Index: /branches/eam_branches/eam_branch_20080719/ippTools/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/.cvsignore	(revision 22158)
@@ -0,0 +1,16 @@
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+compile
+config.guess
+config.log
+config.status
+config.sub
+configure
+depcomp
+install-sh
+libtool
+ltmain.sh
+missing
+pxtools.pc
Index: /branches/eam_branches/eam_branch_20080719/ippTools/COPYING
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/COPYING	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/COPYING	(revision 22158)
@@ -0,0 +1,345 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    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
+
+
+	    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) <year>  <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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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) year 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: /branches/eam_branches/eam_branch_20080719/ippTools/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/Makefile.am	(revision 22158)
@@ -0,0 +1,12 @@
+SUBDIRS = src share
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA= pxtools.pc
+
+EXTRA_DIST = \
+	pxtools.pc.in \
+	autogen.sh
+
+CLEANFILES = *~ core core.*
+
+ACLOCAL_AMFLAGS = -I m4
Index: /branches/eam_branches/eam_branch_20080719/ippTools/TODO
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/TODO	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/TODO	(revision 22158)
@@ -0,0 +1,14 @@
+- change dettol -pretend -define... to return a metadata structure that shows what the created detRun would look like
+- rename dettool -residdetrun -> -todetrunsummary
+- add foreign key constraints to the database
+- add the ability to remove dettool detResidExps
+- change p4tool to accept input from/with magic masks
+- change p5tool to accept input from warp * stack
+- difftool/stacktool error handling
+- move all large SQL statements out into separate files
+- add the option of not automatically flowing through from reg -> chip -> cam
+  tools
+- add workdir inheritance rooted in rawExp, eg.
+    select chipProcessedExp.workdir, rawExp.workdir, IFNULL(chipProcessedExp.workdir, rawExp.workdir) from chipProcessedExp join rawExp using(exp_tag);
+- dettool/detRun support for filelevel
+- combind dettool -definebytag & -definebyquery
Index: /branches/eam_branches/eam_branch_20080719/ippTools/autogen.sh
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/autogen.sh	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/autogen.sh	(revision 22158)
@@ -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=pxtools
+TEST_TYPE=-f
+# change this to be a unique filename in the top level dir
+FILE=autogen.sh
+
+DIE=0
+
+LIBTOOLIZE=libtoolize
+ACLOCAL="aclocal $ACLOCAL_FLAGS"
+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 -I m4 || 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: /branches/eam_branches/eam_branch_20080719/ippTools/configure.ac
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/configure.ac	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/configure.ac	(revision 22158)
@@ -0,0 +1,64 @@
+AC_PREREQ(2.61)
+
+AC_INIT([ipptools], [1.1.36], [ipp-support@ifa.hawaii.edu])
+AC_CONFIG_SRCDIR([autogen.sh])
+
+AM_INIT_AUTOMAKE([1.6 foreign dist-bzip2])
+AM_CONFIG_HEADER([src/config.h])
+AM_MAINTAINER_MODE
+
+IPP_STDCFLAGS
+
+AC_LANG(C)
+AC_GNU_SOURCE
+AC_PROG_CC_C99
+AC_PROG_INSTALL
+AC_PROG_LIBTOOL
+
+PKG_CHECK_MODULES([PSLIB], [pslib >= 1.1.0])
+PKG_CHECK_MODULES([PSMODULES], [psmodules >= 1.1.0])
+PKG_CHECK_MODULES([IPPDB], [ippdb >= 1.1.39]) 
+
+PXTOOLS_CFLAGS="${PSLIB_CFLAGS=} ${PSMODULES_CFLAGS=} ${IPPDB_CFLAGS=}"
+PXTOOLS_LIBS="${PSLIB_LIBS=} ${PSMODULES_LIBS=} ${IPPDB_LIBS=}"
+AC_SUBST(PXTOOLS_CFLAGS,[$PXTOOLS_CFLAGS])
+AC_SUBST(PXTOOLS_LIBS,[$PXTOOLS_LIBS])
+
+dnl check for PSDB support
+TMP_CFLAGS=${CFLAGS}
+CFLAGS="${CFLAGS=} ${PSLIB_CFLAGS}"
+
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+    [[#if !defined HAVE_PSDB
+      error: PSDB support is not avaiable
+      #endif
+    ]])],
+  [],
+  [AC_MSG_ERROR([psLib was built without PSDB support, bailing out.])]
+)
+
+CFLAGS=${TMP_CFLAGS}
+
+dnl --  check for psParseErrorCodes --------------------------------------
+
+AC_PATH_PROG([ERRORCODES], [psParseErrorCodes], [missing])
+if test "$ERRORCODES" = "missing" ; then
+  AC_MSG_ERROR([psParseErrorCodes is required])
+fi
+
+dnl check for perl
+AC_PATH_PROG([PERL], [perl], [missing])
+if test "$PERL" = "missing" ; then
+  AC_MSG_ERROR([perl is required])
+fi
+
+IPP_STDOPTS
+CFLAGS="${CFLAGS=} -Wall -Werror"
+
+AC_CONFIG_FILES([
+  Makefile
+  src/Makefile
+  share/Makefile
+  pxtools.pc
+])
+AC_OUTPUT
Index: /branches/eam_branches/eam_branch_20080719/ippTools/doc/dettool.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/doc/dettool.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/doc/dettool.txt	(revision 22158)
@@ -0,0 +1,181 @@
+# returns a list of unassociated rawDetrendExp (rawDetrendExps that don't
+# correspond to a exp_id in detInputExp)
+dettool -pending -exp_type -inst ..
+
+# define a new detRun semi-automatically by selecting the component exps with
+# the specified search criteria
+dettool -definebyquery -det_type ...
+
+# create a detRun with the specified input exp_ids
+dettool -definebyexp -det_type -exp_id 1 -exp_id 2 ...
+
+--
+# returns a list of rawImfiles that are associated with an detInputExp that do
+# not appear in detProcessedImfiles
+dettool -raw
+
+# add an imfile to detProcessedImfiles
+dettool -addprocessed
+
+--
+# the list of class_ids that are ready to be stacked
+# returns a list of det_id/iter/class_id/det_typs  where class_id is unique per
+# det_id (not a list of all exp_ids/class_ids) that do not have an entry in
+# detStackedImfile
+# results are masked by entries in detResidExpAnalysis
+# may need to check detResidExp's even on iter 0 - ???
+dettool -tostack
+
+# list all of imfiles from different exps with the same class_id that have
+# been processed
+dettool -processed -wholestack -det_id ...
+
+# adds a stacked class_id and and optionally marks it for normalization
+detool -addstacked [-pleasenormalize] -det_id -iter -class_id ...
+
+--
+# returns a list of det_ids/iters where the entire set of class_ids has been
+# processed
+dettool -tonormalize
+
+# returns the complete list of processed imfiles for the specified det_id
+dettool -processed -unmask -det_id -iter
+
+# add per stacked imfile normalization statistics
+# O: this could accept a MDC doc as input from stdin
+dettool -addnormstat -det_id -iter -class_idi -norm F32
+
+--
+# returns a list of det_ids/iter/class_id/uri from detNormStats.  Stops
+# returning entries after the class_is is inserted into detNormalizedImfile
+dettool -normstat -det_id 
+
+# inserts an entry into detNormalizedImfile
+dettool -addnormalized -det_id -ter -class_id -uri
+
+--
+# returns a list of processed imfiles that have also been normalized with
+# processed imfiles being masked out per detResidImfileAnalysis
+# also returns stackedimfiles that have -pleasenormalize set to false
+dettool -toresid -det_id -iter
+
+# inserts a per det_id/iter/exp_id/class_id residual
+dettool -addresidimfile -det_id -exp_id -class_id -iter -stat F32 -stat_stdev F32 -uri -b1 -b2
+
+# returns a list of det_id/iter/exp_ids but only for exp_ids that have resids
+# for all of their imfiles
+dettool -toresidexp
+
+# returns a list of residual imfile data
+dettool -residimfile -det_id -iter -exp_id
+
+# inserts into detResidExpAnalysis 
+# sets the accept accept bool unless -reject is specified
+dettool -addresidexp -det_id -iter -exp_id -jpeg1 -jpeg2 -stat F32 -stat_stdev
+F32 [-reject]
+
+--
+# lists det_id/iter for detruns that have completed all residexps for their
+# current iteration 
+dettool -residdetrun
+
+# lists all residexps for the given det_id/iter
+dettool -residexp -det_id -iter
+
+# updates the given residexp to be accept/reject
+dettool -updateresid -det_id -iter [-reject]
+
+# changes the state of the detrun.  -rerun cause a new iteration to be started
+# with the accepted with just the exp_ids
+dettool -updatedetrun -det_id -iter -stat F32 -stat_stdev [-rerun|-ok|-stop]
+
+# manual starts a new detrun iteration starting from the specified -iter
+dettool -rerun -det_id -iter -accept expid -accept expid -reject expid -reject expid
+dettool -rerun -det_id -iter
+
+# detInputExp needs to track...
+det_id iter exp_id use bool accept bool
+
+
+
+dettool
+
+    -define | creates a a new detrend Run
+        input:
+            exp IDs?
+            type of det run?
+        creates a new detRun ID automatically
+    
+        output: the new det_id
+
+    -raw    | lists raw imfiles needing to be processed
+        input: 
+            det ID
+            exp ID
+            class ID
+            iteration number?
+        output: list of unprocessed imfiles
+    
+    -addprocessed? | marks a raw imfile as processed
+        input:
+            det ID
+            exp ID
+            class ID
+            iteration number?
+            uri
+            stat
+            recipe
+        output: outout on error only
+    -processed | lists processed imfiles
+        input:
+            det ID
+            exp ID
+            class ID
+            iteration number?
+        output: list of processed imfiles
+    -addstacked | adds a stacked imfiles
+        input:
+            det ID
+            class ID
+            iteration number?
+            URI
+            recipe
+            stats
+        output: output on error only
+    -stacked     | lists stacked imfiles
+        input:
+            det ID
+            class ID
+            iteration number?
+        output: list of stacked imfiles
+    -stacked     | lists stacked imfiles
+        input:
+            det ID
+            class ID
+            iteration number?
+        output: list of stacked imfiles 
+    -stackedframe     | lists stacked imfiles for COMPLETE frames
+        input:
+            det ID  // required for simplicity
+            iteration number?
+        output: list of stacked imfiles
+    -addmaster | adds a master imfiles
+        input:
+            det ID
+            class ID
+            iteration number?
+            URI
+            recipe
+            stats
+        output: output on error only
+    -master     | lists master imfiles
+        input:
+            det ID  // required for simplicity
+            class ID
+            iteration number?
+        output: a list of master imfiles
+    -masterframe     | lists master imfiles for COMPLETE frames
+        input:
+            det ID  // required for simplicity
+            iteration number?
+        output: a list of master imfiles
Index: /branches/eam_branches/eam_branch_20080719/ippTools/doc/dsfilesetls
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/doc/dsfilesetls	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/doc/dsfilesetls	(revision 22158)
@@ -0,0 +1,6 @@
+#!/usr/bin/env perl
+
+print "# uri fileid bytes md5sum type \n";
+print "http://example.org/1 foo1.0 123 asadfasdfasdfasfdasdf CELL\n";
+print "http://example.org/2 foo1.1 123 asadfasdfasdfasdfasdf CELL\n";
+print "http://example.org/3 foo1.2 123 asadfasdfasdfasdfasdf CELL\n";
Index: /branches/eam_branches/eam_branch_20080719/ippTools/doc/dsproductls
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/doc/dsproductls	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/doc/dsproductls	(revision 22158)
@@ -0,0 +1,8 @@
+#!/usr/bin/env perl
+
+print "# uri fileset datetime type\n";
+print "http://example.org/1 foo1 2006-04-17T00:00:12 OBJECT\n";
+print "http://example.org/2 foo2 2006-04-17T00:00:12 OBJECT\n";
+print "http://example.org/3 foo3 2006-04-17T00:00:12 OBJECT\n";
+
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/doc/install.pod
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/doc/install.pod	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/doc/install.pod	(revision 22158)
@@ -0,0 +1,251 @@
+=pod
+
+=head1 SYNOPSIS
+
+C<pXtools> is a collection of utilties for tracking image processing
+tasks.  Very little decision making logic is built into these programs.  The
+intent is for higher level programs and scripts to make the real I<decisions>
+and then use C<pXtools> to encode those choices in a persistent manner.
+
+=head1 INSTALL
+
+=head2 Prerequisites
+
+C<pXtools> depends on C<psLib> (built with C<psDB> support), C<psModules>, and
+C<ippdb> and requires a C<C99> capable compiler.
+
+XXX document required library versions
+
+=head2 Build Procedure
+
+C<pXtools> is built with the so-called suite of autotools.   The build
+procedure is pretty typical for software built with these tools.  E.g.
+    
+    ./configure
+    make
+    make install
+
+If you checked out the sources directly from CVS you need to run the
+C<autogen.sh> script.  C<autogen.sh> will run C<configure> for you so that
+changes the build procedure to just:
+
+    sh autogen.sh
+    make
+    make install
+
+=head2 jhbuild Build Procedure
+
+If you are using one of the C<ippdev> modulesets jhbuild can build and install C<pXtools> for you.  E.g.
+
+    jhbuild build pxtools
+    
+=head2 Database Setup
+
+All of the C<pXtools>' persistent storage is ultimately done through C<psLib>'s
+C<psDB> facilties.  In turn, C<psDB> uses C<MySQL> to impliment storage (and
+relational querying).  C<MySQL> requires that each namespace (aka database) is
+configured with basic access controls.  These include usernames, passwords,
+access filtering, and privilege restrictions.  Below is a simple (but somewhat
+dangerous) example of configuring a database named C<ipp>.
+
+    mysql -u root mysql -p
+    (enter your MySQL root password)
+
+    DROP DATABASE IF EXISTS ipp;
+    CREATE DATABASE ipp;
+    GRANT ALL PRIVILEGES ON *.* TO 'ippuser'@'localhost' IDENTIFIED BY 'ipppass';
+    FLUSH PRIVILEGES;
+    quit
+
+After setting up the database you should verify that you can connect to with the username and password you configured
+
+    mysql -u ipp ipp -pipp
+
+Next, C<pXtools> needs to be told where to to find MySQL, the name of the
+database you created, the username, and the password you created.  C<pXtools>
+uses the typical C<psModules> configuration system.  The simplest method is to
+add the follow lines to your $HOME/.ipprc file.
+
+    ### Database configuration
+    DBSERVER        STR     localhost   # Database host name (for psDBInit)
+    DBNAME          STR     ipp
+    DBUSER          STR     ipp         # Database user name (for psDBInit)
+    DBPASSWORD      STR     ipp         # Database password (for psDBInit)
+
+The C<pxTools> utilities require the a schema is pre-loaded into the database.  The C<pxadmin> tool can do this for you.  E.g.
+
+    pxadmin -create
+
+You should always verify that the scheme was actually loaded.  E.g.
+
+    mysql -u ipp ipp -pipp
+    Welcome to the MySQL monitor.  Commands end with ; or \g.
+    Your MySQL connection id is 6 to server version: 4.1.20-log
+
+    Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
+
+    mysql> show tables;
+    +------------------------+
+    | Tables_in_ipp          |
+    +------------------------+
+    | detInputExp            |
+    | detMasterFrame         |
+    | detMasterImfile        |
+    | detNormalizedImfile    |
+    | detProcessedImfile     |
+    | detResidExpAnalysis    |
+    | detResidImfileAnalysis |
+    | detRun                 |
+    | detStackedImfile       |
+    | newExp                 |
+    | newImfile              |
+    | p1PendingExp           |
+    | p2DoneExp              |
+    | p2DoneImfile           |
+    | p2PendingExp           |
+    | p2PendingImfile        |
+    | p3PendingExp           |
+    | pzPendingExp           |
+    | pzPendingImfile        |
+    | rawDetrendExp          |
+    | rawImfile              |
+    | rawScienceExp          |
+    | summitExp              |
+    +------------------------+
+    23 rows in set (0.00 sec)
+
+=head1 USE
+
+The workflow is as follows:
+
+XXX
+
+=head2 Phase 0 tools
+
+The primary C<pXtools> utility for handling Phase 0 is C<p0search>.  This tool
+has two modes C<-pending> and C<-update>. The pending mode lists all
+C<newImfile>s that are part of an exposure that I<has not> yet been classified
+as either science or detrend data.
+
+For example:
+
+    p0search -pending
+
+Would output something like:
+
+    newImfile MULTI #
+
+    newImfile  METADATA
+       exp_id STR  10
+       class STR  OTA
+       class_id STR  0
+       uri STR  file://0
+    END
+
+    newImfile  METADATA
+       exp_id STR  10
+       class STR  OTA
+       class_id STR  1
+       uri STR  file://1
+    END
+
+    newImfile  METADATA
+       exp_id STR  10
+       class STR  OTA
+       class_id STR  2
+       uri STR  file://2
+    END
+
+    newImfile  METADATA
+       exp_id STR  10
+       class STR  OTA
+       class_id STR  3
+       uri STR  file://3
+    END
+
+To declare C<exp_id 10> as science data, you would invoke C<p0search> like this:
+    
+    p0search -update -exp_id 10
+
+Note that by default C<-update> flags the exposure as science data.  To declare it to be detrend data the command would be:
+
+    p0search -update -exp_id 10 -detrend
+
+Also keep in mind that this is a one time declaration.  Once it has been
+declared as either science or detrend data this decision can not be undone
+(without manually editing the database)
+
+=head2 Phase 1 tools
+
+These tools are not yet in use.
+
+=head2 Phase 2 tools
+
+C<p2search> handles all of state for Phase 2.  It has four basic modes:
+
+=over 4
+
+=item * C<-quick>
+
+=item * C<-define>
+
+=item * C<-pending>
+
+    p0search -pending
+
+=item * C<-done>
+
+=head2 Administrative tools
+
+=over 4
+
+=item * C<pxadmin>
+
+This tool can be used to load/unload the database schema.  It has three modes of operation:
+
+=over 4
+
+=item * C<-create>
+
+Loads the database schema.
+
+=item * C<-delete>
+
+Deletes the database schema.
+
+=item * C<-recreate>
+
+Deletes the database schema then reloads it.
+
+=back
+
+=item * C<pxinject>
+
+I<Injects> data directly into the database.  It has one mode parameter for each database table.  Note: support for only a few tables has been impliemented.
+
+=back
+
+=head2 Bypassing 'Summit Copy'
+
+The C<pXtools> suite assumes that exposures and image data are initially
+registered with the C<pz*> set of I<Summit Copy step> tools.  Sometimes this is
+inconvenient as you want to work with local data and bypass this set.  This is
+what the C<pxinject> utility is for.  C<pxinject> directly inserts data into
+the database, side stepping any ordering rules or sanity checking.
+
+The end result of the C<pz*> utilities is that new exposures are registered in the C<newExp> table and raw image data is in the C<newImfile> table.  You can insert this data yourself, preparing the system to run I<phase 0>.
+
+Here is an example of inserting an exposure that has 4 component image files.
+
+    #!//bin/sh
+
+    inject="./pxinject"
+
+    $inject -newExp -exp_id 10 -inst gpc -telescope ps1 -exp_type object -imfiles 4
+
+    `$inject -newImfile -exp_id 10 -class OTA -class_id 0 -uri file://0`
+    `$inject -newImfile -exp_id 10 -class OTA -class_id 1 -uri file://1`
+    `$inject -newImfile -exp_id 10 -class OTA -class_id 2 -uri file://2`
+    `$inject -newImfile -exp_id 10 -class OTA -class_id 3 -uri file://3`
+
+=cut
Index: /branches/eam_branches/eam_branch_20080719/ippTools/doc/magic_flow.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/doc/magic_flow.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/doc/magic_flow.txt	(revision 22158)
@@ -0,0 +1,65 @@
+### Set up a run:
+magictool -definerun -workdir /path/to/workdir
+magictool -addinputskyfile -magic_id 6 -diff_id 1 -node 5.1
+magictool -addinputskyfile -magic_id 6 -diff_id 2 -node 5.2
+magictool -addinputskyfile -magic_id 6 -diff_id 3 -node 5.3
+magictool -addinputskyfile -magic_id 6 -diff_id 4 -node 5.4
+magictool -updaterun -magic_id 6 -state run
+
+### Set up a run in a single call:
+magictool -queue -select_XXX
+
+### Generate a processing tree
+magictool -totree
+#magic_tree.pl --magic_id X [camera, tess_id, ra0, dec0]
+* magictool -inputskyfile -magic_id 6
+* magictool -inputtree -magic_id 6 -dep_file magic_dep.mdc
+
+### Process the tree
+magictool -toprocess
+#magicMe  METADATA
+#   magic_id         S64       5
+#   node             STR       5.1
+#   dep              STR       NULL
+#   done             S64       0
+#   uri              STR       NULL
+#END
+#magic_process.pl --magic_id 6 --node 5.1
+magictool -inputs -magic_id 6 -node 5.1
+
+magictool -addresult -magic_id 6 -node 5.1 -uri foo
+magictool -addresult -magic_id 6 -node 5.2 -uri bar
+magictool -addresult -magic_id 6 -node 5.3 -uri baz
+magictool -addresult -magic_id 6 -node 5.4 -uri qix
+
+### Merging the tree
+magictool -toprocess
+#magicMe  METADATA
+#   magic_id         S64       5
+#   node             STR       5A
+#   uri MULTI
+#   uri              STR       foo
+#   uri              STR       bar
+#END
+#magic_process.pl --magic_id 6 --node 5A
+magictool -inputs -magic_id 6 -node 5A
+
+magictool -addresult -magic_id 6 -node 5A -uri foobar
+magictool -addresult -magic_id 6 -node 5B -uri bazqix
+
+### Final merge
+magictool -toprocess
+#magicMe  METADATA
+#   magic_id         S64       5
+#   node             STR       root
+#END
+#magic_process.pl --magic_id 6 --node root
+magictool -inputs -magic_id 6 -node root
+
+magictool -addresult -magic_id 6 -node root -uri foobarbazqix
+
+### Generate the mask description
+magictool -tomask
+magic_mask.pl --magic_id X
+magictool -inputs -magic_id 6 -node root
+magictool -addmask -magic_id 6 -uri foobarbazqixqit
Index: /branches/eam_branches/eam_branch_20080719/ippTools/doc/p0tools.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/doc/p0tools.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/doc/p0tools.txt	(revision 22158)
@@ -0,0 +1,40 @@
+
+Phase 0 pipeline tools:
+
+p0search -pending :
+  * examine the new.imfiles,new.exposures tables and select exposures ready for analysis
+  * output is: (expID) (camera)
+
+p0search -update (expID) (camera):
+  * select a the corresponding images from the new.imfiles/new.exposures table
+  * extract the specified header information
+  * search the summit metadata db tables
+  * write an entry to the raw.imfiles and raw.exposure tables
+  * set the state on the new.imfiles,new.exposure tables
+  * based on the camera config information;
+    * add an entry to the p1.pending table (mosaic) 
+    - or
+    * add an entry to the p2.pending table (single)
+
+p0search -stats (expID) (camera):
+  * select a specified image in the new.imfiles/new.exposures table
+  * extract the specified header information
+  * search the summit metadata db tables
+  * report the image stats
+  [-update without output to MDDB]
+
+p0search -mkraw (expID) (camera):
+  * select a specified image in the new.imfiles/new.exposures table
+  * extract the specified header information
+  * search the summit metadata db tables
+  * write an entry to the raw.imfiles and raw.exposure tables
+  * set the state on the new.imfiles,new.exposure tables
+
+p0search -cleanup:
+  * remove completed entries from the new.imfiles,new.exposure tables
+
+** note : the division of -pending and -update allows separate processes
+   to be examining the image headers and measuring some stats.  these
+   jobs can be run via pcontrol to reduce the load on the PanTasks
+   machines
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/doc/p1tools.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/doc/p1tools.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/doc/p1tools.txt	(revision 22158)
@@ -0,0 +1,16 @@
+
+Phase 1 pipeline tools:
+
+p1search -define [constraints]:
+  * examine the raw.exposures tables and select exposures matching the given criteria
+  * add entries which are allowed (mosaic) to the p1.pending table
+
+p1search -pending :
+  * examine the p1.pending table and select exposures waiting for p1
+  * output: lines consisting of:
+    (expID) (p1version) (camera)
+
+p1search -done :
+  * select completed entries in the p1.pending table
+  * move to the p1.done table
+  * add new entry to the p2.pending tables
Index: /branches/eam_branches/eam_branch_20080719/ippTools/doc/p2search.sh
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/doc/p2search.sh	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/doc/p2search.sh	(revision 22158)
@@ -0,0 +1,8 @@
+#!/bin/csh -f
+
+echo "# expID class classID url"
+echo "654320o fpa megacam 654320o.fits"
+echo "654321o fpa megacam 654321o.fits"
+echo "654322o fpa megacam 654322o.fits"
+echo "654323o fpa megacam 654323o.fits"
+echo "654324o fpa megacam 654324o.fits"
Index: /branches/eam_branches/eam_branch_20080719/ippTools/doc/p2tools.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/doc/p2tools.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/doc/p2tools.txt	(revision 22158)
@@ -0,0 +1,41 @@
+
+Phase 2 pipeline tools:
+
+p2search -quick 
+  * search for images which match in raw.exp,raw.imfiles
+  * output in format which can be used by ppImage pantasks script
+
+p2search -define [options]
+  * input: searches mddb:raw_exposures,raw_images
+        - compares against p2Pending[Exp|Imfile]
+        - compares against p2Done[Exp|Imfile]
+        - XXX should be implemented as a special wrapper function that
+          implements this comparison as a SQL query
+  * output: updates mddb:P2_exposures_pending,P2_images_pending
+  * alternative output: identical to p2pending
+ 
+p2search -pending 
+  * input: searches mddb:P2_exposures_pending,P2_images_pending
+  * output: Nlines consisting of:
+    (URL) (expID) (class)
+  * options: ?
+
+p2search -update
+  * examine the imfiles and identify any completed exposures
+
+p2search -done
+  * get exp_id/class/class_id from the CLI
+  * add the completed imfile to the p2DoneImfile tables
+  * remove corresponding entries from the p2PendingImfile table
+  * check to see if any p2PendingExps have no associated p2PendingImfiles
+        if so move the p2PendingExp(s) to p2DoneExp
+//  * send new entry to the pending p3 table
+
+ppImage file://path/filename file://path/outroot -recipe (recipe) 
+ppImage neb://nebname neb://outroot -recipe (recipe)
+
+restriction options:
+  -time (start) (stop)
+  -camera (camera) 
+  -region (ra,dec) (ra,dec)
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/doc/p3tools.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/doc/p3tools.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/doc/p3tools.txt	(revision 22158)
@@ -0,0 +1,22 @@
+
+Phase 3 pipeline tools:
+
+p3search -define :
+  * examine the raw.exposures tables and select exposures matching the given criteria
+  * add entries which are allowed (mosaic) to the p3.pending table
+
+p3search -quick :
+  * examine the raw.exposures tables and select exposures matching the given criteria
+  * return list of entries for p3 processing
+  * output: lines consisting of:
+    (expID) (p3version) (camera)
+
+p3search -pending :
+  * examine the p3.pending exposures table and select exposures waiting for p3
+  * return list of entries for p3 processing
+  * output: lines consisting of:
+    (expID) (p3version) (camera)
+
+p3search -done :
+  * select completed entries in the p3.pending table
+  * move to the p3.done table
Index: /branches/eam_branches/eam_branch_20080719/ippTools/doc/summit_copy.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/doc/summit_copy.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/doc/summit_copy.txt	(revision 22158)
@@ -0,0 +1,49 @@
+The summit copy phase (phase Z or pz) consists of three basic steps.
+Discovering what exposures and available, discovering what image files are
+associated with those exposures, and the downloading of image files.  All
+"external" communication with the DataStore is done with three utilities;
+pzgetexp, pzgetimfiles & dsget.  While local state information is accessed and
+updated via the 'pztool' utility.
+
+The basic work follow is:
+
+pzgetexp retrieves a list of all of the exposures (filesets) available from a
+DataStore "product".  If any previously unknown file exposures are found they
+are added to the pzPendingExp tables and the summitExp table.  New entries to
+the summitExp table have a imfile value of NULL as this information can't yet
+be known.  If any exposures are already in the summitExp table the most recent
+exp_id is used to constrain the result set requested from the DataStore.
+
+    ./pzgetexp -uri http://otis/ds/skyprobe/ -inst skyprobe -telescope ps1
+
+The results of pzgetexp and accessible with pztool -pendingexp`.  Which will
+return a list of new exposures from the pzPendingExp table.
+
+    ./pztool -pendingexp
+
+The output of which is used to invoke pzgetimfiles.
+
+pzgetimfiles retrieves a list of all of the imfiles (files) in an exposure
+(fileset) from the DataStore.  It then updates the imfiles count in the
+summitExp table and adds each imfile to the pzPendingImfile table.
+
+./pzgetimfiles -uri http://otis/ds/skyprobe/sep8_twi_05/ -filesetid sep8_twi_05 -inst skyprobe -telescope ps1
+
+pztool -pendingimfile returns the list of imfiles that need to be downloaded.
+
+    ./pztool -pendingimfile
+
+The results of which are used to invoke dsget and pztool -copydone after dsget
+completes it's download.
+
+dsget from the 'DataStore' package takes the follow parameters.
+
+    dsget --uri <uri> --filename <filename> [--bytes <nbytes>] [--md5 <hex>]
+
+Where "filename" may be either just a filename relative to the CWD or a fully
+qualified path.  After dsget has copied the file pztool -copydone needs to be
+invoked
+
+    ./pztool -copydone -exp_id sep8_twi_03 -inst skyprobe -telescope ps1 -class chip -class_id sep8_twi_03.fits -uri file///data/alala/sep8_twi_03.fits
+
+And then we're Pau.
Index: /branches/eam_branches/eam_branch_20080719/ippTools/m4/ac_prog_perl_modules.m4
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/m4/ac_prog_perl_modules.m4	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/m4/ac_prog_perl_modules.m4	(revision 22158)
@@ -0,0 +1,53 @@
+dnl @synopsis AC_PROG_PERL_MODULES([MODULES], [ACTION-IF-TRUE], [ACTION-IF-FALSE])
+dnl
+dnl Checks to see if the the given perl modules are available. If true
+dnl the shell commands in ACTION-IF-TRUE are executed. If not the shell
+dnl commands in ACTION-IF-FALSE are run. Note if $PERL is not set (for
+dnl example by calling AC_CHECK_PROG, or AC_PATH_PROG),
+dnl AC_CHECK_PROG(PERL, perl, perl) will be run.
+dnl
+dnl Example:
+dnl
+dnl   AC_CHECK_PERL_MODULES(Text::Wrap Net::LDAP, ,
+dnl                         AC_MSG_WARN(Need some Perl modules)
+dnl
+dnl @category InstalledPackages
+dnl @author Dean Povey <povey@wedgetail.com>
+dnl @version 2002-09-25
+dnl @license AllPermissive
+
+AC_DEFUN([AC_PROG_PERL_MODULES],[
+    ac_perl_modules="$1"
+    # Make sure we have perl
+    if test -z "$PERL"; then
+        AC_CHECK_PROG(PERL,perl,perl)
+    fi
+
+    if test "x$PERL" != x; then
+        ac_perl_modules_failed=0
+        for ac_perl_module in $ac_perl_modules; do
+            AC_MSG_CHECKING(for perl module $ac_perl_module)
+
+            # Would be nice to log result here, but can't rely on autoconf
+            # internals
+            $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1
+            if test $? -ne 0; then
+                AC_MSG_RESULT(no);
+                ac_perl_modules_failed=1
+            else
+                AC_MSG_RESULT(ok);
+            fi
+        done
+
+        # Run optional shell commands
+        if test "$ac_perl_modules_failed" = 0; then
+            :
+            $2
+        else
+            :
+            $3
+        fi
+    else
+        AC_MSG_WARN(could not find perl)
+    fi
+])
Index: /branches/eam_branches/eam_branch_20080719/ippTools/notes.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/notes.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/notes.txt	(revision 22158)
@@ -0,0 +1,63 @@
+
+2008.07.19 EAM
+
+  * need to add cleanup modes to all stages.  here is the minimum list
+    of stages that need the cleanups:
+
+    * chiptool - DONE
+    * camtool 
+    * faketool
+    * warptool
+    * difftool
+    * stacktool
+    * dettool processedimfile
+    * dettool processedexp
+    * dettool stackedimfile
+    * dettool normalizedstat
+    * dettool normalizedimfile
+    * dettool normalizedexp
+    * dettool residimfile
+    * dettool residexp
+
+    * I am modifiying the tools to use the new states: new, full, goto_cleaned, etc.
+      I am NOT changing: regtool, pztool, magictool, flatcorr, pxregister, pstamptool
+
+    * for dettool, I have added a new field, 'data_state' to the
+      detRunSummary.  My plan here is that a complete detRunIteration
+      is cleaned at once.  I've added functions to all of the dettool
+      major modes to list pending entries to be cleaned and a function
+      to update the data_state when cleaning is done.
+
+2008.07.11 EAM 
+
+  * break dettool.c into files for each detrend stage
+  * require -iteration in more places? (esp -add...)
+  * allow %s, %d arguments in the *.sql files or not?
+  * adddetrunsummary has the ability to set values for multiple detRunSummary entries.  why?
+
+2008.07.09 EAM
+
+  In order to implement the 'cleanup' and 'update' strategies, we have
+  changed the state names and defined addtional states as follows:
+
+  * new          : entry is unprocessed (was 'run')
+  * full         : entry is processed and has all output data products (was 'done')
+  * goto_cleaned : entry should be processed by the 'cleanup' system
+  * cleaned   	 : entry has been processed by the 'cleanup' system --
+    		   some output data products are now missing.
+		   
+  * goto_full    : entry should be re-processed by the 'update' system
+  * full         : entry has been re-processed by the 'update' system
+  
+  * goto_purged  : entry should be processed by the 'cleanup' ssytem
+    		   to purge all output data
+  * purged       : entry has been purged
+
+
+
+2008.05.16 EAM
+
+caltool
+  * add the active field, -active flag to -dbs
+  * add the -region 
+  * change 'catdir' to 'dvo_id'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/pxtools.pc.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/pxtools.pc.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/pxtools.pc.in	(revision 22158)
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/@PACKAGE_NAME@
+
+Name: @PACKAGE_NAME@
+Description: Pan-STARRS IPP Tools Library
+Version: @VERSION@
+Requires: pslib psmodules ippdb
+Libs: -L${libdir} -lpxtools
+Cflags: -I${includedir} @PXTOOLS_CFLAGS@
Index: /branches/eam_branches/eam_branch_20080719/ippTools/scripts/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/scripts/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/scripts/.cvsignore	(revision 22158)
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
Index: /branches/eam_branches/eam_branch_20080719/ippTools/scripts/camtest.sh
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/scripts/camtest.sh	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/scripts/camtest.sh	(revision 22158)
@@ -0,0 +1,11 @@
+#!//bin/sh
+
+set -o verbose
+
+chiptest.sh || exit 1
+
+camtool -pendingexp || exit 1
+camtool -pendingimfile || exit 1
+
+camtool -addprocessedexp -cam_id 1 -uri file:///cam -bg 1 -bg_stdev 2 -bg_mean_stdev 3 -sigma_ra 1 -sigma_dec 2 -zp_mean 10 -zp_stdev 2 -n_stars 2 -n_extended 0 -n_astrom 42 -n_cr 10000000 -path_base file:///foo || exit 1
+camtool -addprocessedexp -cam_id 2 -uri file:///cam -bg 1 -bg_stdev 2 -bg_mean_stdev 3 -sigma_ra 1 -sigma_dec 2 -zp_mean 10 -zp_stdev 2 -n_stars 2 -n_extended 0 -n_astrom 42 -n_cr 10000000 -path_base file:///foo || exit 1
Index: /branches/eam_branches/eam_branch_20080719/ippTools/scripts/chiptest.sh
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/scripts/chiptest.sh	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/scripts/chiptest.sh	(revision 22158)
@@ -0,0 +1,17 @@
+#!//bin/sh
+
+set -o verbose
+
+regtest.sh || exit 1
+
+chiptool -pendingimfile || exit 1
+
+for ID in `seq 0 3`; do
+    chiptool -addprocessedimfile -chip_id 1 -exp_id 1 -class_id $ID -uri file://chipp-t10.$ID -bg 1 -bg_stdev 2 -bg_mean_stdev 3 -path_base file:///foo || exit 1
+done;
+
+for ID in `seq 0 3`; do
+    chiptool -addprocessedimfile -chip_id 2 -exp_id 2 -class_id $ID -uri file://chipp-t11.$ID -bg 1 -bg_stdev 2 -bg_mean_stdev 3 -path_base file:///foo || exit 1
+done;
+
+chiptool -pendingimfile || exit 1
Index: /branches/eam_branches/eam_branch_20080719/ippTools/scripts/dettest.sh
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/scripts/dettest.sh	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/scripts/dettest.sh	(revision 22158)
@@ -0,0 +1,88 @@
+#!//bin/sh
+
+set -o verbose
+
+det_id=1
+
+./regtest.sh -end_stage reg || exit 1
+
+det_id=`dettool -definebyquery -det_type bias -inst gpc -filelevel fpa -select_exp_type bias -airmass_min 1 -airmass_max 10 -exp_time_min 10 -exp_time_max 30.0 -workdir file::///some/path -simple | cut -f1 -d" "` || exit 1
+
+dettool -raw || exit 1
+
+dettool -toprocessedimfile || exit 1
+
+for ID in `seq 0 3` ; do
+    dettool -addprocessedimfile -det_id 1 -exp_id 1 -class_id $ID -uri file://proc-$ID -recip myrecip -bg 2 -bg_stdev 3 -bg_mean_stdev 4 || exit 1
+done;
+
+for ID in `seq 0 3` ; do
+    dettool -addprocessedimfile -det_id 1 -exp_id 2 -class_id $ID -uri file://proc-$ID -recip myrecip -bg 2 -bg_stdev 3 -bg_mean_stdev 4 || exit 1
+done;
+
+
+dettool -tostacked || exit 1
+
+for ID in `seq 0 3` ; do
+    dettool -addstacked -det_id $det_id -uri file://stacked-$ID -class_id $ID -recip myrecipe -bg 1 -bg_stdev 2 -bg_mean_stdev 3 || exit 1
+done;
+
+dettool -tonormalizedstat || exit 1
+
+for ID in `seq 0 3` ; do
+    dettool -addnormalizedstat -det_id $det_id -class_id $ID -norm 0.12345 || exit 1
+done;
+
+dettool -tonormalize || exit 1
+for ID in `seq 0 3` ; do
+    dettool -addnormalizedimfile -det_id $det_id -class_id $ID -uri file://normalized-$ID -bg 1 -bg_stdev 2 -bg_mean_stdev 3 -path_base banana1 || exit 1
+done;
+
+dettool -tonormalizedexp || exit 1
+dettool -addnormalizedexp -det_id $det_id -recip myrecipe -bg 1 -bg_stdev 2 -bg_mean_stdev 3 -path_base file://normalizedexp || exit 1
+
+dettool -toresidimfile || exit 1
+
+for ID in `seq 0 3` ; do
+    dettool -addresidimfile -det_id $det_id -exp_id 1 -class_id $ID -recip myrecip -bg 1 -bg_stdev 1 -bg_mean_stdev 1 -uri file://resid-$ID || exit 1
+done;
+
+for ID in `seq 0 3` ; do
+    dettool -addresidimfile -det_id $det_id -exp_id 2 -class_id $ID -recip myrecip -bg 1 -bg_stdev 1 -bg_mean_stdev 1 -uri file://resid-$ID || exit 1
+done;
+
+dettool -toresidexp || exit 1
+dettool -addresidexp -det_id $det_id -exp_id 1 -recip myrecipe -bg 1 -bg_stdev 2 -bg_mean_stdev 3 -path_base jpeg1 || exit 1
+dettool -addresidexp -det_id $det_id -exp_id 2 -recip myrecipe -bg 1 -bg_stdev 2 -bg_mean_stdev 3 -path_base jpeg1 -reject || exit 1
+
+dettool -todetrunsummary || exit 1
+dettool -residexp || exit 1
+dettool -updateresidexp -det_id $det_id -iteration 0 -recip yourrecipe || exit 1
+dettool -updateresidexp -det_id $det_id -iteration 0 -exp_id 2 -reject || exit 1
+dettool -updateresidexp -det_id $det_id -iteration 0 -exp_id 2 || exit 1
+
+dettool -adddetrunsummary -det_id $det_id -iteration 0 -bg 1 -bg_stdev 2 -bg_mean_stdev 3 -accept || exit 1
+
+dettool -todetrunsummary || exit 1
+
+dettool -residexp || exit 1
+
+dettool -updatedetrun -det_id $det_id -state stop || exit 1
+
+dettool -register_detrend -det_type bias -mode master -filelevel fpa -workdir file:/// -label foo || exit 1
+dettool -register_detrend_imfile -det_id 2 -class_id 1 -uri file:///foo || exit 1
+dettool -register_detrend_imfile -det_id 2 -class_id 2 -uri file:///foo || exit 1
+dettool -register_detrend_imfile -det_id 2 -class_id 3 -uri file:///foo || exit 1
+dettool -register_detrend_imfile -det_id 2 -class_id 4 -uri file:///foo || exit 1
+dettool -updatedetrun -det_id 2 -state stop || exit 1
+
+# correct test
+dettool -makecorrection -det_id 1 || exit 1
+dettool -tocorrectexp || exit 1
+dettool -tocorrectimfile -det_id 3 || exit 1
+dettool -addcorrectimfile -det_id 3 -class_id 0 -uri file:///correct/0 || exit 1
+dettool -addcorrectimfile -det_id 3 -class_id 1 -uri file:///correct/1 || exit 1
+dettool -addcorrectimfile -det_id 3 -class_id 2 -uri file:///correct/2 || exit 1
+dettool -addcorrectimfile -det_id 3 -class_id 3 -uri file:///correct/3 || exit 1
+# detRun 3 should be automatically set to stop by this point 
+dettool -tocorrectexp || exit 1
Index: /branches/eam_branches/eam_branch_20080719/ippTools/scripts/difftest.sh
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/scripts/difftest.sh	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/scripts/difftest.sh	(revision 22158)
@@ -0,0 +1,29 @@
+#!//bin/sh
+
+set -o verbose
+
+warptest.sh || exit 1
+
+
+difftool -definerun -workdir file:///tmp/diff -skycell_id foo1 -tess_id bar || exit 1
+difftool -addinputskyfile -diff_id 1 -warp_id 1 -kind warped -template || exit 1
+difftool -addinputskyfile -diff_id 1 -warp_id 1 -kind warped || exit 1
+#difftool -updaterun -state run -diff_id 1 || exit 1
+difftool -todiffskyfile || exit 1
+difftool -inputskyfile || exit 1
+difftool -adddiffskyfile -diff_id 1 -uri file:///tmp/diff/skyfile -path_base file://lalaland -bg 1 -bg_stdev 2 || exit 1
+difftool -diffskyfile -diff_id 1 || exit 1
+difftool -updaterun -state stop -diff_id 1 || exit 1
+
+#
+# diff_id 2
+#
+difftool -definerun -workdir file:///tmp/diff -skycell_id foo1 -tess_id bar || exit 1
+difftool -addinputskyfile -diff_id 2 -warp_id 1 -kind warped -template || exit 1
+difftool -addinputskyfile -diff_id 2 -warp_id 1 -kind warped || exit 1
+#difftool -updaterun -state run -diff_id 1 || exit 1
+difftool -todiffskyfile || exit 1
+difftool -inputskyfile || exit 1
+difftool -adddiffskyfile -diff_id 2 -uri file:///tmp/diff/skyfile -path_base file://lalaland -bg 1 -bg_stdev 2 || exit 1
+difftool -diffskyfile -diff_id 2 || exit 1
+difftool -updaterun -state stop -diff_id 2 || exit 1
Index: /branches/eam_branches/eam_branch_20080719/ippTools/scripts/faketest.sh
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/scripts/faketest.sh	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/scripts/faketest.sh	(revision 22158)
@@ -0,0 +1,19 @@
+#!//bin/sh
+
+set -o verbose
+
+camtest.sh || exit 1
+
+#faketool -pendingexp || exit 1
+faketool -pendingimfile || exit 1
+
+for ID in `seq 0 3`; do
+    faketool -addprocessedimfile -fake_id 1 -exp_id 1 -class_id $ID -uri file://chipp-t10.$ID -path_base file:///foo || exit 1
+done;
+
+for ID in `seq 0 3`; do
+    faketool -addprocessedimfile -fake_id 2 -exp_id 2 -class_id $ID -uri file://chipp-t11.$ID -path_base file:///foo || exit 1
+done;
+
+faketool -pendingimfile || exit 1
+faketool -processedimfile || exit 1
Index: /branches/eam_branches/eam_branch_20080719/ippTools/scripts/magic_dep.md
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/scripts/magic_dep.md	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/scripts/magic_dep.md	(revision 22158)
@@ -0,0 +1,6 @@
+# node      dep
+a   STR     NULL
+b   STR     NULL
+root   MULTI
+root   STR     a
+root   STR     b
Index: /branches/eam_branches/eam_branch_20080719/ippTools/scripts/magictest.sh
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/scripts/magictest.sh	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/scripts/magictest.sh	(revision 22158)
@@ -0,0 +1,28 @@
+#!//bin/sh
+
+set -o verbose
+
+difftest.sh || exit 1
+
+
+magictool -definerun -workdir file:///foo/bar/ || exit 1
+magictool -addinputskyfile -magic_id 1 -diff_id 1 -node a || exit 1
+magictool -addinputskyfile -magic_id 1 -diff_id 2 -node b || exit 1
+magictool -inputtree -magic_id 1 -dep_file magic_dep.md 
+magictool -updaterun -state run -magic_id 1 || exit 1
+
+magictool -addresult -magic_id 1 -node a -uri file:///foo/a
+magictool -addresult -magic_id 1 -node b -uri file:///foo/b
+magictool -addresult -magic_id 1 -node root -uri file:///foo/root
+magictool -tomask
+magictool -addmask -magic_id 1 -uri file:///foo/mask
+magictool -toskyfilemask
+magictool -addskyfilemask -magic_id 1 -diff_id 1 -uri file:///foo/mask_1
+magictool -addskyfilemask -magic_id 1 -diff_id 2 -uri file:///foo/mask_2
+magictool -updaterun -state stop -magic_id 1 || exit 1
+
+#difftool -todiffskyfile || exit 1
+#difftool -inputskyfile || exit 1
+#difftool -adddiffskyfile -diff_id 1 -uri file:///tmp/diff/skyfile -path_base file://lalaland -bg 1 -bg_stdev 2 || exit 1
+#difftool -diffskyfile -diff_id 1 || exit 1
+#difftool -updaterun -state stop -diff_id 1 || exit 1
Index: /branches/eam_branches/eam_branch_20080719/ippTools/scripts/mapfile.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/scripts/mapfile.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/scripts/mapfile.txt	(revision 22158)
@@ -0,0 +1,19 @@
+warpSkyCellMap MULTI
+
+warpSkyCellMap METADATA
+    warp_id         S64     1
+    cam_id          S64     1
+    skycell_id      STR     foo1
+    tess_id         STR     bar
+    class_id        STR     quix1
+    fault           S16     0
+END
+
+warpSkyCellMap METADATA
+    warp_id         S64     1
+    cam_id          S64     1
+    skycell_id      STR     foo2
+    tess_id         STR     bar
+    class_id        STR     quix2
+    fault           S16     0
+END
Index: /branches/eam_branches/eam_branch_20080719/ippTools/scripts/regtest.sh
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/scripts/regtest.sh	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/scripts/regtest.sh	(revision 22158)
@@ -0,0 +1,49 @@
+#!//bin/sh
+
+set -o verbose
+
+inject="pxinject"
+regtool="regtool"
+
+echo -e "YES\njhipp\n\n" | pxadmin -recreate || exit 1
+
+exp_id1=`$inject -newExp -tmp_exp_name t10 -tmp_inst gpc -tmp_telescope ps1 -workdir file::///some/path -reduction batman -simple` || exit 1
+
+echo $exp_id1
+
+for ID in `seq 0 3`; do
+    $inject -newImfile -exp_id $exp_id1 -tmp_class_id tmp.$ID -uri file://$ID || exit 1
+done;
+
+$inject -updatenewExp -exp_id $exp_id1 -state run
+
+exp_id2=`$inject -newExp -tmp_exp_name t11 -tmp_inst gpc -tmp_telescope ps1 -workdir file::///some/path -reduction robin -simple` || exit 1
+
+for ID in `seq 0 3`; do
+    $inject -newImfile -exp_id $exp_id2 -tmp_class_id tmp.$ID -uri file://$ID || exit 1
+done;
+
+$inject -updatenewExp -exp_id $exp_id2 -state run
+
+
+$regtool -pendingimfile || exit 1
+
+for ID in `seq 0 3`; do
+    $regtool -addprocessedimfile -exp_id $exp_id1 -exp_name t10 -inst gpc -telescope ps1 -tmp_class_id tmp.$ID -class_id $ID -filter r -airmass 10 -ra 1 -decl 2 -exp_time 0 -bg 1 -bg_stdev 1 -bg_mean_stdev 10 -alt 10 -az 10 -ccd_temp 10 -posang 10 -object dog -dateobs 2006-10-20T10:10:10Z -uri file://$ID || exit 1
+done;
+
+$regtool -pendingexp|| exit 1
+
+$regtool -addprocessedexp -exp_id $exp_id1 -exp_name t10 -inst gpc -telescope ps1 -exp_tag batman.t10 -filelevel OTA -filter r -airmass 10 -ra 1 -decl 2 -exp_type object -exp_time 0 -bg 10 -bg_stdev 1 -bg_mean_stdev 10 -alt 10 -az 10 -ccd_temp 45 -posang 10 -object dog -dateobs "2006-10-20T10:10:10Z" -label foobar -tess_id moldyshoe $* || exit 1
+# use BIAS or OBJECT? $regtool -addprocessedexp -exp_id $exp_id1 -exp_name t10 -inst gpc -telescope ps1 -exp_tag batman.t10 -filelevel OTA -filter r -airmass 10 -ra 1 -decl 2 -exp_type bias -exp_time 0 -bg 10 -bg_stdev 1 -bg_mean_stdev 10 -alt 10 -az 10 -ccd_temp 45 -posang 10 -object dog -dateobs "2006-10-20T10:10:10Z" -label foobar -tess_id moldyshoe $* || exit 1
+
+$regtool -pendingimfile || exit 1
+
+for ID in `seq 0 3`; do
+    $regtool -addprocessedimfile -exp_id $exp_id2 -exp_name t11 -inst gpc -telescope ps1  -tmp_class_id tmp.$ID -class_id $ID -filter r -airmass 10 -ra 1 -decl 2 -exp_time 0 -bg 1 -bg_stdev 1 -bg_mean_stdev 10 -alt 10 -az 10 -ccd_temp 10 -posang 10 -object dog -dateobs 2006-10-20T10:10:10Z -uri file://$ID  || exit 1
+done;
+
+$regtool -pendingexp|| exit 1
+
+$regtool -addprocessedexp -exp_id $exp_id2 -exp_name t11 -inst gpc -telescope ps1 -exp_tag batman.t11 -filelevel OTA -filter r -airmass 11 -ra 1 -decl 2 -exp_type object -exp_time 0 -bg 11 -bg_stdev 1 -bg_mean_stdev 11 -alt 11 -az 11 -ccd_temp 45 -posang 11 -object dog -dateobs 2006-10-20T10:10:10Z -label foobar -tess_id moldyshoe $* || exit 1
+# BIAS or OBJECT? $regtool -addprocessedexp -exp_id $exp_id2 -exp_name t11 -inst gpc -telescope ps1 -exp_tag batman.t11 -filelevel OTA -filter r -airmass 11 -ra 1 -decl 2 -exp_type bias -exp_time 0 -bg 11 -bg_stdev 1 -bg_mean_stdev 11 -alt 11 -az 11 -ccd_temp 45 -posang 11 -object dog -dateobs 2006-10-20T10:10:10Z -label foobar -tess_id moldyshoe $* || exit 1
Index: /branches/eam_branches/eam_branch_20080719/ippTools/scripts/warptest.sh
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/scripts/warptest.sh	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/scripts/warptest.sh	(revision 22158)
@@ -0,0 +1,30 @@
+#!//bin/sh
+
+set -o verbose
+
+faketest.sh || exit 1
+
+#warp tool -definerun -fake_id 1 -mode warp -workdir file:///foo 
+
+#warptool -addinputexp -warp_id 1 -cam_id 1 || exit 1
+#warptool -addinputexp -warp_id 1 -cam_id 2 || exit 1
+#warptool -updaterun -warp_id 1 -state run || exit 1
+
+warptool -exp -warp_id 1 || exit 1
+
+warptool -imfile -warp_id 1 || exit 1
+
+warptool -tooverlap -warp_id 1 || exit 1
+
+warptool -addoverlap -mapfile mapfile.txt || exit 1
+
+warptool -scmap || exit 1
+
+warptool -towarped || exit 1
+
+warptool -addwarped -warp_id 1 -skycell_id foo1 -tess_id bar -uri file:///tmp/foo -path_base file://wonderland -bg 1 -bg_stdev 2 || exit 1
+warptool -addwarped -warp_id 1 -skycell_id foo2 -tess_id bar -uri file:///tmp/foo -path_base file://wonderland -bg 1 -bg_stdev 2 || exit 1
+
+warptool -warped -warp_id 1 || exit 1
+
+#warptool -updaterun -warp_id 1 -state stop || exit 1
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/.cvsignore	(revision 22158)
@@ -0,0 +1,2 @@
+Makefile.in
+Makefile
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/Makefile.am	(revision 22158)
@@ -0,0 +1,155 @@
+dist_pkgdata_DATA = \
+        camtool_donecleanup.sql \
+        camtool_find_chip_id.sql \
+        camtool_find_pendingexp.sql \
+        camtool_find_pendingimfile.sql \
+        camtool_find_processedexp.sql \
+        camtool_pendingcleanupexp.sql \
+        camtool_pendingcleanuprun.sql \
+        camtool_queue_chip_id.sql \
+        camtool_reset_faulted_runs.sql \
+        camtool_revertprocessedexp.sql \
+        chiptool_completely_processed_exp.sql \
+        chiptool_donecleanup.sql \
+        chiptool_find_rawexp.sql \
+        chiptool_pendingcleanupimfile.sql \
+        chiptool_pendingcleanuprun.sql \
+        chiptool_pendingimfile.sql \
+        chiptool_processedimfile.sql \
+        chiptool_revertprocessedimfile.sql \
+        chiptool_run.sql \
+        chiptool_unmasked.sql \
+        detselect_search.sql \
+        detselect_select.sql \
+        dettool_addprocessedexp.sql \
+        dettool_childlessrun.sql \
+        dettool_definebydetrun.sql \
+        dettool_detrunsummary.sql \
+        dettool_find_completed_runs.sql \
+        dettool_input.sql \
+        dettool_normalizedexp.sql \
+        dettool_normalizedimfile.sql \
+        dettool_normalizedstat.sql \
+        dettool_pending.sql \
+        dettool_pendingcleanup_normalizedexp.sql \
+        dettool_pendingcleanup_normalizedimfile.sql \
+        dettool_pendingcleanup_normalizedstat.sql \
+        dettool_pendingcleanup_processedexp.sql \
+        dettool_pendingcleanup_processedimfile.sql \
+        dettool_pendingcleanup_residexp.sql \
+        dettool_pendingcleanup_residimfile.sql \
+        dettool_pendingcleanup_stacked.sql \
+        dettool_processedimfile.sql \
+        dettool_raw.sql \
+        dettool_residexp.sql \
+        dettool_residimfile.sql \
+        dettool_revertdetrunsummary.sql \
+        dettool_revertnormalizedexp.sql \
+        dettool_revertnormalizedimfile.sql \
+        dettool_revertnormalizedstat.sql \
+        dettool_revertprocessedexp.sql \
+        dettool_revertprocessedimfile.sql \
+        dettool_revertresidexp.sql \
+        dettool_revertresidimfile.sql \
+        dettool_revertstacked.sql \
+        dettool_runs.sql \
+        dettool_stacked.sql \
+        dettool_start_new_iteration.sql \
+        dettool_stop_completed_correct_runs.sql \
+        dettool_tocorrectexp.sql \
+        dettool_tocorrectimfile.sql \
+        dettool_todetrunsummary.sql \
+        dettool_tonormalize.sql \
+        dettool_tonormalizedexp.sql \
+        dettool_tonormalizedstat.sql \
+        dettool_toprocessedexp.sql \
+        dettool_toprocessedimfile.sql \
+        dettool_toresidexp.sql \
+        dettool_toresidimfile.sql \
+        dettool_tostacked.sql \
+        difftool_definebyquery.sql \
+        difftool_donecleanup.sql \
+        difftool_inputskyfile.sql \
+        difftool_pendingcleanuprun.sql \
+        difftool_pendingcleanupskyfile.sql \
+        difftool_queue.sql \
+        difftool_revertdiffskyfile.sql \
+        difftool_skyfile.sql \
+        difftool_todiffskyfile.sql \
+        faketool_completely_processed_exp.sql \
+        faketool_donecleanup.sql \
+        faketool_find_camrun.sql \
+        faketool_find_pendingexp.sql \
+        faketool_pendingcleanupimfile.sql \
+        faketool_pendingcleanuprun.sql \
+        faketool_pendingimfile.sql \
+        faketool_processedimfile.sql \
+        faketool_queue_cam_id.sql \
+        faketool_revertprocessedimfile.sql \
+        faketool_unmasked.sql \
+        flatcorr_completely_processed_chiprun.sql \
+        flatcorr_create_tmp_chiprundone.sql \
+        flatcorr_find_completed_floatcorruns.sql \
+        flatcorr_find_processedimfiles.sql \
+        flatcorr_pending.sql \
+        magictool_addmask.sql \
+        magictool_create_tmp_warpcomplete.sql \
+        magictool_definebyquery.sql \
+        magictool_definebyquery_insert.sql \
+        magictool_definebyquery_select_part1.sql \
+        magictool_definebyquery_select_part2.sql \
+        magictool_definebyquery_select_test.sql \
+        magictool_definebyquery_temp_create.sql \
+        magictool_definebyquery_temp_insert.sql \
+        magictool_definebyquery_temp_insert_groupby.sql \
+        magictool_inputs.sql \
+        magictool_inputskyfile.sql \
+        magictool_mask.sql \
+        magictool_tomask.sql \
+        magictool_toprocess_inputs.sql \
+        magictool_toprocess_tree.sql \
+        magictool_toskyfilemask.sql \
+        magictool_totree.sql \
+        pstamptool_addjob_otherjob.sql \
+        pstamptool_addjob_stampjob.sql \
+        pstamptool_datastore.sql \
+        pstamptool_pendingjob.sql \
+        pstamptool_pendingreq.sql \
+        pxadmin_create_tables.sql \
+        pxadmin_drop_tables.sql \
+        pztool_find_completed_exp.sql \
+        pztool_pendingimfile.sql \
+        pztool_revert_downloadimfile_faults.sql \
+        pztool_revert_fileset_faults.sql \
+        pztool_revertcopied.sql \
+        regtool_create_dup_table.sql \
+        regtool_pendingexp.sql \
+        regtool_pendingimfile.sql \
+        regtool_populate_dup_table.sql \
+        regtool_processedexp.sql \
+        regtool_processedimfile.sql \
+        regtool_revertprocessedexp.sql \
+        regtool_revertprocessedimfile.sql \
+        stacktool_definebyquery_insert.sql \
+        stacktool_definebyquery_insert_random.sql \
+        stacktool_definebyquery_part1.sql \
+        stacktool_definebyquery_part2.sql \
+        stacktool_definebyquery_test.sql \
+        stacktool_donecleanup.sql \
+        stacktool_find_complete_warps.sql \
+        stacktool_inputskyfile.sql \
+        stacktool_pendingcleanuprun.sql \
+        stacktool_pendingcleanupskyfile.sql \
+        stacktool_revertsumskyfile.sql \
+        stacktool_sumskyfile.sql \
+        stacktool_tosum.sql \
+        warptool_donecleanup.sql \
+        warptool_exp.sql \
+        warptool_imfile.sql \
+        warptool_pendingcleanuprun.sql \
+        warptool_pendingcleanupskyfile.sql \
+        warptool_revertwarped.sql \
+        warptool_scmap.sql \
+        warptool_tooverlap.sql \
+        warptool_towarped.sql \
+        warptool_warped.sql
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_donecleanup.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_donecleanup.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_donecleanup.sql	(revision 22158)
@@ -0,0 +1,5 @@
+SELECT
+    camRun.*
+FROM camRun
+WHERE
+    camRun.state = 'cleaned'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_find_chip_id.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_find_chip_id.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_find_chip_id.sql	(revision 22158)
@@ -0,0 +1,31 @@
+SELECT
+    *
+FROM
+    (SELECT DISTINCT
+        chipRun.*,
+        rawExp.camera,
+        rawExp.telescope,
+        rawExp.dateobs,
+        rawExp.exp_tag,
+        rawExp.exp_type,
+        rawExp.filelevel,
+        rawExp.filter,
+        rawExp.airmass,
+        rawExp.ra,
+        rawExp.decl,
+        rawExp.exp_time,
+        rawExp.sat_pixel_frac,
+        rawExp.bg,
+        rawExp.bg_stdev,
+        rawExp.bg_mean_stdev,
+        rawExp.alt,
+        rawExp.az,
+        rawExp.ccd_temp,
+        rawExp.posang,
+        rawExp.object,
+        rawExp.solang
+    FROM chipRun
+    JOIN rawExp
+        using(exp_id)
+    WHERE
+        chipRun.state = 'full') as Foo
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_find_pendingexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_find_pendingexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_find_pendingexp.sql	(revision 22158)
@@ -0,0 +1,30 @@
+-- this query is used by both camtool -pendingexp & camtool -addprocessedexp it
+-- does a little more work then is necessary for -addprocessed but it seems
+-- "cleaner" to use the same query for both cases 
+SELECT * FROM
+    (SELECT
+        camRun.*,
+        rawExp.exp_tag,
+        rawExp.exp_id,
+        rawExp.exp_name,
+        rawExp.camera,
+        rawExp.telescope,
+        rawExp.filelevel
+    FROM camRun
+    JOIN chipRun
+        USING(chip_id)
+--  JOIN chipProcessedImfile
+--      USING(chip_id)
+    JOIN rawExp
+        USING(exp_id)
+--      ON chipProcessedImfile.exp_id = rawExp.exp_id
+    LEFT JOIN camProcessedExp
+        USING(cam_id)
+    LEFT JOIN camMask
+        ON camRun.label = camMask.label
+    WHERE
+        chipRun.state = 'full'
+        AND camRun.state = 'new'
+        AND camMask.label IS NULL
+        AND camProcessedExp.cam_id IS NULL
+    ) as Foo
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_find_pendingimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_find_pendingimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_find_pendingimfile.sql	(revision 22158)
@@ -0,0 +1,41 @@
+SELECT DISTINCT * FROM 
+     -- the subselect is so where criteria can be specified without knowing
+     -- which table the field came from
+    (SELECT
+        camRun.*,
+        chipProcessedImfile.exp_id,
+        chipProcessedImfile.class_id,
+        chipProcessedImfile.uri,
+        chipProcessedImfile.bg,
+        chipProcessedImfile.bg_stdev,
+        chipProcessedImfile.bg_mean_stdev,
+        chipProcessedImfile.fringe_0,
+        chipProcessedImfile.fringe_1,
+        chipProcessedImfile.fringe_2,
+        chipProcessedImfile.ap_resid,
+        chipProcessedImfile.ap_resid_stdev,
+        chipProcessedImfile.sigma_ra,
+        chipProcessedImfile.sigma_dec,
+        chipProcessedImfile.n_stars,
+        chipProcessedImfile.n_extended,
+        chipProcessedImfile.n_cr,
+        chipProcessedImfile.n_astrom,
+        chipProcessedImfile.path_base,
+        rawExp.exp_name,
+        rawExp.camera,
+        rawExp.telescope,
+        rawExp.filelevel
+    FROM camRun
+    JOIN chipRun
+        USING(chip_id)
+    JOIN chipProcessedImfile
+        USING(chip_id)
+    JOIN rawExp
+        ON chipProcessedImfile.exp_id = rawExp.exp_id
+    LEFT JOIN camProcessedExp
+        USING(cam_id)
+    LEFT JOIN camMask
+        ON camRun.label = camMask.label
+    WHERE
+        camProcessedExp.cam_id IS NULL
+        AND camMask.label IS NULL) as foo
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_find_processedexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_find_processedexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_find_processedexp.sql	(revision 22158)
@@ -0,0 +1,18 @@
+SELECT DISTINCT
+    camProcessedExp.*,
+    rawExp.exp_tag,
+    rawExp.exp_name,
+    rawExp.camera,
+    rawExp.telescope,
+    rawExp.filelevel
+FROM camRun
+JOIN camProcessedExp
+    USING(cam_id)
+JOIN chipRun
+    USING(chip_id)
+JOIN chipProcessedImfile
+    USING(chip_id)
+JOIN rawExp
+    ON chipProcessedImfile.exp_id = rawExp.exp_id
+WHERE -- bogus condition so there is a pre-existing where to append to
+    camProcessedExp.cam_id IS NOT NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_pendingcleanupexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_pendingcleanupexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_pendingcleanupexp.sql	(revision 22158)
@@ -0,0 +1,15 @@
+SELECT
+    camProcessedExp.*,
+    camRun.state,
+    camRun.workdir,
+    camRun.label,
+    camRun.reduction,
+    camRun.expgroup,
+    camRun.dvodb,
+    camRun.tess_id,
+    camRun.end_stage
+FROM camRun
+JOIN camProcessedExp
+    USING(cam_id)
+WHERE
+    camRun.state = 'goto_cleaned'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_pendingcleanuprun.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_pendingcleanuprun.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_pendingcleanuprun.sql	(revision 22158)
@@ -0,0 +1,11 @@
+SELECT
+    camRun.cam_id,
+    rawExp.camera,
+    camRun.state
+FROM camRun
+JOIN chipRun
+USING (chip_id)
+JOIN rawExp 
+USING (exp_id)
+WHERE
+    camRun.state = 'goto_cleaned'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_queue_chip_id.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_queue_chip_id.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_queue_chip_id.sql	(revision 22158)
@@ -0,0 +1,19 @@
+-- camtool only operates on exposures so we can safely queue more then one at a
+-- time without worrying about losing the track of the generated cam_id
+INSERT INTO camRun
+    SElECT
+        0,              -- cam_id
+        chip_id,        -- chip_id
+        '%s',           -- state
+        '%s',           -- workdir
+        '%s',           -- workdir_state
+        '%s',           -- label
+        '%s',           -- reduction
+        '%s',           -- expgroup
+        '%s',           -- dvodb 
+        '%s',           -- tess_id
+        '%s'            -- end_stage
+    FROM chipRun
+    WHERE
+        chipRun.state = 'full'
+        AND chipRun.chip_id = %lld
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_reset_faulted_runs.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_reset_faulted_runs.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_reset_faulted_runs.sql	(revision 22158)
@@ -0,0 +1,7 @@
+UPDATE camRun, camProcessedExp, chipRun, rawExp
+SET camRun.state = 'new'
+WHERE
+    camRun.cam_id = camProcessedExp.cam_id
+    AND camRun.chip_id = chipRun.chip_id
+    AND chipRun.exp_id = rawExp.exp_id
+    AND camProcessedExp.fault != 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_revertprocessedexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_revertprocessedexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/camtool_revertprocessedexp.sql	(revision 22158)
@@ -0,0 +1,7 @@
+DELETE FROM camProcessedExp
+USING camProcessedExp, camRun, chipRun, rawExp
+WHERE
+    camRun.cam_id = camProcessedExp.cam_id
+    AND camRun.chip_id = chipRun.chip_id
+    AND chipRun.exp_id = rawExp.exp_id
+    AND camProcessedExp.fault != 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_completely_processed_exp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_completely_processed_exp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_completely_processed_exp.sql	(revision 22158)
@@ -0,0 +1,34 @@
+-- the output of this query must match the format of chipRun row
+SELECT DISTINCT
+    chip_id,
+    exp_id,
+    state,
+    workdir,
+    workdir_state,
+    label,
+    reduction,
+    expgroup,
+    dvodb,
+    tess_id,
+    end_stage
+FROM
+    (SELECT 
+        chipRun.*,
+        rawImfile.class_id as rawimfile_class_id,
+        chipProcessedImfile.class_id
+    FROM chipRun
+    JOIN rawImfile
+        USING(exp_id)
+    LEFT JOIN chipProcessedImfile
+        ON chipRun.chip_id = chipProcessedImfile.chip_id
+        AND rawImfile.exp_id = chipProcessedImfile.exp_id
+        AND rawImfile.class_id = chipProcessedImfile.class_id
+    WHERE
+        chipRun.state = 'new'
+    GROUP BY
+        chipRun.chip_id,
+        chipRun.exp_id
+    HAVING
+        COUNT(rawImfile.class_id) = COUNT(chipProcessedImfile.class_id)
+        AND SUM(chipProcessedImfile.fault) = 0
+    ) as Foo
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_donecleanup.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_donecleanup.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_donecleanup.sql	(revision 22158)
@@ -0,0 +1,5 @@
+SELECT
+    chipRun.*
+FROM chipRun
+WHERE
+    chipRun.state = 'cleaned'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_find_rawexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_find_rawexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_find_rawexp.sql	(revision 22158)
@@ -0,0 +1,7 @@
+-- this query is used to find potental rawExps to be queued for chiptool
+-- processeing
+SELECT
+    exp_id
+FROM rawExp
+WHERE
+    rawExp.fault = 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_find_unprocessed_imfile.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_find_unprocessed_imfile.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_find_unprocessed_imfile.pl	(revision 22158)
@@ -0,0 +1,8 @@
+SELECT DISTINCT
+   chipInputImfile.*
+FROM chipInputImfile
+LEFT JOIN chipProcessedImfile
+    USING(chip_id, class_id)
+WHERE
+    chipProcessedImfile.chip_id IS NULL
+    AND chipProcessedImfile.class_id IS NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_pendingcleanupimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_pendingcleanupimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_pendingcleanupimfile.sql	(revision 22158)
@@ -0,0 +1,15 @@
+SELECT
+    chipProcessedImfile.*,
+    chipRun.state,
+    chipRun.workdir,
+    chipRun.label,
+    chipRun.reduction,
+    chipRun.expgroup,
+    chipRun.dvodb,
+    chipRun.tess_id,
+    chipRun.end_stage
+FROM chipRun
+JOIN chipProcessedImfile
+    USING(chip_id)
+WHERE
+    chipRun.state = 'goto_cleaned'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_pendingcleanuprun.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_pendingcleanuprun.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_pendingcleanuprun.sql	(revision 22158)
@@ -0,0 +1,9 @@
+SELECT
+    chipRun.chip_id,
+    rawExp.camera,
+    chipRun.state
+FROM chipRun
+JOIN rawExp 
+USING (exp_id)
+WHERE
+    chipRun.state = 'goto_cleaned'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_pendingimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_pendingimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_pendingimfile.sql	(revision 22158)
@@ -0,0 +1,26 @@
+SELECT
+    chipRun.*,
+    rawImfile.class_id,
+    rawImfile.uri,
+    rawExp.exp_tag,
+    rawExp.exp_name,
+    rawExp.camera,
+    rawExp.telescope,
+    rawExp.filelevel
+FROM chipRun
+JOIN rawExp
+    USING(exp_id)
+JOIN rawImfile
+    USING(exp_id)
+LEFT JOIN chipProcessedImfile
+    ON chipRun.chip_id = chipProcessedImfile.chip_id
+    AND rawImfile.exp_id = chipProcessedImfile.exp_id
+    AND rawImfile.class_id = chipProcessedImfile.class_id
+LEFT JOIN chipMask
+    ON chipRun.label = chipMask.label
+WHERE
+    chipRun.state = 'new'
+    AND chipProcessedImfile.chip_id IS NULL
+    AND chipProcessedImfile.exp_id IS NULL
+    AND chipProcessedImfile.class_id IS NULL
+    AND chipMask.label IS NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_processedimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_processedimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_processedimfile.sql	(revision 22158)
@@ -0,0 +1,23 @@
+SELECT DISTINCT
+    chipProcessedImfile.class_id,
+    chipProcessedImfile.uri,
+    chipProcessedImfile.bg,
+    chipProcessedImfile.bg_stdev,
+    chipProcessedImfile.bg_mean_stdev,
+    chipProcessedImfile.path_base,
+    chipRun.state,
+    rawExp.exp_id,
+    rawExp.exp_tag,
+    rawExp.exp_name,
+    rawExp.camera,
+    rawExp.telescope,
+    rawExp.filelevel
+FROM chipRun
+JOIN chipProcessedImfile
+    USING(chip_id)
+JOIN rawExp
+    ON chipProcessedImfile.exp_id = rawExp.exp_id
+WHERE
+-- bogus test; just here so there there is a 'WHERE' stmt to append conditionals too
+    chipProcessedImfile.exp_id is NOT NULL
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_revertprocessedimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_revertprocessedimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_revertprocessedimfile.sql	(revision 22158)
@@ -0,0 +1,5 @@
+DELETE FROM chipProcessedImfile
+USING chipProcessedImfile, rawExp
+WHERE
+    rawExp.exp_id = chipProcessedImfile.exp_id
+    AND chipProcessedImfile.fault != 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_run.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_run.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_run.sql	(revision 22158)
@@ -0,0 +1,3 @@
+SELECT
+    chipRun.*
+FROM chipRun
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_unmasked.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_unmasked.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/chiptool_unmasked.sql	(revision 22158)
@@ -0,0 +1,43 @@
+-- SELECT
+--  *
+-- FROM
+--  (SELECT 
+--      chipMask.label as label, 
+--      count(chipRun.chip_id) as n_chipruns
+--   FROM 
+--      chipMask 
+--   LEFT JOIN 
+--      chipRun 
+--   USING 
+--      (label) 
+--   WHERE chipRun.chip_id IS NOT NULL 
+--   GROUP BY label) as chipMask
+
+-- SELECT
+--  *
+-- FROM
+--  SELECT 
+--      chipRun.*, 
+--      rawExp.*,
+--      chipRun.chip_id as n_chipruns
+--   FROM 
+--      chipRun 
+--   JOIN rawExp ON chipRun.exp_id = rawExp.exp_id
+--   LEFT JOIN chipMask 
+--   USING (label) 
+--   WHERE chipMask.label IS NULL 
+--   AND filter = 'r'
+--   AND chipRun.exp_id = 61
+--  GROUP BY chipRun.label) as chipUnmask
+
+SELECT
+ *
+FROM
+ (SELECT 
+     chipRun.label, 
+     count(chipRun.chip_id) as n_chipruns
+  FROM chipRun 
+  LEFT JOIN chipMask 
+  USING (label) 
+  WHERE chipMask.label IS NULL 
+  GROUP BY chipRun.label) as chipUnmask
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/detselect_search.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/detselect_search.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/detselect_search.sql	(revision 22158)
@@ -0,0 +1,29 @@
+-- this query needs to use the same fields in both of the tables in
+-- the union statement, but we need to report the
+-- detRunSummary.iteration in the first case, and this is missing in
+-- the second case.
+
+SELECT DISTINCT
+    det_id,
+    good_iteration as iteration,
+    filelevel
+FROM
+    (SELECT DISTINCT
+	detRun.*,
+	detRunSummary.iteration as good_iteration
+    FROM detRun
+    JOIN detRunSummary
+        USING(det_id)
+    WHERE
+       detRun.mode  = 'master'
+       AND detRunSummary.accept = 1
+    UNION
+    SELECT DISTINCT
+	detRun.*,
+	detRun.iteration as good_iteration
+    FROM detRun
+    WHERE
+       (detRun.mode  = 'register' OR detRun.mode = 'correction')
+    ) as Foo
+WHERE
+    (state = 'stop' OR state = 'register')
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/detselect_select.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/detselect_select.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/detselect_select.sql	(revision 22158)
@@ -0,0 +1,27 @@
+SELECT DISTINCT
+    *
+FROM
+    (SELECT DISTINCT
+	detRun.state,
+        detNormalizedImfile.*
+    FROM detNormalizedImfile
+    JOIN detRun
+        USING(det_id)
+    JOIN detRunSummary
+        ON detNormalizedImfile.det_id = detRunSummary.det_id
+        AND detNormalizedImfile.iteration = detRunSummary.iteration
+    WHERE
+        detRun.mode  = 'master'
+        AND detRunSummary.accept = 1
+    UNION
+    SELECT DISTINCT
+	detRun.state,
+        detRegisteredImfile.*
+    FROM detRegisteredImfile
+    JOIN detRun
+        USING(det_id)
+    WHERE
+        (detRun.mode  = 'register' OR detRun.mode = 'correction')
+    ) as Foo
+WHERE
+    (state = 'stop' OR state = 'register')
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_addprocessedexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_addprocessedexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_addprocessedexp.sql	(revision 22158)
@@ -0,0 +1,34 @@
+SELECT DISTINCT
+   detProcessedImfile.det_id,
+   detRun.iteration,
+   detRun.det_type,
+   detProcessedImfile.exp_id
+FROM detRun
+JOIN detInputExp
+   ON detRun.det_id = detInputExp.det_id
+   AND detRun.iteration = detInputExp.iteration
+JOIN rawExp
+   ON detInputExp.exp_id = rawExp.exp_id
+JOIN detProcessedImfile
+   ON detInputExp.det_id = detProcessedImfile.det_id
+   AND detInputExp.exp_id = detProcessedImfile.exp_id
+LEFT JOIN detProcessedExp
+   ON detInputExp.det_id = detProcessedExp.det_id
+   AND detProcessedImfile.exp_id= detProcessedExp.exp_id
+LEFT JOIN rawImfile
+   ON detInputExp.exp_id = rawImfile.exp_id
+   AND detProcessedImfile.class_id = rawImfile.class_id
+WHERE
+  detRun.state = 'run'
+  AND detRun.mode = 'master'
+  AND detProcessedExp.det_id IS NULL
+  AND detProcessedExp.exp_id IS NULL
+  AND detInputExp.include = 1
+  AND detRun.det_id = %lld
+  AND detProcessedImfile.exp_id = %lld
+GROUP BY
+   detProcessedImfile.class_id,
+   rawImfile.class_id,
+   detRun.det_id
+HAVING
+   COUNT(detProcessedImfile.class_id) = COUNT(rawImfile.class_id)
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_childlessrun.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_childlessrun.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_childlessrun.sql	(revision 22158)
@@ -0,0 +1,11 @@
+-- dettool -childlessrun
+
+SELECT DISTINCT
+   detRun.*
+ FROM detRun
+ LEFT JOIN detRun as foo
+   ON foo.parent = detRun.det_id
+ WHERE
+   detRun.state = 'stop'
+   AND detRun.mode = 'master'
+   AND foo.det_id IS NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_definebydetrun.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_definebydetrun.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_definebydetrun.sql	(revision 22158)
@@ -0,0 +1,12 @@
+-- dettool -definebydetrun
+
+INSERT INTO detInputExp
+   SELECT
+       %lld,
+       0,
+       detResidExp.exp_id,
+       detResidExp.accept
+   FROM detResidExp
+   JOIN rawExp
+       USING(exp_id)
+   WHERE det_id = %lld
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_detrunsummary.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_detrunsummary.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_detrunsummary.sql	(revision 22158)
@@ -0,0 +1,9 @@
+SELECT DISTINCT
+   detRunSummary.*,
+   detRun.det_type,
+   detRun.mode
+ FROM detRun
+ JOIN detRunSummary
+   USING(det_id, iteration)
+ WHERE
+   detRun.state = 'run'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_find_completed_runs.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_find_completed_runs.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_find_completed_runs.sql	(revision 22158)
@@ -0,0 +1,26 @@
+SELECT DISTINCT
+   det_id,
+   iteration
+FROM
+    (SELECT DISTINCT
+        detRun.det_id,
+        detRun.iteration,
+        detInputExp.exp_id
+    FROM detRun
+        LEFT JOIN detInputExp
+        ON detRun.det_id = detInputExp.det_id
+        AND detRun.iteration = detInputExp.iteration
+    LEFT JOIN rawExp
+        ON detInputExp.exp_id = rawExp.exp_id
+    LEFT JOIN detResidExp
+        ON detRun.det_id = detResidExp.det_id
+        AND detRun.iteration = detResidExp.iteration
+        AND detInputExp.exp_id = detResidExp.exp_id
+   WHERE
+        detRun.state = 'run'
+   GROUP BY
+        detRun.det_id,
+        detRun.iteration
+    HAVING
+        COUNT(detResidExp.exp_id) = COUNT(detInputExp.exp_id)
+    ) AS residdetrun
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_input.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_input.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_input.sql	(revision 22158)
@@ -0,0 +1,4 @@
+SELECT DISTINCT *
+ FROM detInputExp
+ JOIN rawExp
+ USING(exp_id)
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_normalizedexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_normalizedexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_normalizedexp.sql	(revision 22158)
@@ -0,0 +1,8 @@
+SELECT
+   detNormalizedExp.*
+ FROM detNormalizedExp
+ JOIN detRun
+   USING(det_id, iteration)
+ WHERE
+   detRun.state = 'run'
+   AND detRun.mode = 'master'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_normalizedimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_normalizedimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_normalizedimfile.sql	(revision 22158)
@@ -0,0 +1,8 @@
+SELECT
+ detNormalizedImfile.*
+ FROM detNormalizedImfile
+ JOIN detRun
+   USING(det_id, iteration)
+ WHERE
+   detRun.state = 'run'
+   AND detRun.mode = 'master'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_normalizedstat.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_normalizedstat.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_normalizedstat.sql	(revision 22158)
@@ -0,0 +1,12 @@
+SELECT
+    *
+FROM
+    (SELECT
+        detNormalizedStatImfile.*
+    FROM detNormalizedStatImfile
+    JOIN detRun
+    USING(det_id, iteration)
+    WHERE
+        detRun.state = 'run'
+        AND detRun.mode = 'master'
+    ) as Foo
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pending.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pending.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pending.sql	(revision 22158)
@@ -0,0 +1,10 @@
+-- dettool -pending : not sure this is still used (EAM : 2008.07.10)
+
+SELECT
+   rawExp.*
+ FROM rawExp
+ LEFT JOIN detInputExp
+   ON rawExp.exp_id = detInputExp.exp_id
+ WHERE
+    detInputExp.exp_id IS NULL
+    AND rawExp.object != 'object'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_normalizedexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_normalizedexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_normalizedexp.sql	(revision 22158)
@@ -0,0 +1,9 @@
+SELECT
+    detNormalizedExp.*,
+    detRunSummary.data_state
+FROM detRunSummary
+JOIN detNormalizedExp
+    USING(det_id,iteration)
+WHERE
+    detRunSummary.data_state = 'goto_cleaned'
+AND detNormalizedExp.data_state = 'full'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_normalizedimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_normalizedimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_normalizedimfile.sql	(revision 22158)
@@ -0,0 +1,9 @@
+SELECT
+    detNormalizedImfile.*,
+    detRunSummary.data_state
+FROM detRunSummary
+JOIN detNormalizedImfile
+    USING(det_id,iteration)
+WHERE
+    detRunSummary.data_state = 'goto_cleaned'
+AND detNormalizedImfile.data_state = 'full'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_normalizedstat.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_normalizedstat.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_normalizedstat.sql	(revision 22158)
@@ -0,0 +1,9 @@
+SELECT
+    detNormalizedStatImfile.*,
+    detRunSummary.data_state
+FROM detRunSummary
+JOIN detNormalizedStatImfile
+    USING(det_id,iteration)
+WHERE
+    detRunSummary.data_state = 'goto_cleaned'
+AND detNormalizedStatImfile.data_state = 'full'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_processedexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_processedexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_processedexp.sql	(revision 22158)
@@ -0,0 +1,10 @@
+-- need to restrict to a single detRunSummary (require all to say 'cleaned'?)
+SELECT
+    detProcessedExp.*,
+    detRunSummary.data_state
+FROM detRunSummary
+JOIN detProcessedExp
+    USING(det_id)
+WHERE
+    detRunSummary.data_state = 'goto_cleaned'
+AND detProcessedExp.data_state = 'full'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_processedimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_processedimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_processedimfile.sql	(revision 22158)
@@ -0,0 +1,10 @@
+-- need to restrict to a single detRunSummary (require all to say 'cleaned'?)
+SELECT
+    detProcessedImfile.*,
+    detRunSummary.data_state
+FROM detRunSummary
+JOIN detProcessedImfile
+    USING(det_id)
+WHERE
+    detRunSummary.data_state = 'goto_cleaned'
+AND detProcessedImfile.data_state = 'full'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_residexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_residexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_residexp.sql	(revision 22158)
@@ -0,0 +1,9 @@
+SELECT
+    detResidExp.*,
+    detRunSummary.data_state
+FROM detRunSummary
+JOIN detResidExp
+    USING(det_id,iteration)
+WHERE
+    detRunSummary.data_state = 'goto_cleaned'
+AND detResidExp.data_state = 'full'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_residimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_residimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_residimfile.sql	(revision 22158)
@@ -0,0 +1,9 @@
+SELECT
+    detResidImfile.*,
+    detRunSummary.data_state
+FROM detRunSummary
+JOIN detResidImfile
+    USING(det_id,iteration)
+WHERE
+    detRunSummary.data_state = 'goto_cleaned'
+AND detResidImfile.data_state = 'full'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_stacked.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_stacked.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_pendingcleanup_stacked.sql	(revision 22158)
@@ -0,0 +1,9 @@
+SELECT
+    detStackedImfile.*,
+    detRunSummary.data_state
+FROM detRunSummary
+JOIN detStackedImfile
+    USING(det_id,iteration)
+WHERE
+    detRunSummary.data_state = 'goto_cleaned'
+AND detStackedImfile.data_state = 'full'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_processedimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_processedimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_processedimfile.sql	(revision 22158)
@@ -0,0 +1,13 @@
+SELECT DISTINCT
+  detRun.det_type,
+  rawExp.exp_time,
+  detProcessedImfile.*
+FROM detProcessedImfile
+JOIN detRun
+  USING(det_id)
+JOIN detInputExp
+  ON detRun.det_id = detInputExp.det_id
+  AND detRun.iteration = detInputExp.iteration
+  AND detProcessedImfile.exp_id = detInputExp.exp_id
+JOIN rawExp
+  ON rawExp.exp_id = detProcessedImfile.exp_id
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_raw.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_raw.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_raw.sql	(revision 22158)
@@ -0,0 +1,12 @@
+SELECT
+    detInputExp.det_id,
+    detRun.det_type,
+    rawImfile.*
+FROM detRun
+JOIN detInputExp
+    USING(det_id) 
+JOIN rawImfile
+    ON detInputExp.exp_id = rawImfile.exp_id
+WHERE
+    detRun.state = 'run'
+    AND detRun.mode = 'master'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_residexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_residexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_residexp.sql	(revision 22158)
@@ -0,0 +1,11 @@
+SELECT
+   detRun.mode,
+   detResidExp.*,
+   detInputExp.include
+ FROM detRun
+ JOIN detInputExp
+   USING(det_id, iteration)
+ JOIN detResidExp
+   USING(det_id, iteration, exp_id)
+ WHERE
+   detRun.state = 'run'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_residimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_residimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_residimfile.sql	(revision 22158)
@@ -0,0 +1,11 @@
+SELECT
+   detRun.det_type,
+   detRun.mode,
+   detResidImfile.*,
+   rawExp.exp_time
+ FROM detResidImfile
+ JOIN detRun
+   USING(det_id, iteration)
+ JOIN rawExp
+   USING(exp_id)
+ WHERE
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertdetrunsummary.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertdetrunsummary.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertdetrunsummary.sql	(revision 22158)
@@ -0,0 +1,3 @@
+DELETE FROM detRunSummary
+WHERE
+    fault != 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertnormalizedexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertnormalizedexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertnormalizedexp.sql	(revision 22158)
@@ -0,0 +1,3 @@
+DELETE FROM detNormalizedExp
+WHERE
+    fault != 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertnormalizedimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertnormalizedimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertnormalizedimfile.sql	(revision 22158)
@@ -0,0 +1,3 @@
+DELETE FROM detNormalizedImfile
+WHERE
+    fault != 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertnormalizedstat.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertnormalizedstat.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertnormalizedstat.sql	(revision 22158)
@@ -0,0 +1,3 @@
+DELETE FROM detNormalizedStatImfile
+WHERE
+    fault != 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertprocessedexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertprocessedexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertprocessedexp.sql	(revision 22158)
@@ -0,0 +1,3 @@
+DELETE FROM detProcessedExp
+WHERE
+    fault != 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertprocessedimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertprocessedimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertprocessedimfile.sql	(revision 22158)
@@ -0,0 +1,3 @@
+DELETE FROM detProcessedImfile
+WHERE
+    fault != 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertresidexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertresidexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertresidexp.sql	(revision 22158)
@@ -0,0 +1,3 @@
+DELETE FROM detResidExp
+WHERE
+    fault != 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertresidimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertresidimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertresidimfile.sql	(revision 22158)
@@ -0,0 +1,3 @@
+DELETE FROM detResidImfile
+WHERE
+    fault != 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertstacked.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertstacked.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_revertstacked.sql	(revision 22158)
@@ -0,0 +1,3 @@
+DELETE FROM detStackedImfile
+WHERE
+    fault != 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_runs.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_runs.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_runs.sql	(revision 22158)
@@ -0,0 +1,2 @@
+
+SELECT * from detRun
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_stacked.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_stacked.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_stacked.sql	(revision 22158)
@@ -0,0 +1,12 @@
+-- select detStackedImfile.*
+-- by:
+-- where det_id, iteration, class_id is not in detNormalizedImfile
+
+SELECT
+   detStackedImfile.*
+ FROM detStackedImfile
+ JOIN detRun
+   USING(det_id, iteration)
+ WHERE
+   detRun.state = 'run'
+   AND detRun.mode = 'master'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_start_new_iteration.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_start_new_iteration.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_start_new_iteration.sql	(revision 22158)
@@ -0,0 +1,33 @@
+-- select detRun.iteration
+-- select detInputExp.exp_id
+-- select detResidExp.accept
+-- by:
+-- find the current iteration bassed on det_id
+-- find all exp_ids in the current det_id/iteration from detInputExp
+-- find all exp_ids in the current det_id/iteration from detResidExp
+-- compare the counts of exp_ids
+
+SELECT * FROM
+    (SELECT DISTINCT
+        detRun.det_id AS det_id,
+        detRun.iteration,
+        detInputExp.exp_id,
+        detResidExp.accept
+    FROM detRun
+    JOIN detInputExp
+        ON detRun.det_id = detInputExp.det_id
+        AND detRun.iteration = detInputExp.iteration
+    JOIN detResidExp
+        ON detRun.det_id = detResidExp.det_id
+        AND detRun.iteration = detResidExp.iteration
+        AND detInputExp.exp_id = detResidExp.exp_id
+    WHERE
+        detRun.state = 'run'
+        AND detRun.mode = 'master'
+    GROUP BY
+        detRun.det_id,
+        detRun.iteration,
+        detInputExp.exp_id
+    HAVING
+        COUNT(detResidExp.exp_id) = COUNT(detInputExp.exp_id)
+    ) as Foo
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_stop_completed_correct_runs.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_stop_completed_correct_runs.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_stop_completed_correct_runs.sql	(revision 22158)
@@ -0,0 +1,28 @@
+UPDATE detRun
+SET state = 'stop'
+WHERE det_id = (SELECT det_id FROM
+    (SELECT
+        det1.det_id,
+        imfile.class_id,
+        detRegisteredImfile.class_id as reg_class_id
+    FROM detRun AS det1
+    INNER JOIN detRun as det2
+        ON det1.parent = det2.det_id 
+    JOIN detNormalizedImfile as imfile
+        ON det2.det_id = imfile.det_id
+        AND det2.iteration = imfile.iteration
+    LEFT JOIN detRegisteredImfile
+        ON det1.det_id = detRegisteredImfile.det_id
+        AND det1.iteration = detRegisteredImfile.iteration
+        AND imfile.class_id = detRegisteredImfile.class_id
+    WHERE 
+        det1.state = 'run'
+        AND det1.mode = 'correction'
+        AND det2.state = 'stop'
+    GROUP BY
+        det1.det_id
+    HAVING
+        COUNT(imfile.class_id) = COUNT(reg_class_id)
+        AND SUM(imfile.fault) = 0
+    ) as Foo
+)
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_tocorrectexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_tocorrectexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_tocorrectexp.sql	(revision 22158)
@@ -0,0 +1,4 @@
+SELECT * FROM detRun
+WHERE
+    detRun.mode = 'correction'
+    AND detRun.state = 'run'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_tocorrectimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_tocorrectimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_tocorrectimfile.sql	(revision 22158)
@@ -0,0 +1,31 @@
+SELECT
+    det1.*,
+    imfile.class_id,
+    imfile.uri,
+    imfile.bg,
+    imfile.bg_stdev,
+    imfile.bg_mean_stdev,
+    imfile.user_1,
+    imfile.user_2,
+    imfile.user_3,
+    imfile.user_4,
+    imfile.user_5,
+    imfile.path_base,
+    imfile.fault
+FROM detRun AS det1
+INNER JOIN detRun as det2
+    ON det1.parent = det2.det_id 
+JOIN detNormalizedImfile as imfile
+    ON det2.det_id = imfile.det_id
+    AND det2.iteration = imfile.iteration
+LEFT JOIN detRegisteredImfile
+    ON det1.det_id = detRegisteredImfile.det_id
+    AND det1.iteration = detRegisteredImfile.iteration
+    AND imfile.class_id = detRegisteredImfile.class_id
+WHERE 
+    det1.state = 'run'
+    AND det1.mode = 'correction'
+    AND det2.state = 'stop'
+    AND detRegisteredImfile.det_id IS NULL
+    AND detRegisteredImfile.iteration IS NULL
+    AND detRegisteredImfile.class_id IS NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_todetrunsummary.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_todetrunsummary.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_todetrunsummary.sql	(revision 22158)
@@ -0,0 +1,47 @@
+-- select detRun.det_id
+-- select detRun.iteration
+-- select detRun.det_type
+-- by:
+-- find the current iteration bassed on det_id
+-- find all exp_ids in the current det_id/iteration from detInputExp
+-- find all exp_ids in the current det_id/iteration from detResidExp
+-- compare the counts of exp_ids
+
+SELECT DISTINCT
+    det_id,
+    iteration,
+    det_type,
+    mode,
+    workdir,
+    camera
+FROM
+    (SELECT DISTINCT
+        detRun.det_id,
+        detRun.iteration,
+        detRun.det_type,
+        detRun.mode,
+        detRun.workdir,
+        detInputExp.exp_id,
+        rawExp.camera
+    FROM detRun
+    JOIN detInputExp
+        USING(det_id, iteration)
+    JOIN rawExp
+        ON detInputExp.exp_id = rawExp.exp_id
+    LEFT JOIN detResidExp
+        ON detRun.det_id = detResidExp.det_id
+        AND detRun.iteration = detResidExp.iteration
+        AND detInputExp.exp_id = detResidExp.exp_id
+    LEFT JOIN detRunSummary
+        ON detRun.det_id = detRunSummary.det_id
+        AND detRun.iteration = detRunSummary.iteration
+    WHERE
+        detRun.state = 'run'
+        AND detRunSummary.det_id IS NULL
+        AND detRunSummary.iteration IS NULL
+    GROUP BY
+        detRun.det_id,
+        detRun.iteration
+    HAVING
+        COUNT(detResidExp.exp_id) = COUNT(detInputExp.exp_id)
+    ) AS Foo
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_tonormalize.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_tonormalize.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_tonormalize.sql	(revision 22158)
@@ -0,0 +1,27 @@
+SELECT DISTINCT
+   detRun.det_type,
+   detRun.workdir,
+   rawExp.camera,
+   detStackedImfile.uri,
+   detNormalizedStatImfile.*
+ FROM detRun
+ JOIN detStackedImfile
+   USING(det_id, iteration)
+ JOIN detInputExp
+   USING(det_id, iteration)
+ JOIN rawExp
+   ON detInputExp.exp_id = rawExp.exp_id
+ JOIN detNormalizedStatImfile
+   ON detStackedImfile.det_id = detNormalizedStatImfile.det_id
+   AND detStackedImfile.iteration = detNormalizedStatImfile.iteration
+   AND detStackedImfile.class_id = detNormalizedStatImfile.class_id
+ LEFT JOIN detNormalizedImfile
+   ON detNormalizedStatImfile.det_id = detNormalizedImfile.det_id
+   AND detNormalizedStatImfile.iteration = detNormalizedImfile.iteration
+   AND detNormalizedStatImfile.class_id = detNormalizedImfile.class_id
+ WHERE
+   detNormalizedImfile.det_id IS NULL
+   AND detNormalizedImfile.iteration IS NULL
+   AND detNormalizedImfile.class_id IS NULL
+   AND detNormalizedStatImfile.fault = 0
+   AND detRun.state = 'run'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_tonormalizedexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_tonormalizedexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_tonormalizedexp.sql	(revision 22158)
@@ -0,0 +1,48 @@
+-- this is used by both 'tonormalizedexp' and 'addnormalizedexp'
+
+SELECT
+    *
+FROM (SELECT 
+      *
+    FROM (
+        SELECT DISTINCT
+            detRun.det_id,
+            detRun.iteration,
+            detRun.det_type,
+            detRun.workdir,
+            rawExp.camera,
+            rawExp.telescope,
+            rawExp.exp_type,
+            detNormalizedImfile.class_id as norm_class_id,
+            detNormalizedImfile.fault,
+            detStackedImfile.class_id as stack_class_id
+        FROM detRun
+        JOIN detInputExp
+            ON detRun.det_id = detInputExp.det_id
+            AND detRun.iteration = detInputExp.iteration
+        JOIN rawExp
+            ON detInputExp.exp_id = rawExp.exp_id
+        JOIN detStackedImfile
+            ON detStackedImfile.det_id = detRun.det_id
+            AND detStackedImfile.iteration = detRun.iteration
+        LEFT JOIN detNormalizedImfile
+            ON detStackedImfile.det_id = detNormalizedImfile.det_id
+            AND detStackedImfile.iteration = detNormalizedImfile.iteration
+            AND detStackedImfile.class_id = detNormalizedImfile.class_id
+        LEFT JOIN detNormalizedExp
+            ON detInputExp.det_id = detNormalizedExp.det_id
+            AND detInputExp.iteration = detNormalizedExp.iteration
+        WHERE
+            detRun.state = 'run' AND
+            detRun.mode = 'master' AND
+            detNormalizedExp.det_id IS NULL AND
+            detNormalizedExp.iteration IS NULL AND
+            detInputExp.include = 1
+    ) as Foo
+    GROUP BY
+      det_id,
+      iteration
+    HAVING
+      COUNT(norm_class_id) = COUNT(stack_class_id)
+      AND SUM(fault) = 0
+) as Bar
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_tonormalizedstat.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_tonormalizedstat.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_tonormalizedstat.sql	(revision 22158)
@@ -0,0 +1,58 @@
+-- select detRun.det_id (det_id)
+-- select detRun.iteration
+-- by:
+-- find the current iteration bassed on det_id
+-- find all exp_ids in the current det_id/iteration from detInputExp
+-- sort to detInputExp.imfiles to find the largest value per det_id/iter
+-- compare imfiles to the number of detStackedImfiles by class_id
+-- and:
+-- ???
+-- det_id is not in detStackedImfile;
+-- iteration is not in detStackedImfile;
+
+SELECT
+    det_id,
+    det_type,
+    iteration,
+    camera,
+    workdir,
+    class_id
+FROM
+    (SELECT DISTINCT
+        detRun.det_id,
+        detRun.det_type,
+        detRun.iteration,
+        detRun.workdir,
+        rawExp.camera,
+        detStackedImfile.class_id,
+        rawImfile.class_id as rawimfile_class_id
+    FROM detRun
+    JOIN detInputExp
+        ON detRun.det_id = detInputExp.det_id
+        AND detRun.iteration = detInputExp.iteration
+    JOIN rawExp
+        ON detInputExp.exp_id = rawExp.exp_id
+    JOIN rawImfile
+        ON rawExp.exp_id = rawImfile.exp_id
+    LEFT JOIN detStackedImfile
+        ON detInputExp.det_id = detStackedImfile.det_id
+        AND detInputExp.iteration = detStackedImfile.iteration
+        AND rawImfile.class_id = detStackedImfile.class_id
+    LEFT JOIN detNormalizedStatImfile
+        ON detStackedImfile.det_id = detNormalizedStatImfile.det_id
+        AND detStackedImfile.iteration = detNormalizedStatImfile.iteration
+        AND detStackedImfile.class_id = detNormalizedStatImfile.class_id
+    WHERE
+        detRun.state = 'run'
+        AND detRun.mode = 'master'
+        AND detNormalizedStatImfile.det_id IS NULL
+        AND detNormalizedStatImfile.iteration IS NULL
+        AND detNormalizedStatImfile.class_id IS NULL
+    GROUP BY
+--        rawExp.exp_id,
+        detRun.iteration,
+        detRun.det_id
+    HAVING
+        COUNT(rawImfile.class_id) = COUNT(detStackedImfile.class_id)
+        AND SUM(detStackedImfile.fault) = 0
+    ) as tonormalizedstat
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_toprocessedexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_toprocessedexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_toprocessedexp.sql	(revision 22158)
@@ -0,0 +1,61 @@
+-- select detProcessedImfile.det_id
+-- select detRun.iteration
+-- select detRun.det_type
+-- select detProcessedImfile.exp_id
+-- by:
+-- find the current iteration bassed on det_id
+-- find all exp_ids in the current det_id/iteration from detInputExp
+-- find all rawImfiles in the current exp_ids
+-- compare to detProcessedImfiles by det_id/exp_id
+-- found how many imfile there are in each class_id
+-- and:
+-- det_id is not in detProcessedExp;
+-- iteration is not in detProcessedExp;
+
+SELECT DISTINCT
+    det_id,
+    iteration,
+    det_type,
+    exp_id,
+    camera,
+    workdir,
+    exp_tag
+FROM
+    (SELECT DISTINCT
+        detRun.det_id,
+        detRun.iteration,
+        detRun.det_type,
+        detRun.workdir,
+        detProcessedImfile.exp_id,
+        detProcessedImfile.class_id,
+        rawImfile.class_id as rawimfile_class_id,
+        rawExp.camera,
+        rawExp.exp_tag
+    FROM detRun
+    JOIN detInputExp
+        USING(det_id, iteration)
+    JOIN rawExp
+        ON detInputExp.exp_id = rawExp.exp_id
+    JOIN rawImfile
+        ON rawExp.exp_id = rawImfile.exp_id
+    LEFT JOIN detProcessedImfile
+        ON detRun.det_id = detProcessedImfile.det_id
+        AND detInputExp.exp_id = detProcessedImfile.exp_id
+        AND rawImfile.class_id = detProcessedImfile.class_id
+    LEFT JOIN detProcessedExp
+        ON detProcessedImfile.det_id = detProcessedExp.det_id
+        AND detProcessedImfile.exp_id = detProcessedExp.exp_id
+    WHERE
+        detRun.state = 'run'
+        AND detRun.mode = 'master'
+        AND detProcessedExp.det_id IS NULL
+        AND detProcessedExp.exp_id IS NULL
+        AND detInputExp.include = 1
+    GROUP BY
+        rawExp.exp_id,
+        detRun.det_id
+    HAVING
+        COUNT(detProcessedImfile.class_id) = COUNT(rawImfile.class_id)
+        AND SUM(detProcessedImfile.fault) = 0
+    ) AS detProcessedExp
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_toprocessedimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_toprocessedimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_toprocessedimfile.sql	(revision 22158)
@@ -0,0 +1,24 @@
+SELECT
+    detRun.det_id,
+    detRun.det_type,
+    detRun.workdir,
+    detRun.reduction,
+    rawImfile.*,
+    rawExp.exp_tag
+FROM detRun
+JOIN detInputExp
+    USING(det_id, iteration)
+JOIN rawExp
+    ON detInputExp.exp_id = rawExp.exp_id
+JOIN rawImfile
+    ON detInputExp.exp_id = rawImfile.exp_id
+LEFT JOIN detProcessedImfile
+    ON detInputExp.det_id = detProcessedImfile.det_id
+    AND rawImfile.exp_id = detProcessedImfile.exp_id
+    AND rawImfile.class_id = detProcessedImfile.class_id
+WHERE
+    detRun.state = 'run'
+    AND detRun.mode = 'master'
+    AND detProcessedImfile.det_id IS NULL
+    AND detProcessedImfile.exp_id IS NULL
+    AND detProcessedImfile.class_id IS NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_toresidexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_toresidexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_toresidexp.sql	(revision 22158)
@@ -0,0 +1,70 @@
+-- this is used by both 'toresidexp' and 'addresidexp'
+
+-- which returns a list of exposures for which all component class ids have had
+-- residuals created.  This list includes the detrend id, iteration, exposure
+-- id, detrend type, and whether the exposure was included in the stack for
+-- this iteration.
+
+-- select detRun.det_id
+-- select detRun.iteration
+-- select detRun.det_type
+-- select detInputExp.exp_id
+-- select detInputExp.include
+-- by:
+-- find the current iteration bassed on det_id
+-- find all exp_ids in the current det_id/iteration from detInputExp
+-- compare to detInputExp.imfiles to derResidImfile by class_id
+-- and:
+-- detResidImfile.{det_id, iteration, exp_id} is not in detResidExp
+
+SELECT DISTINCT
+    det_id,
+    iteration,
+    det_type,
+    mode,
+    exp_id,
+    include,
+    camera,
+    workdir,
+    exp_tag
+FROM
+    (SELECT DISTINCT
+        detRun.det_id AS det_id,
+        detRun.iteration,
+        detRun.det_type,
+        detRun.mode,
+        detRun.workdir,
+        detInputExp.exp_id,
+        detInputExp.include,
+        rawExp.camera,
+        rawExp.exp_tag,
+        detResidImfile.class_id
+    FROM detRun
+    JOIN detInputExp
+        USING(det_id, iteration)
+    JOIN rawExp
+        ON detInputExp.exp_id = rawExp.exp_id
+    JOIN rawImfile
+        on rawExp.exp_id = rawImfile.exp_id
+    LEFT JOIN detResidImfile
+        ON detRun.det_id = detResidImfile.det_id
+        AND detRun.iteration = detResidImfile.iteration
+        AND detInputExp.exp_id = detResidImfile.exp_id
+        AND rawImfile.class_id = detResidImfile.class_id
+    LEFT JOIN detResidExp
+        ON detResidImfile.det_id = detResidExp.det_id
+        AND detResidImfile.iteration = detResidExp.iteration
+        AND detResidImfile.exp_id = detResidExp.exp_id
+    WHERE
+        detRun.state = 'run'
+        AND detResidExp.det_id IS NULL
+        AND detResidExp.iteration IS NULL
+        AND detResidExp.exp_id IS NULL
+    GROUP BY
+        detInputExp.exp_id,
+        detRun.iteration,
+        detRun.det_id
+    HAVING
+        COUNT(rawImfile.class_id) = COUNT(detResidImfile.class_id)
+        AND SUM(detResidImfile.fault = 0)
+    ) AS toresidexp
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_toresidimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_toresidimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_toresidimfile.sql	(revision 22158)
@@ -0,0 +1,82 @@
+-- which returns a list of processed imfiles (with corresponding detrend id,
+-- iteration, class id, uri, type) for which the appropriate stacked imfile has
+-- been normalised, and which have not been masked out by detResidImfileAnalysis
+
+SELECT DISTINCT
+    detRun.det_id,
+    detRun.iteration,
+    detRun.det_type,
+    detRun.mode,
+    detRun.workdir,
+    detRun.reduction,
+    detProcessedImfile.exp_id,
+    detProcessedImfile.class_id,
+    detProcessedImfile.uri,
+    detNormalizedImfile.uri AS det_uri,
+    rawExp.camera,
+    rawExp.exp_tag
+FROM detRun
+JOIN detInputExp
+    USING(det_id, iteration)
+JOIN rawExp
+    ON detInputExp.exp_id = rawExp.exp_id
+JOIN detProcessedImfile
+    ON detRun.det_id = detProcessedImfile.det_id
+    AND detInputExp.exp_id = detProcessedImfile.exp_id
+JOIN detNormalizedImfile
+    ON detRun.det_id = detNormalizedImfile.det_id
+    AND detRun.iteration = detNormalizedImfile.iteration
+    AND detProcessedImfile.class_id = detNormalizedImfile.class_id
+JOIN detNormalizedExp
+    ON detRun.det_id = detNormalizedExp.det_id
+    AND detRun.iteration = detNormalizedExp.iteration
+LEFT JOIN detResidImfile
+    ON detRun.det_id = detResidImfile.det_id
+    AND detRun.iteration = detResidImfile.iteration
+    AND detProcessedImfile.exp_id = detResidImfile.exp_id
+    AND detProcessedImfile.class_id = detResidImfile.class_id
+WHERE
+    detRun.state = 'run'
+    AND detRun.mode = 'master'
+    AND detNormalizedImfile.fault = 0
+    AND detNormalizedExp.fault = 0
+    AND detResidImfile.det_id IS NULL
+    AND detResidImfile.iteration IS NULL
+    AND detResidImfile.exp_id IS NULL
+    AND detResidImfile.class_id IS NULL
+UNION
+SELECT
+    detRun.det_id,
+    detRun.iteration,
+    detRun.det_type,
+    detRun.mode,
+    detRun.workdir,
+    detRun.reduction,
+    rawImfile.exp_id,
+    rawImfile.class_id,
+    rawImfile.uri,
+    'NULL' AS det_uri,
+    rawExp.camera,
+    rawExp.exp_tag
+FROM detRun
+JOIN detInputExp
+    USING(det_id, iteration)
+JOIN rawExp
+    ON detInputExp.exp_id = rawExp.exp_id
+JOIN rawImfile
+    ON detInputExp.exp_id = rawImfile.exp_id
+LEFT JOIN detResidImfile
+    ON detRun.det_id = detResidImfile.det_id
+    AND detRun.iteration = detResidImfile.iteration
+    AND rawImfile.exp_id = detResidImfile.exp_id
+    AND rawImfile.class_id = detResidImfile.class_id
+WHERE
+    detRun.state = 'run'
+    AND detRun.mode = 'verify'
+    -- AND detNormalizedImfile.fault = 0
+    -- AND detNormalizedExp.fault = 0
+    AND detResidImfile.det_id IS NULL
+    AND detResidImfile.iteration IS NULL
+    AND detResidImfile.exp_id IS NULL
+    AND detResidImfile.class_id IS NULL
+ORDER BY exp_id
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_tostacked.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_tostacked.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/dettool_tostacked.sql	(revision 22158)
@@ -0,0 +1,52 @@
+-- select detRun.iteration
+-- select detProcessedImfile.det_id
+-- select detProcessedImfile.class_id
+-- by:
+-- find the current iteration bassed on det_id
+-- find all exp_ids in the current det_id/iteration from detInputExp
+-- find all rawImfiles in the current exp_ids
+-- compare to detProcessedImfiles by det_id/exp_id
+-- found how many imfile there are in each class_id
+-- and:
+-- det_id is not in detStackedImfile;
+-- iteration is not in detStackedImfile;
+-- class_id is not in detStackedImfile;
+
+SELECT
+    detProcessedImfile.det_id,
+    detRun.iteration,
+    detRun.det_type,
+    detRun.workdir,
+    detRun.reduction,
+    detProcessedImfile.class_id,
+    rawExp.camera,
+    rawExp.exp_tag
+FROM detRun
+JOIN detInputExp
+    ON detRun.det_id = detInputExp.det_id
+    AND detRun.iteration = detInputExp.iteration
+JOIN rawExp
+    ON detInputExp.exp_id = rawExp.exp_id
+JOIN rawImfile
+    ON detInputExp.exp_id = rawImfile.exp_id
+LEFT JOIN detProcessedImfile
+    ON detInputExp.det_id = detProcessedImfile.det_id
+    AND detInputExp.exp_id = detProcessedImfile.exp_id
+    AND rawImfile.class_id = detProcessedImfile.class_id
+LEFT JOIN detStackedImfile
+    ON detInputExp.det_id = detStackedImfile.det_id
+    AND detInputExp.iteration = detStackedImfile.iteration
+    AND rawImfile.class_id = detStackedImfile.class_id
+WHERE
+    detRun.state = 'run'
+    AND detRun.mode = 'master'
+    AND detStackedImfile.det_id IS NULL
+    AND detStackedImfile.iteration IS NULL
+    AND detStackedImfile.class_id IS NULL
+    AND detInputExp.include = 1
+GROUP BY
+    rawImfile.class_id,
+    detRun.det_id
+HAVING
+    COUNT(detProcessedImfile.class_id) = COUNT(rawImfile.class_id)
+    AND SUM(detProcessedImfile.fault) = 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_definebyquery.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_definebyquery.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_definebyquery.sql	(revision 22158)
@@ -0,0 +1,60 @@
+-- Get list of warps that can be diffed, with any associated diff,
+-- and the best stack to use as a template
+-- Warps without an existing diff can be identified by a NULL diff_id
+SELECT
+    warpsToDiff.warp_id,
+    warpsToDiff.skycell_id,
+    warpsToDiff.tess_id,
+    warpsToDiff.filter,
+    warpsToDiff.good_frac,
+    warpsToDiff.diff_id,
+    warpsToDiff.kind,
+    current_stack_id,
+    best_stack_id
+FROM (
+    -- Get list of warps that can be diffed, with any associated diff
+    SELECT
+        warpSkyfile.warp_id,
+        warpSkyfile.skycell_id,
+        warpSkyfile.tess_id,
+        warpSkyfile.good_frac,
+        filter,
+        diffInputs.diff_id,
+        diffInputs.kind,
+        diffTemplates.stack_id AS current_stack_id
+    FROM warpSkyfile
+    JOIN warpRun USING(warp_id, tess_id)
+    JOIN fakeRun USING(fake_id, tess_id)
+    JOIN camRun USING(cam_id, tess_id)
+    JOIN chipRun USING(chip_id, tess_id)
+    JOIN rawExp USING(exp_id, tess_id)
+    -- Check if it has an associated diff
+    LEFT JOIN diffInputSkyfile AS diffInputs
+        ON diffInputs.warp_id = warpSkyfile.warp_id
+        AND diffInputs.skycell_id = warpSkyfile.skycell_id
+        AND diffInputs.tess_id = warpSkyfile.tess_id
+        AND diffInputs.template = 0 -- only join input files
+    -- Get the stack_id currently used as a template, if any
+    LEFT JOIN diffInputSkyfile AS diffTemplates
+        ON diffTemplates.diff_id = diffInputs.diff_id
+        AND diffTemplates.template != 0 -- only join template files
+    WHERE
+        warpSkyfile.fault = 0
+        AND warpSkyfile.ignored = 0
+    ) AS warpsToDiff
+-- Get best stack as a function of skycell_id, filter
+JOIN (
+    SELECT
+        MAX(stack_id) AS best_stack_id, -- most recent stack, by virtue of auto-increment
+        skycell_id,
+        tess_id,
+        filter
+    FROM stackRun
+    JOIN stackSumSkyfile USING(stack_id)
+    WHERE stackRun.state = 'stop'
+        AND stackSumSkyfile.fault = 0
+    GROUP BY
+        skycell_id,
+        tess_id,
+        filter
+    ) AS stacksForDiff USING(skycell_id, tess_id, filter)
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_donecleanup.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_donecleanup.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_donecleanup.sql	(revision 22158)
@@ -0,0 +1,5 @@
+SELECT
+    diffRun.*
+FROM diffRun
+WHERE
+    diffRun.state = 'cleaned'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_inputskyfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_inputskyfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_inputskyfile.sql	(revision 22158)
@@ -0,0 +1,73 @@
+SELECT * FROM
+    (SELECT 
+        diffRun.diff_id,
+        diffRun.skycell_id,
+        diffRun.tess_id,
+        0 as stack_id,
+        warpSkyfile.warp_id,
+        warpSkyfile.uri,
+        warpSkyfile.path_base,
+        diffInputSkyfile.template,
+        rawExp.camera
+    FROM diffRun
+    JOIN diffInputSkyfile
+        USING(diff_id)
+    JOIN warpSkyfile
+        ON  diffInputSkyfile.warp_id    = warpSkyfile.warp_id
+        AND diffInputSkyfile.skycell_id = warpSkyfile.skycell_id
+        AND diffInputSkyfile.tess_id    = warpSkyfile.tess_id
+    JOIN warpRun
+        ON diffInputSkyfile.warp_id = warpRun.warp_id
+    JOIN fakeRun
+        USING(fake_id)
+    JOIN camRun
+        USING(cam_id)
+    JOIN chipRun
+        USING(chip_id)
+    JOIN chipProcessedImfile
+        USING(chip_id)
+    JOIN rawExp
+        ON chipRun.exp_id = rawExp.exp_id
+    WHERE
+        diffRun.state = 'new'
+        AND warpRun.state = 'full'
+        AND fakeRun.state = 'full'
+        AND camRun.state = 'full'
+        AND chipRun.state = 'full'
+    UNION
+    SELECT 
+        diffRun.diff_id,
+        diffRun.skycell_id,
+        diffRun.tess_id,
+        stackSumSkyfile.stack_id,
+        0 as warp_id,
+        stackSumSkyfile.uri,
+        stackSumSkyfile.path_base,
+        diffInputSkyfile.template,
+        rawExp.camera
+    FROM diffRun
+    JOIN diffInputSkyfile
+        USING(diff_id)
+    JOIN stackSumSkyfile
+        ON  diffInputSkyfile.stack_id = stackSumSkyfile.stack_id
+    JOIN stackInputSkyfile
+        ON diffInputSkyfile.stack_id = stackInputSkyfile.stack_id
+    JOIN warpRun
+        ON stackInputSkyfile.warp_id = warpRun.warp_id
+    JOIN fakeRun
+        USING(fake_id)
+    JOIN camRun
+        USING(cam_id)
+    JOIN chipRun
+        USING(chip_id)
+    JOIN chipProcessedImfile
+        USING(chip_id)
+    JOIN rawExp
+        ON chipRun.exp_id = rawExp.exp_id
+    WHERE
+        diffRun.state = 'new'
+        AND warpRun.state = 'full'
+        AND fakeRun.state = 'full'
+        AND camRun.state = 'full'
+        AND chipRun.state = 'full'
+    ) as Foo
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_pendingcleanuprun.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_pendingcleanuprun.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_pendingcleanuprun.sql	(revision 22158)
@@ -0,0 +1,25 @@
+-- does this result in too many entries (one for each diffInputSkyfile?)
+-- all of this is just to get the camera used for the diff run
+SELECT
+    diffRun.diff_id,
+    rawExp.camera,
+    diffRun.state
+FROM diffRun
+JOIN diffInputSkyfile
+    USING(diff_id)
+JOIN warpSkyfile
+    ON  diffInputSkyfile.warp_id    = warpSkyfile.warp_id
+    AND diffInputSkyfile.skycell_id = warpSkyfile.skycell_id
+    AND diffInputSkyfile.tess_id    = warpSkyfile.tess_id
+JOIN warpRun
+    ON warpRun.warp_id = warpSkyfile.warp_id
+JOIN fakeRun
+    USING(fake_id)
+JOIN camRun
+    USING(cam_id)
+JOIN chipRun
+    USING(chip_id)
+JOIN rawExp
+    USING(exp_id)
+WHERE
+    diffRun.state = 'goto_cleaned'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_pendingcleanupskyfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_pendingcleanupskyfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_pendingcleanupskyfile.sql	(revision 22158)
@@ -0,0 +1,11 @@
+SELECT
+    diffSkyfile.*,
+    diffRun.state,
+    diffRun.workdir,
+    diffRun.dvodb,
+    diffRun.tess_id
+FROM diffRun
+JOIN diffSkyfile
+    USING(diff_id)
+WHERE
+    diffRun.state = 'goto_cleaned'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_queue.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_queue.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_queue.sql	(revision 22158)
@@ -0,0 +1,22 @@
+SELECT
+        stackRun.skycell_id,
+        stackRun.tess_id,
+        stackRun.stack_id,
+	diffInputSkyfile.template,
+        warpSkyfile.warp_id
+FROM stackSumSkyfile
+JOIN stackRun
+        USING(stack_id)
+JOIN stackInputSkyfile
+        USING(stack_id)
+JOIN warpSkyfile
+        USING(warp_id,tess_id,skycell_id)
+LEFT JOIN diffInputSkyfile
+        ON diffInputSkyfile.stack_id = stackRun.stack_id
+        OR diffInputSkyfile.warp_id = warpSkyfile.warp_id
+WHERE
+        stackSumSkyfile.fault = 0
+        AND warpSkyfile.fault = 0
+        AND stackRun.state = 'full'
+        AND diffInputSkyfile.stack_id IS NULL
+        AND diffInputSkyfile.warp_id IS NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_revertdiffskyfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_revertdiffskyfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_revertdiffskyfile.sql	(revision 22158)
@@ -0,0 +1,3 @@
+DELETE FROM diffSkyfile
+WHERE
+    fault != 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_skyfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_skyfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_skyfile.sql	(revision 22158)
@@ -0,0 +1,29 @@
+SELECT
+    diffRun.skycell_id,
+    diffRun.tess_id,
+    diffRun.state,
+    diffSkyfile.*,
+    rawExp.exp_id,
+    rawExp.camera
+FROM diffRun
+JOIN diffSkyfile
+    USING(diff_id)
+-- WS: my new stuff begins here
+JOIN diffInputSkyfile
+    ON diffInputSkyfile.diff_id = diffRun.diff_id
+    AND diffInputSkyfile.template = 0
+JOIN warpRun
+    ON diffInputSkyfile.warp_id = warpRun.warp_id
+JOIN fakeRun
+    ON warpRun.fake_id = fakeRun.fake_id
+JOIN camRun
+    ON camRun.cam_id = fakeRun.cam_id
+JOIN chipRun
+    ON camRun.chip_id = chipRun.chip_id
+JOIN rawExp
+    ON chipRun.exp_id = rawExp.exp_id
+-- WS: my new stuff ends here
+    WHERE
+    -- bogus test to allow appending conditionals
+    -- XXX EAM : this is not needed if we modify the difftool.c code : fix
+    diffRun.diff_id IS NOT NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_todiffskyfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_todiffskyfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/difftool_todiffskyfile.sql	(revision 22158)
@@ -0,0 +1,32 @@
+SELECT DISTINCT
+    diffRun.diff_id,
+    diffRun.workdir,
+    diffRun.skycell_id,
+    diffRun.tess_id,
+    rawExp.camera
+FROM diffRun
+JOIN diffInputSkyfile
+    USING(diff_id)
+JOIN warpSkyfile
+    ON  diffInputSkyfile.warp_id    = warpSkyfile.warp_id
+    AND diffInputSkyfile.skycell_id = warpSkyfile.skycell_id
+    AND diffInputSkyfile.tess_id    = warpSkyfile.tess_id
+JOIN warpRun
+    ON warpRun.warp_id = warpSkyfile.warp_id
+JOIN fakeRun
+    USING(fake_id)
+JOIN camRun
+    USING(cam_id)
+JOIN chipRun
+    USING(chip_id)
+JOIN rawExp
+    USING(exp_id)
+LEFT JOIN diffSkyfile
+    ON diffInputSkyfile.diff_id = diffSkyfile.diff_id
+WHERE
+  diffRun.state = 'new'
+  AND warpRun.state = 'full'
+  AND fakeRun.state = 'full'
+  AND camRun.state = 'full'
+  AND chipRun.state = 'full'
+  AND diffSkyfile.diff_id IS NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_completely_processed_exp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_completely_processed_exp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_completely_processed_exp.sql	(revision 22158)
@@ -0,0 +1,40 @@
+-- the output of this query must match the format of fakeRun row
+SELECT DISTINCT
+    fake_id,
+    cam_id,
+    state,
+    workdir,
+    label,
+    reduction,
+    expgroup,
+    dvodb,
+    tess_id,
+    end_stage,
+    epoch
+FROM
+    (SELECT 
+        fakeRun.*,
+        rawImfile.class_id as rawimfile_class_id,
+        fakeProcessedImfile.class_id
+    FROM fakeRun
+    JOIN camRun
+        USING(cam_id)
+    JOIN chipRun
+        USING(chip_id)
+    JOIN rawExp
+        USING(exp_id)
+    JOIN rawImfile
+        USING(exp_id)
+    LEFT JOIN fakeProcessedImfile
+        ON fakeRun.fake_id = fakeProcessedImfile.fake_id
+        AND rawImfile.exp_id = fakeProcessedImfile.exp_id
+        AND rawImfile.class_id = fakeProcessedImfile.class_id
+    WHERE
+        fakeRun.state = 'new'
+    GROUP BY
+        fakeRun.fake_id,
+        rawExp.exp_id
+    HAVING
+        COUNT(rawImfile.class_id) = COUNT(fakeProcessedImfile.class_id)
+        AND SUM(fakeProcessedImfile.fault) = 0
+    ) as Foo
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_donecleanup.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_donecleanup.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_donecleanup.sql	(revision 22158)
@@ -0,0 +1,5 @@
+SELECT
+    fakeRun.*
+FROM fakeRun
+WHERE
+    fakeRun.state = 'cleaned'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_find_camrun.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_find_camrun.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_find_camrun.sql	(revision 22158)
@@ -0,0 +1,36 @@
+SELECT
+    *
+FROM
+    (SELECT DISTINCT
+        camRun.cam_id,
+        chipRun.*,
+        rawExp.camera,
+        rawExp.telescope,
+        rawExp.dateobs,
+        rawExp.exp_tag,
+        rawExp.exp_type,
+        rawExp.filelevel,
+        rawExp.filter,
+        rawExp.airmass,
+        rawExp.ra,
+        rawExp.decl,
+        rawExp.exp_time,
+        rawExp.sat_pixel_frac,
+        rawExp.bg,
+        rawExp.bg_stdev,
+        rawExp.bg_mean_stdev,
+        rawExp.alt,
+        rawExp.az,
+        rawExp.ccd_temp,
+        rawExp.posang,
+        rawExp.object,
+        rawExp.solang
+    FROM camRun
+    JOIN chipRun
+        using(chip_id)
+    JOIN rawExp
+        using(exp_id)
+    WHERE
+        camRun.state = 'full'
+        AND chipRun.state = 'full'
+) as Foo
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_find_pendingexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_find_pendingexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_find_pendingexp.sql	(revision 22158)
@@ -0,0 +1,34 @@
+-- this query is used by both camtool -pendingexp & camtool -addprocessedexp it
+-- does a little more work then is necessary for -addprocessed but it seems
+-- "cleaner" to use the same query for both cases
+SELECT * FROM
+    (SELECT
+        fakeRun.*,
+        rawExp.exp_tag,
+        rawExp.exp_id,
+        rawExp.exp_name,
+        rawExp.camera,
+        rawExp.telescope,
+        rawExp.filelevel
+    FROM fakeRun
+    JOIN camRun
+        USING(cam_id)
+    JOIN chipRun
+        USING(chip_id)
+    JOIN chipProcessedImfile
+        USING(chip_id)
+    JOIN rawExp
+        ON chipRun.exp_id = rawExp.exp_id
+    LEFT JOIN fakeProcessedImfile
+        USING(fake_id)
+    LEFT JOIN fakeMask
+        ON fakeRun.label = fakeMask.label
+    WHERE
+        fakeRun.state = 'new'
+        AND camRun.state = 'full'
+        AND chipRun.state = 'full'
+        AND fakeMask.label IS NULL
+        AND fakeProcessedImfile.fake_id IS NOT NULL
+    GROUP BY
+        fakeRun.fake_id
+    ) as Foo
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_pendingcleanupimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_pendingcleanupimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_pendingcleanupimfile.sql	(revision 22158)
@@ -0,0 +1,15 @@
+SELECT
+    fakeProcessedImfile.*,
+    fakeRun.state,
+    fakeRun.workdir,
+    fakeRun.label,
+    fakeRun.reduction,
+    fakeRun.expgroup,
+    fakeRun.dvodb,
+    fakeRun.tess_id,
+    fakeRun.end_stage
+FROM fakeRun
+JOIN fakeProcessedImfile
+    USING(fake_id)
+WHERE
+    fakeRun.state = 'goto_cleaned'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_pendingcleanuprun.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_pendingcleanuprun.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_pendingcleanuprun.sql	(revision 22158)
@@ -0,0 +1,13 @@
+SELECT
+    fakeRun.fake_id,
+    rawExp.camera,
+    fakeRun.state
+FROM fakeRun
+JOIN camRun
+USING (cam_id)
+JOIN chipRun
+USING (chip_id)
+JOIN rawExp 
+USING (exp_id)
+WHERE
+    fakeRun.state = 'goto_cleaned'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_pendingimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_pendingimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_pendingimfile.sql	(revision 22158)
@@ -0,0 +1,46 @@
+SELECT DISTINCT * FROM (
+    -- the subselect is so where criteria can be specified without knowing
+    -- which table the field came from
+    SELECT
+        fakeRun.*,
+        chipProcessedImfile.exp_id,
+        chipProcessedImfile.class_id,
+        chipProcessedImfile.uri,
+        chipProcessedImfile.bg,
+        chipProcessedImfile.bg_stdev,
+        chipProcessedImfile.bg_mean_stdev,
+        chipProcessedImfile.fringe_0,
+        chipProcessedImfile.fringe_1,
+        chipProcessedImfile.fringe_2,
+        chipProcessedImfile.ap_resid,
+        chipProcessedImfile.ap_resid_stdev,
+        chipProcessedImfile.sigma_ra,
+        chipProcessedImfile.sigma_dec,
+        chipProcessedImfile.n_stars,
+        chipProcessedImfile.n_extended,
+        chipProcessedImfile.n_cr,
+        chipProcessedImfile.n_astrom,
+        chipProcessedImfile.path_base as chip_path_base,
+        camProcessedExp.path_base as cam_path_base,
+        rawExp.exp_name,
+        rawExp.exp_tag,
+        rawExp.camera,
+        rawExp.telescope,
+        rawExp.filelevel
+    FROM fakeRun
+    JOIN camRun USING(cam_id)
+    JOIN camProcessedExp USING(cam_id)
+    JOIN chipRun USING(chip_id)
+    JOIN chipProcessedImfile USING(chip_id)
+    JOIN rawExp
+        ON chipProcessedImfile.exp_id = rawExp.exp_id
+    LEFT JOIN fakeProcessedImfile
+        ON fakeRun.fake_id = fakeProcessedImfile.fake_id
+        AND chipProcessedImfile.class_id = fakeProcessedImfile.class_id
+    LEFT JOIN fakeMask
+        ON fakeRun.label = fakeMask.label
+    WHERE
+        fakeProcessedImfile.fake_id IS NULL
+        AND fakeProcessedImfile.class_id IS NULL
+        AND fakeMask.label IS NULL
+    ) as fakePendingImfile
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_processedimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_processedimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_processedimfile.sql	(revision 22158)
@@ -0,0 +1,17 @@
+SELECT DISTINCT
+    fakeProcessedImfile.*,
+    rawExp.exp_tag,
+    rawExp.exp_name,
+    rawExp.camera,
+    rawExp.telescope,
+    rawExp.filelevel
+FROM fakeRun
+JOIN fakeProcessedImfile
+    USING(fake_id)
+JOIN rawExp
+    ON fakeProcessedImfile.exp_id = rawExp.exp_id
+WHERE
+-- bogus test; just here so there there is a 'WHERE' stmt to append
+-- conditionals too
+    fakeProcessedImfile.exp_id is NOT NULL
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_queue_cam_id.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_queue_cam_id.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_queue_cam_id.sql	(revision 22158)
@@ -0,0 +1,17 @@
+INSERT INTO fakeRun
+    SElECT
+        0,              -- fake_id
+        cam_id,         -- cam_id
+        '%s',           -- state
+        '%s',           -- workdir
+        '%s',           -- label
+        '%s',           -- reduction
+        '%s',           -- expgroup
+        '%s',           -- dvodb 
+        '%s',           -- tess_id
+        '%s',           -- end_stage
+        NULL            -- epoch
+    FROM camRun
+    WHERE
+        camRun.state = 'full'
+        AND camRun.cam_id = %lld
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_revertprocessedimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_revertprocessedimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_revertprocessedimfile.sql	(revision 22158)
@@ -0,0 +1,8 @@
+DELETE FROM fakeProcessedImfile
+USING fakeProcessedImfile, fakeRun, camRun, chipRun, rawExp
+WHERE
+    fakeProcessedImfile.fake_id = fakeRun.fake_id
+    AND fakeRun.cam_id = camRun.cam_id
+    AND camRun.chip_id = chipRun.chip_id
+    AND chipRun.exp_id = rawExp.exp_id
+    AND fakeProcessedImfile.fault != 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_unmasked.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_unmasked.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/faketool_unmasked.sql	(revision 22158)
@@ -0,0 +1,11 @@
+SELECT
+ *
+FROM
+ (SELECT 
+     fakeRun.label, 
+     count(fakeRun.fake_id) as n_fakeruns
+  FROM fakeRun 
+  LEFT JOIN fakeMask 
+  USING (label) 
+  WHERE fakeMask.label IS NULL 
+  GROUP BY fakeRun.label) as fakeUnmask
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/flatcorr_completely_processed_chiprun.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/flatcorr_completely_processed_chiprun.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/flatcorr_completely_processed_chiprun.sql	(revision 22158)
@@ -0,0 +1,36 @@
+INSERT INTO chipRunDone
+SELECT
+    chip_id,
+    exp_id
+FROM (SELECT DISTINCT
+        chip_id,
+        exp_id,
+        state,
+        workdir,
+        workdir_state,
+        label,
+        reduction,
+        expgroup,
+        dvodb
+    FROM
+        (SELECT 
+            chipRun.*,
+            rawImfile.class_id as rawimfile_class_id,
+            chipProcessedImfile.class_id
+        FROM chipRun
+        JOIN rawImfile
+            USING(exp_id)
+        LEFT JOIN chipProcessedImfile
+            ON chipRun.chip_id = chipProcessedImfile.chip_id
+            AND rawImfile.exp_id = chipProcessedImfile.exp_id
+            AND rawImfile.class_id = chipProcessedImfile.class_id
+        WHERE
+            chipRun.state = 'full'
+        GROUP BY
+            chipRun.chip_id,
+            chipRun.exp_id
+        HAVING
+            COUNT(rawImfile.class_id) = COUNT(chipProcessedImfile.class_id)
+            AND SUM(chipProcessedImfile.fault) = 0
+        ) as Foo
+    ) as Bar
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/flatcorr_create_tmp_chiprundone.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/flatcorr_create_tmp_chiprundone.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/flatcorr_create_tmp_chiprundone.sql	(revision 22158)
@@ -0,0 +1,3 @@
+CREATE TEMPORARY TABLE chipRunDone
+(chip_id BIGINT, exp_id VARCHAR(64), PRIMARY KEY(chip_id)) ENGINE=MEMORY
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/flatcorr_find_completed_floatcorruns.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/flatcorr_find_completed_floatcorruns.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/flatcorr_find_completed_floatcorruns.sql	(revision 22158)
@@ -0,0 +1,13 @@
+SELECT DISTINCT
+    flatcorrRun.*
+FROM flatcorrRun
+JOIN flatcorrExp
+    USING(corr_id)
+JOIN chipRunDone
+    USING(chip_id)
+WHERE
+    flatcorrRun.state != "stop"
+GROUP BY
+    corr_id, chip_id
+HAVING
+    COUNT(flatcorrExp.chip_id) = COUNT(chipRunDone.chip_id)
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/flatcorr_find_processedimfiles.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/flatcorr_find_processedimfiles.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/flatcorr_find_processedimfiles.sql	(revision 22158)
@@ -0,0 +1,14 @@
+SELECT
+    corr_id,
+    chipProcessedImfile.*
+FROM flatcorrRun
+JOIN flatcorrExp
+    USING(corr_id)
+JOIN chipRun
+    USING(chip_id)
+JOIN chipProcessedImfile
+    USING(chip_id)
+WHERE
+    flatcorrRun.state = 'run'
+    AND chipRun.state = 'new'
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/flatcorr_pending.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/flatcorr_pending.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/flatcorr_pending.sql	(revision 22158)
@@ -0,0 +1,24 @@
+SELECT 
+    *
+FROM
+flatcorrRun
+JOIN flatcorrExp
+    USING(corr_id)
+JOIN chipRun
+    USING(chip_id)
+JOIN rawImfile
+    USING(exp_id)
+LEFT JOIN chipProcessedImfile
+    ON chipRun.chip_id = chipProcessedImfile.chip_id
+    AND rawImfile.exp_id = chipProcessedImfile.exp_id
+    AND rawImfile.class_id = chipProcessedImfile.class_id
+WHERE
+    flatcorrRun.state = 'run'
+    AND chipRun.state = 'full'
+GROUP BY
+    chipRun.chip_id,
+    chipRun.exp_id
+HAVING
+    COUNT(rawImfile.class_id) = COUNT(chipProcessedImfile.class_id)
+    AND SUM(chipProcessedImfile.fault) = 0
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_addmask.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_addmask.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_addmask.sql	(revision 22158)
@@ -0,0 +1,6 @@
+UPDATE
+    magicRun
+SET
+    state = 'stop'
+WHERE
+    state != 'stop'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_create_tmp_warpcomplete.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_create_tmp_warpcomplete.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_create_tmp_warpcomplete.sql	(revision 22158)
@@ -0,0 +1,3 @@
+CREATE TEMPORARY TABLE warpComplete
+ (warp_id BIGINT, skycell_id VARCHAR(64), tess_id VARCHAR(64),
+ PRIMARY KEY(warp_id, skycell_id, tess_id)) ENGINE=MEMORY;
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery.sql	(revision 22158)
@@ -0,0 +1,109 @@
+-- This is a sequence of SQL for searching for exposures on which
+-- magic may be run, and populating the run.  This file is provided as
+-- a convenience, and is intended solely for playing around and
+-- testing.  Updates here will not affect the operation of magictool.
+-- Conversely, it may not be up to date with the actual queries used
+-- by magictool.
+
+--------------------------------------------------------------------
+-- NOTE: THIS FILE IS NOT USED BY magictool
+--------------------------------------------------------------------
+
+-- magictool_definebyquery_temp_create.sql
+CREATE TEMPORARY TABLE magicBestDiffs (
+exp_id BIGINT,
+skycell_id VARCHAR(64),
+tess_id VARCHAR(64),
+diff_id BIGINT,
+PRIMARY KEY(exp_id, skycell_id, tess_id)
+) ENGINE=MEMORY;
+
+
+-- magictool_definebyquery_temp_insert.sql
+-- List of best differences for each exposure
+INSERT INTO magicBestDiffs
+SELECT
+    exp_id,
+    warpSkyfile.skycell_id,
+    warpSkyfile.tess_id,
+    MAX(diffSkyfile.diff_id) AS diff_id
+FROM rawExp
+JOIN chipRun USING(exp_id, tess_id)
+JOIN camRun USING(chip_id, tess_id)
+JOIN fakeRun USING(cam_id, tess_id)
+JOIN warpRun USING(fake_id, tess_id)
+JOIN warpSkyCellMap USING(warp_id, tess_id)
+JOIN warpSkyfile USING(warp_id, skycell_id, tess_id)
+JOIN diffInputSkyfile
+    ON diffInputSkyfile.warp_id = warpSkyfile.warp_id
+    AND diffInputSkyfile.skycell_id = warpSkyfile.skycell_id
+    AND diffInputSkyfile.tess_id = warpSkyfile.tess_id
+    AND diffInputSkyfile.template = 0 -- selecting inputs only
+JOIN diffSkyfile USING(diff_id)
+WHERE
+    diffSkyfile.fault = 0
+-----    AND warpSkyfile.good_frac >= 0.5
+-- magictool_definebyquery_temp_insert_groupby.sql
+GROUP BY
+    exp_id,
+    warpSkyfile.skycell_id
+;
+
+
+-- magictool_definebyquery_select_part1.sql
+-- This is part 1 of 2 of a query to get a list of exposures on which magic may be performed
+-- After this follows magictool_definebyquery_select_part2.sql
+SELECT
+    exp_id,
+    filter,
+    num_todo,
+    num_done
+FROM (
+    -- Number of skycells as a function of exposure
+    SELECT
+        exp_id,
+        filter,
+        COUNT(skycell_id) AS num_todo
+    FROM rawExp
+    JOIN chipRun USING(exp_id, tess_id)
+    JOIN camRun USING(chip_id, tess_id)
+    JOIN fakeRun USING(cam_id, tess_id)
+    JOIN warpRun USING(fake_id, tess_id)
+    JOIN warpSkyCellMap USING(warp_id, tess_id)
+    JOIN warpSkyfile USING(warp_id, skycell_id, tess_id)
+    WHERE
+        warpSkyfile.ignored = 0
+        AND warpRun.state = 'stop'
+    -- INSERT HERE any additional restrictions (e.g., exp_id, warpSkyfile.good_frac)
+-----        AND warpSkyfile.good_frac > 0.5
+-- INSERT HERE magictool_definebyquery_select_part2.sql
+-- magictool_definebyquery_select_part2.sql
+-- This is part 2 of 2 of a query to get a list of exposures on which magic may be performed
+-- This follows magictool_definebyquery_select_part1.sql
+    GROUP BY
+        exp_id
+    ) AS magicSkycellNums
+JOIN (
+    -- Number of completed diffs for an exposure
+    SELECT
+        exp_id,
+        COUNT(diff_id) AS num_done
+    FROM magicBestDiffs
+    GROUP BY
+        exp_id
+    ) AS magicDiffNums USING(exp_id)
+LEFT JOIN magicRun USING(exp_id)
+WHERE
+    num_done = num_todo
+    AND magicRun.magic_id IS NULL
+;
+
+-- magictool_definebyquery_insert.sql
+-- Insert the best list of diffs as magic inputs
+INSERT INTO magicInputSkyfile
+SELECT
+    @MAGIC_ID@, -- Update this with the appropriate magic_id
+    diff_id,
+    CONCAT(tess_id, '.', skycell_id) AS node
+FROM magicBestDiffs
+;
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_insert.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_insert.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_insert.sql	(revision 22158)
@@ -0,0 +1,9 @@
+-- Insert the best list of diffs as magic inputs
+INSERT INTO magicInputSkyfile
+SELECT
+    @MAGIC_ID@, -- Update this with the appropriate magic_id
+    diff_id,
+    skycell_id
+FROM magicBestDiffs
+WHERE
+    exp_id = @EXP_ID@ -- Update this with the appropriate exp_id
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_select_part1.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_select_part1.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_select_part1.sql	(revision 22158)
@@ -0,0 +1,25 @@
+-- This is part 1 of 2 of a query to get a list of exposures on which magic may be performed
+-- After this follows magictool_definebyquery_select_part2.sql
+SELECT
+    exp_id,
+    filter,
+    num_todo,
+    num_done
+FROM (
+    -- Number of skycells as a function of exposure
+    SELECT
+        exp_id,
+        filter,
+        COUNT(skycell_id) AS num_todo
+    FROM rawExp
+    JOIN chipRun USING(exp_id, tess_id)
+    JOIN camRun USING(chip_id, tess_id)
+    JOIN fakeRun USING(cam_id, tess_id)
+    JOIN warpRun USING(fake_id, tess_id)
+    JOIN warpSkyCellMap USING(warp_id, tess_id)
+    JOIN warpSkyfile USING(warp_id, skycell_id, tess_id)
+    WHERE
+        warpSkyfile.ignored = 0
+        AND warpRun.state = 'stop'
+    -- INSERT HERE any additional restrictions (e.g., exp_id, warpSkyfile.good_frac)
+-- INSERT HERE magictool_definebyquery_select_part2.sql
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_select_part2.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_select_part2.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_select_part2.sql	(revision 22158)
@@ -0,0 +1,18 @@
+-- This is part 2 of 2 of a query to get a list of exposures on which magic may be performed
+-- This follows magictool_definebyquery_select_part1.sql
+    GROUP BY
+        exp_id
+    ) AS magicSkycellNums
+JOIN (
+    -- Number of completed diffs for an exposure
+    SELECT
+        exp_id,
+        COUNT(diff_id) AS num_done
+    FROM magicBestDiffs
+    GROUP BY
+        exp_id
+    ) AS magicDiffNums USING(exp_id)
+LEFT JOIN magicRun USING(exp_id)
+WHERE
+    num_done = num_todo
+    AND magicRun.magic_id IS NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_select_test.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_select_test.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_select_test.sql	(revision 22158)
@@ -0,0 +1,46 @@
+-- This is the combination of the two parts of the query to get a list
+-- of exposures to be magic-ed
+
+--------------------------------------------------------------------------------
+-- THIS FILE IS INTENDED FOR TESTING ONLY!  IT IS NOT USED BY stacktool.
+-- CHANGES SHOULD BE MADE TO magictool_definebyquery_select_part1.sql
+-- AND magictool_definebyquery_select_part2.sql
+--------------------------------------------------------------------------------
+
+-- magictool_definebyquery_select_part1.sql
+SELECT
+    *
+FROM (
+    -- Number of skycells as a function of exposure
+    SELECT
+        exp_id,
+        filter,
+        COUNT(skycell_id) AS num_todo
+    FROM rawExp
+    JOIN chipRun USING(exp_id, tess_id)
+    JOIN camRun USING(chip_id, tess_id)
+    JOIN fakeRun USING(cam_id, tess_id)
+    JOIN warpRun USING(fake_id, tess_id)
+    JOIN warpSkyCellMap USING(warp_id, tess_id)
+    JOIN warpSkyfile USING(warp_id, skycell_id, tess_id)
+    WHERE
+        warpSkyfile.ignored = 0
+        AND warpRun.state = 'stop'
+    -- INSERT HERE any additional restrictions (e.g., exp_id, warpSkyfile.good_frac)
+-- magictool_definebyquery_select_part2.sql
+    GROUP BY
+        exp_id
+    ) AS magicSkycellNums
+JOIN (
+    -- Number of completed diffs for an exposure
+    SELECT
+        exp_id,
+        COUNT(diff_id) AS num_done
+    FROM magicBestDiffs
+    GROUP BY
+        exp_id
+    ) AS magicDiffNums USING(exp_id)
+LEFT JOIN magicRun USING(exp_id)
+WHERE
+    num_done = num_todo
+    AND magicRun.magic_id IS NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_temp_create.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_temp_create.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_temp_create.sql	(revision 22158)
@@ -0,0 +1,7 @@
+CREATE TEMPORARY TABLE magicBestDiffs (
+exp_id BIGINT,
+skycell_id VARCHAR(64),
+tess_id VARCHAR(64),
+diff_id BIGINT,
+PRIMARY KEY(exp_id, skycell_id, tess_id)
+) ENGINE=MEMORY;
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_temp_insert.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_temp_insert.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_temp_insert.sql	(revision 22158)
@@ -0,0 +1,22 @@
+-- List of best differences for each exposure
+INSERT INTO magicBestDiffs
+SELECT
+    exp_id,
+    warpSkyfile.skycell_id,
+    warpSkyfile.tess_id,
+    MAX(diffSkyfile.diff_id) AS diff_id
+FROM rawExp
+JOIN chipRun USING(exp_id, tess_id)
+JOIN camRun USING(chip_id, tess_id)
+JOIN fakeRun USING(cam_id, tess_id)
+JOIN warpRun USING(fake_id, tess_id)
+JOIN warpSkyCellMap USING(warp_id, tess_id)
+JOIN warpSkyfile USING(warp_id, skycell_id, tess_id)
+JOIN diffInputSkyfile
+    ON diffInputSkyfile.warp_id = warpSkyfile.warp_id
+    AND diffInputSkyfile.skycell_id = warpSkyfile.skycell_id
+    AND diffInputSkyfile.tess_id = warpSkyfile.tess_id
+    AND diffInputSkyfile.template = 0 -- selecting inputs only
+JOIN diffSkyfile USING(diff_id)
+WHERE
+    diffSkyfile.fault = 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_temp_insert_groupby.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_temp_insert_groupby.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_definebyquery_temp_insert_groupby.sql	(revision 22158)
@@ -0,0 +1,3 @@
+GROUP BY
+    exp_id,
+    warpSkyfile.skycell_id
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_inputs.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_inputs.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_inputs.sql	(revision 22158)
@@ -0,0 +1,33 @@
+SELECT *
+FROM (
+-- Single skycells
+SELECT
+    magicRun.magic_id,
+    magicRun.state,
+    magicInputSkyfile.node,
+    diffSkyfile.uri,
+    diffSkyfile.path_base,
+    diffSkyfile.fault
+FROM magicInputSkyfile
+JOIN diffSkyfile
+    USING(diff_id)
+JOIN magicRun
+    USING(magic_id)
+UNION
+-- Merged skycells
+SELECT
+    magicRun.magic_id,
+    magicRun.state,
+    magicTree.node,
+    magicNodeResult.uri,
+    NULL, -- magicNodeResult doesn't have a path_base
+    magicNodeResult.fault
+FROM magicTree
+JOIN magicRun
+    USING(magic_id)
+JOIN magicNodeResult
+    ON magicTree.magic_id = magicNodeResult.magic_id
+    AND magicTree.dep = magicNodeResult.node
+) as Foo
+WHERE
+    fault = 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_inputskyfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_inputskyfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_inputskyfile.sql	(revision 22158)
@@ -0,0 +1,7 @@
+SELECT
+    magicInputSkyfile.*
+FROM magicInputSkyfile
+JOIN magicRun
+    USING(magic_id)
+WHERE
+    magicRun.state = 'run'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_mask.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_mask.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_mask.sql	(revision 22158)
@@ -0,0 +1,8 @@
+SELECT
+    magicMask.*
+FROM magicMask
+JOIN magicRun
+    USING(magic_id)
+WHERE
+    magicRun.state = 'stop'
+    AND magicMask.fault = 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_tomask.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_tomask.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_tomask.sql	(revision 22158)
@@ -0,0 +1,18 @@
+SELECT
+    magic_id,
+    exp_id,
+    camera,
+    magicRun.workdir,
+    uri
+FROM magicRun
+JOIN rawExp USING(exp_id)
+JOIN magicTree USING(magic_id)
+LEFT JOIN magicNodeResult USING(magic_id, node)
+WHERE
+    magicRun.state = 'run'
+    AND magicNodeResult.node = 'root'
+    AND magicNodeResult.fault = 0
+GROUP BY
+    magic_id
+HAVING
+    COUNT(magicTree.node) = COUNT(magicNodeResult.node)
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_toprocess_inputs.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_toprocess_inputs.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_toprocess_inputs.sql	(revision 22158)
@@ -0,0 +1,19 @@
+SELECT
+    magicTree.*,
+    rawExp.camera,
+    diffSkyfile.path_base,
+    -- convert magic_id into a boolean value (1 or 0)
+    -- note that the type stays a 64 bit int
+    magicNodeResult.magic_id IS TRUE as done
+FROM magicTree
+JOIN magicRun USING(magic_id)
+JOIN magicInputSkyfile USING(magic_id, node)
+JOIN diffSkyfile USING(diff_id)
+JOIN rawExp USING(exp_id)
+LEFT JOIN magicNodeResult
+    ON magicTree.magic_id = magicNodeResult.magic_id
+    AND magicTree.node = magicNodeResult.node
+WHERE
+    magicRun.state = 'run'
+    AND magicNodeResult.magic_id IS NULL
+    AND magicNodeResult.node IS NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_toprocess_tree.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_toprocess_tree.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_toprocess_tree.sql	(revision 22158)
@@ -0,0 +1,17 @@
+SELECT
+    magicTree.*,
+    exp_id,
+    camera,
+    magicRun.workdir,
+    -- convert magic_id into a boolean value (1 or 0)
+    -- note that the type stays a 64 bit int
+    magicNodeResult.magic_id IS TRUE as done,
+    magicNodeResult.fault IS TRUE as bad
+FROM magicTree
+JOIN magicRun USING(magic_id)
+JOIN rawExp USING(exp_id)
+LEFT JOIN magicNodeResult
+    ON magicTree.magic_id = magicNodeResult.magic_id
+    AND magicTree.node = magicNodeResult.node
+WHERE
+    magicRun.state = 'run'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_toskyfilemask.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_toskyfilemask.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_toskyfilemask.sql	(revision 22158)
@@ -0,0 +1,10 @@
+SELECT
+    magicMask.*
+FROM magicRun
+JOIN magicMask
+    USING(magic_id)
+LEFT JOIN magicSkyfileMask
+    USING(magic_id)
+WHERE
+    magicRun.state = 'run'
+    AND magicSkyfileMask.magic_id IS NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_totree.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_totree.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/magictool_totree.sql	(revision 22158)
@@ -0,0 +1,16 @@
+SELECT
+    magic_id,
+    exp_id,
+    camera,
+    workdir,
+    ra,
+    decl,
+    tess_id
+FROM magicRun
+JOIN rawExp USING(exp_id)
+LEFT JOIN magicTree
+    USING(magic_id)
+WHERE
+    magicRun.state = 'run'
+    AND magicTree.node IS NULL
+    AND magicRun.fault = 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/pstamptool_addjob_otherjob.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/pstamptool_addjob_otherjob.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/pstamptool_addjob_otherjob.sql	(revision 22158)
@@ -0,0 +1,3 @@
+INSERT INTO pstampJob
+ (req_id, rownum, state, jobType, uri, outputBase, fault)
+ VALUES( %s, '%s', '%s', '%s', '%s', '%s', %s)
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/pstamptool_addjob_stampjob.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/pstamptool_addjob_stampjob.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/pstamptool_addjob_stampjob.sql	(revision 22158)
@@ -0,0 +1,3 @@
+INSERT INTO pstampJob
+ (req_id, rownum, state, jobType, uri, outputBase, fault, args)
+ VALUES( %s, '%s', '%s', '%s', '%s', '%s', %s, '%s')
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/pstamptool_datastore.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/pstamptool_datastore.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/pstamptool_datastore.sql	(revision 22158)
@@ -0,0 +1,1 @@
+SELECT * FROM pstampDataStore
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/pstamptool_pendingjob.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/pstamptool_pendingjob.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/pstamptool_pendingjob.sql	(revision 22158)
@@ -0,0 +1,4 @@
+SELECT
+ *
+ FROM pstampJob
+ WHERE state = 'run'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/pstamptool_pendingreq.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/pstamptool_pendingreq.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/pstamptool_pendingreq.sql	(revision 22158)
@@ -0,0 +1,4 @@
+SELECT
+ *
+ FROM pstampRequest
+ WHERE state = 'new'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/pxadmin_create_tables.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/pxadmin_create_tables.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/pxadmin_create_tables.sql	(revision 22158)
@@ -0,0 +1,1022 @@
+CREATE TABLE pzDataStore (
+    camera VARCHAR(64),
+    telescope VARCHAR(64),
+    uri VARCHAR(255),
+    epoch TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    PRIMARY KEY(camera, telescope)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE summitExp (
+    exp_name VARCHAR(64),
+    camera VARCHAR(64),
+    telescope VARCHAR(64),
+    dateobs DATETIME,
+    exp_type VARCHAR(64),
+    uri VARCHAR(255),
+    imfiles INT,
+    fault SMALLINT NOT NULL,
+    epoch TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    PRIMARY KEY(exp_name, camera, telescope),
+    KEY(fault))
+ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE summitImfile (
+    exp_name VARCHAR(64),
+    camera VARCHAR(64),
+    telescope VARCHAR(64),
+    file_id VARCHAR(64),
+    bytes INT,
+    md5sum VARCHAR(32),
+    class VARCHAR(64),
+    class_id VARCHAR(64),
+    uri VARCHAR(255),
+    epoch TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    PRIMARY KEY(exp_name, camera, telescope, class, class_id),
+    KEY(file_id),
+    FOREIGN KEY (exp_name, camera, telescope)
+        REFERENCES  summitExp(exp_name, camera, telescope))
+ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE pzDownloadExp (
+    exp_name VARCHAR(64),
+    camera VARCHAR(64),
+    telescope VARCHAR(64),
+    state VARCHAR(64),
+    epoch TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    PRIMARY KEY(exp_name, camera, telescope),
+    KEY(state),
+    FOREIGN KEY (exp_name, camera, telescope)
+        REFERENCES  summitExp(exp_name, camera, telescope))
+ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE pzDownloadImfile (
+    exp_name VARCHAR(64),
+    camera VARCHAR(64),
+    telescope VARCHAR(64),
+    class VARCHAR(64),
+    class_id VARCHAR(64),
+    uri VARCHAR(255),
+    fault SMALLINT NOT NULL,
+    epoch TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    PRIMARY KEY(exp_name, camera, telescope, class, class_id),
+    KEY(fault),
+    FOREIGN KEY (exp_name, camera, telescope)
+        REFERENCES  pzDownloadExp(exp_name, camera, telescope),
+    FOREIGN KEY (exp_name, camera, telescope, class, class_id)
+        REFERENCES  summitImfile(exp_name, camera, telescope, class, class_id)) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE newExp (
+    exp_id BIGINT AUTO_INCREMENT,
+    tmp_exp_name VARCHAR(64),
+    tmp_camera VARCHAR(64),
+    tmp_telescope VARCHAR(64),
+    state VARCHAR(64),
+    workdir VARCHAR(255),
+    workdir_state VARCHAR(64),
+    reduction VARCHAR(64),
+    dvodb VARCHAR(255),
+    tess_id VARCHAR(64),
+    end_stage VARCHAR(64),
+    label VARCHAR(64),
+    epoch TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    PRIMARY KEY(exp_id),
+    KEY(exp_id),
+    KEY(tmp_exp_name),
+    KEY(tmp_camera),
+    KEY(tmp_telescope),
+    KEY(state),
+    KEY(workdir_state),
+    KEY(end_stage),
+    KEY(label)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE newImfile (
+    exp_id BIGINT,
+    tmp_class_id VARCHAR(64),
+    uri VARCHAR(255),
+    epoch TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    PRIMARY KEY(exp_id, tmp_class_id),
+    FOREIGN KEY (exp_id)
+        REFERENCES  newExp(exp_id))
+ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE rawExp (
+    exp_id BIGINT,
+    exp_name VARCHAR(64),
+    camera VARCHAR(64),
+    telescope VARCHAR(64),
+    dateobs DATETIME,
+    exp_tag VARCHAR(255),
+    exp_type VARCHAR(64),
+    filelevel VARCHAR(64),
+    workdir VARCHAR(255),
+    reduction VARCHAR(64),
+    dvodb VARCHAR(255),
+    tess_id VARCHAR(64),
+    end_stage VARCHAR(64),
+    filter VARCHAR(64),
+    comment VARCHAR(80),
+    airmass FLOAT,
+    ra DOUBLE,
+    decl DOUBLE,
+    exp_time FLOAT,
+    sat_pixel_frac FLOAT,
+    bg DOUBLE,
+    bg_stdev DOUBLE,
+    bg_mean_stdev DOUBLE,
+    alt DOUBLE,
+    az DOUBLE,
+    ccd_temp FLOAT,
+    posang DOUBLE,
+    m1_x FLOAT,
+    m1_y FLOAT,
+    m1_z FLOAT,
+    m1_tip FLOAT,
+    m1_tilt FLOAT,
+    m2_x FLOAT,
+    m2_y FLOAT,
+    m2_z FLOAT,
+    m2_tip FLOAT,
+    m2_tilt FLOAT,
+    env_temperature FLOAT,
+    env_humidity FLOAT,
+    env_wind_speed FLOAT,
+    env_wind_dir FLOAT,
+    teltemp_m1 FLOAT,
+    teltemp_m1cell FLOAT,
+    teltemp_m2 FLOAT,
+    teltemp_spider FLOAT,
+    teltemp_truss FLOAT,
+    teltemp_extra FLOAT,
+    pon_time FLOAT,
+    user_1 DOUBLE,
+    user_2 DOUBLE,
+    user_3 DOUBLE,
+    user_4 DOUBLE,
+    user_5 DOUBLE,
+    object VARCHAR(64),
+    solang FLOAT,
+    hostname VARCHAR(64),
+    fault SMALLINT NOT NULL,
+    epoch TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    PRIMARY KEY(exp_id),
+    KEY(exp_name),
+    KEY(end_stage),
+    KEY(fault),
+    FOREIGN KEY (exp_id)
+        REFERENCES  newExp(exp_id))
+ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE rawImfile (
+    exp_id BIGINT,
+    exp_name VARCHAR(64),
+    camera VARCHAR(64),
+    telescope VARCHAR(64),
+    dateobs DATETIME,
+    tmp_class_id VARCHAR(64),
+    class_id VARCHAR(64),
+    uri VARCHAR(255),
+    exp_type VARCHAR(64),
+    filelevel VARCHAR(64),
+    filter VARCHAR(64),
+    comment VARCHAR(80),
+    airmass FLOAT,
+    ra DOUBLE,
+    decl DOUBLE,
+    exp_time FLOAT,
+    sat_pixel_frac FLOAT,
+    bg DOUBLE,
+    bg_stdev DOUBLE,
+    bg_mean_stdev DOUBLE,
+    alt DOUBLE,
+    az DOUBLE,
+    ccd_temp FLOAT,
+    posang DOUBLE,
+    m1_x FLOAT,
+    m1_y FLOAT,
+    m1_z FLOAT,
+    m1_tip FLOAT,
+    m1_tilt FLOAT,
+    m2_x FLOAT,
+    m2_y FLOAT,
+    m2_z FLOAT,
+    m2_tip FLOAT,
+    m2_tilt FLOAT,
+    env_temperature FLOAT,
+    env_humidity FLOAT,
+    env_wind_speed FLOAT,
+    env_wind_dir FLOAT,
+    teltemp_m1 FLOAT,
+    teltemp_m1cell FLOAT,
+    teltemp_m2 FLOAT,
+    teltemp_spider FLOAT,
+    teltemp_truss FLOAT,
+    teltemp_extra FLOAT,
+    pon_time FLOAT,
+    user_1 DOUBLE,
+    user_2 DOUBLE,
+    user_3 DOUBLE,
+    user_4 DOUBLE,
+    user_5 DOUBLE,
+    object VARCHAR(64),
+    hostname VARCHAR(64),
+    fault SMALLINT NOT NULL,
+    epoch TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    PRIMARY KEY(exp_id, class_id),
+    KEY(tmp_class_id),
+    KEY(fault),
+    UNIQUE KEY(exp_id, tmp_class_id),
+    FOREIGN KEY (exp_id, tmp_class_id)
+        REFERENCES newImfile(exp_id, tmp_class_id))
+ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE guidePendingExp (guide_id BIGINT AUTO_INCREMENT, exp_id BIGINT, recipe VARCHAR(64), PRIMARY KEY(guide_id), KEY(guide_id), KEY(exp_id)) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE chipRun (
+    chip_id BIGINT AUTO_INCREMENT,
+    exp_id BIGINT,
+    state VARCHAR(64),
+    workdir VARCHAR(255),
+    workdir_state VARCHAR(64),
+    label VARCHAR(64),
+    reduction VARCHAR(64),
+     expgroup VARCHAR(64),
+    dvodb VARCHAR(255),
+    tess_id VARCHAR(64),
+    end_stage VARCHAR(64),
+    PRIMARY KEY(chip_id),
+    KEY(chip_id), KEY(exp_id),
+    KEY(state),
+    KEY(workdir_state),
+    KEY(label),
+    KEY(expgroup),
+    KEY(end_stage),
+    INDEX(chip_id, exp_id),
+    FOREIGN KEY (exp_id)
+        REFERENCES rawExp(exp_id))
+ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE chipProcessedImfile (
+    chip_id BIGINT,
+    exp_id BIGINT,
+    class_id VARCHAR(64),
+    uri VARCHAR(255),
+    bg FLOAT,
+    bg_stdev FLOAT,
+    bg_mean_stdev FLOAT,
+    bias FLOAT,
+    bias_stdev FLOAT,
+    fringe_0 FLOAT,
+    fringe_1 FLOAT,
+    fringe_2 FLOAT,
+    sigma_ra FLOAT,
+    sigma_dec FLOAT,
+    ap_resid FLOAT,
+    ap_resid_stdev FLOAT,
+    zp_mean FLOAT,
+    zp_stdev FLOAT,
+    fwhm_major FLOAT,
+    fwhm_minor FLOAT,
+    dtime_detrend FLOAT,
+    dtime_photom FLOAT,
+    dtime_astrom FLOAT,
+    hostname VARCHAR(64),
+    n_stars INT,
+    n_extended INT,
+    n_cr INT,
+    n_astrom INT,
+    path_base VARCHAR(255),
+    fault SMALLINT NOT NULL,
+    PRIMARY KEY(chip_id, exp_id, class_id),
+    KEY(fault),
+    FOREIGN KEY (chip_id, exp_id)
+        REFERENCES  chipRun(chip_id, exp_id),
+    FOREIGN KEY (exp_id, class_id)
+        REFERENCES  rawImfile(exp_id, class_id))
+ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE chipMask (
+    label VARCHAR(64),
+    PRIMARY KEY(label))
+ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE camRun (
+    cam_id BIGINT AUTO_INCREMENT,
+    chip_id BIGINT,
+    state VARCHAR(64),
+    workdir VARCHAR(255),
+    workdir_state VARCHAR(64),
+    label VARCHAR(64),
+    reduction VARCHAR(64),
+    expgroup VARCHAR(64),
+    dvodb VARCHAR(255),
+    tess_id VARCHAR(64),
+    end_stage VARCHAR(64),
+    PRIMARY KEY(cam_id),
+    KEY(cam_id),
+    KEY(chip_id),
+    KEY(state),
+    KEY(workdir_state),
+    KEY(label),
+    KEY(expgroup),
+    KEY(end_stage),
+    INDEX(cam_id, chip_id),
+    FOREIGN KEY (chip_id)
+        REFERENCES chipRun(chip_id))
+ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE camProcessedExp (
+    cam_id BIGINT,
+    uri VARCHAR(255),
+    bg FLOAT,
+    bg_stdev FLOAT,
+    bg_mean_stdev FLOAT,
+    bias FLOAT,
+    bias_stdev FLOAT,
+    fringe_0 FLOAT,
+    fringe_1 FLOAT,
+    fringe_2 FLOAT,
+    sigma_ra FLOAT,
+    sigma_dec FLOAT,
+    ap_resid FLOAT,
+    ap_resid_stdev FLOAT,
+    zp_mean FLOAT,
+    zp_stdev FLOAT,
+    fwhm_major FLOAT,
+    fwhm_minor FLOAT,
+    dtime_detrend FLOAT,
+    dtime_photom FLOAT,
+    dtime_astrom FLOAT,
+    hostname VARCHAR(64),
+    n_stars INT,
+    n_extended INT,
+    n_cr INT,
+    n_astrom INT,
+    path_base VARCHAR(255),
+    fault SMALLINT NOT NULL,
+    PRIMARY KEY(cam_id),
+    KEY(fault),
+    FOREIGN KEY (cam_id)
+        REFERENCES camRun(cam_id))
+ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE camMask (
+    label VARCHAR(64),
+    PRIMARY KEY(label))
+ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE fakeRun (
+    fake_id BIGINT AUTO_INCREMENT,
+    cam_id BIGINT,
+    state VARCHAR(64),
+    workdir VARCHAR(255),
+    label VARCHAR(64),
+    reduction VARCHAR(64),
+    expgroup VARCHAR(64),
+    dvodb VARCHAR(255),
+    tess_id VARCHAR(64),
+    end_stage VARCHAR(64),
+    epoch TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    PRIMARY KEY(fake_id),
+    KEY(cam_id),
+    KEY(state),
+    KEY(label),
+    KEY(expgroup),
+    KEY(end_stage),
+    INDEX(fake_id, cam_id),
+    FOREIGN KEY (cam_id)
+        REFERENCES camRun(cam_id))
+ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE fakeProcessedImfile (
+    fake_id BIGINT AUTO_INCREMENT,
+    exp_id BIGINT,
+    class_id VARCHAR(64),
+    uri VARCHAR(255),
+    dtime_fake FLOAT,
+    hostname VARCHAR(64),
+    path_base VARCHAR(255),
+    fault SMALLINT NOT NULL,
+    epoch TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    PRIMARY KEY(fake_id, exp_id, class_id),
+    KEY(fault),
+    FOREIGN KEY (fake_id)
+        REFERENCES fakeRun(fake_id),
+    FOREIGN KEY (exp_id, class_id)
+        REFERENCES rawImfile(exp_id, class_id))
+ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE fakeMask (
+    label VARCHAR(64),
+    PRIMARY KEY(label))
+ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE detRun (
+    det_id BIGINT AUTO_INCREMENT,
+    iteration INT,
+    det_type VARCHAR(64),
+    mode VARCHAR(64),
+    state VARCHAR(64),
+    filelevel VARCHAR(64),
+    workdir VARCHAR(255),
+    camera VARCHAR(64),
+    telescope VARCHAR(64),
+    exp_type VARCHAR(64),
+    reduction VARCHAR(64),
+    filter VARCHAR(64),
+    airmass_min FLOAT,
+    airmass_max FLOAT,
+    exp_time_min FLOAT,
+    exp_time_max FLOAT,
+    ccd_temp_min FLOAT,
+    ccd_temp_max FLOAT,
+    posang_min DOUBLE,
+    posang_max DOUBLE,
+    registered DATETIME,
+    time_begin DATETIME,
+    time_end DATETIME,
+    use_begin DATETIME,
+    use_end DATETIME,
+    solang_min FLOAT,
+    solang_max FLOAT,
+    label VARCHAR(64),
+    parent INT,
+    PRIMARY KEY(det_id),
+    KEY(det_id),
+    KEY(iteration),
+    KEY(det_type),
+    KEY(mode),
+    KEY(state),
+    KEY(label),
+    KEY(parent),
+    INDEX(det_id, iteration))
+ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE detInputExp (
+det_id BIGINT,
+iteration INT,
+exp_id BIGINT,
+include TINYINT,
+PRIMARY KEY(det_id, iteration, exp_id),
+INDEX(det_id, exp_id),
+INDEX(det_id, iteration),
+FOREIGN KEY (det_id)
+REFERENCES  detRun(det_id),
+FOREIGN KEY (exp_id)
+REFERENCES  rawExp(exp_id))
+ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE detProcessedImfile (
+    det_id BIGINT,
+    exp_id BIGINT,
+    class_id VARCHAR(64),
+    uri VARCHAR(255),
+    recipe VARCHAR(64),
+    bg DOUBLE,
+    bg_stdev DOUBLE,
+    bg_mean_stdev DOUBLE,
+    fringe_0 DOUBLE,
+    fringe_1 DOUBLE,
+    fringe_2 DOUBLE,
+    user_1 DOUBLE,
+    user_2 DOUBLE,
+    user_3 DOUBLE,
+    user_4 DOUBLE,
+    user_5 DOUBLE,
+    path_base VARCHAR(255),
+    data_state VARCHAR(64),
+    fault SMALLINT NOT NULL,
+    PRIMARY KEY(det_id, exp_id, class_id),
+    KEY(fault),
+    INDEX(det_id, class_id),
+    INDEX(det_id, exp_id),
+    FOREIGN KEY (det_id, exp_id)
+        REFERENCES  detInputExp(det_id, exp_id),
+    FOREIGN KEY (exp_id, class_id)
+        REFERENCES  rawImfile(exp_id, class_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE detProcessedExp (
+    det_id BIGINT,
+    exp_id BIGINT,
+    recipe VARCHAR(64),
+    bg DOUBLE,
+    bg_stdev DOUBLE,
+    bg_mean_stdev DOUBLE,
+    fringe_0 DOUBLE,
+    fringe_1 DOUBLE,
+    fringe_2 DOUBLE,
+    user_1 DOUBLE,
+    user_2 DOUBLE,
+    user_3 DOUBLE,
+    user_4 DOUBLE,
+    user_5 DOUBLE,
+    path_base VARCHAR(255),
+    data_state VARCHAR(64),
+    fault SMALLINT NOT NULL,
+    PRIMARY KEY(det_id, exp_id),
+    KEY(fault),
+    FOREIGN KEY (det_id, exp_id)
+        REFERENCES  detInputExp(det_id, exp_id),
+    FOREIGN KEY (det_id, exp_id)
+        REFERENCES  detProcessedImfile(det_id, exp_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE detStackedImfile (
+    det_id BIGINT,
+    iteration INT,
+    class_id VARCHAR(64),
+    uri VARCHAR(255),
+    recipe VARCHAR(64),
+    bg DOUBLE,
+    bg_stdev DOUBLE,
+    bg_mean_stdev DOUBLE,
+    user_1 DOUBLE,
+    user_2 DOUBLE,
+    user_3 DOUBLE,
+    user_4 DOUBLE,
+    user_5 DOUBLE,
+    data_state VARCHAR(64),
+    fault SMALLINT NOT NULL,
+    PRIMARY KEY(det_id, iteration, class_id),
+    KEY(fault),
+    FOREIGN KEY (det_id, iteration)
+        REFERENCES  detInputExp(det_id, iteration),
+    FOREIGN KEY (det_id, class_id)
+        REFERENCES  detProcessedImfile(det_id, class_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE detNormalizedStatImfile (
+    det_id BIGINT,
+    iteration INT,
+    class_id VARCHAR(64),
+    norm FLOAT,
+    data_state VARCHAR(64),
+    fault SMALLINT NOT NULL,
+    PRIMARY KEY(det_id, iteration, class_id),
+    KEY(fault),
+    FOREIGN KEY (det_id, iteration)
+    REFERENCES  detInputExp(det_id, iteration),
+    FOREIGN KEY (det_id, iteration, class_id)
+    REFERENCES  detStackedImfile(det_id, iteration, class_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE detNormalizedImfile (
+    det_id BIGINT,
+    iteration INT,
+    class_id VARCHAR(64),
+    uri VARCHAR(255),
+    bg DOUBLE,
+    bg_stdev DOUBLE,
+    bg_mean_stdev DOUBLE,
+    user_1 DOUBLE,
+    user_2 DOUBLE,
+    user_3 DOUBLE,
+    user_4 DOUBLE,
+    user_5 DOUBLE,
+    path_base VARCHAR(255),
+    data_state VARCHAR(64),
+    fault SMALLINT NOT NULL,
+    PRIMARY KEY(det_id, iteration, class_id),
+    KEY(fault),
+    INDEX(det_id, iteration),
+    FOREIGN KEY (det_id)
+    REFERENCES  detInputExp(det_id),
+    FOREIGN KEY (det_id, iteration, class_id)
+    REFERENCES  detNormalizedStatImfile(det_id, iteration, class_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE detNormalizedExp (
+    det_id BIGINT,
+    iteration INT,
+    recipe VARCHAR(64),
+    bg DOUBLE,
+    bg_stdev DOUBLE,
+    bg_mean_stdev DOUBLE,
+    user_1 DOUBLE,
+    user_2 DOUBLE,
+    user_3 DOUBLE,
+    user_4 DOUBLE,
+    user_5 DOUBLE,
+    path_base VARCHAR(255),
+    data_state VARCHAR(64),
+    fault SMALLINT NOT NULL,
+    PRIMARY KEY(det_id, iteration),
+    KEY(fault),
+    FOREIGN KEY (det_id, iteration)
+    REFERENCES  detInputExp(det_id, iteration),
+    FOREIGN KEY (det_id, iteration)
+    REFERENCES  detNormalizedImfile(det_id, iteration)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE detResidImfile (
+    det_id BIGINT,
+    iteration INT,
+    exp_id BIGINT,
+    class_id VARCHAR(64),
+    uri VARCHAR(255),
+    recipe VARCHAR(64),
+    bg DOUBLE,
+    bg_stdev DOUBLE,
+    bg_mean_stdev DOUBLE,
+    bg_skewness DOUBLE,
+    bg_kurtosis DOUBLE,
+    bin_stdev DOUBLE,
+    fringe_0 DOUBLE,
+    fringe_1 DOUBLE,
+    fringe_2 DOUBLE,
+    fringe_resid_0 DOUBLE,
+    fringe_resid_1 DOUBLE,
+    fringe_resid_2 DOUBLE,
+    user_1 DOUBLE,
+    user_2 DOUBLE,
+    user_3 DOUBLE,
+    user_4 DOUBLE,
+    user_5 DOUBLE,
+    path_base VARCHAR(255),
+    data_state VARCHAR(64),
+    fault SMALLINT NOT NULL,
+    PRIMARY KEY(det_id, iteration, exp_id, class_id),
+    KEY(fault),
+    INDEX(det_id, iteration, exp_id),
+    FOREIGN KEY (det_id, iteration, exp_id)
+    REFERENCES  detInputExp(det_id, iteration, exp_id),
+    FOREIGN KEY (det_id, exp_id, class_id)
+    REFERENCES  detProcessedImfile(det_id, exp_id, class_id),
+    FOREIGN KEY (det_id, iteration)
+    REFERENCES  detNormalizedExp(det_id, iteration)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE detResidExp (
+       det_id BIGINT, 
+       iteration INT, 
+       exp_id BIGINT, 
+       recipe VARCHAR(64), 
+       bg DOUBLE, 
+       bg_stdev DOUBLE, 
+       bg_mean_stdev DOUBLE, 
+       bg_skewness DOUBLE, 
+       bg_kurtosis DOUBLE, 
+       bin_stdev DOUBLE, 
+       fringe_0 DOUBLE, 
+       fringe_1 DOUBLE, 
+       fringe_2 DOUBLE, 
+       fringe_resid_0 DOUBLE, 
+       fringe_resid_1 DOUBLE, 
+       fringe_resid_2 DOUBLE, 
+       user_1 DOUBLE, 
+       user_2 DOUBLE, 
+       user_3 DOUBLE, 
+       user_4 DOUBLE, 
+       user_5 DOUBLE, 
+       path_base VARCHAR(255), 
+       data_state VARCHAR(64),
+       accept TINYINT, 
+       fault SMALLINT NOT NULL, 
+       PRIMARY KEY(det_id, iteration, exp_id), 
+       KEY(fault), 
+       INDEX(det_id, iteration), 
+       FOREIGN KEY (det_id, iteration, exp_id)  
+       REFERENCES  detInputExp(det_id, iteration, exp_id), 
+       FOREIGN KEY (det_id, iteration, exp_id)  
+       REFERENCES  detResidImfile(det_id, iteration, exp_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE detRunSummary (
+       det_id BIGINT, 
+       iteration INT, 
+       data_state VARCHAR(64), 
+       bg DOUBLE, 
+       bg_stdev DOUBLE, 
+       bg_mean_stdev DOUBLE, 
+       accept TINYINT, 
+       fault SMALLINT NOT NULL, 
+       PRIMARY KEY(det_id, iteration), 
+       KEY(fault), 
+       FOREIGN KEY (det_id, iteration)  
+         REFERENCES  detInputExp(det_id, iteration), 
+       FOREIGN KEY (det_id, iteration)  
+         REFERENCES  detResidExp(det_id, iteration)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE detRegisteredImfile (
+       det_id BIGINT, 
+       iteration INT, 
+       class_id VARCHAR(64), 
+       uri VARCHAR(255), 
+       bg DOUBLE, 
+       bg_stdev DOUBLE, 
+       bg_mean_stdev DOUBLE, 
+       user_1 DOUBLE, 
+       user_2 DOUBLE, 
+       user_3 DOUBLE, 
+       user_4 DOUBLE, 
+       user_5 DOUBLE, 
+       path_base VARCHAR(255),
+       data_state VARCHAR(64),
+       fault SMALLINT NOT NULL, 
+       PRIMARY KEY(det_id, iteration, class_id), 
+       KEY(fault), 
+       FOREIGN KEY (det_id, iteration)  
+         REFERENCES  detRun(det_id, iteration)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE warpRun (
+    warp_id BIGINT AUTO_INCREMENT,
+    fake_id BIGINT,
+    mode VARCHAR(64),
+    state VARCHAR(64),
+    workdir VARCHAR(255),
+    workdir_state VARCHAR(64),
+    label VARCHAR(64),
+    dvodb VARCHAR(255),
+    tess_id VARCHAR(64),
+    end_stage VARCHAR(64),
+    registered DATETIME,
+    magiced TINYINT,
+    PRIMARY KEY(warp_id),
+    KEY(warp_id),
+    KEY(fake_id),
+    KEY(mode),
+    KEY(state),
+    KEY(workdir_state),
+    KEY(label),
+    KEY(end_stage),
+    KEY(magiced),
+    INDEX(warp_id, fake_id),
+    FOREIGN KEY (fake_id)
+        REFERENCES fakeRun(fake_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE warpSkyCellMap (
+    warp_id BIGINT,
+    skycell_id VARCHAR(64),
+    tess_id VARCHAR(64),
+    class_id VARCHAR(64),
+    fault SMALLINT,
+    PRIMARY KEY(warp_id, skycell_id, tess_id, class_id),
+    KEY(fault),
+    FOREIGN KEY (warp_id)
+        REFERENCES warpRun(warp_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE warpSkyfile (
+    warp_id BIGINT,
+    skycell_id VARCHAR(64),
+    tess_id VARCHAR(64),
+    uri VARCHAR(255),
+    path_base VARCHAR(255),
+    bg DOUBLE,
+    bg_stdev DOUBLE,
+    dtime_warp FLOAT,
+    hostname VARCHAR(64),
+    good_frac FLOAT,
+    xmin INT,
+    xmax INT,
+    ymin INT,
+    ymax INT,
+    ignored TINYINT,
+    fault SMALLINT,
+    PRIMARY KEY(warp_id, skycell_id, tess_id),
+    KEY(good_frac),
+    KEY(ignored), KEY(fault),
+    FOREIGN KEY (warp_id, skycell_id, tess_id)
+        REFERENCES warpSkyCellMap(warp_id, skycell_id, tess_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE warpMask (
+    label VARCHAR(64),
+    PRIMARY KEY(label)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE stackRun (
+        stack_id BIGINT AUTO_INCREMENT,
+        state VARCHAR(64),
+        workdir VARCHAR(255),
+        dvodb VARCHAR(255),
+        registered DATETIME,
+        skycell_id VARCHAR(64),
+        tess_id VARCHAR(64),
+        filter VARCHAR(64),
+        PRIMARY KEY(stack_id),
+        KEY(stack_id),
+        KEY(state),
+        KEY(skycell_id),
+        KEY(tess_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE stackInputSkyfile (
+        stack_id BIGINT,
+        warp_id BIGINT,
+        PRIMARY KEY(stack_id, warp_id),
+        FOREIGN KEY (stack_id)  REFERENCES  stackRun(stack_id),
+        FOREIGN KEY (warp_id)  REFERENCES  warpSkyfile(warp_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE stackSumSkyfile (
+        stack_id BIGINT,
+        uri VARCHAR(255),
+        path_base VARCHAR(255),
+        bg DOUBLE,
+        bg_stdev DOUBLE,
+        dtime_stack FLOAT,
+        hostname VARCHAR(64),
+        good_frac FLOAT,
+        fault SMALLINT,
+        PRIMARY KEY(stack_id),
+        KEY(dtime_stack),
+        KEY(good_frac),
+        KEY(fault),
+        FOREIGN KEY (stack_id)  REFERENCES  stackRun(stack_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE diffRun (
+        diff_id BIGINT AUTO_INCREMENT,
+        state VARCHAR(64),
+        workdir VARCHAR(255),
+        dvodb VARCHAR(255),
+        registered DATETIME,
+        skycell_id VARCHAR(64),
+        tess_id VARCHAR(64),
+        PRIMARY KEY(diff_id),
+        KEY(diff_id),
+        KEY(state),
+        KEY(skycell_id),
+        KEY(tess_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE diffInputSkyfile (
+        diff_id BIGINT,
+        template TINYINT,
+        stack_id BIGINT,
+        warp_id BIGINT,
+        skycell_id VARCHAR(64),
+        tess_id VARCHAR(64),
+        kind VARCHAR(64),
+        PRIMARY KEY(diff_id, template),
+        KEY(stack_id),
+        KEY(warp_id),
+        KEY(skycell_id),
+        KEY(tess_id),
+        KEY(kind),
+        FOREIGN KEY (diff_id)  REFERENCES  diffRun(diff_id),
+        FOREIGN KEY (stack_id)  REFERENCES  stackSumSkyfile(stack_id),
+        FOREIGN KEY (warp_id, skycell_id, tess_id)  REFERENCES  warpSkyfile(warp_id, skycell_id, tess_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE diffSkyfile (
+        diff_id BIGINT,
+        uri VARCHAR(255),
+        path_base VARCHAR(255),
+        bg DOUBLE,
+        bg_stdev DOUBLE,
+        stamps_num INT,
+        stamps_rms FLOAT,
+        sources INT,
+        dtime_diff FLOAT,
+        hostname VARCHAR(64),
+        good_frac FLOAT,
+        fault SMALLINT,
+        PRIMARY KEY(diff_id),
+        KEY(good_frac),
+        KEY(fault),
+        FOREIGN KEY (diff_id)  REFERENCES  diffRun(diff_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE magicRun (
+        magic_id BIGINT AUTO_INCREMENT,
+        exp_id BIGINT,
+        state VARCHAR(64),
+        workdir VARCHAR(255),
+        workdir_state VARCHAR(255),
+        label VARCHAR(64),
+        dvodb VARCHAR(255),
+        registered DATETIME,
+        fault SMALLINT,
+        PRIMARY KEY(magic_id),
+        KEY(magic_id),
+        KEY(state),
+        KEY(workdir_state),
+        KEY(label),
+        KEY(fault),
+        FOREIGN KEY (exp_id)  REFERENCES  rawExp(exp_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE magicInputSkyfile (
+        magic_id BIGINT,
+        diff_id BIGINT,
+        node VARCHAR(64),
+        PRIMARY KEY(magic_id, diff_id),
+        FOREIGN KEY (magic_id)  REFERENCES  magicRun(magic_id),
+        FOREIGN KEY (diff_id)  REFERENCES  diffRun(diff_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE magicTree (
+        magic_id BIGINT,
+        node VARCHAR(64),
+        dep VARCHAR(64),
+        KEY(magic_id),
+        KEY(node),
+        KEY(dep),
+        INDEX(magic_id, node),
+        FOREIGN KEY (magic_id)  REFERENCES  magicRun(magic_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE magicNodeResult (
+        magic_id BIGINT,
+        node VARCHAR(64),
+        uri VARCHAR(255),
+        fault SMALLINT,
+        PRIMARY KEY(magic_id, node),
+        FOREIGN KEY (magic_id)  REFERENCES  magicRun(magic_id),
+        FOREIGN KEY (magic_id, node)  REFERENCES  magicTree(magic_id, node),
+        KEY(fault)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE magicMask (
+        magic_id BIGINT,
+        uri VARCHAR(255),
+        streaks INT,
+        fault SMALLINT,
+        PRIMARY KEY(magic_id),
+        FOREIGN KEY (magic_id)  REFERENCES  magicRun(magic_id),
+        KEY(fault)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE calDB (
+        cal_id BIGINT AUTO_INCREMENT,
+        dvodb VARCHAR(64),
+        state VARCHAR(64),
+        PRIMARY KEY(cal_id),
+        KEY(cal_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE calRun (
+        cal_id BIGINT AUTO_INCREMENT,
+        region VARCHAR(64),
+        last_step VARCHAR(64),
+        state VARCHAR(64),
+        PRIMARY KEY(cal_id),
+        KEY(cal_id),
+        KEY(last_step),
+        FOREIGN KEY (cal_id)  REFERENCES  calDB(cal_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE flatcorrRun (
+        corr_id BIGINT AUTO_INCREMENT,
+        dvodb VARCHAR(64),
+        filter VARCHAR(64),
+        state VARCHAR(64),
+        workdir VARCHAR(255),
+        label VARCHAR(64),
+        stats VARCHAR(255),
+        region VARCHAR(255),
+        PRIMARY KEY(corr_id),
+        KEY(corr_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE flatcorrExp (
+        corr_id BIGINT,
+        chip_id BIGINT,
+        PRIMARY KEY(corr_id, chip_id),
+        FOREIGN KEY (corr_id)  REFERENCES  flatcorrRun(corr_id),
+        FOREIGN KEY (chip_id)  REFERENCES  chipRun(chip_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE pstampDataStore (
+        ds_id BIGINT AUTO_INCREMENT,
+        state VARCHAR(64),
+        lastFileset VARCHAR(64),
+        outProduct VARCHAR(64) UNIQUE,
+        uri VARCHAR(255),
+        PRIMARY KEY(ds_id),
+        KEY(ds_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE pstampRequest (
+        req_id BIGINT AUTO_INCREMENT,
+        ds_id BIGINT,
+        state VARCHAR(64),
+        name VARCHAR(64) UNIQUE,
+        reqType VARCHAR(16),
+        outProduct VARCHAR(64),
+        uri VARCHAR(255),
+        fault SMALLINT,
+        PRIMARY KEY(req_id),
+        KEY(req_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE pstampJob (
+        job_id BIGINT AUTO_INCREMENT,
+        req_id BIGINT,
+        rownum VARCHAR(64),
+        state VARCHAR(64),
+        jobType VARCHAR(16),
+        fault SMALLINT,
+        uri VARCHAR(255),
+        outputBase VARCHAR(255),
+        args VARCHAR(511),
+        PRIMARY KEY(job_id, req_id),
+        KEY(job_id),
+        FOREIGN KEY (req_id)  REFERENCES  pstampRequest(req_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/pxadmin_drop_tables.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/pxadmin_drop_tables.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/pxadmin_drop_tables.sql	(revision 22158)
@@ -0,0 +1,56 @@
+SET FOREIGN_KEY_CHECKS=0;
+DROP TABLE IF EXISTS pzDataStore;
+DROP TABLE IF EXISTS summitExp;
+DROP TABLE IF EXISTS summitImfile;
+DROP TABLE IF EXISTS pzDownloadExp;
+DROP TABLE IF EXISTS pzDownloadImfile;
+DROP TABLE IF EXISTS newExp;
+DROP TABLE IF EXISTS newImfile;
+DROP TABLE IF EXISTS rawExp;
+DROP TABLE IF EXISTS rawImfile;
+DROP TABLE IF EXISTS guidePendingExp;
+DROP TABLE IF EXISTS chipRun;
+DROP TABLE IF EXISTS chipProcessedImfile;
+DROP TABLE IF EXISTS chipMask;
+DROP TABLE IF EXISTS camRun;
+DROP TABLE IF EXISTS camProcessedExp;
+DROP TABLE IF EXISTS camMask;
+DROP TABLE IF EXISTS detRun;
+DROP TABLE IF EXISTS detInputExp;
+DROP TABLE IF EXISTS fakeRun;
+DROP TABLE IF EXISTS fakeProcessedImfile;
+DROP TABLE IF EXISTS fakeMask;
+DROP TABLE IF EXISTS detProcessedImfile;
+DROP TABLE IF EXISTS detProcessedExp;
+DROP TABLE IF EXISTS detStackedImfile;
+DROP TABLE IF EXISTS detNormalizedStatImfile;
+DROP TABLE IF EXISTS detNormalizedImfile;
+DROP TABLE IF EXISTS detNormalizedExp;
+DROP TABLE IF EXISTS detResidImfile;
+DROP TABLE IF EXISTS detResidExp;
+DROP TABLE IF EXISTS detRunSummary;
+DROP TABLE IF EXISTS detRegisteredImfile;
+DROP TABLE IF EXISTS warpRun;
+DROP TABLE IF EXISTS warpSkyCellMap;
+DROP TABLE IF EXISTS warpSkyfile;
+DROP TABLE IF EXISTS warpMask;
+DROP TABLE IF EXISTS diffRun;
+DROP TABLE IF EXISTS diffInputSkyfile;
+DROP TABLE IF EXISTS diffSkyfile;
+DROP TABLE IF EXISTS stackRun;
+DROP TABLE IF EXISTS stackInputSkyfile;
+DROP TABLE IF EXISTS stackSumSkyfile;
+DROP TABLE IF EXISTS magicRun;
+DROP TABLE IF EXISTS magicInputSkyfile;
+DROP TABLE IF EXISTS magicTree;
+DROP TABLE IF EXISTS magicNodeResult;
+DROP TABLE IF EXISTS magicMask;
+DROP TABLE IF EXISTS magicSkyfileMask;
+DROP TABLE IF EXISTS calDB;
+DROP TABLE IF EXISTS calRun;
+DROP TABLE IF EXISTS flatcorrRun;
+DROP TABLE IF EXISTS flatcorrExp;
+DROP TABLE IF EXISTS pstampDataStore;
+DROP TABLE IF EXISTS pstampRequest;
+DROP TABLE IF EXISTS pstampJob;
+SET FOREIGN_KEY_CHECKS=1
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/pztool_find_completed_exp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/pztool_find_completed_exp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/pztool_find_completed_exp.sql	(revision 22158)
@@ -0,0 +1,35 @@
+SELECT DISTINCT
+    exp_name, -- return should match pzDownloadExp
+    camera,
+    telescope,
+    state,
+    NULL as epoch    -- epoch
+FROM (
+    SELECT
+        pzDownloadImfile.*,
+        pzDownloadExp.state,
+        summitExp.imfiles
+    FROM pzDownloadExp
+    JOIN summitExp
+        USING(exp_name, camera, telescope)
+    LEFT JOIN pzDownloadImfile
+        USING(exp_name, camera, telescope)
+    LEFT JOIN newExp
+        ON pzDownloadExp.exp_name = newExp.tmp_exp_name
+        AND pzDownloadExp.camera = newExp.tmp_camera
+        AND pzDownloadExp.telescope = newExp.tmp_telescope
+    WHERE
+        pzDownloadExp.state = 'run'
+        AND newExp.tmp_exp_name IS NULL
+        AND newExp.tmp_camera IS NULL
+        AND newExp.tmp_telescope IS NULL
+    GROUP BY
+        pzDownloadExp.exp_name,
+        pzDownloadExp.camera,
+        pzDownloadExp.telescope
+    -- it doesn't matter which field in pzDownloadImfile we count as we've
+    -- already Download a group by
+    HAVING
+        COUNT(pzDownloadImfile.exp_name) = summitExp.imfiles
+        AND SUM(pzDownloadImfile.fault) = 0
+    ) as Foo
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/pztool_pendingimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/pztool_pendingimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/pztool_pendingimfile.sql	(revision 22158)
@@ -0,0 +1,20 @@
+SELECT *
+FROM (
+    SELECT
+        summitImfile.*,
+        summitExp.dateobs
+    FROM summitImfile
+    JOIN pzDownloadExp
+        USING(exp_name, camera, telescope)
+    LEFT JOIN pzDownloadImfile
+        USING(exp_name, camera, telescope, class, class_id)
+    JOIN summitExp
+        USING(exp_name, camera, telescope)
+    WHERE 
+        pzDownloadExp.state = 'run'
+        AND pzDownloadImfile.exp_name IS NULL
+        AND pzDownloadImfile.camera IS NULL
+        AND pzDownloadImfile.telescope IS NULL
+        AND pzDownloadImfile.class IS NULL
+        AND pzDownloadImfile.class_id IS NULL
+) as Foo
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/pztool_revert_downloadimfile_faults.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/pztool_revert_downloadimfile_faults.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/pztool_revert_downloadimfile_faults.sql	(revision 22158)
@@ -0,0 +1,17 @@
+DELETE FROM pzDownloadImfile
+WHERE
+    fault != 0
+    -- fault was logged in the last 3 days
+    AND ABS(TIMESTAMPDIFF(SECOND, epoch, NOW())) < 86400 * 3
+    AND (
+        -- HTTP 503: try again
+        fault = 203
+        -- HTTP 500: timeout
+        OR fault = 200
+        -- HTTP 404: unknown datastore internal problem
+        OR fault = 104
+        -- ipptool errors
+        OR fault < 100
+        -- perl untrapped die()
+        OR fault = 255
+    )
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/pztool_revert_fileset_faults.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/pztool_revert_fileset_faults.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/pztool_revert_fileset_faults.sql	(revision 22158)
@@ -0,0 +1,17 @@
+UPDATE summitExp SET fault = 0
+WHERE
+    fault != 0
+    -- fault is older than 10 minutes
+    AND ABS(TIMESTAMPDIFF(SECOND, epoch, NOW())) > 60 * 10 
+    -- fault was logged in the last 3 days
+    AND ABS(TIMESTAMPDIFF(SECOND, epoch, NOW())) < 86400 * 3
+    AND (
+        -- HTTP 500: timeout
+        fault = 200
+        -- HTTP 404: unknown datastore internal problem
+        OR fault = 104
+        -- ipptool errors
+        OR fault < 100
+        -- perl untrapped die()
+        OR fault = 255
+    )
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/pztool_revertcopied.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/pztool_revertcopied.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/pztool_revertcopied.sql	(revision 22158)
@@ -0,0 +1,3 @@
+DELETE FROM pzDownloadImfile
+WHERE
+    fault != 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_create_dup_table.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_create_dup_table.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_create_dup_table.sql	(revision 22158)
@@ -0,0 +1,2 @@
+CREATE TEMPORARY TABLE duplicate (exp_id BIGINT, PRIMARY KEY(exp_id))
+ENGINE=MEMORY
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_pendingexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_pendingexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_pendingexp.sql	(revision 22158)
@@ -0,0 +1,39 @@
+-- output should match the format of newExp
+SELECT DISTINCT
+    exp_id,
+    tmp_exp_name,
+    tmp_camera,
+    tmp_telescope,
+    state,
+    workdir,
+    workdir_state,
+    reduction,
+    dvodb,
+    tess_id,
+    end_stage,
+    label,
+    epoch
+FROM
+    (SELECT
+       newExp.*,
+       newImfile.tmp_class_id,
+       rawImfile.tmp_class_id as raw_tmp_class_id
+    FROM newExp
+    JOIN newImfile
+       USING(exp_id)
+    LEFT JOIN rawExp
+       USING(exp_id)
+    LEFT JOIN rawImfile
+        ON newImfile.exp_id = rawImfile.exp_id
+        AND newImfile.tmp_class_id = rawImfile.tmp_class_id
+    WHERE
+        newExp.state = 'run'
+        AND rawExp.exp_id IS NULL
+-- where hook %s
+    GROUP BY
+        newExp.exp_id
+    HAVING
+        COUNT(newImfile.tmp_class_id) = COUNT(rawImfile.tmp_class_id)
+        AND SUM(rawImfile.fault) = 0
+-- limit hook %s
+    ) as Foo
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_pendingimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_pendingimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_pendingimfile.sql	(revision 22158)
@@ -0,0 +1,17 @@
+SELECT DISTINCT
+    newExp.exp_id,
+    newExp.tmp_exp_name,
+    newExp.tmp_camera,
+    newExp.tmp_telescope,
+    newExp.workdir,
+    newImfile.tmp_class_id,
+    newImfile.uri
+FROM newImfile
+JOIN newExp
+    USING(exp_id)
+LEFT JOIN rawImfile
+    ON newExp.exp_id = rawImfile.exp_id
+    AND newImfile.tmp_class_id = rawImfile.tmp_class_id
+WHERE
+    newExp.state = 'run'
+    AND rawImfile.tmp_class_id IS NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_populate_dup_table.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_populate_dup_table.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_populate_dup_table.sql	(revision 22158)
@@ -0,0 +1,13 @@
+INSERT INTO duplicate
+SELECT exp_id FROM
+    (
+        SELECT
+        MAX(exp_id) AS exp_id,
+--            tmp_exp_name,
+--            tmp_camera,
+--            tmp_telescope,
+        count(exp_id) AS count
+        FROM newExp
+        GROUP BY tmp_exp_name, tmp_camera, tmp_telescope
+        HAVING count > 1
+    ) as Foo
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_processedimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_processedimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_processedimfile.sql	(revision 22158)
@@ -0,0 +1,10 @@
+SELECT
+    rawImfile.*,
+    newExp.tmp_exp_name,
+    newExp.tmp_camera,
+    newExp.tmp_telescope
+FROM rawImfile
+JOIN newExp
+    USING(exp_id)
+-- bogus conditional so there is a where clause to append to
+WHERE rawImfile.exp_id is NOT NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_revertprocessedexp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_revertprocessedexp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_revertprocessedexp.sql	(revision 22158)
@@ -0,0 +1,3 @@
+DELETE FROM rawExp
+WHERE
+    fault != 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_revertprocessedimfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_revertprocessedimfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/regtool_revertprocessedimfile.sql	(revision 22158)
@@ -0,0 +1,3 @@
+DELETE FROM rawImfile
+WHERE
+    fault != 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_definebyquery_insert.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_definebyquery_insert.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_definebyquery_insert.sql	(revision 22158)
@@ -0,0 +1,22 @@
+-- Define the inputs to a defined stack
+INSERT INTO
+        stackInputSkyfile(stack_id, warp_id)
+SELECT
+        @STACK_ID@, -- This should be replaced with the stack_id
+        warp_id
+FROM warpSkyfile
+JOIN warpRun
+    USING(warp_id, tess_id)
+JOIN fakeRun
+    USING(fake_id, tess_id)
+JOIN camRun
+    USING(cam_id, tess_id)
+JOIN chipRun
+    USING(chip_id, tess_id)
+JOIN rawExp
+    USING(exp_id, tess_id)
+WHERE
+    skycell_id = '%s'
+    AND tess_id = '%s'
+    AND rawExp.filter = '%s'
+    AND warpSkyfile.fault = 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_definebyquery_insert_random.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_definebyquery_insert_random.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_definebyquery_insert_random.sql	(revision 22158)
@@ -0,0 +1,32 @@
+-- Use a random set of warps for the inputs to a defined stack
+INSERT INTO
+        stackInputSkyfile(stack_id, warp_id)
+SELECT
+        @STACK_ID@, -- This should be replaced with the stack_id
+        warp_id
+FROM (
+    -- Sub-select to get the random set of warps
+    SELECT
+            warpSkyfile.*,
+            rand() AS rnd_num
+    FROM warpSkyfile
+    JOIN warpRun
+        USING(warp_id, tess_id)
+    JOIN fakeRun
+        USING(fake_id, tess_id)
+    JOIN camRun
+        USING(cam_id, tess_id)
+    JOIN chipRun
+        USING(chip_id, tess_id)
+    JOIN rawExp
+        USING(exp_id, tess_id)
+    WHERE
+        skycell_id = '%s'
+        AND tess_id = '%s'
+        AND rawExp.filter = '%s'
+        AND warpSkyfile.fault = 0
+    -- Sort by the random number, and take the first N
+    -- to get a random set of N.
+    ORDER BY rnd_num
+    LIMIT %d
+) AS randomWarps
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_definebyquery_part1.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_definebyquery_part1.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_definebyquery_part1.sql	(revision 22158)
@@ -0,0 +1,30 @@
+-- This is the first part of the query to get a list of skycells with
+-- warps to be stacked, along with the number of warps already in a
+-- stack.  It needs to be completed by part 2 (see below).
+
+SELECT
+    skycell_id,
+    tess_id,
+    filter,
+    num_warp,
+    MAX(num_stack) AS num_stack
+FROM ((
+    -- Number of stack-ready warps as a function of skycell and filter
+    SELECT
+        skycell_id,
+        tess_id,
+        filter,
+        COUNT(warpSkyfile.skycell_id) AS num_warp -- number of warps that can be stacked
+    FROM warpRun
+        JOIN warpSkyfile USING(warp_id, tess_id)
+        JOIN fakeRun USING(fake_id, tess_id)
+        JOIN camRun USING(cam_id, tess_id)
+        JOIN chipRun USING(chip_id, tess_id)
+        JOIN rawExp USING(exp_id, tess_id)
+    WHERE
+        warpRun.state = 'full'
+    AND warpSkyfile.ignored = 0
+    AND warpSkyfile.fault = 0
+    -- Here should follow the SQL in stacktool_definebyquery_part2.sql,
+    -- after any additional WHERE conditions have been added
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_definebyquery_part2.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_definebyquery_part2.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_definebyquery_part2.sql	(revision 22158)
@@ -0,0 +1,28 @@
+-- This is the second part of the query to get a list of skycells with
+-- warps to be stacked, along with the number of warps already in a
+-- stack.  It should follow part 1, which is in
+-- stacktool_definebyquery_part1.sql
+
+    GROUP BY
+        skycell_id,
+        filter
+        ) AS warpsToStack
+        LEFT JOIN (
+    -- Number of stack inputs as a function of skycell and filter
+    SELECT
+        skycell_id,
+        tess_id,
+        filter,
+        COUNT(stackInputSkyfile.warp_id) as num_stack -- number of warps in a stack
+    FROM stackRun
+        JOIN stackInputSkyfile USING(stack_id)
+    GROUP BY
+        stack_id
+        ) AS stackSizes
+    -- JOINing the warpsToStack and stackSizes tables
+        USING(skycell_id, tess_id, filter)
+        )
+    GROUP BY
+        skycell_id,
+        tess_id,
+        filter
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_definebyquery_test.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_definebyquery_test.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_definebyquery_test.sql	(revision 22158)
@@ -0,0 +1,60 @@
+-- This is the combination of the two parts of the query to get a list
+-- of skycells with warps to be stacked, along with the number of
+-- warps already in a stack.
+
+--------------------------------------------------------------------------------
+-- THIS FILE IS INTENDED FOR TESTING ONLY!  IT IS NOT USED BY stacktool.
+-- CHANGES SHOULD BE MADE TO stacktool_definebyquery_part1.sql
+-- AND stacktool_definebyquery_part2.sql
+--------------------------------------------------------------------------------
+
+-- stacktool_definebyquery_part1.sql
+SELECT
+    skycell_id,
+    tess_id,
+    filter,
+    num_warp,
+    MAX(num_stack) AS num_stack
+FROM ((
+    -- Number of stack-ready warps as a function of skycell and filter
+    SELECT
+        skycell_id,
+        tess_id,
+        filter,
+        COUNT(warpSkyfile.skycell_id) AS num_warp -- number of warps that can be stacked
+    FROM warpRun
+        JOIN warpSkyfile USING(warp_id, tess_id)
+        JOIN fakeRun USING(fake_id, tess_id)
+        JOIN camRun USING(cam_id, tess_id)
+        JOIN chipRun USING(chip_id, tess_id)
+        JOIN rawExp USING(exp_id, tess_id)
+    WHERE
+        warpRun.state = 'full'
+    AND warpSkyfile.ignored = 0
+    AND warpSkyfile.fault = 0
+    -- Any additional selection on warps/exposures goes here
+-- stacktool_definebyquery_part2.sql
+    GROUP BY
+        skycell_id,
+        filter
+        ) AS warpsToStack
+        LEFT JOIN (
+    -- Number of stack inputs as a function of skycell and filter
+    SELECT
+        skycell_id,
+        tess_id,
+        filter,
+        COUNT(stackInputSkyfile.warp_id) as num_stack -- number of warps in a stack
+    FROM stackRun
+        JOIN stackInputSkyfile USING(stack_id)
+    GROUP BY
+        stack_id
+        ) AS stackSizes
+    -- JOINing the warpsToStack and stackSizes tables
+        USING(skycell_id, tess_id, filter)
+        )
+    GROUP BY
+        skycell_id,
+        tess_id,
+        filter
+;
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_donecleanup.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_donecleanup.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_donecleanup.sql	(revision 22158)
@@ -0,0 +1,5 @@
+SELECT
+    stackRun.*
+FROM stackRun
+WHERE
+    stackRun.state = 'cleaned'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_find_complete_warps.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_find_complete_warps.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_find_complete_warps.sql	(revision 22158)
@@ -0,0 +1,46 @@
+SELECT
+    warpSkyfile.skycell_id,
+    warpSkyfile.tess_id,
+    stackRun.stack_id,
+    COUNT(warpSkyfile.skycell_id) AS num_avail,
+    COUNT(stackRun.stack_id) AS num_extant
+FROM warpRun
+JOIN warpSkyfile 
+    USING(warp_id, tess_id)
+JOIN fakeRun
+    USING(fake_id, tess_id)
+JOIN camRun
+    USING(cam_id, tess_id)
+JOIN chipRun
+    USING(chip_id, tess_id)
+JOIN rawExp
+    USING(exp_id, tess_id)
+LEFT JOIN stackInputSkyfile
+    ON warpSkyfile.warp_id = stackInputSkyfile.warp_id
+LEFT JOIN stackRun
+    ON stackRun.tess_id = warpSkyfile.tess_id
+    AND stackRun.skycell_id = warpSkyfile.skycell_id
+    AND stackRun.stack_id = stackInputSkyfile.stack_id
+WHERE
+    warpRun.state = 'full'
+    AND warpSkyfile.ignored = 0
+GROUP BY
+    warpSkyfile.skycell_id, warpSkyfile.tess_id, stackRun.stack_id
+HAVING
+    num_avail > num_extant
+
+-- It seems like we should be grouping the results here but in fact we don't
+-- want to do that as each warp_id may contain multiple skycells.  So a warp_id
+-- may end up in more than one stackRun (for different skycells)
+--    GROUP BY
+--        warp_id
+
+
+INSERT INTO
+        stackInputSkyfile(stack_id, warp_id)
+SELECT
+        13,
+        warp_id
+FROM warpSkyfile
+WHERE
+    skycell_id = 'new';
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_inputskyfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_inputskyfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_inputskyfile.sql	(revision 22158)
@@ -0,0 +1,24 @@
+SELECT DISTINCT
+    warpSkyfile.*,
+    rawExp.camera
+FROM stackRun
+JOIN stackInputSkyfile
+    USING(stack_id)
+JOIN warpSkyfile
+    ON  stackInputSkyfile.warp_id = warpSkyfile.warp_id
+    AND stackRun.skycell_id       = warpSkyfile.skycell_id
+    AND stackRun.tess_id          = warpSkyfile.tess_id
+JOIN warpRun
+    ON stackInputSkyfile.warp_id = warpRun.warp_id
+JOIN fakeRun
+    USING(fake_id)
+JOIN camRun
+    USING(cam_id)
+JOIN chipRun
+    USING(chip_id)
+JOIN chipProcessedImfile
+    USING(chip_id)
+JOIN rawExp
+    ON chipProcessedImfile.exp_id = rawExp.exp_id
+WHERE
+    stackRun.state = 'new'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_pendingcleanuprun.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_pendingcleanuprun.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_pendingcleanuprun.sql	(revision 22158)
@@ -0,0 +1,26 @@
+-- results in too many output files
+-- is the camera needed for this?
+-- is the camera unique for this?
+SELECT
+    stackRun.stack_id,
+    rawExp.camera,
+    stackRun.state
+FROM stackRun
+JOIN stackInputSkyfile
+    USING(stack_id)
+JOIN warpSkyfile
+    ON  stackInputSkyfile.warp_id = warpSkyfile.warp_id
+    AND stackRun.skycell_id       = warpSkyfile.skycell_id
+    AND stackRun.tess_id          = warpSkyfile.tess_id
+JOIN warpRun
+    ON warpRun.warp_id = warpSkyfile.warp_id
+JOIN fakeRun
+    USING(fake_id)
+JOIN camRun
+    USING(cam_id)
+JOIN chipRun
+    USING(chip_id)
+JOIN rawExp 
+     USING (exp_id)
+WHERE
+    stackRun.state = 'goto_cleaned'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_pendingcleanupskyfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_pendingcleanupskyfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_pendingcleanupskyfile.sql	(revision 22158)
@@ -0,0 +1,11 @@
+SELECT
+    stackSumSkyfile.*,
+    stackRun.state,
+    stackRun.workdir,
+    stackRun.dvodb,
+    stackRun.tess_id
+FROM stackRun
+JOIN stackSumSkyfile
+    USING(stack_id)
+WHERE
+    stackRun.state = 'goto_cleaned'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_revertsumskyfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_revertsumskyfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_revertsumskyfile.sql	(revision 22158)
@@ -0,0 +1,3 @@
+DELETE FROM stackSumSkyfile
+WHERE
+    fault != 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_sumskyfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_sumskyfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_sumskyfile.sql	(revision 22158)
@@ -0,0 +1,23 @@
+SELECT
+    stackSumSkyfile.*,
+    stackRun.state,
+    rawExp.camera
+FROM stackRun
+JOIN stackSumSkyfile
+    USING(stack_id)
+JOIN warpRun
+    -- just need 1 warp to find the camera
+    ON warpRun.warp_id = (SELECT warp_id FROM stackInputSkyfile 
+                            WHERE stackInputSkyfile.stack_id = stackRun.stack_id limit 1)
+JOIN fakeRun
+    ON warpRun.fake_id = fakeRun.fake_id
+JOIN camRun
+    ON camRun.cam_id   = fakeRun.cam_id
+JOIN chipRun
+    ON camRun.chip_id  = chipRun.chip_id
+JOIN rawExp
+    ON chipRun.exp_id  = rawExp.exp_id
+WHERE
+-- bogus test; just here so there there is a 'WHERE' stmt to append conditionals too
+-- XXX EAM : this is not needed : fix the stacktool code.
+    stackRun.stack_id is NOT NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_tosum.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_tosum.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/stacktool_tosum.sql	(revision 22158)
@@ -0,0 +1,28 @@
+SELECT DISTINCT
+    stackRun.stack_id,
+    stackRun.tess_id,
+    stackRun.skycell_id,
+    stackRun.workdir,
+    rawExp.camera
+FROM stackRun
+JOIN stackInputSkyfile
+    USING(stack_id)
+JOIN warpSkyfile
+    ON  stackInputSkyfile.warp_id = warpSkyfile.warp_id
+    AND stackRun.skycell_id       = warpSkyfile.skycell_id
+    AND stackRun.tess_id          = warpSkyfile.tess_id
+JOIN warpRun
+    ON warpRun.warp_id = warpSkyfile.warp_id
+JOIN fakeRun
+    USING(fake_id)
+JOIN camRun
+    USING(cam_id)
+JOIN chipRun
+    USING(chip_id)
+JOIN rawExp
+    USING(exp_id)
+LEFT JOIN stackSumSkyfile
+    USING(stack_id)
+WHERE
+    stackRun.state = 'new'
+    AND stackSumSkyfile.stack_id IS NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_donecleanup.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_donecleanup.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_donecleanup.sql	(revision 22158)
@@ -0,0 +1,5 @@
+SELECT
+    warpRun.*
+FROM warpRun
+WHERE
+    warpRun.state = 'cleaned'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_exp.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_exp.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_exp.sql	(revision 22158)
@@ -0,0 +1,8 @@
+SELECT
+    fakeRun.*
+FROM warpRun
+JOIN fakeRun
+    USING(fake_id)
+WHERE
+    warpRun.state = 'new'
+    AND fakeRun.state = 'full'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_imfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_imfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_imfile.sql	(revision 22158)
@@ -0,0 +1,27 @@
+SELECT DISTINCT
+    rawImfile.*,
+    warpRun.fake_id,
+    camRun.cam_id as cam_id,
+    chipProcessedImfile.uri as chip_uri,
+    chipProcessedImfile.path_base as chip_path_base,
+    camProcessedExp.path_base as cam_path_base
+FROM warpRun
+JOIN fakeRun
+    USING(fake_id)
+JOIN camRun
+    USING(cam_id)
+JOIN camProcessedExp
+    USING(cam_id)
+JOIN chipRun
+    ON camRun.chip_id = chipRun.chip_id
+JOIN chipProcessedImfile
+    ON chipRun.chip_id = chipProcessedImfile.chip_id
+JOIN rawImfile -- is there any reason not to refer back to rawimfiles?
+    ON chipProcessedImfile.exp_id = rawImfile.exp_id
+    AND chipProcessedImfile.class_id = rawImfile.class_id 
+WHERE
+    warpRun.state = 'new'
+    AND fakeRun.state = 'full'
+    AND camRun.state = 'full'
+    AND chipRun.state = 'full'
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_pendingcleanuprun.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_pendingcleanuprun.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_pendingcleanuprun.sql	(revision 22158)
@@ -0,0 +1,15 @@
+SELECT
+    warpRun.warp_id,
+    rawExp.camera,
+    warpRun.state
+FROM warpRun
+JOIN fakeRun
+USING (fake_id)
+JOIN camRun
+USING (cam_id)
+JOIN chipRun
+USING (chip_id)
+JOIN rawExp 
+USING (exp_id)
+WHERE
+    warpRun.state = 'goto_cleaned'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_pendingcleanupskyfile.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_pendingcleanupskyfile.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_pendingcleanupskyfile.sql	(revision 22158)
@@ -0,0 +1,15 @@
+SELECT
+    warpSkyfile.*,
+    warpRun.state,
+    warpRun.workdir,
+    warpRun.label,
+    warpRun.reduction,
+    warpRun.expgroup,
+    warpRun.dvodb,
+    warpRun.tess_id,
+    warpRun.end_stage
+FROM warpRun
+JOIN warpSkyfile
+    USING(warp_id)
+WHERE
+    warpRun.state = 'goto_cleaned'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_revertwarped.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_revertwarped.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_revertwarped.sql	(revision 22158)
@@ -0,0 +1,9 @@
+DELETE FROM warpSkyfile
+USING warpSkyfile, warpRun, fakeRun, camRun, chipRun, rawExp
+WHERE
+    warpSkyfile.warp_id = warpRun.warp_id
+    AND warpRun.fake_id = fakeRun.fake_id
+    AND fakeRun.cam_id = camRun.cam_id
+    AND camRun.chip_id = chipRun.chip_id
+    AND chipRun.exp_id = rawExp.exp_id
+    AND warpSkyfile.fault != 0
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_scmap.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_scmap.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_scmap.sql	(revision 22158)
@@ -0,0 +1,24 @@
+SELECT
+    warpSkyCellMap.*,
+    chipProcessedImfile.uri,
+    chipProcessedImfile.path_base as chip_path_base,
+    camProcessedExp.path_base as cam_path_base
+FROM warpRun
+JOIN warpSkyCellMap
+    USING(warp_id)
+JOIN fakeRun
+    USING(fake_id)
+JOIN camRun
+    USING(cam_id)
+JOIN camProcessedExp
+    USING(cam_id)
+JOIN chipRun
+    USING(chip_id)
+JOIN chipProcessedImfile
+    ON chipRun.chip_id = chipProcessedImfile.chip_id
+    AND warpSkyCellMap.class_id = chipProcessedImfile.class_id
+WHERE
+--    warpRun.state = 'new'
+    fakeRun.state = 'full'
+    AND camRun.state = 'full'
+    AND chipRun.state = 'full'
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_tooverlap.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_tooverlap.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_tooverlap.sql	(revision 22158)
@@ -0,0 +1,30 @@
+SELECT
+    warpRun.warp_id,
+    warpRun.fake_id,
+    warpRun.workdir,
+    warpRun.tess_id,
+    warpRun.label,
+    rawExp.camera,
+    exp_id,
+    exp_tag,
+    warpRun.magiced
+FROM warpRun
+JOIN fakeRun
+    USING(fake_id)
+JOIN camRun
+    USING(cam_id)
+JOIN chipRun
+    USING(chip_id)
+JOIN rawExp
+    USING(exp_id)
+LEFT JOIN warpSkyCellMap
+    USING(warp_id)
+LEFT JOIN warpMask
+    ON warpRun.label = warpMask.label
+WHERE
+    warpRun.state = 'new'
+    AND fakeRun.state = 'full'
+    AND camRun.state = 'full'
+    AND chipRun.state = 'full'
+    AND warpSkyCellMap.warp_id IS NULL
+    AND warpMask.label IS NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_towarped.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_towarped.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_towarped.sql	(revision 22158)
@@ -0,0 +1,37 @@
+SELECT DISTINCT
+    warpSkyCellMap.warp_id,
+    warpSkyCellMap.skycell_id,
+    warpSkyCellMap.tess_id,
+    warpRun.fake_id,
+    camRun.cam_id,
+    rawExp.camera,
+    warpRun.workdir
+FROM warpRun
+JOIN warpSkyCellMap
+    USING(warp_id)
+JOIN fakeRun
+    USING(fake_id)
+JOIN camRun
+    USING(cam_id)
+JOIN chipRun
+    USING(chip_id)
+JOIN chipProcessedImfile
+    USING(chip_id)
+JOIN rawExp
+    ON chipRun.exp_id = rawExp.exp_id
+LEFT JOIN warpSkyfile
+    ON warpRun.warp_id = warpSkyfile.warp_id
+    AND warpSkyCellMap.skycell_id = warpSkyfile.skycell_id
+    AND warpSkyCellMap.tess_id = warpSkyfile.tess_id
+LEFT JOIN warpMask
+    ON warpRun.label = warpMask.label
+WHERE
+    warpRun.state = 'new'
+    AND fakeRun.state = 'full'
+    AND camRun.state = 'full'
+    AND chipRun.state = 'full'
+    AND warpSkyfile.warp_id IS NULL
+    AND warpSkyfile.skycell_id IS NULL
+    AND warpSkyfile.tess_id IS NULL
+    AND warpSkyCellMap.fault = 0
+    AND warpMask.label IS NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_warped.sql
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_warped.sql	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/share/warptool_warped.sql	(revision 22158)
@@ -0,0 +1,20 @@
+SELECT
+    warpSkyfile.*,
+    warpRun.state,
+    rawExp.exp_id,
+    rawExp.camera
+FROM warpRun
+JOIN warpSkyfile
+    USING(warp_id)
+JOIN fakeRun
+    ON warpRun.fake_id = fakeRun.fake_id
+JOIN camRun
+    ON camRun.cam_id   = fakeRun.cam_id
+JOIN chipRun
+    ON camRun.chip_id  = chipRun.chip_id
+JOIN rawExp
+    ON chipRun.exp_id  = rawExp.exp_id
+WHERE
+-- bogus test; just here so there there is a 'WHERE' stmt to append conditionals too
+-- XXX EAM : not needed: fix warptool.c
+    warpRun.warp_id is NOT NULL
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/.cvsignore	(revision 22158)
@@ -0,0 +1,32 @@
+.deps
+.gdb_history
+.libs
+Makefile
+Makefile.in
+config.h
+config.h.in
+stamp-h1
+*.la
+*.lo
+pxtoolsErrorCodes.c
+pxtoolsErrorCodes.h
+pxadmin
+pxinject
+pztool
+pzgetexp
+pzgetimfiles
+regtool
+guidetool
+chiptool
+camtool
+warptool
+difftool
+stacktool
+faketool
+dettool
+detselect
+pxdata.c
+magictool
+caltool
+flatcorr
+pstamptool
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/Makefile.am	(revision 22158)
@@ -0,0 +1,220 @@
+bin_PROGRAMS = \
+	caltool \
+	camtool \
+	chiptool \
+	detselect \
+	dettool \
+	difftool \
+	flatcorr \
+	magictool \
+	pstamptool \
+	pxadmin \
+	pxinject \
+	faketool \
+	pzgetexp \
+	pzgetimfiles \
+	pztool \
+	regtool \
+	stacktool \
+	warptool
+
+
+bin_SCRIPTS = \
+	fakemagic
+
+pkginclude_HEADERS = \
+	pxadmin.h \
+	pxcam.h \
+	pxchip.h \
+	pxconfig.h \
+	pxdata.h \
+	pxfake.h \
+	pxregister.h \
+	pxtag.h \
+	pxtools.h \
+	pxtoolsErrorCodes.h \
+	pxtree.h \
+	pxwarp.h
+
+noinst_HEADERS = \
+	caltool.h \
+	camtool.h \
+	chiptool.h \
+	detselect.h \
+	dettool.h \
+	difftool.h \
+	flatcorr.h \
+	faketool.h \
+	magictool.h \
+	pstamptool.h \
+	pxinject.h \
+	pzgetexp.h \
+	pzgetimfiles.h \
+	pztool.h \
+	regtool.h \
+	stacktool.h \
+	warptool.h
+
+lib_LTLIBRARIES = libpxtools.la
+libpxtools_la_CFLAGS	= $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+libpxtools_la_LIBS      = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS)
+libpxtools_la_LDFLAGS   = -release $(PACKAGE_VERSION)
+libpxtools_la_SOURCES   = \
+	pxcam.c \
+	pxchip.c \
+	pxconfig.c \
+	pxdata.c \
+	pxerrors.c \
+	pxfake.c \
+	pxfault.c \
+	pxregister.c \
+	pxtag.c \
+	pxtools.c \
+	pxtoolsErrorCodes.c \
+	pxtree.c \
+	pxwarp.c
+
+# for pxtools.h
+AM_CPPFLAGS = -I$(top_srcdir)/src$
+
+pztool_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS) 
+pztool_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+pztool_SOURCES = \
+    pztool.c \
+    pztoolConfig.c
+
+pstamptool_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS) 
+pstamptool_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+pstamptool_SOURCES = \
+    pstamptool.c \
+    pstamptoolConfig.c
+
+caltool_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+caltool_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+caltool_SOURCES = \
+    caltool.c \
+    caltoolConfig.c
+
+flatcorr_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+flatcorr_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+flatcorr_SOURCES = \
+    flatcorr.c \
+    flatcorrConfig.c
+
+regtool_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+regtool_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+regtool_SOURCES = \
+    regtool.c \
+    regtoolConfig.c
+
+chiptool_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+chiptool_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+chiptool_SOURCES = \
+    chiptool.c \
+    chiptoolConfig.c
+
+camtool_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+camtool_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+camtool_SOURCES = \
+    camtool.c \
+    camtoolConfig.c
+
+faketool_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+faketool_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+faketool_SOURCES = \
+    faketool.c \
+    faketoolConfig.c
+
+magictool_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+magictool_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+magictool_SOURCES = \
+    magictool.c \
+    magictoolConfig.c
+
+warptool_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+warptool_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+warptool_SOURCES = \
+    warptool.c \
+    warptoolConfig.c
+
+difftool_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+difftool_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+difftool_SOURCES = \
+    difftool.c \
+    difftoolConfig.c
+
+stacktool_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+stacktool_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+stacktool_SOURCES = \
+    stacktool.c \
+    stacktoolConfig.c
+
+pxadmin_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+pxadmin_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+pxadmin_SOURCES = \
+    pxadmin.c \
+    pxadminConfig.c
+
+pzgetexp_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+pzgetexp_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+pzgetexp_SOURCES = \
+    pzgetexp.c \
+    pzgetexpConfig.c
+
+pzgetimfiles_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+pzgetimfiles_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+pzgetimfiles_SOURCES = \
+    pzgetimfiles.c \
+    pzgetimfilesConfig.c
+
+dettool_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+dettool_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+dettool_SOURCES = \
+    dettool.c \
+    dettoolConfig.c \
+    dettool_correction.c \
+    dettool_detrunsummary.c \
+    dettool_normalizedexp.c \
+    dettool_normalizedimfile.c \
+    dettool_normalizedstat.c \
+    dettool_processedexp.c \
+    dettool_processedimfile.c \
+    dettool_residexp.c \
+    dettool_residimfile.c \
+    dettool_stack.c
+
+detselect_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+detselect_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+detselect_SOURCES = \
+    detselect.c \
+    detselectConfig.c
+
+pxinject_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+pxinject_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+pxinject_SOURCES = \
+    pxinject.c \
+    pxinjectConfig.c
+
+clean-local:
+	-rm -f TAGS
+# Tags for emacs
+tags:
+	etags `find . -name \*.[ch] -print`
+
+# Error codes.
+BUILT_SOURCES = pxtoolsErrorCodes.h pxtoolsErrorCodes.c
+CLEANFILES = pxtoolsErrorCodes.h pxtoolsErrorCodes.c
+EXTRA_DIST = pxtoolsErrorCodes.dat pxtoolsErrorCodes.c.in pxtoolsErrorCodes.h.in fakemagic
+
+pxtoolsErrorCodes.h : pxtoolsErrorCodes.dat pxtoolsErrorCodes.h.in
+	$(ERRORCODES) --data=pxtoolsErrorCodes.dat --outdir=. pxtoolsErrorCodes.h
+
+pxtoolsErrorCodes.c : pxtoolsErrorCodes.dat pxtoolsErrorCodes.c.in pxtoolsErrorCodes.h
+	$(ERRORCODES) --data=pxtoolsErrorCodes.dat --outdir=. pxtoolsErrorCodes.c
+
+BUILT_SOURCES += pxdata.c
+EXTRA_DIST += pxdata.c.template
+
+pxdata.c: $(srcdir)/pxdata.c.template $(srcdir)/Makefile
+	$(PERL) -pe 's|\@PKGDATADIR\@|$(pkgdatadir)|' $< > $@
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/caltool.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/caltool.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/caltool.c	(revision 22158)
@@ -0,0 +1,261 @@
+/*
+ * caltool.c
+ *
+ * Copyright (C) 2006-2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVB_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include <ippdb.h>
+
+#include "pxtools.h"
+#include "caltool.h"
+
+static bool adddbMode(pxConfig *config);
+static bool dbsMode(pxConfig *config);
+static bool addrunMode(pxConfig *config);
+static bool runsMode(pxConfig *config);
+
+# define MODECASE(caseName, func) \
+    case caseName: \
+    if (!func(config)) { \
+        goto FAIL; \
+    } \
+    break;
+
+int main(int argc, char **argv)
+{
+    psLibInit(NULL);
+
+    pxConfig *config = caltoolConfig(NULL, argc, argv);
+    if (!config) {
+        psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+        goto FAIL;
+    }
+
+    switch (config->mode) {
+        MODECASE(CALTOOL_MODE_ADDDB,        adddbMode);
+        MODECASE(CALTOOL_MODE_DBS,          dbsMode);
+        MODECASE(CALTOOL_MODE_ADDRUN,       addrunMode);
+        MODECASE(CALTOOL_MODE_RUNS,         runsMode);
+        default:
+            psAbort("invalid option (this should not happen)");
+    }
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(EXIT_SUCCESS);
+
+FAIL:
+    psErrorStackPrint(stderr, "\n");
+    int exit_status = pxerrorGetExitStatus();
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exit_status);
+}
+
+static bool adddbMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required 
+    PXOPT_LOOKUP_STR(dvodb, config->args, "-set_dvodb", true, false);
+
+    if (!calDBInsert(config->dbh,
+            0,       // cal_id
+            dvodb,
+            "active"    // state
+        )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+
+    }
+
+    return false;
+}
+
+
+static bool dbsMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = psStringCopy("SELECT * FROM calDB");
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("caltool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "calDB", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool addrunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required
+    PXOPT_LOOKUP_STR(cal_id, config->args, "-cal_id", true, false);
+    PXOPT_LOOKUP_STR(region, config->args, "-region", true, false);
+    PXOPT_LOOKUP_STR(last_step, config->args, "-last_step", true, false);
+    PXOPT_LOOKUP_STR(state, config->args, "-state", true, false);
+
+    if (!calRunInsert(config->dbh,
+            (psS64)atoll(cal_id),
+            region,
+            last_step,
+            state
+        )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+
+    }
+
+    return false;
+}
+
+
+static bool runsMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where,  "-cal_id",     "cal_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_BOOL(faulted, config->args, "-simple", false);
+
+    psString query = psStringCopy("SELECT * FROM calRun");
+
+    if (faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", "WHERE fault != 0");
+    } else {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", "WHERE fault = 0");
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " AND %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("caltool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "calRun", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/caltool.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/caltool.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/caltool.h	(revision 22158)
@@ -0,0 +1,35 @@
+/*
+ * caltool.h
+ *
+ * Copyright (C) 2006-2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef CALTOOL_H
+#define CALTOOL_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+    CALTOOL_MODE_NONE           = PXTOOL_MODE_NONE,
+    CALTOOL_MODE_DBS,
+    CALTOOL_MODE_ADDDB,
+    CALTOOL_MODE_ADDRUN,
+    CALTOOL_MODE_RUNS
+} caltoolMode;
+
+pxConfig *caltoolConfig(pxConfig *config, int argc, char **argv);
+
+#endif // CALTOOL_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/caltoolConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/caltoolConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/caltoolConfig.c	(revision 22158)
@@ -0,0 +1,104 @@
+/*
+ * caltoolConfig.c
+ *
+ * Copyright (C) 2006-2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <psmodules.h>
+
+#include "pxtools.h"
+#include "caltool.h"
+
+pxConfig *caltoolConfig(pxConfig *config, int argc, char **argv)
+{
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    pmConfigReadParamsSet(false);
+
+    // setup site config
+    config->modules = pmConfigRead(&argc, argv, NULL);
+    if (!config->modules) {
+        psError(PS_ERR_UNKNOWN, false, "Can't find site configuration");
+        psFree(config);
+        return NULL;
+    }
+
+    psTime *time = psTimeGetNow(PS_TIME_TAI);
+    psString now = psTimeToISO(time);
+    psFree(time);
+
+    // -adddb
+    psMetadata *adddbArgs = psMetadataAlloc();
+    psMetadataAddStr(adddbArgs, PS_LIST_TAIL, "-dvodb",  0,            "define DVO db (required)", NULL);
+
+    // -dbs
+    psMetadata *dbsArgs = psMetadataAlloc();
+    psMetadataAddU64(dbsArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(dbsArgs, PS_LIST_TAIL, "-simple", 0,            "use the simple output format", false);
+
+    // -addrun
+    psMetadata *addrunArgs = psMetadataAlloc();
+    psMetadataAddStr(addrunArgs, PS_LIST_TAIL, "-cal_id",  0,            "define calibration DB ID (required)", NULL);
+    psMetadataAddStr(addrunArgs, PS_LIST_TAIL, "-region",  0,            "define region (required)", NULL);
+    psMetadataAddStr(addrunArgs, PS_LIST_TAIL, "-last_step",  0,            "define last step (required)", NULL);
+    psMetadataAddStr(addrunArgs, PS_LIST_TAIL, "-state",  0,            "define state (required)", NULL);
+
+    // -runs
+    psMetadata *runsArgs = psMetadataAlloc();
+    psMetadataAddStr(runsArgs, PS_LIST_TAIL, "-cal_id",  0,            "search for calibration ID", NULL);
+    psMetadataAddU64(runsArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(runsArgs, PS_LIST_TAIL, "-faulted",  0,            "only return imfiles with a fault status set", false);
+    psMetadataAddBool(runsArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    psFree(now);
+
+    psMetadata *argSets = psMetadataAlloc();
+    psMetadata *modes = psMetadataAlloc();
+
+    PXOPT_ADD_MODE("-adddb",   "add a DVO calibration DB",        CALTOOL_MODE_ADDDB,     adddbArgs);
+    PXOPT_ADD_MODE("-dbs",     "list DVO calibration DBs",        CALTOOL_MODE_DBS,       dbsArgs);
+    PXOPT_ADD_MODE("-addrun",  "add the results of a calibration run",        CALTOOL_MODE_ADDRUN,    addrunArgs);
+    PXOPT_ADD_MODE("-runs",    "list the results of calibration runs",        CALTOOL_MODE_RUNS,      runsArgs);
+
+    if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
+        psError(PS_ERR_UNKNOWN, true, "option parsing failed");
+        psFree(argSets);
+        psFree(modes);
+        psFree(config);
+        return NULL;
+    }
+
+    psFree(argSets);
+    psFree(modes);
+
+    // define Database handle, if used
+    // do this last so we don't setup a connection before CLI options are
+    // validated
+    config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+    if (!config->dbh) {
+        psError(PS_ERR_UNKNOWN, false, "Can't configure database");
+        psFree(config);
+        return NULL;
+    }
+
+    return config;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/camtool.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/camtool.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/camtool.c	(revision 22158)
@@ -0,0 +1,1107 @@
+/*
+ * camtool.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include "pxtools.h"
+#include "pxcam.h"
+#include "camtool.h"
+
+static bool definebyqueryMode(pxConfig *config);
+static bool updaterunMode(pxConfig *config);
+static bool pendingexpMode(pxConfig *config);
+static bool pendingimfileMode(pxConfig *config);
+static bool addprocessedexpMode(pxConfig *config);
+static bool processedexpMode(pxConfig *config);
+static bool revertprocessedexpMode(pxConfig *config);
+static bool updateprocessedexpMode(pxConfig *config);
+static bool blockMode(pxConfig *config);
+static bool maskedMode(pxConfig *config);
+static bool unblockMode(pxConfig *config);
+static bool pendingcleanuprunMode(pxConfig *config);
+static bool pendingcleanupexpMode(pxConfig *config);
+static bool donecleanupMode(pxConfig *config);
+
+# define MODECASE(caseName, func) \
+    case caseName: \
+    if (!func(config)) { \
+        goto FAIL; \
+    } \
+    break;
+
+int main(int argc, char **argv)
+{
+    psLibInit(NULL);
+
+    pxConfig *config = camtoolConfig(NULL, argc, argv);
+    if (!config) {
+        psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+        goto FAIL;
+    }
+
+    switch (config->mode) {
+        MODECASE(CAMTOOL_MODE_DEFINEBYQUERY,        definebyqueryMode);
+        MODECASE(CAMTOOL_MODE_UPDATERUN,            updaterunMode);
+        MODECASE(CAMTOOL_MODE_PENDINGEXP,           pendingexpMode);
+        MODECASE(CAMTOOL_MODE_PENDINGIMFILE,        pendingimfileMode);
+        MODECASE(CAMTOOL_MODE_ADDPROCESSEDEXP,      addprocessedexpMode);
+        MODECASE(CAMTOOL_MODE_PROCESSEDEXP,         processedexpMode);
+        MODECASE(CAMTOOL_MODE_REVERTPROCESSEDEXP,   revertprocessedexpMode);
+        MODECASE(CAMTOOL_MODE_UPDATEPROCESSEDEXP,   updateprocessedexpMode);
+        MODECASE(CAMTOOL_MODE_BLOCK,                blockMode);
+        MODECASE(CAMTOOL_MODE_MASKED,               maskedMode);
+        MODECASE(CAMTOOL_MODE_UNBLOCK,              unblockMode);
+        MODECASE(CAMTOOL_MODE_PENDINGCLEANUPRUN,    pendingcleanuprunMode);
+        MODECASE(CAMTOOL_MODE_PENDINGCLEANUPEXP,    pendingcleanupexpMode);
+        MODECASE(CAMTOOL_MODE_DONECLEANUP,          donecleanupMode);
+        default:
+            psAbort("invalid option (this should not happen)");
+    }
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(EXIT_SUCCESS);
+
+FAIL:
+    psErrorStackPrint(stderr, "\n");
+    int exit_status = pxerrorGetExitStatus();
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exit_status);
+}
+
+
+static bool definebyqueryMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-chip_id", "chip_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_name", "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where, "-inst", "camera", "==");
+    PXOPT_COPY_STR(config->args, where, "-telescope", "telescope", "==");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_begin", "dateobs", ">=");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_end", "dateobs", "<=");
+    PXOPT_COPY_STR(config->args, where, "-exp_tag", "exp_tag", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_type", "exp_type", "==");
+    PXOPT_COPY_STR(config->args, where, "-filelevel", "filelevel", "==");
+    PXOPT_COPY_STR(config->args, where, "-reduction", "reduction", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter", "filter", "==");
+    PXOPT_COPY_F64(config->args, where, "-airmass_min", "airmass", ">=");
+    PXOPT_COPY_F64(config->args, where, "-airmass_max", "airmass", "<");
+    PXOPT_COPY_F64(config->args, where, "-ra_min", "ra", ">=");
+    PXOPT_COPY_F64(config->args, where, "-ra_max", "ra", "<");
+    PXOPT_COPY_F64(config->args, where, "-decl_min", "decl", ">=");
+    PXOPT_COPY_F64(config->args, where, "-decl_max", "decl", "<");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_min", "exp_time", ">=");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_max", "exp_time", "<");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_min", "sat_pixel_frac", ">=");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_max", "sat_pixel_frac", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_min", "bt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_max", "bt", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_min", "bg_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_max", "bg_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_min", "bg_mean_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_max", "bg_mean_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-alt_min", "alt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-alt_max", "alt", "<");
+    PXOPT_COPY_F64(config->args, where, "-az_min", "az", ">=");
+    PXOPT_COPY_F64(config->args, where, "-az_max", "az", "<");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp_min", "ccd_temp", ">=");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp_max", "ccd_temp", "<");
+    PXOPT_COPY_F64(config->args, where, "-posang_min", "posang", ">=");
+    PXOPT_COPY_F64(config->args, where, "-posang_max", "posang", "<");
+    PXOPT_COPY_STR(config->args, where, "-object", "object", "==");
+    PXOPT_COPY_F32(config->args, where, "-solang_min", "solang", ">=");
+    PXOPT_COPY_F32(config->args, where, "-solang_max", "solang", "<");
+
+    if (!psListLength(where->list)
+        && !psMetadataLookupBool(NULL, config->args, "-all")) {
+        psFree(where);
+        psError(PXTOOLS_ERR_DATA, false, "search parameters are required");
+        return false;
+    }
+
+    PXOPT_LOOKUP_STR(workdir, config->args, "-set_workdir", false, false);
+    PXOPT_LOOKUP_STR(label, config->args, "-set_label", false, false);
+    PXOPT_LOOKUP_STR(reduction, config->args, "-set_reduction", false, false);
+    PXOPT_LOOKUP_STR(expgroup, config->args, "-set_expgroup", false, false);
+    PXOPT_LOOKUP_STR(dvodb, config->args, "-set_dvodb", false, false);
+    PXOPT_LOOKUP_STR(tess_id, config->args, "-set_tess_id", false, false);
+    PXOPT_LOOKUP_STR(end_stage, config->args, "-set_end_stage", false, false);
+
+    // find the exp_id of all the exposures that we want to queue up.
+    psString query = pxDataGet("camtool_find_chip_id.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psFree(where);
+        return false;
+    }
+
+    // use psDBGenerateWhereSQL because the SQL yields an intermediate table
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psStringAppend(&query, "%s", whereClause);
+        psFree(whereClause);
+    }
+
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("camtool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // start a transaction so we don't end up with an exp without any associted
+    // imfiles
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(output);
+        return false;
+    }
+
+    // would could do this "all in the database" if we didn't want the option
+    // of changing the label/reduction/expgroup/dvodb/etc.  So we're pulling the
+    // data out so we have the option of changing these values or leaving the
+    // old values in place (i.e., passing the values through).
+
+    // loop over our list of chipRun rows
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *md = output->data[i];
+
+        chipRunRow *row = chipRunObjectFromMetadata(md);
+        if (!row) {
+            psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into chipRun");
+            psFree(output);
+            return false;
+        }
+
+        // queue the exp
+        if (!pxcamQueueByChipID(config,
+                    row->chip_id,
+                    workdir     ? workdir   : row->workdir,
+                    label       ? label     : row->label,
+                    reduction   ? reduction : row->reduction,
+                    expgroup    ? expgroup  : row->expgroup,
+                    dvodb       ? dvodb     : row->dvodb,
+                    tess_id     ? tess_id   : row->tess_id,
+                    end_stage   ? end_stage : row->end_stage
+        )) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false,
+                    "failed to trying to queue chip_id: %" PRId64, row->chip_id);
+            psFree(row);
+            psFree(output);
+            return false;
+        }
+        psFree(row);
+    }
+    psFree(output);
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool updaterunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-cam_id", "cam_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-chip_id", "chip_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_name", "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where, "-inst", "camera", "==");
+    PXOPT_COPY_STR(config->args, where, "-telescope", "telescope", "==");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_begin", "dateobs", ">=");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_end", "dateobs", "<=");
+    PXOPT_COPY_STR(config->args, where, "-exp_tag", "exp_tag", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_type", "exp_type", "==");
+    PXOPT_COPY_STR(config->args, where, "-filelevel", "filelevel", "==");
+    PXOPT_COPY_STR(config->args, where, "-reduction", "reduction", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter", "filter", "==");
+    PXOPT_COPY_F64(config->args, where, "-airmass_min", "airmass", ">=");
+    PXOPT_COPY_F64(config->args, where, "-airmass_max", "airmass", "<");
+    PXOPT_COPY_F64(config->args, where, "-ra_min", "ra", ">=");
+    PXOPT_COPY_F64(config->args, where, "-ra_max", "ra", "<");
+    PXOPT_COPY_F64(config->args, where, "-decl_min", "decl", ">=");
+    PXOPT_COPY_F64(config->args, where, "-decl_max", "decl", "<");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_min", "exp_time", ">=");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_max", "exp_time", "<");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_min", "sat_pixel_frac", ">=");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_max", "sat_pixel_frac", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_min", "bt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_max", "bt", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_min", "bg_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_max", "bg_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_min", "bg_mean_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_max", "bg_mean_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-alt_min", "alt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-alt_max", "alt", "<");
+    PXOPT_COPY_F64(config->args, where, "-az_min", "az", ">=");
+    PXOPT_COPY_F64(config->args, where, "-az_max", "az", "<");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp_min", "ccd_temp", ">=");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp_max", "ccd_temp", "<");
+    PXOPT_COPY_F64(config->args, where, "-posang_min", "posang", ">=");
+    PXOPT_COPY_F64(config->args, where, "-posang_max", "posang", "<");
+    PXOPT_COPY_STR(config->args, where, "-object", "object", "==");
+    PXOPT_COPY_F32(config->args, where, "-solang_min", "solang", ">=");
+    PXOPT_COPY_F32(config->args, where, "-solang_max", "solang", "<");
+
+    if (!psListLength(where->list)
+        && !psMetadataLookupBool(NULL, config->args, "-all")) {
+        psFree(where);
+        psError(PXTOOLS_ERR_DATA, false, "search parameters are required");
+        return false;
+    }
+
+    PXOPT_LOOKUP_STR(state, config->args, "-state", false, false);
+    PXOPT_LOOKUP_STR(label, config->args, "-label", false, false);
+
+    if ((!state) && (!label)) {
+        psError(PXTOOLS_ERR_DATA, false, "parameters are required");
+        psFree(where);
+        return false;
+    }
+
+    if (state) {
+        // set chipRun.state to state
+        if (!pxcamRunSetStateByQuery(config, where, state)) {
+            psFree(where);
+            return false;
+        }
+    }
+
+    if (label) {
+        // set chipRun.label to label
+        if (!pxcamRunSetLabelByQuery(config, where, label)) {
+            psFree(where);
+            return false;
+        }
+    }
+
+    psFree(where);
+
+    return true;
+}
+
+
+static bool pendingexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-cam_id", "cam_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-chip_id", "chip_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("camtool_find_pendingexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // use psDBGenerateWhereSQL because the SQL yields an intermediate table
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psStringAppend(&query, "%s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("camtool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negate simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "camPendingExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool pendingimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-cam_id",   "cam_id",   "==");
+    PXOPT_COPY_S64(config->args, where, "-chip_id",  "chip_id",  "==");
+    PXOPT_COPY_STR(config->args, where, "-class",    "class",    "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
+
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("camtool_find_pendingimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // use psDBGenerateWhereSQL because the SQL yields an intermediate table
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psStringAppend(&query, "%s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("camtool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negate simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "chipProcessedImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool addprocessedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required
+    PXOPT_LOOKUP_S64(cam_id, config->args, "-cam_id", true, false);
+    PXOPT_LOOKUP_STR(uri, config->args, "-uri", true, false);
+
+    // optional
+    PXOPT_LOOKUP_F32(bg, config->args, "-bg", false, false);
+    PXOPT_LOOKUP_F32(bg_stdev, config->args, "-bg_stdev", false, false);
+    PXOPT_LOOKUP_F32(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
+    PXOPT_LOOKUP_F32(bias, config->args,           "-bias", false, false);
+    PXOPT_LOOKUP_F32(bias_stdev, config->args,     "-bias_stdev", false, false);
+    PXOPT_LOOKUP_F32(fringe_0, config->args,       "-fringe_0", false, false);
+    PXOPT_LOOKUP_F32(fringe_1, config->args,       "-fringe_1", false, false);
+    PXOPT_LOOKUP_F32(fringe_2, config->args,       "-fringe_2", false, false);
+    PXOPT_LOOKUP_F32(sigma_ra, config->args, "-sigma_ra", false, false);
+    PXOPT_LOOKUP_F32(sigma_dec, config->args, "-sigma_dec", false, false);
+    PXOPT_LOOKUP_F32(ap_resid, config->args,       "-ap_resid", false, false);
+    PXOPT_LOOKUP_F32(ap_resid_stdev, config->args, "-ap_resid_stdev", false, false);
+    PXOPT_LOOKUP_F32(zp_mean, config->args, "-zp_mean", false, false);
+    PXOPT_LOOKUP_F32(zp_stdev, config->args, "-zp_stdev", false, false);
+    PXOPT_LOOKUP_F32(fwhm_major, config->args, "-fwhm_major", false, false);
+    PXOPT_LOOKUP_F32(fwhm_minor, config->args, "-fwhm_minor", false, false);
+    PXOPT_LOOKUP_F32(dtime_detrend, config->args, "-dtime_detrend", false, false);
+    PXOPT_LOOKUP_F32(dtime_photom, config->args, "-dtime_photom", false, false);
+    PXOPT_LOOKUP_F32(dtime_astrom, config->args, "-dtime_astrom", false, false);
+    PXOPT_LOOKUP_STR(hostname, config->args,       "-hostname", false, false);
+    PXOPT_LOOKUP_S32(n_stars, config->args,        "-n_stars", false, false);
+    PXOPT_LOOKUP_S32(n_extended, config->args,     "-n_extended", false, false);
+    PXOPT_LOOKUP_S32(n_cr, config->args,           "-n_cr", false, false);
+    PXOPT_LOOKUP_S32(n_astrom, config->args,       "-n_astrom", false, false);
+    PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+
+    // generate restrictions
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-cam_id",   "cam_id",   "==");
+
+    psString query = pxDataGet("camtool_find_pendingexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // use psDBGenerateWhereSQL because the SQL yields an intermediate table
+    if (psListLength(where->list)) {
+        psString whereClaus = psDBGenerateWhereSQL(where, NULL);
+	psStringAppend(&query, "%s", whereClaus);
+	psFree(whereClaus);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("camtool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(output);
+        return false;
+    }
+
+    camRunRow *pendingRow = camRunObjectFromMetadata(output->data[0]);
+    psFree(output);
+    camProcessedExpRow *row = camProcessedExpRowAlloc(
+            pendingRow->cam_id,
+            uri,
+            bg,
+            bg_stdev,
+            bg_mean_stdev,
+            bias,
+            bias_stdev,
+            fringe_0,
+            fringe_1,
+            fringe_2,
+            sigma_ra,
+            sigma_dec,
+            ap_resid,
+            ap_resid_stdev,
+            zp_mean,
+            zp_stdev,
+            fwhm_major,
+            fwhm_minor,
+            dtime_detrend,
+            dtime_photom,
+            dtime_astrom,
+            hostname,
+            n_stars,
+            n_extended,
+            n_cr,
+            n_astrom,
+            path_base,
+            code
+        );
+
+    if (!camProcessedExpInsertObject(config->dbh, row)) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(row);
+        psFree(pendingRow);
+        return false;
+    }
+
+    // since there is only one exp per 'run' set camRun.state = 'stop'
+    if (!pxcamRunSetState(config, row->cam_id, "full")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to change camRun.state for cam_id: %" PRId64, row->cam_id);
+        psFree(row);
+        psFree(pendingRow);
+        return false;
+    }
+
+    // NULL for end_stage means go as far as possible
+    // EAM : skip here if code != 0
+    // Also, we can run fake even if tess_id is not defined
+    if (code || (pendingRow->end_stage && psStrcasestr(pendingRow->end_stage, "cam"))) {
+        psFree(row);
+        psFree(pendingRow);
+        if (!psDBCommit(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        }
+        return true;
+    }
+    psFree(row);
+    // else continue on...
+
+    if (!pxfakeQueueByCamID(config,
+            pendingRow->cam_id,
+            pendingRow->workdir,
+            pendingRow->label,
+            pendingRow->reduction,
+            pendingRow->expgroup,
+            pendingRow->dvodb,
+            pendingRow->tess_id,
+            pendingRow->end_stage
+    )) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "failed to queue new fakeRun");
+        psFree(pendingRow);
+        return false;
+    }
+    psFree(pendingRow);
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool processedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
+
+    // generate restrictions
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-cam_id",   "cam_id",   "==");
+    PXOPT_COPY_S64(config->args, where, "-chip_id",  "chip_id",   "==");
+
+    psString query = pxDataGet("camtool_find_processedexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // use psDBGenerateWhereConditionalSQL with AND ... because the SQL ends in a WHERE
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", "AND camProcessedExp.fault != 0");
+    } else {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", "AND camProcessedExp.fault = 0");
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("camtool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negate simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "camProcessedExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool revertprocessedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-cam_id", "cam_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-chip_id", "chip_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_name", "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where, "-inst", "camera", "==");
+    PXOPT_COPY_STR(config->args, where, "-telescope", "telescope", "==");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_begin", "dateobs", ">=");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_end", "dateobs", "<=");
+    PXOPT_COPY_STR(config->args, where, "-exp_tag", "exp_tag", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_type", "exp_type", "==");
+    PXOPT_COPY_STR(config->args, where, "-filelevel", "filelevel", "==");
+    PXOPT_COPY_STR(config->args, where, "-reduction", "reduction", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter", "filter", "==");
+    PXOPT_COPY_F32(config->args, where, "-airmass_min", "airmass", ">=");
+    PXOPT_COPY_F32(config->args, where, "-airmass_max", "airmass", "<");
+    PXOPT_COPY_F64(config->args, where, "-ra_min", "ra", ">=");
+    PXOPT_COPY_F64(config->args, where, "-ra_max", "ra", "<");
+    PXOPT_COPY_F64(config->args, where, "-decl_min", "decl", ">=");
+    PXOPT_COPY_F64(config->args, where, "-decl_max", "decl", "<");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_min", "exp_time", ">=");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_max", "exp_time", "<");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_min", "sat_pixel_frac", ">=");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_max", "sat_pixel_frac", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_min", "bt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_max", "bt", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_min", "bg_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_max", "bg_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_min", "bg_mean_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_max", "bg_mean_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-alt_min", "alt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-alt_max", "alt", "<");
+    PXOPT_COPY_F64(config->args, where, "-az_min", "az", ">=");
+    PXOPT_COPY_F64(config->args, where, "-az_max", "az", "<");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp_min", "ccd_temp", ">=");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp_max", "ccd_temp", "<");
+    PXOPT_COPY_F64(config->args, where, "-posang_min", "posang", ">=");
+    PXOPT_COPY_F64(config->args, where, "-posang_max", "posang", "<");
+    PXOPT_COPY_STR(config->args, where, "-object", "object", "==");
+    PXOPT_COPY_F32(config->args, where, "-solang_min", "solang", ">=");
+    PXOPT_COPY_F32(config->args, where, "-solang_max", "solang", "<");
+
+    if (!psListLength(where->list) && !psMetadataLookupBool(NULL, config->args, "-all")) {
+        psFree(where);
+        psError(PXTOOLS_ERR_DATA, false, "search parameters are required");
+        return false;
+    }
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(where);
+        return false;
+    }
+
+    {
+	psString query = pxDataGet("camtool_reset_faulted_runs.sql");
+	if (!query) {
+	    psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+	    psFree(where);
+	    return false;
+	}
+
+	// use psDBGenerateWhereConditionalSQL with AND ... because the SQL ends in a WHERE
+	if (where && psListLength(where->list)) {
+	    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+	    psStringAppend(&query, " AND %s", whereClause);
+	    psFree(whereClause);
+	}
+
+	if (!p_psDBRunQuery(config->dbh, query)) {
+	    // rollback
+	    if (!psDBRollback(config->dbh)) {
+		psError(PS_ERR_UNKNOWN, false, "database error");
+	    }
+	    psError(PS_ERR_UNKNOWN, false, "database error");
+	    psFree(query);
+	    psFree(where);
+	    return false;
+	}
+	psFree(query);
+    }
+
+    {
+	psString query = pxDataGet("camtool_revertprocessedexp.sql");
+	if (!query) {
+	    // rollback
+	    if (!psDBRollback(config->dbh)) {
+		psError(PS_ERR_UNKNOWN, false, "database error");
+	    }
+	    psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+	    psFree(where);
+	    return false;
+	}
+
+	// use psDBGenerateWhereConditionalSQL with AND ... because the SQL ends in a WHERE
+	if (where && psListLength(where->list)) {
+	    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+	    psStringAppend(&query, " AND %s", whereClause);
+	    psFree(whereClause);
+	}
+
+	if (!p_psDBRunQuery(config->dbh, query)) {
+	    // rollback
+	    if (!psDBRollback(config->dbh)) {
+		psError(PS_ERR_UNKNOWN, false, "database error");
+	    }
+	    psError(PS_ERR_UNKNOWN, false, "database error");
+	    psFree(query);
+	    psFree(where);
+	    return false;
+	}
+	psFree(query);
+    }
+    psFree(where);
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool updateprocessedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_S16(code, config->args, "-code", true, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-cam_id",   "cam_id",   "==");
+    PXOPT_COPY_S64(config->args, where, "-chip_id",  "chip_id",  "==");
+    PXOPT_COPY_STR(config->args, where, "-class",    "class",    "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
+
+    if (!pxSetFaultCode(config->dbh, "camProcessedExp", where, code)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to set set fault flag");
+	psFree (where);
+        return false;
+    }
+    psFree (where);
+
+    return true;
+}
+
+
+static bool blockMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(label, config->args, "-label", true, false);
+
+    if (!camMaskInsert(config->dbh, label)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool maskedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = psStringCopy("SELECT * FROM camMask");
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("camtool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "camMask", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool unblockMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(label, config->args, "-label", true, false);
+
+    char *query = "DELETE FROM camMask WHERE label = '%s'";
+
+    if (!p_psDBRunQuery(config->dbh, query, label)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+static bool pendingcleanuprunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("camtool_pendingcleanuprun.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("camtool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "camPendingCleanupRun", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool pendingcleanupexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_S64(cam_id, config->args, "-cam_id", false, false);
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    if (cam_id) {
+        PXOPT_COPY_S64(config->args, where, "-cam_id", "cam_id", "==");
+    }
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("camtool_pendingcleanupexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("chiptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "camPendingCleanupExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool donecleanupMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("camtool_donecleanup.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("camtool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "camDoneCleanup", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/camtool.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/camtool.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/camtool.h	(revision 22158)
@@ -0,0 +1,45 @@
+/*
+ * camtool.h
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef CAMTOOL_H
+#define CAMTOOL_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+    CAMTOOL_MODE_NONE      = 0x0,
+    CAMTOOL_MODE_DEFINEBYQUERY,
+    CAMTOOL_MODE_UPDATERUN,
+    CAMTOOL_MODE_PENDINGEXP,
+    CAMTOOL_MODE_PENDINGIMFILE,
+    CAMTOOL_MODE_ADDPROCESSEDEXP,
+    CAMTOOL_MODE_PROCESSEDEXP,
+    CAMTOOL_MODE_REVERTPROCESSEDEXP,
+    CAMTOOL_MODE_UPDATEPROCESSEDEXP,
+    CAMTOOL_MODE_BLOCK,
+    CAMTOOL_MODE_MASKED,
+    CAMTOOL_MODE_UNBLOCK,
+    CAMTOOL_MODE_PENDINGCLEANUPRUN,
+    CAMTOOL_MODE_PENDINGCLEANUPEXP,
+    CAMTOOL_MODE_DONECLEANUP,
+} camtoolMode;
+
+pxConfig *camtoolConfig(pxConfig *config, int argc, char **argv);
+
+#endif // CAMTOOL_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/camtoolConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/camtoolConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/camtoolConfig.c	(revision 22158)
@@ -0,0 +1,334 @@
+/*
+ * camtoolConfig.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <math.h>
+#include <stdint.h>
+
+#include <psmodules.h>
+
+#include "pxtools.h"
+#include "camtool.h"
+
+pxConfig *camtoolConfig(pxConfig *config, int argc, char **argv)
+{
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    pmConfigReadParamsSet(false);
+
+    // setup site config
+    config->modules = pmConfigRead(&argc, argv, NULL);
+    if (!config->modules) {
+        psError(PS_ERR_UNKNOWN, false, "Can't find site configuration");
+        psFree(config);
+        return NULL;
+    }
+
+    // -definebyquery
+    // XXX need to allow multiple chip_ids
+    // XXX need to allow multiple exp_ids
+    psMetadata *definebydefinebyqueryArgs = psMetadataAlloc();
+    psMetadataAddS64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-chip_id",            0, "search by chip_id", 0);
+    psMetadataAddS64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-exp_id",  	     0, "search by exp_id", 0);
+    psMetadataAddStr(definebydefinebyqueryArgs, PS_LIST_TAIL, "-exp_name",  	     0, "search by exp_name", NULL);
+    psMetadataAddStr(definebydefinebyqueryArgs, PS_LIST_TAIL, "-inst",  	     0, "search for camera", NULL);
+    psMetadataAddStr(definebydefinebyqueryArgs, PS_LIST_TAIL, "-telescope",  	     0, "search for telescope", NULL);
+    psMetadataAddTime(definebydefinebyqueryArgs, PS_LIST_TAIL, "-dateobs_begin",     0, "search for exposures by time (>=)", NULL);
+    psMetadataAddTime(definebydefinebyqueryArgs, PS_LIST_TAIL, "-dateobs_end",       0, "search for exposures by time (<)", NULL);
+    psMetadataAddStr(definebydefinebyqueryArgs, PS_LIST_TAIL, "-exp_tag",            0, "search by exp_tag", NULL);
+    psMetadataAddStr(definebydefinebyqueryArgs, PS_LIST_TAIL, "-exp_type",  	     0, "search by exp_type", NULL);
+    psMetadataAddStr(definebydefinebyqueryArgs, PS_LIST_TAIL, "-filelevel",  	     0, "search by filelevel", NULL);
+    psMetadataAddStr(definebydefinebyqueryArgs, PS_LIST_TAIL, "-reduction",  	     0, "search by reduction class", NULL);
+    psMetadataAddStr(definebydefinebyqueryArgs, PS_LIST_TAIL, "-filter",  	     0, "search for filter", NULL);
+    psMetadataAddF64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-airmass_min",  	     0, "define min airmass", NAN);
+    psMetadataAddF64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-airmass_max",  	     0, "define max airmass", NAN);
+    psMetadataAddF64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-ra_min",  	     0, "define min", NAN);
+    psMetadataAddF64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-ra_max",  	     0, "define max", NAN);
+    psMetadataAddF64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-decl_min",  	     0, "define min", NAN);
+    psMetadataAddF64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-decl_max",  	     0, "define max", NAN);
+    psMetadataAddF32(definebydefinebyqueryArgs, PS_LIST_TAIL, "-exp_time_min",       0, "define min", NAN);
+    psMetadataAddF32(definebydefinebyqueryArgs, PS_LIST_TAIL, "-exp_time_max",       0, "define max", NAN);
+    psMetadataAddF32(definebydefinebyqueryArgs, PS_LIST_TAIL, "-sat_pixel_frac_min", 0, "define max fraction of saturated pixels", NAN);
+    psMetadataAddF32(definebydefinebyqueryArgs, PS_LIST_TAIL, "-sat_pixel_frac_max", 0, "define min fraction of saturated pixels", NAN);
+    psMetadataAddF64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-bg_min",  	     0, "define max", NAN);
+    psMetadataAddF64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-bg_max",  	     0, "define max", NAN);
+    psMetadataAddF64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-bg_stdev_min",       0, "define max", NAN);
+    psMetadataAddF64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-bg_stdev_max",       0, "define max", NAN);
+    psMetadataAddF64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-bg_mean_stdev_min",  0, "define max", NAN);
+    psMetadataAddF64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-bg_mean_stdev_max",  0, "define max", NAN);
+    psMetadataAddF64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-alt_min",            0, "define min", NAN);
+    psMetadataAddF64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-alt_max",  	     0, "define max", NAN);
+    psMetadataAddF64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-az_min",  	     0, "define min", NAN);
+    psMetadataAddF64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-az_max",  	     0, "define max", NAN);
+    psMetadataAddF32(definebydefinebyqueryArgs, PS_LIST_TAIL, "-ccd_temp_min",       0, "define min ccd tempature", NAN);
+    psMetadataAddF32(definebydefinebyqueryArgs, PS_LIST_TAIL, "-ccd_temp_max",       0, "define max ccd tempature", NAN);
+    psMetadataAddF64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-posang_min",  	     0, "define min rotator position angle", NAN);
+    psMetadataAddF64(definebydefinebyqueryArgs, PS_LIST_TAIL, "-posang_max",  	     0, "define max rotator position angle", NAN);
+    psMetadataAddStr(definebydefinebyqueryArgs, PS_LIST_TAIL, "-object",  	     0, "search by exposure object", NULL);
+    psMetadataAddF32(definebydefinebyqueryArgs, PS_LIST_TAIL, "-solang_min",  	     0, "define min solar angle", NAN);
+    psMetadataAddF32(definebydefinebyqueryArgs, PS_LIST_TAIL, "-solang_max",  	     0, "define max solar angle", NAN);
+
+    psMetadataAddStr(definebydefinebyqueryArgs, PS_LIST_TAIL, "-set_workdir",  	     0, "define workdir", NULL);
+    psMetadataAddStr(definebydefinebyqueryArgs, PS_LIST_TAIL, "-set_label",  	     0, "define label", NULL);
+    psMetadataAddStr(definebydefinebyqueryArgs, PS_LIST_TAIL, "-set_reduction",      0, "define reduction class", NULL);
+    psMetadataAddStr(definebydefinebyqueryArgs, PS_LIST_TAIL, "-set_expgroup",       0, "define exposure group", NULL);
+    psMetadataAddStr(definebydefinebyqueryArgs, PS_LIST_TAIL, "-set_dvodb",  	     0, "define DVO db", NULL);
+    psMetadataAddStr(definebydefinebyqueryArgs, PS_LIST_TAIL, "-set_tess_id",  	     0, "define tess ID", NULL);
+    psMetadataAddStr(definebydefinebyqueryArgs, PS_LIST_TAIL, "-set_end_stage",      0, "define end stage", NULL);
+    psMetadataAddBool(definebydefinebyqueryArgs, PS_LIST_TAIL, "-all",  	     0, "allow everything to be queued without search terms", false);
+
+    // -updaterun
+    // XXX need to allow multiple cam_ids
+    // XXX need to allow multiple chip_ids
+    // XXX need to allow multiple exp_ids
+    psMetadata *updaterunArgs = psMetadataAlloc();
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-cam_id",             0, "search by cam_id", 0);
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-chip_id",  		 0, "search by chip_id", 0);
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-exp_id",  		 0, "search by exp_id", 0);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-exp_name",  	 0, "search by exp_name", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-inst",  		 0, "search for camera", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-telescope",  	 0, "search for telescope", NULL);
+    psMetadataAddTime(updaterunArgs, PS_LIST_TAIL, "-dateobs_begin", 	 0, "search for exposures by time (>=)", NULL);
+    psMetadataAddTime(updaterunArgs, PS_LIST_TAIL, "-dateobs_end", 	 0, "search for exposures by time (<)", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-exp_tag",  		 0, "search by exp_tag", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-exp_type",  	 0, "search by exp_type", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-filelevel",  	 0, "search by filelevel", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-reduction",  	 0, "search by reduction class", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-filter",  		 0, "search for filter", NULL);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-airmass_min",  	 0, "define min airmass", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-airmass_max",  	 0, "define max airmass", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-ra_min",  		 0, "define min", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-ra_max",  		 0, "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-decl_min",  	 0, "define min", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-decl_max",  	 0, "define max", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-exp_time_min",  	 0, "define min", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-exp_time_max",  	 0, "define max", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-sat_pixel_frac_min", 0, "define max fraction of saturated pixels", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-sat_pixel_frac_max", 0, "define min fraction of saturated pixels", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_min",  		 0, "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_max",  		 0, "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_stdev_min",  	 0, "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_stdev_max",  	 0, "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_mean_stdev_min",  0, "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_mean_stdev_max",  0, "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-alt_min",  		 0, "define min", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-alt_max",  		 0, "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-az_min",  		 0, "define min", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-az_max",  		 0, "define max", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-ccd_temp_min",  	 0, "define min ccd tempature", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-ccd_temp_max",  	 0, "define max ccd tempature", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-posang_min",  	 0, "define min rotator position angle", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-posang_max",  	 0, "define max rotator position angle", NAN);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-object",  		 0, "search by exposure object", NULL);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-solang_min",  	 0, "define min solar angle", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-solang_max",  	 0, "define max solar angle", NAN);
+
+    psMetadataAddBool(updaterunArgs, PS_LIST_TAIL, "-all",               0, "allow everything to be queued without search terms", false);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-state",              0, "set state", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-label",              0, "set label", NULL);
+
+    // -pendingexp
+    psMetadata *pendingexpArgs = psMetadataAlloc();
+    psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-cam_id",            0, "search by camtool ID", 0);
+    psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-chip_id",           0, "search by chiptool ID", 0);
+    psMetadataAddU64(pendingexpArgs, PS_LIST_TAIL, "-limit",             0, "limit result set to N items", 0);
+    psMetadataAddBool(pendingexpArgs, PS_LIST_TAIL, "-simple",           0, "use the simple output format", false);
+
+    // -pendingimfile
+    psMetadata *pendingimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(pendingimfileArgs, PS_LIST_TAIL, "-cam_id", 0,            "search by camtool ID", 0);
+    psMetadataAddS64(pendingimfileArgs, PS_LIST_TAIL, "-chip_id", 0,            "search by chiptool ID", 0);
+    psMetadataAddStr(pendingimfileArgs, PS_LIST_TAIL, "-class", 0,            "search by class", NULL);
+    psMetadataAddStr(pendingimfileArgs, PS_LIST_TAIL, "-class_id", 0,            "search by class ID", NULL);
+    psMetadataAddBool(pendingimfileArgs, PS_LIST_TAIL, "-simple", 0,            "use the simple output format", false);
+
+    // -addprocessedexp
+    psMetadata *addprocessedexpArgs = psMetadataAlloc();
+    psMetadataAddS64(addprocessedexpArgs, PS_LIST_TAIL, "-cam_id", 0,            "define camtool ID (required)", 0);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-uri", 0,            "define URI (required)", NULL);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-bg", 0,            "define exposure background", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-bg_stdev", 0,            "define exposure background stdev", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-bg_mean_stdev", 0,            "define exposure background mean stdev", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-bias",  0,            "define bias", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-bias_stdev",  0,            "define bias stdev", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-fringe_0",  0,            "define fringe term 0", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-fringe_1",  0,            "define fringe term 1", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-fringe_2",  0,            "define fringe term 2", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-sigma_ra", 0,            "define exposure E ra", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-sigma_dec", 0,            "define exposure E dec", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-ap_resid",  0,            "define aperture residual", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-ap_resid_stdev",  0,            "define aperture residual stdev", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-zp_mean", 0,            "define zero point mean", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-zp_stdev", 0,            "define zero point stdev", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-fwhm_major", 0,            "define FWHM (major axis; arcsec)", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-fwhm_minor", 0,            "define FWHM (minor axis; arcsec)", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-dtime_detrend", 0,            "define elapsed detrend processing time (seconds)", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-dtime_photom", 0,            "define elapsed photometry processing time (seconds)", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-dtime_astrom", 0,            "define elapsed astrometry processing time (seconds)", NAN);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-hostname", 0,            "define hostname", NULL);
+    psMetadataAddS32(addprocessedexpArgs, PS_LIST_TAIL, "-n_stars", 0,            "define number of stars", 0);
+    psMetadataAddS32(addprocessedexpArgs, PS_LIST_TAIL, "-n_extended", 0,            "define number of extended objects", 0);
+    psMetadataAddS32(addprocessedexpArgs, PS_LIST_TAIL, "-n_cr", 0,            "define number of cosmic rays", 0);
+    psMetadataAddS32(addprocessedexpArgs, PS_LIST_TAIL, "-n_astrom", 0,            "define number of astrometry reference objects", 0);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-path_base", 0,            "define base output location", NULL);
+    psMetadataAddS16(addprocessedexpArgs, PS_LIST_TAIL, "-code",  0,            "set fault code", 0);
+    psMetadataAddBool(addprocessedexpArgs, PS_LIST_TAIL, "-faulted",  0,            "only return imfiles with a fault status set", false);
+
+    // -processedexp
+    psMetadata *processedexpArgs = psMetadataAlloc();
+    psMetadataAddS64(processedexpArgs, PS_LIST_TAIL, "-cam_id", 0,            "search by camtool ID", 0);
+    psMetadataAddS64(processedexpArgs, PS_LIST_TAIL, "-chip_id", 0,            "search by chiptool ID", 0);
+    psMetadataAddU64(processedexpArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(processedexpArgs, PS_LIST_TAIL, "-simple", 0,            "use the simple output format", false);
+    psMetadataAddBool(processedexpArgs, PS_LIST_TAIL, "-faulted",  0,            "only return imfiles with a fault status set", false);
+
+    // -revertprocessedexp
+    // XXX need to allow multiple cam_ids
+    // XXX need to allow multiple chip_ids
+    // XXX need to allow multiple exp_ids
+    psMetadata *revertprocessedexpArgs = psMetadataAlloc();
+    psMetadataAddS64(revertprocessedexpArgs, PS_LIST_TAIL, "-cam_id",  0,            "search by cam_id", 0);
+    psMetadataAddS64(revertprocessedexpArgs, PS_LIST_TAIL, "-chip_id",  0,            "search by chip_id", 0);
+    psMetadataAddS64(revertprocessedexpArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exp_id", 0);
+    psMetadataAddStr(revertprocessedexpArgs, PS_LIST_TAIL, "-exp_name",  0,            "search by exp_name", NULL);
+    psMetadataAddStr(revertprocessedexpArgs, PS_LIST_TAIL, "-inst",  0,            "search for camera", NULL);
+    psMetadataAddStr(revertprocessedexpArgs, PS_LIST_TAIL, "-telescope",  0,            "search for telescope", NULL);
+    psMetadataAddTime(revertprocessedexpArgs, PS_LIST_TAIL, "-dateobs_begin", 0,            "search for exposures by time (>=)", NULL);
+    psMetadataAddTime(revertprocessedexpArgs, PS_LIST_TAIL, "-dateobs_end", 0,            "search for exposures by time (<)", NULL);
+    psMetadataAddStr(revertprocessedexpArgs, PS_LIST_TAIL, "-exp_tag",  0,            "search by exp_tag", NULL);
+    psMetadataAddStr(revertprocessedexpArgs, PS_LIST_TAIL, "-exp_type",  0,            "search by exp_type", NULL);
+    psMetadataAddStr(revertprocessedexpArgs, PS_LIST_TAIL, "-filelevel",  0,            "search by filelevel", NULL);
+    psMetadataAddStr(revertprocessedexpArgs, PS_LIST_TAIL, "-reduction",  0,            "search by reduction class", NULL);
+    psMetadataAddStr(revertprocessedexpArgs, PS_LIST_TAIL, "-filter",  0,            "search for filter", NULL);
+    psMetadataAddF32(revertprocessedexpArgs, PS_LIST_TAIL, "-airmass_min",  0,            "define min airmass", NAN);
+    psMetadataAddF32(revertprocessedexpArgs, PS_LIST_TAIL, "-airmass_max",  0,            "define max airmass", NAN);
+    psMetadataAddF64(revertprocessedexpArgs, PS_LIST_TAIL, "-ra_min",  0,            "define min", NAN);
+    psMetadataAddF64(revertprocessedexpArgs, PS_LIST_TAIL, "-ra_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedexpArgs, PS_LIST_TAIL, "-decl_min",  0,            "define min", NAN);
+    psMetadataAddF64(revertprocessedexpArgs, PS_LIST_TAIL, "-decl_max",  0,            "define max", NAN);
+    psMetadataAddF32(revertprocessedexpArgs, PS_LIST_TAIL, "-exp_time_min",  0,            "define min", NAN);
+    psMetadataAddF32(revertprocessedexpArgs, PS_LIST_TAIL, "-exp_time_max",  0,            "define max", NAN);
+    psMetadataAddF32(revertprocessedexpArgs, PS_LIST_TAIL, "-sat_pixel_frac_min",  0,            "define max fraction of saturated pixels", NAN);
+    psMetadataAddF32(revertprocessedexpArgs, PS_LIST_TAIL, "-sat_pixel_frac_max",  0,            "define min fraction of saturated pixels", NAN);
+    psMetadataAddF64(revertprocessedexpArgs, PS_LIST_TAIL, "-bg_min",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedexpArgs, PS_LIST_TAIL, "-bg_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedexpArgs, PS_LIST_TAIL, "-bg_stdev_min",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedexpArgs, PS_LIST_TAIL, "-bg_stdev_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedexpArgs, PS_LIST_TAIL, "-bg_mean_stdev_min",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedexpArgs, PS_LIST_TAIL, "-bg_mean_stdev_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedexpArgs, PS_LIST_TAIL, "-alt_min",  0,            "define min", NAN);
+    psMetadataAddF64(revertprocessedexpArgs, PS_LIST_TAIL, "-alt_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedexpArgs, PS_LIST_TAIL, "-az_min",  0,            "define min", NAN);
+    psMetadataAddF64(revertprocessedexpArgs, PS_LIST_TAIL, "-az_max",  0,            "define max", NAN);
+    psMetadataAddF32(revertprocessedexpArgs, PS_LIST_TAIL, "-ccd_temp_min",  0,            "define min ccd tempature", NAN);
+    psMetadataAddF32(revertprocessedexpArgs, PS_LIST_TAIL, "-ccd_temp_max",  0,            "define max ccd tempature", NAN);
+    psMetadataAddF64(revertprocessedexpArgs, PS_LIST_TAIL, "-posang_min",  0,            "define min rotator position angle", NAN);
+    psMetadataAddF64(revertprocessedexpArgs, PS_LIST_TAIL, "-posang_max",  0,            "define max rotator position angle", NAN);
+    psMetadataAddStr(revertprocessedexpArgs, PS_LIST_TAIL, "-object",  0,            "search by exposure object", NULL);
+    psMetadataAddF32(revertprocessedexpArgs, PS_LIST_TAIL, "-solang_min",  0,            "define min solar angle", NAN);
+    psMetadataAddF32(revertprocessedexpArgs, PS_LIST_TAIL, "-solang_max",  0,            "define max solar angle", NAN);
+
+    psMetadataAddBool(revertprocessedexpArgs, PS_LIST_TAIL, "-all",  0,            "allow everything to be queued without search terms", false);
+    psMetadataAddS16(revertprocessedexpArgs, PS_LIST_TAIL, "-code",  0,            "search by fault code", 0);
+
+
+    // -updateprocessedexp
+    psMetadata *updateprocessedexpArgs = psMetadataAlloc();
+    psMetadataAddS64(updateprocessedexpArgs, PS_LIST_TAIL, "-cam_id", 0,            "search by camtool ID", 0);
+    psMetadataAddS64(updateprocessedexpArgs, PS_LIST_TAIL, "-chip_id",  0,            "search by chiptool ID", 0);
+    psMetadataAddStr(updateprocessedexpArgs, PS_LIST_TAIL, "-class",  0,            "search by class", NULL);
+    psMetadataAddStr(updateprocessedexpArgs, PS_LIST_TAIL, "-class_id",  0,            "search by class ID", NULL);
+    psMetadataAddS16(updateprocessedexpArgs, PS_LIST_TAIL, "-code",  0,            "set fault code (required)", INT16_MAX);
+
+    // -block
+    psMetadata *blockArgs = psMetadataAlloc();
+    psMetadataAddStr(blockArgs, PS_LIST_TAIL, "-label",  0,            "name of a label to mask out (required)", NULL);
+
+    // -masked
+    psMetadata *maskedArgs = psMetadataAlloc();
+    psMetadataAddBool(maskedArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -unblock
+    psMetadata *unblockArgs = psMetadataAlloc();
+    psMetadataAddStr(unblockArgs, PS_LIST_TAIL, "-label",  0,            "name of a label to unmask (required)", NULL);
+
+    // -pendingcleanuprun
+    psMetadata *pendingcleanuprunArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingcleanuprunArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddBool(pendingcleanuprunArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanuprunArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -pendingcleanupexp
+    psMetadata *pendingcleanupexpArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingcleanupexpArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddS64(pendingcleanupexpArgs, PS_LIST_TAIL, "-cam_id", 0,            "search by camera ID", 0);
+    psMetadataAddStr(pendingcleanupexpArgs, PS_LIST_TAIL, "-exp_id",                 0,            "search by exp_id", NULL);
+    psMetadataAddBool(pendingcleanupexpArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanupexpArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -donecleanup
+    psMetadata *donecleanupArgs = psMetadataAlloc();
+    psMetadataAddStr(donecleanupArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddBool(donecleanupArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(donecleanupArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    psMetadata *argSets = psMetadataAlloc();
+    psMetadata *modes = psMetadataAlloc();
+
+    PXOPT_ADD_MODE("-definebyquery",        "create runs from chip stage",    	    CAMTOOL_MODE_DEFINEBYQUERY, definebydefinebyqueryArgs);
+    PXOPT_ADD_MODE("-updaterun",            "change cam run properties",      	    CAMTOOL_MODE_UPDATERUN,      updaterunArgs);
+    PXOPT_ADD_MODE("-pendingexp",           "show pending exposures",         	    CAMTOOL_MODE_PENDINGEXP,    pendingexpArgs);
+    PXOPT_ADD_MODE("-pendingimfile",        "show pending imfiles",           	    CAMTOOL_MODE_PENDINGIMFILE, pendingimfileArgs);
+    PXOPT_ADD_MODE("-addprocessedexp",      "add a processed exposure",       	    CAMTOOL_MODE_ADDPROCESSEDEXP, addprocessedexpArgs);
+    PXOPT_ADD_MODE("-processedexp",         "show processed exposures",       	    CAMTOOL_MODE_PROCESSEDEXP,  processedexpArgs);
+    PXOPT_ADD_MODE("-revertprocessedexp",   "change procesed exp properties", 	    CAMTOOL_MODE_REVERTPROCESSEDEXP,  revertprocessedexpArgs);
+    PXOPT_ADD_MODE("-updateprocessedexp",   "undo a processed exposure",      	    CAMTOOL_MODE_UPDATEPROCESSEDEXP,updateprocessedexpArgs);
+    PXOPT_ADD_MODE("-block",                "set a label block",    		    CAMTOOL_MODE_BLOCK,         blockArgs);
+    PXOPT_ADD_MODE("-masked",               "show blocked labels",  		    CAMTOOL_MODE_MASKED,        maskedArgs);
+    PXOPT_ADD_MODE("-unblock",              "remove a label block", 		    CAMTOOL_MODE_UNBLOCK,       unblockArgs);
+    PXOPT_ADD_MODE("-pendingcleanuprun",    "show runs that need to be cleaned up", CAMTOOL_MODE_PENDINGCLEANUPRUN, pendingcleanuprunArgs);
+    PXOPT_ADD_MODE("-pendingcleanupexp",    "show exposures for cleanup runs",      CAMTOOL_MODE_PENDINGCLEANUPEXP, pendingcleanupexpArgs);
+    PXOPT_ADD_MODE("-donecleanup",          "show runs that have been cleaned",     CAMTOOL_MODE_DONECLEANUP,       donecleanupArgs);
+
+    if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
+        psError(PS_ERR_UNKNOWN, false, "option parsing failed");
+        psFree(argSets);
+        psFree(modes);
+        psFree(config);
+        return NULL;
+    }
+
+    psFree(argSets);
+    psFree(modes);
+
+    // define Database handle, if used
+    config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+    if (!config->dbh) {
+        psError(PS_ERR_UNKNOWN, false, "Can't configure database");
+        psFree(config);
+        return NULL;
+    }
+
+    return config;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/chiptool.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/chiptool.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/chiptool.c	(revision 22158)
@@ -0,0 +1,1182 @@
+/*
+ * chiptool.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "pxtools.h"
+#include "pxdata.h"
+
+#include "chiptool.h"
+#include "camtool.h"
+
+static bool definebyqueryMode(pxConfig *config);
+static bool updaterunMode(pxConfig *config);
+static bool pendingimfileMode(pxConfig *config);
+static bool addprocessedimfileMode(pxConfig *config);
+static bool processedimfileMode(pxConfig *config);
+static bool revertprocessedimfileMode(pxConfig *config);
+static bool updateprocessedimfileMode(pxConfig *config);
+static bool blockMode(pxConfig *config);
+static bool maskedMode(pxConfig *config);
+static bool unmaskedMode(pxConfig *config);
+static bool unblockMode(pxConfig *config);
+static bool pendingcleanuprunMode(pxConfig *config);
+static bool pendingcleanupimfileMode(pxConfig *config);
+static bool donecleanupMode(pxConfig *config);
+static bool runMode(pxConfig *config);
+
+static bool chipProcessedCompleteExp(pxConfig *config);
+
+# define MODECASE(caseName, func) \
+    case caseName: \
+    if (!func(config)) { \
+        goto FAIL; \
+    } \
+    break;
+
+int main(int argc, char **argv) {
+    psLibInit(NULL);
+
+    pxConfig *config = chiptoolConfig(NULL, argc, argv);
+    if (!config) {
+        psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+        goto FAIL;
+    }
+
+    switch (config->mode) {
+        MODECASE(CHIPTOOL_MODE_DEFINEBYQUERY,           definebyqueryMode);
+        MODECASE(CHIPTOOL_MODE_UPDATERUN,               updaterunMode);
+        MODECASE(CHIPTOOL_MODE_PENDINGIMFILE,           pendingimfileMode);
+        MODECASE(CHIPTOOL_MODE_ADDPROCESSEDIMFILE,      addprocessedimfileMode);
+        MODECASE(CHIPTOOL_MODE_PROCESSEDIMFILE,         processedimfileMode);
+        MODECASE(CHIPTOOL_MODE_REVERTPROCESSEDIMFILE,   revertprocessedimfileMode);
+        MODECASE(CHIPTOOL_MODE_UPDATEPROCESSEDIMFILE,updateprocessedimfileMode);
+        MODECASE(CHIPTOOL_MODE_BLOCK,                   blockMode);
+        MODECASE(CHIPTOOL_MODE_MASKED,                  maskedMode);
+        MODECASE(CHIPTOOL_MODE_UNMASKED,                unmaskedMode);
+        MODECASE(CHIPTOOL_MODE_UNBLOCK,                 unblockMode);
+        MODECASE(CHIPTOOL_MODE_PENDINGCLEANUPRUN,       pendingcleanuprunMode);
+        MODECASE(CHIPTOOL_MODE_PENDINGCLEANUPIMFILE,    pendingcleanupimfileMode);
+        MODECASE(CHIPTOOL_MODE_DONECLEANUP,             donecleanupMode);
+        MODECASE(CHIPTOOL_MODE_RUN,                     runMode);
+        default:
+            psAbort("invalid option (this should not happen)");
+    }
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(EXIT_SUCCESS);
+
+FAIL:
+    psErrorStackPrint(stderr, "\n");
+    int exit_status = pxerrorGetExitStatus();
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exit_status);
+}
+
+
+static bool definebyqueryMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_S64(exp_id, config->args, "-exp_id", false, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_name", "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where, "-inst", "camera", "==");
+    PXOPT_COPY_STR(config->args, where, "-telescope", "telescope", "==");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_begin", "dateobs", ">=");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_end", "dateobs", "<=");
+    PXOPT_COPY_STR(config->args, where, "-exp_tag", "exp_tag", "==");
+    PXOPT_COPY_STR(config->args, where, "-filelevel", "filelevel", "==");
+    PXOPT_COPY_STR(config->args, where, "-reduction", "reduction", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter", "filter", "==");
+    PXOPT_COPY_F64(config->args, where, "-airmass_min", "airmass", ">=");
+    PXOPT_COPY_F64(config->args, where, "-airmass_max", "airmass", "<");
+    PXOPT_COPY_F64(config->args, where, "-ra_min", "ra", ">=");
+    PXOPT_COPY_F64(config->args, where, "-ra_max", "ra", "<");
+    PXOPT_COPY_F64(config->args, where, "-decl_min", "decl", ">=");
+    PXOPT_COPY_F64(config->args, where, "-decl_max", "decl", "<");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_min", "exp_time", ">=");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_max", "exp_time", "<");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_min", "sat_pixel_frac", ">=");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_max", "sat_pixel_frac", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_min", "bg", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_max", "bg", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_min", "bg_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_max", "bg_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_min", "bg_mean_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_max", "bg_mean_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-alt_min", "alt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-alt_max", "alt", "<");
+    PXOPT_COPY_F64(config->args, where, "-az_min", "az", ">=");
+    PXOPT_COPY_F64(config->args, where, "-az_max", "az", "<");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp_min", "ccd_temp", ">=");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp_max", "ccd_temp", "<");
+    PXOPT_COPY_F64(config->args, where, "-posang_min", "posang", ">=");
+    PXOPT_COPY_F64(config->args, where, "-posang_max", "posang", "<");
+    PXOPT_COPY_STR(config->args, where, "-object", "object", "==");
+    PXOPT_COPY_F32(config->args, where, "-solang_min", "solang", ">=");
+    PXOPT_COPY_F32(config->args, where, "-solang_max", "solang", "<");
+    PXOPT_COPY_STR(config->args, where, "-comment", "comment", "LIKE");
+
+    if (!psListLength(where->list)
+        && !psMetadataLookupBool(NULL, config->args, "-all")) {
+        psFree(where);
+        psError(PXTOOLS_ERR_DATA, false, "search parameters are required");
+        return false;
+    }
+
+    PXOPT_LOOKUP_STR(workdir, config->args, "-set_workdir", false, false);
+    PXOPT_LOOKUP_STR(label, config->args, "-set_label", false, false);
+    PXOPT_LOOKUP_STR(reduction, config->args, "-set_reduction", false, false);
+    PXOPT_LOOKUP_STR(expgroup, config->args, "-set_expgroup", false, false);
+    PXOPT_LOOKUP_STR(dvodb, config->args, "-set_dvodb", false, false);
+    PXOPT_LOOKUP_STR(tess_id, config->args, "-set_tess_id", false, false);
+    PXOPT_LOOKUP_STR(end_stage, config->args, "-set_end_stage", false, false);
+
+    // default
+    PXOPT_COPY_STR(config->args, where, "-exp_type", "exp_type", "==");
+    PXOPT_LOOKUP_BOOL(pretend, config->args, "-pretend", false);
+
+    // find the exp_id of all the exposures that we want to queue up.
+    psString query = pxDataGet("chiptool_find_rawexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psFree(where);
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "rawExp");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+
+    psFree(where);
+
+    if (pretend) {
+        // then stop before running the query
+        fprintf(stderr, "%s\n", query);
+        psFree(query);
+        return true;
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("chiptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // start a transaction so we don't end up with an exp without any associted
+    // imfiles
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(output);
+        return false;
+    }
+
+    // loop over our list of exp_ids
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *md = output->data[i];
+
+        bool status;
+        psS64 exp_id = psMetadataLookupS64(&status, md, "exp_id");
+        if (!status) {
+            psError(PS_ERR_UNKNOWN, false, "failed to lookup value for exp_id");
+            psFree(output);
+            return false;
+        }
+
+        // queue the exp
+        if (!pxchipQueueByExpTag(config, exp_id, workdir, label, reduction, expgroup, dvodb, tess_id, end_stage)) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false,
+                    "failed to trying to queue exp_id: %" PRId64, exp_id);
+            psFree(output);
+            return false;
+        }
+    }
+    psFree(output);
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool updaterunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args,  where, "-chip_id", "chip_id", "==");
+    PXOPT_COPY_S64(config->args,  where, "-exp_id", "exp_id", "==");
+    PXOPT_COPY_STR(config->args,  where, "-exp_name", "exp_name", "==");
+    PXOPT_COPY_STR(config->args,  where, "-inst", "camera", "==");
+    PXOPT_COPY_STR(config->args,  where, "-telescope", "telescope", "==");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_begin", "dateobs", ">=");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_end", "dateobs", "<=");
+    PXOPT_COPY_STR(config->args,  where, "-exp_tag", "exp_tag", "==");
+    PXOPT_COPY_STR(config->args,  where, "-exp_type", "exp_type", "==");
+    PXOPT_COPY_STR(config->args,  where, "-filelevel", "filelevel", "==");
+    PXOPT_COPY_STR(config->args,  where, "-reduction", "reduction", "==");
+    PXOPT_COPY_STR(config->args,  where, "-filter", "filter", "==");
+    PXOPT_COPY_F64(config->args,  where, "-airmass_min", "airmass", ">=");
+    PXOPT_COPY_F64(config->args,  where, "-airmass_max", "airmass", "<");
+    PXOPT_COPY_F64(config->args,  where, "-ra_min", "ra", ">=");
+    PXOPT_COPY_F64(config->args,  where, "-ra_max", "ra", "<");
+    PXOPT_COPY_F64(config->args,  where, "-decl_min", "decl", ">=");
+    PXOPT_COPY_F64(config->args,  where, "-decl_max", "decl", "<");
+    PXOPT_COPY_F32(config->args,  where, "-exp_time_min", "exp_time", ">=");
+    PXOPT_COPY_F32(config->args,  where, "-exp_time_max", "exp_time", "<");
+    PXOPT_COPY_F32(config->args,  where, "-sat_pixel_frac_min", "sat_pixel_frac", ">=");
+    PXOPT_COPY_F32(config->args,  where, "-sat_pixel_frac_max", "sat_pixel_frac", "<");
+    PXOPT_COPY_F64(config->args,  where, "-bg_min", "bg", ">=");
+    PXOPT_COPY_F64(config->args,  where, "-bg_max", "bg", "<");
+    PXOPT_COPY_F64(config->args,  where, "-bg_stdev_min", "bg_stdev", ">=");
+    PXOPT_COPY_F64(config->args,  where, "-bg_stdev_max", "bg_stdev", "<");
+    PXOPT_COPY_F64(config->args,  where, "-bg_mean_stdev_min", "bg_mean_stdev", ">=");
+    PXOPT_COPY_F64(config->args,  where, "-bg_mean_stdev_max", "bg_mean_stdev", "<");
+    PXOPT_COPY_F64(config->args,  where, "-alt_min", "alt", ">=");
+    PXOPT_COPY_F64(config->args,  where, "-alt_max", "alt", "<");
+    PXOPT_COPY_F64(config->args,  where, "-az_min", "az", ">=");
+    PXOPT_COPY_F64(config->args,  where, "-az_max", "az", "<");
+    PXOPT_COPY_F32(config->args,  where, "-ccd_temp_min", "ccd_temp", ">=");
+    PXOPT_COPY_F32(config->args,  where, "-ccd_temp_max", "ccd_temp", "<");
+    PXOPT_COPY_F64(config->args,  where, "-posang_min", "posang", ">=");
+    PXOPT_COPY_F64(config->args,  where, "-posang_max", "posang", "<");
+    PXOPT_COPY_STR(config->args,  where, "-object", "object", "==");
+    PXOPT_COPY_F32(config->args,  where, "-solang_min", "solang", ">=");
+    PXOPT_COPY_F32(config->args,  where, "-solang_max", "solang", "<");
+    PXOPT_COPY_STR(config->args,  where, "-label", "label", "==");
+
+    if (!psListLength(where->list)
+        && !psMetadataLookupBool(NULL, config->args, "-all")) {
+        psFree(where);
+        where = NULL;
+        psError(PXTOOLS_ERR_DATA, false, "search parameters are required");
+        return false;
+    }
+
+    PXOPT_LOOKUP_STR(state, config->args, "-state", false, false);
+    PXOPT_LOOKUP_STR(label, config->args, "-set_label", false, false);
+
+    if ((!state) && (!label)) {
+        psError(PXTOOLS_ERR_DATA, false, "parameters are required");
+        psFree(where);
+        return false;
+    }
+
+    if (state) {
+        // set chipRun.state to state
+        if (!pxchipRunSetStateByQuery(config, where, state)) {
+            psFree(where);
+            return false;
+        }
+    }
+
+    if (label) {
+        // set chipRun.label to label
+        if (!pxchipRunSetLabelByQuery(config, where, label)) {
+            psFree(where);
+            return false;
+        }
+    }
+
+    psFree(where);
+
+    return true;
+}
+
+
+static bool pendingimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-chip_id", "chipRun.chip_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "rawExp.exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "rawImfile.class_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-inst", "rawExp.telescope", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter", "rawExp.filter", "==");
+
+    psString query = pxDataGet("chiptool_pendingimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("chiptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "chipPendingImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool addprocessedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // chip_id, ext_tag, class_id are required
+    PXOPT_LOOKUP_S64(chip_id, config->args, "-chip_id", true, false);
+    PXOPT_LOOKUP_S64(exp_id, config->args, "-exp_id", true, false);
+    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false);
+
+    // optional
+    PXOPT_LOOKUP_STR(uri, config->args,            "-uri", false, false);
+    PXOPT_LOOKUP_F32(bg, config->args,             "-bg", false, false);
+    PXOPT_LOOKUP_F32(bg_stdev, config->args,       "-bg_stdev", false, false);
+    PXOPT_LOOKUP_F32(bg_mean_stdev, config->args,  "-bg_mean_stdev", false, false);
+    PXOPT_LOOKUP_F32(bias, config->args,           "-bias", false, false);
+    PXOPT_LOOKUP_F32(bias_stdev, config->args,     "-bias_stdev", false, false);
+    PXOPT_LOOKUP_F32(fringe_0, config->args,       "-fringe_0", false, false);
+    PXOPT_LOOKUP_F32(fringe_1, config->args,       "-fringe_1", false, false);
+    PXOPT_LOOKUP_F32(fringe_2, config->args,       "-fringe_2", false, false);
+    PXOPT_LOOKUP_F32(sigma_ra, config->args,       "-sigma_ra", false, false);
+    PXOPT_LOOKUP_F32(sigma_dec, config->args,      "-sigma_dec", false, false);
+    PXOPT_LOOKUP_F32(ap_resid, config->args,       "-ap_resid", false, false);
+    PXOPT_LOOKUP_F32(ap_resid_stdev, config->args, "-ap_resid_stdev", false, false);
+    PXOPT_LOOKUP_F32(zp_mean, config->args,        "-zp_mean", false, false);
+    PXOPT_LOOKUP_F32(zp_stdev, config->args,       "-zp_stdev", false, false);
+    PXOPT_LOOKUP_F32(fwhm_major, config->args,     "-fwhm_major", false, false);
+    PXOPT_LOOKUP_F32(fwhm_minor, config->args,     "-fwhm_minor", false, false);
+    PXOPT_LOOKUP_F32(dtime_detrend, config->args,  "-dtime_detrend", false, false);
+    PXOPT_LOOKUP_F32(dtime_photom,  config->args,  "-dtime_photom",  false, false);
+    PXOPT_LOOKUP_F32(dtime_astrom,  config->args,  "-dtime_astrom",  false, false);
+    PXOPT_LOOKUP_STR(hostname, config->args,       "-hostname", false, false);
+    PXOPT_LOOKUP_F32(n_stars, config->args, "-n_stars", false, false);
+    PXOPT_LOOKUP_F32(n_extended, config->args, "-n_extended", false, false);
+    PXOPT_LOOKUP_F32(n_cr, config->args, "-n_cr", false, false);
+    PXOPT_LOOKUP_F32(n_astrom, config->args, "-n_astrom", false, false);
+    PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
+
+    // default values
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!chipProcessedImfileInsert(config->dbh,
+                                   chip_id,
+                                   exp_id,
+                                   class_id,
+                                   uri,
+                                   bg,
+                                   bg_stdev,
+                                   bg_mean_stdev,
+                                   bias,
+                                   bias_stdev,
+                                   fringe_0,
+                                   fringe_1,
+                                   fringe_2,
+                                   sigma_ra,
+                                   sigma_dec,
+                                   ap_resid,
+                                   ap_resid_stdev,
+                                   zp_mean,
+                                   zp_stdev,
+                                   fwhm_major,
+                                   fwhm_minor,
+                                   dtime_detrend,
+                                   dtime_photom,
+                                   dtime_astrom,
+                                   hostname,
+                                   n_stars,
+                                   n_extended,
+                                   n_cr,
+                                   n_astrom,
+                                   path_base,
+                                   code
+            )) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // XXX I've decided to make the transaction cover the Exp migration as
+    // well.  Otherwise, if the last imfile in an exp is moved and the exp
+    // migration fails then the data base is left in a satuation where the exp
+    // migration can't happen.
+
+    if (!chipProcessedCompleteExp(config)) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool processedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-chip_id", "chipRun.chip_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "rawExp.exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_name", "rawExp.exp_name", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "chipProcessedImfile.class_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-inst", "rawExp.camera", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter", "rawExp.filter", "==");
+
+    psString query = pxDataGet("chiptool_processedimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", "AND chipProcessedImfile.fault != 0");
+    } else {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", "AND chipProcessedImfile.fault = 0");
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("chiptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "chipProcessedImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool revertprocessedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-chip_id", "chip_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_name", "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where, "-inst", "camera", "==");
+    PXOPT_COPY_STR(config->args, where, "-telescope", "telescope", "==");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_begin", "dateobs", ">=");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_end", "dateobs", "<=");
+    PXOPT_COPY_STR(config->args, where, "-exp_tag", "exp_tag", "==");
+    PXOPT_COPY_STR(config->args, where, "-filelevel", "filelevel", "==");
+    PXOPT_COPY_STR(config->args, where, "-reduction", "reduction", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter", "filter", "==");
+    PXOPT_COPY_F64(config->args, where, "-airmass_min", "airmass", ">=");
+    PXOPT_COPY_F64(config->args, where, "-airmass_max", "airmass", "<");
+    PXOPT_COPY_F64(config->args, where, "-ra_min", "ra", ">=");
+    PXOPT_COPY_F64(config->args, where, "-ra_max", "ra", "<");
+    PXOPT_COPY_F64(config->args, where, "-decl_min", "decl", ">=");
+    PXOPT_COPY_F64(config->args, where, "-decl_max", "decl", "<");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_min", "exp_time", ">=");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_max", "exp_time", "<");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_min", "sat_pixel_frac", ">=");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_max", "sat_pixel_frac", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_min", "bt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_max", "bt", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_min", "bg_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_max", "bg_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_min", "bg_mean_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_max", "bg_mean_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-alt_min", "alt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-alt_max", "alt", "<");
+    PXOPT_COPY_F64(config->args, where, "-az_min", "az", ">=");
+    PXOPT_COPY_F64(config->args, where, "-az_max", "az", "<");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp_min", "ccd_temp", ">=");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp_max", "ccd_temp", "<");
+    PXOPT_COPY_F64(config->args, where, "-posang_min", "posang", ">=");
+    PXOPT_COPY_F64(config->args, where, "-posang_max", "posang", "<");
+    PXOPT_COPY_STR(config->args, where, "-object", "object", "==");
+    PXOPT_COPY_F32(config->args, where, "-solang_min", "solang", ">=");
+    PXOPT_COPY_F32(config->args, where, "-solang_max", "solang", "<");
+    PXOPT_COPY_S16(config->args, where, "-code", "fault", "=");
+
+    if (!psListLength(where->list)
+        && !psMetadataLookupBool(NULL, config->args, "-all")) {
+        psFree(where);
+        psError(PXTOOLS_ERR_DATA, false, "search parameters are required");
+        return false;
+    }
+
+    psString query = pxDataGet("chiptool_revertprocessedimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psFree(where);
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "chipProcessedImfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    return true;
+}
+
+static bool updateprocessedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-chip_id", "chip_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id",  "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
+
+    PXOPT_LOOKUP_S16(code, config->args, "-code", true, false);
+
+    if (!pxSetFaultCode(config->dbh, "chipProcessedImfile", where, code)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to set set fault flag");
+        return false;
+    }
+    psFree(where);
+
+    return true;
+}
+
+
+static bool blockMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(label, config->args, "-label", true, false);
+
+    if (!chipMaskInsert(config->dbh, label)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool maskedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+
+    psMetadata *where = psMetadataAlloc();
+
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    if (where->list->n < 1) {
+        psFree(where);
+        where = NULL;
+    }
+
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = psStringCopy("SELECT * FROM chipMask");
+
+    if (where) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psFree(where);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("chiptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "chipMask", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+// return the list of labels which are NOT blocked
+static bool unmaskedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+
+    psMetadata *where = psMetadataAlloc();
+
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    if (where->list->n < 1) {
+        psFree(where);
+        where = NULL;
+    }
+
+    psString query = pxDataGet("chiptool_unmasked.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where) {
+        psString whereClause = psDBGenerateWhereSQL(where, "chipUnmask");
+        psFree(where);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("chiptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "chipUnmask", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool unblockMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(label, config->args, "-label", true, false);
+
+    char *query = "DELETE FROM chipMask WHERE label = '%s'";
+
+    if (!p_psDBRunQuery(config->dbh, query, label)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool pendingcleanuprunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("chiptool_pendingcleanuprun.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("chiptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "chipPendingCleanupRun", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool pendingcleanupimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_S64(chip_id, config->args, "-chip_id", false, false);
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    if (chip_id) {
+        PXOPT_COPY_S64(config->args, where, "-chip_id", "chip_id", "==");
+    }
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("chiptool_pendingcleanupimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("chiptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "chipPendingCleanupImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool donecleanupMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("chiptool_donecleanup.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("chiptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "chipDoneCleanup", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool runMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_STR(state, config->args, "-state", true, false);
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // make sure that the state string is valid
+    if (!pxIsValidState(state)) {
+        psError(PXTOOLS_ERR_DATA, false, "%s is not a valid state", state);
+        return false;
+    }
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+    PXOPT_COPY_STR(config->args, where, "-state", "state", "==");
+
+    psString query = pxDataGet("chiptool_run.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("chiptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "chipDoneCleanup", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool chipProcessedCompleteExp(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // look for completed chipPendingExp
+    // migrate them to chipProccessedExp & camPendingExp
+    psString query = pxDataGet("chiptool_completely_processed_exp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("chiptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *row = output->data[i];
+
+        chipRunRow *chipRun = chipRunObjectFromMetadata(row);
+        // set chipRun.state to 'stop'
+        if (!pxchipRunSetState(config, chipRun->chip_id, "full")) {
+            psError(PS_ERR_UNKNOWN, false, "failed to change chipRun.state for chip_id: %" PRId64, chipRun->chip_id);
+            psFree(chipRun);
+            psFree(output);
+            return false;
+        }
+
+        // should we stop here or proceed on to the cam stage?
+        // NULL for end_stage means go as far as possible
+        if (chipRun->end_stage && psStrcasestr(chipRun->end_stage, "chip")) {
+            psFree(chipRun);
+            continue;
+        }
+        // else continue on...
+
+        // camQueueChipID() can only be run after chipRun.state has been set to
+        // stop
+        if (!pxcamQueueByChipID(config,
+                    chipRun->chip_id,
+                    chipRun->workdir,
+                    chipRun->label,
+                    chipRun->reduction,
+                    chipRun->expgroup,
+                    chipRun->dvodb,
+                    chipRun->tess_id,
+                    chipRun->end_stage
+        )) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "failed to queue camPendingExp");
+            psFree(chipRun);
+            psFree(output);
+            return false;
+        }
+        psFree(chipRun);
+    }
+
+    psFree(output);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/chiptool.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/chiptool.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/chiptool.h	(revision 22158)
@@ -0,0 +1,47 @@
+/*
+ * chiptool.h
+ *
+ * Copyright (C) 2006-2008  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef CHIPTOOL_H
+#define CHIPTOOL_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+    CHIPTOOL_MODE_NONE      = 0x0,
+    CHIPTOOL_MODE_DEFINEBYQUERY,
+    CHIPTOOL_MODE_UPDATERUN,
+    CHIPTOOL_MODE_PENDINGIMFILE,
+    CHIPTOOL_MODE_ADDPROCESSEDIMFILE,
+    CHIPTOOL_MODE_PROCESSEDIMFILE,
+    CHIPTOOL_MODE_REVERTPROCESSEDIMFILE,
+    CHIPTOOL_MODE_UPDATEPROCESSEDIMFILE,
+    CHIPTOOL_MODE_BLOCK,
+    CHIPTOOL_MODE_MASKED,
+    CHIPTOOL_MODE_UNMASKED,
+    CHIPTOOL_MODE_UNBLOCK,
+    CHIPTOOL_MODE_RETRYPROCESSEDIMFILE,
+    CHIPTOOL_MODE_PENDINGCLEANUPRUN,
+    CHIPTOOL_MODE_PENDINGCLEANUPIMFILE,
+    CHIPTOOL_MODE_DONECLEANUP,
+    CHIPTOOL_MODE_RUN
+} chiptoolMode;
+
+pxConfig *chiptoolConfig(pxConfig *config, int argc, char **argv);
+
+#endif // CHIPTOOL_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/chiptoolConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/chiptoolConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/chiptoolConfig.c	(revision 22158)
@@ -0,0 +1,342 @@
+/*
+ * chiptoolConfig.c
+ *
+ * Copyright (C) 2006-2008  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+
+#include <psmodules.h>
+
+#include "pxtools.h"
+#include "chiptool.h"
+
+pxConfig *chiptoolConfig(pxConfig *config, int argc, char **argv)
+{
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    pmConfigReadParamsSet(false);
+
+    config->modules = pmConfigRead(&argc, argv, NULL);
+    if (! config->modules) {
+        psError(PS_ERR_UNKNOWN, false, "Can't find site configuration");
+        psFree(config);
+        return NULL;
+    }
+
+    // -definebyquery
+    psMetadata *definebyqueryArgs = psMetadataAlloc();
+
+    // XXX need to allow multiple exp_ids
+    psMetadataAddS64(definebyqueryArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exp_id", 0);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-exp_name",  0,            "search by exp_name", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-inst",  0,            "search for camera", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-telescope",  0,            "search for telescope", NULL);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-dateobs_begin", 0,            "search for exposures by time (>=)", NULL);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-dateobs_end", 0,            "search for exposures by time (<)", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-exp_tag",  0,            "search by exp_tag", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-exp_type",  0,            "search by exp_type", "object");
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-filelevel",  0,            "search by filelevel", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-reduction",  0,            "search by reduction class", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-filter",  0,            "search for filter", NULL);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-airmass_min",  0,            "define min airmass", NAN);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-airmass_max",  0,            "define max airmass", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-ra_min",  0,            "define min", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-ra_max",  0,            "define max", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-decl_min",  0,            "define min", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-decl_max",  0,            "define max", NAN);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-exp_time_min",  0,            "define min", NAN);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-exp_time_max",  0,            "define max", NAN);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-sat_pixel_frac_min",  0,            "define max fraction of saturated pixels", NAN);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-sat_pixel_frac_max",  0,            "define min fraction of saturated pixels", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-bg_min",  0,            "define max", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-bg_max",  0,            "define max", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-bg_stdev_min",  0,            "define max", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-bg_stdev_max",  0,            "define max", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-bg_mean_stdev_min",  0,            "define max", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-bg_mean_stdev_max",  0,            "define max", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-alt_min",  0,            "define min", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-alt_max",  0,            "define max", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-az_min",  0,            "define min", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-az_max",  0,            "define max", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-ccd_temp_min",  0,            "define min ccd tempature", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-ccd_temp_max",  0,            "define max ccd tempature", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-posang_min",  0,            "define min rotator position angle", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-posang_max",  0,            "define max rotator position angle", NAN);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-object",  0,            "search by exposure object", NULL);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-solang_min",  0,            "define min solar angle", NAN);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-solang_max",  0,            "define max solar angle", NAN);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-comment",     0,        "search by comment field (LIKE comparison)", NULL);
+
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-set_workdir",  0,            "define workdir", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-set_label",  0,            "define label", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-set_reduction",  0,            "define reduction class", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-set_expgroup",  0,            "define exposure group", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-set_dvodb",  0,            "define DVO db", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-set_tess_id",  0,            "define tessellation identifier", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-set_end_stage",  0,            "define end stage", NULL);
+    psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-pretend",  0,            "do not actually modify the database", false);
+    psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-all",  0,            "allow everything to be queued without search terms", false);
+
+    // -updaterun
+    psMetadata *updaterunArgs = psMetadataAlloc();
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-chip_id",              0,            "search by chip ID", 0);
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-exp_id",                 0,            "search by exp_id", 0);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-exp_name",             0,            "search by exp_name", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-inst",                 0,            "search for camera", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-telescope",            0,            "search for telescope", NULL);
+    psMetadataAddTime(updaterunArgs, PS_LIST_TAIL, "-dateobs_begin",       0,            "search for exposures by time (>=)", NULL);
+    psMetadataAddTime(updaterunArgs, PS_LIST_TAIL, "-dateobs_end",         0,            "search for exposures by time (<)", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-exp_tag",                 0,            "search by exp_tag", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-exp_type",             0,            "search by exp_type", "object");
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-filelevel",            0,            "search by filelevel", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-reduction",            0,            "search by reduction class", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-filter",                 0,            "search by filter", NULL);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-airmass_min",          0,            "search by min airmass", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-airmass_max",          0,            "search by max airmass", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-ra_min",                 0,            "search by min", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-ra_max",                 0,            "search by max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-decl_min",             0,            "search by min", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-decl_max",             0,            "search by max", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-exp_time_min",         0,            "search by min", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-exp_time_max",         0,            "search by max", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-sat_pixel_frac_min",  0,            "search by max fraction of saturated pixels", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-sat_pixel_frac_max",  0,            "search by min fraction of saturated pixels", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_min",            0,            "search by max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_max",            0,            "search by max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_stdev_min",        0,            "search by max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_stdev_max",        0,            "search by max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_mean_stdev_min",   0,            "search by max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_mean_stdev_max",   0,            "search by max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-alt_min",            0,            "search by min", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-alt_max",            0,            "search by max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-az_min",            0,            "search by min", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-az_max",            0,            "search by max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-ccd_temp_min",        0,            "search by min ccd tempature", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-ccd_temp_max",        0,            "search by max ccd tempature", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-posang_min",        0,            "search by min rotator position angle", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-posang_max",        0,            "search by max rotator position angle", NAN);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-object",            0,            "search by exposure object", NULL);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-solang_min",        0,            "search by min solar angle", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-solang_max",        0,            "search by max solar angle", NAN);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-label",               0,            "search by label", NULL);
+
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-state", 0,            "set state", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-set_label", 0,        "set label", NULL);
+    psMetadataAddBool(updaterunArgs, PS_LIST_TAIL, "-all",  0,            "allow everything to be queued without search terms", false);
+
+
+    // -pendingimfile
+    psMetadata *pendingimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(pendingimfileArgs, PS_LIST_TAIL, "-chip_id",  0,            "search by chip ID", 0);
+    psMetadataAddS64(pendingimfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exposure ID", 0);
+    psMetadataAddStr(pendingimfileArgs, PS_LIST_TAIL, "-class_id",  0,            "search by class ID", NULL);
+    psMetadataAddStr(pendingimfileArgs, PS_LIST_TAIL, "-inst",  0,            "search by camera of interest", NULL);
+    psMetadataAddStr(pendingimfileArgs, PS_LIST_TAIL, "-filter",  0,            "search by filter of interest", NULL);
+    psMetadataAddU64(pendingimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(pendingimfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -addprocessedimfile
+    psMetadata *addprocessedimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(addprocessedimfileArgs, PS_LIST_TAIL, "-chip_id",  0,            "define chip ID (required)", 0);
+    psMetadataAddS64(addprocessedimfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "define exposure ID (required)", 0);
+    psMetadataAddStr(addprocessedimfileArgs, PS_LIST_TAIL, "-class_id",  0,            "define class ID (required)", NULL);
+    psMetadataAddStr(addprocessedimfileArgs, PS_LIST_TAIL, "-uri",  0,            "define URL", NULL);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-bg",  0,            "define exposure background", NAN);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-bg_stdev",  0,            "define exposure background stdev", NAN);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-bg_mean_stdev",  0,            "define exposure background mean stdev", NAN);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-bias",  0,            "define bias", NAN);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-bias_stdev",  0,            "define bias stdev", NAN);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-fringe_0",  0,            "define fringe term 0", NAN);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-fringe_1",  0,            "define fringe term 1", NAN);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-fringe_2",  0,            "define fringe term 2", NAN);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-sigma_ra",  0,            "define error in RA", NAN);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-sigma_dec",  0,            "define error in DEC", NAN);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-ap_resid",  0,            "define aperture residual", NAN);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-ap_resid_stdev",  0,            "define aperture residual stdev", NAN);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-zp_mean",  0,            "define zero point", NAN);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-zp_stdev",  0,            "define zero point stdev", NAN);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-fwhm_major",  0,            "define fwhm (major axis; arcsec)", NAN);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-fwhm_minor",  0,            "define fwhm (minor axis; arcsec)", NAN);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-dtime_detrend",  0,            "define elapsed time for detrend (seconds)", NAN);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-dtime_photom",  0,            "define elapsed time for photometry (seconds)", NAN);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-dtime_astrom",  0,            "define elapsed time for astrometry (seconds)", NAN);
+    psMetadataAddStr(addprocessedimfileArgs, PS_LIST_TAIL, "-hostname",  0,            "define hostname", NULL);
+    psMetadataAddS32(addprocessedimfileArgs, PS_LIST_TAIL, "-n_stars",  0,            "define number of stars in image", 0);
+    psMetadataAddS32(addprocessedimfileArgs, PS_LIST_TAIL, "-n_extended",  0,            "define number of extended objects in image", 0);
+    psMetadataAddS32(addprocessedimfileArgs, PS_LIST_TAIL, "-n_cr",  0,            "define number of cosmic rays in image", 0);
+    psMetadataAddS32(addprocessedimfileArgs, PS_LIST_TAIL, "-n_astrom",  0,            "define number of astrometry stars used", 0);
+
+    psMetadataAddStr(addprocessedimfileArgs, PS_LIST_TAIL, "-path_base",  0,            "define base output location", NULL);
+    psMetadataAddS16(addprocessedimfileArgs, PS_LIST_TAIL, "-code",  0,            "set fault code", 0);
+
+    // -processedimfile
+    psMetadata *processedimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(processedimfileArgs, PS_LIST_TAIL, "-chip_id",  0,         "define chip ID", 0);
+    psMetadataAddS64(processedimfileArgs, PS_LIST_TAIL, "-exp_id",  0,          "define exposure ID", 0);
+    psMetadataAddStr(processedimfileArgs, PS_LIST_TAIL, "-exp_name",  0,        "define exposure name", NULL);
+    psMetadataAddStr(processedimfileArgs, PS_LIST_TAIL, "-class_id",  0,        "define class ID", NULL);
+    psMetadataAddStr(processedimfileArgs, PS_LIST_TAIL, "-inst",  0,            "define camera of interest", NULL);
+    psMetadataAddStr(processedimfileArgs, PS_LIST_TAIL, "-filter",  0,          "define filter of interest", NULL);
+    psMetadataAddU64(processedimfileArgs, PS_LIST_TAIL, "-limit",  0,           "limit result set to N items", 0);
+    psMetadataAddBool(processedimfileArgs, PS_LIST_TAIL, "-faulted",  0,        "only return imfiles with a fault status set", false);
+    psMetadataAddBool(processedimfileArgs, PS_LIST_TAIL, "-simple",  0,         "use the simple output format", false);
+
+    // -updateprocessedimfile
+    psMetadata *updateprocessedimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(updateprocessedimfileArgs, PS_LIST_TAIL, "-chip_id",  0,            "search by chip ID", 0);
+    psMetadataAddS64(updateprocessedimfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exposure ID", 0);
+    psMetadataAddStr(updateprocessedimfileArgs, PS_LIST_TAIL, "-class_id",  0,            "search by class ID", NULL);
+    psMetadataAddS16(updateprocessedimfileArgs, PS_LIST_TAIL, "-code",  0,            "set fault code (required)", 0);
+
+    // -revertprocessedimfile
+    psMetadata *revertprocessedimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(revertprocessedimfileArgs, PS_LIST_TAIL, "-chip_id", 0,            "search by chip ID", 0);
+    psMetadataAddS64(revertprocessedimfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exp_id", 0);
+    psMetadataAddStr(revertprocessedimfileArgs, PS_LIST_TAIL, "-exp_name",  0,            "search by exp_name", NULL);
+    psMetadataAddStr(revertprocessedimfileArgs, PS_LIST_TAIL, "-inst",  0,            "search for camera", NULL);
+    psMetadataAddStr(revertprocessedimfileArgs, PS_LIST_TAIL, "-telescope",  0,            "search for telescope", NULL);
+    psMetadataAddTime(revertprocessedimfileArgs, PS_LIST_TAIL, "-dateobs_begin", 0,            "search for exposures by time (>=)", NULL);
+    psMetadataAddTime(revertprocessedimfileArgs, PS_LIST_TAIL, "-dateobs_end", 0,            "search for exposures by time (<)", NULL);
+    psMetadataAddStr(revertprocessedimfileArgs, PS_LIST_TAIL, "-exp_tag",  0,            "search by exp_tag", NULL);
+    psMetadataAddStr(revertprocessedimfileArgs, PS_LIST_TAIL, "-exp_type",  0,            "search by exp_type", "object");
+    psMetadataAddStr(revertprocessedimfileArgs, PS_LIST_TAIL, "-filelevel",  0,            "search by filelevel", NULL);
+    psMetadataAddStr(revertprocessedimfileArgs, PS_LIST_TAIL, "-reduction",  0,            "search by reduction class", NULL);
+    psMetadataAddStr(revertprocessedimfileArgs, PS_LIST_TAIL, "-filter",  0,            "search for filter", NULL);
+    psMetadataAddF32(revertprocessedimfileArgs, PS_LIST_TAIL, "-airmass_min",  0,            "define min airmass", NAN);
+    psMetadataAddF32(revertprocessedimfileArgs, PS_LIST_TAIL, "-airmass_max",  0,            "define max airmass", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-ra_min",  0,            "define min", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-ra_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-decl_min",  0,            "define min", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-decl_max",  0,            "define max", NAN);
+    psMetadataAddF32(revertprocessedimfileArgs, PS_LIST_TAIL, "-exp_time_min",  0,            "define min", NAN);
+    psMetadataAddF32(revertprocessedimfileArgs, PS_LIST_TAIL, "-exp_time_max",  0,            "define max", NAN);
+    psMetadataAddF32(revertprocessedimfileArgs, PS_LIST_TAIL, "-sat_pixel_frac_min",  0,            "define max fraction of saturated pixels", NAN);
+    psMetadataAddF32(revertprocessedimfileArgs, PS_LIST_TAIL, "-sat_pixel_frac_max",  0,            "define min fraction of saturated pixels", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-bg_min",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-bg_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-bg_stdev_min",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-bg_stdev_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-bg_mean_stdev_min",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-bg_mean_stdev_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-alt_min",  0,            "define min", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-alt_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-az_min",  0,            "define min", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-az_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-ccd_temp_min",0,            "define min ccd tempature", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-ccd_temp_max",0,            "define max ccd tempature", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-posang_min",  0,            "define min rotator position angle", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-posang_max",  0,            "define max rotator position angle", NAN);
+    psMetadataAddStr(revertprocessedimfileArgs, PS_LIST_TAIL, "-object",  0,            "search by exposure object", NULL);
+    psMetadataAddF32(revertprocessedimfileArgs, PS_LIST_TAIL, "-solang_min",  0,            "define min solar angle", NAN);
+    psMetadataAddF32(revertprocessedimfileArgs, PS_LIST_TAIL, "-solang_max",  0,            "define max solar angle", NAN);
+
+    psMetadataAddBool(revertprocessedimfileArgs, PS_LIST_TAIL, "-all",  0,            "allow everything to be queued without search terms", false);
+    psMetadataAddS16(revertprocessedimfileArgs, PS_LIST_TAIL, "-code",  0,            "search by fault code", 0);
+
+    // -block
+    psMetadata *blockArgs = psMetadataAlloc();
+    psMetadataAddStr(blockArgs, PS_LIST_TAIL, "-label",  0,            "name of a label to mask out (required)", NULL);
+
+    // -masked
+    psMetadata *maskedArgs = psMetadataAlloc();
+    psMetadataAddStr(maskedArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddBool(maskedArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(maskedArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -unmasked
+    psMetadata *unmaskedArgs = psMetadataAlloc();
+    psMetadataAddStr(unmaskedArgs, PS_LIST_TAIL, "-label",  0,            "restrict to specified label", NULL);
+    psMetadataAddBool(unmaskedArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(unmaskedArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -unblock
+    psMetadata *unblockArgs = psMetadataAlloc();
+    psMetadataAddStr(unblockArgs, PS_LIST_TAIL, "-label",  0,            "name of a label to unmask (required)", NULL);
+
+    // -pendingcleanuprun
+    psMetadata *pendingcleanuprunArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingcleanuprunArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddBool(pendingcleanuprunArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanuprunArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -pendingcleanupimfile
+    psMetadata *pendingcleanupimfileArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingcleanupimfileArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddS64(pendingcleanupimfileArgs, PS_LIST_TAIL, "-chip_id", 0,          "search by chip ID", 0);
+    psMetadataAddStr(pendingcleanupimfileArgs, PS_LIST_TAIL, "-exp_id",                 0,            "search by exp_id", NULL);
+    psMetadataAddBool(pendingcleanupimfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanupimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -donecleanup
+    psMetadata *donecleanupArgs = psMetadataAlloc();
+    psMetadataAddStr(donecleanupArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddBool(donecleanupArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(donecleanupArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -run
+    psMetadata *runArgs = psMetadataAlloc();
+    psMetadataAddStr(runArgs, PS_LIST_TAIL, "-label",  0,       "search by label", NULL);
+    psMetadataAddBool(runArgs, PS_LIST_TAIL, "-simple",  0,     "use the simple output format", false);
+    psMetadataAddU64(runArgs, PS_LIST_TAIL, "-limit",  0,       "limit result set to N items", 0);
+    psMetadataAddStr(runArgs, PS_LIST_TAIL, "-state", 0,        "search by state (required)", NULL);
+
+    psMetadata *argSets = psMetadataAlloc();
+    psMetadata *modes = psMetadataAlloc();
+
+    PXOPT_ADD_MODE("-definebyquery",        "create runs from raw exposures",       CHIPTOOL_MODE_DEFINEBYQUERY,        definebyqueryArgs);
+    PXOPT_ADD_MODE("-updaterun",            "change chip run properties",           CHIPTOOL_MODE_UPDATERUN,            updaterunArgs);
+    PXOPT_ADD_MODE("-pendingimfile",        "show pending imfiles",        	    CHIPTOOL_MODE_PENDINGIMFILE,        pendingimfileArgs);
+    PXOPT_ADD_MODE("-addprocessedimfile",   "add a processed imfile",      	    CHIPTOOL_MODE_ADDPROCESSEDIMFILE,   addprocessedimfileArgs);
+    PXOPT_ADD_MODE("-processedimfile",      "show processed imfiles",      	    CHIPTOOL_MODE_PROCESSEDIMFILE,      processedimfileArgs);
+    PXOPT_ADD_MODE("-updateprocessedimfile","change procesed imfile properties",    CHIPTOOL_MODE_UPDATEPROCESSEDIMFILE,updateprocessedimfileArgs);
+    PXOPT_ADD_MODE("-revertprocessedimfile","undo a processed imfile",     	    CHIPTOOL_MODE_REVERTPROCESSEDIMFILE,revertprocessedimfileArgs);
+    PXOPT_ADD_MODE("-block",                "set a label block",           	    CHIPTOOL_MODE_BLOCK,                blockArgs);
+    PXOPT_ADD_MODE("-masked",               "show blocked labels",         	    CHIPTOOL_MODE_MASKED,               maskedArgs);
+    PXOPT_ADD_MODE("-unmasked",             "",                            	    CHIPTOOL_MODE_UNMASKED,             unmaskedArgs);
+    PXOPT_ADD_MODE("-unblock",              "remove a label block",        	    CHIPTOOL_MODE_UNBLOCK,              unblockArgs);
+    PXOPT_ADD_MODE("-pendingcleanuprun",    "show runs that need to be cleaned up", CHIPTOOL_MODE_PENDINGCLEANUPRUN,    pendingcleanuprunArgs);
+    PXOPT_ADD_MODE("-pendingcleanupimfile", "show runs that need to be cleaned up", CHIPTOOL_MODE_PENDINGCLEANUPIMFILE, pendingcleanupimfileArgs);
+    PXOPT_ADD_MODE("-donecleanup",          "show runs that have been cleaned",     CHIPTOOL_MODE_DONECLEANUP,          donecleanupArgs);
+    PXOPT_ADD_MODE("-run",                  "show runs",                            CHIPTOOL_MODE_RUN,                  runArgs);
+
+    if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
+        psError(PS_ERR_UNKNOWN, true, "option parsing failed");
+        psFree(argSets);
+        psFree(modes);
+        psFree(config);
+        return NULL;
+    }
+
+    psFree(argSets);
+    psFree(modes);
+
+    // define Database handle, if used
+    config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+    if (!config->dbh) {
+        psError(PS_ERR_UNKNOWN, false, "Can't configure database");
+        psFree(config);
+        return NULL;
+    }
+
+    return config;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/detselect.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/detselect.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/detselect.c	(revision 22158)
@@ -0,0 +1,220 @@
+/*
+ * detselect.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "pxtools.h"
+#include "detselect.h"
+
+static bool searchMode(pxConfig *config);
+static bool selectMode(pxConfig *config);
+
+# define MODECASE(caseName, func) \
+    case caseName: \
+    if (!func(config)) { \
+        goto FAIL; \
+    } \
+    break;
+
+int main(int argc, char **argv)
+{
+    psLibInit(NULL);
+
+    pxConfig *config = detselectConfig(NULL, argc, argv);
+    if (!config) {
+        psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+        goto FAIL;
+    }
+
+    switch (config->mode) {
+        MODECASE(DETSELECT_MODE_SEARCH,        searchMode);
+        MODECASE(DETSELECT_MODE_SELECT,        selectMode);
+        default:
+            psAbort("invalid option (this should not happen)");
+    }
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(EXIT_SUCCESS);
+
+FAIL:
+    psErrorStackPrint(stderr, "\n");
+    int exit_status = pxerrorGetExitStatus();
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exit_status);
+}
+
+static bool searchMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_BOOL(unlimit, config->args, "-unlimit", false);
+
+    PXOPT_LOOKUP_TIME(time, config->args, "-time", false, false);
+
+    psMetadata *where = psMetadataAlloc();
+
+    PXOPT_COPY_STR(config->args, where, "-inst",      "camera", "==");
+    PXOPT_COPY_STR(config->args, where, "-telescope", "telescope", "==");
+    PXOPT_COPY_STR(config->args, where, "-det_type",  "det_type", "==");
+    PXOPT_COPY_STR(config->args, where, "-type",      "det_type", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter",    "filter", "==");
+
+    // airmass_min  < airmass  < airmass_max
+    PXOPT_COPY_F32(config->args, where, "-airmass", "airmass_min", "<=");
+    PXOPT_COPY_F32(config->args, where, "-airmass", "airmass_max", ">=");
+
+    // exp_time_min < exp_time < exp_time_max
+    PXOPT_COPY_F32(config->args, where, "-exp_time", "exp_time_min", "<=");
+    PXOPT_COPY_F32(config->args, where, "-exp_time", "exp_time_max", ">=");
+
+    // ccd_temp_min < ccd_temp < ccd_temp_max
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp", "ccd_temp_min", "<=");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp", "ccd_temp_max", ">=");
+
+    PXOPT_COPY_F64(config->args, where, "-posang", "posang_min", "<=");
+    PXOPT_COPY_F64(config->args, where, "-posang", "posang_max", ">=");
+
+    // time_begin    < time     < time_end
+    // the == NULL tests invokes some psDB magic to make an OR
+    // conditional query
+    psMetadataAddTime(where, PS_LIST_TAIL, "time_begin", 0, "<=", time);
+    psMetadataAddTime(where, PS_LIST_TAIL, "time_begin", PS_META_DUPLICATE_OK, "==", NULL);
+    psMetadataAddTime(where, PS_LIST_TAIL, "time_end", 0, ">=", time);
+    psMetadataAddTime(where, PS_LIST_TAIL, "time_end", PS_META_DUPLICATE_OK, "==", NULL);
+
+    psString query = pxDataGet("detselect_search.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // use psDBGenerateWhereConditionalSQL with AND ... because the SQL ends in a WHERE
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+	psStringAppend(&query, " AND %s", whereClause);
+	psFree(whereClause);
+    }
+    psFree(where);
+
+    // we choose the single detrend image which matches all criteria and has
+    // the latest insertion date
+
+    // unless explicitly specified by the user, list all possible matches
+    if (!unlimit) {
+        psStringAppend(&query, " ORDER BY registered DESC LIMIT 1");
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        // XXX check psError here
+        psError(PS_ERR_UNKNOWN, false, "no detrend exposures found");
+        psFree(output);
+        return true;
+    }
+
+    // negate simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool selectMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
+
+    psString query = pxDataGet("detselect_select.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // use psDBGenerateWhereConditionalSQL with AND ... because the SQL ends in a WHERE
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        // XXX check psError here
+        psError(PS_ERR_UNKNOWN, false, "no detNormalizedImfile rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detNormalizedImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/detselect.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/detselect.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/detselect.h	(revision 22158)
@@ -0,0 +1,33 @@
+/*
+ * detselect.h
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef DETSELECT_H
+#define DETSELECT_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+    DETSELECT_MODE_NONE      = 0x0,
+    DETSELECT_MODE_SEARCH,
+    DETSELECT_MODE_SELECT,
+} detselectMode;
+
+pxConfig *detselectConfig(pxConfig *config, int argc, char **argv);
+
+#endif // DETSELECT_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/detselectConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/detselectConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/detselectConfig.c	(revision 22158)
@@ -0,0 +1,94 @@
+/*
+ * detselectConfig.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <psmodules.h>
+#include <math.h>
+
+#include "pxtools.h"
+#include "detselect.h"
+
+pxConfig *detselectConfig(pxConfig *config, int argc, char **argv)
+{
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    pmConfigReadParamsSet(false);
+
+    // setup site config
+    config->modules = pmConfigRead(&argc, argv, NULL);
+    if (!config->modules) {
+        psError(PS_ERR_UNKNOWN, false, "Can't find site configuration");
+        psFree(config);
+        return NULL;
+    }
+
+    // -search
+    psMetadata *searchArgs = psMetadataAlloc();
+    psMetadataAddStr(searchArgs, PS_LIST_TAIL, "-inst", 0,                     "search by camera", NULL);
+    psMetadataAddStr(searchArgs, PS_LIST_TAIL, "-telescope", 0,                     "search by telescope", NULL);
+    psMetadataAddStr(searchArgs, PS_LIST_TAIL, "-det_type", 0,                     "search by detrend type", NULL);
+    psMetadataAddStr(searchArgs, PS_LIST_TAIL, "-type", 0,                     "search by detrend type (alias for -det_type)", NULL);
+    psMetadataAddStr(searchArgs, PS_LIST_TAIL, "-filter", 0,                     "search by filter", NULL);
+    psMetadataAddF32(searchArgs, PS_LIST_TAIL, "-airmass", 0,                     "define airmass", NAN);
+    psMetadataAddF32(searchArgs, PS_LIST_TAIL, "-exp_time", 0,                     "search by exposure time", NAN);
+    psMetadataAddF32(searchArgs, PS_LIST_TAIL, "-ccd_temp", 0,                     "search by ccd tempature", NAN);
+    psMetadataAddF64(searchArgs, PS_LIST_TAIL, "-posang", 0,                     "search by rotator position angle", NAN);
+    psMetadataAddTime(searchArgs, PS_LIST_TAIL, "-time", 0,                      "define time for desired detrend data", NULL);
+    psMetadataAddBool(searchArgs, PS_LIST_TAIL, "-simple",  0,                      "use the simple output format", false);
+    psMetadataAddBool(searchArgs, PS_LIST_TAIL, "-unlimit",  0,                      "list all possible detruns, not just the best match", false);
+ 
+    // -select
+    psMetadata *selectArgs = psMetadataAlloc();
+    psMetadataAddStr(selectArgs, PS_LIST_TAIL, "-det_id", 0,                     "search by detrend ID", NULL);
+    psMetadataAddS32(selectArgs, PS_LIST_TAIL, "-iteration", 0,                     "search by iteration number", 0);
+    psMetadataAddStr(selectArgs, PS_LIST_TAIL, "-class_id", 0,                     "search by class ID", NULL);
+    psMetadataAddBool(selectArgs, PS_LIST_TAIL, "-simple",  0,                      "use the simple output format", false);
+    
+    psMetadata *argSets = psMetadataAlloc();
+    psMetadata *modes = psMetadataAlloc();
+
+    PXOPT_ADD_MODE("-search",  "search for an appropriate detrend", DETSELECT_MODE_SEARCH, searchArgs);
+    PXOPT_ADD_MODE("-select",  "retreive detrend information", DETSELECT_MODE_SELECT, selectArgs);
+
+    if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
+        psError(PS_ERR_UNKNOWN, true, "option parsing failed");
+        psFree(argSets);
+        psFree(modes);
+        psFree(config);
+        return NULL;
+    }
+
+    psFree(argSets);
+    psFree(modes);
+
+    // define Database handle, if used
+    config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+    if (!config->dbh) {
+        psError(PS_ERR_UNKNOWN, false, "Can't configure database");
+        psFree(config);
+        return NULL;
+    }
+
+    return config;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool.c	(revision 22158)
@@ -0,0 +1,2030 @@
+/*
+ * dettool.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+static bool pendingMode(pxConfig *config);
+static bool definebytagMode(pxConfig *config);
+static bool definebyqueryMode(pxConfig *config);
+static bool definebydetrunMode(pxConfig *config);
+static bool runsMode(pxConfig *config);
+static bool childlessrunMode(pxConfig *config);
+static bool inputMode(pxConfig *config);
+static bool rawMode(pxConfig *config);
+
+// run
+static bool updatedetrunMode(pxConfig *config);
+static bool rerunMode(pxConfig *config);
+// register
+static bool register_detrendMode(pxConfig *config);
+
+//static psArray *validDetInputClassIds(pxConfig *config, const char *det_id);
+//static psArray *searchInputImfiles(pxConfig *config, const char *det_id);
+static detInputExpRow *rawDetrenTodetInputExpRow(rawExpRow *rawExp, psS64 det_id, psS32 iteration);
+static psS32 incrementIteration(pxConfig *config, psS64 det_id);
+
+# define MODECASE(caseName, func) \
+    case caseName: \
+    if (!func(config)) { \
+        goto FAIL; \
+    } \
+    break;
+
+int main(int argc, char **argv)
+{
+    psLibInit(NULL);
+
+    pxConfig *config = dettoolConfig(NULL, argc, argv);
+    if (!config) {
+        psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+        goto FAIL;
+    }
+
+    switch (config->mode) {
+        MODECASE(DETTOOL_MODE_PENDING,          pendingMode);
+        MODECASE(DETTOOL_MODE_DEFINEBYTAG,      definebytagMode);
+        MODECASE(DETTOOL_MODE_DEFINEBYQUERY,    definebyqueryMode);
+        MODECASE(DETTOOL_MODE_DEFINEBYDETRUN,   definebydetrunMode);
+        MODECASE(DETTOOL_MODE_RUNS,             runsMode);
+        MODECASE(DETTOOL_MODE_CHILDLESSRUN,     childlessrunMode);
+        MODECASE(DETTOOL_MODE_INPUT,            inputMode);
+        MODECASE(DETTOOL_MODE_RAW,              rawMode);
+        // correction
+        MODECASE(DETTOOL_MODE_MAKECORRECTION,    makecorrectionMode);
+        MODECASE(DETTOOL_MODE_TOCORRECTEXP,      tocorrectexpMode);
+        MODECASE(DETTOOL_MODE_TOCORRECTIMFILE,   tocorrectimfileMode);
+        MODECASE(DETTOOL_MODE_ADDCORRECTIMFILE,  addcorrectimfileMode);
+        // imfile
+        MODECASE(DETTOOL_MODE_TOPROCESSEDIMFILE,toprocessedimfileMode);
+        MODECASE(DETTOOL_MODE_ADDPROCESSEDIMFILE,addprocessedimfileMode);
+        MODECASE(DETTOOL_MODE_PROCESSEDIMFILE,  processedimfileMode);
+        MODECASE(DETTOOL_MODE_REVERTPROCESSEDIMFILE, revertprocessedimfileMode);
+        MODECASE(DETTOOL_MODE_UPDATEPROCESSEDIMFILE, updateprocessedimfileMode);
+        MODECASE(DETTOOL_MODE_PENDINGCLEANUP_PROCESSEDIMFILE, pendingcleanup_processedimfileMode);
+        MODECASE(DETTOOL_MODE_DONECLEANUP_PROCESSEDIMFILE, donecleanup_processedimfileMode);
+        // exp
+        MODECASE(DETTOOL_MODE_TOPROCESSEDEXP,   toprocessedexpMode);
+        MODECASE(DETTOOL_MODE_ADDPROCESSEDEXP,  addprocessedexpMode);
+        MODECASE(DETTOOL_MODE_PROCESSEDEXP,     processedexpMode);
+        MODECASE(DETTOOL_MODE_REVERTPROCESSEDEXP, revertprocessedexpMode);
+        MODECASE(DETTOOL_MODE_UPDATEPROCESSEDEXP, updateprocessedexpMode);
+        MODECASE(DETTOOL_MODE_PENDINGCLEANUP_PROCESSEDEXP, pendingcleanup_processedexpMode);
+        MODECASE(DETTOOL_MODE_DONECLEANUP_PROCESSEDEXP, donecleanup_processedexpMode);
+        // stacked
+        MODECASE(DETTOOL_MODE_TOSTACKED,        tostackedMode);
+        MODECASE(DETTOOL_MODE_ADDSTACKED,       addstackedMode);
+        MODECASE(DETTOOL_MODE_STACKED,          stackedMode);
+        MODECASE(DETTOOL_MODE_REVERTSTACKED,    revertstackedMode);
+        MODECASE(DETTOOL_MODE_UPDATESTACKED,    updatestackedMode);
+        MODECASE(DETTOOL_MODE_PENDINGCLEANUP_STACKED, pendingcleanup_stackedMode);
+        MODECASE(DETTOOL_MODE_DONECLEANUP_STACKED, donecleanup_stackedMode);
+        // normalizedstat
+        MODECASE(DETTOOL_MODE_TONORMALIZEDSTAT, tonormalizedstatMode);
+        MODECASE(DETTOOL_MODE_ADDNORMALIZEDSTAT,addnormalizedstatMode);
+        MODECASE(DETTOOL_MODE_NORMALIZEDSTAT,   normalizedstatMode);
+        MODECASE(DETTOOL_MODE_REVERTNORMALIZEDSTAT, revertnormalizedstatMode);
+        MODECASE(DETTOOL_MODE_UPDATENORMALIZEDSTAT, updatenormalizedstatMode);
+        MODECASE(DETTOOL_MODE_PENDINGCLEANUP_NORMALIZEDSTAT, pendingcleanup_normalizedstatMode);
+        MODECASE(DETTOOL_MODE_DONECLEANUP_NORMALIZEDSTAT, donecleanup_normalizedstatMode);
+        // normalizedimfile
+        MODECASE(DETTOOL_MODE_TONORMALIZE,      tonormalizeMode);
+        MODECASE(DETTOOL_MODE_ADDNORMALIZEDIMFILE,addnormalizedimfileMode);
+        MODECASE(DETTOOL_MODE_NORMALIZEDIMFILE, normalizedimfileMode);
+        MODECASE(DETTOOL_MODE_REVERTNORMALIZEDIMFILE, revertnormalizedimfileMode);
+        MODECASE(DETTOOL_MODE_UPDATENORMALIZEDIMFILE, updatenormalizedimfileMode);
+        MODECASE(DETTOOL_MODE_PENDINGCLEANUP_NORMALIZEDIMFILE, pendingcleanup_normalizedimfileMode);
+        MODECASE(DETTOOL_MODE_DONECLEANUP_NORMALIZEDIMFILE, donecleanup_normalizedimfileMode);
+        // normalizedexp
+        MODECASE(DETTOOL_MODE_TONORMALIZEDEXP,  tonormalizedexpMode);
+        MODECASE(DETTOOL_MODE_ADDNORMALIZEDEXP, addnormalizedexpMode);
+        MODECASE(DETTOOL_MODE_NORMALIZEDEXP,    normalizedexpMode);
+        MODECASE(DETTOOL_MODE_REVERTNORMALIZEDEXP, revertnormalizedexpMode);
+        MODECASE(DETTOOL_MODE_UPDATENORMALIZEDEXP, updatenormalizedexpMode);
+        MODECASE(DETTOOL_MODE_PENDINGCLEANUP_NORMALIZEDEXP, pendingcleanup_normalizedexpMode);
+        MODECASE(DETTOOL_MODE_DONECLEANUP_NORMALIZEDEXP, donecleanup_normalizedexpMode);
+        // residimfile
+        MODECASE(DETTOOL_MODE_TORESIDIMFILE,    toresidimfileMode);
+        MODECASE(DETTOOL_MODE_ADDRESIDIMFILE,   addresidimfileMode);
+        MODECASE(DETTOOL_MODE_RESIDIMFILE,      residimfileMode);
+        MODECASE(DETTOOL_MODE_REVERTRESIDIMFILE,revertresidimfileMode);
+        MODECASE(DETTOOL_MODE_UPDATERESIDIMFILE, updateresidimfileMode);
+        MODECASE(DETTOOL_MODE_PENDINGCLEANUP_RESIDIMFILE, pendingcleanup_residimfileMode);
+        MODECASE(DETTOOL_MODE_DONECLEANUP_RESIDIMFILE, donecleanup_residimfileMode);
+        // residexp
+        MODECASE(DETTOOL_MODE_TORESIDEXP,       toresidexpMode);
+        MODECASE(DETTOOL_MODE_ADDRESIDEXP,      addresidexpMode);
+        MODECASE(DETTOOL_MODE_RESIDEXP,         residexpMode);
+        MODECASE(DETTOOL_MODE_REVERTRESIDEXP,   revertresidexpMode);
+        MODECASE(DETTOOL_MODE_UPDATERESIDEXP,   updateresidexpMode);
+        MODECASE(DETTOOL_MODE_PENDINGCLEANUP_RESIDEXP, pendingcleanup_residexpMode);
+        MODECASE(DETTOOL_MODE_DONECLEANUP_RESIDEXP, donecleanup_residexpMode);
+        // detrunsummary
+        MODECASE(DETTOOL_MODE_TODETRUNSUMMARY,  todetrunsummaryMode);
+        MODECASE(DETTOOL_MODE_ADDDETRUNSUMMARY, adddetrunsummaryMode);
+        MODECASE(DETTOOL_MODE_DETRUNSUMMARY,    detrunsummaryMode);
+        MODECASE(DETTOOL_MODE_REVERTDETRUNSUMMARY, revertdetrunsummaryMode);
+        MODECASE(DETTOOL_MODE_UPDATEDETRUNSUMMARY, updatedetrunsummaryMode);
+        MODECASE(DETTOOL_MODE_UPDATEDETRUN,     updatedetrunMode);
+        MODECASE(DETTOOL_MODE_RERUN,            rerunMode);
+        // register
+        MODECASE(DETTOOL_MODE_REGISTER_DETREND, register_detrendMode);
+        MODECASE(DETTOOL_MODE_REGISTER_DETREND_IMFILE, register_detrend_imfileMode);
+        default:
+            psAbort("invalid option (this should not happen)");
+    }
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(EXIT_SUCCESS);
+
+FAIL:
+    psErrorStackPrint(stderr, "\n");
+    int exit_status = pxerrorGetExitStatus();
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exit_status);
+}
+
+static bool pendingMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("dettool_pending.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+    
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_type", "exp_type", "==");
+    PXOPT_COPY_STR(config->args, where, "-inst", "camera", "==");
+    PXOPT_COPY_STR(config->args, where, "-telescope", "telescope", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter", "filter", "==");
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "rawExp");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "rawExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool definebytagMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // what type of detRun is this?
+    // required
+    PXOPT_LOOKUP_STR(det_type, config->args, "-det_type", true, false);
+    PXOPT_LOOKUP_STR(workdir, config->args, "-workdir", true, false);
+
+    // optional
+    PXOPT_LOOKUP_STR(filelevel, config->args, "-filelevel", false, false);
+    PXOPT_LOOKUP_STR(mode, config->args, "-mode", false, false);
+    // check mode
+    if (mode && !isValidMode(config, mode)) {
+        psError(PS_ERR_UNKNOWN, false, "invalud mode");
+        return false;
+    }
+    PXOPT_LOOKUP_STR(camera, config->args, "-inst", false, false);
+    PXOPT_LOOKUP_STR(telescope, config->args, "-telescope", false, false);
+    PXOPT_LOOKUP_STR(exp_type, config->args, "-exp_type", false, false);
+    PXOPT_LOOKUP_STR(filter, config->args, "-filter", false, false);
+
+    PXOPT_LOOKUP_F32(airmass_min, config->args, "-airmass_min", false, false);
+    PXOPT_LOOKUP_F32(airmass_max, config->args, "-airmass_max", false, false);
+    PXOPT_LOOKUP_F32(exp_time_min, config->args, "-exp_time_min", false, false);
+    PXOPT_LOOKUP_F32(exp_time_max, config->args, "-exp_time_max", false, false);
+    PXOPT_LOOKUP_F32(ccd_temp_min, config->args, "-ccd_temp_min", false, false);
+    PXOPT_LOOKUP_F32(ccd_temp_max, config->args, "-ccd_temp_max", false, false);
+    PXOPT_LOOKUP_F64(posang_min, config->args, "-posang_min", false, false);
+    PXOPT_LOOKUP_F64(posang_max, config->args, "-posang_max", false, false);
+    PXOPT_LOOKUP_F64(solang_min, config->args, "-solang_min", false, false);
+    PXOPT_LOOKUP_F64(solang_max, config->args, "-solang_max", false, false);
+    PXOPT_LOOKUP_TIME(time_begin, config->args, "-time_begin", false, false);
+    PXOPT_LOOKUP_TIME(time_end, config->args, "-time_end", false, false);
+    PXOPT_LOOKUP_TIME(use_begin, config->args, "-use_begin", false, false);
+    PXOPT_LOOKUP_TIME(use_end, config->args, "-use_end", false, false);
+    PXOPT_LOOKUP_STR(reduction, config->args, "-reduction", false, false);
+    PXOPT_LOOKUP_STR(label, config->args, "-label", false, false);
+
+    // default
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_TIME(registered, config->args, "-registered", false, false);
+
+    // we have to support multipe exp_ids
+    psMetadataItem *item = psMetadataLookup(config->args, "-exp_id");
+    if (!item) {
+        // this shouldn't actually happen when using psArgs
+        psError(PS_ERR_UNKNOWN, true, "-exp_id is required");
+        return false;
+    }
+    psMetadata *where = psMetadataAlloc();
+
+    // make sure that -exp_id was parsed correctly
+    // XXX this can be removed someday
+    // XXX Special case for a multi : move into a macro?
+    if (item->type == PS_DATA_METADATA_MULTI) {
+        psListIterator *iter = psListIteratorAlloc(item->data.list, 0, false);
+        psMetadataItem *mItem = NULL;
+        while ((mItem = psListGetAndIncrement(iter))) {
+            psString exp_id = mItem->data.V;
+            // if exp_id is NULL then it means that -exp_id has not been
+            // specified
+            if (!exp_id) {
+                psError(PS_ERR_UNKNOWN, true,
+                        "at least one -exp_id is required");
+                psFree(where);
+                return false;
+            }
+
+            if (!psMetadataAddStr(where, PS_LIST_TAIL, "exp_id",
+                 PS_META_DUPLICATE_OK, "==", exp_id)) {
+                psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+                psFree(iter);
+                psFree(where);
+                return false;
+            }
+        }
+        psFree(iter);
+    } else {
+        psAbort(                "-exp_id was not parsed correctly (this should not happen");
+    }
+
+    if (psListLength(where->list) < 1) {
+        psFree(where);
+        where = NULL;
+    }
+
+    // check that the specified exp_ids actually exist
+    psArray *detrendExps = rawExpSelectRowObjects(config->dbh, where, 0);
+    psFree(where);
+    if (!detrendExps) {
+        psError(PS_ERR_UNKNOWN, false, "no rawExp rows found");
+        return false;
+    }
+
+    // we should have one rawExp row per exp_id specified
+    if (psListLength(item->data.list) != psArrayLength(detrendExps)) {
+        psAbort(    "an -exp_id matched more then one rawExp (this should not happen");
+
+    }
+
+    // check to see if -filelevel was set on the command line
+    if (!filelevel) {
+        filelevel = psStringCopy(((rawExpRow *)detrendExps->data[0])->filelevel);
+    }
+
+    // start a transaction so we don't end up with childlessed det_ids
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(detrendExps);
+        return false;
+    }
+
+    // the first iteration is always 0
+    // XXX the camera name is set from the first inputExp
+    // XXX det_id
+    detRunInsert(config->dbh,
+                 0,
+                 0,
+                 det_type,
+                 mode,
+                 "run",
+                 filelevel,
+                 workdir,
+                 camera,
+                 telescope,
+                 exp_type,
+                 reduction,
+                 filter,
+                 airmass_min,
+                 airmass_max,
+                 exp_time_min,
+                 exp_time_max,
+                 ccd_temp_min,
+                 ccd_temp_max,
+                 posang_min,
+                 posang_max,
+                 registered,
+                 time_begin,
+                 time_end,
+                 use_begin,
+                 use_end,
+                 solang_min,
+                 solang_max,
+                 label,
+                 0       // parent
+        );
+    psS64 det_id = psDBLastInsertID(config->dbh);
+
+    // create new detInputExp row(s) from the rawExp row(s)
+    psArray *inputExps = psArrayAllocEmpty(psArrayLength(detrendExps));
+    for (long i = 0; i < psArrayLength(detrendExps); i++) {
+        detInputExpRow *inputExp = rawDetrenTodetInputExpRow(
+            detrendExps->data[i],
+            det_id,
+            0 // the first iteration is explicitly 0
+        );
+        psArrayAdd(inputExps, 0, inputExp);
+        psFree(inputExp);
+    }
+
+    psFree(detrendExps);
+
+    // insert detInputExp objects into the database
+    if (!detInputExpInsertObjects(config->dbh, inputExps)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psFree(inputExps);
+        return false;
+    }
+    psFree(inputExps);
+
+    // point of no return for det_id creation
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // print the new det_id
+    psArray *detRuns = NULL;
+    {
+        psMetadata *where = psMetadataAlloc();
+        psMetadataAddS64(where, PS_LIST_TAIL, "det_id", 0, "==", det_id);
+        detRuns = psDBSelectRows(config->dbh, "detRun", where, 0);
+        psFree(where);
+    }
+    if (!detRuns) {
+        psError(PS_ERR_UNKNOWN, false, "can't find the detRun we just created");
+        return false;
+    }
+    // sanity check results
+    if (psArrayLength(detRuns) != 1) {
+        psAbort("found more then one detRun matching det_id %" PRId64 " (this should not happen)", det_id);
+        return false;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, detRuns, "detRun", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(detRuns);
+        return false;
+    }
+    psFree(detRuns);
+
+    return true;
+}
+
+#if 0
+// This function is used to convert the det_id from an int, as it is used
+// internally, to be a string for external use.  The rationale being that we may
+// want to change how det_id is generated in the future and don't want to
+// external programs to become depending on this value being an int.
+static bool convertDetIdToStr(psArray *mds)
+{
+    PS_ASSERT_PTR_NON_NULL(mds, false);
+
+    for (long i = 0; i < psArrayLength(mds); i++) {
+        psMetadata *md = mds->data[i];
+        bool status = false;
+        psS32 det_id = psMetadataLookupS32(&status, md, "det_id");
+        if (!status) {
+            psError(PS_ERR_UNKNOWN, false, "failed to lookup value for det_id");
+            return false;
+        }
+        psMetadataRemoveKey(md, "det_id");
+        psString det_idStr = psDBIntToString((psU64)det_id);
+        psMetadataAddStr(mds->data[i], PS_LIST_HEAD, "det_id", 0, NULL, det_idStr);
+        psFree(det_idStr);
+    }
+
+    return true;
+}
+#endif
+
+static bool definebyqueryMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required
+    PXOPT_LOOKUP_STR(det_type, config->args, "-det_type", true, false);
+    PXOPT_LOOKUP_STR(workdir, config->args, "-workdir", true, false);
+    PXOPT_LOOKUP_STR(camera, config->args, "-inst", true, false);
+
+    // optional
+    PXOPT_LOOKUP_STR(mode, config->args, "-mode", false, false);
+    // check mode
+    if (mode && !isValidMode(config, mode)) {
+        psError(PS_ERR_UNKNOWN, false, "invalid mode");
+        return false;
+    }
+    PXOPT_LOOKUP_STR(filelevel, config->args, "-filelevel", false, false);
+    PXOPT_LOOKUP_STR(telescope, config->args, "-telescope", false, false);
+    PXOPT_LOOKUP_STR(filter, config->args, "-filter", false, false);
+    PXOPT_LOOKUP_F32(airmass_min, config->args, "-airmass_min", false, false);
+    PXOPT_LOOKUP_F32(airmass_max, config->args, "-airmass_max", false, false);
+    PXOPT_LOOKUP_F32(exp_time_min, config->args, "-exp_time_min", false, false);
+    PXOPT_LOOKUP_F32(exp_time_max, config->args, "-exp_time_max", false, false);
+    PXOPT_LOOKUP_F32(ccd_temp_min, config->args, "-ccd_temp_min", false, false);
+    PXOPT_LOOKUP_F32(ccd_temp_max, config->args, "-ccd_temp_max", false, false);
+    PXOPT_LOOKUP_F64(posang_min, config->args, "-posang_min", false, false);
+    PXOPT_LOOKUP_F64(posang_max, config->args, "-posang_max", false, false);
+    PXOPT_LOOKUP_F64(solang_min, config->args, "-solang_min", false, false);
+    PXOPT_LOOKUP_F64(solang_max, config->args, "-solang_max", false, false);
+
+    PXOPT_LOOKUP_BOOL(pretend, config->args, "-pretend", false);
+    PXOPT_LOOKUP_STR(reduction, config->args, "-reduction", false, false);
+    PXOPT_LOOKUP_STR(label, config->args, "-label", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    PXOPT_LOOKUP_BOOL(randomSubset, config->args, "-random_subset", false);
+    PXOPT_LOOKUP_S32(randomLimit, config->args, "-random_limit", false, false);
+
+    PXOPT_LOOKUP_TIME(registered, config->args, "-registered", false, false);
+    PXOPT_LOOKUP_TIME(time_begin, config->args, "-time_begin", false, false);
+    PXOPT_LOOKUP_TIME(time_end, config->args, "-time_end", false, false);
+    PXOPT_LOOKUP_TIME(use_begin, config->args, "-use_begin", false, false);
+    PXOPT_LOOKUP_TIME(use_end, config->args, "-use_end", false, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-select_exp_type", "exp_type", "==");
+    PXOPT_COPY_STR(config->args, where, "-select_inst", "camera", "==");
+    PXOPT_COPY_STR(config->args, where, "-select_telescope", "telescope", "==");
+    PXOPT_COPY_STR(config->args, where, "-select_filter", "filter", "==");
+    PXOPT_COPY_STR(config->args, where, "-select_uri", "uri", "==");
+    PXOPT_COPY_TIME(config->args, where, "-select_dateobs_begin", "dateobs", ">=");
+    PXOPT_COPY_TIME(config->args, where, "-select_dateobs_end", "dateobs", "<=");
+    PXOPT_COPY_F32(config->args, where, "-select_airmass_min", "airmass", ">=");
+    PXOPT_COPY_F32(config->args, where, "-select_airmass_max", "airmass", "<=");
+    PXOPT_COPY_F32(config->args, where, "-select_sat_pixel_frac_max", "sat_pixel_frac", "<=");
+    PXOPT_COPY_F32(config->args, where, "-select_exp_time_min", "exp_time", ">=");
+    PXOPT_COPY_F32(config->args, where, "-select_exp_time_max", "exp_time", "<=");
+    PXOPT_COPY_F64(config->args, where, "-select_ccd_temp_min", "ccd_temp", ">=");
+    PXOPT_COPY_F64(config->args, where, "-select_ccd_temp_max", "ccd_temp", "<=");
+    PXOPT_COPY_F64(config->args, where, "-select_pon_time_min", "pon_time", ">=");
+    PXOPT_COPY_F64(config->args, where, "-select_pon_time_max", "pon_time", "<=");
+    PXOPT_COPY_F64(config->args, where, "-select_posang_min", "posang", ">=");
+    PXOPT_COPY_F64(config->args, where, "-select_posang_max", "posang", "<=");
+    PXOPT_COPY_F64(config->args, where, "-select_solang_min", "solang", ">=");
+    PXOPT_COPY_F64(config->args, where, "-select_solang_max", "solang", "<=");
+
+    if (!psListLength(where->list)) {
+        psFree(where);
+        where = NULL;
+    }
+
+    // there is some namespace overlap between the names of the fields we'd
+    // like to search by to setup a detrun and the names of the fields we'd
+    // like to assign values to so I've separated them but prepending set- to
+    // the assigned values
+
+    // search for rawExps with the specified options
+    psArray *detrendExps = rawExpSelectRowObjects(config->dbh, where, 0);
+    psFree(where);
+    // make sure that we found at least one rawExp
+    if (!detrendExps) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(detrendExps)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(detrendExps);
+        return true;
+    }
+
+    if (randomSubset && (randomLimit < detrendExps->n)) {
+      // generate a random-valued vector, return an index sorted by the random values
+      psVector *randomVector = psVectorAlloc(detrendExps->n, PS_TYPE_F32); // random values
+      psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+      for (int i = 0; i < randomVector->n; i++) {
+        randomVector->data.F32[i] = psRandomUniform(rng);
+      }
+      psVector *indexVector = psVectorSortIndex(NULL, randomVector);
+
+      // accept for first n of the sequence
+      psArray *subset = psArrayAlloc (randomLimit);
+      for (int i = 0; i < randomLimit; i++ ){
+        int j = indexVector->data.S32[i];
+        subset->data[i] = psMemIncrRefCounter (detrendExps->data[j]);
+      }
+      psFree (detrendExps);
+      detrendExps = subset;
+    }
+
+    // check to see if -filelevel was set on the command line
+    if (!filelevel) {
+        filelevel = psStringCopy(((rawExpRow *)detrendExps->data[0])->filelevel);
+    }
+
+    if (pretend) {
+        // negative simple so the default is true
+        if (!rawExpPrintObjects(stdout, detrendExps, !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(detrendExps);
+            return false;
+        }
+        psFree(detrendExps);
+        return true;
+    }
+
+    // start a transaction so we don't end up with childlessed det_ids
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(detrendExps);
+        return false;
+    }
+
+    // the first iteration is always 0
+    // XXX det_id
+    detRunInsert(config->dbh,
+                 0,      // det_id
+                 0,      // iteration
+                 det_type,
+                 mode,
+                 "run",  // state
+                 filelevel,
+                 workdir,
+                 camera,
+                 telescope,
+                 "NA",
+                 reduction,
+                 filter,
+                 airmass_min,
+                 airmass_max,
+                 exp_time_min,
+                 exp_time_max,
+                 ccd_temp_min,
+                 ccd_temp_max,
+                 posang_min,
+                 posang_max,
+                 registered,
+                 time_begin,
+                 time_end,
+                 use_begin,
+                 use_end,
+                 solang_min,
+                 solang_max,
+                 label,
+                 0       // parent
+        );
+    psS64 det_id = psDBLastInsertID(config->dbh);
+
+    // create new detInputExp row(s) from the rawExp row(s)
+    psArray *inputExps = psArrayAllocEmpty(psArrayLength(detrendExps));
+    for (long i = 0; i < psArrayLength(detrendExps); i++) {
+        detInputExpRow *inputExp = rawDetrenTodetInputExpRow(
+            detrendExps->data[i],
+            det_id,
+            0 // the first iteration is explicitly 0
+        );
+        psArrayAdd(inputExps, 0, inputExp);
+        psFree(inputExp);
+    }
+
+    psFree(detrendExps);
+
+    // insert detInputExp objects into the database
+    if (!detInputExpInsertObjects(config->dbh, inputExps)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psFree(inputExps);
+        return false;
+    }
+    psFree(inputExps);
+
+    // point of no return for det_id creation
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+
+    // print the new det_id
+    psArray *detRuns = NULL;
+    {
+        psMetadata *where = psMetadataAlloc();
+        psMetadataAddS64(where, PS_LIST_TAIL, "det_id", 0, "==", det_id);
+        detRuns = psDBSelectRows(config->dbh, "detRun", where, 0);
+        psFree(where);
+    }
+    if (!detRuns) {
+        psError(PS_ERR_UNKNOWN, false, "can't find the detRun we just created");
+        return false;
+    }
+    // sanity check results
+    if (psArrayLength(detRuns) != 1) {
+        psAbort("found more then one detRun matching det_id %" PRId64 " (this should not happen)", det_id);
+        return false;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, detRuns, "detRun", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(detRuns);
+        return false;
+    }
+    psFree(detRuns);
+
+    return true;
+}
+
+static bool definebydetrunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false); // required
+    PXOPT_LOOKUP_STR(det_type, config->args, "-set_det_type", false, false); // optional
+    PXOPT_LOOKUP_STR(mode, config->args, "-set_mode", false, false); // optional
+    PXOPT_LOOKUP_STR(exp_type, config->args, "-set_exp_type", false, false);
+    PXOPT_LOOKUP_STR(filelevel, config->args, "-set_filelevel", false, false);
+    PXOPT_LOOKUP_STR(workdir, config->args, "-set_workdir", false, false);
+    PXOPT_LOOKUP_STR(filter, config->args, "-set_filter", false, false);
+    PXOPT_LOOKUP_F32(airmass_min, config->args, "-set_airmass_min", false, false);
+    PXOPT_LOOKUP_F32(airmass_max, config->args, "-set_airmass_max", false, false);
+    PXOPT_LOOKUP_F32(exp_time_min, config->args, "-set_exp_time_min", false, false);
+    PXOPT_LOOKUP_F32(exp_time_max, config->args, "-set_exp_time_max", false, false);
+    PXOPT_LOOKUP_F64(ccd_temp_min, config->args, "-set_ccd_temp_min", false, false);
+    PXOPT_LOOKUP_F64(ccd_temp_max, config->args, "-set_ccd_temp_max", false, false);
+    PXOPT_LOOKUP_F64(posang_min, config->args, "-set_posang_min", false, false);
+    PXOPT_LOOKUP_F64(posang_max, config->args, "-set_posang_max", false, false);
+    PXOPT_LOOKUP_F64(solang_min, config->args, "-set_solang_min", false, false);
+    PXOPT_LOOKUP_F64(solang_max, config->args, "-set_solang_max", false, false);
+    PXOPT_LOOKUP_TIME(registered, config->args, "-set_registered", false, false);
+    PXOPT_LOOKUP_TIME(time_begin, config->args, "-set_time_begin", false, false);
+    PXOPT_LOOKUP_TIME(time_end, config->args, "-set_end", false, false);
+    PXOPT_LOOKUP_TIME(use_begin, config->args, "-use_begin", false, false);
+    PXOPT_LOOKUP_TIME(use_end, config->args, "-use_end", false, false);
+    PXOPT_LOOKUP_STR(reduction, config->args, "-set_reduction", false, false);
+    PXOPT_LOOKUP_STR(label, config->args, "-set_label", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false); // optional
+
+    // check mode
+    if (mode && !isValidMode(config, mode)) {
+        psError(PS_ERR_UNKNOWN, false, "invalud mode");
+        return false;
+    }
+
+    // lookup the detRun that we will be basing this one on
+    psArray *detRuns = NULL;
+    {
+        psMetadata *where = psMetadataAlloc();
+        psMetadataAddS64(where, PS_LIST_TAIL, "det_id", 0, "==", det_id);
+        detRuns = detRunSelectRowObjects(config->dbh, where, 0);
+        psFree(where);
+    }
+    if (!detRuns) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    // sanity check the result... we should have only found one det_id
+    if (psArrayLength(detRuns) != 1) {
+        psAbort("found more then one detRun matching det_id %" PRId64 " (this should not happen)", det_id);
+        return false;                   // unreachable
+    }
+
+    // pull the detRun object out the result array
+    detRunRow *detRun = psMemIncrRefCounter(detRuns->data[0]);
+
+    // discard the resultarray
+    psFree(detRuns);
+
+    // set the det_id to 0/NULL so the database can assign it
+    detRun->det_id = 0;
+
+    // reset the iteration to 0
+    detRun->iteration = 0;
+
+    // reset the state to "run"
+    psFree(detRun->state);
+    detRun->state = psStringCopy("run");
+
+    // walk through the optional values and update the detRun as required
+    if (det_type) {
+        psFree(detRun->det_type);
+        detRun->det_type = psStringCopy(det_type);
+    }
+
+    if (mode) {
+        psFree(detRun->mode);
+        detRun->mode = psStringCopy(mode);
+    }
+
+    if (exp_type) {
+        psFree(detRun->exp_type);
+        detRun->exp_type = psStringCopy(exp_type);
+    }
+
+    if (filelevel) {
+        psFree(detRun->filelevel);
+        detRun->filelevel = psStringCopy(filelevel);
+    }
+
+    if (workdir) {
+        psFree(detRun->workdir);
+        detRun->workdir = psStringCopy(workdir);
+    }
+
+    if (filter) {
+        psFree(detRun->filter);
+        detRun->filter = psStringCopy(filter);
+    }
+
+    if (!isnan(airmass_min)) {
+        detRun->airmass_min = airmass_min;
+    }
+
+    if (!isnan(airmass_max)) {
+        detRun->airmass_max = airmass_max;
+    }
+
+    if (!isnan(exp_time_min)) {
+        detRun->exp_time_min = exp_time_min;
+    }
+
+    if (!isnan(exp_time_max)) {
+        detRun->exp_time_max = exp_time_max;
+    }
+
+    if (!isnan(ccd_temp_min)) {
+        detRun->ccd_temp_min = ccd_temp_min;
+    }
+
+    if (!isnan(ccd_temp_max)) {
+        detRun->ccd_temp_max = ccd_temp_max;
+    }
+
+    if (!isnan(posang_min)) {
+        detRun->posang_min = posang_min;
+    }
+
+    if (!isnan(posang_max)) {
+        detRun->posang_max = posang_max;
+    }
+
+    if (!isnan(solang_min)) {
+        detRun->solang_min = solang_min;
+    }
+
+    if (!isnan(solang_max)) {
+        detRun->solang_max = solang_max;
+    }
+
+    if (label) {
+        psFree(detRun->label);
+        detRun->label = label;
+    }
+
+    if (registered) {
+        psFree(detRun->registered);
+        detRun->registered = psMemIncrRefCounter(registered);
+    }
+
+    if (time_begin) {
+        psFree(detRun->time_begin);
+        detRun->time_begin = psMemIncrRefCounter(time_begin);
+    }
+
+    if (time_end) {
+        psFree(detRun->time_end);
+        detRun->time_end = psMemIncrRefCounter(time_end);
+    }
+
+    if (use_begin) {
+        psFree(detRun->use_begin);
+        detRun->use_begin = psMemIncrRefCounter(use_begin);
+    }
+
+    if (use_end) {
+        psFree(detRun->use_end);
+        detRun->use_end = psMemIncrRefCounter(use_end);
+    }
+
+    if (reduction) {
+        psFree(detRun->reduction);
+        detRun->reduction = psStringCopy(reduction);
+    }
+
+    // create a metadata to restrict detInputExp's be in in the specified range
+
+    psMetadata *time_filter = psMetadataAlloc();
+
+    // XXX: possible mem leak: PXOPT_COPY* will free time_filter but NOTHING
+    // that has previously been allocated
+    PXOPT_COPY_TIME(config->args, time_filter, "-set_input_begin", "dateobs", ">=");
+    PXOPT_COPY_TIME(config->args, time_filter, "-set_input_end", "dateobs", "<");
+
+    // start a transaction so we don't end up with childlessed det_ids
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(time_filter);
+        psFree(detRun);
+        return false;
+    }
+
+    if (!detRunInsertObject(config->dbh, detRun)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psFree(time_filter);
+        psFree(detRun);
+        return false;
+    }
+    psFree(detRun);
+
+    // get the det_id
+    psS64 newDet_id = psDBLastInsertID(config->dbh);
+
+    psString query = pxDataGet("dettool_definebydetrun.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (time_filter->list->n) {
+        psString whereClause = psDBGenerateWhereConditionSQL(time_filter, "rawExp");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(time_filter);
+
+    if (!p_psDBRunQuery(config->dbh, query, (long long) newDet_id, (long long) det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    // point of no return for det_id creation
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // print the new det_id
+    psArray *newDetRuns = NULL;
+    {
+        psMetadata *where = psMetadataAlloc();
+        psMetadataAddS64(where, PS_LIST_TAIL, "det_id", 0, "==", newDet_id);
+        newDetRuns = psDBSelectRows(config->dbh, "detRun", where, 0);
+        psFree(where);
+    }
+    if (!newDetRuns) {
+        psError(PS_ERR_UNKNOWN, false, "can't find the detRun we just created");
+        return false;
+    }
+    // sanity check the result... we should have only found one det_id
+    if (psArrayLength(newDetRuns) != 1) {
+        psAbort("found more then one detRun matching det_id %" PRId64 " (this should not happen)", newDet_id);
+        return false;                   // unreachable
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, newDetRuns, "detRun", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(newDetRuns);
+        return false;
+    }
+    psFree(newDetRuns);
+
+    return true;
+}
+
+static bool runsMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-det_type", "det_type", "==");
+    PXOPT_COPY_S64(config->args, where, "-det_id",   "det_id", "==");
+
+    PXOPT_COPY_STR(config->args, where, "-inst", "camera", "==");
+    PXOPT_COPY_STR(config->args, where, "-telescope", "telescope", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter", "filter", "==");
+
+    // airmass_min  < airmass  < airmass_max
+    PXOPT_COPY_F32(config->args, where, "-airmass", "airmass_min", "<=");
+    PXOPT_COPY_F32(config->args, where, "-airmass", "airmass_max", ">=");
+
+    // exp_time_min < exp_time < exp_time_max
+    PXOPT_COPY_F32(config->args, where, "-exp_time", "exp_time_min", "<=");
+    PXOPT_COPY_F32(config->args, where, "-exp_time", "exp_time_max", ">=");
+
+    // ccd_temp_min < ccd_temp < ccd_temp_max
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp", "ccd_temp_min", "<=");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp", "ccd_temp_max", ">=");
+
+    PXOPT_COPY_F64(config->args, where, "-posang", "posang_min", "<=");
+    PXOPT_COPY_F64(config->args, where, "-posang", "posang_max", ">=");
+
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_BOOL(active, config->args, "-active", false);
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+
+    psString query = pxDataGet("dettool_runs.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list) && active) {
+        psString whereClause = psDBGenerateWhereSQL(where, "detRun");
+        psStringAppend(&query, " %s AND (detRun.state = 'run' OR detRun.state = 'stop' OR detRun.state = 'register')", whereClause);
+        psFree(whereClause);
+    }
+    if (psListLength(where->list) && !active) {
+        psString whereClause = psDBGenerateWhereSQL(where, "detRun");
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+    if (!psListLength(where->list) && active) {
+        psStringAppend(&query, " WHERE (detRun.state = 'run' OR detRun.state = 'stop' OR detRun.state = 'register')");
+    }
+    psFree (where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *runs = p_psDBFetchResult(config->dbh);
+    if (!runs) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!psArrayLength(runs)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(runs);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, runs, "detRun", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(runs);
+        return false;
+    }
+
+    psFree(runs);
+
+    return true;
+}
+
+static bool childlessrunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-det_type", "det_type", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // find the exp_id of all the exposures that we want to queue up.
+    psString query = pxDataGet("dettool_childlessrun.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psFree(where);
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "detRun");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree (where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detRun", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static detInputExpRow *rawDetrenTodetInputExpRow(rawExpRow *rawExp, psS64 det_id, psS32 iteration)
+{
+    PS_ASSERT_PTR_NON_NULL(rawExp, NULL);
+
+    return detInputExpRowAlloc(
+        det_id,
+        iteration,
+        rawExp->exp_id,
+        true            // use
+    );
+}
+
+static bool inputMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id",    "exp_id", "==");
+
+    psString query = pxDataGet("dettool_input.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psFree(where);
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereSQL(where, "detInputExp");
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree (where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detInputExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool rawMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+
+    psString query = pxDataGet("dettool_raw.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "rawImfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree (where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "rawImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool updatedetrunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false); // required
+    PXOPT_LOOKUP_BOOL(again, config->args, "-again", false);
+    PXOPT_LOOKUP_STR(state, config->args, "-state", false, false);
+
+    // either -rerun or -state must be specified
+    if (!(again || state)) {
+        psError(PS_ERR_UNKNOWN, true, "either -again or -state must be specified");
+        return false;
+    }
+    if (again && state) {
+        psError(PS_ERR_UNKNOWN, true, "-accept and -reject are exclusive");
+        return false;
+    }
+
+    if (state) {
+        // set detRun.state to state
+        return setDetRunState(config, det_id, state);
+    }
+
+    // else
+    // -again
+    if (!startNewIteration(config, det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to start new iteration");
+        return false;
+    }
+
+    return true;
+}
+
+// used by updatedetrunMode 
+bool startNewIteration(pxConfig *config, psS64 det_id)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psString query = pxDataGet("dettool_start_new_iteration.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // restrict the update only to the specified det_id
+    psStringAppend(&query, " WHERE det_id = %" PRId64 , det_id);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psError(PS_ERR_UNKNOWN, false, "det_id %" PRId64 " not found", det_id);
+        psFree(output);
+        return false;
+    }
+
+    // start a transaction so we don't end up with an incremented iteration
+    // count but no detInputExps
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(output);
+        return false;
+    }
+
+    // up the detRuns iteration count for for the single det_id we are
+    // operating on
+    // XXX this will have to changed in order to support multiple det_ids with
+    // a single invocation of this functions
+    psS32 newIteration = incrementIteration(config, det_id);
+    if (!newIteration) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psFree(output);
+        return false;
+    }
+
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *row = output->data[i];
+        bool status = false;
+        psS64 exp_id = psMetadataLookupS64(&status, row, "exp_id");
+        if (!status) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "failed to lookup value for exp_id");
+            psFree(output);
+            return false;
+        }
+        bool accept = psMetadataLookupBool(&status, row, "accept");
+        if (!status) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "failed to lookup value for accept");
+            psFree(output);
+            return false;
+        }
+
+        // detResidExp.include is used to set detInputExp.include
+        if (!detInputExpInsert(
+                    config->dbh,
+                    det_id,
+                    newIteration,
+                    exp_id,
+                    accept
+                )
+        ) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    // point of no return for det_id creation
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+static bool rerunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // det_id is required
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false);
+
+    // we have to support multipe exp_ids
+    psMetadataItem *item = psMetadataLookup(config->args, "-exp_id");
+    if (!item) {
+        // this shouldn't actually happen when using psArgs
+        psError(PS_ERR_UNKNOWN, true, "-exp_id is required");
+        return false;
+    }
+
+    psList *exp_id_list = item->data.list;
+    psMetadata *where = psMetadataAlloc();
+    // make sure that -exp_id was parsed correctly
+    // XXX this can be removed someday
+    if (item->type == PS_DATA_METADATA_MULTI) {
+        psListIterator *iter = psListIteratorAlloc(item->data.list, 0, false);
+        psMetadataItem *mItem = NULL;
+        while ((mItem = psListGetAndIncrement(iter))) {
+            psString exp_id = mItem->data.V;
+            // if exp_id is NULL then it means that -exp_id has not been
+            // specified
+            if (!exp_id) {
+                psError(PS_ERR_UNKNOWN, true,
+                        "at least one -exp_id is required");
+                psFree(where);
+                return false;
+            }
+
+            if (!psMetadataAddStr(where, PS_LIST_TAIL, "exp_id",
+                        PS_META_DUPLICATE_OK, "==", exp_id)) {
+                psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+                psFree(iter);
+                psFree(where);
+                return false;
+            }
+        }
+        psFree(iter);
+    } else {
+        psAbort("-exp_id was not parsed correctly (this should not happen");
+    }
+
+    // check that the specified exp_ids actually exist in the iteration zero
+    // detInputExp set
+
+    // add the det_id & iteration == 0 to the where clause
+    if (!psMetadataAddS64(where, PS_LIST_TAIL, "det_id", 0, "==", det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(where);
+        return false;
+    }
+    if (!psMetadataAddS32(where, PS_LIST_TAIL, "iteration", 0, "==", 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(where);
+        return false;
+    }
+
+    psArray *detrendExps = detInputExpSelectRowObjects(config->dbh, where, 0);
+    psFree(where);
+    if (!detrendExps) {
+        psError(PS_ERR_UNKNOWN, false, "no rawExp rows found");
+        psFree(where);
+        return false;
+    }
+
+    // build a hash for the valid exp_ids
+    psHash *valid_exp_ids = psHashAlloc(psArrayLength(detrendExps));
+    for (long i = 0; i < psArrayLength(detrendExps); i++) {
+        psString exp_idStr = psDBIntToString(((detInputExpRow *)detrendExps->data[i])->exp_id);
+        psHashAdd(valid_exp_ids, exp_idStr, detrendExps->data[i]);
+        psFree(exp_idStr);
+    }
+    psFree(detrendExps);
+
+    // start a transaction so we don't end up with an incremented iteration
+    // count but no detInputExps
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(valid_exp_ids);
+        return false;
+    }
+
+    // up the detRuns iteration count
+    psS32 newIteration = incrementIteration(config, det_id);
+    if (!newIteration) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psFree(valid_exp_ids);
+        return false;
+    }
+
+    // check exp_ids and build up an array of new detInputExp rows at the same
+    // time
+    psListIterator *iter = psListIteratorAlloc(exp_id_list, 0, false);
+    psMetadataItem *mItem = NULL;
+    psArray *newInputExps = psArrayAllocEmpty(psListLength(exp_id_list));
+    while ((mItem = psListGetAndIncrement(iter))) {
+        detInputExpRow *inputExp = psHashLookup(valid_exp_ids,
+                (char *)mItem->data.V);
+        if (!inputExp) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            // invalid exp_id
+            psError(PS_ERR_UNKNOWN, false, "exp_id %s is invalid for det_id %" PRId64,
+                    (char *)mItem->data.V, det_id);
+            psFree(iter);
+            psFree(valid_exp_ids);
+            return false;
+        }
+        detInputExpRow *newInputExp = detInputExpRowAlloc(
+	    det_id,
+            newIteration,
+            inputExp->exp_id,
+            true   // use
+        );
+        psArrayAdd(newInputExps, 0, newInputExp);
+        psFree(newInputExp);
+    }
+    psFree(iter);
+    psFree(valid_exp_ids);
+
+    for (long i = 0; i < psArrayLength(newInputExps); i++) {
+        if (!detInputExpInsertObject(config->dbh, newInputExps->data[i])) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psFree(newInputExps);
+            return false;
+        }
+    }
+    psFree(newInputExps);
+
+    // point of no return for det_id creation
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+static bool register_detrendMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(det_type, config->args, "-det_type", true, false); // required
+    PXOPT_LOOKUP_STR(filelevel, config->args, "-filelevel", true, false); // required
+    PXOPT_LOOKUP_STR(workdir, config->args, "-workdir", false, false);
+    PXOPT_LOOKUP_STR(camera, config->args, "-inst", false, false);
+    PXOPT_LOOKUP_STR(telescope, config->args, "-telescope", false, false);
+    PXOPT_LOOKUP_STR(exp_type, config->args, "-exp_type", false, false);
+    PXOPT_LOOKUP_STR(filter, config->args, "-filter", false, false);
+    PXOPT_LOOKUP_F32(airmass_min, config->args, "-airmass_min", false, false);
+    PXOPT_LOOKUP_F32(airmass_max, config->args, "-airmass_max", false, false);
+    PXOPT_LOOKUP_F32(exp_time_min, config->args, "-exp_time_min", false, false);
+    PXOPT_LOOKUP_F32(exp_time_max, config->args, "-exp_time_max", false, false);
+    PXOPT_LOOKUP_F32(ccd_temp_min, config->args, "-ccd_temp_min", false, false);
+    PXOPT_LOOKUP_F32(ccd_temp_max, config->args, "-ccd_temp_max", false, false);
+    PXOPT_LOOKUP_F64(posang_min, config->args, "-posang_min", false, false);
+    PXOPT_LOOKUP_F64(posang_max, config->args, "-posang_max", false, false);
+    PXOPT_LOOKUP_F64(solang_min, config->args, "-solang_min", false, false);
+    PXOPT_LOOKUP_F64(solang_max, config->args, "-solang_max", false, false);
+    PXOPT_LOOKUP_TIME(registered, config->args, "-registered", false, false);
+    PXOPT_LOOKUP_TIME(time_begin, config->args, "-time_begin", false, false);
+    PXOPT_LOOKUP_TIME(time_end, config->args, "-time_end", false, false);
+    PXOPT_LOOKUP_TIME(use_begin, config->args, "-use_begin", false, false);
+    PXOPT_LOOKUP_TIME(use_end, config->args, "-use_end", false, false);
+    PXOPT_LOOKUP_S64(parent, config->args, "-parent", false, false);
+    PXOPT_LOOKUP_STR(label, config->args, "-label", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!detRunInsert(config->dbh,
+                      0,            // det_id
+                      0,            // the iteration is fixed at 0
+                      det_type,
+                      "register",   // mode is required to be "register"
+                      "register",   // state
+                      filelevel,
+                      workdir,
+                      camera,
+                      telescope,
+                      exp_type,
+                      NULL,
+                      filter,
+                      airmass_min,
+                      airmass_max,
+                      exp_time_min,
+                      exp_time_max,
+                      ccd_temp_min,
+                      ccd_temp_max,
+                      posang_min,
+                      posang_max,
+                      registered,
+                      time_begin,
+                      time_end,
+                      use_begin,
+                      use_end,
+                      solang_min,
+                      solang_max,
+                      label,      // label
+                      parent
+            )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        return false;
+    }
+
+    // print the new detRun
+    psS64 det_id = psDBLastInsertID(config->dbh);
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psArray *detRuns = NULL;
+    {
+        psMetadata *where = psMetadataAlloc();
+        psMetadataAddS64(where, PS_LIST_TAIL, "det_id", 0, "==", det_id);
+        detRuns = psDBSelectRows(config->dbh, "detRun", where, 0);
+        psFree(where);
+    }
+    if (!detRuns) {
+        psError(PS_ERR_UNKNOWN, false, "can't find the detRun we just created");
+        return false;
+    }
+    // sanity check results
+    if (psArrayLength(detRuns) != 1) {
+        psAbort("found more then one detRun matching det_id %" PRId64 "(this should not happen)", det_id);
+        return false;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, detRuns, "detRun", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(detRuns);
+        return false;
+    }
+    psFree(detRuns);
+
+    return true;
+}
+
+// NOTE : this function is also used by addcorrectimfileMode
+bool register_detrend_imfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false); // required
+    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false); // required
+    PXOPT_LOOKUP_STR(uri, config->args, "-uri", true, false); // required
+    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
+    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
+    PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
+    PXOPT_LOOKUP_F64(user_1, config->args, "-user_1", false, false);
+    PXOPT_LOOKUP_F64(user_2, config->args, "-user_2", false, false);
+    PXOPT_LOOKUP_F64(user_3, config->args, "-user_3", false, false);
+    PXOPT_LOOKUP_F64(user_4, config->args, "-user_4", false, false);
+    PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
+    PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
+
+    if (!detRegisteredImfileInsert(config->dbh,
+				   det_id,
+				   0,  // the iteration is fixed at 0
+				   class_id,
+				   uri,
+				   bg,
+				   bg_stdev,
+				   bg_mean_stdev,
+				   user_1,
+				   user_2,
+				   user_3,
+				   user_4,
+				   user_5,
+				   path_base,
+				   "full",				   
+				   0       // fault code
+	    )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+static psS32 incrementIteration(pxConfig *config, psS64 det_id)
+{
+    // this function returns zero on error
+    PS_ASSERT_PTR_NON_NULL(config, 0);
+
+    char *query = "UPDATE detRun SET iteration = iteration + 1 WHERE det_id = %" PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, det_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to increment iteration for det_id %" PRId64, det_id);
+        return 0;
+    }
+
+    psMetadata *where = psMetadataAlloc();
+    if (!psMetadataAddS64(where, PS_LIST_TAIL, "det_id", 0, "==", det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(where);
+        return 0;
+    }
+
+    psArray *detRuns = detRunSelectRowObjects(config->dbh, where, 0);
+    psFree(where);
+    if (!detRuns) {
+        psError(PS_ERR_UNKNOWN, false, "no detRun rows found");
+        return 0;
+    }
+
+    // sanity check the database
+    if (psArrayLength(detRuns) != 1) {
+        // this should no happen
+        psAbort(                "database query return too many rows (this should not happen");
+    }
+
+    psS32 newIteration = ((detRunRow *)detRuns->data[0])->iteration;
+    psFree(detRuns);
+
+    return newIteration;
+}
+
+bool setDetRunState(pxConfig *config, psS64 det_id, const char *state)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(state, false);
+
+    // check that state is a valid string value
+    if (!(
+            (strncmp(state, "run", 4) == 0)
+            || (strncmp(state, "stop", 5) == 0)
+            || (strncmp(state, "drop", 5) == 0)
+            || (strncmp(state, "register", 4) == 0)
+        )
+    ) {
+        psError(PS_ERR_UNKNOWN, false,
+                "invalid detRun state: %s", state);
+        return false;
+    }
+
+    char *query = "UPDATE detRun SET state = '%s' WHERE det_id = %" PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, state, det_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for det_id %" PRId64, det_id);
+        return false;
+    }
+
+    return true;
+}
+
+bool isValidDataState (const char *data_state) {
+
+    // check that state is a valid string value
+    if (!strncmp(data_state, "run", 4)) return true;
+    if (!strncmp(data_state, "stop", 5)) return true;
+    if (!strncmp(data_state, "drop", 5)) return true;
+    if (!strncmp(data_state, "register", 4)) return true;
+
+    psError(PS_ERR_UNKNOWN, true, "invalid data state: %s", data_state);
+    return false;
+}
+
+bool isValidMode(pxConfig *config, const char *mode)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(mode, false);
+
+    // check that state is a valid string value
+    if (!(
+            (strncmp(mode, "master", 7) == 0)
+            || (strncmp(mode, "verify", 7) == 0)
+        )
+    ) {
+        psError(PS_ERR_UNKNOWN, false,
+                "invalid detRun mode: %s", mode);
+        return false;
+    }
+
+    return true;
+}
+
+
+bool setProcessedImfileDataState(pxConfig *config, psS64 det_id, psS64 exp_id, const char *class_id, const char *data_state)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(data_state, false);
+    PS_ASSERT_PTR_NON_NULL(class_id, false);
+
+    if (!isValidDataState (data_state)) return false;
+
+    char *query = "UPDATE detProcessedImfile SET data_state = '%s'"
+	" WHERE det_id = %" PRId64
+	" AND exp_id = %" PRId64 
+	" AND class_id = '%s'";
+    if (!p_psDBRunQuery(config->dbh, query, data_state, det_id, exp_id, class_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for det_id %" PRId64 ", exp_id %" PRId64 ", class_id %s", 
+		det_id, exp_id, class_id);
+        return false;
+    }
+
+    return true;
+}
+
+bool setProcessedExpDataState(pxConfig *config, psS64 det_id, psS64 exp_id, const char *data_state)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(data_state, false);
+
+    if (!isValidDataState (data_state)) return false;
+
+    char *query = "UPDATE detProcessedExp SET data_state = '%s'"
+	" WHERE det_id = %" PRId64
+	" AND exp_id = %" PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, data_state, det_id, exp_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for det_id %" PRId64 ", exp_id %" PRId64, 
+		det_id, exp_id);
+        return false;
+    }
+
+    return true;
+}
+
+
+bool setStackedImfileDataState(pxConfig *config, psS64 det_id, psS32 iteration, const char *class_id, const char *data_state)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(class_id, false);
+    PS_ASSERT_PTR_NON_NULL(data_state, false);
+
+    if (!isValidDataState (data_state)) return false;
+
+    char *query = "UPDATE detStackedImfile SET data_state = '%s'"
+	" WHERE det_id = %" PRId64
+	" AND iteration = %" PRId32
+	" AND class_id = %s";
+    if (!p_psDBRunQuery(config->dbh, query, data_state, det_id, iteration, class_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for det_id %" PRId64 ", iteration %" PRId32 "class_id %s", 
+		det_id, iteration, class_id);
+        return false;
+    }
+
+    return true;
+}
+
+bool setNormStatImfileDataState(pxConfig *config, psS64 det_id, psS32 iteration, const char *class_id, const char *data_state)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(class_id, false);
+    PS_ASSERT_PTR_NON_NULL(data_state, false);
+
+    if (!isValidDataState (data_state)) return false;
+
+    char *query = "UPDATE detNormalizedStatImfile SET data_state = '%s'"
+	" WHERE det_id = %" PRId64
+	" AND iteration = %" PRId32
+	" AND class_id = %s";
+    if (!p_psDBRunQuery(config->dbh, query, data_state, det_id, iteration)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for det_id %" PRId64 ", iteration %" PRId32, 
+		det_id, iteration);
+        return false;
+    }
+
+    return true;
+}
+
+bool setNormImfileDataState(pxConfig *config, psS64 det_id, psS32 iteration, const char *class_id, const char *data_state)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(class_id, false);
+    PS_ASSERT_PTR_NON_NULL(data_state, false);
+
+    if (!isValidDataState (data_state)) return false;
+
+    char *query = "UPDATE detNormalizedImfile SET data_state = '%s'"
+	" WHERE det_id = %" PRId64
+	" AND iteration = %" PRId32
+	" AND class_id = %s";
+    if (!p_psDBRunQuery(config->dbh, query, data_state, det_id, iteration, class_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for det_id %" PRId64 ", iteration %" PRId32 " class %s", 
+		det_id, iteration, class_id);
+        return false;
+    }
+
+    return true;
+}
+
+bool setNormExpDataState(pxConfig *config, psS64 det_id, psS32 iteration, const char *data_state)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(data_state, false);
+
+    if (!isValidDataState (data_state)) return false;
+
+    char *query = "UPDATE detNormalizedExp SET data_state = '%s'"
+	" WHERE det_id = %" PRId64
+	" AND iteration = %" PRId32;
+    if (!p_psDBRunQuery(config->dbh, query, data_state, det_id, iteration)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for det_id %" PRId64 ", iteration %" PRId32, 
+		det_id, iteration);
+        return false;
+    }
+
+    return true;
+}
+
+bool setResidImfileDataState(pxConfig *config, psS64 det_id, psS32 iteration, psS64 exp_id, const char *class_id, const char *data_state)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(data_state, false);
+    PS_ASSERT_PTR_NON_NULL(class_id, false);
+
+    if (!isValidDataState (data_state)) return false;
+
+    char *query = "UPDATE detResidImfile SET data_state = '%s'"
+	" WHERE det_id = %" PRId64
+	" AND iteration = %" PRId32 
+	" AND exp_id = %" PRId64 
+	" AND class_id = '%s'";
+    if (!p_psDBRunQuery(config->dbh, query, data_state, det_id, iteration, exp_id, class_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for det_id %" PRId64 ", iteration %" PRId32 ", exp_id %" PRId64 ", class_id %s", 
+		det_id, iteration, exp_id, class_id);
+        return false;
+    }
+
+    return true;
+}
+
+bool setResidExpDataState(pxConfig *config, psS64 det_id, psS32 iteration, psS64 exp_id, const char *data_state)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(data_state, false);
+
+    if (!isValidDataState (data_state)) return false;
+
+    char *query = "UPDATE detResidExp SET data_state = '%s'"
+	" WHERE det_id = %" PRId64
+	" AND iteration = %" PRId32 
+	" AND exp_id = %" PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, data_state, det_id, iteration, exp_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for det_id %" PRId64 ", iteration %" PRId32 ", exp_id %" PRId64, 
+		det_id, iteration, exp_id);
+        return false;
+    }
+
+    return true;
+}
+
+#if 0
+// XXX this function was left in commented as this method may be useful in the
+// future
+static psArray *validDetInputClassIds(pxConfig *config, const char *det_id)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    // det_id is input as a string because the fact that it is an integer
+    // is just a database impliementation detail.
+    PS_ASSERT_PTR_NON_NULL(det_id, NULL);
+
+    psArray *rawImfiles = searchInputImfiles(config, det_id);
+    if (!rawImfiles) {
+        return NULL;
+    }
+
+    psArray *valid_class_ids = NULL;
+    {
+        // All this jumping through hoops is so that we end up with unique
+        // values. PP thinks that making multiple passes through this array and
+        // deleting matched elements would end up being more expensive then a
+        // double sort and stagger scheme. JH thinks it would be cheaper to
+        // just do a unqiue sort and delete.  So this is really just a cheap
+        // hack to avoid implimenting a unique sort function but at least it's
+        // stable.
+        psHash *hash = psHashAlloc(psArrayLength(rawImfiles));
+        for (long i = 0; i < psArrayLength(rawImfiles); i++) {
+            psHashAdd(hash,
+                ((rawImfileRow *)rawImfiles->data[i])->class_id,
+                ((rawImfileRow *)rawImfiles->data[i])->class_id
+            );
+        }
+        valid_class_ids = psHashToArray(hash);
+        psFree(hash);
+    }
+    psFree(rawImfiles);
+
+    return valid_class_ids;
+}
+
+static psArray *searchInputImfiles(pxConfig *config, const char *det_id)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    // det_id is input as a string because the fact that it is an integer
+    // is just a database impliementation detail.
+    PS_ASSERT_PTR_NON_NULL(det_id, NULL);
+
+    psArray *inputExps = NULL;
+    {
+        psMetadata *where = psMetadataAlloc();
+        if (!psMetadataAddS32(where, PS_LIST_TAIL, "det_id", 0, "==",
+                (psS32)atoi(det_id))) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+            psFree(where);
+            return NULL;
+        }
+        inputExps = detInputExpSelectRowObjects(config->dbh, where, 0);
+        psFree(where);
+    }
+    if (!inputExps) {
+        psError(PS_ERR_UNKNOWN, false, "no detInputExp rows found");
+        return NULL;
+    }
+
+    // find rawImfiles associated with detInputExps
+    psArray *rawImfiles = NULL;
+    {
+        psMetadata *where = psMetadataAlloc();
+        for (long i = 0; i < psArrayLength(inputExps); i++) {
+            if (!psMetadataAddStr(where, PS_LIST_TAIL, "exp_id",
+                    PS_META_DUPLICATE_OK, "==",
+                    ((detInputExpRow *)inputExps->data[i])->exp_id)) {
+                psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+                psFree(inputExps);
+                psFree(where);
+                return NULL;
+            }
+        }
+        psFree(inputExps);
+        rawImfiles = rawImfileSelectRowObjects(config->dbh, where, 0);
+        // XXX this really should be sorted for uniqueness
+        psFree(where);
+    }
+    if (!rawImfiles) {
+        psError(PS_ERR_UNKNOWN, false, "no rawImfile rows found");
+        return NULL;
+    }
+
+    return rawImfiles;
+}
+#endif
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool.h	(revision 22158)
@@ -0,0 +1,225 @@
+/*
+ * dettool.h
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef DETTOOL_H
+#define DETTOOL_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+    DETTOOL_MODE_NONE           = PXTOOL_MODE_NONE,
+    DETTOOL_MODE_PENDING,
+    DETTOOL_MODE_DEFINEBYTAG,
+    DETTOOL_MODE_DEFINEBYQUERY,
+    DETTOOL_MODE_DEFINEBYDETRUN,
+    DETTOOL_MODE_MAKECORRECTION,
+    DETTOOL_MODE_TOCORRECTEXP,
+    DETTOOL_MODE_TOCORRECTIMFILE,
+    DETTOOL_MODE_ADDCORRECTIMFILE,
+    DETTOOL_MODE_RUNS,
+    DETTOOL_MODE_CHILDLESSRUN,
+    DETTOOL_MODE_INPUT,
+    DETTOOL_MODE_RAW,
+
+    DETTOOL_MODE_TOPROCESSEDIMFILE,
+    DETTOOL_MODE_ADDPROCESSEDIMFILE,
+    DETTOOL_MODE_PROCESSEDIMFILE,
+    DETTOOL_MODE_REVERTPROCESSEDIMFILE,
+    DETTOOL_MODE_UPDATEPROCESSEDIMFILE,
+    DETTOOL_MODE_PENDINGCLEANUP_PROCESSEDIMFILE,
+    DETTOOL_MODE_DONECLEANUP_PROCESSEDIMFILE,
+
+    DETTOOL_MODE_TOPROCESSEDEXP,
+    DETTOOL_MODE_ADDPROCESSEDEXP,
+    DETTOOL_MODE_PROCESSEDEXP,
+    DETTOOL_MODE_REVERTPROCESSEDEXP,
+    DETTOOL_MODE_UPDATEPROCESSEDEXP,
+    DETTOOL_MODE_PENDINGCLEANUP_PROCESSEDEXP,
+    DETTOOL_MODE_DONECLEANUP_PROCESSEDEXP,
+
+    DETTOOL_MODE_TOSTACKED,
+    DETTOOL_MODE_ADDSTACKED,
+    DETTOOL_MODE_STACKED,
+    DETTOOL_MODE_REVERTSTACKED,
+    DETTOOL_MODE_UPDATESTACKED,
+    DETTOOL_MODE_PENDINGCLEANUP_STACKED,
+    DETTOOL_MODE_DONECLEANUP_STACKED,
+
+    DETTOOL_MODE_TONORMALIZEDSTAT,
+    DETTOOL_MODE_ADDNORMALIZEDSTAT,
+    DETTOOL_MODE_NORMALIZEDSTAT,
+    DETTOOL_MODE_REVERTNORMALIZEDSTAT,
+    DETTOOL_MODE_UPDATENORMALIZEDSTAT,
+    DETTOOL_MODE_PENDINGCLEANUP_NORMALIZEDSTAT,
+    DETTOOL_MODE_DONECLEANUP_NORMALIZEDSTAT,
+
+    DETTOOL_MODE_TONORMALIZE,
+    DETTOOL_MODE_ADDNORMALIZEDIMFILE,
+    DETTOOL_MODE_NORMALIZEDIMFILE,
+    DETTOOL_MODE_REVERTNORMALIZEDIMFILE,
+    DETTOOL_MODE_UPDATENORMALIZEDIMFILE,
+    DETTOOL_MODE_PENDINGCLEANUP_NORMALIZEDIMFILE,
+    DETTOOL_MODE_DONECLEANUP_NORMALIZEDIMFILE,
+
+    DETTOOL_MODE_TONORMALIZEDEXP,
+    DETTOOL_MODE_ADDNORMALIZEDEXP,
+    DETTOOL_MODE_NORMALIZEDEXP,
+    DETTOOL_MODE_REVERTNORMALIZEDEXP,
+    DETTOOL_MODE_UPDATENORMALIZEDEXP,
+    DETTOOL_MODE_PENDINGCLEANUP_NORMALIZEDEXP,
+    DETTOOL_MODE_DONECLEANUP_NORMALIZEDEXP,
+
+    DETTOOL_MODE_TORESIDIMFILE,
+    DETTOOL_MODE_ADDRESIDIMFILE,
+    DETTOOL_MODE_RESIDIMFILE,
+    DETTOOL_MODE_REVERTRESIDIMFILE,
+    DETTOOL_MODE_UPDATERESIDIMFILE,
+    DETTOOL_MODE_PENDINGCLEANUP_RESIDIMFILE,
+    DETTOOL_MODE_DONECLEANUP_RESIDIMFILE,
+
+    DETTOOL_MODE_TORESIDEXP,
+    DETTOOL_MODE_ADDRESIDEXP,
+    DETTOOL_MODE_RESIDEXP,
+    DETTOOL_MODE_REVERTRESIDEXP,
+    DETTOOL_MODE_UPDATERESIDEXP,
+    DETTOOL_MODE_PENDINGCLEANUP_RESIDEXP,
+    DETTOOL_MODE_DONECLEANUP_RESIDEXP,
+
+    DETTOOL_MODE_TODETRUNSUMMARY,
+    DETTOOL_MODE_ADDDETRUNSUMMARY,
+    DETTOOL_MODE_DETRUNSUMMARY,
+    DETTOOL_MODE_REVERTDETRUNSUMMARY,
+    DETTOOL_MODE_UPDATEDETRUNSUMMARY,
+    DETTOOL_MODE_UPDATEDETRUN,
+    DETTOOL_MODE_RERUN,
+    DETTOOL_MODE_REGISTER_DETREND,
+    DETTOOL_MODE_REGISTER_DETREND_IMFILE
+} dettoolMode;
+
+pxConfig *dettoolConfig(pxConfig *config, int argc, char **argv);
+
+// correct
+bool makecorrectionMode(pxConfig *config);
+bool tocorrectexpMode(pxConfig *config);
+bool tocorrectimfileMode(pxConfig *config);
+bool addcorrectimfileMode(pxConfig *config);
+
+// register
+bool register_detrend_imfileMode(pxConfig *config);
+
+// processedimfile
+bool toprocessedimfileMode(pxConfig *config);
+bool addprocessedimfileMode(pxConfig *config);
+bool processedimfileMode(pxConfig *config);
+bool revertprocessedimfileMode(pxConfig *config);
+bool updateprocessedimfileMode(pxConfig *config);
+bool pendingcleanup_processedimfileMode(pxConfig *config);
+bool donecleanup_processedimfileMode(pxConfig *config);
+
+// processedexp
+bool toprocessedexpMode(pxConfig *config);
+bool addprocessedexpMode(pxConfig *config);
+bool processedexpMode(pxConfig *config);
+bool revertprocessedexpMode(pxConfig *config);
+bool updateprocessedexpMode(pxConfig *config);
+bool pendingcleanup_processedexpMode(pxConfig *config);
+bool donecleanup_processedexpMode(pxConfig *config);
+
+// stackedimfile
+bool tostackedMode(pxConfig *config);
+bool addstackedMode(pxConfig *config);
+bool stackedMode(pxConfig *config);
+bool revertstackedMode(pxConfig *config);
+bool updatestackedMode(pxConfig *config);
+bool pendingcleanup_stackedMode(pxConfig *config);
+bool donecleanup_stackedMode(pxConfig *config);
+
+// normalizedstat
+bool tonormalizedstatMode(pxConfig *config);
+bool addnormalizedstatMode(pxConfig *config);
+bool normalizedstatMode(pxConfig *config);
+bool revertnormalizedstatMode(pxConfig *config);
+bool updatenormalizedstatMode(pxConfig *config);
+bool pendingcleanup_normalizedstatMode(pxConfig *config);
+bool donecleanup_normalizedstatMode(pxConfig *config);
+
+// normalizedimfile
+bool tonormalizeMode(pxConfig *config);
+bool addnormalizedimfileMode(pxConfig *config);
+bool normalizedimfileMode(pxConfig *config);
+bool revertnormalizedimfileMode(pxConfig *config);
+bool updatenormalizedimfileMode(pxConfig *config);
+bool pendingcleanup_normalizedimfileMode(pxConfig *config);
+bool donecleanup_normalizedimfileMode(pxConfig *config);
+
+// normalizedexp
+bool tonormalizedexpMode(pxConfig *config);
+bool addnormalizedexpMode(pxConfig *config);
+bool normalizedexpMode(pxConfig *config);
+bool revertnormalizedexpMode(pxConfig *config);
+bool updatenormalizedexpMode(pxConfig *config);
+bool pendingcleanup_normalizedexpMode(pxConfig *config);
+bool donecleanup_normalizedexpMode(pxConfig *config);
+
+// residimfile
+bool toresidimfileMode(pxConfig *config);
+bool addresidimfileMode(pxConfig *config);
+bool residimfileMode(pxConfig *config);
+bool revertresidimfileMode(pxConfig *config);
+bool updateresidimfileMode(pxConfig *config);
+bool pendingcleanup_residimfileMode(pxConfig *config);
+bool donecleanup_residimfileMode(pxConfig *config);
+
+// residexp
+bool toresidexpMode(pxConfig *config);
+bool addresidexpMode(pxConfig *config);
+bool residexpMode(pxConfig *config);
+bool revertresidexpMode(pxConfig *config);
+bool updateresidexpMode(pxConfig *config);
+bool pendingcleanup_residexpMode(pxConfig *config);
+bool donecleanup_residexpMode(pxConfig *config);
+
+// detrunsummary
+bool todetrunsummaryMode(pxConfig *config);
+bool adddetrunsummaryMode(pxConfig *config);
+bool detrunsummaryMode(pxConfig *config);
+bool revertdetrunsummaryMode(pxConfig *config);
+bool updatedetrunsummaryMode(pxConfig *config);
+
+// other utilities
+bool startNewIteration(pxConfig *config, psS64 det_id);
+bool setDetRunState(pxConfig *config, psS64 det_id, const char *state);
+bool isValidDataState (const char *data_state);
+bool isValidMode(pxConfig *config, const char *mode);
+
+// functions to set the 'data_state' for stages
+bool setProcessedImfileDataState(pxConfig *config, psS64 det_id, psS64 exp_id, const char *class_id, const char *data_state);
+bool setProcessedExpDataState(pxConfig *config, psS64 det_id, psS64 exp_id, const char *data_state);
+bool setStackedImfileDataState(pxConfig *config, psS64 det_id, psS32 iteration, const char *class_id, const char *data_state);
+bool setNormStatImfileDataState(pxConfig *config, psS64 det_id, psS32 iteration, const char *class_id, const char *data_state);
+bool setNormImfileDataState(pxConfig *config, psS64 det_id, psS32 iteration, const char *class_id, const char *data_state);
+bool setNormExpDataState(pxConfig *config, psS64 det_id, psS32 iteration, const char *data_state);
+bool setResidImfileDataState(pxConfig *config, psS64 det_id, psS32 iteration, psS64 exp_id, const char *class_id, const char *data_state);
+bool setResidExpDataState(pxConfig *config, psS64 det_id, psS32 iteration, psS64 exp_id, const char *data_state);
+
+#endif // DETTOOL_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/dettoolConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/dettoolConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/dettoolConfig.c	(revision 22158)
@@ -0,0 +1,951 @@
+/*
+ * dettoolConfig.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+pxConfig *dettoolConfig(pxConfig *config, int argc, char **argv)
+{
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    pmConfigReadParamsSet(false);
+
+    // setup site config
+    config->modules = pmConfigRead(&argc, argv, NULL);
+    if (!config->modules) {
+        psError(PS_ERR_UNKNOWN, false, "Can't find site configuration");
+        psFree(config);
+        return NULL;
+    }
+
+    psTime *now = psTimeGetNow(PS_TIME_TAI);
+
+    // -pending
+    // XXX EAM : is this used?  does it make sense?
+    psMetadata *pendingArgs = psMetadataAlloc();
+    psMetadataAddS64(pendingArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exposure ID", 0);
+    psMetadataAddStr(pendingArgs, PS_LIST_TAIL, "-exp_type",  0,            "search by exposure type", NULL);
+    psMetadataAddStr(pendingArgs, PS_LIST_TAIL, "-inst",  0,            "search by camera", NULL);
+    psMetadataAddStr(pendingArgs, PS_LIST_TAIL, "-telescope",  0,            "search by telescope", NULL);
+    psMetadataAddStr(pendingArgs, PS_LIST_TAIL, "-filter",  0,            "search by filter", NULL);
+    psMetadataAddStr(pendingArgs, PS_LIST_TAIL, "-uri",  0,            "search by URL", NULL);
+    psMetadataAddBool(pendingArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -definebytag
+    psMetadata *definebytagArgs = psMetadataAlloc();
+    psMetadataAddS64(definebytagArgs, PS_LIST_TAIL, "-exp_id",            PS_META_DUPLICATE_OK,           "include this exposure (multiple OK, required)", 0);
+    psMetadataAddStr(definebytagArgs, PS_LIST_TAIL, "-det_type",  0,            "define the type of detrend run (required)", NULL);
+    psMetadataAddStr(definebytagArgs, PS_LIST_TAIL, "-mode",  0,            "define the mode of this detrend run", "master");
+    psMetadataAddStr(definebytagArgs, PS_LIST_TAIL, "-filelevel",  0,            "define filelevel", NULL);
+    psMetadataAddStr(definebytagArgs, PS_LIST_TAIL, "-workdir",  0,            "define workdir (required)", NULL);
+    psMetadataAddStr(definebytagArgs, PS_LIST_TAIL, "-inst",  0,            "define camera", NULL);
+    psMetadataAddStr(definebytagArgs, PS_LIST_TAIL, "-telescope",  0,            "define telescope", NULL);
+    psMetadataAddStr(definebytagArgs, PS_LIST_TAIL, "-exp_type",  0,            "define exposure type", NULL);
+    psMetadataAddStr(definebytagArgs, PS_LIST_TAIL, "-filter",  0,            "define filter ", NULL);
+    psMetadataAddF32(definebytagArgs, PS_LIST_TAIL, "-airmass_min",  0,            "define min airmass", NAN);
+    psMetadataAddF32(definebytagArgs, PS_LIST_TAIL, "-airmass_max",  0,            "define max airmass", NAN);
+    psMetadataAddF32(definebytagArgs, PS_LIST_TAIL, "-exp_time_min",  0,            "define min exposure time", NAN);
+    psMetadataAddF32(definebytagArgs, PS_LIST_TAIL, "-exp_time_max",  0,            "define max exposure time", NAN);
+    psMetadataAddF64(definebytagArgs, PS_LIST_TAIL, "-ccd_temp_min",  0,            "define min ccd tempature", NAN);
+    psMetadataAddF64(definebytagArgs, PS_LIST_TAIL, "-ccd_temp_max",  0,            "define max ccd tempature", NAN);
+    psMetadataAddF64(definebytagArgs, PS_LIST_TAIL, "-posang_min",  0,            "define min rotator position angle", NAN);
+    psMetadataAddF64(definebytagArgs, PS_LIST_TAIL, "-posang_max",  0,            "define max rotator position angle", NAN);
+    psMetadataAddF64(definebytagArgs, PS_LIST_TAIL, "-solang_min",  0,            "define min solar angle", NAN);
+    psMetadataAddF64(definebytagArgs, PS_LIST_TAIL, "-solang_max",  0,            "define max solar angle", NAN);
+    psMetadataAddTime(definebytagArgs, PS_LIST_TAIL, "-registered",  0,            "time detrend run was registered", now);
+    psMetadataAddTime(definebytagArgs, PS_LIST_TAIL, "-time_begin",  0,            "detrend applies to exposures taken during this period", NULL);
+    psMetadataAddTime(definebytagArgs, PS_LIST_TAIL, "-time_end",  0,            "detrend applies to exposures taken during this period", NULL);
+    psMetadataAddTime(definebytagArgs, PS_LIST_TAIL, "-use_begin",  0,            "start of detrend run applicable period", NULL);
+    psMetadataAddTime(definebytagArgs, PS_LIST_TAIL, "-use_end",  0,            "end of detrend run applicable period", NULL);
+    psMetadataAddStr(definebytagArgs, PS_LIST_TAIL, "-reduction",  0,            "define reduction class for processing", NULL);
+    psMetadataAddStr(definebytagArgs, PS_LIST_TAIL, "-label",  0,            "define detrun label", NULL);
+    psMetadataAddBool(definebytagArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -definebyquery
+    psMetadata *definebyqueryArgs = psMetadataAlloc();
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-det_type",  0,            "define the type of detrend run (required)", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-mode",  0,            "define the mode of this detrend run", "master");
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-filelevel",  0,            "define filelevel", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-workdir",  0,            "define workdir (required)", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-inst",  0,            "define camera (required)", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-telescope",  0,            "define telescope", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-filter",  0,            "define filter ", NULL);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-airmass_min",  0,            "define min airmass", NAN);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-airmass_max",  0,            "define max airmass", NAN);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-exp_time_min",  0,            "define min exposure time", NAN);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-exp_time_max",  0,            "define max exposure time", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-ccd_temp_min",  0,            "define min ccd tempature", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-ccd_temp_max",  0,            "define max ccd tempature", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-posang_min",  0,            "define min rotator position angle", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-posang_max",  0,            "define max rotator position angle", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-solang_min",  0,            "define min solar angle", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-solang_max",  0,            "define max solar angle", NAN);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-registered",  0,            "time detrend run was registered", now);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-time_begin",  0,            "detrend applies to exposures taken during this period", NULL);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-time_end",  0,            "detrend applies to exposures taken during this period", NULL);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-use_begin",  0,            "start of detrend run applicable period", NULL);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-use_end",  0,            "end of detrend run applicable period", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-select_exp_type",  0,            "search for exp_type", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-select_inst",  0,            "search for camera", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-select_telescope",  0,            "search for telescope", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-select_filter",  0,            "search for filter", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-select_uri",  0,            "search for uri", NULL);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-select_dateobs_begin", 0,            "search for exposures by time (>=)", NULL);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-select_dateobs_end", 0,            "search for exposures by time (<)", NULL);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-select_airmass_min",  0,            "define min airmass", NAN);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-select_airmass_max",  0,            "define max airmass", NAN);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-select_sat_pixel_frac_max",  0,            "define max fraction of saturated pixels", NAN);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-select_exp_time_min",  0,            "define min exposure time", NAN);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-select_exp_time_max",  0,            "define max exposure time", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-select_ccd_temp_min",  0,            "define min ccd tempature", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-select_ccd_temp_max",  0,            "define max ccd tempature", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-select_pon_time_min",  0,            "define min power-on time", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-select_pon_time_max",  0,            "define max power-on time", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-select_posang_min",  0,            "define min rotator position angle", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-select_posang_max",  0,            "define max rotator position angle", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-select_solang_min",  0,            "define min solar angle", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-select_solang_max",  0,            "define max solar angle", NAN);
+    psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-pretend",  0,            "print the exposures that would be included in the detrend run and exit", false);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-reduction",  0,            "define reduction class for processing", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-label",  0,            "define detrun label", NULL);
+    psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-random_subset",  0,            "use a random subset of elements", false);
+    psMetadataAddS32(definebyqueryArgs, PS_LIST_TAIL, "-random_limit",  0,            "use this number of random elements", 20);
+
+    // -definebydetrun
+    psMetadata *definebydetrunArgs = psMetadataAlloc();
+    psMetadataAddS64(definebydetrunArgs, PS_LIST_TAIL, "-det_id",  0,            "det ID to base a new detRun on (required)", 0);
+    psMetadataAddStr(definebydetrunArgs, PS_LIST_TAIL, "-set_det_type",  0,            "define the type of detrend run", NULL);
+    psMetadataAddStr(definebydetrunArgs, PS_LIST_TAIL, "-set_mode",  0,            "define the mode of this detrend run", "master");
+    psMetadataAddStr(definebydetrunArgs, PS_LIST_TAIL, "-set_exp_type",  0,            "define exposure type", NULL);
+    psMetadataAddStr(definebydetrunArgs, PS_LIST_TAIL, "-set_filelevel",  0,            "define filelevel", NULL);
+    psMetadataAddStr(definebydetrunArgs, PS_LIST_TAIL, "-set_workdir",  0,            "define workdir", NULL);
+    psMetadataAddStr(definebydetrunArgs, PS_LIST_TAIL, "-set_filter",  0,            "define filter ", NULL);
+    psMetadataAddF32(definebydetrunArgs, PS_LIST_TAIL, "-set_airmass_min",  0,            "define airmass", NAN);
+    psMetadataAddF32(definebydetrunArgs, PS_LIST_TAIL, "-set_airmass_max",  0,            "define airmass", NAN);
+    psMetadataAddF32(definebydetrunArgs, PS_LIST_TAIL, "-set_exp_time_min",  0,            "define exposure time", NAN);
+    psMetadataAddF32(definebydetrunArgs, PS_LIST_TAIL, "-set_exp_time_max",  0,            "define exposure time", NAN);
+    psMetadataAddF64(definebydetrunArgs, PS_LIST_TAIL, "-set_ccd_temp_min",  0,            "define ccd tempature", NAN);
+    psMetadataAddF64(definebydetrunArgs, PS_LIST_TAIL, "-set_ccd_temp_max",  0,            "define ccd tempature", NAN);
+    psMetadataAddF64(definebydetrunArgs, PS_LIST_TAIL, "-set_posang_min",  0,            "define rotator position angle", NAN);
+    psMetadataAddF64(definebydetrunArgs, PS_LIST_TAIL, "-set_posang_max",  0,            "define rotator position angle", NAN);
+    psMetadataAddF64(definebydetrunArgs, PS_LIST_TAIL, "-set_solang_min",  0,            "define solar angle", NAN);
+    psMetadataAddF64(definebydetrunArgs, PS_LIST_TAIL, "-set_solang_max",  0,            "define solar angle", NAN);
+    psMetadataAddTime(definebydetrunArgs, PS_LIST_TAIL, "-set_registered",  0,            "time detrend run was registered", now);
+    psMetadataAddTime(definebydetrunArgs, PS_LIST_TAIL, "-set_time_begin",  0,            "start of period to apply detrend too", NULL);
+    psMetadataAddTime(definebydetrunArgs, PS_LIST_TAIL, "-set_time_end",  0,            "end of period to apply detrend too", NULL);
+    psMetadataAddTime(definebydetrunArgs, PS_LIST_TAIL, "-set_use_begin",  0,            "start of detrend run applicable period", NULL);
+    psMetadataAddTime(definebydetrunArgs, PS_LIST_TAIL, "-set_use_end",  0,            "end of detrend run applicable period", NULL);
+    psMetadataAddStr(definebydetrunArgs, PS_LIST_TAIL, "-set_reduction",  0,            "define reduction class for processing", NULL);
+    psMetadataAddStr(definebydetrunArgs, PS_LIST_TAIL, "-set_label",  0,            "define detrun label", NULL);
+    psMetadataAddBool(definebydetrunArgs, PS_LIST_TAIL, "-simple", 0,            "use the simple output format", false);
+    psMetadataAddStr(definebydetrunArgs, PS_LIST_TAIL, "-set_input_begin", 0,     "require input exp to be in this period", NULL);
+    psMetadataAddStr(definebydetrunArgs, PS_LIST_TAIL, "-set_input_end", 0,       "require input exp to be in this period", NULL);
+
+    // *** these are in dettool_correction.c ***
+    // -makecorrection
+    psMetadata *makecorrectionArgs = psMetadataAlloc();
+    psMetadataAddS64(makecorrectionArgs, PS_LIST_TAIL, "-det_id",  0,            "det ID to be corrected (required)", 0);
+    psMetadataAddBool(makecorrectionArgs, PS_LIST_TAIL, "-simple", 0,            "use the simple output format", false);
+
+    // -tocorrectexp
+    psMetadata *tocorrectexpArgs = psMetadataAlloc();
+    psMetadataAddU64(tocorrectexpArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(tocorrectexpArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -tocorrectimfile
+    psMetadata *tocorrectimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(tocorrectimfileArgs, PS_LIST_TAIL, "-det_id", 0,            "search for detrend ID", 0);
+    psMetadataAddU64(tocorrectimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(tocorrectimfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -addcorrectimfile
+    psMetadata *addcorrectimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(addcorrectimfileArgs, PS_LIST_TAIL, "-det_id",  0,            "define detrend ID (required)", 0);
+    psMetadataAddStr(addcorrectimfileArgs, PS_LIST_TAIL, "-class_id",  0,            "search for class ID (required)", NULL);
+    psMetadataAddStr(addcorrectimfileArgs, PS_LIST_TAIL, "-uri",  0,            "define resid file URI", NULL);
+    psMetadataAddF64(addcorrectimfileArgs, PS_LIST_TAIL, "-bg",  0,            "define exposure background", NAN);
+    psMetadataAddF64(addcorrectimfileArgs, PS_LIST_TAIL, "-bg_stdev",  0,            "define exposure background stdev", NAN);
+    psMetadataAddF64(addcorrectimfileArgs, PS_LIST_TAIL, "-bg_mean_stdev",  0,            "define exposure background mean stdev", NAN);
+    psMetadataAddF64(addcorrectimfileArgs, PS_LIST_TAIL, "-user_1",  0,            "define user statistic (1)", NAN);
+    psMetadataAddF64(addcorrectimfileArgs, PS_LIST_TAIL, "-user_2",  0,            "define user statistic (2)", NAN);
+    psMetadataAddF64(addcorrectimfileArgs, PS_LIST_TAIL, "-user_3",  0,            "define user statistic (3)", NAN);
+    psMetadataAddF64(addcorrectimfileArgs, PS_LIST_TAIL, "-user_4",  0,            "define user statistic (4)", NAN);
+    psMetadataAddF64(addcorrectimfileArgs, PS_LIST_TAIL, "-user_5",  0,            "define user statistic (5)", NAN);
+    psMetadataAddStr(addcorrectimfileArgs, PS_LIST_TAIL, "-path_base",  0,            "define base output location", NULL);
+
+    // -runs
+    psMetadata *runsArgs = psMetadataAlloc();
+    psMetadataAddStr(runsArgs, PS_LIST_TAIL, "-det_type",  0,            "search for type of detrend run", NULL);
+    psMetadataAddS64(runsArgs, PS_LIST_TAIL, "-det_id", 0,            "search for detrend ID", 0);
+    psMetadataAddStr(runsArgs, PS_LIST_TAIL, "-inst", 0,            "search for camera (instrument)", NULL);
+    psMetadataAddStr(runsArgs, PS_LIST_TAIL, "-telescope", 0,            "search for telescope", NULL);
+    psMetadataAddStr(runsArgs, PS_LIST_TAIL, "-filter", 0,            "search for filter", NULL);
+    psMetadataAddF32(runsArgs, PS_LIST_TAIL, "-airmass", 0,            "match airmass", NAN);
+    psMetadataAddF32(runsArgs, PS_LIST_TAIL, "-exp_time", 0,            "match exp time", NAN);
+    psMetadataAddF32(runsArgs, PS_LIST_TAIL, "-ccd_temp", 0,            "match ccd temp", NAN);
+    psMetadataAddF64(runsArgs, PS_LIST_TAIL, "-posang", 0,            "match posang", NAN);
+    psMetadataAddBool(runsArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddBool(runsArgs, PS_LIST_TAIL, "-active",  0,            "only return active detRuns", false);
+    psMetadataAddU64(runsArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -childlessrun
+    psMetadata *childlessrunArgs = psMetadataAlloc();
+    psMetadataAddStr(childlessrunArgs, PS_LIST_TAIL, "-det_type",  0,            "search for type of detrend run", NULL);
+    psMetadataAddU64(childlessrunArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(childlessrunArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -input
+    psMetadata *inputArgs = psMetadataAlloc();
+    psMetadataAddS64(inputArgs, PS_LIST_TAIL, "-det_id", 0,            "search for detrend ID", 0);
+    psMetadataAddS32(inputArgs, PS_LIST_TAIL, "-iteration",  0,            "define iteration number", 0);
+    psMetadataAddS64(inputArgs, PS_LIST_TAIL, "-exp_id",  0,            "search for exp ID", 0);
+    psMetadataAddBool(inputArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -raw
+    psMetadata *rawArgs = psMetadataAlloc();
+    psMetadataAddBool(rawArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -toprocessedimfile
+    psMetadata *toprocessedimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(toprocessedimfileArgs, PS_LIST_TAIL, "-det_id",  0,            "search for detrend ID", 0);
+    psMetadataAddS64(toprocessedimfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "search for exp ID", 0);
+    psMetadataAddStr(toprocessedimfileArgs, PS_LIST_TAIL, "-class_id",  0,            "search for class ID", NULL);
+    psMetadataAddU64(toprocessedimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(toprocessedimfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -addprocessedimfile
+    psMetadata *addprocessedimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(addprocessedimfileArgs, PS_LIST_TAIL, "-det_id",  0,            "define detrend ID (required)", 0);
+    psMetadataAddS64(addprocessedimfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "define exp ID (required)", 0);
+    psMetadataAddStr(addprocessedimfileArgs, PS_LIST_TAIL, "-class_id",  0,            "define class ID (required)", NULL);
+    psMetadataAddS16(addprocessedimfileArgs, PS_LIST_TAIL, "-code",  0,            "set fault code", 0);
+    psMetadataAddStr(addprocessedimfileArgs, PS_LIST_TAIL, "-uri",  0,            "define URI", NULL);
+    psMetadataAddStr(addprocessedimfileArgs, PS_LIST_TAIL, "-recip",  0,            "define recipe", NULL);
+    psMetadataAddF64(addprocessedimfileArgs, PS_LIST_TAIL, "-bg",  0,            "define exposure background", NAN);
+    psMetadataAddF64(addprocessedimfileArgs, PS_LIST_TAIL, "-bg_stdev",  0,            "define exposure background stdev", NAN);
+    psMetadataAddF64(addprocessedimfileArgs, PS_LIST_TAIL, "-bg_mean_stdev",  0,            "define exposure background mean stdev", NAN);
+    psMetadataAddF64(addprocessedimfileArgs, PS_LIST_TAIL, "-fringe_0",  0,            "define fringe slope (0th term)", NAN);
+    psMetadataAddF64(addprocessedimfileArgs, PS_LIST_TAIL, "-fringe_1",  0,            "define fringe slope (1st term)", NAN);
+    psMetadataAddF64(addprocessedimfileArgs, PS_LIST_TAIL, "-fringe_2",  0,            "define fringe slope (2nd term)", NAN);
+    psMetadataAddF64(addprocessedimfileArgs, PS_LIST_TAIL, "-user_1",  0,            "define user statistic (1)", NAN);
+    psMetadataAddF64(addprocessedimfileArgs, PS_LIST_TAIL, "-user_2",  0,            "define user statistic (2)", NAN);
+    psMetadataAddF64(addprocessedimfileArgs, PS_LIST_TAIL, "-user_3",  0,            "define user statistic (3)", NAN);
+    psMetadataAddF64(addprocessedimfileArgs, PS_LIST_TAIL, "-user_4",  0,            "define user statistic (4)", NAN);
+    psMetadataAddF64(addprocessedimfileArgs, PS_LIST_TAIL, "-user_5",  0,            "define user statistic (5)", NAN);
+    psMetadataAddStr(addprocessedimfileArgs, PS_LIST_TAIL, "-path_base",  0,            "define base output location", NULL);
+
+    // -processedimfile
+    psMetadata *processedimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(processedimfileArgs, PS_LIST_TAIL, "-det_id",  0,            "search for detrend ID", 0);
+    psMetadataAddS64(processedimfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "search for exp ID", 0);
+    psMetadataAddStr(processedimfileArgs, PS_LIST_TAIL, "-class_id",  0,            "search for class ID", NULL);
+    psMetadataAddStr(processedimfileArgs, PS_LIST_TAIL, "-select_state",  0,            "search for state", NULL);
+    psMetadataAddStr(processedimfileArgs, PS_LIST_TAIL, "-select_mode",  0,            "search for mode", NULL);
+    psMetadataAddBool(processedimfileArgs, PS_LIST_TAIL, "-included",  0,            "restrict results to exposures 'includeded' in the current iteration", false);
+    psMetadataAddBool(processedimfileArgs, PS_LIST_TAIL, "-faulted",  0,            "only return imfiles with a fault status set", false);
+    psMetadataAddU64(processedimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(processedimfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -revertprocessedimfile
+    psMetadata *revertprocessedimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(revertprocessedimfileArgs, PS_LIST_TAIL, "-det_id",  0,            "search for detrend ID (required)", 0);
+    psMetadataAddS64(revertprocessedimfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exposure ID", 0);
+    psMetadataAddStr(revertprocessedimfileArgs, PS_LIST_TAIL, "-class_id",  0,            "search by class ID", NULL);
+    psMetadataAddS16(revertprocessedimfileArgs, PS_LIST_TAIL, "-code",  0,            "search by fault code", 0);
+
+    // -updateprocessedimfile
+    psMetadata *updateprocessedimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(updateprocessedimfileArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS64(updateprocessedimfileArgs, PS_LIST_TAIL, "-exp_id",               0,            "search by exp_id", 0);
+    psMetadataAddStr(updateprocessedimfileArgs, PS_LIST_TAIL, "-class_id",             0,            "search by exp_name", NULL);
+    psMetadataAddStr(updateprocessedimfileArgs, PS_LIST_TAIL, "-data_state",           0,            "search for telescope", NULL);
+
+    // -pendingcleanup_processedimfile
+    psMetadata *pendingcleanup_processedimfileArgs = psMetadataAlloc();
+    psMetadataAddBool(pendingcleanup_processedimfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanup_processedimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddS64(pendingcleanup_processedimfileArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS64(pendingcleanup_processedimfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exposure ID", 0);
+    psMetadataAddStr(pendingcleanup_processedimfileArgs, PS_LIST_TAIL, "-class_id",  0,            "search by class ID", NULL);
+
+    // -donecleanup_processedimfile
+    psMetadata *donecleanup_processedimfileArgs = psMetadataAlloc();
+    psMetadataAddBool(donecleanup_processedimfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(donecleanup_processedimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddS64(donecleanup_processedimfileArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS64(donecleanup_processedimfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exposure ID", 0);
+    psMetadataAddStr(donecleanup_processedimfileArgs, PS_LIST_TAIL, "-class_id",  0,            "search by class ID", NULL);
+
+    // -toprocessedexp
+    psMetadata *toprocessedexpArgs = psMetadataAlloc();
+    psMetadataAddU64(toprocessedexpArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(toprocessedexpArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -addproccessedexp
+    psMetadata *addprocessedexpArgs = psMetadataAlloc();
+    psMetadataAddS64(addprocessedexpArgs, PS_LIST_TAIL, "-det_id",  0,            "define detrend ID (required)", 0);
+    psMetadataAddS64(addprocessedexpArgs, PS_LIST_TAIL, "-exp_id",  0,            "define detrend ID (required)", 0);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-recip",  0,            "define recipe", NULL);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-bg",  0,            "define exposure background", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-bg_stdev",  0,            "define exposure background stdev", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-bg_mean_stdev",  0,            "define exposure background mean stdev", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-fringe_0",  0,            "define fringe slope (0th term)", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-fringe_1",  0,            "define fringe slope (1st term)", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-fringe_2",  0,            "define fringe slope (2nd term)", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-user_1",  0,            "define user statistic (1)", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-user_2",  0,            "define user statistic (2)", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-user_3",  0,            "define user statistic (3)", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-user_4",  0,            "define user statistic (4)", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-user_5",  0,            "define user statistic (5)", NAN);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-path_base",  0,            "define base output location", NULL);
+    psMetadataAddS16(addprocessedexpArgs, PS_LIST_TAIL, "-code",  0,            "set fault code", 0);
+
+    // -proccessedexp
+    psMetadata *processedexpArgs = psMetadataAlloc();
+    psMetadataAddS64(processedexpArgs, PS_LIST_TAIL, "-det_id",  0,            "search by detrend ID", 0);
+    psMetadataAddS64(processedexpArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exp ID", 0);
+    psMetadataAddU64(processedexpArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(processedexpArgs, PS_LIST_TAIL, "-faulted",  0,            "only return imfiles with a fault status set", false);
+    psMetadataAddBool(processedexpArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -revertprocessedexp
+    psMetadata *revertprocessedexpArgs = psMetadataAlloc();
+    psMetadataAddS64(revertprocessedexpArgs, PS_LIST_TAIL, "-det_id",  0,            "search by detrend ID (required)", 0);
+    psMetadataAddS64(revertprocessedexpArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exposure ID", 0);
+    psMetadataAddS16(revertprocessedexpArgs, PS_LIST_TAIL, "-code",  0,            "search by fault code", 0);
+
+    // -updateprocessedexp
+    psMetadata *updateprocessedexpArgs = psMetadataAlloc();
+    psMetadataAddS64(updateprocessedexpArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS64(updateprocessedexpArgs, PS_LIST_TAIL, "-exp_id",               0,            "search by exp_id", 0);
+    psMetadataAddStr(updateprocessedexpArgs, PS_LIST_TAIL, "-data_state",           0,            "search for telescope", NULL);
+
+    // -pendingcleanup_processedexp
+    psMetadata *pendingcleanup_processedexpArgs = psMetadataAlloc();
+    psMetadataAddBool(pendingcleanup_processedexpArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanup_processedexpArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddS64(pendingcleanup_processedexpArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS64(pendingcleanup_processedexpArgs, PS_LIST_TAIL, "-exp_id",               0,            "search by exp_id", 0);
+
+    // -donecleanup_processedexp
+    psMetadata *donecleanup_processedexpArgs = psMetadataAlloc();
+    psMetadataAddBool(donecleanup_processedexpArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(donecleanup_processedexpArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddS64(donecleanup_processedexpArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS64(donecleanup_processedexpArgs, PS_LIST_TAIL, "-exp_id",               0,            "search by exp_id", 0);
+
+    // -tostacked
+    psMetadata *tostackedArgs = psMetadataAlloc();
+    psMetadataAddU64(tostackedArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(tostackedArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -addstacked
+    psMetadata *addstackedArgs = psMetadataAlloc();
+    psMetadataAddS64(addstackedArgs, PS_LIST_TAIL, "-det_id",  0,            "define detrend ID (required)", 0);
+    psMetadataAddS32(addstackedArgs, PS_LIST_TAIL, "-iteration",  0,            "define iteration number (required)", 0);
+    psMetadataAddStr(addstackedArgs, PS_LIST_TAIL, "-class_id",  0,            "define class ID (required)", NULL);
+    psMetadataAddS16(addstackedArgs, PS_LIST_TAIL, "-code",  0,            "set fault code", 0);
+    psMetadataAddStr(addstackedArgs, PS_LIST_TAIL, "-uri",  0,            "define URI", NULL);
+    psMetadataAddStr(addstackedArgs, PS_LIST_TAIL, "-recip",  0,            "define recipe", NULL);
+    psMetadataAddF64(addstackedArgs, PS_LIST_TAIL, "-bg",  0,            "define exposure background", NAN);
+    psMetadataAddF64(addstackedArgs, PS_LIST_TAIL, "-bg_stdev",  0,            "define exposure background stdev", NAN);
+    psMetadataAddF64(addstackedArgs, PS_LIST_TAIL, "-bg_mean_stdev",  0,            "define exposure background mean stdev", NAN);
+    psMetadataAddF64(addstackedArgs, PS_LIST_TAIL, "-user_1",  0,            "define user statistic (1)", NAN);
+    psMetadataAddF64(addstackedArgs, PS_LIST_TAIL, "-user_2",  0,            "define user statistic (2)", NAN);
+    psMetadataAddF64(addstackedArgs, PS_LIST_TAIL, "-user_3",  0,            "define user statistic (3)", NAN);
+    psMetadataAddF64(addstackedArgs, PS_LIST_TAIL, "-user_4",  0,            "define user statistic (4)", NAN);
+    psMetadataAddF64(addstackedArgs, PS_LIST_TAIL, "-user_5",  0,            "define user statistic (5)", NAN);
+
+    // -stacked
+    psMetadata *stackedArgs = psMetadataAlloc();
+    psMetadataAddS64(stackedArgs, PS_LIST_TAIL, "-det_id",  0,            "search for detrend ID", 0);
+    psMetadataAddS32(stackedArgs, PS_LIST_TAIL, "-iteration",  0,            "search for iteration number", 0);
+    psMetadataAddStr(stackedArgs, PS_LIST_TAIL, "-class_id",  0,            "search for class ID", NULL);
+    psMetadataAddStr(stackedArgs, PS_LIST_TAIL, "-recip",  0,            "search for recipe", NULL);
+    psMetadataAddU64(stackedArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(stackedArgs, PS_LIST_TAIL, "-faulted",  0,            "only return imfiles with a fault status set", false);
+    psMetadataAddBool(stackedArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -revertstacked
+    psMetadata *revertstackedArgs= psMetadataAlloc();
+    psMetadataAddS64(revertstackedArgs, PS_LIST_TAIL, "-det_id",  0,            "search for detrend ID (required)", 0);
+    psMetadataAddS32(revertstackedArgs, PS_LIST_TAIL, "-iteration",  0,            "search by iteration number", 0);
+    psMetadataAddStr(revertstackedArgs, PS_LIST_TAIL, "-class_id",  0,            "search by class ID", NULL);
+    psMetadataAddS16(revertstackedArgs, PS_LIST_TAIL, "-code",  0,            "search by fault code", 0);
+
+    // -updatestacked
+    psMetadata *updatestackedArgs = psMetadataAlloc();
+    psMetadataAddS64(updatestackedArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS32(updatestackedArgs, PS_LIST_TAIL, "-iteration",  0,            "search by iteration number", 0);
+    psMetadataAddStr(updatestackedArgs, PS_LIST_TAIL, "-class_id",  0,            "search by class ID", NULL);
+    psMetadataAddStr(updatestackedArgs, PS_LIST_TAIL, "-data_state",           0,            "search for telescope", NULL);
+
+    // -pendingcleanup_stacked
+    psMetadata *pendingcleanup_stackedArgs = psMetadataAlloc();
+    psMetadataAddBool(pendingcleanup_stackedArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanup_stackedArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddS64(pendingcleanup_stackedArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS32(pendingcleanup_stackedArgs, PS_LIST_TAIL, "-iteration",  0,            "search by iteration number", 0);
+    psMetadataAddStr(pendingcleanup_stackedArgs, PS_LIST_TAIL, "-class_id",  0,            "search by class ID", NULL);
+
+    // -donecleanup_stacked
+    psMetadata *donecleanup_stackedArgs = psMetadataAlloc();
+    psMetadataAddBool(donecleanup_stackedArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(donecleanup_stackedArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddS64(donecleanup_stackedArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS32(donecleanup_stackedArgs, PS_LIST_TAIL, "-iteration",  0,            "search by iteration number", 0);
+    psMetadataAddStr(donecleanup_stackedArgs, PS_LIST_TAIL, "-class_id",  0,            "search by class ID", NULL);
+
+    // -tonormalizedstat
+    psMetadata *tonormalizedstatArgs = psMetadataAlloc();
+    psMetadataAddU64(tonormalizedstatArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(tonormalizedstatArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -addnormalizedstat
+    psMetadata *addnormstatArgs = psMetadataAlloc();
+    psMetadataAddS64(addnormstatArgs, PS_LIST_TAIL, "-det_id",  0,            "define detrend ID (required)", 0);
+    psMetadataAddS32(addnormstatArgs, PS_LIST_TAIL, "-iteration",  0,            "define iteration number", 0);
+    psMetadataAddStr(addnormstatArgs, PS_LIST_TAIL, "-class_id",  0,            "define class ID (required)", NULL);
+    psMetadataAddF32(addnormstatArgs, PS_LIST_TAIL, "-norm",  0,            "define normal value (required)", NAN);
+    psMetadataAddS16(addnormstatArgs, PS_LIST_TAIL, "-code",  0,            "set fault code", 0);
+
+    // -normalizedstat
+    psMetadata *normalizedstatArgs = psMetadataAlloc();
+    psMetadataAddS64(normalizedstatArgs, PS_LIST_TAIL, "-det_id",  0,            "search by detrend ID", 0);
+    psMetadataAddS32(normalizedstatArgs, PS_LIST_TAIL, "-iteration",  0,            "search by iteration number", 0);
+    psMetadataAddStr(normalizedstatArgs, PS_LIST_TAIL, "-class_id",  0,            "search by class ID", NULL);
+    psMetadataAddU64(normalizedstatArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(normalizedstatArgs, PS_LIST_TAIL, "-faulted",  0,            "only return imfiles with a fault status set", false);
+    psMetadataAddBool(normalizedstatArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -revertnormalizedstat
+    psMetadata *revertnormalizedstatArgs= psMetadataAlloc();
+    psMetadataAddS64(revertnormalizedstatArgs, PS_LIST_TAIL, "-det_id",  0,            "search by detrend ID (required)", 0);
+    psMetadataAddS32(revertnormalizedstatArgs, PS_LIST_TAIL, "-iteration",  0,            "search by iteration number", 0);
+    psMetadataAddStr(revertnormalizedstatArgs, PS_LIST_TAIL, "-class_id",  0,            "search by class ID", NULL);
+    psMetadataAddS16(revertnormalizedstatArgs, PS_LIST_TAIL, "-code",  0,            "search by fault code", 0);
+
+    // -updatenormalizedstat
+    psMetadata *updatenormalizedstatArgs = psMetadataAlloc();
+    psMetadataAddS64(updatenormalizedstatArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS32(updatenormalizedstatArgs, PS_LIST_TAIL, "-iteration",  0,            "search by iteration number", 0);
+    psMetadataAddStr(updatenormalizedstatArgs, PS_LIST_TAIL, "-class_id",             0,            "search by exp_name", NULL);
+    psMetadataAddStr(updatenormalizedstatArgs, PS_LIST_TAIL, "-data_state",           0,            "search for telescope", NULL);
+
+    // -pendingcleanup_normalizedstat
+    psMetadata *pendingcleanup_normalizedstatArgs = psMetadataAlloc();
+    psMetadataAddBool(pendingcleanup_normalizedstatArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanup_normalizedstatArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddS64(pendingcleanup_normalizedstatArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS32(pendingcleanup_normalizedstatArgs, PS_LIST_TAIL, "-iteration",  0,            "search by iteration number", 0);
+    psMetadataAddStr(pendingcleanup_normalizedstatArgs, PS_LIST_TAIL, "-class_id",             0,            "search by exp_name", NULL);
+
+    // -donecleanup_normalizedstat
+    psMetadata *donecleanup_normalizedstatArgs = psMetadataAlloc();
+    psMetadataAddBool(donecleanup_normalizedstatArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(donecleanup_normalizedstatArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddS64(donecleanup_normalizedstatArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS32(donecleanup_normalizedstatArgs, PS_LIST_TAIL, "-iteration",  0,            "search by iteration number", 0);
+    psMetadataAddStr(donecleanup_normalizedstatArgs, PS_LIST_TAIL, "-class_id",             0,            "search by exp_name", NULL);
+
+    // -tonormalize
+    psMetadata *tonormalizeArgs = psMetadataAlloc();
+    psMetadataAddU64(tonormalizeArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(tonormalizeArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -addnormalizedimfile
+    psMetadata *addnormalizedimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(addnormalizedimfileArgs, PS_LIST_TAIL, "-det_id", 0,            "define detrend ID (required)", 0);
+    psMetadataAddS32(addnormalizedimfileArgs, PS_LIST_TAIL, "-iteration", 0,            "define iteration number", 0);
+    psMetadataAddStr(addnormalizedimfileArgs, PS_LIST_TAIL, "-class_id", 0,            "define class ID (required)", NULL);
+    psMetadataAddS16(addnormalizedimfileArgs, PS_LIST_TAIL, "-code",  0,            "set fault code", 0);
+    psMetadataAddStr(addnormalizedimfileArgs, PS_LIST_TAIL, "-uri", 0,            "define URI", NULL);
+    psMetadataAddF64(addnormalizedimfileArgs, PS_LIST_TAIL, "-bg", 0,            "define exposure background", NAN);
+    psMetadataAddF64(addnormalizedimfileArgs, PS_LIST_TAIL, "-bg_stdev", 0,            "define exposure background stdev", NAN);
+    psMetadataAddF64(addnormalizedimfileArgs, PS_LIST_TAIL, "-bg_mean_stdev", 0,            "define exposure background mean stdev", NAN);
+    psMetadataAddF64(addnormalizedimfileArgs, PS_LIST_TAIL, "-user_1",  0,            "define user statistic (1)", NAN);
+    psMetadataAddF64(addnormalizedimfileArgs, PS_LIST_TAIL, "-user_2",  0,            "define user statistic (2)", NAN);
+    psMetadataAddF64(addnormalizedimfileArgs, PS_LIST_TAIL, "-user_3",  0,            "define user statistic (3)", NAN);
+    psMetadataAddF64(addnormalizedimfileArgs, PS_LIST_TAIL, "-user_4",  0,            "define user statistic (4)", NAN);
+    psMetadataAddF64(addnormalizedimfileArgs, PS_LIST_TAIL, "-user_5",  0,            "define user statistic (5)", NAN);
+    psMetadataAddStr(addnormalizedimfileArgs, PS_LIST_TAIL, "-path_base", 0,            "define base output location", NULL);
+
+    // -normalizedimfile
+    psMetadata *normalizedimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(normalizedimfileArgs, PS_LIST_TAIL, "-det_id",  0,            "search for detrend ID", 0);
+    psMetadataAddS32(normalizedimfileArgs, PS_LIST_TAIL, "-iteration",  0,            "search for iteration number", 0);
+    psMetadataAddStr(normalizedimfileArgs, PS_LIST_TAIL, "-class_id",  0,            "search for class ID", NULL);
+    psMetadataAddStr(normalizedimfileArgs, PS_LIST_TAIL, "-recip",  0,            "search for recipe", NULL);
+    psMetadataAddU64(normalizedimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(normalizedimfileArgs, PS_LIST_TAIL, "-faulted",  0,            "only return imfiles with a fault status set", false);
+    psMetadataAddBool(normalizedimfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -revertnormalizedimfile
+    psMetadata *revertnormalizedimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(revertnormalizedimfileArgs, PS_LIST_TAIL, "-det_id", 0,            "search by detrend ID (required)", 0);
+    psMetadataAddS32(revertnormalizedimfileArgs, PS_LIST_TAIL, "-iteration", 0,            "search by iteration number", 0);
+    psMetadataAddStr(revertnormalizedimfileArgs, PS_LIST_TAIL, "-class_id", 0,            "search by class ID", NULL);
+    psMetadataAddS16(revertnormalizedimfileArgs, PS_LIST_TAIL, "-code",  0,            "search by fault code", 0);
+
+    // -updatenormalizedimfile
+    psMetadata *updatenormalizedimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(updatenormalizedimfileArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS32(updatenormalizedimfileArgs, PS_LIST_TAIL, "-iteration", 0,            "search by iteration number", 0);
+    psMetadataAddStr(updatenormalizedimfileArgs, PS_LIST_TAIL, "-class_id",             0,            "search by exp_name", NULL);
+    psMetadataAddStr(updatenormalizedimfileArgs, PS_LIST_TAIL, "-data_state",           0,            "search for telescope", NULL);
+
+    // -pendingcleanup_normalizedimfile
+    psMetadata *pendingcleanup_normalizedimfileArgs = psMetadataAlloc();
+    psMetadataAddBool(pendingcleanup_normalizedimfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanup_normalizedimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddS64(pendingcleanup_normalizedimfileArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS32(pendingcleanup_normalizedimfileArgs, PS_LIST_TAIL, "-iteration", 0,            "search by iteration number", 0);
+    psMetadataAddStr(pendingcleanup_normalizedimfileArgs, PS_LIST_TAIL, "-class_id",             0,            "search by exp_name", NULL);
+
+    // -donecleanup_normalizedimfile
+    psMetadata *donecleanup_normalizedimfileArgs = psMetadataAlloc();
+    psMetadataAddBool(donecleanup_normalizedimfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(donecleanup_normalizedimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddS64(donecleanup_normalizedimfileArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS32(donecleanup_normalizedimfileArgs, PS_LIST_TAIL, "-iteration", 0,            "search by iteration number", 0);
+    psMetadataAddStr(donecleanup_normalizedimfileArgs, PS_LIST_TAIL, "-class_id",             0,            "search by exp_name", NULL);
+
+    // -tonormalizedexp
+    psMetadata *tonormalizedexpArgs = psMetadataAlloc();
+    psMetadataAddU64(tonormalizedexpArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(tonormalizedexpArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -addnormalizedexp
+    psMetadata *addnormalizedexpArgs = psMetadataAlloc();
+    psMetadataAddS64(addnormalizedexpArgs, PS_LIST_TAIL, "-det_id",  0,            "define detrend ID (required)", 0);
+    psMetadataAddS32(addnormalizedexpArgs, PS_LIST_TAIL, "-iteration",  0,            "define iteration number", 0);
+    psMetadataAddS16(addnormalizedexpArgs, PS_LIST_TAIL, "-code",  0,            "set fault code", 0);
+    psMetadataAddStr(addnormalizedexpArgs, PS_LIST_TAIL, "-recip",  0,            "search for recipe", NULL);
+    psMetadataAddF64(addnormalizedexpArgs, PS_LIST_TAIL, "-bg",  0,            "define exposure background", NAN);
+    psMetadataAddF64(addnormalizedexpArgs, PS_LIST_TAIL, "-bg_stdev",  0,            "define exposure background stdev", NAN);
+    psMetadataAddF64(addnormalizedexpArgs, PS_LIST_TAIL, "-bg_mean_stdev",  0,            "define exposure background mean stdev", NAN);
+    psMetadataAddF64(addnormalizedexpArgs, PS_LIST_TAIL, "-user_1",  0,            "define user statistic (1)", NAN);
+    psMetadataAddF64(addnormalizedexpArgs, PS_LIST_TAIL, "-user_2",  0,            "define user statistic (2)", NAN);
+    psMetadataAddF64(addnormalizedexpArgs, PS_LIST_TAIL, "-user_3",  0,            "define user statistic (3)", NAN);
+    psMetadataAddF64(addnormalizedexpArgs, PS_LIST_TAIL, "-user_4",  0,            "define user statistic (4)", NAN);
+    psMetadataAddF64(addnormalizedexpArgs, PS_LIST_TAIL, "-user_5",  0,            "define user statistic (5)", NAN);
+    psMetadataAddStr(addnormalizedexpArgs, PS_LIST_TAIL, "-path_base",  0,            "define base output location", NULL);
+
+    // -normalizedexp
+    psMetadata *normalizedexpArgs = psMetadataAlloc();
+    psMetadataAddS64(normalizedexpArgs, PS_LIST_TAIL, "-det_id",  0,            "search by detrend ID", 0);
+    psMetadataAddS32(normalizedexpArgs, PS_LIST_TAIL, "-iteration",  0,            "search by iteration number", 0);
+    psMetadataAddStr(normalizedexpArgs, PS_LIST_TAIL, "-recip",  0,            "search for recipe", NULL);
+    psMetadataAddU64(normalizedexpArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(normalizedexpArgs, PS_LIST_TAIL, "-faulted",  0,            "only return imfiles with a fault status set", false);
+    psMetadataAddBool(normalizedexpArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -revertnormalizedexp
+    psMetadata *revertnormalizedexpArgs = psMetadataAlloc();
+    psMetadataAddS64(revertnormalizedexpArgs, PS_LIST_TAIL, "-det_id", 0,            "search by detrend ID (required)", 0);
+    psMetadataAddS32(revertnormalizedexpArgs, PS_LIST_TAIL, "-iteration", 0,            "search by iteration number", 0);
+    psMetadataAddS16(revertnormalizedexpArgs, PS_LIST_TAIL, "-code",  0,            "search by fault code", 0);
+
+    // -updatenormalizedexp
+    psMetadata *updatenormalizedexpArgs = psMetadataAlloc();
+    psMetadataAddS64(updatenormalizedexpArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS32(updatenormalizedexpArgs, PS_LIST_TAIL, "-iteration", 0,            "search by iteration number", 0);
+    psMetadataAddStr(updatenormalizedexpArgs, PS_LIST_TAIL, "-data_state",           0,            "search for telescope", NULL);
+
+    // -pendingcleanup_normalizedexp
+    psMetadata *pendingcleanup_normalizedexpArgs = psMetadataAlloc();
+    psMetadataAddBool(pendingcleanup_normalizedexpArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanup_normalizedexpArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddS64(pendingcleanup_normalizedexpArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS32(pendingcleanup_normalizedexpArgs, PS_LIST_TAIL, "-iteration", 0,            "search by iteration number", 0);
+
+    // -donecleanup_normalizedexp
+    psMetadata *donecleanup_normalizedexpArgs = psMetadataAlloc();
+    psMetadataAddBool(donecleanup_normalizedexpArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(donecleanup_normalizedexpArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddS64(donecleanup_normalizedexpArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS32(donecleanup_normalizedexpArgs, PS_LIST_TAIL, "-iteration", 0,            "search by iteration number", 0);
+
+    // -toresidimfile
+    psMetadata *toresidimfileArgs = psMetadataAlloc();
+    psMetadataAddU64(toresidimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(toresidimfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -addresidimfile
+    psMetadata *addresidimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(addresidimfileArgs, PS_LIST_TAIL, "-det_id",  0,            "define detrend ID (required)", 0);
+    psMetadataAddS32(addresidimfileArgs, PS_LIST_TAIL, "-iteration",  0,            "define iteration number", 0);
+    psMetadataAddS64(addresidimfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "define detrend ID (required)", 0);
+    psMetadataAddStr(addresidimfileArgs, PS_LIST_TAIL, "-class_id",  0,            "define class ID (required)", NULL);
+    psMetadataAddS16(addresidimfileArgs, PS_LIST_TAIL, "-code",  0,            "set fault code", 0);
+    psMetadataAddStr(addresidimfileArgs, PS_LIST_TAIL, "-uri",  0,            "define resid file URI", NULL);
+    psMetadataAddStr(addresidimfileArgs, PS_LIST_TAIL, "-recip",  0,            "define recipe", NULL);
+    psMetadataAddF64(addresidimfileArgs, PS_LIST_TAIL, "-bg",  0,            "define exposure background", NAN);
+    psMetadataAddF64(addresidimfileArgs, PS_LIST_TAIL, "-bg_stdev",  0,            "define exposure background stdev", NAN);
+    psMetadataAddF64(addresidimfileArgs, PS_LIST_TAIL, "-bg_mean_stdev",  0,            "define exposure background mean stdev", NAN);
+    psMetadataAddF64(addresidimfileArgs, PS_LIST_TAIL, "-bg_skewness",  0,            "define exposure background skewness", NAN);
+    psMetadataAddF64(addresidimfileArgs, PS_LIST_TAIL, "-bg_kurtosis",  0,            "define exposure background kurtosis", NAN);
+    psMetadataAddF64(addresidimfileArgs, PS_LIST_TAIL, "-bin_stdev",  0,            "define exposure background binned stdev", NAN);
+    psMetadataAddF64(addresidimfileArgs, PS_LIST_TAIL, "-fringe_0",  0,            "define fringe slope (0th term)", NAN);
+    psMetadataAddF64(addresidimfileArgs, PS_LIST_TAIL, "-fringe_1",  0,            "define fringe slope (1st term)", NAN);
+    psMetadataAddF64(addresidimfileArgs, PS_LIST_TAIL, "-fringe_2",  0,            "define fringe slope (2nd term)", NAN);
+    psMetadataAddF64(addresidimfileArgs, PS_LIST_TAIL, "-fringe_resid_0",  0,            "define fringe residual (0th term)", NAN);
+    psMetadataAddF64(addresidimfileArgs, PS_LIST_TAIL, "-fringe_resid_1",  0,            "define fringe residual (1st term)", NAN);
+    psMetadataAddF64(addresidimfileArgs, PS_LIST_TAIL, "-fringe_resid_2",  0,            "define fringe residual (2nd term)", NAN);
+    psMetadataAddF64(addresidimfileArgs, PS_LIST_TAIL, "-user_1",  0,            "define user statistic (1)", NAN);
+    psMetadataAddF64(addresidimfileArgs, PS_LIST_TAIL, "-user_2",  0,            "define user statistic (2)", NAN);
+    psMetadataAddF64(addresidimfileArgs, PS_LIST_TAIL, "-user_3",  0,            "define user statistic (3)", NAN);
+    psMetadataAddF64(addresidimfileArgs, PS_LIST_TAIL, "-user_4",  0,            "define user statistic (4)", NAN);
+    psMetadataAddF64(addresidimfileArgs, PS_LIST_TAIL, "-user_5",  0,            "define user statistic (5)", NAN);
+    psMetadataAddStr(addresidimfileArgs, PS_LIST_TAIL, "-path_base",  0,            "define base output location", NULL);
+
+    // -residimfile
+    psMetadata *residimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(residimfileArgs, PS_LIST_TAIL, "-det_id",  0,            "search for detrend ID", 0);
+    psMetadataAddS32(residimfileArgs, PS_LIST_TAIL, "-iteration",  0,            "search for iteration number", 0);
+    psMetadataAddS64(residimfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by detrend ID", 0);
+    psMetadataAddStr(residimfileArgs, PS_LIST_TAIL, "-class_id",  0,            "search for class ID", NULL);
+    psMetadataAddStr(residimfileArgs, PS_LIST_TAIL, "-recip",  0,            "search for recipe", NULL);
+    psMetadataAddU64(residimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(residimfileArgs, PS_LIST_TAIL, "-faulted",  0,            "only return imfiles with a fault status set", false);
+    psMetadataAddBool(residimfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddStr(residimfileArgs, PS_LIST_TAIL, "-select_state",  0,            "search for state", NULL);
+
+    // -revertresidimfile
+    psMetadata *revertresidimfileArgs =  psMetadataAlloc();
+    psMetadataAddS64(revertresidimfileArgs, PS_LIST_TAIL, "-det_id", 0,          "search by detrend ID (required)", 0);
+    psMetadataAddS32(revertresidimfileArgs, PS_LIST_TAIL, "-iteration", 0,       "search by iteration number", 0);
+    psMetadataAddS64(revertresidimfileArgs, PS_LIST_TAIL, "-exp_id",  0,         "search by detrend ID", 0);
+    psMetadataAddStr(revertresidimfileArgs, PS_LIST_TAIL, "-class_id",  0,       "search for class ID", NULL);
+    psMetadataAddS16(revertresidimfileArgs, PS_LIST_TAIL, "-code",  0,           "search by fault code", 0);
+
+    // -updateresidimfile
+    psMetadata *updateresidimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(updateresidimfileArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS32(updateresidimfileArgs, PS_LIST_TAIL, "-iteration", 0,       "search by iteration number", 0);
+    psMetadataAddS64(updateresidimfileArgs, PS_LIST_TAIL, "-exp_id",               0,            "search by exp_id", 0);
+    psMetadataAddStr(updateresidimfileArgs, PS_LIST_TAIL, "-class_id",             0,            "search by exp_name", NULL);
+    psMetadataAddStr(updateresidimfileArgs, PS_LIST_TAIL, "-data_state",           0,            "search for telescope", NULL);
+
+    // -pendingcleanup_residimfile
+    psMetadata *pendingcleanup_residimfileArgs = psMetadataAlloc();
+    psMetadataAddBool(pendingcleanup_residimfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanup_residimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddS64(pendingcleanup_residimfileArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS32(pendingcleanup_residimfileArgs, PS_LIST_TAIL, "-iteration", 0,       "search by iteration number", 0);
+    psMetadataAddS64(pendingcleanup_residimfileArgs, PS_LIST_TAIL, "-exp_id",               0,            "search by exp_id", 0);
+    psMetadataAddStr(pendingcleanup_residimfileArgs, PS_LIST_TAIL, "-class_id",             0,            "search by exp_name", NULL);
+
+    // -donecleanup_residimfile
+    psMetadata *donecleanup_residimfileArgs = psMetadataAlloc();
+    psMetadataAddBool(donecleanup_residimfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(donecleanup_residimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddS64(donecleanup_residimfileArgs, PS_LIST_TAIL, "-det_id",               0,            "search by chip ID", 0);
+    psMetadataAddS32(donecleanup_residimfileArgs, PS_LIST_TAIL, "-iteration", 0,       "search by iteration number", 0);
+    psMetadataAddS64(donecleanup_residimfileArgs, PS_LIST_TAIL, "-exp_id",               0,            "search by exp_id", 0);
+    psMetadataAddStr(donecleanup_residimfileArgs, PS_LIST_TAIL, "-class_id",             0,            "search by exp_name", NULL);
+
+    // -toresidexp
+    psMetadata *toresidexpArgs = psMetadataAlloc();
+    psMetadataAddU64(toresidexpArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(toresidexpArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -addresidexp
+    psMetadata *addresidexpArgs = psMetadataAlloc();
+    psMetadataAddS64(addresidexpArgs, PS_LIST_TAIL, "-det_id",  0,            "define detrend ID (required)", 0);
+    psMetadataAddS32(addresidexpArgs, PS_LIST_TAIL, "-iteration",  0,            "define iteration number", 0);
+    psMetadataAddS64(addresidexpArgs, PS_LIST_TAIL, "-exp_id",  0,            "define detrend ID (required)", 0);
+    psMetadataAddS16(addresidexpArgs, PS_LIST_TAIL, "-code",  0,            "set fault code", 0);
+    psMetadataAddStr(addresidexpArgs, PS_LIST_TAIL, "-recip",  0,            "define recipe", NULL);
+    psMetadataAddF64(addresidexpArgs, PS_LIST_TAIL, "-bg",  0,            "define exposure background", NAN);
+    psMetadataAddF64(addresidexpArgs, PS_LIST_TAIL, "-bg_stdev",  0,            "define exposure background stdev", NAN);
+    psMetadataAddF64(addresidexpArgs, PS_LIST_TAIL, "-bg_mean_stdev",  0,            "define exposure background mean stdev", NAN);
+    psMetadataAddF64(addresidexpArgs, PS_LIST_TAIL, "-bg_skewness",  0,            "define exposure background skewness", NAN);
+    psMetadataAddF64(addresidexpArgs, PS_LIST_TAIL, "-bg_kurtosis",  0,            "define exposure background kurtosis", NAN);
+    psMetadataAddF64(addresidexpArgs, PS_LIST_TAIL, "-bin_stdev",  0,            "define exposure background binned stdev", NAN);
+    psMetadataAddF64(addresidexpArgs, PS_LIST_TAIL, "-fringe_0",  0,            "define fringe slope (0th term)", NAN);
+    psMetadataAddF64(addresidexpArgs, PS_LIST_TAIL, "-fringe_1",  0,            "define fringe slope (1st term)", NAN);
+    psMetadataAddF64(addresidexpArgs, PS_LIST_TAIL, "-fringe_2",  0,            "define fringe slope (2nd term)", NAN);
+    psMetadataAddF64(addresidexpArgs, PS_LIST_TAIL, "-fringe_resid_0",  0,            "define fringe residual (0th term)", NAN);
+    psMetadataAddF64(addresidexpArgs, PS_LIST_TAIL, "-fringe_resid_1",  0,            "define fringe residual (1st term)", NAN);
+    psMetadataAddF64(addresidexpArgs, PS_LIST_TAIL, "-fringe_resid_2",  0,            "define fringe residual (2nd term)", NAN);
+    psMetadataAddF64(addresidexpArgs, PS_LIST_TAIL, "-user_1",  0,            "define user statistic (1)", NAN);
+    psMetadataAddF64(addresidexpArgs, PS_LIST_TAIL, "-user_2",  0,            "define user statistic (2)", NAN);
+    psMetadataAddF64(addresidexpArgs, PS_LIST_TAIL, "-user_3",  0,            "define user statistic (3)", NAN);
+    psMetadataAddF64(addresidexpArgs, PS_LIST_TAIL, "-user_4",  0,            "define user statistic (4)", NAN);
+    psMetadataAddF64(addresidexpArgs, PS_LIST_TAIL, "-user_5",  0,            "define user statistic (5)", NAN);
+    psMetadataAddStr(addresidexpArgs, PS_LIST_TAIL, "-path_base",  0,            "define base output location", NULL);
+    psMetadataAddBool(addresidexpArgs, PS_LIST_TAIL, "-reject",  0,            "exposure is not to be stacked in the next iteration", false);
+
+    // -residexp
+    psMetadata *residexpArgs = psMetadataAlloc();
+    psMetadataAddS64(residexpArgs, PS_LIST_TAIL, "-det_id",  0,            "search for detrend ID", 0);
+    psMetadataAddS32(residexpArgs, PS_LIST_TAIL, "-iteration",  0,            "search for iteration number", 0);
+    psMetadataAddS64(residexpArgs, PS_LIST_TAIL, "-exp_id",  0,            "search for exp ID", 0);
+    psMetadataAddStr(residexpArgs, PS_LIST_TAIL, "-recip",  0,            "search for recipe", NULL);
+    psMetadataAddBool(residexpArgs, PS_LIST_TAIL, "-reject",  0,            "search for acceptable residuals", false);
+    psMetadataAddU64(residexpArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(residexpArgs, PS_LIST_TAIL, "-faulted",  0,            "only return imfiles with a fault status set", false);
+    psMetadataAddBool(residexpArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -revertresidexp
+    psMetadata *revertresidexpArgs = psMetadataAlloc();
+    psMetadataAddS64(revertresidexpArgs, PS_LIST_TAIL, "-det_id", 0,            "search by detrend ID (required)", 0);
+    psMetadataAddS32(revertresidexpArgs, PS_LIST_TAIL, "-iteration", 0,            "search by iteration number", 0);
+    psMetadataAddS64(revertresidexpArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by detrend ID", 0);
+    psMetadataAddS16(revertresidexpArgs, PS_LIST_TAIL, "-code",  0,            "search by fault code", 0);
+
+    // -updateresidexp
+    psMetadata *updateresidexpArgs = psMetadataAlloc();
+    psMetadataAddS64(updateresidexpArgs, PS_LIST_TAIL, "-det_id",  0,            "define detrend ID", 0);
+    psMetadataAddS32(updateresidexpArgs, PS_LIST_TAIL, "-iteration",  0,            "define iteration number", 0);
+    psMetadataAddS64(updateresidexpArgs, PS_LIST_TAIL, "-exp_id",  0,            "define exp ID", 0);
+    psMetadataAddStr(updateresidexpArgs, PS_LIST_TAIL, "-recip",  0,            "define recipe", NULL);
+    psMetadataAddF64(updateresidexpArgs, PS_LIST_TAIL, "-bg",  0,            "define exposure background", NAN);
+    psMetadataAddF64(updateresidexpArgs, PS_LIST_TAIL, "-bg_stdev",  0,            "define exposure background stdev", NAN);
+    psMetadataAddF64(updateresidexpArgs, PS_LIST_TAIL, "-bg_mean_stdev",  0,            "define exposure background mean stdev", NAN);
+    psMetadataAddStr(updateresidexpArgs, PS_LIST_TAIL, "-path_base",  0,            "define base output location", NULL);
+    psMetadataAddBool(updateresidexpArgs, PS_LIST_TAIL, "-reject",  0,            "exposure is not to be stacked in the next iteration", false);
+    psMetadataAddStr(updateresidexpArgs, PS_LIST_TAIL, "-data_state",           0,            "search for telescope", NULL);
+
+    // -pendingcleanup_residexp
+    psMetadata *pendingcleanup_residexpArgs = psMetadataAlloc();
+    psMetadataAddBool(pendingcleanup_residexpArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanup_residexpArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddS64(pendingcleanup_residexpArgs, PS_LIST_TAIL, "-det_id", 0,            "search by detrend ID (required)", 0);
+    psMetadataAddS32(pendingcleanup_residexpArgs, PS_LIST_TAIL, "-iteration", 0,            "search by iteration number", 0);
+    psMetadataAddS64(pendingcleanup_residexpArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by detrend ID", 0);
+
+    // -donecleanup_residexp
+    psMetadata *donecleanup_residexpArgs = psMetadataAlloc();
+    psMetadataAddBool(donecleanup_residexpArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(donecleanup_residexpArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddS64(donecleanup_residexpArgs, PS_LIST_TAIL, "-det_id", 0,            "search by detrend ID (required)", 0);
+    psMetadataAddS32(donecleanup_residexpArgs, PS_LIST_TAIL, "-iteration", 0,            "search by iteration number", 0);
+    psMetadataAddS64(donecleanup_residexpArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by detrend ID", 0);
+
+    // -todetrunsummary
+    psMetadata *todetrunsummaryArgs = psMetadataAlloc();
+    psMetadataAddBool(todetrunsummaryArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(todetrunsummaryArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -adddetrunsummary
+    psMetadata *adddetrunsummaryArgs = psMetadataAlloc();
+    psMetadataAddS64(adddetrunsummaryArgs, PS_LIST_TAIL, "-det_id",  0,            "define detrend ID (required)", 0);
+    psMetadataAddS32(adddetrunsummaryArgs, PS_LIST_TAIL, "-iteration",  0,            "define iteration number", 0);
+    psMetadataAddF64(adddetrunsummaryArgs, PS_LIST_TAIL, "-bg",  0,            "define exposure background", NAN);
+    psMetadataAddF64(adddetrunsummaryArgs, PS_LIST_TAIL, "-bg_stdev",  0,            "define exposure background stdev", NAN);
+    psMetadataAddF64(adddetrunsummaryArgs, PS_LIST_TAIL, "-bg_mean_stdev",  0,            "define exposure background mean stdev", NAN);
+    psMetadataAddS16(adddetrunsummaryArgs, PS_LIST_TAIL, "-code",  0,            "set fault code", 0);
+    psMetadataAddBool(adddetrunsummaryArgs, PS_LIST_TAIL, "-accept",  0,            "declare that this detrun iteration is accepted as a master", false);
+    psMetadataAddBool(adddetrunsummaryArgs, PS_LIST_TAIL, "-again",  0,            "start a new iteration of this detrend run", false);
+
+    // -detrunsummary
+    psMetadata *detrunsummaryArgs = psMetadataAlloc();
+    psMetadataAddS64(detrunsummaryArgs, PS_LIST_TAIL, "-det_id",  0,            "search for detrend ID", 0);
+    psMetadataAddS32(detrunsummaryArgs, PS_LIST_TAIL, "-iteration",  0,            "search for iteration number", 0);
+    psMetadataAddU64(detrunsummaryArgs, PS_LIST_TAIL, "-limit",  0,                     "limit result set to N items", 0);
+    psMetadataAddBool(detrunsummaryArgs, PS_LIST_TAIL, "-faulted",  0,            "only return imfiles with a fault status set", false);
+    psMetadataAddBool(detrunsummaryArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddBool(detrunsummaryArgs, PS_LIST_TAIL, "-reject",  0,            "search for acceptable residuals", false);
+
+    // -revertdetrunsummary
+    psMetadata *revertdetrunsummaryArgs = psMetadataAlloc();
+    psMetadataAddS64(revertdetrunsummaryArgs, PS_LIST_TAIL, "-det_id", 0,            "search by detrend ID (required)", 0);
+    psMetadataAddS32(revertdetrunsummaryArgs, PS_LIST_TAIL, "-iteration", 0,            "search by iteration number", 0);
+    psMetadataAddS16(revertdetrunsummaryArgs, PS_LIST_TAIL, "-code",  0,            "search by fault code", 0);
+
+    // -updatedetrunsummary
+    psMetadata *updatedetrunsummaryArgs = psMetadataAlloc();
+    psMetadataAddS64(updatedetrunsummaryArgs, PS_LIST_TAIL, "-det_id",  0,            "search for detrend master for detrend ID (required)", 0);
+    psMetadataAddBool(updatedetrunsummaryArgs, PS_LIST_TAIL, "-accept",  0,            "declare that this detrun iteration is accepted as a master", false);
+    psMetadataAddBool(updatedetrunsummaryArgs, PS_LIST_TAIL, "-reject",  0,            "reject this detrun iteration as a master", false);
+
+    // -updatedetrun
+    psMetadata *updatedetrunArgs = psMetadataAlloc();
+    psMetadataAddS64(updatedetrunArgs, PS_LIST_TAIL, "-det_id",  0,            "search for detrend master for detrend ID (required)", 0);
+    psMetadataAddBool(updatedetrunArgs, PS_LIST_TAIL, "-again",  0,            "start a new iteration of this detrend run", false);
+    psMetadataAddStr(updatedetrunArgs, PS_LIST_TAIL, "-state",  0,            "set the state of this detrend run", false);
+
+    // -rerun
+    psMetadata *rerunArgs = psMetadataAlloc();
+    psMetadataAddS64(rerunArgs, PS_LIST_TAIL, "-det_id",  0,            "search for detrend master for detrend ID (required)", 0);
+    psMetadataAddS64(rerunArgs, PS_LIST_TAIL, "-exp_id",  PS_META_DUPLICATE_OK,            "include this exposure (multiple OK, required)", 0);
+
+    // -register_detrend
+    psMetadata *register_detrendArgs = psMetadataAlloc();
+    psMetadataAddStr(register_detrendArgs, PS_LIST_TAIL, "-det_type",  0,            "define the type of detrend run (required)", NULL);
+    psMetadataAddStr(register_detrendArgs, PS_LIST_TAIL, "-filelevel",  0,            "define filelevel (required)", NULL);
+    psMetadataAddStr(register_detrendArgs, PS_LIST_TAIL, "-workdir",  0,            "define workdir", NULL);
+    psMetadataAddStr(register_detrendArgs, PS_LIST_TAIL, "-inst",  0,            "define camera", NULL);
+    psMetadataAddStr(register_detrendArgs, PS_LIST_TAIL, "-telescope",  0,            "define telescope", NULL);
+    psMetadataAddStr(register_detrendArgs, PS_LIST_TAIL, "-exp_type",  0,            "define exposure type", NULL);
+    psMetadataAddStr(register_detrendArgs, PS_LIST_TAIL, "-filter",  0,            "define filter ", NULL);
+    psMetadataAddF32(register_detrendArgs, PS_LIST_TAIL, "-airmass_min",  0,            "define min airmass", NAN);
+    psMetadataAddF32(register_detrendArgs, PS_LIST_TAIL, "-airmass_max",  0,            "define max airmass", NAN);
+    psMetadataAddF32(register_detrendArgs, PS_LIST_TAIL, "-exp_time_min",  0,            "define min exposure time", NAN);
+    psMetadataAddF32(register_detrendArgs, PS_LIST_TAIL, "-exp_time_max",  0,            "define max exposure time", NAN);
+    psMetadataAddF32(register_detrendArgs, PS_LIST_TAIL, "-ccd_temp_min",  0,            "define min ccd tempature", NAN);
+    psMetadataAddF32(register_detrendArgs, PS_LIST_TAIL, "-ccd_temp_max",  0,            "define max ccd tempature", NAN);
+    psMetadataAddF64(register_detrendArgs, PS_LIST_TAIL, "-posang_min",  0,            "define min rotator position angle", NAN);
+    psMetadataAddF64(register_detrendArgs, PS_LIST_TAIL, "-posang_max",  0,            "define max rotator position angle", NAN);
+    psMetadataAddF64(register_detrendArgs, PS_LIST_TAIL, "-solang_min",  0,            "define min solar angle", NAN);
+    psMetadataAddF64(register_detrendArgs, PS_LIST_TAIL, "-solang_max",  0,            "define max solar angle", NAN);
+    psMetadataAddTime(register_detrendArgs, PS_LIST_TAIL, "-registered",  0,            "time detrend run was registered", now);
+    psMetadataAddTime(register_detrendArgs, PS_LIST_TAIL, "-time_begin",  0,            "detrend applies to exposures taken during this period", NULL);
+    psMetadataAddTime(register_detrendArgs, PS_LIST_TAIL, "-time_end",  0,            "detrend applies to exposures taken during this period", NULL);
+    psMetadataAddTime(register_detrendArgs, PS_LIST_TAIL, "-use_begin",  0,            "start of detrend run applicable period", NULL);
+    psMetadataAddTime(register_detrendArgs, PS_LIST_TAIL, "-use_end",  0,            "end of detrend run applicable period", NULL);
+    psMetadataAddS64(register_detrendArgs, PS_LIST_TAIL, "-parent",  0,            "define parent det_id", 0);
+    psMetadataAddStr(register_detrendArgs, PS_LIST_TAIL, "-label",  0,            "define detrun label", NULL);
+    psMetadataAddBool(register_detrendArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -register_detrend_imfile
+    psMetadata *register_detrend_imfileArgs = psMetadataAlloc();
+    psMetadataAddS64(register_detrend_imfileArgs, PS_LIST_TAIL, "-det_id",  0,            "define detrend ID (required)", 0);
+    psMetadataAddStr(register_detrend_imfileArgs, PS_LIST_TAIL, "-class_id",  0,            "search for class ID (required)", NULL);
+    psMetadataAddStr(register_detrend_imfileArgs, PS_LIST_TAIL, "-uri",  0,            "define resid file URI (required)", NULL);
+    psMetadataAddF64(register_detrend_imfileArgs, PS_LIST_TAIL, "-bg",  0,            "define exposure background", NAN);
+    psMetadataAddF64(register_detrend_imfileArgs, PS_LIST_TAIL, "-bg_stdev",  0,            "define exposure background stdev", NAN);
+    psMetadataAddF64(register_detrend_imfileArgs, PS_LIST_TAIL, "-bg_mean_stdev",  0,            "define exposure background mean stdev", NAN);
+    psMetadataAddF64(register_detrend_imfileArgs, PS_LIST_TAIL, "-user_1",  0,            "define user statistic (1)", NAN);
+    psMetadataAddF64(register_detrend_imfileArgs, PS_LIST_TAIL, "-user_2",  0,            "define user statistic (2)", NAN);
+    psMetadataAddF64(register_detrend_imfileArgs, PS_LIST_TAIL, "-user_3",  0,            "define user statistic (3)", NAN);
+    psMetadataAddF64(register_detrend_imfileArgs, PS_LIST_TAIL, "-user_4",  0,            "define user statistic (4)", NAN);
+    psMetadataAddF64(register_detrend_imfileArgs, PS_LIST_TAIL, "-user_5",  0,            "define user statistic (5)", NAN);
+    psMetadataAddStr(register_detrend_imfileArgs, PS_LIST_TAIL, "-path_base",  0,            "define base output location", NULL);
+
+    psFree(now);
+
+    psMetadata *argSets = psMetadataAlloc();
+    psMetadata *modes = psMetadataAlloc();
+
+    PXOPT_ADD_MODE("-pending",         "list active detruns", DETTOOL_MODE_PENDING,       pendingArgs);
+    PXOPT_ADD_MODE("-definebytag",     "", DETTOOL_MODE_DEFINEBYTAG,   definebytagArgs);
+    PXOPT_ADD_MODE("-definebyquery",   "", DETTOOL_MODE_DEFINEBYQUERY, definebyqueryArgs);
+    PXOPT_ADD_MODE("-definebydetrun",  "", DETTOOL_MODE_DEFINEBYDETRUN, definebydetrunArgs);
+    PXOPT_ADD_MODE("-makecorrection",  "", DETTOOL_MODE_MAKECORRECTION, makecorrectionArgs);
+    PXOPT_ADD_MODE("-tocorrectexp",    "", DETTOOL_MODE_TOCORRECTEXP, tocorrectexpArgs);
+    PXOPT_ADD_MODE("-tocorrectimfile", "", DETTOOL_MODE_TOCORRECTIMFILE, tocorrectimfileArgs);
+    PXOPT_ADD_MODE("-addcorrectimfile", "", DETTOOL_MODE_ADDCORRECTIMFILE, addcorrectimfileArgs);
+    PXOPT_ADD_MODE("-raw",             "", DETTOOL_MODE_RAW,           rawArgs);
+    PXOPT_ADD_MODE("-runs",            "", DETTOOL_MODE_RUNS,          runsArgs);
+    PXOPT_ADD_MODE("-childlessrun",    "", DETTOOL_MODE_CHILDLESSRUN,  childlessrunArgs);
+    PXOPT_ADD_MODE("-input",           "", DETTOOL_MODE_INPUT,         inputArgs);
+
+    PXOPT_ADD_MODE("-toprocessedimfile", "",  		  DETTOOL_MODE_TOPROCESSEDIMFILE, toprocessedimfileArgs);
+    PXOPT_ADD_MODE("-addprocessedimfile", "", 		  DETTOOL_MODE_ADDPROCESSEDIMFILE,  addprocessedimfileArgs);
+    PXOPT_ADD_MODE("-processedimfile", "",    		  DETTOOL_MODE_PROCESSEDIMFILE, processedimfileArgs);
+    PXOPT_ADD_MODE("-revertprocessedimfile", "", 	  DETTOOL_MODE_REVERTPROCESSEDIMFILE, revertprocessedimfileArgs);
+    PXOPT_ADD_MODE("-updateprocessedimfile", "", 	  DETTOOL_MODE_UPDATEPROCESSEDIMFILE, updateprocessedimfileArgs);
+    PXOPT_ADD_MODE("-pendingcleanup_processedimfile", "", DETTOOL_MODE_PENDINGCLEANUP_PROCESSEDIMFILE, pendingcleanup_processedimfileArgs);
+    PXOPT_ADD_MODE("-donecleanup_processedimfile", "",    DETTOOL_MODE_DONECLEANUP_PROCESSEDIMFILE, donecleanup_processedimfileArgs);
+
+    PXOPT_ADD_MODE("-toprocessedexp",  "", DETTOOL_MODE_TOPROCESSEDEXP,  toprocessedexpArgs);
+    PXOPT_ADD_MODE("-addprocessedexp", "", DETTOOL_MODE_ADDPROCESSEDEXP, addprocessedexpArgs);
+    PXOPT_ADD_MODE("-processedexp",    "", DETTOOL_MODE_PROCESSEDEXP, processedexpArgs);
+    PXOPT_ADD_MODE("-revertprocessedexp", "", DETTOOL_MODE_REVERTPROCESSEDEXP, revertprocessedexpArgs);
+    PXOPT_ADD_MODE("-updateprocessedexp", "", DETTOOL_MODE_UPDATEPROCESSEDEXP, updateprocessedexpArgs);
+    PXOPT_ADD_MODE("-pendingcleanup_processedexp", "", DETTOOL_MODE_PENDINGCLEANUP_PROCESSEDEXP, pendingcleanup_processedexpArgs);
+    PXOPT_ADD_MODE("-donecleanup_processedexp", "",    DETTOOL_MODE_DONECLEANUP_PROCESSEDEXP, donecleanup_processedexpArgs);
+
+    PXOPT_ADD_MODE("-tostacked",       "", DETTOOL_MODE_TOSTACKED,     tostackedArgs);
+    PXOPT_ADD_MODE("-addstacked",      "", DETTOOL_MODE_ADDSTACKED,    addstackedArgs);
+    PXOPT_ADD_MODE("-stacked",         "", DETTOOL_MODE_STACKED,       stackedArgs);
+    PXOPT_ADD_MODE("-revertstacked",   "", DETTOOL_MODE_REVERTSTACKED,  revertstackedArgs);
+    PXOPT_ADD_MODE("-updatestacked",   "", DETTOOL_MODE_UPDATESTACKED,  updatestackedArgs);
+    PXOPT_ADD_MODE("-pendingcleanup_stacked", "", DETTOOL_MODE_PENDINGCLEANUP_STACKED, pendingcleanup_stackedArgs);
+    PXOPT_ADD_MODE("-donecleanup_stacked", "",    DETTOOL_MODE_DONECLEANUP_STACKED, donecleanup_stackedArgs);
+
+    PXOPT_ADD_MODE("-tonormalizedstat",      "", DETTOOL_MODE_TONORMALIZEDSTAT,    tonormalizedstatArgs);
+    PXOPT_ADD_MODE("-addnormalizedstat",     "", DETTOOL_MODE_ADDNORMALIZEDSTAT,   addnormstatArgs);
+    PXOPT_ADD_MODE("-normalizedstat",        "", DETTOOL_MODE_NORMALIZEDSTAT,   normalizedstatArgs);
+    PXOPT_ADD_MODE("-revertnormalizedstat",  "", DETTOOL_MODE_REVERTNORMALIZEDSTAT,   revertnormalizedstatArgs);
+    PXOPT_ADD_MODE("-updatenormalizedstat",  "", DETTOOL_MODE_UPDATENORMALIZEDSTAT,   updatenormalizedstatArgs);
+    PXOPT_ADD_MODE("-pendingcleanup_normalizedstat", "", DETTOOL_MODE_PENDINGCLEANUP_NORMALIZEDSTAT, pendingcleanup_normalizedstatArgs);
+    PXOPT_ADD_MODE("-donecleanup_normalizedstat", "",    DETTOOL_MODE_DONECLEANUP_NORMALIZEDSTAT, donecleanup_normalizedstatArgs);
+
+    PXOPT_ADD_MODE("-tonormalize",     "", DETTOOL_MODE_TONORMALIZE,   tonormalizeArgs);
+    PXOPT_ADD_MODE("-addnormalizedimfile", "", DETTOOL_MODE_ADDNORMALIZEDIMFILE,addnormalizedimfileArgs);
+    PXOPT_ADD_MODE("-normalizedimfile","", DETTOOL_MODE_NORMALIZEDIMFILE, normalizedimfileArgs);
+    PXOPT_ADD_MODE("-revertnormalizedimfile","", DETTOOL_MODE_REVERTNORMALIZEDIMFILE, revertnormalizedimfileArgs);
+    PXOPT_ADD_MODE("-updatenormalizedimfile","", DETTOOL_MODE_UPDATENORMALIZEDIMFILE, updatenormalizedimfileArgs);
+    PXOPT_ADD_MODE("-pendingcleanup_normalizedimfile", "", DETTOOL_MODE_PENDINGCLEANUP_NORMALIZEDIMFILE, pendingcleanup_normalizedimfileArgs);
+    PXOPT_ADD_MODE("-donecleanup_normalizedimfile", "",    DETTOOL_MODE_DONECLEANUP_NORMALIZEDIMFILE, donecleanup_normalizedimfileArgs);
+
+    PXOPT_ADD_MODE("-tonormalizedexp", "", DETTOOL_MODE_TONORMALIZEDEXP, tonormalizedexpArgs);
+    PXOPT_ADD_MODE("-addnormalizedexp", "", DETTOOL_MODE_ADDNORMALIZEDEXP, addnormalizedexpArgs);
+    PXOPT_ADD_MODE("-normalizedexp",   "", DETTOOL_MODE_NORMALIZEDEXP, normalizedexpArgs);
+    PXOPT_ADD_MODE("-revertnormalizedexp","", DETTOOL_MODE_REVERTNORMALIZEDEXP, revertnormalizedexpArgs);
+    PXOPT_ADD_MODE("-updatenormalizedexp","", DETTOOL_MODE_UPDATENORMALIZEDEXP, updatenormalizedexpArgs);
+    PXOPT_ADD_MODE("-pendingcleanup_normalizedexp", "", DETTOOL_MODE_PENDINGCLEANUP_NORMALIZEDEXP, pendingcleanup_normalizedexpArgs);
+    PXOPT_ADD_MODE("-donecleanup_normalizedexp", "",    DETTOOL_MODE_DONECLEANUP_NORMALIZEDEXP, donecleanup_normalizedexpArgs);
+
+    PXOPT_ADD_MODE("-toresidimfile",   "", DETTOOL_MODE_TORESIDIMFILE, toresidimfileArgs);
+    PXOPT_ADD_MODE("-addresidimfile",  "", DETTOOL_MODE_ADDRESIDIMFILE, addresidimfileArgs);
+    PXOPT_ADD_MODE("-residimfile",     "", DETTOOL_MODE_RESIDIMFILE, residimfileArgs);
+    PXOPT_ADD_MODE("-revertresidimfile", "", DETTOOL_MODE_REVERTRESIDIMFILE, revertresidimfileArgs);
+    PXOPT_ADD_MODE("-updateresidimfile", "", DETTOOL_MODE_UPDATERESIDIMFILE, updateresidimfileArgs);
+    PXOPT_ADD_MODE("-pendingcleanup_residimfile", "", DETTOOL_MODE_PENDINGCLEANUP_RESIDIMFILE, pendingcleanup_residimfileArgs);
+    PXOPT_ADD_MODE("-donecleanup_residimfile", "",    DETTOOL_MODE_DONECLEANUP_RESIDIMFILE, donecleanup_residimfileArgs);
+
+    PXOPT_ADD_MODE("-toresidexp",      "", DETTOOL_MODE_TORESIDEXP,    toresidexpArgs);
+    PXOPT_ADD_MODE("-addresidexp",     "", DETTOOL_MODE_ADDRESIDEXP,  addresidexpArgs);
+    PXOPT_ADD_MODE("-residexp",        "", DETTOOL_MODE_RESIDEXP,     residexpArgs);
+    PXOPT_ADD_MODE("-revertresidexp",  "", DETTOOL_MODE_REVERTRESIDEXP, revertresidexpArgs);
+    PXOPT_ADD_MODE("-updateresidexp",  "", DETTOOL_MODE_UPDATERESIDEXP, updateresidexpArgs);
+    PXOPT_ADD_MODE("-pendingcleanup_residexp", "", DETTOOL_MODE_PENDINGCLEANUP_RESIDEXP, pendingcleanup_residexpArgs);
+    PXOPT_ADD_MODE("-donecleanup_residexp", "",    DETTOOL_MODE_DONECLEANUP_RESIDEXP, donecleanup_residexpArgs);
+
+    PXOPT_ADD_MODE("-todetrunsummary",  "", DETTOOL_MODE_TODETRUNSUMMARY,  todetrunsummaryArgs);
+    PXOPT_ADD_MODE("-adddetrunsummary", "", DETTOOL_MODE_ADDDETRUNSUMMARY,adddetrunsummaryArgs);
+    PXOPT_ADD_MODE("-detrunsummary", "", DETTOOL_MODE_DETRUNSUMMARY,detrunsummaryArgs);
+    PXOPT_ADD_MODE("-revertdetrunsummary", "", DETTOOL_MODE_REVERTDETRUNSUMMARY, revertdetrunsummaryArgs);
+    PXOPT_ADD_MODE("-updatedetrunsummary", "", DETTOOL_MODE_UPDATEDETRUNSUMMARY, updatedetrunsummaryArgs);
+
+    PXOPT_ADD_MODE("-updatedetrun", "", DETTOOL_MODE_UPDATEDETRUN, updatedetrunArgs);
+    PXOPT_ADD_MODE("-rerun",           "", DETTOOL_MODE_RERUN,         rerunArgs);
+    PXOPT_ADD_MODE("-register_detrend", "", DETTOOL_MODE_REGISTER_DETREND, register_detrendArgs);
+    PXOPT_ADD_MODE("-register_detrend_imfile", "", DETTOOL_MODE_REGISTER_DETREND_IMFILE, register_detrend_imfileArgs);
+
+    if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
+        psError(PS_ERR_UNKNOWN, false, "option parsing failed");
+        psFree(argSets);
+        psFree(modes);
+        psFree(config);
+        return NULL;
+    }
+
+    psFree(argSets);
+    psFree(modes);
+
+    // define Database handle, if used
+    // do this last so we don't setup a connection before CLI options are
+    // validated
+    config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+    if (!config->dbh) {
+        psError(PS_ERR_UNKNOWN, false, "Can't configure database");
+        psFree(config);
+        return NULL;
+    }
+
+    return config;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_correction.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_correction.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_correction.c	(revision 22158)
@@ -0,0 +1,251 @@
+/*
+ * dettool_correction.c
+ *
+ * Copyright (C) 2006-2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+bool makecorrectionMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false); // required
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false); // optional
+
+    // build the needed where 
+    psMetadata *where = psMetadataAlloc();
+    psMetadataAddS64(where, PS_LIST_TAIL, "det_id", 0, "==", det_id);
+    psArray *runs = detRunSelectRowObjects(config->dbh, where, 1);
+    psFree (where);
+
+    if (!psArrayLength(runs)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    detRunRow *detRun = runs->data[0];
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    detRunInsert(config->dbh,
+         0,             // det_id
+         0,             // iteration
+         detRun->det_type,
+         "correction",  // mode
+         "run",         // state
+         detRun->filelevel,
+         detRun->workdir,
+         detRun->camera,
+         detRun->telescope,
+         detRun->exp_type,
+         detRun->reduction,
+         detRun->filter,
+         detRun->airmass_min,
+         detRun->airmass_max,
+         detRun->exp_time_min,
+         detRun->exp_time_max,
+         detRun->ccd_temp_min,
+         detRun->ccd_temp_max,
+         detRun->posang_min,
+         detRun->posang_max,
+         detRun->registered,
+         detRun->time_begin,
+         detRun->time_end,
+         detRun->use_begin,
+         detRun->use_end,
+         detRun->solang_min,
+         detRun->solang_max,
+         detRun->label,
+         detRun->det_id // parent
+    );
+
+    psFree(runs);
+
+    // print the new detRun
+    psS64 new_det_id = psDBLastInsertID(config->dbh);
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psMetadata *where_new = psMetadataAlloc();
+    psMetadataAddS64(where, PS_LIST_TAIL, "det_id", 0, "==", new_det_id);
+    psArray *detRuns = psDBSelectRows(config->dbh, "detRun", where_new, 0);
+    psFree(where_new);
+
+    if (!detRuns) {
+        psError(PS_ERR_UNKNOWN, false, "can't find the detRun we just created");
+        return false;
+    }
+    // sanity check results
+    if (psArrayLength(detRuns) != 1) {
+        psAbort("found more then one detRun matching det_id %" PRId64 "(this should not happen)", new_det_id);
+        return false;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, detRuns, "detRun", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(detRuns);
+        return false;
+    }
+    psFree(detRuns);
+
+    return true;
+}
+
+bool tocorrectexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("dettool_tocorrectexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detRun", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+bool tocorrectimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-det_type", "det_type", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("dettool_tocorrectimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+	// NOTE the SQL uses an intermediate table 'det1' for this query
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "det1"); 
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree (where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detPendingCorrectImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+// NOTE : the command-line args are parsed by register_detrend_imfileMode
+bool addcorrectimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // insert the row into detRegisterImfile
+    if (!register_detrend_imfileMode(config)) {
+        return false;
+    }
+    
+    // automatically stop completed 'correct' detRuns
+    psString query = pxDataGet("dettool_stop_completed_correct_runs.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_detrunsummary.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_detrunsummary.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_detrunsummary.c	(revision 22158)
@@ -0,0 +1,366 @@
+/*
+ * dettool_detrunsummary.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt & EAM; IfA
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+static detRunSummaryRow *mdToDetRunSummary(pxConfig *config, psMetadata *row);
+
+/* The SQL returns a list of detrend runs (with detrend id, iteration and detrend type) which
+ * have completed all residexps.
+ */
+
+bool todetrunsummaryMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("dettool_todetrunsummary.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detRejectExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+// this function is used to generate the detrunSummary entries used below
+// XXX why is this a separate function?  roll it back into adddetrunsummary?
+static detRunSummaryRow *mdToDetRunSummary(pxConfig *config, psMetadata *row)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    bool status = false;
+    // from row
+    psS64 det_id = psMetadataLookupS64(&status, row, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for det_id");
+        return false;
+    }
+    psS32 iteration = psMetadataLookupS32(&status, row, "iteration");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for iteration");
+        return false;
+    }
+
+    // optional
+    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
+    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
+    PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
+
+    // default values
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+    PXOPT_LOOKUP_BOOL(accept, config->args, "-accept", false);
+
+    return detRunSummaryRowAlloc(
+            det_id,
+            iteration,
+	    "full",
+            bg,
+            bg_stdev,
+            bg_mean_stdev,
+            accept,
+            code
+        );
+}
+
+// XXX data_state should be set to 'full' here
+bool adddetrunsummaryMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    
+    // build a query to search by det_id, iteration, exp_id
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false); // required
+    PXOPT_LOOKUP_BOOL(again, config->args, "-again", false);
+
+    // The values supplied as arguments on the command (eg, -bg) are parsed 
+    // by mdToDetRunSummary below. 
+    // XXX why is there ever more than one?
+
+    psString query = pxDataGet("dettool_find_completed_runs.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+	psStringAppend(&query, " WHERE %s", whereClause);
+	psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // start a transaction so it's all rows or nothing
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(output);
+        return false;
+    }
+
+    // XXX why is there ever more than one result here?
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *row = output->data[i];
+        // convert metadata into a detResidExp object
+        detRunSummaryRow *runSummary = mdToDetRunSummary(config, row);
+        if (!runSummary) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "failed to convert metadata to detResidExp");
+            psFree(output);
+            return false;
+        }
+        // insert detResidExp object into the database
+        if (!detRunSummaryInsertObject(config->dbh, runSummary)) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(runSummary);
+            psFree(output);
+            return false;
+        }
+        psFree(runSummary);
+    }
+
+    psFree(output);
+
+    // XXX this logic does not deal with the case of -code being set
+    // XXX it should be an error for -again and -code to both be set
+    if (again) {
+        if (!startNewIteration(config, det_id)) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "failed to start new iteration");
+            return false;
+        }
+    } else {
+        // set detRun.state to stop
+        if (!setDetRunState(config, det_id, "stop")) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "failed to set detRun.state");
+            return false;
+        }
+    }
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    return true;
+}
+
+bool detrunsummaryMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
+
+    psString query = pxDataGet("dettool_detrunsummary.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psFree(where);
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "NULL");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", "AND detRunSummary.fault != 0");
+    } else {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", "AND detRunSummary.fault = 0");
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "rawDetrendImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+bool revertdetrunsummaryMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_STR(config->args, where, "-code",      "fault", "==");
+
+    psString query = pxDataGet("dettool_revertdetrunsummary.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "detRunSummary");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    if (psDBAffectedRows(config->dbh) < 1) {
+        psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
+        return false;
+    }
+
+    return true;
+}
+
+// XXX need to add -data_state here
+bool updatedetrunsummaryMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false); // required
+    PXOPT_LOOKUP_BOOL(accept, config->args, "-accept", false);
+    PXOPT_LOOKUP_BOOL(reject, config->args, "-reject", false);
+
+    if (accept && reject) {
+        psError(PS_ERR_UNKNOWN, true, "-accept and -reject are exclusive");
+        return false;
+    }
+
+    if (!(accept || reject)) {
+        psError(PS_ERR_UNKNOWN, true, "either -accept or -reject is required");
+        return false;
+    }
+
+    char *query = "UPDATE detRunSummary SET accept = %d WHERE det_id = %"PRId64; 
+    if (!p_psDBRunQuery(config->dbh, query, accept, det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_normalizedexp.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_normalizedexp.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_normalizedexp.c	(revision 22158)
@@ -0,0 +1,389 @@
+/*
+ * dettool_normalizedexp.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt & EAM; IfA
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+bool tonormalizedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("dettool_tonormalizedexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detPendingNormExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+bool addnormalizedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false); // required
+    PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", false, false);
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+    PXOPT_LOOKUP_STR(recipe, config->args, "-recip", (code == 0), false); // Required if code == 0
+    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
+    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
+    PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
+    PXOPT_LOOKUP_F64(user_1, config->args, "-user_1", false, false);
+    PXOPT_LOOKUP_F64(user_2, config->args, "-user_2", false, false);
+    PXOPT_LOOKUP_F64(user_3, config->args, "-user_3", false, false);
+    PXOPT_LOOKUP_F64(user_4, config->args, "-user_4", false, false);
+    PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
+    PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
+
+    psString query = pxDataGet("dettool_tonormalizedexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // XXX in some other places, we put the arguments in the .sql and supply them to RunQuery
+    psStringAppend(&query, " WHERE det_id = %" PRId64 " AND iteration = %d", det_id, iteration);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+    psFree(output);
+
+    // insert the new row into the detProcessedImfile table
+    if (!detNormalizedExpInsert(
+	    config->dbh,
+	    det_id,
+	    iteration,
+	    recipe,
+	    bg,
+	    bg_stdev,
+	    bg_mean_stdev,
+	    user_1,
+	    user_2,
+	    user_3,
+	    user_4,
+	    user_5,
+	    path_base,
+	    "full",
+	    code
+	    )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+bool normalizedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_STR(config->args, where, "-recip",  "recipe", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
+
+    psString query = pxDataGet("dettool_normalizedexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", "AND detNormalizedExp.fault != 0");
+    } else {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", "AND detNormalizedExp.fault = 0");
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detNormalizedExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+
+bool revertnormalizedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_S16(config->args, where, "-code",      "fault", "==");
+
+    psString query = pxDataGet("dettool_revertnormalizedexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "detNormalizedExp");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    if (psDBAffectedRows(config->dbh) < 1) {
+        psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
+        return false;
+    }
+
+    return true;
+}
+
+bool updatenormalizedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false);
+    PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", true, false);
+    PXOPT_LOOKUP_STR(data_state, config->args, "-data_state", true, false);
+
+    if (!setNormExpDataState(config, det_id, iteration, data_state)) {
+	return false;
+    }
+    return true;
+}
+
+bool pendingcleanup_normalizedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "detNormalizedExp.det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "detNormalizedExp.iteration", "==");
+
+    psString query = pxDataGet("dettool_pendingcleanup_normalizedexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detCleanupNormExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+bool donecleanup_normalizedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "detNormalizedExp.det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "detNormalizedExp.iteration", "==");
+
+    psString query = pxDataGet("dettool_donecleanup_normalizedexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detDoneCleanup_normalizedexp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_normalizedimfile.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_normalizedimfile.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_normalizedimfile.c	(revision 22158)
@@ -0,0 +1,372 @@
+/*
+ * dettool_normalizedimfile.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt & EAM; IfA
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+// XXX this one is inconsistent - rename 'tonormalizedimfile' and change ipp_serial_detrend.pl and detrend.norm.pro
+bool tonormalizeMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("dettool_tonormalize.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detPendingNormImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+bool addnormalizedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false);
+    PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", false, false);
+    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false);
+
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+
+    // Required if code == 0
+    PXOPT_LOOKUP_STR(uri, config->args, "-uri", (code == 0), false);
+
+    // optional
+    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
+    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
+    PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
+    PXOPT_LOOKUP_F64(user_1, config->args, "-user_1", false, false);
+    PXOPT_LOOKUP_F64(user_2, config->args, "-user_2", false, false);
+    PXOPT_LOOKUP_F64(user_3, config->args, "-user_3", false, false);
+    PXOPT_LOOKUP_F64(user_4, config->args, "-user_4", false, false);
+    PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
+    PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
+
+    if (!detNormalizedImfileInsert(
+	    config->dbh,
+	    det_id,
+	    iteration,
+	    class_id,
+	    uri,
+	    bg,
+	    bg_stdev,
+	    bg_mean_stdev,
+	    user_1,
+	    user_2,
+	    user_3,
+	    user_4,
+	    user_5,
+	    path_base,
+	    "full",
+	    code
+	    )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+bool normalizedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-recip",     "recipe", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
+
+    psString query = pxDataGet("dettool_normalizedimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "detNormalizedImfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", "AND detNormalizedImfile.fault != 0");
+    } else {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", "AND detNormalizedImfile.fault = 0");
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detNormalizedImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+bool revertnormalizedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
+    PXOPT_COPY_S16(config->args, where, "-code",      "fault", "==");
+
+    psString query = pxDataGet("dettool_revertnormalizedimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "detNormalizedImfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    if (psDBAffectedRows(config->dbh) < 1) {
+        psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
+        return false;
+    }
+
+    return true;
+}
+
+bool updatenormalizedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false);
+    PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", true, false);
+    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id",  true, false);
+    PXOPT_LOOKUP_STR(data_state, config->args, "-data_state", true, false);
+
+    if (!setNormImfileDataState(config, det_id, iteration, class_id, data_state)) {
+	return false;
+    }
+    return true;
+}
+
+bool pendingcleanup_normalizedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "detNormalizedImfile.det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "detNormalizedImfile.iteration", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "detNormalizedImfile.det_id", "==");
+
+    psString query = pxDataGet("dettool_pendingcleanup_normalizedimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detCleanupNormImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+bool donecleanup_normalizedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "detNormalizedImfile.det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "detNormalizedImfile.iteration", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "detNormalizedImfile.det_id", "==");
+
+    psString query = pxDataGet("dettool_donecleanup_normalizedimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detDoneCleanup_normalizedimfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_normalizedstat.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_normalizedstat.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_normalizedstat.c	(revision 22158)
@@ -0,0 +1,352 @@
+/*
+ * dettool_normalizedstat.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt & EAM; IfA
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+bool tonormalizedstatMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("dettool_tonormalizedstat.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detPendingNormStatImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+bool addnormalizedstatMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    // required
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false);
+    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false);
+
+    // optional
+    PXOPT_LOOKUP_F32(norm, config->args, "-norm", false, false);
+
+    // default
+    PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", false, false);
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+
+    detNormalizedStatImfileRow *row = detNormalizedStatImfileRowAlloc
+	(det_id,
+	 iteration,
+	 class_id,
+	 norm,
+	 "full",
+	 code);
+									 
+    if (!detNormalizedStatImfileInsertObject(config->dbh, row)) {
+	psError(PS_ERR_UNKNOWN, false, "database error");
+	return false;
+    }
+
+    return true;
+}
+
+
+bool normalizedstatMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("dettool_normalizedstat.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", "WHERE fault != 0");
+    } else {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", "WHERE fault = 0");
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detNormalizedStatImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+bool revertnormalizedstatMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
+    PXOPT_COPY_S16(config->args, where, "-code",      "fault", "==");
+
+    psString query = pxDataGet("dettool_revertnormalizedstat.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "detNormalizedStatImfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    if (psDBAffectedRows(config->dbh) < 1) {
+        psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
+        return false;
+    }
+
+    return true;
+}
+
+bool updatenormalizedstatMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false);
+    PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", true, false);
+    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id",  true, false);
+    PXOPT_LOOKUP_STR(data_state, config->args, "-data_state", true, false);
+
+    if (!setNormStatImfileDataState(config, det_id, iteration, class_id, data_state)) {
+	return false;
+    }
+    return true;
+}
+
+bool pendingcleanup_normalizedstatMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "detNormalizedStatImfile.det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "detNormalizedStatImfile.iteration", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "detNormalizedStatImfile.det_id", "==");
+
+    psString query = pxDataGet("dettool_pendingcleanup_normalizedstat.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detCleanupNormStatImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+bool donecleanup_normalizedstatMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "detNormalizedStatImfile.det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "detNormalizedStatImfile.iteration", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "detNormalizedStatImfile.det_id", "==");
+
+    psString query = pxDataGet("dettool_donecleanup_normalizedstat.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detDoneCleanup_normalizedstat", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_processedexp.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_processedexp.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_processedexp.c	(revision 22158)
@@ -0,0 +1,398 @@
+/*
+ * dettool_processedexp.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt & EAM; IfA
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+bool toprocessedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("dettool_toprocessedexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detPendingProcessedExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+bool addprocessedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // det_id, exp_id, recip, -bg, -bg_stdev
+    // are required
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false);
+    PXOPT_LOOKUP_S64(exp_id, config->args, "-exp_id", true, false);
+
+    // default values
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+
+    // Required if code == 0
+    PXOPT_LOOKUP_STR(recipe, config->args, "-recip", (code == 0), false);
+
+    // optional
+    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
+    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
+    PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
+    PXOPT_LOOKUP_F64(fringe_0, config->args, "-fringe_0", false, false);
+    PXOPT_LOOKUP_F64(fringe_1, config->args, "-fringe_1", false, false);
+    PXOPT_LOOKUP_F64(fringe_2, config->args, "-fringe_2", false, false);
+    PXOPT_LOOKUP_F64(user_1, config->args, "-user_1", false, false);
+    PXOPT_LOOKUP_F64(user_2, config->args, "-user_2", false, false);
+    PXOPT_LOOKUP_F64(user_3, config->args, "-user_3", false, false);
+    PXOPT_LOOKUP_F64(user_4, config->args, "-user_4", false, false);
+    PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
+    PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", true, false);
+
+    psString query = pxDataGet("dettool_addprocessedexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query, (long long) det_id, (long long) exp_id)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+    psFree(output);
+
+    // create a new detProcessedImfile object
+    detProcessedExpRow *detRow = detProcessedExpRowAlloc(
+        det_id,
+        exp_id,
+        recipe,
+        bg,
+        bg_stdev,
+        bg_mean_stdev,
+        fringe_0,
+        fringe_1,
+        fringe_2,
+        user_1,
+        user_2,
+        user_3,
+        user_4,
+        user_5,
+        path_base,
+	"full",
+        code
+    );
+
+    // insert the new row into the detProcessedImfile table
+    if (!detProcessedExpInsertObject(config->dbh, detRow)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(detRow);
+        return false;
+    }
+
+    psFree(detRow);
+
+    return true;
+}
+
+bool processedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "det_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = psStringCopy("SELECT * FROM detProcessedExp");
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", "AND detProcessedExp.fault != 0");
+    } else {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", "AND detProcessedExp.fault = 0");
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detProcessedExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+bool revertprocessedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "det_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+    PXOPT_COPY_S16(config->args, where, "-code",   "fault", "==");
+
+    psString query = pxDataGet("dettool_revertprocessedexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "detProcessedExp");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    if (psDBAffectedRows(config->dbh) < 1) {
+        psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
+        return false;
+    }
+
+    return true;
+}
+
+bool updateprocessedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false);
+    PXOPT_LOOKUP_S64(exp_id, config->args, "-exp_id", true, false);
+    PXOPT_LOOKUP_STR(data_state, config->args, "-data_state", true, false);
+    if (!setProcessedExpDataState(config, det_id, exp_id, data_state)) {
+	return false;
+    }
+    return true;
+}
+
+bool pendingcleanup_processedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "det_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+
+    psString query = pxDataGet("dettool_pendingcleanup_processedexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detCleanupProcessedExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+// XXX SQL missing
+bool donecleanup_processedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "det_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+
+    psString query = pxDataGet("dettool_donecleanup_processedexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detDoneCleanupProcessedExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_processedimfile.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_processedimfile.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_processedimfile.c	(revision 22158)
@@ -0,0 +1,436 @@
+/*
+ * dettool_processedimfile.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt & EAM; IfA
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+bool toprocessedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id",   "det_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id",   "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("dettool_toprocessedimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "rawImfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree (where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detPendingProcessedImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+bool addprocessedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // det_id, exp_id, class_id, uri, recipe, -bg, -bg_stdev are required
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false);
+    PXOPT_LOOKUP_S64(exp_id, config->args, "-exp_id", true, false);
+    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false);
+
+    // default values
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+
+    // Required if code == 0
+    PXOPT_LOOKUP_STR(uri, config->args, "-uri", (code == 0), false);
+    PXOPT_LOOKUP_STR(recipe, config->args, "-recip", (code == 0), false);
+
+    // optional
+    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
+    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
+    PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
+    PXOPT_LOOKUP_F64(fringe_0, config->args, "-fringe_0", false, false);
+    PXOPT_LOOKUP_F64(fringe_1, config->args, "-fringe_1", false, false);
+    PXOPT_LOOKUP_F64(fringe_2, config->args, "-fringe_2", false, false);
+    PXOPT_LOOKUP_F64(user_1, config->args, "-user_1", false, false);
+    PXOPT_LOOKUP_F64(user_2, config->args, "-user_2", false, false);
+    PXOPT_LOOKUP_F64(user_3, config->args, "-user_3", false, false);
+    PXOPT_LOOKUP_F64(user_4, config->args, "-user_4", false, false);
+    PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
+    PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
+
+    // find the matching rawImfile by exp_id/class_id
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-exp_id",   "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
+
+    psArray *rawImfiles = rawImfileSelectRowObjects(config->dbh, where, 0);
+    psFree(where);
+
+    if (!rawImfiles) {
+        psError(PS_ERR_UNKNOWN, false, "no rawImfile rows found ");
+        return false;
+    }
+
+    // create a new detProcessedImfile object
+    detProcessedImfileRow *detRow = detProcessedImfileRowAlloc(
+        det_id,
+        exp_id,
+        class_id,
+        uri,
+        recipe,
+        bg,
+        bg_stdev,
+        bg_mean_stdev,
+        fringe_0,
+        fringe_1,
+        fringe_2,
+        user_1,
+        user_2,
+        user_3,
+        user_4,
+        user_5,
+        path_base,
+	"full",
+        code
+    );
+    psFree(rawImfiles);
+
+    // insert the new row into the detProcessedImfile table
+    if (!detProcessedImfileInsertObject(config->dbh, detRow)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(detRow);
+        return false;
+    }
+
+    psFree(detRow);
+
+    return true;
+}
+
+bool processedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    char *value = NULL;
+
+    PXOPT_LOOKUP_BOOL(included, config->args, "-included", false);
+    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "det_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
+
+    psString query = pxDataGet("dettool_processedimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psFree(where);
+        return false;
+    }
+
+    // add the two required restrictions: detRun.state and detRun.mode
+    // NOTE the above query requires one of the following two WHERE statements
+    {
+        bool status;
+        if ((value = psMetadataLookupStr(&status, config->args, "-select_state"))) {
+            psStringAppend(&query, " WHERE detRun.state = '%s'", value);
+        } else {
+            psStringAppend(&query, " WHERE detRun.state = 'run'");
+        }
+        if ((value = psMetadataLookupStr(&status, config->args, "-select_mode"))) {
+            psStringAppend(&query, " AND detRun.mode = '%s'", value);
+        } else {
+            psStringAppend(&query, " AND detRun.mode = 'master'");
+        }
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "detProcessedImfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree (where);
+
+    // restrict search to included imfiles
+    if (included) {
+	psStringAppend(&query, " AND detInputExp.include = 1");
+    }
+
+    if (faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", "AND detProcessedImfile.fault != 0");
+    } else {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", "AND detProcessedImfile.fault = 0");
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "rawImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+bool revertprocessedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "det_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
+    PXOPT_COPY_S16(config->args, where, "-code", "fault", "==");
+
+    psString query = pxDataGet("dettool_revertprocessedimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "detProcessedImfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    if (psDBAffectedRows(config->dbh) < 1) {
+        psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
+        return false;
+    }
+
+    return true;
+}
+
+bool updateprocessedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false);
+    PXOPT_LOOKUP_S64(exp_id, config->args, "-exp_id", true, false);
+    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false);
+    PXOPT_LOOKUP_STR(data_state, config->args, "-data_state", true, false);
+
+    if (!setProcessedImfileDataState(config, det_id, exp_id, class_id, data_state)) {
+	return false;
+    }
+    return true;
+}
+
+bool pendingcleanup_processedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "det_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
+
+    psString query = pxDataGet("dettool_pendingcleanup_processedimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detCleanupProcessedImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+// XXX SQL missing
+bool donecleanup_processedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "det_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
+
+    psString query = pxDataGet("dettool_donecleanup_processedimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detDoneCleanup_processedimfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_residexp.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_residexp.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_residexp.c	(revision 22158)
@@ -0,0 +1,479 @@
+/*
+ * dettool_residexp.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt & EAM; IfA
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+/*
+  The SQL returns a list of exposures for which all component class ids have had residuals
+  created.  This list includes the detrend id, iteration, exposure id, detrend type, and
+  whether the exposure was included in the stack for this iteration.
+*/
+
+bool toresidexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("dettool_toresidexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detPendingResidExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+/*
+  The SQL returns a list of exposures for which all component class ids have had residuals
+  created.  This list includes the detrend id, iteration, exposure id, detrend type, and
+  whether the exposure was included in the stack for this iteration.
+*/
+
+bool addresidexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // limit search by det_id, iteration, exp_id
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false); // required
+    PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", false, false);
+    PXOPT_LOOKUP_S64(exp_id, config->args, "-exp_id", true, false); // required
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+    PXOPT_LOOKUP_STR(recipe, config->args, "-recip", (code == 0), false); // Required if code == 0
+    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
+    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
+    PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
+    PXOPT_LOOKUP_F64(bg_skewness, config->args, "-bg_skewness", false, false);
+    PXOPT_LOOKUP_F64(bg_kurtosis, config->args, "-bg_kurtosis", false, false);
+    PXOPT_LOOKUP_F64(bin_stdev, config->args, "-bin_stdev", false, false);
+    PXOPT_LOOKUP_F64(fringe_0, config->args, "-fringe_0", false, false);
+    PXOPT_LOOKUP_F64(fringe_1, config->args, "-fringe_1", false, false);
+    PXOPT_LOOKUP_F64(fringe_2, config->args, "-fringe_2", false, false);
+    PXOPT_LOOKUP_F64(fringe_resid_0, config->args, "-fringe_resid_0", false, false);
+    PXOPT_LOOKUP_F64(fringe_resid_1, config->args, "-fringe_resid_1", false, false);
+    PXOPT_LOOKUP_F64(fringe_resid_2, config->args, "-fringe_resid_2", false, false);
+    PXOPT_LOOKUP_F64(user_1, config->args, "-user_1", false, false);
+    PXOPT_LOOKUP_F64(user_2, config->args, "-user_2", false, false);
+    PXOPT_LOOKUP_F64(user_3, config->args, "-user_3", false, false);
+    PXOPT_LOOKUP_F64(user_4, config->args, "-user_4", false, false);
+    PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
+    PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
+    PXOPT_LOOKUP_BOOL(reject, config->args, "-reject", false);
+
+    psString query = pxDataGet("dettool_toresidexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+	psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+	psStringAppend(&query, " WHERE %s", whereClause);
+	psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        // XXX check psError here
+        psError(PS_ERR_UNKNOWN, false, "no detResidImfile rows found");
+        psFree(output);
+        return false;
+    }
+    psFree(output);
+
+    if (!detResidExpInsert(
+	    config->dbh,
+            det_id,
+            iteration,
+            exp_id,
+            recipe,
+            bg,
+            bg_stdev,
+            bg_mean_stdev,
+            bg_skewness,
+            bg_kurtosis,
+            bin_stdev,
+            fringe_0,
+            fringe_1,
+            fringe_2,
+            fringe_resid_0,
+            fringe_resid_1,
+            fringe_resid_2,
+            user_1,
+            user_2,
+            user_3,
+            user_4,
+            user_5,
+            path_base,
+	    "full",
+            !reject,
+            code
+        )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+bool residexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id",    "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-recip",     "recipe", "==");
+
+    PXOPT_LOOKUP_U64(limit,    config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple,  config->args, "-simple", false);
+    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
+    PXOPT_LOOKUP_BOOL(reject,  config->args, "-reject", false);
+
+    psString query = pxDataGet("dettool_residexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "detResidExp");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", "AND detResidExp.fault != 0");
+    } else {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", "AND detResidExp.fault = 0");
+    }
+
+    // list only accepted rows
+    // XXX the usage of this flag is unclear : -reject means "accepted"?
+    if (reject) {
+        psStringAppend(&query, " %s", "AND detResidExp.accept != 0");
+    } 
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detResidExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+bool revertresidexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id",    "exp_id", "==");
+    PXOPT_COPY_S16(config->args, where, "-code",      "fault", "==");
+
+    psString query = pxDataGet("dettool_revertresidexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "detResidExp");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    if (psDBAffectedRows(config->dbh) < 1) {
+        psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
+        return false;
+    }
+
+    return true;
+}
+
+
+bool updateresidexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_BOOL(reject, config->args, "-reject", false);
+
+    // build a query to search by det_id, iteration, exp_id
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+
+    // find the values we're going to set
+    // copy everything but det_id, iteration, & exp_id from the args and
+    // remove the '-' prefix
+    psMetadata *set = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, set, "-recip", "recipe", "==");
+    PXOPT_COPY_F64(config->args, set, "-bg", "bg", "==");
+    PXOPT_COPY_F64(config->args, set, "-bg_stdev", "bg_stdev", "==");
+    PXOPT_COPY_F64(config->args, set, "-bg_mean_stdev", "bg_mean_stdev", "==");
+    PXOPT_COPY_STR(config->args, set, "-path_base", "path_base", "==");
+    PXOPT_COPY_STR(config->args, set, "-data_state", "data_state", "==");
+
+    // double-check the allowed data_state values
+    PXOPT_LOOKUP_STR(data_state, config->args, "-data_state", false, false);
+    if (data_state) {
+	if (!isValidDataState (data_state)) return false;
+    }
+
+    // this can't be PXOPT_ macro-ized as reject is !'d
+    if (!psMetadataAddBool(set, PS_LIST_TAIL, "accept", 0, "==", !reject)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item accept");
+        psFree(set);
+        psFree(where);
+        return false;
+    }
+
+    long changed = psDBUpdateRows(config->dbh, "detResidExp", where, set);
+    psFree(set);
+    psFree(where);
+
+    if (changed < 0) {
+        psError(PS_ERR_UNKNOWN, false, "no rows were updated");
+        return false;
+    }
+
+    return true;
+}
+
+bool pendingcleanup_residexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id",    "exp_id", "==");
+
+    psString query = pxDataGet("dettool_pendingcleanup_residexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detCleanupResidExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+bool donecleanup_residexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id",    "exp_id", "==");
+
+    psString query = pxDataGet("dettool_donecleanup_residexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detDoneCleanup_residexp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_residimfile.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_residimfile.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_residimfile.c	(revision 22158)
@@ -0,0 +1,404 @@
+/*
+ * dettool_residimfile.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt & EAM; IfA
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+bool toresidimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("dettool_toresidimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detPendingResidImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+bool addresidimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false); // required
+    PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", false, false);
+    PXOPT_LOOKUP_S64(exp_id, config->args, "-exp_id", true, false); // required
+    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false); // required
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+    PXOPT_LOOKUP_STR(uri, config->args, "-uri", (code == 0), false); // Required if code == 0
+    PXOPT_LOOKUP_STR(recipe, config->args, "-recip", (code == 0), false); // Required if code == 0
+    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
+    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
+    PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
+    PXOPT_LOOKUP_F64(bg_skewness, config->args, "-bg_skewness", false, false);
+    PXOPT_LOOKUP_F64(bg_kurtosis, config->args, "-bg_kurtosis", false, false);
+    PXOPT_LOOKUP_F64(bin_stdev, config->args, "-bin_stdev", false, false);
+    PXOPT_LOOKUP_F64(fringe_0, config->args, "-fringe_0", false, false);
+    PXOPT_LOOKUP_F64(fringe_1, config->args, "-fringe_1", false, false);
+    PXOPT_LOOKUP_F64(fringe_2, config->args, "-fringe_2", false, false);
+    PXOPT_LOOKUP_F64(fringe_resid_0, config->args, "-fringe_resid_0", false, false);
+    PXOPT_LOOKUP_F64(fringe_resid_1, config->args, "-fringe_resid_1", false, false);
+    PXOPT_LOOKUP_F64(fringe_resid_2, config->args, "-fringe_resid_2", false, false);
+    PXOPT_LOOKUP_F64(user_1, config->args, "-user_1", false, false);
+    PXOPT_LOOKUP_F64(user_2, config->args, "-user_2", false, false);
+    PXOPT_LOOKUP_F64(user_3, config->args, "-user_3", false, false);
+    PXOPT_LOOKUP_F64(user_4, config->args, "-user_4", false, false);
+    PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
+    PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
+
+    if (!detResidImfileInsert(
+	    config->dbh,
+            det_id,
+            iteration,
+            exp_id,
+            class_id,
+            uri,
+            recipe,
+            bg,
+            bg_stdev,
+            bg_mean_stdev,
+            bg_skewness,
+            bg_kurtosis,
+            bin_stdev,
+            fringe_0,
+            fringe_1,
+            fringe_2,
+            fringe_resid_0,
+            fringe_resid_1,
+            fringe_resid_2,
+            user_1,
+            user_2,
+            user_3,
+            user_4,
+            user_5,
+            path_base,
+	    "full",
+            code
+    )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+bool residimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id",     "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration",  "iteration", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id",     "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id",   "class_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-recip",      "recipe", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
+
+    psString query = pxDataGet("dettool_residimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // NOTE: the query ends in a WHERE, add the required restriction on detRun.state
+    char *value = NULL;
+    bool status;
+    if ((value = psMetadataLookupStr(&status, config->args, "-select_state"))) {
+        psStringAppend(&query, " detRun.state = '%s'", value);
+    } else {
+        psStringAppend(&query, " detRun.state = 'run'");
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "detResidImfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", "AND detResidImfile.fault != 0");
+    } else {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", "AND detResidImfile.fault = 0");
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "rawResidImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+bool revertresidimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id",  "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
+    PXOPT_COPY_S16(config->args, where, "-code",      "fault", "==");
+
+    psString query = pxDataGet("dettool_revertresidimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "detResidImfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    if (psDBAffectedRows(config->dbh) < 1) {
+        psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
+        return false;
+    }
+
+    return true;
+}
+
+bool updateresidimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false);
+    PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", true, false);
+    PXOPT_LOOKUP_S64(exp_id, config->args, "-exp_id", true, false);
+    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false);
+    PXOPT_LOOKUP_STR(data_state, config->args, "-data_state", true, false);
+    if (!setResidImfileDataState(config, det_id, iteration, exp_id, class_id, data_state)) {
+	return false;
+    }
+    return true;
+}
+
+bool pendingcleanup_residimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id",  "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
+
+    psString query = pxDataGet("dettool_pendingcleanup_residimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detCleanupResidImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+bool donecleanup_residimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id",  "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
+
+    psString query = pxDataGet("dettool_donecleanup_residimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detDoneCleanup_residimfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_stack.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_stack.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/dettool_stack.c	(revision 22158)
@@ -0,0 +1,457 @@
+/*
+ * dettool_stack.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt & EAM; IfA
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+static psArray *searchRawImfiles(pxConfig *config);
+
+bool tostackedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("dettool_tostacked.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detPendingStackedImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+// this is NOT a command-line mode : it is used by 'addstackedMode'
+static psArray *searchRawImfiles(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+
+    // select exp_ids from detInputExp matching det_id & iteration
+    // where query should be pre-generated
+    psArray *detInputExp = detInputExpSelectRowObjects(config->dbh, where, 0);
+    psFree (where);
+
+    if (!detInputExp) {
+        psError(PS_ERR_UNKNOWN, false, "no rawExp rows found");
+        return NULL;
+    }
+
+    // generate where query with just the exp_ids
+    psMetadata *where_exp_ids = psMetadataAlloc();
+    for (long i = 0; i < psArrayLength(detInputExp); i++) {
+        detInputExpRow *row = detInputExp->data[i];
+        if (!psMetadataAddS64(where_exp_ids, PS_LIST_TAIL, "exp_id",
+                PS_META_DUPLICATE_OK, "==", row->exp_id)
+        ) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+            psFree(detInputExp);
+            psFree(where_exp_ids);
+            return NULL;
+        }
+    }
+    psFree(detInputExp);
+
+    // select rawImfiles with matching exp_ids
+    psArray *rawImfiles =
+        rawImfileSelectRowObjects(config->dbh, where_exp_ids, 0);
+    psFree(where_exp_ids);
+    if (!rawImfiles) {
+        psError(PS_ERR_UNKNOWN, false, "no rawImfile rows found");
+        return NULL;
+    }
+
+    return rawImfiles;
+}
+
+bool addstackedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // det_id, iteration, class_id, uri, & recipe are required
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false);
+    PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", true, false);
+    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false);
+
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+
+    // Required if code == 0
+    PXOPT_LOOKUP_STR(uri, config->args, "-uri", (code == 0), false);
+    PXOPT_LOOKUP_STR(recipe, config->args, "-recip", (code == 0), false);
+
+    // optional
+    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
+    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
+    PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
+    PXOPT_LOOKUP_F64(user_1, config->args, "-user_1", false, false);
+    PXOPT_LOOKUP_F64(user_2, config->args, "-user_2", false, false);
+    PXOPT_LOOKUP_F64(user_3, config->args, "-user_3", false, false);
+    PXOPT_LOOKUP_F64(user_4, config->args, "-user_4", false, false);
+    PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
+
+    // correlate the class_id against the input exposure(s)
+    // searchRawImfiles defines a where clause to search by det_id and iteration
+    psArray *rawImfiles = searchRawImfiles(config);
+
+    if (!rawImfiles) {
+        psError(PS_ERR_UNKNOWN, false, "failed to get rawImfiles from db");
+        return false;
+    }
+
+    bool valid_class_id = false;
+    if (rawImfiles) {
+        for (long i = 0; i < psArrayLength(rawImfiles); i++) {
+            if (!rawImfiles->data[i]) {
+                fprintf (stderr, "*");
+                continue;
+            }
+            if (strcmp(class_id, ((rawImfileRow *)rawImfiles->data[i])->class_id) == 0) {
+                valid_class_id = true;
+                break;
+            }
+        }
+        psFree(rawImfiles);
+    }
+
+    if (!valid_class_id) {
+        psError(PS_ERR_UNKNOWN, true,
+            "class_id can not be correlated with the input exposures");
+        return false;
+    }
+
+    // create a new detStackedImfile object
+    detStackedImfileRow *stackedImfile = detStackedImfileRowAlloc(
+            det_id,
+            iteration,
+            class_id,
+            uri,
+            recipe,
+            bg,
+            bg_stdev,
+            bg_mean_stdev,
+            user_1,
+            user_2,
+            user_3,
+            user_4,
+            user_5,
+	    "full",
+            code
+        );
+
+    // insert the new row into the detProcessedImfile table
+    if (!detStackedImfileInsertObject(config->dbh, stackedImfile)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(stackedImfile);
+        return false;
+    }
+
+    psFree(stackedImfile);
+
+    return true;
+}
+
+bool stackedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-recip",     "recipe", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("dettool_stacked.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psFree(where);
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "detStackedImfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", "AND detStackedImfile.fault != 0");
+    } else {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", "AND detStackedImfile.fault = 0");
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "rawImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+bool revertstackedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
+    PXOPT_COPY_S16(config->args, where, "-code",      "fault", "==");
+
+    psString query = pxDataGet("dettool_revertstacked.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "detStackedImfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    if (psDBAffectedRows(config->dbh) < 1) {
+        psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
+        return false;
+    }
+
+    return true;
+}
+
+bool updatestackedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false);
+    PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", true, false);
+    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false);
+    PXOPT_LOOKUP_STR(data_state, config->args, "-data_state", true, false);
+
+    if (!setStackedImfileDataState(config, det_id, iteration, class_id, data_state)) {
+	return false;
+    }
+    return true;
+}
+
+bool pendingcleanup_stackedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "detStackedImfile.det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "detStackedImfile.iteration", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "detStackedImfile.class_id", "==");
+
+    psString query = pxDataGet("dettool_pendingcleanup_stacked.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detCleanupStackedImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+// XXX SQL missing
+bool donecleanup_stackedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-det_id", "detStackedImfile.det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "detStackedImfile.iteration", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "detStackedImfile.class_id", "==");
+
+    psString query = pxDataGet("dettool_donecleanup_stacked.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detDoneCleanup_stacked", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/difftool.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/difftool.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/difftool.c	(revision 22158)
@@ -0,0 +1,1130 @@
+/*
+ * difftool.c
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVB_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <ippdb.h>
+
+#include "pxtools.h"
+#include "difftool.h"
+
+static bool definerunMode(pxConfig *config);
+static bool updaterunMode(pxConfig *config);
+static bool addinputskyfileMode(pxConfig *config);
+static bool inputskyfileMode(pxConfig *config);
+static bool todiffskyfileMode(pxConfig *config);
+static bool adddiffskyfileMode(pxConfig *config);
+static bool diffskyfileMode(pxConfig *config);
+static bool revertdiffskyfileMode(pxConfig *config);
+static bool definepoprunMode(pxConfig *config);
+static bool definebyqueryMode(pxConfig *config);
+static bool pendingcleanuprunMode(pxConfig *config);
+static bool pendingcleanupskyfileMode(pxConfig *config);
+static bool donecleanupMode(pxConfig *config);
+
+static bool setdiffRunState(pxConfig *config, psS64 diff_id, const char *state);
+
+# define MODECASE(caseName, func) \
+    case caseName: \
+    if (!func(config)) { \
+        goto FAIL; \
+    } \
+    break;
+
+int main(int argc, char **argv)
+{
+    psLibInit(NULL);
+
+    pxConfig *config = difftoolConfig(NULL, argc, argv);
+    if (!config) {
+        psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+        goto FAIL;
+    }
+
+    switch (config->mode) {
+        MODECASE(DIFFTOOL_MODE_DEFINERUN,             definerunMode);
+        MODECASE(DIFFTOOL_MODE_UPDATERUN,             updaterunMode);
+        MODECASE(DIFFTOOL_MODE_ADDINPUTSKYFILE,       addinputskyfileMode);
+        MODECASE(DIFFTOOL_MODE_INPUTSKYFILE,          inputskyfileMode);
+        MODECASE(DIFFTOOL_MODE_TODIFFSKYFILE,         todiffskyfileMode);
+        MODECASE(DIFFTOOL_MODE_ADDDIFFSKYFILE,        adddiffskyfileMode);
+        MODECASE(DIFFTOOL_MODE_DIFFSKYFILE,           diffskyfileMode);
+        MODECASE(DIFFTOOL_MODE_REVERTDIFFSKYFILE,     revertdiffskyfileMode);
+        MODECASE(DIFFTOOL_MODE_DEFINEPOPRUN,          definepoprunMode);
+        MODECASE(DIFFTOOL_MODE_DEFINEBYQUERY,         definebyqueryMode);
+        MODECASE(DIFFTOOL_MODE_PENDINGCLEANUPRUN,     pendingcleanuprunMode);
+        MODECASE(DIFFTOOL_MODE_PENDINGCLEANUPSKYFILE, pendingcleanupskyfileMode);
+        MODECASE(DIFFTOOL_MODE_DONECLEANUP,           donecleanupMode);
+        default:
+            psAbort("invalid option (this should not happen)");
+    }
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(EXIT_SUCCESS);
+
+FAIL:
+    psErrorStackPrint(stderr, "\n");
+    int exit_status = pxerrorGetExitStatus();
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exit_status);
+}
+
+
+static bool definerunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required options
+    PXOPT_LOOKUP_STR(workdir, config->args, "-workdir", true, false);
+    PXOPT_LOOKUP_STR(skycell_id, config->args, "-skycell_id", true, false);
+    PXOPT_LOOKUP_STR(tess_id, config->args, "-tess_id", true, false);
+
+    // default
+    PXOPT_LOOKUP_TIME(registered, config->args, "-registered", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    diffRunRow *run = diffRunRowAlloc(
+            0,          // ID
+            "reg",      // state
+            workdir,
+            NULL,       // dvodb
+            registered,
+            skycell_id,
+            tess_id
+    );
+    if (!run) {
+        psError(PS_ERR_UNKNOWN, false, "failed to alloc diffRun object");
+        return true;
+    }
+    if (!diffRunInsertObject(config->dbh, run)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(run);
+        return true;
+    }
+
+    // get the assigned diff_id
+    run->diff_id = psDBLastInsertID(config->dbh);
+
+    if (!diffRunPrintObject(stdout, run, !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print object");
+            psFree(run);
+            return false;
+    }
+
+    psFree(run);
+
+    return true;
+}
+
+
+static bool updaterunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required options
+    PXOPT_LOOKUP_S64(diff_id, config->args, "-diff_id", true, false);
+    PXOPT_LOOKUP_STR(state, config->args, "-state", true, false);
+
+    if (state) {
+        // set detRun.state to state
+        return setdiffRunState(config, diff_id, state);
+    }
+
+    return true;
+}
+
+
+static bool addinputskyfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required options
+    PXOPT_LOOKUP_S64(diff_id, config->args, "-diff_id", true, false);
+
+    // optional
+    PXOPT_LOOKUP_S64(stack_id, config->args, "-stack_id", false, false);
+    PXOPT_LOOKUP_S64(warp_id, config->args, "-warp_id", false, false);
+    PXOPT_LOOKUP_STR(kind, config->args, "-kind", false, false);
+
+    // defaults to false
+    PXOPT_LOOKUP_BOOL(template, config->args, "-template", false);
+
+    // must provide either stack_id or warp_id but not BOTH
+    if (!(stack_id || warp_id)) {
+        psError(PS_ERR_UNKNOWN, true, "either -stack_id or -warp_id must be specified");
+        return false;
+    }
+    if (stack_id && warp_id) {
+        psError(PS_ERR_UNKNOWN, true, "either -stack_id or -warp_id must be specified");
+        return false;
+    }
+
+    // if a warp_id was provided we need to lookup the skycell_id and tess_id
+    // from the warpRun
+    psString skycell_id = NULL;
+    psString tess_id = NULL;
+    if (warp_id) {
+        if (!p_psDBRunQuery(config->dbh, "SELECT * from diffRun WHERE diff_id = %" PRId64, diff_id)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        }
+
+        psArray *output = p_psDBFetchResult(config->dbh);
+        if (!output) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        }
+        if (!psArrayLength(output)) {
+            psError(PS_ERR_UNKNOWN, false, "diff_id %" PRId64 " not found", diff_id);
+            psFree(output);
+            return false;
+        }
+
+        diffRunRow *run = diffRunObjectFromMetadata(output->data[0]);
+        skycell_id = run->skycell_id;
+        tess_id = run->tess_id;
+    }
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!diffInputSkyfileInsert(config->dbh,
+            diff_id,
+            template,
+            stack_id ? stack_id : PS_MAX_S64, // defined or NULL
+            warp_id ? warp_id : PS_MAX_S64, // defined or NULL
+            skycell_id,
+            tess_id,
+            kind
+        )) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!p_psDBRunQuery(config->dbh, "SELECT count(diff_id) FROM diffRun JOIN diffInputSkyfile USING(diff_id) WHERE diff_id = %" PRId64, diff_id)) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "diff_id %" PRId64 " not found", diff_id);
+        psFree(output);
+        return false;
+    }
+
+    bool status;
+    psS32 count = psMetadataLookupS32(&status, output->data[0], "count(diff_id)");
+
+    if (count == 2) {
+        if (!setdiffRunState(config, diff_id, "new")) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        }
+    }
+
+    // point of no return
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool inputskyfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+
+    PXOPT_COPY_S64(config->args, where,  "-diff_id", "diff_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-warp_id", "warp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-skycell_id", "skycell_id", "==");
+    PXOPT_COPY_STR(config->args, where,  "-tess_id", "tess_id", "==");
+    PXOPT_COPY_STR(config->args, where,  "-kind", "kind", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_BOOL(template, config->args, "-template", false);
+    PXOPT_LOOKUP_BOOL(input, config->args, "-input", false);
+
+    if (template && input) {
+        // User apparently wants both, which is the default behaviour
+        template = false;
+        input = false;
+    }
+
+    // find all rawImfiles matching the default query
+    psString query = pxDataGet("difftool_inputskyfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " WHERE %s", whereClause);
+        psFree(whereClause);
+    }
+
+    // Add condition to get only templates or only inputs
+    {
+        psString whereClause = NULL;
+        if (template) {
+            psStringAppend(&whereClause, " %s", " template != 0");
+        } else if (input) {
+            psStringAppend(&whereClause, " %s", " template = 0");
+        }
+        if (whereClause) {
+            psStringAppend(&query, " %s %s", psListLength(where->list) ? "AND" : "WHERE", whereClause);
+        }
+        psFree(whereClause);
+    }
+
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("difftool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "diffInputSkyfile", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool todiffskyfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where,  "-diff_id", "diff_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("difftool_todiffskyfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "diffSkyfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("difftool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "diffSkyfile", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool adddiffskyfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_S64(diff_id, config->args, "-diff_id", true, false); // required
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+    PXOPT_LOOKUP_STR(uri, config->args, "-uri", (code == 0), false);
+    PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", (code == 0), false);
+
+    // optional
+    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
+    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
+    PXOPT_LOOKUP_F32(dtime_diff, config->args, "-dtime_diff", false, false);
+    PXOPT_LOOKUP_S32(stamps_num, config->args, "-stamps_num", false, false);
+    PXOPT_LOOKUP_F32(stamps_rms, config->args, "-stamps_rms", false, false);
+    PXOPT_LOOKUP_S32(sources, config->args, "-sources", false, false);
+    PXOPT_LOOKUP_STR(hostname, config->args, "-hostname", false, false);
+    PXOPT_LOOKUP_F32(good_frac, config->args, "-good_frac", false, false);
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!diffSkyfileInsert(config->dbh,
+                           diff_id,
+                           uri,
+                           path_base,
+                           bg,
+                           bg_stdev,
+                           stamps_num,
+                           stamps_rms,
+                           sources,
+                           dtime_diff,
+                           hostname,
+                           good_frac,
+                           code
+          )) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!setdiffRunState(config, diff_id, "full")) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // point of no return
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool diffskyfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where,  "-diff_id", "diffSkyfile.diff_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-skycell_id", "diffSkyfile.skycell_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-tess_id", "diffSkyfile.tess_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "rawExp.exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_name", "rawExp.exp_name", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("difftool_skyfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("difftool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "diffSkyfile", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool revertdiffskyfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where,  "-diff_id", "diff_id", "==");
+    PXOPT_COPY_S16(config->args, where, "-code",     "fault", "==");
+
+    psString query = pxDataGet("difftool_revertdiffskyfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "diffSkyfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    if (psDBAffectedRows(config->dbh) < 1) {
+        psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool setdiffRunState(pxConfig *config, psS64 diff_id, const char *state)
+{
+    PS_ASSERT_PTR_NON_NULL(state, false);
+
+    // check that state is a valid string value
+    if (!pxIsValidState(state)) {
+        psError(PS_ERR_UNKNOWN, false, "invalid diffRun state: %s", state);
+        return false;
+    }
+
+    char *query = "UPDATE diffRun SET state = '%s' WHERE diff_id = %"PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, state, diff_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for diff_id %"PRId64, diff_id);
+        return false;
+    }
+
+    return true;
+}
+
+// Generate a single populated run
+static bool populatedrun(psArray *list, // List of runs, to print
+                         const char *workdir, // Working directory
+                         const char *skycell_id, // Skycell identifier
+                         const char *tess_id, // Tessellation identifier
+                         psS64 input_warp_id, // Warp identifier for input image, PS_MAX_S64 for none
+                         psS64 input_stack_id, // Stack identifier for input image, PS_MAX_S64 for none
+                         psS64 template_warp_id, // Warp identifier for template image, PS_MAX_S64 for none
+                         psS64 template_stack_id, // Stack identifier for template image, PS_MAX_S64 for none
+                         pxConfig *config // Configuration
+                         )
+{
+    PS_ASSERT_STRING_NON_EMPTY(workdir, false);
+    PS_ASSERT_STRING_NON_EMPTY(skycell_id, false);
+    PS_ASSERT_STRING_NON_EMPTY(tess_id, false);
+    if ((input_warp_id == PS_MAX_S64 && input_stack_id == PS_MAX_S64) ||
+        (input_warp_id != PS_MAX_S64 && input_stack_id != PS_MAX_S64)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "One, and only one, input must be defined.");
+        return false;
+    }
+    if ((template_warp_id == PS_MAX_S64 && template_stack_id == PS_MAX_S64) ||
+        (template_warp_id != PS_MAX_S64 && template_stack_id != PS_MAX_S64)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "One, and only one, template must be defined.");
+        return false;
+    }
+
+    // default
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_TIME(registered, config->args, "-registered", false, false);
+
+    diffRunRow *run = diffRunRowAlloc(
+            0,          // ID
+            "reg",      // state
+            workdir,
+            NULL,       // dvodb
+            registered,
+            skycell_id,
+            tess_id
+    );
+
+    if (!run) {
+        psError(PS_ERR_UNKNOWN, false, "failed to alloc diffRun object");
+        return true;
+    }
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!diffRunInsertObject(config->dbh, run)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(run);
+        return true;
+    }
+
+    // get the assigned diff_id
+    run->diff_id = psDBLastInsertID(config->dbh);
+
+    // Template
+    if (!diffInputSkyfileInsert(config->dbh,
+            run->diff_id,
+            true,
+            template_stack_id,
+            template_warp_id,
+            skycell_id,
+            tess_id,
+            NULL    // kind
+        )) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // Input
+    if (!diffInputSkyfileInsert(config->dbh,
+            run->diff_id,
+            false,
+            input_stack_id,
+            input_warp_id,
+            skycell_id,
+            tess_id,
+            NULL    // kind
+        )) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    char *query = "UPDATE diffRun SET state = 'run' WHERE diff_id = '%" PRId64 "'";
+    if (!p_psDBRunQuery(config->dbh, query, run->diff_id)) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to set state to run for diff_id %" PRId64, run->diff_id);
+        return false;
+    }
+
+    // point of no return
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (list) {
+        psArrayAdd(list, list->n, run);
+    }
+
+    psFree(run);
+
+    return true;
+}
+
+
+static bool definepoprunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(workdir, config->args, "-workdir", true, false); // required options
+    PXOPT_LOOKUP_STR(skycell_id, config->args, "-skycell_id", true, false); // required options
+    PXOPT_LOOKUP_STR(tess_id, config->args, "-tess_id", true, false); // required options
+    PXOPT_LOOKUP_S64(template_warp_id, config->args, "-template_warp_id", false, false);
+    PXOPT_LOOKUP_S64(template_stack_id, config->args, "-template_stack_id", false, false);
+    PXOPT_LOOKUP_S64(input_warp_id, config->args, "-input_warp_id", false, false);
+    PXOPT_LOOKUP_S64(input_stack_id, config->args, "-input_stack_id", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    if (template_stack_id && template_warp_id) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Only one template can be defined.");
+        return false;
+    }
+    if (!template_stack_id && !template_warp_id) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "No template has been defined (-template_stack_id or -template_warp_id)");
+        return false;
+    }
+
+    if (input_stack_id && input_warp_id) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Only one input can be defined.");
+        return false;
+    }
+    if (!input_stack_id && !input_warp_id) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "No input has been defined (-input_stack_id or -input_warp_id)");
+        return false;
+    }
+
+    psArray *list = psArrayAllocEmpty(16); // List of runs, to print
+
+    if (!populatedrun(list, workdir, skycell_id, tess_id,
+                      input_warp_id ? input_warp_id : PS_MAX_S64,
+                      input_stack_id ? input_stack_id : PS_MAX_S64,
+                      template_warp_id ? template_warp_id : PS_MAX_S64,
+                      template_stack_id ? template_stack_id : PS_MAX_S64,
+                      config)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to create populated diffRun");
+        psFree(list);
+        return false;
+    }
+
+    if (!diffRunPrintObjects(stdout, list, !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print object");
+            psFree(list);
+            return false;
+    }
+    psFree(list);
+
+    return true;
+}
+
+
+static bool definebyqueryMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+
+    PXOPT_COPY_S64(config->args, where, "-warp_id", "warp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-skycell_id", "skycell_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-tess_id", "tess_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter", "filter", "==");
+    PXOPT_COPY_STR(config->args, where,  "-kind", "kind", "==");
+    PXOPT_COPY_F32(config->args, where,  "-good_frac", "good_frac", ">=");
+    PXOPT_LOOKUP_STR(workdir, config->args, "-workdir", true, false); // required options
+    PXOPT_LOOKUP_TIME(registered, config->args, "-registered", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_BOOL(newTemplates, config->args, "-new-templates", false);
+
+    // find all things to queue
+    psString query = pxDataGet("difftool_definebyquery.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (newTemplates) {
+        // Warps that haven't been diffed OR warps that can take a newer template in the diff
+        psStringAppend(&query, " WHERE (diff_id IS NULL OR best_stack_id > current_stack_id)");
+    } else {
+        // Only warps that haven't been diffed
+        psStringAppend(&query, " WHERE diff_id IS NULL");
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "warpsToDiff");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("difftool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    psArray *list = psArrayAllocEmpty(16); // List of runs, to print
+    long numGood = 0;                   // Number of good rows added
+    for (long i = 0; i < output->n; i++) {
+        psMetadata *row = output->data[i]; // Output row from query
+
+        // Selected parameters
+        bool mdok;                      // Status of MD lookup
+        const char *skycell_id = psMetadataLookupStr(&mdok, row, "skycell_id");
+        if (!mdok || !skycell_id) {
+            psWarning("skycell_id not found --- ignoring row %ld", i);
+            continue;
+        }
+        const char *tess_id = psMetadataLookupStr(&mdok, row, "tess_id");
+        if (!mdok || !tess_id) {
+            psWarning("tess_id not found --- ignoring row %ld", i);
+            continue;
+        }
+        psS64 stack_id = psMetadataLookupS64(&mdok, row, "best_stack_id");
+        if (!mdok) {
+            psWarning("stack_id not found --- ignoring row %ld", i);
+            continue;
+        }
+        psS64 warp_id = psMetadataLookupS64(&mdok, row, "warp_id");
+        if (!mdok) {
+            psWarning("warp_id not found --- ignoring row %ld", i);
+            continue;
+        }
+
+        if (!populatedrun(list, workdir, skycell_id, tess_id, warp_id, PS_MAX_S64, PS_MAX_S64,
+                          stack_id, config)) {
+            psWarning("Unable to add run for %s,%s,%" PRId64 ",%" PRId64, skycell_id, tess_id,
+                      warp_id, stack_id);
+            psErrorClear();
+            continue;
+        }
+
+        numGood++;
+    }
+    psFree(output);
+
+    if (!diffRunPrintObjects(stdout, list, !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print object");
+        psFree(list);
+        return false;
+    }
+    psFree(list);
+
+    return true;
+}
+
+static bool pendingcleanuprunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("difftool_pendingcleanuprun.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("difftool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "diffPendingCleanupRun", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool pendingcleanupskyfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_S64(diff_id, config->args, "-diff_id", false, false);
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    if (diff_id) {
+        PXOPT_COPY_S64(config->args, where, "-diff_id", "diff_id", "==");
+    }
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("difftool_pendingcleanupskyfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("difftool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "diffPendingCleanupSkyfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool donecleanupMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("difftool_donecleanup.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("difftool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "diffDoneCleanup", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/difftool.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/difftool.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/difftool.h	(revision 22158)
@@ -0,0 +1,44 @@
+/*
+ * difftool.h
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef DIFFTOOL_H
+#define DIFFTOOL_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+    DIFFTOOL_MODE_NONE           = 0x0,
+    DIFFTOOL_MODE_DEFINERUN,
+    DIFFTOOL_MODE_UPDATERUN,
+    DIFFTOOL_MODE_ADDINPUTSKYFILE,
+    DIFFTOOL_MODE_INPUTSKYFILE,
+    DIFFTOOL_MODE_TODIFFSKYFILE,
+    DIFFTOOL_MODE_ADDDIFFSKYFILE,
+    DIFFTOOL_MODE_DIFFSKYFILE,
+    DIFFTOOL_MODE_REVERTDIFFSKYFILE,
+    DIFFTOOL_MODE_DEFINEPOPRUN,
+    DIFFTOOL_MODE_DEFINEBYQUERY,
+    DIFFTOOL_MODE_PENDINGCLEANUPRUN,
+    DIFFTOOL_MODE_PENDINGCLEANUPSKYFILE,
+    DIFFTOOL_MODE_DONECLEANUP,
+} difftoolMode;
+
+pxConfig *difftoolConfig(pxConfig *config, int argc, char **argv);
+
+#endif // DIFFTOOL_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/difftoolConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/difftoolConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/difftoolConfig.c	(revision 22158)
@@ -0,0 +1,202 @@
+/*
+ * difftoolConfig.c
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <psmodules.h>
+
+#include "pxtools.h"
+#include "difftool.h"
+
+pxConfig *difftoolConfig(pxConfig *config, int argc, char **argv)
+{
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    pmConfigReadParamsSet(false);
+
+    // setup site config
+    config->modules = pmConfigRead(&argc, argv, NULL);
+    if (!config->modules) {
+        psError(PS_ERR_UNKNOWN, false, "Can't find site configuration");
+        psFree(config);
+        return NULL;
+    }
+
+    psTime *now = psTimeGetNow(PS_TIME_TAI);
+
+    // -definerun
+    psMetadata *definerunArgs = psMetadataAlloc();
+    psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-workdir", 0,            "define workdir (required)", NULL);
+    psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-skycell_id",  0,            "define skycell ID (required)", NULL);
+    psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-tess_id",  0,            "define tessellation ID (required)", NULL);
+    psMetadataAddTime(definerunArgs, PS_LIST_TAIL, "-registered",  0,            "time detrend run was registered", now);
+    psMetadataAddBool(definerunArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -updaterun
+    psMetadata *updaterunArgs = psMetadataAlloc();
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-diff_id", 0,            "define diff ID (required)", 0);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-state", 0,            "set state (required)", NULL);
+
+    // -addinputskyfile
+    psMetadata *addinputskyfileArgs = psMetadataAlloc();
+    psMetadataAddS64(addinputskyfileArgs, PS_LIST_TAIL, "-diff_id", 0,            "define diff ID (required)", 0);
+    psMetadataAddS64(addinputskyfileArgs, PS_LIST_TAIL, "-stack_id", 0,            "define stack ID", 0);
+    psMetadataAddS64(addinputskyfileArgs, PS_LIST_TAIL, "-warp_id", 0,            "define warp ID", 0);
+    psMetadataAddStr(addinputskyfileArgs, PS_LIST_TAIL, "-kind", 0,            "define kind", NULL);
+    psMetadataAddBool(addinputskyfileArgs, PS_LIST_TAIL, "-template",  0,            "this sky cell file is the subtrahend", false);
+
+    // -inputskyfile
+    psMetadata *inputskyfileArgs = psMetadataAlloc();
+    psMetadataAddS64(inputskyfileArgs, PS_LIST_TAIL, "-diff_id", 0,            "search by diff ID", 0);
+    psMetadataAddS64(inputskyfileArgs, PS_LIST_TAIL, "-warp_id", 0,            "search by warp ID", 0);
+    psMetadataAddStr(inputskyfileArgs, PS_LIST_TAIL, "-skycell_id", 0,            "search by skycell ID", NULL);
+    psMetadataAddStr(inputskyfileArgs, PS_LIST_TAIL, "-tess_id", 0,            "search by tess ID", NULL);
+    psMetadataAddStr(inputskyfileArgs, PS_LIST_TAIL, "-kind", 0,            "search by kind", NULL);
+    psMetadataAddBool(inputskyfileArgs, PS_LIST_TAIL, "-template",  0,            "find only subtrahend", false);
+    psMetadataAddBool(inputskyfileArgs, PS_LIST_TAIL, "-input", 0, "find only minuend", false);
+    psMetadataAddU64(inputskyfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(inputskyfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -todiffskyfile
+    psMetadata *todiffskyfileArgs = psMetadataAlloc();
+    psMetadataAddS64(todiffskyfileArgs, PS_LIST_TAIL, "-diff_id", 0,            "search by diff ID", 0);
+    psMetadataAddU64(todiffskyfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(todiffskyfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -adddiffskyfile
+    psMetadata *adddiffskyfileArgs = psMetadataAlloc();
+    psMetadataAddS64(adddiffskyfileArgs, PS_LIST_TAIL, "-diff_id", 0,            "define warp ID (required)", 0);
+    psMetadataAddS16(adddiffskyfileArgs, PS_LIST_TAIL, "-code",  0,            "set fault code", 0);
+    psMetadataAddStr(adddiffskyfileArgs, PS_LIST_TAIL, "-uri", 0,            "define URI of file", 0);
+    psMetadataAddStr(adddiffskyfileArgs, PS_LIST_TAIL, "-path_base", 0,            "define base output location", 0);
+    psMetadataAddF64(adddiffskyfileArgs, PS_LIST_TAIL, "-bg",  0,            "define exposure background", NAN);
+    psMetadataAddF64(adddiffskyfileArgs, PS_LIST_TAIL, "-bg_stdev",  0,            "define exposure background mean stdev", NAN);
+    psMetadataAddF32(adddiffskyfileArgs, PS_LIST_TAIL, "-dtime_diff",  0,            "define elapsed processing time", NAN);
+    psMetadataAddS32(adddiffskyfileArgs, PS_LIST_TAIL, "-stamps_num",  0,            "define subtraction stamp number", 0);
+    psMetadataAddF32(adddiffskyfileArgs, PS_LIST_TAIL, "-stamps_rms",  0,            "define subtraction stamp rms", NAN);
+    psMetadataAddS32(adddiffskyfileArgs, PS_LIST_TAIL, "-sources",  0,            "define number of sources", 0);
+    psMetadataAddStr(adddiffskyfileArgs, PS_LIST_TAIL, "-hostname", 0,            "define hostname", 0);
+    psMetadataAddF32(adddiffskyfileArgs, PS_LIST_TAIL, "-good_frac",  0,            "define %% of good pixels", NAN);
+
+    // -diffskyfile
+    psMetadata *diffskyfileArgs = psMetadataAlloc();
+    psMetadataAddS64(diffskyfileArgs, PS_LIST_TAIL, "-diff_id", 0,            "search by warp ID", 0);
+    psMetadataAddStr(diffskyfileArgs , PS_LIST_TAIL, "-skycell_id",  0,            "define skycell ID", NULL);
+    psMetadataAddStr(diffskyfileArgs, PS_LIST_TAIL, "-tess_id",  0,            "define tessellation ID", NULL);
+    psMetadataAddS64(diffskyfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "define exposure ID", 0);
+    psMetadataAddStr(diffskyfileArgs , PS_LIST_TAIL, "-exp_name",  0,         "define exposure name", NULL);
+    psMetadataAddU64(diffskyfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(diffskyfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -revertdiffskyfile
+    psMetadata *revertdiffskyfileArgs = psMetadataAlloc();
+    psMetadataAddS64(revertdiffskyfileArgs, PS_LIST_TAIL, "-diff_id", 0,            "define warp ID (required)", 0);
+    psMetadataAddS16(revertdiffskyfileArgs, PS_LIST_TAIL, "-code",  0,            "search by fault code", 0);
+
+    // -definepoprun
+    psMetadata *definepoprunArgs = psMetadataAlloc();
+    psMetadataAddStr(definepoprunArgs, PS_LIST_TAIL, "-workdir", 0,            "define workdir (required)", NULL);
+    psMetadataAddTime(definepoprunArgs, PS_LIST_TAIL, "-registered",  0,            "time detrend run was registered", now);
+    psMetadataAddStr(definepoprunArgs, PS_LIST_TAIL, "-skycell_id",  0,            "define skycell ID (required)", NULL);
+    psMetadataAddStr(definepoprunArgs, PS_LIST_TAIL, "-tess_id",  0,            "define tessellation ID (required)", NULL);
+    psMetadataAddBool(definepoprunArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddS64(definepoprunArgs, PS_LIST_TAIL, "-template_warp_id", 0,            "define warp ID for template", 0);
+    psMetadataAddS64(definepoprunArgs, PS_LIST_TAIL, "-template_stack_id", 0,            "define stack ID for template", 0);
+    psMetadataAddS64(definepoprunArgs, PS_LIST_TAIL, "-input_warp_id", 0,            "define warp ID for input", 0);
+    psMetadataAddS64(definepoprunArgs, PS_LIST_TAIL, "-input_stack_id", 0,            "define stack ID for input", 0);
+
+    // -definebyquery
+    psMetadata *definebyqueryArgs = psMetadataAlloc();
+    psMetadataAddS64(definebyqueryArgs, PS_LIST_TAIL, "-diff_id", 0, "search by diff ID", 0);
+    psMetadataAddS64(definebyqueryArgs, PS_LIST_TAIL, "-warp_id", 0, "search by warp ID", 0);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-skycell_id", 0, "search by skycell ID", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-tess_id", 0, "search by tess ID", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-filter", 0, "search by filter", NULL);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-good_frac", 0, "minimum good fraction of skycell", NAN);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-kind", 0, "search by kind", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-workdir", 0, "define workdir (required)", NULL);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-registered", 0, "time detrend run was registered", now);
+    psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-new-templates", 0, "also search for diffs with new template", false);
+    psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-simple", 0, "use the simple output format", false);
+
+    // -pendingcleanuprun
+    psMetadata *pendingcleanuprunArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingcleanuprunArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddBool(pendingcleanuprunArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanuprunArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -pendingcleanupskyfile
+    psMetadata *pendingcleanupskyfileArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingcleanupskyfileArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddS64(pendingcleanupskyfileArgs, PS_LIST_TAIL, "-diff_id", 0,          "search by diff ID", 0);
+    psMetadataAddBool(pendingcleanupskyfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanupskyfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -donecleanup
+    psMetadata *donecleanupArgs = psMetadataAlloc();
+    psMetadataAddStr(donecleanupArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddBool(donecleanupArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(donecleanupArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    psFree(now);
+
+    psMetadata *argSets = psMetadataAlloc();
+    psMetadata *modes = psMetadataAlloc();
+
+    PXOPT_ADD_MODE("-definerun",        "", DIFFTOOL_MODE_DEFINERUN,         definerunArgs);
+    PXOPT_ADD_MODE("-updaterun",        "", DIFFTOOL_MODE_UPDATERUN,         updaterunArgs);
+    PXOPT_ADD_MODE("-addinputskyfile",  "", DIFFTOOL_MODE_ADDINPUTSKYFILE,   addinputskyfileArgs);
+    PXOPT_ADD_MODE("-inputskyfile",     "", DIFFTOOL_MODE_INPUTSKYFILE,      inputskyfileArgs);
+    PXOPT_ADD_MODE("-todiffskyfile",    "", DIFFTOOL_MODE_TODIFFSKYFILE,     todiffskyfileArgs);
+    PXOPT_ADD_MODE("-adddiffskyfile",   "", DIFFTOOL_MODE_ADDDIFFSKYFILE,    adddiffskyfileArgs);
+    PXOPT_ADD_MODE("-diffskyfile",      "", DIFFTOOL_MODE_DIFFSKYFILE,       diffskyfileArgs);
+    PXOPT_ADD_MODE("-revertdiffskyfile","", DIFFTOOL_MODE_REVERTDIFFSKYFILE, revertdiffskyfileArgs);
+    PXOPT_ADD_MODE("-definepoprun",     "", DIFFTOOL_MODE_DEFINEPOPRUN,      definepoprunArgs);
+    PXOPT_ADD_MODE("-definebyquery",    "", DIFFTOOL_MODE_DEFINEBYQUERY,     definebyqueryArgs);
+    PXOPT_ADD_MODE("-pendingcleanuprun",     "show runs that need to be cleaned up", DIFFTOOL_MODE_PENDINGCLEANUPRUN,    pendingcleanuprunArgs);
+    PXOPT_ADD_MODE("-pendingcleanupskyfile", "show runs that need to be cleaned up", DIFFTOOL_MODE_PENDINGCLEANUPSKYFILE, pendingcleanupskyfileArgs);
+    PXOPT_ADD_MODE("-donecleanup",           "show runs that have been cleaned",     DIFFTOOL_MODE_DONECLEANUP,          donecleanupArgs);
+
+    if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
+        psError(PS_ERR_UNKNOWN, true, "option parsing failed");
+        psFree(argSets);
+        psFree(modes);
+        psFree(config);
+        return NULL;
+    }
+
+    psFree(argSets);
+    psFree(modes);
+
+    // define Database handle, if used
+    // do this last so we don't setup a connection before CLI options are
+    // validated
+    config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+    if (!config->dbh) {
+        psError(PS_ERR_UNKNOWN, false, "Can't configure database");
+        psFree(config);
+        return NULL;
+    }
+
+    return config;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/fakemagic
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/fakemagic	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/fakemagic	(revision 22158)
@@ -0,0 +1,25 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2007  Joshua Hoblitt
+#
+# $Id: fakemagic,v 1.1 2007-11-05 23:29:54 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.01';
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version pass_through );
+use Pod::Usage qw( pod2usage );
+
+my ($output);
+GetOptions(
+    'output|o=s'    => \$output,
+) || pod2usage( 2 );
+
+pod2usage( -msg => "Required options: --output <filepath>", -exitval => 2 )
+        unless defined $output;
+
+open(my $fh, ">$output") or die "can't open file $output: $!";
+close($fh) or die "can't close file $output: $!";
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/faketool.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/faketool.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/faketool.c	(revision 22158)
@@ -0,0 +1,1123 @@
+/*
+ * faketool.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "pxtools.h"
+#include "pxdata.h"
+
+#include "faketool.h"
+
+static bool definebyqueryMode(pxConfig *config);
+static bool updaterunMode(pxConfig *config);
+static bool pendingexpMode(pxConfig *config);
+static bool pendingimfileMode(pxConfig *config);
+static bool addprocessedimfileMode(pxConfig *config);
+static bool processedimfileMode(pxConfig *config);
+static bool revertprocessedimfileMode(pxConfig *config);
+static bool updateprocessedimfileMode(pxConfig *config);
+static bool blockMode(pxConfig *config);
+static bool maskedMode(pxConfig *config);
+static bool unmaskedMode(pxConfig *config);
+static bool unblockMode(pxConfig *config);
+static bool pendingcleanuprunMode(pxConfig *config);
+static bool pendingcleanupimfileMode(pxConfig *config);
+static bool donecleanupMode(pxConfig *config);
+
+static bool fakeProcessedCompleteExp(pxConfig *config);
+
+# define MODECASE(caseName, func) \
+    case caseName: \
+    if (!func(config)) { \
+        goto FAIL; \
+    } \
+    break;
+
+int main(int argc, char **argv) {
+    psLibInit(NULL);
+
+    pxConfig *config = faketoolConfig(NULL, argc, argv);
+    if (!config) {
+        psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+        goto FAIL;
+    }
+
+    switch (config->mode) {
+        MODECASE(FAKETOOL_MODE_DEFINEBYQUERY,           definebyqueryMode);
+        MODECASE(FAKETOOL_MODE_UPDATERUN,               updaterunMode);
+        MODECASE(FAKETOOL_MODE_PENDINGEXP,              pendingexpMode);
+        MODECASE(FAKETOOL_MODE_PENDINGIMFILE,           pendingimfileMode);
+        MODECASE(FAKETOOL_MODE_ADDPROCESSEDIMFILE,      addprocessedimfileMode);
+        MODECASE(FAKETOOL_MODE_PROCESSEDIMFILE,         processedimfileMode);
+        MODECASE(FAKETOOL_MODE_REVERTPROCESSEDIMFILE,   revertprocessedimfileMode);
+        MODECASE(FAKETOOL_MODE_UPDATEPROCESSEDIMFILE,   updateprocessedimfileMode);
+        MODECASE(FAKETOOL_MODE_BLOCK,                   blockMode);
+        MODECASE(FAKETOOL_MODE_MASKED,                  maskedMode);
+        MODECASE(FAKETOOL_MODE_UNMASKED,                unmaskedMode);
+        MODECASE(FAKETOOL_MODE_UNBLOCK,                 unblockMode);
+        MODECASE(FAKETOOL_MODE_PENDINGCLEANUPRUN,       pendingcleanuprunMode);
+        MODECASE(FAKETOOL_MODE_PENDINGCLEANUPIMFILE,    pendingcleanupimfileMode);
+        MODECASE(FAKETOOL_MODE_DONECLEANUP,             donecleanupMode);
+        default:
+            psAbort("invalid option (this should not happen)");
+    }
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(EXIT_SUCCESS);
+
+FAIL:
+    psErrorStackPrint(stderr, "\n");
+    int exit_status = pxerrorGetExitStatus();
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exit_status);
+}
+
+
+static bool definebyqueryMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_name", "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where, "-inst", "camera", "==");
+    PXOPT_COPY_STR(config->args, where, "-telescope", "telescope", "==");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_begin", "dateobs", ">=");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_end", "dateobs", "<=");
+    PXOPT_COPY_STR(config->args, where, "-exp_tag", "exp_tag", "==");
+    PXOPT_COPY_STR(config->args, where, "-filelevel", "filelevel", "==");
+    PXOPT_COPY_STR(config->args, where, "-reduction", "reduction", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter", "filter", "==");
+    PXOPT_COPY_F64(config->args, where, "-airmass_min", "airmass", ">=");
+    PXOPT_COPY_F64(config->args, where, "-airmass_max", "airmass", "<");
+    PXOPT_COPY_F64(config->args, where, "-ra_min", "ra", ">=");
+    PXOPT_COPY_F64(config->args, where, "-ra_max", "ra", "<");
+    PXOPT_COPY_F64(config->args, where, "-decl_min", "decl", ">=");
+    PXOPT_COPY_F64(config->args, where, "-decl_max", "decl", "<");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_min", "exp_time", ">=");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_max", "exp_time", "<");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_min", "sat_pixel_frac", ">=");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_max", "sat_pixel_frac", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_min", "bt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_max", "bt", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_min", "bg_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_max", "bg_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_min", "bg_mean_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_max", "bg_mean_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-alt_min", "alt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-alt_max", "alt", "<");
+    PXOPT_COPY_F64(config->args, where, "-az_min", "az", ">=");
+    PXOPT_COPY_F64(config->args, where, "-az_max", "az", "<");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp_min", "ccd_temp", ">=");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp_max", "ccd_temp", "<");
+    PXOPT_COPY_F64(config->args, where, "-posang_min", "posang", ">=");
+    PXOPT_COPY_F64(config->args, where, "-posang_max", "posang", "<");
+    PXOPT_COPY_STR(config->args, where, "-object", "object", "==");
+    PXOPT_COPY_F32(config->args, where, "-solang_min", "solang", ">=");
+    PXOPT_COPY_F32(config->args, where, "-solang_max", "solang", "<");
+
+    if (!psListLength(where->list)
+        && !psMetadataLookupBool(NULL, config->args, "-all")) {
+        psFree(where);
+        psError(PXTOOLS_ERR_DATA, false, "search parameters are required");
+        return false;
+    }
+
+    PXOPT_LOOKUP_STR(workdir, config->args, "-set_workdir", false, false);
+    PXOPT_LOOKUP_STR(label, config->args, "-set_label", false, false);
+    PXOPT_LOOKUP_STR(reduction, config->args, "-set_reduction", false, false);
+    PXOPT_LOOKUP_STR(expgroup, config->args, "-set_expgroup", false, false);
+    PXOPT_LOOKUP_STR(dvodb, config->args, "-set_dvodb", false, false);
+    PXOPT_LOOKUP_STR(tess_id, config->args, "-set_tess_id", false, false);
+    PXOPT_LOOKUP_STR(end_stage, config->args, "-set_end_stage", false, false);
+
+    // default
+    PXOPT_COPY_STR(config->args, where, "-exp_type", "exp_type", "==");
+    PXOPT_LOOKUP_BOOL(pretend, config->args, "-pretend", false);
+
+    // find the exp_id of all the exposures that we want to queue up.
+    psString query = pxDataGet("faketool_find_camrun.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psFree(where);
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+
+    psFree(where);
+
+    if (pretend) {
+        // then stop before running the query
+        fprintf(stderr, "%s\n", query);
+        psFree(query);
+        return true;
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("faketool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // start a transaction so we don't end up with an exp without any associted
+    // imfiles
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(output);
+        return false;
+    }
+
+    // loop over our list of cam_ids
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *md = output->data[i];
+
+        bool status;
+        psS64 cam_id = psMetadataLookupS64(&status, md, "cam_id");
+        if (!status) {
+            psError(PS_ERR_UNKNOWN, false, "failed to lookup value for cam_id");
+            psFree(output);
+            return false;
+        }
+
+        // queue the exp
+        if (!pxfakeQueueByCamID(config, cam_id, workdir, label, reduction, expgroup, dvodb, tess_id, end_stage)) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false,
+                    "failed to trying to queue cam_id: %" PRId64, cam_id);
+            psFree(output);
+            return false;
+        }
+    }
+    psFree(output);
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool updaterunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-fake_id", "fake_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_name", "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where, "-inst", "camera", "==");
+    PXOPT_COPY_STR(config->args, where, "-telescope", "telescope", "==");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_begin", "dateobs", ">=");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_end", "dateobs", "<=");
+    PXOPT_COPY_STR(config->args, where, "-exp_tag", "exp_tag", "==");
+    PXOPT_COPY_STR(config->args, where, "-filelevel", "filelevel", "==");
+    PXOPT_COPY_STR(config->args, where, "-reduction", "reduction", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter", "filter", "==");
+    PXOPT_COPY_F64(config->args, where, "-airmass_min", "airmass", ">=");
+    PXOPT_COPY_F64(config->args, where, "-airmass_max", "airmass", "<");
+    PXOPT_COPY_F64(config->args, where, "-ra_min", "ra", ">=");
+    PXOPT_COPY_F64(config->args, where, "-ra_max", "ra", "<");
+    PXOPT_COPY_F64(config->args, where, "-decl_min", "decl", ">=");
+    PXOPT_COPY_F64(config->args, where, "-decl_max", "decl", "<");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_min", "exp_time", ">=");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_max", "exp_time", "<");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_min", "sat_pixel_frac", ">=");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_max", "sat_pixel_frac", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_min", "bt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_max", "bt", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_min", "bg_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_max", "bg_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_min", "bg_mean_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_max", "bg_mean_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-alt_min", "alt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-alt_max", "alt", "<");
+    PXOPT_COPY_F64(config->args, where, "-az_min", "az", ">=");
+    PXOPT_COPY_F64(config->args, where, "-az_max", "az", "<");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp_min", "ccd_temp", ">=");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp_max", "ccd_temp", "<");
+    PXOPT_COPY_F64(config->args, where, "-posang_min", "posang", ">=");
+    PXOPT_COPY_F64(config->args, where, "-posang_max", "posang", "<");
+    PXOPT_COPY_STR(config->args, where, "-object", "object", "==");
+    PXOPT_COPY_F32(config->args, where, "-solang_min", "solang", ">=");
+    PXOPT_COPY_F32(config->args, where, "-solang_max", "solang", "<");
+
+    if (!psListLength(where->list)
+        && !psMetadataLookupBool(NULL, config->args, "-all")) {
+        psFree(where);
+        where = NULL;
+        psError(PXTOOLS_ERR_DATA, false, "search parameters are required");
+        return false;
+    }
+
+    PXOPT_LOOKUP_STR(state, config->args, "-state", false, false);
+    PXOPT_LOOKUP_STR(label, config->args, "-label", false, false);
+
+    if ((!state) && (!label)) {
+        psError(PXTOOLS_ERR_DATA, false, "parameters are required");
+        psFree(where);
+        return false;
+    }
+
+    if (state) {
+        // set fakeRun.state to state
+        if (!pxfakeRunSetStateByQuery(config, where, state)) {
+            psFree(where);
+            return false;
+        }
+    }
+
+    if (label) {
+        // set fakeRun.label to label
+        if (!pxfakeRunSetLabelByQuery(config, where, label)) {
+            psFree(where);
+            return false;
+        }
+    }
+
+    psFree(where);
+
+    return true;
+}
+
+
+static bool pendingexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-fake_id", "fake_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-cam_id", "cam_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-chip_id", "chip_id", "==");
+
+    psString query = pxDataGet("faketool_find_pendingexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psFree(where);
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("camtool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negate simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "fakePendingExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool pendingimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-fake_id", "fake_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "rawImfile.class_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-inst", "rawExp.telescope", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter", "rawExp.filter", "==");
+
+    psString query = pxDataGet("faketool_pendingimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("faketool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "fakePendingImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool addprocessedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // fake_id, ext_tag, class_id are required
+    PXOPT_LOOKUP_S64(fake_id, config->args,     "-fake_id", true, false);
+    PXOPT_LOOKUP_S64(exp_id, config->args,      "-exp_id", true, false);
+    PXOPT_LOOKUP_STR(class_id, config->args,    "-class_id", true, false);
+
+    // optional
+    PXOPT_LOOKUP_STR(uri, config->args,         "-uri", false, false);
+
+    PXOPT_LOOKUP_F32(dtime_fake, config->args,  "-dtime_fake", false, false);
+    PXOPT_LOOKUP_STR(hostname, config->args,    "-hostname", false, false);
+    PXOPT_LOOKUP_STR(path_base, config->args,   "-path_base", false, false);
+
+    // default values
+    PXOPT_LOOKUP_S16(code, config->args,        "-code", false, false);
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!fakeProcessedImfileInsert(config->dbh,
+                                   fake_id,
+                                   exp_id,
+                                   class_id,
+                                   uri,
+                                   dtime_fake,
+                                   hostname,
+                                   path_base,
+                                   code,
+                                   NULL         // epoch
+            )) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // XXX I've decided to make the transaction cover the Exp migration as
+    // well.  Otherwise, if the last imfile in an exp is moved and the exp
+    // migration fails then the data base is left in a satuation where the exp
+    // migration can't happen.
+
+    if (!fakeProcessedCompleteExp(config)) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool processedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-fake_id", "fakeRun.fake_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "rawExp.exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "rawImfile.class_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-inst", "rawExp.telescope", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter", "rawExp.filter", "==");
+
+    psString query = pxDataGet("faketool_processedimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "fakeProcessedImfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", "AND fakeProcessedImfile.fault != 0");
+    } else {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", "AND fakeProcessedImfile.fault = 0");
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("faketool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "fakeProcessedImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool revertprocessedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-fake_id", "fake_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_name", "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where, "-inst", "camera", "==");
+    PXOPT_COPY_STR(config->args, where, "-telescope", "telescope", "==");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_begin", "dateobs", ">=");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_end", "dateobs", "<=");
+    PXOPT_COPY_STR(config->args, where, "-exp_tag", "exp_tag", "==");
+    PXOPT_COPY_STR(config->args, where, "-filelevel", "filelevel", "==");
+    PXOPT_COPY_STR(config->args, where, "-reduction", "reduction", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter", "filter", "==");
+    PXOPT_COPY_F64(config->args, where, "-airmass_min", "airmass", ">=");
+    PXOPT_COPY_F64(config->args, where, "-airmass_max", "airmass", "<");
+    PXOPT_COPY_F64(config->args, where, "-ra_min", "ra", ">=");
+    PXOPT_COPY_F64(config->args, where, "-ra_max", "ra", "<");
+    PXOPT_COPY_F64(config->args, where, "-decl_min", "decl", ">=");
+    PXOPT_COPY_F64(config->args, where, "-decl_max", "decl", "<");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_min", "exp_time", ">=");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_max", "exp_time", "<");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_min", "sat_pixel_frac", ">=");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_max", "sat_pixel_frac", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_min", "bt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_max", "bt", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_min", "bg_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_max", "bg_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_min", "bg_mean_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_max", "bg_mean_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-alt_min", "alt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-alt_max", "alt", "<");
+    PXOPT_COPY_F64(config->args, where, "-az_min", "az", ">=");
+    PXOPT_COPY_F64(config->args, where, "-az_max", "az", "<");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp_min", "ccd_temp", ">=");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp_max", "ccd_temp", "<");
+    PXOPT_COPY_F64(config->args, where, "-posang_min", "posang", ">=");
+    PXOPT_COPY_F64(config->args, where, "-posang_max", "posang", "<");
+    PXOPT_COPY_STR(config->args, where, "-object", "object", "==");
+    PXOPT_COPY_F32(config->args, where, "-solang_min", "solang", ">=");
+    PXOPT_COPY_F32(config->args, where, "-solang_max", "solang", "<");
+
+    if (!psListLength(where->list)
+        && !psMetadataLookupBool(NULL, config->args, "-all")) {
+        psFree(where);
+        psError(PXTOOLS_ERR_DATA, false, "search parameters are required");
+        return false;
+    }
+
+    psString query = pxDataGet("faketool_revertprocessedimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psFree(where);
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "fakeProcessedImfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    return true;
+}
+
+static bool updateprocessedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_S16(code, config->args, "-code", true, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-fake_id", "fake_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
+
+    if (!pxSetFaultCode(config->dbh, "fakeProcessedImfile", where, code)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to set set fault flag");
+        psFree(where);
+        return false;
+    }
+    psFree(where);
+
+    return true;
+}
+
+
+static bool blockMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(label, config->args, "-label", true, false);
+
+    if (!fakeMaskInsert(config->dbh, label)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool maskedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+
+    psMetadata *where = psMetadataAlloc();
+
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    if (where->list->n < 1) {
+        psFree(where);
+        where = NULL;
+    }
+
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = psStringCopy("SELECT * FROM fakeMask");
+
+    if (where) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psFree(where);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("faketool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "fakeMask", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+// return the list of labels which are NOT blocked
+static bool unmaskedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+
+    psMetadata *where = psMetadataAlloc();
+
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    if (where->list->n < 1) {
+        psFree(where);
+        where = NULL;
+    }
+
+    psString query = pxDataGet("faketool_unmasked.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where) {
+        psString whereClause = psDBGenerateWhereSQL(where, "fakeUnmask");
+        psFree(where);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("faketool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "fakeUnmask", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool unblockMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(label, config->args, "-label", true, false);
+
+    char *query = "DELETE FROM fakeMask WHERE label = '%s'";
+
+    if (!p_psDBRunQuery(config->dbh, query, label)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+static bool pendingcleanuprunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("faketool_pendingcleanuprun.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("faketool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "fakePendingCleanupRun", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool pendingcleanupimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_S64(fake_id, config->args, "-fake_id", false, false);
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    if (fake_id) {
+        PXOPT_COPY_S64(config->args, where, "-fake_id", "fake_id", "==");
+    }
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("faketool_pendingcleanupimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("faketool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "fakePendingCleanupImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool donecleanupMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("faketool_donecleanup.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("faketool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "fakeDoneCleanup", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool fakeProcessedCompleteExp(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // look for completed fakePendingExp
+    // migrate them to fakeProccessedExp & camPendingExp
+    psString query = pxDataGet("faketool_completely_processed_exp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("faketool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *row = output->data[i];
+
+        fakeRunRow *fakeRun = fakeRunObjectFromMetadata(row);
+        // set fakeRun.state to 'full'
+        if (!pxfakeRunSetState(config, fakeRun->fake_id, "full")) {
+            psError(PS_ERR_UNKNOWN, false, "failed to change fakeRun.state for fake_id: %" PRId64, fakeRun->fake_id);
+            psFree(fakeRun);
+            psFree(output);
+            return false;
+        }
+
+        // should we stop here or proceed on to the cam stage?
+        // NULL for end_stage means go as far as possible
+        if (fakeRun->end_stage && psStrcasestr(fakeRun->end_stage, "fake")) {
+            psFree(fakeRun);
+            continue;
+        }
+        // else continue on...
+
+        // camQueueFakeID() can only be run after fakeRun.state has been set to
+        // stop
+        if (!pxwarpQueueByFakeID(config,
+                    fakeRun->fake_id,
+                    fakeRun->workdir,
+                    fakeRun->label,
+                    fakeRun->dvodb,
+                    fakeRun->tess_id,
+                    fakeRun->end_stage
+        )) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "failed to queue camPendingExp");
+            psFree(fakeRun);
+            psFree(output);
+            return false;
+        }
+        psFree(fakeRun);
+    }
+
+    psFree(output);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/faketool.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/faketool.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/faketool.h	(revision 22158)
@@ -0,0 +1,47 @@
+/*
+ * faketool.h
+ *
+ * Copyright (C) 2006-2008  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef FAKETOOL_H
+#define FAKETOOL_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+    FAKETOOL_MODE_NONE      = 0x0,
+    FAKETOOL_MODE_DEFINEBYQUERY,
+    FAKETOOL_MODE_UPDATERUN,
+    FAKETOOL_MODE_PENDINGIMFILE,
+    FAKETOOL_MODE_PENDINGEXP,
+    FAKETOOL_MODE_ADDPROCESSEDIMFILE,
+    FAKETOOL_MODE_PROCESSEDIMFILE,
+    FAKETOOL_MODE_REVERTPROCESSEDIMFILE,
+    FAKETOOL_MODE_UPDATEPROCESSEDIMFILE,
+    FAKETOOL_MODE_BLOCK,
+    FAKETOOL_MODE_MASKED,
+    FAKETOOL_MODE_UNMASKED,
+    FAKETOOL_MODE_UNBLOCK,
+    FAKETOOL_MODE_RETRYPROCESSEDIMFILE,
+    FAKETOOL_MODE_PENDINGCLEANUPRUN,
+    FAKETOOL_MODE_PENDINGCLEANUPIMFILE,
+    FAKETOOL_MODE_DONECLEANUP,
+} FAKETOOLMode;
+
+pxConfig *faketoolConfig(pxConfig *config, int argc, char **argv);
+
+#endif // FAKETOOL_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/faketoolConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/faketoolConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/faketoolConfig.c	(revision 22158)
@@ -0,0 +1,314 @@
+/*
+ * faketoolConfig.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+
+#include <psmodules.h>
+
+#include "pxtools.h"
+#include "faketool.h"
+
+pxConfig *faketoolConfig(pxConfig *config, int argc, char **argv)
+{
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    pmConfigReadParamsSet(false);
+
+    config->modules = pmConfigRead(&argc, argv, NULL);
+    if (! config->modules) {
+        psError(PS_ERR_UNKNOWN, false, "Can't find site configuration");
+        psFree(config);
+        return NULL;
+    }
+
+    // -definebyquery
+    psMetadata *queueArgs = psMetadataAlloc();
+    // XXX need to allow multiple exp_ids
+    psMetadataAddS64(queueArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exp_id", 0);
+    psMetadataAddStr(queueArgs, PS_LIST_TAIL, "-exp_name",  0,            "search by exp_name", NULL);
+    psMetadataAddStr(queueArgs, PS_LIST_TAIL, "-inst",  0,            "search for camera", NULL);
+    psMetadataAddStr(queueArgs, PS_LIST_TAIL, "-telescope",  0,            "search for telescope", NULL);
+    psMetadataAddTime(queueArgs, PS_LIST_TAIL, "-dateobs_begin", 0,            "search for exposures by time (>=)", NULL);
+    psMetadataAddTime(queueArgs, PS_LIST_TAIL, "-dateobs_end", 0,            "search for exposures by time (<)", NULL);
+    psMetadataAddStr(queueArgs, PS_LIST_TAIL, "-exp_tag",  0,            "search by exp_tag", NULL);
+    psMetadataAddStr(queueArgs, PS_LIST_TAIL, "-exp_type",  0,            "search by exp_type", "object");
+    psMetadataAddStr(queueArgs, PS_LIST_TAIL, "-filelevel",  0,            "search by filelevel", NULL);
+    psMetadataAddStr(queueArgs, PS_LIST_TAIL, "-reduction",  0,            "search by reduction class", NULL);
+    psMetadataAddStr(queueArgs, PS_LIST_TAIL, "-filter",  0,            "search for filter", NULL);
+    psMetadataAddF32(queueArgs, PS_LIST_TAIL, "-airmass_min",  0,            "define min airmass", NAN);
+    psMetadataAddF32(queueArgs, PS_LIST_TAIL, "-airmass_max",  0,            "define max airmass", NAN);
+    psMetadataAddF64(queueArgs, PS_LIST_TAIL, "-ra_min",  0,            "define min", NAN);
+    psMetadataAddF64(queueArgs, PS_LIST_TAIL, "-ra_max",  0,            "define max", NAN);
+    psMetadataAddF64(queueArgs, PS_LIST_TAIL, "-decl_min",  0,            "define min", NAN);
+    psMetadataAddF64(queueArgs, PS_LIST_TAIL, "-decl_max",  0,            "define max", NAN);
+    psMetadataAddF32(queueArgs, PS_LIST_TAIL, "-exp_time_min",  0,            "define min", NAN);
+    psMetadataAddF32(queueArgs, PS_LIST_TAIL, "-exp_time_max",  0,            "define max", NAN);
+    psMetadataAddF32(queueArgs, PS_LIST_TAIL, "-sat_pixel_frac_min",  0,            "define max fraction of saturated pixels", NAN);
+    psMetadataAddF32(queueArgs, PS_LIST_TAIL, "-sat_pixel_frac_max",  0,            "define min fraction of saturated pixels", NAN);
+    psMetadataAddF64(queueArgs, PS_LIST_TAIL, "-bg_min",  0,            "define max", NAN);
+    psMetadataAddF64(queueArgs, PS_LIST_TAIL, "-bg_max",  0,            "define max", NAN);
+    psMetadataAddF64(queueArgs, PS_LIST_TAIL, "-bg_stdev_min",  0,            "define max", NAN);
+    psMetadataAddF64(queueArgs, PS_LIST_TAIL, "-bg_stdev_max",  0,            "define max", NAN);
+    psMetadataAddF64(queueArgs, PS_LIST_TAIL, "-bg_mean_stdev_min",  0,            "define max", NAN);
+    psMetadataAddF64(queueArgs, PS_LIST_TAIL, "-bg_mean_stdev_max",  0,            "define max", NAN);
+    psMetadataAddF64(queueArgs, PS_LIST_TAIL, "-alt_min",  0,            "define min", NAN);
+    psMetadataAddF64(queueArgs, PS_LIST_TAIL, "-alt_max",  0,            "define max", NAN);
+    psMetadataAddF64(queueArgs, PS_LIST_TAIL, "-az_min",  0,            "define min", NAN);
+    psMetadataAddF64(queueArgs, PS_LIST_TAIL, "-az_max",  0,            "define max", NAN);
+    psMetadataAddF64(queueArgs, PS_LIST_TAIL, "-ccd_temp_min",  0,            "define min ccd tempature", NAN);
+    psMetadataAddF64(queueArgs, PS_LIST_TAIL, "-ccd_temp_max",  0,            "define max ccd tempature", NAN);
+    psMetadataAddF64(queueArgs, PS_LIST_TAIL, "-posang_min",  0,            "define min rotator position angle", NAN);
+    psMetadataAddF64(queueArgs, PS_LIST_TAIL, "-posang_max",  0,            "define max rotator position angle", NAN);
+    psMetadataAddStr(queueArgs, PS_LIST_TAIL, "-object",  0,            "search by exposure object", NULL);
+    psMetadataAddF32(queueArgs, PS_LIST_TAIL, "-solang_min",  0,            "define min solar angle", NAN);
+    psMetadataAddF32(queueArgs, PS_LIST_TAIL, "-solang_max",  0,            "define max solar angle", NAN);
+    psMetadataAddStr(queueArgs, PS_LIST_TAIL, "-set_workdir",  0,            "define workdir", NULL);
+    psMetadataAddStr(queueArgs, PS_LIST_TAIL, "-set_label",  0,            "define label", NULL);
+    psMetadataAddStr(queueArgs, PS_LIST_TAIL, "-set_reduction",  0,            "define reduction class", NULL);
+    psMetadataAddStr(queueArgs, PS_LIST_TAIL, "-set_expgroup",  0,            "define exposure group", NULL);
+    psMetadataAddStr(queueArgs, PS_LIST_TAIL, "-set_dvodb",  0,            "define DVO db", NULL);
+    psMetadataAddStr(queueArgs, PS_LIST_TAIL, "-set_tess_id",  0,            "define tessellation identifier", NULL);
+    psMetadataAddStr(queueArgs, PS_LIST_TAIL, "-set_end_stage",  0,            "define end stage", NULL);
+    psMetadataAddBool(queueArgs, PS_LIST_TAIL, "-pretend",  0,            "do not actually modify the database", false);
+    psMetadataAddBool(queueArgs, PS_LIST_TAIL, "-all",  0,            "allow everything to be queued without search terms", false);
+
+
+    // -updaterun
+    psMetadata *updaterunArgs = psMetadataAlloc();
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-fake_id", 0,            "search by fake ID", 0);
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exp_id", 0);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-exp_name",  0,            "search by exp_name", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-inst",  0,            "search for camera", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-telescope",  0,            "search for telescope", NULL);
+    psMetadataAddTime(updaterunArgs, PS_LIST_TAIL, "-dateobs_begin", 0,            "search for exposures by time (>=)", NULL);
+    psMetadataAddTime(updaterunArgs, PS_LIST_TAIL, "-dateobs_end", 0,            "search for exposures by time (<)", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-exp_tag",  0,            "search by exp_tag", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-exp_type",  0,            "search by exp_type", "object");
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-filelevel",  0,            "search by filelevel", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-reduction",  0,            "search by reduction class", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-filter",  0,            "search for filter", NULL);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-airmass_min",  0,            "define min airmass", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-airmass_max",  0,            "define max airmass", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-ra_min",  0,            "define min", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-ra_max",  0,            "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-decl_min",  0,            "define min", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-decl_max",  0,            "define max", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-exp_time_min",  0,            "define min", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-exp_time_max",  0,            "define max", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-sat_pixel_frac_min",  0,            "define max fraction of saturated pixels", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-sat_pixel_frac_max",  0,            "define min fraction of saturated pixels", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_min",  0,            "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_max",  0,            "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_stdev_min",  0,            "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_stdev_max",  0,            "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_mean_stdev_min",  0,            "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_mean_stdev_max",  0,            "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-alt_min",  0,            "define min", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-alt_max",  0,            "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-az_min",  0,            "define min", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-az_max",  0,            "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-ccd_temp_min",  0,            "define min ccd tempature", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-ccd_temp_max",  0,            "define max ccd tempature", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-posang_min",  0,            "define min rotator position angle", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-posang_max",  0,            "define max rotator position angle", NAN);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-object",  0,            "search by exposure object", NULL);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-solang_min",  0,            "define min solar angle", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-solang_max",  0,            "define max solar angle", NAN);
+
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-state", 0,            "set state", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-label", 0,            "set label", NULL);
+    psMetadataAddBool(updaterunArgs, PS_LIST_TAIL, "-all",  0,            "allow everything to be queued without search terms", false);
+
+    // -pendingexp
+    psMetadata *pendingexpArgs = psMetadataAlloc();
+    psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-fake_id", 0,            "search by fake ID", 0);
+    psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-cam_id", 0,            "search by camtool ID", 0);
+    psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-chip_id", 0,            "search by chiptool ID", 0);
+    psMetadataAddU64(pendingexpArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(pendingexpArgs, PS_LIST_TAIL, "-simple", 0,            "use the simple output format", false);
+
+    // -pendingimfile
+    psMetadata *pendingimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(pendingimfileArgs, PS_LIST_TAIL, "-fake_id",  0,            "search by fake ID", 0);
+    psMetadataAddS64(pendingimfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exposure ID", 0);
+    psMetadataAddStr(pendingimfileArgs, PS_LIST_TAIL, "-class_id",  0,            "search by class ID", NULL);
+    psMetadataAddStr(pendingimfileArgs, PS_LIST_TAIL, "-inst",  0,            "search by camera of interest", NULL);
+    psMetadataAddStr(pendingimfileArgs, PS_LIST_TAIL, "-filter",  0,            "search by filter of interest", NULL);
+    psMetadataAddU64(pendingimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(pendingimfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -addprocessedimfile
+    psMetadata *addprocessedimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(addprocessedimfileArgs, PS_LIST_TAIL, "-fake_id",  0,            "define fake ID (required)", 0);
+    psMetadataAddS64(addprocessedimfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "define exposure ID (required)", 0);
+    psMetadataAddStr(addprocessedimfileArgs, PS_LIST_TAIL, "-class_id",  0,            "define class ID (required)", NULL);
+    psMetadataAddStr(addprocessedimfileArgs, PS_LIST_TAIL, "-uri",  0,            "define URL", NULL);
+    psMetadataAddF32(addprocessedimfileArgs, PS_LIST_TAIL, "-dtime_fake",  0,            "define elapsed time for detrend (seconds)", NAN);
+    psMetadataAddStr(addprocessedimfileArgs, PS_LIST_TAIL, "-hostname",  0,            "define hostname", NULL);
+    psMetadataAddStr(addprocessedimfileArgs, PS_LIST_TAIL, "-path_base",  0,            "define base output location", NULL);
+    psMetadataAddS16(addprocessedimfileArgs, PS_LIST_TAIL, "-code",  0,            "set fault code", 0);
+
+    // -processedimfile
+    psMetadata *processedimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(processedimfileArgs, PS_LIST_TAIL, "-fake_id",  0,            "define fake ID", 0);
+    psMetadataAddS64(processedimfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "define exposure ID", 0);
+    psMetadataAddStr(processedimfileArgs, PS_LIST_TAIL, "-class_id",  0,            "define class ID", NULL);
+    psMetadataAddStr(processedimfileArgs, PS_LIST_TAIL, "-inst",  0,            "define camera of interest", NULL);
+    psMetadataAddStr(processedimfileArgs, PS_LIST_TAIL, "-filter",  0,            "define filter of interest", NULL);
+    psMetadataAddU64(processedimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(processedimfileArgs, PS_LIST_TAIL, "-faulted",  0,            "only return imfiles with a fault status set", false);
+    psMetadataAddBool(processedimfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -updateprocessedimfile
+    psMetadata *updateprocessedimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(updateprocessedimfileArgs, PS_LIST_TAIL, "-fake_id",  0,            "search by fake ID", 0);
+    psMetadataAddS64(updateprocessedimfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exposure ID", 0);
+    psMetadataAddStr(updateprocessedimfileArgs, PS_LIST_TAIL, "-class_id",  0,            "search by class ID", NULL);
+    psMetadataAddS16(updateprocessedimfileArgs, PS_LIST_TAIL, "-code",  0,            "set fault code (required)", 0);
+
+    // -revertprocessedimfile
+    psMetadata *revertprocessedimfileArgs = psMetadataAlloc();
+    psMetadataAddS64(revertprocessedimfileArgs, PS_LIST_TAIL, "-fake_id", 0,            "search by fake ID", 0);
+    psMetadataAddS64(revertprocessedimfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exp_id", 0);
+    psMetadataAddStr(revertprocessedimfileArgs, PS_LIST_TAIL, "-exp_name",  0,            "search by exp_name", NULL);
+    psMetadataAddStr(revertprocessedimfileArgs, PS_LIST_TAIL, "-inst",  0,            "search for camera", NULL);
+    psMetadataAddStr(revertprocessedimfileArgs, PS_LIST_TAIL, "-telescope",  0,            "search for telescope", NULL);
+    psMetadataAddTime(revertprocessedimfileArgs, PS_LIST_TAIL, "-dateobs_begin", 0,            "search for exposures by time (>=)", NULL);
+    psMetadataAddTime(revertprocessedimfileArgs, PS_LIST_TAIL, "-dateobs_end", 0,            "search for exposures by time (<)", NULL);
+    psMetadataAddStr(revertprocessedimfileArgs, PS_LIST_TAIL, "-exp_tag",  0,            "search by exp_tag", NULL);
+    psMetadataAddStr(revertprocessedimfileArgs, PS_LIST_TAIL, "-exp_type",  0,            "search by exp_type", "object");
+    psMetadataAddStr(revertprocessedimfileArgs, PS_LIST_TAIL, "-filelevel",  0,            "search by filelevel", NULL);
+    psMetadataAddStr(revertprocessedimfileArgs, PS_LIST_TAIL, "-reduction",  0,            "search by reduction class", NULL);
+    psMetadataAddStr(revertprocessedimfileArgs, PS_LIST_TAIL, "-filter",  0,            "search for filter", NULL);
+    psMetadataAddF32(revertprocessedimfileArgs, PS_LIST_TAIL, "-airmass_min",  0,            "define min airmass", NAN);
+    psMetadataAddF32(revertprocessedimfileArgs, PS_LIST_TAIL, "-airmass_max",  0,            "define max airmass", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-ra_min",  0,            "define min", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-ra_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-decl_min",  0,            "define min", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-decl_max",  0,            "define max", NAN);
+    psMetadataAddF32(revertprocessedimfileArgs, PS_LIST_TAIL, "-exp_time_min",  0,            "define min", NAN);
+    psMetadataAddF32(revertprocessedimfileArgs, PS_LIST_TAIL, "-exp_time_max",  0,            "define max", NAN);
+    psMetadataAddF32(revertprocessedimfileArgs, PS_LIST_TAIL, "-sat_pixel_frac_min",  0,            "define max fraction of saturated pixels", NAN);
+    psMetadataAddF32(revertprocessedimfileArgs, PS_LIST_TAIL, "-sat_pixel_frac_max",  0,            "define min fraction of saturated pixels", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-bg_min",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-bg_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-bg_stdev_min",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-bg_stdev_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-bg_mean_stdev_min",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-bg_mean_stdev_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-alt_min",  0,            "define min", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-alt_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-az_min",  0,            "define min", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-az_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-ccd_temp_min",0,            "define min ccd tempature", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-ccd_temp_max",0,            "define max ccd tempature", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-posang_min",  0,            "define min rotator position angle", NAN);
+    psMetadataAddF64(revertprocessedimfileArgs, PS_LIST_TAIL, "-posang_max",  0,            "define max rotator position angle", NAN);
+    psMetadataAddStr(revertprocessedimfileArgs, PS_LIST_TAIL, "-object",  0,            "search by exposure object", NULL);
+    psMetadataAddF32(revertprocessedimfileArgs, PS_LIST_TAIL, "-solang_min",  0,            "define min solar angle", NAN);
+    psMetadataAddF32(revertprocessedimfileArgs, PS_LIST_TAIL, "-solang_max",  0,            "define max solar angle", NAN);
+
+    psMetadataAddBool(revertprocessedimfileArgs, PS_LIST_TAIL, "-all",  0,            "allow everything to be queued without search terms", false);
+    psMetadataAddS16(revertprocessedimfileArgs, PS_LIST_TAIL, "-code",  0,            "search by fault code", 0);
+
+    // -block
+    psMetadata *blockArgs = psMetadataAlloc();
+    psMetadataAddStr(blockArgs, PS_LIST_TAIL, "-label",  0,            "name of a label to mask out (required)", NULL);
+
+    // -masked
+    psMetadata *maskedArgs = psMetadataAlloc();
+    psMetadataAddStr(maskedArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddBool(maskedArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(maskedArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -unmasked
+    psMetadata *unmaskedArgs = psMetadataAlloc();
+    psMetadataAddStr(unmaskedArgs, PS_LIST_TAIL, "-label",  0,            "restrict to specified label", NULL);
+    psMetadataAddBool(unmaskedArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(unmaskedArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -unblock
+    psMetadata *unblockArgs = psMetadataAlloc();
+    psMetadataAddStr(unblockArgs, PS_LIST_TAIL, "-label",  0,            "name of a label to unmask (required)", NULL);
+
+    // -pendingcleanuprun
+    psMetadata *pendingcleanuprunArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingcleanuprunArgs,  PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddBool(pendingcleanuprunArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanuprunArgs,  PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -pendingcleanupimfile
+    psMetadata *pendingcleanupimfileArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingcleanupimfileArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddS64(pendingcleanupimfileArgs, PS_LIST_TAIL, "-fake_id", 0,          "search by chip ID", 0);
+    psMetadataAddBool(pendingcleanupimfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanupimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -donecleanup
+    psMetadata *donecleanupArgs = psMetadataAlloc();
+    psMetadataAddStr(donecleanupArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddBool(donecleanupArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(donecleanupArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    psMetadata *argSets = psMetadataAlloc();
+    psMetadata *modes = psMetadataAlloc();
+
+    PXOPT_ADD_MODE("-definebyquery",         "create runs from raw exposures",       FAKETOOL_MODE_DEFINEBYQUERY,                    queueArgs);
+    PXOPT_ADD_MODE("-updaterun",             "change fake run properties",           FAKETOOL_MODE_UPDATERUN,                updaterunArgs);
+    PXOPT_ADD_MODE("-pendingexp",            "show pending exposures",               FAKETOOL_MODE_PENDINGEXP,               pendingexpArgs);
+    PXOPT_ADD_MODE("-pendingimfile",         "show pending imfiles",                 FAKETOOL_MODE_PENDINGIMFILE,            pendingimfileArgs);
+    PXOPT_ADD_MODE("-addprocessedimfile",    "add a processed imfile",               FAKETOOL_MODE_ADDPROCESSEDIMFILE,       addprocessedimfileArgs);
+    PXOPT_ADD_MODE("-processedimfile",       "show processed imfiles",               FAKETOOL_MODE_PROCESSEDIMFILE,          processedimfileArgs);
+    PXOPT_ADD_MODE("-updateprocessedimfile","change procesed imfile properties",     FAKETOOL_MODE_UPDATEPROCESSEDIMFILE,    updateprocessedimfileArgs);
+    PXOPT_ADD_MODE("-revertprocessedimfile", "undo a processed imfile",              FAKETOOL_MODE_REVERTPROCESSEDIMFILE,    revertprocessedimfileArgs);
+    PXOPT_ADD_MODE("-block",                 "set a label block",                    FAKETOOL_MODE_BLOCK,          blockArgs);
+    PXOPT_ADD_MODE("-masked",                "show blocked labels",                  FAKETOOL_MODE_MASKED,         maskedArgs);
+    PXOPT_ADD_MODE("-unmasked",              "",                                     FAKETOOL_MODE_UNMASKED,       unmaskedArgs);
+    PXOPT_ADD_MODE("-unblock",               "remove a label block",                 FAKETOOL_MODE_UNBLOCK,        unblockArgs);
+    PXOPT_ADD_MODE("-pendingcleanuprun",     "show runs that need to be cleaned up", FAKETOOL_MODE_PENDINGCLEANUPRUN,    pendingcleanuprunArgs);
+    PXOPT_ADD_MODE("-pendingcleanupimfile",  "show runs that need to be cleaned up", FAKETOOL_MODE_PENDINGCLEANUPIMFILE, pendingcleanupimfileArgs);
+    PXOPT_ADD_MODE("-donecleanup",           "show runs that have been cleaned",     FAKETOOL_MODE_DONECLEANUP,          donecleanupArgs);
+
+    if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
+        psError(PS_ERR_UNKNOWN, true, "option parsing failed");
+        psFree(argSets);
+        psFree(modes);
+        psFree(config);
+        return NULL;
+    }
+
+    psFree(argSets);
+    psFree(modes);
+
+    // define Database handle, if used
+    config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+    if (!config->dbh) {
+        psError(PS_ERR_UNKNOWN, false, "Can't configure database");
+        psFree(config);
+        return NULL;
+    }
+
+    return config;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/flatcorr.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/flatcorr.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/flatcorr.c	(revision 22158)
@@ -0,0 +1,556 @@
+/*
+ * flatcorr.c
+ *
+ * Copyright (C) 2006-2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVB_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include <ippdb.h>
+
+#include "pxtools.h"
+#include "flatcorr.h"
+
+static bool newrunMode(pxConfig *config);
+static bool addexpMode(pxConfig *config);
+static bool pendingMode(pxConfig *config);
+static bool flatcorrimfileMode(pxConfig *config);
+static bool doneMode(pxConfig *config);
+static bool updaterunMode(pxConfig *config);
+
+static bool setflatcorrRunState(pxConfig *config, psS64 corr_id, const char *state);
+
+# define MODECASE(caseName, func) \
+    case caseName: \
+    if (!func(config)) { \
+        goto FAIL; \
+    } \
+    break;
+
+int main(int argc, char **argv)
+{
+    psLibInit(NULL);
+
+    pxConfig *config = flatcorrConfig(NULL, argc, argv);
+    if (!config) {
+        psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+        goto FAIL;
+    }
+
+    switch (config->mode) {
+        MODECASE(FLATCORR_MODE_NEWRUN,      newrunMode);
+        MODECASE(FLATCORR_MODE_ADDEXP,      addexpMode);
+        MODECASE(FLATCORR_MODE_PENDING,     pendingMode);
+        MODECASE(FLATCORR_MODE_FLATCORRIMFILE, flatcorrimfileMode);
+        MODECASE(FLATCORR_MODE_DONE,        doneMode);
+        MODECASE(FLATCORR_MODE_UPDATERUN,   updaterunMode);
+        default:
+            psAbort("invalid option (this should not happen)");
+    }
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(EXIT_SUCCESS);
+
+FAIL:
+    psErrorStackPrint(stderr, "\n");
+    int exit_status = pxerrorGetExitStatus();
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exit_status);
+}
+
+
+static bool newrunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_name", "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where, "-inst", "camera", "==");
+    PXOPT_COPY_STR(config->args, where, "-telescope", "telescope", "==");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_begin", "dateobs", ">=");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_end", "dateobs", "<=");
+    PXOPT_COPY_STR(config->args, where, "-exp_tag", "exp_tag", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_type", "exp_type", "==");
+    PXOPT_COPY_STR(config->args, where, "-filelevel", "filelvel", "==");
+    PXOPT_COPY_STR(config->args, where, "-reduction", "reduction", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter", "filter", "==");
+    PXOPT_COPY_F32(config->args, where, "-airmass_min", "airmass", ">=");
+    PXOPT_COPY_F32(config->args, where, "-airmass_max", "airmass", "<");
+    PXOPT_COPY_F64(config->args, where, "-ra_min", "ra", ">=");
+    PXOPT_COPY_F64(config->args, where, "-ra_max", "ra", "<");
+    PXOPT_COPY_F64(config->args, where, "-decl_min", "decl", ">=");
+    PXOPT_COPY_F64(config->args, where, "-decl_max", "decl", "<");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_min", "exp_time", ">=");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_max", "exp_time", "<");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_min", "sat_pixel_frac", ">=");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_max", "sat_pixel_frac", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_min", "bt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_max", "bt", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_min", "bg_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_max", "bg_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_min", "bg_mean_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_max", "bg_mean_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-alt_min", "alt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-alt_max", "alt", "<");
+    PXOPT_COPY_F64(config->args, where, "-az_min", "az", ">=");
+    PXOPT_COPY_F64(config->args, where, "-az_max", "az", "<");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp_min", "ccd_temp", ">=");
+    PXOPT_COPY_F32(config->args, where, "-ccd_temp_max", "ccd_temp", "<");
+    PXOPT_COPY_F64(config->args, where, "-posang_min", "posang", ">=");
+    PXOPT_COPY_F64(config->args, where, "-posang_max", "posang", "<");
+    PXOPT_COPY_STR(config->args, where, "-object", "object", "==");
+    PXOPT_COPY_F32(config->args, where, "-solang_min", "solang", ">=");
+    PXOPT_COPY_F32(config->args, where, "-solang_max", "solang", "<");
+
+    if (where->list->n < 1) {
+        psFree(where);
+        psError(PXTOOLS_ERR_DATA, false, "search parameters are required");
+        return false;
+    }
+
+    PXOPT_LOOKUP_STR(workdir, config->args, "-set_workdir", false, false);
+    PXOPT_LOOKUP_STR(label, config->args, "-set_label", false, false);
+    PXOPT_LOOKUP_STR(reduction, config->args, "-set_reduction", false, false);
+    PXOPT_LOOKUP_STR(expgroup, config->args, "-set_expgroup", false, false);
+    PXOPT_LOOKUP_STR(dvodb, config->args, "-set_dvodb", false, false);
+    PXOPT_LOOKUP_STR(filter, config->args, "-set_filter", false, false);
+    PXOPT_LOOKUP_STR(tess_id, config->args, "-set_tess_id", false, false);
+    PXOPT_LOOKUP_STR(end_stage, config->args, "-set_end_stage", false, false);
+    PXOPT_LOOKUP_STR(region, config->args, "-set_region", false, false);
+
+    PXOPT_LOOKUP_BOOL(pretend, config->args, "-pretend", false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // find the exp_id of all the exposures that we want to queue up.
+    psString query = pxDataGet("chiptool_find_rawexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "rawExp");
+        psFree(where);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("chiptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (pretend) {
+        // negative simple so the default is true
+    for (int i = 0; i < output->n; i++) {
+        psMetadata *md = output->data[i];
+        psMetadataConfigPrint (stdout, md);
+    }
+//        if (!rawExpPrintObjects(stdout, output, !simple)) {
+//            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+//            psFree(output);
+//            return false;
+//        }
+        psFree(output);
+        return true;
+    }
+
+    // start a transaction so we don't end up with an exp without any associted
+    // imfiles
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(output);
+        return false;
+    }
+
+    // create a new flatcorrRun
+    if (!flatcorrRunInsert(config->dbh,
+            0,      // corr_id
+            dvodb,
+            filter,
+            "reg",  // state
+            workdir,
+            label,
+            NULL,   // stats
+            region
+        )) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // figure out the ID of the flatcorrRun we just created
+    psS64 corr_id = psDBLastInsertID(config->dbh);
+
+    // loop over our list of exp_ids
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *md = output->data[i];
+
+        bool status;
+        psS64 exp_id = psMetadataLookupS64(&status, md, "exp_id");
+        if (!status) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "failed to lookup value for exp_id");
+            psFree(output);
+            return false;
+        }
+
+        // queue the exp
+        psS64 chip_id = pxchipQueueByExpTag(config, exp_id, workdir, label, reduction, expgroup, dvodb, tess_id, end_stage);
+        if (!chip_id) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false,
+                    "failed to trying to queue exp_id: %" PRId64, exp_id);
+            psFree(output);
+            return false;
+        }
+
+        // add a flatcorrExp to the flatcorr Run we just created
+        if (!flatcorrExpInsert(config->dbh,
+                corr_id,
+                chip_id
+            )) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        }
+
+    }
+    psFree(output);
+
+    // set the flatcorrRun to a state of 'run'
+    if (!setflatcorrRunState(config, corr_id, "run")) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "failed to set run state");
+        return false;
+    }
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool addexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required
+    PXOPT_LOOKUP_STR(corr_id, config->args, "-corr_id", true, false);
+    PXOPT_LOOKUP_STR(chip_id, config->args, "-chip_id", true, false);
+
+    if (!flatcorrExpInsert(config->dbh,
+            (psS64)atoll(corr_id),
+            (psS64)atoll(chip_id)
+        )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool pendingMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_BOOL(limit, config->args, "-limit", false);
+
+    // create a temp table to hold completely processed chipRuns
+    {
+	psString query = pxDataGet("flatcorr_create_tmp_chiprundone.sql");
+	if (!query) {
+	    psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+	    return false;
+	}
+
+	if (!p_psDBRunQuery(config->dbh, query)) {
+	    psError(PS_ERR_UNKNOWN, false, "database error");
+	    psFree(query);
+	    return false;
+	}
+
+	psFree(query);
+    }
+   
+    // find all completed chipRuns
+    {
+	psString query = pxDataGet("flatcorr_completely_processed_chiprun.sql");
+	if (!query) {
+	    psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+	    return false;
+	}
+
+	if (!p_psDBRunQuery(config->dbh, query)) {
+	    psError(PS_ERR_UNKNOWN, false, "database error");
+	    psFree(query);
+	    return false;
+	}
+
+	psFree(query);
+    }
+
+    // find flatcorrRun's that have had all of their chipRun's completed by
+    // comparing against the temp table
+    psString query = pxDataGet("flatcorr_find_completed_floatcorruns.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+	psString limitString = psDBGenerateLimitSQL(limit);
+	psStringAppend(&query, " %s", limitString);
+	psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+	  case PS_ERR_DB_CLIENT:
+	    psError(PXTOOLS_ERR_SYS, false, "database error");
+	  case PS_ERR_DB_SERVER:
+	    psError(PXTOOLS_ERR_PROG, false, "database error");
+	  default:
+	    psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("regtool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "flatcorrPending", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return false;
+}
+
+
+static bool flatcorrimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-corr_id", "corr_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // find all rawImfiles matching the default query
+    psString query = pxDataGet("flatcorr_find_processedimfiles.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+    
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        } 
+    
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("warptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true; 
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "chipProcessedImfile", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool doneMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(corr_id, config->args, "-corr_id", true, false);
+    PXOPT_LOOKUP_STR(stats, config->args, "-stats", true, false);
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!setflatcorrRunState(config, (psS64)atoll(corr_id), "stop")) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "failed to set run state");
+        return false;
+    }
+
+    char *query = "UPDATE flatcorrRun SET stats = '%s' WHERE corr_id = %" PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, stats, (psS64)atoll(corr_id))) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for corr_id %" PRId64, (psS64)atoll(corr_id));
+        return false;
+    }
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return false;
+}
+
+
+static bool setflatcorrRunState(pxConfig *config, psS64 corr_id, const char *state)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(state, false);
+
+    // check that state is a valid string value
+    if (!(
+            (strncmp(state, "run", 4) == 0)
+            || (strncmp(state, "stop", 5) == 0)
+            || (strncmp(state, "reg", 4) == 0)
+        )
+    ) {
+        psError(PS_ERR_UNKNOWN, false, "invalid state: %s", state);
+        return false;
+    }
+
+    char *query = "UPDATE flatcorrRun SET state = '%s' WHERE corr_id = %" PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, state, corr_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for corr_id %" PRId64, corr_id);
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool updaterunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(corr_id, config->args, "-corr_id", true, false);
+    PXOPT_LOOKUP_STR(state, config->args, "-state", true, false);
+
+    if (state) {
+        // set detRun.state to state
+        return setflatcorrRunState(config, (psS64)atoll(corr_id), state);
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/flatcorr.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/flatcorr.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/flatcorr.h	(revision 22158)
@@ -0,0 +1,37 @@
+/*
+ * flatcorr.h
+ *
+ * Copyright (C) 2006-2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef FLATCORR_H
+#define FLATCORR_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+    FLATCORR_MODE_NONE           = PXTOOL_MODE_NONE,
+    FLATCORR_MODE_NEWRUN,
+    FLATCORR_MODE_ADDEXP,
+    FLATCORR_MODE_PENDING,
+    FLATCORR_MODE_FLATCORRIMFILE,
+    FLATCORR_MODE_DONE,
+    FLATCORR_MODE_UPDATERUN
+} flatcorrMode;
+
+pxConfig *flatcorrConfig(pxConfig *config, int argc, char **argv);
+
+#endif // FLATCORR_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/flatcorrConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/flatcorrConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/flatcorrConfig.c	(revision 22158)
@@ -0,0 +1,162 @@
+/*
+ * flatcorrConfig.c
+ *
+ * Copyright (C) 2006-2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <psmodules.h>
+
+#include "pxtools.h"
+#include "flatcorr.h"
+
+pxConfig *flatcorrConfig(pxConfig *config, int argc, char **argv)
+{
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    pmConfigReadParamsSet(false);
+
+    // setup site config
+    config->modules = pmConfigRead(&argc, argv, NULL);
+    if (!config->modules) {
+        psError(PS_ERR_UNKNOWN, false, "Can't find site configuration");
+        psFree(config);
+        return NULL;
+    }
+
+    psTime *now = psTimeGetNow(PS_TIME_TAI);
+
+    // -newrun
+    psMetadata *newrunArgs = psMetadataAlloc();
+    // XXX need to allow multiple exp_ids
+    psMetadataAddS64(newrunArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exp_id", 0);
+    psMetadataAddStr(newrunArgs, PS_LIST_TAIL, "-exp_name",  0,            "search by exp_name", NULL);
+    psMetadataAddStr(newrunArgs, PS_LIST_TAIL, "-inst",  0,            "search for camera", NULL); 
+    psMetadataAddStr(newrunArgs, PS_LIST_TAIL, "-telescope",  0,            "search for telescope", NULL);
+    psMetadataAddTime(newrunArgs, PS_LIST_TAIL, "-dateobs_begin", 0,               "search for exposures by time (>=)", NULL);
+    psMetadataAddTime(newrunArgs, PS_LIST_TAIL, "-dateobs_end", 0,            "search for exposures by time (<)", NULL);
+    psMetadataAddStr(newrunArgs, PS_LIST_TAIL, "-exp_tag",  0,            "search by exp_tag", NULL);
+    psMetadataAddStr(newrunArgs, PS_LIST_TAIL, "-exp_type",  0,            "search by exp_type", "object");
+    psMetadataAddStr(newrunArgs, PS_LIST_TAIL, "-filelevel",  0,            "search by filelevel", NULL);
+    psMetadataAddStr(newrunArgs, PS_LIST_TAIL, "-reduction",  0,            "search by reduction class", NULL);
+    psMetadataAddStr(newrunArgs, PS_LIST_TAIL, "-filter",  0,            "search for filter", NULL); 
+    psMetadataAddF32(newrunArgs, PS_LIST_TAIL, "-airmass_min",  0,            "define min airmass", NAN);
+    psMetadataAddF32(newrunArgs, PS_LIST_TAIL, "-airmass_max",  0,            "define max airmass", NAN); 
+    psMetadataAddF64(newrunArgs, PS_LIST_TAIL, "-ra_min",  0,            "define min", NAN);
+    psMetadataAddF64(newrunArgs, PS_LIST_TAIL, "-ra_max",  0,            "define max", NAN); 
+    psMetadataAddF64(newrunArgs, PS_LIST_TAIL, "-decl_min",  0,            "define min", NAN);
+    psMetadataAddF64(newrunArgs, PS_LIST_TAIL, "-decl_max",  0,            "define max", NAN); 
+    psMetadataAddF32(newrunArgs, PS_LIST_TAIL, "-exp_time_min",  0,            "define min", NAN);
+    psMetadataAddF32(newrunArgs, PS_LIST_TAIL, "-exp_time_max",  0,            "define max", NAN); 
+    psMetadataAddF32(newrunArgs, PS_LIST_TAIL, "-sat_pixel_frac_min",  0,            "define max fraction of saturated pixels", NAN);
+    psMetadataAddF32(newrunArgs, PS_LIST_TAIL, "-sat_pixel_frac_max",  0,            "define min fraction of saturated pixels", NAN);
+    psMetadataAddF64(newrunArgs, PS_LIST_TAIL, "-bg_min",  0,            "define max", NAN);
+    psMetadataAddF64(newrunArgs, PS_LIST_TAIL, "-bg_max",  0,            "define max", NAN);
+    psMetadataAddF64(newrunArgs, PS_LIST_TAIL, "-bg_stdev_min",  0,            "define max", NAN);
+    psMetadataAddF64(newrunArgs, PS_LIST_TAIL, "-bg_stdev_max",  0,            "define max", NAN);
+    psMetadataAddF64(newrunArgs, PS_LIST_TAIL, "-bg_mean_stdev_min",  0,            "define max", NAN);
+    psMetadataAddF64(newrunArgs, PS_LIST_TAIL, "-bg_mean_stdev_max",  0,            "define max", NAN);
+    psMetadataAddF64(newrunArgs, PS_LIST_TAIL, "-alt_min",  0,            "define min", NAN);
+    psMetadataAddF64(newrunArgs, PS_LIST_TAIL, "-alt_max",  0,            "define max", NAN); 
+    psMetadataAddF64(newrunArgs, PS_LIST_TAIL, "-az_min",  0,            "define min", NAN);
+    psMetadataAddF64(newrunArgs, PS_LIST_TAIL, "-az_max",  0,            "define max", NAN);
+    psMetadataAddF32(newrunArgs, PS_LIST_TAIL, "-ccd_temp_min",  0,               "define min ccd tempature", NAN);
+    psMetadataAddF32(newrunArgs, PS_LIST_TAIL, "-ccd_temp_max",  0,            "define max ccd tempature", NAN);
+    psMetadataAddF64(newrunArgs, PS_LIST_TAIL, "-posang_min",  0,            "define min rotator position angle", NAN);
+    psMetadataAddF64(newrunArgs, PS_LIST_TAIL, "-posang_max",  0,            "define max rotator position angle", NAN);
+    psMetadataAddStr(newrunArgs, PS_LIST_TAIL, "-object",  0,            "search by exposure object", NULL);
+    psMetadataAddF32(newrunArgs, PS_LIST_TAIL, "-solang_min",  0,            "define min solar angle", NAN);
+    psMetadataAddF32(newrunArgs, PS_LIST_TAIL, "-solang_max",  0,            "define max solar angle", NAN);
+
+    psMetadataAddStr(newrunArgs, PS_LIST_TAIL, "-set_workdir",  0,            "define workdir", NULL);
+    psMetadataAddStr(newrunArgs, PS_LIST_TAIL, "-set_label",  0,            "define label", NULL);
+    psMetadataAddStr(newrunArgs, PS_LIST_TAIL, "-set_reduction",  0,            "define reduction class", NULL);
+    psMetadataAddStr(newrunArgs, PS_LIST_TAIL, "-set_expgroup",  0,            "define exposure group", NULL);
+    psMetadataAddStr(newrunArgs, PS_LIST_TAIL, "-set_dvodb",  0,            "define DVO db", NULL);
+    psMetadataAddStr(newrunArgs, PS_LIST_TAIL, "-set_filter",  0,            "define filter", NULL);
+    psMetadataAddStr(newrunArgs, PS_LIST_TAIL, "-set_tess_id",  0,            "define tessalation", NULL);
+    psMetadataAddStr(newrunArgs, PS_LIST_TAIL, "-set_end_stage",  0,            "define processing end stage", NULL);
+    psMetadataAddStr(newrunArgs, PS_LIST_TAIL, "-set_region",  0,            "define region", NULL);
+
+    psMetadataAddBool(newrunArgs, PS_LIST_TAIL, "-pretend",  0,            "print the exposures that would be included in the detrend run and exit", false);
+    psMetadataAddBool(newrunArgs, PS_LIST_TAIL, "-simple", 0,            "use the simple output format", false);
+
+    // -addexp
+    psMetadata *addexpArgs = psMetadataAlloc();
+    psMetadataAddStr(addexpArgs, PS_LIST_TAIL, "-corr_id", 0,            "define Flat Correction ID (required)", NULL);
+    psMetadataAddStr(addexpArgs, PS_LIST_TAIL, "-chip_id", 0,            "define Chip ID (required)", NULL);
+
+    // -pending
+    psMetadata *pendingArgs = psMetadataAlloc();
+    psMetadataAddU64(pendingArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(pendingArgs, PS_LIST_TAIL, "-simple", 0,            "use the simple output format", false);
+
+    // -flatcorrimfile
+    psMetadata *flatcorrimfileArgs = psMetadataAlloc();
+    psMetadataAddStr(flatcorrimfileArgs, PS_LIST_TAIL, "-corr_id",  0,            "search by flat correction ID (required)", NULL);
+    psMetadataAddU64(flatcorrimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(flatcorrimfileArgs, PS_LIST_TAIL, "-simple", 0,            "use the simple output format", false);
+
+    // -done
+    psMetadata *doneArgs = psMetadataAlloc();
+    psMetadataAddStr(doneArgs, PS_LIST_TAIL, "-corr_id",  0,            "define correction id (required)", NULL);
+    psMetadataAddStr(doneArgs, PS_LIST_TAIL, "-stats",  0,            "define stats (required)", NULL);
+
+    // -updaterun
+    psMetadata *updaterunArgs = psMetadataAlloc();
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-corr_id",  0,            "define correction id (required)", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-state", 0,            "set state (required)", NULL);
+
+    psFree(now);
+
+    psMetadata *argSets = psMetadataAlloc();
+    psMetadata *modes = psMetadataAlloc();
+
+    PXOPT_ADD_MODE("-newrun",  "start a new flat correction run",        FLATCORR_MODE_NEWRUN,       newrunArgs);
+    PXOPT_ADD_MODE("-addexp",  "add an exp to a flat correction run",        FLATCORR_MODE_ADDEXP,       addexpArgs);
+    PXOPT_ADD_MODE("-pending", "show flat correction runs needing to be processed",        FLATCORR_MODE_PENDING,      pendingArgs);
+    PXOPT_ADD_MODE("-flatcorrimfile", "list all the imfiles in a flat correction run",        FLATCORR_MODE_FLATCORRIMFILE, flatcorrimfileArgs);
+    PXOPT_ADD_MODE("-done",  "change a flat calibration run's state",        FLATCORR_MODE_DONE,         doneArgs);
+    PXOPT_ADD_MODE("-updaterun",  "change a flat calibration run's state",        FLATCORR_MODE_UPDATERUN,   updaterunArgs);
+
+    if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
+        psError(PS_ERR_UNKNOWN, true, "option parsing failed");
+        psFree(argSets);
+        psFree(modes);
+        psFree(config);
+        return NULL;
+    }
+
+    psFree(argSets);
+    psFree(modes);
+
+    // define Database handle, if used
+    // do this last so we don't setup a connection before CLI options are
+    // validated
+    config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+    if (!config->dbh) {
+        psError(PS_ERR_UNKNOWN, false, "Can't configure database");
+        psFree(config);
+        return NULL;
+    }
+
+    return config;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/magictool.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/magictool.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/magictool.c	(revision 22158)
@@ -0,0 +1,1278 @@
+/*
+ * magictool.c
+ *
+ * Copyright (C) 2006-2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVB_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <ippdb.h>
+
+#include "pxtools.h"
+#include "magictool.h"
+
+static bool definebyqueryMode(pxConfig *config);
+static psS64 definerunMode(pxConfig *config);
+static bool updaterunMode(pxConfig *config);
+static bool addinputskyfileMode(pxConfig *config);
+static bool inputskyfileMode(pxConfig *config);
+static bool totreeMode(pxConfig *config);
+static bool inputtreeMode(pxConfig *config);
+static bool reverttreeMode(pxConfig *config);
+static bool toprocessMode(pxConfig *config);
+static bool addresultMode(pxConfig *config);
+static bool revertnodeMode(pxConfig *config);
+static bool inputsMode(pxConfig *config);
+static bool tomaskMode(pxConfig *config);
+static bool addmaskMode(pxConfig *config);
+static bool revertmaskMode(pxConfig *config);
+static bool maskMode(pxConfig *config);
+
+static bool setmagicRunState(pxConfig *config, psS64 magic_id, const char *state);
+static bool parseAndInsertNodeDeps(pxConfig *config, psS64 magic_id, const char *filename);
+
+# define MODECASE(caseName, func) \
+    case caseName: \
+    if (!func(config)) { \
+        goto FAIL; \
+    } \
+    break;
+
+int main(int argc, char **argv)
+{
+    psLibInit(NULL);
+
+    pxConfig *config = magictoolConfig(NULL, argc, argv);
+    if (!config) {
+        psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+        goto FAIL;
+    }
+
+    switch (config->mode) {
+        MODECASE(MAGICTOOL_MODE_DEFINEBYQUERY,  definebyqueryMode);
+        MODECASE(MAGICTOOL_MODE_DEFINERUN,      definerunMode);
+        MODECASE(MAGICTOOL_MODE_UPDATERUN,      updaterunMode);
+        MODECASE(MAGICTOOL_MODE_ADDINPUTSKYFILE,addinputskyfileMode);
+        MODECASE(MAGICTOOL_MODE_INPUTSKYFILE,   inputskyfileMode);
+        MODECASE(MAGICTOOL_MODE_TOTREE,         totreeMode);
+        MODECASE(MAGICTOOL_MODE_INPUTTREE,      inputtreeMode);
+        MODECASE(MAGICTOOL_MODE_REVERTTREE,     reverttreeMode);
+        MODECASE(MAGICTOOL_MODE_TOPROCESS,      toprocessMode);
+        MODECASE(MAGICTOOL_MODE_ADDRESULT,      addresultMode);
+        MODECASE(MAGICTOOL_MODE_REVERTNODE,     revertnodeMode);
+        MODECASE(MAGICTOOL_MODE_INPUTS,         inputsMode);
+        MODECASE(MAGICTOOL_MODE_TOMASK,         tomaskMode);
+        MODECASE(MAGICTOOL_MODE_ADDMASK,        addmaskMode);
+        MODECASE(MAGICTOOL_MODE_REVERTMASK,     revertmaskMode);
+        MODECASE(MAGICTOOL_MODE_MASK,           maskMode);
+        default:
+            psAbort("invalid option (this should not happen)");
+    }
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(EXIT_SUCCESS);
+
+FAIL:
+    psErrorStackPrint(stderr, "\n");
+    int exit_status = pxerrorGetExitStatus();
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exit_status);
+}
+
+static bool definebyqueryMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // Required
+    PXOPT_LOOKUP_STR(workdir, config->args, "-workdir", false, false);
+
+    // Optional
+    PXOPT_LOOKUP_STR(label, config->args, "-label", false, false);
+    PXOPT_LOOKUP_STR(dvodb, config->args, "-dvodb", false, false);
+    PXOPT_LOOKUP_TIME(registered, config->args, "-registered", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // Create temporary table of the best diffs
+    {
+        psString query = pxDataGet("magictool_definebyquery_temp_create.sql");
+        if (!query) {
+            psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+            return false;
+        }
+
+        if (!p_psDBRunQuery(config->dbh, query)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        }
+        psFree(query);
+    }
+
+    // Insert list of best diffs into temporary table
+    {
+        psString query = pxDataGet("magictool_definebyquery_temp_insert.sql");
+        if (!query) {
+            psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+            return false;
+        }
+
+        psMetadata *where = psMetadataAlloc();
+        PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+        PXOPT_COPY_F32(config->args, where, "-good_frac", "warpSkyfile.good_frac", ">=");
+
+        if (psListLength(where->list)) {
+            psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+            psStringAppend(&query, " AND %s", whereClause);
+            psFree(whereClause);
+        }
+        psFree(where);
+
+        psString groupby = pxDataGet("magictool_definebyquery_temp_insert_groupby.sql");
+        if (!groupby) {
+            psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+            psFree(query);
+            return false;
+        }
+
+        psStringAppend(&query, " %s", groupby);
+        psFree(groupby);
+
+        if (!p_psDBRunQuery(config->dbh, query)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(query);
+            return false;
+        }
+        psFree(query);
+    }
+
+    // Get list of exposures ready to magic
+    {
+        psString query = pxDataGet("magictool_definebyquery_select_part1.sql");
+        if (!query) {
+            psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+            return false;
+        }
+
+        {
+            psMetadata *where = psMetadataAlloc();
+            PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+            PXOPT_COPY_F32(config->args, where, "-good_frac", "warpSkyfile.good_frac", ">=");
+
+            if (psListLength(where->list)) {
+                psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+                psStringAppend(&query, " AND %s", whereClause);
+                psFree(whereClause);
+            }
+            psFree(where);
+        }
+
+        psString part2 = pxDataGet("magictool_definebyquery_select_part2.sql");
+        if (!part2) {
+            psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+            return false;
+        }
+
+        psStringAppend(&query, " %s", part2);
+        psFree(part2);
+
+        if (!p_psDBRunQuery(config->dbh, query)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(query);
+            return false;
+        }
+        psFree(query);
+    }
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+          case PS_ERR_DB_CLIENT:
+            psError(PXTOOLS_ERR_SYS, false, "database error");
+          case PS_ERR_DB_SERVER:
+            psError(PXTOOLS_ERR_PROG, false, "database error");
+          default:
+            psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("magictool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psString insert = pxDataGet("magictool_definebyquery_insert.sql"); // Insert query
+
+    psArray *list = psArrayAllocEmpty(16); // List of runs, to print
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *row = output->data[i]; // Row of interest
+        psS64 exp_id = psMetadataLookupS64(NULL, row, "exp_id"); // Exposure identifier
+
+        // create a new magicRun for this group
+        magicRunRow *run = magicRunRowAlloc(0, exp_id, "run", workdir, "dirty", label, dvodb, registered, 0);
+        if (!run) {
+            psAbort("failed to alloc magicRun object");
+        }
+
+        if (!magicRunInsertObject(config->dbh, run)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(run);
+            psFree(insert);
+            psFree(output);
+            psFree(list);
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            return false;
+        }
+
+        psS64 magic_id = psDBLastInsertID(config->dbh); // Assigned identifier
+        run->magic_id = magic_id;
+
+        psArrayAdd(list, list->n, run);
+        psFree(run);
+
+        // Create a suitable insertion query for this run
+        psString thisInsert = psStringCopy(insert);
+        {
+            psString idString = NULL;
+            psStringAppend(&idString, "%" PRId64, magic_id);
+            psStringSubstitute(&thisInsert, idString, "@MAGIC_ID@");
+            psFree(idString);
+        }
+        {
+            psString idString = NULL;
+            psStringAppend(&idString, "%" PRId64, exp_id);
+            psStringSubstitute(&thisInsert, idString, "@EXP_ID@");
+            psFree(idString);
+        }
+
+        if (!p_psDBRunQuery(config->dbh, thisInsert, magic_id, exp_id)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(thisInsert);
+            psFree(insert);
+            psFree(output);
+            psFree(list);
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            return false;
+        }
+        psFree(thisInsert);
+    }
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    psFree(output);
+
+    if (!magicRunPrintObjects(stdout, list, !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print object");
+        psFree(list);
+        return false;
+    }
+
+    psFree(list);
+
+    return true;
+}
+
+static psS64 definerunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required
+    PXOPT_LOOKUP_STR(workdir, config->args, "-workdir", true, false);
+    PXOPT_LOOKUP_S64(exp_id, config->args, "-exp_id", true, false);
+
+    // optional
+    PXOPT_LOOKUP_STR(label, config->args, "-label", false, false);
+    PXOPT_LOOKUP_STR(dvodb, config->args, "-dvodb", false, false);
+    PXOPT_LOOKUP_TIME(registered, config->args, "-registered", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    magicRunRow *run = magicRunRowAlloc(
+            0,          // ID
+            exp_id,
+            "reg",      // state
+            workdir,
+            "dirty",    // workdir_state
+            label,
+            dvodb,
+            registered,
+            0
+    );
+
+    if (!run) {
+        psError(PS_ERR_UNKNOWN, false, "failed to alloc magicRun object");
+        return false;
+    }
+    if (!magicRunInsertObject(config->dbh, run)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(run);
+        return false;
+    }
+
+    // get the assigned warp_id
+    psS64 magic_id = psDBLastInsertID(config->dbh);
+    run->magic_id = magic_id;
+
+    if (!magicRunPrintObject(stdout, run, !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print object");
+            psFree(run);
+            return false;
+    }
+
+    psFree(run);
+
+    return magic_id;
+}
+
+
+static bool updaterunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required
+    PXOPT_LOOKUP_S64(magic_id, config->args, "-magic_id", true, false);
+    PXOPT_LOOKUP_STR(state, config->args, "-state", true, false);
+
+    if (state) {
+        // set detRun.state to state
+        return setmagicRunState(config, magic_id, state);
+    }
+
+    return true;
+}
+
+
+static bool addinputskyfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required
+    PXOPT_LOOKUP_S64(magic_id, config->args, "-magic_id", true, false);
+    PXOPT_LOOKUP_S64(diff_id, config->args, "-diff_id", true, false);
+    PXOPT_LOOKUP_STR(node, config->args, "-node", true, false);
+
+    magicInputSkyfileInsert(
+            config->dbh,
+            magic_id,
+            diff_id,
+            node
+    );
+
+    return true;
+}
+
+
+static bool inputskyfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-magic_id", "magic_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-diff_id", "diff_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-node", "node", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // find all rawImfiles matching the default query
+    psString query = pxDataGet("magictool_inputskyfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "magicInputSkyfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("magictool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "magicInputSkyfile", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool totreeMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-magic_id", "magicRun.magic_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // look for "inputs" that need to processed
+    psString query = pxDataGet("magictool_totree.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("magictool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "totree", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool inputtreeMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required
+    PXOPT_LOOKUP_S64(magic_id, config->args, "-magic_id", true, false);
+
+    // Optional values
+    PXOPT_LOOKUP_STR(dep_file, config->args, "-dep_file", false, false);
+
+    // default values
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+
+    if (code > 0) {
+        char *query = "UPDATE magicRun SET fault = %d, state = 'stop' WHERE magic_id = %" PRId64;
+        if (!p_psDBRunQuery(config->dbh, query, code, magic_id)) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "failed to set fault for magic_id %" PRId64, magic_id);
+            return false;
+        }
+        return true;
+    }
+
+    if (!parseAndInsertNodeDeps(config, magic_id, dep_file)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to parse file");
+        return false;
+    }
+
+    return true;
+}
+
+static bool reverttreeMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-magic_id", "magic_id", "==");
+    PXOPT_COPY_S16(config->args, where, "-code", "fault", "==");
+
+    psString query = psStringCopy("UPDATE magicRun SET fault = 0, state = 'run' WHERE fault != 0");
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to revert");
+        return false;
+    }
+    return true;
+}
+
+
+static bool inputsMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-magic_id", "magic_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-node", "node", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("magictool_inputs.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("magictool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "magicNode", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+bool findBaseNodes(void *arg, pxNode *node)
+{
+    bool status = false;
+    psS64 done = psMetadataLookupS64(&status, node->data, "done");
+    if (!status) {
+        psAbort("failed to lookup value for done column");
+    }
+
+    if ((!pxNodeHasChildren(node)) && (!done)) {
+        // if this node has no child and it's not 'done', then push it's data
+        // onto the void *array
+        psArrayAdd((psArray *)arg, 0, node->data);
+        return false;
+    }
+
+    return true;
+}
+
+
+bool findReadyNodes(void *arg, pxNode *node)
+{
+    if (!node) {
+        // It's not there --- must have failed
+        return false;
+    }
+
+    if (!node->data) {
+        // It's a leaf node, not done
+        return false;
+    }
+
+    if (psMetadataLookupBool(NULL, node->data, "done")) {
+        // It's already done
+        return true;
+    }
+
+    if (pxNodeHasChildren(node)) {
+        psListIterator *iter = psListIteratorAlloc(node->children, 0, false);
+        psMetadata *work = psMetadataCopy(NULL, node->data);
+        psMetadataRemoveKey(work, "dep");
+        psMetadataRemoveKey(work, "done");
+        pxNode *child = NULL;
+        while ((child = psListGetAndIncrement(iter))) {
+            psMetadata *data = child->data;
+            if (!data) {
+                // Child is a leaf node, not done
+                psFree(iter);
+                psFree(work);
+                return false;
+            }
+
+            bool status = false;
+            psS32 done = psMetadataLookupS32(&status, data, "done");
+            if (!status) {
+                psAbort("failed to lookup value for done column");
+            }
+            psS16 bad = psMetadataLookupS16(&status, data, "bad");
+            if (!status) {
+                psAbort("failed to lookup value for bad column");
+            }
+
+            if (!done || bad) {
+                // if a child isn't "done", give up on this node and continue
+                // to crawl the tree
+                psFree(iter);
+                psFree(work);
+                return true;
+            }
+        }
+        psFree(iter);
+        // if all this nodes children are done, then push it's data onto the
+        // void *array
+        psArrayAdd((psArray *)arg, 0, work);
+        psFree(work);
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool toprocessMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-magic_id", "magic_id", "==");
+
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // look for "inputs" that need to processed
+    psString query = pxDataGet("magictool_toprocess_inputs.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    psString whereClause = NULL;
+    if (psListLength(where->list)) {
+        whereClause = psDBGenerateWhereSQL(where, NULL);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("magictool", PS_LOG_INFO, "no rows found");
+        // psFree(output);
+        // return true;
+    }
+
+    // look for tree nodes that need to be processed
+    query = pxDataGet("magictool_toprocess_tree.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (whereClause) {
+        psStringAppend(&query, " %s", whereClause);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *magicTree = p_psDBFetchResult(config->dbh);
+    if (!magicTree) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(magicTree)) {
+        psTrace("magictool", PS_LOG_INFO, "no rows found");
+        psFree(magicTree);
+        return true;
+    }
+
+    psHash *forest = psHashAlloc(psArrayLength(magicTree));
+
+    // convert the array of metadata into a pxTree structure
+    for (long i = 0; i < psArrayLength(magicTree); i++) {
+        bool status;
+        psString node = psMetadataLookupStr(&status, magicTree->data[i], "node");
+        if (!status) {
+            psAbort("failed to lookup value for node column");
+        }
+
+        psString dep = psMetadataLookupStr(&status, magicTree->data[i], "dep");
+        if (!status) {
+            psAbort("failed to lookup value for dep column");
+        }
+
+        pxTreeBuilder(forest, node, dep, magicTree->data[i]);
+
+    }
+    psFree(magicTree);
+
+    // find the root of the tree
+    pxNode *root = psMemIncrRefCounter(psHashLookup(forest, "root"));
+    psFree(forest);
+    //    pxTreePrint(stdout, root);
+
+    // crawl through the tree and looking for nodes with children that are all
+    // "done"
+    pxTreeCrawl(root, findReadyNodes, output);
+    psFree(root);
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "magicMe", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+    psFree(whereClause);
+
+    return true;
+}
+
+
+static bool addresultMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required
+    PXOPT_LOOKUP_S64(magic_id, config->args, "-magic_id", true, false);
+    PXOPT_LOOKUP_STR(node, config->args, "-node", true, false);
+
+    // optional
+    PXOPT_LOOKUP_STR(uri, config->args, "-uri", false, false);
+
+    // default values
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+
+    if (!magicNodeResultInsert(config->dbh,
+                               magic_id,
+                               node,
+                               uri,
+                               code
+        )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+static bool revertnodeMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-magic_id", "magic_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-node", "node", "==");
+    PXOPT_COPY_S16(config->args, where, "-code", "fault", "==");
+
+    psString query = psStringCopy("DELETE FROM magicNodeResult WHERE fault != 0");
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to revert");
+        return false;
+    }
+    return true;
+}
+
+
+static bool tomaskMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // look for "inputs" that need to processed
+    psString query = pxDataGet("magictool_tomask.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("magictool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "tomask", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool addmaskMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required
+    PXOPT_LOOKUP_S64(magic_id, config->args, "-magic_id", true, false);
+
+    // optional
+    PXOPT_LOOKUP_STR(uri, config->args, "-uri", false, false);
+    PXOPT_LOOKUP_S32(streaks, config->args, "-streaks", false, false);
+
+    // default values
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!magicMaskInsert(config->dbh,
+                         magic_id,
+                         uri,
+                         streaks,
+                         code
+        )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        return false;
+    }
+
+    // Set the magicRun state
+    psString query = pxDataGet("magictool_addmask.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        return false;
+    }
+
+    // manually add constraint
+    psStringAppend(&query, " AND magic_id = %" PRId64, magic_id);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        return false;
+    }
+    psFree(query);
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+static bool revertmaskMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-magic_id", "magic_id", "==");
+    PXOPT_COPY_S16(config->args, where, "-code", "fault", "==");
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // Set to "run"
+    {
+        psString query = psStringCopy("UPDATE magicRun JOIN magicMask USING(magic_id) "
+                                      "SET magicRun.state = 'run' WHERE magicMask.fault != 0");
+
+        if (psListLength(where->list)) {
+            psString whereClause = psDBGenerateWhereConditionSQL(where, "magicMask");
+            psStringAppend(&query, " AND %s", whereClause);
+            psFree(whereClause);
+        }
+
+        if (!p_psDBRunQuery(config->dbh, query)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to revert");
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            return false;
+        }
+
+        psFree(query);
+    }
+
+    // Delete failed attempt at mask
+    {
+        psString query = psStringCopy("DELETE FROM magicMask WHERE fault != 0");
+
+        if (psListLength(where->list)) {
+            psString whereClause = psDBGenerateWhereConditionSQL(where, "magicMask");
+            psStringAppend(&query, " AND %s", whereClause);
+            psFree(whereClause);
+        }
+
+        if (!p_psDBRunQuery(config->dbh, query)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to revert");
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            return false;
+        }
+
+        psFree(query);
+    }
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psFree(where);
+
+    return true;
+}
+
+
+static bool maskMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-magic_id", "magicRun.magic_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("magictool_mask.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("magictool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "magicMask", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool setmagicRunState(pxConfig *config, psS64 magic_id, const char *state)
+{
+    PS_ASSERT_PTR_NON_NULL(state, false);
+
+    // check that state is a valid string value
+    if (!(
+            (strncmp(state, "run", 4) == 0)
+            || (strncmp(state, "stop", 5) == 0)
+            || (strncmp(state, "reg", 4) == 0)
+        )
+    ) {
+        psError(PS_ERR_UNKNOWN, false,
+                "invalid magicRun state: %s", state);
+        return false;
+    }
+
+    char *query = "UPDATE magicRun SET state = '%s' WHERE magic_id = %" PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, state, magic_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for magic_id %" PRId64, magic_id);
+        return false;
+    }
+
+    return true;
+}
+
+static bool parseAndInsertNodeDeps(pxConfig *config, psS64 magic_id, const char *filename)
+{
+    unsigned int nFail = 0;
+    psMetadata *deps = psMetadataConfigRead(NULL, &nFail, filename, false);
+    if (!deps) {
+        psError(PS_ERR_UNKNOWN, false, "failed to parse file: %s", filename);
+        return false;
+    }
+    if (nFail) {
+        psError(PS_ERR_UNKNOWN, false, "there were %d errors parsing file: %s", nFail, filename);
+        psFree(deps);
+        return false;
+    }
+
+    psMetadataItem *item = NULL;
+    psMetadataIterator *iter = psMetadataIteratorAlloc(deps, 0, NULL);
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        if (item->type != PS_DATA_STRING) {
+            psError(PS_ERR_UNKNOWN, false, "file: %s is in the wrong format", filename);
+            psFree(iter);
+            psFree(deps);
+            return false;
+        }
+
+        char *name = item->name;
+        char *dependsOn = item->data.str;
+
+        if (!magicTreeInsert(
+                config->dbh,
+                magic_id,
+                name,
+                dependsOn
+            )) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(iter);
+            psFree(deps);
+            return false;
+        }
+    }
+    psFree(iter);
+    psFree(deps);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/magictool.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/magictool.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/magictool.h	(revision 22158)
@@ -0,0 +1,47 @@
+/*
+ * magictool.h
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MAGICTOOL_H
+#define MAGICTOOL_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+    MAGICTOOL_MODE_NONE           = 0x0,
+    MAGICTOOL_MODE_DEFINEBYQUERY,
+    MAGICTOOL_MODE_DEFINERUN,
+    MAGICTOOL_MODE_UPDATERUN,
+    MAGICTOOL_MODE_ADDINPUTSKYFILE,
+    MAGICTOOL_MODE_INPUTSKYFILE,
+    MAGICTOOL_MODE_TOTREE,
+    MAGICTOOL_MODE_INPUTTREE,
+    MAGICTOOL_MODE_REVERTTREE,
+    MAGICTOOL_MODE_TOPROCESS,
+    MAGICTOOL_MODE_INPUTS,
+    MAGICTOOL_MODE_ADDRESULT,
+    MAGICTOOL_MODE_REVERTNODE,
+    MAGICTOOL_MODE_TOMASK,
+    MAGICTOOL_MODE_ADDMASK,
+    MAGICTOOL_MODE_REVERTMASK,
+    MAGICTOOL_MODE_MASK,
+} MAGICtoolMode;
+
+pxConfig *magictoolConfig(pxConfig *config, int argc, char **argv);
+
+#endif // MAGICTOOL_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/magictoolConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/magictoolConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/magictoolConfig.c	(revision 22158)
@@ -0,0 +1,197 @@
+/*
+ * magictoolConfig.c
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+
+#include <psmodules.h>
+
+#include "pxtools.h"
+#include "magictool.h"
+
+pxConfig *magictoolConfig(pxConfig *config, int argc, char **argv)
+{
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    pmConfigReadParamsSet(false);
+
+    // setup site config
+    config->modules = pmConfigRead(&argc, argv, NULL);
+    if (!config->modules) {
+        psError(PS_ERR_UNKNOWN, false, "Can't find site configuration");
+        psFree(config);
+        return NULL;
+    }
+
+    psTime *now = psTimeGetNow(PS_TIME_TAI);
+
+    // -definebyquery
+    psMetadata *definebyqueryArgs = psMetadataAlloc();
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-workdir",     0, "define workdir (required)", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-label",       0, "define label", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-dvodb",       0, "define dvodb", NULL);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-registered", 0, "time detrend run was registered", now);
+    psMetadataAddS64(definebyqueryArgs, PS_LIST_TAIL, "-exp_id", 0, "search exp_id", 0);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-good_frac", 0, "limit good_frac", NAN);
+    psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-simple", 0, "use the simple output format", false);
+
+    // -definerun
+    psMetadata *definerunArgs = psMetadataAlloc();
+    psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-workdir", 0, "define workdir (required)", NULL);
+    psMetadataAddS64(definerunArgs, PS_LIST_TAIL, "-exp_id", 0, "define exp_id (required)", 0);
+    psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-label", 0, "define label", NULL);
+    psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-dvodb", 0, "define dvodb", NULL);
+    psMetadataAddTime(definerunArgs, PS_LIST_TAIL, "-registered", 0, "time detrend run was registered", now);
+    psMetadataAddBool(definerunArgs, PS_LIST_TAIL, "-simple", 0, "use the simple output format", false);
+
+    // -updaterun
+    psMetadata *updaterunArgs = psMetadataAlloc();
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-magic_id", 0, "define magictool ID (required)", 0);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-state", 0, "set state (required)", NULL);
+
+    // -addinputskyfile
+    psMetadata *addinputskyfileArgs = psMetadataAlloc();
+    psMetadataAddS64(addinputskyfileArgs, PS_LIST_TAIL, "-magic_id", 0, "define magictool ID (required)", 0);
+    psMetadataAddS64(addinputskyfileArgs, PS_LIST_TAIL, "-diff_id", 0, "define difftool ID (required)", 0);
+    psMetadataAddStr(addinputskyfileArgs, PS_LIST_TAIL, "-node", 0, "define symbolic node name (required)", NULL);
+
+    // -inputskyfile
+    psMetadata *inputskyfileArgs = psMetadataAlloc();
+    psMetadataAddS64(inputskyfileArgs, PS_LIST_TAIL, "-magic_id", 0, "search by magictool ID", 0);
+    psMetadataAddS64(inputskyfileArgs, PS_LIST_TAIL, "-diff_id", 0, "search by difftool ID", 0);
+    psMetadataAddStr(inputskyfileArgs, PS_LIST_TAIL, "-node", 0, "search by symbolic node name", NULL);
+    psMetadataAddU64(inputskyfileArgs, PS_LIST_TAIL, "-limit", 0, "limit result set to N items", 0);
+    psMetadataAddBool(inputskyfileArgs, PS_LIST_TAIL, "-simple", 0, "use the simple output format", false);
+
+    // -totree
+    psMetadata *totreeArgs = psMetadataAlloc();
+    psMetadataAddS64(totreeArgs, PS_LIST_TAIL, "-magic_id", 0, "search by magic ID", 0);
+    psMetadataAddU64(totreeArgs, PS_LIST_TAIL, "-limit", 0, "limit result set to N items", 0);
+    psMetadataAddBool(totreeArgs, PS_LIST_TAIL, "-simple", 0, "use the simple output format", false);
+
+    // -inputtree
+    psMetadata *inputtreeArgs = psMetadataAlloc();
+    psMetadataAddS64(inputtreeArgs, PS_LIST_TAIL, "-magic_id", 0, "define magictool ID (required)", 0);
+    psMetadataAddStr(inputtreeArgs, PS_LIST_TAIL, "-dep_file", 0, "order of operations dep. file", NULL);
+    psMetadataAddS16(inputtreeArgs, PS_LIST_TAIL, "-code", 0, "set fault code", 0);
+
+    // -reverttree
+    psMetadata *reverttreeArgs = psMetadataAlloc();
+    psMetadataAddS64(reverttreeArgs, PS_LIST_TAIL, "-magic_id", 0, "search by magictool ID", 0);
+    psMetadataAddS16(reverttreeArgs, PS_LIST_TAIL, "-code", 0, "search by fault code", 0);
+
+    // -inputs
+    psMetadata *inputsArgs = psMetadataAlloc();
+    psMetadataAddS64(inputsArgs, PS_LIST_TAIL, "-magic_id", 0, "search by magictool ID", 0);
+    psMetadataAddStr(inputsArgs, PS_LIST_TAIL, "-node", 0, "search by symbolic node name", NULL);
+    psMetadataAddU64(inputsArgs, PS_LIST_TAIL, "-limit", 0, "limit result set to N items", 0);
+    psMetadataAddBool(inputsArgs, PS_LIST_TAIL, "-simple", 0, "use the simple output format", false);
+
+    // -tooprocess
+    psMetadata *toprocessArgs = psMetadataAlloc();
+    psMetadataAddS64(toprocessArgs, PS_LIST_TAIL, "-magic_id", 0, "search by magic ID", 0);
+    psMetadataAddU64(toprocessArgs, PS_LIST_TAIL, "-limit", 0, "limit result set to N items", 0);
+    psMetadataAddBool(toprocessArgs, PS_LIST_TAIL, "-simple", 0, "use the simple output format", false);
+
+    // -addresult
+    psMetadata *addresultArgs = psMetadataAlloc();
+    psMetadataAddS64(addresultArgs, PS_LIST_TAIL, "-magic_id", 0, "define magictool ID (required)", 0);
+    psMetadataAddStr(addresultArgs, PS_LIST_TAIL, "-node", 0, "define symbolic node name (required)", NULL);
+    psMetadataAddStr(addresultArgs, PS_LIST_TAIL, "-uri", 0, "define URI", NULL);
+    psMetadataAddS16(addresultArgs, PS_LIST_TAIL, "-code", 0, "set fault code", 0);
+
+    // -revertnode
+    psMetadata *revertnodeArgs = psMetadataAlloc();
+    psMetadataAddS64(revertnodeArgs, PS_LIST_TAIL, "-magic_id", 0, "search by magictool ID", 0);
+    psMetadataAddStr(revertnodeArgs, PS_LIST_TAIL, "-node", 0, "search by node name", NULL);
+    psMetadataAddS16(revertnodeArgs, PS_LIST_TAIL, "-code", 0, "search by fault code", 0);
+
+    // -tomask
+    psMetadata *tomaskArgs = psMetadataAlloc();
+    psMetadataAddU64(tomaskArgs, PS_LIST_TAIL, "-limit", 0, "limit result set to N items", 0);
+    psMetadataAddBool(tomaskArgs, PS_LIST_TAIL, "-simple", 0, "use the simple output format", false);
+
+    // -addmask
+    psMetadata *addmaskArgs = psMetadataAlloc();
+    psMetadataAddS64(addmaskArgs, PS_LIST_TAIL, "-magic_id", 0, "define magictool ID (required)", 0);
+    psMetadataAddStr(addmaskArgs, PS_LIST_TAIL, "-uri", 0, "define URI", NULL);
+    psMetadataAddS32(addmaskArgs, PS_LIST_TAIL, "-streaks", 0, "define number of streaks", 0);
+    psMetadataAddS16(addmaskArgs, PS_LIST_TAIL, "-code", 0, "set fault code", 0);
+
+    // -revertmask
+    psMetadata *revertmaskArgs = psMetadataAlloc();
+    psMetadataAddS64(revertmaskArgs, PS_LIST_TAIL, "-magic_id", 0, "search by magictool ID", 0);
+    psMetadataAddS16(revertmaskArgs, PS_LIST_TAIL, "-code", 0, "search by fault code", 0);
+
+    // -mask
+    psMetadata *maskArgs = psMetadataAlloc();
+    psMetadataAddS64(maskArgs, PS_LIST_TAIL, "-magic_id", 0, "define magictool ID", 0);
+    psMetadataAddU64(maskArgs, PS_LIST_TAIL, "-limit", 0, "limit result set to N items", 0);
+    psMetadataAddBool(maskArgs, PS_LIST_TAIL, "-simple", 0, "use the simple output format", false);
+
+    psFree(now);
+
+    psMetadata *argSets = psMetadataAlloc();
+    psMetadata *modes   = psMetadataAlloc();
+
+    PXOPT_ADD_MODE("-definebyquery",   "", MAGICTOOL_MODE_DEFINEBYQUERY,   definebyqueryArgs);
+    PXOPT_ADD_MODE("-definerun",       "", MAGICTOOL_MODE_DEFINERUN,       definerunArgs);
+    PXOPT_ADD_MODE("-updaterun",       "", MAGICTOOL_MODE_UPDATERUN,       updaterunArgs);
+    PXOPT_ADD_MODE("-addinputskyfile", "", MAGICTOOL_MODE_ADDINPUTSKYFILE, addinputskyfileArgs);
+    PXOPT_ADD_MODE("-inputskyfile",    "", MAGICTOOL_MODE_INPUTSKYFILE,    inputskyfileArgs);
+    PXOPT_ADD_MODE("-totree",          "", MAGICTOOL_MODE_TOTREE,          totreeArgs);
+    PXOPT_ADD_MODE("-inputtree",       "", MAGICTOOL_MODE_INPUTTREE,       inputtreeArgs);
+    PXOPT_ADD_MODE("-reverttree",      "", MAGICTOOL_MODE_REVERTTREE,      reverttreeArgs);
+    PXOPT_ADD_MODE("-toprocess",       "", MAGICTOOL_MODE_TOPROCESS,       toprocessArgs);
+    PXOPT_ADD_MODE("-inputs",          "", MAGICTOOL_MODE_INPUTS,          inputsArgs);
+    PXOPT_ADD_MODE("-addresult",       "", MAGICTOOL_MODE_ADDRESULT,       addresultArgs);
+    PXOPT_ADD_MODE("-revertnode",      "", MAGICTOOL_MODE_REVERTNODE,      revertnodeArgs);
+    PXOPT_ADD_MODE("-tomask",          "", MAGICTOOL_MODE_TOMASK,          tomaskArgs);
+    PXOPT_ADD_MODE("-addmask",         "", MAGICTOOL_MODE_ADDMASK,         addmaskArgs);
+    PXOPT_ADD_MODE("-revertmask",      "", MAGICTOOL_MODE_REVERTMASK,      revertmaskArgs);
+    PXOPT_ADD_MODE("-mask",            "", MAGICTOOL_MODE_MASK,            maskArgs);
+
+    if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
+        psError(PS_ERR_UNKNOWN, true, "option parsing failed");
+        psFree(argSets);
+        psFree(modes);
+        psFree(config);
+        return NULL;
+    }
+
+    psFree(argSets);
+    psFree(modes);
+
+    // define Database handle, if used
+    // do this last so we don't setup a connection before CLI options are
+    // validated
+    config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+    if (!config->dbh) {
+        psError(PS_ERR_UNKNOWN, false, "Can't configure database");
+        psFree(config);
+        return NULL;
+    }
+
+    return config;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pstamptool.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pstamptool.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pstamptool.c	(revision 22158)
@@ -0,0 +1,717 @@
+/*
+ * pstamptool.c
+ *
+ * Copyright (C) 2008
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "pxtools.h"
+#include "pxdata.h"
+#include "pstamptool.h"
+
+static bool adddatastoreMode(pxConfig *config);
+static bool datastoreMode(pxConfig *config);
+static bool moddatastoreMode(pxConfig *config);
+static bool addReqMode(pxConfig *config);
+static bool completedReqMode(pxConfig *config);
+static bool listReqMode(pxConfig *config);
+static bool pendingReqMode(pxConfig *config);
+static bool processedReqMode(pxConfig *config);
+static bool revertReqMode(pxConfig *config);
+static bool addJobMode(pxConfig *config);
+static bool listJobMode(pxConfig *config);
+static bool pendingJobMode(pxConfig *config);
+static bool processedJobMode(pxConfig *config);
+
+# define MODECASE(caseName, func) \
+    case caseName: \
+    if (!func(config)) { \
+                goto FAIL; \
+            } \
+    break;
+
+
+int main(int argc, char **argv)
+{
+    psLibInit(NULL);
+
+    pxConfig *config = pstamptoolConfig(NULL, argc, argv);
+    if (!config) {
+        psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+        goto FAIL;
+    }
+
+    switch (config->mode) {
+        MODECASE(PSTAMPTOOL_MODE_ADDDATASTORE, adddatastoreMode);
+        MODECASE(PSTAMPTOOL_MODE_DATASTORE, datastoreMode);
+        MODECASE(PSTAMPTOOL_MODE_MODDATASTORE, moddatastoreMode);
+        MODECASE(PSTAMPTOOL_MODE_ADDREQ, addReqMode);
+        MODECASE(PSTAMPTOOL_MODE_COMPLETEDREQ, completedReqMode);
+        MODECASE(PSTAMPTOOL_MODE_LISTREQ, listReqMode);
+        MODECASE(PSTAMPTOOL_MODE_PENDINGREQ, pendingReqMode);
+        MODECASE(PSTAMPTOOL_MODE_PROCESSEDREQ, processedReqMode);
+        MODECASE(PSTAMPTOOL_MODE_REVERTREQ, revertReqMode);
+        MODECASE(PSTAMPTOOL_MODE_ADDJOB, addJobMode);
+        MODECASE(PSTAMPTOOL_MODE_LISTJOB, listJobMode);
+        MODECASE(PSTAMPTOOL_MODE_PENDINGJOB, pendingJobMode);
+        MODECASE(PSTAMPTOOL_MODE_PROCESSEDJOB, processedJobMode);
+        default:
+            psAbort("invalid option (this should not happen)");
+    }
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(EXIT_SUCCESS);
+
+FAIL:
+    psErrorStackPrint(stderr, "\n");
+    int exit_status = pxerrorGetExitStatus();
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exit_status);
+}
+
+static bool adddatastoreMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(uri,         config->args, "-uri",           true, false);
+    PXOPT_LOOKUP_STR(outProduct,  config->args, "-out_product",   true, false);
+    PXOPT_LOOKUP_STR(lastFileset, config->args, "-last_fileset", false, false);
+    PXOPT_LOOKUP_STR(state,       config->args, "-state",         false, false);
+
+    if (!pstampDataStoreInsert(config->dbh,
+            0,
+            state,
+            lastFileset,
+            outProduct,
+            uri
+        )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+static bool datastoreMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-ds_id", "ds_id", "==");
+
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("pstamptool_datastore.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("pstamptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "pstampDataStore", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+static bool moddatastoreMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(ds_id,       config->args, "-ds_id",         true, false);
+    PXOPT_LOOKUP_STR(lastFileset, config->args, "-last_fileset",  false, false);
+    PXOPT_LOOKUP_STR(state,       config->args, "-state",         false, false);
+
+    if (!state && !lastFileset) {
+        psError(PS_ERR_UNKNOWN, true, "at least one of -last_fileset or -state is required");
+        return false;
+    }
+
+    char *query = psStringCopy ("UPDATE pstampDataStore SET");
+    bool needComma = false;
+    
+    if (lastFileset) {
+        psStringAppend(&query, " lastFileset = '%s'", lastFileset);
+        needComma = true;
+    }
+
+    if (state) {
+        psStringAppend(&query, "%s state = '%s'", needComma ? "," : " ", state);
+        needComma = true; // be ready in case we add another field
+    }
+                
+    psStringAppend(&query, " WHERE ds_id = '%s'", ds_id);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+
+    psU64 affected = psDBAffectedRows(config->dbh);
+    if (affected != 1) {
+        psError(PS_ERR_UNKNOWN, false, "should have affected one row but %" 
+                                        PRIu64 " rows were modified", affected);
+        return false;
+    }
+
+    return true;
+}
+
+static bool addReqMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(uri,         config->args, "-uri",           true, false);
+    // PXOPT_LOOKUP_STR(outFileset,  config->args, "-out_fileset",   true, false);
+    PXOPT_LOOKUP_S32(ds_id,       config->args, "-ds_id",         false, false);
+
+    char *query ="INSERT INTO pstampRequest"
+                     " (state, uri, ds_id, fault)"
+                     " VALUES( 'new', '%s', %" PRId64 ", 0 )";
+    if (!p_psDBRunQuery(config->dbh, query, uri, ds_id)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psU64 affected = psDBAffectedRows(config->dbh);
+    if (affected != 1) {
+        psError(PS_ERR_UNKNOWN, false, 
+            "should have affected one row but %" PRIu64 " rows were modified",
+            affected);
+        return false;
+    }
+
+    psS64 req_id = psDBLastInsertID(config->dbh);
+
+    printf("%" PRId64 "\n", req_id);
+
+    return true;
+}
+
+static bool pendingReqMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-req_id", "req_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("pstamptool_pendingreq.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "pstampRequest");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("pstamptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "pstampRequest", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool listReqMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(req_id,  config->args, "-req_id", true, false);
+    PXOPT_LOOKUP_U64(limit,   config->args, "-limit",  false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = NULL;
+    psStringAppend(&query, 
+		   "SELECT * FROM pstampRequest WHERE state = 'run' AND "
+		   "(SELECT count(*) FROM pstampJob WHERE pstampJob.req_id = pstampRequest.req_id "
+		   " AND pstampJob.state != 'stop') = 0" );
+    
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("pstamptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "pstampRequest", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool completedReqMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = 
+        "SELECT * FROM pstampRequest WHERE state = 'run' AND "
+            "(SELECT count(*) FROM pstampJob WHERE pstampJob.req_id = pstampRequest.req_id "
+            " AND pstampJob.state != 'stop') = 0" ;
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!psArrayLength(output)) {
+        psTrace("pstamptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "pstampRequest", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool processedReqMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(req_id,     config->args, "-req_id",     true, false);
+    PXOPT_LOOKUP_STR(state,      config->args, "-state",      false, false);
+    PXOPT_LOOKUP_STR(outProduct, config->args, "-outProduct", false, false);
+    PXOPT_LOOKUP_STR(fault, 	 config->args, "-fault",      false, false);
+    PXOPT_LOOKUP_STR(uri,   	 config->args, "-uri",        false, false);
+    PXOPT_LOOKUP_STR(name,  	 config->args, "-name",       false, false);
+    PXOPT_LOOKUP_STR(reqType,    config->args, "-reqType",    false, false);
+
+    psString query = NULL;
+    psStringAppend(&query, "UPDATE pstampRequest SET");
+
+    char c = ' ';
+    if (state) {
+        psStringAppend(&query, "%c state = '%s'", c, state);
+        c = ',';
+    }
+    if (outProduct) {
+        psStringAppend(&query, "%c outProduct = '%s'", c, outProduct);
+        c = ',';
+    }
+    if (fault) {
+        psStringAppend(&query, "%c fault = %s", c, fault);
+        c = ',';
+    }
+    if (uri) {
+        psStringAppend(&query, "%c uri = '%s'", c, uri);
+        c = ',';
+    }
+    if (name) {
+        psStringAppend(&query, "%c name = '%s'", c, name);
+        c = ',';
+    }
+    if (reqType) {
+        psStringAppend(&query, "%c reqType = '%s'", c, reqType);
+        c = ',';
+    }
+    if (!state && !outProduct && !fault && !uri && !name && !reqType) {
+        psError(PS_ERR_UNKNOWN, true, "at least one of state, outProduct, fault, uri, name, and reqType must be specified");
+        return false;
+    }
+
+    psStringAppend(&query, " WHERE req_id = '%s'", req_id);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+
+    psU64 affected = psDBAffectedRows(config->dbh);
+    // note zero is not an error
+    if (affected > 1) {
+        psError(PS_ERR_UNKNOWN, false, "should have affected one row but %" 
+                                        PRIu64 " rows were modified", affected);
+        return false;
+    }
+
+    return true;
+}
+
+static bool revertReqMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_S64(req_id,     config->args, "-req_id",     true, false);
+
+    printf("Revert request %" PRId64 "\n", req_id);
+    
+    if (!p_psDBRunQuery(config->dbh, "DELETE FROM pstampJob where req_id = %" PRId64, req_id)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!p_psDBRunQuery(config->dbh, 
+        "UPDATE pstampRequest set state ='new', name=NULL, reqType=NULL, fault=0 where req_id = %" PRId64, req_id)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+static bool addJobMode(pxConfig *config)
+{
+    bool    stampJob = false;
+    char   *query = NULL;
+
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(uri,         config->args, "-uri",        true, false);
+    PXOPT_LOOKUP_STR(req_id,      config->args, "-req_id",     true, false);
+    PXOPT_LOOKUP_STR(rownum,      config->args, "-rownum",     true, false);
+    PXOPT_LOOKUP_STR(job_type,    config->args, "-job_type",   false, false);
+    PXOPT_LOOKUP_STR(outputBase,  config->args, "-outputBase", true,  false);
+    PXOPT_LOOKUP_STR(argString,   config->args, "-args",       false, false);
+    PXOPT_LOOKUP_STR(stateString, config->args, "-state",      false, false);
+    PXOPT_LOOKUP_STR(fault,       config->args, "-fault",      false, false);
+
+    // default value for job_type is defined in pstamptoolConfig.c
+    if (!strcmp(job_type, "get_image") || !strcmp(job_type, "detect_query")) {
+	stampJob = false;
+    } else if (!strcmp(job_type, "stamp")) {
+	stampJob = true;
+    } else {
+	psError(PS_ERR_UNKNOWN, false, "unknown value for -job_type: %s", job_type);
+	return false;
+    }
+
+    if (stampJob && !argString) {
+	psError(PS_ERR_UNKNOWN, true, "-args is required for stamp job");
+	return false;
+    }
+
+    if (stampJob) {
+	query = pxDataGet("pstamptool_addjob_stampjob.sql");
+    } else {
+	query = pxDataGet("pstamptool_addjob_otherjob.sql");
+    }
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query, req_id, rownum, stateString, job_type, uri, outputBase, fault, argString)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psU64 affected = psDBAffectedRows(config->dbh);
+    if (affected != 1) {
+        psError(PS_ERR_UNKNOWN, false, 
+            "should have affected one row but %" PRIu64 " rows were modified",
+            affected);
+        return false;
+    }
+
+    psS64 job_id = psDBLastInsertID(config->dbh);
+    printf("%" PRId64 "\n", job_id);
+
+    return true;
+}
+
+static bool listJobMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(req_id, config->args, "-req_id", false, false);
+    PXOPT_LOOKUP_STR(job_id, config->args, "-job_id", false, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = NULL;
+
+    if (!req_id && !job_id) {
+        fprintf(stderr, "either req_id or job_id must be specified\n");
+        exit (1);
+    }
+
+    if (req_id) {
+        psStringAppend(&query,
+                "SELECT"
+                " *"
+                " FROM pstampJob"
+                " WHERE req_id = %s", req_id
+            );
+    } else {
+        psStringAppend(&query,
+                "SELECT"
+                " *"
+                " FROM pstampJob"
+                " WHERE job_id = %s", job_id
+            );
+    } 
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("pstamptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "pstampJob", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool pendingJobMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+
+    PXOPT_COPY_S64(config->args, where, "-job_id", "job_id", "==");
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("pstamptool_pendingjob.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // use psDBGenerateWhereSQL because the SQL yields an intermediate table
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "pstampJob");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("pstamptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "pstampJob", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool processedJobMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(job_id,    config->args, "-job_id", true, false);
+    PXOPT_LOOKUP_STR(state,     config->args, "-state",  true, false);
+    PXOPT_LOOKUP_STR(fault,     config->args, "-fault",  false, false);
+
+    psString faultStr = NULL;
+    if (!fault) {
+        faultStr = psStringCopy("");
+    } else {
+        psStringAppend(&faultStr, ", fault = '%s'", fault);
+    }
+
+    char *query ="UPDATE pstampJob"
+	" SET state = '%s' %s"
+	" WHERE job_id = '%s'";
+    
+    if (!p_psDBRunQuery(config->dbh, query, state, faultStr, job_id)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(faultStr);
+
+    psU64 affected = psDBAffectedRows(config->dbh);
+    if (affected != 1) {
+        psError(PS_ERR_UNKNOWN, false, "should have affected one row but %" 
+                                        PRIu64 " rows were modified", affected);
+        return false;
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pstamptool.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pstamptool.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pstamptool.h	(revision 22158)
@@ -0,0 +1,45 @@
+/*
+ * pstamptool.h
+ *
+ * Copyright (C) 2008
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PSTAMPTOOL_H
+#define PSTAMPTOOL_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+    PSTAMPTOOL_MODE_NONE      = 0x0,
+    PSTAMPTOOL_MODE_ADDDATASTORE,
+    PSTAMPTOOL_MODE_DATASTORE,
+    PSTAMPTOOL_MODE_MODDATASTORE,
+    PSTAMPTOOL_MODE_ADDREQ,
+    PSTAMPTOOL_MODE_LISTREQ,
+    PSTAMPTOOL_MODE_COMPLETEDREQ,
+    PSTAMPTOOL_MODE_PENDINGREQ,
+    PSTAMPTOOL_MODE_PROCESSEDREQ,
+    PSTAMPTOOL_MODE_REVERTREQ,
+    PSTAMPTOOL_MODE_ADDJOB,
+    PSTAMPTOOL_MODE_LISTJOB,
+    PSTAMPTOOL_MODE_PENDINGJOB,
+    PSTAMPTOOL_MODE_JOBRESULT,
+    PSTAMPTOOL_MODE_PROCESSEDJOB,
+} pstamptoolMode;
+
+pxConfig *pstamptoolConfig(pxConfig *config, int argc, char **argv);
+
+#endif // PSTAMPTOOL_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pstamptoolConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pstamptoolConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pstamptoolConfig.c	(revision 22158)
@@ -0,0 +1,173 @@
+/*
+ * pstamptoolConfig.c
+ *
+ * Copyright (C) 2008
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <psmodules.h>
+
+#include "pxtools.h"
+#include "pstamptool.h"
+
+pxConfig *pstamptoolConfig(pxConfig *config, int argc, char **argv)
+{
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    pmConfigReadParamsSet(false);
+
+    // setup site config
+    config->modules = pmConfigRead(&argc, argv, NULL);
+    if (! config->modules) {
+        psError(PS_ERR_UNKNOWN, false, "Can't find site configuration!\n");
+        psFree(config);
+        return NULL;
+    }
+
+    // -adddatastore
+    psMetadata *adddatastoreArgs = psMetadataAlloc();
+    psMetadataAddStr(adddatastoreArgs, PS_LIST_TAIL, "-uri",          0, "define storage uri (required)", NULL);
+    psMetadataAddStr(adddatastoreArgs, PS_LIST_TAIL, "-out_product",  0, "define output product name (required)", NULL);
+    psMetadataAddStr(adddatastoreArgs, PS_LIST_TAIL, "-last_fileset", 0, "define last fileset seen", NULL);
+    psMetadataAddStr(adddatastoreArgs, PS_LIST_TAIL, "-state",        0, "define datastore state", "enabled");
+    
+    // -datastore
+    psMetadata *datastoreArgs = psMetadataAlloc();
+    psMetadataAddStr(datastoreArgs, PS_LIST_TAIL, "-ds_id", 0,            "define ds_id", NULL); 
+    psMetadataAddBool(datastoreArgs, PS_LIST_TAIL, "-simple", 0,            "use the simple output format", false);
+
+    // -moddatastore
+    psMetadata *moddatastoreArgs = psMetadataAlloc();
+    psMetadataAddStr(moddatastoreArgs, PS_LIST_TAIL, "-ds_id", 0,            "define ds_id", "0"); 
+    psMetadataAddStr(moddatastoreArgs, PS_LIST_TAIL, "-last_fileset", 0,            "define storage uri", NULL);
+    psMetadataAddStr(moddatastoreArgs, PS_LIST_TAIL, "-state", 0,            "define storage uri", NULL);
+
+    // -addreq
+    psMetadata *addreqArgs = psMetadataAlloc();
+    psMetadataAddStr(addreqArgs, PS_LIST_TAIL, "-uri", 0,            "define request file uri", NULL); 
+    psMetadataAddS32(addreqArgs, PS_LIST_TAIL, "-ds_id", 0,            "define request ds_id", 0); 
+    // psMetadataAddStr(addreqArgs, PS_LIST_TAIL, "-out_fileset", 0,            "define request output_fileset", NULL); 
+
+    // -pendingreq
+    psMetadata *pendingreqArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingreqArgs, PS_LIST_TAIL, "-req_id", 0,            "define req_id", NULL); 
+    psMetadataAddU64(pendingreqArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(pendingreqArgs, PS_LIST_TAIL, "-simple", 0,            "use the simple output format", false);
+
+    // -listreq
+    psMetadata *listreqArgs = psMetadataAlloc();
+    psMetadataAddStr(listreqArgs, PS_LIST_TAIL, "-req_id", 0,            "define req_id", NULL); 
+    psMetadataAddU64(listreqArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(listreqArgs, PS_LIST_TAIL, "-simple", 0,            "use the simple output format", false);
+
+    // -completedreq
+    psMetadata *completedreqArgs = psMetadataAlloc();
+    psMetadataAddU64(completedreqArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(completedreqArgs, PS_LIST_TAIL, "-simple", 0,            "use the simple output format", false);
+
+    // -processedreq
+    psMetadata *processedreqArgs = psMetadataAlloc();
+    psMetadataAddStr(processedreqArgs, PS_LIST_TAIL, "-req_id", 0,            "req_id for which to change state", NULL); 
+    psMetadataAddStr(processedreqArgs, PS_LIST_TAIL, "-state", 0,            "new state", NULL); 
+    psMetadataAddStr(processedreqArgs, PS_LIST_TAIL, "-outProduct", 0,            "define request outProduct", NULL); 
+    psMetadataAddStr(processedreqArgs, PS_LIST_TAIL, "-fault", 0,            "define request fault code", NULL); 
+    psMetadataAddStr(processedreqArgs, PS_LIST_TAIL, "-uri", 0,            "define the uri", NULL); 
+    psMetadataAddStr(processedreqArgs, PS_LIST_TAIL, "-name", 0,            "define the name", NULL); 
+    psMetadataAddStr(processedreqArgs, PS_LIST_TAIL, "-reqType", 0,            "define the reqType", NULL); 
+
+    // -revertreq
+    psMetadata *revertreqArgs = psMetadataAlloc();
+    psMetadataAddS64(revertreqArgs, PS_LIST_TAIL, "-req_id", 0,            "req_id for which to revert", 0); 
+
+    // -addjob
+    psMetadata *addjobArgs = psMetadataAlloc();
+    psMetadataAddStr(addjobArgs, PS_LIST_TAIL, "-uri", 0,            "define job file uri", NULL); 
+    psMetadataAddStr(addjobArgs, PS_LIST_TAIL, "-req_id", 0,            "define job req_id", NULL); 
+    psMetadataAddStr(addjobArgs, PS_LIST_TAIL, "-rownum", 0,            "define job rownum", NULL); 
+    psMetadataAddStr(addjobArgs, PS_LIST_TAIL, "-job_type", 0,            "define job job_type", "stamp"); 
+    psMetadataAddStr(addjobArgs, PS_LIST_TAIL, "-outputBase", 0,            "define job outputBase", NULL); 
+    psMetadataAddStr(addjobArgs, PS_LIST_TAIL, "-args", 0,            "define job args", NULL); 
+    psMetadataAddStr(addjobArgs, PS_LIST_TAIL, "-state", 0,            "new state", "run"); 
+    // psMetadataAddStr(addjobArgs, PS_LIST_TAIL, "-result", 0,            "new result", "0"); 
+    psMetadataAddStr(addjobArgs, PS_LIST_TAIL, "-fault", 0,            "new result", NULL); 
+
+    // -listjob
+    psMetadata *listjobArgs = psMetadataAlloc();
+    psMetadataAddStr(listjobArgs, PS_LIST_TAIL, "-req_id", 0,            "define request", NULL); 
+    psMetadataAddStr(listjobArgs, PS_LIST_TAIL, "-job_id", 0,            "define job", NULL); 
+    psMetadataAddU64(listjobArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(listjobArgs, PS_LIST_TAIL, "-simple", 0,            "use the simple output format", false);
+
+    // -pendingjob
+    psMetadata *pendingjobArgs = psMetadataAlloc();
+    psMetadataAddS64(pendingjobArgs, PS_LIST_TAIL, "-job_id", 0,            "define job", 0); 
+    psMetadataAddU64(pendingjobArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(pendingjobArgs, PS_LIST_TAIL, "-simple", 0,            "use the simple output format", false);
+
+    // -processedjob
+    psMetadata *processedjobArgs = psMetadataAlloc();
+    psMetadataAddStr(processedjobArgs, PS_LIST_TAIL, "-job_id", 0,            "req_id for which to change state", NULL); 
+    psMetadataAddStr(processedjobArgs, PS_LIST_TAIL, "-state", 0,            "new state", NULL); 
+    // psMetadataAddStr(processedjobArgs, PS_LIST_TAIL, "-result", 0,            "new result", NULL); 
+    psMetadataAddStr(processedjobArgs, PS_LIST_TAIL, "-fault", 0,            "new result", NULL); 
+
+    psMetadata *argSets = psMetadataAlloc();
+    psMetadata *modes = psMetadataAlloc();
+
+    PXOPT_ADD_MODE("-addreq",          "", PSTAMPTOOL_MODE_ADDREQ,       addreqArgs);
+    PXOPT_ADD_MODE("-pendingreq",      "", PSTAMPTOOL_MODE_PENDINGREQ,   pendingreqArgs);
+    PXOPT_ADD_MODE("-processedreq",    "", PSTAMPTOOL_MODE_PROCESSEDREQ, processedreqArgs);
+    PXOPT_ADD_MODE("-listreq",         "", PSTAMPTOOL_MODE_LISTREQ,      listreqArgs);
+    PXOPT_ADD_MODE("-completedreq",    "", PSTAMPTOOL_MODE_COMPLETEDREQ, completedreqArgs);
+    PXOPT_ADD_MODE("-revertreq",       "", PSTAMPTOOL_MODE_REVERTREQ,    revertreqArgs);
+
+    PXOPT_ADD_MODE("-addjob",          "", PSTAMPTOOL_MODE_ADDJOB,       addjobArgs);
+    PXOPT_ADD_MODE("-listjob",         "", PSTAMPTOOL_MODE_LISTJOB,      listjobArgs);
+    PXOPT_ADD_MODE("-pendingjob",      "", PSTAMPTOOL_MODE_PENDINGJOB,   pendingjobArgs);
+    PXOPT_ADD_MODE("-processedjob",    "", PSTAMPTOOL_MODE_PROCESSEDJOB, processedjobArgs);
+
+    PXOPT_ADD_MODE("-adddatastore",    "", PSTAMPTOOL_MODE_ADDDATASTORE, adddatastoreArgs);
+    PXOPT_ADD_MODE("-datastore",       "", PSTAMPTOOL_MODE_DATASTORE,    datastoreArgs);
+    PXOPT_ADD_MODE("-moddatastore",    "", PSTAMPTOOL_MODE_MODDATASTORE, moddatastoreArgs);
+
+    if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
+        psError(PS_ERR_UNKNOWN, true, "option parsing failed");
+        psFree(argSets);
+        psFree(modes);
+        psFree(config);
+        return NULL;
+    }
+
+    psFree(argSets);
+    psFree(modes);
+
+    // define Database handle, if used
+    // do this last so we don't setup a connection before CLI options are
+    // validated
+    config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+    if (!config->dbh) {
+        psError(PS_ERR_UNKNOWN, false, "Can't configure database");
+        psFree(config);
+        return NULL;
+    }
+
+    return config;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxadmin.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxadmin.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxadmin.c	(revision 22158)
@@ -0,0 +1,221 @@
+/*
+ * pxadmin.c
+ *
+ * Copyright (C) 2006-2008  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "pxtools.h"
+#include "pxadmin.h"
+
+bool createMode(pxConfig *config);
+bool deleteMode(pxConfig *config);
+static bool runMultipleStatments(pxConfig *config, const char *query);
+
+int main(int argc, char **argv)
+{
+    psLibInit(NULL);
+
+    pxConfig *config = pxAdminConfig(NULL, argc, argv);
+    if (!config) {
+        psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+        goto FAIL;
+    }
+
+    switch (config->mode) {
+        case PXADMIN_MODE_RECREATE:
+            if (!deleteMode(config)) {
+                goto FAIL;
+            }
+            // fall through
+        case PXADMIN_MODE_CREATE:
+            if (!createMode(config)) {
+                goto FAIL;
+            }
+            break;
+        case PXADMIN_MODE_DELETE:
+            if (!deleteMode(config)) {
+                goto FAIL;
+            }
+            break;
+        default:
+            psAbort("invalid option (this should not happen)");
+    }
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(EXIT_SUCCESS);
+
+FAIL:
+    psErrorStackPrint(stderr, "\n");
+
+    int exit_status = pxerrorGetExitStatus();
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exit_status);
+}
+
+
+bool createMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psString query = pxDataGet("pxadmin_create_tables.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // BEGIN
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!runMultipleStatments(config, query)) {
+        if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    // COMMIT
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+bool deleteMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    {
+        char line[128], answer[128];
+
+        psMetadataItem *name = pmConfigUserSite(config->modules, "DBNAME", PS_DATA_STRING);
+        if (!name) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to determine database name.");
+            return false;
+        }
+        psString dbName = name->data.str;
+
+        fprintf(stdout, "*** delete the tables from database %s? ***\n", dbName);
+        fprintf(stdout, "*** to delete the tables, answer YES, and give password ***\n");
+        fprintf(stdout, "*** WARNING: this action is permanent ***\n\n");
+
+        fprintf(stdout, "delete the tables (YES/[n]): ");
+        if (!fgets(line, 128, stdin)) {
+            psError(PS_ERR_IO, true, "Unable to read response.");
+            return false;
+        }
+        sscanf(line, "%s", answer);
+        if (strcmp (answer, "YES"))  {
+            psError(PS_ERR_UNKNOWN, true, "tables NOT deleleted");
+            return false;
+        }
+
+        fprintf(stdout, "enter dbh connection password: ");
+        if (!fgets(line, 128, stdin)) {
+            psError(PS_ERR_IO, true, "Unable to read response.");
+            return false;
+        }
+        sscanf(line, "%s", answer);
+
+        psMetadataItem *pass = pmConfigUserSite(config->modules, "DBPASSWORD", PS_DATA_STRING);
+        if (!pass) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to determine database password.");
+            return false;
+        }
+        psString dbPassword = pass->data.str;
+        if (strcmp (answer, dbPassword)) {
+            psError(PS_ERR_UNKNOWN, true, "invalid passwd - tables NOT deleleted");
+            return false;
+        }
+    }
+
+    psString query = pxDataGet("pxadmin_drop_tables.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // BEGIN
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!runMultipleStatments(config, query)) {
+        if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    // COMMIT
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool runMultipleStatments(pxConfig *config, const char *query)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(query, false);
+
+    // loop over all statements in string
+    psList *statements = psStringSplit(query, ";", false);
+
+    psString q = NULL;
+    psListIterator *iter = psListIteratorAlloc(statements, PS_LIST_HEAD, false);
+    while ((q = psListGetAndIncrement(iter))) {
+        if (!p_psDBRunQuery(config->dbh, q)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(iter);
+            psFree(statements);
+            return false;
+        }
+    }
+    psFree(iter);
+    psFree(statements);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxadmin.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxadmin.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxadmin.h	(revision 22158)
@@ -0,0 +1,34 @@
+/*
+ * pxadmin.h
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PXADMIN_H
+#define PXADMIN_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+    PXADMIN_MODE_NONE      = 0x0,
+    PXADMIN_MODE_CREATE,
+    PXADMIN_MODE_DELETE,
+    PXADMIN_MODE_RECREATE
+} pxAdminMode;
+
+pxConfig *pxAdminConfig (pxConfig *config, int argc, char **argv);
+
+#endif // PXADMIN_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxadminConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxadminConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxadminConfig.c	(revision 22158)
@@ -0,0 +1,147 @@
+/*
+ * pxadminConfig.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <psmodules.h>
+
+#include "pxtools.h"
+#include "pxadmin.h"
+
+static void pxAdminShowDB (const pxConfig *config, const char *program)
+{
+    fprintf (stderr, "\nPan-STARRS DataBase Admin Tool\n\n");
+    fprintf (stderr, "Usage: %s [mode]\n", program);
+    fprintf (stderr, " [mode] : -create | -delete\n\n");
+
+    psMetadataItem *server = pmConfigUserSite(config->modules, "DBSERVER",   PS_DATA_STRING);
+    psMetadataItem *user   = pmConfigUserSite(config->modules, "DBUSER",     PS_DATA_STRING);
+    psMetadataItem *name   = pmConfigUserSite(config->modules, "DBNAME",     PS_DATA_STRING);
+    psMetadataItem *port   = pmConfigUserSite(config->modules, "DBPORT",     PS_TYPE_S32);
+
+    if (!server || !user || !name) {
+        psErrorClear();
+        psWarning("Unable to determine database connection details.");
+        return;
+    }
+    if (!port) {
+        psErrorClear();
+    }
+
+    fprintf (stderr, "connecting to %s as %s (port %d)\n", server->data.str, user->data.str,
+             port ? port->data.S32 : 0);
+    fprintf (stderr, "using database %s\n\n", name->data.str);
+
+    return;
+}
+
+pxConfig *pxAdminConfig(pxConfig *config, int argc, char **argv)
+{
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    pmConfigReadParamsSet(false);
+
+    config->modules = pmConfigRead(&argc, argv, NULL);
+    if (!config->modules) {
+        psError(PS_ERR_UNKNOWN, false, "Can't find site configuration");
+        psFree(config);
+        return NULL;
+    }
+
+    // Parse other command-line arguments
+    psMetadata *arguments = psMetadataAlloc(); // The arguments, with default values
+
+    int N;
+    config->mode = PXADMIN_MODE_NONE;
+    if ((N = psArgumentGet(argc, argv, "-create"))) {
+        psArgumentRemove(N, &argc, argv);
+        if (config->mode) {
+            psAbort("only one mode selection is allowed");
+        }
+        config->mode = PXADMIN_MODE_CREATE;
+    }
+    if ((N = psArgumentGet(argc, argv, "-delete"))) {
+        psArgumentRemove(N, &argc, argv);
+        if (config->mode) {
+            psAbort("only one mode selection is allowed");
+        }
+        config->mode = PXADMIN_MODE_DELETE;
+    }
+    if ((N = psArgumentGet(argc, argv, "-recreate"))) {
+        psArgumentRemove(N, &argc, argv);
+        if (config->mode) {
+            psAbort("only one mode selection is allowed");
+        }
+        config->mode = PXADMIN_MODE_RECREATE;
+    }
+
+    // paul's argument parsing convention requires: -key value
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-create", 0,
+            "create all IPP tables", "");
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-delete", 0,
+            "delete all IPP tables", "");
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-recreate", 0,
+            "delete and recreate all tables", "");
+
+    if (config->mode == PXADMIN_MODE_NONE) {
+    pxAdminShowDB (config, argv[0]);
+        fprintf (stderr, "admin mode not specified\n");
+
+        psArgumentHelp(arguments);
+        psFree(arguments);
+        psFree(config);
+        return NULL;
+    }
+
+    if ((N = psArgumentGet (argc, argv, "-help"))) {
+    pxAdminShowDB (config, argv[0]);
+        psArgumentHelp(arguments);
+        psFree(arguments);
+        psFree(config);
+        return NULL;
+    }
+
+    if (! psArgumentParse(arguments, &argc, argv) || argc != 1) {
+    pxAdminShowDB (config, argv[0]);
+        psArgumentHelp(arguments);
+        psFree(arguments);
+        psFree(config);
+        return NULL;
+    }
+
+   psFree(arguments);
+
+    // define Database handle, if used
+    config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+    if (!config->dbh) {
+        psError(PS_ERR_UNKNOWN, false, "Can't configure database");
+        psFree(config);
+        return NULL;
+    }
+
+    // save argv/argc
+    config->argv = argv;
+    config->argc = argc;
+
+    return config;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxcam.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxcam.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxcam.c	(revision 22158)
@@ -0,0 +1,176 @@
+/*
+ * pxcam.c
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <ippdb.h>
+#include <string.h>
+
+#include "pxtools.h"
+#include "pxcam.h"
+
+bool pxcamRunSetState(pxConfig *config, psS64 cam_id, const char *state)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(state, false);
+
+    // check that state is a valid string value
+    if (!pxIsValidState(state)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "invalid camRun state: %s", state);
+        return false;
+    }
+
+    char *query = "UPDATE camRun SET state = '%s' WHERE cam_id = %" PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, state, cam_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for cam_id %" PRId64, cam_id);
+        return false;
+    }
+
+    return true;
+}
+
+
+bool pxcamRunSetStateByQuery(pxConfig *config, psMetadata *where, const char *state)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(state, false);
+
+    // check that state is a valid string value
+    if (!pxIsValidState(state)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "invalid chipRun state: %s", state);
+        return false;
+    }
+
+    psString query = psStringCopy("UPDATE camRun JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id) SET state = '%s'");
+
+    if (where) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query, state)) {
+        psFree(query);
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psFree(query);
+
+    return true;
+}
+
+
+bool pxcamRunSetLabel(pxConfig *config, psS64 cam_id, const char *label)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    // note label == NULL should be explicitly allowed
+
+    char *query = "UPDATE camRun SET camRun.label = '%s' WHERE cam_id = %" PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, label, cam_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for cam_id %" PRId64, cam_id);
+        return false;
+    }
+
+    return true;
+}
+
+bool pxcamRunSetLabelByQuery(pxConfig *config, psMetadata *where, const char *label)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    // note label == NULL should be explicitly allowed
+
+    psString query = psStringCopy("UPDATE camRun JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id) SET camRun.label = '%s'");
+
+    if (where) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query, label)) {
+        psFree(query);
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psFree(query);
+
+    return true;
+}
+
+
+bool pxcamQueueByChipID(pxConfig *config,
+                    psS64 chip_id,
+                    char *workdir,
+                    char *label,
+                    char *recipe,
+                    char *expgroup,
+                    char *dvodb,
+                    char *tess_id,
+                    char *end_stage)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // load the SQL to enqueue our exp_ids from disk once
+    static psString query = NULL;
+    if (!query) {
+        query = pxDataGet("camtool_queue_chip_id.sql");
+        psMemSetPersistent(query, true);
+        if (!query) {
+            psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+            return false;
+        }
+    }
+
+    // queue the exp
+    // XXX chip_id is being cast here work around psS64 have a different type
+    // different on 32/64
+    if (!p_psDBRunQuery(config->dbh, query,
+                "new", // state
+                workdir  ? workdir  : "NULL",
+                "dirty", //workdir_state
+                label    ? label    : "NULL",
+                recipe   ? recipe   : "NULL",
+                expgroup ? expgroup : "NULL",
+                dvodb    ? dvodb    : "NULL",
+                tess_id  ? tess_id  : "NULL",
+                end_stage ? end_stage : "NULL",
+                (long long)chip_id
+    )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // just to be safe, we should have changed at least one row
+    if (psDBAffectedRows(config->dbh) < 1) {
+        psError(PS_ERR_UNKNOWN, false,
+                "no rows affected - should have changed at least one row");
+        return false;
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxcam.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxcam.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxcam.h	(revision 22158)
@@ -0,0 +1,42 @@
+/*
+ * pxcam.h
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PXCAM_H
+#define PXCAM_H 1
+
+#include <pslib.h>
+
+#include "pxtools.h"
+
+bool pxcamRunSetState(pxConfig *config, psS64 cam_id, const char *state);
+bool pxcamRunSetStateByQuery(pxConfig *config, psMetadata *where, const char *state);
+bool pxcamRunSetLabel(pxConfig *config, psS64 cam_id, const char *label);
+bool pxcamRunSetLabelByQuery(pxConfig *config, psMetadata *where, const char *label);
+
+bool pxcamQueueByChipID(pxConfig *config,
+                        psS64 chip_id,
+                        char *workdir,
+                        char *label,
+                        char *recipe,
+                        char *expgroup,
+                        char *dvodb,
+                        char *tess_id,
+                        char *end_stage);
+
+#endif // PXCAM_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxchip.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxchip.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxchip.c	(revision 22158)
@@ -0,0 +1,158 @@
+/*
+ * pxchip.c
+ *
+ * Copyright (C) 2007-2008  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <ippdb.h>
+#include <string.h>
+
+#include "pxtools.h"
+#include "pxchip.h"
+
+bool pxchipRunSetState(pxConfig *config, psS64 chip_id, const char *state)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(state, false);
+
+    // check that state is a valid string value
+    if (!pxIsValidState(state)) {
+        psError(PS_ERR_UNKNOWN, false, "invalid chipRun state: %s", state);
+        return false;
+    }
+
+    char *query = "UPDATE chipRun SET state = '%s' WHERE chip_id = %" PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, state, chip_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for chip_id %" PRId64, chip_id);
+        return false;
+    }
+
+    return true;
+}
+
+
+bool pxchipRunSetStateByQuery(pxConfig *config, psMetadata *where, const char *state)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(state, false);
+
+    // check that state is a valid string value
+    if (!pxIsValidState(state)) {
+        psError(PS_ERR_UNKNOWN, false, "invalid chipRun state: %s", state);
+        return false;
+    }
+
+
+    psString query = psStringCopy("UPDATE chipRun JOIN rawExp USING(exp_id) SET state = '%s'");
+
+    if (where) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query, state)) {
+        psFree(query);
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psFree(query);
+
+    return true;
+}
+
+
+bool pxchipRunSetLabel(pxConfig *config, psS64 chip_id, const char *label)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    // note label == NULL should be explicitly allowed
+ 
+    char *query = "UPDATE chipRun SET label = '%s' WHERE chip_id = %" PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, label, chip_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for chip_id %" PRId64, chip_id);
+        return false;
+    }
+
+    return true;
+}
+
+
+bool pxchipRunSetLabelByQuery(pxConfig *config, psMetadata *where, const char *label)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    // note label == NULL should be explicitly allowed
+ 
+    psString query = psStringCopy("UPDATE chipRun JOIN rawExp USING(exp_id) SET label = '%s'");
+
+    if (where) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query, label)) {
+        psFree(query);
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psFree(query);
+
+    return true;
+}
+
+
+psS64 pxchipQueueByExpTag(pxConfig *config,
+                         psS64 exp_id,
+                         const char *workdir,
+                         const char *label,
+                         const char *reduction,
+                         const char *expgroup,
+                         const char *dvodb,
+                         const char *tess_id,
+                         const char *end_stage)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // create a chipRun
+    if (!chipRunInsert(config->dbh,
+            0x0, // chip_id
+            exp_id,
+            "new",      // state                
+            workdir,
+            "dirty",    // workdir_state
+            label,
+            reduction,
+            expgroup,
+            dvodb,
+            tess_id,
+            end_stage)
+    ) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return 0;
+    }
+
+    return psDBLastInsertID(config->dbh);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxchip.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxchip.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxchip.h	(revision 22158)
@@ -0,0 +1,43 @@
+/*
+ * pxchip.h
+ *
+ * Copyright (C) 2007-2008  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PXCHIP_H
+#define PXCHIP_H 1
+
+#include <pslib.h>
+
+#include "pxtools.h"
+
+bool pxchipRunSetState(pxConfig *config, psS64 chip_id, const char *state);
+bool pxchipRunSetStateByQuery(pxConfig *config, psMetadata *where, const char *state);
+bool pxchipRunSetLabel(pxConfig *config, psS64 chip_id, const char *label);
+bool pxchipRunSetLabelByQuery(pxConfig *config, psMetadata *where, const char *label);
+
+psS64 pxchipQueueByExpTag(pxConfig *config,
+                         psS64 exp_id,
+                         const char *workdir,
+                         const char *label,
+                         const char *reduction,
+                         const char *expgroup,
+                         const char *dvodb,
+                         const char *tess_id,
+                         const char *end_stage);
+
+
+#endif // PXCHIP_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxconfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxconfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxconfig.c	(revision 22158)
@@ -0,0 +1,227 @@
+/*
+ * pxconfig.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "pxtools.h"
+
+static void pxConfigFree(pxConfig *ptr);
+
+pxConfig *pxConfigAlloc(void)
+{
+    pxConfig *config;
+
+    config = psAlloc(sizeof(pxConfig));
+    psMemSetDeallocator(config, (psFreeFunc)pxConfigFree);
+
+    config->modeName        = NULL;
+    config->mode            = 0;
+    config->dbh             = NULL;
+    config->modules         = NULL;
+    // XXX config->where           = NULL;
+    config->args            = NULL;
+
+    return config;
+}
+
+static void pxConfigFree(pxConfig *config)
+{
+    psFree(config->modeName);
+    psFree(config->dbh);
+    psFree(config->modules);
+    // XXX psFree(config->where);
+    psFree(config->args);
+}
+
+void pxUsage(FILE *stream, int argc, char **argv, const char *modeName, psMetadata *argSet) 
+{
+    fprintf(stream, "Usage: %s %s [<options>]\n\n", argv[0], modeName);
+    fprintf(stream, "%s:\n", modeName);
+
+    psArgumentHelpSimple(stream, argSet);
+}
+
+bool pxGetOptions(FILE *stream, int argc, char **argv, pxConfig *config, psMetadata *modes, psMetadata *argSets)
+{
+    // figure out what mode we're running in
+    psMetadataIterator *iter = psMetadataIteratorAlloc(modes, PS_LIST_HEAD, NULL);
+    psMetadataItem *item = NULL;
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        int N = 0;
+        if ((N = psArgumentGet(argc, argv, item->name))) {
+            psArgumentRemove(N, &argc, argv);
+            // check for duplicate mode specification
+            if (config->mode) {
+                psError(PS_ERR_UNKNOWN, true, "only one mode selection is allowed");
+                fprintf(stream, "only one mode selection is allowed\n");
+                pxUsage(stream, argc, argv, "<mode>", modes);
+                psFree(iter);
+                return NULL;
+            }
+
+            config->mode = item->data.U32;
+            config->modeName = psStringCopy(item->name);
+
+            bool status = false;
+            psMetadata *argset = psMetadataLookupMetadata(&status, argSets, item->name);
+            // make sure we can find the argSet for the sepcified mode
+            if (!status) {
+                psError(PS_ERR_UNKNOWN, true, "can not find arguments for mode");
+                fprintf(stderr, "can not find arugments for mode");
+                psFree(iter);
+                return NULL;
+            }
+
+            config->args = psMemIncrRefCounter(argset);
+        }
+
+    }
+
+    psFree(iter);
+
+    // make sure we found a mode
+    if (config->mode == PXTOOL_MODE_NONE) {
+        psError(PS_ERR_UNKNOWN, true, "mode argument is required");
+        fprintf(stderr, "mode argument is required\n");
+        pxUsage(stream, argc, argv, "<mode>", modes);
+        return NULL;
+    }
+
+    // actually parse the command line
+    if (!psArgumentParse(config->args, &argc, argv)) {
+        psError(PS_ERR_UNKNOWN, false, "error parsing arguments");
+        fprintf(stderr, "error parsing arguments\n");
+        pxUsage(stream, argc, argv, config->modeName, config->args);
+        return NULL;
+    }
+
+    // look for left overs on the command line
+    if (argc != 1) {
+        psError(PS_ERR_UNKNOWN, false, "extra arguments: ");
+        fprintf(stderr, "extra arguments: ");
+        for (int i = 1; i < argc; i++) {
+            fprintf (stderr, "%s ", argv[i]);
+        }
+        fprintf(stderr, "\n");
+        pxUsage(stream, argc, argv, config->modeName, config->args);
+        return NULL;
+    }
+
+    // make sure that all required parameters have been specified
+    iter = psMetadataIteratorAlloc(config->args, PS_LIST_HEAD, NULL);
+    item = NULL; // Item from iterator
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        if (strstr(item->comment, "require") == NULL) {
+            continue;
+        }
+        if (strstr(item->comment, "(found)") != NULL) {
+            continue;
+        }
+
+        switch (item->type) {
+            case PS_DATA_BOOL:
+                psError(PS_ERR_UNKNOWN, false, "boolean type can not be required");
+                fprintf(stderr, "boolean type can not be required\n");
+                psFree(iter);
+                return NULL;
+                break;
+            case PS_DATA_S8:
+                if (item->data.S8 != INT8_MAX) {
+                    break;
+                }
+                goto ARG_REQUIRED;
+            case PS_DATA_S16:
+                if (item->data.S16 != INT16_MAX) {
+                    break;
+                }
+                goto ARG_REQUIRED;
+            case PS_DATA_S32:
+                if (item->data.S32 != INT32_MAX) {
+                    break;
+                }
+                goto ARG_REQUIRED;
+            case PS_DATA_S64:
+                if (item->data.S64 != INT64_MAX) {
+                    break;
+                }
+                goto ARG_REQUIRED;
+            case PS_DATA_U8:
+                if (item->data.U8 != UINT8_MAX) {
+                    break;
+                }
+                goto ARG_REQUIRED;
+            case PS_DATA_U16:
+                if (item->data.U16 != UINT16_MAX) {
+                    break;
+                }
+                goto ARG_REQUIRED;
+            case PS_DATA_U32:
+                if (item->data.U32 != UINT32_MAX) {
+                    break;
+                }
+                goto ARG_REQUIRED;
+            case PS_DATA_U64:
+                if (item->data.U64 != UINT64_MAX) {
+                    break;
+                }
+                goto ARG_REQUIRED;
+            case PS_DATA_F32:
+            case PS_DATA_F64:
+                if (!isnan(item->data.F64)) {
+                    break;
+                }
+                goto ARG_REQUIRED;
+            case PS_DATA_STRING:
+            case PS_DATA_TIME:
+            case PS_DATA_METADATA:
+                if (item->data.V) {
+                    break;
+                }
+                goto ARG_REQUIRED;
+            default:
+                psError(PS_ERR_UNKNOWN, false, "unknown argument type");
+                fprintf(stream, "unknown argument type\n");
+                psFree(iter);
+                return NULL;
+            ARG_REQUIRED:                
+                psError(PS_ERR_UNKNOWN, false, "argument %s is required", item->name);
+                fprintf(stream, "argument %s is required\n", item->name);
+                pxUsage(stream, argc, argv, config->modeName, config->args);
+                psFree(iter);
+                return NULL;
+        }
+
+    }
+
+    psFree(iter);
+
+    // save argv/argc 
+    config->argv = argv;
+    config->argc = argc;
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxconfig.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxconfig.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxconfig.h	(revision 22158)
@@ -0,0 +1,39 @@
+/*
+ * pxconfig.h
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PXCONFIG_H
+#define PXCONFIG_H 1
+
+#include "pslib.h"
+#include "psmodules.h"
+
+typedef struct {
+    char *modeName;
+    int mode;
+    pmConfig *modules;
+    psDB *dbh;
+    psMetadata *args;
+    // XXX deprecate psMetadata *where;
+    int argc;
+    char **argv;
+} pxConfig;
+
+pxConfig *pxConfigAlloc(void);
+
+#endif // PXCONFIG_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxdata.c.template
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxdata.c.template	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxdata.c.template	(revision 22158)
@@ -0,0 +1,145 @@
+/*
+ * pxdata.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVB_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h> // getenv
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <pslib.h>
+
+#include "pxtools.h"
+#include "pxdata.h"
+
+static psHash *cachedData = NULL;
+
+static int test_f(const char *path);
+
+psString pxDataGet(const char *filename)
+{
+    PS_ASSERT_PTR_NON_NULL(filename, NULL);
+
+    {
+        psString filepath = NULL;
+
+        // look to see if PXDATA is set
+        char *PXDATA = getenv("PXDATA");
+        if (PXDATA) {
+            // if it is, then prepend filename to PXDATA
+            psStringAppend(&filepath, "%s/%s", PXDATA, filename);
+        }
+
+        // see if we have a valid filename
+        if (test_f(filepath)) {
+            // if we do, slurp the file
+            psString data = psSlurpFilename(filepath);
+            if (!data) {
+                psError(PS_ERR_IO, false, "failed to slurp %s", filepath);
+                psFree(filepath);
+                return NULL;
+            }
+            psTrace("pxdata", PS_LOG_INFO, "slupred %s", filepath);
+            psFree(filepath);
+
+            return data;
+        }
+
+        psFree(filepath);
+    }
+
+    {
+        psString filepath = NULL;
+
+        // look under our share path
+        psStringAppend(&filepath, "%s/%s", "@PKGDATADIR@", filename);
+
+        // see if we have a valid filename
+        if (test_f(filepath)) {
+            // if we do, slurp the file
+            psString data = psSlurpFilename(filepath);
+            if (!data) {
+                psError(PS_ERR_IO, false, "failed to slurp %s", filepath);
+                psFree(filepath);
+                return NULL;
+            }
+            psTrace("pxdata", PS_LOG_INFO, "slupred %s", filepath);
+            psFree(filepath);
+
+            return data;
+        }
+
+        psFree(filepath);
+    }
+
+    // couldn't find a matching filename
+    psError(PS_ERR_IO, true, "can't find a file in search path(s) to match : %s", filename);
+
+    return NULL;
+}
+
+static int test_f(const char *path)
+{
+        // copied from coreutils 6.4 test.c licenced under GPL v2 
+        struct stat stat_buf;
+        return (stat (path, &stat_buf) == 0
+                   && S_ISREG (stat_buf.st_mode));
+}
+
+psString pxDataGetCached(const char *filename)
+{
+    bool persistence = p_psMemAllocatePersistent(true);
+
+    // make sure the cache is initalized
+    if (!cachedData) {
+        cachedData = psHashAlloc(10);
+    }
+
+    // look to see if we've cached this file
+    {
+        psString data = psHashLookup(cachedData, filename);
+        if (data) {
+            p_psMemAllocatePersistent(persistence);
+            return psStringCopy(data);
+        } 
+    }
+
+    // we didn't have a cached copy so we need to try to read the file
+    psString data = pxDataGet(filename);
+    if (!data) {
+        p_psMemAllocatePersistent(persistence);
+        psError(PS_ERR_IO, false, "pxDataGet(%s) failed", filename);
+        return NULL;
+    }
+
+    // store a copy of the file
+    if (!psHashAdd(cachedData, filename, data)) {
+        psFree(data);
+        p_psMemAllocatePersistent(persistence);
+        psError(PS_ERR_UNKNOWN, false, "psHashAdd() failed");
+        return NULL;
+    }
+
+    p_psMemAllocatePersistent(persistence);
+
+    return psStringCopy(data);
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxdata.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxdata.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxdata.h	(revision 22158)
@@ -0,0 +1,28 @@
+/*
+ * pxdata.h
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PXDATA_H
+#define PXDATA_H 1
+
+#include <pslib.h>
+
+psString pxDataGet(const char *filename);
+psString pxDataGetCached(const char *filename);
+
+#endif // PXDATA_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxerrors.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxerrors.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxerrors.c	(revision 22158)
@@ -0,0 +1,42 @@
+/*
+ * pxerrors.c
+ *
+ * Copyright (C) 2006  Eugene Magnier
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pxtools.h"
+
+psExit pxerrorGetExitStatus () {
+
+    psErrorCode err = psErrorCodeLast ();
+    switch (err) {
+      case PXTOOLS_ERR_SYS:
+    return PS_EXIT_SYS_ERROR;
+      case PXTOOLS_ERR_CONFIG:
+    return PS_EXIT_CONFIG_ERROR;
+      case PXTOOLS_ERR_PROG:
+    return PS_EXIT_PROG_ERROR;
+      case PXTOOLS_ERR_DATA:
+    return PS_EXIT_DATA_ERROR;
+      default:
+    return PS_EXIT_UNKNOWN_ERROR;
+    }    
+    return PS_EXIT_UNKNOWN_ERROR;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxfake.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxfake.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxfake.c	(revision 22158)
@@ -0,0 +1,178 @@
+/*
+ * pxfake.c
+ *
+ * Copyright (C) 2007-2008  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <ippdb.h>
+#include <string.h>
+
+#include "pxtools.h"
+#include "pxcam.h"
+
+bool pxfakeRunSetState(pxConfig *config, psS64 fake_id, const char *state)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(state, false);
+
+    // check that state is a valid string value
+    if (!pxIsValidState(state)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "invalid fakeRun state: %s", state);
+        return false;
+    }
+
+    char *query = "UPDATE fakeRun SET state = '%s' WHERE fake_id = %" PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, state, fake_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for fake_id %" PRId64, fake_id);
+        return false;
+    }
+
+    return true;
+}
+
+
+bool pxfakeRunSetStateByQuery(pxConfig *config, psMetadata *where, const char *state)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(state, false);
+
+    // check that state is a valid string value
+    if (!pxIsValidState(state)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "invalid fakeRun state: %s", state);
+        return false;
+    }
+
+    psString query = psStringCopy("UPDATE fakeRun JOIN camRun USING(cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id) SET state = '%s'");
+
+    if (where) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query, state)) {
+        psFree(query);
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psFree(query);
+
+    return true;
+}
+
+
+bool pxfakeRunSetLabel(pxConfig *config, psS64 fake_id, const char *label)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    // note label == NULL should be explicitly allowed
+
+    char *query = "UPDATE fakeRun SET fakeRun.label = '%s' WHERE fake_id = %" PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, label, fake_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for fake_id %" PRId64, fake_id);
+        return false;
+    }
+
+    return true;
+}
+
+
+bool pxfakeRunSetLabelByQuery(pxConfig *config, psMetadata *where, const char *label)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    // note label == NULL should be explicitly allowed
+
+    psString query = psStringCopy("UPDATE fakeRun JOIN camRun USING(cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id) SET fakeRun.label = '%s'");
+
+    if (where) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query, label)) {
+        psFree(query);
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psFree(query);
+
+    return true;
+}
+
+
+psS64 pxfakeQueueByCamID(pxConfig *config,
+                    psS64 cam_id,
+                    char *workdir,
+                    char *label,
+                    char *reduction,
+                    char *expgroup,
+                    char *dvodb,
+                    char *tess_id,
+                    char *end_stage)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psTrace("pxtool", PS_LOG_INFO, "attemping to queue cam_id: %"PRId64, cam_id);
+
+    // load the SQL to enqueue our exp_ids from disk once
+    static psString query = NULL;
+    if (!query) {
+        query = pxDataGet("faketool_queue_cam_id.sql");
+        psMemSetPersistent(query, true);
+        if (!query) {
+            psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+            return false;
+        }
+    }
+
+    // queue the exp
+    // XXX chip_id is being cast here work around psS64 have a different type
+    // different on 32/64
+    if (!p_psDBRunQuery(config->dbh, query,
+                "new", // state
+                workdir  ? workdir  : "NULL",
+                label    ? label    : "NULL",
+                reduction? reduction: "NULL",
+                expgroup ? expgroup : "NULL",
+                dvodb    ? dvodb    : "NULL",
+                tess_id  ? tess_id  : "NULL",
+                end_stage ? end_stage : "NULL",
+                (long long)cam_id
+    )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // just to be safe, we should have changed at least one row
+    if (psDBAffectedRows(config->dbh) != 1) {
+        psError(PS_ERR_UNKNOWN, false,
+                "should have changed just one row");
+        return false;
+    }
+
+    return psDBLastInsertID(config->dbh);
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxfake.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxfake.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxfake.h	(revision 22158)
@@ -0,0 +1,44 @@
+/*
+ * pxfake.h
+ *
+ * Copyright (C) 2007-2008  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PXFAKE_H
+#define PXFAKE_H 1
+
+#include <pslib.h>
+
+#include "pxtools.h"
+
+bool pxfakeRunSetState(pxConfig *config, psS64 fake_id, const char *state);
+bool pxfakeRunSetStateByQuery(pxConfig *config, psMetadata *where, const char *state);
+bool pxfakeRunSetLabel(pxConfig *config, psS64 fake_id, const char *label);
+bool pxfakeRunSetLabelByQuery(pxConfig *config, psMetadata *where, const char *label);
+
+
+psS64 pxfakeQueueByCamID(pxConfig *config,
+                    psS64 cam_id,
+                    char *workdir,
+                    char *label,
+                    char *reduction,
+                    char *expgroup,
+                    char *dvodb,
+                    char *tess_id,
+                    char *end_stage);
+
+
+#endif // PXFAKE_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxfault.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxfault.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxfault.c	(revision 22158)
@@ -0,0 +1,65 @@
+/*
+ * pxfault.c
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pslib.h>
+
+#include "pxtools.h"
+
+bool pxSetFaultCode(psDB *dbh, const char *tableName, psMetadata *where, psS16 code)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, false);
+    PS_ASSERT_PTR_NON_NULL(tableName, false);
+    PS_ASSERT_PTR_NON_NULL(where, false);
+
+#if 0
+    // map code string to numeric fault code
+    psU32 code = mapCodeStrToInt(codeStr);
+    if (code == (psU32)-1) {
+        psError(PS_ERR_UNKNOWN, false, "error resolving error code");
+        return false;
+    }
+#endif
+
+    // update the database
+    psMetadata *values = psMetadataAlloc();
+    if (!psMetadataAddS16(values, PS_LIST_HEAD, "fault", 0, NULL, code)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add metadata item fault");
+        psFree(values);
+        return false;
+    }
+
+    long rowsAffected = psDBUpdateRows(dbh, tableName, where, values); 
+    psFree(values);
+    if (rowsAffected < 0) {
+        // database error
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (rowsAffected < 1) {
+        // we didn't do anything
+        psError(PS_ERR_UNKNOWN, false, "zero rows were affected - either the search criteria didn't match any rows or the field already had the value being set.");
+        return false;
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxinject.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxinject.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxinject.c	(revision 22158)
@@ -0,0 +1,163 @@
+/*
+ * pxinject.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <ippdb.h>
+#include <string.h>
+
+#include "pxtools.h"
+#include "pxinject.h"
+
+static bool newExpMode(pxConfig *config);
+static bool newImfileMode(pxConfig *config);
+static bool updatenewExpMode(pxConfig *config);
+
+# define MODECASE(caseName, func) \
+    case caseName: \
+    if (!func(config)) { \
+        goto FAIL; \
+    } \
+    break;
+
+int main(int argc, char **argv)
+{
+    psLibInit(NULL);
+
+    pxConfig *config = pxinjectConfig(NULL, argc, argv);
+    if (!config) {
+        psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+        goto FAIL;
+    }
+
+    switch (config->mode) {
+        MODECASE(PXINJECT_MODE_NEWEXP, newExpMode);
+        MODECASE(PXINJECT_MODE_NEWIMFILE, newImfileMode);
+        MODECASE(PXINJECT_MODE_UPDATENEWEXP, updatenewExpMode);
+        default:
+            psAbort("invalid option (this should not happen)");
+    }
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(EXIT_SUCCESS);
+
+FAIL:
+    psErrorStackPrint (stderr, "failure\n");
+    int exit_status = pxerrorGetExitStatus();
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exit_status);
+}
+
+static bool newExpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(tmp_exp_name, config->args, "-tmp_exp_name", true, false);
+    PXOPT_LOOKUP_STR(tmp_camera, config->args, "-tmp_inst", true, false);
+    PXOPT_LOOKUP_STR(tmp_telescope, config->args, "-tmp_telescope", true, false);
+    PXOPT_LOOKUP_STR(workdir, config->args, "-workdir", true, false);
+    PXOPT_LOOKUP_STR(reduction, config->args, "-reduction", false, false);
+    PXOPT_LOOKUP_STR(dvodb, config->args, "-dvodb", false, false);
+    PXOPT_LOOKUP_STR(tess_id, config->args, "-tess_id", false, false);
+    PXOPT_LOOKUP_STR(end_stage, config->args, "-end_stage", false, false);
+    PXOPT_LOOKUP_STR(label, config->args, "-label", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    if (!newExpInsert(config->dbh,
+                0,    // exp_id
+                tmp_exp_name,
+                tmp_camera,
+                tmp_telescope,
+                "reg",  // state
+                workdir,
+                "dirty",
+                reduction,
+                dvodb,
+                tess_id,
+                end_stage,
+                label,
+                NULL    // epoch
+            )
+        ) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psS64 exp_id = psDBLastInsertID(config->dbh);
+
+    psMetadata *md = psMetadataAlloc();
+    if (!psMetadataAddS64(md, PS_LIST_TAIL, "exp_id", 0, NULL, exp_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+    }
+
+    // negate simple so the default is true
+    if (!ippdbPrintMetadata(stdout, md, !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(md);
+        return false;
+    }
+
+    psFree(md);
+
+    return true;
+}
+
+static bool newImfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_S64(exp_id, config->args, "-exp_id", true, false);
+    PXOPT_LOOKUP_STR(tmp_class_id, config->args, "-tmp_class_id", true, false);
+    PXOPT_LOOKUP_STR(uri, config->args, "-uri", true, false);
+
+    // insert with error flag state set to 0 (no errors)
+    if (!newImfileInsert(config->dbh, exp_id, tmp_class_id, uri, NULL)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool updatenewExpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_S64(exp_id, config->args, "-exp_id", true, false);
+    PXOPT_LOOKUP_STR(state, config->args, "-state", true, false);
+
+    if (state) {
+        // set detRun.state to state
+        return pxnewExpSetState(config, exp_id, state);
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxinject.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxinject.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxinject.h	(revision 22158)
@@ -0,0 +1,34 @@
+/*
+ * pxinject.h
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PXINJECT_H
+#define PXINJECT_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+    PXINJECT_MODE_NONE           = 0x0,
+    PXINJECT_MODE_NEWEXP,
+    PXINJECT_MODE_NEWIMFILE,
+    PXINJECT_MODE_UPDATENEWEXP
+} pxinjectMode;
+
+pxConfig *pxinjectConfig(pxConfig *config, int argc, char **argv);
+
+#endif // PXINJECT_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxinjectConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxinjectConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxinjectConfig.c	(revision 22158)
@@ -0,0 +1,98 @@
+/*
+ * pxinjectConfig.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <psmodules.h>
+
+#include "pxtools.h"
+#include "pxinject.h"
+
+pxConfig *pxinjectConfig(pxConfig *config, int argc, char **argv)
+{
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    pmConfigReadParamsSet(false);
+
+    // setup site config
+    config->modules = pmConfigRead(&argc, argv, NULL);
+    if (!config->modules) {
+        psError(PS_ERR_UNKNOWN, false, "Can't find site configuration");
+        psFree(config);
+        return NULL;
+    }
+
+    // -newExp
+    psMetadata *newExpArgs = psMetadataAlloc();
+    psMetadataAddStr(newExpArgs, PS_LIST_TAIL, "-tmp_exp_name",  0,            "define the exp_name (required)", NULL);
+    psMetadataAddStr(newExpArgs, PS_LIST_TAIL, "-tmp_inst",  0,            "define the camera name (required)", NULL);
+    psMetadataAddStr(newExpArgs, PS_LIST_TAIL, "-tmp_telescope",  0,            "define the telescope name (required)", NULL);
+    psMetadataAddStr(newExpArgs, PS_LIST_TAIL, "-workdir",  0,            "define workdir (required)", 0);
+    psMetadataAddStr(newExpArgs, PS_LIST_TAIL, "-reduction",  0,            "define reduction class", NULL);
+    psMetadataAddStr(newExpArgs, PS_LIST_TAIL, "-dvodb",  0,            "define the dvodb for the next processing step", NULL);
+    psMetadataAddStr(newExpArgs, PS_LIST_TAIL, "-tess_id",  0,            "define the tess_id for the next processing step", NULL);
+    psMetadataAddStr(newExpArgs, PS_LIST_TAIL, "-end_stage",  0,            "define the end goal processing step", NULL);
+    psMetadataAddStr(newExpArgs, PS_LIST_TAIL, "-label",  0,            "define a label (carried to chip stage)", NULL);
+    psMetadataAddBool(newExpArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -newImfile
+    psMetadata *newImfileArgs = psMetadataAlloc();
+    psMetadataAddS64(newImfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "define the exp_id (required)", 0);
+    psMetadataAddStr(newImfileArgs, PS_LIST_TAIL, "-tmp_class_id",  0,            "define the class ID (required)", NULL);
+    psMetadataAddStr(newImfileArgs, PS_LIST_TAIL, "-uri",  0,            "define the URI (required)", NULL);
+
+    // -updatenewExp
+    psMetadata *updatenewExpArgs = psMetadataAlloc();
+    psMetadataAddS64(updatenewExpArgs, PS_LIST_TAIL, "-exp_id",  0,            "define the exp_id (required)", 0);
+    psMetadataAddStr(updatenewExpArgs, PS_LIST_TAIL, "-state", 0,            "set state (required)", NULL);
+
+    psMetadata *argSets = psMetadataAlloc();
+    psMetadata *modes = psMetadataAlloc();
+
+    PXOPT_ADD_MODE("-newExp",      "", PXINJECT_MODE_NEWEXP,       newExpArgs);
+    PXOPT_ADD_MODE("-newImfile",   "", PXINJECT_MODE_NEWIMFILE,    newImfileArgs);
+    PXOPT_ADD_MODE("-updatenewExp",   "", PXINJECT_MODE_UPDATENEWEXP,    updatenewExpArgs);
+
+    if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
+        psError(PS_ERR_UNKNOWN, true, "option parsing failed");
+        psFree(argSets);
+        psFree(modes);
+        psFree(config);
+        return NULL;
+    }
+
+    psFree(argSets);
+    psFree(modes);
+
+    // define Database handle, if used
+    // do this last so we don't setup a connection before CLI options are
+    // validated
+    config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+    if (!config->dbh) {
+        psError(PS_ERR_UNKNOWN, false, "Can't configure database");
+        psFree(config);
+        return NULL;
+    }
+
+    return config;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxregister.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxregister.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxregister.c	(revision 22158)
@@ -0,0 +1,59 @@
+/*
+ * register.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <ippdb.h>
+#include <string.h>
+
+#include "pxtools.h"
+#include "pxregister.h"
+
+bool pxnewExpSetState(pxConfig *config, psS64 exp_id, const char *state)
+{
+    if (!exp_id) {
+        psError(PS_ERR_UNKNOWN, true, "0 is not a valid exp_id");
+        return false;
+    }
+    PS_ASSERT_PTR_NON_NULL(state, false);
+
+    // check that state is a valid string value
+    if (!(
+            (strncmp(state, "run", 4) == 0)
+            || (strncmp(state, "stop", 5) == 0)
+            || (strncmp(state, "reg", 4) == 0)
+        )
+    ) {
+        psError(PS_ERR_UNKNOWN, false,
+                "invalid newExp state: %s", state);
+        return false;
+    }
+
+    char *query = "UPDATE newExp SET state = '%s' WHERE exp_id = %"PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, state, exp_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for exp_id %"PRId64, exp_id);
+        return false;
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxregister.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxregister.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxregister.h	(revision 22158)
@@ -0,0 +1,29 @@
+/*
+ * pxregister.h
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PXREGISTER_H
+#define PXREGISTER_H 1
+
+#include <pslib.h>
+
+#include "pxtools.h"
+
+bool pxnewExpSetState(pxConfig *config, psS64 exp_id, const char *state);
+
+#endif // PXREGISTER_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtag.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtag.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtag.c	(revision 22158)
@@ -0,0 +1,102 @@
+/*
+ * pxtag.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVB_CONFIG_H
+#include <config.h>
+#endif
+
+#include <inttypes.h>
+
+#include "pxtools.h"
+#include "pxtag.h"
+
+psString pxGenExpTag(pxConfig *config, const char *exp_name)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    // start a transaction so we don't increment the expTag counter unless we
+    // can successfully retreive it's value
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return NULL;
+    }
+
+    if (!p_psDBRunQuery(config->dbh,
+        "UPDATE expTagCounter SET counter = LAST_INSERT_ID(counter + 1)")) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return NULL;
+    }
+
+    // psDBLastInsertID() can't be used here as it called mysql_insert_id()
+    // which doesn't work with this trick.  See:
+    // http://dev.mysql.com/doc/refman/4.1/en/information-functions.html
+    if (!p_psDBRunQuery(config->dbh, "SELECT LAST_INSERT_ID() as counter")) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return NULL;
+    }
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return NULL;
+    }
+    // sanity check that we only got one row
+    if (psArrayLength(output) != 1) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "should have gotten 1 row but %lu rows were returned", psArrayLength(output));
+        psFree(output);
+        return NULL;
+    }
+
+    // point of no return 
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(output);
+        return NULL;
+    }
+
+    psMetadata *row = output->data[0];
+    bool status = false;
+    psU64 counter = psMetadataLookupU64(&status, row, "counter");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for counter");
+        psFree(output);
+        return NULL;
+    }
+    psString exp_id = NULL;
+    psStringAppend(&exp_id, "%s.%" PRIu64, exp_name, counter);
+    psFree(output);
+
+    return exp_id;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtag.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtag.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtag.h	(revision 22158)
@@ -0,0 +1,29 @@
+/*
+ * pxtag.h
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PXTAG_H
+#define PXTAG_H 1
+
+#include <pslib.h>
+
+#include "pxconfig.h"
+
+psString pxGenExpTag(pxConfig *config, const char *exp_name);
+
+#endif // PXTAG_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtools.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtools.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtools.c	(revision 22158)
@@ -0,0 +1,46 @@
+/*
+ * pxtool.c
+ *
+ * Copyright (C) 2008  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include "pxtools.h"
+
+bool pxIsValidState(const char *state)
+{
+    PS_ASSERT_PTR_NON_NULL(state, false);
+    
+    // XXX replace strncmp with strcmp
+
+    if (!((strncmp(state, "new", 4) == 0)
+    || (strncmp(state, "reg", 3) == 0)
+    || (strncmp(state, "full", 5) == 0)
+    || (strncmp(state, "goto_cleaned", 8) == 0)
+    || (strncmp(state, "cleaned", 8) == 0)
+    || (strncmp(state, "update", 7) == 0)
+    || (strncmp(state, "purged", 7) == 0)
+    || (strncmp(state, "goto_purged", 12) == 0))) {
+        return false;
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtools.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtools.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtools.h	(revision 22158)
@@ -0,0 +1,480 @@
+/*
+ * pxtools.h
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PXTOOLS_H
+#define PXTOOLS_H 1
+
+#include <stdio.h>
+#include <string.h>   // for strcmp and strncmp
+#include <strings.h>  // for strcasecmp
+#include <unistd.h>   // for unlink
+
+// #include <stdlib.h>
+// #include <stdint.h>
+// #include <inttypes.h>
+
+#include <pslib.h>
+#include <psmodules.h>
+#include <ippdb.h>
+
+#include "pxconfig.h"
+#include "pxtoolsErrorCodes.h"
+
+#include "pxcam.h"
+#include "pxchip.h"
+#include "pxdata.h"
+#include "pxfake.h"
+#include "pxwarp.h"
+#include "pxregister.h"
+#include "pxtag.h"
+#include "pxtree.h"
+
+# define MAX_ROWS 10e9
+# define PXTOOL_MODE_NONE 0x0
+
+bool pxIsValidState(const char *state);
+
+bool pxSetFaultCode(psDB *dbh, const char *tableName, psMetadata *where, psS16 code);
+
+psExit pxerrorGetExitStatus ();
+
+void pxUsage(FILE *stream, int argc, char **argv, const char *modeName, psMetadata *argSet);
+bool pxGetOptions(FILE *stream, int argc, char **argv, pxConfig *config, psMetadata *modes, psMetadata *argSets);
+
+#define PXOPT_ADD_MODE(option, comment, modeval, argset) \
+{ \
+    if (!psMetadataAddMetadata(argSets, PS_LIST_TAIL, option, 0, comment, argset)) {;\
+        psError(PS_ERR_UNKNOWN, false, "failed to add argset for %s", option); \
+    } \
+    psFree(argset); \
+\
+    if (!psMetadataAddU32(modes, PS_LIST_TAIL, option, 0, comment, modeval)) {;\
+        psError(PS_ERR_UNKNOWN, false, "failed to add argset for %s", option); \
+    } \
+}
+
+#define PXOPT_LOOKUP_STR(var, md, key, required, ret) \
+psString var; \
+{ \
+    bool status; \
+ \
+    var = psMetadataLookupStr(&status, md, key); \
+    if (!status) { \
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for %s", key); \
+        return ret; \
+    } \
+ \
+    if (required && (!var)) { \
+        psError(PS_ERR_UNKNOWN, true, "%s is required", key); \
+        return ret; \
+    } \
+}
+
+#define PXOPT_LOOKUP_F(var, md, key, type, required, ret) \
+ps##type var; \
+{ \
+    bool status; \
+ \
+    var = psMetadataLookup##type(&status, md, key); \
+    if (!status) { \
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for %s", key); \
+        return ret; \
+    } \
+ \
+    if (required && isnan(var)) { \
+        psError(PS_ERR_UNKNOWN, true, "%s is required", key); \
+        return ret; \
+    } \
+}
+
+#define PXOPT_LOOKUP_F32(var, md, key, required, ret) \
+    PXOPT_LOOKUP_F(var, md, key, F64, required, ret)
+
+#define PXOPT_LOOKUP_F64(var, md, key, required, ret) \
+    PXOPT_LOOKUP_F(var, md, key, F64, required, ret)
+
+#define PXOPT_LOOKUP_PRIMITIVE(var, md, key, type, suffix, max, required, ret) \
+type var; \
+{ \
+    psMetadataItem *item = psMetadataLookup(md, key); \
+    if (!item) { \
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for %s", key); \
+        return ret; \
+    } \
+    psAssert(item->comment, "metadata item comment should be defined"); \
+    if (required && (!psStrcasestr(item->comment, "(found)"))) { \
+        psError(PS_ERR_UNKNOWN, true, "%s is required", key); \
+        return ret; \
+    } \
+ \
+    var = item->data.suffix; \
+ \
+}
+
+#define PXOPT_LOOKUP_S16(var, md, key, required, ret) \
+    PXOPT_LOOKUP_PRIMITIVE(var, md, key, psS16, S16, INT16_MAX, required, ret)
+
+#define PXOPT_LOOKUP_S32(var, md, key, required, ret) \
+    PXOPT_LOOKUP_PRIMITIVE(var, md, key, psS32, S32, INT32_MAX, required, ret)
+
+#define PXOPT_LOOKUP_S64(var, md, key, required, ret) \
+    PXOPT_LOOKUP_PRIMITIVE(var, md, key, psS64, S64, INT64_MAX, required, ret)
+
+#define PXOPT_LOOKUP_U16(var, md, key, required, ret) \
+    PXOPT_LOOKUP_PRIMITIVE(var, md, key, psU16, U16, UINT16_MAX, required, ret)
+
+#define PXOPT_LOOKUP_U32(var, md, key, required, ret) \
+    PXOPT_LOOKUP_PRIMITIVE(var, md, key, psU32, U32, UINT32_MAX, required, ret)
+
+#define PXOPT_LOOKUP_U64(var, md, key, required, ret) \
+    PXOPT_LOOKUP_PRIMITIVE(var, md, key, psU64, U64, UINT64_MAX, required, ret)
+
+#define PXOPT_LOOKUP_TIME(var, md, key, required, ret) \
+psTime *var; \
+{ \
+    bool status; \
+ \
+    var = psMetadataLookupTime(&status, md, key); \
+    if (!status) { \
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for %s", key); \
+        return ret; \
+    } \
+ \
+    if (required && (!var)) { \
+        psError(PS_ERR_UNKNOWN, true, "%s is required", key); \
+        return ret; \
+    } \
+}
+
+#define PXOPT_LOOKUP_BOOL(var, md, key, ret) \
+bool var; \
+{ \
+    bool status; \
+ \
+    var = psMetadataLookupBool(&status, md, key); \
+    if (!status) { \
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for %s", key); \
+        return ret; \
+    } \
+}
+
+// XXX the PXOPT_COPY_* macros free 'to' on error
+
+#define PXOPT_COPY_PRIMITIVE(from, to, type, suffix, oldname, newname, newcomment) \
+{ \
+    psMetadataItem *item = psMetadataLookup(from, oldname); \
+    if (!item) { \
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for %s", oldname); \
+        return false; \
+    } \
+    psAssert(item->comment, "metadata item comment should be defined"); \
+\
+    if (psStrcasestr(item->comment, "(found)")) { \
+        if (!psMetadataAdd##suffix(to, PS_LIST_TAIL, newname, PS_META_DUPLICATE_OK, newcomment, item->data.suffix)) { \
+            psError(PS_ERR_UNKNOWN, false, "failed to add item " newname); \
+            psFree(to); \
+            return false; \
+        } \
+    } \
+}
+
+#define PXOPT_COPY_V(from, to, type, suffix, oldname, newname, comment) \
+{ \
+    bool status = false; \
+    type var = psMetadataLookup##suffix(&status, from, oldname); \
+    if (!status) { \
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for " oldname); \
+        return false; \
+    } \
+    if (var) { \
+        if (!psMetadataAdd##suffix(to, PS_LIST_TAIL, newname, PS_META_DUPLICATE_OK, comment, var)) { \
+            psError(PS_ERR_UNKNOWN, false, "failed to add item " newname); \
+            psFree(to); \
+            return false; \
+        } \
+    }\
+}
+
+#define PXOPT_COPY_F(from, to, type, oldname, newname, comment) \
+{ \
+    bool status = false; \
+    ps##type var = psMetadataLookup##type(&status, from, oldname); \
+    if (!status) { \
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for " oldname); \
+        return false; \
+    } \
+    if (!isnan(var)) { \
+        if (!psMetadataAdd##type(to, PS_LIST_TAIL, newname, PS_META_DUPLICATE_OK, comment, var)) { \
+            psError(PS_ERR_UNKNOWN, false, "failed to add item " newname); \
+            psFree(to); \
+            return false; \
+        } \
+    } \
+}
+
+#define PXOPT_COPY_F32(from, to, oldname, newname, comment) \
+  PXOPT_COPY_F(from, to, F32, oldname, newname, comment)
+
+#define PXOPT_COPY_F64(from, to, oldname, newname, comment) \
+  PXOPT_COPY_F(from, to, F64, oldname, newname, comment)
+
+#define PXOPT_COPY_TIME(from, to, oldname, newname, comment) \
+  PXOPT_COPY_V(from, to, psTime *, Time, oldname, newname, comment)
+
+#define PXOPT_COPY_STR(from, to, oldname, newname, comment) \
+  PXOPT_COPY_V(from, to, psString, Str, oldname, newname, comment)
+
+#define PXOPT_COPY_S16(from, to, oldname, newname, comment) \
+  PXOPT_COPY_PRIMITIVE(from, to, psS16, S16, oldname, newname, comment)
+
+#define PXOPT_COPY_S32(from, to, oldname, newname, comment) \
+  PXOPT_COPY_PRIMITIVE(from, to, psS32, S32, oldname, newname, comment)
+
+#define PXOPT_COPY_S64(from, to, oldname, newname, comment) \
+  PXOPT_COPY_PRIMITIVE(from, to, psS64, S64, oldname, newname, comment)
+
+#define PXOPT_COPY_U16(from, to, oldname, newname, comment) \
+  PXOPT_COPY_PRIMITIVE(from, to, psU16, U16, oldname, newname, comment)
+
+#define PXOPT_COPY_U32(from, to, oldname, newname, comment) \
+  PXOPT_COPY_PRIMITIVE(from, to, psU32, U32, oldname, newname, comment)
+
+#define PXOPT_COPY_U64(from, to, oldname, newname, comment) \
+  PXOPT_COPY_PRIMITIVE(from, to, psU64, U64, oldname, newname, comment)
+
+
+/*** these PXOPT_ADD_WHERE macros are used to construct the default sql elements ***/
+
+#define PXOPT_ADD_WHERE_STR(name) \
+{ \
+    psString str = NULL; \
+    bool status = false; \
+    if ((str = psMetadataLookupStr(&status, config->args, "-" #name))) { \
+        if (!psMetadataAddStr(config->where, PS_LIST_TAIL, #name, 0, "==", str)) {\
+            psError(PS_ERR_UNKNOWN, false, "failed to add item " #name); \
+            psFree(config); \
+            return NULL; \
+        } \
+    } \
+}
+
+#define PXOPT_ADD_WHERE_STR_ALIAS(name,realname) \
+{ \
+    psString str = NULL; \
+    bool status = false; \
+    if ((str = psMetadataLookupStr(&status, config->args, name))) { \
+        if (!psMetadataAddStr(config->where, PS_LIST_TAIL, realname, 0, "==", str)) {\
+            psError(PS_ERR_UNKNOWN, false, "failed to add item %s", name); \
+            psFree(config); \
+            return NULL; \
+        } \
+    } \
+}
+
+#define PXOPT_ADD_WHERE_S16(name) \
+{ \
+    psS16 s16 = 0; \
+    bool status = false; \
+    if ((s16= psMetadataLookupS16(&status, config->args, "-" #name))) { \
+        if (!psMetadataAddS16(config->where, PS_LIST_TAIL, #name, 0, "==", s16)) { \
+            psError(PS_ERR_UNKNOWN, false, "failed to add item " #name); \
+            psFree(config); \
+            return NULL; \
+        } \
+    } \
+}
+
+#define PXOPT_ADD_WHERE_BOOL(name) \
+{ \
+    bool value = false;	 \
+    bool status = false; \
+    if ((value = psMetadataLookupBool(&status, config->args, "-" #name))) { \
+        if (!psMetadataAddBool(config->where, PS_LIST_TAIL, #name, 0, "==", value)) { \
+            psError(PS_ERR_UNKNOWN, false, "failed to add item " #name); \
+            psFree(config); \
+            return NULL; \
+        } \
+    } \
+}
+
+#define PXOPT_ADD_WHERE_S32(name) \
+{ \
+    psS32 s32 = 0; \
+    bool status = false; \
+    if ((s32= psMetadataLookupS32(&status, config->args, "-" #name))) { \
+        if (!psMetadataAddS32(config->where, PS_LIST_TAIL, #name, 0, "==", s32)) { \
+            psError(PS_ERR_UNKNOWN, false, "failed to add item " #name); \
+            psFree(config); \
+            return NULL; \
+        } \
+    } \
+}
+
+#define PXOPT_ADD_WHERE_S64(name) \
+{ \
+    psS64 s64 = 0; \
+    bool status = false; \
+    if ((s64= psMetadataLookupS64(&status, config->args, "-" #name))) { \
+        if (!psMetadataAddS64(config->where, PS_LIST_TAIL, #name, 0, "==", s64)) { \
+            psError(PS_ERR_UNKNOWN, false, "failed to add item " #name); \
+            psFree(config); \
+            return NULL; \
+        } \
+    } \
+}
+
+#define PXOPT_ADD_WHERE_F32(name) \
+{ \
+    psF32 var = 0; \
+    bool status = false; \
+    if ((var = psMetadataLookupF32(&status, config->args, "-" #name))) { \
+        if (!isnan(var)) { \
+            if (!psMetadataAddF32(config->where, PS_LIST_TAIL, #name, 0, "==", var)) { \
+                psError(PS_ERR_UNKNOWN, false, "failed to add item " #name); \
+                psFree(config); \
+                return NULL; \
+            } \
+        } \
+    } \
+}
+
+#define PXOPT_ADD_WHERE_F64(name) \
+{ \
+    psF64 var = 0; \
+    bool status = false; \
+    if ((var = psMetadataLookupF64(&status, config->args, "-" #name))) { \
+        if (!isnan(var))  { \
+            if (!psMetadataAddF64(config->where, PS_LIST_TAIL, #name, 0, "==", var)) { \
+                psError(PS_ERR_UNKNOWN, false, "failed to add item " #name); \
+                psFree(config); \
+                return NULL; \
+            } \
+        } \
+    } \
+}
+
+#define PXOPT_ADD_WHERE_BOOL_ALIAS(flag,name)	\
+{ \
+    bool value = 0; \
+    bool status = false; \
+    if ((value = psMetadataLookupBool(&status, config->args, flag))) {	\
+        if (!psMetadataAddBOOL(config->where, PS_LIST_TAIL, name, 0, "==", value)) { \
+            psError(PS_ERR_UNKNOWN, false, "failed to add item %s", flag); \
+            psFree(config); \
+            return NULL; \
+        } \
+    } \
+}
+
+#define PXOPT_ADD_WHERE_S16_ALIAS(flag,name)	\
+{ \
+    psS16 s16 = 0; \
+    bool status = false; \
+    if ((s16= psMetadataLookupS16(&status, config->args, flag))) {	\
+        if (!psMetadataAddS16(config->where, PS_LIST_TAIL, name, 0, "==", s16)) { \
+            psError(PS_ERR_UNKNOWN, false, "failed to add item %s", flag); \
+            psFree(config); \
+            return NULL; \
+        } \
+    } \
+}
+
+#define PXOPT_ADD_WHERE_S32_ALIAS(flag,name)	\
+{ \
+    psS32 s32 = 0; \
+    bool status = false; \
+    if ((s32= psMetadataLookupS32(&status, config->args, flag))) {	\
+        if (!psMetadataAddS32(config->where, PS_LIST_TAIL, name, 0, "==", s32)) { \
+            psError(PS_ERR_UNKNOWN, false, "failed to add item %s", flag); \
+            psFree(config); \
+            return NULL; \
+        } \
+    } \
+}
+
+#define PXOPT_ADD_WHERE_S64_ALIAS(flag,name)	\
+{ \
+    psS64 s64 = 0; \
+    bool status = false; \
+    if ((s64= psMetadataLookupS64(&status, config->args, flag))) {	\
+        if (!psMetadataAddS64(config->where, PS_LIST_TAIL, name, 0, "==", s64)) { \
+            psError(PS_ERR_UNKNOWN, false, "failed to add item %s", flag); \
+            psFree(config); \
+            return NULL; \
+        } \
+    } \
+}
+
+#define PXOPT_ADD_WHERE_F32_ALIAS(flag,name)	\
+{ \
+    psF32 var = 0; \
+    bool status = false; \
+    if ((var = psMetadataLookupF32(&status, config->args, flag))) {	\
+        if (!isnan(var))  { \
+            if (!psMetadataAddF32(config->where, PS_LIST_TAIL, name, 0, "==", var)) { \
+                psError(PS_ERR_UNKNOWN, false, "failed to add item %s", flag); \
+                psFree(config); \
+                return NULL; \
+            } \
+        } \
+    } \
+}
+
+#define PXOPT_ADD_WHERE_F64_ALIAS(flag,name)	\
+{ \
+    psF64 var = 0; \
+    bool status = false; \
+    if ((var = psMetadataLookupF64(&status, config->args, flag))) {	\
+        if (!isnan(var))  { \
+            if (!psMetadataAddF64(config->where, PS_LIST_TAIL, name, 0, "==", var)) { \
+                psError(PS_ERR_UNKNOWN, false, "failed to add item %s", flag); \
+                psFree(config); \
+                return NULL; \
+            } \
+        } \
+    } \
+}
+
+#define PXOPT_ADD_WHERE_TIME_STR(name) \
+{ \
+    psString str = NULL; \
+    bool status = false; \
+    if ((str = psMetadataLookupStr(&status, config->args, "-" #name))) { \
+        psTime *time = psTimeFromISO(str, PS_TIME_UTC); \
+        if (!time) { \
+            psError(PS_ERR_UNKNOWN, false, "failed to convert " #name " into a psTime object"); \
+            psFree(config); \
+            return NULL; \
+        } \
+        psMetadataItem *item = psMetadataLookup(config->args, "-" #name); \
+        if (item) { \
+            str = item->comment; \
+        } else { \
+            str = NULL; \
+        } \
+        if (!psMetadataAddTime(config->where, PS_LIST_TAIL, #name, 0, str, time)) {\
+            psError(PS_ERR_UNKNOWN, false, "failed to add item " #name); \
+            psFree(config); \
+            return NULL; \
+        } \
+        psFree(time); \
+    } \
+}
+
+#endif // PXTOOLS_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtoolsErrorCodes.c.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtoolsErrorCodes.c.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtoolsErrorCodes.c.in	(revision 22158)
@@ -0,0 +1,25 @@
+/*
+ * The line
+    { PXTOOLS_ERR_$X{ErrorCode}, "$X{ErrorDescription}"},
+ * (without the Xs)
+ * will be replaced by values from errorCodes.dat
+ */
+#include "pslib.h"
+#include "pxtoolsErrorCodes.h"
+
+void pxtoolsErrorRegister(void)
+{
+    static psErrorDescription errors[] = {
+       { PXTOOLS_ERR_BASE, "First value we use; lower values belong to psLib" },
+       { PXTOOLS_ERR_${ErrorCode}, "${ErrorDescription}"},
+    };
+    static int nerror = PXTOOLS_ERR_NERROR - PXTOOLS_ERR_BASE; // number of values in enum
+
+    for (int i = 0; i < nerror; i++) {
+       psErrorDescription *tmp = psAlloc(sizeof(psErrorDescription));
+       *tmp = errors[i];
+       psErrorRegister(tmp, 1);
+       psFree(tmp);			/* it's on the internal list */
+    }
+    nerror = 0;			                // don't register more than once
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtoolsErrorCodes.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtoolsErrorCodes.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtoolsErrorCodes.dat	(revision 22158)
@@ -0,0 +1,10 @@
+#
+# This file is used to generate pxtoolsErrorCodes.h
+#
+BASE = 1100		First value we use; lower values belong to psLib
+UNKNOWN			Unknown PM error code
+ARGUMENTS		Incorrect arguments
+SYS			System error
+CONFIG			Problem in configure files
+PROG			Programming error
+DATA   			invalid data
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtoolsErrorCodes.h.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtoolsErrorCodes.h.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtoolsErrorCodes.h.in	(revision 22158)
@@ -0,0 +1,18 @@
+#if !defined(PXTOOLS_ERROR_CODES_H)
+#define PXTOOLS_ERROR_CODES_H
+/*
+ * The line
+ *  PXTOOLS_ERR_$X{ErrorCode},
+ * (without the X)
+ *
+ * will be replaced by values from errorCodes.dat
+ */
+typedef enum {
+    PXTOOLS_ERR_BASE = 512,
+    PXTOOLS_ERR_${ErrorCode},
+    PXTOOLS_ERR_NERROR
+} pxtoolsErrorCode;
+
+void pxtoolsErrorRegister(void);
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtree.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtree.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtree.c	(revision 22158)
@@ -0,0 +1,239 @@
+/*
+ * pxio.c
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVB_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pslib.h>
+
+#include "pxtools.h"
+#include "pxtree.h"
+
+static void pxNodeFree(pxNode *node)
+{
+    psFree(node->name);
+    psFree(node->parent);
+    psFree(node->children);
+    psFree(node->data);
+}
+
+pxNode *pxNodeAlloc(const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(name, NULL);
+
+    pxNode *node = psAlloc(sizeof(pxNode));
+
+    node->name = psStringCopy(name);
+    node->parent = NULL;
+    node->children = psListAlloc(NULL);
+    node->data = NULL;
+
+    psMemSetDeallocator(node, (psFreeFunc) pxNodeFree);
+
+    return node;
+}
+
+pxNode *pxNodeAddParent(pxNode *node, pxNode *parent)
+{
+    // add this node to it's parent's children list
+    psListAdd(parent->children, PS_LIST_TAIL, node);
+    // and set the parent pointer
+    node->parent = psMemIncrRefCounter(parent);
+
+    return node;
+}
+
+pxNode *pxNodeAddChild(pxNode *node, pxNode *child)
+{
+    // add the child node to this nodes list of children
+    psListAdd(node->children, PS_LIST_TAIL, child);
+    // if the child already has a parent, release the ref count
+    if (child->parent) {
+        psFree(child->parent);
+    }
+    // [re]parent the child
+    child->parent = psMemIncrRefCounter(node);
+
+    return node;
+}
+
+pxNode *pxNodeAddData(pxNode *node, psPtr data)
+{
+    node->data = psMemIncrRefCounter(data);
+
+    return node;
+}
+
+void pxNodePrint(FILE *stream, pxNode *node)
+{
+    fprintf(stream, "node name: %s\n", node->name);
+    fprintf(stream, "node parent's name: %s\n", node->parent
+                                              ?  node->parent->name
+                                              : NULL);
+    psListIterator *iter = psListIteratorAlloc(node->children, 0, false);
+    pxNode *child = NULL;
+    while ((child = psListGetAndIncrement(iter))) {
+        fprintf(stream, "node child's name: %s\n", child->name);
+    }
+    psFree(iter);
+}
+
+
+static bool printNodes(void *arg, pxNode *node)
+{
+    pxNodePrint((FILE *)arg, node);
+    fprintf((FILE *)arg, "\n\n");
+
+    return true;
+}
+
+
+void pxTreePrint(FILE *stream, pxNode *root)
+{
+    pxTreeCrawl(root, printNodes, (void *)stream);
+}
+
+// func() returning false means decend no futher along this branch
+
+bool pxTreeCrawl(pxNode *node, pxNodeFunc func, void *arg)
+{
+    // if func() returns false, stop
+    if (!func(arg, node)) {
+        return false;
+    }
+
+    psListIterator *iter = psListIteratorAlloc(node->children, 0, false);
+    pxNode *child = NULL;
+    while ((child = psListGetAndIncrement(iter))) {
+        pxTreeCrawl(child, func, arg);
+    }
+    psFree(iter);
+
+    return true;
+}
+
+bool pxNodeFuncCountDependants(void *arg, pxNode *node)
+{
+    (*(int *)arg)++;
+    return true;
+}
+
+bool pxNodeHasChildren(pxNode *node)
+{
+    int children = psListLength(node->children);
+
+    return children ? true : false;
+}
+
+bool pxNodeHasGrandChildren(pxNode *node)
+{
+    // find out how many nodes there are lower in the tree
+    // subtract the parent node from the count so we have just a tally of
+    // decendants
+    int nodes = -1;
+    pxTreeCrawl(node, pxNodeFuncCountDependants, &nodes);
+    psTrace("pxtree", PS_LOG_INFO, "node %s has %d dependants", node->name, nodes);
+
+    // find out how many children this node has
+    int children = psListLength(node->children);
+    psTrace("pxtree", PS_LOG_INFO, "node %s has %d children", node->name, children);
+
+    if (!children) {
+        // no children
+        return false;
+    }
+
+    if (nodes < children) {
+        psAbort("you can't have fewer children than decendants!");
+    }
+
+    if (nodes == children) {
+        // no grandchildren
+        return false;
+    }
+
+    return true;
+}
+
+pxNode *pxTreeFromMetadata(psMetadata *md)
+{
+    psHash *forest = psHashAlloc(10);
+
+    psMetadataIterator *iter = psMetadataIteratorAlloc(md, 0, NULL);
+    psMetadataItem *item = NULL;
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        if (!(item->type == PS_DATA_STRING)) {
+            continue;
+        }
+
+        // add this node to the forest and hopefully it'll get attached to the
+        // root tree
+        pxTreeBuilder(forest, item->name, item->data.str, NULL);
+    }
+    psFree(iter);
+
+    pxNode *root = psHashLookup(forest, "root");
+    psFree(forest);
+
+    return psMemIncrRefCounter(root);
+}
+
+psHash *pxTreeBuilder(psHash *forest,
+                      const char *nodeName,
+                      const char *childName,
+                      psPtr data)
+{
+    // try to find a node with this name
+    pxNode *node = psHashLookup(forest, nodeName);
+    if (!node) {
+        // create a new node with this name
+        node = pxNodeAlloc(nodeName);
+        if (data) {
+            pxNodeAddData(node, data);
+        }
+        // add it to the hash of nodes
+        psHashAdd(forest, nodeName, node);
+        // node may be used below because it will still have a ref count of
+        // 1 from being on the hash, this is equivalent to the "view" we
+        // get from a hashlookup
+        psFree(node);
+    } else if (!node->data) {
+        pxNodeAddData(node, data);
+    }
+
+    // does this node declare a child?
+    if (childName) {
+        // try to find a node with this name
+        pxNode *child = psHashLookup(forest, childName);
+        if (!child ) {
+            // create a new node with this name
+            child = pxNodeAlloc(childName);
+            // add it to the hash of nodes
+            psHashAdd(forest, childName, child);
+            // child may be used below because it will still have a ref
+            // count of 1 from being on the hash, this is equivalent to the
+            // "view" we get from a hashlookup
+            psFree(child);
+        }
+        pxNodeAddChild(node, child);
+    }
+
+    return forest;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtree.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtree.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxtree.h	(revision 22158)
@@ -0,0 +1,72 @@
+/*
+ * pxtree.h
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PXTREE_H
+#define PXTREE_H 1
+
+#include <stdio.h>
+#include <stdbool.h>
+
+#include <pslib.h>
+
+
+typedef struct pxNode {
+  char *name;
+  struct pxNode *parent;
+  psList  *children;
+  void *data;
+} pxNode;
+
+typedef bool (*pxNodeFunc)(void *arg, pxNode *node);
+
+pxNode *pxNodeAlloc(
+    const char *name
+) PS_ATTR_MALLOC;
+
+pxNode *pxNodeAddParent(pxNode *node, pxNode *parent);
+pxNode *pxNodeAddChild(pxNode *node, pxNode *child);
+pxNode *pxNodeAddData(pxNode *node, psPtr data);
+
+void pxTreePrint(FILE *stream, pxNode *root);
+
+void pxNodePrint(
+    FILE *stream,
+    pxNode  *node
+);
+
+bool pxTreeCrawl(
+    pxNode  *node,
+    pxNodeFunc func,
+    void    *arg
+);
+
+bool pxNodeFuncCountDependants(void *arg, pxNode *node);
+
+bool pxNodeHasChildren(pxNode *node);
+
+bool pxNodeHasGrandChildren(pxNode *node);
+
+pxNode *pxTreeFromMetadata(psMetadata *md);
+
+psHash *pxTreeBuilder(psHash *forest,
+                      const char *nodeName,
+                      const char *childName,
+                      psPtr data);
+
+#endif // PXTREE_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxwarp.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxwarp.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxwarp.c	(revision 22158)
@@ -0,0 +1,157 @@
+/*
+ * pxwarp.c
+ *
+ * Copyright (C) 2007-2008  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <ippdb.h>
+#include <string.h>
+
+#include "pxtools.h"
+#include "pxwarp.h"
+
+bool pxwarpRunSetState(pxConfig *config, psS64 warp_id, const char *state)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(state, false);
+
+    // check that state is a valid string value
+    if (!pxIsValidState(state)) {
+        psError(PS_ERR_UNKNOWN, false, "invalid warpRun state: %s", state);
+        return false;
+    }
+
+    char *query = "UPDATE warpRun SET state = '%s' WHERE warp_id = %" PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, state, warp_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for warp_id %" PRId64, warp_id);
+        return false;
+    }
+
+    return true;
+}
+
+
+bool pxwarpRunSetStateByQuery(pxConfig *config, psMetadata *where, const char *state)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(state, false);
+
+    // check that state is a valid string value
+    if (!pxIsValidState(state)) {
+        psError(PS_ERR_UNKNOWN, false, "invalid chipRun state: %s", state);
+        return false;
+    }
+
+    psString query = psStringCopy("UPDATE warpRun JOIN fakeRun USING(fake_id) JOIN camRun USING(cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id) SET warpRun.state = '%s'");
+
+    if (where) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        if (whereClause && strlen(whereClause) > 0) {
+            psStringAppend(&query, " %s", whereClause);
+        }
+        psFree(whereClause);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query, state)) {
+        psFree(query);
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psFree(query);
+
+    return true;
+}
+
+
+bool pxwarpRunSetLabel(pxConfig *config, psS64 warp_id, const char *label)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    // note label == NULL should be explicitly allowed
+
+    char *query = "UPDATE warpRun SET warpRun.label = '%s' WHERE warp_id = %" PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, label, warp_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change label for warp_id %" PRId64, warp_id);
+        return false;
+    }
+
+    return true;
+}
+
+
+bool pxwarpRunSetLabelByQuery(pxConfig *config, psMetadata *where, const char *label)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    // note label == NULL should be explicitly allowed
+
+    psString query = psStringCopy("UPDATE warpRun JOIN fakeRun USING(fake_id) JOIN camRun USING(cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id) SET warpRun.label = '%s'");
+
+    if (where) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query, label)) {
+        psFree(query);
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psFree(query);
+
+    return true;
+}
+
+
+bool pxwarpQueueByFakeID(pxConfig *config,
+                    psS64 fake_id,
+                    char *workdir,
+                    char *label,
+                    char *dvodb,
+                    char *tess_id,
+                    char *end_stage)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // depend on the f-keys to make sure we have a valid cam_id
+    if (!warpRunInsert(config->dbh,
+        0,          // ID
+        fake_id,
+        "warp",     // mode
+        "new",      // state
+        workdir,
+        "dirty",    // workdir_state
+        label,
+        dvodb,
+        tess_id,
+        end_stage,
+        NULL,       // registered
+        false       // magiced
+    )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return true;
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pxwarp.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pxwarp.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pxwarp.h	(revision 22158)
@@ -0,0 +1,40 @@
+/*
+ * pxwarp.h
+ *
+ * Copyright (C) 2007-2008  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PXWARP_H
+#define PXWARP_H 1
+
+#include <pslib.h>
+
+#include "pxtools.h"
+
+bool pxwarpRunSetState(pxConfig *config, psS64 warp_id, const char *state);
+bool pxwarpRunSetStateByQuery(pxConfig *config, psMetadata *where, const char *state);
+bool pxwarpRunSetLabel(pxConfig *config, psS64 warp_id, const char *label);
+bool pxwarpRunSetLabelByQuery(pxConfig *config, psMetadata *where, const char *label);
+
+bool pxwarpQueueByFakeID(pxConfig *config,
+                    psS64 fake_id,
+                    char *workdir,
+                    char *label,
+                    char *dvodb,
+                    char *tess_id,
+                    char *end_stage);
+
+#endif // PXWARP_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pzgetexp.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pzgetexp.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pzgetexp.c	(revision 22158)
@@ -0,0 +1,368 @@
+/*
+ * pzgetexp.c
+ *
+ * Copyright (C) 2006-2008  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "pxtools.h"
+#include "pzgetexp.h"
+
+#define PRODUCT_LS_CMD "dsproductls"
+
+static bool go (pxConfig *config);
+static psArray *parseFileSets(pxConfig *config, const char *str);
+
+int main(int argc, char **argv)
+{
+    psLibInit(NULL);
+
+    pxConfig *config = pzgetexpConfig(NULL, argc, argv);
+    if (!config) {
+        psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+        goto FAIL;
+    }
+
+    if (!go(config)) {
+        goto FAIL;
+    }
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(EXIT_SUCCESS);
+
+FAIL:
+    psErrorStackPrint(stderr, "\n");
+    int exit_status = pxerrorGetExitStatus();
+    
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exit_status);
+}
+
+static bool go(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    // required
+    PXOPT_LOOKUP_STR(camera, config->args, "-inst", true, false);
+    PXOPT_LOOKUP_STR(telescope, config->args, "-telescope", true, false);
+    PXOPT_LOOKUP_STR(uri, config->args, "-uri", true, false);
+
+    //optional
+    PXOPT_LOOKUP_S32(timeout, config->args, "-timeout", false, false);
+    PXOPT_LOOKUP_BOOL(all, config->args, "-all", false);
+
+    // find last fileset/exp_name (if we have one)
+    bool haveLastFileSet = false;
+    psString lastFileSet = NULL;
+
+    // -all means "request all known filesets"
+    if (!all) {
+        char *query = "SELECT * from summitExp WHERE camera = \"%s\" and TELESCOPE = \"%s\" ORDER BY dateobs DESC LIMIT 1";
+        if (!p_psDBRunQuery(config->dbh, query, camera, telescope)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        }
+
+        psArray *output = p_psDBFetchResult(config->dbh);
+        if (!output) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        }
+        if (!psArrayLength(output)) {
+            psError(PS_ERR_UNKNOWN, false, "no summitExp rows found");
+            haveLastFileSet = false;
+            psFree(output);
+        } else {
+            haveLastFileSet = true;
+            bool status = false;
+            lastFileSet = psStringCopy(psMetadataLookupStr(&status, output->data[0], "exp_name"));
+            psFree(output);
+        }
+    }
+
+    // invoke dsproductls
+    // dsproductls --uri <> --last_fileset <>
+    psString cmd = NULL;
+    if (haveLastFileSet) {
+        psStringAppend(&cmd, "%s --uri %s --last_fileset %s",
+            PRODUCT_LS_CMD, uri, lastFileSet);
+        psFree(lastFileSet);
+    } else {
+        psStringAppend(&cmd, "%s --uri %s", PRODUCT_LS_CMD, uri);
+    }
+    if (timeout) {
+        psStringAppend(&cmd, " --timeout %d", timeout);
+    }
+
+    psTrace("pzgetexp", PS_LOG_INFO, "cmd is: %s\n", cmd);
+
+    FILE *output = popen(cmd, "r");
+    psFree(cmd);
+
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, true, "popen() failed");
+        return false;
+    }
+    psString cmdOutput = psSlurpFile(output);
+    pclose(output);
+
+    psArray *newSummitExps = parseFileSets(config, cmdOutput);
+    psFree(cmdOutput);
+    if (!newSummitExps) {
+        // XXX not nessicarily an error
+        psError(PS_ERR_UNKNOWN, true, "no new fileSet/exp IDs");
+        return false;
+    }
+    if (!psArrayLength(newSummitExps)) {
+        psTrace("pzgetexp", PS_LOG_INFO, "no new fileSet/exp IDs");
+        psFree(newSummitExps);
+        return true;
+    }
+
+    // start a transaction so it's all rows or nothing
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(newSummitExps);
+        return false;
+    }
+
+    // increase memory table size limits; deafult is 16MB
+    {
+        // 512MB
+        char *query = "SET max_heap_table_size = 1024*1024*512";
+        if (!p_psDBRunQuery(config->dbh, query)) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(newSummitExps);
+            return false;
+        }
+    }
+
+    // create a temporry table
+    {
+        char *query = "CREATE TEMPORARY TABLE incoming" 
+            " (exp_name VARCHAR(64), camera VARCHAR(64), telescope VARCHAR(64), dateobs DATETIME, exp_type VARCHAR(64), uri VARCHAR(255), PRIMARY KEY(exp_name, camera, telescope))"
+           " ENGINE=MEMORY";
+        if (!p_psDBRunQuery(config->dbh, query)) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(newSummitExps);
+            return false;
+        }
+    }
+
+    {
+        char *query = "INSERT INTO incoming (exp_name, camera, telescope, dateobs, exp_type, uri) VALUES (?, ?, ?, ?, ?, ?)";
+
+        long inserted = p_psDBRunQueryPrepared(config->dbh, newSummitExps, query);
+        if (inserted < 0) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(newSummitExps);
+            return false;
+        }
+        // sanity check that we actually inserted something
+        if (inserted == 0) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error -- we should have inserted at least one row");
+            psFree(newSummitExps);
+            return false;
+        }
+    }
+
+    psFree(newSummitExps);
+
+    // add new exps to summitExp
+    {
+        char *query = 
+            "INSERT INTO summitExp" 
+            "   SElECT"
+            "       incoming.*,"
+            "       NULL,"  // imfiles
+            "       0,"     // fault
+            "       NULL"   // epoch
+            "   FROM incoming"
+            "   LEFT JOIN summitExp"
+            "       USING(exp_name, camera, telescope)"
+            "   WHERE"
+            "       summitExp.exp_name is NULL"
+            "       AND summitExp.camera is NULL"
+            "       AND summitExp.telescope is NULL";
+
+        if (!p_psDBRunQuery(config->dbh, query)) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        }
+    }
+    
+    // point of no return
+    if (!psDBCommit(config->dbh)) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+static psArray *parseFileSets(pxConfig *config, const char *str)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_PTR_NON_NULL(str, NULL);
+    
+    // these are constants for all records parsed -- look them up before we do
+    // any work
+    // required
+    PXOPT_LOOKUP_STR(camera, config->args, "-inst", true, false);
+    PXOPT_LOOKUP_STR(telescope, config->args, "-telescope", true, false);
+
+    // split the string into lines
+    psList *doc = psStringSplit(str, "\n", false);
+
+    psListIterator *lineCursor = psListIteratorAlloc(doc, 0, false);
+
+    psArray *summitExps = psArrayAllocEmpty(psListLength(doc));
+    psString line;
+    while ((line = psListGetAndIncrement(lineCursor))) {
+        psTrace("pzgetimfile", PS_LOG_INFO, "parsing line: %s\n", line);
+
+        // split line into tokens
+        psList *tokens = psStringSplit(line, " ", false);
+
+        // check to see if this line is a comment (or if the first token is
+        // NULL)
+        if (!psListGet(tokens, 0) || *((char *)psListGet(tokens, 0)) == '#') {
+            psFree(tokens);
+            continue;
+        }
+
+        // check that we have the right number of tokens
+        // print "# uri fileset datetime type\n";
+        if (psListLength(tokens) != 4) {
+            // error
+            return false;
+        }
+
+        // find the values of interest
+        psListIterator *tokenCursor = psListIteratorAlloc(tokens, 0, false);
+        char *uri       = psListGetAndIncrement(tokenCursor);
+        char *exp_name    = psListGetAndIncrement(tokenCursor); // fileset
+        char *dateobsStr= psListGetAndIncrement(tokenCursor); // datetime
+        char *exp_type  = psListGetAndIncrement(tokenCursor); // type
+
+        // create a new metadata to represent this line and it's values
+        psMetadata *md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_name", 0, NULL, exp_name)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item exp_name");
+            psFree(md);
+            psFree(tokenCursor);
+            psFree(tokens);
+            return NULL;
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, camera)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+            psFree(md);
+            psFree(tokenCursor);
+            psFree(tokens);
+            return NULL;
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, telescope)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+            psFree(md);
+            psFree(tokenCursor);
+            psFree(tokens);
+            return NULL;
+        }
+        psTime *dateobs = psTimeFromISO(dateobsStr, PS_TIME_UTC);
+        if (!psMetadataAddTime(md, PS_LIST_TAIL, "dateobs", 0, NULL, dateobs)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+            psFree(dateobs);
+            psFree(md);
+            psFree(tokenCursor);
+            psFree(tokens);
+            return NULL;
+        }
+        psFree(dateobs);
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, exp_type)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+            psFree(md);
+            psFree(tokenCursor);
+            psFree(tokens);
+            return NULL;
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, uri)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+            psFree(md);
+            psFree(tokenCursor);
+            psFree(tokens);
+            return NULL;
+        }
+
+        // must be freed after the new metadata is built -- holds the strings
+        psFree(tokenCursor);
+        psFree(tokens);
+
+        // add the new metadata to the result set
+        psArrayAdd(summitExps, 0, md);
+
+        // debugging
+        if (psTraceGetLevel("pzgetexp") == PS_LOG_INFO) {
+            psString doc = psMetadataConfigFormat(md);
+            psTrace("pzgetexp", PS_LOG_INFO, "parsed line as:\n %s\n", doc);
+            psFree(doc);
+        }
+
+        psFree(md);
+
+    }
+
+    psFree(lineCursor);
+    psFree(doc);
+
+    return summitExps;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pzgetexp.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pzgetexp.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pzgetexp.h	(revision 22158)
@@ -0,0 +1,27 @@
+/*
+ * pzgetexp.h
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PZGETEXP_H
+#define PZGETEXP_H 1
+
+#include "pxtools.h"
+
+pxConfig *pzgetexpConfig(pxConfig *config, int argc, char **argv);
+
+#endif // PZGETEXP_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pzgetexpConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pzgetexpConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pzgetexpConfig.c	(revision 22158)
@@ -0,0 +1,88 @@
+/*
+ * pzgetexpConfig.c
+ *
+ * Copyright (C) 2006-2008  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "pxtools.h"
+
+pxConfig *pzgetexpConfig(pxConfig *config, int argc, char **argv)
+{
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    pmConfigReadParamsSet(false);
+
+    config->modules = pmConfigRead(&argc, argv, NULL);
+    if (! config->modules) {
+        psError(PS_ERR_UNKNOWN, false, "Can't find site configuration!\n");
+        psFree(config);
+        return NULL;
+    }
+
+    psMetadata *args = psMetadataAlloc();
+    psMetadataAddStr(args , PS_LIST_TAIL, "-uri", 0,
+        "DataStore product URI (required)", "");
+    psMetadataAddStr(args , PS_LIST_TAIL, "-inst", 0,
+        "camera name (required)", "");
+    psMetadataAddStr(args , PS_LIST_TAIL, "-telescope",  0,
+        "telescope name (required)", "");
+    psMetadataAddS32(args, PS_LIST_TAIL, "-timeout",  0,
+        "HTTP timeout", 0);
+    psMetadataAddBool(args, PS_LIST_TAIL, "-all",  0,
+        "download ALL filesets", 0);
+
+
+    bool status = false;
+    if (!psArgumentParse(args, &argc, argv)
+        || argc != 1
+        || strcmp(psMetadataLookupStr(&status, args, "-uri"), "") == 0
+        || strcmp(psMetadataLookupStr(&status, args, "-inst"), "") == 0
+        || strcmp(psMetadataLookupStr(&status, args, "-telescope"), "") == 0
+    ) {
+        fprintf(stderr, "error parsing arguments\n");
+        printf("\nPan-STARRS Phase Z Get Exposures Tool\n");
+        printf("Usage: %s -uri <uri> -inst <camera> -telescope <telescope> [-timeout <n>]\n\n",
+            argv[0]);
+        psArgumentHelp(args);
+        psFree(config);
+        return NULL;
+    }
+
+    config->args = args;
+    // don't free args here as it's silly to increment the ref count then
+    // "free" it
+
+    // define Database handle, if used
+    config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+    if(!config->dbh) {
+        psError(PS_ERR_UNKNOWN, false, "Can't connect to db\n");
+        psFree(config);
+        return NULL;
+    }
+
+    return config;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pzgetimfiles.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pzgetimfiles.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pzgetimfiles.c	(revision 22158)
@@ -0,0 +1,482 @@
+/*
+ * pzgetimfiles.c
+ *
+ * Copyright (C) 2006-2008  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "pxtag.h"
+#include "pxtools.h"
+#include "pzgetimfiles.h"
+
+#define FILESET_LS_CMD "dsfilesetls"
+
+static bool go (pxConfig *config);
+static psArray *parseFiles(pxConfig *config, const char *str);
+
+int main(int argc, char **argv)
+{
+    psLibInit(NULL);
+
+    pxConfig *config = pzgetimfilesConfig(NULL, argc, argv);
+    if (!config) {
+        psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+        goto FAIL;
+    }
+
+    if (!go(config)) {
+        goto FAIL;
+    }
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(EXIT_SUCCESS);
+
+FAIL:
+    psErrorStackPrint(stderr, "\n");
+    int exit_status = pxerrorGetExitStatus();
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exit_status);
+}
+
+static bool go(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    // required
+    PXOPT_LOOKUP_STR(uri, config->args, "-uri", true, false);
+    PXOPT_LOOKUP_STR(filesetid, config->args, "-filesetid", true, false);
+    PXOPT_LOOKUP_STR(camera, config->args, "-inst", true, false);
+    PXOPT_LOOKUP_STR(telescope, config->args, "-telescope", true, false);
+
+    // optional
+    PXOPT_LOOKUP_S32(timeout, config->args, "-timeout", false, false);
+
+    // invoke dsfilesetls
+    psString cmd = NULL;
+    psStringAppend(&cmd, "%s --uri %s", FILESET_LS_CMD, uri);
+    if (timeout) {
+        psStringAppend(&cmd, " --timeout %d", timeout);
+    }
+
+    psTrace("pzgetimfiles", PS_LOG_INFO, "cmd is: %s\n", cmd);
+
+    FILE *output = popen(cmd, "r");
+    psFree(cmd);
+
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, true, "popen() failed");
+        return false;
+    }
+
+    psString cmdOutput = psSlurpFile(output);
+    int status = pclose(output);
+
+    if (status != 0) {
+        // mark the summitExp row as faulted
+        if (!p_psDBRunQuery(config->dbh, "UPDATE summitExp SET fault = %d WHERE exp_name = '%s' AND camera = '%s' AND telescope = '%s'", WEXITSTATUS(status), filesetid, camera, telescope)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+
+        psError(PS_ERR_UNKNOWN, true, "%s failed with exit status %d",
+            FILESET_LS_CMD, WEXITSTATUS(status));
+        psFree(cmdOutput);
+        return false;
+    }
+
+    // prase output of dsfilesetls
+    psArray *newImfiles = parseFiles(config, cmdOutput);
+    if (!newImfiles) {
+        // XXX not nessicarily an error
+        psError(PS_ERR_UNKNOWN, true, "no new files/imfiles");
+        psFree(cmdOutput);
+        return false;
+    }
+    psFree(cmdOutput);
+    
+    // save the number of new Imfiles;
+    long imfiles = psArrayLength(newImfiles);
+
+    // start a transaction so it's all rows or nothing
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // if the fileset was empty (no files) then we can bail out early
+    if (imfiles == 0) {
+        psFree(newImfiles);
+
+        char *query = 
+            "UPDATE summitExp"
+            " SET imfiles = %d"
+            " WHERE exp_name = '%s'"
+            " AND camera = '%s'"
+            " AND telescope = '%s'";
+        if (!p_psDBRunQuery(config->dbh, query, imfiles, filesetid, camera, telescope)) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        }
+
+        // remove the pzDownloadExp entry for this exp (fileset)
+        {
+            char *query = 
+                "DELETE FROM pzDownloadExp"
+                " WHERE"
+                "   exp_name = '%s'"
+                "   AND camera = '%s'"
+                "   AND telescope = '%s'";
+            if (!p_psDBRunQuery(config->dbh, query, filesetid, camera, telescope)) {
+                // rollback
+                if (!psDBRollback(config->dbh)) {
+                    psError(PS_ERR_UNKNOWN, false, "database error");
+                }
+                psError(PS_ERR_UNKNOWN, false, "database error");
+                return false;
+            }
+
+            // sanity check: we should have removed only one row
+            psU64 affected = psDBAffectedRows(config->dbh);
+            if (psDBAffectedRows(config->dbh) != 1) {
+                // rollback
+                if (!psDBRollback(config->dbh)) {
+                    psError(PS_ERR_UNKNOWN, false, "database error");
+                }
+                psError(PS_ERR_UNKNOWN, false, "should have affected 1 row but %" PRIu64 " rows were modified", affected);
+                return false;
+            }
+        }
+ 
+        // point of no return
+        if (!psDBCommit(config->dbh)) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        }
+
+        return true;
+    } 
+
+    // create a temp table
+    {
+        char *query = 
+            "CREATE TEMPORARY TABLE incoming (exp_name VARCHAR(64), camera VARCHAR(64), telescope VARCHAR(64), file_id VARCHAR(64), bytes INT, md5sum VARCHAR(32), class VARCHAR(64), class_id VARCHAR(64), uri VARCHAR(255), PRIMARY KEY(exp_name, camera, telescope, class, class_id)) ENGINE=MEMORY";
+
+        if (!p_psDBRunQuery(config->dbh, query)) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(newImfiles);
+            return false;
+        }
+    }
+
+    // load the imfiles (files) into the temp table
+    {
+        char *query = "INSERT INTO incoming (exp_name, camera, telescope, file_id, bytes, md5sum, class, class_id, uri) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
+
+        long inserted = p_psDBRunQueryPrepared(config->dbh, newImfiles, query);
+        if (inserted < 0) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(newImfiles);
+            return false;
+        }
+        // sanity check that we actually inserted something
+        if (inserted == 0) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error -- we should have inserted at least one row");
+            psFree(newImfiles);
+            return false;
+        }
+    }
+
+    psFree(newImfiles);
+
+    // copy imfiles (files) from the temp table into summitImfiles
+    {
+        char *query = 
+            "INSERT IGNORE INTO summitImfile" 
+            "   SELECT"
+            "       incoming.exp_name,"
+            "       incoming.camera,"
+            "       incoming.telescope,"
+            "       incoming.file_id,"
+            "       incoming.bytes,"
+            "       incoming.md5sum,"
+            "       incoming.class,"
+            "       incoming.class_id,"
+            "       incoming.uri,"
+            "       NULL"       // epoch
+            "   FROM incoming";
+        if (!p_psDBRunQuery(config->dbh, query)) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        }
+    }
+
+    // update summitExp.imfiles (should have been NULL)
+    {
+        char *query = 
+            "UPDATE summitExp"
+            " SET imfiles = (SELECT COUNT(*) FROM summitImfile"
+            "   WHERE"
+            "       exp_name = '%s'"
+            "       AND camera = '%s'"
+            "       AND telescope = '%s'"
+            ")" 
+            " WHERE"
+            "   exp_name = '%s'"
+            "   AND camera = '%s'"
+            "   AND telescope = '%s'"
+            "   AND imfiles IS NULL";
+        if (!p_psDBRunQuery(config->dbh, query, filesetid, camera, telescope, filesetid, camera, telescope)) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        }
+
+        // sanity check: we should have updated only one row
+        psU64 affected = psDBAffectedRows(config->dbh);
+        if (psDBAffectedRows(config->dbh) != 1) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "should have affected 1 row but %" PRIu64 " rows were modified", affected);
+            return false;
+        }
+    }
+
+    // add new exps to pzDownloadExp -- must be done before the new exps are
+    // added to summitExp because of the SQL logic
+    {
+        char *query = 
+            "INSERT IGNORE INTO pzDownloadExp" 
+            "   SELECT"
+            "       incoming.exp_name,"
+            "       incoming.camera,"
+            "       incoming.telescope,"
+            "       \"run\","    // state
+            "       NULL"
+            "   FROM incoming"
+            "   GROUP BY"
+            "       incoming.exp_name,"
+            "       incoming.camera,"
+            "       incoming.telescope";
+
+        if (!p_psDBRunQuery(config->dbh, query)) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        }
+    }
+
+    // point of no return
+    if (!psDBCommit(config->dbh)) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+static psArray *parseFiles(pxConfig *config, const char *str)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_PTR_NON_NULL(str, NULL);
+
+    // these are constants for all records parsed -- look them up before we do
+    // any work
+    PXOPT_LOOKUP_STR(exp_name, config->args, "-filesetid", true, false);
+    PXOPT_LOOKUP_STR(camera, config->args, "-inst", true, false);
+    PXOPT_LOOKUP_STR(telescope, config->args, "-telescope", true, false);
+
+    // split the string into lines
+    psList *doc = psStringSplit(str, "\n", false);
+
+    psListIterator *lineCursor = psListIteratorAlloc(doc, 0, false);
+
+    psArray *pzPendingImfiles = psArrayAllocEmpty(psListLength(doc));
+    psString line;
+    while ((line = psListGetAndIncrement(lineCursor))) {
+        psTrace("pzgetimfiles", PS_LOG_INFO, "parsing line: %s\n", line);
+
+        // split line into tokens
+        psList *tokens = psStringSplit(line, " ", false);
+
+        // check to see if this line is a comment (or if the first token is
+        // NULL)
+        if (!psListGet(tokens, 0) || *((char *)psListGet(tokens, 0)) == '#') {
+            psFree(tokens);
+            continue;
+        }
+
+        // check that we have the right number of tokens
+        // print "# uri fileid bytes md5sum type \n";
+        if (!psListLength(tokens) > 5) {
+            psError(PS_ERR_UNKNOWN, true, "invalid line format: %s", line);
+            psFree(tokens);
+            psFree(pzPendingImfiles);                
+            psFree(lineCursor);
+            psFree(doc);
+            return false;
+        }
+
+        // find the values of interest
+        psListIterator *tokenCursor = psListIteratorAlloc(tokens, 0, false);
+        char *uri       = psListGetAndIncrement(tokenCursor);
+        char *file_id   = psListGetAndIncrement(tokenCursor); // fileid
+        char *bytes     = psListGetAndIncrement(tokenCursor); // bytes
+        char *md5sum    = psListGetAndIncrement(tokenCursor); // md5sum
+        char *class     = psListGetAndIncrement(tokenCursor); // type
+        char *class_id  = psListGetAndIncrement(tokenCursor); // chipname
+
+        // create a new metadata to represent this line and it's values
+        psMetadata *md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_name", 0, NULL, exp_name)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item exp_name");
+            psFree(md);
+            psFree(tokenCursor);
+            psFree(tokens);
+            return NULL;
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, camera)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+            psFree(md);
+            psFree(tokenCursor);
+            psFree(tokens);
+            return NULL;
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, telescope)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+            psFree(md);
+            psFree(tokenCursor);
+            psFree(tokens);
+            return NULL;
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "file_id", 0, NULL, file_id)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item bytes");
+            psFree(md);
+            psFree(tokenCursor);
+            psFree(tokens);
+            return NULL;
+        }
+        if (!psMetadataAddS64(md, PS_LIST_TAIL, "bytes", 0, NULL, (psS64)atoll(bytes))) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item bytes");
+            psFree(md);
+            psFree(tokenCursor);
+            psFree(tokens);
+            return NULL;
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "md5sum", 0, NULL, md5sum)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item md5sum");
+            psFree(md);
+            psFree(tokenCursor);
+            psFree(tokens);
+            return NULL;
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class", 0, NULL, class)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item class");
+            psFree(md);
+            psFree(tokenCursor);
+            psFree(tokens);
+            return NULL;
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, class_id)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+            psFree(md);
+            psFree(tokenCursor);
+            psFree(tokens);
+            return NULL;
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, uri)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+            psFree(md);
+            psFree(tokenCursor);
+            psFree(tokens);
+            return NULL;
+        }
+
+        // must be freed after the new metadata is built -- holds the strings
+        psFree(tokenCursor);
+        psFree(tokens);
+
+        // debugging
+        if (psTraceGetLevel("pzgetimfiles") >= PS_LOG_INFO) {
+            psString doc = psMetadataConfigFormat(md);
+            psTrace("pzgetimfiles", PS_LOG_INFO, "parsed line as:\n %s\n", doc);
+            psFree(doc);
+        }
+
+        psArrayAdd(pzPendingImfiles, 0, md);
+
+        psFree(md);
+    }
+
+    psFree(lineCursor);
+    psFree(doc);
+
+    if (!psArrayLength(pzPendingImfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "string contained no valid rows");
+        psFree(pzPendingImfiles);
+        return false;
+    }
+
+    return pzPendingImfiles;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pzgetimfiles.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pzgetimfiles.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pzgetimfiles.h	(revision 22158)
@@ -0,0 +1,27 @@
+/*
+ * pzgetimfiles.h
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PZGETIMFILES_H
+#define PZGETIMFILES 1
+
+#include "pxtools.h"
+
+pxConfig *pzgetimfilesConfig(pxConfig *config, int argc, char **argv);
+
+#endif // PZGETIMFILES_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pzgetimfilesConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pzgetimfilesConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pzgetimfilesConfig.c	(revision 22158)
@@ -0,0 +1,89 @@
+/*
+ * pzgetimfilesConfig.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "pxtools.h"
+
+pxConfig *pzgetimfilesConfig(pxConfig *config, int argc, char **argv)
+{
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    pmConfigReadParamsSet(false);
+
+    config->modules = pmConfigRead(&argc, argv, NULL);
+    if (! config->modules) {
+        psError(PS_ERR_UNKNOWN, false, "Can't find site configuration!\n");
+        psFree(config);
+        return NULL;
+    }
+
+    psMetadata *args = psMetadataAlloc();
+    psMetadataAddStr(args , PS_LIST_TAIL, "-uri", 0,
+            "DataStore FileSet URI (required)", NULL);
+    psMetadataAddStr(args , PS_LIST_TAIL, "-filesetid", 0,
+            "FileSet ID (required)", NULL);
+    psMetadataAddStr(args, PS_LIST_TAIL, "-inst",  0,
+            "Camera ID (required)", NULL);
+    psMetadataAddStr(args, PS_LIST_TAIL, "-telescope",  0,
+            "Telescope ID (required)", NULL);
+    psMetadataAddS32(args, PS_LIST_TAIL, "-timeout",  0,
+            "HTTP timeout", 0);
+
+
+    bool status = false;
+    if (!psArgumentParse(args, &argc, argv)
+        || argc != 1
+        || (psMetadataLookupStr(&status, args, "-uri") == NULL)
+        || (psMetadataLookupStr(&status, args, "-filesetid") == NULL)
+        || (psMetadataLookupStr(&status, args, "-inst") == NULL)
+        || (psMetadataLookupStr(&status, args, "-telescope") == NULL)
+    ) {
+        fprintf(stderr, "error parsing arguments\n");
+        printf("\nPan-STARRS Phase Z Get Imfiles Tool\n");
+        printf("Usage: %s -uri <uri> -filesetid <id> -inst <camera> -telescope <telescope [-timeout <n>]\n\n", argv[0]);
+        psArgumentHelp(args);
+        psFree(args);
+        psFree(config);
+        return NULL;
+    }
+
+    config->args = args;
+    // don't free args here as it's silly to increment the ref count then
+    // "free" it
+
+    // define Database handle, if used
+    config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+    if(!config->dbh) {
+        psError(PS_ERR_UNKNOWN, false, "Can't connect to db\n");
+        psFree(config);
+        return NULL;
+    }
+
+    return config;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pztool.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pztool.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pztool.c	(revision 22158)
@@ -0,0 +1,916 @@
+/*
+ * pztool.c
+ *
+ * Copyright (C) 2006-2008  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "pslib.h"
+#include "pxtools.h"
+#include "pxdata.h"
+#include "pztool.h"
+
+static bool adddatastoreMode(pxConfig *config);
+static bool datastoreMode(pxConfig *config);
+static bool seenMode(pxConfig *config);
+static bool pendingExpMode(pxConfig *config);
+static bool pendingImfileMode(pxConfig *config);
+
+static bool copydoneMode(pxConfig *config);
+static bool copiedMode(pxConfig *config);
+static bool updatecopiedMode(pxConfig *config);
+static bool revertcopiedMode(pxConfig *config);
+
+static bool clearcommonfaultsMode(pxConfig *config);
+static bool advanceMode(pxConfig *config);
+
+static bool copydoneCompleteExp(pxConfig *config, const char *exp_name, const char *camera, const char *telescope);
+static psArray *pzGetPendingCameras(pxConfig *config);
+static psArray *pzArrayZip(psArray *arraySet, psS64 limit);
+static bool pzDownloadExpSetState(pxConfig *config, const char *exp_name, const char *camera, const char *telescope, const char *state);
+
+# define MODECASE(caseName, func) \
+    case caseName: \
+    if (!func(config)) { \
+                goto FAIL; \
+            } \
+    break;
+
+
+int main(int argc, char **argv)
+{
+    psLibInit(NULL);
+
+    pxConfig *config = pztoolConfig(NULL, argc, argv);
+    if (!config) {
+        psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+        goto FAIL;
+    }
+
+    switch (config->mode) {
+        MODECASE(PZTOOL_MODE_ADDDATASTORE, adddatastoreMode);
+        MODECASE(PZTOOL_MODE_DATASTORE, datastoreMode);
+        MODECASE(PZTOOL_MODE_SEEN, seenMode);
+        MODECASE(PZTOOL_MODE_PENDINGEXP, pendingExpMode);
+        MODECASE(PZTOOL_MODE_PENDINGIMFILE, pendingImfileMode);
+        MODECASE(PZTOOL_MODE_COPYDONE, copydoneMode);
+        MODECASE(PZTOOL_MODE_COPIED, copiedMode);
+        MODECASE(PZTOOL_MODE_UPDATECOPIED, updatecopiedMode);
+        MODECASE(PZTOOL_MODE_REVERTCOPIED, revertcopiedMode);
+        MODECASE(PZTOOL_MODE_CLEARCOMMONFAULTS, clearcommonfaultsMode);
+        MODECASE(PZTOOL_MODE_ADVANCE, advanceMode);
+        default:
+            psAbort("invalid option (this should not happen)");
+    }
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(EXIT_SUCCESS);
+
+FAIL:
+    psErrorStackPrint(stderr, "\n");
+    int exit_status = pxerrorGetExitStatus();
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exit_status);
+}
+
+static bool adddatastoreMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required
+    PXOPT_LOOKUP_STR(camera, config->args, "-inst", true, false);
+    PXOPT_LOOKUP_STR(telescope, config->args, "-telescope", true, false);
+    PXOPT_LOOKUP_STR(uri, config->args, "-uri", true, false);
+
+    if (!pzDataStoreInsert(config->dbh,
+            camera,
+            telescope,
+            uri,
+            NULL  // epoch
+        )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+static bool datastoreMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    if (!p_psDBRunQuery(config->dbh, "SELECT * FROM pzDataStore")) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("pztool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "pzDataStore", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool seenMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where,  "-exp_name",     "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where,  "-inst",         "camera", "==");
+    PXOPT_COPY_STR(config->args, where,  "-telescope",    "telescope", "==");
+    PXOPT_COPY_STR(config->args, where,  "-exp_type",     "exp_type", "==");
+
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = psStringCopy("SELECT * FROM summitExp");
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "summitExp");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("pztool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "summitExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool pendingExpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where,  "-exp_name",     "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where,  "-inst",         "camera", "==");
+    PXOPT_COPY_STR(config->args, where,  "-telescope",    "telescope", "==");
+    PXOPT_COPY_STR(config->args, where,  "-exp_type",     "exp_type", "==");
+
+    PXOPT_LOOKUP_BOOL(desc, config->args, "-desc", false);
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // XXX leave this query here ?
+    psString query = psStringCopy(
+            "SELECT"
+            "   summitExp.*"
+            " FROM summitExp"
+            " LEFT JOIN pzDownloadExp"
+            "   USING(exp_name, camera, telescope)"
+            " WHERE"
+            "   pzDownloadExp.exp_name IS NULL"
+            "   AND pzDownloadExp.camera IS NULL"
+            "   AND pzDownloadExp.telescope IS NULL"
+            "   AND summitExp.fault = 0"
+        );
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "pzDownloadExp");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    psStringAppend(&query, " ORDER BY summitExp.dateobs");
+    if (desc) {
+        psStringAppend(&query, " DESC");
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("pztool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "pzDownloadExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool pendingImfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where,  "-exp_name",     "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where,  "-inst",         "camera", "==");
+    PXOPT_COPY_STR(config->args, where,  "-telescope",    "telescope", "==");
+    PXOPT_COPY_STR(config->args, where,  "-exp_type",     "exp_type", "==");
+
+    PXOPT_LOOKUP_BOOL(desc, config->args, "-desc", false);
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psArray *cameras = pzGetPendingCameras(config);
+    if (!cameras) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to find any cameras");
+        return false;
+    }
+
+    // array to hold the aggregate results
+    psArray *cameraImfiles = psArrayAlloc(0);
+
+    for (long i = 0; i < psArrayLength(cameras); i++) {
+        psString query = pxDataGet("pztool_pendingimfile.sql");
+        if (!query) {
+            psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+            psFree(cameraImfiles);
+            return false;
+        }
+
+        bool status;
+        psString camera = psMetadataLookupStr(&status, cameras->data[i], "camera");
+        psStringAppend(&query, " WHERE camera = \"%s\"", camera);
+
+        if (psListLength(where->list)) {
+            psString whereClause = psDBGenerateWhereConditionSQL(where, "pzDownloadImfile");
+            psStringAppend(&query, " AND %s", whereClause);
+            psFree(whereClause);
+        }
+
+        psStringAppend(&query, " ORDER BY dateobs");
+        if (desc) {
+            psStringAppend(&query, " DESC");
+        }
+
+        // request the full "limit" from each known camera and throw away any
+        // "extra" rows that we may have after merging the results.  This is
+        // a lot simplier than a complicated scheme (tried that) to attempt to
+        // request on the right number of rows for each camera
+        
+        // treat limit == 0 as "no limit"
+        if (limit) {
+            psString limitString = psDBGenerateLimitSQL(limit);
+            psStringAppend(&query, " %s", limitString);
+            psFree(limitString);
+        }
+
+        if (!p_psDBRunQuery(config->dbh, query)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(query);
+            psFree(cameraImfiles);
+            return false;
+        }
+        psFree(query);
+
+        psArray *result = p_psDBFetchResult(config->dbh);
+        if (!result) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(cameraImfiles);
+            return false;
+        }
+        if (!psArrayLength(result)) {
+            psTrace("pztool", PS_LOG_INFO, "no rows found");
+            psFree(result);
+            continue;
+        }
+
+        // add this query into the array of result set
+        psArrayAdd(cameraImfiles, 0, result);
+        psFree(result);
+    }
+    psFree(where);
+
+    // stitch the arrays of imfiles together
+    psArray *output = pzArrayZip(cameraImfiles, limit);
+    psFree(cameraImfiles);
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "pzDownloadImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool copydoneMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required
+    PXOPT_LOOKUP_STR(exp_name, config->args, "-exp_name", true, false);
+    PXOPT_LOOKUP_STR(camera, config->args, "-inst", true, false);
+    PXOPT_LOOKUP_STR(telescope, config->args, "-telescope", true, false);
+    PXOPT_LOOKUP_STR(class, config->args, "-class", true, false);
+    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false);
+    PXOPT_LOOKUP_STR(uri, config->args, "-uri", true, false);
+
+    // default values
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+
+    // NOTE : the rest of the command-line args are parsed in copydoneCompleteExp
+
+    if (!pzDownloadImfileInsert(config->dbh,
+            exp_name,
+            camera,
+            telescope,
+            class,
+            class_id,
+            uri,
+            code,
+            NULL    // epoch
+    )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // start a transaction so it's all rows or nothing
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!copydoneCompleteExp(config, exp_name, camera, telescope)) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "copydoneCompleteExp() failed");
+        return false;
+    }
+
+    // point of no return
+    if (!psDBCommit(config->dbh)) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+static bool copydoneCompleteExp(pxConfig *config, const char *exp_name, const char *camera, const char *telescope)
+{
+    // THIS FUNCTION MUST BE INVOKED FROM INSIDE A TRANSACTION!!!
+    
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // XXX this is an ugly hack!
+    // we are passing exp level info to a imfile level mode (-copydone)
+    // these options are thrown away unless we just -copydone'd the last imfile
+    // in an exp.  
+ 
+    // optional
+    PXOPT_LOOKUP_STR(workdir, config->args, "-workdir", false, false);
+    PXOPT_LOOKUP_STR(dvodb, config->args, "-dvodb", false, false);
+    PXOPT_LOOKUP_STR(tess_id, config->args, "-tess_id", false, false);
+    PXOPT_LOOKUP_STR(end_stage, config->args, "-end_stage", false, false);
+    PXOPT_LOOKUP_STR(label, config->args, "-label", false, false);
+
+    // find all exposures that have had all of their imfiles downloaded but do
+    // not appear in newExp
+    psString query = pxDataGet("pztool_find_completed_exp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // XXX this is a bit ugly : could just use the PXOPT_COPY_* methods 
+    // and not pass exp_name, camera, or telescope as additional args
+    psMetadata *where = psMetadataAlloc();
+    if (exp_name) {
+        if (!psMetadataAddStr(where, PS_LIST_TAIL, "exp_name", 0, "==", exp_name)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item exp_name");
+            psFree(where);
+            return false;
+        }
+    }
+
+    if (camera) {
+        if (!psMetadataAddStr(where, PS_LIST_TAIL, "camera", 0, "==", camera)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+            psFree(where);
+            return false;
+        }
+    }
+
+    if (telescope) {
+        if (!psMetadataAddStr(where, PS_LIST_TAIL, "telescope", 0, "==", telescope)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+            psFree(where);
+            return false;
+        }
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("pztool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+   for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *row = output->data[i];
+
+        pzDownloadExpRow *doneExp = pzDownloadExpObjectFromMetadata(row);
+        if (!doneExp) {
+            psError(PS_ERR_UNKNOWN, false, "pzDownloadExpObjectFromMetadata() failed");
+            psFree(doneExp);
+            psFree(output);
+            return false;
+        }
+
+        if (!newExpInsert(config->dbh,
+                    0x0,                // exp_id
+                    doneExp->exp_name,  // tmp_exp_name
+                    doneExp->camera,    // tmp_camera
+                    doneExp->telescope, // tmp_telescope
+                    "run",              // state
+                    workdir,            // workdir
+                    "dirty",            // workdir state
+                    NULL,               // reduction class
+                    dvodb,              // dvodb
+                    tess_id,            // tess_id
+                    end_stage,          // end_stage
+                    label,
+                    NULL                // epoch
+                )
+        ) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(doneExp);
+            psFree(output);
+            return false;
+        }
+
+        psS64 exp_id = psDBLastInsertID(config->dbh);
+
+        // insert newImfiles
+        {
+            char *query =
+                "INSERT INTO newImfile"
+                "   SElECT"
+                "       %" PRId64 "," // exp_id
+                "       pzDownloadImfile.class_id," // tmp_class_id
+                "       pzDownloadImfile.uri," // uri
+                "       NULL" // epoch
+                "   FROM pzDownloadImfile"
+                "   WHERE"
+                "       pzDownloadImfile.exp_name = '%s'"
+                "       AND pzDownloadImfile.camera = '%s'"
+                "       AND pzDownloadImfile.telescope = '%s'";
+
+            if (!p_psDBRunQuery(config->dbh, query, exp_id, doneExp->exp_name, doneExp->camera, doneExp->telescope)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+                psFree(doneExp);
+                psFree(output);
+                return false;
+            } 
+
+            // sanity check: we should have inserted at least one row
+            psU64 affected = psDBAffectedRows(config->dbh);
+            if (psDBAffectedRows(config->dbh) < 1) {
+                psError(PS_ERR_UNKNOWN, false, "should have affected at least 1 row but %" PRIu64 " rows were modified", affected);
+                psFree(doneExp);
+                psFree(output);
+                return false;
+            }
+        }
+
+        // set pzDownloadExp.state to 'stop'
+        if (!pzDownloadExpSetState(config, doneExp->exp_name, doneExp->camera, doneExp->telescope, "stop")) {
+            psError(PS_ERR_UNKNOWN, false, "failed to change pzDownloadExp.state for %s:%s:%s", doneExp->exp_name, doneExp->camera, doneExp->telescope);
+            psFree(doneExp);
+            psFree(output);
+            return false;
+        }
+
+        psFree(doneExp);
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static psArray *pzGetPendingCameras(pxConfig *config)
+{
+    // get a list of cameras we've seen exps for
+    if (!p_psDBRunQuery(config->dbh, "SELECT DISTINCT camera FROM pzDownloadExp")) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psArray *cameras = p_psDBFetchResult(config->dbh);
+    if (!cameras) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return NULL;
+    }
+    if (!psArrayLength(cameras)) {
+        psTrace("pztool", PS_LOG_INFO, "no rows found");
+        psFree(cameras);
+        return psArrayAlloc(0);
+    }
+
+    return cameras;
+}
+
+static psArray *pzArrayZip(psArray *arraySet, psS64 limit)
+{
+    // figure out the combined size of all arrays in the set
+    long setSize = 0;
+    for (long i = 0; i < psArrayLength(arraySet); i++) {
+        setSize += psArrayLength(arraySet->data[i]);
+    }
+
+    // treat 0 as "no limit"
+    if (limit == 0) {
+        limit = setSize;
+    }
+
+    psArray *output = psArrayAllocEmpty(limit);
+    // loop over each array in the set forever
+    for (
+            // init
+            long counter = 0,   // the total number of elements zipped so far
+            i = 0,              // which array in the set 
+            index = 0;          // the depth into each array
+            // test
+            (counter < setSize)
+            && (counter < limit)
+            && (i < psArrayLength(arraySet));
+            // incr
+            counter++, ++i,
+            i = i % psArrayLength(arraySet),
+            i % psArrayLength(arraySet) ? : ++index
+        ) {
+
+        psArray *array = arraySet->data[i];
+        // make sure that this array has not run out of elements
+        if (!(index < psArrayLength(array))) {
+            continue;
+        }
+
+        psArrayAdd(output, 0, array->data[index]);
+    }
+
+    return output;
+}
+
+
+static bool copiedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+
+    PXOPT_COPY_STR(config->args, where,  "-exp_name", "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where, "-inst", "inst", "==");
+    PXOPT_COPY_STR(config->args, where, "-telescope", "telescope", "==");
+    PXOPT_COPY_STR(config->args, where,  "-class", "class", "==");
+    PXOPT_COPY_STR(config->args, where,  "-class_id", "class_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
+
+    psString query = psStringCopy("SELECT * FROM pzDownloadImfile");
+
+    if (faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", "WHERE pzDownloadImfile.fault != 0");
+    } else {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", "WHERE pzDownloadImfile.fault = 0");
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "pzDownloadImfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("pztool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "chipPendingImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool updatecopiedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where,  "-exp_name", "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where, "-inst", "inst", "==");
+    PXOPT_COPY_STR(config->args, where, "-telescope", "telescope", "==");
+    PXOPT_COPY_STR(config->args, where,  "-class", "class", "==");
+    PXOPT_COPY_STR(config->args, where,  "-class_id", "class_id", "==");
+
+    PXOPT_LOOKUP_S16(code, config->args, "-code", true, false);
+
+    if (!pxSetFaultCode(config->dbh, "pzDownloadImfile", where, code)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to set set fault flag");
+	psFree (where);
+	return false;
+    }
+    psFree(where);
+
+    return true;
+}
+
+
+static bool revertcopiedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where,  "-exp_name", "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where, "-inst", "inst", "==");
+    PXOPT_COPY_STR(config->args, where, "-telescope", "telescope", "==");
+    PXOPT_COPY_STR(config->args, where,  "-class", "class", "==");
+    PXOPT_COPY_STR(config->args, where,  "-class_id", "class_id", "==");
+
+    psString query = pxDataGet("pztool_revertcopied.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "pzDownloadImfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    if (psDBAffectedRows(config->dbh) < 1) {
+        psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool clearcommonfaultsMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+{
+    psString query = pxDataGet("pztool_revert_downloadimfile_faults.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+}
+
+{
+    psString query = pxDataGet("pztool_revert_fileset_faults.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+}
+
+    return true;
+}
+
+static bool advanceMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // NOTE : the command-line args are parsed in copydoneCompleteExp
+
+    // start a transaction so it's all rows or nothing
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!copydoneCompleteExp(config, NULL, NULL, NULL)) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "copydoneCompleteExp() failed");
+        return false;
+    }
+
+    // point of no return
+    if (!psDBCommit(config->dbh)) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+
+    return true;
+}
+
+
+static bool pzDownloadExpSetState(pxConfig *config, const char *exp_name, const char *camera, const char *telescope, const char *state)
+{
+    PS_ASSERT_PTR_NON_NULL(state, false);
+
+    // check that state is a valid string value
+    if (!(
+            (strncmp(state, "run", 4) == 0)
+            || (strncmp(state, "stop", 5) == 0)
+            || (strncmp(state, "reg", 4) == 0)
+        )
+    ) {
+        psError(PS_ERR_UNKNOWN, false,
+                "invalid pzDownloadExp state: %s", state);
+        return false;
+    }
+
+    char *query = "UPDATE pzDownloadExp SET state = '%s' WHERE exp_name = '%s' and camera = '%s' and telescope = '%s'";
+    if (!p_psDBRunQuery(config->dbh, query, state, exp_name, camera, telescope)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to change state for %s:%s:%s", exp_name, camera, telescope);
+        return false;
+    }
+
+    return true;
+}
+
+
+#if 0
+static psArray *pzArrayAddArray(psArray *array, psArray *input)
+{
+    for (long i = 0; i < psArrayLength(input); i++) {
+        psArrayAdd(array, psArrayLength(input), input->data[i]);
+    }
+
+    return array;
+}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pztool.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pztool.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pztool.h	(revision 22158)
@@ -0,0 +1,42 @@
+/*
+ * pztool.h
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PZTOOL_H
+#define PZTOOL_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+    PZTOOL_MODE_NONE      = 0x0,
+    PZTOOL_MODE_ADDDATASTORE,
+    PZTOOL_MODE_DATASTORE,
+    PZTOOL_MODE_SEEN,
+    PZTOOL_MODE_PENDINGEXP,
+    PZTOOL_MODE_PENDINGIMFILE,
+    PZTOOL_MODE_COPYDONE,
+    PZTOOL_MODE_COPIED,
+    PZTOOL_MODE_UPDATECOPIED,
+    PZTOOL_MODE_REVERTCOPIED,
+    PZTOOL_MODE_CLEARCOMMONFAULTS,
+    PZTOOL_MODE_ADVANCE
+} pztoolMode;
+
+pxConfig *pztoolConfig(pxConfig *config, int argc, char **argv);
+
+#endif // PZTOOL_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/pztoolConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/pztoolConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/pztoolConfig.c	(revision 22158)
@@ -0,0 +1,175 @@
+/*
+ * pztoolConfig.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <psmodules.h>
+
+#include "pxtools.h"
+#include "pztool.h"
+
+pxConfig *pztoolConfig(pxConfig *config, int argc, char **argv)
+{
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    pmConfigReadParamsSet(false);
+
+    // setup site config
+    config->modules = pmConfigRead(&argc, argv, NULL);
+    if (! config->modules) {
+        psError(PS_ERR_UNKNOWN, false, "Can't find site configuration!\n");
+        psFree(config);
+        return NULL;
+    }
+
+    // -adddatastore
+    psMetadata *adddatastoreArgs = psMetadataAlloc();
+    psMetadataAddStr(adddatastoreArgs, PS_LIST_TAIL, "-inst", 0,            "define camera ID", NULL); 
+    psMetadataAddStr(adddatastoreArgs, PS_LIST_TAIL, "-telescope", 0,            "define telescope ID", NULL); 
+    psMetadataAddStr(adddatastoreArgs, PS_LIST_TAIL, "-uri", 0,            "define storage uri", NULL);
+    
+    // -datastore
+    psMetadata *datastoreArgs = psMetadataAlloc();
+    psMetadataAddBool(datastoreArgs, PS_LIST_TAIL, "-simple", 0,            "use the simple output format", false);
+
+    // -seen
+    psMetadata *seenArgs = psMetadataAlloc();
+    psMetadataAddStr(seenArgs, PS_LIST_TAIL, "-exp_name", 0,            "define exposure ID", NULL); 
+    psMetadataAddStr(seenArgs, PS_LIST_TAIL, "-inst", 0,            "define camera ID", NULL); 
+    psMetadataAddStr(seenArgs, PS_LIST_TAIL, "-telescope", 0,            "define telescope ID", NULL); 
+    psMetadataAddStr(seenArgs, PS_LIST_TAIL, "-exp_type", 0,            "define exposure type", NULL); 
+    psMetadataAddBool(seenArgs, PS_LIST_TAIL, "-simple", 0,            "use the simple output format", false);
+    
+    // -pendingexp
+    psMetadata *pendingexpArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingexpArgs, PS_LIST_TAIL, "-exp_name", 0,            "define exposure ID", NULL); 
+    psMetadataAddStr(pendingexpArgs, PS_LIST_TAIL, "-inst", 0,            "define camera ID", NULL); 
+    psMetadataAddStr(pendingexpArgs, PS_LIST_TAIL, "-telescope", 0,            "define telescope ID", NULL); 
+    psMetadataAddStr(pendingexpArgs, PS_LIST_TAIL, "-exp_type", 0,            "define exposure type", NULL); 
+    psMetadataAddBool(pendingexpArgs, PS_LIST_TAIL, "-desc", 0,            "sort ouput in descending format", false);
+    psMetadataAddU64(pendingexpArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(pendingexpArgs, PS_LIST_TAIL, "-simple", 0,            "use the simple output format", false);
+
+    // -pendingimfile
+    psMetadata *pendingimfileArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingimfileArgs, PS_LIST_TAIL, "-exp_name", 0,            "define exposure ID", NULL); 
+    psMetadataAddStr(pendingimfileArgs, PS_LIST_TAIL, "-inst", 0,            "define camera ID", NULL); 
+    psMetadataAddStr(pendingimfileArgs, PS_LIST_TAIL, "-telescope", 0,            "define telescope ID", NULL); 
+    psMetadataAddStr(pendingimfileArgs, PS_LIST_TAIL, "-exp_type", 0,            "define exposure type", NULL); 
+    psMetadataAddBool(pendingimfileArgs, PS_LIST_TAIL, "-desc", 0,            "sort ouput in descending format", false);
+    psMetadataAddU64(pendingimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(pendingimfileArgs, PS_LIST_TAIL, "-simple", 0,            "use the simple output format", false);
+
+    // -copydone
+    psMetadata *copydoneArgs = psMetadataAlloc();
+    psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-exp_name", 0,            "define exposure ID (required)", NULL); 
+    psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-inst", 0,            "define camera ID (required)", NULL); 
+    psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-telescope", 0,            "define telescope ID (required)", NULL); 
+    psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-class", 0,            "define class", NULL);
+    psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-class_id", 0,            "define class_id", NULL);
+    psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-uri", 0,            "define storage uri", NULL);
+    psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-workdir",  0,        "define the \"default\" workdir for this exposure", NULL);
+    psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-dvodb",  0,        "define the dvodb for the next processing step", NULL);
+    psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-tess_id",  0,        "define the tess_id for the next processing step", NULL);
+    psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-end_stage",  0,        "define the end goal processing step", NULL);
+    psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-label",  0,        "define the label for the chip stage", NULL);
+    psMetadataAddS16(copydoneArgs, PS_LIST_TAIL, "-code",  0,            "set fault code", 0);
+
+    // -copied
+    psMetadata *copiedArgs = psMetadataAlloc();
+    psMetadataAddStr(copiedArgs, PS_LIST_TAIL, "-exp_name", 0,            "define exposure ID", NULL); 
+    psMetadataAddStr(copiedArgs, PS_LIST_TAIL, "-inst", 0,            "define camera ID", NULL); 
+    psMetadataAddStr(copiedArgs, PS_LIST_TAIL, "-telescope", 0,            "define telescope ID", NULL); 
+    psMetadataAddStr(copiedArgs, PS_LIST_TAIL, "-class", 0,            "define class", NULL);
+    psMetadataAddStr(copiedArgs, PS_LIST_TAIL, "-class_id", 0,            "define class_id", NULL);
+    psMetadataAddBool(copiedArgs, PS_LIST_TAIL, "-faulted",  0,            "only return imfiles with a fault status set", false);
+    psMetadataAddU64(copiedArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(copiedArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -updatecopied
+    psMetadata *updatecopiedArgs = psMetadataAlloc();
+    psMetadataAddStr(updatecopiedArgs, PS_LIST_TAIL, "-exp_name", 0,            "define exposure ID (required)", NULL); 
+    psMetadataAddStr(updatecopiedArgs, PS_LIST_TAIL, "-inst", 0,            "define camera ID (required)", NULL); 
+    psMetadataAddStr(updatecopiedArgs, PS_LIST_TAIL, "-telescope", 0,            "define telescope ID (required)", NULL); 
+    psMetadataAddStr(updatecopiedArgs, PS_LIST_TAIL, "-class", 0,            "define class", NULL);
+    psMetadataAddStr(updatecopiedArgs, PS_LIST_TAIL, "-class_id", 0,            "define class_id", NULL);
+    psMetadataAddS16(updatecopiedArgs, PS_LIST_TAIL, "-code",  0,            "search by fault code", 0);
+
+    // -revertcopied
+    psMetadata *revertcopiedArgs = psMetadataAlloc();
+    psMetadataAddStr(revertcopiedArgs, PS_LIST_TAIL, "-exp_name", 0,            "define exposure ID (required)", NULL); 
+    psMetadataAddStr(revertcopiedArgs, PS_LIST_TAIL, "-inst", 0,            "define camera ID (required)", NULL); 
+    psMetadataAddStr(revertcopiedArgs, PS_LIST_TAIL, "-telescope", 0,            "define telescope ID (required)", NULL); 
+    psMetadataAddStr(revertcopiedArgs, PS_LIST_TAIL, "-class", 0,            "define class", NULL);
+    psMetadataAddStr(revertcopiedArgs, PS_LIST_TAIL, "-class_id", 0,            "define class_id", NULL);
+    psMetadataAddS16(revertcopiedArgs, PS_LIST_TAIL, "-code",  0,            "search by fault code", 0);
+
+    // -clearcommonfaults
+    psMetadata *clearcommonfaultsArgs = psMetadataAlloc();
+
+    // -advance
+    psMetadata *advanceArgs = psMetadataAlloc();
+    psMetadataAddStr(advanceArgs, PS_LIST_TAIL, "-workdir",  0,        "define the \"default\" workdir for this exposure", NULL);
+    psMetadataAddStr(advanceArgs, PS_LIST_TAIL, "-dvodb",  0,        "define the dvodb for the next processing step", NULL);
+    psMetadataAddStr(advanceArgs, PS_LIST_TAIL, "-tess_id",  0,        "define the tess_id for the next processing step", NULL);
+    psMetadataAddStr(advanceArgs, PS_LIST_TAIL, "-end_stage",  0,        "define the end goal processing step", NULL);
+    psMetadataAddStr(advanceArgs, PS_LIST_TAIL, "-label",  0,        "define the label for the chip stage", NULL);
+
+    psMetadata *argSets = psMetadataAlloc();
+    psMetadata *modes = psMetadataAlloc();
+
+    PXOPT_ADD_MODE("-adddatastore",    "", PZTOOL_MODE_ADDDATASTORE, adddatastoreArgs);
+    PXOPT_ADD_MODE("-datastore",       "", PZTOOL_MODE_DATASTORE,    datastoreArgs);
+    PXOPT_ADD_MODE("-seen",            "", PZTOOL_MODE_SEEN,         seenArgs);
+    PXOPT_ADD_MODE("-pendingexp",      "", PZTOOL_MODE_PENDINGEXP,   pendingexpArgs);
+    PXOPT_ADD_MODE("-pendingimfile",   "", PZTOOL_MODE_PENDINGIMFILE,pendingimfileArgs);
+    PXOPT_ADD_MODE("-copydone",        "", PZTOOL_MODE_COPYDONE,     copydoneArgs);
+    PXOPT_ADD_MODE("-copied",          "", PZTOOL_MODE_COPIED,      copiedArgs);
+    PXOPT_ADD_MODE("-updatecopied",    "", PZTOOL_MODE_UPDATECOPIED,updatecopiedArgs);
+    PXOPT_ADD_MODE("-revertcopied",    "", PZTOOL_MODE_REVERTCOPIED,revertcopiedArgs);
+    PXOPT_ADD_MODE("-clearcommonfaults","", PZTOOL_MODE_CLEARCOMMONFAULTS,clearcommonfaultsArgs);
+    PXOPT_ADD_MODE("-advance",          "", PZTOOL_MODE_ADVANCE,    advanceArgs);
+
+    if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
+        psError(PS_ERR_UNKNOWN, true, "option parsing failed");
+        psFree(argSets);
+        psFree(modes);
+        psFree(config);
+        return NULL;
+    }
+
+    psFree(argSets);
+    psFree(modes);
+
+    // define Database handle, if used
+    // do this last so we don't setup a connection before CLI options are
+    // validated
+    config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+    if (!config->dbh) {
+        psError(PS_ERR_UNKNOWN, false, "Can't configure database");
+        psFree(config);
+        return NULL;
+    }
+
+    return config;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/regtool.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/regtool.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/regtool.c	(revision 22158)
@@ -0,0 +1,1078 @@
+/*
+ * regtool.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <math.h>
+
+#include "pxtools.h"
+#include "pxdata.h"
+#include "regtool.h"
+#include "chiptool.h"
+
+// imfile
+static bool pendingimfileMode(pxConfig *config);
+static bool addprocessedimfileMode(pxConfig *config);
+static bool processedimfileMode(pxConfig *config);
+static bool revertprocessedimfileMode(pxConfig *config);
+static bool updateprocessedimfileMode(pxConfig *config);
+// exp
+static bool pendingexpMode(pxConfig *config);
+static bool addprocessedexpMode(pxConfig *config);
+static bool processedexpMode(pxConfig *config);
+static bool revertprocessedexpMode(pxConfig *config);
+static bool updateprocessedexpMode(pxConfig *config);
+static bool cleardupexpMode(pxConfig *config);
+
+# define MODECASE(caseName, func) \
+    case caseName: \
+    if (!func(config)) { \
+        goto FAIL; \
+    } \
+    break;
+
+int main(int argc, char **argv)
+{
+    psLibInit(NULL);
+
+    pxConfig *config = regtoolConfig(NULL, argc, argv);
+    if (!config) {
+        psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+        goto FAIL;
+    }
+
+    switch (config->mode) {
+        // imfile
+        MODECASE(REGTOOL_MODE_PENDINGIMFILE,         pendingimfileMode);
+        MODECASE(REGTOOL_MODE_ADDPROCESSEDIMFILE,    addprocessedimfileMode);
+        MODECASE(REGTOOL_MODE_PROCESSEDIMFILE,       processedimfileMode);
+        MODECASE(REGTOOL_MODE_REVERTPROCESSEDIMFILE, revertprocessedimfileMode);
+        MODECASE(REGTOOL_MODE_UPDATEPROCESSEDIMFILE, updateprocessedimfileMode);
+        // exp
+        MODECASE(REGTOOL_MODE_PENDINGEXP,            pendingexpMode);
+        MODECASE(REGTOOL_MODE_ADDPROCESSEDEXP,       addprocessedexpMode);
+        MODECASE(REGTOOL_MODE_PROCESSEDEXP,          processedexpMode);
+        MODECASE(REGTOOL_MODE_REVERTPROCESSEDEXP,    revertprocessedexpMode);
+        MODECASE(REGTOOL_MODE_UPDATEPROCESSEDEXP,    updateprocessedexpMode);
+        MODECASE(REGTOOL_MODE_CLEARDUPEXP,           cleardupexpMode);
+        default:
+            psAbort("invalid option (this should not happen)");
+    }
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(EXIT_SUCCESS);
+
+FAIL:
+    psErrorStackPrint(stderr, "\n");
+    int exit_status = pxerrorGetExitStatus();
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exit_status);
+}
+
+
+static bool pendingimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // select newImfiles that:
+    // exp_id is in newExp
+    // don't have their exp_id in rawExp
+    // XXX having the same exp_id in newExp and raw*Exp is probably an error
+    // that should be checked for
+
+    psString query = pxDataGet("regtool_pendingimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        // XXX PS_EXIT_PROG_ERROR (incorrect SQL) or SYS_ERROR (database comms)
+        psError(PXTOOLS_ERR_PROG, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("regtool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negate simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "regPendingImfile", !simple)) {
+        psError(PXTOOLS_ERR_PROG, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool addprocessedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required
+    PXOPT_LOOKUP_S64(exp_id, config->args, "-exp_id", true, false);
+    PXOPT_LOOKUP_STR(exp_name, config->args, "-exp_name", true, false);
+    PXOPT_LOOKUP_STR(camera, config->args, "-inst", true, false);
+    PXOPT_LOOKUP_STR(telescope, config->args, "-telescope", true, false);
+    PXOPT_LOOKUP_STR(tmp_class_id, config->args, "-tmp_class_id", true, false);
+    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false);
+    PXOPT_LOOKUP_STR(uri, config->args, "-uri", true, false);
+
+    // optional
+    PXOPT_LOOKUP_STR(exp_type, config->args, "-exp_type", false, false);
+    PXOPT_LOOKUP_STR(filelevel, config->args, "-filelevel", false, false);
+    PXOPT_LOOKUP_STR(filter, config->args, "-filter", false, false);
+    PXOPT_LOOKUP_STR(comment, config->args, "-comment", false, false);
+
+    PXOPT_LOOKUP_F32(airmass, config->args, "-airmass", false, false);
+    PXOPT_LOOKUP_F64(ra, config->args, "-ra", false, false);
+    PXOPT_LOOKUP_F64(decl, config->args, "-decl", false, false);
+    PXOPT_LOOKUP_F32(exp_time, config->args, "-exp_time", false, false);
+    PXOPT_LOOKUP_F32(sat_pixel_frac, config->args, "-sat_pixel_frac", false, false);
+    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
+    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
+    PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
+    PXOPT_LOOKUP_F64(alt, config->args, "-alt", false, false);
+    PXOPT_LOOKUP_F64(az, config->args, "-az", false, false);
+    PXOPT_LOOKUP_F32(ccd_temp, config->args, "-ccd_temp", false, false);
+    PXOPT_LOOKUP_F64(posang, config->args, "-posang", false, false);
+    PXOPT_LOOKUP_F32(m1_x, config->args, "-m1_x", false, false);
+    PXOPT_LOOKUP_F32(m1_y, config->args, "-m1_y", false, false);
+    PXOPT_LOOKUP_F32(m1_z, config->args, "-m1_z", false, false);
+    PXOPT_LOOKUP_F32(m1_tip, config->args, "-m1_tip", false, false);
+    PXOPT_LOOKUP_F32(m1_tilt, config->args, "-m1_tilt", false, false);
+    PXOPT_LOOKUP_F32(m2_x, config->args, "-m2_x", false, false);
+    PXOPT_LOOKUP_F32(m2_y, config->args, "-m2_y", false, false);
+    PXOPT_LOOKUP_F32(m2_z, config->args, "-m2_z", false, false);
+    PXOPT_LOOKUP_F32(m2_tip, config->args, "-m2_tip", false, false);
+    PXOPT_LOOKUP_F32(m2_tilt, config->args, "-m2_tilt", false, false);
+
+    PXOPT_LOOKUP_F32(env_temp, config->args, "-env_temperature", false, false);
+    PXOPT_LOOKUP_F32(env_humid, config->args, "-env_humidity", false, false);
+    PXOPT_LOOKUP_F32(env_wind, config->args, "-env_wind_speed", false, false);
+    PXOPT_LOOKUP_F32(env_dir, config->args, "-env_wind_dir", false, false);
+    PXOPT_LOOKUP_F32(teltemp_m1, config->args, "-teltemp_m1", false, false);
+    PXOPT_LOOKUP_F32(teltemp_m1cell, config->args, "-teltemp_m1cell", false, false);
+    PXOPT_LOOKUP_F32(teltemp_m2, config->args, "-teltemp_m2", false, false);
+    PXOPT_LOOKUP_F32(teltemp_spider, config->args, "-teltemp_spider", false, false);
+    PXOPT_LOOKUP_F32(teltemp_truss, config->args, "-teltemp_truss", false, false);
+    PXOPT_LOOKUP_F32(teltemp_extra, config->args, "-teltemp_extra", false, false);
+    PXOPT_LOOKUP_F32(pon_time, config->args, "-pon_time", false, false);
+    PXOPT_LOOKUP_F64(user_1, config->args, "-user_1", false, false);
+    PXOPT_LOOKUP_F64(user_2, config->args, "-user_2", false, false);
+    PXOPT_LOOKUP_F64(user_3, config->args, "-user_3", false, false);
+    PXOPT_LOOKUP_F64(user_4, config->args, "-user_4", false, false);
+    PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
+    PXOPT_LOOKUP_STR(object, config->args, "-object", false, false);
+    PXOPT_LOOKUP_TIME(dateobs, config->args, "-dateobs", false, false);
+    PXOPT_LOOKUP_STR(hostname, config->args, "-hostname", false, false);
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+
+    if (!rawImfileInsert(
+        config->dbh,
+        exp_id,
+        exp_name,
+        camera,
+        telescope,
+        dateobs,
+        tmp_class_id,
+        class_id,
+        uri,
+        exp_type,
+        filelevel,
+        filter,
+        comment,
+        airmass,
+        ra,
+        decl,
+        exp_time,
+        sat_pixel_frac,
+        bg,
+        bg_stdev,
+        bg_mean_stdev,
+        alt,
+        az,
+        ccd_temp,
+        posang,
+        m1_x,
+        m1_y,
+        m1_z,
+        m1_tip,
+        m1_tilt,
+        m2_x,
+        m2_y,
+        m2_z,
+        m2_tip,
+        m2_tilt,
+        env_temp,
+        env_humid,
+        env_wind,
+        env_dir,
+        teltemp_m1,
+        teltemp_m1cell,
+        teltemp_m2,
+        teltemp_spider,
+        teltemp_truss,
+        teltemp_extra,
+        pon_time,
+        user_1,
+        user_2,
+        user_3,
+        user_4,
+        user_5,
+        object,
+        hostname,
+        code,
+        NULL
+    )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool processedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where,  "-exp_id", "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where,  "-exp_name", "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where,  "-class_id", "class_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("regtool_processedimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psFree(where);
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "rawImfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", "AND rawImfile.fault != 0");
+    } else {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", "AND rawImfile.fault = 0");
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("regtool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "rawImfile", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool revertprocessedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where,  "-exp_id",       "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where,  "-tmp_class_id", "tmp_class_id", "==");
+    PXOPT_COPY_STR(config->args, where,  "-class_id",     "class_id", "==");
+    PXOPT_COPY_S16(config->args, where,  "-code",         "fault", "==");
+
+    psString query = pxDataGet("regtool_revertprocessedimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+	psFree(where);
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "rawImfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    if (psDBAffectedRows(config->dbh) < 1) {
+        psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool updateprocessedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where,  "-exp_id",       "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where,  "-class_id",     "class_id", "==");
+
+    PXOPT_LOOKUP_S16(code, config->args, "-code", true, false);
+
+    if (!pxSetFaultCode(config->dbh, "rawImfile", where, code)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to set set fault flag");
+	psFree (where);
+        return false;
+    }
+    psFree (where);
+
+    return true;
+}
+
+
+static bool pendingexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // return only exps that:
+    // are not in rawExp
+    // have ALL of their imfiles in rawImfile (by count)
+    // and have no associated imfiles left in newImfile
+    psString query = pxDataGet("regtool_pendingexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // treat limit == 0 as "no limit"
+    psString limitString = NULL;
+    if (limit) {
+        limitString = psDBGenerateLimitSQL(limit);
+        // skip past the "hook" comment
+        psStringPrepend(&limitString, "\n");
+    }
+
+    // 1st arg: where hook, 2nd arg: limit hook
+    if (!p_psDBRunQuery(config->dbh, query, "", limitString ? limitString : "")) {
+        // XXX PS_EXIT_PROG_ERROR (incorrect SQL) or SYS_ERROR (database comms)
+        psError(PXTOOLS_ERR_PROG, false, "database error");
+        psFree(limitString);
+        psFree(query);
+        return false;
+    }
+    psFree(limitString);
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("regtool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negate simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "regPendingExp", !simple)) {
+        psError(PXTOOLS_ERR_PROG, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool addprocessedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // make sure that the exp_id(s) are ready to be updated based on:
+    // exp_id is not in rawExp
+    // exp_id is not in newImfile
+    // that the correct count of imfiles is in rawImfile
+
+    // required
+    PXOPT_LOOKUP_S64(exp_id, config->args, "-exp_id", true, false);
+    PXOPT_LOOKUP_STR(exp_name, config->args, "-exp_name", true, false);
+    PXOPT_LOOKUP_STR(camera, config->args, "-inst", true, false);
+    PXOPT_LOOKUP_STR(telescope, config->args, "-telescope", true, false);
+    PXOPT_LOOKUP_STR(exp_tag, config->args, "-exp_tag", true, false);
+    PXOPT_LOOKUP_STR(filelevel, config->args, "-filelevel", true, false);
+
+    // optional
+    PXOPT_LOOKUP_TIME(dateobs, config->args, "-dateobs", false, false);
+    PXOPT_LOOKUP_STR(exp_type, config->args, "-exp_type", false, false);
+    PXOPT_LOOKUP_STR(workdir, config->args, "-workdir", false, false);
+    PXOPT_LOOKUP_STR(dvodb, config->args, "-dvodb", false, false);
+    PXOPT_LOOKUP_STR(tess_id, config->args, "-tess_id", false, false);
+    PXOPT_LOOKUP_STR(end_stage, config->args, "-end_stage", false, false);
+    PXOPT_LOOKUP_STR(reduction, config->args, "-reduction", false, false);
+    PXOPT_LOOKUP_STR(filter, config->args, "-filter", false, false);
+    PXOPT_LOOKUP_STR(comment, config->args, "-comment", false, false);
+    PXOPT_LOOKUP_F32(airmass, config->args, "-airmass", false, false);
+    PXOPT_LOOKUP_F64(ra, config->args, "-ra", false, false);
+    PXOPT_LOOKUP_F64(decl, config->args, "-decl", false, false);
+    PXOPT_LOOKUP_F32(exp_time, config->args, "-exp_time", false, false);
+    PXOPT_LOOKUP_F32(sat_pixel_frac, config->args, "-sat_pixel_frac", false, false);
+    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
+    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
+    PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
+    PXOPT_LOOKUP_F64(alt, config->args, "-alt", false, false);
+    PXOPT_LOOKUP_F64(az, config->args, "-az", false, false);
+    PXOPT_LOOKUP_F32(ccd_temp, config->args, "-ccd_temp", false, false);
+    PXOPT_LOOKUP_F64(posang, config->args, "-posang", false, false);
+    PXOPT_LOOKUP_F32(m1_x, config->args, "-m1_x", false, false);
+    PXOPT_LOOKUP_F32(m1_y, config->args, "-m1_y", false, false);
+    PXOPT_LOOKUP_F32(m1_z, config->args, "-m1_z", false, false);
+    PXOPT_LOOKUP_F32(m1_tip, config->args, "-m1_tip", false, false);
+    PXOPT_LOOKUP_F32(m1_tilt, config->args, "-m1_tilt", false, false);
+    PXOPT_LOOKUP_F32(m2_x, config->args, "-m2_x", false, false);
+    PXOPT_LOOKUP_F32(m2_y, config->args, "-m2_y", false, false);
+    PXOPT_LOOKUP_F32(m2_z, config->args, "-m2_z", false, false);
+    PXOPT_LOOKUP_F32(m2_tip, config->args, "-m2_tip", false, false);
+    PXOPT_LOOKUP_F32(m2_tilt, config->args, "-m2_tilt", false, false);
+
+    PXOPT_LOOKUP_F32(env_temp, config->args, "-env_temperature", false, false);
+    PXOPT_LOOKUP_F32(env_humid, config->args, "-env_humidity", false, false);
+    PXOPT_LOOKUP_F32(env_wind, config->args, "-env_wind_speed", false, false);
+    PXOPT_LOOKUP_F32(env_dir, config->args, "-env_wind_dir", false, false);
+    PXOPT_LOOKUP_F32(teltemp_m1, config->args, "-teltemp_m1", false, false);
+    PXOPT_LOOKUP_F32(teltemp_m1cell, config->args, "-teltemp_m1cell", false, false);
+    PXOPT_LOOKUP_F32(teltemp_m2, config->args, "-teltemp_m2", false, false);
+    PXOPT_LOOKUP_F32(teltemp_spider, config->args, "-teltemp_spider", false, false);
+    PXOPT_LOOKUP_F32(teltemp_truss, config->args, "-teltemp_truss", false, false);
+    PXOPT_LOOKUP_F32(teltemp_extra, config->args, "-teltemp_extra", false, false);
+    PXOPT_LOOKUP_F32(pon_time, config->args, "-pon_time", false, false);
+    PXOPT_LOOKUP_F64(user_1, config->args, "-user_1", false, false);
+    PXOPT_LOOKUP_F64(user_2, config->args, "-user_2", false, false);
+    PXOPT_LOOKUP_F64(user_3, config->args, "-user_3", false, false);
+    PXOPT_LOOKUP_F64(user_4, config->args, "-user_4", false, false);
+    PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
+    PXOPT_LOOKUP_STR(object, config->args, "-object", false, false);
+    PXOPT_LOOKUP_STR(label,  config->args, "-label", false, false);
+    PXOPT_LOOKUP_STR(hostname, config->args, "-hostname", false, false);
+
+    // default
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+
+    psString query = pxDataGet("regtool_pendingexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    psString whereClause = NULL;
+    {
+        // build a query to search by exp_id
+        psMetadata *where = psMetadataAlloc();
+        if (!psMetadataAddS64(where, PS_LIST_TAIL, "newExp.exp_id", 0, "==", exp_id)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+            psFree(where);
+            psFree(query);
+            return false;
+        }
+
+        whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psFree(where);
+        if (whereClause) {
+            // skip past comment "hook"
+            psStringPrepend(&whereClause, "\n AND ");
+        }
+    }
+
+    // 1st arg: where hook, 2nd arg: limit hook
+    if (!p_psDBRunQuery(config->dbh, query, whereClause ? whereClause : "", "")) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(whereClause);
+        psFree(query);
+        return false;
+    }
+    psFree(whereClause);
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psError(PS_ERR_UNKNOWN, false, "no pending newExp rows found");
+        psFree(output);
+        return false;
+    }
+    // sanity check that we only got one row
+    if (psArrayLength(output) != 1) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "should have gotten 1 row but %lu rows were returned", psArrayLength(output));
+        psFree(output);
+        return NULL;
+    }
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(output);
+        return false;
+    }
+
+    // insert the exp into rawExp
+    psMetadata *row = output->data[0];
+    // convert metadata into a newExp object
+    psMetadataConfigPrint(stdout, row);
+    newExpRow *newExp = newExpObjectFromMetadata(row);
+    psFree(output);
+    if (!newExp) {
+        psError(PS_ERR_UNKNOWN, false, "this should not happen");
+        return false;
+    }
+
+    // carry through these values
+    // new CLI options overwrite existing values
+    workdir   = workdir   ? workdir   : newExp->workdir;
+    reduction = reduction ? reduction : newExp->reduction;
+    dvodb     = dvodb     ? dvodb     : newExp->dvodb;
+    tess_id   = tess_id   ? tess_id   : newExp->tess_id;
+    end_stage = end_stage ? end_stage : newExp->end_stage;
+    label     = label     ? label     : newExp->label;
+    // don't free newExp until just before we return, or these refs will break
+
+    if (!rawExpInsert(config->dbh,
+        exp_id,
+        exp_name,
+        camera,
+        telescope,
+        dateobs,
+        exp_tag,
+        exp_type,
+        filelevel,
+        workdir,
+        reduction,
+        dvodb,
+        tess_id,
+        end_stage,
+        filter,
+        comment,
+        airmass,
+        ra,
+        decl,
+        exp_time,
+        sat_pixel_frac,
+        bg,
+        bg_stdev,
+        bg_mean_stdev,
+        alt,
+        az,
+        ccd_temp,
+        posang,
+        m1_x,
+        m1_y,
+        m1_z,
+        m1_tip,
+        m1_tilt,
+        m2_x,
+        m2_y,
+        m2_z,
+        m2_tip,
+        m2_tilt,
+        env_temp,
+        env_humid,
+        env_wind,
+        env_dir,
+        teltemp_m1,
+        teltemp_m1cell,
+        teltemp_m2,
+        teltemp_spider,
+        teltemp_truss,
+        teltemp_extra,
+        pon_time,
+        user_1,
+        user_2,
+        user_3,
+        user_4,
+        user_5,
+        object,
+        0.0,
+        hostname,
+        code,
+        NULL
+    )) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(newExp);
+        return false;
+    }
+
+    // set the state for the newExp to stop
+    if (!pxnewExpSetState(config, exp_id, "stop")) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "failed to change newExp.state for exp_id: %"PRId64, exp_id);
+    psFree(newExp);
+        return false;
+    }
+
+    // should we stop here and proceed on to the chip stage?
+    // NULL for end_stage means go as far as possible
+    if (end_stage && psStrcasestr(end_stage, "reg")) {
+        // then we are done here
+        if (!psDBCommit(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        }
+
+    psFree(newExp);
+        return true;
+    }
+    // else continue on...
+
+
+    // insert an entry into the chipPendingExp table
+    // this can only be run as the newExp's state has been set to stop
+    if (!pxchipQueueByExpTag(config,
+                exp_id,
+                workdir,
+            label,
+                reduction,
+                NULL, // expgroup
+                dvodb,
+                tess_id,
+                end_stage
+    )) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "failed to queue chipPendingExp");
+    psFree(newExp);
+        return false;
+    }
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(newExp);
+        return false;
+    }
+
+    psFree(newExp);
+    return true;
+}
+
+
+static bool processedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psString query = pxDataGet("regtool_processedexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // XX test this out; need to make this consistent with the list in regtoolConfig.c
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where,  "-exp_id", "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where,  "-exp_name", "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where,  "-inst", "camera", "==");
+    PXOPT_COPY_STR(config->args, where,  "-telescope", "telescope", "==");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_begin", "dateobs", ">=");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_end", "dateobs", "<=");
+    PXOPT_COPY_STR(config->args, where,  "-exp_tag", "exp_tag", "==");
+    PXOPT_COPY_STR(config->args, where,  "-exp_type", "exp_type", "==");
+    PXOPT_COPY_STR(config->args, where,  "-filelevel", "filelevel", "==");
+    PXOPT_COPY_STR(config->args, where,  "-reduction", "reduction", "==");
+    PXOPT_COPY_STR(config->args, where,  "-filter", "filter", "==");
+    PXOPT_COPY_F32(config->args, where,  "-airmass_min", "airmass", ">=");
+    PXOPT_COPY_F32(config->args, where,  "-airmass_max", "airmass", "<");
+    PXOPT_COPY_F64(config->args, where,  "-ra_min", "ra", ">=");
+    PXOPT_COPY_F64(config->args, where,  "-ra_max", "ra", "<");
+    PXOPT_COPY_F64(config->args, where,  "-decl_min", "decl", ">=");
+    PXOPT_COPY_F64(config->args, where,  "-decl_max", "decl", "<");
+    PXOPT_COPY_F32(config->args, where,  "-exp_time_min", "exp_time", ">=");
+    PXOPT_COPY_F32(config->args, where,  "-exp_time_max", "exp_time", "<");
+    PXOPT_COPY_F32(config->args, where,  "-sat_pixel_frac_min", "sat_pixel_frac", ">=");
+    PXOPT_COPY_F32(config->args, where,  "-sat_pixel_frac_max", "sat_pixel_frac", "<");
+    PXOPT_COPY_F64(config->args, where,  "-bg_min", "bg", ">=");
+    PXOPT_COPY_F64(config->args, where,  "-bg_max", "bg", "<");
+    PXOPT_COPY_F64(config->args, where,  "-bg_stdev_min", "bg_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where,  "-bg_stdev_max", "bg_stdev", "<");
+    PXOPT_COPY_F64(config->args, where,  "-bg_mean_stdev_min", "bg_mean_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where,  "-bg_mean_stdev_max", "bg_mean_stdev", "<");
+    PXOPT_COPY_F64(config->args, where,  "-alt_min", "alt", ">=");
+    PXOPT_COPY_F64(config->args, where,  "-alt_max", "alt", "<");
+    PXOPT_COPY_F64(config->args, where,  "-az_min", "az", ">=");
+    PXOPT_COPY_F64(config->args, where,  "-az_max", "az", "<");
+    PXOPT_COPY_F64(config->args, where,  "-ccd_temp_min", "ccd_temp", ">=");
+    PXOPT_COPY_F64(config->args, where,  "-ccd_temp_max", "ccd_temp", "<");
+    PXOPT_COPY_F64(config->args, where,  "-posang_min", "posang", ">=");
+    PXOPT_COPY_F64(config->args, where,  "-posang_max", "posang", "<");
+    PXOPT_COPY_STR(config->args, where,  "-object", "object", "==");
+    PXOPT_COPY_F32(config->args, where,  "-solang_min", "solang", ">=");
+    PXOPT_COPY_F32(config->args, where,  "-solang_max", "solang", "<");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "rawExp");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", "AND rawExp.fault != 0");
+    } else {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", "AND rawExp.fault = 0");
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("regtool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "rawExp", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool revertprocessedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where,  "-exp_id",       "exp_id", "==");
+    PXOPT_COPY_S16(config->args, where,  "-code",         "fault", "==");
+
+    psString query = pxDataGet("regtool_revertprocessedexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+	psFree(where);
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "rawExp");
+        psStringAppend(&query, " AND %s", whereClause);
+	psFree(where);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    if (psDBAffectedRows(config->dbh) < 1) {
+        psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool updateprocessedexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where,  "-exp_id",       "exp_id", "==");
+
+    PXOPT_LOOKUP_S16(code, config->args, "-code", true, false);
+
+    if (!pxSetFaultCode(config->dbh, "rawExp", where, code)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to set set fault flag");
+	psFree(where);
+        return false;
+    }
+    psFree(where);
+
+    return true;
+}
+
+
+static bool cleardupexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+// create temp table of exp_ids to be removed
+{
+    psString query = pxDataGet("regtool_create_dup_table.sql");
+    if (!query) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+}
+
+// populate that table
+// XXX note that this query currently doesn't not correctly handle the case
+// where there is more than one duplicate
+{
+    psString query = pxDataGet("regtool_populate_dup_table.sql");
+    if (!query) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+}
+
+    if (!p_psDBRunQuery(config->dbh, "DELETE FROM rawImfile USING rawImfile, duplicate WHERE duplicate.exp_id = rawImfile.exp_id")) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!p_psDBRunQuery(config->dbh, "DELETE FROM rawExp USING rawExp, duplicate WHERE duplicate.exp_id = rawExp.exp_id")) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!p_psDBRunQuery(config->dbh, "DELETE FROM newImfile USING newImfile, duplicate WHERE duplicate.exp_id = newImfile.exp_id")) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!p_psDBRunQuery(config->dbh, "DELETE FROM newExp USING newExp, duplicate WHERE duplicate.exp_id = newExp.exp_id")) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/regtool.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/regtool.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/regtool.h	(revision 22158)
@@ -0,0 +1,42 @@
+/*
+ * regtool.h
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef REGTOOL_H
+#define REGTOOL_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+    REGTOOL_MODE_NONE      = 0x0,
+    REGTOOL_MODE_PENDINGIMFILE,
+    REGTOOL_MODE_ADDPROCESSEDIMFILE,
+    REGTOOL_MODE_PROCESSEDIMFILE,
+    REGTOOL_MODE_REVERTPROCESSEDIMFILE,
+    REGTOOL_MODE_UPDATEPROCESSEDIMFILE,
+    REGTOOL_MODE_PENDINGEXP,
+    REGTOOL_MODE_ADDPROCESSEDEXP,
+    REGTOOL_MODE_PROCESSEDEXP,
+    REGTOOL_MODE_REVERTPROCESSEDEXP,
+    REGTOOL_MODE_UPDATEPROCESSEDEXP,
+    REGTOOL_MODE_CLEARDUPEXP,
+} regtoolMode;
+
+pxConfig *regtoolConfig(pxConfig *config, int argc, char **argv);
+
+#endif // REGTOOL_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/regtoolConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/regtoolConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/regtoolConfig.c	(revision 22158)
@@ -0,0 +1,295 @@
+/*
+ * regtoolConfig.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <math.h>
+#include <stdint.h>
+
+#include <psmodules.h>
+
+#include "pxtools.h"
+#include "regtool.h"
+
+#define ADD_OPT(TYPE,TARG,NAME,COMMENT,DEFAULT) psMetadataAdd##TYPE(TARG, PS_LIST_TAIL, NAME, 0, COMMENT, DEFAULT)
+
+pxConfig *regtoolConfig(pxConfig *config, int argc, char **argv)
+{
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    pmConfigReadParamsSet(false);
+
+    // setup site config
+    config->modules = pmConfigRead(&argc, argv, NULL);
+    if (!config->modules) {
+        psError(PXTOOLS_ERR_CONFIG, false, "Can't find site configuration");
+        psFree(config);
+        return NULL;
+    }
+
+    // -pendingimfile
+    psMetadata *pendingimfileArgs = psMetadataAlloc();
+    ADD_OPT(U64,  pendingimfileArgs, "-limit",     "limit result set to N items",  0);
+    ADD_OPT(Bool, pendingimfileArgs, "-simple",    "use the simple output format", false);
+
+    // -addprocessedimfile
+    psMetadata *addprocessedimfileArgs = psMetadataAlloc();
+    ADD_OPT(S64,  addprocessedimfileArgs, "-exp_id",         "define exposure ID (required)",        0);
+    ADD_OPT(Str,  addprocessedimfileArgs, "-exp_name",       "define the exp_name (required)",         NULL);
+    ADD_OPT(Str,  addprocessedimfileArgs, "-inst",           "define the camera name (required)",     NULL);
+    ADD_OPT(Str,  addprocessedimfileArgs, "-telescope",      "define the telescope name (required)",     NULL);
+    ADD_OPT(Str,  addprocessedimfileArgs, "-tmp_class_id",   "define temp. class ID (required)",     NULL);
+    ADD_OPT(Str,  addprocessedimfileArgs, "-class_id",       "define class ID (required)",         NULL);
+    ADD_OPT(Str,  addprocessedimfileArgs, "-uri",            "define URI (required)",             NULL);
+
+    ADD_OPT(Str,  addprocessedimfileArgs, "-exp_type",       "define exposure type",             NULL);
+    ADD_OPT(Str,  addprocessedimfileArgs, "-filelevel",      "define filelevel",             NULL);
+    ADD_OPT(Str,  addprocessedimfileArgs, "-filter",         "define filter ",                 NULL);
+    ADD_OPT(Str,  addprocessedimfileArgs, "-comment",        "define comment ",             NULL);
+
+    ADD_OPT(F32,  addprocessedimfileArgs, "-airmass",        "define airmass",                 NAN);
+    ADD_OPT(F64,  addprocessedimfileArgs, "-ra",             "define RA",                 NAN);
+    ADD_OPT(F64,  addprocessedimfileArgs, "-decl",           "define DEC",                 NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-exp_time",       "define exposure time",             NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-sat_pixel_frac", "define fraction of saturated pixels",     NAN);
+    ADD_OPT(F64,  addprocessedimfileArgs, "-bg",             "define exposue background",          NAN);
+    ADD_OPT(F64,  addprocessedimfileArgs, "-bg_stdev",       "define exposue background stdev",     NAN);
+    ADD_OPT(F64,  addprocessedimfileArgs, "-bg_mean_stdev",  "define exposue background mean stdev",     NAN);
+    ADD_OPT(F64,  addprocessedimfileArgs, "-alt",            "define altitute",                  NAN);
+    ADD_OPT(F64,  addprocessedimfileArgs, "-az",             "define azimuth",                      NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-ccd_temp",       "define ccd tempature",                NAN);
+    ADD_OPT(F64,  addprocessedimfileArgs, "-posang",         "define rotator position angle",         NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-m1_x",           "define M1 X position",                NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-m1_y",           "define M1 Y position",                NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-m1_z",           "define M1 Z position",                NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-m1_tip",         "define M1 TIP position",                NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-m1_tilt",        "define M1 TILT position",            NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-m2_x",           "define M2 X position",                NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-m2_y",           "define M2 Y position",                NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-m2_z",           "define M2 Z position",                NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-m2_tip",         "define M2 TIP position",                NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-m2_tilt",        "define M2 TILT position",         NAN);
+
+    ADD_OPT(F32,  addprocessedimfileArgs, "-env_temperature","define Environmental Temperature",     NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-env_humidity",   "define Environmental Humidity",         NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-env_wind_speed", "define Environmental Wind Speed",     NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-env_wind_dir",   "define Environmental Wind Direction",     NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-teltemp_m1",     "define Telescope Temperature : M1",     NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-teltemp_m1cell", "define Telescope Temperature : M1 Cell",     NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-teltemp_m2",     "define Telescope Temperature : M2",     NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-teltemp_spider", "define Telescope Temperature : Spider",     NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-teltemp_truss",  "define Telescope Temperature : Truss",     NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-teltemp_extra",  "define Telescope Temperature : Extra",     NAN);
+    ADD_OPT(F32,  addprocessedimfileArgs, "-pon_time",       "define time to last Power On",         NAN);
+    ADD_OPT(F64,  addprocessedimfileArgs, "-user_1",         "define user statistic (1)",         NAN);
+    ADD_OPT(F64,  addprocessedimfileArgs, "-user_2",         "define user statistic (2)",         NAN);
+    ADD_OPT(F64,  addprocessedimfileArgs, "-user_3",         "define user statistic (3)",         NAN);
+    ADD_OPT(F64,  addprocessedimfileArgs, "-user_4",         "define user statistic (4)",         NAN);
+    ADD_OPT(F64,  addprocessedimfileArgs, "-user_5",         "define user statistic (5)",         NAN);
+    ADD_OPT(Str,  addprocessedimfileArgs, "-object",         "define exposure object",             NULL);
+    ADD_OPT(Time, addprocessedimfileArgs, "-dateobs",        "define observation time",         NULL);
+    ADD_OPT(Str,  addprocessedimfileArgs, "-hostname",       "define host name",                NULL);
+    ADD_OPT(S16,  addprocessedimfileArgs, "-code",           "set fault code",                  0);
+
+    // -processedimfile
+    psMetadata *processedimfileArgs = psMetadataAlloc();
+   ADD_OPT(S64,  processedimfileArgs, "-exp_id",    "search by exposure ID",                 0);
+   ADD_OPT(Str,  processedimfileArgs, "-exp_name",  "search by exposure name",               NULL);
+   ADD_OPT(Str,  processedimfileArgs, "-class_id",  "search by class ID",                    NULL);
+   ADD_OPT(U64,  processedimfileArgs, "-limit",     "limit result set to N items",           0);
+   ADD_OPT(Bool, processedimfileArgs, "-faulted",   "only return imfiles with a fault status set", false);
+   ADD_OPT(Bool, processedimfileArgs, "-simple",    "use the simple output format",          false);
+
+    // -revertprocessedimfile
+    psMetadata *revertprocessedimfileArgs = psMetadataAlloc();
+    ADD_OPT(S64, revertprocessedimfileArgs, "-exp_id",        "search by exposure ID (required)", 0);
+    ADD_OPT(Str, revertprocessedimfileArgs, "-tmp_class_id",  "searcy by temp. class ID", NULL);
+    ADD_OPT(Str, revertprocessedimfileArgs, "-class_id",      "search by class ID", NULL);
+    ADD_OPT(S16, revertprocessedimfileArgs, "-code",          "search by fault code", 0);
+
+    // -updateprocessedimfile
+    psMetadata *updateprocessedimfileArgs = psMetadataAlloc();
+    ADD_OPT(S64, updateprocessedimfileArgs, "-exp_id",        "search by exposure ID", 0);
+    ADD_OPT(Str, updateprocessedimfileArgs, "-class_id",      "search by class ID", NULL);
+    ADD_OPT(S16, updateprocessedimfileArgs, "-code",          "set fault code (required)", INT16_MAX);
+
+    // -pendingexp
+    psMetadata *pendingexpArgs = psMetadataAlloc();
+    psMetadataAddU64(pendingexpArgs, PS_LIST_TAIL, "-limit",    0,        "limit result set to N items", 0);
+    psMetadataAddBool(pendingexpArgs, PS_LIST_TAIL, "-simple",  0,        "use the simple output format", false);
+
+    // -addprocessedexp
+    psMetadata *addprocessedexpArgs = psMetadataAlloc();
+    psMetadataAddS64(addprocessedexpArgs, PS_LIST_TAIL, "-exp_id",           0,        "exp_id to operate on (required)", 0);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-exp_name",         0,        "define the exp_name (required)", NULL);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-inst",             0,        "define the camera name (required)", NULL);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-telescope",        0,        "define the telescope name (required)", NULL);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-exp_tag",          0,        "define the external exposure tag name (required)", NULL);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-filelevel",        0,        "define the data partitioning level of this file (required)", NULL);
+
+    psMetadataAddTime(addprocessedexpArgs, PS_LIST_TAIL, "-dateobs",         0,        "define observation time", NULL);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-exp_type",         0,        "define exposure type", NULL);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-workdir",          0,        "define the \"default\" workdir for this exposure", NULL);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-dvodb",            0,        "define the dvodb for the next processing step", NULL);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-tess_id",          0,        "define the tess_id for the next processing step", NULL);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-end_stage",        0,        "define the end goal processing step", NULL);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-reduction",        0,        "define the \"default\" reduction class for this exposure", NULL);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-filter",           0,        "define filter ", NULL);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-comment",          0,        "define comment ", NULL);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-airmass",          0,        "define airmass", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-ra",               0,        "define RA", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-decl",             0,        "define DEC", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-exp_time",         0,        "define exposure time", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-sat_pixel_frac",   0,        "define fraction of saturated pixels", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-bg",               0,        "define exposue background", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-bg_stdev",         0,        "define exposue background stdev", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-bg_mean_stdev",    0,        "define exposue background mean stdev", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-alt",              0,        "define altitute", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-az",               0,        "define azimuth", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-ccd_temp",         0,        "define ccd tempature", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-posang",           0,        "define rotator position angle", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-m1_x",             0,        "define M1 X position", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-m1_y",             0,        "define M1 Y position", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-m1_z",             0,        "define M1 Z position", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-m1_tip",           0,        "define M1 TIP position", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-m1_tilt",          0,        "define M1 TILT position", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-m2_x",             0,        "define M2 X position", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-m2_y",             0,        "define M2 Y position", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-m2_z",             0,        "define M2 Z position", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-m2_tip",           0,        "define M2 TIP position", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-m2_tilt",          0,        "define M2 TILT position", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-env_temperature",  0,        "define Environmental Temperature", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-env_humidity",     0,        "define Environmental Humidity", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-env_wind_speed",   0,        "define Environmental Wind Speed", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-env_wind_dir",     0,        "define Environmental Wind Direction", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-teltemp_m1",       0,        "define Telescope Temperature : M1", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-teltemp_m1cell",   0,        "define Telescope Temperature : M1 Cell", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-teltemp_m2",       0,        "define Telescope Temperature : M2", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-teltemp_spider",   0,        "define Telescope Temperature : Spider", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-teltemp_truss",    0,        "define Telescope Temperature : Truss", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-teltemp_extra",    0,        "define Telescope Temperature : Extra", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-pon_time",         0,        "define time to last Power On", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-user_1",           0,        "define user statistic (1)", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-user_2",           0,        "define user statistic (2)", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-user_3",           0,        "define user statistic (3)", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-user_4",           0,        "define user statistic (4)", NAN);
+    psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-user_5",           0,        "define user statistic (5)", NAN);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-object",           0,        "define exposure object", NULL);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-label",            0,        "define label for chip stage (non-detrend data only)", NULL);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-hostname",         0,        "define host name", NULL);
+    psMetadataAddS16(addprocessedexpArgs, PS_LIST_TAIL, "-code",             0,        "set fault code", 0);
+
+    // -processedexp
+    psMetadata *processedexpArgs = psMetadataAlloc();
+    psMetadataAddS64(processedexpArgs,  PS_LIST_TAIL, "-exp_id",        0,            "search by exposure ID", 0);
+    psMetadataAddStr(processedexpArgs,  PS_LIST_TAIL, "-exp_name",      0,            "search by exp_name", NULL);
+    psMetadataAddStr(processedexpArgs,  PS_LIST_TAIL, "-inst",          0,            "search for camera", NULL);
+    psMetadataAddStr(processedexpArgs,  PS_LIST_TAIL, "-telescope",     0,            "search for telescope", NULL);
+    psMetadataAddTime(processedexpArgs, PS_LIST_TAIL, "-dateobs_begin", 0,            "search for exposures by time (>=)", NULL);
+    psMetadataAddTime(processedexpArgs, PS_LIST_TAIL, "-dateobs_end",   0,            "search for exposures by time (<)", NULL);
+    psMetadataAddStr(processedexpArgs,  PS_LIST_TAIL, "-exp_tag",       0,            "search by exp_tag", NULL);
+    psMetadataAddStr(processedexpArgs,  PS_LIST_TAIL, "-exp_type",      0,            "search by exp_type", "object");
+    psMetadataAddStr(processedexpArgs,  PS_LIST_TAIL, "-filelevel",     0,            "search by filelevel", NULL);
+    psMetadataAddStr(processedexpArgs,  PS_LIST_TAIL, "-reduction",     0,            "search by reduction class", NULL);
+    psMetadataAddStr(processedexpArgs,  PS_LIST_TAIL, "-filter",        0,            "search for filter", NULL);
+    psMetadataAddF32(processedexpArgs,  PS_LIST_TAIL, "-airmass_min",   0,            "search by min airmass", NAN);
+    psMetadataAddF32(processedexpArgs,  PS_LIST_TAIL, "-airmass_max",   0,            "search by max airmass", NAN);
+    psMetadataAddF64(processedexpArgs,  PS_LIST_TAIL, "-ra_min",        0,            "search by min", NAN);
+    psMetadataAddF64(processedexpArgs,  PS_LIST_TAIL, "-ra_max",        0,            "search by max", NAN);
+    psMetadataAddF64(processedexpArgs,  PS_LIST_TAIL, "-decl_min",      0,            "search by min", NAN);
+    psMetadataAddF64(processedexpArgs,  PS_LIST_TAIL, "-decl_max",      0,            "search by max", NAN);
+    psMetadataAddF32(processedexpArgs,  PS_LIST_TAIL, "-exp_time_min",  0,            "search by min", NAN);
+    psMetadataAddF32(processedexpArgs,  PS_LIST_TAIL, "-exp_time_max",  0,            "search by max", NAN);
+    psMetadataAddF32(processedexpArgs,  PS_LIST_TAIL, "-sat_pixel_frac_min",  0,      "search by max fraction of saturated pixels", NAN);
+    psMetadataAddF32(processedexpArgs,  PS_LIST_TAIL, "-sat_pixel_frac_max",  0,      "search by min fraction of saturated pixels", NAN);
+    psMetadataAddF64(processedexpArgs,  PS_LIST_TAIL, "-bg_min",        0,            "search by max", NAN);
+    psMetadataAddF64(processedexpArgs,  PS_LIST_TAIL, "-bg_max",        0,            "search by max", NAN);
+    psMetadataAddF64(processedexpArgs,  PS_LIST_TAIL, "-bg_stdev_min",  0,            "search by max", NAN);
+    psMetadataAddF64(processedexpArgs,  PS_LIST_TAIL, "-bg_stdev_max",  0,            "search by max", NAN);
+    psMetadataAddF64(processedexpArgs,  PS_LIST_TAIL, "-bg_mean_stdev_min",  0,       "search by max", NAN);
+    psMetadataAddF64(processedexpArgs,  PS_LIST_TAIL, "-bg_mean_stdev_max",  0,       "search by max", NAN);
+    psMetadataAddF64(processedexpArgs,  PS_LIST_TAIL, "-alt_min",       0,            "search by min", NAN);
+    psMetadataAddF64(processedexpArgs,  PS_LIST_TAIL, "-alt_max",       0,            "search by max", NAN);
+    psMetadataAddF64(processedexpArgs,  PS_LIST_TAIL, "-az_min",        0,            "search by min", NAN);
+    psMetadataAddF64(processedexpArgs,  PS_LIST_TAIL, "-az_max",        0,            "search by max", NAN);
+    psMetadataAddF64(processedexpArgs,  PS_LIST_TAIL, "-ccd_temp_min",  0,            "search by min ccd tempature", NAN);
+    psMetadataAddF64(processedexpArgs,  PS_LIST_TAIL, "-ccd_temp_max",  0,            "search by max ccd tempature", NAN);
+    psMetadataAddF64(processedexpArgs,  PS_LIST_TAIL, "-posang_min",    0,            "search by min rotator position angle", NAN);
+    psMetadataAddF64(processedexpArgs,  PS_LIST_TAIL, "-posang_max",    0,            "search by max rotator position angle", NAN);
+    psMetadataAddStr(processedexpArgs,  PS_LIST_TAIL, "-object",        0,            "search by exposure object", NULL);
+    psMetadataAddF32(processedexpArgs,  PS_LIST_TAIL, "-solang_min",    0,            "define min solar angle", NAN);
+    psMetadataAddF32(processedexpArgs,  PS_LIST_TAIL, "-solang_max",    0,            "define max solar angle", NAN);
+
+    psMetadataAddU64(processedexpArgs,  PS_LIST_TAIL, "-limit",         0,            "limit result set to N items", 0);
+    psMetadataAddBool(processedexpArgs, PS_LIST_TAIL, "-faulted",       0,            "only return imfiles with a fault status set", false);
+    psMetadataAddBool(processedexpArgs, PS_LIST_TAIL, "-simple",        0,            "use the simple output format", false);
+
+    // -revertprocessedexp
+    psMetadata *revertprocessedexpArgs = psMetadataAlloc();
+    psMetadataAddS64(revertprocessedexpArgs, PS_LIST_TAIL, "-exp_id",   0,            "search by exposure ID (required)", 0);
+    psMetadataAddS16(revertprocessedexpArgs, PS_LIST_TAIL, "-code",     0,            "search by fault code", 0);
+
+    // -updatedprocessedexp
+    psMetadata *updatedprocessedexpArgs = psMetadataAlloc();
+    psMetadataAddS64(updatedprocessedexpArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exposure ID", 0);
+    psMetadataAddS16(updatedprocessedexpArgs, PS_LIST_TAIL, "-code",    0,            "set fault code (required)", INT16_MAX);
+
+    // -cleardupexp
+    psMetadata *cleardupexpArgs = psMetadataAlloc();
+
+    psMetadata *argSets = psMetadataAlloc();
+    psMetadata *modes = psMetadataAlloc();
+
+    PXOPT_ADD_MODE("-pendingimfile",           "", REGTOOL_MODE_PENDINGIMFILE, pendingimfileArgs);
+    PXOPT_ADD_MODE("-addprocessedimfile",      "", REGTOOL_MODE_ADDPROCESSEDIMFILE, addprocessedimfileArgs);
+    PXOPT_ADD_MODE("-processedimfile",         "", REGTOOL_MODE_PROCESSEDIMFILE, processedimfileArgs);
+    PXOPT_ADD_MODE("-revertprocessedimfile",   "", REGTOOL_MODE_REVERTPROCESSEDIMFILE, revertprocessedimfileArgs);
+    PXOPT_ADD_MODE("-updateprocessedimfile",   "", REGTOOL_MODE_UPDATEPROCESSEDIMFILE, updateprocessedimfileArgs);
+    PXOPT_ADD_MODE("-pendingexp",              "", REGTOOL_MODE_PENDINGEXP,pendingexpArgs);
+    PXOPT_ADD_MODE("-addprocessedexp",         "", REGTOOL_MODE_ADDPROCESSEDEXP, addprocessedexpArgs);
+    PXOPT_ADD_MODE("-processedexp",            "", REGTOOL_MODE_PROCESSEDEXP, processedexpArgs);
+    PXOPT_ADD_MODE("-revertprocessedexp",      "", REGTOOL_MODE_REVERTPROCESSEDEXP, revertprocessedexpArgs);
+    PXOPT_ADD_MODE("-updateprocessedexp",      "", REGTOOL_MODE_UPDATEPROCESSEDEXP,      updatedprocessedexpArgs);
+    PXOPT_ADD_MODE("-cleardupexp",             "", REGTOOL_MODE_CLEARDUPEXP,      cleardupexpArgs);
+
+    if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
+        psError(PS_ERR_UNKNOWN, true, "option parsing failed");
+        psFree(argSets);
+        psFree(modes);
+        psFree(config);
+        return NULL;
+    }
+
+    psFree(argSets);
+    psFree(modes);
+
+    // define Database handle, if used
+    config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+    if (!config->dbh) {
+        psError(PXTOOLS_ERR_SYS, false, "Can't configure database");
+        psFree(config);
+        return NULL;
+    }
+
+    return config;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/stacktool.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/stacktool.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/stacktool.c	(revision 22158)
@@ -0,0 +1,1024 @@
+/*
+ * stacktool.c
+ *
+ * Copyright (C) 2007-2008  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVB_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <ippdb.h>
+
+#include "pxtools.h"
+#include "stacktool.h"
+
+static bool definebyqueryMode(pxConfig *config);
+static bool definerunMode(pxConfig *config);
+static bool updaterunMode(pxConfig *config);
+static bool addinputskyfileMode(pxConfig *config);
+static bool inputskyfileMode(pxConfig *config);
+static bool tosumMode(pxConfig *config);
+static bool addsumskyfileMode(pxConfig *config);
+static bool sumskyfileMode(pxConfig *config);
+static bool revertsumskyfileMode(pxConfig *config);
+static bool pendingcleanuprunMode(pxConfig *config);
+static bool pendingcleanupskyfileMode(pxConfig *config);
+static bool donecleanupMode(pxConfig *config);
+
+static bool setstackRunState(pxConfig *config, psS64 stack_id, const char *state);
+
+# define MODECASE(caseName, func) \
+    case caseName: \
+    if (!func(config)) { \
+        goto FAIL; \
+    } \
+    break;
+
+int main(int argc, char **argv)
+{
+    psLibInit(NULL);
+
+    pxConfig *config = stacktoolConfig(NULL, argc, argv);
+    if (!config) {
+        psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+        goto FAIL;
+    }
+
+    switch (config->mode) {
+        MODECASE(STACKTOOL_MODE_DEFINEBYQUERY,         definebyqueryMode);
+        MODECASE(STACKTOOL_MODE_DEFINERUN,             definerunMode);
+        MODECASE(STACKTOOL_MODE_UPDATERUN,             updaterunMode);
+        MODECASE(STACKTOOL_MODE_ADDINPUTSKYFILE,       addinputskyfileMode);
+        MODECASE(STACKTOOL_MODE_INPUTSKYFILE,          inputskyfileMode);
+        MODECASE(STACKTOOL_MODE_TOSUM,                 tosumMode);
+        MODECASE(STACKTOOL_MODE_ADDSUMSKYFILE,         addsumskyfileMode);
+        MODECASE(STACKTOOL_MODE_SUMSKYFILE,            sumskyfileMode);
+        MODECASE(STACKTOOL_MODE_REVERTSUMSKYFILE,      revertsumskyfileMode);
+        MODECASE(STACKTOOL_MODE_PENDINGCLEANUPRUN,     pendingcleanuprunMode);
+        MODECASE(STACKTOOL_MODE_PENDINGCLEANUPSKYFILE, pendingcleanupskyfileMode);
+        MODECASE(STACKTOOL_MODE_DONECLEANUP,           donecleanupMode);
+        default:
+            psAbort("invalid option (this should not happen)");
+    }
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(EXIT_SUCCESS);
+
+FAIL:
+    psErrorStackPrint(stderr, "\n");
+    int exit_status = pxerrorGetExitStatus();
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exit_status);
+}
+
+
+static bool definebyqueryMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required options
+    PXOPT_LOOKUP_STR(workdir, config->args, "-workdir", true, false);
+
+    psMetadata *whereRE = psMetadataAlloc(); // rawExp where
+    psMetadata *whereWSF = psMetadataAlloc(); // warpSkyfile where
+    psMetadata *having = psMetadataAlloc(); // HAVING clause
+    // map -inst -> camera, etc
+    PXOPT_COPY_STR(config->args, whereRE, "-select_inst", "camera", "==");
+    PXOPT_COPY_STR(config->args, whereRE, "-select_telescope", "telescope", "==");
+    PXOPT_COPY_STR(config->args, whereRE, "-select_filter", "filter", "==");
+    PXOPT_COPY_STR(config->args, whereRE, "-select_uri", "uri", "==");
+    PXOPT_COPY_TIME(config->args, whereRE, "-select_dateobs_begin", "dateobs", ">=");
+    PXOPT_COPY_TIME(config->args, whereRE, "-select_dateobs_end", "dateobs", "<=");
+    PXOPT_COPY_F32(config->args, whereRE, "-select_airmass_min", "airmass", ">=");
+    PXOPT_COPY_F32(config->args, whereRE, "-select_airmass_max", "airmass", "<=");
+    PXOPT_COPY_F32(config->args, whereRE, "-select_sat_pixel_frac_max", "sat_pixel_frac", "<=");
+    PXOPT_COPY_F32(config->args, whereRE, "-select_exp_time_min", "exp_time", ">=");
+    PXOPT_COPY_F32(config->args, whereRE, "-select_exp_time_max", "exp_time", "<=");
+    PXOPT_COPY_F32(config->args, whereRE, "-select_ccd_temp_min", "ccd_temp", ">=");
+    PXOPT_COPY_F32(config->args, whereRE, "-select_ccd_temp_max", "ccd_temp", "<=");
+    PXOPT_COPY_F32(config->args, whereRE, "-select_posang_min", "posang", ">=");
+    PXOPT_COPY_F32(config->args, whereRE, "-select_posang_max", "posang", "<=");
+    PXOPT_COPY_F32(config->args, whereRE, "-select_solang_min", "solang", ">=");
+    PXOPT_COPY_F32(config->args, whereRE, "-select_solang_max", "solang", "<=");
+
+    PXOPT_COPY_STR(config->args, having, "-select_skycell_id", "skycell_id", "==");
+    PXOPT_COPY_S32(config->args, having, "-min_num", "num_warp", ">=");
+
+    PXOPT_LOOKUP_S32(randomLimit, config->args, "-random", false, false);
+
+    PXOPT_LOOKUP_S32(min_new, config->args, "-min_new", false, false);
+    PXOPT_LOOKUP_F32(min_frac, config->args, "-min_frac", false, false);
+
+    if (!psListLength(whereRE->list) && !psListLength(whereWSF->list) &&
+        !psMetadataLookupBool(NULL, config->args, "-all")) {
+        psFree(whereRE);
+        psFree(whereWSF);
+        psError(PXTOOLS_ERR_DATA, false, "search parameters are required");
+        return false;
+    }
+
+    // default
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_TIME(registered, config->args, "-registered", false, false);
+    PXOPT_COPY_STR(config->args, whereRE, "-select_exp_type", "exp_type", "==");
+    PXOPT_COPY_F32(config->args, whereWSF, "-select_good_frac_min", "good_frac", ">=");
+
+    psString select = pxDataGet("stacktool_definebyquery_part1.sql");
+    if (!select) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(whereRE->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(whereRE, "rawExp");
+        psStringAppend(&select, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(whereRE);
+
+    if (psListLength(whereWSF->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(whereWSF, "warpSkyfile");
+        psStringAppend(&select, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(whereWSF);
+
+    psString groupby = pxDataGet("stacktool_definebyquery_part2.sql");
+    if (!groupby) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+    psStringAppend(&select, " %s", groupby);
+    psFree(groupby);
+
+    // Restriction on aggregated quantities using HAVING
+    {
+        psString havingClause = NULL;   // HAVING string
+        if (psListLength(having->list)) {
+            havingClause = psDBGenerateWhereConditionSQL(having, NULL);
+        }
+
+        if (min_new > 0) {
+            if (havingClause) {
+                psStringAppend(&havingClause, " AND");
+            }
+            psStringAppend(&havingClause,
+                           " (num_warp - num_stack >= %d OR (num_warp >= %d AND num_stack IS NULL))",
+                           min_new, min_new);
+        }
+        if (isfinite(min_frac)) {
+            if (havingClause) {
+                psStringAppend(&havingClause, " AND");
+            }
+            // Avoiding division by zero
+            psStringAppend(&havingClause, " (num_warp >= %f * num_stack OR num_stack IS NULL)",
+                           (double)min_frac);
+        }
+        if (havingClause) {
+            psStringAppend(&select, " HAVING %s", havingClause);
+            psFree(havingClause);
+        }
+    }
+    psFree(having);
+
+
+    if (!p_psDBRunQuery(config->dbh, select)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(select);
+        return false;
+    }
+    psFree(select);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("stacktool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    psString insert = NULL;             // Insertion query
+    if (randomLimit > 0) {
+        insert = pxDataGet("stacktool_definebyquery_insert_random.sql");
+    } else {
+        insert = pxDataGet("stacktool_definebyquery_insert.sql");
+    }
+    if (!insert) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psArray *list = psArrayAllocEmpty(16); // List of runs, to print
+    for (long i = 0; i < output->n; i++) {
+        psMetadata *row = output->data[i]; // Row from select
+        bool status;
+
+        // pull out the skycell_id, tess_id, filter
+        psString skycell_id = psMetadataLookupStr(&status, row, "skycell_id");
+        if (!status) {
+            psError(PS_ERR_UNKNOWN, false, "failed to lookup skycell_id");
+            psFree(output);
+            psFree(insert);
+            psFree(list);
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            return false;
+        }
+
+        psString tess_id = psMetadataLookupStr(&status, row, "tess_id");
+        if (!status) {
+            psError(PS_ERR_UNKNOWN, false, "failed to lookup tess_id");
+            psFree(output);
+            psFree(insert);
+            psFree(list);
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            return false;
+        }
+
+        psString filter = psMetadataLookupStr(&status, row, "filter");
+        if (!status) {
+            psError(PS_ERR_UNKNOWN, false, "failed to lookup filter");
+            psFree(output);
+            psFree(insert);
+            psFree(list);
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            return false;
+        }
+
+        // create a new stackRun for this stack
+        stackRunRow *run = stackRunRowAlloc(
+	    0, 				// ID
+	    "new", 			// state
+	    workdir, 
+	    NULL, 			// workdir_state
+	    registered, 
+	    skycell_id, 
+	    tess_id, 
+	    filter);
+
+        if (!stackRunInsertObject(config->dbh, run)) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(output);
+            psFree(run);
+            psFree(insert);
+            psFree(list);
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            return false;
+        }
+
+        // figure out the new stack_id
+        psS64 stack_id = psDBLastInsertID(config->dbh);
+        run->stack_id = stack_id;
+
+        psArrayAdd(list, list->n, run);
+        psFree(run);
+
+        // Create a suitable insertion query for this run
+        psString thisInsert = psStringCopy(insert);
+        psString idString = NULL;
+        psStringAppend(&idString, "%" PRId64, stack_id);
+        psStringSubstitute(&thisInsert, idString, "@STACK_ID@");
+        psFree(idString);
+
+        if ((randomLimit > 0 && !p_psDBRunQuery(config->dbh, thisInsert, skycell_id, tess_id, filter,
+                                                randomLimit)) ||
+            (randomLimit <= 0 && !p_psDBRunQuery(config->dbh, thisInsert, skycell_id, tess_id, filter))) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(thisInsert);
+            psFree(insert);
+            psFree(output);
+            psFree(list);
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            return false;
+        }
+        psFree(thisInsert);
+    }
+    psFree(output);
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(list);
+        return false;
+    }
+
+    if (!stackRunPrintObjects(stdout, list, !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print object");
+        psFree(list);
+        return false;
+    }
+    psFree(list);
+    return true;
+}
+
+
+static bool definerunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required options
+    PXOPT_LOOKUP_STR(workdir, config->args, "-workdir", true, false);
+    PXOPT_LOOKUP_STR(skycell_id, config->args, "-skycell_id", true, false);
+    PXOPT_LOOKUP_STR(tess_id, config->args, "-tess_id", true, false);
+    PXOPT_LOOKUP_STR(filter, config->args, "-filter", true, false);
+
+    // default
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_TIME(registered, config->args, "-registered", false, false);
+
+    // we have to support multipe exp_ids
+    psMetadataItem *warp_ids = psMetadataLookup(config->args, "-warp_id");
+    if (!warp_ids) {
+        // this shouldn't actually happen when using psArgs
+        psError(PS_ERR_UNKNOWN, true, "-warp_id is required");
+        return false;
+    }
+
+    stackRunRow *run = stackRunRowAlloc(
+	0, 				// ID
+	"new", 				// state
+	workdir, 
+	NULL, 				// workdir_state
+	registered, 
+	skycell_id, 
+	tess_id, 
+	filter);
+
+    if (!run) {
+        psError(PS_ERR_UNKNOWN, false, "failed to alloc stackRun object");
+        return true;
+    }
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!stackRunInsertObject(config->dbh, run)) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(run);
+        return true;
+    }
+
+    // get the assigned warp_id
+    run->stack_id = psDBLastInsertID(config->dbh);
+
+    // insert the stackInputSkyfile rows
+    psListIterator *iter = psListIteratorAlloc(warp_ids->data.list, 0, false);
+    psMetadataItem *item = NULL;
+    while ((item = psListGetAndIncrement(iter))) {
+        // if the value is NULL this is probably the first pass through the
+        // loop and -warp_id was not specified at all
+        if (!item->data.V) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -warp_id");
+            return false;
+        }
+        if (!stackInputSkyfileInsert(config->dbh, run->stack_id, (psS64)atoll((char *)item->data.V))) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "failed to insert stackInputSkyfile rows");
+            return false;
+        }
+    }
+    psFree(iter);
+
+    // point of no return
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!stackRunPrintObject(stdout, run, !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print object");
+            psFree(run);
+            return false;
+    }
+
+    psFree(run);
+
+    return true;
+}
+
+
+static bool updaterunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_S64(stack_id, config->args, "-stack_id", true, false);
+    PXOPT_LOOKUP_STR(state, config->args, "-state", true, false);
+
+    if (state) {
+        // set detRun.state to state
+        return setstackRunState(config, stack_id, state);
+    }
+
+    return true;
+}
+
+
+static bool addinputskyfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_S64(stack_id, config->args, "-stack_id", true, false);
+    PXOPT_LOOKUP_S64(warp_id, config->args, "-warp_id", true, false);
+
+    // XXX need to validate the warp_id here
+    // XXX instead of validiting it here we should just use forgein key
+    // constrants
+    if (!stackInputSkyfileInsert(config->dbh,
+            stack_id,
+            warp_id
+        )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool inputskyfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-warp_id", "warp_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-stack_id", "stack_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("stacktool_inputskyfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "stackInputSkyfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("stacktool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "stackInputSkyfile", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool tosumMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-warp_id", "warp_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-stack_id", "stack_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("stacktool_tosum.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "stackSumSkyfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("stacktool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "stackSumSkyfile", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool addsumskyfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required
+    PXOPT_LOOKUP_S64(stack_id, config->args, "-stack_id", true, false);
+
+    // optional
+    PXOPT_LOOKUP_STR(uri, config->args, "-uri", false, false);
+    PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
+    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
+    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
+    PXOPT_LOOKUP_F32(dtime_stack, config->args, "-dtime_stack", false, false);
+    PXOPT_LOOKUP_STR(hostname, config->args, "-hostname", false, false);
+    PXOPT_LOOKUP_F32(good_frac, config->args, "-good_frac", false, false);
+
+    // default values
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // XXX need to validate the stack_id here
+    // XXX instead of validiting it here we should just use forgein key
+    // constrants
+    if (!stackSumSkyfileInsert(config->dbh,
+                               stack_id,
+                               uri,
+                               path_base,
+                               bg,
+                               bg_stdev,
+                               dtime_stack,
+                               hostname,
+                               good_frac,
+                               code
+          )) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!setstackRunState(config, stack_id, "full")) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "failed to change stackRun's state");
+        return false;
+    }
+
+    // point of no return
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool sumskyfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-warp_id", "warpRun.warp_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-stack_id", "stackSumSkyfile.stack_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "rawExp.exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_name", "rawExp.exp_name", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("stacktool_sumskyfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("stacktool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        if (!ippdbPrintMetadatas(stdout, output, "stackSumSkyfile", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool revertsumskyfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-stack_id", "stack_id", "==");
+    PXOPT_COPY_S16(config->args, where, "-code", "fault", "==");
+
+    psString query = pxDataGet("stacktool_revertsumskyfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "stackSumSkyfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    if (psDBAffectedRows(config->dbh) < 1) {
+        psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool setstackRunState(pxConfig *config, psS64 stack_id, const char *state)
+{
+    PS_ASSERT_PTR_NON_NULL(state, false);
+
+    // check that state is a valid string value
+    if (!pxIsValidState(state)) {
+        psError(PS_ERR_UNKNOWN, false, "invalid stackRun state: %s", state);
+        return false;
+    }
+
+    char *query = "UPDATE stackRun SET state = '%s' WHERE stack_id = %"PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, state, stack_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for stack_id %"PRId64, stack_id);
+        return false;
+    }
+
+    return true;
+}
+
+static bool pendingcleanuprunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("stacktool_pendingcleanuprun.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("stacktool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "stackPendingCleanupRun", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool pendingcleanupskyfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_S64(stack_id, config->args, "-stack_id", false, false);
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    if (stack_id) {
+        PXOPT_COPY_S64(config->args, where, "-stack_id", "stack_id", "==");
+    }
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("stacktool_pendingcleanupskyfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("stacktool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "stackPendingCleanupSkyfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool donecleanupMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("stacktool_donecleanup.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("stacktool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "stackDoneCleanup", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/stacktool.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/stacktool.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/stacktool.h	(revision 22158)
@@ -0,0 +1,43 @@
+/*
+ * stacktool.h
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef STACKTOOL_H
+#define STACKTOOL_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+    STACKTOOL_MODE_NONE           = 0x0,
+    STACKTOOL_MODE_DEFINEBYQUERY,
+    STACKTOOL_MODE_DEFINERUN,
+    STACKTOOL_MODE_UPDATERUN,
+    STACKTOOL_MODE_ADDINPUTSKYFILE,
+    STACKTOOL_MODE_INPUTSKYFILE,
+    STACKTOOL_MODE_TOSUM,
+    STACKTOOL_MODE_ADDSUMSKYFILE,
+    STACKTOOL_MODE_SUMSKYFILE,
+    STACKTOOL_MODE_REVERTSUMSKYFILE,
+    STACKTOOL_MODE_PENDINGCLEANUPRUN,
+    STACKTOOL_MODE_PENDINGCLEANUPSKYFILE,
+    STACKTOOL_MODE_DONECLEANUP,
+} stacktoolMode;
+
+pxConfig *stacktoolConfig(pxConfig *config, int argc, char **argv);
+
+#endif // STACKTOOL_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/stacktoolConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/stacktoolConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/stacktoolConfig.c	(revision 22158)
@@ -0,0 +1,197 @@
+/*
+ * stacktoolConfig.c
+ *
+ * Copyright (C) 2007-2008  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <psmodules.h>
+
+#include "pxtools.h"
+#include "stacktool.h"
+
+pxConfig *stacktoolConfig(pxConfig *config, int argc, char **argv)
+{
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    pmConfigReadParamsSet(false);
+
+    // setup site config
+    config->modules = pmConfigRead(&argc, argv, NULL);
+    if (!config->modules) {
+        psError(PS_ERR_UNKNOWN, false, "Can't find site configuration");
+        psFree(config);
+        return NULL;
+    }
+
+    psTime *now = psTimeGetNow(PS_TIME_TAI);
+
+    // -definebyquery
+    psMetadata *definebyqueryArgs = psMetadataAlloc();
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-workdir", 0, "define workdir (required)", NULL);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-registered", 0, "time detrend run was registered", now);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-select_skycell_id", 0, "search for skycell_id", NULL);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-select_good_frac_min", 0, "define min good_frac", 0.0);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-select_exp_type", 0, "search for exp_type", "object");
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-select_inst", 0, "search for camera", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-select_telescope", 0, "search for telescope", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-select_filter", 0, "search for filter", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-select_uri", 0, "search for uri", NULL);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-select_dateobs_begin", 0, "search for exposures by time (>=)", NULL);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-select_dateobs_end", 0, "search for exposures by time (<)", NULL);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-select_airmass_min", 0, "define min airmass", NAN);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-select_airmass_max", 0, "define max airmass", NAN);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-select_sat_pixel_frac_max", 0, "define max fraction of saturated pixels", NAN);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-select_exp_time_min", 0, "define min exposure time", NAN);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-select_exp_time_max", 0, "define max exposure time", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-select_ccd_temp_min", 0, "define min ccd tempature", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-select_ccd_temp_max", 0, "define max ccd tempature", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-select_posang_min", 0, "define min rotator position angle", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-select_posang_max", 0, "define max rotator position angle", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-select_solang_min", 0, "define min solar angle", NAN);
+    psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-select_solang_max", 0, "define max solar angle", NAN);
+    psMetadataAddS32(definebyqueryArgs, PS_LIST_TAIL, "-random", 0, "use this number of random elements", 0);
+    psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-all", 0, "allow everything to be queued without search terms", false);
+    psMetadataAddS32(definebyqueryArgs, PS_LIST_TAIL, "-min_num", 0, "minimum number of inputs", 0);
+    psMetadataAddS32(definebyqueryArgs, PS_LIST_TAIL, "-min_new", 0, "minimum number of new inputs", 0);
+    psMetadataAddF32(definebyqueryArgs, PS_LIST_TAIL, "-min_frac", 0, "minumum fraction of new inputs", NAN);
+    psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-simple", 0, "use the simple output format", false);
+
+    // -definerun
+    psMetadata *definerunArgs = psMetadataAlloc();
+    psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-workdir", 0,            "define workdir (required)", NULL);
+    psMetadataAddTime(definerunArgs, PS_LIST_TAIL, "-registered",  0,            "time detrend run was registered", now);
+    psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-skycell_id",  0,            "define skycell ID (required)", NULL);
+    psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-tess_id",  0,            "define tessellation ID (required)", NULL);
+    psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-filter", 0, "define filter (required)", NULL);
+    psMetadataAddS64(definerunArgs, PS_LIST_TAIL, "-warp_id",             PS_META_DUPLICATE_OK,             "include this warp ID (multiple OK, required)", 0);
+    psMetadataAddBool(definerunArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -updaterun
+    psMetadata *updaterunArgs = psMetadataAlloc();
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-stack_id", 0,            "define stack ID (required)", 0);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-state", 0,            "set state (required)", NULL);
+
+    // -addinputskyfile
+    psMetadata *addinputskyfileArgs = psMetadataAlloc();
+    psMetadataAddS64(addinputskyfileArgs, PS_LIST_TAIL, "-stack_id", 0,            "define stack ID (required)", 0);
+    psMetadataAddS64(addinputskyfileArgs, PS_LIST_TAIL, "-warp_id", 0,            "define warp ID (required)", 0);
+
+    // -inputskyfile
+    psMetadata *inputskyfileArgs = psMetadataAlloc();
+    psMetadataAddS64(inputskyfileArgs, PS_LIST_TAIL, "-stack_id", 0,            "search by stack ID", 0);
+    psMetadataAddS64(inputskyfileArgs, PS_LIST_TAIL, "-warp_id", 0,            "search by warp ID", 0);
+    psMetadataAddU64(inputskyfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(inputskyfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -tosum
+    psMetadata *tosumArgs = psMetadataAlloc();
+    psMetadataAddS64(tosumArgs, PS_LIST_TAIL, "-stack_id", 0,            "search by stack ID", 0);
+    psMetadataAddS64(tosumArgs, PS_LIST_TAIL, "-warp_id", 0,            "search by warp ID", 0);
+    psMetadataAddU64(tosumArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(tosumArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -addsumskyfile
+    psMetadata *addsumskyfileArgs = psMetadataAlloc();
+    psMetadataAddS64(addsumskyfileArgs, PS_LIST_TAIL, "-stack_id", 0,            "define stack ID (required)", 0);
+    psMetadataAddStr(addsumskyfileArgs, PS_LIST_TAIL, "-uri", 0,            "define URI of file", 0);
+    psMetadataAddStr(addsumskyfileArgs, PS_LIST_TAIL, "-path_base", 0,            "define base output location", 0);
+    psMetadataAddF64(addsumskyfileArgs, PS_LIST_TAIL, "-bg",  0,            "define exposue background", NAN);
+    psMetadataAddF64(addsumskyfileArgs, PS_LIST_TAIL, "-bg_stdev",  0,            "define exposue background mean stdev", NAN);
+    psMetadataAddF32(addsumskyfileArgs, PS_LIST_TAIL, "-dtime_stack",  0,            "define elapsed processing time", NAN);
+    psMetadataAddStr(addsumskyfileArgs, PS_LIST_TAIL, "-hostname", 0,            "define hostname", 0);
+    psMetadataAddF32(addsumskyfileArgs, PS_LIST_TAIL, "-good_frac",  0,            "define %% of good pixels", NAN);
+    psMetadataAddS16(addsumskyfileArgs, PS_LIST_TAIL, "-code",  0,            "set fault code", 0);
+
+    // -sumskyfile
+    psMetadata *sumskyfileArgs= psMetadataAlloc();
+    psMetadataAddS64(sumskyfileArgs, PS_LIST_TAIL, "-stack_id", 0,            "search by stack ID", 0);
+    psMetadataAddS64(sumskyfileArgs, PS_LIST_TAIL, "-warp_id", 0,            "search by warp ID", 0);
+    psMetadataAddS64(sumskyfileArgs, PS_LIST_TAIL, "-exp_id", 0,            "search by exposure ID", 0);
+    psMetadataAddStr(sumskyfileArgs, PS_LIST_TAIL, "-exp_name", 0,          "search by exposure name", NULL);
+    psMetadataAddU64(sumskyfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(sumskyfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -revertsumskyfile
+    psMetadata *revertsumskyfileArgs= psMetadataAlloc();
+    psMetadataAddS64(revertsumskyfileArgs, PS_LIST_TAIL, "-stack_id", 0,            "search by stack ID (required)", 0);
+    psMetadataAddS16(revertsumskyfileArgs, PS_LIST_TAIL, "-code",  0,            "search by fault code", 0);
+
+    // -pendingcleanuprun
+    psMetadata *pendingcleanuprunArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingcleanuprunArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddBool(pendingcleanuprunArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanuprunArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -pendingcleanupskyfile
+    psMetadata *pendingcleanupskyfileArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingcleanupskyfileArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddS64(pendingcleanupskyfileArgs, PS_LIST_TAIL, "-stack_id", 0,          "search by stack ID", 0);
+    psMetadataAddBool(pendingcleanupskyfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanupskyfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -donecleanup
+    psMetadata *donecleanupArgs = psMetadataAlloc();
+    psMetadataAddStr(donecleanupArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddBool(donecleanupArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(donecleanupArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    psFree(now);
+
+    psMetadata *argSets = psMetadataAlloc();
+    psMetadata *modes   = psMetadataAlloc();
+
+    PXOPT_ADD_MODE("-definebyquery", "Define a new stackRun by searching for warp IDs", STACKTOOL_MODE_DEFINEBYQUERY,  definebyqueryArgs);
+    PXOPT_ADD_MODE("-definerun",       "", STACKTOOL_MODE_DEFINERUN,      definerunArgs);
+    PXOPT_ADD_MODE("-updaterun",       "", STACKTOOL_MODE_UPDATERUN,      updaterunArgs);
+    PXOPT_ADD_MODE("-addinputskyfile", "", STACKTOOL_MODE_ADDINPUTSKYFILE, addinputskyfileArgs);
+    PXOPT_ADD_MODE("-inputskyfile",    "", STACKTOOL_MODE_INPUTSKYFILE,    inputskyfileArgs);
+    PXOPT_ADD_MODE("-tosum",           "", STACKTOOL_MODE_TOSUM,          tosumArgs);
+    PXOPT_ADD_MODE("-addsumskyfile",   "", STACKTOOL_MODE_ADDSUMSKYFILE,   addsumskyfileArgs);
+    PXOPT_ADD_MODE("-sumskyfile",      "list results of stackRun", STACKTOOL_MODE_SUMSKYFILE,      sumskyfileArgs);
+    PXOPT_ADD_MODE("-revertsumskyfile","", STACKTOOL_MODE_REVERTSUMSKYFILE,      revertsumskyfileArgs);
+    PXOPT_ADD_MODE("-pendingcleanuprun",     "show runs that need to be cleaned up", STACKTOOL_MODE_PENDINGCLEANUPRUN,    pendingcleanuprunArgs);
+    PXOPT_ADD_MODE("-pendingcleanupskyfile", "show runs that need to be cleaned up", STACKTOOL_MODE_PENDINGCLEANUPSKYFILE, pendingcleanupskyfileArgs);
+    PXOPT_ADD_MODE("-donecleanup",           "show runs that have been cleaned",     STACKTOOL_MODE_DONECLEANUP,          donecleanupArgs);
+
+    if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
+        psError(PS_ERR_UNKNOWN, true, "option parsing failed");
+        psFree(argSets);
+        psFree(modes);
+        psFree(config);
+        return NULL;
+    }
+
+    psFree(argSets);
+    psFree(modes);
+
+    // define Database handle, if used
+    // do this last so we don't setup a connection before CLI options are
+    // validated
+    config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+    if (!config->dbh) {
+        psError(PS_ERR_UNKNOWN, false, "Can't configure database");
+        psFree(config);
+        return NULL;
+    }
+
+    return config;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/warptool.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/warptool.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/warptool.c	(revision 22158)
@@ -0,0 +1,1351 @@
+/*
+ * warptool.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVB_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <ippdb.h>
+
+#include "pxtools.h"
+#include "warptool.h"
+#include "pxwarp.h"
+
+static psS64 definerunMode(pxConfig *config);
+static bool updaterunMode(pxConfig *config);
+static bool expMode(pxConfig *config);
+static bool imfileMode(pxConfig *config);
+static bool tooverlapMode(pxConfig *config);
+static bool addoverlapMode(pxConfig *config);
+static bool scmapMode(pxConfig *config);
+static bool towarpedMode(pxConfig *config);
+static bool addwarpedMode(pxConfig *config);
+static bool warpedMode(pxConfig *config);
+static bool revertwarpedMode(pxConfig *config);
+static bool blockMode(pxConfig *config);
+static bool maskedMode(pxConfig *config);
+static bool unblockMode(pxConfig *config);
+static bool pendingcleanuprunMode(pxConfig *config);
+static bool pendingcleanupwarpMode(pxConfig *config);
+static bool donecleanupMode(pxConfig *config);
+
+static bool parseAndInsertSkyCellMap(pxConfig *config, const char *mapfile);
+static bool isValidMode(pxConfig *config, const char *mode);
+bool warpCompletedRuns(pxConfig *config);
+
+# define MODECASE(caseName, func) \
+    case caseName: \
+    if (!func(config)) { \
+        goto FAIL; \
+    } \
+    break;
+
+int main(int argc, char **argv)
+{
+    psLibInit(NULL);
+
+    pxConfig *config = warptoolConfig(NULL, argc, argv);
+    if (!config) {
+        psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+        goto FAIL;
+    }
+
+    switch (config->mode) {
+        MODECASE(WARPTOOL_MODE_DEFINERUN,          definerunMode);
+        MODECASE(WARPTOOL_MODE_UPDATERUN,          updaterunMode);
+        MODECASE(WARPTOOL_MODE_EXP,                expMode);
+        MODECASE(WARPTOOL_MODE_IMFILE,             imfileMode);
+        MODECASE(WARPTOOL_MODE_TOOVERLAP,          tooverlapMode);
+        MODECASE(WARPTOOL_MODE_ADDOVERLAP,         addoverlapMode);
+        MODECASE(WARPTOOL_MODE_SCMAP,              scmapMode);
+        MODECASE(WARPTOOL_MODE_TOWARPED,           towarpedMode);
+        MODECASE(WARPTOOL_MODE_ADDWARPED,          addwarpedMode);
+        MODECASE(WARPTOOL_MODE_WARPED,             warpedMode);
+        MODECASE(WARPTOOL_MODE_REVERTWARPED,       revertwarpedMode);
+        MODECASE(WARPTOOL_MODE_BLOCK,              blockMode);
+        MODECASE(WARPTOOL_MODE_MASKED,             maskedMode);
+        MODECASE(WARPTOOL_MODE_UNBLOCK,            unblockMode);
+        MODECASE(WARPTOOL_MODE_PENDINGCLEANUPRUN,  pendingcleanuprunMode);
+        MODECASE(WARPTOOL_MODE_PENDINGCLEANUPSKYFILE, pendingcleanupwarpMode);
+        MODECASE(WARPTOOL_MODE_DONECLEANUP,        donecleanupMode);
+
+        default:
+            psAbort("invalid option (this should not happen)");
+    }
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(EXIT_SUCCESS);
+
+FAIL:
+    psErrorStackPrint(stderr, "\n");
+    int exit_status = pxerrorGetExitStatus();
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exit_status);
+}
+
+
+static psS64 definerunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_S64(fake_id, config->args, "-fake_id", true, false); // required
+    PXOPT_LOOKUP_STR(mode, config->args, "-mode", true, false); // required
+    PXOPT_LOOKUP_STR(workdir, config->args, "-workdir", true, false); // required
+    PXOPT_LOOKUP_STR(label, config->args, "-label", false, false);
+    PXOPT_LOOKUP_STR(dvodb, config->args, "-dvodb", false, false);
+    PXOPT_LOOKUP_STR(tess_id, config->args, "-tess_id", false, false);
+    PXOPT_LOOKUP_STR(end_stage, config->args, "-end_stage", false, false);
+    PXOPT_LOOKUP_TIME(registered, config->args, "-registered", false, false);
+    PXOPT_LOOKUP_BOOL(magiced, config->args, "-magiced", false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // check mode
+    if (mode && !isValidMode(config, mode)) {
+        psError(PS_ERR_UNKNOWN, false, "invalid mode");
+        return false;
+    }
+
+    warpRunRow *warpRun = warpRunRowAlloc(
+            0,          // ID
+            fake_id,
+            mode,
+            "new",      // state
+            workdir,
+            "dirty",    // workdir_state
+            label,
+            dvodb,
+            tess_id,
+            end_stage,
+            registered,
+            magiced
+    );
+    if (!warpRun) {
+        psError(PS_ERR_UNKNOWN, false, "failed to alloc warpRun object");
+        return true;
+    }
+    if (!warpRunInsertObject(config->dbh, warpRun)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(warpRun);
+        return true;
+    }
+
+    // get the assigned warp_id
+    psS64 warp_id = psDBLastInsertID(config->dbh);
+    warpRun->warp_id = warp_id;
+
+    if (!warpRunPrintObject(stdout, warpRun, !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print object");
+            psFree(warpRun);
+            return false;
+    }
+
+    psFree(warpRun);
+
+    return warp_id;
+}
+
+
+static bool updaterunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-warp_id", "warp_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-fake_id", "fake_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-chip_id", "chip_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_name", "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where, "-inst", "camera", "==");
+    PXOPT_COPY_STR(config->args, where, "-telescope", "telescope", "==");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_begin", "dateobs", ">=");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_end", "dateobs", "<=");
+    PXOPT_COPY_STR(config->args, where, "-exp_tag", "exp_tag", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_type", "exp_type", "==");
+    PXOPT_COPY_STR(config->args, where, "-filelevel", "filelevel", "==");
+    PXOPT_COPY_STR(config->args, where, "-reduction", "reduction", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter", "filter", "==");
+    PXOPT_COPY_F32(config->args, where, "-airmass_min", "airmass", ">=");
+    PXOPT_COPY_F32(config->args, where, "-airmass_max", "airmass", "<");
+    PXOPT_COPY_F64(config->args, where, "-ra_min", "ra", ">=");
+    PXOPT_COPY_F64(config->args, where, "-ra_max", "ra", "<");
+    PXOPT_COPY_F64(config->args, where, "-decl_min", "decl", ">=");
+    PXOPT_COPY_F64(config->args, where, "-decl_max", "decl", "<");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_min", "exp_time", ">=");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_max", "exp_time", "<");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_min", "sat_pixel_frac", ">=");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_max", "sat_pixel_frac", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_min", "bt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_max", "bt", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_min", "bg_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_max", "bg_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_min", "bg_mean_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_max", "bg_mean_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-alt_min", "alt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-alt_max", "alt", "<");
+    PXOPT_COPY_F64(config->args, where, "-az_min", "az", ">=");
+    PXOPT_COPY_F64(config->args, where, "-az_max", "az", "<");
+    PXOPT_COPY_F64(config->args, where, "-ccd_temp_min", "ccd_temp", ">=");
+    PXOPT_COPY_F64(config->args, where, "-ccd_temp_max", "ccd_temp", "<");
+    PXOPT_COPY_F64(config->args, where, "-posang_min", "posang", ">=");
+    PXOPT_COPY_F64(config->args, where, "-posang_max", "posang", "<");
+    PXOPT_COPY_STR(config->args, where, "-object", "object", "==");
+    PXOPT_COPY_F32(config->args, where, "-solang_min", "solang", ">=");
+    PXOPT_COPY_F32(config->args, where, "-solang_max", "solang", "<");
+
+    if (!psListLength(where->list)
+        && !psMetadataLookupBool(NULL, config->args, "-all")) {
+        psFree(where);
+        where = NULL;
+        psError(PXTOOLS_ERR_DATA, false, "search parameters are required");
+        return false;
+    }
+
+    PXOPT_LOOKUP_STR(state, config->args, "-state", false, false);
+    PXOPT_LOOKUP_STR(label, config->args, "-label", false, false);
+
+    if ((!state) && (!label)) {
+        psError(PXTOOLS_ERR_DATA, false, "parameters (-state or -label) are required");
+        psFree(where);
+        return false;
+    }
+
+    if (state) {
+        // set warpRun.state to state
+        if (!pxwarpRunSetStateByQuery(config, where, state)) {
+            psFree(where);
+            return false;
+        }
+    }
+
+    if (label) {
+        // set chipRun.label to label
+        if (!pxwarpRunSetLabelByQuery(config, where, label)) {
+            psFree(where);
+            return false;
+        }
+    }
+
+    psFree(where);
+
+    return true;
+}
+
+
+static bool expMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-warp_id", "warp_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-fake_id", "fake_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // find all rawImfiles matching the default query
+    psString query = pxDataGet("warptool_exp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "warpRun");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("warptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "warpRun", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool imfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-warp_id", "warp_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-fake_id", "fake_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // find all rawImfiles matching the default query
+    psString query = pxDataGet("warptool_imfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "warpRun");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("warptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "warpInputImfile", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool tooverlapMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-warp_id", "warp_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // find all rawImfiles matching the default query
+    psString query = pxDataGet("warptool_tooverlap.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "warpRun");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("warptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "warpRun", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool addoverlapMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(mapfile, config->args, "-mapfile", false, false);
+    PXOPT_LOOKUP_S64(warp_id, config->args, "-warp_id", false, false);
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (code == 0) {
+        if (!parseAndInsertSkyCellMap(config, mapfile)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to inject mapfile: %s into the database", mapfile);
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            return false;
+        }
+    } else {
+        warpSkyCellMapInsert(config->dbh,
+            warp_id,
+            NULL,   // skycell_id
+            NULL,   // tess_id
+            NULL,   // class_id
+            code    // fault
+        );
+    }
+
+    // point of no return
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool parseAndInsertSkyCellMap(pxConfig *config, const char *mapfile)
+{
+    unsigned int nFail = 0;
+    psMetadata *skycells = psMetadataConfigRead(NULL, &nFail, mapfile, false);
+    if (!skycells) {
+        psError(PS_ERR_UNKNOWN, false, "failed to parse mapfile: %s", mapfile);
+        return false;
+    }
+    if (nFail) {
+        psError(PS_ERR_UNKNOWN, false, "there were %d errors parsing mapfile: %s", nFail, mapfile);
+        psFree(skycells);
+        return false;
+    }
+
+    psMetadataItem *item = NULL;
+    psMetadataIterator *iter = psMetadataIteratorAlloc(skycells, 0, NULL);
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        if (item->type != PS_DATA_METADATA) {
+            psError(PS_ERR_UNKNOWN, false, "mapfile: %s is in the wrong format", mapfile);
+            psFree(iter);
+            psFree(skycells);
+            return false;
+        }
+
+        psMetadata *sc = item->data.md;
+        // this conversion isn't strictly nessicary but it's an easy way of
+        // validating the format
+        warpSkyCellMapRow *row = warpSkyCellMapObjectFromMetadata(sc);
+        if (!row) {
+            psError(PS_ERR_UNKNOWN, false, "failed to convert mapfile: %s metdata entry into a warpSkyCellMap object", mapfile);
+            psFree(iter);
+            psFree(skycells);
+            return false;
+        }
+
+        if (!warpSkyCellMapInsertObject(config->dbh, row)) {
+            psErrorCode err = psErrorCodeLast();
+            switch (err) {
+                case PS_ERR_DB_CLIENT:
+                    psError(PXTOOLS_ERR_SYS, false, "database error");
+                case PS_ERR_DB_SERVER:
+                    psError(PXTOOLS_ERR_PROG, false, "database error");
+                default:
+                    psError(PXTOOLS_ERR_PROG, false, "unknown error");
+            }
+            psFree(row);
+            psFree(iter);
+            psFree(skycells);
+            return false;
+        }
+
+        psFree(row);
+    }
+    psFree(iter);
+    psFree(skycells);
+
+    return true;
+}
+
+
+static bool scmapMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-warp_id", "warp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-skycell_id", "skycell_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-tess_id", "tess_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // find all rawImfiles matching the default query
+    psString query = pxDataGet("warptool_scmap.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "warpSkyCellMap");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("warptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "warpSkyCellMap", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool towarpedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-warp_id", "warp_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // find all rawImfiles matching the default query
+    psString query = pxDataGet("warptool_towarped.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "warpSkyCellMap");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("warptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "warpPendingSkyCell", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool addwarpedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_S64(warp_id, config->args, "-warp_id", true, false);
+    PXOPT_LOOKUP_STR(skycell_id, config->args, "-skycell_id", true, false);
+    PXOPT_LOOKUP_STR(tess_id, config->args, "-tess_id", true, false);
+
+    // optional
+    PXOPT_LOOKUP_STR(uri, config->args, "-uri", false, false);
+    PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
+    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
+    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
+    PXOPT_LOOKUP_F32(dtime_warp, config->args, "-dtime_warp", false, false);
+    PXOPT_LOOKUP_S32(xmin, config->args, "-xmin", false, false);
+    PXOPT_LOOKUP_S32(xmax, config->args, "-xmax", false, false);
+    PXOPT_LOOKUP_S32(ymin, config->args, "-ymin", false, false);
+    PXOPT_LOOKUP_S32(ymax, config->args, "-ymax", false, false);
+    PXOPT_LOOKUP_STR(hostname, config->args, "-hostname", false, false);
+    PXOPT_LOOKUP_F32(good_frac, config->args, "-good_frac", false, false);
+    PXOPT_LOOKUP_BOOL(ignore, config->args, "-ignore", false);
+
+    // default values
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+
+    // we don't want to insert the last skyfile in a run but then not mark the
+    // run as 'stop'
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // XXX need to validate that this coresponds to an warpInputImfile
+    if (!warpSkyfileInsert(config->dbh,
+                           warp_id,
+                           skycell_id,
+                           tess_id,
+                           uri,
+                           path_base,
+                           bg,
+                           bg_stdev,
+                           dtime_warp,
+                           hostname,
+                           good_frac,
+                           xmin,
+                           xmax,
+                           ymin,
+                           ymax,
+                           ignore,
+                           code
+        )) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!warpCompletedRuns(config)) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // point of no return
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+bool warpCompletedRuns(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // XXX this SQL has not been broken out to into seperate files as the MYSQL
+    // < 5 & MYSQL 5 versions need to be kept in sync
+
+#undef MYSQL5
+#if MYSQL5
+    // XXX at MySQL 4.1.21 (probably all of 4.1.x) chokes and dies on this
+    // statement as it thinks it is trying to select from the table being
+    // updated. The 4.1 manual says that nested sub-queries are explicited
+    // allowed to do this with update statements as a temporary table is
+    // created so that you are not actually selecting from the table you are
+    // modifying.
+    char *query =
+        "UPDATE warpRun\n"
+        "   SET warpRun.state = 'stop'\n"
+        " WHERE\n"
+        "   warpRun.warp_id =\n"
+        "   (SELECT DISTINCT\n"
+        "       warp_id\n"
+        "   FROM\n"
+        "       (SELECT DISTINCT\n"
+        "           warpRun.warp_id,\n"
+        "           warpSkyCellMap.warp_id as foo,\n"
+        "           warpSkyfile.warp_id as bar\n"
+        "       FROM warpRun\n"
+        "       JOIN warpSkyCellMap\n"
+        "           USING(warp_id)\n"
+        "       LEFT JOIN warpSkyfile\n"
+        "           USING(warp_id, skycell_id, tess_id)\n"
+        "       WHERE\n"
+        "           warpRun.state = 'run'\n"
+        "       GROUP BY\n"
+        "           warpRun.warp_id\n"
+        "       HAVING\n"
+        "       COUNT(warpSkyCellMap.warp_id) = COUNT(warpSkyfile.warp_id)\n"
+        "       ) as Foo\n"
+        "   )\n";
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+#else // if MYSQL5
+{
+    char *query =
+        "CREATE TEMPORARY TABLE finished\n"
+        " (warp_id INT, PRIMARY KEY(warp_id)) ENGINE=MEMORY\n";
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+}
+
+{
+    char *query =
+        "INSERT INTO finished\n"
+        " SELECT\n"
+        "   warp_id\n"
+        " FROM\n"
+        "   (SELECT DISTINCT\n"
+        "       warpRun.warp_id,\n"
+        "       warpSkyCellMap.warp_id as foo,\n"
+        "       warpSkyfile.warp_id as bar\n"
+        "   FROM warpRun\n"
+        "   JOIN warpSkyCellMap\n"
+        "       USING(warp_id)\n"
+        "   LEFT JOIN warpSkyfile\n"
+        "       USING(warp_id, skycell_id)\n"
+        "   WHERE\n"
+        "       warpRun.state = 'run'\n"
+        "   GROUP BY\n"
+        "       warpRun.warp_id\n"
+        "   HAVING\n"
+        "       COUNT(warpSkyCellMap.warp_id) = COUNT(warpSkyfile.warp_id)\n"
+        " ) as Foo \n";
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+}
+
+{
+    char *query =
+        "UPDATE warpRun\n"
+        "   SET warpRun.state = 'stop'\n"
+        " WHERE\n"
+        "   warpRun.warp_id =\n"
+        "   (SELECT DISTINCT\n"
+        "       warp_id\n"
+        "   FROM finished\n"
+        "   )\n";
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+}
+#endif // if MYSQL5
+
+    return true;
+}
+
+static bool warpedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-warp_id",    "warpSkyfile.warp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-skycell_id", "warpSkyfile.skycell_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-tess_id",    "warpSkyfile.tess_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id",     "rawExp.exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_name",   "rawExp.exp_name", "==");
+    PXOPT_COPY_S64(config->args, where, "-fake_id",    "fakeRun.fake_id", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // find all rawImfiles matching the default query
+    psString query = pxDataGet("warptool_warped.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("warptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "warpSkyfile", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool revertwarpedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-warp_id", "warp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-skycell_id", "skycell_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-tess_id", "tess_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-fake_id", "fake_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-chip_id", "chip_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+
+    // XXX These may need to be updated with the table name?
+    PXOPT_COPY_STR(config->args, where, "-exp_name", "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where, "-inst", "camera", "==");
+    PXOPT_COPY_STR(config->args, where, "-telescope", "telescope", "==");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_begin", "dateobs", ">=");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_end", "dateobs", "<=");
+    PXOPT_COPY_STR(config->args, where, "-exp_tag", "exp_tag", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_type", "exp_type", "==");
+    PXOPT_COPY_STR(config->args, where, "-filelevel", "filelevel", "==");
+    PXOPT_COPY_STR(config->args, where, "-reduction", "reduction", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter", "filter", "==");
+
+    PXOPT_COPY_F32(config->args, where, "-airmass_min", "airmass", ">=");
+    PXOPT_COPY_F32(config->args, where, "-airmass_max", "airmass", "<");
+    PXOPT_COPY_F64(config->args, where, "-ra_min", "ra", ">=");
+    PXOPT_COPY_F64(config->args, where, "-ra_max", "ra", "<");
+    PXOPT_COPY_F64(config->args, where, "-decl_min", "decl", ">=");
+    PXOPT_COPY_F64(config->args, where, "-decl_max", "decl", "<");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_min", "exp_time", ">=");
+    PXOPT_COPY_F32(config->args, where, "-exp_time_max", "exp_time", "<");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_min", "sat_pixel_frac", ">=");
+    PXOPT_COPY_F32(config->args, where, "-sat_pixel_frac_max", "sat_pixel_frac", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_min", "bt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_max", "bt", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_min", "bg_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_stdev_max", "bg_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_min", "bg_mean_stdev", ">=");
+    PXOPT_COPY_F64(config->args, where, "-bg_mean_stdev_max", "bg_mean_stdev", "<");
+    PXOPT_COPY_F64(config->args, where, "-alt_min", "alt", ">=");
+    PXOPT_COPY_F64(config->args, where, "-alt_max", "alt", "<");
+    PXOPT_COPY_F64(config->args, where, "-az_min", "az", ">=");
+    PXOPT_COPY_F64(config->args, where, "-az_max", "az", "<");
+    PXOPT_COPY_F64(config->args, where, "-ccd_temp_min", "ccd_temp", ">=");
+    PXOPT_COPY_F64(config->args, where, "-ccd_temp_max", "ccd_temp", "<");
+    PXOPT_COPY_F64(config->args, where, "-posang_min", "posang", ">=");
+    PXOPT_COPY_F64(config->args, where, "-posang_max", "posang", "<");
+    PXOPT_COPY_STR(config->args, where, "-object", "object", "==");
+    PXOPT_COPY_F32(config->args, where, "-solang_min", "solang", ">=");
+    PXOPT_COPY_F32(config->args, where, "-solang_max", "solang", "<");
+    PXOPT_COPY_S16(config->args, where, "-code", "warpSkyfile.fault", "==");
+
+    if (!psListLength(where->list)
+        && !psMetadataLookupBool(NULL, config->args, "-all")) {
+        psFree(where);
+        psError(PXTOOLS_ERR_DATA, false, "search parameters are required");
+        return false;
+    }
+
+    psString query = pxDataGet("warptool_revertwarped.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psFree(where);
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    return true;
+}
+
+
+static bool blockMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(label, config->args, "-label", true, false);
+
+    if (!warpMaskInsert(config->dbh, label)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool maskedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = psStringCopy("SELECT * FROM warpMask");
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("warpool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "warpMask", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool unblockMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(label, config->args, "-label", true, false);
+
+    char *query = "DELETE FROM warpMask WHERE label = '%s'";
+
+    if (!p_psDBRunQuery(config->dbh, query, label)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+static bool pendingcleanuprunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("warptool_pendingcleanuprun.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("warptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "warpPendingCleanupRun", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool pendingcleanupwarpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_S64(warp_id, config->args, "-warp_id", false, false);
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    if (warp_id) {
+        PXOPT_COPY_S64(config->args, where, "-warp_id", "warp_id", "==");
+    }
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("warptool_pendingcleanupskyfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("warptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "warpPendingCleanupWarp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool donecleanupMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("warptool_donecleanup.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("warptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "warpDoneCleanup", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool isValidMode(pxConfig *config, const char *mode)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(mode, false);
+
+    // check that state is a valid string value
+    if (!(
+            (strncmp(mode, "warp", 5) == 0)
+            || (strncmp(mode, "diff", 5) == 0)
+            || (strncmp(mode, "stack", 6) == 0)
+            || (strncmp(mode, "magic", 6) == 0)
+        )
+    ) {
+        psError(PS_ERR_UNKNOWN, false,
+                "invalid warpRun mode: %s", mode);
+        return false;
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/warptool.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/warptool.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/warptool.h	(revision 22158)
@@ -0,0 +1,50 @@
+/*
+ * warptool.h
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef WARPTOOL_H
+#define WARPTOOL_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+    WARPTOOL_MODE_NONE           = 0x0,
+    WARPTOOL_MODE_DEFINERUN,
+    WARPTOOL_MODE_RUNONE,
+    WARPTOOL_MODE_UPDATERUN,
+    WARPTOOL_MODE_ADDINPUTEXP,
+    WARPTOOL_MODE_EXP,
+    WARPTOOL_MODE_IMFILE,
+    WARPTOOL_MODE_TOOVERLAP,
+    WARPTOOL_MODE_ADDOVERLAP,
+    WARPTOOL_MODE_SCMAP,
+    WARPTOOL_MODE_TOWARPED,
+    WARPTOOL_MODE_ADDWARPED,
+    WARPTOOL_MODE_WARPED,
+    WARPTOOL_MODE_REVERTWARPED,
+    WARPTOOL_MODE_BLOCK,
+    WARPTOOL_MODE_MASKED,
+    WARPTOOL_MODE_UNBLOCK,
+    WARPTOOL_MODE_PENDINGCLEANUPRUN,
+    WARPTOOL_MODE_PENDINGCLEANUPSKYFILE,
+    WARPTOOL_MODE_DONECLEANUP,
+} warptoolMode;
+
+pxConfig *warptoolConfig(pxConfig *config, int argc, char **argv);
+
+#endif // WARPTOOL_H
Index: /branches/eam_branches/eam_branch_20080719/ippTools/src/warptoolConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ippTools/src/warptoolConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ippTools/src/warptoolConfig.c	(revision 22158)
@@ -0,0 +1,317 @@
+/*
+ * warptoolConfig.c
+ *
+ * Copyright (C) 2006-2007  Joshua Hoblitt
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+
+#include <psmodules.h>
+
+#include "pxtools.h"
+#include "warptool.h"
+
+pxConfig *warptoolConfig(pxConfig *config, int argc, char **argv)
+{
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    pmConfigReadParamsSet(false);
+
+    // setup site config
+    config->modules = pmConfigRead(&argc, argv, NULL);
+    if (!config->modules) {
+        psError(PS_ERR_UNKNOWN, false, "Can't find site configuration");
+        psFree(config);
+        return NULL;
+    }
+
+    psTime *now = psTimeGetNow(PS_TIME_TAI);
+
+    // -definerun
+    psMetadata *definerunArgs = psMetadataAlloc();
+    psMetadataAddS64(definerunArgs, PS_LIST_TAIL, "-fake_id", 0,            "define camtool ID (required)", 0);
+    psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-mode", 0,            "define mode (required)", NULL);
+    psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-workdir", 0,            "define workdir (required)", NULL);
+    psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-label", 0,            "define label", NULL);
+    psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-dvodb", 0,            "define dvodb", NULL);
+    psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-tess_id", 0,            "define tess_id", NULL);
+    psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-end_stage", 0,            "define end stage", NULL);
+    psMetadataAddTime(definerunArgs, PS_LIST_TAIL, "-registered",  0,            "time detrend run was registered", now);
+    psMetadataAddBool(definerunArgs, PS_LIST_TAIL, "-magiced",  0,            "has this exposure been magiced", false);
+    psMetadataAddBool(definerunArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -updaterun
+    // XXX need to allow multiple fake_ids
+    // XXX need to allow multiple fake_ids
+    // XXX need to allow multiple chip_ids
+    // XXX need to allow multiple exp_ids
+    psMetadata *updaterunArgs = psMetadataAlloc();
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-warp_id", 0,            "search by warptool ID", 0);
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-fake_id",  0,            "search by fake_id", 0);
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-chip_id",  0,            "search by chip_id", 0);
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exp_id", 0);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-exp_name",  0,            "search by exp_name", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-inst",  0,            "search for camera", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-telescope",  0,            "search for telescope", NULL);
+    psMetadataAddTime(updaterunArgs, PS_LIST_TAIL, "-dateobs_begin", 0,            "search for exposures by time (>=)", NULL);
+    psMetadataAddTime(updaterunArgs, PS_LIST_TAIL, "-dateobs_end", 0,            "search for exposures by time (<)", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-exp_tag",  0,            "search by exp_tag", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-exp_type",  0,            "search by exp_type", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-filelevel",  0,            "search by filelevel", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-reduction",  0,            "search by reduction class", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-filter",  0,            "search for filter", NULL);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-airmass_min",  0,            "define min airmass", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-airmass_max",  0,            "define max airmass", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-ra_min",  0,            "define min", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-ra_max",  0,            "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-decl_min",  0,            "define min", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-decl_max",  0,            "define max", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-exp_time_min",  0,            "define min", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-exp_time_max",  0,            "define max", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-sat_pixel_frac_min",  0,            "define max fraction of saturated pixels", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-sat_pixel_frac_max",  0,            "define min fraction of saturated pixels", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_min",  0,            "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_max",  0,            "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_stdev_min",  0,            "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_stdev_max",  0,            "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_mean_stdev_min",  0,            "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-bg_mean_stdev_max",  0,            "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-alt_min",  0,            "define min", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-alt_max",  0,            "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-az_min",  0,            "define min", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-az_max",  0,            "define max", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-ccd_temp_min",  0,            "define min ccd tempature", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-ccd_temp_max",  0,            "define max ccd tempature", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-posang_min",  0,            "define min rotator position angle", NAN);
+    psMetadataAddF64(updaterunArgs, PS_LIST_TAIL, "-posang_max",  0,            "define max rotator position angle", NAN);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-object",  0,            "search by exposure object", NULL);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-solang_min",  0,            "define min solar angle", NAN);
+    psMetadataAddF32(updaterunArgs, PS_LIST_TAIL, "-solang_max",  0,            "define max solar angle", NAN);
+
+    psMetadataAddBool(updaterunArgs, PS_LIST_TAIL, "-all",  0,            "allow everything to be queued without search terms", false);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-state", 0,            "set state", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-label", 0,            "set label", NULL);
+
+#if 0
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-workdir", 0,            "define workdir (required)", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-registered",  0,            "time detrend run was registered", now);
+#endif
+
+    // -exp
+    psMetadata *expArgs = psMetadataAlloc();
+    psMetadataAddS64(expArgs, PS_LIST_TAIL, "-warp_id", 0,            "search by warptool ID", 0);
+    psMetadataAddS64(expArgs, PS_LIST_TAIL, "-fake_id", 0,            "search by camtool ID", 0);
+    psMetadataAddU64(expArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(expArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -imfile
+    psMetadata *imfileArgs = psMetadataAlloc();
+    psMetadataAddS64(imfileArgs, PS_LIST_TAIL, "-warp_id", 0,            "search by warptool ID", 0);
+    psMetadataAddS64(imfileArgs, PS_LIST_TAIL, "-fake_id", 0,            "search by camtool ID", 0);
+    psMetadataAddU64(imfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(imfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -tooverlap
+    psMetadata *tooverlapArgs = psMetadataAlloc();
+    psMetadataAddS64(tooverlapArgs, PS_LIST_TAIL, "-warp_id", 0,            "search by warp ID", 0);
+    psMetadataAddU64(tooverlapArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(tooverlapArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -addoverlap
+    psMetadata *addoverlapArgs = psMetadataAlloc();
+    psMetadataAddStr(addoverlapArgs, PS_LIST_TAIL, "-mapfile", 0,            "path to skycell <-> imfile mapping file", NULL);
+    psMetadataAddS64(addoverlapArgs, PS_LIST_TAIL, "-warp_id",  0,            "set warp ID", 0);
+    psMetadataAddS16(addoverlapArgs, PS_LIST_TAIL, "-code",  0,            "set fault code", 0);
+
+    // -scmap
+    psMetadata *scmapArgs = psMetadataAlloc();
+    psMetadataAddS64(scmapArgs, PS_LIST_TAIL, "-warp_id", 0,            "search by warptool ID", 0);
+    psMetadataAddStr(scmapArgs, PS_LIST_TAIL, "-skycell_id", 0,            "search by skycell ID", NULL);
+    psMetadataAddStr(scmapArgs, PS_LIST_TAIL, "-tess_id", 0,            "search by tess ID", NULL);
+    psMetadataAddU64(scmapArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(scmapArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -towarped
+    psMetadata *towarpedArgs = psMetadataAlloc();
+    psMetadataAddS64(towarpedArgs, PS_LIST_TAIL, "-warp_id", 0,            "search by warptool ID", 0);
+    psMetadataAddU64(towarpedArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(towarpedArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -addwarped
+    psMetadata *addwarpedArgs = psMetadataAlloc();
+    psMetadataAddS64(addwarpedArgs, PS_LIST_TAIL, "-warp_id", 0,            "define warptool ID (required)", 0);
+    psMetadataAddStr(addwarpedArgs, PS_LIST_TAIL, "-skycell_id",  0,            "define skycell ID (required)", NULL);
+    psMetadataAddStr(addwarpedArgs, PS_LIST_TAIL, "-tess_id",  0,            "define tessellation ID (required)", NULL);
+    psMetadataAddStr(addwarpedArgs, PS_LIST_TAIL, "-uri", 0,            "define URI of file", 0);
+    psMetadataAddStr(addwarpedArgs, PS_LIST_TAIL, "-path_base", 0,            "define base output location", 0);
+    psMetadataAddF64(addwarpedArgs, PS_LIST_TAIL, "-bg",  0,            "define exposure background", NAN);
+    psMetadataAddF64(addwarpedArgs, PS_LIST_TAIL, "-bg_stdev",  0,            "define exposure background stdev", NAN);
+    psMetadataAddF32(addwarpedArgs, PS_LIST_TAIL, "-dtime_warp",  0,            "define elapsed processing time", NAN);
+    psMetadataAddS32(addwarpedArgs, PS_LIST_TAIL, "-xmin",  0,            "define minimum x value", INT_MAX);
+    psMetadataAddS32(addwarpedArgs, PS_LIST_TAIL, "-xmax",  0,            "define maximum x value", -INT_MAX);
+    psMetadataAddS32(addwarpedArgs, PS_LIST_TAIL, "-ymin",  0,            "define minimum y value", INT_MAX);
+    psMetadataAddS32(addwarpedArgs, PS_LIST_TAIL, "-ymax",  0,            "define maximum y value", -INT_MAX);
+    psMetadataAddStr(addwarpedArgs, PS_LIST_TAIL, "-hostname", 0,            "define hostname", 0);
+    psMetadataAddF32(addwarpedArgs, PS_LIST_TAIL, "-good_frac",  0,            "define %% of good pixels", NAN);
+    psMetadataAddBool(addwarpedArgs, PS_LIST_TAIL, "-ignore",  0,            "define if this skycell should be ignored", false);
+    psMetadataAddS16(addwarpedArgs, PS_LIST_TAIL, "-code",  0,            "set fault code", 0);
+
+    // -warped
+    psMetadata *warpedArgs = psMetadataAlloc();
+    psMetadataAddS64(warpedArgs, PS_LIST_TAIL, "-warp_id", 0,            "search by warptool ID", 0);
+    psMetadataAddStr(warpedArgs, PS_LIST_TAIL, "-skycell_id",  0,            "define skycell ID", NULL);
+    psMetadataAddStr(warpedArgs, PS_LIST_TAIL, "-tess_id",  0,            "define tessellation ID", NULL);
+    psMetadataAddS64(warpedArgs, PS_LIST_TAIL, "-exp_id", 0,            "define exposure tag", 0);
+    psMetadataAddStr(warpedArgs, PS_LIST_TAIL, "-exp_name", 0,          "define exposure tag", 0);
+    psMetadataAddS64(warpedArgs, PS_LIST_TAIL, "-fake_id", 0,            "define phase 3 version of exposure tag", 0);
+    psMetadataAddU64(warpedArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(warpedArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -revertwarped
+    // XXX need to allow multiple fake_ids
+    // XXX need to allow multiple fake_ids
+    // XXX need to allow multiple chip_ids
+    // XXX need to allow multiple exp_ids
+    psMetadata *revertwarpedArgs = psMetadataAlloc();
+    psMetadataAddS64(revertwarpedArgs, PS_LIST_TAIL, "-warp_id", 0,            "search by warptool ID", 0);
+    psMetadataAddStr(revertwarpedArgs, PS_LIST_TAIL, "-skycell_id",  0,            "search by skycell ID", NULL);
+    psMetadataAddStr(revertwarpedArgs, PS_LIST_TAIL, "-tess_id",  0,            "searcy by tessellation ID", NULL);
+    psMetadataAddS64(revertwarpedArgs, PS_LIST_TAIL, "-fake_id",  0,            "search by fake_id", 0);
+    psMetadataAddS64(revertwarpedArgs, PS_LIST_TAIL, "-chip_id",  0,            "search by chip_id", 0);
+    psMetadataAddS64(revertwarpedArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by exp_id", 0);
+    psMetadataAddStr(revertwarpedArgs, PS_LIST_TAIL, "-exp_name",  0,            "search by exp_name", NULL);
+    psMetadataAddStr(revertwarpedArgs, PS_LIST_TAIL, "-inst",  0,            "search for camera", NULL);
+    psMetadataAddStr(revertwarpedArgs, PS_LIST_TAIL, "-telescope",  0,            "search for telescope", NULL);
+    psMetadataAddTime(revertwarpedArgs, PS_LIST_TAIL, "-dateobs_begin", 0,            "search for exposures by time (>=)", NULL);
+    psMetadataAddTime(revertwarpedArgs, PS_LIST_TAIL, "-dateobs_end", 0,            "search for exposures by time (<)", NULL);
+    psMetadataAddStr(revertwarpedArgs, PS_LIST_TAIL, "-exp_tag",  0,            "search by exp_tag", NULL);
+    psMetadataAddStr(revertwarpedArgs, PS_LIST_TAIL, "-exp_type",  0,            "search by exp_type", NULL);
+    psMetadataAddStr(revertwarpedArgs, PS_LIST_TAIL, "-filelevel",  0,            "search by filelevel", NULL);
+    psMetadataAddStr(revertwarpedArgs, PS_LIST_TAIL, "-reduction",  0,            "search by reduction class", NULL);
+    psMetadataAddStr(revertwarpedArgs, PS_LIST_TAIL, "-filter",  0,            "search for filter", NULL);
+    psMetadataAddF32(revertwarpedArgs, PS_LIST_TAIL, "-airmass_min",  0,            "define min airmass", NAN);
+    psMetadataAddF32(revertwarpedArgs, PS_LIST_TAIL, "-airmass_max",  0,            "define max airmass", NAN);
+    psMetadataAddF64(revertwarpedArgs, PS_LIST_TAIL, "-ra_min",  0,            "define min", NAN);
+    psMetadataAddF64(revertwarpedArgs, PS_LIST_TAIL, "-ra_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertwarpedArgs, PS_LIST_TAIL, "-decl_min",  0,            "define min", NAN);
+    psMetadataAddF64(revertwarpedArgs, PS_LIST_TAIL, "-decl_max",  0,            "define max", NAN);
+    psMetadataAddF32(revertwarpedArgs, PS_LIST_TAIL, "-exp_time_min",  0,            "define min", NAN);
+    psMetadataAddF32(revertwarpedArgs, PS_LIST_TAIL, "-exp_time_max",  0,            "define max", NAN);
+    psMetadataAddF32(revertwarpedArgs, PS_LIST_TAIL, "-sat_pixel_frac_min",  0,            "define max fraction of saturated pixels", NAN);
+    psMetadataAddF32(revertwarpedArgs, PS_LIST_TAIL, "-sat_pixel_frac_max",  0,            "define min fraction of saturated pixels", NAN);
+    psMetadataAddF64(revertwarpedArgs, PS_LIST_TAIL, "-bg_min",  0,            "define max", NAN);
+    psMetadataAddF64(revertwarpedArgs, PS_LIST_TAIL, "-bg_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertwarpedArgs, PS_LIST_TAIL, "-bg_stdev_min",  0,            "define max", NAN);
+    psMetadataAddF64(revertwarpedArgs, PS_LIST_TAIL, "-bg_stdev_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertwarpedArgs, PS_LIST_TAIL, "-bg_mean_stdev_min",  0,            "define max", NAN);
+    psMetadataAddF64(revertwarpedArgs, PS_LIST_TAIL, "-bg_mean_stdev_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertwarpedArgs, PS_LIST_TAIL, "-alt_min",  0,            "define min", NAN);
+    psMetadataAddF64(revertwarpedArgs, PS_LIST_TAIL, "-alt_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertwarpedArgs, PS_LIST_TAIL, "-az_min",  0,            "define min", NAN);
+    psMetadataAddF64(revertwarpedArgs, PS_LIST_TAIL, "-az_max",  0,            "define max", NAN);
+    psMetadataAddF64(revertwarpedArgs, PS_LIST_TAIL, "-ccd_temp_min",  0,            "define min ccd tempature", NAN);
+    psMetadataAddF64(revertwarpedArgs, PS_LIST_TAIL, "-ccd_temp_max",  0,            "define max ccd tempature", NAN);
+    psMetadataAddF64(revertwarpedArgs, PS_LIST_TAIL, "-posang_min",  0,            "define min rotator position angle", NAN);
+    psMetadataAddF64(revertwarpedArgs, PS_LIST_TAIL, "-posang_max",  0,            "define max rotator position angle", NAN);
+    psMetadataAddStr(revertwarpedArgs, PS_LIST_TAIL, "-object",  0,            "search by exposure object", NULL);
+    psMetadataAddF32(revertwarpedArgs, PS_LIST_TAIL, "-solang_min",  0,            "define min solar angle", NAN);
+    psMetadataAddF32(revertwarpedArgs, PS_LIST_TAIL, "-solang_max",  0,            "define max solar angle", NAN);
+
+    psMetadataAddS16(revertwarpedArgs, PS_LIST_TAIL, "-code",  0,            "search by fault code", 0);
+    psMetadataAddBool(revertwarpedArgs, PS_LIST_TAIL, "-all",  0,            "allow everything to be queued without search terms", false);
+
+    // -block
+    psMetadata *blockArgs = psMetadataAlloc();
+    psMetadataAddStr(blockArgs, PS_LIST_TAIL, "-label",  0,            "name of a label to mask out (required)", NULL);
+
+    // -masked
+    psMetadata *maskedArgs = psMetadataAlloc();
+    psMetadataAddBool(maskedArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+
+    // -unblock
+    psMetadata *unblockArgs = psMetadataAlloc();
+    psMetadataAddStr(unblockArgs, PS_LIST_TAIL, "-label",  0,            "name of a label to unmask (required)", NULL);
+
+    // -pendingcleanuprun
+    psMetadata *pendingcleanuprunArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingcleanuprunArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddBool(pendingcleanuprunArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanuprunArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -pendingcleanupskyfile
+    psMetadata *pendingcleanupskyfileArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingcleanupskyfileArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddS64(pendingcleanupskyfileArgs, PS_LIST_TAIL, "-warp_id", 0,          "search by warp ID", 0);
+    psMetadataAddBool(pendingcleanupskyfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanupskyfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -donecleanup
+    psMetadata *donecleanupArgs = psMetadataAlloc();
+    psMetadataAddStr(donecleanupArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddBool(donecleanupArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(donecleanupArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    psFree(now);
+    psMetadata *argSets = psMetadataAlloc();
+    psMetadata *modes   = psMetadataAlloc();
+
+    PXOPT_ADD_MODE("-definerun",       "", WARPTOOL_MODE_DEFINERUN,      definerunArgs);
+    PXOPT_ADD_MODE("-updaterun",       "", WARPTOOL_MODE_UPDATERUN,      updaterunArgs);
+    PXOPT_ADD_MODE("-exp",             "", WARPTOOL_MODE_EXP,            expArgs);
+    PXOPT_ADD_MODE("-imfile",          "", WARPTOOL_MODE_IMFILE,         imfileArgs);
+    PXOPT_ADD_MODE("-tooverlap",       "", WARPTOOL_MODE_TOOVERLAP,      tooverlapArgs);
+    PXOPT_ADD_MODE("-addoverlap",      "", WARPTOOL_MODE_ADDOVERLAP,     addoverlapArgs);
+    PXOPT_ADD_MODE("-scmap",           "", WARPTOOL_MODE_SCMAP,          scmapArgs);
+    PXOPT_ADD_MODE("-towarped",        "", WARPTOOL_MODE_TOWARPED,       towarpedArgs);
+    PXOPT_ADD_MODE("-addwarped",       "", WARPTOOL_MODE_ADDWARPED,      addwarpedArgs);
+    PXOPT_ADD_MODE("-warped",          "", WARPTOOL_MODE_WARPED,         warpedArgs);
+    PXOPT_ADD_MODE("-revertwarped",    "", WARPTOOL_MODE_REVERTWARPED,   revertwarpedArgs);
+    PXOPT_ADD_MODE("-block",                 "set a label block",                    WARPTOOL_MODE_BLOCK,          blockArgs);
+    PXOPT_ADD_MODE("-masked",                "show blocked lables",                  WARPTOOL_MODE_MASKED,         maskedArgs);
+    PXOPT_ADD_MODE("-unblock",               "remove a label block",                 WARPTOOL_MODE_UNBLOCK,        unblockArgs);
+    PXOPT_ADD_MODE("-pendingcleanuprun",     "show runs that need to be cleaned up", WARPTOOL_MODE_PENDINGCLEANUPRUN,    pendingcleanuprunArgs);
+    PXOPT_ADD_MODE("-pendingcleanupskyfile", "show runs that need to be cleaned up", WARPTOOL_MODE_PENDINGCLEANUPSKYFILE, pendingcleanupskyfileArgs);
+    PXOPT_ADD_MODE("-donecleanup",           "show runs that have been cleaned",     WARPTOOL_MODE_DONECLEANUP,          donecleanupArgs);
+
+    if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
+        psError(PS_ERR_UNKNOWN, true, "option parsing failed");
+        psFree(argSets);
+        psFree(modes);
+        psFree(config);
+        return NULL;
+    }
+
+    psFree(argSets);
+    psFree(modes);
+
+    // define Database handle, if used
+    // do this last so we don't setup a connection before CLI options are
+    // validated
+    config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+    if (!config->dbh) {
+        psError(PS_ERR_UNKNOWN, false, "Can't configure database");
+        psFree(config);
+        return NULL;
+    }
+
+    return config;
+}
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/.cvsignore	(revision 22158)
@@ -0,0 +1,12 @@
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+compile
+config.log
+config.status
+configure
+depcomp
+install-sh
+missing
+test
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/Makefile.am	(revision 22158)
@@ -0,0 +1,3 @@
+SUBDIRS = src
+
+CLEANFILES = *~ core core.*
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/autogen.sh
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/autogen.sh	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/autogen.sh	(revision 22158)
@@ -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=ppMerge
+TEST_TYPE=-f
+# change this to be a unique filename in the top level dir
+FILE=autogen.sh
+
+DIE=0
+
+LIBTOOLIZE=libtoolize
+ACLOCAL="aclocal $ACLOCAL_FLAGS"
+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: /branches/eam_branches/eam_branch_20080719/ppMerge/configure.ac
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/configure.ac	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/configure.ac	(revision 22158)
@@ -0,0 +1,30 @@
+AC_PREREQ(2.61)
+
+AC_INIT([ppMerge], [1.1.0], [ipp-support@ifa.hawaii.edu])
+AC_CONFIG_SRCDIR([src])
+
+AM_INIT_AUTOMAKE([1.6 foreign dist-bzip2])
+AM_CONFIG_HEADER([src/config.h])
+AM_MAINTAINER_MODE
+
+IPP_STDCFLAGS
+
+AC_LANG(C)
+AC_GNU_SOURCE
+AC_PROG_CC_C99
+AC_PROG_INSTALL
+dnl AC_PROG_LIBTOOL
+AC_SYS_LARGEFILE
+
+PKG_CHECK_MODULES([PSLIB], [pslib >= 1.0.0])
+PKG_CHECK_MODULES([PSMODULE], [psmodules >= 1.0.0])
+PKG_CHECK_MODULES([PPSTATS], [ppStats >= 1.0.0]) 
+
+IPP_STDOPTS
+CFLAGS="${CFLAGS=} -Wall -Werror"
+
+AC_CONFIG_FILES([
+  Makefile
+  src/Makefile
+])
+AC_OUTPUT
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/.cvsignore	(revision 22158)
@@ -0,0 +1,7 @@
+.deps
+Makefile
+Makefile.in
+ppMerge
+config.h
+config.h.in
+stamp-h1
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/Makefile.am	(revision 22158)
@@ -0,0 +1,29 @@
+bin_PROGRAMS = ppMerge
+
+ppMerge_CFLAGS = $(PPSTATS_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
+ppMerge_LDFLAGS = $(PPSTATS_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
+
+ppMerge_SOURCES =		\
+	ppMerge.c		\
+	ppMergeArguments.c	\
+	ppMergeCamera.c		\
+	ppMergeFiles.c		\
+	ppMergeScaleZero.c	\
+	ppMergeFileGroup.c	\
+	ppMergeReadChunk.c	\
+	ppMergeLoop_Threaded.c  \
+	ppMergeSetThreads.c	\
+	ppMergeMask.c
+
+#	ppMergeLoop.c		
+
+noinst_HEADERS =		\
+	ppMerge.h
+
+CLEANFILES = *~
+
+clean-local:
+	-rm -f TAGS
+# Tags for emacs
+tags:
+	etags `find . -name \*.[ch] -print`
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMerge.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMerge.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMerge.c	(revision 22158)
@@ -0,0 +1,143 @@
+#include "ppMerge.h"
+
+// Yet to do:
+//
+// 1. Mask pixels with less than the minimum number of electrons
+// 2. Sampling factor for background measurement
+// 3. On/off pairs
+
+int main(int argc, char **argv)
+{
+    psLibInit(NULL);
+    psTimerStart(TIMERNAME);
+
+    psExit exitValue = PS_EXIT_SUCCESS; // Exit value for program
+
+    pmConfig *config = pmConfigRead(&argc, argv, PPMERGE_RECIPE); // Configuration
+    if (!config) {
+        psErrorStackPrint(stderr, "Error reading configuration.");
+        exitValue = PS_EXIT_CONFIG_ERROR;
+        goto die;
+    }
+
+    if (!ppMergeArguments(argc, argv, config)) {
+        psErrorStackPrint(stderr, "Error reading arguments.");
+        exitValue = PS_EXIT_CONFIG_ERROR;
+        goto die;
+    }
+
+    ppMergeType type = psMetadataLookupS32(NULL, config->arguments, "TYPE"); // Type of frame
+    switch (type) {
+      case PPMERGE_TYPE_MASK:
+        if (!ppMergeMask(config)) {
+            psErrorStackPrint(stderr, "Error generating mask.");
+            exitValue = PS_EXIT_DATA_ERROR;
+            goto die;
+        }
+        break;
+      case PPMERGE_TYPE_BIAS:
+      case PPMERGE_TYPE_DARK:
+      case PPMERGE_TYPE_SHUTTER:
+      case PPMERGE_TYPE_FLAT:
+      case PPMERGE_TYPE_FRINGE:
+        if (!ppMergeScaleZero(config)) {
+            psErrorStackPrint(stderr, "Error getting scale and zero-points.");
+            exitValue = PS_EXIT_DATA_ERROR;
+            goto die;
+        }
+        if (!ppMergeLoop(config)) {
+            psErrorStackPrint(stderr, "Error performing merge.");
+            exitValue = PS_EXIT_PROG_ERROR;
+            goto die;
+        }
+        break;
+      default:
+        psAbort("Invalid frame type: %x", type);
+    }
+
+
+    // Output the statistics
+    bool mdok;                          // Status of MD lookup
+    psString statsName = psMetadataLookupStr(&mdok, config->arguments, "STATS.NAME"); // Statistics file name
+    if (mdok && statsName && strlen(statsName) > 0) {
+        psString resolved = pmConfigConvertFilename(statsName, config, true, true); // Resolved filename
+        FILE *statsFile = fopen(resolved, "w"); // Output statistics file
+        if (!statsFile) {
+            psError(PS_ERR_IO, true, "Unable to open statistics file %s for writing.", resolved);
+            psFree(resolved);
+            exitValue = PS_EXIT_CONFIG_ERROR;
+            goto die;
+        }
+        psFree(resolved);
+        psMetadata *stats = psMetadataLookupMetadata(&mdok, config->arguments, "STATS.DATA"); // Statistics
+        if (!stats) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find statistics");
+            exitValue = PS_EXIT_PROG_ERROR;
+            goto die;
+        }
+        psString statsOut = psMetadataConfigFormat(stats); // String to write out
+        fprintf(statsFile, "%s", statsOut);
+        psFree(statsOut);
+        fclose(statsFile);
+    }
+
+
+
+
+#if 0
+    // Set various tasks (define optional operations)
+    ppMergeOptions *options = ppMergeOptionsParse(config);
+    if (!options) {
+        psErrorStackPrint(stderr, "Unable to parse options.");
+        exit(EXIT_FAILURE);
+    }
+
+    // Check the inputs
+    ppMergeData *data = ppMergeCheckInputs(options, config);
+    if (!data) {
+        psErrorStackPrint(stderr, "Not enough valid input files.");
+        exit(EXIT_FAILURE);
+    }
+
+    if (options->mask) {
+        // Generate a mask
+        ppMergeMask(data, options, config);
+    } else {
+
+        psImage *scale = NULL;              // The scalings
+        psImage *zero = NULL;               // The zeros
+        psArray *shutters = NULL;           // The shutter correction data
+
+        // Measure the background in each image
+        ppMergeScaleZero(&scale, &zero, &shutters, data, options, config);
+
+        // Do the combination and write
+        ppMergeCombine(scale, zero, shutters, data, options, config);
+
+        psFree(scale);
+        psFree(zero);
+        psFree(shutters);
+    }
+
+    // Output the statistics
+    if (data->statsFile && data->stats) {
+        psString statsOut = psMetadataConfigFormat(data->stats); // String to write out
+        fprintf(data->statsFile, "%s", statsOut);
+        psFree(statsOut);
+    }
+
+    // Cleaning up
+    psFree(data);
+    psFree(options);
+#endif
+
+ die:
+    psTrace("ppSub", 1, "Finished at %f sec\n", psTimerMark("ppSub"));
+    psTimerStop();
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exitValue);
+}
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMerge.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMerge.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMerge.h	(revision 22158)
@@ -0,0 +1,109 @@
+#ifndef PP_MERGE_H
+#define PP_MERGE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include <ppStats.h>
+
+#define TIMERNAME "ppMerge"             // Name for timer
+#define PPMERGE_RECIPE "PPMERGE"        // Recipe name
+#define THREADED 1
+
+// Type of frame to merge
+typedef enum {
+    PPMERGE_TYPE_UNKNOWN,               // Unknown type
+    PPMERGE_TYPE_BIAS,                  // Bias frame
+    PPMERGE_TYPE_DARK,                  // (Multi-)Dark frame
+    PPMERGE_TYPE_MASK,                  // Mask frame
+    PPMERGE_TYPE_SHUTTER,               // Shutter frame
+    PPMERGE_TYPE_FLAT,                  // Flat-field frame (dome or sky)
+    PPMERGE_TYPE_FRINGE,                // Fringe frame
+} ppMergeType;
+
+// Files, for activation
+typedef enum {
+    PPMERGE_FILES_ALL,                  // All files
+    PPMERGE_FILES_INPUT,                // Input files
+    PPMERGE_FILES_OUTPUT                // Output files
+} ppMergeFiles;
+
+typedef struct {
+    psArray *readouts;
+    bool read;
+    bool busy;
+    int firstScan;
+    int lastScan;
+} ppMergeFileGroup;
+
+// Parse command-line arguments and recipe
+bool ppMergeArguments(int argc, char *argv[], // Command-line arguments
+                      pmConfig *config  // Configuration
+    );
+
+// Set up camera files
+bool ppMergeCamera(pmConfig *config     // Configuration
+    );
+
+// Measure scale and zero-points
+bool ppMergeScaleZero(pmConfig *config  // Configuration
+    );
+
+// Main loop to do the merging
+bool ppMergeLoop(pmConfig *config       // Configuration
+    );
+
+// Main loop for masks
+bool ppMergeMask(pmConfig *config       // Configuration
+    );
+
+// Read nominated input file
+bool ppMergeFileReadInput(pmConfig *config, // Configuration
+                          pmReadout *readout, // Readout into which to read
+                          int num,      // Number of file in sequence
+                          int rows      // Number of rows to read at once
+    );
+
+// Open nominated input file
+bool ppMergeFileOpenInput(pmConfig *config, // Configuration
+                          const pmFPAview *view, // View to open
+                          int num       // Number of file in sequence
+    );
+
+// Set the data level for files specified by name; return an array of the files
+psArray *ppMergeFileDataLevel(const pmConfig *config, // Configuration
+                              const char *name, // Name of files
+                              pmFPALevel level // Level for file data level
+    );
+
+// Activate/deactivate a list of files
+bool ppMergeFileActivate(const pmConfig *config, // Configuration
+                         ppMergeFiles files, // Files to turn on/off
+                         bool state     // Activation state
+    );
+
+// Activate/deactivate a single element for a list; return array of files
+psArray *ppMergeFileActivateSingle(const pmConfig *config, // Configuration
+                                   ppMergeFiles files, // Files to turn on/off
+                                   bool state,   // Activation state
+                                   int num // Number of file in sequence
+    );
+
+// Return name of output pmFPAfile
+psString ppMergeOutputFile(const pmConfig *config // Configuration
+    );
+
+
+ppMergeFileGroup *ppMergeFileGroupAlloc();
+ppMergeFileGroup *ppMergeReadChunk (bool *status, psArray *fileGroups, pmConfig *config, int numChunk);
+void *ppMergeThreadLauncher (void *data);
+
+bool ppMergeSetThreads ();
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeArguments.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeArguments.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeArguments.c	(revision 22158)
@@ -0,0 +1,387 @@
+#include "ppMerge.h"
+
+// Print usage information and die
+static void usage(const char *program,  // Name of the program
+                  psMetadata *arguments // Command-line arguments
+    )
+{
+    fprintf(stderr, "\nPan-STARRS Detrend Merging\n\n");
+    fprintf(stderr, "Usage: %s INPUT.mdc OUTPUT_ROOT\n"
+            "where INPUTS.mdc contains various METADATAs, each with:\n"
+            "\tIMAGE(STR):     Image filename\n"
+            "\tMASK(STR):      Mask filename\n"
+            "\tWEIGHT(STR)     Weight map filename\n"
+            "where MASK and WEIGHT are optional.",
+            program);
+    fprintf(stderr, "\n");
+    psArgumentHelp(arguments);
+}
+
+// Get a float-point value from the command-line or recipe, and add it to the arguments
+#define VALUE_ARG_RECIPE_FLOAT(ARGNAME, RECIPENAME, TYPE) { \
+    ps##TYPE value = psMetadataLookup##TYPE(NULL, arguments, ARGNAME); \
+    if (isnan(value)) { \
+        bool mdok; \
+        value = psMetadataLookup##TYPE(&mdok, recipe, RECIPENAME); \
+        if (!mdok) { \
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to find %s in recipe %s", \
+                RECIPENAME, PPMERGE_RECIPE); \
+            goto ERROR; \
+        } \
+    } \
+    psMetadataAdd##TYPE(config->arguments, PS_LIST_TAIL, RECIPENAME, 0, NULL, value); \
+}
+
+// Get an integer value from the command-line or recipe, and add it to the arguments
+#define VALUE_ARG_RECIPE_INT(ARGNAME, RECIPENAME, TYPE, UNSET) { \
+    ps##TYPE value = psMetadataLookup##TYPE(NULL, arguments, ARGNAME); \
+    if (value == UNSET) { \
+        bool mdok; \
+        value = psMetadataLookup##TYPE(&mdok, recipe, RECIPENAME); \
+        if (!mdok) { \
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to find %s in recipe %s", \
+                RECIPENAME, PPMERGE_RECIPE); \
+            goto ERROR; \
+        } \
+    } \
+    psMetadataAdd##TYPE(config->arguments, PS_LIST_TAIL, RECIPENAME, 0, NULL, value); \
+}
+
+// Get a boolean from the command-line or recipe, and add it to the arguments if either is set
+#define VALUE_ARG_RECIPE_BOOL(ARGNAME, RECIPENAME) { \
+    bool value = (psMetadataLookupBool(NULL, arguments, ARGNAME) || \
+                  psMetadataLookupBool(NULL, recipe, RECIPENAME)); \
+    psMetadataAddBool(config->arguments, PS_LIST_TAIL, RECIPENAME, 0, NULL, value); \
+}
+
+// Get a statistic name from the command-line or recipe, and add the enum to the arguments
+#define VALUE_ARG_RECIPE_STAT(ARGNAME, RECIPENAME) { \
+    const char *stat = psMetadataLookupStr(NULL, arguments, ARGNAME); \
+    if (!stat) { \
+        stat = psMetadataLookupStr(NULL, recipe, RECIPENAME); \
+        if (!stat) { \
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Unable to find %s in recipe %s", \
+                    RECIPENAME, PPMERGE_RECIPE); \
+            goto ERROR; \
+        } \
+    } \
+    psMetadataAddS32(config->arguments, PS_LIST_TAIL, RECIPENAME, 0, NULL, psStatsOptionFromString(stat)); \
+}
+
+// Get a string from the command-line or recipe, and add to the arguments
+#define VALUE_ARG_RECIPE_STR(ARGNAME, RECIPENAME) { \
+    const char *str = psMetadataLookupStr(NULL, arguments, ARGNAME); \
+    if (!str) { \
+        str = psMetadataLookupStr(NULL, recipe, RECIPENAME); \
+        if (!str) { \
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Unable to find %s in recipe %s", \
+                    RECIPENAME, PPMERGE_RECIPE); \
+            goto ERROR; \
+        } \
+    } \
+    psMetadataAddStr(config->arguments, PS_LIST_TAIL, RECIPENAME, 0, NULL, str); \
+}
+
+// Get a string from the command-line or recipe, and add the appropriate mask value to the arguments
+#define VALUE_ARG_RECIPE_MASK(ARGNAME, RECIPENAME) { \
+    const char *str = psMetadataLookupStr(NULL, arguments, ARGNAME); \
+    if (!str) { \
+        str = psMetadataLookupStr(NULL, recipe, RECIPENAME); \
+        if (!str) { \
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Unable to find %s in recipe %s", \
+                    RECIPENAME, PPMERGE_RECIPE); \
+            goto ERROR; \
+        } \
+    } \
+    psMaskType mask = pmConfigMask(str, config); \
+    psMetadataAddU8(config->arguments, PS_LIST_TAIL, RECIPENAME, 0, NULL, mask); \
+}
+
+// Get a string value from the command-line and add it to the target
+static bool valueArgStr(psMetadata *arguments, // Command-line arguments
+                        const char *argName, // Argument name in the command-line arguments
+                        const char *mdName, // Name for value in the metadata
+                        psMetadata *target // Target metadata to which to add value
+                        )
+{
+    psString value = psMetadataLookupStr(NULL, arguments, argName); // Value of interest
+    if (value && strlen(value) > 0) {
+        return psMetadataAddStr(target, PS_LIST_TAIL, mdName, 0, NULL, value);
+    }
+    return false;
+}
+
+bool ppMergeArguments(int argc, char *argv[], pmConfig *config)
+{
+    assert(config);
+
+    psMetadata *arguments = psMetadataAlloc(); // Command-line arguments
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-type", 0, "Type of calibration frame", NULL);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-stats", 0, "MDC file to hold statistics ", NULL);
+    // Standard combination parameters
+    psMetadataAddS32(arguments, PS_LIST_TAIL, "-rows",     0, "Rows to read per scan", 0);
+    psMetadataAddS32(arguments, PS_LIST_TAIL, "-sample",   0, "Sampling factor for background", 0);
+    psMetadataAddS32(arguments, PS_LIST_TAIL, "-iter",     0, "Number of rejection iterations", 0);
+    psMetadataAddF32(arguments, PS_LIST_TAIL, "-rej",      0, "Rejection threshold (sigma)", NAN);
+    psMetadataAddF32(arguments, PS_LIST_TAIL, "-fraclow",  0, "Fraction of low pixels to discard", NAN);
+    psMetadataAddF32(arguments, PS_LIST_TAIL, "-frachigh", 0, "Fraction of low pixels to discard", NAN);
+    psMetadataAddS32(arguments, PS_LIST_TAIL, "-nkeep",    0, "Minimum number of pixels in stack to keep", 0);
+    psMetadataAddBool(arguments, PS_LIST_TAIL, "-weights", 0, "Use image weights in combination?", false);
+
+    // XXX EAM : not clear this should be allowed on the command line.
+    // psMetadataAddStr(arguments, PS_LIST_TAIL, "-maskval",  0, "Mask value for input data", NULL);
+
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-combine",  0, "Statistic to use for combination", NULL);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-mean",     0, "Statistic to use to measure the mean", NULL);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-stdev",    0, "Statistic to use to measure the stdev", NULL);
+
+    // Fringe construction parameters
+    psMetadataAddS32(arguments, PS_LIST_TAIL, "-fringe-num",     0, "Number of fringe regions", 0);
+    psMetadataAddS32(arguments, PS_LIST_TAIL, "-fringe-size",    0, "Half-size of fringe regions", 0);
+    psMetadataAddS32(arguments, PS_LIST_TAIL, "-fringe-xsmooth", 0, "Number of smoothing regions in x", 0);
+    psMetadataAddS32(arguments, PS_LIST_TAIL, "-fringe-ysmooth", 0, "Number of smoothing regions in y", 0);
+
+    // Shutter construction parameters
+    psMetadataAddS32(arguments, PS_LIST_TAIL, "-shutter-size", 0, "Size for shutter measurement regions", 0);
+    psMetadataAddS32(arguments, PS_LIST_TAIL, "-shutter-iter", 0, "Number of iterations for shutter", 0);
+    psMetadataAddF32(arguments, PS_LIST_TAIL, "-shutter-rej",  0, "Rejection limit for shutter", NAN);
+
+    // Mask construction parameters
+    psMetadataAddF32(arguments, PS_LIST_TAIL, "-mask-suspect",  0, "Threshold for suspect pixels (sigma)", NAN);
+    psMetadataAddF32(arguments, PS_LIST_TAIL, "-mask-bad",      0, "Threshold for bad pixels (sigma)", NAN);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-mask-mode",     0, "Mode to identify bad pixels", NULL);
+    psMetadataAddS32(arguments, PS_LIST_TAIL, "-mask-grow",     0, "Number of pixels to grow final mask", 0);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-mask-set-value",0, "Value to set for output mask pixels", NULL);
+    psMetadataAddBool(arguments, PS_LIST_TAIL, "-mask-chip",    0, "Measure mask statistics by chip?", false);
+
+    psMetadataAddBool(arguments, PS_LIST_TAIL, "-mask-smooth-suspect",  0, "smooth suspect pixels?", false);
+    psMetadataAddF32(arguments, PS_LIST_TAIL, "-mask-smooth-scale",  0, "smoothing sigma for suspect pixels", NAN);
+
+    // chip & cell selections are used to limit chips to be processed
+    int argnum;
+    if ((argnum = psArgumentGet (argc, argv, "-chip"))) {
+        psArgumentRemove (argnum, &argc, argv);
+        psMetadataAddStr (config->arguments, PS_LIST_TAIL, "CHIP_SELECTIONS", PS_DATA_STRING, "", argv[argnum]);
+        psArgumentRemove (argnum, &argc, argv);
+    }
+    if ((argnum = psArgumentGet (argc, argv, "-cell"))) {
+        psArgumentRemove (argnum, &argc, argv);
+        psMetadataAddStr (config->arguments, PS_LIST_TAIL, "CELL_SELECTIONS", PS_DATA_STRING, "", argv[argnum]);
+        psArgumentRemove (argnum, &argc, argv);
+    }
+
+    // Number of threads
+    if ((argnum = psArgumentGet(argc, argv, "-threads"))) {
+        psArgumentRemove(argnum, &argc, argv);
+	int nThreads = atoi(argv[argnum]);
+        psMetadataAddS32(config->arguments, PS_LIST_TAIL, "NTHREADS", 0, "number of warp threads", nThreads);
+        psArgumentRemove(argnum, &argc, argv);
+
+	// create the thread pool with number of desired threads, supplying our thread launcher function
+	// XXX need to determine the number of threads from the config data
+	psThreadPoolInit (nThreads);
+    }
+    ppMergeSetThreads();
+
+    if (argc == 1 || !psArgumentParse(arguments, &argc, argv) || argc != 3) {
+        usage(argv[0], arguments);
+        goto ERROR;
+    }
+
+    unsigned int numBad = 0;                     // Number of bad lines
+    psMetadata *inputs = psMetadataConfigRead(NULL, &numBad, argv[1], false); // Information about inputs
+    if (!inputs || numBad > 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Unable to cleanly read MDC file with inputs.");
+        goto ERROR;
+    }
+    psMetadataAddMetadata(config->arguments, PS_LIST_TAIL, "INPUTS", 0,
+                          "Metadata with input details", inputs);
+    psFree(inputs);
+    psMetadataAddStr(config->arguments, PS_LIST_TAIL, "OUTPUT", 0,
+                     "Root name of the output image list", argv[2]);
+
+    valueArgStr(arguments, "-stats", "STATS.NAME", config->arguments);
+
+
+    // Set the type of calibration frame
+    const char *typeStr = psMetadataLookupStr(NULL, arguments, "-type"); // Type of calibration
+    if (strlen(typeStr) <= 0) {
+      psError(PS_ERR_UNKNOWN, false, "No -type specified.");
+      goto ERROR;
+    }
+    ppMergeType type = PPMERGE_TYPE_UNKNOWN; // Enumerated type for frame type
+    if (strcasecmp(typeStr, "BIAS") == 0) {
+      type = PPMERGE_TYPE_BIAS;
+      goto VALID;
+    }
+    if (strcasecmp(typeStr, "DARK") == 0 ||
+        strcasecmp(typeStr, "DARK_PREMASK") == 0) {
+      type = PPMERGE_TYPE_DARK;
+      goto VALID;
+    }
+    if (strcasecmp(typeStr, "FLAT") == 0 ||
+        strcasecmp(typeStr, "DOMEFLAT") == 0 ||
+        strcasecmp(typeStr, "SKYFLAT") == 0 ||
+        strcasecmp(typeStr, "FLAT_PREMASK") == 0 ||
+        strcasecmp(typeStr, "SKYFLAT_PREMASK") == 0 ||
+        strcasecmp(typeStr, "DOMEFLAT_PREMASK") == 0) {
+      type = PPMERGE_TYPE_FLAT;
+      goto VALID;
+    }
+    if (strcasecmp(typeStr, "FRINGE") == 0) {
+      type = PPMERGE_TYPE_FRINGE;
+      goto VALID;
+    }
+    if (strcasecmp(typeStr, "SHUTTER") == 0) {
+      type = PPMERGE_TYPE_SHUTTER;
+      goto VALID;
+    }
+    if (strcasecmp(typeStr, "MASK") == 0 ||
+        strcasecmp(typeStr, "DARKMASK") == 0 ||
+        strcasecmp(typeStr, "FLATMASK") == 0) {
+      type = PPMERGE_TYPE_MASK;
+      goto VALID;
+    }
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unrecognised image type: %s", typeStr);
+    goto ERROR;
+
+ VALID:
+    psMetadataAddS32(config->arguments, PS_LIST_TAIL, "TYPE", 0, "Type of calibration frame", type);
+
+    // Need to set the camera before the recipes can be read
+    if (!ppMergeCamera(config)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to setup cameras.");
+        goto ERROR;
+    }
+
+    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPMERGE_RECIPE); // Recipe for ppSim
+    if (!recipe) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find recipe %s", PPMERGE_RECIPE);
+        goto ERROR;
+    }
+
+    // Standard combination parameters
+    VALUE_ARG_RECIPE_INT("-rows",       "ROWS",     S32, 0);
+    VALUE_ARG_RECIPE_INT("-sample",     "SAMPLE",   S32, 0);
+    VALUE_ARG_RECIPE_INT("-iter",       "ITER",     S32, 0);
+    VALUE_ARG_RECIPE_FLOAT("-rej",      "REJ",      F32);
+    VALUE_ARG_RECIPE_FLOAT("-fraclow",  "FRACLOW",  F32);
+    VALUE_ARG_RECIPE_FLOAT("-frachigh", "FRACHIGH", F32);
+    VALUE_ARG_RECIPE_INT("-nkeep",      "NKEEP",    S32, 0);
+    VALUE_ARG_RECIPE_BOOL("-weights",   "WEIGHTS");
+
+    // XXX we do not supply this on the command line
+    // VALUE_ARG_RECIPE_MASK("-maskval",   "MASKVAL");
+
+    VALUE_ARG_RECIPE_STAT("-combine",   "COMBINE");
+    VALUE_ARG_RECIPE_STAT("-mean",      "MEAN");
+    VALUE_ARG_RECIPE_STAT("-stdev",     "STDEV");
+
+    // Fringe construction parameters
+    VALUE_ARG_RECIPE_INT("-fringe-num",     "FRINGE.NUM",     S32, 0);
+    VALUE_ARG_RECIPE_INT("-fringe-size",    "FRINGE.SIZE",    S32, 0);
+    VALUE_ARG_RECIPE_INT("-fringe-xsmooth", "FRINGE.XSMOOTH", S32, 0);
+    VALUE_ARG_RECIPE_INT("-fringe-ysmooth", "FRINGE.YSMOOTH", S32, 0);
+
+    // Shutter construction parameters
+    VALUE_ARG_RECIPE_INT("-shutter-size",  "SHUTTER.SIZE", S32, 0);
+
+    // Mask construction parameters
+    VALUE_ARG_RECIPE_FLOAT("-mask-suspect", "MASK.SUSPECT", F32);
+    VALUE_ARG_RECIPE_FLOAT("-mask-bad",     "MASK.BAD",     F32);
+    VALUE_ARG_RECIPE_INT("-mask-grow",      "MASK.GROW",    S32, 0);
+    VALUE_ARG_RECIPE_STR("-mask-set-value", "MASK.SET.VALUE");
+    VALUE_ARG_RECIPE_BOOL("-mask-chip",     "MASK.CHIPSTATS");
+
+    VALUE_ARG_RECIPE_BOOL("-mask-smooth-suspect", "MASK.SMOOTH.SUSPECT");
+    VALUE_ARG_RECIPE_FLOAT("-mask-smooth-scale", "MASK.SMOOTH.SCALE", F32);
+
+    const char *maskModeStr = psMetadataLookupStr(NULL, arguments, "-mask-mode"); // Mode to identify bad pix
+    if (!maskModeStr) {
+        maskModeStr = psMetadataLookupStr(NULL, recipe, "MASK.MODE");
+        if (!maskModeStr) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false, "No mask mode specified in recipe.");
+            goto ERROR;
+        }
+    }
+    pmMaskIdentifyMode maskMode = pmMaskIdentifyModeFromString(maskModeStr);
+    if (maskMode == PM_MASK_ID_NONE) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Invalid mask mode %s", maskModeStr);
+        goto ERROR;
+    }
+    psMetadataAddS32(config->arguments, PS_LIST_TAIL, "MASK.MODE", 0, "Mode for mask identification",
+                     maskMode);
+
+
+    if (type == PPMERGE_TYPE_DARK) {
+        psMetadata *ordinates = psMetadataLookupMetadata(NULL, recipe, "DARK.ORDINATES"); // Ordinates info
+        psArray *translated = psArrayAllocEmpty(psListLength(ordinates->list)); // Translated version
+
+        psMetadataIterator *iter = psMetadataIteratorAlloc(ordinates, PS_LIST_HEAD, NULL); // Iterator
+        psMetadataItem *item;           // Item from iteration
+        while ((item = psMetadataGetAndIncrement(iter))) {
+            int order = 0;              // Polynomial order
+            bool scale = false;         // Scale values?
+            float min = NAN, max = NAN; // Minimum and maximum values for scaling
+            switch (item->type) {
+              case PS_TYPE_S32:
+                order = item->data.S32;
+                break;
+              case PS_DATA_METADATA:
+                order = psMetadataLookupS32(NULL, item->data.md, "ORDER");
+                bool mdok;                  // Status of MD lookup
+                scale = psMetadataLookupBool(&mdok, item->data.md, "SCALE");
+                min = psMetadataLookupF32(&mdok, item->data.md, "MIN");
+                max = psMetadataLookupF32(&mdok, item->data.md, "MAX");
+                break;
+              default:
+                psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                        "Type of DARK.ORDINATES entry %s (%x) is not METADATA or S32",
+                        item->name, item->type);
+                return false;
+            }
+            if (order <= 0) {
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true, "ORDER not positive (%d) for DARK.ORDINATES %s",
+                        order, item->name);
+                return false;
+            }
+
+            pmDarkOrdinate *ord = pmDarkOrdinateAlloc(item->name, order);
+            ord->scale = scale;
+            ord->min = min;
+            ord->max = max;
+            psArrayAdd(translated, translated->n, ord);
+            psFree(ord);
+        }
+        psFree(iter);
+
+        psMetadataAddArray(config->arguments, PS_LIST_TAIL, "DARK.ORDINATES", 0,
+                           "Ordinates to fit for dark", translated);
+        psFree(translated);             // Drop reference
+
+        psString darkNorm = psMetadataLookupStr(NULL, recipe, "DARK.NORM"); // Normalisation concept
+        if (darkNorm && strcmp(darkNorm, "NONE") != 0) {
+            psMetadataAddStr(config->arguments, PS_LIST_TAIL, "DARK.NORM", 0,
+                             "Normalisation concept for dark", darkNorm);
+        }
+    }
+
+
+#if 0
+    // Add concepts for scale and zero
+    // XXX These have never been used
+    psMetadataItem *scaleItem = psMetadataItemAllocF32("PPMERGE.SCALE", "Scaling for ppMerge", NAN);
+    psMetadataItem *zeroItem = psMetadataItemAllocF32("PPMERGE.ZERO", "Zero offset for ppMerge", NAN);
+    pmConceptRegister(scaleItem, NULL, NULL, false, PM_FPA_LEVEL_CELL);
+    pmConceptRegister(zeroItem, NULL, NULL, false, PM_FPA_LEVEL_CELL);
+    psFree(scaleItem);
+    psFree(zeroItem);
+#endif
+
+    return true;
+
+ERROR:
+    psFree(arguments);
+    return false;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeCamera.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeCamera.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeCamera.c	(revision 22158)
@@ -0,0 +1,353 @@
+#include "ppMerge.h"
+
+// Define an output file, with its own FPA
+bool outputFile(pmConfig *config,       // Configuration
+                const char *name,       // Name of output file
+                pmFPAfileType type,     // Type of file
+                const char *description, // Description of file
+                psMetadata *format,     // Camera format
+                pmFPAview *view         // View for PHU
+    )
+{
+    assert(config);
+    assert(name && strlen(name) > 0);
+    assert(view);
+
+    // Output image
+    pmFPA *fpa = pmFPAConstruct(config->camera, config->cameraName); // FPA to contain the output
+    if (!fpa) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to construct an FPA from camera configuration.");
+        return false;
+    }
+
+    // Chip selection: turn on only the chips specified.
+    bool status;
+    char *chipLine = psMetadataLookupStr(&status, config->arguments, "CHIP_SELECTIONS");
+    psArray *chips = psStringSplitArray (chipLine, ",", false);
+    if (chips->n > 0) {
+        pmFPASelectChip (fpa, -1, true); // deselect all chips
+        for (int i = 0; i < chips->n; i++) {
+            int chipNum = atoi(chips->data[i]);
+            if (! pmFPASelectChip(fpa, chipNum, false)) {
+                psError(PS_ERR_IO, false, "Chip number %d doesn't exist in camera.\n", chipNum);
+		psFree (chips);
+                return false;
+            }
+        }
+    }
+    psFree (chips);
+
+    // Cell selection: turn on only the cells specified.  Note that this affects the same cell
+    // for all chips
+    char *cellLine = psMetadataLookupStr(&status, config->arguments, "CELL_SELECTIONS");
+    psArray *cells = psStringSplitArray (cellLine, ",", false);
+    if (cells->n > 0) {
+	for (int i = 0; i < fpa->chips->n; i++) {
+	    pmChip *chip = fpa->chips->data[i];
+	    pmChipSelectCell (chip, -1, true); // deselect all cells
+	    for (int j = 0; j < cells->n; j++) {
+		int cellNum = atoi(cells->data[j]);
+		if (! pmChipSelectCell(chip, cellNum, false)) {
+		    psError(PS_ERR_IO, false, "Cell number %d doesn't exist in camera.\n", cellNum);
+		    psFree (cells);
+		    return false;
+		}
+	    }
+	}
+    }
+    psFree (cells);
+
+    pmFPAfile *output = pmFPAfileDefineOutput(config, fpa, name);
+    psFree(fpa);                        // Drop reference
+    if (!output) {
+        psError(PS_ERR_IO, false, "Unable to generate output file from %s", name);
+        return false;
+    }
+    if (output->type != type) {
+        psError(PS_ERR_IO, true, "%s is not of type %s", name, pmFPAfileStringFromType(type));
+        return false;
+    }
+    output->save = true;
+
+    if (!pmFPAAddSourceFromView(fpa, description, view, format)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to generate output FPA.");
+        return false;
+    }
+
+    return true;
+}
+
+
+bool ppMergeCamera(pmConfig *config)
+{
+    bool haveMasks = false;             // Do we have masks?
+    bool haveWeights = false;           // Do we have weight maps?
+
+    ppMergeType type = psMetadataLookupS32(NULL, config->arguments, "TYPE"); // Type of frame
+    psMetadata *inputs = psMetadataLookupMetadata(NULL, config->arguments, "INPUTS"); // The inputs info
+    psMetadataIterator *iter = psMetadataIteratorAlloc(inputs, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *item;               // Item from iteration
+    int numFiles = 0;                   // Number of files
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        if (item->type != PS_DATA_METADATA) {
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    "Component %s of the input metadata is not of type METADATA", item->name);
+            psFree(iter);
+            return false;
+        }
+
+        psMetadata *input = item->data.md; // The input metadata of interest
+
+        psString image = psMetadataLookupStr(NULL, input, "IMAGE"); // Name of image
+        if (!image || strlen(image) == 0) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Component %s lacks IMAGE of type STR", item->name);
+            psFree(iter);
+            return false;
+        }
+
+        bool mdok;
+        psString mask = psMetadataLookupStr(&mdok, input, "MASK"); // Name of mask
+        psString weight = psMetadataLookupStr(&mdok, input, "WEIGHT"); // Name of weight map
+
+        // Add the image file
+        psArray *imageFiles = psArrayAlloc(1); // Array of filenames for this FPA
+        imageFiles->data[0] = psMemIncrRefCounter(image);
+        psMetadataAddArray(config->arguments, PS_LIST_TAIL, "IMAGE.FILENAMES", PS_META_REPLACE,
+                           "Filenames of image files", imageFiles);
+        psFree(imageFiles);
+
+        bool found = false;             // Found the file?
+        pmFPAfile *imageFile = pmFPAfileDefineFromArgs(&found, config, "PPMERGE.INPUT", "IMAGE.FILENAMES");
+        if (!imageFile || !found) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to define file from image %d (%s)", numFiles, image);
+            return false;
+        }
+        if (imageFile->type != PM_FPA_FILE_IMAGE) {
+            psError(PS_ERR_IO, true, "PPMERGE.INPUT is not of type IMAGE");
+            return false;
+        }
+
+        // Optionally add the mask file
+        if (mask && strlen(mask) > 0) {
+            psArray *maskFiles = psArrayAlloc(1); // Array of filenames for this FPA
+            maskFiles->data[0] = psMemIncrRefCounter(mask);
+            psMetadataAddArray(config->arguments, PS_LIST_TAIL, "MASK.FILENAMES", PS_META_REPLACE,
+                               "Filenames of mask files", maskFiles);
+            psFree(maskFiles);
+
+            bool status;
+            pmFPAfile *maskFile = pmFPAfileBindFromArgs(&status, imageFile, config, "PPMERGE.INPUT.MASK",
+                                                        "MASK.FILENAMES");
+            if (!status) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to define file from mask %d (%s)", numFiles, mask);
+                return false;
+            }
+            if (maskFile->type != PM_FPA_FILE_MASK) {
+                psError(PS_ERR_IO, true, "PPMERGE.INPUT.MASK is not of type MASK");
+                return false;
+            }
+            haveMasks = true;
+        }
+
+        // Optionally add the weight file
+        if (weight && strlen(weight) > 0) {
+            haveWeights = true;
+            psArray *weightFiles = psArrayAlloc(1); // Array of filenames for this FPA
+            weightFiles->data[0] = psMemIncrRefCounter(weight);
+            psMetadataAddArray(config->arguments, PS_LIST_TAIL, "WEIGHT.FILENAMES", PS_META_REPLACE,
+                               "Filenames of weight files", weightFiles);
+            psFree(weightFiles);
+
+            bool status;
+            pmFPAfile *weightFile = pmFPAfileBindFromArgs(&status, imageFile, config, "PPMERGE.INPUT.WEIGHT",
+                                                          "WEIGHT.FILENAMES");
+            if (!status) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to define file from weight %d (%s)", numFiles, weight);
+                return false;
+            }
+            if (weightFile->type != PM_FPA_FILE_WEIGHT) {
+                psError(PS_ERR_IO, true, "PPMERGE.INPUT.WEIGHT is not of type WEIGHT");
+                return false;
+            }
+            haveWeights = true;
+        }
+
+        numFiles++;
+    }
+    psFree(iter);
+    psMetadataRemoveKey(config->arguments, "IMAGE.FILENAMES");
+    if (psMetadataLookup(config->arguments, "MASK.FILENAMES")) {
+        psMetadataRemoveKey(config->arguments, "MASK.FILENAMES");
+    }
+    if (psMetadataLookup(config->arguments, "WEIGHT.FILENAMES")) {
+        psMetadataRemoveKey(config->arguments, "WEIGHT.FILENAMES");
+    }
+    if (psMetadataLookup(config->arguments, "PSF.FILENAMES")) {
+        psMetadataRemoveKey(config->arguments, "PSF.FILENAMES");
+    }
+
+    psMetadataAddS32(config->arguments, PS_LIST_TAIL, "INPUTS.NUM", 0, "Number of input files", numFiles);
+    psMetadataAddBool(config->arguments, PS_LIST_TAIL, "INPUTS.MASKS", 0, "Got input masks?", haveMasks);
+    psMetadataAddBool(config->arguments, PS_LIST_TAIL, "INPUTS.WEIGHTS", 0,
+                      "Got input weights?", haveWeights);
+
+
+    // Check that all the inputs are consistent
+
+// Check an FPA level to ensure the camera format and PHU are consistent across all input files
+#define CHECK_LEVEL(HDU, CHIP, CELL) { \
+    if (HDU) { \
+        if (!phuView) { \
+            phuView = pmFPAviewAlloc(0); \
+            phuView->chip = CHIP; \
+            phuView->cell = CELL; \
+        } else if ((phuView->chip != (CHIP)) && (phuView->cell != (CELL))) { \
+            psError(PS_ERR_UNKNOWN, true, "Differing PHU for input %d", i); \
+            psFree(phuView); \
+            return false; \
+        } \
+        if (!format) { \
+            format = (HDU)->format; \
+        } else if (format != (HDU)->format) { \
+            psError(PS_ERR_UNKNOWN, true, "Camera format %d doesn't match: %p vs %p", \
+                    i, format, (HDU)->format); \
+            psFree(phuView); \
+            return false; \
+        } \
+        continue; \
+    } \
+}
+
+    psMetadata *format = NULL;          // Camera format
+    pmFPAview *phuView = NULL;          // View to PHU
+    for (int i = 0; i < numFiles; i++) {
+        pmFPAfile *input = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", i); // File of interest
+        pmFPA *fpa = input->fpa;        // FPA of interest
+        CHECK_LEVEL(fpa->hdu, -1, -1);
+        psArray *chips = fpa->chips;    // Array of chips
+        for (int j = 0; j < chips->n; j++) {
+            pmChip *chip = chips->data[j]; // Chip of interest
+            CHECK_LEVEL(chip->hdu, j, -1);
+            psArray *cells = chip->cells;   // Array of cells
+            for (int k = 0; k < cells->n; k++) {
+                pmCell *cell = cells->data[k]; // Cell of interest
+                CHECK_LEVEL(cell->hdu, j, k);
+            }
+        }
+    }
+    if (!phuView || !format) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find PHU for input files.");
+        psFree(phuView);
+        return false;
+    }
+
+    // Cull chips and cells that don't have data
+    // Otherwise the abundance of metadata in the concepts (esp. for GPC) can overload the memory
+    for (int i = 0; i < numFiles; i++) {
+        pmFPAfile *input = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", i); // File of interest
+        pmFPA *fpa = input->fpa;        // FPA of interest
+        psArray *chips = fpa->chips; // Array of chips in output
+        for (int i = 0; i < chips->n; i++) {
+            pmChip *chip = chips->data[i]; // Chip of interest
+            psArray *cells = chip->cells; // Array of cells
+            int culled = 0;             // Number of culled cells
+            for (int j = 0; j < cells->n; j++) {
+                pmCell *cell = cells->data[j];
+                pmHDU *hdu = pmHDUGetLowest(fpa, chip, cell); // HDU for cell
+                if (!hdu || hdu->blankPHU) {
+                    cell->data_exists = false;
+                    cell->file_exists = false;
+                    culled++;
+		    if (cell->concepts) {
+			psFree(cell->concepts);
+			cell->concepts = NULL;
+		    }
+                }
+            }
+            if (culled == cells->n) {
+                chip->data_exists = false;
+                chip->file_exists = false;
+		if (chip->concepts) {
+		    psFree(chip->concepts);
+		    chip->concepts = NULL;
+		}
+            }
+        }
+    }
+
+    // Count the cells
+    {
+        int numCells = 0;               // Number of cells
+        pmFPAfile *input = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", 0); // Representative file
+        pmFPA *fpa = input->fpa;        // FPA for file
+        psArray *chips = fpa->chips; // Array of chips
+        for (int i = 0; i < chips->n; i++) {
+            pmChip *chip = chips->data[i]; // Chip of interest
+            psArray *cells = chip->cells; // Array of cells
+            for (int j = 0; j < cells->n; j++) {
+                pmCell *cell = cells->data[j]; // Cell of interest
+                pmHDU *hdu = pmHDUGetLowest(fpa, chip, cell); // HDU that would have data
+                if (hdu && !hdu->blankPHU) {
+                    numCells++;
+                }
+            }
+        }
+
+        psMetadataAddS32(config->arguments, PS_LIST_TAIL, "INPUTS.CELLS", 0, "Number of cells in input",
+                         numCells);
+    }
+
+    // Output image
+    pmFPA *fpa = pmFPAConstruct(config->camera, config->cameraName); // FPA to contain the output
+    if (!fpa) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to construct an FPA from camera configuration.");
+        psFree(phuView);
+        return false;
+    }
+
+    psString outName = ppMergeOutputFile(config); // Name of output file
+
+    pmFPAfileType fileType = PM_FPA_FILE_NONE; // Type of output file
+    switch (type) {
+      case PPMERGE_TYPE_BIAS:
+        fileType = PM_FPA_FILE_IMAGE;
+        break;
+      case PPMERGE_TYPE_DARK:
+        fileType = PM_FPA_FILE_DARK;
+        break;
+      case PPMERGE_TYPE_MASK:
+        fileType = PM_FPA_FILE_MASK;
+        break;
+      case PPMERGE_TYPE_SHUTTER:
+        fileType = PM_FPA_FILE_IMAGE;
+        break;
+      case PPMERGE_TYPE_FLAT:
+        fileType = PM_FPA_FILE_IMAGE;
+        break;
+      case PPMERGE_TYPE_FRINGE:
+        fileType = PM_FPA_FILE_FRINGE;
+      default:
+        psAbort("Unknown frame type: %x", type);
+    }
+
+    if (!outputFile(config, outName, fileType, "Merged detrend", format, phuView)) {
+        psFree(outName);
+        psFree(phuView);
+        return false;
+    }
+    psFree(outName);
+
+    if (!outputFile(config, "PPMERGE.OUTPUT.SIGMA", PM_FPA_FILE_IMAGE, "Merge sigma", format, phuView)) {
+        psFree(phuView);
+        return false;
+    }
+
+    if (!outputFile(config, "PPMERGE.OUTPUT.COUNT", PM_FPA_FILE_IMAGE, "Merged count", format, phuView)) {
+        psFree(phuView);
+        return false;
+    }
+
+    psFree(phuView);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeErrorCodes.c.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeErrorCodes.c.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeErrorCodes.c.in	(revision 22158)
@@ -0,0 +1,26 @@
+/*
+ * The line
+    { PPMERGE_ERR_$X{ErrorCode}, "$X{ErrorDescription}"},
+ * (without the Xs)
+ * will be replaced by values from errorCodes.dat
+ */
+#include "pslib.h"
+#include "ppMergeErrorCodes.h"
+
+void ppMergeErrorRegister(void)
+{
+    static psErrorDescription errors[] = {
+       { PPMERGE_ERR_BASE, "First value we use; lower values belong to psLib" },
+       { PPMERGE_ERR_${ErrorCode}, "${ErrorDescription}"},
+    };
+    static int nerror = PPMERGE_ERR_NERROR - PPMERGE_ERR_BASE; // number of values in enum
+
+    for (int i = 0; i < nerror; i++) {
+       psErrorDescription *tmp = psAlloc(sizeof(psErrorDescription));
+       p_psMemSetPersistent(tmp, true);
+       *tmp = errors[i];
+       psErrorRegister(tmp, 1);
+       psFree(tmp);			/* it's on the internal list */
+    }
+    nerror = 0;			                // don't register more than once
+}
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeErrorCodes.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeErrorCodes.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeErrorCodes.dat	(revision 22158)
@@ -0,0 +1,10 @@
+#
+# This file is used to generate ppMergeErrorClasses.h
+#
+BASE = 700		First value we use; lower values belong to psLib
+# these errors correspond to standard exit conditions
+ARGUMENTS               Incorrect arguments
+SYS                     System error
+CONFIG                  Problem in configure files
+PROG                    Programming error
+DATA                    invalid data
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeErrorCodes.h.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeErrorCodes.h.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeErrorCodes.h.in	(revision 22158)
@@ -0,0 +1,18 @@
+#if !defined(PPMERGE_ERROR_CODES_H)
+#define PPMERGE_ERROR_CODES_H
+/*
+ * The line
+ *  PPMERGE_ERR_$X{ErrorCode},
+ * (without the X)
+ *
+ * will be replaced by values from errorCodes.dat
+ */
+typedef enum {
+    PPMERGE_ERR_BASE = 512,
+    PPMERGE_ERR_${ErrorCode},
+    PPMERGE_ERR_NERROR
+} ppMergeErrorCode;
+
+void ppMergeErrorRegister(void);
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeFileGroup.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeFileGroup.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeFileGroup.c	(revision 22158)
@@ -0,0 +1,20 @@
+# include "ppMerge.h"
+
+void ppMergeFileGroupFree (ppMergeFileGroup *group) {
+
+    if (!group) return;
+
+    psFree (group->readouts);
+    return;
+}
+
+ppMergeFileGroup *ppMergeFileGroupAlloc() {
+
+    ppMergeFileGroup *group = (ppMergeFileGroup *) psAlloc(sizeof(ppMergeFileGroup));
+    psMemSetDeallocator(group, (psFreeFunc) ppMergeFileGroupFree);
+
+    group->readouts = NULL;
+    group->read = false;
+    group->busy = false;
+    return group;
+}
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeFiles.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeFiles.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeFiles.c	(revision 22158)
@@ -0,0 +1,205 @@
+#include "ppMerge.h"
+
+const char *allFiles[] = { "PPMERGE.INPUT", "PPMERGE.INPUT.MASK", "PPMERGE.INPUT.WEIGHT",
+                           "PPMERGE.OUTPUT", "PPMERGE.OUTPUT.COUNT", "PPMERGE.OUTPUT.SIGMA",
+                           NULL };      // All files
+const char *inputFiles[] = { "PPMERGE.INPUT", "PPMERGE.INPUT.MASK", "PPMERGE.INPUT.WEIGHT",
+                             NULL };    // Input files
+const char *outputFiles[] = { "PPMERGE.OUTPUT", "PPMERGE.OUTPUT.COUNT", "PPMERGE.OUTPUT.SIGMA",
+                              NULL };   // Output files
+
+// Select file list based on enum
+static const char **selectFiles(ppMergeFiles files)
+{
+    switch (files) {
+      case PPMERGE_FILES_ALL:    return allFiles;
+      case PPMERGE_FILES_INPUT:  return inputFiles;
+      case PPMERGE_FILES_OUTPUT: return outputFiles;
+      default:
+        psAbort("Invalid file option");
+    }
+    return NULL;
+}
+
+bool ppMergeFileReadInput(pmConfig *config, pmReadout *readout, int num, int rows)
+{
+    pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", num);
+    if (!pmReadoutReadChunk(readout, file->fits, 0, rows, 0, config)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read readout.");
+        return false;
+    }
+    bool mdok;          // Status of MD lookup
+    if (psMetadataLookupBool(&mdok, config->arguments, "INPUTS.MASKS")) {
+        pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT.MASK", num);
+        if (!pmReadoutReadChunkMask(readout, file->fits, 0, rows, 0, config)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to read readout mask.");
+            return false;
+        }
+    }
+    if (psMetadataLookupBool(&mdok, config->arguments, "INPUTS.WEIGHTS")) {
+        pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT.WEIGHT", num);
+        if (!pmReadoutReadChunkWeight(readout, file->fits, 0, rows, 0, config)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to read readout weight.");
+            return false;
+        }
+    }
+    return true;
+}
+
+bool ppMergeFileOpenInput(pmConfig *config, const pmFPAview *view, int num)
+{
+    {
+        pmFPAfile *input = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", num);
+        pmFPAview *fileView = pmFPAviewForLevel(input->fileLevel, view);
+        if (!pmFPAfileOpen(input, fileView, config)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to open image file %d", num);
+            psFree(fileView);
+            return false;
+        }
+        psFree(fileView);
+    }
+    bool mdok;          // Status of MD lookup
+    if (psMetadataLookupBool(&mdok, config->arguments, "INPUTS.MASKS")) {
+        pmFPAfile *mask = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT.MASK", num); // Mask file
+        pmFPAview *fileView = pmFPAviewForLevel(mask->fileLevel, view);
+        if (!pmFPAfileOpen(mask, fileView, config)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to open mask file %d", num);
+            psFree(fileView);
+            return false;
+        }
+        psFree(fileView);
+    }
+    if (psMetadataLookupBool(&mdok, config->arguments, "INPUTS.WEIGHTS")) {
+        pmFPAfile *weight = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT.WEIGHT", num); // Weight file
+        pmFPAview *fileView = pmFPAviewForLevel(weight->fileLevel, view);
+        if (!pmFPAfileOpen(weight, fileView, config)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to open weight file %d", num);
+            psFree(fileView);
+            return false;
+        }
+        psFree(fileView);
+    }
+    return true;
+}
+
+psArray *ppMergeFileDataLevel(const pmConfig *config, const char *name, pmFPALevel level)
+{
+    assert(config);
+    assert(name);
+
+    int numFiles = psMetadataLookupS32(NULL, config->arguments, "INPUTS.NUM"); // Number of input files
+    assert(numFiles > 0);
+    psArray *files = psArrayAlloc(numFiles); // Files of interest
+    for (int i = 0; i < numFiles; i++) {
+        pmFPAfile *file = pmFPAfileSelectSingle(config->files, name, i); // Image file
+        file->dataLevel = level;
+        file->freeLevel = level;
+        files->data[i] = psMemIncrRefCounter(file);
+    }
+    return files;
+}
+
+bool ppMergeFileActivate(const pmConfig *config, ppMergeFiles files, bool state)
+{
+    assert(config);
+
+    bool mdok;                          // Status of MD lookup
+    bool haveMasks = psMetadataLookupBool(&mdok, config->arguments, "INPUTS.MASKS"); // Do we have masks?
+    bool haveWeights = psMetadataLookupBool(&mdok, config->arguments, "INPUTS.WEIGHTS"); // Got weights?
+
+    const char **fileList = selectFiles(files); // Files to activate
+    for (int i = 0; fileList[i] != NULL; i++) {
+        if (!haveMasks && strcmp(fileList[i], "PPMERGE.INPUT.MASK") == 0) {
+            continue;
+        }
+        if (!haveWeights && strcmp(fileList[i], "PPMERGE.INPUT.WEIGHT") == 0) {
+            continue;
+        }
+        psString name = NULL;           // Name of file
+        if (strcmp(fileList[i], "PPMERGE.OUTPUT") == 0) {
+            name = ppMergeOutputFile(config);
+        } else {
+            name = psStringCopy(fileList[i]);
+        }
+
+        if (!pmFPAfileActivate(config->files, state, name)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to activate file %s", name);
+            psFree(name);
+            return false;
+        }
+        psFree(name);
+    }
+
+    return true;
+}
+
+
+
+psArray *ppMergeFileActivateSingle(const pmConfig *config, ppMergeFiles files, bool state, int num)
+{
+    assert(config);
+
+    bool mdok;                          // Status of MD lookup
+    bool haveMasks = psMetadataLookupBool(&mdok, config->arguments, "INPUTS.MASKS"); // Do we have masks?
+    bool haveWeights = psMetadataLookupBool(&mdok, config->arguments, "INPUTS.WEIGHTS"); // Got weights?
+
+    psList *list = psListAlloc(NULL);   // List of files
+    const char **fileList = selectFiles(files); // Files to activate
+    for (int i = 0; fileList[i] != NULL; i++) {
+        if (!haveMasks && strcmp(fileList[i], "PPMERGE.INPUT.MASK") == 0) {
+            continue;
+        }
+        if (!haveWeights && strcmp(fileList[i], "PPMERGE.INPUT.WEIGHT") == 0) {
+            continue;
+        }
+
+        psString name = NULL;           // Name of file
+        if (strcmp(fileList[i], "PPMERGE.OUTPUT") == 0) {
+            name = ppMergeOutputFile(config);
+        } else {
+            name = psStringCopy(fileList[i]);
+        }
+
+        pmFPAfile *file = pmFPAfileActivateSingle(config->files, state, name, num); // Activated file
+        psFree(name);
+        psListAdd(list, PS_LIST_TAIL, file);
+    }
+
+    psArray *array = psListToArray(list);
+    psFree(list);
+
+    return array;
+}
+
+
+psString ppMergeOutputFile(const pmConfig *config)
+{
+    ppMergeType type = psMetadataLookupS32(NULL, config->arguments, "TYPE"); // Type of frame
+    const char *outSuffix = NULL;         // Suffix for output file
+    switch (type) {
+      case PPMERGE_TYPE_BIAS:
+        outSuffix = "BIAS";
+        break;
+      case PPMERGE_TYPE_DARK:
+        outSuffix = "DARK";
+        break;
+      case PPMERGE_TYPE_MASK:
+        outSuffix = "MASK";
+        break;
+      case PPMERGE_TYPE_SHUTTER:
+        outSuffix = "SHUTTER";
+        break;
+      case PPMERGE_TYPE_FLAT:
+        outSuffix = "FLAT";
+        break;
+      case PPMERGE_TYPE_FRINGE:
+        outSuffix = "FRINGE";
+      default:
+        psAbort("Unknown frame type: %x", type);
+    }
+
+    psString outName = NULL;            // Name of output file
+    psStringAppend(&outName, "PPMERGE.OUTPUT.%s", outSuffix);
+
+    return outName;
+}
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeLoop.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeLoop.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeLoop.c	(revision 22158)
@@ -0,0 +1,358 @@
+#include "ppMerge.h"
+
+bool ppMergeLoop(pmConfig *config)
+{
+    assert(config);
+
+    psMetadata *arguments = config->arguments; // Arguments
+    ppMergeType type = psMetadataLookupS32(NULL, config->arguments, "TYPE"); // Type of frame
+    int numFiles = psMetadataLookupS32(NULL, arguments, "INPUTS.NUM"); // Number of input files
+    bool mdok;                          // Status of MD lookup
+    bool haveMasks = psMetadataLookupBool(&mdok, arguments, "INPUTS.MASKS"); // Do we have masks?
+    bool haveWeights = psMetadataLookupBool(&mdok, arguments, "INPUTS.WEIGHTS"); // Do we have weights?
+
+    psArray *inputs = ppMergeFileDataLevel(config, "PPMERGE.INPUT", PM_FPA_LEVEL_READOUT); // Input images
+    psArray *masks = NULL, *weights = NULL; // Input masks and weights
+    if (haveMasks) {
+        masks = ppMergeFileDataLevel(config, "PPMERGE.INPUT.MASK", PM_FPA_LEVEL_READOUT);
+    }
+    if (haveWeights) {
+        weights = ppMergeFileDataLevel(config, "PPMERGE.INPUT.WEIGHT", PM_FPA_LEVEL_READOUT);
+    }
+
+    // General combination parameters
+    int rows = psMetadataLookupS32(NULL, arguments, "ROWS"); // Number of rows to read per chunk
+    int iter = psMetadataLookupS32(NULL, arguments, "ITER"); // Number of rejection iterations
+    float rej = psMetadataLookupF32(NULL, arguments, "REJ"); // Rejection level
+    float fraclow = psMetadataLookupF32(NULL, arguments, "FRACLOW"); // Reject fraction of low pixels
+    float frachigh = psMetadataLookupF32(NULL, arguments, "FRACHIGH"); // Reject fraction of hi pixels
+    int nKeep = psMetadataLookupS32(NULL, arguments, "NKEEP"); // Minimum number of values to keep
+    psStatsOptions combineStat = psMetadataLookupS32(NULL, arguments, "COMBINE"); // Combination statistic
+    bool useWeights = psMetadataLookupBool(NULL, arguments, "WEIGHTS"); // Use weights?
+
+    // Fringe parameters
+    int fringeNum = psMetadataLookupS32(NULL, arguments, "FRINGE.NUM"); // Number of fringe points
+    int fringeSize = psMetadataLookupS32(NULL, arguments, "FRINGE.SIZE"); // Size of fringe regions
+    int fringeSmoothX = psMetadataLookupS32(NULL, arguments, "FRINGE.XSMOOTH"); // Smoothing regions in x
+    int fringeSmoothY = psMetadataLookupS32(NULL, arguments, "FRINGE.YSMOOTH"); // Smoothing regions in y
+
+    // set the mask and mark bit values based on the named masks
+    psMaskType maskVal;
+    psMaskType markVal;
+    if (!pmConfigMaskSetBits (&maskVal, &markVal, config)) {
+	psError (PS_ERR_UNKNOWN, true, "Unable to define the mask bit values");
+	return false;
+    }
+
+    pmCombineParams *combination = pmCombineParamsAlloc(combineStat); // Combination parameters
+    combination->maskVal = maskVal;
+    combination->blank = pmConfigMaskGet("BLANK", config);
+    combination->nKeep = nKeep;
+    combination->fracHigh = frachigh;
+    combination->fracLow = fraclow;
+    combination->iter = iter;
+    combination->rej = rej;
+    combination->weights = useWeights;
+
+    psMetadata *stats = NULL;           // Statistics for output
+    if (psMetadataLookup(config->arguments, "STATS.NAME")) {
+        stats = psMetadataAlloc();
+        psMetadataAddMetadata(config->arguments, PS_LIST_TAIL, "STATS.DATA", 0, "Statistics output", stats);
+    }
+
+    pmFPAview *view = pmFPAviewAlloc(0); // View to component of interest
+
+    // Retrieve data placed on analysis
+    psVector *scales = NULL, *zeros = NULL; // Scale and zeroes for combination
+    psArray *shutters = NULL;           // Shutter correction data
+    switch (type) {
+      case PPMERGE_TYPE_FRINGE:
+        zeros = psMetadataLookupPtr(NULL, arguments, "ZEROS");
+        if (!zeros) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find ZEROS");
+            goto ERROR;
+        }
+        // Flow through
+      case PPMERGE_TYPE_FLAT:
+        scales = psMetadataLookupPtr(NULL, arguments, "SCALES");
+        if (!scales) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find SCALES");
+            goto ERROR;
+        }
+        break;
+      case PPMERGE_TYPE_SHUTTER:
+        shutters = psMetadataLookupPtr(NULL, arguments, "SHUTTER");
+        if (!shutters) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find SHUTTER");
+            goto ERROR;
+        }
+        break;
+      case PPMERGE_TYPE_MASK:
+      case PPMERGE_TYPE_BIAS:
+      case PPMERGE_TYPE_DARK:
+        break;
+      default:
+        psAbort("Should never get here.");
+    }
+
+    // Dark parameters
+    psArray *darkOrdinates = psMetadataLookupPtr(NULL, arguments, "DARK.ORDINATES"); // Dark info
+    psString darkNorm = psMetadataLookupStr(&mdok, arguments, "DARK.NORM"); // Dark normalisation
+
+
+    if (!ppMergeFileActivate(config, PPMERGE_FILES_ALL, true)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to activate files.");
+        goto ERROR;
+    }
+    psString outName = ppMergeOutputFile(config); // Name of output file
+    pmFPAfile *output = psMetadataLookupPtr(NULL, config->files, outName); // Output file
+    psFree(outName);
+    assert(output && output->fpa);
+    pmFPA *outFPA = output->fpa;        // Output FPA
+    int cellNum = 0;                    // Index of cell
+    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+        goto ERROR;
+    }
+    pmChip *outChip;                    // Chip of interest
+    while ((outChip = pmFPAviewNextChip(view, outFPA, 1))) {
+        if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+            goto ERROR;
+        }
+        pmCell *outCell;                // Cell of interest
+        while ((outCell = pmFPAviewNextCell(view, outFPA, 1))) {
+            if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+                goto ERROR;
+            }
+
+            pmHDU *hdu = pmHDUGetLowest(outFPA, outChip, outCell); // HDU for cell
+            if (!hdu || hdu->blankPHU) {
+                // No data here
+                continue;
+            }
+
+            pmReadout *outRO = pmReadoutAlloc(outCell);
+
+            psArray *readouts = psArrayAlloc(numFiles); // Input readouts
+            for (int i = 0; i < numFiles; i++) {
+                // We need to do some of the opening ourselves
+                if (!ppMergeFileOpenInput(config, view, i)) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to open file %d", i);
+                    goto ERROR;
+                }
+
+                pmFPAfile *input = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", i);
+                pmCell *inCell = pmFPAviewThisCell(view, input->fpa); // Input cell
+                readouts->data[i] = pmReadoutAlloc(inCell);
+            }
+
+            float shutterRef = NAN;     // Reference shutter correction
+            if (type == PPMERGE_TYPE_SHUTTER) {
+                shutterRef = pmShutterCorrectionReference(shutters->data[cellNum]);
+            }
+
+            // Read convolutions by chunks
+            bool more = true;               // More to read?
+            for (int numChunk = 0; more; numChunk++) {
+                psTrace("ppStack", 2, "Initial stack of chunk %d....\n", numChunk);
+                for (int i = 0; i < numFiles; i++) {
+                    pmReadout *inRO = readouts->data[i]; // Input readout
+
+                    // Read a chunk from a file
+                    #define READ_CHUNK(NAME,TYPE) { \
+                        pmFPAfile *file = pmFPAfileSelectSingle(config->files, NAME, i); \
+                        if (!pmReadoutReadChunk##TYPE(inRO, file->fits, 0, rows, 0, config)) { \
+                            psError(PS_ERR_IO, false, "Unable to read chunk %d for file %s %d", \
+                                    numChunk, NAME, i); \
+                            psFree(readouts); \
+                            psFree(outRO); \
+                            goto ERROR; \
+                        } \
+                    }
+
+                    READ_CHUNK("PPMERGE.INPUT", /* Blank */);
+                    if (haveMasks) {
+                        READ_CHUNK("PPMERGE.INPUT.MASK", Mask);
+                    }
+                    if (haveWeights) {
+                        READ_CHUNK("PPMERGE.INPUT.WEIGHT", Weight);
+                    }
+                }
+
+                switch (type) {
+                  case PPMERGE_TYPE_SHUTTER:
+                    if (!pmShutterCorrectionGenerate(outRO, NULL, readouts, shutterRef,
+                                                     shutters->data[cellNum], iter, rej, maskVal)) {
+                        psFree(readouts);
+                        psFree(outRO);
+                        goto ERROR;
+                    }
+                    break;
+                  case PPMERGE_TYPE_DARK:
+                    if (!pmDarkCombine(outCell, readouts, darkOrdinates, darkNorm, iter, rej, maskVal)) {
+                        psFree(readouts);
+                        psFree(outRO);
+                        goto ERROR;
+                    }
+                    break;
+                  case PPMERGE_TYPE_BIAS:
+                  case PPMERGE_TYPE_FLAT:
+                  case PPMERGE_TYPE_FRINGE:
+                    if (!pmReadoutCombine(outRO, readouts, zeros, scales, combination)) {
+                        psFree(readouts);
+                        psFree(outRO);
+                        goto ERROR;
+                    }
+                    break;
+                  default:
+                    psAbort("Should never get here.");
+                }
+
+
+                for (int i = 0; i < numFiles && more; i++) {
+                    pmReadout *inRO = readouts->data[i];
+
+                    // Check to see if there's more chunks to read
+                    #define MORE_CHUNK(NAME,TYPE) { \
+                        pmFPAfile *file = pmFPAfileSelectSingle(config->files, NAME, i); \
+                        more &= pmReadoutMore##TYPE(inRO, file->fits, 0, rows, config); \
+                    }
+
+                    MORE_CHUNK("PPMERGE.INPUT", /* Blank */);
+                    if (haveMasks) {
+                        MORE_CHUNK("PPMERGE.INPUT.MASK", Mask);
+                    }
+                    if (haveWeights) {
+                        MORE_CHUNK("PPMERGE.INPUT.WEIGHT", Weight);
+                    }
+                }
+            }
+
+            // Get list of cells for concepts averaging
+            psList *inCells = psListAlloc(NULL); // List of cells
+            for (int i = 0; i < numFiles; i++) {
+                pmReadout *readout = readouts->data[i]; // Readout of interest
+                psListAdd(inCells, PS_LIST_TAIL, readout->parent);
+            }
+            if (!pmConceptsAverageCells(outCell, inCells, NULL, NULL, true)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to average cell concepts.");
+                psFree(inCells);
+                psFree(outRO);
+                goto ERROR;
+            }
+            psFree(inCells);
+
+            psFree(readouts);
+
+            // Plug supplementary images into their own FPAs
+            {
+                pmCell *countsCell = pmFPAfileThisCell(config->files, view, "PPMERGE.OUTPUT.COUNT");
+                pmReadout *countsRO = pmReadoutAlloc(countsCell); // Readout with count of inputs per pixel
+                psImage *counts = psMetadataLookupPtr(NULL, outRO->analysis, PM_READOUT_STACK_ANALYSIS_COUNT);
+                countsRO->image = psImageCopy(countsRO->image, counts, PS_TYPE_F32);
+                psMetadataRemoveKey(outRO->analysis, PM_READOUT_STACK_ANALYSIS_COUNT);
+                countsRO->data_exists = countsCell->data_exists = countsCell->parent->data_exists = true;
+                psFree(countsRO);
+
+                pmCell *sigmaCell = pmFPAfileThisCell(config->files, view, "PPMERGE.OUTPUT.SIGMA");
+                pmReadout *sigmaRO = pmReadoutAlloc(sigmaCell); // Readout with stdev per pixel
+                psImage *sigma = psMetadataLookupPtr(NULL, outRO->analysis, PM_READOUT_STACK_ANALYSIS_SIGMA);
+                sigmaRO->image = psImageCopy(sigmaRO->image, sigma, PS_TYPE_F32);
+                psMetadataRemoveKey(outRO->analysis, PM_READOUT_STACK_ANALYSIS_SIGMA);
+                sigmaRO->data_exists = sigmaCell->data_exists = sigmaCell->parent->data_exists = true;
+                psFree(sigmaRO);
+            }
+
+            // Measure the fringes for this cell
+            //
+            // XXX Need to deal with multiple components: we will do this by building up the components
+            // Read the existing fringe measurements
+            // Use existing regions to measure fringe statistics
+            // Add the new fringe measurements to the existing fringe measurements.
+            // Write the appended fringe measurements.
+            // Read in the "output" file to get the existing components.
+            // Put the new readout into the cell after the existing readouts.
+            if (type == PPMERGE_TYPE_FRINGE && outRO) {
+                pmFringeRegions *regions = pmFringeRegionsAlloc(fringeNum, fringeSize, fringeSize,
+                                                                fringeSmoothX, fringeSmoothY);
+                pmFringeStats *fringe = pmFringeStatsMeasure(regions, outRO, maskVal);
+                psFree(regions);
+                if (!fringe) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to measure fringe statistics.\n");
+                    psFree(outRO);
+                    goto ERROR;
+                }
+
+                psArray *fringes = psArrayAlloc(1); // Array of fringes
+                fringes->data[0] = fringe;
+
+                pmFringesFormat(outCell, NULL, fringes);
+                psFree(fringes);        // Drop reference
+            }
+
+            if (!ppStatsFPA(stats, outFPA, view, maskVal, config)) {
+                psError(PS_ERR_UNKNOWN, true, "Unable to generate stats for image.");
+                goto ERROR;
+            }
+
+            psFree(outRO);
+            cellNum++;
+
+            if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+                goto ERROR;
+            }
+        }
+
+        if (outChip->data_exists) {
+            psList *inChips = psListAlloc(NULL);
+            for (int i=0; i < numFiles; i++) {
+                pmChip *chip = pmFPAviewThisChip(view, ((pmFPAfile *)inputs->data[i])->fpa);
+                psListAdd(inChips, PS_LIST_TAIL, chip);
+            }
+            if (!pmConceptsAverageChips(outChip, inChips, true)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to average Chip concepts.");
+                psFree(inChips);
+                goto ERROR;
+            }
+            psFree(inChips);
+        }
+        if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+            goto ERROR;
+        }
+    }
+
+    // Get list of FPAs for concepts averaging
+    psList *inFPAs = psListAlloc(NULL); // List of FPAs
+    for (int i = 0; i < numFiles; i++) {
+        pmFPAfile *input = inputs->data[i]; // Input file
+        psListAdd(inFPAs, PS_LIST_TAIL, input->fpa);
+    }
+    if (!pmConceptsAverageFPAs(output->fpa, inFPAs)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to average FPA concepts.");
+        psFree(inFPAs);
+        goto ERROR;
+    }
+    psFree(inFPAs);
+
+
+    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+        goto ERROR;
+    }
+
+    psFree(view);
+    psFree(combination);
+    psFree(inputs);
+    psFree(masks);
+    psFree(weights);
+    psFree(stats);
+    return true;
+
+ERROR:
+    psFree(view);
+    psFree(combination);
+    psFree(inputs);
+    psFree(masks);
+    psFree(weights);
+    psFree(stats);
+    return false;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeLoop_Threaded.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeLoop_Threaded.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeLoop_Threaded.c	(revision 22158)
@@ -0,0 +1,411 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include <pslib.h>
+#include <psmodules.h>
+#include <ppStats.h>
+
+#include "ppMerge.h"
+
+bool ppMergeLoop(pmConfig *config)
+{
+    assert(config);
+
+    psMetadata *arguments = config->arguments; // Arguments
+    ppMergeType type = psMetadataLookupS32(NULL, config->arguments, "TYPE"); // Type of frame
+    int numFiles = psMetadataLookupS32(NULL, arguments, "INPUTS.NUM"); // Number of input files
+    bool mdok;                          // Status of MD lookup
+    bool haveMasks = psMetadataLookupBool(&mdok, arguments, "INPUTS.MASKS"); // Do we have masks?
+    bool haveWeights = psMetadataLookupBool(&mdok, arguments, "INPUTS.WEIGHTS"); // Do we have weights?
+
+    psArray *inputs = ppMergeFileDataLevel(config, "PPMERGE.INPUT", PM_FPA_LEVEL_READOUT); // Input images
+    psArray *masks = NULL, *weights = NULL; // Input masks and weights
+    if (haveMasks) {
+        masks = ppMergeFileDataLevel(config, "PPMERGE.INPUT.MASK", PM_FPA_LEVEL_READOUT);
+    }
+    if (haveWeights) {
+        weights = ppMergeFileDataLevel(config, "PPMERGE.INPUT.WEIGHT", PM_FPA_LEVEL_READOUT);
+    }
+
+    int nThreads = psMetadataLookupS32 (&mdok, arguments, "NTHREADS");
+    if (!mdok) nThreads = 0;
+
+    // General combination parameters
+    int iter = psMetadataLookupS32(NULL, arguments, "ITER"); // Number of rejection iterations
+    float rej = psMetadataLookupF32(NULL, arguments, "REJ"); // Rejection level
+    float fraclow = psMetadataLookupF32(NULL, arguments, "FRACLOW"); // Reject fraction of low pixels
+    float frachigh = psMetadataLookupF32(NULL, arguments, "FRACHIGH"); // Reject fraction of hi pixels
+    int nKeep = psMetadataLookupS32(NULL, arguments, "NKEEP"); // Minimum number of values to keep
+    psStatsOptions combineStat = psMetadataLookupS32(NULL, arguments, "COMBINE"); // Combination statistic
+    bool useWeights = psMetadataLookupBool(NULL, arguments, "WEIGHTS"); // Use weights?
+
+    // Fringe parameters
+    int fringeNum = psMetadataLookupS32(NULL, arguments, "FRINGE.NUM"); // Number of fringe points
+    int fringeSize = psMetadataLookupS32(NULL, arguments, "FRINGE.SIZE"); // Size of fringe regions
+    int fringeSmoothX = psMetadataLookupS32(NULL, arguments, "FRINGE.XSMOOTH"); // Smoothing regions in x
+    int fringeSmoothY = psMetadataLookupS32(NULL, arguments, "FRINGE.YSMOOTH"); // Smoothing regions in y
+
+    // set the mask and mark bit values based on the named masks
+    psMaskType maskVal;
+    psMaskType markVal;
+    if (!pmConfigMaskSetBits (&maskVal, &markVal, config)) {
+	psError (PS_ERR_UNKNOWN, true, "Unable to define the mask bit values");
+	return false;
+    }
+
+    pmCombineParams *combination = pmCombineParamsAlloc(combineStat); // Combination parameters
+    combination->maskVal = maskVal;
+    combination->blank = pmConfigMaskGet("BLANK", config);
+    combination->nKeep = nKeep;
+    combination->fracHigh = frachigh;
+    combination->fracLow = fraclow;
+    combination->iter = iter;
+    combination->rej = rej;
+    combination->weights = useWeights;
+
+    psMetadata *stats = NULL;           // Statistics for output
+    if (psMetadataLookup(config->arguments, "STATS.NAME")) {
+        stats = psMetadataAlloc();
+        psMetadataAddMetadata(config->arguments, PS_LIST_TAIL, "STATS.DATA", 0, "Statistics output", stats);
+    }
+
+    pmFPAview *view = pmFPAviewAlloc(0); // View to component of interest
+
+    // Retrieve data placed on analysis
+    psVector *scales = NULL, *zeros = NULL; // Scale and zeroes for combination
+    psArray *shutters = NULL;           // Shutter correction data
+    switch (type) {
+      case PPMERGE_TYPE_FRINGE:
+        zeros = psMetadataLookupPtr(NULL, arguments, "ZEROS");
+        if (!zeros) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find ZEROS");
+            goto ERROR;
+        }
+        // Flow through
+      case PPMERGE_TYPE_FLAT:
+        scales = psMetadataLookupPtr(NULL, arguments, "SCALES");
+        if (!scales) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find SCALES");
+            goto ERROR;
+        }
+        break;
+      case PPMERGE_TYPE_SHUTTER:
+        shutters = psMetadataLookupPtr(NULL, arguments, "SHUTTER");
+        if (!shutters) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find SHUTTER");
+            goto ERROR;
+        }
+        break;
+      case PPMERGE_TYPE_MASK:
+      case PPMERGE_TYPE_BIAS:
+      case PPMERGE_TYPE_DARK:
+        break;
+      default:
+        psAbort("Should never get here.");
+    }
+
+    // Dark parameters
+    psArray *darkOrdinates = psMetadataLookupPtr(NULL, arguments, "DARK.ORDINATES"); // Dark info
+    psString darkNorm = psMetadataLookupStr(&mdok, arguments, "DARK.NORM"); // Dark normalisation
+
+
+    if (!ppMergeFileActivate(config, PPMERGE_FILES_ALL, true)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to activate files.");
+        goto ERROR;
+    }
+    psString outName = ppMergeOutputFile(config); // Name of output file
+    pmFPAfile *output = psMetadataLookupPtr(NULL, config->files, outName); // Output file
+    psFree(outName);
+    assert(output && output->fpa);
+    pmFPA *outFPA = output->fpa;        // Output FPA
+    int cellNum = 0;                    // Index of cell
+    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+        goto ERROR;
+    }
+    pmChip *outChip;                    // Chip of interest
+    while ((outChip = pmFPAviewNextChip(view, outFPA, 1))) {
+        if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+            goto ERROR;
+        }
+        pmCell *outCell;                // Cell of interest
+        while ((outCell = pmFPAviewNextCell(view, outFPA, 1))) {
+            if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+                goto ERROR;
+            }
+
+            pmHDU *hdu = pmHDUGetLowest(outFPA, outChip, outCell); // HDU for cell
+            if (!hdu || hdu->blankPHU) {
+                // No data here
+                continue;
+            }
+
+            float shutterRef = NAN;     // Reference shutter correction
+            if (type == PPMERGE_TYPE_SHUTTER) {
+                shutterRef = pmShutterCorrectionReference(shutters->data[cellNum]);
+            }
+
+            pmReadout *outRO = pmReadoutAlloc(outCell);
+
+	    // open the input files (we need to do the work ourselves)
+            for (int i = 0; i < numFiles; i++) {
+                if (!ppMergeFileOpenInput(config, view, i)) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to open file %d", i);
+                    goto ERROR;
+                }
+	    }
+
+	    psArray *fileGroups = psArrayAlloc (nThreads + 1);
+
+	    // generate readouts for each input file in each file group
+	    for (int i = 0; i < fileGroups->n; i++) {
+		psArray *readouts = psArrayAlloc(numFiles); // Input readouts
+		for (int j = 0; j < numFiles; j++) {
+		    pmFPAfile *input = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", i);
+		    pmCell *inCell = pmFPAviewThisCell(view, input->fpa); // Input cell
+		    readouts->data[j] = pmReadoutAlloc(inCell);
+		}
+
+		ppMergeFileGroup *fileGroup = ppMergeFileGroupAlloc();
+		fileGroup->readouts = readouts;
+		fileGroup->read = false;
+		fileGroup->busy = false;
+		fileGroup->lastScan = 0;
+		fileGroup->firstScan = 0;
+		fileGroups->data[i] = fileGroup;
+            }
+
+	    // call the init functions
+	    switch (type) {
+	      case PPMERGE_TYPE_BIAS:
+	      case PPMERGE_TYPE_FLAT:
+	      case PPMERGE_TYPE_FRINGE: 
+		psAssert (fileGroups->n > 0, "no valid file groups defined");
+		ppMergeFileGroup *fileGroup = fileGroups->data[0];
+		if (!pmReadoutCombinePrepare(outRO, fileGroup->readouts, combination)) {
+		    goto ERROR;
+		}
+		break;
+
+	      default:
+		fprintf (stderr, "not yet ready");
+		goto ERROR;
+	    }
+
+            // Read input data by chunks
+	    // psTimerStart ("ppMergeLoop");
+            for (int numChunk = 0; true; numChunk++) {
+
+		bool status = false;
+		ppMergeFileGroup *fileGroup = ppMergeReadChunk (&status, fileGroups, config, numChunk);
+		if (!status) goto ERROR;
+		if (!fileGroup) break;
+
+		psThreadJob *job = NULL;
+
+                switch (type) {
+                  case PPMERGE_TYPE_SHUTTER:
+		    // allocate a job
+		    job = psThreadJobAlloc ("PPMERGE_SHUTTER_CORRECTION");
+
+		    // construct the arguments for this job
+		    psArrayAdd (job->args, 1, outRO);
+		    psArrayAdd (job->args, 1, fileGroup);
+		    psArrayAdd (job->args, 1, psScalarAlloc(shutterRef, PS_TYPE_F32));
+		    psArrayAdd (job->args, 1, shutters->data[cellNum]);
+		    psArrayAdd (job->args, 1, psScalarAlloc(iter, PS_TYPE_S32));
+		    psArrayAdd (job->args, 1, psScalarAlloc(rej, PS_TYPE_F32));
+		    psArrayAdd (job->args, 1, psScalarAlloc(maskVal, PS_TYPE_U8));
+
+		    // call: pmShutterCorrectionGenerate(outRO, NULL, fileGroup->readouts, shutterRef, shutters->data[cellNum], iter, rej, maskVal)
+		    if (!psThreadJobAddPending (job)) {
+			goto ERROR;
+		    }
+                    break;
+                  case PPMERGE_TYPE_DARK:
+		    // allocate a job
+		    job = psThreadJobAlloc ("PPMERGE_DARK_COMBINE");
+
+		    // construct the arguments for this job
+		    psArrayAdd (job->args, 1, outCell);
+		    psArrayAdd (job->args, 1, fileGroup);
+		    psArrayAdd (job->args, 1, darkOrdinates);
+		    psArrayAdd (job->args, 1, darkNorm);
+		    psArrayAdd (job->args, 1, psScalarAlloc(iter, PS_TYPE_S32));
+		    psArrayAdd (job->args, 1, psScalarAlloc(rej, PS_TYPE_F32));
+		    psArrayAdd (job->args, 1, psScalarAlloc(maskVal, PS_TYPE_U8));
+
+		    // call: pmDarkCombine(outCell, fileGroup->readouts, darkOrdinates, darkNorm, iter, rej, maskVal);
+		    if (!psThreadJobAddPending (job)) {			
+			goto ERROR;
+		    }
+                    break;
+                  case PPMERGE_TYPE_BIAS:
+                  case PPMERGE_TYPE_FLAT:
+                  case PPMERGE_TYPE_FRINGE:
+		    // allocate a job
+		    job = psThreadJobAlloc ("PPMERGE_READOUT_COMBINE");
+
+		    // construct the arguments for this job
+		    psArrayAdd (job->args, 1, outRO);
+		    psArrayAdd (job->args, 1, fileGroup);
+		    psArrayAdd (job->args, 1, zeros);
+		    psArrayAdd (job->args, 1, scales);
+		    psArrayAdd (job->args, 1, combination);
+
+		    // call: pmReadoutCombine(outRO, fileGroup->readouts, zeros, scales, combination);
+		    if (!psThreadJobAddPending (job)) {
+			goto ERROR;
+		    }
+                    break;
+                  default:
+                    psAbort("Should never get here.");
+                }
+            }
+
+	    // wait for the threads to finish and manage results
+	    if (!psThreadPoolWait ()) {
+		psError(PS_ERR_UNKNOWN, false, "Unable to combine images.");
+		return false;
+	    }
+
+	    // we don't care about the results, just dump the done queue jobs
+	    psThreadJob *job = NULL;
+	    while ((job = psThreadJobGetDone()) != NULL) {
+		psFree (job);
+	    }
+
+            psFree(fileGroups);
+
+            // Get list of cells for concepts averaging
+            psList *inCells = psListAlloc(NULL); // List of cells
+            for (int i = 0; i < numFiles; i++) {
+		pmFPAfile *input = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", i);
+		pmCell *inCell = pmFPAviewThisCell(view, input->fpa); // Input cell
+                psListAdd(inCells, PS_LIST_TAIL, inCell);
+            }
+            if (!pmConceptsAverageCells(outCell, inCells, NULL, NULL, true)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to average cell concepts.");
+                psFree(inCells);
+                psFree(outRO);
+                goto ERROR;
+            }
+            psFree(inCells);
+	    // fprintf (stdout, "done ppMergeLoop for cell : %f\n", psTimerMark ("ppMergeLoop"));
+
+            // Plug supplementary images into their own FPAs
+            {
+                pmCell *countsCell = pmFPAfileThisCell(config->files, view, "PPMERGE.OUTPUT.COUNT");
+                pmReadout *countsRO = pmReadoutAlloc(countsCell); // Readout with count of inputs per pixel
+                psImage *counts = psMetadataLookupPtr(NULL, outRO->analysis, PM_READOUT_STACK_ANALYSIS_COUNT);
+                countsRO->image = psImageCopy(countsRO->image, counts, PS_TYPE_F32);
+                psMetadataRemoveKey(outRO->analysis, PM_READOUT_STACK_ANALYSIS_COUNT);
+                countsRO->data_exists = countsCell->data_exists = countsCell->parent->data_exists = true;
+                psFree(countsRO);
+
+                pmCell *sigmaCell = pmFPAfileThisCell(config->files, view, "PPMERGE.OUTPUT.SIGMA");
+                pmReadout *sigmaRO = pmReadoutAlloc(sigmaCell); // Readout with stdev per pixel
+                psImage *sigma = psMetadataLookupPtr(NULL, outRO->analysis, PM_READOUT_STACK_ANALYSIS_SIGMA);
+                sigmaRO->image = psImageCopy(sigmaRO->image, sigma, PS_TYPE_F32);
+                psMetadataRemoveKey(outRO->analysis, PM_READOUT_STACK_ANALYSIS_SIGMA);
+                sigmaRO->data_exists = sigmaCell->data_exists = sigmaCell->parent->data_exists = true;
+                psFree(sigmaRO);
+            }
+
+            // Measure the fringes for this cell
+            //
+            // XXX Need to deal with multiple components: we will do this by building up the components
+            // Read the existing fringe measurements
+            // Use existing regions to measure fringe statistics
+            // Add the new fringe measurements to the existing fringe measurements.
+            // Write the appended fringe measurements.
+            // Read in the "output" file to get the existing components.
+            // Put the new readout into the cell after the existing readouts.
+            if (type == PPMERGE_TYPE_FRINGE && outRO) {
+                pmFringeRegions *regions = pmFringeRegionsAlloc(fringeNum, fringeSize, fringeSize,
+                                                                fringeSmoothX, fringeSmoothY);
+                pmFringeStats *fringe = pmFringeStatsMeasure(regions, outRO, maskVal);
+                psFree(regions);
+                if (!fringe) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to measure fringe statistics.\n");
+                    psFree(outRO);
+                    goto ERROR;
+                }
+
+                psArray *fringes = psArrayAlloc(1); // Array of fringes
+                fringes->data[0] = fringe;
+
+                pmFringesFormat(outCell, NULL, fringes);
+                psFree(fringes);        // Drop reference
+            }
+
+            if (!ppStatsFPA(stats, outFPA, view, maskVal, config)) {
+                psError(PS_ERR_UNKNOWN, true, "Unable to generate stats for image.");
+                goto ERROR;
+            }
+
+            psFree(outRO);
+            cellNum++;
+
+            if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+                goto ERROR;
+            }
+        }
+
+        if (outChip->data_exists) {
+            psList *inChips = psListAlloc(NULL);
+            for (int i=0; i < numFiles; i++) {
+                pmChip *chip = pmFPAviewThisChip(view, ((pmFPAfile *)inputs->data[i])->fpa);
+                psListAdd(inChips, PS_LIST_TAIL, chip);
+            }
+            if (!pmConceptsAverageChips(outChip, inChips, true)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to average Chip concepts.");
+                psFree(inChips);
+                goto ERROR;
+            }
+            psFree(inChips);
+        }
+        if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+            goto ERROR;
+        }
+    }
+
+    // Get list of FPAs for concepts averaging
+    psList *inFPAs = psListAlloc(NULL); // List of FPAs
+    for (int i = 0; i < numFiles; i++) {
+        pmFPAfile *input = inputs->data[i]; // Input file
+        psListAdd(inFPAs, PS_LIST_TAIL, input->fpa);
+    }
+    if (!pmConceptsAverageFPAs(output->fpa, inFPAs)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to average FPA concepts.");
+        psFree(inFPAs);
+        goto ERROR;
+    }
+    psFree(inFPAs);
+
+
+    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+        goto ERROR;
+    }
+
+    psFree(view);
+    psFree(combination);
+    psFree(inputs);
+    psFree(masks);
+    psFree(weights);
+    psFree(stats);
+    return true;
+
+ERROR:
+    psFree(view);
+    psFree(combination);
+    psFree(inputs);
+    psFree(masks);
+    psFree(weights);
+    psFree(stats);
+    return false;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeMask.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeMask.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeMask.c	(revision 22158)
@@ -0,0 +1,457 @@
+#include "ppMerge.h"
+
+static bool mergeMask(pmConfig *config, // Configuration
+                      const pmFPAview *view, // View to chip
+                      bool writeOut,     // Write output?
+                      psRandom *rng,    // Random number generator
+                      psMetadata *stats // Statistics output
+    )
+{
+    assert(config);
+    assert(view);
+    assert(view->chip != -1 && view->cell == -1 && view->readout == -1);
+
+    bool mdok;                          // Status of MD lookup
+    int numFiles = psMetadataLookupS32(NULL, config->arguments, "INPUTS.NUM"); // Number of input files
+    psStatsOptions meanStat = psMetadataLookupS32(NULL, config->arguments, "MEAN"); // Statistic for mean
+    psStatsOptions stdevStat = psMetadataLookupS32(NULL, config->arguments, "STDEV"); // Statistic for stdev
+    int sample = psMetadataLookupS32(NULL, config->arguments, "SAMPLE"); // Size of sample for statistics
+    bool chipStats = psMetadataLookupBool(&mdok, config->arguments, "MASK.CHIPSTATS"); // Statistics on chip?
+    float maskSuspect = psMetadataLookupF32(NULL, config->arguments, "MASK.SUSPECT"); // Threshold for suspect pixels
+    float maskBad = psMetadataLookupF32(NULL, config->arguments, "MASK.BAD"); // Threshold for bad pixels
+    pmMaskIdentifyMode maskMode = psMetadataLookupS32(NULL, config->arguments, "MASK.MODE"); // Mode for identifying bad pixels
+    int maskGrow = psMetadataLookupS32(NULL, config->arguments, "MASK.GROW"); // Radius to grow mask
+
+    bool smoothSuspect = psMetadataLookupBool(&mdok, config->arguments, "MASK.SMOOTH.SUSPECT"); // Radius to grow mask
+    float smoothScale = psMetadataLookupF32(&mdok, config->arguments, "MASK.SMOOTH.SCALE"); // Radius to grow mask
+
+    psMaskType markVal;
+    psMaskType maskValRaw;
+    if (!pmConfigMaskSetBits (&maskValRaw, &markVal, config)) {
+	psError (PS_ERR_UNKNOWN, true, "Unable to define the mask bit values");
+	return false;
+    }
+
+    char *maskOutName = psMetadataLookupStr (&mdok, config->arguments, "MASK.SET.VALUE");
+    psMaskType maskValOut = pmConfigMaskGet (maskOutName, config);
+    if (!maskValOut) {
+	psError (PS_ERR_UNKNOWN, true, "Undefined output mask bit value");
+	return false;
+    }
+    
+    psStats *statistics = psStatsAlloc(meanStat | stdevStat); // Statistics for background
+
+    psString outName = ppMergeOutputFile(config); // Name of output file
+    pmChip *outChip = pmFPAfileThisChip(config->files, view, outName); // Output chip
+    psFree(outName);
+    
+    int numCells = 1;
+    if (chipStats) {
+	// count the number of active cells for this chip:
+	numCells = 0;
+	for (int i = 0; i < outChip->cells->n; i++) {
+	    pmCell *cell = outChip->cells->data[i];
+	    if (!cell->process) continue;
+	    numCells ++;
+	}
+    }
+
+    // For each input file, get the statistics, which can be calculated at the chip or cell levels
+    psVector *values = psVectorAlloc(sample, PS_TYPE_F32); // Pixel values for statistics
+    pmFPAview *inView = pmFPAviewAlloc(0); // View for input
+    for (int i = 0; i < numFiles; i++) {
+        pmFPAfileActivate(config->files, false, NULL);
+        psArray *files = ppMergeFileActivateSingle(config, PPMERGE_FILES_INPUT, true, i); // Input files
+        pmFPAfile *input = files->data[0]; // Input file
+        psFree(files);
+        pmFPA *inFPA = input->fpa;  // Input FPA
+        *inView = *view;
+
+        int valueIndex = 0;             // Index for vector of pixel values
+
+        pmCell *inCell;                 // Input cell
+        while ((inCell = pmFPAviewNextCell(inView, inFPA, 1))) {
+
+	    // the output FPA structure carries the information about which cells to process
+            pmCell *outCell = pmFPAfileThisCell(config->files, inView, "PPMERGE.OUTPUT.MASK"); // Output cell
+	    if (!outCell->process) continue;
+
+            pmHDU *hdu = pmHDUFromCell(inCell); // HDU for cell
+            if (!hdu || hdu->blankPHU) {
+                // No data here
+                continue;
+            }
+            psTrace("ppMerge", 1, "Getting suspect pixels for file %d chip %d cell %d",
+                    i, inView->chip, inView->cell);
+
+            if (!pmFPAfileIOChecks(config, inView, PM_FPA_BEFORE)) {
+                psFree(inView);
+                goto MERGE_MASK_ERROR;
+            }
+
+            if (!ppMergeFileOpenInput(config, view, i)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to open file %d", i);
+                psFree(inView);
+                goto MERGE_MASK_ERROR;
+            }
+
+            if (inCell->readouts->n > 1) {
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                        "File %d chip %d cell %d contains more than one readout (%ld)",
+                        i, inView->chip, inView->cell, inCell->readouts->n);
+                psFree(inView);
+                goto MERGE_MASK_ERROR;
+            }
+
+            pmReadout *readout;
+            if (inCell->readouts && inCell->readouts->n == 1) {
+                readout = psMemIncrRefCounter(inCell->readouts->data[0]); // Input readout
+            } else {
+                readout = pmReadoutAlloc(inCell);
+            }
+
+            if (!ppMergeFileReadInput(config, readout, i, 0)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to read readout %d", i);
+                psFree(inView);
+                psFree(readout);
+                goto MERGE_MASK_ERROR;
+            }
+
+            pmReadout *outRO = NULL;    // Output readout
+            if (outCell->readouts && outCell->readouts->n == 1) {
+                outRO = psMemIncrRefCounter(outCell->readouts->data[0]);
+            } else {
+                outRO = pmReadoutAlloc(outCell);
+            }
+            psImage *outMask = outRO->mask;    // Output mask image (for iterative generation of mask)
+
+            psImage *image = readout->image, *mask = readout->mask; // Image and mask
+            int numCols = readout->image->numCols, numRows = readout->image->numRows; // Image size
+            int numPix = numCols * numRows; // Number of pixels
+            int num = PS_MIN(numPix, sample / numCells); // Number of values to add
+            if (!chipStats) {
+                valueIndex = 0;
+            }
+            for (int i = 0; i < num; i++) {
+                int pixel = numPix * psRandomUniform(rng);
+                int x = pixel % numCols;
+                int y = pixel / numCols;
+                if (mask && (mask->data.PS_TYPE_MASK_DATA[y][x] & maskValRaw)) continue;
+		if (outMask && (outMask->data.PS_TYPE_MASK_DATA[y][x] & maskValOut)) continue;
+		if (!isfinite(image->data.F32[y][x])) continue;
+
+                values->data.F32[valueIndex++] = image->data.F32[y][x];
+            }
+
+            if (!chipStats) {
+                values->n = valueIndex;
+                if (!psVectorStats(statistics, values, NULL, NULL, 0)) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to do statistics on readout.");
+                    psFree(inView);
+                    psFree(readout);
+                    goto MERGE_MASK_ERROR;
+                }
+
+		float mean = psStatsGetValue(statistics, meanStat);
+		float stdev = psStatsGetValue(statistics, stdevStat);
+
+		// this function increments the count for each suspect pixel in each input plane
+		// maskValRaw is used to test for valid input pixels
+                if (!pmMaskFlagSuspectPixels(outRO, readout, mean, stdev, maskSuspect, maskValRaw)) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to find suspect values in file %d", i);
+                    psFree(inView);
+                    psFree(readout);
+                    goto MERGE_MASK_ERROR;
+                }
+                pmCellFreeData(inCell);
+
+                if (!pmFPAfileIOChecks(config, inView, PM_FPA_AFTER)) {
+                    psFree(inView);
+                    psFree(readout);
+                    goto MERGE_MASK_ERROR;
+                }
+            }
+            psFree(readout);
+            psFree(outRO);
+        }
+
+        // Additional run through cells if we want chip-level statistics
+        if (chipStats && valueIndex > 0) {
+            values->n = valueIndex;
+            if (!psVectorStats(statistics, values, NULL, NULL, 0)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to do statistics on chip.");
+                goto MERGE_MASK_ERROR;
+            }
+            inView->cell = -1;
+            while ((inCell = pmFPAviewNextCell(inView, inFPA, 1))) {
+
+		// the output FPA structure carries the information about which cells to process
+		pmCell *outCell = pmFPAfileThisCell(config->files, inView, "PPMERGE.OUTPUT.MASK"); // Output cell
+		if (!outCell->process) continue;
+
+                pmHDU *hdu = pmHDUFromCell(inCell); // HDU for cell
+                if (!hdu || hdu->blankPHU) continue;
+
+                pmReadout *readout = inCell->readouts->data[0]; // Readout of interest
+
+                inView->readout = 0;
+                pmReadout *outRO = pmFPAfileThisReadout(config->files, inView, "PPMERGE.OUTPUT.MASK");
+
+		float mean = psStatsGetValue(statistics, meanStat);
+		float stdev = psStatsGetValue(statistics, stdevStat);
+
+		if (!pmMaskFlagSuspectPixels(outRO, readout, mean, stdev, maskSuspect, maskValRaw)) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to find suspect values in file %d", i);
+                    goto MERGE_MASK_ERROR;
+                }
+                pmCellFreeData(inCell);
+
+                inView->readout = -1;
+                if (!pmFPAfileIOChecks(config, inView, PM_FPA_AFTER)) {
+                    psFree(inView);
+                    goto MERGE_MASK_ERROR;
+                }
+            }
+        }
+    }
+    psFree(inView);
+    psFree(statistics); statistics = NULL;
+    psFree(values); values = NULL;
+
+
+    // Another run through the chip to threshold on the suspects
+    pmFPAfileActivate(config->files, false, NULL);
+    if (writeOut) {
+        ppMergeFileActivate(config, PPMERGE_FILES_OUTPUT, true);
+    }
+    pmFPA *outFPA = outChip->parent;    // Output FPA
+    pmCell *outCell;                    // Output cell
+    pmFPAview *outView = pmFPAviewAlloc(0); // View into output FPA
+    *outView = *view;
+    while ((outCell = pmFPAviewNextCell(outView, outFPA, 1))) {
+
+	// skip inactive cells
+	if (!outCell->process) continue;
+
+        pmHDU *hdu = pmHDUFromCell(outCell); // HDU for cell
+        if (!hdu || hdu->blankPHU) continue;
+
+        psTrace("ppMerge", 1, "Getting bad pixels for chip %d cell %d", outView->chip, outView->cell);
+
+        assert(outCell->readouts && outCell->readouts->n == 1);
+        pmReadout *outRO = outCell->readouts->data[0]; // Output readout
+
+	if (smoothSuspect) {
+	    // XXX test output of suspect pixel image
+	    psImage *suspects = psMetadataLookupPtr(NULL, outRO->analysis, PM_MASK_ANALYSIS_SUSPECT); // Suspect img
+	    assert (suspects);
+	    psImageSmooth (suspects, smoothScale, 3); // extend smoothing region to 3-sigma
+	}
+
+	// set the bad pixels to the value 'maskVal'
+        if (!pmMaskIdentifyBadPixels(outRO, maskValOut, maskBad, maskMode)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to mask bad pixels");
+            goto MERGE_MASK_ERROR;
+        }
+
+        // Supplementary outputs
+        {
+            // The counts image is fairly useless, but it preserves the model
+            pmCell *countsCell = pmFPAfileThisCell(config->files, outView, "PPMERGE.OUTPUT.COUNT");
+            pmReadout *countsRO = pmReadoutAlloc(countsCell); // Readout with count of inputs per pixel
+            countsRO->image = psImageAlloc(outRO->mask->numCols, outRO->mask->numRows, PS_TYPE_F32);
+            psImageInit(countsRO->image, numFiles);
+            countsRO->data_exists = countsCell->data_exists = countsCell->parent->data_exists = true;
+            psFree(countsRO);
+
+            pmCell *sigmaCell = pmFPAfileThisCell(config->files, outView, "PPMERGE.OUTPUT.SIGMA");
+            pmReadout *sigmaRO = pmReadoutAlloc(sigmaCell); // Readout with suspect image
+            psImage *suspect = psMetadataLookupPtr(NULL, outRO->analysis, PM_MASK_ANALYSIS_SUSPECT);
+            sigmaRO->image = psImageCopy(sigmaRO->image, suspect, PS_TYPE_F32);
+            psMetadataRemoveKey(outRO->analysis, PM_MASK_ANALYSIS_SUSPECT);
+            sigmaRO->data_exists = sigmaCell->data_exists = sigmaCell->parent->data_exists = true;
+            psFree(sigmaRO);
+        }
+
+        if (maskGrow > 0) {
+            psImage *grown = psImageGrowMask(NULL, outRO->mask, maskValOut, maskGrow, maskValOut); // Grown mask
+            psFree(outRO->mask);
+            outRO->mask = grown;
+        }
+
+        if (writeOut) {
+            if (!pmFPAfileIOChecks(config, outView, PM_FPA_BEFORE)) {
+                psFree(outView);
+                goto MERGE_MASK_ERROR;
+            }
+
+            outRO->data_exists = outCell->data_exists = outChip->data_exists = true;
+
+            // Average concepts
+            psList *cells = psListAlloc(NULL); // List of cells, for concept averaging
+            for (int i = 0; i < numFiles; i++) {
+                pmFPAfile *inFile = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", i); // Input file
+                pmCell *inCell = pmFPAviewThisCell(outView, inFile->fpa); // Input cell
+                psListAdd(cells, PS_LIST_TAIL, inCell);
+            }
+            if (!pmConceptsAverageCells(outCell, cells, NULL, NULL, true)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to average cell concepts.");
+                psFree(cells);
+                psFree(outRO);
+                psFree(outView);
+                return false;
+            }
+            psFree(cells);
+
+            // Statistics on the merged cell using a fake image
+            outRO->image = psImageAlloc(outRO->mask->numCols, outRO->mask->numRows, PS_TYPE_F32);
+            psImageInit(outRO->image, 1.0);
+            if (!ppStatsFPA(stats, outRO->parent->parent->parent, outView, maskValOut, config)) {
+                psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to generate stats for image.");
+                psFree(outRO);
+                psFree(outView);
+                return false;
+            }
+            psFree(outRO->image);
+            outRO->image = NULL;
+
+            // Write
+            if (!pmFPAfileIOChecks(config, outView, PM_FPA_AFTER)) {
+                psFree(outView);
+                goto MERGE_MASK_ERROR;
+            }
+        }
+    }
+    psFree(outView);
+
+    ppMergeFileActivate(config, PPMERGE_FILES_ALL, true);
+
+    return true;
+
+
+MERGE_MASK_ERROR:
+    psFree(statistics);
+    psFree(values);
+    return false;
+}
+
+bool ppMergeMask(pmConfig *config)
+{
+    assert(config);
+
+    bool mdok;                          // Status of MD lookup
+    int numFiles = psMetadataLookupS32(NULL, config->arguments, "INPUTS.NUM"); // Number of inputs
+    bool haveMasks = psMetadataLookupBool(&mdok, config->arguments, "INPUTS.MASKS"); // Do we have masks?
+    bool haveWeights = psMetadataLookupBool(&mdok, config->arguments, "INPUTS.WEIGHTS"); // Do we have weights?
+    int iter = psMetadataLookupS32(NULL, config->arguments, "ITER"); // Number of rejection iterations
+
+    PS_ASSERT_INT_POSITIVE(iter, false);
+
+    pmFPAview *view = pmFPAviewAlloc(0); // View to component of interest
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0); // Random number generator
+
+    psMetadata *stats = NULL;           // Statistics for output
+    if (psMetadataLookup(config->arguments, "STATS.NAME")) {
+        stats = psMetadataAlloc();
+        psMetadataAddMetadata(config->arguments, PS_LIST_TAIL, "STATS.DATA", 0, "Statistics output", stats);
+    }
+
+    psArray *inputs = ppMergeFileDataLevel(config, "PPMERGE.INPUT", PM_FPA_LEVEL_READOUT); // Input images
+    psFree(inputs);
+    if (haveMasks) {
+        psArray *masks = ppMergeFileDataLevel(config, "PPMERGE.INPUT.MASK", PM_FPA_LEVEL_READOUT);
+        psFree(masks);
+    }
+    if (haveWeights) {
+        psArray *weights = ppMergeFileDataLevel(config, "PPMERGE.INPUT.WEIGHT", PM_FPA_LEVEL_READOUT);
+        psFree(weights);
+    }
+
+    if (!ppMergeFileActivate(config, PPMERGE_FILES_INPUT, true)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to activate files.");
+        goto PPMERGE_MASK_ERROR;
+    }
+    if (!ppMergeFileActivate(config, PPMERGE_FILES_OUTPUT, true)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to activate files.");
+        goto PPMERGE_MASK_ERROR;
+    }
+
+    // XXX this function should use pmConfigMaskReadHeader () to get the named values defined
+    // for the input masks.
+
+    psString outName = ppMergeOutputFile(config); // Name of output file
+    pmFPAfile *output = psMetadataLookupPtr(NULL, config->files, outName); // Output file
+    psFree(outName);
+    assert(output && output->fpa);
+    pmFPA *outFPA = output->fpa;        // Output FPA
+
+    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+        goto PPMERGE_MASK_ERROR;
+    }
+    pmChip *outChip;                    // Chip of interest
+    while ((outChip = pmFPAviewNextChip(view, outFPA, 1))) {
+
+        if (!outChip->process) continue;
+
+        if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+            goto PPMERGE_MASK_ERROR;
+        }
+
+        for (int i = 0; i < iter; i++) {
+            if (!mergeMask(config, view, (i == iter - 1), rng, stats)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to merge chip %d", view->chip);
+                goto PPMERGE_MASK_ERROR;
+            }
+        }
+
+	if (outChip->data_exists) {
+	    psList *inChips = psListAlloc(NULL);
+	    for (int i=0; i < numFiles; i++) {
+		pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", i); // Input file
+		pmChip *chip = pmFPAviewThisChip(view, file->fpa);
+		psListAdd(inChips, PS_LIST_TAIL, chip);
+	    }
+
+	    // XXX I need to call pmConfigMaskWriteHeader for the PHU somewhere, after it is created!
+
+	    if (!pmConceptsAverageChips(outChip, inChips, true)) {
+		psError(PS_ERR_UNKNOWN, false, "Unable to average Chip concepts.");
+		psFree(inChips);
+		goto PPMERGE_MASK_ERROR;
+	    }
+	    psFree(inChips);
+	}
+        if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+            goto PPMERGE_MASK_ERROR;
+        }
+    }
+
+    psList *fpaList = psListAlloc(NULL);// List of FPAs for concept averaging
+    for (int i = 0; i < numFiles; i++) {
+        pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", i); // Input file
+        psListAdd(fpaList, PS_LIST_TAIL, file->fpa);
+    }
+    if (!pmConceptsAverageFPAs(outFPA, fpaList)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to average FPA concepts.");
+        psFree(fpaList);
+        goto PPMERGE_MASK_ERROR;
+    }
+    psFree(fpaList);
+
+    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+        goto PPMERGE_MASK_ERROR;
+    }
+
+    psFree(stats);
+    psFree(view);
+    psFree(rng);
+
+    return true;
+
+PPMERGE_MASK_ERROR:
+    psFree(stats);
+    psFree(view);
+    psFree(rng);
+    return false;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeReadChunk.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeReadChunk.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeReadChunk.c	(revision 22158)
@@ -0,0 +1,93 @@
+# include "ppMerge.h"
+
+ppMergeFileGroup *ppMergeReadChunk (bool *status, psArray *fileGroups, pmConfig *config, int numChunk) {
+
+    *status = true;
+
+    bool mdok;
+    bool haveMasks = psMetadataLookupBool(&mdok, config->arguments, "INPUTS.MASKS"); // Do we have masks?
+    bool haveWeights = psMetadataLookupBool(&mdok, config->arguments, "INPUTS.WEIGHTS"); // Do we have weights?
+    int rows = psMetadataLookupS32(NULL, config->arguments, "ROWS"); // Number of rows to read per chunk
+
+    // select an available fileGroup
+    while (1) {
+	// check for any fileGroups which can read data
+	for (int j = 0; j < fileGroups->n; j++) {
+	    ppMergeFileGroup *fileGroup = fileGroups->data[j];
+	    if (fileGroup->read) continue;
+
+	    // find max last scan so far
+	    int lastScan = 0;
+	    for (int i = 0; i < fileGroups->n; i++) {
+		ppMergeFileGroup *fileGroup = fileGroups->data[i];
+		lastScan = PS_MAX (fileGroup->lastScan, lastScan);
+	    }
+	    fileGroup->firstScan = lastScan;
+	    fileGroup->lastScan = lastScan + rows;
+
+	    psArray *readouts = fileGroup->readouts;
+
+	    psTimerStart ("ppMergeReadChunk");
+
+	    psTrace("ppStack", 2, "Reading data for chunk %d into fileGroup %d....n", numChunk, j);
+	    for (int i = 0; i < readouts->n; i++) {
+		pmReadout *inRO = readouts->data[i]; // Input readout
+
+		// override the recorded last scan
+		inRO->thisImageScan  = fileGroup->firstScan;
+		inRO->thisWeightScan = fileGroup->firstScan;
+		inRO->thisMaskScan   = fileGroup->firstScan;
+
+		// Read a chunk from a file
+		pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT", i); 
+
+		bool keepReading = false;
+		if (pmReadoutMore(inRO, file->fits, 0, rows, config)) {
+		    keepReading = true;
+		    if (!pmReadoutReadChunk(inRO, file->fits, 0, rows, 0, config)) { 
+			psError(PS_ERR_IO, false, "Unable to read chunk %d for file PPMERGE.INPUT %d", numChunk, i);
+			*status = false;
+			return NULL;
+		    }							
+		}
+
+		if (haveMasks && pmReadoutMoreMask(inRO, file->fits, 0, rows, config)) {
+		    keepReading = true;
+		    pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT.MASK", i); 
+		    if (!pmReadoutReadChunkMask(inRO, file->fits, 0, rows, 0, config)) { 
+			psError(PS_ERR_IO, false, "Unable to read chunk %d for file PPMERGE.INPUT.MASK %d", numChunk, i);
+			*status = false;
+			return NULL;
+		    }							
+		}
+
+		if (haveWeights && pmReadoutMoreWeight(inRO, file->fits, 0, rows, config)) {
+		    keepReading = true;
+		    pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PPMERGE.INPUT.WEIGHT", i); 
+		    if (!pmReadoutReadChunkWeight(inRO, file->fits, 0, rows, 0, config)) {
+			psError(PS_ERR_IO, false, "Unable to read chunk %d for file PPMERGE.INPUT.WEIGHT %d", numChunk, i);
+			*status = false;
+			return NULL;
+		    }							
+		}
+		if (!keepReading) {
+		    return NULL;
+		}
+	    }
+
+	    fileGroup->read = fileGroup->busy = true;
+	    return fileGroup;
+	}
+
+	// check for any fileGroups which are done processing
+	bool wait = false;
+	for (int j = 0; j < fileGroups->n; j++) {
+	    ppMergeFileGroup *fileGroup = fileGroups->data[j];
+	    if (!fileGroup->read || fileGroup->busy) continue;
+	    fileGroup->read = false;
+	    wait = true;
+	}
+	if (wait) usleep (10000);
+    }
+    return NULL;
+}
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeScaleZero.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeScaleZero.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeScaleZero.c	(revision 22158)
@@ -0,0 +1,211 @@
+#include "ppMerge.h"
+
+// Get the scale and zero for each chip of each input
+bool ppMergeScaleZero(pmConfig *config)
+{
+    assert(config);
+
+    ppMergeType type = psMetadataLookupS32(NULL, config->arguments, "TYPE"); // Type of frame
+    int numInputs = psMetadataLookupS32(NULL, config->arguments, "INPUTS.NUM"); // Number of inputs
+    int numCells = psMetadataLookupS32(NULL, config->arguments, "INPUTS.CELLS"); // Number of cells
+    psStatsOptions meanStat = psMetadataLookupS32(NULL, config->arguments, "MEAN"); // Statistic for mean
+    psStatsOptions stdevStat = psMetadataLookupS32(NULL, config->arguments, "STDEV"); // Statistic for stdev
+    int shutterSize = psMetadataLookupS32(NULL, config->arguments, "SHUTTER.SIZE"); // Size of shutter region
+
+    psMaskType maskVal = pmConfigMaskGet("MASK.VALUE", config); // Value to mask
+
+    psVector *gains = NULL;             // Gains for each cell
+    psArray *shutters = NULL;           // Shutter data for each cell
+    psStats *stats = NULL;              // Statistics for background
+    psImage *background = NULL;         // Background measurements per cell per file
+
+    switch (type) {
+      case PPMERGE_TYPE_BIAS:
+      case PPMERGE_TYPE_DARK:
+        // Nothing to measure
+        return true;
+      case PPMERGE_TYPE_FLAT:
+      case PPMERGE_TYPE_FRINGE:
+        gains = psVectorAlloc(numCells, PS_TYPE_F32);
+        background = psImageAlloc(numCells, numInputs, PS_TYPE_F32);
+        psImageInit(background, NAN);
+        stats = psStatsAlloc(meanStat);
+        break;
+      case PPMERGE_TYPE_SHUTTER:
+        shutters = psArrayAlloc(numCells);
+        break;
+      case PPMERGE_TYPE_MASK:
+      default:
+        break;
+    }
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0); // Random number generator
+    pmFPAview *view = NULL;             // View into FPA
+
+    for (int i = 0; i < numInputs; i++) {
+        pmFPAfileActivate(config->files, false, NULL);
+        psArray *files = ppMergeFileActivateSingle(config, PPMERGE_FILES_INPUT, true, i); // Activated files
+        pmFPAfile *input = files->data[0]; // Representative file; should be the image (not mask or weight)
+        pmFPA *fpa = input->fpa;        // FPA of interest
+        view = pmFPAviewAlloc(0);       // View to component of interest
+        int cellNum = 0;                // Index for cell
+        if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+            goto ERROR;
+        }
+        pmChip *chip;                   // Chip of interest
+        while ((chip = pmFPAviewNextChip(view, fpa, 1))) {
+            if (!chip->file_exists) {
+                continue;
+            }
+            if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+                goto ERROR;
+            }
+
+            pmCell *cell;               // Cell of interest
+            while ((cell = pmFPAviewNextCell(view, fpa, 1))) {
+                if (!cell->file_exists) {
+                    continue;
+                }
+                if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+                    goto ERROR;
+                }
+
+                if (!cell->data_exists) {
+                    continue;
+                }
+
+                if (cell->readouts->n > 1) {
+                    psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                            "File %d chip %d cell %d contains more than one readout (%ld)",
+                            i, view->chip, view->cell, cell->readouts->n);
+                    goto ERROR;
+                }
+                pmReadout *readout = cell->readouts->data[0]; // Readout of interest
+
+                switch (type) {
+                  case PPMERGE_TYPE_FLAT:
+                  case PPMERGE_TYPE_FRINGE: {
+                      // Extract the gain
+                      float gain = psMetadataLookupF32(NULL, cell->concepts, "CELL.GAIN"); // Cell gain
+                      if (!isfinite(gain)) {
+			// psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+			// "CELL.GAIN for file %d chip %d cell %d is not set.",
+			// i, view->chip, view->cell);
+			// goto ERROR;
+			psWarning ("CELL.GAIN for file %d chip %d cell %d is NaN", i, view->chip, view->cell);
+                      }
+                      gains->data.F32[cellNum] = gain;
+
+                      // Measure the background
+                      if (!psImageBackground(stats, NULL, readout->image, readout->mask, maskVal, rng)) {
+			// psError(PS_ERR_UNKNOWN, false,
+			// "Unable to get statistics for file %d chip %d cell %d",
+			// i, view->chip, view->cell);
+			// goto ERROR;
+			psWarning ("Unable to get statistics for file %d chip %d cell %d", i, view->chip, view->cell);
+			background->data.F32[i][cellNum] = NAN;
+                      } else {
+			background->data.F32[i][cellNum] = psStatsGetValue(stats, meanStat);
+		      }
+                      break;
+                  }
+                  case PPMERGE_TYPE_SHUTTER: {
+                      pmShutterCorrectionData *shutter = shutters->data[cellNum]; // Shutter correction data
+                      if (!shutter) {
+                          shutter = pmShutterCorrectionDataAlloc(readout->image->numCols,
+                                                                 readout->image->numRows,
+                                                                 shutterSize);
+                          shutters->data[cellNum] = shutter;
+                      }
+                      if (!pmShutterCorrectionAddReadout(shutter, readout, meanStat, stdevStat,
+                                                         maskVal, rng)) {
+                          psError(PS_ERR_UNKNOWN, false,
+                                  "Can't add file %d chip %d cell %d to shutter correction.",
+                                  i, view->chip, view->cell);
+                          goto ERROR;
+                      }
+                      break;
+                  }
+                  case PPMERGE_TYPE_MASK:
+                  default:
+                    psAbort("Should never get here.");
+                }
+
+                cellNum++;
+
+                if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+                    goto ERROR;
+                }
+            }
+
+            if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+                goto ERROR;
+            }
+        }
+
+        if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+            goto ERROR;
+        }
+
+        psFree(view);
+
+#if 0
+        // Reset files for reading again
+        for (int i = 0; i < files->n; i++) {
+            pmFPAfile *file = files->data[i]; // File of interest
+        }
+#endif
+        psFree(files);
+    }
+
+    psFree(rng); rng = NULL;
+    psFree(stats); stats = NULL;
+
+    // Store results
+    switch (type) {
+      case PPMERGE_TYPE_FRINGE:
+        psMetadataAddImage(config->arguments, PS_LIST_TAIL, "ZEROS", 0,
+                           "Zero to subtract from each input cell", background);
+        // Flow through
+      case PPMERGE_TYPE_FLAT: {
+          // Need to normalize over the focal plane
+          if (psTraceGetLevel("ppMerge") > 9) {
+              for (int i = 0; i < gains->n; i++) {
+                  psTrace("ppMerge", 10, "Gain for cell %d is %f\n", i, gains->data.F32[i]);
+              }
+          }
+          psVector *fluxes = NULL;        // Solution to fluxes
+          if (!pmFlatNormalize(&fluxes, &gains, background)) {
+              psError(PS_ERR_UNKNOWN, false, "Normalisation failed to converge --- continuing anyway.");
+              psFree(fluxes);
+              goto ERROR;
+          }
+
+          psMetadataAddVector(config->arguments, PS_LIST_TAIL, "SCALES", 0,
+                              "Scale to divide into each input file", fluxes);
+          psFree(fluxes);               // Drop reference
+          break;
+      }
+      case PPMERGE_TYPE_SHUTTER:
+        psMetadataAddArray(config->arguments, PS_LIST_TAIL, "SHUTTER", 0,
+                           "Shutter data", shutters);
+        break;
+      case PPMERGE_TYPE_MASK:
+      default:
+        psAbort("Should never get here.");
+    }
+
+    psFree(background);
+    psFree(shutters);
+    return true;
+
+ERROR:
+    // Common path for errors
+    psFree(gains);
+    psFree(background);
+    psFree(shutters);
+    psFree(rng);
+    psFree(stats);
+    psFree(view);
+    return false;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeScaleZero.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeScaleZero.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeScaleZero.h	(revision 22158)
@@ -0,0 +1,19 @@
+#ifndef PP_MERGE_SCALE_ZERO_H
+#define PP_MERGE_SCALE_ZERO_H
+
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "ppMergeData.h"
+#include "ppMergeOptions.h"
+
+// Get the scale and zero for each chip of each input
+bool ppMergeScaleZero(psImage **scales, // The scales for each integration/cell
+                      psImage **zeros, // The zeroes for each integration/cell
+                      psArray **shutter,// The shutter correction data for each cell
+                      ppMergeData *data,// The data
+                      const ppMergeOptions *options, // The options
+                      const pmConfig *config // The configuration
+    );
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeSetThreads.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeSetThreads.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeSetThreads.c	(revision 22158)
@@ -0,0 +1,70 @@
+# include "ppMerge.h"
+
+// "PPMERGE_READOUT_COMBINE", 5
+bool ppMergeThread_pmReadoutCombine (psThreadJob *job) {
+
+    pmReadout *output           = job->args->data[0];
+    ppMergeFileGroup *fileGroup = job->args->data[1];
+    psVector *zero              = job->args->data[2];
+    psVector *scale             = job->args->data[3];
+    pmCombineParams *params     = job->args->data[4];
+
+    bool status = pmReadoutCombine (output, fileGroup->readouts, zero, scale, params);
+
+    // after we are done, tell the I/O system that this file group is done
+    fileGroup->busy = false; 
+    return status;
+}
+
+bool ppMergeThread_pmDarkCombine (psThreadJob *job) {
+
+    pmCell *outCell             = job->args->data[0];
+    ppMergeFileGroup *fileGroup = job->args->data[1];
+    psArray *darkOrdinates      = job->args->data[2];
+    psString darkNorm           = job->args->data[3];
+    psScalar *iter     	        = job->args->data[4];
+    psScalar *rej     	        = job->args->data[5];
+    psScalar *maskVal     	= job->args->data[6];
+
+    bool status = pmDarkCombine(outCell, fileGroup->readouts, darkOrdinates, darkNorm, iter->data.S32, rej->data.F32, maskVal->data.U8);
+
+    // after we are done, tell the I/O system that this file group is done
+    fileGroup->busy = false;
+    return status;
+}
+
+bool ppMergeThread_pmShuttderCorrectionGenerate (psThreadJob *job) {
+
+    pmReadout *output             = job->args->data[0];
+    ppMergeFileGroup *fileGroup   = job->args->data[1];
+    psScalar *shutterRef          = job->args->data[2];
+    pmShutterCorrectionData *data = job->args->data[3];
+    psScalar *iter     	          = job->args->data[4];
+    psScalar *rej     	          = job->args->data[5];
+    psScalar *maskVal     	  = job->args->data[6];
+
+    bool status = pmShutterCorrectionGenerate(output, NULL, fileGroup->readouts, shutterRef->data.F32, data, iter->data.S32, rej->data.F32, maskVal->data.U8);
+
+    // after we are done, tell the I/O system that this file group is done
+    fileGroup->busy = false;
+    return status;
+}
+
+bool ppMergeSetThreads () {
+
+    psThreadTask *task = NULL;
+
+    task = psThreadTaskAlloc ("PPMERGE_READOUT_COMBINE", 5);
+    task->function = &ppMergeThread_pmReadoutCombine;
+    psThreadTaskAdd (task);
+
+    task = psThreadTaskAlloc ("PPMERGE_DARK_COMBINE", 7);
+    task->function = &ppMergeThread_pmReadoutCombine;
+    psThreadTaskAdd (task);
+
+    task = psThreadTaskAlloc ("PPMERGE_SHUTTER_CORRECTION", 7);
+    task->function = &ppMergeThread_pmReadoutCombine;
+    psThreadTaskAdd (task);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeThreadLauncher.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeThreadLauncher.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeThreadLauncher.c	(revision 22158)
@@ -0,0 +1,94 @@
+# include "ppMerge.h"
+
+// each thread runs this function, starting a new job when it finished with an old one
+// it is called with a (void *) pointer to its own thread pointer
+void *ppMergeThreadLauncher (void *data) {
+
+    psThread *self = data;
+    psThreadJob *job = NULL;
+
+    while (1) {
+
+	// if we get an error, just wait until we are cleared or killed
+	while (self->fault) {
+	    usleep (10000);
+	}
+
+	// request a new job, if there are none available, sleep a bit
+	// we have to lock here so the job queue cannot be empty yet no threads busy
+	psThreadLock();
+	while ((job = psThreadJobGetPending ()) == NULL) {
+	    psThreadUnlock();
+	    usleep (10000);
+	}
+	self->busy = true;
+	psThreadUnlock();
+
+	// list all allowed job types here
+
+	// pmReadoutCombine
+	if (!strcmp (job->type, "PPMERGE_READOUT_COMBINE")) {
+	    psAssert (job->args->n == 5, "invalid number of arguments to pmReadoutCombine");
+
+	    pmReadout *output           = job->args->data[0];
+	    ppMergeFileGroup *fileGroup = job->args->data[1];
+	    psVector *zero              = job->args->data[2];
+	    psVector *scale             = job->args->data[3];
+	    pmCombineParams *params     = job->args->data[4];
+
+	    bool status = pmReadoutCombine (output, fileGroup->readouts, zero, scale, params);
+	    if (!status) {
+		self->fault = true;
+	    }
+
+	    // we do not have to lock here because this transition is not tied to the job queue
+	    fileGroup->busy = false;
+	    self->busy = false;  
+	    continue;
+	}
+
+	// pmDarkCombine
+	if (!strcmp (job->type, "PPMERGE_DARK_COMBINE")) {
+	    psAssert (job->args->n == 7, "invalid number of arguments to pmDarkCombine");
+
+	    pmCell *outCell             = job->args->data[0];
+	    ppMergeFileGroup *fileGroup = job->args->data[1];
+	    psArray *darkOrdinates      = job->args->data[2];
+	    psString darkNorm           = job->args->data[3];
+	    psScalar *iter     	        = job->args->data[4];
+	    psScalar *rej     	        = job->args->data[5];
+	    psScalar *maskVal     	= job->args->data[6];
+
+	    bool status = pmDarkCombine(outCell, fileGroup->readouts, darkOrdinates, darkNorm, iter->data.S32, rej->data.F32, maskVal->data.U8);
+	    if (!status) {
+		self->fault = true;
+	    }
+	    // we do not have to lock here because this transition is not tied to the job queue
+	    fileGroup->busy = false;
+	    self->busy = false;  
+	    continue;
+	}
+
+	// pmShutterCorrectionGenerate
+	if (!strcmp (job->type, "PPMERGE_SHUTTER_CORRECTION")) {
+	    psAssert (job->args->n == 7, "invalid number of arguments to pmDarkCombine");
+
+	    pmReadout *output             = job->args->data[0];
+	    ppMergeFileGroup *fileGroup   = job->args->data[1];
+	    psScalar *shutterRef          = job->args->data[2];
+	    pmShutterCorrectionData *data = job->args->data[3];
+	    psScalar *iter     	          = job->args->data[4];
+	    psScalar *rej     	          = job->args->data[5];
+	    psScalar *maskVal     	  = job->args->data[6];
+
+	    bool status = pmShutterCorrectionGenerate(output, NULL, fileGroup->readouts, shutterRef->data.F32, data, iter->data.S32, rej->data.F32, maskVal->data.U8);
+	    if (!status) {
+		self->fault = true;
+	    }
+	    // we do not have to lock here because this transition is not tied to the job queue
+	    fileGroup->busy = false;
+	    self->busy = false;  
+	    continue;
+	}
+    }  
+}
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeVersion.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeVersion.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeVersion.c	(revision 22158)
@@ -0,0 +1,60 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include <ppStats.h>
+
+#include "ppMergeVersion.h"
+
+static const char *cvsTag = "$Name: not supported by cvs2svn $";// CVS tag name
+
+psString ppMergeVersion(void)
+{
+    psString version = NULL;            // Version, to return
+    psStringAppend(&version, "%s-%s",PACKAGE_NAME,PACKAGE_VERSION);
+    return version;
+}
+
+psString ppMergeVersionLong(void)
+{
+    psString version = ppMergeVersion(); // Version, to return
+    psString tag = psStringStripCVS(cvsTag, "Name"); // CVS tag
+    psStringAppend(&version, " (cvs tag %s) %s, %s", tag, __DATE__, __TIME__);
+    psFree(tag);
+    return version;
+}
+
+
+void ppMergeVersionMetadata(psMetadata *metadata)
+{
+    PS_ASSERT_METADATA_NON_NULL(metadata,);
+
+    psString pslib = psLibVersionLong();// psLib version
+    psString psmodules = psModulesVersionLong(); // psModules version
+    psString ppStats = ppStatsVersionLong(); // ppStats version
+    psString ppMerge = ppMergeVersionLong(); // ppMerge version
+
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psString head = NULL;               // Head string
+    psStringAppend(&head, "ppMerge processing at %s. Component information:", timeString);
+    psFree(timeString);
+
+    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, head, "");
+    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, pslib, "");
+    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, psmodules, "");
+    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, ppStats, "");
+    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, ppMerge, "");
+
+    psFree(head);
+    psFree(pslib);
+    psFree(psmodules);
+    psFree(ppStats);
+    psFree(ppMerge);
+
+    return;
+}
Index: /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeVersion.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeVersion.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/ppMerge/src/ppMergeVersion.h	(revision 22158)
@@ -0,0 +1,14 @@
+#ifndef PP_MERGE_VERSION_H
+#define PP_MERGE_VERSION_H
+
+/// Return short version information
+psString ppMergeVersion(void);
+
+/// Return long version information
+psString ppMergeVersionLong(void);
+
+/// Update the metadata with version information for all dependencies
+void ppMergeVersionMetadata(psMetadata *metadata ///< Metadata to update with version information
+    );
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/.cvsignore	(revision 22158)
@@ -0,0 +1,35 @@
+DoxygenLog
+Doxyfile
+ChangeLog
+bin
+lib
+include
+man
+include
+pslib.kdevelop.*
+docs
+Makefile.in
+aclocal.m4
+autom4te.cache
+configure
+Makefile
+config.log
+config.status
+libtool
+pslib-config
+pslib.pc
+pslib-*.tar.gz
+pslib-*.tar.bz2
+compile
+config.guess
+config.sub
+depcomp
+install-sh
+ltmain.sh
+missing
+pslib.kdevses
+.deps
+.libs
+*.bb
+*.bbg
+*.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/AUTHORS
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/AUTHORS	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/AUTHORS	(revision 22158)
@@ -0,0 +1,1 @@
+Copyright 2004 Maui High Performance Computing Center, University of Hawaii
Index: /branches/eam_branches/eam_branch_20080719/psLib/COPYING
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/COPYING	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/COPYING	(revision 22158)
@@ -0,0 +1,345 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    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
+
+
+	    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) <year>  <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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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) year 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: /branches/eam_branches/eam_branch_20080719/psLib/DEV_NOTES
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/DEV_NOTES	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/DEV_NOTES	(revision 22158)
@@ -0,0 +1,175 @@
+---- Developing in the autotools environment for non-autotools developers. ----
+
+
+There are many detailed resources on the web about the autotools (autoconf,
+automake, libtools).  Being GNU tools, the primary resources are found there
+at:
+  o  http://www.gnu.org/software/autoconf/manual/autoconf-2.57/autoconf.html
+  o  http://www.gnu.org/software/automake/manual/automake.html
+  o  http://www.gnu.org/software/libtool/manual.html
+
+This document will deal with only the basic required tasks for developing in
+the autotools environment, namely:
+  o  Creating the configuration environment from CVS check-out,
+  o  Configuring the library,
+  o  Making the library,
+  o  Adding and removing a source code file, and
+  o  Adding and removing a test code file.
+
+
+Creating the configuration environment from CVS check-out
+===============================================================================
+
+The autotools as a group help you create software distributions which will
+build reliably on a large variety of platforms.  The minimum required contact
+with the autotools is to generate the files which will let you configure a
+freshly checked-out directory before working on it, since these configuration
+files are not checked in to the repository. The Makefile.cvs makefile will do
+this for you, but it can only do this if the autotools are installed (which is
+commonly included into every Linux Distribution as well as Mac OSX).
+
+The command sequence example for this step is as follows:
+  > cvs co psLib
+  > cd psLib
+  > make -f Makefile.cvs
+
+Configuring the library
+===============================================================================
+
+Running the configure script is basically very simple: ./configure.  There are,
+however, options and arguments which can help you, or catch you out.  You can
+see the full list of options with the command ./configure --help.
+
+You set the place where the configured component will be installed with the
+--prefix option. This names a directory which will end up with the standard
+directories bin, lib and so on.  The default is `pwd` currently, but that may
+change to something like $HOME in the future.
+
+The psLib autoconf adds a couple of extra options to ./configure that may be
+of interest to a developer.
+
+--enable-perlmodule
+  enables the building of the perl module using SWIG.  The default is to not
+  build the perl modules
+
+--enable-optimize
+  by default, the build disables compiler optimization for C files to speed up
+  the compile time.  By adding this, '-O2' is added to CFLAGS.
+
+--enable-static
+  by default, only a shared, dynamically-linked, library is built.  This option
+  enables the creation of a static library at the cost of doubling the compiling
+  time.  To create only a static library, include the --disable-shared option
+  as well.
+
+--with-cfitsio=DIR
+  specifies the location of the CFITSIO installation prefix, e.g., /usr/local.
+  To specify the include and/or library directories directly, use the options
+  --with-cfitsio-include=DIR and --with-cfitsio-lib=DIR respectively.  If not
+  specified, CFITSIO is assumed to have been installed in the standard paths
+  for the OS, e.g., /usr or /usr/local.
+
+--with-fftw3=DIR
+  specifies the location of the FFTW3 installation prefix, e.g., /usr/local.
+  To specify the include and/or library directories directly, use the options
+  --with-fftw3-include=DIR and --with-fftw3-lib=DIR respectively.  If not
+  specified, FFTW3 is assumed to have been installed in the standard paths
+  for the OS, e.g., /usr or /usr/local.
+
+--with-gsl-config=FILE
+  specifies the gsl-config script to use to gather the GSL library information.
+  This is the full path to the gsl-config script included in the package's
+  installation, e.g., /usr/local/bin/gsl-config.  If not specified, $PATH is
+  used to find the script.
+
+--with-xml2-config=FILE
+  specifies the xml2-config script to use to gather the XML2 library
+  information.  This is the full path to the xml2-config script included in
+  the package's installation, e.g., /usr/local/bin/xml2-config.  If not
+  specified, $PATH is used to find the script.
+
+--with-swig=FILE
+  specifies the swig executable to use to generate the SWIG wrapper code.
+  This is the full path to the swig executable, e.g., /usr/bin/swig.  If not
+  specified, $PATH is used to find the executable.
+
+--with-perl=FILE
+  specifies the perl executable to use to generate the SWIG wrapper code.
+  This is the full path to the perl executable, e.g., /usr/bin/perl.  If not
+  specified, $PATH is used to find the executable.
+
+--with-perlprefix=DIR
+  specifies the installation prefix for the perl module.  If not
+  specified, the PREFIX as specified by the --prefix option (or its default)
+  is used.
+
+
+The command sequence example for this step, using all default settings, is as
+follows:  
+  > ./configure
+
+  
+Adding and removing a source code file
+===============================================================================
+
+The library is built from a number of smaller, 'convienence' libraries, one
+convienence library for each subdirectory off of src.  To add a file to the
+pslib library, you need to add it to one of convienence libraries in the
+appropriate subdirectory
+
+To add functionality, you need to add the filenames to the Makefile.am in the
+subdirectory in which the file is being added.
+  o  The source filename needs to added to the libpslibSUBDIR_la_SOURCES
+     variable, where SUBDIR is the subdirectory name.
+  o  Any header files needed to be installed (which is generally going to be
+     all header files) should be added to the pslibinclude_HEADERS variable.
+  o  Any other file needed to be included in the distribution tarball but are
+     not to be installed should be included in the EXTRA_DIST variable.
+
+Upon saving Makefile.am, the existing Makefile will detect the change and
+automagically perform any executation of automake/autoconf, so a simple
+'make' should fold in these changes for you.
+
+
+Adding and removing a test code file
+===============================================================================
+
+Tests are added into a subdirectory of the test directory which corresponds to
+the functionality location under src being tested.  For example, if testing
+functionality found in src/astronomy/psFoo.c, you will need to add the
+corresponding tests in test/astronomy/tst_psFoo.c.  If the test driver code
+file does not current exist, use test/tst_template.c as a template on how to
+utilize the psLib test facilities.
+
+To add a test, you need to add the filenames to the Makefile.am in the
+subdirectory in which the file is being added.
+  o  The source filename minux the .c suffix needs to added to the
+     TESTS and variable.  This specifies the executable target name.
+  o  Using the name you added to TESTS, create a line of the form
+        tst_psFoo_SOURCES = tst_psFoo.c
+     This specifies the source files needed to create the test driver
+     executable (in the psLib test suite, this is generally just one file).
+  o  Any test data file needs to be added to the check_DATA variable and
+     a rule needs to be created that will copy the file from the source
+     directory to the build directory.  This is because the directory in
+     which your data file exists is not necessarily where the test executable
+     is built.  The simpliest way to do this is to place the data file in
+     a subdirectory like 'verified' and create a rule like:
+        fBiOut.fits: verified/fBiOut.fits
+                cp $? $@
+     Automake will determine that the target directory of the cp should be
+     the build directory, so the file will be copied to the same directory
+     as your executable (so that in the code, you can assume the path is '.')
+     
+
+Upon saving Makefile.am, the existing Makefile will detect the change and
+automagically perform any executation of automake/autoconf, so a simple
+'make' should fold in these changes for you.
+
+-------------------------------------------------------------------------------
+N.B. this file is not to be included in distribution packages.
+
+Gotchas
+===============================================================================
+
+libtap uses asprintf() which is non-portable
Index: /branches/eam_branches/eam_branch_20080719/psLib/Doxyfile.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/Doxyfile.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/Doxyfile.in	(revision 22158)
@@ -0,0 +1,1080 @@
+# Doxyfile 1.3.4
+
+# 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         = @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
+
+# 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, 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
+
+# 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    = YES
+
+# 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. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_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
+# explict @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = YES
+
+# 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         = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# reimplements.
+
+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
+
+# 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  = YES
+
+# 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            = NO
+
+#---------------------------------------------------------------------------
+# 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            = YES
+
+# 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  = 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
+# 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
+
+# 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
+
+#---------------------------------------------------------------------------
+# 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
+
+# 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.
+
+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           = DoxygenLog
+
+#---------------------------------------------------------------------------
+# 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
+
+FILE_PATTERNS          = *.h *.dox
+
+# 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       = *_wrap.c
+
+# 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.
+
+INPUT_FILTER           =
+
+# 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.
+
+SOURCE_BROWSER         = YES
+
+# 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    = NO
+
+# 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     = YES
+
+# 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
+
+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 dir.
+
+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             = YES
+
+# 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   = 10
+
+# 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          = YES
+
+# 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             = letter
+
+# 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         = times
+
+# 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         = YES
+
+# 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           = YES
+
+# 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 optimised 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 assigments. 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              = YES
+
+#---------------------------------------------------------------------------
+# 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. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+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                =
+
+#---------------------------------------------------------------------------
+# 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.
+
+PREDEFINED             = DOXYGEN
+
+# 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::addtions 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 superceded 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               = YES
+
+# 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 UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similiar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK               = YES
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = YES
+
+# 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
+
+# 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 on 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
+
+# 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::addtions 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: /branches/eam_branches/eam_branch_20080719/psLib/INSTALL
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/INSTALL	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/INSTALL	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/Makefile.am	(revision 22158)
@@ -0,0 +1,30 @@
+SUBDIRS = m4 $(SUBDIR)
+
+bin_SCRIPTS = pslib-config 
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA= pslib.pc
+
+EXTRA_DIST = \
+    Doxyfile.in \
+    pslib-config.in \
+    pslib.pc.in \
+    autogen.sh
+
+if HAVE_DOXYGEN
+install-data-hook: doxygen
+	-$(mkdir_p) $(mandir)/man3
+	chmod 0755 $(mandir)/man3
+	-cp $(top_builddir)/docs/man/man3/* $(mandir)/man3
+
+doxygen:
+	$(DOXYGEN)
+endif
+
+CLEANFILES = *~ *.bb *.bbg *.da DoxygenLog
+
+clean-local:
+	-rm -rf docs
+
+test: check
+
+ACLOCAL_AMFLAGS = -I m4
Index: /branches/eam_branches/eam_branch_20080719/psLib/README
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/README	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/README	(revision 22158)
@@ -0,0 +1,47 @@
+Pan-STARRS Image Processing Pipeline Library
+============================================
+
+The is psLib, the Pan-STARRS Image Processing Pipeline Library, a base
+collection of functions for the Pan-STARRS PS1 observatory.
+
+It was developed by the Maui High Performance Computing Center
+(http://www.mhpcc.edu) for the University of Hawai'i Institute for Astronomy
+(http://ifa.hawaii.edu).
+
+psLib is free software, you can redistribute it and/or modify it under
+the terms of the GNU General Public License.
+
+The GNU General Public License does not permit this software to be
+redistributed in proprietary programs.
+
+This library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+Availability
+============
+
+The current version of psLib is always available from
+http://mhpcc.pan-starrs.org/code.
+
+Installation
+============
+
+psLib follows the standard GNU installation procedure.  Please consult
+the INSTALL file in this distribution for more detailed instructions.
+
+For information about specific platforms and compilers see the
+"Compilation Notes" section in the INSTALL file.
+
+More information about Pan-STARRS
+=================================
+
+The project homepage is http://www.pan-starrs.org.
+
+Reporting Bugs
+==============
+
+If you find a bug, please report it via the project's Bugzilla webpage at
+http://www.pan-starrs.org/bugzilla or email robert.desonia@mhpcc.hpc.mil.
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/autogen.sh
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/autogen.sh	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/autogen.sh	(revision 22158)
@@ -0,0 +1,113 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+PROJECT=pslib
+TEST_TYPE=-f
+FILE=pslib.pc.in
+
+DIE=0
+
+if [ "`which glibtoolize 2> /dev/null`" != "" ]
+ then LIBTOOLIZE=glibtoolize
+ else LIBTOOLIZE=libtoolize
+fi
+
+ACLOCAL="aclocal $ACLOCAL_FLAGS"
+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 -I m4 || echo "$ACLOCAL failed"
+$AUTOHEADER || echo "$AUTOHEADER failed"
+$AUTOMAKE --add-missing --force-missing --copy || echo "$AUTOMAKE failed"
+$AUTOCONF || echo "$AUTOCONF failed"
+
+# bypass taps bootstrap.sh
+cd ./test/tap
+$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: /branches/eam_branches/eam_branch_20080719/psLib/configure.ac
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/configure.ac	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/configure.ac	(revision 22158)
@@ -0,0 +1,472 @@
+AC_PREREQ(2.61)
+
+AC_INIT([pslib],[1.1.1],[http://pan-starrs.ifa.hawaii.edu/bugzilla])
+AC_CONFIG_SRCDIR([pslib.pc.in])
+AC_CANONICAL_TARGET
+
+dnl this enables the building of libtap
+AC_CONFIG_SUBDIRS([test/tap])
+
+AM_INIT_AUTOMAKE([1.7 foreign dist-bzip2])
+AC_CONFIG_HEADERS([src/config.h])
+AM_MAINTAINER_MODE
+
+dnl So, libtool library versions are described by three integers:
+dnl 
+dnl current
+dnl     The most recent interface number that this library implements.
+dnl revision
+dnl     The implementation number of the current interface.
+dnl age
+dnl     The difference between the newest and oldest interfaces that this
+dnl library implements. In other words, the library implements all the
+dnl interface numbers in the range from number current - age to current
+
+PSLIB_LT_VERSION="1:1:0"
+AC_SUBST(PSLIB_LT_VERSION,$PSLIB_LT_VERSION)
+
+IPP_STDCFLAGS
+
+dnl ------------------- PERL options ---------------------
+  AC_ARG_WITH(perl,
+    [AS_HELP_STRING(--with-perl=FILE,Specify location of PERL executable.)],
+    [AC_CHECK_PROG(PERL, $withval, $withval)],
+    [AC_CHECK_PROG(PERL, perl, `which perl`)])
+    if test "$PERL" == ""
+    then
+      AC_MSG_ERROR([PERL is required.  Use --with-perl to specify its install location.])
+    fi
+    AC_SUBST(PERL,$PERL)
+
+SUBDIR="etc src share test utils" dnl don't include 'swig', as it is optional
+
+SRCPATH='${top_srcdir}/src'
+SRCDIRS="sys astro db fft fits imageops jpeg math mathtypes types"   dnl xml
+# escape two escapes at this level so \\ gets passed to the shell and \ to perl
+SRCINC=`echo "${SRCDIRS=}" | ${PERL} -pe "s|(\w+)|-I\\\\${SRCPATH=}/\1|g"`
+SRCINC="-I${SRCPATH=} ${SRCINC=}"
+SRCSUBLIBS=`echo "${SRCDIRS=}" | ${PERL} -pe "s|(\w+)|\1/libpslib\1.la|g"`
+AC_SUBST(SRCSUBLIBS,${SRCSUBLIBS=})
+AC_SUBST(SRCINC,${SRCINC=})
+AC_SUBST(ABS_SRCDIR,`pwd`) dnl assuming configure is run in top directory -- is there something better?
+AC_PROG_MAKE_SET
+
+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)
+
+dnl turn on mem leak backtracing 
+AC_ARG_ENABLE(backtrace,
+  [AS_HELP_STRING(--enable-backtrace, enable memory allocation backtracing)],
+  [AC_MSG_RESULT(memory allocation backtracing enabled)
+    AC_DEFINE([PS_MEM_BACKTRACE], 1, [Define to 1 if you want memory backtracing])
+    CFLAGS="${CFLAGS=} -rdynamic"
+  ]
+)
+AC_CHECK_FUNCS([backtrace])
+
+AC_LANG(C)
+AC_PROG_CC_C99
+dnl _GNU_SOURCE is needed for atleast strcasestr() with glibc
+AC_GNU_SOURCE
+AC_C_INLINE
+
+dnl enable largefile supports
+AC_SYS_LARGEFILE
+AC_FUNC_FSEEKO
+
+AC_PROG_INSTALL
+AC_PROG_LIBTOOL
+
+dnl check the systems endianness
+AC_C_BIGENDIAN
+
+AC_PREFIX_DEFAULT([/usr/local])
+test "$prefix" = NONE && prefix=/usr/local
+
+dnl ----------------- pthread support --------------------
+
+dnl Check for how to link against pthreads
+dnl RHEL 4.0 was upset about the first arg to ACX_PTHREAD being NULL ([]) so
+dnl we've added in a worthless message to keep it happy
+dnl PTHREAD_CFLAGS /must/ also be used in the linking of an exe.  Without
+dnl adding PTHREAD_CFLAGS into PSLIB_LIBS we can't link exes on Linux.
+dnl Basically this means the entire method of only linking psLib's deps in the
+dnl final exe or library is flawed.
+
+ACX_PTHREAD(
+  [PSLIB_CFLAGS="${PSLIB_CFLAGS=} ${PTHREAD_CFLAGS}"
+    PSLIB_LIBS="${PSLIB_LIBS=} ${PTHREAD_CFLAGS} ${PTHREAD_LIBS}"],
+  [AC_MSG_ERROR([pthread support is required to build psLib])]
+)
+
+dnl ----------------- MYSQL options --------------------
+
+AX_LIB_MYSQL([4.1.2],
+  [PSLIB_CFLAGS="${PSLIB_CFLAGS=} ${MYSQL_CFLAGS} -DHAVE_PSDB"
+    PSLIB_LIBS="${PSLIB_LIBS=} ${MYSQL_LDFLAGS}"],
+  [PSLIB_CFLAGS="${PSLIB_CFLAGS=}"]
+)
+
+dnl ----------------- CFITSIO options --------------------
+
+dnl save LIBS/CFLAGS/LDFLAGS
+TMP_LIBS=${LIBS}
+TMP_CFLAGS=${CFLAGS}
+TMP_LDFLAGS=${LDFLAGS}
+TMP_CPPFLAGS=${CPPFLAGS}
+
+AC_ARG_WITH(cfitsio,
+[AS_HELP_STRING(--with-cfitsio=DIR,Specify location of CFITSIO.)],
+[CFITSIO_CFLAGS="-I$withval/include"
+ CFITSIO_LDFLAGS="-L$withval/lib"])
+AC_ARG_WITH(cfitsio-include,
+[AS_HELP_STRING(--with-cfitsio-include=DIR,Specify CFITSIO include directory.)],
+[CFITSIO_CFLAGS="-I$withval"])
+AC_ARG_WITH(cfitsio-lib,
+[AS_HELP_STRING(--with-cfitsio-lib=DIR,Specify CFITSIO library directory.)],
+[CFITSIO_LDFLAGS="-L$withval"])
+PSLIB_CFLAGS="${PSLIB_CFLAGS=} ${CFITSIO_CFLAGS}"
+PSLIB_LIBS="${PSLIB_LIBS=} $CFITSIO_LDFLAGS -lcfitsio -lm"
+
+CFLAGS="${CFLAGS=} ${CFITSIO_CFLAGS}"
+LDFLAGS="${LDFLAGS=} ${CFITSIO_LDFLAGS}"
+
+dnl Solaris needs to suck in these symbols from unusual locations
+AC_SEARCH_LIBS([gethostbyname], [nsl])
+AC_SEARCH_LIBS([socket], [socket])
+
+AC_CHECK_HEADERS([fitsio.h],[],
+   [AC_MSG_ERROR([CFITSIO headers not found.  Obtain CFITSIO at  http://heasarc.gsfc.nasa.gov/docs/software/fitsio or use --with-cfitsio to specify location.])]
+)
+TMP_LIBS=${LIBS}
+AC_CHECK_LIB(cfitsio,ffopen,[],
+  [AC_MSG_ERROR([CFITSIO library not found.  Obtain it at  http://heasarc.gsfc.nasa.gov/docs/software/fitsio or use --with-cfitsio to specify location.])],[-lm]
+)
+dnl Now check if CFITSIO supports fits_open_diskfile, i.e., is at least version 2.501
+AC_CHECK_LIB(cfitsio,ffdkopn,
+  [CFITSIO_DISKFILE=1],
+  [AC_MSG_WARN([The CFITSIO library version is rather old.  Suggested version is 2.501 or greater.])
+   CFITSIO_DISKFILE=0],[-lm]
+)
+
+AC_DEFINE_UNQUOTED([CFITSIO_DISKFILE],${CFITSIO_DISKFILE},[Define to 1 if you have fits_open_diskfile in CFITSIO])
+AC_SUBST([CFITSIO_CFLAGS])
+
+dnl restore the LIBS/CFLAGS/LDFLAGS
+LIBS=${TMP_LIBS}
+CFLAGS=${TMP_CFLAGS}
+LDFLAGS=${TMP_LDFLAGS}
+CPPFLAGS=${TMP_CPPFLAGS}
+
+dnl ------------------ FFTW3 options ---------------------
+
+dnl save LIBS/CFLAGS/LDFLAGS
+TMP_LIBS=${LIBS}
+TMP_CFLAGS=${CFLAGS}
+TMP_LDFLAGS=${LDFLAGS}
+TMP_CPPFLAGS=${CPPFLAGS}
+
+AC_ARG_WITH(fftw3,
+[AS_HELP_STRING(--with-fftw3=DIR,Specify location of FFTW version 3.)],
+[FFTW3_CFLAGS="-I$withval/include"
+ FFTW3_LDFLAGS="-L$withval/lib"])
+AC_ARG_WITH(fftw3-include,
+[AS_HELP_STRING(--with-fftw3-include=DIR,Specify FFTW version 3 include directory.)],
+[FFTW3_CFLAGS="-I$withval"])
+AC_ARG_WITH(fftw3-lib,
+[AS_HELP_STRING(--with-fftw3-lib=DIR,Specify FFTW version 3 library directory.)],
+[FFTW3_LDFLAGS="-L$withval"])
+PSLIB_CFLAGS="${PSLIB_CFLAGS=} ${FFTW3_CFLAGS}"
+PSLIB_LIBS="${PSLIB_LIBS=} $FFTW3_LDFLAGS -lfftw3f"
+
+CFLAGS="${CFLAGS} ${FFTW3_CFLAGS}"
+CPPFLAGS=${CFLAGS}
+LDFLAGS="${LDFLAGS} ${FFTW3_LDFLAGS}"
+
+AC_CHECK_HEADERS([fftw3.h],[],
+  [AC_MSG_ERROR([FFTW version 3 (--enable-float) headers not found.  Obtain it at http://www.fftw.org/ or use --with-fftw3 to specify location.])]
+)
+AC_CHECK_LIB(fftw3f,fftwf_plan_dft_2d,[],
+  [AC_MSG_ERROR([FFTW version 3 (--enable-float) library not found.  Obtain it at http://www.fftw.org/ or use --with-fftw3 to specify location.])],[-lm]
+)
+
+AC_SUBST([FFTW3_CFLAGS])
+
+dnl restore the CFLAGS/LDFLAGS
+LIBS=${TMP_LIBS}
+CFLAGS=${TMP_CFLAGS}
+LDFLAGS=${TMP_LDFLAGS}
+CPPFLAGS=${TMP_CPPFLAGS}
+
+dnl -------------------- GSL options ---------------------
+
+dnl save LIBS/CFLAGS/LDFLAGS
+TMP_LIBS=${LIBS}
+TMP_CFLAGS=${CFLAGS}
+TMP_LDFLAGS=${LDFLAGS}
+TMP_CPPFLAGS=${CPPFLAGS}
+
+AC_ARG_WITH(gsl-config,
+[AS_HELP_STRING(--with-gsl-config=FILE,Specify location of gsl-config.)],
+[GSL_CONFIG=$withval],
+[GSL_CONFIG=`which gsl-config`])
+AC_CHECK_FILE($GSL_CONFIG,[],
+    [AC_MSG_ERROR([GSL is required.  Obtain it at http://www.gnu.org/software/gsl or use --with-gsl-config to specify location.])])
+
+AC_MSG_CHECKING([GSL cflags])
+GSL_CFLAGS="`${GSL_CONFIG} --cflags`"
+AC_MSG_RESULT([${GSL_CFLAGS}])
+
+AC_MSG_CHECKING([GSL ldflags])
+GSL_LDFLAGS="`${GSL_CONFIG} --libs`"
+AC_MSG_RESULT([${GSL_LDFLAGS}])
+
+PSLIB_CFLAGS="${PSLIB_CFLAGS=} ${GSL_CFLAGS}"
+PSLIB_LIBS="${PSLIB_LIBS=} ${GSL_LDFLAGS}"
+
+AC_SUBST([GSL_CFLAGS])
+
+dnl restore the CFLAGS/LDFLAGS
+LIBS=${TMP_LIBS}
+CFLAGS=${TMP_CFLAGS}
+LDFLAGS=${TMP_LDFLAGS}
+CPPFLAGS=${TMP_CPPFLAGS}
+
+dnl ------------------ libjpeg options ---------------------
+
+dnl save LIBS/CFLAGS/LDFLAGS
+TMP_LIBS=${LIBS}
+TMP_CFLAGS=${CFLAGS}
+TMP_LDFLAGS=${LDFLAGS}
+TMP_CPPFLAGS=${CPPFLAGS}
+
+AC_ARG_WITH(jpeg,
+[AS_HELP_STRING(--with-jpeg=DIR,Specify location of libjpeg.)],
+[JPEG_CFLAGS="-I$withval/include"
+ JPEG_LDFLAGS="-L$withval/lib"])
+AC_ARG_WITH(jpeg-include,
+[AS_HELP_STRING(--with-jpeg-include=DIR,Specify libjpeg include directory.)],
+[JPEG_CFLAGS="-I$withval"])
+AC_ARG_WITH(jpeg-lib,
+[AS_HELP_STRING(--with-jpeg-lib=DIR,Specify libjpeg library directory.)],
+[JPEG_LDFLAGS="-L$withval"])
+
+CFLAGS="${CFLAGS} ${JPEG_CFLAGS}"
+CPPFLAGS=${CFLAGS}
+LDFLAGS="${LDFLAGS} ${JPEG_LDFLAGS}"
+
+AC_CHECK_HEADERS([jpeglib.h],[PSLIB_CFLAGS="$PSLIB_CFLAGS $JPEG_CFLAGS"
+			      AC_SUBST(JPEG_CFLAGS)],
+  [AC_MSG_ERROR([libjpeg headers not found.  Obtain libjpeg from http://www.ijg.org/ or use --with-jpeg to specify location.])]
+)
+
+AC_CHECK_LIB(jpeg,jpeg_CreateCompress,[PSLIB_LIBS="$PSLIB_LIBS $JPEG_LDFLAGS -ljpeg"],
+  [AC_MSG_ERROR([libjpeg library not found.  Obtain libjpeg from http://www.ijg.org/ or use --with-jpeg to specify location.])]
+)
+
+dnl restore the CFLAGS/LDFLAGS
+LIBS=${TMP_LIBS}
+CFLAGS=${TMP_CFLAGS}
+LDFLAGS=${TMP_LDFLAGS}
+CPPFLAGS=${TMP_CPPFLAGS}
+
+dnl ------------------- XML2 options ---------------------
+dnl AC_ARG_WITH(xml2-config,
+dnl [AS_HELP_STRING(--with-xml2-config=FILE,Specify location of xml2-config.)],
+dnl [XML_CONFIG=$withval],
+dnl [XML_CONFIG=`which xml2-config`])
+dnl AC_CHECK_FILE($XML_CONFIG,[],
+dnl     [AC_MSG_ERROR([GNOME XML C parser is required.  Obtain it at http://www.xmlsoft.org or use --with-xml2-config to specify location.])])
+dnl
+dnl AC_MSG_CHECKING([xml2 version])
+dnl XML_VERSION=`xml2-config --version`
+dnl XML_VERSION_major=`echo $XML_VERSION | ${PERL} -pe 's|^(\d+).*|\1|'`
+dnl XML_VERSION_minor=`echo $XML_VERSION | ${PERL} -pe 's|^(\d+)\.(\d+).*|\2|'`
+dnl dnl First test the minimum version of 2.6
+dnl if test $XML_VERSION_major -lt 2 || ( test $XML_VERSION_major -eq 2 && test $XML_VERSION_minor -lt 6 )
+dnl then
+dnl 	AC_MSG_ERROR([requires libxml2 2.6.0 or greater, found $XML_VERSION.  Install newer version or use --with-xml2-config to specify another location.])
+dnl else
+dnl     AC_MSG_RESULT([$XML_VERSION... yes])
+dnl fi
+dnl
+dnl AC_MSG_CHECKING([xml2 cflags])
+dnl XML_CFLAGS="`${XML_CONFIG} --cflags`"
+dnl AC_MSG_RESULT([${XML_CFLAGS}])
+dnl
+dnl AC_MSG_CHECKING([xml2 ldflags])
+dnl XML_LDFLAGS="`${XML_CONFIG} --libs`"
+dnl AC_MSG_RESULT([${XML_LDFLAGS}])
+dnl
+dnl PSLIB_CFLAGS="${PSLIB_CFLAGS=} ${XML_CFLAGS}"
+dnl PSLIB_LIBS="${PSLIB_LIBS=} ${XML_LDFLAGS}"
+dnl
+dnl AC_SUBST([XML_CFLAGS])
+
+dnl ------------------- SWIG options ---------------------
+
+dnl save LIBS/CFLAGS/LDFLAGS
+TMP_LIBS=${LIBS}
+TMP_CFLAGS=${CFLAGS}
+TMP_LDFLAGS=${LDFLAGS}
+TMP_CPPFLAGS=${CPPFLAGS}
+
+AC_ARG_ENABLE(perlmodule,
+ [AS_HELP_STRING(--enable-perlmodule,Enables creation of perl module)],
+ [SWIG_REQ="$enableval"],
+ [SWIG_REQ="no"])
+
+if test "$SWIG_REQ" == "yes"
+then
+  AC_MSG_RESULT([enable building perl module])
+  AC_ARG_WITH(swig,
+  [AS_HELP_STRING(--with-swig=FILE,Specify location of SWIG executable.)],
+  [SWIG=$withval],
+  [SWIG=`which swig`])
+  AC_SUBST(SWIG,$SWIG)
+
+  AC_CHECK_FILE($SWIG,[],
+     [AC_MSG_ERROR([SWIG is required.  Obtain it at www.swig.org or use --with-swig to specify its install location.])])
+  SUBDIR="${SUBDIR=} swig"
+
+dnl restore the CFLAGS/LDFLAGS
+LIBS=${TMP_LIBS}
+CFLAGS=${TMP_CFLAGS}
+LDFLAGS=${TMP_LDFLAGS}
+CPPFLAGS=${TMP_CPPFLAGS}
+
+dnl ---------------- PERLPREFIX option -------------------
+
+dnl save LIBS/CFLAGS/LDFLAGS
+TMP_LIBS=${LIBS}
+TMP_CFLAGS=${CFLAGS}
+TMP_LDFLAGS=${LDFLAGS}
+TMP_CPPFLAGS=${CPPFLAGS}
+
+  AC_ARG_WITH(perlprefix,
+    [AS_HELP_STRING(--with-perlprefix=DIR,Specify prefix of Perl Module's installation. (default=PREFIX))],
+    [PERL_PREFIX="$withval"],
+    [PERL_PREFIX="$prefix"])
+    AC_SUBST(PERL_PREFIX,$PERL_PREFIX)
+    AC_SUBST(PERL_INSTALLSYTLE,[`perl '-V:installstyle'`])
+
+else
+  AC_MSG_RESULT([disable building perl module])
+fi
+
+dnl restore the CFLAGS/LDFLAGS
+LIBS=${TMP_LIBS}
+CFLAGS=${TMP_CFLAGS}
+LDFLAGS=${TMP_LDFLAGS}
+CPPFLAGS=${TMP_CPPFLAGS}
+
+dnl for MacOSX suppport -- check if sqrtf is in mx library.
+
+dnl save LIBS/CFLAGS/LDFLAGS
+TMP_LIBS=${LIBS}
+TMP_CFLAGS=${CFLAGS}
+TMP_LDFLAGS=${LDFLAGS}
+TMP_CPPFLAGS=${CPPFLAGS}
+
+AC_CHECK_LIB(mx,sqrtf,
+  [PSLIB_LIBS="${PSLIB_LIBS=} -lmx"])
+LIBS=${TMP_LIBS}
+AC_CHECK_FUNC(atoll, [],
+  [AC_MSG_ERROR([The C99 function, atoll, is required; update your compiler version?])])
+
+dnl restore the CFLAGS/LDFLAGS
+LIBS=${TMP_LIBS}
+CFLAGS=${TMP_CFLAGS}
+LDFLAGS=${TMP_LDFLAGS}
+CPPFLAGS=${TMP_CPPFLAGS}
+
+dnl doxygen doc generation is very, very slow so we're turing it off by default
+
+dnl save LIBS/CFLAGS/LDFLAGS
+TMP_LIBS=${LIBS}
+TMP_CFLAGS=${CFLAGS}
+TMP_LDFLAGS=${LDFLAGS}
+TMP_CPPFLAGS=${CPPFLAGS}
+
+AC_ARG_ENABLE(doxygen,
+  [AS_HELP_STRING(--enable-doxygen ,enable manpage generation)],
+  [AC_MSG_RESULT(doxygen enabled)
+    AC_PATH_PROG([DOXYGEN], [doxygen], [])
+  ],
+  [AC_MSG_RESULT([doxygen disabled])
+    doxygen=off
+  ]
+)
+AM_CONDITIONAL([HAVE_DOXYGEN], test -n "$DOXYGEN" -a "x$doxygen" != "xoff")
+
+dnl restore the CFLAGS/LDFLAGS
+LIBS=${TMP_LIBS}
+CFLAGS=${TMP_CFLAGS}
+LDFLAGS=${TMP_LDFLAGS}
+CPPFLAGS=${TMP_CPPFLAGS}
+
+dnl ------- enable -Werror after all of the probes have run ---------
+IPP_STDOPTS
+
+CFLAGS="${CFLAGS} -Wall -Werror"
+dnl enable POSIX/XSI and C99 compliance
+CFLAGS="${CFLAGS=} -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L"
+
+dnl ---------------- export variables --------------------
+
+AC_SUBST(SUBDIR,[$SUBDIR])
+AC_SUBST(SRCDIRS,[$SRCDIRS])
+AC_SUBST(PSLIB_LIBS,[$PSLIB_LIBS])
+AC_SUBST(PSLIB_CFLAGS,[$PSLIB_CFLAGS])
+
+AC_SUBST(PS_LANG,[en])
+
+AC_CONFIG_FILES([
+  Doxyfile
+  Makefile
+  etc/Makefile
+  m4/Makefile
+  pslib-config
+  pslib.pc
+  share/Makefile
+  src/Makefile
+  src/astro/Makefile
+  src/db/Makefile
+  src/fft/Makefile
+  src/fits/Makefile
+  src/imageops/Makefile
+  src/jpeg/Makefile
+  src/math/Makefile
+  src/mathtypes/Makefile
+  src/sys/Makefile
+  src/types/Makefile
+  test/Makefile
+  test/astro/Makefile
+  test/db/Makefile
+  test/fft/Makefile
+  test/fits/Makefile
+  test/imageops/Makefile
+  test/jpeg/Makefile
+  test/math/Makefile
+  test/mathtypes/Makefile
+  test/pstap/Makefile
+  test/pstap/src/Makefile
+  test/sys/Makefile
+  test/types/Makefile
+  utils/Makefile
+])
+dnl src/xml/Makefile
+dnl test/xml/Makefile
+
+
+#if test "$SWIG_REQ" == "yes"
+#then
+#  AC_CONFIG_FILES([ swig/Makefile ])
+#fi
+
+AC_OUTPUT
Index: /branches/eam_branches/eam_branch_20080719/psLib/etc/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/etc/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/etc/.cvsignore	(revision 22158)
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+*.bb
+*.bbg
+*.da
+pslib.config
Index: /branches/eam_branches/eam_branch_20080719/psLib/etc/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/etc/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/etc/Makefile.am	(revision 22158)
@@ -0,0 +1,15 @@
+BUILT_SOURCES = pslib.config
+EXTRA_DIST = pslib.config.template
+
+# this is done instead of using autoconf to delay the expansion of datadir
+# until --prefix is known
+pslib.config: $(srcdir)/pslib.config.template
+	$(PERL) -pe 's|DATADIR|$(pkgdatadir)|' $? > $@
+
+pslibconfdir = $(sysconfdir)/@PACKAGE_NAME@
+pslibconf_DATA = pslib.config
+
+#install-data-hook:
+#	chmod 0755 $(pslibconfdir)
+
+CLEANFILES = pslib.config
Index: /branches/eam_branches/eam_branch_20080719/psLib/etc/pslib.config.template
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/etc/pslib.config.template	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/etc/pslib.config.template	(revision 22158)
@@ -0,0 +1,43 @@
+# This configuration file specifies values required by psLib.
+#
+# psTime settings
+#
+psLib.time.tables.dir STR DATADIR
+psLib.time.tables.n S32 4                                                               # Number of time tables
+psLib.time.tables.files STR daily.dat eopc01_1900_2004.dat finals_all.dat tai_utc.dat
+psLib.time.tables.format STR %lf %lf %lf %lf %lf %lf %lf, %lf %lf %lf %lf, %lf %lf %lf %lf %lf %lf %lf, %lf %lf %lf %lf
+@psLib.time.tables.index S32 0, 0, 0, 0
+@psLib.time.tables.from F64 53403.0, 15020.0, 41684.0 2437300.5                         # Valid from these dates
+@psLib.time.tables.to F64 53583.0, 53258.0, 53627.0 2451179.5                           # Valid to these dates
+psLib.time.before.xp F64 0.0                                                            # Value of XP for before the earliest MJD
+psLib.time.before.yp F64 0.0                                                            # Value of YP for before the earliest MJD
+psLib.time.before.dut F64 0.0                                                           # Value of UT1-UTC for before the earliest MJD
+# Now follows formulae for predicting ahead of the most recent available table entry.
+# xp = [0] + [1]*cos A + [2]*sin A + [3]*cos C + [4]*sin C
+# yp = [0] + [1]*cos A + [2]*sin A + [3]*cos C + [4]*sin C
+# A = 2*pi*(MJD - pslib.time.predict.mjd)/365.25
+# C = 2*pi*(MJD - pslib.time.predict.mjd)/435.0
+# dut = ut1-utc = [0] + [1]*(MJD - [2]) - (UT2-UT1)
+# ut2-ut1 = 0.022 sin(2*pi*T) - 0.012 cos(2*pi*T) - 0.006 sin(4*pi*T) + 0.007 cos(4*pi*T)
+# T = 2000.0 + (MJD - 51544.03)/365.2422
+@psLib.time.predict.xp F64 0.0569, 0.0555, -0.0200, 0.0513, 0.1483
+@psLib.time.predict.yp F64 0.3498, -0.0176, -0.0498, 0.1483, -0.0513
+psLib.time.predict.mjd F64 53257.0
+@psLib.time.predict.dut F64 -0.4944, -0.00023, 53262.0
+#
+# psEOC settings
+#
+psLib.eoc.precession.table.format STR  %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf
+psLib.eoc.precession.iers.table.format STR %lf %lf %lf %lf %lf
+psLib.eoc.precession.finals.table.format STR %lf %lf %lf %lf %lf %lf %lf
+psLib.eoc.precession.table.file.x STR DATADIR/tab5.2a.dat
+psLib.eoc.precession.table.file.y STR DATADIR/tab5.2b.dat
+psLib.eoc.precession.table.file.s STR DATADIR/tab5.2c.dat
+psLib.eoc.precession.table.file.iers STR DATADIR/finals2000A.dat
+psLib.eoc.precession.table.file.final STR DATADIR/finals_all.dat
+@psLib.eoc.precession.poly.x F64 -16616.99 2004191742.88 -427219.05 -198620.54 -46.05 5.98
+@psLib.eoc.precession.poly.y F64 -6950.78 -25381.99 -22407250.99 1842.28 1113.06 0.99
+@psLib.eoc.precession.poly.s F64 94.0 3808.35 -119.94 -72574.09 27.70 15.61
+
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/m4/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/m4/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/m4/.cvsignore	(revision 22158)
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
Index: /branches/eam_branches/eam_branch_20080719/psLib/m4/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/m4/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/m4/Makefile.am	(revision 22158)
@@ -0,0 +1,9 @@
+installed_m4 = ipp_stdopts.m4
+
+EXTRA_DIST= \
+	acx_pthread.m4 \
+    ax_lib_mysql.m4 \
+	$(installed_m4)
+
+m4datadir = $(datadir)/aclocal
+m4data_DATA = $(installed_m4)
Index: /branches/eam_branches/eam_branch_20080719/psLib/m4/acx_pthread.m4
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/m4/acx_pthread.m4	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/m4/acx_pthread.m4	(revision 22158)
@@ -0,0 +1,242 @@
+dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+dnl
+dnl @summary figure out how to build C programs using POSIX threads
+dnl
+dnl This macro figures out how to build C programs using POSIX threads.
+dnl It sets the PTHREAD_LIBS output variable to the threads library and
+dnl linker flags, and the PTHREAD_CFLAGS output variable to any special
+dnl C compiler flags that are needed. (The user can also force certain
+dnl compiler flags/libs to be tested by setting these environment
+dnl variables.)
+dnl
+dnl Also sets PTHREAD_CC to any special C compiler that is needed for
+dnl multi-threaded programs (defaults to the value of CC otherwise).
+dnl (This is necessary on AIX to use the special cc_r compiler alias.)
+dnl
+dnl NOTE: You are assumed to not only compile your program with these
+dnl flags, but also link it with them as well. e.g. you should link
+dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS
+dnl $LIBS
+dnl
+dnl If you are only building threads programs, you may wish to use
+dnl these variables in your default LIBS, CFLAGS, and CC:
+dnl
+dnl        LIBS="$PTHREAD_LIBS $LIBS"
+dnl        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+dnl        CC="$PTHREAD_CC"
+dnl
+dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute
+dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to
+dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+dnl
+dnl ACTION-IF-FOUND is a list of shell commands to run if a threads
+dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to
+dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the
+dnl default action will define HAVE_PTHREAD.
+dnl
+dnl Please let the authors know if this macro fails on any platform, or
+dnl if you have any other suggestions or comments. This macro was based
+dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with
+dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros
+dnl posted by Alejandro Forero Cuervo to the autoconf macro repository.
+dnl We are also grateful for the helpful feedback of numerous users.
+dnl
+dnl @category InstalledPackages
+dnl @author Steven G. Johnson <stevenj@alum.mit.edu>
+dnl @version 2006-05-29
+dnl @license GPLWithACException
+
+AC_DEFUN([ACX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_SAVE
+AC_LANG_C
+acx_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+        AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
+        AC_MSG_RESULT($acx_pthread_ok)
+        if test x"$acx_pthread_ok" = xno; then
+                PTHREAD_LIBS=""
+                PTHREAD_CFLAGS=""
+        fi
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try.  Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all, and "pthread-config"
+# which is a program returning the flags for the Pth emulation library.
+
+acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important.  Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+#       other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+#      doesn't hurt to check since this sometimes defines pthreads too;
+#      also defines -D_REENTRANT)
+#      ... -mt is also the pthreads flag for HP/aCC
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case "${host_cpu}-${host_os}" in
+        *solaris*)
+
+        # On Solaris (at least, for some versions), libc contains stubbed
+        # (non-functional) versions of the pthreads routines, so link-based
+        # tests will erroneously succeed.  (We need to link with -pthreads/-mt/
+        # -lpthread.)  (The stubs are missing pthread_cleanup_push, or rather
+        # a function called by this macro, so we could check for that, but
+        # who knows whether they'll stub that too in a future libc.)  So,
+        # we'll just look for -pthreads and -lpthread first:
+
+        acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags"
+        ;;
+esac
+
+if test x"$acx_pthread_ok" = xno; then
+for flag in $acx_pthread_flags; do
+
+        case $flag in
+                none)
+                AC_MSG_CHECKING([whether pthreads work without any flags])
+                ;;
+
+                -*)
+                AC_MSG_CHECKING([whether pthreads work with $flag])
+                PTHREAD_CFLAGS="$flag"
+                ;;
+
+		pthread-config)
+		AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no)
+		if test x"$acx_pthread_config" = xno; then continue; fi
+		PTHREAD_CFLAGS="`pthread-config --cflags`"
+		PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+		;;
+
+                *)
+                AC_MSG_CHECKING([for the pthreads library -l$flag])
+                PTHREAD_LIBS="-l$flag"
+                ;;
+        esac
+
+        save_LIBS="$LIBS"
+        save_CFLAGS="$CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Check for various functions.  We must include pthread.h,
+        # since some functions may be macros.  (On the Sequent, we
+        # need a special flag -Kthread to make this header compile.)
+        # We check for pthread_join because it is in -lpthread on IRIX
+        # while pthread_create is in libc.  We check for pthread_attr_init
+        # due to DEC craziness with -lpthreads.  We check for
+        # pthread_cleanup_push because it is one of the few pthread
+        # functions on Solaris that doesn't have a non-functional libc stub.
+        # We try pthread_create on general principles.
+        AC_TRY_LINK([#include <pthread.h>],
+                    [pthread_t th; pthread_join(th, 0);
+                     pthread_attr_init(0); pthread_cleanup_push(0, 0);
+                     pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+                    [acx_pthread_ok=yes])
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+
+        AC_MSG_RESULT($acx_pthread_ok)
+        if test "x$acx_pthread_ok" = xyes; then
+                break;
+        fi
+
+        PTHREAD_LIBS=""
+        PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$acx_pthread_ok" = xyes; then
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+	AC_MSG_CHECKING([for joinable pthread attribute])
+	attr_name=unknown
+	for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+	    AC_TRY_LINK([#include <pthread.h>], [int attr=$attr; return attr;],
+                        [attr_name=$attr; break])
+	done
+        AC_MSG_RESULT($attr_name)
+        if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
+            AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
+                               [Define to necessary symbol if this constant
+                                uses a non-standard name on your system.])
+        fi
+
+        AC_MSG_CHECKING([if more special flags are required for pthreads])
+        flag=no
+        case "${host_cpu}-${host_os}" in
+            *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
+            *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+        esac
+        AC_MSG_RESULT(${flag})
+        if test "x$flag" != xno; then
+            PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+        fi
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+
+        # More AIX lossage: must compile with xlc_r or cc_r
+	if test x"$GCC" != xyes; then
+          AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
+        else
+          PTHREAD_CC=$CC
+	fi
+else
+        PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_pthread_ok" = xyes; then
+        ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+        :
+else
+        acx_pthread_ok=no
+        $2
+fi
+AC_LANG_RESTORE
+])dnl ACX_PTHREAD
Index: /branches/eam_branches/eam_branch_20080719/psLib/m4/ax_lib_mysql.m4
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/m4/ax_lib_mysql.m4	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/m4/ax_lib_mysql.m4	(revision 22158)
@@ -0,0 +1,158 @@
+##### http://autoconf-archive.cryp.to/ax_lib_mysql.html
+#
+# SYNOPSIS
+#
+#   AX_LIB_MYSQL([MINIMUM-VERSION[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]])
+#
+# DESCRIPTION
+#
+#   This macro provides tests of availability of MySQL client library
+#   of particular version or newer.
+#
+#   AX_LIB_MYSQL macro takes only one argument which is optional. If
+#   there is no required version passed, then macro does not run
+#   version test.
+#
+#   The --with-mysql option takes one of three possible values:
+#
+#   no - do not check for MySQL client library
+#
+#   yes - do check for MySQL library in standard locations
+#   (mysql_config should be in the PATH)
+#
+#   path - complete path to mysql_config utility, use this option if
+#   mysql_config can't be found in the PATH
+#
+#   This macro calls:
+#
+#     AC_SUBST(MYSQL_CFLAGS)
+#     AC_SUBST(MYSQL_LDFLAGS)
+#     AC_SUBST(MYSQL_VERSION)
+#
+#   And sets:
+#
+#     HAVE_MYSQL
+#
+# LAST MODIFICATION
+#
+#   2006-07-16
+#
+# COPYLEFT
+#
+#   Copyright (c) 2006 Mateusz Loskot <mateusz@loskot.net>
+#
+#   Copying and distribution of this file, with or without
+#   modification, are permitted in any medium without royalty provided
+#   the copyright notice and this notice are preserved.
+
+AC_DEFUN([AX_LIB_MYSQL],
+[
+    AC_ARG_WITH([mysql],
+        AC_HELP_STRING([--with-mysql=@<:@ARG@:>@],
+            [use MySQL client library @<:@default=yes@:>@, optionally specify path to mysql_config]
+        ),
+        [
+        if test "$withval" = "no"; then
+            want_mysql="no"
+        elif test "$withval" = "yes"; then
+            want_mysql="yes"
+        else
+            want_mysql="yes"
+            MYSQL_CONFIG="$withval"
+        fi
+        ],
+        [want_mysql="yes"]
+    )
+
+    MYSQL_CFLAGS=""
+    MYSQL_LDFLAGS=""
+    MYSQL_VERSION=""
+
+    dnl
+    dnl Check MySQL libraries (libpq)
+    dnl
+
+    if test "$want_mysql" = "yes"; then
+
+        if test -z "$MYSQL_CONFIG" -o test; then
+            AC_PATH_PROG([MYSQL_CONFIG], [mysql_config], [no])
+        fi
+
+        if test "$MYSQL_CONFIG" != "no"; then
+            AC_MSG_CHECKING([for MySQL libraries])
+
+            MYSQL_CFLAGS="`$MYSQL_CONFIG --cflags`"
+            MYSQL_LDFLAGS="`$MYSQL_CONFIG --libs`"
+
+            MYSQL_VERSION=`$MYSQL_CONFIG --version`
+
+            AC_DEFINE([HAVE_MYSQL], [1],
+                [Define to 1 if MySQL libraries are available])
+
+            found_mysql="yes"
+            AC_MSG_RESULT([yes])
+        else
+            found_mysql="no"
+            AC_MSG_RESULT([no])
+        fi
+    fi
+
+    dnl
+    dnl Check if required version of MySQL is available
+    dnl
+
+
+    mysql_version_req=ifelse([$1], [], [], [$1])
+
+    if test "$found_mysql" = "yes" -a -n "$mysql_version_req"; then
+
+        AC_MSG_CHECKING([if MySQL version is >= $mysql_version_req])
+
+        dnl Decompose required version string of MySQL
+        dnl and calculate its number representation
+        mysql_version_req_major=`expr $mysql_version_req : '\([[0-9]]*\)'`
+        mysql_version_req_minor=`expr $mysql_version_req : '[[0-9]]*\.\([[0-9]]*\)'`
+        mysql_version_req_micro=`expr $mysql_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
+        if test "x$mysql_version_req_micro" = "x"; then
+            mysql_version_req_micro="0"
+        fi
+
+        mysql_version_req_number=`expr $mysql_version_req_major \* 1000000 \
+                                   \+ $mysql_version_req_minor \* 1000 \
+                                   \+ $mysql_version_req_micro`
+
+        dnl Decompose version string of installed MySQL
+        dnl and calculate its number representation
+        mysql_version_major=`expr $MYSQL_VERSION : '\([[0-9]]*\)'`
+        mysql_version_minor=`expr $MYSQL_VERSION : '[[0-9]]*\.\([[0-9]]*\)'`
+        mysql_version_micro=`expr $MYSQL_VERSION : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
+        if test "x$mysql_version_micro" = "x"; then
+            mysql_version_micro="0"
+        fi
+
+        mysql_version_number=`expr $mysql_version_major \* 1000000 \
+                                   \+ $mysql_version_minor \* 1000 \
+                                   \+ $mysql_version_micro`
+
+        mysql_version_check=`expr $mysql_version_number \>\= $mysql_version_req_number`
+        if test "$mysql_version_check" = "1"; then
+            AC_MSG_RESULT([yes])
+        else
+            AC_MSG_RESULT([no])
+        fi
+    fi
+
+    AC_SUBST([MYSQL_VERSION])
+    AC_SUBST([MYSQL_CFLAGS])
+    AC_SUBST([MYSQL_LDFLAGS])
+
+dnl Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test "$mysql_version_check" = "1"; then
+    $2
+    :
+else
+    $3
+    :
+fi
+
+]) dnl ax_lib_mysql
Index: /branches/eam_branches/eam_branch_20080719/psLib/m4/ipp_stdopts.m4
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/m4/ipp_stdopts.m4	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/m4/ipp_stdopts.m4	(revision 22158)
@@ -0,0 +1,38 @@
+
+AC_DEFUN([IPP_STDCFLAGS],
+[
+    AC_ARG_ENABLE(optimize,
+      [AS_HELP_STRING(--enable-optimize,enable compiler optimization)],
+      [AC_MSG_RESULT(compile optimization enabled)
+       CFLAGS="-pipe -O2 -g -DPS_NO_TRACE"],
+      [AC_MSG_RESULT([compile optimization disabled])
+        if test x"${CFLAGS}" == x; then
+          CFLAGS="-pipe -O0 -g"
+        fi
+      ]
+    )
+])
+
+AC_DEFUN([IPP_STDOPTS],
+[
+    dnl handle profiler building
+    AC_ARG_ENABLE(profile, [AS_HELP_STRING(--enable-profile,enable compiler profiler information inclusion)],
+      [AC_MSG_RESULT(profiling enabled, check that you also did --disable-shared)
+       CFLAGS="${CFLAGS=} -pg -g"
+       LDFLAGS="${LDFLAGS=} -pg"]
+    )
+
+    dnl handle path coverage checking
+    AC_ARG_ENABLE(coverage,
+      [AS_HELP_STRING(--enable-coverage,enable path coverage checking)],
+      [AC_MSG_RESULT(path coverage enabled)
+       CFLAGS="${CFLAGS=} -lgcov -fprofile-arcs -ftest-coverage -pg"]
+    )
+
+    dnl turn off trace messages
+    AC_ARG_ENABLE(trace,
+      [AS_HELP_STRING(--disable-trace,disable psTrace functionality)],
+      [AC_MSG_RESULT(psTrace disabled)
+       CFLAGS="${CFLAGS=} -DPS_NO_TRACE"]
+    )
+])
Index: /branches/eam_branches/eam_branch_20080719/psLib/pslib-config.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/pslib-config.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/pslib-config.in	(revision 22158)
@@ -0,0 +1,92 @@
+#! /bin/sh
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/@PACKAGE_NAME@
+top_srcdir=@ABS_SRCDIR@
+@PERL_INSTALLSYTLE@
+
+usage()
+{
+    cat <<EOF
+Usage: pslib-config [OPTION]
+
+Known values for OPTION are:
+
+  --prefix		print psLib installation prefix
+  --perlmodule  	print psLib perl module's installation location
+  --libs		print library linking information
+  --cflags		print pre-processor and compiler flags
+  --build-libs		print library linking information to the build (non-installed) version
+  --build-cflags	print pre-processor and compiler flags to the build (non-installed) version
+  --help		display this help and exit
+  --version		output version information
+
+EOF
+
+    exit $1
+}
+
+if test $# -eq 0; then
+    usage 1
+fi
+
+cflags=false
+libs=false
+
+while test $# -gt 0; do
+    case "$1" in
+    -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+    *) optarg= ;;
+    esac
+
+    case "$1" in
+    --prefix=*)
+	prefix=$optarg
+	;;
+
+    --prefix)
+	echo $prefix
+	;;
+
+    --version)
+	echo @VERSION@
+	exit 0
+	;;
+
+    --help)
+	usage 0
+	;;
+
+    --cflags)
+       	echo -I${includedir} @PSLIB_CFLAGS@
+       	;;
+
+    --libs)
+       	echo -L${libdir} -lpslib @PSLIB_LIBS@
+       	;;
+
+    --build-cflags)
+       	echo @SRCINC@ @PSLIB_CFLAGS@
+       	;;
+
+    --build-libs)
+       	echo -L@ABS_SRCDIR@/src/.libs -lpslib @PSLIB_LIBS@
+       	;;
+
+    --deps)
+       	echo @PSLIB_LIBS@
+       	;;
+    --perlmodule)
+       	echo @PERL_PREFIX@/$installstyle
+       	;;
+    *)
+	usage
+	exit 1
+	;;
+    esac
+    shift
+done
+
+exit 0
Index: /branches/eam_branches/eam_branch_20080719/psLib/pslib.kdevelop
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/pslib.kdevelop	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/pslib.kdevelop	(revision 22158)
@@ -0,0 +1,194 @@
+<?xml version = '1.0'?>
+<kdevelop>
+  <general>
+    <author>Robert Daniel DeSonia</author>
+    <email>robert.desonia@mhpcc.hpc.mil</email>
+    <version>1.6</version>
+    <projectmanagement>KDevAutoProject</projectmanagement>
+    <primarylanguage>C</primarylanguage>
+    <keywords>
+      <keyword>C</keyword>
+      <keyword>Code</keyword>
+    </keywords>
+    <ignoreparts/>
+    <projectdirectory>.</projectdirectory>
+    <absoluteprojectpath>false</absoluteprojectpath>
+    <description/>
+    <secondaryLanguages/>
+  </general>
+  <kdevautoproject>
+    <general>
+      <activetarget>src/pslib</activetarget>
+      <useconfiguration>default</useconfiguration>
+    </general>
+    <run>
+      <mainprogram>src/pslib</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>
+      <showvcsfields>false</showvcsfields>
+    </tree>
+  </kdevfileview>
+  <kdevdocumentation>
+    <projectdoc>
+      <docsystem>Doxygen Documentation Collection</docsystem>
+      <docurl>${APPNAMELC}.tag</docurl>
+    </projectdoc>
+  </kdevdocumentation>
+  <substmap>
+    <APPNAME>psLib</APPNAME>
+    <APPNAMELC>pslib</APPNAMELC>
+    <APPNAMEUC>PSLIB</APPNAMEUC>
+    <AUTHOR>Robert Daniel DeSonia</AUTHOR>
+    <CFLAGS/>
+    <EMAIL>robert.desonia@mhpcc.hpc.mil</EMAIL>
+    <LICENSE>GPL</LICENSE>
+    <LICENSEFILE>COPYING</LICENSEFILE>
+    <OPT_INCS>-I/usr/include</OPT_INCS>
+    <OPT_LIBS>-lm</OPT_LIBS>
+    <VERSION>1.5</VERSION>
+    <dest>/home/desonia/pslib</dest>
+  </substmap>
+  <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>
+    <creategettersetter>
+      <prefixGet/>
+      <prefixSet>set</prefixSet>
+      <prefixVariable>m_,_</prefixVariable>
+      <parameterName>theValue</parameterName>
+      <inlineGet>true</inlineGet>
+      <inlineSet>true</inlineSet>
+    </creategettersetter>
+  </kdevcppsupport>
+  <cppsupportpart>
+    <filetemplates>
+      <interfacesuffix>.h</interfacesuffix>
+      <implementationsuffix>.cpp</implementationsuffix>
+    </filetemplates>
+  </cppsupportpart>
+  <kdevdebugger>
+    <general>
+      <programargs/>
+      <gdbpath/>
+      <dbgshell>libtool</dbgshell>
+      <configGdbScript/>
+      <runShellScript/>
+      <runGdbScript/>
+      <breakonloadinglibs>true</breakonloadinglibs>
+      <separatetty>false</separatetty>
+      <floatingtoolbar>false</floatingtoolbar>
+    </general>
+    <display>
+      <staticmembers>false</staticmembers>
+      <demanglenames>true</demanglenames>
+      <outputradix>10</outputradix>
+    </display>
+  </kdevdebugger>
+  <kdevcvsservice>
+    <recursivewhenupdate>true</recursivewhenupdate>
+    <prunedirswhenupdate>true</prunedirswhenupdate>
+    <createdirswhenupdate>true</createdirswhenupdate>
+    <recursivewhencommitremove>true</recursivewhencommitremove>
+    <revertoptions>-C</revertoptions>
+  </kdevcvsservice>
+</kdevelop>
Index: /branches/eam_branches/eam_branch_20080719/psLib/pslib.pc.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/pslib.pc.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/pslib.pc.in	(revision 22158)
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/@PACKAGE_NAME@
+
+Name: @PACKAGE_NAME@
+Description: Pan-STARRS Library
+Version: @VERSION@
+Libs: -L${libdir} -lpslib
+Libs.private: @PSLIB_LIBS@
+Cflags: -I${includedir} @PSLIB_CFLAGS@
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/.cvsignore	(revision 22158)
@@ -0,0 +1,9 @@
+Makefile
+Makefile.in
+.libs
+.deps
+psTime.config
+psTime.xml
+*.bb
+*.bbg
+*.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/Makefile.am	(revision 22158)
@@ -0,0 +1,11 @@
+dist_pkgdata_DATA = \
+	daily.dat \
+	eopc01_1900_2004.dat \
+	finals_all.dat \
+	tai_utc.dat \
+	tab5.2a.dat \
+	tab5.2b.dat \
+	tab5.2c.dat \
+	finals2000A.dat \
+	finals_all.dat
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/daily.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/daily.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/daily.dat	(revision 22158)
@@ -0,0 +1,188 @@
+#
+#  Stripped version of finals.daily.orig file
+#
+#
+#          Bull A     Bull A      Bull A      Bull B      Bull B      Bull B
+#  MJD     PM-x       PM-y        UT1-UTC     PM-x        PM-y        UT1-UTC
+#
+53403.00   0.089198   0.207773  -0.5218861    0.089220    0.207360   -0.5219040
+53404.00   0.086551   0.206870  -0.5224171    0.086670    0.206850   -0.5224260
+53405.00   0.083583   0.206138  -0.5227683    0.083920    0.206040   -0.5227550
+53406.00   0.081544   0.205866  -0.5229579    0.081570    0.205850   -0.5229780
+53407.00   0.078824   0.205838  -0.5231935    0.078920    0.205580   -0.5231160
+53408.00   0.076009   0.205787  -0.5235614    0.076100    0.205770   -0.5237140
+53409.00   0.073081   0.205511  -0.5240823    0.073150    0.205280   -0.5240730
+53410.00   0.069881   0.205007  -0.5249001    0.070030    0.205020   -0.5248950
+53411.00   0.066804   0.204321  -0.5260474    0.066860    0.204090   -0.5260380
+53412.00   0.064032   0.203564  -0.5274687    0.064120    0.203610   -0.5274600
+53413.00   0.061534   0.203227  -0.5290349    0.061670    0.203150   -0.5290210
+53414.00   0.059261   0.203103  -0.5305665    0.059180    0.202910   -0.5305800
+53415.00   0.057167   0.203188  -0.5319092    0.057480    0.203020   -0.5318810
+53416.00   0.054644   0.203355  -0.5329893    0.054560    0.203270   -0.5329820
+53417.00   0.051723   0.203158  -0.5337631    0.052100    0.202990   -0.5337520
+53418.00   0.048514   0.202982  -0.5342942    0.048250    0.202830   -0.5342930
+53419.00   0.045299   0.203112  -0.5347071    0.045910    0.203060   -0.5347030
+53420.00   0.042672   0.203749  -0.5351354    0.042380    0.203710   -0.5351220
+53421.00   0.040104   0.204528  -0.5356628    0.040510    0.204360   -0.5356850
+53422.00   0.037711   0.205249  -0.5363046    0.037570    0.205130   -0.5362980
+53423.00   0.035491   0.205831  -0.5371187    0.035710    0.205590   -0.5371080
+53424.00   0.033293   0.206107  -0.5381067    0.033200    0.206030   -0.5380940
+53425.00   0.031547   0.206232  -0.5393036    0.031760    0.205990   -0.5392940
+53426.00   0.030088   0.206585  -0.5407214    0.030330    0.206570   -0.5407130
+53427.00   0.029197   0.207542  -0.5423144    0.029430    0.207400   -0.5422950
+53428.00   0.027670   0.208625  -0.5440523    0.027720    0.208530   -0.5440730
+53429.00   0.025817   0.209840  -0.5457450    0.025890    0.209650   -0.5457110
+53430.00   0.024127   0.211329  -0.5473574    0.024110    0.211090   -0.5473360
+53431.00   0.021777   0.212859  -0.5488360    0.021880    0.212750   -0.5488330
+53432.00   0.019378   0.214130  -0.5501178    0.019440    0.213970   -0.5500970
+53433.00   0.016950   0.214888  -0.5512259    0.017160    0.214930   -0.5512200
+53434.00   0.015134   0.215851  -0.5522278    0.015180    0.215700   -0.5522110
+53435.00   0.012738   0.216531  -0.5531713    0.000000    0.000000    0.0000000
+53436.00   0.010558   0.217070  -0.5541355    0.000000    0.000000    0.0000000
+53437.00   0.008806   0.217765  -0.5552417    0.000000    0.000000    0.0000000
+53438.00   0.006758   0.218630  -0.5565094    0.000000    0.000000    0.0000000
+53439.00   0.004646   0.219469  -0.5578989    0.000000    0.000000    0.0000000
+53440.00   0.002116   0.220380  -0.5593918    0.000000    0.000000    0.0000000
+53441.00   0.000386   0.221223  -0.5609127    0.000000    0.000000    0.0000000
+53442.00  -0.001411   0.221965  -0.5622917    0.000000    0.000000    0.0000000
+53443.00  -0.002676   0.222526  -0.5634066    0.000000    0.000000    0.0000000
+53444.00  -0.003697   0.223202  -0.5641684    0.000000    0.000000    0.0000000
+53445.00  -0.005587   0.223370  -0.5645880    0.000000    0.000000    0.0000000
+53446.00  -0.006897   0.223602  -0.5647672    0.000000    0.000000    0.0000000
+53447.00  -0.008129   0.223964  -0.5648197    0.000000    0.000000    0.0000000
+53448.00  -0.009000   0.224770  -0.5648551    0.000000    0.000000    0.0000000
+53449.00  -0.009853   0.225788  -0.5649488    0.000000    0.000000    0.0000000
+53450.00  -0.010752   0.226865  -0.5651214    0.000000    0.000000    0.0000000
+53451.00  -0.011836   0.228183  -0.5654543    0.000000    0.000000    0.0000000
+53452.00  -0.013357   0.230115  -0.5660328    0.000000    0.000000    0.0000000
+53453.00  -0.015359   0.231733  -0.5668880    0.000000    0.000000    0.0000000
+53454.00  -0.016630   0.233036  -0.5679461    0.000000    0.000000    0.0000000
+53455.00  -0.017847   0.234493  -0.5691352    0.000000    0.000000    0.0000000
+53456.00  -0.019260   0.236179  -0.5703273    0.000000    0.000000    0.0000000
+53457.00  -0.020917   0.237826  -0.5714205    0.000000    0.000000    0.0000000
+53458.00  -0.022446   0.239266  -0.5723283    0.000000    0.000000    0.0000000
+53459.00  -0.024822   0.240180  -0.5729862    0.000000    0.000000    0.0000000
+53460.00  -0.026796   0.241256  -0.5733634    0.000000    0.000000    0.0000000
+53461.00  -0.028996   0.242469  -0.5735448    0.000000    0.000000    0.0000000
+53462.00  -0.030749   0.243908  -0.5736219    0.000000    0.000000    0.0000000
+53463.00  -0.032355   0.244910  -0.5738480    0.000000    0.000000    0.0000000
+53464.00  -0.033549   0.245574  -0.5743129    0.000000    0.000000    0.0000000
+53465.00  -0.034314   0.245993  -0.5750873    0.000000    0.000000    0.0000000
+53466.00  -0.035092   0.246518  -0.5760683    0.000000    0.000000    0.0000000
+53467.00  -0.035603   0.247955  -0.5772363    0.000000    0.000000    0.0000000
+53468.00  -0.036716   0.250081  -0.5785305    0.000000    0.000000    0.0000000
+53469.00  -0.038502   0.252221  -0.5797696    0.000000    0.000000    0.0000000
+53470.00  -0.040638   0.253880  -0.5808118    0.000000    0.000000    0.0000000
+53471.00  -0.042584   0.255277  -0.5815764    0.000000    0.000000    0.0000000
+53472.00  -0.044043   0.256694  -0.5820791    0.000000    0.000000    0.0000000
+53473.00  -0.045469   0.258542  -0.5823466    0.000000    0.000000    0.0000000
+53474.00  -0.046115   0.260366  -0.5825923    0.000000    0.000000    0.0000000
+53475.00  -0.046845   0.262272  -0.5828567    0.000000    0.000000    0.0000000
+53476.00  -0.047872   0.264710  -0.5831790    0.000000    0.000000    0.0000000
+53477.00  -0.049363   0.267066  -0.5836570    0.000000    0.000000    0.0000000
+53478.00  -0.050998   0.269275  -0.5842978    0.000000    0.000000    0.0000000
+53479.00  -0.052488   0.271589  -0.5851290    0.000000    0.000000    0.0000000
+53480.00  -0.053852   0.273907  -0.5861727    0.000000    0.000000    0.0000000
+53481.00  -0.054932   0.276138  -0.5874000    0.000000    0.000000    0.0000000
+53482.00  -0.055785   0.278356  -0.5887508    0.000000    0.000000    0.0000000
+53483.00  -0.056771   0.280694  -0.5901790    0.000000    0.000000    0.0000000
+53484.00  -0.057675   0.283027  -0.5916199    0.000000    0.000000    0.0000000
+53485.00  -0.058387   0.284998  -0.5929329    0.000000    0.000000    0.0000000
+53486.00  -0.058807   0.286670  -0.5940239    0.000000    0.000000    0.0000000
+53487.00  -0.058834   0.288337  -0.5948463    0.000000    0.000000    0.0000000
+53488.00  -0.058468   0.290172  -0.5954614    0.000000    0.000000    0.0000000
+53489.00  -0.057836   0.292253  -0.5959457    0.000000    0.000000    0.0000000
+53490.00  -0.057279   0.294632  -0.5964394    0.000000    0.000000    0.0000000
+53491.00  -0.057256   0.297300  -0.5970769    0.000000    0.000000    0.0000000
+53492.00  -0.057639   0.299933  -0.5980051    0.000000    0.000000    0.0000000
+53493.00  -0.058151   0.302373  -0.5992687    0.000000    0.000000    0.0000000
+53494.00  -0.058700   0.304712  -0.6007248    0.000000    0.000000    0.0000000
+53495.00  -0.059272   0.306960  -0.6022420    0.000000    0.000000    0.0000000
+53496.00  -0.059856   0.309127  -0.6037093    0.000000    0.000000    0.0000000
+53497.00  -0.060443   0.311221  -0.6050339    0.000000    0.000000    0.0000000
+53498.00  -0.061026   0.313251  -0.6061046    0.000000    0.000000    0.0000000
+53499.00  -0.061597   0.315222  -0.6069056    0.000000    0.000000    0.0000000
+53500.00  -0.062154   0.317143  -0.6074547    0.000000    0.000000    0.0000000
+53501.00  -0.062691   0.319018  -0.6077615    0.000000    0.000000    0.0000000
+53502.00  -0.063205   0.320852  -0.6079384    0.000000    0.000000    0.0000000
+53503.00  -0.063695   0.322650  -0.6080889    0.000000    0.000000    0.0000000
+53504.00  -0.064157   0.324417  -0.6082912    0.000000    0.000000    0.0000000
+53505.00  -0.064591   0.326156  -0.6085899    0.000000    0.000000    0.0000000
+53506.00  -0.064995   0.327871  -0.6090260    0.000000    0.000000    0.0000000
+53507.00  -0.065369   0.329564  -0.6096200    0.000000    0.000000    0.0000000
+53508.00  -0.065711   0.331238  -0.6103620    0.000000    0.000000    0.0000000
+53509.00  -0.066022   0.332895  -0.6112057    0.000000    0.000000    0.0000000
+53510.00  -0.066301   0.334538  -0.6120710    0.000000    0.000000    0.0000000
+53511.00  -0.066547   0.336169  -0.6128774    0.000000    0.000000    0.0000000
+53512.00  -0.066762   0.337788  -0.6135321    0.000000    0.000000    0.0000000
+53513.00  -0.066944   0.339398  -0.6139426    0.000000    0.000000    0.0000000
+53514.00  -0.067094   0.340999  -0.6140704    0.000000    0.000000    0.0000000
+53515.00  -0.067212   0.342593  -0.6139338    0.000000    0.000000    0.0000000
+53516.00  -0.067298   0.344181  -0.6136271    0.000000    0.000000    0.0000000
+53517.00  -0.067353   0.345763  -0.6132988    0.000000    0.000000    0.0000000
+53518.00  -0.067376   0.347339  -0.6130910    0.000000    0.000000    0.0000000
+53519.00  -0.067368   0.348912  -0.6130983    0.000000    0.000000    0.0000000
+53520.00  -0.067329   0.350480  -0.6133377    0.000000    0.000000    0.0000000
+53521.00  -0.067259   0.352045  -0.6137530    0.000000    0.000000    0.0000000
+53522.00  -0.067158   0.353606  -0.6142476    0.000000    0.000000    0.0000000
+53523.00  -0.067028   0.355164  -0.6147019    0.000000    0.000000    0.0000000
+53524.00  -0.066867   0.356719  -0.6150115    0.000000    0.000000    0.0000000
+53525.00  -0.066677   0.358271  -0.6151081    0.000000    0.000000    0.0000000
+53526.00  -0.066458   0.359820  -0.6149565    0.000000    0.000000    0.0000000
+53527.00  -0.066209   0.361365  -0.6145663    0.000000    0.000000    0.0000000
+53528.00  -0.065932   0.362908  -0.6139974    0.000000    0.000000    0.0000000
+53529.00  -0.065626   0.364447  -0.6133312    0.000000    0.000000    0.0000000
+53530.00  -0.065291   0.365983  -0.6126499    0.000000    0.000000    0.0000000
+53531.00  -0.064929   0.367516  -0.6120298    0.000000    0.000000    0.0000000
+53532.00  -0.064539   0.369045  -0.6115355    0.000000    0.000000    0.0000000
+53533.00  -0.064122   0.370569  -0.6112118    0.000000    0.000000    0.0000000
+53534.00  -0.063678   0.372090  -0.6110774    0.000000    0.000000    0.0000000
+53535.00  -0.063206   0.373606  -0.6111281    0.000000    0.000000    0.0000000
+53536.00  -0.062731   0.375118  -0.6113333    0.000000    0.000000    0.0000000
+53537.00  -0.062204   0.376624  -0.6116363    0.000000    0.000000    0.0000000
+53538.00  -0.061652   0.378126  -0.6119672    0.000000    0.000000    0.0000000
+53539.00  -0.061075   0.379621  -0.6122419    0.000000    0.000000    0.0000000
+53540.00  -0.060472   0.381111  -0.6123670    0.000000    0.000000    0.0000000
+53541.00  -0.059845   0.382595  -0.6122687    0.000000    0.000000    0.0000000
+53542.00  -0.059194   0.384072  -0.6119327    0.000000    0.000000    0.0000000
+53543.00  -0.058518   0.385543  -0.6114171    0.000000    0.000000    0.0000000
+53544.00  -0.057818   0.387006  -0.6108419    0.000000    0.000000    0.0000000
+53545.00  -0.057095   0.388462  -0.6103562    0.000000    0.000000    0.0000000
+53546.00  -0.056348   0.389911  -0.6100804    0.000000    0.000000    0.0000000
+53547.00  -0.055579   0.391351  -0.6100654    0.000000    0.000000    0.0000000
+53548.00  -0.054787   0.392783  -0.6102740    0.000000    0.000000    0.0000000
+53549.00  -0.053973   0.394206  -0.6106035    0.000000    0.000000    0.0000000
+53550.00  -0.053137   0.395620  -0.6109243    0.000000    0.000000    0.0000000
+53551.00  -0.052279   0.397025  -0.6111159    0.000000    0.000000    0.0000000
+53552.00  -0.051400   0.398421  -0.6110951    0.000000    0.000000    0.0000000
+53553.00  -0.050500   0.399806  -0.6108246    0.000000    0.000000    0.0000000
+53554.00  -0.049580   0.401181  -0.6103105    0.000000    0.000000    0.0000000
+53555.00  -0.048640   0.402546  -0.6095938    0.000000    0.000000    0.0000000
+53556.00  -0.047679   0.403899  -0.6087372    0.000000    0.000000    0.0000000
+53557.00  -0.046700   0.405242  -0.6078156    0.000000    0.000000    0.0000000
+53558.00  -0.045701   0.406573  -0.6069068    0.000000    0.000000    0.0000000
+53559.00  -0.044683   0.407892  -0.6060834    0.000000    0.000000    0.0000000
+53560.00  -0.043647   0.409199  -0.6053990    0.000000    0.000000    0.0000000
+53561.00  -0.042594   0.410494  -0.6048821    0.000000    0.000000    0.0000000
+53562.00  -0.041522   0.411776  -0.6045336    0.000000    0.000000    0.0000000
+53563.00  -0.040434   0.413046  -0.6043315    0.000000    0.000000    0.0000000
+53564.00  -0.039328   0.414302  -0.6042312    0.000000    0.000000    0.0000000
+53565.00  -0.038206   0.415545  -0.6041737    0.000000    0.000000    0.0000000
+53566.00  -0.037068   0.416774  -0.6040854    0.000000    0.000000    0.0000000
+53567.00  -0.035915   0.417989  -0.6038884    0.000000    0.000000    0.0000000
+53568.00  -0.034746   0.419190  -0.6035134    0.000000    0.000000    0.0000000
+53569.00  -0.033562   0.420376  -0.6029275    0.000000    0.000000    0.0000000
+53570.00  -0.032364   0.421547  -0.6021579    0.000000    0.000000    0.0000000
+53571.00  -0.031152   0.422704  -0.6013029    0.000000    0.000000    0.0000000
+53572.00  -0.029926   0.423845  -0.6005091    0.000000    0.000000    0.0000000
+53573.00  -0.028687   0.424971  -0.5999238    0.000000    0.000000    0.0000000
+53574.00  -0.027434   0.426081  -0.5996363    0.000000    0.000000    0.0000000
+53575.00  -0.026170   0.427175  -0.5996429    0.000000    0.000000    0.0000000
+53576.00  -0.024893   0.428253  -0.5998473    0.000000    0.000000    0.0000000
+53577.00  -0.023604   0.429314  -0.6000987    0.000000    0.000000    0.0000000
+53578.00  -0.022304   0.430358  -0.6002451    0.000000    0.000000    0.0000000
+53579.00  -0.020993   0.431386  -0.6001768    0.000000    0.000000    0.0000000
+53580.00  -0.019672   0.432397  -0.5998445    0.000000    0.000000    0.0000000
+53581.00  -0.018341   0.433247  -0.5992544    0.000000    0.000000    0.0000000
+53582.00  -0.016999   0.434231  -0.5984530    0.000000    0.000000    0.0000000
+53583.00  -0.015649   0.435197  -0.5975086    0.000000    0.000000    0.0000000
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/eopc01_1900_2004.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/eopc01_1900_2004.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/eopc01_1900_2004.dat	(revision 22158)
@@ -0,0 +1,2103 @@
+#  eopc01_1900_2004.dat
+#
+#  This file comes from http://hpiers.obspm.fr/eoppc/eop/eopc01/eopc01.1900-2004. See readme.eopc01 (located
+#  in the psLib/data directory) for details.
+#
+#  @author Ross Harman, MHPCC
+#
+#  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+#  @date $Date: 2006-09-23 02:20:17 $
+#
+#
+#    Date       PM-x      PM-y     UT1-UTC
+#   (year)    (arcsec)   (arcsec)   (sec)
+#     psF64     psF64      psF64     psF64
+    1900.00  -.212818  -.097229   .0000000
+    1900.05  -.047461  -.065631   .0000000
+    1900.10  -.112006  -.040467   .0000000
+    1900.15  -.076710  -.009674   .0000000
+    1900.20  -.099850  -.066660   .0000000
+    1900.25  -.131173  -.072076   .0000000
+    1900.30  -.087390  -.089427   .0000000
+    1900.35  -.164078  -.131034   .0000000
+    1900.40  -.151407  -.105838   .0000000
+    1900.45  -.143764  -.179125   .0000000
+    1900.50  -.124341  -.105747   .0000000
+    1900.55  -.206229  -.144555   .0000000
+    1900.60  -.192711  -.095563   .0000000
+    1900.65  -.190299  -.067717   .0000000
+    1900.70  -.135718  -.081480   .0000000
+    1900.75  -.153807   .030568   .0000000
+    1900.80  -.173818   .001034   .0000000
+    1900.85  -.257716  -.006499   .0000000
+    1900.90  -.209085   .046511   .0000000
+    1900.95  -.133145   .004905   .0000000
+    1901.00  -.138242   .014255   .0000000
+    1901.05  -.162602   .006609   .0000000
+    1901.10  -.121242  -.000875   .0000000
+    1901.15  -.109773   .024691   .0000000
+    1901.20  -.103805   .039564   .0000000
+    1901.25  -.021306  -.011519   .0000000
+    1901.30  -.001300   .021700   .0000000
+    1901.35   .037156  -.049753   .0000000
+    1901.40   .003993  -.095314   .0000000
+    1901.45   .054079  -.081336   .0000000
+    1901.50   .089761  -.084901   .0000000
+    1901.55   .004864  -.187233   .0000000
+    1901.60  -.023099  -.179528   .0000000
+    1901.65  -.057910  -.197673   .0000000
+    1901.70  -.033170  -.202981   .0000000
+    1901.75  -.155604  -.187085   .0000000
+    1901.80  -.169658  -.183163   .0000000
+    1901.85  -.188623  -.181458   .0000000
+    1901.90  -.223086  -.144566   .0000000
+    1901.95  -.254958  -.114447   .0000000
+    1902.00  -.259243  -.078157   .0000000
+    1902.05  -.211792   .038633   .0000000
+    1902.10  -.216991   .064250   .0000000
+    1902.15  -.242537   .171246   .0000000
+    1902.20  -.188324   .158468   .0000000
+    1902.25  -.152570   .207171   .0000000
+    1902.30  -.062244   .171387   .0000000
+    1902.35  -.016045   .182141   .0000000
+    1902.40   .036032   .156268   .0000000
+    1902.45   .217293   .252814   .0000000
+    1902.50   .119283   .066262   .0000000
+    1902.55   .125538   .016781   .0000000
+    1902.60   .082496  -.058369   .0000000
+    1902.65   .051287  -.069631   .0000000
+    1902.70   .051239  -.093785   .0000000
+    1902.75  -.024248  -.151921   .0000000
+    1902.80  -.054789  -.179957   .0000000
+    1902.85  -.146320  -.146959   .0000000
+    1902.90  -.193061  -.169534   .0000000
+    1902.95  -.237694  -.119404   .0000000
+    1903.00  -.319420  -.043030   .0000000
+    1903.05  -.341204   .031366   .0000000
+    1903.10  -.345930  -.002271   .0000000
+    1903.15  -.363449   .022246   .0000000
+    1903.20  -.363639   .126744   .0000000
+    1903.25  -.275204   .088178   .0000000
+    1903.30  -.217973   .142752   .0000000
+    1903.35  -.133649   .193127   .0000000
+    1903.40  -.073538   .187785   .0000000
+    1903.45  -.033275   .242905   .0000000
+    1903.50  -.025665   .185828   .0000000
+    1903.55   .065994   .199396   .0000000
+    1903.60   .124642   .131603   .0000000
+    1903.65   .138085   .043707   .0000000
+    1903.70   .131036  -.010458   .0000000
+    1903.75   .129875  -.132885   .0000000
+    1903.80   .020188  -.149501   .0000000
+    1903.85  -.013164  -.224089   .0000000
+    1903.90   .017200  -.148400   .0000000
+    1903.95  -.054459  -.187411   .0000000
+    1904.00  -.148856  -.076687   .0000000
+    1904.05  -.254004  -.136031   .0000000
+    1904.10  -.260513  -.134266   .0000000
+    1904.15  -.250640  -.062308   .0000000
+    1904.20  -.318450  -.022118   .0000000
+    1904.25  -.293126   .024733   .0000000
+    1904.30  -.249230   .052166   .0000000
+    1904.35  -.263860   .072953   .0000000
+    1904.40  -.210918   .172463   .0000000
+    1904.45  -.152700   .188900   .0000000
+    1904.50  -.109676   .182564   .0000000
+    1904.55  -.082798   .158201   .0000000
+    1904.60   .001500   .164000   .0000000
+    1904.65   .042084   .134884   .0000000
+    1904.70   .062535   .070240   .0000000
+    1904.75   .083512   .063227   .0000000
+    1904.80   .042326   .010531   .0000000
+    1904.85   .042284  -.029751   .0000000
+    1904.90  -.008473  -.063250   .0000000
+    1904.95   .028258  -.057405   .0000000
+    1905.00  -.040538  -.099671   .0000000
+    1905.05  -.017099  -.158118   .0000000
+    1905.10  -.105713  -.176117   .0000000
+    1905.15  -.176213  -.100777   .0000000
+    1905.20  -.231493  -.136695   .0000000
+    1905.25  -.251440  -.151097   .0000000
+    1905.30  -.248000  -.108800   .0000000
+    1905.35  -.304428   .045206   .0000000
+    1905.40  -.236545   .042822   .0000000
+    1905.45  -.250592   .048859   .0000000
+    1905.50  -.185960   .112145   .0000000
+    1905.55  -.156532   .117102   .0000000
+    1905.60  -.109352   .166247   .0000000
+    1905.65  -.067846   .135598   .0000000
+    1905.70   .014037   .151407   .0000000
+    1905.75  -.034403   .175804   .0000000
+    1905.80  -.031721   .049970   .0000000
+    1905.85   .025746   .080453   .0000000
+    1905.90   .024021  -.056728   .0000000
+    1905.95   .040706  -.006383   .0000000
+    1906.00   .003853  -.026096   .0000000
+    1906.05  -.017613  -.075020   .0000000
+    1906.10  -.157406  -.092487   .0000000
+    1906.15  -.067506  -.080298   .0000000
+    1906.20  -.149450  -.119103   .0000000
+    1906.25  -.128247  -.061169   .0000000
+    1906.30  -.179648  -.057693   .0000000
+    1906.35  -.186449  -.044109   .0000000
+    1906.40  -.208575  -.019448   .0000000
+    1906.45  -.217870   .042944   .0000000
+    1906.50  -.199891   .058881   .0000000
+    1906.55  -.173543   .070934   .0000000
+    1906.60  -.182003   .113024   .0000000
+    1906.65  -.142776   .095154   .0000000
+    1906.70  -.093740   .095224   .0000000
+    1906.75  -.093900   .111200   .0000000
+    1906.80  -.102758   .078405   .0000000
+    1906.85  -.009641   .137918   .0000000
+    1906.90  -.126885   .077766   .0000000
+    1906.95  -.085940   .122947   .0000000
+    1907.00  -.079416   .150174   .0000000
+    1907.05  -.067350   .041498   .0000000
+    1907.10  -.027042   .024883   .0000000
+    1907.15  -.069913   .039794   .0000000
+    1907.20  -.059194  -.025833   .0000000
+    1907.25  -.032978  -.010025   .0000000
+    1907.30  -.032298  -.079952   .0000000
+    1907.35  -.012800  -.038790   .0000000
+    1907.40  -.094517  -.051596   .0000000
+    1907.45  -.089447  -.124297   .0000000
+    1907.50  -.131771  -.098748   .0000000
+    1907.55  -.109356  -.122489   .0000000
+    1907.60  -.134764  -.084340   .0000000
+    1907.65  -.150915  -.095204   .0000000
+    1907.70  -.183652  -.070567   .0000000
+    1907.75  -.247755  -.037271   .0000000
+    1907.80  -.276782   .006594   .0000000
+    1907.85  -.260675   .115176   .0000000
+    1907.90  -.279309   .066165   .0000000
+    1907.95  -.247411   .158512   .0000000
+    1908.00  -.179825   .190418   .0000000
+    1908.05  -.162104   .175855   .0000000
+    1908.10  -.073775   .244495   .0000000
+    1908.15  -.088534   .184551   .0000000
+    1908.20   .072181   .185212   .0000000
+    1908.25   .000811   .129285   .0000000
+    1908.30   .094290   .125029   .0000000
+    1908.35   .098031   .048028   .0000000
+    1908.40   .085376  -.037173   .0000000
+    1908.45   .110614  -.053618   .0000000
+    1908.50   .110175  -.121985   .0000000
+    1908.55   .062891  -.147259   .0000000
+    1908.60   .016036  -.174778   .0000000
+    1908.65  -.044507  -.258578   .0000000
+    1908.70  -.126698  -.236805   .0000000
+    1908.75  -.185227  -.279032   .0000000
+    1908.80  -.218671  -.234349   .0000000
+    1908.85  -.258124  -.193490   .0000000
+    1908.90  -.348498  -.117029   .0000000
+    1908.95  -.441656  -.087821   .0000000
+    1909.00  -.418026   .032515   .0000000
+    1909.05  -.464700   .053100   .0000000
+    1909.10  -.381402   .081369   .0000000
+    1909.15  -.331872   .208343   .0000000
+    1909.20  -.262800   .230900   .0000000
+    1909.25  -.180022   .262477   .0000000
+    1909.30  -.088674   .272316   .0000000
+    1909.35  -.017300   .301900   .0000000
+    1909.40   .082311   .293915   .0000000
+    1909.45   .145682   .242356   .0000000
+    1909.50   .159939   .145514   .0000000
+    1909.55   .219001   .050735   .0000000
+    1909.60   .251107   .038325   .0000000
+    1909.65   .216000  -.092100   .0000000
+    1909.70   .239771  -.129218   .0000000
+    1909.75   .122030  -.229024   .0000000
+    1909.80  -.027219  -.280542   .0000000
+    1909.85  -.097816  -.318227   .0000000
+    1909.90  -.212272  -.273213   .0000000
+    1909.95  -.262295  -.211841   .0000000
+    1910.00  -.323074  -.200846   .0000000
+    1910.05  -.442329  -.257217   .0000000
+    1910.10  -.448532  -.107453   .0000000
+    1910.15  -.408744   .030815   .0000000
+    1910.20  -.414020  -.006268   .0000000
+    1910.25  -.385676   .162890   .0000000
+    1910.30  -.368387   .272702   .0000000
+    1910.35  -.268774   .293213   .0000000
+    1910.40  -.147573   .342824   .0000000
+    1910.45  -.081273   .328529   .0000000
+    1910.50  -.020932   .388520   .0000000
+    1910.55   .105674   .327555   .0000000
+    1910.60   .176301   .312524   .0000000
+    1910.65   .191756   .171612   .0000000
+    1910.70   .222257   .091742   .0000000
+    1910.75   .211332  -.009012   .0000000
+    1910.80   .205000  -.105700   .0000000
+    1910.85   .120900  -.162494   .0000000
+    1910.90   .083916  -.253801   .0000000
+    1910.95  -.057477  -.280025   .0000000
+    1911.00  -.089579  -.260914   .0000000
+    1911.05  -.218786  -.263597   .0000000
+    1911.10  -.224700  -.257286   .0000000
+    1911.15  -.335860  -.182205   .0000000
+    1911.20  -.267000  -.050900   .0000000
+    1911.25  -.370633   .021540   .0000000
+    1911.30  -.353109   .047330   .0000000
+    1911.35  -.332727   .126340   .0000000
+    1911.40  -.234107   .168826   .0000000
+    1911.45  -.272718   .310644   .0000000
+    1911.50  -.193283   .331807   .0000000
+    1911.55  -.136796   .347029   .0000000
+    1911.60  -.056770   .304448   .0000000
+    1911.65   .060600   .363500   .0000000
+    1911.70   .112694   .325844   .0000000
+    1911.75   .129599   .242729   .0000000
+    1911.80   .130866   .155825   .0000000
+    1911.85   .158551   .088616   .0000000
+    1911.90   .145314  -.044498   .0000000
+    1911.95   .095603  -.041933   .0000000
+    1912.00   .083131  -.041367   .0000000
+    1912.05  -.038956  -.097988   .0000000
+    1912.10   .078300  -.165300   .0000000
+    1912.15  -.088995  -.223549   .0000000
+    1912.20  -.127587  -.102840   .0000000
+    1912.25  -.227272  -.194080   .0000000
+    1912.30  -.209405  -.109730   .0000000
+    1912.35  -.237021  -.041122   .0000000
+    1912.40  -.262082  -.006966   .0000000
+    1912.45  -.225320   .056285   .0000000
+    1912.50  -.263907   .044713   .0000000
+    1912.55  -.196951   .144625   .0000000
+    1912.60  -.198267   .185500   .0000000
+    1912.65  -.219124   .151146   .0000000
+    1912.70  -.175982   .183356   .0000000
+    1912.75  -.160280   .162811   .0000000
+    1912.80  -.103200   .187700   .0000000
+    1912.85  -.078852   .172599   .0000000
+    1912.90  -.076719   .222193   .0000000
+    1912.95  -.018200   .178000   .0000000
+    1913.00  -.088918   .098053   .0000000
+    1913.05  -.043449   .115101   .0000000
+    1913.10  -.001323   .124168   .0000000
+    1913.15  -.021744   .057252   .0000000
+    1913.20   .011122   .015761   .0000000
+    1913.25  -.010477  -.071666   .0000000
+    1913.30   .032491   .003044   .0000000
+    1913.35   .048101  -.050706   .0000000
+    1913.40   .032669  -.039496   .0000000
+    1913.45   .008311  -.068348   .0000000
+    1913.50   .000027  -.047918   .0000000
+    1913.55  -.076685  -.083122   .0000000
+    1913.60  -.108057  -.085386   .0000000
+    1913.65  -.100400  -.040800   .0000000
+    1913.70  -.162152  -.081823   .0000000
+    1913.75  -.223157  -.030051   .0000000
+    1913.80  -.224000  -.002700   .0000000
+    1913.85  -.226344   .078679   .0000000
+    1913.90  -.200560   .102525   .0000000
+    1913.95  -.313300   .074600   .0000000
+    1914.00  -.203986   .155067   .0000000
+    1914.05  -.260937   .252070   .0000000
+    1914.10  -.152037   .221001   .0000000
+    1914.15  -.093945   .191653   .0000000
+    1914.20  -.063798   .184214   .0000000
+    1914.25  -.013635   .132013   .0000000
+    1914.30   .045383   .170364   .0000000
+    1914.35   .034013   .110450   .0000000
+    1914.40   .073793   .089719   .0000000
+    1914.45   .106389   .069624   .0000000
+    1914.50   .104207   .003118   .0000000
+    1914.55   .085502  -.025467   .0000000
+    1914.60   .049258  -.008534   .0000000
+    1914.65  -.013923  -.060487   .0000000
+    1914.70  -.046141  -.151237   .0000000
+    1914.75  -.094789  -.177467   .0000000
+    1914.80  -.140169  -.214589   .0000000
+    1914.85  -.220007  -.164939   .0000000
+    1914.90  -.271487  -.080598   .0000000
+    1914.95  -.197162  -.003731   .0000000
+    1915.00  -.365371   .018627   .0000000
+    1915.05  -.311390   .018527   .0000000
+    1915.10  -.363577   .127944   .0000000
+    1915.15  -.230546   .091634   .0000000
+    1915.20  -.285678   .254673   .0000000
+    1915.25  -.300793   .364102   .0000000
+    1915.30  -.145488   .374588   .0000000
+    1915.35  -.084157   .325899   .0000000
+    1915.40  -.008400   .253100   .0000000
+    1915.45   .086674   .275352   .0000000
+    1915.50   .081245   .210673   .0000000
+    1915.55   .121650   .162508   .0000000
+    1915.60   .169064  -.052355   .0000000
+    1915.65   .112084   .002862   .0000000
+    1915.70   .099188  -.061928   .0000000
+    1915.75   .093628  -.172293   .0000000
+    1915.80  -.031363  -.267297   .0000000
+    1915.85  -.050020  -.262266   .0000000
+    1915.90  -.047776  -.265495   .0000000
+    1915.95  -.135461  -.219164   .0000000
+    1916.00  -.250486  -.127502   .0000000
+    1916.05  -.339030  -.192532   .0000000
+    1916.10  -.414793  -.366168   .0000000
+    1916.15  -.341536  -.026629   .0000000
+    1916.20  -.344556   .102289   .0000000
+    1916.25  -.312204   .143646   .0000000
+    1916.30  -.283589   .181301   .0000000
+    1916.35  -.251093   .263902   .0000000
+    1916.40  -.158543   .396971   .0000000
+    1916.45  -.236712   .246063   .0000000
+    1916.50  -.049133   .295525   .0000000
+    1916.55  -.019000   .215800   .0000000
+    1916.60   .091660   .193570   .0000000
+    1916.65   .171184   .142932   .0000000
+    1916.70   .135500   .053900   .0000000
+    1916.75   .159276  -.060418   .0000000
+    1916.80   .195249  -.060384   .0000000
+    1916.85   .041662  -.606821   .0000000
+    1916.90   .012991  -.219566   .0000000
+    1916.95  -.003679  -.318930   .0000000
+    1917.00  -.095516  -.232917   .0000000
+    1917.05  -.151536  -.182785   .0000000
+    1917.10  -.182049  -.136279   .0000000
+    1917.15  -.292198  -.114514   .0000000
+    1917.20  -.293211  -.077170   .0000000
+    1917.25  -.310501  -.047076   .0000000
+    1917.30  -.262144   .028782   .0000000
+    1917.35  -.195616   .145893   .0000000
+    1917.40  -.216823   .172434   .0000000
+    1917.45  -.195552   .154519   .0000000
+    1917.50  -.114387   .252819   .0000000
+    1917.55  -.014913   .095478   .0000000
+    1917.60  -.032948   .203552   .0000000
+    1917.65  -.004274   .202191   .0000000
+    1917.70  -.029300   .187800   .0000000
+    1917.75   .047363   .077854   .0000000
+    1917.80   .027454   .011902   .0000000
+    1917.85   .086395   .016630   .0000000
+    1917.90   .011086   .026413   .0000000
+    1917.95   .061347  -.033647   .0000000
+    1918.00  -.045800  -.126500   .0000000
+    1918.05  -.063352  -.187119   .0000000
+    1918.10  -.140380  -.029766   .0000000
+    1918.15  -.139590  -.046948   .0000000
+    1918.20  -.186229  -.012003   .0000000
+    1918.25  -.197272  -.022847   .0000000
+    1918.30  -.162233   .009864   .0000000
+    1918.35  -.209522   .106965   .0000000
+    1918.40  -.183315   .111698   .0000000
+    1918.45  -.186120   .161230   .0000000
+    1918.50  -.206139   .170211   .0000000
+    1918.55  -.140500   .134700   .0000000
+    1918.60  -.075624   .126939   .0000000
+    1918.65  -.035250   .149125   .0000000
+    1918.70  -.038388   .139481   .0000000
+    1918.75   .005607   .126979   .0000000
+    1918.80  -.039489   .133454   .0000000
+    1918.85  -.047400   .170000   .0000000
+    1918.90  -.061884   .112716   .0000000
+    1918.95  -.059354   .062420   .0000000
+    1919.00  -.058158   .016625   .0000000
+    1919.05  -.045037   .121493   .0000000
+    1919.10  -.064165   .072740   .0000000
+    1919.15  -.046142   .055541   .0000000
+    1919.20  -.076649   .084834   .0000000
+    1919.25  -.032000   .101400   .0000000
+    1919.30  -.032764   .042454   .0000000
+    1919.35  -.034002   .057361   .0000000
+    1919.40  -.081513   .071678   .0000000
+    1919.45  -.024396   .011394   .0000000
+    1919.50  -.005435   .014449   .0000000
+    1919.55  -.036700  -.072300   .0000000
+    1919.60  -.054480  -.035798   .0000000
+    1919.65  -.109833  -.018115   .0000000
+    1919.70  -.180209  -.046368   .0000000
+    1919.75  -.144050   .048583   .0000000
+    1919.80  -.181892  -.009524   .0000000
+    1919.85  -.159213   .054630   .0000000
+    1919.90  -.092562  -.197751   .0000000
+    1919.95  -.186227   .107207   .0000000
+    1920.00  -.097388   .112723   .0000000
+    1920.05  -.145513   .244405   .0000000
+    1920.10  -.066010   .127964   .0000000
+    1920.15  -.108000   .125400   .0000000
+    1920.20  -.066646   .249459   .0000000
+    1920.25   .062692   .241400   .0000000
+    1920.30   .077897   .212694   .0000000
+    1920.35   .112620   .177084   .0000000
+    1920.40   .081000   .157700   .0000000
+    1920.45   .148386   .115656   .0000000
+    1920.50   .111770   .088776   .0000000
+    1920.55   .063562  -.046004   .0000000
+    1920.60   .129866   .027842   .0000000
+    1920.65   .091341  -.043051   .0000000
+    1920.70   .068767  -.053549   .0000000
+    1920.75  -.008467  -.089633   .0000000
+    1920.80  -.052510  -.063097   .0000000
+    1920.85  -.131312  -.127174   .0000000
+    1920.90  -.098074  -.069955   .0000000
+    1920.95  -.202848  -.093388   .0000000
+    1921.00  -.275100   .041200   .0000000
+    1921.05  -.199380   .005397   .0000000
+    1921.10  -.269861   .062960   .0000000
+    1921.15  -.315700   .186534   .0000000
+    1921.20  -.190287   .164991   .0000000
+    1921.25  -.119466   .139311   .0000000
+    1921.30  -.014599   .217462   .0000000
+    1921.35   .031054   .201362   .0000000
+    1921.40   .091820   .160909   .0000000
+    1921.45   .100985   .083825   .0000000
+    1921.50   .212445   .182524   .0000000
+    1921.55   .138182   .088243   .0000000
+    1921.60   .178414   .025800   .0000000
+    1921.65   .167323   .004838   .0000000
+    1921.70   .073545  -.078915   .0000000
+    1921.75   .127179  -.080673   .0000000
+    1921.80  -.002474  -.169272   .0000000
+    1921.85  -.007518  -.143864   .0000000
+    1921.90  -.098209   .106262   .0000000
+    1921.95  -.133071  -.095128   .0000000
+    1922.00  -.045524  -.029486   .0000000
+    1922.05  -.194756  -.097510   .0000000
+    1922.10  -.208934   .039567   .0000000
+    1922.15  -.210300   .137300   .0000000
+    1922.20  -.165744   .125734   .0000000
+    1922.25  -.162390   .134218   .0000000
+    1922.30  -.132697   .221570   .0000000
+    1922.35  -.090259   .277564   .0000000
+    1922.40  -.047480   .260568   .0000000
+    1922.45   .009070   .222538   .0000000
+    1922.50   .111622   .240501   .0000000
+    1922.55   .088770   .114259   .0000000
+    1922.60   .163154   .076991   .0000000
+    1922.65   .151317   .014994   .0000000
+    1922.70   .141800   .014900   .0000000
+    1922.75   .120772  -.019145   .0000000
+    1922.80   .083381  -.139651   .0000000
+    1922.85   .063654  -.088851   .0000000
+    1922.90   .041976   .015059   .0000000
+    1922.95  -.163179  -.120346   .0000000
+    1923.00  -.162345  -.088042   .0000000
+    1923.05  -.166986  -.055441   .0000000
+    1923.10  -.332673  -.032441   .0000000
+    1923.15  -.262008  -.033456   .0000000
+    1923.20  -.207748   .016212   .0000000
+    1923.25  -.274792   .140175   .0000000
+    1923.30  -.179152   .157417   .0000000
+    1923.35  -.176779   .129676   .0000000
+    1923.40  -.097364   .300984   .0000000
+    1923.45  -.024124   .317510   .0000000
+    1923.50  -.019994   .239535   .0000000
+    1923.55   .060132   .240230   .0000000
+    1923.60   .112367   .311274   .0000000
+    1923.65   .142183   .249476   .0000000
+    1923.70   .151780   .226170   .0000000
+    1923.75   .161990   .129040   .0000000
+    1923.80   .130175   .020789   .0000000
+    1923.85   .136144   .082803   .0000000
+    1923.90   .088243   .024731   .0000000
+    1923.95   .035504  -.012841   .0000000
+    1924.00  -.005804   .073064   .0000000
+    1924.05  -.068517   .011667   .0000000
+    1924.10  -.029063   .003840   .0000000
+    1924.15  -.149500  -.020500   .0000000
+    1924.20  -.151107   .038096   .0000000
+    1924.25  -.170714   .072246   .0000000
+    1924.30  -.127400   .135100   .0000000
+    1924.35  -.165261   .139194   .0000000
+    1924.40  -.187563   .107926   .0000000
+    1924.45  -.081980   .195088   .0000000
+    1924.50  -.075229   .183050   .0000000
+    1924.55  -.059435   .142566   .0000000
+    1924.60   .014627   .135909   .0000000
+    1924.65   .029893   .185564   .0000000
+    1924.70  -.002107   .154303   .0000000
+    1924.75   .041539   .113626   .0000000
+    1924.80   .032319   .000498   .0000000
+    1924.85  -.079291   .056224   .0000000
+    1924.90  -.006172   .025546   .0000000
+    1924.95   .035597   .085593   .0000000
+    1925.00  -.012995   .036963   .0000000
+    1925.05  -.056182  -.049412   .0000000
+    1925.10  -.103481  -.003581   .0000000
+    1925.15  -.107312  -.041495   .0000000
+    1925.20  -.141179  -.046236   .0000000
+    1925.25  -.102647   .016748   .0000000
+    1925.30  -.130539   .119861   .0000000
+    1925.35  -.066774   .097721   .0000000
+    1925.40  -.004013   .055231   .0000000
+    1925.45  -.066873   .032174   .0000000
+    1925.50  -.055672   .061909   .0000000
+    1925.55  -.070311   .114851   .0000000
+    1925.60   .017853   .118506   .0000000
+    1925.65  -.015743   .056794   .0000000
+    1925.70   .001485   .004726   .0000000
+    1925.75  -.005631   .015549   .0000000
+    1925.80   .001128   .013928   .0000000
+    1925.85  -.243256  -.060509   .0000000
+    1925.90  -.025734   .007049   .0000000
+    1925.95  -.041648  -.013321   .0000000
+    1926.00  -.199605  -.083663   .0000000
+    1926.05  -.163818  -.029853   .0000000
+    1926.10  -.073051  -.074540   .0000000
+    1926.15  -.177265  -.060285   .0000000
+    1926.20  -.230084  -.024826   .0000000
+    1926.25  -.173813   .058121   .0000000
+    1926.30  -.052708   .122825   .0000000
+    1926.35  -.106664   .067451   .0000000
+    1926.40  -.129567   .112402   .0000000
+    1926.45  -.076581   .132865   .0000000
+    1926.50  -.051765   .131885   .0000000
+    1926.55  -.033933   .119936   .0000000
+    1926.60  -.053049   .122331   .0000000
+    1926.65  -.021532   .117705   .0000000
+    1926.70   .018915   .156256   .0000000
+    1926.75  -.001894   .104146   .0000000
+    1926.80  -.075772   .076597   .0000000
+    1926.85  -.120294   .111799   .0000000
+    1926.90  -.050061   .130391   .0000000
+    1926.95  -.098525   .073404   .0000000
+    1927.00  -.058200   .056215   .0000000
+    1927.05  -.142988   .109762   .0000000
+    1927.10  -.032237   .116674   .0000000
+    1927.15  -.095191   .115885   .0000000
+    1927.20  -.059447   .084129   .0000000
+    1927.25  -.115876   .071429   .0000000
+    1927.30  -.052232   .049356   .0000000
+    1927.35  -.054137   .027885   .0000000
+    1927.40  -.013624   .120684   .0000000
+    1927.45   .095331   .074304   .0000000
+    1927.50   .015128   .128662   .0000000
+    1927.55  -.016024   .158240   .0000000
+    1927.60  -.031647   .047004   .0000000
+    1927.65  -.020014   .048718   .0000000
+    1927.70  -.004146   .054252   .0000000
+    1927.75  -.052691   .005745   .0000000
+    1927.80  -.052571  -.025327   .0000000
+    1927.85  -.093446  -.044573   .0000000
+    1927.90  -.185615   .036816   .0000000
+    1927.95  -.159711  -.002380   .0000000
+    1928.00  -.008822  -.065239   .0000000
+    1928.05  -.145700  -.017500   .0000000
+    1928.10  -.134670   .100011   .0000000
+    1928.15  -.142914   .014838   .0000000
+    1928.20  -.130658   .109191   .0000000
+    1928.25  -.071799   .135022   .0000000
+    1928.30  -.077913   .109713   .0000000
+    1928.35  -.084562   .184119   .0000000
+    1928.40  -.070452   .122462   .0000000
+    1928.45  -.071262   .128166   .0000000
+    1928.50  -.023166   .138252   .0000000
+    1928.55  -.049392   .114652   .0000000
+    1928.60  -.132084  -.134582   .0000000
+    1928.65   .020427   .100107   .0000000
+    1928.70  -.028438   .032299   .0000000
+    1928.75  -.110100   .107500   .0000000
+    1928.80  -.143376  -.000841   .0000000
+    1928.85  -.115036   .011216   .0000000
+    1928.90  -.110841   .085727   .0000000
+    1928.95  -.072093   .151032   .0000000
+    1929.00  -.160303   .044210   .0000000
+    1929.05  -.288649   .003539   .0000000
+    1929.10  -.100071   .109711   .0000000
+    1929.15  -.169363   .171496   .0000000
+    1929.20  -.126222   .140853   .0000000
+    1929.25  -.057249   .149535   .0000000
+    1929.30   .003629   .164681   .0000000
+    1929.35   .131595   .332923   .0000000
+    1929.40   .031158   .160059   .0000000
+    1929.45   .069220   .115295   .0000000
+    1929.50   .103978   .187112   .0000000
+    1929.55   .082883   .085168   .0000000
+    1929.60   .049832  -.000080   .0000000
+    1929.65   .073767   .013919   .0000000
+    1929.70   .084972   .064950   .0000000
+    1929.75  -.015329  -.028934   .0000000
+    1929.80  -.093999  -.073280   .0000000
+    1929.85  -.161299  -.061529   .0000000
+    1929.90  -.165908  -.084395   .0000000
+    1929.95  -.205862   .028014   .0000000
+    1930.00  -.214153  -.044059   .0000000
+    1930.05  -.215942   .054329   .0000000
+    1930.10  -.225480   .057826   .0000000
+    1930.15  -.206525   .096138   .0000000
+    1930.20  -.166814   .146704   .0000000
+    1930.25  -.130922   .224514   .0000000
+    1930.30  -.049593   .179473   .0000000
+    1930.35  -.125200   .154900   .0000000
+    1930.40   .006745   .237422   .0000000
+    1930.45   .017674   .198183   .0000000
+    1930.50   .035577   .132240   .0000000
+    1930.55   .081022   .126161   .0000000
+    1930.60   .098407   .114242   .0000000
+    1930.65   .074379  -.037760   .0000000
+    1930.70   .062912  -.022243   .0000000
+    1930.75   .028598   .019082   .0000000
+    1930.80  -.011225  -.081563   .0000000
+    1930.85  -.084804  -.009200   .0000000
+    1930.90  -.116025  -.003658   .0000000
+    1930.95  -.158405  -.031682   .0000000
+    1931.00  -.353309   .027867   .0000000
+    1931.05  -.277671   .046550   .0000000
+    1931.10  -.239000  -.015100   .0000000
+    1931.15  -.355078   .116611   .0000000
+    1931.20  -.226864   .167103   .0000000
+    1931.25  -.248657   .182523   .0000000
+    1931.30  -.150564   .238762   .0000000
+    1931.35  -.151393   .231228   .0000000
+    1931.40  -.039529   .281355   .0000000
+    1931.45   .024987   .296176   .0000000
+    1931.50   .039600   .242500   .0000000
+    1931.55   .074415   .182812   .0000000
+    1931.60   .098426   .094944   .0000000
+    1931.65   .082462   .055652   .0000000
+    1931.70   .165785   .079323   .0000000
+    1931.75   .067878   .029704   .0000000
+    1931.80   .052973  -.106345   .0000000
+    1931.85  -.083590  -.105084   .0000000
+    1931.90  -.060868  -.054736   .0000000
+    1931.95  -.091079  -.143458   .0000000
+    1932.00  -.117202  -.090917   .0000000
+    1932.05  -.196529  -.057717   .0000000
+    1932.10  -.166200  -.015500   .0000000
+    1932.15  -.312357   .014781   .0000000
+    1932.20  -.324819   .020690   .0000000
+    1932.25  -.229236   .137146   .0000000
+    1932.30  -.199450   .181143   .0000000
+    1932.35  -.169007   .207207   .0000000
+    1932.40  -.138350   .219864   .0000000
+    1932.45  -.071670   .214482   .0000000
+    1932.50  -.075142   .230743   .0000000
+    1932.55  -.052070   .236227   .0000000
+    1932.60   .026338   .224720   .0000000
+    1932.65   .071800   .178200   .0000000
+    1932.70   .070092   .209808   .0000000
+    1932.75   .087369   .059518   .0000000
+    1932.80   .122666   .122560   .0000000
+    1932.85   .085699   .068358   .0000000
+    1932.90   .094388   .033874   .0000000
+    1932.95   .097006   .030486   .0000000
+    1933.00  -.073655  -.011865   .0000000
+    1933.05  -.058596   .014472   .0000000
+    1933.10  -.188030  -.012586   .0000000
+    1933.15  -.173476   .013624   .0000000
+    1933.20  -.221474   .048831   .0000000
+    1933.25  -.211408   .107715   .0000000
+    1933.30  -.186714   .112536   .0000000
+    1933.35  -.179116   .019117   .0000000
+    1933.40  -.132931   .166511   .0000000
+    1933.45  -.129933   .222792   .0000000
+    1933.50  -.065800   .247600   .0000000
+    1933.55  -.061257   .170077   .0000000
+    1933.60  -.092890   .168864   .0000000
+    1933.65  -.011311   .114462   .0000000
+    1933.70  -.041560   .155440   .0000000
+    1933.75  -.007268   .135250   .0000000
+    1933.80  -.048100   .064100   .0000000
+    1933.85  -.030166   .051458   .0000000
+    1933.90  -.059454   .050490   .0000000
+    1933.95  -.000334  -.055485   .0000000
+    1934.00  -.047994   .160539   .0000000
+    1934.05  -.128330   .132957   .0000000
+    1934.10  -.104712  -.032479   .0000000
+    1934.15  -.123185   .026628   .0000000
+    1934.20  -.156884   .046650   .0000000
+    1934.25  -.146878   .039678   .0000000
+    1934.30  -.212952   .066280   .0000000
+    1934.35  -.109680   .080647   .0000000
+    1934.40  -.064907   .218438   .0000000
+    1934.45  -.115818   .182058   .0000000
+    1934.50  -.093600   .146400   .0000000
+    1934.55  -.026049   .206821   .0000000
+    1934.60  -.036375   .197949   .0000000
+    1934.65  -.018200   .130900   .0000000
+    1934.70   .003251   .176660   .0000000
+    1934.75  -.019469   .192448   .0000000
+    1934.80   .016400   .142200   .0000000
+    1934.85   .017784   .028679   .0000000
+    1934.90  -.064537   .102035   .0000000
+    1934.95  -.095694   .072497   .0000000
+    1935.00  -.053671   .063917   .0000000
+    1935.05  -.169016   .020530   .0000000
+    1935.10   .005900   .019800   .0000000
+    1935.15  -.121309   .043629   .0000000
+    1935.20  -.067132   .059209   .0000000
+    1935.25  -.065954   .062433   .0000000
+    1935.30  -.066468   .107258   .0000000
+    1935.35  -.021635   .104029   .0000000
+    1935.40  -.033804   .063816   .0000000
+    1935.45  -.056658   .141422   .0000000
+    1935.50  -.052090   .108980   .0000000
+    1935.55  -.177790  -.002912   .0000000
+    1935.60  -.039043   .085087   .0000000
+    1935.65  -.133855   .062467   .0000000
+    1935.70  -.005002   .093252   .0000000
+    1935.75  -.055390   .041687   .0000000
+    1935.80  -.109561   .035449   .0000000
+    1935.85  -.173680   .091852   .0000000
+    1935.90  -.136077   .056437   .0000000
+    1935.95  -.015578   .047611   .0000000
+    1936.00   .023251   .090679   .0000000
+    1936.05  -.146877   .108152   .0000000
+    1936.10  -.047500   .098500   .0000000
+    1936.15  -.125964   .209295   .0000000
+    1936.20  -.159573   .182595   .0000000
+    1936.25  -.106700   .188100   .0000000
+    1936.30  -.080483   .175745   .0000000
+    1936.35  -.093917   .159713   .0000000
+    1936.40  -.037416   .107419   .0000000
+    1936.45   .060450   .167046   .0000000
+    1936.50  -.013617   .143961   .0000000
+    1936.55  -.000451   .115066   .0000000
+    1936.60  -.004315   .072471   .0000000
+    1936.65  -.043164   .033288   .0000000
+    1936.70  -.018826   .032928   .0000000
+    1936.75  -.074570  -.007560   .0000000
+    1936.80  -.106024  -.004717   .0000000
+    1936.85  -.100771  -.011306   .0000000
+    1936.90  -.188334   .029368   .0000000
+    1936.95  -.173300  -.047400   .0000000
+    1937.00  -.140145   .085152   .0000000
+    1937.05  -.193481   .094688   .0000000
+    1937.10  -.158811   .074182   .0000000
+    1937.15  -.245489   .179964   .0000000
+    1937.20  -.176313   .131564   .0000000
+    1937.25  -.121499   .208926   .0000000
+    1937.30  -.116696   .187814   .0000000
+    1937.35  -.040102   .222305   .0000000
+    1937.40  -.088573   .195445   .0000000
+    1937.45   .035320   .209660   .0000000
+    1937.50   .073386   .231432   .0000000
+    1937.55   .069100   .137800   .0000000
+    1937.60   .090711   .121711   .0000000
+    1937.65   .056677   .054539   .0000000
+    1937.70   .047138   .041472   .0000000
+    1937.75  -.015251  -.021479   .0000000
+    1937.80  -.008680  -.029054   .0000000
+    1937.85  -.107027  -.071074   .0000000
+    1937.90  -.105060  -.016349   .0000000
+    1937.95  -.217410  -.006067   .0000000
+    1938.00  -.204894   .021733   .0000000
+    1938.05  -.303156   .013057   .0000000
+    1938.10  -.147755   .071361   .0000000
+    1938.15  -.221442   .102093   .0000000
+    1938.20  -.226757   .130364   .0000000
+    1938.25  -.171954   .165869   .0000000
+    1938.30  -.138432   .225318   .0000000
+    1938.35  -.116911   .287363   .0000000
+    1938.40  -.046436   .227821   .0000000
+    1938.45  -.080914   .286589   .0000000
+    1938.50   .111257   .295958   .0000000
+    1938.55   .109700   .236000   .0000000
+    1938.60   .174186   .248989   .0000000
+    1938.65   .172035   .065415   .0000000
+    1938.70   .075919   .117887   .0000000
+    1938.75   .167309   .023607   .0000000
+    1938.80   .026111  -.003055   .0000000
+    1938.85  -.037869  -.061382   .0000000
+    1938.90  -.052264  -.072478   .0000000
+    1938.95  -.134539   .030821   .0000000
+    1939.00  -.301769   .106206   .0000000
+    1939.05  -.116858  -.001150   .0000000
+    1939.10  -.213896   .044637   .0000000
+    1939.15  -.161300   .101800   .0000000
+    1939.20  -.181054   .143917   .0000000
+    1939.25  -.192526   .184454   .0000000
+    1939.30  -.119371   .187626   .0000000
+    1939.35  -.079336   .224723   .0000000
+    1939.40  -.087263   .216206   .0000000
+    1939.45  -.044976   .211200   .0000000
+    1939.50   .023086   .214921   .0000000
+    1939.55   .072500   .233900   .0000000
+    1939.60   .118411   .224190   .0000000
+    1939.65   .146657   .195121   .0000000
+    1939.70   .095496   .180767   .0000000
+    1939.75   .089672   .076885   .0000000
+    1939.80   .069378   .045780   .0000000
+    1939.85   .042361   .018571   .0000000
+    1939.90   .005289   .055015   .0000000
+    1939.95  -.058344   .043141   .0000000
+    1940.00   .027411  -.055656   .0000000
+    1940.05  -.148565  -.007660   .0000000
+    1940.10  -.249170  -.018138   .0000000
+    1940.15  -.210741   .047170   .0000000
+    1940.20  -.226589   .078515   .0000000
+    1940.25  -.290100   .142200   .0000000
+    1940.30  -.223492   .078291   .0000000
+    1940.35  -.135189   .151824   .0000000
+    1940.40  -.175712   .271518   .0000000
+    1940.45  -.063144   .235042   .0000000
+    1940.50  -.029661   .260179   .0000000
+    1940.55   .019816   .250937   .0000000
+    1940.60   .162656   .241704   .0000000
+    1940.65   .098439   .147379   .0000000
+    1940.70   .065800   .175200   .0000000
+    1940.75   .125165   .119102   .0000000
+    1940.80   .070275   .085726   .0000000
+    1940.85   .053300   .043221   .0000000
+    1940.90   .004300  -.026993   .0000000
+    1940.95  -.049213   .034742   .0000000
+    1941.00   .033843   .015616   .0000000
+    1941.05   .033262  -.034927   .0000000
+    1941.10  -.043717   .028212   .0000000
+    1941.15  -.000032   .034220   .0000000
+    1941.20   .008262   .025372   .0000000
+    1941.25  -.118927   .084292   .0000000
+    1941.30  -.183857   .100975   .0000000
+    1941.35  -.159123   .204194   .0000000
+    1941.40  -.088480   .133512   .0000000
+    1941.45  -.092443   .191571   .0000000
+    1941.50  -.062260   .120954   .0000000
+    1941.55  -.073372   .253085   .0000000
+    1941.60   .012678   .219220   .0000000
+    1941.65  -.041165   .167041   .0000000
+    1941.70  -.086224   .093311   .0000000
+    1941.75   .001683   .150415   .0000000
+    1941.80   .068909   .186888   .0000000
+    1941.85  -.028851   .102187   .0000000
+    1941.90  -.020115   .119301   .0000000
+    1941.95   .145863   .081312   .0000000
+    1942.00  -.029700   .145400   .0000000
+    1942.05  -.086609   .107756   .0000000
+    1942.10   .034025   .019905   .0000000
+    1942.15  -.065983   .120029   .0000000
+    1942.20  -.026845   .031907   .0000000
+    1942.25  -.066569   .031627   .0000000
+    1942.30  -.008392   .098245   .0000000
+    1942.35  -.012154   .089180   .0000000
+    1942.40  -.068264   .122550   .0000000
+    1942.45  -.064544   .139302   .0000000
+    1942.50  -.032732   .122930   .0000000
+    1942.55  -.007371   .174390   .0000000
+    1942.60  -.089026   .117492   .0000000
+    1942.65  -.075180   .095255   .0000000
+    1942.70  -.036158   .121535   .0000000
+    1942.75  -.075817   .122674   .0000000
+    1942.80  -.089165   .085346   .0000000
+    1942.85  -.152931   .083401   .0000000
+    1942.90  -.103187   .103300   .0000000
+    1942.95  -.039915   .183470   .0000000
+    1943.00  -.090405   .234551   .0000000
+    1943.05  -.093652   .180949   .0000000
+    1943.10  -.061971   .090993   .0000000
+    1943.15  -.080573   .145031   .0000000
+    1943.20  -.051329   .138129   .0000000
+    1943.25   .001923   .184841   .0000000
+    1943.30  -.019745   .090795   .0000000
+    1943.35   .035917   .105605   .0000000
+    1943.40   .078661   .117427   .0000000
+    1943.45   .033384   .108682   .0000000
+    1943.50   .105491   .061063   .0000000
+    1943.55  -.047847  -.001805   .0000000
+    1943.60  -.036338   .050187   .0000000
+    1943.65   .022793   .034134   .0000000
+    1943.70   .070899   .024180   .0000000
+    1943.75   .004438   .011224   .0000000
+    1943.80  -.122806   .001491   .0000000
+    1943.85  -.144327   .028604   .0000000
+    1943.90  -.120953   .074676   .0000000
+    1943.95  -.253705   .095567   .0000000
+    1944.00  -.188535   .058157   .0000000
+    1944.05  -.213170   .082626   .0000000
+    1944.10  -.133388   .103606   .0000000
+    1944.15  -.243714   .045296   .0000000
+    1944.20  -.280687   .123924   .0000000
+    1944.25  -.099857   .132270   .0000000
+    1944.30  -.102089   .098582   .0000000
+    1944.35   .034173   .068935   .0000000
+    1944.40   .052475   .180058   .0000000
+    1944.45   .204300   .170300   .0000000
+    1944.50   .174930   .065429   .0000000
+    1944.55   .236527   .061957   .0000000
+    1944.60   .208915  -.039275   .0000000
+    1944.65   .171265  -.034213   .0000000
+    1944.70   .158830  -.127515   .0000000
+    1944.75  -.041184  -.081574   .0000000
+    1944.80  -.054199  -.141045   .0000000
+    1944.85  -.122864  -.138640   .0000000
+    1944.90  -.173922  -.079180   .0000000
+    1944.95  -.266129  -.029277   .0000000
+    1945.00  -.117527   .046084   .0000000
+    1945.05  -.172366   .076642   .0000000
+    1945.10  -.218168   .119657   .0000000
+    1945.15  -.269380   .084980   .0000000
+    1945.20  -.105476   .185324   .0000000
+    1945.25  -.252149   .252063   .0000000
+    1945.30  -.119100   .283700   .0000000
+    1945.35  -.098829   .296275   .0000000
+    1945.40   .041205   .299528   .0000000
+    1945.45   .070100   .328900   .0000000
+    1945.50   .161286   .243704   .0000000
+    1945.55   .111735   .157891   .0000000
+    1945.60   .279930   .129955   .0000000
+    1945.65   .210791   .086270   .0000000
+    1945.70   .167958  -.034212   .0000000
+    1945.75   .387534  -.060857   .0000000
+    1945.80   .203824  -.175689   .0000000
+    1945.85  -.009562  -.200723   .0000000
+    1945.90   .082043  -.254725   .0000000
+    1945.95  -.167775   .011828   .0000000
+    1946.00  -.105894  -.143593   .0000000
+    1946.05  -.238800  -.143600   .0000000
+    1946.10  -.161621  -.086524   .0000000
+    1946.15  -.292120  -.032154   .0000000
+    1946.20  -.369539   .005399   .0000000
+    1946.25  -.243748   .106804   .0000000
+    1946.30  -.260700   .154700   .0000000
+    1946.35  -.227834   .263600   .0000000
+    1946.40  -.105890   .285597   .0000000
+    1946.45  -.219288   .379684   .0000000
+    1946.50  -.063112   .324947   .0000000
+    1946.55   .056826   .295929   .0000000
+    1946.60   .082673   .302031   .0000000
+    1946.65   .134672   .242569   .0000000
+    1946.70   .188918   .179805   .0000000
+    1946.75   .230337   .153795   .0000000
+    1946.80   .230653   .126700   .0000000
+    1946.85   .324003  -.014854   .0000000
+    1946.90   .083430  -.030662   .0000000
+    1946.95   .071411  -.089697   .0000000
+    1947.00   .033741  -.095143   .0000000
+    1947.05  -.003804  -.062704   .0000000
+    1947.10  -.105253  -.159077   .0000000
+    1947.15  -.140851  -.129656   .0000000
+    1947.20  -.217901  -.081483   .0000000
+    1947.25  -.204585  -.117897   .0000000
+    1947.30  -.260050   .044441   .0000000
+    1947.35  -.358491   .174358   .0000000
+    1947.40  -.202905   .152120   .0000000
+    1947.45  -.254945   .153196   .0000000
+    1947.50  -.137802   .288460   .0000000
+    1947.55  -.094877   .287150   .0000000
+    1947.60   .023089   .335301   .0000000
+    1947.65   .060945   .357002   .0000000
+    1947.70   .113078   .313539   .0000000
+    1947.75   .120020   .273848   .0000000
+    1947.80   .175924   .294753   .0000000
+    1947.85   .206992   .222458   .0000000
+    1947.90   .140099   .174866   .0000000
+    1947.95   .157648   .156590   .0000000
+    1948.00   .225955   .143369   .0000000
+    1948.05   .157129   .071959   .0000000
+    1948.10   .150055   .021583   .0000000
+    1948.15   .171585  -.019271   .0000000
+    1948.20   .145400  -.041700   .0000000
+    1948.25   .147680  -.064178   .0000000
+    1948.30   .053983  -.075038   .0000000
+    1948.35  -.045837  -.072956   .0000000
+    1948.40  -.091431  -.067958   .0000000
+    1948.45  -.076060   .010010   .0000000
+    1948.50  -.106057   .014185   .0000000
+    1948.55  -.097516   .015430   .0000000
+    1948.60  -.130026   .063326   .0000000
+    1948.65  -.136613   .110269   .0000000
+    1948.70  -.236212   .081015   .0000000
+    1948.75  -.122022   .165015   .0000000
+    1948.80  -.082996   .181422   .0000000
+    1948.85  -.102718   .194496   .0000000
+    1948.90  -.056364   .288203   .0000000
+    1948.95  -.060517   .337067   .0000000
+    1949.00  -.038708   .272547   .0000000
+    1949.05   .050766   .309560   .0000000
+    1949.10  -.036412   .244629   .0000000
+    1949.15   .092035   .269182   .0000000
+    1949.20   .117000   .151400   .0000000
+    1949.25   .167243   .119693   .0000000
+    1949.30   .167879   .072692   .0000000
+    1949.35   .134722   .072089   .0000000
+    1949.40   .145230   .001256   .0000000
+    1949.45   .089326  -.093079   .0000000
+    1949.50   .154408  -.078539   .0000000
+    1949.55   .073064  -.060780   .0000000
+    1949.60   .043289  -.033614   .0000000
+    1949.65  -.013262  -.122149   .0000000
+    1949.70  -.164254  -.145566   .0000000
+    1949.75  -.163827  -.040926   .0000000
+    1949.80  -.236686  -.074967   .0000000
+    1949.85  -.237557   .040887   .0000000
+    1949.90  -.224455   .063927   .0000000
+    1949.95  -.290753   .157252   .0000000
+    1950.00  -.220930   .287191   .0000000
+    1950.05  -.222249   .248856   .0000000
+    1950.10  -.144425   .335072   .0000000
+    1950.15  -.061597   .365805   .0000000
+    1950.20   .023935   .338761   .0000000
+    1950.25   .046105   .332438   .0000000
+    1950.30   .127597   .297890   .0000000
+    1950.35   .258100   .317900   .0000000
+    1950.40   .238376   .209297   .0000000
+    1950.45   .300481   .140257   .0000000
+    1950.50   .287564   .015981   .0000000
+    1950.55   .286892   .093660   .0000000
+    1950.60   .270451  -.079337   .0000000
+    1950.65   .258830  -.098373   .0000000
+    1950.70   .116078  -.227489   .0000000
+    1950.75  -.010608  -.232154   .0000000
+    1950.80  -.087101  -.278552   .0000000
+    1950.85  -.183732  -.306109   .0000000
+    1950.90  -.306855  -.243256   .0000000
+    1950.95  -.321363  -.117027   .0000000
+    1951.00  -.365022   .014938   .0000000
+    1951.05  -.304225   .001015   .0000000
+    1951.10  -.369566   .099280   .0000000
+    1951.15  -.378609   .229045   .0000000
+    1951.20  -.253183   .324399   .0000000
+    1951.25  -.183608   .395804   .0000000
+    1951.30  -.113043   .407480   .0000000
+    1951.35   .025400   .357400   .0000000
+    1951.40   .169217   .366203   .0000000
+    1951.45   .251730   .336817   .0000000
+    1951.50   .268771   .266485   .0000000
+    1951.55   .325834   .218909   .0000000
+    1951.60   .416116   .097318   .0000000
+    1951.65   .369300   .007200   .0000000
+    1951.70   .311161  -.128485   .0000000
+    1951.75   .291955  -.216643   .0000000
+    1951.80   .143989  -.282893   .0000000
+    1951.85   .078168  -.298582   .0000000
+    1951.90  -.072498  -.293768   .0000000
+    1951.95  -.121266  -.283286   .0000000
+    1952.00  -.228941  -.289334   .0000000
+    1952.05  -.384844  -.280973   .0000000
+    1952.10  -.425432  -.085033   .0000000
+    1952.15  -.415187   .007147   .0000000
+    1952.20  -.438050   .104950   .0000000
+    1952.25  -.373937   .199595   .0000000
+    1952.30  -.214791   .330880   .0000000
+    1952.35  -.237011   .436678   .0000000
+    1952.40  -.206498   .424479   .0000000
+    1952.45  -.114247   .462331   .0000000
+    1952.50   .053909   .452330   .0000000
+    1952.55   .152162   .415113   .0000000
+    1952.60   .302914   .389455   .0000000
+    1952.65   .303583   .272217   .0000000
+    1952.70   .379665   .235664   .0000000
+    1952.75   .284255   .115197   .0000000
+    1952.80   .290673   .004058   .0000000
+    1952.85   .273678  -.093103   .0000000
+    1952.90   .201204  -.160920   .0000000
+    1952.95   .092473  -.181244   .0000000
+    1953.00   .123811  -.231433   .0000000
+    1953.05  -.059768  -.287803   .0000000
+    1953.10  -.099969  -.181194   .0000000
+    1953.15  -.117820  -.081862   .0000000
+    1953.20  -.288724  -.112507   .0000000
+    1953.25  -.256646  -.080086   .0000000
+    1953.30  -.275672   .047975   .0000000
+    1953.35  -.343300   .172800   .0000000
+    1953.40  -.325734   .244282   .0000000
+    1953.45  -.275838   .294124   .0000000
+    1953.50  -.079095   .448538   .0000000
+    1953.55  -.029260   .528535   .0000000
+    1953.60   .021387   .421200   .0000000
+    1953.65   .022300   .491500   .0000000
+    1953.70   .219443   .448367   .0000000
+    1953.75   .204160   .288329   .0000000
+    1953.80   .197400   .214300   .0000000
+    1953.85   .224082   .155717   .0000000
+    1953.90   .236336   .022065   .0000000
+    1953.95   .184200   .032600   .0000000
+    1954.00   .136603  -.090735   .0000000
+    1954.05   .015320  -.126354   .0000000
+    1954.10   .036575  -.126953   .0000000
+    1954.15  -.024887  -.150786   .0000000
+    1954.20  -.154021  -.147087   .0000000
+    1954.25  -.164556  -.108061   .0000000
+    1954.30  -.195623  -.112539   .0000000
+    1954.35  -.239513  -.079926   .0000000
+    1954.40  -.212137   .053878   .0000000
+    1954.45  -.133960   .116843   .0000000
+    1954.50  -.215416   .144317   .0000000
+    1954.55  -.127059   .218349   .0000000
+    1954.60  -.161882   .209542   .0000000
+    1954.65   .022753   .272072   .0000000
+    1954.70  -.093222   .296413   .0000000
+    1954.75  -.075965   .339411   .0000000
+    1954.80   .010000   .310600   .0000000
+    1954.85  -.019012   .279865   .0000000
+    1954.90  -.029023   .206222   .0000000
+    1954.95   .099499   .204533   .0000000
+    1955.00   .017291   .175152   .0000000
+    1955.05   .124344   .144779   .0000000
+    1955.10   .029988   .049576   .0000000
+    1955.15   .124568   .140522   .0000000
+    1955.20   .158988   .106674   .0000000
+    1955.25   .105321   .083753   .0000000
+    1955.30   .046473  -.027556   .0000000
+    1955.35   .065044  -.038566   .0000000
+    1955.40   .041687  -.021509   .0000000
+    1955.45  -.001269  -.080686   .0000000
+    1955.50  -.055935  -.006263   .0000000
+    1955.55   .003124   .039639   .0000000
+    1955.60  -.109785   .034162   .0000000
+    1955.65  -.137337   .039769   .0000000
+    1955.70  -.226992   .043228   .0000000
+    1955.75  -.229553   .066146   .0000000
+    1955.80  -.219600   .137300   .0000000
+    1955.85  -.189281   .159204   .0000000
+    1955.90  -.219306   .167037   .0000000
+    1955.95  -.203131   .233918   .0000000
+    1956.00  -.070247   .341707   .0000000
+    1956.05  -.007398   .192673   .0000000
+    1956.10   .016713   .339190   .0000000
+    1956.15   .038798   .279099   .0000000
+    1956.20   .117409   .334384   .0000000
+    1956.25   .083759   .248766   .0000000
+    1956.30   .152189   .209354   .0000000
+    1956.35   .160798   .161261   .0000000
+    1956.40   .211912   .132122   .0000000
+    1956.45   .219468   .113755   .0000000
+    1956.50   .212688   .021181   .0000000
+    1956.55   .169132  -.055280   .0000000
+    1956.60   .146149   .000797   .0000000
+    1956.65   .059496  -.049301   .0000000
+    1956.70   .018377  -.044723   .0000000
+    1956.75  -.050507  -.037579   .0000000
+    1956.80  -.204692  -.059809   .0000000
+    1956.85  -.228535   .004844   .0000000
+    1956.90  -.318792   .068497   .0000000
+    1956.95  -.290530   .108736   .0000000
+    1957.00  -.401787   .175879   .0000000
+    1957.05  -.340710   .217146   .0000000
+    1957.10  -.222754   .314496   .0000000
+    1957.15  -.224552   .381610   .0000000
+    1957.20  -.194858   .441895   .0000000
+    1957.25  -.099300   .411100   .0000000
+    1957.30   .007920   .425095   .0000000
+    1957.35   .076323   .453030   .0000000
+    1957.40   .152477   .481943   .0000000
+    1957.45   .235240   .383132   .0000000
+    1957.50   .240076   .308449   .0000000
+    1957.55   .292684   .272059   .0000000
+    1957.60   .345486   .208463   .0000000
+    1957.65   .271110   .018347   .0000000
+    1957.70   .229000  -.058924   .0000000
+    1957.75   .126351  -.051070   .0000000
+    1957.80   .039747  -.126282   .0000000
+    1957.85  -.003182  -.164541   .0000000
+    1957.90  -.069900  -.130259   .0000000
+    1957.95  -.209601  -.084401   .0000000
+    1958.00  -.305232  -.027916   .0000000
+    1958.05  -.343994   .036549   .0000000
+    1958.10  -.333001   .173344   .0000000
+    1958.15  -.335927   .215384   .0000000
+    1958.20  -.305676   .288831   .0000000
+    1958.25  -.300800   .338700   .0000000
+    1958.30  -.179030   .409116   .0000000
+    1958.35  -.101308   .407552   .0000000
+    1958.40  -.041921   .434062   .0000000
+    1958.45   .051783   .422110   .0000000
+    1958.50   .098517   .451402   .0000000
+    1958.55   .180900   .370800   .0000000
+    1958.60   .203233   .334686   .0000000
+    1958.65   .303286   .248765   .0000000
+    1958.70   .276253   .146280   .0000000
+    1958.75   .267226   .075078   .0000000
+    1958.80   .266128   .119921   .0000000
+    1958.85   .213073  -.055607   .0000000
+    1958.90   .164238  -.060513   .0000000
+    1958.95   .101815  -.044255   .0000000
+    1959.00   .016105  -.129490   .0000000
+    1959.05  -.095165  -.054368   .0000000
+    1959.10  -.153168  -.068371   .0000000
+    1959.15  -.195475  -.058794   .0000000
+    1959.20  -.253927   .017351   .0000000
+    1959.25  -.238076   .061599   .0000000
+    1959.30  -.240657   .198641   .0000000
+    1959.35  -.252739   .262649   .0000000
+    1959.40  -.214144   .308577   .0000000
+    1959.45  -.142987   .396049   .0000000
+    1959.50  -.037927   .401546   .0000000
+    1959.55  -.034800   .382000   .0000000
+    1959.60   .106849   .415365   .0000000
+    1959.65   .129032   .368627   .0000000
+    1959.70   .175804   .336333   .0000000
+    1959.75   .222541   .303817   .0000000
+    1959.80   .203199   .215274   .0000000
+    1959.85   .202366   .197922   .0000000
+    1959.90   .175341   .085444   .0000000
+    1959.95   .132030   .058528   .0000000
+    1960.00   .008173   .006252   .0000000
+    1960.05  -.003037  -.014016   .0000000
+    1960.10  -.096783  -.064746   .0000000
+    1960.15  -.049029  -.015531   .0000000
+    1960.20  -.070352   .005059   .0000000
+    1960.25  -.093472  -.033430   .0000000
+    1960.30  -.144743   .036124   .0000000
+    1960.35  -.136289   .091137   .0000000
+    1960.40  -.185600   .139573   .0000000
+    1960.45  -.144215   .156992   .0000000
+    1960.50  -.093892   .234106   .0000000
+    1960.55  -.141900   .251100   .0000000
+    1960.60  -.082108   .224170   .0000000
+    1960.65  -.054888   .246897   .0000000
+    1960.70   .000500   .272000   .0000000
+    1960.75   .027616   .261292   .0000000
+    1960.80   .028359   .217569   .0000000
+    1960.85  -.026324   .268219   .0000000
+    1960.90   .045255   .178998   .0000000
+    1960.95   .018041   .148022   .0000000
+    1961.00  -.010002   .178091   .0000000
+    1961.05   .014227   .129318   .0000000
+    1961.10  -.034519   .135146   .0000000
+    1961.15   .020541   .071804   .0000000
+    1961.20  -.008860   .093978   .0000000
+    1961.25  -.009493   .077921   .0000000
+    1961.30  -.013247   .104033   .0000000
+    1961.35  -.011871   .106863   .0000000
+    1961.40  -.055595   .050930   .0000000
+    1961.45  -.006478   .093211   .0000000
+    1961.50  -.052932   .075634   .0000000
+    1961.55  -.008206   .085606   .0000000
+    1961.60  -.051487   .123137   .0000000
+    1961.65  -.017757   .095707   .0000000
+    1961.70  -.062010   .097662   .0000000
+    1961.75  -.081090   .089862   .0000000
+    1961.80  -.110423   .077764   .0000000
+    1961.85  -.090300   .114700   .0000000
+    1961.90  -.167482   .169747   .0000000
+    1961.95  -.142626   .162677   .0000000
+    1962.00  -.033900   .203700   .0376300
+    1962.05  -.050170   .211840   .0338900
+    1962.10  -.002320   .229940   .0290470
+    1962.15   .006920   .252420   .0240100
+    1962.20   .024920   .267420   .0164880
+    1962.25   .036710   .249550   .0102410
+    1962.30   .072420   .225380  -.0005960
+    1962.35   .094690   .208290  -.0104660
+    1962.40   .093250   .193210  -.0187080
+    1962.45   .107960   .129190  -.0156280
+    1962.50   .095310   .127660  -.0096470
+    1962.55   .086920   .113560   .0013710
+    1962.60   .069240   .063740   .0066930
+    1962.65   .055400   .049150   .0122100
+    1962.70   .008500   .041810   .0142490
+    1962.75  -.014150   .060290   .0105620
+    1962.80  -.066110   .050990   .0038340
+    1962.85  -.113040   .105830  -.0066870
+    1962.90  -.153970   .139440  -.0175860
+    1962.95  -.160030   .176030  -.0286510
+    1963.00  -.205590   .212120  -.0332190
+    1963.05  -.201720   .264370  -.0339840
+    1963.10  -.173000   .287920  -.0309280
+    1963.15  -.148670   .335970  -.0308550
+    1963.20  -.099870   .335960  -.0392730
+    1963.25  -.044310   .360350  -.0507330
+    1963.30   .021450   .354760  -.0615850
+    1963.35   .093210   .324570  -.0762480
+    1963.40   .152910   .306570  -.0852720
+    1963.45   .175600   .263720  -.0898040
+    1963.50   .230800   .226120  -.0911400
+    1963.55   .218840   .193180  -.0850800
+    1963.60   .207420   .115940  -.0800220
+    1963.65   .148670   .085350  -.0829150
+    1963.70   .096090   .028620  -.0876470
+    1963.75   .053710  -.010670  -.0974610
+    1963.80  -.017030  -.023980  -.1141360
+    1963.85  -.106000  -.008970  -.0370110
+    1963.90  -.162800   .001510  -.0481380
+    1963.95  -.172400   .042730  -.0669830
+    1964.00  -.225800   .073470  -.0808460
+    1964.05  -.277190   .142370  -.0959270
+    1964.10  -.316290   .213450  -.1133170
+    1964.15  -.278600   .281690  -.1248710
+    1964.20  -.246040   .323490  -.1403400
+    1964.25  -.179450   .390780  -.0597570
+    1964.30  -.106780   .417820  -.0730700
+    1964.35  -.051130   .465850  -.0918930
+    1964.40  -.000180   .454570  -.1099970
+    1964.45   .070820   .457390  -.1212000
+    1964.50   .122250   .410720  -.1147420
+    1964.55   .188300   .371690  -.1164510
+    1964.60   .233650   .317960  -.1142910
+    1964.65   .243950   .251720  -.1118720
+    1964.70   .228520   .159640  -.0165730
+    1964.75   .202930   .093010  -.0291840
+    1964.80   .163200   .037870  -.0476800
+    1964.85   .107390   .018400  -.0671060
+    1964.90   .042310  -.014260  -.0837400
+    1964.95  -.022710  -.019620  -.1003350
+    1965.00  -.089890  -.005080  -.0182700
+    1965.05  -.109340  -.011770  -.0248210
+    1965.10  -.187520   .079690  -.0413790
+    1965.15  -.220180   .108850  -.0595530
+    1965.20  -.239960   .170890   .0201840
+    1965.25  -.239880   .232370  -.0057010
+    1965.30  -.221390   .286720  -.0330600
+    1965.35  -.177010   .329310  -.0487050
+    1965.40  -.151550   .380270  -.0661190
+    1965.45  -.115410   .406270  -.0832370
+    1965.50  -.033960   .439390   .0111050
+    1965.55   .047390   .425360   .0060030
+    1965.60   .084440   .411480  -.0046230
+    1965.65   .105520   .371940  -.0087120
+    1965.70   .137420   .304360   .0758570
+    1965.75   .168630   .248710   .0544290
+    1965.80   .200590   .176560   .0353090
+    1965.85   .178810   .143930   .0119610
+    1965.90   .158060   .087030  -.0139660
+    1965.95   .115300   .054420  -.0327310
+    1966.00   .047900   .005530  -.0467430
+    1966.05   .003210   .018400  -.0442320
+    1966.10  -.020370   .017330  -.0397280
+    1966.15  -.092720   .042830  -.0398940
+    1966.20  -.126630   .060540  -.0393290
+    1966.25  -.126250   .087680  -.0396900
+    1966.30  -.167720   .130720  -.0463990
+    1966.35  -.161730   .172470  -.0516050
+    1966.40  -.151510   .196200  -.0495510
+    1966.45  -.128550   .234880  -.0432800
+    1966.50  -.124150   .306450  -.0321410
+    1966.55  -.081600   .310620  -.0125560
+    1966.60  -.055550   .328730   .0003880
+    1966.65  -.017090   .338450   .0095020
+    1966.70   .006590   .333040   .0161450
+    1966.75   .042120   .311320   .0146070
+    1966.80   .091960   .283830   .0121820
+    1966.85   .094580   .252760   .0098330
+    1966.90   .116210   .220110   .0051870
+    1966.95   .135490   .172910   .0058710
+    1967.00   .097100   .162300   .0124750
+    1967.05   .070010   .139910   .0184380
+    1967.10   .048010   .130910   .0211400
+    1967.15   .032320   .139020   .0229620
+    1967.20   .014320   .136220   .0194950
+    1967.25   .005330   .130830   .0167670
+    1967.30  -.008570   .144330   .0133100
+    1967.35  -.013670   .164530   .0065720
+    1967.40  -.008560   .148640   .0071750
+    1967.45   .003850   .168250   .0176880
+    1967.50  -.011850   .176050   .0301300
+    1967.55  -.008350   .193960   .0477730
+    1967.60  -.011740   .189260   .0663160
+    1967.65  -.001430   .186370   .0768980
+    1967.70  -.029530   .191370   .0890110
+    1967.75  -.033830   .184480   .0963740
+    1967.80  -.030620   .195580   .0971770
+    1967.85  -.035120   .205980   .0953500
+    1967.90  -.026910   .212290   .0952730
+    1967.95  -.026200   .222600   .0931660
+    1968.00  -.034000   .239700   .0951090
+    1968.05  -.005100   .237510   .0987210
+    1968.10  -.004790   .238810  -.0023360
+    1968.15  -.001680   .237720  -.0036230
+    1968.20   .030920   .241420  -.0012590
+    1968.25   .015230   .230330  -.0024360
+    1968.30   .046430   .242330  -.0107430
+    1968.35   .060630   .223740  -.0118800
+    1968.40   .057340   .203640  -.0136970
+    1968.45   .059250   .198750  -.0100140
+    1968.50   .068150   .173950   .0057390
+    1968.55   .067460   .166360   .0170720
+    1968.60   .052060   .142860   .0302750
+    1968.65   .027070   .135670   .0354390
+    1968.70   .005570   .135770   .0390020
+    1968.75  -.013830   .118780   .0406750
+    1968.80  -.042020   .106380   .0419680
+    1968.85  -.084920   .124390   .0356310
+    1968.90  -.139410   .147490   .0341150
+    1968.95  -.126810   .185200   .0350180
+    1969.00  -.139900   .214900   .0335710
+    1969.05  -.124100   .251100   .0372640
+    1969.10  -.106290   .262510   .0391280
+    1969.15  -.095880   .326120   .0309210
+    1969.20  -.079080   .337320   .0246540
+    1969.25  -.036380   .347630   .0124870
+    1969.30  -.000970   .351930   .0000710
+    1969.35   .055030   .361340  -.0043960
+    1969.40   .090640   .316240  -.0064830
+    1969.45   .125150   .295450  -.0097100
+    1969.50   .133450   .267750   .0040040
+    1969.55   .150150   .228760   .0133570
+    1969.60   .134960   .187660   .0232700
+    1969.65   .117370   .136570   .0362230
+    1969.70   .095770   .114170   .0343170
+    1969.75   .058680   .100680   .0285300
+    1969.80   .011380   .065480   .0246530
+    1969.85  -.011720   .063480   .0178860
+    1969.90  -.062210   .070390   .0119090
+    1969.95  -.122410   .082300   .0067420
+    1970.00  -.163200   .117800   .0047260
+    1970.05  -.200400   .175210  -.0043710
+    1970.10  -.217990   .213110  -.0072880
+    1970.15  -.167580   .287720  -.0178350
+    1970.20  -.155880   .325820  -.0272820
+    1970.25  -.140180   .357830  -.0373190
+    1970.30  -.092070   .388230  -.0515660
+    1970.35  -.036570   .394540  -.0614930
+    1970.40   .009940   .407740  -.0624500
+    1970.45   .077750   .394750  -.0622170
+    1970.50   .130150   .370950  -.0542940
+    1970.55   .166660   .330060  -.0435010
+    1970.60   .200960   .262860  -.0298880
+    1970.65   .205070   .222970  -.0204550
+    1970.70   .196270   .160070  -.0125620
+    1970.75   .178680   .101880  -.0144890
+    1970.80   .141580   .043980  -.0185570
+    1970.85   .064680   .026980  -.0256240
+    1970.90   .013790   .006190  -.0358210
+    1970.95  -.045910  -.008500  -.0395080
+    1971.00  -.094800   .014300  -.0386560
+    1971.05  -.145000   .063100  -.0423130
+    1971.10  -.193590   .108210  -.0417900
+    1971.15  -.226190   .164220  -.0385280
+    1971.20  -.248080   .221720  -.0447450
+    1971.25  -.221480   .298620  -.0573030
+    1971.30  -.200070   .353230  -.0652400
+    1971.35  -.187870   .384540  -.0779880
+    1971.40  -.131860   .428740  -.0875360
+    1971.45  -.046460   .458050  -.0888030
+    1971.50   .029850   .466050  -.0875110
+    1971.55   .104850   .444960  -.0828490
+    1971.60   .162960   .400160  -.0790560
+    1971.65   .211970   .361270  -.0778240
+    1971.70   .233970   .304470  -.0821020
+    1971.75   .225880   .218780  -.0877900
+    1971.80   .208880   .167780  -.1047780
+    1971.85   .181790   .101490  -.1220760
+    1971.90   .140590   .071290  -.1384440
+    1971.95   .084400   .039100  -.1490720
+    1972.00   .031820   .019710  -.0474900
+    1972.05  -.029350   .019540  -.1025340
+    1972.10  -.085000   .023390  -.1641870
+    1972.15  -.113320   .038780  -.2239540
+    1972.20  -.170800   .100130  -.2844970
+    1972.25  -.178190   .157660  -.3489940
+    1972.30  -.193440   .216340  -.4137270
+    1972.35  -.177900   .273960  -.4751870
+    1972.40  -.148990   .302730  -.5400640
+    1972.45  -.101340   .350600  -.5937930
+    1972.50  -.048730   .379110   .3591600
+    1972.55   .000850   .403050   .3124850
+    1972.60   .057740   .404590   .2662670
+    1972.65   .089870   .408890   .2208620
+    1972.70   .119360   .367470   .1685090
+    1972.75   .125150   .330830   .1107640
+    1972.80   .161790   .292310   .0507720
+    1972.85   .164080   .229730  -.0089650
+    1972.90   .154490   .213280  -.0670860
+    1972.95   .142830   .172430  -.1269170
+    1973.00   .123610   .125710   .8114390
+    1973.05   .091980   .093390   .7545430
+    1973.10   .055100   .086390   .6973530
+    1973.15   .024830   .089030   .6317400
+    1973.20  -.023270   .093100   .5731350
+    1973.25  -.050430   .105840   .5070570
+    1973.30  -.090950   .145940   .4422160
+    1973.35  -.107840   .174450   .3817300
+    1973.40  -.116560   .201930   .3252920
+    1973.45  -.109350   .245230   .2701480
+    1973.50  -.097490   .273170   .2259990
+    1973.55  -.074020   .300780   .1814520
+    1973.60  -.053250   .315260   .1350890
+    1973.65  -.014030   .319880   .0897480
+    1973.70   .014500   .323150   .0381470
+    1973.75   .034570   .333410  -.0166510
+    1973.80   .069270   .331530  -.0721010
+    1973.85   .082930   .288210  -.1313010
+    1973.90   .094550   .270630  -.1950090
+    1973.95   .105000   .265120  -.2487100
+    1974.00   .113200   .225230   .7002310
+    1974.05   .091980   .203370   .6520660
+    1974.10   .077870   .176520   .6063570
+    1974.15   .078890   .171530   .5537260
+    1974.20   .050750   .157750   .4983770
+    1974.25   .029950   .179730   .4438800
+    1974.30   .029220   .187280   .3871170
+    1974.35   .015470   .182320   .3220300
+    1974.40   .005080   .179910   .2706650
+    1974.45  -.016260   .187160   .2230120
+    1974.50   .019490   .195670   .1828640
+    1974.55   .022340   .210720   .1474170
+    1974.60   .019950   .212310   .1109470
+    1974.65   .016610   .209630   .0663730
+    1974.70   .010980   .202280   .0252920
+    1974.75   .003730   .216240  -.0251410
+    1974.80  -.012130   .232720  -.0802570
+    1974.85  -.024480   .240310  -.1325930
+    1974.90  -.033410   .254200  -.1905590
+    1974.95  -.043730   .267890  -.2441870
+    1975.00  -.050120   .270650   .7083150
+    1975.05  -.053700   .285590   .6585310
+    1975.10  -.030920   .306400   .6055510
+    1975.15  -.019500   .329540   .5525990
+    1975.20   .010660   .335300   .5013940
+    1975.25   .043890   .337490   .4422900
+    1975.30   .070800   .313520   .3887900
+    1975.35   .089170   .296380   .3321200
+    1975.40   .103620   .270190   .2824180
+    1975.45   .125630   .246550   .2386220
+    1975.50   .146030   .234320   .1972230
+    1975.55   .132900   .199120   .1637560
+    1975.60   .126320   .176400   .1307220
+    1975.65   .119740   .152660   .0878550
+    1975.70   .092300   .118640   .0444550
+    1975.75   .062280   .103450  -.0020730
+    1975.80   .020950   .098770  -.0586960
+    1975.85  -.041700   .103980  -.1161850
+    1975.90  -.072420   .130280  -.1711520
+    1975.95  -.127410   .157660  -.2229470
+    1976.00  -.144340   .193270   .7251490
+    1976.05  -.151500   .247180   .6775030
+    1976.10  -.156180   .289100   .6214200
+    1976.15  -.145290   .329230   .5693700
+    1976.20  -.117400   .367510   .5147140
+    1976.25  -.095400   .393190   .4538780
+    1976.30  -.041730   .425870   .3908040
+    1976.35  -.008800   .433170   .3343790
+    1976.40   .046660   .423870   .2739120
+    1976.45   .111730   .401030   .2245910
+    1976.50   .156480   .370970   .1856130
+    1976.55   .195270   .330200   .1405230
+    1976.60   .229060   .289950   .0972370
+    1976.65   .235790   .241180   .0569540
+    1976.70   .220780   .189190   .0056210
+    1976.75   .172600   .157950  -.0542780
+    1976.80   .159550   .117960  -.1129530
+    1976.85   .113500   .093390  -.1756720
+    1976.90   .053590   .071240  -.2292200
+    1976.95  -.004070   .065610  -.2824520
+    1977.00  -.068560   .069220   .6657090
+    1977.05  -.139290   .118540   .6143360
+    1977.10  -.188740   .156640   .5651410
+    1977.15  -.226790   .231150   .5121100
+    1977.20  -.228460   .290850   .4600880
+    1977.25  -.216780   .362450   .4021850
+    1977.30  -.174880   .414280   .3418380
+    1977.35  -.133880   .458560   .2827490
+    1977.40  -.071690   .489080   .2309290
+    1977.45   .012030   .504510   .1838870
+    1977.50   .082770   .495390   .1468180
+    1977.55   .149380   .454360   .1142770
+    1977.60   .210730   .410780   .0768320
+    1977.65   .249250   .351780   .0408590
+    1977.70   .269380   .292600  -.0085350
+    1977.75   .263020   .222970  -.0636710
+    1977.80   .243710   .151260  -.1196200
+    1977.85   .195430   .095930  -.1771710
+    1977.90   .133680   .061560  -.2363140
+    1977.95   .063460   .030340  -.2912280
+    1978.00  -.000350   .027050   .6495220
+    1978.05  -.067600   .036990   .5903240
+    1978.10  -.136660   .072860   .5357610
+    1978.15  -.182100   .105900   .4701360
+    1978.20  -.214500   .163140   .4061470
+    1978.25  -.236230   .234600   .3442840
+    1978.30  -.229900   .312160   .2835510
+    1978.35  -.200940   .379730   .2243820
+    1978.40  -.157910   .433860   .1677820
+    1978.45  -.110240   .468530   .1209930
+    1978.50  -.044260   .492280   .0799780
+    1978.55   .033760   .496900   .0461430
+    1978.60   .098530   .478150   .0128410
+    1978.65   .150640   .444140  -.0312900
+    1978.70   .194320   .408640  -.0754340
+    1978.75   .221790   .353150  -.1252120
+    1978.80   .234780   .290520  -.1826230
+    1978.85   .228930   .229200  -.2362770
+    1978.90   .196110   .176960  -.2927440
+    1978.95   .169350   .117020  -.3501350
+    1979.00   .140600   .085500   .5990550
+    1979.05   .098400   .059560   .5436940
+    1979.10   .023200   .064460   .4873690
+    1979.15  -.017580   .069020   .4372970
+    1979.20  -.067290   .087350   .3838980
+    1979.25  -.111680   .125490   .3253590
+    1979.30  -.137550   .174350   .2698590
+    1979.35  -.152140   .218350   .2124640
+    1979.40  -.158240   .263800   .1596610
+    1979.45  -.145410   .301690   .1196450
+    1979.50  -.120340   .348910   .0786440
+    1979.55  -.093020   .378590   .0405690
+    1979.60  -.032280   .404160   .0082610
+    1979.65   .013040   .420310  -.0308800
+    1979.70   .053770   .423000  -.0723390
+    1979.75   .087730   .410920  -.1151000
+    1979.80   .103920   .386840  -.1669670
+    1979.85   .133930   .357770  -.2160390
+    1979.90   .132630   .322640  -.2606420
+    1979.95   .135250   .285040  -.3086520
+    1980.00   .142150   .250260   .6449390
+    1980.05   .121150   .224530   .5994770
+    1980.10   .089390   .199240   .5548120
+    1980.15   .064250   .182700   .5085250
+    1980.20   .043590   .179240   .4666600
+    1980.25   .012160   .187460   .4165130
+    1980.30  -.020440   .201760   .3666940
+    1980.35  -.043480   .221870   .3219240
+    1980.40  -.052250   .240890   .2763230
+    1980.45  -.054760   .259160   .2387700
+    1980.50  -.051620   .282750   .2063630
+    1980.55  -.039350   .301970   .1755970
+    1980.60  -.035550   .314750   .1452760
+    1980.65  -.030090   .328120   .1151990
+    1980.70  -.030200   .337170   .0750790
+    1980.75  -.023160   .345640   .0300980
+    1980.80  -.012370   .358870  -.0127940
+    1980.85   .000830   .366600  -.0624580
+    1980.90   .022640   .373160  -.1078580
+    1980.95   .049120   .373030  -.1500100
+    1981.00   .070580   .360660  -.1953270
+    1981.05   .077000   .348400  -.2391430
+    1981.10   .089260   .329090  -.2776990
+    1981.15   .084840   .315780  -.3202690
+    1981.20   .090210   .304230  -.3727280
+    1981.25   .101630   .289720  -.4159950
+    1981.30   .096310   .268760  -.4685540
+    1981.35   .093750   .257220  -.5165520
+    1981.40   .090250   .241670  -.5587390
+    1981.45   .078570   .226280  -.6009320
+    1981.50   .068150   .210210   .3698510
+    1981.55   .059540   .193490   .3498320
+    1981.60   .033080   .184820   .3198500
+    1981.65   .004150   .185370   .2918900
+    1981.70  -.024140   .193490   .2653000
+    1981.75  -.060920   .209640   .2228820
+    1981.80  -.084890   .235550   .1804970
+    1981.85  -.104520   .264190   .1393580
+    1981.90  -.110340   .298730   .0957520
+    1981.95  -.112180   .336860   .0571520
+    1982.00  -.093080   .376820   .0184280
+    1982.05  -.056710   .406900  -.0233770
+    1982.10  -.029250   .429470  -.0576400
+    1982.15   .016930   .440390  -.0968960
+    1982.20   .062800   .438790  -.1429420
+    1982.25   .108360   .429570  -.1860770
+    1982.30   .144250   .410160  -.2324500
+    1982.35   .175760   .379360  -.2826500
+    1982.40   .202440   .335180  -.3212050
+    1982.45   .227390   .284220  -.3589540
+    1982.50   .225400   .235390   .6073090
+    1982.55   .211690   .183440   .5824430
+    1982.60   .188000   .139540   .5595280
+    1982.65   .147580   .100920   .5266190
+    1982.70   .090980   .077680   .4890550
+    1982.75   .028040   .068920   .4484150
+    1982.80  -.036070   .079650   .4039600
+    1982.85  -.092580   .099410   .3645380
+    1982.90  -.143280   .139280   .3204710
+    1982.95  -.184870   .194480   .2722880
+    1983.00  -.202510   .257960   .2276730
+    1983.05  -.208590   .319420   .1807080
+    1983.10  -.188080   .386630   .1215960
+    1983.15  -.166980   .446850   .0712980
+    1983.20  -.130670   .499770   .0173990
+    1983.25  -.060990   .541150  -.0393690
+    1983.30   .018010   .561080  -.0893990
+    1983.35   .089520   .551750  -.1353850
+    1983.40   .165160   .528540  -.1815520
+    1983.45   .220450   .481900  -.2193950
+    1983.50   .270130   .421220   .7475800
+    1983.55   .307330   .346400   .7215090
+    1983.60   .323430   .271320   .6952120
+    1983.65   .311990   .193620   .6642850
+    1983.70   .270820   .123360   .6298510
+    1983.75   .212870   .065270   .5983220
+    1983.80   .144260   .027540   .5583590
+    1983.85   .061990   .014950   .5132280
+    1983.90  -.016890   .026220   .4716860
+    1983.95  -.085210   .050470   .4337780
+    1984.00  -.133280   .091680   .3954610
+    1984.05  -.178600   .145720   .3663980
+    1984.10  -.217680   .203540   .3393920
+    1984.15  -.239790   .267220   .3071050
+    1984.20  -.240330   .342950   .2769000
+    1984.25  -.215180   .414620   .2386810
+    1984.30  -.165880   .478570   .2012160
+    1984.35  -.103940   .529520   .1686240
+    1984.40  -.036610   .557690   .1381370
+    1984.45   .043530   .559030   .1142480
+    1984.50   .118910   .544370   .0977110
+    1984.55   .192030   .505220   .0854250
+    1984.60   .256550   .452690   .0683640
+    1984.65   .294920   .386890   .0497870
+    1984.70   .308190   .317250   .0228220
+    1984.75   .311850   .246370  -.0075050
+    1984.80   .284570   .180700  -.0363910
+    1984.85   .247250   .123390  -.0715010
+    1984.90   .198900   .081750  -.1028830
+    1984.95   .127310   .041390  -.1301440
+    1985.00   .045080   .022560  -.1575460
+    1985.05  -.021710   .036290  -.1889130
+    1985.10  -.079030   .063220  -.2116370
+    1985.15  -.133690   .102890  -.2407380
+    1985.20  -.185320   .156740  -.2736890
+    1985.25  -.201050   .230230  -.3070830
+    1985.30  -.195870   .298580  -.3429910
+    1985.35  -.182010   .364520  -.3771130
+    1985.40  -.138460   .418650  -.4025590
+    1985.45  -.095300   .459340  -.4317500
+    1985.50  -.043950   .483270   .5478600
+    1985.55   .017740   .494700   .5395290
+    1985.60   .076740   .494160   .5251140
+    1985.65   .135950   .477470   .5115900
+    1985.70   .182620   .445550   .4948280
+    1985.75   .211380   .402010   .4660470
+    1985.80   .227170   .347600   .4338690
+    1985.85   .228420   .297330   .4018540
+    1985.90   .228310   .251090   .3668480
+    1985.95   .209470   .210230   .3364070
+    1986.00   .185940   .170580   .3132290
+    1986.05   .148620   .136920   .2869110
+    1986.10   .097820   .120120   .2595480
+    1986.15   .050650   .114890   .2343500
+    1986.20  -.004480   .120220   .2069080
+    1986.25  -.045110   .137800   .1831500
+    1986.30  -.074620   .174240   .1553600
+    1986.35  -.091050   .210930   .1220280
+    1986.40  -.103510   .248370   .0984900
+    1986.45  -.097870   .286570   .0863460
+    1986.50  -.071490   .325960   .0698390
+    1986.55  -.044780   .356680   .0591900
+    1986.60  -.017440   .376640   .0494220
+    1986.65   .010780   .391720   .0327720
+    1986.70   .039560   .398150   .0179060
+    1986.75   .061300   .393670  -.0068750
+    1986.80   .085600   .389850  -.0389540
+    1986.85   .108410   .379180  -.0658570
+    1986.90   .121680   .358470  -.0899120
+    1986.95   .139690   .333040  -.1163700
+    1987.00   .146260   .313070  -.1380760
+    1987.05   .139250   .286810  -.1601160
+    1987.10   .129080   .265690  -.1865420
+    1987.15   .122130   .247910  -.2129500
+    1987.20   .110320   .223500  -.2463650
+    1987.25   .094220   .212870  -.2807030
+    1987.30   .072280   .204670  -.3086560
+    1987.35   .053320   .200540  -.3362570
+    1987.40   .030170   .199490  -.3639160
+    1987.45   .015310   .199420  -.3832670
+    1987.50  -.006420   .206770  -.3985660
+    1987.55  -.025810   .218770  -.4124200
+    1987.60  -.031970   .234330  -.4193230
+    1987.65  -.037620   .254830  -.4346680
+    1987.70  -.043540   .272020  -.4584800
+    1987.75  -.055190   .296620  -.4825460
+    1987.80  -.063220   .318760  -.5129600
+    1987.85  -.060180   .341610  -.5455880
+    1987.90  -.056330   .371220  -.5748670
+    1987.95  -.049860   .395210  -.6043940
+    1988.00  -.023960   .412730   .3641980
+    1988.05   .004500   .424730   .3384500
+    1988.10   .047020   .432110   .3144130
+    1988.15   .067110   .430020   .2785320
+    1988.20   .105530   .427540   .2471970
+    1988.25   .133210   .406300   .2166860
+    1988.30   .150780   .378320   .1792750
+    1988.35   .171170   .354020   .1522840
+    1988.40   .176460   .321580   .1225530
+    1988.45   .165470   .287990   .0988100
+    1988.50   .169520   .251610   .0898640
+    1988.55   .162560   .216260   .0807490
+    1988.60   .140250   .179670   .0689520
+    1988.65   .106640   .154640   .0603010
+    1988.70   .066470   .136560   .0448510
+    1988.75   .009150   .129100   .0228930
+    1988.80  -.050020   .138100  -.0018930
+    1988.85  -.100790   .165460  -.0330640
+    1988.90  -.138410   .207940  -.0653100
+    1988.95  -.164740   .261170  -.0918720
+    1989.00  -.160800   .315200  -.1150310
+    1989.05  -.142800   .359530  -.1376110
+    1989.10  -.118060   .400480  -.1614360
+    1989.15  -.076130   .436720  -.1886810
+    1989.20  -.027240   .466260  -.2181740
+    1989.25   .029070   .480900  -.2452640
+    1989.30   .085860   .481670  -.2761340
+    1989.35   .127570   .470310  -.3109290
+    1989.40   .169220   .445260  -.3388540
+    1989.45   .204420   .412890  -.3680090
+    1989.50   .239210   .364510  -.3859960
+    1989.55   .259150   .312920  -.4009490
+    1989.60   .259400   .255620  -.4214040
+    1989.65   .250970   .197720  -.4424920
+    1989.70   .217420   .146080  -.4611150
+    1989.75   .165120   .105110  -.4903590
+    1989.80   .098020   .083150  -.5228010
+    1989.85   .031480   .074730  -.5592470
+    1989.90  -.036820   .087780  -.6014820
+    1989.95  -.090410   .118340  -.6390910
+    1990.00  -.132820   .163800   .3294770
+    1990.05  -.165870   .215080   .2971590
+    1990.10  -.202780   .276390   .2614270
+    1990.15  -.201680   .344430   .2205110
+    1990.20  -.185180   .413230   .1791940
+    1990.25  -.153910   .471710   .1351550
+    1990.30  -.101550   .524360   .0948910
+    1990.35  -.049070   .556830   .0554040
+    1990.40   .025280   .572830   .0201240
+    1990.45   .096160   .568570  -.0096640
+    1990.50   .166980   .541670  -.0403750
+    1990.55   .230520   .499990  -.0614930
+    1990.60   .276540   .439320  -.0830990
+    1990.65   .306230   .379690  -.1154370
+    1990.70   .312300   .309110  -.1458280
+    1990.75   .295990   .241750  -.1816860
+    1990.80   .258290   .178550  -.2226650
+    1990.85   .214630   .130690  -.2630650
+    1990.90   .158460   .095450  -.3023270
+    1990.95   .092590   .076290  -.3458130
+    1991.00   .023070   .070420   .6189660
+    1991.05  -.040210   .085850   .5788470
+    1991.10  -.104560   .109710   .5375110
+    1991.15  -.159350   .156090   .4982140
+    1991.20  -.193710   .215880   .4563180
+    1991.25  -.218250   .286330   .4101900
+    1991.30  -.211540   .359670   .3695240
+    1991.35  -.196100   .427740   .3269160
+    1991.40  -.148030   .487300   .2852580
+    1991.45  -.087780   .535430   .2509990
+    1991.50  -.027600   .563210   .2244370
+    1991.55   .049470   .572690   .1994110
+    1991.60   .118890   .560660   .1792000
+    1991.65   .172940   .527310   .1523860
+    1991.70   .218130   .487510   .1145380
+    1991.75   .251390   .434860   .0781450
+    1991.80   .262130   .372840   .0419620
+    1991.85   .263160   .317840   .0002900
+    1991.90   .247290   .263630  -.0397540
+    1991.95   .217400   .209210  -.0833930
+    1992.00   .183430   .168250  -.1253090
+    1992.05   .132860   .139720  -.1664230
+    1992.10   .083410   .121340  -.2133580
+    1992.15   .026850   .116920  -.2592480
+    1992.20  -.034650   .126400  -.3037880
+    1992.25  -.082680   .163990  -.3574120
+    1992.30  -.115610   .203320  -.4102900
+    1992.35  -.145550   .245630  -.4539040
+    1992.40  -.156500   .291880  -.4959850
+    1992.45  -.153110   .334650  -.5303330
+    1992.50  -.140940   .381020   .4420910
+    1992.55  -.115160   .420770   .4184490
+    1992.60  -.077490   .459320   .3892290
+    1992.65  -.031830   .492120   .3596050
+    1992.70   .014530   .506730   .3231410
+    1992.75   .055600   .503780   .2854080
+    1992.80   .103120   .494250   .2458780
+    1992.85   .137780   .473110   .1994080
+    1992.90   .170750   .444760   .1538820
+    1992.95   .187750   .406300   .1096390
+    1993.00   .208200   .361780   .0639800
+    1993.05   .212870   .311750   .0163900
+    1993.10   .205710   .265790  -.0283100
+    1993.15   .186400   .225690  -.0785000
+    1993.20   .159450   .194090  -.1275600
+    1993.25   .113650   .170110  -.1750500
+    1993.30   .065420   .163930  -.2286500
+    1993.35   .025160   .166410  -.2813400
+    1993.40  -.005520   .177900  -.3249500
+    1993.45  -.036590   .190810  -.3670900
+    1993.50  -.063740   .211350   .5975800
+    1993.55  -.073070   .234400   .5709200
+    1993.60  -.091560   .266690   .5374700
+    1993.65  -.101560   .302050   .5021000
+    1993.70  -.099970   .336910   .4679700
+    1993.75  -.095410   .370980   .4245500
+    1993.80  -.080940   .403840   .3774500
+    1993.85  -.062500   .428470   .3322200
+    1993.90  -.041250   .448950   .2851400
+    1993.95  -.019600   .464960   .2441700
+    1994.00   .009200   .476210   .2006800
+    1994.05   .054050   .478850   .1576400
+    1994.10   .099840   .467200   .1161800
+    1994.15   .137660   .448700   .0759200
+    1994.20   .158340   .421910   .0247300
+    1994.25   .175010   .390000  -.0223200
+    1994.30   .183970   .356950  -.0662200
+    1994.35   .186340   .317810  -.1154700
+    1994.40   .180670   .281910  -.1586500
+    1994.45   .160850   .243850  -.1904900
+    1994.50   .134830   .210780   .7815600
+    1994.55   .101460   .184820   .7562100
+    1994.60   .067260   .172080   .7314100
+    1994.65   .026570   .168170   .7029600
+    1994.70  -.016290   .179410   .6665200
+    1994.75  -.066370   .200140   .6249200
+    1994.80  -.106130   .232880   .5793400
+    1994.85  -.141410   .271820   .5355300
+    1994.90  -.152620   .321150   .4935800
+    1994.95  -.153790   .368190   .4476700
+    1995.00  -.153720   .418090   .3991000
+    1995.05  -.127450   .461200   .3532000
+    1995.10  -.111580   .494070   .3028200
+    1995.15  -.075420   .524080   .2573700
+    1995.20  -.022770   .546010   .2056500
+    1995.25   .035210   .558400   .1532400
+    1995.30   .092910   .555900   .1027500
+    1995.35   .162220   .532900   .0547700
+    1995.40   .209220   .497340   .0067200
+    1995.45   .254650   .443560  -.0324300
+    1995.50   .281610   .378980  -.0635800
+    1995.55   .287570   .308430  -.0926700
+    1995.60   .273820   .237780  -.1136100
+    1995.65   .237560   .179860  -.1418400
+    1995.70   .189520   .133990  -.1803800
+    1995.75   .135580   .105900  -.2213600
+    1995.80   .066650   .085830  -.2632900
+    1995.85   .002730   .084730  -.3084000
+    1995.90  -.067070   .101140  -.3533700
+    1995.95  -.138200   .136100  -.3981800
+    1996.00  -.176160   .192180   .5551900
+    1996.05  -.203930   .246410   .5221600
+    1996.10  -.223380   .312950   .4899200
+    1996.15  -.220960   .378460   .4499500
+    1996.20  -.196520   .448570   .4092600
+    1996.25  -.150870   .508690   .3699700
+    1996.30  -.101690   .553340   .3258300
+    1996.35  -.033850   .584490   .2846000
+    1996.40   .040580   .595820   .2454400
+    1996.45   .115360   .581210   .2114200
+    1996.50   .181570   .545250   .1862900
+    1996.55   .239170   .495410   .1659300
+    1996.60   .267760   .436840   .1407800
+    1996.65   .297160   .371810   .1230500
+    1996.70   .290780   .296700   .0985300
+    1996.75   .267110   .228290   .0638000
+    1996.80   .227160   .171270   .0297800
+    1996.85   .175940   .122030  -.0071800
+    1996.90   .109730   .096200  -.0441600
+    1996.95   .039500   .084250  -.0749400
+    1997.00  -.020320   .095060  -.1096500
+    1997.05  -.073030   .119750  -.1459800
+    1997.10  -.124420   .156650  -.1730900
+    1997.15  -.161820   .203960  -.2056400
+    1997.20  -.186450   .263310  -.2482000
+    1997.25  -.190710   .331710  -.2929300
+    1997.30  -.174960   .396620  -.3387100
+    1997.35  -.145010   .452930  -.3794300
+    1997.40  -.098250   .498370  -.4162300
+    1997.45  -.047990   .525350  -.4516000
+    1997.50   .023090   .536790   .5261800
+    1997.55   .088210   .526330   .5094900
+    1997.60   .141170   .505000   .4812500
+    1997.65   .181140   .467130   .4540400
+    1997.70   .216860   .428130   .4276000
+    1997.75   .221240   .378750   .3908700
+    1997.80   .226280   .329150   .3513700
+    1997.85   .214670   .278540   .3151900
+    1997.90   .190380   .234080   .2784700
+    1997.95   .151700   .201890   .2466500
+    1998.00   .103371   .174919   .2187928
+    1998.05   .051655   .167526   .1878736
+    1998.10  -.005228   .173571   .1500342
+    1998.15  -.051800   .188169   .1146000
+    1998.20  -.079308   .220212   .0745974
+    1998.25  -.110294   .254246   .0360847
+    1998.30  -.113475   .301652   .0024942
+    1998.35  -.114391   .344204  -.0345923
+    1998.40  -.107406   .383854  -.0684825
+    1998.45  -.099535   .414513  -.0887736
+    1998.50  -.065007   .440850  -.1011400
+    1998.55  -.021674   .465308  -.1082697
+    1998.60   .017316   .478858  -.1146002
+    1998.65   .058055   .476585  -.1250252
+    1998.70   .097135   .465706  -.1418293
+    1998.75   .125857   .444588  -.1587117
+    1998.80   .149956   .418823  -.1862362
+    1998.85   .163218   .388340  -.2147711
+    1998.90   .154524   .350655  -.2401730
+    1998.95   .137225   .321181  -.2653190
+    1999.00   .138906   .296108   .7168562
+    1999.05   .117532   .271385   .7014530
+    1999.10   .100290   .252373   .6791687
+    1999.15   .077098   .244566   .6561574
+    1999.20   .054921   .239895   .6399826
+    1999.25   .023809   .240618   .6145151
+    1999.30   .001100   .248865   .5879676
+    1999.35  -.017471   .262305   .5664931
+    1999.40  -.023004   .281431   .5435885
+    1999.45  -.031745   .296763   .5267825
+    1999.50  -.031910   .311187   .5198637
+    1999.55  -.024948   .330418   .5120479
+    1999.60  -.014139   .345615   .5055648
+    1999.65  -.008467   .361644   .4977768
+    1999.70   .002079   .370914   .4819857
+    1999.75   .006586   .379679   .4688203
+    1999.80   .015741   .382597   .4506114
+    1999.85   .024443   .379545   .4230946
+    1999.90   .032087   .377378   .3974911
+    1999.95   .037562   .380865   .3782104
+    2000.00   .043300   .377661   .3554817
+    2000.05   .052375   .375702   .3413574
+    2000.10   .060632   .372427   .3250578
+    2000.15   .067994   .365396   .3071171
+    2000.20   .074610   .357979   .2899885
+    2000.25   .075437   .346051   .2762541
+    2000.30   .082353   .343278   .2552646
+    2000.35   .088049   .332016   .2358447
+    2000.40   .096303   .321406   .2198842
+    2000.45   .113565   .304386   .2064913
+    2000.50   .110079   .279086   .2040804
+    2000.55   .096137   .261702   .2004203
+    2000.60   .083088   .248498   .1987985
+    2000.65   .058388   .242745   .1949233
+    2000.70   .025972   .239588   .1871360
+    2000.75  -.005722   .246917   .1747298
+    2000.80  -.036045   .262831   .1600032
+    2000.85  -.059965   .292223   .1391654
+    2000.90  -.076915   .325404   .1205337
+    2000.95  -.082660   .357017   .1045817
+    2001.00  -.074006   .396764   .0936988
+    2001.05  -.060835   .427064   .0806986
+    2001.10  -.032401   .451341   .0762852
+    2001.15   .004327   .475921   .0624390
+    2001.20   .044840   .486196   .0388944
+    2001.25   .091974   .489418   .0251539
+    2001.30   .139116   .477702   .0096675
+    2001.35   .178791   .452008  -.0088652
+    2001.40   .215170   .409242  -.0228961
+    2001.45   .242795   .359595  -.0245445
+    2001.50   .254005   .304725  -.0278187
+    2001.55   .247620   .249184  -.0254430
+    2001.60   .220968   .199893  -.0206066
+    2001.65   .175053   .158811  -.0281492
+    2001.70   .125932   .132198  -.0304154
+    2001.75   .064697   .117778  -.0383976
+    2001.80   .001422   .120744  -.0558549
+    2001.85  -.061030   .140506  -.0697006
+    2001.90  -.103646   .180496  -.0868556
+    2001.95  -.153361   .228492  -.1008918
+    2002.00  -.176817   .292216  -.1154380
+    2002.05  -.178852   .348438  -.1269166
+    2002.10  -.163183   .406360  -.1417309
+    2002.15  -.135832   .461499  -.1552923
+    2002.20  -.088799   .513379  -.1739301
+    2002.25  -.027634   .540974  -.1901581
+    2002.30   .029239   .554816  -.2007113
+    2002.35   .092521   .550437  -.2137458
+    2002.40   .142157   .534179  -.2303514
+    2002.45   .192923   .504114  -.2287794
+    2002.50   .228889   .458092  -.2296246
+    2002.55   .244514   .404459  -.2327614
+    2002.60   .257521   .348296  -.2240428
+    2002.65   .254939   .295393  -.2248033
+    2002.70   .235509   .242129  -.2303263
+    2002.75   .197659   .199413  -.2327877
+    2002.80   .151551   .165804  -.2429725
+    2002.85   .084865   .146837  -.2549716
+    2002.90   .022450   .142124  -.2612171
+    2002.95  -.038228   .154264  -.2767537
+    2003.00  -.087743   .187387  -.2892390
+    2003.05  -.127578   .228891  -.2995032
+    2003.10  -.147530   .278647  -.3078795
+    2003.15  -.154775   .332102  -.3201905
+    2003.20  -.157108   .383491  -.3285379
+    2003.25  -.131007   .438825  -.3439523
+    2003.30  -.094644   .486399  -.3588043
+    2003.35  -.043183   .522695  -.3638535
+    2003.40   .001931   .541957  -.3745652
+    2003.45   .062632   .546600  -.3752839
+    2003.50   .135203   .538240  -.3661265
+    2003.55   .191134   .509318  -.3577046
+    2003.60   .232086   .463954  -.3537978
+    2003.65   .259508   .415127  -.3494880
+    2003.70   .264299   .356543  -.3529986
+    2003.75   .257771   .302232  -.3575570
+    2003.80   .226130   .250158  -.3628298
+    2003.85   .195950   .207643  -.3728456
+    2003.90   .147593   .174905  -.3807556
+    2003.95   .087282   .158884  -.3820300
+    2004.00   .031246   .153785  -.3896036
+    2004.05  -.014033   .166554  -.3994989
+    2004.10  -.057805   .191331  -.4041551
+    2004.15  -.101004   .228144  -.4153922
+    2004.20  -.126021   .268583  -.4225892
+    2004.25  -.140343   .321451  -.4338646
+    2004.30  -.132911   .375713  -.4512439
+    2004.35  -.112725   .423506  -.4596331
+    2004.40  -.090722   .458455  -.4683249
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/eopc01_1900_2004.raw
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/eopc01_1900_2004.raw	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/eopc01_1900_2004.raw	(revision 22158)
@@ -0,0 +1,2092 @@
+     Date         x       sx         y       sy      ut1-utc    sut1       dPsi     sdPsi     dEps      sEps
+     year        (")      (")       (")      (")        s         s         (")      (")       (")      (")
+
+    1900.00  -.212818  .053760  -.097229  .037446   .0000000  .0000000  -.333677  .126760  -.065408  .046343
+    1900.05  -.047461  .029853  -.065631  .023330   .0000000  .0000000  -.193398  .127676   .017394  .021636
+    1900.10  -.112006  .028504  -.040467  .024327   .0000000  .0000000   .521675  .123684   .068013  .029930
+    1900.15  -.076710  .021791  -.009674  .021233   .0000000  .0000000   .352564  .078239   .072061  .029062
+    1900.20  -.099850  .026908  -.066660  .025620   .0000000  .0000000   .318962  .097104   .007820  .057366
+    1900.25  -.131173  .039344  -.072076  .027851   .0000000  .0000000   .232096  .066951   .093766  .058547
+    1900.30  -.087390  .025660  -.089427  .024505   .0000000  .0000000   .307133  .066507   .003862  .042366
+    1900.35  -.164078  .026598  -.131034  .027439   .0000000  .0000000   .317237  .071973   .026743  .042837
+    1900.40  -.151407  .019173  -.105838  .020221   .0000000  .0000000   .202192  .096423   .017399  .023063
+    1900.45  -.143764  .021261  -.179125  .029817   .0000000  .0000000  -.028123  .129358  -.012124  .020663
+    1900.50  -.124341  .024357  -.105747  .019115   .0000000  .0000000   .041669  .127181   .044334  .017158
+    1900.55  -.206229  .021263  -.144555  .025505   .0000000  .0000000  -.041788  .102389   .095807  .029772
+    1900.60  -.192711  .025172  -.095563  .029564   .0000000  .0000000   .002017  .105331   .044212  .031575
+    1900.65  -.190299  .023335  -.067717  .020577   .0000000  .0000000   .194828  .076930   .085772  .045933
+    1900.70  -.135718  .022933  -.081480  .020157   .0000000  .0000000   .269845  .072594   .075357  .044405
+    1900.75  -.153807  .024518   .030568  .021592   .0000000  .0000000   .181946  .044492  -.154452  .052427
+    1900.80  -.173818  .022558   .001034  .018183   .0000000  .0000000   .170594  .039178  -.072797  .045202
+    1900.85  -.257716  .032834  -.006499  .028017   .0000000  .0000000   .236454  .094350  -.162464  .054953
+    1900.90  -.209085  .025040   .046511  .025197   .0000000  .0000000   .088373  .092346  -.089729  .055564
+    1900.95  -.133145  .034581   .004905  .026144   .0000000  .0000000  -.039864  .127792  -.039118  .041313
+    1901.00  -.138242  .027367   .014255  .024185   .0000000  .0000000  -.228636  .134455  -.003944  .038305
+    1901.05  -.162602  .024087   .006609  .023908   .0000000  .0000000  -.262902  .109076  -.069779  .020676
+    1901.10  -.121242  .025526  -.000875  .022222   .0000000  .0000000   .356041  .119705  -.014506  .031232
+    1901.15  -.109773  .028420   .024691  .024157   .0000000  .0000000   .373538  .100048   .018214  .036225
+    1901.20  -.103805  .026286   .039564  .021736   .0000000  .0000000   .309930  .078709  -.018732  .045262
+    1901.25  -.021306  .024508  -.011519  .023560   .0000000  .0000000   .226326  .046973  -.026068  .056093
+    1901.30  -.001300  .016000   .021700  .023300   .0000000  .0000000   .431800  .058100  -.012900  .035900
+    1901.35   .037156  .024692  -.049753  .024062   .0000000  .0000000   .430826  .066845  -.018088  .038805
+    1901.40   .003993  .019282  -.095314  .029126   .0000000  .0000000   .120522  .119007   .083355  .027210
+    1901.45   .054079  .019606  -.081336  .019143   .0000000  .0000000   .051073  .111137   .020471  .014069
+    1901.50   .089761  .031152  -.084901  .023841   .0000000  .0000000   .055714  .133759   .011540  .022405
+    1901.55   .004864  .024183  -.187233  .019218   .0000000  .0000000   .191254  .111589   .051708  .031744
+    1901.60  -.023099  .020532  -.179528  .016169   .0000000  .0000000  -.025500  .092583   .010166  .026232
+    1901.65  -.057910  .022283  -.197673  .018043   .0000000  .0000000   .127452  .059894   .095943  .032516
+    1901.70  -.033170  .021132  -.202981  .020887   .0000000  .0000000   .151218  .074568   .035224  .044759
+    1901.75  -.155604  .038076  -.187085  .030924   .0000000  .0000000   .009135  .074519  -.123734  .051462
+    1901.80  -.169658  .026229  -.183163  .023359   .0000000  .0000000   .110066  .049415  -.117592  .046192
+    1901.85  -.188623  .023529  -.181458  .023343   .0000000  .0000000   .176267  .083759  -.158104  .051685
+    1901.90  -.223086  .037997  -.144566  .029526   .0000000  .0000000   .074590  .108405  -.100008  .058672
+    1901.95  -.254958  .016090  -.114447  .017896   .0000000  .0000000   .038950  .101799  -.062510  .027550
+    1902.00  -.259243  .023993  -.078157  .021579   .0000000  .0000000   .062919  .117810  -.054074  .032269
+    1902.05  -.211792  .028790   .038633  .029579   .0000000  .0000000   .017451  .148456   .020130  .024810
+    1902.10  -.216991  .031892   .064250  .026547   .0000000  .0000000   .199832  .133961   .037086  .035402
+    1902.15  -.242537  .023685   .171246  .025297   .0000000  .0000000   .415690  .088702   .043663  .034234
+    1902.20  -.188324  .019932   .158468  .019402   .0000000  .0000000   .337145  .073499   .052572  .046916
+    1902.25  -.152570  .029794   .207171  .027372   .0000000  .0000000   .214367  .061488  -.046953  .060194
+    1902.30  -.062244  .016488   .171387  .022647   .0000000  .0000000   .256881  .057371   .006551  .033174
+    1902.35  -.016045  .025756   .182141  .020157   .0000000  .0000000   .265355  .062603  -.028692  .033970
+    1902.40   .036032  .019117   .156268  .020794   .0000000  .0000000   .211676  .098381  -.021285  .023510
+    1902.45   .217293  .048928   .252814  .059193   .0000000  .0000000   .146268  .124285  -.113359  .044438
+    1902.50   .119283  .025360   .066262  .021894   .0000000  .0000000   .024206  .116290   .019059  .018772
+    1902.55   .125538  .021669   .016781  .019109   .0000000  .0000000   .091941  .099925   .027890  .029268
+    1902.60   .082496  .025116  -.058369  .022971   .0000000  .0000000   .250234  .108900   .110308  .030400
+    1902.65   .051287  .024489  -.069631  .016515   .0000000  .0000000   .261163  .069618   .097323  .039865
+    1902.70   .051239  .015838  -.093785  .015438   .0000000  .0000000   .250384  .055426   .068387  .034338
+    1902.75  -.024248  .022473  -.151921  .025442   .0000000  .0000000   .149156  .045045  -.095975  .053371
+    1902.80  -.054789  .019443  -.179957  .016628   .0000000  .0000000   .124553  .035265  -.069583  .040068
+    1902.85  -.146320  .020063  -.146959  .023110   .0000000  .0000000   .078608  .078920  -.089216  .047165
+    1902.90  -.193061  .020857  -.169534  .022315   .0000000  .0000000   .286457  .076181  -.208670  .046902
+    1902.95  -.237694  .019690  -.119404  .024324   .0000000  .0000000   .109034  .129370  -.052789  .034514
+    1903.00  -.319420  .030492  -.043030  .024811   .0000000  .0000000  -.038528  .145631  -.047724  .038302
+    1903.05  -.341204  .033829   .031366  .029406   .0000000  .0000000  -.098874  .160686   .018102  .023703
+    1903.10  -.345930  .022972  -.002271  .021847   .0000000  .0000000   .351093  .102851   .012471  .027943
+    1903.15  -.363449  .026083   .022246  .026034   .0000000  .0000000   .188593  .093308  -.023174  .037211
+    1903.20  -.363639  .026221   .126744  .020945   .0000000  .0000000   .245152  .087844   .029758  .051375
+    1903.25  -.275204  .023659   .088178  .025161   .0000000  .0000000   .291261  .044592   .065540  .051947
+    1903.30  -.217973  .027174   .142752  .021557   .0000000  .0000000   .210847  .075501   .063304  .043755
+    1903.35  -.133649  .019233   .193127  .019408   .0000000  .0000000   .260252  .056126   .060431  .031402
+    1903.40  -.073538  .019722   .187785  .025512   .0000000  .0000000   .238595  .103039  -.018625  .024658
+    1903.45  -.033275  .020533   .242905  .022048   .0000000  .0000000   .056127  .129511   .027798  .017107
+    1903.50  -.025665  .019429   .185828  .015678   .0000000  .0000000  -.045779  .099979   .027960  .013960
+    1903.55   .065994  .027595   .199396  .021362   .0000000  .0000000   .091259  .113401   .039908  .032424
+    1903.60   .124642  .022783   .131603  .021652   .0000000  .0000000   .051145  .098411   .025315  .027842
+    1903.65   .138085  .017587   .043707  .024380   .0000000  .0000000   .246657  .066217   .079088  .036242
+    1903.70   .131036  .023145  -.010458  .018213   .0000000  .0000000   .227846  .071262   .028294  .042237
+    1903.75   .129875  .035187  -.132885  .050492   .0000000  .0000000   .250549  .112846  -.094268  .048466
+    1903.80   .020188  .021139  -.149501  .017604   .0000000  .0000000   .109261  .036528  -.073754  .040709
+    1903.85  -.013164  .021345  -.224089  .020262   .0000000  .0000000   .056925  .074780  -.070392  .044352
+    1903.90   .017200  .027500  -.148400  .021400   .0000000  .0000000   .365700  .082200  -.239900  .051000
+    1903.95  -.054459  .030056  -.187411  .022835   .0000000  .0000000   .143493  .154516  -.103709  .039701
+    1904.00  -.148856  .044509  -.076687  .044456   .0000000  .0000000  -.114333  .231473   .061858  .075829
+    1904.05  -.254004  .025206  -.136031  .021177   .0000000  .0000000   .004573  .125550  -.037187  .017298
+    1904.10  -.260513  .025120  -.134266  .024182   .0000000  .0000000   .245917  .113408  -.023869  .030194
+    1904.15  -.250640  .038286  -.062308  .029112   .0000000  .0000000   .153720  .139136  -.072025  .046748
+    1904.20  -.318450  .021790  -.022118  .038002   .0000000  .0000000   .343107  .107286   .029958  .054168
+    1904.25  -.293126  .023025   .024733  .019604   .0000000  .0000000   .257570  .041421   .099537  .048628
+    1904.30  -.249230  .043032   .052166  .022314   .0000000  .0000000   .250262  .082833   .005740  .053675
+    1904.35  -.263860  .019701   .072953  .018143   .0000000  .0000000   .249463  .055609   .056281  .034733
+    1904.40  -.210918  .029867   .172463  .020549   .0000000  .0000000   .242277  .114143   .012153  .028773
+    1904.45  -.152700  .018200   .188900  .018000   .0000000  .0000000  -.038200  .111600   .003300  .013500
+    1904.50  -.109676  .019307   .182564  .018938   .0000000  .0000000  -.148627  .111520   .030744  .015061
+    1904.55  -.082798  .020647   .158201  .020009   .0000000  .0000000   .046632  .096224   .074456  .028089
+    1904.60   .001500  .014600   .164000  .015300   .0000000  .0000000   .059100  .081200   .033100  .023200
+    1904.65   .042084  .017502   .134884  .014207   .0000000  .0000000   .299232  .053479   .160529  .030251
+    1904.70   .062535  .019610   .070240  .018761   .0000000  .0000000   .233434  .063943   .112999  .037691
+    1904.75   .083512  .024774   .063227  .023502   .0000000  .0000000   .100183  .048551   .039087  .030313
+    1904.80   .042326  .022076   .010531  .021354   .0000000  .0000000   .108009  .041403  -.080528  .043561
+    1904.85   .042284  .020582  -.029751  .021504   .0000000  .0000000   .096546  .079450  -.128975  .047377
+    1904.90  -.008473  .045473  -.063250  .044351   .0000000  .0000000   .231014  .135878  -.063402  .095840
+    1904.95   .028258  .028399  -.057405  .026815   .0000000  .0000000   .103781  .158414  -.073395  .041300
+    1905.00  -.040538  .025021  -.099671  .024519   .0000000  .0000000   .185220  .087951  -.032327  .026835
+    1905.05  -.017099  .027266  -.158118  .027398   .0000000  .0000000  -.161540  .107012   .074302  .024020
+    1905.10  -.105713  .031136  -.176117  .024035   .0000000  .0000000   .347522  .131488   .052168  .033695
+    1905.15  -.176213  .023287  -.100777  .021215   .0000000  .0000000   .290801  .072797   .017315  .027805
+    1905.20  -.231493  .023017  -.136695  .016189   .0000000  .0000000   .101899  .056885   .024298  .027994
+    1905.25  -.251440  .023914  -.151097  .022693   .0000000  .0000000   .183959  .044511   .085260  .040895
+    1905.30  -.248000  .029100  -.108800  .028300   .0000000  .0000000   .303300  .084900   .012900  .044900
+    1905.35  -.304428  .020727   .045206  .018309   .0000000  .0000000   .195471  .060148   .000919  .037654
+    1905.40  -.236545  .022973   .042822  .026077   .0000000  .0000000   .123361  .118627   .009977  .029220
+    1905.45  -.250592  .031413   .048859  .027624   .0000000  .0000000   .029364  .124702   .025729  .021942
+    1905.50  -.185960  .023539   .112145  .027395   .0000000  .0000000   .098352  .135807   .009326  .019311
+    1905.55  -.156532  .021895   .117102  .020138   .0000000  .0000000  -.081301  .087252  -.037089  .024732
+    1905.60  -.109352  .021554   .166247  .018456   .0000000  .0000000  -.052333  .098533  -.005779  .029043
+    1905.65  -.067846  .028256   .135598  .020885   .0000000  .0000000   .277618  .064061   .111046  .035631
+    1905.70   .014037  .023029   .151407  .022182   .0000000  .0000000   .282266  .062970   .052905  .033997
+    1905.75  -.034403  .030475   .175804  .021521   .0000000  .0000000   .255754  .049868  -.148491  .055323
+    1905.80  -.031721  .028070   .049970  .029042   .0000000  .0000000  -.006276  .049203  -.163042  .046545
+    1905.85   .025746  .026045   .080453  .024204   .0000000  .0000000   .318572  .083837  -.162672  .049900
+    1905.90   .024021  .023876  -.056728  .024447   .0000000  .0000000   .191888  .086082  -.081159  .052664
+    1905.95   .040706  .025939  -.006383  .031653   .0000000  .0000000   .176684  .151253  -.066028  .042122
+    1906.00   .003853  .027774  -.026096  .022568   .0000000  .0000000   .353052  .125609  -.085851  .034335
+    1906.05  -.017613  .037626  -.075020  .028373   .0000000  .0000000   .058236  .116066   .042743  .028389
+    1906.10  -.157406  .027525  -.092487  .019150   .0000000  .0000000   .270125  .098675   .087800  .028450
+    1906.15  -.067506  .039670  -.080298  .024017   .0000000  .0000000   .057244  .086367   .041170  .032989
+    1906.20  -.149450  .019538  -.119103  .021544   .0000000  .0000000   .113356  .066083   .003460  .039537
+    1906.25  -.128247  .021258  -.061169  .019210   .0000000  .0000000   .102973  .039658   .057831  .043484
+    1906.30  -.179648  .019342  -.057693  .015619   .0000000  .0000000   .175340  .057093  -.039542  .032940
+    1906.35  -.186449  .028318  -.044109  .017466   .0000000  .0000000   .140376  .060295  -.002299  .033838
+    1906.40  -.208575  .017756  -.019448  .017400   .0000000  .0000000   .015574  .074861   .005300  .018332
+    1906.45  -.217870  .027036   .042944  .019247   .0000000  .0000000   .248883  .103492   .000061  .019037
+    1906.50  -.199891  .026352   .058881  .022948   .0000000  .0000000   .227682  .100657   .031386  .018187
+    1906.55  -.173543  .014562   .070934  .014278   .0000000  .0000000   .117292  .076299   .023764  .021614
+    1906.60  -.182003  .014184   .113024  .020481   .0000000  .0000000   .238491  .076914   .064891  .023037
+    1906.65  -.142776  .020805   .095154  .018992   .0000000  .0000000   .200399  .060830   .052899  .036334
+    1906.70  -.093740  .023427   .095224  .019026   .0000000  .0000000   .165899  .057427   .024389  .033984
+    1906.75  -.093900  .030400   .111200  .029700   .0000000  .0000000   .123100  .056800  -.022900  .055700
+    1906.80  -.102758  .020273   .078405  .019941   .0000000  .0000000   .158671  .038107  -.057296  .034270
+    1906.85  -.009641  .037790   .137918  .023678   .0000000  .0000000   .110473  .086093  -.121337  .055949
+    1906.90  -.126885  .017403   .077766  .014954   .0000000  .0000000   .071042  .050965  -.101739  .029910
+    1906.95  -.085940  .024352   .122947  .033076   .0000000  .0000000  -.173911  .144919   .052592  .043974
+    1907.00  -.079416  .024620   .150174  .023710   .0000000  .0000000   .080001  .116688   .018143  .029500
+    1907.05  -.067350  .025143   .041498  .035409   .0000000  .0000000   .073095  .126257   .055036  .023696
+    1907.10  -.027042  .044273   .024883  .037921   .0000000  .0000000   .189029  .138258   .070923  .040212
+    1907.15  -.069913  .023457   .039794  .019305   .0000000  .0000000   .247270  .073147   .059702  .028726
+    1907.20  -.059194  .025568  -.025833  .019658   .0000000  .0000000  -.067453  .070577  -.036942  .042421
+    1907.25  -.032978  .027136  -.010025  .021118   .0000000  .0000000   .097977  .045607   .028819  .047104
+    1907.30  -.032298  .018376  -.079952  .018100   .0000000  .0000000   .091289  .058321   .098117  .035752
+    1907.35  -.012800  .019968  -.038790  .015828   .0000000  .0000000   .026669  .051078   .005099  .029065
+    1907.40  -.094517  .018850  -.051596  .019350   .0000000  .0000000   .154034  .095591  -.036263  .023594
+    1907.45  -.089447  .022296  -.124297  .019779   .0000000  .0000000   .029209  .101385   .026543  .015722
+    1907.50  -.131771  .019108  -.098748  .017119   .0000000  .0000000   .242100  .089088   .009307  .014240
+    1907.55  -.109356  .015221  -.122489  .014661   .0000000  .0000000   .138257  .080858   .007021  .022508
+    1907.60  -.134764  .018056  -.084340  .015443   .0000000  .0000000   .202735  .078593   .056406  .022873
+    1907.65  -.150915  .013218  -.095204  .011457   .0000000  .0000000   .186489  .042036   .065484  .024490
+    1907.70  -.183652  .013853  -.070567  .012711   .0000000  .0000000   .238161  .042637   .067956  .025900
+    1907.75  -.247755  .015944  -.037271  .014847   .0000000  .0000000   .069057  .030949  -.166534  .035037
+    1907.80  -.276782  .022683   .006594  .013921   .0000000  .0000000   .113611  .036307  -.078859  .035934
+    1907.85  -.260675  .020328   .115176  .026887   .0000000  .0000000   .036991  .076862  -.028790  .043520
+    1907.90  -.279309  .022735   .066165  .018080   .0000000  .0000000   .244677  .062092  -.110026  .038954
+    1907.95  -.247411  .024711   .158512  .031173   .0000000  .0000000   .062917  .124068   .010688  .030974
+    1908.00  -.179825  .022677   .190418  .019382   .0000000  .0000000   .045084  .106993   .062586  .027161
+    1908.05  -.162104  .025046   .175855  .028444   .0000000  .0000000   .103742  .155855   .042061  .019892
+    1908.10  -.073775  .028891   .244495  .024516   .0000000  .0000000   .245695  .110802   .095557  .031435
+    1908.15  -.088534  .027458   .184551  .017033   .0000000  .0000000   .202671  .076752   .059013  .031780
+    1908.20   .072181  .033438   .185212  .026915   .0000000  .0000000  -.041708  .089470  -.103296  .050987
+    1908.25   .000811  .023430   .129285  .025494   .0000000  .0000000   .206115  .053034   .050623  .041550
+    1908.30   .094290  .022523   .125029  .016876   .0000000  .0000000   .216543  .060033  -.027207  .036610
+    1908.35   .098031  .015570   .048028  .014659   .0000000  .0000000   .030976  .044622   .052821  .026959
+    1908.40   .085376  .019153  -.037173  .015904   .0000000  .0000000   .105038  .078267   .015997  .019045
+    1908.45   .110614  .025853  -.053618  .024285   .0000000  .0000000   .153787  .106634   .013544  .019968
+    1908.50   .110175  .026610  -.121985  .025563   .0000000  .0000000   .031077  .108516   .006967  .020390
+    1908.55   .062891  .022400  -.147259  .019060   .0000000  .0000000  -.082788  .089320  -.037852  .025333
+    1908.60   .016036  .021495  -.174778  .023275   .0000000  .0000000   .210112  .099015   .066788  .027598
+    1908.65  -.044507  .019073  -.258578  .021281   .0000000  .0000000   .179528  .051480   .053306  .026579
+    1908.70  -.126698  .019826  -.236805  .014026   .0000000  .0000000   .159666  .057586   .116131  .031215
+    1908.75  -.185227  .018908  -.279032  .016051   .0000000  .0000000  -.038867  .036568  -.059976  .030485
+    1908.80  -.218671  .014651  -.234349  .016957   .0000000  .0000000   .085591  .033574  -.055343  .025266
+    1908.85  -.258124  .022801  -.193490  .017680   .0000000  .0000000   .058307  .057282  -.155806  .034798
+    1908.90  -.348498  .023013  -.117029  .019986   .0000000  .0000000  -.044263  .072425  -.031398  .041662
+    1908.95  -.441656  .045827  -.087821  .024170   .0000000  .0000000  -.222508  .111975   .074175  .042506
+    1909.00  -.418026  .030202   .032515  .029485   .0000000  .0000000  -.124136  .114958   .001844  .034290
+    1909.05  -.464700  .023300   .053100  .021200   .0000000  .0000000   .142200  .122400  -.021900  .017600
+    1909.10  -.381402  .029397   .081369  .026583   .0000000  .0000000   .136482  .135028   .026300  .032872
+    1909.15  -.331872  .024908   .208343  .022250   .0000000  .0000000   .142551  .088861   .003686  .028690
+    1909.20  -.262800  .025300   .230900  .020400   .0000000  .0000000   .246000  .077700   .119000  .052700
+    1909.25  -.180022  .021604   .262477  .015586   .0000000  .0000000   .204810  .034370   .159389  .041898
+    1909.30  -.088674  .020876   .272316  .018026   .0000000  .0000000   .224372  .061549  -.013291  .039957
+    1909.35  -.017300  .024900   .301900  .020400   .0000000  .0000000   .115400  .068600  -.009000  .037100
+    1909.40   .082311  .016643   .293915  .015624   .0000000  .0000000   .161696  .084291   .000839  .021602
+    1909.45   .145682  .019466   .242356  .024029   .0000000  .0000000   .169328  .107429  -.009796  .017280
+    1909.50   .159939  .021629   .145514  .016260   .0000000  .0000000  -.073128  .091190   .030057  .015366
+    1909.55   .219001  .015849   .050735  .015308   .0000000  .0000000  -.011547  .079780  -.013148  .022447
+    1909.60   .251107  .017083   .038325  .012976   .0000000  .0000000   .142763  .076342   .011621  .021565
+    1909.65   .216000  .017200  -.092100  .014200   .0000000  .0000000   .209600  .053300   .068800  .031100
+    1909.70   .239771  .033367  -.129218  .018723   .0000000  .0000000   .327841  .068174   .031505  .035607
+    1909.75   .122030  .026859  -.229024  .021510   .0000000  .0000000   .118789  .051222  -.041929  .044658
+    1909.80  -.027219  .018091  -.280542  .014742   .0000000  .0000000   .105788  .032512  -.034222  .033019
+    1909.85  -.097816  .031222  -.318227  .020306   .0000000  .0000000   .102209  .083756  -.040327  .052036
+    1909.90  -.212272  .020651  -.273213  .013760   .0000000  .0000000   .155022  .055398  -.090967  .034028
+    1909.95  -.262295  .016361  -.211841  .019362   .0000000  .0000000  -.306349  .093272   .051436  .026436
+    1910.00  -.323074  .027015  -.200846  .037795   .0000000  .0000000   .099003  .103352  -.005730  .037950
+    1910.05  -.442329  .027265  -.257217  .023282   .0000000  .0000000   .036708  .143048  -.002189  .019658
+    1910.10  -.448532  .041123  -.107453  .027419   .0000000  .0000000   .043621  .162329   .045460  .040389
+    1910.15  -.408744  .021087   .030815  .032683   .0000000  .0000000   .172827  .103869  -.015696  .038230
+    1910.20  -.414020  .027029  -.006268  .022893   .0000000  .0000000  -.006953  .079653  -.073319  .048574
+    1910.25  -.385676  .029272   .162890  .037814   .0000000  .0000000   .131554  .075221   .115988  .049835
+    1910.30  -.368387  .014246   .272702  .023082   .0000000  .0000000   .168008  .058720   .013868  .035304
+    1910.35  -.268774  .014096   .293213  .017618   .0000000  .0000000   .102868  .050954   .015300  .031518
+    1910.40  -.147573  .033402   .342824  .031269   .0000000  .0000000   .108410  .144680   .021531  .038312
+    1910.45  -.081273  .036206   .328529  .024940   .0000000  .0000000   .268834  .133538  -.046158  .027171
+    1910.50  -.020932  .018243   .388520  .021784   .0000000  .0000000   .186364  .101418   .015650  .016119
+    1910.55   .105674  .015903   .327555  .015193   .0000000  .0000000  -.016453  .084989  -.015338  .023625
+    1910.60   .176301  .025502   .312524  .018735   .0000000  .0000000   .146119  .091503   .028960  .027777
+    1910.65   .191756  .047195   .171612  .029191   .0000000  .0000000   .176229  .097407   .121387  .055812
+    1910.70   .222257  .017196   .091742  .015870   .0000000  .0000000   .182638  .052853   .063604  .032838
+    1910.75   .211332  .016710  -.009012  .016112   .0000000  .0000000   .048463  .032674  -.060190  .037462
+    1910.80   .205000  .020700  -.105700  .017200   .0000000  .0000000   .062800  .036400  -.095100  .039600
+    1910.85   .120900  .020101  -.162494  .021135   .0000000  .0000000   .123726  .059606  -.019765  .042156
+    1910.90   .083916  .023956  -.253801  .024007   .0000000  .0000000   .013354  .073655  -.021508  .051519
+    1910.95  -.057477  .033626  -.280025  .025436   .0000000  .0000000   .072073  .128036  -.009321  .037844
+    1911.00  -.089579  .028621  -.260914  .027948   .0000000  .0000000   .169478  .116395   .037311  .032178
+    1911.05  -.218786  .029820  -.263597  .035792   .0000000  .0000000   .069459  .152501   .061462  .023480
+    1911.10  -.224700  .024170  -.257286  .021305   .0000000  .0000000   .325278  .115919   .068961  .028144
+    1911.15  -.335860  .021547  -.182205  .019739   .0000000  .0000000   .133424  .083961   .036224  .025924
+    1911.20  -.267000  .034500  -.050900  .036500   .0000000  .0000000  -.104000  .121900   .078500  .058700
+    1911.25  -.370633  .024922   .021540  .022191   .0000000  .0000000   .297392  .046601   .002211  .053352
+    1911.30  -.353109  .024050   .047330  .019022   .0000000  .0000000   .167158  .069713  -.013280  .040848
+    1911.35  -.332727  .014668   .126340  .014928   .0000000  .0000000   .252875  .048137  -.056184  .031637
+    1911.40  -.234107  .032662   .168826  .020525   .0000000  .0000000   .201020  .113961   .056925  .030206
+    1911.45  -.272718  .028763   .310644  .020913   .0000000  .0000000   .192952  .130471   .027320  .018467
+    1911.50  -.193283  .022444   .331807  .023636   .0000000  .0000000   .287728  .116745  -.006204  .019212
+    1911.55  -.136796  .026687   .347029  .020769   .0000000  .0000000   .100558  .095132  -.013315  .028295
+    1911.60  -.056770  .020828   .304448  .016125   .0000000  .0000000   .038851  .087052  -.008402  .025164
+    1911.65   .060600  .022900   .363500  .027100   .0000000  .0000000   .205100  .059600   .017900  .029800
+    1911.70   .112694  .032188   .325844  .023151   .0000000  .0000000   .299304  .082079   .040320  .047025
+    1911.75   .129599  .019997   .242729  .021387   .0000000  .0000000   .155515  .039558  -.094239  .038228
+    1911.80   .130866  .021743   .155825  .020309   .0000000  .0000000   .123438  .042282  -.010054  .034573
+    1911.85   .158551  .020434   .088616  .025134   .0000000  .0000000   .051214  .068383  -.010926  .041562
+    1911.90   .145314  .028595  -.044498  .021946   .0000000  .0000000  -.100129  .069086  -.007673  .044906
+    1911.95   .095603  .025949  -.041933  .034319   .0000000  .0000000   .023942  .151461  -.068062  .043736
+    1912.00   .083131  .028082  -.041367  .045117   .0000000  .0000000   .086921  .127853   .026547  .039122
+    1912.05  -.038956  .035506  -.097988  .024047   .0000000  .0000000  -.007819  .159622   .019820  .021583
+    1912.10   .078300  .036400  -.165300  .022900   .0000000  .0000000   .233500  .115600   .104200  .031000
+    1912.15  -.088995  .031251  -.223549  .023255   .0000000  .0000000   .220333  .093899   .077473  .038050
+    1912.20  -.127587  .022657  -.102840  .033381   .0000000  .0000000   .170145  .089310   .010912  .046724
+    1912.25  -.227272  .023288  -.194080  .022502   .0000000  .0000000   .186406  .044893  -.084389  .049865
+    1912.30  -.209405  .020707  -.109730  .020075   .0000000  .0000000   .055672  .058713   .017194  .031326
+    1912.35  -.237021  .016480  -.041122  .019962   .0000000  .0000000   .022407  .056949   .025940  .032792
+    1912.40  -.262082  .018289  -.006966  .017816   .0000000  .0000000   .029363  .090838   .043339  .022758
+    1912.45  -.225320  .035063   .056285  .028655   .0000000  .0000000   .180293  .125295  -.022633  .026061
+    1912.50  -.263907  .021742   .044713  .019951   .0000000  .0000000   .002937  .113586   .003018  .016324
+    1912.55  -.196951  .023121   .144625  .021044   .0000000  .0000000   .068149  .094223   .007916  .027238
+    1912.60  -.198267  .021321   .185500  .018223   .0000000  .0000000   .204439  .104019   .018183  .028277
+    1912.65  -.219124  .027649   .151146  .023604   .0000000  .0000000   .159364  .071235   .100388  .039220
+    1912.70  -.175982  .021677   .183356  .018936   .0000000  .0000000   .236280  .063918   .115620  .039114
+    1912.75  -.160280  .019553   .162811  .016252   .0000000  .0000000   .097070  .035523  -.038213  .039632
+    1912.80  -.103200  .021500   .187700  .021600   .0000000  .0000000   .069900  .040000  -.065100  .046800
+    1912.85  -.078852  .022537   .172599  .021871   .0000000  .0000000   .014043  .067846   .025894  .043515
+    1912.90  -.076719  .031453   .222193  .024394   .0000000  .0000000   .080993  .083189  -.048971  .054231
+    1912.95  -.018200  .033800   .178000  .021300   .0000000  .0000000  -.209300  .149500   .097800  .039400
+    1913.00  -.088918  .036157   .098053  .038779   .0000000  .0000000  -.130297  .147099   .004638  .045245
+    1913.05  -.043449  .024134   .115101  .031313   .0000000  .0000000  -.107525  .148353   .028795  .019234
+    1913.10  -.001323  .029225   .124168  .025147   .0000000  .0000000   .274923  .112863   .004371  .033360
+    1913.15  -.021744  .022356   .057252  .022649   .0000000  .0000000  -.015634  .080957  -.073590  .030838
+    1913.20   .011122  .019340   .015761  .020873   .0000000  .0000000   .202756  .058131   .031678  .036427
+    1913.25  -.010477  .016419  -.071666  .019034   .0000000  .0000000   .000632  .034529   .016072  .036418
+    1913.30   .032491  .025253   .003044  .016851   .0000000  .0000000  -.002118  .060835   .051937  .035678
+    1913.35   .048101  .019458  -.050706  .023830   .0000000  .0000000   .005973  .067868   .058074  .035138
+    1913.40   .032669  .022624  -.039496  .022980   .0000000  .0000000   .145719  .101370  -.023783  .025456
+    1913.45   .008311  .023950  -.068348  .019240   .0000000  .0000000   .095341  .112721   .009351  .016753
+    1913.50   .000027  .031816  -.047918  .022600   .0000000  .0000000   .254609  .113267  -.033878  .023651
+    1913.55  -.076685  .026892  -.083122  .018481   .0000000  .0000000  -.087757  .110497  -.002857  .031253
+    1913.60  -.108057  .017340  -.085386  .017913   .0000000  .0000000  -.016574  .091878  -.013581  .024005
+    1913.65  -.100400  .027900  -.040800  .019000   .0000000  .0000000   .371500  .067400   .106400  .035600
+    1913.70  -.162152  .019790  -.081823  .024953   .0000000  .0000000   .226011  .076275   .094102  .046150
+    1913.75  -.223157  .019148  -.030051  .015589   .0000000  .0000000   .140482  .033187  -.042264  .041169
+    1913.80  -.224000  .020000  -.002700  .028700   .0000000  .0000000   .069600  .047200   .013500  .044900
+    1913.85  -.226344  .023162   .078679  .023742   .0000000  .0000000   .094095  .068956  -.075759  .047116
+    1913.90  -.200560  .022160   .102525  .020236   .0000000  .0000000   .123629  .061773  -.061520  .034578
+    1913.95  -.313300  .039300   .074600  .021000   .0000000  .0000000  -.070900  .110300  -.070800  .034100
+    1914.00  -.203986  .042377   .155067  .052640   .0000000  .0000000  -.053388  .166647  -.005376  .060606
+    1914.05  -.260937  .067620   .252070  .062023   .0000000  .0000000   .482868  .261586  -.080710  .047209
+    1914.10  -.152037  .032358   .221001  .033547   .0000000  .0000000   .460108  .138175   .079547  .033998
+    1914.15  -.093945  .023823   .191653  .020597   .0000000  .0000000   .274282  .082321  -.003172  .029356
+    1914.20  -.063798  .022074   .184214  .017949   .0000000  .0000000   .368801  .055476   .034615  .036141
+    1914.25  -.013635  .021036   .132013  .036281   .0000000  .0000000   .182668  .064550  -.005456  .042311
+    1914.30   .045383  .017243   .170364  .018313   .0000000  .0000000   .027064  .052599   .079159  .031296
+    1914.35   .034013  .021428   .110450  .025557   .0000000  .0000000   .058854  .067678   .018142  .040045
+    1914.40   .073793  .015420   .089719  .013907   .0000000  .0000000   .195994  .076098  -.004195  .018039
+    1914.45   .106389  .029431   .069624  .018977   .0000000  .0000000   .150803  .132359   .044380  .016981
+    1914.50   .104207  .017302   .003118  .015383   .0000000  .0000000   .061613  .079659   .007552  .014041
+    1914.55   .085502  .013219  -.025467  .011498   .0000000  .0000000  -.005456  .066776  -.016331  .019034
+    1914.60   .049258  .014447  -.008534  .018946   .0000000  .0000000  -.039541  .090380   .020453  .024494
+    1914.65  -.013923  .021070  -.060487  .020484   .0000000  .0000000   .029862  .061791   .025569  .031829
+    1914.70  -.046141  .017808  -.151237  .014883   .0000000  .0000000   .000046  .048187  -.025157  .027803
+    1914.75  -.094789  .022287  -.177467  .016968   .0000000  .0000000   .017265  .038972  -.054229  .037879
+    1914.80  -.140169  .032081  -.214589  .017725   .0000000  .0000000  -.107241  .042845  -.020467  .037875
+    1914.85  -.220007  .022213  -.164939  .020100   .0000000  .0000000   .010800  .055608  -.127015  .043005
+    1914.90  -.271487  .019822  -.080598  .028419   .0000000  .0000000   .093833  .074114  -.119831  .044306
+    1914.95  -.197162  .054534  -.003731  .040356   .0000000  .0000000  -.033235  .234490   .126051  .065477
+    1915.00  -.365371  .033632   .018627  .024793   .0000000  .0000000   .050076  .137027   .007352  .039388
+    1915.05  -.311390  .034237   .018527  .036937   .0000000  .0000000   .470422  .190718  -.025907  .027027
+    1915.10  -.363577  .028404   .127944  .046152   .0000000  .0000000   .199111  .082412  -.005714  .031288
+    1915.15  -.230546  .034338   .091634  .039141   .0000000  .0000000   .217155  .152154   .062311  .052850
+    1915.20  -.285678  .027666   .254673  .030284   .0000000  .0000000   .366048  .083251   .064727  .056257
+    1915.25  -.300793  .035000   .364102  .032230   .0000000  .0000000   .480897  .069664  -.061038  .070711
+    1915.30  -.145488  .022572   .374588  .051362   .0000000  .0000000   .264689  .087911  -.030308  .039430
+    1915.35  -.084157  .022819   .325899  .025296   .0000000  .0000000   .251653  .074966   .026434  .040212
+    1915.40  -.008400  .021600   .253100  .027800   .0000000  .0000000   .261400  .120600   .015400  .027700
+    1915.45   .086674  .025374   .275352  .030762   .0000000  .0000000   .027152  .116818   .032016  .025083
+    1915.50   .081245  .018951   .210673  .023988   .0000000  .0000000   .020150  .110182   .042758  .016256
+    1915.55   .121650  .022685   .162508  .020369   .0000000  .0000000  -.076632  .111521   .060233  .031530
+    1915.60   .169064  .028416  -.052355  .038319   .0000000  .0000000   .017374  .111772  -.019577  .038525
+    1915.65   .112084  .021944   .002862  .022580   .0000000  .0000000   .038242  .062160   .031483  .035854
+    1915.70   .099188  .020367  -.061928  .021327   .0000000  .0000000  -.010568  .066166   .064707  .036261
+    1915.75   .093628  .029174  -.172293  .033092   .0000000  .0000000  -.095497  .050692  -.056246  .054216
+    1915.80  -.031363  .037232  -.267297  .036264   .0000000  .0000000   .011846  .072173  -.063122  .041518
+    1915.85  -.050020  .030742  -.262266  .023155   .0000000  .0000000  -.027821  .088036  -.038193  .050505
+    1915.90  -.047776  .025033  -.265495  .028877   .0000000  .0000000   .118091  .069539  -.019792  .039372
+    1915.95  -.135461  .023173  -.219164  .028298   .0000000  .0000000  -.012289  .086845  -.027399  .027321
+    1916.00  -.250486  .023204  -.127502  .022968   .0000000  .0000000  -.021577  .103420   .018951  .028163
+    1916.05  -.339030  .037330  -.192532  .045931   .0000000  .0000000   .024111  .137392  -.018940  .034175
+    1916.10  -.414793  .058039  -.366168  .141532   .0000000  .0000000  -.098174  .170431   .076541  .118153
+    1916.15  -.341536  .021953  -.026629  .029162   .0000000  .0000000   .169266  .088743  -.014264  .030157
+    1916.20  -.344556  .018814   .102289  .019703   .0000000  .0000000   .252240  .050378  -.029106  .028335
+    1916.25  -.312204  .024609   .143646  .020499   .0000000  .0000000   .180470  .047266   .015853  .027610
+    1916.30  -.283589  .023924   .181301  .020568   .0000000  .0000000   .143325  .058658   .063949  .026548
+    1916.35  -.251093  .018184   .263902  .019588   .0000000  .0000000   .138055  .053509   .020526  .024625
+    1916.40  -.158543  .020020   .396971  .033556   .0000000  .0000000   .158620  .085492   .044177  .026115
+    1916.45  -.236712  .062220   .246063  .050573   .0000000  .0000000   .136788  .152108   .143947  .057248
+    1916.50  -.049133  .028615   .295525  .022294   .0000000  .0000000  -.030297  .075359   .037090  .022295
+    1916.55  -.019000  .038200   .215800  .026700   .0000000  .0000000   .070100  .103300   .069400  .029700
+    1916.60   .091660  .018963   .193570  .018460   .0000000  .0000000  -.039878  .073489   .007240  .022693
+    1916.65   .171184  .018604   .142932  .016015   .0000000  .0000000   .230323  .045535   .085540  .025321
+    1916.70   .135500  .023400   .053900  .025100   .0000000  .0000000  -.046700  .057800  -.000100  .025700
+    1916.75   .159276  .025292  -.060418  .036456   .0000000  .0000000   .011834  .078911  -.008215  .026973
+    1916.80   .195249  .023248  -.060384  .023203   .0000000  .0000000   .031580  .041769  -.048167  .034018
+    1916.85   .041662  .033202  -.606821  .141969   .0000000  .0000000   .943431  .274302   .112475  .054856
+    1916.90   .012991  .025535  -.219566  .030003   .0000000  .0000000   .053736  .068762  -.061942  .039228
+    1916.95  -.003679  .034430  -.318930  .051949   .0000000  .0000000   .050138  .118290  -.018448  .050335
+    1917.00  -.095516  .031991  -.232917  .036690   .0000000  .0000000   .113371  .098425  -.038837  .039895
+    1917.05  -.151536  .032643  -.182785  .035632   .0000000  .0000000   .177793  .081918  -.049965  .028040
+    1917.10  -.182049  .018780  -.136279  .020541   .0000000  .0000000   .226590  .064294  -.029064  .017525
+    1917.15  -.292198  .021566  -.114514  .025900   .0000000  .0000000   .378588  .066745  -.025331  .022017
+    1917.20  -.293211  .023421  -.077170  .028302   .0000000  .0000000   .271657  .067886  -.007479  .030789
+    1917.25  -.310501  .018384  -.047076  .019377   .0000000  .0000000   .320842  .036052   .020607  .038323
+    1917.30  -.262144  .022858   .028782  .036242   .0000000  .0000000   .158905  .076173   .065957  .042121
+    1917.35  -.195616  .034674   .145893  .043448   .0000000  .0000000  -.131604  .107830   .175394  .060186
+    1917.40  -.216823  .016046   .172434  .021974   .0000000  .0000000   .205536  .089022   .029871  .023536
+    1917.45  -.195552  .023695   .154519  .024785   .0000000  .0000000   .094768  .093800   .041009  .017617
+    1917.50  -.114387  .021710   .252819  .017637   .0000000  .0000000   .160593  .109832   .011260  .015601
+    1917.55  -.014913  .026123   .095478  .050081   .0000000  .0000000   .119251  .121268  -.101896  .040784
+    1917.60  -.032948  .022517   .203552  .021771   .0000000  .0000000  -.017169  .093714  -.018236  .029087
+    1917.65  -.004274  .018041   .202191  .017393   .0000000  .0000000   .223112  .056366   .133130  .035319
+    1917.70  -.029300  .023400   .187800  .020200   .0000000  .0000000   .092500  .064100   .150900  .036000
+    1917.75   .047363  .042714   .077854  .035380   .0000000  .0000000  -.021470  .089513  -.046959  .056889
+    1917.80   .027454  .027359   .011902  .023281   .0000000  .0000000  -.023835  .047870  -.100501  .044000
+    1917.85   .086395  .033256   .016630  .018122   .0000000  .0000000   .164901  .073747  -.031988  .042757
+    1917.90   .011086  .026318   .026413  .034694   .0000000  .0000000   .093324  .100088  -.148308  .056746
+    1917.95   .061347  .020973  -.033647  .023957   .0000000  .0000000  -.024511  .101763   .006694  .027343
+    1918.00  -.045800  .028200  -.126500  .035300   .0000000  .0000000   .111100  .145300  -.004400  .040900
+    1918.05  -.063352  .035400  -.187119  .045038   .0000000  .0000000  -.004287  .122131   .022486  .027016
+    1918.10  -.140380  .021869  -.029766  .034383   .0000000  .0000000   .138678  .119162  -.033442  .029042
+    1918.15  -.139590  .025411  -.046948  .025044   .0000000  .0000000   .255759  .076958   .009428  .028052
+    1918.20  -.186229  .018686  -.012003  .022437   .0000000  .0000000   .099720  .046074  -.030547  .019541
+    1918.25  -.197272  .017486  -.022847  .021751   .0000000  .0000000   .138537  .040238   .001337  .024304
+    1918.30  -.162233  .019532   .009864  .026445   .0000000  .0000000   .072541  .049151  -.023444  .023410
+    1918.35  -.209522  .022531   .106965  .024980   .0000000  .0000000   .166654  .068932  -.049008  .032858
+    1918.40  -.183315  .017646   .111698  .021615   .0000000  .0000000   .030447  .078502   .025251  .021946
+    1918.45  -.186120  .023373   .161230  .026925   .0000000  .0000000   .057971  .095803   .032482  .020663
+    1918.50  -.206139  .033232   .170211  .036136   .0000000  .0000000   .083654  .106947   .070057  .023682
+    1918.55  -.140500  .023300   .134700  .019600   .0000000  .0000000   .227200  .082400   .039700  .023100
+    1918.60  -.075624  .019336   .126939  .021875   .0000000  .0000000   .214103  .104242   .041851  .030046
+    1918.65  -.035250  .017052   .149125  .023557   .0000000  .0000000   .188283  .065782   .040647  .035960
+    1918.70  -.038388  .018281   .139481  .017860   .0000000  .0000000   .132147  .048923  -.014313  .024805
+    1918.75   .005607  .032180   .126979  .025465   .0000000  .0000000   .182018  .068228  -.028571  .028371
+    1918.80  -.039489  .022068   .133454  .021575   .0000000  .0000000   .134319  .041766  -.041681  .031411
+    1918.85  -.047400  .036400   .170000  .021500   .0000000  .0000000   .337000  .084200  -.073900  .051500
+    1918.90  -.061884  .029362   .112716  .024389   .0000000  .0000000   .055984  .073331  -.062078  .035249
+    1918.95  -.059354  .023109   .062420  .030480   .0000000  .0000000   .077009  .074970  -.013496  .022825
+    1919.00  -.058158  .032137   .016625  .047864   .0000000  .0000000  -.016848  .102171  -.051654  .033902
+    1919.05  -.045037  .027163   .121493  .032572   .0000000  .0000000   .061742  .159161   .007806  .023268
+    1919.10  -.064165  .030520   .072740  .023797   .0000000  .0000000   .054161  .103195  -.030628  .028565
+    1919.15  -.046142  .019958   .055541  .023710   .0000000  .0000000   .175499  .058670   .000885  .017390
+    1919.20  -.076649  .021472   .084834  .024008   .0000000  .0000000   .192932  .054744   .038099  .024214
+    1919.25  -.032000  .023100   .101400  .024500   .0000000  .0000000   .019400  .044200  -.032300  .039800
+    1919.30  -.032764  .019670   .042454  .021259   .0000000  .0000000   .063473  .058489  -.018695  .035014
+    1919.35  -.034002  .016296   .057361  .029991   .0000000  .0000000  -.073542  .063390   .036074  .027766
+    1919.40  -.081513  .022556   .071678  .026159   .0000000  .0000000   .028931  .092000  -.007650  .026187
+    1919.45  -.024396  .025236   .011394  .055909   .0000000  .0000000  -.005223  .115240   .015397  .031016
+    1919.50  -.005435  .021494   .014449  .023472   .0000000  .0000000  -.038104  .127579  -.000757  .018115
+    1919.55  -.036700  .021400  -.072300  .031400   .0000000  .0000000   .269200  .086200   .023200  .025300
+    1919.60  -.054480  .015453  -.035798  .017133   .0000000  .0000000   .178399  .073800   .000860  .022478
+    1919.65  -.109833  .019620  -.018115  .022290   .0000000  .0000000   .165576  .057084   .045457  .031020
+    1919.70  -.180209  .028864  -.046368  .034048   .0000000  .0000000  -.171687  .073328  -.040531  .036099
+    1919.75  -.144050  .022290   .048583  .024879   .0000000  .0000000   .020057  .046725   .052546  .035444
+    1919.80  -.181892  .022085  -.009524  .029451   .0000000  .0000000   .105329  .047459   .021452  .057824
+    1919.85  -.159213  .031568   .054630  .033813   .0000000  .0000000   .116987  .080398  -.092610  .059791
+    1919.90  -.092562  .035587  -.197751  .085221   .0000000  .0000000   .508266  .132410  -.030663  .066537
+    1919.95  -.186227  .020600   .107207  .025198   .0000000  .0000000   .190069  .079840  -.028542  .020491
+    1920.00  -.097388  .030280   .112723  .034355   .0000000  .0000000   .077211  .158857   .019743  .045632
+    1920.05  -.145513  .024771   .244405  .039029   .0000000  .0000000   .138524  .118895   .020497  .021109
+    1920.10  -.066010  .025834   .127964  .037067   .0000000  .0000000   .069846  .071235   .039802  .023703
+    1920.15  -.108000  .026100   .125400  .030600   .0000000  .0000000   .066300  .061600  -.028500  .020500
+    1920.20  -.066646  .021442   .249459  .031772   .0000000  .0000000   .259358  .059627   .009901  .025076
+    1920.25   .062692  .073768   .241400  .067889   .0000000  .0000000  -.048321  .138016   .122761  .080310
+    1920.30   .077897  .026364   .212694  .025041   .0000000  .0000000   .062704  .072934   .037479  .040486
+    1920.35   .112620  .035137   .177084  .039181   .0000000  .0000000  -.098984  .079850  -.019825  .039959
+    1920.40   .081000  .026100   .157700  .026100   .0000000  .0000000  -.043700  .108300  -.015600  .028200
+    1920.45   .148386  .049244   .115656  .054235   .0000000  .0000000   .112764  .143248   .013350  .037333
+    1920.50   .111770  .030133   .088776  .036499   .0000000  .0000000   .028214  .158865   .019352  .026783
+    1920.55   .063562  .015232  -.046004  .020074   .0000000  .0000000   .165210  .082557   .043804  .025214
+    1920.60   .129866  .041977   .027842  .044099   .0000000  .0000000   .444455  .121075   .035385  .035705
+    1920.65   .091341  .025804  -.043051  .044110   .0000000  .0000000   .423298  .113613   .126527  .044771
+    1920.70   .068767  .019510  -.053549  .019567   .0000000  .0000000   .301134  .054516   .031598  .032433
+    1920.75  -.008467  .023590  -.089633  .026491   .0000000  .0000000   .246094  .050688  -.014311  .026566
+    1920.80  -.052510  .023572  -.063097  .026540   .0000000  .0000000   .236741  .048355   .000018  .029138
+    1920.85  -.131312  .033720  -.127174  .033493   .0000000  .0000000   .118162  .097614  -.029769  .052448
+    1920.90  -.098074  .032286  -.069955  .039897   .0000000  .0000000   .253234  .084957  -.026576  .049577
+    1920.95  -.202848  .015313  -.093388  .023228   .0000000  .0000000   .182078  .068140  -.040270  .013923
+    1921.00  -.275100  .066800   .041200  .042500   .0000000  .0000000  -.023400  .165100   .016600  .058000
+    1921.05  -.199380  .028586   .005397  .035333   .0000000  .0000000  -.091572  .106408   .013613  .024602
+    1921.10  -.269861  .029700   .062960  .035227   .0000000  .0000000   .056699  .084797   .008766  .026645
+    1921.15  -.315700  .072269   .186534  .055564   .0000000  .0000000   .005612  .166973  -.066640  .056276
+    1921.20  -.190287  .020595   .164991  .022318   .0000000  .0000000   .165225  .054654   .011393  .022283
+    1921.25  -.119466  .019502   .139311  .022964   .0000000  .0000000   .019224  .041993   .045599  .037519
+    1921.30  -.014599  .021085   .217462  .027666   .0000000  .0000000  -.095568  .071875   .053887  .036645
+    1921.35   .031054  .022785   .201362  .025135   .0000000  .0000000  -.092298  .078183   .029571  .039060
+    1921.40   .091820  .030242   .160909  .034076   .0000000  .0000000   .148554  .113642  -.091464  .030982
+    1921.45   .100985  .022216   .083825  .027543   .0000000  .0000000   .026744  .143369   .003906  .018410
+    1921.50   .212445  .039267   .182524  .042606   .0000000  .0000000   .140091  .125525  -.098040  .030768
+    1921.55   .138182  .021575   .088243  .019204   .0000000  .0000000   .229534  .076740   .023025  .021882
+    1921.60   .178414  .025674   .025800  .028487   .0000000  .0000000   .214034  .076980  -.028148  .027220
+    1921.65   .167323  .022291   .004838  .025249   .0000000  .0000000   .247682  .060809   .003549  .027454
+    1921.70   .073545  .013037  -.078915  .019119   .0000000  .0000000   .220099  .042119   .012353  .023753
+    1921.75   .127179  .026772  -.080673  .030632   .0000000  .0000000   .314240  .060325   .082886  .038983
+    1921.80  -.002474  .023205  -.169272  .027927   .0000000  .0000000   .209071  .046972  -.018626  .044988
+    1921.85  -.007518  .031000  -.143864  .026801   .0000000  .0000000   .203157  .091797  -.064613  .051434
+    1921.90  -.098209  .028421   .106262  .070691   .0000000  .0000000   .097249  .075872  -.090948  .061889
+    1921.95  -.133071  .031967  -.095128  .035219   .0000000  .0000000   .117126  .148240   .014827  .043509
+    1922.00  -.045524  .055991  -.029486  .044384   .0000000  .0000000   .307043  .104146  -.016902  .046439
+    1922.05  -.194756  .044532  -.097510  .058848   .0000000  .0000000   .106856  .218178   .015172  .035679
+    1922.10  -.208934  .027890   .039567  .023542   .0000000  .0000000  -.073805  .098981  -.066748  .026652
+    1922.15  -.210300  .032200   .137300  .030800   .0000000  .0000000   .054500  .114600  -.016000  .036100
+    1922.20  -.165744  .024812   .125734  .026711   .0000000  .0000000   .114625  .076649   .019807  .040009
+    1922.25  -.162390  .024060   .134218  .035829   .0000000  .0000000   .058232  .055785  -.023740  .059016
+    1922.30  -.132697  .018657   .221570  .018851   .0000000  .0000000  -.022634  .045866   .005230  .025428
+    1922.35  -.090259  .029663   .277564  .025982   .0000000  .0000000   .017361  .084752  -.018873  .040448
+    1922.40  -.047480  .019893   .260568  .022366   .0000000  .0000000   .175300  .084793  -.012303  .021789
+    1922.45   .009070  .019132   .222538  .023939   .0000000  .0000000  -.056816  .112701  -.019610  .016697
+    1922.50   .111622  .026181   .240501  .028555   .0000000  .0000000   .412616  .116971  -.064542  .019953
+    1922.55   .088770  .020152   .114259  .024598   .0000000  .0000000   .214716  .105492   .025888  .030218
+    1922.60   .163154  .024272   .076991  .025729   .0000000  .0000000  -.013639  .112548  -.019895  .030195
+    1922.65   .151317  .021950   .014994  .023451   .0000000  .0000000   .186478  .061686  -.002172  .033412
+    1922.70   .141800  .018300   .014900  .018700   .0000000  .0000000   .139000  .038700   .018300  .031200
+    1922.75   .120772  .026230  -.019145  .032331   .0000000  .0000000   .103344  .057611   .012603  .056829
+    1922.80   .083381  .019058  -.139651  .018579   .0000000  .0000000   .134790  .050035  -.044946  .030526
+    1922.85   .063654  .035885  -.088851  .036843   .0000000  .0000000   .060419  .131035  -.020871  .058891
+    1922.90   .041976  .038739   .015059  .046298   .0000000  .0000000   .137765  .082264   .022699  .035152
+    1922.95  -.163179  .049215  -.120346  .044629   .0000000  .0000000  -.088422  .186106   .057819  .039344
+    1923.00  -.162345  .024176  -.088042  .028195   .0000000  .0000000  -.164558  .105026   .022870  .021395
+    1923.05  -.166986  .029597  -.055441  .032552   .0000000  .0000000  -.155703  .122746  -.022616  .036478
+    1923.10  -.332673  .046590  -.032441  .038226   .0000000  .0000000   .118174  .100248   .127325  .057503
+    1923.15  -.262008  .031040  -.033456  .038152   .0000000  .0000000  -.075136  .091210  -.070144  .043722
+    1923.20  -.207748  .020628   .016212  .020991   .0000000  .0000000  -.002057  .040807  -.018829  .031774
+    1923.25  -.274792  .051456   .140175  .032202   .0000000  .0000000   .200018  .110268   .020372  .031238
+    1923.30  -.179152  .022040   .157417  .021359   .0000000  .0000000  -.096701  .057214   .020842  .030157
+    1923.35  -.176779  .038078   .129676  .046107   .0000000  .0000000   .232484  .110410   .012090  .038815
+    1923.40  -.097364  .026461   .300984  .030708   .0000000  .0000000   .012199  .114308  -.024269  .032124
+    1923.45  -.024124  .029729   .317510  .037800   .0000000  .0000000   .242278  .122543  -.026966  .025412
+    1923.50  -.019994  .014380   .239535  .021068   .0000000  .0000000   .097043  .096033   .007601  .012214
+    1923.55   .060132  .038504   .240230  .038033   .0000000  .0000000   .008628  .090767  -.027426  .036225
+    1923.60   .112367  .014229   .311274  .019214   .0000000  .0000000   .109885  .052765   .034879  .027024
+    1923.65   .142183  .016013   .249476  .023914   .0000000  .0000000   .086034  .050317   .040333  .029040
+    1923.70   .151780  .026662   .226170  .029457   .0000000  .0000000   .065406  .051934   .009481  .027690
+    1923.75   .161990  .027635   .129040  .031921   .0000000  .0000000  -.002354  .060430   .038004  .044922
+    1923.80   .130175  .022364   .020789  .024598   .0000000  .0000000   .076566  .061195  -.044418  .038181
+    1923.85   .136144  .036406   .082803  .038211   .0000000  .0000000  -.134067  .095774   .027947  .040494
+    1923.90   .088243  .027972   .024731  .025906   .0000000  .0000000  -.078050  .103716   .037490  .030391
+    1923.95   .035504  .031898  -.012841  .031608   .0000000  .0000000   .128937  .135153   .027011  .025480
+    1924.00  -.005804  .035143   .073064  .051468   .0000000  .0000000  -.102657  .167052   .001261  .032029
+    1924.05  -.068517  .027242   .011667  .025525   .0000000  .0000000   .059077  .111376   .021297  .030942
+    1924.10  -.029063  .036913   .003840  .046785   .0000000  .0000000   .232378  .154239   .074931  .048315
+    1924.15  -.149500  .033400  -.020500  .049200   .0000000  .0000000   .296300  .127700   .093800  .074500
+    1924.20  -.151107  .021433   .038096  .026611   .0000000  .0000000   .023358  .049099   .009227  .029539
+    1924.25  -.170714  .022449   .072246  .022869   .0000000  .0000000   .026865  .044276  -.077597  .042873
+    1924.30  -.127400  .020900   .135100  .025000   .0000000  .0000000  -.040200  .068600  -.015300  .035600
+    1924.35  -.165261  .035290   .139194  .034218   .0000000  .0000000  -.000914  .122546  -.014604  .040754
+    1924.40  -.187563  .014175   .107926  .015713   .0000000  .0000000   .089797  .091070  -.022451  .023568
+    1924.45  -.081980  .023478   .195088  .030162   .0000000  .0000000   .124901  .125047  -.048720  .019768
+    1924.50  -.075229  .031225   .183050  .046061   .0000000  .0000000   .102382  .137256  -.009329  .023857
+    1924.55  -.059435  .017414   .142566  .018273   .0000000  .0000000   .192221  .072824   .009825  .019926
+    1924.60   .014627  .017728   .135909  .020162   .0000000  .0000000   .138120  .065731   .009780  .030529
+    1924.65   .029893  .027133   .185564  .023512   .0000000  .0000000   .102141  .075815   .020640  .040568
+    1924.70  -.002107  .026548   .154303  .031812   .0000000  .0000000  -.026603  .057367  -.011327  .030482
+    1924.75   .041539  .036354   .113626  .034837   .0000000  .0000000   .151911  .071214   .043723  .033814
+    1924.80   .032319  .024384   .000498  .024990   .0000000  .0000000   .207029  .078052  -.085419  .044908
+    1924.85  -.079291  .038861   .056224  .034261   .0000000  .0000000   .076218  .110676  -.016385  .058046
+    1924.90  -.006172  .018051   .025546  .020137   .0000000  .0000000  -.054575  .085395   .029590  .022098
+    1924.95   .035597  .040982   .085593  .033254   .0000000  .0000000   .234642  .097196   .022594  .030779
+    1925.00  -.012995  .031013   .036963  .045216   .0000000  .0000000   .188166  .186937   .012966  .026431
+    1925.05  -.056182  .020519  -.049412  .028318   .0000000  .0000000   .285166  .064449   .087534  .023179
+    1925.10  -.103481  .027056  -.003581  .026594   .0000000  .0000000   .125679  .101046  -.029143  .030668
+    1925.15  -.107312  .034292  -.041495  .031768   .0000000  .0000000   .212551  .082271  -.011883  .035673
+    1925.20  -.141179  .021992  -.046236  .026297   .0000000  .0000000  -.026763  .049519  -.021964  .028860
+    1925.25  -.102647  .037056   .016748  .044842   .0000000  .0000000  -.039005  .088062  -.049630  .046314
+    1925.30  -.130539  .021781   .119861  .026310   .0000000  .0000000   .018221  .070534  -.089786  .034850
+    1925.35  -.066774  .024942   .097721  .023850   .0000000  .0000000  -.014274  .068507  -.016102  .033898
+    1925.40  -.004013  .035871   .055231  .029359   .0000000  .0000000   .224329  .117863   .022171  .035324
+    1925.45  -.066873  .019233   .032174  .023508   .0000000  .0000000   .259899  .137874  -.029799  .017789
+    1925.50  -.055672  .016072   .061909  .019348   .0000000  .0000000   .361168  .126978   .002462  .014184
+    1925.55  -.070311  .022033   .114851  .022917   .0000000  .0000000   .040450  .074518   .020575  .020834
+    1925.60   .017853  .031090   .118506  .030840   .0000000  .0000000   .070523  .090048   .005634  .031098
+    1925.65  -.015743  .021671   .056794  .019940   .0000000  .0000000   .035280  .051561   .027148  .024849
+    1925.70   .001485  .022114   .004726  .025001   .0000000  .0000000   .123941  .045601   .003221  .030968
+    1925.75  -.005631  .042884   .015549  .045587   .0000000  .0000000   .017215  .067382  -.048574  .041449
+    1925.80   .001128  .022221   .013928  .028038   .0000000  .0000000   .024302  .054538  -.002247  .034619
+    1925.85  -.243256  .079470  -.060509  .053110   .0000000  .0000000   .276019  .175165  -.019029  .077528
+    1925.90  -.025734  .030105   .007049  .023785   .0000000  .0000000   .121188  .105485   .002998  .040199
+    1925.95  -.041648  .066166  -.013321  .030918   .0000000  .0000000   .015089  .105117   .021729  .049347
+    1926.00  -.199605  .036146  -.083663  .038724   .0000000  .0000000   .245215  .109884   .039478  .035638
+    1926.05  -.163818  .039434  -.029853  .040669   .0000000  .0000000   .044359  .068495   .053898  .032339
+    1926.10  -.073051  .027728  -.074540  .032460   .0000000  .0000000   .213393  .066358  -.048102  .023696
+    1926.15  -.177265  .023116  -.060285  .021659   .0000000  .0000000   .105872  .050817  -.037163  .026399
+    1926.20  -.230084  .046104  -.024826  .045615   .0000000  .0000000   .025719  .090929   .040620  .034105
+    1926.25  -.173813  .019079   .058121  .020126   .0000000  .0000000   .132828  .041532  -.018853  .028000
+    1926.30  -.052708  .037348   .122825  .027319   .0000000  .0000000  -.076773  .071126  -.041129  .037601
+    1926.35  -.106664  .050808   .067451  .031627   .0000000  .0000000   .269221  .103461  -.035203  .041686
+    1926.40  -.129567  .034399   .112402  .028636   .0000000  .0000000  -.020163  .110908   .014179  .027107
+    1926.45  -.076581  .041883   .132865  .051608   .0000000  .0000000   .286320  .144497  -.043525  .025421
+    1926.50  -.051765  .019589   .131885  .021134   .0000000  .0000000   .052798  .090155   .047918  .015748
+    1926.55  -.033933  .030075   .119936  .029214   .0000000  .0000000   .315712  .098450   .006669  .028847
+    1926.60  -.053049  .024930   .122331  .026656   .0000000  .0000000   .154883  .074546   .015092  .039362
+    1926.65  -.021532  .025016   .117705  .028125   .0000000  .0000000   .160320  .076375   .063924  .039989
+    1926.70   .018915  .028880   .156256  .031268   .0000000  .0000000   .164856  .056655  -.000981  .030026
+    1926.75  -.001894  .051763   .104146  .035162   .0000000  .0000000   .018542  .092282  -.065648  .073984
+    1926.80  -.075772  .034355   .076597  .025218   .0000000  .0000000   .115426  .075478  -.006398  .036664
+    1926.85  -.120294  .031359   .111799  .022066   .0000000  .0000000   .009381  .067532   .019260  .032445
+    1926.90  -.050061  .047015   .130391  .040796   .0000000  .0000000  -.137747  .156385   .046403  .040460
+    1926.95  -.098525  .038333   .073404  .038221   .0000000  .0000000   .009895  .081858   .017527  .033499
+    1927.00  -.058200  .031028   .056215  .030066   .0000000  .0000000   .045607  .114872   .011025  .024078
+    1927.05  -.142988  .021528   .109762  .025240   .0000000  .0000000   .117355  .050786   .038633  .014167
+    1927.10  -.032237  .029414   .116674  .028615   .0000000  .0000000   .072703  .088337   .033588  .026881
+    1927.15  -.095191  .041669   .115885  .031413   .0000000  .0000000  -.020091  .084410  -.002517  .021791
+    1927.20  -.059447  .042723   .084129  .029841   .0000000  .0000000   .129499  .067080   .031133  .036799
+    1927.25  -.115876  .069511   .071429  .057155   .0000000  .0000000  -.078722  .128583  -.029423  .079680
+    1927.30  -.052232  .023950   .049356  .028721   .0000000  .0000000  -.131758  .063986  -.015955  .033137
+    1927.35  -.054137  .026269   .027885  .031093   .0000000  .0000000  -.111493  .097984  -.040770  .029515
+    1927.40  -.013624  .039136   .120684  .028181   .0000000  .0000000   .007610  .143696  -.035268  .039320
+    1927.45   .095331  .054825   .074304  .030591   .0000000  .0000000   .251516  .118766   .055469  .038560
+    1927.50   .015128  .025200   .128662  .022917   .0000000  .0000000   .098949  .079649  -.039049  .019701
+    1927.55  -.016024  .022647   .158240  .023726   .0000000  .0000000   .097476  .087155  -.044639  .022680
+    1927.60  -.031647  .018259   .047004  .021176   .0000000  .0000000   .125683  .060861   .048557  .029299
+    1927.65  -.020014  .030139   .048718  .035066   .0000000  .0000000   .149458  .064278   .009084  .029568
+    1927.70  -.004146  .030681   .054252  .029156   .0000000  .0000000   .114527  .062750  -.020703  .027155
+    1927.75  -.052691  .022091   .005745  .024345   .0000000  .0000000   .004075  .043762  -.019228  .034849
+    1927.80  -.052571  .021420  -.025327  .020197   .0000000  .0000000   .121377  .062185  -.034289  .031578
+    1927.85  -.093446  .029344  -.044573  .032284   .0000000  .0000000   .242147  .119038  -.103622  .049001
+    1927.90  -.185615  .022153   .036816  .025910   .0000000  .0000000  -.005638  .086229   .039597  .024397
+    1927.95  -.159711  .056181  -.002380  .036259   .0000000  .0000000   .080488  .138148  -.032442  .037062
+    1928.00  -.008822  .073018  -.065239  .048131   .0000000  .0000000   .060773  .116263  -.147510  .046945
+    1928.05  -.145700  .027000  -.017500  .028100   .0000000  .0000000   .270700  .055800  -.018800  .023000
+    1928.10  -.134670  .045726   .100011  .059042   .0000000  .0000000   .168304  .084694   .043459  .044433
+    1928.15  -.142914  .038281   .014838  .046056   .0000000  .0000000   .107359  .084557  -.028794  .052158
+    1928.20  -.130658  .024641   .109191  .027751   .0000000  .0000000   .026775  .050999  -.017275  .032088
+    1928.25  -.071799  .039508   .135022  .041766   .0000000  .0000000  -.192268  .090376  -.008559  .044952
+    1928.30  -.077913  .033120   .109713  .023627   .0000000  .0000000  -.035111  .069778   .018221  .041598
+    1928.35  -.084562  .016658   .184119  .017469   .0000000  .0000000  -.049343  .069065   .025439  .023154
+    1928.40  -.070452  .022088   .122462  .029237   .0000000  .0000000   .106064  .091812  -.013073  .025375
+    1928.45  -.071262  .019075   .128166  .024402   .0000000  .0000000   .173467  .102949  -.034195  .016324
+    1928.50  -.023166  .030166   .138252  .028569   .0000000  .0000000   .127043  .091048  -.010519  .024191
+    1928.55  -.049392  .022526   .114652  .023977   .0000000  .0000000   .083308  .071831  -.025202  .024135
+    1928.60  -.132084  .056938  -.134582  .083942   .0000000  .0000000  -.190699  .101467   .059541  .048184
+    1928.65   .020427  .019776   .100107  .024660   .0000000  .0000000   .087240  .054196   .014561  .032237
+    1928.70  -.028438  .018567   .032299  .019668   .0000000  .0000000  -.034806  .039592   .048647  .026722
+    1928.75  -.110100  .026400   .107500  .033000   .0000000  .0000000  -.023100  .060300   .111700  .072200
+    1928.80  -.143376  .025745  -.000841  .024534   .0000000  .0000000  -.069267  .061539  -.023213  .023665
+    1928.85  -.115036  .034254   .011216  .024412   .0000000  .0000000   .040894  .081254  -.065663  .034994
+    1928.90  -.110841  .024115   .085727  .033606   .0000000  .0000000   .007425  .148468  -.024778  .044137
+    1928.95  -.072093  .032112   .151032  .037101   .0000000  .0000000   .038861  .124679  -.002752  .024079
+    1929.00  -.160303  .029001   .044210  .030370   .0000000  .0000000   .121852  .128216  -.032636  .021252
+    1929.05  -.288649  .053456   .003539  .044103   .0000000  .0000000  -.023736  .147949  -.084211  .042433
+    1929.10  -.100071  .039581   .109711  .034391   .0000000  .0000000   .289148  .113132  -.033205  .044177
+    1929.15  -.169363  .033012   .171496  .030953   .0000000  .0000000   .241431  .111617  -.005452  .049005
+    1929.20  -.126222  .020713   .140853  .024303   .0000000  .0000000   .067108  .045114  -.056829  .037420
+    1929.25  -.057249  .016782   .149535  .017242   .0000000  .0000000   .031820  .032694  -.046550  .031388
+    1929.30   .003629  .032178   .164681  .031323   .0000000  .0000000   .092760  .083365   .035925  .044336
+    1929.35   .131595  .040910   .332923  .037479   .0000000  .0000000  -.356197  .110153   .059423  .033529
+    1929.40   .031158  .021226   .160059  .029831   .0000000  .0000000   .028882  .119329   .013646  .030434
+    1929.45   .069220  .021082   .115295  .019283   .0000000  .0000000   .196940  .112372   .007935  .014267
+    1929.50   .103978  .030232   .187112  .034392   .0000000  .0000000   .202257  .130538   .013072  .024857
+    1929.55   .082883  .017225   .085168  .023736   .0000000  .0000000   .082421  .084147   .017983  .020976
+    1929.60   .049832  .020908  -.000080  .026960   .0000000  .0000000   .138280  .081479   .046409  .034977
+    1929.65   .073767  .019423   .013919  .021340   .0000000  .0000000   .065310  .066193   .016860  .034935
+    1929.70   .084972  .061105   .064950  .075161   .0000000  .0000000   .161526  .109929  -.025795  .083002
+    1929.75  -.015329  .020990  -.028934  .031128   .0000000  .0000000  -.002841  .046003  -.101838  .056884
+    1929.80  -.093999  .017499  -.073280  .016597   .0000000  .0000000   .073164  .043236  -.044932  .023701
+    1929.85  -.161299  .029904  -.061529  .021325   .0000000  .0000000  -.006386  .072407   .008835  .041415
+    1929.90  -.165908  .024019  -.084395  .026630   .0000000  .0000000  -.121433  .117280   .028022  .031988
+    1929.95  -.205862  .034033   .028014  .040755   .0000000  .0000000   .026057  .137650  -.067140  .030804
+    1930.00  -.214153  .025399  -.044059  .024030   .0000000  .0000000   .202892  .112867   .004848  .020655
+    1930.05  -.215942  .020998   .054329  .022252   .0000000  .0000000   .153369  .082377  -.003220  .020741
+    1930.10  -.225480  .033817   .057826  .028905   .0000000  .0000000   .103087  .099115  -.045942  .038739
+    1930.15  -.206525  .026438   .096138  .031489   .0000000  .0000000   .032674  .078500   .019438  .036829
+    1930.20  -.166814  .026412   .146704  .021097   .0000000  .0000000   .070394  .052440  -.038621  .031795
+    1930.25  -.130922  .025349   .224514  .023384   .0000000  .0000000  -.037018  .048621   .040396  .033628
+    1930.30  -.049593  .026987   .179473  .025143   .0000000  .0000000   .135378  .074078  -.008703  .042877
+    1930.35  -.125200  .026100   .154900  .024500   .0000000  .0000000   .104500  .094000  -.024100  .028100
+    1930.40   .006745  .019346   .237422  .020329   .0000000  .0000000  -.048105  .087983   .035750  .025097
+    1930.45   .017674  .022192   .198183  .024829   .0000000  .0000000   .497903  .112541  -.047527  .017231
+    1930.50   .035577  .019204   .132240  .022916   .0000000  .0000000   .114673  .112661   .031958  .015928
+    1930.55   .081022  .028941   .126161  .035280   .0000000  .0000000   .178570  .113183   .044067  .033186
+    1930.60   .098407  .020433   .114242  .025772   .0000000  .0000000   .115599  .079567   .015376  .029606
+    1930.65   .074379  .020892  -.037760  .025658   .0000000  .0000000  -.079804  .064054   .053494  .038670
+    1930.70   .062912  .022160  -.022243  .022567   .0000000  .0000000   .042622  .042296  -.013889  .047025
+    1930.75   .028598  .018984   .019082  .021020   .0000000  .0000000   .040430  .039123  -.000354  .032659
+    1930.80  -.011225  .023863  -.081563  .021891   .0000000  .0000000   .037880  .062133  -.007597  .035154
+    1930.85  -.084804  .062224  -.009200  .038617   .0000000  .0000000  -.028399  .149308   .076616  .069941
+    1930.90  -.116025  .028558  -.003658  .026403   .0000000  .0000000   .122780  .124121  -.036343  .039668
+    1930.95  -.158405  .032485  -.031682  .028104   .0000000  .0000000   .230804  .094347  -.015785  .025706
+    1931.00  -.353309  .096479   .027867  .089982   .0000000  .0000000  -.059218  .147494   .047382  .083239
+    1931.05  -.277671  .037328   .046550  .032796   .0000000  .0000000   .029490  .181518   .039120  .037162
+    1931.10  -.239000  .080700  -.015100  .066000   .0000000  .0000000   .135500  .183700  -.036200  .061100
+    1931.15  -.355078  .047704   .116611  .027520   .0000000  .0000000  -.068468  .119503  -.011647  .037294
+    1931.20  -.226864  .040213   .167103  .029516   .0000000  .0000000   .008206  .083614   .006204  .048961
+    1931.25  -.248657  .048779   .182523  .025817   .0000000  .0000000  -.106053  .087283  -.017485  .048950
+    1931.30  -.150564  .025159   .238762  .019410   .0000000  .0000000  -.021250  .053953  -.038649  .032878
+    1931.35  -.151393  .023537   .231228  .027262   .0000000  .0000000   .005501  .079420   .004284  .027058
+    1931.40  -.039529  .026810   .281355  .018958   .0000000  .0000000   .011981  .079330  -.009609  .023743
+    1931.45   .024987  .022077   .296176  .025076   .0000000  .0000000   .034315  .105782   .013971  .017995
+    1931.50   .039600  .020200   .242500  .021800   .0000000  .0000000   .024100  .122600  -.003900  .015000
+    1931.55   .074415  .022490   .182812  .023523   .0000000  .0000000   .025877  .085360   .022079  .023021
+    1931.60   .098426  .027142   .094944  .022076   .0000000  .0000000   .019474  .068532   .038770  .032649
+    1931.65   .082462  .022539   .055652  .020618   .0000000  .0000000  -.131105  .059693   .032424  .033455
+    1931.70   .165785  .028535   .079323  .020027   .0000000  .0000000   .014870  .042304  -.046763  .030159
+    1931.75   .067878  .020433   .029704  .017501   .0000000  .0000000  -.026892  .036533  -.004535  .030519
+    1931.80   .052973  .019446  -.106345  .016117   .0000000  .0000000  -.001599  .049110   .000611  .027249
+    1931.85  -.083590  .035160  -.105084  .021113   .0000000  .0000000   .167197  .098585  -.038658  .042268
+    1931.90  -.060868  .023135  -.054736  .023489   .0000000  .0000000   .098301  .077842  -.032916  .026478
+    1931.95  -.091079  .025492  -.143458  .016987   .0000000  .0000000   .006878  .111090   .002060  .014193
+    1932.00  -.117202  .022857  -.090917  .014931   .0000000  .0000000   .032518  .104975  -.031310  .014357
+    1932.05  -.196529  .025311  -.057717  .024631   .0000000  .0000000   .020887  .093791  -.023320  .023453
+    1932.10  -.166200  .038500  -.015500  .021000   .0000000  .0000000   .148800  .080700  -.020600  .028300
+    1932.15  -.312357  .031985   .014781  .024170   .0000000  .0000000   .038023  .080383  -.026564  .031241
+    1932.20  -.324819  .072653   .020690  .050831   .0000000  .0000000   .031104  .170624  -.100605  .080162
+    1932.25  -.229236  .026510   .137146  .021528   .0000000  .0000000   .013136  .050132   .049470  .031438
+    1932.30  -.199450  .026455   .181143  .016335   .0000000  .0000000   .095308  .054191  -.026872  .023956
+    1932.35  -.169007  .034571   .207207  .032670   .0000000  .0000000   .044033  .102384   .025012  .037867
+    1932.40  -.138350  .036293   .219864  .040626   .0000000  .0000000   .060440  .140345   .036075  .038355
+    1932.45  -.071670  .043042   .214482  .046258   .0000000  .0000000  -.173260  .179819  -.021750  .028001
+    1932.50  -.075142  .023103   .230743  .021057   .0000000  .0000000   .103975  .124324   .021563  .016261
+    1932.55  -.052070  .017708   .236227  .018063   .0000000  .0000000  -.052630  .081070   .009506  .023476
+    1932.60   .026338  .029331   .224720  .020402   .0000000  .0000000   .121501  .071173   .029831  .028301
+    1932.65   .071800  .021400   .178200  .016200   .0000000  .0000000   .176200  .064800   .027600  .034400
+    1932.70   .070092  .031963   .209808  .019638   .0000000  .0000000   .157431  .046568  -.018677  .039795
+    1932.75   .087369  .026903   .059518  .018128   .0000000  .0000000   .041519  .042163   .044435  .039343
+    1932.80   .122666  .029306   .122560  .023321   .0000000  .0000000   .119499  .083814   .019577  .054465
+    1932.85   .085699  .034806   .068358  .021347   .0000000  .0000000   .049531  .108948  -.015296  .041625
+    1932.90   .094388  .040534   .033874  .026315   .0000000  .0000000  -.108647  .114058  -.060994  .031474
+    1932.95   .097006  .050740   .030486  .029273   .0000000  .0000000   .482296  .145305   .000628  .028292
+    1933.00  -.073655  .027436  -.011865  .031985   .0000000  .0000000   .162502  .157095  -.020578  .021128
+    1933.05  -.058596  .051280   .014472  .053169   .0000000  .0000000   .223380  .102794   .066612  .048012
+    1933.10  -.188030  .022039  -.012586  .033302   .0000000  .0000000   .250070  .092253   .044862  .039280
+    1933.15  -.173476  .033322   .013624  .023011   .0000000  .0000000   .194918  .072032   .048475  .039047
+    1933.20  -.221474  .041821   .048831  .041000   .0000000  .0000000   .119403  .071452  -.081642  .051296
+    1933.25  -.211408  .022399   .107715  .020713   .0000000  .0000000  -.020870  .044128  -.019603  .039541
+    1933.30  -.186714  .030754   .112536  .021771   .0000000  .0000000  -.002865  .075552   .026320  .049219
+    1933.35  -.179116  .026288   .019117  .087056   .0000000  .0000000  -.201524  .142281   .035768  .052919
+    1933.40  -.132931  .016888   .166511  .016395   .0000000  .0000000   .060002  .072293  -.004573  .020527
+    1933.45  -.129933  .016924   .222792  .014909   .0000000  .0000000   .286473  .091703  -.005444  .011969
+    1933.50  -.065800  .025900   .247600  .020300   .0000000  .0000000   .311900  .120900  -.017000  .016600
+    1933.55  -.061257  .021807   .170077  .017113   .0000000  .0000000   .039399  .081939  -.018902  .022170
+    1933.60  -.092890  .018754   .168864  .018460   .0000000  .0000000   .113285  .056890   .045761  .023309
+    1933.65  -.011311  .017613   .114462  .013330   .0000000  .0000000   .064859  .048461   .045019  .025788
+    1933.70  -.041560  .030493   .155440  .028708   .0000000  .0000000   .049236  .053531  -.015828  .042651
+    1933.75  -.007268  .017906   .135250  .018020   .0000000  .0000000  -.007973  .034135  -.000158  .033869
+    1933.80  -.048100  .019500   .064100  .017400   .0000000  .0000000   .017600  .058100  -.063400  .038000
+    1933.85  -.030166  .025628   .051458  .019159   .0000000  .0000000   .034753  .089541   .032965  .037829
+    1933.90  -.059454  .029041   .050490  .020860   .0000000  .0000000  -.164756  .096039   .047298  .032548
+    1933.95  -.000334  .034076  -.055485  .023257   .0000000  .0000000   .230726  .104399   .016229  .025451
+    1934.00  -.047994  .028916   .160539  .032204   .0000000  .0000000   .065271  .168737  -.021590  .027670
+    1934.05  -.128330  .116172   .132957  .078644   .0000000  .0000000  -.139608  .119120  -.007947  .065655
+    1934.10  -.104712  .044574  -.032479  .045279   .0000000  .0000000   .189751  .182927  -.016887  .044388
+    1934.15  -.123185  .034839   .026628  .023806   .0000000  .0000000  -.001909  .080452   .042261  .036319
+    1934.20  -.156884  .022421   .046650  .014031   .0000000  .0000000  -.077774  .035064  -.053603  .025990
+    1934.25  -.146878  .022878   .039678  .017834   .0000000  .0000000   .004010  .039645   .032796  .035823
+    1934.30  -.212952  .024627   .066280  .025561   .0000000  .0000000   .004615  .064923  -.011894  .041422
+    1934.35  -.109680  .021540   .080647  .019629   .0000000  .0000000  -.072650  .066917   .003651  .024807
+    1934.40  -.064907  .045330   .218438  .045155   .0000000  .0000000  -.371262  .146182   .036964  .043452
+    1934.45  -.115818  .023038   .182058  .018394   .0000000  .0000000   .101136  .124249  -.027130  .015075
+    1934.50  -.093600  .024600   .146400  .021300   .0000000  .0000000  -.052800  .123400  -.006600  .016700
+    1934.55  -.026049  .035938   .206821  .025948   .0000000  .0000000   .146997  .091495  -.058792  .031002
+    1934.60  -.036375  .029411   .197949  .023037   .0000000  .0000000   .099724  .078245  -.046107  .031760
+    1934.65  -.018200  .015900   .130900  .014700   .0000000  .0000000   .117400  .055500   .027800  .028700
+    1934.70   .003251  .029618   .176660  .036611   .0000000  .0000000   .038319  .058136   .000146  .038912
+    1934.75  -.019469  .019153   .192448  .019467   .0000000  .0000000   .035354  .039079  -.123725  .034856
+    1934.80   .016400  .020800   .142200  .015600   .0000000  .0000000   .110800  .041500  -.044200  .026500
+    1934.85   .017784  .039544   .028679  .035506   .0000000  .0000000   .034240  .080020  -.051485  .039956
+    1934.90  -.064537  .023501   .102035  .022977   .0000000  .0000000  -.032496  .110469   .037326  .032922
+    1934.95  -.095694  .072841   .072497  .043608   .0000000  .0000000   .066833  .100561   .004247  .038628
+    1935.00  -.053671  .027453   .063917  .025431   .0000000  .0000000   .530155  .161149  -.037620  .019547
+    1935.05  -.169016  .044842   .020530  .061196   .0000000  .0000000   .000152  .139986   .016457  .054370
+    1935.10   .005900  .041800   .019800  .023600   .0000000  .0000000   .105800  .093200  -.024400  .029100
+    1935.15  -.121309  .039625   .043629  .025194   .0000000  .0000000   .154113  .083605   .027210  .035617
+    1935.20  -.067132  .058136   .059209  .032996   .0000000  .0000000   .070527  .094074   .016045  .067279
+    1935.25  -.065954  .020239   .062433  .016524   .0000000  .0000000   .020752  .038651   .017978  .031286
+    1935.30  -.066468  .018206   .107258  .015299   .0000000  .0000000   .147676  .050194  -.030079  .029955
+    1935.35  -.021635  .032644   .104029  .022829   .0000000  .0000000   .127678  .090082  -.013917  .034060
+    1935.40  -.033804  .023187   .063816  .014742   .0000000  .0000000   .084520  .068957  -.018098  .020813
+    1935.45  -.056658  .021884   .141422  .022076   .0000000  .0000000   .067394  .119437  -.035622  .016660
+    1935.50  -.052090  .023446   .108980  .020627   .0000000  .0000000   .081002  .098951  -.009813  .017371
+    1935.55  -.177790  .028614  -.002912  .021799   .0000000  .0000000   .175896  .084399   .095563  .025291
+    1935.60  -.039043  .021399   .085087  .019792   .0000000  .0000000   .042098  .070193  -.024099  .027889
+    1935.65  -.133855  .029242   .062467  .018438   .0000000  .0000000   .015839  .059663  -.000203  .031181
+    1935.70  -.005002  .024380   .093252  .014874   .0000000  .0000000   .086950  .036097  -.071649  .026762
+    1935.75  -.055390  .044761   .041687  .032838   .0000000  .0000000   .035882  .084773   .030563  .038356
+    1935.80  -.109561  .032418   .035449  .020733   .0000000  .0000000   .044617  .062241   .051621  .032317
+    1935.85  -.173680  .063585   .091852  .041729   .0000000  .0000000   .191925  .110010  -.010510  .050761
+    1935.90  -.136077  .022508   .056437  .019658   .0000000  .0000000   .189125  .083693  -.032856  .027713
+    1935.95  -.015578  .049221   .047611  .030480   .0000000  .0000000   .212536  .151736  -.092986  .028781
+    1936.00   .023251  .075588   .090679  .029556   .0000000  .0000000  -.002397  .137610  -.040276  .034707
+    1936.05  -.146877  .035923   .108152  .031524   .0000000  .0000000  -.182166  .136466  -.078906  .033638
+    1936.10  -.047500  .045100   .098500  .029300   .0000000  .0000000   .059100  .095300  -.064600  .041600
+    1936.15  -.125964  .044336   .209295  .047551   .0000000  .0000000  -.013101  .148607   .038221  .034734
+    1936.20  -.159573  .031869   .182595  .024035   .0000000  .0000000   .086452  .052309   .002678  .050131
+    1936.25  -.106700  .021800   .188100  .024300   .0000000  .0000000   .083400  .045200   .004700  .036900
+    1936.30  -.080483  .037462   .175745  .023124   .0000000  .0000000   .182437  .068031  -.021893  .040778
+    1936.35  -.093917  .025288   .159713  .018555   .0000000  .0000000   .254458  .063727   .016423  .025453
+    1936.40  -.037416  .027242   .107419  .017531   .0000000  .0000000   .164477  .088120  -.023220  .024444
+    1936.45   .060450  .027773   .167046  .014396   .0000000  .0000000   .176408  .107607  -.063856  .013305
+    1936.50  -.013617  .028925   .143961  .025305   .0000000  .0000000   .236894  .130004   .035176  .020557
+    1936.55  -.000451  .017115   .115066  .017856   .0000000  .0000000   .122627  .081777  -.058150  .020610
+    1936.60  -.004315  .025184   .072471  .020889   .0000000  .0000000   .038232  .081985  -.058168  .031985
+    1936.65  -.043164  .028713   .033288  .021693   .0000000  .0000000   .094645  .064962   .018201  .035522
+    1936.70  -.018826  .029628   .032928  .023917   .0000000  .0000000   .155039  .054656  -.025877  .033828
+    1936.75  -.074570  .021101  -.007560  .019749   .0000000  .0000000   .080734  .039849  -.029856  .040096
+    1936.80  -.106024  .027836  -.004717  .023634   .0000000  .0000000  -.100276  .067963   .123125  .041897
+    1936.85  -.100771  .034341  -.011306  .033811   .0000000  .0000000   .091602  .124978   .002425  .049008
+    1936.90  -.188334  .046712   .029368  .036290   .0000000  .0000000   .144275  .148300   .051888  .054622
+    1936.95  -.173300  .034400  -.047400  .033100   .0000000  .0000000   .208300  .134200  -.087100  .029800
+    1937.00  -.140145  .030719   .085152  .035730   .0000000  .0000000  -.028907  .188436   .019138  .025183
+    1937.05  -.193481  .028051   .094688  .027126   .0000000  .0000000   .064059  .116828  -.054443  .026500
+    1937.10  -.158811  .048222   .074182  .024328   .0000000  .0000000  -.005732  .118084  -.057897  .037315
+    1937.15  -.245489  .037300   .179964  .024899   .0000000  .0000000  -.082441  .095065   .015064  .035935
+    1937.20  -.176313  .024347   .131564  .021480   .0000000  .0000000  -.011162  .047116   .007665  .035588
+    1937.25  -.121499  .027993   .208926  .020364   .0000000  .0000000   .055374  .052535   .003693  .031433
+    1937.30  -.116696  .019325   .187814  .017441   .0000000  .0000000   .031160  .051109   .025088  .031903
+    1937.35  -.040102  .019283   .222305  .018618   .0000000  .0000000  -.006141  .067700   .013902  .025889
+    1937.40  -.088573  .032312   .195445  .025157   .0000000  .0000000   .036933  .108610   .035897  .031983
+    1937.45   .035320  .032900   .209660  .037569   .0000000  .0000000   .286079  .120190  -.061321  .033034
+    1937.50   .073386  .027070   .231432  .034139   .0000000  .0000000   .280629  .125639   .000056  .019985
+    1937.55   .069100  .021000   .137800  .021600   .0000000  .0000000   .183700  .097800  -.010900  .022900
+    1937.60   .090711  .017787   .121711  .017775   .0000000  .0000000   .155485  .063704  -.047427  .028153
+    1937.65   .056677  .025156   .054539  .029534   .0000000  .0000000   .085924  .077674   .002358  .044134
+    1937.70   .047138  .020415   .041472  .019505   .0000000  .0000000   .109899  .040740  -.021845  .033649
+    1937.75  -.015251  .029698  -.021479  .026262   .0000000  .0000000   .240537  .052747   .030065  .054171
+    1937.80  -.008680  .024570  -.029054  .021966   .0000000  .0000000  -.011361  .071538   .032695  .042628
+    1937.85  -.107027  .052301  -.071074  .029844   .0000000  .0000000  -.010644  .121826  -.009140  .052614
+    1937.90  -.105060  .033224  -.016349  .021708   .0000000  .0000000   .000897  .097421   .024894  .028423
+    1937.95  -.217410  .042351  -.006067  .021722   .0000000  .0000000   .163760  .106926  -.045437  .024199
+    1938.00  -.204894  .067766   .021733  .040401   .0000000  .0000000  -.026212  .134573   .019500  .049776
+    1938.05  -.303156  .051189   .013057  .057781   .0000000  .0000000   .455009  .256240   .061652  .060953
+    1938.10  -.147755  .030762   .071361  .022609   .0000000  .0000000   .103134  .085082   .057226  .032009
+    1938.15  -.221442  .020302   .102093  .022050   .0000000  .0000000   .012967  .059919  -.070502  .029053
+    1938.20  -.226757  .021464   .130364  .026643   .0000000  .0000000   .001658  .043406  -.006758  .051291
+    1938.25  -.171954  .020038   .165869  .024298   .0000000  .0000000  -.015881  .041937   .027639  .048387
+    1938.30  -.138432  .027223   .225318  .026550   .0000000  .0000000   .005010  .071389   .049609  .036109
+    1938.35  -.116911  .032602   .287363  .030442   .0000000  .0000000   .023008  .087321  -.083163  .045743
+    1938.40  -.046436  .022237   .227821  .021177   .0000000  .0000000   .113723  .092236  -.024826  .026919
+    1938.45  -.080914  .049543   .286589  .026940   .0000000  .0000000   .413938  .153469  -.041876  .030065
+    1938.50   .111257  .046529   .295958  .032882   .0000000  .0000000   .105264  .144089  -.049291  .032748
+    1938.55   .109700  .023800   .236000  .032100   .0000000  .0000000   .188500  .136200   .070100  .035900
+    1938.60   .174186  .027008   .248989  .025076   .0000000  .0000000  -.058945  .089978   .001625  .036058
+    1938.65   .172035  .024829   .065415  .017812   .0000000  .0000000  -.020619  .065169  -.092811  .034848
+    1938.70   .075919  .028103   .117887  .029399   .0000000  .0000000   .080439  .054649   .078144  .057554
+    1938.75   .167309  .024278   .023607  .020665   .0000000  .0000000   .012905  .044571   .011731  .039332
+    1938.80   .026111  .026090  -.003055  .018168   .0000000  .0000000  -.050130  .064328   .032800  .035397
+    1938.85  -.037869  .024814  -.061382  .026313   .0000000  .0000000  -.139398  .101758   .068126  .036773
+    1938.90  -.052264  .036085  -.072478  .027939   .0000000  .0000000   .227134  .081018  -.049973  .031785
+    1938.95  -.134539  .074845   .030821  .034255   .0000000  .0000000   .203647  .139364   .006955  .034675
+    1939.00  -.301769  .052095   .106206  .041046   .0000000  .0000000   .097782  .134445   .126933  .040015
+    1939.05  -.116858  .031761  -.001150  .027067   .0000000  .0000000   .069219  .114100  -.043972  .026676
+    1939.10  -.213896  .052347   .044637  .029951   .0000000  .0000000   .100499  .115589  -.034090  .040064
+    1939.15  -.161300  .028000   .101800  .022400   .0000000  .0000000   .026600  .079200   .033400  .032600
+    1939.20  -.181054  .026344   .143917  .017714   .0000000  .0000000   .108271  .043838  -.012560  .032033
+    1939.25  -.192526  .031348   .184454  .017928   .0000000  .0000000   .063502  .044160  -.075863  .035745
+    1939.30  -.119371  .031056   .187626  .017082   .0000000  .0000000   .060381  .054162  -.000618  .035005
+    1939.35  -.079336  .031918   .224723  .019528   .0000000  .0000000   .100471  .072304  -.010194  .028022
+    1939.40  -.087263  .033604   .216206  .018087   .0000000  .0000000   .029625  .098189  -.024268  .026120
+    1939.45  -.044976  .026415   .211200  .017721   .0000000  .0000000   .127332  .116805   .012013  .015370
+    1939.50   .023086  .029357   .214921  .024272   .0000000  .0000000   .143133  .143921  -.008201  .020892
+    1939.55   .072500  .021500   .233900  .028500   .0000000  .0000000   .200600  .111800   .034800  .028200
+    1939.60   .118411  .034504   .224190  .022418   .0000000  .0000000   .287927  .083553   .059985  .030415
+    1939.65   .146657  .026608   .195121  .022452   .0000000  .0000000   .056615  .078763   .049268  .045366
+    1939.70   .095496  .035816   .180767  .028811   .0000000  .0000000  -.041206  .062114   .054138  .050547
+    1939.75   .089672  .036394   .076885  .031936   .0000000  .0000000   .103650  .054497   .044565  .059625
+    1939.80   .069378  .025942   .045780  .020362   .0000000  .0000000   .014679  .068846   .001210  .038438
+    1939.85   .042361  .022277   .018571  .019603   .0000000  .0000000   .116647  .076374  -.030570  .028495
+    1939.90   .005289  .024937   .055015  .021233   .0000000  .0000000   .263913  .091441  -.088895  .026766
+    1939.95  -.058344  .061163   .043141  .028428   .0000000  .0000000  -.027276  .144601  -.054993  .033244
+    1940.00   .027411  .077275  -.055656  .040309   .0000000  .0000000   .280673  .124019  -.035461  .049996
+    1940.05  -.148565  .048427  -.007660  .029624   .0000000  .0000000   .036827  .132048  -.063083  .034740
+    1940.10  -.249170  .031848  -.018138  .026098   .0000000  .0000000   .102082  .088814  -.092441  .032061
+    1940.15  -.210741  .037178   .047170  .021871   .0000000  .0000000   .010781  .074147  -.079933  .032336
+    1940.20  -.226589  .024698   .078515  .018759   .0000000  .0000000   .085455  .046548  -.040264  .028160
+    1940.25  -.290100  .050400   .142200  .033500   .0000000  .0000000   .134700  .071900   .042900  .053100
+    1940.30  -.223492  .021873   .078291  .021431   .0000000  .0000000   .027242  .064239  -.034537  .032075
+    1940.35  -.135189  .033253   .151824  .022526   .0000000  .0000000   .232845  .087503  -.051245  .033133
+    1940.40  -.175712  .026622   .271518  .024079   .0000000  .0000000   .114010  .103141   .010283  .029308
+    1940.45  -.063144  .024189   .235042  .021942   .0000000  .0000000   .478962  .120381  -.016662  .017980
+    1940.50  -.029661  .027901   .260179  .025258   .0000000  .0000000   .238529  .128248   .022554  .021672
+    1940.55   .019816  .031393   .250937  .020228   .0000000  .0000000   .354490  .091541   .059761  .024911
+    1940.60   .162656  .033993   .241704  .019243   .0000000  .0000000   .174897  .087947   .029852  .031332
+    1940.65   .098439  .030861   .147379  .026781   .0000000  .0000000   .240708  .082500   .081456  .045187
+    1940.70   .065800  .040900   .175200  .018000   .0000000  .0000000  -.035700  .042700   .085200  .040300
+    1940.75   .125165  .021480   .119102  .016993   .0000000  .0000000   .016575  .035997   .066860  .036856
+    1940.80   .070275  .044378   .085726  .026840   .0000000  .0000000  -.112729  .075342   .022843  .052931
+    1940.85   .053300  .039909   .043221  .022772   .0000000  .0000000   .036946  .099058   .016973  .049873
+    1940.90   .004300  .047102  -.026993  .022398   .0000000  .0000000   .087581  .123251  -.052575  .037425
+    1940.95  -.049213  .047073   .034742  .025669   .0000000  .0000000   .139401  .127260  -.014801  .025328
+    1941.00   .033843  .046840   .015616  .040643   .0000000  .0000000  -.091313  .169246  -.034822  .030156
+    1941.05   .033262  .065113  -.034927  .049589   .0000000  .0000000   .245435  .199929  -.094435  .040091
+    1941.10  -.043717  .034446   .028212  .023694   .0000000  .0000000  -.081372  .089249  -.088631  .024387
+    1941.15  -.000032  .040323   .034220  .023892   .0000000  .0000000  -.150594  .086706  -.096703  .041061
+    1941.20   .008262  .043291   .025372  .030470   .0000000  .0000000   .248876  .079912   .058207  .043168
+    1941.25  -.118927  .034295   .084292  .022975   .0000000  .0000000   .111681  .054924   .024383  .042665
+    1941.30  -.183857  .030309   .100975  .021078   .0000000  .0000000   .107066  .059447   .000181  .036107
+    1941.35  -.159123  .039022   .204194  .031221   .0000000  .0000000   .071615  .081202  -.068183  .040363
+    1941.40  -.088480  .032885   .133512  .017317   .0000000  .0000000   .070452  .086127   .044016  .024793
+    1941.45  -.092443  .034238   .191571  .017249   .0000000  .0000000   .117795  .113137  -.001774  .015851
+    1941.50  -.062260  .034985   .120954  .025898   .0000000  .0000000   .154337  .164516   .060142  .021607
+    1941.55  -.073372  .034124   .253085  .025499   .0000000  .0000000   .175314  .089621  -.032968  .031504
+    1941.60   .012678  .047325   .219220  .028237   .0000000  .0000000   .377508  .098725   .051572  .037240
+    1941.65  -.041165  .030633   .167041  .020566   .0000000  .0000000   .226991  .070394   .075100  .036381
+    1941.70  -.086224  .042656   .093311  .024666   .0000000  .0000000  -.065811  .076606   .024269  .038115
+    1941.75   .001683  .035139   .150415  .033889   .0000000  .0000000   .066674  .066441  -.051084  .071325
+    1941.80   .068909  .027624   .186888  .030051   .0000000  .0000000  -.062154  .087481   .111358  .049014
+    1941.85  -.028851  .042976   .102187  .034278   .0000000  .0000000  -.062261  .122940  -.000004  .047542
+    1941.90  -.020115  .032129   .119301  .036007   .0000000  .0000000   .083441  .141823   .000045  .040889
+    1941.95   .145863  .062788   .081312  .039067   .0000000  .0000000  -.007050  .135487  -.107320  .035369
+    1942.00  -.029700  .035000   .145400  .036400   .0000000  .0000000  -.023400  .145000   .047000  .030200
+    1942.05  -.086609  .043305   .107756  .043155   .0000000  .0000000   .130386  .156484  -.001875  .044788
+    1942.10   .034025  .099193   .019905  .065306   .0000000  .0000000   .143195  .150532  -.075786  .050544
+    1942.15  -.065983  .072737   .120029  .039191   .0000000  .0000000  -.010695  .103966  -.056494  .047800
+    1942.20  -.026845  .054073   .031907  .044318   .0000000  .0000000   .058500  .099629  -.057425  .067689
+    1942.25  -.066569  .033252   .031627  .021536   .0000000  .0000000   .235923  .052015   .010261  .035920
+    1942.30  -.008392  .035500   .098245  .025834   .0000000  .0000000  -.010612  .066911   .041308  .034586
+    1942.35  -.012154  .043636   .089180  .020492   .0000000  .0000000   .145144  .083706   .067848  .034201
+    1942.40  -.068264  .024748   .122550  .016674   .0000000  .0000000   .096755  .072277   .030454  .019928
+    1942.45  -.064544  .021997   .139302  .017836   .0000000  .0000000   .314458  .119425  -.015997  .014334
+    1942.50  -.032732  .023724   .122930  .023171   .0000000  .0000000   .154348  .125251  -.016508  .019523
+    1942.55  -.007371  .025769   .174390  .020405   .0000000  .0000000   .184138  .089648  -.053147  .023645
+    1942.60  -.089026  .027264   .117492  .027789   .0000000  .0000000   .171854  .105929   .063537  .043272
+    1942.65  -.075180  .025712   .095255  .017548   .0000000  .0000000   .079381  .066570   .051325  .035699
+    1942.70  -.036158  .026547   .121535  .020117   .0000000  .0000000   .056200  .051173   .051601  .032470
+    1942.75  -.075817  .024570   .122674  .020107   .0000000  .0000000   .044556  .041433   .073768  .042854
+    1942.80  -.089165  .025839   .085346  .023589   .0000000  .0000000  -.085206  .072822   .050192  .047934
+    1942.85  -.152931  .030206   .083401  .026797   .0000000  .0000000   .064794  .101785  -.119249  .040379
+    1942.90  -.103187  .039909   .103300  .029302   .0000000  .0000000  -.051792  .135763  -.004428  .042467
+    1942.95  -.039915  .046498   .183470  .030930   .0000000  .0000000  -.154219  .135897   .022603  .031303
+    1943.00  -.090405  .044945   .234551  .028097   .0000000  .0000000   .031918  .130831   .002072  .024383
+    1943.05  -.093652  .033425   .180949  .023112   .0000000  .0000000   .307004  .136349   .039921  .032842
+    1943.10  -.061971  .041347   .090993  .035224   .0000000  .0000000   .125377  .126839  -.037571  .041480
+    1943.15  -.080573  .025864   .145031  .020718   .0000000  .0000000   .010542  .065253  -.060381  .032471
+    1943.20  -.051329  .044348   .138129  .024337   .0000000  .0000000   .114304  .060216  -.071526  .042656
+    1943.25   .001923  .020443   .184841  .014117   .0000000  .0000000   .080154  .033484  -.028209  .025002
+    1943.30  -.019745  .047888   .090795  .029239   .0000000  .0000000   .286805  .085349  -.065939  .046350
+    1943.35   .035917  .046036   .105605  .027853   .0000000  .0000000  -.071916  .116350   .011802  .039509
+    1943.40   .078661  .029069   .117427  .015875   .0000000  .0000000  -.017176  .107309   .031813  .027567
+    1943.45   .033384  .028581   .108682  .016851   .0000000  .0000000   .211785  .118690  -.001950  .015077
+    1943.50   .105491  .034946   .061063  .017106   .0000000  .0000000   .162842  .133454   .015217  .015918
+    1943.55  -.047847  .103549  -.001805  .032245   .0000000  .0000000   .078989  .171419  -.055324  .049530
+    1943.60  -.036338  .029169   .050187  .016889   .0000000  .0000000   .270467  .067593   .080426  .035071
+    1943.65   .022793  .032813   .034134  .016076   .0000000  .0000000   .131087  .060479   .025598  .033468
+    1943.70   .070899  .035442   .024180  .017600   .0000000  .0000000  -.005569  .045031   .007882  .031512
+    1943.75   .004438  .048663   .011224  .022566   .0000000  .0000000  -.051189  .056973   .018685  .052347
+    1943.80  -.122806  .048296   .001491  .031982   .0000000  .0000000  -.112682  .090687   .019698  .065615
+    1943.85  -.144327  .059258   .028604  .023563   .0000000  .0000000  -.227848  .107147   .001673  .039855
+    1943.90  -.120953  .040528   .074676  .019274   .0000000  .0000000  -.181415  .090120   .034939  .027690
+    1943.95  -.253705  .054648   .095567  .033760   .0000000  .0000000  -.038519  .105800   .043310  .030581
+    1944.00  -.188535  .056504   .058157  .026927   .0000000  .0000000   .011710  .117984   .050033  .025258
+    1944.05  -.213170  .050255   .082626  .030045   .0000000  .0000000  -.043329  .159056   .015731  .038148
+    1944.10  -.133388  .045661   .103606  .024095   .0000000  .0000000   .229543  .103942   .175796  .038943
+    1944.15  -.243714  .051614   .045296  .028302   .0000000  .0000000   .177000  .105652   .113149  .053398
+    1944.20  -.280687  .055970   .123924  .030138   .0000000  .0000000  -.188279  .079808   .142494  .052159
+    1944.25  -.099857  .044604   .132270  .024510   .0000000  .0000000  -.025648  .058133   .069120  .050952
+    1944.30  -.102089  .049295   .098582  .026644   .0000000  .0000000  -.105879  .081537  -.005922  .046044
+    1944.35   .034173  .049135   .068935  .022447   .0000000  .0000000  -.023121  .090661  -.065807  .032003
+    1944.40   .052475  .031410   .180058  .020077   .0000000  .0000000  -.054212  .110366  -.009055  .033903
+    1944.45   .204300  .039900   .170300  .019200   .0000000  .0000000  -.041200  .149500  -.017000  .018300
+    1944.50   .174930  .034829   .065429  .018224   .0000000  .0000000   .283677  .123221   .036322  .017098
+    1944.55   .236527  .044383   .061957  .020707   .0000000  .0000000   .188768  .113215   .012042  .027235
+    1944.60   .208915  .031465  -.039275  .017646   .0000000  .0000000  -.005744  .077108   .019100  .031084
+    1944.65   .171265  .036525  -.034213  .019816   .0000000  .0000000  -.062495  .073567  -.102429  .040486
+    1944.70   .158830  .051306  -.127515  .024358   .0000000  .0000000  -.038891  .054838   .097809  .058068
+    1944.75  -.041184  .050911  -.081574  .028622   .0000000  .0000000   .155086  .088314  -.062691  .057585
+    1944.80  -.054199  .033951  -.141045  .019266   .0000000  .0000000  -.094099  .062789   .080547  .037140
+    1944.85  -.122864  .049362  -.138640  .027245   .0000000  .0000000  -.050906  .092832  -.001887  .045221
+    1944.90  -.173922  .041193  -.079180  .024982   .0000000  .0000000  -.034262  .124491   .051550  .040084
+    1944.95  -.266129  .053704  -.029277  .022854   .0000000  .0000000   .131877  .110016  -.008643  .020029
+    1945.00  -.117527  .098174   .046084  .041335   .0000000  .0000000   .087723  .217282   .013102  .036075
+    1945.05  -.172366  .049912   .076642  .030967   .0000000  .0000000   .267719  .179675  -.006805  .044952
+    1945.10  -.218168  .050084   .119657  .026439   .0000000  .0000000   .154283  .108024   .033489  .042789
+    1945.15  -.269380  .049677   .084980  .028834   .0000000  .0000000   .082804  .098489   .000447  .045397
+    1945.20  -.105476  .046714   .185324  .018697   .0000000  .0000000  -.039045  .050584   .029208  .036366
+    1945.25  -.252149  .085268   .252063  .049965   .0000000  .0000000  -.159686  .129068   .042012  .044566
+    1945.30  -.119100  .039700   .283700  .019900   .0000000  .0000000   .073600  .061300  -.050300  .036300
+    1945.35  -.098829  .042741   .296275  .018875   .0000000  .0000000   .039859  .081486   .017185  .031128
+    1945.40   .041205  .032181   .299528  .018137   .0000000  .0000000   .064232  .099406   .040381  .028527
+    1945.45   .070100  .036700   .328900  .019100   .0000000  .0000000   .396100  .134000  -.033000  .017800
+    1945.50   .161286  .035364   .243704  .019020   .0000000  .0000000   .203888  .143130   .028038  .016730
+    1945.55   .111735  .045860   .157891  .023770   .0000000  .0000000   .181839  .111435   .048925  .027434
+    1945.60   .279930  .033860   .129955  .019470   .0000000  .0000000  -.146537  .081354  -.012702  .036212
+    1945.65   .210791  .036056   .086270  .018333   .0000000  .0000000  -.033172  .070699   .023239  .035846
+    1945.70   .167958  .069541  -.034212  .029604   .0000000  .0000000  -.117022  .078929   .033399  .058465
+    1945.75   .387534  .081155  -.060857  .039921   .0000000  .0000000  -.163738  .085766   .026932  .080324
+    1945.80   .203824  .038877  -.175689  .021959   .0000000  .0000000  -.196190  .063085  -.030286  .035599
+    1945.85  -.009562  .068992  -.200723  .050136   .0000000  .0000000  -.100653  .130011  -.024714  .045668
+    1945.90   .082043  .098983  -.254725  .060995   .0000000  .0000000  -.152230  .134994  -.064263  .053177
+    1945.95  -.167775  .079020   .011828  .069978   .0000000  .0000000   .177563  .114048   .221283  .066533
+    1946.00  -.105894  .056205  -.143593  .034311   .0000000  .0000000   .199964  .143624  -.000929  .034314
+    1946.05  -.238800  .088800  -.143600  .064100   .0000000  .0000000   .131900  .121100  -.025600  .062000
+    1946.10  -.161621  .048683  -.086524  .026893   .0000000  .0000000   .231302  .121796  -.045219  .045241
+    1946.15  -.292120  .041826  -.032154  .024745   .0000000  .0000000  -.072356  .097341  -.079506  .047899
+    1946.20  -.369539  .095096   .005399  .055328   .0000000  .0000000   .052740  .148879  -.113594  .053330
+    1946.25  -.243748  .049762   .106804  .017998   .0000000  .0000000   .037891  .052028  -.000958  .033355
+    1946.30  -.260700  .043900   .154700  .024700   .0000000  .0000000   .146500  .060100   .015300  .028900
+    1946.35  -.227834  .043383   .263600  .027335   .0000000  .0000000   .054514  .099861  -.014064  .035241
+    1946.40  -.105890  .029765   .285597  .015086   .0000000  .0000000   .209512  .066402  -.021484  .018107
+    1946.45  -.219288  .045405   .379684  .028341   .0000000  .0000000   .452054  .158962  -.033761  .026542
+    1946.50  -.063112  .023701   .324947  .023954   .0000000  .0000000   .329269  .135513  -.005721  .018983
+    1946.55   .056826  .021226   .295929  .018350   .0000000  .0000000  -.002104  .085088  -.017459  .020736
+    1946.60   .082673  .031070   .302031  .017679   .0000000  .0000000   .128310  .076546   .041444  .030472
+    1946.65   .134672  .028275   .242569  .018267   .0000000  .0000000  -.028935  .065586  -.006894  .035842
+    1946.70   .188918  .042253   .179805  .024653   .0000000  .0000000  -.085803  .069558   .082797  .058786
+    1946.75   .230337  .027345   .153795  .018577   .0000000  .0000000  -.135090  .042785   .070652  .040411
+    1946.80   .230653  .029557   .126700  .021510   .0000000  .0000000  -.081513  .070902   .011646  .042602
+    1946.85   .324003  .050001  -.014854  .031141   .0000000  .0000000  -.035261  .123641   .093395  .055954
+    1946.90   .083430  .029570  -.030662  .030935   .0000000  .0000000   .022357  .123080  -.104915  .035679
+    1946.95   .071411  .037775  -.089697  .035099   .0000000  .0000000   .207114  .170228  -.059531  .032194
+    1947.00   .033741  .037012  -.095143  .035317   .0000000  .0000000   .042302  .138704  -.001326  .028954
+    1947.05  -.003804  .040478  -.062704  .036415   .0000000  .0000000   .057712  .144446   .028471  .038643
+    1947.10  -.105253  .032813  -.159077  .026207   .0000000  .0000000  -.130260  .128557  -.006703  .040601
+    1947.15  -.140851  .044726  -.129656  .031276   .0000000  .0000000   .151813  .087397  -.009561  .037416
+    1947.20  -.217901  .022739  -.081483  .019933   .0000000  .0000000   .194724  .038687  -.082918  .045835
+    1947.25  -.204585  .031621  -.117897  .024841   .0000000  .0000000   .088210  .050211   .043359  .050085
+    1947.30  -.260050  .024410   .044441  .020965   .0000000  .0000000   .143500  .059651  -.004458  .031726
+    1947.35  -.358491  .051825   .174358  .038713   .0000000  .0000000  -.150770  .096426  -.043413  .039711
+    1947.40  -.202905  .022247   .152120  .016348   .0000000  .0000000   .142834  .078507  -.003972  .021997
+    1947.45  -.254945  .036398   .153196  .024495   .0000000  .0000000   .397632  .136809   .050744  .019703
+    1947.50  -.137802  .039259   .288460  .018339   .0000000  .0000000   .293369  .123364  -.003044  .017321
+    1947.55  -.094877  .027323   .287150  .018613   .0000000  .0000000   .368362  .095231   .027479  .024367
+    1947.60   .023089  .026612   .335301  .022225   .0000000  .0000000   .150553  .077407   .061567  .034232
+    1947.65   .060945  .023461   .357002  .018134   .0000000  .0000000   .097432  .066202   .048073  .035423
+    1947.70   .113078  .020025   .313539  .016869   .0000000  .0000000  -.070258  .035820   .101461  .024940
+    1947.75   .120020  .028834   .273848  .017090   .0000000  .0000000  -.054866  .041783   .080301  .036715
+    1947.80   .175924  .021367   .294753  .021098   .0000000  .0000000  -.096099  .059629  -.025532  .033285
+    1947.85   .206992  .026904   .222458  .026059   .0000000  .0000000  -.169918  .093163   .019324  .036768
+    1947.90   .140099  .156501   .174866  .060855   .0000000  .0000000   .308350  .258739  -.060133  .111353
+    1947.95   .157648  .033763   .156590  .020766   .0000000  .0000000  -.193207  .100077  -.016713  .022002
+    1948.00   .225955  .060139   .143369  .036132   .0000000  .0000000  -.092621  .131439  -.043843  .036950
+    1948.05   .157129  .032190   .071959  .019313   .0000000  .0000000   .173710  .115614  -.018864  .031870
+    1948.10   .150055  .042780   .021583  .029804   .0000000  .0000000   .052631  .106024  -.078329  .042590
+    1948.15   .171585  .046287  -.019271  .026507   .0000000  .0000000   .106127  .104273   .019381  .050631
+    1948.20   .145400  .027900  -.041700  .017300   .0000000  .0000000   .061600  .043200  -.053500  .028000
+    1948.25   .147680  .042680  -.064178  .028623   .0000000  .0000000   .200452  .066728  -.018979  .038952
+    1948.30   .053983  .032261  -.075038  .023059   .0000000  .0000000   .129227  .065461  -.012305  .032841
+    1948.35  -.045837  .029177  -.072956  .018100   .0000000  .0000000   .188712  .075504   .014525  .029107
+    1948.40  -.091431  .027583  -.067958  .028678   .0000000  .0000000   .169771  .114458   .026487  .034330
+    1948.45  -.076060  .032359   .010010  .024096   .0000000  .0000000   .027309  .122213  -.001558  .022938
+    1948.50  -.106057  .029471   .014185  .023433   .0000000  .0000000   .331345  .133211   .006509  .020305
+    1948.55  -.097516  .035671   .015430  .022947   .0000000  .0000000   .126049  .105235  -.000300  .028138
+    1948.60  -.130026  .022269   .063326  .020675   .0000000  .0000000   .013796  .068888  -.005195  .026597
+    1948.65  -.136613  .027877   .110269  .016852   .0000000  .0000000   .035140  .061022   .025543  .033534
+    1948.70  -.236212  .036919   .081015  .020424   .0000000  .0000000  -.058798  .047650   .040632  .030948
+    1948.75  -.122022  .023509   .165015  .021825   .0000000  .0000000  -.061524  .043538   .001342  .044698
+    1948.80  -.082996  .027186   .181422  .022777   .0000000  .0000000  -.039394  .068076  -.033338  .040318
+    1948.85  -.102718  .027953   .194496  .030520   .0000000  .0000000  -.054000  .090691   .015084  .040774
+    1948.90  -.056364  .032781   .288203  .026870   .0000000  .0000000  -.055418  .127534   .046448  .038790
+    1948.95  -.060517  .032204   .337067  .027905   .0000000  .0000000   .111431  .081826   .008714  .026545
+    1949.00  -.038708  .049316   .272547  .039019   .0000000  .0000000   .165371  .196818   .017298  .033085
+    1949.05   .050766  .046642   .309560  .032725   .0000000  .0000000   .053360  .111299   .008811  .040210
+    1949.10  -.036412  .034106   .244629  .035866   .0000000  .0000000   .058169  .111719   .045433  .043521
+    1949.15   .092035  .026254   .269182  .028319   .0000000  .0000000   .047496  .079311  -.003430  .044089
+    1949.20   .117000  .030700   .151400  .021500   .0000000  .0000000   .121100  .057800  -.038500  .032400
+    1949.25   .167243  .019974   .119693  .019482   .0000000  .0000000   .029460  .038689   .002111  .032263
+    1949.30   .167879  .019742   .072692  .018970   .0000000  .0000000   .079695  .055856  -.065511  .031070
+    1949.35   .134722  .018528   .072089  .017990   .0000000  .0000000  -.005600  .064474  -.028475  .024032
+    1949.40   .145230  .020357   .001256  .019435   .0000000  .0000000  -.009693  .083433  -.012814  .022777
+    1949.45   .089326  .032677  -.093079  .026228   .0000000  .0000000   .145656  .151896  -.012762  .022385
+    1949.50   .154408  .024388  -.078539  .019318   .0000000  .0000000   .266006  .106446  -.037253  .018520
+    1949.55   .073064  .019811  -.060780  .019254   .0000000  .0000000   .142959  .090937  -.041160  .022053
+    1949.60   .043289  .020218  -.033614  .020112   .0000000  .0000000   .205821  .056832   .001724  .022392
+    1949.65  -.013262  .031902  -.122149  .021421   .0000000  .0000000   .142460  .071339   .053448  .035449
+    1949.70  -.164254  .018967  -.145566  .017345   .0000000  .0000000  -.015451  .034611   .066843  .027464
+    1949.75  -.163827  .021670  -.040926  .019401   .0000000  .0000000   .024694  .039400   .012926  .034357
+    1949.80  -.236686  .025116  -.074967  .021759   .0000000  .0000000  -.159054  .061893  -.000411  .033474
+    1949.85  -.237557  .024531   .040887  .019382   .0000000  .0000000  -.125444  .074771   .002484  .027168
+    1949.90  -.224455  .033530   .063927  .018810   .0000000  .0000000   .023909  .066713  -.057764  .022311
+    1949.95  -.290753  .033619   .157252  .026266   .0000000  .0000000   .122957  .121459   .002499  .023060
+    1950.00  -.220930  .031188   .287191  .027116   .0000000  .0000000   .096834  .072355   .057514  .028313
+    1950.05  -.222249  .025733   .248856  .019958   .0000000  .0000000   .104625  .074014  -.005680  .018913
+    1950.10  -.144425  .027227   .335072  .022605   .0000000  .0000000   .028561  .060323  -.026022  .026755
+    1950.15  -.061597  .027136   .365805  .021433   .0000000  .0000000   .024639  .059588  -.037465  .026662
+    1950.20   .023935  .031899   .338761  .020543   .0000000  .0000000   .059885  .052747   .066709  .027018
+    1950.25   .046105  .025279   .332438  .016279   .0000000  .0000000   .076271  .042306   .073850  .026697
+    1950.30   .127597  .020170   .297890  .015238   .0000000  .0000000   .056717  .042025  -.009493  .022675
+    1950.35   .258100  .018500   .317900  .015100   .0000000  .0000000  -.020400  .045700  -.037300  .017900
+    1950.40   .238376  .018584   .209297  .018693   .0000000  .0000000  -.076414  .079552   .026728  .021964
+    1950.45   .300481  .034000   .140257  .022063   .0000000  .0000000   .057815  .104537  -.019883  .022607
+    1950.50   .287564  .026024   .015981  .022256   .0000000  .0000000   .226741  .112107  -.052289  .020011
+    1950.55   .286892  .019714   .093660  .017169   .0000000  .0000000   .112008  .067624   .007534  .019107
+    1950.60   .270451  .020268  -.079337  .015524   .0000000  .0000000   .067069  .046463   .031933  .019940
+    1950.65   .258830  .028976  -.098373  .021452   .0000000  .0000000   .172046  .055504  -.006099  .028183
+    1950.70   .116078  .031592  -.227489  .022550   .0000000  .0000000   .003803  .057717   .008677  .031671
+    1950.75  -.010608  .020131  -.232154  .018407   .0000000  .0000000  -.004975  .037832   .033624  .028346
+    1950.80  -.087101  .027544  -.278552  .022565   .0000000  .0000000  -.063955  .066989  -.024757  .025075
+    1950.85  -.183732  .026532  -.306109  .019244   .0000000  .0000000  -.110177  .063411  -.030087  .026370
+    1950.90  -.306855  .023793  -.243256  .019914   .0000000  .0000000   .053527  .057910  -.056163  .022108
+    1950.95  -.321363  .042409  -.117027  .020603   .0000000  .0000000   .059400  .104950   .044587  .020723
+    1951.00  -.365022  .027994   .014938  .024338   .0000000  .0000000   .033574  .070227   .052409  .023757
+    1951.05  -.304225  .029966   .001015  .019948   .0000000  .0000000   .245382  .073638  -.006980  .023904
+    1951.10  -.369566  .026330   .099280  .020125   .0000000  .0000000   .016276  .066839  -.017562  .022936
+    1951.15  -.378609  .027648   .229045  .020079   .0000000  .0000000   .090817  .056998   .047240  .025224
+    1951.20  -.253183  .022810   .324399  .018429   .0000000  .0000000   .046964  .041849   .002459  .028010
+    1951.25  -.183608  .024150   .395804  .019034   .0000000  .0000000  -.037382  .044917   .057110  .031569
+    1951.30  -.113043  .023771   .407480  .014823   .0000000  .0000000   .062870  .045151  -.038716  .023368
+    1951.35   .025400  .022200   .357400  .017600   .0000000  .0000000   .124400  .055300   .024200  .022200
+    1951.40   .169217  .024409   .366203  .018242   .0000000  .0000000   .024260  .074441  -.045446  .022145
+    1951.45   .251730  .029607   .336817  .018573   .0000000  .0000000   .236504  .116554  -.033823  .017608
+    1951.50   .268771  .026562   .266485  .020994   .0000000  .0000000   .157566  .093858  -.016515  .020215
+    1951.55   .325834  .019822   .218909  .017563   .0000000  .0000000   .235511  .071342  -.004900  .019775
+    1951.60   .416116  .016950   .097318  .012584   .0000000  .0000000   .155524  .039133  -.041868  .017702
+    1951.65   .369300  .021400   .007200  .015000   .0000000  .0000000   .065100  .049500  -.037700  .025500
+    1951.70   .311161  .023969  -.128485  .015394   .0000000  .0000000   .039483  .040843   .057950  .022981
+    1951.75   .291955  .028273  -.216643  .022009   .0000000  .0000000   .089520  .052363   .037232  .033229
+    1951.80   .143989  .022624  -.282893  .015852   .0000000  .0000000   .040347  .048814   .001367  .022678
+    1951.85   .078168  .022632  -.298582  .017123   .0000000  .0000000  -.003139  .050304   .007860  .021614
+    1951.90  -.072498  .032917  -.293768  .018894   .0000000  .0000000   .125502  .076976   .015054  .025251
+    1951.95  -.121266  .022373  -.283286  .017006   .0000000  .0000000   .057744  .061298   .007417  .016688
+    1952.00  -.228941  .023453  -.289334  .015160   .0000000  .0000000   .065699  .092924   .003733  .013960
+    1952.05  -.384844  .040550  -.280973  .024273   .0000000  .0000000   .284884  .084576  -.039072  .026814
+    1952.10  -.425432  .029375  -.085033  .024938   .0000000  .0000000   .197790  .069953   .036197  .028108
+    1952.15  -.415187  .022758   .007147  .018201   .0000000  .0000000   .014303  .053656  -.042298  .024848
+    1952.20  -.438050  .021653   .104950  .013956   .0000000  .0000000   .103593  .038544   .013736  .021002
+    1952.25  -.373937  .019560   .199595  .015899   .0000000  .0000000   .082171  .034312  -.021995  .029667
+    1952.30  -.214791  .022330   .330880  .015622   .0000000  .0000000  -.000098  .045004   .010157  .021459
+    1952.35  -.237011  .019115   .436678  .016079   .0000000  .0000000   .085512  .059804  -.036097  .020952
+    1952.40  -.206498  .024081   .424479  .014987   .0000000  .0000000  -.106002  .058773  -.011340  .017563
+    1952.45  -.114247  .019359   .462331  .013963   .0000000  .0000000   .197230  .078764  -.027464  .013303
+    1952.50   .053909  .020944   .452330  .015244   .0000000  .0000000   .220087  .065328  -.021920  .014673
+    1952.55   .152162  .021907   .415113  .015937   .0000000  .0000000   .258642  .055326  -.015693  .018024
+    1952.60   .302914  .027762   .389455  .021787   .0000000  .0000000   .189218  .066538  -.038539  .026682
+    1952.65   .303583  .024397   .272217  .019567   .0000000  .0000000   .027558  .060530   .059113  .029543
+    1952.70   .379665  .028581   .235664  .018126   .0000000  .0000000   .074403  .052206   .018652  .023236
+    1952.75   .284255  .027142   .115197  .015107   .0000000  .0000000   .068113  .039440  -.013031  .024266
+    1952.80   .290673  .022339   .004058  .017613   .0000000  .0000000  -.026814  .055548  -.016646  .029117
+    1952.85   .273678  .020792  -.093103  .016658   .0000000  .0000000  -.034611  .056709  -.003478  .023533
+    1952.90   .201204  .024394  -.160920  .017352   .0000000  .0000000   .101205  .066918  -.021440  .021197
+    1952.95   .092473  .035990  -.181244  .018135   .0000000  .0000000   .170540  .070181   .035931  .018927
+    1953.00   .123811  .046112  -.231433  .020713   .0000000  .0000000   .146975  .077941   .022420  .020965
+    1953.05  -.059768  .026615  -.287803  .019405   .0000000  .0000000   .073539  .061229   .031161  .022222
+    1953.10  -.099969  .025918  -.181194  .018804   .0000000  .0000000   .323839  .059555   .015830  .022517
+    1953.15  -.117820  .027928  -.081862  .022704   .0000000  .0000000   .083580  .061634   .087507  .024412
+    1953.20  -.288724  .030705  -.112507  .019672   .0000000  .0000000   .199470  .052632   .023652  .024078
+    1953.25  -.256646  .026746  -.080086  .022173   .0000000  .0000000  -.022337  .051580   .003880  .031966
+    1953.30  -.275672  .020599   .047975  .014455   .0000000  .0000000  -.058750  .041994   .037409  .023317
+    1953.35  -.343300  .027500   .172800  .021700   .0000000  .0000000   .059600  .060800  -.079200  .026000
+    1953.40  -.325734  .024532   .244282  .019035   .0000000  .0000000  -.140676  .074294  -.025887  .022799
+    1953.45  -.275838  .026641   .294124  .022470   .0000000  .0000000  -.053471  .102814  -.008273  .021290
+    1953.50  -.079095  .026144   .448538  .019122   .0000000  .0000000  -.217507  .080168  -.055041  .019564
+    1953.55  -.029260  .034099   .528535  .024925   .0000000  .0000000  -.271311  .082407  -.112618  .028206
+    1953.60   .021387  .028585   .421200  .018422   .0000000  .0000000   .246134  .065248  -.032333  .023040
+    1953.65   .022300  .022600   .491500  .016100   .0000000  .0000000   .021900  .051500  -.053600  .025900
+    1953.70   .219443  .028716   .448367  .021305   .0000000  .0000000   .081104  .050590  -.103119  .029687
+    1953.75   .204160  .023329   .288329  .022475   .0000000  .0000000   .063711  .047750   .050719  .031526
+    1953.80   .197400  .022700   .214300  .018100   .0000000  .0000000  -.168400  .053500   .047700  .029700
+    1953.85   .224082  .032786   .155717  .022938   .0000000  .0000000  -.147230  .058603   .052039  .028865
+    1953.90   .236336  .031970   .022065  .020042   .0000000  .0000000  -.041651  .071485  -.009290  .026217
+    1953.95   .184200  .022800   .032600  .018100   .0000000  .0000000   .031900  .065100   .028800  .017000
+    1954.00   .136603  .026849  -.090735  .023182   .0000000  .0000000  -.050796  .061331  -.024245  .023569
+    1954.05   .015320  .026526  -.126354  .027416   .0000000  .0000000   .055392  .101392  -.020027  .026427
+    1954.10   .036575  .028672  -.126953  .021059   .0000000  .0000000   .049545  .062772   .017389  .023557
+    1954.15  -.024887  .026248  -.150786  .018394   .0000000  .0000000   .027980  .050050   .006061  .023351
+    1954.20  -.154021  .026855  -.147087  .022367   .0000000  .0000000   .099882  .049362  -.064110  .038953
+    1954.25  -.164556  .021461  -.108061  .015823   .0000000  .0000000   .013419  .035979   .034450  .032006
+    1954.30  -.195623  .019666  -.112539  .014869   .0000000  .0000000   .068849  .042354  -.004632  .022316
+    1954.35  -.239513  .027637  -.079926  .020540   .0000000  .0000000   .120193  .052482  -.023196  .024829
+    1954.40  -.212137  .021964   .053878  .015717   .0000000  .0000000  -.030530  .063171  -.023356  .019706
+    1954.45  -.133960  .026786   .116843  .020849   .0000000  .0000000   .148397  .093316  -.062326  .018748
+    1954.50  -.215416  .032565   .144317  .022605   .0000000  .0000000   .077216  .082065   .011241  .023161
+    1954.55  -.127059  .022877   .218349  .016607   .0000000  .0000000   .220575  .059648  -.058397  .018458
+    1954.60  -.161882  .021549   .209542  .014593   .0000000  .0000000   .143856  .050849  -.025255  .018115
+    1954.65   .022753  .033378   .272072  .017886   .0000000  .0000000   .370787  .069710  -.024009  .031002
+    1954.70  -.093222  .026299   .296413  .019708   .0000000  .0000000   .117923  .043945  -.004252  .024702
+    1954.75  -.075965  .029848   .339411  .018236   .0000000  .0000000   .090049  .048544  -.034750  .027623
+    1954.80   .010000  .028200   .310600  .017800   .0000000  .0000000   .081200  .052000   .034100  .027200
+    1954.85  -.019012  .031351   .279865  .019533   .0000000  .0000000  -.167084  .066989  -.023408  .025878
+    1954.90  -.029023  .024480   .206222  .019033   .0000000  .0000000   .033885  .058871  -.016160  .021829
+    1954.95   .099499  .037242   .204533  .031026   .0000000  .0000000  -.042950  .097768   .047091  .030742
+    1955.00   .017291  .021213   .175152  .014290   .0000000  .0000000   .033370  .060138  -.009317  .014478
+    1955.05   .124344  .031213   .144779  .017718   .0000000  .0000000   .155624  .053807   .046471  .021918
+    1955.10   .029988  .022320   .049576  .019991   .0000000  .0000000   .130361  .063377  -.044089  .022481
+    1955.15   .124568  .023803   .140522  .017538   .0000000  .0000000   .099333  .048360  -.019436  .019780
+    1955.20   .158988  .028047   .106674  .020956   .0000000  .0000000   .027132  .056954   .019986  .020199
+    1955.25   .105321  .020346   .083753  .013910   .0000000  .0000000   .145617  .037687  -.006161  .018209
+    1955.30   .046473  .022676  -.027556  .016976   .0000000  .0000000   .059051  .046376  -.011698  .024166
+    1955.35   .065044  .022393  -.038566  .018508   .0000000  .0000000   .141355  .053642   .015979  .020549
+    1955.40   .041687  .021698  -.021509  .017344   .0000000  .0000000   .049719  .058520  -.013052  .018222
+    1955.45  -.001269  .019033  -.080686  .017959   .0000000  .0000000   .157478  .077168  -.034083  .014725
+    1955.50  -.055935  .018975  -.006263  .016799   .0000000  .0000000   .168650  .068965  -.004592  .014438
+    1955.55   .003124  .021527   .039639  .017456   .0000000  .0000000   .285877  .055508  -.027040  .017711
+    1955.60  -.109785  .024289   .034162  .020938   .0000000  .0000000   .155096  .051168   .005073  .020720
+    1955.65  -.137337  .016833   .039769  .014406   .0000000  .0000000   .221681  .037552   .015682  .016835
+    1955.70  -.226992  .018502   .043228  .013887   .0000000  .0000000   .019429  .034500   .008777  .017654
+    1955.75  -.229553  .028384   .066146  .018650   .0000000  .0000000   .028042  .048891  -.015119  .021530
+    1955.80  -.219600  .034400   .137300  .022400   .0000000  .0000000   .055500  .068100  -.045900  .026000
+    1955.85  -.189281  .026314   .159204  .023051   .0000000  .0000000   .008612  .064603  -.018369  .029468
+    1955.90  -.219306  .015150   .167037  .014494   .0000000  .0000000  -.007341  .043047  -.058591  .015797
+    1955.95  -.203131  .020472   .233918  .019303   .0000000  .0000000  -.005547  .055439  -.053440  .017788
+    1956.00  -.070247  .032431   .341707  .031719   .0000000  .0000000   .135590  .076991   .014708  .031785
+    1956.05  -.007398  .035739   .192673  .028194   .0000000  .0000000   .279279  .089268   .011918  .030549
+    1956.10   .016713  .022564   .339190  .016817   .0000000  .0000000  -.016698  .043762   .026854  .019658
+    1956.15   .038798  .019068   .279099  .015588   .0000000  .0000000   .074850  .041926   .016647  .017933
+    1956.20   .117409  .024592   .334384  .022962   .0000000  .0000000   .116289  .049460  -.006365  .018888
+    1956.25   .083759  .020019   .248766  .015039   .0000000  .0000000   .150435  .038028   .011561  .018956
+    1956.30   .152189  .026345   .209354  .017636   .0000000  .0000000   .075592  .048774  -.003266  .022999
+    1956.35   .160798  .016985   .161261  .012469   .0000000  .0000000   .097469  .041497  -.003484  .014663
+    1956.40   .211912  .021913   .132122  .016197   .0000000  .0000000  -.051769  .059819   .008059  .017699
+    1956.45   .219468  .026982   .113755  .020920   .0000000  .0000000   .021605  .075035  -.053813  .017971
+    1956.50   .212688  .023269   .021181  .017172   .0000000  .0000000   .002238  .083659  -.027947  .015641
+    1956.55   .169132  .028754  -.055280  .025008   .0000000  .0000000   .141001  .088082  -.001245  .026443
+    1956.60   .146149  .017097   .000797  .015538   .0000000  .0000000   .153254  .042082  -.055786  .017332
+    1956.65   .059496  .017297  -.049301  .015542   .0000000  .0000000   .073822  .039023  -.068925  .019163
+    1956.70   .018377  .015792  -.044723  .014377   .0000000  .0000000   .116191  .033209   .042646  .018835
+    1956.75  -.050507  .015619  -.037579  .015578   .0000000  .0000000   .100776  .031217  -.026861  .016950
+    1956.80  -.204692  .020241  -.059809  .016760   .0000000  .0000000   .042062  .045466  -.058731  .018652
+    1956.85  -.228535  .015021   .004844  .015190   .0000000  .0000000   .101849  .044702  -.061427  .017412
+    1956.90  -.318792  .017388   .068497  .018115   .0000000  .0000000   .059661  .049314  -.004755  .019308
+    1956.95  -.290530  .022402   .108736  .015607   .0000000  .0000000   .073717  .070250  -.046158  .016280
+    1957.00  -.401787  .020041   .175879  .017971   .0000000  .0000000   .020759  .054482  -.038155  .017054
+    1957.05  -.340710  .013184   .217146  .014033   .0000000  .0000000   .043470  .039909   .013138  .013164
+    1957.10  -.222754  .020310   .314496  .018886   .0000000  .0000000   .133183  .046866   .069621  .020912
+    1957.15  -.224552  .015429   .381610  .015155   .0000000  .0000000   .043022  .041393  -.013743  .016201
+    1957.20  -.194858  .017215   .441895  .013724   .0000000  .0000000   .036351  .034424   .007720  .019962
+    1957.25  -.099300  .012700   .411100  .012500   .0000000  .0000000   .052800  .030400   .017200  .013700
+    1957.30   .007920  .019006   .425095  .016097   .0000000  .0000000  -.068439  .041536  -.043108  .021122
+    1957.35   .076323  .017320   .453030  .014204   .0000000  .0000000   .022407  .046976  -.013461  .017459
+    1957.40   .152477  .017111   .481943  .013762   .0000000  .0000000  -.008718  .049449  -.044238  .015537
+    1957.45   .235240  .019941   .383132  .014899   .0000000  .0000000   .054280  .061264  -.026198  .015178
+    1957.50   .240076  .018320   .308449  .014258   .0000000  .0000000   .127074  .057250  -.053032  .014600
+    1957.55   .292684  .018822   .272059  .014287   .0000000  .0000000   .164388  .051760  -.012495  .016205
+    1957.60   .345486  .021836   .208463  .017253   .0000000  .0000000   .144962  .046548  -.044037  .019490
+    1957.65   .271110  .017701   .018347  .016626   .0000000  .0000000   .186498  .041069  -.008776  .019808
+    1957.70   .229000  .019985  -.058924  .017160   .0000000  .0000000   .212200  .039170   .039827  .021540
+    1957.75   .126351  .013356  -.051070  .011486   .0000000  .0000000   .098832  .028027   .000193  .016418
+    1957.80   .039747  .017662  -.126282  .015886   .0000000  .0000000   .103719  .040471   .013898  .018150
+    1957.85  -.003182  .017681  -.164541  .014422   .0000000  .0000000   .103918  .045521  -.058888  .017935
+    1957.90  -.069900  .017277  -.130259  .016231   .0000000  .0000000   .044071  .049795   .025530  .017047
+    1957.95  -.209601  .016394  -.084401  .013534   .0000000  .0000000   .013751  .041087   .004369  .013311
+    1958.00  -.305232  .025889  -.027916  .020974   .0000000  .0000000   .082277  .079180  -.008332  .020418
+    1958.05  -.343994  .024077   .036549  .023193   .0000000  .0000000   .119698  .054790  -.000916  .021924
+    1958.10  -.333001  .029858   .173344  .021209   .0000000  .0000000   .184998  .061702   .025625  .021775
+    1958.15  -.335927  .021083   .215384  .017353   .0000000  .0000000  -.038407  .050054   .059727  .019629
+    1958.20  -.305676  .013074   .288831  .012035   .0000000  .0000000   .000673  .027834   .029655  .017165
+    1958.25  -.300800  .016700   .338700  .012700   .0000000  .0000000   .068600  .037200  -.012200  .014500
+    1958.30  -.179030  .015640   .409116  .012973   .0000000  .0000000   .000773  .035277  -.023103  .015460
+    1958.35  -.101308  .015426   .407552  .013248   .0000000  .0000000  -.082328  .041851  -.003564  .015349
+    1958.40  -.041921  .011854   .434062  .011071   .0000000  .0000000   .055644  .041768  -.053159  .012218
+    1958.45   .051783  .015866   .422110  .012064   .0000000  .0000000   .232517  .059118  -.058358  .011873
+    1958.50   .098517  .016172   .451402  .013366   .0000000  .0000000   .046882  .056090  -.034994  .012743
+    1958.55   .180900  .016500   .370800  .013300   .0000000  .0000000   .091200  .044200  -.047700  .014600
+    1958.60   .203233  .018061   .334686  .013407   .0000000  .0000000   .011579  .041113  -.035020  .017378
+    1958.65   .303286  .015997   .248765  .012940   .0000000  .0000000   .125521  .035626  -.012307  .016621
+    1958.70   .276253  .012998   .146280  .010124   .0000000  .0000000  -.015057  .027164  -.007869  .014747
+    1958.75   .267226  .014759   .075078  .011492   .0000000  .0000000   .047112  .029887   .006651  .014882
+    1958.80   .266128  .019581   .119921  .014314   .0000000  .0000000   .031926  .040676  -.005640  .019317
+    1958.85   .213073  .022286  -.055607  .017133   .0000000  .0000000   .187421  .049471  -.037917  .021103
+    1958.90   .164238  .017142  -.060513  .012750   .0000000  .0000000   .112400  .041721  -.007397  .014646
+    1958.95   .101815  .018071  -.044255  .014672   .0000000  .0000000  -.037404  .040891   .040556  .014509
+    1959.00   .016105  .016596  -.129490  .016078   .0000000  .0000000   .215527  .058118   .043330  .014219
+    1959.05  -.095165  .015366  -.054368  .013998   .0000000  .0000000  -.027941  .050308   .039826  .013974
+    1959.10  -.153168  .012186  -.068371  .010996   .0000000  .0000000  -.074850  .034602   .038500  .012638
+    1959.15  -.195475  .012676  -.058794  .010334   .0000000  .0000000  -.105669  .029582   .067018  .012900
+    1959.20  -.253927  .011124   .017351  .010816   .0000000  .0000000  -.142133  .024682  -.006852  .012762
+    1959.25  -.238076  .011033   .061599  .010326   .0000000  .0000000  -.131493  .023456  -.007203  .014765
+    1959.30  -.240657  .013727   .198641  .012008   .0000000  .0000000  -.101022  .033062  -.033398  .015979
+    1959.35  -.252739  .016361   .262649  .012664   .0000000  .0000000  -.062746  .043776  -.057614  .015424
+    1959.40  -.214144  .015160   .308577  .012240   .0000000  .0000000  -.021546  .048769  -.098482  .014808
+    1959.45  -.142987  .014320   .396049  .012083   .0000000  .0000000   .121990  .055278  -.110626  .011749
+    1959.50  -.037927  .015406   .401546  .013586   .0000000  .0000000   .080033  .055336  -.131910  .013763
+    1959.55  -.034800  .013400   .382000  .012900   .0000000  .0000000   .264400  .044500  -.023000  .012800
+    1959.60   .106849  .019451   .415365  .015951   .0000000  .0000000   .293255  .046029  -.042593  .020540
+    1959.65   .129032  .016194   .368627  .012976   .0000000  .0000000   .179256  .037492  -.054083  .016866
+    1959.70   .175804  .019261   .336333  .014357   .0000000  .0000000   .099735  .039610   .006099  .021384
+    1959.75   .222541  .020118   .303817  .015057   .0000000  .0000000   .192338  .042252   .040102  .019978
+    1959.80   .203199  .012170   .215274  .011218   .0000000  .0000000   .075466  .029823  -.025358  .016907
+    1959.85   .202366  .014406   .197922  .014152   .0000000  .0000000  -.028643  .033913   .086031  .018165
+    1959.90   .175341  .011394   .085444  .010511   .0000000  .0000000   .049587  .030991   .019198  .011465
+    1959.95   .132030  .014553   .058528  .014121   .0000000  .0000000  -.013851  .052494  -.002008  .012094
+    1960.00   .008173  .019278   .006252  .016657   .0000000  .0000000   .178324  .069497   .058431  .015235
+    1960.05  -.003037  .017665  -.014016  .013888   .0000000  .0000000  -.064124  .047557   .010047  .014619
+    1960.10  -.096783  .013952  -.064746  .012789   .0000000  .0000000   .106423  .042002  -.000985  .013848
+    1960.15  -.049029  .012919  -.015531  .012193   .0000000  .0000000  -.087043  .031708   .000092  .014702
+    1960.20  -.070352  .018905   .005059  .015333   .0000000  .0000000  -.105083  .037064  -.038903  .022636
+    1960.25  -.093472  .013986  -.033430  .010931   .0000000  .0000000  -.061937  .026397   .024171  .016309
+    1960.30  -.144743  .010967   .036124  .009691   .0000000  .0000000  -.067451  .026687  -.002796  .012403
+    1960.35  -.136289  .013576   .091137  .011939   .0000000  .0000000  -.076098  .039075  -.017355  .015119
+    1960.40  -.185600  .011906   .139573  .010679   .0000000  .0000000  -.002643  .039828  -.050680  .011802
+    1960.45  -.144215  .015781   .156992  .012210   .0000000  .0000000  -.015514  .055952  -.047725  .012257
+    1960.50  -.093892  .014294   .234106  .012054   .0000000  .0000000   .292676  .057465  -.098800  .011318
+    1960.55  -.141900  .011200   .251100  .009400   .0000000  .0000000   .151300  .037400  -.033800  .010100
+    1960.60  -.082108  .010316   .224170  .009024   .0000000  .0000000   .062250  .029440  -.026798  .011262
+    1960.65  -.054888  .012519   .246897  .011749   .0000000  .0000000   .045087  .032512  -.058084  .016015
+    1960.70   .000500  .017600   .272000  .014800   .0000000  .0000000   .124200  .038200  -.016300  .019400
+    1960.75   .027616  .012393   .261292  .010364   .0000000  .0000000   .052321  .024867   .015003  .016433
+    1960.80   .028359  .012729   .217569  .010841   .0000000  .0000000  -.008342  .029411   .025216  .015182
+    1960.85  -.026324  .013635   .268219  .012928   .0000000  .0000000   .038656  .041050   .005303  .016382
+    1960.90   .045255  .017858   .178998  .013681   .0000000  .0000000   .052844  .047472  -.010855  .017694
+    1960.95   .018041  .022609   .148022  .013632   .0000000  .0000000   .086354  .057597   .003814  .014939
+    1961.00  -.010002  .021576   .178091  .018578   .0000000  .0000000  -.109701  .072493   .033406  .017217
+    1961.05   .014227  .016229   .129318  .014031   .0000000  .0000000   .172641  .051102   .000182  .013001
+    1961.10  -.034519  .012398   .135146  .010864   .0000000  .0000000   .046666  .040969  -.001677  .012123
+    1961.15   .020541  .009690   .071804  .008953   .0000000  .0000000   .017130  .023800  -.002468  .011041
+    1961.20  -.008860  .013770   .093978  .011954   .0000000  .0000000  -.062540  .030784   .042272  .017489
+    1961.25  -.009493  .013722   .077921  .012877   .0000000  .0000000  -.064367  .027888  -.002371  .019533
+    1961.30  -.013247  .012140   .104033  .010537   .0000000  .0000000  -.027246  .029362  -.027553  .013240
+    1961.35  -.011871  .016049   .106863  .012333   .0000000  .0000000  -.042391  .043669  -.025470  .015685
+    1961.40  -.055595  .010554   .050930  .010174   .0000000  .0000000   .015492  .037524  -.030144  .010919
+    1961.45  -.006478  .013451   .093211  .011987   .0000000  .0000000  -.007698  .053913  -.067298  .011171
+    1961.50  -.052932  .012403   .075634  .010452   .0000000  .0000000   .044608  .049361  -.022091  .010010
+    1961.55  -.008206  .011519   .085606  .010050   .0000000  .0000000   .122173  .040208  -.064085  .011324
+    1961.60  -.051487  .015238   .123137  .012517   .0000000  .0000000   .076453  .040358  -.034798  .016069
+    1961.65  -.017757  .013816   .095707  .012173   .0000000  .0000000   .139748  .037766  -.009789  .017459
+    1961.70  -.062010  .014301   .097662  .010789   .0000000  .0000000   .151076  .028427   .021771  .016330
+    1961.75  -.081090  .015416   .089862  .012166   .0000000  .0000000   .050875  .029772  -.029162  .018757
+    1961.80  -.110423  .013068   .077764  .010812   .0000000  .0000000   .050749  .030057  -.051615  .016866
+    1961.85  -.090300  .016100   .114700  .012300   .0000000  .0000000  -.014600  .037900  -.010800  .016400
+    1961.90  -.167482  .018102   .169747  .012490   .0000000  .0000000  -.025160  .044893  -.020808  .015706
+    1961.95  -.142626  .013234   .162677  .012140   .0000000  .0000000   .096048  .047052   .003845  .011241
+    1962.00  -.033900  .017100   .203700  .013600   .0376300  .0146000   .000000  .000000   .000000  .000000
+    1962.05  -.050170  .014430   .211840  .012140   .0338900  .0133200   .000000  .000000   .000000  .000000
+    1962.10  -.002320  .017110   .229940  .012770   .0290470  .0134500   .000000  .000000   .000000  .000000
+    1962.15   .006920  .018700   .252420  .018200   .0240100  .0162000   .000000  .000000   .000000  .000000
+    1962.20   .024920  .016200   .267420  .015500   .0164880  .0149000   .000000  .000000   .000000  .000000
+    1962.25   .036710  .015210   .249550  .015050   .0102410  .0142600   .000000  .000000   .000000  .000000
+    1962.30   .072420  .017430   .225380  .017660  -.0005960  .0168200   .000000  .000000   .000000  .000000
+    1962.35   .094690  .018700   .208290  .017540  -.0104660  .0169000   .000000  .000000   .000000  .000000
+    1962.40   .093250  .017570   .193210  .017020  -.0187080  .0156600   .000000  .000000   .000000  .000000
+    1962.45   .107960  .018660   .129190  .018270  -.0156280  .0180200   .000000  .000000   .000000  .000000
+    1962.50   .095310  .017460   .127660  .017260  -.0096470  .0164200   .000000  .000000   .000000  .000000
+    1962.55   .086920  .016900   .113560  .015650   .0013710  .0151500   .000000  .000000   .000000  .000000
+    1962.60   .069240  .017840   .063740  .017960   .0066930  .0171500   .000000  .000000   .000000  .000000
+    1962.65   .055400  .016640   .049150  .016300   .0122100  .0149300   .000000  .000000   .000000  .000000
+    1962.70   .008500  .016540   .041810  .015810   .0142490  .0148400   .000000  .000000   .000000  .000000
+    1962.75  -.014150  .018820   .060290  .018700   .0105620  .0178200   .000000  .000000   .000000  .000000
+    1962.80  -.066110  .016250   .050990  .015590   .0038340  .0149800   .000000  .000000   .000000  .000000
+    1962.85  -.113040  .016610   .105830  .015680  -.0066870  .0155700   .000000  .000000   .000000  .000000
+    1962.90  -.153970  .021970   .139440  .019620  -.0175860  .0181300   .000000  .000000   .000000  .000000
+    1962.95  -.160030  .021360   .176030  .019750  -.0286510  .0182100   .000000  .000000   .000000  .000000
+    1963.00  -.205590  .024840   .212120  .022870  -.0332190  .0207100   .000000  .000000   .000000  .000000
+    1963.05  -.201720  .020230   .264370  .018510  -.0339840  .0173800   .000000  .000000   .000000  .000000
+    1963.10  -.173000  .017760   .287920  .016570  -.0309280  .0156300   .000000  .000000   .000000  .000000
+    1963.15  -.148670  .018450   .335970  .017880  -.0308550  .0159600   .000000  .000000   .000000  .000000
+    1963.20  -.099870  .017450   .335960  .016390  -.0392730  .0161400   .000000  .000000   .000000  .000000
+    1963.25  -.044310  .017840   .360350  .016930  -.0507330  .0157900   .000000  .000000   .000000  .000000
+    1963.30   .021450  .017350   .354760  .016500  -.0615850  .0150300   .000000  .000000   .000000  .000000
+    1963.35   .093210  .018140   .324570  .016940  -.0762480  .0155900   .000000  .000000   .000000  .000000
+    1963.40   .152910  .018670   .306570  .017860  -.0852720  .0170900   .000000  .000000   .000000  .000000
+    1963.45   .175600  .021310   .263720  .019770  -.0898040  .0196500   .000000  .000000   .000000  .000000
+    1963.50   .230800  .019620   .226120  .017420  -.0911400  .0167700   .000000  .000000   .000000  .000000
+    1963.55   .218840  .016860   .193180  .015570  -.0850800  .0147700   .000000  .000000   .000000  .000000
+    1963.60   .207420  .018510   .115940  .016960  -.0800220  .0155000   .000000  .000000   .000000  .000000
+    1963.65   .148670  .018730   .085350  .019220  -.0829150  .0174300   .000000  .000000   .000000  .000000
+    1963.70   .096090  .016040   .028620  .015490  -.0876470  .0147500   .000000  .000000   .000000  .000000
+    1963.75   .053710  .020020  -.010670  .018330  -.0974610  .0165900   .000000  .000000   .000000  .000000
+    1963.80  -.017030  .015520  -.023980  .014320  -.1141360  .0137500   .000000  .000000   .000000  .000000
+    1963.85  -.106000  .018730  -.008970  .018460  -.0370110  .0172000   .000000  .000000   .000000  .000000
+    1963.90  -.162800  .022040   .001510  .021360  -.0481380  .0197300   .000000  .000000   .000000  .000000
+    1963.95  -.172400  .018540   .042730  .017540  -.0669830  .0169800   .000000  .000000   .000000  .000000
+    1964.00  -.225800  .021630   .073470  .019990  -.0808460  .0189500   .000000  .000000   .000000  .000000
+    1964.05  -.277190  .019900   .142370  .019340  -.0959270  .0189700   .000000  .000000   .000000  .000000
+    1964.10  -.316290  .018270   .213450  .017350  -.1133170  .0162800   .000000  .000000   .000000  .000000
+    1964.15  -.278600  .020010   .281690  .017670  -.1248710  .0168000   .000000  .000000   .000000  .000000
+    1964.20  -.246040  .017960   .323490  .016880  -.1403400  .0160800   .000000  .000000   .000000  .000000
+    1964.25  -.179450  .016490   .390780  .015240  -.0597570  .0147800   .000000  .000000   .000000  .000000
+    1964.30  -.106780  .015610   .417820  .015450  -.0730700  .0143500   .000000  .000000   .000000  .000000
+    1964.35  -.051130  .017730   .465850  .017200  -.0918930  .0154900   .000000  .000000   .000000  .000000
+    1964.40  -.000180  .016200   .454570  .015860  -.1099970  .0146100   .000000  .000000   .000000  .000000
+    1964.45   .070820  .017660   .457390  .017230  -.1212000  .0157600   .000000  .000000   .000000  .000000
+    1964.50   .122250  .016730   .410720  .017010  -.1147420  .0153900   .000000  .000000   .000000  .000000
+    1964.55   .188300  .016040   .371690  .015870  -.1164510  .0145300   .000000  .000000   .000000  .000000
+    1964.60   .233650  .018730   .317960  .018160  -.1142910  .0164100   .000000  .000000   .000000  .000000
+    1964.65   .243950  .015300   .251720  .015260  -.1118720  .0137800   .000000  .000000   .000000  .000000
+    1964.70   .228520  .015130   .159640  .014810  -.0165730  .0137500   .000000  .000000   .000000  .000000
+    1964.75   .202930  .016080   .093010  .015660  -.0291840  .0142000   .000000  .000000   .000000  .000000
+    1964.80   .163200  .017480   .037870  .017150  -.0476800  .0153100   .000000  .000000   .000000  .000000
+    1964.85   .107390  .017250   .018400  .016220  -.0671060  .0146300   .000000  .000000   .000000  .000000
+    1964.90   .042310  .018970  -.014260  .017750  -.0837400  .0159100   .000000  .000000   .000000  .000000
+    1964.95  -.022710  .017480  -.019620  .017800  -.1003350  .0168300   .000000  .000000   .000000  .000000
+    1965.00  -.089890  .017540  -.005080  .017770  -.0182700  .0155700   .000000  .000000   .000000  .000000
+    1965.05  -.109340  .020910  -.011770  .019760  -.0248210  .0178900   .000000  .000000   .000000  .000000
+    1965.10  -.187520  .016700   .079690  .015740  -.0413790  .0153700   .000000  .000000   .000000  .000000
+    1965.15  -.220180  .015780   .108850  .015600  -.0595530  .0148100   .000000  .000000   .000000  .000000
+    1965.20  -.239960  .015850   .170890  .014540   .0201840  .0139800   .000000  .000000   .000000  .000000
+    1965.25  -.239880  .014860   .232370  .014700  -.0057010  .0133300   .000000  .000000   .000000  .000000
+    1965.30  -.221390  .016120   .286720  .014580  -.0330600  .0137300   .000000  .000000   .000000  .000000
+    1965.35  -.177010  .016430   .329310  .015110  -.0487050  .0144700   .000000  .000000   .000000  .000000
+    1965.40  -.151550  .014790   .380270  .013930  -.0661190  .0133300   .000000  .000000   .000000  .000000
+    1965.45  -.115410  .017280   .406270  .016860  -.0832370  .0153900   .000000  .000000   .000000  .000000
+    1965.50  -.033960  .018000   .439390  .016580   .0111050  .0152100   .000000  .000000   .000000  .000000
+    1965.55   .047390  .018020   .425360  .016460   .0060030  .0153800   .000000  .000000   .000000  .000000
+    1965.60   .084440  .020530   .411480  .019450  -.0046230  .0178800   .000000  .000000   .000000  .000000
+    1965.65   .105520  .016310   .371940  .015300  -.0087120  .0140700   .000000  .000000   .000000  .000000
+    1965.70   .137420  .016280   .304360  .015810   .0758570  .0142700   .000000  .000000   .000000  .000000
+    1965.75   .168630  .020750   .248710  .019550   .0544290  .0168100   .000000  .000000   .000000  .000000
+    1965.80   .200590  .016310   .176560  .016160   .0353090  .0145100   .000000  .000000   .000000  .000000
+    1965.85   .178810  .017050   .143930  .016190   .0119610  .0151900   .000000  .000000   .000000  .000000
+    1965.90   .158060  .021980   .087030  .020220  -.0139660  .0178700   .000000  .000000   .000000  .000000
+    1965.95   .115300  .019820   .054420  .018510  -.0327310  .0171400   .000000  .000000   .000000  .000000
+    1966.00   .047900  .021460   .005530  .019630  -.0467430  .0170800   .000000  .000000   .000000  .000000
+    1966.05   .003210  .021070   .018400  .019450  -.0442320  .0179400   .000000  .000000   .000000  .000000
+    1966.10  -.020370  .019000   .017330  .017320  -.0397280  .0152900   .000000  .000000   .000000  .000000
+    1966.15  -.092720  .018200   .042830  .016850  -.0398940  .0153300   .000000  .000000   .000000  .000000
+    1966.20  -.126630  .016810   .060540  .016230  -.0393290  .0144800   .000000  .000000   .000000  .000000
+    1966.25  -.126250  .016740   .087680  .015810  -.0396900  .0146800   .000000  .000000   .000000  .000000
+    1966.30  -.167720  .015830   .130720  .015330  -.0463990  .0140700   .000000  .000000   .000000  .000000
+    1966.35  -.161730  .017410   .172470  .016490  -.0516050  .0149100   .000000  .000000   .000000  .000000
+    1966.40  -.151510  .017850   .196200  .018220  -.0495510  .0164900   .000000  .000000   .000000  .000000
+    1966.45  -.128550  .016130   .234880  .015210  -.0432800  .0141600   .000000  .000000   .000000  .000000
+    1966.50  -.124150  .018800   .306450  .019320  -.0321410  .0172300   .000000  .000000   .000000  .000000
+    1966.55  -.081600  .016620   .310620  .015820  -.0125560  .0141500   .000000  .000000   .000000  .000000
+    1966.60  -.055550  .015510   .328730  .015120   .0003880  .0138900   .000000  .000000   .000000  .000000
+    1966.65  -.017090  .017080   .338450  .016220   .0095020  .0144900   .000000  .000000   .000000  .000000
+    1966.70   .006590  .015310   .333040  .014830   .0161450  .0135400   .000000  .000000   .000000  .000000
+    1966.75   .042120  .017470   .311320  .016490   .0146070  .0149000   .000000  .000000   .000000  .000000
+    1966.80   .091960  .017500   .283830  .016510   .0121820  .0146500   .000000  .000000   .000000  .000000
+    1966.85   .094580  .019200   .252760  .017990   .0098330  .0157100   .000000  .000000   .000000  .000000
+    1966.90   .116210  .023420   .220110  .021570   .0051870  .0180300   .000000  .000000   .000000  .000000
+    1966.95   .135490  .020350   .172910  .017450   .0058710  .0172200   .000000  .000000   .000000  .000000
+    1967.00   .097100  .016900   .162300  .014300   .0124750  .0140000   .000000  .000000   .000000  .000000
+    1967.05   .070010  .015300   .139910  .013600   .0184380  .0129000   .000000  .000000   .000000  .000000
+    1967.10   .048010  .014100   .130910  .012600   .0211400  .0121000   .000000  .000000   .000000  .000000
+    1967.15   .032320  .014100   .139020  .012500   .0229620  .0122000   .000000  .000000   .000000  .000000
+    1967.20   .014320  .014500   .136220  .013100   .0194950  .0124000   .000000  .000000   .000000  .000000
+    1967.25   .005330  .013900   .130830  .012200   .0167670  .0120000   .000000  .000000   .000000  .000000
+    1967.30  -.008570  .013300   .144330  .011700   .0133100  .0117000   .000000  .000000   .000000  .000000
+    1967.35  -.013670  .014300   .164530  .013100   .0065720  .0126000   .000000  .000000   .000000  .000000
+    1967.40  -.008560  .013800   .148640  .012200   .0071750  .0121000   .000000  .000000   .000000  .000000
+    1967.45   .003850  .014000   .168250  .012300   .0176880  .0122000   .000000  .000000   .000000  .000000
+    1967.50  -.011850  .014100   .176050  .012200   .0301300  .0124000   .000000  .000000   .000000  .000000
+    1967.55  -.008350  .013500   .193960  .011900   .0477730  .0121000   .000000  .000000   .000000  .000000
+    1967.60  -.011740  .013700   .189260  .011600   .0663160  .0120000   .000000  .000000   .000000  .000000
+    1967.65  -.001430  .014800   .186370  .012900   .0768980  .0127000   .000000  .000000   .000000  .000000
+    1967.70  -.029530  .013400   .191370  .011300   .0890110  .0117000   .000000  .000000   .000000  .000000
+    1967.75  -.033830  .013300   .184480  .011800   .0963740  .0118000   .000000  .000000   .000000  .000000
+    1967.80  -.030620  .014100   .195580  .012400   .0971770  .0125000   .000000  .000000   .000000  .000000
+    1967.85  -.035120  .013800   .205980  .012100   .0953500  .0121000   .000000  .000000   .000000  .000000
+    1967.90  -.026910  .014200   .212290  .013000   .0952730  .0126000   .000000  .000000   .000000  .000000
+    1967.95  -.026200  .014100   .222600  .012300   .0931660  .0121000   .000000  .000000   .000000  .000000
+    1968.00  -.034000  .015100   .239700  .012400   .0951090  .0127000   .000000  .000000   .000000  .000000
+    1968.05  -.005100  .016200   .237510  .014100   .0987210  .0143000   .000000  .000000   .000000  .000000
+    1968.10  -.004790  .014500   .238810  .012300  -.0023360  .0129000   .000000  .000000   .000000  .000000
+    1968.15  -.001680  .014200   .237720  .011900  -.0036230  .0123000   .000000  .000000   .000000  .000000
+    1968.20   .030920  .015500   .241420  .013500  -.0012590  .0137000   .000000  .000000   .000000  .000000
+    1968.25   .015230  .013900   .230330  .011900  -.0024360  .0123000   .000000  .000000   .000000  .000000
+    1968.30   .046430  .013500   .242330  .011700  -.0107430  .0121000   .000000  .000000   .000000  .000000
+    1968.35   .060630  .014400   .223740  .012300  -.0118800  .0127000   .000000  .000000   .000000  .000000
+    1968.40   .057340  .014100   .203640  .011900  -.0136970  .0125000   .000000  .000000   .000000  .000000
+    1968.45   .059250  .012900   .198750  .011400  -.0100140  .0119000   .000000  .000000   .000000  .000000
+    1968.50   .068150  .013800   .173950  .012800   .0057390  .0131000   .000000  .000000   .000000  .000000
+    1968.55   .067460  .012900   .166360  .011300   .0170720  .0117000   .000000  .000000   .000000  .000000
+    1968.60   .052060  .013300   .142860  .011400   .0302750  .0120000   .000000  .000000   .000000  .000000
+    1968.65   .027070  .014100   .135670  .012200   .0354390  .0123000   .000000  .000000   .000000  .000000
+    1968.70   .005570  .012700   .135770  .011500   .0390020  .0117000   .000000  .000000   .000000  .000000
+    1968.75  -.013830  .013300   .118780  .011800   .0406750  .0120000   .000000  .000000   .000000  .000000
+    1968.80  -.042020  .013400   .106380  .012200   .0419680  .0123000   .000000  .000000   .000000  .000000
+    1968.85  -.084920  .013700   .124390  .012000   .0356310  .0122000   .000000  .000000   .000000  .000000
+    1968.90  -.139410  .013500   .147490  .011800   .0341150  .0121000   .000000  .000000   .000000  .000000
+    1968.95  -.126810  .014100   .185200  .012800   .0350180  .0130000   .000000  .000000   .000000  .000000
+    1969.00  -.139900  .013900   .214900  .012500   .0335710  .0124000   .000000  .000000   .000000  .000000
+    1969.05  -.124100  .014400   .251100  .013200   .0372640  .0130000   .000000  .000000   .000000  .000000
+    1969.10  -.106290  .014000   .262510  .012300   .0391280  .0124000   .000000  .000000   .000000  .000000
+    1969.15  -.095880  .013200   .326120  .011800   .0309210  .0121000   .000000  .000000   .000000  .000000
+    1969.20  -.079080  .014000   .337320  .012600   .0246540  .0127000   .000000  .000000   .000000  .000000
+    1969.25  -.036380  .013000   .347630  .011600   .0124870  .0121000   .000000  .000000   .000000  .000000
+    1969.30  -.000970  .012900   .351930  .011700   .0000710  .0119000   .000000  .000000   .000000  .000000
+    1969.35   .055030  .013300   .361340  .011900  -.0043960  .0120000   .000000  .000000   .000000  .000000
+    1969.40   .090640  .013200   .316240  .011700  -.0064830  .0120000   .000000  .000000   .000000  .000000
+    1969.45   .125150  .012500   .295450  .011800  -.0097100  .0117000   .000000  .000000   .000000  .000000
+    1969.50   .133450  .013100   .267750  .012100   .0040040  .0121000   .000000  .000000   .000000  .000000
+    1969.55   .150150  .012800   .228760  .011500   .0133570  .0117000   .000000  .000000   .000000  .000000
+    1969.60   .134960  .012500   .187660  .011100   .0232700  .0114000   .000000  .000000   .000000  .000000
+    1969.65   .117370  .013900   .136570  .012200   .0362230  .0124000   .000000  .000000   .000000  .000000
+    1969.70   .095770  .012500   .114170  .011000   .0343170  .0114000   .000000  .000000   .000000  .000000
+    1969.75   .058680  .012700   .100680  .011200   .0285300  .0115000   .000000  .000000   .000000  .000000
+    1969.80   .011380  .013400   .065480  .012200   .0246530  .0122000   .000000  .000000   .000000  .000000
+    1969.85  -.011720  .012800   .063480  .011300   .0178860  .0116000   .000000  .000000   .000000  .000000
+    1969.90  -.062210  .013700   .070390  .011900   .0119090  .0122000   .000000  .000000   .000000  .000000
+    1969.95  -.122410  .013900   .082300  .012300   .0067420  .0122000   .000000  .000000   .000000  .000000
+    1970.00  -.163200  .013900   .117800  .012300   .0047260  .0123000   .000000  .000000   .000000  .000000
+    1970.05  -.200400  .013900   .175210  .012800  -.0043710  .0122000   .000000  .000000   .000000  .000000
+    1970.10  -.217990  .013300   .213110  .012200  -.0072880  .0119000   .000000  .000000   .000000  .000000
+    1970.15  -.167580  .013400   .287720  .012000  -.0178350  .0119000   .000000  .000000   .000000  .000000
+    1970.20  -.155880  .013700   .325820  .013200  -.0272820  .0127000   .000000  .000000   .000000  .000000
+    1970.25  -.140180  .013600   .357830  .012300  -.0373190  .0122000   .000000  .000000   .000000  .000000
+    1970.30  -.092070  .012800   .388230  .011900  -.0515660  .0116000   .000000  .000000   .000000  .000000
+    1970.35  -.036570  .014100   .394540  .012600  -.0614930  .0126000   .000000  .000000   .000000  .000000
+    1970.40   .009940  .012700   .407740  .011300  -.0624500  .0116000   .000000  .000000   .000000  .000000
+    1970.45   .077750  .013100   .394750  .011700  -.0622170  .0120000   .000000  .000000   .000000  .000000
+    1970.50   .130150  .013700   .370950  .012300  -.0542940  .0124000   .000000  .000000   .000000  .000000
+    1970.55   .166660  .012800   .330060  .011600  -.0435010  .0117000   .000000  .000000   .000000  .000000
+    1970.60   .200960  .012700   .262860  .011000  -.0298880  .0113000   .000000  .000000   .000000  .000000
+    1970.65   .205070  .013300   .222970  .011800  -.0204550  .0120000   .000000  .000000   .000000  .000000
+    1970.70   .196270  .012800   .160070  .011500  -.0125620  .0117000   .000000  .000000   .000000  .000000
+    1970.75   .178680  .012600   .101880  .011300  -.0144890  .0115000   .000000  .000000   .000000  .000000
+    1970.80   .141580  .013000   .043980  .011900  -.0185570  .0120000   .000000  .000000   .000000  .000000
+    1970.85   .064680  .012600   .026980  .011300  -.0256240  .0115000   .000000  .000000   .000000  .000000
+    1970.90   .013790  .012900   .006190  .011500  -.0358210  .0115000   .000000  .000000   .000000  .000000
+    1970.95  -.045910  .013500  -.008500  .012300  -.0395080  .0121000   .000000  .000000   .000000  .000000
+    1971.00  -.094800  .013300   .014300  .011800  -.0386560  .0118000   .000000  .000000   .000000  .000000
+    1971.05  -.145000  .013400   .063100  .011700  -.0423130  .0118000   .000000  .000000   .000000  .000000
+    1971.10  -.193590  .013100   .108210  .011500  -.0417900  .0117000   .000000  .000000   .000000  .000000
+    1971.15  -.226190  .012700   .164220  .011100  -.0385280  .0115000   .000000  .000000   .000000  .000000
+    1971.20  -.248080  .012700   .221720  .010900  -.0447450  .0112000   .000000  .000000   .000000  .000000
+    1971.25  -.221480  .012500   .298620  .010800  -.0573030  .0112000   .000000  .000000   .000000  .000000
+    1971.30  -.200070  .012400   .353230  .010700  -.0652400  .0112000   .000000  .000000   .000000  .000000
+    1971.35  -.187870  .013100   .384540  .011400  -.0779880  .0117000   .000000  .000000   .000000  .000000
+    1971.40  -.131860  .013100   .428740  .011000  -.0875360  .0115000   .000000  .000000   .000000  .000000
+    1971.45  -.046460  .012800   .458050  .010900  -.0888030  .0114000   .000000  .000000   .000000  .000000
+    1971.50   .029850  .012700   .466050  .011100  -.0875110  .0113000   .000000  .000000   .000000  .000000
+    1971.55   .104850  .012400   .444960  .010600  -.0828490  .0111000   .000000  .000000   .000000  .000000
+    1971.60   .162960  .012000   .400160  .010200  -.0790560  .0108000   .000000  .000000   .000000  .000000
+    1971.65   .211970  .012600   .361270  .011000  -.0778240  .0114000   .000000  .000000   .000000  .000000
+    1971.70   .233970  .012200   .304470  .010700  -.0821020  .0111000   .000000  .000000   .000000  .000000
+    1971.75   .225880  .012300   .218780  .010600  -.0877900  .0111000   .000000  .000000   .000000  .000000
+    1971.80   .208880  .012600   .167780  .011000  -.1047780  .0114000   .000000  .000000   .000000  .000000
+    1971.85   .181790  .012500   .101490  .010900  -.1220760  .0112000   .000000  .000000   .000000  .000000
+    1971.90   .140590  .012800   .071290  .011000  -.1384440  .0112000   .000000  .000000   .000000  .000000
+    1971.95   .084400  .014100   .039100  .012000  -.1490720  .0119000   .000000  .000000   .000000  .000000
+    1972.00   .031820  .013570   .019710  .011210  -.0474900  .0033800   .000000  .000000   .000000  .000000
+    1972.05  -.029350  .012770   .019540  .010910  -.1025340  .0037900   .000000  .000000   .000000  .000000
+    1972.10  -.085000  .013210   .023390  .011220  -.1641870  .0035000   .000000  .000000   .000000  .000000
+    1972.15  -.113320  .012570   .038780  .010590  -.2239540  .0021800   .000000  .000000   .000000  .000000
+    1972.20  -.170800  .012180   .100130  .010510  -.2844970  .0034200   .000000  .000000   .000000  .000000
+    1972.25  -.178190  .013190   .157660  .011180  -.3489940  .0024900   .000000  .000000   .000000  .000000
+    1972.30  -.193440  .012520   .216340  .010780  -.4137270  .0029400   .000000  .000000   .000000  .000000
+    1972.35  -.177900  .012220   .273960  .010460  -.4751870  .0043600   .000000  .000000   .000000  .000000
+    1972.40  -.148990  .013040   .302730  .011340  -.5400640  .0031600   .000000  .000000   .000000  .000000
+    1972.45  -.101340  .012210   .350600  .010680  -.5937930  .0110200   .000000  .000000   .000000  .000000
+    1972.50  -.048730  .012910   .379110  .010840   .3591600  .0042800   .000000  .000000   .000000  .000000
+    1972.55   .000850  .012690   .403050  .010910   .3124850  .0029100   .000000  .000000   .000000  .000000
+    1972.60   .057740  .012190   .404590  .010360   .2662670  .0026800   .000000  .000000   .000000  .000000
+    1972.65   .089870  .012660   .408890  .010920   .2208620  .0023600   .000000  .000000   .000000  .000000
+    1972.70   .119360  .012130   .367470  .010410   .1685090  .0057300   .000000  .000000   .000000  .000000
+    1972.75   .125150  .012250   .330830  .010670   .1107640  .0028700   .000000  .000000   .000000  .000000
+    1972.80   .161790  .013110   .292310  .011320   .0507720  .0115700   .000000  .000000   .000000  .000000
+    1972.85   .164080  .012730   .229730  .010910  -.0089650  .0112300   .000000  .000000   .000000  .000000
+    1972.90   .154490  .012570   .213280  .010660  -.0670860  .0029200   .000000  .000000   .000000  .000000
+    1972.95   .142830  .013030   .172430  .011240  -.1269170  .0037200   .000000  .000000   .000000  .000000
+    1973.00   .123610  .010590   .125710  .007920   .8114390  .0113200   .000000  .000000   .000000  .000000
+    1973.05   .091980  .008970   .093390  .007760   .7545430  .0028400   .000000  .000000   .000000  .000000
+    1973.10   .055100  .010360   .086390  .007830   .6973530  .0116100   .000000  .000000   .000000  .000000
+    1973.15   .024830  .008970   .089030  .007800   .6317400  .0036200   .000000  .000000   .000000  .000000
+    1973.20  -.023270  .009910   .093100  .007690   .5731350  .0039400   .000000  .000000   .000000  .000000
+    1973.25  -.050430  .010230   .105840  .007750   .5070570  .0041400   .000000  .000000   .000000  .000000
+    1973.30  -.090950  .010050   .145940  .007670   .4422160  .0030600   .000000  .000000   .000000  .000000
+    1973.35  -.107840  .007540   .174450  .006420   .3817300  .0030300   .000000  .000000   .000000  .000000
+    1973.40  -.116560  .007550   .201930  .005940   .3252920  .0036100   .000000  .000000   .000000  .000000
+    1973.45  -.109350  .011160   .245230  .005950   .2701480  .0031200   .000000  .000000   .000000  .000000
+    1973.50  -.097490  .007510   .273170  .005970   .2259990  .0034000   .000000  .000000   .000000  .000000
+    1973.55  -.074020  .009970   .300780  .007710   .1814520  .0071400   .000000  .000000   .000000  .000000
+    1973.60  -.053250  .009780   .315260  .007550   .1350890  .0030500   .000000  .000000   .000000  .000000
+    1973.65  -.014030  .009960   .319880  .007620   .0897480  .0035100   .000000  .000000   .000000  .000000
+    1973.70   .014500  .009970   .323150  .007660   .0381470  .0060700   .000000  .000000   .000000  .000000
+    1973.75   .034570  .009690   .333410  .006090  -.0166510  .0063800   .000000  .000000   .000000  .000000
+    1973.80   .069270  .007630   .331530  .007560  -.0721010  .0033300   .000000  .000000   .000000  .000000
+    1973.85   .082930  .008760   .288210  .007590  -.1313010  .0024900   .000000  .000000   .000000  .000000
+    1973.90   .094550  .009970   .270630  .007570  -.1950090  .0106800   .000000  .000000   .000000  .000000
+    1973.95   .105000  .009050   .265120  .007810  -.2487100  .0023500   .000000  .000000   .000000  .000000
+    1974.00   .113200  .010100   .225230  .007730   .7002310  .0073000   .000000  .000000   .000000  .000000
+    1974.05   .091980  .011510   .203370  .007650   .6520660  .0043200   .000000  .000000   .000000  .000000
+    1974.10   .077870  .008970   .176520  .007820   .6063570  .0031800   .000000  .000000   .000000  .000000
+    1974.15   .078890  .009940   .171530  .007620   .5537260  .0069500   .000000  .000000   .000000  .000000
+    1974.20   .050750  .010050   .157750  .007660   .4983770  .0044100   .000000  .000000   .000000  .000000
+    1974.25   .029950  .007680   .179730  .006060   .4438800  .0107400   .000000  .000000   .000000  .000000
+    1974.30   .029220  .009390   .187280  .007720   .3871170  .0107700   .000000  .000000   .000000  .000000
+    1974.35   .015470  .009500   .182320  .007730   .3220300  .0031000   .000000  .000000   .000000  .000000
+    1974.40   .005080  .009580   .179910  .007850   .2706650  .0115400   .000000  .000000   .000000  .000000
+    1974.45  -.016260  .009460   .187160  .007750   .2230120  .0031700   .000000  .000000   .000000  .000000
+    1974.50   .019490  .009480   .195670  .007770   .1828640  .0025100   .000000  .000000   .000000  .000000
+    1974.55   .022340  .009570   .210720  .007760   .1474170  .0038500   .000000  .000000   .000000  .000000
+    1974.60   .019950  .009360   .212310  .007650   .1109470  .0031300   .000000  .000000   .000000  .000000
+    1974.65   .016610  .009410   .209630  .007650   .0663730  .0027200   .000000  .000000   .000000  .000000
+    1974.70   .010980  .009550   .202280  .007770   .0252920  .0024300   .000000  .000000   .000000  .000000
+    1974.75   .003730  .009660   .216240  .007790  -.0251410  .0033500   .000000  .000000   .000000  .000000
+    1974.80  -.012130  .008500   .232720  .007750  -.0802570  .0059400   .000000  .000000   .000000  .000000
+    1974.85  -.024480  .009820   .240310  .007970  -.1325930  .0041100   .000000  .000000   .000000  .000000
+    1974.90  -.033410  .009690   .254200  .007970  -.1905590  .0028600   .000000  .000000   .000000  .000000
+    1974.95  -.043730  .009750   .267890  .008040  -.2441870  .0086400   .000000  .000000   .000000  .000000
+    1975.00  -.050120  .008590   .270650  .008000   .7083150  .0113300   .000000  .000000   .000000  .000000
+    1975.05  -.053700  .008370   .285590  .007710   .6585310  .0049400   .000000  .000000   .000000  .000000
+    1975.10  -.030920  .008550   .306400  .008030   .6055510  .0112100   .000000  .000000   .000000  .000000
+    1975.15  -.019500  .009350   .329540  .007790   .5525990  .0035600   .000000  .000000   .000000  .000000
+    1975.20   .010660  .009430   .335300  .007810   .5013940  .0068100   .000000  .000000   .000000  .000000
+    1975.25   .043890  .009600   .337490  .007980   .4422900  .0026300   .000000  .000000   .000000  .000000
+    1975.30   .070800  .009650   .313520  .007850   .3887900  .0025400   .000000  .000000   .000000  .000000
+    1975.35   .089170  .009480   .296380  .007840   .3321200  .0029200   .000000  .000000   .000000  .000000
+    1975.40   .103620  .009630   .270190  .007850   .2824180  .0024800   .000000  .000000   .000000  .000000
+    1975.45   .125630  .009450   .246550  .007760   .2386220  .0028800   .000000  .000000   .000000  .000000
+    1975.50   .146030  .009560   .234320  .007940   .1972230  .0039100   .000000  .000000   .000000  .000000
+    1975.55   .132900  .009470   .199120  .007760   .1637560  .0032000   .000000  .000000   .000000  .000000
+    1975.60   .126320  .009330   .176400  .007760   .1307220  .0105700   .000000  .000000   .000000  .000000
+    1975.65   .119740  .009380   .152660  .007800   .0878550  .0028400   .000000  .000000   .000000  .000000
+    1975.70   .092300  .009530   .118640  .007850   .0444550  .0039100   .000000  .000000   .000000  .000000
+    1975.75   .062280  .009540   .103450  .007720  -.0020730  .0026100   .000000  .000000   .000000  .000000
+    1975.80   .020950  .009400   .098770  .007780  -.0586960  .0024800   .000000  .000000   .000000  .000000
+    1975.85  -.041700  .009490   .103980  .007900  -.1161850  .0027700   .000000  .000000   .000000  .000000
+    1975.90  -.072420  .009650   .130280  .007910  -.1711520  .0025700   .000000  .000000   .000000  .000000
+    1975.95  -.127410  .008520   .157660  .007880  -.2229470  .0032300   .000000  .000000   .000000  .000000
+    1976.00  -.144340  .009600   .193270  .008000   .7251490  .0105200   .000000  .000000   .000000  .000000
+    1976.05  -.151500  .008420   .247180  .007820   .6775030  .0033100   .000000  .000000   .000000  .000000
+    1976.10  -.156180  .009510   .289100  .007920   .6214200  .0066400   .000000  .000000   .000000  .000000
+    1976.15  -.145290  .009630   .329230  .007930   .5693700  .0037300   .000000  .000000   .000000  .000000
+    1976.20  -.117400  .009560   .367510  .007930   .5147140  .0046300   .000000  .000000   .000000  .000000
+    1976.25  -.095400  .009540   .393190  .007880   .4538780  .0109900   .000000  .000000   .000000  .000000
+    1976.30  -.041730  .009490   .425870  .007790   .3908040  .0060800   .000000  .000000   .000000  .000000
+    1976.35  -.008800  .007870   .433170  .006840   .3343790  .0037900   .000000  .000000   .000000  .000000
+    1976.40   .046660  .004470   .423870  .006980   .2739120  .0041400   .000000  .000000   .000000  .000000
+    1976.45   .111730  .004720   .401030  .006880   .2245910  .0032300   .000000  .000000   .000000  .000000
+    1976.50   .156480  .005240   .370970  .006350   .1856130  .0037500   .000000  .000000   .000000  .000000
+    1976.55   .195270  .005570   .330200  .007560   .1405230  .0072500   .000000  .000000   .000000  .000000
+    1976.60   .229060  .008910   .289950  .009410   .0972370  .0027300   .000000  .000000   .000000  .000000
+    1976.65   .235790  .007970   .241180  .006750   .0569540  .0066700   .000000  .000000   .000000  .000000
+    1976.70   .220780  .008280   .189190  .006630   .0056210  .0033300   .000000  .000000   .000000  .000000
+    1976.75   .172600  .004740   .157950  .005040  -.0542780  .0057200   .000000  .000000   .000000  .000000
+    1976.80   .159550  .003200   .117960  .003370  -.1129530  .0032600   .000000  .000000   .000000  .000000
+    1976.85   .113500  .003710   .093390  .003730  -.1756720  .0035700   .000000  .000000   .000000  .000000
+    1976.90   .053590  .003540   .071240  .003560  -.2292200  .0041000   .000000  .000000   .000000  .000000
+    1976.95  -.004070  .003990   .065610  .003690  -.2824520  .0048500   .000000  .000000   .000000  .000000
+    1977.00  -.068560  .004880   .069220  .004230   .6657090  .0036700   .000000  .000000   .000000  .000000
+    1977.05  -.139290  .004730   .118540  .004370   .6143360  .0051800   .000000  .000000   .000000  .000000
+    1977.10  -.188740  .004460   .156640  .003860   .5651410  .0031900   .000000  .000000   .000000  .000000
+    1977.15  -.226790  .006250   .231150  .004950   .5121100  .0031000   .000000  .000000   .000000  .000000
+    1977.20  -.228460  .005680   .290850  .004120   .4600880  .0068900   .000000  .000000   .000000  .000000
+    1977.25  -.216780  .003080   .362450  .002890   .4021850  .0021700   .000000  .000000   .000000  .000000
+    1977.30  -.174880  .003600   .414280  .003440   .3418380  .0045300   .000000  .000000   .000000  .000000
+    1977.35  -.133880  .004150   .458560  .003960   .2827490  .0051900   .000000  .000000   .000000  .000000
+    1977.40  -.071690  .010490   .489080  .009550   .2309290  .0023600   .000000  .000000   .000000  .000000
+    1977.45   .012030  .003540   .504510  .003880   .1838870  .0041000   .000000  .000000   .000000  .000000
+    1977.50   .082770  .002520   .495390  .002840   .1468180  .0018000   .000000  .000000   .000000  .000000
+    1977.55   .149380  .003370   .454360  .003620   .1142770  .0019800   .000000  .000000   .000000  .000000
+    1977.60   .210730  .003320   .410780  .003600   .0768320  .0019700   .000000  .000000   .000000  .000000
+    1977.65   .249250  .004220   .351780  .004520   .0408590  .0024600   .000000  .000000   .000000  .000000
+    1977.70   .269380  .002950   .292600  .003710  -.0085350  .0021100   .000000  .000000   .000000  .000000
+    1977.75   .263020  .003500   .222970  .003510  -.0636710  .0025300   .000000  .000000   .000000  .000000
+    1977.80   .243710  .003790   .151260  .003990  -.1196200  .0033400   .000000  .000000   .000000  .000000
+    1977.85   .195430  .003850   .095930  .004190  -.1771710  .0026900   .000000  .000000   .000000  .000000
+    1977.90   .133680  .003770   .061560  .003970  -.2363140  .0019400   .000000  .000000   .000000  .000000
+    1977.95   .063460  .003070   .030340  .003390  -.2912280  .0026400   .000000  .000000   .000000  .000000
+    1978.00  -.000350  .006860   .027050  .006710   .6495220  .0045600   .000000  .000000   .000000  .000000
+    1978.05  -.067600  .005140   .036990  .007410   .5903240  .0049700   .000000  .000000   .000000  .000000
+    1978.10  -.136660  .005210   .072860  .006600   .5357610  .0070500   .000000  .000000   .000000  .000000
+    1978.15  -.182100  .005230   .105900  .006590   .4701360  .0039900   .000000  .000000   .000000  .000000
+    1978.20  -.214500  .003140   .163140  .003850   .4061470  .0056400   .000000  .000000   .000000  .000000
+    1978.25  -.236230  .003270   .234600  .003050   .3442840  .0041700   .000000  .000000   .000000  .000000
+    1978.30  -.229900  .003970   .312160  .003250   .2835510  .0022700   .000000  .000000   .000000  .000000
+    1978.35  -.200940  .002850   .379730  .002600   .2243820  .0069100   .000000  .000000   .000000  .000000
+    1978.40  -.157910  .004050   .433860  .003990   .1677820  .0022300   .000000  .000000   .000000  .000000
+    1978.45  -.110240  .003970   .468530  .003570   .1209930  .0031800   .000000  .000000   .000000  .000000
+    1978.50  -.044260  .003530   .492280  .003560   .0799780  .0027100   .000000  .000000   .000000  .000000
+    1978.55   .033760  .002730   .496900  .002830   .0461430  .0025300   .000000  .000000   .000000  .000000
+    1978.60   .098530  .002640   .478150  .002760   .0128410  .0034000   .000000  .000000   .000000  .000000
+    1978.65   .150640  .001940   .444140  .002040  -.0312900  .0030700   .000000  .000000   .000000  .000000
+    1978.70   .194320  .002790   .408640  .002980  -.0754340  .0036100   .000000  .000000   .000000  .000000
+    1978.75   .221790  .002910   .353150  .003140  -.1252120  .0037900   .000000  .000000   .000000  .000000
+    1978.80   .234780  .002740   .290520  .002920  -.1826230  .0020000   .000000  .000000   .000000  .000000
+    1978.85   .228930  .003190   .229200  .003160  -.2362770  .0029900   .000000  .000000   .000000  .000000
+    1978.90   .196110  .004580   .176960  .004140  -.2927440  .0029900   .000000  .000000   .000000  .000000
+    1978.95   .169350  .004230   .117020  .004390  -.3501350  .0030400   .000000  .000000   .000000  .000000
+    1979.00   .140600  .004850   .085500  .004540   .5990550  .0092100   .000000  .000000   .000000  .000000
+    1979.05   .098400  .006120   .059560  .005460   .5436940  .0079200   .000000  .000000   .000000  .000000
+    1979.10   .023200  .003360   .064460  .003420   .4873690  .0025000   .000000  .000000   .000000  .000000
+    1979.15  -.017580  .003950   .069020  .004470   .4372970  .0035200   .000000  .000000   .000000  .000000
+    1979.20  -.067290  .004260   .087350  .004270   .3838980  .0025100   .000000  .000000   .000000  .000000
+    1979.25  -.111680  .003470   .125490  .003760   .3253590  .0027200   .000000  .000000   .000000  .000000
+    1979.30  -.137550  .002330   .174350  .002950   .2698590  .0018600   .000000  .000000   .000000  .000000
+    1979.35  -.152140  .002870   .218350  .003250   .2124640  .0021400   .000000  .000000   .000000  .000000
+    1979.40  -.158240  .002720   .263800  .003010   .1596610  .0032200   .000000  .000000   .000000  .000000
+    1979.45  -.145410  .003090   .301690  .003070   .1196450  .0029900   .000000  .000000   .000000  .000000
+    1979.50  -.120340  .002530   .348910  .003130   .0786440  .0064600   .000000  .000000   .000000  .000000
+    1979.55  -.093020  .002590   .378590  .002700   .0405690  .0031000   .000000  .000000   .000000  .000000
+    1979.60  -.032280  .004930   .404160  .004640   .0082610  .0040400   .000000  .000000   .000000  .000000
+    1979.65   .013040  .003750   .420310  .003990  -.0308800  .0025600   .000000  .000000   .000000  .000000
+    1979.70   .053770  .002720   .423000  .003330  -.0723390  .0024500   .000000  .000000   .000000  .000000
+    1979.75   .087730  .002540   .410920  .002940  -.1151000  .0041800   .000000  .000000   .000000  .000000
+    1979.80   .103920  .001630   .386840  .001740  -.1669670  .0022100   .000000  .000000   .000000  .000000
+    1979.85   .133930  .003380   .357770  .003350  -.2160390  .0041200   .000000  .000000   .000000  .000000
+    1979.90   .132630  .001940   .322640  .002410  -.2606420  .0032900   .000000  .000000   .000000  .000000
+    1979.95   .135250  .001860   .285040  .001910  -.3086520  .0027600   .000000  .000000   .000000  .000000
+    1980.00   .142150  .002360   .250260  .002550   .6449390  .0010700   .000000  .000000   .000000  .000000
+    1980.05   .121150  .002430   .224530  .002000   .5994770  .0011100   .000000  .000000   .000000  .000000
+    1980.10   .089390  .002000   .199240  .001640   .5548120  .0012400   .000000  .000000   .000000  .000000
+    1980.15   .064250  .001990   .182700  .001610   .5085250  .0009700   .000000  .000000   .000000  .000000
+    1980.20   .043590  .001540   .179240  .001360   .4666600  .0011300   .000000  .000000   .000000  .000000
+    1980.25   .012160  .001970   .187460  .001550   .4165130  .0012000   .000000  .000000   .000000  .000000
+    1980.30  -.020440  .001920   .201760  .002020   .3666940  .0005600   .012390  .001200  -.003550  .000350
+    1980.35  -.043480  .002040   .221870  .001830   .3219240  .0014400   .000000  .000000   .000000  .000000
+    1980.40  -.052250  .001920   .240890  .001830   .2763230  .0012400   .000000  .000000   .000000  .000000
+    1980.45  -.054760  .001770   .259160  .001660   .2387700  .0013700   .000000  .000000   .000000  .000000
+    1980.50  -.051620  .001940   .282750  .001860   .2063630  .0015100   .000000  .000000   .000000  .000000
+    1980.55  -.039350  .001980   .301970  .001810   .1755970  .0002600   .002900  .000800  -.003360  .000230
+    1980.60  -.035550  .001470   .314750  .001410   .1452760  .0009200   .000000  .000000   .000000  .000000
+    1980.65  -.030090  .001510   .328120  .001390   .1151990  .0009800   .000000  .000000   .000000  .000000
+    1980.70  -.030200  .001490   .337170  .001410   .0750790  .0009700   .000000  .000000   .000000  .000000
+    1980.75  -.023160  .001500   .345640  .001450   .0300980  .0001600   .000590  .000360  -.002620  .000120
+    1980.80  -.012370  .001400   .358870  .001410  -.0127940  .0001400   .004850  .000300  -.001960  .000100
+    1980.85   .000830  .001430   .366600  .001360  -.0624580  .0012400  -.000310  .003340  -.001500  .000790
+    1980.90   .022640  .001990   .373160  .001740  -.1078580  .0004200   .007390  .001200  -.001790  .000320
+    1980.95   .049120  .002020   .373030  .001700  -.1500100  .0003600   .010830  .001030  -.000520  .000270
+    1981.00   .070580  .001670   .360660  .001840  -.1953270  .0040700   .004000  .002680  -.000470  .000650
+    1981.05   .077000  .001510   .348400  .001680  -.2391430  .0005100   .007830  .001280  -.000010  .000380
+    1981.10   .089260  .001270   .329090  .001060  -.2776990  .0011000   .010230  .002700  -.000250  .000960
+    1981.15   .084840  .001010   .315780  .001020  -.3202690  .0007000   .011050  .002700   .000040  .000580
+    1981.20   .090210  .000790   .304230  .000800  -.3727280  .0013700   .008890  .002840  -.002880  .000900
+    1981.25   .101630  .000890   .289720  .000940  -.4159950  .0016800   .000000  .000000   .000000  .000000
+    1981.30   .096310  .000870   .268760  .001200  -.4685540  .0013900   .000000  .000000   .000000  .000000
+    1981.35   .093750  .000980   .257220  .000920  -.5165520  .0015500   .010480  .004480  -.003860  .001390
+    1981.40   .090250  .001110   .241670  .001230  -.5587390  .0015600   .000000  .000000   .000000  .000000
+    1981.45   .078570  .000850   .226280  .001070  -.6009320  .0004300   .002930  .000690  -.003700  .000200
+    1981.50   .068150  .000810   .210210  .000810   .3698510  .0014900   .002610  .002490  -.004120  .000620
+    1981.55   .059540  .000770   .193490  .000780   .3498320  .0013400   .000750  .003130  -.002280  .000880
+    1981.60   .033080  .000950   .184820  .001110   .3198500  .0017100  -.003550  .003350  -.003460  .000910
+    1981.65   .004150  .000740   .185370  .000750   .2918900  .0012000   .000910  .002860  -.004060  .000710
+    1981.70  -.024140  .000710   .193490  .000710   .2653000  .0011700  -.005840  .002480  -.002860  .000720
+    1981.75  -.060920  .000710   .209640  .000700   .2228820  .0011100  -.005830  .002680  -.000670  .000950
+    1981.80  -.084890  .000690   .235550  .000670   .1804970  .0005200  -.001860  .001480  -.001690  .000470
+    1981.85  -.104520  .000780   .264190  .000800   .1393580  .0013800   .005070  .001970  -.000530  .000530
+    1981.90  -.110340  .001250   .298730  .000870   .0957520  .0002200   .001260  .000360   .000660  .000120
+    1981.95  -.112180  .001070   .336860  .000790   .0571520  .0020500   .006620  .002610   .000650  .000690
+    1982.00  -.093080  .001000   .376820  .000860   .0184280  .0017100   .005820  .001770   .001000  .000510
+    1982.05  -.056710  .001150   .406900  .000920  -.0233770  .0024400   .001600  .001660   .001710  .000480
+    1982.10  -.029250  .000960   .429470  .000810  -.0576400  .0017900   .004510  .002200   .001450  .000580
+    1982.15   .016930  .000960   .440390  .000860  -.0968960  .0018300   .002170  .002170   .000850  .000570
+    1982.20   .062800  .000970   .438790  .000820  -.1429420  .0004100   .004220  .001240  -.000430  .000340
+    1982.25   .108360  .000970   .429570  .000940  -.1860770  .0023100   .004830  .002410  -.000950  .000720
+    1982.30   .144250  .000790   .410160  .000790  -.2324500  .0006000   .007640  .001680  -.002570  .000390
+    1982.35   .175760  .000710   .379360  .000750  -.2826500  .0013700   .004140  .002320  -.002400  .000650
+    1982.40   .202440  .000650   .335180  .000690  -.3212050  .0009700   .006000  .002100  -.002670  .000570
+    1982.45   .227390  .000730   .284220  .000920  -.3589540  .0001600   .001880  .000460  -.001670  .000140
+    1982.50   .225400  .000620   .235390  .000680   .6073090  .0009800  -.003910  .002750  -.001360  .000780
+    1982.55   .211690  .000650   .183440  .000650   .5824430  .0010100  -.000930  .002400  -.001680  .000670
+    1982.60   .188000  .000700   .139540  .000730   .5595280  .0011600  -.003430  .003010   .000260  .000800
+    1982.65   .147580  .000710   .100920  .000670   .5266190  .0012700  -.004690  .002940  -.001270  .000780
+    1982.70   .090980  .000660   .077680  .000680   .4890550  .0005400  -.005130  .001680  -.000640  .000510
+    1982.75   .028040  .000650   .068920  .000670   .4484150  .0012400  -.008690  .003000   .000710  .000970
+    1982.80  -.036070  .000640   .079650  .000610   .4039600  .0002700  -.002760  .000740  -.000180  .000200
+    1982.85  -.092580  .000660   .099410  .000700   .3645380  .0009400  -.001670  .001640   .000520  .000530
+    1982.90  -.143280  .000890   .139280  .000840   .3204710  .0017700  -.000420  .002110   .002190  .000590
+    1982.95  -.184870  .000690   .194480  .000690   .2722880  .0001700   .000730  .000420   .002030  .000130
+    1983.00  -.202510  .000710   .257960  .000670   .2276730  .0011300   .004010  .001640   .002770  .000480
+    1983.05  -.208590  .000690   .319420  .000710   .1807080  .0011500   .002530  .001490   .002220  .000410
+    1983.10  -.188080  .000740   .386630  .000780   .1215960  .0004400   .002640  .000960   .001590  .000270
+    1983.15  -.166980  .000740   .446850  .000760   .0712980  .0004000   .007800  .001060   .000500  .000310
+    1983.20  -.130670  .000690   .499770  .000680   .0173990  .0004000   .004030  .001030   .000410  .000290
+    1983.25  -.060990  .000680   .541150  .000730  -.0393690  .0010800   .002480  .002210  -.000190  .000610
+    1983.30   .018010  .000730   .561080  .000730  -.0893990  .0010700   .005370  .001500  -.001230  .000430
+    1983.35   .089520  .000660   .551750  .000890  -.1353850  .0003100   .005970  .000760  -.001240  .000230
+    1983.40   .165160  .000700   .528540  .000850  -.1815520  .0010800   .003960  .002480  -.001540  .000630
+    1983.45   .220450  .000760   .481900  .000930  -.2193950  .0003800   .002630  .000840  -.001270  .000240
+    1983.50   .270130  .000770   .421220  .000920   .7475800  .0010100  -.003070  .001710   .000180  .000430
+    1983.55   .307330  .000670   .346400  .000780   .7215090  .0006600  -.006430  .001190  -.000660  .000270
+    1983.60   .323430  .000710   .271320  .000770   .6952120  .0007200  -.004220  .001220  -.000850  .000320
+    1983.65   .311990  .000680   .193620  .000840   .6642850  .0008600  -.006240  .001200  -.000820  .000310
+    1983.70   .270820  .000560   .123360  .000640   .6298510  .0008700  -.008450  .001710  -.000360  .000500
+    1983.75   .212870  .000570   .065270  .000690   .5983220  .0004400  -.006270  .000840  -.000160  .000250
+    1983.80   .144260  .000200   .027540  .000210   .5583590  .0004000  -.007880  .001040   .001710  .000580
+    1983.85   .061990  .000220   .014950  .000200   .5132280  .0059100  -.004500  .000960   .002060  .000720
+    1983.90  -.016890  .000210   .026220  .000210   .4716860  .0022000   .000610  .001070   .004000  .000750
+    1983.95  -.085210  .000200   .050470  .000200   .4337780  .0004600   .000050  .000660   .003990  .000490
+    1984.00  -.133280  .000230   .091680  .000230   .3954610  .0002500   .001240  .000900   .002650  .000490
+    1984.05  -.178600  .000200   .145720  .000190   .3663980  .0002200   .002630  .000710   .003010  .000320
+    1984.10  -.217680  .000210   .203540  .000210   .3393920  .0002100   .001960  .000650   .003760  .000390
+    1984.15  -.239790  .000210   .267220  .000190   .3071050  .0002200   .001970  .000640   .002560  .000280
+    1984.20  -.240330  .000210   .342950  .000210   .2769000  .0001600   .004310  .000360   .001640  .000190
+    1984.25  -.215180  .000210   .414620  .000210   .2386810  .0002000   .003990  .000530   .001510  .000320
+    1984.30  -.165880  .000180   .478570  .000170   .2012160  .0001500   .004670  .000270  -.000090  .000160
+    1984.35  -.103940  .000200   .529520  .000180   .1686240  .0001900   .005600  .000380  -.000670  .000250
+    1984.40  -.036610  .000170   .557690  .000160   .1381370  .0001700   .002970  .000330  -.000030  .000230
+    1984.45   .043530  .000180   .559030  .000170   .1142480  .0001700   .000400  .000350  -.000580  .000220
+    1984.50   .118910  .000170   .544370  .000170   .0977110  .0001500  -.000110  .000220  -.000540  .000130
+    1984.55   .192030  .000170   .505220  .000160   .0854250  .0001600  -.004690  .000250   .000080  .000150
+    1984.60   .256550  .000160   .452690  .000150   .0683640  .0001300  -.006200  .000210  -.000330  .000110
+    1984.65   .294920  .000130   .386890  .000130   .0497870  .0000800  -.007620  .000160  -.000590  .000090
+    1984.70   .308190  .000180   .317250  .000170   .0228220  .0001600  -.008140  .000320   .000970  .000190
+    1984.75   .311850  .000180   .246370  .000170  -.0075050  .0001700  -.009280  .000330   .000570  .000200
+    1984.80   .284570  .000170   .180700  .000160  -.0363910  .0001600  -.004020  .000290   .001860  .000200
+    1984.85   .247250  .000180   .123390  .000170  -.0715010  .0001600  -.004470  .000300   .002490  .000220
+    1984.90   .198900  .000180   .081750  .000170  -.1028830  .0001700  -.001400  .000320   .003070  .000250
+    1984.95   .127310  .000170   .041390  .000160  -.1301440  .0001500  -.000720  .000240   .003610  .000160
+    1985.00   .045080  .000180   .022560  .000170  -.1575460  .0001400   .000660  .000240   .004680  .000130
+    1985.05  -.021710  .000190   .036290  .000170  -.1889130  .0001500   .001040  .000300   .003940  .000130
+    1985.10  -.079030  .000170   .063220  .000160  -.2116370  .0001200   .002930  .000220   .003730  .000110
+    1985.15  -.133690  .000170   .102890  .000170  -.2407380  .0001200   .001780  .000220   .003340  .000110
+    1985.20  -.185320  .000170   .156740  .000160  -.2736890  .0001200   .002900  .000210   .000710  .000120
+    1985.25  -.201050  .000160   .230230  .000150  -.3070830  .0001200   .006560  .000200   .000520  .000110
+    1985.30  -.195870  .000170   .298580  .000150  -.3429910  .0001200   .005330  .000210   .000700  .000130
+    1985.35  -.182010  .000140   .364520  .000130  -.3771130  .0001000   .005260  .000180  -.000440  .000090
+    1985.40  -.138460  .000170   .418650  .000160  -.4025590  .0001300   .004820  .000210  -.000700  .000130
+    1985.45  -.095300  .000130   .459340  .000130  -.4317500  .0000800   .001180  .000170  -.000230  .000090
+    1985.50  -.043950  .000150   .483270  .000150   .5478600  .0001200  -.000110  .000190   .000060  .000110
+    1985.55   .017740  .000140   .494700  .000140   .5395290  .0001100  -.003020  .000180  -.000640  .000090
+    1985.60   .076740  .000150   .494160  .000140   .5251140  .0001200  -.006370  .000190   .000200  .000100
+    1985.65   .135950  .000150   .477470  .000150   .5115900  .0001300  -.008700  .000240  -.000310  .000120
+    1985.70   .182620  .000150   .445550  .000150   .4948280  .0001200  -.007150  .000210  -.000090  .000120
+    1985.75   .211380  .000150   .402010  .000140   .4660470  .0001200  -.008410  .000190   .001000  .000100
+    1985.80   .227170  .000160   .347600  .000150   .4338690  .0001200  -.006020  .000210   .000470  .000140
+    1985.85   .228420  .000150   .297330  .000150   .4018540  .0001200  -.003090  .000210   .001620  .000130
+    1985.90   .228310  .000130   .251090  .000130   .3668480  .0000800  -.003190  .000170   .003280  .000100
+    1985.95   .209470  .000170   .210230  .000160   .3364070  .0001400  -.002280  .000240   .003710  .000160
+    1986.00   .185940  .000180   .170580  .000170   .3132290  .0001600   .000210  .000280   .003660  .000180
+    1986.05   .148620  .000140   .136920  .000130   .2869110  .0001200  -.001040  .000190   .004400  .000100
+    1986.10   .097820  .000140   .120120  .000130   .2595480  .0001100  -.001060  .000190   .003540  .000090
+    1986.15   .050650  .000150   .114890  .000150   .2343500  .0001200   .000210  .000240   .002680  .000120
+    1986.20  -.004480  .000160   .120220  .000150   .2069080  .0001300   .001510  .000200   .002050  .000120
+    1986.25  -.045110  .000140   .137800  .000130   .1831500  .0001000   .001580  .000180   .000470  .000100
+    1986.30  -.074620  .000150   .174240  .000150   .1553600  .0001200   .005500  .000210   .000020  .000130
+    1986.35  -.091050  .000150   .210930  .000140   .1220280  .0001100   .003860  .000180  -.000070  .000100
+    1986.40  -.103510  .000170   .248370  .000160   .0984900  .0001400   .003140  .000240  -.000240  .000160
+    1986.45  -.097870  .000130   .286570  .000130   .0863460  .0000800   .002230  .000170   .000410  .000100
+    1986.50  -.071490  .000150   .325960  .000150   .0698390  .0001100  -.003030  .000180   .000210  .000100
+    1986.55  -.044780  .000140   .356680  .000140   .0591900  .0001000  -.004290  .000160   .000190  .000080
+    1986.60  -.017440  .000150   .376640  .000140   .0494220  .0001100  -.007430  .000170   .000050  .000090
+    1986.65   .010780  .000180   .391720  .000170   .0327720  .0001500  -.010920  .000310  -.000160  .000170
+    1986.70   .039560  .000160   .398150  .000150   .0179060  .0001200  -.008650  .000190   .000010  .000110
+    1986.75   .061300  .000170   .393670  .000160  -.0068750  .0001500  -.006850  .000330   .001200  .000200
+    1986.80   .085600  .000140   .389850  .000130  -.0389540  .0001000  -.006290  .000180   .001170  .000100
+    1986.85   .108410  .000130   .379180  .000130  -.0658570  .0000800  -.003770  .000160   .001570  .000090
+    1986.90   .121680  .000160   .358470  .000150  -.0899120  .0001200  -.001090  .000210   .002640  .000150
+    1986.95   .139690  .000150   .333040  .000140  -.1163700  .0001100  -.002590  .000190   .002420  .000110
+    1987.00   .146260  .000160   .313070  .000150  -.1380760  .0001100  -.001700  .000210   .002690  .000120
+    1987.05   .139250  .000160   .286810  .000140  -.1601160  .0001100  -.001080  .000190   .003260  .000100
+    1987.10   .129080  .000130   .265690  .000120  -.1865420  .0001100  -.002300  .000160   .002650  .000090
+    1987.15   .122130  .000130   .247910  .000120  -.2129500  .0001000  -.000630  .000160   .001850  .000090
+    1987.20   .110320  .000140   .223500  .000140  -.2463650  .0001100  -.000050  .000190   .001220  .000100
+    1987.25   .094220  .000140   .212870  .000130  -.2807030  .0001000  -.000080  .000170   .000190  .000090
+    1987.30   .072280  .000140   .204670  .000140  -.3086560  .0001100   .001600  .000180  -.000620  .000100
+    1987.35   .053320  .000130   .200540  .000130  -.3362570  .0001000   .002010  .000170  -.000810  .000090
+    1987.40   .030170  .000150   .199490  .000150  -.3639160  .0001100   .001280  .000190  -.000580  .000110
+    1987.45   .015310  .000140   .199420  .000140  -.3832670  .0001100  -.000210  .000180  -.000410  .000110
+    1987.50  -.006420  .000130   .206770  .000130  -.3985660  .0000800  -.002110  .000160   .000130  .000090
+    1987.55  -.025810  .000130   .218770  .000130  -.4124200  .0001000  -.006670  .000160  -.000360  .000090
+    1987.60  -.031970  .000140   .234330  .000130  -.4193230  .0001100  -.007390  .000160  -.000770  .000090
+    1987.65  -.037620  .000140   .254830  .000140  -.4346680  .0001100  -.009480  .000200   .000110  .000100
+    1987.70  -.043540  .000150   .272020  .000140  -.4584800  .0001100  -.010770  .000200  -.000250  .000110
+    1987.75  -.055190  .000150   .296620  .000150  -.4825460  .0001300  -.007710  .000220  -.000170  .000130
+    1987.80  -.063220  .000130   .318760  .000130  -.5129600  .0000900  -.006400  .000160   .000820  .000090
+    1987.85  -.060180  .000130   .341610  .000130  -.5455880  .0000800  -.005460  .000160   .001310  .000090
+    1987.90  -.056330  .000150   .371220  .000140  -.5748670  .0001200  -.003730  .000190   .001910  .000110
+    1987.95  -.049860  .000140   .395210  .000130  -.6043940  .0001000  -.001870  .000170   .002500  .000100
+    1988.00  -.023960  .000140   .412730  .000130   .3641980  .0001200  -.004140  .000190   .002660  .000100
+    1988.05   .004500  .000120   .424730  .000110   .3384500  .0001000  -.002530  .000160   .002120  .000090
+    1988.10   .047020  .000130   .432110  .000120   .3144130  .0001000  -.000740  .000180   .002150  .000100
+    1988.15   .067110  .000130   .430020  .000130   .2785320  .0001100  -.002550  .000190   .000600  .000100
+    1988.20   .105530  .000130   .427540  .000130   .2471970  .0001000  -.000980  .000170  -.000240  .000090
+    1988.25   .133210  .000130   .406300  .000130   .2166860  .0001100  -.000500  .000180  -.000430  .000100
+    1988.30   .150780  .000130   .378320  .000120   .1792750  .0000900  -.000370  .000160  -.001620  .000090
+    1988.35   .171170  .000140   .354020  .000140   .1522840  .0001100   .000780  .000190  -.001780  .000130
+    1988.40   .176460  .000130   .321580  .000130   .1225530  .0001000  -.000040  .000180  -.001500  .000100
+    1988.45   .165470  .000120   .287990  .000120   .0988100  .0000800  -.001720  .000160  -.001290  .000090
+    1988.50   .169520  .000140   .251610  .000130   .0898640  .0001200  -.003630  .000190  -.001180  .000100
+    1988.55   .162560  .000130   .216260  .000120   .0807490  .0001000  -.007890  .000160  -.000680  .000090
+    1988.60   .140250  .000120   .179670  .000110   .0689520  .0000800  -.010350  .000160  -.001420  .000080
+    1988.65   .106640  .000120   .154640  .000120   .0603010  .0001000  -.010090  .000180  -.001000  .000100
+    1988.70   .066470  .000120   .136560  .000120   .0448510  .0001000  -.010210  .000170  -.000500  .000100
+    1988.75   .009150  .000130   .129100  .000130   .0228930  .0001000  -.011320  .000200  -.000380  .000110
+    1988.80  -.050020  .000130   .138100  .000130  -.0018930  .0001100  -.007830  .000200  -.000750  .000110
+    1988.85  -.100790  .000110   .165460  .000110  -.0330640  .0000700  -.005600  .000150   .000990  .000080
+    1988.90  -.138410  .000120   .207940  .000120  -.0653100  .0000900  -.005220  .000170   .001020  .000100
+    1988.95  -.164740  .000120   .261170  .000110  -.0918720  .0000800  -.003500  .000160   .001530  .000080
+    1989.00  -.160800  .000130   .315200  .000140  -.1150310  .0000900  -.002340  .000170   .002030  .000090
+    1989.05  -.142800  .000120   .359530  .000110  -.1376110  .0000900  -.003600  .000170   .001370  .000090
+    1989.10  -.118060  .000120   .400480  .000110  -.1614360  .0000900  -.002340  .000170   .000860  .000090
+    1989.15  -.076130  .000120   .436720  .000110  -.1886810  .0000900  -.001680  .000160   .000380  .000080
+    1989.20  -.027240  .000130   .466260  .000120  -.2181740  .0001000  -.001820  .000180  -.001260  .000100
+    1989.25   .029070  .000120   .480900  .000120  -.2452640  .0000900  -.000610  .000170  -.002120  .000090
+    1989.30   .085860  .000120   .481670  .000120  -.2761340  .0000800  -.000780  .000150  -.002250  .000080
+    1989.35   .127570  .000120   .470310  .000120  -.3109290  .0001000  -.001920  .000170  -.003040  .000100
+    1989.40   .169220  .000120   .445260  .000120  -.3388540  .0000800  -.001680  .000150  -.003030  .000080
+    1989.45   .204420  .000120   .412890  .000120  -.3680090  .0000900  -.004720  .000170  -.002620  .000090
+    1989.50   .239210  .000120   .364510  .000120  -.3859960  .0000800  -.007490  .000160  -.002840  .000090
+    1989.55   .259150  .000120   .312920  .000120  -.4009490  .0000900  -.009020  .000170  -.002220  .000090
+    1989.60   .259400  .000120   .255620  .000120  -.4214040  .0000800  -.011270  .000150  -.002020  .000080
+    1989.65   .250970  .000120   .197720  .000120  -.4424920  .0000900  -.013980  .000160  -.002400  .000090
+    1989.70   .217420  .000120   .146080  .000120  -.4611150  .0000800  -.013140  .000160  -.002080  .000090
+    1989.75   .165120  .000120   .105110  .000110  -.4903590  .0000800  -.012600  .000160  -.000730  .000080
+    1989.80   .098020  .000110   .083150  .000110  -.5228010  .0000700  -.011010  .000150  -.001130  .000070
+    1989.85   .031480  .000110   .074730  .000110  -.5592470  .0000700  -.008550  .000150  -.000710  .000080
+    1989.90  -.036820  .000110   .087780  .000110  -.6014820  .0000800  -.007450  .000150   .000760  .000080
+    1989.95  -.090410  .000110   .118340  .000110  -.6390910  .0000700  -.006100  .000150   .000840  .000080
+    1990.00  -.132820  .000120   .163800  .000120   .3294770  .0000800  -.004230  .000160   .000950  .000090
+    1990.05  -.165870  .000110   .215080  .000110   .2971590  .0000800  -.005310  .000150   .000930  .000080
+    1990.10  -.202780  .000110   .276390  .000110   .2614270  .0000800  -.005390  .000150  -.000120  .000080
+    1990.15  -.201680  .000110   .344430  .000110   .2205110  .0000800  -.004370  .000160  -.000690  .000080
+    1990.20  -.185180  .000110   .413230  .000110   .1791940  .0000800  -.004430  .000150  -.002050  .000080
+    1990.25  -.153910  .000110   .471710  .000110   .1351550  .0000800  -.003760  .000150  -.003080  .000080
+    1990.30  -.101550  .000110   .524360  .000110   .0948910  .0000800  -.001280  .000150  -.003890  .000080
+    1990.35  -.049070  .000110   .556830  .000110   .0554040  .0000800  -.002860  .000150  -.003970  .000080
+    1990.40   .025280  .000110   .572830  .000110   .0201240  .0000700  -.004400  .000150  -.004260  .000080
+    1990.45   .096160  .000110   .568570  .000110  -.0096640  .0000800  -.004910  .000160  -.004050  .000080
+    1990.50   .166980  .000110   .541670  .000110  -.0403750  .0000800  -.009000  .000150  -.003880  .000080
+    1990.55   .230520  .000110   .499990  .000110  -.0614930  .0000800  -.011350  .000160  -.003850  .000080
+    1990.60   .276540  .000120   .439320  .000110  -.0830990  .0000800  -.013660  .000160  -.002920  .000090
+    1990.65   .306230  .000110   .379690  .000110  -.1154370  .0000700  -.015530  .000160  -.003320  .000080
+    1990.70   .312300  .000110   .309110  .000110  -.1458280  .0000800  -.015250  .000160  -.003160  .000080
+    1990.75   .295990  .000110   .241750  .000110  -.1816860  .0000800  -.014130  .000150  -.002630  .000080
+    1990.80   .258290  .000110   .178550  .000110  -.2226650  .0000800  -.013370  .000150  -.001910  .000080
+    1990.85   .214630  .000110   .130690  .000110  -.2630650  .0000800  -.010960  .000150  -.001740  .000080
+    1990.90   .158460  .000110   .095450  .000110  -.3023270  .0000800  -.009260  .000150  -.000700  .000080
+    1990.95   .092590  .000110   .076290  .000110  -.3458130  .0000800  -.008690  .000150   .000090  .000080
+    1991.00   .023070  .000120   .070420  .000120   .6189660  .0000800  -.007640  .000160   .000100  .000080
+    1991.05  -.040210  .000110   .085850  .000110   .5788470  .0000800  -.006390  .000160   .000290  .000080
+    1991.10  -.104560  .000110   .109710  .000100   .5375110  .0000700  -.007400  .000150  -.000780  .000080
+    1991.15  -.159350  .000110   .156090  .000110   .4982140  .0000800  -.007290  .000160  -.002160  .000080
+    1991.20  -.193710  .000110   .215880  .000110   .4563180  .0000700  -.005840  .000150  -.002750  .000080
+    1991.25  -.218250  .000110   .286330  .000110   .4101900  .0000800  -.005420  .000150  -.004230  .000080
+    1991.30  -.211540  .000110   .359670  .000110   .3695240  .0000700  -.004780  .000150  -.005250  .000080
+    1991.35  -.196100  .000120   .427740  .000110   .3269160  .0000800  -.003480  .000150  -.005350  .000080
+    1991.40  -.148030  .000110   .487300  .000110   .2852580  .0000700  -.006750  .000150  -.005630  .000080
+    1991.45  -.087780  .000120   .535430  .000110   .2509990  .0000800  -.007820  .000150  -.005310  .000080
+    1991.50  -.027600  .000110   .563210  .000110   .2244370  .0000700  -.010640  .000150  -.004690  .000080
+    1991.55   .049470  .000110   .572690  .000110   .1994110  .0000800  -.014450  .000150  -.004550  .000080
+    1991.60   .118890  .000110   .560660  .000110   .1792000  .0000700  -.015800  .000150  -.004890  .000080
+    1991.65   .172940  .000110   .527310  .000110   .1523860  .0000800  -.017410  .000150  -.004390  .000080
+    1991.70   .218130  .000110   .487510  .000110   .1145380  .0000700  -.019540  .000150  -.003880  .000080
+    1991.75   .251390  .000110   .434860  .000120   .0781450  .0000800  -.017070  .000150  -.004230  .000080
+    1991.80   .262130  .000100   .372840  .000100   .0419620  .0000700  -.015530  .000150  -.003410  .000070
+    1991.85   .263160  .000110   .317840  .000110   .0002900  .0000700  -.013880  .000150  -.002470  .000080
+    1991.90   .247290  .000110   .263630  .000110  -.0397540  .0000800  -.011140  .000150  -.001880  .000080
+    1991.95   .217400  .000100   .209210  .000100  -.0833930  .0000700  -.010160  .000150  -.000890  .000070
+    1992.00   .183430  .000110   .168250  .000110  -.1253090  .0000700  -.010560  .000150  -.001100  .000080
+    1992.05   .132860  .000110   .139720  .000110  -.1664230  .0000700  -.009680  .000150  -.001230  .000080
+    1992.10   .083410  .000110   .121340  .000110  -.2133580  .0000700  -.009250  .000150  -.001360  .000070
+    1992.15   .026850  .000110   .116920  .000100  -.2592480  .0000700  -.009810  .000150  -.002790  .000080
+    1992.20  -.034650  .000110   .126400  .000110  -.3037880  .0000700  -.008310  .000150  -.004080  .000080
+    1992.25  -.082680  .000120   .163990  .000110  -.3574120  .0000800  -.007420  .000160  -.004690  .000080
+    1992.30  -.115610  .000110   .203320  .000110  -.4102900  .0000700  -.007920  .000150  -.005450  .000080
+    1992.35  -.145550  .000110   .245630  .000110  -.4539040  .0000700  -.007330  .000150  -.006620  .000080
+    1992.40  -.156500  .000110   .291880  .000110  -.4959850  .0000700  -.008410  .000150  -.006170  .000080
+    1992.45  -.153110  .000120   .334650  .000120  -.5303330  .0000800  -.010970  .000170  -.005880  .000090
+    1992.50  -.140940  .000110   .381020  .000110   .4420910  .0000700  -.012890  .000150  -.006070  .000080
+    1992.55  -.115160  .000110   .420770  .000110   .4184490  .0000700  -.016380  .000140  -.005610  .000070
+    1992.60  -.077490  .000100   .459320  .000100   .3892290  .0000700  -.020190  .000140  -.005790  .000070
+    1992.65  -.031830  .000110   .492120  .000110   .3596050  .0000700  -.020360  .000150  -.006130  .000080
+    1992.70   .014530  .000110   .506730  .000110   .3231410  .0000700  -.021800  .000150  -.005180  .000080
+    1992.75   .055600  .000110   .503780  .000110   .2854080  .0000700  -.021980  .000150  -.005110  .000080
+    1992.80   .103120  .000110   .494250  .000100   .2458780  .0000700  -.018870  .000150  -.004950  .000080
+    1992.85   .137780  .000110   .473110  .000110   .1994080  .0000700  -.017150  .000150  -.004090  .000080
+    1992.90   .170750  .000110   .444760  .000110   .1538820  .0000700  -.015860  .000150  -.003210  .000080
+    1992.95   .187750  .000110   .406300  .000110   .1096390  .0000700  -.014370  .000150  -.002500  .000080
+    1993.00   .208200  .000170   .361780  .000190   .0639800  .0010000  -.012130  .000220  -.001820  .000110
+    1993.05   .212870  .000170   .311750  .000160   .0163900  .0010000  -.013700  .000240  -.001980  .000130
+    1993.10   .205710  .000220   .265790  .000200  -.0283100  .0010000  -.013700  .000160  -.003160  .000080
+    1993.15   .186400  .000210   .225690  .000200  -.0785000  .0010000  -.013380  .000160  -.003430  .000080
+    1993.20   .159450  .000220   .194090  .000150  -.1275600  .0010000  -.012960  .000160  -.005350  .000080
+    1993.25   .113650  .000210   .170110  .000230  -.1750500  .0010000  -.011070  .000170  -.006100  .000080
+    1993.30   .065420  .000250   .163930  .000160  -.2286500  .0010000  -.010500  .000170  -.006910  .000080
+    1993.35   .025160  .000210   .166410  .000190  -.2813400  .0010000  -.012890  .000170  -.007620  .000080
+    1993.40  -.005520  .000210   .177900  .000180  -.3249500  .0010000  -.012100  .000160  -.007690  .000080
+    1993.45  -.036590  .000150   .190810  .000200  -.3670900  .0010000  -.013970  .000160  -.007020  .000070
+    1993.50  -.063740  .000150   .211350  .000230   .5975800  .0010000  -.018750  .000150  -.006860  .000070
+    1993.55  -.073070  .000180   .234400  .000190   .5709200  .0010000  -.019920  .000150  -.007380  .000070
+    1993.60  -.091560  .000150   .266690  .000200   .5374700  .0010000  -.022820  .000160  -.006800  .000080
+    1993.65  -.101560  .000150   .302050  .000170   .5021000  .0010000  -.024430  .000160  -.007300  .000080
+    1993.70  -.099970  .000150   .336910  .000150   .4679700  .0010000  -.024360  .000160  -.007220  .000080
+    1993.75  -.095410  .000150   .370980  .000150   .4245500  .0010000  -.024680  .000150  -.006070  .000070
+    1993.80  -.080940  .000150   .403840  .000180   .3774500  .0010000  -.023390  .000150  -.005460  .000070
+    1993.85  -.062500  .000200   .428470  .000150   .3322200  .0010000  -.020420  .000150  -.005010  .000080
+    1993.90  -.041250  .000160   .448950  .000230   .2851400  .0010000  -.019020  .000150  -.004290  .000070
+    1993.95  -.019600  .000160   .464960  .000170   .2441700  .0010000  -.018560  .000150  -.003470  .000070
+    1994.00   .009200  .000170   .476210  .000190   .2006800  .0010000  -.016450  .000160  -.003840  .000070
+    1994.05   .054050  .000150   .478850  .000160   .1576400  .0010000  -.018260  .000150  -.002940  .000070
+    1994.10   .099840  .000190   .467200  .000180   .1161800  .0010000  -.019390  .000150  -.003820  .000070
+    1994.15   .137660  .000200   .448700  .000150   .0759200  .0010000  -.019230  .000160  -.005950  .000080
+    1994.20   .158340  .000190   .421910  .000150   .0247300  .0010000  -.018050  .000160  -.005840  .000070
+    1994.25   .175010  .000150   .390000  .000240  -.0223200  .0010000  -.017140  .000160  -.007230  .000080
+    1994.30   .183970  .000250   .356950  .000230  -.0662200  .0010000  -.015760  .000150  -.007610  .000070
+    1994.35   .186340  .000150   .317810  .000170  -.1154700  .0010000  -.017740  .000160  -.007860  .000080
+    1994.40   .180670  .000190   .281910  .000150  -.1586500  .0010000  -.017830  .000150  -.008150  .000070
+    1994.45   .160850  .000210   .243850  .000150  -.1904900  .0010000  -.019400  .000160  -.008520  .000080
+    1994.50   .134830  .000150   .210780  .000190   .7815600  .0010000  -.022820  .000150  -.007870  .000080
+    1994.55   .101460  .000170   .184820  .000180   .7562100  .0010000  -.026320  .000150  -.007960  .000070
+    1994.60   .067260  .000180   .172080  .000230   .7314100  .0010000  -.028350  .000160  -.008050  .000070
+    1994.65   .026570  .000160   .168170  .000230   .7029600  .0010000  -.029900  .000150  -.007730  .000070
+    1994.70  -.016290  .000150   .179410  .000190   .6665200  .0010000  -.030070  .000150  -.007650  .000070
+    1994.75  -.066370  .000150   .200140  .000190   .6249200  .0010000  -.029730  .000150  -.008050  .000070
+    1994.80  -.106130  .000140   .232880  .000190   .5793400  .0010000  -.028170  .000150  -.006430  .000070
+    1994.85  -.141410  .000170   .271820  .000170   .5355300  .0010000  -.026750  .000150  -.005780  .000080
+    1994.90  -.152620  .000190   .321150  .000180   .4935800  .0010000  -.024040  .000150  -.005160  .000070
+    1994.95  -.153790  .000170   .368190  .000160   .4476700  .0010000  -.022980  .000150  -.004610  .000070
+    1995.00  -.153720  .000170   .418090  .000170   .3991000  .0010000  -.023030  .000150  -.004120  .000070
+    1995.05  -.127450  .000130   .461200  .000150   .3532000  .0010000  -.022230  .000150  -.004420  .000070
+    1995.10  -.111580  .000130   .494070  .000160   .3028200  .0010000  -.024400  .000150  -.004660  .000070
+    1995.15  -.075420  .000170   .524080  .000150   .2573700  .0010000  -.023460  .000160  -.005540  .000070
+    1995.20  -.022770  .000140   .546010  .000130   .2056500  .0010000  -.022640  .000150  -.007170  .000070
+    1995.25   .035210  .000170   .558400  .000140   .1532400  .0010000  -.023210  .000150  -.007800  .000070
+    1995.30   .092910  .000130   .555900  .000200   .1027500  .0010000  -.021940  .000150  -.008930  .000070
+    1995.35   .162220  .000130   .532900  .000130   .0547700  .0010000  -.020550  .000150  -.009080  .000070
+    1995.40   .209220  .000170   .497340  .000210   .0067200  .0010000  -.023280  .000150  -.008740  .000080
+    1995.45   .254650  .000170   .443560  .000170  -.0324300  .0010000  -.024970  .000150  -.008710  .000070
+    1995.50   .281610  .000140   .378980  .000160  -.0635800  .0010000  -.026890  .000160  -.008000  .000080
+    1995.55   .287570  .000140   .308430  .000170  -.0926700  .0010000  -.031920  .000150  -.008630  .000070
+    1995.60   .273820  .000130   .237780  .000160  -.1136100  .0010000  -.034000  .000150  -.008830  .000070
+    1995.65   .237560  .000140   .179860  .000130  -.1418400  .0010000  -.035010  .000150  -.008040  .000070
+    1995.70   .189520  .000140   .133990  .000170  -.1803800  .0010000  -.036390  .000150  -.008250  .000070
+    1995.75   .135580  .000130   .105900  .000180  -.2213600  .0010000  -.035770  .000150  -.008060  .000070
+    1995.80   .066650  .000130   .085830  .000130  -.2632900  .0010000  -.033420  .000150  -.007150  .000070
+    1995.85   .002730  .000130   .084730  .000160  -.3084000  .0010000  -.032240  .000150  -.006220  .000070
+    1995.90  -.067070  .000140   .101140  .000160  -.3533700  .0010000  -.029910  .000150  -.005870  .000070
+    1995.95  -.138200  .000140   .136100  .000150  -.3981800  .0010000  -.029210  .000150  -.005260  .000070
+    1996.00  -.176160  .000140   .192180  .000160   .5551900  .0010000  -.029560  .000150  -.004540  .000070
+    1996.05  -.203930  .000140   .246410  .000130   .5221600  .0010000  -.028890  .000150  -.005090  .000070
+    1996.10  -.223380  .000140   .312950  .000130   .4899200  .0010000  -.028480  .000150  -.005710  .000070
+    1996.15  -.220960  .000130   .378460  .000210   .4499500  .0010000  -.030480  .000160  -.006550  .000070
+    1996.20  -.196520  .000130   .448570  .000150   .4092600  .0010000  -.029110  .000150  -.007690  .000070
+    1996.25  -.150870  .000130   .508690  .000130   .3699700  .0010000  -.028160  .000150  -.008330  .000070
+    1996.30  -.101690  .000140   .553340  .000160   .3258300  .0010000  -.028610  .000150  -.009150  .000070
+    1996.35  -.033850  .000170   .584490  .000150   .2846000  .0010000  -.029230  .000150  -.009690  .000070
+    1996.40   .040580  .000130   .595820  .000130   .2454400  .0010000  -.028510  .000160  -.009100  .000080
+    1996.45   .115360  .000170   .581210  .000130   .2114200  .0010000  -.032010  .000150  -.009350  .000070
+    1996.50   .181570  .000140   .545250  .000160   .1862900  .0010000  -.034130  .000150  -.008760  .000070
+    1996.55   .239170  .000170   .495410  .000130   .1659300  .0010000  -.036630  .000160  -.008420  .000070
+    1996.60   .267760  .000170   .436840  .000170   .1407800  .0010000  -.040480  .000150  -.008540  .000070
+    1996.65   .297160  .000240   .371810  .000140   .1230500  .0010000  -.041550  .000150  -.009250  .000070
+    1996.70   .290780  .000260   .296700  .000130   .0985300  .0010000  -.041950  .000150  -.008320  .000070
+    1996.75   .267110  .000130   .228290  .000130   .0638000  .0010000  -.042090  .000150  -.007370  .000070
+    1996.80   .227160  .000130   .171270  .000210   .0297800  .0010000  -.039090  .000150  -.007420  .000070
+    1996.85   .175940  .000140   .122030  .000150  -.0071800  .0010000  -.037160  .000150  -.007010  .000070
+    1996.90   .109730  .000140   .096200  .000170  -.0441600  .0010000  -.036960  .000150  -.005310  .000070
+    1996.95   .039500  .000140   .084250  .000160  -.0749400  .0010000  -.034810  .000150  -.005410  .000070
+    1997.00  -.020320  .000090   .095060  .000100  -.1096500  .0010000  -.034140  .000260  -.004920  .000100
+    1997.05  -.073030  .000100   .119750  .000090  -.1459800  .0010000  -.035390  .000290  -.004340  .000100
+    1997.10  -.124420  .000100   .156650  .000100  -.1730900  .0010000  -.035760  .000100  -.005370  .000100
+    1997.15  -.161820  .000090   .203960  .000100  -.2056400  .0010000  -.034520  .000260  -.006530  .000200
+    1997.20  -.186450  .000100   .263310  .000100  -.2482000  .0010000  -.035780  .000110  -.007860  .000200
+    1997.25  -.190710  .000100   .331710  .000090  -.2929300  .0010000  -.034320  .000100  -.008360  .000250
+    1997.30  -.174960  .000210   .396620  .000090  -.3387100  .0010000  -.033330  .000140  -.008810  .000200
+    1997.35  -.145010  .000100   .452930  .000100  -.3794300  .0010000  -.034730  .000310  -.009360  .000200
+    1997.40  -.098250  .000090   .498370  .000100  -.4162300  .0010000  -.036400  .000240  -.008940  .000250
+    1997.45  -.047990  .000090   .525350  .000090  -.4516000  .0010000  -.037960  .000130  -.008900  .000100
+    1997.50   .023090  .000090   .536790  .000100   .5261800  .0010000  -.041230  .000160  -.008490  .000200
+    1997.55   .088210  .000090   .526330  .000100   .5094900  .0010000  -.043740  .000130  -.007930  .000210
+    1997.60   .141170  .000100   .505000  .000100   .4812500  .0010000  -.045890  .000250  -.008370  .000090
+    1997.65   .181140  .000100   .467130  .000100   .4540400  .0010000  -.048080  .000130  -.008480  .000250
+    1997.70   .216860  .000100   .428130  .000100   .4276000  .0010000  -.047640  .000130  -.008290  .000090
+    1997.75   .221240  .000090   .378750  .000100   .3908700  .0010000  -.046790  .000110  -.007660  .000090
+    1997.80   .226280  .000100   .329150  .000100   .3513700  .0010000  -.047260  .000140  -.007180  .000140
+    1997.85   .214670  .000100   .278540  .000100   .3151900  .0010000  -.043960  .000230  -.006110  .000250
+    1997.90   .190380  .000100   .234080  .000100   .2784700  .0010000  -.041880  .000120  -.005170  .000100
+    1997.95   .151700  .000100   .201890  .000090   .2466500  .0010000  -.042270  .000270  -.004300  .000090
+    1998.00   .103371  .000034   .174919  .000027   .2187928  .0000860  -.040796  .000037  -.004526  .000010
+    1998.05   .051655  .000022   .167526  .000019   .1878736  .0000890  -.041014  .000035  -.004475  .000012
+    1998.10  -.005228  .000016   .173571  .000018   .1500342  .0000730  -.041089  .000022  -.005161  .000008
+    1998.15  -.051800  .000023   .188169  .000023   .1146000  .0001160  -.041022  .000032  -.005626  .000010
+    1998.20  -.079308  .000030   .220212  .000019   .0745974  .0000880  -.040480  .000039  -.006825  .000012
+    1998.25  -.110294  .000014   .254246  .000016   .0360847  .0001770  -.040068  .000027  -.007821  .000008
+    1998.30  -.113475  .000016   .301652  .000019   .0024942  .0001720  -.038470  .000023  -.008066  .000007
+    1998.35  -.114391  .000017   .344204  .000018  -.0345923  .0000870  -.039421  .000031  -.008546  .000010
+    1998.40  -.107406  .000018   .383854  .000019  -.0684825  .0000940  -.041256  .000027  -.008334  .000010
+    1998.45  -.099535  .000028   .414513  .000017  -.0887736  .0000800  -.041621  .000026  -.008251  .000008
+    1998.50  -.065007  .000030   .440850  .000025  -.1011400  .0000880  -.045405  .000032  -.008110  .000011
+    1998.55  -.021674  .000015   .465308  .000016  -.1082697  .0000780  -.048663  .000024  -.008757  .000008
+    1998.60   .017316  .000019   .478858  .000027  -.1146002  .0002360  -.050511  .000039  -.007435  .000011
+    1998.65   .058055  .000016   .476585  .000023  -.1250252  .0002150  -.052327  .000030  -.007918  .000009
+    1998.70   .097135  .000027   .465706  .000028  -.1418293  .0001130  -.053894  .000040  -.008104  .000011
+    1998.75   .125857  .000018   .444588  .000019  -.1587117  .0001640  -.051842  .000022  -.007051  .000007
+    1998.80   .149956  .000021   .418823  .000019  -.1862362  .0000880  -.050192  .000031  -.006161  .000011
+    1998.85   .163218  .000021   .388340  .000021  -.2147711  .0000750  -.049319  .000030  -.006025  .000010
+    1998.90   .154524  .000028   .350655  .000017  -.2401730  .0000940  -.047797  .000031  -.004755  .000011
+    1998.95   .137225  .000021   .321181  .000020  -.2653190  .0001500  -.047813  .000021  -.003519  .000007
+    1999.00   .138906  .000031   .296108  .000029   .7168562  .0000292  -.047632  .000102  -.004189  .000043
+    1999.05   .117532  .000023   .271385  .000020   .7014530  .0000153  -.046335  .000048  -.003666  .000020
+    1999.10   .100290  .000021   .252373  .000021   .6791687  .0000143  -.046361  .000049  -.004161  .000020
+    1999.15   .077098  .000025   .244566  .000019   .6561574  .0000165  -.046789  .000052  -.005200  .000021
+    1999.20   .054921  .000027   .239895  .000025   .6399826  .0000120  -.045030  .000034  -.006293  .000016
+    1999.25   .023809  .000025   .240618  .000020   .6145151  .0000125  -.044196  .000045  -.007261  .000018
+    1999.30   .001100  .000019   .248865  .000019   .5879676  .0000131  -.044112  .000036  -.007830  .000016
+    1999.35  -.017471  .000018   .262305  .000019   .5664931  .0000136  -.044623  .000039  -.008106  .000016
+    1999.40  -.023004  .000021   .281431  .000020   .5435885  .0000194  -.045556  .000056  -.007660  .000023
+    1999.45  -.031745  .000021   .296763  .000020   .5267825  .0000126  -.048393  .000040  -.007395  .000016
+    1999.50  -.031910  .000022   .311187  .000022   .5198637  .0000156  -.048944  .000060  -.007195  .000024
+    1999.55  -.024948  .000020   .330418  .000018   .5120479  .0000152  -.053295  .000049  -.007043  .000020
+    1999.60  -.014139  .000024   .345615  .000018   .5055648  .0000141  -.056278  .000043  -.007418  .000019
+    1999.65  -.008467  .000024   .361644  .000020   .4977768  .0000187  -.056558  .000058  -.008033  .000024
+    1999.70   .002079  .000023   .370914  .000021   .4819857  .0000165  -.056409  .000052  -.007053  .000020
+    1999.75   .006586  .000021   .379679  .000020   .4688203  .0000177  -.056851  .000056  -.006375  .000024
+    1999.80   .015741  .000023   .382597  .000021   .4506114  .0000177  -.054003  .000055  -.005858  .000024
+    1999.85   .024443  .000019   .379545  .000021   .4230946  .0000175  -.053148  .000040  -.004652  .000016
+    1999.90   .032087  .000018   .377378  .000022   .3974911  .0000145  -.051094  .000053  -.003961  .000022
+    1999.95   .037562  .000014   .380865  .000016   .3782104  .0000090  -.051070  .000033  -.003416  .000014
+    2000.00   .043300  .000014   .377661  .000021   .3554817  .0000572  -.050733  .000113  -.002289  .000040
+    2000.05   .052375  .000013   .375702  .000010   .3413574  .0000176  -.051501  .000042  -.002836  .000017
+    2000.10   .060632  .000009   .372427  .000010   .3250578  .0000117  -.050521  .000020  -.003334  .000008
+    2000.15   .067994  .000010   .365396  .000012   .3071171  .0000317  -.049754  .000059  -.004597  .000022
+    2000.20   .074610  .000010   .357979  .000010   .2899885  .0000127  -.049540  .000021  -.005112  .000008
+    2000.25   .075437  .000013   .346051  .000011   .2762541  .0000417  -.047537  .000065  -.005662  .000025
+    2000.30   .082353  .000009   .343278  .000012   .2552646  .0000219  -.047555  .000041  -.006187  .000015
+    2000.35   .088049  .000010   .332016  .000011   .2358447  .0000313  -.047653  .000056  -.006571  .000025
+    2000.40   .096303  .000010   .321406  .000009   .2198842  .0000179  -.048984  .000028  -.007124  .000011
+    2000.45   .113565  .000010   .304386  .000010   .2064913  .0000369  -.051715  .000058  -.006255  .000026
+    2000.50   .110079  .000010   .279086  .000010   .2040804  .0000193  -.054816  .000029  -.006360  .000013
+    2000.55   .096137  .000010   .261702  .000009   .2004203  .0000221  -.056391  .000040  -.006197  .000016
+    2000.60   .083088  .000009   .248498  .000010   .1987985  .0000409  -.058853  .000067  -.005982  .000024
+    2000.65   .058388  .000010   .242745  .000009   .1949233  .0000220  -.061330  .000046  -.006232  .000017
+    2000.70   .025972  .000011   .239588  .000009   .1871360  .0000185  -.059727  .000043  -.005855  .000016
+    2000.75  -.005722  .000011   .246917  .000009   .1747298  .0000378  -.060691  .000064  -.005000  .000026
+    2000.80  -.036045  .000011   .262831  .000008   .1600032  .0000134  -.057246  .000025  -.004209  .000010
+    2000.85  -.059965  .000009   .292223  .000009   .1391654  .0000181  -.055712  .000047  -.003613  .000017
+    2000.90  -.076915  .000010   .325404  .000010   .1205337  .0000302  -.054880  .000062  -.002841  .000022
+    2000.95  -.082660  .000008   .357017  .000009   .1045817  .0000131  -.053226  .000023  -.001982  .000008
+    2001.00  -.074006  .000010   .396764  .000009   .0936988  .0000299  -.051517  .000057  -.002267  .000022
+    2001.05  -.060835  .000011   .427064  .000009   .0806986  .0000145  -.051206  .000034  -.001604  .000013
+    2001.10  -.032401  .000008   .451341  .000009   .0762852  .0000112  -.054284  .000022  -.002328  .000008
+    2001.15   .004327  .000010   .475921  .000009   .0624390  .0000224  -.051152  .000049  -.002799  .000019
+    2001.20   .044840  .000008   .486196  .000008   .0388944  .0000105  -.050633  .000020  -.004153  .000008
+    2001.25   .091974  .000010   .489418  .000009   .0251539  .0000108  -.050009  .000020  -.005388  .000008
+    2001.30   .139116  .000011   .477702  .000011   .0096675  .0000143  -.049561  .000031  -.005489  .000013
+    2001.35   .178791  .000009   .452008  .000009  -.0088652  .0000125  -.051474  .000024  -.005586  .000009
+    2001.40   .215170  .000008   .409242  .000008  -.0228961  .0000160  -.051036  .000033  -.006224  .000014
+    2001.45   .242795  .000009   .359595  .000010  -.0245445  .0000168  -.053049  .000033  -.006319  .000013
+    2001.50   .254005  .000008   .304725  .000011  -.0278187  .0000118  -.055182  .000022  -.005536  .000008
+    2001.55   .247620  .000008   .249184  .000008  -.0254430  .0000161  -.059426  .000037  -.005789  .000014
+    2001.60   .220968  .000009   .199893  .000010  -.0206066  .0000143  -.060879  .000033  -.005547  .000012
+    2001.65   .175053  .000010   .158811  .000008  -.0281492  .0000148  -.062667  .000033  -.005926  .000013
+    2001.70   .125932  .000009   .132198  .000009  -.0304154  .0000126  -.062257  .000030  -.005599  .000012
+    2001.75   .064697  .000008   .117778  .000010  -.0383976  .0000155  -.060742  .000033  -.004371  .000013
+    2001.80   .001422  .000009   .120744  .000009  -.0558549  .0000201  -.059793  .000035  -.003611  .000015
+    2001.85  -.061030  .000010   .140506  .000009  -.0697006  .0000124  -.057258  .000022  -.002969  .000009
+    2001.90  -.103646  .000009   .180496  .000011  -.0868556  .0000215  -.055186  .000049  -.001724  .000020
+    2001.95  -.153361  .000010   .228492  .000010  -.1008918  .0000126  -.055469  .000028  -.001427  .000010
+    2002.00  -.176817  .000008   .292216  .000010  -.1154380  .0000264  -.053319  .000053  -.000648  .000022
+    2002.05  -.178852  .000009   .348438  .000008  -.1269166  .0000109  -.053365  .000021  -.001380  .000010
+    2002.10  -.163183  .000009   .406360  .000008  -.1417309  .0000151  -.053999  .000037  -.001540  .000014
+    2002.15  -.135832  .000008   .461499  .000008  -.1552923  .0000115  -.053015  .000033  -.003430  .000013
+    2002.20  -.088799  .000009   .513379  .000008  -.1739301  .0000084  -.051685  .000019  -.003023  .000007
+    2002.25  -.027634  .000009   .540974  .000007  -.1901581  .0000111  -.049814  .000027  -.004247  .000011
+    2002.30   .029239  .000008   .554816  .000008  -.2007113  .0000127  -.050367  .000032  -.005206  .000014
+    2002.35   .092521  .000009   .550437  .000008  -.2137458  .0000109  -.050343  .000020  -.004880  .000008
+    2002.40   .142157  .000008   .534179  .000008  -.2303514  .0000141  -.052550  .000037  -.004780  .000014
+    2002.45   .192923  .000007   .504114  .000008  -.2287794  .0000185  -.054054  .000036  -.005547  .000015
+    2002.50   .228889  .000009   .458092  .000008  -.2296246  .0000129  -.056387  .000033  -.005342  .000013
+    2002.55   .244514  .000007   .404459  .000007  -.2327614  .0000150  -.059477  .000026  -.005044  .000012
+    2002.60   .257521  .000010   .348296  .000008  -.2240428  .0000160  -.061751  .000039  -.005617  .000015
+    2002.65   .254939  .000008   .295393  .000008  -.2248033  .0000158  -.062523  .000045  -.004834  .000018
+    2002.70   .235509  .000007   .242129  .000007  -.2303263  .0000137  -.063071  .000027  -.004894  .000011
+    2002.75   .197659  .000007   .199413  .000007  -.2327877  .0000115  -.061560  .000022  -.004292  .000009
+    2002.80   .151551  .000010   .165804  .000007  -.2429725  .0000068  -.059948  .000013  -.003171  .000006
+    2002.85   .084865  .000008   .146837  .000008  -.2549716  .0000092  -.058425  .000020  -.002538  .000008
+    2002.90   .022450  .000008   .142124  .000009  -.2612171  .0000117  -.056420  .000026  -.002110  .000011
+    2002.95  -.038228  .000007   .154264  .000009  -.2767537  .0000111  -.055849  .000022  -.000854  .000010
+    2003.00  -.087743  .000008   .187387  .000009  -.2892390  .0000166  -.057149  .000032  -.000539  .000013
+    2003.05  -.127578  .000009   .228891  .000008  -.2995032  .0000119  -.054522  .000029  -.001356  .000012
+    2003.10  -.147530  .000007   .278647  .000008  -.3078795  .0000102  -.053909  .000022  -.001160  .000008
+    2003.15  -.154775  .000007   .332102  .000008  -.3201905  .0000109  -.053952  .000027  -.001913  .000010
+    2003.20  -.157108  .000008   .383491  .000008  -.3285379  .0000101  -.052108  .000022  -.003382  .000008
+    2003.25  -.131007  .000009   .438825  .000008  -.3439523  .0000120  -.051249  .000026  -.003305  .000010
+    2003.30  -.094644  .000008   .486399  .000008  -.3588043  .0000091  -.050741  .000021  -.004457  .000009
+    2003.35  -.043183  .000007   .522695  .000008  -.3638535  .0000108  -.050307  .000021  -.005323  .000009
+    2003.40   .001931  .000007   .541957  .000008  -.3745652  .0000102  -.051708  .000023  -.004153  .000009
+    2003.45   .062632  .000007   .546600  .000008  -.3752839  .0000160  -.054049  .000027  -.004697  .000012
+    2003.50   .135203  .000007   .538240  .000007  -.3661265  .0000115  -.056222  .000022  -.005013  .000009
+    2003.55   .191134  .000008   .509318  .000008  -.3577046  .0000128  -.060297  .000028  -.004614  .000012
+    2003.60   .232086  .000007   .463954  .000008  -.3537978  .0000190  -.062184  .000036  -.004744  .000015
+    2003.65   .259508  .000007   .415127  .000007  -.3494880  .0000129  -.062965  .000029  -.005055  .000011
+    2003.70   .264299  .000008   .356543  .000008  -.3529986  .0000103  -.063232  .000023  -.003950  .000009
+    2003.75   .257771  .000008   .302232  .000008  -.3575570  .0000116  -.062983  .000024  -.004229  .000010
+    2003.80   .226130  .000007   .250158  .000008  -.3628298  .0000113  -.059567  .000025  -.003622  .000011
+    2003.85   .195950  .000007   .207643  .000011  -.3728456  .0000145  -.058843  .000028  -.002215  .000013
+    2003.90   .147593  .000007   .174905  .000010  -.3807556  .0000134  -.057362  .000026  -.001897  .000011
+    2003.95   .087282  .000007   .158884  .000008  -.3820300  .0000099  -.054770  .000019  -.001608  .000008
+    2004.00   .031246  .000007   .153785  .000007  -.3896036  .0000155  -.056035  .000032  -.000255  .000014
+    2004.05  -.014033  .000009   .166554  .000010  -.3994989  .0000112  -.055954  .000030  -.000864  .000012
+    2004.10  -.057805  .000007   .191331  .000008  -.4041551  .0000156  -.054298  .000036  -.001804  .000014
+    2004.15  -.101004  .000007   .228144  .000008  -.4153922  .0000097  -.054532  .000024  -.002010  .000009
+    2004.20  -.126021  .000007   .268583  .000008  -.4225892  .0000165  -.053954  .000034  -.003026  .000014
+    2004.25  -.140343  .000008   .321451  .000008  -.4338646  .0000126  -.051273  .000029  -.004478  .000012
+    2004.30  -.132911  .000007   .375713  .000007  -.4512439  .0000137  -.051136  .000030  -.003701  .000012
+    2004.35  -.112725  .000007   .423506  .000008  -.4596331  .0000144  -.052649  .000025  -.005159  .000011
+    2004.40  -.090722  .000008   .458455  .000008  -.4683249  .0000165  -.051299  .000033  -.005609  .000015
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/finals2000A.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/finals2000A.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/finals2000A.dat	(revision 22158)
@@ -0,0 +1,5525 @@
+#
+#  Stripped version of finals.all.orig file
+#
+#
+#            Bull A      Bull A      Bull B     Bull B
+#  MJD         dX          dY          dX         dY
+#
+48622.00     -0.086      0.130       0.129      -0.653
+48623.00     -0.027      0.128       0.155      -0.575
+48624.00      0.014      0.154       0.135      -0.478
+48625.00      0.032      0.205      -0.006      -0.229
+48626.00      0.026      0.265      -0.100      -0.226
+48627.00      0.009      0.301      -0.174      -0.453
+48628.00      0.002      0.282      -0.229      -0.657
+48629.00      0.013      0.222      -0.255      -0.711
+48630.00      0.042      0.241      -0.169      -0.647
+48631.00      0.096      0.314      -0.108      -0.587
+48632.00      0.172      0.312      -0.087      -0.561
+48633.00      0.248      0.225      -0.085      -0.485
+48634.00      0.294      0.133      -0.041      -0.340
+48635.00      0.282      0.125       0.027      -0.178
+48636.00      0.201      0.193       0.135      -0.334
+48637.00      0.091      0.177       0.210      -0.566
+48638.00     -0.002      0.116       0.225      -0.558
+48639.00     -0.075      0.095       0.124      -0.240
+48640.00     -0.142      0.075      -0.096      -0.028
+48641.00     -0.187      0.023      -0.332      -0.004
+48642.00     -0.182      0.014      -0.452      -0.247
+48643.00     -0.127      0.101      -0.444      -0.380
+48644.00     -0.090      0.182      -0.430      -0.393
+48645.00     -0.089      0.204      -0.392      -0.499
+48646.00     -0.096      0.201      -0.276      -0.639
+48647.00     -0.101      0.215      -0.089      -0.809
+48648.00     -0.089      0.246       0.002      -0.771
+48649.00     -0.029      0.281       0.048      -0.529
+48650.00      0.094      0.213       0.125      -0.451
+48651.00      0.274      0.092       0.244      -0.365
+48652.00      0.452      0.034       0.295      -0.396
+48653.00      0.551      0.048       0.267      -0.337
+48654.00      0.558      0.123       0.095      -0.483
+48655.00      0.493      0.206       0.024      -0.568
+48656.00      0.380      0.224       0.013      -0.764
+48657.00      0.247      0.140       0.049      -0.895
+48658.00      0.136      0.013       0.139      -0.735
+48659.00      0.054     -0.093       0.135      -0.529
+48660.00     -0.012     -0.156       0.110      -0.514
+48661.00     -0.043     -0.177       0.017      -0.491
+48662.00     -0.041     -0.129      -0.012      -0.493
+48663.00     -0.033      0.037      -0.001      -0.519
+48664.00     -0.029      0.271       0.136      -0.603
+48665.00      0.006      0.334       0.277      -0.552
+48666.00      0.054      0.241       0.377      -0.365
+48667.00      0.048      0.146       0.365      -0.019
+48668.00     -0.043      0.126       0.120       0.377
+48669.00     -0.184      0.123      -0.180       0.293
+48670.00     -0.286      0.085      -0.424      -0.020
+48671.00     -0.290      0.044      -0.519      -0.409
+48672.00     -0.218      0.028      -0.579      -0.468
+48673.00     -0.105      0.066      -0.537      -0.493
+48674.00      0.022      0.183      -0.434      -0.410
+48675.00      0.105      0.208      -0.344      -0.380
+48676.00      0.121      0.083      -0.311      -0.137
+48677.00      0.083     -0.085      -0.376       0.046
+48678.00      0.014     -0.158      -0.340       0.141
+48679.00     -0.019     -0.039      -0.216       0.233
+48680.00     -0.016      0.141      -0.069       0.202
+48681.00      0.005      0.199      -0.032       0.174
+48682.00      0.033      0.152      -0.086       0.171
+48683.00      0.054      0.085      -0.146      -0.062
+48684.00      0.062      0.033      -0.165      -0.333
+48685.00      0.060      0.014       0.053      -0.473
+48686.00      0.059      0.018       0.064      -0.417
+48687.00      0.062      0.046       0.107      -0.279
+48688.00      0.077      0.090       0.165      -0.222
+48689.00      0.142      0.193       0.170      -0.303
+48690.00      0.242      0.308       0.170      -0.455
+48691.00      0.324      0.321       0.168      -0.584
+48692.00      0.335      0.119       0.226      -0.637
+48693.00      0.273     -0.024       0.349      -0.568
+48694.00      0.153     -0.059       0.384      -0.333
+48695.00      0.059     -0.066       0.315       0.004
+48696.00      0.041     -0.024       0.149       0.212
+48697.00      0.044      0.015      -0.003       0.155
+48698.00     -0.010     -0.035      -0.099      -0.330
+48699.00     -0.133     -0.172      -0.120      -0.836
+48700.00     -0.214     -0.252      -0.054      -0.980
+48701.00     -0.202     -0.200      -0.005      -0.942
+48702.00     -0.122     -0.035       0.088      -0.784
+48703.00     -0.033      0.064       0.180      -0.542
+48704.00      0.047      0.038       0.159      -0.467
+48705.00      0.129     -0.009       0.117      -0.366
+48706.00      0.206      0.010       0.109      -0.324
+48707.00      0.246      0.077       0.220      -0.282
+48708.00      0.230      0.118       0.263      -0.190
+48709.00      0.152      0.091       0.145      -0.078
+48710.00      0.029      0.035      -0.022      -0.038
+48711.00     -0.110     -0.000      -0.208      -0.220
+48712.00     -0.220     -0.019      -0.315      -0.354
+48713.00     -0.244     -0.047      -0.368      -0.509
+48714.00     -0.133     -0.097      -0.407      -0.531
+48715.00      0.013     -0.101      -0.315      -0.592
+48716.00      0.047      0.007      -0.238      -0.598
+48717.00     -0.017      0.171      -0.114      -0.679
+48718.00     -0.097      0.309      -0.048      -0.777
+48719.00     -0.110      0.350      -0.041      -0.822
+48720.00     -0.034      0.283      -0.037      -0.683
+48721.00      0.057      0.105      -0.077      -0.564
+48722.00      0.123     -0.034      -0.147      -0.285
+48723.00      0.146     -0.230      -0.263      -0.003
+48724.00      0.130     -0.469      -0.403       0.259
+48725.00      0.090     -0.633      -0.479       0.178
+48726.00      0.030     -0.584      -0.533      -0.037
+48727.00     -0.050     -0.286      -0.488      -0.292
+48728.00     -0.110     -0.004      -0.421      -0.457
+48729.00     -0.160      0.155      -0.374      -0.241
+48730.00     -0.209      0.204      -0.333       0.039
+48731.00     -0.252      0.184      -0.344       0.179
+48732.00     -0.288      0.137      -0.379       0.240
+48733.00     -0.322      0.103      -0.381       0.038
+48734.00     -0.333      0.048      -0.312      -0.191
+48735.00     -0.309     -0.051      -0.199      -0.304
+48736.00     -0.257     -0.152      -0.088      -0.368
+48737.00     -0.183     -0.226      -0.117      -0.285
+48738.00     -0.115     -0.253      -0.213      -0.294
+48739.00     -0.082     -0.241      -0.278      -0.435
+48740.00     -0.096     -0.242      -0.244      -0.623
+48741.00     -0.126     -0.285      -0.164      -0.654
+48742.00     -0.085     -0.283      -0.061      -0.723
+48743.00      0.011     -0.203       0.025      -0.710
+48744.00      0.095     -0.081       0.097      -0.861
+48745.00      0.149      0.020       0.088      -1.011
+48746.00      0.170      0.049       0.100      -0.963
+48747.00      0.147     -0.038       0.101      -0.909
+48748.00      0.090     -0.217       0.004      -0.738
+48749.00      0.060     -0.290      -0.072      -0.539
+48750.00      0.070     -0.238      -0.121      -0.510
+48751.00      0.117     -0.155      -0.130      -0.391
+48752.00      0.193     -0.081      -0.131      -0.368
+48753.00      0.288     -0.025      -0.150      -0.306
+48754.00      0.391      0.022      -0.132      -0.360
+48755.00      0.446      0.075      -0.073      -0.588
+48756.00      0.400      0.169      -0.000      -0.751
+48757.00      0.305      0.192       0.123      -0.629
+48758.00      0.194     -0.009       0.153      -0.437
+48759.00      0.096     -0.279       0.073      -0.229
+48760.00      0.071     -0.331       0.013      -0.172
+48761.00      0.126     -0.188      -0.083      -0.403
+48762.00      0.202     -0.053      -0.122      -0.587
+48763.00      0.211      0.035      -0.179      -0.646
+48764.00      0.094      0.060      -0.258      -0.522
+48765.00     -0.011      0.059      -0.344      -0.327
+48766.00     -0.049      0.063      -0.466      -0.227
+48767.00     -0.058      0.060      -0.621      -0.268
+48768.00     -0.094      0.038      -0.626      -0.342
+48769.00     -0.175     -0.028      -0.565      -0.335
+48770.00     -0.238     -0.113      -0.395      -0.280
+48771.00     -0.220     -0.160      -0.239      -0.319
+48772.00     -0.147     -0.062      -0.106      -0.402
+48773.00     -0.078      0.063      -0.029      -0.583
+48774.00     -0.052      0.041      -0.153      -0.870
+48775.00     -0.032     -0.033       0.099      -0.567
+48776.00      0.030     -0.108       0.164      -0.284
+48777.00      0.064     -0.239       0.182      -0.101
+48778.00      0.066     -0.311       0.243      -0.193
+48779.00      0.121     -0.316       0.339      -0.196
+48780.00      0.234     -0.257       0.403      -0.101
+48781.00      0.355     -0.143       0.342      -0.126
+48782.00      0.431      0.011       0.165      -0.146
+48783.00      0.437      0.193       0.009      -0.302
+48784.00      0.384      0.350      -0.130      -0.564
+48785.00      0.283      0.412      -0.128      -0.861
+48786.00      0.153      0.303      -0.052      -1.052
+48787.00      0.030     -0.034       0.078      -1.081
+48788.00     -0.059     -0.391       0.196      -1.166
+48789.00     -0.154     -0.524       0.309      -1.198
+48790.00     -0.225     -0.527       0.401      -1.250
+48791.00     -0.159     -0.485       0.469      -1.182
+48792.00     -0.040     -0.472       0.439      -0.975
+48793.00     -0.039     -0.507       0.391      -0.557
+48794.00     -0.099     -0.201       0.218      -0.270
+48795.00     -0.049      0.089      -0.032      -0.095
+48796.00      0.068      0.075      -0.323      -0.051
+48797.00      0.090     -0.023      -0.523      -0.008
+48798.00      0.047     -0.150      -0.597       0.015
+48799.00     -0.008     -0.228      -0.511      -0.162
+48800.00     -0.030     -0.199      -0.386      -0.448
+48801.00     -0.023     -0.104      -0.226      -0.892
+48802.00     -0.018     -0.010      -0.166      -1.033
+48803.00     -0.050      0.034      -0.180      -0.933
+48804.00     -0.126     -0.029      -0.154      -0.844
+48805.00     -0.192     -0.219      -0.128      -0.992
+48806.00     -0.204     -0.389      -0.221      -1.233
+48807.00     -0.167     -0.422      -0.227      -1.277
+48808.00     -0.113     -0.362      -0.209      -1.131
+48809.00     -0.067     -0.273      -0.241      -1.114
+48810.00     -0.058     -0.219      -0.344      -1.027
+48811.00     -0.090     -0.233      -0.456      -0.943
+48812.00     -0.094     -0.234      -0.528      -0.692
+48813.00     -0.099     -0.191      -0.562      -0.553
+48814.00     -0.108     -0.102      -0.419      -0.458
+48815.00     -0.106     -0.005      -0.185      -0.378
+48816.00     -0.093      0.068      -0.033      -0.303
+48817.00     -0.086      0.088       0.063      -0.300
+48818.00     -0.103      0.045      -0.036      -0.435
+48819.00     -0.129     -0.053      -0.172      -0.751
+48820.00     -0.136     -0.188      -0.340      -0.888
+48821.00     -0.099     -0.205      -0.441      -0.755
+48822.00     -0.051     -0.125      -0.601      -0.628
+48823.00     -0.013     -0.049      -0.862      -0.544
+48824.00      0.009     -0.066      -1.110      -0.520
+48825.00     -0.003     -0.147      -1.280      -0.453
+48826.00     -0.025     -0.144      -1.266      -0.304
+48827.00     -0.015     -0.095      -1.025      -0.297
+48828.00      0.042     -0.093      -0.706      -0.368
+48829.00      0.144     -0.141      -0.459      -0.637
+48830.00      0.237     -0.183      -0.370      -0.671
+48831.00      0.232     -0.207      -0.335      -0.512
+48832.00      0.149     -0.261      -0.300      -0.381
+48833.00      0.049     -0.309      -0.282      -0.274
+48834.00     -0.048     -0.297      -0.168      -0.403
+48835.00     -0.157     -0.217      -0.061      -0.372
+48836.00     -0.253     -0.172      -0.020      -0.274
+48837.00     -0.267     -0.169       0.007      -0.317
+48838.00     -0.194     -0.163       0.087      -0.348
+48839.00     -0.128     -0.168       0.000      -0.289
+48840.00     -0.103     -0.123      -0.162      -0.220
+48841.00     -0.106     -0.089      -0.394      -0.038
+48842.00     -0.115     -0.129      -0.391       0.071
+48843.00     -0.114     -0.150      -0.276      -0.076
+48844.00     -0.076     -0.142       0.023      -0.256
+48845.00     -0.018     -0.225       0.100      -0.233
+48846.00     -0.013     -0.365       0.027      -0.180
+48847.00     -0.034     -0.408      -0.142      -0.414
+48848.00     -0.104     -0.298      -0.304      -0.605
+48849.00     -0.200     -0.161      -0.471      -0.495
+48850.00     -0.291     -0.087      -0.599      -0.395
+48851.00     -0.350     -0.078      -0.728      -0.375
+48852.00     -0.340     -0.136      -0.901      -0.464
+48853.00     -0.259     -0.232      -0.975      -0.524
+48854.00     -0.178     -0.254      -0.798      -0.657
+48855.00     -0.146     -0.203      -0.420      -0.758
+48856.00     -0.174     -0.154       0.018      -0.810
+48857.00     -0.103     -0.178       0.300      -0.913
+48858.00      0.015     -0.290       0.421      -0.860
+48859.00      0.058     -0.394       0.365      -0.639
+48860.00      0.023     -0.380       0.222      -0.520
+48861.00     -0.066     -0.249       0.099      -0.622
+48862.00     -0.156     -0.109       0.058      -0.594
+48863.00     -0.192      0.113      -0.109      -0.612
+48864.00     -0.167      0.125      -0.355      -0.511
+48865.00     -0.157     -0.063      -0.549      -0.606
+48866.00     -0.156     -0.178      -0.600      -0.916
+48867.00     -0.118     -0.149      -0.493      -1.105
+48868.00     -0.070     -0.205      -0.479      -1.134
+48869.00     -0.003     -0.391      -0.587      -0.869
+48870.00      0.083     -0.513      -0.632      -0.860
+48871.00      0.143     -0.510      -0.378      -0.757
+48872.00      0.130     -0.459      -0.088      -0.719
+48873.00      0.020     -0.464       0.126      -0.537
+48874.00     -0.172     -0.538       0.118      -0.442
+48875.00     -0.339     -0.529       0.018      -0.587
+48876.00     -0.423     -0.431      -0.122      -0.611
+48877.00     -0.426     -0.359      -0.247      -0.688
+48878.00     -0.367     -0.319      -0.410      -0.596
+48879.00     -0.274     -0.270      -0.451      -0.478
+48880.00     -0.161     -0.187      -0.575      -0.590
+48881.00     -0.059     -0.075      -0.557      -0.938
+48882.00     -0.032      0.007      -0.468      -1.002
+48883.00     -0.062      0.020      -0.329      -1.083
+48884.00     -0.098     -0.010      -0.112      -1.082
+48885.00     -0.135     -0.067       0.102      -0.938
+48886.00     -0.168     -0.136       0.135      -0.776
+48887.00     -0.189     -0.183       0.063      -0.459
+48888.00     -0.192     -0.171       0.000      -0.417
+48889.00     -0.185     -0.048      -0.008      -0.497
+48890.00     -0.190      0.070       0.034      -0.625
+48891.00     -0.228      0.044      -0.020      -0.657
+48892.00     -0.280     -0.092      -0.208      -0.482
+48893.00     -0.320     -0.267      -0.383      -0.531
+48894.00     -0.328     -0.356      -0.399      -0.646
+48895.00     -0.315     -0.286      -0.252      -0.808
+48896.00     -0.296     -0.147      -0.116      -0.944
+48897.00     -0.265     -0.055      -0.101      -0.866
+48898.00     -0.220     -0.050      -0.091      -0.716
+48899.00     -0.189     -0.077      -0.003      -0.763
+48900.00     -0.194     -0.120      -0.005      -0.742
+48901.00     -0.242     -0.189      -0.013      -0.680
+48902.00     -0.328     -0.278      -0.200      -0.488
+48903.00     -0.428     -0.376      -0.407      -0.416
+48904.00     -0.508     -0.482      -0.653      -0.356
+48905.00     -0.534     -0.541      -0.833      -0.354
+48906.00     -0.501     -0.516      -0.877      -0.300
+48907.00     -0.425     -0.411      -0.857      -0.371
+48908.00     -0.311     -0.260      -0.749      -0.446
+48909.00     -0.178     -0.107      -0.529      -0.805
+48910.00     -0.092      0.018      -0.309      -1.044
+48911.00     -0.084      0.095      -0.062      -1.068
+48912.00     -0.145      0.100       0.066      -0.968
+48913.00     -0.234      0.055       0.207      -0.799
+48914.00     -0.298      0.005       0.260      -0.529
+48915.00     -0.284      0.004       0.226      -0.137
+48916.00     -0.149      0.044       0.154      -0.013
+48917.00      0.027      0.114       0.087       0.021
+48918.00      0.146      0.270      -0.002      -0.111
+48919.00      0.150      0.523      -0.091      -0.199
+48920.00      0.057      0.676      -0.240      -0.057
+48921.00     -0.075      0.650      -0.396      -0.008
+48922.00     -0.186      0.522      -0.417      -0.044
+48923.00     -0.245      0.369      -0.247      -0.230
+48924.00     -0.260      0.191      -0.056      -0.494
+48925.00     -0.222     -0.032       0.050      -0.740
+48926.00     -0.135     -0.247       0.140      -0.820
+48927.00     -0.060     -0.285       0.202      -0.925
+48928.00     -0.032     -0.196       0.223      -0.671
+48929.00     -0.057     -0.187       0.151      -0.592
+48930.00     -0.121     -0.324       0.308      -0.535
+48931.00     -0.175     -0.394       0.153      -0.520
+48932.00     -0.218     -0.322      -0.047      -0.632
+48933.00     -0.252     -0.259      -0.251      -0.659
+48934.00     -0.271     -0.252      -0.475      -0.830
+48935.00     -0.261     -0.219      -0.658      -0.987
+48936.00     -0.207     -0.103      -0.583      -1.116
+48937.00     -0.107      0.060      -0.403      -1.224
+48938.00     -0.003      0.070      -0.176      -1.115
+48939.00      0.084     -0.162      -0.072      -0.774
+48940.00      0.147     -0.622      -0.000      -0.469
+48941.00      0.119     -0.756      -0.016      -0.177
+48942.00     -0.002     -0.435      -0.012       0.071
+48943.00     -0.144     -0.085      -0.044       0.272
+48944.00     -0.260      0.008      -0.216       0.200
+48945.00     -0.351     -0.048      -0.460       0.020
+48946.00     -0.424     -0.125      -0.690      -0.342
+48947.00     -0.488     -0.111      -0.711      -0.662
+48948.00     -0.550     -0.003      -0.702      -0.916
+48949.00     -0.599      0.133      -0.646      -0.896
+48950.00     -0.618      0.244      -0.504      -1.034
+48951.00     -0.594      0.306      -0.306      -0.995
+48952.00     -0.540      0.322      -0.118      -1.141
+48953.00     -0.468      0.290       0.099      -1.294
+48954.00     -0.392      0.213       0.307      -1.394
+48955.00     -0.320      0.114       0.437      -1.132
+48956.00     -0.265      0.001       0.476      -0.725
+48957.00     -0.249     -0.131       0.448      -0.387
+48958.00     -0.253     -0.234       0.318      -0.221
+48959.00     -0.190     -0.187       0.184      -0.028
+48960.00     -0.137      0.010      -0.064      -0.041
+48961.00     -0.154      0.162      -0.292      -0.029
+48962.00     -0.213      0.211      -0.427      -0.259
+48963.00     -0.249      0.217      -0.502      -0.612
+48964.00     -0.216      0.216      -0.508      -0.847
+48965.00     -0.117      0.176      -0.490      -1.102
+48966.00     -0.034     -0.006      -0.434      -1.055
+48967.00     -0.007     -0.234      -0.393      -0.767
+48968.00     -0.047     -0.348      -0.375      -0.519
+48969.00     -0.128     -0.319      -0.352      -0.527
+48970.00     -0.210     -0.159      -0.239      -0.545
+48971.00     -0.254      0.138      -0.177      -0.659
+48972.00     -0.260      0.437      -0.116      -0.429
+48973.00     -0.227      0.790      -0.218      -0.508
+48974.00     -0.160      0.875      -0.306      -0.539
+48975.00     -0.074      0.629      -0.403      -0.686
+48976.00      0.003      0.291      -0.370      -0.752
+48977.00      0.025      0.057      -0.298      -0.585
+48978.00     -0.003     -0.047      -0.265      -0.537
+48979.00     -0.045     -0.061      -0.288      -0.440
+48980.00     -0.079     -0.055      -0.309      -0.402
+48981.00     -0.101     -0.061      -0.264      -0.513
+48982.00     -0.115     -0.081      -0.223      -0.546
+48983.00     -0.113     -0.105      -0.164      -0.553
+48984.00     -0.087     -0.123      -0.156      -0.292
+48985.00     -0.036     -0.139      -0.129      -0.060
+48986.00      0.043     -0.149      -0.013       0.013
+48987.00      0.158     -0.118       0.023       0.005
+48988.00      0.219     -0.049      -0.013      -0.087
+48989.00      0.187      0.020      -0.020      -0.087
+48990.00      0.099      0.063       0.035      -0.168
+48991.00     -0.001      0.074       0.064      -0.479
+48992.00     -0.071      0.042       0.150      -0.736
+48993.00     -0.088     -0.021       0.153      -0.941
+48994.00     -0.076     -0.025       0.100      -0.797
+48995.00     -0.067      0.036      -0.025      -0.476
+48996.00     -0.077      0.122      -0.193      -0.074
+48997.00     -0.102      0.188      -0.358       0.028
+48998.00     -0.140      0.214      -0.449      -0.046
+48999.00     -0.197      0.184      -0.488      -0.152
+49000.00     -0.269      0.073      -0.475      -0.205
+49001.00     -0.337     -0.078      -0.501      -0.289
+49002.00     -0.385     -0.193      -0.555      -0.371
+49003.00     -0.395     -0.182      -0.478      -0.532
+49004.00     -0.365     -0.069      -0.325      -0.641
+49005.00     -0.309      0.051      -0.115      -0.611
+49006.00     -0.254      0.084       0.053      -0.588
+49007.00     -0.213      0.006       0.059      -0.511
+49008.00     -0.181     -0.043       0.010      -0.414
+49009.00     -0.164     -0.018      -0.075      -0.319
+49010.00     -0.183      0.033      -0.173      -0.293
+49011.00     -0.229      0.093      -0.252      -0.335
+49012.00     -0.269      0.152      -0.346      -0.148
+49013.00     -0.274      0.189      -0.436      -0.034
+49014.00     -0.231      0.123      -0.496       0.002
+49015.00     -0.176     -0.063      -0.504      -0.018
+49016.00     -0.137     -0.094      -0.603      -0.145
+49017.00     -0.087     -0.059      -0.694      -0.279
+49018.00     -0.026     -0.064      -0.585      -0.250
+49019.00      0.024     -0.067      -0.443      -0.428
+49020.00      0.039     -0.036       5.621       2.700
+49021.00      0.022      0.029      -0.131      -0.926
+49022.00      0.048      0.096       0.004      -0.909
+49023.00      0.136      0.182       0.030      -0.459
+49024.00      0.145      0.191      -0.050      -0.119
+49025.00      0.081      0.138      -0.175       0.036
+49026.00     -0.005      0.065      -0.266      -0.247
+49027.00     -0.095      0.041      -0.197      -0.409
+49028.00     -0.183      0.060      -0.210      -0.510
+49029.00     -0.234      0.055      -0.273      -0.482
+49030.00     -0.224      0.054      -0.302      -0.532
+49031.00     -0.215      0.017      -0.384      -0.521
+49032.00     -0.227     -0.031      -0.406      -0.530
+49033.00     -0.241     -0.081      -0.377      -0.365
+49034.00     -0.253     -0.156      -0.309      -0.431
+49035.00     -0.251     -0.208      -0.160      -0.409
+49036.00     -0.212     -0.136      -0.150      -0.321
+49037.00     -0.165     -0.022      -0.173      -0.253
+49038.00     -0.159      0.049      -0.233      -0.148
+49039.00     -0.191      0.069      -0.288      -0.289
+49040.00     -0.227      0.066      -0.349      -0.357
+49041.00     -0.227      0.067      -0.405      -0.251
+49042.00     -0.172      0.098      -0.319      -0.220
+49043.00     -0.089      0.161      -0.300      -0.098
+49044.00     -0.019      0.245      -0.249      -0.241
+49045.00     -0.012      0.329      -0.308      -0.280
+49046.00     -0.064      0.394      -0.235      -0.168
+49047.00     -0.132      0.431      -0.102      -0.201
+49048.00     -0.175      0.413       0.048      -0.300
+49049.00     -0.172      0.319       0.101      -0.396
+49050.00     -0.155      0.237       0.240      -0.554
+49051.00     -0.163      0.243       0.096      -0.201
+49052.00     -0.197      0.214      -0.135      -0.004
+49053.00     -0.235      0.082      -0.424       0.043
+49054.00     -0.241     -0.084      -0.467      -0.358
+49055.00     -0.211     -0.144      -0.487      -0.619
+49056.00     -0.186     -0.039      -0.479      -0.552
+49057.00     -0.204      0.104      -0.485      -0.420
+49058.00     -0.231      0.211      -0.457      -0.306
+49059.00     -0.224      0.273      -0.416      -0.184
+49060.00     -0.179      0.289      -0.391      -0.188
+49061.00     -0.102      0.254      -0.282      -0.112
+49062.00     -0.007      0.163      -0.149       0.008
+49063.00      0.073      0.064       0.110      -0.113
+49064.00      0.100      0.076       0.232      -0.155
+49065.00      0.069      0.117       0.201      -0.168
+49066.00      0.016      0.152       0.060      -0.024
+49067.00     -0.045      0.202      -0.114      -0.160
+49068.00     -0.106      0.268      -0.171      -0.271
+49069.00     -0.150      0.349      -0.235      -0.302
+49070.00     -0.176      0.396      -0.351      -0.137
+49071.00     -0.213      0.257      -0.367      -0.030
+49072.00     -0.252      0.154      -0.464      -0.027
+49073.00     -0.254      0.120      -0.535      -0.226
+49074.00     -0.222      0.110      -0.475      -0.331
+49075.00     -0.172      0.123      -0.334      -0.416
+49076.00     -0.120      0.148      -0.086      -0.340
+49077.00     -0.082      0.147       0.067      -0.425
+49078.00     -0.064      0.111       0.133      -0.282
+49079.00     -0.060      0.069       0.065       0.032
+49080.00     -0.070      0.046       0.196       0.176
+49081.00     -0.087      0.024      -0.012       0.074
+49082.00     -0.092     -0.005      -0.209      -0.190
+49083.00     -0.069     -0.003      -0.230      -0.398
+49084.00     -0.036      0.058      -0.274      -0.277
+49085.00     -0.021      0.131      -0.290      -0.193
+49086.00     -0.033      0.156      -0.297      -0.191
+49087.00     -0.052      0.132      -0.341      -0.203
+49088.00     -0.056      0.096      -0.357      -0.222
+49089.00     -0.033      0.094      -0.358      -0.318
+49090.00      0.016      0.174      -0.191      -0.349
+49091.00      0.081      0.310       0.017      -0.328
+49092.00      0.146      0.341       0.181      -0.298
+49093.00      0.171      0.172       0.123      -0.253
+49094.00      0.176      0.015      -0.031      -0.167
+49095.00      0.156     -0.040      -0.159      -0.287
+49096.00      0.101     -0.054      -0.201      -0.425
+49097.00      0.019     -0.099      -0.183      -0.524
+49098.00     -0.053     -0.135      -0.102      -0.532
+49099.00     -0.020     -0.012      -0.050      -0.466
+49100.00      0.042      0.018       0.030      -0.383
+49101.00      0.028      0.031       0.064      -0.628
+49102.00     -0.075      0.082       0.126      -0.821
+49103.00     -0.226      0.117       0.188      -0.780
+49104.00     -0.373      0.082       0.339      -0.797
+49105.00     -0.443     -0.023       0.401      -0.612
+49106.00     -0.338     -0.040       0.308      -0.549
+49107.00     -0.141      0.017       0.108      -0.336
+49108.00      0.033      0.109      -0.155      -0.346
+49109.00      0.150      0.204      -0.357      -0.427
+49110.00      0.206      0.268      -0.485      -0.776
+49111.00      0.197      0.265      -0.567      -0.858
+49112.00      0.122      0.161      -0.653      -0.748
+49113.00     -0.018      0.006      -0.696      -0.580
+49114.00     -0.192     -0.068      -0.719      -0.503
+49115.00     -0.306     -0.128      -0.670      -0.525
+49116.00     -0.320     -0.227      -0.618      -0.757
+49117.00     -0.258     -0.310      -0.499      -0.756
+49118.00     -0.154     -0.316      -0.259      -0.742
+49119.00     -0.046     -0.212       0.056      -0.510
+49120.00      0.044     -0.015       0.315      -0.112
+49121.00      0.119      0.186       0.397       0.055
+49122.00      0.157      0.317       0.252       0.194
+49123.00      0.146      0.366       0.062       0.087
+49124.00      0.117      0.320      -0.038      -0.171
+49125.00      0.115      0.148      -0.116      -0.347
+49126.00      0.160     -0.123      -0.180      -0.493
+49127.00      0.205     -0.267      -0.211      -0.473
+49128.00      0.220     -0.229      -0.229      -0.579
+49129.00      0.201     -0.099      -0.241      -0.735
+49130.00      0.145      0.049      -0.236      -0.710
+49131.00      0.081      0.161      -0.197      -0.680
+49132.00      0.057      0.170      -0.103      -0.563
+49133.00      0.112      0.021       0.018      -0.382
+49134.00      0.190     -0.201       0.153      -0.337
+49135.00      0.251     -0.384       0.166      -0.124
+49136.00      0.297     -0.504       0.062      -0.070
+49137.00      0.330     -0.570      -0.103      -0.206
+49138.00      0.343     -0.569      -0.200      -0.378
+49139.00      0.325     -0.477      -0.191      -0.649
+49140.00      0.268     -0.305      -0.129      -0.609
+49141.00      0.175     -0.093      -0.068      -0.408
+49142.00      0.076      0.088      -0.083      -0.424
+49143.00     -0.002      0.185      -0.059      -0.513
+49144.00     -0.049      0.204      -0.082      -0.576
+49145.00     -0.057      0.153      -0.118      -0.765
+49146.00     -0.018      0.050      -0.019      -0.809
+49147.00      0.069     -0.087       0.097      -0.545
+49148.00      0.143     -0.204       0.156      -0.160
+49149.00      0.187     -0.278       0.120       0.075
+49150.00      0.207     -0.283      -0.055       0.132
+49151.00      0.204     -0.236      -0.182      -0.177
+49152.00      0.198     -0.182      -0.269      -0.434
+49153.00      0.206     -0.183      -0.271      -0.727
+49154.00      0.223     -0.257      -0.164      -0.945
+49155.00      0.236     -0.257      -0.052      -1.144
+49156.00      0.237     -0.153       0.060      -1.246
+49157.00      0.225     -0.016       0.074      -1.307
+49158.00      0.206      0.090       0.079      -1.201
+49159.00      0.179      0.121       0.003      -1.101
+49160.00      0.138      0.017      -0.033      -0.930
+49161.00      0.094     -0.223      -0.039      -0.833
+49162.00      0.112     -0.318       0.077      -0.911
+49163.00      0.150     -0.240       0.122      -0.819
+49164.00      0.127     -0.140       0.114      -0.698
+49165.00      0.060     -0.099       0.004      -0.614
+49166.00     -0.015     -0.113      -0.202      -0.547
+49167.00     -0.062     -0.127      -0.329      -0.692
+49168.00     -0.059     -0.099      -0.289      -0.672
+49169.00     -0.028     -0.096      -0.167      -0.641
+49170.00      0.020     -0.147      -0.058      -0.560
+49171.00      0.088     -0.214       0.022      -0.458
+49172.00      0.175     -0.254       0.064      -0.516
+49173.00      0.261     -0.237       0.031      -0.682
+49174.00      0.331     -0.141       0.062      -0.804
+49175.00      0.384      0.064       0.127      -0.664
+49176.00      0.421      0.371       0.163      -0.380
+49177.00      0.434      0.508       0.090       0.007
+49178.00      0.395      0.408       0.031       0.065
+49179.00      0.318      0.196      -0.109      -0.005
+49180.00      0.250     -0.028      -0.247      -0.086
+49181.00      0.214     -0.181      -0.235      -0.181
+49182.00      0.208     -0.214      -0.099      -0.216
+49183.00      0.196     -0.208       0.091      -0.394
+49184.00      0.202     -0.271       0.274      -0.540
+49185.00      0.225     -0.237       0.321      -0.648
+49186.00      0.218     -0.152       0.259      -0.530
+49187.00      0.171     -0.141       0.115      -0.374
+49188.00      0.105     -0.134       0.009      -0.296
+49189.00      0.046     -0.092      -0.060      -0.492
+49190.00      0.018     -0.072      -0.052      -0.710
+49191.00      0.013     -0.067       0.065      -0.894
+49192.00      0.022     -0.044       0.165      -0.924
+49193.00      0.038     -0.019       0.098      -0.678
+49194.00      0.055     -0.017      -0.071      -0.600
+49195.00      0.078     -0.040      -0.172      -0.466
+49196.00      0.110     -0.070      -0.212      -0.570
+49197.00      0.134     -0.102      -0.083      -0.478
+49198.00      0.132     -0.205       0.065      -0.481
+49199.00      0.133     -0.280       0.228      -0.415
+49200.00      0.160     -0.257       0.238      -0.436
+49201.00      0.189     -0.202       0.228      -0.470
+49202.00      0.185     -0.183       0.166      -0.461
+49203.00      0.135     -0.251       0.074      -0.501
+49204.00      0.065     -0.358      -0.004      -0.508
+49205.00      0.002     -0.396       0.155      -0.207
+49206.00     -0.030     -0.387       0.098      -0.202
+49207.00     -0.017     -0.362      -0.079      -0.246
+49208.00      0.032     -0.301      -0.236      -0.485
+49209.00      0.080     -0.206      -0.339      -0.538
+49210.00      0.086     -0.092      -0.222      -0.633
+49211.00      0.082      0.044       0.014      -0.813
+49212.00      0.076      0.135       0.207      -0.959
+49213.00      0.065      0.139       0.265      -1.171
+49214.00      0.046      0.067       0.156      -1.176
+49215.00      0.016     -0.055       0.034      -0.980
+49216.00     -0.014     -0.204      -0.054      -0.992
+49217.00     -0.021     -0.345      -0.105      -1.047
+49218.00      0.009     -0.342      -0.088      -1.213
+49219.00      0.016     -0.325      -0.057      -1.351
+49220.00      0.010     -0.297      -0.036      -1.290
+49221.00      0.037     -0.213      -0.019      -1.129
+49222.00      0.107     -0.129      -0.030      -1.035
+49223.00      0.216     -0.120      -0.055      -0.786
+49224.00      0.364     -0.250      -0.112      -0.698
+49225.00      0.478     -0.394      -0.083      -0.565
+49226.00      0.491     -0.453       0.049      -0.454
+49227.00      0.407     -0.423       0.186      -0.432
+49228.00      0.279     -0.340       0.316      -0.437
+49229.00      0.157     -0.243       0.342      -0.366
+49230.00      0.083     -0.158       0.326      -0.349
+49231.00      0.095     -0.056       0.259      -0.453
+49232.00      0.194      0.024       0.198      -0.563
+49233.00      0.318      0.045       0.178      -0.595
+49234.00      0.371      0.031       0.101      -0.501
+49235.00      0.338      0.005      -0.066      -0.299
+49236.00      0.268     -0.019      -0.163      -0.533
+49237.00      0.194     -0.052      -0.239      -0.646
+49238.00      0.135     -0.113      -0.094      -0.615
+49239.00      0.102     -0.170       0.205      -0.646
+49240.00      0.099     -0.207       0.452      -0.667
+49241.00      0.121     -0.236       0.485      -0.939
+49242.00      0.147     -0.267       0.430      -0.982
+49243.00      0.155     -0.293       0.271      -0.803
+49244.00      0.134     -0.312       0.189      -0.727
+49245.00      0.091     -0.332       0.103      -0.782
+49246.00      0.027     -0.339       0.048      -0.779
+49247.00     -0.045     -0.239      -0.117      -0.655
+49248.00     -0.100     -0.192      -0.356      -0.556
+49249.00     -0.108     -0.295      -0.471      -0.762
+49250.00     -0.063     -0.413      -0.429      -0.859
+49251.00      0.004     -0.406      -0.305      -0.918
+49252.00      0.066     -0.222      -0.270      -0.833
+49253.00      0.130      0.052      -0.354      -0.492
+49254.00      0.132      0.053      -0.387      -0.431
+49255.00      0.074     -0.085      -0.303      -0.467
+49256.00      0.017     -0.122      -0.148      -0.544
+49257.00     -0.028     -0.126      -0.081      -0.568
+49258.00     -0.055     -0.151      -0.113      -0.482
+49259.00     -0.059     -0.233      -0.163      -0.631
+49260.00     -0.018     -0.393      -0.203      -0.744
+49261.00      0.111     -0.434      -0.208      -0.803
+49262.00      0.178     -0.376      -0.184      -0.708
+49263.00      0.166     -0.393      -0.189      -0.694
+49264.00      0.109     -0.436      -0.240      -0.769
+49265.00      0.037     -0.458      -0.276      -0.898
+49266.00     -0.025     -0.407      -0.122      -0.896
+49267.00     -0.049     -0.245       0.085      -0.774
+49268.00     -0.003     -0.053       0.249      -0.745
+49269.00      0.041      0.045       0.340      -0.756
+49270.00      0.032      0.026       0.211      -0.816
+49271.00     -0.004     -0.052       0.060      -0.623
+49272.00     -0.040     -0.129      -0.050      -0.512
+49273.00     -0.054     -0.185      -0.089      -0.551
+49274.00     -0.060     -0.288      -0.134      -0.459
+49275.00     -0.096     -0.295      -0.361      -0.309
+49276.00     -0.129     -0.227      -0.651      -0.197
+49277.00     -0.113     -0.195      -0.854      -0.288
+49278.00     -0.055     -0.189      -0.758      -0.627
+49279.00     -0.006     -0.168      -0.489      -0.911
+49280.00     -0.018     -0.150      -0.269      -0.875
+49281.00     -0.053     -0.090      -0.200      -0.616
+49282.00     -0.060     -0.063      -0.203      -0.436
+49283.00     -0.041     -0.079      -0.139      -0.468
+49284.00     -0.019     -0.097      -0.012      -0.504
+49285.00      0.002     -0.129       0.041      -0.612
+49286.00      0.025     -0.176      -0.008      -0.592
+49287.00      0.044     -0.216      -0.073      -0.703
+49288.00      0.033     -0.252      -0.165      -0.728
+49289.00      0.003     -0.287      -0.191      -0.679
+49290.00     -0.029     -0.305      -0.226      -0.728
+49291.00     -0.065     -0.298      -0.212      -0.661
+49292.00     -0.092     -0.283      -0.207      -0.673
+49293.00     -0.090     -0.280      -0.214      -0.839
+49294.00     -0.042     -0.292      -0.163      -0.758
+49295.00      0.047     -0.338      -0.167      -0.888
+49296.00      0.140     -0.351      -0.101      -0.603
+49297.00      0.200     -0.307      -0.052      -0.400
+49298.00      0.206     -0.247      -0.126      -0.294
+49299.00      0.154     -0.184      -0.280      -0.248
+49300.00      0.041     -0.128      -0.401      -0.357
+49301.00     -0.127     -0.094      -0.430      -0.609
+49302.00     -0.270     -0.077      -0.443      -0.692
+49303.00     -0.358     -0.061      -0.561      -0.559
+49304.00     -0.395     -0.056      -0.736      -0.157
+49305.00     -0.373     -0.087      -0.845      -0.052
+49306.00     -0.303     -0.148      -0.771      -0.224
+49307.00     -0.213     -0.209      -0.487      -0.530
+49308.00     -0.136     -0.267      -0.210      -0.585
+49309.00     -0.081     -0.350      -0.128      -0.495
+49310.00     -0.037     -0.428      -0.108      -0.310
+49311.00     -0.006     -0.453      -0.048      -0.198
+49312.00      0.000     -0.423       0.027      -0.091
+49313.00     -0.012     -0.370       0.037      -0.240
+49314.00     -0.031     -0.314      -0.052      -0.320
+49315.00     -0.052     -0.256      -0.126      -0.537
+49316.00     -0.074     -0.206      -0.212      -0.675
+49317.00     -0.086     -0.170      -0.299      -0.788
+49318.00     -0.085     -0.135      -0.287      -0.857
+49319.00     -0.081     -0.085      -0.275      -0.814
+49320.00     -0.075     -0.042      -0.139      -0.784
+49321.00     -0.063     -0.041      -0.038      -0.732
+49322.00     -0.051     -0.090       0.027      -0.604
+49323.00     -0.071     -0.161       0.044      -0.399
+49324.00     -0.111     -0.198      -0.031      -0.194
+49325.00     -0.152     -0.198      -0.005       0.126
+49326.00     -0.193     -0.190      -0.060       0.031
+49327.00     -0.228     -0.181      -0.152      -0.161
+49328.00     -0.245     -0.180      -0.275      -0.332
+49329.00     -0.229     -0.202      -0.360      -0.748
+49330.00     -0.188     -0.260      -0.412      -0.999
+49331.00     -0.139     -0.267      -0.402      -1.235
+49332.00     -0.098     -0.113      -0.379      -1.127
+49333.00     -0.068      0.095      -0.372      -0.754
+49334.00     -0.054      0.135      -0.286      -0.664
+49335.00     -0.050      0.018      -0.105      -0.726
+49336.00     -0.044     -0.134       0.015      -0.787
+49337.00     -0.019     -0.179       0.136      -0.741
+49338.00      0.020     -0.145       0.109      -0.608
+49339.00      0.052     -0.132       0.119      -0.454
+49340.00      0.061     -0.167       0.126      -0.202
+49341.00      0.047     -0.214       0.080      -0.142
+49342.00      0.016     -0.211      -0.015      -0.184
+49343.00     -0.024     -0.132      -0.121      -0.374
+49344.00     -0.052     -0.070      -0.245      -0.546
+49345.00     -0.059     -0.061      -0.363      -0.680
+49346.00     -0.051     -0.091      -0.427      -0.803
+49347.00     -0.037     -0.121      -0.437      -0.943
+49348.00     -0.019     -0.137      -0.290      -0.966
+49349.00      0.003     -0.147      -0.149      -0.802
+49350.00      0.021     -0.147      -0.123      -0.535
+49351.00      0.023     -0.114      -0.141      -0.258
+49352.00      0.034     -0.083      -0.163      -0.103
+49353.00      0.067     -0.088      -0.177      -0.021
+49354.00      0.110     -0.124      -0.161      -0.144
+49355.00      0.145     -0.159      -0.134      -0.166
+49356.00      0.150     -0.169      -0.164      -0.343
+49357.00      0.107     -0.156      -0.231      -0.494
+49358.00      0.009     -0.124      -0.343      -0.613
+49359.00     -0.126     -0.190      -0.348      -0.722
+49360.00     -0.242     -0.240      -0.340      -0.553
+49361.00     -0.319     -0.184      -0.291      -0.268
+49362.00     -0.368     -0.101      -0.283      -0.056
+49363.00     -0.391     -0.042      -0.308      -0.076
+49364.00     -0.389     -0.034      -0.354      -0.317
+49365.00     -0.368     -0.069      -0.408      -0.499
+49366.00     -0.326     -0.111      -0.441      -0.522
+49367.00     -0.260     -0.129      -0.459      -0.425
+49368.00     -0.197     -0.114      -0.436      -0.210
+49369.00     -0.160     -0.080      -0.426      -0.036
+49370.00     -0.146     -0.013      -0.415      -0.074
+49371.00     -0.147      0.039      -0.434      -0.265
+49372.00     -0.150      0.039      -0.501      -0.403
+49373.00     -0.143     -0.053      -0.566      -0.464
+49374.00     -0.140     -0.124      -0.555      -0.434
+49375.00     -0.144     -0.092      -0.517      -0.698
+49376.00     -0.138     -0.050      -0.330      -0.717
+49377.00     -0.113     -0.020      -0.226      -0.753
+49378.00     -0.076     -0.001      -0.137      -0.447
+49379.00     -0.044     -0.028      -0.168      -0.130
+49380.00     -0.042     -0.071      -0.318      -0.017
+49381.00     -0.078     -0.112      -0.452      -0.075
+49382.00     -0.137     -0.147      -0.540      -0.332
+49383.00     -0.209     -0.148      -0.524      -0.545
+49384.00     -0.292     -0.098      -0.541      -0.428
+49385.00     -0.386     -0.015      -0.704      -0.183
+49386.00     -0.479      0.079      -0.763      -0.240
+49387.00     -0.535      0.167      -0.769      -0.421
+49388.00     -0.549      0.272      -0.607      -0.471
+49389.00     -0.528      0.348      -0.477      -0.367
+49390.00     -0.476      0.334      -0.298      -0.283
+49391.00     -0.378      0.193      -0.252      -0.332
+49392.00     -0.214     -0.044      -0.234      -0.456
+49393.00      0.003     -0.186      -0.167      -0.674
+49394.00      0.196     -0.215      -0.119      -0.729
+49395.00      0.272     -0.218      -0.131      -0.807
+49396.00      0.224     -0.218      -0.185      -0.720
+49397.00      0.099     -0.205      -0.313      -0.582
+49398.00     -0.057     -0.176      -0.396      -0.594
+49399.00     -0.190     -0.124      -0.508      -0.651
+49400.00     -0.255     -0.043      -0.626      -0.767
+49401.00     -0.234      0.080      -0.753      -0.706
+49402.00     -0.157      0.220      -0.799      -0.668
+49403.00     -0.059      0.348      -0.690      -0.804
+49404.00      0.034      0.428      -0.630      -0.924
+49405.00      0.087      0.401      -0.564      -1.039
+49406.00      0.075      0.235      -0.605      -0.960
+49407.00      0.024      0.047      -0.601      -0.542
+49408.00     -0.040     -0.103      -0.681      -0.363
+49409.00     -0.104     -0.213      -0.759      -0.492
+49410.00     -0.155     -0.277      -0.837      -0.656
+49411.00     -0.187     -0.265      -0.809      -0.829
+49412.00     -0.192     -0.177      -0.738      -0.782
+49413.00     -0.162     -0.043      -0.622      -0.567
+49414.00     -0.093      0.122      -0.640      -0.382
+49415.00     -0.002      0.311      -0.557      -0.382
+49416.00      0.088      0.502      -0.493      -0.423
+49417.00      0.158      0.647      -0.365      -0.288
+49418.00      0.180      0.679      -0.251      -0.296
+49419.00      0.129      0.540      -0.194      -0.267
+49420.00     -0.001      0.228      -0.226      -0.305
+49421.00     -0.170     -0.029      -0.214      -0.401
+49422.00     -0.320     -0.148      -0.170      -0.418
+49423.00     -0.389     -0.169      -0.150      -0.477
+49424.00     -0.363     -0.121      -0.172      -0.602
+49425.00     -0.280     -0.034      -0.193      -0.485
+49426.00     -0.188      0.052      -0.215      -0.410
+49427.00     -0.123      0.104      -0.224      -0.357
+49428.00     -0.131      0.143      -0.266      -0.427
+49429.00     -0.197      0.196      -0.246      -0.279
+49430.00     -0.244      0.219      -0.190      -0.260
+49431.00     -0.238      0.198       0.026      -0.213
+49432.00     -0.201      0.158       0.144      -0.415
+49433.00     -0.168      0.093       0.095      -0.711
+49434.00     -0.175      0.006       0.073      -0.725
+49435.00     -0.242     -0.056       0.018      -0.374
+49436.00     -0.314     -0.051      -0.093      -0.103
+49437.00     -0.354     -0.030      -0.250      -0.083
+49438.00     -0.361     -0.029      -0.421      -0.450
+49439.00     -0.345     -0.019      -0.497      -0.583
+49440.00     -0.322      0.002      -0.542      -0.627
+49441.00     -0.291     -0.003      -0.518      -0.640
+49442.00     -0.241     -0.050      -0.517      -0.620
+49443.00     -0.180     -0.102      -0.472      -0.668
+49444.00     -0.129     -0.125      -0.385      -0.612
+49445.00     -0.091     -0.122      -0.333      -0.581
+49446.00     -0.060     -0.105      -0.228      -0.645
+49447.00     -0.043     -0.087      -0.180      -0.588
+49448.00     -0.046     -0.073      -0.186      -0.537
+49449.00     -0.074     -0.063      -0.267      -0.580
+49450.00     -0.126     -0.046      -0.326      -0.566
+49451.00     -0.198     -0.014      -0.381      -0.690
+49452.00     -0.272      0.021      -0.420      -0.735
+49453.00     -0.330      0.043      -0.395      -0.686
+49454.00     -0.370      0.051      -0.350      -0.476
+49455.00     -0.384      0.051      -0.316      -0.357
+49456.00     -0.363      0.043      -0.321      -0.339
+49457.00     -0.316      0.021      -0.303      -0.300
+49458.00     -0.266     -0.008      -0.159      -0.090
+49459.00     -0.218     -0.023      -0.002      -0.058
+49460.00     -0.172     -0.014       0.129      -0.098
+49461.00     -0.138     -0.007       0.048      -0.273
+49462.00     -0.128     -0.026      -0.164      -0.382
+49463.00     -0.143     -0.048      -0.298      -0.180
+49464.00     -0.172     -0.037      -0.396       0.112
+49465.00     -0.200     -0.004      -0.387       0.062
+49466.00     -0.211      0.027      -0.435      -0.136
+49467.00     -0.201      0.060      -0.447      -0.336
+49468.00     -0.185      0.101      -0.450      -0.301
+49469.00     -0.170      0.111      -0.450      -0.390
+49470.00     -0.151      0.088      -0.394      -0.395
+49471.00     -0.152     -0.011      -0.377      -0.572
+49472.00     -0.162     -0.109      -0.388      -0.576
+49473.00     -0.162     -0.135      -0.364      -0.425
+49474.00     -0.153     -0.101      -0.346      -0.351
+49475.00     -0.141     -0.030      -0.249      -0.488
+49476.00     -0.134      0.042      -0.215      -0.447
+49477.00     -0.130      0.088      -0.316      -0.381
+49478.00     -0.131      0.125      -0.496      -0.346
+49479.00     -0.144      0.172      -0.656      -0.478
+49480.00     -0.161      0.204      -0.620      -0.578
+49481.00     -0.162      0.187      -0.568      -0.695
+49482.00     -0.154      0.118      -0.478      -0.615
+49483.00     -0.155      0.019      -0.436      -0.405
+49484.00     -0.190     -0.099      -0.384      -0.436
+49485.00     -0.219     -0.236      -0.294      -0.519
+49486.00     -0.235     -0.300      -0.178      -0.641
+49487.00     -0.254     -0.245       0.053      -0.640
+49488.00     -0.270     -0.117       0.158      -0.567
+49489.00     -0.283      0.004       0.121      -0.580
+49490.00     -0.303      0.026      -0.100      -0.648
+49491.00     -0.331     -0.089      -0.312      -0.600
+49492.00     -0.335     -0.200      -0.442      -0.552
+49493.00     -0.302     -0.224      -0.512      -0.674
+49494.00     -0.243     -0.188      -0.428      -0.913
+49495.00     -0.176     -0.108      -0.322      -0.887
+49496.00     -0.124     -0.004      -0.299      -0.721
+49497.00     -0.106      0.087      -0.278      -0.604
+49498.00     -0.096      0.144      -0.261      -0.653
+49499.00     -0.073      0.168      -0.206      -0.742
+49500.00     -0.033      0.174      -0.252      -0.875
+49501.00      0.017      0.178      -0.333      -0.673
+49502.00      0.059      0.193      -0.269      -0.533
+49503.00      0.073      0.210      -0.148      -0.354
+49504.00      0.048      0.188      -0.041      -0.231
+49505.00     -0.007      0.091      -0.152      -0.336
+49506.00     -0.067     -0.019      -0.382      -0.389
+49507.00     -0.117     -0.053      -0.538      -0.505
+49508.00     -0.147     -0.023      -0.568      -0.709
+49509.00     -0.135      0.014      -0.491      -0.684
+49510.00     -0.082      0.032      -0.376      -0.706
+49511.00     -0.011      0.034      -0.278      -0.593
+49512.00      0.057      0.006      -0.263      -0.591
+49513.00      0.107     -0.098      -0.244      -0.730
+49514.00      0.135     -0.263      -0.208      -0.818
+49515.00      0.140     -0.418      -0.103      -0.865
+49516.00      0.136     -0.489      -0.005      -0.772
+49517.00      0.144     -0.425       0.015      -0.601
+49518.00      0.175     -0.182      -0.081      -0.603
+49519.00      0.230      0.261      -0.291      -0.491
+49520.00      0.267      0.575      -0.521      -0.665
+49521.00      0.267      0.617      -0.603      -0.788
+49522.00      0.229      0.489      -0.578      -0.939
+49523.00      0.150      0.287      -0.448      -0.959
+49524.00      0.039      0.091      -0.340      -0.720
+49525.00     -0.095     -0.045      -0.277      -0.416
+49526.00     -0.247     -0.108      -0.196      -0.393
+49527.00     -0.392     -0.109      -0.208      -0.497
+49528.00     -0.479     -0.073      -0.236      -0.656
+49529.00     -0.459     -0.034      -0.377      -0.592
+49530.00     -0.330     -0.001      -0.394      -0.475
+49531.00     -0.180      0.052      -0.324      -0.398
+49532.00     -0.080      0.115      -0.273      -0.159
+49533.00     -0.041      0.115      -0.308      -0.207
+49534.00     -0.052     -0.045      -0.495      -0.349
+49535.00     -0.065     -0.222      -0.697       0.054
+49536.00     -0.064     -0.215      -0.588      -0.124
+49537.00     -0.042     -0.102      -0.382      -0.122
+49538.00     -0.003      0.025      -0.112      -0.142
+49539.00      0.027      0.098       0.061      -0.048
+49540.00      0.034      0.062       0.211      -0.001
+49541.00      0.018      0.006       0.302       0.093
+49542.00     -0.011      0.022       0.313       0.162
+49543.00     -0.046      0.052       0.265       0.216
+49544.00     -0.084      0.088       0.232       0.137
+49545.00     -0.110      0.097       0.262       0.222
+49546.00     -0.106      0.064       0.241       0.092
+49547.00     -0.069     -0.017       0.115      -0.032
+49548.00     -0.009     -0.124      -0.057      -0.161
+49549.00      0.028     -0.163      -0.255      -0.302
+49550.00      0.012     -0.108      -0.365      -0.501
+49551.00     -0.047     -0.019      -0.328      -0.649
+49552.00     -0.131      0.030      -0.139      -0.503
+49553.00     -0.213     -0.045       0.027      -0.279
+49554.00     -0.233     -0.197       0.173      -0.081
+49555.00     -0.151     -0.370       0.241      -0.226
+49556.00     -0.042     -0.444       0.248      -0.441
+49557.00      0.025     -0.378       0.175      -0.537
+49558.00      0.056     -0.244       0.139      -0.472
+49559.00      0.059     -0.103       0.136      -0.248
+49560.00      0.047     -0.028       0.121      -0.079
+49561.00      0.036     -0.088       0.086       0.118
+49562.00      0.019     -0.165      -0.020       0.114
+49563.00     -0.013     -0.070      -0.144       0.069
+49564.00     -0.051      0.142      -0.194      -0.039
+49565.00     -0.085      0.314      -0.214       0.009
+49566.00     -0.115      0.283      -0.041       0.065
+49567.00     -0.142     -0.040       0.095       0.075
+49568.00     -0.148     -0.451       0.235       0.057
+49569.00     -0.109     -0.781       0.386       0.071
+49570.00     -0.083     -0.917       0.110       0.427
+49571.00     -0.107     -0.831      -0.023       0.440
+49572.00     -0.148     -0.610      -0.088       0.308
+49573.00     -0.159     -0.364      -0.069       0.245
+49574.00     -0.090     -0.175       0.053      -0.113
+49575.00      0.042     -0.011       0.144      -0.323
+49576.00      0.225      0.290       0.141      -0.369
+49577.00      0.334      0.529       0.009      -0.351
+49578.00      0.307      0.519      -0.151      -0.359
+49579.00      0.207      0.340      -0.198      -0.479
+49580.00      0.098      0.101      -0.114      -0.344
+49581.00      0.029     -0.113       0.029      -0.151
+49582.00      0.016     -0.256       0.226       0.002
+49583.00      0.051     -0.321       0.349       0.093
+49584.00      0.118     -0.317       0.341       0.001
+49585.00      0.189     -0.264       0.302      -0.167
+49586.00      0.237     -0.193       0.237      -0.154
+49587.00      0.247     -0.122       0.188      -0.076
+49588.00      0.211     -0.064       0.100       0.031
+49589.00      0.115     -0.045       0.063       0.163
+49590.00     -0.004     -0.066      -0.011       0.153
+49591.00     -0.066     -0.098      -0.127       0.120
+49592.00     -0.040     -0.116      -0.229       0.021
+49593.00      0.034     -0.115      -0.240       0.056
+49594.00      0.101     -0.103      -0.093       0.050
+49595.00      0.127     -0.076       0.070       0.025
+49596.00      0.159     -0.043       0.283      -0.087
+49597.00      0.215     -0.087       0.414      -0.058
+49598.00      0.258     -0.157       0.368       0.092
+49599.00      0.259     -0.176       0.331       0.373
+49600.00      0.224     -0.150       0.149       0.403
+49601.00      0.166     -0.101       0.077       0.224
+49602.00      0.099     -0.047       0.027      -0.007
+49603.00      0.041      0.013       0.047      -0.177
+49604.00     -0.001      0.028       0.044      -0.133
+49605.00     -0.015      0.026       0.047      -0.194
+49606.00     -0.010      0.036      -0.038      -0.085
+49607.00     -0.001      0.028      -0.015      -0.123
+49608.00      0.012     -0.011      -0.025      -0.162
+49609.00      0.020     -0.080       0.043       0.009
+49610.00      0.011     -0.161       0.132       0.049
+49611.00     -0.006     -0.223       0.172       0.207
+49612.00      0.007     -0.244       0.213       0.165
+49613.00      0.050     -0.231       0.212       0.057
+49614.00      0.084     -0.216       0.217       0.056
+49615.00      0.078     -0.216       0.204      -0.155
+49616.00      0.023     -0.230       0.113      -0.131
+49617.00     -0.057     -0.178       0.098      -0.092
+49618.00     -0.119     -0.100       0.009      -0.010
+49619.00     -0.117     -0.071      -0.046       0.058
+49620.00     -0.051     -0.070      -0.146      -0.085
+49621.00      0.036     -0.072      -0.160      -0.028
+49622.00      0.089     -0.079      -0.070       0.081
+49623.00      0.075     -0.091       0.145       0.050
+49624.00      0.038     -0.116       0.324      -0.036
+49625.00      0.004     -0.147       0.360      -0.143
+49626.00     -0.029     -0.184       0.282      -0.003
+49627.00     -0.060     -0.216       0.230       0.288
+49628.00     -0.079     -0.231       0.217       0.440
+49629.00     -0.066     -0.216       0.131       0.399
+49630.00     -0.017     -0.188       0.034       0.345
+49631.00      0.022     -0.246      -0.146      -0.031
+49632.00     -0.019     -0.360      -0.267      -0.084
+49633.00     -0.062     -0.447      -0.226      -0.321
+49634.00     -0.044     -0.461      -0.042      -0.483
+49635.00     -0.012     -0.399       0.132      -0.474
+49636.00      0.012     -0.307       0.161      -0.349
+49637.00      0.044     -0.238       0.159      -0.121
+49638.00      0.090     -0.193       0.128      -0.022
+49639.00      0.131     -0.133       0.144       0.148
+49640.00      0.147     -0.046       0.240       0.085
+49641.00      0.144      0.025       0.303       0.147
+49642.00      0.133      0.033       0.351       0.121
+49643.00      0.127     -0.040       0.325       0.102
+49644.00      0.142     -0.182       0.364       0.047
+49645.00      0.161     -0.285       0.301       0.013
+49646.00      0.158     -0.306       0.237      -0.129
+49647.00      0.139     -0.274       0.142      -0.079
+49648.00      0.125     -0.211       0.057      -0.192
+49649.00      0.124     -0.133       0.019      -0.233
+49650.00      0.134     -0.079       0.077      -0.277
+49651.00      0.152     -0.083       0.221      -0.285
+49652.00      0.149     -0.121       0.293      -0.240
+49653.00      0.097     -0.176       0.258      -0.295
+49654.00     -0.001     -0.167       0.068      -0.379
+49655.00     -0.111     -0.061      -0.030      -0.091
+49656.00     -0.186      0.070      -0.101      -0.040
+49657.00     -0.180      0.142      -0.131       0.006
+49658.00     -0.077      0.098      -0.268      -0.139
+49659.00      0.025      0.035      -0.528      -0.220
+49660.00      0.079     -0.007      -0.928      -0.121
+49661.00      0.109     -0.046      -0.872      -0.297
+49662.00      0.136     -0.072      -0.531      -0.477
+49663.00      0.140     -0.045      -0.135      -0.454
+49664.00      0.094      0.001       0.126      -0.280
+49665.00      0.029     -0.015       0.127       0.178
+49666.00      0.014     -0.127       0.014       0.343
+49667.00      0.048     -0.249       0.000       0.466
+49668.00      0.076     -0.301       0.113       0.332
+49669.00      0.078     -0.297       0.127       0.293
+49670.00      0.068     -0.277       0.076       0.225
+49671.00      0.057     -0.242       0.057       0.040
+49672.00      0.052     -0.181       0.038      -0.157
+49673.00      0.060     -0.099       0.003      -0.189
+49674.00      0.075     -0.016      -0.068      -0.337
+49675.00      0.078      0.048      -0.063      -0.384
+49676.00      0.063      0.071      -0.093      -0.501
+49677.00      0.035      0.037      -0.084      -0.444
+49678.00     -0.006     -0.062       0.013      -0.427
+49679.00     -0.058     -0.207       0.124      -0.165
+49680.00     -0.092     -0.291       0.188       0.025
+49681.00     -0.104     -0.303       0.220       0.068
+49682.00     -0.109     -0.291       0.133       0.039
+49683.00     -0.106     -0.270       0.026       0.057
+49684.00     -0.092     -0.246       0.022      -0.069
+49685.00     -0.079     -0.244       0.060      -0.113
+49686.00     -0.083     -0.283       0.080      -0.239
+49687.00     -0.111     -0.300      -0.049      -0.403
+49688.00     -0.155     -0.269      -0.210      -0.303
+49689.00     -0.194     -0.228      -0.283      -0.268
+49690.00     -0.205     -0.205      -0.287      -0.561
+49691.00     -0.184     -0.188       0.037      -0.721
+49692.00     -0.155     -0.180       0.143      -0.589
+49693.00     -0.123     -0.215       0.002      -0.181
+49694.00     -0.112     -0.236      -0.037       0.147
+49695.00     -0.110     -0.190      -0.010       0.156
+49696.00     -0.114     -0.089       0.138       0.261
+49697.00     -0.119      0.007       0.185       0.138
+49698.00     -0.103      0.042       0.198       0.212
+49699.00     -0.057     -0.004       0.189       0.098
+49700.00      0.007     -0.133       0.158       0.051
+49701.00      0.052     -0.246       0.161      -0.090
+49702.00      0.066     -0.303       0.137      -0.393
+49703.00      0.049     -0.316       0.177      -0.493
+49704.00      0.013     -0.306       0.180      -0.531
+49705.00     -0.018     -0.299       0.215      -0.667
+49706.00     -0.025     -0.290       0.193      -0.520
+49707.00     -0.004     -0.254       0.171      -0.189
+49708.00      0.009     -0.184       0.130       0.214
+49709.00     -0.001     -0.110       0.138       0.470
+49710.00     -0.030     -0.068       0.059       0.566
+49711.00     -0.065     -0.064      -0.045       0.582
+49712.00     -0.086     -0.081      -0.054       0.493
+49713.00     -0.087     -0.112      -0.005       0.339
+49714.00     -0.077     -0.163       0.102       0.310
+49715.00     -0.059     -0.227       0.211       0.334
+49716.00     -0.035     -0.320       0.338       0.598
+49717.00     -0.014     -0.384       0.467       0.946
+49718.00     -0.001     -0.389       0.570       0.901
+49719.00      0.004     -0.357       0.723       0.680
+49720.00      0.006     -0.290       0.109      -0.047
+49721.00      0.008     -0.204      -0.056       0.019
+49722.00      0.011     -0.121      -0.187       0.022
+49723.00      0.001     -0.046      -0.186       0.105
+49724.00     -0.028      0.012      -0.093       0.116
+49725.00     -0.064      0.028      -0.108       0.013
+49726.00     -0.085     -0.002      -0.160      -0.054
+49727.00     -0.089     -0.061      -0.163      -0.193
+49728.00     -0.086     -0.137      -0.158      -0.434
+49729.00     -0.069     -0.177      -0.091      -0.591
+49730.00     -0.037     -0.167      -0.059      -0.768
+49731.00     -0.004     -0.110       0.013      -0.867
+49732.00      0.017     -0.037       0.161      -0.972
+49733.00      0.021     -0.007       0.274      -0.937
+49734.00     -0.006     -0.061       0.295      -0.632
+49735.00     -0.088     -0.212       0.226      -0.294
+49736.00     -0.226     -0.453       0.140      -0.019
+49737.00     -0.328     -0.605       0.092       0.224
+49738.00     -0.350     -0.599       0.025       0.249
+49739.00     -0.320     -0.492       0.007       0.121
+49740.00     -0.260     -0.335      -0.097       0.002
+49741.00     -0.190     -0.187      -0.068      -0.163
+49742.00     -0.144     -0.110       0.033      -0.200
+49743.00     -0.150     -0.104       0.151      -0.219
+49744.00     -0.198     -0.171       0.290       0.066
+49745.00     -0.252     -0.327       0.385       0.452
+49746.00     -0.293     -0.516       0.436       0.474
+49747.00     -0.310     -0.639       0.446       0.356
+49748.00     -0.290     -0.577       0.382      -0.004
+49749.00     -0.230     -0.301       0.226      -0.118
+49750.00     -0.169     -0.088      -0.011      -0.156
+49751.00     -0.127     -0.063      -0.057       0.092
+49752.00     -0.097     -0.104      -0.132       0.250
+49753.00     -0.071     -0.125      -0.171       0.417
+49754.00     -0.050     -0.127      -0.157       0.311
+49755.00     -0.046     -0.101      -0.163       0.203
+49756.00     -0.074     -0.061      -0.115       0.029
+49757.00     -0.141     -0.050      -0.116      -0.046
+49758.00     -0.234     -0.076      -0.128      -0.283
+49759.00     -0.331     -0.102      -0.100      -0.396
+49760.00     -0.412     -0.104      -0.061      -0.617
+49761.00     -0.449     -0.085       0.011      -0.556
+49762.00     -0.417     -0.058      -0.030      -0.305
+49763.00     -0.313     -0.033      -0.133      -0.169
+49764.00     -0.196     -0.104      -0.284      -0.067
+49765.00     -0.117     -0.179      -0.404      -0.012
+49766.00     -0.085     -0.191      -0.430      -0.189
+49767.00     -0.090     -0.157      -0.413      -0.175
+49768.00     -0.132     -0.090      -0.341      -0.142
+49769.00     -0.202     -0.031      -0.269      -0.152
+49770.00     -0.286     -0.028      -0.125      -0.044
+49771.00     -0.369     -0.094       0.050       0.020
+49772.00     -0.430     -0.166       0.288       0.176
+49773.00     -0.447     -0.185       0.504       0.452
+49774.00     -0.427     -0.178       0.620       0.580
+49775.00     -0.378     -0.154       0.645       0.459
+49776.00     -0.304     -0.108       0.627       0.276
+49777.00     -0.224     -0.065      -0.112       0.159
+49778.00     -0.152     -0.068      -0.145       0.195
+49779.00     -0.095     -0.098      -0.253       0.376
+49780.00     -0.048     -0.100      -0.288       0.633
+49781.00     -0.012     -0.071      -0.351       0.694
+49782.00      0.004     -0.028      -0.310       0.519
+49783.00     -0.003      0.015      -0.187       0.393
+49784.00     -0.024      0.036      -0.024       0.206
+49785.00     -0.035      0.012       0.076       0.043
+49786.00     -0.036     -0.052       0.089       0.008
+49787.00     -0.040     -0.115       0.131      -0.255
+49788.00     -0.053     -0.141       0.160      -0.370
+49789.00     -0.076     -0.122       0.190      -0.483
+49790.00     -0.111     -0.060       0.165      -0.234
+49791.00     -0.154      0.057       0.090      -0.050
+49792.00     -0.179      0.172      -0.011       0.074
+49793.00     -0.177      0.246      -0.150      -0.108
+49794.00     -0.152      0.272      -0.236      -0.221
+49795.00     -0.113      0.264      -0.218      -0.338
+49796.00     -0.073      0.238      -0.145      -0.119
+49797.00     -0.050      0.184      -0.074      -0.029
+49798.00     -0.056      0.092       0.076       0.164
+49799.00     -0.091     -0.018       0.156       0.142
+49800.00     -0.126     -0.098       0.311       0.203
+49801.00     -0.133     -0.129       0.384       0.201
+49802.00     -0.118     -0.139       0.396       0.383
+49803.00     -0.099     -0.147       0.300       0.464
+49804.00     -0.082     -0.138       0.123       0.334
+49805.00     -0.074     -0.107      -0.028       0.191
+49806.00     -0.063     -0.078      -0.159       0.161
+49807.00     -0.044     -0.063      -0.215       0.197
+49808.00     -0.013     -0.047      -0.348       0.340
+49809.00      0.020     -0.020      -0.368       0.374
+49810.00      0.036      0.003      -0.321       0.226
+49811.00      0.029      0.003      -0.185       0.110
+49812.00      0.008     -0.020      -0.038      -0.005
+49813.00     -0.033     -0.064       0.078      -0.098
+49814.00     -0.097     -0.116       0.184      -0.139
+49815.00     -0.179     -0.152       0.275      -0.218
+49816.00     -0.258     -0.157       0.252      -0.308
+49817.00     -0.320     -0.147       0.220      -0.444
+49818.00     -0.349     -0.141       0.133      -0.279
+49819.00     -0.329     -0.122       0.055       0.029
+49820.00     -0.272     -0.051      -0.040       0.140
+49821.00     -0.156      0.014      -0.141      -0.001
+49822.00     -0.044      0.043      -0.309      -0.250
+49823.00      0.004      0.051      -0.405      -0.409
+49824.00      0.003      0.053      -0.344      -0.173
+49825.00     -0.028      0.044      -0.294      -0.033
+49826.00     -0.074      0.028      -0.165       0.067
+49827.00     -0.124      0.039      -0.059       0.082
+49828.00     -0.192      0.039       0.099       0.030
+49829.00     -0.243      0.036       0.236       0.001
+49830.00     -0.254      0.043       0.323       0.097
+49831.00     -0.241      0.042       0.284       0.184
+49832.00     -0.214      0.039       0.131       0.148
+49833.00     -0.187      0.053       0.003       0.190
+49834.00     -0.185      0.091      -0.141       0.023
+49835.00     -0.204      0.146      -0.241      -0.010
+49836.00     -0.222      0.205      -0.269      -0.052
+49837.00     -0.228      0.247      -0.323      -0.093
+49838.00     -0.227      0.240      -0.322      -0.097
+49839.00     -0.217      0.157      -0.268      -0.050
+49840.00     -0.184      0.006      -0.113       0.029
+49841.00     -0.133     -0.114       0.021      -0.016
+49842.00     -0.086     -0.168       0.206       0.029
+49843.00     -0.054     -0.162       0.396       0.099
+49844.00     -0.028     -0.105       0.380       0.042
+49845.00     -0.011     -0.033       0.269      -0.061
+49846.00     -0.023      0.002       0.075      -0.045
+49847.00     -0.066     -0.009      -0.042       0.040
+49848.00     -0.131     -0.045      -0.039       0.223
+49849.00     -0.180     -0.064      -0.127       0.203
+49850.00     -0.201     -0.064      -0.171      -0.062
+49851.00     -0.208     -0.048      -0.252      -0.382
+49852.00     -0.216     -0.017      -0.254      -0.207
+49853.00     -0.224      0.005      -0.227       0.085
+49854.00     -0.211      0.003      -0.147       0.235
+49855.00     -0.165      0.007      -0.014       0.213
+49856.00     -0.104      0.052       0.108       0.252
+49857.00     -0.044      0.129       0.190       0.214
+49858.00      0.007      0.204       0.350       0.261
+49859.00      0.037      0.250       0.467       0.295
+49860.00      0.034      0.249       0.448       0.370
+49861.00     -0.013      0.197       0.309       0.293
+49862.00     -0.104      0.110       0.090       0.291
+49863.00     -0.196      0.048      -0.008       0.132
+49864.00     -0.250      0.026      -0.035       0.093
+49865.00     -0.258      0.014       0.010       0.080
+49866.00     -0.232      0.007       0.021       0.075
+49867.00     -0.196      0.013       0.025       0.140
+49868.00     -0.158      0.042       0.033       0.173
+49869.00     -0.127      0.080       0.126       0.123
+49870.00     -0.119      0.067       0.273       0.100
+49871.00     -0.137     -0.001       0.467       0.119
+49872.00     -0.152     -0.076       0.507       0.284
+49873.00     -0.147     -0.119       0.288       0.239
+49874.00     -0.128     -0.118       0.068       0.056
+49875.00     -0.095     -0.045      -0.142      -0.066
+49876.00     -0.036      0.143      -0.171      -0.059
+49877.00      0.041      0.377      -0.085      -0.232
+49878.00      0.105      0.519      -0.049      -0.454
+49879.00      0.136      0.531      -0.021      -0.624
+49880.00      0.110      0.454       0.019      -0.440
+49881.00      0.017      0.298       0.023      -0.190
+49882.00     -0.118      0.075       0.095      -0.016
+49883.00     -0.253     -0.165       0.158      -0.008
+49884.00     -0.310     -0.292       0.201       0.026
+49885.00     -0.282     -0.275       0.197       0.249
+49886.00     -0.207     -0.170       0.321       0.359
+49887.00     -0.117     -0.034       0.445       0.405
+49888.00     -0.033      0.071       0.452       0.477
+49889.00      0.051      0.096       0.339       0.540
+49890.00      0.184      0.079       0.052       0.629
+49891.00      0.349      0.070      -0.124       0.453
+49892.00      0.500      0.073      -0.087       0.332
+49893.00      0.610      0.052       0.028       0.269
+49894.00      0.637     -0.004       0.100       0.291
+49895.00      0.516     -0.072       0.133       0.288
+49896.00      0.225     -0.110       0.145       0.247
+49897.00     -0.058     -0.009       0.184       0.304
+49898.00     -0.234      0.133       0.309       0.308
+49899.00     -0.318      0.222       0.469       0.440
+49900.00     -0.333      0.274       0.582       0.725
+49901.00     -0.294      0.296       0.523       0.826
+49902.00     -0.235      0.288       0.296       0.697
+49903.00     -0.196      0.243       0.054       0.491
+49904.00     -0.209      0.167      -0.013       0.173
+49905.00     -0.293      0.065      -0.032      -0.025
+49906.00     -0.417     -0.052       0.054      -0.229
+49907.00     -0.531     -0.154       0.068      -0.326
+49908.00     -0.591     -0.201       0.066      -0.127
+49909.00     -0.556     -0.179       0.051       0.145
+49910.00     -0.400     -0.115      -0.003       0.161
+49911.00     -0.223     -0.148       0.062      -0.032
+49912.00     -0.078     -0.185       0.131      -0.080
+49913.00      0.031     -0.153       0.108       0.051
+49914.00      0.093     -0.085       0.105       0.155
+49915.00      0.105     -0.010       0.208       0.196
+49916.00      0.076      0.021       0.332       0.087
+49917.00      0.039     -0.028       0.274       0.015
+49918.00      0.024     -0.083      -0.037      -0.008
+49919.00      0.022     -0.078      -0.250      -0.041
+49920.00      0.016     -0.013      -0.347      -0.215
+49921.00      0.013      0.062      -0.308      -0.299
+49922.00      0.024      0.102      -0.248      -0.265
+49923.00      0.035      0.094      -0.243      -0.252
+49924.00      0.040      0.070      -0.290      -0.318
+49925.00      0.072      0.186      -0.216      -0.242
+49926.00      0.138      0.440      -0.109      -0.132
+49927.00      0.206      0.740       0.054      -0.022
+49928.00      0.246      0.986       0.153       0.155
+49929.00      0.245      1.074       0.218       0.305
+49930.00      0.191      0.898       0.264       0.266
+49931.00      0.073      0.428       0.126       0.140
+49932.00     -0.028      0.038      -0.043      -0.224
+49933.00     -0.075     -0.133      -0.169      -0.452
+49934.00     -0.086     -0.152      -0.141      -0.547
+49935.00     -0.076     -0.071      -0.105      -0.535
+49936.00     -0.059      0.058      -0.079      -0.177
+49937.00     -0.046      0.162      -0.015       0.104
+49938.00     -0.055      0.187      -0.035       0.196
+49939.00     -0.105      0.204       0.057       0.031
+49940.00     -0.145      0.227       0.097      -0.140
+49941.00     -0.146      0.232       0.048      -0.012
+49942.00     -0.119      0.220      -0.039       0.191
+49943.00     -0.084      0.208      -0.007       0.306
+49944.00     -0.059      0.197       0.056       0.332
+49945.00     -0.046      0.165       0.109       0.198
+49946.00     -0.045      0.110       0.019       0.080
+49947.00     -0.036      0.066      -0.074       0.009
+49948.00     -0.021      0.060      -0.103      -0.137
+49949.00     -0.008      0.074      -0.034      -0.096
+49950.00     -0.003      0.087       0.056      -0.086
+49951.00     -0.019      0.094       0.119      -0.106
+49952.00     -0.069      0.099       0.140       0.066
+49953.00     -0.139      0.092       0.204       0.153
+49954.00     -0.149      0.077       0.178       0.353
+49955.00     -0.103      0.138       0.120       0.432
+49956.00     -0.069      0.237       0.039       0.460
+49957.00     -0.089      0.325       0.065       0.351
+49958.00     -0.138      0.302       0.018       0.158
+49959.00     -0.210      0.139      -0.063       0.015
+49960.00     -0.328      0.073      -0.190      -0.192
+49961.00     -0.470      0.133      -0.379      -0.387
+49962.00     -0.540      0.178      -0.441      -0.544
+49963.00     -0.502      0.166      -0.358      -0.605
+49964.00     -0.395      0.139      -0.244      -0.473
+49965.00     -0.263      0.112      -0.138      -0.274
+49966.00     -0.153      0.076      -0.055      -0.274
+49967.00     -0.102      0.041       0.039      -0.203
+49968.00     -0.089      0.031       0.058      -0.406
+49969.00     -0.088      0.040      -0.028      -0.381
+49970.00     -0.090      0.049      -0.059      -0.159
+49971.00     -0.089      0.062      -0.070       0.059
+49972.00     -0.087      0.088      -0.018       0.229
+49973.00     -0.083      0.104       0.088       0.099
+49974.00     -0.075      0.084       0.149      -0.066
+49975.00     -0.058      0.038       0.171      -0.172
+49976.00     -0.034     -0.000       0.164      -0.296
+49977.00     -0.006     -0.018       0.168      -0.198
+49978.00      0.013     -0.015       0.189      -0.153
+49979.00      0.010      0.026       0.258      -0.066
+49980.00     -0.011      0.098       0.334       0.027
+49981.00     -0.024      0.052       0.387       0.182
+49982.00     -0.018     -0.070       0.387       0.562
+49983.00     -0.002     -0.110       0.296       0.742
+49984.00      0.014     -0.065       0.220       0.638
+49985.00      0.030      0.002       0.102       0.418
+49986.00      0.046      0.037       0.085       0.163
+49987.00      0.060      0.031       0.042       0.103
+49988.00      0.062      0.043      -0.021       0.104
+49989.00      0.046      0.075      -0.139       0.024
+49990.00      0.018      0.086      -0.147      -0.035
+49991.00     -0.004      0.072      -0.117      -0.043
+49992.00     -0.010      0.066      -0.043      -0.124
+49993.00     -0.015      0.086       0.041       0.026
+49994.00     -0.042      0.103       0.054       0.122
+49995.00     -0.086      0.040       0.076       0.197
+49996.00     -0.120     -0.055       0.022       0.088
+49997.00     -0.125     -0.087       0.004       0.114
+49998.00     -0.107     -0.059      -0.026       0.062
+49999.00     -0.087      0.009      -0.057       0.113
+50000.00     -0.076      0.105      -0.092       0.173
+50001.00     -0.092      0.194      -0.039      -0.028
+50002.00     -0.122      0.210       0.002      -0.173
+50003.00     -0.135      0.067       0.018      -0.285
+50004.00     -0.110     -0.060      -0.059      -0.319
+50005.00     -0.059     -0.097      -0.094      -0.210
+50006.00     -0.006     -0.081      -0.118      -0.143
+50007.00      0.029     -0.043      -0.057      -0.067
+50008.00      0.045      0.012      -0.029       0.067
+50009.00      0.045      0.072       0.043       0.252
+50010.00      0.028      0.117       0.042       0.503
+50011.00     -0.005      0.137       0.064       0.805
+50012.00     -0.043      0.133       0.047       0.716
+50013.00     -0.067      0.104       0.031       0.552
+50014.00     -0.066      0.050       0.012       0.124
+50015.00     -0.042     -0.013       0.025       0.037
+50016.00     -0.021     -0.044       0.030       0.177
+50017.00     -0.014     -0.034       0.075       0.143
+50018.00     -0.022     -0.007       0.179       0.173
+50019.00     -0.041      0.025       0.310       0.087
+50020.00     -0.056      0.062       0.367       0.094
+50021.00     -0.053      0.099       0.390       0.139
+50022.00     -0.038      0.121       0.275       0.188
+50023.00     -0.023      0.114       0.242       0.306
+50024.00     -0.009      0.079       0.206       0.408
+50025.00      0.012      0.027       0.224       0.427
+50026.00      0.034     -0.031       0.230       0.478
+50027.00      0.042     -0.061       0.245       0.346
+50028.00      0.030     -0.026       0.285       0.316
+50029.00     -0.009      0.089       0.340       0.282
+50030.00     -0.093      0.267       0.351      -0.051
+50031.00     -0.179      0.415       0.373      -0.170
+50032.00     -0.186      0.441       0.421      -0.252
+50033.00     -0.106      0.354       0.375      -0.291
+50034.00      0.002      0.210       0.393      -0.130
+50035.00      0.080      0.061       0.446      -0.145
+50036.00      0.100     -0.025       0.422      -0.058
+50037.00      0.078     -0.007       0.320       0.007
+50038.00      0.033      0.062       0.232       0.247
+50039.00     -0.014      0.112       0.187       0.345
+50040.00     -0.047      0.132       0.183       0.462
+50041.00     -0.055      0.128       0.111       0.324
+50042.00     -0.042      0.107       0.046      -0.030
+50043.00     -0.018      0.056      -0.064      -0.070
+50044.00      0.001     -0.078      -0.117       0.126
+50045.00      0.023     -0.293      -0.016       0.126
+50046.00      0.051     -0.526       0.219       0.040
+50047.00      0.066     -0.694       0.376      -0.077
+50048.00      0.052     -0.736       0.481      -0.171
+50049.00      0.020     -0.630       0.413      -0.120
+50050.00     -0.009     -0.386       0.262      -0.102
+50051.00     -0.036     -0.151       0.173      -0.115
+50052.00     -0.071      0.022       0.128       0.030
+50053.00     -0.106      0.122       0.086       0.269
+50054.00     -0.119      0.146       0.030       0.424
+50055.00     -0.104      0.122       0.029       0.302
+50056.00     -0.058      0.092      -0.004       0.207
+50057.00      0.026      0.067       0.056       0.111
+50058.00      0.139      0.042       0.068      -0.138
+50059.00      0.220      0.007       0.191      -0.163
+50060.00      0.246     -0.031       0.217      -0.282
+50061.00      0.237     -0.058       0.245      -0.265
+50062.00      0.203     -0.077       0.358      -0.191
+50063.00      0.159     -0.098       0.350      -0.025
+50064.00      0.125     -0.129       0.316       0.033
+50065.00      0.107     -0.168       0.141       0.079
+50066.00      0.083     -0.159       0.018       0.026
+50067.00      0.050     -0.095      -0.035       0.166
+50068.00      0.022     -0.012       0.043       0.141
+50069.00      0.007      0.046       0.128       0.031
+50070.00     -0.000      0.029       0.149      -0.120
+50071.00     -0.007     -0.073       0.152      -0.107
+50072.00     -0.020     -0.155       0.179       0.036
+50073.00     -0.038     -0.201       0.310       0.179
+50074.00     -0.048     -0.244       0.421       0.078
+50075.00     -0.046     -0.259       0.533      -0.106
+50076.00     -0.046     -0.221       0.522      -0.237
+50077.00     -0.056     -0.150       0.347      -0.056
+50078.00     -0.057     -0.087       0.164      -0.097
+50079.00     -0.046     -0.027       0.097      -0.108
+50080.00     -0.036      0.047       0.159      -0.057
+50081.00     -0.030      0.112       0.081       0.155
+50082.00     -0.011      0.143       0.011       0.441
+50083.00      0.024      0.147       0.021       0.435
+50084.00      0.060      0.142       0.062       0.391
+50085.00      0.093      0.131       0.263       0.199
+50086.00      0.125      0.109       0.395       0.048
+50087.00      0.149      0.074       0.504      -0.170
+50088.00      0.165      0.025       0.607      -0.392
+50089.00      0.177     -0.036       0.634      -0.486
+50090.00      0.186     -0.098       0.592      -0.291
+50091.00      0.184     -0.142       0.482      -0.234
+50092.00      0.175     -0.154       0.364      -0.144
+50093.00      0.155     -0.141       0.182      -0.109
+50094.00      0.123     -0.130      -0.063      -0.169
+50095.00      0.087     -0.136      -0.146      -0.192
+50096.00      0.066     -0.143      -0.104      -0.239
+50097.00      0.060     -0.147      -0.056      -0.183
+50098.00      0.054     -0.173       0.059      -0.240
+50099.00      0.048     -0.221       0.150      -0.284
+50100.00      0.044     -0.264       0.343      -0.047
+50101.00      0.034     -0.291       0.472       0.191
+50102.00      0.013     -0.328       0.614       0.177
+50103.00     -0.009     -0.376       0.688      -0.070
+50104.00     -0.020     -0.389       0.550      -0.276
+50105.00     -0.020     -0.332       0.320      -0.183
+50106.00     -0.011     -0.221       0.077      -0.106
+50107.00     -0.006     -0.139       0.020      -0.090
+50108.00     -0.019     -0.101      -0.012      -0.188
+50109.00     -0.042     -0.097      -0.037      -0.177
+50110.00     -0.049     -0.122      -0.112      -0.060
+50111.00     -0.029     -0.162      -0.097      -0.067
+50112.00      0.012     -0.204       0.057      -0.186
+50113.00      0.073     -0.250       0.250      -0.287
+50114.00      0.128     -0.281       0.416      -0.400
+50115.00      0.160     -0.272       0.412      -0.401
+50116.00      0.162     -0.226       0.453      -0.406
+50117.00      0.135     -0.177       0.434      -0.388
+50118.00      0.078     -0.139       0.414      -0.294
+50119.00     -0.022     -0.096       0.271      -0.128
+50120.00     -0.172     -0.045       0.189       0.013
+50121.00     -0.378     -0.067       0.223      -0.064
+50122.00     -0.516     -0.146       0.247      -0.249
+50123.00     -0.530     -0.232       0.298      -0.449
+50124.00     -0.446     -0.288       0.336      -0.595
+50125.00     -0.299     -0.282       0.305      -0.488
+50126.00     -0.148     -0.215       0.178      -0.340
+50127.00     -0.028     -0.092       0.043      -0.107
+50128.00      0.122      0.064       0.045       0.324
+50129.00      0.281      0.201       0.146       0.614
+50130.00      0.369      0.254       0.264       0.577
+50131.00      0.376      0.215       0.430       0.325
+50132.00      0.324      0.125       0.464       0.007
+50133.00      0.242      0.025       0.408      -0.160
+50134.00      0.147     -0.055       0.320      -0.030
+50135.00      0.049     -0.087       0.224       0.091
+50136.00     -0.047     -0.092       0.155      -0.003
+50137.00     -0.128     -0.112       0.014      -0.048
+50138.00     -0.180     -0.144      -0.103      -0.050
+50139.00     -0.208     -0.163      -0.172       0.001
+50140.00     -0.223     -0.170      -0.132      -0.150
+50141.00     -0.225     -0.185       0.024      -0.151
+50142.00     -0.206     -0.205       0.081      -0.208
+50143.00     -0.176     -0.196       0.120      -0.200
+50144.00     -0.149     -0.150       0.196      -0.297
+50145.00     -0.128     -0.100       0.257      -0.265
+50146.00     -0.107     -0.078       0.295      -0.091
+50147.00     -0.093     -0.079       0.239       0.000
+50148.00     -0.091     -0.091       0.118      -0.042
+50149.00     -0.086     -0.121       0.006      -0.036
+50150.00     -0.079     -0.163      -0.110      -0.149
+50151.00     -0.080     -0.198      -0.194      -0.135
+50152.00     -0.086     -0.210      -0.218      -0.184
+50153.00     -0.088     -0.193      -0.200      -0.214
+50154.00     -0.081     -0.158      -0.131      -0.224
+50155.00     -0.078     -0.114       0.014      -0.083
+50156.00     -0.081     -0.078       0.178      -0.098
+50157.00     -0.084     -0.061       0.283       0.030
+50158.00     -0.079     -0.070       0.381      -0.128
+50159.00     -0.073     -0.081       0.397      -0.358
+50160.00     -0.074     -0.077       0.325      -0.561
+50161.00     -0.086     -0.063       0.248      -0.527
+50162.00     -0.114     -0.067       0.142      -0.346
+50163.00     -0.166     -0.095       0.104       0.084
+50164.00     -0.233     -0.134       0.047       0.261
+50165.00     -0.299     -0.168       0.030       0.152
+50166.00     -0.352     -0.183       0.057       0.086
+50167.00     -0.383     -0.156       0.138      -0.001
+50168.00     -0.381     -0.085       0.209       0.020
+50169.00     -0.338      0.010       0.289       0.075
+50170.00     -0.311      0.078       0.311      -0.029
+50171.00     -0.298      0.126       0.215      -0.013
+50172.00     -0.290      0.175       0.214      -0.019
+50173.00     -0.289      0.212       0.191       0.013
+50174.00     -0.293      0.209       0.181       0.177
+50175.00     -0.305      0.174       0.007       0.297
+50176.00     -0.335      0.132      -0.150       0.228
+50177.00     -0.383      0.087      -0.266       0.025
+50178.00     -0.408      0.039      -0.411       0.008
+50179.00     -0.398     -0.001      -0.521       0.040
+50180.00     -0.370     -0.024      -0.565       0.051
+50181.00     -0.330     -0.031      -0.525       0.110
+50182.00     -0.275     -0.035      -0.419       0.155
+50183.00     -0.214     -0.029      -0.254       0.044
+50184.00     -0.168      0.001      -0.036       0.060
+50185.00     -0.151      0.031       0.071       0.095
+50186.00     -0.159      0.027       0.074       0.059
+50187.00     -0.179     -0.006       0.036       0.010
+50188.00     -0.204     -0.034      -0.014      -0.162
+50189.00     -0.233     -0.054      -0.017      -0.203
+50190.00     -0.269     -0.097      -0.020      -0.153
+50191.00     -0.315     -0.187      -0.092      -0.012
+50192.00     -0.361     -0.298      -0.217       0.046
+50193.00     -0.398     -0.395      -0.281      -0.164
+50194.00     -0.425     -0.457      -0.276      -0.267
+50195.00     -0.433     -0.471      -0.243      -0.417
+50196.00     -0.404     -0.413      -0.102      -0.332
+50197.00     -0.318     -0.262       0.030      -0.163
+50198.00     -0.193     -0.074       0.072       0.076
+50199.00     -0.111      0.031       0.092       0.215
+50200.00     -0.094      0.098       0.094       0.294
+50201.00     -0.119      0.150       0.083       0.297
+50202.00     -0.170      0.160       0.113       0.442
+50203.00     -0.228      0.122       0.072       0.341
+50204.00     -0.279      0.063       0.017       0.107
+50205.00     -0.301      0.004      -0.140      -0.207
+50206.00     -0.226      0.013      -0.346      -0.513
+50207.00     -0.065      0.095      -0.521      -0.467
+50208.00      0.107      0.195      -0.561      -0.250
+50209.00      0.211      0.250      -0.544      -0.108
+50210.00      0.171      0.191      -0.464      -0.020
+50211.00     -0.034      0.011      -0.271      -0.229
+50212.00     -0.221     -0.121      -0.064      -0.238
+50213.00     -0.326     -0.156       0.094      -0.121
+50214.00     -0.372     -0.146       0.075      -0.009
+50215.00     -0.375     -0.125       0.026       0.094
+50216.00     -0.346     -0.086      -0.068       0.146
+50217.00     -0.301     -0.014      -0.123       0.188
+50218.00     -0.262      0.072      -0.076       0.080
+50219.00     -0.239      0.143       0.010       0.131
+50220.00     -0.219      0.191      -0.022       0.196
+50221.00     -0.194      0.224      -0.040       0.029
+50222.00     -0.175      0.227      -0.029      -0.074
+50223.00     -0.165      0.185       0.036      -0.073
+50224.00     -0.151      0.097       0.111      -0.017
+50225.00     -0.122     -0.023       0.233       0.097
+50226.00     -0.105     -0.104       0.293       0.314
+50227.00     -0.107     -0.129       0.304       0.362
+50228.00     -0.117     -0.100       0.229       0.525
+50229.00     -0.125     -0.036       0.056       0.468
+50230.00     -0.142      0.024      -0.037       0.450
+50231.00     -0.172      0.050      -0.030       0.434
+50232.00     -0.208      0.055       0.039       0.212
+50233.00     -0.239      0.052       0.074      -0.040
+50234.00     -0.255      0.054      -0.012      -0.355
+50235.00     -0.257      0.072      -0.074      -0.317
+50236.00     -0.249      0.097      -0.117      -0.034
+50237.00     -0.231      0.096      -0.053       0.322
+50238.00     -0.204      0.032       0.067       0.291
+50239.00     -0.177     -0.092       0.098       0.100
+50240.00     -0.158     -0.181       0.251      -0.105
+50241.00     -0.148     -0.202       0.342      -0.138
+50242.00     -0.146     -0.191       0.349       0.002
+50243.00     -0.147     -0.174       0.229       0.118
+50244.00     -0.145     -0.145       0.008       0.132
+50245.00     -0.138     -0.087      -0.141       0.200
+50246.00     -0.124      0.037      -0.186       0.001
+50247.00     -0.092      0.333      -0.111      -0.241
+50248.00     -0.049      0.581      -0.044      -0.365
+50249.00     -0.003      0.622      -0.010      -0.422
+50250.00      0.035      0.512       0.068      -0.436
+50251.00      0.050      0.319       0.024      -0.280
+50252.00      0.044      0.116       0.063      -0.288
+50253.00      0.021     -0.034       0.114      -0.109
+50254.00     -0.029     -0.089       0.197       0.115
+50255.00     -0.117     -0.019       0.251       0.266
+50256.00     -0.220      0.158       0.180       0.271
+50257.00     -0.319      0.310      -0.024       0.313
+50258.00     -0.400      0.374      -0.219       0.251
+50259.00     -0.429      0.291      -0.181       0.123
+50260.00     -0.370      0.071      -0.026       0.065
+50261.00     -0.286     -0.062       0.056      -0.107
+50262.00     -0.219     -0.072       0.017      -0.323
+50263.00     -0.184     -0.034      -0.142      -0.378
+50264.00     -0.195      0.025      -0.273       0.000
+50265.00     -0.239      0.089      -0.291       0.303
+50266.00     -0.284      0.133      -0.285       0.377
+50267.00     -0.304      0.159      -0.222       0.241
+50268.00     -0.303      0.177      -0.139       0.026
+50269.00     -0.301      0.187      -0.019      -0.031
+50270.00     -0.307      0.172       0.060       0.116
+50271.00     -0.317      0.136       0.206      -0.003
+50272.00     -0.326      0.098       0.173       0.025
+50273.00     -0.332      0.074       0.076      -0.000
+50274.00     -0.336      0.080      -0.051       0.139
+50275.00     -0.352      0.143      -0.058      -0.030
+50276.00     -0.368      0.224       0.076      -0.063
+50277.00     -0.351      0.258       0.231       0.046
+50278.00     -0.296      0.235       0.240       0.216
+50279.00     -0.223      0.192       0.188       0.347
+50280.00     -0.146      0.163       0.111       0.353
+50281.00     -0.068      0.160       0.053       0.196
+50282.00     -0.025      0.189       0.126       0.323
+50283.00     -0.029      0.219       0.196       0.391
+50284.00     -0.057      0.239       0.161       0.503
+50285.00     -0.087      0.262       0.020       0.446
+50286.00     -0.118      0.268      -0.125       0.416
+50287.00     -0.150      0.207      -0.156       0.188
+50288.00     -0.171      0.070      -0.006      -0.020
+50289.00     -0.189     -0.010       0.174      -0.169
+50290.00     -0.202     -0.025       0.221      -0.464
+50291.00     -0.206     -0.043       0.204      -0.591
+50292.00     -0.214     -0.054       0.067      -0.479
+50293.00     -0.238     -0.055       0.007      -0.261
+50294.00     -0.263     -0.057      -0.007      -0.117
+50295.00     -0.264     -0.058      -0.059      -0.103
+50296.00     -0.236     -0.031      -0.146      -0.106
+50297.00     -0.203      0.012      -0.244       0.240
+50298.00     -0.185      0.049      -0.267       0.280
+50299.00     -0.186      0.081      -0.156       0.310
+50300.00     -0.209      0.114      -0.002       0.242
+50301.00     -0.249      0.125      -0.012       0.222
+50302.00     -0.304      0.090      -0.133       0.418
+50303.00     -0.386      0.026      -0.228       0.380
+50304.00     -0.451      0.007      -0.222       0.238
+50305.00     -0.462      0.041      -0.133       0.245
+50306.00     -0.417      0.086      -0.129       0.158
+50307.00     -0.339      0.132      -0.190       0.230
+50308.00     -0.254      0.171      -0.201       0.094
+50309.00     -0.171      0.178      -0.043      -0.012
+50310.00     -0.100      0.161       0.187       0.058
+50311.00     -0.056      0.129       0.341       0.197
+50312.00     -0.043      0.094       0.401       0.342
+50313.00     -0.054      0.073       0.398       0.455
+50314.00     -0.077      0.067       0.312       0.475
+50315.00     -0.111      0.064       0.191       0.346
+50316.00     -0.151      0.056       0.180       0.129
+50317.00     -0.191      0.038       0.319       0.033
+50318.00     -0.227      0.008       0.417      -0.150
+50319.00     -0.256     -0.022       0.380      -0.184
+50320.00     -0.270     -0.034       0.291      -0.171
+50321.00     -0.263     -0.024       0.185      -0.022
+50322.00     -0.228     -0.020       0.132      -0.149
+50323.00     -0.164     -0.026       0.081      -0.171
+50324.00     -0.112      0.007      -0.040      -0.072
+50325.00     -0.077      0.059      -0.186       0.207
+50326.00     -0.046      0.095      -0.242       0.465
+50327.00     -0.025      0.132      -0.114       0.521
+50328.00     -0.018      0.180       0.073       0.364
+50329.00     -0.016      0.213       0.186       0.136
+50330.00     -0.007      0.191       0.138       0.245
+50331.00     -0.025      0.114       0.135       0.284
+50332.00     -0.070     -0.015       0.092       0.292
+50333.00     -0.084     -0.025       0.099       0.301
+50334.00     -0.058      0.028       0.110       0.130
+50335.00     -0.024      0.044       0.034       0.197
+50336.00     -0.007      0.039      -0.032       0.095
+50337.00     -0.011      0.019      -0.092       0.039
+50338.00     -0.012     -0.016      -0.078       0.090
+50339.00      0.002     -0.022      -0.089       0.108
+50340.00      0.017      0.018      -0.087       0.196
+50341.00      0.024      0.067      -0.049       0.210
+50342.00      0.025      0.089      -0.011       0.217
+50343.00      0.016      0.060      -0.061       0.214
+50344.00     -0.010     -0.022      -0.026       0.010
+50345.00     -0.049     -0.074       0.145      -0.086
+50346.00     -0.082     -0.043       0.285      -0.052
+50347.00     -0.113      0.079       0.452      -0.065
+50348.00     -0.148      0.190       0.453       0.142
+50349.00     -0.173      0.215       0.432       0.155
+50350.00     -0.169      0.138       0.310       0.082
+50351.00     -0.133     -0.001       0.203       0.005
+50352.00     -0.102     -0.040       0.019      -0.065
+50353.00     -0.080      0.039      -0.224       0.175
+50354.00     -0.056      0.171      -0.379       0.482
+50355.00     -0.032      0.314      -0.358       0.533
+50356.00     -0.020      0.431      -0.215       0.497
+50357.00     -0.019      0.450      -0.023       0.263
+50358.00     -0.019      0.313       0.096       0.136
+50359.00     -0.020      0.165       0.168       0.242
+50360.00      0.005      0.110       0.146       0.339
+50361.00      0.032      0.057       0.178       0.264
+50362.00      0.015     -0.016       0.180       0.154
+50363.00     -0.048     -0.065       0.130       0.038
+50364.00     -0.131     -0.059       0.098       0.072
+50365.00     -0.201      0.017       0.034       0.073
+50366.00     -0.232      0.122      -0.027       0.119
+50367.00     -0.226      0.216      -0.108       0.094
+50368.00     -0.202      0.269      -0.102       0.137
+50369.00     -0.166      0.278      -0.071       0.142
+50370.00     -0.116      0.247      -0.009       0.188
+50371.00     -0.063      0.209       0.034       0.365
+50372.00     -0.025      0.195       0.108       0.474
+50373.00     -0.034      0.142       0.200       0.418
+50374.00     -0.079      0.072       0.318       0.288
+50375.00     -0.111      0.048       0.439       0.149
+50376.00     -0.120      0.126       0.495       0.239
+50377.00     -0.121      0.265       0.491       0.203
+50378.00     -0.110      0.337       0.371       0.154
+50379.00     -0.082      0.272       0.225       0.212
+50380.00     -0.058      0.199       0.148       0.223
+50381.00     -0.045      0.169       0.041       0.407
+50382.00     -0.036      0.155      -0.036       0.618
+50383.00     -0.029      0.147      -0.114       0.782
+50384.00     -0.019      0.151      -0.060       0.679
+50385.00     -0.007      0.162       0.036       0.376
+50386.00      0.009      0.146       0.144       0.156
+50387.00      0.032      0.091       0.196       0.138
+50388.00      0.058      0.029       0.233       0.275
+50389.00      0.082     -0.009       0.213       0.404
+50390.00      0.093     -0.011       0.185       0.304
+50391.00      0.083      0.047       0.186       0.173
+50392.00      0.047      0.169       0.212       0.188
+50393.00     -0.008      0.201       0.193       0.100
+50394.00     -0.052      0.146       0.175      -0.031
+50395.00     -0.051      0.081       0.146      -0.181
+50396.00     -0.050      0.099       0.115      -0.436
+50397.00     -0.074      0.185       0.089      -0.645
+50398.00     -0.096      0.250       0.132      -0.727
+50399.00     -0.087      0.222       0.147      -0.549
+50400.00     -0.035      0.077       0.179      -0.179
+50401.00      0.018      0.012       0.224      -0.050
+50402.00      0.073      0.049       0.352      -0.053
+50403.00      0.121      0.116       0.441      -0.184
+50404.00      0.142      0.174       0.487      -0.079
+50405.00      0.131      0.212       0.440      -0.077
+50406.00      0.090      0.206       0.294       0.065
+50407.00      0.031      0.133       0.137       0.187
+50408.00     -0.023      0.009       0.033       0.316
+50409.00     -0.110     -0.121       0.030       0.417
+50410.00     -0.284     -0.417       0.070       0.591
+50411.00     -0.505     -0.872       0.126       0.549
+50412.00     -0.658     -1.204       0.195       0.503
+50413.00     -0.627     -1.128       0.292       0.358
+50414.00     -0.356     -0.503       0.419       0.121
+50415.00     -0.090      0.076       0.589       0.001
+50416.00      0.065      0.360       0.679      -0.089
+50417.00      0.139      0.431       0.661      -0.039
+50418.00      0.151      0.343       0.669      -0.057
+50419.00      0.125      0.151       0.615      -0.185
+50420.00      0.089     -0.064       0.553      -0.274
+50421.00      0.061     -0.199       0.456      -0.350
+50422.00     -0.020     -0.101       0.302      -0.408
+50423.00     -0.135      0.134       0.238      -0.425
+50424.00     -0.196      0.301       0.154      -0.558
+50425.00     -0.173      0.341       0.110      -0.727
+50426.00     -0.099      0.292       0.085      -0.833
+50427.00     -0.020      0.197       0.079      -0.554
+50428.00      0.033      0.094       0.133      -0.117
+50429.00      0.061      0.029       0.255       0.077
+50430.00      0.071     -0.003       0.356       0.045
+50431.00      0.062     -0.010       0.466      -0.206
+50432.00      0.041      0.014       0.498      -0.317
+50433.00      0.019      0.066       0.476      -0.344
+50434.00     -0.004      0.120       0.353      -0.220
+50435.00     -0.029      0.156       0.182      -0.037
+50436.00     -0.055      0.163       0.028       0.167
+50437.00     -0.069      0.142      -0.092       0.279
+50438.00     -0.074      0.090      -0.164       0.463
+50439.00     -0.077      0.017      -0.202       0.371
+50440.00     -0.080     -0.049      -0.188       0.293
+50441.00     -0.074     -0.089      -0.156       0.078
+50442.00     -0.064     -0.114      -0.050      -0.010
+50443.00     -0.060     -0.142       0.126      -0.135
+50444.00     -0.059     -0.162       0.285      -0.095
+50445.00     -0.054     -0.151       0.333       0.087
+50446.00     -0.044     -0.114       0.350       0.074
+50447.00     -0.032     -0.075       0.313       0.016
+50448.00     -0.008     -0.042       0.234       0.002
+50449.00      0.031     -0.007       0.023      -0.023
+50450.00      0.069      0.022      -0.058       0.099
+50451.00      0.106      0.032      -0.073       0.147
+50452.00      0.154      0.028       0.002       0.012
+50453.00      0.217      0.026       0.086      -0.166
+50454.00      0.277      0.027       0.110      -0.364
+50455.00      0.311      0.022       0.162      -0.359
+50456.00      0.310      0.015       0.312      -0.015
+50457.00      0.269     -0.009       0.441       0.213
+50458.00      0.211     -0.041       0.519       0.354
+50459.00      0.149     -0.065       0.538       0.141
+50460.00      0.082     -0.062       0.420      -0.158
+50461.00      0.025     -0.038       0.298      -0.072
+50462.00     -0.007     -0.015       0.125      -0.144
+50463.00     -0.010      0.003       0.041      -0.054
+50464.00      0.002      0.030      -0.054       0.102
+50465.00      0.021      0.054      -0.200       0.221
+50466.00      0.052      0.052      -0.255       0.412
+50467.00      0.092      0.023      -0.263       0.275
+50468.00      0.124     -0.013      -0.147       0.118
+50469.00      0.139     -0.042      -0.042       0.045
+50470.00      0.133     -0.072       0.177      -0.067
+50471.00      0.097     -0.115       0.356      -0.035
+50472.00      0.061     -0.158       0.526      -0.104
+50473.00      0.045     -0.182       0.641      -0.065
+50474.00      0.040     -0.182       0.640      -0.075
+50475.00      0.033     -0.170       0.572      -0.045
+50476.00      0.025     -0.158       0.424      -0.044
+50477.00      0.016     -0.150       0.236      -0.095
+50478.00      0.000     -0.157       0.025      -0.135
+50479.00     -0.014     -0.177      -0.081      -0.013
+50480.00     -0.010     -0.185      -0.107      -0.010
+50481.00      0.008     -0.170      -0.149      -0.079
+50482.00      0.018     -0.155      -0.228      -0.318
+50483.00      0.021     -0.156      -0.247      -0.396
+50484.00      0.030     -0.132      -0.065      -0.209
+50485.00      0.043     -0.000       0.200       0.134
+50486.00      0.037      0.144       0.351       0.438
+50487.00      0.004      0.161       0.347       0.309
+50488.00     -0.036      0.085       0.195       0.240
+50489.00     -0.061     -0.020       0.063       0.192
+50490.00     -0.045     -0.118      -0.005       0.110
+50491.00      0.022     -0.157      -0.029       0.014
+50492.00      0.102     -0.087      -0.024      -0.025
+50493.00      0.143      0.025      -0.101      -0.010
+50494.00      0.131      0.072      -0.265       0.191
+50495.00      0.089      0.052      -0.354       0.310
+50496.00      0.032      0.003      -0.285       0.181
+50497.00     -0.027     -0.046      -0.131       0.086
+50498.00     -0.064     -0.063      -0.004       0.014
+50499.00     -0.062     -0.025       0.067       0.054
+50500.00     -0.035      0.031       0.135      -0.051
+50501.00     -0.001      0.045       0.189      -0.182
+50502.00      0.033      0.006       0.227      -0.149
+50503.00      0.054     -0.065       0.205      -0.115
+50504.00      0.058     -0.142       0.162      -0.153
+50505.00      0.057     -0.215       0.101      -0.147
+50506.00      0.057     -0.288       0.041      -0.181
+50507.00      0.065     -0.354       0.115      -0.178
+50508.00      0.090     -0.385       0.152      -0.245
+50509.00      0.117     -0.367       0.211      -0.303
+50510.00      0.113     -0.341       0.105      -0.327
+50511.00      0.076     -0.346       0.116      -0.493
+50512.00      0.039     -0.357       0.219      -0.400
+50513.00      0.021     -0.324       0.428      -0.135
+50514.00      0.001     -0.250       0.548       0.205
+50515.00     -0.035     -0.180       0.525       0.300
+50516.00     -0.079     -0.136       0.328       0.264
+50517.00     -0.114     -0.109       0.084       0.225
+50518.00     -0.135     -0.101       0.014       0.214
+50519.00     -0.143     -0.109       0.026       0.006
+50520.00     -0.138     -0.125       0.030      -0.244
+50521.00     -0.119     -0.142      -0.103      -0.461
+50522.00     -0.086     -0.160      -0.263      -0.399
+50523.00     -0.045     -0.174      -0.338      -0.293
+50524.00     -0.014     -0.173      -0.223      -0.188
+50525.00     -0.006     -0.155      -0.097      -0.105
+50526.00     -0.022     -0.124       0.004       0.010
+50527.00     -0.053     -0.136       0.013       0.181
+50528.00     -0.083     -0.132       0.033       0.094
+50529.00     -0.099     -0.102       0.046       0.073
+50530.00     -0.099     -0.087       0.112       0.003
+50531.00     -0.095     -0.089       0.117       0.042
+50532.00     -0.101     -0.090       0.058       0.059
+50533.00     -0.116     -0.094       0.027      -0.024
+50534.00     -0.125     -0.097       0.014      -0.134
+50535.00     -0.126     -0.098       0.042      -0.143
+50536.00     -0.116     -0.082       0.016      -0.232
+50537.00     -0.097     -0.042       0.022      -0.244
+50538.00     -0.087     -0.007      -0.014      -0.228
+50539.00     -0.100     -0.022      -0.073      -0.160
+50540.00     -0.118     -0.094      -0.115      -0.075
+50541.00     -0.107     -0.191      -0.124       0.031
+50542.00     -0.069     -0.247      -0.077       0.182
+50543.00     -0.029     -0.246      -0.063       0.070
+50544.00     -0.009     -0.211      -0.142      -0.075
+50545.00     -0.012     -0.164      -0.169       0.055
+50546.00     -0.043     -0.135      -0.229       0.066
+50547.00     -0.103     -0.137      -0.214       0.063
+50548.00     -0.166     -0.177      -0.239      -0.202
+50549.00     -0.208     -0.241      -0.368      -0.471
+50550.00     -0.222     -0.306      -0.480      -0.581
+50551.00     -0.215     -0.347      -0.533      -0.436
+50552.00     -0.200     -0.351      -0.440      -0.272
+50553.00     -0.176     -0.325      -0.294      -0.109
+50554.00     -0.137     -0.273      -0.250      -0.079
+50555.00     -0.091     -0.167      -0.298       0.053
+50556.00     -0.072     -0.051      -0.366       0.029
+50557.00     -0.080      0.023      -0.263      -0.014
+50558.00     -0.093      0.033      -0.173      -0.040
+50559.00     -0.101     -0.010      -0.115      -0.017
+50560.00     -0.106     -0.065       0.015      -0.024
+50561.00     -0.103     -0.115       0.069       0.041
+50562.00     -0.093     -0.149       0.115      -0.032
+50563.00     -0.084     -0.165       0.137       0.021
+50564.00     -0.087     -0.153       0.150       0.047
+50565.00     -0.101     -0.116       0.185       0.007
+50566.00     -0.119     -0.071       0.187      -0.091
+50567.00     -0.148     -0.038       0.133      -0.110
+50568.00     -0.195     -0.024      -0.013      -0.038
+50569.00     -0.245     -0.036      -0.216      -0.026
+50570.00     -0.250     -0.081      -0.422      -0.126
+50571.00     -0.207     -0.128      -0.519      -0.281
+50572.00     -0.153     -0.144      -0.423      -0.428
+50573.00     -0.116     -0.134      -0.305      -0.343
+50574.00     -0.112     -0.132      -0.114      -0.195
+50575.00     -0.141     -0.156      -0.029      -0.197
+50576.00     -0.174     -0.195       0.001      -0.288
+50577.00     -0.197     -0.231      -0.085      -0.604
+50578.00     -0.210     -0.250      -0.217      -0.860
+50579.00     -0.223     -0.246      -0.237      -0.845
+50580.00     -0.240     -0.218      -0.210      -0.612
+50581.00     -0.249     -0.185      -0.167      -0.404
+50582.00     -0.240     -0.164      -0.186      -0.218
+50583.00     -0.219     -0.154      -0.271      -0.049
+50584.00     -0.203     -0.131      -0.313       0.067
+50585.00     -0.194     -0.097      -0.367       0.172
+50586.00     -0.181     -0.076      -0.270       0.257
+50587.00     -0.166     -0.076      -0.226       0.101
+50588.00     -0.155     -0.077      -0.194       0.037
+50589.00     -0.150     -0.069      -0.158      -0.041
+50590.00     -0.145     -0.065      -0.209      -0.161
+50591.00     -0.140     -0.067      -0.261      -0.061
+50592.00     -0.145     -0.067      -0.354       0.116
+50593.00     -0.164     -0.070      -0.355       0.139
+50594.00     -0.189     -0.100      -0.250       0.002
+50595.00     -0.209     -0.168      -0.171      -0.080
+50596.00     -0.221     -0.257      -0.127       0.003
+50597.00     -0.225     -0.364      -0.241       0.045
+50598.00     -0.221     -0.488      -0.342       0.158
+50599.00     -0.208     -0.598      -0.471       0.008
+50600.00     -0.193     -0.639      -0.493      -0.021
+50601.00     -0.184     -0.580      -0.333      -0.015
+50602.00     -0.181     -0.431      -0.133       0.140
+50603.00     -0.172     -0.227      -0.020       0.127
+50604.00     -0.140     -0.073       0.032       0.212
+50605.00     -0.090      0.020      -0.010       0.071
+50606.00     -0.042      0.076      -0.010      -0.098
+50607.00     -0.012      0.100      -0.026      -0.185
+50608.00      0.003      0.108       0.063      -0.068
+50609.00      0.012      0.109       0.104       0.078
+50610.00      0.013      0.109       0.102       0.274
+50611.00     -0.000      0.117       0.028       0.300
+50612.00     -0.025      0.146      -0.157       0.489
+50613.00     -0.050      0.189      -0.248       0.566
+50614.00     -0.070      0.213      -0.303       0.702
+50615.00     -0.089      0.184      -0.227       0.644
+50616.00     -0.101      0.101      -0.083       0.394
+50617.00     -0.098     -0.016       0.031       0.160
+50618.00     -0.078     -0.097       0.073       0.096
+50619.00     -0.051     -0.126       0.081       0.147
+50620.00     -0.022     -0.111       0.090       0.366
+50621.00      0.001     -0.067       0.109       0.526
+50622.00      0.016     -0.026       0.152       0.332
+50623.00      0.021     -0.008       0.208       0.122
+50624.00      0.022     -0.002       0.196       0.126
+50625.00      0.020      0.001       0.124       0.241
+50626.00      0.011     -0.012      -0.090       0.377
+50627.00     -0.007     -0.053      -0.327       0.491
+50628.00     -0.030     -0.107      -0.516       0.335
+50629.00     -0.056     -0.154      -0.449       0.259
+50630.00     -0.087     -0.193      -0.229       0.222
+50631.00     -0.121     -0.232      -0.020       0.024
+50632.00     -0.142     -0.259       0.112       0.022
+50633.00     -0.146     -0.258       0.125      -0.021
+50634.00     -0.148     -0.229       0.093      -0.115
+50635.00     -0.166     -0.190       0.044       0.253
+50636.00     -0.196     -0.147       0.003       0.211
+50637.00     -0.229     -0.107      -0.061       0.190
+50638.00     -0.275     -0.092      -0.159       0.114
+50639.00     -0.337     -0.116      -0.258      -0.021
+50640.00     -0.348     -0.113      -0.458      -0.143
+50641.00     -0.286     -0.055      -0.663      -0.179
+50642.00     -0.193      0.012      -0.716      -0.260
+50643.00     -0.117      0.019      -0.610      -0.327
+50644.00     -0.085     -0.072      -0.334      -0.414
+50645.00     -0.103     -0.236      -0.066      -0.578
+50646.00     -0.128     -0.356       0.020      -0.671
+50647.00     -0.155     -0.402       0.035      -0.550
+50648.00     -0.184     -0.392       0.022      -0.249
+50649.00     -0.203     -0.337       0.068       0.099
+50650.00     -0.196     -0.257       0.073       0.305
+50651.00     -0.157     -0.163       0.070       0.136
+50652.00     -0.085     -0.049       0.070       0.037
+50653.00      0.015      0.085      -0.024       0.050
+50654.00      0.072      0.163      -0.067       0.103
+50655.00      0.059      0.162      -0.233       0.167
+50656.00     -0.005      0.104      -0.395      -0.006
+50657.00     -0.093      0.012      -0.474      -0.095
+50658.00     -0.183     -0.095      -0.391      -0.197
+50659.00     -0.264     -0.194      -0.189      -0.221
+50660.00     -0.316     -0.258       0.044      -0.257
+50661.00     -0.328     -0.280       0.234      -0.191
+50662.00     -0.303     -0.274       0.301       0.044
+50663.00     -0.264     -0.246       0.259       0.079
+50664.00     -0.216     -0.198       0.165      -0.006
+50665.00     -0.159     -0.146       0.059       0.088
+50666.00     -0.105     -0.127       0.026      -0.000
+50667.00     -0.088     -0.146      -0.073      -0.022
+50668.00     -0.104     -0.177      -0.245       0.043
+50669.00     -0.128     -0.182      -0.414       0.088
+50670.00     -0.156     -0.157      -0.540       0.074
+50671.00     -0.193     -0.142      -0.451       0.204
+50672.00     -0.224     -0.157      -0.191       0.155
+50673.00     -0.232     -0.193       0.039       0.091
+50674.00     -0.225     -0.248       0.107      -0.024
+50675.00     -0.226     -0.317      -0.032      -0.025
+50676.00     -0.247     -0.381      -0.097       0.079
+50677.00     -0.286     -0.419      -0.075       0.249
+50678.00     -0.331     -0.424      -0.101       0.265
+50679.00     -0.372     -0.377      -0.186       0.010
+50680.00     -0.415     -0.244      -0.274      -0.242
+50681.00     -0.471     -0.019      -0.317      -0.293
+50682.00     -0.508      0.165      -0.291      -0.330
+50683.00     -0.510      0.257      -0.170      -0.412
+50684.00     -0.485      0.286      -0.066      -0.333
+50685.00     -0.436      0.239      -0.072      -0.283
+50686.00     -0.356      0.084      -0.017      -0.023
+50687.00     -0.253     -0.160       0.119       0.090
+50688.00     -0.162     -0.363       0.440       0.186
+50689.00     -0.092     -0.476       0.689       0.109
+50690.00     -0.038     -0.523       0.862       0.092
+50691.00     -0.009     -0.515       0.851       0.179
+50692.00     -0.014     -0.453       0.766      -0.076
+50693.00     -0.048     -0.358       0.625      -0.284
+50694.00     -0.106     -0.264       0.392      -0.363
+50695.00     -0.194     -0.207       0.212      -0.315
+50696.00     -0.269     -0.177      -0.104      -0.028
+50697.00     -0.303     -0.140      -0.415       0.041
+50698.00     -0.300     -0.086      -0.681       0.228
+50699.00     -0.277     -0.037      -0.705       0.275
+50700.00     -0.243     -0.016      -0.525       0.105
+50701.00     -0.205     -0.023      -0.241       0.069
+50702.00     -0.177     -0.055      -0.066      -0.058
+50703.00     -0.166     -0.100       0.036      -0.181
+50704.00     -0.168     -0.130       0.124      -0.083
+50705.00     -0.179     -0.128       0.262      -0.010
+50706.00     -0.197     -0.103       0.355       0.180
+50707.00     -0.210     -0.061       0.328       0.154
+50708.00     -0.208      0.010       0.167       0.048
+50709.00     -0.203      0.080      -0.030       0.108
+50710.00     -0.200      0.125      -0.092      -0.012
+50711.00     -0.195      0.160      -0.001      -0.285
+50712.00     -0.189      0.215       0.114      -0.510
+50713.00     -0.186      0.275       0.130      -0.624
+50714.00     -0.169      0.283       0.055      -0.237
+50715.00     -0.128      0.219       0.067       0.184
+50716.00     -0.075      0.108       0.212       0.312
+50717.00     -0.022     -0.018       0.430       0.432
+50718.00      0.031     -0.153       0.559       0.436
+50719.00      0.082     -0.289       0.539       0.364
+50720.00      0.118     -0.401       0.437       0.200
+50721.00      0.134     -0.470       0.307      -0.016
+50722.00      0.136     -0.478       0.223      -0.254
+50723.00      0.119     -0.408       0.029      -0.214
+50724.00      0.076     -0.272      -0.147      -0.132
+50725.00      0.019     -0.100      -0.275      -0.032
+50726.00     -0.031      0.073      -0.380      -0.083
+50727.00     -0.064      0.208      -0.372       0.038
+50728.00     -0.072      0.274      -0.254       0.072
+50729.00     -0.050      0.256      -0.022       0.199
+50730.00     -0.025      0.216       0.124       0.275
+50731.00     -0.015      0.188       0.229       0.408
+50732.00     -0.014      0.185       0.226       0.641
+50733.00     -0.017      0.210       0.255       0.652
+50734.00     -0.032      0.233       0.162       0.575
+50735.00     -0.065      0.233       0.027       0.451
+50736.00     -0.109      0.209      -0.145       0.241
+50737.00     -0.149      0.174      -0.423       0.298
+50738.00     -0.178      0.127      -0.538       0.134
+50739.00     -0.191      0.075      -0.554      -0.136
+50740.00     -0.190      0.047      -0.408      -0.401
+50741.00     -0.173      0.051      -0.282      -0.652
+50742.00     -0.128      0.063      -0.228      -0.356
+50743.00     -0.052      0.070      -0.134       0.198
+50744.00      0.022      0.054       0.046       0.613
+50745.00      0.071      0.025       0.295       0.762
+50746.00      0.102     -0.016       0.442       0.713
+50747.00      0.119     -0.061       0.461       0.686
+50748.00      0.110     -0.090       0.329       0.534
+50749.00      0.067     -0.083       0.243       0.364
+50750.00     -0.006     -0.024       0.065       0.104
+50751.00     -0.106      0.081      -0.149      -0.092
+50752.00     -0.208      0.127      -0.310      -0.288
+50753.00     -0.269      0.140      -0.375      -0.293
+50754.00     -0.275      0.143      -0.454      -0.440
+50755.00     -0.241      0.134      -0.415      -0.363
+50756.00     -0.190      0.123      -0.345      -0.196
+50757.00     -0.136      0.103      -0.193      -0.068
+50758.00     -0.086      0.057       0.002       0.112
+50759.00     -0.049     -0.009       0.215       0.254
+50760.00     -0.028     -0.064       0.282       0.354
+50761.00     -0.019     -0.092       0.263       0.370
+50762.00     -0.014     -0.100       0.179       0.278
+50763.00     -0.012     -0.083       0.153      -0.024
+50764.00     -0.013     -0.008       0.090      -0.045
+50765.00     -0.011      0.138      -0.017       0.095
+50766.00     -0.012      0.223      -0.063       0.226
+50767.00     -0.015      0.197      -0.109       0.189
+50768.00     -0.010      0.121      -0.072      -0.072
+50769.00      0.015      0.049      -0.031      -0.247
+50770.00      0.074      0.025       0.065      -0.204
+50771.00      0.175      0.054       0.134       0.054
+50772.00      0.307      0.028       0.234       0.418
+50773.00      0.409     -0.044       0.369       0.697
+50774.00      0.422     -0.098       0.466       0.673
+50775.00      0.364     -0.124       0.400       0.562
+50776.00      0.265     -0.118       0.320       0.369
+50777.00      0.158     -0.087       0.197       0.200
+50778.00      0.076     -0.053       0.048       0.002
+50779.00      0.030     -0.039      -0.101      -0.438
+50780.00      0.015     -0.037      -0.230      -0.650
+50781.00      0.031     -0.039      -0.291      -0.725
+50782.00      0.072     -0.045      -0.247      -0.715
+50783.00      0.115     -0.036      -0.194      -0.398
+50784.00      0.126      0.021      -0.121      -0.124
+50785.00      0.086      0.127       0.008       0.095
+50786.00     -0.000      0.264       0.211       0.175
+50787.00     -0.107      0.403       0.418       0.214
+50788.00     -0.214      0.533       0.552       0.380
+50789.00     -0.304      0.627       0.498       0.451
+50790.00     -0.345      0.626       0.424       0.377
+50791.00     -0.299      0.483       0.291       0.296
+50792.00     -0.158      0.213       0.289       0.243
+50793.00     -0.026      0.000       0.252       0.298
+50794.00      0.057     -0.112       0.258       0.566
+50795.00      0.106     -0.161       0.223       0.529
+50796.00      0.137     -0.155       0.161       0.361
+50797.00      0.162     -0.100       0.155       0.155
+50798.00      0.185     -0.029       0.154       0.018
+50799.00      0.206      0.014       0.196       0.068
+50800.00      0.224     -0.023       0.232       0.233
+50801.00      0.241     -0.122       0.227       0.549
+50802.00      0.254     -0.244       0.206       0.533
+50803.00      0.254     -0.346       0.186       0.538
+50804.00      0.224     -0.369       0.164       0.459
+50805.00      0.151     -0.256       0.081       0.422
+50806.00      0.041     -0.014       0.002       0.253
+50807.00     -0.052      0.169      -0.035      -0.117
+50808.00     -0.100      0.248      -0.104      -0.451
+50809.00     -0.099      0.260      -0.097      -0.596
+50810.00     -0.055      0.229      -0.079      -0.615
+50811.00      0.007      0.174      -0.034      -0.236
+50812.00      0.065      0.116      -0.038       0.039
+50813.00      0.106      0.065      -0.016       0.194
+50814.00      0.132      0.008       0.157       0.091
+50815.00      0.155     -0.061       0.224      -0.107
+50816.00      0.177     -0.118       0.325      -0.300
+50817.00      0.192     -0.138       0.381      -0.228
+50818.00      0.194     -0.140       0.340      -0.172
+50819.00      0.184     -0.150       0.315      -0.114
+50820.00      0.173     -0.166       0.308      -0.240
+50821.00      0.161     -0.180       0.273      -0.105
+50822.00      0.142     -0.197       0.261       0.069
+50823.00      0.110     -0.219       0.200       0.081
+50824.00      0.075     -0.223       0.126       0.154
+50825.00      0.049     -0.182       0.030       0.026
+50826.00      0.033     -0.097       0.015       0.018
+50827.00      0.018      0.012       0.109       0.128
+50828.00      0.013      0.085       0.146       0.346
+50829.00      0.022      0.125       0.119       0.588
+50830.00      0.040      0.144       0.076       0.683
+50831.00      0.052      0.129       0.092       0.527
+50832.00      0.054      0.088       0.106       0.367
+50833.00      0.046      0.039       0.119       0.227
+50834.00      0.022     -0.006       0.092       0.070
+50835.00     -0.018     -0.043       0.120      -0.182
+50836.00     -0.059     -0.063       0.139      -0.463
+50837.00     -0.086     -0.053       0.144      -0.786
+50838.00     -0.099     -0.024       0.143      -0.872
+50839.00     -0.098     -0.003       0.071      -0.707
+50840.00     -0.068     -0.005       0.064      -0.288
+50841.00     -0.002     -0.037      -0.015       0.015
+50842.00      0.059     -0.082      -0.128       0.214
+50843.00      0.067     -0.105      -0.307       0.004
+50844.00      0.008     -0.056      -0.423      -0.044
+50845.00     -0.080      0.048      -0.359      -0.066
+50846.00     -0.155      0.154      -0.273       0.184
+50847.00     -0.184      0.195      -0.187       0.269
+50848.00     -0.146      0.150      -0.087       0.235
+50849.00     -0.070      0.111      -0.042       0.191
+50850.00      0.002      0.086       0.029       0.226
+50851.00      0.051      0.054       0.063       0.102
+50852.00      0.076      0.023       0.040       0.012
+50853.00      0.084      0.004      -0.005      -0.096
+50854.00      0.085     -0.015      -0.022      -0.171
+50855.00      0.079     -0.061      -0.002      -0.007
+50856.00      0.071     -0.132      -0.022      -0.029
+50857.00      0.060     -0.181      -0.057       0.052
+50858.00      0.033     -0.171      -0.072       0.249
+50859.00     -0.016     -0.133      -0.078       0.261
+50860.00     -0.073     -0.094      -0.058       0.372
+50861.00     -0.116     -0.062      -0.046       0.173
+50862.00     -0.136     -0.030      -0.069       0.170
+50863.00     -0.130      0.002      -0.071       0.034
+50864.00     -0.098      0.046      -0.063      -0.315
+50865.00     -0.054      0.108      -0.088      -0.715
+50866.00     -0.022      0.151      -0.229      -1.053
+50867.00     -0.011      0.132      -0.257      -0.992
+50868.00     -0.002      0.054      -0.064      -0.622
+50869.00      0.011     -0.050       0.056      -0.144
+50870.00      0.018     -0.112       0.016       0.211
+50871.00      0.009     -0.134      -0.244       0.249
+50872.00     -0.012     -0.131      -0.386       0.004
+50873.00     -0.029     -0.101      -0.430       0.020
+50874.00     -0.031     -0.054      -0.280       0.008
+50875.00     -0.024     -0.003      -0.108       0.053
+50876.00     -0.024      0.056       0.006       0.023
+50877.00     -0.035      0.112      -0.037       0.039
+50878.00     -0.045      0.140      -0.044       0.057
+50879.00     -0.042      0.129       0.024      -0.011
+50880.00     -0.034      0.097       0.085      -0.075
+50881.00     -0.033      0.064       0.127      -0.060
+50882.00     -0.040      0.038       0.131      -0.014
+50883.00     -0.056      0.013       0.048       0.120
+50884.00     -0.075     -0.010      -0.054       0.181
+50885.00     -0.076     -0.008      -0.163       0.199
+50886.00     -0.061      0.021      -0.197       0.176
+50887.00     -0.045      0.056      -0.196       0.259
+50888.00     -0.029      0.083      -0.181       0.294
+50889.00     -0.001      0.096      -0.089       0.211
+50890.00      0.036      0.092       0.053       0.118
+50891.00      0.070      0.075       0.218       0.151
+50892.00      0.098      0.064       0.380       0.057
+50893.00      0.113      0.078       0.356      -0.086
+50894.00      0.097      0.080       0.199      -0.298
+50895.00      0.060      0.027       0.019      -0.478
+50896.00      0.045     -0.052       0.002      -0.286
+50897.00      0.072     -0.082       0.050       0.044
+50898.00      0.105     -0.043       0.025       0.401
+50899.00      0.095      0.005      -0.204       0.476
+50900.00      0.050      0.022      -0.429       0.301
+50901.00      0.002      0.015      -0.445       0.222
+50902.00     -0.035     -0.012      -0.258       0.077
+50903.00     -0.047     -0.069      -0.014      -0.039
+50904.00     -0.020     -0.150       0.130      -0.129
+50905.00      0.053     -0.252       0.095      -0.212
+50906.00      0.125     -0.344      -0.000      -0.119
+50907.00      0.140     -0.388       0.011      -0.006
+50908.00      0.106     -0.382       0.156       0.040
+50909.00      0.040     -0.332       0.224      -0.016
+50910.00     -0.030     -0.247       0.137      -0.080
+50911.00     -0.077     -0.137      -0.042       0.040
+50912.00     -0.074     -0.022      -0.201      -0.015
+50913.00     -0.020      0.060      -0.274      -0.123
+50914.00      0.065      0.087      -0.317      -0.156
+50915.00      0.140      0.061      -0.256      -0.127
+50916.00      0.167      0.007      -0.198       0.015
+50917.00      0.124     -0.061      -0.104      -0.042
+50918.00      0.007     -0.132       0.039      -0.028
+50919.00     -0.123     -0.164       0.279      -0.088
+50920.00     -0.234     -0.140       0.459      -0.011
+50921.00     -0.318     -0.066       0.530       0.004
+50922.00     -0.378      0.014       0.378      -0.047
+50923.00     -0.407      0.033       0.184      -0.212
+50924.00     -0.368     -0.021       0.022      -0.217
+50925.00     -0.241     -0.092      -0.076      -0.092
+50926.00     -0.112     -0.106      -0.180       0.141
+50927.00     -0.035     -0.069      -0.324       0.066
+50928.00     -0.002     -0.018      -0.414       0.075
+50929.00      0.010      0.032      -0.409       0.125
+50930.00      0.007      0.079      -0.209       0.186
+50931.00     -0.009      0.105      -0.047       0.193
+50932.00     -0.017      0.101       0.040       0.022
+50933.00      0.005      0.065      -0.083       0.017
+50934.00      0.056      0.005      -0.168       0.046
+50935.00      0.112     -0.063      -0.146       0.182
+50936.00      0.146     -0.120      -0.010       0.167
+50937.00      0.142     -0.156       0.158       0.190
+50938.00      0.100     -0.158       0.141       0.149
+50939.00      0.021     -0.113      -0.025       0.106
+50940.00     -0.065     -0.091      -0.231       0.042
+50941.00     -0.134     -0.090      -0.369      -0.053
+50942.00     -0.167     -0.111      -0.337      -0.210
+50943.00     -0.166     -0.152      -0.287      -0.245
+50944.00     -0.148     -0.185      -0.182      -0.161
+50945.00     -0.121     -0.188      -0.056      -0.234
+50946.00     -0.078     -0.167       0.060      -0.223
+50947.00     -0.037     -0.134       0.255      -0.118
+50948.00     -0.013     -0.092       0.419       0.005
+50949.00     -0.006     -0.042       0.613       0.119
+50950.00     -0.006      0.002       0.626       0.156
+50951.00     -0.014      0.013       0.464       0.180
+50952.00     -0.029     -0.019       0.216       0.111
+50953.00     -0.041     -0.079      -0.062       0.082
+50954.00     -0.045     -0.144      -0.266      -0.083
+50955.00     -0.048     -0.177      -0.350      -0.214
+50956.00     -0.056     -0.175      -0.343      -0.268
+50957.00     -0.063     -0.156      -0.217      -0.070
+50958.00     -0.064     -0.140      -0.041       0.043
+50959.00     -0.061     -0.138       0.072       0.127
+50960.00     -0.054     -0.147       0.075      -0.003
+50961.00     -0.036     -0.151      -0.010      -0.183
+50962.00     -0.006     -0.148      -0.069      -0.232
+50963.00      0.022     -0.133      -0.072      -0.161
+50964.00      0.033     -0.108       0.107      -0.125
+50965.00      0.028     -0.089       0.310      -0.024
+50966.00      0.024     -0.092       0.293      -0.119
+50967.00      0.020     -0.110       0.144      -0.127
+50968.00      0.004     -0.114      -0.107      -0.220
+50969.00     -0.021     -0.104      -0.196      -0.134
+50970.00     -0.032     -0.104      -0.244      -0.185
+50971.00     -0.019     -0.124      -0.158      -0.334
+50972.00      0.007     -0.143      -0.100      -0.316
+50973.00      0.042     -0.147       0.042      -0.200
+50974.00      0.098     -0.142       0.182      -0.112
+50975.00      0.170     -0.128       0.288       0.090
+50976.00      0.230     -0.105       0.444       0.153
+50977.00      0.259     -0.080       0.539       0.261
+50978.00      0.258     -0.072       0.639       0.334
+50979.00      0.232     -0.087       0.616       0.287
+50980.00      0.161     -0.120       0.402       0.194
+50981.00      0.040     -0.152       0.078       0.112
+50982.00     -0.065     -0.111      -0.270      -0.156
+50983.00     -0.111      0.026      -0.415      -0.493
+50984.00     -0.108      0.225      -0.356      -0.626
+50985.00     -0.079      0.414      -0.235      -0.387
+50986.00     -0.036      0.489      -0.055      -0.217
+50987.00      0.006      0.361       0.020      -0.070
+50988.00      0.023      0.033       0.062      -0.175
+50989.00     -0.009     -0.286       0.002      -0.426
+50990.00     -0.086     -0.507      -0.020      -0.618
+50991.00     -0.185     -0.638      -0.024      -0.662
+50992.00     -0.281     -0.675       0.068      -0.636
+50993.00     -0.341     -0.620       0.205      -0.559
+50994.00     -0.336     -0.485       0.252      -0.458
+50995.00     -0.260     -0.279       0.194      -0.476
+50996.00     -0.196     -0.066       0.094      -0.181
+50997.00     -0.150      0.082      -0.034      -0.017
+50998.00     -0.096      0.139      -0.037       0.042
+50999.00     -0.035      0.120      -0.007      -0.004
+51000.00      0.024      0.055      -0.097      -0.254
+51001.00      0.072     -0.017       0.012      -0.269
+51002.00      0.113     -0.071       0.170      -0.093
+51003.00      0.142     -0.088       0.221       0.089
+51004.00      0.147     -0.062       0.257       0.319
+51005.00      0.122     -0.015       0.311       0.196
+51006.00      0.077      0.018       0.405       0.164
+51007.00      0.028      0.015       0.450      -0.054
+51008.00     -0.016     -0.012       0.403      -0.081
+51009.00     -0.059     -0.050       0.187      -0.157
+51010.00     -0.102     -0.111      -0.066      -0.167
+51011.00     -0.112     -0.229      -0.293      -0.318
+51012.00     -0.083     -0.377      -0.344      -0.512
+51013.00     -0.036     -0.490      -0.286      -0.458
+51014.00      0.004     -0.536      -0.156      -0.294
+51015.00      0.015     -0.490      -0.028      -0.170
+51016.00     -0.018     -0.320      -0.062      -0.105
+51017.00     -0.057     -0.137      -0.079      -0.291
+51018.00     -0.089     -0.006      -0.100      -0.415
+51019.00     -0.118      0.066      -0.090      -0.481
+51020.00     -0.136      0.083      -0.058      -0.481
+51021.00     -0.138      0.057      -0.015      -0.458
+51022.00     -0.130     -0.014      -0.038      -0.326
+51023.00     -0.127     -0.138      -0.152      -0.169
+51024.00     -0.127     -0.284      -0.413      -0.091
+51025.00     -0.118     -0.364      -0.697      -0.056
+51026.00     -0.096     -0.361      -0.890      -0.042
+51027.00     -0.072     -0.322      -0.846      -0.269
+51028.00     -0.052     -0.271      -0.626      -0.346
+51029.00     -0.031     -0.211      -0.280      -0.316
+51030.00     -0.006     -0.152       0.048      -0.164
+51031.00      0.015     -0.123       0.176       0.175
+51032.00      0.024     -0.130       0.248       0.515
+51033.00      0.019     -0.163       0.271       0.560
+51034.00      0.004     -0.219       0.337       0.378
+51035.00     -0.023     -0.290       0.285       0.034
+51036.00     -0.062     -0.340       0.222      -0.166
+51037.00     -0.113     -0.326       0.074      -0.277
+51038.00     -0.186     -0.243      -0.158      -0.219
+51039.00     -0.272     -0.135      -0.393      -0.219
+51040.00     -0.349     -0.039      -0.536      -0.378
+51041.00     -0.391      0.031      -0.536      -0.318
+51042.00     -0.389      0.056      -0.413      -0.300
+51043.00     -0.346      0.009      -0.212      -0.165
+51044.00     -0.266     -0.112      -0.086      -0.182
+51045.00     -0.195     -0.212      -0.017      -0.186
+51046.00     -0.146     -0.264      -0.044      -0.372
+51047.00     -0.116     -0.287      -0.015      -0.521
+51048.00     -0.097     -0.286       0.012      -0.696
+51049.00     -0.079     -0.266       0.037      -0.835
+51050.00     -0.062     -0.250       0.002      -0.768
+51051.00     -0.057     -0.260       0.001      -0.476
+51052.00     -0.074     -0.245      -0.128      -0.124
+51053.00     -0.079     -0.201      -0.318       0.088
+51054.00     -0.061     -0.146      -0.502       0.194
+51055.00     -0.042     -0.111      -0.480       0.195
+51056.00     -0.028     -0.115      -0.261       0.141
+51057.00     -0.009     -0.130      -0.028      -0.489
+51058.00      0.012     -0.124       0.080      -0.202
+51059.00      0.018     -0.104       0.104       0.344
+51060.00      0.000     -0.087       0.103       0.763
+51061.00     -0.028     -0.085       0.138       0.854
+51062.00     -0.056     -0.102       0.126       0.789
+51063.00     -0.079     -0.141       0.028       0.277
+51064.00     -0.102     -0.195      -0.066      -0.034
+51065.00     -0.124     -0.253      -0.085      -0.325
+51066.00     -0.141     -0.315      -0.111      -0.309
+51067.00     -0.151     -0.374      -0.135      -0.432
+51068.00     -0.155     -0.410      -0.161      -0.593
+51069.00     -0.149     -0.415      -0.246      -0.612
+51070.00     -0.126     -0.391      -0.213      -0.479
+51071.00     -0.098     -0.326      -0.115      -0.362
+51072.00     -0.083     -0.190      -0.032      -0.208
+51073.00     -0.080      0.026      -0.043      -0.014
+51074.00     -0.083      0.215      -0.092       0.118
+51075.00     -0.092      0.284      -0.124       0.250
+51076.00     -0.107      0.268      -0.141       0.178
+51077.00     -0.120      0.208      -0.139       0.001
+51078.00     -0.127      0.119      -0.061      -0.030
+51079.00     -0.129      0.007      -0.082       0.042
+51080.00     -0.121     -0.092      -0.188       0.122
+51081.00     -0.092     -0.134      -0.382       0.170
+51082.00     -0.053     -0.108      -0.522       0.130
+51083.00     -0.029     -0.053      -0.517       0.041
+51084.00     -0.023     -0.016      -0.373       0.032
+51085.00     -0.031      0.009      -0.123       0.082
+51086.00     -0.054      0.039      -0.013       0.091
+51087.00     -0.095      0.076       0.045       0.134
+51088.00     -0.135      0.106       0.179       0.462
+51089.00     -0.146      0.115       0.290       0.580
+51090.00     -0.131      0.090       0.381       0.631
+51091.00     -0.099      0.022       0.304       0.340
+51092.00     -0.069     -0.079       0.201       0.129
+51093.00     -0.066     -0.194       0.135      -0.077
+51094.00     -0.097     -0.271       0.072      -0.211
+51095.00     -0.143     -0.305       0.082      -0.432
+51096.00     -0.186     -0.289       0.118      -0.670
+51097.00     -0.217     -0.229       0.036      -0.755
+51098.00     -0.222     -0.182      -0.085      -0.599
+51099.00     -0.181     -0.195      -0.060      -0.495
+51100.00     -0.102     -0.255      -0.010      -0.166
+51101.00     -0.039     -0.301       0.119      -0.164
+51102.00     -0.001     -0.324       0.104       0.002
+51103.00      0.023     -0.338       0.092       0.228
+51104.00      0.033     -0.333       0.030       0.168
+51105.00      0.032     -0.299       0.027       0.065
+51106.00      0.032     -0.251       0.056      -0.137
+51107.00      0.039     -0.210       0.028      -0.043
+51108.00      0.052     -0.182      -0.057      -0.019
+51109.00      0.063     -0.150      -0.193      -0.007
+51110.00      0.067     -0.103      -0.354      -0.063
+51111.00      0.056     -0.048      -0.376      -0.031
+51112.00      0.035     -0.002      -0.249       0.024
+51113.00      0.019      0.045      -0.114       0.138
+51114.00      0.005      0.106      -0.005       0.129
+51115.00     -0.015      0.179       0.051       0.131
+51116.00     -0.050      0.238       0.156       0.353
+51117.00     -0.098      0.266       0.272       0.516
+51118.00     -0.152      0.244       0.311       0.525
+51119.00     -0.192      0.163       0.284       0.377
+51120.00     -0.193      0.048       0.109       0.148
+51121.00     -0.153     -0.055       0.059       0.142
+51122.00     -0.118     -0.094       0.012      -0.014
+51123.00     -0.105     -0.030       0.034      -0.349
+51124.00     -0.093      0.040       0.081      -0.700
+51125.00     -0.079      0.069       0.045      -0.794
+51126.00     -0.077      0.065      -0.034      -0.547
+51127.00     -0.097      0.019      -0.097      -0.184
+51128.00     -0.145     -0.040      -0.066      -0.044
+51129.00     -0.224     -0.074      -0.001       0.080
+51130.00     -0.302     -0.084      -0.003       0.054
+51131.00     -0.336     -0.081      -0.075       0.172
+51132.00     -0.326     -0.065      -0.128       0.196
+51133.00     -0.297     -0.036      -0.111       0.184
+51134.00     -0.254      0.001      -0.056       0.095
+51135.00     -0.201      0.038      -0.015      -0.082
+51136.00     -0.155      0.071      -0.042      -0.041
+51137.00     -0.119      0.091      -0.011      -0.066
+51138.00     -0.089      0.094      -0.027      -0.212
+51139.00     -0.071      0.083      -0.067      -0.162
+51140.00     -0.064      0.069      -0.024      -0.191
+51141.00     -0.059      0.064       0.014       0.054
+51142.00     -0.050      0.069       0.035       0.098
+51143.00     -0.042      0.074      -0.038       0.228
+51144.00     -0.036      0.075      -0.149       0.309
+51145.00     -0.028      0.076      -0.295       0.190
+51146.00     -0.021      0.066      -0.376       0.062
+51147.00     -0.023      0.032      -0.375      -0.142
+51148.00     -0.029     -0.007      -0.274      -0.182
+51149.00     -0.033     -0.006      -0.092       0.018
+51150.00     -0.045      0.033       0.155       0.076
+51151.00     -0.072      0.069       0.387       0.012
+51152.00     -0.102      0.079       0.554      -0.195
+51153.00     -0.114      0.079       0.606      -0.467
+51154.00     -0.103      0.075       0.485      -0.390
+51155.00     -0.069      0.060       0.312      -0.173
+51156.00     -0.027      0.047       0.120       0.018
+51157.00     -0.013      0.089      -0.005       0.083
+51158.00     -0.022      0.178      -0.193       0.153
+51159.00     -0.038      0.271      -0.424       0.188
+51160.00     -0.062      0.336      -0.358       0.209
+51161.00     -0.097      0.344      -0.316       0.238
+51162.00     -0.128      0.261      -0.219       0.230
+51163.00     -0.136      0.090      -0.115       0.030
+51164.00     -0.134     -0.062       0.002      -0.090
+51165.00     -0.121     -0.139       0.114      -0.213
+51166.00     -0.094     -0.160       0.167      -0.178
+51167.00     -0.062     -0.142       0.175      -0.143
+51168.00     -0.044     -0.089       0.121      -0.055
+51169.00     -0.041     -0.010       0.032       0.163
+51170.00     -0.040      0.065      -0.030       0.216
+51171.00     -0.041      0.105      -0.115       0.227
+51172.00     -0.053      0.111      -0.244       0.315
+51173.00     -0.071      0.090      -0.456       0.175
+51174.00     -0.080      0.040      -0.567       0.008
+51175.00     -0.071     -0.037      -0.629      -0.124
+51176.00     -0.045     -0.109      -0.472      -0.297
+51177.00     -0.003     -0.141      -0.191      -0.265
+51178.00      0.039     -0.137       0.126      -0.081
+51179.00      0.070     -0.126       0.220      -0.191
+51180.00      0.089     -0.120       0.321      -0.564
+51181.00      0.103     -0.117       0.333      -0.897
+51182.00      0.118     -0.113       0.302      -0.840
+51183.00      0.133     -0.108       0.214      -0.574
+51184.00      0.141     -0.092       0.164      -0.199
+51185.00      0.141     -0.060       0.200       0.211
+51186.00      0.141     -0.023       0.207       0.280
+51187.00      0.138      0.011       0.200       0.356
+51188.00      0.120      0.047       0.215       0.422
+51189.00      0.081      0.087       0.195       0.431
+51190.00      0.028      0.122       0.171       0.388
+51191.00     -0.034      0.154       0.120       0.083
+51192.00     -0.106      0.201       0.075      -0.091
+51193.00     -0.163      0.234       0.040      -0.129
+51194.00     -0.192      0.227       0.048      -0.024
+51195.00     -0.200      0.188       0.055       0.214
+51196.00     -0.204      0.143      -0.026       0.343
+51197.00     -0.207      0.111      -0.096       0.305
+51198.00     -0.195      0.096      -0.139       0.172
+51199.00     -0.164      0.098      -0.162       0.066
+51200.00     -0.128      0.126      -0.181       0.048
+51201.00     -0.103      0.170      -0.224       0.074
+51202.00     -0.082      0.199      -0.295       0.077
+51203.00     -0.051      0.186      -0.256       0.064
+51204.00     -0.017      0.144      -0.100       0.021
+51205.00     -0.004      0.078       0.116       0.098
+51206.00     -0.025     -0.020       0.305       0.216
+51207.00     -0.057     -0.053       0.382       0.218
+51208.00     -0.112     -0.010       0.405       0.047
+51209.00     -0.176      0.069       0.348      -0.181
+51210.00     -0.226      0.135      -0.101      -0.181
+51211.00     -0.243      0.123      -0.131      -0.097
+51212.00     -0.218      0.018      -0.129      -0.052
+51213.00     -0.176     -0.069      -0.192      -0.112
+51214.00     -0.124     -0.109      -0.374       0.176
+51215.00     -0.064     -0.127      -0.243       0.001
+51216.00     -0.011     -0.135       0.032      -0.534
+51217.00      0.022     -0.130       0.023      -0.422
+51218.00      0.024     -0.123       0.005      -0.134
+51219.00     -0.014     -0.150      -0.054      -0.013
+51220.00     -0.051     -0.345      -0.109      -0.007
+51221.00     -0.075     -0.580       0.004       0.103
+51222.00     -0.095     -0.653       0.108       0.084
+51223.00     -0.113     -0.588       0.229       0.365
+51224.00     -0.122     -0.444       0.295       0.470
+51225.00     -0.116     -0.265       0.202       0.262
+51226.00     -0.092     -0.119       0.047       0.070
+51227.00     -0.052     -0.067      -0.200      -0.126
+51228.00     -0.021     -0.071      -0.374      -0.155
+51229.00     -0.026     -0.058      -0.477      -0.008
+51230.00     -0.059     -0.029      -0.579       0.188
+51231.00     -0.100     -0.007      -0.512       0.319
+51232.00     -0.136      0.015      -0.368       0.187
+51233.00     -0.165      0.054      -0.175       0.161
+51234.00     -0.194      0.096      -0.013       0.057
+51235.00     -0.227      0.115       0.091      -0.069
+51236.00     -0.260      0.112       0.086      -0.146
+51237.00     -0.279      0.113       0.050      -0.327
+51238.00     -0.283      0.122       0.005      -0.242
+51239.00     -0.282      0.119      -0.019      -0.077
+51240.00     -0.279      0.102      -0.148       0.098
+51241.00     -0.272      0.095      -0.272       0.198
+51242.00     -0.262      0.105      -0.348       0.304
+51243.00     -0.255      0.111      -0.316       0.265
+51244.00     -0.244      0.095      -0.224       0.243
+51245.00     -0.211      0.071      -0.146       0.160
+51246.00     -0.155      0.055      -0.066       0.194
+51247.00     -0.086      0.048      -0.042       0.105
+51248.00     -0.019      0.066      -0.058       0.081
+51249.00      0.029      0.134      -0.108      -0.040
+51250.00      0.045      0.225      -0.191      -0.082
+51251.00      0.027      0.282      -0.161       0.100
+51252.00     -0.006      0.275      -0.020       0.233
+51253.00     -0.037      0.209       0.051       0.243
+51254.00     -0.070      0.090       0.048       0.123
+51255.00     -0.102     -0.030      -0.080      -0.119
+51256.00     -0.127     -0.122      -0.178      -0.227
+51257.00     -0.134     -0.179      -0.143      -0.168
+51258.00     -0.119     -0.195      -0.021       0.039
+51259.00     -0.089     -0.180       0.054       0.276
+51260.00     -0.054     -0.128       0.065       0.259
+51261.00     -0.017     -0.022       0.037       0.055
+51262.00      0.022      0.123       0.092      -0.056
+51263.00      0.055      0.200       0.158      -0.249
+51264.00      0.074      0.179       0.226      -0.220
+51265.00      0.081      0.105       0.243      -0.254
+51266.00      0.077      0.007       0.226      -0.262
+51267.00      0.064     -0.099       0.204      -0.103
+51268.00      0.044     -0.194       0.106      -0.131
+51269.00      0.028     -0.237       0.059      -0.226
+51270.00      0.012     -0.221      -0.094      -0.309
+51271.00     -0.012     -0.177      -0.181      -0.321
+51272.00     -0.037     -0.133      -0.185      -0.270
+51273.00     -0.046     -0.089      -0.181      -0.286
+51274.00     -0.040     -0.043      -0.085      -0.174
+51275.00     -0.038     -0.002       0.004       0.064
+51276.00     -0.048      0.038       0.135       0.178
+51277.00     -0.066      0.096       0.124       0.195
+51278.00     -0.101      0.155       0.038       0.121
+51279.00     -0.153      0.169      -0.020       0.184
+51280.00     -0.196      0.135       0.005       0.289
+51281.00     -0.198      0.104       0.049       0.350
+51282.00     -0.162      0.106      -0.054       0.257
+51283.00     -0.098      0.106      -0.210      -0.036
+51284.00     -0.018      0.081      -0.233      -0.395
+51285.00      0.071      0.045      -0.059      -0.389
+51286.00      0.154      0.016       0.201      -0.281
+51287.00      0.209     -0.009       0.440      -0.126
+51288.00      0.213     -0.018       0.462       0.051
+51289.00      0.155      0.002       0.336       0.129
+51290.00      0.074      0.015       0.308       0.202
+51291.00      0.018      0.055       0.325       0.275
+51292.00     -0.004      0.131       0.419       0.446
+51293.00     -0.007      0.211       0.425       0.449
+51294.00     -0.000      0.251       0.328       0.383
+51295.00      0.009      0.199       0.239       0.362
+51296.00      0.017      0.038       0.145       0.108
+51297.00      0.029     -0.105       0.164      -0.126
+51298.00      0.048     -0.188       0.212      -0.185
+51299.00      0.066     -0.230       0.244      -0.269
+51300.00      0.080     -0.237      -0.075      -0.227
+51301.00      0.102     -0.211       0.258      -0.069
+51302.00      0.132     -0.157       0.204      -0.121
+51303.00      0.151     -0.096       0.225      -0.043
+51304.00      0.151     -0.014       0.233       0.146
+51305.00      0.139      0.057       0.166       0.224
+51306.00      0.110      0.086       0.001       0.003
+51307.00      0.056      0.042      -0.162      -0.224
+51308.00     -0.008     -0.072      -0.156      -0.252
+51309.00     -0.057     -0.189      -0.079      -0.221
+51310.00     -0.091     -0.255      -0.012      -0.192
+51311.00     -0.118     -0.288      -0.132      -0.300
+51312.00     -0.132     -0.315      -0.165      -0.419
+51313.00     -0.127     -0.322      -0.067      -0.338
+51314.00     -0.114     -0.291       0.101      -0.192
+51315.00     -0.095     -0.233       0.207      -0.017
+51316.00     -0.053     -0.151       0.150      -0.015
+51317.00      0.023     -0.028       0.100      -0.057
+51318.00      0.118      0.129       0.104       0.065
+51319.00      0.176      0.225       0.281       0.191
+51320.00      0.181      0.233       0.553       0.339
+51321.00      0.144      0.184       0.671       0.253
+51322.00      0.082      0.106       0.601       0.309
+51323.00      0.005      0.024       0.283       0.181
+51324.00     -0.078     -0.034      -0.009       0.068
+51325.00     -0.150     -0.059      -0.170      -0.235
+51326.00     -0.189     -0.071      -0.263      -0.497
+51327.00     -0.196     -0.084      -0.309      -0.595
+51328.00     -0.188     -0.082      -0.309      -0.554
+51329.00     -0.167     -0.059      -0.314      -0.407
+51330.00     -0.131     -0.029      -0.188      -0.318
+51331.00     -0.092     -0.025       0.023      -0.237
+51332.00     -0.063     -0.065       0.300      -0.020
+51333.00     -0.038     -0.128       0.452       0.259
+51334.00     -0.010     -0.188       0.497       0.282
+51335.00      0.016     -0.260       0.285       0.145
+51336.00      0.037     -0.350       0.105      -0.013
+51337.00      0.057     -0.425       0.107      -0.268
+51338.00      0.074     -0.442       0.121      -0.338
+51339.00      0.074     -0.402       0.193      -0.390
+51340.00      0.064     -0.333       0.248      -0.478
+51341.00      0.055     -0.243       0.371      -0.314
+51342.00      0.038     -0.137       0.491       0.014
+51343.00      0.003     -0.043       0.467       0.096
+51344.00     -0.035      0.016       0.350       0.088
+51345.00     -0.053      0.039       0.096       0.187
+51346.00     -0.038      0.037      -0.072       0.247
+51347.00     -0.009      0.015      -0.099       0.476
+51348.00      0.011     -0.018       0.064       0.593
+51349.00      0.018     -0.052       0.260       0.486
+51350.00      0.018     -0.092       0.279       0.285
+51351.00      0.004     -0.127       0.159       0.165
+51352.00     -0.041     -0.131       0.013       0.056
+51353.00     -0.122     -0.084      -0.055      -0.126
+51354.00     -0.207     -0.014      -0.004      -0.353
+51355.00     -0.267      0.054       0.018      -0.519
+51356.00     -0.301      0.114      -0.036      -0.577
+51357.00     -0.303      0.156      -0.103      -0.391
+51358.00     -0.245      0.149      -0.102      -0.243
+51359.00     -0.117      0.079      -0.005      -0.040
+51360.00      0.010      0.015       0.166       0.163
+51361.00      0.085     -0.028       0.368       0.480
+51362.00      0.117     -0.059       0.518       0.664
+51363.00      0.126     -0.082       0.608       0.670
+51364.00      0.117     -0.101       0.501       0.508
+51365.00      0.093     -0.118       0.238       0.330
+51366.00      0.062     -0.127       0.164      -0.008
+51367.00      0.030     -0.119       0.117      -0.144
+51368.00     -0.001     -0.089       0.154      -0.212
+51369.00     -0.023     -0.040       0.236      -0.025
+51370.00     -0.032      0.008       0.255       0.252
+51371.00     -0.035      0.032       0.264       0.312
+51372.00     -0.038      0.026       0.199       0.242
+51373.00     -0.041     -0.006       0.113       0.172
+51374.00     -0.041     -0.058       0.010       0.300
+51375.00     -0.026     -0.069       0.074       0.471
+51376.00     -0.001     -0.017       0.190       0.572
+51377.00      0.021      0.068       0.319       0.511
+51378.00      0.036      0.132       0.355       0.295
+51379.00      0.035      0.131       0.195       0.260
+51380.00      0.004      0.068      -0.018       0.203
+51381.00     -0.028      0.016      -0.158       0.112
+51382.00     -0.035     -0.004      -0.215      -0.081
+51383.00     -0.019     -0.005      -0.233      -0.313
+51384.00     -0.001      0.003      -0.196      -0.468
+51385.00     -0.001      0.016      -0.099      -0.404
+51386.00     -0.010      0.021      -0.065      -0.187
+51387.00     -0.020      0.020      -0.065      -0.119
+51388.00     -0.043      0.020      -0.113      -0.050
+51389.00     -0.092      0.013      -0.160       0.062
+51390.00     -0.151     -0.018      -0.076       0.091
+51391.00     -0.199     -0.067      -0.077       0.075
+51392.00     -0.228     -0.117      -0.100       0.181
+51393.00     -0.239     -0.158      -0.199       0.049
+51394.00     -0.223     -0.198      -0.242      -0.127
+51395.00     -0.168     -0.233      -0.052      -0.265
+51396.00     -0.084     -0.239       0.132      -0.358
+51397.00      0.006     -0.205       0.362      -0.204
+51398.00      0.088     -0.152       0.435       0.046
+51399.00      0.148     -0.116       0.425       0.006
+51400.00      0.161     -0.102       0.301      -0.052
+51401.00      0.105     -0.091       0.160      -0.158
+51402.00      0.004     -0.064       0.047       0.075
+51403.00     -0.096     -0.076      -0.071       0.255
+51404.00     -0.171     -0.132      -0.038       0.535
+51405.00     -0.211     -0.185       0.049       0.505
+51406.00     -0.209     -0.207       0.116       0.413
+51407.00     -0.161     -0.172       0.199       0.281
+51408.00     -0.071     -0.057       0.109       0.138
+51409.00      0.009      0.082      -0.039      -0.009
+51410.00      0.066      0.205      -0.109      -0.260
+51411.00      0.099      0.282      -0.174      -0.591
+51412.00      0.104      0.286      -0.104      -0.773
+51413.00      0.091      0.214      -0.008      -0.796
+51414.00      0.086      0.063       0.101      -0.592
+51415.00      0.106     -0.154       0.104      -0.221
+51416.00      0.130     -0.337       0.135      -0.137
+51417.00      0.140     -0.441       0.133      -0.245
+51418.00      0.135     -0.492       0.102      -0.396
+51419.00      0.124     -0.511       0.190      -0.414
+51420.00      0.113     -0.492       0.198      -0.251
+51421.00      0.103     -0.426       0.186      -0.210
+51422.00      0.095     -0.337       0.176      -0.228
+51423.00      0.096     -0.260       0.204      -0.239
+51424.00      0.113     -0.197       0.269      -0.360
+51425.00      0.142     -0.122       0.602      -2.311
+51426.00      0.173     -0.039       0.858      -2.223
+51427.00      0.199      0.029       0.930      -1.797
+51428.00      0.220      0.072       0.816      -1.086
+51429.00      0.237      0.096       0.583      -0.135
+51430.00      0.245      0.092       0.324       0.948
+51431.00      0.242      0.047       0.049       1.792
+51432.00      0.230     -0.032      -0.252       2.250
+51433.00      0.214     -0.119      -0.469       2.185
+51434.00      0.192     -0.205      -0.501       1.734
+51435.00      0.160     -0.291      -0.402       0.858
+51436.00      0.123     -0.354      -0.236      -0.041
+51437.00      0.093     -0.352      -0.087      -1.148
+51438.00      0.073     -0.286       0.130      -2.144
+51439.00      0.052     -0.204       0.438      -2.720
+51440.00      0.024     -0.146       0.778      -2.881
+51441.00      0.009     -0.102       1.031      -2.333
+51442.00      0.028     -0.054       0.992      -1.383
+51443.00      0.078     -0.012       0.682      -0.153
+51444.00      0.104     -0.001       0.221       1.002
+51445.00      0.093     -0.029      -0.276       1.624
+51446.00      0.058     -0.083      -0.717       1.840
+51447.00      0.008     -0.154      -1.049       1.687
+51448.00     -0.048     -0.221      -1.136       1.319
+51449.00     -0.098     -0.252      -0.947       0.765
+51450.00     -0.130     -0.236      -0.515      -0.013
+51451.00     -0.133     -0.185      -0.027      -0.985
+51452.00     -0.108     -0.115       0.515      -2.015
+51453.00     -0.059     -0.035       0.998      -2.555
+51454.00      0.003      0.043       1.294      -2.614
+51455.00      0.055      0.088       1.891       0.284
+51456.00      0.079      0.070       1.236       0.281
+51457.00      0.078     -0.020       0.368       0.051
+51458.00      0.068     -0.119      -0.291      -0.115
+51459.00      0.052     -0.197      -0.645      -0.127
+51460.00      0.031     -0.250      -0.646      -0.287
+51461.00      0.012     -0.261      -0.488      -0.240
+51462.00      0.003     -0.231      -0.220      -0.299
+51463.00      0.005     -0.178       0.021      -0.125
+51464.00      0.019     -0.108       0.116       0.021
+51465.00      0.039     -0.038       0.335       0.133
+51466.00      0.057      0.027       0.802       0.256
+51467.00      0.058      0.056       1.384       0.416
+51468.00      0.045      0.021       1.766       0.366
+51469.00      0.035     -0.047       1.673       0.329
+51470.00      0.039     -0.103       1.125       0.091
+51471.00      0.047     -0.137       0.312       0.031
+51472.00      0.057     -0.174      -0.353      -0.194
+51473.00      0.077     -0.222      -0.694      -0.437
+51474.00      0.109     -0.265      -0.604      -0.580
+51475.00      0.143     -0.290      -0.297      -0.660
+51476.00      0.156     -0.285       0.038      -0.473
+51477.00      0.133     -0.250       0.265      -0.221
+51478.00      0.082     -0.209       0.111      -0.168
+51479.00      0.045     -0.207      -0.065      -0.264
+51480.00      0.038     -0.229      -0.188      -0.576
+51481.00      0.049     -0.241      -0.207      -0.879
+51482.00      0.067     -0.241      -0.152      -0.839
+51483.00      0.084     -0.248       0.013      -0.704
+51484.00      0.087     -0.255       0.110      -0.360
+51485.00      0.074     -0.252       0.098      -0.232
+51486.00      0.054     -0.243       0.168      -0.030
+51487.00      0.035     -0.234       0.203       0.100
+51488.00      0.014     -0.216       0.205       0.126
+51489.00     -0.007     -0.172       0.213      -0.083
+51490.00     -0.017     -0.112       0.194      -0.089
+51491.00     -0.010     -0.064       0.134      -0.125
+51492.00      0.011     -0.041       0.063       0.027
+51493.00      0.048     -0.020       0.031       0.029
+51494.00      0.093      0.020       0.064       0.033
+51495.00      0.128      0.057       0.157      -0.103
+51496.00      0.150      0.054       0.345      -0.139
+51497.00      0.169      0.014       0.477      -0.014
+51498.00      0.180     -0.042       0.424      -0.073
+51499.00      0.162     -0.114       0.236      -0.172
+51500.00      0.131     -0.181       0.067      -0.125
+51501.00      0.111     -0.228      -0.031      -0.040
+51502.00      0.105     -0.251      -0.144      -0.017
+51503.00      0.110     -0.250      -0.219      -0.345
+51504.00      0.118     -0.221      -0.192      -0.336
+51505.00      0.115     -0.166      -0.041      -0.183
+51506.00      0.094     -0.127       0.132      -0.083
+51507.00      0.074     -0.146       0.243      -0.220
+51508.00      0.081     -0.194       0.358      -0.480
+51509.00      0.110     -0.209       0.397      -0.680
+51510.00      0.138     -0.182       0.420      -0.662
+51511.00      0.156     -0.154       0.401      -0.455
+51512.00      0.165     -0.141       0.374      -0.230
+51513.00      0.166     -0.130       0.255      -0.078
+51514.00      0.167     -0.125       0.097      -0.003
+51515.00      0.172     -0.139      -0.062       0.195
+51516.00      0.175     -0.164      -0.128       0.233
+51517.00      0.166     -0.174      -0.069       0.200
+51518.00      0.151     -0.160       0.011       0.107
+51519.00      0.136     -0.133       0.069      -0.045
+51520.00      0.116     -0.110       0.147      -0.002
+51521.00      0.082     -0.120       0.237      -0.098
+51522.00      0.035     -0.158       0.265      -0.193
+51523.00     -0.023     -0.206       0.314      -0.224
+51524.00     -0.084     -0.255       0.386      -0.230
+51525.00     -0.127     -0.284       0.348      -0.151
+51526.00     -0.142     -0.275       0.180      -0.157
+51527.00     -0.132     -0.240      -0.024      -0.115
+51528.00     -0.099     -0.226      -0.198      -0.106
+51529.00     -0.040     -0.230      -0.333       0.001
+51530.00      0.032     -0.241      -0.442      -0.027
+51531.00      0.102     -0.273      -0.442      -0.188
+51532.00      0.172     -0.320      -0.323      -0.353
+51533.00      0.243     -0.337      -0.032      -0.329
+51534.00      0.283     -0.317       0.302      -0.281
+51535.00      0.268     -0.308       0.472      -0.271
+51536.00      0.220     -0.336       0.491      -0.466
+51537.00      0.170     -0.359       0.416      -0.625
+51538.00      0.121     -0.344       0.257      -0.368
+51539.00      0.063     -0.307       0.157      -0.135
+51540.00     -0.002     -0.269       0.014      -0.062
+51541.00     -0.064     -0.227      -0.033      -0.149
+51542.00     -0.108     -0.192      -0.151      -0.199
+51543.00     -0.130     -0.182      -0.260      -0.096
+51544.00     -0.135     -0.204      -0.252      -0.119
+51545.00      0.121     -0.258      -0.111      -0.079
+51546.00      0.105     -0.271       0.049      -0.072
+51547.00      0.104     -0.278       0.159      -0.312
+51548.00      0.116     -0.272       0.230      -0.279
+51549.00      0.211     -0.323       0.321      -0.157
+51550.00      0.225     -0.324       0.388      -0.121
+51551.00      0.236     -0.336       0.519      -0.046
+51552.00      0.233     -0.340       0.525       0.138
+51553.00      0.219     -0.327       0.575       0.344
+51554.00      0.203     -0.299       0.496       0.538
+51555.00      0.185     -0.279       0.413       0.616
+51556.00      0.142     -0.255       0.233       0.624
+51557.00      0.126     -0.260       0.037       0.675
+51558.00      0.115     -0.258      -0.168       0.590
+51559.00      0.099     -0.268      -0.259       0.398
+51560.00      0.084     -0.298      -0.202       0.081
+51561.00      0.093     -0.315       0.089      -0.001
+51562.00      0.122     -0.288       0.446       0.156
+51563.00      0.070     -0.143       0.629       0.265
+51564.00      0.064     -0.125       0.672       0.320
+51565.00      0.049     -0.140       0.540       0.263
+51566.00      0.040     -0.160       0.323       0.559
+51567.00      0.037     -0.170       0.094       0.920
+51568.00      0.031     -0.167      -0.053       1.015
+51569.00      0.018     -0.148      -0.081       0.793
+51570.00      0.044     -0.169      -0.203       0.652
+51571.00      0.034     -0.157      -0.264       0.396
+51572.00      0.023     -0.159      -0.276       0.326
+51573.00      0.010     -0.167      -0.199       0.297
+51574.00      0.003     -0.180      -0.063       0.207
+51575.00      0.011     -0.193      -0.005      -0.018
+51576.00      0.026     -0.189       0.011      -0.015
+51577.00      0.041     -0.189       0.071       0.108
+51578.00      0.052     -0.177       0.134       0.284
+51579.00      0.061     -0.186       0.218       0.367
+51580.00      0.059     -0.198       0.312       0.089
+51581.00      0.044     -0.192       0.366      -0.178
+51582.00      0.025     -0.173       0.444      -0.177
+51583.00      0.010     -0.158       0.350      -0.097
+51584.00      0.003     -0.179       0.190       0.024
+51585.00     -0.019     -0.183      -0.044      -0.078
+51586.00     -0.028     -0.188      -0.271      -0.151
+51587.00     -0.021     -0.195      -0.368      -0.281
+51588.00     -0.014     -0.201      -0.330      -0.483
+51589.00     -0.013     -0.195      -0.114      -0.374
+51590.00     -0.011     -0.179       0.060      -0.188
+51591.00     -0.003     -0.162       0.213      -0.048
+51592.00      0.005     -0.151       0.295      -0.015
+51593.00      0.005     -0.143       0.226      -0.087
+51594.00     -0.003     -0.136       0.149       0.062
+51595.00     -0.016     -0.138       0.046       0.285
+51596.00     -0.033     -0.141      -0.039       0.191
+51597.00     -0.052     -0.138      -0.062      -0.023
+51598.00     -0.066     -0.129      -0.060      -0.438
+51599.00     -0.076     -0.128      -0.032      -0.648
+51600.00     -0.084     -0.129       0.034      -0.669
+51601.00     -0.089     -0.124       0.096      -0.493
+51602.00     -0.082     -0.117       0.132      -0.352
+51603.00     -0.060     -0.116       0.118      -0.181
+51604.00     -0.037     -0.115       0.031      -0.122
+51605.00     -0.108     -0.058      -0.029       0.071
+51606.00     -0.106     -0.047      -0.010       0.162
+51607.00     -0.107     -0.054       0.022       0.264
+51608.00     -0.112     -0.073       0.024       0.145
+51609.00     -0.122     -0.083      -0.048      -0.022
+51610.00     -0.133     -0.079      -0.133      -0.200
+51611.00     -0.139     -0.078      -0.227      -0.208
+51612.00     -0.181     -0.084      -0.307      -0.086
+51613.00     -0.192     -0.084      -0.335      -0.066
+51614.00     -0.197     -0.085      -0.337      -0.055
+51615.00     -0.181     -0.092      -0.233      -0.047
+51616.00     -0.155     -0.090      -0.111      -0.143
+51617.00     -0.143     -0.071       0.005      -0.069
+51618.00     -0.150     -0.056       0.011       0.050
+51619.00     -0.051     -0.004      -0.012       0.130
+51620.00     -0.051     -0.035      -0.024       0.247
+51621.00     -0.041     -0.043      -0.005       0.177
+51622.00     -0.037     -0.024       0.047       0.201
+51623.00     -0.047     -0.009       0.094       0.292
+51624.00     -0.069     -0.011       0.063       0.221
+51625.00     -0.089     -0.017       0.042       0.091
+51626.00     -0.097     -0.070       0.067      -0.349
+51627.00     -0.107     -0.067       0.070      -0.557
+51628.00     -0.117     -0.069       0.170      -0.537
+51629.00     -0.121     -0.068       0.213      -0.517
+51630.00     -0.108     -0.059       0.228      -0.290
+51631.00     -0.084     -0.052       0.090      -0.111
+51632.00     -0.061     -0.049      -0.034       0.038
+51633.00     -0.084     -0.054      -0.072       0.298
+51634.00     -0.089     -0.036      -0.079       0.462
+51635.00     -0.104     -0.038       0.047       0.574
+51636.00     -0.122     -0.066       0.157       0.583
+51637.00     -0.135     -0.092       0.227       0.311
+51638.00     -0.143     -0.097       0.181       0.071
+51639.00     -0.150     -0.095       0.087      -0.005
+51640.00     -0.157     -0.098       0.008       0.024
+51641.00     -0.159     -0.116       0.007       0.151
+51642.00     -0.154     -0.108       0.042       0.191
+51643.00     -0.146     -0.107       0.123       0.136
+51644.00     -0.139     -0.115       0.163       0.039
+51645.00     -0.138     -0.113       0.148      -0.165
+51646.00     -0.141     -0.104       0.081      -0.198
+51647.00     -0.230     -0.105      -0.002      -0.076
+51648.00     -0.219     -0.122      -0.111       0.061
+51649.00     -0.205     -0.124      -0.208       0.207
+51650.00     -0.198     -0.103      -0.221       0.266
+51651.00     -0.206     -0.087      -0.159       0.307
+51652.00     -0.222     -0.090      -0.227       0.287
+51653.00     -0.233     -0.099      -0.306       0.101
+51654.00     -0.325     -0.066      -0.396      -0.191
+51655.00     -0.325     -0.057      -0.411      -0.416
+51656.00     -0.325     -0.061      -0.319      -0.453
+51657.00     -0.314     -0.071      -0.257      -0.536
+51658.00     -0.288     -0.078      -0.137      -0.413
+51659.00     -0.259     -0.079      -0.076      -0.304
+51660.00     -0.236     -0.074      -0.074      -0.022
+51661.00     -0.193     -0.055      -0.123       0.318
+51662.00     -0.190     -0.016      -0.207       0.511
+51663.00     -0.202     -0.007      -0.223       0.576
+51664.00     -0.220     -0.044      -0.090       0.728
+51665.00     -0.227     -0.088       0.019       0.650
+51666.00     -0.224     -0.099       0.017       0.533
+51667.00     -0.225     -0.087      -0.098       0.152
+51668.00     -0.232     -0.101      -0.168       0.140
+51669.00     -0.227     -0.102      -0.173       0.218
+51670.00     -0.208     -0.099      -0.038       0.208
+51671.00     -0.186     -0.101       0.075       0.190
+51672.00     -0.177     -0.117      -0.013      -0.066
+51673.00     -0.178     -0.130      -0.071      -0.188
+51674.00     -0.178     -0.130      -0.113      -0.209
+51675.00     -0.169     -0.121      -0.182      -0.099
+51676.00     -0.156     -0.107      -0.266       0.282
+51677.00     -0.148     -0.087      -0.388       0.468
+51678.00     -0.151     -0.061      -0.450       0.604
+51679.00     -0.167     -0.049      -0.456       0.635
+51680.00     -0.188     -0.057      -0.405       0.360
+51681.00     -0.200     -0.070      -0.369       0.069
+51682.00     -0.230     -0.109      -0.339      -0.309
+51683.00     -0.220     -0.111      -0.339      -0.427
+51684.00     -0.211     -0.118      -0.271      -0.460
+51685.00     -0.191     -0.128      -0.132      -0.420
+51686.00     -0.159     -0.130      -0.031      -0.435
+51687.00     -0.135     -0.131       0.162      -0.362
+51688.00     -0.127     -0.131       0.328      -0.190
+51689.00     -0.074     -0.077       0.329       0.118
+51690.00     -0.075     -0.037       0.184       0.218
+51691.00     -0.084     -0.020       0.077       0.177
+51692.00     -0.097     -0.055       0.091       0.211
+51693.00     -0.098     -0.104       0.235       0.327
+51694.00     -0.089     -0.112       0.277       0.201
+51695.00     -0.086     -0.089       0.234      -0.128
+51696.00      0.032     -0.076       0.145      -0.319
+51697.00      0.019     -0.075       0.259      -0.311
+51698.00      0.014     -0.075       0.368      -0.082
+51699.00      0.014     -0.081       0.412       0.021
+51700.00      0.017     -0.098       0.313      -0.093
+51701.00      0.019     -0.109       0.163      -0.064
+51702.00      0.015     -0.106       0.118       0.072
+51703.00      0.006     -0.095       0.106       0.204
+51704.00     -0.005     -0.079       0.156       0.347
+51705.00     -0.018     -0.050       0.060       0.579
+51706.00     -0.038     -0.021      -0.136       0.603
+51707.00     -0.065     -0.009      -0.258       0.472
+51708.00     -0.097     -0.015      -0.313       0.237
+51709.00     -0.120     -0.028      -0.252      -0.035
+51710.00     -0.237     -0.028      -0.172      -0.292
+51711.00     -0.212     -0.043      -0.137      -0.364
+51712.00     -0.189     -0.055      -0.137      -0.156
+51713.00     -0.166     -0.051      -0.199      -0.139
+51714.00     -0.139     -0.032      -0.143      -0.057
+51715.00     -0.122     -0.021      -0.102      -0.009
+51716.00     -0.127     -0.029      -0.040       0.186
+51717.00     -0.108     -0.005      -0.081       0.373
+51718.00     -0.117      0.005      -0.249       0.458
+51719.00     -0.118      0.012      -0.397       0.374
+51720.00     -0.115     -0.012      -0.423       0.375
+51721.00     -0.103     -0.045      -0.257       0.428
+51722.00     -0.091     -0.043      -0.106       0.408
+51723.00     -0.090     -0.018      -0.000       0.264
+51724.00     -0.072     -0.059       0.091      -0.039
+51725.00     -0.070     -0.058       0.216      -0.215
+51726.00     -0.065     -0.053       0.399      -0.156
+51727.00     -0.067     -0.052       0.449      -0.159
+51728.00     -0.064     -0.065       0.252      -0.315
+51729.00     -0.048     -0.075       0.093      -0.376
+51730.00     -0.030     -0.072       0.012      -0.219
+51731.00     -0.049     -0.127      -0.030      -0.044
+51732.00     -0.056     -0.118       0.057       0.009
+51733.00     -0.067     -0.094       0.017      -0.112
+51734.00     -0.075     -0.065      -0.080      -0.048
+51735.00     -0.083     -0.059      -0.248       0.030
+51736.00     -0.092     -0.073      -0.261       0.007
+51737.00     -0.098     -0.089      -0.108      -0.095
+51738.00     -0.080     -0.116       0.079      -0.202
+51739.00     -0.053     -0.123       0.264      -0.217
+51740.00     -0.027     -0.125       0.305      -0.076
+51741.00     -0.017     -0.112       0.303      -0.123
+51742.00     -0.012     -0.093       0.213      -0.127
+51743.00     -0.009     -0.082       0.185      -0.093
+51744.00     -0.018     -0.092       0.158      -0.087
+51745.00     -0.005     -0.099       0.041      -0.004
+51746.00     -0.023     -0.102      -0.087       0.162
+51747.00     -0.026     -0.095      -0.318       0.167
+51748.00     -0.022     -0.098      -0.403       0.089
+51749.00     -0.016     -0.110      -0.342       0.114
+51750.00     -0.017     -0.111      -0.240       0.108
+51751.00     -0.031     -0.099      -0.071      -0.026
+51752.00     -0.045     -0.093       0.033      -0.190
+51753.00     -0.040     -0.089       0.223      -0.203
+51754.00     -0.018     -0.077       0.288      -0.184
+51755.00     -0.004     -0.066       0.353      -0.172
+51756.00     -0.000     -0.073       0.277      -0.397
+51757.00      0.004     -0.082       0.128      -0.477
+51758.00      0.012     -0.081       0.012      -0.189
+51759.00      0.001     -0.088      -0.027       0.122
+51760.00     -0.006     -0.083       0.044       0.145
+51761.00     -0.016     -0.063       0.088       0.018
+51762.00     -0.022     -0.039       0.017      -0.105
+51763.00     -0.018     -0.040      -0.101       0.019
+51764.00     -0.009     -0.067      -0.147       0.069
+51765.00      0.002     -0.086      -0.059       0.042
+51766.00      0.082     -0.046       0.127      -0.121
+51767.00      0.102     -0.030       0.316      -0.228
+51768.00      0.116     -0.016       0.473      -0.304
+51769.00      0.109     -0.011       0.519      -0.196
+51770.00      0.093     -0.015       0.575      -0.187
+51771.00      0.084     -0.027       0.565      -0.169
+51772.00      0.077     -0.035       0.489      -0.139
+51773.00      0.121     -0.049       0.393       0.086
+51774.00      0.093     -0.034       0.229       0.191
+51775.00      0.073     -0.017       0.092       0.314
+51776.00      0.060     -0.008      -0.091       0.316
+51777.00      0.046     -0.009      -0.155       0.209
+51778.00      0.029     -0.016      -0.151       0.123
+51779.00      0.011     -0.028       0.003       0.076
+51780.00     -0.007     -0.031       0.155       0.085
+51781.00     -0.015     -0.019       0.212       0.124
+51782.00     -0.007      0.004       0.220       0.088
+51783.00      0.008      0.016       0.110       0.057
+51784.00      0.013      0.011      -0.016      -0.030
+51785.00      0.003      0.011      -0.134      -0.049
+51786.00     -0.018      0.021      -0.258       0.160
+51787.00     -0.082      0.096      -0.390       0.387
+51788.00     -0.097      0.096      -0.423       0.494
+51789.00     -0.108      0.102      -0.572       0.434
+51790.00     -0.114      0.113      -0.559       0.111
+51791.00     -0.113      0.104      -0.245       0.012
+51792.00     -0.104      0.078      -0.193      -0.015
+51793.00     -0.091      0.064      -0.132      -0.092
+51794.00      0.008      0.067       0.040      -0.154
+51795.00      0.024      0.090       0.217      -0.340
+51796.00      0.030      0.099       0.308      -0.404
+51797.00      0.019      0.090       0.366      -0.297
+51798.00      0.005      0.070       0.307      -0.103
+51799.00      0.005      0.052       0.187       0.077
+51800.00      0.010      0.054      -0.036       0.052
+51801.00     -0.002      0.048      -0.198       0.037
+51802.00     -0.017      0.066      -0.352       0.052
+51803.00     -0.029      0.066      -0.440       0.114
+51804.00     -0.032      0.058      -0.466       0.233
+51805.00     -0.033      0.054      -0.419       0.197
+51806.00     -0.033      0.050      -0.251       0.176
+51807.00     -0.026      0.035      -0.034       0.029
+51808.00      0.013     -0.011       0.284       0.034
+51809.00      0.024     -0.007       0.458       0.083
+51810.00      0.033      0.010       0.438       0.162
+51811.00      0.043      0.016       0.387      -0.035
+51812.00      0.053      0.010       0.324      -0.166
+51813.00      0.052      0.016       0.277      -0.240
+51814.00      0.037      0.039       0.235      -0.100
+51815.00      0.017      0.054       0.177       0.109
+51816.00     -0.009      0.078       0.101       0.308
+51817.00     -0.014      0.068       0.034       0.298
+51818.00     -0.012      0.064       0.055       0.165
+51819.00     -0.008      0.052       0.087       0.141
+51820.00     -0.001      0.035       0.137       0.222
+51821.00      0.013      0.034       0.213       0.159
+51822.00      0.031      0.101       0.198       0.035
+51823.00      0.047      0.110       0.291      -0.110
+51824.00      0.048      0.092       0.350      -0.127
+51825.00      0.037      0.063       0.402      -0.030
+51826.00      0.027      0.047       0.338       0.108
+51827.00      0.026      0.052       0.257       0.235
+51828.00      0.028      0.070       0.086       0.178
+51829.00     -0.010      0.086      -0.105       0.036
+51830.00     -0.020      0.091      -0.220      -0.095
+51831.00     -0.024      0.074      -0.277       0.019
+51832.00     -0.020      0.052      -0.306       0.225
+51833.00     -0.015      0.049      -0.273       0.433
+51834.00     -0.012      0.060      -0.158       0.377
+51835.00     -0.007      0.058       0.092       0.248
+51836.00     -0.034      0.045       0.296      -0.035
+51837.00     -0.015      0.026       0.448      -0.064
+51838.00      0.001      0.028       0.448      -0.143
+51839.00      0.008      0.034       0.374      -0.147
+51840.00      0.006      0.035       0.264      -0.099
+51841.00     -0.002      0.041       0.129      -0.134
+51842.00     -0.011      0.055       0.032      -0.076
+51843.00     -0.021      0.060      -0.020       0.071
+51844.00     -0.029      0.048      -0.088       0.133
+51845.00     -0.030      0.033      -0.211       0.162
+51846.00     -0.023      0.024      -0.225       0.085
+51847.00     -0.014      0.012      -0.155       0.050
+51848.00     -0.004     -0.008      -0.071       0.032
+51849.00      0.012     -0.014       0.038      -0.256
+51850.00      0.036      0.002       0.205      -0.164
+51851.00      0.055      0.009       0.295      -0.237
+51852.00      0.060     -0.019       0.370      -0.264
+51853.00      0.055     -0.056       0.388      -0.189
+51854.00      0.051     -0.065       0.312      -0.172
+51855.00      0.046     -0.043       0.156      -0.232
+51856.00      0.037     -0.020       0.002      -0.449
+51857.00      0.030     -0.013      -0.115      -0.687
+51858.00      0.031     -0.012      -0.279      -0.891
+51859.00      0.038     -0.014      -0.360      -0.889
+51860.00      0.042     -0.014      -0.429      -0.527
+51861.00      0.039     -0.009      -0.352      -0.155
+51862.00      0.035     -0.004      -0.251       0.076
+51863.00      0.035     -0.019      -0.125       0.035
+51864.00      0.044     -0.048       0.086      -0.265
+51865.00      0.060     -0.066       0.235      -0.400
+51866.00      0.082     -0.055       0.351      -0.460
+51867.00      0.098     -0.026       0.334      -0.499
+51868.00      0.097     -0.000       0.275      -0.320
+51869.00      0.082      0.015       0.176      -0.268
+51870.00      0.069      0.016       0.070      -0.142
+51871.00      0.062      0.003       0.050      -0.047
+51872.00      0.057     -0.018      -0.001       0.012
+51873.00      0.052     -0.028      -0.053       0.070
+51874.00      0.053     -0.024      -0.085       0.086
+51875.00      0.061     -0.031      -0.050       0.169
+51876.00      0.074     -0.061       0.104       0.242
+51877.00      0.091     -0.085       0.283       0.216
+51878.00      0.113     -0.081       0.425       0.087
+51879.00      0.128     -0.064       0.581      -0.054
+51880.00      0.155      0.008       0.595      -0.222
+51881.00      0.152     -0.017       0.602      -0.120
+51882.00      0.148     -0.025       0.480      -0.108
+51883.00      0.137     -0.015       0.277      -0.036
+51884.00      0.118     -0.012       0.189      -0.024
+51885.00      0.120     -0.057       0.159      -0.097
+51886.00      0.121     -0.056       0.097      -0.158
+51887.00      0.126     -0.046       0.056      -0.403
+51888.00      0.125     -0.034       0.054      -0.352
+51889.00      0.118     -0.027       0.146      -0.063
+51890.00      0.106     -0.035       0.220       0.149
+51891.00      0.100     -0.075       0.272       0.122
+51892.00      0.143     -0.100       0.327      -0.039
+51893.00      0.158     -0.117       0.362      -0.275
+51894.00      0.171     -0.087       0.484      -0.209
+51895.00      0.179     -0.043       0.495      -0.106
+51896.00      0.177     -0.010       0.471      -0.009
+51897.00      0.163      0.008       0.325      -0.058
+51898.00      0.144      0.012       0.204      -0.118
+51899.00      0.140     -0.049       0.127      -0.195
+51900.00      0.129     -0.078       0.065      -0.422
+51901.00      0.118     -0.090       0.031      -0.468
+51902.00      0.112     -0.081       0.031      -0.443
+51903.00      0.116     -0.079       0.013      -0.317
+51904.00      0.129     -0.102      -0.015      -0.183
+51905.00      0.145     -0.134       0.095      -0.167
+51906.00      0.161     -0.146       0.164      -0.071
+51907.00      0.166     -0.133       0.332      -0.071
+51908.00      0.158     -0.123       0.463      -0.074
+51909.00      0.149     -0.123       0.536       0.089
+51910.00      0.142     -0.123       0.506       0.036
+51911.00      0.128     -0.126       0.379      -0.042
+51912.00      0.106     -0.138       0.274      -0.196
+51913.00      0.090     -0.143       0.138      -0.265
+51914.00      0.078     -0.130      -0.027       0.110
+51915.00      0.065     -0.123      -0.167      -0.102
+51916.00      0.066     -0.140      -0.127      -0.365
+51917.00      0.089     -0.150       0.054      -0.303
+51918.00      0.112     -0.135       0.303      -0.181
+51919.00      0.110     -0.133       0.289      -0.153
+51920.00      0.192     -0.199       0.162      -0.417
+51921.00      0.182     -0.235       0.014      -0.799
+51922.00      0.180     -0.231      -0.019      -0.678
+51923.00      0.176     -0.209       0.017      -0.591
+51924.00      0.169     -0.196       0.093      -0.478
+51925.00      0.160     -0.184       0.140      -0.407
+51926.00      0.144     -0.169       0.121      -0.426
+51927.00      0.134     -0.168       0.100      -0.298
+51928.00      0.118     -0.190       0.111      -0.342
+51929.00      0.106     -0.211       0.199      -0.346
+51930.00      0.100     -0.216       0.247      -0.367
+51931.00      0.106     -0.213       0.189      -0.334
+51932.00      0.121     -0.215       0.159      -0.193
+51933.00      0.138     -0.222       0.196      -0.065
+51934.00      0.179     -0.188       0.260       0.024
+51935.00      0.181     -0.190       0.429      -0.102
+51936.00      0.168     -0.189       0.515      -0.115
+51937.00      0.151     -0.187       0.595      -0.025
+51938.00      0.138     -0.183       0.560      -0.125
+51939.00      0.125     -0.187       0.462      -0.147
+51940.00      0.110     -0.203       0.261      -0.334
+51941.00      0.122     -0.258       0.076      -0.493
+51942.00      0.109     -0.236      -0.131      -0.667
+51943.00      0.084     -0.229      -0.242      -1.062
+51944.00      0.071     -0.268      -0.248      -1.407
+51945.00      0.103     -0.307       0.033      -1.371
+51946.00      0.159     -0.277       0.263      -0.982
+51947.00      0.180     -0.210       0.268      -0.357
+51948.00      0.154     -0.156       0.009      -0.013
+51949.00      0.117     -0.192      -0.276      -0.004
+51950.00      0.101     -0.234      -0.408       0.291
+51951.00      0.098     -0.254      -0.333       0.303
+51952.00      0.094     -0.259      -0.155       0.218
+51953.00      0.088     -0.251       0.060      -0.118
+51954.00      0.079     -0.231       0.149      -0.284
+51955.00      0.061     -0.192       0.276      -0.176
+51956.00      0.050     -0.205       0.343      -0.139
+51957.00      0.042     -0.228       0.514      -0.188
+51958.00      0.043     -0.248       0.578      -0.178
+51959.00      0.058     -0.255       0.541      -0.226
+51960.00      0.080     -0.247       0.411      -0.189
+51961.00      0.097     -0.224       0.306      -0.225
+51962.00      0.147     -0.213       0.257      -0.278
+51963.00      0.145     -0.217       0.327      -0.271
+51964.00      0.132     -0.236       0.353      -0.362
+51965.00      0.111     -0.250       0.349      -0.300
+51966.00      0.094     -0.248       0.342      -0.245
+51967.00      0.086     -0.246       0.278      -0.279
+51968.00      0.079     -0.253       0.117      -0.423
+51969.00     -0.038     -0.305      -0.011      -0.579
+51970.00     -0.033     -0.295      -0.100      -0.795
+51971.00     -0.029     -0.284      -0.174      -1.114
+51972.00     -0.034     -0.301      -0.190      -1.259
+51973.00     -0.028     -0.330      -0.054      -1.255
+51974.00     -0.002     -0.322       0.100      -0.849
+51975.00      0.017     -0.274       0.098      -0.229
+51976.00      0.007     -0.237      -0.038       0.093
+51977.00     -0.020     -0.243      -0.216       0.244
+51978.00     -0.035     -0.272      -0.295       0.400
+51979.00     -0.038     -0.292      -0.271       0.498
+51980.00     -0.042     -0.291      -0.108       0.422
+51981.00     -0.051     -0.276       0.041       0.154
+51982.00     -0.059     -0.257       0.153      -0.224
+51983.00     -0.063     -0.252       0.269      -0.361
+51984.00     -0.066     -0.263       0.358      -0.339
+51985.00     -0.069     -0.276       0.504      -0.380
+51986.00     -0.062     -0.286       0.545      -0.407
+51987.00     -0.039     -0.292       0.438      -0.561
+51988.00     -0.012     -0.284       0.186      -0.440
+51989.00      0.000     -0.255       0.004      -0.427
+51990.00      0.002     -0.270      -0.093      -0.374
+51991.00     -0.010     -0.267      -0.084      -0.378
+51992.00     -0.025     -0.288      -0.074      -0.437
+51993.00     -0.045     -0.309      -0.022      -0.441
+51994.00     -0.059     -0.314       0.024      -0.373
+51995.00     -0.058     -0.311       0.014      -0.318
+51996.00     -0.054     -0.309       0.059      -0.289
+51997.00     -0.023     -0.292       0.105      -0.453
+51998.00     -0.018     -0.290       0.226      -0.701
+51999.00      0.002     -0.285       0.329      -0.773
+52000.00      0.021     -0.276       0.390      -0.802
+52001.00      0.022     -0.268       0.357      -0.664
+52002.00      0.008     -0.265       0.242      -0.516
+52003.00     -0.004     -0.273       0.028      -0.264
+52004.00     -0.008     -0.282      -0.088      -0.140
+52005.00     -0.012     -0.283      -0.263      -0.343
+52006.00     -0.021     -0.272      -0.274      -0.336
+52007.00     -0.032     -0.261      -0.215      -0.226
+52008.00     -0.044     -0.256      -0.176      -0.156
+52009.00     -0.055     -0.251      -0.128      -0.208
+52010.00     -0.060     -0.243      -0.060      -0.386
+52011.00     -0.108     -0.301       0.092      -0.344
+52012.00     -0.106     -0.313       0.266      -0.174
+52013.00     -0.105     -0.321       0.400      -0.010
+52014.00     -0.094     -0.317       0.546      -0.067
+52015.00     -0.069     -0.310       0.529      -0.224
+52016.00     -0.046     -0.300       0.386      -0.286
+52017.00     -0.042     -0.276       0.232      -0.314
+52018.00     -0.056     -0.247       0.124      -0.464
+52019.00     -0.074     -0.238       0.107      -0.593
+52020.00     -0.090     -0.256       0.110      -0.766
+52021.00     -0.103     -0.279       0.142      -0.862
+52022.00     -0.111     -0.289       0.089      -0.781
+52023.00     -0.107     -0.288       0.031      -0.641
+52024.00     -0.096     -0.287       0.036      -0.365
+52025.00     -0.141     -0.329       0.065      -0.186
+52026.00     -0.137     -0.321       0.187      -0.243
+52027.00     -0.127     -0.318       0.366      -0.267
+52028.00     -0.111     -0.314       0.476      -0.360
+52029.00     -0.104     -0.296       0.444      -0.199
+52030.00     -0.114     -0.277       0.251      -0.254
+52031.00     -0.128     -0.278       0.016      -0.309
+52032.00     -0.150     -0.319      -0.127      -0.359
+52033.00     -0.151     -0.324      -0.163      -0.596
+52034.00     -0.158     -0.304      -0.037      -0.625
+52035.00     -0.175     -0.288       0.088      -0.258
+52036.00     -0.190     -0.293       0.041      -0.195
+52037.00     -0.194     -0.306      -0.024      -0.205
+52038.00     -0.186     -0.307      -0.084      -0.451
+52039.00     -0.193     -0.332      -0.034      -0.547
+52040.00     -0.186     -0.339       0.055      -0.572
+52041.00     -0.177     -0.347       0.227      -0.583
+52042.00     -0.160     -0.343       0.313      -0.536
+52043.00     -0.139     -0.331       0.330      -0.517
+52044.00     -0.128     -0.317       0.253      -0.374
+52045.00     -0.134     -0.293       0.137      -0.305
+52046.00     -0.158     -0.246      -0.021      -0.075
+52047.00     -0.172     -0.234      -0.091      -0.052
+52048.00     -0.181     -0.255      -0.017      -0.127
+52049.00     -0.184     -0.286       0.026      -0.312
+52050.00     -0.185     -0.294       0.026      -0.394
+52051.00     -0.186     -0.284      -0.029      -0.414
+52052.00     -0.183     -0.277      -0.029      -0.308
+52053.00     -0.165     -0.261       0.051      -0.286
+52054.00     -0.148     -0.253       0.165      -0.268
+52055.00     -0.135     -0.249       0.336      -0.392
+52056.00     -0.134     -0.255       0.442      -0.488
+52057.00     -0.140     -0.257       0.401      -0.454
+52058.00     -0.146     -0.237       0.237      -0.360
+52059.00     -0.149     -0.207      -0.010      -0.257
+52060.00     -0.157     -0.224      -0.278      -0.099
+52061.00     -0.168     -0.215      -0.469      -0.079
+52062.00     -0.186     -0.211      -0.575      -0.063
+52063.00     -0.205     -0.220      -0.508      -0.036
+52064.00     -0.220     -0.246      -0.137       0.002
+52065.00     -0.221     -0.270      -0.039      -0.131
+52066.00     -0.209     -0.271      -0.022      -0.199
+52067.00     -0.168     -0.241       0.031      -0.400
+52068.00     -0.158     -0.236       0.162      -0.592
+52069.00     -0.145     -0.239       0.244      -0.738
+52070.00     -0.124     -0.236       0.297      -0.834
+52071.00     -0.110     -0.229       0.309      -0.916
+52072.00     -0.116     -0.222       0.178      -0.744
+52073.00     -0.135     -0.208       0.001      -0.363
+52074.00     -0.191     -0.146      -0.261      -0.157
+52075.00     -0.196     -0.129      -0.348       0.044
+52076.00     -0.198     -0.156      -0.359       0.081
+52077.00     -0.195     -0.200      -0.180       0.111
+52078.00     -0.190     -0.213      -0.050       0.069
+52079.00     -0.192     -0.192      -0.027      -0.100
+52080.00     -0.199     -0.172      -0.019      -0.124
+52081.00     -0.200     -0.111       0.062       0.002
+52082.00     -0.181     -0.106       0.225       0.141
+52083.00     -0.159     -0.100       0.233       0.018
+52084.00     -0.152     -0.107       0.179      -0.188
+52085.00     -0.158     -0.117       0.111      -0.324
+52086.00     -0.166     -0.111       0.003      -0.360
+52087.00     -0.169     -0.084      -0.059      -0.214
+52088.00     -0.212     -0.056      -0.253      -0.176
+52089.00     -0.224     -0.028      -0.426      -0.088
+52090.00     -0.242     -0.021      -0.520      -0.042
+52091.00     -0.258     -0.042      -0.457      -0.025
+52092.00     -0.267     -0.081      -0.277      -0.117
+52093.00     -0.264     -0.110      -0.028      -0.148
+52094.00     -0.247     -0.114       0.122      -0.151
+52095.00     -0.263     -0.096      -0.271      -0.153
+52096.00     -0.246     -0.089      -0.427      -0.091
+52097.00     -0.231     -0.082      -0.460      -0.085
+52098.00     -0.214     -0.068      -0.394      -0.107
+52099.00     -0.206     -0.057      -0.278      -0.213
+52100.00     -0.220     -0.066      -0.167      -0.219
+52101.00     -0.242     -0.079      -0.133      -0.088
+52102.00     -0.274     -0.074      -0.289      -0.131
+52103.00     -0.272     -0.060      -0.472      -0.152
+52104.00     -0.269     -0.078      -0.435      -0.250
+52105.00     -0.265     -0.121      -0.305      -0.367
+52106.00     -0.257     -0.138      -0.153      -0.267
+52107.00     -0.251     -0.117      -0.094      -0.209
+52108.00     -0.247     -0.091      -0.054      -0.109
+52109.00     -0.216     -0.088       0.193       0.158
+52110.00     -0.204     -0.074       0.426       0.521
+52111.00     -0.198     -0.063       0.493       0.650
+52112.00     -0.195     -0.067       0.434       0.453
+52113.00     -0.194     -0.078       0.255       0.297
+52114.00     -0.196     -0.079       0.100       0.054
+52115.00     -0.204     -0.074      -0.167      -0.116
+52116.00     -0.238     -0.045      -0.294      -0.230
+52117.00     -0.245     -0.020      -0.468      -0.375
+52118.00     -0.253      0.006      -0.595      -0.359
+52119.00     -0.260      0.005      -0.628      -0.176
+52120.00     -0.261     -0.025      -0.463      -0.209
+52121.00     -0.253     -0.051      -0.214      -0.179
+52122.00     -0.234     -0.056       0.024      -0.013
+52123.00     -0.214     -0.033       0.126       0.024
+52124.00     -0.186     -0.021       0.094       0.228
+52125.00     -0.179     -0.007       0.121       0.255
+52126.00     -0.178      0.019       0.135       0.208
+52127.00     -0.180      0.038       0.127      -0.040
+52128.00     -0.192      0.029       0.161      -0.044
+52129.00     -0.208      0.004       0.050      -0.041
+52130.00     -0.244     -0.012      -0.136      -0.066
+52131.00     -0.242     -0.003      -0.296      -0.247
+52132.00     -0.244     -0.010      -0.341      -0.272
+52133.00     -0.246     -0.039      -0.191      -0.256
+52134.00     -0.241     -0.054      -0.046      -0.085
+52135.00     -0.231     -0.042       0.026      -0.107
+52136.00     -0.214     -0.022       0.005      -0.115
+52137.00     -0.166      0.002      -0.050      -0.073
+52138.00     -0.147      0.027      -0.040       0.123
+52139.00     -0.151      0.042      -0.114       0.201
+52140.00     -0.165      0.030      -0.183      -0.005
+52141.00     -0.168      0.013      -0.235      -0.097
+52142.00     -0.165      0.011      -0.252       0.001
+52143.00     -0.174      0.009      -0.215       0.080
+52144.00     -0.179     -0.009      -0.263       0.038
+52145.00     -0.184     -0.007      -0.331      -0.081
+52146.00     -0.181      0.018      -0.494      -0.152
+52147.00     -0.176      0.032      -0.598      -0.007
+52148.00     -0.169      0.013      -0.581       0.166
+52149.00     -0.158     -0.010      -0.402       0.179
+52150.00     -0.142     -0.012      -0.132       0.046
+52151.00     -0.121     -0.000       0.057       0.094
+52152.00     -0.105      0.010       0.126       0.156
+52153.00     -0.107      0.021       0.185       0.038
+52154.00     -0.119      0.037       0.208       0.088
+52155.00     -0.128      0.051       0.030       0.609
+52156.00     -0.133      0.052      -0.028       0.257
+52157.00     -0.140      0.041      -0.071       0.055
+52158.00     -0.142      0.040      -0.098       0.096
+52159.00     -0.146      0.042      -0.065       0.200
+52160.00     -0.151      0.035       0.017       0.316
+52161.00     -0.154      0.014       0.134       0.326
+52162.00     -0.149     -0.000       0.285       0.304
+52163.00     -0.136      0.003       0.310       0.227
+52164.00     -0.118      0.019       0.241       0.035
+52165.00     -0.120      0.010       0.162      -0.133
+52166.00     -0.098      0.039       0.054      -0.270
+52167.00     -0.095      0.053      -0.032      -0.347
+52168.00     -0.109      0.035      -0.120      -0.627
+52169.00     -0.119      0.015      -0.066      -0.666
+52170.00     -0.121      0.024      -0.085      -0.486
+52171.00     -0.127      0.045      -0.136      -0.146
+52172.00     -0.139      0.044      -0.179       0.043
+52173.00     -0.141      0.038      -0.227      -0.053
+52174.00     -0.133      0.046      -0.266      -0.170
+52175.00     -0.121      0.051      -0.283       0.063
+52176.00     -0.108      0.031      -0.273       0.185
+52177.00     -0.093      0.007      -0.134       0.118
+52178.00     -0.077      0.008      -0.009      -0.104
+52179.00     -0.062      0.024       0.147      -0.418
+52180.00     -0.053      0.035       0.201      -0.363
+52181.00     -0.082      0.082       0.247      -0.350
+52182.00     -0.096      0.082       0.285      -0.288
+52183.00     -0.103      0.085       0.223      -0.200
+52184.00     -0.102      0.093       0.158      -0.188
+52185.00     -0.103      0.103       0.020      -0.054
+52186.00     -0.109      0.106       0.025       0.092
+52187.00     -0.111      0.097       0.051       0.173
+52188.00     -0.106      0.118       0.091       0.234
+52189.00     -0.104      0.095       0.121       0.182
+52190.00     -0.095      0.079       0.146       0.136
+52191.00     -0.073      0.075       0.158       0.183
+52192.00     -0.049      0.082       0.041       0.284
+52193.00     -0.034      0.100      -0.193       0.494
+52194.00     -0.029      0.118      -0.401       0.661
+52195.00     -0.050      0.190      -0.593       0.764
+52196.00     -0.058      0.160      -0.563       0.618
+52197.00     -0.068      0.138      -0.450       0.375
+52198.00     -0.075      0.151      -0.250       0.296
+52199.00     -0.082      0.181      -0.146       0.134
+52200.00     -0.086      0.192      -0.127      -0.137
+52201.00     -0.084      0.185      -0.072      -0.548
+52202.00     -0.079      0.160      -0.070      -1.022
+52203.00     -0.069      0.144       0.003      -1.053
+52204.00     -0.053      0.118       0.011      -0.584
+52205.00     -0.031      0.095       0.056      -0.233
+52206.00     -0.006      0.091       0.150      -0.002
+52207.00      0.017      0.097       0.313       0.041
+52208.00      0.027      0.093       0.464       0.185
+52209.00      0.021      0.085       0.551       0.264
+52210.00      0.009      0.084       0.632       0.341
+52211.00      0.004      0.095       0.605       0.187
+52212.00      0.004      0.112       0.455       0.025
+52213.00     -0.001      0.127       0.197      -0.095
+52214.00     -0.008      0.126       0.007       0.053
+52215.00     -0.007      0.101      -0.098       0.059
+52216.00     -0.033      0.126      -0.123       0.209
+52217.00     -0.026      0.108      -0.068       0.187
+52218.00     -0.021      0.107       0.069       0.069
+52219.00     -0.003      0.108       0.190       0.010
+52220.00      0.023      0.104       0.288       0.061
+52221.00      0.041      0.108       0.151       0.304
+52222.00      0.040      0.117       0.002       0.562
+52223.00      0.030      0.172      -0.056       0.794
+52224.00      0.018      0.140      -0.048       0.785
+52225.00      0.010      0.116       0.099       0.714
+52226.00      0.005      0.121       0.190       0.497
+52227.00      0.007      0.136       0.186       0.047
+52228.00      0.008      0.140       0.063       0.047
+52229.00      0.011      0.130       0.007       0.070
+52230.00      0.006      0.130       0.007      -0.112
+52231.00      0.014      0.113       0.031       0.041
+52232.00      0.027      0.089       0.089       0.052
+52233.00      0.052      0.077       0.126       0.120
+52234.00      0.082      0.085       0.121       0.080
+52235.00      0.107      0.089       0.177       0.008
+52236.00      0.115      0.074       0.225       0.336
+52237.00      0.109      0.063       0.260       0.584
+52238.00      0.095      0.066       0.229       0.719
+52239.00      0.085      0.090       0.205       0.784
+52240.00      0.076      0.112       0.149       0.465
+52241.00      0.065      0.117       0.148       0.115
+52242.00      0.057      0.102       0.154      -0.166
+52243.00      0.060      0.072       0.219      -0.293
+52244.00      0.089      0.049       0.269      -0.254
+52245.00      0.096      0.037       0.336      -0.041
+52246.00      0.099      0.047       0.366      -0.087
+52247.00      0.103      0.057       0.395      -0.084
+52248.00      0.113      0.054       0.438      -0.015
+52249.00      0.124      0.054       0.411       0.215
+52250.00      0.123      0.066       0.272       0.396
+52251.00      0.138      0.071       0.096       0.560
+52252.00      0.119      0.058      -0.032       0.684
+52253.00      0.107      0.037      -0.141       0.823
+52254.00      0.106      0.029      -0.163       0.834
+52255.00      0.077      0.038      -0.193       0.799
+52256.00      0.082      0.033      -0.257       0.654
+52257.00      0.081      0.026      -0.265       0.461
+52258.00      0.081      0.025      -0.220       0.249
+52259.00      0.088      0.015      -0.022       0.061
+52260.00      0.102     -0.004       0.170      -0.117
+52261.00      0.121     -0.014       0.324      -0.134
+52262.00      0.141      0.001       0.400       0.002
+52263.00      0.153      0.022       0.465       0.158
+52264.00      0.148      0.018       0.365       0.497
+52265.00      0.213     -0.095       0.223       0.893
+52266.00      0.195     -0.097       0.093       1.034
+52267.00      0.178     -0.078      -0.158       1.021
+52268.00      0.159     -0.066      -0.245       0.550
+52269.00      0.144     -0.078      -0.283       0.124
+52270.00      0.140     -0.099      -0.235      -0.208
+52271.00      0.159     -0.112      -0.173      -0.420
+52272.00      0.168     -0.131      -0.020      -0.190
+52273.00      0.177     -0.139       0.122       0.155
+52274.00      0.183     -0.129       0.206       0.489
+52275.00      0.185     -0.118       0.591       0.263
+52276.00      0.181     -0.118       0.445      -0.050
+52277.00      0.172     -0.115       0.307      -0.139
+52278.00      0.163     -0.095       0.205      -0.174
+52279.00      0.140     -0.071       0.137      -0.007
+52280.00      0.125     -0.067       0.057       0.149
+52281.00      0.108     -0.081       0.038       0.151
+52282.00      0.101     -0.096       0.043       0.224
+52283.00      0.115     -0.115       0.159       0.190
+52284.00      0.121     -0.123       0.242       0.058
+52285.00      0.119     -0.123       0.293      -0.036
+52286.00      0.134     -0.113       0.236      -0.152
+52287.00      0.141     -0.114       0.199      -0.204
+52288.00      0.155     -0.137       0.190      -0.178
+52289.00      0.170     -0.159       0.190      -0.248
+52290.00      0.180     -0.151       0.211      -0.289
+52291.00      0.178     -0.118       0.207      -0.299
+52292.00      0.162     -0.097       0.203      -0.121
+52293.00      0.141     -0.133       0.236       0.087
+52294.00      0.128     -0.138       0.208       0.227
+52295.00      0.110     -0.140       0.218       0.271
+52296.00      0.087     -0.153       0.229       0.167
+52297.00      0.073     -0.176       0.324       0.051
+52298.00      0.075     -0.188       0.274      -0.073
+52299.00      0.087     -0.193       0.216      -0.152
+52300.00      0.116     -0.188       0.230      -0.236
+52301.00      0.137     -0.190       0.324      -0.155
+52302.00      0.153     -0.166       0.345       0.091
+52303.00      0.149     -0.140       0.123      -0.037
+52304.00      0.130     -0.142      -0.008      -0.142
+52305.00      0.112     -0.155      -0.049      -0.270
+52306.00      0.100     -0.150       0.138      -0.131
+52307.00      0.089     -0.144       0.306      -0.006
+52308.00      0.080     -0.145       0.364       0.151
+52309.00      0.068     -0.160       0.336       0.165
+52310.00      0.055     -0.170      -0.078       0.181
+52311.00      0.050     -0.180      -0.052       0.124
+52312.00      0.052     -0.193       0.076       0.065
+52313.00      0.059     -0.201       0.255      -0.092
+52314.00      0.107     -0.190       0.305      -0.089
+52315.00      0.123     -0.190       0.321      -0.017
+52316.00      0.143     -0.203       0.264       0.025
+52317.00      0.159     -0.218       0.245       0.023
+52318.00      0.167     -0.214       0.242      -0.103
+52319.00      0.161     -0.188       0.252      -0.105
+52320.00      0.143     -0.165       0.237      -0.075
+52321.00      0.118     -0.179       0.241       0.036
+52322.00      0.108     -0.179       0.226       0.019
+52323.00      0.097     -0.188       0.215       0.062
+52324.00      0.081     -0.213       0.290       0.145
+52325.00      0.075     -0.238       0.366       0.184
+52326.00      0.084     -0.237       0.398       0.064
+52327.00      0.094     -0.229       0.325      -0.285
+52328.00      0.132     -0.277       0.314      -0.598
+52329.00      0.155     -0.291       0.377      -0.621
+52330.00      0.179     -0.251       0.403      -0.402
+52331.00      0.171     -0.183       0.213      -0.143
+52332.00      0.136     -0.166      -0.045      -0.238
+52333.00      0.112     -0.203      -0.103      -0.305
+52334.00      0.112     -0.231       0.158      -0.160
+52335.00      0.082     -0.213       0.359       0.113
+52336.00      0.069     -0.209       0.557       0.450
+52337.00      0.054     -0.216       0.547       0.465
+52338.00      0.044     -0.220       0.426       0.445
+52339.00      0.037     -0.225       0.340       0.334
+52340.00      0.036     -0.242       0.293       0.217
+52341.00      0.045     -0.265       0.331      -0.109
+52342.00      0.090     -0.268       0.374      -0.306
+52343.00      0.114     -0.265       0.354      -0.387
+52344.00      0.139     -0.253       0.268      -0.276
+52345.00      0.152     -0.233       0.213      -0.181
+52346.00      0.146     -0.207       0.255      -0.217
+52347.00      0.133     -0.191       0.263      -0.333
+52348.00      0.111     -0.190       0.289      -0.272
+52349.00      0.088     -0.197       0.263      -0.038
+52350.00      0.076     -0.198       0.234       0.041
+52351.00      0.072     -0.199       0.251       0.095
+52352.00      0.068     -0.215       0.287       0.174
+52353.00      0.074     -0.237       0.378       0.210
+52354.00      0.096     -0.235       0.414       0.208
+52355.00      0.114     -0.222       0.350      -0.053
+52356.00      0.117     -0.237       0.288      -0.498
+52357.00      0.120     -0.267       0.291      -0.685
+52358.00      0.131     -0.248       0.351      -0.540
+52359.00      0.123     -0.179       0.287      -0.235
+52360.00      0.091     -0.151       0.143      -0.172
+52361.00      0.070     -0.183       0.097      -0.173
+52362.00      0.080     -0.226       0.280      -0.199
+52363.00      0.090     -0.231       0.554      -0.013
+52364.00      0.073     -0.213       0.746       0.034
+52365.00      0.046     -0.201       0.735      -0.062
+52366.00      0.033     -0.201       0.589      -0.185
+52367.00      0.035     -0.212       0.431      -0.249
+52368.00      0.028     -0.232       0.265      -0.188
+52369.00      0.042     -0.258       0.249      -0.199
+52370.00      0.061     -0.270       0.202      -0.298
+52371.00      0.085     -0.264       0.148      -0.349
+52372.00      0.105     -0.240       0.007      -0.270
+52373.00      0.106     -0.200      -0.085      -0.119
+52374.00      0.090     -0.161      -0.051      -0.056
+52375.00      0.069     -0.150       0.030      -0.194
+52376.00      0.051     -0.171       0.108      -0.168
+52377.00     -0.003     -0.200       0.175      -0.116
+52378.00     -0.010     -0.209       0.240      -0.044
+52379.00     -0.003     -0.203       0.252       0.008
+52380.00      0.005     -0.205       0.244      -0.003
+52381.00      0.011     -0.199       0.236      -0.042
+52382.00      0.029     -0.208       0.246      -0.098
+52383.00      0.059     -0.200       0.215      -0.109
+52384.00      0.079     -0.194       0.190      -0.176
+52385.00      0.077     -0.200       0.115      -0.227
+52386.00      0.063     -0.200       0.067      -0.130
+52387.00      0.046     -0.182       0.035      -0.091
+52388.00      0.026     -0.171       0.026      -0.125
+52389.00      0.016     -0.185       0.069      -0.252
+52390.00      0.022     -0.203       0.196      -0.166
+52391.00      0.004     -0.204       0.339      -0.014
+52392.00     -0.008     -0.189       0.382       0.051
+52393.00     -0.030     -0.178       0.293      -0.070
+52394.00     -0.040     -0.178       0.154      -0.261
+52395.00     -0.031     -0.195      -0.038      -0.391
+52396.00     -0.011     -0.221      -0.123      -0.339
+52397.00      0.009     -0.237       0.002      -0.212
+52398.00      0.022     -0.206       0.181      -0.187
+52399.00      0.039     -0.189       0.312      -0.149
+52400.00      0.047     -0.172       0.274       0.130
+52401.00      0.034     -0.149       0.182       0.439
+52402.00      0.011     -0.130       0.093       0.389
+52403.00     -0.009     -0.128       0.067       0.180
+52404.00     -0.014     -0.151       0.053      -0.153
+52405.00      0.006     -0.179       0.103      -0.283
+52406.00      0.007     -0.187       0.173      -0.229
+52407.00      0.014     -0.185       0.201      -0.137
+52408.00      0.024     -0.187       0.216      -0.046
+52409.00      0.026     -0.206       0.181      -0.079
+52410.00      0.025     -0.222       0.202      -0.164
+52411.00      0.041     -0.224       0.235      -0.120
+52412.00      0.066     -0.204       0.306      -0.035
+52413.00      0.074     -0.175       0.245       0.036
+52414.00      0.053     -0.156       0.117       0.109
+52415.00      0.024     -0.167      -0.014       0.036
+52416.00      0.006     -0.198      -0.115      -0.234
+52417.00     -0.002     -0.221      -0.076      -0.357
+52418.00     -0.006     -0.221       0.028      -0.313
+52419.00     -0.012     -0.213       0.175      -0.032
+52420.00     -0.018     -0.215       0.258       0.137
+52421.00     -0.021     -0.223       0.260       0.115
+52422.00     -0.017     -0.226       0.245      -0.004
+52423.00     -0.004     -0.230       0.194       0.004
+52424.00      0.014     -0.242       0.156      -0.087
+52425.00      0.031     -0.245       0.111      -0.227
+52426.00      0.045     -0.227       0.225      -0.307
+52427.00      0.052     -0.204       0.312      -0.270
+52428.00      0.045     -0.193       0.307      -0.215
+52429.00      0.022     -0.192       0.262      -0.046
+52430.00     -0.005     -0.189       0.130       0.046
+52431.00     -0.018     -0.192       0.046      -0.079
+52432.00     -0.014     -0.209       0.001      -0.321
+52433.00      0.044     -0.249       0.045      -0.514
+52434.00      0.040     -0.257       0.140      -0.480
+52435.00      0.038     -0.259       0.162      -0.306
+52436.00      0.042     -0.268       0.143      -0.162
+52437.00      0.048     -0.282       0.131      -0.162
+52438.00      0.052     -0.289       0.122      -0.182
+52439.00      0.058     -0.285       0.179      -0.218
+52440.00      0.085     -0.286       0.276      -0.197
+52441.00      0.088     -0.254       0.325      -0.151
+52442.00      0.076     -0.216       0.238      -0.175
+52443.00      0.054     -0.204       0.123      -0.233
+52444.00      0.036     -0.227       0.000      -0.278
+52445.00      0.025     -0.259      -0.008      -0.289
+52446.00      0.015     -0.273       0.040      -0.177
+52447.00      0.029     -0.297       0.100      -0.060
+52448.00      0.027     -0.311       0.182      -0.014
+52449.00      0.038     -0.328       0.228      -0.077
+52450.00      0.056     -0.324       0.268      -0.207
+52451.00      0.073     -0.308       0.287      -0.266
+52452.00      0.084     -0.298       0.319      -0.392
+52453.00      0.091     -0.294       0.289      -0.376
+52454.00      0.074     -0.318       0.262      -0.455
+52455.00      0.070     -0.304       0.172      -0.380
+52456.00      0.051     -0.301       0.100      -0.191
+52457.00      0.022     -0.306       0.071      -0.116
+52458.00      0.001     -0.300       0.082      -0.235
+52459.00     -0.006     -0.294       0.159      -0.474
+52460.00     -0.007     -0.312       0.168      -0.740
+52461.00     -0.010     -0.348       0.250      -0.877
+52462.00     -0.016     -0.370       0.267      -0.796
+52463.00     -0.018     -0.369       0.170      -0.537
+52464.00     -0.012     -0.363       0.067      -0.233
+52465.00      0.003     -0.361       0.063      -0.022
+52466.00      0.020     -0.349       0.146      -0.074
+52467.00      0.028     -0.331       0.192      -0.158
+52468.00     -0.006     -0.317       0.242      -0.370
+52469.00     -0.021     -0.311       0.195      -0.419
+52470.00     -0.033     -0.291       0.147      -0.304
+52471.00     -0.041     -0.262       0.091      -0.200
+52472.00     -0.051     -0.246       0.062      -0.269
+52473.00     -0.065     -0.252       0.068      -0.293
+52474.00     -0.078     -0.272       0.109      -0.416
+52475.00     -0.080     -0.345       0.150      -0.396
+52476.00     -0.071     -0.371       0.129      -0.408
+52477.00     -0.053     -0.380       0.049      -0.330
+52478.00     -0.030     -0.364       0.019      -0.160
+52479.00     -0.010     -0.335       0.028      -0.058
+52480.00      0.000     -0.316       0.165      -0.036
+52481.00      0.001     -0.310       0.319      -0.166
+52482.00     -0.013     -0.302       0.477      -0.306
+52483.00     -0.023     -0.296       0.581      -0.335
+52484.00     -0.046     -0.305       0.549      -0.286
+52485.00     -0.071     -0.316       0.375      -0.214
+52486.00     -0.085     -0.304       0.076      -0.308
+52487.00     -0.089     -0.284      -0.125      -0.369
+52488.00     -0.095     -0.297      -0.177      -0.490
+52489.00     -0.102     -0.345       0.031      -0.569
+52490.00     -0.098     -0.378       0.214      -0.507
+52491.00     -0.080     -0.363       0.338      -0.379
+52492.00     -0.062     -0.325       0.363      -0.254
+52493.00     -0.076     -0.314       0.359      -0.085
+52494.00     -0.070     -0.295       0.330       0.054
+52495.00     -0.073     -0.284       0.274      -0.086
+52496.00     -0.088     -0.288       0.101      -0.216
+52497.00     -0.110     -0.302      -0.012      -0.341
+52498.00     -0.129     -0.307      -0.067      -0.269
+52499.00     -0.137     -0.299      -0.103      -0.114
+52500.00     -0.139     -0.286      -0.114      -0.046
+52501.00     -0.145     -0.274      -0.147      -0.105
+52502.00     -0.152     -0.272      -0.073      -0.313
+52503.00     -0.171     -0.276       0.031      -0.395
+52504.00     -0.159     -0.296       0.108      -0.425
+52505.00     -0.141     -0.302       0.175      -0.378
+52506.00     -0.123     -0.282       0.121      -0.239
+52507.00     -0.094     -0.278       0.026      -0.175
+52508.00     -0.084     -0.264      -0.047      -0.034
+52509.00     -0.088     -0.257      -0.106      -0.211
+52510.00     -0.092     -0.238      -0.043      -0.332
+52511.00     -0.103     -0.228       0.040      -0.502
+52512.00     -0.119     -0.238       0.062      -0.398
+52513.00     -0.135     -0.259       0.063      -0.280
+52514.00     -0.142     -0.261      -0.059      -0.172
+52515.00     -0.165     -0.234      -0.119      -0.186
+52516.00     -0.175     -0.233      -0.052      -0.215
+52517.00     -0.179     -0.264       0.183      -0.100
+52518.00     -0.164     -0.283       0.348       0.052
+52519.00     -0.134     -0.256       0.370      -0.016
+52520.00     -0.111     -0.208       0.220      -0.034
+52521.00     -0.105     -0.177       0.055      -0.114
+52522.00     -0.115     -0.174      -0.044      -0.131
+52523.00     -0.132     -0.191      -0.163      -0.252
+52524.00     -0.146     -0.215      -0.248      -0.529
+52525.00     -0.154     -0.223      -0.193      -0.638
+52526.00     -0.168     -0.210      -0.084      -0.458
+52527.00     -0.189     -0.207      -0.010      -0.183
+52528.00     -0.200     -0.245      -0.044      -0.089
+52529.00     -0.188     -0.262      -0.073      -0.188
+52530.00     -0.170     -0.246      -0.066      -0.273
+52531.00     -0.159     -0.223      -0.009      -0.232
+52532.00     -0.153     -0.221       0.021      -0.149
+52533.00     -0.146     -0.227       0.118      -0.119
+52534.00     -0.138     -0.219       0.157      -0.020
+52535.00     -0.130     -0.204       0.090      -0.009
+52536.00     -0.126     -0.200       0.048       0.049
+52537.00     -0.134     -0.198       0.003      -0.058
+52538.00     -0.112     -0.167       0.003      -0.210
+52539.00     -0.123     -0.150       0.058      -0.420
+52540.00     -0.128     -0.152       0.055      -0.320
+52541.00     -0.132     -0.175       0.057      -0.236
+52542.00     -0.136     -0.190       0.045      -0.113
+52543.00     -0.141     -0.185       0.045      -0.119
+52544.00     -0.151     -0.180       0.126      -0.177
+52545.00     -0.153     -0.191       0.263      -0.035
+52546.00     -0.136     -0.191       0.344       0.088
+52547.00     -0.111     -0.165       0.276       0.103
+52548.00     -0.098     -0.138       0.051      -0.021
+52549.00     -0.074     -0.104      -0.057      -0.025
+52550.00     -0.080     -0.119      -0.070       0.109
+52551.00     -0.094     -0.143      -0.031       0.043
+52552.00     -0.129     -0.172       0.053      -0.226
+52553.00     -0.131     -0.169       0.124      -0.502
+52554.00     -0.140     -0.121       0.132      -0.456
+52555.00     -0.170     -0.082      -0.013      -0.215
+52556.00     -0.199     -0.104      -0.153      -0.033
+52557.00     -0.189     -0.150      -0.251      -0.019
+52558.00     -0.151     -0.153      -0.197      -0.042
+52559.00     -0.121     -0.116      -0.093       0.101
+52560.00     -0.112     -0.095      -0.015       0.335
+52561.00     -0.109     -0.098       0.014       0.295
+52562.00     -0.106     -0.095       0.059       0.056
+52563.00     -0.144     -0.097      -0.029      -0.119
+52564.00     -0.146     -0.093      -0.114      -0.043
+52565.00     -0.156     -0.096      -0.180       0.006
+52566.00     -0.171     -0.094      -0.201      -0.045
+52567.00     -0.179     -0.084      -0.206      -0.110
+52568.00     -0.176     -0.081      -0.184      -0.225
+52569.00     -0.174     -0.091      -0.171      -0.145
+52570.00     -0.177     -0.104      -0.186       0.019
+52571.00     -0.181     -0.112      -0.175       0.053
+52572.00     -0.183     -0.122      -0.170      -0.044
+52573.00     -0.229     -0.146      -0.101      -0.021
+52574.00     -0.206     -0.139      -0.019       0.083
+52575.00     -0.179     -0.119      -0.027       0.050
+52576.00     -0.165     -0.107      -0.045       0.042
+52577.00     -0.166     -0.115      -0.075      -0.044
+52578.00     -0.169     -0.128      -0.039      -0.005
+52579.00     -0.176     -0.140      -0.029      -0.058
+52580.00     -0.206     -0.154      -0.002      -0.214
+52581.00     -0.217     -0.157       0.013      -0.227
+52582.00     -0.224     -0.120       0.029      -0.160
+52583.00     -0.241     -0.069      -0.096       0.131
+52584.00     -0.261     -0.062      -0.207       0.311
+52585.00     -0.259     -0.097      -0.206       0.116
+52586.00     -0.229     -0.118      -0.073      -0.048
+52587.00     -0.195     -0.102       0.086       0.073
+52588.00     -0.171     -0.084       0.133       0.338
+52589.00     -0.154     -0.077       0.135       0.321
+52590.00     -0.140     -0.066       0.076       0.123
+52591.00     -0.169     -0.052       0.008      -0.163
+52592.00     -0.174     -0.042      -0.164      -0.244
+52593.00     -0.187     -0.046      -0.249      -0.137
+52594.00     -0.200     -0.051      -0.265      -0.076
+52595.00     -0.205     -0.050      -0.195       0.007
+52596.00     -0.202     -0.050      -0.102      -0.064
+52597.00     -0.202     -0.052      -0.009      -0.062
+52598.00     -0.208     -0.061       0.068      -0.007
+52599.00     -0.207     -0.080       0.149      -0.023
+52600.00     -0.197     -0.100       0.147      -0.104
+52601.00     -0.173     -0.100       0.093      -0.155
+52602.00     -0.153     -0.087      -0.019      -0.144
+52603.00     -0.129     -0.062      -0.089      -0.060
+52604.00     -0.114     -0.047      -0.169      -0.015
+52605.00     -0.121     -0.049      -0.264      -0.111
+52606.00     -0.142     -0.059      -0.378      -0.052
+52607.00     -0.160     -0.074      -0.410      -0.057
+52608.00     -0.225     -0.089      -0.323      -0.004
+52609.00     -0.232     -0.102      -0.183       0.032
+52610.00     -0.233     -0.090      -0.131      -0.329
+52611.00     -0.228     -0.062      -0.111      -0.055
+52612.00     -0.221     -0.051      -0.091       0.134
+52613.00     -0.211     -0.065      -0.066       0.046
+52614.00     -0.197     -0.079       0.022      -0.053
+52615.00     -0.181     -0.077       0.074       0.029
+52616.00     -0.163     -0.067       0.025       0.129
+52617.00     -0.142     -0.052      -0.051       0.208
+52618.00     -0.125     -0.029      -0.112       0.051
+52619.00     -0.111     -0.011      -0.125      -0.108
+52620.00     -0.122     -0.011      -0.084      -0.178
+52621.00     -0.140     -0.023      -0.044      -0.038
+52622.00     -0.156     -0.024      -0.047       0.081
+52623.00     -0.162     -0.016      -0.029       0.090
+52624.00     -0.163     -0.014      -0.075       0.073
+52625.00     -0.169     -0.024      -0.117      -0.100
+52626.00     -0.185     -0.034      -0.090      -0.054
+52627.00     -0.179     -0.063      -0.064       0.021
+52628.00     -0.157     -0.085      -0.065      -0.043
+52629.00     -0.149     -0.038      -0.082      -0.150
+52630.00     -0.137     -0.009      -0.025      -0.277
+52631.00     -0.131      0.027       0.056      -0.429
+52632.00     -0.131      0.046       0.140      -0.339
+52633.00     -0.147      0.043       0.210      -0.225
+52634.00     -0.178      0.029       0.229      -0.057
+52635.00     -0.202      0.004       0.158       0.014
+52636.00     -0.148     -0.023       0.070       0.017
+52637.00     -0.138     -0.033       0.018       0.054
+52638.00     -0.128     -0.015      -0.003       0.112
+52639.00     -0.121      0.009      -0.071       0.177
+52640.00     -0.115      0.010      -0.083       0.154
+52641.00     -0.108     -0.008      -0.076       0.090
+52642.00     -0.101     -0.021      -0.001       0.035
+52643.00     -0.093     -0.021       0.073       0.055
+52644.00     -0.083     -0.012       0.061       0.113
+52645.00     -0.074      0.006       0.062       0.085
+52646.00     -0.071      0.035       0.035       0.012
+52647.00     -0.079      0.053      -0.005      -0.130
+52648.00     -0.097      0.043      -0.003      -0.124
+52649.00     -0.119      0.020      -0.003      -0.056
+52650.00     -0.126      0.051       0.002       0.083
+52651.00     -0.135      0.068      -0.031       0.130
+52652.00     -0.140      0.076      -0.037       0.047
+52653.00     -0.144      0.057      -0.069      -0.016
+52654.00     -0.143      0.026      -0.074      -0.162
+52655.00     -0.128     -0.001      -0.076      -0.139
+52656.00     -0.106     -0.017      -0.043      -0.004
+52657.00     -0.084     -0.012      -0.054      -0.015
+52658.00     -0.076      0.018      -0.065      -0.025
+52659.00     -0.083      0.051      -0.101       0.037
+52660.00     -0.099      0.060      -0.089       0.003
+52661.00     -0.121      0.045      -0.022       0.058
+52662.00     -0.144      0.025       0.022       0.081
+52663.00     -0.160      0.009       0.052       0.088
+52664.00     -0.149      0.009       0.072       0.025
+52665.00     -0.140      0.006       0.009       0.018
+52666.00     -0.130      0.025      -0.014       0.030
+52667.00     -0.124      0.047      -0.067      -0.001
+52668.00     -0.125      0.043      -0.081      -0.068
+52669.00     -0.126     -0.002      -0.070      -0.065
+52670.00     -0.119     -0.026      -0.058      -0.095
+52671.00     -0.103     -0.034      -0.004       0.004
+52672.00     -0.084     -0.035       0.010       0.153
+52673.00     -0.073     -0.026      -0.001       0.191
+52674.00     -0.075      0.001      -0.003       0.138
+52675.00     -0.087      0.031      -0.017       0.078
+52676.00     -0.107      0.038      -0.002       0.073
+52677.00     -0.126      0.022       0.046       0.098
+52678.00     -0.138      0.015       0.093       0.088
+52679.00     -0.146      0.024       0.074       0.131
+52680.00     -0.150      0.026       0.067       0.094
+52681.00     -0.145      0.010       0.045      -0.044
+52682.00     -0.115      0.005      -0.019      -0.061
+52683.00     -0.090      0.004      -0.058      -0.190
+52684.00     -0.070      0.005      -0.060      -0.085
+52685.00     -0.058      0.005      -0.004       0.077
+52686.00     -0.055      0.019       0.047       0.285
+52687.00     -0.061      0.038       0.001       0.368
+52688.00     -0.077      0.035      -0.078       0.211
+52689.00     -0.080     -0.001      -0.089       0.127
+52690.00     -0.091     -0.016      -0.044      -0.053
+52691.00     -0.096     -0.016       0.032      -0.004
+52692.00     -0.099     -0.016       0.018       0.000
+52693.00     -0.105     -0.022      -0.043       0.081
+52694.00     -0.108     -0.023      -0.079      -0.009
+52695.00     -0.102     -0.017      -0.021       0.021
+52696.00     -0.088     -0.018       0.038       0.030
+52697.00     -0.073     -0.029       0.123       0.044
+52698.00     -0.056     -0.039       0.147       0.047
+52699.00     -0.028     -0.015       0.174       0.256
+52700.00     -0.006     -0.021       0.121       0.249
+52701.00      0.004     -0.020       0.073       0.171
+52702.00     -0.000      0.001       0.020       0.103
+52703.00     -0.020      0.033      -0.051      -0.001
+52704.00     -0.042      0.059      -0.092       0.035
+52705.00     -0.061      0.060      -0.109       0.149
+52706.00     -0.069      0.053      -0.072       0.146
+52707.00     -0.071      0.045      -0.071       0.124
+52708.00     -0.070      0.030       0.013       0.060
+52709.00     -0.056      0.012       0.037       0.176
+52710.00     -0.025      0.018       0.048       0.189
+52711.00      0.001      0.043      -0.047       0.130
+52712.00      0.007      0.049      -0.039       0.065
+52713.00      0.002      0.030       0.118       0.201
+52714.00     -0.002      0.027       0.246       0.366
+52715.00     -0.010      0.045       0.242       0.313
+52716.00     -0.025      0.043       0.075       0.044
+52717.00     -0.033      0.013      -0.011      -0.298
+52718.00     -0.032     -0.006       0.003      -0.296
+52719.00     -0.033     -0.000       0.081      -0.132
+52720.00     -0.049     -0.004       0.044       0.058
+52721.00     -0.055     -0.021      -0.014       0.117
+52722.00     -0.054     -0.036      -0.046       0.107
+52723.00     -0.043     -0.037       0.028       0.032
+52724.00     -0.022     -0.034       0.127      -0.099
+52725.00      0.004     -0.029       0.162      -0.116
+52726.00      0.028     -0.016       0.141      -0.021
+52727.00      0.046     -0.002       0.021       0.155
+52728.00      0.057      0.008      -0.045       0.216
+52729.00      0.054      0.015      -0.033       0.194
+52730.00      0.041      0.033       0.056      -0.020
+52731.00      0.026      0.075       0.167      -0.116
+52732.00      0.003      0.086       0.236      -0.161
+52733.00     -0.013      0.080       0.271      -0.030
+52734.00     -0.014      0.071       0.212       0.012
+52735.00     -0.002      0.063       0.140       0.005
+52736.00      0.011      0.046       0.124       0.020
+52737.00      0.031      0.027       0.128       0.186
+52738.00      0.063      0.034       0.172       0.292
+52739.00      0.085      0.060       0.106       0.227
+52740.00      0.081      0.052       0.117      -0.016
+52741.00      0.067      0.010       0.243      -0.002
+52742.00      0.060     -0.005       0.385       0.099
+52743.00      0.050      0.030       0.327       0.282
+52744.00      0.032      0.049       0.140       0.172
+52745.00     -0.047      0.063       0.017      -0.077
+52746.00     -0.030      0.025       0.063      -0.052
+52747.00     -0.022      0.024       0.219       0.100
+52748.00     -0.027      0.066       0.282       0.272
+52749.00     -0.035      0.054       0.275       0.186
+52750.00     -0.021      0.039       0.198       0.007
+52751.00      0.002      0.036       0.164       0.018
+52752.00      0.022      0.035       0.174       0.017
+52753.00      0.040      0.036       0.196       0.058
+52754.00      0.055      0.049       0.151       0.151
+52755.00      0.063      0.075       0.118       0.199
+52756.00      0.060      0.093       0.074       0.221
+52757.00      0.044      0.109       0.062       0.258
+52758.00      0.022      0.124       0.097       0.137
+52759.00      0.004      0.128       0.033       0.042
+52760.00     -0.007      0.113      -0.041       0.138
+52761.00     -0.010      0.090      -0.099       0.278
+52762.00      0.007      0.072      -0.105       0.345
+52763.00      0.027      0.079      -0.050       0.188
+52764.00      0.047      0.079       0.055       0.038
+52765.00      0.060      0.065       0.152       0.083
+52766.00      0.076      0.058       0.247       0.102
+52767.00      0.091      0.065       0.204       0.104
+52768.00      0.091      0.054       0.067       0.017
+52769.00      0.113      0.034       0.062      -0.089
+52770.00      0.103      0.012       0.140       0.061
+52771.00      0.089      0.038       0.163       0.163
+52772.00      0.066      0.066       0.173       0.063
+52773.00      0.056      0.044       0.106      -0.169
+52774.00      0.074      0.004       0.176      -0.191
+52775.00      0.090     -0.005       0.260      -0.018
+52776.00      0.077      0.031       0.268       0.206
+52777.00      0.060      0.030       0.270       0.129
+52778.00      0.066      0.019       0.221       0.118
+52779.00      0.091      0.007       0.195       0.142
+52780.00      0.114     -0.007       0.191       0.234
+52781.00      0.128     -0.016       0.233       0.156
+52782.00      0.134     -0.003       0.210      -0.004
+52783.00      0.132      0.022       0.137      -0.036
+52784.00      0.119      0.036       0.040       0.011
+52785.00      0.094      0.041      -0.070       0.113
+52786.00      0.067      0.044      -0.009       0.110
+52787.00      0.070      0.048       0.063      -0.018
+52788.00      0.074      0.030       0.138      -0.117
+52789.00      0.083      0.011       0.138       0.027
+52790.00      0.091      0.010       0.171       0.125
+52791.00      0.103      0.022       0.201       0.264
+52792.00      0.116      0.026       0.254       0.197
+52793.00      0.118      0.011       0.301       0.140
+52794.00      0.115     -0.008       0.324       0.003
+52795.00      0.121     -0.011       0.314      -0.103
+52796.00      0.130     -0.003       0.192      -0.117
+52797.00      0.136      0.035       0.103      -0.047
+52798.00      0.121      0.022       0.008       0.005
+52799.00      0.100      0.011      -0.028       0.175
+52800.00      0.080     -0.001       0.067       0.107
+52801.00      0.061     -0.044       0.239      -0.010
+52802.00      0.069     -0.062       0.445      -0.180
+52803.00      0.085     -0.065       0.556      -0.135
+52804.00      0.091     -0.063       0.491      -0.209
+52805.00      0.089     -0.069       0.360      -0.308
+52806.00      0.094     -0.079       0.204      -0.353
+52807.00      0.109     -0.092       0.051      -0.263
+52808.00      0.155     -0.113       0.048      -0.078
+52809.00      0.167     -0.120       0.134       0.059
+52810.00      0.169     -0.099       0.289      -0.096
+52811.00      0.161     -0.068       0.450      -0.241
+52812.00      0.142     -0.059       0.425      -0.270
+52813.00      0.116     -0.075       0.372      -0.177
+52814.00      0.092     -0.089       0.281      -0.064
+52815.00      0.083     -0.093       0.238      -0.147
+52816.00      0.092     -0.097       0.183      -0.109
+52817.00      0.103     -0.102       0.156       0.036
+52818.00      0.121     -0.081       0.124       0.195
+52819.00      0.125     -0.079       0.183       0.255
+52820.00      0.137     -0.087       0.225       0.084
+52821.00      0.144     -0.104       0.229      -0.163
+52822.00      0.154     -0.143       0.264      -0.213
+52823.00      0.150     -0.137       0.242      -0.149
+52824.00      0.154     -0.116       0.227       0.108
+52825.00      0.154     -0.091       0.187       0.242
+52826.00      0.139     -0.081       0.101       0.247
+52827.00      0.118     -0.103       0.074       0.108
+52828.00      0.106     -0.145       0.204      -0.182
+52829.00      0.104     -0.179       0.352      -0.278
+52830.00      0.106     -0.182       0.464      -0.283
+52831.00      0.111     -0.173       0.480      -0.142
+52832.00      0.142     -0.238       0.439       0.004
+52833.00      0.163     -0.251       0.414       0.086
+52834.00      0.181     -0.253       0.381       0.073
+52835.00      0.188     -0.246       0.314      -0.060
+52836.00      0.187     -0.247       0.192      -0.188
+52837.00      0.181     -0.250       0.106      -0.268
+52838.00      0.173     -0.239       0.040      -0.242
+52839.00      0.160     -0.248       0.026      -0.374
+52840.00      0.141     -0.246       0.026      -0.309
+52841.00      0.120     -0.263      -0.031      -0.241
+52842.00      0.104     -0.275       0.008      -0.173
+52843.00      0.100     -0.270       0.099      -0.247
+52844.00      0.103     -0.266       0.244      -0.269
+52845.00      0.105     -0.273       0.337      -0.119
+52846.00      0.143     -0.308       0.355       0.091
+52847.00      0.153     -0.305       0.285       0.192
+52848.00      0.175     -0.302       0.207       0.108
+52849.00      0.194     -0.299       0.108      -0.194
+52850.00      0.214     -0.298       0.107      -0.385
+52851.00      0.195     -0.288       0.183      -0.496
+52852.00      0.174     -0.284       0.281      -0.367
+52853.00      0.158     -0.282       0.302      -0.181
+52854.00      0.148     -0.274       0.261      -0.068
+52855.00      0.141     -0.270       0.197      -0.389
+52856.00      0.135     -0.282       0.204      -0.182
+52857.00      0.131     -0.303       0.240      -0.227
+52858.00      0.127     -0.311       0.265      -0.253
+52859.00      0.129     -0.308       0.229      -0.285
+52860.00      0.146     -0.329       0.187      -0.202
+52861.00      0.172     -0.333       0.197      -0.241
+52862.00      0.196     -0.318       0.222      -0.288
+52863.00      0.204     -0.289       0.307      -0.237
+52864.00      0.195     -0.274       0.365      -0.338
+52865.00      0.178     -0.279       0.373      -0.342
+52866.00      0.161     -0.285       0.362      -0.317
+52867.00      0.145     -0.290       0.373      -0.254
+52868.00      0.131     -0.296       0.359      -0.177
+52869.00      0.118     -0.305       0.297      -0.130
+52870.00      0.113     -0.297       0.172      -0.115
+52871.00      0.116     -0.276       0.106      -0.255
+52872.00      0.115     -0.270       0.107      -0.462
+52873.00      0.112     -0.289       0.122      -0.432
+52874.00      0.082     -0.288       0.171      -0.277
+52875.00      0.102     -0.273       0.100      -0.127
+52876.00      0.130     -0.240       0.061      -0.024
+52877.00      0.149     -0.219       0.037      -0.115
+52878.00      0.145     -0.213       0.063      -0.224
+52879.00      0.122     -0.206       0.132      -0.315
+52880.00      0.087     -0.230       0.195      -0.276
+52881.00      0.058     -0.262       0.261      -0.182
+52882.00      0.050     -0.278       0.249       0.073
+52883.00      0.058     -0.264       0.253       0.154
+52884.00      0.064     -0.245       0.236       0.192
+52885.00      0.057     -0.240       0.218       0.039
+52886.00      0.048     -0.250       0.201      -0.102
+52887.00      0.052     -0.261       0.227      -0.271
+52888.00      0.109     -0.252       0.257      -0.265
+52889.00      0.129     -0.241       0.250      -0.309
+52890.00      0.140     -0.214       0.233      -0.244
+52891.00      0.141     -0.185       0.198      -0.140
+52892.00      0.132     -0.174       0.160      -0.168
+52893.00      0.114     -0.183       0.112      -0.223
+52894.00      0.094     -0.193       0.050      -0.286
+52895.00      0.052     -0.233       0.024      -0.204
+52896.00      0.042     -0.243       0.062      -0.032
+52897.00      0.034     -0.256       0.035       0.025
+52898.00      0.036     -0.249       0.027      -0.070
+52899.00      0.042     -0.220      -0.009      -0.234
+52900.00      0.042     -0.207       0.067      -0.376
+52901.00      0.040     -0.229       0.203      -0.329
+52902.00      0.036     -0.244       0.308      -0.257
+52903.00      0.055     -0.226       0.298      -0.183
+52904.00      0.073     -0.190       0.253      -0.161
+52905.00      0.077     -0.181       0.218      -0.242
+52906.00      0.069     -0.200       0.224      -0.358
+52907.00      0.054     -0.226       0.244      -0.367
+52908.00      0.033     -0.243       0.183      -0.393
+52909.00      0.009     -0.249       0.121      -0.336
+52910.00     -0.009     -0.245       0.058      -0.113
+52911.00     -0.010     -0.242       0.014      -0.018
+52912.00      0.004     -0.248      -0.018      -0.132
+52913.00      0.022     -0.252      -0.058      -0.316
+52914.00      0.032     -0.242      -0.014      -0.379
+52915.00      0.038     -0.228       0.056      -0.409
+52916.00      0.051     -0.222       0.166      -0.250
+52917.00      0.065     -0.212       0.221      -0.086
+52918.00      0.067     -0.193       0.240      -0.059
+52919.00      0.060     -0.178       0.195       0.092
+52920.00      0.038     -0.221       0.087       0.012
+52921.00      0.021     -0.234       0.067      -0.204
+52922.00      0.003     -0.236       0.141      -0.328
+52923.00     -0.012     -0.210       0.213      -0.370
+52924.00     -0.016     -0.217       0.209      -0.255
+52925.00     -0.016     -0.241       0.157      -0.108
+52926.00     -0.012     -0.257       0.078      -0.115
+52927.00     -0.006     -0.243       0.026      -0.225
+52928.00     -0.003     -0.226       0.042      -0.346
+52929.00      0.002     -0.230       0.150      -0.320
+52930.00      0.006     -0.249       0.224      -0.142
+52931.00      0.023     -0.239       0.218      -0.142
+52932.00      0.029     -0.229       0.152      -0.202
+52933.00      0.026     -0.245       0.135      -0.158
+52934.00      0.022     -0.273       0.152      -0.124
+52935.00      0.017     -0.287       0.181      -0.076
+52936.00      0.006     -0.279       0.100      -0.159
+52937.00     -0.030     -0.257       0.063      -0.238
+52938.00     -0.053     -0.218       0.051      -0.101
+52939.00     -0.076     -0.208      -0.001      -0.010
+52940.00     -0.073     -0.250      -0.038      -0.126
+52941.00     -0.031     -0.296      -0.038      -0.425
+52942.00      0.020     -0.282       0.088      -0.624
+52943.00      0.044     -0.224       0.169      -0.584
+52944.00      0.030     -0.193       0.215      -0.382
+52945.00      0.032     -0.188       0.120      -0.148
+52946.00      0.035     -0.184       0.088      -0.196
+52947.00      0.028     -0.175       0.072      -0.202
+52948.00      0.012     -0.177       0.056      -0.312
+52949.00     -0.006     -0.193       0.042      -0.464
+52950.00     -0.021     -0.197       0.038      -0.327
+52951.00     -0.059     -0.181       0.011      -0.158
+52952.00     -0.055     -0.184      -0.037      -0.146
+52953.00     -0.048     -0.207      -0.087      -0.069
+52954.00     -0.042     -0.233      -0.091      -0.127
+52955.00     -0.036     -0.236      -0.053      -0.221
+52956.00     -0.028     -0.222       0.028      -0.279
+52957.00     -0.016     -0.208       0.138      -0.116
+52958.00     -0.003     -0.176       0.155      -0.088
+52959.00      0.011     -0.166       0.099      -0.012
+52960.00      0.009     -0.175       0.038      -0.168
+52961.00     -0.001     -0.204       0.043      -0.179
+52962.00      0.011     -0.222       0.091      -0.153
+52963.00     -0.002     -0.207       0.141      -0.030
+52964.00     -0.026     -0.190       0.148      -0.160
+52965.00     -0.046     -0.188       0.175      -0.415
+52966.00     -0.051     -0.175       0.182      -0.444
+52967.00     -0.058     -0.160       0.111      -0.279
+52968.00     -0.064     -0.185       0.045      -0.209
+52969.00     -0.042     -0.240       0.045      -0.221
+52970.00      0.005     -0.253       0.187      -0.261
+52971.00      0.038     -0.205       0.357       0.048
+52972.00      0.031     -0.160       0.355       0.291
+52973.00      0.029     -0.154       0.256       0.341
+52974.00      0.032     -0.155       0.158       0.188
+52975.00      0.027     -0.139       0.055      -0.095
+52976.00      0.009     -0.128      -0.005      -0.114
+52977.00     -0.011     -0.136       0.012      -0.113
+52978.00     -0.022     -0.147       0.022      -0.201
+52979.00     -0.023     -0.146      -0.001      -0.252
+52980.00     -0.015     -0.154      -0.021      -0.352
+52981.00     -0.009     -0.170      -0.042      -0.194
+52982.00     -0.006     -0.183      -0.035      -0.129
+52983.00      0.000     -0.186       0.058      -0.100
+52984.00      0.013     -0.177       0.157      -0.194
+52985.00      0.027     -0.159       0.245      -0.207
+52986.00      0.040     -0.137       0.302      -0.205
+52987.00      0.045     -0.120       0.273      -0.146
+52988.00      0.031     -0.128       0.230      -0.155
+52989.00      0.007     -0.159       0.129      -0.154
+52990.00      0.010     -0.188       0.055      -0.292
+52991.00     -0.005     -0.171       0.024      -0.167
+52992.00     -0.028     -0.157       0.044      -0.200
+52993.00     -0.047     -0.177       0.115      -0.290
+52994.00     -0.036     -0.203       0.237      -0.276
+52995.00     -0.007     -0.198       0.308      -0.191
+52996.00      0.008     -0.186       0.196      -0.074
+52997.00      0.023     -0.175       0.090      -0.220
+52998.00      0.026     -0.195       0.022      -0.419
+52999.00      0.033     -0.188      -0.065      -0.395
+53000.00      0.032     -0.167      -0.102      -0.160
+53001.00      0.036     -0.159      -0.154       0.025
+53002.00      0.040     -0.148      -0.093      -0.067
+53003.00      0.032     -0.126      -0.042      -0.162
+53004.00      0.011     -0.112       0.034      -0.016
+53005.00     -0.011     -0.116       0.022       0.140
+53006.00     -0.022     -0.125       0.045       0.122
+53007.00     -0.034     -0.157       0.057      -0.047
+53008.00     -0.025     -0.169       0.020      -0.174
+53009.00     -0.019     -0.181       0.017      -0.271
+53010.00     -0.016     -0.187       0.057      -0.108
+53011.00     -0.005     -0.181       0.162      -0.037
+53012.00      0.014     -0.169       0.226      -0.029
+53013.00      0.027     -0.152       0.214      -0.112
+53014.00      0.024     -0.128       0.132      -0.278
+53015.00      0.012     -0.112       0.086      -0.389
+53016.00     -0.009     -0.118       0.059      -0.377
+53017.00     -0.037     -0.149       0.038      -0.183
+53018.00     -0.032     -0.185       0.050       0.167
+53019.00     -0.039     -0.191      -0.014       0.148
+53020.00     -0.034     -0.180      -0.097      -0.041
+53021.00     -0.032     -0.173      -0.075      -0.309
+53022.00     -0.031     -0.174      -0.027      -0.305
+53023.00     -0.021     -0.171       0.041      -0.194
+53024.00     -0.007     -0.170       0.063      -0.033
+53025.00     -0.007     -0.227       0.090      -0.093
+53026.00     -0.010     -0.239       0.058      -0.162
+53027.00     -0.015     -0.240       0.047      -0.226
+53028.00     -0.022     -0.247      -0.064      -0.189
+53029.00     -0.017     -0.228      -0.129      -0.072
+53030.00     -0.016     -0.202      -0.139      -0.097
+53031.00     -0.027     -0.179      -0.090      -0.099
+53032.00     -0.049     -0.178       0.006      -0.114
+53033.00     -0.070     -0.192       0.043      -0.070
+53034.00     -0.081     -0.193       0.080      -0.127
+53035.00     -0.082     -0.207       0.072      -0.275
+53036.00     -0.072     -0.205       0.072      -0.334
+53037.00     -0.059     -0.217       0.054      -0.386
+53038.00     -0.048     -0.226       0.048      -0.230
+53039.00     -0.030     -0.219       0.105      -0.104
+53040.00     -0.010     -0.205       0.129      -0.039
+53041.00     -0.000     -0.187       0.101      -0.232
+53042.00     -0.011     -0.166       0.033      -0.368
+53043.00     -0.036     -0.157      -0.016      -0.335
+53044.00     -0.057     -0.171      -0.083      -0.212
+53045.00     -0.075     -0.202      -0.049      -0.062
+53046.00     -0.089     -0.230      -0.054       0.039
+53047.00     -0.089     -0.239      -0.029       0.068
+53048.00     -0.071     -0.225       0.007      -0.027
+53049.00     -0.075     -0.189       0.015      -0.066
+53050.00     -0.074     -0.155       0.040      -0.092
+53051.00     -0.086     -0.141      -0.005      -0.020
+53052.00     -0.094     -0.164      -0.012      -0.134
+53053.00     -0.087     -0.204       0.015      -0.209
+53054.00     -0.072     -0.227       0.013      -0.256
+53055.00     -0.054     -0.251      -0.023      -0.234
+53056.00     -0.046     -0.222      -0.098      -0.231
+53057.00     -0.045     -0.190      -0.143      -0.166
+53058.00     -0.053     -0.158      -0.155      -0.119
+53059.00     -0.068     -0.140      -0.084      -0.117
+53060.00     -0.086     -0.149       0.027      -0.114
+53061.00     -0.101     -0.176       0.110      -0.160
+53062.00     -0.107     -0.185       0.188      -0.255
+53063.00     -0.141     -0.133       0.161      -0.324
+53064.00     -0.126     -0.121       0.125      -0.384
+53065.00     -0.105     -0.126       0.051      -0.231
+53066.00     -0.084     -0.131       0.007      -0.068
+53067.00     -0.064     -0.121       0.004      -0.004
+53068.00     -0.052     -0.108       0.039      -0.063
+53069.00     -0.055     -0.105       0.138      -0.180
+53070.00     -0.096     -0.083       0.165      -0.306
+53071.00     -0.119     -0.084       0.156      -0.252
+53072.00     -0.136     -0.103       0.087      -0.145
+53073.00     -0.144     -0.136       0.021      -0.050
+53074.00     -0.142     -0.158      -0.118      -0.085
+53075.00     -0.135     -0.155      -0.117      -0.104
+53076.00     -0.124     -0.140      -0.099      -0.148
+53077.00     -0.144     -0.102      -0.069      -0.213
+53078.00     -0.137     -0.084      -0.018      -0.164
+53079.00     -0.131     -0.071       0.058      -0.084
+53080.00     -0.122     -0.079       0.127       0.020
+53081.00     -0.109     -0.103       0.111       0.024
+53082.00     -0.094     -0.117       0.033      -0.001
+53083.00     -0.081     -0.105      -0.028      -0.091
+53084.00     -0.071     -0.072      -0.055      -0.165
+53085.00     -0.077     -0.048      -0.124      -0.185
+53086.00     -0.093     -0.026      -0.158      -0.161
+53087.00     -0.110     -0.011      -0.129      -0.115
+53088.00     -0.121     -0.016      -0.058       0.041
+53089.00     -0.125     -0.043       0.063       0.004
+53090.00     -0.118     -0.067       0.096      -0.111
+53091.00     -0.112     -0.066       0.129      -0.179
+53092.00     -0.090     -0.065       0.089      -0.291
+53093.00     -0.066     -0.067      -0.002      -0.186
+53094.00     -0.042     -0.055      -0.038      -0.015
+53095.00     -0.026     -0.028      -0.076       0.019
+53096.00     -0.028     -0.017      -0.004      -0.036
+53097.00     -0.043     -0.033       0.103      -0.071
+53098.00     -0.071      0.003       0.147      -0.104
+53099.00     -0.085     -0.001       0.080      -0.084
+53100.00     -0.099     -0.011      -0.136      -0.072
+53101.00     -0.104     -0.042      -0.218      -0.195
+53102.00     -0.093     -0.067      -0.092      -0.289
+53103.00     -0.072     -0.067       0.002      -0.079
+53104.00     -0.056     -0.058      -0.040       0.059
+53105.00     -0.049     -0.065      -0.084       0.196
+53106.00     -0.042     -0.076      -0.085       0.148
+53107.00     -0.024     -0.073      -0.039       0.089
+53108.00      0.004     -0.055       0.039       0.048
+53109.00      0.025     -0.032       0.049       0.009
+53110.00      0.030     -0.010       0.037       0.133
+53111.00      0.024      0.006       0.039       0.165
+53112.00      0.013      0.012       0.070       0.171
+53113.00     -0.003      0.012       0.094       0.201
+53114.00     -0.021      0.015       0.134       0.103
+53115.00     -0.035      0.025       0.141       0.219
+53116.00      0.003      0.068       0.146       0.243
+53117.00      0.006      0.050       0.208       0.316
+53118.00      0.023      0.024       0.230       0.186
+53119.00      0.078      0.009       0.233      -0.037
+53120.00      0.101     -0.003       0.212      -0.125
+53121.00      0.117     -0.011       0.189      -0.114
+53122.00      0.132      0.003       0.091       0.006
+53123.00      0.141      0.036       0.027       0.120
+53124.00      0.132      0.046       0.037       0.048
+53125.00      0.112      0.016       0.130       0.197
+53126.00      0.096     -0.010       0.276       0.350
+53127.00      0.081     -0.002       0.295       0.517
+53128.00      0.064      0.005       0.151       0.300
+53129.00      0.057     -0.020       0.061      -0.062
+53130.00      0.050     -0.067       0.100      -0.207
+53131.00      0.071     -0.070       0.183      -0.159
+53132.00      0.081     -0.064       0.132      -0.082
+53133.00      0.086     -0.078       0.000      -0.026
+53134.00      0.097     -0.103      -0.058      -0.103
+53135.00      0.114     -0.110      -0.038      -0.127
+53136.00      0.133     -0.096       0.112      -0.107
+53137.00      0.142     -0.085       0.219      -0.093
+53138.00      0.140     -0.045       0.237      -0.066
+53139.00      0.123     -0.016       0.174       0.022
+53140.00      0.100     -0.011       0.077       0.177
+53141.00      0.076     -0.021       0.039       0.107
+53142.00      0.056     -0.026       0.015       0.016
+53143.00      0.048     -0.023       0.029      -0.036
+53144.00      0.049     -0.027       0.036      -0.014
+53145.00      0.057     -0.042       0.027       0.005
+53146.00      0.075     -0.053      -0.006      -0.018
+53147.00      0.116     -0.041      -0.049      -0.045
+53148.00      0.133     -0.040      -0.066      -0.037
+53149.00      0.135     -0.047       0.022       0.029
+53150.00      0.134     -0.047       0.148       0.105
+53151.00      0.135     -0.027       0.255      -0.130
+53152.00      0.127     -0.020       0.287      -0.259
+53153.00      0.111     -0.050       0.259      -0.223
+53154.00      0.097     -0.025       0.255       0.120
+53155.00      0.077     -0.015       0.200       0.361
+53156.00      0.055     -0.002       0.052       0.306
+53157.00      0.052     -0.026      -0.027       0.128
+53158.00      0.075     -0.058       0.091       0.034
+53159.00      0.093     -0.058       0.191       0.069
+53160.00      0.083     -0.047       0.198       0.164
+53161.00      0.070     -0.065       0.009       0.129
+53162.00      0.082     -0.099      -0.150       0.168
+53163.00      0.109     -0.119      -0.195       0.178
+53164.00      0.127     -0.122      -0.070       0.085
+53165.00      0.131     -0.109       0.186      -0.237
+53166.00      0.097     -0.049       0.265      -0.317
+53167.00      0.080     -0.006       0.224      -0.142
+53168.00      0.054      0.010       0.189       0.092
+53169.00      0.028      0.001       0.221       0.223
+53170.00      0.011     -0.011       0.300       0.109
+53171.00      0.009     -0.016       0.297       0.034
+53172.00      0.023     -0.029       0.123       0.175
+53173.00      0.042     -0.045      -0.020       0.218
+53174.00      0.059     -0.049       0.033       0.109
+53175.00      0.093     -0.017       0.078       0.013
+53176.00      0.101     -0.002       0.155      -0.161
+53177.00      0.096     -0.006       0.237      -0.212
+53178.00      0.085     -0.016       0.313      -0.082
+53179.00      0.080     -0.010       0.271      -0.062
+53180.00      0.077     -0.003       0.191      -0.204
+53181.00      0.066     -0.020       0.060      -0.228
+53182.00      0.049     -0.053       0.024      -0.159
+53183.00      0.031     -0.069       0.009       0.112
+53184.00      0.015     -0.077       0.038       0.144
+53185.00      0.020     -0.098       0.093       0.014
+53186.00      0.036     -0.131       0.244      -0.120
+53187.00      0.062     -0.118       0.329      -0.082
+53188.00      0.055     -0.102       0.282      -0.105
+53189.00      0.055     -0.083       0.122      -0.298
+53190.00      0.060     -0.118       0.041      -0.376
+53191.00      0.086     -0.139      -0.017      -0.284
+53192.00      0.104     -0.147       0.023      -0.118
+53193.00      0.103     -0.143       0.082       0.011
+53194.00      0.089     -0.111       0.210      -0.063
+53195.00      0.069     -0.066       0.312      -0.062
+53196.00      0.032     -0.051       0.284       0.103
+53197.00      0.013     -0.071       0.173       0.246
+53198.00      0.004     -0.096       0.130       0.194
+53199.00      0.010     -0.104       0.116       0.026
+53200.00      0.031     -0.107       0.113      -0.157
+53201.00      0.058     -0.111       0.141      -0.149
+53202.00      0.076     -0.106       0.151      -0.120
+53203.00      0.076     -0.123       0.170      -0.145
+53204.00      0.079     -0.111       0.154      -0.196
+53205.00      0.074     -0.113       0.172      -0.169
+53206.00      0.060     -0.120       0.180      -0.106
+53207.00      0.049     -0.115       0.174      -0.018
+53208.00      0.046     -0.099       0.150      -0.019
+53209.00      0.039     -0.095       0.020      -0.069
+53210.00      0.024     -0.108      -0.068      -0.146
+53211.00      0.012     -0.147      -0.117      -0.117
+53212.00      0.011     -0.182      -0.045      -0.069
+53213.00      0.024     -0.197       0.057       0.051
+53214.00      0.048     -0.184       0.243      -0.001
+53215.00      0.070     -0.153       0.301       0.009
+53216.00      0.080     -0.136       0.320      -0.114
+53217.00      0.083     -0.151       0.271      -0.452
+53218.00      0.091     -0.171       0.234      -0.627
+53219.00      0.102     -0.171       0.217      -0.528
+53220.00      0.101     -0.164       0.095      -0.213
+53221.00      0.089     -0.158       0.022      -0.112
+53222.00      0.071     -0.138       0.040      -0.089
+53223.00      0.051     -0.107       0.130      -0.145
+53224.00      0.049     -0.129       0.191       0.099
+53225.00      0.042     -0.160       0.239       0.283
+53226.00      0.047     -0.195       0.249       0.317
+53227.00      0.062     -0.202       0.219       0.139
+53228.00      0.083     -0.191       0.212      -0.136
+53229.00      0.105     -0.179       0.140      -0.401
+53230.00      0.120     -0.167       0.105      -0.425
+53231.00      0.160     -0.161       0.164      -0.283
+53232.00      0.167     -0.151       0.260      -0.252
+53233.00      0.165     -0.150       0.298      -0.213
+53234.00      0.146     -0.153       0.258      -0.277
+53235.00      0.122     -0.153       0.046      -0.262
+53236.00      0.107     -0.150       0.015      -0.252
+53237.00      0.099     -0.150       0.153      -0.188
+53238.00      0.085     -0.168       0.166      -0.234
+53239.00      0.076     -0.192       0.131      -0.341
+53240.00      0.080     -0.225       0.154      -0.400
+53241.00      0.095     -0.241       0.179      -0.238
+53242.00      0.109     -0.226       0.227      -0.085
+53243.00      0.108     -0.169       0.249       0.024
+53244.00      0.120     -0.155       0.273       0.044
+53245.00      0.137     -0.163       0.307      -0.127
+53246.00      0.150     -0.162       0.377      -0.310
+53247.00      0.149     -0.141       0.440      -0.318
+53248.00      0.132     -0.121       0.342      -0.056
+53249.00      0.111     -0.118       0.198       0.122
+53250.00      0.091     -0.117       0.130      -0.071
+53251.00      0.076     -0.108       0.147      -0.165
+53252.00      0.060     -0.108       0.161      -0.276
+53253.00      0.061     -0.137       0.123      -0.354
+53254.00      0.074     -0.164       0.059      -0.424
+53255.00      0.094     -0.170       0.043      -0.412
+53256.00      0.112     -0.166       0.074      -0.293
+53257.00      0.122     -0.168       0.142      -0.136
+53258.00      0.129     -0.165       0.196       0.034
+53259.00      0.127     -0.130       0.253       0.157
+53260.00      0.143     -0.105       0.305       0.096
+53261.00      0.148     -0.090       0.334      -0.020
+53262.00      0.131     -0.091       0.290      -0.133
+53263.00      0.101     -0.103       0.178      -0.106
+53264.00      0.076     -0.128       0.120      -0.132
+53265.00      0.067     -0.154       0.153      -0.116
+53266.00      0.101     -0.163       0.164      -0.065
+53267.00      0.102     -0.157       0.154      -0.101
+53268.00      0.106     -0.160       0.218      -0.158
+53269.00      0.114     -0.175       0.217      -0.067
+53270.00      0.126     -0.186       0.271      -0.128
+53271.00      0.142     -0.182       0.282      -0.217
+53272.00      0.163     -0.192       0.292      -0.410
+53273.00      0.173     -0.188       0.265      -0.504
+53274.00      0.175     -0.177       0.257      -0.518
+53275.00      0.165     -0.156       0.211      -0.369
+53276.00      0.148     -0.142       0.104      -0.242
+53277.00      0.145     -0.157       0.014      -0.262
+53278.00      0.126     -0.168      -0.005      -0.235
+53279.00      0.113     -0.172       0.051      -0.336
+53280.00      0.107     -0.184       0.109      -0.185
+53281.00      0.111     -0.205       0.198      -0.071
+53282.00      0.126     -0.221       0.206      -0.080
+53283.00      0.147     -0.220       0.180      -0.183
+53284.00      0.163     -0.224       0.180      -0.349
+53285.00      0.169     -0.247       0.223      -0.383
+53286.00      0.172     -0.263       0.296      -0.332
+53287.00      0.208     -0.179       0.260      -0.143
+53288.00      0.219     -0.138       0.224      -0.124
+53289.00      0.220     -0.111       0.235      -0.157
+53290.00      0.205     -0.111       0.249      -0.232
+53291.00      0.179     -0.128       0.319      -0.235
+53292.00      0.154     -0.153       0.340      -0.198
+53293.00      0.140     -0.181       0.336      -0.024
+53294.00      0.163     -0.181       0.298       0.116
+53295.00      0.176     -0.170       0.264       0.116
+53296.00      0.190     -0.154       0.241       0.019
+53297.00      0.197     -0.154       0.244      -0.137
+53298.00      0.202     -0.166       0.272      -0.182
+53299.00      0.216     -0.173       0.307      -0.196
+53300.00      0.236     -0.169       0.339      -0.119
+53301.00      0.242     -0.161       0.322      -0.087
+53302.00      0.228     -0.151       0.283      -0.107
+53303.00      0.206     -0.145       0.225      -0.170
+53304.00      0.188     -0.151       0.163      -0.263
+53305.00      0.176     -0.181       0.133      -0.338
+53306.00      0.162     -0.191       0.081      -0.306
+53307.00      0.152     -0.193       0.082      -0.205
+53308.00      0.141     -0.224       0.119      -0.086
+53309.00      0.148     -0.252       0.161       0.002
+53310.00      0.160     -0.272       0.216      -0.051
+53311.00      0.175     -0.268       0.217      -0.207
+53312.00      0.188     -0.260       0.203      -0.332
+53313.00      0.195     -0.273       0.219      -0.263
+53314.00      0.202     -0.288       0.196      -0.187
+53315.00      0.230     -0.270       0.115      -0.235
+53316.00      0.227     -0.234       0.084      -0.234
+53317.00      0.212     -0.216       0.120      -0.394
+53318.00      0.191     -0.223       0.212      -0.438
+53319.00      0.182     -0.265       0.279      -0.364
+53320.00      0.166     -0.277       0.295      -0.347
+53321.00      0.154     -0.287       0.290      -0.281
+53322.00      0.150     -0.290       0.259      -0.016
+53323.00      0.158     -0.290       0.234       0.106
+53324.00      0.177     -0.297       0.178      -0.017
+53325.00      0.199     -0.303       0.208      -0.202
+53326.00      0.212     -0.291       0.266      -0.390
+53327.00      0.214     -0.266       0.325      -0.482
+53328.00      0.215     -0.252       0.318      -0.358
+53329.00      0.216     -0.251       0.220      -0.327
+53330.00      0.204     -0.251       0.111      -0.393
+53331.00      0.180     -0.247       0.100      -0.292
+53332.00      0.160     -0.255       0.176      -0.292
+53333.00      0.155     -0.302       0.288      -0.276
+53334.00      0.148     -0.308       0.345      -0.171
+53335.00      0.146     -0.304       0.356       0.016
+53336.00      0.152     -0.313       0.333       0.173
+53337.00      0.160     -0.343       0.309       0.248
+53338.00      0.166     -0.371       0.292       0.177
+53339.00      0.170     -0.370       0.273      -0.045
+53340.00      0.176     -0.373       0.284      -0.284
+53341.00      0.183     -0.355       0.261      -0.365
+53342.00      0.193     -0.346       0.247      -0.372
+53343.00      0.195     -0.333       0.188      -0.423
+53344.00      0.177     -0.322       0.164      -0.483
+53345.00      0.145     -0.332       0.259      -0.486
+53346.00      0.119     -0.349       0.402      -0.463
+53347.00      0.112     -0.399       0.470      -0.340
+53348.00      0.102     -0.408       0.481      -0.522
+53349.00      0.103     -0.425       0.471      -0.558
+53350.00      0.115     -0.428       0.436      -0.528
+53351.00      0.121     -0.414       0.363      -0.208
+53352.00      0.118     -0.419       0.236      -0.128
+53353.00      0.127     -0.447       0.104      -0.326
+53354.00      0.147     -0.445       0.159      -0.488
+53355.00      0.152     -0.400       0.246      -0.507
+53356.00      0.137     -0.364       0.245      -0.383
+53357.00      0.075     -0.376       0.155      -0.422
+53358.00      0.066     -0.387       0.062      -0.503
+53359.00      0.049     -0.375       0.007      -0.529
+53360.00      0.025     -0.362       0.035      -0.404
+53361.00      0.010     -0.367       0.107      -0.198
+53362.00      0.009     -0.378       0.196      -0.076
+53363.00      0.018     -0.385       0.184      -0.083
+53364.00      0.031     -0.395       0.115       0.043
+53365.00      0.040     -0.418       0.045       0.019
+53366.00      0.044     -0.435       0.062      -0.026
+53367.00      0.046     -0.429       0.078      -0.162
+53368.00      0.055     -0.433       0.126      -0.380
+53369.00      0.062     -0.403       0.119      -0.457
+53370.00      0.067     -0.379       0.078      -0.512
+53371.00      0.061     -0.367       0.041      -0.647
+53372.00      0.034     -0.377      -0.008      -0.741
+53373.00     -0.001     -0.411      -0.011      -0.737
+53374.00     -0.020     -0.435       0.012      -0.553
+53375.00     -0.006     -0.451       0.014      -0.348
+53376.00     -0.015     -0.447      -0.031      -0.316
+53377.00     -0.011     -0.478       0.060      -0.360
+53378.00      0.023     -0.503       0.190      -0.378
+53379.00      0.055     -0.472       0.307      -0.220
+53380.00      0.052     -0.430       0.253      -0.131
+53381.00      0.031     -0.432       0.107      -0.282
+53382.00      0.026     -0.453       0.035      -0.611
+53383.00      0.031     -0.438       0.092      -0.617
+53384.00      0.023     -0.405       0.097      -0.512
+53385.00      0.023     -0.411       0.073      -0.427
+53386.00      0.008     -0.414       0.041      -0.581
+53387.00     -0.009     -0.399       0.039      -0.631
+53388.00     -0.035     -0.380       0.027      -0.524
+53389.00     -0.054     -0.382       0.056      -0.384
+53390.00     -0.055     -0.402       0.064      -0.309
+53391.00     -0.042     -0.421       0.102      -0.319
+53392.00     -0.031     -0.444       0.068      -0.397
+53393.00     -0.018     -0.457       0.009      -0.409
+53394.00     -0.011     -0.453       0.004      -0.384
+53395.00     -0.005     -0.425       0.030      -0.340
+53396.00      0.001     -0.394       0.066      -0.327
+53397.00      0.002     -0.372       0.083      -0.293
+53398.00     -0.009     -0.360       0.079      -0.264
+53399.00     -0.028     -0.356       0.107      -0.193
+53400.00     -0.056     -0.370       0.082      -0.228
+53401.00     -0.083     -0.407       0.086      -0.317
+53402.00     -0.091     -0.436       0.015      -0.298
+53403.00     -0.080     -0.458      -0.013      -0.343
+53404.00     -0.071     -0.434      -0.081      -0.392
+53405.00     -0.073     -0.444      -0.058      -0.520
+53406.00     -0.085     -0.474       0.067      -0.622
+53407.00     -0.057     -0.464       0.172      -0.514
+53408.00     -0.039     -0.416       0.163      -0.425
+53409.00     -0.048     -0.387       0.069      -0.423
+53410.00     -0.061     -0.396      -0.037      -0.442
+53411.00     -0.064     -0.404      -0.055      -0.399
+53412.00     -0.067     -0.392      -0.058      -0.301
+53413.00     -0.078     -0.374      -0.041      -0.199
+53414.00     -0.093     -0.359      -0.039      -0.365
+53415.00     -0.112     -0.344       0.000      -0.446
+53416.00     -0.132     -0.344       0.012      -0.313
+53417.00     -0.158     -0.384       0.038      -0.280
+53418.00     -0.151     -0.405       0.072      -0.262
+53419.00     -0.131     -0.417       0.096      -0.512
+53420.00     -0.117     -0.446       0.071      -0.591
+53421.00     -0.097     -0.453       0.036      -0.588
+53422.00     -0.082     -0.437       0.018      -0.369
+53423.00     -0.074     -0.399       0.036      -0.284
+53424.00     -0.071     -0.363       0.037      -0.364
+53425.00     -0.080     -0.348       0.004      -0.377
+53426.00     -0.105     -0.351      -0.091      -0.374
+53427.00     -0.165     -0.347      -0.158      -0.334
+53428.00     -0.185     -0.361      -0.175      -0.334
+53429.00     -0.197     -0.385      -0.204      -0.337
+53430.00     -0.197     -0.410      -0.196      -0.347
+53431.00     -0.176     -0.412      -0.161      -0.449
+53432.00     -0.142     -0.390      -0.106      -0.449
+53433.00     -0.122     -0.368      -0.031      -0.436
+53434.00     -0.139     -0.355       0.027      -0.465
+53435.00     -0.146     -0.359       0.019      -0.337
+53436.00     -0.142     -0.359       0.015      -0.172
+53437.00     -0.129     -0.357      -0.012      -0.198
+53438.00     -0.119     -0.351      -0.029      -0.278
+53439.00     -0.117     -0.337      -0.097      -0.332
+53440.00     -0.122     -0.314      -0.168      -0.254
+53441.00     -0.137     -0.268      -0.212      -0.199
+53442.00     -0.151     -0.252      -0.209      -0.229
+53443.00     -0.166     -0.248      -0.160      -0.202
+53444.00     -0.173     -0.269      -0.075      -0.274
+53445.00     -0.168     -0.308      -0.003      -0.127
+53446.00     -0.151     -0.327       0.063      -0.196
+53447.00     -0.127     -0.319       0.098      -0.294
+53448.00     -0.116     -0.317       0.107      -0.492
+53449.00     -0.095     -0.313       0.010      -0.479
+53450.00     -0.084     -0.302      -0.030      -0.408
+53451.00     -0.084     -0.273      -0.071      -0.241
+53452.00     -0.092     -0.245      -0.059      -0.265
+53453.00     -0.110     -0.238      -0.109      -0.299
+53454.00     -0.137     -0.244      -0.147      -0.377
+53455.00     -0.206     -0.258      -0.202      -0.308
+53456.00     -0.217     -0.273      -0.244      -0.320
+53457.00     -0.215     -0.296      -0.185      -0.298
+53458.00     -0.208     -0.317      -0.121      -0.289
+53459.00     -0.192     -0.325      -0.036      -0.282
+53460.00     -0.161     -0.314       0.039      -0.244
+53461.00     -0.128     -0.292       0.070      -0.268
+53462.00     -0.118     -0.261       0.016      -0.281
+53463.00     -0.130     -0.248      -0.034      -0.238
+53464.00     -0.144     -0.259      -0.040      -0.191
+53465.00     -0.141     -0.283      -0.030      -0.264
+53466.00     -0.130     -0.285       0.026      -0.319
+53467.00     -0.126     -0.254       0.038      -0.376
+53468.00     -0.135     -0.213      -0.035      -0.276
+53469.00     -0.188     -0.188      -0.114      -0.298
+53470.00     -0.206     -0.180      -0.130      -0.336
+53471.00     -0.214     -0.188      -0.157      -0.391
+53472.00     -0.207     -0.216      -0.142      -0.301
+53473.00     -0.185     -0.255      -0.088      -0.251
+53474.00     -0.157     -0.276      -0.102      -0.201
+53475.00     -0.128     -0.262      -0.115      -0.304
+53476.00     -0.116     -0.212      -0.081      -0.242
+53477.00     -0.100     -0.197      -0.087      -0.258
+53478.00     -0.095     -0.183      -0.066      -0.138
+53479.00     -0.099     -0.159      -0.019      -0.041
+53480.00     -0.111     -0.140       0.043      -0.146
+53481.00     -0.126     -0.143       0.074      -0.192
+53482.00     -0.144     -0.156       0.023      -0.249
+53483.00     -0.145     -0.145      -0.040      -0.320
+53484.00     -0.153     -0.155      -0.095      -0.274
+53485.00     -0.149     -0.179      -0.087      -0.208
+53486.00     -0.133     -0.203      -0.045      -0.133
+53487.00     -0.110     -0.208       0.048      -0.094
+53488.00     -0.087     -0.199       0.076      -0.168
+53489.00     -0.069     -0.195       0.024      -0.212
+53490.00     -0.062     -0.176      -0.016      -0.340
+53491.00     -0.059     -0.160      -0.006      -0.335
+53492.00     -0.060     -0.143      -0.012      -0.375
+53493.00     -0.065     -0.137       0.021      -0.254
+53494.00     -0.072     -0.136       0.007      -0.180
+53495.00     -0.080     -0.122       0.004      -0.155
+53496.00     -0.093     -0.104      -0.020      -0.153
+53497.00     -0.143     -0.089      -0.025      -0.194
+53498.00     -0.161     -0.093      -0.027      -0.186
+53499.00     -0.168     -0.101      -0.004      -0.105
+53500.00     -0.157     -0.118       0.034       0.056
+53501.00     -0.132     -0.145       0.091       0.148
+53502.00     -0.101     -0.166       0.134       0.101
+53503.00     -0.073     -0.165       0.130      -0.012
+53504.00     -0.053     -0.152       0.112      -0.055
+53505.00     -0.046     -0.139       0.083      -0.096
+53506.00     -0.048     -0.119       0.024      -0.050
+53507.00     -0.055     -0.085      -0.042      -0.157
+53508.00     -0.111     -0.068      -0.065      -0.233
+53509.00     -0.128     -0.087      -0.053      -0.276
+53510.00     -0.141     -0.123      -0.005      -0.295
+53511.00     -0.171     -0.154      -0.080      -0.286
+53512.00     -0.172     -0.155      -0.187      -0.344
+53513.00     -0.167     -0.167      -0.217      -0.273
+53514.00     -0.151     -0.184      -0.145      -0.178
+53515.00     -0.132     -0.173      -0.013       0.071
+53516.00     -0.113     -0.165       0.047       0.057
+53517.00     -0.102     -0.176       0.030      -0.071
+53518.00     -0.095     -0.197      -0.015      -0.372
+53519.00     -0.081     -0.196       0.003      -0.612
+53520.00     -0.068     -0.160       0.029      -0.618
+53521.00     -0.067     -0.112       0.035      -0.405
+53522.00     -0.082     -0.079      -0.012      -0.213
+53523.00     -0.101     -0.072      -0.045      -0.069
+53524.00     -0.112     -0.085      -0.032      -0.062
+53525.00     -0.140     -0.084       0.004      -0.215
+53526.00     -0.143     -0.100      -0.032      -0.201
+53527.00     -0.139     -0.104      -0.121      -0.151
+53528.00     -0.123     -0.111      -0.226       0.038
+53529.00     -0.100     -0.126      -0.266       0.047
+53530.00     -0.075     -0.140      -0.199       0.020
+53531.00     -0.052     -0.140      -0.091      -0.190
+53532.00     -0.026     -0.097       0.036      -0.305
+53533.00     -0.025     -0.093       0.120      -0.232
+53534.00     -0.032     -0.080       0.135      -0.059
+53535.00     -0.040     -0.048       0.032      -0.109
+53536.00     -0.047     -0.022      -0.073      -0.149
+53537.00     -0.068     -0.055      -0.071      -0.219
+53538.00     -0.081     -0.117       0.009      -0.140
+53539.00     -0.077     -0.151       0.007      -0.024
+53540.00     -0.062     -0.148      -0.021       0.008
+53541.00     -0.044     -0.139      -0.080      -0.054
+53542.00     -0.027     -0.134      -0.014      -0.018
+53543.00     -0.011     -0.099       0.078       0.092
+53544.00     -0.017     -0.099       0.066       0.011
+53545.00     -0.016     -0.125       0.002      -0.135
+53546.00      0.004     -0.155       0.003      -0.423
+53547.00      0.026     -0.152       0.002      -0.449
+53548.00      0.033     -0.117       0.043      -0.194
+53549.00      0.022     -0.072       0.030      -0.065
+53550.00     -0.000     -0.033       0.041       0.013
+53551.00     -0.023     -0.016       0.052       0.010
+53552.00     -0.034     -0.029       0.118      -0.137
+53553.00     -0.020     -0.050       0.147      -0.334
+53554.00     -0.013     -0.071       0.189      -0.544
+53555.00      0.003     -0.076       0.151      -0.591
+53556.00      0.026     -0.081       0.145      -0.405
+53557.00      0.052     -0.095       0.123      -0.185
+53558.00      0.069     -0.103       0.197      -0.048
+53559.00      0.079     -0.093       0.289      -0.005
+53560.00      0.082     -0.078       0.346      -0.148
+53561.00      0.075     -0.077       0.382      -0.079
+53562.00      0.062     -0.080       0.324      -0.105
+53563.00      0.049     -0.070       0.175      -0.144
+53564.00      0.042     -0.050       0.023      -0.299
+53565.00      0.022     -0.083      -0.046      -0.321
+53566.00      0.013     -0.143       0.059      -0.224
+53567.00      0.004     -0.188       0.120      -0.051
+53568.00      0.029     -0.179       0.108      -0.023
+53569.00      0.059     -0.155       0.080      -0.140
+53570.00      0.084     -0.132       0.075      -0.109
+53571.00      0.082     -0.112       0.089       0.014
+53572.00      0.056     -0.117       0.065       0.028
+53573.00      0.045     -0.153       0.092      -0.169
+53574.00      0.097     -0.177       0.166      -0.361
+53575.00      0.125     -0.151       0.210      -0.420
+53576.00      0.118     -0.112       0.227      -0.153
+53577.00      0.084     -0.097       0.135      -0.132
+53578.00      0.054     -0.092       0.107      -0.187
+53579.00      0.039     -0.078       0.050      -0.193
+53580.00      0.035     -0.076       0.027      -0.112
+53581.00      0.041     -0.096       0.032      -0.035
+53582.00      0.055     -0.114       0.059      -0.091
+53583.00      0.075     -0.112       0.127      -0.161
+53584.00      0.101     -0.106       0.191      -0.077
+53585.00      0.129     -0.110       0.208       0.090
+53586.00      0.147     -0.110       0.293       0.151
+53587.00      0.149     -0.095       0.390       0.025
+53588.00      0.187     -0.056       0.418      -0.221
+53589.00      0.175     -0.058       0.408      -0.231
+53590.00      0.160     -0.070       0.388      -0.218
+53591.00      0.147     -0.072       0.280      -0.089
+53592.00      0.135     -0.069       0.191      -0.144
+53593.00      0.121     -0.085       0.148      -0.142
+53594.00      0.115     -0.126       0.222      -0.109
+53595.00      0.117     -0.168       0.304      -0.010
+53596.00      0.136     -0.168       0.354      -0.016
+53597.00      0.158     -0.147       0.348      -0.189
+53598.00      0.179     -0.124       0.296      -0.134
+53599.00      0.186     -0.103       0.238      -0.008
+53600.00      0.175     -0.107       0.220      -0.019
+53601.00      0.167     -0.138       0.290      -0.070
+53602.00      0.183     -0.149       0.412      -0.290
+53603.00      0.200     -0.106       0.507      -0.239
+53604.00      0.181     -0.057       0.409       0.012
+53605.00      0.139     -0.054       0.266      -0.030
+53606.00      0.111     -0.077       0.183      -0.167
+53607.00      0.105     -0.078       0.185      -0.316
+53608.00      0.111     -0.075       0.202      -0.138
+53609.00      0.124     -0.094       0.201      -0.023
+53610.00      0.144     -0.117       0.207       0.099
+53611.00      0.165     -0.114       0.219      -0.028
+53612.00      0.184     -0.094       0.291      -0.075
+53613.00      0.214     -0.076       0.289       0.026
+53614.00      0.225     -0.068       0.281       0.068
+53615.00      0.224     -0.058       0.333       0.021
+53616.00      0.216     -0.042       0.323      -0.254
+53617.00      0.202     -0.048       0.280      -0.433
+53618.00      0.184     -0.060       0.255      -0.463
+53619.00      0.168     -0.061       0.260      -0.295
+53620.00      0.156     -0.054       0.204      -0.191
+53621.00      0.146     -0.059       0.158      -0.143
+53622.00      0.139     -0.086       0.136      -0.229
+53623.00      0.144     -0.120       0.221      -0.210
+53624.00      0.163     -0.144       0.291      -0.207
+53625.00      0.187     -0.145       0.317      -0.255
+53626.00      0.204     -0.129       0.305      -0.167
+53627.00      0.212     -0.108       0.222       0.018
+53628.00      0.214     -0.106       0.143      -0.070
+53629.00      0.217     -0.125       0.139      -0.179
+53630.00      0.223     -0.130       0.278      -0.355
+53631.00      0.219     -0.092       0.375      -0.272
+53632.00      0.194     -0.045       0.275      -0.045
+53633.00      0.162     -0.037       0.165      -0.018
+53634.00      0.145     -0.053       0.149      -0.053
+53635.00      0.144     -0.057       0.240      -0.265
+53636.00      0.151     -0.056       0.295      -0.131
+53637.00      0.166     -0.077       0.292      -0.087
+53638.00      0.190     -0.107       0.260      -0.031
+53639.00      0.214     -0.110       0.234      -0.133
+53640.00      0.227     -0.094       0.241      -0.071
+53641.00      0.232     -0.078       0.291      -0.020
+53642.00      0.231     -0.068       0.333       0.167
+53643.00      0.227     -0.055       0.352       0.144
+53644.00      0.221     -0.045       0.372      -0.026
+53645.00      0.211     -0.047       0.323      -0.196
+53646.00      0.191     -0.055       0.285      -0.282
+53647.00      0.169     -0.061       0.271      -0.150
+53648.00      0.158     -0.066       0.268      -0.028
+53649.00      0.156     -0.077       0.320       0.029
+53650.00      0.157     -0.092       0.334      -0.029
+53651.00      0.164     -0.110       0.334      -0.142
+53652.00      0.187     -0.129       0.327      -0.228
+53653.00      0.219     -0.139       0.353      -0.166
+53654.00      0.240     -0.133       0.296      -0.007
+53655.00      0.243     -0.116       0.269       0.052
+53656.00      0.237     -0.111       0.257       0.141
+53657.00      0.232     -0.126       0.349       0.104
+53658.00      0.227     -0.134       0.485       0.012
+53659.00      0.215     -0.116       0.502       0.031
+53660.00      0.195     -0.088       0.389       0.248
+53661.00      0.180     -0.082       0.223       0.297
+53662.00      0.174     -0.090       0.120       0.260
+53663.00      0.176     -0.091       0.191       0.079
+53664.00      0.184     -0.090       0.343      -0.061
+53665.00      0.201     -0.102       0.465      -0.086
+53666.00      0.226     -0.118       0.492      -0.196
+53667.00      0.250     -0.119       0.443      -0.310
+53668.00      0.261     -0.114       0.421      -0.327
+53669.00      0.259     -0.120       0.392      -0.264
+53670.00      0.250     -0.123       0.388      -0.068
+53671.00      0.243     -0.103       0.391      -0.071
+53672.00      0.236     -0.072       0.388      -0.130
+53673.00      0.224     -0.059       0.342      -0.142
+53674.00      0.203     -0.070       0.297      -0.137
+53675.00      0.184     -0.094       0.275      -0.127
+53676.00      0.179     -0.121       0.270      -0.067
+53677.00      0.192     -0.144       0.267      -0.091
+53678.00      0.210     -0.148       0.263      -0.195
+53679.00      0.226     -0.128       0.261      -0.284
+53680.00      0.239     -0.103       0.000       0.000
+53681.00      0.251     -0.096       0.000       0.000
+53682.00      0.256     -0.101       0.000       0.000
+53683.00      0.254     -0.105       0.000       0.000
+53684.00      0.246     -0.110       0.000       0.000
+53685.00      0.235     -0.123       0.000       0.000
+53686.00      0.223     -0.133       0.000       0.000
+53687.00      0.214     -0.128       0.000       0.000
+53688.00      0.208     -0.117       0.000       0.000
+53689.00      0.203     -0.117       0.000       0.000
+53690.00      0.200     -0.126       0.000       0.000
+53691.00      0.202     -0.133       0.000       0.000
+53692.00      0.214     -0.136       0.000       0.000
+53693.00      0.234     -0.144       0.000       0.000
+53694.00      0.255     -0.146       0.000       0.000
+53695.00      0.271     -0.135       0.000       0.000
+53696.00      0.277     -0.128       0.000       0.000
+53697.00      0.275     -0.143       0.000       0.000
+53698.00      0.268     -0.161       0.000       0.000
+53699.00      0.258     -0.145       0.000       0.000
+53700.00      0.243     -0.108       0.000       0.000
+53701.00      0.222     -0.091       0.000       0.000
+53702.00      0.203     -0.113       0.000       0.000
+53703.00      0.197     -0.152       0.000       0.000
+53704.00      0.207     -0.187       0.000       0.000
+53705.00      0.227     -0.209       0.000       0.000
+53706.00      0.249     -0.206       0.000       0.000
+53707.00      0.258     -0.160       0.000       0.000
+53708.00      0.266     -0.120       0.000       0.000
+53709.00      0.260     -0.099       0.000       0.000
+53710.00      0.245     -0.101       0.000       0.000
+53711.00      0.233     -0.111       0.000       0.000
+53712.00      0.229     -0.119       0.000       0.000
+53713.00      0.226     -0.124       0.000       0.000
+53714.00      0.215     -0.124       0.000       0.000
+53715.00      0.202     -0.114       0.000       0.000
+53716.00      0.198     -0.104       0.000       0.000
+53717.00      0.196     -0.103       0.000       0.000
+53718.00      0.192     -0.111       0.000       0.000
+53719.00      0.192     -0.119       0.000       0.000
+53720.00      0.205     -0.131       0.000       0.000
+53721.00      0.225     -0.144       0.000       0.000
+53722.00      0.238     -0.150       0.000       0.000
+53723.00      0.244     -0.134       0.000       0.000
+53724.00      0.246     -0.110       0.000       0.000
+53725.00      0.248     -0.105       0.000       0.000
+53726.00      0.245     -0.110       0.000       0.000
+53727.00      0.233     -0.101       0.000       0.000
+53728.00      0.206     -0.082       0.000       0.000
+53729.00      0.175     -0.084       0.000       0.000
+53730.00      0.160     -0.113       0.000       0.000
+53731.00      0.171     -0.140       0.000       0.000
+53732.00      0.194     -0.153       0.000       0.000
+53733.00      0.215     -0.156       0.000       0.000
+53734.00      0.231     -0.148       0.000       0.000
+53735.00      0.239     -0.124       0.000       0.000
+53736.00      0.240     -0.103       0.000       0.000
+53737.00      0.238     -0.099       0.000       0.000
+53738.00      0.231     -0.095       0.000       0.000
+53739.00      0.217     -0.077       0.000       0.000
+53740.00      0.202     -0.065       0.000       0.000
+53741.00      0.192     -0.072       0.000       0.000
+53742.00      0.181     -0.078       0.000       0.000
+53743.00      0.164     -0.067       0.000       0.000
+53744.00      0.149     -0.052       0.000       0.000
+53745.00      0.145     -0.052       0.000       0.000
+53746.00      0.148     -0.061       0.000       0.000
+53747.00      0.157     -0.072       0.000       0.000
+53748.00      0.172     -0.088       0.000       0.000
+53749.00      0.191     -0.107       0.000       0.000
+53750.00      0.202     -0.118       0.000       0.000
+53751.00      0.206     -0.104       0.000       0.000
+53752.00      0.208     -0.073       0.000       0.000
+53753.00      0.210     -0.049       0.000       0.000
+53754.00      0.206     -0.037       0.000       0.000
+53755.00      0.189     -0.032       0.000       0.000
+53756.00      0.158     -0.039       0.000       0.000
+53757.00      0.129     -0.066       0.000       0.000
+53758.00      0.128     -0.093       0.000       0.000
+53759.00      0.149     -0.092       0.000       0.000
+53760.00      0.170     -0.080       0.000       0.000
+53761.00      0.185     -0.089       0.000       0.000
+53762.00      0.206     -0.096       0.000       0.000
+53763.00      0.226     -0.069       0.000       0.000
+53764.00      0.227     -0.032       0.000       0.000
+53765.00      0.216     -0.031       0.000       0.000
+53766.00      0.211     -0.044       0.000       0.000
+53767.00      0.202     -0.030       0.000       0.000
+53768.00      0.177     -0.007       0.000       0.000
+53769.00      0.153     -0.016       0.000       0.000
+53770.00      0.145     -0.039       0.000       0.000
+53771.00      0.141     -0.037       0.000       0.000
+53772.00      0.132     -0.018       0.000       0.000
+53773.00      0.129     -0.014       0.000       0.000
+53774.00      0.142     -0.027       0.000       0.000
+53775.00      0.163     -0.041       0.000       0.000
+53776.00      0.186     -0.056       0.000       0.000
+53777.00      0.205     -0.066       0.000       0.000
+53778.00      0.219     -0.063       0.000       0.000
+53779.00      0.226     -0.039       0.000       0.000
+53780.00      0.227     -0.008       0.000       0.000
+53781.00      0.220      0.011       0.000       0.000
+53782.00      0.204      0.014       0.000       0.000
+53783.00      0.181      0.012       0.000       0.000
+53784.00      0.158     -0.002       0.000       0.000
+53785.00      0.148     -0.032       0.000       0.000
+53786.00      0.166     -0.052       0.000       0.000
+53787.00      0.197     -0.034       0.000       0.000
+53788.00      0.209     -0.010       0.000       0.000
+53789.00      0.202     -0.034       0.000       0.000
+53790.00      0.215     -0.081       0.000       0.000
+53791.00      0.254     -0.070       0.000       0.000
+53792.00      0.277     -0.003       0.000       0.000
+53793.00      0.265      0.035       0.000       0.000
+53794.00      0.247      0.013       0.000       0.000
+53795.00      0.237     -0.018       0.000       0.000
+53796.00      0.223     -0.024       0.000       0.000
+53797.00      0.000      0.000       0.000       0.000
+53798.00      0.000      0.000       0.000       0.000
+53799.00      0.000      0.000       0.000       0.000
+53800.00      0.000      0.000       0.000       0.000
+53801.00      0.000      0.000       0.000       0.000
+53802.00      0.000      0.000       0.000       0.000
+53803.00      0.000      0.000       0.000       0.000
+53804.00      0.000      0.000       0.000       0.000
+53805.00      0.000      0.000       0.000       0.000
+53806.00      0.000      0.000       0.000       0.000
+53807.00      0.000      0.000       0.000       0.000
+53808.00      0.000      0.000       0.000       0.000
+53809.00      0.000      0.000       0.000       0.000
+53810.00      0.000      0.000       0.000       0.000
+53811.00      0.000      0.000       0.000       0.000
+53812.00      0.000      0.000       0.000       0.000
+53813.00      0.000      0.000       0.000       0.000
+53814.00      0.000      0.000       0.000       0.000
+53815.00      0.000      0.000       0.000       0.000
+53816.00      0.000      0.000       0.000       0.000
+53817.00      0.000      0.000       0.000       0.000
+53818.00      0.000      0.000       0.000       0.000
+53819.00      0.000      0.000       0.000       0.000
+53820.00      0.000      0.000       0.000       0.000
+53821.00      0.000      0.000       0.000       0.000
+53822.00      0.000      0.000       0.000       0.000
+53823.00      0.000      0.000       0.000       0.000
+53824.00      0.000      0.000       0.000       0.000
+53825.00      0.000      0.000       0.000       0.000
+53826.00      0.000      0.000       0.000       0.000
+53827.00      0.000      0.000       0.000       0.000
+53828.00      0.000      0.000       0.000       0.000
+53829.00      0.000      0.000       0.000       0.000
+53830.00      0.000      0.000       0.000       0.000
+53831.00      0.000      0.000       0.000       0.000
+53832.00      0.000      0.000       0.000       0.000
+53833.00      0.000      0.000       0.000       0.000
+53834.00      0.000      0.000       0.000       0.000
+53835.00      0.000      0.000       0.000       0.000
+53836.00      0.000      0.000       0.000       0.000
+53837.00      0.000      0.000       0.000       0.000
+53838.00      0.000      0.000       0.000       0.000
+53839.00      0.000      0.000       0.000       0.000
+53840.00      0.000      0.000       0.000       0.000
+53841.00      0.000      0.000       0.000       0.000
+53842.00      0.000      0.000       0.000       0.000
+53843.00      0.000      0.000       0.000       0.000
+53844.00      0.000      0.000       0.000       0.000
+53845.00      0.000      0.000       0.000       0.000
+53846.00      0.000      0.000       0.000       0.000
+53847.00      0.000      0.000       0.000       0.000
+53848.00      0.000      0.000       0.000       0.000
+53849.00      0.000      0.000       0.000       0.000
+53850.00      0.000      0.000       0.000       0.000
+53851.00      0.000      0.000       0.000       0.000
+53852.00      0.000      0.000       0.000       0.000
+53853.00      0.000      0.000       0.000       0.000
+53854.00      0.000      0.000       0.000       0.000
+53855.00      0.000      0.000       0.000       0.000
+53856.00      0.000      0.000       0.000       0.000
+53857.00      0.000      0.000       0.000       0.000
+53858.00      0.000      0.000       0.000       0.000
+53859.00      0.000      0.000       0.000       0.000
+53860.00      0.000      0.000       0.000       0.000
+53861.00      0.000      0.000       0.000       0.000
+53862.00      0.000      0.000       0.000       0.000
+53863.00      0.000      0.000       0.000       0.000
+53864.00      0.000      0.000       0.000       0.000
+53865.00      0.000      0.000       0.000       0.000
+53866.00      0.000      0.000       0.000       0.000
+53867.00      0.000      0.000       0.000       0.000
+53868.00      0.000      0.000       0.000       0.000
+53869.00      0.000      0.000       0.000       0.000
+53870.00      0.000      0.000       0.000       0.000
+53871.00      0.000      0.000       0.000       0.000
+53872.00      0.000      0.000       0.000       0.000
+53873.00      0.000      0.000       0.000       0.000
+53874.00      0.000      0.000       0.000       0.000
+53875.00      0.000      0.000       0.000       0.000
+53876.00      0.000      0.000       0.000       0.000
+53877.00      0.000      0.000       0.000       0.000
+53878.00      0.000      0.000       0.000       0.000
+53879.00      0.000      0.000       0.000       0.000
+53880.00      0.000      0.000       0.000       0.000
+53881.00      0.000      0.000       0.000       0.000
+53882.00      0.000      0.000       0.000       0.000
+53883.00      0.000      0.000       0.000       0.000
+53884.00      0.000      0.000       0.000       0.000
+53885.00      0.000      0.000       0.000       0.000
+53886.00      0.000      0.000       0.000       0.000
+53887.00      0.000      0.000       0.000       0.000
+53888.00      0.000      0.000       0.000       0.000
+53889.00      0.000      0.000       0.000       0.000
+53890.00      0.000      0.000       0.000       0.000
+53891.00      0.000      0.000       0.000       0.000
+53892.00      0.000      0.000       0.000       0.000
+53893.00      0.000      0.000       0.000       0.000
+53894.00      0.000      0.000       0.000       0.000
+53895.00      0.000      0.000       0.000       0.000
+53896.00      0.000      0.000       0.000       0.000
+53897.00      0.000      0.000       0.000       0.000
+53898.00      0.000      0.000       0.000       0.000
+53899.00      0.000      0.000       0.000       0.000
+53900.00      0.000      0.000       0.000       0.000
+53901.00      0.000      0.000       0.000       0.000
+53902.00      0.000      0.000       0.000       0.000
+53903.00      0.000      0.000       0.000       0.000
+53904.00      0.000      0.000       0.000       0.000
+53905.00      0.000      0.000       0.000       0.000
+53906.00      0.000      0.000       0.000       0.000
+53907.00      0.000      0.000       0.000       0.000
+53908.00      0.000      0.000       0.000       0.000
+53909.00      0.000      0.000       0.000       0.000
+53910.00      0.000      0.000       0.000       0.000
+53911.00      0.000      0.000       0.000       0.000
+53912.00      0.000      0.000       0.000       0.000
+53913.00      0.000      0.000       0.000       0.000
+53914.00      0.000      0.000       0.000       0.000
+53915.00      0.000      0.000       0.000       0.000
+53916.00      0.000      0.000       0.000       0.000
+53917.00      0.000      0.000       0.000       0.000
+53918.00      0.000      0.000       0.000       0.000
+53919.00      0.000      0.000       0.000       0.000
+53920.00      0.000      0.000       0.000       0.000
+53921.00      0.000      0.000       0.000       0.000
+53922.00      0.000      0.000       0.000       0.000
+53923.00      0.000      0.000       0.000       0.000
+53924.00      0.000      0.000       0.000       0.000
+53925.00      0.000      0.000       0.000       0.000
+53926.00      0.000      0.000       0.000       0.000
+53927.00      0.000      0.000       0.000       0.000
+53928.00      0.000      0.000       0.000       0.000
+53929.00      0.000      0.000       0.000       0.000
+53930.00      0.000      0.000       0.000       0.000
+53931.00      0.000      0.000       0.000       0.000
+53932.00      0.000      0.000       0.000       0.000
+53933.00      0.000      0.000       0.000       0.000
+53934.00      0.000      0.000       0.000       0.000
+53935.00      0.000      0.000       0.000       0.000
+53936.00      0.000      0.000       0.000       0.000
+53937.00      0.000      0.000       0.000       0.000
+53938.00      0.000      0.000       0.000       0.000
+53939.00      0.000      0.000       0.000       0.000
+53940.00      0.000      0.000       0.000       0.000
+53941.00      0.000      0.000       0.000       0.000
+53942.00      0.000      0.000       0.000       0.000
+53943.00      0.000      0.000       0.000       0.000
+53944.00      0.000      0.000       0.000       0.000
+53945.00      0.000      0.000       0.000       0.000
+53946.00      0.000      0.000       0.000       0.000
+53947.00      0.000      0.000       0.000       0.000
+53948.00      0.000      0.000       0.000       0.000
+53949.00      0.000      0.000       0.000       0.000
+53950.00      0.000      0.000       0.000       0.000
+53951.00      0.000      0.000       0.000       0.000
+53952.00      0.000      0.000       0.000       0.000
+53953.00      0.000      0.000       0.000       0.000
+53954.00      0.000      0.000       0.000       0.000
+53955.00      0.000      0.000       0.000       0.000
+53956.00      0.000      0.000       0.000       0.000
+53957.00      0.000      0.000       0.000       0.000
+53958.00      0.000      0.000       0.000       0.000
+53959.00      0.000      0.000       0.000       0.000
+53960.00      0.000      0.000       0.000       0.000
+53961.00      0.000      0.000       0.000       0.000
+53962.00      0.000      0.000       0.000       0.000
+53963.00      0.000      0.000       0.000       0.000
+53964.00      0.000      0.000       0.000       0.000
+53965.00      0.000      0.000       0.000       0.000
+53966.00      0.000      0.000       0.000       0.000
+53967.00      0.000      0.000       0.000       0.000
+53968.00      0.000      0.000       0.000       0.000
+53969.00      0.000      0.000       0.000       0.000
+53970.00      0.000      0.000       0.000       0.000
+53971.00      0.000      0.000       0.000       0.000
+53972.00      0.000      0.000       0.000       0.000
+53973.00      0.000      0.000       0.000       0.000
+53974.00      0.000      0.000       0.000       0.000
+53975.00      0.000      0.000       0.000       0.000
+53976.00      0.000      0.000       0.000       0.000
+53977.00      0.000      0.000       0.000       0.000
+53978.00      0.000      0.000       0.000       0.000
+53979.00      0.000      0.000       0.000       0.000
+53980.00      0.000      0.000       0.000       0.000
+53981.00      0.000      0.000       0.000       0.000
+53982.00      0.000      0.000       0.000       0.000
+53983.00      0.000      0.000       0.000       0.000
+53984.00      0.000      0.000       0.000       0.000
+53985.00      0.000      0.000       0.000       0.000
+53986.00      0.000      0.000       0.000       0.000
+53987.00      0.000      0.000       0.000       0.000
+53988.00      0.000      0.000       0.000       0.000
+53989.00      0.000      0.000       0.000       0.000
+53990.00      0.000      0.000       0.000       0.000
+53991.00      0.000      0.000       0.000       0.000
+53992.00      0.000      0.000       0.000       0.000
+53993.00      0.000      0.000       0.000       0.000
+53994.00      0.000      0.000       0.000       0.000
+53995.00      0.000      0.000       0.000       0.000
+53996.00      0.000      0.000       0.000       0.000
+53997.00      0.000      0.000       0.000       0.000
+53998.00      0.000      0.000       0.000       0.000
+53999.00      0.000      0.000       0.000       0.000
+54000.00      0.000      0.000       0.000       0.000
+54001.00      0.000      0.000       0.000       0.000
+54002.00      0.000      0.000       0.000       0.000
+54003.00      0.000      0.000       0.000       0.000
+54004.00      0.000      0.000       0.000       0.000
+54005.00      0.000      0.000       0.000       0.000
+54006.00      0.000      0.000       0.000       0.000
+54007.00      0.000      0.000       0.000       0.000
+54008.00      0.000      0.000       0.000       0.000
+54009.00      0.000      0.000       0.000       0.000
+54010.00      0.000      0.000       0.000       0.000
+54011.00      0.000      0.000       0.000       0.000
+54012.00      0.000      0.000       0.000       0.000
+54013.00      0.000      0.000       0.000       0.000
+54014.00      0.000      0.000       0.000       0.000
+54015.00      0.000      0.000       0.000       0.000
+54016.00      0.000      0.000       0.000       0.000
+54017.00      0.000      0.000       0.000       0.000
+54018.00      0.000      0.000       0.000       0.000
+54019.00      0.000      0.000       0.000       0.000
+54020.00      0.000      0.000       0.000       0.000
+54021.00      0.000      0.000       0.000       0.000
+54022.00      0.000      0.000       0.000       0.000
+54023.00      0.000      0.000       0.000       0.000
+54024.00      0.000      0.000       0.000       0.000
+54025.00      0.000      0.000       0.000       0.000
+54026.00      0.000      0.000       0.000       0.000
+54027.00      0.000      0.000       0.000       0.000
+54028.00      0.000      0.000       0.000       0.000
+54029.00      0.000      0.000       0.000       0.000
+54030.00      0.000      0.000       0.000       0.000
+54031.00      0.000      0.000       0.000       0.000
+54032.00      0.000      0.000       0.000       0.000
+54033.00      0.000      0.000       0.000       0.000
+54034.00      0.000      0.000       0.000       0.000
+54035.00      0.000      0.000       0.000       0.000
+54036.00      0.000      0.000       0.000       0.000
+54037.00      0.000      0.000       0.000       0.000
+54038.00      0.000      0.000       0.000       0.000
+54039.00      0.000      0.000       0.000       0.000
+54040.00      0.000      0.000       0.000       0.000
+54041.00      0.000      0.000       0.000       0.000
+54042.00      0.000      0.000       0.000       0.000
+54043.00      0.000      0.000       0.000       0.000
+54044.00      0.000      0.000       0.000       0.000
+54045.00      0.000      0.000       0.000       0.000
+54046.00      0.000      0.000       0.000       0.000
+54047.00      0.000      0.000       0.000       0.000
+54048.00      0.000      0.000       0.000       0.000
+54049.00      0.000      0.000       0.000       0.000
+54050.00      0.000      0.000       0.000       0.000
+54051.00      0.000      0.000       0.000       0.000
+54052.00      0.000      0.000       0.000       0.000
+54053.00      0.000      0.000       0.000       0.000
+54054.00      0.000      0.000       0.000       0.000
+54055.00      0.000      0.000       0.000       0.000
+54056.00      0.000      0.000       0.000       0.000
+54057.00      0.000      0.000       0.000       0.000
+54058.00      0.000      0.000       0.000       0.000
+54059.00      0.000      0.000       0.000       0.000
+54060.00      0.000      0.000       0.000       0.000
+54061.00      0.000      0.000       0.000       0.000
+54062.00      0.000      0.000       0.000       0.000
+54063.00      0.000      0.000       0.000       0.000
+54064.00      0.000      0.000       0.000       0.000
+54065.00      0.000      0.000       0.000       0.000
+54066.00      0.000      0.000       0.000       0.000
+54067.00      0.000      0.000       0.000       0.000
+54068.00      0.000      0.000       0.000       0.000
+54069.00      0.000      0.000       0.000       0.000
+54070.00      0.000      0.000       0.000       0.000
+54071.00      0.000      0.000       0.000       0.000
+54072.00      0.000      0.000       0.000       0.000
+54073.00      0.000      0.000       0.000       0.000
+54074.00      0.000      0.000       0.000       0.000
+54075.00      0.000      0.000       0.000       0.000
+54076.00      0.000      0.000       0.000       0.000
+54077.00      0.000      0.000       0.000       0.000
+54078.00      0.000      0.000       0.000       0.000
+54079.00      0.000      0.000       0.000       0.000
+54080.00      0.000      0.000       0.000       0.000
+54081.00      0.000      0.000       0.000       0.000
+54082.00      0.000      0.000       0.000       0.000
+54083.00      0.000      0.000       0.000       0.000
+54084.00      0.000      0.000       0.000       0.000
+54085.00      0.000      0.000       0.000       0.000
+54086.00      0.000      0.000       0.000       0.000
+54087.00      0.000      0.000       0.000       0.000
+54088.00      0.000      0.000       0.000       0.000
+54089.00      0.000      0.000       0.000       0.000
+54090.00      0.000      0.000       0.000       0.000
+54091.00      0.000      0.000       0.000       0.000
+54092.00      0.000      0.000       0.000       0.000
+54093.00      0.000      0.000       0.000       0.000
+54094.00      0.000      0.000       0.000       0.000
+54095.00      0.000      0.000       0.000       0.000
+54096.00      0.000      0.000       0.000       0.000
+54097.00      0.000      0.000       0.000       0.000
+54098.00      0.000      0.000       0.000       0.000
+54099.00      0.000      0.000       0.000       0.000
+54100.00      0.000      0.000       0.000       0.000
+54101.00      0.000      0.000       0.000       0.000
+54102.00      0.000      0.000       0.000       0.000
+54103.00      0.000      0.000       0.000       0.000
+54104.00      0.000      0.000       0.000       0.000
+54105.00      0.000      0.000       0.000       0.000
+54106.00      0.000      0.000       0.000       0.000
+54107.00      0.000      0.000       0.000       0.000
+54108.00      0.000      0.000       0.000       0.000
+54109.00      0.000      0.000       0.000       0.000
+54110.00      0.000      0.000       0.000       0.000
+54111.00      0.000      0.000       0.000       0.000
+54112.00      0.000      0.000       0.000       0.000
+54113.00      0.000      0.000       0.000       0.000
+54114.00      0.000      0.000       0.000       0.000
+54115.00      0.000      0.000       0.000       0.000
+54116.00      0.000      0.000       0.000       0.000
+54117.00      0.000      0.000       0.000       0.000
+54118.00      0.000      0.000       0.000       0.000
+54119.00      0.000      0.000       0.000       0.000
+54120.00      0.000      0.000       0.000       0.000
+54121.00      0.000      0.000       0.000       0.000
+54122.00      0.000      0.000       0.000       0.000
+54123.00      0.000      0.000       0.000       0.000
+54124.00      0.000      0.000       0.000       0.000
+54125.00      0.000      0.000       0.000       0.000
+54126.00      0.000      0.000       0.000       0.000
+54127.00      0.000      0.000       0.000       0.000
+54128.00      0.000      0.000       0.000       0.000
+54129.00      0.000      0.000       0.000       0.000
+54130.00      0.000      0.000       0.000       0.000
+54131.00      0.000      0.000       0.000       0.000
+54132.00      0.000      0.000       0.000       0.000
+54133.00      0.000      0.000       0.000       0.000
+54134.00      0.000      0.000       0.000       0.000
+54135.00      0.000      0.000       0.000       0.000
+54136.00      0.000      0.000       0.000       0.000
+54137.00      0.000      0.000       0.000       0.000
+54138.00      0.000      0.000       0.000       0.000
+54139.00      0.000      0.000       0.000       0.000
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/finals_all.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/finals_all.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/finals_all.dat	(revision 22158)
@@ -0,0 +1,12232 @@
+#
+#  Stripped version of finals.all.orig file
+#
+#
+#          Bull A     Bull A      Bull A      Bull B      Bull B      Bull B
+#  MJD     PM-x       PM-y        UT1-UTC     PM-x        PM-y        UT1-UTC
+#
+41684.00   0.120724   0.137066   0.8084319    0.143000    0.137000    0.8075000
+41685.00   0.118971   0.135756   0.8056304    0.141000    0.134000    0.8044000
+41686.00   0.117218   0.134448   0.8028036    0.139000    0.131000    0.8012000
+41687.00   0.115464   0.133144   0.7998870    0.137000    0.128000    0.7981000
+41688.00   0.113708   0.131846   0.7968285    0.136000    0.126000    0.7949000
+41689.00   0.111948   0.130558   0.7935963    0.134000    0.123000    0.7918000
+41690.00   0.110180   0.129282   0.7901851    0.132000    0.122000    0.7887000
+41691.00   0.108401   0.128020   0.7866194    0.130000    0.120000    0.7855000
+41692.00   0.106607   0.126775   0.7829530    0.128000    0.119000    0.7824000
+41693.00   0.104795   0.125551   0.7792628    0.126000    0.117000    0.7792000
+41694.00   0.102960   0.124351   0.7756359    0.124000    0.116000    0.7761000
+41695.00   0.101103   0.123180   0.7721500    0.122000    0.114000    0.7730000
+41696.00   0.099219   0.122040   0.7688519    0.120000    0.113000    0.7698000
+41697.00   0.097304   0.120936   0.7657376    0.118000    0.111000    0.7667000
+41698.00   0.095355   0.119870   0.7627466    0.116000    0.110000    0.7635000
+41699.00   0.093368   0.118846   0.7597749    0.114000    0.108000    0.7604000
+41700.00   0.091341   0.117865   0.7567072    0.112000    0.106000    0.7573000
+41701.00   0.089273   0.116926   0.7534582    0.110000    0.105000    0.7541000
+41702.00   0.087167   0.116031   0.7500021    0.107000    0.103000    0.7510000
+41703.00   0.085025   0.115178   0.7463792    0.105000    0.102000    0.7478000
+41704.00   0.082853   0.114370   0.7426762    0.103000    0.100000    0.7447000
+41705.00   0.080657   0.113605   0.7389931    0.101000    0.098000    0.7415000
+41706.00   0.078440   0.112884   0.7354139    0.099000    0.097000    0.7383000
+41707.00   0.076205   0.112202   0.7319919    0.096000    0.095000    0.7352000
+41708.00   0.073954   0.111559   0.7287489    0.094000    0.094000    0.7320000
+41709.00   0.071691   0.110952   0.7256811    0.092000    0.092000    0.7288000
+41710.00   0.069420   0.110378   0.7227643    0.090000    0.091000    0.7256000
+41711.00   0.067147   0.109836   0.7199568    0.088000    0.089000    0.7224000
+41712.00   0.064874   0.109325   0.7172012    0.086000    0.088000    0.7193000
+41713.00   0.062607   0.108846   0.7144307    0.084000    0.087000    0.7161000
+41714.00   0.060349   0.108400   0.7115769    0.082000    0.086000    0.7129000
+41715.00   0.058100   0.107987   0.7085797    0.079000    0.084000    0.7096000
+41716.00   0.055865   0.107608   0.7053972    0.077000    0.083000    0.7063000
+41717.00   0.053644   0.107263   0.7020146    0.075000    0.082000    0.7031000
+41718.00   0.051441   0.106954   0.6984511    0.073000    0.080000    0.6998000
+41719.00   0.049257   0.106681   0.6947614    0.071000    0.079000    0.6965000
+41720.00   0.047093   0.106442   0.6910290    0.069000    0.080000    0.6932000
+41721.00   0.044951   0.106239   0.6873489    0.067000    0.081000    0.6899000
+41722.00   0.042831   0.106070   0.6838052    0.066000    0.082000    0.6866000
+41723.00   0.040732   0.105935   0.6804490    0.064000    0.083000    0.6833000
+41724.00   0.038653   0.105832   0.6772827    0.062000    0.085000    0.6800000
+41725.00   0.036593   0.105760   0.6742568    0.060000    0.086000    0.6767000
+41726.00   0.034550   0.105717   0.6712808    0.058000    0.087000    0.6734000
+41727.00   0.032521   0.105702   0.6682469    0.057000    0.088000    0.6701000
+41728.00   0.030505   0.105715   0.6650607    0.055000    0.089000    0.6668000
+41729.00   0.028503   0.105755   0.6616712    0.053000    0.090000    0.6635000
+41730.00   0.026512   0.105824   0.6580860    0.051000    0.091000    0.6601000
+41731.00   0.024531   0.105922   0.6543676    0.049000    0.092000    0.6568000
+41732.00   0.022556   0.106048   0.6506111    0.047000    0.093000    0.6534000
+41733.00   0.020582   0.106203   0.6469136    0.045000    0.094000    0.6501000
+41734.00   0.018606   0.106384   0.6433499    0.044000    0.095000    0.6467000
+41735.00   0.016623   0.106592   0.6399606    0.042000    0.096000    0.6433000
+41736.00   0.014632   0.106828   0.6367535    0.040000    0.097000    0.6400000
+41737.00   0.012634   0.107093   0.6337102    0.038000    0.098000    0.6366000
+41738.00   0.010628   0.107386   0.6307923    0.036000    0.099000    0.6333000
+41739.00   0.008615   0.107709   0.6279462    0.034000    0.100000    0.6299000
+41740.00   0.006593   0.108060   0.6251074    0.032000    0.101000    0.6265000
+41741.00   0.004564   0.108438   0.6222069    0.030000    0.102000    0.6232000
+41742.00   0.002526   0.108842   0.6191790    0.028000    0.102000    0.6198000
+41743.00   0.000479   0.109270   0.6159706    0.026000    0.103000    0.6165000
+41744.00  -0.001578   0.109721   0.6125505    0.024000    0.104000    0.6131000
+41745.00  -0.003643   0.110195   0.6089196    0.022000    0.105000    0.6097000
+41746.00  -0.005713   0.110692   0.6051180    0.020000    0.106000    0.6063000
+41747.00  -0.007786   0.111214   0.6012241    0.018000    0.106000    0.6030000
+41748.00  -0.009857   0.111761   0.5973410    0.016000    0.107000    0.5996000
+41749.00  -0.011922   0.112336   0.5935706    0.014000    0.108000    0.5962000
+41750.00  -0.013977   0.112940   0.5899833    0.012000    0.109000    0.5928000
+41751.00  -0.016019   0.113573   0.5865962    0.009000    0.109000    0.5893000
+41752.00  -0.018040   0.114237   0.5833682    0.007000    0.110000    0.5859000
+41753.00  -0.020032   0.114933   0.5802133    0.004000    0.111000    0.5824000
+41754.00  -0.021990   0.115661   0.5770261    0.002000    0.112000    0.5790000
+41755.00  -0.023907   0.116421   0.5737111    0.000000    0.112000    0.5755000
+41756.00  -0.025780   0.117212   0.5702072   -0.003000    0.113000    0.5720000
+41757.00  -0.027610   0.118036   0.5665027   -0.005000    0.114000    0.5685000
+41758.00  -0.029400   0.118890   0.5626361   -0.008000    0.114000    0.5650000
+41759.00  -0.031155   0.119773   0.5586838   -0.010000    0.115000    0.5615000
+41760.00  -0.032878   0.120683   0.5547386   -0.012000    0.116000    0.5579000
+41761.00  -0.034573   0.121619   0.5508857   -0.015000    0.117000    0.5544000
+41762.00  -0.036242   0.122582   0.5471853   -0.017000    0.118000    0.5508000
+41763.00  -0.037885   0.123571   0.5436641   -0.020000    0.119000    0.5473000
+41764.00  -0.039504   0.124588   0.5403179   -0.022000    0.120000    0.5437000
+41765.00  -0.041099   0.125635   0.5371173   -0.024000    0.120000    0.5401000
+41766.00  -0.042673   0.126712   0.5340153   -0.027000    0.121000    0.5365000
+41767.00  -0.044229   0.127821   0.5309537   -0.029000    0.122000    0.5330000
+41768.00  -0.045771   0.128964   0.5278687   -0.032000    0.123000    0.5294000
+41769.00  -0.047302   0.130142   0.5246976   -0.034000    0.124000    0.5258000
+41770.00  -0.048828   0.131356   0.5213856   -0.036000    0.125000    0.5222000
+41771.00  -0.050351   0.132605   0.5178924   -0.039000    0.127000    0.5186000
+41772.00  -0.051875   0.133891   0.5142009   -0.041000    0.128000    0.5149000
+41773.00  -0.053404   0.135214   0.5103278   -0.044000    0.129000    0.5113000
+41774.00  -0.054940   0.136573   0.5063304   -0.046000    0.131000    0.5077000
+41775.00  -0.056488   0.137969   0.5023026   -0.048000    0.132000    0.5041000
+41776.00  -0.058053   0.139402   0.4983553   -0.051000    0.133000    0.5006000
+41777.00  -0.059639   0.140872   0.4945843   -0.053000    0.134000    0.4970000
+41778.00  -0.061247   0.142377   0.4910366   -0.056000    0.136000    0.4935000
+41779.00  -0.062874   0.143917   0.4876939   -0.058000    0.137000    0.4899000
+41780.00  -0.064517   0.145494   0.4844787   -0.061000    0.139000    0.4864000
+41781.00  -0.066174   0.147108   0.4812836   -0.063000    0.141000    0.4829000
+41782.00  -0.067840   0.148757   0.4780073   -0.066000    0.143000    0.4794000
+41783.00  -0.069512   0.150437   0.4745829   -0.068000    0.145000    0.4759000
+41784.00  -0.071188   0.152143   0.4709918   -0.071000    0.147000    0.4724000
+41785.00  -0.072868   0.153873   0.4672608   -0.073000    0.148000    0.4689000
+41786.00  -0.074547   0.155619   0.4634499   -0.076000    0.150000    0.4655000
+41787.00  -0.076226   0.157377   0.4596361   -0.078000    0.152000    0.4620000
+41788.00  -0.077898   0.159141   0.4558961   -0.081000    0.154000    0.4586000
+41789.00  -0.079559   0.160904   0.4522916   -0.083000    0.156000    0.4551000
+41790.00  -0.081206   0.162664   0.4488589   -0.085000    0.158000    0.4517000
+41791.00  -0.082836   0.164416   0.4456047   -0.086000    0.160000    0.4483000
+41792.00  -0.084445   0.166159   0.4425079   -0.088000    0.162000    0.4448000
+41793.00  -0.086031   0.167888   0.4395262   -0.090000    0.164000    0.4414000
+41794.00  -0.087594   0.169602   0.4366037   -0.092000    0.166000    0.4380000
+41795.00  -0.089132   0.171299   0.4336788   -0.093000    0.168000    0.4346000
+41796.00  -0.090646   0.172977   0.4306908   -0.095000    0.170000    0.4312000
+41797.00  -0.092135   0.174637   0.4275866   -0.097000    0.172000    0.4277000
+41798.00  -0.093600   0.176280   0.4243250   -0.098000    0.174000    0.4243000
+41799.00  -0.095039   0.177908   0.4208818   -0.100000    0.176000    0.4209000
+41800.00  -0.096452   0.179524   0.4172571   -0.101000    0.178000    0.4175000
+41801.00  -0.097839   0.181129   0.4134837   -0.102000    0.180000    0.4141000
+41802.00  -0.099202   0.182728   0.4096311   -0.103000    0.181000    0.4108000
+41803.00  -0.100543   0.184322   0.4057984   -0.104000    0.183000    0.4074000
+41804.00  -0.101860   0.185910   0.4020902   -0.106000    0.185000    0.4040000
+41805.00  -0.103149   0.187492   0.3985825   -0.107000    0.187000    0.4006000
+41806.00  -0.104401   0.189067   0.3952917   -0.108000    0.189000    0.3972000
+41807.00  -0.105607   0.190634   0.3921651   -0.109000    0.190000    0.3939000
+41808.00  -0.106760   0.192195   0.3891000   -0.110000    0.192000    0.3905000
+41809.00  -0.107853   0.193751   0.3859841   -0.111000    0.194000    0.3871000
+41810.00  -0.108882   0.195303   0.3827358   -0.112000    0.196000    0.3838000
+41811.00  -0.109843   0.196854   0.3793280   -0.112000    0.198000    0.3805000
+41812.00  -0.110735   0.198402   0.3757875   -0.113000    0.200000    0.3771000
+41813.00  -0.111557   0.199950   0.3721774   -0.113000    0.202000    0.3738000
+41814.00  -0.112313   0.201499   0.3685739   -0.114000    0.204000    0.3705000
+41815.00  -0.113006   0.203052   0.3650488   -0.114000    0.205000    0.3672000
+41816.00  -0.113643   0.204611   0.3616590   -0.115000    0.207000    0.3640000
+41817.00  -0.114229   0.206179   0.3584406   -0.115000    0.209000    0.3607000
+41818.00  -0.114769   0.207756   0.3554062   -0.116000    0.211000    0.3575000
+41819.00  -0.115267   0.209342   0.3525437   -0.116000    0.213000    0.3542000
+41820.00  -0.115729   0.210937   0.3498182   -0.116000    0.214000    0.3510000
+41821.00  -0.116160   0.212543   0.3471778   -0.116000    0.216000    0.3479000
+41822.00  -0.116560   0.214161   0.3445621   -0.116000    0.217000    0.3447000
+41823.00  -0.116928   0.215794   0.3419107   -0.116000    0.219000    0.3416000
+41824.00  -0.117260   0.217446   0.3391710   -0.117000    0.220000    0.3384000
+41825.00  -0.117551   0.219118   0.3363033   -0.117000    0.221000    0.3353000
+41826.00  -0.117796   0.220811   0.3332839   -0.117000    0.223000    0.3321000
+41827.00  -0.117988   0.222526   0.3301084   -0.117000    0.224000    0.3290000
+41828.00  -0.118122   0.224260   0.3267957   -0.117000    0.226000    0.3258000
+41829.00  -0.118191   0.226015   0.3233929   -0.117000    0.227000    0.3227000
+41830.00  -0.118187   0.227791   0.3199751   -0.117000    0.228000    0.3196000
+41831.00  -0.118104   0.229587   0.3166341   -0.117000    0.230000    0.3166000
+41832.00  -0.117943   0.231402   0.3134538   -0.117000    0.231000    0.3135000
+41833.00  -0.117703   0.233238   0.3104780   -0.117000    0.233000    0.3105000
+41834.00  -0.117388   0.235091   0.3076868   -0.117000    0.234000    0.3074000
+41835.00  -0.117002   0.236962   0.3049978   -0.117000    0.235000    0.3044000
+41836.00  -0.116549   0.238846   0.3022950   -0.117000    0.237000    0.3014000
+41837.00  -0.116036   0.240738   0.2994746   -0.117000    0.238000    0.2984000
+41838.00  -0.115466   0.242636   0.2964846   -0.117000    0.240000    0.2954000
+41839.00  -0.114846   0.244536   0.2933393   -0.117000    0.241000    0.2924000
+41840.00  -0.114180   0.246436   0.2901054   -0.117000    0.243000    0.2895000
+41841.00  -0.113474   0.248333   0.2868723   -0.116000    0.245000    0.2865000
+41842.00  -0.112728   0.250227   0.2837227   -0.116000    0.246000    0.2836000
+41843.00  -0.111943   0.252117   0.2807165   -0.116000    0.248000    0.2806000
+41844.00  -0.111124   0.254000   0.2778874   -0.116000    0.250000    0.2777000
+41845.00  -0.110279   0.255878   0.2752458   -0.115000    0.252000    0.2748000
+41846.00  -0.109416   0.257745   0.2727809   -0.115000    0.254000    0.2720000
+41847.00  -0.108543   0.259600   0.2704624   -0.115000    0.255000    0.2691000
+41848.00  -0.107669   0.261438   0.2682428   -0.114000    0.257000    0.2663000
+41849.00  -0.106798   0.263258   0.2660632   -0.114000    0.259000    0.2634000
+41850.00  -0.105935   0.265060   0.2638618   -0.113000    0.261000    0.2607000
+41851.00  -0.105082   0.266846   0.2615839   -0.112000    0.263000    0.2580000
+41852.00  -0.104241   0.268620   0.2591881   -0.111000    0.264000    0.2552000
+41853.00  -0.103414   0.270385   0.2566509   -0.110000    0.266000    0.2525000
+41854.00  -0.102602   0.272147   0.2539691   -0.110000    0.268000    0.2498000
+41855.00  -0.101802   0.273910   0.2511601   -0.109000    0.270000    0.2472000
+41856.00  -0.101014   0.275678   0.2482631   -0.108000    0.272000    0.2446000
+41857.00  -0.100233   0.277455   0.2453372   -0.107000    0.273000    0.2421000
+41858.00  -0.099456   0.279243   0.2424569   -0.106000    0.275000    0.2395000
+41859.00  -0.098677   0.281043   0.2396968   -0.105000    0.277000    0.2369000
+41860.00  -0.097889   0.282855   0.2371084   -0.103000    0.279000    0.2344000
+41861.00  -0.097085   0.284679   0.2346963   -0.102000    0.281000    0.2320000
+41862.00  -0.096256   0.286516   0.2324062   -0.100000    0.282000    0.2295000
+41863.00  -0.095395   0.288366   0.2301356   -0.099000    0.284000    0.2271000
+41864.00  -0.094499   0.290226   0.2277697   -0.097000    0.286000    0.2246000
+41865.00  -0.093566   0.292091   0.2252259   -0.095000    0.288000    0.2223000
+41866.00  -0.092596   0.293957   0.2224869   -0.094000    0.290000    0.2200000
+41867.00  -0.091588   0.295818   0.2196042   -0.092000    0.291000    0.2177000
+41868.00  -0.090547   0.297669   0.2166747   -0.091000    0.293000    0.2154000
+41869.00  -0.089478   0.299504   0.2138025   -0.089000    0.295000    0.2131000
+41870.00  -0.088387   0.301319   0.2110689   -0.087000    0.296000    0.2108000
+41871.00  -0.087280   0.303108   0.2085187   -0.085000    0.298000    0.2085000
+41872.00  -0.086167   0.304868   0.2061633   -0.083000    0.299000    0.2062000
+41873.00  -0.085056   0.306592   0.2039890   -0.081000    0.300000    0.2039000
+41874.00  -0.083952   0.308278   0.2019641   -0.080000    0.302000    0.2016000
+41875.00  -0.082861   0.309919   0.2000425   -0.078000    0.303000    0.1993000
+41876.00  -0.081780   0.311513   0.1981661   -0.076000    0.304000    0.1970000
+41877.00  -0.080706   0.313057   0.1962715   -0.074000    0.305000    0.1947000
+41878.00  -0.079639   0.314550   0.1942984   -0.072000    0.307000    0.1924000
+41879.00  -0.078576   0.315992   0.1921991   -0.070000    0.308000    0.1901000
+41880.00  -0.077516   0.317382   0.1899451   -0.068000    0.309000    0.1877000
+41881.00  -0.076456   0.318721   0.1875310   -0.066000    0.310000    0.1854000
+41882.00  -0.075393   0.320007   0.1849750   -0.064000    0.311000    0.1830000
+41883.00  -0.074324   0.321240   0.1823177   -0.062000    0.312000    0.1807000
+41884.00  -0.073249   0.322420   0.1796175   -0.061000    0.314000    0.1783000
+41885.00  -0.072165   0.323546   0.1769433   -0.059000    0.315000    0.1759000
+41886.00  -0.071074   0.324618   0.1743623   -0.057000    0.316000    0.1735000
+41887.00  -0.069974   0.325637   0.1719236   -0.055000    0.317000    0.1712000
+41888.00  -0.068865   0.326605   0.1696410   -0.053000    0.318000    0.1688000
+41889.00  -0.067746   0.327521   0.1674796   -0.051000    0.319000    0.1664000
+41890.00  -0.066615   0.328385   0.1653574   -0.049000    0.320000    0.1639000
+41891.00  -0.065470   0.329200   0.1631654   -0.047000    0.321000    0.1615000
+41892.00  -0.064308   0.329966   0.1608038   -0.046000    0.322000    0.1590000
+41893.00  -0.063127   0.330684   0.1582205   -0.044000    0.323000    0.1566000
+41894.00  -0.061922   0.331356   0.1554320   -0.042000    0.325000    0.1541000
+41895.00  -0.060690   0.331984   0.1525183   -0.040000    0.326000    0.1516000
+41896.00  -0.059426   0.332571   0.1495917   -0.038000    0.327000    0.1491000
+41897.00  -0.058129   0.333123   0.1467587   -0.037000    0.328000    0.1467000
+41898.00  -0.056796   0.333641   0.1440916   -0.035000    0.329000    0.1442000
+41899.00  -0.055426   0.334129   0.1416190   -0.033000    0.330000    0.1417000
+41900.00  -0.054018   0.334587   0.1393332   -0.031000    0.331000    0.1392000
+41901.00  -0.052571   0.335018   0.1372021   -0.030000    0.331000    0.1368000
+41902.00  -0.051087   0.335422   0.1351788   -0.028000    0.332000    0.1343000
+41903.00  -0.049566   0.335801   0.1332063   -0.027000    0.333000    0.1319000
+41904.00  -0.048009   0.336158   0.1312213   -0.025000    0.334000    0.1294000
+41905.00  -0.046418   0.336495   0.1291610   -0.023000    0.334000    0.1269000
+41906.00  -0.044793   0.336814   0.1269711   -0.022000    0.335000    0.1244000
+41907.00  -0.043138   0.337117   0.1246142   -0.020000    0.336000    0.1219000
+41908.00  -0.041457   0.337408   0.1220762   -0.019000    0.336000    0.1194000
+41909.00  -0.039753   0.337689   0.1193688   -0.017000    0.337000    0.1169000
+41910.00  -0.038027   0.337962   0.1165303   -0.016000    0.337000    0.1144000
+41911.00  -0.036279   0.338231   0.1136211   -0.014000    0.337000    0.1118000
+41912.00  -0.034509   0.338497   0.1107146   -0.013000    0.338000    0.1093000
+41913.00  -0.032716   0.338764   0.1078820   -0.011000    0.338000    0.1067000
+41914.00  -0.030904   0.339034   0.1051753   -0.010000    0.338000    0.1042000
+41915.00  -0.029072   0.339312   0.1026111   -0.009000    0.338000    0.1016000
+41916.00  -0.027225   0.339599   0.1001622   -0.007000    0.338000    0.0990000
+41917.00  -0.025364   0.339898   0.0977587   -0.006000    0.339000    0.0965000
+41918.00  -0.023491   0.340210   0.0953036   -0.004000    0.339000    0.0939000
+41919.00  -0.021609   0.340534   0.0926991   -0.003000    0.339000    0.0913000
+41920.00  -0.019719   0.340866   0.0898766   -0.002000    0.339000    0.0887000
+41921.00  -0.017823   0.341204   0.0868220   -0.001000    0.339000    0.0860000
+41922.00  -0.015923   0.341546   0.0835842    0.000000    0.339000    0.0834000
+41923.00  -0.014024   0.341889   0.0802614    0.001000    0.339000    0.0807000
+41924.00  -0.012126   0.342230   0.0769694    0.003000    0.340000    0.0781000
+41925.00  -0.010233   0.342570   0.0738075    0.004000    0.340000    0.0754000
+41926.00  -0.008345   0.342904   0.0708351    0.005000    0.340000    0.0727000
+41927.00  -0.006462   0.343233   0.0680673    0.006000    0.340000    0.0699000
+41928.00  -0.004582   0.343554   0.0654838    0.007000    0.340000    0.0672000
+41929.00  -0.002703   0.343867   0.0630419    0.008000    0.340000    0.0645000
+41930.00  -0.000823   0.344170   0.0606870    0.010000    0.340000    0.0617000
+41931.00   0.001061   0.344464   0.0583584    0.011000    0.340000    0.0589000
+41932.00   0.002946   0.344750   0.0559943    0.013000    0.341000    0.0561000
+41933.00   0.004833   0.345026   0.0535381    0.015000    0.341000    0.0533000
+41934.00   0.006719   0.345293   0.0509461    0.017000    0.341000    0.0505000
+41935.00   0.008606   0.345551   0.0481927    0.018000    0.341000    0.0476000
+41936.00   0.010491   0.345797   0.0452758    0.020000    0.341000    0.0447000
+41937.00   0.012375   0.346029   0.0422207    0.022000    0.342000    0.0418000
+41938.00   0.014258   0.346244   0.0390798    0.023000    0.342000    0.0389000
+41939.00   0.016138   0.346440   0.0359271    0.025000    0.342000    0.0360000
+41940.00   0.018015   0.346613   0.0328428    0.027000    0.342000    0.0331000
+41941.00   0.019888   0.346762   0.0298925    0.028000    0.343000    0.0301000
+41942.00   0.021754   0.346884   0.0271064    0.030000    0.343000    0.0272000
+41943.00   0.023611   0.346978   0.0244669    0.031000    0.344000    0.0242000
+41944.00   0.025456   0.347042   0.0219114    0.033000    0.344000    0.0213000
+41945.00   0.027289   0.347074   0.0193484    0.035000    0.344000    0.0183000
+41946.00   0.029108   0.347072   0.0166814    0.036000    0.345000    0.0153000
+41947.00   0.030916   0.347036   0.0138355    0.038000    0.345000    0.0123000
+41948.00   0.032711   0.346966   0.0107781    0.039000    0.346000    0.0093000
+41949.00   0.034492   0.346860   0.0075291    0.041000    0.346000    0.0063000
+41950.00   0.036259   0.346719   0.0041565    0.042000    0.346000    0.0033000
+41951.00   0.038008   0.346543   0.0007577    0.044000    0.346000    0.0002000
+41952.00   0.039739   0.346333  -0.0025677    0.045000    0.347000   -0.0028000
+41953.00   0.041450   0.346086  -0.0057439    0.047000    0.347000   -0.0059000
+41954.00   0.043140   0.345801  -0.0087342    0.048000    0.347000   -0.0089000
+41955.00   0.044808   0.345476  -0.0115428    0.049000    0.347000   -0.0120000
+41956.00   0.046453   0.345111  -0.0142048    0.051000    0.347000   -0.0151000
+41957.00   0.048076   0.344705  -0.0167739    0.052000    0.348000   -0.0181000
+41958.00   0.049673   0.344259  -0.0193120    0.054000    0.348000   -0.0212000
+41959.00   0.051242   0.343773  -0.0218818    0.055000    0.348000   -0.0243000
+41960.00   0.052777   0.343248  -0.0245414    0.057000    0.348000   -0.0274000
+41961.00   0.054276   0.342684  -0.0273383    0.058000    0.348000   -0.0305000
+41962.00   0.055736   0.342080  -0.0303046    0.060000    0.347000   -0.0336000
+41963.00   0.057156   0.341436  -0.0334515    0.061000    0.347000   -0.0367000
+41964.00   0.058539   0.340754  -0.0367661    0.063000    0.347000   -0.0398000
+41965.00   0.059888   0.340035  -0.0402090    0.065000    0.347000   -0.0429000
+41966.00   0.061203   0.339282  -0.0437149    0.066000    0.347000   -0.0460000
+41967.00   0.062488   0.338497  -0.0472011    0.068000    0.346000   -0.0492000
+41968.00   0.063742   0.337684  -0.0505867    0.069000    0.346000   -0.0523000
+41969.00   0.064969   0.336845  -0.0538171    0.071000    0.346000   -0.0554000
+41970.00   0.066169   0.335980  -0.0568853    0.072000    0.346000   -0.0586000
+41971.00   0.067343   0.335085  -0.0598382    0.074000    0.345000   -0.0618000
+41972.00   0.068487   0.334159  -0.0627630    0.075000    0.345000   -0.0650000
+41973.00   0.069599   0.333202  -0.0657581    0.077000    0.344000   -0.0682000
+41974.00   0.070676   0.332213  -0.0689022    0.078000    0.344000   -0.0714000
+41975.00   0.071714   0.331195  -0.0722334    0.079000    0.343000   -0.0746000
+41976.00   0.072709   0.330147  -0.0757409    0.081000    0.343000   -0.0779000
+41977.00   0.073660   0.329075  -0.0793711    0.082000    0.342000   -0.0811000
+41978.00   0.074564   0.327981  -0.0830434    0.084000    0.342000   -0.0844000
+41979.00   0.075421   0.326871  -0.0866712    0.085000    0.341000   -0.0876000
+41980.00   0.076229   0.325751  -0.0901797    0.086000    0.340000   -0.0909000
+41981.00   0.076990   0.324625  -0.0935217    0.088000    0.339000   -0.0941000
+41982.00   0.077706   0.323499  -0.0966847    0.089000    0.339000   -0.0974000
+41983.00   0.078381   0.322377  -0.0996889    0.091000    0.338000   -0.1006000
+41984.00   0.079016   0.321265  -0.1025792    0.092000    0.337000   -0.1039000
+41985.00   0.079614   0.320168  -0.1054139    0.093000    0.336000   -0.1072000
+41986.00   0.080175   0.319086  -0.1082551    0.095000    0.335000   -0.1105000
+41987.00   0.080703   0.318022  -0.1111607    0.096000    0.335000   -0.1139000
+41988.00   0.081201   0.316975  -0.1141787    0.098000    0.334000   -0.1172000
+41989.00   0.081671   0.315947  -0.1173433    0.099000    0.333000   -0.1205000
+41990.00   0.082118   0.314936  -0.1206712    0.100000    0.332000   -0.1238000
+41991.00   0.082543   0.313944  -0.1241596    0.101000    0.331000   -0.1271000
+41992.00   0.082951   0.312970  -0.1277842    0.101000    0.330000   -0.1305000
+41993.00   0.083347   0.312016  -0.1314973    0.102000    0.329000   -0.1338000
+41994.00   0.083732   0.311082  -0.1352296    0.103000    0.328000   -0.1371000
+41995.00   0.084109   0.310169  -0.1389005    0.104000    0.326000   -0.1404000
+41996.00   0.084479   0.309275  -0.1424400    0.105000    0.325000   -0.1437000
+41997.00   0.084843   0.308399  -0.1458132    0.105000    0.324000   -0.1470000
+41998.00   0.085205   0.307541  -0.1490397    0.106000    0.323000   -0.1503000
+41999.00   0.085567   0.306698  -0.1521912    0.107000    0.322000   -0.1536000
+42000.00   0.085934   0.305868  -0.1553673    0.108000    0.321000   -0.1569000
+42001.00   0.086310   0.305050  -0.1586579    0.108000    0.320000   -0.1603000
+42002.00   0.086696   0.304242  -0.1621106    0.109000    0.318000   -0.1636000
+42003.00   0.087092   0.303442  -0.1657170    0.109000    0.317000   -0.1670000
+42004.00   0.087500   0.302650  -0.1694219    0.110000    0.316000   -0.1703000
+42005.00   0.087923   0.301867  -0.1731446    0.110000    0.315000   -0.1736000
+42006.00   0.088360   0.301092  -0.1768022    0.111000    0.314000   -0.1768000
+42007.00   0.088813   0.300322  -0.1803275    0.111000    0.312000   -0.1801000
+42008.00   0.089282   0.299559  -0.1836772    0.112000    0.311000   -0.1833000
+42009.00   0.089767   0.298800  -0.1868358    0.112000    0.310000   -0.1866000
+42010.00   0.090270   0.298044  -0.1898150    0.113000    0.309000   -0.1898000
+42011.00   0.090789   0.297288  -0.1926504    0.113000    0.308000   -0.1930000
+42012.00   0.091322   0.296531  -0.1953941    0.114000    0.307000   -0.1963000
+42013.00   0.091866   0.295769  -0.1981060    0.114000    0.306000   -0.1995000
+42014.00   0.092419   0.295002  -0.2008443    0.115000    0.305000   -0.2027000
+42015.00   0.092978   0.294225  -0.2036580    0.116000    0.303000   -0.2059000
+42016.00   0.093541   0.293436  -0.2065818    0.116000    0.302000   -0.2090000
+42017.00   0.094106   0.292631  -0.2096332    0.117000    0.301000   -0.2122000
+42018.00   0.094671   0.291809  -0.2128122    0.117000    0.300000   -0.2153000
+42019.00   0.095233   0.290966  -0.2161014    0.118000    0.299000   -0.2185000
+42020.00   0.095789   0.290100  -0.2194657    0.119000    0.298000   -0.2217000
+42021.00   0.096336   0.289208  -0.2228531    0.120000    0.296000   -0.2248000
+42022.00   0.096871   0.288288  -0.2261984    0.120000    0.295000   -0.2280000
+42023.00   0.097393   0.287336  -0.2294359    0.121000    0.293000   -0.2311000
+42024.00   0.097902   0.286351  -0.2325201    0.122000    0.292000   -0.2343000
+42025.00   0.098396   0.285330  -0.2354485    0.123000    0.291000   -0.2374000
+42026.00   0.098876   0.284272  -0.2382734    0.124000    0.289000   -0.2405000
+42027.00   0.099341   0.283177  -0.2410897    0.124000    0.288000   -0.2436000
+42028.00   0.099789   0.282043  -0.2440007    0.125000    0.286000   -0.2467000
+42029.00   0.100218   0.280870  -0.2470769    0.126000    0.285000   -0.2498000
+42030.00   0.100626   0.279656  -0.2503280    0.127000    0.283000   -0.2528000
+42031.00   0.101013   0.278397  -0.2537002    0.127000    0.282000   -0.2558000
+42032.00   0.101377   0.277095  -0.2570999    0.128000    0.280000   -0.2589000
+42033.00   0.101720   0.275751  -0.2604279    0.128000    0.279000   -0.2619000
+42034.00   0.102043   0.274366  -0.2636073    0.129000    0.277000   -0.2649000
+42035.00   0.102347   0.272944  -0.2665943    0.129000    0.275000   -0.2678000
+42036.00   0.102630   0.271487  -0.2693777    0.130000    0.274000   -0.2708000
+42037.00   0.102890   0.270000  -0.2719721    0.130000    0.272000   -0.2737000
+42038.00   0.103124   0.268487  -0.2744117    0.131000    0.271000   -0.2767000
+42039.00   0.103328   0.266952  -0.2767452    0.131000    0.269000   -0.2796000
+42040.00   0.103502   0.265400  -0.2790302    0.131000    0.267000   -0.2823000
+42041.00   0.103641   0.263832  -0.2813262    0.131000    0.265000   -0.2850000
+42042.00   0.103746   0.262251  -0.2836854    0.131000    0.263000   -0.2876000
+42043.00   0.103816   0.260657  -0.2861463    0.131000    0.261000   -0.2903000
+42044.00   0.103849   0.259051  -0.2887288    0.131000    0.260000   -0.2930000
+42045.00   0.103845   0.257437  -0.2914337    0.131000    0.258000   -0.2952000
+42046.00   0.103805   0.255813  -0.2942442    0.131000    0.256000   -0.2974000
+42047.00   0.103728   0.254183  -0.2971285    0.131000    0.254000   -0.2997000
+42048.00   0.103613   0.252548   0.6999577    0.131000    0.252000    0.6981000
+42049.00   0.103459   0.250912   0.6970678    0.131000    0.250000    0.6959000
+42050.00   0.103264   0.249280   0.6942575    0.130000    0.248000    0.6934000
+42051.00   0.103028   0.247655   0.6915715    0.129000    0.246000    0.6909000
+42052.00   0.102751   0.246038   0.6890254    0.129000    0.243000    0.6885000
+42053.00   0.102434   0.244432   0.6865897    0.128000    0.241000    0.6860000
+42054.00   0.102077   0.242835   0.6841878    0.127000    0.239000    0.6835000
+42055.00   0.101678   0.241249   0.6817150    0.126000    0.237000    0.6807000
+42056.00   0.101236   0.239674   0.6790766    0.125000    0.235000    0.6778000
+42057.00   0.100750   0.238110   0.6762273    0.125000    0.232000    0.6750000
+42058.00   0.100222   0.236557   0.6731927    0.124000    0.230000    0.6721000
+42059.00   0.099653   0.235016   0.6700606    0.123000    0.228000    0.6693000
+42060.00   0.099045   0.233489   0.6669475    0.122000    0.226000    0.6666000
+42061.00   0.098399   0.231975   0.6639589    0.120000    0.224000    0.6639000
+42062.00   0.097719   0.230476   0.6611611    0.119000    0.222000    0.6611000
+42063.00   0.097006   0.228990   0.6585751    0.118000    0.220000    0.6584000
+42064.00   0.096261   0.227517   0.6561854    0.117000    0.218000    0.6557000
+42065.00   0.095487   0.226057   0.6539538    0.115000    0.216000    0.6534000
+42066.00   0.094684   0.224609   0.6518298    0.114000    0.214000    0.6511000
+42067.00   0.093852   0.223173   0.6497560    0.113000    0.212000    0.6489000
+42068.00   0.092995   0.221752   0.6476724    0.111000    0.210000    0.6466000
+42069.00   0.092117   0.220345   0.6455229    0.110000    0.208000    0.6443000
+42070.00   0.091222   0.218956   0.6432632    0.109000    0.207000    0.6420000
+42071.00   0.090317   0.217587   0.6408669    0.108000    0.205000    0.6397000
+42072.00   0.089404   0.216242   0.6383288    0.106000    0.204000    0.6375000
+42073.00   0.088485   0.214922   0.6356643    0.105000    0.202000    0.6352000
+42074.00   0.087567   0.213632   0.6329062    0.104000    0.201000    0.6329000
+42075.00   0.086653   0.212376   0.6301000    0.103000    0.200000    0.6302000
+42076.00   0.085750   0.211155   0.6272985    0.102000    0.198000    0.6276000
+42077.00   0.084863   0.209973   0.6245540    0.100000    0.197000    0.6249000
+42078.00   0.083998   0.208833   0.6219084    0.099000    0.195000    0.6223000
+42079.00   0.083160   0.207738   0.6193803    0.098000    0.194000    0.6196000
+42080.00   0.082351   0.206691   0.6169531    0.097000    0.193000    0.6167000
+42081.00   0.081573   0.205695   0.6145682    0.096000    0.193000    0.6139000
+42082.00   0.080822   0.204752   0.6121330    0.095000    0.192000    0.6110000
+42083.00   0.080096   0.203862   0.6095460    0.094000    0.192000    0.6082000
+42084.00   0.079390   0.203027   0.6067332    0.093000    0.191000    0.6053000
+42085.00   0.078702   0.202247   0.6036800    0.092000    0.190000    0.6024000
+42086.00   0.078027   0.201524   0.6004433    0.091000    0.190000    0.5996000
+42087.00   0.077360   0.200856   0.5971340    0.090000    0.189000    0.5967000
+42088.00   0.076698   0.200241   0.5938779    0.089000    0.189000    0.5939000
+42089.00   0.076036   0.199679   0.5907764    0.088000    0.188000    0.5910000
+42090.00   0.075371   0.199166   0.5878817    0.087000    0.188000    0.5883000
+42091.00   0.074696   0.198701   0.5851957    0.086000    0.187000    0.5856000
+42092.00   0.074011   0.198281   0.5826839    0.086000    0.187000    0.5830000
+42093.00   0.073312   0.197903   0.5802936    0.085000    0.186000    0.5803000
+42094.00   0.072601   0.197565   0.5779652    0.084000    0.186000    0.5776000
+42095.00   0.071874   0.197261   0.5756383    0.083000    0.186000    0.5750000
+42096.00   0.071131   0.196990   0.5732552    0.082000    0.185000    0.5724000
+42097.00   0.070373   0.196746   0.5707666    0.082000    0.185000    0.5697000
+42098.00   0.069596   0.196527   0.5681383    0.081000    0.184000    0.5671000
+42099.00   0.068798   0.196328   0.5653568    0.080000    0.184000    0.5645000
+42100.00   0.067976   0.196145   0.5624308    0.079000    0.184000    0.5617000
+42101.00   0.067127   0.195974   0.5593901    0.078000    0.183000    0.5589000
+42102.00   0.066248   0.195811   0.5562812    0.077000    0.183000    0.5562000
+42103.00   0.065336   0.195653   0.5531613    0.076000    0.182000    0.5534000
+42104.00   0.064391   0.195500   0.5500884    0.076000    0.182000    0.5506000
+42105.00   0.063408   0.195349   0.5471104    0.075000    0.182000    0.5476000
+42106.00   0.062390   0.195202   0.5442519    0.074000    0.181000    0.5446000
+42107.00   0.061338   0.195056   0.5415040    0.073000    0.181000    0.5416000
+42108.00   0.060251   0.194913   0.5388205    0.072000    0.180000    0.5386000
+42109.00   0.059132   0.194771   0.5361227    0.071000    0.180000    0.5356000
+42110.00   0.057982   0.194630   0.5333157    0.070000    0.180000    0.5325000
+42111.00   0.056803   0.194488   0.5303155    0.068000    0.180000    0.5293000
+42112.00   0.055601   0.194343   0.5270781    0.067000    0.180000    0.5262000
+42113.00   0.054379   0.194194   0.5236205    0.066000    0.180000    0.5230000
+42114.00   0.053147   0.194042   0.5200213    0.065000    0.180000    0.5199000
+42115.00   0.051913   0.193888   0.5163977    0.063000    0.179000    0.5166000
+42116.00   0.050682   0.193733   0.5128685    0.062000    0.179000    0.5134000
+42117.00   0.049458   0.193578   0.5095191    0.061000    0.179000    0.5101000
+42118.00   0.048242   0.193426   0.5063829    0.059000    0.179000    0.5069000
+42119.00   0.047038   0.193276   0.5034451    0.058000    0.179000    0.5036000
+42120.00   0.045847   0.193131   0.5006586    0.056000    0.179000    0.5004000
+42121.00   0.044672   0.192991   0.4979625    0.055000    0.179000    0.4972000
+42122.00   0.043517   0.192859   0.4952943    0.053000    0.180000    0.4940000
+42123.00   0.042385   0.192733   0.4925950    0.052000    0.180000    0.4908000
+42124.00   0.041274   0.192617   0.4898130    0.050000    0.180000    0.4876000
+42125.00   0.040185   0.192508   0.4869085    0.048000    0.180000    0.4846000
+42126.00   0.039119   0.192409   0.4838591    0.047000    0.180000    0.4815000
+42127.00   0.038076   0.192317   0.4806634    0.045000    0.181000    0.4785000
+42128.00   0.037057   0.192231   0.4773418    0.044000    0.181000    0.4754000
+42129.00   0.036067   0.192146   0.4739344    0.042000    0.181000    0.4724000
+42130.00   0.035104   0.192061   0.4704966    0.040000    0.182000    0.4695000
+42131.00   0.034171   0.191977   0.4670908    0.039000    0.182000    0.4666000
+42132.00   0.033267   0.191893   0.4637744    0.037000    0.183000    0.4636000
+42133.00   0.032395   0.191811   0.4605841    0.036000    0.183000    0.4607000
+42134.00   0.031552   0.191732   0.4575226    0.034000    0.184000    0.4578000
+42135.00   0.030738   0.191656   0.4545535    0.032000    0.184000    0.4549000
+42136.00   0.029953   0.191584   0.4516067    0.031000    0.185000    0.4520000
+42137.00   0.029197   0.191517   0.4485951    0.029000    0.185000    0.4491000
+42138.00   0.028470   0.191456   0.4454372    0.028000    0.186000    0.4462000
+42139.00   0.027772   0.191399   0.4420806    0.026000    0.186000    0.4433000
+42140.00   0.027104   0.191349   0.4385193    0.024000    0.187000    0.4404000
+42141.00   0.026463   0.191303   0.4347997    0.023000    0.187000    0.4375000
+42142.00   0.025851   0.191261   0.4310112    0.021000    0.188000    0.4347000
+42143.00   0.025266   0.191223   0.4272623    0.020000    0.188000    0.4318000
+42144.00   0.024707   0.191187   0.4236496    0.018000    0.189000    0.4289000
+42145.00   0.024174   0.191153   0.4202328    0.016000    0.190000    0.4259000
+42146.00   0.023660   0.191121   0.4170238    0.015000    0.190000    0.4229000
+42147.00   0.023163   0.191091   0.4139931    0.013000    0.191000    0.4199000
+42148.00   0.022678   0.191064   0.4110859    0.012000    0.191000    0.4169000
+42149.00   0.022199   0.191040   0.4082387    0.010000    0.192000    0.4139000
+42150.00   0.021724   0.191017   0.4053908    0.009000    0.193000    0.4106000
+42151.00   0.021250   0.190994   0.4024893    0.008000    0.193000    0.4074000
+42152.00   0.020770   0.190971   0.3994923    0.006000    0.194000    0.4041000
+42153.00   0.020280   0.190949   0.3963728    0.005000    0.194000    0.4009000
+42154.00   0.019776   0.190925   0.3931219    0.004000    0.195000    0.3976000
+42155.00   0.019254   0.190901   0.3897500    0.003000    0.196000    0.3941000
+42156.00   0.018715   0.190875   0.3862870    0.002000    0.196000    0.3906000
+42157.00   0.018156   0.190850   0.3827794    0.000000    0.197000    0.3872000
+42158.00   0.017577   0.190827   0.3792856   -0.001000    0.197000    0.3837000
+42159.00   0.016976   0.190808   0.3758664   -0.002000    0.198000    0.3802000
+42160.00   0.016356   0.190795   0.3725704   -0.003000    0.198000    0.3767000
+42161.00   0.015719   0.190790   0.3694168   -0.004000    0.199000    0.3732000
+42162.00   0.015068   0.190796   0.3663835   -0.005000    0.199000    0.3696000
+42163.00   0.014407   0.190812   0.3634087   -0.006000    0.200000    0.3661000
+42164.00   0.013735   0.190839   0.3604073   -0.007000    0.200000    0.3626000
+42165.00   0.013053   0.190877   0.3572975   -0.007000    0.200000    0.3592000
+42166.00   0.012362   0.190927   0.3540256   -0.008000    0.201000    0.3558000
+42167.00   0.011662   0.190986   0.3505813   -0.009000    0.201000    0.3524000
+42168.00   0.010954   0.191053   0.3470003   -0.010000    0.202000    0.3490000
+42169.00   0.010240   0.191129   0.3433539   -0.011000    0.202000    0.3456000
+42170.00   0.009519   0.191213   0.3397321   -0.012000    0.202000    0.3424000
+42171.00   0.008791   0.191305   0.3362223   -0.013000    0.203000    0.3392000
+42172.00   0.008058   0.191406   0.3328887   -0.014000    0.203000    0.3359000
+42173.00   0.007323   0.191517   0.3297594   -0.015000    0.203000    0.3327000
+42174.00   0.006592   0.191636   0.3268237   -0.016000    0.204000    0.3295000
+42175.00   0.005869   0.191765   0.3240393   -0.016000    0.204000    0.3264000
+42176.00   0.005159   0.191901   0.3213473   -0.017000    0.204000    0.3233000
+42177.00   0.004465   0.192046   0.3186855   -0.018000    0.204000    0.3201000
+42178.00   0.003788   0.192197   0.3159986   -0.019000    0.205000    0.3170000
+42179.00   0.003132   0.192354   0.3132432   -0.020000    0.205000    0.3139000
+42180.00   0.002499   0.192516   0.3103906   -0.021000    0.205000    0.3109000
+42181.00   0.001889   0.192683   0.3074284   -0.021000    0.206000    0.3079000
+42182.00   0.001303   0.192856   0.3043618   -0.022000    0.206000    0.3050000
+42183.00   0.000740   0.193037   0.3012128   -0.022000    0.206000    0.3020000
+42184.00   0.000202   0.193225   0.2980181   -0.023000    0.207000    0.2990000
+42185.00  -0.000310   0.193423   0.2948268   -0.023000    0.207000    0.2960000
+42186.00  -0.000794   0.193631   0.2916945   -0.024000    0.207000    0.2930000
+42187.00  -0.001250   0.193850   0.2886731   -0.024000    0.207000    0.2900000
+42188.00  -0.001679   0.194079   0.2857950   -0.025000    0.208000    0.2870000
+42189.00  -0.002080   0.194321   0.2830565   -0.025000    0.208000    0.2840000
+42190.00  -0.002456   0.194577   0.2804098   -0.025000    0.208000    0.2810000
+42191.00  -0.002805   0.194845   0.2777733   -0.026000    0.209000    0.2779000
+42192.00  -0.003130   0.195128   0.2750574   -0.026000    0.209000    0.2749000
+42193.00  -0.003430   0.195427   0.2721975   -0.026000    0.209000    0.2718000
+42194.00  -0.003708   0.195744   0.2691772   -0.027000    0.210000    0.2688000
+42195.00  -0.003966   0.196082   0.2660328   -0.027000    0.210000    0.2659000
+42196.00  -0.004202   0.196445   0.2628389   -0.027000    0.210000    0.2630000
+42197.00  -0.004414   0.196839   0.2596849   -0.027000    0.210000    0.2600000
+42198.00  -0.004600   0.197266   0.2566525   -0.028000    0.211000    0.2571000
+42199.00  -0.004756   0.197730   0.2538000   -0.028000    0.211000    0.2542000
+42200.00  -0.004877   0.198235   0.2511548   -0.028000    0.211000    0.2515000
+42201.00  -0.004960   0.198781   0.2487125   -0.027000    0.211000    0.2488000
+42202.00  -0.005000   0.199370   0.2464406   -0.027000    0.212000    0.2462000
+42203.00  -0.004992   0.200001   0.2442871   -0.027000    0.212000    0.2435000
+42204.00  -0.004932   0.200676   0.2421917   -0.027000    0.212000    0.2408000
+42205.00  -0.004816   0.201393   0.2400963   -0.026000    0.212000    0.2384000
+42206.00  -0.004643   0.202153   0.2379537   -0.026000    0.212000    0.2359000
+42207.00  -0.004410   0.202956   0.2357321   -0.026000    0.213000    0.2335000
+42208.00  -0.004117   0.203801   0.2334170   -0.025000    0.213000    0.2310000
+42209.00  -0.003764   0.204685   0.2310113   -0.025000    0.213000    0.2286000
+42210.00  -0.003348   0.205605   0.2285338   -0.024000    0.213000    0.2264000
+42211.00  -0.002866   0.206557   0.2260158   -0.024000    0.213000    0.2242000
+42212.00  -0.002321   0.207536   0.2234977   -0.023000    0.214000    0.2220000
+42213.00  -0.001713   0.208538   0.2210256   -0.023000    0.214000    0.2198000
+42214.00  -0.001045   0.209555   0.2186454   -0.022000    0.214000    0.2176000
+42215.00  -0.000315   0.210579   0.2163925   -0.021000    0.214000    0.2155000
+42216.00   0.000476   0.211604   0.2142759   -0.021000    0.214000    0.2135000
+42217.00   0.001331   0.212624   0.2122651   -0.020000    0.215000    0.2114000
+42218.00   0.002251   0.213636   0.2102885   -0.020000    0.215000    0.2094000
+42219.00   0.003234   0.214635   0.2082511   -0.019000    0.215000    0.2073000
+42220.00   0.004277   0.215616   0.2060678   -0.018000    0.215000    0.2053000
+42221.00   0.005373   0.216573   0.2036984   -0.017000    0.215000    0.2032000
+42222.00   0.006518   0.217503   0.2011655   -0.016000    0.215000    0.2012000
+42223.00   0.007703   0.218405   0.1985464   -0.015000    0.215000    0.1991000
+42224.00   0.008924   0.219276   0.1959452   -0.014000    0.216000    0.1971000
+42225.00   0.010171   0.220115   0.1934584   -0.013000    0.216000    0.1951000
+42226.00   0.011437   0.220919   0.1911510   -0.012000    0.216000    0.1930000
+42227.00   0.012711   0.221686   0.1890489   -0.011000    0.216000    0.1910000
+42228.00   0.013984   0.222416   0.1871428   -0.010000    0.216000    0.1889000
+42229.00   0.015250   0.223106   0.1853992   -0.009000    0.216000    0.1869000
+42230.00   0.016503   0.223758   0.1837679   -0.008000    0.216000    0.1848000
+42231.00   0.017736   0.224372   0.1821913   -0.007000    0.216000    0.1827000
+42232.00   0.018940   0.224947   0.1806110   -0.006000    0.216000    0.1805000
+42233.00   0.020113   0.225484   0.1789761   -0.005000    0.216000    0.1784000
+42234.00   0.021252   0.225982   0.1772496   -0.004000    0.216000    0.1763000
+42235.00   0.022358   0.226444   0.1754130   -0.002000    0.216000    0.1742000
+42236.00   0.023430   0.226867   0.1734666   -0.001000    0.216000    0.1721000
+42237.00   0.024465   0.227255   0.1714277    0.000000    0.216000    0.1699000
+42238.00   0.025459   0.227607   0.1693264    0.001000    0.216000    0.1678000
+42239.00   0.026407   0.227925   0.1672016    0.002000    0.216000    0.1657000
+42240.00   0.027305   0.228211   0.1650959    0.003000    0.216000    0.1636000
+42241.00   0.028151   0.228464   0.1630508    0.004000    0.216000    0.1616000
+42242.00   0.028942   0.228683   0.1610997    0.005000    0.216000    0.1595000
+42243.00   0.029674   0.228869   0.1592580    0.006000    0.216000    0.1575000
+42244.00   0.030340   0.229023   0.1575102    0.007000    0.217000    0.1554000
+42245.00   0.030935   0.229145   0.1558022    0.007000    0.217000    0.1534000
+42246.00   0.031459   0.229236   0.1540466    0.008000    0.217000    0.1515000
+42247.00   0.031910   0.229297   0.1521472    0.009000    0.217000    0.1495000
+42248.00   0.032289   0.229326   0.1500348    0.010000    0.217000    0.1476000
+42249.00   0.032598   0.229326   0.1476996    0.011000    0.217000    0.1456000
+42250.00   0.032838   0.229296   0.1452006    0.012000    0.217000    0.1437000
+42251.00   0.033012   0.229237   0.1426478    0.012000    0.217000    0.1418000
+42252.00   0.033124   0.229150   0.1401629    0.013000    0.218000    0.1399000
+42253.00   0.033179   0.229032   0.1378411    0.013000    0.218000    0.1380000
+42254.00   0.033183   0.228884   0.1357282    0.014000    0.218000    0.1361000
+42255.00   0.033140   0.228705   0.1338212    0.015000    0.218000    0.1342000
+42256.00   0.033052   0.228495   0.1320826    0.015000    0.218000    0.1323000
+42257.00   0.032919   0.228251   0.1304569    0.016000    0.219000    0.1305000
+42258.00   0.032742   0.227975   0.1288833    0.016000    0.219000    0.1286000
+42259.00   0.032525   0.227666   0.1273020    0.017000    0.219000    0.1267000
+42260.00   0.032268   0.227323   0.1256589    0.017000    0.219000    0.1247000
+42261.00   0.031975   0.226948   0.1239113    0.017000    0.219000    0.1227000
+42262.00   0.031645   0.226540   0.1220332    0.017000    0.220000    0.1206000
+42263.00   0.031279   0.226103   0.1200186    0.017000    0.220000    0.1186000
+42264.00   0.030879   0.225640   0.1178811    0.017000    0.220000    0.1166000
+42265.00   0.030451   0.225155   0.1156503    0.017000    0.220000    0.1143000
+42266.00   0.029999   0.224651   0.1133655    0.017000    0.220000    0.1121000
+42267.00   0.029528   0.224133   0.1110705    0.017000    0.221000    0.1098000
+42268.00   0.029038   0.223605   0.1088073    0.017000    0.221000    0.1076000
+42269.00   0.028531   0.223069   0.1066102    0.017000    0.221000    0.1053000
+42270.00   0.028009   0.222528   0.1044981    0.017000    0.221000    0.1029000
+42271.00   0.027475   0.221983   0.1024651    0.018000    0.220000    0.1005000
+42272.00   0.026931   0.221433   0.1004733    0.018000    0.220000    0.0980000
+42273.00   0.026380   0.220880   0.0984520    0.019000    0.220000    0.0956000
+42274.00   0.025824   0.220324   0.0963103    0.019000    0.220000    0.0932000
+42275.00   0.025264   0.219770   0.0939641    0.019000    0.219000    0.0908000
+42276.00   0.024699   0.219221   0.0913700    0.020000    0.219000    0.0884000
+42277.00   0.024131   0.218679   0.0885501    0.020000    0.219000    0.0860000
+42278.00   0.023558   0.218150   0.0855929    0.021000    0.218000    0.0836000
+42279.00   0.022981   0.217635   0.0826272    0.021000    0.218000    0.0812000
+42280.00   0.022400   0.217136   0.0797792    0.021000    0.218000    0.0789000
+42281.00   0.021818   0.216657   0.0771343    0.021000    0.218000    0.0766000
+42282.00   0.021237   0.216199   0.0747195    0.020000    0.218000    0.0743000
+42283.00   0.020664   0.215762   0.0725103    0.020000    0.218000    0.0720000
+42284.00   0.020105   0.215347   0.0704511    0.020000    0.218000    0.0697000
+42285.00   0.019567   0.214953   0.0684765    0.020000    0.218000    0.0675000
+42286.00   0.019055   0.214582   0.0665239    0.020000    0.218000    0.0653000
+42287.00   0.018573   0.214234   0.0645387    0.019000    0.218000    0.0632000
+42288.00   0.018120   0.213910   0.0624767    0.019000    0.218000    0.0610000
+42289.00   0.017700   0.213614   0.0603081    0.019000    0.218000    0.0588000
+42290.00   0.017314   0.213344   0.0580213    0.019000    0.218000    0.0566000
+42291.00   0.016963   0.213104   0.0556227    0.019000    0.218000    0.0543000
+42292.00   0.016648   0.212894   0.0531363    0.018000    0.218000    0.0521000
+42293.00   0.016370   0.212717   0.0505988    0.018000    0.218000    0.0498000
+42294.00   0.016129   0.212577   0.0480536    0.018000    0.218000    0.0476000
+42295.00   0.015927   0.212477   0.0455436    0.018000    0.218000    0.0452000
+42296.00   0.015762   0.212418   0.0431045    0.018000    0.218000    0.0428000
+42297.00   0.015632   0.212401   0.0407563    0.018000    0.218000    0.0403000
+42298.00   0.015532   0.212427   0.0384965    0.018000    0.218000    0.0379000
+42299.00   0.015456   0.212495   0.0362936    0.018000    0.218000    0.0355000
+42300.00   0.015400   0.212606   0.0340879    0.018000    0.218000    0.0330000
+42301.00   0.015358   0.212761   0.0317988    0.018000    0.218000    0.0304000
+42302.00   0.015324   0.212960   0.0293420    0.019000    0.218000    0.0279000
+42303.00   0.015293   0.213203   0.0266552    0.019000    0.218000    0.0253000
+42304.00   0.015256   0.213488   0.0237243    0.019000    0.218000    0.0228000
+42305.00   0.015206   0.213815   0.0205976    0.019000    0.218000    0.0201000
+42306.00   0.015133   0.214184   0.0173782    0.019000    0.218000    0.0175000
+42307.00   0.015032   0.214591   0.0141941    0.020000    0.219000    0.0148000
+42308.00   0.014897   0.215036   0.0111579    0.020000    0.219000    0.0122000
+42309.00   0.014725   0.215514   0.0083342    0.020000    0.219000    0.0095000
+42310.00   0.014510   0.216019   0.0057286    0.020000    0.219000    0.0068000
+42311.00   0.014246   0.216544   0.0032992    0.020000    0.220000    0.0041000
+42312.00   0.013932   0.217082   0.0009794    0.019000    0.220000    0.0013000
+42313.00   0.013565   0.217628  -0.0013001    0.019000    0.221000   -0.0014000
+42314.00   0.013142   0.218176  -0.0036001    0.019000    0.221000   -0.0041000
+42315.00   0.012664   0.218720  -0.0059688    0.019000    0.222000   -0.0068000
+42316.00   0.012129   0.219255  -0.0084405    0.019000    0.222000   -0.0095000
+42317.00   0.011540   0.219774  -0.0110335    0.018000    0.223000   -0.0122000
+42318.00   0.010901   0.220274  -0.0137479    0.018000    0.223000   -0.0149000
+42319.00   0.010218   0.220751  -0.0165659    0.018000    0.224000   -0.0176000
+42320.00   0.009497   0.221202  -0.0194541    0.018000    0.225000   -0.0203000
+42321.00   0.008739   0.221628  -0.0223698    0.018000    0.225000   -0.0230000
+42322.00   0.007946   0.222027  -0.0252664    0.017000    0.226000   -0.0258000
+42323.00   0.007119   0.222401  -0.0281018    0.017000    0.226000   -0.0285000
+42324.00   0.006262   0.222753  -0.0308468    0.017000    0.227000   -0.0312000
+42325.00   0.005380   0.223082  -0.0334946    0.016000    0.228000   -0.0341000
+42326.00   0.004477   0.223392  -0.0360675    0.016000    0.229000   -0.0370000
+42327.00   0.003560   0.223685  -0.0386168    0.015000    0.230000   -0.0398000
+42328.00   0.002633   0.223963  -0.0412151    0.015000    0.231000   -0.0427000
+42329.00   0.001704   0.224230  -0.0439406    0.014000    0.232000   -0.0456000
+42330.00   0.000778   0.224491  -0.0468567    0.013000    0.233000   -0.0487000
+42331.00  -0.000138   0.224747  -0.0499919    0.012000    0.234000   -0.0518000
+42332.00  -0.001038   0.225001  -0.0533268    0.012000    0.236000   -0.0548000
+42333.00  -0.001917   0.225253  -0.0567922    0.011000    0.237000   -0.0579000
+42334.00  -0.002775   0.225504  -0.0602843    0.010000    0.238000   -0.0610000
+42335.00  -0.003611   0.225755  -0.0636919    0.009000    0.239000   -0.0641000
+42336.00  -0.004427   0.226006  -0.0669295    0.008000    0.240000   -0.0673000
+42337.00  -0.005222   0.226259  -0.0699599    0.007000    0.242000   -0.0704000
+42338.00  -0.005998   0.226515  -0.0727978    0.006000    0.243000   -0.0736000
+42339.00  -0.006755   0.226777  -0.0754965    0.005000    0.244000   -0.0767000
+42340.00  -0.007498   0.227044  -0.0781253    0.004000    0.245000   -0.0798000
+42341.00  -0.008231   0.227318  -0.0807508    0.003000    0.246000   -0.0830000
+42342.00  -0.008959   0.227600  -0.0834263    0.002000    0.247000   -0.0861000
+42343.00  -0.009685   0.227891  -0.0861902    0.001000    0.248000   -0.0893000
+42344.00  -0.010412   0.228192  -0.0890648    0.000000    0.249000   -0.0924000
+42345.00  -0.011141   0.228506  -0.0920563   -0.001000    0.250000   -0.0955000
+42346.00  -0.011873   0.228834  -0.0951537   -0.002000    0.251000   -0.0986000
+42347.00  -0.012609   0.229178  -0.0983305   -0.003000    0.252000   -0.1017000
+42348.00  -0.013350   0.229538  -0.1015481   -0.004000    0.253000   -0.1048000
+42349.00  -0.014093   0.229916  -0.1047621   -0.005000    0.254000   -0.1079000
+42350.00  -0.014838   0.230312  -0.1079286   -0.006000    0.255000   -0.1110000
+42351.00  -0.015582   0.230727  -0.1110115   -0.007000    0.256000   -0.1140000
+42352.00  -0.016326   0.231161  -0.1139930   -0.008000    0.256000   -0.1171000
+42353.00  -0.017073   0.231616  -0.1168828   -0.009000    0.257000   -0.1201000
+42354.00  -0.017822   0.232090  -0.1197222   -0.010000    0.258000   -0.1232000
+42355.00  -0.018574   0.232584  -0.1225786   -0.011000    0.259000   -0.1262000
+42356.00  -0.019330   0.233097  -0.1255277   -0.012000    0.259000   -0.1293000
+42357.00  -0.020086   0.233628  -0.1286323   -0.012000    0.260000   -0.1323000
+42358.00  -0.020843   0.234176  -0.1319226   -0.013000    0.260000   -0.1354000
+42359.00  -0.021598   0.234741  -0.1353865   -0.014000    0.261000   -0.1384000
+42360.00  -0.022348   0.235320  -0.1389706   -0.015000    0.261000   -0.1415000
+42361.00  -0.023091   0.235914  -0.1425916   -0.015000    0.262000   -0.1445000
+42362.00  -0.023823   0.236519  -0.1461556   -0.016000    0.262000   -0.1476000
+42363.00  -0.024543   0.237136  -0.1495809   -0.016000    0.263000   -0.1506000
+42364.00  -0.025251   0.237761  -0.1528176   -0.017000    0.263000   -0.1537000
+42365.00  -0.025948   0.238390  -0.1558584   -0.018000    0.263000   -0.1568000
+42366.00  -0.026638   0.239023  -0.1587363   -0.018000    0.264000   -0.1599000
+42367.00  -0.027322   0.239655  -0.1615100   -0.019000    0.264000   -0.1629000
+42368.00  -0.027999   0.240288  -0.1642452   -0.019000    0.265000   -0.1660000
+42369.00  -0.028670   0.240920  -0.1669996   -0.020000    0.265000   -0.1691000
+42370.00  -0.029332   0.241553  -0.1698154   -0.021000    0.265000   -0.1722000
+42371.00  -0.029984   0.242187  -0.1727172   -0.021000    0.266000   -0.1753000
+42372.00  -0.030624   0.242822  -0.1757133   -0.022000    0.266000   -0.1783000
+42373.00  -0.031252   0.243455  -0.1787966   -0.022000    0.267000   -0.1814000
+42374.00  -0.031866   0.244087  -0.1819454   -0.023000    0.267000   -0.1845000
+42375.00  -0.032463   0.244716  -0.1851271   -0.024000    0.267000   -0.1876000
+42376.00  -0.033043   0.245339  -0.1883019   -0.025000    0.268000   -0.1906000
+42377.00  -0.033605   0.245957  -0.1914286   -0.025000    0.268000   -0.1937000
+42378.00  -0.034149   0.246568  -0.1944705   -0.026000    0.269000   -0.1967000
+42379.00  -0.034674   0.247172  -0.1974034   -0.027000    0.269000   -0.1998000
+42380.00  -0.035178   0.247771  -0.2002257   -0.028000    0.269000   -0.2029000
+42381.00  -0.035660   0.248366  -0.2029672   -0.029000    0.270000   -0.2059000
+42382.00  -0.036119   0.248959  -0.2056880   -0.029000    0.270000   -0.2090000
+42383.00  -0.036555   0.249549  -0.2084660   -0.030000    0.271000   -0.2120000
+42384.00  -0.036969   0.250136  -0.2113722   -0.031000    0.271000   -0.2151000
+42385.00  -0.037360   0.250720  -0.2144449   -0.031000    0.271000   -0.2180000
+42386.00  -0.037727   0.251301  -0.2176753   -0.032000    0.272000   -0.2210000
+42387.00  -0.038067   0.251878  -0.2210090   -0.032000    0.272000   -0.2239000
+42388.00  -0.038382   0.252448  -0.2243632   -0.033000    0.273000   -0.2269000
+42389.00  -0.038673   0.253012  -0.2276498   -0.033000    0.273000   -0.2298000
+42390.00  -0.038940   0.253568  -0.2307956   -0.033000    0.273000   -0.2326000
+42391.00  -0.039184   0.254115  -0.2337566   -0.034000    0.274000   -0.2354000
+42392.00  -0.039408   0.254656  -0.2365234   -0.034000    0.274000   -0.2381000
+42393.00  -0.039614   0.255193  -0.2391202   -0.035000    0.275000   -0.2409000
+42394.00  -0.039809   0.255726  -0.2415963   -0.035000    0.275000   -0.2437000
+42395.00  -0.039996   0.256257  -0.2440136   -0.035000    0.275000   -0.2463000
+42396.00  -0.040178   0.256789  -0.2464328   -0.035000    0.276000   -0.2490000
+42397.00  -0.040360   0.257323  -0.2489018   -0.036000    0.276000   -0.2516000
+42398.00  -0.040542   0.257858  -0.2514511   -0.036000    0.277000   -0.2543000
+42399.00  -0.040724   0.258394  -0.2540928   -0.036000    0.277000   -0.2569000
+42400.00  -0.040910   0.258930  -0.2568225   -0.036000    0.277000   -0.2595000
+42401.00  -0.041101   0.259466  -0.2596221   -0.036000    0.278000   -0.2621000
+42402.00  -0.041297   0.260000  -0.2624630   -0.037000    0.278000   -0.2648000
+42403.00  -0.041498   0.260534  -0.2653103   -0.037000    0.279000   -0.2674000
+42404.00  -0.041705   0.261069  -0.2681275   -0.037000    0.279000   -0.2700000
+42405.00  -0.041917   0.261606  -0.2708818   -0.037000    0.279000   -0.2726000
+42406.00  -0.042136   0.262144  -0.2735492   -0.037000    0.279000   -0.2752000
+42407.00  -0.042362   0.262684  -0.2761222   -0.038000    0.280000   -0.2777000
+42408.00  -0.042596   0.263227  -0.2786190   -0.038000    0.280000   -0.2803000
+42409.00  -0.042837   0.263773  -0.2810892   -0.038000    0.280000   -0.2829000
+42410.00  -0.043081   0.264322  -0.2836080   -0.038000    0.280000   -0.2855000
+42411.00  -0.043325   0.264876  -0.2862566   -0.038000    0.280000   -0.2882000
+42412.00  -0.043569   0.265436  -0.2890927   -0.039000    0.281000   -0.2908000
+42413.00  -0.043813   0.266001   0.7078756   -0.039000    0.281000    0.7065000
+42414.00  -0.044056   0.266573   0.7046980   -0.039000    0.281000    0.7039000
+42415.00  -0.044299   0.267153   0.7014674   -0.039000    0.281000    0.7012000
+42416.00  -0.044538   0.267744   0.6982891   -0.039000    0.282000    0.6986000
+42417.00  -0.044768   0.268350   0.6952497   -0.040000    0.282000    0.6959000
+42418.00  -0.044988   0.268975   0.6923984   -0.040000    0.283000    0.6933000
+42419.00  -0.045193   0.269624   0.6897425   -0.040000    0.283000    0.6906000
+42420.00  -0.045381   0.270298   0.6872556   -0.040000    0.283000    0.6879000
+42421.00  -0.045545   0.271002   0.6848888   -0.040000    0.284000    0.6853000
+42422.00  -0.045681   0.271735   0.6825825   -0.039000    0.284000    0.6826000
+42423.00  -0.045780   0.272497   0.6802763   -0.039000    0.285000    0.6800000
+42424.00  -0.045838   0.273288   0.6779183   -0.039000    0.285000    0.6773000
+42425.00  -0.045849   0.274108   0.6754717   -0.039000    0.286000    0.6746000
+42426.00  -0.045810   0.274956   0.6729187   -0.038000    0.286000    0.6719000
+42427.00  -0.045718   0.275833   0.6702599   -0.038000    0.287000    0.6691000
+42428.00  -0.045572   0.276739   0.6675120   -0.037000    0.287000    0.6664000
+42429.00  -0.045372   0.277675   0.6647030   -0.037000    0.288000    0.6637000
+42430.00  -0.045120   0.278643   0.6618672   -0.036000    0.289000    0.6610000
+42431.00  -0.044818   0.279643   0.6590403   -0.036000    0.289000    0.6582000
+42432.00  -0.044467   0.280677   0.6562544   -0.035000    0.290000    0.6555000
+42433.00  -0.044070   0.281746   0.6535334   -0.035000    0.290000    0.6527000
+42434.00  -0.043628   0.282851   0.6508876   -0.034000    0.291000    0.6500000
+42435.00  -0.043138   0.283988   0.6483073   -0.033000    0.292000    0.6472000
+42436.00  -0.042603   0.285155   0.6457559   -0.032000    0.292000    0.6443000
+42437.00  -0.042021   0.286350   0.6431682   -0.032000    0.293000    0.6415000
+42438.00  -0.041394   0.287570   0.6404612   -0.031000    0.293000    0.6386000
+42439.00  -0.040726   0.288813   0.6375585   -0.030000    0.294000    0.6358000
+42440.00  -0.040018   0.290078   0.6344222   -0.029000    0.295000    0.6328000
+42441.00  -0.039271   0.291366   0.6310758   -0.028000    0.295000    0.6299000
+42442.00  -0.038487   0.292676   0.6276040   -0.026000    0.296000    0.6269000
+42443.00  -0.037672   0.294007   0.6241280   -0.025000    0.296000    0.6240000
+42444.00  -0.036831   0.295362   0.6207651   -0.024000    0.297000    0.6210000
+42445.00  -0.035972   0.296738   0.6175948   -0.023000    0.298000    0.6181000
+42446.00  -0.035098   0.298134   0.6146428   -0.022000    0.299000    0.6151000
+42447.00  -0.034215   0.299551   0.6118869   -0.022000    0.300000    0.6122000
+42448.00  -0.033323   0.300984   0.6092753   -0.021000    0.301000    0.6092000
+42449.00  -0.032428   0.302432   0.6067448   -0.020000    0.302000    0.6063000
+42450.00  -0.031533   0.303890   0.6042334   -0.019000    0.303000    0.6034000
+42451.00  -0.030641   0.305355   0.6016879   -0.018000    0.304000    0.6005000
+42452.00  -0.029752   0.306822   0.5990674   -0.018000    0.306000    0.5975000
+42453.00  -0.028867   0.308289   0.5963479   -0.017000    0.307000    0.5946000
+42454.00  -0.027985   0.309752   0.5935241   -0.016000    0.308000    0.5917000
+42455.00  -0.027107   0.311208   0.5906088   -0.015000    0.309000    0.5888000
+42456.00  -0.026233   0.312651   0.5876293   -0.014000    0.310000    0.5859000
+42457.00  -0.025359   0.314078   0.5846213   -0.014000    0.312000    0.5830000
+42458.00  -0.024481   0.315489   0.5816232   -0.013000    0.313000    0.5801000
+42459.00  -0.023595   0.316880   0.5786704   -0.012000    0.314000    0.5772000
+42460.00  -0.022698   0.318250   0.5757901   -0.011000    0.315000    0.5743000
+42461.00  -0.021785   0.319596   0.5729971   -0.011000    0.316000    0.5714000
+42462.00  -0.020854   0.320913   0.5702878   -0.010000    0.318000    0.5686000
+42463.00  -0.019901   0.322199   0.5676357   -0.010000    0.319000    0.5657000
+42464.00  -0.018922   0.323451   0.5649878   -0.009000    0.320000    0.5628000
+42465.00  -0.017916   0.324668   0.5622687   -0.008000    0.321000    0.5600000
+42466.00  -0.016879   0.325847   0.5593957   -0.008000    0.322000    0.5572000
+42467.00  -0.015812   0.326987   0.5563054   -0.007000    0.323000    0.5543000
+42468.00  -0.014712   0.328087   0.5529823   -0.007000    0.324000    0.5515000
+42469.00  -0.013581   0.329149   0.5494757   -0.006000    0.325000    0.5487000
+42470.00  -0.012420   0.330173   0.5458914   -0.006000    0.326000    0.5459000
+42471.00  -0.011231   0.331158   0.5423600   -0.005000    0.327000    0.5432000
+42472.00  -0.010016   0.332105   0.5389947   -0.005000    0.327000    0.5404000
+42473.00  -0.008773   0.333012   0.5358580   -0.004000    0.328000    0.5377000
+42474.00  -0.007500   0.333880   0.5329514   -0.004000    0.329000    0.5349000
+42475.00  -0.006197   0.334705   0.5302293   -0.004000    0.330000    0.5321000
+42476.00  -0.004863   0.335489   0.5276233   -0.003000    0.331000    0.5292000
+42477.00  -0.003500   0.336232   0.5250636   -0.003000    0.331000    0.5264000
+42478.00  -0.002108   0.336934   0.5224911   -0.002000    0.332000    0.5235000
+42479.00  -0.000692   0.337597   0.5198611   -0.002000    0.333000    0.5207000
+42480.00   0.000744   0.338223   0.5171438   -0.002000    0.334000    0.5178000
+42481.00   0.002194   0.338812   0.5143260   -0.001000    0.334000    0.5149000
+42482.00   0.003653   0.339365   0.5114119   -0.001000    0.335000    0.5121000
+42483.00   0.005126   0.339885   0.5084225    0.000000    0.335000    0.5092000
+42484.00   0.006613   0.340372   0.5053905    0.000000    0.336000    0.5063000
+42485.00   0.008116   0.340829   0.5023538    0.001000    0.337000    0.5033000
+42486.00   0.009635   0.341255   0.4993497    0.001000    0.337000    0.5003000
+42487.00   0.011171   0.341651   0.4964084    0.002000    0.338000    0.4974000
+42488.00   0.012726   0.342017   0.4935487    0.002000    0.338000    0.4944000
+42489.00   0.014304   0.342352   0.4907725    0.003000    0.339000    0.4914000
+42490.00   0.015905   0.342660   0.4880607    0.004000    0.340000    0.4883000
+42491.00   0.017531   0.342942   0.4853706    0.005000    0.340000    0.4852000
+42492.00   0.019180   0.343198   0.4826378    0.005000    0.341000    0.4821000
+42493.00   0.020849   0.343430   0.4797859    0.006000    0.341000    0.4790000
+42494.00   0.022537   0.343638   0.4767436    0.007000    0.342000    0.4759000
+42495.00   0.024242   0.343820   0.4734686    0.008000    0.342000    0.4727000
+42496.00   0.025962   0.343976   0.4699702    0.009000    0.343000    0.4695000
+42497.00   0.027694   0.344104   0.4663166    0.010000    0.343000    0.4664000
+42498.00   0.029437   0.344201   0.4626221    0.011000    0.344000    0.4632000
+42499.00   0.031187   0.344266   0.4590129    0.012000    0.344000    0.4600000
+42500.00   0.032941   0.344294   0.4555869    0.013000    0.344000    0.4569000
+42501.00   0.034696   0.344283   0.4523866    0.015000    0.344000    0.4538000
+42502.00   0.036448   0.344232   0.4493950    0.016000    0.344000    0.4507000
+42503.00   0.038197   0.344141   0.4465544    0.018000    0.344000    0.4476000
+42504.00   0.039936   0.344009   0.4437925    0.019000    0.344000    0.4445000
+42505.00   0.041661   0.343836   0.4410437    0.020000    0.344000    0.4415000
+42506.00   0.043367   0.343622   0.4382584    0.021000    0.344000    0.4386000
+42507.00   0.045053   0.343367   0.4354043    0.023000    0.345000    0.4356000
+42508.00   0.046719   0.343070   0.4324646    0.024000    0.345000    0.4327000
+42509.00   0.048364   0.342730   0.4294378    0.025000    0.345000    0.4297000
+42510.00   0.049985   0.342348   0.4263381    0.026000    0.345000    0.4268000
+42511.00   0.051578   0.341921   0.4231931    0.027000    0.345000    0.4239000
+42512.00   0.053137   0.341449   0.4200387    0.029000    0.345000    0.4211000
+42513.00   0.054661   0.340931   0.4169125    0.030000    0.345000    0.4182000
+42514.00   0.056146   0.340369   0.4138476    0.031000    0.345000    0.4153000
+42515.00   0.057593   0.339764   0.4108669    0.032000    0.345000    0.4124000
+42516.00   0.058999   0.339119   0.4079785    0.033000    0.345000    0.4095000
+42517.00   0.060367   0.338435   0.4051706    0.035000    0.344000    0.4065000
+42518.00   0.061701   0.337716   0.4024088    0.036000    0.344000    0.4036000
+42519.00   0.063009   0.336966   0.3996382    0.037000    0.344000    0.4007000
+42520.00   0.064296   0.336186   0.3967917    0.038000    0.343000    0.3977000
+42521.00   0.065567   0.335382   0.3938035    0.039000    0.343000    0.3947000
+42522.00   0.066826   0.334554   0.3906270    0.041000    0.342000    0.3917000
+42523.00   0.068077   0.333704   0.3872515    0.042000    0.342000    0.3887000
+42524.00   0.069321   0.332833   0.3837133    0.043000    0.341000    0.3857000
+42525.00   0.070557   0.331940   0.3800930    0.044000    0.340000    0.3826000
+42526.00   0.071788   0.331024   0.3764981    0.045000    0.339000    0.3796000
+42527.00   0.073014   0.330086   0.3730323    0.046000    0.338000    0.3765000
+42528.00   0.074238   0.329124   0.3697646    0.047000    0.337000    0.3735000
+42529.00   0.075463   0.328141   0.3667112    0.048000    0.336000    0.3704000
+42530.00   0.076690   0.327137   0.3638376    0.049000    0.335000    0.3674000
+42531.00   0.077921   0.326113   0.3610792    0.050000    0.334000    0.3643000
+42532.00   0.079157   0.325068   0.3583660    0.051000    0.332000    0.3613000
+42533.00   0.080398   0.324001   0.3556415    0.052000    0.331000    0.3582000
+42534.00   0.081641   0.322911   0.3528694    0.053000    0.330000    0.3552000
+42535.00   0.082882   0.321798   0.3500319    0.054000    0.329000    0.3522000
+42536.00   0.084121   0.320663   0.3471267    0.055000    0.327000    0.3492000
+42537.00   0.085356   0.319504   0.3441649    0.055000    0.326000    0.3462000
+42538.00   0.086586   0.318325   0.3411700    0.056000    0.324000    0.3432000
+42539.00   0.087811   0.317127   0.3381746    0.057000    0.323000    0.3402000
+42540.00   0.089031   0.315913   0.3352143    0.058000    0.322000    0.3373000
+42541.00   0.090241   0.314689   0.3323221    0.059000    0.321000    0.3344000
+42542.00   0.091439   0.313459   0.3295229    0.059000    0.319000    0.3314000
+42543.00   0.092621   0.312226   0.3268285    0.060000    0.318000    0.3285000
+42544.00   0.093786   0.310993   0.3242325    0.061000    0.317000    0.3256000
+42545.00   0.094932   0.309761   0.3217068    0.062000    0.316000    0.3228000
+42546.00   0.096058   0.308531   0.3192016    0.063000    0.314000    0.3200000
+42547.00   0.097163   0.307303   0.3166529    0.064000    0.313000    0.3172000
+42548.00   0.098247   0.306076   0.3139979    0.065000    0.311000    0.3144000
+42549.00   0.099311   0.304848   0.3111915    0.066000    0.310000    0.3116000
+42550.00   0.100359   0.303619   0.3082210    0.067000    0.309000    0.3089000
+42551.00   0.101397   0.302388   0.3051124    0.068000    0.308000    0.3061000
+42552.00   0.102426   0.301158   0.3019278    0.069000    0.306000    0.3034000
+42553.00   0.103450   0.299929   0.2987524    0.070000    0.305000    0.3006000
+42554.00   0.104473   0.298699   0.2956753    0.071000    0.304000    0.2979000
+42555.00   0.105500   0.297467   0.2927661    0.072000    0.303000    0.2952000
+42556.00   0.106539   0.296233   0.2900570    0.073000    0.302000    0.2926000
+42557.00   0.107595   0.294997   0.2875349    0.074000    0.300000    0.2899000
+42558.00   0.108671   0.293758   0.2851496    0.075000    0.299000    0.2873000
+42559.00   0.109773   0.292518   0.2828336    0.076000    0.298000    0.2846000
+42560.00   0.110906   0.291275   0.2805229    0.077000    0.297000    0.2820000
+42561.00   0.112075   0.290031   0.2781713    0.079000    0.295000    0.2795000
+42562.00   0.113283   0.288785   0.2757543    0.080000    0.294000    0.2769000
+42563.00   0.114533   0.287537   0.2732663    0.082000    0.292000    0.2744000
+42564.00   0.115825   0.286288   0.2707160    0.083000    0.291000    0.2718000
+42565.00   0.117160   0.285035   0.2681232    0.084000    0.290000    0.2693000
+42566.00   0.118536   0.283780   0.2655170    0.086000    0.289000    0.2668000
+42567.00   0.119950   0.282521   0.2629321    0.087000    0.287000    0.2643000
+42568.00   0.121398   0.281258   0.2604028    0.089000    0.286000    0.2618000
+42569.00   0.122879   0.279990   0.2579562    0.090000    0.285000    0.2593000
+42570.00   0.124388   0.278717   0.2556079    0.092000    0.284000    0.2568000
+42571.00   0.125921   0.277438   0.2533572    0.093000    0.282000    0.2544000
+42572.00   0.127474   0.276154   0.2511834    0.095000    0.281000    0.2519000
+42573.00   0.129037   0.274864   0.2490428    0.096000    0.279000    0.2495000
+42574.00   0.130603   0.273567   0.2468736    0.098000    0.278000    0.2470000
+42575.00   0.132165   0.272260   0.2446096    0.100000    0.277000    0.2446000
+42576.00   0.133713   0.270945   0.2422005    0.101000    0.275000    0.2422000
+42577.00   0.135237   0.269625   0.2396310    0.103000    0.274000    0.2398000
+42578.00   0.136725   0.268302   0.2369286    0.104000    0.272000    0.2374000
+42579.00   0.138167   0.266980   0.2341584    0.106000    0.271000    0.2350000
+42580.00   0.139554   0.265660   0.2314051    0.108000    0.270000    0.2326000
+42581.00   0.140882   0.264345   0.2287524    0.109000    0.268000    0.2303000
+42582.00   0.142146   0.263038   0.2262630    0.111000    0.267000    0.2279000
+42583.00   0.143336   0.261738   0.2239675    0.112000    0.265000    0.2256000
+42584.00   0.144446   0.260444   0.2218601    0.114000    0.264000    0.2232000
+42585.00   0.145469   0.259152   0.2199022    0.115000    0.263000    0.2209000
+42586.00   0.146405   0.257856   0.2180341    0.117000    0.261000    0.2187000
+42587.00   0.147255   0.256553   0.2161921    0.118000    0.260000    0.2164000
+42588.00   0.148021   0.255237   0.2143237    0.120000    0.258000    0.2142000
+42589.00   0.148702   0.253903   0.2123966    0.121000    0.257000    0.2119000
+42590.00   0.149300   0.252549   0.2104005    0.122000    0.255000    0.2098000
+42591.00   0.149817   0.251173   0.2083430    0.123000    0.254000    0.2077000
+42592.00   0.150256   0.249773   0.2062449    0.125000    0.252000    0.2055000
+42593.00   0.150620   0.248350   0.2041341    0.126000    0.251000    0.2034000
+42594.00   0.150907   0.246906   0.2020430    0.127000    0.249000    0.2013000
+42595.00   0.151121   0.245438   0.2000033    0.128000    0.247000    0.1993000
+42596.00   0.151264   0.243945   0.1980417    0.129000    0.246000    0.1973000
+42597.00   0.151341   0.242428   0.1961746    0.129000    0.244000    0.1953000
+42598.00   0.151357   0.240886   0.1944039    0.130000    0.243000    0.1933000
+42599.00   0.151316   0.239321   0.1927134    0.131000    0.241000    0.1913000
+42600.00   0.151218   0.237734   0.1910650    0.131000    0.239000    0.1893000
+42601.00   0.151067   0.236130   0.1893995    0.132000    0.238000    0.1874000
+42602.00   0.150864   0.234510   0.1876449    0.132000    0.236000    0.1854000
+42603.00   0.150608   0.232880   0.1857359    0.133000    0.235000    0.1835000
+42604.00   0.150303   0.231240   0.1836383    0.133000    0.233000    0.1815000
+42605.00   0.149951   0.229592   0.1813664    0.133000    0.231000    0.1796000
+42606.00   0.149556   0.227935   0.1789845    0.133000    0.230000    0.1777000
+42607.00   0.149123   0.226270   0.1765882    0.134000    0.228000    0.1758000
+42608.00   0.148659   0.224596   0.1742749    0.134000    0.227000    0.1739000
+42609.00   0.148167   0.222915   0.1721174    0.134000    0.225000    0.1720000
+42610.00   0.147651   0.221225   0.1701488    0.134000    0.223000    0.1702000
+42611.00   0.147119   0.219529   0.1683616    0.134000    0.221000    0.1683000
+42612.00   0.146579   0.217826   0.1667168    0.135000    0.220000    0.1665000
+42613.00   0.146036   0.216118   0.1651568    0.135000    0.218000    0.1646000
+42614.00   0.145495   0.214404   0.1636182    0.135000    0.216000    0.1628000
+42615.00   0.144958   0.212684   0.1620442    0.135000    0.214000    0.1610000
+42616.00   0.144430   0.210958   0.1603935    0.135000    0.213000    0.1592000
+42617.00   0.143917   0.209226   0.1586456    0.135000    0.211000    0.1573000
+42618.00   0.143422   0.207487   0.1568008    0.135000    0.210000    0.1555000
+42619.00   0.142948   0.205744   0.1548759    0.135000    0.208000    0.1537000
+42620.00   0.142495   0.203995   0.1528981    0.135000    0.206000    0.1518000
+42621.00   0.142061   0.202241   0.1508998    0.135000    0.204000    0.1499000
+42622.00   0.141647   0.200481   0.1489135    0.136000    0.203000    0.1480000
+42623.00   0.141250   0.198715   0.1469678    0.136000    0.201000    0.1461000
+42624.00   0.140866   0.196941   0.1450827    0.136000    0.199000    0.1442000
+42625.00   0.140495   0.195159   0.1432652    0.136000    0.197000    0.1422000
+42626.00   0.140131   0.193370   0.1415062    0.136000    0.195000    0.1402000
+42627.00   0.139771   0.191574   0.1397771    0.136000    0.194000    0.1383000
+42628.00   0.139409   0.189773   0.1380281    0.136000    0.192000    0.1363000
+42629.00   0.139043   0.187967   0.1361916    0.136000    0.190000    0.1343000
+42630.00   0.138669   0.186160   0.1341949    0.136000    0.188000    0.1322000
+42631.00   0.138283   0.184355   0.1319829    0.136000    0.186000    0.1301000
+42632.00   0.137886   0.182552   0.1295436    0.137000    0.185000    0.1279000
+42633.00   0.137474   0.180753   0.1269223    0.137000    0.183000    0.1258000
+42634.00   0.137044   0.178960   0.1242150    0.137000    0.181000    0.1237000
+42635.00   0.136594   0.177173   0.1215397    0.137000    0.179000    0.1215000
+42636.00   0.136127   0.175389   0.1189993    0.137000    0.178000    0.1193000
+42637.00   0.135643   0.173609   0.1166529    0.137000    0.176000    0.1172000
+42638.00   0.135138   0.171833   0.1145063    0.137000    0.175000    0.1150000
+42639.00   0.134611   0.170059   0.1125222    0.137000    0.173000    0.1128000
+42640.00   0.134057   0.168287   0.1106400    0.137000    0.172000    0.1106000
+42641.00   0.133477   0.166517   0.1087940    0.137000    0.170000    0.1084000
+42642.00   0.132872   0.164748   0.1069262    0.136000    0.169000    0.1063000
+42643.00   0.132241   0.162980   0.1049929    0.136000    0.167000    0.1041000
+42644.00   0.131582   0.161210   0.1029686    0.136000    0.166000    0.1019000
+42645.00   0.130895   0.159439   0.1008470    0.136000    0.165000    0.0998000
+42646.00   0.130180   0.157663   0.0986407    0.136000    0.163000    0.0976000
+42647.00   0.129438   0.155884   0.0963759    0.135000    0.162000    0.0955000
+42648.00   0.128669   0.154099   0.0940867    0.135000    0.160000    0.0933000
+42649.00   0.127872   0.152307   0.0918087    0.135000    0.159000    0.0912000
+42650.00   0.127042   0.150509   0.0895730    0.134000    0.158000    0.0890000
+42651.00   0.126175   0.148704   0.0874023    0.134000    0.156000    0.0869000
+42652.00   0.125270   0.146895   0.0853067    0.133000    0.155000    0.0847000
+42653.00   0.124326   0.145082   0.0832809    0.133000    0.153000    0.0826000
+42654.00   0.123343   0.143270   0.0813027    0.132000    0.152000    0.0804000
+42655.00   0.122316   0.141461   0.0793306    0.131000    0.151000    0.0781000
+42656.00   0.121242   0.139659   0.0773052    0.130000    0.149000    0.0758000
+42657.00   0.120119   0.137868   0.0751549    0.128000    0.148000    0.0735000
+42658.00   0.118946   0.136090   0.0728116    0.127000    0.146000    0.0712000
+42659.00   0.117724   0.134331   0.0702342    0.126000    0.145000    0.0689000
+42660.00   0.116450   0.132594   0.0674318    0.125000    0.144000    0.0665000
+42661.00   0.115122   0.130881   0.0644718    0.123000    0.143000    0.0641000
+42662.00   0.113735   0.129198   0.0614672    0.122000    0.141000    0.0618000
+42663.00   0.112285   0.127549   0.0585415    0.120000    0.140000    0.0594000
+42664.00   0.110770   0.125938   0.0557892    0.119000    0.139000    0.0570000
+42665.00   0.109188   0.124368   0.0532491    0.117000    0.138000    0.0546000
+42666.00   0.107540   0.122843   0.0509018    0.116000    0.137000    0.0521000
+42667.00   0.105831   0.121362   0.0486878    0.114000    0.135000    0.0497000
+42668.00   0.104064   0.119928   0.0465338    0.113000    0.134000    0.0472000
+42669.00   0.102244   0.118541   0.0443734    0.111000    0.133000    0.0448000
+42670.00   0.100377   0.117203   0.0421573    0.109000    0.132000    0.0423000
+42671.00   0.098468   0.115914   0.0398549    0.107000    0.131000    0.0398000
+42672.00   0.096524   0.114671   0.0374535    0.106000    0.130000    0.0374000
+42673.00   0.094556   0.113472   0.0349574    0.104000    0.129000    0.0349000
+42674.00   0.092568   0.112315   0.0323854    0.102000    0.128000    0.0324000
+42675.00   0.090562   0.111197   0.0297676    0.100000    0.127000    0.0298000
+42676.00   0.088541   0.110116   0.0271382    0.098000    0.126000    0.0272000
+42677.00   0.086507   0.109068   0.0245291    0.097000    0.124000    0.0247000
+42678.00   0.084463   0.108051   0.0219647    0.095000    0.123000    0.0221000
+42679.00   0.082411   0.107063   0.0194578    0.093000    0.122000    0.0195000
+42680.00   0.080351   0.106103   0.0170073    0.091000    0.121000    0.0168000
+42681.00   0.078281   0.105169   0.0145964    0.089000    0.120000    0.0141000
+42682.00   0.076200   0.104262   0.0121912    0.087000    0.119000    0.0114000
+42683.00   0.074109   0.103379   0.0097417    0.085000    0.118000    0.0087000
+42684.00   0.072008   0.102523   0.0071859    0.083000    0.117000    0.0060000
+42685.00   0.069891   0.101693   0.0044591    0.081000    0.116000    0.0032000
+42686.00   0.067753   0.100891   0.0015094    0.079000    0.115000    0.0004000
+42687.00   0.065591   0.100115  -0.0016819    0.077000    0.114000   -0.0023000
+42688.00   0.063400   0.099364  -0.0050831    0.075000    0.113000   -0.0051000
+42689.00   0.061177   0.098637  -0.0086107    0.073000    0.112000   -0.0079000
+42690.00   0.058918   0.097935  -0.0121475    0.071000    0.111000   -0.0108000
+42691.00   0.056619   0.097260  -0.0155777    0.069000    0.110000   -0.0137000
+42692.00   0.054278   0.096614  -0.0188238    0.066000    0.110000   -0.0167000
+42693.00   0.051893   0.095998  -0.0218672    0.064000    0.109000   -0.0196000
+42694.00   0.049466   0.095416  -0.0247445    0.062000    0.108000   -0.0225000
+42695.00   0.046997   0.094868  -0.0275243    0.060000    0.107000   -0.0255000
+42696.00   0.044489   0.094358  -0.0302791    0.057000    0.107000   -0.0285000
+42697.00   0.041945   0.093886  -0.0330653    0.055000    0.106000   -0.0315000
+42698.00   0.039363   0.093452  -0.0359169    0.052000    0.106000   -0.0345000
+42699.00   0.036746   0.093054  -0.0388482    0.050000    0.105000   -0.0375000
+42700.00   0.034093   0.092693  -0.0418584    0.047000    0.105000   -0.0406000
+42701.00   0.031402   0.092367  -0.0449336    0.045000    0.104000   -0.0437000
+42702.00   0.028671   0.092077  -0.0480485    0.042000    0.104000   -0.0469000
+42703.00   0.025899   0.091825  -0.0511704    0.040000    0.103000   -0.0500000
+42704.00   0.023088   0.091609  -0.0542659    0.037000    0.103000   -0.0531000
+42705.00   0.020236   0.091433  -0.0573070    0.034000    0.103000   -0.0563000
+42706.00   0.017343   0.091295  -0.0602766    0.032000    0.103000   -0.0594000
+42707.00   0.014408   0.091196  -0.0631707    0.029000    0.102000   -0.0626000
+42708.00   0.011430   0.091136  -0.0660001    0.027000    0.102000   -0.0657000
+42709.00   0.008415   0.091113  -0.0687916    0.024000    0.102000   -0.0689000
+42710.00   0.005366   0.091128  -0.0715879    0.021000    0.102000   -0.0721000
+42711.00   0.002284   0.091180  -0.0744434    0.018000    0.102000   -0.0753000
+42712.00  -0.000828   0.091271  -0.0774171    0.016000    0.102000   -0.0785000
+42713.00  -0.003970   0.091400  -0.0805602    0.013000    0.102000   -0.0817000
+42714.00  -0.007140   0.091566  -0.0839023    0.010000    0.102000   -0.0849000
+42715.00  -0.010330   0.091769  -0.0874367    0.007000    0.102000   -0.0881000
+42716.00  -0.013536   0.092013  -0.0911128    0.004000    0.102000   -0.0913000
+42717.00  -0.016752   0.092297  -0.0948426    0.001000    0.103000   -0.0945000
+42718.00  -0.019973   0.092625  -0.0985208   -0.002000    0.103000   -0.0977000
+42719.00  -0.023191   0.092996  -0.1020561   -0.005000    0.103000   -0.1009000
+42720.00  -0.026399   0.093412  -0.1053988   -0.008000    0.104000   -0.1041000
+42721.00  -0.029590   0.093876  -0.1085538   -0.011000    0.105000   -0.1073000
+42722.00  -0.032760   0.094391  -0.1115712   -0.013000    0.105000   -0.1106000
+42723.00  -0.035902   0.094961  -0.1145216   -0.016000    0.106000   -0.1138000
+42724.00  -0.039010   0.095587  -0.1174698   -0.019000    0.107000   -0.1170000
+42725.00  -0.042077   0.096271  -0.1204590   -0.022000    0.108000   -0.1202000
+42726.00  -0.045090   0.097017  -0.1235075   -0.025000    0.110000   -0.1234000
+42727.00  -0.048044   0.097829  -0.1266150   -0.027000    0.111000   -0.1266000
+42728.00  -0.050932   0.098710  -0.1297683   -0.030000    0.113000   -0.1298000
+42729.00  -0.053751   0.099660  -0.1329450   -0.033000    0.114000   -0.1330000
+42730.00  -0.056499   0.100680  -0.1361156   -0.036000    0.116000   -0.1362000
+42731.00  -0.059173   0.101771  -0.1392475   -0.039000    0.117000   -0.1393000
+42732.00  -0.061773   0.102933  -0.1423112   -0.041000    0.119000   -0.1425000
+42733.00  -0.064300   0.104164  -0.1452861   -0.044000    0.120000   -0.1456000
+42734.00  -0.066758   0.105465  -0.1481645   -0.047000    0.122000   -0.1488000
+42735.00  -0.069154   0.106830  -0.1509530   -0.050000    0.124000   -0.1519000
+42736.00  -0.071496   0.108256  -0.1536738   -0.053000    0.126000   -0.1550000
+42737.00  -0.073792   0.109737  -0.1563645   -0.055000    0.127000   -0.1582000
+42738.00  -0.076051   0.111268  -0.1590747   -0.058000    0.129000   -0.1613000
+42739.00  -0.078276   0.112848  -0.1618592   -0.061000    0.131000   -0.1644000
+42740.00  -0.080474   0.114472  -0.1647655   -0.064000    0.133000   -0.1674000
+42741.00  -0.082652   0.116140  -0.1678220   -0.066000    0.135000   -0.1705000
+42742.00  -0.084820   0.117848  -0.1710272   -0.069000    0.136000   -0.1735000
+42743.00  -0.086983   0.119596  -0.1743461   -0.071000    0.138000   -0.1766000
+42744.00  -0.089145   0.121384  -0.1777136   -0.074000    0.140000   -0.1796000
+42745.00  -0.091308   0.123210  -0.1810477   -0.077000    0.142000   -0.1826000
+42746.00  -0.093472   0.125073  -0.1842687   -0.079000    0.144000   -0.1855000
+42747.00  -0.095638   0.126970  -0.1873216   -0.082000    0.145000   -0.1885000
+42748.00  -0.097804   0.128899  -0.1901925   -0.084000    0.147000   -0.1914000
+42749.00  -0.099969   0.130854  -0.1929110   -0.087000    0.149000   -0.1944000
+42750.00  -0.102128   0.132833  -0.1955375   -0.089000    0.151000   -0.1972000
+42751.00  -0.104281   0.134833  -0.1981401   -0.091000    0.152000   -0.2000000
+42752.00  -0.106423   0.136852  -0.2007731   -0.093000    0.154000   -0.2029000
+42753.00  -0.108550   0.138887  -0.2034657   -0.095000    0.155000   -0.2057000
+42754.00  -0.110656   0.140936  -0.2062227   -0.097000    0.157000   -0.2085000
+42755.00  -0.112735   0.142996  -0.2090323   -0.099000    0.159000   -0.2113000
+42756.00  -0.114783   0.145066  -0.2118730   -0.100000    0.160000   -0.2141000
+42757.00  -0.116794   0.147142  -0.2147182   -0.102000    0.162000   -0.2168000
+42758.00  -0.118762   0.149221  -0.2175390   -0.103000    0.163000   -0.2196000
+42759.00  -0.120682   0.151303  -0.2203080   -0.105000    0.165000   -0.2224000
+42760.00  -0.122549   0.153388  -0.2230042   -0.107000    0.167000   -0.2252000
+42761.00  -0.124360   0.155474  -0.2256178   -0.108000    0.169000   -0.2279000
+42762.00  -0.126111   0.157562  -0.2281532   -0.110000    0.170000   -0.2307000
+42763.00  -0.127800   0.159653  -0.2306297   -0.111000    0.172000   -0.2334000
+42764.00  -0.129423   0.161749  -0.2330821   -0.113000    0.174000   -0.2362000
+42765.00  -0.130977   0.163852  -0.2355587   -0.114000    0.176000   -0.2389000
+42766.00  -0.132461   0.165965  -0.2381153   -0.116000    0.178000   -0.2416000
+42767.00  -0.133879   0.168089  -0.2408033   -0.117000    0.180000   -0.2444000
+42768.00  -0.135231   0.170225  -0.2436542   -0.119000    0.182000   -0.2471000
+42769.00  -0.136520   0.172373  -0.2466668   -0.120000    0.184000   -0.2498000
+42770.00  -0.137749   0.174535  -0.2498037   -0.121000    0.186000   -0.2525000
+42771.00  -0.138922   0.176708  -0.2529990   -0.122000    0.188000   -0.2551000
+42772.00  -0.140046   0.178891  -0.2561747   -0.123000    0.191000   -0.2578000
+42773.00  -0.141125   0.181081  -0.2592587   -0.124000    0.193000   -0.2604000
+42774.00  -0.142162   0.183277  -0.2622010   -0.125000    0.195000   -0.2631000
+42775.00  -0.143157   0.185479  -0.2649847   -0.126000    0.197000   -0.2657000
+42776.00  -0.144114   0.187689  -0.2676290   -0.127000    0.199000   -0.2683000
+42777.00  -0.145035   0.189909  -0.2701822   -0.128000    0.202000   -0.2710000
+42778.00  -0.145922   0.192143   0.7272928   -0.129000    0.204000    0.7264000
+42779.00  -0.146779   0.194393   0.7247370   -0.130000    0.206000    0.7238000
+42780.00  -0.147599   0.196662   0.7221112   -0.131000    0.208000    0.7211000
+42781.00  -0.148380   0.198951   0.7194019   -0.131000    0.210000    0.7185000
+42782.00  -0.149117   0.201257   0.7166183   -0.132000    0.213000    0.7158000
+42783.00  -0.149810   0.203580   0.7137839   -0.132000    0.215000    0.7132000
+42784.00  -0.150451   0.205917   0.7109287   -0.133000    0.217000    0.7105000
+42785.00  -0.151041   0.208267   0.7080839   -0.133000    0.219000    0.7078000
+42786.00  -0.151577   0.210631   0.7052786   -0.134000    0.221000    0.7051000
+42787.00  -0.152057   0.213008   0.7025362   -0.134000    0.224000    0.7024000
+42788.00  -0.152481   0.215400   0.6998696   -0.135000    0.226000    0.6997000
+42789.00  -0.152852   0.217808   0.6972785   -0.135000    0.228000    0.6970000
+42790.00  -0.153173   0.220234   0.6947468   -0.135000    0.230000    0.6942000
+42791.00  -0.153446   0.222679   0.6922431   -0.135000    0.232000    0.6915000
+42792.00  -0.153675   0.225144   0.6897202   -0.136000    0.235000    0.6887000
+42793.00  -0.153862   0.227632   0.6871198   -0.136000    0.237000    0.6860000
+42794.00  -0.154011   0.230140   0.6843817   -0.136000    0.239000    0.6832000
+42795.00  -0.154124   0.232668   0.6814605   -0.136000    0.241000    0.6803000
+42796.00  -0.154204   0.235217   0.6783439   -0.136000    0.243000    0.6775000
+42797.00  -0.154253   0.237786   0.6750641   -0.137000    0.246000    0.6746000
+42798.00  -0.154273   0.240376   0.6716935   -0.137000    0.248000    0.6718000
+42799.00  -0.154264   0.242988   0.6683242   -0.137000    0.250000    0.6689000
+42800.00  -0.154226   0.245617   0.6650428   -0.137000    0.252000    0.6660000
+42801.00  -0.154162   0.248261   0.6619076   -0.137000    0.255000    0.6630000
+42802.00  -0.154076   0.250916   0.6589383   -0.138000    0.257000    0.6601000
+42803.00  -0.153970   0.253580   0.6561175   -0.138000    0.260000    0.6571000
+42804.00  -0.153848   0.256250   0.6533998   -0.138000    0.262000    0.6542000
+42805.00  -0.153715   0.258922   0.6507259   -0.138000    0.264000    0.6512000
+42806.00  -0.153574   0.261594   0.6480368   -0.138000    0.267000    0.6482000
+42807.00  -0.153428   0.264265   0.6452861   -0.138000    0.269000    0.6453000
+42808.00  -0.153279   0.266934   0.6424496   -0.138000    0.272000    0.6423000
+42809.00  -0.153131   0.269604   0.6395274   -0.138000    0.274000    0.6393000
+42810.00  -0.152986   0.272274   0.6365390   -0.138000    0.277000    0.6363000
+42811.00  -0.152842   0.274945   0.6335159   -0.138000    0.279000    0.6333000
+42812.00  -0.152695   0.277617   0.6304930   -0.138000    0.282000    0.6302000
+42813.00  -0.152540   0.280290   0.6275034   -0.138000    0.284000    0.6272000
+42814.00  -0.152375   0.282961   0.6245740   -0.138000    0.287000    0.6242000
+42815.00  -0.152197   0.285628   0.6217225   -0.138000    0.290000    0.6213000
+42816.00  -0.152000   0.288288   0.6189541   -0.138000    0.292000    0.6184000
+42817.00  -0.151781   0.290936   0.6162592   -0.137000    0.295000    0.6155000
+42818.00  -0.151533   0.293573   0.6136127   -0.137000    0.297000    0.6126000
+42819.00  -0.151251   0.296199   0.6109741   -0.137000    0.300000    0.6097000
+42820.00  -0.150933   0.298814   0.6082897   -0.137000    0.302000    0.6069000
+42821.00  -0.150575   0.301418   0.6054976   -0.136000    0.305000    0.6040000
+42822.00  -0.150174   0.304014   0.6025395   -0.136000    0.307000    0.6012000
+42823.00  -0.149726   0.306599   0.5993805   -0.135000    0.310000    0.5983000
+42824.00  -0.149229   0.309176   0.5960279   -0.135000    0.312000    0.5955000
+42825.00  -0.148684   0.311742   0.5925383   -0.134000    0.314000    0.5927000
+42826.00  -0.148094   0.314296   0.5890064   -0.134000    0.317000    0.5899000
+42827.00  -0.147460   0.316836   0.5855373   -0.133000    0.319000    0.5871000
+42828.00  -0.146784   0.319360   0.5822144   -0.133000    0.322000    0.5843000
+42829.00  -0.146073   0.321867   0.5790765   -0.132000    0.324000    0.5815000
+42830.00  -0.145331   0.324357   0.5761146   -0.131000    0.326000    0.5787000
+42831.00  -0.144566   0.326827   0.5732827   -0.131000    0.328000    0.5759000
+42832.00  -0.143778   0.329279   0.5705177   -0.130000    0.331000    0.5731000
+42833.00  -0.142971   0.331710   0.5677568   -0.130000    0.333000    0.5703000
+42834.00  -0.142145   0.334119   0.5649494   -0.129000    0.335000    0.5675000
+42835.00  -0.141302   0.336505   0.5620635   -0.128000    0.337000    0.5646000
+42836.00  -0.140442   0.338863   0.5590883   -0.128000    0.339000    0.5617000
+42837.00  -0.139563   0.341194   0.5560332   -0.127000    0.341000    0.5589000
+42838.00  -0.138660   0.343496   0.5529235   -0.127000    0.343000    0.5560000
+42839.00  -0.137733   0.345769   0.5497932   -0.126000    0.345000    0.5531000
+42840.00  -0.136781   0.348013   0.5466772   -0.125000    0.347000    0.5501000
+42841.00  -0.135807   0.350227   0.5436056   -0.124000    0.349000    0.5471000
+42842.00  -0.134811   0.352411   0.5405995   -0.124000    0.350000    0.5441000
+42843.00  -0.133796   0.354565   0.5376686   -0.123000    0.352000    0.5411000
+42844.00  -0.132760   0.356692   0.5348089   -0.122000    0.354000    0.5381000
+42845.00  -0.131707   0.358793   0.5320016   -0.121000    0.356000    0.5350000
+42846.00  -0.130636   0.360869   0.5292134   -0.120000    0.358000    0.5319000
+42847.00  -0.129551   0.362923   0.5263966   -0.120000    0.359000    0.5288000
+42848.00  -0.128452   0.364956   0.5234931   -0.119000    0.361000    0.5257000
+42849.00  -0.127341   0.366971   0.5204408   -0.118000    0.363000    0.5226000
+42850.00  -0.126221   0.368970   0.5171889   -0.117000    0.365000    0.5194000
+42851.00  -0.125094   0.370954   0.5137165   -0.116000    0.367000    0.5163000
+42852.00  -0.123959   0.372922   0.5100498   -0.116000    0.368000    0.5131000
+42853.00  -0.122815   0.374874   0.5062651   -0.115000    0.370000    0.5100000
+42854.00  -0.121658   0.376808   0.5024721   -0.114000    0.372000    0.5068000
+42855.00  -0.120484   0.378726   0.4987803   -0.113000    0.374000    0.5036000
+42856.00  -0.119284   0.380628   0.4952644   -0.112000    0.376000    0.5003000
+42857.00  -0.118052   0.382514   0.4919446   -0.112000    0.377000    0.4971000
+42858.00  -0.116778   0.384388   0.4887897   -0.111000    0.379000    0.4938000
+42859.00  -0.115450   0.386253   0.4857373   -0.110000    0.381000    0.4906000
+42860.00  -0.114059   0.388112   0.4827192   -0.109000    0.383000    0.4873000
+42861.00  -0.112595   0.389968   0.4796800   -0.108000    0.385000    0.4839000
+42862.00  -0.111052   0.391823   0.4765838   -0.107000    0.386000    0.4806000
+42863.00  -0.109424   0.393681   0.4734152   -0.106000    0.388000    0.4772000
+42864.00  -0.107709   0.395542   0.4701765   -0.105000    0.390000    0.4739000
+42865.00  -0.105906   0.397406   0.4668847   -0.104000    0.392000    0.4705000
+42866.00  -0.104018   0.399271   0.4635681   -0.103000    0.394000    0.4671000
+42867.00  -0.102047   0.401134   0.4602603   -0.102000    0.395000    0.4638000
+42868.00  -0.099995   0.402994   0.4569929   -0.101000    0.397000    0.4604000
+42869.00  -0.097866   0.404852   0.4537904   -0.100000    0.399000    0.4570000
+42870.00  -0.095669   0.406706   0.4506658   -0.099000    0.401000    0.4536000
+42871.00  -0.093413   0.408553   0.4476198   -0.097000    0.403000    0.4502000
+42872.00  -0.091109   0.410392   0.4446395   -0.096000    0.405000    0.4467000
+42873.00  -0.088767   0.412218   0.4416984   -0.094000    0.407000    0.4433000
+42874.00  -0.086392   0.414029   0.4387576   -0.093000    0.409000    0.4399000
+42875.00  -0.083990   0.415821   0.4357669   -0.091000    0.411000    0.4366000
+42876.00  -0.081562   0.417591   0.4326701   -0.090000    0.413000    0.4332000
+42877.00  -0.079110   0.419335   0.4294138   -0.088000    0.415000    0.4299000
+42878.00  -0.076635   0.421048   0.4259609   -0.087000    0.417000    0.4265000
+42879.00  -0.074138   0.422728   0.4223079   -0.085000    0.419000    0.4232000
+42880.00  -0.071621   0.424368   0.4184967   -0.083000    0.421000    0.4199000
+42881.00  -0.069088   0.425965   0.4146124   -0.081000    0.423000    0.4166000
+42882.00  -0.066544   0.427516   0.4107633   -0.080000    0.424000    0.4132000
+42883.00  -0.063992   0.429019   0.4070470   -0.078000    0.426000    0.4099000
+42884.00  -0.061439   0.430471   0.4035190   -0.076000    0.428000    0.4066000
+42885.00  -0.058886   0.431870   0.4001787   -0.074000    0.430000    0.4033000
+42886.00  -0.056337   0.433213   0.3969785   -0.072000    0.431000    0.4000000
+42887.00  -0.053792   0.434496   0.3938495   -0.071000    0.433000    0.3968000
+42888.00  -0.051253   0.435720   0.3907280   -0.069000    0.434000    0.3935000
+42889.00  -0.048720   0.436883   0.3875718   -0.067000    0.436000    0.3902000
+42890.00  -0.046197   0.437983   0.3843629   -0.065000    0.437000    0.3870000
+42891.00  -0.043688   0.439018   0.3811017   -0.063000    0.439000    0.3837000
+42892.00  -0.041199   0.439986   0.3778019   -0.061000    0.440000    0.3805000
+42893.00  -0.038736   0.440883   0.3744861   -0.059000    0.442000    0.3772000
+42894.00  -0.036303   0.441706   0.3711830   -0.057000    0.443000    0.3740000
+42895.00  -0.033903   0.442451   0.3679226   -0.055000    0.444000    0.3707000
+42896.00  -0.031534   0.443115   0.3647305   -0.053000    0.445000    0.3675000
+42897.00  -0.029191   0.443696   0.3616222   -0.050000    0.446000    0.3642000
+42898.00  -0.026867   0.444191   0.3586003   -0.048000    0.447000    0.3610000
+42899.00  -0.024555   0.444600   0.3556546   -0.046000    0.448000    0.3577000
+42900.00  -0.022248   0.444920   0.3527621   -0.044000    0.449000    0.3545000
+42901.00  -0.019943   0.445150   0.3498887   -0.042000    0.450000    0.3512000
+42902.00  -0.017638   0.445288   0.3469905   -0.039000    0.450000    0.3480000
+42903.00  -0.015335   0.445331   0.3440182   -0.037000    0.451000    0.3447000
+42904.00  -0.013036   0.445276   0.3409233   -0.035000    0.452000    0.3415000
+42905.00  -0.010745   0.445122   0.3376682   -0.032000    0.452000    0.3381000
+42906.00  -0.008465   0.444867   0.3342371   -0.030000    0.453000    0.3347000
+42907.00  -0.006202   0.444511   0.3306472   -0.027000    0.453000    0.3314000
+42908.00  -0.003954   0.444053   0.3269529   -0.025000    0.454000    0.3280000
+42909.00  -0.001718   0.443494   0.3232386   -0.022000    0.454000    0.3246000
+42910.00   0.000512   0.442837   0.3195973   -0.019000    0.454000    0.3212000
+42911.00   0.002734   0.442084   0.3161017   -0.017000    0.454000    0.3177000
+42912.00   0.004949   0.441237   0.3127807   -0.014000    0.454000    0.3143000
+42913.00   0.007154   0.440300   0.3096121   -0.012000    0.454000    0.3108000
+42914.00   0.009354   0.439276   0.3065373   -0.009000    0.454000    0.3074000
+42915.00   0.011554   0.438172   0.3034880   -0.006000    0.454000    0.3041000
+42916.00   0.013761   0.436993   0.3004110   -0.003000    0.454000    0.3007000
+42917.00   0.015983   0.435748   0.2972803    0.002000    0.453000    0.2940000
+42918.00   0.018227   0.434445   0.2940956    0.002000    0.453000    0.2940000
+42919.00   0.020497   0.433093   0.2908756    0.005000    0.453000    0.2907000
+42920.00   0.022791   0.431707   0.2876480    0.008000    0.452000    0.2876000
+42921.00   0.025112   0.430297   0.2844442    0.011000    0.452000    0.2845000
+42922.00   0.027462   0.428878   0.2812960    0.014000    0.451000    0.2813000
+42923.00   0.029845   0.427465   0.2782318    0.017000    0.451000    0.2782000
+42924.00   0.032266   0.426071   0.2752722    0.020000    0.450000    0.2751000
+42925.00   0.034735   0.424714   0.2724254    0.023000    0.449000    0.2721000
+42926.00   0.037259   0.423411   0.2696860    0.026000    0.448000    0.2692000
+42927.00   0.039850   0.422181   0.2670353    0.029000    0.447000    0.2662000
+42928.00   0.042519   0.421041   0.2644432    0.032000    0.446000    0.2633000
+42929.00   0.045268   0.419990   0.2618698    0.035000    0.445000    0.2603000
+42930.00   0.048095   0.419011   0.2592691    0.038000    0.444000    0.2575000
+42931.00   0.050998   0.418092   0.2565967    0.041000    0.443000    0.2547000
+42932.00   0.053973   0.417222   0.2538185    0.044000    0.441000    0.2518000
+42933.00   0.057023   0.416390   0.2509208    0.047000    0.440000    0.2490000
+42934.00   0.060145   0.415586   0.2479160    0.050000    0.439000    0.2462000
+42935.00   0.063339   0.414802   0.2448453    0.053000    0.438000    0.2436000
+42936.00   0.066601   0.414032   0.2417737    0.056000    0.436000    0.2411000
+42937.00   0.069929   0.413270   0.2387777    0.060000    0.435000    0.2385000
+42938.00   0.073319   0.412510   0.2359248    0.063000    0.433000    0.2360000
+42939.00   0.076764   0.411747   0.2332542    0.066000    0.432000    0.2334000
+42940.00   0.080261   0.410977   0.2307632    0.069000    0.430000    0.2310000
+42941.00   0.083804   0.410197   0.2284091    0.072000    0.428000    0.2286000
+42942.00   0.087388   0.409404   0.2261262    0.076000    0.427000    0.2262000
+42943.00   0.091007   0.408596   0.2238509    0.079000    0.425000    0.2238000
+42944.00   0.094657   0.407772   0.2215422    0.082000    0.423000    0.2214000
+42945.00   0.098336   0.406929   0.2191885    0.085000    0.421000    0.2192000
+42946.00   0.102046   0.406065   0.2168023    0.089000    0.419000    0.2170000
+42947.00   0.105785   0.405180   0.2144087    0.092000    0.417000    0.2147000
+42948.00   0.109553   0.404273   0.2120361    0.096000    0.415000    0.2125000
+42949.00   0.113344   0.403338   0.2097117    0.099000    0.413000    0.2103000
+42950.00   0.117150   0.402367   0.2074596    0.102000    0.411000    0.2082000
+42951.00   0.120965   0.401350   0.2052974    0.106000    0.409000    0.2060000
+42952.00   0.124783   0.400278   0.2032318    0.109000    0.407000    0.2039000
+42953.00   0.128599   0.399142   0.2012559    0.113000    0.405000    0.2017000
+42954.00   0.132409   0.397934   0.1993482    0.116000    0.403000    0.1996000
+42955.00   0.136210   0.396646   0.1974747    0.119000    0.401000    0.1974000
+42956.00   0.139998   0.395270   0.1955915    0.123000    0.399000    0.1952000
+42957.00   0.143772   0.393797   0.1936489    0.126000    0.396000    0.1931000
+42958.00   0.147529   0.392219   0.1915975    0.130000    0.394000    0.1909000
+42959.00   0.151267   0.390543   0.1893993    0.133000    0.392000    0.1887000
+42960.00   0.154984   0.388776   0.1870376    0.136000    0.390000    0.1865000
+42961.00   0.158679   0.386923   0.1845248    0.140000    0.387000    0.1843000
+42962.00   0.162352   0.384992   0.1819028    0.143000    0.385000    0.1821000
+42963.00   0.166004   0.382986   0.1792345    0.147000    0.382000    0.1799000
+42964.00   0.169636   0.380910   0.1765898    0.150000    0.380000    0.1777000
+42965.00   0.173247   0.378770   0.1740294    0.153000    0.378000    0.1753000
+42966.00   0.176837   0.376569   0.1715909    0.156000    0.376000    0.1730000
+42967.00   0.180401   0.374315   0.1692790    0.159000    0.373000    0.1706000
+42968.00   0.183934   0.372014   0.1670645    0.162000    0.371000    0.1683000
+42969.00   0.187428   0.369671   0.1648930    0.165000    0.369000    0.1659000
+42970.00   0.190877   0.367294   0.1627037    0.168000    0.367000    0.1635000
+42971.00   0.194274   0.364887   0.1604486    0.171000    0.365000    0.1611000
+42972.00   0.197611   0.362456   0.1581059    0.173000    0.362000    0.1586000
+42973.00   0.200882   0.360005   0.1556828    0.176000    0.360000    0.1562000
+42974.00   0.204078   0.357538   0.1532076    0.179000    0.358000    0.1538000
+42975.00   0.207189   0.355057   0.1507172    0.182000    0.356000    0.1514000
+42976.00   0.210205   0.352562   0.1482482    0.184000    0.354000    0.1489000
+42977.00   0.213113   0.350055   0.1458315    0.187000    0.351000    0.1465000
+42978.00   0.215903   0.347537   0.1434907    0.189000    0.349000    0.1440000
+42979.00   0.218565   0.345008   0.1412396    0.192000    0.347000    0.1416000
+42980.00   0.221086   0.342468   0.1390792    0.194000    0.345000    0.1392000
+42981.00   0.223456   0.339916   0.1369961    0.197000    0.343000    0.1368000
+42982.00   0.225666   0.337350   0.1349622    0.199000    0.340000    0.1343000
+42983.00   0.227725   0.334770   0.1329375    0.202000    0.338000    0.1319000
+42984.00   0.229645   0.332174   0.1308736    0.204000    0.336000    0.1295000
+42985.00   0.231435   0.329559   0.1287194    0.206000    0.334000    0.1271000
+42986.00   0.233101   0.326925   0.1264293    0.209000    0.332000    0.1247000
+42987.00   0.234651   0.324267   0.1239761    0.211000    0.329000    0.1223000
+42988.00   0.236088   0.321585   0.1213634    0.214000    0.327000    0.1199000
+42989.00   0.237420   0.318877   0.1186313    0.216000    0.325000    0.1175000
+42990.00   0.238655   0.316140   0.1158493    0.218000    0.323000    0.1151000
+42991.00   0.239798   0.313373   0.1130985    0.220000    0.320000    0.1128000
+42992.00   0.240858   0.310575   0.1104494    0.223000    0.318000    0.1104000
+42993.00   0.241840   0.307745   0.1079439    0.225000    0.315000    0.1081000
+42994.00   0.242751   0.304881   0.1055884    0.227000    0.313000    0.1057000
+42995.00   0.243595   0.301983   0.1033558    0.229000    0.310000    0.1034000
+42996.00   0.244380   0.299052   0.1011959    0.231000    0.308000    0.1011000
+42997.00   0.245108   0.296091   0.0990505    0.233000    0.305000    0.0989000
+42998.00   0.245781   0.293101   0.0968681    0.235000    0.303000    0.0966000
+42999.00   0.246402   0.290085   0.0946168    0.237000    0.300000    0.0943000
+43000.00   0.246970   0.287047   0.0922901    0.239000    0.297000    0.0921000
+43001.00   0.247487   0.283988   0.0899044    0.241000    0.294000    0.0898000
+43002.00   0.247953   0.280913   0.0874919    0.242000    0.292000    0.0876000
+43003.00   0.248371   0.277825   0.0850903    0.244000    0.289000    0.0853000
+43004.00   0.248745   0.274725   0.0827333    0.246000    0.286000    0.0831000
+43005.00   0.249075   0.271617   0.0804458    0.248000    0.283000    0.0809000
+43006.00   0.249363   0.268503   0.0782417    0.249000    0.280000    0.0786000
+43007.00   0.249611   0.265386   0.0761236    0.251000    0.278000    0.0764000
+43008.00   0.249819   0.262269   0.0740805    0.252000    0.275000    0.0741000
+43009.00   0.249988   0.259157   0.0720864    0.254000    0.272000    0.0719000
+43010.00   0.250115   0.256052   0.0701021    0.255000    0.269000    0.0696000
+43011.00   0.250199   0.252957   0.0680790    0.256000    0.266000    0.0673000
+43012.00   0.250237   0.249874   0.0659637    0.258000    0.263000    0.0649000
+43013.00   0.250226   0.246806   0.0637037    0.259000    0.260000    0.0626000
+43014.00   0.250164   0.243753   0.0612575    0.260000    0.257000    0.0603000
+43015.00   0.250047   0.240718   0.0586089    0.261000    0.254000    0.0579000
+43016.00   0.249873   0.237703   0.0557798    0.262000    0.251000    0.0555000
+43017.00   0.249635   0.234708   0.0528321    0.263000    0.248000    0.0530000
+43018.00   0.249330   0.231736   0.0498545    0.264000    0.245000    0.0506000
+43019.00   0.248952   0.228790   0.0469369    0.265000    0.242000    0.0482000
+43020.00   0.248499   0.225872   0.0441424    0.266000    0.239000    0.0456000
+43021.00   0.247962   0.222984   0.0414915    0.266000    0.236000    0.0431000
+43022.00   0.247335   0.220128   0.0389619    0.267000    0.233000    0.0405000
+43023.00   0.246611   0.217308   0.0365018    0.267000    0.230000    0.0380000
+43024.00   0.245781   0.214527   0.0340482    0.268000    0.227000    0.0354000
+43025.00   0.244837   0.211786   0.0315440    0.268000    0.224000    0.0326000
+43026.00   0.243773   0.209088   0.0289484    0.268000    0.222000    0.0299000
+43027.00   0.242580   0.206434   0.0262430    0.267000    0.219000    0.0271000
+43028.00   0.241249   0.203825   0.0234329    0.267000    0.217000    0.0244000
+43029.00   0.239773   0.201263   0.0205429    0.267000    0.214000    0.0216000
+43030.00   0.238153   0.198749   0.0176095    0.266000    0.212000    0.0186000
+43031.00   0.236405   0.196285   0.0146718    0.266000    0.209000    0.0157000
+43032.00   0.234546   0.193873   0.0117630    0.265000    0.207000    0.0127000
+43033.00   0.232589   0.191512   0.0089050    0.265000    0.204000    0.0098000
+43034.00   0.230549   0.189206   0.0061070    0.264000    0.202000    0.0068000
+43035.00   0.228436   0.186953   0.0033653    0.263000    0.200000    0.0037000
+43036.00   0.226262   0.184756   0.0006625    0.262000    0.197000    0.0006000
+43037.00   0.224040   0.182613  -0.0020313    0.262000    0.195000   -0.0024000
+43038.00   0.221780   0.180523  -0.0047568    0.261000    0.192000   -0.0055000
+43039.00   0.219493   0.178483  -0.0075618    0.260000    0.190000   -0.0086000
+43040.00   0.217189   0.176491  -0.0104971    0.259000    0.187000   -0.0118000
+43041.00   0.214879   0.174542  -0.0136096    0.258000    0.185000   -0.0150000
+43042.00   0.212572   0.172634  -0.0169307    0.257000    0.182000   -0.0183000
+43043.00   0.210280   0.170763  -0.0204622    0.256000    0.180000   -0.0215000
+43044.00   0.208015   0.168926  -0.0241649    0.255000    0.177000   -0.0247000
+43045.00   0.205788   0.167116  -0.0279605    0.254000    0.175000   -0.0280000
+43046.00   0.203607   0.165330  -0.0317496    0.252000    0.172000   -0.0313000
+43047.00   0.201482   0.163560  -0.0354420    0.251000    0.170000   -0.0345000
+43048.00   0.199423   0.161799  -0.0389851    0.249000    0.167000   -0.0378000
+43049.00   0.197443   0.160038  -0.0423772    0.248000    0.165000   -0.0411000
+43050.00   0.195556   0.158267  -0.0456595    0.246000    0.163000   -0.0444000
+43051.00   0.193761   0.156476  -0.0488942    0.245000    0.161000   -0.0477000
+43052.00   0.192049   0.154657  -0.0521409    0.243000    0.158000   -0.0509000
+43053.00   0.190412   0.152802  -0.0554420    0.242000    0.156000   -0.0542000
+43054.00   0.188844   0.150901  -0.0588172    0.240000    0.154000   -0.0575000
+43055.00   0.187338   0.148947  -0.0622645    0.238000    0.152000   -0.0609000
+43056.00   0.185878   0.146941  -0.0657649    0.236000    0.150000   -0.0642000
+43057.00   0.184444   0.144886  -0.0692867    0.233000    0.147000   -0.0676000
+43058.00   0.183018   0.142781  -0.0727925    0.231000    0.145000   -0.0709000
+43059.00   0.181581   0.140626  -0.0762483    0.229000    0.143000   -0.0743000
+43060.00   0.180116   0.138420  -0.0796288    0.227000    0.141000   -0.0777000
+43061.00   0.178626   0.136163  -0.0829199    0.224000    0.139000   -0.0811000
+43062.00   0.177119   0.133857  -0.0861213    0.222000    0.137000   -0.0846000
+43063.00   0.175602   0.131502  -0.0892462    0.219000    0.135000   -0.0880000
+43064.00   0.174075   0.129107  -0.0923197    0.217000    0.133000   -0.0914000
+43065.00   0.172531   0.126686  -0.0953760    0.214000    0.131000   -0.0948000
+43066.00   0.170964   0.124257  -0.0984571    0.212000    0.129000   -0.0982000
+43067.00   0.169366   0.121837  -0.1016087    0.209000    0.128000   -0.1017000
+43068.00   0.167730   0.119440  -0.1048764    0.207000    0.126000   -0.1051000
+43069.00   0.166052   0.117081  -0.1082973    0.204000    0.124000   -0.1085000
+43070.00   0.164323   0.114771  -0.1118907    0.201000    0.122000   -0.1119000
+43071.00   0.162540   0.112517  -0.1156453    0.198000    0.121000   -0.1153000
+43072.00   0.160699   0.110324  -0.1195118    0.196000    0.119000   -0.1188000
+43073.00   0.158798   0.108199  -0.1234077    0.193000    0.118000   -0.1222000
+43074.00   0.156836   0.106147  -0.1272383    0.190000    0.116000   -0.1256000
+43075.00   0.154807   0.104176  -0.1309265    0.187000    0.114000   -0.1290000
+43076.00   0.152708   0.102291  -0.1344389    0.184000    0.113000   -0.1324000
+43077.00   0.150532   0.100493  -0.1377922    0.181000    0.111000   -0.1358000
+43078.00   0.148275   0.098774  -0.1410399    0.178000    0.110000   -0.1392000
+43079.00   0.145933   0.097124  -0.1442462    0.175000    0.108000   -0.1426000
+43080.00   0.143504   0.095532  -0.1474621    0.172000    0.106000   -0.1459000
+43081.00   0.140986   0.093990  -0.1507129    0.169000    0.104000   -0.1492000
+43082.00   0.138378   0.092491  -0.1540004    0.165000    0.103000   -0.1526000
+43083.00   0.135685   0.091033  -0.1573108    0.162000    0.101000   -0.1559000
+43084.00   0.132909   0.089609  -0.1606205    0.159000    0.099000   -0.1592000
+43085.00   0.130046   0.088210  -0.1638992    0.156000    0.097000   -0.1624000
+43086.00   0.127091   0.086820  -0.1671159    0.152000    0.096000   -0.1656000
+43087.00   0.124040   0.085427  -0.1702435    0.149000    0.094000   -0.1687000
+43088.00   0.120887   0.084023  -0.1732639    0.145000    0.093000   -0.1719000
+43089.00   0.117629   0.082602  -0.1761719    0.142000    0.091000   -0.1751000
+43090.00   0.114259   0.081160  -0.1789766    0.139000    0.090000   -0.1782000
+43091.00   0.110789   0.079701  -0.1817006    0.135000    0.088000   -0.1813000
+43092.00   0.107237   0.078236  -0.1843763    0.132000    0.087000   -0.1843000
+43093.00   0.103622   0.076775  -0.1870431    0.128000    0.085000   -0.1874000
+43094.00   0.099976   0.075327  -0.1897447    0.125000    0.084000   -0.1905000
+43095.00   0.096332   0.073900  -0.1925243    0.122000    0.083000   -0.1935000
+43096.00   0.092723   0.072502  -0.1954200    0.118000    0.081000   -0.1965000
+43097.00   0.089176   0.071137  -0.1984565    0.115000    0.080000   -0.1995000
+43098.00   0.085713   0.069805  -0.2016370    0.111000    0.078000   -0.2025000
+43099.00   0.082352   0.068506  -0.2049362    0.108000    0.077000   -0.2055000
+43100.00   0.079093   0.067245  -0.2083012    0.105000    0.076000   -0.2085000
+43101.00   0.075922   0.066036  -0.2116598    0.101000    0.075000   -0.2115000
+43102.00   0.072820   0.064892  -0.2149386    0.098000    0.073000   -0.2145000
+43103.00   0.069783   0.063821  -0.2180867    0.094000    0.072000   -0.2175000
+43104.00   0.066805   0.062834  -0.2210963    0.091000    0.071000   -0.2205000
+43105.00   0.063885   0.061943  -0.2240040    0.088000    0.070000   -0.2235000
+43106.00   0.061019   0.061152  -0.2268716    0.084000    0.070000   -0.2265000
+43107.00   0.058197   0.060458  -0.2297588    0.081000    0.069000   -0.2294000
+43108.00   0.055414   0.059859  -0.2327027    0.077000    0.069000   -0.2324000
+43109.00   0.052661   0.059348  -0.2357106    0.074000    0.068000   -0.2354000
+43110.00   0.049933   0.058916  -0.2387657    0.071000    0.068000   -0.2384000
+43111.00   0.047221   0.058557  -0.2418399    0.068000    0.067000   -0.2414000
+43112.00   0.044512   0.058263  -0.2449021    0.064000    0.067000   -0.2444000
+43113.00   0.041779   0.058026  -0.2479232    0.061000    0.066000   -0.2474000
+43114.00   0.038999   0.057837  -0.2508785    0.058000    0.066000   -0.2504000
+43115.00   0.036147   0.057695  -0.2537501    0.054000    0.066000   -0.2534000
+43116.00   0.033197   0.057603  -0.2565310    0.051000    0.066000   -0.2564000
+43117.00   0.030129   0.057561  -0.2592275    0.047000    0.066000   -0.2595000
+43118.00   0.026940   0.057570  -0.2618595    0.044000    0.066000   -0.2625000
+43119.00   0.023629   0.057629  -0.2644568    0.040000    0.066000   -0.2655000
+43120.00   0.020197   0.057738  -0.2670559    0.036000    0.066000   -0.2685000
+43121.00   0.016660   0.057894  -0.2696957    0.033000    0.066000   -0.2715000
+43122.00   0.013042   0.058091  -0.2724142    0.029000    0.066000   -0.2745000
+43123.00   0.009367   0.058325  -0.2752438    0.026000    0.066000   -0.2775000
+43124.00   0.005650   0.058591  -0.2782053    0.022000    0.066000   -0.2805000
+43125.00   0.001900   0.058889  -0.2813018    0.018000    0.066000   -0.2834000
+43126.00  -0.001873   0.059217  -0.2845144    0.015000    0.066000   -0.2864000
+43127.00  -0.005671   0.059580  -0.2878015    0.011000    0.067000   -0.2893000
+43128.00  -0.009501   0.059986  -0.2911032    0.008000    0.067000   -0.2923000
+43129.00  -0.013371   0.060446  -0.2943538    0.004000    0.067000   -0.2952000
+43130.00  -0.017289   0.060970  -0.2974989    0.000000    0.067000   -0.2981000
+43131.00  -0.021259   0.061568  -0.3005132   -0.003000    0.068000   -0.3010000
+43132.00  -0.025285   0.062241  -0.3034101   -0.007000    0.068000   -0.3038000
+43133.00  -0.029368   0.062994  -0.3062365   -0.010000    0.069000   -0.3067000
+43134.00  -0.033512   0.063830  -0.3090520   -0.014000    0.069000   -0.3096000
+43135.00  -0.037719   0.064751  -0.3119048   -0.018000    0.070000   -0.3124000
+43136.00  -0.041989   0.065763  -0.3148158   -0.021000    0.070000   -0.3153000
+43137.00  -0.046322   0.066870  -0.3177753   -0.025000    0.071000   -0.3181000
+43138.00  -0.050717   0.068076  -0.3207530   -0.028000    0.071000   -0.3210000
+43139.00  -0.055176   0.069388  -0.3237125   -0.032000    0.072000   -0.3238000
+43140.00  -0.059698   0.070808  -0.3266212   -0.035000    0.073000   -0.3265000
+43141.00  -0.064273   0.072331  -0.3294534   -0.039000    0.074000   -0.3293000
+43142.00  -0.068888   0.073951  -0.3321916   -0.042000    0.074000   -0.3320000
+43143.00  -0.073529   0.075660  -0.3348284   -0.046000    0.075000   -0.3348000
+43144.00  -0.078182   0.077451   0.6626318   -0.049000    0.076000    0.6625000
+43145.00  -0.082831   0.079316   0.6601714   -0.052000    0.077000    0.6597000
+43146.00  -0.087456   0.081248   0.6577609   -0.056000    0.079000    0.6569000
+43147.00  -0.092040   0.083241   0.6553626   -0.059000    0.080000    0.6542000
+43148.00  -0.096564   0.085288   0.6529353   -0.063000    0.082000    0.6514000
+43149.00  -0.101010   0.087382   0.6504376   -0.066000    0.083000    0.6486000
+43150.00  -0.105357   0.089515   0.6478336   -0.069000    0.085000    0.6458000
+43151.00  -0.109588   0.091680   0.6450997   -0.073000    0.087000    0.6430000
+43152.00  -0.113685   0.093870   0.6422322   -0.076000    0.088000    0.6403000
+43153.00  -0.117633   0.096076   0.6392508   -0.080000    0.090000    0.6375000
+43154.00  -0.121416   0.098289   0.6361975   -0.083000    0.092000    0.6347000
+43155.00  -0.125019   0.100498   0.6331285   -0.086000    0.094000    0.6319000
+43156.00  -0.128428   0.102693   0.6301016   -0.090000    0.096000    0.6291000
+43157.00  -0.131651   0.104872   0.6271638   -0.093000    0.098000    0.6264000
+43158.00  -0.134713   0.107036   0.6243384   -0.097000    0.100000    0.6236000
+43159.00  -0.137636   0.109191   0.6216184   -0.100000    0.102000    0.6208000
+43160.00  -0.140438   0.111338   0.6189663   -0.103000    0.104000    0.6180000
+43161.00  -0.143137   0.113481   0.6163259   -0.106000    0.107000    0.6152000
+43162.00  -0.145749   0.115623   0.6136413   -0.110000    0.109000    0.6125000
+43163.00  -0.148288   0.117769   0.6108770   -0.113000    0.112000    0.6097000
+43164.00  -0.150769   0.119923   0.6080291   -0.116000    0.114000    0.6069000
+43165.00  -0.153209   0.122089   0.6051233   -0.119000    0.117000    0.6042000
+43166.00  -0.155619   0.124269   0.6022025   -0.122000    0.120000    0.6015000
+43167.00  -0.158001   0.126466   0.5993115   -0.126000    0.122000    0.5987000
+43168.00  -0.160358   0.128681   0.5964868   -0.129000    0.125000    0.5960000
+43169.00  -0.162693   0.130919   0.5937527   -0.132000    0.128000    0.5933000
+43170.00  -0.165008   0.133184   0.5911218   -0.135000    0.131000    0.5906000
+43171.00  -0.167302   0.135480   0.5885942   -0.138000    0.134000    0.5879000
+43172.00  -0.169575   0.137814   0.5861572   -0.142000    0.137000    0.5853000
+43173.00  -0.171822   0.140189   0.5837852   -0.145000    0.140000    0.5826000
+43174.00  -0.174043   0.142610   0.5814415   -0.148000    0.143000    0.5799000
+43175.00  -0.176244   0.145082   0.5790819   -0.151000    0.146000    0.5773000
+43176.00  -0.178434   0.147612   0.5766600   -0.154000    0.149000    0.5746000
+43177.00  -0.180620   0.150203   0.5741326   -0.157000    0.153000    0.5720000
+43178.00  -0.182809   0.152861   0.5714666   -0.160000    0.156000    0.5693000
+43179.00  -0.185006   0.155592   0.5686478   -0.163000    0.159000    0.5667000
+43180.00  -0.187216   0.158401   0.5656889   -0.166000    0.162000    0.5641000
+43181.00  -0.189444   0.161298   0.5626312   -0.169000    0.166000    0.5614000
+43182.00  -0.191697   0.164290   0.5595370   -0.172000    0.169000    0.5588000
+43183.00  -0.193973   0.167373   0.5564734   -0.175000    0.173000    0.5561000
+43184.00  -0.196266   0.170544   0.5534939   -0.178000    0.176000    0.5535000
+43185.00  -0.198571   0.173796   0.5506249   -0.181000    0.180000    0.5509000
+43186.00  -0.200881   0.177122   0.5478609   -0.184000    0.183000    0.5482000
+43187.00  -0.203191   0.180515   0.5451674   -0.186000    0.187000    0.5456000
+43188.00  -0.205494   0.183966   0.5424907   -0.189000    0.190000    0.5429000
+43189.00  -0.207785   0.187470   0.5397734   -0.192000    0.194000    0.5403000
+43190.00  -0.210053   0.191017   0.5369705   -0.194000    0.198000    0.5376000
+43191.00  -0.212281   0.194602   0.5340632   -0.197000    0.201000    0.5349000
+43192.00  -0.214452   0.198216   0.5310624   -0.199000    0.205000    0.5322000
+43193.00  -0.216553   0.201853   0.5280040   -0.202000    0.208000    0.5295000
+43194.00  -0.218572   0.205506   0.5249359   -0.204000    0.212000    0.5268000
+43195.00  -0.220498   0.209170   0.5219041   -0.206000    0.216000    0.5240000
+43196.00  -0.222323   0.212838   0.5189433   -0.208000    0.219000    0.5212000
+43197.00  -0.224035   0.216503   0.5160743   -0.210000    0.223000    0.5185000
+43198.00  -0.225626   0.220158   0.5133038   -0.212000    0.226000    0.5157000
+43199.00  -0.227088   0.223796   0.5106251   -0.214000    0.230000    0.5129000
+43200.00  -0.228413   0.227410   0.5080187   -0.216000    0.234000    0.5100000
+43201.00  -0.229592   0.230994   0.5054527   -0.217000    0.237000    0.5071000
+43202.00  -0.230618   0.234542   0.5028868   -0.219000    0.241000    0.5041000
+43203.00  -0.231493   0.238056   0.5002744   -0.220000    0.244000    0.5012000
+43204.00  -0.232225   0.241545   0.4975693   -0.222000    0.248000    0.4983000
+43205.00  -0.232824   0.245014   0.4947312   -0.223000    0.252000    0.4954000
+43206.00  -0.233299   0.248473   0.4917340   -0.224000    0.256000    0.4925000
+43207.00  -0.233660   0.251931   0.4885759   -0.226000    0.259000    0.4895000
+43208.00  -0.233915   0.255398   0.4852872   -0.227000    0.263000    0.4866000
+43209.00  -0.234077   0.258884   0.4819292   -0.228000    0.267000    0.4837000
+43210.00  -0.234156   0.262400   0.4785808   -0.229000    0.271000    0.4807000
+43211.00  -0.234164   0.265954   0.4753155   -0.230000    0.275000    0.4777000
+43212.00  -0.234116   0.269558   0.4721797   -0.231000    0.278000    0.4748000
+43213.00  -0.234025   0.273222   0.4691810   -0.232000    0.282000    0.4718000
+43214.00  -0.233903   0.276956   0.4662904   -0.233000    0.286000    0.4688000
+43215.00  -0.233757   0.280757   0.4634546   -0.234000    0.290000    0.4658000
+43216.00  -0.233593   0.284619   0.4606137   -0.235000    0.294000    0.4627000
+43217.00  -0.233417   0.288535   0.4577165   -0.235000    0.297000    0.4597000
+43218.00  -0.233234   0.292501   0.4547318   -0.236000    0.301000    0.4566000
+43219.00  -0.233050   0.296512   0.4516527   -0.237000    0.305000    0.4536000
+43220.00  -0.232852   0.300562   0.4484970   -0.237000    0.309000    0.4505000
+43221.00  -0.232628   0.304642   0.4453000   -0.237000    0.313000    0.4474000
+43222.00  -0.232363   0.308747   0.4421034   -0.238000    0.316000    0.4444000
+43223.00  -0.232043   0.312871   0.4389447   -0.238000    0.320000    0.4413000
+43224.00  -0.231654   0.317004   0.4358503   -0.238000    0.324000    0.4382000
+43225.00  -0.231184   0.321135   0.4328343   -0.238000    0.328000    0.4350000
+43226.00  -0.230620   0.325247   0.4298967   -0.238000    0.332000    0.4319000
+43227.00  -0.229953   0.329327   0.4270241   -0.237000    0.335000    0.4287000
+43228.00  -0.229171   0.333361   0.4241914   -0.237000    0.339000    0.4256000
+43229.00  -0.228262   0.337335   0.4213638   -0.237000    0.343000    0.4224000
+43230.00  -0.227216   0.341235   0.4184999   -0.237000    0.347000    0.4192000
+43231.00  -0.226025   0.345047   0.4155560   -0.236000    0.351000    0.4160000
+43232.00  -0.224684   0.348760   0.4124907   -0.236000    0.354000    0.4129000
+43233.00  -0.223197   0.352373   0.4092696   -0.235000    0.358000    0.4097000
+43234.00  -0.221567   0.355890   0.4058751   -0.235000    0.362000    0.4065000
+43235.00  -0.219801   0.359314   0.4023164   -0.234000    0.365000    0.4033000
+43236.00  -0.217905   0.362650   0.3986364   -0.234000    0.369000    0.4000000
+43237.00  -0.215888   0.365903   0.3949074   -0.233000    0.372000    0.3968000
+43238.00  -0.213757   0.369077   0.3912141   -0.233000    0.376000    0.3935000
+43239.00  -0.211521   0.372177   0.3876271   -0.232000    0.379000    0.3903000
+43240.00  -0.209204   0.375211   0.3841797   -0.231000    0.382000    0.3870000
+43241.00  -0.206833   0.378192   0.3808609   -0.230000    0.385000    0.3838000
+43242.00  -0.204436   0.381129   0.3776260   -0.228000    0.389000    0.3805000
+43243.00  -0.202037   0.384034   0.3744170   -0.227000    0.392000    0.3773000
+43244.00  -0.199634   0.386910   0.3711831   -0.226000    0.395000    0.3740000
+43245.00  -0.197223   0.389761   0.3678933   -0.224000    0.398000    0.3707000
+43246.00  -0.194800   0.392590   0.3645398   -0.222000    0.401000    0.3674000
+43247.00  -0.192364   0.395402   0.3611356   -0.221000    0.405000    0.3641000
+43248.00  -0.189909   0.398198   0.3577092   -0.219000    0.408000    0.3608000
+43249.00  -0.187432   0.400979   0.3542975   -0.217000    0.411000    0.3575000
+43250.00  -0.184928   0.403743   0.3509383   -0.215000    0.414000    0.3542000
+43251.00  -0.182393   0.406489   0.3476626   -0.213000    0.417000    0.3509000
+43252.00  -0.179824   0.409217   0.3444889   -0.210000    0.420000    0.3476000
+43253.00  -0.177220   0.411927   0.3414210   -0.208000    0.423000    0.3443000
+43254.00  -0.174581   0.414621   0.3384487   -0.206000    0.426000    0.3410000
+43255.00  -0.171908   0.417300   0.3355486   -0.204000    0.429000    0.3377000
+43256.00  -0.169202   0.419965   0.3326873   -0.201000    0.432000    0.3345000
+43257.00  -0.166465   0.422621   0.3298248   -0.199000    0.435000    0.3312000
+43258.00  -0.163700   0.425272   0.3269178   -0.196000    0.438000    0.3280000
+43259.00  -0.160921   0.427918   0.3239247   -0.194000    0.441000    0.3247000
+43260.00  -0.158151   0.430559   0.3208092   -0.191000    0.444000    0.3215000
+43261.00  -0.155409   0.433193   0.3175457   -0.189000    0.446000    0.3183000
+43262.00  -0.152699   0.435805   0.3141276   -0.186000    0.449000    0.3150000
+43263.00  -0.150019   0.438383   0.3105747   -0.184000    0.451000    0.3118000
+43264.00  -0.147367   0.440911   0.3069376   -0.181000    0.454000    0.3086000
+43265.00  -0.144737   0.443377   0.3032920   -0.178000    0.457000    0.3054000
+43266.00  -0.142125   0.445774   0.2997180   -0.175000    0.459000    0.3022000
+43267.00  -0.139531   0.448096   0.2962739   -0.173000    0.462000    0.2991000
+43268.00  -0.136957   0.450348   0.2929751   -0.170000    0.464000    0.2959000
+43269.00  -0.134402   0.452536   0.2897933   -0.167000    0.467000    0.2927000
+43270.00  -0.131868   0.454667   0.2866728   -0.164000    0.469000    0.2896000
+43271.00  -0.129341   0.456743   0.2835566   -0.161000    0.471000    0.2865000
+43272.00  -0.126805   0.458766   0.2804070   -0.158000    0.474000    0.2833000
+43273.00  -0.124248   0.460739   0.2772138   -0.155000    0.476000    0.2802000
+43274.00  -0.121648   0.462667   0.2739915   -0.152000    0.478000    0.2771000
+43275.00  -0.118986   0.464559   0.2707687   -0.149000    0.480000    0.2741000
+43276.00  -0.116243   0.466423   0.2675802   -0.145000    0.482000    0.2710000
+43277.00  -0.113404   0.468267   0.2644600   -0.142000    0.483000    0.2680000
+43278.00  -0.110466   0.470091   0.2614370   -0.138000    0.485000    0.2649000
+43279.00  -0.107435   0.471893   0.2585308   -0.135000    0.487000    0.2619000
+43280.00  -0.104316   0.473673   0.2557486   -0.131000    0.488000    0.2590000
+43281.00  -0.101114   0.475428   0.2530837   -0.128000    0.490000    0.2560000
+43282.00  -0.097835   0.477158   0.2505171   -0.124000    0.491000    0.2531000
+43283.00  -0.094479   0.478858   0.2480201   -0.121000    0.493000    0.2501000
+43284.00  -0.091047   0.480525   0.2455580   -0.117000    0.494000    0.2472000
+43285.00  -0.087541   0.482158   0.2430929   -0.113000    0.495000    0.2444000
+43286.00  -0.083960   0.483754   0.2405877   -0.109000    0.496000    0.2416000
+43287.00  -0.080306   0.485308   0.2380093   -0.105000    0.497000    0.2388000
+43288.00  -0.076579   0.486820   0.2353333   -0.101000    0.498000    0.2360000
+43289.00  -0.072781   0.488284   0.2325485   -0.097000    0.499000    0.2332000
+43290.00  -0.068911   0.489700   0.2296621   -0.093000    0.500000    0.2305000
+43291.00  -0.064971   0.491064   0.2267043   -0.089000    0.500000    0.2278000
+43292.00  -0.060961   0.492372   0.2237282   -0.084000    0.501000    0.2251000
+43293.00  -0.056883   0.493623   0.2208005   -0.080000    0.501000    0.2224000
+43294.00  -0.052743   0.494815   0.2179811   -0.076000    0.502000    0.2197000
+43295.00  -0.048549   0.495946   0.2153028   -0.072000    0.503000    0.2172000
+43296.00  -0.044308   0.497014   0.2127578   -0.067000    0.503000    0.2146000
+43297.00  -0.040027   0.498019   0.2103014   -0.063000    0.504000    0.2121000
+43298.00  -0.035714   0.498957   0.2078726   -0.058000    0.504000    0.2095000
+43299.00  -0.031377   0.499829   0.2054199   -0.054000    0.505000    0.2070000
+43300.00  -0.027023   0.500632   0.2029206   -0.050000    0.505000    0.2046000
+43301.00  -0.022658   0.501365   0.2003829   -0.045000    0.506000    0.2021000
+43302.00  -0.018292   0.502026   0.1978364   -0.041000    0.506000    0.1997000
+43303.00  -0.013929   0.502613   0.1953189   -0.036000    0.507000    0.1972000
+43304.00  -0.009571   0.503126   0.1928660   -0.032000    0.507000    0.1948000
+43305.00  -0.005223   0.503562   0.1905050   -0.027000    0.507000    0.1925000
+43306.00  -0.000887   0.503920   0.1882536   -0.023000    0.507000    0.1902000
+43307.00   0.003430   0.504204   0.1861192   -0.018000    0.508000    0.1878000
+43308.00   0.007721   0.504419   0.1840966   -0.014000    0.508000    0.1855000
+43309.00   0.011979   0.504571   0.1821681   -0.009000    0.508000    0.1832000
+43310.00   0.016202   0.504661   0.1803069   -0.004000    0.508000    0.1810000
+43311.00   0.020388   0.504691   0.1784795    0.000000    0.508000    0.1788000
+43312.00   0.024538   0.504661   0.1766499    0.005000    0.508000    0.1765000
+43313.00   0.028650   0.504573   0.1747829    0.009000    0.508000    0.1743000
+43314.00   0.032724   0.504425   0.1728472    0.014000    0.508000    0.1721000
+43315.00   0.036766   0.504209   0.1708190    0.018000    0.507000    0.1700000
+43316.00   0.040780   0.503916   0.1686870    0.023000    0.507000    0.1679000
+43317.00   0.044771   0.503537   0.1664562    0.027000    0.506000    0.1658000
+43318.00   0.048745   0.503064   0.1641497    0.032000    0.506000    0.1637000
+43319.00   0.052704   0.502488   0.1618082    0.036000    0.505000    0.1616000
+43320.00   0.056653   0.501798   0.1594844    0.040000    0.504000    0.1596000
+43321.00   0.060594   0.500987   0.1572312    0.045000    0.503000    0.1576000
+43322.00   0.064541   0.500045   0.1550854    0.049000    0.503000    0.1556000
+43323.00   0.068508   0.498965   0.1530532    0.054000    0.502000    0.1536000
+43324.00   0.072512   0.497736   0.1511055    0.058000    0.501000    0.1516000
+43325.00   0.076569   0.496352   0.1491874    0.062000    0.500000    0.1497000
+43326.00   0.080691   0.494806   0.1472403    0.067000    0.498000    0.1478000
+43327.00   0.084878   0.493103   0.1452269    0.071000    0.497000    0.1458000
+43328.00   0.089128   0.491249   0.1431446    0.076000    0.495000    0.1439000
+43329.00   0.093441   0.489249   0.1410233    0.080000    0.494000    0.1420000
+43330.00   0.097811   0.487111   0.1389103    0.084000    0.493000    0.1401000
+43331.00   0.102226   0.484849   0.1368509    0.089000    0.491000    0.1382000
+43332.00   0.106665   0.482482   0.1348787    0.093000    0.490000    0.1364000
+43333.00   0.111111   0.480027   0.1330132    0.098000    0.488000    0.1345000
+43334.00   0.115549   0.477496   0.1312618    0.102000    0.487000    0.1326000
+43335.00   0.119963   0.474902   0.1296198    0.106000    0.485000    0.1307000
+43336.00   0.124338   0.472259   0.1280705    0.111000    0.483000    0.1289000
+43337.00   0.128654   0.469581   0.1265848    0.115000    0.482000    0.1270000
+43338.00   0.132889   0.466887   0.1251247    0.120000    0.480000    0.1252000
+43339.00   0.137022   0.464193   0.1236482    0.124000    0.478000    0.1233000
+43340.00   0.141046   0.461511   0.1221143    0.128000    0.476000    0.1215000
+43341.00   0.144961   0.458851   0.1204865    0.132000    0.474000    0.1196000
+43342.00   0.148769   0.456223   0.1187374    0.137000    0.472000    0.1178000
+43343.00   0.152475   0.453630   0.1168530    0.141000    0.470000    0.1159000
+43344.00   0.156086   0.451069   0.1148374    0.145000    0.468000    0.1141000
+43345.00   0.159611   0.448538   0.1127143    0.149000    0.466000    0.1123000
+43346.00   0.163059   0.446031   0.1105254    0.153000    0.464000    0.1105000
+43347.00   0.166440   0.443541   0.1083208    0.157000    0.461000    0.1086000
+43348.00   0.169759   0.441062   0.1061490    0.161000    0.459000    0.1068000
+43349.00   0.173020   0.438590   0.1040455    0.165000    0.457000    0.1050000
+43350.00   0.176223   0.436122   0.1020235    0.169000    0.454000    0.1031000
+43351.00   0.179368   0.433652   0.1000677    0.172000    0.452000    0.1012000
+43352.00   0.182457   0.431178   0.0981372    0.176000    0.449000    0.0994000
+43353.00   0.185491   0.428696   0.0961782    0.179000    0.447000    0.0975000
+43354.00   0.188469   0.426202   0.0941448    0.183000    0.444000    0.0956000
+43355.00   0.191393   0.423697   0.0920173    0.186000    0.441000    0.0937000
+43356.00   0.194260   0.421184   0.0898110    0.190000    0.439000    0.0918000
+43357.00   0.197068   0.418666   0.0875704    0.193000    0.436000    0.0900000
+43358.00   0.199812   0.416148   0.0853505    0.197000    0.434000    0.0881000
+43359.00   0.202487   0.413635   0.0831987    0.200000    0.431000    0.0862000
+43360.00   0.205086   0.411134   0.0811463    0.203000    0.428000    0.0843000
+43361.00   0.207607   0.408645   0.0792069    0.207000    0.425000    0.0824000
+43362.00   0.210050   0.406167   0.0773793    0.210000    0.422000    0.0804000
+43363.00   0.212415   0.403695   0.0756495    0.214000    0.419000    0.0785000
+43364.00   0.214700   0.401224   0.0739912    0.217000    0.416000    0.0766000
+43365.00   0.216906   0.398749   0.0723674    0.220000    0.413000    0.0746000
+43366.00   0.219033   0.396262   0.0707352    0.223000    0.410000    0.0726000
+43367.00   0.221096   0.393754   0.0690521    0.227000    0.406000    0.0705000
+43368.00   0.223113   0.391214   0.0672798    0.230000    0.403000    0.0685000
+43369.00   0.225102   0.388632   0.0653877    0.233000    0.400000    0.0665000
+43370.00   0.227082   0.385999   0.0633572    0.236000    0.397000    0.0644000
+43371.00   0.229062   0.383309   0.0611873    0.239000    0.393000    0.0622000
+43372.00   0.231045   0.380563   0.0588980    0.241000    0.390000    0.0601000
+43373.00   0.233032   0.377760   0.0565309    0.244000    0.386000    0.0579000
+43374.00   0.235027   0.374900   0.0541403    0.247000    0.383000    0.0558000
+43375.00   0.237031   0.371983   0.0517795    0.250000    0.380000    0.0536000
+43376.00   0.239047   0.369011   0.0494863    0.252000    0.377000    0.0514000
+43377.00   0.241077   0.365981   0.0472730    0.255000    0.373000    0.0491000
+43378.00   0.243123   0.362896   0.0451234    0.257000    0.370000    0.0469000
+43379.00   0.245184   0.359754   0.0429967    0.260000    0.367000    0.0447000
+43380.00   0.247249   0.356560   0.0408378    0.262000    0.364000    0.0423000
+43381.00   0.249300   0.353319   0.0385923    0.265000    0.360000    0.0400000
+43382.00   0.251321   0.350034   0.0362236    0.267000    0.357000    0.0376000
+43383.00   0.253295   0.346710   0.0337251    0.270000    0.353000    0.0353000
+43384.00   0.255206   0.343352   0.0311225    0.272000    0.350000    0.0329000
+43385.00   0.257037   0.339965   0.0284644    0.274000    0.346000    0.0304000
+43386.00   0.258773   0.336553   0.0258056    0.276000    0.343000    0.0279000
+43387.00   0.260403   0.333124   0.0231927    0.278000    0.339000    0.0254000
+43388.00   0.261918   0.329686   0.0206533    0.280000    0.336000    0.0229000
+43389.00   0.263308   0.326247   0.0181958    0.282000    0.332000    0.0204000
+43390.00   0.264561   0.322814   0.0158123    0.283000    0.329000    0.0177000
+43391.00   0.265669   0.319396   0.0134830    0.285000    0.325000    0.0150000
+43392.00   0.266628   0.315994   0.0111780    0.286000    0.322000    0.0123000
+43393.00   0.267445   0.312596   0.0088600    0.288000    0.318000    0.0096000
+43394.00   0.268133   0.309189   0.0064876    0.289000    0.315000    0.0069000
+43395.00   0.268701   0.305760   0.0040210    0.290000    0.311000    0.0041000
+43396.00   0.269160   0.302295   0.0014261    0.291000    0.308000    0.0013000
+43397.00   0.269522   0.298782  -0.0013213    0.292000    0.304000   -0.0015000
+43398.00   0.269796   0.295208  -0.0042306    0.293000    0.301000   -0.0043000
+43399.00   0.269986   0.291573  -0.0072892    0.294000    0.297000   -0.0071000
+43400.00   0.270092   0.287884  -0.0104594    0.295000    0.293000   -0.0100000
+43401.00   0.270114   0.284148  -0.0136818    0.296000    0.289000   -0.0129000
+43402.00   0.270054   0.280373  -0.0168882    0.296000    0.286000   -0.0157000
+43403.00   0.269909   0.276564  -0.0200210    0.297000    0.282000   -0.0186000
+43404.00   0.269682   0.272729  -0.0230495    0.298000    0.278000   -0.0215000
+43405.00   0.269372   0.268874  -0.0259776    0.298000    0.274000   -0.0244000
+43406.00   0.268979   0.265007  -0.0288387    0.298000    0.271000   -0.0274000
+43407.00   0.268504   0.261134  -0.0316835    0.299000    0.267000   -0.0303000
+43408.00   0.267952   0.257254  -0.0345648    0.299000    0.264000   -0.0333000
+43409.00   0.267328   0.253366  -0.0375231    0.299000    0.260000   -0.0362000
+43410.00   0.266637   0.249467  -0.0405750    0.299000    0.256000   -0.0392000
+43411.00   0.265886   0.245557  -0.0437097    0.299000    0.252000   -0.0422000
+43412.00   0.265079   0.241635  -0.0468915    0.299000    0.249000   -0.0451000
+43413.00   0.264214   0.237704  -0.0500708    0.299000    0.245000   -0.0481000
+43414.00   0.263284   0.233771  -0.0531981    0.299000    0.241000   -0.0511000
+43415.00   0.262283   0.229846  -0.0562362    0.298000    0.237000   -0.0541000
+43416.00   0.261204   0.225936  -0.0591666    0.298000    0.233000   -0.0571000
+43417.00   0.260040   0.222048  -0.0619897    0.297000    0.230000   -0.0601000
+43418.00   0.258791   0.218186  -0.0647210    0.297000    0.226000   -0.0631000
+43419.00   0.257454   0.214353  -0.0673890    0.296000    0.222000   -0.0661000
+43420.00   0.256033   0.210549  -0.0700321    0.295000    0.218000   -0.0692000
+43421.00   0.254546   0.206766  -0.0726932    0.294000    0.214000   -0.0723000
+43422.00   0.253012   0.202993  -0.0754167    0.293000    0.211000   -0.0755000
+43423.00   0.251451   0.199220  -0.0782432    0.292000    0.207000   -0.0786000
+43424.00   0.249883   0.195435  -0.0812060    0.291000    0.203000   -0.0817000
+43425.00   0.248334   0.191630  -0.0843280    0.289000    0.199000   -0.0849000
+43426.00   0.246824   0.187794  -0.0876157    0.288000    0.195000   -0.0881000
+43427.00   0.245357   0.183928  -0.0910496    0.286000    0.192000   -0.0912000
+43428.00   0.243924   0.180034  -0.0945828    0.285000    0.188000   -0.0944000
+43429.00   0.242517   0.176116  -0.0981487    0.283000    0.184000   -0.0976000
+43430.00   0.241125   0.172177  -0.1016771    0.281000    0.180000   -0.1009000
+43431.00   0.239742   0.168223  -0.1051158    0.279000    0.177000   -0.1041000
+43432.00   0.238365   0.164261  -0.1084474    0.277000    0.173000   -0.1074000
+43433.00   0.236992   0.160299  -0.1116924    0.275000    0.170000   -0.1106000
+43434.00   0.235622   0.156343  -0.1148973    0.273000    0.166000   -0.1139000
+43435.00   0.234244   0.152405  -0.1181151    0.271000    0.163000   -0.1172000
+43436.00   0.232834   0.148495  -0.1213882    0.268000    0.159000   -0.1204000
+43437.00   0.231360   0.144629  -0.1247362    0.266000    0.156000   -0.1237000
+43438.00   0.229791   0.140821  -0.1281541    0.263000    0.152000   -0.1269000
+43439.00   0.228100   0.137082  -0.1316161    0.261000    0.149000   -0.1302000
+43440.00   0.226268   0.133418  -0.1350826    0.258000    0.146000   -0.1334000
+43441.00   0.224273   0.129837  -0.1385092    0.256000    0.142000   -0.1367000
+43442.00   0.222098   0.126344  -0.1418558    0.253000    0.139000   -0.1399000
+43443.00   0.219726   0.122945  -0.1450950    0.251000    0.135000   -0.1432000
+43444.00   0.217146   0.119647  -0.1482166    0.248000    0.132000   -0.1464000
+43445.00   0.214360   0.116453  -0.1512272    0.245000    0.129000   -0.1496000
+43446.00   0.211380   0.113368  -0.1541470    0.242000    0.126000   -0.1528000
+43447.00   0.208216   0.110397  -0.1570059    0.240000    0.122000   -0.1559000
+43448.00   0.204878   0.107544  -0.1598398    0.237000    0.119000   -0.1591000
+43449.00   0.201393   0.104809  -0.1626876    0.234000    0.116000   -0.1623000
+43450.00   0.197804   0.102181  -0.1655874    0.231000    0.113000   -0.1654000
+43451.00   0.194157   0.099653  -0.1685717    0.228000    0.110000   -0.1685000
+43452.00   0.190500   0.097216  -0.1716640    0.226000    0.108000   -0.1716000
+43453.00   0.186872   0.094859  -0.1748758    0.223000    0.105000   -0.1747000
+43454.00   0.183296   0.092575  -0.1782032    0.220000    0.102000   -0.1778000
+43455.00   0.179789   0.090356  -0.1816217    0.217000    0.099000   -0.1809000
+43456.00   0.176367   0.088191  -0.1850845    0.214000    0.097000   -0.1840000
+43457.00   0.173044   0.086073  -0.1885299    0.212000    0.094000   -0.1870000
+43458.00   0.169819   0.083993  -0.1918985    0.209000    0.092000   -0.1901000
+43459.00   0.166678   0.081943  -0.1951549    0.206000    0.089000   -0.1932000
+43460.00   0.163610   0.079914  -0.1983014    0.203000    0.087000   -0.1963000
+43461.00   0.160601   0.077898  -0.2013761    0.200000    0.084000   -0.1994000
+43462.00   0.157639   0.075885  -0.2044350    0.198000    0.082000   -0.2024000
+43463.00   0.154712   0.073867  -0.2075283    0.195000    0.079000   -0.2055000
+43464.00   0.151806   0.071837  -0.2106822    0.192000    0.077000   -0.2086000
+43465.00   0.148908   0.069796  -0.2138939    0.189000    0.075000   -0.2117000
+43466.00   0.146001   0.067748  -0.2171378    0.186000    0.073000   -0.2148000
+43467.00   0.143069   0.065696  -0.2203774    0.184000    0.070000   -0.2178000
+43468.00   0.140096   0.063645  -0.2235741    0.181000    0.068000   -0.2209000
+43469.00   0.137068   0.061601  -0.2266946    0.178000    0.066000   -0.2240000
+43470.00   0.133967   0.059568  -0.2297155    0.175000    0.064000   -0.2271000
+43471.00   0.130783   0.057551  -0.2326260    0.172000    0.062000   -0.2302000
+43472.00   0.127525   0.055548  -0.2354300    0.169000    0.060000   -0.2332000
+43473.00   0.124210   0.053556  -0.2381449    0.166000    0.058000   -0.2363000
+43474.00   0.120857   0.051573  -0.2407984    0.163000    0.056000   -0.2394000
+43475.00   0.117476   0.049596  -0.2434254    0.160000    0.054000   -0.2424000
+43476.00   0.114076   0.047626  -0.2460646    0.157000    0.052000   -0.2455000
+43477.00   0.110660   0.045664  -0.2487541    0.153000    0.051000   -0.2485000
+43478.00   0.107236   0.043711  -0.2515275    0.150000    0.049000   -0.2516000
+43479.00   0.103810   0.041766  -0.2544109    0.147000    0.047000   -0.2546000
+43480.00   0.100399   0.039832  -0.2574196    0.143000    0.045000   -0.2577000
+43481.00   0.097018   0.037907  -0.2605561    0.140000    0.043000   -0.2608000
+43482.00   0.093685   0.035992  -0.2638080    0.136000    0.042000   -0.2640000
+43483.00   0.090413   0.034089  -0.2671458    0.133000    0.040000   -0.2671000
+43484.00   0.087214   0.032206  -0.2705236    0.129000    0.038000   -0.2702000
+43485.00   0.084094   0.030357  -0.2738882    0.125000    0.036000   -0.2734000
+43486.00   0.081061   0.028552  -0.2771957    0.121000    0.035000   -0.2766000
+43487.00   0.078120   0.026806  -0.2804311    0.117000    0.033000   -0.2797000
+43488.00   0.075273   0.025137  -0.2836161    0.113000    0.032000   -0.2829000
+43489.00   0.072525   0.023559  -0.2867999    0.109000    0.030000   -0.2861000
+43490.00   0.069874   0.022086  -0.2900354    0.105000    0.029000   -0.2893000
+43491.00   0.067317   0.020731  -0.2933573    0.101000    0.028000   -0.2925000
+43492.00   0.064853   0.019504  -0.2967677    0.096000    0.026000   -0.2957000
+43493.00   0.062474   0.018405  -0.3002377    0.092000    0.025000   -0.2989000
+43494.00   0.060173   0.017429  -0.3037211    0.088000    0.024000   -0.3021000
+43495.00   0.057942   0.016575  -0.3071703    0.084000    0.023000   -0.3053000
+43496.00   0.055757   0.015844  -0.3105474    0.080000    0.022000   -0.3086000
+43497.00   0.053585   0.015243  -0.3138279    0.075000    0.021000   -0.3118000
+43498.00   0.051390   0.014776  -0.3170006    0.071000    0.020000   -0.3151000
+43499.00   0.049138   0.014450  -0.3200671    0.067000    0.019000   -0.3183000
+43500.00   0.046792   0.014270  -0.3230414    0.063000    0.018000   -0.3215000
+43501.00   0.044321   0.014241  -0.3259482    0.058000    0.018000   -0.3248000
+43502.00   0.041712   0.014360  -0.3288195    0.054000    0.017000   -0.3280000
+43503.00   0.038970   0.014618  -0.3316910    0.049000    0.017000   -0.3313000
+43504.00   0.036101   0.015005  -0.3345972    0.045000    0.016000   -0.3345000
+43505.00   0.033110   0.015512  -0.3375686    0.041000    0.016000   -0.3377000
+43506.00   0.030003   0.016128  -0.3406283    0.036000    0.016000   -0.3410000
+43507.00   0.026786   0.016844  -0.3437893    0.032000    0.015000   -0.3442000
+43508.00   0.023463   0.017651  -0.3470520    0.027000    0.015000   -0.3475000
+43509.00   0.020040   0.018540   0.6495968    0.023000    0.015000    0.6493000
+43510.00   0.016522   0.019499   0.6461826    0.019000    0.015000    0.6461000
+43511.00   0.012916   0.020520   0.6427420    0.015000    0.015000    0.6429000
+43512.00   0.009227   0.021594   0.6393177    0.011000    0.015000    0.6398000
+43513.00   0.005460   0.022710   0.6359491    0.007000    0.015000    0.6366000
+43514.00   0.001620   0.023858   0.6326596    0.003000    0.015000    0.6334000
+43515.00  -0.002286   0.025031   0.6294446   -0.001000    0.016000    0.6303000
+43516.00  -0.006254   0.026216   0.6262694   -0.005000    0.016000    0.6271000
+43517.00  -0.010278   0.027406   0.6230813   -0.008000    0.017000    0.6240000
+43518.00  -0.014352   0.028591   0.6198327   -0.012000    0.017000    0.6208000
+43519.00  -0.018472   0.029769   0.6165018   -0.016000    0.018000    0.6177000
+43520.00  -0.022634   0.030938   0.6131041   -0.020000    0.019000    0.6146000
+43521.00  -0.026834   0.032100   0.6096852   -0.024000    0.020000    0.6115000
+43522.00  -0.031067   0.033253   0.6063026   -0.027000    0.021000    0.6083000
+43523.00  -0.035329   0.034397   0.6030057   -0.031000    0.022000    0.6052000
+43524.00  -0.039617   0.035533   0.5998260   -0.035000    0.023000    0.6021000
+43525.00  -0.043925   0.036659   0.5967754   -0.039000    0.024000    0.5990000
+43526.00  -0.048250   0.037777   0.5938494   -0.042000    0.026000    0.5960000
+43527.00  -0.052587   0.038885   0.5910312   -0.046000    0.027000    0.5929000
+43528.00  -0.056933   0.039983   0.5882930   -0.049000    0.029000    0.5899000
+43529.00  -0.061283   0.041071   0.5855990   -0.053000    0.030000    0.5868000
+43530.00  -0.065632   0.042149   0.5829089   -0.057000    0.032000    0.5838000
+43531.00  -0.069978   0.043217   0.5801827   -0.060000    0.033000    0.5807000
+43532.00  -0.074314   0.044276   0.5773848   -0.064000    0.035000    0.5777000
+43533.00  -0.078629   0.045329   0.5744866   -0.067000    0.036000    0.5746000
+43534.00  -0.082914   0.046382   0.5714703   -0.071000    0.038000    0.5716000
+43535.00  -0.087156   0.047440   0.5683313   -0.075000    0.040000    0.5685000
+43536.00  -0.091345   0.048508   0.5650802   -0.079000    0.042000    0.5654000
+43537.00  -0.095469   0.049592   0.5617421   -0.082000    0.045000    0.5623000
+43538.00  -0.099518   0.050695   0.5583520   -0.086000    0.047000    0.5592000
+43539.00  -0.103479   0.051823   0.5549479   -0.090000    0.049000    0.5561000
+43540.00  -0.107343   0.052982   0.5515624   -0.094000    0.051000    0.5529000
+43541.00  -0.111101   0.054176   0.5482159   -0.097000    0.054000    0.5497000
+43542.00  -0.114749   0.055410   0.5449082   -0.101000    0.056000    0.5465000
+43543.00  -0.118282   0.056689   0.5416135   -0.104000    0.059000    0.5433000
+43544.00  -0.121695   0.058017   0.5382847   -0.108000    0.061000    0.5401000
+43545.00  -0.124985   0.059400   0.5348688   -0.111000    0.063000    0.5367000
+43546.00  -0.128145   0.060842   0.5313286   -0.114000    0.066000    0.5333000
+43547.00  -0.131173   0.062348   0.5276610   -0.118000    0.068000    0.5300000
+43548.00  -0.134063   0.063923   0.5239011   -0.121000    0.071000    0.5266000
+43549.00  -0.136811   0.065571   0.5201109   -0.124000    0.073000    0.5232000
+43550.00  -0.139412   0.067299   0.5163583   -0.127000    0.076000    0.5197000
+43551.00  -0.141862   0.069109   0.5126973   -0.130000    0.078000    0.5162000
+43552.00  -0.144157   0.071007   0.5091584   -0.133000    0.081000    0.5128000
+43553.00  -0.146306   0.072987   0.5057484   -0.136000    0.083000    0.5093000
+43554.00  -0.148325   0.075040   0.5024562   -0.139000    0.086000    0.5058000
+43555.00  -0.150229   0.077157   0.4992585   -0.142000    0.089000    0.5023000
+43556.00  -0.152032   0.079328   0.4961223   -0.145000    0.091000    0.4988000
+43557.00  -0.153750   0.081544   0.4930084   -0.148000    0.094000    0.4952000
+43558.00  -0.155398   0.083795   0.4898759   -0.151000    0.096000    0.4917000
+43559.00  -0.156991   0.086073   0.4866864   -0.154000    0.099000    0.4882000
+43560.00  -0.158545   0.088367   0.4834090   -0.157000    0.102000    0.4847000
+43561.00  -0.160073   0.090673   0.4800234   -0.160000    0.104000    0.4812000
+43562.00  -0.161591   0.092993   0.4765236   -0.162000    0.107000    0.4776000
+43563.00  -0.163112   0.095331   0.4729200   -0.165000    0.109000    0.4741000
+43564.00  -0.164649   0.097691   0.4692407   -0.168000    0.112000    0.4706000
+43565.00  -0.166217   0.100078   0.4655291   -0.171000    0.115000    0.4671000
+43566.00  -0.167826   0.102497   0.4618338   -0.174000    0.118000    0.4636000
+43567.00  -0.169483   0.104958   0.4581963   -0.176000    0.120000    0.4602000
+43568.00  -0.171196   0.107469   0.4546412   -0.179000    0.123000    0.4567000
+43569.00  -0.172969   0.110041   0.4511691   -0.182000    0.126000    0.4532000
+43570.00  -0.174810   0.112681   0.4477555   -0.185000    0.129000    0.4498000
+43571.00  -0.176725   0.115401   0.4443550   -0.187000    0.132000    0.4464000
+43572.00  -0.178721   0.118208   0.4409123   -0.190000    0.136000    0.4429000
+43573.00  -0.180803   0.121112   0.4373785   -0.192000    0.139000    0.4395000
+43574.00  -0.182979   0.124123   0.4337276   -0.195000    0.142000    0.4361000
+43575.00  -0.185247   0.127245   0.4299692   -0.197000    0.146000    0.4328000
+43576.00  -0.187587   0.130475   0.4261477   -0.199000    0.149000    0.4294000
+43577.00  -0.189978   0.133808   0.4223286   -0.202000    0.153000    0.4261000
+43578.00  -0.192398   0.137237   0.4185771   -0.204000    0.156000    0.4227000
+43579.00  -0.194826   0.140760   0.4149412   -0.206000    0.160000    0.4194000
+43580.00  -0.197240   0.144369   0.4114441   -0.208000    0.164000    0.4161000
+43581.00  -0.199617   0.148061   0.4080856   -0.210000    0.168000    0.4128000
+43582.00  -0.201929   0.151830   0.4048488   -0.212000    0.172000    0.4096000
+43583.00  -0.204152   0.155670   0.4017049   -0.214000    0.176000    0.4063000
+43584.00  -0.206260   0.159578   0.3986177   -0.216000    0.180000    0.4030000
+43585.00  -0.208229   0.163547   0.3955460   -0.218000    0.184000    0.3997000
+43586.00  -0.210050   0.167578   0.3924463   -0.220000    0.188000    0.3964000
+43587.00  -0.211723   0.171670   0.3892796   -0.222000    0.192000    0.3930000
+43588.00  -0.213243   0.175824   0.3860160   -0.224000    0.196000    0.3897000
+43589.00  -0.214610   0.180039   0.3826376   -0.226000    0.200000    0.3864000
+43590.00  -0.215820   0.184315   0.3791411   -0.228000    0.204000    0.3830000
+43591.00  -0.216879   0.188649   0.3755424   -0.229000    0.208000    0.3796000
+43592.00  -0.217801   0.193031   0.3718781   -0.231000    0.212000    0.3762000
+43593.00  -0.218600   0.197451   0.3681999   -0.232000    0.216000    0.3728000
+43594.00  -0.219292   0.201898   0.3645615   -0.234000    0.220000    0.3694000
+43595.00  -0.219892   0.206364   0.3610038   -0.235000    0.224000    0.3660000
+43596.00  -0.220414   0.210837   0.3575414   -0.236000    0.228000    0.3625000
+43597.00  -0.220871   0.215307   0.3541595   -0.238000    0.232000    0.3591000
+43598.00  -0.221278   0.219764   0.3508197   -0.239000    0.236000    0.3556000
+43599.00  -0.221646   0.224195   0.3474716   -0.240000    0.240000    0.3522000
+43600.00  -0.221987   0.228597   0.3440670   -0.241000    0.244000    0.3487000
+43601.00  -0.222313   0.232972   0.3405726   -0.242000    0.248000    0.3452000
+43602.00  -0.222636   0.237325   0.3369818   -0.242000    0.253000    0.3416000
+43603.00  -0.222965   0.241659   0.3333181   -0.243000    0.257000    0.3381000
+43604.00  -0.223290   0.245977   0.3296311   -0.244000    0.261000    0.3346000
+43605.00  -0.223596   0.250283   0.3259824   -0.245000    0.265000    0.3311000
+43606.00  -0.223867   0.254578   0.3224283   -0.245000    0.269000    0.3276000
+43607.00  -0.224091   0.258862   0.3190052   -0.246000    0.274000    0.3240000
+43608.00  -0.224257   0.263134   0.3157250   -0.246000    0.278000    0.3205000
+43609.00  -0.224355   0.267391   0.3125785   -0.247000    0.282000    0.3170000
+43610.00  -0.224376   0.271631   0.3095413   -0.247000    0.286000    0.3135000
+43611.00  -0.224308   0.275854   0.3065796   -0.247000    0.290000    0.3101000
+43612.00  -0.224149   0.280058   0.3036531   -0.248000    0.293000    0.3066000
+43613.00  -0.223913   0.284249   0.3007180   -0.248000    0.297000    0.3032000
+43614.00  -0.223616   0.288433   0.2977329   -0.248000    0.301000    0.2997000
+43615.00  -0.223270   0.292613   0.2946647   -0.248000    0.305000    0.2964000
+43616.00  -0.222878   0.296791   0.2914932   -0.248000    0.309000    0.2930000
+43617.00  -0.222440   0.300969   0.2882108   -0.247000    0.313000    0.2897000
+43618.00  -0.221956   0.305144   0.2848250   -0.247000    0.317000    0.2863000
+43619.00  -0.221413   0.309310   0.2813607   -0.247000    0.321000    0.2830000
+43620.00  -0.220797   0.313452   0.2778616   -0.246000    0.325000    0.2798000
+43621.00  -0.220093   0.317558   0.2743831   -0.246000    0.328000    0.2765000
+43622.00  -0.219285   0.321617   0.2709789   -0.245000    0.332000    0.2733000
+43623.00  -0.218367   0.325616   0.2676812   -0.245000    0.335000    0.2700000
+43624.00  -0.217331   0.329543   0.2644895   -0.244000    0.339000    0.2668000
+43625.00  -0.216175   0.333387   0.2613712   -0.243000    0.342000    0.2636000
+43626.00  -0.214891   0.337134   0.2582750   -0.242000    0.346000    0.2605000
+43627.00  -0.213476   0.340775   0.2551491   -0.241000    0.349000    0.2573000
+43628.00  -0.211925   0.344296   0.2519580   -0.240000    0.353000    0.2542000
+43629.00  -0.210242   0.347698   0.2486897   -0.239000    0.356000    0.2510000
+43630.00  -0.208441   0.350988   0.2453578   -0.238000    0.359000    0.2478000
+43631.00  -0.206533   0.354173   0.2419965   -0.237000    0.363000    0.2446000
+43632.00  -0.204531   0.357260   0.2386522   -0.235000    0.366000    0.2415000
+43633.00  -0.202448   0.360257   0.2353720   -0.234000    0.370000    0.2383000
+43634.00  -0.200298   0.363172   0.2321928   -0.233000    0.373000    0.2351000
+43635.00  -0.198095   0.366014   0.2291324   -0.232000    0.376000    0.2319000
+43636.00  -0.195857   0.368795   0.2261885   -0.230000    0.380000    0.2287000
+43637.00  -0.193599   0.371523   0.2233411   -0.229000    0.383000    0.2256000
+43638.00  -0.191337   0.374210   0.2205588   -0.227000    0.387000    0.2224000
+43639.00  -0.189077   0.376868   0.2178060   -0.226000    0.390000    0.2192000
+43640.00  -0.186824   0.379510   0.2150448   -0.224000    0.393000    0.2160000
+43641.00  -0.184585   0.382150   0.2122382   -0.222000    0.396000    0.2128000
+43642.00  -0.182362   0.384800   0.2093543   -0.220000    0.399000    0.2095000
+43643.00  -0.180143   0.387471   0.2063708   -0.218000    0.402000    0.2063000
+43644.00  -0.177914   0.390173   0.2032768   -0.216000    0.405000    0.2031000
+43645.00  -0.175657   0.392915   0.2000735   -0.214000    0.408000    0.2000000
+43646.00  -0.173361   0.395700   0.1967754   -0.212000    0.410000    0.1969000
+43647.00  -0.171014   0.398527   0.1934123   -0.210000    0.413000    0.1937000
+43648.00  -0.168606   0.401396   0.1900291   -0.208000    0.415000    0.1906000
+43649.00  -0.166125   0.404308   0.1866781   -0.206000    0.418000    0.1875000
+43650.00  -0.163564   0.407259   0.1834043   -0.203000    0.420000    0.1845000
+43651.00  -0.160919   0.410238   0.1802282   -0.201000    0.422000    0.1815000
+43652.00  -0.158192   0.413233   0.1771364   -0.198000    0.425000    0.1786000
+43653.00  -0.155381   0.416231   0.1740874   -0.196000    0.427000    0.1756000
+43654.00  -0.152485   0.419219   0.1710302   -0.193000    0.429000    0.1726000
+43655.00  -0.149505   0.422184   0.1679265   -0.190000    0.431000    0.1697000
+43656.00  -0.146444   0.425115   0.1647655   -0.187000    0.433000    0.1669000
+43657.00  -0.143321   0.428001   0.1615647   -0.185000    0.435000    0.1640000
+43658.00  -0.140155   0.430832   0.1583622   -0.182000    0.437000    0.1612000
+43659.00  -0.136967   0.433598   0.1552040   -0.179000    0.439000    0.1583000
+43660.00  -0.133776   0.436289   0.1521349   -0.176000    0.440000    0.1556000
+43661.00  -0.130589   0.438906   0.1491926   -0.173000    0.442000    0.1530000
+43662.00  -0.127415   0.441447   0.1464011   -0.170000    0.443000    0.1503000
+43663.00  -0.124258   0.443914   0.1437676   -0.167000    0.445000    0.1477000
+43664.00  -0.121127   0.446307   0.1412826   -0.164000    0.446000    0.1450000
+43665.00  -0.118027   0.448625   0.1389238   -0.161000    0.448000    0.1424000
+43666.00  -0.114966   0.450871   0.1366611   -0.158000    0.450000    0.1399000
+43667.00  -0.111946   0.453043   0.1344602   -0.154000    0.451000    0.1373000
+43668.00  -0.108962   0.455143   0.1322833   -0.151000    0.453000    0.1348000
+43669.00  -0.106002   0.457171   0.1300956   -0.148000    0.455000    0.1322000
+43670.00  -0.103056   0.459126   0.1278696   -0.144000    0.457000    0.1298000
+43671.00  -0.100114   0.461011   0.1255884   -0.141000    0.458000    0.1274000
+43672.00  -0.097167   0.462824   0.1232466   -0.137000    0.460000    0.1250000
+43673.00  -0.094212   0.464567   0.1208500   -0.134000    0.461000    0.1226000
+43674.00  -0.091255   0.466241   0.1184157   -0.130000    0.463000    0.1202000
+43675.00  -0.088300   0.467846   0.1159719   -0.126000    0.464000    0.1179000
+43676.00  -0.085345   0.469387   0.1135555   -0.122000    0.466000    0.1156000
+43677.00  -0.082389   0.470867   0.1112044   -0.118000    0.467000    0.1134000
+43678.00  -0.079428   0.472291   0.1089430   -0.114000    0.469000    0.1111000
+43679.00  -0.076459   0.473663   0.1067689   -0.110000    0.470000    0.1088000
+43680.00  -0.073480   0.474988   0.1046477   -0.106000    0.471000    0.1066000
+43681.00  -0.070485   0.476267   0.1025246   -0.102000    0.473000    0.1044000
+43682.00  -0.067473   0.477504   0.1003467   -0.098000    0.474000    0.1023000
+43683.00  -0.064438   0.478702   0.0980864   -0.094000    0.476000    0.1001000
+43684.00  -0.061377   0.479862   0.0957528   -0.090000    0.477000    0.0979000
+43685.00  -0.058285   0.480987   0.0933861   -0.086000    0.478000    0.0958000
+43686.00  -0.055159   0.482079   0.0910414   -0.082000    0.479000    0.0937000
+43687.00  -0.051996   0.483137   0.0887710   -0.077000    0.480000    0.0916000
+43688.00  -0.048792   0.484159   0.0866126   -0.073000    0.481000    0.0895000
+43689.00  -0.045544   0.485142   0.0845858   -0.069000    0.482000    0.0874000
+43690.00  -0.042250   0.486085   0.0826924   -0.065000    0.483000    0.0854000
+43691.00  -0.038905   0.486984   0.0809192   -0.061000    0.484000    0.0834000
+43692.00  -0.035507   0.487837   0.0792409   -0.056000    0.484000    0.0814000
+43693.00  -0.032052   0.488642   0.0776234   -0.052000    0.485000    0.0794000
+43694.00  -0.028535   0.489396   0.0760289   -0.048000    0.486000    0.0774000
+43695.00  -0.024953   0.490096   0.0744199   -0.044000    0.486000    0.0755000
+43696.00  -0.021301   0.490739   0.0727630   -0.039000    0.486000    0.0736000
+43697.00  -0.017575   0.491319   0.0710331   -0.035000    0.487000    0.0718000
+43698.00  -0.013772   0.491827   0.0692151   -0.030000    0.487000    0.0699000
+43699.00  -0.009888   0.492256   0.0673059   -0.026000    0.487000    0.0680000
+43700.00  -0.005928   0.492599   0.0653151   -0.022000    0.487000    0.0662000
+43701.00  -0.001900   0.492850   0.0632630   -0.017000    0.487000    0.0644000
+43702.00   0.002188   0.493007   0.0611786   -0.013000    0.487000    0.0626000
+43703.00   0.006322   0.493071   0.0590949   -0.008000    0.487000    0.0608000
+43704.00   0.010492   0.493048   0.0570456   -0.004000    0.487000    0.0590000
+43705.00   0.014681   0.492942   0.0550569    0.000000    0.487000    0.0572000
+43706.00   0.018873   0.492757   0.0531365    0.005000    0.487000    0.0554000
+43707.00   0.023046   0.492495   0.0512652    0.009000    0.486000    0.0537000
+43708.00   0.027181   0.492160   0.0493981    0.014000    0.486000    0.0519000
+43709.00   0.031258   0.491754   0.0474797    0.018000    0.486000    0.0501000
+43710.00   0.035262   0.491279   0.0454676    0.022000    0.485000    0.0483000
+43711.00   0.039190   0.490733   0.0433524    0.027000    0.485000    0.0465000
+43712.00   0.043039   0.490114   0.0411655    0.031000    0.484000    0.0447000
+43713.00   0.046808   0.489419   0.0389671    0.036000    0.484000    0.0429000
+43714.00   0.050496   0.488646   0.0368240    0.040000    0.483000    0.0411000
+43715.00   0.054113   0.487792   0.0347876    0.044000    0.482000    0.0392000
+43716.00   0.057670   0.486857   0.0328847    0.049000    0.482000    0.0374000
+43717.00   0.061179   0.485838   0.0311179    0.053000    0.481000    0.0355000
+43718.00   0.064651   0.484736   0.0294711    0.058000    0.481000    0.0337000
+43719.00   0.068101   0.483559   0.0279158    0.062000    0.480000    0.0318000
+43720.00   0.071536   0.482311   0.0264152    0.066000    0.479000    0.0298000
+43721.00   0.074958   0.481001   0.0249285    0.071000    0.478000    0.0278000
+43722.00   0.078364   0.479640   0.0234147    0.075000    0.477000    0.0259000
+43723.00   0.081753   0.478236   0.0218367    0.080000    0.476000    0.0239000
+43724.00   0.085123   0.476798   0.0201654    0.084000    0.475000    0.0219000
+43725.00   0.088473   0.475336   0.0183812    0.088000    0.474000    0.0197000
+43726.00   0.091802   0.473857   0.0164758    0.092000    0.472000    0.0175000
+43727.00   0.095104   0.472363   0.0144542    0.097000    0.471000    0.0154000
+43728.00   0.098376   0.470854   0.0123337    0.101000    0.469000    0.0132000
+43729.00   0.101614   0.469331   0.0101418    0.105000    0.468000    0.0110000
+43730.00   0.104814   0.467794   0.0079106    0.109000    0.466000    0.0087000
+43731.00   0.107971   0.466245   0.0056707    0.113000    0.465000    0.0063000
+43732.00   0.111084   0.464682   0.0034456    0.116000    0.463000    0.0040000
+43733.00   0.114151   0.463104   0.0012434    0.120000    0.462000    0.0016000
+43734.00   0.117171   0.461510  -0.0009488    0.124000    0.460000   -0.0007000
+43735.00   0.120145   0.459899  -0.0031673    0.127000    0.458000   -0.0031000
+43736.00   0.123077   0.458278  -0.0054643    0.131000    0.457000   -0.0055000
+43737.00   0.125976   0.456650  -0.0078913    0.134000    0.455000   -0.0080000
+43738.00   0.128849   0.455022  -0.0104762    0.138000    0.454000   -0.0104000
+43739.00   0.131701   0.453397  -0.0132074    0.141000    0.452000   -0.0128000
+43740.00   0.134538   0.451778  -0.0160330    0.144000    0.450000   -0.0153000
+43741.00   0.137366   0.450165  -0.0188762    0.147000    0.448000   -0.0178000
+43742.00   0.140189   0.448559  -0.0216605    0.151000    0.447000   -0.0202000
+43743.00   0.143012   0.446960  -0.0243301    0.154000    0.445000   -0.0227000
+43744.00   0.145841   0.445366  -0.0268586    0.157000    0.443000   -0.0252000
+43745.00   0.148680   0.443773  -0.0292468    0.160000    0.441000   -0.0277000
+43746.00   0.151531   0.442177  -0.0315147    0.163000    0.439000   -0.0302000
+43747.00   0.154396   0.440571  -0.0336935    0.166000    0.437000   -0.0326000
+43748.00   0.157271   0.438948  -0.0358210    0.169000    0.435000   -0.0351000
+43749.00   0.160151   0.437299  -0.0379363    0.172000    0.433000   -0.0376000
+43750.00   0.163031   0.435617  -0.0400759    0.175000    0.431000   -0.0401000
+43751.00   0.165899   0.433894  -0.0422703    0.177000    0.428000   -0.0426000
+43752.00   0.168737   0.432123  -0.0445405    0.180000    0.426000   -0.0452000
+43753.00   0.171528   0.430297  -0.0468958    0.182000    0.423000   -0.0477000
+43754.00   0.174256   0.428408  -0.0493332    0.185000    0.421000   -0.0502000
+43755.00   0.176908   0.426457  -0.0518383    0.188000    0.419000   -0.0527000
+43756.00   0.179473   0.424449  -0.0543860    0.191000    0.417000   -0.0552000
+43757.00   0.181941   0.422390  -0.0569425    0.193000    0.414000   -0.0577000
+43758.00   0.184304   0.420286  -0.0594734    0.196000    0.412000   -0.0602000
+43759.00   0.186550   0.418143  -0.0619536    0.199000    0.410000   -0.0627000
+43760.00   0.188684   0.415963  -0.0643739    0.202000    0.408000   -0.0652000
+43761.00   0.190718   0.413744  -0.0667459    0.205000    0.406000   -0.0677000
+43762.00   0.192669   0.411482  -0.0691035    0.207000    0.403000   -0.0703000
+43763.00   0.194550   0.409169  -0.0714977    0.210000    0.401000   -0.0728000
+43764.00   0.196378   0.406797  -0.0739843    0.213000    0.399000   -0.0753000
+43765.00   0.198163   0.404359  -0.0766076    0.216000    0.397000   -0.0779000
+43766.00   0.199903   0.401853  -0.0793833    0.218000    0.394000   -0.0805000
+43767.00   0.201596   0.399274  -0.0822877    0.221000    0.392000   -0.0831000
+43768.00   0.203239   0.396620  -0.0852623    0.223000    0.389000   -0.0857000
+43769.00   0.204826   0.393892  -0.0882315    0.226000    0.387000   -0.0883000
+43770.00   0.206351   0.391093  -0.0911272    0.228000    0.384000   -0.0910000
+43771.00   0.207809   0.388224  -0.0939069    0.230000    0.382000   -0.0937000
+43772.00   0.209195   0.385287  -0.0965604    0.233000    0.379000   -0.0964000
+43773.00   0.210502   0.382285  -0.0991042    0.235000    0.377000   -0.0991000
+43774.00   0.211732   0.379220  -0.1015708    0.237000    0.374000   -0.1018000
+43775.00   0.212889   0.376092  -0.1040003    0.239000    0.371000   -0.1046000
+43776.00   0.213980   0.372904  -0.1064361    0.241000    0.369000   -0.1074000
+43777.00   0.215010   0.369658  -0.1089203    0.243000    0.366000   -0.1101000
+43778.00   0.215989   0.366356  -0.1114893    0.245000    0.364000   -0.1129000
+43779.00   0.216932   0.363006  -0.1141692    0.247000    0.361000   -0.1157000
+43780.00   0.217853   0.359612  -0.1169746    0.249000    0.358000   -0.1186000
+43781.00   0.218767   0.356179  -0.1199073    0.250000    0.356000   -0.1214000
+43782.00   0.219684   0.352717  -0.1229554    0.252000    0.353000   -0.1243000
+43783.00   0.220609   0.349234  -0.1260928    0.253000    0.351000   -0.1271000
+43784.00   0.221550   0.345743  -0.1292806    0.255000    0.348000   -0.1300000
+43785.00   0.222509   0.342253  -0.1324730    0.256000    0.345000   -0.1329000
+43786.00   0.223491   0.338774  -0.1356278    0.257000    0.342000   -0.1359000
+43787.00   0.224485   0.335309  -0.1387186    0.259000    0.340000   -0.1388000
+43788.00   0.225478   0.331858  -0.1417440    0.260000    0.337000   -0.1418000
+43789.00   0.226457   0.328422  -0.1447283    0.261000    0.334000   -0.1447000
+43790.00   0.227409   0.325001  -0.1477144    0.262000    0.331000   -0.1477000
+43791.00   0.228323   0.321596  -0.1507530    0.263000    0.328000   -0.1507000
+43792.00   0.229191   0.318206  -0.1538881    0.263000    0.324000   -0.1536000
+43793.00   0.230008   0.314828  -0.1571436    0.264000    0.321000   -0.1566000
+43794.00   0.230768   0.311463  -0.1605123    0.265000    0.318000   -0.1596000
+43795.00   0.231468   0.308107  -0.1639545    0.265000    0.315000   -0.1626000
+43796.00   0.232115   0.304757  -0.1674075    0.266000    0.311000   -0.1656000
+43797.00   0.232718   0.301409  -0.1708012    0.266000    0.308000   -0.1687000
+43798.00   0.233283   0.298057  -0.1740780    0.267000    0.304000   -0.1717000
+43799.00   0.233814   0.294691  -0.1772045    0.267000    0.301000   -0.1747000
+43800.00   0.234310   0.291299  -0.1801762    0.267000    0.297000   -0.1778000
+43801.00   0.234773   0.287874  -0.1830117    0.267000    0.294000   -0.1809000
+43802.00   0.235200   0.284417  -0.1857462    0.268000    0.290000   -0.1839000
+43803.00   0.235586   0.280934  -0.1884211    0.268000    0.287000   -0.1870000
+43804.00   0.235928   0.277428  -0.1910785    0.268000    0.283000   -0.1901000
+43805.00   0.236222   0.273904  -0.1937577    0.268000    0.279000   -0.1932000
+43806.00   0.236463   0.270369  -0.1964924    0.268000    0.276000   -0.1963000
+43807.00   0.236650   0.266835  -0.1993084    0.267000    0.272000   -0.1994000
+43808.00   0.236778   0.263312  -0.2022192    0.267000    0.269000   -0.2025000
+43809.00   0.236845   0.259814  -0.2052260    0.267000    0.265000   -0.2056000
+43810.00   0.236847   0.256349  -0.2083172    0.267000    0.261000   -0.2087000
+43811.00   0.236778   0.252925  -0.2114663    0.266000    0.258000   -0.2118000
+43812.00   0.236632   0.249544  -0.2146351    0.266000    0.254000   -0.2149000
+43813.00   0.236404   0.246213  -0.2177810    0.265000    0.251000   -0.2180000
+43814.00   0.236086   0.242932  -0.2208692    0.265000    0.247000   -0.2211000
+43815.00   0.235680   0.239702  -0.2238856    0.264000    0.243000   -0.2243000
+43816.00   0.235182   0.236519  -0.2268452    0.264000    0.240000   -0.2274000
+43817.00   0.234594   0.233379  -0.2297885    0.263000    0.236000   -0.2306000
+43818.00   0.233914   0.230281  -0.2327680    0.263000    0.233000   -0.2337000
+43819.00   0.233142   0.227222  -0.2358311    0.262000    0.229000   -0.2369000
+43820.00   0.232276   0.224198  -0.2390052    0.261000    0.225000   -0.2401000
+43821.00   0.231317   0.221208  -0.2422912    0.260000    0.222000   -0.2432000
+43822.00   0.230263   0.218247  -0.2456624    0.259000    0.218000   -0.2464000
+43823.00   0.229114   0.215313  -0.2490712    0.258000    0.215000   -0.2495000
+43824.00   0.227870   0.212404  -0.2524596    0.257000    0.211000   -0.2527000
+43825.00   0.226529   0.209516  -0.2557732    0.256000    0.207000   -0.2559000
+43826.00   0.225095   0.206646  -0.2589735    0.255000    0.204000   -0.2590000
+43827.00   0.223575   0.203788  -0.2620454    0.253000    0.200000   -0.2622000
+43828.00   0.221976   0.200937  -0.2649981    0.252000    0.197000   -0.2653000
+43829.00   0.220303   0.198088  -0.2678583    0.251000    0.193000   -0.2685000
+43830.00   0.218564   0.195236  -0.2706623    0.249000    0.190000   -0.2716000
+43831.00   0.216764   0.192375  -0.2734491    0.248000    0.186000   -0.2748000
+43832.00   0.214912   0.189501  -0.2762562    0.246000    0.183000   -0.2779000
+43833.00   0.213012   0.186609  -0.2791156    0.245000    0.179000   -0.2811000
+43834.00   0.211071   0.183701  -0.2820508    0.243000    0.176000   -0.2842000
+43835.00   0.209093   0.180776  -0.2850740    0.241000    0.173000   -0.2873000
+43836.00   0.207082   0.177839  -0.2881851    0.239000    0.169000   -0.2904000
+43837.00   0.205044   0.174892  -0.2913729    0.238000    0.166000   -0.2936000
+43838.00   0.202984   0.171935  -0.2946162    0.236000    0.162000   -0.2967000
+43839.00   0.200905   0.168972  -0.2978839    0.234000    0.159000   -0.2998000
+43840.00   0.198815   0.166005  -0.3011377    0.232000    0.156000   -0.3029000
+43841.00   0.196725   0.163037  -0.3043399    0.230000    0.153000   -0.3060000
+43842.00   0.194646   0.160071  -0.3074654    0.228000    0.149000   -0.3091000
+43843.00   0.192590   0.157112  -0.3105135    0.226000    0.146000   -0.3122000
+43844.00   0.190570   0.154161  -0.3135135    0.224000    0.143000   -0.3153000
+43845.00   0.188596   0.151222  -0.3165158    0.222000    0.140000   -0.3184000
+43846.00   0.186681   0.148300  -0.3195721    0.220000    0.137000   -0.3214000
+43847.00   0.184837   0.145396  -0.3227160    0.217000    0.134000   -0.3245000
+43848.00   0.183075   0.142515  -0.3259501    0.215000    0.131000   -0.3275000
+43849.00   0.181394   0.139662  -0.3292471    0.213000    0.128000   -0.3306000
+43850.00   0.179786   0.136842  -0.3325594    0.211000    0.125000   -0.3336000
+43851.00   0.178245   0.134062  -0.3358331    0.209000    0.122000   -0.3366000
+43852.00   0.176763   0.131326  -0.3390196    0.206000    0.120000   -0.3397000
+43853.00   0.175333   0.128642  -0.3420848    0.204000    0.117000   -0.3427000
+43854.00   0.173948   0.126014  -0.3450138    0.202000    0.114000   -0.3457000
+43855.00   0.172598   0.123448  -0.3478125    0.200000    0.112000   -0.3487000
+43856.00   0.171269   0.120945  -0.3505033    0.198000    0.109000   -0.3517000
+43857.00   0.169949   0.118509  -0.3531192    0.195000    0.107000   -0.3547000
+43858.00   0.168623   0.116141  -0.3556976    0.193000    0.104000   -0.3577000
+43859.00   0.167280   0.113846  -0.3582751    0.191000    0.102000   -0.3607000
+43860.00   0.165906   0.111626  -0.3608843    0.189000    0.100000   -0.3637000
+43861.00   0.164489   0.109482  -0.3635510    0.187000    0.098000   -0.3667000
+43862.00   0.163023   0.107410  -0.3662935    0.184000    0.096000   -0.3696000
+43863.00   0.161506   0.105405  -0.3691193    0.182000    0.094000   -0.3726000
+43864.00   0.159933   0.103460  -0.3720247    0.180000    0.092000   -0.3756000
+43865.00   0.158303   0.101569  -0.3749969    0.178000    0.090000   -0.3786000
+43866.00   0.156610   0.099725  -0.3780160    0.176000    0.088000   -0.3815000
+43867.00   0.154854   0.097924  -0.3810565    0.173000    0.087000   -0.3845000
+43868.00   0.153029   0.096158  -0.3840898    0.171000    0.085000   -0.3874000
+43869.00   0.151133   0.094422  -0.3870918    0.169000    0.083000   -0.3904000
+43870.00   0.149163   0.092709  -0.3900537    0.167000    0.082000   -0.3933000
+43871.00   0.147115   0.091014  -0.3929930    0.164000    0.080000   -0.3962000
+43872.00   0.144987   0.089332  -0.3959529    0.162000    0.079000   -0.3992000
+43873.00   0.142776   0.087666  -0.3989868    0.159000    0.077000   -0.4021000
+43874.00   0.140480   0.086025   0.5978633    0.157000    0.076000    0.5950000
+43875.00   0.138099   0.084414   0.5945863    0.155000    0.075000    0.5921000
+43876.00   0.135629   0.082840   0.5912098    0.152000    0.074000    0.5892000
+43877.00   0.133069   0.081309   0.5877910    0.150000    0.072000    0.5863000
+43878.00   0.130417   0.079829   0.5843976    0.147000    0.071000    0.5834000
+43879.00   0.127672   0.078406   0.5810892    0.145000    0.070000    0.5805000
+43880.00   0.124831   0.077047   0.5779048    0.143000    0.069000    0.5776000
+43881.00   0.121894   0.075758   0.5748607    0.140000    0.068000    0.5747000
+43882.00   0.118858   0.074545   0.5719519    0.138000    0.067000    0.5719000
+43883.00   0.115732   0.073408   0.5691563    0.135000    0.066000    0.5690000
+43884.00   0.112525   0.072343   0.5664409    0.133000    0.065000    0.5661000
+43885.00   0.109250   0.071345   0.5637676    0.131000    0.064000    0.5632000
+43886.00   0.105917   0.070411   0.5610988    0.128000    0.063000    0.5604000
+43887.00   0.102538   0.069537   0.5584014    0.126000    0.063000    0.5575000
+43888.00   0.099123   0.068719   0.5556491    0.123000    0.062000    0.5547000
+43889.00   0.095684   0.067954   0.5528245    0.121000    0.061000    0.5518000
+43890.00   0.092231   0.067237   0.5499209    0.118000    0.060000    0.5489000
+43891.00   0.088776   0.066565   0.5469430    0.116000    0.060000    0.5461000
+43892.00   0.085330   0.065933   0.5439059    0.113000    0.059000    0.5432000
+43893.00   0.081903   0.065338   0.5408321    0.111000    0.059000    0.5404000
+43894.00   0.078507   0.064776   0.5377474    0.108000    0.058000    0.5375000
+43895.00   0.075153   0.064243   0.5346777    0.105000    0.057000    0.5346000
+43896.00   0.071853   0.063735   0.5316455    0.102000    0.057000    0.5318000
+43897.00   0.068616   0.063248   0.5286629    0.100000    0.056000    0.5289000
+43898.00   0.065446   0.062784   0.5257234    0.097000    0.056000    0.5261000
+43899.00   0.062342   0.062344   0.5227957    0.094000    0.055000    0.5232000
+43900.00   0.059301   0.061935   0.5198283    0.091000    0.055000    0.5203000
+43901.00   0.056322   0.061559   0.5167664    0.088000    0.054000    0.5175000
+43902.00   0.053402   0.061220   0.5135772    0.085000    0.054000    0.5146000
+43903.00   0.050539   0.060923   0.5102684    0.082000    0.053000    0.5118000
+43904.00   0.047732   0.060670   0.5068909    0.079000    0.053000    0.5089000
+43905.00   0.044977   0.060467   0.5035221    0.076000    0.053000    0.5060000
+43906.00   0.042272   0.060316   0.5002411    0.073000    0.053000    0.5031000
+43907.00   0.039616   0.060220   0.4971054    0.070000    0.052000    0.5003000
+43908.00   0.037003   0.060177   0.4941406    0.067000    0.052000    0.4974000
+43909.00   0.034431   0.060183   0.4913431    0.064000    0.052000    0.4945000
+43910.00   0.031894   0.060235   0.4886884    0.061000    0.052000    0.4916000
+43911.00   0.029391   0.060324   0.4861395    0.058000    0.053000    0.4887000
+43912.00   0.026917   0.060443   0.4836543    0.054000    0.053000    0.4859000
+43913.00   0.024464   0.060590   0.4811906    0.051000    0.054000    0.4830000
+43914.00   0.022021   0.060766   0.4787103    0.048000    0.054000    0.4801000
+43915.00   0.019579   0.060969   0.4761830    0.044000    0.055000    0.4772000
+43916.00   0.017129   0.061199   0.4735876    0.041000    0.055000    0.4743000
+43917.00   0.014664   0.061456   0.4709136    0.037000    0.056000    0.4714000
+43918.00   0.012186   0.061739   0.4681619    0.034000    0.056000    0.4685000
+43919.00   0.009695   0.062047   0.4653447    0.030000    0.057000    0.4656000
+43920.00   0.007190   0.062380   0.4624842    0.026000    0.058000    0.4627000
+43921.00   0.004672   0.062736   0.4596078    0.023000    0.058000    0.4598000
+43922.00   0.002142   0.063115   0.4567426    0.019000    0.059000    0.4569000
+43923.00  -0.000401   0.063517   0.4539100    0.016000    0.059000    0.4540000
+43924.00  -0.002956   0.063940   0.4511200    0.012000    0.060000    0.4511000
+43925.00  -0.005524   0.064384   0.4483673    0.008000    0.061000    0.4482000
+43926.00  -0.008108   0.064848   0.4456269    0.005000    0.062000    0.4453000
+43927.00  -0.010711   0.065332   0.4428528    0.001000    0.062000    0.4423000
+43928.00  -0.013336   0.065834   0.4399875   -0.002000    0.063000    0.4394000
+43929.00  -0.015987   0.066356   0.4369807   -0.006000    0.064000    0.4365000
+43930.00  -0.018666   0.066895   0.4338127   -0.010000    0.065000    0.4336000
+43931.00  -0.021378   0.067451   0.4305092   -0.014000    0.066000    0.4306000
+43932.00  -0.024122   0.068028   0.4271378   -0.017000    0.068000    0.4277000
+43933.00  -0.026899   0.068637   0.4237864   -0.021000    0.069000    0.4247000
+43934.00  -0.029706   0.069293   0.4205356   -0.025000    0.070000    0.4218000
+43935.00  -0.032543   0.070009   0.4174369   -0.029000    0.072000    0.4189000
+43936.00  -0.035406   0.070797   0.4145046   -0.032000    0.073000    0.4159000
+43937.00  -0.038296   0.071672   0.4117220   -0.036000    0.075000    0.4130000
+43938.00  -0.041208   0.072647   0.4090524   -0.039000    0.076000    0.4100000
+43939.00  -0.044139   0.073730   0.4064513   -0.043000    0.078000    0.4071000
+43940.00  -0.047081   0.074925   0.4038728   -0.046000    0.080000    0.4041000
+43941.00  -0.050025   0.076239   0.4012742   -0.050000    0.082000    0.4012000
+43942.00  -0.052969   0.077670   0.3986191   -0.053000    0.083000    0.3982000
+43943.00  -0.055911   0.079210   0.3958803   -0.057000    0.085000    0.3953000
+43944.00  -0.058854   0.080847   0.3930421   -0.060000    0.087000    0.3923000
+43945.00  -0.061800   0.082570   0.3901010   -0.063000    0.089000    0.3893000
+43946.00  -0.064750   0.084368   0.3870650   -0.066000    0.091000    0.3863000
+43947.00  -0.067704   0.086231   0.3839535   -0.070000    0.093000    0.3834000
+43948.00  -0.070664   0.088147   0.3807956   -0.073000    0.095000    0.3804000
+43949.00  -0.073618   0.090106   0.3776271   -0.076000    0.097000    0.3774000
+43950.00  -0.076549   0.092098   0.3744811   -0.079000    0.099000    0.3744000
+43951.00  -0.079444   0.094114   0.3713788   -0.082000    0.101000    0.3714000
+43952.00  -0.082286   0.096143   0.3683230   -0.084000    0.104000    0.3683000
+43953.00  -0.085059   0.098177   0.3652961   -0.087000    0.106000    0.3653000
+43954.00  -0.087749   0.100204   0.3622606   -0.090000    0.108000    0.3623000
+43955.00  -0.090350   0.102221   0.3591650   -0.093000    0.110000    0.3592000
+43956.00  -0.092865   0.104229   0.3559556   -0.096000    0.113000    0.3562000
+43957.00  -0.095296   0.106231   0.3525963   -0.098000    0.115000    0.3531000
+43958.00  -0.097642   0.108233   0.3490860   -0.101000    0.118000    0.3501000
+43959.00  -0.099898   0.110239   0.3454675   -0.104000    0.120000    0.3470000
+43960.00  -0.102064   0.112255   0.3418196   -0.106000    0.123000    0.3439000
+43961.00  -0.104136   0.114286   0.3382344   -0.109000    0.125000    0.3409000
+43962.00  -0.106120   0.116336   0.3347871   -0.111000    0.128000    0.3378000
+43963.00  -0.108024   0.118409   0.3315186   -0.114000    0.130000    0.3348000
+43964.00  -0.109856   0.120506   0.3284323   -0.116000    0.133000    0.3317000
+43965.00  -0.111624   0.122632   0.3255016   -0.118000    0.136000    0.3286000
+43966.00  -0.113335   0.124790   0.3226839   -0.120000    0.139000    0.3255000
+43967.00  -0.114998   0.126982   0.3199310   -0.123000    0.141000    0.3223000
+43968.00  -0.116619   0.129213   0.3171962   -0.125000    0.144000    0.3192000
+43969.00  -0.118202   0.131482   0.3144374   -0.127000    0.147000    0.3161000
+43970.00  -0.119746   0.133788   0.3116208   -0.129000    0.150000    0.3130000
+43971.00  -0.121251   0.136129   0.3087243   -0.131000    0.153000    0.3099000
+43972.00  -0.122714   0.138504   0.3057383   -0.133000    0.155000    0.3068000
+43973.00  -0.124135   0.140910   0.3026656   -0.135000    0.158000    0.3037000
+43974.00  -0.125512   0.143345   0.2995202   -0.137000    0.161000    0.3006000
+43975.00  -0.126849   0.145809   0.2963268   -0.139000    0.164000    0.2975000
+43976.00  -0.128150   0.148298   0.2931183   -0.141000    0.166000    0.2943000
+43977.00  -0.129419   0.150811   0.2899290   -0.142000    0.169000    0.2912000
+43978.00  -0.130661   0.153347   0.2867850   -0.144000    0.171000    0.2880000
+43979.00  -0.131882   0.155903   0.2836958   -0.146000    0.174000    0.2849000
+43980.00  -0.133085   0.158477   0.2806490   -0.148000    0.177000    0.2818000
+43981.00  -0.134274   0.161067   0.2776110   -0.149000    0.179000    0.2787000
+43982.00  -0.135449   0.163669   0.2745349   -0.151000    0.182000    0.2755000
+43983.00  -0.136606   0.166279   0.2713707   -0.152000    0.184000    0.2724000
+43984.00  -0.137741   0.168891   0.2680793   -0.154000    0.187000    0.2693000
+43985.00  -0.138853   0.171502   0.2646455   -0.155000    0.190000    0.2662000
+43986.00  -0.139941   0.174110   0.2610886   -0.157000    0.192000    0.2631000
+43987.00  -0.141004   0.176715   0.2574631   -0.158000    0.195000    0.2601000
+43988.00  -0.142046   0.179318   0.2538475   -0.160000    0.197000    0.2570000
+43989.00  -0.143074   0.181927   0.2503237   -0.161000    0.200000    0.2539000
+43990.00  -0.144092   0.184548   0.2469541   -0.162000    0.203000    0.2506000
+43991.00  -0.145100   0.187182   0.2437655   -0.163000    0.205000    0.2473000
+43992.00  -0.146089   0.189825   0.2407493   -0.164000    0.208000    0.2440000
+43993.00  -0.147054   0.192477   0.2378725   -0.165000    0.210000    0.2407000
+43994.00  -0.147988   0.195134   0.2350903   -0.142000    0.213000    0.2374000
+43995.00  -0.148886   0.197796   0.2323562   -0.143000    0.215000    0.2344000
+43996.00  -0.149745   0.200461   0.2296276   -0.143000    0.218000    0.2314000
+43997.00  -0.150564   0.203128   0.2268695   -0.144000    0.220000    0.2283000
+43998.00  -0.151339   0.205796   0.2240570   -0.144000    0.223000    0.2253000
+43999.00  -0.152070   0.208464   0.2211782   -0.145000    0.225000    0.2223000
+44000.00  -0.152753   0.211131   0.2182336   -0.145000    0.227000    0.2194000
+44001.00  -0.153387   0.213797   0.2152346   -0.146000    0.230000    0.2164000
+44002.00  -0.153973   0.216460   0.2122023   -0.146000    0.232000    0.2135000
+44003.00  -0.154510   0.219120   0.2091655   -0.147000    0.235000    0.2105000
+44004.00  -0.154999   0.221774   0.2061571   -0.147000    0.237000    0.2076000
+44005.00  -0.155442   0.224422   0.2032085   -0.147000    0.239000    0.2047000
+44006.00  -0.155839   0.227063   0.2003390   -0.148000    0.242000    0.2019000
+44007.00  -0.156190   0.229696   0.1975461   -0.148000    0.244000    0.1990000
+44008.00  -0.156498   0.232317   0.1948025   -0.149000    0.247000    0.1962000
+44009.00  -0.156760   0.234922   0.1920627   -0.149000    0.249000    0.1933000
+44010.00  -0.156979   0.237507   0.1892751   -0.149000    0.251000    0.1905000
+44011.00  -0.157154   0.240066   0.1863978   -0.149000    0.253000    0.1878000
+44012.00  -0.157284   0.242593   0.1834122   -0.149000    0.256000    0.1850000
+44013.00  -0.157372   0.245080   0.1803290   -0.149000    0.258000    0.1823000
+44014.00  -0.157415   0.247523   0.1771873   -0.149000    0.260000    0.1795000
+44015.00  -0.157410   0.249924   0.1740488   -0.149000    0.262000    0.1768000
+44016.00  -0.157353   0.252291   0.1709837   -0.149000    0.264000    0.1742000
+44017.00  -0.157240   0.254629   0.1680538   -0.149000    0.267000    0.1715000
+44018.00  -0.157071   0.256943   0.1652975   -0.149000    0.269000    0.1689000
+44019.00  -0.156842   0.259234   0.1627230   -0.149000    0.271000    0.1662000
+44020.00  -0.156555   0.261507   0.1603115   -0.149000    0.273000    0.1637000
+44021.00  -0.156206   0.263765   0.1580270   -0.149000    0.275000    0.1611000
+44022.00  -0.155797   0.266011   0.1558269   -0.148000    0.278000    0.1586000
+44023.00  -0.155330   0.268245   0.1536684   -0.148000    0.280000    0.1560000
+44024.00  -0.154810   0.270470   0.1515140   -0.148000    0.282000    0.1535000
+44025.00  -0.154242   0.272685   0.1493351   -0.147000    0.284000    0.1511000
+44026.00  -0.153628   0.274892   0.1471131   -0.147000    0.286000    0.1486000
+44027.00  -0.152969   0.277094   0.1448408   -0.146000    0.289000    0.1462000
+44028.00  -0.152263   0.279291   0.1425226   -0.146000    0.291000    0.1437000
+44029.00  -0.151511   0.281486   0.1401719   -0.145000    0.293000    0.1413000
+44030.00  -0.150712   0.283680   0.1378086   -0.144000    0.295000    0.1389000
+44031.00  -0.149866   0.285876   0.1354564   -0.143000    0.298000    0.1365000
+44032.00  -0.148972   0.288076   0.1331408   -0.142000    0.300000    0.1341000
+44033.00  -0.148031   0.290280   0.1308829   -0.141000    0.303000    0.1317000
+44034.00  -0.147047   0.292494   0.1286901   -0.140000    0.305000    0.1293000
+44035.00  -0.146027   0.294720   0.1265461   -0.139000    0.307000    0.1270000
+44036.00  -0.144979   0.296961   0.1244090   -0.138000    0.310000    0.1246000
+44037.00  -0.143907   0.299222   0.1222235   -0.137000    0.312000    0.1223000
+44038.00  -0.142819   0.301505   0.1199394   -0.136000    0.315000    0.1199000
+44039.00  -0.141721   0.303814   0.1175309   -0.135000    0.317000    0.1176000
+44040.00  -0.140619   0.306150   0.1150055   -0.134000    0.319000    0.1154000
+44041.00  -0.139515   0.308510   0.1124028   -0.133000    0.321000    0.1131000
+44042.00  -0.138413   0.310891   0.1097815   -0.132000    0.324000    0.1109000
+44043.00  -0.137315   0.313290   0.1072050   -0.131000    0.326000    0.1086000
+44044.00  -0.136226   0.315703   0.1047273   -0.130000    0.328000    0.1064000
+44045.00  -0.135149   0.318127   0.1023839   -0.129000    0.330000    0.1042000
+44046.00  -0.134082   0.320558   0.1001851   -0.128000    0.332000    0.1020000
+44047.00  -0.133023   0.322987   0.0981170   -0.126000    0.335000    0.0997000
+44048.00  -0.131967   0.325406   0.0961475   -0.125000    0.337000    0.0975000
+44049.00  -0.130909   0.327807   0.0942354   -0.124000    0.339000    0.0953000
+44050.00  -0.129846   0.330183   0.0923394   -0.123000    0.341000    0.0932000
+44051.00  -0.128778   0.332535   0.0904232   -0.122000    0.343000    0.0910000
+44052.00  -0.127706   0.334862   0.0884588   -0.120000    0.345000    0.0889000
+44053.00  -0.126628   0.337163   0.0864284   -0.119000    0.347000    0.0867000
+44054.00  -0.125542   0.339439   0.0843264   -0.118000    0.349000    0.0846000
+44055.00  -0.124442   0.341688   0.0821596   -0.117000    0.351000    0.0825000
+44056.00  -0.123326   0.343909   0.0799453   -0.116000    0.353000    0.0805000
+44057.00  -0.122188   0.346100   0.0777069   -0.114000    0.355000    0.0784000
+44058.00  -0.121023   0.348261   0.0754707   -0.113000    0.357000    0.0764000
+44059.00  -0.119823   0.350392   0.0732628   -0.112000    0.359000    0.0743000
+44060.00  -0.118580   0.352492   0.0711070   -0.111000    0.361000    0.0723000
+44061.00  -0.117286   0.354562   0.0690175   -0.109000    0.363000    0.0703000
+44062.00  -0.115933   0.356601   0.0669908   -0.108000    0.364000    0.0684000
+44063.00  -0.114514   0.358609   0.0649984   -0.106000    0.366000    0.0664000
+44064.00  -0.113023   0.360584   0.0629905   -0.105000    0.368000    0.0644000
+44065.00  -0.111458   0.362525   0.0609115   -0.103000    0.370000    0.0624000
+44066.00  -0.109817   0.364427   0.0587243   -0.101000    0.371000    0.0605000
+44067.00  -0.108098   0.366288   0.0564281   -0.100000    0.373000    0.0585000
+44068.00  -0.106300   0.368105   0.0540628   -0.098000    0.374000    0.0566000
+44069.00  -0.104419   0.369877   0.0516943   -0.096000    0.376000    0.0546000
+44070.00  -0.102454   0.371605   0.0493954   -0.094000    0.377000    0.0527000
+44071.00  -0.100404   0.373287   0.0472259   -0.092000    0.379000    0.0507000
+44072.00  -0.098267   0.374923   0.0452206   -0.090000    0.380000    0.0488000
+44073.00  -0.096040   0.376514   0.0433866   -0.088000    0.382000    0.0468000
+44074.00  -0.093725   0.378060   0.0417069   -0.086000    0.383000    0.0449000
+44075.00  -0.091327   0.379565   0.0401465   -0.084000    0.384000    0.0430000
+44076.00  -0.088856   0.381037   0.0386609   -0.081000    0.386000    0.0410000
+44077.00  -0.086321   0.382482   0.0372045   -0.079000    0.387000    0.0391000
+44078.00  -0.083733   0.383905   0.0357367   -0.075990    0.389000    0.0371000
+44079.00  -0.081101   0.385315   0.0342253   -0.074000    0.390000    0.0352000
+44080.00  -0.078433   0.386717   0.0326479   -0.071000    0.391000    0.0333000
+44081.00  -0.075739   0.388117   0.0309929   -0.069000    0.392000    0.0313990
+44082.00  -0.073026   0.389522   0.0292595   -0.066000    0.394000    0.0294000
+44083.00  -0.070302   0.390939   0.0274579   -0.064000    0.395000    0.0275000
+44084.00  -0.067573   0.392373   0.0256065   -0.061000    0.396000    0.0256000
+44085.00  -0.064847   0.393830   0.0237269   -0.058000    0.397000    0.0236000
+44086.00  -0.062126   0.395308   0.0218404   -0.055000    0.398000    0.0216000
+44087.00  -0.059411   0.396802   0.0199639   -0.053000    0.400000    0.0197000
+44088.00  -0.056703   0.398306   0.0181066   -0.050000    0.401000    0.0177000
+44089.00  -0.054003   0.399814   0.0162656   -0.047000    0.402000    0.0156990
+44090.00  -0.051312   0.401319   0.0144201   -0.044000    0.403000    0.0137000
+44091.00  -0.048629   0.402812   0.0125271   -0.041000    0.404000    0.0117000
+44092.00  -0.045956   0.404284   0.0105286   -0.039000    0.405000    0.0096000
+44093.00  -0.043291   0.405727   0.0083720   -0.035990    0.406000    0.0076000
+44094.00  -0.040636   0.407132   0.0060328   -0.033000    0.407000    0.0056000
+44095.00  -0.037989   0.408492   0.0035321   -0.030000    0.408000    0.0035000
+44096.00  -0.035345   0.409799   0.0009371   -0.027000    0.409000    0.0015000
+44097.00  -0.032689   0.411047  -0.0016589   -0.025000    0.409000   -0.0006000
+44098.00  -0.030008   0.412228  -0.0041672   -0.022000    0.410000   -0.0026000
+44099.00  -0.027287   0.413337  -0.0065267   -0.018990    0.411000   -0.0047000
+44100.00  -0.024514   0.414367  -0.0087132   -0.016000    0.412000   -0.0068000
+44101.00  -0.021675   0.415312  -0.0107356   -0.013000    0.413000   -0.0089000
+44102.00  -0.018775   0.416172  -0.0126275   -0.011000    0.413000   -0.0110000
+44103.00  -0.015826   0.416953  -0.0144346   -0.008000    0.414000   -0.0131000
+44104.00  -0.012839   0.417659  -0.0162036   -0.005000    0.415000   -0.0152000
+44105.00  -0.009828   0.418293  -0.0179767   -0.002000    0.416000   -0.0173000
+44106.00  -0.006804   0.418860  -0.0197865    0.000000    0.416000   -0.0194000
+44107.00  -0.003779   0.419365  -0.0216552    0.003000    0.417000   -0.0215000
+44108.00  -0.000767   0.419812  -0.0235931    0.005000    0.417000   -0.0236000
+44109.00   0.002222   0.420205  -0.0255994    0.008000    0.418000   -0.0257000
+44110.00   0.005175   0.420548  -0.0276627    0.011000    0.418000   -0.0278000
+44111.00   0.008079   0.420847  -0.0297624    0.013000    0.419000   -0.0300000
+44112.00   0.010923   0.421105  -0.0318720    0.016000    0.419000   -0.0321000
+44113.00   0.013703   0.421323  -0.0339667    0.017990    0.420000   -0.0343000
+44114.00   0.016420   0.421501  -0.0360279    0.021000    0.420000   -0.0364000
+44115.00   0.019077   0.421639  -0.0380466    0.024000    0.420000   -0.0386000
+44116.00   0.021674   0.421735  -0.0400268    0.026000    0.420000   -0.0407000
+44117.00   0.024215   0.421790  -0.0419887    0.029000    0.420000   -0.0429000
+44118.00   0.026700   0.421802  -0.0439715    0.031000    0.420000   -0.0450000
+44119.00   0.029132   0.421771  -0.0460322    0.034000    0.420000   -0.0472000
+44120.00   0.031511   0.421697  -0.0482331    0.037000    0.420000   -0.0494000
+44121.00   0.033842   0.421579  -0.0506223    0.039000    0.420000   -0.0516000
+44122.00   0.036124   0.421415  -0.0532098    0.042000    0.419000   -0.0539000
+44123.00   0.038362   0.421208  -0.0559546    0.044000    0.419000   -0.0561000
+44124.00   0.040559   0.420956  -0.0587727    0.047000    0.419000   -0.0583000
+44125.00   0.042720   0.420659  -0.0615625    0.049000    0.419000   -0.0606000
+44126.00   0.044847   0.420319  -0.0642366    0.052000    0.419000   -0.0627990
+44127.00   0.046946   0.419936  -0.0667455    0.054000    0.418000   -0.0651000
+44128.00   0.049019   0.419508  -0.0690829    0.057000    0.418000   -0.0673000
+44129.00   0.051074   0.419032  -0.0712768    0.059000    0.418000   -0.0696000
+44130.00   0.053117   0.418502  -0.0733744    0.061000    0.418000   -0.0720000
+44131.00   0.055153   0.417912  -0.0754270    0.063000    0.418000   -0.0743000
+44132.00   0.057180   0.417258  -0.0774808    0.066000    0.417000   -0.0767000
+44133.00   0.059199   0.416536  -0.0795726    0.068000    0.417000   -0.0790000
+44134.00   0.061206   0.415743  -0.0817274    0.070000    0.417000   -0.0814000
+44135.00   0.063200   0.414878  -0.0839581    0.071990    0.416000   -0.0838000
+44136.00   0.065176   0.413944  -0.0862669    0.074000    0.416000   -0.0863000
+44137.00   0.067126   0.412949  -0.0886452    0.075990    0.415000   -0.0887000
+44138.00   0.069047   0.411900  -0.0910757    0.078000    0.415000   -0.0912000
+44139.00   0.070931   0.410806  -0.0935341    0.080000    0.414000   -0.0936000
+44140.00   0.072773   0.409675  -0.0959929    0.082000    0.413000   -0.0961000
+44141.00   0.074567   0.408515  -0.0984269    0.083000    0.412000   -0.0987000
+44142.00   0.076307   0.407335  -0.1008215    0.085000    0.412000   -0.1012000
+44143.00   0.077989   0.406142  -0.1031763    0.086000    0.411000   -0.1038000
+44144.00   0.079608   0.404944  -0.1055084    0.088000    0.410000   -0.1063000
+44145.00   0.081169   0.403754  -0.1078519    0.089000    0.409000   -0.1089000
+44146.00   0.082675   0.402580  -0.1102558    0.091000    0.408000   -0.1116000
+44147.00   0.084132   0.401428  -0.1127779    0.092000    0.408000   -0.1142000
+44148.00   0.085546   0.400303  -0.1154722    0.094000    0.407000   -0.1169000
+44149.00   0.086922   0.399210  -0.1183698    0.095000    0.406000   -0.1195000
+44150.00   0.088261   0.398147  -0.1214611    0.096000    0.405000   -0.1222000
+44151.00   0.089562   0.397110  -0.1246893    0.097000    0.404000   -0.1249000
+44152.00   0.090826   0.396094  -0.1279624    0.098000    0.404000   -0.1275000
+44153.00   0.092056   0.395093  -0.1311808    0.099000    0.403000   -0.1302000
+44154.00   0.093254   0.394100  -0.1342675    0.100000    0.402000   -0.1329000
+44155.00   0.094421   0.393111  -0.1371874    0.101000    0.401000   -0.1356000
+44156.00   0.095564   0.392119  -0.1399479    0.102000    0.400000   -0.1383000
+44157.00   0.096691   0.391120  -0.1425862    0.103000    0.400000   -0.1409000
+44158.00   0.097813   0.390111  -0.1451529    0.104000    0.399000   -0.1436000
+44159.00   0.098939   0.389088  -0.1476981    0.105000    0.398000   -0.1463000
+44160.00   0.100079   0.388046  -0.1502641    0.106000    0.397000   -0.1490000
+44161.00   0.101241   0.386981  -0.1528811    0.107000    0.396000   -0.1517000
+44162.00   0.102432   0.385888  -0.1555665    0.108000    0.395000   -0.1545000
+44163.00   0.103656   0.384759  -0.1583234    0.109000    0.394000   -0.1572000
+44164.00   0.104919   0.383589  -0.1611426    0.110000    0.393000   -0.1599000
+44165.00   0.106230   0.382375  -0.1640036    0.111000    0.392000   -0.1626000
+44166.00   0.107594   0.381114  -0.1668783    0.112000    0.391000   -0.1653000
+44167.00   0.109010   0.379805  -0.1697354    0.113000    0.389000   -0.1681000
+44168.00   0.110472   0.378448  -0.1725428    0.114000    0.388000   -0.1708000
+44169.00   0.111973   0.377043  -0.1752734    0.115000    0.387000   -0.1735000
+44170.00   0.113508   0.375592  -0.1779123    0.116000    0.386000   -0.1762000
+44171.00   0.115071   0.374096  -0.1804638    0.117000    0.385000   -0.1790000
+44172.00   0.116658   0.372558  -0.1829532    0.117000    0.383000   -0.1817000
+44173.00   0.118264   0.370981  -0.1854237    0.118000    0.382000   -0.1845000
+44174.00   0.119881   0.369370  -0.1879304    0.119000    0.381000   -0.1872000
+44175.00   0.121499   0.367730  -0.1905278    0.120000    0.380000   -0.1899000
+44176.00   0.123110   0.366067  -0.1932557    0.121000    0.378000   -0.1927000
+44177.00   0.124704   0.364386  -0.1961259    0.121000    0.377000   -0.1954000
+44178.00   0.126267   0.362696  -0.1991127    0.122000    0.375000   -0.1982000
+44179.00   0.127786   0.361002  -0.2021533    0.123000    0.374000   -0.2009000
+44180.00   0.129247   0.359310  -0.2051622    0.124000    0.372000   -0.2036000
+44181.00   0.130640   0.357627  -0.2080566    0.125000    0.370000   -0.2063000
+44182.00   0.131952   0.355957  -0.2107808    0.126000    0.369000   -0.2090000
+44183.00   0.133174   0.354305  -0.2133200    0.127000    0.367000   -0.2117000
+44184.00   0.134298   0.352671  -0.2156970    0.128000    0.365000   -0.2144000
+44185.00   0.135323   0.351057  -0.2179589    0.128990    0.363000   -0.2170000
+44186.00   0.136248   0.349458  -0.2201601    0.130000    0.361000   -0.2197000
+44187.00   0.137075   0.347869  -0.2223508    0.131000    0.358000   -0.2223000
+44188.00   0.137808   0.346286  -0.2245710    0.132000    0.356000   -0.2250000
+44189.00   0.138446   0.344704  -0.2268483    0.133000    0.354000   -0.2276000
+44190.00   0.138994   0.343119  -0.2291972    0.134000    0.352000   -0.2302000
+44191.00   0.139451   0.341524  -0.2316187    0.135000    0.350000   -0.2328000
+44192.00   0.139821   0.339914  -0.2341023    0.135000    0.347000   -0.2355000
+44193.00   0.140103   0.338282  -0.2366291    0.136000    0.345000   -0.2381000
+44194.00   0.140302   0.336622  -0.2391737    0.136990    0.343000   -0.2407000
+44195.00   0.140426   0.334928  -0.2417079    0.138000    0.341000   -0.2433000
+44196.00   0.140482   0.333196  -0.2442046    0.138000    0.339000   -0.2459000
+44197.00   0.140477   0.331420  -0.2466437    0.139000    0.336000   -0.2485000
+44198.00   0.140419   0.329595  -0.2490207    0.139000    0.334000   -0.2511000
+44199.00   0.140318   0.327721  -0.2513531    0.140000    0.332000   -0.2536990
+44200.00   0.140180   0.325795  -0.2536803    0.140000    0.330000   -0.2563000
+44201.00   0.140012   0.323818  -0.2560557    0.140000    0.328000   -0.2588990
+44202.00   0.139821   0.321787  -0.2585334    0.141000    0.324990   -0.2615000
+44203.00   0.139611   0.319701  -0.2611536    0.141000    0.323000   -0.2641000
+44204.00   0.139390   0.317562  -0.2639311    0.141000    0.321000   -0.2667000
+44205.00   0.139167   0.315386  -0.2668483    0.141000    0.319000   -0.2693000
+44206.00   0.138953   0.313192  -0.2698572    0.141000    0.316000   -0.2718000
+44207.00   0.138753   0.310995  -0.2728880    0.141000    0.314000   -0.2744000
+44208.00   0.138573   0.308809  -0.2758646    0.141000    0.310990   -0.2769000
+44209.00   0.138418   0.306639  -0.2787243    0.141000    0.308990   -0.2795000
+44210.00   0.138289   0.304489  -0.2814329    0.141000    0.307000   -0.2821000
+44211.00   0.138190   0.302360  -0.2839919    0.141000    0.305000   -0.2846000
+44212.00   0.138124   0.300255  -0.2864315    0.140000    0.303000   -0.2872000
+44213.00   0.138091   0.298174  -0.2887981    0.140000    0.301000   -0.2897000
+44214.00   0.138089   0.296114  -0.2911396    0.140000    0.299000   -0.2923000
+44215.00   0.138117   0.294075  -0.2934961    0.140000    0.297000   -0.2949000
+44216.00   0.138168   0.292058  -0.2958970    0.140000    0.294990   -0.2974000
+44217.00   0.138238   0.290066  -0.2983595    0.139000    0.293000   -0.3000000
+44218.00   0.138320   0.288099  -0.3008881    0.139000    0.291000   -0.3025000
+44219.00   0.138410   0.286159  -0.3034748    0.139000    0.289000   -0.3051000
+44220.00   0.138505   0.284248  -0.3061010    0.139000    0.287000   -0.3076000
+44221.00   0.138603   0.282368  -0.3087421    0.138000    0.285000   -0.3102000
+44222.00   0.138703   0.280516  -0.3113708    0.138000    0.283000   -0.3127000
+44223.00   0.138805   0.278690  -0.3139607    0.136990    0.280990   -0.3153000
+44224.00   0.138909   0.276887  -0.3164895    0.136990    0.279000   -0.3178000
+44225.00   0.139014   0.275106  -0.3189447    0.136990    0.277000   -0.3203000
+44226.00   0.139120   0.273342  -0.3213305    0.136000    0.275000   -0.3229000
+44227.00   0.139225   0.271595  -0.3236743    0.136000    0.273990   -0.3254000
+44228.00   0.139326   0.269861  -0.3260234    0.135000    0.272000   -0.3280000
+44229.00   0.139418   0.268135  -0.3284335    0.135000    0.270000   -0.3305000
+44230.00   0.139498   0.266416  -0.3309502    0.134000    0.268000   -0.3330000
+44231.00   0.139560   0.264700  -0.3335935    0.134000    0.266000   -0.3355000
+44232.00   0.139603   0.262986  -0.3363494    0.133000    0.264000   -0.3380000
+44233.00   0.139621   0.261273  -0.3391744    0.133000    0.262000   -0.3405000
+44234.00   0.139611   0.259557  -0.3420076    0.132000    0.260000   -0.3430000
+44235.00   0.139569   0.257838  -0.3447863    0.131000    0.257990   -0.3455000
+44236.00   0.139492   0.256114  -0.3474594    0.131000    0.256000   -0.3480000
+44237.00   0.139373   0.254387  -0.3499978    0.130000    0.255000   -0.3506000
+44238.00   0.139205   0.252659  -0.3524007    0.130000    0.253000   -0.3531000
+44239.00   0.138980   0.250935   0.6453058    0.128990    0.250990    0.6444000
+44240.00   0.138693   0.249216   0.6430784    0.128000    0.249000    0.6419000
+44241.00   0.138335   0.247506   0.6408691    0.127000    0.247000    0.6394000
+44242.00   0.137902   0.245807   0.6386352    0.127000    0.246000    0.6368000
+44243.00   0.137395   0.244120   0.6363457    0.126000    0.244000    0.6343000
+44244.00   0.136811   0.242446   0.6339818    0.125000    0.242000    0.6318000
+44245.00   0.136151   0.240786   0.6315374    0.124000    0.240000    0.6293000
+44246.00   0.135413   0.239142   0.6290184    0.123000    0.239000    0.6267000
+44247.00   0.134598   0.237513   0.6264412    0.122000    0.237000    0.6242000
+44248.00   0.133709   0.235902   0.6238294    0.121000    0.236000    0.6216000
+44249.00   0.132757   0.234310   0.6212086    0.120000    0.234000    0.6191000
+44250.00   0.131748   0.232740   0.6186020    0.119000    0.232000    0.6166000
+44251.00   0.130692   0.231191   0.6160289    0.118000    0.231000    0.6141000
+44252.00   0.129593   0.229665   0.6135018    0.116000    0.229000    0.6115000
+44253.00   0.128457   0.228159   0.6110210    0.115000    0.228000    0.6090000
+44254.00   0.127290   0.226672   0.6085683    0.114000    0.226000    0.6065000
+44255.00   0.126096   0.225205   0.6061039    0.113000    0.224000    0.6040000
+44256.00   0.124881   0.223755   0.6035730    0.111000    0.223000    0.6015000
+44257.00   0.123646   0.222321   0.6009239    0.110000    0.221000    0.5989000
+44258.00   0.122392   0.220902   0.5981297    0.108000    0.220000    0.5964000
+44259.00   0.121118   0.219496   0.5952043    0.107000    0.218000    0.5939000
+44260.00   0.119821   0.218103   0.5922023    0.106000    0.216000    0.5914000
+44261.00   0.118501   0.216720   0.5892033    0.104000    0.215000    0.5889000
+44262.00   0.117150   0.215348   0.5862886    0.103000    0.213000    0.5863000
+44263.00   0.115758   0.213987   0.5835214    0.101000    0.212000    0.5838000
+44264.00   0.114323   0.212638   0.5809352    0.100000    0.210000    0.5813000
+44265.00   0.112841   0.211304   0.5785319    0.099000    0.209000    0.5788000
+44266.00   0.111310   0.209984   0.5762861    0.097000    0.207000    0.5764000
+44267.00   0.109728   0.208682   0.5741545    0.096000    0.206000    0.5739000
+44268.00   0.108092   0.207398   0.5720865    0.094000    0.204000    0.5715000
+44269.00   0.106402   0.206132   0.5700354    0.093000    0.203000    0.5690000
+44270.00   0.104655   0.204884   0.5679641    0.092000    0.202000    0.5665000
+44271.00   0.102851   0.203651   0.5658492    0.090000    0.201000    0.5641000
+44272.00   0.100993   0.202433   0.5636796    0.089000    0.199000    0.5616000
+44273.00   0.099091   0.201231   0.5614565    0.087000    0.198000    0.5592000
+44274.00   0.097155   0.200045   0.5591909    0.086000    0.197000    0.5567000
+44275.00   0.095195   0.198875   0.5569018    0.085000    0.196000    0.5543000
+44276.00   0.093226   0.197723   0.5546116    0.084000    0.195000    0.5519000
+44277.00   0.091266   0.196591   0.5523411    0.083000    0.193000    0.5494000
+44278.00   0.089333   0.195479   0.5501051    0.082000    0.192000    0.5470000
+44279.00   0.087446   0.194388   0.5479092    0.081000    0.191000    0.5446000
+44280.00   0.085620   0.193319   0.5457478    0.080000    0.190000    0.5422000
+44281.00   0.083873   0.192271   0.5436007    0.079000    0.189000    0.5397000
+44282.00   0.082218   0.191244   0.5414283    0.079000    0.188000    0.5373000
+44283.00   0.080651   0.190240   0.5391704    0.078000    0.187000    0.5348000
+44284.00   0.079166   0.189260   0.5367591    0.077000    0.186000    0.5324000
+44285.00   0.077756   0.188305   0.5341446    0.075990    0.185000    0.5300000
+44286.00   0.076414   0.187376   0.5313165    0.075000    0.184000    0.5276000
+44287.00   0.075131   0.186474   0.5283146    0.075000    0.184000    0.5251000
+44288.00   0.073900   0.185601   0.5252221    0.074000    0.183000    0.5227000
+44289.00   0.072715   0.184756   0.5221418    0.073000    0.182000    0.5202990
+44290.00   0.071567   0.183944   0.5191657    0.071990    0.181000    0.5179000
+44291.00   0.070449   0.183165   0.5163523    0.071000    0.180000    0.5155000
+44292.00   0.069354   0.182425   0.5137186    0.071000    0.180000    0.5130000
+44293.00   0.068273   0.181726   0.5112459    0.070000    0.179000    0.5105990
+44294.00   0.067199   0.181072   0.5088943    0.069000    0.178000    0.5082000
+44295.00   0.066122   0.180469   0.5066145    0.068000    0.177000    0.5058000
+44296.00   0.065033   0.179919   0.5043588    0.067000    0.177000    0.5034000
+44297.00   0.063923   0.179427   0.5020888    0.067000    0.176000    0.5010000
+44298.00   0.062782   0.178993   0.4997791    0.066000    0.176000    0.4986000
+44299.00   0.061603   0.178619   0.4974185    0.065000    0.175000    0.4962000
+44300.00   0.060380   0.178307   0.4950075    0.064000    0.175000    0.4938000
+44301.00   0.059110   0.178054   0.4925570    0.063000    0.175000    0.4913000
+44302.00   0.057789   0.177863   0.4900871    0.062000    0.175000    0.4889000
+44303.00   0.056416   0.177730   0.4876240    0.061000    0.175000    0.4864000
+44304.00   0.054990   0.177653   0.4851957    0.060000    0.175000    0.4840000
+44305.00   0.053512   0.177625   0.4828251    0.059000    0.175000    0.4815000
+44306.00   0.051987   0.177643   0.4805241    0.057000    0.175000    0.4790000
+44307.00   0.050421   0.177702   0.4782909    0.056000    0.176000    0.4766000
+44308.00   0.048818   0.177795   0.4761094    0.054000    0.176000    0.4741000
+44309.00   0.047184   0.177919   0.4739461    0.053000    0.176000    0.4716000
+44310.00   0.045521   0.178073   0.4717485    0.052000    0.176000    0.4691000
+44311.00   0.043833   0.178255   0.4694499    0.050000    0.177000    0.4666000
+44312.00   0.042121   0.178468   0.4669834    0.049000    0.177000    0.4641000
+44313.00   0.040391   0.178710   0.4643042    0.047000    0.178000    0.4616000
+44314.00   0.038646   0.178983   0.4614115    0.046000    0.178000    0.4591000
+44315.00   0.036890   0.179286   0.4583594    0.044000    0.179000    0.4566000
+44316.00   0.035126   0.179618   0.4552437    0.042000    0.179000    0.4541000
+44317.00   0.033358   0.179979   0.4521716    0.041000    0.180000    0.4515000
+44318.00   0.031588   0.180365   0.4492286    0.039000    0.180000    0.4490000
+44319.00   0.029816   0.180776   0.4464563    0.037000    0.181000    0.4465000
+44320.00   0.028044   0.181209   0.4438491    0.035000    0.182000    0.4439000
+44321.00   0.026277   0.181661   0.4413673    0.033000    0.182000    0.4413000
+44322.00   0.024517   0.182131   0.4389552    0.032000    0.183000    0.4388000
+44323.00   0.022769   0.182616   0.4365571    0.030000    0.183000    0.4362000
+44324.00   0.021032   0.183114   0.4341277    0.028000    0.184000    0.4336000
+44325.00   0.019308   0.183625   0.4316361    0.026000    0.185000    0.4310000
+44326.00   0.017596   0.184149   0.4290667    0.024000    0.186000    0.4284000
+44327.00   0.015900   0.184683   0.4264192    0.021000    0.186000    0.4258000
+44328.00   0.014225   0.185227   0.4237058    0.018990    0.187000    0.4232000
+44329.00   0.012573   0.185779   0.4209487    0.017000    0.188000    0.4206000
+44330.00   0.010942   0.186341   0.4181764    0.014000    0.189000    0.4180000
+44331.00   0.009330   0.186913   0.4154210    0.012000    0.190000    0.4154000
+44332.00   0.007732   0.187499   0.4127132    0.008990    0.191000    0.4127000
+44333.00   0.006145   0.188098   0.4100757    0.007000    0.192000    0.4101000
+44334.00   0.004564   0.188713   0.4075181    0.004000    0.193000    0.4075000
+44335.00   0.002985   0.189344   0.4050339    0.002000    0.194000    0.4049000
+44336.00   0.001404   0.189993   0.4025986    0.000000    0.195000    0.4022000
+44337.00  -0.000184   0.190657   0.4001715   -0.003000    0.196000    0.3996000
+44338.00  -0.001784   0.191338   0.3976986   -0.005000    0.197000    0.3969000
+44339.00  -0.003399   0.192036   0.3951184   -0.007000    0.198000    0.3943000
+44340.00  -0.005035   0.192749   0.3923766   -0.008990    0.199000    0.3916000
+44341.00  -0.006693   0.193480   0.3894468   -0.011000    0.200000    0.3889000
+44342.00  -0.008371   0.194228   0.3863481   -0.012000    0.202000    0.3863000
+44343.00  -0.010064   0.194996   0.3831491   -0.014000    0.203000    0.3836000
+44344.00  -0.011767   0.195783   0.3799519   -0.016000    0.204000    0.3809000
+44345.00  -0.013473   0.196591   0.3768602   -0.017990    0.205000    0.3782000
+44346.00  -0.015173   0.197424   0.3739470   -0.018990    0.206000    0.3756000
+44347.00  -0.016861   0.198283   0.3712357   -0.021000    0.208000    0.3729000
+44348.00  -0.018531   0.199172   0.3687020   -0.022000    0.209000    0.3703000
+44349.00  -0.020180   0.200093   0.3662917   -0.024000    0.210000    0.3676000
+44350.00  -0.021803   0.201050   0.3639420   -0.025000    0.211000    0.3650000
+44351.00  -0.023391   0.202038   0.3615979   -0.027000    0.213000    0.3623000
+44352.00  -0.024933   0.203054   0.3592189   -0.028000    0.214000    0.3597000
+44353.00  -0.026421   0.204098   0.3567803   -0.030000    0.216000    0.3570000
+44354.00  -0.027852   0.205166   0.3542727   -0.031000    0.217000    0.3544000
+44355.00  -0.029222   0.206260   0.3517004   -0.032000    0.218000    0.3518000
+44356.00  -0.030530   0.207376   0.3490794   -0.033000    0.220000    0.3492000
+44357.00  -0.031780   0.208512   0.3464344   -0.035000    0.221000    0.3465000
+44358.00  -0.032974   0.209662   0.3437946   -0.035990    0.223000    0.3439000
+44359.00  -0.034117   0.210823   0.3411890   -0.037000    0.224000    0.3413000
+44360.00  -0.035211   0.211990   0.3386427   -0.037990    0.225000    0.3387000
+44361.00  -0.036260   0.213160   0.3361710   -0.039000    0.226000    0.3362000
+44362.00  -0.037268   0.214328   0.3337745   -0.040000    0.228000    0.3336000
+44363.00  -0.038237   0.215493   0.3314354   -0.041000    0.229000    0.3311000
+44364.00  -0.039170   0.216651   0.3291184   -0.042000    0.230000    0.3285000
+44365.00  -0.040070   0.217799   0.3267747   -0.043000    0.231000    0.3260000
+44366.00  -0.040940   0.218938   0.3243499   -0.044000    0.232000    0.3235000
+44367.00  -0.041786   0.220064   0.3217946   -0.044000    0.234000    0.3210000
+44368.00  -0.042610   0.221179   0.3190770   -0.045000    0.235000    0.3185000
+44369.00  -0.043412   0.222281   0.3161979   -0.046000    0.236000    0.3160000
+44370.00  -0.044191   0.223371   0.3131995   -0.047000    0.237000    0.3135000
+44371.00  -0.044944   0.224447   0.3101614   -0.047000    0.238000    0.3111000
+44372.00  -0.045667   0.225511   0.3071817   -0.048000    0.240000    0.3086000
+44373.00  -0.046356   0.226563   0.3043487   -0.048000    0.241000    0.3062000
+44374.00  -0.047008   0.227603   0.3017146   -0.049000    0.242000    0.3037000
+44375.00  -0.047627   0.228634   0.2992833   -0.050000    0.243000    0.3014000
+44376.00  -0.048213   0.229657   0.2970177   -0.050000    0.244000    0.2990000
+44377.00  -0.048768   0.230674   0.2948597   -0.051000    0.245000    0.2967000
+44378.00  -0.049291   0.231685   0.2927505   -0.051000    0.246000    0.2943000
+44379.00  -0.049783   0.232689   0.2906432   -0.052000    0.247000    0.2920000
+44380.00  -0.050242   0.233687   0.2885074   -0.052000    0.248000    0.2897000
+44381.00  -0.050670   0.234679   0.2863292   -0.052000    0.249000    0.2874000
+44382.00  -0.051071   0.235667   0.2841089   -0.053000    0.250000    0.2852000
+44383.00  -0.051448   0.236653   0.2818591   -0.053000    0.250990    0.2829000
+44384.00  -0.051806   0.237638   0.2796014   -0.053000    0.252000    0.2806000
+44385.00  -0.052152   0.238627   0.2773624   -0.053000    0.253000    0.2784000
+44386.00  -0.052492   0.239621   0.2751687   -0.053000    0.254000    0.2762000
+44387.00  -0.052829   0.240622   0.2730435   -0.054000    0.255000    0.2741000
+44388.00  -0.053166   0.241634   0.2710025   -0.054000    0.256000    0.2719000
+44389.00  -0.053503   0.242657   0.2690501   -0.054000    0.257000    0.2697000
+44390.00  -0.053835   0.243694   0.2671735   -0.054000    0.257990    0.2676000
+44391.00  -0.054155   0.244745   0.2653405   -0.054000    0.259000    0.2655000
+44392.00  -0.054454   0.245810   0.2635027   -0.054000    0.260000    0.2634000
+44393.00  -0.054729   0.246888   0.2616043   -0.054000    0.261000    0.2613000
+44394.00  -0.054978   0.247978   0.2595953   -0.054000    0.262000    0.2592000
+44395.00  -0.055198   0.249076   0.2574431   -0.054000    0.263000    0.2572000
+44396.00  -0.055390   0.250181   0.2551422   -0.054000    0.264000    0.2551000
+44397.00  -0.055555   0.251291   0.2527187   -0.054000    0.264000    0.2531000
+44398.00  -0.055697   0.252403   0.2502291   -0.054000    0.264990    0.2509990
+44399.00  -0.055819   0.253518   0.2477506   -0.054000    0.266000    0.2490000
+44400.00  -0.055929   0.254635   0.2453624   -0.054000    0.266990    0.2470000
+44401.00  -0.056030   0.255754   0.2431236   -0.054000    0.268000    0.2451000
+44402.00  -0.056121   0.256876   0.2410578   -0.053000    0.268000    0.2431000
+44403.00  -0.056197   0.258000   0.2391486   -0.053000    0.269000    0.2412000
+44404.00  -0.056252   0.259130   0.2373506   -0.053000    0.270000    0.2392000
+44405.00  -0.056283   0.260267   0.2356071   -0.053000    0.271000    0.2373000
+44406.00  -0.056288   0.261414   0.2338680   -0.053000    0.271000    0.2355000
+44407.00  -0.056263   0.262575   0.2320990   -0.052000    0.272000    0.2336000
+44408.00  -0.056206   0.263751   0.2302829   -0.052000    0.272000    0.2318000
+44409.00  -0.056120   0.264944   0.2284177   -0.052000    0.273000    0.2299000
+44410.00  -0.056007   0.266154   0.2265144   -0.051000    0.273990    0.2281000
+44411.00  -0.055869   0.267379   0.2245938   -0.051000    0.273990    0.2263000
+44412.00  -0.055710   0.268620   0.2226833   -0.050000    0.275000    0.2245000
+44413.00  -0.055531   0.269874   0.2208110   -0.050000    0.275000    0.2227000
+44414.00  -0.055334   0.271140   0.2190006   -0.049000    0.276000    0.2209000
+44415.00  -0.055118   0.272416   0.2172690   -0.048000    0.277000    0.2192000
+44416.00  -0.054881   0.273700   0.2156238   -0.048000    0.277000    0.2175000
+44417.00  -0.054612   0.274989   0.2140596   -0.047000    0.278000    0.2157000
+44418.00  -0.054299   0.276282   0.2125530   -0.047000    0.278000    0.2140000
+44419.00  -0.053930   0.277574   0.2110616   -0.046000    0.279000    0.2123000
+44420.00  -0.053497   0.278865   0.2095287   -0.045000    0.280000    0.2106000
+44421.00  -0.052996   0.280150   0.2078977   -0.044000    0.280000    0.2089000
+44422.00  -0.052422   0.281429   0.2061299   -0.044000    0.280990    0.2073000
+44423.00  -0.051780   0.282702   0.2042170   -0.043000    0.280990    0.2056000
+44424.00  -0.051095   0.283971   0.2021850   -0.042000    0.282000    0.2039000
+44425.00  -0.050384   0.285238   0.2000888   -0.041000    0.283000    0.2022000
+44426.00  -0.049652   0.286501   0.1980003   -0.041000    0.283000    0.2006000
+44427.00  -0.048902   0.287755   0.1959907   -0.040000    0.284000    0.1989000
+44428.00  -0.048137   0.288998   0.1941150   -0.040000    0.284000    0.1973000
+44429.00  -0.047357   0.290226   0.1924001   -0.039000    0.285000    0.1956000
+44430.00  -0.046564   0.291435   0.1908393   -0.037990    0.286000    0.1939000
+44431.00  -0.045762   0.292623   0.1893957   -0.037990    0.287000    0.1923000
+44432.00  -0.044962   0.293793   0.1880149   -0.037000    0.287000    0.1906000
+44433.00  -0.044175   0.294946   0.1866427   -0.037000    0.287990    0.1890000
+44434.00  -0.043412   0.296085   0.1852377   -0.035990    0.289000    0.1873000
+44435.00  -0.042680   0.297212   0.1837753   -0.035000    0.290000    0.1857000
+44436.00  -0.041982   0.298330   0.1822469   -0.035000    0.291000    0.1841000
+44437.00  -0.041317   0.299440   0.1806576   -0.034000    0.291000    0.1824000
+44438.00  -0.040682   0.300543   0.1790231   -0.034000    0.292000    0.1808000
+44439.00  -0.040070   0.301639   0.1773670   -0.033000    0.293000    0.1792000
+44440.00  -0.039481   0.302728   0.1757154   -0.032000    0.294000    0.1776000
+44441.00  -0.038915   0.303805   0.1740930   -0.032000    0.294000    0.1760000
+44442.00  -0.038378   0.304868   0.1725194   -0.031000    0.294990    0.1743000
+44443.00  -0.037876   0.305911   0.1710052   -0.031000    0.294990    0.1727000
+44444.00  -0.037416   0.306930   0.1695499   -0.030000    0.296000    0.1711000
+44445.00  -0.037005   0.307918   0.1681384   -0.030000    0.297000    0.1695000
+44446.00  -0.036652   0.308869   0.1667384   -0.029000    0.297000    0.1679000
+44447.00  -0.036373   0.309774   0.1653007   -0.029000    0.298000    0.1662000
+44448.00  -0.036176   0.310620   0.1637689   -0.028000    0.298000    0.1646000
+44449.00  -0.036043   0.311387   0.1620941   -0.028000    0.299000    0.1630000
+44450.00  -0.035959   0.312081   0.1602557   -0.028000    0.299000    0.1614000
+44451.00  -0.035911   0.312715   0.1582745   -0.027000    0.300000    0.1598000
+44452.00  -0.035885   0.313299   0.1562108   -0.027000    0.300000    0.1581000
+44453.00  -0.035873   0.313843   0.1541461   -0.026000    0.301000    0.1565000
+44454.00  -0.035866   0.314353   0.1521605   -0.026000    0.301000    0.1549000
+44455.00  -0.035856   0.314838   0.1503126   -0.026000    0.301990    0.1533000
+44456.00  -0.035834   0.315303   0.1486280   -0.025000    0.301990    0.1517000
+44457.00  -0.035796   0.315753   0.1470977   -0.025000    0.303000    0.1500000
+44458.00  -0.035736   0.316194   0.1456845   -0.024000    0.303000    0.1484000
+44459.00  -0.035652   0.316631   0.1443340   -0.024000    0.303990    0.1468000
+44460.00  -0.035543   0.317071   0.1429894   -0.024000    0.305000    0.1451000
+44461.00  -0.035410   0.317518   0.1416036   -0.023000    0.305000    0.1435000
+44462.00  -0.035258   0.317974   0.1401463   -0.023000    0.306000    0.1418000
+44463.00  -0.035091   0.318443   0.1386056   -0.022000    0.306000    0.1402000
+44464.00  -0.034914   0.318927   0.1369849   -0.022000    0.307000    0.1385000
+44465.00  -0.034730   0.319428   0.1352991   -0.022000    0.308000    0.1368000
+44466.00  -0.034545   0.319948   0.1335716   -0.021000    0.308000    0.1351000
+44467.00  -0.034361   0.320488   0.1318295   -0.021000    0.308990    0.1333000
+44468.00  -0.034185   0.321048   0.1300996   -0.020000    0.308990    0.1316000
+44469.00  -0.034021   0.321629   0.1284021   -0.020000    0.310000    0.1298990
+44470.00  -0.033876   0.322231   0.1267463   -0.020000    0.310990    0.1280990
+44471.00  -0.033753   0.322852   0.1251295   -0.020000    0.310990    0.1263000
+44472.00  -0.033655   0.323491   0.1235369   -0.018990    0.312000    0.1244000
+44473.00  -0.033585   0.324146   0.1219387   -0.018990    0.312000    0.1226000
+44474.00  -0.033544   0.324811   0.1202889   -0.018990    0.313000    0.1208000
+44475.00  -0.033532   0.325482   0.1185273   -0.018990    0.313000    0.1189000
+44476.00  -0.033545   0.326154   0.1165928   -0.018990    0.314000    0.1170000
+44477.00  -0.033575   0.326823   0.1144442   -0.017990    0.314000    0.1151000
+44478.00  -0.033616   0.327484   0.1120823   -0.017990    0.315000    0.1132000
+44479.00  -0.033658   0.328135   0.1095587   -0.017990    0.315000    0.1113000
+44480.00  -0.033692   0.328774   0.1069650   -0.017990    0.315000    0.1093000
+44481.00  -0.033706   0.329403   0.1044053   -0.017990    0.316000    0.1073000
+44482.00  -0.033692   0.330022   0.1019650   -0.017000    0.316000    0.1052000
+44483.00  -0.033648   0.330632   0.0996895   -0.017000    0.317000    0.1032000
+44484.00  -0.033568   0.331235   0.0975787   -0.017000    0.317000    0.1012000
+44485.00  -0.033449   0.331832   0.0955965   -0.017000    0.317990    0.0991000
+44486.00  -0.033291   0.332424   0.0936871   -0.016000    0.317990    0.0969000
+44487.00  -0.033093   0.333013   0.0917909   -0.016000    0.319000    0.0948000
+44488.00  -0.032856   0.333598   0.0898578   -0.015000    0.319000    0.0926000
+44489.00  -0.032585   0.334183   0.0878542   -0.015000    0.320000    0.0905000
+44490.00  -0.032281   0.334766   0.0857654   -0.015000    0.321000    0.0883000
+44491.00  -0.031950   0.335350   0.0835940   -0.014000    0.321000    0.0861000
+44492.00  -0.031593   0.335936   0.0813562   -0.014000    0.322000    0.0838000
+44493.00  -0.031215   0.336526   0.0790771   -0.013000    0.322000    0.0816000
+44494.00  -0.030818   0.337119   0.0767870   -0.013000    0.323000    0.0794000
+44495.00  -0.030404   0.337719   0.0745165   -0.013000    0.324000    0.0771000
+44496.00  -0.029974   0.338327   0.0722922   -0.012000    0.324000    0.0748000
+44497.00  -0.029527   0.338943   0.0701300   -0.012000    0.324990    0.0724000
+44498.00  -0.029065   0.339567   0.0680318   -0.011000    0.324990    0.0701000
+44499.00  -0.028584   0.340199   0.0659849   -0.011000    0.326000    0.0678000
+44500.00  -0.028086   0.340837   0.0639626   -0.011000    0.327000    0.0653990
+44501.00  -0.027570   0.341480   0.0619229   -0.010000    0.327000    0.0630000
+44502.00  -0.027034   0.342124   0.0598094   -0.010000    0.328000    0.0607000
+44503.00  -0.026481   0.342766   0.0575568   -0.008990    0.328000    0.0583000
+44504.00  -0.025918   0.343399   0.0551051   -0.008990    0.329000    0.0559000
+44505.00  -0.025350   0.344019   0.0524227   -0.008990    0.330000    0.0534000
+44506.00  -0.024784   0.344617   0.0495267   -0.008000    0.331000    0.0510000
+44507.00  -0.024228   0.345183   0.0464885   -0.008000    0.332000    0.0485000
+44508.00  -0.023692   0.345704   0.0434152   -0.007000    0.333000    0.0461000
+44509.00  -0.023185   0.346167   0.0404165   -0.007000    0.334000    0.0436000
+44510.00  -0.022722   0.346558   0.0375738   -0.007000    0.335000    0.0411000
+44511.00  -0.022320   0.346877   0.0349343   -0.007000    0.336000    0.0385000
+44512.00  -0.021988   0.347173   0.0324995   -0.006000    0.337000    0.0360000
+44513.00  -0.021717   0.347498   0.0302196   -0.006000    0.338000    0.0334000
+44514.00  -0.021472   0.347867   0.0280224   -0.006000    0.339000    0.0309000
+44515.00  -0.021217   0.348281   0.0258395   -0.006000    0.340000    0.0283000
+44516.00  -0.020922   0.348738   0.0236201   -0.006000    0.341000    0.0258000
+44517.00  -0.020573   0.349238   0.0213366   -0.005000    0.341000    0.0232000
+44518.00  -0.020162   0.349784   0.0189812   -0.005000    0.342000    0.0207000
+44519.00  -0.019683   0.350378   0.0165613   -0.005000    0.343000    0.0181000
+44520.00  -0.019138   0.351018   0.0140960   -0.005000    0.344000    0.0155000
+44521.00  -0.018535   0.351705   0.0116109   -0.005000    0.345000    0.0129000
+44522.00  -0.017881   0.352436   0.0091350   -0.004000    0.345000    0.0103000
+44523.00  -0.017190   0.353206   0.0066954   -0.004000    0.346000    0.0077000
+44524.00  -0.016473   0.354013   0.0043126   -0.004000    0.347000    0.0051000
+44525.00  -0.015748   0.354848   0.0019960   -0.004000    0.348000    0.0025000
+44526.00  -0.015032   0.355706  -0.0002604   -0.004000    0.349000   -0.0002000
+44527.00  -0.014340   0.356578  -0.0024781   -0.004000    0.349000   -0.0028000
+44528.00  -0.013690   0.357455  -0.0046917   -0.004000    0.350000   -0.0055000
+44529.00  -0.013099   0.358326  -0.0069477   -0.004000    0.351000   -0.0081000
+44530.00  -0.012591   0.359173  -0.0093009   -0.004000    0.352000   -0.0108000
+44531.00  -0.012196   0.359957  -0.0118060   -0.004000    0.353000   -0.0135000
+44532.00  -0.011860   0.360634  -0.0145143   -0.004000    0.353000   -0.0161000
+44533.00  -0.011534   0.361203  -0.0174444   -0.004000    0.354000   -0.0188000
+44534.00  -0.011167   0.361676  -0.0205670   -0.004000    0.355000   -0.0215000
+44535.00  -0.010731   0.362085  -0.0237945   -0.004000    0.356000   -0.0242000
+44536.00  -0.010254   0.362467  -0.0270050   -0.004000    0.357000   -0.0268000
+44537.00  -0.009746   0.362830  -0.0300888   -0.005000    0.358000   -0.0295000
+44538.00  -0.009207   0.363175  -0.0329788   -0.005000    0.359000   -0.0321000
+44539.00  -0.008637   0.363503  -0.0356645   -0.005000    0.360000   -0.0348000
+44540.00  -0.008038   0.363816  -0.0381850   -0.005000    0.361000   -0.0375000
+44541.00  -0.007413   0.364115  -0.0406058   -0.006000    0.362000   -0.0402000
+44542.00  -0.006765   0.364402  -0.0429935   -0.006000    0.363000   -0.0428000
+44543.00  -0.006092   0.364677  -0.0453991   -0.007000    0.364000   -0.0455000
+44544.00  -0.005390   0.364943  -0.0478520   -0.007000    0.365000   -0.0482000
+44545.00  -0.004658   0.365200  -0.0503616   -0.007000    0.366000   -0.0508000
+44546.00  -0.003896   0.365451  -0.0529205   -0.007000    0.366000   -0.0534000
+44547.00  -0.003106   0.365698  -0.0555091   -0.006000    0.367000   -0.0560000
+44548.00  -0.002287   0.365945  -0.0581001   -0.006000    0.367000   -0.0586000
+44549.00  -0.001437   0.366193  -0.0606628   -0.006000    0.368000   -0.0612000
+44550.00  -0.000553   0.366443  -0.0631675   -0.006000    0.369000   -0.0638000
+44551.00   0.000371   0.366696  -0.0655907   -0.005000    0.369000   -0.0664000
+44552.00   0.001340   0.366953  -0.0679193   -0.005000    0.370000   -0.0689000
+44553.00   0.002361   0.367214  -0.0701540   -0.004000    0.370000   -0.0715000
+44554.00   0.003438   0.367480  -0.0723119   -0.004000    0.371000   -0.0741000
+44555.00   0.004576   0.367750  -0.0744269   -0.003000    0.371000   -0.0767000
+44556.00   0.005773   0.368025  -0.0765465   -0.002000    0.372000   -0.0792000
+44557.00   0.007027   0.368305  -0.0787259   -0.002000    0.372000   -0.0818000
+44558.00   0.008338   0.368590  -0.0810214   -0.001000    0.373000   -0.0843000
+44559.00   0.009704   0.368879  -0.0834809    0.000000    0.373000   -0.0869000
+44560.00   0.011124   0.369171  -0.0861313    0.001000    0.373000   -0.0894000
+44561.00   0.012595   0.369466  -0.0889644    0.002000    0.374000   -0.0919000
+44562.00   0.014116   0.369758  -0.0919282    0.004000    0.374000   -0.0945000
+44563.00   0.015682   0.370042  -0.0949346    0.005000    0.375000   -0.0970000
+44564.00   0.017292   0.370316  -0.0978809    0.006000    0.375000   -0.0995000
+44565.00   0.018944   0.370574  -0.1006828    0.007000    0.375000   -0.1020000
+44566.00   0.020631   0.370816  -0.1033006    0.008000    0.376000   -0.1045000
+44567.00   0.022349   0.371039  -0.1057468    0.010000    0.376000   -0.1069000
+44568.00   0.024091   0.371242  -0.1080740    0.011000    0.377000   -0.1094000
+44569.00   0.025851   0.371423  -0.1103500    0.012000    0.377000   -0.1119000
+44570.00   0.027614   0.371580  -0.1126341    0.013000    0.377000   -0.1143000
+44571.00   0.029368   0.371712  -0.1149645    0.014000    0.377000   -0.1168000
+44572.00   0.031095   0.371818  -0.1173563    0.016000    0.378000   -0.1192000
+44573.00   0.032776   0.371896  -0.1198056    0.017000    0.378000   -0.1217000
+44574.00   0.034394   0.371947  -0.1222956    0.018000    0.378000   -0.1241000
+44575.00   0.035930   0.371968  -0.1248005    0.019000    0.378000   -0.1265000
+44576.00   0.037371   0.371959  -0.1272907    0.021000    0.378000   -0.1289000
+44577.00   0.038728   0.371917  -0.1297379    0.022000    0.377000   -0.1314000
+44578.00   0.040017   0.371841  -0.1321190    0.024000    0.377000   -0.1338000
+44579.00   0.041254   0.371728  -0.1344185    0.025000    0.377000   -0.1362000
+44580.00   0.042454   0.371577  -0.1366321    0.026000    0.377000   -0.1386000
+44581.00   0.043634   0.371385  -0.1387701    0.028000    0.376000   -0.1410000
+44582.00   0.044806   0.371153  -0.1408587    0.029000    0.376000   -0.1434000
+44583.00   0.045978   0.370882  -0.1429387    0.031000    0.375000   -0.1458000
+44584.00   0.047160   0.370575  -0.1450613    0.032000    0.375000   -0.1482000
+44585.00   0.048360   0.370233  -0.1472792    0.033000    0.374000   -0.1506000
+44586.00   0.049583   0.369860  -0.1496355    0.034000    0.374000   -0.1530000
+44587.00   0.050829   0.369458  -0.1521542    0.036000    0.373000   -0.1553000
+44588.00   0.052094   0.369033  -0.1548320    0.037000    0.373000   -0.1577000
+44589.00   0.053373   0.368587  -0.1576339    0.038000    0.372000   -0.1601000
+44590.00   0.054663   0.368127  -0.1604947    0.039000    0.371000   -0.1625000
+44591.00   0.055958   0.367656  -0.1633315    0.040000    0.371000   -0.1649000
+44592.00   0.057255   0.367181  -0.1660643    0.042000    0.370000   -0.1672000
+44593.00   0.058546   0.366708  -0.1686409    0.043000    0.370000   -0.1696000
+44594.00   0.059819   0.366243  -0.1710521    0.044000    0.369000   -0.1720000
+44595.00   0.061068   0.365777  -0.1733318    0.045000    0.368000   -0.1744000
+44596.00   0.062292   0.365303  -0.1755406    0.046000    0.368000   -0.1768000
+44597.00   0.063487   0.364811  -0.1777423    0.048000    0.367000   -0.1791000
+44598.00   0.064652   0.364297  -0.1799847    0.049000    0.367000   -0.1815000
+44599.00   0.065782   0.363758  -0.1822914    0.050000    0.366000   -0.1839000
+44600.00   0.066876   0.363194  -0.1846637    0.051000    0.365000   -0.1863000
+44601.00   0.067929   0.362608  -0.1870873    0.052000    0.364000   -0.1886000
+44602.00   0.068940   0.362000  -0.1895385    0.053000    0.364000   -0.1910000
+44603.00   0.069905   0.361371  -0.1919885    0.054000    0.363000   -0.1933000
+44604.00   0.070820   0.360722  -0.1944082    0.055000    0.362000   -0.1957000
+44605.00   0.071683   0.360054  -0.1967724    0.056000    0.361000   -0.1981000
+44606.00   0.072490   0.359365  -0.1990643    0.057000    0.360000   -0.2004000
+44607.00   0.073235   0.358658  -0.2012778    0.057000    0.360000   -0.2028000
+44608.00   0.073915   0.357930  -0.2034193    0.058000    0.359000   -0.2051000
+44609.00   0.074525   0.357183  -0.2055098    0.059000    0.358000   -0.2075000
+44610.00   0.075064   0.356414  -0.2075860    0.060000    0.357000   -0.2099000
+44611.00   0.075536   0.355623  -0.2096986    0.060000    0.356000   -0.2122000
+44612.00   0.075945   0.354805  -0.2119034    0.061000    0.355000   -0.2146000
+44613.00   0.076296   0.353958  -0.2142488    0.061000    0.354000   -0.2169000
+44614.00   0.076594   0.353079  -0.2167605    0.062000    0.353000   -0.2193000
+44615.00   0.076842   0.352166  -0.2194331    0.062000    0.352000   -0.2216000
+44616.00   0.077049   0.351219  -0.2222276    0.063000    0.351000   -0.2239000
+44617.00   0.077220   0.350241  -0.2250792    0.063000    0.350000   -0.2263000
+44618.00   0.077364   0.349233  -0.2279115    0.064000    0.349000   -0.2286000
+44619.00   0.077487   0.348200  -0.2306522    0.064000    0.348000   -0.2309000
+44620.00   0.077597   0.347144  -0.2332501    0.064000    0.347000   -0.2332000
+44621.00   0.077698   0.346074  -0.2356873    0.065000    0.346000   -0.2355000
+44622.00   0.077796   0.345000  -0.2379834    0.065000    0.346000   -0.2379000
+44623.00   0.077897   0.343929  -0.2401875    0.066000    0.345000   -0.2402000
+44624.00   0.078006   0.342872  -0.2423598    0.066000    0.344000   -0.2425000
+44625.00   0.078128   0.341837  -0.2445519    0.066000    0.343000   -0.2448000
+44626.00   0.078270   0.340832  -0.2467935    0.067000    0.342000   -0.2471000
+44627.00   0.078438   0.339867  -0.2490897    0.067000    0.342000   -0.2493000
+44628.00   0.078639   0.338947  -0.2514260    0.068000    0.341000   -0.2516000
+44629.00   0.078874   0.338070  -0.2537780    0.068000    0.340000   -0.2539000
+44630.00   0.079143   0.337230  -0.2561161    0.068000    0.339000   -0.2562000
+44631.00   0.079447   0.336422  -0.2584095    0.069000    0.339000   -0.2584000
+44632.00   0.079787   0.335641  -0.2606311    0.069000    0.338000   -0.2607000
+44633.00   0.080160   0.334884  -0.2627623    0.070000    0.338000   -0.2629000
+44634.00   0.080567   0.334149  -0.2647967    0.070000    0.337000   -0.2652000
+44635.00   0.081002   0.333433  -0.2667414    0.070000    0.336000   -0.2674000
+44636.00   0.081459   0.332735  -0.2686169    0.071000    0.335000   -0.2697000
+44637.00   0.081926   0.332049  -0.2704577    0.071000    0.335000   -0.2719000
+44638.00   0.082394   0.331372  -0.2723128    0.072000    0.334000   -0.2742000
+44639.00   0.082853   0.330701  -0.2742421    0.072000    0.333000   -0.2764000
+44640.00   0.083296   0.330031  -0.2763049    0.073000    0.332000   -0.2787000
+44641.00   0.083721   0.329357  -0.2785419    0.073000    0.331000   -0.2810000
+44642.00   0.084131   0.328675  -0.2809579    0.074000    0.330000   -0.2833000
+44643.00   0.084534   0.327978  -0.2835154    0.074000    0.329000   -0.2856000
+44644.00   0.084935   0.327264  -0.2861427    0.075000    0.328000   -0.2879000
+44645.00   0.085339   0.326526  -0.2887526    0.076000    0.327000   -0.2902000
+44646.00   0.085753   0.325761  -0.2912661    0.076000    0.326000   -0.2925000
+44647.00   0.086171   0.324966  -0.2936321    0.077000    0.325000   -0.2949000
+44648.00   0.086582   0.324142  -0.2958376    0.077000    0.324000   -0.2972000
+44649.00   0.086975   0.323288  -0.2979063    0.078000    0.323000   -0.2995000
+44650.00   0.087342   0.322406  -0.2998904    0.079000    0.322000   -0.3019000
+44651.00   0.087683   0.321500  -0.3018556    0.079000    0.321000   -0.3043000
+44652.00   0.087995   0.320574  -0.3038641    0.080000    0.320000   -0.3066000
+44653.00   0.088275   0.319631  -0.3059601    0.080000    0.319000   -0.3090000
+44654.00   0.088523   0.318674  -0.3081632    0.081000    0.318000   -0.3114000
+44655.00   0.088735   0.317707  -0.3104694    0.082000    0.317000   -0.3138000
+44656.00   0.088911   0.316734  -0.3128585    0.082000    0.316000   -0.3162000
+44657.00   0.089055   0.315759  -0.3153014    0.083000    0.315000   -0.3187000
+44658.00   0.089169   0.314787  -0.3177663    0.083000    0.314000   -0.3211000
+44659.00   0.089258   0.313822  -0.3202234    0.084000    0.313000   -0.3235000
+44660.00   0.089324   0.312869  -0.3226500    0.084000    0.312000   -0.3260000
+44661.00   0.089374   0.311931  -0.3250343    0.085000    0.311000   -0.3285000
+44662.00   0.089414   0.311013  -0.3273788    0.085000    0.311000   -0.3309000
+44663.00   0.089444   0.310118  -0.3297000    0.086000    0.310000   -0.3334000
+44664.00   0.089465   0.309250  -0.3320271    0.086000    0.309000   -0.3359000
+44665.00   0.089485   0.308410  -0.3343997    0.086000    0.308000   -0.3384000
+44666.00   0.089511   0.307600  -0.3368684    0.087000    0.307000   -0.3410000
+44667.00   0.089556   0.306819  -0.3394912    0.087000    0.307000   -0.3435000
+44668.00   0.089628   0.306068  -0.3423190    0.088000    0.306000   -0.3461000
+44669.00   0.089735   0.305347  -0.3453741    0.088000    0.305000   -0.3486000
+44670.00   0.089884   0.304656  -0.3486333    0.088000    0.304000   -0.3512000
+44671.00   0.090081   0.303995  -0.3520246    0.088000    0.303000   -0.3537000
+44672.00   0.090330   0.303357  -0.3554424    0.089000    0.303000   -0.3563000
+44673.00   0.090635   0.302736  -0.3587773    0.089000    0.302000   -0.3588000
+44674.00   0.090999   0.302126  -0.3619463    0.089000    0.301000   -0.3614000
+44675.00   0.091420   0.301521  -0.3649125    0.089000    0.300000   -0.3640000
+44676.00   0.091892   0.300917  -0.3676865    0.089000    0.299000   -0.3666000
+44677.00   0.092409   0.300309  -0.3703147    0.089000    0.299000   -0.3691000
+44678.00   0.092963   0.299696  -0.3728610    0.089000    0.298000   -0.3717000
+44679.00   0.093548   0.299077  -0.3753878    0.089000    0.297000   -0.3743000
+44680.00   0.094158   0.298450  -0.3779422    0.089000    0.296000   -0.3769000
+44681.00   0.094786   0.297814  -0.3805484    0.089000    0.296000   -0.3795000
+44682.00   0.095427   0.297169  -0.3832082    0.089000    0.295000   -0.3821000
+44683.00   0.096077   0.296513  -0.3859045    0.089000    0.295000   -0.3847000
+44684.00   0.096730   0.295846  -0.3886086    0.089000    0.294000   -0.3873000
+44685.00   0.097382   0.295168  -0.3912862    0.089000    0.293000   -0.3899000
+44686.00   0.098029   0.294476  -0.3939040    0.089000    0.292000   -0.3926000
+44687.00   0.098666   0.293764  -0.3964337    0.089000    0.292000   -0.3952000
+44688.00   0.099288   0.293029  -0.3988580    0.089000    0.291000   -0.3979000
+44689.00   0.099892   0.292266  -0.4011740    0.089000    0.290000   -0.4005000
+44690.00   0.100472   0.291472  -0.4033956    0.089000    0.289000   -0.4031000
+44691.00   0.101022   0.290643  -0.4055526    0.089000    0.288000   -0.4058000
+44692.00   0.101536   0.289778  -0.4076876    0.088000    0.288000   -0.4084000
+44693.00   0.102008   0.288877  -0.4098543    0.088000    0.287000   -0.4111000
+44694.00   0.102433   0.287939  -0.4121152    0.088000    0.286000   -0.4137000
+44695.00   0.102804   0.286963  -0.4145355    0.088000    0.285000   -0.4164000
+44696.00   0.103118   0.285951  -0.4171670    0.088000    0.284000   -0.4191000
+44697.00   0.103374   0.284904  -0.4200277    0.087000    0.283000   -0.4217000
+44698.00   0.103570   0.283826  -0.4230844    0.087000    0.282000   -0.4244000
+44699.00   0.103706   0.282720  -0.4262527    0.087000    0.281000   -0.4271000
+44700.00   0.103787   0.281591  -0.4294194    0.087000    0.280000   -0.4298000
+44701.00   0.103815   0.280444  -0.4324794    0.087000    0.279000   -0.4326000
+44702.00   0.103796   0.279284  -0.4353684    0.087000    0.279000   -0.4353000
+44703.00   0.103731   0.278118  -0.4380784    0.087000    0.278000   -0.4381000
+44704.00   0.103622   0.276950  -0.4406514    0.087000    0.277000   -0.4408000
+44705.00   0.103472   0.275789  -0.4431571    0.087000    0.276000   -0.4435000
+44706.00   0.103281   0.274641  -0.4456681    0.087000    0.276000   -0.4462000
+44707.00   0.103048   0.273513  -0.4482414    0.087000    0.275000   -0.4490000
+44708.00   0.102772   0.272412  -0.4509090    0.087000    0.275000   -0.4517000
+44709.00   0.102451   0.271342  -0.4536782    0.087000    0.274000   -0.4544000
+44710.00   0.102084   0.270310  -0.4565359    0.087000    0.273000   -0.4571000
+44711.00   0.101671   0.269319  -0.4594538    0.087000    0.273000   -0.4598000
+44712.00   0.101215   0.268373  -0.4623949    0.087000    0.272000   -0.4626000
+44713.00   0.100723   0.267472  -0.4653187    0.087000    0.272000   -0.4653000
+44714.00   0.100204   0.266611  -0.4681860    0.087000    0.271000   -0.4680000
+44715.00   0.099670   0.265784  -0.4709654    0.087000    0.270000   -0.4707000
+44716.00   0.099132   0.264986  -0.4736384    0.087000    0.270000   -0.4734000
+44717.00   0.098598   0.264212  -0.4762027    0.087000    0.269000   -0.4761000
+44718.00   0.098078   0.263458  -0.4786745    0.087000    0.269000   -0.4788000
+44719.00   0.097577   0.262721  -0.4810851    0.087000    0.268000   -0.4815000
+44720.00   0.097098   0.262000  -0.4834781    0.087000    0.267000   -0.4841000
+44721.00   0.096643   0.261292  -0.4859053    0.087000    0.266000   -0.4868000
+44722.00   0.096213   0.260597  -0.4884219    0.087000    0.266000   -0.4894000
+44723.00   0.095810   0.259912  -0.4910793    0.087000    0.265000   -0.4921000
+44724.00   0.095437   0.259235  -0.4939106    0.087000    0.264000   -0.4947000
+44725.00   0.095099   0.258566  -0.4969117    0.087000    0.263000   -0.4973000
+44726.00   0.094796   0.257901  -0.5000299    0.087000    0.263000   -0.4999000
+44727.00   0.094526   0.257240  -0.5031687    0.086000    0.262000   -0.5025000
+44728.00   0.094287   0.256579  -0.5062135    0.086000    0.262000   -0.5051000
+44729.00   0.094077   0.255917  -0.5090697    0.086000    0.261000   -0.5077000
+44730.00   0.093897   0.255250  -0.5116939    0.086000    0.260000   -0.5102000
+44731.00   0.093746   0.254576  -0.5141026    0.086000    0.259000   -0.5127000
+44732.00   0.093621   0.253891  -0.5163592    0.086000    0.259000   -0.5153000
+44733.00   0.093517   0.253193  -0.5185444    0.086000    0.258000   -0.5178000
+44734.00   0.093428   0.252480  -0.5207305    0.086000    0.257000   -0.5203000
+44735.00   0.093349   0.251752  -0.5229648    0.086000    0.256000   -0.5227000
+44736.00   0.093274   0.251007  -0.5252670    0.086000    0.255000   -0.5251000
+44737.00   0.093197   0.250245  -0.5276341    0.086000    0.255000   -0.5276000
+44738.00   0.093113   0.249466  -0.5300478    0.086000    0.254000   -0.5300000
+44739.00   0.093014   0.248669  -0.5324811    0.086000    0.253000   -0.5324000
+44740.00   0.092896   0.247853  -0.5349032    0.086000    0.252000   -0.5348000
+44741.00   0.092753   0.247018  -0.5372836    0.086000    0.251000   -0.5371000
+44742.00   0.092580   0.246162  -0.5395967    0.086000    0.251000   -0.5395000
+44743.00   0.092374   0.245286  -0.5418269    0.086000    0.250000   -0.5418000
+44744.00   0.092128   0.244389  -0.5439719    0.086000    0.249000   -0.5442000
+44745.00   0.091841   0.243473  -0.5460448    0.086000    0.248000   -0.5465000
+44746.00   0.091507   0.242539  -0.5480747    0.086000    0.247000   -0.5488000
+44747.00   0.091128   0.241590  -0.5501027    0.086000    0.246000   -0.5511000
+44748.00   0.090703   0.240630  -0.5521769    0.086000    0.245000   -0.5534000
+44749.00   0.090233   0.239660  -0.5543473    0.086000    0.244000   -0.5557000
+44750.00   0.089719   0.238686  -0.5566596    0.086000    0.243000   -0.5580000
+44751.00   0.089165   0.237709  -0.5591475    0.086000    0.242000   -0.5602000
+44752.00   0.088574   0.236737  -0.5618204    0.085000    0.241000   -0.5625000
+44753.00   0.087953   0.235775  -0.5646512    0.085000    0.240000   -0.5647000
+44754.00   0.087307   0.234829  -0.5675712    0.085000    0.239000   -0.5670000
+44755.00   0.086642   0.233906  -0.5704801    0.085000    0.238000   -0.5692000
+44756.00   0.085963   0.233012  -0.5732731    0.085000    0.237000   -0.5713000
+44757.00   0.085277   0.232152  -0.5758756    0.085000    0.236000   -0.5735000
+44758.00   0.084589   0.231328  -0.5782669    0.085000    0.235000   -0.5756000
+44759.00   0.083908   0.230536  -0.5804817    0.085000    0.234000   -0.5778000
+44760.00   0.083242   0.229771  -0.5825897    0.085000    0.233000   -0.5799000
+44761.00   0.082595   0.229030  -0.5846656    0.085000    0.232000   -0.5819000
+44762.00   0.081969   0.228306  -0.5867638    0.084000    0.232000   -0.5840000
+44763.00   0.081359   0.227593  -0.5889077    0.084000    0.231000   -0.5860000
+44764.00   0.080762   0.226886  -0.5910926    0.084000    0.230000   -0.5881000
+44765.00   0.080177   0.226178  -0.5932950    0.084000    0.229000   -0.5900000
+44766.00   0.079601   0.225466  -0.5954823    0.083000    0.228000   -0.5920000
+44767.00   0.079033   0.224744  -0.5976188    0.083000    0.227000   -0.5939000
+44768.00   0.078473   0.224009  -0.5996709    0.082000    0.226000   -0.5959000
+44769.00   0.077923   0.223258  -0.6016105    0.082000    0.225000   -0.5978000
+44770.00   0.077383   0.222489  -0.6034192    0.082000    0.224000   -0.5996000
+44771.00   0.076854   0.221699  -0.6050920    0.081000    0.223000   -0.6014000
+44772.00   0.076331   0.220890  -0.6066392    0.081000    0.223000   -0.6033000
+44773.00   0.075810   0.220065  -0.6080868    0.080000    0.222000   -0.6051000
+44774.00   0.075287   0.219227  -0.6094747    0.080000    0.221000   -0.6069000
+44775.00   0.074760   0.218381  -0.6108528    0.080000    0.220000   -0.6086000
+44776.00   0.074228   0.217529  -0.6122734    0.079000    0.219000   -0.6103000
+44777.00   0.073692   0.216671  -0.6137833    0.079000    0.218000   -0.6120000
+44778.00   0.073151   0.215806  -0.6154147    0.078000    0.217000   -0.6137000
+44779.00   0.072607   0.214934  -0.6171786    0.078000    0.216000   -0.6154000
+44780.00   0.072064   0.214053  -0.6190588    0.078000    0.215000   -0.6170000
+44781.00   0.071529   0.213163  -0.6210088    0.077000    0.214000   -0.6186000
+44782.00   0.071005   0.212264  -0.6229551    0.077000    0.213000   -0.6201000
+44783.00   0.070500   0.211356  -0.6248128    0.076000    0.212000   -0.6217000
+44784.00   0.070017   0.210444  -0.6265089    0.076000    0.211000   -0.6233000
+44785.00   0.069562   0.209527  -0.6280070    0.076000    0.210000   -0.6248000
+44786.00   0.069135   0.208610   0.3706787    0.075000    0.209000    0.3738000
+44787.00   0.068727   0.207692   0.3694899    0.075000    0.208000    0.3723000
+44788.00   0.068327   0.206774   0.3683480    0.074000    0.207000    0.3709000
+44789.00   0.067935   0.205857   0.3671843    0.074000    0.206000    0.3694000
+44790.00   0.067552   0.204942   0.3659587    0.073000    0.205000    0.3680000
+44791.00   0.067176   0.204031   0.3646653    0.073000    0.204000    0.3666000
+44792.00   0.066808   0.203123   0.3633237    0.072000    0.204000    0.3651000
+44793.00   0.066442   0.202222   0.3619672    0.072000    0.203000    0.3637000
+44794.00   0.066073   0.201328   0.3606327    0.071000    0.202000    0.3623000
+44795.00   0.065696   0.200444   0.3593538    0.070000    0.201000    0.3609000
+44796.00   0.065302   0.199571   0.3581575    0.069000    0.200000    0.3596000
+44797.00   0.064885   0.198710   0.3570599    0.069000    0.200000    0.3582000
+44798.00   0.064440   0.197866   0.3560642    0.068000    0.199000    0.3569000
+44799.00   0.063959   0.197041   0.3551590    0.067000    0.198000    0.3555000
+44800.00   0.063435   0.196238   0.3543187    0.066000    0.197000    0.3542000
+44801.00   0.062865   0.195458   0.3535035    0.065000    0.196000    0.3529000
+44802.00   0.062243   0.194704   0.3526621    0.064000    0.196000    0.3515000
+44803.00   0.061567   0.193973   0.3517366    0.063000    0.195000    0.3502000
+44804.00   0.060837   0.193262   0.3506726    0.062000    0.194000    0.3489000
+44805.00   0.060054   0.192568   0.3494308    0.061000    0.193000    0.3476000
+44806.00   0.059219   0.191888   0.3479970    0.060000    0.193000    0.3462000
+44807.00   0.058334   0.191218   0.3463884    0.059000    0.192000    0.3449000
+44808.00   0.057398   0.190553   0.3446521    0.058000    0.192000    0.3435000
+44809.00   0.056412   0.189891   0.3428561    0.057000    0.191000    0.3422000
+44810.00   0.055375   0.189230   0.3410767    0.056000    0.190000    0.3408000
+44811.00   0.054287   0.188569   0.3393814    0.055000    0.190000    0.3394000
+44812.00   0.053147   0.187908   0.3378102    0.054000    0.189000    0.3380000
+44813.00   0.051952   0.187248   0.3363637    0.053000    0.189000    0.3366000
+44814.00   0.050703   0.186592   0.3350022    0.052000    0.188000    0.3352000
+44815.00   0.049399   0.185946   0.3336592    0.051000    0.187000    0.3337000
+44816.00   0.048043   0.185316   0.3322658    0.050000    0.187000    0.3323000
+44817.00   0.046639   0.184711   0.3307738    0.049000    0.186000    0.3308000
+44818.00   0.045190   0.184134   0.3291684    0.048000    0.186000    0.3294000
+44819.00   0.043700   0.183590   0.3274667    0.047000    0.185000    0.3279000
+44820.00   0.042171   0.183082   0.3257067    0.046000    0.185000    0.3264000
+44821.00   0.040604   0.182613   0.3239344    0.045000    0.184000    0.3250000
+44822.00   0.039001   0.182187   0.3221940    0.043000    0.184000    0.3235000
+44823.00   0.037364   0.181810   0.3205223    0.042000    0.183000    0.3221000
+44824.00   0.035693   0.181488   0.3189449    0.041000    0.183000    0.3206000
+44825.00   0.033992   0.181224   0.3174735    0.040000    0.183000    0.3191000
+44826.00   0.032265   0.181021   0.3161045    0.038000    0.183000    0.3176000
+44827.00   0.030516   0.180881   0.3148191    0.037000    0.182000    0.3161000
+44828.00   0.028750   0.180802   0.3135857    0.035000    0.182000    0.3146000
+44829.00   0.026974   0.180777   0.3123613    0.034000    0.182000    0.3131000
+44830.00   0.025195   0.180800   0.3110942    0.033000    0.182000    0.3116000
+44831.00   0.023416   0.180862   0.3097288    0.031000    0.182000    0.3100000
+44832.00   0.021640   0.180959   0.3082181    0.030000    0.181000    0.3085000
+44833.00   0.019869   0.181085   0.3065392    0.028000    0.181000    0.3069000
+44834.00   0.018106   0.181235   0.3047050    0.027000    0.181000    0.3054000
+44835.00   0.016361   0.181406   0.3027657    0.025000    0.181000    0.3038000
+44836.00   0.014640   0.181598   0.3007986    0.024000    0.181000    0.3022000
+44837.00   0.012948   0.181808   0.2988884    0.022000    0.181000    0.3006000
+44838.00   0.011288   0.182037   0.2971055    0.021000    0.181000    0.2990000
+44839.00   0.009661   0.182284   0.2954891    0.019000    0.181000    0.2974000
+44840.00   0.008067   0.182551   0.2940387    0.017000    0.181000    0.2958000
+44841.00   0.006502   0.182837   0.2927164    0.016000    0.181000    0.2941000
+44842.00   0.004967   0.183144   0.2914576    0.014000    0.182000    0.2925000
+44843.00   0.003459   0.183472   0.2901894    0.013000    0.182000    0.2908000
+44844.00   0.001971   0.183822   0.2888507    0.011000    0.182000    0.2892000
+44845.00   0.000498   0.184192   0.2874083    0.009000    0.182000    0.2875000
+44846.00  -0.000964   0.184580   0.2858615    0.008000    0.182000    0.2858000
+44847.00  -0.002421   0.184983   0.2842370    0.006000    0.183000    0.2841000
+44848.00  -0.003878   0.185399   0.2825765    0.005000    0.183000    0.2824000
+44849.00  -0.005341   0.185825   0.2809244    0.003000    0.183000    0.2807000
+44850.00  -0.006820   0.186262   0.2793189    0.001000    0.183000    0.2789000
+44851.00  -0.008321   0.186711   0.2777869    0.000000    0.184000    0.2771000
+44852.00  -0.009847   0.187177   0.2763411   -0.002000    0.184000    0.2754000
+44853.00  -0.011401   0.187664   0.2749774   -0.003000    0.185000    0.2736000
+44854.00  -0.012986   0.188175   0.2736749   -0.005000    0.185000    0.2718000
+44855.00  -0.014601   0.188708   0.2723988   -0.007000    0.186000    0.2699000
+44856.00  -0.016248   0.189263   0.2711036   -0.008000    0.186000    0.2681000
+44857.00  -0.017925   0.189838   0.2697354   -0.010000    0.187000    0.2662000
+44858.00  -0.019633   0.190433   0.2682354   -0.011000    0.187000    0.2644000
+44859.00  -0.021374   0.191049   0.2665468   -0.013000    0.188000    0.2625000
+44860.00  -0.023145   0.191686   0.2646284   -0.015000    0.189000    0.2606000
+44861.00  -0.024947   0.192346   0.2624718   -0.016000    0.190000    0.2586000
+44862.00  -0.026777   0.193028   0.2601132   -0.018000    0.191000    0.2567000
+44863.00  -0.028635   0.193735   0.2576309   -0.019000    0.192000    0.2547000
+44864.00  -0.030519   0.194466   0.2551270   -0.021000    0.193000    0.2528000
+44865.00  -0.032426   0.195223   0.2526969   -0.023000    0.194000    0.2508000
+44866.00  -0.034352   0.196006   0.2504021   -0.024000    0.195000    0.2488000
+44867.00  -0.036297   0.196814   0.2482567   -0.026000    0.197000    0.2467000
+44868.00  -0.038258   0.197645   0.2462289   -0.027000    0.198000    0.2447000
+44869.00  -0.040233   0.198500   0.2442564   -0.029000    0.199000    0.2427000
+44870.00  -0.042219   0.199377   0.2422674   -0.031000    0.200000    0.2406000
+44871.00  -0.044215   0.200276   0.2402008   -0.033000    0.201000    0.2385000
+44872.00  -0.046217   0.201196   0.2380198   -0.034000    0.203000    0.2365000
+44873.00  -0.048222   0.202137   0.2357184   -0.036000    0.204000    0.2344000
+44874.00  -0.050225   0.203100   0.2333195   -0.038000    0.205000    0.2323000
+44875.00  -0.052222   0.204084   0.2308657   -0.040000    0.206000    0.2301000
+44876.00  -0.054203   0.205092   0.2284081   -0.042000    0.207000    0.2279000
+44877.00  -0.056160   0.206123   0.2259958   -0.043000    0.209000    0.2258000
+44878.00  -0.058084   0.207180   0.2236689   -0.045000    0.210000    0.2236000
+44879.00  -0.059970   0.208266   0.2214526   -0.047000    0.211000    0.2214000
+44880.00  -0.061812   0.209382   0.2193548   -0.049000    0.212000    0.2192000
+44881.00  -0.063603   0.210532   0.2173644   -0.050000    0.213000    0.2169000
+44882.00  -0.065341   0.211718   0.2154516   -0.052000    0.215000    0.2147000
+44883.00  -0.067020   0.212941   0.2135733   -0.053000    0.216000    0.2124000
+44884.00  -0.068636   0.214202   0.2116786   -0.055000    0.217000    0.2102000
+44885.00  -0.070186   0.215504   0.2097112   -0.056000    0.218000    0.2079000
+44886.00  -0.071670   0.216846   0.2076132   -0.058000    0.219000    0.2056000
+44887.00  -0.073087   0.218228   0.2053325   -0.059000    0.221000    0.2032000
+44888.00  -0.074442   0.219649   0.2028375   -0.061000    0.222000    0.2009000
+44889.00  -0.075740   0.221105   0.2001341   -0.062000    0.223000    0.1986000
+44890.00  -0.076987   0.222593   0.1972769   -0.063000    0.224000    0.1962000
+44891.00  -0.078189   0.224110   0.1943629   -0.064000    0.226000    0.1939000
+44892.00  -0.079350   0.225653   0.1915051   -0.066000    0.227000    0.1915000
+44893.00  -0.080477   0.227218   0.1887956   -0.067000    0.229000    0.1892000
+44894.00  -0.081573   0.228801   0.1862774   -0.068000    0.230000    0.1868000
+44895.00  -0.082642   0.230398   0.1839350   -0.069000    0.231000    0.1844000
+44896.00  -0.083687   0.232006   0.1817077   -0.070000    0.233000    0.1820000
+44897.00  -0.084709   0.233618   0.1795157   -0.072000    0.234000    0.1797000
+44898.00  -0.085710   0.235233   0.1772865   -0.073000    0.236000    0.1773000
+44899.00  -0.086693   0.236845   0.1749720   -0.074000    0.237000    0.1749000
+44900.00  -0.087659   0.238452   0.1725556   -0.075000    0.239000    0.1725000
+44901.00  -0.088611   0.240050   0.1700496   -0.076000    0.240000    0.1700000
+44902.00  -0.089553   0.241637   0.1674868   -0.078000    0.242000    0.1676000
+44903.00  -0.090490   0.243214   0.1649119   -0.079000    0.243000    0.1651000
+44904.00  -0.091427   0.244778   0.1623716   -0.080000    0.245000    0.1627000
+44905.00  -0.092366   0.246330   0.1599077   -0.081000    0.247000    0.1603000
+44906.00  -0.093305   0.247871   0.1575515   -0.082000    0.248000    0.1579000
+44907.00  -0.094240   0.249406   0.1553197   -0.083000    0.250000    0.1554000
+44908.00  -0.095166   0.250935   0.1532109   -0.084000    0.251000    0.1530000
+44909.00  -0.096079   0.252462   0.1512050   -0.085000    0.253000    0.1506000
+44910.00  -0.096977   0.253991   0.1492653   -0.086000    0.255000    0.1482000
+44911.00  -0.097855   0.255525   0.1473445   -0.087000    0.257000    0.1459000
+44912.00  -0.098712   0.257066   0.1453902   -0.087000    0.258000    0.1435000
+44913.00  -0.099541   0.258616   0.1433488   -0.088000    0.260000    0.1412000
+44914.00  -0.100337   0.260174   0.1411696   -0.089000    0.262000    0.1388000
+44915.00  -0.101093   0.261743   0.1388120   -0.090000    0.264000    0.1365000
+44916.00  -0.101804   0.263326   0.1362590   -0.090000    0.266000    0.1342000
+44917.00  -0.102468   0.264926   0.1335327   -0.091000    0.268000    0.1319000
+44918.00  -0.103083   0.266547   0.1307020   -0.091000    0.270000    0.1296000
+44919.00  -0.103648   0.268194   0.1278706   -0.092000    0.272000    0.1273000
+44920.00  -0.104163   0.269872   0.1251477   -0.093000    0.274000    0.1250000
+44921.00  -0.104631   0.271582   0.1226108   -0.093000    0.276000    0.1228000
+44922.00  -0.105057   0.273331   0.1202790   -0.094000    0.278000    0.1205000
+44923.00  -0.105442   0.275117   0.1181126   -0.094000    0.280000    0.1183000
+44924.00  -0.105788   0.276940   0.1160345   -0.095000    0.282000    0.1160000
+44925.00  -0.106093   0.278798   0.1139627   -0.096000    0.284000    0.1138000
+44926.00  -0.106359   0.280687   0.1118375   -0.096000    0.286000    0.1115000
+44927.00  -0.106590   0.282607   0.1096341   -0.097000    0.288000    0.1093000
+44928.00  -0.106792   0.284556   0.1073603   -0.097000    0.290000    0.1070000
+44929.00  -0.106971   0.286533   0.1050456   -0.098000    0.292000    0.1048000
+44930.00  -0.107133   0.288535   0.1027286   -0.099000    0.294000    0.1026000
+44931.00  -0.107280   0.290560   0.1004497   -0.099000    0.296000    0.1004000
+44932.00  -0.107416   0.292608   0.0982459   -0.100000    0.299000    0.0982000
+44933.00  -0.107540   0.294677   0.0961454   -0.100000    0.301000    0.0960000
+44934.00  -0.107648   0.296764   0.0941645   -0.101000    0.303000    0.0938000
+44935.00  -0.107733   0.298869   0.0923040   -0.101000    0.305000    0.0916000
+44936.00  -0.107791   0.300991   0.0905479   -0.102000    0.307000    0.0894000
+44937.00  -0.107815   0.303127   0.0888633   -0.102000    0.310000    0.0872000
+44938.00  -0.107800   0.305278   0.0872040   -0.103000    0.312000    0.0850000
+44939.00  -0.107740   0.307440   0.0855165   -0.103000    0.314000    0.0828000
+44940.00  -0.107632   0.309614   0.0837467   -0.103000    0.314000    0.0806000
+44941.00  -0.107476   0.311800   0.0818456   -0.103000    0.314000    0.0785000
+44942.00  -0.107274   0.314001   0.0797734   -0.104000    0.314000    0.0763000
+44943.00  -0.107030   0.316218   0.0775061   -0.104000    0.314000    0.0742000
+44944.00  -0.106757   0.318450   0.0750458   -0.104000    0.314000    0.0720000
+44945.00  -0.106473   0.320697   0.0724298   -0.104000    0.318000    0.0699000
+44946.00  -0.106199   0.322958   0.0697333   -0.104000    0.323000    0.0677000
+44947.00  -0.105953   0.325231   0.0670535   -0.104000    0.327000    0.0656000
+44948.00  -0.105744   0.327514   0.0644823   -0.104000    0.332000    0.0634000
+44949.00  -0.105574   0.329807   0.0620725   -0.104000    0.336000    0.0613000
+44950.00  -0.105442   0.332106   0.0598174   -0.104000    0.338000    0.0592000
+44951.00  -0.105335   0.334407   0.0576587   -0.104000    0.340000    0.0570000
+44952.00  -0.105240   0.336708   0.0555139   -0.103000    0.342000    0.0549000
+44953.00  -0.105141   0.339004   0.0533108   -0.103000    0.344000    0.0527000
+44954.00  -0.105022   0.341291   0.0510120   -0.103000    0.346000    0.0506000
+44955.00  -0.104869   0.343568   0.0486201   -0.102000    0.348000    0.0485000
+44956.00  -0.104667   0.345832   0.0461677   -0.102000    0.350000    0.0463000
+44957.00  -0.104404   0.348081   0.0437014   -0.101000    0.352000    0.0442000
+44958.00  -0.104069   0.350313   0.0412683   -0.101000    0.354000    0.0420000
+44959.00  -0.103653   0.352526   0.0389087   -0.100000    0.356000    0.0399000
+44960.00  -0.103155   0.354720   0.0366522   -0.099000    0.358000    0.0378000
+44961.00  -0.102571   0.356893   0.0345166   -0.099000    0.360000    0.0357000
+44962.00  -0.101899   0.359045   0.0325064   -0.098000    0.362000    0.0335000
+44963.00  -0.101139   0.361177   0.0306103   -0.098000    0.364000    0.0314000
+44964.00  -0.100290   0.363287   0.0288017   -0.097000    0.366000    0.0293000
+44965.00  -0.099351   0.365377   0.0270397   -0.096000    0.368000    0.0271000
+44966.00  -0.098323   0.367444   0.0252743   -0.095000    0.370000    0.0249000
+44967.00  -0.097204   0.369491   0.0234518   -0.094000    0.372000    0.0228000
+44968.00  -0.095993   0.371516   0.0215243   -0.093000    0.374000    0.0206000
+44969.00  -0.094684   0.373520   0.0194563   -0.092000    0.376000    0.0184000
+44970.00  -0.093270   0.375504   0.0172296   -0.091000    0.378000    0.0163000
+44971.00  -0.091756   0.377467   0.0148474   -0.090000    0.380000    0.0141000
+44972.00  -0.090151   0.379406   0.0123377   -0.089000    0.382000    0.0120000
+44973.00  -0.088467   0.381320   0.0097557   -0.088000    0.384000    0.0098000
+44974.00  -0.086713   0.383207   0.0071781   -0.087000    0.386000    0.0077000
+44975.00  -0.084900   0.385064   0.0046864   -0.086000    0.388000    0.0052000
+44976.00  -0.083037   0.386892   0.0023421   -0.085000    0.390000    0.0028000
+44977.00  -0.081135   0.388691   0.0001620   -0.084000    0.391000    0.0003000
+44978.00  -0.079203   0.390460  -0.0018896   -0.083000    0.393000   -0.0021000
+44979.00  -0.077248   0.392198  -0.0038869   -0.082000    0.395000   -0.0046000
+44980.00  -0.075276   0.393905  -0.0059126   -0.081000    0.396000   -0.0071000
+44981.00  -0.073292   0.395579  -0.0080250   -0.080000    0.398000   -0.0096000
+44982.00  -0.071301   0.397219  -0.0102397   -0.078000    0.399000   -0.0121000
+44983.00  -0.069308   0.398823  -0.0125318   -0.077000    0.401000   -0.0146000
+44984.00  -0.067313   0.400393  -0.0148514   -0.076000    0.402000   -0.0171000
+44985.00  -0.065316   0.401928  -0.0171431   -0.074000    0.403000   -0.0192000
+44986.00  -0.063321   0.403428  -0.0193587   -0.073000    0.404000   -0.0213000
+44987.00  -0.061331   0.404895  -0.0214634   -0.071000    0.406000   -0.0235000
+44988.00  -0.059352   0.406328  -0.0234369   -0.070000    0.407000   -0.0256000
+44989.00  -0.057388   0.407730  -0.0252742   -0.068000    0.408000   -0.0277000
+44990.00  -0.055443   0.409100  -0.0269851   -0.066000    0.409000   -0.0289000
+44991.00  -0.053521   0.410441  -0.0285942   -0.064000    0.410000   -0.0301000
+44992.00  -0.051625   0.411754  -0.0301393   -0.062000    0.412000   -0.0313000
+44993.00  -0.049757   0.413040  -0.0316687   -0.060000    0.413000   -0.0325000
+44994.00  -0.047923   0.414302  -0.0332374   -0.058000    0.414000   -0.0337000
+44995.00  -0.046124   0.415539  -0.0348993   -0.056000    0.415000   -0.0357000
+44996.00  -0.044360   0.416754  -0.0366974   -0.054000    0.416000   -0.0378000
+44997.00  -0.042622   0.417944  -0.0386546   -0.051000    0.417000   -0.0398000
+44998.00  -0.040900   0.419110  -0.0407674   -0.049000    0.418000   -0.0419000
+44999.00  -0.039185   0.420248  -0.0430055   -0.047000    0.419000   -0.0439000
+45000.00  -0.037469   0.421359  -0.0453154   -0.045000    0.420000   -0.0462000
+45001.00  -0.035743   0.422440  -0.0476297   -0.043000    0.421000   -0.0485000
+45002.00  -0.033998   0.423491  -0.0498798   -0.040000    0.422000   -0.0507000
+45003.00  -0.032228   0.424510  -0.0520130   -0.038000    0.423000   -0.0530000
+45004.00  -0.030426   0.425498  -0.0540096   -0.036000    0.424000   -0.0553000
+45005.00  -0.028587   0.426453  -0.0558938   -0.034000    0.425000   -0.0574000
+45006.00  -0.026708   0.427377  -0.0577298   -0.032000    0.426000   -0.0596000
+45007.00  -0.024782   0.428269  -0.0596014   -0.029000    0.426000   -0.0617000
+45008.00  -0.022809   0.429130  -0.0615825   -0.027000    0.427000   -0.0639000
+45009.00  -0.020783   0.429960  -0.0637115   -0.025000    0.428000   -0.0660000
+45010.00  -0.018701   0.430758  -0.0659818   -0.023000    0.429000   -0.0686000
+45011.00  -0.016564   0.431527  -0.0683497   -0.021000    0.430000   -0.0711000
+45012.00  -0.014371   0.432269  -0.0707537   -0.018000    0.430000   -0.0737000
+45013.00  -0.012124   0.432987  -0.0731338   -0.016000    0.431000   -0.0762000
+45014.00  -0.009825   0.433684  -0.0754433   -0.014000    0.432000   -0.0788000
+45015.00  -0.007476   0.434361  -0.0776534   -0.012000    0.433000   -0.0809000
+45016.00  -0.005079   0.435019  -0.0797529   -0.010000    0.433000   -0.0830000
+45017.00  -0.002636   0.435659  -0.0817487   -0.007000    0.434000   -0.0852000
+45018.00  -0.000144   0.436282  -0.0836642   -0.005000    0.434000   -0.0873000
+45019.00   0.002399   0.436885  -0.0855371   -0.003000    0.435000   -0.0894000
+45020.00   0.004994   0.437468  -0.0874157   -0.001000    0.435000   -0.0915000
+45021.00   0.007642   0.438026  -0.0893546    0.001000    0.436000   -0.0935000
+45022.00   0.010346   0.438557  -0.0914086    0.004000    0.436000   -0.0956000
+45023.00   0.013106   0.439060  -0.0936249    0.006000    0.437000   -0.0976000
+45024.00   0.015915   0.439529  -0.0960319    0.008000    0.437000   -0.0997000
+45025.00   0.018763   0.439959  -0.0986291    0.010000    0.437000   -0.1023000
+45026.00   0.021638   0.440346  -0.1013812    0.012000    0.438000   -0.1049000
+45027.00   0.024531   0.440682  -0.1042217    0.015000    0.438000   -0.1075000
+45028.00   0.027431   0.440966  -0.1070648    0.017000    0.439000   -0.1101000
+45029.00   0.030329   0.441192  -0.1098255    0.019000    0.439000   -0.1127000
+45030.00   0.033215   0.441358  -0.1124409    0.021000    0.439000   -0.1149000
+45031.00   0.036080   0.441461  -0.1148853    0.023000    0.439000   -0.1170000
+45032.00   0.038915   0.441502  -0.1171751    0.026000    0.440000   -0.1192000
+45033.00   0.041713   0.441483  -0.1193640    0.028000    0.440000   -0.1213000
+45034.00   0.044468   0.441406  -0.1215290    0.030000    0.440000   -0.1235000
+45035.00   0.047179   0.441276  -0.1237490    0.024000    0.446000   -0.1259000
+45036.00   0.049845   0.441095  -0.1260787    0.026000    0.445000   -0.1282000
+45037.00   0.052468   0.440866  -0.1285333    0.028000    0.445000   -0.1306000
+45038.00   0.055050   0.440593  -0.1310860    0.030000    0.445000   -0.1329000
+45039.00   0.057596   0.440277  -0.1336814    0.042000    0.440000   -0.1353000
+45040.00   0.060110   0.439922  -0.1362541    0.045000    0.440000   -0.1376000
+45041.00   0.062597   0.439531  -0.1387466    0.047000    0.440000   -0.1399000
+45042.00   0.065059   0.439108  -0.1411186    0.050000    0.439000   -0.1423000
+45043.00   0.067495   0.438656  -0.1433509    0.052000    0.439000   -0.1446000
+45044.00   0.069900   0.438180  -0.1454461    0.055000    0.439000   -0.1469000
+45045.00   0.072266   0.437682  -0.1474266    0.057000    0.439000   -0.1489000
+45046.00   0.074588   0.437168  -0.1493315    0.060000    0.438000   -0.1509000
+45047.00   0.076865   0.436637  -0.1512116    0.062000    0.438000   -0.1529000
+45048.00   0.079099   0.436091  -0.1531232    0.065000    0.437000   -0.1549000
+45049.00   0.081299   0.435531  -0.1551240    0.067000    0.437000   -0.1569000
+45050.00   0.083474   0.434956  -0.1572687    0.069000    0.437000   -0.1595000
+45051.00   0.085634   0.434365  -0.1596019    0.072000    0.436000   -0.1621000
+45052.00   0.087787   0.433758  -0.1621463    0.074000    0.436000   -0.1646000
+45053.00   0.089939   0.433136  -0.1648898    0.077000    0.435000   -0.1672000
+45054.00   0.092088   0.432499  -0.1677794    0.079000    0.435000   -0.1698000
+45055.00   0.094233   0.431849  -0.1707293    0.081000    0.434000   -0.1725000
+45056.00   0.096372   0.431186  -0.1736428    0.084000    0.434000   -0.1752000
+45057.00   0.098502   0.430514  -0.1764405    0.086000    0.433000   -0.1778000
+45058.00   0.100624   0.429830  -0.1790828    0.089000    0.433000   -0.1805000
+45059.00   0.102737   0.429134  -0.1815781    0.091000    0.432000   -0.1832000
+45060.00   0.104842   0.428425  -0.1839775    0.093000    0.431000   -0.1857000
+45061.00   0.106941   0.427702  -0.1863567    0.096000    0.430000   -0.1881000
+45062.00   0.109031   0.426961  -0.1887936    0.098000    0.430000   -0.1906000
+45063.00   0.111112   0.426199  -0.1913466    0.101000    0.429000   -0.1930000
+45064.00   0.113181   0.425415  -0.1940409    0.103000    0.428000   -0.1955000
+45065.00   0.115237   0.424605  -0.1968630    0.105000    0.427000   -0.1981000
+45066.00   0.117279   0.423766  -0.1997669    0.107000    0.426000   -0.2009000
+45067.00   0.119306   0.422896  -0.2026883    0.110000    0.426000   -0.2038000
+45068.00   0.121322   0.421994  -0.2055617    0.112000    0.425000   -0.2066000
+45069.00   0.123331   0.421059  -0.2083333    0.114000    0.424000   -0.2093000
+45070.00   0.125337   0.420090  -0.2109687    0.116000    0.423000   -0.2118000
+45071.00   0.127343   0.419085  -0.2134548    0.118000    0.422000   -0.2143000
+45072.00   0.129354   0.418044  -0.2158001    0.121000    0.422000   -0.2165000
+45073.00   0.131372   0.416966  -0.2180335    0.123000    0.421000   -0.2187000
+45074.00   0.133400   0.415850  -0.2202005    0.125000    0.420000   -0.2209000
+45075.00   0.135437   0.414696  -0.2223560    0.127000    0.419000   -0.2230000
+45076.00   0.137486   0.413503  -0.2245576    0.130000    0.418000   -0.2252000
+45077.00   0.139544   0.412274  -0.2268617    0.132000    0.416000   -0.2274000
+45078.00   0.141609   0.411007  -0.2293184    0.135000    0.415000   -0.2299000
+45079.00   0.143679   0.409704  -0.2319647    0.137000    0.414000   -0.2325000
+45080.00   0.145750   0.408365  -0.2348120    0.139000    0.413000   -0.2353000
+45081.00   0.147821   0.406989  -0.2378327    0.141000    0.411000   -0.2383000
+45082.00   0.149889   0.405577  -0.2409566    0.143000    0.410000   -0.2415000
+45083.00   0.151952   0.404127  -0.2440824    0.145000    0.408000   -0.2446000
+45084.00   0.154008   0.402641  -0.2471068    0.147000    0.407000   -0.2476000
+45085.00   0.156054   0.401118  -0.2499578    0.149000    0.406000   -0.2504000
+45086.00   0.158087   0.399556  -0.2526180    0.151000    0.404000   -0.2531000
+45087.00   0.160102   0.397954  -0.2551261    0.153000    0.403000   -0.2556000
+45088.00   0.162096   0.396311  -0.2575582    0.155000    0.401000   -0.2580000
+45089.00   0.164065   0.394625  -0.2599978    0.157000    0.400000   -0.2604000
+45090.00   0.166004   0.392896  -0.2625100    0.159000    0.398000   -0.2628000
+45091.00   0.167910   0.391120  -0.2651262    0.161000    0.397000   -0.2653000
+45092.00   0.169780   0.389297  -0.2678408    0.163000    0.395000   -0.2680000
+45093.00   0.171613   0.387425  -0.2706173    0.165000    0.394000   -0.2706000
+45094.00   0.173407   0.385501  -0.2733995    0.167000    0.392000   -0.2733000
+45095.00   0.175159   0.383526  -0.2761253    0.169000    0.390000   -0.2759000
+45096.00   0.176870   0.381499  -0.2787385    0.171000    0.388000   -0.2784000
+45097.00   0.178538   0.379421  -0.2811970    0.173000    0.387000   -0.2807000
+45098.00   0.180164   0.377297  -0.2834795    0.175000    0.385000   -0.2829000
+45099.00   0.181745   0.375131  -0.2855857    0.177000    0.383000   -0.2849000
+45100.00   0.183283   0.372928  -0.2875363    0.179000    0.381000   -0.2868000
+45101.00   0.184779   0.370692  -0.2893706    0.181000    0.379000   -0.2885000
+45102.00   0.186242   0.368423  -0.2911426    0.183000    0.377000   -0.2901000
+45103.00   0.187678   0.366121  -0.2929113    0.185000    0.375000   -0.2918000
+45104.00   0.189092   0.363786  -0.2947347    0.187000    0.373000   -0.2936000
+45105.00   0.190487   0.361416  -0.2966654    0.189000    0.371000   -0.2954000
+45106.00   0.191868   0.359012  -0.2987462    0.191000    0.369000   -0.2975000
+45107.00   0.193238   0.356574  -0.3010038    0.192000    0.366000   -0.2997000
+45108.00   0.194605   0.354105  -0.3034383    0.194000    0.364000   -0.3021000
+45109.00   0.195973   0.351604  -0.3060123    0.196000    0.362000   -0.3046000
+45110.00   0.197343   0.349077  -0.3086493    0.198000    0.360000   -0.3072000
+45111.00   0.198718   0.346526  -0.3112500    0.200000    0.357000   -0.3098000
+45112.00   0.200099   0.343956  -0.3137251    0.201000    0.355000   -0.3121000
+45113.00   0.201486   0.341371  -0.3160281    0.203000    0.352000   -0.3144000
+45114.00   0.202880   0.338771  -0.3181723    0.205000    0.350000   -0.3164000
+45115.00   0.204280   0.336160  -0.3202241    0.206000    0.348000   -0.3184000
+45116.00   0.205687   0.333541  -0.3222740    0.208000    0.345000   -0.3204000
+45117.00   0.207099   0.330914  -0.3244012    0.209000    0.343000   -0.3225000
+45118.00   0.208516   0.328282  -0.3266486    0.211000    0.340000   -0.3247000
+45119.00   0.209939   0.325647  -0.3290153    0.212000    0.338000   -0.3270000
+45120.00   0.211368   0.323011  -0.3314653    0.213000    0.335000   -0.3294000
+45121.00   0.212803   0.320375  -0.3339430    0.214000    0.332000   -0.3318000
+45122.00   0.214243   0.317740  -0.3363887    0.216000    0.330000   -0.3342000
+45123.00   0.215683   0.315108  -0.3387481    0.217000    0.327000   -0.3365000
+45124.00   0.217119   0.312481  -0.3409797    0.218000    0.324000   -0.3387000
+45125.00   0.218546   0.309859  -0.3430580    0.219000    0.321000   -0.3408000
+45126.00   0.219954   0.307245  -0.3449760    0.220000    0.318000   -0.3427000
+45127.00   0.221334   0.304638  -0.3467460    0.221000    0.315000   -0.3445000
+45128.00   0.222672   0.302037  -0.3483989    0.222000    0.312000   -0.3461000
+45129.00   0.223952   0.299440  -0.3499803    0.223000    0.309000   -0.3477000
+45130.00   0.225160   0.296844  -0.3515439    0.224000    0.306000   -0.3492000
+45131.00   0.226281   0.294244  -0.3531437    0.225000    0.303000   -0.3507000
+45132.00   0.227300   0.291637  -0.3548271    0.225000    0.300000   -0.3523000
+45133.00   0.228203   0.289017  -0.3566297    0.226000    0.297000   -0.3541000
+45134.00   0.228977   0.286377  -0.3585730    0.227000    0.294000   -0.3559000
+45135.00   0.229609   0.283712  -0.3606600    0.227000    0.291000   -0.3579000
+45136.00   0.230087   0.281016  -0.3628686    0.228000    0.288000   -0.3600000
+45137.00   0.230396   0.278281  -0.3651449    0.228000    0.284000   -0.3620000
+45138.00   0.230535   0.275502  -0.3674097    0.229000    0.281000   -0.3642000
+45139.00   0.230552   0.272663  -0.3695846    0.229000    0.278000   -0.3663000
+45140.00   0.230505   0.269756  -0.3716098    0.229000    0.275000   -0.3682000
+45141.00   0.230433   0.266803  -0.3734581    0.230000    0.272000   -0.3699000
+45142.00   0.230327   0.263830  -0.3751547    0.230000    0.268000   -0.3716000
+45143.00   0.230183   0.260847  -0.3767764    0.231000    0.265000   -0.3732000
+45144.00   0.230002   0.257860  -0.3784170    0.231000    0.262000   -0.3748000
+45145.00   0.229786   0.254873  -0.3801438    0.231000    0.259000   -0.3766000
+45146.00   0.229539   0.251890  -0.3819751    0.231000    0.255000   -0.3784000
+45147.00   0.229263   0.248915  -0.3838827    0.231000    0.252000   -0.3804000
+45148.00   0.228962   0.245950  -0.3858102    0.231000    0.248000   -0.3824000
+45149.00   0.228635   0.242994  -0.3876947    0.231000    0.245000   -0.3843000
+45150.00   0.228282   0.240048  -0.3894825    0.231000    0.242000   -0.3860000
+45151.00   0.227903   0.237109   0.6088635    0.231000    0.239000    0.6123000
+45152.00   0.227500   0.234178   0.6073635    0.230000    0.235000    0.6110000
+45153.00   0.227071   0.231255   0.6060205    0.230000    0.232000    0.6097000
+45154.00   0.226617   0.228339   0.6048210    0.230000    0.229000    0.6085000
+45155.00   0.226138   0.225430   0.6037356    0.230000    0.226000    0.6074000
+45156.00   0.225636   0.222527   0.6027209    0.229000    0.223000    0.6063000
+45157.00   0.225110   0.219631   0.6017239    0.229000    0.220000    0.6053000
+45158.00   0.224558   0.216742   0.6006889    0.228000    0.217000    0.6042000
+45159.00   0.223980   0.213861   0.5995655    0.228000    0.214000    0.6031000
+45160.00   0.223370   0.210992   0.5983163    0.227000    0.211000    0.6018000
+45161.00   0.222726   0.208136   0.5969212    0.227000    0.208000    0.6003000
+45162.00   0.222040   0.205296   0.5953796    0.226000    0.206000    0.5988000
+45163.00   0.221308   0.202475   0.5937112    0.226000    0.203000    0.5971000
+45164.00   0.220525   0.199677   0.5919581    0.225000    0.200000    0.5953000
+45165.00   0.219686   0.196902   0.5901832    0.224000    0.197000    0.5934000
+45166.00   0.218788   0.194154   0.5884624    0.223000    0.194000    0.5917000
+45167.00   0.217832   0.191432   0.5868650    0.223000    0.192000    0.5900000
+45168.00   0.216819   0.188738   0.5854280    0.222000    0.189000    0.5885000
+45169.00   0.215754   0.186071   0.5841359    0.221000    0.186000    0.5872000
+45170.00   0.214638   0.183431   0.5829209    0.220000    0.183000    0.5859000
+45171.00   0.213479   0.180819   0.5816866    0.219000    0.181000    0.5846000
+45172.00   0.212281   0.178235   0.5803469    0.219000    0.178000    0.5833000
+45173.00   0.211046   0.175677   0.5788593    0.218000    0.176000    0.5817000
+45174.00   0.209779   0.173145   0.5772372    0.217000    0.173000    0.5801000
+45175.00   0.208482   0.170639   0.5755388    0.216000    0.170000    0.5783000
+45176.00   0.207157   0.168158   0.5738419    0.215000    0.168000    0.5765000
+45177.00   0.205807   0.165701   0.5722188    0.213000    0.165000    0.5749000
+45178.00   0.204434   0.163268   0.5707209    0.212000    0.163000    0.5733000
+45179.00   0.203041   0.160858   0.5693752    0.211000    0.160000    0.5719000
+45180.00   0.201628   0.158467   0.5681868    0.210000    0.157000    0.5706000
+45181.00   0.200198   0.156095   0.5671419    0.209000    0.155000    0.5695000
+45182.00   0.198750   0.153738   0.5662108    0.207000    0.152000    0.5685000
+45183.00   0.197283   0.151396   0.5653507    0.206000    0.150000    0.5675000
+45184.00   0.195796   0.149065   0.5645097    0.205000    0.147000    0.5666000
+45185.00   0.194287   0.146746   0.5636315    0.203000    0.145000    0.5656000
+45186.00   0.192753   0.144436   0.5626608    0.202000    0.142000    0.5646000
+45187.00   0.191188   0.142138   0.5615525    0.200000    0.140000    0.5634000
+45188.00   0.189587   0.139850   0.5602790    0.199000    0.137000    0.5620000
+45189.00   0.187942   0.137574   0.5588353    0.197000    0.135000    0.5605000
+45190.00   0.186248   0.135311   0.5572413    0.195000    0.133000    0.5589000
+45191.00   0.184499   0.133061   0.5555391    0.193000    0.130000    0.5572000
+45192.00   0.182691   0.130826   0.5537867    0.191000    0.128000    0.5556000
+45193.00   0.180820   0.128606   0.5520488    0.189000    0.125000    0.5538000
+45194.00   0.178885   0.126404   0.5503848    0.187000    0.123000    0.5522000
+45195.00   0.176885   0.124221   0.5488306    0.185000    0.121000    0.5506000
+45196.00   0.174821   0.122061   0.5473828    0.182000    0.119000    0.5492000
+45197.00   0.172698   0.119925   0.5459912    0.180000    0.116000    0.5479000
+45198.00   0.170519   0.117816   0.5445700    0.177000    0.114000    0.5464000
+45199.00   0.168290   0.115737   0.5430252    0.175000    0.112000    0.5448000
+45200.00   0.166012   0.113689   0.5412908    0.172000    0.110000    0.5430000
+45201.00   0.163690   0.111677   0.5393529    0.169000    0.108000    0.5409000
+45202.00   0.161328   0.109701   0.5372528    0.167000    0.106000    0.5386000
+45203.00   0.158931   0.107765   0.5350698    0.164000    0.104000    0.5363000
+45204.00   0.156504   0.105868   0.5328919    0.161000    0.102000    0.5340000
+45205.00   0.154050   0.104013   0.5307914    0.158000    0.100000    0.5318000
+45206.00   0.151574   0.102200   0.5288123    0.155000    0.098000    0.5297000
+45207.00   0.149075   0.100430   0.5269696    0.153000    0.097000    0.5277000
+45208.00   0.146556   0.098701   0.5252541    0.150000    0.095000    0.5259000
+45209.00   0.144019   0.097016   0.5236373    0.147000    0.093000    0.5243000
+45210.00   0.141467   0.095372   0.5220765    0.144000    0.091000    0.5228000
+45211.00   0.138905   0.093769   0.5205198    0.141000    0.090000    0.5213000
+45212.00   0.136334   0.092209   0.5189112    0.139000    0.088000    0.5198000
+45213.00   0.133756   0.090691   0.5171961    0.136000    0.087000    0.5182000
+45214.00   0.131172   0.089216   0.5153275    0.133000    0.085000    0.5165000
+45215.00   0.128584   0.087785   0.5132734    0.130000    0.083000    0.5145000
+45216.00   0.125988   0.086396   0.5110245    0.127000    0.082000    0.5124000
+45217.00   0.123382   0.085050   0.5086007    0.124000    0.080000    0.5101000
+45218.00   0.120758   0.083746   0.5060521    0.121000    0.079000    0.5077000
+45219.00   0.118109   0.082484   0.5034506    0.118000    0.077000    0.5052000
+45220.00   0.115426   0.081262   0.5008748    0.115000    0.076000    0.5027000
+45221.00   0.112698   0.080080   0.4983934    0.112000    0.074000    0.5003000
+45222.00   0.109909   0.078941   0.4960501    0.108000    0.073000    0.4980000
+45223.00   0.107038   0.077844   0.4938502    0.105000    0.071000    0.4959000
+45224.00   0.104060   0.076792   0.4917594    0.102000    0.070000    0.4939000
+45225.00   0.100941   0.075789   0.4897097    0.099000    0.069000    0.4919000
+45226.00   0.097653   0.074836   0.4876187    0.095000    0.068000    0.4899000
+45227.00   0.094171   0.073937   0.4854146    0.092000    0.067000    0.4877000
+45228.00   0.090519   0.073093   0.4830529    0.088000    0.066000    0.4854000
+45229.00   0.086735   0.072309   0.4805389    0.085000    0.065000    0.4828000
+45230.00   0.082848   0.071586   0.4779277    0.082000    0.064000    0.4802000
+45231.00   0.078886   0.070926   0.4753023    0.078000    0.064000    0.4775000
+45232.00   0.074873   0.070329   0.4727448    0.075000    0.063000    0.4750000
+45233.00   0.070826   0.069797   0.4703178    0.071000    0.063000    0.4725000
+45234.00   0.066765   0.069330   0.4680526    0.068000    0.062000    0.4702000
+45235.00   0.062704   0.068926   0.4659500    0.064000    0.062000    0.4680000
+45236.00   0.058656   0.068587   0.4639867    0.061000    0.062000    0.4660000
+45237.00   0.054630   0.068310   0.4621210    0.057000    0.061000    0.4640000
+45238.00   0.050631   0.068095   0.4603001    0.054000    0.061000    0.4622000
+45239.00   0.046665   0.067940   0.4584668    0.050000    0.061000    0.4602000
+45240.00   0.042735   0.067845   0.4565644    0.046000    0.061000    0.4583000
+45241.00   0.038844   0.067806   0.4545431    0.043000    0.061000    0.4562000
+45242.00   0.034995   0.067825   0.4523646    0.039000    0.060000    0.4539000
+45243.00   0.031186   0.067899   0.4500084    0.036000    0.060000    0.4514000
+45244.00   0.027414   0.068028   0.4474796    0.032000    0.060000    0.4488000
+45245.00   0.023680   0.068212   0.4448154    0.028000    0.060000    0.4461000
+45246.00   0.019981   0.068449   0.4420846    0.025000    0.060000    0.4433000
+45247.00   0.016317   0.068737   0.4393739    0.021000    0.061000    0.4406000
+45248.00   0.012688   0.069075   0.4367670    0.018000    0.061000    0.4379000
+45249.00   0.009093   0.069459   0.4343200    0.014000    0.061000    0.4354000
+45250.00   0.005535   0.069887   0.4320443    0.010000    0.062000    0.4331000
+45251.00   0.002014   0.070356   0.4299041    0.007000    0.062000    0.4310000
+45252.00  -0.001469   0.070862   0.4278270    0.003000    0.063000    0.4288000
+45253.00  -0.004914   0.071405   0.4257247    0.000000    0.063000    0.4267000
+45254.00  -0.008321   0.071980   0.4235175   -0.004000    0.064000    0.4245000
+45255.00  -0.011694   0.072585   0.4211563   -0.008000    0.065000    0.4221000
+45256.00  -0.015035   0.073219   0.4186360   -0.011000    0.066000    0.4196000
+45257.00  -0.018348   0.073880   0.4159972   -0.015000    0.067000    0.4169000
+45258.00  -0.021639   0.074564   0.4133142   -0.018000    0.068000    0.4142000
+45259.00  -0.024914   0.075271   0.4106733   -0.022000    0.069000    0.4115000
+45260.00  -0.028185   0.076001   0.4081512   -0.025000    0.070000    0.4089000
+45261.00  -0.031465   0.076753   0.4057997   -0.029000    0.072000    0.4065000
+45262.00  -0.034762   0.077527   0.4036387   -0.032000    0.073000    0.4042000
+45263.00  -0.038074   0.078327   0.4016561   -0.036000    0.075000    0.4022000
+45264.00  -0.041396   0.079157   0.3998154   -0.039000    0.076000    0.4002000
+45265.00  -0.044721   0.080019   0.3980639   -0.042000    0.078000    0.3984000
+45266.00  -0.048047   0.080921   0.3963395   -0.046000    0.079000    0.3965000
+45267.00  -0.051372   0.081867   0.3945793   -0.049000    0.081000    0.3947000
+45268.00  -0.054691   0.082863   0.3927267   -0.053000    0.082000    0.3927000
+45269.00  -0.058002   0.083912   0.3907363   -0.056000    0.084000    0.3906000
+45270.00  -0.061300   0.085016   0.3885770   -0.059000    0.086000    0.3884000
+45271.00  -0.064579   0.086176   0.3862366   -0.063000    0.088000    0.3860000
+45272.00  -0.067838   0.087394   0.3837292   -0.066000    0.090000    0.3834000
+45273.00  -0.071075   0.088669   0.3811019   -0.070000    0.092000    0.3807000
+45274.00  -0.074288   0.090002   0.3784328   -0.073000    0.094000    0.3780000
+45275.00  -0.077476   0.091392   0.3758140   -0.076000    0.096000    0.3754000
+45276.00  -0.080641   0.092837   0.3733233   -0.080000    0.097000    0.3729000
+45277.00  -0.083781   0.094337   0.3709964   -0.083000    0.099000    0.3706000
+45278.00  -0.086897   0.095891   0.3688131   -0.087000    0.100000    0.3685000
+45279.00  -0.089988   0.097496   0.3667045   -0.090000    0.102000    0.3663000
+45280.00  -0.093053   0.099153   0.3645773   -0.093000    0.104000    0.3642000
+45281.00  -0.096090   0.100860   0.3623449   -0.097000    0.105000    0.3619000
+45282.00  -0.099097   0.102619   0.3599507   -0.100000    0.107000    0.3594000
+45283.00  -0.102073   0.104429   0.3573813   -0.104000    0.108000    0.3568000
+45284.00  -0.105017   0.106290   0.3546666   -0.107000    0.110000    0.3541000
+45285.00  -0.107930   0.108203   0.3518680   -0.110000    0.112000    0.3513000
+45286.00  -0.110814   0.110166   0.3490618   -0.114000    0.114000    0.3485000
+45287.00  -0.113671   0.112177   0.3463220   -0.117000    0.116000    0.3457000
+45288.00  -0.116507   0.114233   0.3437057   -0.121000    0.118000    0.3431000
+45289.00  -0.119327   0.116329   0.3412446   -0.124000    0.120000    0.3407000
+45290.00  -0.122137   0.118463   0.3389427   -0.127000    0.122000    0.3384000
+45291.00  -0.124937   0.120632   0.3367799   -0.130000    0.124000    0.3362000
+45292.00  -0.127729   0.122834   0.3347163   -0.134000    0.126000    0.3342000
+45293.00  -0.130510   0.125067   0.3326984   -0.137000    0.128000    0.3322000
+45294.00  -0.133273   0.127330   0.3306678   -0.140000    0.130000    0.3302000
+45295.00  -0.136016   0.129623   0.3285691   -0.143000    0.132000    0.3281000
+45296.00  -0.138730   0.131948   0.3263564   -0.146000    0.135000    0.3259000
+45297.00  -0.141410   0.134311   0.3239977   -0.150000    0.137000    0.3236000
+45298.00  -0.144048   0.136713   0.3214765   -0.153000    0.140000    0.3211000
+45299.00  -0.146643   0.139159   0.3187951   -0.156000    0.142000    0.3184000
+45300.00  -0.149194   0.141652   0.3159804   -0.159000    0.144000    0.3156000
+45301.00  -0.151702   0.144196   0.3130895   -0.162000    0.147000    0.3128000
+45302.00  -0.154167   0.146794   0.3102055   -0.165000    0.149000    0.3099000
+45303.00  -0.156589   0.149450   0.3074182   -0.168000    0.152000    0.3071000
+45304.00  -0.158966   0.152166   0.3047930   -0.171000    0.154000    0.3045000
+45305.00  -0.161296   0.154943   0.3023427   -0.173000    0.157000    0.3021000
+45306.00  -0.163575   0.157781   0.3000190   -0.175000    0.159000    0.2997000
+45307.00  -0.165800   0.160681   0.2977304   -0.177000    0.162000    0.2974000
+45308.00  -0.167968   0.163642   0.2953770   -0.179000    0.164000    0.2950000
+45309.00  -0.170080   0.166663   0.2928865   -0.181000    0.167000    0.2925000
+45310.00  -0.172133   0.169742   0.2902369   -0.183000    0.170000    0.2899000
+45311.00  -0.174126   0.172880   0.2874545   -0.185000    0.173000    0.2872000
+45312.00  -0.176059   0.176075   0.2845995   -0.186000    0.175000    0.2844000
+45313.00  -0.177931   0.179324   0.2817447   -0.188000    0.178000    0.2816000
+45314.00  -0.179743   0.182626   0.2789577   -0.190000    0.181000    0.2789000
+45315.00  -0.181493   0.185976   0.2762903   -0.191000    0.184000    0.2764000
+45316.00  -0.183181   0.189370   0.2737720   -0.193000    0.187000    0.2740000
+45317.00  -0.184801   0.192806   0.2714093   -0.194000    0.190000    0.2719000
+45318.00  -0.186349   0.196277   0.2691863   -0.196000    0.193000    0.2698000
+45319.00  -0.187819   0.199780   0.2670684   -0.197000    0.196000    0.2678000
+45320.00  -0.189206   0.203308   0.2650073   -0.198000    0.199000    0.2658000
+45321.00  -0.190511   0.206851   0.2629497   -0.199000    0.202000    0.2638000
+45322.00  -0.191733   0.210394   0.2608427   -0.201000    0.205000    0.2617000
+45323.00  -0.192882   0.213927   0.2586404   -0.202000    0.208000    0.2596000
+45324.00  -0.193966   0.217450   0.2563087   -0.203000    0.211000    0.2572000
+45325.00  -0.194995   0.220960   0.2538298   -0.204000    0.214000    0.2547000
+45326.00  -0.195974   0.224458   0.2512028   -0.205000    0.218000    0.2521000
+45327.00  -0.196909   0.227945   0.2484449   -0.206000    0.221000    0.2493000
+45328.00  -0.197805   0.231421   0.2455952   -0.207000    0.225000    0.2464000
+45329.00  -0.198664   0.234887   0.2427162   -0.208000    0.228000    0.2434000
+45330.00  -0.199490   0.238344   0.2398866   -0.209000    0.231000    0.2404000
+45331.00  -0.200286   0.241793   0.2371797   -0.209000    0.235000    0.2376000
+45332.00  -0.201053   0.245236   0.2346342   -0.210000    0.238000    0.2347000
+45333.00  -0.201797   0.248673   0.2322319   -0.210000    0.242000    0.2321000
+45334.00  -0.202517   0.252106   0.2298981   -0.211000    0.245000    0.2295000
+45335.00  -0.203212   0.255534   0.2275282   -0.211000    0.249000    0.2269000
+45336.00  -0.203881   0.258959   0.2250294   -0.212000    0.252000    0.2242000
+45337.00  -0.204519   0.262381   0.2223567   -0.212000    0.256000    0.2222000
+45338.00  -0.205125   0.265800   0.2195252   -0.213000    0.259000    0.2194000
+45339.00  -0.205695   0.269217   0.2165984   -0.213000    0.263000    0.2150000
+45340.00  -0.206227   0.272632   0.2136601   -0.213000    0.267000    0.2120000
+45341.00  -0.206714   0.276045   0.2107876   -0.213000    0.271000    0.2092000
+45342.00  -0.207150   0.279453   0.2080355   -0.212000    0.275000    0.2068000
+45343.00  -0.207528   0.282860   0.2054302   -0.212000    0.279000    0.2044000
+45344.00  -0.207840   0.286269   0.2029718   -0.212000    0.283000    0.2021000
+45345.00  -0.208081   0.289686   0.2006395   -0.212000    0.287000    0.2000000
+45346.00  -0.208244   0.293116   0.1983961   -0.212000    0.291000    0.1980000
+45347.00  -0.208322   0.296563   0.1961929   -0.211000    0.295000    0.1962000
+45348.00  -0.208311   0.300030   0.1939732   -0.211000    0.299000    0.1943000
+45349.00  -0.208208   0.303518   0.1916788   -0.211000    0.303000    0.1923000
+45350.00  -0.208010   0.307029   0.1892581   -0.210000    0.307000    0.1901000
+45351.00  -0.207718   0.310562   0.1866722   -0.210000    0.311000    0.1879000
+45352.00  -0.207328   0.314118   0.1839011   -0.209000    0.315000    0.1855000
+45353.00  -0.206842   0.317697   0.1809453   -0.209000    0.319000    0.1829000
+45354.00  -0.206262   0.321296   0.1778254   -0.208000    0.323000    0.1800000
+45355.00  -0.205593   0.324915   0.1745799   -0.207000    0.327000    0.1771000
+45356.00  -0.204842   0.328552   0.1712638   -0.207000    0.331000    0.1740000
+45357.00  -0.204017   0.332205   0.1679448   -0.206000    0.335000    0.1710000
+45358.00  -0.203126   0.335874   0.1646928   -0.206000    0.339000    0.1679000
+45359.00  -0.202180   0.339560   0.1615602   -0.205000    0.343000    0.1649000
+45360.00  -0.201190   0.343261   0.1585570   -0.204000    0.347000    0.1619000
+45361.00  -0.200166   0.346978   0.1556373   -0.204000    0.351000    0.1589000
+45362.00  -0.199118   0.350711   0.1527105   -0.203000    0.354000    0.1558000
+45363.00  -0.198059   0.354459   0.1496744   -0.203000    0.358000    0.1526000
+45364.00  -0.196995   0.358220   0.1464584   -0.202000    0.362000    0.1491000
+45365.00  -0.195926   0.361986   0.1430533   -0.201000    0.366000    0.1455000
+45366.00  -0.194851   0.365751   0.1395149   -0.200000    0.369000    0.1416000
+45367.00  -0.193771   0.369508   0.1359409   -0.199000    0.373000    0.1374000
+45368.00  -0.192684   0.373250   0.1324362   -0.198000    0.376000    0.1335000
+45369.00  -0.191588   0.376969   0.1290835   -0.197000    0.380000    0.1298000
+45370.00  -0.190484   0.380659   0.1259296   -0.196000    0.383000    0.1264000
+45371.00  -0.189367   0.384312   0.1229869   -0.195000    0.386000    0.1233000
+45372.00  -0.188234   0.387921   0.1202404   -0.193000    0.390000    0.1205000
+45373.00  -0.187082   0.391479   0.1176558   -0.192000    0.393000    0.1178000
+45374.00  -0.185908   0.394981   0.1151858   -0.191000    0.396000    0.1152000
+45375.00  -0.184713   0.398433   0.1127737   -0.190000    0.399000    0.1127000
+45376.00  -0.183498   0.401844   0.1103595   -0.188000    0.402000    0.1103000
+45377.00  -0.182269   0.405222   0.1078857   -0.187000    0.406000    0.1079000
+45378.00  -0.181029   0.408577   0.1053057   -0.185000    0.409000    0.1053000
+45379.00  -0.179780   0.411914   0.1025905   -0.184000    0.412000    0.1025000
+45380.00  -0.178518   0.415234   0.0997325   -0.182000    0.415000    0.0996000
+45381.00  -0.177241   0.418537   0.0967476   -0.181000    0.418000    0.0965000
+45382.00  -0.175944   0.421823   0.0936712   -0.179000    0.421000    0.0934000
+45383.00  -0.174625   0.425092   0.0905532   -0.178000    0.424000    0.0902000
+45384.00  -0.173282   0.428344   0.0874499   -0.176000    0.427000    0.0870000
+45385.00  -0.171913   0.431577   0.0844157   -0.174000    0.430000    0.0840000
+45386.00  -0.170518   0.434794   0.0814906   -0.172000    0.433000    0.0810000
+45387.00  -0.169096   0.437994   0.0786836   -0.171000    0.436000    0.0782000
+45388.00  -0.167646   0.441179   0.0759597   -0.169000    0.439000    0.0755000
+45389.00  -0.166167   0.444350   0.0732408   -0.167000    0.442000    0.0728000
+45390.00  -0.164660   0.447507   0.0704274   -0.165000    0.445000    0.0700000
+45391.00  -0.163125   0.450652   0.0674296   -0.163000    0.448000    0.0670000
+45392.00  -0.161563   0.453782   0.0642052   -0.162000    0.451000    0.0637000
+45393.00  -0.159973   0.456896   0.0607805   -0.160000    0.454000    0.0603000
+45394.00  -0.158356   0.459991   0.0572429   -0.158000    0.457000    0.0567000
+45395.00  -0.156711   0.463065   0.0537102   -0.156000    0.460000    0.0531000
+45396.00  -0.155027   0.466114   0.0502915   -0.154000    0.463000    0.0496000
+45397.00  -0.153292   0.469131   0.0470614   -0.152000    0.466000    0.0462000
+45398.00  -0.151495   0.472111   0.0440498   -0.150000    0.469000    0.0431000
+45399.00  -0.149620   0.475047   0.0412480   -0.148000    0.472000    0.0403000
+45400.00  -0.147661   0.477937   0.0386193   -0.146000    0.475000    0.0376000
+45401.00  -0.145613   0.480781   0.0361107   -0.144000    0.478000    0.0351000
+45402.00  -0.143471   0.483580   0.0336612   -0.141000    0.481000    0.0326000
+45403.00  -0.141231   0.486336   0.0312083   -0.139000    0.484000    0.0302000
+45404.00  -0.138889   0.489050   0.0286930   -0.137000    0.487000    0.0277000
+45405.00  -0.136442   0.491725   0.0260663   -0.134000    0.490000    0.0251000
+45406.00  -0.133885   0.494364   0.0232944   -0.132000    0.493000    0.0224000
+45407.00  -0.131210   0.496969   0.0203649   -0.129000    0.496000    0.0197000
+45408.00  -0.128410   0.499543   0.0172904   -0.127000    0.499000    0.0167000
+45409.00  -0.125478   0.502086   0.0141085   -0.124000    0.502000    0.0136000
+45410.00  -0.122418   0.504602   0.0108778   -0.121000    0.505000    0.0104000
+45411.00  -0.119235   0.507091   0.0076674   -0.118000    0.507000    0.0073000
+45412.00  -0.115937   0.509555   0.0045425   -0.115000    0.510000    0.0043000
+45413.00  -0.112530   0.511993   0.0015490   -0.112000    0.512000    0.0014000
+45414.00  -0.109022   0.514404  -0.0012990   -0.109000    0.515000   -0.0014000
+45415.00  -0.105420   0.516789  -0.0040274   -0.106000    0.517000   -0.0041000
+45416.00  -0.101731   0.519147  -0.0067025   -0.102000    0.519000   -0.0068000
+45417.00  -0.097962   0.521477  -0.0094192   -0.099000    0.522000   -0.0095000
+45418.00  -0.094119   0.523776  -0.0122760   -0.095000    0.524000   -0.0124000
+45419.00  -0.090209   0.526043  -0.0153433   -0.092000    0.526000   -0.0154000
+45420.00  -0.086237   0.528276  -0.0186359   -0.088000    0.528000   -0.0187000
+45421.00  -0.082209   0.530471  -0.0221034   -0.084000    0.530000   -0.0222000
+45422.00  -0.078130   0.532621  -0.0256461   -0.081000    0.532000   -0.0257000
+45423.00  -0.074009   0.534721  -0.0291468   -0.077000    0.534000   -0.0292000
+45424.00  -0.069850   0.536763  -0.0325059   -0.073000    0.536000   -0.0326000
+45425.00  -0.065659   0.538743  -0.0356630   -0.069000    0.538000   -0.0358000
+45426.00  -0.061440   0.540657  -0.0386029   -0.065000    0.539000   -0.0387000
+45427.00  -0.057195   0.542501  -0.0413476   -0.060000    0.541000   -0.0415000
+45428.00  -0.052928   0.544268  -0.0439429   -0.056000    0.542000   -0.0441000
+45429.00  -0.048642   0.545956  -0.0464476   -0.052000    0.544000   -0.0466000
+45430.00  -0.044341   0.547559  -0.0489244   -0.048000    0.545000   -0.0491000
+45431.00  -0.040027   0.549075  -0.0514330   -0.044000    0.547000   -0.0516000
+45432.00  -0.035702   0.550499  -0.0540247   -0.040000    0.548000   -0.0542000
+45433.00  -0.031369   0.551829  -0.0567364   -0.036000    0.550000   -0.0568000
+45434.00  -0.027031   0.553065  -0.0595887   -0.032000    0.551000   -0.0596000
+45435.00  -0.022693   0.554205  -0.0625809   -0.028000    0.552000   -0.0625000
+45436.00  -0.018358   0.555249  -0.0656872   -0.024000    0.553000   -0.0656000
+45437.00  -0.014034   0.556197  -0.0688558   -0.020000    0.555000   -0.0686000
+45438.00  -0.009727   0.557050  -0.0720153   -0.016000    0.556000   -0.0716000
+45439.00  -0.005446   0.557808  -0.0750885   -0.012000    0.557000   -0.0746000
+45440.00  -0.001195   0.558473  -0.0780126   -0.008000    0.558000   -0.0774000
+45441.00   0.003020   0.559045  -0.0807588   -0.004000    0.559000   -0.0800000
+45442.00   0.007198   0.559527  -0.0833430    0.001000    0.559000   -0.0825000
+45443.00   0.011338   0.559922  -0.0858234    0.005000    0.560000   -0.0849000
+45444.00   0.015440   0.560231  -0.0882865    0.009000    0.561000   -0.0873000
+45445.00   0.019503   0.560459  -0.0908251    0.013000    0.561000   -0.0897000
+45446.00   0.023529   0.560610  -0.0935121    0.017000    0.562000   -0.0924000
+45447.00   0.027520   0.560689  -0.0963788    0.022000    0.562000   -0.0952000
+45448.00   0.031477   0.560698  -0.0994022    0.026000    0.563000   -0.0982000
+45449.00   0.035403   0.560642  -0.1025100    0.030000    0.563000   -0.1013000
+45450.00   0.039300   0.560525  -0.1056022    0.034000    0.563000   -0.1044000
+45451.00   0.043172   0.560348  -0.1085773    0.038000    0.563000   -0.1074000
+45452.00   0.047021   0.560116  -0.1113600    0.043000    0.564000   -0.1102000
+45453.00   0.050854   0.559830  -0.1139153    0.047000    0.564000   -0.1128000
+45454.00   0.054675   0.559493  -0.1162496    0.051000    0.564000   -0.1153000
+45455.00   0.058491   0.559106  -0.1184020    0.055000    0.564000   -0.1175000
+45456.00   0.062309   0.558672  -0.1204319    0.059000    0.564000   -0.1197000
+45457.00   0.066136   0.558194  -0.1224077    0.064000    0.564000   -0.1219000
+45458.00   0.069979   0.557674  -0.1243973    0.068000    0.564000   -0.1240000
+45459.00   0.073844   0.557115  -0.1264606    0.072000    0.564000   -0.1262000
+45460.00   0.077738   0.556519  -0.1286443    0.076000    0.563000   -0.1285000
+45461.00   0.081669   0.555888  -0.1309783    0.080000    0.563000   -0.1310000
+45462.00   0.085642   0.555220  -0.1334714    0.085000    0.562000   -0.1336000
+45463.00   0.089658   0.554509  -0.1361100    0.089000    0.562000   -0.1363000
+45464.00   0.093715   0.553751  -0.1388562    0.093000    0.561000   -0.1392000
+45465.00   0.097812   0.552942  -0.1416479    0.097000    0.560000   -0.1421000
+45466.00   0.101946   0.552078  -0.1444055    0.101000    0.559000   -0.1450000
+45467.00   0.106112   0.551155  -0.1470507    0.105000    0.559000   -0.1478000
+45468.00   0.110302   0.550170  -0.1495316    0.109000    0.558000   -0.1504000
+45469.00   0.114509   0.549120  -0.1518442    0.113000    0.557000   -0.1528000
+45470.00   0.118726   0.547998  -0.1540358    0.117000    0.556000   -0.1551000
+45471.00   0.122945   0.546802  -0.1561922    0.121000    0.555000   -0.1573000
+45472.00   0.127159   0.545527  -0.1584097    0.125000    0.554000   -0.1597000
+45473.00   0.131360   0.544168  -0.1607653    0.129000    0.553000   -0.1621000
+45474.00   0.135539   0.542719  -0.1632953    0.133000    0.552000   -0.1647000
+45475.00   0.139689   0.541175  -0.1659860    0.137000    0.551000   -0.1675000
+45476.00   0.143801   0.539534  -0.1687803    0.141000    0.549000   -0.1704000
+45477.00   0.147867   0.537793  -0.1715926    0.144000    0.548000   -0.1733000
+45478.00   0.151878   0.535950  -0.1743313    0.148000    0.546000   -0.1760000
+45479.00   0.155826   0.534004  -0.1769185    0.152000    0.545000   -0.1787000
+45480.00   0.159706   0.531958  -0.1793060    0.156000    0.543000   -0.1811000
+45481.00   0.163513   0.529815  -0.1814826    0.159000    0.541000   -0.1833000
+45482.00   0.167243   0.527577  -0.1834712    0.163000    0.540000   -0.1852000
+45483.00   0.170895   0.525249  -0.1853193    0.166000    0.538000   -0.1871000
+45484.00   0.174469   0.522836  -0.1870888    0.170000    0.536000   -0.1889000
+45485.00   0.177966   0.520342  -0.1888461    0.174000    0.534000   -0.1906000
+45486.00   0.181388   0.517771  -0.1906526    0.177000    0.532000   -0.1924000
+45487.00   0.184737   0.515127  -0.1925570    0.181000    0.529000   -0.1942000
+45488.00   0.188016   0.512417  -0.1945898    0.184000    0.527000   -0.1962000
+45489.00   0.191228   0.509648  -0.1967628    0.188000    0.525000   -0.1984000
+45490.00   0.194379   0.506829  -0.1990697    0.191000    0.522000   -0.2007000
+45491.00   0.197476   0.503969  -0.2014855    0.195000    0.520000   -0.2032000
+45492.00   0.200525   0.501077  -0.2039651    0.198000    0.517000   -0.2058000
+45493.00   0.203534   0.498163  -0.2064431    0.202000    0.515000   -0.2083000
+45494.00   0.206511   0.495238  -0.2088431    0.205000    0.512000   -0.2107000
+45495.00   0.209463   0.492312  -0.2110986    0.208000    0.509000   -0.2129000
+45496.00   0.212398   0.489397  -0.2131805    0.212000    0.506000   -0.2150000
+45497.00   0.215316   0.486502  -0.2151148    0.215000    0.503000   -0.2169000
+45498.00   0.218216   0.483639  -0.2169799    0.219000    0.500000   -0.2188000
+45499.00   0.221098   0.480815  -0.2188808    0.222000    0.497000   -0.2206000
+45500.00   0.223959   0.478037  -0.2209105    0.225000    0.494000   -0.2226000
+45501.00   0.226807   0.475297  -0.2231172    0.228000    0.490000   -0.2247000
+45502.00   0.229649   0.472583  -0.2254904    0.232000    0.487000   -0.2270000
+45503.00   0.232469   0.469865  -0.2279672    0.235000    0.483000   -0.2294000
+45504.00   0.235245   0.467113  -0.2304555    0.238000    0.480000   -0.2318000
+45505.00   0.237965   0.464296  -0.2328591    0.241000    0.476000   -0.2340000
+45506.00   0.240656   0.461383  -0.2350984    0.244000    0.473000   -0.2361000
+45507.00   0.243352   0.458346  -0.2371218    0.246000    0.469000   -0.2380000
+45508.00   0.246079   0.455162  -0.2389102    0.249000    0.466000   -0.2397000
+45509.00   0.248790   0.451851  -0.2404772    0.252000    0.462000   -0.2411000
+45510.00   0.251403   0.448455  -0.2418619    0.255000    0.458000   -0.2424000
+45511.00   0.253904   0.444994  -0.2431196    0.257000    0.455000   -0.2435000
+45512.00   0.256323   0.441473  -0.2443137    0.260000    0.451000   -0.2446000
+45513.00   0.258689   0.437896  -0.2455067    0.262000    0.448000   -0.2458000
+45514.00   0.261034   0.434269  -0.2467514    0.265000    0.444000   -0.2470000
+45515.00   0.263368   0.430601  -0.2480856    0.267000    0.440000   -0.2483000
+45516.00   0.265685   0.426907   0.7504719    0.269000    0.436000    0.7503000
+45517.00   0.267977   0.423195   0.7489233    0.272000    0.433000    0.7487000
+45518.00   0.270239   0.419450   0.7472900    0.274000    0.429000    0.7470000
+45519.00   0.272465   0.415657   0.7456089    0.276000    0.425000    0.7453000
+45520.00   0.274650   0.411797   0.7439316    0.278000    0.421000    0.7436000
+45521.00   0.276789   0.407855   0.7423215    0.280000    0.417000    0.7419000
+45522.00   0.278877   0.403817   0.7408431    0.283000    0.413000    0.7403000
+45523.00   0.280924   0.399698   0.7395374    0.285000    0.409000    0.7389000
+45524.00   0.282943   0.395528   0.7383994    0.287000    0.405000    0.7376000
+45525.00   0.284950   0.391334   0.7373669    0.289000    0.401000    0.7365000
+45526.00   0.286959   0.387145   0.7363329    0.291000    0.397000    0.7353000
+45527.00   0.288985   0.382991   0.7351809    0.294000    0.392000    0.7340000
+45528.00   0.291042   0.378900   0.7338288    0.296000    0.388000    0.7325000
+45529.00   0.293139   0.374884   0.7322570    0.298000    0.384000    0.7309000
+45530.00   0.295275   0.370936   0.7305113    0.300000    0.380000    0.7290000
+45531.00   0.297449   0.367044   0.7286812    0.302000    0.376000    0.7271000
+45532.00   0.299642   0.363202   0.7268689    0.305000    0.371000    0.7253000
+45533.00   0.301814   0.359408   0.7251607    0.307000    0.367000    0.7236000
+45534.00   0.303922   0.355660   0.7236072    0.309000    0.363000    0.7221000
+45535.00   0.305929   0.351954   0.7222224    0.311000    0.359000    0.7208000
+45536.00   0.307817   0.348280   0.7209944    0.313000    0.354000    0.7197000
+45537.00   0.309571   0.344626   0.7198906    0.315000    0.350000    0.7188000
+45538.00   0.311184   0.340978   0.7188644    0.317000    0.345000    0.7179000
+45539.00   0.312662   0.337319   0.7178588    0.319000    0.341000    0.7171000
+45540.00   0.314018   0.333629   0.7168157    0.320000    0.337000    0.7163000
+45541.00   0.315265   0.329890   0.7156832    0.322000    0.332000    0.7153000
+45542.00   0.316426   0.326094   0.7144231    0.323000    0.328000    0.7143000
+45543.00   0.317524   0.322234   0.7130171    0.325000    0.323000    0.7131000
+45544.00   0.318573   0.318298   0.7114668    0.326000    0.319000    0.7117000
+45545.00   0.319575   0.314267   0.7097910    0.327000    0.315000    0.7101000
+45546.00   0.320531   0.310123   0.7080234    0.328000    0.311000    0.7085000
+45547.00   0.321434   0.305872   0.7062103    0.328000    0.306000    0.7067000
+45548.00   0.322273   0.301533   0.7044070    0.329000    0.302000    0.7050000
+45549.00   0.323036   0.297129   0.7026705    0.330000    0.298000    0.7033000
+45550.00   0.323703   0.292676   0.7010479    0.331000    0.294000    0.7017000
+45551.00   0.324245   0.288185   0.6995577    0.331000    0.290000    0.7003000
+45552.00   0.324630   0.283662   0.6981705    0.332000    0.285000    0.6989000
+45553.00   0.324867   0.279123   0.6968051    0.332000    0.281000    0.6975000
+45554.00   0.325008   0.274583   0.6953489    0.333000    0.277000    0.6960000
+45555.00   0.325109   0.270061   0.6936998    0.333000    0.273000    0.6943000
+45556.00   0.325220   0.265574   0.6918090    0.333000    0.269000    0.6923000
+45557.00   0.325345   0.261129   0.6897026    0.333000    0.264000    0.6901000
+45558.00   0.325442   0.256722   0.6874726    0.333000    0.260000    0.6878000
+45559.00   0.325463   0.252350   0.6852440    0.333000    0.256000    0.6854000
+45560.00   0.325347   0.248012   0.6831328    0.333000    0.252000    0.6832000
+45561.00   0.325027   0.243710   0.6812146    0.332000    0.248000    0.6812000
+45562.00   0.324439   0.239444   0.6795146    0.332000    0.243000    0.6794000
+45563.00   0.323570   0.235203   0.6780156    0.331000    0.239000    0.6778000
+45564.00   0.322552   0.230949   0.6766742    0.331000    0.235000    0.6764000
+45565.00   0.321508   0.226648   0.6754331    0.330000    0.231000    0.6751000
+45566.00   0.320461   0.222306   0.6742298    0.330000    0.227000    0.6739000
+45567.00   0.319418   0.217934   0.6730031    0.329000    0.222000    0.6726000
+45568.00   0.318373   0.213545   0.6716981    0.329000    0.218000    0.6713000
+45569.00   0.317312   0.209152   0.6702728    0.328000    0.214000    0.6698000
+45570.00   0.316217   0.204768   0.6687035    0.327000    0.210000    0.6682000
+45571.00   0.315057   0.200403   0.6669878    0.326000    0.206000    0.6665000
+45572.00   0.313769   0.196072   0.6651441    0.324000    0.201000    0.6646000
+45573.00   0.312292   0.191785   0.6632099    0.323000    0.197000    0.6627000
+45574.00   0.310611   0.187543   0.6612365    0.322000    0.193000    0.6608000
+45575.00   0.308761   0.183334   0.6592822    0.320000    0.189000    0.6590000
+45576.00   0.306780   0.179145   0.6574024    0.319000    0.185000    0.6572000
+45577.00   0.304707   0.174963   0.6556410    0.317000    0.180000    0.6556000
+45578.00   0.302568   0.170795   0.6540182    0.316000    0.176000    0.6541000
+45579.00   0.300382   0.166667   0.6525168    0.314000    0.172000    0.6528000
+45580.00   0.298158   0.162606   0.6510751    0.312000    0.168000    0.6514000
+45581.00   0.295874   0.158623   0.6495919    0.310000    0.164000    0.6501000
+45582.00   0.293495   0.154721   0.6479549    0.308000    0.159000    0.6486000
+45583.00   0.290991   0.150908   0.6460815    0.306000    0.155000    0.6468000
+45584.00   0.288340   0.147183   0.6439545    0.304000    0.151000    0.6448000
+45585.00   0.285620   0.143517   0.6416305    0.302000    0.147000    0.6425000
+45586.00   0.282932   0.139868   0.6392241    0.300000    0.143000    0.6402000
+45587.00   0.280329   0.136199   0.6368703    0.297000    0.139000    0.6380000
+45588.00   0.277835   0.132485   0.6346791    0.295000    0.135000    0.6359000
+45589.00   0.275415   0.128738   0.6327116    0.293000    0.131000    0.6340000
+45590.00   0.273024   0.124983   0.6309726    0.290000    0.127000    0.6323000
+45591.00   0.270614   0.121243   0.6294242    0.288000    0.123000    0.6308000
+45592.00   0.268140   0.117541   0.6280058    0.285000    0.120000    0.6295000
+45593.00   0.265569   0.113896   0.6266502    0.283000    0.116000    0.6282000
+45594.00   0.262872   0.110324   0.6252925    0.280000    0.112000    0.6268000
+45595.00   0.260033   0.106829   0.6238741    0.277000    0.109000    0.6254000
+45596.00   0.257047   0.103408   0.6223466    0.274000    0.105000    0.6238000
+45597.00   0.253908   0.100056   0.6206790    0.271000    0.102000    0.6221000
+45598.00   0.250619   0.096769   0.6188601    0.268000    0.098000    0.6202000
+45599.00   0.247218   0.093546   0.6169004    0.265000    0.095000    0.6181000
+45600.00   0.243752   0.090388   0.6148318    0.262000    0.092000    0.6159000
+45601.00   0.240255   0.087290   0.6127044    0.259000    0.089000    0.6136000
+45602.00   0.236747   0.084238   0.6105772    0.255000    0.086000    0.6112000
+45603.00   0.233246   0.081217   0.6085069    0.252000    0.083000    0.6090000
+45604.00   0.229770   0.078212   0.6065357    0.249000    0.080000    0.6069000
+45605.00   0.226324   0.075212   0.6046808    0.245000    0.077000    0.6049000
+45606.00   0.222887   0.072205   0.6029261    0.242000    0.074000    0.6031000
+45607.00   0.219443   0.069196   0.6012183    0.238000    0.072000    0.6012000
+45608.00   0.215995   0.066215   0.5994726    0.235000    0.069000    0.5995000
+45609.00   0.212552   0.063299   0.5975868    0.231000    0.066000    0.5976000
+45610.00   0.209116   0.060476   0.5954696    0.227000    0.064000    0.5955000
+45611.00   0.205677   0.057756   0.5930760    0.223000    0.061000    0.5931000
+45612.00   0.202226   0.055143   0.5904304    0.219000    0.059000    0.5905000
+45613.00   0.198751   0.052641   0.5876271    0.215000    0.056000    0.5878000
+45614.00   0.195241   0.050236   0.5848052    0.211000    0.054000    0.5851000
+45615.00   0.191681   0.047915   0.5821044    0.207000    0.052000    0.5825000
+45616.00   0.188069   0.045677   0.5796249    0.202000    0.050000    0.5800000
+45617.00   0.184406   0.043530   0.5774064    0.198000    0.047000    0.5779000
+45618.00   0.180694   0.041484   0.5754327    0.193000    0.045000    0.5760000
+45619.00   0.176934   0.039547   0.5736494    0.189000    0.043000    0.5742000
+45620.00   0.173127   0.037715   0.5719840    0.185000    0.041000    0.5726000
+45621.00   0.169272   0.035973   0.5703624    0.180000    0.039000    0.5710000
+45622.00   0.165367   0.034308   0.5687185    0.176000    0.038000    0.5693000
+45623.00   0.161397   0.032717   0.5669967    0.171000    0.036000    0.5675000
+45624.00   0.157343   0.031201   0.5651578    0.167000    0.034000    0.5656000
+45625.00   0.153187   0.029760   0.5631825    0.163000    0.033000    0.5635000
+45626.00   0.148934   0.028382   0.5610699    0.158000    0.031000    0.5612000
+45627.00   0.144606   0.027048   0.5588385    0.154000    0.030000    0.5588000
+45628.00   0.140224   0.025746   0.5565266    0.149000    0.028000    0.5563000
+45629.00   0.135800   0.024495   0.5541889    0.145000    0.027000    0.5537000
+45630.00   0.131340   0.023320   0.5518854    0.141000    0.026000    0.5513000
+45631.00   0.126852   0.022244   0.5496675    0.136000    0.025000    0.5489000
+45632.00   0.122332   0.021273   0.5475627    0.132000    0.024000    0.5467000
+45633.00   0.117777   0.020411   0.5455610    0.127000    0.023000    0.5447000
+45634.00   0.113183   0.019661   0.5436110    0.123000    0.022000    0.5427000
+45635.00   0.108558   0.019010   0.5416323    0.118000    0.021000    0.5407000
+45636.00   0.103917   0.018434   0.5395291    0.114000    0.020000    0.5386000
+45637.00   0.099285   0.017915   0.5372094    0.109000    0.020000    0.5364000
+45638.00   0.094682   0.017444   0.5346166    0.105000    0.019000    0.5339000
+45639.00   0.090127   0.017010   0.5317491    0.100000    0.018000    0.5311000
+45640.00   0.085635   0.016605   0.5286668    0.095000    0.018000    0.5282000
+45641.00   0.081180   0.016226   0.5254822    0.091000    0.018000    0.5252000
+45642.00   0.076707   0.015875   0.5223304    0.086000    0.017000    0.5222000
+45643.00   0.072188   0.015555   0.5193312    0.082000    0.017000    0.5194000
+45644.00   0.067650   0.015274   0.5165611    0.077000    0.017000    0.5167000
+45645.00   0.063133   0.015041   0.5140408    0.073000    0.017000    0.5143000
+45646.00   0.058673   0.014863   0.5117429    0.068000    0.017000    0.5121000
+45647.00   0.054298   0.014750   0.5096069    0.064000    0.018000    0.5099000
+45648.00   0.050016   0.014711   0.5075559    0.059000    0.018000    0.5079000
+45649.00   0.045825   0.014760   0.5055162    0.055000    0.018000    0.5058000
+45650.00   0.041690   0.014919   0.5034252    0.051000    0.018000    0.5037000
+45651.00   0.037570   0.015212   0.5012379    0.046000    0.018000    0.5015000
+45652.00   0.033436   0.015651   0.4989301    0.042000    0.019000    0.4991000
+45653.00   0.029287   0.016216   0.4964974    0.037000    0.019000    0.4966000
+45654.00   0.025129   0.016880   0.4939555    0.033000    0.019000    0.4940000
+45655.00   0.020959   0.017618   0.4913389    0.029000    0.020000    0.4913000
+45656.00   0.016746   0.018418   0.4887009    0.025000    0.020000    0.4887000
+45657.00   0.012470   0.019266   0.4861057    0.020000    0.021000    0.4861000
+45658.00   0.008132   0.020152   0.4836202    0.016000    0.021000    0.4836000
+45659.00   0.003743   0.021065   0.4812962    0.012000    0.022000    0.4812000
+45660.00  -0.000682   0.021994   0.4791497    0.008000    0.023000    0.4790000
+45661.00  -0.005128   0.022932   0.4771491    0.004000    0.024000    0.4770000
+45662.00  -0.009563   0.023887   0.4752188   -0.001000    0.024000    0.4749000
+45663.00  -0.013953   0.024877   0.4732586   -0.005000    0.025000    0.4729000
+45664.00  -0.018277   0.025911   0.4711735   -0.009000    0.026000    0.4707000
+45665.00  -0.022529   0.026991   0.4689010   -0.013000    0.027000    0.4684000
+45666.00  -0.026704   0.028118   0.4664286   -0.017000    0.028000    0.4659000
+45667.00  -0.030799   0.029291   0.4637977   -0.021000    0.030000    0.4633000
+45668.00  -0.034830   0.030504   0.4610947   -0.025000    0.031000    0.4606000
+45669.00  -0.038822   0.031742   0.4584273   -0.029000    0.032000    0.4579000
+45670.00  -0.042803   0.032994   0.4558981   -0.033000    0.033000    0.4554000
+45671.00  -0.046774   0.034259   0.4535817   -0.036000    0.035000    0.4531000
+45672.00  -0.050719   0.035547   0.4515093   -0.040000    0.036000    0.4511000
+45673.00  -0.054619   0.036867   0.4496656   -0.043000    0.038000    0.4493000
+45674.00  -0.058443   0.038228   0.4479977   -0.047000    0.039000    0.4476000
+45675.00  -0.062153   0.039638   0.4464330   -0.050000    0.041000    0.4461000
+45676.00  -0.065717   0.041105   0.4448954   -0.054000    0.042000    0.4446000
+45677.00  -0.069128   0.042651   0.4433152   -0.057000    0.044000    0.4431000
+45678.00  -0.072386   0.044297   0.4416385   -0.061000    0.045000    0.4414000
+45679.00  -0.075499   0.046056   0.4398322   -0.064000    0.047000    0.4395000
+45680.00  -0.078500   0.047907   0.4378858   -0.067000    0.049000    0.4375000
+45681.00  -0.081426   0.049824   0.4358100   -0.070000    0.051000    0.4354000
+45682.00  -0.084310   0.051784   0.4336338   -0.074000    0.052000    0.4331000
+45683.00  -0.087163   0.053773   0.4313994   -0.077000    0.054000    0.4307000
+45684.00  -0.089984   0.055779   0.4291600   -0.080000    0.056000    0.4284000
+45685.00  -0.092784   0.057796   0.4269767   -0.083000    0.058000    0.4261000
+45686.00  -0.095588   0.059831   0.4249091   -0.086000    0.060000    0.4240000
+45687.00  -0.098428   0.061893   0.4229931   -0.089000    0.062000    0.4219000
+45688.00  -0.101331   0.063991   0.4212216   -0.092000    0.064000    0.4201000
+45689.00  -0.104285   0.066120   0.4195351   -0.095000    0.066000    0.4183000
+45690.00  -0.107234   0.068258   0.4178346   -0.098000    0.068000    0.4165000
+45691.00  -0.110135   0.070392   0.4160138   -0.101000    0.070000    0.4147000
+45692.00  -0.112977   0.072525   0.4139933   -0.103000    0.072000    0.4125000
+45693.00  -0.115751   0.074659   0.4117490   -0.106000    0.074000    0.4102000
+45694.00  -0.118457   0.076816   0.4093198   -0.109000    0.076000    0.4078000
+45695.00  -0.121102   0.079021   0.4067917   -0.112000    0.078000    0.4053000
+45696.00  -0.123689   0.081302   0.4042707   -0.114000    0.080000    0.4029000
+45697.00  -0.126226   0.083687   0.4018558   -0.117000    0.083000    0.4005000
+45698.00  -0.128720   0.086194   0.3996181   -0.119000    0.085000    0.3984000
+45699.00  -0.131198   0.088822   0.3975912   -0.122000    0.087000    0.3966000
+45700.00  -0.133693   0.091556   0.3957700   -0.125000    0.089000    0.3950000
+45701.00  -0.136248   0.094364   0.3941189   -0.127000    0.092000    0.3937000
+45702.00  -0.138908   0.097214   0.3925820   -0.130000    0.091000    0.3928000
+45703.00  -0.141713   0.100076   0.3910960   -0.132000    0.094000    0.3908000
+45704.00  -0.144634   0.102933   0.3896011   -0.135000    0.099000    0.3900000
+45705.00  -0.147567   0.105787   0.3880487   -0.137000    0.102000    0.3886000
+45706.00  -0.150445   0.108641   0.3864062   -0.140000    0.104000    0.3871000
+45707.00  -0.153237   0.111497   0.3846611   -0.142000    0.107000    0.3854000
+45708.00  -0.155921   0.114358   0.3828226   -0.145000    0.110000    0.3836000
+45709.00  -0.158475   0.117229   0.3809185   -0.147000    0.113000    0.3816000
+45710.00  -0.160879   0.120116   0.3789884   -0.150000    0.116000    0.3797000
+45711.00  -0.163135   0.123034   0.3770820   -0.152000    0.119000    0.3777000
+45712.00  -0.165270   0.125996   0.3752552   -0.154000    0.122000    0.3757000
+45713.00  -0.167340   0.128998   0.3735584   -0.157000    0.125000    0.3739000
+45714.00  -0.169412   0.132027   0.3720280   -0.159000    0.128000    0.3722000
+45715.00  -0.171529   0.135077   0.3706685   -0.161000    0.131000    0.3707000
+45716.00  -0.173696   0.138154   0.3694355   -0.164000    0.134000    0.3693000
+45717.00  -0.175913   0.141261   0.3682349   -0.166000    0.138000    0.3679000
+45718.00  -0.178181   0.144398   0.3669465   -0.168000    0.141000    0.3664000
+45719.00  -0.180499   0.147546   0.3654672   -0.171000    0.144000    0.3648000
+45720.00  -0.182868   0.150678   0.3637489   -0.173000    0.147000    0.3629000
+45721.00  -0.185285   0.153776   0.3618180   -0.175000    0.150000    0.3609000
+45722.00  -0.187747   0.156841   0.3597665   -0.177000    0.153000    0.3589000
+45723.00  -0.190250   0.159874   0.3577188   -0.180000    0.157000    0.3567000
+45724.00  -0.192791   0.162876   0.3557903   -0.182000    0.160000    0.3548000
+45725.00  -0.195341   0.165856   0.3540603   -0.184000    0.163000    0.3530000
+45726.00  -0.197857   0.168829   0.3525635   -0.186000    0.166000    0.3515000
+45727.00  -0.200310   0.171811   0.3512901   -0.189000    0.169000    0.3501000
+45728.00  -0.202689   0.174810   0.3501969   -0.191000    0.173000    0.3490000
+45729.00  -0.204988   0.177835   0.3492225   -0.193000    0.176000    0.3481000
+45730.00  -0.207201   0.180895   0.3482974   -0.195000    0.179000    0.3472000
+45731.00  -0.209302   0.184010   0.3473493   -0.197000    0.183000    0.3464000
+45732.00  -0.211263   0.187209   0.3463147   -0.200000    0.186000    0.3457000
+45733.00  -0.213058   0.190510   0.3451465   -0.202000    0.189000    0.3446000
+45734.00  -0.214671   0.193897   0.3438190   -0.204000    0.193000    0.3434000
+45735.00  -0.216102   0.197345   0.3423294   -0.206000    0.196000    0.3420000
+45736.00  -0.217398   0.200842   0.3407013   -0.208000    0.200000    0.3404000
+45737.00  -0.218614   0.204396   0.3389802   -0.210000    0.203000    0.3387000
+45738.00  -0.219801   0.208015   0.3372199   -0.212000    0.207000    0.3370000
+45739.00  -0.221010   0.211703   0.3354758   -0.214000    0.210000    0.3354000
+45740.00  -0.222283   0.215418   0.3338026   -0.216000    0.214000    0.3337000
+45741.00  -0.223623   0.219088   0.3322386   -0.217000    0.217000    0.3322000
+45742.00  -0.225009   0.222662   0.3307985   -0.219000    0.221000    0.3307000
+45743.00  -0.226395   0.226137   0.3294628   -0.221000    0.225000    0.3294000
+45744.00  -0.227735   0.229512   0.3281652   -0.223000    0.228000    0.3281000
+45745.00  -0.228996   0.232798   0.3267982   -0.224000    0.232000    0.3268000
+45746.00  -0.230184   0.236043   0.3252405   -0.226000    0.236000    0.3252000
+45747.00  -0.231313   0.239301   0.3234042   -0.227000    0.239000    0.3234000
+45748.00  -0.232399   0.242625   0.3212741   -0.229000    0.243000    0.3213000
+45749.00  -0.233470   0.246041   0.3189226   -0.230000    0.247000    0.3190000
+45750.00  -0.234563   0.249561   0.3164862   -0.231000    0.250000    0.3167000
+45751.00  -0.235703   0.253172   0.3141195   -0.233000    0.254000    0.3144000
+45752.00  -0.236884   0.256861   0.3119521   -0.234000    0.258000    0.3123000
+45753.00  -0.238091   0.260612   0.3100573   -0.235000    0.261000    0.3105000
+45754.00  -0.239304   0.264417   0.3084469   -0.236000    0.265000    0.3089000
+45755.00  -0.240498   0.268293   0.3070853   -0.237000    0.269000    0.3075000
+45756.00  -0.241649   0.272247   0.3058959   -0.238000    0.273000    0.3063000
+45757.00  -0.242735   0.276271   0.3047850   -0.238000    0.277000    0.3051000
+45758.00  -0.243735   0.280348   0.3036583   -0.239000    0.280000    0.3039000
+45759.00  -0.244627   0.284464   0.3024328   -0.240000    0.284000    0.3026000
+45760.00  -0.245397   0.288604   0.3010452   -0.241000    0.288000    0.3011000
+45761.00  -0.246066   0.292756   0.2994704   -0.241000    0.292000    0.2996000
+45762.00  -0.246663   0.296911   0.2977127   -0.241000    0.296000    0.2978000
+45763.00  -0.247186   0.301065   0.2957984   -0.242000    0.300000    0.2959000
+45764.00  -0.247564   0.305215   0.2937702   -0.242000    0.304000    0.2939000
+45765.00  -0.247740   0.309367   0.2916832   -0.242000    0.308000    0.2919000
+45766.00  -0.247738   0.313525   0.2895946   -0.242000    0.312000    0.2899000
+45767.00  -0.247545   0.317689   0.2875612   -0.242000    0.316000    0.2880000
+45768.00  -0.247117   0.321851   0.2856316   -0.241000    0.320000    0.2861000
+45769.00  -0.246412   0.326007   0.2838347   -0.241000    0.324000    0.2844000
+45770.00  -0.245453   0.330153   0.2821681   -0.240000    0.328000    0.2827000
+45771.00  -0.244301   0.334287   0.2805828   -0.240000    0.332000    0.2811000
+45772.00  -0.243017   0.338411   0.2789864   -0.239000    0.336000    0.2795000
+45773.00  -0.241646   0.342540   0.2772601   -0.239000    0.340000    0.2777000
+45774.00  -0.240224   0.346696   0.2752929   -0.238000    0.344000    0.2757000
+45775.00  -0.238804   0.350899   0.2730242   -0.237000    0.347000    0.2733000
+45776.00  -0.237426   0.355140   0.2704742   -0.236000    0.351000    0.2706000
+45777.00  -0.236099   0.359395   0.2677449   -0.235000    0.355000    0.2677000
+45778.00  -0.234833   0.363640   0.2649881   -0.234000    0.359000    0.2649000
+45779.00  -0.233638   0.367852   0.2623533   -0.233000    0.363000    0.2621000
+45780.00  -0.232516   0.372008   0.2599421   -0.231000    0.367000    0.2596000
+45781.00  -0.231434   0.376092   0.2577934   -0.230000    0.371000    0.2574000
+45782.00  -0.230332   0.380098   0.2558878   -0.228000    0.375000    0.2554000
+45783.00  -0.229142   0.384027   0.2541670   -0.227000    0.379000    0.2536000
+45784.00  -0.227828   0.387876   0.2525587   -0.225000    0.383000    0.2520000
+45785.00  -0.226424   0.391632   0.2509899   -0.223000    0.387000    0.2503000
+45786.00  -0.224943   0.395303   0.2493888   -0.221000    0.390000    0.2487000
+45787.00  -0.223387   0.398901   0.2476965   -0.219000    0.394000    0.2469000
+45788.00  -0.221753   0.402445   0.2458792   -0.218000    0.398000    0.2450000
+45789.00  -0.220027   0.405961   0.2439299   -0.216000    0.402000    0.2430000
+45790.00  -0.218203   0.409467   0.2418646   -0.213000    0.406000    0.2409000
+45791.00  -0.216277   0.412970   0.2397213   -0.211000    0.410000    0.2386000
+45792.00  -0.214248   0.416473   0.2375544   -0.209000    0.414000    0.2363000
+45793.00  -0.212116   0.419980   0.2354255   -0.206000    0.417000    0.2341000
+45794.00  -0.209885   0.423499   0.2333936   -0.204000    0.421000    0.2320000
+45795.00  -0.207558   0.427047   0.2315025   -0.202000    0.425000    0.2301000
+45796.00  -0.205116   0.430657   0.2297717   -0.199000    0.428000    0.2283000
+45797.00  -0.202564   0.434329   0.2281875   -0.197000    0.432000    0.2268000
+45798.00  -0.199927   0.438042   0.2267002   -0.195000    0.436000    0.2252000
+45799.00  -0.197234   0.441776   0.2252257   -0.192000    0.439000    0.2238000
+45800.00  -0.194512   0.445521   0.2236558   -0.190000    0.443000    0.2222000
+45801.00  -0.191747   0.449274   0.2218794   -0.187000    0.446000    0.2204000
+45802.00  -0.188910   0.453024   0.2198122   -0.185000    0.450000    0.2184000
+45803.00  -0.186018   0.456733   0.2174328   -0.182000    0.453000    0.2161000
+45804.00  -0.183103   0.460348   0.2148017   -0.179000    0.457000    0.2136000
+45805.00  -0.180195   0.463824   0.2120503   -0.177000    0.460000    0.2109000
+45806.00  -0.177307   0.467156   0.2093423   -0.174000    0.463000    0.2084000
+45807.00  -0.174447   0.470354   0.2068199   -0.171000    0.466000    0.2061000
+45808.00  -0.171620   0.473431   0.2045618   -0.168000    0.469000    0.2039000
+45809.00  -0.168823   0.476398   0.2025697   -0.165000    0.473000    0.2020000
+45810.00  -0.166061   0.479278   0.2007854   -0.162000    0.475000    0.2003000
+45811.00  -0.163372   0.482112   0.1991292   -0.159000    0.479000    0.1987000
+45812.00  -0.160723   0.484922   0.1975172   -0.156000    0.481000    0.1970000
+45813.00  -0.158061   0.487723   0.1958781   -0.153000    0.484000    0.1953000
+45814.00  -0.155331   0.490533   0.1941616   -0.150000    0.488000    0.1936000
+45815.00  -0.152483   0.493366   0.1923383   -0.146000    0.490000    0.1917000
+45816.00  -0.149499   0.496226   0.1903968   -0.143000    0.493000    0.1898000
+45817.00  -0.146378   0.499108   0.1883442   -0.140000    0.496000    0.1876000
+45818.00  -0.143112   0.502004   0.1862065   -0.136000    0.499000    0.1854000
+45819.00  -0.139694   0.504907   0.1840258   -0.133000    0.501000    0.1832000
+45820.00  -0.136117   0.507802   0.1818567   -0.129000    0.504000    0.1810000
+45821.00  -0.132404   0.510670   0.1797638   -0.126000    0.506000    0.1788000
+45822.00  -0.128584   0.513487   0.1778052   -0.122000    0.509000    0.1767000
+45823.00  -0.124685   0.516235   0.1760190   -0.119000    0.511000    0.1749000
+45824.00  -0.120721   0.518909   0.1744128   -0.115000    0.514000    0.1732000
+45825.00  -0.116696   0.521516   0.1729556   -0.112000    0.516000    0.1717000
+45826.00  -0.112618   0.524062   0.1715775   -0.108000    0.518000    0.1703000
+45827.00  -0.108541   0.526540   0.1701798   -0.104000    0.521000    0.1689000
+45828.00  -0.104534   0.528942   0.1686564   -0.101000    0.523000    0.1673000
+45829.00  -0.100665   0.531257   0.1669190   -0.097000    0.525000    0.1655000
+45830.00  -0.096980   0.533468   0.1649239   -0.094000    0.527000    0.1635000
+45831.00  -0.093484   0.535562   0.1626958   -0.090000    0.529000    0.1612000
+45832.00  -0.090126   0.537536   0.1603279   -0.086000    0.531000    0.1587000
+45833.00  -0.086832   0.539392   0.1579581   -0.083000    0.533000    0.1563000
+45834.00  -0.083528   0.541130   0.1557314   -0.079000    0.535000    0.1541000
+45835.00  -0.080144   0.542753   0.1537564   -0.075000    0.537000    0.1521000
+45836.00  -0.076659   0.544280   0.1520742   -0.071000    0.538000    0.1504000
+45837.00  -0.073068   0.545737   0.1506565   -0.067000    0.540000    0.1490000
+45838.00  -0.069372   0.547148   0.1494269   -0.064000    0.542000    0.1477000
+45839.00  -0.065593   0.548539   0.1482916   -0.060000    0.544000    0.1466000
+45840.00  -0.061753   0.549930   0.1471636   -0.056000    0.545000    0.1454000
+45841.00  -0.057842   0.551303   0.1459754   -0.052000    0.546000    0.1442000
+45842.00  -0.053862   0.552630   0.1446855   -0.048000    0.548000    0.1429000
+45843.00  -0.049830   0.553883   0.1432785   -0.044000    0.549000    0.1416000
+45844.00  -0.045764   0.555039   0.1417625   -0.040000    0.550000    0.1401000
+45845.00  -0.041679   0.556087   0.1401662   -0.036000    0.552000    0.1385000
+45846.00  -0.037550   0.557031   0.1385293   -0.032000    0.553000    0.1368000
+45847.00  -0.033346   0.557886   0.1368996   -0.028000    0.554000    0.1352000
+45848.00  -0.029063   0.558661   0.1353285   -0.024000    0.555000    0.1337000
+45849.00  -0.024702   0.559368   0.1338643   -0.020000    0.556000    0.1322000
+45850.00  -0.020261   0.560019   0.1325442   -0.016000    0.557000    0.1310000
+45851.00  -0.015736   0.560616   0.1313877   -0.012000    0.557000    0.1299000
+45852.00  -0.011164   0.561137   0.1303775   -0.007000    0.558000    0.1289000
+45853.00  -0.006584   0.561557   0.1294549   -0.003000    0.559000    0.1280000
+45854.00  -0.002004   0.561867   0.1285322    0.001000    0.559000    0.1272000
+45855.00   0.002574   0.562062   0.1275139    0.005000    0.560000    0.1262000
+45856.00   0.007150   0.562137   0.1263199    0.009000    0.560000    0.1250000
+45857.00   0.011713   0.562095   0.1249107    0.014000    0.560000    0.1236000
+45858.00   0.016250   0.561940   0.1233020    0.018000    0.560000    0.1220000
+45859.00   0.020744   0.561678   0.1215661    0.022000    0.560000    0.1203000
+45860.00   0.025167   0.561321   0.1198165    0.026000    0.560000    0.1185000
+45861.00   0.029479   0.560886   0.1181750    0.030000    0.560000    0.1169000
+45862.00   0.033651   0.560392   0.1167397    0.035000    0.560000    0.1154000
+45863.00   0.037698   0.559870   0.1155606    0.039000    0.560000    0.1142000
+45864.00   0.041648   0.559352   0.1146282    0.043000    0.560000    0.1132000
+45865.00   0.045528   0.558866   0.1138831    0.047000    0.559000    0.1125000
+45866.00   0.049374   0.558416   0.1132413    0.052000    0.559000    0.1118000
+45867.00   0.053228   0.557996   0.1126155    0.056000    0.558000    0.1112000
+45868.00   0.057118   0.557597   0.1119315    0.060000    0.558000    0.1105000
+45869.00   0.061049   0.557210   0.1111373    0.064000    0.557000    0.1097000
+45870.00   0.065011   0.556822   0.1102061    0.069000    0.556000    0.1088000
+45871.00   0.068961   0.556410   0.1091371    0.073000    0.555000    0.1077000
+45872.00   0.072888   0.555944   0.1079499    0.077000    0.555000    0.1066000
+45873.00   0.076789   0.555397   0.1066807    0.081000    0.554000    0.1053000
+45874.00   0.080672   0.554742   0.1053753    0.086000    0.553000    0.1041000
+45875.00   0.084588   0.553970   0.1040846    0.090000    0.552000    0.1029000
+45876.00   0.088574   0.553073   0.1028675    0.094000    0.551000    0.1017000
+45877.00   0.092657   0.552046   0.1017801    0.098000    0.549000    0.1006000
+45878.00   0.096871   0.550896   0.1008610    0.102000    0.548000    0.0998000
+45879.00   0.101258   0.549641   0.1001166    0.107000    0.547000    0.0991000
+45880.00   0.105838   0.548297   0.0995091    0.111000    0.546000    0.0986000
+45881.00   0.110541   0.546878   0.0989598    0.115000    0.544000    0.0981000
+45882.00   0.115262   0.545401   0.0983676    0.119000    0.543000    0.0975000
+45883.00   0.119923   0.543875   0.0976423    0.123000    0.541000    0.0967000
+45884.00   0.124503   0.542301   0.0967379    0.128000    0.540000    0.0957000
+45885.00   0.128981   0.540676   0.0956692    0.132000    0.538000    0.0946000
+45886.00   0.133340   0.538990   0.0944962    0.136000    0.536000    0.0932000
+45887.00   0.137574   0.537225   0.0933116    0.140000    0.535000    0.0919000
+45888.00   0.141680   0.535361   0.0922166    0.145000    0.533000    0.0907000
+45889.00   0.145664   0.533389   0.0912929    0.149000    0.531000    0.0897000
+45890.00   0.149545   0.531308   0.0905856    0.153000    0.529000    0.0889000
+45891.00   0.153348   0.529131   0.0900997    0.157000    0.527000    0.0884000
+45892.00   0.157110   0.526879   0.0897970    0.161000    0.525000    0.0881000
+45893.00   0.160862   0.524579   0.0896094    0.165000    0.523000    0.0880000
+45894.00   0.164632   0.522263   0.0894579    0.169000    0.521000    0.0878000
+45895.00   0.168441   0.519958   0.0892686    0.173000    0.518000    0.0877000
+45896.00   0.172283   0.517656   0.0889796    0.177000    0.516000    0.0874000
+45897.00   0.176152   0.515337   0.0885517    0.181000    0.514000    0.0870000
+45898.00   0.180041   0.512981   0.0879727    0.185000    0.511000    0.0865000
+45899.00   0.183948   0.510566   0.0872532    0.189000    0.509000    0.0858000
+45900.00   0.187878   0.508072   0.0864211    0.193000    0.507000    0.0850000
+45901.00   0.191806   0.505497   0.0855229    0.197000    0.504000    0.0842000
+45902.00   0.195733   0.502847   0.0846132    0.201000    0.502000    0.0834000
+45903.00   0.199670   0.500128   0.0837447    0.204000    0.499000    0.0826000
+45904.00   0.203624   0.497351   0.0829616    0.208000    0.496000    0.0819000
+45905.00   0.207573   0.494543   0.0822899    0.212000    0.494000    0.0813000
+45906.00   0.211481   0.491731   0.0817349    0.215000    0.491000    0.0808000
+45907.00   0.215311   0.488936   0.0812672    0.219000    0.488000    0.0804000
+45908.00   0.219051   0.486154   0.0808141    0.223000    0.485000    0.0801000
+45909.00   0.222688   0.483378   0.0802680    0.226000    0.483000    0.0796000
+45910.00   0.226221   0.480603   0.0795154    0.230000    0.479000    0.0789000
+45911.00   0.229681   0.477813   0.0784771    0.233000    0.476000    0.0780000
+45912.00   0.233082   0.474988   0.0771460    0.236000    0.473000    0.0768000
+45913.00   0.236413   0.472105   0.0755994    0.240000    0.470000    0.0753000
+45914.00   0.239692   0.469146   0.0739710    0.243000    0.467000    0.0737000
+45915.00   0.242944   0.466103   0.0724111    0.246000    0.464000    0.0722000
+45916.00   0.246165   0.462984   0.0710446    0.249000    0.461000    0.0708000
+45917.00   0.249335   0.459789   0.0699438    0.252000    0.458000    0.0695000
+45918.00   0.252427   0.456515   0.0691185    0.255000    0.454000    0.0686000
+45919.00   0.255424   0.453164   0.0685157    0.258000    0.451000    0.0679000
+45920.00   0.258353   0.449761   0.0680443    0.261000    0.448000    0.0674000
+45921.00   0.261229   0.446324   0.0676057    0.264000    0.444000    0.0669000
+45922.00   0.264070   0.442875   0.0671077    0.266000    0.441000    0.0666000
+45923.00   0.266901   0.439437   0.0664755    0.269000    0.438000    0.0660000
+45924.00   0.269751   0.436036   0.0656580    0.272000    0.434000    0.0652000
+45925.00   0.272629   0.432674   0.0646337    0.274000    0.431000    0.0642000
+45926.00   0.275486   0.429332   0.0634174    0.276000    0.427000    0.0631000
+45927.00   0.278259   0.425990   0.0620488    0.279000    0.424000    0.0619000
+45928.00   0.280889   0.422626   0.0605835    0.281000    0.420000    0.0605000
+45929.00   0.283325   0.419206   0.0590876    0.283000    0.417000    0.0591000
+45930.00   0.285528   0.415699   0.0576264    0.285000    0.413000    0.0578000
+45931.00   0.287484   0.412093   0.0562564    0.287000    0.410000    0.0565000
+45932.00   0.289188   0.408397   0.0550201    0.289000    0.406000    0.0552000
+45933.00   0.290636   0.404617   0.0539412    0.291000    0.403000    0.0541000
+45934.00   0.291826   0.400762   0.0530166    0.293000    0.399000    0.0531000
+45935.00   0.292763   0.396846   0.0522015    0.295000    0.395000    0.0521000
+45936.00   0.293494   0.392898   0.0513881    0.297000    0.392000    0.0511000
+45937.00   0.294091   0.388946   0.0504355    0.298000    0.388000    0.0499000
+45938.00   0.294653   0.385010   0.0492161    0.300000    0.384000    0.0485000
+45939.00   0.295269   0.381094   0.0476622    0.301000    0.380000    0.0468000
+45940.00   0.295999   0.377203   0.0457925    0.303000    0.377000    0.0448000
+45941.00   0.296808   0.373365   0.0437138    0.304000    0.373000    0.0426000
+45942.00   0.297631   0.369631   0.0415824    0.305000    0.369000    0.0404000
+45943.00   0.298357   0.366043   0.0395489    0.307000    0.365000    0.0384000
+45944.00   0.298912   0.362592   0.0377174    0.308000    0.362000    0.0367000
+45945.00   0.299411   0.359180   0.0361407    0.309000    0.358000    0.0353000
+45946.00   0.299981   0.355697   0.0348172    0.310000    0.354000    0.0341000
+45947.00   0.300693   0.352060   0.0337007    0.311000    0.350000    0.0330000
+45948.00   0.301537   0.348292   0.0327062    0.312000    0.346000    0.0321000
+45949.00   0.302483   0.344438   0.0317496    0.313000    0.342000    0.0312000
+45950.00   0.303491   0.340541   0.0307616    0.313000    0.338000    0.0302000
+45951.00   0.304482   0.336627   0.0296857    0.314000    0.334000    0.0291000
+45952.00   0.305408   0.332703   0.0284850    0.314000    0.331000    0.0279000
+45953.00   0.306254   0.328765   0.0271466    0.315000    0.327000    0.0266000
+45954.00   0.307012   0.324806   0.0256802    0.315000    0.323000    0.0251000
+45955.00   0.307671   0.320822   0.0241161    0.316000    0.319000    0.0236000
+45956.00   0.308251   0.316811   0.0225070    0.316000    0.315000    0.0220000
+45957.00   0.308790   0.312776   0.0209113    0.316000    0.311000    0.0206000
+45958.00   0.309318   0.308721   0.0193787    0.317000    0.307000    0.0192000
+45959.00   0.309831   0.304651   0.0179451    0.317000    0.303000    0.0179000
+45960.00   0.310317   0.300575   0.0166281    0.317000    0.299000    0.0168000
+45961.00   0.310782   0.296516   0.0154253    0.317000    0.295000    0.0157000
+45962.00   0.311226   0.292500   0.0143055    0.317000    0.291000    0.0147000
+45963.00   0.311631   0.288546   0.0132022    0.317000    0.288000    0.0137000
+45964.00   0.311986   0.284672   0.0120182    0.317000    0.284000    0.0126000
+45965.00   0.312306   0.280886   0.0106403    0.317000    0.280000    0.0112000
+45966.00   0.312596   0.277175   0.0089703    0.317000    0.276000    0.0095000
+45967.00   0.312847   0.273513   0.0069740    0.317000    0.272000    0.0075000
+45968.00   0.313046   0.269870   0.0047065    0.316000    0.268000    0.0052000
+45969.00   0.313180   0.266215   0.0022988    0.316000    0.265000    0.0028000
+45970.00   0.313234   0.262524  -0.0000854    0.315000    0.261000    0.0004000
+45971.00   0.313173   0.258798  -0.0022935    0.315000    0.257000   -0.0017000
+45972.00   0.312953   0.255048  -0.0042383    0.314000    0.253000   -0.0037000
+45973.00   0.312541   0.251287  -0.0059163    0.314000    0.249000   -0.0052000
+45974.00   0.311931   0.247524  -0.0073872    0.313000    0.246000   -0.0066000
+45975.00   0.311122   0.243769  -0.0087419    0.312000    0.242000   -0.0079000
+45976.00   0.310139   0.240020  -0.0100752    0.311000    0.238000   -0.0091000
+45977.00   0.309014   0.236272  -0.0114658    0.311000    0.234000   -0.0105000
+45978.00   0.307765   0.232514  -0.0129651    0.310000    0.231000   -0.0119000
+45979.00   0.306411   0.228737  -0.0145974    0.309000    0.227000   -0.0135000
+45980.00   0.304973   0.224926  -0.0163618    0.308000    0.223000   -0.0152000
+45981.00   0.303439   0.221082  -0.0182367    0.307000    0.219000   -0.0170000
+45982.00   0.301786   0.217214  -0.0201825    0.305000    0.216000   -0.0189000
+45983.00   0.300011   0.213339  -0.0221498    0.304000    0.212000   -0.0208000
+45984.00   0.298118   0.209481  -0.0240852    0.303000    0.209000   -0.0227000
+45985.00   0.296138   0.205665  -0.0259385    0.302000    0.205000   -0.0245000
+45986.00   0.294132   0.201920  -0.0276638    0.300000    0.201000   -0.0261000
+45987.00   0.292159   0.198270  -0.0292338    0.299000    0.198000   -0.0276000
+45988.00   0.290281   0.194738  -0.0306484    0.298000    0.194000   -0.0290000
+45989.00   0.288571   0.191344  -0.0319410    0.296000    0.191000   -0.0303000
+45990.00   0.287079   0.188101  -0.0331759    0.294000    0.187000   -0.0316000
+45991.00   0.285717   0.184988  -0.0344489    0.293000    0.184000   -0.0329000
+45992.00   0.284400   0.181961  -0.0358756    0.291000    0.180000   -0.0343000
+45993.00   0.283074   0.178971  -0.0375672    0.290000    0.177000   -0.0361000
+45994.00   0.281715   0.175971  -0.0395921    0.288000    0.174000   -0.0381000
+45995.00   0.280336   0.172924  -0.0419415    0.286000    0.170000   -0.0405000
+45996.00   0.278889   0.169829  -0.0445100    0.284000    0.167000   -0.0431000
+45997.00   0.277303   0.166697  -0.0471278    0.282000    0.164000   -0.0457000
+45998.00   0.275547   0.163527  -0.0496179    0.280000    0.160000   -0.0482000
+45999.00   0.273605   0.160317  -0.0518502    0.279000    0.157000   -0.0504000
+46000.00   0.271474   0.157067  -0.0537756    0.277000    0.154000   -0.0524000
+46001.00   0.269197   0.153794  -0.0554279    0.274000    0.151000   -0.0541000
+46002.00   0.266819   0.150514  -0.0568970    0.272000    0.148000   -0.0557000
+46003.00   0.264389   0.147245  -0.0582891    0.270000    0.145000   -0.0571000
+46004.00   0.261986   0.144010  -0.0596984    0.268000    0.142000   -0.0586000
+46005.00   0.259695   0.140827  -0.0611907    0.266000    0.139000   -0.0602000
+46006.00   0.257508   0.137697  -0.0628018    0.264000    0.136000   -0.0619000
+46007.00   0.255389   0.134606  -0.0645409    0.261000    0.133000   -0.0638000
+46008.00   0.253304   0.131541  -0.0663943    0.259000    0.130000   -0.0657000
+46009.00   0.251214   0.128501  -0.0683312    0.257000    0.127000   -0.0678000
+46010.00   0.249079   0.125494  -0.0703066    0.254000    0.124000   -0.0698000
+46011.00   0.246833   0.122520  -0.0722578    0.252000    0.121000   -0.0719000
+46012.00   0.244423   0.119576  -0.0741189    0.249000    0.119000   -0.0738000
+46013.00   0.241881   0.116679  -0.0758335    0.246000    0.116000   -0.0756000
+46014.00   0.239258   0.113852  -0.0773639    0.244000    0.113000   -0.0771000
+46015.00   0.236613   0.111116  -0.0787022    0.241000    0.110000   -0.0786000
+46016.00   0.233977   0.108480  -0.0798857    0.238000    0.108000   -0.0798000
+46017.00   0.231360   0.105945  -0.0809883    0.235000    0.105000   -0.0810000
+46018.00   0.228770   0.103517  -0.0821065    0.233000    0.103000   -0.0822000
+46019.00   0.226210   0.101208  -0.0833444    0.230000    0.100000   -0.0835000
+46020.00   0.223677   0.099029  -0.0847991    0.227000    0.098000   -0.0850000
+46021.00   0.221139   0.096966  -0.0865409    0.224000    0.095000   -0.0868000
+46022.00   0.218568   0.094989  -0.0885838    0.221000    0.092000   -0.0888000
+46023.00   0.215938   0.093066  -0.0908741    0.218000    0.090000   -0.0911000
+46024.00   0.213225   0.091166  -0.0932968    0.215000    0.088000   -0.0934000
+46025.00   0.210406   0.089264  -0.0957003    0.211000    0.085000   -0.0957000
+46026.00   0.207423   0.087336  -0.0979370    0.208000    0.083000   -0.0978000
+46027.00   0.204236   0.085360  -0.0999119    0.205000    0.081000   -0.0996000
+46028.00   0.200873   0.083317  -0.1016052    0.202000    0.078000   -0.1012000
+46029.00   0.197372   0.081189  -0.1030670    0.198000    0.076000   -0.1026000
+46030.00   0.193765   0.078961  -0.1043881    0.195000    0.074000   -0.1039000
+46031.00   0.190075   0.076633  -0.1056759    0.192000    0.072000   -0.1052000
+46032.00   0.186314   0.074211  -0.1070185    0.188000    0.069000   -0.1066000
+46033.00   0.182505   0.071705  -0.1084686    0.185000    0.067000   -0.1081000
+46034.00   0.178719   0.069134  -0.1100477    0.181000    0.065000   -0.1098000
+46035.00   0.175026   0.066518  -0.1117507    0.178000    0.063000   -0.1117000
+46036.00   0.171408   0.063884  -0.1135490    0.174000    0.061000   -0.1136000
+46037.00   0.167834   0.061277  -0.1153998    0.170000    0.059000   -0.1156000
+46038.00   0.164269   0.058741  -0.1172522    0.166000    0.057000   -0.1176000
+46039.00   0.160686   0.056322  -0.1190543    0.163000    0.055000   -0.1194000
+46040.00   0.157068   0.054065  -0.1207603    0.159000    0.053000   -0.1211000
+46041.00   0.153378   0.051970  -0.1223307    0.155000    0.051000   -0.1227000
+46042.00   0.149571   0.050022  -0.1237441    0.151000    0.050000   -0.1241000
+46043.00   0.145616   0.048212  -0.1250117    0.147000    0.048000   -0.1253000
+46044.00   0.141486   0.046529  -0.1261785    0.143000    0.046000   -0.1265000
+46045.00   0.137154   0.044964  -0.1273183    0.139000    0.045000   -0.1276000
+46046.00   0.132626   0.043500  -0.1285200    0.135000    0.043000   -0.1287000
+46047.00   0.127941   0.042103  -0.1298686    0.131000    0.042000   -0.1300000
+46048.00   0.123137   0.040739  -0.1314199    0.126000    0.040000   -0.1315000
+46049.00   0.118217   0.039369  -0.1331843    0.122000    0.039000   -0.1333000
+46050.00   0.113171   0.037956  -0.1351183    0.118000    0.037000   -0.1352000
+46051.00   0.108005   0.036506  -0.1371294    0.114000    0.036000   -0.1372000
+46052.00   0.102735   0.035042  -0.1390966    0.110000    0.035000   -0.1392000
+46053.00   0.097379   0.033587  -0.1408996    0.106000    0.034000   -0.1410000
+46054.00   0.091986   0.032161  -0.1424543    0.102000    0.033000   -0.1426000
+46055.00   0.086657   0.030775  -0.1437381    0.097000    0.032000   -0.1439000
+46056.00   0.081481   0.029451  -0.1447949    0.093000    0.031000   -0.1449000
+46057.00   0.076553   0.028198  -0.1457150    0.089000    0.030000   -0.1458000
+46058.00   0.071971   0.027005  -0.1466072    0.085000    0.029000   -0.1468000
+46059.00   0.067706   0.025917  -0.1475790    0.081000    0.028000   -0.1478000
+46060.00   0.063659   0.024995  -0.1487065    0.076000    0.028000   -0.1489000
+46061.00   0.059795   0.024242  -0.1500226    0.072000    0.027000   -0.1503000
+46062.00   0.056087   0.023657  -0.1515275    0.068000    0.026000   -0.1517000
+46063.00   0.052510   0.023235  -0.1531963    0.064000    0.026000   -0.1533000
+46064.00   0.049040   0.022967  -0.1549845    0.060000    0.025000   -0.1550000
+46065.00   0.045647   0.022839  -0.1568370    0.055000    0.025000   -0.1568000
+46066.00   0.042277   0.022841  -0.1586909    0.051000    0.025000   -0.1585000
+46067.00   0.038867   0.022960  -0.1604870    0.047000    0.025000   -0.1601000
+46068.00   0.035355   0.023183  -0.1621783    0.043000    0.025000   -0.1617000
+46069.00   0.031690   0.023492  -0.1637360    0.039000    0.025000   -0.1631000
+46070.00   0.027848   0.023864  -0.1651577    0.035000    0.025000   -0.1645000
+46071.00   0.023839   0.024297  -0.1664779    0.030000    0.025000   -0.1657000
+46072.00   0.019696   0.024802  -0.1677671    0.026000    0.025000   -0.1670000
+46073.00   0.015499   0.025390  -0.1691195    0.022000    0.025000   -0.1683000
+46074.00   0.011336   0.026070  -0.1706301    0.018000    0.025000   -0.1699000
+46075.00   0.007290   0.026845  -0.1723661    0.014000    0.026000   -0.1716000
+46076.00   0.003381   0.027703  -0.1743467    0.010000    0.027000   -0.1736000
+46077.00  -0.000400   0.028635  -0.1765293    0.006000    0.027000   -0.1758000
+46078.00  -0.004039   0.029631  -0.1788167    0.003000    0.028000   -0.1781000
+46079.00  -0.007510   0.030685  -0.1810844   -0.001000    0.029000   -0.1804000
+46080.00  -0.010793   0.031794  -0.1832128   -0.005000    0.029000   -0.1825000
+46081.00  -0.013922   0.032971  -0.1851106   -0.009000    0.030000   -0.1844000
+46082.00  -0.016965   0.034224  -0.1867379   -0.013000    0.031000   -0.1861000
+46083.00  -0.019994   0.035558  -0.1881139   -0.016000    0.032000   -0.1875000
+46084.00  -0.023076   0.036972  -0.1893057   -0.020000    0.033000   -0.1888000
+46085.00  -0.026261   0.038429  -0.1904083   -0.024000    0.034000   -0.1900000
+46086.00  -0.029573   0.039922  -0.1915209   -0.027000    0.035000   -0.1912000
+46087.00  -0.033034   0.041461  -0.1927203   -0.031000    0.036000   -0.1925000
+46088.00  -0.036654   0.043045  -0.1940474   -0.034000    0.037000   -0.1939000
+46089.00  -0.040417   0.044650  -0.1955065   -0.037000    0.039000   -0.1955000
+46090.00  -0.044273   0.046244  -0.1970727   -0.041000    0.040000   -0.1971000
+46091.00  -0.048135   0.047808  -0.1987025   -0.044000    0.041000   -0.1987000
+46092.00  -0.051928   0.049331  -0.2003427   -0.047000    0.043000   -0.2003000
+46093.00  -0.055578   0.050805  -0.2019384   -0.050000    0.044000   -0.2018000
+46094.00  -0.059013   0.052219  -0.2034409   -0.053000    0.046000   -0.2032000
+46095.00  -0.062163   0.053572  -0.2048137   -0.056000    0.048000   -0.2044000
+46096.00  -0.065008   0.054912  -0.2060277   -0.060000    0.049000   -0.2055000
+46097.00  -0.067595   0.056280  -0.2070748   -0.063000    0.051000   -0.2064000
+46098.00  -0.069992   0.057704  -0.2079760   -0.066000    0.053000   -0.2072000
+46099.00  -0.072265   0.059200  -0.2087876   -0.068000    0.055000   -0.2080000
+46100.00  -0.074472   0.060763  -0.2096027   -0.072000    0.057000   -0.2089000
+46101.00  -0.076633   0.062402  -0.2105400   -0.075000    0.059000   -0.2101000
+46102.00  -0.078755   0.064139  -0.2117058   -0.078000    0.061000   -0.2115000
+46103.00  -0.080874   0.066000  -0.2131574   -0.082000    0.063000   -0.2132000
+46104.00  -0.083041   0.068013  -0.2148787   -0.085000    0.065000   -0.2151000
+46105.00  -0.085300   0.070194  -0.2167819   -0.088000    0.067000   -0.2172000
+46106.00  -0.087660   0.072510  -0.2187311   -0.091000    0.069000   -0.2193000
+46107.00  -0.090126   0.074917  -0.2205888   -0.094000    0.071000   -0.2212000
+46108.00  -0.092701   0.077370  -0.2222578   -0.097000    0.073000   -0.2230000
+46109.00  -0.095382   0.079814  -0.2237016   -0.100000    0.075000   -0.2244000
+46110.00  -0.098160   0.082196  -0.2249468   -0.103000    0.077000   -0.2258000
+46111.00  -0.101037   0.084501  -0.2260661   -0.106000    0.080000   -0.2269000
+46112.00  -0.104051   0.086729  -0.2271542   -0.109000    0.082000   -0.2280000
+46113.00  -0.107245   0.088881  -0.2283057   -0.112000    0.084000   -0.2291000
+46114.00  -0.110647   0.090957  -0.2295951   -0.114000    0.086000   -0.2304000
+46115.00  -0.114250   0.092963  -0.2310654   -0.117000    0.088000   -0.2316000
+46116.00  -0.118004   0.094931  -0.2327217   -0.119000    0.091000   -0.2331000
+46117.00  -0.121853   0.096905  -0.2345343   -0.122000    0.093000   -0.2347000
+46118.00  -0.125726   0.098912  -0.2364516   -0.125000    0.096000   -0.2364000
+46119.00  -0.129547   0.100973  -0.2384076   -0.127000    0.098000   -0.2382000
+46120.00  -0.133243   0.103110  -0.2403331   -0.130000    0.101000   -0.2400000
+46121.00  -0.136777   0.105344  -0.2421679   -0.132000    0.103000   -0.2418000
+46122.00  -0.140144   0.107701  -0.2438655   -0.135000    0.106000   -0.2435000
+46123.00  -0.143341   0.110196  -0.2453988   -0.138000    0.109000   -0.2450000
+46124.00  -0.146379   0.112815  -0.2467622   -0.140000    0.111000   -0.2464000
+46125.00  -0.149266   0.115542  -0.2479762   -0.143000    0.114000   -0.2477000
+46126.00  -0.152035   0.118359  -0.2490984   -0.145000    0.117000   -0.2489000
+46127.00  -0.154732   0.121245  -0.2502217   -0.148000    0.119000   -0.2501000
+46128.00  -0.157401   0.124178  -0.2514646   -0.150000    0.122000   -0.2514000
+46129.00  -0.160087   0.127139  -0.2529506   -0.153000    0.125000   -0.2530000
+46130.00  -0.162838   0.130105  -0.2547729   -0.155000    0.128000   -0.2549000
+46131.00  -0.165701   0.133042  -0.2569614   -0.158000    0.131000   -0.2572000
+46132.00  -0.168632   0.135964  -0.2594436   -0.160000    0.134000   -0.2597000
+46133.00  -0.171568   0.138910  -0.2620707   -0.162000    0.137000   -0.2623000
+46134.00  -0.174442   0.141921  -0.2646679   -0.164000    0.141000   -0.2649000
+46135.00  -0.177192   0.145035  -0.2670902   -0.166000    0.144000   -0.2673000
+46136.00  -0.179774   0.148284  -0.2692583   -0.168000    0.147000   -0.2693000
+46137.00  -0.182174   0.151687  -0.2711697   -0.170000    0.150000   -0.2712000
+46138.00  -0.184390   0.155262  -0.2728870   -0.172000    0.154000   -0.2728000
+46139.00  -0.186475   0.159014  -0.2745066   -0.174000    0.157000   -0.2743000
+46140.00  -0.188489   0.162944  -0.2761266   -0.176000    0.161000   -0.2759000
+46141.00  -0.190425   0.167016  -0.2778277   -0.178000    0.164000   -0.2775000
+46142.00  -0.192241   0.171174  -0.2796601   -0.179000    0.168000   -0.2793000
+46143.00  -0.193893   0.175364  -0.2816404   -0.181000    0.171000   -0.2813000
+46144.00  -0.195330   0.179529  -0.2837540   -0.182000    0.175000   -0.2834000
+46145.00  -0.196459   0.183619  -0.2859606   -0.184000    0.178000   -0.2856000
+46146.00  -0.197257   0.187641  -0.2882065   -0.185000    0.182000   -0.2879000
+46147.00  -0.197770   0.191620  -0.2904336   -0.187000    0.186000   -0.2901000
+46148.00  -0.198078   0.195575  -0.2925881   -0.188000    0.189000   -0.2923000
+46149.00  -0.198263   0.199521  -0.2946278   -0.189000    0.193000   -0.2944000
+46150.00  -0.198402   0.203478  -0.2965273   -0.190000    0.197000   -0.2963000
+46151.00  -0.198546   0.207460  -0.2982722   -0.192000    0.200000   -0.2980000
+46152.00  -0.198758   0.211475  -0.2998687   -0.192000    0.204000   -0.2996000
+46153.00  -0.199088   0.215521  -0.3013471   -0.193000    0.208000   -0.3011000
+46154.00  -0.199546   0.219579  -0.3027625   -0.194000    0.212000   -0.3026000
+46155.00  -0.200125   0.223631  -0.3041967   -0.195000    0.216000   -0.3041000
+46156.00  -0.200799   0.227676  -0.3057583   -0.196000    0.220000   -0.3057000
+46157.00  -0.201506   0.231711  -0.3075487   -0.197000    0.223000   -0.3077000
+46158.00  -0.202157   0.235725  -0.3096280   -0.197000    0.227000   -0.3099000
+46159.00  -0.202656   0.239703  -0.3119810   -0.198000    0.231000   -0.3124000
+46160.00  -0.202894   0.243632  -0.3145091   -0.198000    0.235000   -0.3151000
+46161.00  -0.202887   0.247510  -0.3170467   -0.198000    0.239000   -0.3177000
+46162.00  -0.202694   0.251352  -0.3194193   -0.198000    0.243000   -0.3202000
+46163.00  -0.202363   0.255174  -0.3215064   -0.198000    0.247000   -0.3224000
+46164.00  -0.201945   0.258993  -0.3232768   -0.198000    0.251000   -0.3242000
+46165.00  -0.201479   0.262823  -0.3247880   -0.198000    0.255000   -0.3258000
+46166.00  -0.200979   0.266659  -0.3261551   -0.198000    0.259000   -0.3272000
+46167.00  -0.200452   0.270482  -0.3275061   -0.198000    0.263000   -0.3286000
+46168.00  -0.199907   0.274270  -0.3289482   -0.198000    0.267000   -0.3300000
+46169.00  -0.199368   0.277987  -0.3305500   -0.198000    0.271000   -0.3316000
+46170.00  -0.198855   0.281599  -0.3323403   -0.198000    0.275000   -0.3333000
+46171.00  -0.198376   0.285115  -0.3343101   -0.198000    0.279000   -0.3352000
+46172.00  -0.197935   0.288574  -0.3364221   -0.197000    0.283000   -0.3372000
+46173.00  -0.197529   0.292023  -0.3386206   -0.197000    0.286000   -0.3393000
+46174.00  -0.197147   0.295507  -0.3408390   -0.197000    0.290000   -0.3414000
+46175.00  -0.196748   0.299057  -0.3430114   -0.196000    0.294000   -0.3434000
+46176.00  -0.196341   0.302665  -0.3450778   -0.196000    0.298000   -0.3454000
+46177.00  -0.195970   0.306310  -0.3469911   -0.195000    0.302000   -0.3472000
+46178.00  -0.195653   0.309964  -0.3487283   -0.194000    0.305000   -0.3489000
+46179.00  -0.195403   0.313600  -0.3502938   -0.193000    0.309000   -0.3504000
+46180.00  -0.195218   0.317194  -0.3517206   -0.193000    0.313000   -0.3518000
+46181.00  -0.195070   0.320749  -0.3530704   -0.192000    0.316000   -0.3532000
+46182.00  -0.194934   0.324277  -0.3544233   -0.191000    0.320000   -0.3546000
+46183.00  -0.194754   0.327794  -0.3558732   -0.190000    0.324000   -0.3561000
+46184.00  -0.194430   0.331318  -0.3575151   -0.189000    0.327000   -0.3578000
+46185.00  -0.193875   0.334866  -0.3594226   -0.188000    0.331000   -0.3599000
+46186.00  -0.193064   0.338446  -0.3616246   -0.187000    0.335000   -0.3622000
+46187.00  -0.192022   0.342059  -0.3640725   -0.185000    0.338000   -0.3648000
+46188.00  -0.190796   0.345705  -0.3666421   -0.184000    0.342000   -0.3675000
+46189.00  -0.189423   0.349371  -0.3691694   -0.183000    0.345000   -0.3702000
+46190.00  -0.187921   0.353018  -0.3715021   -0.181000    0.349000   -0.3725000
+46191.00  -0.186343   0.356639  -0.3735395   -0.180000    0.352000   -0.3745000
+46192.00  -0.184758   0.360244  -0.3752701   -0.178000    0.355000   -0.3761000
+46193.00  -0.183180   0.363836  -0.3767639   -0.177000    0.359000   -0.3775000
+46194.00  -0.181540   0.367403  -0.3781335   -0.175000    0.362000   -0.3788000
+46195.00  -0.179759   0.370913  -0.3794931   -0.174000    0.365000   -0.3801000
+46196.00  -0.177855   0.374344  -0.3809154   -0.172000    0.369000   -0.3815000
+46197.00  -0.175860   0.377706  -0.3824452   -0.170000    0.372000   -0.3830000
+46198.00  -0.173806   0.381008  -0.3840934   -0.169000    0.375000   -0.3847000
+46199.00  -0.171735   0.384244  -0.3858435   -0.167000    0.378000   -0.3864000
+46200.00  -0.169684   0.387395  -0.3876593   -0.165000    0.382000   -0.3883000
+46201.00  -0.167665   0.390431  -0.3894825   -0.163000    0.385000   -0.3901000
+46202.00  -0.165657   0.393334  -0.3912474   -0.161000    0.388000   -0.3918000
+46203.00  -0.163573   0.396137  -0.3928999   -0.159000    0.391000   -0.3935000
+46204.00  -0.161262   0.398882  -0.3943990   -0.157000    0.394000   -0.3950000
+46205.00  -0.158584   0.401605  -0.3957248   -0.155000    0.397000   -0.3964000
+46206.00  -0.155578   0.404325  -0.3968812   -0.153000    0.400000   -0.3975000
+46207.00  -0.152367   0.407057  -0.3978971   -0.151000    0.403000   -0.3986000
+46208.00  -0.149070   0.409800  -0.3988270   -0.149000    0.406000   -0.3995000
+46209.00  -0.145811   0.412542  -0.3997466   -0.147000    0.409000   -0.4005000
+46210.00  -0.142687   0.415266  -0.4007451   -0.144000    0.412000   -0.4015000
+46211.00  -0.139715   0.417959  -0.4019197   -0.142000    0.415000   -0.4027000
+46212.00  -0.136898   0.420617  -0.4033516   -0.140000    0.418000   -0.4042000
+46213.00  -0.134239   0.423234  -0.4050843   -0.137000    0.420000   -0.4059000
+46214.00  -0.131710   0.425794  -0.4071018   -0.135000    0.423000   -0.4079000
+46215.00  -0.129268   0.428277  -0.4093187   -0.132000    0.426000   -0.4100000
+46216.00  -0.126862   0.430697  -0.4115847   -0.130000    0.429000   -0.4122000
+46217.00  -0.124466   0.433064  -0.4137295   -0.127000    0.431000   -0.4142000
+46218.00  -0.122062   0.435383  -0.4156205   -0.125000    0.434000   -0.4159000
+46219.00  -0.119627   0.437662  -0.4172008   -0.122000    0.436000   -0.4174000
+46220.00  -0.117138   0.439906  -0.4185018   -0.119000    0.439000   -0.4186000
+46221.00  -0.114629   0.442113  -0.4196298   -0.117000    0.441000   -0.4198000
+46222.00  -0.112156   0.444281  -0.4207131   -0.114000    0.443000   -0.4209000
+46223.00  -0.109765   0.446419  -0.4218551   -0.112000    0.445000   -0.4221000
+46224.00  -0.107492   0.448543  -0.4231118   -0.109000    0.447000   -0.4234000
+46225.00  -0.105357   0.450662  -0.4244918   -0.106000    0.449000   -0.4248000
+46226.00  -0.103325   0.452758  -0.4259725   -0.104000    0.451000   -0.4263000
+46227.00  -0.101352   0.454805  -0.4275097   -0.101000    0.453000   -0.4279000
+46228.00  -0.099393   0.456780  -0.4290493   -0.098000    0.455000   -0.4295000
+46229.00  -0.097404   0.458668  -0.4305347   -0.095000    0.456000   -0.4310000
+46230.00  -0.095335   0.460461  -0.4319136   -0.093000    0.458000   -0.4324000
+46231.00  -0.093149   0.462163  -0.4331459   -0.090000    0.460000   -0.4337000
+46232.00  -0.090825   0.463779  -0.4342128   -0.087000    0.462000   -0.4348000
+46233.00  -0.088349   0.465312  -0.4351203   -0.084000    0.464000   -0.4358000
+46234.00  -0.085711   0.466761  -0.4359015   -0.082000    0.465000   -0.4365000
+46235.00  -0.082936   0.468118  -0.4366149   -0.079000    0.467000   -0.4372000
+46236.00  -0.080122   0.469408  -0.4373028   -0.076000    0.468000   -0.4378000
+46237.00  -0.077361   0.470667  -0.4380153   -0.073000    0.470000   -0.4385000
+46238.00  -0.074610   0.471903  -0.4388551   -0.070000    0.471000   -0.4393000
+46239.00  -0.071793   0.473116  -0.4399191   -0.067000    0.473000   -0.4403000
+46240.00  -0.068839   0.474303  -0.4412630   -0.064000    0.474000   -0.4416000
+46241.00  -0.065753   0.475472  -0.4428618   -0.062000    0.475000   -0.4431000
+46242.00  -0.062576   0.476631  -0.4446257   -0.058000    0.477000   -0.4447000
+46243.00  -0.059354   0.477788  -0.4464248   -0.056000    0.478000   -0.4463000
+46244.00  -0.056153   0.478938  -0.4481124   -0.053000    0.479000   -0.4478000
+46245.00  -0.053034   0.480065  -0.4495582   -0.050000    0.480000   -0.4491000
+46246.00  -0.050009   0.481156  -0.4506836   -0.047000    0.481000   -0.4501000
+46247.00  -0.047069   0.482203   0.5485152   -0.044000    0.483000    0.5492000
+46248.00  -0.044201   0.483202   0.5479681   -0.041000    0.484000    0.5486000
+46249.00  -0.041392   0.484143   0.5475631   -0.038000    0.484000    0.5482000
+46250.00  -0.038612   0.485025   0.5471829   -0.034000    0.485000    0.5477000
+46251.00  -0.035784   0.485851   0.5467352   -0.031000    0.486000    0.5472000
+46252.00  -0.032827   0.486625   0.5461737   -0.028000    0.487000    0.5465000
+46253.00  -0.029687   0.487346   0.5455003   -0.025000    0.488000    0.5458000
+46254.00  -0.026333   0.488016   0.5447512   -0.022000    0.489000    0.5449000
+46255.00  -0.022800   0.488669   0.5439789   -0.019000    0.489000    0.5440000
+46256.00  -0.019130   0.489314   0.5432315   -0.016000    0.490000    0.5431000
+46257.00  -0.015371   0.489951   0.5425526   -0.013000    0.490000    0.5423000
+46258.00  -0.011572   0.490575   0.5419778   -0.010000    0.491000    0.5416000
+46259.00  -0.007792   0.491171   0.5415318   -0.006000    0.492000    0.5411000
+46260.00  -0.004082   0.491721   0.5412161   -0.003000    0.492000    0.5408000
+46261.00  -0.000464   0.492239   0.5410125    0.000000    0.493000    0.5405000
+46262.00   0.003063   0.492745   0.5408855    0.003000    0.493000    0.5404000
+46263.00   0.006507   0.493256   0.5407766    0.006000    0.493000    0.5403000
+46264.00   0.009872   0.493788   0.5406063    0.010000    0.494000    0.5401000
+46265.00   0.013176   0.494340   0.5402860    0.013000    0.494000    0.5398000
+46266.00   0.016429   0.494873   0.5397323    0.016000    0.494000    0.5393000
+46267.00   0.019647   0.495332   0.5389012    0.019000    0.495000    0.5386000
+46268.00   0.022886   0.495665   0.5378134    0.023000    0.495000    0.5375000
+46269.00   0.026158   0.495886   0.5365587    0.026000    0.495000    0.5363000
+46270.00   0.029459   0.496025   0.5352637    0.029000    0.495000    0.5351000
+46271.00   0.032763   0.496114   0.5340619    0.033000    0.495000    0.5339000
+46272.00   0.036041   0.496176   0.5330642    0.036000    0.495000    0.5329000
+46273.00   0.039272   0.496233   0.5323336    0.039000    0.495000    0.5321000
+46274.00   0.042463   0.496285   0.5318666    0.043000    0.495000    0.5316000
+46275.00   0.045629   0.496323   0.5315935    0.046000    0.495000    0.5313000
+46276.00   0.048765   0.496335   0.5313965    0.049000    0.495000    0.5310000
+46277.00   0.051872   0.496310   0.5311553    0.053000    0.495000    0.5307000
+46278.00   0.054974   0.496231   0.5307762    0.056000    0.495000    0.5303000
+46279.00   0.058100   0.496081   0.5302084    0.059000    0.495000    0.5297000
+46280.00   0.061323   0.495838   0.5294499    0.063000    0.494000    0.5289000
+46281.00   0.064658   0.495523   0.5285432    0.066000    0.494000    0.5280000
+46282.00   0.068084   0.495159   0.5275565    0.069000    0.494000    0.5271000
+46283.00   0.071580   0.494755   0.5265648    0.073000    0.493000    0.5261000
+46284.00   0.075122   0.494320   0.5256392    0.076000    0.493000    0.5252000
+46285.00   0.078697   0.493855   0.5248374    0.080000    0.493000    0.5244000
+46286.00   0.082279   0.493336   0.5241943    0.083000    0.492000    0.5237000
+46287.00   0.085829   0.492728   0.5237231    0.086000    0.492000    0.5232000
+46288.00   0.089317   0.491994   0.5234146    0.090000    0.491000    0.5229000
+46289.00   0.092722   0.491108   0.5232339    0.093000    0.491000    0.5226000
+46290.00   0.096012   0.490110   0.5231072    0.096000    0.490000    0.5224000
+46291.00   0.099202   0.489066   0.5229433    0.099000    0.489000    0.5222000
+46292.00   0.102330   0.488030   0.5226398    0.103000    0.488000    0.5219000
+46293.00   0.105445   0.487036   0.5220976    0.106000    0.488000    0.5213000
+46294.00   0.108604   0.486110   0.5212499    0.109000    0.487000    0.5205000
+46295.00   0.111863   0.485251   0.5200893    0.112000    0.486000    0.5194000
+46296.00   0.115192   0.484438   0.5186855    0.115000    0.485000    0.5180000
+46297.00   0.118524   0.483639   0.5171687    0.118000    0.484000    0.5166000
+46298.00   0.121791   0.482814   0.5156920    0.121000    0.483000    0.5152000
+46299.00   0.124926   0.481908   0.5143879    0.124000    0.482000    0.5140000
+46300.00   0.127884   0.480877   0.5133339    0.127000    0.481000    0.5130000
+46301.00   0.130691   0.479741   0.5125465    0.130000    0.479000    0.5123000
+46302.00   0.133380   0.478546   0.5119814    0.133000    0.478000    0.5117000
+46303.00   0.136005   0.477310   0.5115435    0.136000    0.477000    0.5113000
+46304.00   0.138660   0.475975   0.5111038    0.139000    0.476000    0.5108000
+46305.00   0.141430   0.474480   0.5105460    0.142000    0.474000    0.5102000
+46306.00   0.144270   0.472834   0.5098009    0.145000    0.473000    0.5094000
+46307.00   0.147121   0.471079   0.5088480    0.148000    0.471000    0.5084000
+46308.00   0.149942   0.469255   0.5077043    0.150000    0.470000    0.5072000
+46309.00   0.152721   0.467398   0.5064174    0.153000    0.468000    0.5060000
+46310.00   0.155498   0.465536   0.5050530    0.156000    0.467000    0.5047000
+46311.00   0.158276   0.463694   0.5036912    0.159000    0.465000    0.5035000
+46312.00   0.161038   0.461899   0.5024070    0.161000    0.464000    0.5023000
+46313.00   0.163789   0.460177   0.5012528    0.164000    0.462000    0.5013000
+46314.00   0.166536   0.458544   0.5002573    0.166000    0.460000    0.5005000
+46315.00   0.169227   0.456971   0.4994287    0.169000    0.458000    0.4997000
+46316.00   0.171822   0.455409   0.4987417    0.171000    0.456000    0.4991000
+46317.00   0.174282   0.453812   0.4981437    0.174000    0.455000    0.4985000
+46318.00   0.176573   0.452131   0.4975589    0.176000    0.453000    0.4979000
+46319.00   0.178677   0.450315   0.4968903    0.178000    0.451000    0.4971000
+46320.00   0.180611   0.448316   0.4960317    0.181000    0.449000    0.4962000
+46321.00   0.182398   0.446159   0.4948855    0.183000    0.447000    0.4949000
+46322.00   0.184053   0.443888   0.4934018    0.185000    0.445000    0.4934000
+46323.00   0.185592   0.441539   0.4916065    0.187000    0.442000    0.4915000
+46324.00   0.187053   0.439148   0.4896077    0.189000    0.440000    0.4894000
+46325.00   0.188508   0.436747   0.4875697    0.191000    0.438000    0.4873000
+46326.00   0.189998   0.434355   0.4856603    0.193000    0.436000    0.4854000
+46327.00   0.191546   0.431996   0.4839986    0.195000    0.434000    0.4837000
+46328.00   0.193176   0.429680   0.4826222    0.197000    0.431000    0.4823000
+46329.00   0.194912   0.427417   0.4814891    0.199000    0.429000    0.4812000
+46330.00   0.196776   0.425207   0.4805008    0.200000    0.427000    0.4802000
+46331.00   0.198726   0.423023   0.4795289    0.202000    0.424000    0.4791000
+46332.00   0.200685   0.420838   0.4784586    0.204000    0.422000    0.4780000
+46333.00   0.202577   0.418621   0.4772123    0.205000    0.419000    0.4767000
+46334.00   0.204362   0.416327   0.4757559    0.207000    0.417000    0.4752000
+46335.00   0.206018   0.413909   0.4740976    0.208000    0.414000    0.4736000
+46336.00   0.207522   0.411358   0.4722834    0.210000    0.412000    0.4718000
+46337.00   0.208873   0.408682   0.4703842    0.211000    0.409000    0.4699000
+46338.00   0.210079   0.405896   0.4684802    0.212000    0.406000    0.4681000
+46339.00   0.211149   0.403012   0.4666470    0.214000    0.404000    0.4663000
+46340.00   0.212122   0.400053   0.4649418    0.215000    0.401000    0.4646000
+46341.00   0.213067   0.397048   0.4633893    0.216000    0.398000    0.4631000
+46342.00   0.214036   0.394029   0.4619896    0.217000    0.395000    0.4617000
+46343.00   0.215075   0.391019   0.4607163    0.219000    0.392000    0.4604000
+46344.00   0.216228   0.388042   0.4595225    0.220000    0.390000    0.4592000
+46345.00   0.217527   0.385111   0.4583458    0.220000    0.387000    0.4580000
+46346.00   0.218911   0.382221   0.4571011    0.221000    0.384000    0.4568000
+46347.00   0.220280   0.379362   0.4556925    0.222000    0.381000    0.4554000
+46348.00   0.221542   0.376513   0.4540317    0.223000    0.378000    0.4538000
+46349.00   0.222619   0.373620   0.4520607    0.224000    0.375000    0.4518000
+46350.00   0.223455   0.370637   0.4497784    0.225000    0.372000    0.4496000
+46351.00   0.224080   0.367587   0.4472576    0.226000    0.369000    0.4471000
+46352.00   0.224562   0.364512   0.4446451    0.226000    0.366000    0.4444000
+46353.00   0.224966   0.361454   0.4421210    0.227000    0.363000    0.4419000
+46354.00   0.225359   0.358452   0.4398379    0.228000    0.360000    0.4396000
+46355.00   0.225798   0.355520   0.4378696    0.228000    0.358000    0.4376000
+46356.00   0.226285   0.352648   0.4361921    0.229000    0.355000    0.4359000
+46357.00   0.226795   0.349824   0.4347040    0.229000    0.352000    0.4344000
+46358.00   0.227307   0.347014   0.4332664    0.230000    0.349000    0.4329000
+46359.00   0.227800   0.344182   0.4317540    0.230000    0.346000    0.4314000
+46360.00   0.228257   0.341300   0.4300833    0.231000    0.343000    0.4297000
+46361.00   0.228671   0.338380   0.4282195    0.231000    0.340000    0.4279000
+46362.00   0.229030   0.335455   0.4261722    0.231000    0.337000    0.4258000
+46363.00   0.229326   0.332557   0.4239808    0.232000    0.334000    0.4237000
+46364.00   0.229560   0.329701   0.4217036    0.232000    0.331000    0.4215000
+46365.00   0.229736   0.326901   0.4194097    0.232000    0.328000    0.4192000
+46366.00   0.229840   0.324156   0.4171761    0.232000    0.326000    0.4171000
+46367.00   0.229859   0.321447   0.4150728    0.232000    0.323000    0.4150000
+46368.00   0.229785   0.318755   0.4131510    0.233000    0.320000    0.4132000
+46369.00   0.229620   0.316060   0.4114356    0.233000    0.317000    0.4115000
+46370.00   0.229408   0.313351   0.4099157    0.233000    0.314000    0.4100000
+46371.00   0.229171   0.310637   0.4085510    0.233000    0.312000    0.4086000
+46372.00   0.228924   0.307937   0.4072826    0.233000    0.309000    0.4073000
+46373.00   0.228693   0.305271   0.4060380    0.233000    0.306000    0.4060000
+46374.00   0.228504   0.302658   0.4047364    0.232000    0.303000    0.4046000
+46375.00   0.228386   0.300114   0.4032939    0.232000    0.301000    0.4030000
+46376.00   0.228334   0.297638   0.4016286    0.232000    0.298000    0.4012000
+46377.00   0.228320   0.295220   0.3996907    0.232000    0.295000    0.3990000
+46378.00   0.228317   0.292843   0.3974904    0.232000    0.293000    0.3967000
+46379.00   0.228298   0.290458   0.3951109    0.232000    0.290000    0.3942000
+46380.00   0.228247   0.288015   0.3926938    0.231000    0.288000    0.3917000
+46381.00   0.228135   0.285484   0.3904061    0.231000    0.285000    0.3893000
+46382.00   0.227954   0.282861   0.3883798    0.231000    0.282000    0.3873000
+46383.00   0.227722   0.280152   0.3866578    0.230000    0.280000    0.3855000
+46384.00   0.227464   0.277366   0.3851853    0.230000    0.277000    0.3841000
+46385.00   0.227247   0.274515   0.3838348    0.230000    0.275000    0.3827000
+46386.00   0.227107   0.271641   0.3824592    0.229000    0.272000    0.3814000
+46387.00   0.227067   0.268788   0.3809433    0.229000    0.270000    0.3799000
+46388.00   0.227161   0.265981   0.3792292    0.229000    0.267000    0.3783000
+46389.00   0.227422   0.263244   0.3773162    0.228000    0.265000    0.3765000
+46390.00   0.227857   0.260599   0.3752469    0.228000    0.262000    0.3746000
+46391.00   0.228289   0.258093   0.3731068    0.227000    0.260000    0.3726000
+46392.00   0.228513   0.255777   0.3709919    0.227000    0.257000    0.3705000
+46393.00   0.228522   0.253611   0.3689618    0.226000    0.255000    0.3686000
+46394.00   0.228351   0.251535   0.3670608    0.226000    0.252000    0.3667000
+46395.00   0.228034   0.249492   0.3653185    0.225000    0.250000    0.3650000
+46396.00   0.227578   0.247438   0.3637506    0.225000    0.247000    0.3635000
+46397.00   0.226974   0.245348   0.3623496    0.224000    0.245000    0.3622000
+46398.00   0.226214   0.243204   0.3610822    0.224000    0.243000    0.3609000
+46399.00   0.225289   0.240987   0.3598928    0.223000    0.240000    0.3598000
+46400.00   0.224203   0.238690   0.3587090    0.222000    0.238000    0.3586000
+46401.00   0.222985   0.236330   0.3574534    0.222000    0.235000    0.3574000
+46402.00   0.221664   0.233938   0.3560531    0.221000    0.233000    0.3560000
+46403.00   0.220295   0.231542   0.3544448    0.220000    0.231000    0.3544000
+46404.00   0.218965   0.229164   0.3525858    0.219000    0.228000    0.3526000
+46405.00   0.217750   0.226823   0.3504737    0.219000    0.226000    0.3505000
+46406.00   0.216636   0.224519   0.3481682    0.218000    0.224000    0.3482000
+46407.00   0.215563   0.222242   0.3457903    0.217000    0.221000    0.3459000
+46408.00   0.214475   0.219989   0.3434927    0.216000    0.219000    0.3436000
+46409.00   0.213331   0.217755   0.3414142    0.215000    0.217000    0.3416000
+46410.00   0.212100   0.215538   0.3396322    0.215000    0.215000    0.3398000
+46411.00   0.210811   0.213345   0.3381405    0.214000    0.213000    0.3383000
+46412.00   0.209523   0.211181   0.3368527    0.212000    0.211000    0.3371000
+46413.00   0.208303   0.209052   0.3356368    0.211000    0.208000    0.3358000
+46414.00   0.207217   0.206963   0.3343657    0.210000    0.206000    0.3345000
+46415.00   0.206324   0.204913   0.3329571    0.209000    0.204000    0.3331000
+46416.00   0.205587   0.202891   0.3313867    0.208000    0.202000    0.3315000
+46417.00   0.204918   0.200878   0.3296829    0.207000    0.200000    0.3297000
+46418.00   0.204245   0.198834   0.3279056    0.206000    0.198000    0.3279000
+46419.00   0.203505   0.196704   0.3261229    0.205000    0.196000    0.3261000
+46420.00   0.202651   0.194441   0.3243953    0.203000    0.194000    0.3244000
+46421.00   0.201682   0.192067   0.3227800    0.202000    0.192000    0.3228000
+46422.00   0.200599   0.189640   0.3213244    0.201000    0.190000    0.3213000
+46423.00   0.199401   0.187217   0.3200557    0.199000    0.188000    0.3201000
+46424.00   0.198074   0.184830   0.3189776    0.198000    0.186000    0.3191000
+46425.00   0.196602   0.182503   0.3180691    0.196000    0.184000    0.3182000
+46426.00   0.194969   0.180259   0.3172844    0.195000    0.182000    0.3174000
+46427.00   0.193183   0.178098   0.3165573    0.193000    0.180000    0.3167000
+46428.00   0.191268   0.176008   0.3158105    0.192000    0.178000    0.3159000
+46429.00   0.189274   0.173979   0.3149682    0.190000    0.176000    0.3150000
+46430.00   0.187278   0.172001   0.3139669    0.188000    0.174000    0.3139000
+46431.00   0.185312   0.170079   0.3127601    0.187000    0.172000    0.3126000
+46432.00   0.183379   0.168223   0.3113387    0.185000    0.170000    0.3111000
+46433.00   0.181454   0.166418   0.3097389    0.183000    0.169000    0.3094000
+46434.00   0.179503   0.164642   0.3080397    0.181000    0.167000    0.3076000
+46435.00   0.177500   0.162872   0.3063498    0.179000    0.165000    0.3058000
+46436.00   0.175449   0.161098   0.3047858    0.177000    0.163000    0.3042000
+46437.00   0.173353   0.159317   0.3034362    0.175000    0.161000    0.3028000
+46438.00   0.171218   0.157523   0.3023221    0.173000    0.159000    0.3017000
+46439.00   0.169057   0.155692   0.3013826    0.171000    0.157000    0.3008000
+46440.00   0.166891   0.153788   0.3004973    0.169000    0.155000    0.2999000
+46441.00   0.164758   0.151817   0.2995308    0.168000    0.153000    0.2990000
+46442.00   0.162690   0.149796   0.2983744    0.165000    0.151000    0.2979000
+46443.00   0.160722   0.147740   0.2969782    0.164000    0.149000    0.2966000
+46444.00   0.158878   0.145663   0.2953575    0.161000    0.147000    0.2950000
+46445.00   0.157141   0.143587   0.2935775    0.159000    0.145000    0.2933000
+46446.00   0.155372   0.141583   0.2917394    0.157000    0.144000    0.2916000
+46447.00   0.153408   0.139731   0.2899452    0.155000    0.142000    0.2898000
+46448.00   0.151200   0.138054   0.2882630    0.153000    0.141000    0.2882000
+46449.00   0.148727   0.136557   0.2867365    0.150000    0.139000    0.2867000
+46450.00   0.145986   0.135246   0.2853861    0.148000    0.137000    0.2853000
+46451.00   0.143091   0.134110   0.2842001    0.145000    0.136000    0.2842000
+46452.00   0.140167   0.133107   0.2831507    0.142000    0.135000    0.2831000
+46453.00   0.137314   0.132188   0.2821915    0.140000    0.133000    0.2822000
+46454.00   0.134567   0.131298   0.2812568    0.137000    0.132000    0.2813000
+46455.00   0.131939   0.130388   0.2802680    0.134000    0.131000    0.2803000
+46456.00   0.129401   0.129446   0.2791405    0.131000    0.130000    0.2793000
+46457.00   0.126889   0.128481   0.2777997    0.128000    0.128000    0.2780000
+46458.00   0.124344   0.127502   0.2761995    0.125000    0.127000    0.2764000
+46459.00   0.121701   0.126519   0.2743377    0.122000    0.126000    0.2747000
+46460.00   0.118895   0.125549   0.2722597    0.119000    0.125000    0.2727000
+46461.00   0.115908   0.124658   0.2700604    0.116000    0.124000    0.2707000
+46462.00   0.112821   0.123850   0.2678653    0.113000    0.124000    0.2686000
+46463.00   0.109714   0.123099   0.2657978    0.111000    0.123000    0.2668000
+46464.00   0.106661   0.122378   0.2639515    0.108000    0.122000    0.2651000
+46465.00   0.103734   0.121667   0.2623630    0.105000    0.122000    0.2636000
+46466.00   0.100944   0.121002   0.2609992    0.103000    0.121000    0.2624000
+46467.00   0.098291   0.120373   0.2597681    0.100000    0.121000    0.2612000
+46468.00   0.095777   0.119754   0.2585474    0.098000    0.120000    0.2600000
+46469.00   0.093387   0.119115   0.2572194    0.095000    0.120000    0.2587000
+46470.00   0.091103   0.118430   0.2557082    0.093000    0.120000    0.2571000
+46471.00   0.088893   0.117719   0.2539971    0.091000    0.119000    0.2554000
+46472.00   0.086712   0.117033   0.2521272    0.088000    0.119000    0.2535000
+46473.00   0.084518   0.116424   0.2501744    0.086000    0.119000    0.2515000
+46474.00   0.082279   0.115931   0.2482237    0.084000    0.119000    0.2495000
+46475.00   0.080014   0.115531   0.2463535    0.081000    0.119000    0.2477000
+46476.00   0.077728   0.115215   0.2446300    0.079000    0.118000    0.2459000
+46477.00   0.075396   0.114980   0.2431000    0.076000    0.118000    0.2443000
+46478.00   0.072972   0.114814   0.2417861    0.074000    0.118000    0.2430000
+46479.00   0.070407   0.114705   0.2406830    0.072000    0.118000    0.2417000
+46480.00   0.067671   0.114639   0.2397571    0.069000    0.118000    0.2406000
+46481.00   0.064784   0.114612   0.2389393    0.066000    0.118000    0.2395000
+46482.00   0.061769   0.114632   0.2381421    0.063000    0.118000    0.2385000
+46483.00   0.058642   0.114705   0.2372709    0.060000    0.118000    0.2373000
+46484.00   0.055401   0.114826   0.2362378    0.057000    0.118000    0.2360000
+46485.00   0.052054   0.114988   0.2349740    0.054000    0.118000    0.2346000
+46486.00   0.048662   0.115180   0.2334475    0.051000    0.118000    0.2330000
+46487.00   0.045283   0.115387   0.2316829    0.048000    0.118000    0.2312000
+46488.00   0.041965   0.115589   0.2297646    0.045000    0.118000    0.2292000
+46489.00   0.038757   0.115766   0.2278141    0.042000    0.118000    0.2273000
+46490.00   0.035706   0.115906   0.2259578    0.039000    0.118000    0.2255000
+46491.00   0.032791   0.116044   0.2243030    0.036000    0.118000    0.2239000
+46492.00   0.029953   0.116217   0.2229021    0.032000    0.118000    0.2226000
+46493.00   0.027128   0.116443   0.2217315    0.029000    0.118000    0.2216000
+46494.00   0.024253   0.116739   0.2207104    0.026000    0.118000    0.2206000
+46495.00   0.021283   0.117115   0.2197275    0.023000    0.119000    0.2197000
+46496.00   0.018245   0.117561   0.2186638    0.020000    0.119000    0.2187000
+46497.00   0.015184   0.118063   0.2174311    0.017000    0.119000    0.2175000
+46498.00   0.012129   0.118590   0.2159936    0.015000    0.119000    0.2161000
+46499.00   0.009097   0.119104   0.2143741    0.012000    0.120000    0.2145000
+46500.00   0.006107   0.119568   0.2126434    0.009000    0.120000    0.2128000
+46501.00   0.003162   0.119982   0.2109038    0.006000    0.121000    0.2111000
+46502.00   0.000266   0.120366   0.2092616    0.004000    0.121000    0.2095000
+46503.00  -0.002553   0.120732   0.2078046    0.001000    0.121000    0.2081000
+46504.00  -0.005233   0.121082   0.2065820   -0.002000    0.122000    0.2068000
+46505.00  -0.007745   0.121426   0.2055882   -0.004000    0.123000    0.2057000
+46506.00  -0.010088   0.121808   0.2047961   -0.007000    0.123000    0.2048000
+46507.00  -0.012282   0.122274   0.2041610   -0.009000    0.124000    0.2041000
+46508.00  -0.014357   0.122843   0.2036164   -0.011000    0.124000    0.2034000
+46509.00  -0.016346   0.123521   0.2030807   -0.014000    0.125000    0.2028000
+46510.00  -0.018278   0.124312   0.2024589   -0.016000    0.126000    0.2021000
+46511.00  -0.020183   0.125208   0.2016446   -0.018000    0.127000    0.2012000
+46512.00  -0.022093   0.126208   0.2005405   -0.021000    0.128000    0.2001000
+46513.00  -0.024062   0.127293   0.1990832   -0.023000    0.129000    0.1987000
+46514.00  -0.026177   0.128425   0.1972693   -0.025000    0.130000    0.1970000
+46515.00  -0.028501   0.129563   0.1951654   -0.027000    0.131000    0.1950000
+46516.00  -0.030986   0.130692   0.1929143   -0.030000    0.132000    0.1930000
+46517.00  -0.033545   0.131826   0.1906985   -0.032000    0.134000    0.1910000
+46518.00  -0.036090   0.132981   0.1886785   -0.034000    0.135000    0.1892000
+46519.00  -0.038555   0.134187   0.1869491   -0.036000    0.136000    0.1878000
+46520.00  -0.040914   0.135472   0.1855148   -0.039000    0.137000    0.1865000
+46521.00  -0.043172   0.136853   0.1842927   -0.041000    0.139000    0.1854000
+46522.00  -0.045336   0.138344   0.1831580   -0.043000    0.140000    0.1844000
+46523.00  -0.047454   0.139934   0.1819794   -0.045000    0.141000    0.1832000
+46524.00  -0.049568   0.141566   0.1806466   -0.047000    0.143000    0.1819000
+46525.00  -0.051700   0.143185   0.1790974   -0.049000    0.145000    0.1803000
+46526.00  -0.053825   0.144820   0.1773314   -0.051000    0.146000    0.1785000
+46527.00  -0.055874   0.146521   0.1754022   -0.053000    0.148000    0.1766000
+46528.00  -0.057773   0.148339   0.1733924   -0.055000    0.150000    0.1745000
+46529.00  -0.059477   0.150309   0.1713959   -0.057000    0.152000    0.1725000
+46530.00  -0.060969   0.152445   0.1694985   -0.059000    0.154000    0.1705000
+46531.00  -0.062290   0.154704   0.1677555   -0.060000    0.155000    0.1687000
+46532.00  -0.063503   0.157021   0.1661917   -0.062000    0.157000    0.1671000
+46533.00  -0.064673   0.159335   0.1648015   -0.064000    0.159000    0.1656000
+46534.00  -0.065863   0.161602   0.1635526   -0.065000    0.161000    0.1643000
+46535.00  -0.067116   0.163798   0.1623914   -0.067000    0.163000    0.1631000
+46536.00  -0.068423   0.165915   0.1612565   -0.068000    0.165000    0.1619000
+46537.00  -0.069777   0.167954   0.1600837   -0.070000    0.167000    0.1607000
+46538.00  -0.071187   0.169929   0.1588076   -0.071000    0.169000    0.1594000
+46539.00  -0.072663   0.171851   0.1573670   -0.072000    0.171000    0.1579000
+46540.00  -0.074202   0.173729   0.1557132   -0.074000    0.173000    0.1562000
+46541.00  -0.075759   0.175573   0.1538128   -0.075000    0.175000    0.1541000
+46542.00  -0.077279   0.177399   0.1516836   -0.077000    0.177000    0.1519000
+46543.00  -0.078707   0.179220   0.1494123   -0.078000    0.179000    0.1495000
+46544.00  -0.080012   0.181058   0.1471433   -0.079000    0.181000    0.1471000
+46545.00  -0.081171   0.182934   0.1450321   -0.081000    0.183000    0.1449000
+46546.00  -0.082168   0.184865   0.1431903   -0.082000    0.185000    0.1430000
+46547.00  -0.083015   0.186866   0.1416451   -0.083000    0.187000    0.1414000
+46548.00  -0.083728   0.188951   0.1403312   -0.084000    0.189000    0.1400000
+46549.00  -0.084328   0.191137   0.1391180   -0.085000    0.191000    0.1388000
+46550.00  -0.084841   0.193434   0.1378587   -0.086000    0.193000    0.1376000
+46551.00  -0.085302   0.195807   0.1364402   -0.087000    0.195000    0.1362000
+46552.00  -0.085766   0.198188   0.1348073   -0.088000    0.197000    0.1346000
+46553.00  -0.086310   0.200499   0.1329628   -0.089000    0.199000    0.1328000
+46554.00  -0.087006   0.202681   0.1309539   -0.090000    0.201000    0.1309000
+46555.00  -0.087865   0.204743   0.1288565   -0.090000    0.203000    0.1289000
+46556.00  -0.088838   0.206708   0.1267570   -0.091000    0.205000    0.1268000
+46557.00  -0.089873   0.208598   0.1247376   -0.092000    0.207000    0.1248000
+46558.00  -0.090917   0.210433   0.1228653   -0.092000    0.210000    0.1230000
+46559.00  -0.091923   0.212232   0.1211815   -0.093000    0.212000    0.1214000
+46560.00  -0.092849   0.214013   0.1196996   -0.094000    0.214000    0.1199000
+46561.00  -0.093688   0.215808   0.1184135   -0.094000    0.216000    0.1187000
+46562.00  -0.094451   0.217648   0.1172924   -0.095000    0.218000    0.1176000
+46563.00  -0.095149   0.219567   0.1162853   -0.095000    0.221000    0.1167000
+46564.00  -0.095796   0.221597   0.1153295   -0.096000    0.223000    0.1157000
+46565.00  -0.096430   0.223764   0.1143641   -0.096000    0.225000    0.1147000
+46566.00  -0.097129   0.226072   0.1133334   -0.097000    0.227000    0.1135000
+46567.00  -0.097864   0.228443   0.1121536   -0.097000    0.229000    0.1122000
+46568.00  -0.098581   0.230775   0.1107561   -0.098000    0.232000    0.1107000
+46569.00  -0.099267   0.233012   0.1091256   -0.098000    0.234000    0.1089000
+46570.00  -0.099946   0.235158   0.1073146   -0.099000    0.236000    0.1070000
+46571.00  -0.100619   0.237225   0.1054365   -0.099000    0.238000    0.1051000
+46572.00  -0.101277   0.239225   0.1036423   -0.100000    0.240000    0.1033000
+46573.00  -0.101901   0.241178   0.1020719   -0.100000    0.242000    0.1018000
+46574.00  -0.102451   0.243121   0.1008047   -0.100000    0.244000    0.1006000
+46575.00  -0.102876   0.245094   0.0998261   -0.101000    0.246000    0.0997000
+46576.00  -0.103160   0.247103   0.0990329   -0.102000    0.248000    0.0990000
+46577.00  -0.103325   0.249134   0.0982836   -0.102000    0.250000    0.0983000
+46578.00  -0.103399   0.251173   0.0974527   -0.103000    0.252000    0.0976000
+46579.00  -0.103404   0.253206   0.0964718   -0.103000    0.253000    0.0967000
+46580.00  -0.103346   0.255218   0.0953424   -0.103000    0.255000    0.0956000
+46581.00  -0.103243   0.257218   0.0941066   -0.104000    0.257000    0.0944000
+46582.00  -0.103123   0.259234   0.0928334   -0.104000    0.259000    0.0932000
+46583.00  -0.103011   0.261304   0.0915998   -0.104000    0.261000    0.0919000
+46584.00  -0.102934   0.263462   0.0904755   -0.104000    0.263000    0.0908000
+46585.00  -0.102910   0.265735   0.0895140   -0.104000    0.265000    0.0899000
+46586.00  -0.102914   0.268094   0.0887517   -0.104000    0.267000    0.0891000
+46587.00  -0.102903   0.270487   0.0882035   -0.103000    0.269000    0.0885000
+46588.00  -0.102833   0.272860   0.0878589   -0.103000    0.271000    0.0881000
+46589.00  -0.102660   0.275152   0.0876797   -0.102000    0.274000    0.0879000
+46590.00  -0.102342   0.277314   0.0876058   -0.101000    0.276000    0.0878000
+46591.00  -0.101845   0.279349   0.0875678   -0.100000    0.278000    0.0877000
+46592.00  -0.101155   0.281292   0.0874923   -0.100000    0.280000    0.0875000
+46593.00  -0.100277   0.283176   0.0873049   -0.099000    0.282000    0.0872000
+46594.00  -0.099225   0.285031   0.0869416   -0.098000    0.284000    0.0867000
+46595.00  -0.098024   0.286885   0.0863563   -0.096000    0.287000    0.0859000
+46596.00  -0.096693   0.288773   0.0855339   -0.095000    0.289000    0.0850000
+46597.00  -0.095276   0.290712   0.0844919   -0.094000    0.291000    0.0838000
+46598.00  -0.093812   0.292705   0.0832929   -0.093000    0.293000    0.0826000
+46599.00  -0.092335   0.294749   0.0820471   -0.092000    0.296000    0.0814000
+46600.00  -0.090889   0.296847   0.0808817   -0.090000    0.298000    0.0803000
+46601.00  -0.089542   0.299006   0.0799154   -0.089000    0.300000    0.0794000
+46602.00  -0.088276   0.301210   0.0791929   -0.088000    0.303000    0.0788000
+46603.00  -0.087034   0.303439   0.0786670   -0.087000    0.305000    0.0784000
+46604.00  -0.085751   0.305684   0.0782238   -0.085000    0.307000    0.0781000
+46605.00  -0.084370   0.307936   0.0777276   -0.084000    0.309000    0.0777000
+46606.00  -0.082897   0.310196   0.0770662   -0.083000    0.311000    0.0771000
+46607.00  -0.081352   0.312466   0.0761962   -0.081000    0.313000    0.0762000
+46608.00  -0.079745   0.314743   0.0751471   -0.080000    0.316000    0.0752000
+46609.00  -0.078095   0.317015   0.0739938   -0.079000    0.318000    0.0740000
+46610.00  -0.076437   0.319251   0.0728272   -0.077000    0.320000    0.0728000
+46611.00  -0.074819   0.321453   0.0717335   -0.076000    0.322000    0.0717000
+46612.00  -0.073288   0.323644   0.0707726   -0.075000    0.324000    0.0707000
+46613.00  -0.071864   0.325834   0.0699821   -0.073000    0.326000    0.0699000
+46614.00  -0.070558   0.328031   0.0693782   -0.072000    0.328000    0.0693000
+46615.00  -0.069363   0.330236   0.0689524   -0.070000    0.330000    0.0689000
+46616.00  -0.068207   0.332442   0.0686737   -0.069000    0.332000    0.0686000
+46617.00  -0.067004   0.334648   0.0684897   -0.067000    0.334000    0.0684000
+46618.00  -0.065692   0.336846   0.0683299   -0.066000    0.336000    0.0683000
+46619.00  -0.064318   0.339016   0.0681120   -0.064000    0.338000    0.0681000
+46620.00  -0.062954   0.341131   0.0677608   -0.063000    0.340000    0.0677000
+46621.00  -0.061644   0.343144   0.0672256   -0.061000    0.342000    0.0672000
+46622.00  -0.060394   0.344996   0.0664822   -0.060000    0.344000    0.0665000
+46623.00  -0.059201   0.346626   0.0655386   -0.058000    0.346000    0.0656000
+46624.00  -0.057992   0.348012   0.0644446   -0.056000    0.348000    0.0645000
+46625.00  -0.056638   0.349195   0.0632836   -0.054000    0.350000    0.0633000
+46626.00  -0.055124   0.350248   0.0621501   -0.053000    0.351000    0.0622000
+46627.00  -0.053477   0.351247   0.0611486   -0.051000    0.353000    0.0611000
+46628.00  -0.051711   0.352262   0.0603652   -0.049000    0.354000    0.0602000
+46629.00  -0.049825   0.353364   0.0598363   -0.047000    0.356000    0.0597000
+46630.00  -0.047823   0.354603   0.0595248   -0.045000    0.358000    0.0593000
+46631.00  -0.045742   0.355959   0.0593177   -0.043000    0.359000    0.0591000
+46632.00  -0.043634   0.357389   0.0590660   -0.042000    0.360000    0.0588000
+46633.00  -0.041552   0.358849   0.0586337   -0.040000    0.362000    0.0584000
+46634.00  -0.039560   0.360304   0.0579461   -0.038000    0.363000    0.0577000
+46635.00  -0.037728   0.361725   0.0570104   -0.036000    0.364000    0.0568000
+46636.00  -0.036067   0.363091   0.0559092   -0.034000    0.365000    0.0558000
+46637.00  -0.034531   0.364382   0.0547645   -0.033000    0.367000    0.0547000
+46638.00  -0.033067   0.365577   0.0536947   -0.031000    0.368000    0.0536000
+46639.00  -0.031637   0.366669   0.0527888   -0.029000    0.368000    0.0527000
+46640.00  -0.030274   0.367690   0.0520890   -0.028000    0.369000    0.0520000
+46641.00  -0.028996   0.368666   0.0516086   -0.026000    0.370000    0.0515000
+46642.00  -0.027795   0.369619   0.0513373   -0.025000    0.371000    0.0511000
+46643.00  -0.026634   0.370570   0.0512372   -0.024000    0.372000    0.0509000
+46644.00  -0.025468   0.371543   0.0512451   -0.022000    0.372000    0.0509000
+46645.00  -0.024242   0.372545   0.0512849   -0.021000    0.373000    0.0509000
+46646.00  -0.022891   0.373498   0.0512841   -0.020000    0.374000    0.0508000
+46647.00  -0.021434   0.374402   0.0511452   -0.019000    0.375000    0.0506000
+46648.00  -0.019918   0.375285   0.0507817   -0.018000    0.376000    0.0502000
+46649.00  -0.018396   0.376154   0.0501389   -0.017000    0.377000    0.0496000
+46650.00  -0.016918   0.377001   0.0492042   -0.016000    0.378000    0.0487000
+46651.00  -0.015510   0.377825   0.0480271   -0.014000    0.379000    0.0476000
+46652.00  -0.014168   0.378641   0.0467073   -0.013000    0.380000    0.0464000
+46653.00  -0.012882   0.379462   0.0453699   -0.012000    0.381000    0.0452000
+46654.00  -0.011640   0.380306   0.0441420   -0.011000    0.382000    0.0440000
+46655.00  -0.010403   0.381186   0.0431236   -0.009000    0.383000    0.0430000
+46656.00  -0.009141   0.382083   0.0423668   -0.008000    0.384000    0.0423000
+46657.00  -0.007839   0.382970   0.0418592   -0.007000    0.385000    0.0419000
+46658.00  -0.006482   0.383837   0.0415167   -0.005000    0.386000    0.0415000
+46659.00  -0.005055   0.384681   0.0412078   -0.004000    0.387000    0.0412000
+46660.00  -0.003544   0.385493   0.0407924   -0.002000    0.388000    0.0407000
+46661.00  -0.001936   0.386285   0.0401629    0.000000    0.389000    0.0401000
+46662.00  -0.000222   0.387076   0.0392789    0.001000    0.390000    0.0391000
+46663.00   0.001602   0.387884   0.0381772    0.003000    0.391000    0.0380000
+46664.00   0.003514   0.388702   0.0369529    0.005000    0.391000    0.0368000
+46665.00   0.005484   0.389514   0.0357240    0.006000    0.392000    0.0355000
+46666.00   0.007473   0.390301   0.0345931    0.008000    0.393000    0.0344000
+46667.00   0.009457   0.391054   0.0336291    0.010000    0.394000    0.0334000
+46668.00   0.011415   0.391764   0.0328618    0.011000    0.394000    0.0327000
+46669.00   0.013324   0.392421   0.0322875    0.013000    0.395000    0.0321000
+46670.00   0.015140   0.393021   0.0318770    0.015000    0.395000    0.0317000
+46671.00   0.016870   0.393579   0.0315836    0.016000    0.396000    0.0314000
+46672.00   0.018538   0.394122   0.0313464    0.018000    0.396000    0.0312000
+46673.00   0.020155   0.394677   0.0310971    0.020000    0.397000    0.0310000
+46674.00   0.021728   0.395271   0.0307690    0.021000    0.397000    0.0306000
+46675.00   0.023265   0.395918   0.0302994    0.023000    0.397000    0.0301000
+46676.00   0.024777   0.396582   0.0296206    0.025000    0.398000    0.0293000
+46677.00   0.026280   0.397211   0.0286889    0.026000    0.398000    0.0283000
+46678.00   0.027776   0.397750   0.0275048    0.028000    0.398000    0.0270000
+46679.00   0.029242   0.398137   0.0261182    0.030000    0.398000    0.0256000
+46680.00   0.030660   0.398317   0.0246201    0.031000    0.399000    0.0240000
+46681.00   0.032040   0.398304   0.0231308    0.033000    0.399000    0.0226000
+46682.00   0.033398   0.398165   0.0217642    0.034000    0.399000    0.0213000
+46683.00   0.034748   0.397969   0.0205972    0.036000    0.399000    0.0202000
+46684.00   0.036109   0.397793   0.0196517    0.037000    0.399000    0.0194000
+46685.00   0.037511   0.397718   0.0188843    0.038000    0.399000    0.0186000
+46686.00   0.038937   0.397755   0.0181818    0.040000    0.399000    0.0180000
+46687.00   0.040369   0.397869   0.0174055    0.041000    0.399000    0.0172000
+46688.00   0.041792   0.398011   0.0164323    0.043000    0.399000    0.0161000
+46689.00   0.043195   0.398133   0.0151853    0.044000    0.399000    0.0149000
+46690.00   0.044565   0.398189   0.0136551    0.045000    0.399000    0.0133000
+46691.00   0.045892   0.398157   0.0119068    0.046000    0.399000    0.0115000
+46692.00   0.047175   0.398031   0.0100508    0.048000    0.399000    0.0097000
+46693.00   0.048412   0.397812   0.0082069    0.049000    0.399000    0.0079000
+46694.00   0.049596   0.397519   0.0064771    0.050000    0.399000    0.0062000
+46695.00   0.050721   0.397166   0.0049286    0.051000    0.399000    0.0047000
+46696.00   0.051787   0.396760   0.0035841    0.052000    0.398000    0.0034000
+46697.00   0.052821   0.396311   0.0024267    0.054000    0.398000    0.0022000
+46698.00   0.053854   0.395831   0.0014112    0.055000    0.398000    0.0012000
+46699.00   0.054917   0.395336   0.0004703    0.056000    0.398000    0.0003000
+46700.00   0.056028   0.394854  -0.0004763    0.057000    0.397000   -0.0007000
+46701.00   0.057188   0.394417  -0.0015092    0.058000    0.397000   -0.0017000
+46702.00   0.058390   0.394051  -0.0027028    0.060000    0.396000   -0.0029000
+46703.00   0.059614   0.393782  -0.0041178    0.061000    0.396000   -0.0043000
+46704.00   0.060833   0.393642  -0.0057892    0.062000    0.395000   -0.0060000
+46705.00   0.062023   0.393644  -0.0077152    0.063000    0.395000   -0.0080000
+46706.00   0.063183   0.393743  -0.0098497    0.064000    0.395000   -0.0101000
+46707.00   0.064319   0.393870  -0.0120944    0.066000    0.394000   -0.0124000
+46708.00   0.065439   0.393967  -0.0143128    0.067000    0.394000   -0.0146000
+46709.00   0.066561   0.393983  -0.0163691    0.068000    0.393000   -0.0167000
+46710.00   0.067700   0.393877  -0.0181709    0.069000    0.393000   -0.0184000
+46711.00   0.068857   0.393644  -0.0196953    0.071000    0.392000   -0.0200000
+46712.00   0.070031   0.393309  -0.0209933    0.072000    0.392000   -0.0212000
+46713.00   0.071220   0.392901  -0.0221744    0.073000    0.392000   -0.0224000
+46714.00   0.072432   0.392455  -0.0233677    0.074000    0.391000   -0.0237000
+46715.00   0.073692   0.392017  -0.0246816    0.076000    0.391000   -0.0251000
+46716.00   0.075028   0.391609  -0.0261924    0.077000    0.391000   -0.0267000
+46717.00   0.076466   0.391242  -0.0279202    0.078000    0.391000   -0.0285000
+46718.00   0.078018   0.390927  -0.0298285    0.079000    0.390000   -0.0305000
+46719.00   0.079677   0.390666  -0.0318410    0.081000    0.390000   -0.0326000
+46720.00   0.081418   0.390457  -0.0338647    0.082000    0.390000   -0.0347000
+46721.00   0.083132   0.390277  -0.0358018    0.083000    0.389000   -0.0367000
+46722.00   0.084741   0.390107  -0.0375854    0.085000    0.389000   -0.0384000
+46723.00   0.086193   0.389931  -0.0391847    0.086000    0.389000   -0.0400000
+46724.00   0.087450   0.389740  -0.0406038    0.087000    0.388000   -0.0413000
+46725.00   0.088503   0.389529  -0.0418764    0.088000    0.388000   -0.0425000
+46726.00   0.089430   0.389295  -0.0430563    0.090000    0.388000   -0.0435000
+46727.00   0.090340   0.389034  -0.0442099    0.091000    0.387000   -0.0445000
+46728.00   0.091325   0.388742  -0.0454034    0.092000    0.387000   -0.0455000
+46729.00   0.092387   0.388414  -0.0466797    0.094000    0.387000   -0.0467000
+46730.00   0.093479   0.388037  -0.0480733    0.095000    0.387000   -0.0480000
+46731.00   0.094579   0.387595  -0.0496329    0.096000    0.386000   -0.0495000
+46732.00   0.095684   0.387071  -0.0513921    0.097000    0.386000   -0.0512000
+46733.00   0.096822   0.386457  -0.0533440    0.099000    0.385000   -0.0532000
+46734.00   0.098035   0.385746  -0.0554304    0.100000    0.385000   -0.0553000
+46735.00   0.099348   0.384936  -0.0575419    0.101000    0.385000   -0.0574000
+46736.00   0.100727   0.384042  -0.0595353    0.103000    0.384000   -0.0594000
+46737.00   0.102130   0.383079  -0.0612828    0.104000    0.383000   -0.0612000
+46738.00   0.103520   0.382064  -0.0627206    0.105000    0.383000   -0.0627000
+46739.00   0.104920   0.381025  -0.0638732    0.106000    0.382000   -0.0638000
+46740.00   0.106443   0.380021  -0.0648435    0.108000    0.382000   -0.0648000
+46741.00   0.108160   0.379146  -0.0657776    0.109000    0.381000   -0.0659000
+46742.00   0.110029   0.378363  -0.0668165    0.111000    0.380000   -0.0670000
+46743.00   0.111974   0.377602  -0.0680527    0.113000    0.379000   -0.0683000
+46744.00   0.113883   0.376827  -0.0695212    0.114000    0.378000   -0.0698000
+46745.00   0.115670   0.376009  -0.0711957    0.116000    0.377000   -0.0716000
+46746.00   0.117284   0.375126  -0.0730039    0.117000    0.376000   -0.0734000
+46747.00   0.118681   0.374161  -0.0748528    0.118000    0.374000   -0.0753000
+46748.00   0.119822   0.373111  -0.0766462    0.119000    0.373000   -0.0770000
+46749.00   0.120675   0.371975  -0.0783024    0.120000    0.372000   -0.0786000
+46750.00   0.121222   0.370755  -0.0797678    0.121000    0.371000   -0.0800000
+46751.00   0.121525   0.369473  -0.0810249    0.121000    0.370000   -0.0813000
+46752.00   0.121669   0.368161  -0.0820903    0.122000    0.368000   -0.0823000
+46753.00   0.121731   0.366845  -0.0830098    0.122000    0.367000   -0.0832000
+46754.00   0.121735   0.365532  -0.0838496    0.123000    0.366000   -0.0840000
+46755.00   0.121695   0.364223  -0.0846851    0.123000    0.365000   -0.0848000
+46756.00   0.121645   0.362924  -0.0855930    0.123000    0.364000   -0.0857000
+46757.00   0.121615   0.361638  -0.0866396    0.124000    0.362000   -0.0868000
+46758.00   0.121636   0.360361  -0.0878742    0.124000    0.361000   -0.0881000
+46759.00   0.121737   0.359088  -0.0893248    0.124000    0.360000   -0.0895000
+46760.00   0.121951   0.357817  -0.0909912    0.125000    0.359000   -0.0912000
+46761.00   0.122300   0.356546  -0.0928325    0.125000    0.358000   -0.0931000
+46762.00   0.122802   0.355271  -0.0947608    0.126000    0.356000   -0.0950000
+46763.00   0.123482   0.353996  -0.0966481    0.126000    0.355000   -0.0969000
+46764.00   0.124368   0.352720  -0.0983574    0.127000    0.354000   -0.0986000
+46765.00   0.125479   0.351444  -0.0997919    0.127000    0.352000   -0.1001000
+46766.00   0.126780   0.350165  -0.1009402    0.128000    0.351000   -0.1012000
+46767.00   0.128205   0.348882  -0.1018824    0.129000    0.350000   -0.1022000
+46768.00   0.129688   0.347592  -0.1027627    0.130000    0.348000   -0.1031000
+46769.00   0.131165   0.346274  -0.1037358    0.131000    0.347000   -0.1041000
+46770.00   0.132580   0.344903  -0.1049099    0.132000    0.346000   -0.1052000
+46771.00   0.133924   0.343466  -0.1063124    0.133000    0.344000   -0.1066000
+46772.00   0.135176   0.341972  -0.1079059    0.134000    0.343000   -0.1082000
+46773.00   0.136306   0.340435  -0.1096072    0.135000    0.341000   -0.1099000
+46774.00   0.137286   0.338871  -0.1113158    0.136000    0.340000   -0.1115000
+46775.00   0.138103   0.337292  -0.1129402    0.137000    0.339000   -0.1131000
+46776.00   0.138777   0.335713  -0.1144085    0.138000    0.337000   -0.1146000
+46777.00   0.139334   0.334158  -0.1156739    0.138000    0.336000   -0.1158000
+46778.00   0.139803   0.332651  -0.1167165    0.139000    0.335000   -0.1168000
+46779.00   0.140216   0.331220  -0.1175448    0.140000    0.334000   -0.1177000
+46780.00   0.140605   0.329888  -0.1182030    0.140000    0.332000   -0.1184000
+46781.00   0.140997   0.328664  -0.1187732    0.141000    0.331000   -0.1191000
+46782.00   0.141411   0.327549  -0.1193512    0.141000    0.330000   -0.1197000
+46783.00   0.141868   0.326542  -0.1200310    0.142000    0.329000   -0.1204000
+46784.00   0.142385   0.325615  -0.1208896    0.142000    0.328000   -0.1213000
+46785.00   0.142978   0.324735  -0.1219795    0.142000    0.327000   -0.1223000
+46786.00   0.143609   0.323868  -0.1233149    0.143000    0.326000   -0.1236000
+46787.00   0.144204   0.322977  -0.1248792    0.143000    0.325000   -0.1251000
+46788.00   0.144684   0.322025  -0.1266263    0.144000    0.325000   -0.1267000
+46789.00   0.145013   0.321001  -0.1284839    0.144000    0.323000   -0.1285000
+46790.00   0.145222   0.319917  -0.1303569    0.144000    0.322000   -0.1303000
+46791.00   0.145351   0.318788  -0.1321329    0.145000    0.321000   -0.1321000
+46792.00   0.145443   0.317630  -0.1337127    0.145000    0.320000   -0.1336000
+46793.00   0.145537   0.316458  -0.1350465    0.145000    0.319000   -0.1349000
+46794.00   0.145675   0.315287  -0.1361608    0.145000    0.317000   -0.1360000
+46795.00   0.145891   0.314129  -0.1371607    0.146000    0.316000   -0.1369000
+46796.00   0.146164   0.312978  -0.1381993    0.146000    0.315000   -0.1379000
+46797.00   0.146446   0.311819  -0.1394157    0.146000    0.314000   -0.1391000
+46798.00   0.146692   0.310639  -0.1408817    0.146000    0.312000   -0.1406000
+46799.00   0.146854   0.309420  -0.1425808    0.146000    0.311000   -0.1423000
+46800.00   0.146890   0.308156  -0.1444251    0.146000    0.309000   -0.1441000
+46801.00   0.146762   0.306858  -0.1462932    0.146000    0.308000   -0.1460000
+46802.00   0.146447   0.305532  -0.1480683    0.145000    0.307000   -0.1478000
+46803.00   0.145930   0.304171  -0.1496648    0.145000    0.305000   -0.1493000
+46804.00   0.145216   0.302764  -0.1510340    0.145000    0.304000   -0.1507000
+46805.00   0.144363   0.301309  -0.1521611    0.144000    0.303000   -0.1518000
+46806.00   0.143461   0.299808  -0.1530660    0.144000    0.302000   -0.1528000
+46807.00   0.142592   0.298270  -0.1537942    0.143000    0.300000   -0.1535000
+46808.00   0.141826   0.296709  -0.1544114    0.143000    0.299000   -0.1542000
+46809.00   0.141231   0.295141  -0.1549984    0.142000    0.297000   -0.1548000
+46810.00   0.140855   0.293585  -0.1556391    0.141000    0.296000   -0.1555000
+46811.00   0.140624   0.292056  -0.1564038    0.141000    0.295000   -0.1563000
+46812.00   0.140450   0.290534  -0.1573502    0.140000    0.293000   -0.1573000
+46813.00   0.140262   0.289004  -0.1585097    0.140000    0.292000   -0.1585000
+46814.00   0.139989   0.287471  -0.1598827    0.139000    0.290000   -0.1598000
+46815.00   0.139575   0.285944  -0.1614379    0.138000    0.289000   -0.1614000
+46816.00   0.139026   0.284463  -0.1631089    0.138000    0.288000   -0.1631000
+46817.00   0.138418   0.283070  -0.1648016    0.137000    0.286000   -0.1647000
+46818.00   0.137857   0.281786  -0.1664139    0.137000    0.285000   -0.1664000
+46819.00   0.137431   0.280616  -0.1678506    0.136000    0.284000   -0.1678000
+46820.00   0.137166   0.279539  -0.1690519    0.136000    0.282000   -0.1690000
+46821.00   0.137038   0.278561  -0.1700244    0.135000    0.281000   -0.1700000
+46822.00   0.137011   0.277704  -0.1708510    0.135000    0.280000   -0.1708000
+46823.00   0.137001   0.276949  -0.1716741    0.135000    0.279000   -0.1717000
+46824.00   0.136835   0.276208  -0.1726509    0.134000    0.277000   -0.1727000
+46825.00   0.136335   0.275387  -0.1738984    0.134000    0.276000   -0.1740000
+46826.00   0.135381   0.274410  -0.1754526    0.133000    0.275000   -0.1756000
+46827.00   0.134106   0.273266  -0.1772565    0.133000    0.274000   -0.1774000
+46828.00   0.132707   0.271968  -0.1791915    0.132000    0.273000   -0.1793000
+46829.00   0.131373   0.270544  -0.1811235    0.132000    0.271000   -0.1812000
+46830.00   0.130288   0.269034  -0.1829432    0.132000    0.270000   -0.1830000
+46831.00   0.129572   0.267504  -0.1845796    0.131000    0.269000   -0.1846000
+46832.00   0.129204   0.266010  -0.1860049    0.131000    0.268000   -0.1860000
+46833.00   0.129075   0.264586  -0.1872302    0.130000    0.267000   -0.1872000
+46834.00   0.129034   0.263271  -0.1882929    0.130000    0.266000   -0.1882000
+46835.00   0.128903   0.262120  -0.1892463    0.129000    0.265000   -0.1891000
+46836.00   0.128587   0.261167  -0.1901571    0.129000    0.264000   -0.1900000
+46837.00   0.128150   0.260373  -0.1911065    0.128000    0.263000   -0.1909000
+46838.00   0.127667   0.259684  -0.1921723    0.128000    0.262000   -0.1920000
+46839.00   0.127184   0.259047  -0.1934137    0.128000    0.262000   -0.1933000
+46840.00   0.126747   0.258408  -0.1948653    0.127000    0.261000   -0.1948000
+46841.00   0.126370   0.257736  -0.1965376    0.127000    0.260000   -0.1965000
+46842.00   0.126024   0.257013  -0.1984046    0.127000    0.259000   -0.1984000
+46843.00   0.125673   0.256225  -0.2004034    0.126000    0.258000   -0.2004000
+46844.00   0.125290   0.255354  -0.2024439    0.126000    0.257000   -0.2025000
+46845.00   0.124857   0.254391  -0.2044244    0.125000    0.256000   -0.2045000
+46846.00   0.124399   0.253371  -0.2062584    0.125000    0.255000   -0.2064000
+46847.00   0.123945   0.252313  -0.2078958    0.124000    0.254000   -0.2081000
+46848.00   0.123508   0.251228  -0.2093397    0.124000    0.253000   -0.2096000
+46849.00   0.123087   0.250117  -0.2106572    0.123000    0.252000   -0.2109000
+46850.00   0.122661   0.248976  -0.2119707    0.123000    0.251000   -0.2122000
+46851.00   0.122246   0.247844  -0.2134289    0.122000    0.250000   -0.2137000
+46852.00   0.121872   0.246727  -0.2151634    0.122000    0.249000   -0.2153000
+46853.00   0.121495   0.245613  -0.2172400    0.121000    0.247000   -0.2173000
+46854.00   0.121053   0.244482  -0.2196369    0.121000    0.246000   -0.2196000
+46855.00   0.120474   0.243307  -0.2222510    0.120000    0.245000   -0.2220000
+46856.00   0.119739   0.242064  -0.2249249    0.119000    0.243000   -0.2245000
+46857.00   0.118859   0.240737  -0.2274987    0.118000    0.242000   -0.2268000
+46858.00   0.117846   0.239311  -0.2298512    0.118000    0.240000   -0.2290000
+46859.00   0.116699   0.237782  -0.2319140    0.117000    0.239000   -0.2309000
+46860.00   0.115417   0.236156  -0.2336699    0.116000    0.237000   -0.2326000
+46861.00   0.114084   0.234471  -0.2351542    0.115000    0.236000   -0.2341000
+46862.00   0.112799   0.232769  -0.2364341    0.115000    0.235000   -0.2355000
+46863.00   0.111657   0.231094  -0.2375923    0.114000    0.234000   -0.2368000
+46864.00   0.110751   0.229489  -0.2387201    0.113000    0.233000   -0.2382000
+46865.00   0.110161   0.227994  -0.2399098    0.113000    0.231000   -0.2395000
+46866.00   0.109870   0.226654  -0.2412443    0.112000    0.230000   -0.2411000
+46867.00   0.109779   0.225503  -0.2427787    0.111000    0.229000   -0.2428000
+46868.00   0.109810   0.224548  -0.2445374    0.111000    0.228000   -0.2447000
+46869.00   0.109899   0.223794  -0.2465079    0.110000    0.227000   -0.2468000
+46870.00   0.109988   0.223232  -0.2486381    0.109000    0.226000   -0.2490000
+46871.00   0.110020   0.222818  -0.2508431    0.109000    0.225000   -0.2512000
+46872.00   0.109928   0.222495  -0.2530193    0.108000    0.224000   -0.2534000
+46873.00   0.109637   0.222199  -0.2550668    0.107000    0.223000   -0.2553000
+46874.00   0.109055   0.221849  -0.2569179    0.107000    0.223000   -0.2571000
+46875.00   0.108093   0.221367  -0.2585563    0.106000    0.222000   -0.2586000
+46876.00   0.106728   0.220718  -0.2600186    0.105000    0.221000   -0.2599000
+46877.00   0.105080   0.219945  -0.2613939    0.104000    0.220000   -0.2612000
+46878.00   0.103299   0.219106  -0.2628015    0.104000    0.219000   -0.2624000
+46879.00   0.101537   0.218262  -0.2643567    0.103000    0.218000   -0.2639000
+46880.00   0.099933   0.217460  -0.2661370    0.102000    0.217000   -0.2656000
+46881.00   0.098585   0.216712  -0.2681613    0.101000    0.216000   -0.2676000
+46882.00   0.097540   0.216016  -0.2703756    0.100000    0.215000   -0.2698000
+46883.00   0.096745   0.215368  -0.2726712    0.099000    0.215000   -0.2722000
+46884.00   0.096120   0.214758  -0.2749188    0.098000    0.214000   -0.2745000
+46885.00   0.095597   0.214178  -0.2770051    0.097000    0.213000   -0.2766000
+46886.00   0.095139   0.213641  -0.2788608    0.096000    0.212000   -0.2785000
+46887.00   0.094713   0.213178  -0.2804693    0.095000    0.211000   -0.2801000
+46888.00   0.094270   0.212808  -0.2818591    0.094000    0.211000   -0.2815000
+46889.00   0.093722   0.212509  -0.2830897    0.093000    0.210000   -0.2828000
+46890.00   0.092988   0.212263  -0.2842360    0.092000    0.210000   -0.2839000
+46891.00   0.092064   0.212060  -0.2853731    0.091000    0.209000   -0.2850000
+46892.00   0.090975   0.211868  -0.2865731    0.090000    0.209000   -0.2862000
+46893.00   0.089743   0.211650  -0.2878977    0.089000    0.209000   -0.2875000
+46894.00   0.088394   0.211366  -0.2893924    0.088000    0.208000   -0.2890000
+46895.00   0.086971   0.210974  -0.2910801    0.087000    0.208000   -0.2907000
+46896.00   0.085500   0.210491  -0.2929587    0.086000    0.208000   -0.2926000
+46897.00   0.083991   0.209938  -0.2949955    0.085000    0.207000   -0.2946000
+46898.00   0.082464   0.209321  -0.2971198    0.084000    0.207000   -0.2968000
+46899.00   0.080935   0.208641  -0.2992297    0.083000    0.206000   -0.2989000
+46900.00   0.079424   0.207916  -0.3012155    0.082000    0.206000   -0.3009000
+46901.00   0.077952   0.207220  -0.3029897    0.081000    0.206000   -0.3027000
+46902.00   0.076542   0.206595  -0.3045084    0.080000    0.206000   -0.3043000
+46903.00   0.075219   0.206060  -0.3057977    0.078000    0.205000   -0.3055000
+46904.00   0.074010   0.205614  -0.3069486    0.077000    0.205000   -0.3067000
+46905.00   0.072932   0.205255  -0.3080894    0.076000    0.205000   -0.3079000
+46906.00   0.071990   0.204990  -0.3093493    0.075000    0.204000   -0.3092000
+46907.00   0.071179   0.204811  -0.3108178    0.074000    0.204000   -0.3107000
+46908.00   0.070473   0.204690  -0.3125279    0.073000    0.204000   -0.3125000
+46909.00   0.069810   0.204601  -0.3144718    0.072000    0.203000   -0.3145000
+46910.00   0.069116   0.204498  -0.3165887    0.071000    0.203000   -0.3166000
+46911.00   0.068329   0.204384  -0.3187598    0.070000    0.203000   -0.3187000
+46912.00   0.067396   0.204269  -0.3208546    0.069000    0.202000   -0.3207000
+46913.00   0.066290   0.204134  -0.3227685    0.068000    0.202000   -0.3225000
+46914.00   0.064990   0.203955  -0.3244426    0.067000    0.202000   -0.3241000
+46915.00   0.063489   0.203714  -0.3258673    0.066000    0.202000   -0.3254000
+46916.00   0.061855   0.203438  -0.3270799    0.064000    0.201000   -0.3265000
+46917.00   0.060205   0.203149  -0.3281429    0.063000    0.201000   -0.3275000
+46918.00   0.058669   0.202858  -0.3291293    0.062000    0.201000   -0.3284000
+46919.00   0.057350   0.202549  -0.3301078    0.060000    0.201000   -0.3293000
+46920.00   0.056318   0.202180  -0.3311396    0.059000    0.201000   -0.3304000
+46921.00   0.055534   0.201759  -0.3322852    0.058000    0.200000   -0.3316000
+46922.00   0.054880   0.201348  -0.3335849    0.056000    0.200000   -0.3330000
+46923.00   0.054226   0.201005  -0.3350588    0.055000    0.200000   -0.3346000
+46924.00   0.053433   0.200748  -0.3367160    0.054000    0.200000   -0.3363000
+46925.00   0.052428   0.200544  -0.3385294    0.052000    0.199000   -0.3382000
+46926.00   0.051219   0.200369  -0.3404133    0.051000    0.199000   -0.3401000
+46927.00   0.049840   0.200207  -0.3422469    0.049000    0.199000   -0.3420000
+46928.00   0.048329   0.200022  -0.3439092    0.048000    0.198000   -0.3437000
+46929.00   0.046729   0.199778  -0.3453195    0.047000    0.198000   -0.3451000
+46930.00   0.045091   0.199449  -0.3464683    0.045000    0.198000   -0.3462000
+46931.00   0.043468   0.199072  -0.3474324    0.043000    0.197000   -0.3472000
+46932.00   0.041909   0.198704  -0.3483486    0.042000    0.197000   -0.3482000
+46933.00   0.040463   0.198405  -0.3493633    0.041000    0.197000   -0.3492000
+46934.00   0.039181   0.198239  -0.3505857    0.039000    0.197000   -0.3505000
+46935.00   0.038100   0.198265  -0.3520593    0.038000    0.196000   -0.3520000
+46936.00   0.037168   0.198481  -0.3537602    0.037000    0.196000   -0.3538000
+46937.00   0.036280   0.198815  -0.3556124    0.036000    0.196000   -0.3557000
+46938.00   0.035329   0.199181  -0.3575135    0.035000    0.196000   -0.3576000
+46939.00   0.034223   0.199476  -0.3593644    0.034000    0.195000   -0.3594000
+46940.00   0.032936   0.199579  -0.3610880    0.034000    0.195000   -0.3611000
+46941.00   0.031586   0.199492  -0.3626238    0.033000    0.195000   -0.3625000
+46942.00   0.030268   0.199271  -0.3639418    0.032000    0.195000   -0.3637000
+46943.00   0.029042   0.198973  -0.3650490    0.031000    0.195000   -0.3647000
+46944.00   0.027961   0.198658  -0.3659816    0.030000    0.195000   -0.3655000
+46945.00   0.027069   0.198384  -0.3667955    0.030000    0.195000   -0.3663000
+46946.00   0.026356   0.198192  -0.3675670    0.029000    0.195000   -0.3670000
+46947.00   0.025775   0.198083  -0.3683667    0.029000    0.195000   -0.3678000
+46948.00   0.025279   0.198053  -0.3692478    0.028000    0.195000   -0.3687000
+46949.00   0.024820   0.198093  -0.3702416    0.027000    0.195000   -0.3698000
+46950.00   0.024353   0.198199  -0.3713598    0.027000    0.195000   -0.3711000
+46951.00   0.023855   0.198360  -0.3726176    0.026000    0.195000   -0.3726000
+46952.00   0.023324   0.198545  -0.3740154    0.025000    0.196000   -0.3742000
+46953.00   0.022759   0.198715  -0.3755227    0.025000    0.196000   -0.3759000
+46954.00   0.022130   0.198843  -0.3770620    0.024000    0.196000   -0.3775000
+46955.00   0.021384   0.198929  -0.3785134    0.023000    0.197000   -0.3790000
+46956.00   0.020463   0.198976  -0.3797706    0.022000    0.197000   -0.3802000
+46957.00   0.019334   0.198993  -0.3807825    0.021000    0.198000   -0.3812000
+46958.00   0.018054   0.199008  -0.3815793    0.020000    0.198000   -0.3819000
+46959.00   0.016708   0.199060  -0.3822681    0.019000    0.199000   -0.3826000
+46960.00   0.015382   0.199185  -0.3829938    0.018000    0.199000   -0.3833000
+46961.00   0.014115   0.199396  -0.3838894    0.017000    0.200000   -0.3842000
+46962.00   0.012925   0.199696  -0.3850249    0.016000    0.200000   -0.3853000
+46963.00   0.011828   0.200086  -0.3863871    0.014000    0.201000   -0.3867000
+46964.00   0.010807   0.200548  -0.3878939    0.013000    0.201000   -0.3883000
+46965.00   0.009827   0.201057  -0.3894316    0.012000    0.202000   -0.3898000
+46966.00   0.008835   0.201586  -0.3908886    0.011000    0.202000   -0.3912000
+46967.00   0.007817   0.202110  -0.3921712    0.010000    0.203000   -0.3925000
+46968.00   0.006773   0.202608  -0.3932229    0.008000    0.203000   -0.3935000
+46969.00   0.005702   0.203054  -0.3940250    0.007000    0.204000   -0.3942000
+46970.00   0.004581   0.203435  -0.3945922    0.006000    0.205000   -0.3948000
+46971.00   0.003328   0.203807  -0.3949640    0.005000    0.205000   -0.3951000
+46972.00   0.001879   0.204234  -0.3952013    0.003000    0.206000   -0.3954000
+46973.00   0.000318   0.204697  -0.3953915    0.002000    0.206000   -0.3956000
+46974.00  -0.001239   0.205162  -0.3956235    0.001000    0.207000   -0.3959000
+46975.00  -0.002680   0.205607  -0.3959716    0.000000    0.207000   -0.3963000
+46976.00  -0.003968   0.206069  -0.3964826   -0.002000    0.208000   -0.3969000
+46977.00  -0.005103   0.206556  -0.3971767   -0.003000    0.209000   -0.3976000
+46978.00  -0.006110   0.207053  -0.3980465   -0.004000    0.209000   -0.3985000
+46979.00  -0.007044   0.207548  -0.3990551   -0.005000    0.210000   -0.3996000
+46980.00  -0.007966   0.208033  -0.4001420   -0.007000    0.210000   -0.4006000
+46981.00  -0.008911   0.208509  -0.4012269   -0.008000    0.211000   -0.4017000
+46982.00  -0.009909   0.208988  -0.4022166   -0.009000    0.211000   -0.4026000
+46983.00  -0.010986   0.209478  -0.4030268   -0.010000    0.212000   -0.4034000
+46984.00  -0.012169   0.209989  -0.4036106   -0.012000    0.213000   -0.4039000
+46985.00  -0.013472   0.210517  -0.4039816   -0.013000    0.213000   -0.4042000
+46986.00  -0.014873   0.211044  -0.4042189   -0.014000    0.214000   -0.4044000
+46987.00  -0.016356   0.211553  -0.4044596   -0.016000    0.215000   -0.4046000
+46988.00  -0.017869   0.212064  -0.4048559   -0.017000    0.216000   -0.4050000
+46989.00  -0.019344   0.212606  -0.4055222   -0.018000    0.216000   -0.4057000
+46990.00  -0.020705   0.213196  -0.4064820   -0.019000    0.217000   -0.4066000
+46991.00  -0.021913   0.213841  -0.4076496   -0.020000    0.218000   -0.4078000
+46992.00  -0.022946   0.214544  -0.4088811   -0.021000    0.219000   -0.4090000
+46993.00  -0.023784   0.215306  -0.4100321   -0.022000    0.219000   -0.4101000
+46994.00  -0.024434   0.216111  -0.4109970   -0.023000    0.220000   -0.4111000
+46995.00  -0.024929   0.216938  -0.4117266   -0.023000    0.221000   -0.4118000
+46996.00  -0.025340   0.217783  -0.4122057   -0.024000    0.222000   -0.4123000
+46997.00  -0.025680   0.218647  -0.4124557   -0.024000    0.222000   -0.4126000
+46998.00  -0.025937   0.219537  -0.4125270   -0.025000    0.223000   -0.4126000
+46999.00  -0.026102   0.220452  -0.4124929   -0.025000    0.224000   -0.4126000
+47000.00  -0.026180   0.221376  -0.4124338   -0.025000    0.225000   -0.4125000
+47001.00  -0.026210   0.222271  -0.4124291   -0.025000    0.226000   -0.4125000
+47002.00  -0.026216   0.223132  -0.4125424   -0.026000    0.226000   -0.4126000
+47003.00  -0.026225   0.223964  -0.4128161   -0.026000    0.227000   -0.4129000
+47004.00  -0.026262   0.224772  -0.4132713   -0.026000    0.228000   -0.4133000
+47005.00  -0.026357   0.225559  -0.4139051   -0.026000    0.229000   -0.4140000
+47006.00  -0.026538   0.226339  -0.4146832   -0.026000    0.230000   -0.4148000
+47007.00  -0.026828   0.227130  -0.4155480   -0.027000    0.230000   -0.4156000
+47008.00  -0.027249   0.227951  -0.4164262   -0.027000    0.231000   -0.4165000
+47009.00  -0.027824   0.228830  -0.4172396   -0.027000    0.232000   -0.4174000
+47010.00  -0.028553   0.229784  -0.4179193   -0.028000    0.233000   -0.4181000
+47011.00  -0.029366   0.230769  -0.4184132   -0.028000    0.234000   -0.4186000
+47012.00  -0.030185   0.231733  -0.4187114   -0.028000    0.234000   -0.4189000
+47013.00  -0.030950   0.232651  -0.4188688   -0.029000    0.235000   -0.4191000
+47014.00  -0.031605   0.233510  -0.4190079   -0.030000    0.236000   -0.4193000
+47015.00  -0.032125   0.234318  -0.4192911   -0.030000    0.237000   -0.4195000
+47016.00  -0.032557   0.235103  -0.4198449   -0.030000    0.238000   -0.4200000
+47017.00  -0.032972   0.235882  -0.4207195   -0.031000    0.239000   -0.4209000
+47018.00  -0.033433   0.236668  -0.4218732   -0.032000    0.239000   -0.4221000
+47019.00  -0.033981   0.237483  -0.4231936   -0.032000    0.240000   -0.4234000
+47020.00  -0.034635   0.238350  -0.4245314   -0.032000    0.241000   -0.4248000
+47021.00  -0.035353   0.239274  -0.4257428   -0.033000    0.242000   -0.4261000
+47022.00  -0.036075   0.240246  -0.4267350   -0.034000    0.243000   -0.4271000
+47023.00  -0.036740   0.241261  -0.4274817   -0.034000    0.244000   -0.4279000
+47024.00  -0.037298   0.242313  -0.4280123   -0.034000    0.245000   -0.4284000
+47025.00  -0.037712   0.243403  -0.4283918   -0.035000    0.246000   -0.4288000
+47026.00  -0.038015   0.244553  -0.4286951   -0.035000    0.247000   -0.4291000
+47027.00  -0.038232   0.245777  -0.4289996   -0.035000    0.248000   -0.4293000
+47028.00  -0.038367   0.247084  -0.4293826   -0.036000    0.249000   -0.4297000
+47029.00  -0.038417   0.248479  -0.4299181   -0.036000    0.250000   -0.4301000
+47030.00  -0.038349   0.249945  -0.4306659   -0.036000    0.251000   -0.4308000
+47031.00  -0.038177   0.251444  -0.4316518   -0.036000    0.252000   -0.4317000
+47032.00  -0.037996   0.252925  -0.4328582   -0.036000    0.253000   -0.4327000
+47033.00  -0.037882   0.254343  -0.4342427   -0.036000    0.254000   -0.4340000
+47034.00  -0.037847   0.255669  -0.4357424   -0.036000    0.256000   -0.4354000
+47035.00  -0.037895   0.256887  -0.4372807   -0.037000    0.257000   -0.4369000
+47036.00  -0.038023   0.258032  -0.4387741   -0.037000    0.258000   -0.4383000
+47037.00  -0.038225   0.259111  -0.4401286   -0.037000    0.259000   -0.4395000
+47038.00  -0.038498   0.260125  -0.4412756   -0.037000    0.260000   -0.4406000
+47039.00  -0.038840   0.261097  -0.4421910   -0.037000    0.261000   -0.4415000
+47040.00  -0.039245   0.262047  -0.4429115   -0.037000    0.262000   -0.4423000
+47041.00  -0.039685   0.262965  -0.4435399   -0.038000    0.263000   -0.4430000
+47042.00  -0.040124   0.263832  -0.4442230   -0.038000    0.264000   -0.4437000
+47043.00  -0.040523   0.264630  -0.4451130   -0.038000    0.265000   -0.4447000
+47044.00  -0.040855   0.265354  -0.4463229   -0.039000    0.266000   -0.4460000
+47045.00  -0.041118   0.266020  -0.4478847   -0.039000    0.267000   -0.4476000
+47046.00  -0.041363   0.266679  -0.4497182   -0.040000    0.268000   -0.4495000
+47047.00  -0.041653   0.267387  -0.4516703   -0.040000    0.269000   -0.4514000
+47048.00  -0.042021   0.268187  -0.4535705   -0.040000    0.270000   -0.4534000
+47049.00  -0.042457   0.269114  -0.4552813   -0.041000    0.271000   -0.4551000
+47050.00  -0.042953   0.270192  -0.4567302   -0.041000    0.272000   -0.4565000
+47051.00  -0.043493   0.271416  -0.4579047   -0.042000    0.273000   -0.4577000
+47052.00  -0.044063   0.272731  -0.4588415   -0.042000    0.274000   -0.4587000
+47053.00  -0.044648   0.274073  -0.4596119   -0.043000    0.275000   -0.4595000
+47054.00  -0.045227   0.275365  -0.4603080   -0.043000    0.276000   -0.4603000
+47055.00  -0.045787   0.276532  -0.4610335   -0.044000    0.277000   -0.4611000
+47056.00  -0.046373   0.277570  -0.4618809   -0.045000    0.278000   -0.4620000
+47057.00  -0.046997   0.278534  -0.4629139   -0.045000    0.279000   -0.4631000
+47058.00  -0.047655   0.279488  -0.4641732   -0.046000    0.280000   -0.4644000
+47059.00  -0.048324   0.280493  -0.4656749   -0.046000    0.281000   -0.4659000
+47060.00  -0.048973   0.281599  -0.4674083   -0.047000    0.282000   -0.4676000
+47061.00  -0.049614   0.282841  -0.4693152   -0.048000    0.284000   -0.4694000
+47062.00  -0.050272   0.284240  -0.4713061   -0.048000    0.285000   -0.4714000
+47063.00  -0.050944   0.285787  -0.4732788   -0.049000    0.286000   -0.4732000
+47064.00  -0.051614   0.287435  -0.4751360   -0.050000    0.288000   -0.4750000
+47065.00  -0.052266   0.289135  -0.4768015   -0.050000    0.289000   -0.4765000
+47066.00  -0.052910   0.290855  -0.4782346   -0.051000    0.291000   -0.4779000
+47067.00  -0.053555   0.292544  -0.4794534   -0.052000    0.292000   -0.4791000
+47068.00  -0.054200   0.294149  -0.4805379   -0.052000    0.294000   -0.4802000
+47069.00  -0.054800   0.295654  -0.4816162   -0.053000    0.295000   -0.4813000
+47070.00  -0.055299   0.297063  -0.4828365   -0.054000    0.296000   -0.4826000
+47071.00  -0.055709   0.298407  -0.4843190   -0.055000    0.298000   -0.4842000
+47072.00  -0.056069   0.299702  -0.4861217   -0.055000    0.299000   -0.4861000
+47073.00  -0.056419   0.300959  -0.4882227   -0.056000    0.300000   -0.4883000
+47074.00  -0.056798   0.302186  -0.4905233   -0.056000    0.302000   -0.4906000
+47075.00  -0.057215   0.303393  -0.4928758   -0.057000    0.303000   -0.4930000
+47076.00  -0.057662   0.304588  -0.4951190   -0.058000    0.304000   -0.4952000
+47077.00  -0.058140   0.305779  -0.4971304   -0.058000    0.305000   -0.4971000
+47078.00  -0.058658   0.306976  -0.4988550   -0.059000    0.307000   -0.4988000
+47079.00  -0.059234   0.308184  -0.5003025   -0.059000    0.308000   -0.5002000
+47080.00  -0.059879   0.309408  -0.5015304   -0.060000    0.309000   -0.5014000
+47081.00  -0.060578   0.310627  -0.5026280   -0.060000    0.310000   -0.5025000
+47082.00  -0.061318   0.311812  -0.5036915   -0.060000    0.311000   -0.5035000
+47083.00  -0.062070   0.312940  -0.5048089   -0.061000    0.313000   -0.5046000
+47084.00  -0.062740   0.314034  -0.5060519   -0.061000    0.314000   -0.5059000
+47085.00  -0.063223   0.315126  -0.5074719   -0.062000    0.315000   -0.5073000
+47086.00  -0.063481   0.316244  -0.5090887   -0.062000    0.316000   -0.5089000
+47087.00  -0.063542   0.317388  -0.5108898   -0.062000    0.317000   -0.5107000
+47088.00  -0.063443   0.318552  -0.5128381   -0.062000    0.318000   -0.5127000
+47089.00  -0.063229   0.319720  -0.5148723   -0.062000    0.319000   -0.5147000
+47090.00  -0.062982   0.320871  -0.5169156   -0.063000    0.320000   -0.5168000
+47091.00  -0.062783   0.322005  -0.5188895   -0.063000    0.321000   -0.5187000
+47092.00  -0.062657   0.323114  -0.5207186   -0.063000    0.322000   -0.5205000
+47093.00  -0.062589   0.324213  -0.5223417   -0.063000    0.323000   -0.5220000
+47094.00  -0.062553   0.325320  -0.5237487   -0.063000    0.325000   -0.5234000
+47095.00  -0.062531   0.326452  -0.5249939   -0.063000    0.326000   -0.5246000
+47096.00  -0.062507   0.327621  -0.5261949   -0.063000    0.327000   -0.5257000
+47097.00  -0.062459   0.328833  -0.5274888   -0.063000    0.328000   -0.5271000
+47098.00  -0.062370   0.330089  -0.5289897   -0.063000    0.329000   -0.5286000
+47099.00  -0.062261   0.331385  -0.5307583   -0.063000    0.331000   -0.5304000
+47100.00  -0.062173   0.332711  -0.5327890   -0.062000    0.332000   -0.5325000
+47101.00  -0.062171   0.334055  -0.5350140   -0.062000    0.333000   -0.5348000
+47102.00  -0.062204   0.335394  -0.5373157   -0.062000    0.335000   -0.5372000
+47103.00  -0.062184   0.336699  -0.5395601   -0.062000    0.336000   -0.5394000
+47104.00  -0.062019   0.337962  -0.5416347   -0.061000    0.337000   -0.5415000
+47105.00  -0.061613   0.339246  -0.5434731   -0.061000    0.339000   -0.5434000
+47106.00  -0.060956   0.340659  -0.5450545   -0.060000    0.340000   -0.5450000
+47107.00  -0.060130   0.342210  -0.5464189   -0.060000    0.342000   -0.5463000
+47108.00  -0.059246   0.343883  -0.5476474   -0.060000    0.343000   -0.5476000
+47109.00  -0.058418   0.345665  -0.5488370   -0.059000    0.345000   -0.5487000
+47110.00  -0.057743   0.347539  -0.5500785   -0.059000    0.346000   -0.5500000
+47111.00  -0.057237   0.349460  -0.5514459   -0.059000    0.348000   -0.5513000
+47112.00  -0.056859   0.351377  -0.5529858   -0.058000    0.350000   -0.5528000
+47113.00  -0.056557   0.353241  -0.5547122   -0.058000    0.351000   -0.5545000
+47114.00  -0.056266   0.355008  -0.5566074   -0.058000    0.353000   -0.5564000
+47115.00  -0.055923   0.356643  -0.5586307   -0.057000    0.355000   -0.5584000
+47116.00  -0.055519   0.358163  -0.5607359   -0.057000    0.356000   -0.5605000
+47117.00  -0.055096   0.359613  -0.5628610   -0.056000    0.358000   -0.5627000
+47118.00  -0.054714   0.361041  -0.5649276   -0.056000    0.360000   -0.5648000
+47119.00  -0.054428   0.362491  -0.5668549   -0.056000    0.362000   -0.5667000
+47120.00  -0.054270   0.363988  -0.5685829   -0.056000    0.363000   -0.5685000
+47121.00  -0.054283   0.365542  -0.5700928   -0.056000    0.365000   -0.5700000
+47122.00  -0.054500   0.367150  -0.5714266   -0.056000    0.366000   -0.5713000
+47123.00  -0.054941   0.368800  -0.5726827   -0.056000    0.368000   -0.5726000
+47124.00  -0.055621   0.370474  -0.5739870   -0.057000    0.369000   -0.5740000
+47125.00  -0.056525   0.372135  -0.5754571   -0.057000    0.371000   -0.5756000
+47126.00  -0.057559   0.373744  -0.5771728   -0.057000    0.373000   -0.5774000
+47127.00  -0.058610   0.375255  -0.5791443   -0.058000    0.374000   -0.5795000
+47128.00  -0.059560   0.376646  -0.5813132   -0.058000    0.375000   -0.5817000
+47129.00  -0.060283   0.377940  -0.5835738   -0.058000    0.377000   -0.5840000
+47130.00  -0.060669   0.379173  -0.5857988   -0.058000    0.378000   -0.5863000
+47131.00  -0.060705   0.380381  -0.5878707   -0.058000    0.379000   -0.5884000
+47132.00  -0.060455   0.381576  -0.5897125   -0.058000    0.380000   -0.5903000
+47133.00  -0.059990   0.382762  -0.5912961   -0.057000    0.382000   -0.5918000
+47134.00  -0.059370   0.383937  -0.5926399   -0.057000    0.383000   -0.5931000
+47135.00  -0.058644   0.385103  -0.5937993   -0.056000    0.385000   -0.5942000
+47136.00  -0.057828   0.386266  -0.5948576   -0.056000    0.386000   -0.5952000
+47137.00  -0.056931   0.387435  -0.5959009   -0.055000    0.387000   -0.5962000
+47138.00  -0.055941   0.388625  -0.5970021   -0.054000    0.389000   -0.5972000
+47139.00  -0.054829   0.389872  -0.5982189   -0.053000    0.390000   -0.5985000
+47140.00  -0.053586   0.391201  -0.5995910   -0.052000    0.391000   -0.5998000
+47141.00  -0.052243   0.392604  -0.6011298   -0.051000    0.393000   -0.6013000
+47142.00  -0.050835   0.394060  -0.6028227   -0.050000    0.394000   -0.6030000
+47143.00  -0.049410   0.395542  -0.6046343   -0.049000    0.395000   -0.6048000
+47144.00  -0.048052   0.396989  -0.6065087   -0.048000    0.396000   -0.6067000
+47145.00  -0.046844   0.398339  -0.6083731   -0.047000    0.397000   -0.6086000
+47146.00  -0.045784   0.399552  -0.6101502   -0.045000    0.399000   -0.6104000
+47147.00  -0.044816   0.400625  -0.6117713   -0.044000    0.400000   -0.6120000
+47148.00  -0.043878   0.401565  -0.6132009   -0.043000    0.401000   -0.6135000
+47149.00  -0.042903   0.402385  -0.6144610   -0.042000    0.402000   -0.6147000
+47150.00  -0.041828   0.403123  -0.6156405   -0.040000    0.403000   -0.6159000
+47151.00  -0.040607   0.403827  -0.6168739   -0.039000    0.404000   -0.6170000
+47152.00  -0.039281   0.404537  -0.6182946   -0.038000    0.405000   -0.6184000
+47153.00  -0.037899   0.405269  -0.6199903   -0.036000    0.406000   -0.6201000
+47154.00  -0.036458   0.406039  -0.6219738   -0.035000    0.407000   -0.6221000
+47155.00  -0.034936   0.406865  -0.6241775   -0.033000    0.408000   -0.6243000
+47156.00  -0.033335   0.407754  -0.6264776   -0.032000    0.409000   -0.6266000
+47157.00  -0.031657   0.408711  -0.6287351   -0.030000    0.410000   -0.6288000
+47158.00  -0.029907   0.409744  -0.6308325   -0.028000    0.411000   -0.6309000
+47159.00  -0.028088   0.410856  -0.6326933   -0.027000    0.412000   -0.6327000
+47160.00  -0.026206   0.412048  -0.6342906   -0.025000    0.413000   -0.6343000
+47161.00  -0.024282   0.413287   0.3643500   -0.023000    0.414000    0.3643000
+47162.00  -0.022333   0.414528   0.3631681   -0.021000    0.415000    0.3631000
+47163.00  -0.020379   0.415724   0.3620846   -0.019000    0.416000    0.3621000
+47164.00  -0.018437   0.416831   0.3610156   -0.017000    0.417000    0.3610000
+47165.00  -0.016529   0.417809   0.3598894   -0.015000    0.418000    0.3598000
+47166.00  -0.014674   0.418643   0.3586506   -0.013000    0.419000    0.3586000
+47167.00  -0.012861   0.419338   0.3572612   -0.011000    0.420000    0.3571000
+47168.00  -0.011080   0.419907   0.3557089   -0.010000    0.421000    0.3555000
+47169.00  -0.009315   0.420360   0.3540054   -0.008000    0.422000    0.3537000
+47170.00  -0.007555   0.420728   0.3521806   -0.006000    0.423000    0.3519000
+47171.00  -0.005836   0.421099   0.3502919   -0.004000    0.423000    0.3500000
+47172.00  -0.004197   0.421557   0.3484143   -0.003000    0.424000    0.3481000
+47173.00  -0.002659   0.422118   0.3466188   -0.001000    0.425000    0.3464000
+47174.00  -0.001282   0.422756   0.3449689    0.000000    0.425000    0.3447000
+47175.00  -0.000119   0.423392   0.3435070    0.002000    0.426000    0.3434000
+47176.00   0.000915   0.423966   0.3422443    0.003000    0.426000    0.3422000
+47177.00   0.001971   0.424454   0.3411366    0.005000    0.427000    0.3412000
+47178.00   0.003149   0.424857   0.3400813    0.006000    0.427000    0.3403000
+47179.00   0.004431   0.425192   0.3389456    0.008000    0.428000    0.3392000
+47180.00   0.005795   0.425472   0.3376186    0.009000    0.428000    0.3379000
+47181.00   0.007263   0.425747   0.3360472    0.011000    0.429000    0.3363000
+47182.00   0.008856   0.426060   0.3342621    0.012000    0.429000    0.3344000
+47183.00   0.010591   0.426454   0.3323757    0.014000    0.430000    0.3324000
+47184.00   0.012479   0.426949   0.3305363    0.016000    0.430000    0.3305000
+47185.00   0.014531   0.427485   0.3288699    0.018000    0.431000    0.3287000
+47186.00   0.016729   0.428019   0.3274564    0.020000    0.431000    0.3272000
+47187.00   0.019043   0.428523   0.3263147    0.022000    0.431000    0.3260000
+47188.00   0.021473   0.428978   0.3254055    0.024000    0.432000    0.3250000
+47189.00   0.024050   0.429387   0.3246553    0.027000    0.432000    0.3242000
+47190.00   0.026750   0.429743   0.3239802    0.029000    0.433000    0.3235000
+47191.00   0.029541   0.430052   0.3232923    0.031000    0.433000    0.3227000
+47192.00   0.032380   0.430341   0.3225081    0.033000    0.433000    0.3220000
+47193.00   0.035225   0.430638   0.3215594    0.036000    0.434000    0.3210000
+47194.00   0.038029   0.430972   0.3204005    0.038000    0.434000    0.3199000
+47195.00   0.040717   0.431369   0.3190133    0.041000    0.435000    0.3185000
+47196.00   0.043197   0.431846   0.3174101    0.044000    0.435000    0.3169000
+47197.00   0.045436   0.432383   0.3156276    0.046000    0.435000    0.3152000
+47198.00   0.047417   0.432934   0.3137210    0.049000    0.435000    0.3133000
+47199.00   0.049127   0.433448   0.3117564    0.051000    0.435000    0.3114000
+47200.00   0.050562   0.433883   0.3098046    0.053000    0.435000    0.3095000
+47201.00   0.051772   0.434212   0.3079399    0.054000    0.435000    0.3077000
+47202.00   0.052828   0.434415   0.3062239    0.056000    0.435000    0.3061000
+47203.00   0.053789   0.434472   0.3046859    0.057000    0.435000    0.3046000
+47204.00   0.054660   0.434371   0.3033032    0.058000    0.434000    0.3033000
+47205.00   0.055477   0.434080   0.3019846    0.059000    0.434000    0.3019000
+47206.00   0.056309   0.433626   0.3005816    0.060000    0.434000    0.3005000
+47207.00   0.057220   0.433069   0.2989343    0.061000    0.434000    0.2988000
+47208.00   0.058272   0.432465   0.2969319    0.062000    0.433000    0.2967000
+47209.00   0.059504   0.431860   0.2945576    0.063000    0.433000    0.2943000
+47210.00   0.060894   0.431273   0.2919006    0.064000    0.433000    0.2916000
+47211.00   0.062344   0.430743   0.2891320    0.065000    0.433000    0.2889000
+47212.00   0.063722   0.430316   0.2864434    0.066000    0.432000    0.2862000
+47213.00   0.064928   0.430027   0.2839871    0.067000    0.432000    0.2838000
+47214.00   0.065945   0.429861   0.2818466    0.068000    0.432000    0.2817000
+47215.00   0.066799   0.429796   0.2800276    0.069000    0.432000    0.2798000
+47216.00   0.067596   0.429844   0.2784642    0.071000    0.432000    0.2782000
+47217.00   0.068476   0.429993   0.2770556    0.072000    0.432000    0.2768000
+47218.00   0.069557   0.430227   0.2756960    0.073000    0.431000    0.2754000
+47219.00   0.070903   0.430544   0.2742860    0.075000    0.431000    0.2739000
+47220.00   0.072553   0.430941   0.2727442    0.076000    0.432000    0.2724000
+47221.00   0.074468   0.431406   0.2710225    0.078000    0.432000    0.2707000
+47222.00   0.076565   0.431907   0.2691009    0.080000    0.432000    0.2688000
+47223.00   0.078739   0.432401   0.2669896    0.082000    0.432000    0.2667000
+47224.00   0.080892   0.432834   0.2647288    0.084000    0.432000    0.2646000
+47225.00   0.082956   0.433137   0.2623834    0.086000    0.432000    0.2624000
+47226.00   0.084978   0.433274   0.2600346    0.088000    0.432000    0.2602000
+47227.00   0.087034   0.433225   0.2577686    0.090000    0.432000    0.2581000
+47228.00   0.089182   0.432984   0.2556665    0.092000    0.432000    0.2562000
+47229.00   0.091479   0.432548   0.2537920    0.095000    0.432000    0.2544000
+47230.00   0.093968   0.431925   0.2521810    0.097000    0.432000    0.2530000
+47231.00   0.096616   0.431178   0.2508327    0.100000    0.431000    0.2516000
+47232.00   0.099373   0.430378   0.2496800    0.102000    0.431000    0.2505000
+47233.00   0.102178   0.429573   0.2485988    0.104000    0.430000    0.2493000
+47234.00   0.104954   0.428784   0.2474383    0.107000    0.429000    0.2480000
+47235.00   0.107628   0.428032   0.2460608    0.109000    0.428000    0.2465000
+47236.00   0.110146   0.427325   0.2443810    0.112000    0.428000    0.2446000
+47237.00   0.112463   0.426598   0.2424056    0.114000    0.427000    0.2424000
+47238.00   0.114535   0.425771   0.2402340    0.116000    0.425000    0.2401000
+47239.00   0.116348   0.424764   0.2380222    0.118000    0.424000    0.2378000
+47240.00   0.117957   0.423510   0.2359328    0.120000    0.423000    0.2356000
+47241.00   0.119427   0.422058   0.2340876    0.122000    0.422000    0.2338000
+47242.00   0.120827   0.420480   0.2325317    0.123000    0.420000    0.2322000
+47243.00   0.122229   0.418839   0.2312297    0.125000    0.419000    0.2309000
+47244.00   0.123705   0.417199   0.2300952    0.126000    0.418000    0.2298000
+47245.00   0.125305   0.415613   0.2290276    0.128000    0.417000    0.2287000
+47246.00   0.126960   0.414115   0.2279249    0.129000    0.415000    0.2276000
+47247.00   0.128550   0.412734   0.2267026    0.130000    0.414000    0.2264000
+47248.00   0.129982   0.411461   0.2252995    0.131000    0.413000    0.2250000
+47249.00   0.131179   0.410263   0.2236844    0.132000    0.412000    0.2233000
+47250.00   0.132077   0.409106   0.2218552    0.133000    0.410000    0.2215000
+47251.00   0.132689   0.407969   0.2198328    0.134000    0.409000    0.2195000
+47252.00   0.133060   0.406819   0.2176635    0.134000    0.407000    0.2173000
+47253.00   0.133242   0.405621   0.2154137    0.135000    0.406000    0.2151000
+47254.00   0.133291   0.404331   0.2131608    0.136000    0.405000    0.2128000
+47255.00   0.133276   0.402927   0.2109864    0.136000    0.403000    0.2107000
+47256.00   0.133296   0.401435   0.2089597    0.137000    0.402000    0.2087000
+47257.00   0.133451   0.399885   0.2071178    0.137000    0.400000    0.2069000
+47258.00   0.133796   0.398302   0.2054537    0.138000    0.399000    0.2052000
+47259.00   0.134366   0.396706   0.2039126    0.138000    0.397000    0.2037000
+47260.00   0.135164   0.395107   0.2023987    0.139000    0.396000    0.2021000
+47261.00   0.136105   0.393495   0.2007934    0.140000    0.394000    0.2005000
+47262.00   0.137096   0.391851   0.1989811    0.141000    0.392000    0.1987000
+47263.00   0.138122   0.390169   0.1968751    0.142000    0.391000    0.1965000
+47264.00   0.139252   0.388462   0.1944597    0.143000    0.389000    0.1941000
+47265.00   0.140573   0.386753   0.1918060    0.144000    0.388000    0.1914000
+47266.00   0.142124   0.385078   0.1890631    0.146000    0.386000    0.1887000
+47267.00   0.143839   0.383464   0.1864171    0.147000    0.385000    0.1862000
+47268.00   0.145638   0.381931   0.1840284    0.148000    0.383000    0.1838000
+47269.00   0.147446   0.380503   0.1819888    0.150000    0.382000    0.1818000
+47270.00   0.149227   0.379205   0.1803083    0.151000    0.381000    0.1802000
+47271.00   0.150923   0.378018   0.1789243    0.153000    0.379000    0.1788000
+47272.00   0.152480   0.376907   0.1777309    0.154000    0.378000    0.1776000
+47273.00   0.153883   0.375832   0.1766178    0.156000    0.377000    0.1764000
+47274.00   0.155182   0.374728   0.1754892    0.157000    0.374000    0.1751000
+47275.00   0.156463   0.373523   0.1742706    0.159000    0.373000    0.1738000
+47276.00   0.157752   0.372218   0.1729094    0.160000    0.372000    0.1724000
+47277.00   0.159044   0.370851   0.1713784    0.162000    0.370000    0.1708000
+47278.00   0.160340   0.369461   0.1696762    0.163000    0.369000    0.1690000
+47279.00   0.161671   0.368081   0.1678264    0.165000    0.368000    0.1671000
+47280.00   0.163064   0.366725   0.1658776    0.166000    0.367000    0.1652000
+47281.00   0.164477   0.365389   0.1639065    0.167000    0.366000    0.1633000
+47282.00   0.165855   0.364063   0.1620006    0.169000    0.364000    0.1614000
+47283.00   0.167147   0.362735   0.1602385    0.170000    0.363000    0.1597000
+47284.00   0.168285   0.361394   0.1586712    0.171000    0.363000    0.1582000
+47285.00   0.169162   0.360021   0.1573034    0.172000    0.362000    0.1569000
+47286.00   0.169788   0.358587   0.1560843    0.173000    0.360000    0.1557000
+47287.00   0.170224   0.357071   0.1549187    0.173000    0.359000    0.1545000
+47288.00   0.170572   0.355490   0.1536860    0.174000    0.357000    0.1533000
+47289.00   0.170939   0.353873   0.1522705    0.174000    0.355000    0.1519000
+47290.00   0.171422   0.352246   0.1505918    0.175000    0.354000    0.1502000
+47291.00   0.172031   0.350624   0.1486276    0.176000    0.352000    0.1482000
+47292.00   0.172740   0.349018   0.1464257    0.176000    0.351000    0.1460000
+47293.00   0.173522   0.347441   0.1440946    0.177000    0.349000    0.1436000
+47294.00   0.174315   0.345886   0.1417745    0.177000    0.347000    0.1413000
+47295.00   0.175061   0.344342   0.1396002    0.178000    0.346000    0.1392000
+47296.00   0.175731   0.342790   0.1376748    0.178000    0.344000    0.1373000
+47297.00   0.176269   0.341207   0.1360396    0.178000    0.342000    0.1357000
+47298.00   0.176616   0.339565   0.1346682    0.179000    0.340000    0.1345000
+47299.00   0.176737   0.337839   0.1334901    0.179000    0.339000    0.1333000
+47300.00   0.176689   0.336003   0.1324249    0.179000    0.337000    0.1323000
+47301.00   0.176571   0.334072   0.1313853    0.179000    0.335000    0.1313000
+47302.00   0.176472   0.332078   0.1302903    0.179000    0.333000    0.1301000
+47303.00   0.176453   0.330055   0.1290823    0.179000    0.331000    0.1288000
+47304.00   0.176504   0.328048   0.1277310    0.178000    0.330000    0.1274000
+47305.00   0.176508   0.326097   0.1262273    0.178000    0.328000    0.1258000
+47306.00   0.176371   0.324224   0.1245896    0.177000    0.326000    0.1241000
+47307.00   0.176036   0.322405   0.1228631    0.177000    0.324000    0.1224000
+47308.00   0.175458   0.320609   0.1211064    0.176000    0.323000    0.1206000
+47309.00   0.174650   0.318806   0.1193840    0.176000    0.321000    0.1189000
+47310.00   0.173647   0.316974   0.1177611    0.175000    0.319000    0.1174000
+47311.00   0.172508   0.315109   0.1163064    0.174000    0.317000    0.1161000
+47312.00   0.171313   0.313217   0.1150594    0.174000    0.315000    0.1149000
+47313.00   0.170143   0.311304   0.1140094    0.173000    0.313000    0.1140000
+47314.00   0.169074   0.309379   0.1130943    0.172000    0.311000    0.1132000
+47315.00   0.168160   0.307456   0.1122126    0.171000    0.309000    0.1122000
+47316.00   0.167385   0.305554   0.1112338    0.170000    0.307000    0.1112000
+47317.00   0.166735   0.303687   0.1100538    0.170000    0.304000    0.1099000
+47318.00   0.166213   0.301859   0.1086331    0.169000    0.302000    0.1083000
+47319.00   0.165809   0.300064   0.1070061    0.168000    0.300000    0.1066000
+47320.00   0.165500   0.298286   0.1052785    0.168000    0.298000    0.1048000
+47321.00   0.165260   0.296515   0.1035866    0.168000    0.296000    0.1030000
+47322.00   0.165075   0.294741   0.1020572    0.168000    0.294000    0.1015000
+47323.00   0.164939   0.292954   0.1007806    0.167000    0.292000    0.1002000
+47324.00   0.164891   0.291145   0.0997917    0.167000    0.290000    0.0992000
+47325.00   0.164964   0.289308   0.0990674    0.167000    0.289000    0.0985000
+47326.00   0.165103   0.287445   0.0985414    0.167000    0.287000    0.0980000
+47327.00   0.165220   0.285551   0.0981234    0.167000    0.285000    0.0976000
+47328.00   0.165235   0.283612   0.0977212    0.167000    0.283000    0.0973000
+47329.00   0.165078   0.281610   0.0972599    0.168000    0.281000    0.0969000
+47330.00   0.164740   0.279509   0.0966944    0.168000    0.279000    0.0964000
+47331.00   0.164408   0.277292   0.0960175    0.168000    0.277000    0.0957000
+47332.00   0.164308   0.274976   0.0952407    0.168000    0.275000    0.0950000
+47333.00   0.164459   0.272627   0.0943817    0.169000    0.273000    0.0941000
+47334.00   0.164844   0.270336   0.0934727    0.169000    0.271000    0.0932000
+47335.00   0.165440   0.268181   0.0925620    0.169000    0.269000    0.0922000
+47336.00   0.166198   0.266171   0.0917134    0.170000    0.267000    0.0914000
+47337.00   0.167033   0.264291   0.0909916    0.170000    0.265000    0.0907000
+47338.00   0.167857   0.262495   0.0904523    0.170000    0.263000    0.0901000
+47339.00   0.168577   0.260716   0.0901316    0.171000    0.261000    0.0898000
+47340.00   0.169078   0.258899   0.0900288    0.171000    0.259000    0.0897000
+47341.00   0.169346   0.257053   0.0900763    0.171000    0.257000    0.0897000
+47342.00   0.169407   0.255191   0.0901508    0.171000    0.255000    0.0897000
+47343.00   0.169293   0.253312   0.0901073    0.171000    0.253000    0.0897000
+47344.00   0.169043   0.251413   0.0898241    0.171000    0.251000    0.0893000
+47345.00   0.168718   0.249492   0.0892455    0.171000    0.249000    0.0887000
+47346.00   0.168392   0.247551   0.0883989    0.171000    0.247000    0.0878000
+47347.00   0.168128   0.245587   0.0873872    0.171000    0.246000    0.0868000
+47348.00   0.167947   0.243581   0.0863579    0.171000    0.244000    0.0858000
+47349.00   0.167849   0.241539   0.0854474    0.170000    0.242000    0.0849000
+47350.00   0.167747   0.239484   0.0847557    0.170000    0.240000    0.0842000
+47351.00   0.167560   0.237432   0.0843280    0.169000    0.239000    0.0838000
+47352.00   0.167240   0.235399   0.0841458    0.169000    0.237000    0.0836000
+47353.00   0.166830   0.233390   0.0841389    0.169000    0.235000    0.0837000
+47354.00   0.166361   0.231408   0.0842164    0.168000    0.233000    0.0838000
+47355.00   0.165858   0.229461   0.0842809    0.168000    0.231000    0.0838000
+47356.00   0.165381   0.227575   0.0842424    0.167000    0.229000    0.0838000
+47357.00   0.164937   0.225745   0.0840428    0.167000    0.228000    0.0837000
+47358.00   0.164436   0.223927   0.0836617    0.166000    0.226000    0.0833000
+47359.00   0.163829   0.222063   0.0831075    0.165000    0.223000    0.0828000
+47360.00   0.163209   0.220095   0.0824115    0.165000    0.221000    0.0821000
+47361.00   0.162581   0.218034   0.0816152    0.164000    0.219000    0.0813000
+47362.00   0.161910   0.215909   0.0807731    0.163000    0.217000    0.0804000
+47363.00   0.161156   0.213768   0.0799456    0.162000    0.215000    0.0796000
+47364.00   0.160277   0.211659   0.0791869    0.161000    0.213000    0.0788000
+47365.00   0.159233   0.209618   0.0785392    0.160000    0.211000    0.0782000
+47366.00   0.158046   0.207629   0.0780408    0.159000    0.209000    0.0777000
+47367.00   0.156759   0.205662   0.0777049    0.158000    0.207000    0.0775000
+47368.00   0.155411   0.203688   0.0775034    0.156000    0.205000    0.0773000
+47369.00   0.154067   0.201711   0.0773500    0.155000    0.203000    0.0772000
+47370.00   0.152797   0.199746   0.0771104    0.154000    0.201000    0.0770000
+47371.00   0.151642   0.197803   0.0766462    0.153000    0.199000    0.0765000
+47372.00   0.150613   0.195889   0.0758730    0.152000    0.198000    0.0758000
+47373.00   0.149680   0.193991   0.0748029    0.150000    0.196000    0.0747000
+47374.00   0.148737   0.192093   0.0735477    0.149000    0.194000    0.0734000
+47375.00   0.147679   0.190193   0.0722613    0.148000    0.192000    0.0720000
+47376.00   0.146460   0.188283   0.0710986    0.147000    0.190000    0.0708000
+47377.00   0.145064   0.186359   0.0701735    0.145000    0.188000    0.0698000
+47378.00   0.143549   0.184427   0.0695288    0.144000    0.185000    0.0691000
+47379.00   0.141975   0.182503   0.0691416    0.142000    0.184000    0.0687000
+47380.00   0.140372   0.180588   0.0689507    0.141000    0.182000    0.0686000
+47381.00   0.138711   0.178690   0.0688957    0.140000    0.180000    0.0685000
+47382.00   0.137032   0.176831   0.0688826    0.138000    0.178000    0.0685000
+47383.00   0.135399   0.175036   0.0688161    0.137000    0.177000    0.0684000
+47384.00   0.133883   0.173345   0.0686211    0.135000    0.175000    0.0682000
+47385.00   0.132534   0.171798   0.0682485    0.134000    0.174000    0.0678000
+47386.00   0.131275   0.170397   0.0676839    0.132000    0.172000    0.0672000
+47387.00   0.130008   0.169109   0.0669456    0.131000    0.171000    0.0665000
+47388.00   0.128643   0.167903   0.0660771    0.129000    0.169000    0.0656000
+47389.00   0.127093   0.166742   0.0651379    0.127000    0.168000    0.0647000
+47390.00   0.125331   0.165595   0.0641926    0.125000    0.167000    0.0637000
+47391.00   0.123406   0.164434   0.0633086    0.124000    0.165000    0.0629000
+47392.00   0.121374   0.163241   0.0625467    0.122000    0.164000    0.0622000
+47393.00   0.119274   0.162008   0.0619491    0.120000    0.163000    0.0616000
+47394.00   0.117135   0.160741   0.0615310    0.118000    0.161000    0.0612000
+47395.00   0.114975   0.159443   0.0612741    0.116000    0.160000    0.0610000
+47396.00   0.112786   0.158136   0.0611109    0.114000    0.159000    0.0608000
+47397.00   0.110555   0.156842   0.0609245    0.112000    0.158000    0.0606000
+47398.00   0.108275   0.155581   0.0605739    0.110000    0.156000    0.0602000
+47399.00   0.105966   0.154361   0.0599372    0.108000    0.155000    0.0595000
+47400.00   0.103668   0.153183   0.0589596    0.105000    0.154000    0.0584000
+47401.00   0.101413   0.152048   0.0576822    0.103000    0.153000    0.0570000
+47402.00   0.099179   0.150947   0.0562406    0.101000    0.152000    0.0555000
+47403.00   0.096931   0.149870   0.0548202    0.099000    0.151000    0.0540000
+47404.00   0.094639   0.148808   0.0535890    0.097000    0.150000    0.0527000
+47405.00   0.092289   0.147762   0.0526372    0.094000    0.149000    0.0517000
+47406.00   0.089921   0.146743   0.0519722    0.092000    0.148000    0.0511000
+47407.00   0.087577   0.145762   0.0515357    0.090000    0.147000    0.0507000
+47408.00   0.085267   0.144806   0.0512297    0.088000    0.146000    0.0504000
+47409.00   0.082984   0.143851   0.0509546    0.086000    0.145000    0.0503000
+47410.00   0.080727   0.142877   0.0506274    0.083000    0.144000    0.0501000
+47411.00   0.078490   0.141894   0.0501843    0.081000    0.143000    0.0497000
+47412.00   0.076267   0.140924   0.0495867    0.079000    0.142000    0.0492000
+47413.00   0.074057   0.139990   0.0488225    0.076000    0.141000    0.0485000
+47414.00   0.071886   0.139112   0.0479034    0.074000    0.141000    0.0476000
+47415.00   0.069777   0.138302   0.0468630    0.071000    0.140000    0.0466000
+47416.00   0.067686   0.137557   0.0457511    0.069000    0.139000    0.0454000
+47417.00   0.065546   0.136864   0.0446227    0.067000    0.138000    0.0442000
+47418.00   0.063293   0.136209   0.0435312    0.064000    0.138000    0.0431000
+47419.00   0.060869   0.135577   0.0425233    0.062000    0.137000    0.0420000
+47420.00   0.058265   0.134961   0.0416315    0.059000    0.136000    0.0411000
+47421.00   0.055502   0.134348   0.0408676    0.056000    0.136000    0.0404000
+47422.00   0.052603   0.133723   0.0402159    0.053000    0.135000    0.0397000
+47423.00   0.049581   0.133086   0.0396256    0.050000    0.135000    0.0392000
+47424.00   0.046436   0.132471   0.0390073    0.047000    0.134000    0.0386000
+47425.00   0.043170   0.131913   0.0382443    0.044000    0.134000    0.0379000
+47426.00   0.039824   0.131419   0.0372149    0.041000    0.133000    0.0369000
+47427.00   0.036435   0.130977   0.0358406    0.037000    0.133000    0.0355000
+47428.00   0.033043   0.130578   0.0341172    0.034000    0.133000    0.0338000
+47429.00   0.029697   0.130234   0.0321301    0.031000    0.132000    0.0318000
+47430.00   0.026438   0.129962   0.0300408    0.027000    0.132000    0.0297000
+47431.00   0.023217   0.129768   0.0280465    0.024000    0.132000    0.0277000
+47432.00   0.019958   0.129647   0.0263097    0.021000    0.132000    0.0260000
+47433.00   0.016604   0.129578   0.0249050    0.018000    0.132000    0.0245000
+47434.00   0.013117   0.129525   0.0238086    0.014000    0.132000    0.0234000
+47435.00   0.009537   0.129435   0.0229268    0.011000    0.132000    0.0225000
+47436.00   0.005981   0.129326   0.0221395    0.008000    0.132000    0.0216000
+47437.00   0.002559   0.129250   0.0213314    0.005000    0.132000    0.0207000
+47438.00  -0.000668   0.129269   0.0204069    0.002000    0.132000    0.0198000
+47439.00  -0.003644   0.129446   0.0193018   -0.001600    0.132100    0.0186300
+47440.00  -0.006348   0.129831   0.0179812   -0.004800    0.132500    0.0172900
+47441.00  -0.008941   0.130419   0.0164502   -0.008000    0.133000    0.0157700
+47442.00  -0.011635   0.131184   0.0147438   -0.011200    0.133500    0.0141000
+47443.00  -0.014534   0.132069   0.0129147   -0.014400    0.134100    0.0123300
+47444.00  -0.017668   0.132983   0.0110303   -0.017600    0.134700    0.0105200
+47445.00  -0.021041   0.133834   0.0091639   -0.020800    0.135300    0.0087500
+47446.00  -0.024606   0.134593   0.0073898   -0.024000    0.136000    0.0070800
+47447.00  -0.028288   0.135265   0.0057691   -0.027200    0.136700    0.0055600
+47448.00  -0.031998   0.135860   0.0043350   -0.030400    0.137400    0.0042200
+47449.00  -0.035649   0.136389   0.0030862   -0.033600    0.138100    0.0030300
+47450.00  -0.039166   0.136885   0.0019811   -0.036800    0.138800    0.0019600
+47451.00  -0.042495   0.137399   0.0009354   -0.039900    0.139500    0.0009200
+47452.00  -0.045595   0.137986  -0.0001641   -0.043000    0.140300   -0.0002100
+47453.00  -0.048446   0.138691  -0.0014361   -0.046100    0.141100   -0.0015300
+47454.00  -0.051072   0.139535  -0.0029797   -0.049200    0.141900   -0.0031300
+47455.00  -0.053561   0.140503  -0.0048462   -0.052300    0.142800   -0.0050600
+47456.00  -0.056022   0.141580  -0.0069989   -0.055300    0.143700   -0.0072600
+47457.00  -0.058573   0.142753  -0.0093158   -0.058300    0.144700   -0.0096200
+47458.00  -0.061320   0.144005  -0.0116231   -0.061300    0.145700   -0.0119800
+47459.00  -0.064320   0.145306  -0.0137447   -0.064300    0.146800   -0.0141400
+47460.00  -0.067585   0.146623  -0.0155610   -0.067300    0.148000   -0.0160000
+47461.00  -0.071008   0.147942  -0.0170483   -0.070300    0.149200   -0.0175400
+47462.00  -0.074448   0.149283  -0.0182697   -0.073200    0.150600   -0.0188100
+47463.00  -0.077762   0.150669  -0.0193425   -0.076200    0.151900   -0.0199300
+47464.00  -0.080813   0.152136  -0.0203951   -0.079100    0.153400   -0.0210200
+47465.00  -0.083525   0.153718  -0.0215348   -0.082000    0.154900   -0.0222000
+47466.00  -0.086039   0.155397  -0.0228325   -0.084900    0.156500   -0.0235300
+47467.00  -0.088557   0.157148  -0.0243200   -0.087700    0.158200   -0.0250200
+47468.00  -0.091194   0.158948  -0.0259991   -0.090500    0.159900   -0.0266900
+47469.00  -0.093909   0.160779  -0.0278487   -0.093200    0.161700   -0.0285100
+47470.00  -0.096631   0.162627  -0.0298275   -0.095900    0.163500   -0.0304200
+47471.00  -0.099338   0.164502  -0.0318693   -0.098600    0.165400   -0.0323700
+47472.00  -0.102060   0.166418  -0.0338902   -0.101300    0.167300   -0.0343100
+47473.00  -0.104826   0.168374  -0.0358126   -0.103900    0.169200   -0.0361700
+47474.00  -0.107616   0.170322  -0.0375893   -0.106400    0.171200   -0.0378900
+47475.00  -0.110370   0.172220  -0.0391988   -0.108800    0.173200   -0.0394700
+47476.00  -0.112960   0.174102  -0.0406350   -0.111200    0.175300   -0.0408900
+47477.00  -0.115258   0.176073  -0.0419216   -0.113400    0.177400   -0.0421800
+47478.00  -0.117269   0.178146  -0.0431352   -0.115700    0.179600   -0.0434200
+47479.00  -0.119034   0.180309  -0.0443845   -0.117800    0.181800   -0.0447200
+47480.00  -0.120585   0.182550  -0.0457852   -0.119900    0.184100   -0.0461700
+47481.00  -0.121991   0.184885  -0.0474319   -0.121900    0.186400   -0.0478600
+47482.00  -0.123340   0.187332  -0.0493727   -0.123900    0.188800   -0.0498400
+47483.00  -0.124708   0.189888  -0.0515897   -0.125800    0.191300   -0.0520900
+47484.00  -0.126172   0.192541  -0.0539944   -0.127700    0.193800   -0.0545100
+47485.00  -0.127798   0.195270  -0.0564475   -0.129600    0.196400   -0.0569700
+47486.00  -0.129602   0.198043  -0.0587926   -0.131400    0.199000   -0.0593200
+47487.00  -0.131586   0.200833  -0.0609012   -0.133300    0.201700   -0.0614200
+47488.00  -0.133739   0.203614  -0.0627064   -0.135100    0.204400   -0.0632200
+47489.00  -0.135980   0.206392  -0.0642198   -0.136900    0.207200   -0.0647300
+47490.00  -0.138213   0.209184  -0.0655199   -0.138700    0.210000   -0.0660300
+47491.00  -0.140403   0.212013  -0.0667258   -0.140500    0.212800   -0.0672500
+47492.00  -0.142552   0.214861  -0.0679543   -0.142300    0.215700   -0.0684900
+47493.00  -0.144665   0.217698  -0.0692912   -0.144000    0.218500   -0.0698400
+47494.00  -0.146749   0.220493  -0.0707816   -0.145700    0.221400   -0.0713400
+47495.00  -0.148794   0.223228  -0.0724359   -0.147400    0.224300   -0.0729900
+47496.00  -0.150745   0.225929  -0.0742397   -0.149000    0.227100   -0.0747800
+47497.00  -0.152550   0.228623  -0.0761494   -0.150600    0.230000   -0.0766700
+47498.00  -0.154162   0.231337  -0.0781025   -0.152100    0.232900   -0.0785900
+47499.00  -0.155533   0.234098  -0.0800263   -0.153600    0.235800   -0.0804900
+47500.00  -0.156686   0.236928  -0.0818496   -0.155100    0.238700   -0.0822900
+47501.00  -0.157701   0.239829  -0.0835181   -0.156400    0.241500   -0.0839300
+47502.00  -0.158659   0.242801  -0.0849965   -0.157700    0.244400   -0.0853800
+47503.00  -0.159628   0.245841  -0.0862774   -0.158900    0.247200   -0.0866400
+47504.00  -0.160621   0.248931  -0.0873914   -0.160000    0.250100   -0.0877300
+47505.00  -0.161634   0.252042  -0.0884065   -0.160900    0.253000   -0.0887000
+47506.00  -0.162667   0.255108  -0.0894034   -0.161700    0.255900   -0.0896700
+47507.00  -0.163707   0.258085  -0.0904717   -0.162400    0.258800   -0.0907500
+47508.00  -0.164702   0.260986  -0.0917109   -0.163000    0.261700   -0.0920300
+47509.00  -0.165583   0.263835  -0.0931807   -0.163500    0.264600   -0.0935700
+47510.00  -0.166239   0.266649  -0.0948778   -0.164000    0.267500   -0.0953200
+47511.00  -0.166572   0.269463  -0.0967332   -0.164400    0.270400   -0.0972300
+47512.00  -0.166652   0.272299  -0.0986221   -0.164700    0.273300   -0.0991700
+47513.00  -0.166579   0.275166  -0.1004058   -0.164900    0.276200   -0.1009900
+47514.00  -0.166451   0.278072  -0.1019672   -0.165000    0.279100   -0.1025800
+47515.00  -0.166364   0.281028  -0.1032387   -0.165000    0.282000   -0.1038800
+47516.00  -0.166345   0.284038  -0.1042255   -0.165000    0.284900   -0.1049000
+47517.00  -0.166322   0.287090  -0.1049930   -0.164800    0.287700   -0.1057000
+47518.00  -0.166208   0.290178  -0.1056444   -0.164600    0.290600   -0.1063800
+47519.00  -0.165936   0.293325  -0.1062911   -0.164300    0.293500   -0.1070400
+47520.00  -0.165480   0.296533  -0.1070274   -0.163900    0.296400   -0.1078000
+47521.00  -0.164879   0.299756  -0.1079153   -0.163400    0.299300   -0.1087200
+47522.00  -0.164185   0.302943  -0.1089782   -0.162800    0.302200   -0.1098000
+47523.00  -0.163448   0.306042  -0.1102095   -0.162200    0.305100   -0.1110300
+47524.00  -0.162718   0.309000  -0.1115825   -0.161500    0.308000   -0.1123800
+47525.00  -0.162014   0.311771  -0.1130535   -0.160700    0.310800   -0.1138000
+47526.00  -0.161329   0.314379  -0.1145574   -0.159900    0.313700   -0.1152300
+47527.00  -0.160623   0.316868  -0.1160242   -0.159100    0.316500   -0.1166000
+47528.00  -0.159834   0.319279  -0.1173940   -0.158200    0.319200   -0.1178600
+47529.00  -0.158899   0.321651  -0.1186247   -0.157300    0.322000   -0.1189700
+47530.00  -0.157777   0.324021  -0.1196954   -0.156100    0.324500   -0.1200400
+47531.00  -0.156514   0.326406  -0.1206076   -0.154900    0.327000   -0.1209400
+47532.00  -0.155183   0.328817  -0.1213994   -0.153700    0.329500   -0.1217400
+47533.00  -0.153835   0.331261  -0.1221507   -0.152500    0.332000   -0.1225100
+47534.00  -0.152507   0.333745  -0.1229689   -0.151300    0.334600   -0.1233600
+47535.00  -0.151241   0.336273  -0.1239605   -0.150200    0.337300   -0.1243300
+47536.00  -0.150107   0.338829  -0.1252112   -0.149300    0.340000   -0.1255800
+47537.00  -0.149139   0.341389  -0.1267405   -0.148400    0.342700   -0.1271300
+47538.00  -0.148319   0.343925  -0.1284866   -0.147600    0.345300   -0.1288800
+47539.00  -0.147620   0.346411  -0.1303312   -0.146800    0.347900   -0.1307300
+47540.00  -0.146987   0.348832  -0.1321353   -0.146000    0.350300   -0.1325300
+47541.00  -0.146334   0.351191  -0.1337636   -0.145100    0.352700   -0.1341600
+47542.00  -0.145597   0.353501  -0.1351367   -0.144200    0.355100   -0.1355200
+47543.00  -0.144734   0.355784  -0.1362438   -0.143300    0.357400   -0.1366300
+47544.00  -0.143704   0.358063  -0.1371317   -0.142300    0.359600   -0.1375100
+47545.00  -0.142476   0.360360  -0.1378875   -0.141100    0.361800   -0.1382600
+47546.00  -0.141091   0.362676  -0.1386235   -0.140000    0.364000   -0.1389800
+47547.00  -0.139636   0.364995  -0.1394478   -0.138700    0.366200   -0.1397900
+47548.00  -0.138188   0.367291  -0.1404436   -0.137500    0.368300   -0.1407900
+47549.00  -0.136813   0.369529  -0.1416598   -0.136300    0.370400   -0.1419900
+47550.00  -0.135556   0.371683  -0.1431067   -0.135100    0.372400   -0.1435100
+47551.00  -0.134376   0.373769  -0.1447478   -0.134000    0.374400   -0.1452100
+47552.00  -0.133268   0.375796  -0.1465163   -0.132900    0.376400   -0.1470300
+47553.00  -0.132239   0.377769  -0.1483335   -0.131800    0.378400   -0.1488800
+47554.00  -0.131292   0.379698  -0.1501200   -0.130800    0.380300   -0.1507100
+47555.00  -0.130378   0.381620  -0.1518051   -0.129800    0.382400   -0.1523400
+47556.00  -0.129424   0.383583  -0.1533415   -0.128800    0.384500   -0.1538200
+47557.00  -0.128349   0.385633  -0.1547032   -0.127700    0.386700   -0.1551400
+47558.00  -0.127087   0.387818  -0.1558913   -0.126500    0.388900   -0.1562700
+47559.00  -0.125585   0.390188  -0.1569400   -0.125100    0.391200   -0.1572800
+47560.00  -0.123832   0.392773  -0.1579212   -0.123500    0.393600   -0.1583500
+47561.00  -0.121911   0.395525  -0.1589440   -0.121600    0.396200   -0.1593900
+47562.00  -0.119903   0.398354  -0.1601397   -0.119600    0.398900   -0.1606200
+47563.00  -0.117871   0.401156  -0.1616185   -0.117500    0.401600   -0.1621400
+47564.00  -0.115849   0.403803  -0.1634295   -0.115300    0.404100   -0.1639800
+47565.00  -0.113860   0.406177  -0.1655334   -0.113200    0.406500   -0.1661000
+47566.00  -0.111876   0.408262  -0.1678033   -0.111000    0.408700   -0.1683600
+47567.00  -0.109852   0.410131  -0.1700525   -0.108800    0.410800   -0.1705800
+47568.00  -0.107744   0.411869  -0.1721051   -0.106600    0.412700   -0.1726000
+47569.00  -0.105503   0.413566  -0.1738461   -0.104300    0.414600   -0.1743200
+47570.00  -0.103089   0.415308  -0.1752415   -0.101800    0.416200   -0.1757100
+47571.00  -0.100531   0.417146  -0.1763413   -0.099200    0.417700   -0.1768200
+47572.00  -0.097904   0.419098  -0.1772436   -0.096700    0.419300   -0.1777600
+47573.00  -0.095312   0.421131  -0.1780595   -0.094100    0.420900   -0.1786100
+47574.00  -0.092857   0.423210  -0.1788889   -0.091600    0.422600   -0.1794900
+47575.00  -0.090612   0.425283  -0.1798109   -0.089600    0.425000   -0.1803500
+47576.00  -0.088536   0.427269  -0.1808903   -0.087600    0.427400   -0.1813500
+47577.00  -0.086538   0.429119  -0.1821532   -0.085500    0.429900   -0.1825200
+47578.00  -0.084432   0.430932  -0.1835922   -0.083400    0.432500   -0.1838500
+47579.00  -0.082059   0.432797  -0.1851673   -0.081100    0.435000   -0.1852900
+47580.00  -0.079410   0.434757  -0.1868075   -0.078000    0.436900   -0.1870700
+47581.00  -0.076519   0.436825  -0.1884434   -0.074800    0.438700   -0.1888600
+47582.00  -0.073472   0.438984  -0.1900135   -0.071500    0.440400   -0.1905900
+47583.00  -0.070384   0.441200  -0.1914703   -0.068200    0.442200   -0.1922000
+47584.00  -0.067355   0.443424  -0.1927852   -0.065000    0.444000   -0.1936400
+47585.00  -0.064462   0.445590  -0.1939514   -0.062400    0.446200   -0.1946700
+47586.00  -0.061777   0.447654  -0.1949889   -0.060000    0.448300   -0.1955700
+47587.00  -0.059322   0.449590  -0.1959522   -0.057700    0.450300   -0.1963900
+47588.00  -0.057032   0.451392  -0.1969334   -0.055600    0.452100   -0.1972600
+47589.00  -0.054827   0.453056  -0.1980522   -0.053500    0.453900   -0.1983000
+47590.00  -0.052640   0.454584  -0.1994315   -0.051500    0.455300   -0.1997600
+47591.00  -0.050464   0.455997  -0.2011648   -0.049300    0.456600   -0.2015700
+47592.00  -0.048237   0.457318  -0.2032656   -0.047100    0.457700   -0.2037500
+47593.00  -0.045879   0.458566  -0.2056514   -0.044800    0.458800   -0.2061700
+47594.00  -0.043333   0.459762  -0.2081660   -0.042400    0.459900   -0.2087000
+47595.00  -0.040559   0.460928  -0.2106262   -0.039700    0.461200   -0.2111500
+47596.00  -0.037601   0.462108  -0.2128614   -0.037000    0.462600   -0.2133400
+47597.00  -0.034537   0.463328  -0.2147751   -0.034100    0.464000   -0.2151900
+47598.00  -0.031444   0.464609  -0.2163651   -0.031100    0.465500   -0.2167300
+47599.00  -0.028399   0.465972  -0.2176977   -0.028100    0.467000   -0.2180500
+47600.00  -0.025444   0.467418  -0.2188749   -0.025000    0.468400   -0.2192200
+47601.00  -0.022537   0.468923  -0.2200257   -0.021800    0.469800   -0.2204100
+47602.00  -0.019637   0.470447  -0.2212566   -0.018700    0.471100   -0.2217300
+47603.00  -0.016728   0.471924  -0.2226366   -0.015600    0.472300   -0.2232000
+47604.00  -0.013793   0.473291  -0.2242018   -0.012500    0.473500   -0.2248600
+47605.00  -0.010811   0.474489  -0.2259581   -0.009500    0.474800   -0.2265900
+47606.00  -0.007772   0.475523  -0.2278645   -0.006400    0.475900   -0.2284400
+47607.00  -0.004680   0.476423  -0.2298524   -0.003400    0.476900   -0.2303600
+47608.00  -0.001536   0.477221  -0.2318442   -0.000400    0.477800   -0.2322500
+47609.00   0.001662   0.477931  -0.2337629    0.002600    0.478600   -0.2340800
+47610.00   0.004910   0.478562  -0.2355462    0.005700    0.479300   -0.2359200
+47611.00   0.008163   0.479117  -0.2371585    0.008700    0.479800   -0.2375800
+47612.00   0.011358   0.479605  -0.2385892    0.011700    0.480300   -0.2390200
+47613.00   0.014456   0.480025  -0.2398493    0.014800    0.480700   -0.2402700
+47614.00   0.017512   0.480344  -0.2409700    0.017900    0.481100   -0.2413800
+47615.00   0.020572   0.480580  -0.2420101    0.021100    0.481400   -0.2424700
+47616.00   0.023676   0.480793  -0.2430699    0.024400    0.481700   -0.2436200
+47617.00   0.026828   0.481018  -0.2442733    0.027700    0.481900   -0.2449400
+47618.00   0.030002   0.481275  -0.2457298    0.031100    0.482200   -0.2465400
+47619.00   0.033252   0.481540  -0.2475001    0.034500    0.482400   -0.2484400
+47620.00   0.036645   0.481775  -0.2495596    0.037900    0.482600   -0.2503600
+47621.00   0.040156   0.481968  -0.2517880    0.041300    0.482700   -0.2524200
+47622.00   0.043695   0.482123  -0.2540059    0.044800    0.482900   -0.2544400
+47623.00   0.047168   0.482245  -0.2560372    0.048200    0.483000   -0.2563000
+47624.00   0.050497   0.482334  -0.2577692    0.051600    0.483100   -0.2578500
+47625.00   0.053617   0.482389  -0.2591858    0.054700    0.483200   -0.2594100
+47626.00   0.056542   0.482418  -0.2603588    0.057800    0.483200   -0.2607300
+47627.00   0.059357   0.482421  -0.2614125    0.060900    0.483200   -0.2619200
+47628.00   0.062146   0.482398  -0.2624770    0.063900    0.483200   -0.2630900
+47629.00   0.064996   0.482348  -0.2636536    0.066900    0.483200   -0.2643500
+47630.00   0.067974   0.482275  -0.2650022    0.069900    0.483100   -0.2656000
+47631.00   0.071056   0.482182  -0.2665444    0.072900    0.483000   -0.2670200
+47632.00   0.074175   0.482084  -0.2682722    0.075800    0.482900   -0.2686400
+47633.00   0.077261   0.481993  -0.2701558    0.078700    0.482800   -0.2704300
+47634.00   0.080242   0.481921  -0.2721509    0.081400    0.482800   -0.2723800
+47635.00   0.083051   0.481881  -0.2742048    0.084000    0.482900   -0.2745500
+47636.00   0.085654   0.481862  -0.2762618    0.086500    0.483000   -0.2767500
+47637.00   0.088070   0.481819  -0.2782747    0.088800    0.483100   -0.2789200
+47638.00   0.090333   0.481716  -0.2802104    0.091000    0.483200   -0.2809800
+47639.00   0.092486   0.481533  -0.2820442    0.093100    0.483100   -0.2829000
+47640.00   0.094494   0.481236  -0.2837585    0.095200    0.482700   -0.2844400
+47641.00   0.096371   0.480834  -0.2853637    0.097200    0.482100   -0.2858300
+47642.00   0.098163   0.480347  -0.2869023    0.099200    0.481400   -0.2871600
+47643.00   0.099938   0.479781  -0.2884530    0.101100    0.480700   -0.2885100
+47644.00   0.101770   0.479145  -0.2901074    0.103100    0.479800   -0.2899900
+47645.00   0.103681   0.478475  -0.2919493    0.104900    0.479400   -0.2919500
+47646.00   0.105679   0.477783  -0.2940401    0.106900    0.478800   -0.2942000
+47647.00   0.107778   0.477063  -0.2963841    0.109000    0.478300   -0.2966900
+47648.00   0.110015   0.476300  -0.2989080    0.111300    0.477700   -0.2993400
+47649.00   0.112428   0.475470  -0.3014717    0.113600    0.477000   -0.3020200
+47650.00   0.115060   0.474545  -0.3039073    0.116100    0.476000   -0.3044400
+47651.00   0.117874   0.473559  -0.3060707    0.118800    0.474900   -0.3065900
+47652.00   0.120803   0.472567  -0.3078923    0.121600    0.473800   -0.3084100
+47653.00   0.123774   0.471615  -0.3093978    0.124400    0.472800   -0.3099400
+47654.00   0.126711   0.470731  -0.3106890    0.127300    0.471800   -0.3112700
+47655.00   0.129543   0.469925  -0.3119010    0.130200    0.470900   -0.3124200
+47656.00   0.132250   0.469156  -0.3131560    0.133100    0.470000   -0.3136000
+47657.00   0.134873   0.468363  -0.3145339    0.135900    0.469100   -0.3148900
+47658.00   0.137457   0.467478  -0.3160676    0.138700    0.468100   -0.3163400
+47659.00   0.140051   0.466439  -0.3177515    0.141500    0.467000   -0.3179100
+47660.00   0.142692   0.465202  -0.3195541    0.144100    0.465800   -0.3197900
+47661.00   0.145352   0.463771  -0.3214257    0.146600    0.464600   -0.3217400
+47662.00   0.147974   0.462165  -0.3233090    0.149000    0.463200   -0.3236900
+47663.00   0.150536   0.460428  -0.3251465    0.151400    0.461700   -0.3255900
+47664.00   0.153032   0.458624  -0.3268908    0.153700    0.460100   -0.3274000
+47665.00   0.155458   0.456813  -0.3285086    0.156000    0.458200   -0.3290600
+47666.00   0.157792   0.455046  -0.3299836    0.158100    0.456200   -0.3305900
+47667.00   0.159992   0.453368  -0.3313262    0.160200    0.454200   -0.3320200
+47668.00   0.161991   0.451794  -0.3325726    0.162200    0.452200   -0.3333900
+47669.00   0.163797   0.450258  -0.3337839    0.164100    0.450300   -0.3347300
+47670.00   0.165449   0.448686  -0.3350409    0.166000    0.449200   -0.3357500
+47671.00   0.167014   0.447059  -0.3364270    0.167900    0.448100   -0.3368900
+47672.00   0.168630   0.445410  -0.3380170    0.169700    0.447100   -0.3382400
+47673.00   0.170353   0.443761  -0.3398651    0.171500    0.446000   -0.3398400
+47674.00   0.172213   0.442138  -0.3419779    0.173300    0.444800   -0.3417200
+47675.00   0.174223   0.440579  -0.3443007    0.175100    0.442700   -0.3443400
+47676.00   0.176326   0.439081  -0.3467165    0.176900    0.440500   -0.3470700
+47677.00   0.178441   0.437618  -0.3490693    0.178800    0.438300   -0.3496900
+47678.00   0.180503   0.436141  -0.3512058    0.180600    0.436100   -0.3520600
+47679.00   0.182458   0.434592  -0.3530186    0.182600    0.434100   -0.3540600
+47680.00   0.184277   0.432933  -0.3544779    0.184700    0.432400   -0.3555200
+47681.00   0.185968   0.431184  -0.3556373    0.186700    0.431000   -0.3567100
+47682.00   0.187552   0.429384  -0.3566092    0.188800    0.429700   -0.3577100
+47683.00   0.189112   0.427581  -0.3575300    0.190900    0.428500   -0.3586700
+47684.00   0.190740   0.425782  -0.3585215    0.192900    0.427200   -0.3597100
+47685.00   0.192506   0.423983  -0.3596579    0.195000    0.425500   -0.3608800
+47686.00   0.194400   0.422163  -0.3609551    0.197000    0.423800   -0.3621600
+47687.00   0.196393   0.420297  -0.3623900    0.199000    0.421900   -0.3635400
+47688.00   0.198458   0.418355  -0.3639148    0.201000    0.420000   -0.3649900
+47689.00   0.200570   0.416317  -0.3654695    0.202900    0.417900   -0.3664500
+47690.00   0.202666   0.414182  -0.3669805    0.204700    0.415500   -0.3678700
+47691.00   0.204677   0.411958  -0.3683846    0.206400    0.413100   -0.3691700
+47692.00   0.206570   0.409656  -0.3696329    0.208100    0.410600   -0.3703100
+47693.00   0.208381   0.407288  -0.3706947    0.209700    0.408000   -0.3712700
+47694.00   0.210155   0.404868  -0.3715637    0.211400    0.405400   -0.3720900
+47695.00   0.211929   0.402408  -0.3722632    0.213100    0.402800   -0.3727600
+47696.00   0.213726   0.399916  -0.3728549    0.214900    0.400300   -0.3733200
+47697.00   0.215569   0.397397  -0.3734306    0.216700    0.397700   -0.3738500
+47698.00   0.217478   0.394856  -0.3740968    0.218500    0.395100   -0.3744500
+47699.00   0.219460   0.392288  -0.3749524    0.220400    0.392400   -0.3752200
+47700.00   0.221490   0.389688  -0.3760604    0.222400    0.389800   -0.3764300
+47701.00   0.223484   0.387050  -0.3774185    0.224500    0.387200   -0.3778900
+47702.00   0.225443   0.384378  -0.3789637    0.226600    0.384600   -0.3795300
+47703.00   0.227389   0.381680  -0.3805834    0.228800    0.382000   -0.3812500
+47704.00   0.229349   0.378961  -0.3821356    0.230900    0.379300   -0.3829100
+47705.00   0.231358   0.376225  -0.3834821    0.232900    0.376700   -0.3841500
+47706.00   0.233388   0.373459  -0.3845358    0.234800    0.374000   -0.3851100
+47707.00   0.235346   0.370661  -0.3852727    0.236600    0.371300   -0.3857600
+47708.00   0.237174   0.367822  -0.3857380    0.238400    0.368600   -0.3861700
+47709.00   0.238840   0.364929  -0.3860344    0.240100    0.365800   -0.3864300
+47710.00   0.240365   0.361986  -0.3862903    0.241800    0.363000   -0.3867200
+47711.00   0.241816   0.359017  -0.3866311    0.243400    0.359800   -0.3870900
+47712.00   0.243232   0.356043  -0.3871441    0.244900    0.356500   -0.3876300
+47713.00   0.244637   0.353083  -0.3878642    0.246400    0.353200   -0.3883600
+47714.00   0.246029   0.350152  -0.3887809    0.247800    0.350000   -0.3892600
+47715.00   0.247390   0.347247  -0.3898499    0.249100    0.347000   -0.3903000
+47716.00   0.248711   0.344346  -0.3910046    0.250400    0.344100   -0.3914000
+47717.00   0.249981   0.341423  -0.3921652    0.251500    0.341300   -0.3925200
+47718.00   0.251214   0.338475  -0.3932617    0.252600    0.338500   -0.3935800
+47719.00   0.252378   0.335505  -0.3942564    0.253600    0.335700   -0.3945600
+47720.00   0.253441   0.332538  -0.3951311    0.254500    0.333000   -0.3954500
+47721.00   0.254448   0.329617  -0.3958903    0.255400    0.330200   -0.3962100
+47722.00   0.255471   0.326783  -0.3965658    0.256100    0.327500   -0.3968500
+47723.00   0.256523   0.324049  -0.3972030    0.256900    0.324700   -0.3975300
+47724.00   0.257510   0.321393  -0.3978523    0.257500    0.322000   -0.3980000
+47725.00   0.258280   0.318751  -0.3985792    0.258000    0.319100   -0.3986800
+47726.00   0.258834   0.316059  -0.3994760    0.258500    0.316200   -0.3995800
+47727.00   0.259242   0.313273  -0.4006205    0.258900    0.313200   -0.4007400
+47728.00   0.259520   0.310377  -0.4020440    0.259300    0.310100   -0.4022100
+47729.00   0.259677   0.307373  -0.4037092    0.259700    0.307100   -0.4039200
+47730.00   0.259721   0.304260  -0.4055103    0.260100    0.304000   -0.4057500
+47731.00   0.259656   0.301045  -0.4072883    0.260500    0.300900   -0.4075500
+47732.00   0.259516   0.297755  -0.4088916    0.260800    0.297800   -0.4092000
+47733.00   0.259411   0.294397  -0.4102297    0.261100    0.294700   -0.4105700
+47734.00   0.259400   0.290980  -0.4112703    0.261200    0.291500   -0.4116300
+47735.00   0.259475   0.287550  -0.4120367    0.261100    0.288400   -0.4122900
+47736.00   0.259578   0.284153  -0.4126159    0.260900    0.285300   -0.4127600
+47737.00   0.259598   0.280826  -0.4131170    0.260600    0.282100   -0.4131300
+47738.00   0.259486   0.277618  -0.4136479    0.260300    0.279000   -0.4135600
+47739.00   0.259283   0.274517  -0.4142997    0.259900    0.275800   -0.4141200
+47740.00   0.259062   0.271488  -0.4151187    0.259600    0.272500   -0.4149900
+47741.00   0.258932   0.268482  -0.4161049    0.259400    0.269200   -0.4160500
+47742.00   0.258981   0.265471  -0.4172229    0.259300    0.266000   -0.4172400
+47743.00   0.259177   0.262452  -0.4184194    0.259200    0.262800   -0.4185100
+47744.00   0.259382   0.259419  -0.4196321    0.259200    0.259600   -0.4197900
+47745.00   0.259502   0.256372  -0.4208062    0.259300    0.256400   -0.4210000
+47746.00   0.259528   0.253308  -0.4218918    0.259400    0.253200   -0.4220600
+47747.00   0.259514   0.250247  -0.4228527    0.259400    0.250000   -0.4229700
+47748.00   0.259562   0.247205  -0.4236824    0.259500    0.246800   -0.4237400
+47749.00   0.259708   0.244204  -0.4243916    0.259500    0.243700   -0.4243800
+47750.00   0.259841   0.241279  -0.4250039    0.259400    0.240800   -0.4250300
+47751.00   0.259861   0.238419  -0.4255850    0.259300    0.237900   -0.4256300
+47752.00   0.259701   0.235585  -0.4262314    0.259000    0.235100   -0.4263200
+47753.00   0.259331   0.232721  -0.4270534    0.258700    0.232200   -0.4271700
+47754.00   0.258722   0.229769  -0.4281495    0.258400    0.229400   -0.4283300
+47755.00   0.257874   0.226673  -0.4295740    0.257800    0.226300   -0.4297400
+47756.00   0.256866   0.223437  -0.4313153    0.257200    0.223000   -0.4314600
+47757.00   0.255786   0.220100  -0.4332828    0.256500    0.219700   -0.4333800
+47758.00   0.254697   0.216697  -0.4353113    0.255700    0.216300   -0.4353500
+47759.00   0.253687   0.213255  -0.4372182    0.255000    0.213000   -0.4372000
+47760.00   0.252831   0.209803  -0.4388607    0.254100    0.209600   -0.4389300
+47761.00   0.252154   0.206380  -0.4401749    0.253200    0.206300   -0.4403400
+47762.00   0.251620   0.203035  -0.4411822    0.252400    0.203000   -0.4414600
+47763.00   0.251154   0.199820  -0.4419658    0.251500    0.199900   -0.4423900
+47764.00   0.250680   0.196789  -0.4426360    0.250600    0.196800   -0.4431800
+47765.00   0.250131   0.193995  -0.4433011    0.250000    0.193900   -0.4436700
+47766.00   0.249428   0.191364  -0.4440612    0.249300    0.191100   -0.4442400
+47767.00   0.248493   0.188770  -0.4449861    0.248500    0.188300   -0.4449600
+47768.00   0.247289   0.186106  -0.4461029    0.247600    0.185500   -0.4458700
+47769.00   0.245810   0.183287  -0.4473984    0.246500    0.182700   -0.4469500
+47770.00   0.244066   0.180279  -0.4488220    0.245000    0.179700   -0.4486000
+47771.00   0.242130   0.177130  -0.4502998    0.243300    0.176800   -0.4503200
+47772.00   0.240098   0.173910  -0.4517486    0.241400    0.173700   -0.4520100
+47773.00   0.238027   0.170686  -0.4530928    0.239400    0.170700   -0.4536000
+47774.00   0.235922   0.167512  -0.4542755    0.237200    0.167600   -0.4550100
+47775.00   0.233773   0.164445  -0.4552687    0.234900    0.164200   -0.4556800
+47776.00   0.231549   0.161528  -0.4560882    0.232600    0.161100   -0.4563700
+47777.00   0.229223   0.158754  -0.4567806    0.230100    0.158100   -0.4569300
+47778.00   0.226787   0.156103  -0.4574131    0.227600    0.155200   -0.4574300
+47779.00   0.224295   0.153554  -0.4580653    0.225000    0.152400   -0.4579600
+47780.00   0.221831   0.151091  -0.4588307    0.222500    0.149900   -0.4587600
+47781.00   0.219415   0.148691  -0.4598036    0.220000    0.147500   -0.4597900
+47782.00   0.217025   0.146348  -0.4610755    0.217400    0.145200   -0.4611000
+47783.00   0.214648   0.144057  -0.4626902    0.214900    0.142900   -0.4627700
+47784.00   0.212275   0.141805  -0.4646152    0.212400    0.140700   -0.4647300
+47785.00   0.209901   0.139576  -0.4667389    0.210100    0.138600   -0.4669400
+47786.00   0.207490   0.137349  -0.4688831    0.207900    0.136500   -0.4691500
+47787.00   0.205003   0.135107  -0.4708694    0.205500    0.134400   -0.4711900
+47788.00   0.202444   0.132834  -0.4725772    0.203100    0.132300   -0.4729500
+47789.00   0.199818   0.130546  -0.4739759    0.200600    0.130100   -0.4744000
+47790.00   0.197123   0.128280  -0.4751244    0.197800    0.127600   -0.4754200
+47791.00   0.194319   0.126036  -0.4761386    0.194800    0.125000   -0.4763200
+47792.00   0.191399   0.123797  -0.4771475    0.191800    0.122400   -0.4772200
+47793.00   0.188364   0.121549  -0.4782554    0.188700    0.119800   -0.4782300
+47794.00   0.185238   0.119268  -0.4795257    0.185500    0.117200   -0.4794200
+47795.00   0.182078   0.116925  -0.4809871    0.182400    0.115100   -0.4809700
+47796.00   0.178927   0.114535  -0.4826303    0.179300    0.113000   -0.4827000
+47797.00   0.175801   0.112143  -0.4844125    0.176100    0.111000   -0.4845500
+47798.00   0.172692   0.109843  -0.4862662    0.172900    0.109100   -0.4864500
+47799.00   0.169578   0.107752  -0.4881118    0.169700    0.107400   -0.4883400
+47800.00   0.166400   0.105964  -0.4898709    0.166600    0.105800   -0.4901000
+47801.00   0.163140   0.104437  -0.4914920    0.163500    0.104400   -0.4917400
+47802.00   0.159817   0.103076  -0.4929552    0.160300    0.103000   -0.4932500
+47803.00   0.156445   0.101784  -0.4942671    0.157100    0.101700   -0.4946200
+47804.00   0.153030   0.100460  -0.4954603    0.153800    0.100400   -0.4958600
+47805.00   0.149568   0.099020  -0.4965907    0.150400    0.099000   -0.4968500
+47806.00   0.146082   0.097493  -0.4977285    0.146900    0.097700   -0.4978400
+47807.00   0.142608   0.095962  -0.4989574    0.143300    0.096400   -0.4988900
+47808.00   0.139183   0.094510  -0.5003659    0.139600    0.095100   -0.5001200
+47809.00   0.135807   0.093205  -0.5020325    0.135800    0.093800   -0.5016400
+47810.00   0.132325   0.092049  -0.5040085    0.131900    0.092500   -0.5037300
+47811.00   0.128573   0.090993  -0.5062987    0.127900    0.091200   -0.5062100
+47812.00   0.124506   0.089968  -0.5088255    0.123800    0.090000   -0.5089400
+47813.00   0.120219   0.088938  -0.5114430    0.119600    0.088700   -0.5117600
+47814.00   0.115844   0.087877  -0.5139777    0.115400    0.087500   -0.5145000
+47815.00   0.111554   0.086777  -0.5162918    0.111300    0.086400   -0.5167800
+47816.00   0.107593   0.085697  -0.5183447    0.107300    0.085300   -0.5187500
+47817.00   0.103907   0.084674  -0.5201702    0.103300    0.084300   -0.5204900
+47818.00   0.100289   0.083678  -0.5218716    0.099300    0.083200   -0.5220800
+47819.00   0.096530   0.082687  -0.5235770    0.095500    0.082100   -0.5236700
+47820.00   0.092643   0.081623  -0.5253861    0.091800    0.081100   -0.5255000
+47821.00   0.088758   0.080515  -0.5273585    0.088200    0.080000   -0.5275000
+47822.00   0.084999   0.079469  -0.5295096    0.084600    0.079100   -0.5296700
+47823.00   0.081461   0.078569  -0.5318132    0.081100    0.078200   -0.5319700
+47824.00   0.078112   0.077817  -0.5342076    0.077600    0.077400   -0.5343600
+47825.00   0.074806   0.077207  -0.5366070    0.074300    0.076900   -0.5368100
+47826.00   0.071438   0.076761  -0.5389626    0.071000    0.076500   -0.5392300
+47827.00   0.068006   0.076490  -0.5412601    0.067700    0.076300   -0.5415600
+47828.00   0.064380   0.076301  -0.5434609    0.064400    0.076100   -0.5437800
+47829.00   0.060604   0.076052  -0.5455241    0.061100    0.076000   -0.5458500
+47830.00   0.056867   0.075662  -0.5474344    0.057500    0.075700   -0.5476900
+47831.00   0.053306   0.075251  -0.5492010    0.053800    0.075500   -0.5493800
+47832.00   0.049948   0.074957  -0.5508516    0.050100    0.075200   -0.5510000
+47833.00   0.046609   0.074778  -0.5524322    0.046300    0.074900   -0.5525700
+47834.00   0.043062   0.074689  -0.5540111    0.042500    0.074600   -0.5541900
+47835.00   0.039172   0.074657  -0.5556779    0.039800    0.074600   -0.5558600
+47836.00   0.034976   0.074651  -0.5575302    0.035900    0.074300   -0.5577500
+47837.00   0.030594   0.074651  -0.5596418    0.031900    0.074100   -0.5599000
+47838.00   0.026170   0.074658  -0.5620377    0.027900    0.074000   -0.5623200
+47839.00   0.021873   0.074685  -0.5646849    0.023800    0.074000   -0.5649700
+47840.00   0.017774   0.074750  -0.5674802    0.019800    0.074100   -0.5676900
+47841.00   0.013797   0.074867  -0.5702598    0.015700    0.074400   -0.5703800
+47842.00   0.009853   0.075052  -0.5728625    0.011800    0.074600   -0.5728800
+47843.00   0.005935   0.075329  -0.5751842    0.007900    0.075000   -0.5751000
+47844.00   0.002118   0.075723  -0.5772119    0.004000    0.075500   -0.5770200
+47845.00  -0.001536   0.076257  -0.5790178    0.000400    0.076000   -0.5789500
+47846.00  -0.005052   0.076920  -0.5807332   -0.003100    0.076600   -0.5807900
+47847.00  -0.008515   0.077690  -0.5824945   -0.006600    0.077300   -0.5826900
+47848.00  -0.011982   0.078552  -0.5844024   -0.010200    0.078100   -0.5847500
+47849.00  -0.015443   0.079520  -0.5865052   -0.013700    0.079000   -0.5870000
+47850.00  -0.018894   0.080613  -0.5887973   -0.017400    0.080300   -0.5891500
+47851.00  -0.022304   0.081830  -0.5912393   -0.021200    0.081600   -0.5914300
+47852.00  -0.025738   0.083181  -0.5937721   -0.025100    0.083100   -0.5938300
+47853.00  -0.029284   0.084672  -0.5963324   -0.028900    0.084500   -0.5962600
+47854.00  -0.032975   0.086275  -0.5988612   -0.032900    0.086100   -0.5986900
+47855.00  -0.036766   0.087923  -0.6013089   -0.036700    0.087500   -0.6012100
+47856.00  -0.040644   0.089531  -0.6036224   -0.040400    0.088800   -0.6036100
+47857.00  -0.044621   0.091021  -0.6057624   -0.044100    0.090200   -0.6058300
+47858.00  -0.048622   0.092360  -0.6077381   -0.047700    0.091400   -0.6078900
+47859.00  -0.052504   0.093533  -0.6095892   -0.051200    0.092700   -0.6098000
+47860.00  -0.056142   0.094538  -0.6113724   -0.054600    0.093900   -0.6115700
+47861.00  -0.059499   0.095445  -0.6131492   -0.057800    0.095100   -0.6133100
+47862.00  -0.062559   0.096349  -0.6149856   -0.060800    0.096300   -0.6150900
+47863.00  -0.065327   0.097344  -0.6169418   -0.063700    0.097700   -0.6169800
+47864.00  -0.067830   0.098522  -0.6190600   -0.066400    0.099100   -0.6190500
+47865.00  -0.070117   0.099965  -0.6213521   -0.069000    0.100400   -0.6214400
+47866.00  -0.072305   0.101669  -0.6238043   -0.071500    0.102000   -0.6238700
+47867.00  -0.074486   0.103589  -0.6263590   -0.074000    0.103700   -0.6264000
+47868.00  -0.076739   0.105674  -0.6289126   -0.076500    0.105600   -0.6289500
+47869.00  -0.079122   0.107881  -0.6313409   -0.078900    0.107700   -0.6313800
+47870.00  -0.081630   0.110183  -0.6335356   -0.081300    0.109900   -0.6335700
+47871.00  -0.084241   0.112555  -0.6354462   -0.083700    0.112300   -0.6354900
+47872.00  -0.086932   0.114974  -0.6371037   -0.086200    0.114800   -0.6371500
+47873.00  -0.089614   0.117435  -0.6386064   -0.088800    0.117400   -0.6386400
+47874.00  -0.092151   0.119956  -0.6400823   -0.091100    0.120000   -0.6401300
+47875.00  -0.094464   0.122557  -0.6416399   -0.093500    0.122400   -0.6416800
+47876.00  -0.096596   0.125204  -0.6433545   -0.095800    0.125200   -0.6434200
+47877.00  -0.098647   0.127845  -0.6452473   -0.098100    0.127800   -0.6453100
+47878.00  -0.100700   0.130424  -0.6472936   -0.100200    0.130300   -0.6473600
+47879.00  -0.102791   0.132890  -0.6494431   -0.102300    0.132800   -0.6495200
+47880.00  -0.104932   0.135228  -0.6516350   -0.104300    0.135100   -0.6517000
+47881.00  -0.107038   0.137530  -0.6537996   -0.106300    0.137500   -0.6538500
+47882.00  -0.109166   0.139802  -0.6558744   -0.108600    0.139700   -0.6559100
+47883.00  -0.111425   0.142033  -0.6578097   -0.110900    0.141800   -0.6578200
+47884.00  -0.113908   0.144250  -0.6595674   -0.113200    0.144100   -0.6595900
+47885.00  -0.116617   0.146490  -0.6611365   -0.115800    0.146300   -0.6611500
+47886.00  -0.119446   0.148785  -0.6625434   -0.118400    0.148800   -0.6625900
+47887.00  -0.122271   0.151162  -0.6638408   -0.120900    0.151100   -0.6639200
+47888.00  -0.124968   0.153651  -0.6650994   -0.123500    0.153800   -0.6651700
+47889.00  -0.127413   0.156281  -0.6663989   -0.126200    0.156700   -0.6664800
+47890.00  -0.129524   0.159074  -0.6678172   -0.128600    0.159700   -0.6679000
+47891.00  -0.131349   0.161999  -0.6694241   -0.130600    0.162500   -0.6695100
+47892.00  -0.132974   0.164998   0.3287404   -0.132500    0.165300    0.3286400
+47893.00  -0.134485   0.168017   0.3266860   -0.134100    0.168000    0.3265900
+47894.00  -0.135970   0.170997   0.3244717   -0.135500    0.170600    0.3243500
+47895.00  -0.137516   0.173884   0.3221932   -0.136800    0.173400    0.3221100
+47896.00  -0.139181   0.176642   0.3199771   -0.138200    0.176000    0.3199100
+47897.00  -0.140984   0.179271   0.3179432   -0.139900    0.178800    0.3178800
+47898.00  -0.142938   0.181783   0.3161659   -0.141800    0.181300    0.3160700
+47899.00  -0.145050   0.184190   0.3146584   -0.143800    0.183400    0.3146100
+47900.00  -0.147283   0.186517   0.3133695   -0.146100    0.185800    0.3133200
+47901.00  -0.149527   0.188891   0.3121848   -0.148400    0.188200    0.3121100
+47902.00  -0.151664   0.191448   0.3109700   -0.150600    0.191000    0.3108600
+47903.00  -0.153666   0.194203   0.3096123   -0.152500    0.193700    0.3095300
+47904.00  -0.155469   0.197091   0.3080493   -0.154400    0.196600    0.3079800
+47905.00  -0.157038   0.200038   0.3062812   -0.156200    0.199900    0.3062400
+47906.00  -0.158489   0.203022   0.3043732   -0.157600    0.203200    0.3043100
+47907.00  -0.159972   0.206036   0.3024133   -0.159500    0.206100    0.3023500
+47908.00  -0.161637   0.209075   0.3004836   -0.161100    0.208900    0.3004300
+47909.00  -0.163648   0.212119   0.2986485   -0.162600    0.211200    0.2985800
+47910.00  -0.166171   0.215135   0.2969497   -0.165400    0.214500    0.2968900
+47911.00  -0.169172   0.218109   0.2953954   -0.168400    0.217500    0.2952300
+47912.00  -0.172428   0.221071   0.2939803   -0.172300    0.220900    0.2936200
+47913.00  -0.175694   0.224056   0.2926783   -0.174900    0.223800    0.2925700
+47914.00  -0.178725   0.227102   0.2914388   -0.177600    0.227000    0.2915700
+47915.00  -0.181309   0.230256   0.2901924   -0.180000    0.230000    0.2903300
+47916.00  -0.183495   0.233556   0.2888525   -0.182500    0.233400    0.2889000
+47917.00  -0.185427   0.236998   0.2873251   -0.185100    0.236700    0.2873100
+47918.00  -0.187215   0.240537   0.2855331   -0.187400    0.239900    0.2855600
+47919.00  -0.188973   0.244118   0.2834373   -0.189600    0.243100    0.2835100
+47920.00  -0.190812   0.247664   0.2810477   -0.191700    0.246300    0.2811600
+47921.00  -0.192611   0.251151   0.2784173   -0.193400    0.249600    0.2785100
+47922.00  -0.194191   0.254600   0.2756436   -0.195100    0.253200    0.2757500
+47923.00  -0.195576   0.258070   0.2728727   -0.196100    0.256800    0.2729000
+47924.00  -0.196900   0.261580   0.2702385   -0.196400    0.260600    0.2701800
+47925.00  -0.198266   0.265115   0.2678273   -0.197300    0.264100    0.2678600
+47926.00  -0.199681   0.268675   0.2656487   -0.198600    0.268000    0.2657200
+47927.00  -0.201065   0.272274   0.2636380   -0.200000    0.271900    0.2637700
+47928.00  -0.202333   0.275932   0.2616887   -0.201400    0.275700    0.2617500
+47929.00  -0.203403   0.279667   0.2596837   -0.202800    0.279500    0.2597000
+47930.00  -0.204211   0.283483   0.2575309   -0.203900    0.283200    0.2574600
+47931.00  -0.204694   0.287359   0.2551758   -0.204500    0.287000    0.2550700
+47932.00  -0.204841   0.291287   0.2526216   -0.204300    0.290600    0.2525600
+47933.00  -0.204676   0.295263   0.2499181   -0.203800    0.294500    0.2499100
+47934.00  -0.204224   0.299284   0.2471377   -0.202800    0.298600    0.2471500
+47935.00  -0.203533   0.303354   0.2443607   -0.202200    0.302700    0.2443800
+47936.00  -0.202713   0.307486   0.2416612   -0.201500    0.306700    0.2416800
+47937.00  -0.201903   0.311642   0.2390961   -0.200900    0.310800    0.2390900
+47938.00  -0.201203   0.315725   0.2366996   -0.200500    0.314800    0.2367000
+47939.00  -0.200751   0.319639   0.2344775   -0.200500    0.318800    0.2344600
+47940.00  -0.200722   0.323310   0.2324294   -0.200300    0.322600    0.2324500
+47941.00  -0.201068   0.326771   0.2305399   -0.200400    0.326300    0.2306200
+47942.00  -0.201659   0.330102   0.2287872   -0.200600    0.329800    0.2289000
+47943.00  -0.202289   0.333378   0.2271173   -0.200900    0.333100    0.2272200
+47944.00  -0.202612   0.336678   0.2254160   -0.201300    0.336400    0.2254900
+47945.00  -0.202312   0.340074   0.2235642   -0.200400    0.339400    0.2236000
+47946.00  -0.201390   0.343597   0.2214781   -0.199300    0.342800    0.2214800
+47947.00  -0.199994   0.347250   0.2191223   -0.198100    0.346400    0.2191200
+47948.00  -0.198336   0.351023   0.2165307   -0.197000    0.350000    0.2165100
+47949.00  -0.196637   0.354907   0.2138054   -0.195800    0.353800    0.2138000
+47950.00  -0.195118   0.358888   0.2110894   -0.194700    0.357900    0.2111100
+47951.00  -0.193973   0.362910   0.2085379   -0.193800    0.361900    0.2085800
+47952.00  -0.193306   0.366897   0.2062554   -0.193100    0.365800    0.2063000
+47953.00  -0.192965   0.370776   0.2042577   -0.192500    0.369800    0.2043200
+47954.00  -0.192737   0.374532   0.2024849   -0.192000    0.373700    0.2025600
+47955.00  -0.192439   0.378169   0.2008309   -0.191800    0.377700    0.2009100
+47956.00  -0.192013   0.381747   0.1991734   -0.191000    0.381600    0.1992000
+47957.00  -0.191447   0.385333   0.1973997   -0.190400    0.385100    0.1974000
+47958.00  -0.190752   0.388961   0.1954329   -0.189800    0.388800    0.1954000
+47959.00  -0.189934   0.392658   0.1932407   -0.188800    0.392400    0.1932300
+47960.00  -0.188990   0.396433   0.1908357   -0.187800    0.395700    0.1908200
+47961.00  -0.187975   0.400222   0.1882909   -0.186900    0.399300    0.1882700
+47962.00  -0.186968   0.403938   0.1857013   -0.186100    0.402900    0.1856700
+47963.00  -0.186071   0.407506   0.1831593   -0.185500    0.406600    0.1831000
+47964.00  -0.185394   0.410852   0.1807412   -0.184900    0.410200    0.1806400
+47965.00  -0.184985   0.413929   0.1784922   -0.184800    0.413200    0.1783300
+47966.00  -0.184660   0.416814   0.1763986   -0.184200    0.416100    0.1762300
+47967.00  -0.184220   0.419631   0.1744241   -0.183700    0.419200    0.1743500
+47968.00  -0.183515   0.422474   0.1725242   -0.182800    0.422100    0.1724700
+47969.00  -0.182424   0.425419   0.1706383   -0.181800    0.424900    0.1706200
+47970.00  -0.180871   0.428535   0.1686948   -0.180100    0.428200    0.1687600
+47971.00  -0.178945   0.431863   0.1666247   -0.178400    0.431500    0.1667000
+47972.00  -0.176800   0.435421   0.1643610   -0.176300    0.434900    0.1644100
+47973.00  -0.174577   0.439208   0.1618486   -0.174200    0.438600    0.1618200
+47974.00  -0.172343   0.443146   0.1590562   -0.171900    0.442500    0.1590600
+47975.00  -0.170198   0.447045   0.1559934   -0.169500    0.446100    0.1559800
+47976.00  -0.168148   0.450794   0.1527522   -0.167100    0.449700    0.1527600
+47977.00  -0.166137   0.454332   0.1494856   -0.164900    0.453400    0.1494900
+47978.00  -0.164136   0.457615   0.1463661   -0.162600    0.456800    0.1463300
+47979.00  -0.162161   0.460647   0.1435361   -0.160400    0.460000    0.1435100
+47980.00  -0.160228   0.463506   0.1410660   -0.158300    0.463100    0.1410500
+47981.00  -0.158241   0.466349   0.1389047   -0.156200    0.466100    0.1388900
+47982.00  -0.156117   0.469229   0.1369332   -0.154000    0.469000    0.1369100
+47983.00  -0.153796   0.472157   0.1350106   -0.151900    0.471900    0.1350100
+47984.00  -0.151225   0.475109   0.1330082   -0.149800    0.474800    0.1329900
+47985.00  -0.148374   0.478055   0.1308397   -0.147600    0.477600    0.1308000
+47986.00  -0.145312   0.480999   0.1284925   -0.145300    0.480200    0.1284300
+47987.00  -0.142123   0.483957   0.1260024   -0.142500    0.483200    0.1259600
+47988.00  -0.138849   0.486959   0.1234139   -0.139400    0.486300    0.1233900
+47989.00  -0.135526   0.490037   0.1207829   -0.136300    0.489800    0.1207400
+47990.00  -0.132195   0.493212   0.1181738   -0.132700    0.493100    0.1181400
+47991.00  -0.128937   0.496456   0.1156518   -0.129200    0.496400    0.1156300
+47992.00  -0.125835   0.499714   0.1132670   -0.125500    0.499800    0.1132800
+47993.00  -0.122922   0.502925   0.1110453   -0.122400    0.502900    0.1110100
+47994.00  -0.120184   0.506020   0.1089861   -0.119500    0.506000    0.1089800
+47995.00  -0.117489   0.508907   0.1070738   -0.116800    0.508700    0.1070600
+47996.00  -0.114801   0.511621   0.1052702   -0.114200    0.511600    0.1052700
+47997.00  -0.112127   0.514204   0.1035097   -0.111600    0.514200    0.1035000
+47998.00  -0.109471   0.516685   0.1017159   -0.109200    0.516200    0.1016800
+47999.00  -0.106858   0.519103   0.0998076   -0.106600    0.518400    0.0998100
+48000.00  -0.104324   0.521523   0.0976962   -0.104100    0.520900    0.0977300
+48001.00  -0.101893   0.523999   0.0953261   -0.101700    0.523200    0.0953800
+48002.00  -0.099610   0.526519   0.0926861   -0.099500    0.525300    0.0927600
+48003.00  -0.097463   0.528988   0.0898268   -0.097200    0.527700    0.0899300
+48004.00  -0.095416   0.531306   0.0868628   -0.094900    0.530100    0.0868500
+48005.00  -0.093418   0.533400   0.0839541   -0.092700    0.532300    0.0838600
+48006.00  -0.091348   0.535243   0.0812546   -0.090600    0.534500    0.0811100
+48007.00  -0.089161   0.536945   0.0788778   -0.088400    0.536700    0.0787500
+48008.00  -0.086878   0.538638   0.0768512   -0.086000    0.538500    0.0767500
+48009.00  -0.084572   0.540379   0.0751104   -0.083800    0.540300    0.0750700
+48010.00  -0.082361   0.542122   0.0735487   -0.081600    0.541900    0.0736400
+48011.00  -0.080182   0.543839   0.0720199   -0.079200    0.543400    0.0720700
+48012.00  -0.077877   0.545523   0.0703975   -0.076700    0.545100    0.0704400
+48013.00  -0.075287   0.547166   0.0686133   -0.073900    0.546600    0.0686400
+48014.00  -0.072276   0.548758   0.0666583   -0.070800    0.548100    0.0666600
+48015.00  -0.068759   0.550281   0.0645693   -0.067100    0.549600    0.0645800
+48016.00  -0.064784   0.551772   0.0624088   -0.063000    0.551100    0.0623900
+48017.00  -0.060468   0.553258   0.0602525   -0.058800    0.552700    0.0602400
+48018.00  -0.055942   0.554752   0.0581712   -0.054600    0.554200    0.0581700
+48019.00  -0.051343   0.556267   0.0562209   -0.050100    0.555700    0.0562200
+48020.00  -0.046853   0.557798   0.0544325   -0.045800    0.557300    0.0544100
+48021.00  -0.042609   0.559319   0.0527930   -0.041600    0.558800    0.0527700
+48022.00  -0.038544   0.560777   0.0512772   -0.037200    0.560300    0.0512600
+48023.00  -0.034545   0.562139   0.0498442   -0.032900    0.561800    0.0498300
+48024.00  -0.030505   0.563381   0.0484348   -0.028600    0.563100    0.0484100
+48025.00  -0.026329   0.564505   0.0469792   -0.024200    0.564300    0.0469400
+48026.00  -0.022010   0.565557   0.0453965   -0.019800    0.565300    0.0453300
+48027.00  -0.017588   0.566569   0.0436153   -0.015600    0.566300    0.0435700
+48028.00  -0.013173   0.567518   0.0416069   -0.011300    0.567200    0.0415600
+48029.00  -0.008793   0.568420   0.0393602   -0.007000    0.568000    0.0393400
+48030.00  -0.004462   0.569293   0.0369007   -0.002800    0.568800    0.0368700
+48031.00  -0.000214   0.570103   0.0342940    0.001200    0.569500    0.0342700
+48032.00   0.003913   0.570813   0.0316432    0.005100    0.570100    0.0316000
+48033.00   0.007879   0.571392   0.0290757    0.009200    0.570600    0.0290200
+48034.00   0.011670   0.571830   0.0267069    0.013000    0.571000    0.0266500
+48035.00   0.015380   0.572205   0.0246173    0.016600    0.571100    0.0246100
+48036.00   0.019079   0.572518   0.0228185    0.020300    0.571200    0.0228400
+48037.00   0.022725   0.572767   0.0212270    0.023700    0.571200    0.0212300
+48038.00   0.026334   0.572981   0.0196908    0.027200    0.571300    0.0196800
+48039.00   0.029941   0.573192   0.0180715    0.030800    0.571300    0.0180200
+48040.00   0.033584   0.573433   0.0162917    0.034500    0.571700    0.0162200
+48041.00   0.037283   0.573697   0.0143478    0.038100    0.572000    0.0142600
+48042.00   0.041030   0.573946   0.0122870    0.041900    0.572400    0.0122100
+48043.00   0.044816   0.574165   0.0101794    0.045600    0.572700    0.0101000
+48044.00   0.048642   0.574355   0.0080994    0.049400    0.573000    0.0080500
+48045.00   0.052531   0.574522   0.0061118    0.053300    0.573300    0.0060900
+48046.00   0.056477   0.574617   0.0042663    0.057200    0.573600    0.0042500
+48047.00   0.060427   0.574560   0.0025991    0.061100    0.573700    0.0025500
+48048.00   0.064325   0.574288   0.0011235    0.065000    0.573700    0.0010700
+48049.00   0.068136   0.573790  -0.0001825    0.068900    0.573700   -0.0002400
+48050.00   0.071863   0.573089  -0.0013675    0.072800    0.572500   -0.0014200
+48051.00   0.075621   0.572246  -0.0025001    0.076700    0.571500   -0.0025700
+48052.00   0.079542   0.571331  -0.0036596    0.080600    0.570500   -0.0037300
+48053.00   0.083643   0.570420  -0.0049200    0.084400    0.569500   -0.0049900
+48054.00   0.087869   0.569582  -0.0063350    0.088400    0.568400   -0.0063900
+48055.00   0.092108   0.568860  -0.0079295    0.092200    0.567900   -0.0080100
+48056.00   0.096265   0.568224  -0.0097134    0.096200    0.567300   -0.0098000
+48057.00   0.100309   0.567608  -0.0116770    0.100100    0.566600   -0.0117500
+48058.00   0.104234   0.566950  -0.0137740    0.104100    0.565300   -0.0138400
+48059.00   0.108071   0.566198  -0.0159224    0.108100    0.564300   -0.0159800
+48060.00   0.111870   0.565323  -0.0180150    0.112100    0.563000   -0.0180900
+48061.00   0.115674   0.564316  -0.0199498    0.116100    0.561900   -0.0200200
+48062.00   0.119509   0.563148  -0.0216658    0.119900    0.560700   -0.0217500
+48063.00   0.123347   0.561823  -0.0231539    0.123700    0.559800   -0.0232500
+48064.00   0.127096   0.560361  -0.0244627    0.127300    0.558400   -0.0245600
+48065.00   0.130620   0.558791  -0.0256832    0.130600    0.556900   -0.0257500
+48066.00   0.134018   0.557053  -0.0269483    0.133800    0.555400   -0.0269900
+48067.00   0.137425   0.555162  -0.0283598    0.137100    0.553600   -0.0283900
+48068.00   0.140913   0.553151  -0.0299500    0.140600    0.551900   -0.0299700
+48069.00   0.144519   0.551067  -0.0316821    0.144000    0.549800   -0.0317100
+48070.00   0.148236   0.549015  -0.0334770    0.148100    0.547900   -0.0335000
+48071.00   0.152136   0.547071  -0.0352622    0.152300    0.546000   -0.0352800
+48072.00   0.156303   0.545287  -0.0369802    0.156400    0.544100   -0.0370400
+48073.00   0.160777   0.543635  -0.0385964    0.161100    0.542400   -0.0386700
+48074.00   0.165414   0.542060  -0.0400777    0.165400    0.540500   -0.0401500
+48075.00   0.169947   0.540503  -0.0413918    0.170000    0.539600   -0.0414200
+48076.00   0.174278   0.538913  -0.0425512    0.174600    0.538700   -0.0425100
+48077.00   0.178387   0.537236  -0.0435793    0.179100    0.537200   -0.0435200
+48078.00   0.182250   0.535415  -0.0445130    0.182800    0.535400   -0.0445600
+48079.00   0.185852   0.533390  -0.0454012    0.186200    0.533000   -0.0454800
+48080.00   0.189216   0.531114  -0.0462908    0.189300    0.530300   -0.0463400
+48081.00   0.192463   0.528646  -0.0472579    0.192800    0.527400   -0.0473200
+48082.00   0.195765   0.526086  -0.0483778    0.196300    0.525100   -0.0484700
+48083.00   0.199218   0.523520  -0.0496942    0.199700    0.522400   -0.0497600
+48084.00   0.202743   0.521000  -0.0512015    0.202900    0.520000   -0.0512800
+48085.00   0.206192   0.518522  -0.0528385    0.206000    0.517200   -0.0529500
+48086.00   0.209567   0.516057  -0.0545233    0.209200    0.514500   -0.0546100
+48087.00   0.212890   0.513585  -0.0561489    0.212500    0.511900   -0.0562100
+48088.00   0.216181   0.511092  -0.0576099    0.216100    0.510000   -0.0576800
+48089.00   0.219452   0.508596  -0.0588309    0.219900    0.507900   -0.0588900
+48090.00   0.222704   0.506113  -0.0597892    0.223700    0.505900   -0.0598600
+48091.00   0.225900   0.503614  -0.0605297    0.227400    0.503400   -0.0605700
+48092.00   0.229029   0.501038  -0.0611658    0.230500    0.500700   -0.0612600
+48093.00   0.232094   0.498320  -0.0618410    0.233600    0.497600   -0.0619500
+48094.00   0.235100   0.495415  -0.0626823    0.236200    0.494500   -0.0627700
+48095.00   0.238069   0.492348  -0.0637592    0.238800    0.491200   -0.0638100
+48096.00   0.241052   0.489190  -0.0650623    0.241800    0.488000   -0.0651100
+48097.00   0.244089   0.486004  -0.0665222    0.244900    0.484600   -0.0665400
+48098.00   0.247129   0.482782  -0.0680495    0.248000    0.481400   -0.0680900
+48099.00   0.250068   0.479505  -0.0695657    0.251000    0.478200   -0.0695900
+48100.00   0.252813   0.476174  -0.0710254    0.253800    0.474900   -0.0710300
+48101.00   0.255333   0.472800  -0.0723894    0.256300    0.471800   -0.0724200
+48102.00   0.257658   0.469387  -0.0736311    0.258500    0.468500   -0.0736800
+48103.00   0.259827   0.465943  -0.0747407    0.260500    0.465200   -0.0748300
+48104.00   0.261882   0.462474  -0.0757207    0.262500    0.462100   -0.0757800
+48105.00   0.263860   0.458987  -0.0765851    0.264200    0.457800   -0.0766300
+48106.00   0.265854   0.455485  -0.0773983    0.266000    0.454300   -0.0774500
+48107.00   0.267940   0.451994  -0.0782502    0.268700    0.451400   -0.0782800
+48108.00   0.270121   0.448524  -0.0792279    0.271900    0.448500   -0.0792400
+48109.00   0.272360   0.445084  -0.0804064    0.274300    0.445500   -0.0804500
+48110.00   0.274589   0.441685  -0.0818318    0.276500    0.442500   -0.0818700
+48111.00   0.276741   0.438343  -0.0835090    0.278200    0.439000   -0.0835500
+48112.00   0.278754   0.435072  -0.0853967    0.279800    0.435300   -0.0854300
+48113.00   0.280596   0.431901  -0.0874084    0.281200    0.431200   -0.0874800
+48114.00   0.282279   0.428841  -0.0894342    0.282600    0.427500   -0.0894900
+48115.00   0.283818   0.425877  -0.0913622    0.284000    0.424500   -0.0914600
+48116.00   0.285247   0.422970  -0.0931091    0.285700    0.421600   -0.0933000
+48117.00   0.286585   0.420014  -0.0946352    0.286900    0.418600   -0.0948000
+48118.00   0.287859   0.416916  -0.0959629    0.288200    0.416000   -0.0960600
+48119.00   0.289172   0.413704  -0.0971804    0.290000    0.413000   -0.0972400
+48120.00   0.290686   0.410418  -0.0984078    0.291700    0.409300   -0.0984100
+48121.00   0.292427   0.407051  -0.0997677    0.293400    0.405500   -0.0998400
+48122.00   0.294320   0.403618  -0.1013457    0.295400    0.401900   -0.1014400
+48123.00   0.296284   0.400149  -0.1031677    0.297500    0.398400   -0.1032600
+48124.00   0.298236   0.396673  -0.1051968    0.299600    0.395700   -0.1053400
+48125.00   0.300054   0.393217  -0.1073506    0.301500    0.392900   -0.1074500
+48126.00   0.301644   0.389767  -0.1095274    0.303000    0.389800   -0.1096500
+48127.00   0.302975   0.386306  -0.1116384    0.304100    0.386400   -0.1117600
+48128.00   0.304034   0.382824  -0.1136104    0.305000    0.382300   -0.1137100
+48129.00   0.304812   0.379313  -0.1153995    0.305800    0.378400   -0.1154700
+48130.00   0.305343   0.375769  -0.1169930    0.305800    0.375100   -0.1170600
+48131.00   0.305706   0.372194  -0.1184076    0.306000    0.371900   -0.1184500
+48132.00   0.305957   0.368585  -0.1196803    0.306200    0.368500   -0.1197400
+48133.00   0.306169   0.364943  -0.1208648    0.306400    0.364700   -0.1209200
+48134.00   0.306493   0.361281  -0.1220331    0.307000    0.360600   -0.1220800
+48135.00   0.307079   0.357616  -0.1232639    0.307700    0.356600   -0.1233000
+48136.00   0.307923   0.353948  -0.1246436    0.308300    0.352500   -0.1246200
+48137.00   0.308928   0.350259  -0.1262465    0.309300    0.348600   -0.1261700
+48138.00   0.309992   0.346527  -0.1281148    0.310300    0.344800   -0.1280700
+48139.00   0.311003   0.342728  -0.1302441    0.311700    0.341400   -0.1303100
+48140.00   0.311833   0.338838  -0.1325698    0.312100    0.337500   -0.1327600
+48141.00   0.312470   0.334859  -0.1349571    0.312800    0.333600   -0.1351200
+48142.00   0.312954   0.330804  -0.1372534    0.313500    0.329700   -0.1374100
+48143.00   0.313259   0.326689  -0.1393367    0.313600    0.325700   -0.1394800
+48144.00   0.313337   0.322545  -0.1411452    0.313700    0.321600   -0.1412500
+48145.00   0.313177   0.318438  -0.1426925    0.313700    0.317500   -0.1427300
+48146.00   0.312883   0.314378  -0.1440792    0.313400    0.313500   -0.1441000
+48147.00   0.312523   0.310356  -0.1454500    0.312900    0.309400   -0.1454700
+48148.00   0.312119   0.306392  -0.1469374    0.312600    0.305600   -0.1469700
+48149.00   0.311661   0.302501  -0.1486353    0.311800    0.301500   -0.1486700
+48150.00   0.311131   0.298699  -0.1505805    0.310800    0.297400   -0.1505900
+48151.00   0.310531   0.294983  -0.1527464    0.310000    0.293700   -0.1527900
+48152.00   0.309871   0.291347  -0.1550642    0.309500    0.290500   -0.1551600
+48153.00   0.309160   0.287783  -0.1574408    0.309400    0.287000   -0.1575100
+48154.00   0.308393   0.284282  -0.1597815    0.309100    0.283700   -0.1598600
+48155.00   0.307506   0.280822  -0.1620083    0.308700    0.280400   -0.1620200
+48156.00   0.306397   0.277373  -0.1640705    0.307900    0.277000   -0.1641000
+48157.00   0.305056   0.273887  -0.1659581    0.306500    0.273600   -0.1660200
+48158.00   0.303574   0.270303  -0.1676926    0.304900    0.270000   -0.1677500
+48159.00   0.302063   0.266557  -0.1693171    0.303100    0.266300   -0.1694200
+48160.00   0.300634   0.262617  -0.1708895    0.301000    0.262200   -0.1710400
+48161.00   0.299388   0.258587  -0.1724761    0.299600    0.257900   -0.1726200
+48162.00   0.298364   0.254585  -0.1741494    0.298000    0.253500   -0.1742800
+48163.00   0.297561   0.250709  -0.1759802    0.297700    0.249800   -0.1760800
+48164.00   0.296905   0.247030  -0.1780282    0.297700    0.246300   -0.1781200
+48165.00   0.296302   0.243594  -0.1803265    0.297400    0.243000   -0.1804100
+48166.00   0.295654   0.240360  -0.1828631    0.297000    0.240100   -0.1829400
+48167.00   0.294851   0.237241  -0.1855792    0.295900    0.236900   -0.1856200
+48168.00   0.293782   0.234151  -0.1883677    0.294300    0.233700   -0.1884200
+48169.00   0.292376   0.230984  -0.1910975    0.292300    0.230000   -0.1911500
+48170.00   0.290636   0.227640  -0.1936458    0.290100    0.226000   -0.1937100
+48171.00   0.288711   0.224110  -0.1959332    0.287700    0.221900   -0.1960100
+48172.00   0.286692   0.220434  -0.1979555    0.285800    0.218400   -0.1980200
+48173.00   0.284630   0.216660  -0.1997832    0.283800    0.214900   -0.1998800
+48174.00   0.282572   0.212839  -0.2015301    0.282000    0.211800   -0.2016300
+48175.00   0.280541   0.209022  -0.2033154    0.280300    0.208800   -0.2033300
+48176.00   0.278421   0.205271  -0.2052338    0.278700    0.205400   -0.2052200
+48177.00   0.276142   0.201622  -0.2073263    0.276800    0.202000   -0.2073700
+48178.00   0.273732   0.198072  -0.2095793    0.274400    0.198200   -0.2096700
+48179.00   0.271236   0.194613  -0.2119396    0.271700    0.194200   -0.2120200
+48180.00   0.268687   0.191236  -0.2143357    0.269000    0.190700   -0.2143600
+48181.00   0.266124   0.187938  -0.2166969    0.266300    0.187300   -0.2167500
+48182.00   0.263546   0.184709  -0.2189627    0.263500    0.184100   -0.2190000
+48183.00   0.260909   0.181498  -0.2210914    0.260700    0.180900   -0.2211300
+48184.00   0.258171   0.178283  -0.2230666    0.258000    0.178100   -0.2231500
+48185.00   0.255334   0.175151  -0.2248874    0.255400    0.175300   -0.2249700
+48186.00   0.252529   0.172099  -0.2265925    0.252600    0.172300   -0.2266200
+48187.00   0.249944   0.169070  -0.2282489    0.250000    0.169100   -0.2282900
+48188.00   0.247695   0.166030  -0.2299310    0.247600    0.165700   -0.2300200
+48189.00   0.245667   0.163016  -0.2316994    0.245400    0.162000   -0.2317700
+48190.00   0.243703   0.160079  -0.2336061    0.244100    0.158900   -0.2337400
+48191.00   0.241754   0.157249  -0.2356992    0.242200    0.155800   -0.2357700
+48192.00   0.239851   0.154550  -0.2380273    0.240300    0.153400   -0.2381500
+48193.00   0.238015   0.152003  -0.2406142    0.238600    0.151400   -0.2406500
+48194.00   0.236208   0.149592  -0.2434364    0.236800    0.149200   -0.2435300
+48195.00   0.234410   0.147255  -0.2464136    0.235100    0.147300   -0.2465500
+48196.00   0.232557   0.144959  -0.2494178    0.233000    0.144000   -0.2494400
+48197.00   0.230548   0.142681  -0.2523024    0.231200    0.141800   -0.2522500
+48198.00   0.228263   0.140412  -0.2549381    0.228500    0.139400   -0.2549800
+48199.00   0.225562   0.138140  -0.2572554    0.226000    0.137100   -0.2573500
+48200.00   0.222305   0.135834  -0.2592738    0.222400    0.134500   -0.2594700
+48201.00   0.218641   0.133500  -0.2611209    0.218900    0.132000   -0.2611900
+48202.00   0.214857   0.131159  -0.2629680    0.214800    0.129500   -0.2631600
+48203.00   0.211202   0.128824  -0.2649608    0.211000    0.127600   -0.2650800
+48204.00   0.207788   0.126509  -0.2671750    0.207300    0.125300   -0.2672500
+48205.00   0.204666   0.124230  -0.2696089    0.203900    0.123000   -0.2697100
+48206.00   0.201775   0.121988  -0.2721936    0.201100    0.120800   -0.2724300
+48207.00   0.199017   0.119764  -0.2748376    0.198000    0.118600   -0.2750100
+48208.00   0.196297   0.117541  -0.2774490    0.195400    0.116400   -0.2775800
+48209.00   0.193519   0.115309  -0.2799492    0.192800    0.113800   -0.2800400
+48210.00   0.190608   0.113086  -0.2822820    0.189900    0.111800   -0.2823400
+48211.00   0.187568   0.110916  -0.2844222    0.186900    0.109500   -0.2844000
+48212.00   0.184445   0.108853  -0.2863721    0.183900    0.107900   -0.2863600
+48213.00   0.181286   0.106953  -0.2881592    0.180700    0.106100   -0.2881300
+48214.00   0.178131   0.105240  -0.2898352    0.177700    0.104400   -0.2898400
+48215.00   0.175047   0.103600  -0.2914843    0.174700    0.102800   -0.2915300
+48216.00   0.172026   0.102002  -0.2931847    0.171500    0.101200   -0.2932900
+48217.00   0.169017   0.100466  -0.2949979    0.168400    0.099600   -0.2951400
+48218.00   0.165974   0.098992  -0.2969738    0.165400    0.097800   -0.2970900
+48219.00   0.162854   0.097582  -0.2991467    0.162300    0.096300   -0.2992100
+48220.00   0.159599   0.096223  -0.3015319    0.159200    0.094800   -0.3015500
+48221.00   0.156136   0.094901  -0.3041180    0.155800    0.093300   -0.3041400
+48222.00   0.152413   0.093609  -0.3068584    0.152200    0.092400   -0.3068700
+48223.00   0.148427   0.092345  -0.3096706    0.147900    0.091200   -0.3097300
+48224.00   0.144337   0.091103  -0.3124545    0.143600    0.090000   -0.3125400
+48225.00   0.140317   0.089885  -0.3151098    0.139300    0.088800   -0.3152100
+48226.00   0.136535   0.088739  -0.3175645    0.135500    0.087700   -0.3176400
+48227.00   0.132960   0.087668  -0.3198018    0.131700    0.086600   -0.3198800
+48228.00   0.129504   0.086654  -0.3218807    0.128400    0.085500   -0.3219400
+48229.00   0.126079   0.085679  -0.3239147    0.125100    0.084500   -0.3240300
+48230.00   0.122590   0.084722  -0.3260221    0.121500    0.083500   -0.3261200
+48231.00   0.119050   0.083780  -0.3282816    0.117900    0.082600   -0.3284000
+48232.00   0.115520   0.082857  -0.3307054    0.114300    0.081700   -0.3308400
+48233.00   0.112032   0.081940  -0.3332465    0.110800    0.080800   -0.3333800
+48234.00   0.108594   0.081004  -0.3358221    0.107300    0.079900   -0.3359400
+48235.00   0.105159   0.080000  -0.3383410    0.103800    0.078900   -0.3384200
+48236.00   0.101696   0.078953  -0.3407106    0.100400    0.077900   -0.3407500
+48237.00   0.098177   0.077921  -0.3428633    0.097100    0.076900   -0.3429000
+48238.00   0.094582   0.076908  -0.3447823    0.093700    0.075800   -0.3448300
+48239.00   0.090989   0.075839  -0.3464901    0.090400    0.074700   -0.3465700
+48240.00   0.087493   0.074656  -0.3480344    0.087200    0.073500   -0.3481300
+48241.00   0.084124   0.073460  -0.3494722    0.083900    0.072500   -0.3495700
+48242.00   0.080833   0.072344  -0.3508638    0.080600    0.071500   -0.3509700
+48243.00   0.077561   0.071380  -0.3522759    0.077200    0.070600   -0.3523800
+48244.00   0.074250   0.070638  -0.3537777    0.073700    0.069800   -0.3538900
+48245.00   0.070866   0.070146  -0.3554434    0.070200    0.069200   -0.3555600
+48246.00   0.067377   0.069860  -0.3573110    0.066500    0.068600   -0.3574000
+48247.00   0.063775   0.069730  -0.3593874    0.062800    0.068200   -0.3594600
+48248.00   0.060069   0.069705  -0.3616542    0.058900    0.068000   -0.3617100
+48249.00   0.056270   0.069732  -0.3640664    0.055000    0.067800   -0.3641200
+48250.00   0.052379   0.069786  -0.3665589    0.050900    0.067700   -0.3666200
+48251.00   0.048355   0.069869  -0.3690509    0.046900    0.067700   -0.3691300
+48252.00   0.044145   0.069989  -0.3714556    0.042800    0.067800   -0.3715300
+48253.00   0.039730   0.070144  -0.3737009    0.038700    0.067900   -0.3737700
+48254.00   0.035225   0.070309  -0.3757491    0.034600    0.068100   -0.3757900
+48255.00   0.030776   0.070470  -0.3776271    0.030700    0.068400   -0.3776600
+48256.00   0.026474   0.070678  -0.3794330    0.026900    0.068800   -0.3794600
+48257.00   0.022389   0.070986   0.6186975    0.023100    0.069300    0.6186700
+48258.00   0.018591   0.071447   0.6166447    0.019500    0.070000    0.6166000
+48259.00   0.015151   0.072113   0.6143495    0.016100    0.070700    0.6142800
+48260.00   0.012118   0.073018   0.6118302    0.013200    0.072200    0.6117600
+48261.00   0.009382   0.074132   0.6091699    0.010000    0.073200    0.6091200
+48262.00   0.006782   0.075384   0.6064782    0.006800    0.074300    0.6064400
+48263.00   0.004177   0.076691   0.6038514    0.003600    0.075500    0.6038400
+48264.00   0.001418   0.077970   0.6013588    0.000400    0.076600    0.6013600
+48265.00  -0.001661   0.079172   0.5990451   -0.002800    0.077800    0.5990600
+48266.00  -0.005050   0.080296   0.5969117   -0.006100    0.078800    0.5969200
+48267.00  -0.008653   0.081354   0.5949329   -0.009500    0.079800    0.5949300
+48268.00  -0.012377   0.082340   0.5930695   -0.013000    0.080700    0.5930700
+48269.00  -0.016122   0.083186   0.5912743   -0.016600    0.081500    0.5912800
+48270.00  -0.019806   0.083830   0.5894949   -0.020300    0.082100    0.5895000
+48271.00  -0.023464   0.084317   0.5876705   -0.024000    0.082700    0.5876600
+48272.00  -0.027175   0.084736   0.5857450   -0.027700    0.083300    0.5857400
+48273.00  -0.031011   0.085171   0.5836807   -0.031400    0.083700    0.5836800
+48274.00  -0.034995   0.085646   0.5814692   -0.035100    0.084200    0.5814600
+48275.00  -0.039044   0.086098   0.5791302   -0.038700    0.084800    0.5791000
+48276.00  -0.043017   0.086553   0.5766972   -0.042200    0.085400    0.5766400
+48277.00  -0.046776   0.087092   0.5742211   -0.045600    0.086100    0.5741300
+48278.00  -0.050215   0.087788   0.5717685   -0.049000    0.086900    0.5716400
+48279.00  -0.053236   0.088712   0.5694044   -0.052200    0.087800    0.5692800
+48280.00  -0.055812   0.089927   0.5671813   -0.055300    0.088900    0.5670700
+48281.00  -0.058173   0.091415   0.5651398   -0.058500    0.090200    0.5650600
+48282.00  -0.060588   0.093097   0.5632680   -0.061800    0.091500    0.5632300
+48283.00  -0.063289   0.094881   0.5614935   -0.065100    0.092900    0.5614900
+48284.00  -0.066451   0.096671   0.5597015   -0.068600    0.094400    0.5597000
+48285.00  -0.070208   0.098382   0.5577729   -0.072100    0.096000    0.5577700
+48286.00  -0.074442   0.100022   0.5556263   -0.075800    0.097500    0.5556000
+48287.00  -0.078910   0.101594   0.5532423   -0.079600    0.099100    0.5531700
+48288.00  -0.083389   0.103081   0.5506707   -0.083500    0.100600    0.5505600
+48289.00  -0.087740   0.104469   0.5480040   -0.087400    0.102200    0.5478600
+48290.00  -0.091885   0.105752   0.5453487   -0.090900    0.103500    0.5452100
+48291.00  -0.095784   0.106978   0.5428091   -0.094400    0.104800    0.5426800
+48292.00  -0.099377   0.108224   0.5404512   -0.097900    0.106200    0.5403600
+48293.00  -0.102658   0.109555   0.5382971   -0.101500    0.107800    0.5382100
+48294.00  -0.105703   0.110999   0.5363232   -0.105000    0.109400    0.5362300
+48295.00  -0.108620   0.112573   0.5344856   -0.108400    0.111100    0.5343900
+48296.00  -0.111491   0.114302   0.5327295   -0.111700    0.112900    0.5326300
+48297.00  -0.114367   0.116185   0.5309856   -0.114900    0.114800    0.5308900
+48298.00  -0.117315   0.118198   0.5291822   -0.118000    0.116900    0.5290900
+48299.00  -0.120404   0.120310   0.5272551   -0.121100    0.119100    0.5271700
+48300.00  -0.123664   0.122513   0.5251586   -0.124100    0.121400    0.5251000
+48301.00  -0.126908   0.124910   0.5228707   -0.127100    0.123900    0.5228300
+48302.00  -0.130112   0.127563   0.5203904   -0.130100    0.126500    0.5203900
+48303.00  -0.133270   0.130449   0.5177638   -0.133100    0.129200    0.5177900
+48304.00  -0.136368   0.133521   0.5150737   -0.136100    0.132000    0.5151300
+48305.00  -0.139405   0.136727   0.5124253   -0.139100    0.134900    0.5124700
+48306.00  -0.142389   0.140004   0.5099051   -0.142200    0.137800    0.5099100
+48307.00  -0.145325   0.143291   0.5075665   -0.145300    0.140800    0.5075200
+48308.00  -0.148250   0.146514   0.5054215   -0.148300    0.143800    0.5053200
+48309.00  -0.151190   0.149542   0.5034249   -0.151300    0.146800    0.5033000
+48310.00  -0.154175   0.152268   0.5014858   -0.154300    0.149800    0.5013600
+48311.00  -0.157177   0.154778   0.4995116   -0.157100    0.152800    0.4994000
+48312.00  -0.160098   0.157240   0.4974054   -0.159900    0.155700    0.4973000
+48313.00  -0.162850   0.159794   0.4950844   -0.162600    0.158600    0.4949800
+48314.00  -0.165376   0.162467   0.4925069   -0.165200    0.161500    0.4923900
+48315.00  -0.167647   0.165250   0.4896908   -0.167700    0.164300    0.4895600
+48316.00  -0.169720   0.168114   0.4867258   -0.170100    0.167200    0.4866100
+48317.00  -0.171679   0.171052   0.4837438   -0.172400    0.170100    0.4836600
+48318.00  -0.173596   0.174060   0.4808788   -0.174500    0.173000    0.4808300
+48319.00  -0.175545   0.177130   0.4782346   -0.176500    0.175900    0.4782300
+48320.00  -0.177585   0.180250   0.4758656   -0.178400    0.179300    0.4758600
+48321.00  -0.179691   0.183430   0.4737648   -0.180200    0.182700    0.4737500
+48322.00  -0.181814   0.186689   0.4718903   -0.181900    0.186200    0.4718600
+48323.00  -0.183873   0.190040   0.4701765   -0.183500    0.189700    0.4701000
+48324.00  -0.185715   0.193494   0.4685319   -0.185200    0.193200    0.4684200
+48325.00  -0.187247   0.197079   0.4668623   -0.186800    0.196700    0.4667300
+48326.00  -0.188552   0.200801   0.4650913   -0.188400    0.200300    0.4649500
+48327.00  -0.189749   0.204643   0.4631528   -0.189900    0.203900    0.4630100
+48328.00  -0.190961   0.208577   0.4610003   -0.191400    0.207600    0.4608400
+48329.00  -0.192341   0.212539   0.4586217   -0.192800    0.211300    0.4584300
+48330.00  -0.193994   0.216441   0.4560330   -0.194200    0.215000    0.4557900
+48331.00  -0.195667   0.220202   0.4532397   -0.195600    0.218700    0.4529900
+48332.00  -0.197292   0.223842   0.4503304   -0.197000    0.222400    0.4501100
+48333.00  -0.198813   0.227397   0.4474393   -0.198400    0.226100    0.4472800
+48334.00  -0.200148   0.230902   0.4446940   -0.199700    0.229900    0.4445900
+48335.00  -0.201247   0.234395   0.4421798   -0.201100    0.233600    0.4421300
+48336.00  -0.202195   0.237934   0.4399037   -0.202600    0.237300    0.4398900
+48337.00  -0.203113   0.241573   0.4378071   -0.204000    0.241100    0.4378100
+48338.00  -0.204155   0.245328   0.4357970   -0.205400    0.245000    0.4358000
+48339.00  -0.205483   0.249211   0.4337687   -0.206900    0.248800    0.4337400
+48340.00  -0.207237   0.253232   0.4316295   -0.208400    0.252800    0.4315400
+48341.00  -0.209344   0.257362   0.4292805   -0.209800    0.256700    0.4291300
+48342.00  -0.211542   0.261519   0.4266726   -0.211300    0.260700    0.4265000
+48343.00  -0.213596   0.265659   0.4238689   -0.212600    0.264700    0.4237100
+48344.00  -0.215298   0.269752   0.4209839   -0.214000    0.268800    0.4208500
+48345.00  -0.216509   0.273776   0.4181445   -0.215100    0.272900    0.4180100
+48346.00  -0.217320   0.277756   0.4154460   -0.216200    0.277000    0.4152800
+48347.00  -0.217857   0.281739   0.4129329   -0.217200    0.281000    0.4127500
+48348.00  -0.218249   0.285770   0.4106103   -0.218100    0.285200    0.4104000
+48349.00  -0.218610   0.289880   0.4084511   -0.218800    0.289300    0.4082400
+48350.00  -0.219006   0.294038   0.4064165   -0.219600    0.293400    0.4062000
+48351.00  -0.219449   0.298196   0.4044592   -0.220200    0.297300    0.4042500
+48352.00  -0.219906   0.302322   0.4025264   -0.220600    0.301400    0.4023300
+48353.00  -0.220303   0.306406   0.4005663   -0.220700    0.305400    0.4004000
+48354.00  -0.220558   0.310445   0.3985331   -0.220700    0.309400    0.3983700
+48355.00  -0.220598   0.314438   0.3963880   -0.220400    0.313400    0.3962200
+48356.00  -0.220373   0.318404   0.3940960   -0.219900    0.317500    0.3939200
+48357.00  -0.219857   0.322358   0.3916419   -0.219300    0.321500    0.3914500
+48358.00  -0.219056   0.326309   0.3890362   -0.218600    0.325500    0.3888200
+48359.00  -0.218014   0.330253   0.3863229   -0.217800    0.329500    0.3861200
+48360.00  -0.216806   0.334184   0.3835812   -0.216900    0.333500    0.3834300
+48361.00  -0.215546   0.338103   0.3809266   -0.216000    0.337400    0.3808300
+48362.00  -0.214356   0.342027   0.3784616   -0.215200    0.341400    0.3784200
+48363.00  -0.213352   0.345978   0.3762352   -0.214500    0.345300    0.3762400
+48364.00  -0.212598   0.349971   0.3742255   -0.213800    0.349200    0.3742100
+48365.00  -0.212116   0.353997   0.3723417   -0.213200    0.353200    0.3722700
+48366.00  -0.211712   0.357991   0.3704127   -0.212800    0.357100    0.3702800
+48367.00  -0.211353   0.361955   0.3683187   -0.212400    0.361000    0.3681400
+48368.00  -0.211093   0.365896   0.3660009   -0.212200    0.365000    0.3657900
+48369.00  -0.210987   0.369820   0.3634567   -0.212000    0.368900    0.3632200
+48370.00  -0.211028   0.373708   0.3607315   -0.211900    0.372700    0.3605000
+48371.00  -0.211077   0.377499   0.3579095   -0.211800    0.376600    0.3576800
+48372.00  -0.211001   0.381195   0.3550906   -0.211700    0.380400    0.3548800
+48373.00  -0.210716   0.384817   0.3523675   -0.211500    0.384200    0.3521800
+48374.00  -0.210235   0.388395   0.3498073   -0.211200    0.388000    0.3496500
+48375.00  -0.209581   0.391966   0.3474433   -0.210700    0.391700    0.3473000
+48376.00  -0.208780   0.395564   0.3452739   -0.210000    0.395400    0.3451300
+48377.00  -0.207855   0.399210   0.3432674   -0.209200    0.399100    0.3431200
+48378.00  -0.206791   0.402890   0.3413683   -0.208200    0.402800    0.3412100
+48379.00  -0.205572   0.406589   0.3395114   -0.207000    0.406500    0.3393200
+48380.00  -0.204205   0.410310   0.3376298   -0.205400    0.409500    0.3374200
+48381.00  -0.202702   0.414042   0.3356575   -0.203900    0.413200    0.3354200
+48382.00  -0.201075   0.417773   0.3335389   -0.202400    0.417000    0.3332900
+48383.00  -0.199327   0.421520   0.3312343   -0.200700    0.420700    0.3309700
+48384.00  -0.197475   0.425296   0.3287302   -0.198900    0.424400    0.3284700
+48385.00  -0.195569   0.429075   0.3260494   -0.197000    0.428200    0.3257900
+48386.00  -0.193643   0.432845   0.3232425   -0.195100    0.431900    0.3229800
+48387.00  -0.191707   0.436597   0.3203892   -0.193000    0.435600    0.3201200
+48388.00  -0.189725   0.440306   0.3175869   -0.190700    0.439200    0.3173100
+48389.00  -0.187655   0.443949   0.3149288   -0.188400    0.442800    0.3146500
+48390.00  -0.185453   0.447502   0.3124747   -0.185900    0.446400    0.3122100
+48391.00  -0.183061   0.450942   0.3102256   -0.183200    0.449800    0.3099900
+48392.00  -0.180442   0.454273   0.3081325   -0.180500    0.453200    0.3079300
+48393.00  -0.177606   0.457530   0.3061030   -0.177600    0.456500    0.3059200
+48394.00  -0.174586   0.460741   0.3040388   -0.174600    0.459700    0.3038700
+48395.00  -0.171472   0.463903   0.3018647   -0.171700    0.462800    0.3017100
+48396.00  -0.168371   0.467004   0.2995630   -0.168700    0.465900    0.2994200
+48397.00  -0.165388   0.470030   0.2971748   -0.165700    0.468900    0.2970500
+48398.00  -0.162556   0.472974   0.2947821   -0.162800    0.471900    0.2946900
+48399.00  -0.159759   0.475856   0.2924858   -0.159800    0.474800    0.2924200
+48400.00  -0.156924   0.478719   0.2903538   -0.156900    0.477700    0.2902800
+48401.00  -0.154015   0.481596   0.2884229   -0.154000    0.480600    0.2883200
+48402.00  -0.151055   0.484485   0.2866991   -0.151100    0.483400    0.2865400
+48403.00  -0.148081   0.487372   0.2851582   -0.148200    0.486200    0.2849100
+48404.00  -0.145115   0.490241   0.2837485   -0.145200    0.489000    0.2834100
+48405.00  -0.142177   0.493080   0.2824062   -0.142300    0.491800    0.2819600
+48406.00  -0.139273   0.495891   0.2810759   -0.139400    0.494600    0.2805200
+48407.00  -0.136397   0.498678   0.2797012   -0.136400    0.497400    0.2790300
+48408.00  -0.133530   0.501446   0.2782301   -0.133300    0.500200    0.2774600
+48409.00  -0.130632   0.504185   0.2766170   -0.130200    0.502900    0.2758000
+48410.00  -0.127650   0.506887   0.2748345   -0.127300    0.505700    0.2751600
+48411.00  -0.124536   0.509546   0.2728759   -0.124100    0.508500    0.2730300
+48412.00  -0.121236   0.512145   0.2707460   -0.120800    0.511200    0.2707400
+48413.00  -0.117799   0.514711   0.2684654   -0.117500    0.513900    0.2683000
+48414.00  -0.114309   0.517299   0.2660808   -0.114000    0.516500    0.2657700
+48415.00  -0.110827   0.519947   0.2636634   -0.110500    0.519100    0.2633500
+48416.00  -0.107321   0.522631   0.2613040   -0.106900    0.521700    0.2610100
+48417.00  -0.103738   0.525310   0.2590792   -0.103200    0.524200    0.2588000
+48418.00  -0.100023   0.527945   0.2570190   -0.099400    0.526700    0.2567700
+48419.00  -0.096172   0.530474   0.2551011   -0.095600    0.529000    0.2549000
+48420.00  -0.092407   0.532808   0.2532746   -0.091800    0.531300    0.2530800
+48421.00  -0.088697   0.534938   0.2514330   -0.088100    0.533500    0.2512000
+48422.00  -0.084948   0.536894   0.2494815   -0.084400    0.535600    0.2492100
+48423.00  -0.081217   0.538697   0.2473810   -0.080700    0.537500    0.2470600
+48424.00  -0.077580   0.540381   0.2451650   -0.077200    0.539300    0.2448100
+48425.00  -0.074071   0.542020   0.2429220   -0.073700    0.541100    0.2425200
+48426.00  -0.070701   0.543663   0.2407553   -0.070300    0.542700    0.2403400
+48427.00  -0.067473   0.545292   0.2387508   -0.067100    0.544300    0.2383200
+48428.00  -0.064420   0.546876   0.2369620   -0.063900    0.545900    0.2365500
+48429.00  -0.061563   0.548392   0.2354087   -0.060900    0.547300    0.2350300
+48430.00  -0.058826   0.549874   0.2340892   -0.057800    0.548800    0.2337300
+48431.00  -0.056103   0.551379   0.2329812   -0.054800    0.550300    0.2326600
+48432.00  -0.053290   0.552965   0.2320435   -0.051700    0.551800    0.2317300
+48433.00  -0.050301   0.554667   0.2312179   -0.048700    0.553200    0.2309100
+48434.00  -0.047131   0.556431   0.2304329   -0.045600    0.554700    0.2301000
+48435.00  -0.043799   0.558138   0.2296136   -0.042500    0.556200    0.2292700
+48436.00  -0.040312   0.559642   0.2286955   -0.039300    0.557600    0.2283500
+48437.00  -0.036690   0.560847   0.2276412   -0.036000    0.559000    0.2272900
+48438.00  -0.033013   0.561856   0.2264439   -0.032600    0.560300    0.2260700
+48439.00  -0.029366   0.562824   0.2251163   -0.029100    0.561600    0.2247200
+48440.00  -0.025727   0.563843   0.2236695   -0.025000    0.563100    0.2234700
+48441.00  -0.021941   0.564872   0.2221343   -0.021200    0.564100    0.2219200
+48442.00  -0.017994   0.565876   0.2205824   -0.017400    0.565000    0.2203700
+48443.00  -0.013950   0.566824   0.2190993   -0.013500    0.565900    0.2189100
+48444.00  -0.009878   0.567683   0.2177630   -0.009600    0.566700    0.2176000
+48445.00  -0.005846   0.568421   0.2166216   -0.005700    0.567400    0.2164800
+48446.00  -0.001914   0.569021   0.2156705   -0.001700    0.568100    0.2155300
+48447.00   0.001903   0.569477   0.2148371    0.002300    0.568700    0.2146700
+48448.00   0.005725   0.569812   0.2139795    0.006300    0.569200    0.2137800
+48449.00   0.009670   0.570109   0.2129437    0.010300    0.569700    0.2127100
+48450.00   0.013729   0.570442   0.2116343    0.014400    0.570200    0.2113800
+48451.00   0.017946   0.570858   0.2100398    0.018700    0.570600    0.2097900
+48452.00   0.022375   0.571352   0.2082363    0.023000    0.570900    0.2080100
+48453.00   0.026968   0.571904   0.2063631    0.027400    0.571200    0.2061600
+48454.00   0.031649   0.572418   0.2045564    0.031800    0.571500    0.2043600
+48455.00   0.036358   0.572701   0.2029001    0.036400    0.571700    0.2027300
+48456.00   0.041044   0.572782   0.2014419    0.041000    0.571900    0.2012900
+48457.00   0.045589   0.572739   0.2002059    0.045600    0.572000    0.2000600
+48458.00   0.050029   0.572650   0.1991700    0.050300    0.572000    0.1990200
+48459.00   0.054497   0.572540   0.1982781    0.054900    0.572000    0.1981300
+48460.00   0.059109   0.572417   0.1974633    0.059500    0.571900    0.1973100
+48461.00   0.063817   0.572247   0.1966611    0.064000    0.571700    0.1965100
+48462.00   0.068502   0.572009   0.1958101    0.068500    0.571500    0.1956600
+48463.00   0.073105   0.571718   0.1948501    0.072800    0.571200    0.1947100
+48464.00   0.077590   0.571383   0.1937368    0.076900    0.570800    0.1936000
+48465.00   0.081901   0.571007   0.1924553    0.081000    0.570400    0.1923400
+48466.00   0.085971   0.570583   0.1910240    0.084800    0.569800    0.1909400
+48467.00   0.089710   0.570085   0.1895032    0.088500    0.569200    0.1894300
+48468.00   0.093032   0.569494   0.1879815    0.092000    0.568400    0.1878800
+48469.00   0.096042   0.568777   0.1865172    0.095400    0.567600    0.1863600
+48470.00   0.098933   0.567909   0.1851435    0.098700    0.566700    0.1849200
+48471.00   0.101871   0.566886   0.1838886    0.101900    0.565600    0.1836600
+48472.00   0.104958   0.565705   0.1827794    0.105100    0.564500    0.1825800
+48473.00   0.108217   0.564427   0.1818143    0.108400    0.563400    0.1816700
+48474.00   0.111662   0.563106   0.1809531    0.112300    0.562700    0.1807900
+48475.00   0.115248   0.561778   0.1801100    0.115600    0.561500    0.1799900
+48476.00   0.118816   0.560444   0.1791690    0.118900    0.560200    0.1790600
+48477.00   0.122395   0.559084   0.1780101    0.122300    0.558900    0.1778800
+48478.00   0.126042   0.557680   0.1765680    0.125800    0.557500    0.1764200
+48479.00   0.129721   0.556237   0.1748620    0.129300    0.556000    0.1746800
+48480.00   0.133366   0.554770   0.1729817    0.132700    0.554500    0.1727600
+48481.00   0.136914   0.553290   0.1710455    0.136200    0.552900    0.1708200
+48482.00   0.140316   0.551783   0.1691646    0.139500    0.551200    0.1689400
+48483.00   0.143560   0.550210   0.1674311    0.142800    0.549400    0.1672400
+48484.00   0.146642   0.548540   0.1658892    0.146000    0.547600    0.1657200
+48485.00   0.149543   0.546773   0.1645384    0.149000    0.545700    0.1644000
+48486.00   0.152226   0.544914   0.1633450    0.151800    0.543800    0.1632200
+48487.00   0.154714   0.542974   0.1622537    0.154600    0.541800    0.1621400
+48488.00   0.157052   0.540992   0.1612062    0.157200    0.539800    0.1611000
+48489.00   0.159312   0.538993   0.1601450    0.159700    0.537800    0.1600400
+48490.00   0.161609   0.536939   0.1590155    0.162200    0.535800    0.1588800
+48491.00   0.164054   0.534799   0.1577638    0.164500    0.533700    0.1575700
+48492.00   0.166659   0.532583   0.1563302    0.166900    0.531700    0.1561000
+48493.00   0.169344   0.530338   0.1546978    0.169300    0.529600    0.1544400
+48494.00   0.171997   0.528109   0.1528838    0.171700    0.527600    0.1525900
+48495.00   0.174560   0.525956   0.1509325    0.174100    0.525600    0.1506300
+48496.00   0.177137   0.523935   0.1489024    0.176600    0.523500    0.1486100
+48497.00   0.179726   0.521986   0.1468790    0.179200    0.521400    0.1466000
+48498.00   0.182299   0.520033   0.1449414    0.181800    0.519400    0.1446900
+48499.00   0.184849   0.518012   0.1431336    0.184500    0.517300    0.1429000
+48500.00   0.187398   0.515918   0.1414584    0.187300    0.515200    0.1412500
+48501.00   0.189978   0.513764   0.1398743    0.190100    0.513100    0.1396800
+48502.00   0.192616   0.511566   0.1383010    0.192900    0.510900    0.1381200
+48503.00   0.195337   0.509352   0.1366345    0.195700    0.508800    0.1364500
+48504.00   0.198209   0.507148   0.1347696    0.198400    0.506600    0.1345800
+48505.00   0.201270   0.504976   0.1326407    0.201400    0.504300    0.1324500
+48506.00   0.204388   0.502847   0.1302495    0.204100    0.502100    0.1300500
+48507.00   0.207393   0.500743   0.1276691    0.206700    0.499800    0.1274400
+48508.00   0.210161   0.498606   0.1250076    0.209100    0.497500    0.1247500
+48509.00   0.212566   0.496400   0.1223822    0.211300    0.495200    0.1221100
+48510.00   0.214480   0.494106   0.1198897    0.213300    0.492800    0.1196300
+48511.00   0.215997   0.491708   0.1175991    0.215100    0.490300    0.1173700
+48512.00   0.217312   0.489190   0.1155326    0.216900    0.487800    0.1153500
+48513.00   0.218598   0.486539   0.1136722    0.218600    0.485200    0.1135500
+48514.00   0.219935   0.483763   0.1119721    0.220200    0.482500    0.1119000
+48515.00   0.221414   0.480892   0.1103748    0.221900    0.479800    0.1103500
+48516.00   0.223135   0.477963   0.1088260    0.223700    0.477000    0.1088200
+48517.00   0.225137   0.475008   0.1072693    0.225500    0.474200    0.1072500
+48518.00   0.227290   0.472047   0.1056320    0.227400    0.471300    0.1055800
+48519.00   0.229438   0.469103   0.1038529    0.229400    0.468400    0.1037400
+48520.00   0.231466   0.466196   0.1018945    0.231400    0.465600    0.1017200
+48521.00   0.233424   0.463342   0.0997466    0.233500    0.462700    0.0995100
+48522.00   0.235406   0.460554   0.0974257    0.235600    0.459800    0.0971300
+48523.00   0.237502   0.457846   0.0949725    0.237800    0.456900    0.0946600
+48524.00   0.239748   0.455199   0.0924587    0.239800    0.454000    0.0921500
+48525.00   0.242034   0.452492   0.0899884    0.241800    0.451000    0.0897100
+48526.00   0.244219   0.449613   0.0876444    0.243600    0.448100    0.0874100
+48527.00   0.246208   0.446617   0.0854745    0.245300    0.445000    0.0852900
+48528.00   0.247973   0.443544   0.0834657    0.246900    0.442000    0.0833200
+48529.00   0.249478   0.440410   0.0815602    0.248300    0.438900    0.0814500
+48530.00   0.250664   0.437218   0.0796781    0.249500    0.435700    0.0795600
+48531.00   0.251533   0.433958   0.0777307    0.250700    0.432500    0.0775900
+48532.00   0.252261   0.430611   0.0756290    0.251700    0.429200    0.0754400
+48533.00   0.253026   0.427190   0.0733329    0.252700    0.425900    0.0731100
+48534.00   0.253919   0.423732   0.0708653    0.253500    0.422600    0.0706100
+48535.00   0.254908   0.420246   0.0683008    0.254600    0.419100    0.0680400
+48536.00   0.255934   0.416738   0.0657398    0.255600    0.415600    0.0655000
+48537.00   0.256938   0.413216   0.0632768    0.256600    0.412100    0.0630400
+48538.00   0.257857   0.409694   0.0609769    0.257500    0.408700    0.0607800
+48539.00   0.258653   0.406205   0.0588820    0.258400    0.405300    0.0587400
+48540.00   0.259307   0.402771   0.0569980    0.259000    0.401800    0.0569100
+48541.00   0.259816   0.399401   0.0552983    0.259600    0.398400    0.0552600
+48542.00   0.260215   0.396078   0.0537336    0.260100    0.395000    0.0537300
+48543.00   0.260541   0.392784   0.0522502    0.260600    0.391600    0.0522600
+48544.00   0.260834   0.389497   0.0508005    0.260900    0.388200    0.0507900
+48545.00   0.261131   0.386204   0.0493325    0.261200    0.384800    0.0492500
+48546.00   0.261471   0.382917   0.0477694    0.261400    0.381500    0.0476200
+48547.00   0.261748   0.379673   0.0460491    0.261500    0.378100    0.0458400
+48548.00   0.261878   0.376475   0.0441486    0.261500    0.374800    0.0439100
+48549.00   0.261867   0.373298   0.0420742    0.261400    0.371400    0.0418300
+48550.00   0.261762   0.370065   0.0398639    0.261200    0.368100    0.0396300
+48551.00   0.261585   0.366705   0.0375816    0.261000    0.364800    0.0373800
+48552.00   0.261298   0.363280   0.0353079    0.260700    0.361500    0.0351300
+48553.00   0.260952   0.359926   0.0331125    0.260400    0.358200    0.0329600
+48554.00   0.260565   0.356662   0.0310547    0.260100    0.355000    0.0309200
+48555.00   0.260157   0.353463   0.0291278    0.259800    0.351800    0.0289900
+48556.00   0.259771   0.350310   0.0272670    0.259700    0.348700    0.0271200
+48557.00   0.259457   0.347183   0.0253742    0.259700    0.345600    0.0252200
+48558.00   0.259269   0.344065   0.0233532    0.259900    0.342600    0.0231900
+48559.00   0.259278   0.340934   0.0211389    0.260100    0.339600    0.0209600
+48560.00   0.259575   0.337805   0.0187158    0.260400    0.336700    0.0185000
+48561.00   0.260184   0.334747   0.0160973    0.260800    0.333800    0.0158700
+48562.00   0.261067   0.331831   0.0133398    0.261100    0.330900    0.0131100
+48563.00   0.262021   0.329086   0.0105434    0.261500    0.328100    0.0103500
+48564.00   0.262838   0.326446   0.0078236    0.261800    0.325200    0.0076700
+48565.00   0.263316   0.323824   0.0052780    0.262300    0.322400    0.0051600
+48566.00   0.263351   0.321155   0.0029617    0.262400    0.319700    0.0028700
+48567.00   0.263058   0.318417   0.0008641    0.262400    0.317000    0.0007600
+48568.00   0.262580   0.315600  -0.0010654    0.262100    0.314300   -0.0011900
+48569.00   0.262019   0.312716  -0.0028975    0.261800    0.311400   -0.0030400
+48570.00   0.261375   0.309796  -0.0047002    0.261200    0.308500   -0.0048500
+48571.00   0.260618   0.306885  -0.0065338    0.260500    0.305600   -0.0066900
+48572.00   0.259733   0.303992  -0.0084483    0.259700    0.302600   -0.0086100
+48573.00   0.258711   0.301113  -0.0104806    0.258800    0.299700   -0.0106500
+48574.00   0.257557   0.298217  -0.0126521    0.257800    0.296700   -0.0128400
+48575.00   0.256324   0.295259  -0.0149750    0.256800    0.293800   -0.0151700
+48576.00   0.255081   0.292194  -0.0174429    0.255700    0.290800   -0.0176400
+48577.00   0.253909   0.289017  -0.0200270    0.254700    0.287800   -0.0202100
+48578.00   0.252920   0.285821  -0.0226646    0.253700    0.284700   -0.0228200
+48579.00   0.252234   0.282720  -0.0252746    0.252700    0.281700   -0.0253900
+48580.00   0.251872   0.279772  -0.0277784    0.251800    0.278600   -0.0278700
+48581.00   0.251571   0.276910  -0.0301254    0.250900    0.275500   -0.0302000
+48582.00   0.251059   0.274132  -0.0322901    0.250100    0.272400   -0.0323700
+48583.00   0.250193   0.271398  -0.0343196    0.249200    0.269300   -0.0344300
+48584.00   0.249052   0.268621  -0.0363251    0.248400    0.266200   -0.0364800
+48585.00   0.247766   0.265706  -0.0384389    0.247500    0.263100   -0.0386300
+48586.00   0.246464   0.262558  -0.0407691    0.246700    0.260000   -0.0409800
+48587.00   0.245276   0.259134  -0.0433617    0.246000    0.256900   -0.0435600
+48588.00   0.244270   0.255563  -0.0461708    0.245200    0.253800   -0.0463600
+48589.00   0.243445   0.251970  -0.0491002    0.244400    0.250800   -0.0492700
+48590.00   0.242748   0.248441  -0.0520428    0.243600    0.247800   -0.0522000
+48591.00   0.242116   0.245061  -0.0548992    0.242700    0.244800   -0.0550500
+48592.00   0.241483   0.241909  -0.0575943    0.241600    0.241900   -0.0577600
+48593.00   0.240748   0.239028  -0.0600857    0.240500    0.239100   -0.0602600
+48594.00   0.239785   0.236379  -0.0623717    0.239100    0.236300   -0.0625700
+48595.00   0.238404   0.233887  -0.0644791    0.237500    0.233600   -0.0646900
+48596.00   0.236477   0.231434  -0.0664603    0.235800    0.230800   -0.0666800
+48597.00   0.234014   0.228899  -0.0683727    0.233800    0.228000   -0.0685900
+48598.00   0.231202   0.226236  -0.0702803    0.231700    0.225200   -0.0704900
+48599.00   0.228292   0.223448  -0.0722415    0.229500    0.222400   -0.0724600
+48600.00   0.225542   0.220545  -0.0743029    0.227200    0.219600   -0.0745200
+48601.00   0.223142   0.217573  -0.0764947    0.224800    0.216800   -0.0767200
+48602.00   0.221062   0.214672  -0.0788245    0.222400    0.214100   -0.0790600
+48603.00   0.219187   0.211939  -0.0812771    0.220000    0.211400   -0.0815300
+48604.00   0.217366   0.209355  -0.0838232    0.217900    0.208800   -0.0841000
+48605.00   0.215521   0.206838  -0.0864216    0.215700    0.206200   -0.0867100
+48606.00   0.213630   0.204303  -0.0890221    0.213700    0.203800   -0.0893100
+48607.00   0.211809   0.201740  -0.0915598    0.211700    0.201400   -0.0918400
+48608.00   0.210191   0.199201  -0.0939742    0.209800    0.199100   -0.0942200
+48609.00   0.208711   0.196874  -0.0962138    0.207900    0.196800   -0.0964200
+48610.00   0.207235   0.194795  -0.0982561    0.206000    0.194600   -0.0984300
+48611.00   0.205507   0.192814  -0.1001693    0.204100    0.192400   -0.1003400
+48612.00   0.203369   0.190776  -0.1020840    0.202200    0.190200   -0.1022700
+48613.00   0.200948   0.188654  -0.1041185    0.200300    0.187900   -0.1043100
+48614.00   0.198454   0.186472  -0.1063444    0.198300    0.185700   -0.1065500
+48615.00   0.196072   0.184253  -0.1087701    0.196300    0.183400   -0.1089900
+48616.00   0.193885   0.182012  -0.1113399    0.194400    0.181200   -0.1115800
+48617.00   0.191929   0.179752  -0.1139584    0.192400    0.178900   -0.1142000
+48618.00   0.190212   0.177484  -0.1165251    0.190400    0.176600   -0.1167500
+48619.00   0.188613   0.175240  -0.1189540    0.188400    0.174400   -0.1191500
+48620.00   0.186972   0.173043  -0.1211998    0.186500    0.172200   -0.1213700
+48621.00   0.185126   0.170911  -0.1232581    0.184500    0.170000   -0.1234200
+48622.00   0.182965   0.168856  -0.1251559    0.182400    0.167900   -0.1253000
+48623.00   0.180592   0.166857  -0.1269451    0.180300    0.165900   -0.1270800
+48624.00   0.178161   0.164885  -0.1286896    0.178200    0.163900   -0.1288200
+48625.00   0.175799   0.162915  -0.1304568    0.175700    0.161600   -0.1305800
+48626.00   0.173506   0.160942  -0.1323066    0.173500    0.159600   -0.1324300
+48627.00   0.171249   0.158962  -0.1342857    0.171100    0.157800   -0.1344200
+48628.00   0.168993   0.156979  -0.1364224    0.168700    0.156000   -0.1365600
+48629.00   0.166663   0.155043  -0.1387244    0.166200    0.154200   -0.1388600
+48630.00   0.164123   0.153294  -0.1411761    0.163600    0.152600   -0.1413200
+48631.00   0.161402   0.151714  -0.1437490    0.160900    0.151000   -0.1439000
+48632.00   0.158585   0.150245  -0.1464011    0.158100    0.149500   -0.1465400
+48633.00   0.155692   0.148849  -0.1490736    0.155300    0.148100   -0.1491800
+48634.00   0.152741   0.147494  -0.1517024    0.152300    0.146700   -0.1518000
+48635.00   0.149763   0.146138  -0.1542271    0.149300    0.145400   -0.1543000
+48636.00   0.146774   0.144772  -0.1566078    0.146200    0.144200   -0.1566900
+48637.00   0.143765   0.143469  -0.1588545    0.143100    0.142900   -0.1589500
+48638.00   0.140654   0.142244  -0.1610204    0.139900    0.141700   -0.1611400
+48639.00   0.137345   0.141095  -0.1632032    0.136700    0.140500   -0.1633600
+48640.00   0.133813   0.139997  -0.1655276    0.133500    0.139300   -0.1657200
+48641.00   0.130220   0.138870  -0.1680973    0.130300    0.138000   -0.1683300
+48642.00   0.126773   0.137616  -0.1709548    0.127200    0.136700   -0.1712100
+48643.00   0.123633   0.136222  -0.1740492    0.124100    0.135400   -0.1742900
+48644.00   0.120838   0.134840  -0.1772390    0.121000    0.134000   -0.1774700
+48645.00   0.118239   0.133514  -0.1803757    0.118000    0.132700   -0.1805900
+48646.00   0.115660   0.132246  -0.1833389    0.115100    0.131300   -0.1835400
+48647.00   0.113031   0.131007  -0.1860675    0.112300    0.129900   -0.1862800
+48648.00   0.110308   0.129756  -0.1885557    0.109500    0.128600   -0.1887700
+48649.00   0.107447   0.128450  -0.1908372    0.106800    0.127300   -0.1910600
+48650.00   0.104483   0.127120  -0.1929756    0.104200    0.126100   -0.1932200
+48651.00   0.101609   0.125938  -0.1950580    0.101600    0.125000   -0.1953000
+48652.00   0.098935   0.124947  -0.1971464    0.099100    0.123900   -0.1973700
+48653.00   0.096518   0.124143  -0.1992921    0.096700    0.123000   -0.1994900
+48654.00   0.094302   0.123506  -0.2015317    0.094300    0.122200   -0.2017000
+48655.00   0.092183   0.123008  -0.2038871    0.091700    0.121400   -0.2040200
+48656.00   0.090027   0.122615  -0.2063606    0.089300    0.120700   -0.2065100
+48657.00   0.087698   0.122252  -0.2089429    0.086900    0.120100   -0.2091300
+48658.00   0.085120   0.121749  -0.2116347    0.084500    0.119600   -0.2118600
+48659.00   0.082425   0.121095  -0.2143996    0.082000    0.119100   -0.2146100
+48660.00   0.079747   0.120336  -0.2171790    0.079400    0.118600   -0.2173600
+48661.00   0.077048   0.119538  -0.2198943    0.076700    0.118200   -0.2200300
+48662.00   0.074254   0.118767  -0.2224826    0.073900    0.117700   -0.2225800
+48663.00   0.071296   0.118085  -0.2249019    0.071100    0.117300   -0.2249800
+48664.00   0.068126   0.117511  -0.2271426    0.068100    0.116900   -0.2272000
+48665.00   0.064769   0.117034  -0.2292410    0.065100    0.116600   -0.2293000
+48666.00   0.061346   0.116670  -0.2312755    0.062000    0.116300   -0.2313500
+48667.00   0.057994   0.116441  -0.2333549    0.058900    0.116100   -0.2334600
+48668.00   0.054803   0.116362  -0.2355963    0.055800    0.115900   -0.2357400
+48669.00   0.051751   0.116424  -0.2380810    0.052600    0.115700   -0.2382600
+48670.00   0.048799   0.116604  -0.2408220    0.049500    0.115700   -0.2410200
+48671.00   0.045888   0.116854  -0.2437544    0.046300    0.115600   -0.2439800
+48672.00   0.042907   0.117120  -0.2467553    0.043000    0.115500   -0.2469800
+48673.00   0.039772   0.117341  -0.2496841    0.039800    0.115500   -0.2499100
+48674.00   0.036468   0.117447  -0.2524364    0.036500    0.115400   -0.2526400
+48675.00   0.033121   0.117372  -0.2549754    0.033200    0.115300   -0.2551400
+48676.00   0.029796   0.117134  -0.2573113    0.029900    0.115300   -0.2574300
+48677.00   0.026512   0.116772  -0.2594898    0.026600    0.115200   -0.2595300
+48678.00   0.023303   0.116361  -0.2615661    0.023200    0.115100   -0.2615300
+48679.00   0.020120   0.116041  -0.2635649    0.019800    0.115000   -0.2634800
+48680.00   0.016870   0.115871  -0.2655401    0.016400    0.115000   -0.2654600
+48681.00   0.013480   0.115880  -0.2675507    0.013000    0.115100   -0.2675100
+48682.00   0.009978   0.116087  -0.2696648    0.009500    0.115200   -0.2697000
+48683.00   0.006393   0.116477  -0.2719343    0.006000    0.115400   -0.2720500
+48684.00   0.002747   0.117026  -0.2743831    0.002500    0.115700   -0.2745600
+48685.00  -0.000960   0.117699  -0.2770061   -0.000900    0.116200   -0.2772200
+48686.00  -0.004773   0.118416  -0.2797652   -0.004400    0.116700   -0.2799900
+48687.00  -0.008589   0.119105  -0.2825980   -0.008000    0.117300   -0.2828200
+48688.00  -0.012262   0.119710  -0.2854369   -0.011500    0.118000   -0.2856300
+48689.00  -0.015689   0.120230  -0.2882203   -0.015000    0.118800   -0.2883600
+48690.00  -0.018919   0.120750  -0.2908904   -0.018400    0.119700   -0.2910000
+48691.00  -0.022035   0.121373  -0.2934116   -0.021900    0.120700   -0.2935400
+48692.00  -0.025117   0.122197  -0.2958109   -0.025300    0.121800   -0.2959800
+48693.00  -0.028234   0.123272  -0.2982033   -0.028700    0.123000   -0.2984000
+48694.00  -0.031378   0.124589  -0.3006878   -0.032100    0.124300   -0.3008900
+48695.00  -0.034530   0.126117  -0.3033568   -0.035400    0.125700   -0.3035600
+48696.00  -0.037731   0.127806  -0.3062763   -0.038700    0.127300   -0.3064700
+48697.00  -0.040970   0.129629  -0.3094750   -0.042000    0.128900   -0.3096600
+48698.00  -0.044230   0.131570  -0.3129125   -0.045300    0.130600   -0.3130800
+48699.00  -0.047505   0.133592  -0.3164823   -0.048500    0.132400   -0.3166600
+48700.00  -0.050798   0.135598  -0.3200428   -0.051600    0.134300   -0.3202100
+48701.00  -0.054100   0.137506  -0.3234626   -0.054600    0.136300   -0.3236400
+48702.00  -0.057350   0.139342  -0.3266588   -0.057600    0.138300   -0.3268300
+48703.00  -0.060446   0.141156  -0.3296001   -0.060400    0.140300   -0.3297700
+48704.00  -0.063319   0.143002  -0.3323193   -0.063100    0.142400   -0.3324800
+48705.00  -0.065917   0.144942  -0.3348843   -0.065700    0.144600   -0.3350400
+48706.00  -0.068216   0.147021  -0.3373685   -0.068200    0.146800   -0.3375000
+48707.00  -0.070314   0.149236  -0.3398287   -0.070600    0.149000   -0.3399300
+48708.00  -0.072339   0.151570  -0.3423103   -0.072800    0.151200   -0.3424000
+48709.00  -0.074391   0.153996  -0.3448509   -0.074900    0.153400   -0.3449700
+48710.00  -0.076467   0.156449  -0.3474917   -0.077000    0.155600   -0.3476400
+48711.00  -0.078543   0.158854  -0.3502571   -0.079000    0.157800   -0.3504400
+48712.00  -0.080594   0.161135  -0.3531461   -0.080900    0.159900   -0.3533400
+48713.00  -0.082596   0.163229  -0.3561338   -0.082800    0.161900   -0.3563400
+48714.00  -0.084556   0.165149  -0.3591684   -0.084600    0.163900   -0.3593600
+48715.00  -0.086492   0.166920  -0.3621836   -0.086500    0.165900   -0.3623500
+48716.00  -0.088401   0.168583  -0.3651128   -0.088200    0.167700   -0.3652700
+48717.00  -0.090251   0.170205  -0.3679050   -0.090000    0.169600   -0.3680400
+48718.00  -0.092014   0.171858  -0.3705355   -0.091800    0.171500   -0.3706600
+48719.00  -0.093706   0.173611  -0.3730152   -0.093500    0.173400   -0.3731300
+48720.00  -0.095351   0.175516  -0.3753975   -0.095300    0.175300   -0.3755200
+48721.00  -0.096976   0.177569  -0.3777761   -0.097000    0.177300   -0.3779200
+48722.00  -0.098597   0.179745  -0.3802556   -0.098800    0.179300   -0.3804300
+48723.00  -0.100207   0.182020  -0.3829267   -0.100600    0.181500   -0.3831500
+48724.00  -0.101809   0.184383  -0.3858506   -0.102300    0.183800   -0.3861300
+48725.00  -0.103423   0.186819  -0.3890352   -0.104100    0.186100   -0.3893700
+48726.00  -0.105076   0.189311  -0.3924319   -0.105900    0.188500   -0.3927900
+48727.00  -0.106793   0.191842  -0.3959418   -0.107700    0.190800   -0.3962800
+48728.00  -0.108599   0.194378  -0.3994216   -0.109500    0.193200   -0.3997000
+48729.00  -0.110484   0.196883  -0.4027295   -0.111300    0.195700   -0.4029400
+48730.00  -0.112402   0.199323  -0.4057833   -0.113100    0.198100   -0.4059300
+48731.00  -0.114309   0.201692  -0.4085627   -0.114800    0.200500   -0.4086600
+48732.00  -0.116160   0.203983  -0.4110990   -0.116500    0.202800   -0.4111700
+48733.00  -0.117913   0.206196  -0.4134536   -0.118100    0.205200   -0.4135300
+48734.00  -0.119538   0.208379  -0.4157038   -0.119700    0.207600   -0.4158200
+48735.00  -0.121032   0.210673  -0.4179446   -0.121300    0.209900   -0.4181000
+48736.00  -0.122480   0.213058  -0.4202420   -0.122800    0.212300   -0.4204300
+48737.00  -0.123975   0.215479  -0.4226378   -0.124300    0.214700   -0.4228500
+48738.00  -0.125501   0.217910  -0.4251565   -0.125900    0.217100   -0.4253900
+48739.00  -0.127017   0.220342  -0.4277973   -0.127400    0.219400   -0.4280300
+48740.00  -0.128494   0.222791  -0.4305358   -0.129000    0.221800   -0.4307400
+48741.00  -0.129927   0.225263  -0.4333245   -0.130500    0.224100   -0.4335000
+48742.00  -0.131420   0.227741  -0.4360890   -0.132100    0.226500   -0.4362300
+48743.00  -0.133096   0.230149  -0.4387615   -0.133800    0.228800   -0.4388700
+48744.00  -0.135028   0.232420  -0.4412846   -0.135400    0.231100   -0.4413800
+48745.00  -0.137123   0.234572  -0.4436273   -0.137200    0.233300   -0.4437200
+48746.00  -0.139228   0.236665  -0.4457947   -0.138800    0.235700   -0.4458900
+48747.00  -0.141185   0.238758  -0.4478320   -0.140500    0.238100   -0.4479500
+48748.00  -0.142849   0.240919  -0.4498196   -0.142000    0.240500   -0.4499600
+48749.00  -0.144143   0.243238  -0.4518569   -0.143500    0.243000   -0.4520300
+48750.00  -0.145138   0.245766  -0.4540441   -0.144900    0.245500   -0.4542500
+48751.00  -0.145941   0.248520  -0.4564424   -0.146200    0.248000   -0.4566700
+48752.00  -0.146679   0.251420  -0.4590478   -0.147400    0.250600   -0.4592700
+48753.00  -0.147478   0.254362  -0.4618024   -0.148400    0.253100   -0.4620200
+48754.00  -0.148460   0.257247  -0.4646084   -0.149400    0.255700   -0.4648100
+48755.00  -0.149655   0.259981  -0.4673633   -0.150200    0.258200   -0.4675800
+48756.00  -0.150888   0.262487  -0.4700007   -0.151000    0.260700   -0.4702000
+48757.00  -0.151944   0.264796  -0.4724541   -0.151600    0.263100   -0.4726300
+48758.00  -0.152674   0.266971  -0.4746929   -0.152200    0.265600   -0.4748600
+48759.00  -0.153100   0.269090  -0.4767418   -0.152800    0.268000   -0.4769000
+48760.00  -0.153324   0.271238  -0.4786626   -0.153300    0.270400   -0.4788200
+48761.00  -0.153492   0.273491  -0.4805333   -0.153700    0.272800   -0.4806900
+48762.00  -0.153702   0.275896  -0.4824287   -0.154200    0.275200   -0.4825800
+48763.00  -0.153937   0.278419  -0.4843968   -0.154600    0.277600   -0.4845400
+48764.00  -0.154207   0.281007  -0.4864569   -0.155000    0.280000   -0.4865900
+48765.00  -0.154584   0.283623  -0.4886033   -0.155400    0.282400   -0.4887500
+48766.00  -0.155104   0.286252  -0.4908421   -0.155900    0.284700   -0.4910000
+48767.00  -0.155760   0.288822  -0.4931589   -0.156300    0.287100   -0.4933200
+48768.00  -0.156535   0.291241  -0.4955207   -0.156600    0.289500   -0.4956700
+48769.00  -0.157366   0.293461  -0.4978772   -0.157000    0.291800   -0.4980000
+48770.00  -0.158048   0.295568  -0.5001556   -0.157300    0.294200   -0.5002600
+48771.00  -0.158364   0.297671  -0.5022890   -0.157500    0.296500   -0.5023900
+48772.00  -0.158224   0.299872  -0.5042519   -0.157600    0.298900   -0.5043500
+48773.00  -0.157794   0.302214  -0.5060354   -0.157700    0.301200   -0.5061400
+48774.00  -0.157251   0.304723  -0.5076563   -0.157600    0.303500   -0.5077700
+48775.00  -0.156693   0.307325  -0.5091858   -0.157400    0.306000   -0.5093000
+48776.00  -0.156213   0.309905  -0.5107243   -0.157200    0.308800   -0.5108600
+48777.00  -0.155865   0.312371  -0.5123786   -0.156900    0.311500   -0.5125300
+48778.00  -0.155629   0.314694  -0.5142194   -0.156600    0.314100   -0.5143800
+48779.00  -0.155420   0.316894  -0.5162500   -0.156300    0.316300   -0.5164300
+48780.00  -0.155182   0.319021  -0.5184166   -0.156000    0.318300   -0.5186000
+48781.00  -0.154897   0.321135  -0.5206263   -0.155500    0.320200   -0.5208200
+48782.00  -0.154597   0.323300  -0.5227758   -0.154800    0.322200   -0.5229400
+48783.00  -0.154299   0.325574  -0.5247841   -0.154200    0.324500   -0.5249100
+48784.00  -0.153976   0.327985  -0.5266096   -0.153700    0.327100   -0.5266900
+48785.00  -0.153631   0.330557  -0.5282452   -0.153500    0.330000   -0.5282800
+48786.00  -0.153301   0.333315  -0.5297193   -0.153400    0.333000   -0.5297300
+48787.00  -0.153029   0.336272  -0.5310856   -0.153200    0.336000   -0.5311000
+48788.00  -0.152876   0.339376  -0.5324041   -0.153000    0.339100   -0.5324500
+48789.00  -0.152878   0.342509  -0.5337292   -0.152900    0.342000   -0.5338200
+48790.00  -0.153016   0.345557  -0.5351059   -0.153100    0.344800   -0.5352300
+48791.00  -0.153169   0.348440  -0.5365664   -0.153300    0.347400   -0.5367200
+48792.00  -0.153196   0.351097  -0.5381314   -0.153400    0.349900   -0.5383100
+48793.00  -0.152947   0.353491  -0.5398079   -0.153300    0.352200   -0.5400000
+48794.00  -0.152328   0.355688  -0.5415918   -0.153000    0.354400   -0.5417800
+48795.00  -0.151443   0.357814  -0.5434488   -0.152200    0.356600   -0.5436200
+48796.00  -0.150489   0.359987  -0.5453287   -0.151200    0.358800   -0.5454800
+48797.00  -0.149658   0.362268  -0.5471758   -0.150200    0.361000   -0.5473200
+48798.00  -0.148926   0.364635  -0.5489337   -0.149200    0.363400   -0.5490800
+48799.00  -0.148103   0.367069  -0.5505592   -0.148000    0.365800   -0.5507200
+48800.00  -0.147055   0.369542  -0.5520272   -0.146800    0.368400   -0.5521800
+48801.00  -0.145800   0.372031  -0.5533401   -0.145700    0.371000   -0.5535000
+48802.00  -0.144519   0.374531  -0.5545415   -0.144700    0.373500   -0.5547000
+48803.00  -0.143342   0.377023  -0.5557122   -0.143600    0.375900   -0.5558700
+48804.00  -0.142256   0.379477   0.4430472   -0.142500    0.378200    0.4429100
+48805.00  -0.141189   0.381860   0.4416753   -0.141300    0.380500    0.4415300
+48806.00  -0.140045   0.384172   0.4401262   -0.140200    0.382700    0.4399700
+48807.00  -0.138748   0.386425   0.4384135   -0.139200    0.384900    0.4382400
+48808.00  -0.137348   0.388614   0.4366213   -0.138000    0.387100    0.4364400
+48809.00  -0.135865   0.390743   0.4348628   -0.136700    0.389400    0.4346700
+48810.00  -0.134255   0.392840   0.4332363   -0.135000    0.391500    0.4330500
+48811.00  -0.132501   0.394965   0.4317956   -0.133200    0.393700    0.4316200
+48812.00  -0.130806   0.397220   0.4305555   -0.131400    0.396100    0.4304000
+48813.00  -0.129424   0.399651   0.4294993   -0.129900    0.398800    0.4293600
+48814.00  -0.128330   0.402171   0.4285694   -0.128700    0.401700    0.4284400
+48815.00  -0.127463   0.404642   0.4277093   -0.128000    0.404500    0.4275900
+48816.00  -0.126732   0.406920   0.4268671   -0.127500    0.406800    0.4267600
+48817.00  -0.126065   0.408912   0.4259970   -0.127000    0.408600    0.4258900
+48818.00  -0.125322   0.410633   0.4250476   -0.126200    0.410100    0.4249200
+48819.00  -0.124191   0.412277   0.4239735   -0.124900    0.411600    0.4238400
+48820.00  -0.122472   0.414066   0.4227595   -0.123100    0.413300    0.4226200
+48821.00  -0.120237   0.416097   0.4214188   -0.120700    0.415400    0.4212700
+48822.00  -0.117661   0.418425   0.4199735   -0.118100    0.417800    0.4198100
+48823.00  -0.114962   0.420939   0.4184560   -0.115400    0.420400    0.4182900
+48824.00  -0.112339   0.423477   0.4169068   -0.112800    0.422900    0.4167400
+48825.00  -0.110008   0.425890   0.4153668   -0.110400    0.425200    0.4152100
+48826.00  -0.108033   0.428109   0.4138765   -0.108200    0.427400    0.4137200
+48827.00  -0.106077   0.430216   0.4124657   -0.106000    0.429500    0.4122900
+48828.00  -0.103972   0.432230   0.4111448   -0.104000    0.431500    0.4109600
+48829.00  -0.101805   0.434165   0.4098930   -0.102100    0.433400    0.4097000
+48830.00  -0.099751   0.436034   0.4086562   -0.100000    0.435300    0.4084800
+48831.00  -0.097900   0.437831   0.4073690   -0.098000    0.437200    0.4072100
+48832.00  -0.096176   0.439589   0.4059513   -0.096100    0.439000    0.4058000
+48833.00  -0.094340   0.441446   0.4043197   -0.094300    0.440800    0.4041700
+48834.00  -0.092328   0.443549   0.4024494   -0.092500    0.442700    0.4023000
+48835.00  -0.090223   0.445839   0.4003910   -0.090400    0.444900    0.4002500
+48836.00  -0.088082   0.448188   0.3982501   -0.088300    0.447300    0.3981000
+48837.00  -0.085895   0.450460   0.3961543   -0.086200    0.449700    0.3959900
+48838.00  -0.083755   0.452563   0.3942075   -0.084100    0.451900    0.3940300
+48839.00  -0.081828   0.454576   0.3924681   -0.082200    0.454100    0.3922700
+48840.00  -0.080003   0.456571   0.3909099   -0.080400    0.456100    0.3907400
+48841.00  -0.078139   0.458634   0.3895165   -0.078500    0.457900    0.3893600
+48842.00  -0.076208   0.460875   0.3882434   -0.076500    0.459800    0.3881300
+48843.00  -0.074290   0.463332   0.3870412   -0.074400    0.462000    0.3869300
+48844.00  -0.072315   0.465924   0.3858530   -0.072500    0.464700    0.3857400
+48845.00  -0.070241   0.468541   0.3846145   -0.070700    0.467200    0.3844400
+48846.00  -0.068261   0.471062   0.3832183   -0.068900    0.469700    0.3830000
+48847.00  -0.066397   0.473325   0.3816262   -0.067100    0.471800    0.3814100
+48848.00  -0.064466   0.475307   0.3798709   -0.065100    0.473800    0.3796700
+48849.00  -0.062333   0.477088   0.3780113   -0.063000    0.475900    0.3778100
+48850.00  -0.060005   0.478776   0.3761010   -0.060700    0.477800    0.3759100
+48851.00  -0.057474   0.480454   0.3741898   -0.058100    0.479700    0.3740100
+48852.00  -0.054730   0.482120   0.3723218   -0.055400    0.481500    0.3721400
+48853.00  -0.051810   0.483699   0.3705234   -0.052500    0.483100    0.3703400
+48854.00  -0.048783   0.485162   0.3687999   -0.049300    0.484600    0.3686300
+48855.00  -0.045664   0.486491   0.3671538   -0.046100    0.485900    0.3669900
+48856.00  -0.042499   0.487683   0.3655657   -0.043100    0.487100    0.3654300
+48857.00  -0.039354   0.488789   0.3639866   -0.040100    0.488200    0.3638700
+48858.00  -0.036252   0.489888   0.3623445   -0.037200    0.489200    0.3622400
+48859.00  -0.033146   0.491085   0.3605595   -0.034200    0.490300    0.3604500
+48860.00  -0.030036   0.492464   0.3585519   -0.031000    0.491600    0.3584100
+48861.00  -0.026957   0.493979   0.3562597   -0.027700    0.493200    0.3560900
+48862.00  -0.023903   0.495593   0.3536961   -0.024400    0.494900    0.3535100
+48863.00  -0.020858   0.497302   0.3509702   -0.021300    0.496700    0.3507800
+48864.00  -0.017903   0.499041   0.3482488   -0.018300    0.498500    0.3480800
+48865.00  -0.015192   0.500593   0.3457035   -0.015600    0.499900    0.3455300
+48866.00  -0.012886   0.501710   0.3434557   -0.013200    0.500900    0.3432800
+48867.00  -0.010966   0.502220   0.3415326   -0.011000    0.501200    0.3413000
+48868.00  -0.008939   0.502278   0.3398721   -0.008900    0.501100    0.3396100
+48869.00  -0.006749   0.502235   0.3383956   -0.006700    0.500900    0.3381600
+48870.00  -0.004454   0.502390   0.3370185   -0.004100    0.501200    0.3368300
+48871.00  -0.002028   0.502831   0.3356478   -0.001500    0.501600    0.3355000
+48872.00   0.000513   0.503509   0.3342017    0.001000    0.502500    0.3340600
+48873.00   0.003059   0.504279   0.3326178    0.003300    0.503500    0.3324700
+48874.00   0.005476   0.504990   0.3308625    0.005600    0.504400    0.3307100
+48875.00   0.007814   0.505575   0.3289492    0.008000    0.505100    0.3287900
+48876.00   0.010098   0.506007   0.3269116    0.010500    0.505500    0.3267400
+48877.00   0.012363   0.506266   0.3247966    0.012800    0.505700    0.3246300
+48878.00   0.014709   0.506388   0.3226585    0.015100    0.505700    0.3225000
+48879.00   0.017122   0.506485   0.3205567    0.017300    0.505700    0.3204100
+48880.00   0.019557   0.506712   0.3185458    0.019400    0.505700    0.3184100
+48881.00   0.022043   0.507108   0.3166597    0.021800    0.506100    0.3165100
+48882.00   0.024591   0.507480   0.3148939    0.024400    0.506500    0.3147400
+48883.00   0.027139   0.507675   0.3132183    0.027200    0.506800    0.3130700
+48884.00   0.029623   0.507617   0.3115916    0.029900    0.506900    0.3114600
+48885.00   0.032003   0.507391   0.3099566    0.032400    0.506700    0.3098500
+48886.00   0.034238   0.507135   0.3082435    0.034600    0.506500    0.3081500
+48887.00   0.036273   0.507005   0.3063870    0.036500    0.506300    0.3062800
+48888.00   0.038147   0.507048   0.3043250    0.038300    0.506100    0.3041800
+48889.00   0.040098   0.507093   0.3020052    0.040200    0.506100    0.3018300
+48890.00   0.042174   0.507081   0.2994677    0.042200    0.506100    0.2992800
+48891.00   0.044339   0.506983   0.2968178    0.044500    0.506200    0.2966300
+48892.00   0.046531   0.506715   0.2941925    0.046600    0.505900    0.2940000
+48893.00   0.048707   0.506217   0.2917083    0.048700    0.505500    0.2915200
+48894.00   0.050938   0.505528   0.2894253    0.050800    0.504800    0.2892500
+48895.00   0.053292   0.504791   0.2873458    0.053000    0.504000    0.2872000
+48896.00   0.055692   0.504145   0.2854308    0.055400    0.503200    0.2853100
+48897.00   0.058118   0.503680   0.2836186    0.057800    0.502500    0.2835100
+48898.00   0.060608   0.503410   0.2818446    0.060400    0.502300    0.2817300
+48899.00   0.063234   0.503229   0.2800370    0.063100    0.502100    0.2799300
+48900.00   0.066052   0.503051   0.2781375    0.066200    0.501900    0.2780900
+48901.00   0.069055   0.502853   0.2761060    0.069200    0.501900    0.2760600
+48902.00   0.072135   0.502609   0.2739224    0.072300    0.501800    0.2738600
+48903.00   0.075164   0.502249   0.2715976    0.075300    0.501600    0.2715000
+48904.00   0.078011   0.501719   0.2691643    0.078100    0.501100    0.2690300
+48905.00   0.080592   0.500975   0.2666714    0.080600    0.500400    0.2665000
+48906.00   0.082938   0.500005   0.2641812    0.082800    0.499300    0.2640000
+48907.00   0.085182   0.498864   0.2617535    0.085100    0.498100    0.2615900
+48908.00   0.087534   0.497713   0.2594361    0.087500    0.496700    0.2592900
+48909.00   0.090137   0.496752   0.2572455    0.090200    0.495600    0.2571100
+48910.00   0.092869   0.496097   0.2551454    0.093100    0.495000    0.2550400
+48911.00   0.095524   0.495655   0.2531016    0.095800    0.494800    0.2530300
+48912.00   0.097959   0.495300   0.2510598    0.098300    0.494700    0.2509900
+48913.00   0.100177   0.494912   0.2489308    0.100400    0.494500    0.2488400
+48914.00   0.102242   0.494385   0.2466266    0.102200    0.493800    0.2465000
+48915.00   0.104231   0.493641   0.2440833    0.103900    0.492900    0.2439300
+48916.00   0.106221   0.492669   0.2412656    0.106000    0.491700    0.2410900
+48917.00   0.108349   0.491575   0.2381997    0.108200    0.490400    0.2380300
+48918.00   0.110632   0.490517   0.2350047    0.110700    0.489400    0.2348600
+48919.00   0.112984   0.489593   0.2318337    0.113300    0.488500    0.2317100
+48920.00   0.115243   0.488773   0.2288108    0.115600    0.487700    0.2286900
+48921.00   0.117297   0.487948   0.2260199    0.117500    0.487000    0.2259100
+48922.00   0.119065   0.486996   0.2234917    0.119000    0.486000    0.2233700
+48923.00   0.120544   0.485856   0.2211912    0.120200    0.484800    0.2210600
+48924.00   0.121936   0.484560   0.2190355    0.121400    0.483500    0.2188900
+48925.00   0.123457   0.483156   0.2169378    0.123000    0.482200    0.2167700
+48926.00   0.125267   0.481680   0.2148240    0.125000    0.480900    0.2146500
+48927.00   0.127408   0.480182   0.2126421    0.127400    0.479500    0.2124900
+48928.00   0.129736   0.478689   0.2103838    0.129900    0.478100    0.2102600
+48929.00   0.132018   0.477293   0.2080688    0.132200    0.476700    0.2079700
+48930.00   0.134034   0.476071   0.2057129    0.134000    0.475600    0.2056100
+48931.00   0.135730   0.474916   0.2032926    0.135500    0.474200    0.2031600
+48932.00   0.137164   0.473676   0.2007989    0.136900    0.473000    0.2006600
+48933.00   0.138539   0.472270   0.1982865    0.138100    0.471500    0.1981600
+48934.00   0.140013   0.470709   0.1958095    0.139500    0.470000    0.1956900
+48935.00   0.141637   0.469027   0.1934112    0.141100    0.468300    0.1932900
+48936.00   0.143375   0.467265   0.1911216    0.142900    0.466500    0.1909900
+48937.00   0.145215   0.465487   0.1889393    0.144900    0.464700    0.1887800
+48938.00   0.147211   0.463795   0.1868318    0.147000    0.463000    0.1866800
+48939.00   0.149308   0.462245   0.1847543    0.149200    0.461500    0.1846000
+48940.00   0.151459   0.460843   0.1826347    0.151300    0.460100    0.1824900
+48941.00   0.153688   0.459540   0.1803904    0.153500    0.458900    0.1802400
+48942.00   0.155993   0.458291   0.1779453    0.155800    0.457700    0.1778000
+48943.00   0.158277   0.457088   0.1752648    0.158200    0.456500    0.1751100
+48944.00   0.160480   0.455924   0.1723679    0.160600    0.455400    0.1722100
+48945.00   0.162663   0.454751   0.1693369    0.163000    0.454200    0.1691800
+48946.00   0.164781   0.453500   0.1662885    0.165200    0.452900    0.1661400
+48947.00   0.166706   0.452072   0.1633407    0.167200    0.451300    0.1632000
+48948.00   0.168352   0.450398   0.1605728    0.168700    0.449600    0.1604400
+48949.00   0.169592   0.448510   0.1580229    0.169600    0.447800    0.1578900
+48950.00   0.170409   0.446462   0.1556831    0.170200    0.445800    0.1555500
+48951.00   0.170909   0.444279   0.1535019    0.170600    0.443700    0.1533300
+48952.00   0.171329   0.441971   0.1514019    0.170900    0.441400    0.1512000
+48953.00   0.171871   0.439582   0.1493071    0.171400    0.439000    0.1490900
+48954.00   0.172586   0.437181   0.1471611    0.172000    0.436600    0.1469400
+48955.00   0.173419   0.434829   0.1449299    0.172700    0.434200    0.1447300
+48956.00   0.174288   0.432567   0.1425977    0.173500    0.432000    0.1424200
+48957.00   0.175124   0.430416   0.1401658    0.174400    0.429900    0.1400100
+48958.00   0.175909   0.428369   0.1376364    0.175600    0.427800    0.1374800
+48959.00   0.176811   0.426428   0.1350035    0.176900    0.425800    0.1348500
+48960.00   0.178006   0.424602   0.1323019    0.178200    0.424000    0.1321700
+48961.00   0.179261   0.422835   0.1296009    0.179500    0.422400    0.1294800
+48962.00   0.180442   0.421016   0.1269445    0.180600    0.420700    0.1268200
+48963.00   0.181507   0.419048   0.1243624    0.181600    0.418900    0.1242500
+48964.00   0.182424   0.416981   0.1218870    0.182400    0.416800    0.1217800
+48965.00   0.183234   0.414896   0.1195148    0.183300    0.414600    0.1194100
+48966.00   0.184075   0.412781   0.1171967    0.184100    0.412300    0.1170700
+48967.00   0.185114   0.410653   0.1148636    0.185100    0.410100    0.1147100
+48968.00   0.186391   0.408560   0.1124375    0.186200    0.407900    0.1122700
+48969.00   0.187772   0.406530   0.1098522    0.187400    0.405800    0.1096700
+48970.00   0.189068   0.404548   0.1070804    0.188600    0.403800    0.1069000
+48971.00   0.190156   0.402565   0.1041438    0.189800    0.401900    0.1039600
+48972.00   0.190995   0.400504   0.1011071    0.190800    0.400000    0.1009100
+48973.00   0.191741   0.398313   0.0980773    0.191700    0.397900    0.0978900
+48974.00   0.192464   0.395974   0.0951610    0.192700    0.395500    0.0949800
+48975.00   0.193139   0.393493   0.0924394    0.193500    0.393000    0.0922800
+48976.00   0.193720   0.390895   0.0899542    0.194200    0.390300    0.0898200
+48977.00   0.194234   0.388228   0.0877011    0.194800    0.387700    0.0875800
+48978.00   0.194827   0.385566   0.0856314    0.195500    0.385200    0.0855100
+48979.00   0.195638   0.382963   0.0836635    0.196100    0.382700    0.0835200
+48980.00   0.196651   0.380395   0.0817043    0.196700    0.380300    0.0815400
+48981.00   0.197901   0.377836   0.0796786    0.197700    0.377700    0.0794900
+48982.00   0.199439   0.375287   0.0775356    0.199200    0.375100    0.0773400
+48983.00   0.201252   0.372765   0.0752484    0.201000    0.372400    0.0750600
+48984.00   0.203210   0.370284   0.0728132    0.203100    0.369800    0.0726400
+48985.00   0.205074   0.367837   0.0702468    0.205100    0.367200    0.0701000
+48986.00   0.206599   0.365331   0.0675835    0.206700    0.364700    0.0674400
+48987.00   0.207631   0.362604   0.0648749    0.207800    0.362000    0.0647400
+48988.00   0.208194   0.359648   0.0621615    0.208500    0.359100    0.0620200
+48989.00   0.208431   0.356562   0.0594783    0.208700    0.355900    0.0593100
+48990.00   0.208526   0.353449   0.0568545    0.208800    0.352600    0.0566700
+48991.00   0.208647   0.350396   0.0543068    0.208900    0.349600    0.0541300
+48992.00   0.208921   0.347431   0.0518327    0.209000    0.346600    0.0516600
+48993.00   0.209421   0.344530   0.0494074    0.209300    0.343800    0.0492500
+48994.00   0.210159   0.341695   0.0469999    0.209700    0.341100    0.0468700
+48995.00   0.211067   0.338925   0.0445590    0.210600    0.338400    0.0444300
+48996.00   0.212049   0.336234   0.0420253    0.211600    0.335800    0.0418800
+48997.00   0.213045   0.333641   0.0393377    0.212800    0.333200    0.0392000
+48998.00   0.213955   0.331154   0.0364839    0.213900    0.330800    0.0363500
+48999.00   0.214684   0.328784   0.0335118    0.214800    0.328400    0.0333800
+49000.00   0.215132   0.326497   0.0305107    0.215300    0.326200    0.0303900
+49001.00   0.215226   0.324183   0.0275822    0.215500    0.324100    0.0274700
+49002.00   0.214978   0.321737   0.0248090    0.215300    0.321800    0.0247000
+49003.00   0.214461   0.319091   0.0222319    0.214500    0.319200    0.0221400
+49004.00   0.213815   0.316306   0.0198540    0.213700    0.316400    0.0197600
+49005.00   0.213184   0.313454   0.0176442    0.212800    0.313300    0.0175500
+49006.00   0.212639   0.310580   0.0155523    0.212300    0.310100    0.0154500
+49007.00   0.212180   0.307690   0.0135130    0.212000    0.306900    0.0133900
+49008.00   0.211925   0.304822   0.0114464    0.211900    0.303900    0.0113300
+49009.00   0.211898   0.302089   0.0093022    0.212000    0.301000    0.0091800
+49010.00   0.211999   0.299570   0.0070530    0.212100    0.298500    0.0069300
+49011.00   0.212110   0.297312   0.0046827    0.212300    0.296300    0.0045600
+49012.00   0.212144   0.295279   0.0021893    0.212400    0.294300    0.0020500
+49013.00   0.212037   0.293336  -0.0004160    0.212300    0.292300   -0.0005600
+49014.00   0.211751   0.291318  -0.0031141    0.211800    0.290300   -0.0032600
+49015.00   0.211304   0.289155  -0.0058559    0.211100    0.288300   -0.0059900
+49016.00   0.210612   0.286843  -0.0085770    0.210200    0.286100   -0.0087000
+49017.00   0.209635   0.284374  -0.0112341    0.209100    0.283700   -0.0113600
+49018.00   0.208394   0.281767  -0.0137992    0.208000    0.281100   -0.0139300
+49019.00   0.207041   0.279023  -0.0162659    0.206800    0.278400   -0.0164000
+49020.00   0.205890   0.276161  -0.0186504    0.205800    0.275500   -0.0187800
+49021.00   0.205272   0.273272  -0.0210032    0.205600    0.272600   -0.0211300
+49022.00   0.205181   0.270501  -0.0234080    0.205600    0.269600   -0.0235400
+49023.00   0.205410   0.267923  -0.0259570    0.205700    0.266800   -0.0261000
+49024.00   0.205674   0.265552  -0.0287298    0.205700    0.264600   -0.0288900
+49025.00   0.205728   0.263317  -0.0317594    0.205700    0.262400   -0.0319500
+49026.00   0.205400   0.261104  -0.0350095    0.205400    0.260200   -0.0352200
+49027.00   0.204693   0.258794  -0.0383773    0.204900    0.257800   -0.0386000
+49028.00   0.203779   0.256316  -0.0417285    0.204200    0.255300   -0.0419400
+49029.00   0.202761   0.253763  -0.0449247    0.203400    0.252700   -0.0451200
+49030.00   0.201616   0.251195  -0.0478655    0.202200    0.250100   -0.0480400
+49031.00   0.200385   0.248588  -0.0505214    0.200900    0.247500   -0.0506900
+49032.00   0.199315   0.245908  -0.0529393    0.199500    0.245000   -0.0531000
+49033.00   0.198417   0.243224  -0.0552035    0.198400    0.242500   -0.0553600
+49034.00   0.197692   0.240590  -0.0574059    0.197600    0.240100   -0.0575600
+49035.00   0.197110   0.238066  -0.0596344    0.197100    0.237400   -0.0597700
+49036.00   0.196581   0.235758  -0.0619457    0.196800    0.234900   -0.0620600
+49037.00   0.195886   0.233727  -0.0643816    0.196300    0.232700   -0.0644800
+49038.00   0.194803   0.232000  -0.0669627    0.195400    0.230900   -0.0670500
+49039.00   0.193264   0.230511  -0.0696740    0.193900    0.229400   -0.0697600
+49040.00   0.191321   0.229092  -0.0724767    0.191900    0.228000   -0.0725800
+49041.00   0.189105   0.227541  -0.0753148    0.189600    0.226700   -0.0754400
+49042.00   0.186790   0.225705  -0.0781292    0.187300    0.224800   -0.0782800
+49043.00   0.184497   0.223638  -0.0808761    0.184900    0.222900   -0.0810400
+49044.00   0.182313   0.221451  -0.0835222    0.182600    0.220800   -0.0836700
+49045.00   0.180270   0.219255  -0.0860470    0.180600    0.218600   -0.0861700
+49046.00   0.178323   0.217119  -0.0884464    0.178600    0.216500   -0.0885500
+49047.00   0.176433   0.215094  -0.0907343    0.176600    0.214400   -0.0908200
+49048.00   0.174589   0.213215  -0.0929467    0.174600    0.212500   -0.0930500
+49049.00   0.172837   0.211506  -0.0951493    0.172700    0.210700   -0.0952700
+49050.00   0.171272   0.209920  -0.0974343    0.171200    0.209000   -0.0975700
+49051.00   0.169878   0.208394  -0.0998884    0.169800    0.207600   -0.1000400
+49052.00   0.168575   0.206865  -0.1025715    0.168400    0.206100   -0.1027400
+49053.00   0.167251   0.205305  -0.1055072    0.167000    0.204500   -0.1056700
+49054.00   0.165878   0.203710  -0.1086556    0.165800    0.202900   -0.1088200
+49055.00   0.164621   0.202094  -0.1119204    0.164700    0.201400   -0.1120700
+49056.00   0.163704   0.200494  -0.1151810    0.163700    0.199800   -0.1153000
+49057.00   0.163151   0.198951  -0.1183182    0.163100    0.198300   -0.1184100
+49058.00   0.162596   0.197466  -0.1212618    0.162600    0.196900   -0.1213400
+49059.00   0.161644   0.196015  -0.1240068    0.161900    0.195500   -0.1240900
+49060.00   0.160152   0.194585  -0.1266037    0.160500    0.194100   -0.1267000
+49061.00   0.158171   0.193139  -0.1291206    0.158500    0.192700   -0.1292200
+49062.00   0.155860   0.191669  -0.1316158    0.156000    0.191200   -0.1317200
+49063.00   0.153408   0.190202  -0.1341389    0.153600    0.189700   -0.1342400
+49064.00   0.150961   0.188755  -0.1367249    0.151100    0.188200   -0.1368200
+49065.00   0.148646   0.187318  -0.1393946    0.148600    0.186700   -0.1394800
+49066.00   0.146522   0.185882  -0.1421530    0.146500    0.185300   -0.1422400
+49067.00   0.144578   0.184458  -0.1449878    0.144600    0.183900   -0.1450800
+49068.00   0.142711   0.183056  -0.1478704    0.142700    0.182600   -0.1479800
+49069.00   0.140784   0.181682  -0.1507614    0.140900    0.181100   -0.1508900
+49070.00   0.138650   0.180349  -0.1536223    0.138700    0.179700   -0.1537700
+49071.00   0.136190   0.179107  -0.1564082    0.136200    0.178400   -0.1565700
+49072.00   0.133300   0.177912  -0.1590735    0.133300    0.177200   -0.1592400
+49073.00   0.130164   0.176669  -0.1616137    0.130200    0.175900   -0.1617700
+49074.00   0.126954   0.175365  -0.1640387    0.127000    0.174400   -0.1641800
+49075.00   0.123795   0.174030  -0.1663745    0.123700    0.173000   -0.1665100
+49076.00   0.120808   0.172734  -0.1686651    0.120500    0.171600   -0.1687800
+49077.00   0.118065   0.171571  -0.1709796    0.117700    0.170700   -0.1711000
+49078.00   0.115461   0.170608  -0.1734106    0.115200    0.169800   -0.1735300
+49079.00   0.112819   0.169850  -0.1760396    0.112800    0.169100   -0.1761600
+49080.00   0.109985   0.169234  -0.1789125    0.110400    0.168500   -0.1790400
+49081.00   0.106929   0.168672  -0.1820214    0.107500    0.167900   -0.1821500
+49082.00   0.103742   0.168107  -0.1852993    0.104400    0.167300   -0.1854200
+49083.00   0.100497   0.167543  -0.1886393    0.101000    0.166800   -0.1887400
+49084.00   0.097190   0.166999  -0.1919310    0.097400    0.166300   -0.1920200
+49085.00   0.093870   0.166460  -0.1950761    0.093800    0.165900   -0.1951500
+49086.00   0.090617   0.165924  -0.1980306    0.090200    0.165400   -0.1981000
+49087.00   0.087503   0.165434  -0.2008148    0.087100    0.164900   -0.2008700
+49088.00   0.084599   0.165031  -0.2034890    0.084300    0.164400   -0.2035500
+49089.00   0.081980   0.164749  -0.2061209    0.081800    0.163900   -0.2061900
+49090.00   0.079691   0.164583  -0.2087601    0.079700    0.163600   -0.2088500
+49091.00   0.077753   0.164501  -0.2114531    0.077900    0.163600   -0.2115600
+49092.00   0.076037   0.164432  -0.2142464    0.076200    0.163600   -0.2143700
+49093.00   0.074297   0.164311  -0.2171315    0.074400    0.163600   -0.2172500
+49094.00   0.072364   0.164130  -0.2200758    0.072400    0.163500   -0.2201900
+49095.00   0.070167   0.163952  -0.2230453    0.070300    0.163500   -0.2231600
+49096.00   0.067678   0.163854  -0.2260020    0.068000    0.163400   -0.2261100
+49097.00   0.064991   0.163886  -0.2289063    0.065500    0.163400   -0.2290100
+49098.00   0.062269   0.164046  -0.2317394    0.062800    0.163400   -0.2318600
+49099.00   0.059560   0.164214  -0.2345184    0.060000    0.163300   -0.2346600
+49100.00   0.056815   0.164291  -0.2372510    0.057000    0.163100   -0.2373800
+49101.00   0.054017   0.164249  -0.2399097    0.054000    0.162900   -0.2400300
+49102.00   0.051235   0.164158  -0.2424968    0.051100    0.162800   -0.2426200
+49103.00   0.048568   0.164102  -0.2450409    0.048300    0.163000   -0.2451500
+49104.00   0.046083   0.164147  -0.2475844    0.045800    0.163400   -0.2477200
+49105.00   0.043828   0.164335  -0.2502105    0.043400    0.163800   -0.2503800
+49106.00   0.041787   0.164665  -0.2530275    0.041400    0.164200   -0.2532100
+49107.00   0.039911   0.165073  -0.2560917    0.039500    0.164600   -0.2562600
+49108.00   0.038162   0.165485  -0.2593800    0.038000    0.165000   -0.2595300
+49109.00   0.036530   0.165871  -0.2628226    0.036600    0.165300   -0.2629600
+49110.00   0.034937   0.166200  -0.2663070    0.035100    0.165600   -0.2664400
+49111.00   0.033243   0.166454  -0.2696980    0.033300    0.165800   -0.2698200
+49112.00   0.031379   0.166619  -0.2728791    0.031400    0.166100   -0.2730100
+49113.00   0.029478   0.166678  -0.2758004    0.029500    0.166200   -0.2759200
+49114.00   0.027545   0.166609  -0.2784700    0.027700    0.166400   -0.2785800
+49115.00   0.025583   0.166474  -0.2809558    0.025900    0.166400   -0.2810600
+49116.00   0.023567   0.166356  -0.2833422    0.024000    0.166400   -0.2834500
+49117.00   0.021584   0.166332  -0.2857034    0.022100    0.166300   -0.2858100
+49118.00   0.019770   0.166462  -0.2880885    0.020100    0.166200   -0.2882100
+49119.00   0.018154   0.166749  -0.2905120    0.018200    0.166100   -0.2906300
+49120.00   0.016659   0.167191  -0.2929677    0.016600    0.166400   -0.2931100
+49121.00   0.015280   0.167765  -0.2954686    0.015300    0.166800   -0.2956200
+49122.00   0.014000   0.168440  -0.2980239    0.014000    0.167400   -0.2981900
+49123.00   0.012715   0.169193  -0.3006133    0.012700    0.168200   -0.3007600
+49124.00   0.011395   0.170002  -0.3032040    0.011400    0.169000   -0.3033500
+49125.00   0.010122   0.170851  -0.3057593    0.010200    0.170000   -0.3059000
+49126.00   0.008962   0.171744  -0.3082467    0.009000    0.170900   -0.3083700
+49127.00   0.007802   0.172669  -0.3106349    0.007600    0.171900   -0.3107400
+49128.00   0.006488   0.173605  -0.3129097    0.006000    0.172900   -0.3130200
+49129.00   0.004962   0.174529  -0.3150881    0.004000    0.173900   -0.3152100
+49130.00   0.003180   0.175435  -0.3172081    0.001900    0.174900   -0.3173300
+49131.00   0.001001   0.176264  -0.3193324   -0.000400    0.175700   -0.3194600
+49132.00  -0.001543   0.176968  -0.3215329   -0.002700    0.176500   -0.3216700
+49133.00  -0.004186   0.177552  -0.3238725   -0.004900    0.177000   -0.3240100
+49134.00  -0.006612   0.178039  -0.3263804   -0.006900    0.177400   -0.3265300
+49135.00  -0.008664   0.178485  -0.3290562   -0.008700    0.177700   -0.3292300
+49136.00  -0.010426   0.178935  -0.3318619   -0.010400    0.178000   -0.3320500
+49137.00  -0.012046   0.179405  -0.3347233   -0.012000    0.178400   -0.3349100
+49138.00  -0.013693   0.179884  -0.3375466   -0.013700    0.178900   -0.3377400
+49139.00  -0.015457   0.180333  -0.3402389   -0.015400    0.179500   -0.3404000
+49140.00  -0.017306   0.180721  -0.3427283   -0.017100    0.180000   -0.3428600
+49141.00  -0.019162   0.181046  -0.3449825   -0.018900    0.180500   -0.3450900
+49142.00  -0.020994   0.181454  -0.3470279   -0.020900    0.180900   -0.3471100
+49143.00  -0.022821   0.182091  -0.3489347   -0.022800    0.181500   -0.3489900
+49144.00  -0.024651   0.182945  -0.3507899   -0.024600    0.182400   -0.3508500
+49145.00  -0.026472   0.183944  -0.3526721   -0.026500    0.183300   -0.3527500
+49146.00  -0.028260   0.184996  -0.3546329   -0.028300    0.184300   -0.3547500
+49147.00  -0.029986   0.186010  -0.3566907   -0.030200    0.185300   -0.3568300
+49148.00  -0.031655   0.186928  -0.3588295   -0.032000    0.186200   -0.3590000
+49149.00  -0.033229   0.187816  -0.3610373   -0.033500    0.187000   -0.3612300
+49150.00  -0.034528   0.188782  -0.3632832   -0.034700    0.188100   -0.3634800
+49151.00  -0.035578   0.189930  -0.3655243   -0.035600    0.189300   -0.3657100
+49152.00  -0.036543   0.191288  -0.3677157   -0.036600    0.190600   -0.3678700
+49153.00  -0.037651   0.192787  -0.3698172   -0.037800    0.192000   -0.3699400
+49154.00  -0.039083   0.194308  -0.3718005   -0.039200    0.193500   -0.3719100
+49155.00  -0.040805   0.195682  -0.3736641   -0.040900    0.194800   -0.3737700
+49156.00  -0.042804   0.196851  -0.3754291   -0.042900    0.195900   -0.3755400
+49157.00  -0.045006   0.197823  -0.3771254   -0.045100    0.196900   -0.3772600
+49158.00  -0.047278   0.198658  -0.3788066   -0.047200    0.197800   -0.3789600
+49159.00  -0.049500   0.199429  -0.3805425   -0.049300    0.198600   -0.3807100
+49160.00  -0.051507   0.200208  -0.3823984   -0.051300    0.199300   -0.3825600
+49161.00  -0.053139   0.201109  -0.3844143   -0.053000    0.200200   -0.3845700
+49162.00  -0.054384   0.202161  -0.3865801   -0.054400    0.201400   -0.3867400
+49163.00  -0.055378   0.203307  -0.3888537   -0.055600    0.202600   -0.3890300
+49164.00  -0.056273   0.204479  -0.3911756   -0.056600    0.203800   -0.3913600
+49165.00  -0.057333   0.205615  -0.3934676   -0.057700    0.204800   -0.3936400
+49166.00  -0.058551   0.206700  -0.3956403   -0.058800    0.205900   -0.3958000
+49167.00  -0.059828   0.207760  -0.3976239   -0.060000    0.206900   -0.3977900
+49168.00  -0.061112   0.208846  -0.3993921   -0.061200    0.208100   -0.3995700
+49169.00  -0.062437   0.210047   0.5990240   -0.062300    0.209300    0.5988300
+49170.00  -0.063739   0.211328   0.5975692   -0.063500    0.210600    0.5974000
+49171.00  -0.064926   0.212596   0.5961771   -0.064700    0.211800    0.5960200
+49172.00  -0.065948   0.213794   0.5947836   -0.065800    0.213000    0.5946400
+49173.00  -0.066764   0.214898   0.5933425   -0.066800    0.214100    0.5932100
+49174.00  -0.067351   0.215906   0.5918315   -0.067600    0.215200    0.5917300
+49175.00  -0.067751   0.216822   0.5902532   -0.068100    0.216100    0.5901800
+49176.00  -0.068022   0.217671   0.5886301   -0.068300    0.216800    0.5885900
+49177.00  -0.068127   0.218538   0.5869959   -0.068400    0.217600    0.5869700
+49178.00  -0.068091   0.219466   0.5853818   -0.068500    0.218600    0.5853600
+49179.00  -0.068029   0.220478   0.5838113   -0.068500    0.219600    0.5837500
+49180.00  -0.068167   0.221597   0.5822997   -0.068700    0.220900    0.5821800
+49181.00  -0.068638   0.222851   0.5808530   -0.069000    0.222300    0.5806900
+49182.00  -0.069396   0.224261   0.5794633   -0.069500    0.223800    0.5792900
+49183.00  -0.070293   0.225760   0.5781232   -0.070200    0.225100    0.5779600
+49184.00  -0.071136   0.227328   0.5768387   -0.071100    0.226600    0.5767200
+49185.00  -0.071804   0.228951   0.5755861   -0.071900    0.228000    0.5755000
+49186.00  -0.072163   0.230617   0.5743088   -0.072400    0.229700    0.5742500
+49187.00  -0.072376   0.232328   0.5729212   -0.072800    0.231500    0.5728500
+49188.00  -0.072659   0.234071   0.5713467   -0.073100    0.233300    0.5712500
+49189.00  -0.073162   0.235815   0.5695413   -0.073400    0.235100    0.5694000
+49190.00  -0.073761   0.237549   0.5674973   -0.073800    0.236700    0.5673200
+49191.00  -0.074331   0.239305   0.5652901   -0.074300    0.238300    0.5651100
+49192.00  -0.074925   0.241023   0.5630454   -0.074900    0.239900    0.5628700
+49193.00  -0.075668   0.242640   0.5608853   -0.075600    0.241500    0.5607100
+49194.00  -0.076631   0.244148   0.5588963   -0.076500    0.243100    0.5587400
+49195.00  -0.077778   0.245624   0.5571142   -0.077700    0.244800    0.5569700
+49196.00  -0.078981   0.247191   0.5555234   -0.078900    0.246600    0.5553900
+49197.00  -0.080118   0.248935   0.5540600   -0.080000    0.248400    0.5539300
+49198.00  -0.081227   0.250760   0.5526319   -0.081100    0.250200    0.5525200
+49199.00  -0.082366   0.252510   0.5511802   -0.082200    0.252100    0.5510800
+49200.00  -0.083461   0.254212   0.5496530   -0.083200    0.253900    0.5495600
+49201.00  -0.084451   0.255956   0.5480175   -0.084100    0.255600    0.5479300
+49202.00  -0.085351   0.257807   0.5462633   -0.085100    0.257300    0.5461500
+49203.00  -0.086260   0.259752   0.5443991   -0.086300    0.259100    0.5442500
+49204.00  -0.087499   0.261732   0.5424427   -0.087800    0.261100    0.5422800
+49205.00  -0.089023   0.263722   0.5404353   -0.089300    0.263000    0.5402800
+49206.00  -0.090640   0.265695   0.5384455   -0.090700    0.265000    0.5382800
+49207.00  -0.092153   0.267658   0.5365244   -0.092100    0.267000    0.5363500
+49208.00  -0.093437   0.269647   0.5347066   -0.093100    0.268900    0.5345300
+49209.00  -0.094417   0.271698   0.5330118   -0.094100    0.270900    0.5328700
+49210.00  -0.095113   0.273838   0.5314421   -0.094700    0.273000    0.5313200
+49211.00  -0.095676   0.276076   0.5299608   -0.095300    0.275200    0.5298800
+49212.00  -0.096200   0.278363   0.5285077   -0.095700    0.277400    0.5284700
+49213.00  -0.096752   0.280621   0.5270114   -0.096300    0.279500    0.5270100
+49214.00  -0.097412   0.282790   0.5253905   -0.097000    0.281600    0.5254000
+49215.00  -0.098178   0.284807   0.5235760   -0.097800    0.283500    0.5235700
+49216.00  -0.098964   0.286624   0.5215295   -0.098800    0.285400    0.5214800
+49217.00  -0.099720   0.288258   0.5192544   -0.099800    0.287100    0.5191600
+49218.00  -0.100408   0.289796   0.5167887   -0.100700    0.288800    0.5166500
+49219.00  -0.101032   0.291317   0.5142204   -0.101400    0.290500    0.5140600
+49220.00  -0.101549   0.292889   0.5116758   -0.101800    0.292100    0.5115200
+49221.00  -0.101885   0.294559   0.5092718   -0.102100    0.293700    0.5091100
+49222.00  -0.102012   0.296341   0.5070777   -0.102100    0.295500    0.5069000
+49223.00  -0.101942   0.298233   0.5051082   -0.102000    0.297300    0.5049300
+49224.00  -0.101719   0.300269   0.5033333   -0.101700    0.299400    0.5031500
+49225.00  -0.101402   0.302496   0.5016905   -0.101500    0.301700    0.5015000
+49226.00  -0.101072   0.304851   0.5001094   -0.101100    0.304100    0.4999300
+49227.00  -0.100733   0.307233   0.4985168   -0.100800    0.306500    0.4983600
+49228.00  -0.100362   0.309577   0.4968559   -0.100500    0.308900    0.4967200
+49229.00  -0.099972   0.311833   0.4950917   -0.100100    0.311100    0.4949600
+49230.00  -0.099671   0.313947   0.4932110   -0.099800    0.313100    0.4930800
+49231.00  -0.099584   0.315892   0.4912200   -0.099500    0.315100    0.4910800
+49232.00  -0.099550   0.317749   0.4891461   -0.099300    0.316900    0.4890000
+49233.00  -0.099476   0.319598   0.4870423   -0.099200    0.318800    0.4868900
+49234.00  -0.099417   0.321454   0.4849612   -0.099200    0.320600    0.4847900
+49235.00  -0.099508   0.323283   0.4829426   -0.099400    0.322300    0.4827600
+49236.00  -0.099829   0.325038   0.4810086   -0.099800    0.324000    0.4808200
+49237.00  -0.100319   0.326663   0.4791607   -0.100300    0.325600    0.4789900
+49238.00  -0.100783   0.328160   0.4773845   -0.100900    0.327100    0.4772400
+49239.00  -0.101141   0.329689   0.4756590   -0.101300    0.328700    0.4755400
+49240.00  -0.101269   0.331310   0.4739299   -0.101400    0.330300    0.4738300
+49241.00  -0.101089   0.333037   0.4721218   -0.101200    0.332100    0.4720200
+49242.00  -0.100565   0.334903   0.4701547   -0.100600    0.334000    0.4700600
+49243.00  -0.099728   0.336973   0.4679612   -0.099800    0.336100    0.4678600
+49244.00  -0.098778   0.339250   0.4655123   -0.099000    0.338400    0.4654000
+49245.00  -0.097920   0.341636   0.4628345   -0.098100    0.340900    0.4627000
+49246.00  -0.097307   0.344011   0.4600161   -0.097400    0.343300    0.4598700
+49247.00  -0.096914   0.346228   0.4571881   -0.096900    0.345600    0.4570400
+49248.00  -0.096709   0.348151   0.4544796   -0.096700    0.347600    0.4543300
+49249.00  -0.096650   0.349767   0.4519736   -0.096700    0.349400    0.4518200
+49250.00  -0.096757   0.351130   0.4496859   -0.096800    0.350800    0.4495400
+49251.00  -0.096961   0.352364   0.4475688   -0.097100    0.352000    0.4474300
+49252.00  -0.097137   0.353660   0.4455356   -0.097300    0.353200    0.4454100
+49253.00  -0.097226   0.355198   0.4435103   -0.097300    0.354400    0.4434000
+49254.00  -0.097154   0.356944   0.4414471   -0.097200    0.355900    0.4413300
+49255.00  -0.096846   0.358816   0.4393042   -0.096800    0.357700    0.4391800
+49256.00  -0.096384   0.360749   0.4370666   -0.096400    0.359600    0.4369400
+49257.00  -0.095887   0.362707   0.4347408   -0.095900    0.361700    0.4346100
+49258.00  -0.095487   0.364679   0.4323504   -0.095600    0.363900    0.4322300
+49259.00  -0.095344   0.366640   0.4299340   -0.095400    0.366000    0.4298200
+49260.00  -0.095565   0.368552   0.4275414   -0.095400    0.368000    0.4274400
+49261.00  -0.095760   0.370405   0.4251976   -0.095400    0.369900    0.4250900
+49262.00  -0.095500   0.372243   0.4229157   -0.095300    0.371700    0.4228100
+49263.00  -0.094925   0.374109   0.4207044   -0.094900    0.373400    0.4206100
+49264.00  -0.094225   0.376028   0.4185569   -0.094300    0.375200    0.4184500
+49265.00  -0.093568   0.377975   0.4164492   -0.093900    0.377100    0.4163300
+49266.00  -0.093027   0.379897   0.4143430   -0.093500    0.378900    0.4142100
+49267.00  -0.092536   0.381742   0.4121963   -0.092800    0.380700    0.4120700
+49268.00  -0.091935   0.383500   0.4099864   -0.092100    0.382500    0.4098600
+49269.00  -0.091076   0.385238   0.4076651   -0.091100    0.384200    0.4075300
+49270.00  -0.089912   0.387006   0.4051709   -0.089900    0.386000    0.4050400
+49271.00  -0.088541   0.388858   0.4024546   -0.088500    0.387900    0.4023200
+49272.00  -0.087093   0.390877   0.3995030   -0.087000    0.390000    0.3993700
+49273.00  -0.085687   0.393093   0.3963491   -0.085600    0.392300    0.3962100
+49274.00  -0.084433   0.395382   0.3930678   -0.084300    0.394500    0.3929500
+49275.00  -0.083389   0.397498   0.3898032   -0.083200    0.396600    0.3897000
+49276.00  -0.082597   0.399324   0.3866909   -0.082400    0.398400    0.3865900
+49277.00  -0.082066   0.400879   0.3838085   -0.081800    0.399900    0.3837000
+49278.00  -0.081697   0.402206   0.3811629   -0.081400    0.401200    0.3810500
+49279.00  -0.081249   0.403378   0.3787015   -0.081000    0.402400    0.3785800
+49280.00  -0.080501   0.404517   0.3763403   -0.080700    0.403700    0.3762200
+49281.00  -0.079780   0.405850   0.3739861   -0.080300    0.405100    0.3738500
+49282.00  -0.079255   0.407354   0.3715641   -0.079800    0.406700    0.3714300
+49283.00  -0.078848   0.408918   0.3690462   -0.079300    0.408300    0.3689200
+49284.00  -0.078395   0.410502   0.3664339   -0.078600    0.410000    0.3663200
+49285.00  -0.077753   0.412128   0.3637438   -0.077900    0.411700    0.3636400
+49286.00  -0.076914   0.413836   0.3610009   -0.077100    0.413400    0.3609000
+49287.00  -0.076031   0.415576   0.3582377   -0.076400    0.415100    0.3581400
+49288.00  -0.075370   0.417185   0.3554951   -0.075800    0.416700    0.3554000
+49289.00  -0.074954   0.418609   0.3528138   -0.075300    0.418000    0.3527000
+49290.00  -0.074635   0.419832   0.3502215   -0.074900    0.419100    0.3500800
+49291.00  -0.074213   0.420862   0.3477349   -0.074400    0.420000    0.3475800
+49292.00  -0.073492   0.421760   0.3453578   -0.073600    0.420800    0.3451900
+49293.00  -0.072270   0.422619   0.3430772   -0.072500    0.421500    0.3429200
+49294.00  -0.070455   0.423522   0.3408636   -0.071000    0.422300    0.3407300
+49295.00  -0.068458   0.424564   0.3386838   -0.069100    0.423400    0.3385700
+49296.00  -0.066409   0.425838   0.3364799   -0.066900    0.424700    0.3363600
+49297.00  -0.064303   0.427336   0.3341689   -0.064600    0.426300    0.3340500
+49298.00  -0.062188   0.428971   0.3316825   -0.062300    0.428100    0.3315700
+49299.00  -0.060083   0.430629   0.3289829   -0.060100    0.429800    0.3288600
+49300.00  -0.058051   0.432202   0.3260761   -0.058100    0.431400    0.3259500
+49301.00  -0.056232   0.433615   0.3230175   -0.056400    0.432900    0.3229000
+49302.00  -0.054719   0.434848   0.3199125   -0.054900    0.434200    0.3197900
+49303.00  -0.053383   0.435925   0.3168850   -0.053500    0.435300    0.3167600
+49304.00  -0.052073   0.436873   0.3140291   -0.052100    0.436100    0.3139000
+49305.00  -0.050757   0.437726   0.3113888   -0.050800    0.436900    0.3112500
+49306.00  -0.049472   0.438542   0.3089486   -0.049500    0.437600    0.3088100
+49307.00  -0.048279   0.439395   0.3066469   -0.048500    0.438500    0.3065200
+49308.00  -0.047288   0.440342   0.3044064   -0.047700    0.439400    0.3042900
+49309.00  -0.046610   0.441395   0.3021613   -0.047000    0.440400    0.3020400
+49310.00  -0.046115   0.442500   0.2998652   -0.046400    0.441500    0.2997400
+49311.00  -0.045686   0.443609   0.2975016   -0.045900    0.442600    0.2973700
+49312.00  -0.045176   0.444669   0.2950769   -0.045300    0.443700    0.2949600
+49313.00  -0.044412   0.445671   0.2926107   -0.044600    0.444800    0.2925000
+49314.00  -0.043359   0.446638   0.2901289   -0.043700    0.445900    0.2900300
+49315.00  -0.042190   0.447596   0.2876619   -0.042700    0.447000    0.2875600
+49316.00  -0.041254   0.448548   0.2852456   -0.041700    0.448000    0.2851600
+49317.00  -0.040560   0.449434   0.2829184   -0.040900    0.448900    0.2828300
+49318.00  -0.039980   0.450216   0.2806996   -0.040100    0.449600    0.2806200
+49319.00  -0.039440   0.450907   0.2785978   -0.039300    0.450300    0.2785100
+49320.00  -0.038813   0.451524   0.2766129   -0.038600    0.450800    0.2765200
+49321.00  -0.037886   0.452118   0.2747398   -0.037700    0.451300    0.2746400
+49322.00  -0.036491   0.452767   0.2729459   -0.036600    0.451900    0.2728200
+49323.00  -0.035037   0.453502   0.2711337   -0.035300    0.452600    0.2710000
+49324.00  -0.033629   0.454320   0.2692482   -0.033800    0.453400    0.2690900
+49325.00  -0.032184   0.455219   0.2672266   -0.032100    0.454600    0.2671000
+49326.00  -0.030695   0.456183   0.2650228   -0.030600    0.455600    0.2648700
+49327.00  -0.029197   0.457189   0.2626230   -0.029000    0.456600    0.2624600
+49328.00  -0.027689   0.458224   0.2600475   -0.027600    0.457600    0.2598800
+49329.00  -0.026169   0.459296   0.2573503   -0.026300    0.458600    0.2572000
+49330.00  -0.024876   0.460349   0.2546337   -0.025000    0.459500    0.2545100
+49331.00  -0.023654   0.461368   0.2519902   -0.023700    0.460400    0.2518700
+49332.00  -0.022373   0.462389   0.2494811   -0.022400    0.461400    0.2493700
+49333.00  -0.021116   0.463459   0.2471210   -0.021200    0.462400    0.2470100
+49334.00  -0.019978   0.464619   0.2448779   -0.020100    0.463600    0.2447600
+49335.00  -0.018938   0.465875   0.2426803   -0.019000    0.465000    0.2425400
+49336.00  -0.017978   0.467130   0.2404463   -0.017900    0.466300    0.2403000
+49337.00  -0.016999   0.468233   0.2381032   -0.017000    0.467500    0.2379400
+49338.00  -0.015881   0.469162   0.2356355   -0.016000    0.468500    0.2354700
+49339.00  -0.014635   0.469955   0.2330778   -0.014800    0.469300    0.2329100
+49340.00  -0.013258   0.470683   0.2304656   -0.013500    0.470000    0.2303000
+49341.00  -0.011691   0.471433   0.2278282   -0.011700    0.470700    0.2276700
+49342.00  -0.009752   0.472284   0.2251854   -0.009700    0.471500    0.2250500
+49343.00  -0.007342   0.473280   0.2225628   -0.007400    0.472500    0.2224700
+49344.00  -0.004758   0.474365   0.2200279   -0.005000    0.473600    0.2199400
+49345.00  -0.002260   0.475357   0.2176001   -0.002700    0.474600    0.2175100
+49346.00  -0.000079   0.476105   0.2152727   -0.000600    0.475300    0.2151800
+49347.00   0.001645   0.476538   0.2130411    0.001200    0.475800    0.2129400
+49348.00   0.002979   0.476647   0.2108865    0.002600    0.475900    0.2107800
+49349.00   0.004130   0.476509   0.2087733    0.003900    0.475800    0.2086600
+49350.00   0.005326   0.476268   0.2066509    0.005000    0.475600    0.2065100
+49351.00   0.006736   0.476099   0.2044548    0.006200    0.475500    0.2042600
+49352.00   0.008448   0.476147   0.2020948    0.007800    0.475500    0.2018500
+49353.00   0.010488   0.476399   0.1995489    0.009700    0.475600    0.1992800
+49354.00   0.012823   0.476816   0.1968449    0.012000    0.476000    0.1965900
+49355.00   0.015382   0.477358   0.1940457    0.014700    0.476700    0.1938000
+49356.00   0.018130   0.477976   0.1912390    0.017600    0.477300    0.1910200
+49357.00   0.021020   0.478639   0.1885171    0.020600    0.478000    0.1883300
+49358.00   0.023887   0.479288   0.1859460    0.023600    0.478600    0.1857800
+49359.00   0.026706   0.479806   0.1835517    0.026400    0.479000    0.1834100
+49360.00   0.029429   0.480131   0.1813388    0.029100    0.479200    0.1812100
+49361.00   0.031915   0.480235   0.1792719    0.031600    0.479300    0.1791600
+49362.00   0.034135   0.480135   0.1772787    0.033900    0.479200    0.1771700
+49363.00   0.036207   0.479908   0.1752855    0.036200    0.479000    0.1751800
+49364.00   0.038357   0.479664   0.1732344    0.038400    0.478900    0.1731100
+49365.00   0.040806   0.479395   0.1710573    0.040800    0.478700    0.1709500
+49366.00   0.043564   0.479149   0.1687462    0.043200    0.478700    0.1686700
+49367.00   0.046270   0.479033   0.1663712    0.045600    0.478600    0.1663300
+49368.00   0.048614   0.479092   0.1640261    0.047900    0.478700    0.1639700
+49369.00   0.050696   0.479199   0.1617348    0.050100    0.478700    0.1616500
+49370.00   0.052590   0.479158   0.1594831    0.052300    0.478500    0.1593800
+49371.00   0.054280   0.478859   0.1572956    0.054300    0.478200    0.1572000
+49372.00   0.055909   0.478392   0.1552205    0.056300    0.477600    0.1551100
+49373.00   0.057689   0.477780   0.1532311    0.058400    0.477000    0.1531100
+49374.00   0.059822   0.477049   0.1512759    0.060500    0.476400    0.1511700
+49375.00   0.062349   0.476481   0.1493481    0.062700    0.475900    0.1492600
+49376.00   0.065142   0.476263   0.1474173    0.065100    0.475500    0.1473300
+49377.00   0.067938   0.476205   0.1454482    0.067700    0.475200    0.1453500
+49378.00   0.070662   0.475982   0.1433702    0.070400    0.474900    0.1432400
+49379.00   0.073391   0.475402   0.1410971    0.073200    0.474500    0.1409600
+49380.00   0.076083   0.474665   0.1386113    0.076000    0.473900    0.1384800
+49381.00   0.078769   0.473851   0.1359433    0.078700    0.473200    0.1358100
+49382.00   0.081448   0.472951   0.1331513    0.081500    0.472300    0.1330100
+49383.00   0.084148   0.471983   0.1303264    0.084200    0.471400    0.1301900
+49384.00   0.086895   0.471012   0.1275677    0.086900    0.470400    0.1274300
+49385.00   0.089671   0.470130   0.1249677    0.089600    0.469600    0.1248200
+49386.00   0.092442   0.469412   0.1225727    0.092300    0.468800    0.1224200
+49387.00   0.095098   0.468762   0.1203722    0.095000    0.468000    0.1202300
+49388.00   0.097505   0.468057   0.1183323    0.097500    0.467300    0.1182000
+49389.00   0.099674   0.467277   0.1163942    0.099900    0.466600    0.1162700
+49390.00   0.101698   0.466450   0.1144788    0.102000    0.465800    0.1143600
+49391.00   0.103663   0.465580   0.1125030    0.104100    0.464900    0.1123800
+49392.00   0.105628   0.464636   0.1104216    0.106100    0.464000    0.1103000
+49393.00   0.107685   0.463574   0.1082301    0.108000    0.463000    0.1081000
+49394.00   0.109662   0.462451   0.1059464    0.109800    0.462000    0.1058200
+49395.00   0.111429   0.461331   0.1036106    0.111500    0.460800    0.1034800
+49396.00   0.113118   0.460239   0.1012573    0.113100    0.459700    0.1011200
+49397.00   0.114866   0.459172   0.0989138    0.114700    0.458500    0.0987800
+49398.00   0.116741   0.458065   0.0966117    0.116500    0.457300    0.0964700
+49399.00   0.118747   0.456839   0.0943824    0.118300    0.456100    0.0942400
+49400.00   0.120837   0.455491   0.0922419    0.120200    0.454800    0.0920800
+49401.00   0.122767   0.454064   0.0901704    0.122200    0.453400    0.0900000
+49402.00   0.124543   0.452625   0.0881463    0.124200    0.452000    0.0879700
+49403.00   0.126444   0.451326   0.0861344    0.126400    0.450800    0.0859700
+49404.00   0.128682   0.450311   0.0840749    0.128800    0.449800    0.0839300
+49405.00   0.131239   0.449616   0.0819021    0.131400    0.449100    0.0817700
+49406.00   0.133898   0.449154   0.0795498    0.134000    0.448600    0.0794300
+49407.00   0.136340   0.448793   0.0769470    0.136400    0.448300    0.0768400
+49408.00   0.138371   0.448401   0.0740647    0.138400    0.447900    0.0739700
+49409.00   0.139965   0.447866   0.0709302    0.140100    0.447400    0.0708400
+49410.00   0.141211   0.447137   0.0676205    0.141400    0.446600    0.0675100
+49411.00   0.142256   0.446175   0.0642490    0.142500    0.445600    0.0641200
+49412.00   0.143219   0.444899   0.0609375    0.143400    0.444200    0.0607900
+49413.00   0.144190   0.443314   0.0577774    0.144300    0.442700    0.0576300
+49414.00   0.145240   0.441509   0.0548062    0.145200    0.440900    0.0546700
+49415.00   0.146278   0.439625   0.0520263    0.146200    0.439000    0.0519500
+49416.00   0.147211   0.437777   0.0494116    0.147300    0.437200    0.0493600
+49417.00   0.148071   0.436001   0.0469051    0.148200    0.435400    0.0468600
+49418.00   0.148970   0.434307   0.0444290    0.149100    0.433800    0.0443700
+49419.00   0.149918   0.432679   0.0419256    0.150000    0.432200    0.0418500
+49420.00   0.150889   0.431067   0.0393615    0.150900    0.430500    0.0392600
+49421.00   0.151945   0.429415   0.0367221    0.151800    0.428800    0.0366200
+49422.00   0.153095   0.427708   0.0340371    0.153000    0.427100    0.0339500
+49423.00   0.154380   0.425975   0.0313733    0.154200    0.425200    0.0312900
+49424.00   0.155842   0.424297   0.0287840    0.155700    0.423500    0.0286800
+49425.00   0.157393   0.422761   0.0262872    0.157200    0.421800    0.0261500
+49426.00   0.158931   0.421377   0.0238883    0.158800    0.420400    0.0237300
+49427.00   0.160366   0.420007   0.0215796    0.160300    0.419000    0.0214200
+49428.00   0.161723   0.418500   0.0193435    0.161500    0.417700    0.0192100
+49429.00   0.162780   0.416933   0.0171856    0.162500    0.416200    0.0170800
+49430.00   0.163469   0.415334   0.0150740    0.163100    0.414700    0.0149800
+49431.00   0.163895   0.413673   0.0129631    0.163500    0.413100    0.0128700
+49432.00   0.164155   0.411919   0.0107951    0.163800    0.411400    0.0107000
+49433.00   0.164345   0.410066   0.0085070    0.164200    0.409600    0.0084200
+49434.00   0.164664   0.408178   0.0060379    0.164700    0.407700    0.0059400
+49435.00   0.165351   0.406360   0.0033379    0.165600    0.405800    0.0032300
+49436.00   0.166358   0.404603   0.0004004    0.166500    0.403900    0.0002800
+49437.00   0.167468   0.402813  -0.0027475    0.167500    0.402000   -0.0028700
+49438.00   0.168527   0.400966  -0.0060032    0.168400    0.400100   -0.0061200
+49439.00   0.169439   0.399053  -0.0092285    0.169300    0.398200   -0.0093300
+49440.00   0.170178   0.397074  -0.0122952    0.170300    0.396300   -0.0124100
+49441.00   0.170917   0.395070  -0.0151299    0.171400    0.394400   -0.0152600
+49442.00   0.172023   0.393179  -0.0177504    0.172600    0.392600   -0.0178900
+49443.00   0.173479   0.391451  -0.0202159    0.174000    0.390800   -0.0203400
+49444.00   0.175073   0.389822  -0.0225980    0.175300    0.389100   -0.0227200
+49445.00   0.176575   0.388195  -0.0249739    0.176500    0.387500   -0.0251000
+49446.00   0.177850   0.386499  -0.0273956    0.177700    0.385800   -0.0274900
+49447.00   0.178909   0.384736  -0.0298724    0.178800    0.384200   -0.0299700
+49448.00   0.179853   0.382938  -0.0323972    0.179800    0.382400   -0.0325000
+49449.00   0.180783   0.381137  -0.0349731    0.180800    0.380700   -0.0350900
+49450.00   0.181636   0.379343  -0.0375888    0.181700    0.379000   -0.0377100
+49451.00   0.182329   0.377572  -0.0402176    0.182400    0.377300   -0.0403500
+49452.00   0.182867   0.375874  -0.0428274    0.183000    0.375600   -0.0429600
+49453.00   0.183229   0.374257  -0.0453837    0.183300    0.373900   -0.0455200
+49454.00   0.183341   0.372623  -0.0478529    0.183400    0.372200   -0.0479800
+49455.00   0.183248   0.370836  -0.0502164    0.183300    0.370400   -0.0503400
+49456.00   0.183142   0.368777  -0.0524756    0.183100    0.368500   -0.0525900
+49457.00   0.183089   0.366542  -0.0546441    0.183100    0.366300   -0.0547500
+49458.00   0.183155   0.364319  -0.0567524    0.183200    0.364000   -0.0568600
+49459.00   0.183364   0.362224  -0.0588633    0.183400    0.361800   -0.0589700
+49460.00   0.183638   0.360311  -0.0610425    0.183600    0.359700   -0.0611500
+49461.00   0.183851   0.358589  -0.0633504    0.183800    0.357800   -0.0634500
+49462.00   0.183927   0.357041  -0.0658290    0.184000    0.356200   -0.0659100
+49463.00   0.183893   0.355593  -0.0684853    0.183900    0.354800   -0.0685800
+49464.00   0.183783   0.354125  -0.0713343    0.183800    0.353400   -0.0714500
+49465.00   0.183580   0.352535  -0.0743644    0.183600    0.351900   -0.0744800
+49466.00   0.183329   0.350751  -0.0775031    0.183300    0.350200   -0.0776000
+49467.00   0.183076   0.348730  -0.0806300    0.183000    0.348200   -0.0806900
+49468.00   0.182904   0.346445  -0.0836211    0.182800    0.345900   -0.0836600
+49469.00   0.182861   0.343925  -0.0864020    0.182700    0.343200   -0.0864600
+49470.00   0.182883   0.341266  -0.0889845    0.182700    0.340400   -0.0890600
+49471.00   0.183010   0.338645  -0.0914518    0.183000    0.337700   -0.0915600
+49472.00   0.183316   0.336208  -0.0938945    0.183300    0.335200   -0.0940100
+49473.00   0.183751   0.333988  -0.0963720    0.183800    0.332900   -0.0964900
+49474.00   0.184268   0.331918  -0.0989092    0.184300    0.330900   -0.0990100
+49475.00   0.184802   0.329910  -0.1014984    0.184400    0.329300   -0.1016100
+49476.00   0.185248   0.327875  -0.1041177    0.184700    0.327300   -0.1042400
+49477.00   0.185493   0.325771  -0.1067517    0.184900    0.325100   -0.1068800
+49478.00   0.185617   0.323560  -0.1093766    0.185200    0.322800   -0.1095100
+49479.00   0.185787   0.321227  -0.1119535    0.185500    0.320400   -0.1120800
+49480.00   0.186127   0.318824  -0.1144563    0.186000    0.318000   -0.1145800
+49481.00   0.186656   0.316455  -0.1168720    0.186700    0.315600   -0.1169900
+49482.00   0.187338   0.314204  -0.1191899    0.187400    0.313400   -0.1193000
+49483.00   0.188084   0.312099  -0.1214190    0.188200    0.311300   -0.1215400
+49484.00   0.188701   0.310098  -0.1236014    0.188700    0.309300   -0.1237200
+49485.00   0.189149   0.308105  -0.1257618    0.189000    0.307400   -0.1258600
+49486.00   0.189254   0.306043  -0.1279101    0.189000    0.305400   -0.1280100
+49487.00   0.188985   0.303929  -0.1300973    0.188800    0.303300   -0.1301900
+49488.00   0.188471   0.301845  -0.1323644    0.188400    0.301200   -0.1324700
+49489.00   0.187907   0.299837  -0.1347430    0.188000    0.299100   -0.1348500
+49490.00   0.187447   0.297844  -0.1372496    0.187600    0.297000   -0.1373600
+49491.00   0.187258   0.295802  -0.1398852    0.187300    0.295000   -0.1400100
+49492.00   0.187165   0.293799  -0.1426253    0.187000    0.293100   -0.1427500
+49493.00   0.186911   0.291936  -0.1454033    0.186600    0.291300   -0.1455300
+49494.00   0.186381   0.290234  -0.1481329    0.186000    0.289700   -0.1482500
+49495.00   0.185530   0.288644  -0.1507284    0.185200    0.288100   -0.1508300
+49496.00   0.184389   0.287063  -0.1531330    0.184200    0.286400   -0.1532300
+49497.00   0.183055   0.285359  -0.1553305    0.183100    0.284700   -0.1554300
+49498.00   0.181653   0.283438  -0.1573496    0.181900    0.282700   -0.1574600
+49499.00   0.180293   0.281331  -0.1592708    0.180600    0.280600   -0.1593900
+49500.00   0.179012   0.279090  -0.1611620    0.179200    0.278400   -0.1612800
+49501.00   0.177800   0.276742  -0.1630720    0.177900    0.276100   -0.1632000
+49502.00   0.176635   0.274317  -0.1650226    0.176700    0.273600   -0.1651600
+49503.00   0.175513   0.271880  -0.1670147    0.175500    0.271300   -0.1671600
+49504.00   0.174487   0.269528  -0.1690326    0.174500    0.268900   -0.1691800
+49505.00   0.173610   0.267345  -0.1710389    0.173500    0.266700   -0.1711600
+49506.00   0.172730   0.265339  -0.1729923    0.172400    0.264700   -0.1731100
+49507.00   0.171669   0.263474  -0.1748627    0.171400    0.262700   -0.1749800
+49508.00   0.170453   0.261702  -0.1766318    0.170200    0.260900   -0.1767500
+49509.00   0.169134   0.259973  -0.1782903    0.169100    0.259100   -0.1784000
+49510.00   0.167779   0.258226  -0.1798374    0.167900    0.257300   -0.1799400
+49511.00   0.166542   0.256394  -0.1812913    0.166800    0.255500   -0.1813900
+49512.00   0.165561   0.254458  -0.1826856    0.165700    0.253600   -0.1827900
+49513.00   0.164659   0.252447  -0.1840720    0.164600    0.251700   -0.1842000
+49514.00   0.163719   0.250366  -0.1855180    0.163600    0.249600   -0.1856600
+49515.00   0.162763   0.248207  -0.1870737    0.162600    0.247400   -0.1872300
+49516.00   0.161851   0.245977  -0.1887704    0.161800    0.245200   -0.1889200
+49517.00   0.161026   0.243751  -0.1906238    0.161000    0.243100   -0.1907700
+49518.00   0.160281   0.241641  -0.1926234    0.160200    0.241000   -0.1927500
+49519.00   0.159534   0.239746  -0.1947203    0.159500    0.239100   -0.1948300
+49520.00   0.158676   0.237991  -0.1968565    0.158700    0.237400   -0.1969500
+49521.00   0.157611   0.236226  -0.1989637    0.157700    0.235600   -0.1990500
+49522.00   0.156276   0.234349  -0.2009653    0.156500    0.233800   -0.2010400
+49523.00   0.154689   0.232316  -0.2027923    0.155100    0.231800   -0.2028700
+49524.00   0.152998   0.230146  -0.2044062    0.153500    0.229600   -0.2045000
+49525.00   0.151432   0.227937  -0.2058193    0.151900    0.227300   -0.2059300
+49526.00   0.149986   0.225843  -0.2071000    0.150100    0.225100   -0.2072300
+49527.00   0.148533   0.223884  -0.2083200    0.148300    0.223100   -0.2084500
+49528.00   0.146973   0.222011  -0.2095412    0.146500    0.221200   -0.2096800
+49529.00   0.145298   0.220177  -0.2108058    0.144800    0.219300   -0.2109400
+49530.00   0.143565   0.218360  -0.2121185    0.143000    0.217500   -0.2122400
+49531.00   0.141813   0.216582  -0.2134590    0.141400    0.215800   -0.2135700
+49532.00   0.140036   0.214909  -0.2147803    0.139800    0.214200   -0.2148800
+49533.00   0.138313   0.213438  -0.2160203    0.138300    0.212700   -0.2161400
+49534.00   0.136704   0.212123   0.7828134    0.136800    0.211500    0.7826700
+49535.00   0.135090   0.210874   0.7817000    0.135000    0.210300    0.7815500
+49536.00   0.133370   0.209627   0.7806540    0.133300    0.209000    0.7805200
+49537.00   0.131521   0.208338   0.7796814    0.131400    0.207600    0.7795600
+49538.00   0.129613   0.206974   0.7787730    0.129500    0.206200    0.7786700
+49539.00   0.127726   0.205520   0.7779060    0.127700    0.204600    0.7778100
+49540.00   0.125890   0.203972   0.7770472    0.125900    0.203000    0.7769300
+49541.00   0.124100   0.202429   0.7761321    0.124100    0.201400    0.7759900
+49542.00   0.122316   0.200998   0.7750765    0.122400    0.199900    0.7749200
+49543.00   0.120582   0.199702   0.7738352    0.120600    0.198700    0.7737000
+49544.00   0.118900   0.198504   0.7723924    0.118800    0.197600    0.7722700
+49545.00   0.117262   0.197367   0.7707577    0.117100    0.196600    0.7706400
+49546.00   0.115585   0.196254   0.7689693    0.115300    0.195500    0.7688400
+49547.00   0.113774   0.195114   0.7670815    0.113500    0.194400    0.7669300
+49548.00   0.111917   0.193886   0.7651629    0.111700    0.193100    0.7649800
+49549.00   0.110060   0.192527   0.7632581    0.109900    0.191700    0.7630900
+49550.00   0.108157   0.191009   0.7614317    0.108000    0.190200    0.7613000
+49551.00   0.106172   0.189314   0.7597348    0.106000    0.188400    0.7596400
+49552.00   0.104134   0.187488   0.7581907    0.104000    0.186600    0.7581200
+49553.00   0.102165   0.185697   0.7567906    0.102000    0.184800    0.7567200
+49554.00   0.100269   0.184109   0.7554917    0.100100    0.183100    0.7553900
+49555.00   0.098391   0.182709   0.7542115    0.098200    0.181700    0.7540600
+49556.00   0.096537   0.181392   0.7528672    0.096400    0.180400    0.7526900
+49557.00   0.094755   0.180140   0.7514222    0.094600    0.179200    0.7512600
+49558.00   0.092961   0.178983   0.7499005    0.092700    0.178100    0.7497800
+49559.00   0.091017   0.177952   0.7483472    0.090700    0.177100    0.7482500
+49560.00   0.088891   0.177080   0.7468139    0.088500    0.176200    0.7467100
+49561.00   0.086705   0.176385   0.7453424    0.086300    0.175400    0.7451900
+49562.00   0.084616   0.175803   0.7439290    0.084200    0.174700    0.7437300
+49563.00   0.082635   0.175254   0.7425566    0.082100    0.174200    0.7423500
+49564.00   0.080660   0.174710   0.7412436    0.080200    0.173800    0.7410500
+49565.00   0.078707   0.174217   0.7400066    0.078500    0.173400    0.7398500
+49566.00   0.076835   0.173815   0.7388476    0.076800    0.173100    0.7387200
+49567.00   0.075074   0.173500   0.7377391    0.075100    0.172800    0.7376000
+49568.00   0.073460   0.173232   0.7366003    0.073400    0.172500    0.7364400
+49569.00   0.071866   0.172970   0.7353776    0.071600    0.172200    0.7352000
+49570.00   0.070233   0.172666   0.7340370    0.069900    0.171700    0.7339000
+49571.00   0.068588   0.172309   0.7325559    0.068300    0.171400    0.7324300
+49572.00   0.067030   0.171954   0.7309394    0.066800    0.171300    0.7308300
+49573.00   0.065656   0.171684   0.7292203    0.065400    0.171200    0.7291200
+49574.00   0.064458   0.171547   0.7274593    0.064100    0.171200    0.7273400
+49575.00   0.063177   0.171524   0.7256921    0.062700    0.171200    0.7255600
+49576.00   0.061639   0.171505   0.7239814    0.061100    0.171000    0.7238400
+49577.00   0.059681   0.171353   0.7223951    0.059100    0.170700    0.7222500
+49578.00   0.057308   0.170981   0.7209662    0.056900    0.170200    0.7208100
+49579.00   0.054665   0.170386   0.7196757    0.054500    0.169600    0.7195100
+49580.00   0.052050   0.169688   0.7184603    0.052000    0.168900    0.7183000
+49581.00   0.049759   0.169084   0.7172468    0.049700    0.168300    0.7171100
+49582.00   0.047661   0.168749   0.7159904    0.047300    0.168000    0.7158700
+49583.00   0.045502   0.168670   0.7146430    0.045000    0.167800    0.7145300
+49584.00   0.043003   0.168739   0.7131745    0.042400    0.167900    0.7130500
+49585.00   0.040105   0.168840   0.7115798    0.039800    0.168000    0.7114500
+49586.00   0.036966   0.168869   0.7098798    0.037000    0.168000    0.7097400
+49587.00   0.033817   0.168787   0.7081159    0.034200    0.167900    0.7079800
+49588.00   0.030911   0.168608   0.7063369    0.031400    0.167600    0.7062200
+49589.00   0.028467   0.168424   0.7045966    0.029000    0.167400    0.7044700
+49590.00   0.026502   0.168362   0.7029378    0.026800    0.167300    0.7027900
+49591.00   0.024679   0.168471   0.7013413    0.024700    0.167400    0.7011900
+49592.00   0.022800   0.168698   0.6998036    0.022700    0.167700    0.6996800
+49593.00   0.020795   0.169007   0.6983214    0.020600    0.168100    0.6982400
+49594.00   0.018609   0.169415   0.6968824    0.018400    0.168600    0.6968200
+49595.00   0.016183   0.169907   0.6954573    0.016100    0.169000    0.6953800
+49596.00   0.013552   0.170355   0.6939768    0.013700    0.169400    0.6938700
+49597.00   0.010952   0.170717   0.6923683    0.011200    0.169800    0.6922400
+49598.00   0.008574   0.171044   0.6905787    0.008800    0.170200    0.6904400
+49599.00   0.006431   0.171426   0.6885696    0.006400    0.170700    0.6884300
+49600.00   0.004323   0.171935   0.6863372    0.004000    0.171000    0.6862300
+49601.00   0.002002   0.172597   0.6839238    0.001600    0.171800    0.6838300
+49602.00  -0.000616   0.173385   0.6814098   -0.000800    0.172700    0.6813000
+49603.00  -0.003456   0.174249   0.6788784   -0.003500    0.173600    0.6787400
+49604.00  -0.006148   0.175135   0.6763470   -0.006100    0.174600    0.6762100
+49605.00  -0.008596   0.176085   0.6738930   -0.008500    0.175500    0.6737700
+49606.00  -0.010833   0.177119   0.6715460   -0.010800    0.176500    0.6714500
+49607.00  -0.013072   0.178169   0.6692901   -0.013100    0.177400    0.6692100
+49608.00  -0.015556   0.179143   0.6670788   -0.015600    0.178200    0.6670100
+49609.00  -0.018422   0.179980   0.6648563   -0.018400    0.179100    0.6647800
+49610.00  -0.021599   0.180790   0.6625777   -0.021400    0.179800    0.6624700
+49611.00  -0.024813   0.181577   0.6601997   -0.024700    0.180600    0.6600700
+49612.00  -0.027798   0.182332   0.6576960   -0.027800    0.181300    0.6575600
+49613.00  -0.030505   0.183089   0.6551011   -0.030700    0.182200    0.6549800
+49614.00  -0.033007   0.183934   0.6524739   -0.033300    0.183100    0.6523600
+49615.00  -0.035461   0.184962   0.6498753   -0.035800    0.184200    0.6497700
+49616.00  -0.038015   0.186147   0.6473536   -0.038400    0.185400    0.6472300
+49617.00  -0.040832   0.187296   0.6449207   -0.041000    0.186600    0.6447800
+49618.00  -0.043818   0.188375   0.6426013   -0.043800    0.187700    0.6424600
+49619.00  -0.046775   0.189470   0.6404117   -0.046600    0.188700    0.6402600
+49620.00  -0.049585   0.190626   0.6383387   -0.049400    0.189700    0.6381900
+49621.00  -0.052280   0.191848   0.6363505   -0.052300    0.190900    0.6362000
+49622.00  -0.054909   0.193105   0.6344068   -0.055100    0.192100    0.6342700
+49623.00  -0.057521   0.194405   0.6324646   -0.057900    0.193600    0.6323400
+49624.00  -0.060233   0.195865   0.6304856   -0.060700    0.195100    0.6303600
+49625.00  -0.062857   0.197484   0.6284157   -0.063300    0.196800    0.6282800
+49626.00  -0.065164   0.199217   0.6261970   -0.065500    0.198500    0.6260500
+49627.00  -0.067149   0.201047   0.6237941   -0.067400    0.200300    0.6236400
+49628.00  -0.068989   0.202944   0.6212049   -0.069200    0.202200    0.6210500
+49629.00  -0.070976   0.204837   0.6184532   -0.071200    0.204000    0.6183100
+49630.00  -0.073424   0.206629   0.6155998   -0.073900    0.205500    0.6155100
+49631.00  -0.076446   0.208213   0.6127461   -0.076800    0.207100    0.6126800
+49632.00  -0.079838   0.209601   0.6100058   -0.080000    0.208600    0.6099500
+49633.00  -0.083262   0.210886   0.6074385   -0.083300    0.210000    0.6073700
+49634.00  -0.086479   0.212130   0.6050286   -0.086500    0.211300    0.6049500
+49635.00  -0.089290   0.213380   0.6027164   -0.089300    0.212600    0.6026200
+49636.00  -0.091505   0.214693   0.6004284   -0.091600    0.214000    0.6003300
+49637.00  -0.093166   0.216160   0.5981027   -0.093400    0.215500    0.5980000
+49638.00  -0.094538   0.217881   0.5957062   -0.094800    0.217200    0.5956100
+49639.00  -0.095750   0.219840   0.5932373   -0.095900    0.219100    0.5931400
+49640.00  -0.096889   0.221990   0.5907151   -0.096900    0.221100    0.5906300
+49641.00  -0.098078   0.224264   0.5881772   -0.098000    0.223400    0.5881000
+49642.00  -0.099501   0.226604   0.5856753   -0.099500    0.225700    0.5856200
+49643.00  -0.101377   0.228955   0.5832655   -0.101500    0.228000    0.5832200
+49644.00  -0.103841   0.231268   0.5809929   -0.104100    0.230300    0.5809500
+49645.00  -0.106752   0.233466   0.5788597   -0.107100    0.232600    0.5788000
+49646.00  -0.109750   0.235599   0.5768260   -0.110100    0.234900    0.5767600
+49647.00  -0.112530   0.237770   0.5748551   -0.112800    0.237100    0.5747800
+49648.00  -0.114973   0.239947   0.5729195   -0.115100    0.239300    0.5728500
+49649.00  -0.117092   0.242100   0.5709849   -0.117200    0.241300    0.5709100
+49650.00  -0.119084   0.244217   0.5690110   -0.119200    0.243300    0.5689300
+49651.00  -0.121195   0.246300   0.5669543   -0.121400    0.245300    0.5668700
+49652.00  -0.123525   0.248390   0.5647789   -0.123800    0.247300    0.5646900
+49653.00  -0.125949   0.250477   0.5624625   -0.126100    0.249400    0.5623800
+49654.00  -0.128152   0.252528   0.5599782   -0.128300    0.251500    0.5599200
+49655.00  -0.130001   0.254583   0.5573138   -0.130200    0.253700    0.5572700
+49656.00  -0.131520   0.256710   0.5544892   -0.131800    0.255900    0.5544400
+49657.00  -0.132859   0.258913   0.5515578   -0.133200    0.258200    0.5515000
+49658.00  -0.134179   0.261087   0.5485981   -0.134500    0.260400    0.5485300
+49659.00  -0.135582   0.263155   0.5457003   -0.135800    0.262600    0.5456100
+49660.00  -0.136997   0.265187   0.5429500   -0.137200    0.264900    0.5428600
+49661.00  -0.138425   0.267286   0.5403769   -0.138600    0.267000    0.5402800
+49662.00  -0.139887   0.269503   0.5379537   -0.140100    0.269100    0.5378600
+49663.00  -0.141344   0.271822   0.5356169   -0.141700    0.271300    0.5355300
+49664.00  -0.142740   0.274220   0.5333062   -0.143100    0.273600    0.5332300
+49665.00  -0.143972   0.276693   0.5309772   -0.144300    0.276000    0.5309100
+49666.00  -0.144804   0.279285   0.5285867   -0.145200    0.278700    0.5285300
+49667.00  -0.145287   0.281983   0.5261314   -0.145700    0.281400    0.5260800
+49668.00  -0.145653   0.284744   0.5236320   -0.146200    0.284200    0.5236000
+49669.00  -0.146085   0.287529   0.5211225   -0.146500    0.286900    0.5210900
+49670.00  -0.146623   0.290267   0.5186373   -0.146800    0.289600    0.5186000
+49671.00  -0.147213   0.292902   0.5162031   -0.147200    0.292300    0.5161600
+49672.00  -0.147808   0.295464   0.5138394   -0.147700    0.294900    0.5137800
+49673.00  -0.148488   0.298075   0.5115623   -0.148300    0.297500    0.5114900
+49674.00  -0.149331   0.300760   0.5093815   -0.149200    0.300200    0.5093100
+49675.00  -0.150308   0.303477   0.5072894   -0.150300    0.302900    0.5072100
+49676.00  -0.151335   0.306191   0.5052594   -0.151400    0.305600    0.5051700
+49677.00  -0.152336   0.308941   0.5032454   -0.152500    0.308400    0.5031400
+49678.00  -0.153136   0.311793   0.5011934   -0.153400    0.311100    0.5010800
+49679.00  -0.153511   0.314720   0.4990493   -0.153800    0.313900    0.4989500
+49680.00  -0.153354   0.317579   0.4967655   -0.153700    0.316700    0.4967000
+49681.00  -0.152777   0.320381   0.4943244   -0.153100    0.319500    0.4942900
+49682.00  -0.152113   0.323160   0.4917358   -0.152300    0.322300    0.4917300
+49683.00  -0.151650   0.325909   0.4890285   -0.151600    0.325100    0.4890400
+49684.00  -0.151460   0.328635   0.4862510   -0.151200    0.327900    0.4862600
+49685.00  -0.151383   0.331360   0.4834753   -0.151200    0.330600    0.4834500
+49686.00  -0.151275   0.334074   0.4807701   -0.151400    0.333400    0.4806900
+49687.00  -0.151498   0.336727   0.4781455   -0.151700    0.336100    0.4780300
+49688.00  -0.152003   0.339262   0.4756244   -0.152200    0.338700    0.4755000
+49689.00  -0.152556   0.341652   0.4732183   -0.152500    0.341100    0.4730900
+49690.00  -0.152865   0.343888   0.4708950   -0.152900    0.343200    0.4707300
+49691.00  -0.152737   0.346018   0.4685954   -0.152900    0.345300    0.4684300
+49692.00  -0.152319   0.348133   0.4662553   -0.152600    0.347400    0.4661100
+49693.00  -0.151855   0.350338   0.4638417   -0.152200    0.349600    0.4637200
+49694.00  -0.151502   0.352762   0.4613657   -0.151900    0.352100    0.4612800
+49695.00  -0.151377   0.355413   0.4588597   -0.151700    0.354700    0.4587800
+49696.00  -0.151519   0.358227   0.4563534   -0.151700    0.357600    0.4562800
+49697.00  -0.152018   0.361091   0.4538684   -0.152000    0.360500    0.4537800
+49698.00  -0.152813   0.363880   0.4514189   -0.152600    0.363300    0.4513200
+49699.00  -0.153503   0.366531   0.4490111   -0.153200    0.366000    0.4489200
+49700.00  -0.153781   0.369106   0.4466544   -0.153800    0.368500    0.4465900
+49701.00  -0.153973   0.371747   0.4443857   -0.154400    0.370900    0.4443300
+49702.00  -0.154240   0.374469   0.4421722   -0.154900    0.373300    0.4421100
+49703.00  -0.154662   0.377245   0.4399678   -0.155400    0.375900    0.4398900
+49704.00  -0.155272   0.380014   0.4377180   -0.156000    0.378700    0.4376300
+49705.00  -0.156060   0.382715   0.4353743   -0.156700    0.381500    0.4352700
+49706.00  -0.156932   0.385263   0.4328925   -0.157400    0.384300    0.4327900
+49707.00  -0.157709   0.387602   0.4302489   -0.158000    0.386800    0.4301800
+49708.00  -0.158271   0.389863   0.4274840   -0.158600    0.389100    0.4274400
+49709.00  -0.158674   0.392127   0.4246131   -0.159000    0.391400    0.4245700
+49710.00  -0.158946   0.394483   0.4216396   -0.159200    0.393700    0.4215900
+49711.00  -0.159032   0.397043   0.4185905   -0.159300    0.396200    0.4185400
+49712.00  -0.158912   0.399861   0.4155133   -0.159200    0.399100    0.4154600
+49713.00  -0.158656   0.402918   0.4124665   -0.159000    0.402200    0.4124000
+49714.00  -0.158336   0.406112   0.4095072   -0.158700    0.405500    0.4094300
+49715.00  -0.157891   0.409294   0.4066683   -0.158100    0.408700    0.4065700
+49716.00  -0.156905   0.412426   0.4039580   -0.157100    0.411700    0.4038300
+49717.00  -0.155298   0.415519   0.4013094   -0.155600    0.414800    0.4011600
+49718.00  -0.153189   0.418559   0.3986542   -0.153600    0.417700    0.3985000
+49719.00  -0.150825   0.421482   0.3959327   -0.151300    0.420500    0.3957900
+49720.00  -0.148493   0.424222   0.3931052   -0.148900    0.423300    0.3929800
+49721.00  -0.146361   0.426771   0.3901717   -0.146700    0.426000    0.3900700
+49722.00  -0.144479   0.429174   0.3871759   -0.144700    0.428500    0.3870900
+49723.00  -0.142828   0.431398   0.3841933   -0.143100    0.430800    0.3841100
+49724.00  -0.141374   0.433434   0.3812858   -0.141600    0.432800    0.3812000
+49725.00  -0.140045   0.435337   0.3785005   -0.140300    0.434700    0.3784200
+49726.00  -0.138689   0.437218   0.3758672   -0.138900    0.436700    0.3757900
+49727.00  -0.137139   0.439265   0.3734000   -0.137400    0.438800    0.3733300
+49728.00  -0.135392   0.441655   0.3710942   -0.135800    0.441100    0.3710100
+49729.00  -0.133709   0.444245   0.3689076   -0.134100    0.443500    0.3688100
+49730.00  -0.132167   0.446876   0.3667940   -0.132600    0.446100    0.3666900
+49731.00  -0.130820   0.449483   0.3647144   -0.131200    0.448700    0.3646100
+49732.00  -0.129771   0.452053   0.3626227   -0.130200    0.451300    0.3625200
+49733.00  -0.129050   0.454549   0.3604814   -0.129400    0.453800    0.3603800
+49734.00  -0.128552   0.456895   0.3582618   -0.128800    0.456200    0.3581600
+49735.00  -0.128075   0.459036   0.3559323   -0.128200    0.458300    0.3558300
+49736.00  -0.127274   0.460979   0.3534489   -0.127500    0.460200    0.3533500
+49737.00  -0.126173   0.462741   0.3508263   -0.126600    0.461900    0.3507400
+49738.00  -0.124927   0.464397   0.3480913   -0.125400    0.463400    0.3480000
+49739.00  -0.123597   0.466094   0.3452808   -0.124000    0.465200    0.3452000
+49740.00  -0.122176   0.468000   0.3424368   -0.122500    0.467100    0.3423600
+49741.00  -0.120697   0.470190   0.3396079   -0.120900    0.469400    0.3395300
+49742.00  -0.119243   0.472586   0.3368351   -0.119300    0.471900    0.3367500
+49743.00  -0.117856   0.475101   0.3341227   -0.117900    0.474400    0.3340300
+49744.00  -0.116658   0.477515   0.3314510   -0.116700    0.476800    0.3313600
+49745.00  -0.115778   0.479680   0.3287997   -0.115800    0.479000    0.3287100
+49746.00  -0.115216   0.481614   0.3261178   -0.115300    0.480900    0.3260400
+49747.00  -0.114986   0.483338   0.3233651   -0.115200    0.482600    0.3233000
+49748.00  -0.115087   0.484913   0.3205334   -0.115400    0.484200    0.3204800
+49749.00  -0.115431   0.486423   0.3176520   -0.115900    0.485700    0.3175900
+49750.00  -0.115770   0.487929   0.3147682   -0.116200    0.487200    0.3146800
+49751.00  -0.115750   0.489384   0.3119068   -0.116300    0.488600    0.3118000
+49752.00  -0.115037   0.490757   0.3090844   -0.115800    0.489900    0.3089800
+49753.00  -0.113739   0.492107   0.3063359   -0.114600    0.491300    0.3062500
+49754.00  -0.111844   0.493562   0.3036856   -0.112700    0.492800    0.3036200
+49755.00  -0.109299   0.495255   0.3011561   -0.110100    0.494600    0.3011100
+49756.00  -0.106276   0.497280   0.2987650   -0.107000    0.496600    0.2987300
+49757.00  -0.103092   0.499653   0.2965034   -0.103800    0.498900    0.2964500
+49758.00  -0.100159   0.502148   0.2943105   -0.100900    0.501300    0.2942500
+49759.00  -0.097808   0.504465   0.2921455   -0.098400    0.503500    0.2920700
+49760.00  -0.096094   0.506447   0.2899714   -0.096600    0.505500    0.2899000
+49761.00  -0.094893   0.508087   0.2877376   -0.095200    0.507300    0.2876600
+49762.00  -0.093920   0.509472   0.2853989   -0.094100    0.508700    0.2853100
+49763.00  -0.092755   0.510757   0.2829181   -0.092800    0.510100    0.2828300
+49764.00  -0.091000   0.512165   0.2802679   -0.091300    0.511400    0.2801800
+49765.00  -0.088903   0.513700   0.2774850   -0.089500    0.512800    0.2774100
+49766.00  -0.086820   0.515241   0.2746413   -0.087700    0.514200    0.2745700
+49767.00  -0.084959   0.516735   0.2718026   -0.085900    0.515600    0.2717300
+49768.00  -0.083343   0.518078   0.2690284   -0.084200    0.517000    0.2689500
+49769.00  -0.081869   0.519239   0.2663575   -0.082600    0.518400    0.2662800
+49770.00  -0.080396   0.520331   0.2637974   -0.081000    0.519800    0.2637300
+49771.00  -0.078734   0.521570   0.2613248   -0.079200    0.521300    0.2612700
+49772.00  -0.076638   0.523062   0.2588847   -0.077000    0.522800    0.2588400
+49773.00  -0.073891   0.524836   0.2564009   -0.074300    0.524500    0.2563800
+49774.00  -0.070608   0.526809   0.2538179   -0.071300    0.526200    0.2538100
+49775.00  -0.067041   0.528787   0.2511060   -0.067900    0.528000    0.2511100
+49776.00  -0.063404   0.530614   0.2482696   -0.064300    0.529700    0.2482600
+49777.00  -0.059834   0.532244   0.2453351   -0.060400    0.531300    0.2452600
+49778.00  -0.056421   0.533667   0.2423301   -0.057000    0.532700    0.2422100
+49779.00  -0.053150   0.534943   0.2392855   -0.053700    0.534200    0.2391700
+49780.00  -0.049859   0.536159   0.2362316   -0.050300    0.535400    0.2361300
+49781.00  -0.046533   0.537369   0.2332219   -0.047000    0.536600    0.2331600
+49782.00  -0.043210   0.538620   0.2303048   -0.043600    0.537800    0.2302700
+49783.00  -0.039960   0.539942   0.2275100   -0.040400    0.539000    0.2274800
+49784.00  -0.036857   0.541301   0.2248388   -0.037300    0.540300    0.2247700
+49785.00  -0.034054   0.542584   0.2222167   -0.034500    0.541600    0.2221100
+49786.00  -0.031586   0.543697   0.2195729   -0.032000    0.542800    0.2194600
+49787.00  -0.029449   0.544584   0.2168735   -0.029900    0.543800    0.2167900
+49788.00  -0.027596   0.545229   0.2141008   -0.028000    0.544400    0.2140400
+49789.00  -0.025967   0.545574   0.2112397   -0.026300    0.544800    0.2112100
+49790.00  -0.024318   0.545700   0.2082900   -0.024500    0.545000    0.2082700
+49791.00  -0.022230   0.545858   0.2052493   -0.022400    0.545200    0.2052000
+49792.00  -0.019570   0.546291   0.2020894   -0.019900    0.545500    0.2020200
+49793.00  -0.016638   0.547022   0.1988327   -0.017100    0.546100    0.1987600
+49794.00  -0.013712   0.547927   0.1955371   -0.014100    0.547000    0.1954600
+49795.00  -0.010970   0.548911   0.1922824   -0.011300    0.548000    0.1922100
+49796.00  -0.008609   0.549912   0.1891428   -0.009000    0.549000    0.1890800
+49797.00  -0.006664   0.550852   0.1861914   -0.007200    0.550000    0.1861400
+49798.00  -0.004915   0.551625   0.1834651   -0.005500    0.550700    0.1834100
+49799.00  -0.003080   0.552167   0.1809253   -0.003700    0.551200    0.1808400
+49800.00  -0.000718   0.552558   0.1784517   -0.001100    0.551600    0.1783400
+49801.00   0.002665   0.552945   0.1759392    0.002200    0.552000    0.1758500
+49802.00   0.007068   0.553526   0.1733344    0.006500    0.552600    0.1732600
+49803.00   0.012125   0.554424   0.1706200    0.011300    0.553600    0.1705600
+49804.00   0.017209   0.555609   0.1678072    0.016300    0.554800    0.1677500
+49805.00   0.021783   0.556881   0.1649300    0.021000    0.556000    0.1648600
+49806.00   0.025737   0.557853   0.1620269    0.025100    0.557000    0.1619500
+49807.00   0.029145   0.558411   0.1591455    0.028700    0.557600    0.1590500
+49808.00   0.032223   0.558606   0.1563266    0.031800    0.557800    0.1562300
+49809.00   0.035253   0.558563   0.1535919    0.034800    0.557700    0.1535000
+49810.00   0.038395   0.558415   0.1509506    0.037700    0.557500    0.1508600
+49811.00   0.041610   0.558191   0.1484005    0.041000    0.557300    0.1483300
+49812.00   0.044799   0.557877   0.1459346    0.044300    0.557000    0.1458700
+49813.00   0.048055   0.557657   0.1435147    0.047800    0.556900    0.1434500
+49814.00   0.051330   0.557646   0.1410720    0.051100    0.556800    0.1410100
+49815.00   0.054471   0.557796   0.1385650    0.054200    0.557000    0.1385200
+49816.00   0.057417   0.557972   0.1359808    0.057100    0.557200    0.1359400
+49817.00   0.060287   0.558056   0.1333095    0.059800    0.557300    0.1332500
+49818.00   0.063186   0.557998   0.1305124    0.062500    0.557300    0.1304400
+49819.00   0.066106   0.557795   0.1275648    0.065300    0.557100    0.1274900
+49820.00   0.069162   0.557477   0.1244732    0.068300    0.556600    0.1244100
+49821.00   0.072319   0.557059   0.1213199    0.071600    0.556200    0.1212700
+49822.00   0.075646   0.556623   0.1181739    0.075100    0.555700    0.1181200
+49823.00   0.079115   0.556274   0.1150863    0.078700    0.555400    0.1150300
+49824.00   0.082588   0.556036   0.1120940    0.082200    0.555100    0.1120400
+49825.00   0.085904   0.555871   0.1092209    0.085600    0.555000    0.1091800
+49826.00   0.088995   0.555759   0.1064576    0.088700    0.555000    0.1064300
+49827.00   0.091859   0.555687   0.1037831    0.091600    0.554900    0.1037200
+49828.00   0.094840   0.555488   0.1011338    0.094700    0.554700    0.1010300
+49829.00   0.098282   0.555027   0.0984390    0.097900    0.554300    0.0983000
+49830.00   0.101923   0.554313   0.0956750    0.101300    0.553600    0.0955200
+49831.00   0.105677   0.553421   0.0928361    0.105100    0.552800    0.0926800
+49832.00   0.109648   0.552409   0.0899362    0.109200    0.551800    0.0897900
+49833.00   0.113828   0.551295   0.0870060    0.113400    0.550600    0.0869000
+49834.00   0.118052   0.550083   0.0841042    0.117600    0.549400    0.0840200
+49835.00   0.122201   0.548781   0.0812932    0.121800    0.548000    0.0812200
+49836.00   0.126200   0.547400   0.0786103    0.125900    0.546600    0.0785400
+49837.00   0.130004   0.545963   0.0760682    0.129800    0.545100    0.0759800
+49838.00   0.133625   0.544472   0.0736575    0.133600    0.543700    0.0735500
+49839.00   0.137151   0.542978   0.0713226    0.137100    0.542200    0.0712000
+49840.00   0.140652   0.541540   0.0689971    0.140500    0.540700    0.0688500
+49841.00   0.144150   0.540101   0.0666340    0.144000    0.539100    0.0664900
+49842.00   0.147689   0.538598   0.0642119    0.147600    0.537600    0.0640600
+49843.00   0.151386   0.537040   0.0617241    0.151400    0.536000    0.0615800
+49844.00   0.155353   0.535497   0.0591702    0.155400    0.534400    0.0590300
+49845.00   0.159560   0.533999   0.0565425    0.159500    0.533000    0.0564200
+49846.00   0.163824   0.532527   0.0538021    0.163600    0.531600    0.0536900
+49847.00   0.167886   0.531033   0.0509297    0.167600    0.530200    0.0508200
+49848.00   0.171598   0.529473   0.0479442    0.171400    0.528700    0.0478400
+49849.00   0.174931   0.527820   0.0449067    0.175000    0.527100    0.0448200
+49850.00   0.178042   0.526120   0.0419048    0.178400    0.525500    0.0418100
+49851.00   0.181104   0.524458   0.0389846    0.181500    0.523800    0.0388900
+49852.00   0.184123   0.522872   0.0361612    0.184300    0.522100    0.0360800
+49853.00   0.187027   0.521341   0.0334480    0.186900    0.520400    0.0333900
+49854.00   0.189688   0.519782   0.0308279    0.189300    0.518700    0.0307800
+49855.00   0.191958   0.518055   0.0282646    0.191600    0.516900    0.0282100
+49856.00   0.193890   0.516107   0.0257150    0.193700    0.514900    0.0256500
+49857.00   0.195623   0.513903   0.0231537    0.195700    0.512800    0.0230700
+49858.00   0.197336   0.511469   0.0205831    0.197600    0.510400    0.0204900
+49859.00   0.199225   0.508960   0.0180327    0.199500    0.508100    0.0179500
+49860.00   0.201339   0.506500   0.0155409    0.201300    0.505700    0.0154600
+49861.00   0.203530   0.504116   0.0131463    0.203100    0.503400    0.0130500
+49862.00   0.205615   0.501788   0.0108704    0.205000    0.501000    0.0107500
+49863.00   0.207613   0.499451   0.0086859    0.207000    0.498600    0.0085600
+49864.00   0.209581   0.497026   0.0065837    0.209000    0.496100    0.0064700
+49865.00   0.211530   0.494489   0.0045724    0.211100    0.493600    0.0044800
+49866.00   0.213501   0.491824   0.0026326    0.213200    0.491000    0.0025600
+49867.00   0.215531   0.489023   0.0007373    0.215300    0.488400    0.0006700
+49868.00   0.217624   0.486128  -0.0011437    0.217400    0.485500   -0.0012200
+49869.00   0.219839   0.483227  -0.0030435    0.219700    0.482600   -0.0031400
+49870.00   0.222301   0.480281  -0.0050071    0.222200    0.479500   -0.0051200
+49871.00   0.225108   0.477193  -0.0070698    0.224900    0.476300   -0.0071900
+49872.00   0.228205   0.473977  -0.0092459    0.227900    0.473100   -0.0093500
+49873.00   0.231450   0.470731  -0.0115205    0.231000    0.469800   -0.0116100
+49874.00   0.234633   0.467602  -0.0138775    0.234200    0.466700   -0.0139500
+49875.00   0.237641   0.464714  -0.0162951    0.237400    0.463800   -0.0163700
+49876.00   0.240594   0.462046  -0.0187550    0.240300    0.461000   -0.0188200
+49877.00   0.243439   0.459261  -0.0212012    0.243100    0.458200   -0.0212500
+49878.00   0.246051   0.456323  -0.0235719    0.245600    0.455300   -0.0236100
+49879.00   0.248386   0.453343  -0.0258309    0.247900    0.452300   -0.0258700
+49880.00   0.250452   0.450340  -0.0279733    0.250100    0.449300   -0.0280200
+49881.00   0.252350   0.447248  -0.0300289    0.252100    0.446300   -0.0300900
+49882.00   0.254267   0.444027  -0.0320660    0.254200    0.443200   -0.0321300
+49883.00   0.256310   0.440739  -0.0341466    0.256200    0.440000   -0.0342100
+49884.00   0.258509   0.437481  -0.0362715    0.258400    0.436800   -0.0363500
+49885.00   0.260839   0.434277  -0.0384633    0.260600    0.433600   -0.0385600
+49886.00   0.263215   0.431106  -0.0407064    0.262900    0.430300   -0.0408200
+49887.00   0.265545   0.427896  -0.0429534    0.265100    0.427000   -0.0430700
+49888.00   0.267697   0.424553  -0.0451547    0.267300    0.423600   -0.0452600
+49889.00   0.269577   0.421018  -0.0472665    0.269200    0.420100   -0.0473600
+49890.00   0.271154   0.417398  -0.0492487    0.270800    0.416500   -0.0493200
+49891.00   0.272392   0.413796  -0.0510626    0.272100    0.412900   -0.0511200
+49892.00   0.273290   0.410267  -0.0526763    0.273000    0.409400   -0.0527200
+49893.00   0.273966   0.406811  -0.0540931    0.273700    0.405800   -0.0541400
+49894.00   0.274637   0.403337  -0.0553614    0.274400    0.402300   -0.0554100
+49895.00   0.275453   0.399721  -0.0565304    0.275100    0.398700   -0.0565800
+49896.00   0.276446   0.395963  -0.0576556    0.276100    0.395100   -0.0577100
+49897.00   0.277574   0.392210  -0.0588041    0.277300    0.391400   -0.0588700
+49898.00   0.278839   0.388463  -0.0600344    0.278600    0.387600   -0.0601100
+49899.00   0.280135   0.384623  -0.0613867    0.279900    0.383700   -0.0614700
+49900.00   0.281307   0.380660  -0.0628822    0.281100    0.379700   -0.0629700
+49901.00   0.282279   0.376569  -0.0645201    0.282100    0.375600   -0.0646000
+49902.00   0.283155   0.372366  -0.0662537    0.283000    0.371400   -0.0663200
+49903.00   0.284080   0.368160  -0.0680185    0.283900    0.367200   -0.0680800
+49904.00   0.284998   0.364071  -0.0697585    0.284700    0.363000   -0.0698300
+49905.00   0.285752   0.360096  -0.0714445    0.285500    0.358900   -0.0715200
+49906.00   0.286264   0.356144  -0.0730519    0.286100    0.354900   -0.0731300
+49907.00   0.286592   0.352185  -0.0745701    0.286500    0.351000   -0.0746500
+49908.00   0.286847   0.348271  -0.0760160    0.286800    0.347200   -0.0760900
+49909.00   0.287167   0.344456  -0.0774314    0.287100    0.343500   -0.0774900
+49910.00   0.287522   0.340770  -0.0788750    0.287200    0.339900   -0.0789200
+49911.00   0.287691   0.337184  -0.0803920    0.287400    0.336400   -0.0804300
+49912.00   0.287724   0.333635  -0.0819965    0.287400    0.332800   -0.0820500
+49913.00   0.287795   0.330040  -0.0836972    0.287500    0.329200   -0.0837700
+49914.00   0.287949   0.326344  -0.0854542    0.287600    0.325500   -0.0855200
+49915.00   0.288082   0.322556  -0.0872007    0.287700    0.321700   -0.0872600
+49916.00   0.288062   0.318743  -0.0888665    0.287800    0.317800   -0.0889200
+49917.00   0.287868   0.314950  -0.0904009    0.287700    0.313900   -0.0904600
+49918.00   0.287689   0.311145  -0.0917787    0.287600    0.309900   -0.0918600
+49919.00   0.287565   0.307292  -0.0929977    0.287400    0.306000   -0.0931000
+49920.00   0.287387   0.303396  -0.0940641    0.287100    0.302100   -0.0941900
+49921.00   0.287031   0.299471  -0.0950056    0.286700    0.298300   -0.0951400
+49922.00   0.286566   0.295521  -0.0958652    0.286300    0.294500   -0.0959900
+49923.00   0.286095   0.291575  -0.0966853    0.285800    0.290600   -0.0968000
+49924.00   0.285505   0.287660  -0.0975064    0.285100    0.286800   -0.0975900
+49925.00   0.284645   0.283792  -0.0983658    0.284300    0.282900   -0.0984300
+49926.00   0.283658   0.280001  -0.0992918    0.283300    0.279100   -0.0993500
+49927.00   0.282595   0.276263  -0.1003121    0.282200    0.275300   -0.1003800
+49928.00   0.281448   0.272477  -0.1014508    0.281100    0.271500   -0.1015400
+49929.00   0.280368   0.268586  -0.1027208    0.280100    0.267700   -0.1028100
+49930.00   0.279541   0.264644  -0.1041002    0.279200    0.263800   -0.1041800
+49931.00   0.278952   0.260708  -0.1055396    0.278500    0.259900   -0.1056100
+49932.00   0.278360   0.256799  -0.1069717    0.277900    0.255900   -0.1070400
+49933.00   0.277631   0.252861  -0.1083570    0.277200    0.251900   -0.1084400
+49934.00   0.276791   0.248912  -0.1096881    0.276500    0.248000   -0.1097900
+49935.00   0.275892   0.245043  -0.1109876    0.275900    0.244100   -0.1110900
+49936.00   0.274915   0.241303  -0.1122929    0.274800    0.240400   -0.1123800
+49937.00   0.273771   0.237673  -0.1136461    0.273500    0.236700   -0.1137100
+49938.00   0.272359   0.234099  -0.1150900    0.272100    0.233100   -0.1151400
+49939.00   0.270663   0.230520  -0.1166522    0.270600    0.229600   -0.1167000
+49940.00   0.269001   0.226934  -0.1183333    0.269100    0.226000   -0.1183800
+49941.00   0.267541   0.223342  -0.1200937    0.267600    0.222500   -0.1201600
+49942.00   0.266166   0.219764  -0.1218769    0.266100    0.218900   -0.1219600
+49943.00   0.264644   0.216284  -0.1236236    0.264400    0.215300   -0.1237100
+49944.00   0.262691   0.212933  -0.1252897    0.262400    0.211900   -0.1253800
+49945.00   0.260241   0.209642  -0.1268567    0.260100    0.208500   -0.1269500
+49946.00   0.257691   0.206449  -0.1283241    0.257700    0.205300   -0.1284100
+49947.00   0.255336   0.203412  -0.1296985    0.255300    0.202300   -0.1297800
+49948.00   0.253179   0.200506  -0.1310131    0.253000    0.199500   -0.1311000
+49949.00   0.251097   0.197685  -0.1323117    0.250800    0.196800   -0.1324000
+49950.00   0.249107   0.194904  -0.1336314    0.248900    0.194000   -0.1337000
+49951.00   0.247201   0.192091  -0.1350051    0.246900    0.191200   -0.1350600
+49952.00   0.245183   0.189208  -0.1364567    0.244800    0.188400   -0.1364900
+49953.00   0.242878   0.186348  -0.1379952    0.242600    0.185400   -0.1380200
+49954.00   0.240438   0.183450  -0.1396425    0.240300    0.182400   -0.1396900
+49955.00   0.238156   0.180477  -0.1414378    0.238000    0.179500   -0.1414900
+49956.00   0.236101   0.177546  -0.1433880    0.235800    0.176700   -0.1434400
+49957.00   0.234106   0.174753  -0.1454513    0.233600    0.173900   -0.1454900
+49958.00   0.232124   0.172120  -0.1475858    0.231500    0.171200   -0.1476000
+49959.00   0.229971   0.169548  -0.1496976    0.229300    0.168500   -0.1497300
+49960.00   0.227437   0.166958  -0.1517621    0.227000    0.165700   -0.1518200
+49961.00   0.224672   0.164364  -0.1537776    0.224600    0.163100   -0.1538500
+49962.00   0.221943   0.161813  -0.1557561    0.222000    0.160600   -0.1558300
+49963.00   0.219408   0.159389  -0.1577167    0.219600    0.158400   -0.1577800
+49964.00   0.217128   0.157140  -0.1596912    0.217200    0.156300   -0.1597400
+49965.00   0.215002   0.155058  -0.1617171    0.214800    0.154300   -0.1617900
+49966.00   0.212740   0.153069  -0.1638234    0.212500    0.152300   -0.1638800
+49967.00   0.210029   0.151075  -0.1660164    0.209800    0.150200   -0.1660900
+49968.00   0.206969   0.148852  -0.1682977    0.206900    0.147800   -0.1684000
+49969.00   0.203795   0.146375  -0.1706431    0.203600    0.145200   -0.1707500
+49970.00   0.200570   0.143742  -0.1729846    0.200300    0.142400   -0.1730900
+49971.00   0.197305   0.140984  -0.1752536    0.197000    0.139500   -0.1753400
+49972.00   0.194074   0.138110  -0.1774091    0.193700    0.136700   -0.1774800
+49973.00   0.191035   0.135293  -0.1794394    0.190800    0.134100   -0.1794900
+49974.00   0.188269   0.132860  -0.1813611    0.188000    0.131900   -0.1814000
+49975.00   0.185662   0.130861  -0.1832127    0.185400    0.129800   -0.1832300
+49976.00   0.182997   0.129117  -0.1850363    0.182800    0.127900   -0.1850200
+49977.00   0.180140   0.127395  -0.1868638    0.180200    0.126100   -0.1868200
+49978.00   0.177142   0.125569  -0.1887169    0.177500    0.124300   -0.1886600
+49979.00   0.174227   0.123629  -0.1906144    0.174600    0.122600   -0.1905900
+49980.00   0.171426   0.121661  -0.1925842    0.171500    0.120800   -0.1926200
+49981.00   0.168433   0.119799  -0.1946974    0.168300    0.119100   -0.1947900
+49982.00   0.165227   0.118066  -0.1969832    0.165000    0.117300   -0.1971000
+49983.00   0.161888   0.116469  -0.1994317    0.161700    0.115600   -0.1995500
+49984.00   0.158666   0.114917  -0.2020139    0.158400    0.113900   -0.2021200
+49985.00   0.155648   0.113415  -0.2046817    0.155400    0.112400   -0.2047700
+49986.00   0.152758   0.112022  -0.2073726    0.152500    0.111000   -0.2074300
+49987.00   0.149886   0.110801  -0.2100182    0.149700    0.109800   -0.2100500
+49988.00   0.147073   0.109840  -0.2125541    0.146900    0.108800   -0.2125800
+49989.00   0.144280   0.108970  -0.2149738    0.144100    0.107800   -0.2150100
+49990.00   0.141336   0.108038  -0.2173092    0.141100    0.106900   -0.2173700
+49991.00   0.138111   0.107025  -0.2196143    0.137900    0.105900   -0.2196900
+49992.00   0.134567   0.105987  -0.2219501    0.134300    0.105000   -0.2220200
+49993.00   0.130695   0.105001  -0.2243638    0.130600    0.104100   -0.2244200
+49994.00   0.126575   0.104045  -0.2268727    0.126600    0.103100   -0.2269100
+49995.00   0.122609   0.103062  -0.2294525    0.122500    0.102000   -0.2295000
+49996.00   0.118773   0.101939  -0.2320905    0.118500    0.100900   -0.2321600
+49997.00   0.114860   0.100643  -0.2347659    0.114600    0.099600   -0.2348500
+49998.00   0.110837   0.099201  -0.2374358    0.110600    0.098100   -0.2375100
+49999.00   0.106690   0.097625  -0.2400381    0.106400    0.096500   -0.2401000
+50000.00   0.102471   0.095946  -0.2425086    0.102200    0.094900   -0.2425500
+50001.00   0.098323   0.094278  -0.2448171    0.098200    0.093200   -0.2448700
+50002.00   0.094472   0.092742  -0.2469890    0.094400    0.091700   -0.2470300
+50003.00   0.090997   0.091469  -0.2490365    0.090900    0.090200   -0.2490800
+50004.00   0.087895   0.090594  -0.2509869    0.087800    0.089400   -0.2510300
+50005.00   0.084727   0.090020  -0.2528981    0.084800    0.088800   -0.2529600
+50006.00   0.081140   0.089428  -0.2548170    0.081100    0.088200   -0.2548900
+50007.00   0.077223   0.088633  -0.2567910    0.077100    0.087500   -0.2568600
+50008.00   0.073319   0.087696  -0.2588592    0.072900    0.086700   -0.2589200
+50009.00   0.069832   0.086810  -0.2610189    0.069400    0.085700   -0.2610700
+50010.00   0.066975   0.086104  -0.2632595    0.066600    0.084900   -0.2633200
+50011.00   0.064561   0.085696  -0.2656028    0.064500    0.084600   -0.2656600
+50012.00   0.062087   0.085544  -0.2680337    0.062100    0.084500   -0.2680800
+50013.00   0.059125   0.085440  -0.2705006    0.059000    0.084300   -0.2705500
+50014.00   0.055535   0.085180  -0.2729630    0.055100    0.084100   -0.2730200
+50015.00   0.051426   0.084676  -0.2753887    0.051100    0.083700   -0.2754500
+50016.00   0.047101   0.084034  -0.2777537    0.046900    0.083200   -0.2778100
+50017.00   0.042802   0.083316  -0.2800474    0.042600    0.082400   -0.2800900
+50018.00   0.038761   0.082671  -0.2823000    0.038600    0.081800   -0.2823500
+50019.00   0.035078   0.082295  -0.2845748    0.034900    0.081400   -0.2846300
+50020.00   0.031665   0.082253  -0.2869319    0.031500    0.081300   -0.2870000
+50021.00   0.028365   0.082439  -0.2894134    0.028200    0.081400   -0.2894800
+50022.00   0.025113   0.082725  -0.2920343    0.025000    0.081700   -0.2921000
+50023.00   0.021946   0.083061  -0.2947758    0.021800    0.082100   -0.2948200
+50024.00   0.018673   0.083419  -0.2975496    0.018300    0.082400   -0.2975700
+50025.00   0.015135   0.083780  -0.3002725    0.014900    0.082700   -0.3003000
+50026.00   0.011387   0.084118  -0.3028973    0.011200    0.083000   -0.3029300
+50027.00   0.007541   0.084428  -0.3053956    0.007600    0.083300   -0.3054500
+50028.00   0.003739   0.084751  -0.3077684    0.003700    0.083600   -0.3078300
+50029.00   0.000001   0.085124  -0.3100311   -0.000200    0.083900   -0.3100700
+50030.00  -0.003744   0.085488  -0.3121888   -0.004100    0.084300   -0.3122000
+50031.00  -0.007475   0.085790  -0.3142379   -0.007800    0.084600   -0.3142500
+50032.00  -0.011231   0.086077  -0.3162171   -0.011500    0.084900   -0.3162400
+50033.00  -0.014987   0.086408  -0.3181895   -0.015200    0.085300   -0.3182300
+50034.00  -0.018569   0.086804  -0.3202225   -0.018800    0.085700   -0.3202700
+50035.00  -0.021862   0.087327  -0.3223659   -0.022300    0.086300   -0.3224300
+50036.00  -0.025065   0.088127  -0.3246626   -0.025800    0.087100   -0.3247200
+50037.00  -0.028782   0.089292  -0.3271535   -0.029500    0.088100   -0.3271800
+50038.00  -0.033035   0.090654  -0.3298032   -0.033600    0.089400   -0.3298000
+50039.00  -0.037476   0.092091  -0.3325547   -0.037800    0.090800   -0.3325600
+50040.00  -0.041719   0.093516  -0.3353883   -0.042100    0.092200   -0.3354100
+50041.00  -0.045724   0.094850  -0.3382631   -0.046300    0.093600   -0.3383100
+50042.00  -0.049751   0.096014  -0.3411295   -0.050400    0.094800   -0.3411800
+50043.00  -0.053914   0.096986  -0.3439446   -0.054400    0.096000   -0.3440000
+50044.00  -0.057976   0.097979  -0.3466769   -0.058300    0.097200   -0.3467200
+50045.00  -0.061727   0.099130  -0.3493369   -0.061900    0.098300   -0.3493700
+50046.00  -0.065201   0.100487  -0.3519652   -0.065400    0.099600   -0.3519800
+50047.00  -0.068566   0.102026  -0.3546099   -0.068900    0.101000   -0.3546300
+50048.00  -0.071992   0.103675  -0.3573086   -0.072400    0.102600   -0.3573300
+50049.00  -0.075682   0.105386  -0.3600689   -0.076300    0.104400   -0.3601100
+50050.00  -0.079882   0.107134  -0.3628755   -0.080600    0.106100   -0.3629200
+50051.00  -0.084668   0.108887  -0.3656937   -0.085300    0.107800   -0.3657400
+50052.00  -0.089793   0.110581  -0.3684577   -0.090300    0.109500   -0.3685100
+50053.00  -0.094910   0.112190  -0.3711199   -0.095300    0.111200   -0.3711900
+50054.00  -0.099728   0.113810  -0.3736715   -0.100100    0.112800   -0.3737600
+50055.00  -0.104255   0.115578  -0.3761191   -0.104800    0.114500   -0.3762000
+50056.00  -0.108571   0.117528  -0.3784535   -0.109200    0.116400   -0.3785200
+50057.00  -0.112580   0.119567  -0.3806794   -0.113200    0.118500   -0.3807300
+50058.00  -0.116132   0.121605  -0.3828140   -0.116600    0.120700   -0.3828500
+50059.00  -0.119291   0.123582  -0.3849046   -0.119700    0.122700   -0.3849300
+50060.00  -0.122360   0.125522  -0.3870040   -0.122600    0.124600   -0.3870300
+50061.00  -0.125428   0.127453  -0.3891584   -0.125800    0.126400   -0.3891800
+50062.00  -0.128714   0.129439  -0.3913900   -0.129100    0.128400   -0.3914100
+50063.00  -0.132294   0.131545  -0.3937117   -0.132600    0.130400   -0.3937500
+50064.00  -0.135762   0.133872  -0.3961394   -0.135900    0.132800   -0.3961900
+50065.00  -0.138554   0.136542  -0.3986872   -0.138900    0.135500   -0.3987300
+50066.00  -0.140929   0.139485  -0.4013079   -0.141300    0.138400   -0.4013500
+50067.00  -0.143210   0.142573  -0.4039535   -0.143500    0.141400   -0.4040000
+50068.00  -0.145513   0.145731  -0.4066048   -0.145700    0.144600   -0.4066600
+50069.00  -0.147835   0.148873  -0.4092583   -0.148000    0.147700   -0.4093200
+50070.00  -0.150201   0.151908  -0.4118837   -0.150400    0.150800   -0.4119500
+50071.00  -0.152541   0.154799  -0.4144558   -0.152900    0.153700   -0.4145200
+50072.00  -0.154776   0.157666  -0.4169546   -0.155200    0.156600   -0.4170000
+50073.00  -0.156826   0.160665  -0.4193989   -0.157100    0.159500   -0.4194400
+50074.00  -0.158669   0.163912  -0.4218509   -0.158900    0.162800   -0.4218800
+50075.00  -0.160459   0.167387  -0.4243901   -0.160700    0.166200   -0.4244100
+50076.00  -0.162335   0.170951  -0.4270547   -0.162700    0.169900   -0.4270700
+50077.00  -0.164330   0.174443  -0.4298117   -0.164800    0.173400   -0.4298400
+50078.00  -0.166407   0.177742  -0.4325949   -0.167000    0.176600   -0.4326300
+50079.00  -0.168495   0.180798  -0.4353285   -0.169000    0.179500   -0.4353800
+50080.00  -0.170527   0.183633  -0.4379429   -0.170900    0.182300   -0.4379900
+50081.00  -0.172465   0.186350  -0.4403853   -0.172700    0.185100   -0.4404300
+50082.00  -0.174304   0.189077  -0.4426252   -0.174500    0.188000   -0.4426700
+50083.00  -0.175934   0.191874   0.5553429   -0.176200    0.190800    0.5552900
+50084.00  -0.177203   0.194733   0.5534992   -0.177700    0.193700    0.5534400
+50085.00  -0.178219   0.197661   0.5518040   -0.178700    0.196600    0.5517600
+50086.00  -0.179271   0.200769   0.5502108   -0.179700    0.199600    0.5501600
+50087.00  -0.180413   0.204061   0.5486679   -0.180700    0.202900    0.5486300
+50088.00  -0.181716   0.207436   0.5471137   -0.182100    0.206200    0.5471000
+50089.00  -0.183392   0.210670   0.5454827   -0.183900    0.209600    0.5454800
+50090.00  -0.185233   0.213575   0.5437364   -0.185700    0.212600    0.5437200
+50091.00  -0.186902   0.216171   0.5418803   -0.187100    0.215200    0.5418400
+50092.00  -0.188610   0.218633   0.5399478   -0.189000    0.217500    0.5399000
+50093.00  -0.190544   0.221323   0.5379721   -0.191000    0.220100    0.5379200
+50094.00  -0.192621   0.224329   0.5359773   -0.192700    0.223000    0.5359300
+50095.00  -0.194690   0.227472   0.5339774   -0.194800    0.226200    0.5339400
+50096.00  -0.196600   0.230482   0.5319852   -0.197000    0.229500    0.5319200
+50097.00  -0.198256   0.233199   0.5300178   -0.198600    0.232300    0.5299700
+50098.00  -0.199573   0.235746   0.5280928   -0.200000    0.234700    0.5280700
+50099.00  -0.200722   0.238434   0.5262338   -0.201300    0.237100    0.5262100
+50100.00  -0.202042   0.241575   0.5244563   -0.202500    0.240200    0.5244100
+50101.00  -0.203464   0.245190   0.5227037   -0.203700    0.244000    0.5227000
+50102.00  -0.204972   0.249073   0.5208840   -0.205300    0.248100    0.5209000
+50103.00  -0.206515   0.252890   0.5189387   -0.207100    0.252000    0.5189200
+50104.00  -0.208097   0.256437   0.5168645   -0.208500    0.255500    0.5168300
+50105.00  -0.209673   0.259782   0.5147185   -0.209900    0.258800    0.5146800
+50106.00  -0.210988   0.263176   0.5125896   -0.211400    0.262100    0.5125500
+50107.00  -0.211914   0.266751   0.5105347   -0.212400    0.265600    0.5104800
+50108.00  -0.212703   0.270456   0.5085976   -0.213000    0.269400    0.5085400
+50109.00  -0.213735   0.274297   0.5067973   -0.213900    0.273300    0.5067400
+50110.00  -0.215159   0.278183   0.5051407   -0.215500    0.277300    0.5051000
+50111.00  -0.216851   0.281901   0.5036132   -0.217200    0.281000    0.5035800
+50112.00  -0.218493   0.285363   0.5021832   -0.218800    0.284400    0.5021500
+50113.00  -0.219824   0.288726   0.5008057   -0.220200    0.287700    0.5007700
+50114.00  -0.220800   0.292186   0.4994203   -0.221300    0.290900    0.4993900
+50115.00  -0.221440   0.295824   0.4979729   -0.221800    0.294600    0.4979800
+50116.00  -0.221815   0.299586   0.4964256   -0.222200    0.298700    0.4964100
+50117.00  -0.222065   0.303384   0.4947668   -0.222300    0.302300    0.4947300
+50118.00  -0.222381   0.307187   0.4930004   -0.222400    0.305900    0.4929300
+50119.00  -0.222896   0.310942   0.4911259   -0.223200    0.309700    0.4910300
+50120.00  -0.223554   0.314574   0.4891368   -0.223900    0.313300    0.4890800
+50121.00  -0.224342   0.318023   0.4870476   -0.224600    0.316900    0.4870400
+50122.00  -0.225044   0.321171   0.4849035   -0.225300    0.320300    0.4848600
+50123.00  -0.225181   0.323983   0.4827588   -0.225300    0.322900    0.4827400
+50124.00  -0.224580   0.326681   0.4806567   -0.224700    0.325500    0.4806600
+50125.00  -0.223400   0.329470   0.4786206   -0.223900    0.328400    0.4786100
+50126.00  -0.221975   0.332497   0.4766505   -0.222400    0.331400    0.4766200
+50127.00  -0.220650   0.335894   0.4747223   -0.221000    0.334800    0.4746900
+50128.00  -0.219519   0.339747   0.4727933   -0.219800    0.338500    0.4727600
+50129.00  -0.218710   0.344051   0.4707968   -0.219100    0.342700    0.4707600
+50130.00  -0.218381   0.348607   0.4686632   -0.218900    0.347600    0.4686900
+50131.00  -0.218571   0.353126   0.4663566   -0.219000    0.352200    0.4664100
+50132.00  -0.219284   0.357369   0.4638910   -0.219800    0.356500    0.4639200
+50133.00  -0.220255   0.361221   0.4613243   -0.220800    0.360200    0.4613000
+50134.00  -0.221031   0.364694   0.4587397   -0.221300    0.363600    0.4586900
+50135.00  -0.221356   0.367982   0.4562191   -0.221700    0.366900    0.4562000
+50136.00  -0.221356   0.371356   0.4538542   -0.221500    0.369900    0.4538500
+50137.00  -0.221173   0.375065   0.4517135   -0.221400    0.373500    0.4516400
+50138.00  -0.220760   0.379108   0.4497550   -0.221200    0.378000    0.4496300
+50139.00  -0.220267   0.383241   0.4479084   -0.220700    0.382200    0.4477600
+50140.00  -0.219849   0.387230   0.4461162   -0.220100    0.386100    0.4459900
+50141.00  -0.219416   0.391075   0.4443430   -0.219800    0.390000    0.4442800
+50142.00  -0.218720   0.394877   0.4425576   -0.219200    0.393500    0.4425900
+50143.00  -0.217592   0.398724   0.4406961   -0.218100    0.397500    0.4407400
+50144.00  -0.216046   0.402709   0.4387105   -0.216400    0.401800    0.4386800
+50145.00  -0.214256   0.406820   0.4365826   -0.214400    0.405800    0.4365700
+50146.00  -0.212377   0.410989   0.4343027   -0.212700    0.409800    0.4343200
+50147.00  -0.210462   0.415165   0.4318862   -0.210800    0.413800    0.4318900
+50148.00  -0.208540   0.419342   0.4293659   -0.209000    0.418200    0.4293400
+50149.00  -0.206795   0.423380   0.4267812   -0.207100    0.422300    0.4267300
+50150.00  -0.205259   0.427213   0.4241680   -0.205900    0.425900    0.4241600
+50151.00  -0.203908   0.430867   0.4215619   -0.204300    0.429800    0.4216000
+50152.00  -0.202582   0.434377   0.4189899   -0.203000    0.433300    0.4190100
+50153.00  -0.201172   0.437787   0.4164748   -0.201800    0.436600    0.4164900
+50154.00  -0.199681   0.441159   0.4140508   -0.199800    0.440100    0.4140600
+50155.00  -0.198181   0.444555   0.4117438   -0.198600    0.443400    0.4117000
+50156.00  -0.196547   0.448062   0.4095361   -0.197100    0.447000    0.4094800
+50157.00  -0.194698   0.451546   0.4073526   -0.195100    0.450500    0.4073300
+50158.00  -0.192737   0.454954   0.4051230   -0.193100    0.453800    0.4051100
+50159.00  -0.190621   0.458387   0.4028131   -0.191100    0.457400    0.4028100
+50160.00  -0.188103   0.461977   0.4004263   -0.188700    0.460700    0.4004400
+50161.00  -0.185015   0.465952   0.3979922   -0.185500    0.464600    0.3979900
+50162.00  -0.181736   0.470274   0.3955522   -0.182000    0.469400    0.3955200
+50163.00  -0.178926   0.474524   0.3931553   -0.179100    0.473800    0.3931500
+50164.00  -0.176775   0.478401   0.3908599   -0.177000    0.477600    0.3908500
+50165.00  -0.175051   0.481739   0.3886987   -0.175600    0.480800    0.3886500
+50166.00  -0.173268   0.484606   0.3866632   -0.173900    0.483500    0.3866500
+50167.00  -0.171139   0.487249   0.3847174   -0.171600    0.486200    0.3847200
+50168.00  -0.168588   0.489916   0.3828287   -0.169100    0.488800    0.3828000
+50169.00  -0.165644   0.492745   0.3809636   -0.166000    0.491600    0.3809300
+50170.00  -0.162586   0.495671   0.3790850   -0.162900    0.494600    0.3790600
+50171.00  -0.159679   0.498650   0.3771505   -0.160200    0.497700    0.3771400
+50172.00  -0.156908   0.501603   0.3751298   -0.157200    0.500500    0.3751100
+50173.00  -0.154212   0.504539   0.3730040   -0.154600    0.503400    0.3729600
+50174.00  -0.151663   0.507519   0.3707596   -0.152300    0.506400    0.3708000
+50175.00  -0.149362   0.510501   0.3683888   -0.149700    0.509400    0.3685000
+50176.00  -0.147360   0.513289   0.3659173   -0.147900    0.512200    0.3659300
+50177.00  -0.145638   0.515645   0.3634127   -0.146000    0.514500    0.3633400
+50178.00  -0.143920   0.517579   0.3609107   -0.144200    0.516300    0.3609000
+50179.00  -0.142117   0.519318   0.3584370   -0.142300    0.518100    0.3584400
+50180.00  -0.140191   0.521063   0.3560213   -0.140400    0.519900    0.3560200
+50181.00  -0.137977   0.522959   0.3536761   -0.138500    0.521600    0.3536600
+50182.00  -0.135234   0.525188   0.3513918   -0.135700    0.523700    0.3513800
+50183.00  -0.132187   0.527816   0.3491286   -0.132700    0.526700    0.3491000
+50184.00  -0.129341   0.530702   0.3468257   -0.129400    0.529800    0.3468200
+50185.00  -0.126573   0.533654   0.3444367   -0.126700    0.532700    0.3444800
+50186.00  -0.123540   0.536510   0.3419479   -0.123800    0.535500    0.3419800
+50187.00  -0.120077   0.539229   0.3393835   -0.120300    0.538200    0.3393300
+50188.00  -0.116351   0.541835   0.3367947   -0.116700    0.540600    0.3367600
+50189.00  -0.112714   0.544371   0.3342362   -0.112900    0.543100    0.3342400
+50190.00  -0.109479   0.546890   0.3317556   -0.109600    0.545800    0.3317400
+50191.00  -0.106534   0.549353   0.3293821   -0.107000    0.548400    0.3293200
+50192.00  -0.103718   0.551690   0.3271622   -0.104200    0.550600    0.3271400
+50193.00  -0.100881   0.553900   0.3250953   -0.100900    0.552900    0.3250900
+50194.00  -0.097922   0.556020   0.3231337   -0.098000    0.554900    0.3231400
+50195.00  -0.094702   0.558058   0.3212225   -0.095100    0.556600    0.3212000
+50196.00  -0.091203   0.559985   0.3193323   -0.091300    0.558900    0.3192800
+50197.00  -0.087651   0.561722   0.3174315   -0.088000    0.560600    0.3174000
+50198.00  -0.084232   0.563198   0.3154816   -0.084800    0.562300    0.3154700
+50199.00  -0.080698   0.564540   0.3134595   -0.081100    0.563800    0.3134500
+50200.00  -0.076772   0.565959   0.3113307   -0.077100    0.564900    0.3113000
+50201.00  -0.072472   0.567693   0.3090793   -0.072700    0.566400    0.3090500
+50202.00  -0.068033   0.569841   0.3067111   -0.068300    0.568500    0.3066900
+50203.00  -0.063732   0.572237   0.3042392   -0.064000    0.571100    0.3042100
+50204.00  -0.059829   0.574547   0.3016817   -0.059900    0.573600    0.3016500
+50205.00  -0.056414   0.576487   0.2990626   -0.056600    0.575600    0.2990300
+50206.00  -0.053179   0.578097   0.2964375   -0.053500    0.577000    0.2964200
+50207.00  -0.049736   0.579512   0.2938736   -0.049900    0.578500    0.2938600
+50208.00  -0.045973   0.580829   0.2914053   -0.046000    0.579900    0.2913700
+50209.00  -0.042012   0.582102   0.2890282   -0.042100    0.581000    0.2890300
+50210.00  -0.037918   0.583347   0.2866998   -0.038000    0.582200    0.2867100
+50211.00  -0.033632   0.584594   0.2843591   -0.033800    0.583500    0.2843400
+50212.00  -0.029180   0.585848   0.2819499   -0.029300    0.584800    0.2819500
+50213.00  -0.024728   0.587025   0.2794478   -0.024900    0.586000    0.2794900
+50214.00  -0.020330   0.588093   0.2768482   -0.020800    0.587000    0.2768600
+50215.00  -0.015922   0.589125   0.2741811   -0.016300    0.587800    0.2741700
+50216.00  -0.011521   0.590154   0.2715088   -0.011700    0.589000    0.2714900
+50217.00  -0.007268   0.591099   0.2688973   -0.007800    0.589800    0.2688800
+50218.00  -0.003399   0.591911   0.2663992   -0.004000    0.590700    0.2663800
+50219.00  -0.000024   0.592626   0.2640413   -0.000300    0.591600    0.2640100
+50220.00   0.003144   0.593209   0.2618504    0.003000    0.592300    0.2618600
+50221.00   0.006435   0.593685   0.2598275    0.006000    0.592600    0.2598300
+50222.00   0.009919   0.594127   0.2579410    0.009700    0.592900    0.2579500
+50223.00   0.013491   0.594555   0.2561562    0.013400    0.593600    0.2561500
+50224.00   0.017124   0.594917   0.2544473    0.017100    0.593900    0.2544200
+50225.00   0.020937   0.595164   0.2527826    0.020800    0.594100    0.2527500
+50226.00   0.025152   0.595261   0.2511090    0.024800    0.594000    0.2511000
+50227.00   0.029779   0.595317   0.2493911    0.029600    0.594000    0.2493600
+50228.00   0.034665   0.595469   0.2476132    0.034400    0.594300    0.2476200
+50229.00   0.039753   0.595702   0.2457632    0.039400    0.594600    0.2457400
+50230.00   0.044841   0.595957   0.2438479    0.044700    0.594700    0.2438100
+50231.00   0.049615   0.596238   0.2418917    0.049500    0.594900    0.2418500
+50232.00   0.053882   0.596541   0.2399269    0.053800    0.595400    0.2398900
+50233.00   0.057700   0.596714   0.2379830    0.057500    0.595600    0.2379800
+50234.00   0.061444   0.596642   0.2361074    0.061200    0.595600    0.2361100
+50235.00   0.065503   0.596277   0.2343259    0.065300    0.595400    0.2343000
+50236.00   0.069860   0.595604   0.2326331    0.069800    0.594500    0.2326100
+50237.00   0.074230   0.594696   0.2309860    0.074300    0.593500    0.2309700
+50238.00   0.078467   0.593622   0.2293212    0.078400    0.592900    0.2292900
+50239.00   0.082604   0.592449   0.2275791    0.082300    0.591600    0.2275400
+50240.00   0.086784   0.591323   0.2257463    0.086400    0.590000    0.2257100
+50241.00   0.090816   0.590282   0.2238242    0.090500    0.589000    0.2237900
+50242.00   0.094546   0.589194   0.2218261    0.094500    0.588000    0.2218100
+50243.00   0.098025   0.587957   0.2197756    0.097900    0.586900    0.2198100
+50244.00   0.101457   0.586564   0.2177168    0.101200    0.585400    0.2177500
+50245.00   0.105120   0.585084   0.2157148    0.104900    0.583900    0.2156800
+50246.00   0.109158   0.583575   0.2138240    0.108900    0.582500    0.2137800
+50247.00   0.113468   0.581998   0.2120760    0.113200    0.580900    0.2121100
+50248.00   0.117895   0.580426   0.2104819    0.117800    0.579200    0.2104800
+50249.00   0.122258   0.578845   0.2090393    0.122200    0.577800    0.2089500
+50250.00   0.126467   0.577104   0.2077336    0.126100    0.576400    0.2077400
+50251.00   0.130498   0.575237   0.2065038    0.130300    0.574100    0.2064900
+50252.00   0.134268   0.573331   0.2053055    0.134300    0.572000    0.2052500
+50253.00   0.137862   0.571399   0.2040955    0.137800    0.570400    0.2040700
+50254.00   0.141523   0.569469   0.2028277    0.141400    0.568400    0.2028700
+50255.00   0.145303   0.567674   0.2014758    0.145100    0.566600    0.2015300
+50256.00   0.149172   0.566173   0.2000356    0.148900    0.565100    0.2000600
+50257.00   0.153039   0.564948   0.1985142    0.152900    0.564000    0.1984900
+50258.00   0.156765   0.563751   0.1969418    0.156600    0.562700    0.1969100
+50259.00   0.160185   0.562310   0.1953602    0.159800    0.561300    0.1953400
+50260.00   0.163281   0.560423   0.1938095    0.162900    0.559500    0.1937800
+50261.00   0.166362   0.558025   0.1923025    0.166200    0.556800    0.1923000
+50262.00   0.169493   0.555334   0.1908709    0.169200    0.554100    0.1908900
+50263.00   0.172608   0.552597   0.1895423    0.172200    0.551400    0.1895400
+50264.00   0.175817   0.549915   0.1883068    0.175600    0.548600    0.1882900
+50265.00   0.179070   0.547255   0.1871278    0.179000    0.545900    0.1871200
+50266.00   0.182205   0.544555   0.1859475    0.182300    0.543100    0.1859300
+50267.00   0.185266   0.541804   0.1846984    0.185200    0.540600    0.1846700
+50268.00   0.188487   0.539052   0.1833305    0.188100    0.537900    0.1833800
+50269.00   0.191979   0.536334   0.1818802    0.191700    0.534600    0.1820100
+50270.00   0.195778   0.533729   0.1804193    0.195600    0.531800    0.1805700
+50271.00   0.199792   0.531295   0.1790079    0.199700    0.529500    0.1791100
+50272.00   0.203823   0.528995   0.1776848    0.203900    0.527500    0.1777200
+50273.00   0.207687   0.526712   0.1764712    0.207800    0.525300    0.1764400
+50274.00   0.211388   0.524315   0.1753711    0.211100    0.523000    0.1753400
+50275.00   0.215158   0.521696   0.1743692    0.215000    0.520300    0.1743700
+50276.00   0.218752   0.518866   0.1734575    0.218500    0.517300    0.1734500
+50277.00   0.221889   0.515895   0.1726196    0.221500    0.514400    0.1725800
+50278.00   0.224827   0.512845   0.1718092    0.224800    0.511400    0.1718100
+50279.00   0.227709   0.509712   0.1709819    0.227600    0.508500    0.1710000
+50280.00   0.230519   0.506559   0.1701089    0.230200    0.505200    0.1701000
+50281.00   0.233085   0.503531   0.1691727    0.232800    0.502000    0.1691400
+50282.00   0.235301   0.500701   0.1681581    0.235000    0.499200    0.1681300
+50283.00   0.237275   0.497932   0.1670524    0.237200    0.497000    0.1670400
+50284.00   0.238918   0.495123   0.1658696    0.239100    0.493900    0.1658600
+50285.00   0.240184   0.492260   0.1646247    0.240000    0.490700    0.1645800
+50286.00   0.241314   0.489368   0.1633338    0.241100    0.487900    0.1632900
+50287.00   0.242591   0.486495   0.1620133    0.242800    0.484800    0.1620200
+50288.00   0.244009   0.483674   0.1606780    0.244000    0.482100    0.1606700
+50289.00   0.245469   0.480888   0.1593401    0.245000    0.479800    0.1593400
+50290.00   0.247079   0.478037   0.1580361    0.246800    0.476700    0.1580200
+50291.00   0.248835   0.475059   0.1567921    0.248700    0.473500    0.1567500
+50292.00   0.250734   0.472110   0.1555719    0.250700    0.470400    0.1555600
+50293.00   0.252661   0.469292   0.1543073    0.252700    0.467600    0.1542900
+50294.00   0.254453   0.466543   0.1529305    0.254300    0.465200    0.1529300
+50295.00   0.256087   0.463725   0.1513964    0.255900    0.462600    0.1513900
+50296.00   0.257649   0.460694   0.1497082    0.257700    0.459300    0.1496800
+50297.00   0.259242   0.457382   0.1479439    0.259000    0.456300    0.1479100
+50298.00   0.260754   0.453772   0.1462136    0.260500    0.452800    0.1461800
+50299.00   0.262152   0.449899   0.1446201    0.262200    0.448300    0.1445800
+50300.00   0.263615   0.445865   0.1432182    0.263600    0.444600    0.1432100
+50301.00   0.265323   0.441767   0.1420121    0.265100    0.440500    0.1420100
+50302.00   0.267376   0.437702   0.1409883    0.267100    0.436500    0.1410100
+50303.00   0.269796   0.433842   0.1401274    0.269400    0.432600    0.1401400
+50304.00   0.272298   0.430200   0.1393817    0.272200    0.429000    0.1394400
+50305.00   0.274464   0.426635   0.1386936    0.274400    0.425200    0.1386800
+50306.00   0.276292   0.423082   0.1380287    0.276000    0.421400    0.1379900
+50307.00   0.278048   0.419545   0.1373368    0.277800    0.418000    0.1372800
+50308.00   0.279980   0.416016   0.1365864    0.279900    0.414800    0.1365800
+50309.00   0.282112   0.412506   0.1357628    0.282000    0.411200    0.1357600
+50310.00   0.284194   0.409021   0.1348547    0.283900    0.407800    0.1348200
+50311.00   0.285973   0.405504   0.1338546    0.286100    0.404200    0.1338600
+50312.00   0.287390   0.401913   0.1327661    0.287200    0.400700    0.1327800
+50313.00   0.288667   0.398273   0.1316146    0.288100    0.396900    0.1315700
+50314.00   0.290024   0.394658   0.1304407    0.289900    0.393200    0.1304000
+50315.00   0.291404   0.391108   0.1292722    0.291000    0.389900    0.1292800
+50316.00   0.292692   0.387592   0.1281259    0.292200    0.386400    0.1281100
+50317.00   0.293933   0.384110   0.1270006    0.293900    0.382600    0.1269900
+50318.00   0.295088   0.380662   0.1258849    0.294800    0.379300    0.1258700
+50319.00   0.296087   0.377192   0.1247746    0.295600    0.376000    0.1247200
+50320.00   0.296841   0.373579   0.1236414    0.296700    0.372300    0.1235900
+50321.00   0.297290   0.369723   0.1224278    0.297100    0.368300    0.1224000
+50322.00   0.297493   0.365659   0.1210837    0.297000    0.364100    0.1210700
+50323.00   0.297670   0.361446   0.1195813    0.297300    0.360100    0.1195700
+50324.00   0.298033   0.357036   0.1178957    0.297900    0.355700    0.1179000
+50325.00   0.298180   0.352481   0.1160999    0.297700    0.351500    0.1161200
+50326.00   0.297996   0.347920   0.1142992    0.297500    0.346700    0.1143200
+50327.00   0.297595   0.343439   0.1125912    0.297200    0.342200    0.1126200
+50328.00   0.297111   0.339045   0.1110459    0.296800    0.337900    0.1111500
+50329.00   0.296552   0.334745   0.1096902    0.296500    0.333200    0.1098300
+50330.00   0.295960   0.330523   0.1085160    0.295700    0.329200    0.1085500
+50331.00   0.295473   0.326376   0.1074717    0.295100    0.325300    0.1073800
+50332.00   0.294897   0.322302   0.1065122    0.294600    0.321100    0.1064600
+50333.00   0.294281   0.318273   0.1055830    0.294000    0.316900    0.1055800
+50334.00   0.293581   0.314370   0.1046463    0.293300    0.313300    0.1046500
+50335.00   0.292918   0.310562   0.1036476    0.292600    0.309500    0.1036700
+50336.00   0.292468   0.306814   0.1025295    0.292200    0.305500    0.1025400
+50337.00   0.292078   0.303180   0.1012360    0.291700    0.302000    0.1012300
+50338.00   0.291441   0.299621   0.0997288    0.291100    0.298400    0.0997500
+50339.00   0.290440   0.295973   0.0980515    0.290200    0.294600    0.0980600
+50340.00   0.289166   0.292145   0.0962769    0.288800    0.291300    0.0962500
+50341.00   0.287719   0.288083   0.0944635    0.287500    0.287200    0.0944700
+50342.00   0.286237   0.283819   0.0926574    0.286000    0.282600    0.0927000
+50343.00   0.284921   0.279497   0.0909065    0.284000    0.278100    0.0908900
+50344.00   0.283911   0.275292   0.0892429    0.283300    0.274100    0.0892200
+50345.00   0.283203   0.271200   0.0876477    0.282900    0.270000    0.0876400
+50346.00   0.282657   0.267301   0.0860787    0.282500    0.266000    0.0860000
+50347.00   0.282139   0.263790   0.0844801    0.281900    0.262400    0.0844400
+50348.00   0.281419   0.260549   0.0828080    0.281100    0.259300    0.0828300
+50349.00   0.280372   0.257324   0.0809917    0.280100    0.256600    0.0810400
+50350.00   0.278936   0.253900   0.0789841    0.278500    0.253000    0.0790100
+50351.00   0.277230   0.250239   0.0767836    0.276800    0.249000    0.0767800
+50352.00   0.275516   0.246473   0.0744490    0.275400    0.245200    0.0744500
+50353.00   0.273808   0.242655   0.0720875    0.273500    0.241500    0.0720500
+50354.00   0.272150   0.238863   0.0698002    0.271400    0.237300    0.0697300
+50355.00   0.270516   0.235209   0.0676504    0.269700    0.233500    0.0676500
+50356.00   0.268914   0.231685   0.0656491    0.268400    0.230500    0.0656900
+50357.00   0.267380   0.228141   0.0637705    0.266800    0.227100    0.0638000
+50358.00   0.265754   0.224491   0.0619873    0.265200    0.223300    0.0619900
+50359.00   0.263829   0.220650   0.0603299    0.263400    0.219300    0.0603100
+50360.00   0.261799   0.216746   0.0587553    0.261400    0.215700    0.0587300
+50361.00   0.259851   0.213089   0.0572015    0.259500    0.212000    0.0571500
+50362.00   0.257961   0.209664   0.0556113    0.257600    0.208500    0.0555600
+50363.00   0.256087   0.206436   0.0539591    0.255700    0.205200    0.0539600
+50364.00   0.254144   0.203440   0.0522227    0.253800    0.202300    0.0522300
+50365.00   0.252026   0.200631   0.0503866    0.251600    0.199400    0.0503900
+50366.00   0.249757   0.197861   0.0484432    0.249400    0.196800    0.0484400
+50367.00   0.247358   0.194971   0.0464105    0.246900    0.193900    0.0463800
+50368.00   0.244908   0.191925   0.0443206    0.244400    0.190700    0.0443200
+50369.00   0.242479   0.188831   0.0422045    0.242000    0.187700    0.0422100
+50370.00   0.239981   0.185792   0.0400921    0.239500    0.184700    0.0401100
+50371.00   0.237451   0.182854   0.0380178    0.236900    0.181500    0.0380400
+50372.00   0.235135   0.180027   0.0360083    0.234600    0.178800    0.0360100
+50373.00   0.232875   0.177326   0.0340670    0.232300    0.176200    0.0340600
+50374.00   0.230420   0.174678   0.0321772    0.230000    0.173400    0.0321500
+50375.00   0.227845   0.172031   0.0302706    0.227500    0.170800    0.0302700
+50376.00   0.225250   0.169455   0.0282566    0.224900    0.168300    0.0283100
+50377.00   0.222714   0.166943   0.0261129    0.222200    0.165600    0.0261100
+50378.00   0.220149   0.164399   0.0238554    0.219700    0.163000    0.0238100
+50379.00   0.217347   0.161682   0.0215014    0.217100    0.160500    0.0215000
+50380.00   0.214308   0.158809   0.0190585    0.213900    0.157900    0.0190400
+50381.00   0.211321   0.155815   0.0166062    0.210900    0.154600    0.0165600
+50382.00   0.208747   0.152758   0.0142398    0.208300    0.151400    0.0142000
+50383.00   0.206648   0.149723   0.0120193    0.206100    0.148400    0.0119700
+50384.00   0.204727   0.146782   0.0099692    0.204300    0.145500    0.0099500
+50385.00   0.202616   0.143945   0.0080787    0.202100    0.142900    0.0080900
+50386.00   0.200095   0.141147   0.0063248    0.199500    0.139900    0.0063400
+50387.00   0.197246   0.138301   0.0046700    0.197100    0.137000    0.0046300
+50388.00   0.194360   0.135259   0.0030512    0.194300    0.134100    0.0030100
+50389.00   0.191481   0.132248   0.0014209    0.191000    0.130900    0.0014500
+50390.00   0.188491   0.129471  -0.0002731    0.188200    0.128200   -0.0002500
+50391.00   0.185317   0.126988  -0.0020740    0.185100    0.125800   -0.0021100
+50392.00   0.181928   0.124826  -0.0040039    0.181500    0.123400   -0.0040700
+50393.00   0.178262   0.122939  -0.0060643    0.177700    0.121700   -0.0060700
+50394.00   0.174164   0.121176  -0.0082014    0.173600    0.120000   -0.0081500
+50395.00   0.170037   0.119377  -0.0103803    0.169500    0.118000   -0.0104100
+50396.00   0.166197   0.117456  -0.0125639    0.165800    0.116000   -0.0126300
+50397.00   0.162466   0.115589  -0.0146986    0.162100    0.114300   -0.0147400
+50398.00   0.158663   0.113955  -0.0167781    0.158200    0.112600   -0.0168200
+50399.00   0.154633   0.112544  -0.0188187    0.154300    0.111200   -0.0188400
+50400.00   0.150422   0.111200  -0.0208427    0.150200    0.109900   -0.0208200
+50401.00   0.146079   0.109862  -0.0228148    0.145700    0.108800   -0.0228400
+50402.00   0.141568   0.108374  -0.0246957    0.141500    0.107300   -0.0247200
+50403.00   0.137457   0.106632  -0.0265370    0.137400    0.105400   -0.0264900
+50404.00   0.134081   0.104805  -0.0284527    0.133700    0.103500   -0.0284100
+50405.00   0.131054   0.103105  -0.0304736    0.130800    0.101900   -0.0304600
+50406.00   0.128026   0.101643  -0.0325821    0.127800    0.100400   -0.0325900
+50407.00   0.125019   0.100437  -0.0347399    0.124600    0.099200   -0.0347400
+50408.00   0.122162   0.099507  -0.0369011    0.121700    0.098300   -0.0369000
+50409.00   0.119269   0.098733  -0.0390000    0.118800    0.097400   -0.0390000
+50410.00   0.116042   0.097932  -0.0409795    0.115600    0.096900   -0.0409600
+50411.00   0.112575   0.097007  -0.0428249    0.112100    0.096000   -0.0427700
+50412.00   0.108895   0.096055  -0.0445572    0.108500    0.094800   -0.0444900
+50413.00   0.105076   0.095273  -0.0462060    0.104700    0.094000   -0.0461600
+50414.00   0.101293   0.094701  -0.0478085    0.100900    0.093400   -0.0478000
+50415.00   0.097465   0.094238  -0.0493838    0.097000    0.093200   -0.0493900
+50416.00   0.093540   0.093769  -0.0509576    0.093000    0.092800   -0.0509700
+50417.00   0.089593   0.093199  -0.0525574    0.089100    0.092000   -0.0525600
+50418.00   0.085827   0.092517  -0.0542025    0.085800    0.091500   -0.0541800
+50419.00   0.082281   0.091772  -0.0558923    0.082300    0.090600   -0.0558700
+50420.00   0.078743   0.091073  -0.0576114    0.078300    0.089700   -0.0576100
+50421.00   0.074984   0.090512  -0.0593535    0.074600    0.089400   -0.0593300
+50422.00   0.070877   0.089989  -0.0611357    0.070700    0.089000   -0.0611100
+50423.00   0.066593   0.089367  -0.0629445    0.066600    0.088100   -0.0629300
+50424.00   0.062411   0.088604  -0.0647376    0.062400    0.087300   -0.0647300
+50425.00   0.058416   0.087729  -0.0664852    0.058100    0.086500   -0.0664800
+50426.00   0.054504   0.086825  -0.0681764    0.054200    0.085500   -0.0681700
+50427.00   0.050574   0.085999  -0.0698227    0.050200    0.084500   -0.0697800
+50428.00   0.046689   0.085384  -0.0714549    0.046200    0.084100   -0.0714300
+50429.00   0.043010   0.085082  -0.0731165    0.042500    0.084000   -0.0731400
+50430.00   0.039688   0.085081  -0.0748463    0.039400    0.083000   -0.0748400
+50431.00   0.036684   0.085362  -0.0766865    0.036500    0.083600   -0.0766400
+50432.00   0.033789   0.085870  -0.0786548    0.033500    0.084600   -0.0786500
+50433.00   0.030822   0.086510  -0.0807293    0.030700    0.085300   -0.0807400
+50434.00   0.027731   0.087197  -0.0828705    0.027600    0.085900   -0.0828800
+50435.00   0.024552   0.087895  -0.0850383    0.024300    0.086600   -0.0850300
+50436.00   0.021384   0.088618  -0.0871961    0.020900    0.087200   -0.0871800
+50437.00   0.018204   0.089314  -0.0892816    0.017800    0.088000   -0.0892900
+50438.00   0.015098   0.089938  -0.0912487    0.014900    0.088500   -0.0912500
+50439.00   0.012264   0.090507  -0.0931030    0.012000    0.089100   -0.0930700
+50440.00   0.009778   0.091040  -0.0948805    0.009400    0.089700   -0.0948400
+50441.00   0.007387   0.091534  -0.0966031    0.007100    0.090300   -0.0965900
+50442.00   0.004683   0.091983  -0.0982859    0.004500    0.090800   -0.0982600
+50443.00   0.001482   0.092365  -0.0999606    0.001200    0.091300   -0.0999300
+50444.00  -0.002138   0.092697  -0.1016613   -0.002300    0.091500   -0.1016500
+50445.00  -0.006054   0.093050  -0.1034141   -0.006000    0.091700   -0.1034200
+50446.00  -0.010233   0.093503  -0.1052325   -0.010500    0.092100   -0.1052300
+50447.00  -0.014631   0.094090  -0.1071181   -0.014800    0.092900   -0.1071000
+50448.00  -0.019065   0.094720  -0.1090616   -0.019400    0.093700   -0.1090300
+50449.00  -0.023125   0.095292  -0.1110467   -0.023120    0.095270   -0.1110260
+50450.00  -0.026846   0.095921  -0.1130512   -0.026650    0.095730   -0.1129910
+50451.00  -0.030356   0.096804  -0.1150536   -0.030320    0.096580   -0.1150660
+50452.00  -0.033659   0.098009  -0.1170274   -0.033580    0.097740   -0.1170900
+50453.00  -0.036894   0.099459  -0.1189536   -0.036610    0.099330   -0.1189530
+50454.00  -0.040341   0.100969  -0.1208302   -0.040400    0.100800   -0.1208340
+50455.00  -0.043963   0.102347  -0.1226704   -0.044180    0.102110   -0.1226990
+50456.00  -0.047384   0.103560  -0.1245101   -0.047410    0.103440   -0.1245240
+50457.00  -0.050363   0.104719  -0.1263955   -0.050390    0.104490   -0.1264190
+50458.00  -0.053191   0.105897  -0.1283614   -0.053080    0.105700   -0.1283790
+50459.00  -0.056069   0.107078  -0.1304323   -0.055890    0.106970   -0.1304310
+50460.00  -0.058933   0.108271  -0.1325930   -0.058900    0.108160   -0.1326170
+50461.00  -0.061619   0.109534  -0.1348093   -0.061840    0.109360   -0.1347970
+50462.00  -0.063963   0.110918  -0.1370449   -0.063990    0.110710   -0.1370150
+50463.00  -0.066046   0.112506  -0.1392469   -0.065980    0.112380   -0.1392600
+50464.00  -0.068034   0.114400  -0.1413615   -0.068080    0.114440   -0.1413620
+50465.00  -0.069960   0.116470  -0.1433426   -0.069680    0.115950   -0.1433430
+50466.00  -0.071941   0.118545  -0.1451623   -0.071350    0.117780   -0.1451910
+50467.00  -0.074152   0.120610  -0.1468202   -0.074030    0.120500   -0.1468210
+50468.00  -0.076773   0.122686  -0.1483487   -0.076670    0.122510   -0.1483560
+50469.00  -0.079660   0.124753  -0.1497922   -0.079820    0.124740   -0.1498140
+50470.00  -0.082335   0.126769  -0.1512048   -0.082480    0.126830   -0.1512110
+50471.00  -0.084929   0.128732  -0.1526485   -0.084950    0.128440   -0.1526570
+50472.00  -0.087687   0.130552  -0.1541269   -0.087820    0.130140   -0.1541470
+50473.00  -0.090542   0.132279  -0.1556175   -0.090550    0.132210   -0.1556260
+50474.00  -0.093642   0.133992  -0.1571430   -0.093280    0.134020   -0.1571430
+50475.00  -0.096798   0.135756  -0.1587242   -0.096530    0.135560   -0.1586830
+50476.00  -0.099828   0.137597  -0.1603627   -0.099770    0.137440   -0.1603380
+50477.00  -0.102756   0.139487  -0.1620217   -0.102820    0.139450   -0.1620400
+50478.00  -0.105545   0.141428  -0.1636253   -0.105760    0.141240   -0.1636150
+50479.00  -0.108317   0.143490  -0.1651635   -0.108290    0.143260   -0.1651560
+50480.00  -0.111349   0.145610  -0.1666459   -0.111150    0.145580   -0.1666790
+50481.00  -0.114391   0.147746  -0.1680324   -0.114590    0.147850   -0.1680380
+50482.00  -0.117215   0.149884  -0.1693291   -0.117340    0.149870   -0.1693300
+50483.00  -0.119869   0.152077  -0.1705907   -0.119820    0.151850   -0.1705910
+50484.00  -0.122471   0.154427  -0.1718955   -0.122580    0.154440   -0.1718900
+50485.00  -0.124786   0.156838  -0.1733379   -0.124840    0.156950   -0.1733440
+50486.00  -0.126743   0.159259  -0.1749635   -0.126880    0.159370   -0.1749570
+50487.00  -0.128511   0.161777  -0.1767825   -0.128590    0.161690   -0.1767640
+50488.00  -0.130350   0.164433  -0.1787477   -0.130260    0.164120   -0.1787810
+50489.00  -0.132250   0.167200  -0.1807865   -0.132220    0.167330   -0.1807960
+50490.00  -0.134165   0.170000  -0.1828595   -0.134060    0.170390   -0.1828460
+50491.00  -0.136191   0.172752  -0.1849226   -0.136190    0.172770   -0.1849320
+50492.00  -0.138295   0.175444  -0.1868678   -0.138400    0.175240   -0.1868910
+50493.00  -0.140379   0.178160  -0.1886653   -0.140490    0.178200   -0.1886420
+50494.00  -0.142530   0.180941  -0.1903477   -0.142460    0.181110   -0.1903170
+50495.00  -0.144884   0.183697  -0.1919402   -0.144880    0.183840   -0.1919650
+50496.00  -0.147478   0.186326  -0.1934698   -0.147590    0.186540   -0.1934630
+50497.00  -0.150122   0.188791  -0.1949925   -0.150110    0.188740   -0.1949620
+50498.00  -0.152594   0.191120  -0.1965482   -0.152560    0.191020   -0.1965500
+50499.00  -0.154965   0.193390  -0.1981573   -0.155120    0.193450   -0.1981660
+50500.00  -0.157097   0.195697  -0.1998452   -0.157190    0.195650   -0.1998380
+50501.00  -0.158915   0.198140  -0.2016223   -0.158970    0.197900   -0.2016180
+50502.00  -0.160453   0.200800  -0.2034968   -0.160360    0.200690   -0.2034930
+50503.00  -0.161818   0.203733  -0.2054597   -0.161690    0.203580   -0.2054440
+50504.00  -0.163299   0.206941  -0.2074795   -0.163220    0.206860   -0.2074620
+50505.00  -0.165215   0.210308  -0.2095110   -0.165150    0.210200   -0.2095060
+50506.00  -0.167652   0.213624  -0.2115238   -0.167740    0.213480   -0.2115180
+50507.00  -0.170138   0.216857  -0.2135309   -0.170330    0.216900   -0.2135090
+50508.00  -0.172256   0.220043  -0.2155422   -0.172380    0.219970   -0.2155140
+50509.00  -0.173879   0.223231  -0.2175595   -0.173970    0.223050   -0.2175420
+50510.00  -0.174995   0.226453  -0.2195849   -0.175070    0.226410   -0.2195720
+50511.00  -0.175740   0.229709  -0.2216355   -0.175650    0.229730   -0.2216320
+50512.00  -0.176415   0.232987  -0.2237518   -0.176420    0.232950   -0.2237540
+50513.00  -0.177300   0.236295  -0.2259897   -0.177190    0.236190   -0.2259670
+50514.00  -0.178558   0.239568  -0.2284127   -0.178250    0.239750   -0.2283680
+50515.00  -0.180253   0.242757  -0.2310411   -0.180110    0.242900   -0.2310240
+50516.00  -0.182213   0.245858  -0.2338346   -0.182130    0.245820   -0.2338510
+50517.00  -0.184152   0.248905  -0.2367006   -0.184210    0.248920   -0.2366890
+50518.00  -0.185660   0.251986  -0.2395438   -0.185880    0.251900   -0.2395060
+50519.00  -0.186433   0.255167  -0.2422867   -0.186520    0.255110   -0.2422750
+50520.00  -0.186654   0.258479  -0.2448840   -0.186640    0.258650   -0.2449000
+50521.00  -0.186547   0.262016  -0.2473473   -0.186430    0.261920   -0.2473450
+50522.00  -0.186532   0.265890  -0.2497212   -0.186230    0.265770   -0.2496900
+50523.00  -0.186927   0.270001  -0.2520565   -0.186860    0.270210   -0.2520300
+50524.00  -0.187669   0.274026  -0.2543915   -0.187830    0.274290   -0.2543900
+50525.00  -0.188374   0.277782  -0.2567473   -0.188480    0.277770   -0.2567630
+50526.00  -0.188751   0.281365  -0.2591447   -0.188700    0.281390   -0.2591520
+50527.00  -0.188948   0.284964  -0.2615966   -0.188980    0.285030   -0.2615730
+50528.00  -0.189277   0.288636  -0.2640664   -0.189010    0.288660   -0.2640260
+50529.00  -0.189584   0.292340  -0.2665641   -0.189180    0.292380   -0.2665350
+50530.00  -0.189715   0.296049  -0.2691041   -0.189770    0.296020   -0.2691000
+50531.00  -0.189650   0.299799  -0.2716708   -0.189710    0.299790   -0.2716640
+50532.00  -0.189501   0.303650  -0.2742439   -0.189510    0.303670   -0.2742150
+50533.00  -0.189576   0.307593  -0.2767977   -0.189610    0.307610   -0.2767820
+50534.00  -0.190011   0.311542  -0.2793072   -0.190060    0.311790   -0.2793000
+50535.00  -0.190465   0.315430  -0.2817635   -0.190390    0.315590   -0.2817270
+50536.00  -0.190817   0.319244  -0.2841799   -0.190700    0.319190   -0.2841550
+50537.00  -0.191111   0.322923  -0.2865724   -0.191090    0.323120   -0.2865830
+50538.00  -0.191277   0.326401  -0.2889662   -0.191330    0.326200   -0.2889710
+50539.00  -0.191095   0.329761  -0.2913990   -0.191030    0.329370   -0.2913530
+50540.00  -0.190396   0.333126  -0.2939066   -0.190470    0.333060   -0.2938890
+50541.00  -0.189369   0.336798  -0.2965213   -0.189510    0.336850   -0.2965170
+50542.00  -0.188326   0.340644  -0.2992707   -0.188320    0.340750   -0.2992520
+50543.00  -0.187324   0.344421  -0.3021543   -0.186950    0.344770   -0.3021410
+50544.00  -0.186426   0.348044  -0.3051186   -0.186080    0.348490   -0.3050560
+50545.00  -0.185573   0.351535  -0.3080759   -0.185710    0.351620   -0.3080380
+50546.00  -0.184596   0.354973  -0.3109377   -0.184670    0.355100   -0.3109070
+50547.00  -0.183491   0.358473  -0.3136437   -0.183910    0.358510   -0.3136330
+50548.00  -0.182447   0.362076  -0.3161928   -0.182710    0.362170   -0.3162020
+50549.00  -0.181423   0.365823  -0.3185995   -0.181650    0.365730   -0.3186020
+50550.00  -0.180458   0.369697  -0.3208959   -0.180750    0.369460   -0.3209070
+50551.00  -0.179741   0.373586  -0.3231184   -0.179540    0.373610   -0.3231080
+50552.00  -0.179301   0.377335  -0.3253059   -0.179130    0.377460   -0.3253080
+50553.00  -0.178935   0.380843  -0.3274896   -0.179170    0.381090   -0.3275180
+50554.00  -0.178449   0.384082  -0.3296974   -0.178510    0.384090   -0.3297100
+50555.00  -0.177770   0.387200  -0.3319711   -0.177840    0.387160   -0.3319570
+50556.00  -0.176894   0.390339  -0.3342906   -0.177080    0.390390   -0.3342830
+50557.00  -0.175898   0.393568  -0.3366294   -0.175800    0.393490   -0.3366160
+50558.00  -0.174918   0.396920  -0.3389891   -0.174820    0.396880   -0.3389690
+50559.00  -0.174074   0.400408  -0.3413517   -0.173790    0.400430   -0.3413440
+50560.00  -0.173393   0.404014  -0.3436733   -0.173130    0.404030   -0.3436830
+50561.00  -0.172759   0.407606  -0.3459204   -0.172750    0.407590   -0.3459270
+50562.00  -0.171839   0.410966  -0.3480859   -0.172230    0.411360   -0.3480680
+50563.00  -0.170499   0.414152  -0.3501739   -0.170760    0.414200   -0.3501490
+50564.00  -0.168831   0.417314  -0.3521945   -0.168870    0.417240   -0.3521830
+50565.00  -0.167106   0.420468  -0.3541611   -0.167060    0.420570   -0.3541560
+50566.00  -0.165634   0.423541  -0.3561064   -0.165470    0.423620   -0.3560980
+50567.00  -0.164540   0.426430  -0.3580823   -0.164390    0.426550   -0.3580740
+50568.00  -0.163574   0.429110  -0.3601397   -0.163620    0.429130   -0.3601370
+50569.00  -0.162447   0.431668  -0.3623133   -0.162550    0.431430   -0.3623130
+50570.00  -0.160959   0.434208  -0.3645947   -0.161010    0.434320   -0.3645950
+50571.00  -0.158952   0.436863  -0.3669830   -0.159020    0.437110   -0.3669560
+50572.00  -0.156442   0.439744  -0.3694605   -0.156530    0.439490   -0.3694140
+50573.00  -0.153614   0.442881  -0.3719702   -0.153640    0.442850   -0.3719270
+50574.00  -0.150798   0.446180  -0.3744440   -0.150610    0.446380   -0.3744430
+50575.00  -0.148127   0.449423  -0.3768402   -0.148120    0.449590   -0.3768500
+50576.00  -0.145405   0.452426  -0.3790965   -0.145420    0.452510   -0.3790580
+50577.00  -0.142482   0.455307  -0.3812199   -0.142440    0.455210   -0.3811930
+50578.00  -0.139426   0.458227  -0.3832642   -0.139410    0.458130   -0.3832900
+50579.00  -0.136461   0.461179  -0.3852533   -0.136280    0.461250   -0.3852540
+50580.00  -0.133867   0.464047  -0.3872115   -0.133860    0.464070   -0.3872040
+50581.00  -0.131687   0.466720  -0.3891616   -0.131640    0.466690   -0.3891660
+50582.00  -0.129668   0.469178  -0.3911154   -0.129560    0.469170   -0.3911180
+50583.00  -0.127578   0.471457  -0.3930758   -0.127760    0.471830   -0.3930820
+50584.00  -0.125217   0.473621  -0.3950526   -0.125190    0.473650   -0.3950390
+50585.00  -0.122492   0.475779  -0.3970639   -0.122280    0.475780   -0.3970140
+50586.00  -0.119535   0.478059  -0.3991144   -0.119350    0.478040   -0.3990670
+50587.00  -0.116559   0.480544  -0.4011911   -0.116500    0.480480   -0.4011750
+50588.00  -0.113641   0.483188  -0.4032818   -0.113540    0.483140   -0.4032990
+50589.00  -0.110776   0.485865  -0.4053710   -0.110730    0.485760   -0.4053930
+50590.00  -0.108256   0.488391  -0.4074257   -0.108270    0.488390   -0.4074370
+50591.00  -0.105963   0.490720  -0.4094314   -0.105880    0.490770   -0.4094310
+50592.00  -0.103700   0.492983  -0.4114046   -0.103560    0.492970   -0.4114080
+50593.00  -0.101447   0.495252  -0.4133742   -0.101400    0.495370   -0.4133980
+50594.00  -0.099172   0.497478  -0.4153798   -0.099110    0.497570   -0.4154060
+50595.00  -0.096785   0.499650  -0.4174722   -0.096900    0.499300   -0.4174680
+50596.00  -0.094267   0.501741  -0.4196953   -0.094180    0.501500   -0.4197000
+50597.00  -0.091850   0.503791  -0.4220672   -0.091740    0.504070   -0.4220830
+50598.00  -0.089584   0.505799  -0.4245581   -0.089680    0.506070   -0.4245640
+50599.00  -0.087350   0.507760  -0.4270965   -0.087270    0.507660   -0.4271100
+50600.00  -0.085071   0.509688  -0.4296072   -0.084900    0.509870   -0.4295920
+50601.00  -0.082698   0.511540  -0.4320282   -0.082550    0.511740   -0.4320310
+50602.00  -0.080141   0.513310  -0.4342951   -0.080290    0.513170   -0.4342640
+50603.00  -0.077450   0.515008  -0.4363661   -0.077560    0.514830   -0.4363590
+50604.00  -0.074955   0.516512  -0.4382224   -0.074960    0.516480   -0.4382470
+50605.00  -0.072662   0.517746  -0.4398921   -0.072650    0.517730   -0.4398790
+50606.00  -0.070423   0.518722  -0.4414443   -0.070340    0.518680   -0.4414520
+50607.00  -0.068053   0.519422  -0.4429291   -0.068210    0.519640   -0.4429350
+50608.00  -0.065268   0.519887  -0.4443891   -0.065500    0.520040   -0.4443870
+50609.00  -0.061898   0.520349  -0.4458636   -0.061880    0.520140   -0.4458620
+50610.00  -0.058127   0.521097  -0.4473822   -0.058090    0.520920   -0.4473900
+50611.00  -0.054367   0.522302  -0.4489535   -0.054330    0.522280   -0.4489650
+50612.00  -0.050642   0.523897  -0.4505582   -0.050440    0.523870   -0.4505490
+50613.00  -0.046970   0.525560  -0.4521676   -0.046980    0.525830   -0.4521290
+50614.00  -0.043365   0.526958  -0.4537530   -0.043510    0.527200   -0.4537240
+50615.00  -0.039765   0.528003  -0.4552828   -0.039660    0.528020   -0.4552880
+50616.00  -0.036136   0.528829  -0.4567309   -0.036070    0.528570   -0.4567500
+50617.00  -0.032476   0.529592  -0.4580759   -0.032510    0.529440   -0.4580800
+50618.00  -0.028867   0.530411  -0.4592748   -0.028920    0.530430   -0.4592590
+50619.00  -0.025152   0.531246  -0.4603396   -0.025010    0.531400   -0.4603310
+50620.00  -0.021281   0.532003  -0.4613282   -0.021080    0.532140   -0.4613360
+50621.00  -0.017250   0.532620  -0.4623065   -0.017230    0.532690   -0.4623090
+50622.00  -0.013076   0.533105  -0.4633442   -0.012820    0.533010   -0.4633470
+50623.00  -0.008959   0.533538  -0.4644849   -0.008700    0.533480   -0.4644800
+50624.00  -0.005037   0.533969  -0.4657361   -0.004870    0.533880   -0.4657440
+50625.00  -0.001305   0.534422  -0.4670736   -0.001160    0.534400   -0.4670770
+50626.00   0.002419   0.534850  -0.4684479    0.002430    0.534990   -0.4684540
+50627.00   0.006322   0.535197  -0.4697869    0.006390    0.535310   -0.4698040
+50628.00   0.010476   0.535489  -0.4710285    0.010520    0.535600   -0.4710160
+50629.00   0.014809   0.535883  -0.4721332    0.014850    0.535860   -0.4721370
+50630.00   0.019205   0.536419   0.5269220    0.019150    0.536250    0.5268940
+50631.00   0.023493   0.536912   0.5261374    0.023390    0.536680    0.5261270
+50632.00   0.027452   0.537141   0.5254967    0.027540    0.537280    0.5255080
+50633.00   0.031223   0.537076   0.5249515    0.031140    0.536960    0.5249520
+50634.00   0.034962   0.536773   0.5244340    0.034850    0.536560    0.5244230
+50635.00   0.038689   0.536291   0.5238814    0.038740    0.536120    0.5238950
+50636.00   0.042534   0.535696   0.5232476    0.042370    0.535810    0.5232340
+50637.00   0.046663   0.535063   0.5225157    0.046380    0.534930    0.5224760
+50638.00   0.050873   0.534487   0.5216906    0.050830    0.534450    0.5216790
+50639.00   0.054750   0.534055   0.5207857    0.054960    0.534310    0.5207760
+50640.00   0.058275   0.533596   0.5198074    0.058500    0.533840    0.5198110
+50641.00   0.061703   0.532970   0.5187691    0.061880    0.533060    0.5187780
+50642.00   0.065250   0.532212   0.5176801    0.065180    0.532240    0.5176940
+50643.00   0.068880   0.531426   0.5165642    0.068750    0.531420    0.5166260
+50644.00   0.072463   0.530698   0.5154546    0.072390    0.530670    0.5154970
+50645.00   0.075783   0.530020   0.5143902    0.075690    0.529910    0.5143660
+50646.00   0.078739   0.529321   0.5133592    0.078780    0.529110    0.5133850
+50647.00   0.081527   0.528578   0.5122953    0.081560    0.528620    0.5123300
+50648.00   0.084482   0.527746   0.5111334    0.084430    0.527980    0.5111090
+50649.00   0.087863   0.526792   0.5098259    0.087470    0.526420    0.5098570
+50650.00   0.091630   0.525731   0.5083296    0.091370    0.525420    0.5083920
+50651.00   0.095462   0.524636   0.5066364    0.095540    0.524670    0.5066460
+50652.00   0.099070   0.523593   0.5047789    0.099300    0.523600    0.5047620
+50653.00   0.102369   0.522632   0.5028128    0.102360    0.522590    0.5028580
+50654.00   0.105406   0.521769   0.5007884    0.105250    0.521650    0.5008370
+50655.00   0.108028   0.520860   0.4988149    0.108100    0.520900    0.4987890
+50656.00   0.110314   0.519815   0.4969636    0.110350    0.519920    0.4969520
+50657.00   0.112515   0.518611   0.4952704    0.112490    0.518700    0.4952740
+50658.00   0.114866   0.517276   0.4937342    0.114770    0.517170    0.4937570
+50659.00   0.117460   0.515918   0.4923373    0.117530    0.515740    0.4923430
+50660.00   0.120245   0.514597   0.4910524    0.120280    0.514540    0.4910370
+50661.00   0.123226   0.513301   0.4898217    0.123130    0.513310    0.4898480
+50662.00   0.126325   0.512004   0.4885897    0.126390    0.512030    0.4885980
+50663.00   0.129373   0.510695   0.4873339    0.129470    0.510800    0.4872900
+50664.00   0.132300   0.509356   0.4860454    0.132500    0.509470    0.4860610
+50665.00   0.135125   0.507996   0.4847079    0.135210    0.508000    0.4847340
+50666.00   0.137790   0.506654   0.4833214    0.137730    0.506730    0.4833070
+50667.00   0.140168   0.505311   0.4818941    0.140190    0.505620    0.4819060
+50668.00   0.142406   0.503863   0.4804318    0.142330    0.503990    0.4804660
+50669.00   0.144656   0.502196   0.4789539    0.144720    0.502370    0.4789680
+50670.00   0.146894   0.500298   0.4774990    0.146900    0.500350    0.4775170
+50671.00   0.149084   0.498268   0.4761027    0.149040    0.498160    0.4761580
+50672.00   0.151262   0.496249   0.4747824    0.151260    0.496060    0.4748590
+50673.00   0.153451   0.494316   0.4735354    0.153290    0.494020    0.4735610
+50674.00   0.155554   0.492263   0.4723490    0.155510    0.492230    0.4723190
+50675.00   0.157518   0.490077   0.4711881    0.157600    0.489950    0.4711990
+50676.00   0.159400   0.487885   0.4699843    0.159390    0.487510    0.4700320
+50677.00   0.161219   0.485756   0.4686609    0.161220    0.485780    0.4686570
+50678.00   0.163022   0.483664   0.4671734    0.162940    0.483860    0.4671290
+50679.00   0.164917   0.481520   0.4655203    0.165070    0.481530    0.4655210
+50680.00   0.166942   0.479299   0.4637208    0.167120    0.479130    0.4637370
+50681.00   0.169141   0.476973   0.4618231    0.169090    0.476780    0.4617800
+50682.00   0.171583   0.474577   0.4599375    0.171650    0.474590    0.4599200
+50683.00   0.174167   0.472261   0.4581597    0.174220    0.472300    0.4581840
+50684.00   0.176778   0.470154   0.4565369    0.176740    0.470020    0.4564810
+50685.00   0.179283   0.468296   0.4550755    0.179480    0.468220    0.4549860
+50686.00   0.181563   0.466641   0.4537300    0.181730    0.466700    0.4537580
+50687.00   0.183704   0.465033   0.4524304    0.183670    0.465180    0.4524560
+50688.00   0.185879   0.463308   0.4511285    0.186040    0.463220    0.4510470
+50689.00   0.188047   0.461515   0.4498180    0.188200    0.461540    0.4497610
+50690.00   0.190182   0.459681   0.4484854    0.190040    0.459870    0.4484800
+50691.00   0.192397   0.457851   0.4471108    0.192810    0.457580    0.4470950
+50692.00   0.194835   0.456075   0.4456687    0.195190    0.455900    0.4456580
+50693.00   0.197512   0.454304   0.4441490    0.197410    0.454390    0.4441620
+50694.00   0.200273   0.452464   0.4425676    0.199960    0.452670    0.4425770
+50695.00   0.202819   0.450531   0.4409528    0.202790    0.450800    0.4409470
+50696.00   0.204834   0.448415   0.4393440    0.204910    0.448760    0.4393220
+50697.00   0.206425   0.446053   0.4377641    0.206370    0.446300    0.4377530
+50698.00   0.207950   0.443508   0.4362179    0.207950    0.443560    0.4362150
+50699.00   0.209613   0.440941   0.4347090    0.209570    0.440850    0.4347020
+50700.00   0.211333   0.438467   0.4332717    0.211080    0.438240    0.4332700
+50701.00   0.212799   0.435949   0.4319120    0.212530    0.435910    0.4319150
+50702.00   0.214129   0.433249   0.4305354    0.213980    0.433250    0.4305350
+50703.00   0.215443   0.430595   0.4290757    0.215450    0.430440    0.4290670
+50704.00   0.216636   0.428209   0.4274979    0.216880    0.428020    0.4275020
+50705.00   0.217447   0.426056   0.4257653    0.217650    0.426110    0.4257870
+50706.00   0.217825   0.423914   0.4238243    0.218030    0.424210    0.4238360
+50707.00   0.217939   0.421578   0.4216578    0.218030    0.421720    0.4216490
+50708.00   0.218042   0.419053   0.4193071    0.217980    0.419020    0.4192990
+50709.00   0.218405   0.416554   0.4168661    0.218320    0.416550    0.4168570
+50710.00   0.219060   0.414120   0.4144571    0.219070    0.414120    0.4144540
+50711.00   0.219824   0.411705   0.4121859    0.219840    0.411700    0.4122050
+50712.00   0.220552   0.409271   0.4100988    0.220580    0.409270    0.4101310
+50713.00   0.221159   0.406759   0.4081784    0.221230    0.406690    0.4081940
+50714.00   0.221544   0.404116   0.4063782    0.221670    0.403970    0.4063660
+50715.00   0.221639   0.401267   0.4046411    0.221680    0.400980    0.4046340
+50716.00   0.221427   0.398075   0.4029151    0.221290    0.397770    0.4029280
+50717.00   0.221148   0.394691   0.4011444    0.221180    0.394520    0.4011560
+50718.00   0.220967   0.391340   0.3992871    0.220850    0.391110    0.3992790
+50719.00   0.220896   0.388141   0.3973575    0.220760    0.387900    0.3973340
+50720.00   0.220936   0.385125   0.3953779    0.220990    0.385200    0.3953510
+50721.00   0.221029   0.382236   0.3933771    0.221110    0.382080    0.3933600
+50722.00   0.221183   0.379339   0.3913652    0.221130    0.379260    0.3913550
+50723.00   0.221438   0.376317   0.3893063    0.221440    0.376660    0.3893070
+50724.00   0.221678   0.373215   0.3872347    0.221760    0.373380    0.3872330
+50725.00   0.221852   0.370134   0.3852065    0.221910    0.370090    0.3852180
+50726.00   0.222066   0.367211   0.3832492    0.222050    0.367100    0.3832650
+50727.00   0.222328   0.364524   0.3813624    0.222270    0.364270    0.3813700
+50728.00   0.222531   0.362045   0.3795218    0.222490    0.361950    0.3795040
+50729.00   0.222583   0.359663   0.3776878    0.222450    0.359630    0.3776800
+50730.00   0.222463   0.357334   0.3758081    0.222590    0.357400    0.3758620
+50731.00   0.222364   0.354973   0.3738415    0.222250    0.355160    0.3739320
+50732.00   0.222546   0.352483   0.3717573    0.222270    0.352650    0.3718190
+50733.00   0.223066   0.349874   0.3695248    0.223130    0.349980    0.3695390
+50734.00   0.223742   0.347247   0.3671319    0.224030    0.347190    0.3671270
+50735.00   0.224350   0.344654   0.3646101    0.224420    0.344320    0.3646070
+50736.00   0.224829   0.342047   0.3620202    0.224770    0.341830    0.3620180
+50737.00   0.225233   0.339341   0.3594312    0.225390    0.339510    0.3594170
+50738.00   0.225513   0.336514   0.3569238    0.225690    0.336490    0.3568930
+50739.00   0.225723   0.333587   0.3545707    0.225510    0.333780    0.3545530
+50740.00   0.226071   0.330617   0.3524006    0.225840    0.330710    0.3524200
+50741.00   0.226734   0.327713   0.3503925    0.226660    0.327500    0.3504260
+50742.00   0.227583   0.324971   0.3485072    0.227620    0.324710    0.3485250
+50743.00   0.228135   0.322377   0.3467023    0.228130    0.322290    0.3467090
+50744.00   0.228073   0.319805   0.3449452    0.227930    0.319980    0.3449410
+50745.00   0.227639   0.317177   0.3431894    0.227590    0.317140    0.3431750
+50746.00   0.227015   0.314451   0.3413928    0.227000    0.314360    0.3413770
+50747.00   0.226260   0.311590   0.3395366    0.226170    0.311650    0.3395010
+50748.00   0.225349   0.308591   0.3376163    0.225500    0.308760    0.3375650
+50749.00   0.224117   0.305464   0.3356391    0.224230    0.305610    0.3356010
+50750.00   0.222553   0.302189   0.3336090    0.222490    0.302310    0.3336030
+50751.00   0.220887   0.298780   0.3315353    0.221120    0.298860    0.3315420
+50752.00   0.219360   0.295439   0.3294279    0.219130    0.295250    0.3294120
+50753.00   0.218197   0.292331   0.3272972    0.217830    0.292330    0.3272540
+50754.00   0.217440   0.289537   0.3251797    0.217660    0.290260    0.3251270
+50755.00   0.216911   0.287060   0.3231026    0.217200    0.287420    0.3230750
+50756.00   0.216413   0.284799   0.3210639    0.216380    0.285030    0.3210520
+50757.00   0.215856   0.282591   0.3190230    0.215990    0.282700    0.3190130
+50758.00   0.215208   0.280313   0.3168940    0.215420    0.280340    0.3168880
+50759.00   0.214575   0.278014   0.3146522    0.214490    0.278000    0.3146430
+50760.00   0.213973   0.275719   0.3123008    0.213790    0.275840    0.3122920
+50761.00   0.213355   0.273388   0.3098278    0.213340    0.273380    0.3098240
+50762.00   0.212621   0.271003   0.3072218    0.212890    0.271220    0.3072180
+50763.00   0.211614   0.268548   0.3045421    0.211850    0.268880    0.3045330
+50764.00   0.210284   0.266043   0.3018805    0.210220    0.266070    0.3018760
+50765.00   0.208730   0.263564   0.2993329    0.208840    0.263480    0.2993360
+50766.00   0.207088   0.261177   0.2969961    0.207230    0.261170    0.2969980
+50767.00   0.205438   0.258919   0.2949190    0.205490    0.258980    0.2949020
+50768.00   0.203918   0.256761   0.2930689    0.203880    0.256780    0.2930260
+50769.00   0.202655   0.254669   0.2913779    0.202760    0.254780    0.2913250
+50770.00   0.201619   0.252564   0.2897821    0.201850    0.252560    0.2897440
+50771.00   0.200584   0.250318   0.2882163    0.200620    0.250230    0.2882030
+50772.00   0.199174   0.247864   0.2866280    0.199210    0.248060    0.2866450
+50773.00   0.197451   0.245209   0.2850227    0.197520    0.245450    0.2850530
+50774.00   0.195727   0.242394   0.2834162    0.195750    0.242480    0.2834300
+50775.00   0.194034   0.239527   0.2817959    0.194200    0.239640    0.2817920
+50776.00   0.192232   0.236767   0.2801566    0.192380    0.236780    0.2801520
+50777.00   0.190303   0.234238   0.2785077    0.190440    0.234200    0.2785100
+50778.00   0.188296   0.231988   0.2768699    0.188400    0.232120    0.2768720
+50779.00   0.186082   0.230043   0.2752722    0.186160    0.230400    0.2752670
+50780.00   0.183599   0.228284   0.2737303    0.183680    0.228470    0.2737230
+50781.00   0.180925   0.226584   0.2722504    0.181050    0.226750    0.2722450
+50782.00   0.178200   0.224851   0.2708259    0.178370    0.225150    0.2708160
+50783.00   0.175672   0.223009   0.2694351    0.175500    0.223390    0.2694290
+50784.00   0.173588   0.221047   0.2680505    0.173170    0.221480    0.2680540
+50785.00   0.171942   0.219053   0.2666417    0.171810    0.219080    0.2666530
+50786.00   0.170344   0.217157   0.2651830    0.170440    0.217090    0.2651940
+50787.00   0.168527   0.215369   0.2636186    0.168750    0.215580    0.2636170
+50788.00   0.166342   0.213626   0.2618905    0.166520    0.213890    0.2618910
+50789.00   0.163903   0.211872   0.2599495    0.164000    0.212020    0.2599740
+50790.00   0.161422   0.210090   0.2577994    0.161480    0.210280    0.2578130
+50791.00   0.159046   0.208306   0.2555327    0.159250    0.208410    0.2555200
+50792.00   0.157016   0.206578   0.2532611    0.157260    0.206590    0.2532500
+50793.00   0.155360   0.204964   0.2510794    0.155610    0.204990    0.2510800
+50794.00   0.153813   0.203422   0.2490314    0.154140    0.203490    0.2490330
+50795.00   0.151960   0.201840   0.2471484    0.152290    0.202230    0.2471530
+50796.00   0.149526   0.200084   0.2454378    0.149870    0.200740    0.2454510
+50797.00   0.146669   0.198079   0.2438609    0.146680    0.198370    0.2438760
+50798.00   0.143768   0.195933   0.2423544    0.143740    0.196060    0.2423610
+50799.00   0.141075   0.193902   0.2408754    0.141160    0.194160    0.2408750
+50800.00   0.138876   0.192194   0.2393864    0.139040    0.192400    0.2393930
+50801.00   0.137047   0.190980   0.2378658    0.137340    0.191070    0.2378620
+50802.00   0.134949   0.190057   0.2362873    0.135090    0.190480    0.2362660
+50803.00   0.132348   0.189130   0.2346470    0.132320    0.189640    0.2346450
+50804.00   0.129498   0.188011   0.2329639    0.129690    0.188190    0.2329880
+50805.00   0.126543   0.186609   0.2312498    0.126820    0.186830    0.2312730
+50806.00   0.123555   0.184907   0.2295451    0.123590    0.185080    0.2295430
+50807.00   0.120723   0.183142   0.2278943    0.120750    0.183220    0.2278720
+50808.00   0.118041   0.181462   0.2263238    0.118120    0.181490    0.2263070
+50809.00   0.115429   0.179926   0.2248520    0.115510    0.179870    0.2248460
+50810.00   0.112782   0.178571   0.2234795    0.112950    0.178530    0.2234750
+50811.00   0.110042   0.177409   0.2221795    0.110410    0.177530    0.2221700
+50812.00   0.107282   0.176420   0.2208913    0.107600    0.176500    0.2208800
+50813.00   0.104669   0.175520   0.2195567    0.104840    0.175500    0.2195510
+50814.00   0.102330   0.174610   0.2181268    0.102620    0.174590    0.2181430
+50815.00   0.100067   0.173756   0.2165474    0.100400    0.173810    0.2165920
+50816.00   0.097717   0.173046   0.2147880    0.097860    0.173110    0.2148370
+50817.00   0.095308   0.172486   0.2128524    0.095580    0.172660    0.2128680
+50818.00   0.092881   0.172032   0.2107892    0.093160    0.172300    0.2107640
+50819.00   0.090425   0.171596   0.2087156    0.090530    0.171710    0.2086890
+50820.00   0.087912   0.171078   0.2067344    0.088120    0.171270    0.2067320
+50821.00   0.085272   0.170438   0.2048885    0.085520    0.170630    0.2048730
+50822.00   0.082407   0.169723   0.2032072    0.082510    0.169920    0.2031800
+50823.00   0.079324   0.169046   0.2016899    0.079420    0.168960    0.2016870
+50824.00   0.076072   0.168515   0.2002746    0.076390    0.168470    0.2002920
+50825.00   0.072675   0.168147   0.1988820    0.072880    0.168310    0.1988680
+50826.00   0.069398   0.167910   0.1974576    0.069500    0.167940    0.1974300
+50827.00   0.066566   0.167768   0.1959508    0.066770    0.167790    0.1959580
+50828.00   0.063657   0.167608   0.1943544    0.063900    0.167680    0.1943530
+50829.00   0.060477   0.167464   0.1927001    0.060510    0.167550    0.1926850
+50830.00   0.057260   0.167422   0.1910127    0.057290    0.167510    0.1910200
+50831.00   0.054151   0.167516   0.1892952    0.054110    0.167560    0.1893100
+50832.00   0.051100   0.167743   0.1875474    0.051120    0.167890    0.1875500
+50833.00   0.047984   0.167986   0.1857901    0.048350    0.168320    0.1857890
+50834.00   0.044715   0.168028   0.1840492    0.044980    0.168210    0.1840490
+50835.00   0.041334   0.167746   0.1823291    0.041680    0.167720    0.1823160
+50836.00   0.037958   0.167314   0.1806273    0.038150    0.167320    0.1806180
+50837.00   0.034688   0.166906   0.1789316    0.034730    0.167260    0.1789340
+50838.00   0.031556   0.166612   0.1772322    0.031770    0.167010    0.1772150
+50839.00   0.028551   0.166534   0.1755271    0.028770    0.166600    0.1754970
+50840.00   0.025795   0.166733   0.1737632    0.025910    0.166860    0.1737480
+50841.00   0.023234   0.167166   0.1718530    0.023200    0.167300    0.1718700
+50842.00   0.020394   0.167717   0.1697221    0.020430    0.167790    0.1697400
+50843.00   0.017343   0.168286   0.1673762    0.017520    0.168400    0.1673530
+50844.00   0.014234   0.168811   0.1648804    0.014380    0.168980    0.1648510
+50845.00   0.011108   0.169359   0.1623325    0.011350    0.169560    0.1623420
+50846.00   0.007955   0.170019   0.1597821    0.007820    0.170180    0.1597890
+50847.00   0.004686   0.170837   0.1572725    0.004450    0.170980    0.1572640
+50848.00   0.001321   0.171691   0.1548339    0.001740    0.171850    0.1548260
+50849.00  -0.001925   0.172410   0.1524679   -0.001740    0.172650    0.1524600
+50850.00  -0.004907   0.173114   0.1502065   -0.005010    0.173440    0.1501780
+50851.00  -0.007577   0.173869   0.1480662   -0.007560    0.174140    0.1480560
+50852.00  -0.010035   0.174566   0.1459967   -0.009850    0.174770    0.1460250
+50853.00  -0.012460   0.175079   0.1439594   -0.012370    0.175200    0.1439480
+50854.00  -0.015089   0.175334   0.1419780   -0.014930    0.175270    0.1419500
+50855.00  -0.017954   0.175401   0.1400520   -0.017950    0.175420    0.1400530
+50856.00  -0.020654   0.175617   0.1381159   -0.020750    0.175750    0.1381030
+50857.00  -0.023038   0.176036   0.1361486   -0.022900    0.176290    0.1361190
+50858.00  -0.025089   0.176594   0.1341574   -0.025110    0.176620    0.1341540
+50859.00  -0.026885   0.177371   0.1321610   -0.026860    0.177210    0.1321700
+50860.00  -0.028529   0.178429   0.1301747   -0.028500    0.178670    0.1302110
+50861.00  -0.030138   0.179743   0.1282129   -0.030170    0.179970    0.1282310
+50862.00  -0.032005   0.181204   0.1263079   -0.031880    0.181340    0.1262970
+50863.00  -0.034594   0.182632   0.1244965   -0.034580    0.182820    0.1244970
+50864.00  -0.037751   0.183914   0.1227247   -0.037650    0.184250    0.1227710
+50865.00  -0.041186   0.185022   0.1209348   -0.040900    0.185400    0.1210210
+50866.00  -0.044703   0.185960   0.1191234   -0.044630    0.186210    0.1191930
+50867.00  -0.047998   0.186807   0.1172605   -0.048200    0.186940    0.1172860
+50868.00  -0.050931   0.187634   0.1152941   -0.051200    0.187930    0.1152930
+50869.00  -0.053569   0.188438   0.1131771   -0.053470    0.188800    0.1131760
+50870.00  -0.055810   0.189277   0.1108978   -0.055720    0.189430    0.1109010
+50871.00  -0.057486   0.190283   0.1084770   -0.057560    0.190280    0.1084740
+50872.00  -0.058657   0.191598   0.1059310   -0.058660    0.191770    0.1059310
+50873.00  -0.059602   0.193205   0.1032905   -0.059380    0.193340    0.1033060
+50874.00  -0.060660   0.194960   0.1006586   -0.060390    0.194970    0.1006710
+50875.00  -0.062008   0.196729   0.0981386   -0.061790    0.196830    0.0981390
+50876.00  -0.063592   0.198476   0.0957946   -0.063460    0.198530    0.0957850
+50877.00  -0.065267   0.200360   0.0936210   -0.065140    0.200500    0.0935970
+50878.00  -0.066905   0.202319   0.0915841   -0.066730    0.202460    0.0915420
+50879.00  -0.068490   0.204312   0.0896482   -0.068240    0.204350    0.0895940
+50880.00  -0.070085   0.206386   0.0877786   -0.070080    0.206330    0.0877340
+50881.00  -0.071696   0.208509   0.0859377   -0.071740    0.208600    0.0859110
+50882.00  -0.073337   0.210604   0.0840788   -0.073230    0.210690    0.0840630
+50883.00  -0.074912   0.212602   0.0821452   -0.074840    0.212610    0.0821340
+50884.00  -0.076183   0.214536   0.0800910   -0.076150    0.214770    0.0801100
+50885.00  -0.077239   0.216649   0.0779831   -0.077210    0.216810    0.0780040
+50886.00  -0.078422   0.218857   0.0758586   -0.078270    0.219010    0.0758610
+50887.00  -0.080159   0.220952   0.0737412   -0.079990    0.221170    0.0737280
+50888.00  -0.082383   0.222816   0.0716611   -0.082370    0.222800    0.0716340
+50889.00  -0.084734   0.224483   0.0696389   -0.084700    0.224290    0.0696090
+50890.00  -0.086987   0.226085   0.0676945   -0.086850    0.226100    0.0676700
+50891.00  -0.089008   0.227692   0.0658367   -0.088830    0.227490    0.0658220
+50892.00  -0.090879   0.229385   0.0640498   -0.090580    0.229270    0.0640470
+50893.00  -0.092870   0.231116   0.0623018   -0.092640    0.231340    0.0623090
+50894.00  -0.094860   0.232676   0.0605486   -0.094790    0.232860    0.0605620
+50895.00  -0.096558   0.234047   0.0587419   -0.096640    0.234260    0.0587590
+50896.00  -0.097957   0.235445   0.0568313   -0.097950    0.235530    0.0568400
+50897.00  -0.099289   0.237069   0.0547597   -0.099210    0.237070    0.0547480
+50898.00  -0.100687   0.238870   0.0524515   -0.100620    0.239000    0.0524510
+50899.00  -0.102256   0.240823   0.0499414   -0.102090    0.240920    0.0499410
+50900.00  -0.104010   0.242915   0.0473499   -0.103850    0.242890    0.0473420
+50901.00  -0.105925   0.245145   0.0447784   -0.105760    0.245180    0.0447980
+50902.00  -0.107733   0.247444   0.0422919   -0.107670    0.247570    0.0423000
+50903.00  -0.109077   0.249741   0.0399650   -0.109050    0.249770    0.0399470
+50904.00  -0.109935   0.252103   0.0378239   -0.109830    0.252060    0.0378020
+50905.00  -0.110527   0.254548   0.0358353   -0.110280    0.254420    0.0358140
+50906.00  -0.111154   0.256961   0.0339580   -0.110870    0.256870    0.0339240
+50907.00  -0.112007   0.259254   0.0321401   -0.111810    0.259280    0.0321020
+50908.00  -0.112987   0.261411   0.0303301   -0.112870    0.261520    0.0303230
+50909.00  -0.113778   0.263513   0.0284947   -0.113770    0.263420    0.0285300
+50910.00  -0.114131   0.265742   0.0266181   -0.114090    0.265490    0.0266580
+50911.00  -0.114147   0.268209   0.0246935   -0.114030    0.268270    0.0247080
+50912.00  -0.113999   0.270830   0.0227298   -0.113910    0.270980    0.0227410
+50913.00  -0.113829   0.273649   0.0207804   -0.113910    0.273640    0.0207910
+50914.00  -0.113728   0.276606   0.0188422   -0.113670    0.276770    0.0188450
+50915.00  -0.113850   0.279529   0.0168902   -0.113640    0.279590    0.0168970
+50916.00  -0.114218   0.282316   0.0149437   -0.114090    0.282260    0.0149670
+50917.00  -0.114694   0.284973   0.0130558   -0.114540    0.285160    0.0130720
+50918.00  -0.115071   0.287594   0.0112541   -0.114800    0.287640    0.0112440
+50919.00  -0.114962   0.290211   0.0095180   -0.114880    0.290140    0.0095240
+50920.00  -0.114593   0.292907   0.0078497   -0.114520    0.292890    0.0078650
+50921.00  -0.114123   0.295738   0.0061926   -0.113800    0.295860    0.0061990
+50922.00  -0.113765   0.298599   0.0044955   -0.113500    0.298690    0.0044940
+50923.00  -0.113651   0.301376   0.0027115   -0.113460    0.301360    0.0027230
+50924.00  -0.113687   0.304101   0.0007922   -0.113590    0.304190    0.0008070
+50925.00  -0.113745   0.306874  -0.0013031   -0.113720    0.307070   -0.0012960
+50926.00  -0.113785   0.309763  -0.0035829   -0.113540    0.309850   -0.0035750
+50927.00  -0.113731   0.312527  -0.0060392   -0.113670    0.312610   -0.0060240
+50928.00  -0.113542   0.314955  -0.0086030   -0.113670    0.315030   -0.0085900
+50929.00  -0.113192   0.317088  -0.0111380   -0.113000    0.317070   -0.0111280
+50930.00  -0.112849   0.319179  -0.0135214   -0.112520    0.319060   -0.0135040
+50931.00  -0.112779   0.321423  -0.0156958   -0.112730    0.321280   -0.0156750
+50932.00  -0.113003   0.323784  -0.0176699   -0.113080    0.323640   -0.0176610
+50933.00  -0.113272   0.326044  -0.0195105   -0.113090    0.326010   -0.0195140
+50934.00  -0.113419   0.328142  -0.0212989   -0.113480    0.328220   -0.0213010
+50935.00  -0.113532   0.330140  -0.0230801   -0.113460    0.330150   -0.0230680
+50936.00  -0.113724   0.332146  -0.0248627   -0.113500    0.332250   -0.0248360
+50937.00  -0.113999   0.334250  -0.0266435   -0.113900    0.334350   -0.0266060
+50938.00  -0.114283   0.336511  -0.0284218   -0.114060    0.336460   -0.0283880
+50939.00  -0.114503   0.338910  -0.0302130   -0.114270    0.338950   -0.0301970
+50940.00  -0.114596   0.341219  -0.0320567   -0.114420    0.341170   -0.0320350
+50941.00  -0.114527   0.343367  -0.0339048   -0.114350    0.343360   -0.0338790
+50942.00  -0.114308   0.345406  -0.0357187   -0.114230    0.345460   -0.0357040
+50943.00  -0.113923   0.347417  -0.0374953   -0.113610    0.347380   -0.0374910
+50944.00  -0.113420   0.349476  -0.0392108   -0.113120    0.349430   -0.0392160
+50945.00  -0.112913   0.351594  -0.0408403   -0.112850    0.351680   -0.0408540
+50946.00  -0.112428   0.353738  -0.0423730   -0.112340    0.353770   -0.0423860
+50947.00  -0.111946   0.355832  -0.0438200   -0.111790    0.355760   -0.0438250
+50948.00  -0.111435   0.357812  -0.0452267   -0.111280    0.357820   -0.0452220
+50949.00  -0.110968   0.359665  -0.0466667   -0.110670    0.359770   -0.0466610
+50950.00  -0.110639   0.361433  -0.0482169   -0.110410    0.361540   -0.0482240
+50951.00  -0.110376   0.363189  -0.0499317   -0.110290    0.363160   -0.0499590
+50952.00  -0.110102   0.365018  -0.0518421   -0.110140    0.365110   -0.0518730
+50953.00  -0.109967   0.367001  -0.0539483   -0.109960    0.367090   -0.0539550
+50954.00  -0.109945   0.369171  -0.0562109   -0.109810    0.369190   -0.0561900
+50955.00  -0.109673   0.371698  -0.0585571   -0.109650    0.371850   -0.0585430
+50956.00  -0.109234   0.374455  -0.0609492   -0.109220    0.374630   -0.0609400
+50957.00  -0.108731   0.377218  -0.0632756   -0.108590    0.377330   -0.0632740
+50958.00  -0.108142   0.379851  -0.0654284   -0.107930    0.379900   -0.0654430
+50959.00  -0.107668   0.382295  -0.0673610   -0.107430    0.382270   -0.0673860
+50960.00  -0.107472   0.384492  -0.0690754   -0.107250    0.384510   -0.0690950
+50961.00  -0.107423   0.386358  -0.0705961   -0.107410    0.386640   -0.0706060
+50962.00  -0.107151   0.387984  -0.0719801   -0.107110    0.388050   -0.0719760
+50963.00  -0.106549   0.389639  -0.0733016   -0.106410    0.389480   -0.0732880
+50964.00  -0.105883   0.391519  -0.0746174   -0.105720    0.391520   -0.0746120
+50965.00  -0.105316   0.393568  -0.0759485   -0.105150    0.393650   -0.0759530
+50966.00  -0.104823   0.395623  -0.0772754   -0.104610    0.395670   -0.0772840
+50967.00  -0.104525   0.397545  -0.0785861   -0.104580    0.397600   -0.0785930
+50968.00  -0.104589   0.399252  -0.0798820   -0.104650    0.399280   -0.0798900
+50969.00  -0.104719   0.400837  -0.0811497   -0.104610    0.400860   -0.0811560
+50970.00  -0.104591   0.402402  -0.0823602   -0.104480    0.402480   -0.0823650
+50971.00  -0.104185   0.403981  -0.0834622   -0.104060    0.404030   -0.0834740
+50972.00  -0.103655   0.405577  -0.0844369   -0.103460    0.405670   -0.0844450
+50973.00  -0.103042   0.407182  -0.0852883   -0.102880    0.407220   -0.0852860
+50974.00  -0.102217   0.408801  -0.0860368   -0.102140    0.408820   -0.0860440
+50975.00  -0.101272   0.410408  -0.0867308   -0.101130    0.410530   -0.0867380
+50976.00  -0.100513   0.411926  -0.0874101   -0.100270    0.412130   -0.0873920
+50977.00  -0.100010   0.413302  -0.0881062   -0.099840    0.413470   -0.0880890
+50978.00  -0.099407   0.414567  -0.0888650   -0.099300    0.414620   -0.0888680
+50979.00  -0.098389   0.415830  -0.0897238   -0.098200    0.415820   -0.0897280
+50980.00  -0.097022   0.417175  -0.0906571   -0.096830    0.417220   -0.0906520
+50981.00  -0.095357   0.418640  -0.0916396   -0.095290    0.418670   -0.0916240
+50982.00  -0.093646   0.420329  -0.0926459   -0.093450    0.420380   -0.0926230
+50983.00  -0.091783   0.421990  -0.0936208   -0.091580    0.422120   -0.0936100
+50984.00  -0.089921   0.423490  -0.0945457   -0.089720    0.423670   -0.0945390
+50985.00  -0.088168   0.424852  -0.0953771   -0.087960    0.425010   -0.0953740
+50986.00  -0.086454   0.426143  -0.0960672   -0.086300    0.426230   -0.0960770
+50987.00  -0.084694   0.427473  -0.0966007   -0.084560    0.427490   -0.0966180
+50988.00  -0.082934   0.428940  -0.0970187   -0.082690    0.428930   -0.0970360
+50989.00  -0.081371   0.430507  -0.0974038   -0.081120    0.430630   -0.0974240
+50990.00  -0.079860   0.431951  -0.0977963   -0.079670    0.432110   -0.0978250
+50991.00  -0.078218   0.433227  -0.0982229   -0.078070    0.433380   -0.0982420
+50992.00  -0.076251   0.434408  -0.0986901   -0.076120    0.434520   -0.0986920
+50993.00  -0.073849   0.435647  -0.0992107   -0.073650    0.435640   -0.0992050
+50994.00  -0.071100   0.437082  -0.0997910   -0.070940    0.437030   -0.0997880
+50995.00  -0.068239   0.438694  -0.1004131   -0.068160    0.438840   -0.1004110
+50996.00  -0.065567   0.440347  -0.1010373   -0.065400    0.440690   -0.1010300
+50997.00  -0.063009   0.441996  -0.1016024   -0.062830    0.442190   -0.1015890
+50998.00  -0.060511   0.443674  -0.1020711   -0.060370    0.443770   -0.1020530
+50999.00  -0.057993   0.445381  -0.1024447   -0.057850    0.445490   -0.1024230
+51000.00  -0.055404   0.447048  -0.1027229   -0.055190    0.447270   -0.1027270
+51001.00  -0.052822   0.448568  -0.1029010   -0.052640    0.448880   -0.1029200
+51002.00  -0.050272   0.449909  -0.1029867   -0.050110    0.450080   -0.1030040
+51003.00  -0.047789   0.451171  -0.1030078   -0.047580    0.451160   -0.1030060
+51004.00  -0.045284   0.452559  -0.1030458   -0.045060    0.452530   -0.1030150
+51005.00  -0.042770   0.454154  -0.1031990   -0.042630    0.454360   -0.1031510
+51006.00  -0.040237   0.455835  -0.1035270   -0.040080    0.456150   -0.1034910
+51007.00  -0.037743   0.457466  -0.1040342   -0.037610    0.457660   -0.1040260
+51008.00  -0.035317   0.458998  -0.1046856   -0.035190    0.459100   -0.1046950
+51009.00  -0.032985   0.460388  -0.1054234   -0.032820    0.460470   -0.1054320
+51010.00  -0.030768   0.461506  -0.1061780   -0.030630    0.461620   -0.1061790
+51011.00  -0.028607   0.462383  -0.1068703   -0.028420    0.462510   -0.1068730
+51012.00  -0.026513   0.463176  -0.1074437   -0.026280    0.463320   -0.1074530
+51013.00  -0.024528   0.463998  -0.1078768   -0.024350    0.464190   -0.1078910
+51014.00  -0.022578   0.464858  -0.1081687   -0.022400    0.465070   -0.1081780
+51015.00  -0.020654   0.465732  -0.1083355   -0.020390    0.465930   -0.1083390
+51016.00  -0.018742   0.466609  -0.1084270   -0.018520    0.466820   -0.1084240
+51017.00  -0.016591   0.467461  -0.1085268   -0.016390    0.467730   -0.1085030
+51018.00  -0.014288   0.468234  -0.1086888   -0.014030    0.468560   -0.1086470
+51019.00  -0.011898   0.468963  -0.1089490   -0.011710    0.469190   -0.1089050
+51020.00  -0.009354   0.469790  -0.1093187   -0.009170    0.469900   -0.1092880
+51021.00  -0.006753   0.470803  -0.1097667   -0.006510    0.470970   -0.1097590
+51022.00  -0.004257   0.471952  -0.1102513   -0.004050    0.472140   -0.1102550
+51023.00  -0.001928   0.473168  -0.1107348   -0.001800    0.473270   -0.1107300
+51024.00   0.000141   0.474366  -0.1111979    0.000400    0.474440   -0.1111900
+51025.00   0.002045   0.475412  -0.1116748    0.002240    0.475590   -0.1116620
+51026.00   0.003902   0.476287  -0.1121413    0.004030    0.476470   -0.1121250
+51027.00   0.005810   0.476934  -0.1125566    0.006030    0.477150   -0.1125390
+51028.00   0.007707   0.477354  -0.1129220    0.007910    0.477580   -0.1129010
+51029.00   0.009695   0.477689  -0.1132513    0.009780    0.477780   -0.1132420
+51030.00   0.011888   0.478048  -0.1135649    0.011970    0.478280   -0.1135780
+51031.00   0.014036   0.478378  -0.1138882    0.014310    0.478670   -0.1138850
+51032.00   0.016013   0.478564  -0.1142787    0.016310    0.478810   -0.1142650
+51033.00   0.017857   0.478532  -0.1147998    0.018000    0.478750   -0.1147840
+51034.00   0.019846   0.478394  -0.1154884    0.020000    0.478530   -0.1154780
+51035.00   0.022136   0.478349  -0.1163435    0.022360    0.478550   -0.1163610
+51036.00   0.024683   0.478428  -0.1173135    0.024920    0.478620   -0.1172870
+51037.00   0.027507   0.478537  -0.1183214    0.027750    0.478650   -0.1183140
+51038.00   0.030469   0.478490  -0.1192916    0.030740    0.478710   -0.1193330
+51039.00   0.033161   0.478373  -0.1201373    0.033470    0.478530   -0.1201380
+51040.00   0.035385   0.478230  -0.1208043    0.035640    0.478380   -0.1208020
+51041.00   0.037338   0.477954  -0.1212799    0.037440    0.478200   -0.1212930
+51042.00   0.039383   0.477571  -0.1215970    0.039480    0.477780   -0.1215910
+51043.00   0.041616   0.477282  -0.1218310    0.041850    0.477460   -0.1217910
+51044.00   0.043877   0.477170  -0.1220399    0.044010    0.477310   -0.1220280
+51045.00   0.046118   0.477172  -0.1222411    0.046250    0.477350   -0.1222380
+51046.00   0.048308   0.477138  -0.1224999    0.048530    0.477440   -0.1224530
+51047.00   0.050364   0.476926  -0.1228631    0.050550    0.477220   -0.1228260
+51048.00   0.052280   0.476613  -0.1233193    0.052440    0.476810   -0.1233090
+51049.00   0.054145   0.476412  -0.1238454    0.054320    0.476560   -0.1238350
+51050.00   0.056077   0.476410  -0.1244283    0.056240    0.476540   -0.1244130
+51051.00   0.058154   0.476479  -0.1250667    0.058240    0.476620   -0.1250660
+51052.00   0.060476   0.476406  -0.1257468    0.060590    0.476610   -0.1257590
+51053.00   0.063022   0.476301  -0.1263679    0.063220    0.476500   -0.1263670
+51054.00   0.065457   0.476258  -0.1269255    0.065630    0.476440   -0.1268960
+51055.00   0.067554   0.476216  -0.1274719    0.067680    0.476380   -0.1274620
+51056.00   0.069401   0.476025  -0.1280318    0.069550    0.476230   -0.1280370
+51057.00   0.071120   0.475561  -0.1286135    0.071240    0.475620   -0.1285890
+51058.00   0.072844   0.474730  -0.1292386    0.073020    0.474780   -0.1292390
+51059.00   0.074764   0.473551  -0.1299286    0.074860    0.473590   -0.1299930
+51060.00   0.077100   0.472242  -0.1307263    0.077130    0.472220   -0.1307450
+51061.00   0.079771   0.471042  -0.1316873    0.079940    0.471050   -0.1316510
+51062.00   0.082436   0.470009  -0.1328413    0.082560    0.470090   -0.1328540
+51063.00   0.084904   0.469113  -0.1341544    0.084950    0.469130   -0.1341840
+51064.00   0.087182   0.468379  -0.1355772    0.087280    0.468310   -0.1355640
+51065.00   0.089300   0.467798  -0.1370359    0.089440    0.467860   -0.1370290
+51066.00   0.091338   0.467196  -0.1384475    0.091430    0.467320   -0.1384850
+51067.00   0.093191   0.466586  -0.1397068    0.093290    0.466610   -0.1397250
+51068.00   0.094945   0.466045  -0.1407607    0.095020    0.466090   -0.1407430
+51069.00   0.096838   0.465596  -0.1416295    0.096750    0.465690   -0.1416630
+51070.00   0.099104   0.465229  -0.1423579    0.099100    0.465260   -0.1423780
+51071.00   0.101649   0.464944  -0.1430406    0.101750    0.464930   -0.1430220
+51072.00   0.104134   0.464679  -0.1437528    0.104290    0.464720   -0.1437630
+51073.00   0.106262   0.464282  -0.1445295    0.106540    0.464300   -0.1445660
+51074.00   0.107886   0.463595  -0.1453877    0.108060    0.463730   -0.1453830
+51075.00   0.109157   0.462458  -0.1463485    0.109190    0.462570   -0.1463160
+51076.00   0.110451   0.461014  -0.1474139    0.110510    0.460960   -0.1474310
+51077.00   0.112012   0.459494  -0.1485386    0.112080    0.459540   -0.1485550
+51078.00   0.113860   0.457995  -0.1496770    0.113860    0.458050   -0.1496660
+51079.00   0.115813   0.456545  -0.1507847    0.115840    0.456520   -0.1507800
+51080.00   0.117554   0.455099  -0.1518337    0.117640    0.455060   -0.1518410
+51081.00   0.119055   0.453760  -0.1528303    0.119170    0.453760   -0.1528260
+51082.00   0.120278   0.452516  -0.1537788    0.120390    0.452570   -0.1537680
+51083.00   0.121282   0.451171  -0.1546743    0.121340    0.451320   -0.1546930
+51084.00   0.122230   0.449599  -0.1555100    0.122300    0.449720   -0.1555430
+51085.00   0.123196   0.447930  -0.1563226    0.123320    0.447910   -0.1563210
+51086.00   0.124155   0.446382  -0.1571765    0.124320    0.446400   -0.1571750
+51087.00   0.125228   0.445043  -0.1581667    0.125350    0.445040   -0.1581770
+51088.00   0.126461   0.443833  -0.1593503    0.126530    0.443810   -0.1593500
+51089.00   0.128001   0.442525  -0.1607548    0.128040    0.442560   -0.1607750
+51090.00   0.129722   0.441128  -0.1623864    0.129790    0.441260   -0.1623690
+51091.00   0.131406   0.439608  -0.1642040    0.131470    0.439610   -0.1641980
+51092.00   0.132907   0.437892  -0.1661050    0.132950    0.438040   -0.1661190
+51093.00   0.134223   0.435948  -0.1679813    0.134300    0.436030   -0.1679800
+51094.00   0.135605   0.433878  -0.1697762    0.135650    0.433830   -0.1697670
+51095.00   0.137157   0.431974  -0.1714343    0.137210    0.431860   -0.1714380
+51096.00   0.138748   0.430520  -0.1729566    0.138840    0.430600   -0.1729550
+51097.00   0.140117   0.429469  -0.1743488    0.140170    0.429510   -0.1743740
+51098.00   0.141200   0.428517  -0.1756317    0.141300    0.428710   -0.1756750
+51099.00   0.142006   0.427407  -0.1768635    0.142080    0.427600   -0.1768890
+51100.00   0.142798   0.426003  -0.1781129    0.142800    0.426040   -0.1781180
+51101.00   0.143900   0.424493  -0.1794441    0.144040    0.424490   -0.1794610
+51102.00   0.145221   0.423152  -0.1808316    0.145380    0.423230   -0.1808420
+51103.00   0.146618   0.422003  -0.1822482    0.146710    0.422100   -0.1822120
+51104.00   0.147994   0.420910  -0.1836933    0.148110    0.420990   -0.1836610
+51105.00   0.149208   0.419738  -0.1851581    0.149290    0.419730   -0.1851800
+51106.00   0.150207   0.418399  -0.1866206    0.150230    0.418400   -0.1866130
+51107.00   0.151112   0.416821  -0.1880692    0.151150    0.416880   -0.1880530
+51108.00   0.151751   0.414917  -0.1894838    0.151950    0.414940   -0.1895090
+51109.00   0.152151   0.412904  -0.1908182    0.152320    0.412880   -0.1908230
+51110.00   0.152450   0.411039  -0.1920780    0.152530    0.411040   -0.1920590
+51111.00   0.152867   0.409395  -0.1933079    0.152960    0.409450   -0.1933040
+51112.00   0.153419   0.407837  -0.1945276    0.153510    0.407950   -0.1945460
+51113.00   0.154100   0.406206  -0.1957206    0.154190    0.406270   -0.1957380
+51114.00   0.154951   0.404482  -0.1969058    0.155000    0.404560   -0.1969190
+51115.00   0.155988   0.402752  -0.1981645    0.156040    0.402790   -0.1981300
+51116.00   0.157099   0.401147  -0.1995944    0.157170    0.401180   -0.1995050
+51117.00   0.158205   0.399656  -0.2012498    0.158280    0.399690   -0.2011920
+51118.00   0.159372   0.398227  -0.2031347    0.159470    0.398270   -0.2031340
+51119.00   0.160608   0.396796  -0.2051970    0.160720    0.396800   -0.2052100
+51120.00   0.161800   0.395350  -0.2073295    0.161840    0.395320   -0.2073330
+51121.00   0.162759   0.393866  -0.2094137    0.162790    0.393910   -0.2094130
+51122.00   0.163186   0.392206  -0.2113694    0.163190    0.392310   -0.2113550
+51123.00   0.163127   0.390338  -0.2131451    0.163130    0.390500   -0.2131330
+51124.00   0.163177   0.388193  -0.2147595    0.163230    0.388320   -0.2147600
+51125.00   0.163540   0.385840  -0.2162531    0.163570    0.385860   -0.2162550
+51126.00   0.164135   0.383444  -0.2176863    0.164150    0.383480   -0.2176810
+51127.00   0.164793   0.381095  -0.2191246    0.164860    0.381130   -0.2191100
+51128.00   0.165431   0.378844  -0.2205953    0.165440    0.378810   -0.2205850
+51129.00   0.166094   0.376752  -0.2220940    0.166110    0.376800   -0.2220960
+51130.00   0.166560   0.374724  -0.2236125    0.166620    0.374820   -0.2236190
+51131.00   0.166577   0.372674  -0.2251363    0.166590    0.372680   -0.2251430
+51132.00   0.166129   0.370621  -0.2266458    0.166180    0.370690   -0.2266690
+51133.00   0.165389   0.368567  -0.2281187    0.165440    0.368620   -0.2281310
+51134.00   0.164616   0.366565  -0.2295496    0.164590    0.366530   -0.2295470
+51135.00   0.164092   0.364644  -0.2309382    0.164060    0.364670   -0.2309380
+51136.00   0.163768   0.362711  -0.2322849    0.163740    0.362710   -0.2322770
+51137.00   0.163194   0.360797  -0.2335826    0.163200    0.360760   -0.2335820
+51138.00   0.161963   0.358907  -0.2348381    0.162040    0.359040   -0.2348520
+51139.00   0.160085   0.356946  -0.2360666    0.160030    0.357130   -0.2360610
+51140.00   0.158115   0.354896  -0.2372925    0.158090    0.354910   -0.2372750
+51141.00   0.156354   0.352913  -0.2385373    0.156480    0.352940   -0.2385630
+51142.00   0.154814   0.351026  -0.2398232    0.154930    0.351080   -0.2398440
+51143.00   0.153691   0.349091  -0.2412084    0.153770    0.349160   -0.2411550
+51144.00   0.152791   0.347042  -0.2427449    0.152870    0.347140   -0.2427040
+51145.00   0.151834   0.344872  -0.2444448    0.151860    0.344890   -0.2444480
+51146.00   0.150915   0.342720  -0.2462737    0.150870    0.342630   -0.2462790
+51147.00   0.150141   0.340779  -0.2481367    0.150250    0.340730   -0.2481490
+51148.00   0.149184   0.339098  -0.2499346    0.149440    0.339290   -0.2499460
+51149.00   0.147951   0.337562  -0.2515983    0.148060    0.337590   -0.2516030
+51150.00   0.147004   0.336146  -0.2531202    0.146980    0.336120   -0.2531290
+51151.00   0.146455   0.335017  -0.2544842    0.146520    0.335080   -0.2544910
+51152.00   0.145863   0.334151  -0.2557114    0.145960    0.334300   -0.2557150
+51153.00   0.144933   0.333320  -0.2568539    0.144940    0.333360   -0.2568680
+51154.00   0.143695   0.332385  -0.2579548    0.143730    0.332270   -0.2579490
+51155.00   0.142269   0.331265  -0.2590365    0.142260    0.331140   -0.2590450
+51156.00   0.140845   0.329776  -0.2601098    0.140850    0.329720   -0.2601250
+51157.00   0.139654   0.327889  -0.2612229    0.139700    0.327880   -0.2611980
+51158.00   0.138670   0.325829  -0.2623954    0.138680    0.325810   -0.2623830
+51159.00   0.137880   0.323810  -0.2635872    0.137890    0.323810   -0.2636020
+51160.00   0.137344   0.321899  -0.2647402    0.137390    0.321940   -0.2647510
+51161.00   0.137118   0.320090  -0.2658320    0.137150    0.320130   -0.2658350
+51162.00   0.137191   0.318439  -0.2668510    0.137240    0.318410   -0.2668620
+51163.00   0.137482   0.317021  -0.2677836    0.137450    0.316970   -0.2677810
+51164.00   0.137993   0.315738  -0.2686203    0.137950    0.315730   -0.2686130
+51165.00   0.138867   0.314494  -0.2693765    0.138870    0.314470   -0.2693900
+51166.00   0.140070   0.313420  -0.2700640    0.140080    0.313340   -0.2700750
+51167.00   0.141362   0.312536  -0.2707054    0.141430    0.312550   -0.2706980
+51168.00   0.142330   0.311541  -0.2713404    0.142400    0.311680   -0.2713370
+51169.00   0.142795   0.310097  -0.2720051    0.142860    0.310170   -0.2720570
+51170.00   0.142988   0.308356  -0.2727487    0.143050    0.308250   -0.2727810
+51171.00   0.143090   0.306710  -0.2736544    0.143130    0.306690   -0.2735780
+51172.00   0.143080   0.305222  -0.2747547    0.143110    0.305330   -0.2746410
+51173.00   0.142815   0.303796  -0.2760051    0.142820    0.303820   -0.2759310
+51174.00   0.142282   0.302444  -0.2773357    0.142260    0.302430   -0.2773300
+51175.00   0.141721   0.301186  -0.2786798    0.141690    0.301160   -0.2787160
+51176.00   0.141207   0.299985  -0.2799819    0.141210    0.299910   -0.2800170
+51177.00   0.140598   0.298726  -0.2812143    0.140690    0.298710   -0.2812110
+51178.00   0.139675   0.297292  -0.2823385    0.139760    0.297390   -0.2823330
+51179.00   0.138577   0.295556   0.7166587    0.138510    0.295650    0.7166370
+51180.00   0.137785   0.293577   0.7157494    0.137710    0.293550    0.7157410
+51181.00   0.137421   0.291696   0.7148885    0.137480    0.291660    0.7148720
+51182.00   0.137132   0.290124   0.7140379    0.137190    0.290230    0.7139820
+51183.00   0.136733   0.288814   0.7131775    0.136690    0.288940    0.7131390
+51184.00   0.136397   0.287754   0.7122751    0.136360    0.287820    0.7122810
+51185.00   0.136247   0.287027   0.7112608    0.136280    0.287070    0.7112410
+51186.00   0.136118   0.286554   0.7101793    0.136140    0.286610    0.7101380
+51187.00   0.135752   0.286182   0.7091003    0.135710    0.286270    0.7091040
+51188.00   0.134909   0.285701   0.7080310    0.134860    0.285720    0.7080490
+51189.00   0.133471   0.284873   0.7069893    0.133490    0.284910    0.7069560
+51190.00   0.131464   0.283567   0.7060440    0.131450    0.283640    0.7060060
+51191.00   0.129180   0.281889   0.7052302    0.129100    0.281870    0.7052330
+51192.00   0.126962   0.279990   0.7044958    0.126900    0.280070    0.7044610
+51193.00   0.124851   0.277989   0.7038139    0.124920    0.278020    0.7037620
+51194.00   0.122714   0.276071   0.7032033    0.122820    0.276030    0.7031910
+51195.00   0.120630   0.274356   0.7026480    0.120620    0.274400    0.7026250
+51196.00   0.118887   0.272823   0.7021026    0.118870    0.272900    0.7020740
+51197.00   0.117525   0.271405   0.7014865    0.117530    0.271450    0.7014750
+51198.00   0.116539   0.270022   0.7007330    0.116510    0.270050    0.7007330
+51199.00   0.116083   0.268687   0.6997928    0.116100    0.268630    0.6997900
+51200.00   0.116118   0.267493   0.6986675    0.116140    0.267460    0.6986490
+51201.00   0.116223   0.266420   0.6973983    0.116330    0.266480    0.6973720
+51202.00   0.115937   0.265363   0.6960300    0.116040    0.265470    0.6960030
+51203.00   0.115117   0.264256   0.6946208    0.115100    0.264350    0.6945500
+51204.00   0.113991   0.263174   0.6932696    0.113920    0.263120    0.6931850
+51205.00   0.112826   0.262237   0.6920205    0.112830    0.262250    0.6919960
+51206.00   0.111620   0.261398   0.6908379    0.111640    0.261450    0.6908520
+51207.00   0.110525   0.260526   0.6896941    0.110480    0.260550    0.6896900
+51208.00   0.109379   0.259573   0.6885405    0.109400    0.259590    0.6885240
+51209.00   0.108080   0.258531   0.6873571    0.108160    0.258590    0.6873410
+51210.00   0.106598   0.257341   0.6861313    0.106640    0.257490    0.6861150
+51211.00   0.105004   0.256005   0.6848593    0.105030    0.256080    0.6848460
+51212.00   0.103396   0.254659   0.6835503    0.103380    0.254690    0.6835470
+51213.00   0.101922   0.253439   0.6822214    0.101750    0.253390    0.6822120
+51214.00   0.100916   0.252566   0.6808880    0.100770    0.252400    0.6808730
+51215.00   0.100335   0.252224   0.6795667    0.100380    0.252260    0.6795660
+51216.00   0.099624   0.252238   0.6782837    0.099720    0.252380    0.6782890
+51217.00   0.098384   0.252265   0.6770716    0.098340    0.252260    0.6770550
+51218.00   0.096675   0.252190   0.6759507    0.096530    0.252090    0.6759100
+51219.00   0.094706   0.251925   0.6749074    0.094590    0.252050    0.6748970
+51220.00   0.092622   0.251225   0.6739383    0.092500    0.251370    0.6739270
+51221.00   0.090736   0.250235   0.6730319    0.090610    0.250190    0.6730310
+51222.00   0.089163   0.249217   0.6721348    0.089120    0.249330    0.6721840
+51223.00   0.087881   0.248238   0.6711759    0.087860    0.248370    0.6711830
+51224.00   0.086783   0.247431   0.6701095    0.086770    0.247460    0.6701030
+51225.00   0.085708   0.246965   0.6689138    0.085630    0.246990    0.6689060
+51226.00   0.084445   0.246805   0.6675690    0.084480    0.246820    0.6675580
+51227.00   0.082689   0.246707   0.6660476    0.082810    0.246830    0.6660510
+51228.00   0.080806   0.246425   0.6643896    0.080790    0.246630    0.6643680
+51229.00   0.079313   0.245935   0.6626922    0.079250    0.246020    0.6626600
+51230.00   0.078445   0.245457   0.6610367    0.078400    0.245460    0.6610490
+51231.00   0.078153   0.245134   0.6594679    0.078140    0.245200    0.6594700
+51232.00   0.078078   0.244906   0.6580462    0.078080    0.244950    0.6580360
+51233.00   0.077632   0.244669   0.6568065    0.077660    0.244710    0.6568110
+51234.00   0.076472   0.244314   0.6557266    0.076510    0.244390    0.6557030
+51235.00   0.074875   0.243781   0.6547633    0.074890    0.243870    0.6547300
+51236.00   0.073082   0.243098   0.6538706    0.073090    0.243170    0.6538810
+51237.00   0.071378   0.242384   0.6529831    0.071330    0.242420    0.6529950
+51238.00   0.069983   0.241806   0.6520627    0.069960    0.241870    0.6520380
+51239.00   0.068909   0.241487   0.6511207    0.068880    0.241600    0.6510780
+51240.00   0.068114   0.241469   0.6501709    0.068060    0.241560    0.6501610
+51241.00   0.067407   0.241688   0.6491932    0.067400    0.241730    0.6492320
+51242.00   0.066561   0.242023   0.6481793    0.066570    0.242140    0.6481930
+51243.00   0.065483   0.242354   0.6471690    0.065460    0.242450    0.6471360
+51244.00   0.064348   0.242547   0.6462538    0.064360    0.242600    0.6462500
+51245.00   0.063278   0.242556   0.6454247    0.063280    0.242620    0.6454270
+51246.00   0.062192   0.242377   0.6446631    0.062040    0.242430    0.6446490
+51247.00   0.061032   0.242009   0.6439529    0.060890    0.242050    0.6439460
+51248.00   0.059969   0.241610   0.6432600    0.059840    0.241620    0.6432690
+51249.00   0.058807   0.241239   0.6425445    0.058710    0.241350    0.6425460
+51250.00   0.057514   0.240861   0.6417607    0.057520    0.241090    0.6417470
+51251.00   0.056092   0.240433   0.6408596    0.056150    0.240550    0.6408520
+51252.00   0.054562   0.239984   0.6397960    0.054620    0.239970    0.6397940
+51253.00   0.052907   0.239553   0.6385563    0.052900    0.239580    0.6385570
+51254.00   0.051136   0.239142   0.6371559    0.051100    0.239140    0.6371530
+51255.00   0.049793   0.238932   0.6356238    0.049790    0.238830    0.6356030
+51256.00   0.048941   0.239050   0.6340022    0.049020    0.238990    0.6339940
+51257.00   0.048186   0.239430   0.6323403    0.048260    0.239470    0.6323600
+51258.00   0.047327   0.239931   0.6306782    0.047260    0.239980    0.6306790
+51259.00   0.046514   0.240468   0.6290778    0.046430    0.240490    0.6290540
+51260.00   0.045565   0.240966   0.6276165    0.045540    0.241010    0.6275870
+51261.00   0.044085   0.241305   0.6263131    0.044080    0.241400    0.6263030
+51262.00   0.042017   0.241415   0.6251109    0.041950    0.241450    0.6251350
+51263.00   0.039295   0.241416   0.6239616    0.039180    0.241430    0.6239720
+51264.00   0.036347   0.241357   0.6227854    0.036230    0.241480    0.6227770
+51265.00   0.033747   0.241145   0.6215430    0.033680    0.241250    0.6215430
+51266.00   0.031676   0.240915   0.6202226    0.031690    0.240850    0.6202090
+51267.00   0.029843   0.240902   0.6188504    0.029860    0.240820    0.6188340
+51268.00   0.027952   0.241025   0.6174612    0.028000    0.241080    0.6174570
+51269.00   0.025972   0.240966   0.6160514    0.026030    0.241020    0.6160780
+51270.00   0.023889   0.240663   0.6146313    0.023870    0.240740    0.6146500
+51271.00   0.021820   0.240215   0.6132443    0.021760    0.240220    0.6132240
+51272.00   0.020052   0.239794   0.6119391    0.019960    0.239760    0.6119380
+51273.00   0.018652   0.239541   0.6107150    0.018570    0.239620    0.6107220
+51274.00   0.017384   0.239548   0.6095457    0.017320    0.239570    0.6095590
+51275.00   0.015829   0.239833   0.6084018    0.015740    0.239860    0.6084080
+51276.00   0.013791   0.240165   0.6072974    0.013730    0.240310    0.6072760
+51277.00   0.012055   0.240386   0.6062115    0.011990    0.240520    0.6061980
+51278.00   0.010998   0.240635   0.6050749    0.010940    0.240690    0.6050670
+51279.00   0.010475   0.241143   0.6038335    0.010500    0.241200    0.6038210
+51280.00   0.010119   0.241969   0.6024322    0.010210    0.242090    0.6024510
+51281.00   0.009565   0.242944   0.6008268    0.009610    0.243030    0.6008480
+51282.00   0.008800   0.243956   0.5990280    0.008830    0.243840    0.5990220
+51283.00   0.008074   0.245070   0.5971222    0.008020    0.244910    0.5971310
+51284.00   0.007323   0.246324   0.5951849    0.007300    0.246280    0.5951890
+51285.00   0.006257   0.247512   0.5932963    0.006360    0.247560    0.5932790
+51286.00   0.004782   0.248353   0.5915380    0.004820    0.248450    0.5915350
+51287.00   0.003071   0.248755   0.5899323    0.002980    0.248890    0.5899240
+51288.00   0.001508   0.248848   0.5884751    0.001420    0.248930    0.5884800
+51289.00   0.000190   0.248839   0.5871312    0.000130    0.248850    0.5871390
+51290.00  -0.001057   0.248911   0.5858655   -0.001090    0.248950    0.5858710
+51291.00  -0.002271   0.249270   0.5846479   -0.002300    0.249360    0.5846520
+51292.00  -0.003651   0.249966   0.5834051   -0.003630    0.250120    0.5833930
+51293.00  -0.005339   0.250849   0.5820993   -0.005340    0.251010    0.5820920
+51294.00  -0.006985   0.251766   0.5807227   -0.007100    0.251870    0.5807220
+51295.00  -0.008027   0.252694   0.5792838   -0.008140    0.252780    0.5792780
+51296.00  -0.008362   0.253742   0.5778108   -0.008440    0.253770    0.5777930
+51297.00  -0.008472   0.255001   0.5763380   -0.008530    0.255000    0.5763270
+51298.00  -0.008673   0.256408   0.5749065   -0.008740    0.256480    0.5749090
+51299.00  -0.009270   0.257734   0.5735522   -0.009340    0.257860    0.5735560
+51300.00  -0.010432   0.258759   0.5722963   -0.010510    0.258900    0.5723070
+51301.00  -0.011958   0.259424   0.5711562   -0.011990    0.259570    0.5711640
+51302.00  -0.013543   0.259790   0.5701485   -0.013550    0.260020    0.5701520
+51303.00  -0.014882   0.260006   0.5692803   -0.014970    0.260010    0.5692870
+51304.00  -0.015809   0.260357   0.5685207   -0.015880    0.260350    0.5685460
+51305.00  -0.016511   0.260980   0.5677978   -0.016510    0.261130    0.5678080
+51306.00  -0.017204   0.261793   0.5670197   -0.017230    0.261940    0.5670120
+51307.00  -0.017955   0.262620   0.5661215   -0.018020    0.262790    0.5661330
+51308.00  -0.018562   0.263437   0.5650617   -0.018650    0.263510    0.5650480
+51309.00  -0.018908   0.264417   0.5638338   -0.019000    0.264410    0.5638010
+51310.00  -0.019144   0.265626   0.5624372   -0.019220    0.265740    0.5624390
+51311.00  -0.019272   0.267017   0.5608976   -0.019370    0.267170    0.5609190
+51312.00  -0.019234   0.268489   0.5593032   -0.019350    0.268670    0.5593160
+51313.00  -0.019058   0.270015   0.5577666   -0.019090    0.270160    0.5577750
+51314.00  -0.019061   0.271612   0.5563793   -0.019060    0.271710    0.5563890
+51315.00  -0.019409   0.273248   0.5551731   -0.019510    0.273340    0.5551900
+51316.00  -0.019872   0.274767   0.5541002   -0.019990    0.274890    0.5541190
+51317.00  -0.020213   0.275981   0.5530726   -0.020290    0.276130    0.5530890
+51318.00  -0.020417   0.276839   0.5520267   -0.020500    0.276930    0.5520360
+51319.00  -0.020523   0.277505   0.5509281   -0.020570    0.277570    0.5509490
+51320.00  -0.020535   0.278185   0.5497378   -0.020560    0.278270    0.5497680
+51321.00  -0.020552   0.278928   0.5484707   -0.020600    0.279020    0.5484720
+51322.00  -0.020768   0.279657   0.5471797   -0.020760    0.279750    0.5471860
+51323.00  -0.021347   0.280333   0.5458784   -0.021300    0.280390    0.5459010
+51324.00  -0.022250   0.280942   0.5446124   -0.022280    0.280980    0.5446230
+51325.00  -0.023138   0.281436   0.5434745   -0.023170    0.281490    0.5434710
+51326.00  -0.023752   0.281994   0.5424832   -0.023750    0.282100    0.5424970
+51327.00  -0.024118   0.282646   0.5416162   -0.024110    0.282830    0.5416450
+51328.00  -0.024418   0.283263   0.5408527   -0.024450    0.283410    0.5408500
+51329.00  -0.024737   0.283829   0.5401746   -0.024820    0.283930    0.5401390
+51330.00  -0.025164   0.284461   0.5395663   -0.025220    0.284540    0.5395750
+51331.00  -0.025839   0.285250   0.5389945   -0.025920    0.285380    0.5390250
+51332.00  -0.026663   0.286131   0.5384164   -0.026790    0.286290    0.5383850
+51333.00  -0.027370   0.287157   0.5377925   -0.027450    0.287220    0.5377750
+51334.00  -0.027956   0.288463   0.5370730   -0.027980    0.288510    0.5371050
+51335.00  -0.028608   0.290007   0.5362194   -0.028550    0.290050    0.5362130
+51336.00  -0.029271   0.291489   0.5352299   -0.029220    0.291540    0.5352240
+51337.00  -0.029839   0.292673   0.5340830   -0.029720    0.292750    0.5341110
+51338.00  -0.030385   0.293489   0.5327898   -0.030240    0.293620    0.5327920
+51339.00  -0.030823   0.293963   0.5314166   -0.030730    0.294060    0.5314210
+51340.00  -0.031123   0.294357   0.5300536   -0.031020    0.294390    0.5300850
+51341.00  -0.031394   0.294908   0.5287990   -0.031350    0.295020    0.5287960
+51342.00  -0.031599   0.295656   0.5277405   -0.031630    0.295780    0.5277610
+51343.00  -0.031741   0.296616   0.5268796   -0.031650    0.296690    0.5269420
+51344.00  -0.032060   0.297675   0.5261601   -0.031880    0.297780    0.5261980
+51345.00  -0.032633   0.298575   0.5255218   -0.032610    0.298690    0.5255170
+51346.00  -0.033005   0.299226   0.5249077   -0.033010    0.299280    0.5249170
+51347.00  -0.033064   0.299759   0.5242518   -0.032930    0.299810    0.5242620
+51348.00  -0.032912   0.300307   0.5235385   -0.032790    0.300340    0.5235260
+51349.00  -0.032633   0.301003   0.5227939   -0.032530    0.301030    0.5228120
+51350.00  -0.032416   0.301872   0.5220497   -0.032260    0.301940    0.5220930
+51351.00  -0.032382   0.302784   0.5213298   -0.032230    0.302870    0.5213500
+51352.00  -0.032414   0.303630   0.5206856   -0.032430    0.303730    0.5206850
+51353.00  -0.032237   0.304449   0.5201823   -0.032270    0.304480    0.5202060
+51354.00  -0.032009   0.305351   0.5198199   -0.031920    0.305360    0.5198390
+51355.00  -0.032072   0.306343   0.5195874   -0.031990    0.306370    0.5195890
+51356.00  -0.032424   0.307330   0.5194846   -0.032390    0.307400    0.5195020
+51357.00  -0.032681   0.308172   0.5194888   -0.032680    0.308260    0.5194870
+51358.00  -0.032643   0.308831   0.5195759   -0.032600    0.308870    0.5196000
+51359.00  -0.032439   0.309415   0.5196994   -0.032410    0.309380    0.5197040
+51360.00  -0.032311   0.310020   0.5198139   -0.032200    0.309950    0.5198250
+51361.00  -0.032153   0.310745   0.5198820   -0.032030    0.310750    0.5199040
+51362.00  -0.031784   0.311739   0.5198545   -0.031690    0.311740    0.5198140
+51363.00  -0.031170   0.313045   0.5196951   -0.031120    0.313080    0.5197340
+51364.00  -0.030442   0.314529   0.5193487   -0.030430    0.314630    0.5194090
+51365.00  -0.029704   0.315956   0.5188292   -0.029680    0.316030    0.5188420
+51366.00  -0.028910   0.317201   0.5181918   -0.028900    0.317270    0.5181920
+51367.00  -0.027983   0.318324   0.5175273   -0.028030    0.318330    0.5175160
+51368.00  -0.027037   0.319481   0.5169244   -0.027030    0.319480    0.5169230
+51369.00  -0.026224   0.320703   0.5164345   -0.026250    0.320820    0.5164500
+51370.00  -0.025557   0.321908   0.5160590   -0.025590    0.321960    0.5160600
+51371.00  -0.025019   0.323101   0.5157613   -0.024980    0.323000    0.5157550
+51372.00  -0.024667   0.324344   0.5154946   -0.024670    0.324210    0.5154940
+51373.00  -0.024535   0.325578   0.5152068   -0.024560    0.325580    0.5152140
+51374.00  -0.024744   0.326635   0.5148456   -0.024670    0.326630    0.5148690
+51375.00  -0.025238   0.327339   0.5144052   -0.025120    0.327330    0.5144310
+51376.00  -0.025708   0.327855   0.5138917   -0.025670    0.327860    0.5138980
+51377.00  -0.025892   0.328401   0.5133447   -0.025820    0.328410    0.5133180
+51378.00  -0.025770   0.329054   0.5128171   -0.025650    0.329040    0.5127800
+51379.00  -0.025384   0.329837   0.5123367   -0.025280    0.329830    0.5123250
+51380.00  -0.024803   0.330652   0.5119213   -0.024770    0.330670    0.5119280
+51381.00  -0.024166   0.331389   0.5115879   -0.024170    0.331470    0.5115740
+51382.00  -0.023612   0.332029   0.5113555   -0.023650    0.332070    0.5113690
+51383.00  -0.023436   0.332554   0.5112222   -0.023290    0.332570    0.5112600
+51384.00  -0.023690   0.332988   0.5111749   -0.023610    0.333050    0.5111350
+51385.00  -0.023985   0.333417   0.5111988   -0.023970    0.333480    0.5111610
+51386.00  -0.024026   0.333921   0.5112401   -0.023980    0.333980    0.5112580
+51387.00  -0.023857   0.334593   0.5112419   -0.023810    0.334630    0.5112540
+51388.00  -0.023510   0.335462   0.5111595   -0.023400    0.335520    0.5111360
+51389.00  -0.023000   0.336427   0.5109628   -0.022860    0.336460    0.5109910
+51390.00  -0.022362   0.337453   0.5105973   -0.022280    0.337490    0.5106410
+51391.00  -0.021640   0.338517   0.5100551   -0.021570    0.338540    0.5100190
+51392.00  -0.020859   0.339539   0.5093789   -0.020830    0.339690    0.5093670
+51393.00  -0.019878   0.340497   0.5085788   -0.019910    0.340720    0.5086130
+51394.00  -0.018583   0.341387   0.5077202   -0.018720    0.341550    0.5077120
+51395.00  -0.017112   0.342266   0.5069471   -0.017190    0.342340    0.5069180
+51396.00  -0.015757   0.343305   0.5063317   -0.015620    0.343440    0.5063360
+51397.00  -0.014781   0.344488   0.5058809   -0.014670    0.344680    0.5058930
+51398.00  -0.014169   0.345595   0.5055680   -0.014300    0.345840    0.5055380
+51399.00  -0.013827   0.346439   0.5053520   -0.013890    0.346680    0.5053180
+51400.00  -0.013570   0.347008   0.5051508   -0.013640    0.347170    0.5051770
+51401.00  -0.013229   0.347413   0.5048772   -0.013310    0.347500    0.5048890
+51402.00  -0.012743   0.347767   0.5044897   -0.012860    0.347800    0.5044840
+51403.00  -0.012239   0.348141   0.5040260   -0.012470    0.348220    0.5040580
+51404.00  -0.011835   0.348680   0.5034709   -0.011940    0.348780    0.5034900
+51405.00  -0.011719   0.349523   0.5028289   -0.011760    0.349630    0.5028440
+51406.00  -0.011590   0.350631   0.5021460   -0.011790    0.350780    0.5021740
+51407.00  -0.011034   0.351884   0.5014710   -0.011220    0.352100    0.5014320
+51408.00  -0.010319   0.353153   0.5008619   -0.010320    0.353250    0.5008390
+51409.00  -0.009797   0.354359   0.5003492   -0.009880    0.354600    0.5003400
+51410.00  -0.009297   0.355503   0.4999451   -0.009530    0.355730    0.4999570
+51411.00  -0.008671   0.356678   0.4996400   -0.008740    0.356860    0.4997250
+51412.00  -0.008248   0.357883   0.4993711   -0.008330    0.358130    0.4993600
+51413.00  -0.008243   0.358996   0.4991033   -0.008270    0.359220    0.4990810
+51414.00  -0.008483   0.359983   0.4988082   -0.008450    0.360160    0.4988010
+51415.00  -0.008694   0.360823   0.4984339   -0.008880    0.360930    0.4984360
+51416.00  -0.008598   0.361514   0.4978839   -0.008690    0.361790    0.4979120
+51417.00  -0.008393   0.362115   0.4971095   -0.008440    0.362310    0.4971170
+51418.00  -0.008182   0.362641   0.4961321   -0.008280    0.362810    0.4961240
+51419.00  -0.007823   0.363098   0.4950086   -0.007930    0.363190    0.4950170
+51420.00  -0.007289   0.363548   0.4937904   -0.007340    0.363690    0.4937990
+51421.00  -0.006771   0.364020   0.4925551   -0.006770    0.364210    0.4925550
+51422.00  -0.006488   0.364447   0.4913924   -0.006490    0.364650    0.4913850
+51423.00  -0.006386   0.364778   0.4903690   -0.006430    0.364930    0.4903750
+51424.00  -0.006220   0.365077   0.4894913   -0.006220    0.365200    0.4895020
+51425.00  -0.005751   0.365411   0.4887284   -0.005850    0.365580    0.4887250
+51426.00  -0.004880   0.365869   0.4880370   -0.004960    0.366010    0.4880420
+51427.00  -0.003703   0.366428   0.4873721   -0.003810    0.366600    0.4873840
+51428.00  -0.002464   0.367003   0.4866972   -0.002570    0.367190    0.4867060
+51429.00  -0.001309   0.367620   0.4859923   -0.001440    0.367610    0.4860000
+51430.00  -0.000411   0.368267   0.4852548   -0.000550    0.368300    0.4852780
+51431.00   0.000061   0.368863   0.4844846    0.000030    0.369070    0.4845120
+51432.00   0.000383   0.369397   0.4836996    0.000460    0.369580    0.4837120
+51433.00   0.000863   0.369937   0.4829502    0.000800    0.370170    0.4829480
+51434.00   0.001600   0.370608   0.4822679    0.001620    0.370730    0.4822670
+51435.00   0.002414   0.371490   0.4816712    0.002450    0.371490    0.4816770
+51436.00   0.003040   0.372432   0.4811759    0.003040    0.372620    0.4811780
+51437.00   0.003503   0.373142   0.4807967    0.003510    0.373430    0.4807760
+51438.00   0.003889   0.373599   0.4805028    0.003850    0.373750    0.4804930
+51439.00   0.004184   0.373979   0.4802355    0.004070    0.374060    0.4802480
+51440.00   0.004345   0.374430   0.4799329    0.004280    0.374520    0.4799360
+51441.00   0.004513   0.374913   0.4795506    0.004470    0.375080    0.4795610
+51442.00   0.004887   0.375305   0.4790321    0.004820    0.375420    0.4790480
+51443.00   0.005344   0.375576   0.4783296    0.005330    0.375590    0.4783330
+51444.00   0.005458   0.375778   0.4774428    0.005560    0.375850    0.4774500
+51445.00   0.005210   0.375829   0.4763994    0.005150    0.376030    0.4764010
+51446.00   0.004983   0.375759   0.4752638    0.004960    0.375910    0.4752540
+51447.00   0.005018   0.375787   0.4740970    0.005000    0.375900    0.4741130
+51448.00   0.005262   0.376086   0.4729339    0.005160    0.376130    0.4729480
+51449.00   0.005564   0.376625   0.4718474    0.005430    0.376760    0.4718160
+51450.00   0.005826   0.377307   0.4708876    0.005810    0.377530    0.4708750
+51451.00   0.006099   0.378097   0.4700343    0.006070    0.378340    0.4700530
+51452.00   0.006366   0.378984   0.4692888    0.006260    0.379200    0.4692770
+51453.00   0.006616   0.379890   0.4686406    0.006580    0.380060    0.4686480
+51454.00   0.007091   0.380748   0.4679841    0.007070    0.380920    0.4680100
+51455.00   0.007760   0.381484   0.4671962    0.007850    0.381800    0.4672270
+51456.00   0.008441   0.382034   0.4662445    0.008400    0.382310    0.4662570
+51457.00   0.009156   0.382437   0.4651338    0.009120    0.382600    0.4651320
+51458.00   0.009792   0.382579   0.4638922    0.010140    0.382930    0.4639000
+51459.00   0.010453   0.382483   0.4625759    0.010710    0.382670    0.4625900
+51460.00   0.011302   0.382442   0.4612270    0.011250    0.382540    0.4612430
+51461.00   0.012327   0.382576   0.4598931    0.012270    0.382700    0.4599020
+51462.00   0.013291   0.382712   0.4586308    0.013270    0.382940    0.4586320
+51463.00   0.013933   0.382739   0.4574905    0.013950    0.382940    0.4574970
+51464.00   0.014160   0.382696   0.4564699    0.014140    0.382830    0.4564730
+51465.00   0.014011   0.382620   0.4555245    0.013960    0.382790    0.4555120
+51466.00   0.013764   0.382574   0.4546679    0.013670    0.382780    0.4546620
+51467.00   0.013723   0.382518   0.4539027    0.013670    0.382760    0.4539230
+51468.00   0.013998   0.382379   0.4531777    0.014010    0.382650    0.4531920
+51469.00   0.014481   0.382265   0.4524251    0.014510    0.382440    0.4524180
+51470.00   0.015066   0.382334   0.4515871    0.015050    0.382360    0.4515800
+51471.00   0.015704   0.382570   0.4505951    0.015740    0.382680    0.4505970
+51472.00   0.016335   0.382806   0.4493644    0.016400    0.382990    0.4493660
+51473.00   0.016759   0.382957   0.4478747    0.016850    0.383150    0.4478740
+51474.00   0.017150   0.383056   0.4461607    0.017130    0.383230    0.4461670
+51475.00   0.017702   0.383229   0.4442931    0.017730    0.383390    0.4442970
+51476.00   0.018291   0.383481   0.4423756    0.018330    0.383650    0.4423640
+51477.00   0.018863   0.383621   0.4405168    0.018810    0.383830    0.4405100
+51478.00   0.019452   0.383532   0.4388010    0.019430    0.383710    0.4387960
+51479.00   0.019978   0.383305   0.4372960    0.019970    0.383500    0.4372900
+51480.00   0.020327   0.383128   0.4359633    0.020230    0.383360    0.4359710
+51481.00   0.020502   0.383004   0.4347173    0.020480    0.383150    0.4347180
+51482.00   0.020765   0.382805   0.4334775    0.020760    0.382990    0.4334870
+51483.00   0.021271   0.382449   0.4321898    0.021280    0.382720    0.4321920
+51484.00   0.021918   0.381946   0.4308357    0.021890    0.382230    0.4308260
+51485.00   0.022609   0.381443   0.4294020    0.022700    0.381380    0.4293980
+51486.00   0.023219   0.380905   0.4278975    0.023300    0.380950    0.4279030
+51487.00   0.023757   0.380406   0.4263817    0.023730    0.380400    0.4263920
+51488.00   0.024151   0.380035   0.4248891    0.024130    0.380020    0.4249070
+51489.00   0.024358   0.379606   0.4234446    0.024420    0.379640    0.4234540
+51490.00   0.024501   0.378912   0.4220772    0.024490    0.378880    0.4220890
+51491.00   0.024892   0.378025   0.4207713    0.024840    0.377880    0.4207840
+51492.00   0.025657   0.377145   0.4195125    0.025610    0.377150    0.4195120
+51493.00   0.026741   0.376460   0.4183198    0.026750    0.376460    0.4183170
+51494.00   0.027764   0.376262   0.4171923    0.027750    0.376140    0.4172030
+51495.00   0.028474   0.376609   0.4160811    0.028440    0.376550    0.4160980
+51496.00   0.028809   0.377310   0.4149095    0.028950    0.377350    0.4149150
+51497.00   0.028761   0.377949   0.4136514    0.028830    0.378060    0.4136300
+51498.00   0.028712   0.378224   0.4123109    0.028600    0.378260    0.4122870
+51499.00   0.029229   0.378250   0.4108591    0.029220    0.378260    0.4108540
+51500.00   0.030311   0.378225   0.4092440    0.030320    0.378220    0.4092360
+51501.00   0.031599   0.378298   0.4075068    0.031550    0.378290    0.4074990
+51502.00   0.032630   0.378479   0.4057008    0.032670    0.378520    0.4057080
+51503.00   0.033130   0.378618   0.4038769    0.033180    0.378650    0.4038770
+51504.00   0.033152   0.378618   0.4021328    0.033160    0.378630    0.4021340
+51505.00   0.032879   0.378417   0.4005584    0.032830    0.378490    0.4005630
+51506.00   0.032516   0.378016   0.3991948    0.032520    0.378050    0.3991930
+51507.00   0.032158   0.377578   0.3980249    0.032220    0.377580    0.3980150
+51508.00   0.031840   0.377205   0.3969956    0.031880    0.377270    0.3969800
+51509.00   0.031731   0.376900   0.3960227    0.031730    0.376960    0.3960080
+51510.00   0.032013   0.376716   0.3950159    0.031980    0.376690    0.3950130
+51511.00   0.032624   0.376739   0.3939021    0.032620    0.376770    0.3939120
+51512.00   0.033305   0.377007   0.3926455    0.033360    0.377030    0.3926480
+51513.00   0.033866   0.377511   0.3912784    0.033910    0.377480    0.3912670
+51514.00   0.034243   0.378168   0.3898971    0.034260    0.378180    0.3898730
+51515.00   0.034482   0.378767   0.3885654    0.034480    0.378850    0.3885010
+51516.00   0.034712   0.379145   0.3873141    0.034700    0.379180    0.3872730
+51517.00   0.034806   0.379274   0.3861571    0.034850    0.379330    0.3861610
+51518.00   0.034636   0.379187   0.3851032    0.034710    0.379240    0.3851200
+51519.00   0.034509   0.378991   0.3841467    0.034490    0.378970    0.3841480
+51520.00   0.034839   0.378900   0.3832822    0.034790    0.378900    0.3832790
+51521.00   0.035705   0.379108   0.3824822    0.035700    0.379150    0.3824670
+51522.00   0.036626   0.379542   0.3816877    0.036690    0.379600    0.3816790
+51523.00   0.037157   0.379986   0.3808536    0.037230    0.380060    0.3808610
+51524.00   0.037313   0.380340   0.3799565    0.037340    0.380370    0.3799460
+51525.00   0.037388   0.380650   0.3789967    0.037370    0.380650    0.3790130
+51526.00   0.037709   0.381013   0.3779240    0.037680    0.380980    0.3779550
+51527.00   0.038233   0.381469   0.3767143    0.038290    0.381490    0.3767130
+51528.00   0.038411   0.381831   0.3753863    0.038470    0.381890    0.3753720
+51529.00   0.038307   0.381983   0.3739443    0.038300    0.381920    0.3739430
+51530.00   0.038151   0.382020   0.3724233    0.038120    0.381980    0.3724420
+51531.00   0.037966   0.382019   0.3708867    0.037990    0.382080    0.3709520
+51532.00   0.037613   0.381863   0.3694136    0.037700    0.381940    0.3694790
+51533.00   0.037076   0.381420   0.3680734    0.037210    0.381360    0.3680520
+51534.00   0.036608   0.380682   0.3668939    0.036610    0.380730    0.3668750
+51535.00   0.036570   0.379666   0.3658297    0.036540    0.379730    0.3658610
+51536.00   0.037112   0.378618   0.3648087    0.037160    0.378560    0.3647670
+51537.00   0.038004   0.377845   0.3637629    0.038060    0.377680    0.3636580
+51538.00   0.039000   0.377510   0.3626369    0.039020    0.377410    0.3625410
+51539.00   0.040049   0.377548   0.3614129    0.040050    0.377580    0.3613690
+51540.00   0.041137   0.377788   0.3601152    0.041120    0.377740    0.3601150
+51541.00   0.042052   0.378106   0.3588103    0.041930    0.378160    0.3588120
+51542.00   0.042547   0.378200   0.3575773    0.042450    0.378270    0.3575540
+51543.00   0.042890   0.377991   0.3564633    0.042860    0.377980    0.3564530
+51544.00   0.043215   0.377697   0.3554732    0.043190    0.377700    0.3554990
+51545.00   0.043455   0.377468   0.3545966    0.043480    0.377510    0.3546330
+51546.00   0.043512   0.377238   0.3538464    0.043590    0.377270    0.3538640
+51547.00   0.043363   0.376945   0.3532360    0.043410    0.376940    0.3532310
+51548.00   0.043134   0.376623   0.3527537    0.043160    0.376600    0.3527960
+51549.00   0.043149   0.376297   0.3523431    0.043140    0.376270    0.3524010
+51550.00   0.043422   0.376104   0.3519484    0.043440    0.376070    0.3519450
+51551.00   0.043659   0.375969   0.3515404    0.043730    0.376020    0.3515040
+51552.00   0.043675   0.375686   0.3510966    0.043690    0.375760    0.3510900
+51553.00   0.043604   0.375254   0.3505534    0.043590    0.375250    0.3505590
+51554.00   0.043745   0.374881   0.3498790    0.043740    0.374760    0.3498330
+51555.00   0.044251   0.374731   0.3490532    0.044220    0.374640    0.3489670
+51556.00   0.045178   0.374726   0.3480742    0.045170    0.374690    0.3479980
+51557.00   0.046378   0.374757   0.3469483    0.046490    0.374730    0.3469090
+51558.00   0.047518   0.374783   0.3457480    0.047640    0.374810    0.3457280
+51559.00   0.048487   0.374789   0.3445662    0.048510    0.374820    0.3445610
+51560.00   0.049484   0.374848   0.3434739    0.049450    0.374840    0.3435070
+51561.00   0.050671   0.375099   0.3424895    0.050690    0.375130    0.3425460
+51562.00   0.051944   0.375468   0.3415968    0.051980    0.375540    0.3416250
+51563.00   0.053115   0.375682   0.3407635    0.053160    0.375720    0.3407420
+51564.00   0.054190   0.375869   0.3399193    0.054210    0.375830    0.3398860
+51565.00   0.055094   0.376229   0.3390041    0.055110    0.376210    0.3389880
+51566.00   0.055780   0.376695   0.3379742    0.055820    0.376690    0.3379660
+51567.00   0.056228   0.377100   0.3368184    0.056210    0.377100    0.3368040
+51568.00   0.056440   0.377321   0.3355604    0.056420    0.377350    0.3355310
+51569.00   0.056569   0.377302   0.3342584    0.056570    0.377290    0.3342110
+51570.00   0.056930   0.377024   0.3329659    0.056980    0.376990    0.3329220
+51571.00   0.057279   0.376691   0.3317549    0.057300    0.376720    0.3317330
+51572.00   0.057260   0.376406   0.3306897    0.057180    0.376380    0.3306810
+51573.00   0.057053   0.376159   0.3297764    0.056980    0.376130    0.3297760
+51574.00   0.056920   0.375899   0.3289928    0.056930    0.375950    0.3290060
+51575.00   0.056955   0.375515   0.3283083    0.056890    0.375520    0.3283220
+51576.00   0.057214   0.374985   0.3276983    0.057200    0.375010    0.3276990
+51577.00   0.057620   0.374341   0.3271605    0.057660    0.374400    0.3271500
+51578.00   0.058222   0.373714   0.3266641    0.058190    0.373750    0.3266670
+51579.00   0.058993   0.373135   0.3261312    0.059040    0.373130    0.3261480
+51580.00   0.059938   0.372624   0.3254829    0.059970    0.372620    0.3254630
+51581.00   0.061017   0.372235   0.3246859    0.061040    0.372220    0.3245860
+51582.00   0.062195   0.371971   0.3237181    0.062240    0.371940    0.3236430
+51583.00   0.063502   0.371823   0.3225902    0.063470    0.371980    0.3225890
+51584.00   0.064771   0.371580   0.3213657    0.064720    0.371710    0.3213750
+51585.00   0.065761   0.371153   0.3201477    0.065790    0.371160    0.3201260
+51586.00   0.066202   0.370649   0.3190448    0.066240    0.370670    0.3190220
+51587.00   0.066157   0.370171   0.3181117    0.066190    0.370140    0.3181430
+51588.00   0.066000   0.369722   0.3173178    0.065970    0.369710    0.3173170
+51589.00   0.066136   0.369254   0.3166298    0.066020    0.369250    0.3166280
+51590.00   0.066699   0.368822   0.3159886    0.066650    0.368810    0.3159960
+51591.00   0.067329   0.368509   0.3153378    0.067380    0.368490    0.3153000
+51592.00   0.067939   0.368369   0.3146275    0.067960    0.368340    0.3145900
+51593.00   0.068516   0.368291   0.3137951    0.068520    0.368310    0.3138080
+51594.00   0.069027   0.368146   0.3127835    0.069000    0.368190    0.3128270
+51595.00   0.069214   0.367844   0.3116045    0.069170    0.367900    0.3116160
+51596.00   0.069035   0.367356   0.3103486    0.068980    0.367350    0.3103220
+51597.00   0.068730   0.366746   0.3091149    0.068720    0.366770    0.3091040
+51598.00   0.068361   0.366024   0.3079714    0.068400    0.366050    0.3079750
+51599.00   0.067890   0.365197   0.3069563    0.067930    0.365220    0.3069360
+51600.00   0.067390   0.364288   0.3060864    0.067440    0.364350    0.3060680
+51601.00   0.066951   0.363382   0.3053466    0.066970    0.363430    0.3053490
+51602.00   0.066617   0.362566   0.3047064    0.066620    0.362640    0.3046720
+51603.00   0.066422   0.361905   0.3041427    0.066450    0.361910    0.3041150
+51604.00   0.066401   0.361388   0.3036098    0.066400    0.361470    0.3036080
+51605.00   0.066648   0.360890   0.3030436    0.066580    0.360960    0.3030390
+51606.00   0.067130   0.360477   0.3024079    0.067140    0.360330    0.3024040
+51607.00   0.067620   0.360236   0.3016646    0.067760    0.360170    0.3016670
+51608.00   0.067948   0.360099   0.3007691    0.067950    0.360180    0.3007680
+51609.00   0.068216   0.359961   0.2996940    0.068160    0.360020    0.2996990
+51610.00   0.068525   0.359801   0.2984518    0.068600    0.359770    0.2984570
+51611.00   0.068828   0.359586   0.2970918    0.068820    0.359720    0.2970870
+51612.00   0.069387   0.359217   0.2956919    0.069280    0.359300    0.2956890
+51613.00   0.070402   0.358866   0.2943263    0.070270    0.358810    0.2943390
+51614.00   0.071773   0.358686   0.2930544    0.071690    0.358680    0.2930720
+51615.00   0.073083   0.358599   0.2919128    0.073060    0.358650    0.2919190
+51616.00   0.073990   0.358364   0.2909174    0.073940    0.358480    0.2909220
+51617.00   0.074480   0.357854   0.2900542    0.074370    0.357960    0.2900640
+51618.00   0.074671   0.357111   0.2892761    0.074620    0.357200    0.2892770
+51619.00   0.074758   0.356241   0.2884848    0.074740    0.356290    0.2884850
+51620.00   0.074596   0.355401   0.2876281    0.074570    0.355470    0.2876310
+51621.00   0.074245   0.354616   0.2867043    0.074260    0.354760    0.2867060
+51622.00   0.073913   0.353859   0.2857300    0.073980    0.353950    0.2857400
+51623.00   0.073747   0.353172   0.2847254    0.073730    0.353110    0.2847510
+51624.00   0.073826   0.352606   0.2836875    0.073800    0.352620    0.2837170
+51625.00   0.073986   0.352100   0.2826302    0.074010    0.352130    0.2826370
+51626.00   0.073990   0.351575   0.2816146    0.073980    0.351510    0.2815880
+51627.00   0.073949   0.351028   0.2807146    0.073900    0.351030    0.2807060
+51628.00   0.073762   0.350394   0.2799580    0.073770    0.350450    0.2799650
+51629.00   0.073420   0.349596   0.2793488    0.073380    0.349600    0.2793210
+51630.00   0.073080   0.348740   0.2788852    0.073100    0.348650    0.2789080
+51631.00   0.072772   0.347935   0.2784878    0.072860    0.347950    0.2785310
+51632.00   0.072757   0.347135   0.2780890    0.072710    0.347190    0.2780890
+51633.00   0.073380   0.346415   0.2776678    0.073380    0.346410    0.2776610
+51634.00   0.074374   0.345977   0.2771617    0.074460    0.346060    0.2771740
+51635.00   0.075198   0.345904   0.2764928    0.075220    0.345980    0.2765170
+51636.00   0.075808   0.346131   0.2756134    0.075680    0.346120    0.2756560
+51637.00   0.076481   0.346510   0.2745277    0.076340    0.346510    0.2745730
+51638.00   0.076985   0.346828   0.2732774    0.077030    0.346880    0.2732930
+51639.00   0.077059   0.346914   0.2719400    0.077060    0.346950    0.2719320
+51640.00   0.077093   0.346707   0.2706251    0.077060    0.346750    0.2706330
+51641.00   0.077296   0.346262   0.2694147    0.077310    0.346310    0.2694350
+51642.00   0.077573   0.345685   0.2683416    0.077600    0.345730    0.2683450
+51643.00   0.077806   0.345015   0.2674068    0.077800    0.345120    0.2674040
+51644.00   0.078238   0.344262   0.2665760    0.078180    0.344290    0.2665780
+51645.00   0.079142   0.343638   0.2657834    0.079090    0.343600    0.2657810
+51646.00   0.080330   0.343365   0.2649542    0.080370    0.343360    0.2649460
+51647.00   0.081333   0.343380   0.2640252    0.081460    0.343390    0.2640320
+51648.00   0.081906   0.343576   0.2629513    0.081990    0.343570    0.2629550
+51649.00   0.082086   0.343849   0.2617145    0.082090    0.343870    0.2617140
+51650.00   0.082136   0.344069   0.2603384    0.082110    0.344100    0.2603470
+51651.00   0.082226   0.344150   0.2588795    0.082280    0.344150    0.2588640
+51652.00   0.082276   0.344044   0.2574198    0.082430    0.344110    0.2574370
+51653.00   0.082219   0.343715   0.2560309    0.082280    0.343740    0.2560440
+51654.00   0.082294   0.343161   0.2547592    0.082350    0.343120    0.2547520
+51655.00   0.082424   0.342461   0.2536047    0.082580    0.342510    0.2536740
+51656.00   0.082541   0.341696   0.2525701    0.082560    0.341730    0.2526650
+51657.00   0.082838   0.340923   0.2516714    0.082870    0.340860    0.2517210
+51658.00   0.083396   0.340229   0.2509021    0.083440    0.340130    0.2509180
+51659.00   0.084129   0.339694   0.2502312    0.084160    0.339640    0.2502580
+51660.00   0.084942   0.339305   0.2496080    0.084990    0.339270    0.2496080
+51661.00   0.085776   0.338979   0.2489548    0.085840    0.338870    0.2489720
+51662.00   0.086596   0.338677   0.2481768    0.086640    0.338570    0.2481970
+51663.00   0.087438   0.338335   0.2472104    0.087450    0.338270    0.2471880
+51664.00   0.088310   0.337912   0.2460469    0.088320    0.337850    0.2460670
+51665.00   0.089074   0.337501   0.2447165    0.089060    0.337400    0.2447320
+51666.00   0.089646   0.337119   0.2432550    0.089650    0.337110    0.2432530
+51667.00   0.089943   0.336653   0.2417404    0.089980    0.336700    0.2417460
+51668.00   0.089876   0.335967   0.2402498    0.089850    0.336090    0.2402460
+51669.00   0.089512   0.335028   0.2388797    0.089490    0.334990    0.2388380
+51670.00   0.089040   0.333967   0.2376950    0.089050    0.333810    0.2376060
+51671.00   0.088496   0.332907   0.2366841    0.088530    0.332910    0.2365990
+51672.00   0.087926   0.331857   0.2357910    0.087960    0.331860    0.2357550
+51673.00   0.087469   0.330886   0.2349382    0.087530    0.330830    0.2349480
+51674.00   0.087221   0.330148   0.2340443    0.087260    0.330140    0.2340480
+51675.00   0.087388   0.329677   0.2330322    0.087380    0.329760    0.2330110
+51676.00   0.088025   0.329575   0.2319108    0.088070    0.329580    0.2318930
+51677.00   0.088812   0.329617   0.2307012    0.088870    0.329580    0.2307180
+51678.00   0.089475   0.329668   0.2294361    0.089470    0.329690    0.2294520
+51679.00   0.090028   0.329588   0.2281687    0.090050    0.329610    0.2281330
+51680.00   0.090488   0.329187   0.2269698    0.090540    0.329170    0.2269170
+51681.00   0.090846   0.328477   0.2258826    0.090870    0.328450    0.2258710
+51682.00   0.091393   0.327755   0.2248928    0.091390    0.327710    0.2248910
+51683.00   0.092217   0.327154   0.2240194    0.092280    0.327100    0.2239890
+51684.00   0.093187   0.326636   0.2232798    0.093220    0.326590    0.2232440
+51685.00   0.093994   0.326187   0.2226631    0.094040    0.326130    0.2226540
+51686.00   0.094457   0.325675   0.2221314    0.094520    0.325650    0.2221350
+51687.00   0.094541   0.324805   0.2216301    0.094640    0.324730    0.2216290
+51688.00   0.094765   0.323507   0.2211125    0.094850    0.323410    0.2210940
+51689.00   0.095304   0.322391   0.2205648    0.095340    0.322360    0.2205220
+51690.00   0.096112   0.321571   0.2199668    0.096140    0.321540    0.2199430
+51691.00   0.097312   0.320835   0.2192941    0.097340    0.320780    0.2193000
+51692.00   0.098918   0.320093   0.2185232    0.098910    0.320120    0.2185070
+51693.00   0.100678   0.319359   0.2176552    0.100690    0.319400    0.2176300
+51694.00   0.102331   0.318691   0.2167245    0.102300    0.318690    0.2167470
+51695.00   0.103800   0.318055   0.2157888    0.103790    0.318060    0.2157980
+51696.00   0.105087   0.317341   0.2149209    0.105050    0.317360    0.2149210
+51697.00   0.106400   0.316492   0.2141761    0.106310    0.316510    0.2141970
+51698.00   0.107684   0.315507   0.2135716    0.107760    0.315500    0.2135470
+51699.00   0.108770   0.314486   0.2130846    0.108820    0.314500    0.2130840
+51700.00   0.109818   0.313510   0.2126473    0.109820    0.313540    0.2126560
+51701.00   0.110928   0.312639   0.2121691    0.110970    0.312620    0.2121930
+51702.00   0.111937   0.311860   0.2115752    0.111870    0.311870    0.2115840
+51703.00   0.112461   0.311070   0.2108262    0.112450    0.311120    0.2108200
+51704.00   0.112535   0.310143   0.2099522    0.112510    0.310180    0.2099400
+51705.00   0.112490   0.308914   0.2090299    0.112470    0.308970    0.2090050
+51706.00   0.112729   0.307475   0.2081422    0.112680    0.307450    0.2081520
+51707.00   0.113194   0.306099   0.2073506    0.113130    0.306060    0.2073440
+51708.00   0.113500   0.304864   0.2067048    0.113470    0.304900    0.2067100
+51709.00   0.113577   0.303639   0.2062475    0.113620    0.303680    0.2062480
+51710.00   0.113645   0.302472   0.2060009    0.113600    0.302480    0.2059850
+51711.00   0.113161   0.301332   0.2059520    0.113100    0.301300    0.2059900
+51712.00   0.112189   0.300267   0.2060449    0.112160    0.300250    0.2060860
+51713.00   0.110999   0.299135   0.2062115    0.111010    0.299210    0.2061740
+51714.00   0.109831   0.297643   0.2064062    0.109870    0.297710    0.2063480
+51715.00   0.108880   0.295971   0.2065859    0.108870    0.296020    0.2065770
+51716.00   0.108124   0.294316   0.2066983    0.108140    0.294340    0.2067080
+51717.00   0.107741   0.292556   0.2067001    0.107770    0.292570    0.2066590
+51718.00   0.107635   0.290771   0.2065948    0.107700    0.290810    0.2065550
+51719.00   0.107822   0.289158   0.2063949    0.107890    0.289170    0.2064170
+51720.00   0.108185   0.287884   0.2061000    0.108190    0.287890    0.2061060
+51721.00   0.108554   0.286664   0.2057138    0.108550    0.286670    0.2056990
+51722.00   0.108995   0.285324   0.2052783    0.108990    0.285330    0.2053220
+51723.00   0.109531   0.283989   0.2048415    0.109520    0.283980    0.2048650
+51724.00   0.110044   0.282821   0.2044716    0.110020    0.282840    0.2044680
+51725.00   0.110221   0.281535   0.2042304    0.110210    0.281560    0.2042410
+51726.00   0.110169   0.280039   0.2041293    0.110140    0.280000    0.2040530
+51727.00   0.109967   0.278617   0.2041166    0.109940    0.278620    0.2039720
+51728.00   0.109546   0.277387   0.2040917    0.109520    0.277410    0.2039550
+51729.00   0.108963   0.276322   0.2039568    0.108970    0.276340    0.2038820
+51730.00   0.108195   0.275448   0.2036533    0.108210    0.275460    0.2036680
+51731.00   0.107386   0.274682   0.2031755    0.107390    0.274680    0.2031930
+51732.00   0.107012   0.273910   0.2025619    0.106990    0.273890    0.2025540
+51733.00   0.106830   0.273235   0.2018964    0.106810    0.273230    0.2018930
+51734.00   0.106345   0.272676   0.2012574    0.106320    0.272700    0.2012680
+51735.00   0.105472   0.272081   0.2006965    0.105450    0.272070    0.2007080
+51736.00   0.104471   0.271366   0.2002445    0.104450    0.271300    0.2002440
+51737.00   0.103658   0.270383   0.1999051    0.103620    0.270380    0.1999000
+51738.00   0.102881   0.269207   0.1996952    0.102910    0.269240    0.1996870
+51739.00   0.102127   0.268078   0.1996037    0.102150    0.268100    0.1996080
+51740.00   0.101213   0.266972   0.1996296    0.101200    0.267020    0.1996010
+51741.00   0.100163   0.265843   0.1997601    0.100110    0.265850    0.1997040
+51742.00   0.099235   0.264837   0.1999437    0.099230    0.264830    0.1999110
+51743.00   0.098285   0.263948   0.2001382    0.098270    0.263900    0.2001430
+51744.00   0.097161   0.262947   0.2003128    0.097120    0.262910    0.2003170
+51745.00   0.096019   0.261634   0.2004413    0.096020    0.261600    0.2004180
+51746.00   0.094818   0.260257   0.2005212    0.094860    0.260160    0.2005040
+51747.00   0.093439   0.259074   0.2005555    0.093450    0.259050    0.2005770
+51748.00   0.092112   0.258017   0.2005297    0.092080    0.258090    0.2005480
+51749.00   0.091249   0.256975   0.2004521    0.091250    0.257010    0.2004300
+51750.00   0.090774   0.256140   0.2003567    0.090800    0.256130    0.2003190
+51751.00   0.090467   0.255547   0.2002801    0.090420    0.255640    0.2002770
+51752.00   0.090291   0.255049   0.2002659    0.090210    0.255130    0.2002820
+51753.00   0.089877   0.254516   0.2003391    0.089820    0.254560    0.2003350
+51754.00   0.089117   0.253907   0.2004866    0.089090    0.253970    0.2004870
+51755.00   0.088353   0.253164   0.2006483    0.088320    0.253210    0.2006530
+51756.00   0.087624   0.252369   0.2007368    0.087600    0.252400    0.2007420
+51757.00   0.086922   0.251692   0.2006819    0.086920    0.251760    0.2006950
+51758.00   0.086416   0.251127   0.2004629    0.086350    0.251190    0.2004710
+51759.00   0.085879   0.250675   0.2001140    0.085880    0.250750    0.2000900
+51760.00   0.085277   0.250228   0.1997081    0.085310    0.250310    0.1997160
+51761.00   0.084583   0.249655   0.1993192    0.084600    0.249680    0.1993260
+51762.00   0.083909   0.249042   0.1990109    0.083890    0.249060    0.1990050
+51763.00   0.083208   0.248525   0.1988276    0.083200    0.248580    0.1988220
+51764.00   0.082305   0.248115   0.1987890    0.082270    0.248180    0.1987940
+51765.00   0.081267   0.247773   0.1988874    0.081170    0.247790    0.1988930
+51766.00   0.079976   0.247487   0.1990782    0.079980    0.247550    0.1990860
+51767.00   0.078346   0.247089   0.1993185    0.078360    0.247210    0.1993320
+51768.00   0.076607   0.246398   0.1995682    0.076600    0.246450    0.1995820
+51769.00   0.075050   0.245638   0.1997864    0.075080    0.245660    0.1997900
+51770.00   0.073685   0.245040   0.1999357    0.073680    0.245120    0.1999360
+51771.00   0.072650   0.244535   0.1999812    0.072610    0.244590    0.1999960
+51772.00   0.071939   0.244191   0.1998923    0.071990    0.244180    0.1999100
+51773.00   0.071315   0.244107   0.1996358    0.071320    0.244120    0.1996310
+51774.00   0.070374   0.244145   0.1992137    0.070350    0.244190    0.1992030
+51775.00   0.069083   0.244139   0.1986598    0.069080    0.244150    0.1986760
+51776.00   0.067529   0.244006   0.1980179    0.067510    0.244020    0.1980460
+51777.00   0.065843   0.243813   0.1973375    0.065840    0.243870    0.1973380
+51778.00   0.063909   0.243619   0.1966686    0.063950    0.243660    0.1966380
+51779.00   0.062076   0.243350   0.1960529    0.062070    0.243450    0.1960370
+51780.00   0.060596   0.243028   0.1955095    0.060540    0.243110    0.1955580
+51781.00   0.059118   0.242771   0.1950637    0.059070    0.242770    0.1951390
+51782.00   0.057453   0.242702   0.1946679    0.057380    0.242750    0.1946870
+51783.00   0.055584   0.242638   0.1942311    0.055540    0.242700    0.1942120
+51784.00   0.053762   0.242461   0.1936784    0.053770    0.242480    0.1936680
+51785.00   0.052242   0.242168   0.1929644    0.052240    0.242200    0.1929680
+51786.00   0.051091   0.241829   0.1920968    0.051050    0.241840    0.1920900
+51787.00   0.050026   0.241689   0.1911429    0.050050    0.241700    0.1911300
+51788.00   0.049004   0.241787   0.1901885    0.049000    0.241830    0.1902050
+51789.00   0.047868   0.241878   0.1893152    0.047870    0.241900    0.1893390
+51790.00   0.046627   0.241895   0.1885815    0.046610    0.241930    0.1885410
+51791.00   0.045163   0.241966   0.1880169    0.045120    0.242050    0.1879720
+51792.00   0.043394   0.242041   0.1876245    0.043370    0.242120    0.1875600
+51793.00   0.041253   0.242044   0.1873924    0.041300    0.242150    0.1873680
+51794.00   0.038987   0.241874   0.1872994    0.038960    0.241980    0.1873270
+51795.00   0.036646   0.241519   0.1873119    0.036650    0.241590    0.1873080
+51796.00   0.034228   0.241045   0.1873757    0.034220    0.241120    0.1874040
+51797.00   0.031863   0.240490   0.1874162    0.031860    0.240520    0.1874630
+51798.00   0.029800   0.240042   0.1873909    0.029850    0.240070    0.1874080
+51799.00   0.027756   0.239711   0.1872765    0.027770    0.239730    0.1872670
+51800.00   0.025131   0.239553   0.1870392    0.025180    0.239550    0.1870400
+51801.00   0.022100   0.239613   0.1866261    0.022170    0.239660    0.1866420
+51802.00   0.019235   0.239702   0.1860446    0.019230    0.239770    0.1860490
+51803.00   0.016892   0.239768   0.1853451    0.016920    0.239800    0.1853450
+51804.00   0.015146   0.239926   0.1846132    0.015190    0.239960    0.1845970
+51805.00   0.013673   0.240390   0.1839280    0.013700    0.240450    0.1839060
+51806.00   0.012234   0.241177   0.1833480    0.012240    0.241170    0.1833410
+51807.00   0.010639   0.242107   0.1828855    0.010580    0.242100    0.1828890
+51808.00   0.008784   0.242995   0.1824901    0.008730    0.243030    0.1824890
+51809.00   0.006877   0.243489   0.1821322    0.006910    0.243550    0.1821650
+51810.00   0.005374   0.243521   0.1817526    0.005410    0.243510    0.1817180
+51811.00   0.004180   0.243406   0.1812846    0.004180    0.243400    0.1812110
+51812.00   0.002961   0.243379   0.1806641    0.002940    0.243410    0.1806320
+51813.00   0.001685   0.243522   0.1798529    0.001720    0.243530    0.1798730
+51814.00   0.000637   0.243908   0.1788651    0.000670    0.243960    0.1788750
+51815.00  -0.000618   0.244567   0.1777557   -0.000600    0.244620    0.1777340
+51816.00  -0.002327   0.245461   0.1766239   -0.002350    0.245470    0.1766000
+51817.00  -0.004224   0.246291   0.1755666   -0.004230    0.246310    0.1756310
+51818.00  -0.005825   0.246948   0.1746510   -0.005830    0.246970    0.1747260
+51819.00  -0.007317   0.247621   0.1739216   -0.007300    0.247640    0.1739250
+51820.00  -0.009224   0.248297   0.1733949   -0.009170    0.248320    0.1733650
+51821.00  -0.011143   0.248950   0.1730499   -0.011180    0.248870    0.1730460
+51822.00  -0.013069   0.249438   0.1728087   -0.013050    0.249390    0.1728150
+51823.00  -0.014665   0.249912   0.1725813   -0.014670    0.249930    0.1725740
+51824.00  -0.016139   0.250291   0.1722903   -0.016150    0.250310    0.1723010
+51825.00  -0.017636   0.250548   0.1718754   -0.017650    0.250520    0.1718640
+51826.00  -0.019065   0.250992   0.1712972   -0.019100    0.250930    0.1712420
+51827.00  -0.020494   0.251829   0.1705340   -0.020520    0.251850    0.1704830
+51828.00  -0.021762   0.253062   0.1695809   -0.021790    0.253120    0.1695750
+51829.00  -0.022955   0.254629   0.1684621   -0.022930    0.254700    0.1684640
+51830.00  -0.024334   0.256374   0.1672188   -0.024370    0.256430    0.1672620
+51831.00  -0.026199   0.257929   0.1659060   -0.026230    0.257910    0.1658840
+51832.00  -0.028276   0.259197   0.1645897   -0.028270    0.259150    0.1644540
+51833.00  -0.030364   0.260226   0.1633355   -0.030370    0.260220    0.1631760
+51834.00  -0.032237   0.261068   0.1621903   -0.032240    0.261070    0.1621250
+51835.00  -0.034006   0.261825   0.1611638   -0.033940    0.261820    0.1611760
+51836.00  -0.035697   0.262610   0.1602119   -0.035650    0.262640    0.1601930
+51837.00  -0.037440   0.263490   0.1592914   -0.037410    0.263500    0.1593100
+51838.00  -0.039119   0.264415   0.1583268   -0.039160    0.264420    0.1584290
+51839.00  -0.040594   0.265452   0.1572384   -0.040620    0.265410    0.1573430
+51840.00  -0.041999   0.266789   0.1559864   -0.042050    0.266770    0.1560110
+51841.00  -0.043325   0.268351   0.1545737   -0.043340    0.268370    0.1545450
+51842.00  -0.044307   0.269937   0.1530409   -0.044330    0.269950    0.1530330
+51843.00  -0.045559   0.271645   0.1514582   -0.045520    0.271650    0.1514710
+51844.00  -0.046947   0.273406   0.1499040   -0.046990    0.273440    0.1499100
+51845.00  -0.048312   0.274938   0.1484473   -0.048330    0.274930    0.1484300
+51846.00  -0.049258   0.276441   0.1471312   -0.049290    0.276360    0.1471610
+51847.00  -0.050029   0.278336   0.1459646   -0.050100    0.278260    0.1460480
+51848.00  -0.051245   0.280534   0.1449376   -0.051190    0.280530    0.1449780
+51849.00  -0.052365   0.282579   0.1440273   -0.052430    0.282600    0.1440070
+51850.00  -0.053768   0.284278   0.1432139   -0.053760    0.284260    0.1432280
+51851.00  -0.055168   0.285920   0.1424100   -0.055120    0.285960    0.1424240
+51852.00  -0.056466   0.287605   0.1415673   -0.056420    0.287660    0.1415700
+51853.00  -0.057701   0.289318   0.1406684   -0.057720    0.289250    0.1406590
+51854.00  -0.059197   0.291235   0.1396914   -0.059220    0.291140    0.1396830
+51855.00  -0.060735   0.293436   0.1386201   -0.060760    0.293410    0.1386150
+51856.00  -0.062207   0.295705   0.1374452   -0.062220    0.295680    0.1374380
+51857.00  -0.063703   0.297752   0.1361688   -0.063730    0.297700    0.1361610
+51858.00  -0.065070   0.299403   0.1348301   -0.065100    0.299370    0.1348130
+51859.00  -0.065971   0.300644   0.1335009   -0.066020    0.300590    0.1334650
+51860.00  -0.066267   0.301799   0.1322709   -0.066280    0.301690    0.1322310
+51861.00  -0.066492   0.303333   0.1312182   -0.066450    0.303290    0.1312040
+51862.00  -0.067493   0.305215   0.1303689   -0.067400    0.305250    0.1303790
+51863.00  -0.069107   0.306966   0.1296774   -0.069160    0.307050    0.1296860
+51864.00  -0.071252   0.308424   0.1290646   -0.071220    0.308460    0.1290580
+51865.00  -0.073154   0.309840   0.1284567   -0.073120    0.309810    0.1284520
+51866.00  -0.074727   0.311485   0.1277697   -0.074710    0.311500    0.1277780
+51867.00  -0.075653   0.313425   0.1269444   -0.075660    0.313440    0.1269430
+51868.00  -0.075902   0.315632   0.1259690   -0.075870    0.315600    0.1259530
+51869.00  -0.075832   0.317969   0.1248704   -0.075810    0.317980    0.1248720
+51870.00  -0.075847   0.320194   0.1236988   -0.075840    0.320240    0.1237180
+51871.00  -0.076126   0.322251   0.1225155   -0.076120    0.322250    0.1224790
+51872.00  -0.076569   0.324131   0.1214167   -0.076580    0.324110    0.1213050
+51873.00  -0.077090   0.325916   0.1204631   -0.077060    0.325860    0.1203310
+51874.00  -0.077734   0.327749   0.1196786   -0.077740    0.327710    0.1195830
+51875.00  -0.078464   0.329650   0.1190476   -0.078510    0.329660    0.1190050
+51876.00  -0.079156   0.331507   0.1185260   -0.079060    0.331530    0.1185190
+51877.00  -0.079387   0.333385   0.1180405   -0.079330    0.333330    0.1180470
+51878.00  -0.079572   0.335195   0.1175256   -0.079610    0.335150    0.1175220
+51879.00  -0.080077   0.336962   0.1169465   -0.080070    0.336980    0.1169220
+51880.00  -0.080633   0.338725   0.1162730   -0.080610    0.338690    0.1162800
+51881.00  -0.080874   0.340453   0.1154659   -0.080890    0.340360    0.1155090
+51882.00  -0.080959   0.342134   0.1145151   -0.081000    0.342100    0.1145360
+51883.00  -0.081277   0.343792   0.1134289   -0.081290    0.343710    0.1134120
+51884.00  -0.081778   0.345435   0.1122263   -0.081830    0.345320    0.1122210
+51885.00  -0.082321   0.347178   0.1109317   -0.082340    0.347130    0.1109530
+51886.00  -0.082764   0.349073   0.1095995   -0.082810    0.349020    0.1095820
+51887.00  -0.083349   0.350969   0.1083132   -0.083330    0.350940    0.1083340
+51888.00  -0.083714   0.352612   0.1071406   -0.083680    0.352570    0.1071950
+51889.00  -0.083829   0.353999   0.1061295   -0.083840    0.354000    0.1061520
+51890.00  -0.083649   0.355350   0.1052914   -0.083610    0.355370    0.1052740
+51891.00  -0.082749   0.357031   0.1045855   -0.082670    0.356990    0.1045790
+51892.00  -0.081454   0.359066   0.1039318   -0.081380    0.359130    0.1039370
+51893.00  -0.080187   0.361234   0.1032411   -0.080170    0.361250    0.1032250
+51894.00  -0.079088   0.363461   0.1024684   -0.079090    0.363400    0.1024390
+51895.00  -0.078140   0.365712   0.1016101   -0.078160    0.365680    0.1014840
+51896.00  -0.077838   0.367832   0.1006813   -0.077860    0.367890    0.1004880
+51897.00  -0.078183   0.369725   0.0997235   -0.078140    0.369680    0.0996230
+51898.00  -0.078693   0.371616   0.0987847   -0.078760    0.371540    0.0987910
+51899.00  -0.078656   0.373822   0.0979190   -0.078790    0.373900    0.0978530
+51900.00  -0.078397   0.376311   0.0971744   -0.078300    0.376360    0.0971970
+51901.00  -0.078015   0.378911   0.0965589   -0.077960    0.378920    0.0966350
+51902.00  -0.077568   0.381524   0.0960664   -0.077570    0.381510    0.0961140
+51903.00  -0.077052   0.384097   0.0956855   -0.077090    0.384100    0.0956820
+51904.00  -0.076627   0.386538   0.0953894   -0.076580    0.386520    0.0953610
+51905.00  -0.076313   0.388743   0.0951401   -0.076400    0.388660    0.0951180
+51906.00  -0.076058   0.390710   0.0948989   -0.076070    0.390660    0.0948940
+51907.00  -0.075340   0.392637   0.0946252   -0.075390    0.392710    0.0946300
+51908.00  -0.074867   0.394535   0.0942721   -0.074860    0.394520    0.0942860
+51909.00  -0.074232   0.396311   0.0938013   -0.074200    0.396280    0.0938240
+51910.00  -0.073475   0.398000   0.0932012   -0.073450    0.397930    0.0932210
+51911.00  -0.072616   0.399776   0.0924807   -0.072570    0.399630    0.0924880
+51912.00  -0.071574   0.401696   0.0916585   -0.071560    0.401750    0.0916580
+51913.00  -0.071043   0.403552   0.0907643   -0.071020    0.403630    0.0907650
+51914.00  -0.070727   0.405169   0.0898571   -0.070740    0.405100    0.0898580
+51915.00  -0.070375   0.406607   0.0890085   -0.070400    0.406550    0.0890200
+51916.00  -0.070175   0.407955   0.0882806   -0.070180    0.407910    0.0883060
+51917.00  -0.070202   0.409286   0.0876993   -0.070120    0.409250    0.0877260
+51918.00  -0.070110   0.410656   0.0872305   -0.070060    0.410700    0.0872420
+51919.00  -0.069867   0.412121   0.0868107   -0.069810    0.412100    0.0868070
+51920.00  -0.069253   0.413913   0.0863871   -0.069330    0.413860    0.0863720
+51921.00  -0.068491   0.415946   0.0858811   -0.068490    0.415910    0.0858980
+51922.00  -0.067476   0.418035   0.0852171   -0.067480    0.418010    0.0852290
+51923.00  -0.066439   0.420036   0.0843862   -0.066440    0.420030    0.0843870
+51924.00  -0.065330   0.421837   0.0834544   -0.065340    0.421820    0.0834490
+51925.00  -0.063996   0.423433   0.0825093   -0.064050    0.423420    0.0825050
+51926.00  -0.062707   0.424929   0.0816517   -0.062730    0.424880    0.0816480
+51927.00  -0.061468   0.426305   0.0809688   -0.061460    0.426190    0.0809690
+51928.00  -0.060311   0.427747   0.0804814   -0.060340    0.427710    0.0804850
+51929.00  -0.059229   0.429112   0.0801680   -0.059270    0.429150    0.0801190
+51930.00  -0.058108   0.430179   0.0800094   -0.058160    0.430160    0.0799550
+51931.00  -0.056802   0.431143   0.0799699   -0.056820    0.431050    0.0799820
+51932.00  -0.055433   0.432399   0.0800133   -0.055400    0.432420    0.0800690
+51933.00  -0.054105   0.434088   0.0800967   -0.054080    0.434170    0.0801060
+51934.00  -0.052244   0.435907   0.0801067   -0.052310    0.435870    0.0800960
+51935.00  -0.050480   0.437795   0.0799898   -0.050530    0.437790    0.0799840
+51936.00  -0.049071   0.439653   0.0797378   -0.049080    0.439600    0.0797570
+51937.00  -0.047516   0.441457   0.0793490   -0.047500    0.441380    0.0794010
+51938.00  -0.045591   0.443202   0.0788464   -0.045590    0.443170    0.0789010
+51939.00  -0.043693   0.444798   0.0782754   -0.043680    0.444700    0.0782950
+51940.00  -0.042033   0.446206   0.0776959   -0.042080    0.446190    0.0776930
+51941.00  -0.040636   0.447190   0.0771815   -0.040620    0.447160    0.0771880
+51942.00  -0.039126   0.447931   0.0767659   -0.039100    0.447830    0.0767630
+51943.00  -0.037703   0.448626   0.0764797   -0.037700    0.448620    0.0764750
+51944.00  -0.036061   0.449368   0.0763355   -0.036070    0.449360    0.0763320
+51945.00  -0.034020   0.450341   0.0762962   -0.034080    0.450270    0.0763010
+51946.00  -0.032180   0.451589   0.0762796   -0.032090    0.451620    0.0762880
+51947.00  -0.030365   0.453000   0.0761678   -0.030410    0.453010    0.0761720
+51948.00  -0.028369   0.454523   0.0758262   -0.028520    0.454470    0.0758360
+51949.00  -0.026513   0.456074   0.0752100   -0.026520    0.456090    0.0751990
+51950.00  -0.024700   0.457538   0.0743443   -0.024720    0.457560    0.0743150
+51951.00  -0.023433   0.458809   0.0733026   -0.023390    0.458870    0.0732830
+51952.00  -0.022363   0.459792   0.0721740   -0.022340    0.459760    0.0721790
+51953.00  -0.020906   0.460725   0.0710272   -0.020910    0.460680    0.0710400
+51954.00  -0.019204   0.461937   0.0699186   -0.019230    0.461970    0.0699210
+51955.00  -0.017628   0.463232   0.0689386   -0.017580    0.463260    0.0689260
+51956.00  -0.015910   0.464556   0.0681089   -0.015900    0.464530    0.0681100
+51957.00  -0.014070   0.465865   0.0674058   -0.014070    0.465820    0.0673560
+51958.00  -0.012282   0.467076   0.0667945   -0.012260    0.467050    0.0667340
+51959.00  -0.010501   0.468197   0.0662114   -0.010490    0.468140    0.0661950
+51960.00  -0.008318   0.469373   0.0656072   -0.008260    0.469310    0.0656190
+51961.00  -0.005520   0.470698   0.0649585   -0.005540    0.470720    0.0649590
+51962.00  -0.002296   0.472165   0.0642607   -0.002380    0.472160    0.0642450
+51963.00   0.000948   0.473902   0.0634634    0.001010    0.473850    0.0634730
+51964.00   0.004069   0.475723   0.0625081    0.004070    0.475750    0.0625000
+51965.00   0.006803   0.477346   0.0613757    0.006820    0.477360    0.0613410
+51966.00   0.009390   0.478757   0.0600802    0.009410    0.478700    0.0600530
+51967.00   0.011992   0.479986   0.0586678    0.011990    0.479910    0.0586680
+51968.00   0.014200   0.481045   0.0572087    0.014300    0.481000    0.0572140
+51969.00   0.016153   0.481998   0.0557767    0.016090    0.481990    0.0557520
+51970.00   0.017276   0.482700   0.0544494    0.017280    0.482630    0.0544200
+51971.00   0.018496   0.483232   0.0532711    0.018470    0.483100    0.0532710
+51972.00   0.020341   0.483840   0.0522268    0.020380    0.483750    0.0522360
+51973.00   0.022588   0.484558   0.0512724    0.022620    0.484550    0.0512640
+51974.00   0.024503   0.485112   0.0503386    0.024500    0.485160    0.0503260
+51975.00   0.026284   0.485380   0.0493333    0.026380    0.485330    0.0493410
+51976.00   0.028795   0.485434   0.0481232    0.028660    0.485440    0.0481510
+51977.00   0.031018   0.485399   0.0466901    0.031050    0.485380    0.0466690
+51978.00   0.033359   0.485373   0.0451120    0.033350    0.485300    0.0451310
+51979.00   0.035564   0.485413   0.0434664    0.035550    0.485400    0.0435500
+51980.00   0.038022   0.485524   0.0418693    0.037980    0.485480    0.0419400
+51981.00   0.040915   0.485734   0.0404265    0.040870    0.485670    0.0404350
+51982.00   0.043874   0.486103   0.0392186    0.043920    0.486220    0.0392130
+51983.00   0.046406   0.486377   0.0382843    0.046450    0.486420    0.0383080
+51984.00   0.048681   0.486655   0.0375617    0.048650    0.486610    0.0375840
+51985.00   0.050978   0.487043   0.0369778    0.050980    0.487060    0.0369820
+51986.00   0.053555   0.487408   0.0364941    0.053540    0.487400    0.0364890
+51987.00   0.056329   0.487821   0.0360676    0.056310    0.487770    0.0360630
+51988.00   0.059135   0.488394   0.0356430    0.059060    0.488390    0.0356370
+51989.00   0.061688   0.488864   0.0351568    0.061640    0.488880    0.0351550
+51990.00   0.064613   0.489050   0.0345635    0.064420    0.489130    0.0345770
+51991.00   0.067318   0.489461   0.0338698    0.067340    0.489510    0.0338570
+51992.00   0.070277   0.490025   0.0330839    0.070240    0.490030    0.0330900
+51993.00   0.073332   0.490497   0.0321623    0.073320    0.490500    0.0321940
+51994.00   0.076391   0.490842   0.0311235    0.076380    0.490860    0.0311380
+51995.00   0.079270   0.491052   0.0300255    0.079230    0.491060    0.0300160
+51996.00   0.081797   0.491117   0.0289424    0.081730    0.491080    0.0289390
+51997.00   0.084181   0.491078   0.0279322    0.084070    0.491050    0.0279420
+51998.00   0.086363   0.490780   0.0270475    0.086360    0.490830    0.0270520
+51999.00   0.088580   0.490263   0.0262681    0.088550    0.490340    0.0262730
+52000.00   0.090657   0.489693   0.0255680    0.090660    0.489730    0.0255590
+52001.00   0.092713   0.489218   0.0248977    0.092710    0.489170    0.0248780
+52002.00   0.094742   0.488819   0.0241865    0.094770    0.488820    0.0241770
+52003.00   0.096970   0.488212   0.0233415    0.097060    0.488230    0.0233470
+52004.00   0.099146   0.487316   0.0222831    0.099230    0.487290    0.0222820
+52005.00   0.101639   0.486689   0.0210200    0.101620    0.486670    0.0210190
+52006.00   0.104372   0.486451   0.0196018    0.104330    0.486450    0.0196170
+52007.00   0.106684   0.486230   0.0181065    0.106650    0.486230    0.0181290
+52008.00   0.108446   0.485677   0.0167021    0.108450    0.485660    0.0167110
+52009.00   0.110408   0.484787   0.0155036    0.110420    0.484780    0.0155010
+52010.00   0.112966   0.483921   0.0145483    0.113020    0.483870    0.0145520
+52011.00   0.115877   0.483273   0.0138282    0.115940    0.483200    0.0138300
+52012.00   0.118552   0.482764   0.0133060    0.118580    0.482740    0.0132910
+52013.00   0.120993   0.482036   0.0129373    0.121010    0.481980    0.0129400
+52014.00   0.123648   0.481138   0.0126343    0.123680    0.481070    0.0126510
+52015.00   0.126521   0.480220   0.0122983    0.126590    0.480190    0.0123230
+52016.00   0.129576   0.479260   0.0118375    0.129610    0.479320    0.0118590
+52017.00   0.132758   0.478579   0.0112160    0.132870    0.478610    0.0112190
+52018.00   0.136404   0.478052   0.0104241    0.136310    0.478060    0.0104330
+52019.00   0.139400   0.477581   0.0095180    0.139470    0.477590    0.0095310
+52020.00   0.142322   0.476918   0.0085454    0.142300    0.476880    0.0085640
+52021.00   0.144945   0.476117   0.0075411    0.144920    0.476040    0.0075520
+52022.00   0.147340   0.475404   0.0065665    0.147380    0.475340    0.0065630
+52023.00   0.149333   0.474680   0.0056600    0.149330    0.474630    0.0056590
+52024.00   0.151014   0.473687   0.0048331    0.151040    0.473690    0.0048440
+52025.00   0.153471   0.472377   0.0040681    0.153320    0.472380    0.0040670
+52026.00   0.155789   0.471026   0.0033913    0.155790    0.470940    0.0033730
+52027.00   0.157806   0.469570   0.0028082    0.157800    0.469490    0.0028290
+52028.00   0.159603   0.467985   0.0022319    0.159600    0.467950    0.0022510
+52029.00   0.161444   0.466243   0.0015624    0.161460    0.466200    0.0015540
+52030.00   0.163356   0.464304   0.0007169    0.163170    0.464260    0.0006960
+52031.00   0.164950   0.462522  -0.0003369    0.164950    0.462500   -0.0003420
+52032.00   0.167277   0.461283  -0.0016044    0.167170    0.461160   -0.0015850
+52033.00   0.169451   0.460079  -0.0030462    0.169470    0.460060   -0.0030340
+52034.00   0.171731   0.458504  -0.0046043    0.171710    0.458490   -0.0046170
+52035.00   0.173634   0.456540  -0.0061441    0.173660    0.456560   -0.0061660
+52036.00   0.175770   0.454417  -0.0075479    0.175750    0.454430   -0.0075520
+52037.00   0.178361   0.452275  -0.0087514    0.178400    0.452300   -0.0087500
+52038.00   0.181152   0.450055  -0.0097479    0.181190    0.450110   -0.0097520
+52039.00   0.183899   0.447804  -0.0105429    0.183850    0.447870   -0.0105440
+52040.00   0.186558   0.445713  -0.0111874    0.186520    0.445780   -0.0111840
+52041.00   0.189162   0.444034  -0.0117606    0.189130    0.444060   -0.0117580
+52042.00   0.191399   0.442523  -0.0123357    0.191380    0.442540   -0.0123210
+52043.00   0.193310   0.440749  -0.0129715    0.193240    0.440740   -0.0129560
+52044.00   0.194797   0.438595  -0.0137153    0.194970    0.438620   -0.0137180
+52045.00   0.196885   0.436321  -0.0145805    0.196880    0.436330   -0.0145870
+52046.00   0.198612   0.433526  -0.0155485    0.198680    0.433650   -0.0155280
+52047.00   0.200793   0.430724  -0.0166117    0.200760    0.430710   -0.0166130
+52048.00   0.203161   0.427891  -0.0177380    0.203180    0.427890   -0.0177410
+52049.00   0.205174   0.425164  -0.0188736    0.205110    0.425180   -0.0188620
+52050.00   0.206955   0.422557  -0.0199526    0.206910    0.422590   -0.0199380
+52051.00   0.208746   0.420125  -0.0209135    0.208850    0.420250   -0.0209080
+52052.00   0.210426   0.417989  -0.0216892    0.210410    0.418040   -0.0216940
+52053.00   0.212039   0.415612  -0.0222479    0.211890    0.415630   -0.0222490
+52054.00   0.213256   0.413088  -0.0226142    0.213350    0.413120   -0.0226100
+52055.00   0.214679   0.410347  -0.0228347    0.214620    0.410370   -0.0228330
+52056.00   0.215942   0.407372  -0.0230140    0.215880    0.407350   -0.0230120
+52057.00   0.217326   0.404456  -0.0232574    0.217320    0.404480   -0.0232580
+52058.00   0.219019   0.401751  -0.0236287    0.219030    0.401800   -0.0236350
+52059.00   0.220923   0.399153  -0.0241428    0.220930    0.399220   -0.0241480
+52060.00   0.222844   0.396603  -0.0247593    0.222860    0.396660   -0.0247580
+52061.00   0.224462   0.394024  -0.0254085    0.224420    0.394050   -0.0253810
+52062.00   0.225856   0.391301  -0.0260285    0.225790    0.391340   -0.0260010
+52063.00   0.227208   0.388448  -0.0265294    0.227200    0.388480   -0.0265140
+52064.00   0.228755   0.385506  -0.0268396    0.228700    0.385520   -0.0268270
+52065.00   0.230305   0.382461  -0.0269233    0.230520    0.382550   -0.0268950
+52066.00   0.232394   0.379951  -0.0267701    0.232380    0.380060   -0.0267660
+52067.00   0.234494   0.377269  -0.0264129    0.234400    0.377400   -0.0264180
+52068.00   0.236427   0.374759  -0.0259398    0.236450    0.374730   -0.0259510
+52069.00   0.238000   0.372435  -0.0254444    0.237980    0.372450   -0.0254460
+52070.00   0.239149   0.370013  -0.0250118    0.239120    0.370100   -0.0250090
+52071.00   0.240122   0.367384  -0.0247004    0.240140    0.367450   -0.0246970
+52072.00   0.241075   0.364662  -0.0245354    0.241010    0.364630   -0.0245310
+52073.00   0.241862   0.361668  -0.0245107    0.241850    0.361720   -0.0245030
+52074.00   0.243205   0.358359  -0.0245966    0.243170    0.358550   -0.0245960
+52075.00   0.244809   0.355242  -0.0247260    0.244820    0.355300   -0.0247330
+52076.00   0.246266   0.352304  -0.0248955    0.246230    0.352330   -0.0248900
+52077.00   0.247366   0.349444  -0.0250968    0.247330    0.349550   -0.0250730
+52078.00   0.248189   0.346490  -0.0252880    0.248170    0.346560   -0.0252650
+52079.00   0.248439   0.343539  -0.0254205    0.248480    0.343620   -0.0254190
+52080.00   0.248322   0.340726  -0.0254431    0.248350    0.340790   -0.0254530
+52081.00   0.248209   0.337798  -0.0253430    0.248270    0.337830   -0.0253190
+52082.00   0.248422   0.334848  -0.0251893    0.248430    0.334900   -0.0252160
+52083.00   0.248662   0.331828  -0.0250212    0.248720    0.331890   -0.0249870
+52084.00   0.248931   0.328775  -0.0249081    0.248970    0.328800   -0.0248170
+52085.00   0.249514   0.325692  -0.0249313    0.249480    0.325730   -0.0248560
+52086.00   0.250305   0.322581  -0.0251681    0.250410    0.322600   -0.0251460
+52087.00   0.251263   0.319736  -0.0256329    0.251270    0.319770   -0.0256330
+52088.00   0.252011   0.317012  -0.0262455    0.251940    0.316990   -0.0262050
+52089.00   0.252360   0.313934  -0.0268484    0.252380    0.313920   -0.0268050
+52090.00   0.252992   0.310715  -0.0273415    0.252990    0.310720   -0.0273470
+52091.00   0.253731   0.307575  -0.0276738    0.253780    0.307610   -0.0277010
+52092.00   0.253964   0.304394  -0.0278178    0.253940    0.304430   -0.0278370
+52093.00   0.253753   0.301145  -0.0277834    0.253750    0.301190   -0.0277890
+52094.00   0.254215   0.298188  -0.0276027    0.254090    0.298230   -0.0276160
+52095.00   0.254232   0.295468  -0.0273324    0.254290    0.295550   -0.0273580
+52096.00   0.253911   0.292761  -0.0270278    0.253890    0.292770   -0.0270370
+52097.00   0.253524   0.290040  -0.0267282    0.253530    0.290050   -0.0267140
+52098.00   0.252708   0.287256  -0.0264986    0.252700    0.287310   -0.0264760
+52099.00   0.251813   0.284150  -0.0263669    0.251720    0.284140   -0.0263590
+52100.00   0.251686   0.280793  -0.0263067    0.251690    0.280760   -0.0263210
+52101.00   0.251944   0.277620  -0.0263047    0.251980    0.277670   -0.0263080
+52102.00   0.251507   0.274653  -0.0263530    0.251470    0.274620   -0.0263440
+52103.00   0.250977   0.271726  -0.0264534    0.250880    0.271650   -0.0264360
+52104.00   0.250420   0.268800  -0.0265857    0.250360    0.268790   -0.0265840
+52105.00   0.249489   0.265680  -0.0266888    0.249470    0.265690   -0.0266870
+52106.00   0.248487   0.262337  -0.0267108    0.248500    0.262310   -0.0266970
+52107.00   0.248045   0.259044  -0.0266166    0.248020    0.259030   -0.0265990
+52108.00   0.247899   0.255898  -0.0263879    0.247930    0.255930   -0.0263840
+52109.00   0.247886   0.252693  -0.0260054    0.247880    0.252780   -0.0260360
+52110.00   0.247644   0.249621  -0.0255194    0.247620    0.249630   -0.0255320
+52111.00   0.247124   0.246549  -0.0250172    0.247110    0.246510   -0.0250070
+52112.00   0.246308   0.243497  -0.0246244    0.246310    0.243480   -0.0245960
+52113.00   0.245303   0.240604  -0.0244283    0.245290    0.240600   -0.0243980
+52114.00   0.244181   0.237844  -0.0244490    0.244230    0.237850   -0.0244370
+52115.00   0.243624   0.235369  -0.0246366    0.243550    0.235400   -0.0246340
+52116.00   0.242989   0.232644  -0.0248666    0.242970    0.232700   -0.0248580
+52117.00   0.242022   0.229827  -0.0250474    0.242000    0.229780   -0.0250340
+52118.00   0.240668   0.226879  -0.0250822    0.240630    0.226830   -0.0250700
+52119.00   0.239018   0.223779  -0.0249085    0.239010    0.223820   -0.0249070
+52120.00   0.237308   0.220720  -0.0245315    0.237300    0.220680   -0.0245330
+52121.00   0.235872   0.217961  -0.0239862    0.235850    0.217860   -0.0239860
+52122.00   0.234708   0.215461  -0.0233285    0.234740    0.215420   -0.0233300
+52123.00   0.233413   0.213496  -0.0226143    0.233290    0.213440   -0.0226280
+52124.00   0.230934   0.211330  -0.0219419    0.230970    0.211380   -0.0219510
+52125.00   0.228252   0.208668  -0.0213853    0.228190    0.208600   -0.0213740
+52126.00   0.225848   0.205783  -0.0209760    0.225820    0.205680   -0.0209610
+52127.00   0.223854   0.203137  -0.0207247    0.223840    0.203130   -0.0207250
+52128.00   0.221846   0.200695  -0.0206206    0.221850    0.200830   -0.0206260
+52129.00   0.219641   0.198602  -0.0206566    0.219630    0.198630   -0.0206580
+52130.00   0.217156   0.196301  -0.0208393    0.217110    0.196290   -0.0208430
+52131.00   0.214270   0.194048  -0.0211293    0.214300    0.194010   -0.0211170
+52132.00   0.211292   0.191558  -0.0214996    0.211260    0.191530   -0.0215140
+52133.00   0.208443   0.188809  -0.0218695    0.208400    0.188780   -0.0219090
+52134.00   0.205986   0.186155  -0.0221796    0.206010    0.186150   -0.0222080
+52135.00   0.203661   0.183652  -0.0223872    0.203770    0.183640   -0.0223950
+52136.00   0.201030   0.181204  -0.0224832    0.201050    0.181170   -0.0224850
+52137.00   0.198726   0.178978  -0.0225064    0.198400    0.178940   -0.0225100
+52138.00   0.195935   0.176831  -0.0225537    0.196010    0.176810   -0.0225520
+52139.00   0.193417   0.174597  -0.0227462    0.193410    0.174570   -0.0227320
+52140.00   0.190985   0.172340  -0.0231581    0.190970    0.172310   -0.0231440
+52141.00   0.188799   0.170234  -0.0238223    0.188770    0.170270   -0.0238140
+52142.00   0.186205   0.168172  -0.0246828    0.186480    0.168150   -0.0246870
+52143.00   0.183852   0.165911  -0.0256448    0.183820    0.165890   -0.0256510
+52144.00   0.181210   0.163907  -0.0265834    0.181090    0.163910   -0.0265740
+52145.00   0.178677   0.162045  -0.0273417    0.178690    0.162090   -0.0273220
+52146.00   0.176475   0.160131  -0.0278971    0.176480    0.160180   -0.0279020
+52147.00   0.174361   0.158092  -0.0282024    0.174360    0.158120   -0.0282170
+52148.00   0.172421   0.156000  -0.0282814    0.172380    0.156010   -0.0282800
+52149.00   0.170433   0.153890  -0.0281922    0.170520    0.154080   -0.0281840
+52150.00   0.168322   0.152401  -0.0279987    0.168310    0.152450   -0.0280010
+52151.00   0.166083   0.150982  -0.0277811    0.165940    0.151010   -0.0277760
+52152.00   0.163282   0.149983  -0.0276358    0.163320    0.150020   -0.0276410
+52153.00   0.160290   0.149077  -0.0275677    0.160240    0.149120   -0.0275220
+52154.00   0.157071   0.147756  -0.0276349    0.157030    0.147790   -0.0275400
+52155.00   0.153925   0.146230  -0.0278569    0.153930    0.146230   -0.0278290
+52156.00   0.150804   0.144646  -0.0282213    0.150800    0.144700   -0.0282350
+52157.00   0.147452   0.142777  -0.0286907    0.147470    0.142820   -0.0286930
+52158.00   0.144611   0.140770  -0.0292332    0.144570    0.140680   -0.0292230
+52159.00   0.141812   0.139100  -0.0297340    0.141940    0.139040   -0.0296950
+52160.00   0.139469   0.137762  -0.0301363    0.139480    0.137780   -0.0301450
+52161.00   0.137173   0.136680  -0.0304103    0.137220    0.136710   -0.0304570
+52162.00   0.134793   0.135598  -0.0305519    0.134820    0.135600   -0.0305810
+52163.00   0.131937   0.134534  -0.0305697    0.132050    0.134440   -0.0305690
+52164.00   0.128799   0.133191  -0.0305005    0.128800    0.133200   -0.0304980
+52165.00   0.125569   0.132151  -0.0304014    0.125660    0.132030   -0.0304240
+52166.00   0.122462   0.130991  -0.0303880    0.122490    0.130970   -0.0304260
+52167.00   0.118823   0.129921  -0.0305704    0.118860    0.129900   -0.0305830
+52168.00   0.115134   0.129008  -0.0310339    0.115160    0.129020   -0.0310310
+52169.00   0.111702   0.128161  -0.0317828    0.111710    0.128160   -0.0317820
+52170.00   0.108312   0.127305  -0.0327193    0.108320    0.127300   -0.0327230
+52171.00   0.104560   0.126560  -0.0336945    0.104560    0.126580   -0.0336970
+52172.00   0.101202   0.125935  -0.0345894    0.101130    0.125960   -0.0345850
+52173.00   0.097832   0.125409  -0.0353300    0.097880    0.125390   -0.0353410
+52174.00   0.094515   0.124864  -0.0358762    0.094530    0.124880   -0.0358710
+52175.00   0.091429   0.124165  -0.0362401    0.091460    0.124210   -0.0362300
+52176.00   0.088536   0.123182  -0.0364427    0.088580    0.123200   -0.0364470
+52177.00   0.085411   0.122051  -0.0365260    0.085470    0.122040   -0.0365380
+52178.00   0.082376   0.120940  -0.0365832    0.082290    0.120950   -0.0365820
+52179.00   0.078852   0.119978  -0.0366762    0.078960    0.119830   -0.0366910
+52180.00   0.075375   0.119070  -0.0368739    0.075340    0.118980   -0.0368680
+52181.00   0.071799   0.118503  -0.0372183    0.071810    0.118500   -0.0372090
+52182.00   0.068626   0.118099  -0.0376932    0.068640    0.118080   -0.0376640
+52183.00   0.065428   0.117780  -0.0382971    0.065420    0.117780   -0.0382510
+52184.00   0.061701   0.117636  -0.0390380    0.061680    0.117630   -0.0390180
+52185.00   0.057927   0.117397  -0.0398955    0.057890    0.117430   -0.0399000
+52186.00   0.054765   0.117299  -0.0407777    0.054770    0.117230   -0.0407620
+52187.00   0.052007   0.117381  -0.0416711    0.052010    0.117390   -0.0416520
+52188.00   0.048970   0.117600  -0.0425184    0.049030    0.117650   -0.0425430
+52189.00   0.045981   0.117726  -0.0432326    0.045990    0.117750   -0.0432790
+52190.00   0.043041   0.117743  -0.0438207    0.043020    0.117720   -0.0438420
+52191.00   0.039838   0.117721  -0.0443233    0.039870    0.117720   -0.0443200
+52192.00   0.036029   0.117573  -0.0448060    0.036070    0.117610   -0.0447990
+52193.00   0.031916   0.117281  -0.0453585    0.031890    0.117280   -0.0453630
+52194.00   0.027453   0.117238  -0.0460502    0.027530    0.117290   -0.0460900
+52195.00   0.023095   0.117487  -0.0469466    0.023160    0.117520   -0.0469310
+52196.00   0.019346   0.117756  -0.0481163    0.019360    0.117720   -0.0480670
+52197.00   0.015946   0.118233  -0.0495361    0.015960    0.118200   -0.0495160
+52198.00   0.012831   0.118897  -0.0511037    0.012800    0.118850   -0.0511100
+52199.00   0.009771   0.119369  -0.0526870    0.009780    0.119370   -0.0526840
+52200.00   0.006624   0.119915  -0.0541499    0.006640    0.119920   -0.0541550
+52201.00   0.003117   0.120419  -0.0553755    0.003130    0.120460   -0.0553510
+52202.00  -0.000633   0.121004  -0.0563214   -0.000630    0.121030   -0.0563460
+52203.00  -0.004548   0.121787  -0.0570287   -0.004550    0.121810   -0.0571110
+52204.00  -0.008592   0.122717  -0.0575979   -0.008610    0.122720   -0.0576820
+52205.00  -0.012764   0.123691  -0.0581052   -0.012680    0.123650   -0.0581450
+52206.00  -0.016471   0.124646  -0.0586147   -0.016540    0.124620   -0.0586110
+52207.00  -0.020057   0.125720  -0.0591595   -0.020140    0.125640   -0.0591720
+52208.00  -0.023592   0.126873  -0.0598171   -0.023560    0.126840   -0.0598170
+52209.00  -0.027016   0.128062  -0.0606384   -0.027010    0.128060   -0.0606310
+52210.00  -0.030363   0.129127  -0.0616118   -0.030400    0.129080   -0.0616080
+52211.00  -0.033489   0.130207  -0.0626844   -0.033430    0.130180   -0.0626800
+52212.00  -0.036312   0.131409  -0.0638054   -0.036440    0.131310   -0.0637910
+52213.00  -0.039723   0.132495  -0.0649117   -0.039670    0.132430   -0.0649050
+52214.00  -0.042998   0.133687  -0.0659738   -0.043040    0.133660   -0.0659630
+52215.00  -0.046638   0.134773  -0.0669227   -0.046640    0.134770   -0.0669370
+52216.00  -0.050417   0.135809  -0.0676901   -0.050340    0.135800   -0.0676910
+52217.00  -0.053930   0.136813  -0.0683200   -0.053880    0.136820   -0.0683050
+52218.00  -0.056874   0.137877  -0.0688598   -0.056890    0.137870   -0.0688520
+52219.00  -0.059567   0.139242  -0.0693496   -0.059350    0.139300   -0.0693540
+52220.00  -0.061636   0.140902  -0.0698298   -0.061630    0.140970   -0.0698350
+52221.00  -0.063465   0.142802  -0.0704038   -0.063600    0.142770   -0.0703970
+52222.00  -0.065483   0.144986  -0.0712220   -0.065480    0.145000   -0.0712120
+52223.00  -0.067793   0.147468  -0.0723560   -0.067800    0.147470   -0.0723670
+52224.00  -0.069810   0.149958  -0.0737262   -0.069820    0.149910   -0.0737430
+52225.00  -0.071468   0.152519  -0.0752515   -0.071500    0.152520   -0.0752510
+52226.00  -0.073350   0.155089  -0.0768355   -0.073310    0.155070   -0.0768330
+52227.00  -0.075332   0.157245  -0.0783711   -0.075350    0.157260   -0.0783700
+52228.00  -0.077750   0.159099  -0.0796914   -0.077860    0.159060   -0.0796860
+52229.00  -0.080457   0.160740  -0.0807265   -0.080460    0.160730   -0.0807140
+52230.00  -0.082630   0.162556  -0.0815412   -0.082630    0.162600   -0.0815400
+52231.00  -0.084537   0.164432  -0.0821981   -0.084550    0.164490   -0.0822050
+52232.00  -0.086599   0.166367  -0.0827684   -0.086610    0.166400   -0.0827700
+52233.00  -0.088961   0.168447  -0.0833152   -0.088970    0.168490   -0.0833120
+52234.00  -0.091666   0.170548  -0.0838756   -0.091650    0.170580   -0.0838760
+52235.00  -0.094439   0.172912  -0.0844874   -0.094470    0.172930   -0.0844770
+52236.00  -0.097417   0.175528  -0.0852001   -0.097430    0.175550   -0.0851540
+52237.00  -0.100610   0.178082  -0.0860027   -0.100640    0.178070   -0.0859420
+52238.00  -0.103621   0.180536  -0.0868873   -0.103680    0.180540   -0.0868450
+52239.00  -0.106097   0.183056  -0.0878437   -0.106080    0.183040   -0.0878340
+52240.00  -0.108161   0.185529  -0.0888340   -0.108120    0.185520   -0.0888440
+52241.00  -0.110184   0.187897  -0.0898046   -0.110230    0.187940   -0.0898050
+52242.00  -0.112626   0.190242  -0.0906958   -0.112570    0.190300   -0.0906720
+52243.00  -0.115319   0.192771  -0.0914748   -0.115330    0.192810   -0.0914570
+52244.00  -0.118472   0.195444  -0.0921087   -0.118480    0.195510   -0.0921210
+52245.00  -0.121686   0.197956  -0.0925504   -0.121680    0.198010   -0.0925740
+52246.00  -0.124538   0.200158  -0.0928592   -0.124610    0.200230   -0.0928610
+52247.00  -0.127367   0.202499  -0.0931227   -0.127150    0.202470   -0.0931050
+52248.00  -0.129424   0.205211  -0.0934180   -0.129470    0.205230   -0.0934140
+52249.00  -0.131746   0.208532  -0.0938524   -0.131820    0.208530   -0.0938520
+52250.00  -0.134559   0.211661  -0.0944922   -0.134560    0.211710   -0.0944960
+52251.00  -0.137796   0.214373  -0.0953455   -0.137790    0.214400   -0.0953380
+52252.00  -0.140993   0.216887  -0.0963972   -0.140970    0.216840   -0.0963730
+52253.00  -0.143845   0.219614  -0.0975759   -0.143840    0.219610   -0.0975250
+52254.00  -0.146663   0.222530  -0.0987595   -0.146720    0.222550   -0.0986800
+52255.00  -0.149955   0.225288  -0.0998250   -0.149810    0.225270   -0.0997520
+52256.00  -0.152619   0.227892  -0.1007198   -0.152690    0.227810   -0.1006790
+52257.00  -0.155312   0.230578  -0.1014175   -0.155270    0.230440   -0.1014000
+52258.00  -0.157721   0.233138  -0.1018974   -0.157710    0.233150   -0.1018990
+52259.00  -0.159985   0.235805  -0.1022319   -0.159980    0.235780   -0.1022370
+52260.00  -0.161987   0.238560  -0.1025397   -0.161990    0.238560   -0.1025390
+52261.00  -0.163912   0.241535  -0.1029096   -0.163910    0.241570   -0.1029110
+52262.00  -0.165861   0.244801  -0.1033804   -0.165910    0.244800   -0.1033780
+52263.00  -0.167850   0.248402  -0.1039633   -0.167810    0.248290   -0.1039500
+52264.00  -0.169230   0.251819  -0.1047528   -0.169310    0.251770   -0.1047380
+52265.00  -0.170330   0.255332  -0.1057456   -0.170420    0.255330   -0.1057660
+52266.00  -0.171339   0.258892  -0.1068441   -0.171340    0.258950   -0.1068720
+52267.00  -0.172082   0.262522  -0.1080049   -0.172130    0.262500   -0.1080060
+52268.00  -0.172610   0.266399  -0.1091917   -0.172630    0.266380   -0.1091660
+52269.00  -0.173029   0.270501  -0.1103666   -0.172980    0.270520   -0.1103540
+52270.00  -0.173564   0.274604  -0.1114947   -0.173600    0.274890   -0.1114930
+52271.00  -0.174569   0.278560  -0.1125366   -0.174540    0.278470   -0.1125380
+52272.00  -0.175316   0.282350  -0.1134552   -0.175190    0.282350   -0.1134560
+52273.00  -0.175984   0.286373  -0.1142677   -0.175920    0.286410   -0.1142540
+52274.00  -0.176653   0.290272  -0.1150324   -0.176950    0.290250   -0.1149770
+52275.00  -0.177016   0.293921  -0.1158152   -0.177000    0.293620   -0.1158230
+52276.00  -0.177495   0.297612  -0.1166808   -0.177470    0.297200   -0.1166920
+52277.00  -0.178336   0.300810  -0.1177100   -0.178340    0.300940   -0.1177150
+52278.00  -0.179101   0.303585  -0.1189101   -0.179090    0.303680   -0.1189030
+52279.00  -0.179532   0.306461  -0.1202228   -0.179550    0.306440   -0.1202550
+52280.00  -0.180020   0.309511  -0.1215588   -0.179970    0.309560   -0.1216410
+52281.00  -0.180675   0.312707  -0.1228480   -0.180630    0.312730   -0.1229070
+52282.00  -0.181819   0.315313  -0.1239725   -0.181690    0.315560   -0.1239680
+52283.00  -0.182661   0.318169  -0.1248182   -0.182690    0.318280   -0.1248070
+52284.00  -0.183034   0.321152  -0.1254127   -0.183060    0.321190   -0.1254210
+52285.00  -0.183124   0.324202  -0.1258003   -0.183040    0.324220   -0.1257940
+52286.00  -0.182606   0.327370  -0.1260104   -0.182770    0.327380   -0.1260400
+52287.00  -0.182290   0.330466  -0.1260705   -0.182260    0.330390   -0.1261170
+52288.00  -0.181735   0.333568  -0.1260606   -0.181660    0.333550   -0.1260720
+52289.00  -0.181305   0.336868  -0.1260645   -0.181260    0.336820   -0.1260550
+52290.00  -0.180666   0.339816  -0.1261542   -0.180660    0.339780   -0.1261430
+52291.00  -0.179799   0.342945  -0.1263182   -0.179880    0.342870   -0.1263090
+52292.00  -0.179235   0.346080  -0.1265902   -0.179240    0.346120   -0.1265880
+52293.00  -0.178756   0.349176  -0.1270231   -0.178740    0.349230   -0.1270260
+52294.00  -0.178420   0.352206  -0.1275466   -0.178410    0.352280   -0.1275570
+52295.00  -0.178175   0.355254  -0.1281161   -0.178170    0.355300   -0.1281260
+52296.00  -0.177717   0.358445  -0.1287129   -0.177750    0.358510   -0.1287150
+52297.00  -0.177120   0.361868  -0.1293129   -0.177120    0.361930   -0.1293080
+52298.00  -0.176579   0.365288  -0.1298667   -0.176510    0.365290   -0.1298590
+52299.00  -0.175468   0.368698  -0.1303104   -0.175730    0.368690   -0.1303060
+52300.00  -0.174998   0.372115  -0.1306448   -0.175000    0.372170   -0.1306280
+52301.00  -0.174316   0.375411  -0.1309512   -0.174370    0.375470   -0.1309230
+52302.00  -0.173598   0.378730  -0.1313384   -0.173550    0.378710   -0.1313120
+52303.00  -0.172607   0.382056  -0.1319137   -0.172820    0.382030   -0.1319070
+52304.00  -0.172389   0.385066  -0.1327493   -0.172060    0.385140   -0.1327840
+52305.00  -0.170719   0.388310  -0.1338791   -0.170750    0.388250   -0.1339120
+52306.00  -0.168875   0.391546  -0.1351973   -0.168940    0.391530   -0.1352080
+52307.00  -0.167477   0.394739  -0.1366556   -0.167400    0.394750   -0.1365590
+52308.00  -0.166425   0.397897  -0.1381554   -0.166390    0.397840   -0.1380160
+52309.00  -0.165568   0.400893  -0.1395328   -0.165460    0.400780   -0.1394740
+52310.00  -0.164218   0.403149  -0.1407285   -0.164370    0.403580   -0.1407190
+52311.00  -0.163276   0.406446  -0.1417207   -0.163320    0.406310   -0.1417360
+52312.00  -0.162284   0.409364  -0.1424592   -0.162230    0.409320   -0.1424540
+52313.00  -0.161022   0.412491  -0.1430272   -0.161130    0.412430   -0.1430230
+52314.00  -0.159842   0.415394  -0.1434514   -0.159750    0.415430   -0.1434440
+52315.00  -0.157943   0.418781  -0.1438265   -0.157950    0.418820   -0.1438150
+52316.00  -0.156070   0.422412  -0.1442607   -0.156050    0.422450   -0.1442500
+52317.00  -0.154331   0.425633  -0.1448045   -0.154400    0.425740   -0.1447930
+52318.00  -0.153348   0.428706  -0.1454279   -0.153250    0.428820   -0.1454300
+52319.00  -0.152471   0.431713  -0.1461593   -0.152390    0.431700   -0.1461620
+52320.00  -0.151431   0.434433  -0.1469919   -0.151390    0.434420   -0.1469910
+52321.00  -0.150089   0.437078  -0.1479225   -0.150100    0.437100   -0.1479090
+52322.00  -0.148485   0.439730  -0.1489536   -0.148490    0.439730   -0.1489370
+52323.00  -0.146818   0.442441  -0.1500204   -0.146780    0.442390   -0.1500170
+52324.00  -0.145248   0.445256  -0.1510529   -0.145260    0.445150   -0.1510560
+52325.00  -0.143908   0.447804  -0.1520116   -0.143730    0.447920   -0.1520210
+52326.00  -0.142017   0.450844  -0.1528875   -0.142030    0.450810   -0.1528980
+52327.00  -0.140236   0.453903  -0.1536583   -0.140240    0.453930   -0.1536530
+52328.00  -0.138470   0.457214  -0.1543530   -0.138440    0.457220   -0.1543870
+52329.00  -0.136564   0.460595  -0.1550116   -0.136510    0.460600   -0.1551080
+52330.00  -0.134094   0.463762  -0.1557661   -0.134050    0.463790   -0.1558460
+52331.00  -0.131075   0.466899  -0.1567270   -0.131080    0.466900   -0.1567280
+52332.00  -0.128411   0.470196  -0.1579544   -0.128360    0.470160   -0.1579220
+52333.00  -0.125976   0.473454  -0.1594256   -0.125970    0.473440   -0.1594490
+52334.00  -0.123473   0.476420  -0.1610247   -0.123360    0.476540   -0.1610230
+52335.00  -0.120773   0.479750  -0.1626879   -0.120890    0.479830   -0.1626750
+52336.00  -0.118537   0.482904  -0.1642927   -0.118380    0.482830   -0.1642830
+52337.00  -0.116662   0.485901  -0.1656830   -0.116640    0.485860   -0.1656820
+52338.00  -0.114402   0.488895  -0.1668039   -0.114530    0.488880   -0.1668110
+52339.00  -0.111601   0.491674  -0.1677040   -0.111870    0.491710   -0.1677050
+52340.00  -0.108721   0.494389  -0.1684320   -0.108770    0.494280   -0.1684280
+52341.00  -0.105539   0.497043  -0.1690387   -0.105510    0.497000   -0.1690330
+52342.00  -0.102297   0.499702  -0.1695899   -0.102260    0.499710   -0.1696080
+52343.00  -0.099240   0.502427  -0.1701263   -0.099160    0.502440   -0.1701600
+52344.00  -0.096907   0.505134  -0.1707381   -0.096810    0.505150   -0.1707500
+52345.00  -0.095010   0.507537  -0.1714858   -0.095040    0.507560   -0.1714790
+52346.00  -0.092703   0.509844  -0.1723819   -0.092840    0.509890   -0.1723820
+52347.00  -0.090280   0.512133  -0.1733703   -0.090220    0.512070   -0.1733690
+52348.00  -0.087647   0.514321  -0.1743650   -0.087660    0.514370   -0.1743580
+52349.00  -0.084887   0.516458  -0.1753014   -0.084860    0.516470   -0.1753050
+52350.00  -0.081872   0.518429  -0.1761905   -0.081840    0.518430   -0.1762050
+52351.00  -0.078750   0.520307  -0.1770307   -0.078700    0.520250   -0.1770390
+52352.00  -0.075580   0.522229  -0.1777808   -0.075630    0.522210   -0.1777670
+52353.00  -0.072564   0.523982  -0.1783793   -0.072570    0.523990   -0.1783600
+52354.00  -0.069255   0.525681  -0.1788451   -0.069250    0.525600   -0.1788340
+52355.00  -0.065799   0.527523  -0.1792335   -0.065770    0.527460   -0.1792290
+52356.00  -0.062329   0.529144  -0.1796148   -0.062270    0.529100   -0.1796230
+52357.00  -0.058837   0.530650  -0.1800603   -0.058810    0.530710   -0.1801030
+52358.00  -0.055246   0.532291  -0.1806694   -0.055180    0.532160   -0.1807120
+52359.00  -0.051312   0.534075  -0.1815255   -0.051350    0.533960   -0.1815250
+52360.00  -0.048010   0.535792  -0.1826741   -0.047900    0.535800   -0.1826590
+52361.00  -0.045031   0.537281  -0.1841051   -0.044850    0.537270   -0.1841020
+52362.00  -0.041718   0.538545  -0.1856662   -0.041730    0.538490   -0.1856720
+52363.00  -0.038236   0.539546  -0.1871407   -0.038250    0.539420   -0.1871400
+52364.00  -0.034512   0.540256  -0.1884214   -0.034510    0.540310   -0.1884220
+52365.00  -0.030784   0.540741  -0.1894701   -0.030760    0.540660   -0.1894800
+52366.00  -0.027006   0.541124  -0.1902749   -0.026850    0.541150   -0.1902860
+52367.00  -0.022763   0.541626  -0.1908693   -0.022980    0.541720   -0.1908570
+52368.00  -0.018616   0.542855  -0.1913055   -0.018830    0.542820   -0.1912760
+52369.00  -0.014936   0.544230  -0.1916850   -0.014960    0.544200   -0.1916810
+52370.00  -0.011584   0.545683  -0.1920849   -0.011580    0.545710   -0.1920770
+52371.00  -0.008818   0.546912  -0.1925759   -0.008710    0.546960   -0.1925570
+52372.00  -0.006177   0.547837  -0.1931609   -0.006160    0.547850   -0.1931530
+52373.00  -0.003471   0.548651  -0.1938494   -0.003780    0.548650   -0.1938450
+52374.00  -0.001639   0.549319  -0.1946504   -0.001790    0.549280   -0.1946360
+52375.00   0.000751   0.549735  -0.1955552    0.000630    0.549660   -0.1955480
+52376.00   0.003786   0.550390  -0.1965192    0.003750    0.550380   -0.1965140
+52377.00   0.006859   0.551221  -0.1974561    0.006850    0.551270   -0.1974570
+52378.00   0.009914   0.551919  -0.1983019    0.009940    0.551890   -0.1983280
+52379.00   0.012891   0.552556  -0.1990194    0.012910    0.552530   -0.1990500
+52380.00   0.015666   0.553134  -0.1995747    0.015700    0.553150   -0.1995690
+52381.00   0.018798   0.553633  -0.1999273    0.018850    0.553680   -0.1999170
+52382.00   0.022135   0.554122  -0.2002060    0.022150    0.554150   -0.2001990
+52383.00   0.025465   0.554554  -0.2004662    0.025500    0.554540   -0.2004610
+52384.00   0.028893   0.554819  -0.2006861    0.028950    0.554890   -0.2006920
+52385.00   0.032006   0.554948  -0.2009777    0.032050    0.555000   -0.2009790
+52386.00   0.034837   0.554923  -0.2014742    0.034890    0.554920   -0.2014710
+52387.00   0.037858   0.554783  -0.2022657    0.037860    0.554810   -0.2022590
+52388.00   0.041216   0.554620  -0.2033246    0.041250    0.554620   -0.2033180
+52389.00   0.044875   0.554471  -0.2045984    0.044890    0.554490   -0.2045770
+52390.00   0.048626   0.554293  -0.2060056    0.048700    0.554360   -0.2059990
+52391.00   0.052514   0.553903  -0.2073772    0.052510    0.553960   -0.2073770
+52392.00   0.056207   0.553344  -0.2085449    0.056270    0.553350   -0.2085470
+52393.00   0.059895   0.552842  -0.2094192    0.059990    0.552900   -0.2094170
+52394.00   0.063457   0.552433  -0.2100075    0.063540    0.552680   -0.2099850
+52395.00   0.066763   0.552386  -0.2103409    0.066810    0.552550   -0.2103280
+52396.00   0.069968   0.552234  -0.2105649    0.070040    0.552260   -0.2105750
+52397.00   0.073288   0.551921  -0.2107657    0.073400    0.551980   -0.2107650
+52398.00   0.076875   0.551796  -0.2110038    0.076890    0.551810   -0.2110110
+52399.00   0.080648   0.551735  -0.2113748    0.080730    0.551700   -0.2114160
+52400.00   0.084621   0.551579  -0.2119226    0.084750    0.551580   -0.2119720
+52401.00   0.088539   0.551194  -0.2126279    0.088540    0.551260   -0.2126300
+52402.00   0.091562   0.550682  -0.2134579    0.091560    0.550730   -0.2134090
+52403.00   0.094243   0.549881  -0.2143723    0.094320    0.549950   -0.2143480
+52404.00   0.097639   0.549119  -0.2153390    0.097670    0.549210   -0.2153350
+52405.00   0.101069   0.548815  -0.2163055    0.101130    0.548850   -0.2163140
+52406.00   0.103917   0.548350  -0.2172079    0.104010    0.548380   -0.2172330
+52407.00   0.106766   0.547632  -0.2180235    0.106820    0.547560   -0.2180410
+52408.00   0.109822   0.546781  -0.2187407    0.109690    0.546720   -0.2187190
+52409.00   0.112006   0.545573  -0.2193284    0.112130    0.545580   -0.2193030
+52410.00   0.114375   0.544014  -0.2198677    0.114200    0.544020   -0.2198500
+52411.00   0.116538   0.542416  -0.2203632    0.116510    0.542440   -0.2203590
+52412.00   0.119081   0.541230  -0.2208752    0.119110    0.541240   -0.2208620
+52413.00   0.121980   0.540478  -0.2215514    0.121990    0.540490   -0.2215070
+52414.00   0.125203   0.539959  -0.2224608    0.125270    0.539970   -0.2224240
+52415.00   0.128372   0.539462  -0.2236311    0.128480    0.539480   -0.2236270
+52416.00   0.131149   0.538798  -0.2249998    0.131230    0.538810   -0.2250060
+52417.00   0.133610   0.537948  -0.2264286    0.133700    0.537930   -0.2264180
+52418.00   0.135820   0.537054  -0.2278096    0.135990    0.537030   -0.2278030
+52419.00   0.138173   0.536021  -0.2290156    0.138220    0.536070   -0.2290250
+52420.00   0.140457   0.534941  -0.2299334    0.140550    0.534950   -0.2299640
+52421.00   0.143105   0.533782  -0.2305356    0.143240    0.533780   -0.2305660
+52422.00   0.146195   0.532652  -0.2308616    0.146250    0.532660   -0.2308730
+52423.00   0.148920   0.531341  -0.2309940    0.149140    0.531430   -0.2309950
+52424.00   0.151861   0.529999  -0.2310346    0.151940    0.530030   -0.2310410
+52425.00   0.154660   0.528524  -0.2310732    0.154720    0.528570   -0.2310720
+52426.00   0.157254   0.526992  -0.2311274    0.157340    0.527040   -0.2311240
+52427.00   0.159754   0.525267  -0.2312328    0.159880    0.525310   -0.2312140
+52428.00   0.162414   0.523380  -0.2313968    0.162500    0.523430   -0.2313740
+52429.00   0.165131   0.521795  -0.2316129    0.165300    0.521670   -0.2316120
+52430.00   0.168230   0.520114  -0.2318286    0.168340    0.520030   -0.2318370
+52431.00   0.171414   0.518441  -0.2319476    0.171450    0.518430   -0.2319380
+52432.00   0.174114   0.516725  -0.2319645    0.174530    0.516740   -0.2319570
+52433.00   0.177634   0.515071  -0.2318775    0.177650    0.515060   -0.2318840
+52434.00   0.180641   0.513456  -0.2316492    0.180710    0.513450   -0.2316690
+52435.00   0.183530   0.511787  -0.2312677    0.183570    0.511780   -0.2312790
+52436.00   0.186077   0.509890  -0.2307375    0.186120    0.509890   -0.2307300
+52437.00   0.188424   0.507805  -0.2300812    0.188420    0.507800   -0.2300660
+52438.00   0.190960   0.505694  -0.2294015    0.190770    0.505750   -0.2293550
+52439.00   0.193075   0.503992  -0.2287126    0.193220    0.503920   -0.2287030
+52440.00   0.195887   0.502180  -0.2281968    0.195910    0.502180   -0.2282220
+52441.00   0.199050   0.500101  -0.2279198    0.199100    0.500090   -0.2279630
+52442.00   0.202216   0.497766  -0.2279049    0.202290    0.497760   -0.2279310
+52443.00   0.204825   0.495346  -0.2280920    0.204940    0.495220   -0.2280790
+52444.00   0.207395   0.492822  -0.2283708    0.207500    0.492730   -0.2283380
+52445.00   0.210129   0.490564  -0.2286949    0.210240    0.490560   -0.2286600
+52446.00   0.212475   0.488780  -0.2289991    0.212630    0.488670   -0.2289890
+52447.00   0.214565   0.486718  -0.2292301    0.214630    0.486680   -0.2292480
+52448.00   0.216538   0.484377  -0.2293139    0.216550    0.484340   -0.2293260
+52449.00   0.218215   0.481849  -0.2292565    0.218230    0.481840   -0.2292470
+52450.00   0.219488   0.479106  -0.2291217    0.219580    0.479140   -0.2291160
+52451.00   0.220855   0.476274  -0.2289744    0.220900    0.476260   -0.2289770
+52452.00   0.222495   0.473233  -0.2288397    0.222530    0.473240   -0.2288370
+52453.00   0.224475   0.470176  -0.2287886    0.224420    0.470060   -0.2287840
+52454.00   0.225974   0.467245  -0.2288471    0.226010    0.467180   -0.2288750
+52455.00   0.227145   0.464496  -0.2289808    0.227260    0.464490   -0.2290160
+52456.00   0.228085   0.461571  -0.2292183    0.228170    0.461610   -0.2292270
+52457.00   0.228670   0.458420  -0.2295755    0.228800    0.458450   -0.2295720
+52458.00   0.229477   0.455657  -0.2300230    0.229470    0.455480   -0.2300200
+52459.00   0.229929   0.452705  -0.2304413    0.230020    0.452640   -0.2304250
+52460.00   0.230325   0.449629  -0.2307979    0.230440    0.449620   -0.2307870
+52461.00   0.230813   0.446335  -0.2310385    0.230840    0.446330   -0.2310450
+52462.00   0.231538   0.442868  -0.2311346    0.231560    0.442800   -0.2311160
+52463.00   0.232357   0.439566  -0.2310913    0.232370    0.439500   -0.2310570
+52464.00   0.233101   0.436299  -0.2309258    0.233070    0.436310   -0.2309210
+52465.00   0.234036   0.433127  -0.2306797    0.234030    0.433250   -0.2306780
+52466.00   0.235477   0.430263  -0.2304023    0.235400    0.430340   -0.2303350
+52467.00   0.236735   0.427399  -0.2301805    0.236820    0.427380   -0.2301690
+52468.00   0.238121   0.424430  -0.2301960    0.238100    0.424380   -0.2302190
+52469.00   0.239167   0.421365  -0.2304459    0.239200    0.421320   -0.2304620
+52470.00   0.240194   0.418308  -0.2309062    0.240220    0.418270   -0.2308980
+52471.00   0.241186   0.415505  -0.2314847    0.241160    0.415450   -0.2314830
+52472.00   0.241880   0.412784  -0.2320585    0.241970    0.412750   -0.2320660
+52473.00   0.242880   0.410344  -0.2325272    0.242950    0.410280   -0.2324960
+52474.00   0.244016   0.408159  -0.2328183    0.243920    0.408040   -0.2328090
+52475.00   0.244296   0.405615  -0.2328375    0.244380    0.405560   -0.2328360
+52476.00   0.244742   0.402725  -0.2325613    0.244780    0.402680   -0.2325410
+52477.00   0.245495   0.399749  -0.2320551    0.245540    0.399670   -0.2320260
+52478.00   0.246117   0.396855  -0.2314115    0.246260    0.396850   -0.2314050
+52479.00   0.246666   0.394095  -0.2307041    0.246670    0.394040   -0.2307260
+52480.00   0.246900   0.391189  -0.2299998    0.246940    0.391050   -0.2300230
+52481.00   0.246744   0.387877  -0.2294179    0.246920    0.387830   -0.2294130
+52482.00   0.246820   0.384346  -0.2289761    0.246880    0.384320   -0.2289960
+52483.00   0.247096   0.380592  -0.2286673    0.247190    0.380540   -0.2287050
+52484.00   0.247619   0.376810  -0.2284689    0.247690    0.376780   -0.2284900
+52485.00   0.248459   0.373119  -0.2283114    0.248530    0.373170   -0.2283280
+52486.00   0.249767   0.369842  -0.2281178    0.249840    0.369800   -0.2281490
+52487.00   0.251195   0.366848  -0.2278583    0.251250    0.366800   -0.2278600
+52488.00   0.252209   0.364110  -0.2275238    0.252240    0.364080   -0.2275160
+52489.00   0.252951   0.361548  -0.2271092    0.253020    0.361480   -0.2271160
+52490.00   0.253921   0.358980  -0.2265683    0.253980    0.358920   -0.2265870
+52491.00   0.254925   0.356325  -0.2259038    0.254980    0.356280   -0.2259130
+52492.00   0.255633   0.353419  -0.2251723    0.255770    0.353310   -0.2251650
+52493.00   0.256726   0.350230  -0.2244566    0.256720    0.350180   -0.2244500
+52494.00   0.257858   0.347410  -0.2238681    0.257930    0.347350   -0.2238700
+52495.00   0.259013   0.344903  -0.2235232    0.259060    0.344730   -0.2235210
+52496.00   0.259881   0.342253  -0.2234895    0.259930    0.342210   -0.2235000
+52497.00   0.260387   0.339692  -0.2237494    0.260430    0.339680   -0.2237760
+52498.00   0.260493   0.336844  -0.2242302    0.260510    0.336830   -0.2242470
+52499.00   0.260687   0.333646  -0.2248094    0.260660    0.333730   -0.2248020
+52500.00   0.260828   0.330859  -0.2253333    0.260880    0.330800   -0.2253290
+52501.00   0.260774   0.328167  -0.2257140    0.260800    0.328160   -0.2257190
+52502.00   0.260540   0.325597  -0.2258714    0.260590    0.325560   -0.2258670
+52503.00   0.260229   0.322975  -0.2257922    0.260270    0.322960   -0.2258040
+52504.00   0.259728   0.320286  -0.2255360    0.259760    0.320270   -0.2255640
+52505.00   0.259106   0.317546  -0.2251760    0.259100    0.317490   -0.2251930
+52506.00   0.258503   0.314720  -0.2247865    0.258500    0.314620   -0.2247810
+52507.00   0.257794   0.311720  -0.2244519    0.257860    0.311680   -0.2244460
+52508.00   0.257201   0.308634  -0.2242797    0.257220    0.308630   -0.2242690
+52509.00   0.256792   0.305386  -0.2242788    0.256760    0.305340   -0.2242730
+52510.00   0.256222   0.302075  -0.2243658    0.256260    0.302050   -0.2243560
+52511.00   0.255523   0.298675  -0.2245688    0.255550    0.298650   -0.2245560
+52512.00   0.254858   0.295170  -0.2248545    0.254880    0.295130   -0.2248520
+52513.00   0.254463   0.291714  -0.2251742    0.254570    0.291610   -0.2251720
+52514.00   0.254529   0.288453  -0.2254807    0.254600    0.288320   -0.2254850
+52515.00   0.254519   0.285396  -0.2257157    0.254560    0.285420   -0.2257490
+52516.00   0.254091   0.282309  -0.2258262    0.254150    0.282230   -0.2258220
+52517.00   0.253545   0.279192  -0.2258030    0.253570    0.279080   -0.2258010
+52518.00   0.252756   0.276056  -0.2256657    0.252800    0.276040   -0.2256610
+52519.00   0.251578   0.272855  -0.2254402    0.251620    0.272820   -0.2254090
+52520.00   0.250129   0.269689  -0.2251797    0.250140    0.269660   -0.2251190
+52521.00   0.248953   0.266676  -0.2249860    0.248990    0.266590   -0.2249760
+52522.00   0.248303   0.263660  -0.2249649    0.248290    0.263550   -0.2249850
+52523.00   0.247358   0.260693  -0.2251708    0.247480    0.260610   -0.2251690
+52524.00   0.246202   0.258028  -0.2257018    0.246250    0.257990   -0.2256930
+52525.00   0.244623   0.255658  -0.2265511    0.244650    0.255640   -0.2265270
+52526.00   0.242763   0.253201  -0.2275770    0.242770    0.253220   -0.2275570
+52527.00   0.241036   0.250576  -0.2285921    0.241050    0.250530   -0.2286070
+52528.00   0.239272   0.248027  -0.2294206    0.239380    0.247960   -0.2294510
+52529.00   0.237442   0.245443  -0.2299704    0.237550    0.245520   -0.2299690
+52530.00   0.235727   0.242781  -0.2303005    0.235820    0.242720   -0.2302950
+52531.00   0.234195   0.239697  -0.2304384    0.234230    0.239620   -0.2304410
+52532.00   0.232872   0.236809  -0.2304447    0.232900    0.236760   -0.2304400
+52533.00   0.231666   0.234534  -0.2304053    0.231690    0.234540   -0.2303880
+52534.00   0.230134   0.232605  -0.2303821    0.230150    0.232650   -0.2303780
+52535.00   0.227992   0.230846  -0.2304091    0.228000    0.230880   -0.2304330
+52536.00   0.225292   0.229151  -0.2305297    0.225360    0.229150   -0.2305380
+52537.00   0.222316   0.227178  -0.2307597    0.222380    0.227190   -0.2307560
+52538.00   0.219435   0.224964  -0.2310915    0.219440    0.224910   -0.2310880
+52539.00   0.216745   0.222702  -0.2315018    0.216770    0.222670   -0.2314890
+52540.00   0.214368   0.220362  -0.2319528    0.214380    0.220350   -0.2319350
+52541.00   0.212100   0.217747  -0.2323967    0.212310    0.217770   -0.2323930
+52542.00   0.210452   0.215446  -0.2327672    0.210510    0.215420   -0.2327630
+52543.00   0.208767   0.213100  -0.2330159    0.208750    0.213110   -0.2329580
+52544.00   0.206775   0.210842  -0.2331152    0.206800    0.210720   -0.2330990
+52545.00   0.204745   0.208471  -0.2331567    0.204730    0.208400   -0.2332060
+52546.00   0.202677   0.205888  -0.2330781    0.202690    0.205880   -0.2331410
+52547.00   0.200592   0.203187  -0.2329247    0.200580    0.203140   -0.2329430
+52548.00   0.198430   0.200445  -0.2327953    0.198520    0.200480   -0.2328000
+52549.00   0.196564   0.198099  -0.2328142    0.196610    0.198090   -0.2328330
+52550.00   0.194659   0.195695  -0.2330134    0.194670    0.195650   -0.2330330
+52551.00   0.192452   0.193467  -0.2334663    0.192520    0.193410   -0.2334550
+52552.00   0.189854   0.191374  -0.2342676    0.189930    0.191370   -0.2343080
+52553.00   0.187313   0.189304  -0.2353188    0.187340    0.189270   -0.2353840
+52554.00   0.184951   0.187197  -0.2364692    0.184980    0.187140   -0.2364880
+52555.00   0.182522   0.185011  -0.2375451    0.182620    0.184970   -0.2375410
+52556.00   0.180036   0.182676  -0.2384155    0.180170    0.182730   -0.2384380
+52557.00   0.177936   0.180677  -0.2390205    0.177910    0.180620   -0.2390100
+52558.00   0.175524   0.178743  -0.2393753    0.175550    0.178830   -0.2393640
+52559.00   0.173126   0.176892  -0.2395524    0.173160    0.176910   -0.2395600
+52560.00   0.170913   0.175068  -0.2396689    0.170950    0.175020   -0.2396870
+52561.00   0.168481   0.173411  -0.2398339    0.168490    0.173340   -0.2398360
+52562.00   0.165852   0.171533  -0.2401034    0.165930    0.171640   -0.2400990
+52563.00   0.163384   0.170132  -0.2404951    0.163530    0.170080   -0.2405390
+52564.00   0.161183   0.168869  -0.2410285    0.161140    0.168790   -0.2410910
+52565.00   0.158396   0.167813  -0.2417084    0.158390    0.167740   -0.2417050
+52566.00   0.154524   0.166697  -0.2424420    0.154650    0.166660   -0.2424460
+52567.00   0.150245   0.165404  -0.2432013    0.150440    0.165330   -0.2432310
+52568.00   0.146611   0.163868  -0.2439578    0.146600    0.163910   -0.2439770
+52569.00   0.143148   0.162588  -0.2446889    0.143220    0.162700   -0.2446860
+52570.00   0.139888   0.161306  -0.2453597    0.139950    0.161420   -0.2453520
+52571.00   0.136555   0.160043  -0.2459212    0.136600    0.159880   -0.2459250
+52572.00   0.132959   0.158365  -0.2463482    0.133050    0.158470   -0.2463450
+52573.00   0.129479   0.156684  -0.2466410    0.129500    0.156810   -0.2466280
+52574.00   0.125826   0.155193  -0.2468584    0.125880    0.155240   -0.2468390
+52575.00   0.122277   0.154017  -0.2470415    0.122280    0.153930   -0.2470170
+52576.00   0.118729   0.152877  -0.2472156    0.118900    0.152880   -0.2472120
+52577.00   0.115378   0.152147  -0.2475286    0.115420    0.152150   -0.2475260
+52578.00   0.111554   0.151452  -0.2480936    0.111560    0.151430   -0.2480760
+52579.00   0.107456   0.150724  -0.2489322    0.107540    0.150700   -0.2489260
+52580.00   0.103551   0.149991  -0.2500339    0.103570    0.149990   -0.2500350
+52581.00   0.099863   0.149384  -0.2512752    0.099910    0.149380   -0.2512750
+52582.00   0.096363   0.148926  -0.2525032    0.096410    0.148870   -0.2524980
+52583.00   0.092454   0.148083  -0.2535988    0.092750    0.148250   -0.2535730
+52584.00   0.088989   0.147567  -0.2544123    0.088800    0.147510   -0.2544100
+52585.00   0.084733   0.146842  -0.2549895    0.084780    0.146840   -0.2549740
+52586.00   0.080605   0.146169  -0.2553384    0.080700    0.146110   -0.2553240
+52587.00   0.076653   0.145400  -0.2555385    0.076660    0.145430   -0.2555430
+52588.00   0.072792   0.144872  -0.2556375    0.072840    0.144860   -0.2556750
+52589.00   0.069204   0.144512  -0.2557455    0.069250    0.144500   -0.2557700
+52590.00   0.065865   0.144240  -0.2559352    0.065950    0.144170   -0.2559250
+52591.00   0.062931   0.143850  -0.2562653    0.063020    0.143850   -0.2562560
+52592.00   0.059962   0.143707  -0.2567568    0.059990    0.143740   -0.2567520
+52593.00   0.056305   0.143674  -0.2573501    0.056470    0.143620   -0.2573380
+52594.00   0.052983   0.143654  -0.2579905    0.053070    0.143640   -0.2579920
+52595.00   0.049731   0.143605  -0.2586403    0.049760    0.143600   -0.2586500
+52596.00   0.046266   0.143164  -0.2592524    0.046290    0.143150   -0.2592520
+52597.00   0.042668   0.142504  -0.2597790    0.042760    0.142590   -0.2597580
+52598.00   0.039023   0.142080  -0.2601516    0.039060    0.142050   -0.2601350
+52599.00   0.035643   0.141645  -0.2603927    0.035610    0.141620   -0.2603750
+52600.00   0.032382   0.141439  -0.2605844    0.032530    0.141440   -0.2605540
+52601.00   0.029455   0.141705  -0.2607451    0.029500    0.141590   -0.2607550
+52602.00   0.026278   0.141919  -0.2609050    0.026290    0.141920   -0.2609170
+52603.00   0.023146   0.142072  -0.2611561    0.023140    0.142090   -0.2611320
+52604.00   0.020419   0.142111  -0.2615777    0.020440    0.142180   -0.2615560
+52605.00   0.017702   0.141972  -0.2622236    0.017780    0.141910   -0.2622010
+52606.00   0.014598   0.141668  -0.2631419    0.014610    0.141600   -0.2631340
+52607.00   0.011103   0.141506  -0.2642958    0.011120    0.141530   -0.2642190
+52608.00   0.007579   0.141384  -0.2656414    0.007650    0.141380   -0.2655300
+52609.00   0.004190   0.141181  -0.2670650    0.004230    0.141160   -0.2669760
+52610.00   0.000976   0.141175  -0.2684199    0.000980    0.141150   -0.2683720
+52611.00  -0.002188   0.141366  -0.2695781   -0.002100    0.141540   -0.2695620
+52612.00  -0.005190   0.142182  -0.2704599   -0.005140    0.142250   -0.2704590
+52613.00  -0.008410   0.143068  -0.2710687   -0.008540    0.143130   -0.2710520
+52614.00  -0.012360   0.144207  -0.2714357   -0.012430    0.144160   -0.2714150
+52615.00  -0.016720   0.145538  -0.2717517   -0.016710    0.145520   -0.2717620
+52616.00  -0.020888   0.146709  -0.2721330   -0.020860    0.146750   -0.2721450
+52617.00  -0.024269   0.147737  -0.2726535   -0.024190    0.147790   -0.2726310
+52618.00  -0.027099   0.149028  -0.2733480   -0.027050    0.149110   -0.2733250
+52619.00  -0.030097   0.150624  -0.2742030   -0.029990    0.150660   -0.2742050
+52620.00  -0.032910   0.152253  -0.2751980   -0.032910    0.152320   -0.2751850
+52621.00  -0.036521   0.153643  -0.2762097   -0.036380    0.153690   -0.2762010
+52622.00  -0.040135   0.154901  -0.2772696   -0.040130    0.154810   -0.2772850
+52623.00  -0.044170   0.155905  -0.2782719   -0.044120    0.155800   -0.2783150
+52624.00  -0.048085   0.156669  -0.2791553   -0.048100    0.156550   -0.2791780
+52625.00  -0.051623   0.157274  -0.2798786   -0.051560    0.157350   -0.2798630
+52626.00  -0.054557   0.158497  -0.2804448   -0.054500    0.158360   -0.2804270
+52627.00  -0.056950   0.159883  -0.2808192   -0.056950    0.159770   -0.2808220
+52628.00  -0.059147   0.161774  -0.2810419   -0.059110    0.161760   -0.2810310
+52629.00  -0.061584   0.164084  -0.2812224   -0.061540    0.164060   -0.2812280
+52630.00  -0.064259   0.166441  -0.2813994   -0.064250    0.166410   -0.2814080
+52631.00  -0.066758   0.168646  -0.2816508   -0.066770    0.168630   -0.2816380
+52632.00  -0.069104   0.170874  -0.2820935   -0.069100    0.170830   -0.2820620
+52633.00  -0.071648   0.173153  -0.2828125   -0.071640    0.173150   -0.2827880
+52634.00  -0.074203   0.175133  -0.2837772   -0.074230    0.175140   -0.2837740
+52635.00  -0.076492   0.176860  -0.2849084   -0.076500    0.176820   -0.2849120
+52636.00  -0.078749   0.178859  -0.2860947   -0.078730    0.178830   -0.2860920
+52637.00  -0.081140   0.181116  -0.2872199   -0.081160    0.181130   -0.2872110
+52638.00  -0.083425   0.183254  -0.2881773   -0.083470    0.183210   -0.2881680
+52639.00  -0.085587   0.185612  -0.2889136   -0.085710    0.185460   -0.2889120
+52640.00  -0.088506   0.187936  -0.2894400   -0.088460    0.187930   -0.2894480
+52641.00  -0.091525   0.190250  -0.2897971   -0.091550    0.190200   -0.2897920
+52642.00  -0.094535   0.192681  -0.2901029   -0.094510    0.192640   -0.2900920
+52643.00  -0.097547   0.195185  -0.2904422   -0.097560    0.195210   -0.2904570
+52644.00  -0.100674   0.197402  -0.2908236   -0.100680    0.197410   -0.2908460
+52645.00  -0.103497   0.199315  -0.2913364   -0.103540    0.199310   -0.2913490
+52646.00  -0.105918   0.201164  -0.2920312   -0.105960    0.201290   -0.2920180
+52647.00  -0.108609   0.203326  -0.2928525   -0.108520    0.203380   -0.2928610
+52648.00  -0.111066   0.205508  -0.2937266   -0.111060    0.205470   -0.2937380
+52649.00  -0.113231   0.207881  -0.2946374   -0.113170    0.207880   -0.2946290
+52650.00  -0.115263   0.210338  -0.2955678   -0.115240    0.210360   -0.2955520
+52651.00  -0.117288   0.212631  -0.2964717   -0.117260    0.212610   -0.2964480
+52652.00  -0.118995   0.214760  -0.2972660   -0.119000    0.214730   -0.2972470
+52653.00  -0.120321   0.216851  -0.2979152   -0.120310    0.216890   -0.2979030
+52654.00  -0.121679   0.219146  -0.2984219   -0.121570    0.219120   -0.2984020
+52655.00  -0.122808   0.221634  -0.2987735   -0.122870    0.221530   -0.2987500
+52656.00  -0.124297   0.224033  -0.2990067   -0.124280    0.224060   -0.2989930
+52657.00  -0.126047   0.226509  -0.2992149   -0.125980    0.226530   -0.2992100
+52658.00  -0.127673   0.228811  -0.2994968   -0.127580    0.228790   -0.2994690
+52659.00  -0.128873   0.231030  -0.2999075   -0.128840    0.231010   -0.2998440
+52660.00  -0.129940   0.233478  -0.3004639   -0.129910    0.233420   -0.3004010
+52661.00  -0.131006   0.236356  -0.3011699   -0.130970    0.236350   -0.3011540
+52662.00  -0.132220   0.239582  -0.3019920   -0.132140    0.239610   -0.3020130
+52663.00  -0.133567   0.242395  -0.3028736   -0.133540    0.242440   -0.3028670
+52664.00  -0.135144   0.244806  -0.3037659   -0.135120    0.244810   -0.3037500
+52665.00  -0.136792   0.247042  -0.3045278   -0.136780    0.247020   -0.3045260
+52666.00  -0.138126   0.249381  -0.3050546   -0.138090    0.249450   -0.3050560
+52667.00  -0.138992   0.252107  -0.3053340   -0.138880    0.252210   -0.3053250
+52668.00  -0.139269   0.255088  -0.3054123   -0.139280    0.255170   -0.3054140
+52669.00  -0.139478   0.258219  -0.3054011   -0.139380    0.258240   -0.3053970
+52670.00  -0.139794   0.261292  -0.3053653   -0.139870    0.261290   -0.3053620
+52671.00  -0.141155   0.264059  -0.3053500   -0.141130    0.264050   -0.3053730
+52672.00  -0.142642   0.266788  -0.3054336   -0.142570    0.266750   -0.3054490
+52673.00  -0.144127   0.269650  -0.3056955   -0.144090    0.269670   -0.3056800
+52674.00  -0.145231   0.272399  -0.3061850   -0.145260    0.272440   -0.3061760
+52675.00  -0.146060   0.275320  -0.3068810   -0.146160    0.275280   -0.3068960
+52676.00  -0.147316   0.277939  -0.3076581   -0.147270    0.278000   -0.3076810
+52677.00  -0.148426   0.280393  -0.3084369   -0.148390    0.280430   -0.3084350
+52678.00  -0.149667   0.283189  -0.3091443   -0.149610    0.283160   -0.3091510
+52679.00  -0.151304   0.285945  -0.3097464   -0.151270    0.285920   -0.3097880
+52680.00  -0.152949   0.288612  -0.3102376   -0.152910    0.288570   -0.3102810
+52681.00  -0.154297   0.291302  -0.3106009   -0.154280    0.291370   -0.3106030
+52682.00  -0.155365   0.294094  -0.3108547   -0.155300    0.294100   -0.3108090
+52683.00  -0.155875   0.296851  -0.3110916   -0.155910    0.296780   -0.3110340
+52684.00  -0.156091   0.299473  -0.3113852   -0.156160    0.299500   -0.3113730
+52685.00  -0.156343   0.302128  -0.3117429   -0.156320    0.302110   -0.3117780
+52686.00  -0.156302   0.304583  -0.3121947   -0.156290    0.304550   -0.3122450
+52687.00  -0.155862   0.307063  -0.3128650   -0.155780    0.307060   -0.3128800
+52688.00  -0.155323   0.310072  -0.3137985   -0.155280    0.310030   -0.3137900
+52689.00  -0.154911   0.313488  -0.3149478   -0.154890    0.313550   -0.3149440
+52690.00  -0.154784   0.317584  -0.3161986   -0.154700    0.317550   -0.3161840
+52691.00  -0.155311   0.321366  -0.3174385   -0.155090    0.321380   -0.3174310
+52692.00  -0.155475   0.324475  -0.3185303   -0.155490    0.324470   -0.3185360
+52693.00  -0.155454   0.327396  -0.3193753   -0.155400    0.327390   -0.3193890
+52694.00  -0.155123   0.330443  -0.3199700   -0.155070    0.330430   -0.3199750
+52695.00  -0.154614   0.333493  -0.3203602   -0.154650    0.333430   -0.3203540
+52696.00  -0.154637   0.336386  -0.3206182   -0.154530    0.336370   -0.3206160
+52697.00  -0.154656   0.339306  -0.3208399   -0.154610    0.339280   -0.3208330
+52698.00  -0.154375   0.342141  -0.3210741   -0.154360    0.342110   -0.3210690
+52699.00  -0.153841   0.344649  -0.3213467   -0.153800    0.344630   -0.3213410
+52700.00  -0.153198   0.347240  -0.3217410   -0.153150    0.347190   -0.3217350
+52701.00  -0.152880   0.350202  -0.3222894   -0.152810    0.350190   -0.3222940
+52702.00  -0.153092   0.353080  -0.3229464   -0.153040    0.353130   -0.3229420
+52703.00  -0.153422   0.355842  -0.3236106   -0.153370    0.355830   -0.3236090
+52704.00  -0.153763   0.358316  -0.3242961   -0.153700    0.358310   -0.3242970
+52705.00  -0.154354   0.360787  -0.3250005   -0.154090    0.360750   -0.3249950
+52706.00  -0.154534   0.363477  -0.3256463   -0.154490    0.363470   -0.3256600
+52707.00  -0.154768   0.366339  -0.3262172   -0.154690    0.366290   -0.3262470
+52708.00  -0.154911   0.369337  -0.3267117   -0.154860    0.369300   -0.3267360
+52709.00  -0.155587   0.372368  -0.3271255   -0.155520    0.372380   -0.3271240
+52710.00  -0.156437   0.375474  -0.3274535   -0.156400    0.375480   -0.3274420
+52711.00  -0.157026   0.378713  -0.3277792   -0.157030    0.378590   -0.3277560
+52712.00  -0.157691   0.381330  -0.3281342   -0.157290    0.381370   -0.3281250
+52713.00  -0.157076   0.384012  -0.3286353   -0.157110    0.384010   -0.3286480
+52714.00  -0.156943   0.386870  -0.3293660   -0.156910    0.386880   -0.3293890
+52715.00  -0.156743   0.389761  -0.3303950   -0.156650    0.389760   -0.3304080
+52716.00  -0.155936   0.392624  -0.3317189   -0.155950    0.392630   -0.3317120
+52717.00  -0.154945   0.395674  -0.3332271   -0.154890    0.395810   -0.3332170
+52718.00  -0.153875   0.399566  -0.3347675   -0.153840    0.399600   -0.3347600
+52719.00  -0.153268   0.403517  -0.3361673   -0.153080    0.403390   -0.3361610
+52720.00  -0.152322   0.406664  -0.3373037   -0.152280    0.406640   -0.3373110
+52721.00  -0.151525   0.409589  -0.3381325   -0.151440    0.409600   -0.3381530
+52722.00  -0.150576   0.412494  -0.3386755   -0.150480    0.412410   -0.3386950
+52723.00  -0.148982   0.415439  -0.3390145   -0.149060    0.415390   -0.3390110
+52724.00  -0.147578   0.418309  -0.3392556   -0.147490    0.418350   -0.3392450
+52725.00  -0.145779   0.421212  -0.3395425   -0.145670    0.421160   -0.3395480
+52726.00  -0.143452   0.424036  -0.3399480   -0.143350    0.424030   -0.3399430
+52727.00  -0.140613   0.426885  -0.3404906   -0.140570    0.426870   -0.3404850
+52728.00  -0.137880   0.429885  -0.3411865   -0.137770    0.429840   -0.3412060
+52729.00  -0.135448   0.432832  -0.3420147   -0.135380    0.432830   -0.3420440
+52730.00  -0.133253   0.435574  -0.3429313   -0.133250    0.435620   -0.3429290
+52731.00  -0.131337   0.438596  -0.3438876   -0.131170    0.438590   -0.3438740
+52732.00  -0.129096   0.441736  -0.3448712   -0.129050    0.441740   -0.3448740
+52733.00  -0.127130   0.444678  -0.3458013   -0.126950    0.444670   -0.3457940
+52734.00  -0.124629   0.447542  -0.3466152   -0.124580    0.447540   -0.3466170
+52735.00  -0.122177   0.450759  -0.3473352   -0.122080    0.450760   -0.3473310
+52736.00  -0.119826   0.454061  -0.3479283   -0.119780    0.454050   -0.3479260
+52737.00  -0.117581   0.456994  -0.3483759   -0.117590    0.456990   -0.3483700
+52738.00  -0.116238   0.459671  -0.3487087   -0.115960    0.459710   -0.3487010
+52739.00  -0.114690   0.462343  -0.3490285   -0.114680    0.462350   -0.3490260
+52740.00  -0.113539   0.464834  -0.3494229   -0.113230    0.464850   -0.3494180
+52741.00  -0.111408   0.467511  -0.3499690   -0.111410    0.467490   -0.3499570
+52742.00  -0.109399   0.470304  -0.3507694   -0.109290    0.470290   -0.3507470
+52743.00  -0.107268   0.472883  -0.3518708   -0.107170    0.472880   -0.3518560
+52744.00  -0.105224   0.475253  -0.3532336   -0.105260    0.475280   -0.3532260
+52745.00  -0.103976   0.477415  -0.3547178   -0.103790    0.477410   -0.3547140
+52746.00  -0.102241   0.479238  -0.3561391   -0.102200    0.479230   -0.3561370
+52747.00  -0.100347   0.481207  -0.3573084   -0.100290    0.481160   -0.3572750
+52748.00  -0.098110   0.483411  -0.3581655   -0.098020    0.483390   -0.3581420
+52749.00  -0.095579   0.485678  -0.3586492   -0.095490    0.485660   -0.3586890
+52750.00  -0.093129   0.487711  -0.3588349   -0.093040    0.487740   -0.3589020
+52751.00  -0.090755   0.489518  -0.3588929   -0.090700    0.489620   -0.3588960
+52752.00  -0.088601   0.491625  -0.3589248   -0.088490    0.491700   -0.3588860
+52753.00  -0.086073   0.493677  -0.3590416   -0.085900    0.493740   -0.3590440
+52754.00  -0.082835   0.495853  -0.3593016   -0.082770    0.495770   -0.3592960
+52755.00  -0.080055   0.497996  -0.3596948   -0.079990    0.497960   -0.3596890
+52756.00  -0.077683   0.500185  -0.3602410   -0.077590    0.500160   -0.3602360
+52757.00  -0.075264   0.502396  -0.3609113   -0.075190    0.502440   -0.3609080
+52758.00  -0.072945   0.504336  -0.3616574   -0.072840    0.504420   -0.3616510
+52759.00  -0.070452   0.506168  -0.3624152   -0.070270    0.506180   -0.3624080
+52760.00  -0.066884   0.508018  -0.3631068   -0.066850    0.508020   -0.3631080
+52761.00  -0.063134   0.509849  -0.3636406   -0.063020    0.509870   -0.3636450
+52762.00  -0.059460   0.511574  -0.3639858   -0.059380    0.511610   -0.3639710
+52763.00  -0.056188   0.513428  -0.3641403   -0.056110    0.513430   -0.3640950
+52764.00  -0.053251   0.515445  -0.3641271   -0.053140    0.515420   -0.3640860
+52765.00  -0.050102   0.517481  -0.3640312   -0.050100    0.517520   -0.3640240
+52766.00  -0.047177   0.519684  -0.3639292   -0.047150    0.519710   -0.3639140
+52767.00  -0.044759   0.521707  -0.3638449   -0.044670    0.521610   -0.3638350
+52768.00  -0.042316   0.523206  -0.3639183   -0.042140    0.523330   -0.3639110
+52769.00  -0.039744   0.525015  -0.3642129   -0.039680    0.525050   -0.3642000
+52770.00  -0.037767   0.526629  -0.3647435   -0.037690    0.526600   -0.3647260
+52771.00  -0.036128   0.527945  -0.3655317   -0.036010    0.527970   -0.3655100
+52772.00  -0.034478   0.529264  -0.3665666   -0.034400    0.529290   -0.3665540
+52773.00  -0.032655   0.530583  -0.3677702   -0.032560    0.530530   -0.3677770
+52774.00  -0.030523   0.531887  -0.3689547   -0.030430    0.531850   -0.3689700
+52775.00  -0.028293   0.533225  -0.3699223   -0.028250    0.533180   -0.3699180
+52776.00  -0.025981   0.534353  -0.3705531   -0.025890    0.534300   -0.3705330
+52777.00  -0.023693   0.535468  -0.3709000   -0.023560    0.535470   -0.3708860
+52778.00  -0.021358   0.536500  -0.3710701   -0.021250    0.536550   -0.3710520
+52779.00  -0.018620   0.537522  -0.3712217   -0.018500    0.537530   -0.3712130
+52780.00  -0.015410   0.538602  -0.3714380   -0.015430    0.538610   -0.3714480
+52781.00  -0.012603   0.539688  -0.3717551   -0.012490    0.539640   -0.3717310
+52782.00  -0.009866   0.540575  -0.3722105   -0.009800    0.540440   -0.3722000
+52783.00  -0.007004   0.540972  -0.3727809   -0.006960    0.540960   -0.3727690
+52784.00  -0.004106   0.541211  -0.3734260   -0.004030    0.541340   -0.3733950
+52785.00  -0.001056   0.541528  -0.3740728   -0.000940    0.541610   -0.3740370
+52786.00   0.002298   0.541977  -0.3746654    0.002370    0.541990   -0.3746410
+52787.00   0.005837   0.542598  -0.3751705    0.005880    0.542640   -0.3751620
+52788.00   0.009260   0.543591  -0.3755531    0.009390    0.543690   -0.3755520
+52789.00   0.012429   0.544507  -0.3757844    0.012550    0.544580   -0.3757760
+52790.00   0.015576   0.545546  -0.3758359    0.015640    0.545500   -0.3758550
+52791.00   0.018416   0.546437  -0.3756855    0.018520    0.546410   -0.3757030
+52792.00   0.021231   0.547100  -0.3753793    0.021340    0.546990   -0.3753690
+52793.00   0.024311   0.547652  -0.3749825    0.024380    0.547540   -0.3749710
+52794.00   0.027719   0.547855  -0.3745271    0.027810    0.547850   -0.3745520
+52795.00   0.031430   0.547882  -0.3740730    0.031540    0.547890   -0.3740740
+52796.00   0.034917   0.547818  -0.3737576    0.035020    0.547910   -0.3737490
+52797.00   0.038130   0.547817  -0.3736737    0.038190    0.547810   -0.3736780
+52798.00   0.041333   0.547855  -0.3738447    0.041410    0.547810   -0.3738780
+52799.00   0.044736   0.547922  -0.3742503    0.044810    0.547930   -0.3742770
+52800.00   0.048281   0.548027  -0.3747833    0.048330    0.548050   -0.3747790
+52801.00   0.051673   0.548061  -0.3752832    0.051790    0.548060   -0.3752700
+52802.00   0.055139   0.547756  -0.3756082    0.055260    0.547750   -0.3756120
+52803.00   0.058556   0.547201  -0.3756412    0.058730    0.547230   -0.3756430
+52804.00   0.062094   0.546689  -0.3753452    0.062170    0.546630   -0.3753230
+52805.00   0.065802   0.546171  -0.3747957    0.065870    0.546100   -0.3747700
+52806.00   0.069733   0.545588  -0.3741172    0.069830    0.545570   -0.3741000
+52807.00   0.074052   0.545079  -0.3734464    0.074140    0.545040   -0.3734360
+52808.00   0.078547   0.544862  -0.3728845    0.078630    0.544840   -0.3728820
+52809.00   0.082892   0.544756  -0.3724844    0.083140    0.544680   -0.3724930
+52810.00   0.087700   0.544532  -0.3722530    0.087770    0.544520   -0.3722550
+52811.00   0.091956   0.544384  -0.3721348    0.092070    0.544420   -0.3721070
+52812.00   0.095888   0.544085  -0.3720627    0.095980    0.544080   -0.3720050
+52813.00   0.099772   0.543616  -0.3719772    0.099880    0.543620   -0.3719230
+52814.00   0.103554   0.542996  -0.3718238    0.103640    0.543060   -0.3718090
+52815.00   0.107221   0.542491  -0.3715540    0.107340    0.542480   -0.3715590
+52816.00   0.110928   0.542076  -0.3711389    0.111030    0.542050   -0.3711060
+52817.00   0.114722   0.541683  -0.3705786    0.114840    0.541520   -0.3705660
+52818.00   0.118619   0.541064  -0.3698746    0.118730    0.540990   -0.3698540
+52819.00   0.122623   0.540447  -0.3690496    0.122740    0.540420   -0.3690180
+52820.00   0.126689   0.539883  -0.3681479    0.126790    0.539860   -0.3681090
+52821.00   0.130468   0.539313  -0.3672420    0.130560    0.539290   -0.3672270
+52822.00   0.133821   0.538582  -0.3664106    0.133980    0.538570   -0.3664210
+52823.00   0.136813   0.537563  -0.3657010    0.137040    0.537500   -0.3656920
+52824.00   0.139880   0.535923  -0.3651475    0.139980    0.535890   -0.3651290
+52825.00   0.143073   0.534157  -0.3647861    0.143200    0.534100   -0.3647340
+52826.00   0.146403   0.532623  -0.3645739    0.146510    0.532570   -0.3644890
+52827.00   0.149616   0.531187  -0.3644331    0.149680    0.531190   -0.3643570
+52828.00   0.153014   0.529717  -0.3642754    0.153090    0.529730   -0.3642560
+52829.00   0.156652   0.528214  -0.3640177    0.156730    0.528180   -0.3640300
+52830.00   0.160400   0.526692  -0.3635461    0.160450    0.526650   -0.3635320
+52831.00   0.163893   0.525208  -0.3628283    0.164060    0.525270   -0.3628150
+52832.00   0.167447   0.523922  -0.3619299    0.167540    0.523940   -0.3619300
+52833.00   0.170540   0.522624  -0.3609656    0.170640    0.522650   -0.3609700
+52834.00   0.173119   0.521200  -0.3600377    0.173240    0.521190   -0.3600350
+52835.00   0.175615   0.519726  -0.3592355    0.175690    0.519660   -0.3592290
+52836.00   0.178216   0.518207  -0.3586320    0.178280    0.518100   -0.3586240
+52837.00   0.180961   0.516617  -0.3582506    0.180970    0.516510   -0.3582320
+52838.00   0.183442   0.514713  -0.3580347    0.183560    0.514700   -0.3580200
+52839.00   0.186304   0.512678  -0.3579064    0.186360    0.512610   -0.3579100
+52840.00   0.189291   0.510645  -0.3577985    0.189360    0.510580   -0.3577950
+52841.00   0.191970   0.508531  -0.3576469    0.192020    0.508560   -0.3576290
+52842.00   0.194308   0.506211  -0.3574124    0.194430    0.506240   -0.3573990
+52843.00   0.197124   0.503868  -0.3570731    0.197180    0.503790   -0.3570760
+52844.00   0.199921   0.501622  -0.3566195    0.200020    0.501600   -0.3566200
+52845.00   0.202476   0.499419  -0.3560571    0.202520    0.499500   -0.3560510
+52846.00   0.204685   0.497220  -0.3554030    0.204770    0.497210   -0.3554020
+52847.00   0.206809   0.494817  -0.3547428    0.206880    0.494770   -0.3547510
+52848.00   0.208980   0.492100  -0.3541361    0.209050    0.492120   -0.3541420
+52849.00   0.211303   0.489142  -0.3536200    0.211370    0.489240   -0.3536150
+52850.00   0.213815   0.486413  -0.3532271    0.213900    0.486430   -0.3532260
+52851.00   0.216500   0.483887  -0.3530459    0.216580    0.483900   -0.3530440
+52852.00   0.219112   0.481538  -0.3531033    0.219220    0.481570   -0.3530920
+52853.00   0.221386   0.479513  -0.3533306    0.221430    0.479470   -0.3533400
+52854.00   0.223071   0.477318  -0.3536689    0.223150    0.477200   -0.3537200
+52855.00   0.224748   0.474861  -0.3540496    0.224830    0.474730   -0.3540840
+52856.00   0.226443   0.472367  -0.3543334    0.226500    0.472310   -0.3543240
+52857.00   0.228150   0.469614  -0.3543726    0.228230    0.469600   -0.3543660
+52858.00   0.230141   0.466612  -0.3541745    0.230230    0.466580   -0.3541780
+52859.00   0.232124   0.463704  -0.3537567    0.232240    0.463660   -0.3537490
+52860.00   0.234060   0.461100  -0.3531909    0.234120    0.461030   -0.3531860
+52861.00   0.235882   0.458865  -0.3526009    0.235980    0.458830   -0.3525970
+52862.00   0.237707   0.456702  -0.3521001    0.237790    0.456760   -0.3520940
+52863.00   0.239487   0.454309  -0.3517812    0.239600    0.454460   -0.3517730
+52864.00   0.241314   0.452088  -0.3516894    0.241370    0.452080   -0.3516780
+52865.00   0.243093   0.449784  -0.3517784    0.243160    0.449760   -0.3517770
+52866.00   0.244570   0.447324  -0.3520012    0.244710    0.447420   -0.3519870
+52867.00   0.246011   0.444752  -0.3523064    0.246050    0.444730   -0.3523300
+52868.00   0.247532   0.441804  -0.3526161    0.247620    0.441710   -0.3526850
+52869.00   0.249124   0.438677  -0.3528512    0.249190    0.438650   -0.3529040
+52870.00   0.250680   0.435417  -0.3529173    0.250720    0.435430   -0.3529140
+52871.00   0.252254   0.432462  -0.3527417    0.252330    0.432380   -0.3527250
+52872.00   0.253774   0.429753  -0.3523732    0.253840    0.429680   -0.3523710
+52873.00   0.254928   0.427262  -0.3518548    0.255050    0.427260   -0.3518440
+52874.00   0.255947   0.424872  -0.3512339    0.255980    0.424890   -0.3512340
+52875.00   0.256958   0.422061  -0.3505935    0.257020    0.422020   -0.3506380
+52876.00   0.258249   0.418880  -0.3499998    0.258310    0.418840   -0.3500360
+52877.00   0.259210   0.415542  -0.3495442    0.259350    0.415660   -0.3495410
+52878.00   0.260146   0.412296  -0.3493055    0.260160    0.412320   -0.3493060
+52879.00   0.261170   0.409038  -0.3494278    0.261270    0.409070   -0.3493980
+52880.00   0.262134   0.406067  -0.3498745    0.262410    0.406130   -0.3498590
+52881.00   0.263337   0.403308  -0.3505380    0.263420    0.403290   -0.3505460
+52882.00   0.264430   0.400496  -0.3512890    0.264490    0.400450   -0.3513040
+52883.00   0.265244   0.397526  -0.3519601    0.265340    0.397440   -0.3519670
+52884.00   0.265514   0.394414  -0.3524292    0.265610    0.394360   -0.3524220
+52885.00   0.265529   0.391195  -0.3526473    0.265540    0.391190   -0.3526340
+52886.00   0.265386   0.387938  -0.3525985    0.265490    0.387910   -0.3525990
+52887.00   0.265113   0.384441  -0.3523713    0.265320    0.384430   -0.3523630
+52888.00   0.265182   0.380910  -0.3520822    0.265190    0.380840   -0.3520800
+52889.00   0.265053   0.377505  -0.3517877    0.265120    0.377410   -0.3518070
+52890.00   0.264911   0.374278  -0.3515887    0.264960    0.374190   -0.3515900
+52891.00   0.264699   0.371156  -0.3515693    0.264780    0.371110   -0.3515600
+52892.00   0.264511   0.367894  -0.3517499    0.264640    0.367820   -0.3517590
+52893.00   0.264605   0.364586  -0.3520732    0.264740    0.364530   -0.3520710
+52894.00   0.264519   0.361280  -0.3524733    0.264560    0.361260   -0.3524620
+52895.00   0.264233   0.357987  -0.3528459    0.264300    0.357910   -0.3528470
+52896.00   0.264223   0.354809  -0.3531448    0.264280    0.354740   -0.3531440
+52897.00   0.264230   0.351772  -0.3533557    0.264320    0.351740   -0.3533550
+52898.00   0.264141   0.348778  -0.3534664    0.264230    0.348800   -0.3534580
+52899.00   0.264033   0.345932  -0.3534705    0.264090    0.345900   -0.3534420
+52900.00   0.264004   0.342995  -0.3533594    0.264010    0.342920   -0.3533250
+52901.00   0.263698   0.339808  -0.3531016    0.263760    0.339770   -0.3530900
+52902.00   0.263057   0.336422  -0.3528097    0.263100    0.336400   -0.3528150
+52903.00   0.262535   0.332948  -0.3525464    0.262570    0.332800   -0.3525610
+52904.00   0.262588   0.329728  -0.3524014    0.262610    0.329590   -0.3523970
+52905.00   0.262482   0.326856  -0.3524815    0.262550    0.326880   -0.3524690
+52906.00   0.261882   0.324086  -0.3528272    0.261930    0.324050   -0.3528410
+52907.00   0.260917   0.320821  -0.3534321    0.260980    0.320860   -0.3534380
+52908.00   0.260061   0.317273  -0.3542544    0.260120    0.317310   -0.3542520
+52909.00   0.259523   0.314020  -0.3551847    0.259650    0.313970   -0.3551960
+52910.00   0.259357   0.311099  -0.3560733    0.259430    0.311050   -0.3560970
+52911.00   0.259185   0.308483  -0.3567894    0.259270    0.308390   -0.3568040
+52912.00   0.259205   0.306213  -0.3572758    0.259180    0.306160   -0.3572700
+52913.00   0.258441   0.304032  -0.3575077    0.258530    0.304000   -0.3575060
+52914.00   0.257371   0.301431  -0.3575564    0.257380    0.301390   -0.3575580
+52915.00   0.256285   0.298632  -0.3575382    0.256250    0.298690   -0.3575300
+52916.00   0.254920   0.296130  -0.3575692    0.254990    0.296150   -0.3575800
+52917.00   0.253564   0.293447  -0.3577245    0.253630    0.293450   -0.3577210
+52918.00   0.252216   0.290458  -0.3580633    0.252280    0.290420   -0.3580400
+52919.00   0.250917   0.287406  -0.3586134    0.250960    0.287370   -0.3586000
+52920.00   0.249549   0.284675  -0.3593206    0.249600    0.284630   -0.3593330
+52921.00   0.248047   0.282076  -0.3600671    0.248110    0.282020   -0.3600770
+52922.00   0.246394   0.279262  -0.3607698    0.246430    0.279220   -0.3607580
+52923.00   0.244461   0.276479  -0.3614181    0.244420    0.276420   -0.3614210
+52924.00   0.242041   0.273675  -0.3619580    0.242100    0.273640   -0.3619840
+52925.00   0.239767   0.270716  -0.3623574    0.239820    0.270690   -0.3623750
+52926.00   0.237786   0.267467  -0.3626070    0.237790    0.267490   -0.3625980
+52927.00   0.235754   0.264252  -0.3627139    0.235850    0.264180   -0.3626930
+52928.00   0.233833   0.261075  -0.3626985    0.233880    0.261050   -0.3626940
+52929.00   0.231713   0.257917  -0.3626126    0.231840    0.257960   -0.3626070
+52930.00   0.229791   0.255061  -0.3625398    0.229830    0.254970   -0.3625330
+52931.00   0.227912   0.252528  -0.3625865    0.227960    0.252450   -0.3626020
+52932.00   0.225985   0.250041  -0.3628482    0.226020    0.250040   -0.3628760
+52933.00   0.224045   0.247363  -0.3633946    0.224070    0.247350   -0.3633930
+52934.00   0.221840   0.244727  -0.3642337    0.221970    0.244690   -0.3641960
+52935.00   0.220252   0.242207  -0.3653312    0.220270    0.242220   -0.3652860
+52936.00   0.219375   0.239955  -0.3666165    0.219290    0.239920   -0.3665910
+52937.00   0.218588   0.237830  -0.3679282    0.218640    0.237720   -0.3679320
+52938.00   0.218074   0.235800  -0.3690879    0.218130    0.235680   -0.3690970
+52939.00   0.217044   0.233764  -0.3699470    0.217130    0.233710   -0.3699450
+52940.00   0.215526   0.231571  -0.3704387    0.215490    0.231520   -0.3704240
+52941.00   0.213727   0.229245  -0.3705972    0.213800    0.229150   -0.3705920
+52942.00   0.212410   0.226990  -0.3705550    0.212460    0.226900   -0.3705570
+52943.00   0.210964   0.225015  -0.3704466    0.211060    0.225010   -0.3704340
+52944.00   0.209202   0.223347  -0.3703764    0.209260    0.223310   -0.3703860
+52945.00   0.207195   0.221630  -0.3704385    0.207240    0.221550   -0.3704470
+52946.00   0.205026   0.219554  -0.3706830    0.205080    0.219480   -0.3706680
+52947.00   0.202683   0.217024  -0.3711079    0.202740    0.216980   -0.3710900
+52948.00   0.200310   0.214164  -0.3716585    0.200360    0.214070   -0.3716580
+52949.00   0.198074   0.211221  -0.3722295    0.198250    0.211100   -0.3722220
+52950.00   0.196251   0.208259  -0.3727509    0.196320    0.208230   -0.3727430
+52951.00   0.194565   0.205715  -0.3731800    0.194580    0.205620   -0.3731760
+52952.00   0.192663   0.203465  -0.3735121    0.192750    0.203370   -0.3735510
+52953.00   0.190187   0.201115  -0.3737231    0.190250    0.201140   -0.3737820
+52954.00   0.187195   0.198509  -0.3738188    0.187240    0.198490   -0.3738110
+52955.00   0.184474   0.196121  -0.3737553    0.184520    0.195980   -0.3737240
+52956.00   0.182107   0.193777  -0.3736979    0.182190    0.193700   -0.3736830
+52957.00   0.179905   0.191388  -0.3737004    0.179870    0.191370   -0.3736890
+52958.00   0.177366   0.189111  -0.3737575    0.177470    0.189040   -0.3737660
+52959.00   0.175135   0.187130  -0.3739175    0.175190    0.187030   -0.3739370
+52960.00   0.172807   0.185468  -0.3742697    0.172860    0.185420   -0.3742740
+52961.00   0.170303   0.183784  -0.3748706    0.170180    0.183740   -0.3748600
+52962.00   0.167240   0.181979  -0.3756862    0.167340    0.181890   -0.3756920
+52963.00   0.164407   0.180379  -0.3766273    0.164430    0.180360   -0.3766400
+52964.00   0.161879   0.179080  -0.3776699    0.161850    0.179120   -0.3776600
+52965.00   0.159310   0.178390  -0.3787721    0.159410    0.178310   -0.3787760
+52966.00   0.156601   0.177787  -0.3797053    0.156660    0.177700   -0.3797530
+52967.00   0.153407   0.176857  -0.3803525    0.153490    0.176770   -0.3803940
+52968.00   0.149829   0.175610  -0.3807045    0.149710    0.175550   -0.3806940
+52969.00   0.145164   0.174214  -0.3807790    0.145320    0.174190   -0.3807670
+52970.00   0.141260   0.172979  -0.3807209    0.141260    0.172870   -0.3807190
+52971.00   0.137855   0.171862  -0.3806866    0.137930    0.171760   -0.3807010
+52972.00   0.134328   0.170603  -0.3807901    0.134400    0.170550   -0.3808080
+52973.00   0.130325   0.169151  -0.3810508    0.130400    0.169040   -0.3810580
+52974.00   0.126420   0.167832  -0.3814428    0.126440    0.167710   -0.3814390
+52975.00   0.123266   0.166673  -0.3819390    0.123160    0.166610   -0.3819270
+52976.00   0.120076   0.165475  -0.3824741    0.120170    0.165390   -0.3824720
+52977.00   0.116995   0.164471  -0.3829730    0.117050    0.164370   -0.3829730
+52978.00   0.113973   0.163778  -0.3833573    0.114130    0.163830   -0.3833480
+52979.00   0.111334   0.163491  -0.3836394    0.111400    0.163450   -0.3836440
+52980.00   0.108467   0.163096  -0.3838023    0.108520    0.162960   -0.3838250
+52981.00   0.105420   0.162534  -0.3837965    0.105460    0.162450   -0.3837940
+52982.00   0.102488   0.162010  -0.3835799    0.102520    0.162010   -0.3835510
+52983.00   0.099885   0.161527  -0.3832095    0.099840    0.161520   -0.3832000
+52984.00   0.096725   0.161011  -0.3828210    0.096870    0.160960   -0.3828340
+52985.00   0.093248   0.160277  -0.3824442    0.093360    0.160300   -0.3824450
+52986.00   0.089735   0.159516  -0.3821568    0.089740    0.159450   -0.3821680
+52987.00   0.086412   0.158859  -0.3819860    0.086450    0.158710   -0.3819980
+52988.00   0.083456   0.158562  -0.3820095    0.083500    0.158510   -0.3820050
+52989.00   0.080536   0.158347  -0.3822637    0.080610    0.158360   -0.3822560
+52990.00   0.077519   0.158153  -0.3827665    0.077620    0.158050   -0.3827510
+52991.00   0.074448   0.157708  -0.3834666    0.074480    0.157650   -0.3834390
+52992.00   0.071389   0.157209  -0.3842406    0.071480    0.157210   -0.3842270
+52993.00   0.068871   0.156887  -0.3850126    0.068890    0.156860   -0.3850240
+52994.00   0.066300   0.156452  -0.3856916    0.066350    0.156400   -0.3857350
+52995.00   0.063454   0.155925  -0.3861420    0.063520    0.155850   -0.3861900
+52996.00   0.060465   0.155499  -0.3863182    0.060390    0.155410   -0.3863100
+52997.00   0.056583   0.155114  -0.3863249    0.056690    0.155070   -0.3862360
+52998.00   0.052600   0.154776  -0.3863931    0.052620    0.154710   -0.3862160
+52999.00   0.048915   0.154521  -0.3865721    0.048950    0.154440   -0.3863760
+53000.00   0.045817   0.154535  -0.3868940    0.045870    0.154430   -0.3867280
+53001.00   0.042887   0.154743  -0.3873570    0.042940    0.154660   -0.3872450
+53002.00   0.039838   0.154765  -0.3879178    0.039910    0.154710   -0.3878690
+53003.00   0.037041   0.154460  -0.3885253    0.037030    0.154430   -0.3885140
+53004.00   0.034030   0.154152  -0.3891069    0.034120    0.154100   -0.3890920
+53005.00   0.031244   0.153837  -0.3896242    0.031250    0.153770   -0.3895920
+53006.00   0.028844   0.153666  -0.3900898    0.028870    0.153550   -0.3900740
+53007.00   0.026642   0.153845  -0.3904388    0.026700    0.153740   -0.3904550
+53008.00   0.024196   0.154296  -0.3906064    0.024260    0.154230   -0.3906300
+53009.00   0.021488   0.154846  -0.3906172    0.021590    0.154800   -0.3906200
+53010.00   0.018791   0.155474  -0.3905345    0.018790    0.155440   -0.3905240
+53011.00   0.015852   0.156213  -0.3904555    0.015960    0.156150   -0.3904520
+53012.00   0.012904   0.156919  -0.3904750    0.012990    0.156850   -0.3904660
+53013.00   0.010078   0.157347  -0.3906236    0.010150    0.157360   -0.3906230
+53014.00   0.007583   0.157668  -0.3909863    0.007710    0.157630   -0.3909980
+53015.00   0.005354   0.157925  -0.3916007    0.005380    0.157840   -0.3916020
+53016.00   0.003033   0.158350  -0.3924755    0.003030    0.158320   -0.3924550
+53017.00   0.001086   0.159029  -0.3935831    0.001150    0.159010   -0.3935690
+53018.00  -0.001169   0.160079  -0.3948550   -0.000940    0.159990   -0.3948590
+53019.00  -0.003297   0.161392  -0.3961229   -0.003280    0.161360   -0.3961320
+53020.00  -0.005379   0.162631  -0.3972759   -0.005390    0.162610   -0.3972730
+53021.00  -0.007618   0.163769  -0.3982373   -0.007540    0.163700   -0.3982610
+53022.00  -0.010220   0.165080  -0.3989327   -0.010170    0.165030   -0.3989770
+53023.00  -0.013234   0.166344  -0.3993909   -0.013220    0.166280   -0.3994140
+53024.00  -0.016200   0.167254  -0.3996555   -0.016180    0.167220   -0.3996580
+53025.00  -0.018669   0.168256  -0.3998536   -0.018640    0.168310   -0.3998410
+53026.00  -0.021135   0.170026  -0.4000824   -0.021090    0.169990   -0.4000790
+53027.00  -0.024176   0.171779  -0.4004461   -0.023830    0.171790   -0.4004350
+53028.00  -0.026293   0.173195  -0.4009626   -0.026220    0.173120   -0.4009750
+53029.00  -0.027930   0.174506  -0.4016320   -0.027880    0.174430   -0.4016610
+53030.00  -0.029166   0.175922  -0.4024375   -0.029110    0.175870   -0.4024540
+53031.00  -0.030225   0.177463  -0.4033134   -0.030220    0.177420   -0.4033020
+53032.00  -0.031671   0.179219  -0.4040843   -0.031610    0.179160   -0.4040940
+53033.00  -0.033515   0.181087  -0.4046773   -0.033490    0.181000   -0.4046910
+53034.00  -0.036000   0.182968  -0.4050564   -0.035950    0.182930   -0.4050420
+53035.00  -0.038965   0.184635  -0.4051777   -0.038950    0.184640   -0.4051900
+53036.00  -0.042053   0.185947  -0.4051274   -0.042020    0.185890   -0.4051460
+53037.00  -0.045042   0.187066  -0.4049571   -0.044930    0.186970   -0.4049600
+53038.00  -0.047761   0.188154  -0.4047153   -0.047970    0.188030   -0.4047120
+53039.00  -0.051257   0.189038  -0.4044378   -0.051200    0.188970   -0.4044510
+53040.00  -0.054189   0.189870  -0.4041928   -0.054160    0.189780   -0.4042020
+53041.00  -0.056733   0.190686  -0.4041270   -0.056640    0.190710   -0.4041170
+53042.00  -0.058825   0.192037  -0.4042345   -0.058780    0.191970   -0.4042390
+53043.00  -0.060688   0.193626  -0.4046462   -0.060610    0.193540   -0.4046350
+53044.00  -0.062592   0.195360  -0.4053054   -0.062540    0.195330   -0.4052940
+53045.00  -0.064874   0.197078  -0.4061337   -0.064880    0.197140   -0.4061210
+53046.00  -0.067757   0.199111  -0.4070526   -0.067650    0.199070   -0.4070350
+53047.00  -0.070767   0.200933  -0.4079696   -0.070720    0.200890   -0.4079620
+53048.00  -0.073855   0.202602  -0.4087687   -0.073760    0.202610   -0.4087570
+53049.00  -0.076809   0.204484  -0.4093587   -0.076740    0.204440   -0.4093720
+53050.00  -0.079498   0.206270  -0.4097087   -0.079460    0.206200   -0.4097500
+53051.00  -0.081567   0.208068  -0.4098775   -0.081510    0.208070   -0.4099010
+53052.00  -0.082877   0.210042  -0.4099673   -0.082870    0.210050   -0.4099550
+53053.00  -0.084374   0.212379  -0.4100716   -0.084210    0.212270   -0.4100770
+53054.00  -0.086622   0.214835  -0.4103309   -0.086570    0.214860   -0.4103380
+53055.00  -0.090064   0.217070  -0.4108241   -0.089840    0.217220   -0.4108150
+53056.00  -0.093068   0.219557  -0.4115674   -0.093010    0.219500   -0.4115850
+53057.00  -0.095704   0.222040  -0.4124818   -0.095640    0.221970   -0.4125160
+53058.00  -0.097959   0.224295  -0.4135315   -0.097910    0.224270   -0.4135320
+53059.00  -0.099798   0.226393  -0.4146100   -0.099810    0.226380   -0.4145990
+53060.00  -0.101355   0.228660  -0.4155830   -0.101260    0.228610   -0.4155980
+53061.00  -0.102509   0.231015  -0.4163774   -0.102480    0.230940   -0.4163790
+53062.00  -0.104300   0.233444  -0.4169791   -0.103900    0.233390   -0.4169680
+53063.00  -0.105932   0.235858  -0.4173906   -0.105970    0.235800   -0.4173890
+53064.00  -0.108401   0.237914  -0.4175409   -0.108330    0.237830   -0.4175520
+53065.00  -0.110501   0.239906  -0.4174892   -0.110480    0.239820   -0.4174860
+53066.00  -0.112161   0.242124  -0.4173477   -0.112280    0.242030   -0.4173340
+53067.00  -0.114044   0.244227  -0.4172256   -0.113870    0.244170   -0.4172170
+53068.00  -0.115346   0.246409  -0.4171978   -0.115450    0.246340   -0.4171940
+53069.00  -0.117613   0.248880  -0.4173544   -0.117240    0.248810   -0.4173440
+53070.00  -0.118972   0.251544  -0.4177290   -0.118920    0.251420   -0.4177250
+53071.00  -0.120333   0.254079  -0.4183482   -0.120260    0.254030   -0.4183150
+53072.00  -0.121611   0.256235  -0.4191872   -0.121520    0.256150   -0.4191520
+53073.00  -0.122119   0.258099  -0.4201285   -0.122270    0.258000   -0.4201170
+53074.00  -0.123051   0.260080  -0.4210229   -0.122910    0.260000   -0.4210240
+53075.00  -0.123777   0.262118  -0.4217468   -0.123690    0.262090   -0.4217560
+53076.00  -0.124455   0.264057  -0.4222153   -0.124390    0.264080   -0.4222000
+53077.00  -0.125205   0.266248  -0.4224569   -0.125150    0.266190   -0.4224630
+53078.00  -0.126024   0.268487  -0.4225151   -0.125960    0.268470   -0.4225910
+53079.00  -0.126916   0.270666  -0.4224659   -0.126830    0.270610   -0.4225390
+53080.00  -0.128146   0.272835  -0.4224683   -0.128020    0.272740   -0.4224570
+53081.00  -0.129176   0.274877  -0.4225792   -0.129130    0.274780   -0.4225720
+53082.00  -0.130041   0.277121  -0.4229180   -0.130030    0.277030   -0.4229130
+53083.00  -0.131319   0.279582  -0.4235105   -0.131010    0.279470   -0.4234930
+53084.00  -0.131686   0.281985  -0.4243745   -0.131650    0.281880   -0.4243930
+53085.00  -0.131870   0.284727  -0.4254624   -0.131780    0.284630   -0.4255200
+53086.00  -0.131970   0.287889  -0.4266041   -0.131850    0.287800   -0.4266280
+53087.00  -0.131763   0.291266  -0.4277337   -0.131810    0.291260   -0.4277180
+53088.00  -0.132120   0.294892  -0.4288225   -0.132020    0.294870   -0.4288330
+53089.00  -0.132879   0.298392  -0.4297907   -0.132830    0.298330   -0.4298080
+53090.00  -0.134157   0.301760  -0.4306100   -0.134010    0.301770   -0.4306060
+53091.00  -0.135580   0.305204  -0.4312566   -0.135510    0.305200   -0.4312590
+53092.00  -0.136937   0.308387  -0.4317381   -0.136880    0.308330   -0.4317360
+53093.00  -0.137964   0.311519  -0.4321208   -0.137840    0.311480   -0.4321140
+53094.00  -0.138655   0.314671  -0.4325104   -0.138680    0.314710   -0.4325020
+53095.00  -0.139535   0.317771  -0.4329854   -0.139440    0.317740   -0.4329880
+53096.00  -0.140236   0.320643  -0.4336280   -0.140150    0.320590   -0.4336250
+53097.00  -0.140804   0.323381  -0.4344862   -0.140650    0.323290   -0.4344790
+53098.00  -0.140861   0.326053  -0.4355582   -0.140730    0.325970   -0.4355490
+53099.00  -0.140991   0.328659  -0.4368895   -0.140850    0.328620   -0.4368240
+53100.00  -0.141196   0.331012  -0.4384145   -0.141110    0.330940   -0.4383520
+53101.00  -0.140720   0.333333  -0.4399631   -0.140720    0.333270   -0.4399620
+53102.00  -0.140158   0.336193  -0.4414204   -0.140070    0.336140   -0.4414210
+53103.00  -0.139965   0.339311  -0.4426320   -0.139870    0.339300   -0.4426250
+53104.00  -0.139741   0.342543  -0.4435244   -0.139720    0.342460   -0.4435230
+53105.00  -0.139228   0.345814  -0.4441924   -0.139160    0.345730   -0.4441910
+53106.00  -0.138782   0.349171  -0.4446457   -0.138700    0.349120   -0.4446890
+53107.00  -0.138908   0.352344  -0.4449674   -0.138820    0.352320   -0.4450120
+53108.00  -0.139092   0.355216  -0.4453570   -0.139050    0.355180   -0.4453520
+53109.00  -0.139133   0.358031  -0.4459426   -0.139020    0.357970   -0.4459340
+53110.00  -0.138562   0.360795  -0.4467443   -0.138500    0.360750   -0.4467570
+53111.00  -0.137666   0.363707  -0.4476965   -0.137280    0.363660   -0.4476920
+53112.00  -0.135942   0.367067  -0.4487434   -0.135880    0.367000   -0.4487340
+53113.00  -0.134730   0.370449  -0.4497836   -0.134630    0.370400   -0.4498170
+53114.00  -0.133542   0.373800  -0.4507463   -0.133420    0.373690   -0.4507790
+53115.00  -0.132548   0.377244  -0.4515631   -0.132720    0.377200   -0.4515530
+53116.00  -0.133007   0.380339  -0.4521528   -0.132860    0.380270   -0.4521440
+53117.00  -0.133116   0.382851  -0.4525157   -0.133030    0.382740   -0.4525130
+53118.00  -0.132946   0.385170  -0.4526433   -0.132900    0.385140   -0.4526290
+53119.00  -0.132752   0.387312  -0.4525541   -0.132680    0.387240   -0.4525500
+53120.00  -0.132086   0.389109  -0.4523613   -0.132000    0.389000   -0.4523700
+53121.00  -0.130584   0.390902  -0.4521309   -0.130460    0.390820   -0.4521400
+53122.00  -0.128369   0.392900  -0.4519811   -0.128460    0.392810   -0.4519700
+53123.00  -0.126762   0.395229  -0.4519888   -0.126640    0.395120   -0.4519830
+53124.00  -0.125075   0.398008  -0.4522232   -0.125000    0.397910   -0.4522110
+53125.00  -0.123708   0.401091  -0.4526894   -0.123340    0.401040   -0.4526730
+53126.00  -0.121495   0.404263  -0.4534530   -0.121380    0.404210   -0.4534520
+53127.00  -0.119760   0.407435  -0.4544589   -0.119660    0.407360   -0.4544520
+53128.00  -0.118501   0.410525  -0.4555827   -0.118390    0.410450   -0.4555700
+53129.00  -0.117058   0.413529  -0.4567177   -0.117060    0.413470   -0.4567090
+53130.00  -0.115921   0.416451  -0.4577698   -0.115790    0.416380   -0.4577810
+53131.00  -0.115001   0.419270  -0.4586211   -0.114930    0.419100   -0.4586060
+53132.00  -0.113993   0.421565  -0.4592557   -0.113920    0.421550   -0.4592340
+53133.00  -0.112544   0.423904  -0.4596957   -0.112480    0.423880   -0.4597010
+53134.00  -0.111161   0.426258  -0.4600231   -0.111080    0.426160   -0.4600310
+53135.00  -0.109683   0.428816  -0.4603919   -0.109620    0.428730   -0.4603710
+53136.00  -0.107972   0.431679  -0.4608945   -0.107920    0.431630   -0.4608740
+53137.00  -0.106068   0.434503  -0.4615534   -0.105990    0.434460   -0.4615630
+53138.00  -0.104092   0.437149  -0.4623758   -0.103920    0.437210   -0.4623610
+53139.00  -0.102428   0.440023  -0.4633390   -0.102230    0.439990   -0.4633250
+53140.00  -0.101278   0.442385  -0.4643792   -0.101230    0.442280   -0.4643800
+53141.00  -0.100665   0.444173  -0.4654198   -0.100590    0.444050   -0.4654470
+53142.00  -0.100219   0.445640  -0.4663589   -0.100120    0.445550   -0.4663810
+53143.00  -0.099649   0.446857  -0.4671628   -0.099630    0.446880   -0.4671500
+53144.00  -0.098890   0.448219  -0.4677645   -0.098880    0.448150   -0.4677680
+53145.00  -0.097898   0.449511  -0.4681790   -0.097620    0.449480   -0.4681660
+53146.00  -0.096338   0.451049  -0.4683682   -0.096230    0.450990   -0.4683520
+53147.00  -0.095219   0.452370  -0.4684372   -0.095120    0.452300   -0.4684340
+53148.00  -0.094280   0.453624  -0.4684003   -0.094210    0.453520   -0.4684300
+53149.00  -0.093254   0.455066  -0.4682929   -0.093170    0.454970   -0.4683400
+53150.00  -0.091741   0.456647  -0.4682759   -0.091820    0.456610   -0.4682760
+53151.00  -0.090950   0.458370  -0.4683178   -0.090800    0.458290   -0.4683110
+53152.00  -0.090152   0.459921  -0.4684932   -0.090100    0.459820   -0.4684840
+53153.00  -0.089523   0.461519  -0.4688633   -0.089290    0.461430   -0.4688530
+53154.00  -0.088312   0.463088  -0.4693417   -0.088260    0.463050   -0.4693440
+53155.00  -0.087161   0.464435  -0.4698880   -0.087050    0.464430   -0.4699190
+53156.00  -0.085650   0.465701  -0.4704246   -0.085550    0.465620   -0.4704730
+53157.00  -0.083868   0.467218  -0.4708810   -0.083740    0.467120   -0.4709090
+53158.00  -0.081799   0.468949  -0.4711648   -0.081900    0.468990   -0.4711550
+53159.00  -0.079985   0.470735  -0.4711849   -0.079860    0.470660   -0.4711760
+53160.00  -0.077621   0.472213  -0.4710285   -0.077750    0.472270   -0.4710280
+53161.00  -0.075857   0.473775  -0.4707305   -0.075560    0.473570   -0.4707200
+53162.00  -0.074535   0.475438  -0.4704523   -0.074410    0.475460   -0.4705960
+53163.00  -0.073383   0.476969  -0.4703119   -0.073240    0.476850   -0.4704280
+53164.00  -0.071795   0.478307  -0.4703860   -0.071780    0.478280   -0.4703790
+53165.00  -0.070038   0.479938  -0.4706078   -0.069820    0.479820   -0.4706000
+53166.00  -0.068404   0.481561  -0.4709961   -0.068360    0.481590   -0.4710010
+53167.00  -0.066910   0.483048  -0.4714383   -0.066580    0.482870   -0.4714330
+53168.00  -0.064939   0.484485  -0.4719111   -0.064920    0.484510   -0.4719020
+53169.00  -0.062810   0.485931  -0.4723223   -0.062670    0.485760   -0.4723950
+53170.00  -0.060442   0.487285  -0.4725840   -0.060290    0.487340   -0.4726390
+53171.00  -0.057892   0.488548  -0.4726368   -0.057860    0.488480   -0.4726280
+53172.00  -0.054948   0.489985  -0.4724290   -0.054740    0.489970   -0.4724330
+53173.00  -0.051504   0.491577  -0.4720163   -0.051580    0.491350   -0.4720090
+53174.00  -0.048345   0.493373  -0.4714789   -0.048070    0.493340   -0.4714770
+53175.00  -0.045157   0.495352  -0.4708713   -0.045250    0.495410   -0.4708420
+53176.00  -0.041914   0.497014  -0.4703102   -0.041700    0.496900   -0.4702260
+53177.00  -0.038593   0.498387  -0.4697864   -0.038620    0.498330   -0.4697110
+53178.00  -0.035032   0.499688  -0.4693800   -0.035040    0.499680   -0.4693630
+53179.00  -0.031929   0.500978  -0.4691390   -0.031760    0.500860   -0.4691500
+53180.00  -0.028606   0.502081  -0.4690429   -0.028540    0.502170   -0.4690560
+53181.00  -0.025186   0.503216  -0.4691310   -0.024900    0.503120   -0.4691160
+53182.00  -0.022010   0.504758  -0.4693568   -0.022050    0.504870   -0.4693900
+53183.00  -0.019196   0.506084  -0.4695599   -0.019040    0.505910   -0.4695710
+53184.00  -0.016274   0.507102  -0.4696971   -0.016150    0.507110   -0.4696610
+53185.00  -0.013099   0.507971  -0.4696824   -0.013090    0.507900   -0.4696690
+53186.00  -0.010373   0.509063  -0.4694842   -0.010180    0.508950   -0.4694860
+53187.00  -0.007578   0.510144  -0.4690131   -0.007570    0.510130   -0.4689890
+53188.00  -0.004596   0.510923  -0.4683883   -0.004540    0.510830   -0.4683790
+53189.00  -0.001923   0.511665  -0.4676178   -0.001750    0.511710   -0.4676050
+53190.00   0.000402   0.512395  -0.4668923    0.000410    0.512320   -0.4671130
+53191.00   0.002674   0.513104  -0.4663701    0.002740    0.512910   -0.4665540
+53192.00   0.005046   0.513765  -0.4660865    0.005140    0.513650   -0.4661270
+53193.00   0.007429   0.514409  -0.4659617    0.007380    0.514200   -0.4659470
+53194.00   0.009614   0.514767  -0.4658791    0.009680    0.514750   -0.4659020
+53195.00   0.012046   0.515222  -0.4657610    0.012350    0.515160   -0.4657470
+53196.00   0.015285   0.516147  -0.4655392    0.015460    0.516110   -0.4655440
+53197.00   0.018237   0.517026  -0.4651595    0.018290    0.517010   -0.4651960
+53198.00   0.021368   0.517832  -0.4646157    0.021370    0.517650   -0.4646290
+53199.00   0.024098   0.518753  -0.4638864    0.024340    0.518770   -0.4638740
+53200.00   0.026259   0.519371  -0.4629584    0.026250    0.519040   -0.4629580
+53201.00   0.028136   0.519908  -0.4619342    0.028290    0.519920   -0.4619040
+53202.00   0.030201   0.520349  -0.4608848    0.030460    0.520300   -0.4608800
+53203.00   0.032695   0.520696  -0.4598724    0.032540    0.520650   -0.4598740
+53204.00   0.035675   0.520838  -0.4589813    0.035970    0.520750   -0.4591510
+53205.00   0.038656   0.520772  -0.4582448    0.038570    0.520680   -0.4583560
+53206.00   0.041511   0.520561  -0.4576830    0.041520    0.520480   -0.4576720
+53207.00   0.043937   0.520226  -0.4573298    0.044090    0.520190   -0.4573140
+53208.00   0.046947   0.519842  -0.4572036    0.046900    0.519710   -0.4572010
+53209.00   0.049938   0.519578  -0.4572236    0.050240    0.519410   -0.4572220
+53210.00   0.053027   0.519249  -0.4573103    0.053030    0.519170   -0.4573080
+53211.00   0.056044   0.519068  -0.4573685    0.056170    0.518960   -0.4575160
+53212.00   0.059036   0.519100  -0.4572955    0.059160    0.518990   -0.4573630
+53213.00   0.061402   0.519126  -0.4570073    0.061620    0.519010   -0.4569860
+53214.00   0.063961   0.518761  -0.4564881    0.064010    0.518560   -0.4565000
+53215.00   0.066425   0.518316  -0.4557866    0.066520    0.518320   -0.4557640
+53216.00   0.068292   0.517610  -0.4550391    0.068510    0.517600   -0.4550260
+53217.00   0.070361   0.516953  -0.4543881    0.070360    0.516990   -0.4544200
+53218.00   0.072781   0.516279  -0.4539370    0.073010    0.516150   -0.4539160
+53219.00   0.075509   0.515709  -0.4537905    0.075510    0.515600   -0.4537780
+53220.00   0.078330   0.515356  -0.4539134    0.078360    0.515260   -0.4539070
+53221.00   0.081069   0.515218  -0.4541631    0.081140    0.515250   -0.4541560
+53222.00   0.083899   0.515111  -0.4544162    0.083910    0.514940   -0.4544350
+53223.00   0.086284   0.514958  -0.4545697    0.086610    0.514910   -0.4545740
+53224.00   0.088898   0.514767  -0.4546248    0.088870    0.514780   -0.4546190
+53225.00   0.091700   0.514255  -0.4545303    0.091820    0.514020   -0.4545550
+53226.00   0.094712   0.513742  -0.4542631    0.094820    0.513720   -0.4543150
+53227.00   0.097298   0.513313  -0.4538315    0.097430    0.513170   -0.4538400
+53228.00   0.099778   0.512915  -0.4532408    0.099730    0.512940   -0.4532180
+53229.00   0.102675   0.512908  -0.4526319    0.102930    0.512670   -0.4526570
+53230.00   0.105710   0.513250  -0.4519755    0.105680    0.513270   -0.4519510
+53231.00   0.108724   0.513582  -0.4514079    0.109030    0.513470   -0.4514100
+53232.00   0.111598   0.513717  -0.4509577    0.111430    0.513730   -0.4509560
+53233.00   0.114518   0.513528  -0.4507020    0.114790    0.513410   -0.4506920
+53234.00   0.117334   0.513095  -0.4506897    0.117320    0.513010   -0.4506820
+53235.00   0.119676   0.512409  -0.4509190    0.119780    0.512270   -0.4509170
+53236.00   0.121944   0.511753  -0.4513356    0.122060    0.511690   -0.4513250
+53237.00   0.124050   0.511179  -0.4518695    0.124400    0.511110   -0.4518640
+53238.00   0.126390   0.510409  -0.4524144    0.126480    0.510290   -0.4523980
+53239.00   0.128311   0.509358  -0.4528330    0.128420    0.509320   -0.4527810
+53240.00   0.130122   0.507982  -0.4530276    0.130190    0.507920   -0.4529650
+53241.00   0.132321   0.506426  -0.4529950    0.132450    0.506280   -0.4529790
+53242.00   0.134332   0.505013  -0.4528267    0.134230    0.504940   -0.4528310
+53243.00   0.136126   0.503770  -0.4524803    0.136480    0.503780   -0.4525190
+53244.00   0.138481   0.502491  -0.4521246    0.138370    0.502450   -0.4521300
+53245.00   0.141011   0.501310  -0.4518504    0.141370    0.501310   -0.4518260
+53246.00   0.143747   0.500062  -0.4518326    0.143630    0.500000   -0.4519000
+53247.00   0.146762   0.498775  -0.4520936    0.146990    0.498580   -0.4519870
+53248.00   0.149575   0.497404  -0.4525890    0.149620    0.497350   -0.4525720
+53249.00   0.152186   0.495783  -0.4531724    0.152260    0.495710   -0.4531700
+53250.00   0.154805   0.494025  -0.4537231    0.154950    0.493790   -0.4537380
+53251.00   0.156751   0.492063  -0.4540991    0.157100    0.492160   -0.4540690
+53252.00   0.159306   0.489843  -0.4542873    0.159290    0.489530   -0.4543050
+53253.00   0.161596   0.487414  -0.4542082    0.161670    0.487550   -0.4542020
+53254.00   0.163658   0.484943  -0.4538241    0.163920    0.484750   -0.4538370
+53255.00   0.165355   0.482747  -0.4532046    0.165290    0.482670   -0.4531710
+53256.00   0.167626   0.480880  -0.4524372    0.167670    0.480770   -0.4524300
+53257.00   0.169427   0.478979  -0.4516332    0.169340    0.478900   -0.4516360
+53258.00   0.171745   0.477178  -0.4509009    0.171940    0.476990   -0.4508980
+53259.00   0.173940   0.475321  -0.4503629    0.173870    0.475360   -0.4503450
+53260.00   0.176082   0.473181  -0.4500928    0.176360    0.473000   -0.4501280
+53261.00   0.178039   0.470868  -0.4501143    0.177940    0.470780   -0.4500520
+53262.00   0.179683   0.468549  -0.4504353    0.179830    0.468440   -0.4504170
+53263.00   0.180952   0.466219  -0.4509843    0.181080    0.466080   -0.4509920
+53264.00   0.182269   0.463884  -0.4516538    0.182210    0.463820   -0.4516470
+53265.00   0.183470   0.461490  -0.4523111    0.183810    0.461380   -0.4522950
+53266.00   0.185044   0.459163  -0.4528708    0.184930    0.459040   -0.4528940
+53267.00   0.186416   0.456911  -0.4531693    0.186690    0.456860   -0.4531750
+53268.00   0.187895   0.454563  -0.4532092    0.187940    0.454470   -0.4531980
+53269.00   0.189810   0.452079  -0.4530455    0.189840    0.452090   -0.4530270
+53270.00   0.191609   0.449970  -0.4527551    0.191680    0.449870   -0.4527690
+53271.00   0.193437   0.448135  -0.4524592    0.193570    0.448000   -0.4524880
+53272.00   0.194889   0.446565  -0.4522814    0.194980    0.446500   -0.4522670
+53273.00   0.195547   0.444853  -0.4523419    0.195610    0.444780   -0.4523490
+53274.00   0.195827   0.442870  -0.4526597    0.196000    0.442720   -0.4526700
+53275.00   0.196285   0.440805  -0.4531943    0.196280    0.440770   -0.4531930
+53276.00   0.197100   0.438643  -0.4539437    0.197200    0.438530   -0.4539310
+53277.00   0.197791   0.436437  -0.4547530    0.197950    0.436360   -0.4547580
+53278.00   0.198126   0.434025  -0.4554428    0.198130    0.433980   -0.4554360
+53279.00   0.198194   0.431641  -0.4559734    0.198510    0.431510   -0.4559600
+53280.00   0.198981   0.429193  -0.4563607    0.199100    0.429100   -0.4563610
+53281.00   0.199852   0.426681  -0.4565717    0.199940    0.426610   -0.4565630
+53282.00   0.200636   0.424209  -0.4566457    0.200730    0.424020   -0.4566420
+53283.00   0.201335   0.421828  -0.4566609    0.201340    0.421850   -0.4566540
+53284.00   0.201842   0.419341  -0.4566663    0.202020    0.419160   -0.4566540
+53285.00   0.202607   0.416861  -0.4567542    0.202660    0.416750   -0.4567840
+53286.00   0.203214   0.414366  -0.4569443    0.203200    0.414300   -0.4569290
+53287.00   0.203452   0.412140  -0.4571469    0.203540    0.411920   -0.4571240
+53288.00   0.203421   0.409992  -0.4575931    0.203630    0.410140   -0.4575590
+53289.00   0.203230   0.407653  -0.4582463    0.203200    0.407350   -0.4582150
+53290.00   0.203306   0.405183  -0.4591080    0.203500    0.405210   -0.4590980
+53291.00   0.203570   0.402676  -0.4601640    0.203520    0.402510   -0.4601650
+53292.00   0.203797   0.399898  -0.4612971    0.203970    0.399850   -0.4612710
+53293.00   0.204353   0.397057  -0.4623647    0.204570    0.396910   -0.4623530
+53294.00   0.205297   0.394763  -0.4633118    0.205350    0.394800   -0.4633100
+53295.00   0.205760   0.392592  -0.4639139    0.205870    0.392450   -0.4639360
+53296.00   0.205980   0.390523  -0.4641872    0.206030    0.390350   -0.4641390
+53297.00   0.205961   0.388589  -0.4642472    0.206130    0.388570   -0.4642380
+53298.00   0.205903   0.386513  -0.4642229    0.205820    0.386210   -0.4642030
+53299.00   0.205991   0.384516  -0.4642770    0.206220    0.384560   -0.4642620
+53300.00   0.205965   0.382563  -0.4645168    0.205990    0.382410   -0.4645050
+53301.00   0.205914   0.380751  -0.4649778    0.206050    0.380650   -0.4649800
+53302.00   0.205468   0.378916  -0.4656335    0.205590    0.378870   -0.4656320
+53303.00   0.205089   0.376842  -0.4664432    0.205090    0.376680   -0.4664280
+53304.00   0.205365   0.374567  -0.4673313    0.205460    0.374570   -0.4673210
+53305.00   0.205862   0.372441  -0.4682317    0.205960    0.372360   -0.4682280
+53306.00   0.206688   0.370131  -0.4690505    0.206610    0.370000   -0.4690430
+53307.00   0.207148   0.367884  -0.4697064    0.207220    0.367830   -0.4696950
+53308.00   0.207181   0.365758  -0.4701190    0.207370    0.365660   -0.4701200
+53309.00   0.207011   0.363608  -0.4702980    0.207040    0.363600   -0.4702780
+53310.00   0.207338   0.361428  -0.4703278    0.207210    0.361180   -0.4703530
+53311.00   0.208128   0.359183  -0.4703004    0.208320    0.359280   -0.4702890
+53312.00   0.208200   0.357165  -0.4702755    0.208080    0.356940   -0.4702790
+53313.00   0.208048   0.354846  -0.4703089    0.208280    0.354810   -0.4702980
+53314.00   0.207819   0.352108  -0.4704739    0.207730    0.352090   -0.4704670
+53315.00   0.207806   0.349429  -0.4708618    0.207990    0.349330   -0.4708600
+53316.00   0.207932   0.346855  -0.4715148    0.207990    0.346740   -0.4715210
+53317.00   0.208042   0.344640  -0.4724291    0.208130    0.344430   -0.4724170
+53318.00   0.207968   0.342708  -0.4735707    0.208170    0.342720   -0.4735620
+53319.00   0.208062   0.341039  -0.4748663    0.208020    0.340850   -0.4748570
+53320.00   0.207963   0.339038  -0.4761744    0.208180    0.339000   -0.4761690
+53321.00   0.207689   0.336617  -0.4773539    0.207760    0.336450   -0.4773500
+53322.00   0.208011   0.334322  -0.4783658    0.208150    0.334360   -0.4783540
+53323.00   0.207894   0.331940  -0.4790716    0.207950    0.331750   -0.4791100
+53324.00   0.207640   0.329327  -0.4795120    0.207730    0.329340   -0.4794100
+53325.00   0.207538   0.326628  -0.4798472    0.207490    0.326570   -0.4798260
+53326.00   0.207120   0.324354  -0.4801878    0.207330    0.324420   -0.4801980
+53327.00   0.206905   0.322071  -0.4806762    0.206980    0.321840   -0.4806780
+53328.00   0.206703   0.319823  -0.4813958    0.206820    0.319770   -0.4813830
+53329.00   0.206022   0.317745  -0.4823155    0.205970    0.317760   -0.4823050
+53330.00   0.205577   0.315592  -0.4834040    0.205910    0.315230   -0.4834030
+53331.00   0.205037   0.313371  -0.4845338    0.204990    0.313220   -0.4845320
+53332.00   0.204298   0.311115  -0.4856362    0.204340    0.311110   -0.4856390
+53333.00   0.203036   0.308969  -0.4866192    0.203200    0.308830   -0.4866210
+53334.00   0.201791   0.306736  -0.4873872    0.201810    0.306630   -0.4873620
+53335.00   0.200589   0.304321  -0.4879570    0.200720    0.304190   -0.4878990
+53336.00   0.199842   0.301959  -0.4882769    0.199830    0.301850   -0.4882490
+53337.00   0.199477   0.299851  -0.4883918    0.199660    0.299680   -0.4884350
+53338.00   0.199141   0.297878  -0.4884007    0.199190    0.297800   -0.4884790
+53339.00   0.198457   0.295825  -0.4883758    0.198590    0.295660   -0.4883780
+53340.00   0.197400   0.293534  -0.4883166    0.197420    0.293400   -0.4882780
+53341.00   0.195839   0.291194  -0.4884185    0.196040    0.291060   -0.4883320
+53342.00   0.194117   0.288731  -0.4887420    0.193950    0.288690   -0.4887380
+53343.00   0.192188   0.286454  -0.4891950    0.192260    0.286290   -0.4891760
+53344.00   0.190470   0.284460  -0.4898540    0.190570    0.284260   -0.4897990
+53345.00   0.188810   0.282492  -0.4907220    0.188940    0.282480   -0.4907450
+53346.00   0.187431   0.280376  -0.4917378    0.187320    0.280240   -0.4917210
+53347.00   0.186133   0.278540  -0.4928255    0.186440    0.278200   -0.4928240
+53348.00   0.184330   0.276772  -0.4938695    0.184120    0.276920   -0.4938780
+53349.00   0.181822   0.274584  -0.4946942    0.182340    0.274360   -0.4946950
+53350.00   0.180265   0.272589  -0.4953247    0.180270    0.272530   -0.4953200
+53351.00   0.178425   0.270639  -0.4957109    0.178570    0.270460   -0.4957160
+53352.00   0.176542   0.268620  -0.4959183    0.176580    0.268500   -0.4958990
+53353.00   0.174874   0.266464  -0.4961188    0.174870    0.266360   -0.4960900
+53354.00   0.173183   0.264323  -0.4964932    0.173230    0.264190   -0.4964970
+53355.00   0.171738   0.262289  -0.4970982    0.171920    0.262080   -0.4970940
+53356.00   0.170288   0.260433  -0.4979187    0.170300    0.260390   -0.4979080
+53357.00   0.169309   0.258834  -0.4989160    0.169390    0.258700   -0.4989080
+53358.00   0.168587   0.257388  -0.4999777    0.168680    0.257210   -0.4999790
+53359.00   0.167436   0.255847  -0.5010346    0.167570    0.255800   -0.5010160
+53360.00   0.165938   0.254031  -0.5019557    0.165950    0.253860   -0.5019450
+53361.00   0.164494   0.252104  -0.5025952    0.164650    0.252080   -0.5025630
+53362.00   0.162908   0.250099  -0.5030885    0.163020    0.250020   -0.5030760
+53363.00   0.161464   0.248564  -0.5033585    0.161650    0.248540   -0.5033550
+53364.00   0.159803   0.247327  -0.5034028    0.159800    0.247200   -0.5033760
+53365.00   0.158183   0.246477  -0.5032959    0.158420    0.246260   -0.5032740
+53366.00   0.156267   0.245476  -0.5031410    0.156380    0.245520   -0.5031320
+53367.00   0.154683   0.243879  -0.5030152    0.154540    0.243630   -0.5030010
+53368.00   0.152721   0.242334  -0.5029581    0.153040    0.242230   -0.5029620
+53369.00   0.151003   0.240748  -0.5029873    0.151160    0.240790   -0.5029790
+53370.00   0.149998   0.239256  -0.5031989    0.150140    0.239040   -0.5031920
+53371.00   0.149104   0.237996  -0.5036402    0.149240    0.237870   -0.5036520
+53372.00   0.148678   0.236862  -0.5042759    0.148770    0.236710   -0.5042860
+53373.00   0.148656   0.235806  -0.5050240    0.148790    0.235650   -0.5050180
+53374.00   0.148204   0.234687  -0.5058603    0.148460    0.234660   -0.5058480
+53375.00   0.147981   0.233358  -0.5066944    0.148050    0.233130   -0.5067430
+53376.00   0.146797   0.231734  -0.5074074    0.146950    0.231630   -0.5074040
+53377.00   0.145070   0.229723  -0.5078917    0.145140    0.229740   -0.5078740
+53378.00   0.143416   0.228078  -0.5081696    0.143520    0.227800   -0.5081770
+53379.00   0.141821   0.226807  -0.5083413    0.141930    0.226690   -0.5083080
+53380.00   0.139769   0.225653  -0.5085214    0.139960    0.225440   -0.5085820
+53381.00   0.137387   0.224471  -0.5087974    0.137390    0.224310   -0.5087860
+53382.00   0.135161   0.223188  -0.5093487    0.135370    0.223010   -0.5093340
+53383.00   0.133594   0.221990  -0.5101914    0.133610    0.221820   -0.5101990
+53384.00   0.131829   0.220955  -0.5112823    0.131980    0.220840   -0.5112860
+53385.00   0.130028   0.219792  -0.5124667    0.130070    0.219630   -0.5124470
+53386.00   0.128580   0.218550  -0.5136689    0.128720    0.218340   -0.5136980
+53387.00   0.127274   0.217360  -0.5147717    0.127440    0.217250   -0.5147280
+53388.00   0.125770   0.216373  -0.5157120    0.125840    0.216160   -0.5156800
+53389.00   0.124131   0.215757  -0.5164304    0.124160    0.215520   -0.5164150
+53390.00   0.121542   0.215118  -0.5169046    0.121650    0.215080   -0.5169020
+53391.00   0.119235   0.214095  -0.5172315    0.119310    0.213850   -0.5172320
+53392.00   0.117016   0.213241  -0.5174137    0.117180    0.213190   -0.5174180
+53393.00   0.114655   0.212420  -0.5174974    0.114640    0.212230   -0.5175070
+53394.00   0.112303   0.211497  -0.5175387    0.112480    0.211350   -0.5175350
+53395.00   0.110008   0.210563  -0.5175949    0.110060    0.210450   -0.5175790
+53396.00   0.107599   0.209727  -0.5177116    0.107690    0.209510   -0.5177280
+53397.00   0.105423   0.209179  -0.5179821    0.105520    0.209030   -0.5179890
+53398.00   0.102987   0.208872  -0.5184503    0.103190    0.208950   -0.5184380
+53399.00   0.100584   0.208896  -0.5190574    0.100770    0.208770   -0.5190740
+53400.00   0.097538   0.208712  -0.5197447    0.097550    0.208720   -0.5196790
+53401.00   0.094624   0.208515  -0.5204753    0.094690    0.208020   -0.5203660
+53402.00   0.091954   0.208506  -0.5212031    0.092070    0.208360   -0.5211880
+53403.00   0.089197   0.207774  -0.5218860    0.089220    0.207360   -0.5219040
+53404.00   0.086552   0.206870  -0.5224172    0.086670    0.206850   -0.5224260
+53405.00   0.083584   0.206141  -0.5227682    0.083920    0.206040   -0.5227550
+53406.00   0.081544   0.205868  -0.5229579    0.081570    0.205850   -0.5229780
+53407.00   0.078824   0.205838  -0.5231935    0.078920    0.205580   -0.5231160
+53408.00   0.076009   0.205788  -0.5235610    0.076100    0.205770   -0.5237140
+53409.00   0.073076   0.205521  -0.5240825    0.073150    0.205280   -0.5240730
+53410.00   0.069879   0.205014  -0.5249003    0.070030    0.205020   -0.5248950
+53411.00   0.066804   0.204321  -0.5260474    0.066860    0.204090   -0.5260380
+53412.00   0.064032   0.203564  -0.5274687    0.064120    0.203610   -0.5274600
+53413.00   0.061534   0.203227  -0.5290350    0.061670    0.203150   -0.5290210
+53414.00   0.059260   0.203103  -0.5305665    0.059180    0.202910   -0.5305800
+53415.00   0.057168   0.203188  -0.5319091    0.057480    0.203020   -0.5318810
+53416.00   0.054637   0.203354  -0.5329896    0.054560    0.203270   -0.5329820
+53417.00   0.051720   0.203158  -0.5337633    0.052100    0.202990   -0.5337520
+53418.00   0.048512   0.202982  -0.5342942    0.048250    0.202830   -0.5342930
+53419.00   0.045319   0.203117  -0.5347072    0.045910    0.203060   -0.5347030
+53420.00   0.042670   0.203752  -0.5351355    0.042380    0.203710   -0.5351220
+53421.00   0.040103   0.204527  -0.5356627    0.040510    0.204360   -0.5356850
+53422.00   0.037712   0.205249  -0.5363048    0.037570    0.205130   -0.5362980
+53423.00   0.035488   0.205829  -0.5371187    0.035710    0.205590   -0.5371080
+53424.00   0.033293   0.206106  -0.5381066    0.033200    0.206030   -0.5380940
+53425.00   0.031548   0.206231  -0.5393036    0.031760    0.205990   -0.5392940
+53426.00   0.030087   0.206590  -0.5407214    0.030330    0.206570   -0.5407130
+53427.00   0.029198   0.207544  -0.5423145    0.029430    0.207400   -0.5422950
+53428.00   0.027670   0.208625  -0.5440521    0.027720    0.208530   -0.5440730
+53429.00   0.025816   0.209840  -0.5457451    0.025890    0.209650   -0.5457110
+53430.00   0.024128   0.211329  -0.5473574    0.024110    0.211090   -0.5473360
+53431.00   0.021776   0.212859  -0.5488361    0.021880    0.212750   -0.5488330
+53432.00   0.019379   0.214130  -0.5501179    0.019440    0.213970   -0.5500970
+53433.00   0.016952   0.214886  -0.5512260    0.017160    0.214930   -0.5512200
+53434.00   0.015134   0.215849  -0.5522279    0.015180    0.215700   -0.5522110
+53435.00   0.012738   0.216531  -0.5531713    0.000000    0.000000    0.0000000
+53436.00   0.010557   0.217070  -0.5541355    0.000000    0.000000    0.0000000
+53437.00   0.008805   0.217764  -0.5552418    0.000000    0.000000    0.0000000
+53438.00   0.006758   0.218630  -0.5565094    0.000000    0.000000    0.0000000
+53439.00   0.004648   0.219470  -0.5578988    0.000000    0.000000    0.0000000
+53440.00   0.002114   0.220380  -0.5593918    0.000000    0.000000    0.0000000
+53441.00   0.000388   0.221223  -0.5609127    0.000000    0.000000    0.0000000
+53442.00  -0.001412   0.221965  -0.5622917    0.000000    0.000000    0.0000000
+53443.00  -0.002677   0.222527  -0.5634065    0.000000    0.000000    0.0000000
+53444.00  -0.003696   0.223202  -0.5641684    0.000000    0.000000    0.0000000
+53445.00  -0.005588   0.223371  -0.5645880    0.000000    0.000000    0.0000000
+53446.00  -0.006897   0.223602  -0.5647672    0.000000    0.000000    0.0000000
+53447.00  -0.008130   0.223964  -0.5648197    0.000000    0.000000    0.0000000
+53448.00  -0.009000   0.224769  -0.5648552    0.000000    0.000000    0.0000000
+53449.00  -0.009854   0.225788  -0.5649488    0.000000    0.000000    0.0000000
+53450.00  -0.010752   0.226865  -0.5651214    0.000000    0.000000    0.0000000
+53451.00  -0.011840   0.228178  -0.5654544    0.000000    0.000000    0.0000000
+53452.00  -0.013358   0.230112  -0.5660329    0.000000    0.000000    0.0000000
+53453.00  -0.015359   0.231733  -0.5668881    0.000000    0.000000    0.0000000
+53454.00  -0.016629   0.233036  -0.5679461    0.000000    0.000000    0.0000000
+53455.00  -0.017847   0.234493  -0.5691350    0.000000    0.000000    0.0000000
+53456.00  -0.019259   0.236179  -0.5703272    0.000000    0.000000    0.0000000
+53457.00  -0.020918   0.237826  -0.5714205    0.000000    0.000000    0.0000000
+53458.00  -0.022444   0.239266  -0.5723283    0.000000    0.000000    0.0000000
+53459.00  -0.024824   0.240180  -0.5729861    0.000000    0.000000    0.0000000
+53460.00  -0.026795   0.241255  -0.5733634    0.000000    0.000000    0.0000000
+53461.00  -0.028997   0.242470  -0.5735448    0.000000    0.000000    0.0000000
+53462.00  -0.030748   0.243908  -0.5736220    0.000000    0.000000    0.0000000
+53463.00  -0.032355   0.244908  -0.5738480    0.000000    0.000000    0.0000000
+53464.00  -0.033549   0.245573  -0.5743133    0.000000    0.000000    0.0000000
+53465.00  -0.034314   0.246009  -0.5750870    0.000000    0.000000    0.0000000
+53466.00  -0.035093   0.246522  -0.5760682    0.000000    0.000000    0.0000000
+53467.00  -0.035603   0.247955  -0.5772363    0.000000    0.000000    0.0000000
+53468.00  -0.036718   0.250078  -0.5785306    0.000000    0.000000    0.0000000
+53469.00  -0.038502   0.252218  -0.5797697    0.000000    0.000000    0.0000000
+53470.00  -0.040638   0.253880  -0.5808114    0.000000    0.000000    0.0000000
+53471.00  -0.042585   0.255276  -0.5815761    0.000000    0.000000    0.0000000
+53472.00  -0.044042   0.256696  -0.5820791    0.000000    0.000000    0.0000000
+53473.00  -0.045470   0.258542  -0.5823466    0.000000    0.000000    0.0000000
+53474.00  -0.046115   0.260362  -0.5825920    0.000000    0.000000    0.0000000
+53475.00  -0.046839   0.262307  -0.5828570    0.000000    0.000000    0.0000000
+53476.00  -0.047868   0.264720  -0.5831796    0.000000    0.000000    0.0000000
+53477.00  -0.049363   0.267063  -0.5836566    0.000000    0.000000    0.0000000
+53478.00  -0.050998   0.269275  -0.5842974    0.000000    0.000000    0.0000000
+53479.00  -0.052488   0.271589  -0.5851281    0.000000    0.000000    0.0000000
+53480.00  -0.053852   0.273906  -0.5861710    0.000000    0.000000    0.0000000
+53481.00  -0.054932   0.276138  -0.5873988    0.000000    0.000000    0.0000000
+53482.00  -0.055784   0.278356  -0.5887576    0.000000    0.000000    0.0000000
+53483.00  -0.056771   0.280694  -0.5901941    0.000000    0.000000    0.0000000
+53484.00  -0.057675   0.283026  -0.5916167    0.000000    0.000000    0.0000000
+53485.00  -0.058387   0.284998  -0.5929170    0.000000    0.000000    0.0000000
+53486.00  -0.058808   0.286671  -0.5940167    0.000000    0.000000    0.0000000
+53487.00  -0.058820   0.288330  -0.5948574    0.000000    0.000000    0.0000000
+53488.00  -0.058559   0.290118  -0.5954984    0.000000    0.000000    0.0000000
+53489.00  -0.058393   0.291917  -0.5960518    0.000000    0.000000    0.0000000
+53490.00  -0.058316   0.293666  -0.5966125    0.000000    0.000000    0.0000000
+53491.00  -0.058318   0.295380  -0.5973345    0.000000    0.000000    0.0000000
+53492.00  -0.058390   0.297070  -0.5983193    0.000000    0.000000    0.0000000
+53493.00  -0.058522   0.298743  -0.5995699    0.000000    0.000000    0.0000000
+53494.00  -0.058706   0.300405  -0.6009985    0.000000    0.000000    0.0000000
+53495.00  -0.058935   0.302062  -0.6024845    0.000000    0.000000    0.0000000
+53496.00  -0.059203   0.303716  -0.6039283    0.000000    0.000000    0.0000000
+53497.00  -0.059502   0.305370  -0.6052122    0.000000    0.000000    0.0000000
+53498.00  -0.059826   0.307027  -0.6062461    0.000000    0.000000    0.0000000
+53499.00  -0.060171   0.308686  -0.6069829    0.000000    0.000000    0.0000000
+53500.00  -0.060532   0.310349  -0.6074436    0.000000    0.000000    0.0000000
+53501.00  -0.060904   0.312017  -0.6076888    0.000000    0.000000    0.0000000
+53502.00  -0.061282   0.313689  -0.6077942    0.000000    0.000000    0.0000000
+53503.00  -0.061663   0.315365  -0.6078289    0.000000    0.000000    0.0000000
+53504.00  -0.062043   0.317046  -0.6078505    0.000000    0.000000    0.0000000
+53505.00  -0.062420   0.318731  -0.6079327    0.000000    0.000000    0.0000000
+53506.00  -0.062790   0.320420  -0.6081303    0.000000    0.000000    0.0000000
+53507.00  -0.063150   0.322112  -0.6084627    0.000000    0.000000    0.0000000
+53508.00  -0.063499   0.323806  -0.6089358    0.000000    0.000000    0.0000000
+53509.00  -0.063834   0.325504  -0.6095162    0.000000    0.000000    0.0000000
+53510.00  -0.064152   0.327203  -0.6101472    0.000000    0.000000    0.0000000
+53511.00  -0.064453   0.328905  -0.6107558    0.000000    0.000000    0.0000000
+53512.00  -0.064734   0.330607  -0.6112464    0.000000    0.000000    0.0000000
+53513.00  -0.064995   0.332310  -0.6115299    0.000000    0.000000    0.0000000
+53514.00  -0.065232   0.334014  -0.6115529    0.000000    0.000000    0.0000000
+53515.00  -0.065447   0.335717  -0.6113279    0.000000    0.000000    0.0000000
+53516.00  -0.065637   0.337420  -0.6109488    0.000000    0.000000    0.0000000
+53517.00  -0.065801   0.339122  -0.6105519    0.000000    0.000000    0.0000000
+53518.00  -0.065939   0.340822  -0.6102797    0.000000    0.000000    0.0000000
+53519.00  -0.066050   0.342522  -0.6102362    0.000000    0.000000    0.0000000
+53520.00  -0.066134   0.344219  -0.6104445    0.000000    0.000000    0.0000000
+53521.00  -0.066189   0.345913  -0.6108579    0.000000    0.000000    0.0000000
+53522.00  -0.066215   0.347605  -0.6113927    0.000000    0.000000    0.0000000
+53523.00  -0.066212   0.349281  -0.6119409    0.000000    0.000000    0.0000000
+53524.00  -0.066180   0.350968  -0.6123911    0.000000    0.000000    0.0000000
+53525.00  -0.066119   0.352651  -0.6126575    0.000000    0.000000    0.0000000
+53526.00  -0.066027   0.354330  -0.6126980    0.000000    0.000000    0.0000000
+53527.00  -0.065906   0.356004  -0.6125152    0.000000    0.000000    0.0000000
+53528.00  -0.065754   0.357673  -0.6121483    0.000000    0.000000    0.0000000
+53529.00  -0.065572   0.359337  -0.6116652    0.000000    0.000000    0.0000000
+53530.00  -0.065360   0.360996  -0.6111423    0.000000    0.000000    0.0000000
+53531.00  -0.065118   0.362649  -0.6106517    0.000000    0.000000    0.0000000
+53532.00  -0.064846   0.364296  -0.6102616    0.000000    0.000000    0.0000000
+53533.00  -0.064544   0.365936  -0.6100239    0.000000    0.000000    0.0000000
+53534.00  -0.064213   0.367570  -0.6099593    0.000000    0.000000    0.0000000
+53535.00  -0.063851   0.369197  -0.6100599    0.000000    0.000000    0.0000000
+53536.00  -0.063461   0.370817  -0.6102988    0.000000    0.000000    0.0000000
+53537.00  -0.063041   0.372430  -0.6106255    0.000000    0.000000    0.0000000
+53538.00  -0.062592   0.374034  -0.6109647    0.000000    0.000000    0.0000000
+53539.00  -0.062114   0.375631  -0.6112275    0.000000    0.000000    0.0000000
+53540.00  -0.061608   0.377220  -0.6113218    0.000000    0.000000    0.0000000
+53541.00  -0.061074   0.378800  -0.6111834    0.000000    0.000000    0.0000000
+53542.00  -0.060512   0.380371  -0.6108019    0.000000    0.000000    0.0000000
+53543.00  -0.059922   0.381934  -0.6102428    0.000000    0.000000    0.0000000
+53544.00  -0.059305   0.383487  -0.6096371    0.000000    0.000000    0.0000000
+53545.00  -0.058662   0.385030  -0.6091370    0.000000    0.000000    0.0000000
+53546.00  -0.057992   0.386564  -0.6088632    0.000000    0.000000    0.0000000
+53547.00  -0.057296   0.388087  -0.6088621    0.000000    0.000000    0.0000000
+53548.00  -0.056574   0.389600  -0.6090923    0.000000    0.000000    0.0000000
+53549.00  -0.055826   0.391103  -0.6094469    0.000000    0.000000    0.0000000
+53550.00  -0.055054   0.392595  -0.6097895    0.000000    0.000000    0.0000000
+53551.00  -0.054258   0.394076  -0.6099955    0.000000    0.000000    0.0000000
+53552.00  -0.053437   0.395545  -0.6099794    0.000000    0.000000    0.0000000
+53553.00  -0.052592   0.397002  -0.6097058    0.000000    0.000000    0.0000000
+53554.00  -0.051725   0.398448  -0.6091810    0.000000    0.000000    0.0000000
+53555.00  -0.050834   0.399882  -0.6084457    0.000000    0.000000    0.0000000
+53556.00  -0.049921   0.401303  -0.6075639    0.000000    0.000000    0.0000000
+53557.00  -0.048986   0.402712  -0.6066152    0.000000    0.000000    0.0000000
+53558.00  -0.048029   0.404108  -0.6056803    0.000000    0.000000    0.0000000
+53559.00  -0.047052   0.405491  -0.6048334    0.000000    0.000000    0.0000000
+53560.00  -0.046053   0.406860  -0.6041286    0.000000    0.000000    0.0000000
+53561.00  -0.045035   0.408216  -0.6035963    0.000000    0.000000    0.0000000
+53562.00  -0.043996   0.409558  -0.6032371    0.000000    0.000000    0.0000000
+53563.00  -0.042938   0.410886  -0.6030275    0.000000    0.000000    0.0000000
+53564.00  -0.041862   0.412200  -0.6029216    0.000000    0.000000    0.0000000
+53565.00  -0.040767   0.413499  -0.6028588    0.000000    0.000000    0.0000000
+53566.00  -0.039654   0.414784  -0.6027649    0.000000    0.000000    0.0000000
+53567.00  -0.038523   0.416054  -0.6025605    0.000000    0.000000    0.0000000
+53568.00  -0.037375   0.417308  -0.6021755    0.000000    0.000000    0.0000000
+53569.00  -0.036211   0.418547  -0.6015762    0.000000    0.000000    0.0000000
+53570.00  -0.035030   0.419770  -0.6007902    0.000000    0.000000    0.0000000
+53571.00  -0.033834   0.420977  -0.5999156    0.000000    0.000000    0.0000000
+53572.00  -0.032622   0.422169  -0.5991005    0.000000    0.000000    0.0000000
+53573.00  -0.031396   0.423344  -0.5984935    0.000000    0.000000    0.0000000
+53574.00  -0.030155   0.424502  -0.5981855    0.000000    0.000000    0.0000000
+53575.00  -0.028900   0.425644  -0.5981730    0.000000    0.000000    0.0000000
+53576.00  -0.027631   0.426768  -0.5983602    0.000000    0.000000    0.0000000
+53577.00  -0.026350   0.427876  -0.5985965    0.000000    0.000000    0.0000000
+53578.00  -0.025056   0.428966  -0.5987300    0.000000    0.000000    0.0000000
+53579.00  -0.023749   0.430039  -0.5986511    0.000000    0.000000    0.0000000
+53580.00  -0.022431   0.431093  -0.5983098    0.000000    0.000000    0.0000000
+53581.00  -0.021102   0.432130  -0.5977117    0.000000    0.000000    0.0000000
+53582.00  -0.019762   0.433149  -0.5969010    0.000000    0.000000    0.0000000
+53583.00  -0.018411   0.434149  -0.5959441    0.000000    0.000000    0.0000000
+53584.00  -0.017050   0.435131  -0.5949184    0.000000    0.000000    0.0000000
+53585.00  -0.015680   0.436094  -0.5939036    0.000000    0.000000    0.0000000
+53586.00  -0.014300   0.437038  -0.5929728    0.000000    0.000000    0.0000000
+53587.00  -0.012912   0.437962  -0.5921853    0.000000    0.000000    0.0000000
+53588.00  -0.011515   0.438868  -0.5915752    0.000000    0.000000    0.0000000
+53589.00  -0.010110   0.439754  -0.5911486    0.000000    0.000000    0.0000000
+53590.00  -0.008698   0.440620  -0.5908851    0.000000    0.000000    0.0000000
+53591.00  -0.007279   0.441467  -0.5907400    0.000000    0.000000    0.0000000
+53592.00  -0.005853   0.442293  -0.5906517    0.000000    0.000000    0.0000000
+53593.00  -0.004420   0.443100  -0.5905516    0.000000    0.000000    0.0000000
+53594.00  -0.003209   0.443886  -0.5904012    0.000000    0.000000    0.0000000
+53595.00  -0.001754   0.444651  -0.5901045    0.000000    0.000000    0.0000000
+53596.00  -0.000295   0.445396  -0.5896244    0.000000    0.000000    0.0000000
+53597.00   0.001169   0.446120  -0.5889693    0.000000    0.000000    0.0000000
+53598.00   0.002636   0.446824  -0.5882077    0.000000    0.000000    0.0000000
+53599.00   0.004108   0.447506  -0.5874650    0.000000    0.000000    0.0000000
+53600.00   0.005582   0.448167  -0.5868920    0.000000    0.000000    0.0000000
+53601.00   0.007059   0.448806  -0.5866144    0.000000    0.000000    0.0000000
+53602.00   0.008538   0.449425  -0.5866804    0.000000    0.000000    0.0000000
+53603.00   0.010020   0.450021  -0.5870364    0.000000    0.000000    0.0000000
+53604.00   0.011504   0.450596  -0.5875436    0.000000    0.000000    0.0000000
+53605.00   0.012989   0.451149  -0.5880275    0.000000    0.000000    0.0000000
+53606.00   0.014475   0.451680  -0.5883354    0.000000    0.000000    0.0000000
+53607.00   0.015961   0.452189  -0.5883779    0.000000    0.000000    0.0000000
+53608.00   0.017449   0.452676  -0.5881384    0.000000    0.000000    0.0000000
+53609.00   0.018936   0.453141  -0.5876592    0.000000    0.000000    0.0000000
+53610.00   0.020423   0.453583  -0.5870155    0.000000    0.000000    0.0000000
+53611.00   0.021910   0.454003  -0.5862936    0.000000    0.000000    0.0000000
+53612.00   0.023396   0.454401  -0.5855783    0.000000    0.000000    0.0000000
+53613.00   0.024881   0.454776  -0.5849460    0.000000    0.000000    0.0000000
+53614.00   0.026364   0.455128  -0.5844593    0.000000    0.000000    0.0000000
+53615.00   0.027845   0.455458  -0.5841604    0.000000    0.000000    0.0000000
+53616.00   0.029325   0.455765  -0.5840650    0.000000    0.000000    0.0000000
+53617.00   0.030802   0.456049  -0.5841590    0.000000    0.000000    0.0000000
+53618.00   0.032276   0.456310  -0.5844004    0.000000    0.000000    0.0000000
+53619.00   0.033748   0.456548  -0.5847248    0.000000    0.000000    0.0000000
+53620.00   0.035216   0.456764  -0.5850557    0.000000    0.000000    0.0000000
+53621.00   0.036681   0.456956  -0.5853163    0.000000    0.000000    0.0000000
+53622.00   0.038142   0.457126  -0.5854416    0.000000    0.000000    0.0000000
+53623.00   0.039599   0.457272  -0.5853929    0.000000    0.000000    0.0000000
+53624.00   0.041052   0.457396  -0.5851720    0.000000    0.000000    0.0000000
+53625.00   0.042500   0.457496  -0.5848305    0.000000    0.000000    0.0000000
+53626.00   0.043944   0.457573  -0.5844710    0.000000    0.000000    0.0000000
+53627.00   0.045382   0.457628  -0.5842291    0.000000    0.000000    0.0000000
+53628.00   0.046815   0.457659  -0.5842381    0.000000    0.000000    0.0000000
+53629.00   0.048243   0.457668  -0.5845824    0.000000    0.000000    0.0000000
+53630.00   0.049664   0.457653  -0.5852609    0.000000    0.000000    0.0000000
+53631.00   0.051080   0.457616  -0.5861783    0.000000    0.000000    0.0000000
+53632.00   0.052489   0.457555  -0.5871727    0.000000    0.000000    0.0000000
+53633.00   0.053892   0.457472  -0.5880692    0.000000    0.000000    0.0000000
+53634.00   0.055288   0.457366  -0.5887343    0.000000    0.000000    0.0000000
+53635.00   0.056677   0.457237  -0.5891083    0.000000    0.000000    0.0000000
+53636.00   0.058059   0.457086  -0.5892062    0.000000    0.000000    0.0000000
+53637.00   0.059434   0.456912  -0.5890965    0.000000    0.000000    0.0000000
+53638.00   0.060801   0.456715  -0.5888716    0.000000    0.000000    0.0000000
+53639.00   0.062160   0.456496  -0.5886259    0.000000    0.000000    0.0000000
+53640.00   0.063511   0.456255  -0.5884432    0.000000    0.000000    0.0000000
+53641.00   0.064854   0.455992  -0.5883910    0.000000    0.000000    0.0000000
+53642.00   0.066188   0.455706  -0.5885166    0.000000    0.000000    0.0000000
+53643.00   0.067514   0.455398  -0.5888431    0.000000    0.000000    0.0000000
+53644.00   0.068832   0.455069  -0.5893658    0.000000    0.000000    0.0000000
+53645.00   0.070140   0.454717  -0.5900518    0.000000    0.000000    0.0000000
+53646.00   0.071439   0.454344  -0.5908420    0.000000    0.000000    0.0000000
+53647.00   0.072729   0.453949  -0.5916589    0.000000    0.000000    0.0000000
+53648.00   0.074009   0.453533  -0.5924178    0.000000    0.000000    0.0000000
+53649.00   0.075280   0.453096  -0.5930421    0.000000    0.000000    0.0000000
+53650.00   0.076540   0.452638  -0.5934813    0.000000    0.000000    0.0000000
+53651.00   0.077791   0.452159  -0.5937269    0.000000    0.000000    0.0000000
+53652.00   0.079032   0.451659  -0.5938215    0.000000    0.000000    0.0000000
+53653.00   0.080262   0.451138  -0.5938556    0.000000    0.000000    0.0000000
+53654.00   0.081482   0.450597  -0.5939521    0.000000    0.000000    0.0000000
+53655.00   0.082692   0.450036  -0.5942384    0.000000    0.000000    0.0000000
+53656.00   0.083890   0.449455  -0.5948111    0.000000    0.000000    0.0000000
+53657.00   0.085078   0.448853  -0.5957022    0.000000    0.000000    0.0000000
+53658.00   0.086255   0.448233  -0.5968621    0.000000    0.000000    0.0000000
+53659.00   0.087420   0.447593  -0.5981670    0.000000    0.000000    0.0000000
+53660.00   0.088575   0.446933  -0.5994545    0.000000    0.000000    0.0000000
+53661.00   0.089717   0.446255  -0.6005727    0.000000    0.000000    0.0000000
+53662.00   0.090849   0.445558  -0.6014225    0.000000    0.000000    0.0000000
+53663.00   0.091968   0.444843  -0.6019788    0.000000    0.000000    0.0000000
+53664.00   0.093076   0.444109  -0.6022833    0.000000    0.000000    0.0000000
+53665.00   0.094172   0.443357  -0.6024214    0.000000    0.000000    0.0000000
+53666.00   0.095255   0.442587  -0.6024933    0.000000    0.000000    0.0000000
+53667.00   0.096327   0.441800  -0.6025936    0.000000    0.000000    0.0000000
+53668.00   0.097386   0.440996  -0.6027999    0.000000    0.000000    0.0000000
+53669.00   0.098433   0.440175  -0.6031678    0.000000    0.000000    0.0000000
+53670.00   0.099468   0.439336  -0.6037281    0.000000    0.000000    0.0000000
+53671.00   0.100489   0.438482  -0.6044850    0.000000    0.000000    0.0000000
+53672.00   0.101499   0.437611  -0.6054158    0.000000    0.000000    0.0000000
+53673.00   0.102495   0.436724  -0.6064715    0.000000    0.000000    0.0000000
+53674.00   0.103478   0.435822  -0.6075801    0.000000    0.000000    0.0000000
+53675.00   0.104449   0.434904  -0.6086532    0.000000    0.000000    0.0000000
+53676.00   0.105406   0.433972  -0.6095989    0.000000    0.000000    0.0000000
+53677.00   0.106350   0.433024  -0.6103430    0.000000    0.000000    0.0000000
+53678.00   0.107281   0.432062  -0.6108514    0.000000    0.000000    0.0000000
+53679.00   0.108223   0.431124  -0.6111462    0.000000    0.000000    0.0000000
+53680.00   0.109151   0.430171  -0.6113060    0.000000    0.000000    0.0000000
+53681.00   0.110066   0.429205  -0.6114479    0.000000    0.000000    0.0000000
+53682.00   0.110967   0.428226  -0.6116958    0.000000    0.000000    0.0000000
+53683.00   0.111855   0.427233  -0.6121457    0.000000    0.000000    0.0000000
+53684.00   0.112729   0.426229  -0.6128371    0.000000    0.000000    0.0000000
+53685.00   0.113589   0.425212  -0.6137401    0.000000    0.000000    0.0000000
+53686.00   0.114435   0.424183  -0.6147618    0.000000    0.000000    0.0000000
+53687.00   0.115267   0.423142  -0.6157710    0.000000    0.000000    0.0000000
+53688.00   0.116085   0.422091  -0.6166338    0.000000    0.000000    0.0000000
+53689.00   0.116888   0.421028  -0.6172502    0.000000    0.000000    0.0000000
+53690.00   0.117678   0.419955  -0.6175782    0.000000    0.000000    0.0000000
+53691.00   0.118453   0.418871  -0.6176403    0.000000    0.000000    0.0000000
+53692.00   0.119213   0.417778  -0.6175113    0.000000    0.000000    0.0000000
+53693.00   0.119960   0.416675  -0.6172933    0.000000    0.000000    0.0000000
+53694.00   0.120692   0.415563  -0.6170891    0.000000    0.000000    0.0000000
+53695.00   0.121409   0.414442  -0.6169821    0.000000    0.000000    0.0000000
+53696.00   0.122111   0.413312  -0.6170263    0.000000    0.000000    0.0000000
+53697.00   0.122799   0.412174  -0.6172457    0.000000    0.000000    0.0000000
+53698.00   0.123472   0.411029  -0.6176422    0.000000    0.000000    0.0000000
+53699.00   0.124131   0.409875  -0.6182042    0.000000    0.000000    0.0000000
+53700.00   0.124774   0.408715  -0.6189069    0.000000    0.000000    0.0000000
+53701.00   0.125403   0.407548  -0.6197065    0.000000    0.000000    0.0000000
+53702.00   0.126016   0.406374  -0.6205275    0.000000    0.000000    0.0000000
+53703.00   0.126615   0.405194  -0.6212552    0.000000    0.000000    0.0000000
+53704.00   0.127199   0.404009  -0.6217797    0.000000    0.000000    0.0000000
+53705.00   0.127767   0.402818  -0.6220429    0.000000    0.000000    0.0000000
+53706.00   0.128320   0.401621  -0.6220504    0.000000    0.000000    0.0000000
+53707.00   0.128858   0.400420  -0.6218700    0.000000    0.000000    0.0000000
+53708.00   0.129381   0.399215  -0.6216063    0.000000    0.000000    0.0000000
+53709.00   0.129889   0.398005  -0.6214324    0.000000    0.000000    0.0000000
+53710.00   0.130381   0.396792  -0.6215055    0.000000    0.000000    0.0000000
+53711.00   0.130858   0.395575  -0.6218252    0.000000    0.000000    0.0000000
+53712.00   0.131319   0.394355  -0.6223291    0.000000    0.000000    0.0000000
+53713.00   0.131765   0.393132  -0.6230128    0.000000    0.000000    0.0000000
+53714.00   0.132196   0.391907  -0.6237385    0.000000    0.000000    0.0000000
+53715.00   0.132611   0.390680  -0.6243539    0.000000    0.000000    0.0000000
+53716.00   0.133011   0.389450  -0.6247772    0.000000    0.000000    0.0000000
+53717.00   0.133395   0.388220  -0.6249471    0.000000    0.000000    0.0000000
+53718.00   0.133763   0.386988  -0.6248605    0.000000    0.000000    0.0000000
+53719.00   0.134116   0.385755  -0.6245562    0.000000    0.000000    0.0000000
+53720.00   0.134453   0.384522  -0.6241433    0.000000    0.000000    0.0000000
+53721.00   0.134775   0.383288  -0.6237553    0.000000    0.000000    0.0000000
+53722.00   0.135081   0.382055  -0.6234058    0.000000    0.000000    0.0000000
+53723.00   0.135371   0.380822  -0.6231935    0.000000    0.000000    0.0000000
+53724.00   0.135646   0.379589  -0.6231388    0.000000    0.000000    0.0000000
+53725.00   0.135905   0.378358  -0.6232290    0.000000    0.000000    0.0000000
+53726.00   0.136148   0.377127  -0.6234184    0.000000    0.000000    0.0000000
+53727.00   0.136375   0.375898  -0.6236764    0.000000    0.000000    0.0000000
+53728.00   0.136587   0.374671  -0.6239384    0.000000    0.000000    0.0000000
+53729.00   0.136783   0.373447  -0.6241555    0.000000    0.000000    0.0000000
+53730.00   0.136964   0.372224  -0.6243078    0.000000    0.000000    0.0000000
+53731.00   0.137128   0.371004  -0.6243570    0.000000    0.000000    0.0000000
+53732.00   0.137277   0.369787  -0.6242861    0.000000    0.000000    0.0000000
+53733.00   0.137410   0.368573  -0.6241018    0.000000    0.000000    0.0000000
+53734.00   0.137528   0.367362  -0.6238675    0.000000    0.000000    0.0000000
+53735.00   0.137630   0.366156  -0.6236275    0.000000    0.000000    0.0000000
+53736.00   0.137716   0.364952  -0.6234604    0.000000    0.000000    0.0000000
+53737.00   0.137786   0.363754  -0.6235498    0.000000    0.000000    0.0000000
+53738.00   0.137841   0.362559  -0.6239378    0.000000    0.000000    0.0000000
+53739.00   0.137880   0.361369  -0.6246240    0.000000    0.000000    0.0000000
+53740.00   0.137904   0.360184  -0.6254857    0.000000    0.000000    0.0000000
+53741.00   0.137912   0.359004  -0.6263990    0.000000    0.000000    0.0000000
+53742.00   0.137904   0.357829  -0.6272249    0.000000    0.000000    0.0000000
+53743.00   0.137881   0.356660  -0.6279379    0.000000    0.000000    0.0000000
+53744.00   0.137842   0.355496  -0.6284401    0.000000    0.000000    0.0000000
+53745.00   0.137788   0.354338  -0.6287682    0.000000    0.000000    0.0000000
+53746.00   0.137719   0.353186  -0.6288322    0.000000    0.000000    0.0000000
+53747.00   0.137634   0.352041  -0.6287654    0.000000    0.000000    0.0000000
+53748.00   0.137534   0.350901  -0.6286803    0.000000    0.000000    0.0000000
+53749.00   0.137419   0.349769  -0.6286400    0.000000    0.000000    0.0000000
+53750.00   0.137288   0.348643  -0.6286794    0.000000    0.000000    0.0000000
+53751.00   0.137143   0.347524  -0.6288431    0.000000    0.000000    0.0000000
+53752.00   0.136982   0.346413  -0.6291656    0.000000    0.000000    0.0000000
+53753.00   0.136806   0.345308  -0.6296356    0.000000    0.000000    0.0000000
+53754.00   0.136615   0.344211  -0.6302305    0.000000    0.000000    0.0000000
+53755.00   0.136410   0.343122  -0.6309239    0.000000    0.000000    0.0000000
+53756.00   0.136189   0.342040  -0.6316796    0.000000    0.000000    0.0000000
+53757.00   0.135954   0.340966  -0.6323916    0.000000    0.000000    0.0000000
+53758.00   0.135704   0.339900  -0.6330571    0.000000    0.000000    0.0000000
+53759.00   0.135439   0.338842  -0.6335213    0.000000    0.000000    0.0000000
+53760.00   0.135160   0.337792  -0.6338344    0.000000    0.000000    0.0000000
+53761.00   0.134867   0.336751  -0.6339713    0.000000    0.000000    0.0000000
+53762.00   0.134559   0.335718  -0.6339889    0.000000    0.000000    0.0000000
+53763.00   0.134237   0.334693  -0.6339930    0.000000    0.000000    0.0000000
+53764.00   0.133901   0.333677  -0.6341178    0.000000    0.000000    0.0000000
+53765.00   0.133550   0.332670  -0.6345595    0.000000    0.000000    0.0000000
+53766.00   0.133186   0.331672  -0.6353636    0.000000    0.000000    0.0000000
+53767.00   0.132808   0.330682  -0.6364640    0.000000    0.000000    0.0000000
+53768.00   0.132416   0.329702  -0.6376642    0.000000    0.000000    0.0000000
+53769.00   0.132011   0.328730  -0.6387772    0.000000    0.000000    0.0000000
+53770.00   0.131592   0.327768  -0.6396991    0.000000    0.000000    0.0000000
+53771.00   0.131160   0.326814  -0.6403238    0.000000    0.000000    0.0000000
+53772.00   0.130714   0.325870  -0.6406376    0.000000    0.000000    0.0000000
+53773.00   0.130256   0.324935  -0.6407102    0.000000    0.000000    0.0000000
+53774.00   0.129784   0.324010  -0.6406236    0.000000    0.000000    0.0000000
+53775.00   0.129300   0.323094  -0.6404781    0.000000    0.000000    0.0000000
+53776.00   0.128802   0.322187  -0.6403549    0.000000    0.000000    0.0000000
+53777.00   0.128293   0.321290  -0.6403270    0.000000    0.000000    0.0000000
+53778.00   0.127770   0.320402  -0.6404516    0.000000    0.000000    0.0000000
+53779.00   0.127236   0.319524  -0.6407561    0.000000    0.000000    0.0000000
+53780.00   0.126689   0.318655  -0.6412093    0.000000    0.000000    0.0000000
+53781.00   0.126130   0.317795  -0.6418189    0.000000    0.000000    0.0000000
+53782.00   0.125560   0.316946  -0.6425537    0.000000    0.000000    0.0000000
+53783.00   0.124978   0.316106  -0.6433265    0.000000    0.000000    0.0000000
+53784.00   0.124384   0.315275  -0.6440384    0.000000    0.000000    0.0000000
+53785.00   0.123779   0.314454  -0.6446354    0.000000    0.000000    0.0000000
+53786.00   0.123163   0.313643  -0.6450543    0.000000    0.000000    0.0000000
+53787.00   0.122535   0.312841  -0.6452726    0.000000    0.000000    0.0000000
+53788.00   0.121897   0.312049  -0.6453503    0.000000    0.000000    0.0000000
+53789.00   0.121248   0.311267  -0.6453001    0.000000    0.000000    0.0000000
+53790.00   0.120589   0.310494  -0.6452021    0.000000    0.000000    0.0000000
+53791.00   0.119920   0.309730  -0.6452154    0.000000    0.000000    0.0000000
+53792.00   0.119240   0.308976  -0.6454803    0.000000    0.000000    0.0000000
+53793.00   0.118550   0.308232  -0.6461007    0.000000    0.000000    0.0000000
+53794.00   0.117851   0.307497  -0.6470960    0.000000    0.000000    0.0000000
+53795.00   0.117142   0.306772  -0.6483371    0.000000    0.000000    0.0000000
+53796.00   0.116423   0.306056  -0.6496191    0.000000    0.000000    0.0000000
+53797.00   0.115695   0.305350  -0.6507704    0.000000    0.000000    0.0000000
+53798.00   0.114959   0.304653  -0.6517162    0.000000    0.000000    0.0000000
+53799.00   0.114213   0.303966  -0.6524506    0.000000    0.000000    0.0000000
+53800.00   0.113459   0.303288  -0.6528723    0.000000    0.000000    0.0000000
+53801.00   0.112697   0.302619  -0.6531031    0.000000    0.000000    0.0000000
+53802.00   0.111926   0.301960  -0.6531597    0.000000    0.000000    0.0000000
+53803.00   0.111148   0.301310  -0.6531858    0.000000    0.000000    0.0000000
+53804.00   0.110362   0.300669  -0.6532919    0.000000    0.000000    0.0000000
+53805.00   0.109568   0.300038  -0.6536087    0.000000    0.000000    0.0000000
+53806.00   0.108766   0.299416  -0.6540974    0.000000    0.000000    0.0000000
+53807.00   0.107958   0.298803  -0.6547697    0.000000    0.000000    0.0000000
+53808.00   0.107143   0.298199  -0.6556600    0.000000    0.000000    0.0000000
+53809.00   0.106320   0.297604  -0.6566890    0.000000    0.000000    0.0000000
+53810.00   0.105492   0.297018  -0.6578024    0.000000    0.000000    0.0000000
+53811.00   0.104657   0.296441  -0.6589494    0.000000    0.000000    0.0000000
+53812.00   0.103816   0.295873  -0.6599791    0.000000    0.000000    0.0000000
+53813.00   0.102969   0.295314  -0.6608763    0.000000    0.000000    0.0000000
+53814.00   0.102117   0.294764  -0.6615944    0.000000    0.000000    0.0000000
+53815.00   0.101259   0.294223  -0.6621621    0.000000    0.000000    0.0000000
+53816.00   0.100396   0.293691  -0.6626469    0.000000    0.000000    0.0000000
+53817.00   0.099528   0.293168  -0.6630793    0.000000    0.000000    0.0000000
+53818.00   0.098655   0.292653  -0.6635451    0.000000    0.000000    0.0000000
+53819.00   0.097777   0.292147  -0.6641407    0.000000    0.000000    0.0000000
+53820.00   0.096895   0.291650  -0.6649557    0.000000    0.000000    0.0000000
+53821.00   0.096010   0.291162  -0.6660964    0.000000    0.000000    0.0000000
+53822.00   0.095120   0.290682  -0.6674847    0.000000    0.000000    0.0000000
+53823.00   0.094226   0.290211  -0.6690594    0.000000    0.000000    0.0000000
+53824.00   0.093329   0.289748  -0.6705733    0.000000    0.000000    0.0000000
+53825.00   0.092429   0.289294  -0.6718669    0.000000    0.000000    0.0000000
+53826.00   0.091526   0.288849  -0.6728283    0.000000    0.000000    0.0000000
+53827.00   0.090620   0.288412  -0.6734571    0.000000    0.000000    0.0000000
+53828.00   0.089711   0.287983  -0.6737357    0.000000    0.000000    0.0000000
+53829.00   0.088800   0.287563  -0.6738183    0.000000    0.000000    0.0000000
+53830.00   0.087887   0.287152  -0.6737775    0.000000    0.000000    0.0000000
+53831.00   0.086972   0.286749  -0.6737327    0.000000    0.000000    0.0000000
+53832.00   0.086055   0.286354  -0.6738200    0.000000    0.000000    0.0000000
+53833.00   0.085136   0.285968  -0.6741178    0.000000    0.000000    0.0000000
+53834.00   0.084216   0.285590  -0.6746694    0.000000    0.000000    0.0000000
+53835.00   0.083295   0.285220  -0.6753979    0.000000    0.000000    0.0000000
+53836.00   0.082373   0.284859  -0.6763123    0.000000    0.000000    0.0000000
+53837.00   0.081450   0.284507  -0.6773890    0.000000    0.000000    0.0000000
+53838.00   0.080527   0.284162  -0.6784682    0.000000    0.000000    0.0000000
+53839.00   0.079604   0.283826  -0.6795676    0.000000    0.000000    0.0000000
+53840.00   0.078680   0.283498  -0.6805828    0.000000    0.000000    0.0000000
+53841.00   0.077756   0.283179  -0.6814142    0.000000    0.000000    0.0000000
+53842.00   0.076833   0.282868  -0.6821005    0.000000    0.000000    0.0000000
+53843.00   0.075910   0.282565  -0.6826011    0.000000    0.000000    0.0000000
+53844.00   0.074987   0.282270  -0.6829987    0.000000    0.000000    0.0000000
+53845.00   0.074066   0.281984  -0.6833576    0.000000    0.000000    0.0000000
+53846.00   0.073145   0.281707  -0.6838171    0.000000    0.000000    0.0000000
+53847.00   0.072226   0.281437  -0.6844564    0.000000    0.000000    0.0000000
+53848.00   0.071307   0.281176  -0.6853447    0.000000    0.000000    0.0000000
+53849.00   0.070391   0.280924  -0.6864878    0.000000    0.000000    0.0000000
+53850.00   0.069476   0.280680  -0.6878293    0.000000    0.000000    0.0000000
+53851.00   0.068563   0.280444  -0.6892386    0.000000    0.000000    0.0000000
+53852.00   0.067651   0.280217  -0.6905256    0.000000    0.000000    0.0000000
+53853.00   0.066742   0.279998  -0.6915469    0.000000    0.000000    0.0000000
+53854.00   0.065836   0.279787  -0.6922592    0.000000    0.000000    0.0000000
+53855.00   0.064931   0.279586  -0.6926365    0.000000    0.000000    0.0000000
+53856.00   0.064030   0.279392  -0.6927103    0.000000    0.000000    0.0000000
+53857.00   0.063131   0.279208  -0.6925860    0.000000    0.000000    0.0000000
+53858.00   0.062235   0.279032  -0.6923453    0.000000    0.000000    0.0000000
+53859.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53860.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53861.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53862.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53863.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53864.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53865.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53866.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53867.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53868.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53869.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53870.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53871.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53872.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53873.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53874.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53875.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53876.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53877.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53878.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53879.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53880.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53881.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53882.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53883.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53884.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53885.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53886.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53887.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53888.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53889.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53890.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53891.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53892.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53893.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53894.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53895.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53896.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53897.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53898.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53899.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53900.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53901.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53902.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53903.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53904.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53905.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53906.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53907.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
+53908.00   0.000000   0.000000   0.0000000    0.000000    0.000000    0.0000000
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/finals_all.raw
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/finals_all.raw	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/finals_all.raw	(revision 22158)
@@ -0,0 +1,11994 @@
+73 1 2 41684.00 I   .120724  .009786   .137066  .015902  I  .8084319  .0002710  0.0000 0.1916  P    44.969     .500     2.839     .300   .143000   .137000   .8075000      .000      .000  
+73 1 3 41685.00 I   .118971  .011039   .135756  .013616  I  .8056304  .0002710  3.5563 0.1916  P    45.005     .500     2.762     .300   .141000   .134000   .8044000      .000      .000  
+73 1 4 41686.00 I   .117218  .011039   .134448  .013616  I  .8028036  .0002710  2.6599 0.1916  P    45.122     .500     2.851     .300   .139000   .131000   .8012000      .000      .000  
+73 1 5 41687.00 I   .115464  .009743   .133144  .013089  I  .7998870  .0002710  3.0344 0.1916  P    45.344     .500     3.020     .300   .137000   .128000   .7981000      .000      .000  
+73 1 6 41688.00 I   .113708  .011236   .131846  .009898  I  .7968285  .0002710  3.1276 0.1916  P    45.623     .500     3.115     .300   .136000   .126000   .7949000      .000      .000  
+73 1 7 41689.00 I   .111948  .012506   .130558  .009144  I  .7935963  .0002710  3.3271 0.1916  P    45.812     .500     3.086     .300   .134000   .123000   .7918000      .000      .000  
+73 1 8 41690.00 I   .110180  .012042   .129282  .008563  I  .7901851  .0002710  3.4940 0.1916  P    45.804     .500     3.014     .300   .132000   .122000   .7887000      .000      .000  
+73 1 9 41691.00 I   .108401  .011753   .128020  .007670  I  .7866194  .0002710  3.6275 0.1916  P    45.647     .500     2.993     .300   .130000   .120000   .7855000      .000      .000  
+73 110 41692.00 I   .106607  .011233   .126775  .007850  I  .7829530  .0002710  3.6924 0.2189  P    45.466     .500     3.049     .300   .128000   .119000   .7824000      .000      .000  
+73 111 41693.00 I   .104795  .010595   .125551  .006952  I  .7792628  .0003439  3.6729 0.2373  P    45.326     .500     3.164     .300   .126000   .117000   .7792000      .000      .000  
+73 112 41694.00 I   .102960  .012040   .124351  .004628  I  .7756359  .0003895  3.5674 0.2632  P    45.177     .500     3.328     .300   .124000   .116000   .7761000      .000      .000  
+73 113 41695.00 I   .101103  .017283   .123180  .014244  I  .7721500  .0003986  3.3960 0.2787  P    44.931     .500     3.504     .300   .122000   .114000   .7730000      .000      .000  
+73 114 41696.00 I   .099219  .017776   .122040  .016032  I  .7688519  .0003986  3.2007 0.2819  P    44.607     .500     3.585     .300   .120000   .113000   .7698000      .000      .000  
+73 115 41697.00 I   .097304  .020404   .120936  .014510  I  .7657376  .0003986  3.0383 0.2819  P    44.381     .500     3.456     .300   .118000   .111000   .7667000      .000      .000  
+73 116 41698.00 I   .095355  .022714   .119870  .016602  I  .7627466  .0003986  2.9620 0.2917  P    44.444     .500     3.159     .300   .116000   .110000   .7635000      .000      .000  
+73 117 41699.00 I   .093368  .024425   .118846  .015222  I  .7597749  .0004261  3.0019 0.3035  P    44.789     .500     2.911     .300   .114000   .108000   .7604000      .000      .000  
+73 118 41700.00 I   .091341  .027783   .117865  .017497  I  .7567072  .0004579  3.1486 0.3214  P    45.213     .500     2.902     .300   .112000   .106000   .7573000      .000      .000  
+73 119 41701.00 I   .089273  .027006   .116926  .020543  I  .7534582  .0004814  3.3540 0.3322  P    45.571     .500     3.082     .300   .110000   .105000   .7541000      .000      .000  
+73 120 41702.00 I   .087167  .026817   .116031  .017708  I  .7500021  .0004814  3.5509 0.3404  P    45.880     .500     3.232     .300   .107000   .103000   .7510000      .000      .000  
+73 121 41703.00 I   .085025  .023253   .115178  .016235  I  .7463792  .0004814  3.6794 0.3404  P    46.144     .500     3.212     .300   .105000   .102000   .7478000      .000      .000  
+73 122 41704.00 I   .082853  .021951   .114370  .018104  I  .7426762  .0004814  3.7090 0.2762  P    46.215     .500     3.080     .300   .103000   .100000   .7447000      .000      .000  
+73 123 41705.00 I   .080657  .020859   .113605  .016592  I  .7389931  .0002710  3.6428 0.2762  P    45.986     .500     2.953     .300   .101000   .098000   .7415000      .000      .000  
+73 124 41706.00 I   .078440  .017339   .112884  .018269  I  .7354139  .0002710  3.5067 0.1916  P    45.602     .500     2.872     .300   .099000   .097000   .7383000      .000      .000  
+73 125 41707.00 I   .076205  .015190   .112202  .018414  I  .7319919  .0002710  3.3338 0.1916  P    45.321     .500     2.830     .300   .096000   .095000   .7352000      .000      .000  
+73 126 41708.00 I   .073954  .010350   .111559  .013984  I  .7287489  .0002710  3.1530 0.1916  P    45.204     .500     2.845     .300   .094000   .094000   .7320000      .000      .000  
+73 127 41709.00 I   .071691  .011387   .110952  .013008  I  .7256811  .0002710  2.9868 0.1916  P    45.127     .500     2.911     .300   .092000   .092000   .7288000      .000      .000  
+73 128 41710.00 I   .069420  .013080   .110378  .013702  I  .7227643  .0002710  2.8538 0.1916  P    45.037     .500     2.932     .300   .090000   .091000   .7256000      .000      .000  
+73 129 41711.00 I   .067147  .011392   .109836  .011893  I  .7199568  .0002710  2.7710 0.1916  P    45.034     .500     2.807     .300   .088000   .089000   .7224000      .000      .000  
+73 130 41712.00 I   .064874  .008644   .109325  .012216  I  .7172012  .0002710  2.7515 0.1916  P    45.159     .500     2.575     .300   .086000   .088000   .7193000      .000      .000  
+73 131 41713.00 I   .062607  .007486   .108846  .010740  I  .7144307  .0002710  2.8012 0.1916  P    45.302     .500     2.396     .300   .084000   .087000   .7161000      .000      .000  
+73 2 1 41714.00 I   .060349  .008228   .108400  .005952  I  .7115769  .0002710  2.9167 0.1916  P    45.368     .500     2.374     .300   .082000   .086000   .7129000      .000      .000  
+73 2 2 41715.00 I   .058100  .008273   .107987  .006132  I  .7085797  .0002710  3.0849 0.1916  P    45.424     .500     2.457     .300   .079000   .084000   .7096000      .000      .000  
+73 2 3 41716.00 I   .055865  .005051   .107608  .004481  I  .7053972  .0002710  3.2828 0.1916  P    45.573     .500     2.528     .300   .077000   .083000   .7063000      .000      .000  
+73 2 4 41717.00 I   .053644  .005684   .107263  .004652  I  .7020146  .0002710  3.4793 0.1916  P    45.777     .500     2.546     .300   .075000   .082000   .7031000      .000      .000  
+73 2 5 41718.00 I   .051441  .006413   .106954  .005294  I  .6984511  .0002710  3.6385 0.1916  P    45.873     .500     2.551     .300   .073000   .080000   .6998000      .000      .000  
+73 2 6 41719.00 I   .049257  .009371   .106681  .005496  I  .6947614  .0002710  3.7265 0.1916  P    45.754     .500     2.591     .300   .071000   .079000   .6965000      .000      .000  
+73 2 7 41720.00 I   .047093  .010820   .106442  .005977  I  .6910290  .0002710  3.7218 0.1916  P    45.463     .500     2.668     .300   .069000   .080000   .6932000      .000      .000  
+73 2 8 41721.00 I   .044951  .009430   .106239  .005536  I  .6873489  .0002710  3.6237 0.1916  P    45.133     .500     2.756     .300   .067000   .081000   .6899000      .000      .000  
+73 2 9 41722.00 I   .042831  .009747   .106070  .005115  I  .6838052  .0002710  3.4547 0.1916  P    44.868     .500     2.829     .300   .066000   .082000   .6866000      .000      .000  
+73 210 41723.00 I   .040732  .009517   .105935  .009579  I  .6804490  .0002710  3.2572 0.1916  P    44.688     .500     2.858     .300   .064000   .083000   .6833000      .000      .000  
+73 211 41724.00 I   .038653  .010158   .105832  .010657  I  .6772827  .0002710  3.0839 0.1916  P    44.561     .500     2.796     .300   .062000   .085000   .6800000      .000      .000  
+73 212 41725.00 I   .036593  .008858   .105760  .010542  I  .6742568  .0002710  2.9836 0.2290  P    44.488     .500     2.592     .300   .060000   .086000   .6767000      .000      .000  
+73 213 41726.00 I   .034550  .005354   .105717  .011659  I  .6712808  .0003693  2.9872 0.2290  P    44.523     .500     2.256     .300   .058000   .087000   .6734000      .000      .000  
+73 214 41727.00 I   .032521  .014261   .105702  .013368  I  .6682469  .0003693  3.0973 0.2611  P    44.706     .500     1.910     .300   .057000   .088000   .6701000      .000      .000  
+73 215 41728.00 I   .030505  .016421   .105715  .015269  I  .6650607  .0003693  3.2841 0.2611  P    45.014     .500     1.740     .300   .055000   .089000   .6668000      .000      .000  
+73 216 41729.00 I   .028503  .014294   .105755  .013263  I  .6616712  .0003693  3.4936 0.2611  P    45.369     .500     1.834     .300   .053000   .090000   .6635000      .000      .000  
+73 217 41730.00 I   .026512  .015706   .105824  .011762  I  .6580860  .0003693  3.6657 0.2611  P    45.690     .500     2.090     .300   .051000   .091000   .6601000      .000      .000  
+73 218 41731.00 I   .024531  .020115   .105922  .013465  I  .6543676  .0003693  3.7543 0.2290  P    45.896     .500     2.292     .300   .049000   .092000   .6568000      .000      .000  
+73 219 41732.00 I   .022556  .023196   .106048  .014393  I  .6506111  .0002710  3.7418 0.2290  P    45.915     .500     2.292     .300   .047000   .093000   .6534000      .000      .000  
+73 220 41733.00 I   .020582  .020204   .106203  .013455  I  .6469136  .0002710  3.6403 0.1916  P    45.743     .500     2.108     .300   .045000   .094000   .6501000      .000      .000  
+73 221 41734.00 I   .018606  .017371   .106384  .011791  I  .6433499  .0002710  3.4804 0.1916  P    45.478     .500     1.871     .300   .044000   .095000   .6467000      .000      .000  
+73 222 41735.00 I   .016623  .015060   .106592  .011458  I  .6399606  .0002710  3.2971 0.1916  P    45.236     .500     1.717     .300   .042000   .096000   .6433000      .000      .000  
+73 223 41736.00 I   .014632  .017310   .106828  .013177  I  .6367535  .0002710  3.1203 0.1916  P    45.062     .500     1.699     .300   .040000   .097000   .6400000      .000      .000  
+73 224 41737.00 I   .012634  .015302   .107093  .012172  I  .6337102  .0002710  2.9728 0.1916  P    44.960     .500     1.744     .300   .038000   .098000   .6366000      .000      .000  
+73 225 41738.00 I   .010628  .004408   .107386  .009703  I  .6307923  .0002710  2.8720 0.1916  P    44.978     .500     1.702     .300   .036000   .099000   .6333000      .000      .000  
+73 226 41739.00 I   .008615  .006024   .107709  .009450  I  .6279462  .0002710  2.8311 0.1916  P    45.179     .500     1.485     .300   .034000   .100000   .6299000      .000      .000  
+73 227 41740.00 I   .006593  .006496   .108060  .009211  I  .6251074  .0002710  2.8582 0.1916  P    45.518     .500     1.180     .300   .032000   .101000   .6265000      .000      .000  
+73 228 41741.00 I   .004564  .012724   .108438  .011717  I  .6222069  .0002710  2.9540 0.1916  P    45.826     .500      .966     .300   .030000   .102000   .6232000      .000      .000  
+73 3 1 41742.00 I   .002526  .014671   .108842  .012126  I  .6191790  .0002710  3.1108 0.1916  P    45.957     .500      .925     .300   .028000   .102000   .6198000      .000      .000  
+73 3 2 41743.00 I   .000479  .013161   .109270  .011853  I  .6159706  .0002710  3.3115 0.1916  P    45.948     .500      .981     .300   .026000   .103000   .6165000      .000      .000  
+73 3 3 41744.00 I  -.001578  .014776   .109721  .012783  I  .6125505  .0002710  3.5288 0.1916  P    45.972     .500     1.036     .300   .024000   .104000   .6131000      .000      .000  
+73 3 4 41745.00 I  -.003643  .012867   .110195  .012062  I  .6089196  .0002710  3.7263 0.1916  P    46.134     .500     1.098     .300   .022000   .105000   .6097000      .000      .000  
+73 3 5 41746.00 I  -.005713  .013849   .110692  .013003  I  .6051180  .0002710  3.8634 0.1916  P    46.333     .500     1.230     .300   .020000   .106000   .6063000      .000      .000  
+73 3 6 41747.00 I  -.007786  .018598   .111214  .011377  I  .6012241  .0002710  3.9064 0.1916  P    46.349     .500     1.411     .300   .018000   .106000   .6030000      .000      .000  
+73 3 7 41748.00 I  -.009857  .016956   .111761  .008623  I  .5973410  .0002710  3.8419 0.1916  P    46.073     .500     1.530     .300   .016000   .107000   .5996000      .000      .000  
+73 3 8 41749.00 I  -.011922  .014730   .112336  .010019  I  .5935706  .0002710  3.6865 0.1916  P    45.630     .500     1.491     .300   .014000   .108000   .5962000      .000      .000  
+73 3 9 41750.00 I  -.013977  .016541   .112940  .009673  I  .5899833  .0002710  3.4851 0.1916  P    45.282     .500     1.305     .300   .012000   .109000   .5928000      .000      .000  
+73 310 41751.00 I  -.016019  .027845   .113573  .009673  I  .5865962  .0002710  3.2964 0.1916  P    45.200     .500     1.053     .300   .009000   .109000   .5893000      .000      .000  
+73 311 41752.00 I  -.018040  .032115   .114237  .009720  I  .5833682  .0002710  3.1747 0.4760  P    45.348     .500      .809     .300   .007000   .110000   .5859000      .000      .000  
+73 312 41753.00 I  -.020032  .035235   .114933  .012152  I  .5802133  .0009126  3.1535 0.4760  P    45.567     .500      .583     .300   .004000   .111000   .5824000      .000      .000  
+73 313 41754.00 I  -.021990  .037228   .115661  .014705  I  .5770261  .0009126  3.2375 0.6453  P    45.749     .500      .342     .300   .002000   .112000   .5790000      .000      .000  
+73 314 41755.00 I  -.023907  .032343   .116421  .014705  I  .5737111  .0009126  3.4032 0.6453  P    45.908     .500      .085     .300   .000000   .112000   .5755000      .000      .000  
+73 315 41756.00 I  -.025780  .037323   .117212  .015938  I  .5702072  .0009126  3.6066 0.6453  P    46.111     .500     -.101     .300  -.003000   .113000   .5720000      .000      .000  
+73 316 41757.00 I  -.027610  .033991   .118036  .018578  I  .5665027  .0009126  3.7956 0.6453  P    46.359     .500     -.097     .300  -.005000   .114000   .5685000      .000      .000  
+73 317 41758.00 I  -.029400  .027934   .118890  .018578  I  .5626361  .0009126  3.9242 0.4760  P    46.565     .500      .113     .300  -.008000   .114000   .5650000      .000      .000  
+73 318 41759.00 I  -.031155  .024244   .119773  .016207  I  .5586838  .0002710  3.9642 0.4760  P    46.646     .500      .377     .300  -.010000   .115000   .5615000      .000      .000  
+73 319 41760.00 I  -.032878  .012640   .120683  .016340  I  .5547386  .0002710  3.9115 0.1916  P    46.625     .500      .491     .300  -.012000   .116000   .5579000      .000      .000  
+73 320 41761.00 I  -.034573  .013809   .121619  .013403  I  .5508857  .0002710  3.7840 0.1916  P    46.599     .500      .371     .300  -.015000   .117000   .5544000      .000      .000  
+73 321 41762.00 I  -.036242  .015665   .122582  .013403  I  .5471853  .0002710  3.6125 0.1916  P    46.602     .500      .123     .300  -.017000   .118000   .5508000      .000      .000  
+73 322 41763.00 I  -.037885  .014168   .123571  .012131  I  .5436641  .0002710  3.4307 0.1916  P    46.573     .500     -.074     .300  -.020000   .119000   .5473000      .000      .000  
+73 323 41764.00 I  -.039504  .010960   .124588  .007128  I  .5403179  .0002710  3.2668 0.1916  P    46.479     .500     -.128     .300  -.022000   .120000   .5437000      .000      .000  
+73 324 41765.00 I  -.041099  .009572   .125635  .010385  I  .5371173  .0002710  3.1424 0.1916  P    46.407     .500     -.113     .300  -.024000   .120000   .5401000      .000      .000  
+73 325 41766.00 I  -.042673  .010897   .126712  .010546  I  .5340153  .0002710  3.0715 0.4939  P    46.482     .500     -.191     .300  -.027000   .121000   .5365000      .000      .000  
+73 326 41767.00 I  -.044229  .010997   .127821  .009188  I  .5309537  .0009499  3.0626 0.4939  P    46.738     .500     -.435     .300  -.029000   .122000   .5330000      .000      .000  
+73 327 41768.00 I  -.045771  .008170   .128964  .010531  I  .5278687  .0009499  3.1181 0.6717  P    47.096     .500     -.719     .300  -.032000   .123000   .5294000      .000      .000  
+73 328 41769.00 I  -.047302  .008769   .130142  .009502  I  .5246976  .0009499  3.2334 0.6717  P    47.439     .500     -.841     .300  -.034000   .124000   .5258000      .000      .000  
+73 329 41770.00 I  -.048828  .008961   .131356  .010189  I  .5213856  .0009499  3.3975 0.6717  P    47.660     .500     -.755     .300  -.036000   .125000   .5222000      .000      .000  
+73 330 41771.00 I  -.050351  .008871   .132605  .008830  I  .5178924  .0009499  3.5920 0.6717  P    47.708     .500     -.619     .300  -.039000   .127000   .5186000      .000      .000  
+73 331 41772.00 I  -.051875  .010144   .133891  .003313  I  .5142009  .0009499  3.7884 0.4939  P    47.656     .500     -.586     .300  -.041000   .128000   .5149000      .000      .000  
+73 4 1 41773.00 I  -.053404  .027169   .135214  .005442  I  .5103278  .0002710  3.9482 0.4939  P    47.657     .500     -.594     .300  -.044000   .129000   .5113000      .000      .000  
+73 4 2 41774.00 I  -.054940  .030688   .136573  .006176  I  .5063304  .0002710  4.0304 0.1916  P    47.755     .500     -.472     .300  -.046000   .131000   .5077000      .000      .000  
+73 4 3 41775.00 I  -.056488  .027434   .137969  .013677  I  .5023026  .0002710  4.0058 0.1916  P    47.777     .500     -.208     .300  -.048000   .132000   .5041000      .000      .000  
+73 4 4 41776.00 I  -.058053  .031109   .139402  .015490  I  .4983553  .0002710  3.8718 0.1916  P    47.525     .500     -.014     .300  -.051000   .133000   .5006000      .000      .000  
+73 4 5 41777.00 I  -.059639  .027250   .140872  .029276  I  .4945843  .0002710  3.6619 0.1916  P    47.067     .500     -.098     .300  -.053000   .134000   .4970000      .000      .000  
+73 4 6 41778.00 I  -.061247  .031072   .142377  .033803  I  .4910366  .0002710  3.4367 0.1916  P    46.721     .500     -.445     .300  -.056000   .136000   .4935000      .000      .000  
+73 4 7 41779.00 I  -.062874  .029203   .143917  .029521  I  .4876939  .0002710  3.2625 0.1355  P    46.735     .500     -.857     .300  -.058000   .137000   .4899000      .000      .000  
+73 4 8 41780.00 I  -.064517  .015992   .145494  .033667  I  .4844787  .0000063  3.1868 0.1368  P    47.048     .500    -1.157     .300  -.061000   .139000   .4864000      .000      .000  
+73 4 9 41781.00 I  -.066174  .014330   .147108  .030260  I  .4812836  .0000370  3.2211 0.0188  P    47.407     .500    -1.310     .300  -.063000   .141000   .4829000      .000      .000  
+73 410 41782.00 I  -.067840  .014560   .148757  .031775  I  .4780073  .0000370  3.3431 0.0262  P    47.621     .500    -1.381     .300  -.066000   .143000   .4794000      .000      .000  
+73 411 41783.00 I  -.069512  .016351   .150437  .027523  I  .4745829  .0000370  3.5087 0.0262  P    47.697     .500    -1.438     .300  -.068000   .145000   .4759000      .000      .000  
+73 412 41784.00 I  -.071188  .018280   .152143  .010351  I  .4709918  .0000370  3.6687 0.0262  P    47.760     .500    -1.487     .300  -.071000   .147000   .4724000      .000      .000  
+73 413 41785.00 I  -.072868  .016606   .153873  .013467  I  .4672608  .0000370  3.7828 0.0319  P    47.893     .500    -1.478     .300  -.073000   .148000   .4689000      .000      .000  
+73 414 41786.00 I  -.074547  .014003   .155619  .014917  I  .4634499  .0000519  3.8256 0.1368  P    48.042     .500    -1.369     .300  -.076000   .150000   .4655000      .000      .000  
+73 415 41787.00 I  -.076226  .012772   .157377  .015513  I  .4596361  .0002710  3.7888 0.1380  P    48.110     .500    -1.192     .300  -.078000   .152000   .4620000      .000      .000  
+73 416 41788.00 I  -.077898  .014123   .159141  .015277  I  .4558961  .0002710  3.6806 0.1916  P    48.103     .500    -1.063     .300  -.081000   .154000   .4586000      .000      .000  
+73 417 41789.00 I  -.079559  .013893   .160904  .013978  I  .4522916  .0002710  3.5222 0.2293  P    48.130     .500    -1.090     .300  -.083000   .156000   .4551000      .000      .000  
+73 418 41790.00 I  -.081206  .010623   .162664  .016129  I  .4488589  .0003700  3.3421 0.2293  P    48.230     .500    -1.274     .300  -.085000   .158000   .4517000      .000      .000  
+73 419 41791.00 I  -.082836  .009813   .164416  .022876  I  .4456047  .0003700  3.1700 0.2320  P    48.307     .500    -1.497     .300  -.086000   .160000   .4483000      .000      .000  
+73 420 41792.00 I  -.084445  .009740   .166159  .023729  I  .4425079  .0002801  3.0308 0.2893  P    48.285     .500    -1.633     .300  -.088000   .162000   .4448000      .000      .000  
+73 421 41793.00 I  -.086031  .008672   .167888  .020834  I  .4395262  .0004449  2.9421 0.2779  P    48.252     .500    -1.673     .300  -.090000   .164000   .4414000      .000      .000  
+73 422 41794.00 I  -.087594  .008879   .169602  .021918  I  .4366037  .0004801  2.9133 0.3093  P    48.328     .500    -1.729     .300  -.092000   .166000   .4380000      .000      .000  
+73 423 41795.00 I  -.089132  .007702   .171299  .022632  I  .4336788  .0004298  2.9468 0.3268  P    48.496     .500    -1.890     .300  -.093000   .168000   .4346000      .000      .000  
+73 424 41796.00 I  -.090646  .004604   .172977  .025609  I  .4306908  .0004434  3.0381 0.3088  P    48.672     .500    -2.069     .300  -.095000   .170000   .4312000      .000      .000  
+73 425 41797.00 I  -.092135  .013391   .174637  .022861  I  .4275866  .0004434  3.1773 0.3362  P    48.855     .500    -2.076     .300  -.097000   .172000   .4277000      .000      .000  
+73 426 41798.00 I  -.093600  .014952   .176280  .016101  I  .4243250  .0005055  3.3502 0.3006  P    49.072     .500    -1.865     .300  -.098000   .174000   .4243000      .000      .000  
+73 427 41799.00 I  -.095039  .017996   .177908  .016389  I  .4208818  .0004060  3.5365 0.2535  P    49.227     .500    -1.639     .300  -.100000   .176000   .4209000      .000      .000  
+73 428 41800.00 I  -.096452  .020007   .179524  .018068  I  .4172571  .0000402  3.7076 0.2441  P    49.192     .500    -1.624     .300  -.101000   .178000   .4175000      .000      .000  
+73 429 41801.00 I  -.097839  .022840   .181129  .016125  I  .4134837  .0002710  3.8275 0.1370  P    49.002     .500    -1.766     .300  -.102000   .180000   .4141000      .000      .000  
+73 430 41802.00 I  -.099202  .024995   .182728  .013615  I  .4096311  .0002710  3.8605 0.1916  P    48.804     .500    -1.785     .300  -.103000   .181000   .4108000      .000      .000  
+73 5 1 41803.00 I  -.100543  .024464   .184322  .016261  I  .4057984  .0002710  3.7865 0.1916  P    48.609     .500    -1.553     .300  -.104000   .183000   .4074000      .000      .000  
+73 5 2 41804.00 I  -.101860  .024278   .185910  .017034  I  .4020902  .0002710  3.6163 0.1916  P    48.303     .500    -1.283     .300  -.106000   .185000   .4040000      .000      .000  
+73 5 3 41805.00 I  -.103149  .023618   .187492  .015012  I  .3985825  .0002710  3.3961 0.1916  P    47.912     .500    -1.272     .300  -.107000   .187000   .4006000      .000      .000  
+73 5 4 41806.00 I  -.104401  .024214   .189067  .014347  I  .3952917  .0002710  3.1948 0.1916  P    47.676     .500    -1.556     .300  -.108000   .189000   .3972000      .000      .000  
+73 5 5 41807.00 I  -.105607  .021898   .190634  .012515  I  .3921651  .0002710  3.0767 0.1916  P    47.783     .500    -1.901     .300  -.109000   .190000   .3939000      .000      .000  
+73 5 6 41808.00 I  -.106760  .019623   .192195  .012981  I  .3891000  .0002710  3.0734 0.1916  P    48.144     .500    -2.105     .300  -.110000   .192000   .3905000      .000      .000  
+73 5 7 41809.00 I  -.107853  .019807   .193751  .012218  I  .3859841  .0002710  3.1727 0.1916  P    48.506     .500    -2.159     .300  -.111000   .194000   .3871000      .000      .000  
+73 5 8 41810.00 I  -.108882  .018586   .195303  .006619  I  .3827358  .0002710  3.3283 0.1423  P    48.682     .500    -2.135     .300  -.112000   .196000   .3838000      .000      .000  
+73 5 9 41811.00 I  -.109843  .017897   .196854  .007580  I  .3793280  .0000870  3.4823 0.1423  P    48.646     .500    -2.059     .300  -.112000   .198000   .3805000      .000      .000  
+73 510 41812.00 I  -.110735  .016515   .198402  .008142  I  .3757875  .0000870  3.5875 0.0615  P    48.495     .500    -1.934     .300  -.113000   .200000   .3771000      .000      .000  
+73 511 41813.00 I  -.111557  .014604   .199950  .020486  I  .3721774  .0000870  3.6195 0.0615  P    48.380     .500    -1.805     .300  -.113000   .202000   .3738000      .000      .000  
+73 512 41814.00 I  -.112313  .015209   .201499  .023592  I  .3685739  .0000870  3.5752 0.0615  P    48.391     .500    -1.724     .300  -.114000   .204000   .3705000      .000      .000  
+73 513 41815.00 I  -.113006  .013690   .203052  .025493  I  .3650488  .0000870  3.4653 0.0615  P    48.470     .500    -1.681     .300  -.114000   .205000   .3672000      .000      .000  
+73 514 41816.00 I  -.113643  .010576   .204611  .028913  I  .3616590  .0000870  3.3082 0.1423  P    48.493     .500    -1.642     .300  -.115000   .207000   .3640000      .000      .000  
+73 515 41817.00 I  -.114229  .015352   .206179  .026139  I  .3584406  .0002710  3.1264 0.1274  P    48.429     .500    -1.642     .300  -.115000   .209000   .3607000      .000      .000  
+73 516 41818.00 I  -.114769  .015251   .207756  .029634  I  .3554062  .0002395  2.9444 0.1808  P    48.338     .500    -1.764     .300  -.116000   .211000   .3575000      .000      .000  
+73 517 41819.00 I  -.115267  .018306   .209342  .025695  I  .3525437  .0002395  2.7866 0.1694  P    48.257     .500    -2.005     .300  -.116000   .213000   .3542000      .000      .000  
+73 518 41820.00 I  -.115729  .020861   .210937  .019673  I  .3498182  .0002395  2.6733 0.1694  P    48.190     .500    -2.232     .300  -.116000   .214000   .3510000      .000      .000  
+73 519 41821.00 I  -.116160  .018243   .212543  .019925  I  .3471778  .0002395  2.6178 0.1694  P    48.184     .500    -2.313     .300  -.116000   .216000   .3479000      .000      .000  
+73 520 41822.00 I  -.116560  .020619   .214161  .014814  I  .3445621  .0002395  2.6239 0.1694  P    48.271     .500    -2.270     .300  -.116000   .217000   .3447000      .000      .000  
+73 521 41823.00 I  -.116928  .025576   .215794  .012854  I  .3419107  .0002395  2.6878 0.1808  P    48.355     .500    -2.237     .300  -.116000   .219000   .3416000      .000      .000  
+73 522 41824.00 I  -.117260  .025880   .217446  .012054  I  .3391710  .0002710  2.7983 0.1808  P    48.321     .500    -2.263     .300  -.117000   .220000   .3384000      .000      .000  
+73 523 41825.00 I  -.117551  .022418   .219118  .011225  I  .3363033  .0002710  2.9411 0.1916  P    48.237     .500    -2.235     .300  -.117000   .221000   .3353000      .000      .000  
+73 524 41826.00 I  -.117796  .021351   .220811  .012878  I  .3332839  .0002710  3.0985 0.1916  P    48.279     .500    -2.059     .300  -.117000   .223000   .3321000      .000      .000  
+73 525 41827.00 I  -.117988  .024367   .222526  .012677  I  .3301084  .0002710  3.2495 0.1916  P    48.438     .500    -1.855     .300  -.117000   .224000   .3290000      .000      .000  
+73 526 41828.00 I  -.118122  .027985   .224260  .008483  I  .3267957  .0002710  3.3681 0.1916  P    48.477     .500    -1.837     .300  -.117000   .226000   .3258000      .000      .000  
+73 527 41829.00 I  -.118191  .025031   .226015  .010133  I  .3233929  .0002710  3.4247 0.1916  P    48.233     .500    -2.004     .300  -.117000   .227000   .3227000      .000      .000  
+73 528 41830.00 I  -.118187  .019707   .227791  .011665  I  .3199751  .0002710  3.3949 0.1916  P    47.789     .500    -2.097     .300  -.117000   .228000   .3196000      .000      .000  
+73 529 41831.00 I  -.118104  .017895   .229587  .015466  I  .3166341  .0002710  3.2722 0.1916  P    47.316     .500    -1.928     .300  -.117000   .230000   .3166000      .000      .000  
+73 530 41832.00 I  -.117943  .020656   .231402  .017212  I  .3134538  .0002710  3.0804 0.1916  P    46.906     .500    -1.643     .300  -.117000   .231000   .3135000      .000      .000  
+73 531 41833.00 I  -.117703  .017892   .233238  .016251  I  .3104780  .0002710  2.8745 0.1916  P    46.634     .500    -1.536     .300  -.117000   .233000   .3105000      .000      .000  
+73 6 1 41834.00 I  -.117388  .009540   .235091  .017428  I  .3076868  .0002710  2.7224 0.1916  P    46.601     .500    -1.673     .300  -.117000   .234000   .3074000      .000      .000  
+73 6 2 41835.00 I  -.117002  .008392   .236962  .015311  I  .3049978  .0002710  2.6763 0.1916  P    46.812     .500    -1.851     .300  -.117000   .235000   .3044000      .000      .000  
+73 6 3 41836.00 I  -.116549  .006454   .238846  .015736  I  .3022950  .0002710  2.7478 0.1916  P    47.124     .500    -1.909     .300  -.117000   .237000   .3014000      .000      .000  
+73 6 4 41837.00 I  -.116036  .013487   .240738  .014724  I  .2994746  .0002710  2.9021 0.1916  P    47.384     .500    -1.899     .300  -.117000   .238000   .2984000      .000      .000  
+73 6 5 41838.00 I  -.115466  .014280   .242636  .010305  I  .2964846  .0002710  3.0751 0.1916  P    47.513     .500    -1.906     .300  -.117000   .240000   .2954000      .000      .000  
+73 6 6 41839.00 I  -.114846  .019850   .244536  .009134  I  .2933393  .0002710  3.2035 0.2630  P    47.430     .500    -1.863     .300  -.117000   .241000   .2924000      .000      .000  
+73 6 7 41840.00 I  -.114180  .022917   .246436  .007441  I  .2901054  .0004509  3.2485 0.2630  P    47.075     .500    -1.675     .300  -.117000   .243000   .2895000      .000      .000  
+73 6 8 41841.00 I  -.113474  .022825   .248333  .011421  I  .2868723  .0004509  3.2035 0.3188  P    46.583     .500    -1.423     .300  -.116000   .245000   .2865000      .000      .000  
+73 6 9 41842.00 I  -.112728  .026302   .250227  .012847  I  .2837227  .0004509  3.0857 0.3188  P    46.250     .500    -1.296     .300  -.116000   .246000   .2836000      .000      .000  
+73 610 41843.00 I  -.111943  .023501   .252117  .012077  I  .2807165  .0004509  2.9212 0.3188  P    46.209     .500    -1.348     .300  -.116000   .248000   .2806000      .000      .000  
+73 611 41844.00 I  -.111124  .023142   .254000  .012371  I  .2778874  .0004509  2.7353 0.3188  P    46.255     .500    -1.447     .300  -.116000   .250000   .2777000      .000      .000  
+73 612 41845.00 I  -.110279  .021487   .255878  .017632  I  .2752458  .0004509  2.5498 0.2630  P    46.116     .500    -1.494     .300  -.115000   .252000   .2748000      .000      .000  
+73 613 41846.00 I  -.109416  .017151   .257745  .020236  I  .2727809  .0002710  2.3851 0.2630  P    45.778     .500    -1.564     .300  -.115000   .254000   .2720000      .000      .000  
+73 614 41847.00 I  -.108543  .016601   .259600  .018843  I  .2704624  .0002710  2.2600 0.3157  P    45.432     .500    -1.753     .300  -.115000   .255000   .2691000      .000      .000  
+73 615 41848.00 I  -.107669  .014071   .261438  .018838  I  .2682428  .0005702  2.1893 0.3157  P    45.234     .500    -1.978     .300  -.114000   .257000   .2663000      .000      .000  
+73 616 41849.00 I  -.106798  .025101   .263258  .017549  I  .2660632  .0005702  2.1806 0.4032  P    45.208     .500    -2.043     .300  -.114000   .259000   .2634000      .000      .000  
+73 617 41850.00 I  -.105935  .028203   .265060  .019524  I  .2638618  .0005702  2.2315 0.4032  P    45.288     .500    -1.886     .300  -.113000   .261000   .2607000      .000      .000  
+73 618 41851.00 I  -.105082  .027314   .266846  .017249  I  .2615839  .0005702  2.3313 0.4032  P    45.332     .500    -1.668     .300  -.112000   .263000   .2580000      .000      .000  
+73 619 41852.00 I  -.104241  .030244   .268620  .011627  I  .2591881  .0005702  2.4643 0.4032  P    45.194     .500    -1.573     .300  -.111000   .264000   .2552000      .000      .000  
+73 620 41853.00 I  -.103414  .026380   .270385  .014594  I  .2566509  .0005702  2.6107 0.3157  P    44.903     .500    -1.600     .300  -.110000   .266000   .2525000      .000      .000  
+73 621 41854.00 I  -.102602  .029233   .272147  .014833  I  .2539691  .0002710  2.7501 0.3157  P    44.673     .500    -1.617     .300  -.110000   .268000   .2498000      .000      .000  
+73 622 41855.00 I  -.101802  .026309   .273910  .014971  I  .2511601  .0002710  2.8613 0.1784  P    44.646     .500    -1.579     .300  -.109000   .270000   .2472000      .000      .000  
+73 623 41856.00 I  -.101014  .016756   .275678  .015592  I  .2482631  .0002321  2.9228 0.2197  P    44.685     .500    -1.573     .300  -.108000   .272000   .2446000      .000      .000  
+73 624 41857.00 I  -.100233  .014869   .277455  .016456  I  .2453372  .0003459  2.9161 0.2083  P    44.530     .500    -1.640     .300  -.107000   .273000   .2421000      .000      .000  
+73 625 41858.00 I  -.099456  .009771   .279243  .018589  I  .2424569  .0003459  2.8314 0.2446  P    44.084     .500    -1.662     .300  -.106000   .275000   .2395000      .000      .000  
+73 626 41859.00 I  -.098677  .014683   .281043  .020595  I  .2396968  .0003459  2.6795 0.2446  P    43.488     .500    -1.528     .300  -.105000   .277000   .2369000      .000      .000  
+73 627 41860.00 I  -.097889  .016561   .282855  .020415  I  .2371084  .0003459  2.4962 0.2446  P    42.990     .500    -1.336     .300  -.103000   .279000   .2344000      .000      .000  
+73 628 41861.00 I  -.097085  .019212   .284679  .018761  I  .2346963  .0003459  2.3374 0.2762  P    42.793     .500    -1.289     .300  -.102000   .281000   .2320000      .000      .000  
+73 629 41862.00 I  -.096256  .020588   .286516  .019760  I  .2324062  .0004307  2.2610 0.2197  P    42.935     .500    -1.412     .300  -.100000   .282000   .2295000      .000      .000  
+73 630 41863.00 I  -.095395  .021457   .288366  .017237  I  .2301356  .0002710  2.3006 0.2544  P    43.238     .500    -1.515     .300  -.099000   .284000   .2271000      .000      .000  
+73 7 1 41864.00 I  -.094499  .024493   .290226  .016679  I  .2277697  .0002710  2.4460 0.1916  P    43.467     .500    -1.477     .300  -.097000   .286000   .2246000      .000      .000  
+73 7 2 41865.00 I  -.093566  .021929   .292091  .016416  I  .2252259  .0002710  2.6446 0.1916  P    43.568     .500    -1.406     .300  -.095000   .288000   .2223000      .000      .000  
+73 7 3 41866.00 I  -.092596  .021194   .293957  .011802  I  .2224869  .0002710  2.8242 0.1916  P    43.619     .500    -1.435     .300  -.094000   .290000   .2200000      .000      .000  
+73 7 4 41867.00 I  -.091588  .019350   .295818  .011256  I  .2196042  .0002710  2.9239 0.1916  P    43.555     .500    -1.481     .300  -.092000   .291000   .2177000      .000      .000  
+73 7 5 41868.00 I  -.090547  .016774   .297669  .010791  I  .2166747  .0002710  2.9169 0.1916  P    43.148     .500    -1.365     .300  -.091000   .293000   .2154000      .000      .000  
+73 7 6 41869.00 I  -.089478  .016849   .299504  .009358  I  .2138025  .0002710  2.8135 0.1916  P    42.410     .500    -1.110     .300  -.089000   .295000   .2131000      .000      .000  
+73 7 7 41870.00 I  -.088387  .013730   .301319  .010540  I  .2110689  .0002710  2.6464 0.1916  P    41.750     .500     -.951     .300  -.087000   .296000   .2108000      .000      .000  
+73 7 8 41871.00 I  -.087280  .019979   .303108  .012764  I  .2085187  .0002710  2.4524 0.1916  P    41.540     .500    -1.025     .300  -.085000   .298000   .2085000      .000      .000  
+73 7 9 41872.00 I  -.086167  .022157   .304868  .011666  I  .2061633  .0002710  2.2609 0.1916  P    41.654     .500    -1.203     .300  -.083000   .299000   .2062000      .000      .000  
+73 710 41873.00 I  -.085056  .020893   .306592  .015599  I  .2039890  .0002710  2.0931 0.1916  P    41.661     .500    -1.301     .300  -.081000   .300000   .2039000      .000      .000  
+73 711 41874.00 I  -.083952  .023481   .308278  .017434  I  .2019641  .0002710  1.9644 0.1916  P    41.377     .500    -1.323     .300  -.080000   .302000   .2016000      .000      .000  
+73 712 41875.00 I  -.082861  .021541   .309919  .015936  I  .2000425  .0002710  1.8887 0.1916  P    41.003     .500    -1.397     .300  -.078000   .303000   .1993000      .000      .000  
+73 713 41876.00 I  -.081780  .023470   .311513  .019360  I  .1981661  .0002710  1.8749 0.1916  P    40.774     .500    -1.523     .300  -.076000   .304000   .1970000      .000      .000  
+73 714 41877.00 I  -.080706  .021516   .313057  .017777  I  .1962715  .0002710  1.9246 0.1916  P    40.719     .500    -1.543     .300  -.074000   .305000   .1947000      .000      .000  
+73 715 41878.00 I  -.079639  .008902   .314550  .017736  I  .1942984  .0002710  2.0297 0.1916  P    40.750     .500    -1.368     .300  -.072000   .307000   .1924000      .000      .000  
+73 716 41879.00 I  -.078576  .013383   .315992  .015590  I  .1921991  .0002710  2.1738 0.1916  P    40.772     .500    -1.121     .300  -.070000   .308000   .1901000      .000      .000  
+73 717 41880.00 I  -.077516  .014265   .317382  .006845  I  .1899451  .0002710  2.3351 0.1916  P    40.683     .500    -1.011     .300  -.068000   .309000   .1877000      .000      .000  
+73 718 41881.00 I  -.076456  .012458   .318721  .007667  I  .1875310  .0002710  2.4900 0.1916  P    40.421     .500    -1.103     .300  -.066000   .310000   .1854000      .000      .000  
+73 719 41882.00 I  -.075393  .014120   .320007  .008445  I  .1849750  .0002710  2.6151 0.1916  P    40.073     .500    -1.280     .300  -.064000   .311000   .1830000      .000      .000  
+73 720 41883.00 I  -.074324  .012666   .321240  .007383  I  .1823177  .0002710  2.6896 0.1916  P    39.825     .500    -1.400     .300  -.062000   .312000   .1807000      .000      .000  
+73 721 41884.00 I  -.073249  .013325   .322420  .006510  I  .1796175  .0002710  2.6990 0.1916  P    39.743     .500    -1.425     .300  -.061000   .314000   .1783000      .000      .000  
+73 722 41885.00 I  -.072165  .011720   .323546  .005658  I  .1769433  .0002710  2.6378 0.1916  P    39.684     .500    -1.388     .300  -.059000   .315000   .1759000      .000      .000  
+73 723 41886.00 I  -.071074  .004857   .324618  .005761  I  .1743623  .0002710  2.5156 0.1916  P    39.458     .500    -1.310     .300  -.057000   .316000   .1735000      .000      .000  
+73 724 41887.00 I  -.069974  .007184   .325637  .005914  I  .1719236  .0002710  2.3591 0.1916  P    39.044     .500    -1.212     .300  -.055000   .317000   .1712000      .000      .000  
+73 725 41888.00 I  -.068865  .008084   .326605  .003889  I  .1696410  .0002710  2.2120 0.1916  P    38.635     .500    -1.178     .300  -.053000   .318000   .1688000      .000      .000  
+73 726 41889.00 I  -.067746  .007905   .327521  .003722  I  .1674796  .0002710  2.1251 0.1916  P    38.475     .500    -1.300     .300  -.051000   .319000   .1664000      .000      .000  
+73 727 41890.00 I  -.066615  .008293   .328385  .004136  I  .1653574  .0002710  2.1386 0.1916  P    38.632     .500    -1.529     .300  -.049000   .320000   .1639000      .000      .000  
+73 728 41891.00 I  -.065470  .007735   .329200  .014973  I  .1631654  .0002710  2.2632 0.1916  P    38.911     .500    -1.670     .300  -.047000   .321000   .1615000      .000      .000  
+73 729 41892.00 I  -.064308  .008613   .329966  .017281  I  .1608038  .0002710  2.4692 0.1916  P    39.057     .500    -1.601     .300  -.046000   .322000   .1590000      .000      .000  
+73 730 41893.00 I  -.063127  .009939   .330684  .016150  I  .1582205  .0002710  2.6945 0.1916  P    39.048     .500    -1.422     .300  -.044000   .323000   .1566000      .000      .000  
+73 731 41894.00 I  -.061922  .009300   .331356  .018284  I  .1554320  .0002710  2.8682 0.1916  P    39.042     .500    -1.320     .300  -.042000   .325000   .1541000      .000      .000  
+73 8 1 41895.00 I  -.060690  .008717   .331984  .020554  I  .1525183  .0002710  2.9394 0.1916  P    39.030     .500    -1.312     .300  -.040000   .326000   .1516000      .000      .000  
+73 8 2 41896.00 I  -.059426  .009129   .332571  .023664  I  .1495917  .0002710  2.8952 0.1916  P    38.750     .500    -1.259     .300  -.038000   .327000   .1491000      .000      .000  
+73 8 3 41897.00 I  -.058129  .011588   .333123  .021583  I  .1467587  .0002710  2.7584 0.1916  P    38.079     .500    -1.104     .300  -.037000   .328000   .1467000      .000      .000  
+73 8 4 41898.00 I  -.056796  .012963   .333641  .018419  I  .1440916  .0002710  2.5713 0.1916  P    37.356     .500     -.980     .300  -.035000   .329000   .1442000      .000      .000  
+73 8 5 41899.00 I  -.055426  .012045   .334129  .016004  I  .1416190  .0002710  2.3756 0.1916  P    37.053     .500    -1.016     .300  -.033000   .330000   .1417000      .000      .000  
+73 8 6 41900.00 I  -.054018  .011657   .334587  .017099  I  .1393332  .0002710  2.2017 0.1916  P    37.223     .500    -1.147     .300  -.031000   .331000   .1392000      .000      .000  
+73 8 7 41901.00 I  -.052571  .013442   .335018  .014829  I  .1372021  .0002710  2.0684 0.1916  P    37.493     .500    -1.221     .300  -.030000   .331000   .1368000      .000      .000  
+73 8 8 41902.00 I  -.051087  .015037   .335422  .008011  I  .1351788  .0002710  1.9877 0.1916  P    37.566     .500    -1.207     .300  -.028000   .332000   .1343000      .000      .000  
+73 8 9 41903.00 I  -.049566  .014660   .335801  .007393  I  .1332063  .0002710  1.9680 0.1916  P    37.487     .500    -1.200     .300  -.027000   .333000   .1319000      .000      .000  
+73 810 41904.00 I  -.048009  .013814   .336158  .003430  I  .1312213  .0002710  2.0127 0.1432  P    37.412     .500    -1.241     .300  -.025000   .334000   .1294000      .000      .000  
+73 811 41905.00 I  -.046418  .020502   .336495  .003133  I  .1291610  .0000927  2.1172 0.1747  P    37.363     .500    -1.248     .300  -.023000   .334000   .1269000      .000      .000  
+73 812 41906.00 I  -.044793  .023132   .336814  .003291  I  .1269711  .0002206  2.2690 0.1196  P    37.300     .500    -1.156     .300  -.022000   .335000   .1244000      .000      .000  
+73 813 41907.00 I  -.043138  .020037   .337117  .003063  I  .1246142  .0002206  2.4472 0.1660  P    37.253     .500    -1.025     .300  -.020000   .336000   .1219000      .000      .000  
+73 814 41908.00 I  -.041457  .020744   .337408  .003419  I  .1220762  .0002482  2.6269 0.1660  P    37.235     .500     -.981     .300  -.019000   .336000   .1194000      .000      .000  
+73 815 41909.00 I  -.039753  .019112   .337689  .006789  I  .1193688  .0002482  2.7814 0.1653  P    37.148     .500    -1.064     .300  -.017000   .337000   .1169000      .000      .000  
+73 816 41910.00 I  -.038027  .020655   .337962  .007263  I  .1165303  .0002183  2.8853 0.1749  P    36.897     .500    -1.202     .300  -.016000   .337000   .1144000      .000      .000  
+73 817 41911.00 I  -.036279  .018781   .338231  .008496  I  .1136211  .0002464  2.9204 0.1536  P    36.550     .500    -1.292     .300  -.014000   .337000   .1118000      .000      .000  
+73 818 41912.00 I  -.034509  .010034   .338497  .009743  I  .1107146  .0002161  2.8803 0.1639  P    36.278     .500    -1.285     .300  -.013000   .338000   .1093000      .000      .000  
+73 819 41913.00 I  -.032716  .010358   .338764  .015201  I  .1078820  .0002161  2.7757 0.5275  P    36.167     .500    -1.206     .300  -.011000   .338000   .1067000      .000      .000  
+73 820 41914.00 I  -.030904  .011949   .339034  .017505  I  .1051753  .0010326  2.6347 0.4683  P    36.149     .500    -1.113     .300  -.010000   .338000   .1042000      .000      .000  
+73 821 41915.00 I  -.029072  .010447   .339312  .024151  I  .1026111  .0009113  2.4982 0.7598  P    36.119     .500    -1.077     .300  -.009000   .338000   .1016000      .000      .000  
+73 822 41916.00 I  -.027225  .009422   .339599  .026980  I  .1001622  .0011148  2.4117 0.7199  P    36.066     .500    -1.158     .300  -.007000   .338000   .0990000      .000      .000  
+73 823 41917.00 I  -.025364  .008885   .339898  .024179  I  .0977587  .0011148  2.4123 0.7883  P    36.072     .500    -1.377     .300  -.006000   .339000   .0965000      .000      .000  
+73 824 41918.00 I  -.023491  .007846   .340210  .027130  I  .0953036  .0011148  2.5151 0.7883  P    36.178     .500    -1.657     .300  -.004000   .339000   .0939000      .000      .000  
+73 825 41919.00 I  -.021609  .006916   .340534  .023659  I  .0926991  .0011148  2.7061 0.6328  P    36.302     .500    -1.839     .300  -.003000   .339000   .0913000      .000      .000  
+73 826 41920.00 I  -.019719  .004628   .340866  .023091  I  .0898766  .0005990  2.9415 0.5736  P    36.331     .500    -1.793     .300  -.002000   .339000   .0887000      .000      .000  
+73 827 41921.00 I  -.017823  .009660   .341204  .020004  I  .0868220  .0002710  3.1591 0.3287  P    36.274     .500    -1.543     .300  -.001000   .339000   .0860000      .000      .000  
+73 828 41922.00 I  -.015923  .011031   .341546  .007889  I  .0835842  .0002710  3.2991 0.1916  P    36.251     .500    -1.253     .300   .000000   .339000   .0834000      .000      .000  
+73 829 41923.00 I  -.014024  .013022   .341889  .007631  I  .0802614  .0002710  3.3262 0.1916  P    36.267     .500    -1.065     .300   .001000   .339000   .0807000      .000      .000  
+73 830 41924.00 I  -.012126  .014478   .342230  .005104  I  .0769694  .0002710  3.2406 0.1916  P    36.134     .500     -.987     .300   .003000   .340000   .0781000      .000      .000  
+73 831 41925.00 I  -.010233  .012716   .342570  .006431  I  .0738075  .0002710  3.0733 0.1916  P    35.708     .500     -.958     .300   .004000   .340000   .0754000      .000      .000  
+73 9 1 41926.00 I  -.008345  .014608   .342904  .006697  I  .0708351  .0002710  2.8693 0.3603  P    35.162     .500     -.955     .300   .005000   .340000   .0727000      .000      .000  
+73 9 2 41927.00 I  -.006462  .019669   .343233  .006730  I  .0680673  .0006676  2.6701 0.3603  P    34.859     .500     -.990     .300   .006000   .340000   .0699000      .000      .000  
+73 9 3 41928.00 I  -.004582  .020318   .343554  .007748  I  .0654838  .0006676  2.5044 0.4181  P    34.981     .500    -1.038     .300   .007000   .340000   .0672000      .000      .000  
+73 9 4 41929.00 I  -.002703  .017699   .343867  .007243  I  .0630419  .0005035  2.3887 0.4181  P    35.383     .500    -1.053     .300   .008000   .340000   .0645000      .000      .000  
+73 9 5 41930.00 I  -.000823  .017699   .344170  .007386  I  .0606870  .0005035  2.3314 0.4917  P    35.812     .500    -1.041     .300   .010000   .340000   .0617000      .000      .000  
+73 9 6 41931.00 I   .001061  .015526   .344464  .014265  I  .0583584  .0008448  2.3363 0.4621  P    36.129     .500    -1.055     .300   .011000   .340000   .0589000      .000      .000  
+73 9 7 41932.00 I   .002946  .017760   .344750  .015563  I  .0559943  .0007750  2.4016 0.5844  P    36.294     .500    -1.103     .300   .013000   .341000   .0561000      .000      .000  
+73 9 8 41933.00 I   .004833  .015493   .345026  .013573  I  .0535381  .0008076  2.5182 0.5597  P    36.287     .500    -1.135     .300   .015000   .341000   .0533000      .000      .000  
+73 9 9 41934.00 I   .006719  .004197   .345293  .015169  I  .0509461  .0008076  2.6702 0.6324  P    36.140     .500    -1.123     .300   .017000   .341000   .0505000      .000      .000  
+73 910 41935.00 I   .008606  .003692   .345551  .013815  I  .0481927  .0009735  2.8370 0.6324  P    35.984     .500    -1.115     .300   .018000   .341000   .0476000      .000      .000  
+73 911 41936.00 I   .010491  .003652   .345797  .015639  I  .0452758  .0009735  2.9925 0.5498  P    35.929     .500    -1.153     .300   .020000   .341000   .0447000      .000      .000  
+73 912 41937.00 I   .012375  .007163   .346029  .016450  I  .0422207  .0005113  3.1088 0.5053  P    35.930     .500    -1.203     .300   .022000   .342000   .0418000      .000      .000  
+73 913 41938.00 I   .014258  .007764   .346244  .012001  I  .0390798  .0002710  3.1602 0.3320  P    35.836     .500    -1.194     .300   .023000   .342000   .0389000      .000      .000  
+73 914 41939.00 I   .016138  .006751   .346440  .011191  I  .0359271  .0004237  3.1313 0.3320  P    35.575     .500    -1.110     .300   .025000   .342000   .0360000      .000      .000  
+73 915 41940.00 I   .018015  .007492   .346613  .012790  I  .0328428  .0006062  3.0258 0.3698  P    35.255     .500     -.996     .300   .027000   .342000   .0331000      .000      .000  
+73 916 41941.00 I   .019888  .014443   .346762  .012607  I  .0298925  .0006062  2.8694 0.4286  P    35.063     .500     -.901     .300   .028000   .343000   .0301000      .000      .000  
+73 917 41942.00 I   .021754  .016660   .346884  .013693  I  .0271064  .0006062  2.7058 0.4286  P    35.106     .500     -.851     .300   .030000   .343000   .0272000      .000      .000  
+73 918 41943.00 I   .023611  .015938   .346978  .012071  I  .0244669  .0006062  2.5841 0.4286  P    35.349     .500     -.862     .300   .031000   .344000   .0242000      .000      .000  
+73 919 41944.00 I   .025456  .016842   .347042  .008835  I  .0219114  .0006062  2.5428 0.4803  P    35.671     .500     -.950     .300   .033000   .344000   .0213000      .000      .000  
+73 920 41945.00 I   .027289  .015226   .347074  .009369  I  .0193484  .0007452  2.6000 0.3320  P    35.952     .500    -1.113     .300   .035000   .344000   .0183000      .000      .000  
+73 921 41946.00 I   .029108  .017568   .347072  .009699  I  .0166814  .0002710  2.7470 0.3965  P    36.134     .500    -1.315     .300   .036000   .345000   .0153000      .000      .000  
+73 922 41947.00 I   .030916  .015327   .347036  .010335  I  .0138355  .0002710  2.9505 0.1916  P    36.213     .500    -1.471     .300   .038000   .345000   .0123000      .000      .000  
+73 923 41948.00 I   .032711  .009551   .346966  .009700  I  .0107781  .0002710  3.1609 0.1916  P    36.226     .500    -1.476     .300   .039000   .346000   .0093000      .000      .000  
+73 924 41949.00 I   .034492  .008391   .346860  .011018  I  .0075291  .0002710  3.3253 0.1916  P    36.225     .500    -1.273     .300   .041000   .346000   .0063000      .000      .000  
+73 925 41950.00 I   .036259  .005722   .346719  .012453  I  .0041565  .0002710  3.4029 0.1916  P    36.241     .500     -.933     .300   .042000   .346000   .0033000      .000      .000  
+73 926 41951.00 I   .038008  .005853   .346543  .013390  I  .0007577  .0002710  3.3773 0.1916  P    36.243     .500     -.625     .300   .044000   .346000   .0002000      .000      .000  
+73 927 41952.00 I   .039739  .004493   .346333  .014145  I -.0025677  .0002710  3.2604 0.1916  P    36.159     .500     -.491     .300   .045000   .347000  -.0028000      .000      .000  
+73 928 41953.00 I   .041450  .011754   .346086  .014431  I -.0057439  .0002710  3.0858 0.1916  P    35.950     .500     -.542     .300   .047000   .347000  -.0059000      .000      .000  
+73 929 41954.00 I   .043140  .013403   .345801  .015144  I -.0087342  .0002710  2.8958 0.1916  P    35.683     .500     -.681     .300   .048000   .347000  -.0089000      .000      .000  
+73 930 41955.00 I   .044808  .012719   .345476  .014070  I -.0115428  .0002710  2.7276 0.1916  P    35.517     .500     -.796     .300   .049000   .347000  -.0120000      .000      .000  
+7310 1 41956.00 I   .046453  .014596   .345111  .014007  I -.0142048  .0002710  2.6057 0.1916  P    35.609     .500     -.833     .300   .051000   .347000  -.0151000      .000      .000  
+7310 2 41957.00 I   .048076  .018419   .344705  .012204  I -.0167739  .0002710  2.5431 0.1916  P    36.017     .500     -.814     .300   .052000   .348000  -.0181000      .000      .000  
+7310 3 41958.00 I   .049673  .020963   .344259  .010706  I -.0193120  .0002710  2.5437 0.1916  P    36.629     .500     -.805     .300   .054000   .348000  -.0212000      .000      .000  
+7310 4 41959.00 I   .051242  .019970   .343773  .016288  I -.0218818  .0002710  2.6058 0.1916  P    37.213     .500     -.849     .300   .055000   .348000  -.0243000      .000      .000  
+7310 5 41960.00 I   .052777  .024885   .343248  .021259  I -.0245414  .0002710  2.7215 0.1916  P    37.556     .500     -.911     .300   .057000   .348000  -.0274000      .000      .000  
+7310 6 41961.00 I   .054276  .023456   .342684  .023115  I -.0273383  .0002710  2.8779 0.1916  P    37.600     .500     -.920     .300   .058000   .348000  -.0305000      .000      .000  
+7310 7 41962.00 I   .055736  .021473   .342080  .022267  I -.0303046  .0002710  3.0567 0.1916  P    37.446     .500     -.881     .300   .060000   .347000  -.0336000      .000      .000  
+7310 8 41963.00 I   .057156  .020400   .341436  .021453  I -.0334515  .0002710  3.2351 0.1916  P    37.245     .500     -.885     .300   .061000   .347000  -.0367000      .000      .000  
+7310 9 41964.00 I   .058539  .017609   .340754  .020681  I -.0367661  .0002710  3.3876 0.1916  P    37.102     .500     -.977     .300   .063000   .347000  -.0398000      .000      .000  
+731010 41965.00 I   .059888  .017199   .340035  .024914  I -.0402090  .0002710  3.4871 0.3006  P    37.042     .500    -1.063     .300   .065000   .347000  -.0429000      .000      .000  
+731011 41966.00 I   .061203  .018154   .339282  .022836  I -.0437149  .0005367  3.5103 0.3006  P    37.031     .500    -1.003     .300   .066000   .347000  -.0460000      .000      .000  
+731012 41967.00 I   .062488  .013776   .338497  .020474  I -.0472011  .0005367  3.4479 0.3293  P    37.007     .500     -.791     .300   .068000   .346000  -.0492000      .000      .000  
+731013 41968.00 I   .063742  .014686   .337684  .025127  I -.0505867  .0003817  3.3136 0.3293  P    36.954     .500     -.561     .300   .069000   .346000  -.0523000      .000      .000  
+731014 41969.00 I   .064969  .015228   .336845  .025892  I -.0538171  .0003817  3.1459 0.3118  P    36.937     .500     -.429     .300   .071000   .346000  -.0554000      .000      .000  
+731015 41970.00 I   .066169  .018441   .335980  .025066  I -.0568853  .0004931  2.9987 0.3239  P    37.043     .500     -.391     .300   .072000   .346000  -.0586000      .000      .000  
+731016 41971.00 I   .067343  .019432   .335085  .026019  I -.0598382  .0005235  2.9225 0.3539  P    37.283     .500     -.383     .300   .074000   .345000  -.0618000      .000      .000  
+731017 41972.00 I   .068487  .019507   .334159  .024326  I -.0627630  .0005078  2.9444 0.3950  P    37.574     .500     -.385     .300   .075000   .345000  -.0650000      .000      .000  
+731018 41973.00 I   .069599  .018037   .333202  .025205  I -.0657581  .0005916  3.0595 0.4113  P    37.828     .500     -.427     .300   .077000   .344000  -.0682000      .000      .000  
+731019 41974.00 I   .070676  .018253   .332213  .026705  I -.0689022  .0006471  3.2354 0.4384  P    38.023     .500     -.522     .300   .078000   .344000  -.0714000      .000      .000  
+731020 41975.00 I   .071714  .017726   .331195  .018646  I -.0722334  .0006471  3.4250 0.4562  P    38.185     .500     -.620     .300   .079000   .343000  -.0746000      .000      .000  
+731021 41976.00 I   .072709  .018911   .330147  .019479  I -.0757409  .0006433  3.5806 0.4605  P    38.342     .500     -.634     .300   .081000   .343000  -.0779000      .000      .000  
+731022 41977.00 I   .073660  .017522   .329075  .019560  I -.0793711  .0006554  3.6657 0.4865  P    38.486     .500     -.494     .300   .082000   .342000  -.0811000      .000      .000  
+731023 41978.00 I   .074564  .018102   .327981  .021186  I -.0830434  .0007299  3.6640 0.4405  P    38.559     .500     -.216     .300   .084000   .342000  -.0844000      .000      .000  
+731024 41979.00 I   .075421  .018676   .326871  .008742  I -.0866712  .0005887  3.5787 0.3893  P    38.511     .500      .080     .300   .085000   .341000  -.0876000      .000      .000  
+731025 41980.00 I   .076229  .021565   .325751  .006749  I -.0901797  .0002710  3.4303 0.3240  P    38.369     .500      .243     .300   .086000   .340000  -.0909000      .000      .000  
+731026 41981.00 I   .076990  .019107   .324625  .017092  I -.0935217  .0002710  3.2517 0.1916  P    38.235     .500      .206     .300   .088000   .339000  -.0941000      .000      .000  
+731027 41982.00 I   .077706  .020657   .323499  .018931  I -.0966847  .0002710  3.0779 0.1916  P    38.179     .500      .031     .300   .089000   .339000  -.0974000      .000      .000  
+731028 41983.00 I   .078381  .018058   .322377  .018836  I -.0996889  .0002710  2.9383 0.1916  P    38.212     .500     -.141     .300   .091000   .338000  -.1006000      .000      .000  
+731029 41984.00 I   .079016  .011901   .321265  .021443  I -.1025792  .0002710  2.8522 0.1916  P    38.373     .500     -.207     .300   .092000   .337000  -.1039000      .000      .000  
+731030 41985.00 I   .079614  .010319   .320168  .018574  I -.1054139  .0002710  2.8278 0.1916  P    38.756     .500     -.167     .300   .093000   .336000  -.1072000      .000      .000  
+731031 41986.00 I   .080175  .005485   .319086  .021421  I -.1082551  .0002710  2.8645 0.1916  P    39.353     .500     -.103     .300   .095000   .335000  -.1105000      .000      .000  
+7311 1 41987.00 I   .080703  .006708   .318022  .018887  I -.1111607  .0002710  2.9548 0.1916  P    39.940     .500     -.083     .300   .096000   .335000  -.1139000      .000      .000  
+7311 2 41988.00 I   .081201  .006187   .316975  .011474  I -.1141787  .0002710  3.0870 0.1916  P    40.252     .500     -.079     .300   .098000   .334000  -.1172000      .000      .000  
+7311 3 41989.00 I   .081671  .010329   .315947  .010024  I -.1173433  .0002710  3.2450 0.2907  P    40.248     .500     -.008     .300   .099000   .333000  -.1205000      .000      .000  
+7311 4 41990.00 I   .082118  .011584   .314936  .004394  I -.1206712  .0005143  3.4103 0.2538  P    40.092     .500      .127     .300   .100000   .332000  -.1238000      .000      .000  
+7311 5 41991.00 I   .082543  .010808   .313944  .007728  I -.1241596  .0004293  3.5625 0.3350  P    39.917     .500      .188     .300   .101000   .331000  -.1271000      .000      .000  
+7311 6 41992.00 I   .082951  .012467   .312970  .008912  I -.1277842  .0004293  3.6787 0.3854  P    39.731     .500      .072     .300   .101000   .330000  -.1305000      .000      .000  
+7311 7 41993.00 I   .083347  .014222   .312016  .009978  I -.1314973  .0006403  3.7357 0.3854  P    39.552     .500     -.116     .300   .102000   .329000  -.1338000      .000      .000  
+7311 8 41994.00 I   .083732  .015484   .311082  .010767  I -.1352296  .0006403  3.7148 0.4528  P    39.482     .500     -.147     .300   .103000   .328000  -.1371000      .000      .000  
+7311 9 41995.00 I   .084109  .013649   .310169  .009652  I -.1389005  .0006403  3.6146 0.4348  P    39.596     .500      .060     .300   .104000   .326000  -.1404000      .000      .000  
+731110 41996.00 I   .084479  .012018   .309275  .011041  I -.1424400  .0005883  3.4579 0.4872  P    39.861     .500      .336     .300   .105000   .325000  -.1437000      .000      .000  
+731111 41997.00 I   .084843  .016474   .308399  .010225  I -.1458132  .0007344  3.2918 0.4705  P    40.194     .500      .487     .300   .105000   .324000  -.1470000      .000      .000  
+731112 41998.00 I   .085205  .018447   .307541  .008893  I -.1490397  .0007344  3.1738 0.4760  P    40.509     .500      .512     .300   .106000   .323000  -.1503000      .000      .000  
+731113 41999.00 I   .085567  .016377   .306698  .017613  I -.1521912  .0006057  3.1469 0.4760  P    40.699     .500      .533     .300   .107000   .322000  -.1536000      .000      .000  
+731114 42000.00 I   .085934  .015599   .305868  .018983  I -.1553673  .0006057  3.2212 0.4283  P    40.689     .500      .589     .300   .108000   .321000  -.1569000      .000      .000  
+731115 42001.00 I   .086310  .014034   .305050  .020813  I -.1586579  .0006057  3.3683 0.4692  P    40.555     .500      .593     .300   .108000   .320000  -.1603000      .000      .000  
+731116 42002.00 I   .086696  .015936   .304242  .023860  I -.1621106  .0007168  3.5353 0.4215  P    40.495     .500      .499     .300   .109000   .318000  -.1636000      .000      .000  
+731117 42003.00 I   .087092  .013880   .303442  .021493  I -.1657170  .0005864  3.6676 0.4631  P    40.625     .500      .398     .300   .109000   .317000  -.1670000      .000      .000  
+731118 42004.00 I   .087500  .006283   .302650  .024463  I -.1694219  .0005864  3.7280 0.3230  P    40.870     .500      .418     .300   .110000   .316000  -.1703000      .000      .000  
+731119 42005.00 I   .087923  .005441   .301867  .023066  I -.1731446  .0002710  3.7030 0.3230  P    41.069     .500      .588     .300   .110000   .315000  -.1736000      .000      .000  
+731120 42006.00 I   .088360  .004710   .301092  .019360  I -.1768022  .0002710  3.6008 0.1916  P    41.114     .500      .828     .300   .111000   .314000  -.1768000      .000      .000  
+731121 42007.00 I   .088813  .014519   .300322  .016766  I -.1803275  .0002710  3.4424 0.1916  P    40.995     .500     1.040     .300   .111000   .312000  -.1801000      .000      .000  
+731122 42008.00 I   .089282  .016180   .299559  .012552  I -.1836772  .0002710  3.2544 0.1916  P    40.787     .500     1.161     .300   .112000   .311000  -.1833000      .000      .000  
+731123 42009.00 I   .089767  .014146   .298800  .011093  I -.1868358  .0002710  3.0648 0.1916  P    40.620     .500     1.162     .300   .112000   .310000  -.1866000      .000      .000  
+731124 42010.00 I   .090270  .016245   .298044  .010837  I -.1898150  .0002710  2.8998 0.1916  P    40.598     .500     1.053     .300   .113000   .309000  -.1898000      .000      .000  
+731125 42011.00 I   .090789  .014532   .297288  .009837  I -.1926504  .0002710  2.7800 0.1916  P    40.715     .500      .905     .300   .113000   .308000  -.1930000      .000      .000  
+731126 42012.00 I   .091322  .016780   .296531  .004253  I -.1953941  .0002710  2.7177 0.1916  P    40.934     .500      .829     .300   .114000   .307000  -.1963000      .000      .000  
+731127 42013.00 I   .091866  .014929   .295769  .005106  I -.1981060  .0002710  2.7160 0.1916  P    41.279     .500      .889     .300   .114000   .306000  -.1995000      .000      .000  
+731128 42014.00 I   .092419  .006188   .295002  .005895  I -.2008443  .0002710  2.7689 0.1916  P    41.744     .500     1.032     .300   .115000   .305000  -.2027000      .000      .000  
+731129 42015.00 I   .092978  .006391   .294225  .005109  I -.2036580  .0002710  2.8644 0.1916  P    42.157     .500     1.153     .300   .116000   .303000  -.2059000      .000      .000  
+731130 42016.00 I   .093541  .007031   .293436  .005320  I -.2065818  .0002710  2.9861 0.1916  P    42.298     .500     1.218     .300   .116000   .302000  -.2090000      .000      .000  
+7312 1 42017.00 I   .094106  .009172   .292631  .005126  I -.2096332  .0002710  3.1166 0.1916  P    42.167     .500     1.301     .300   .117000   .301000  -.2122000      .000      .000  
+7312 2 42018.00 I   .094671  .009720   .291809  .004844  I -.2128122  .0002710  3.2385 0.3071  P    41.979     .500     1.442     .300   .117000   .300000  -.2153000      .000      .000  
+7312 3 42019.00 I   .095233  .009484   .290966  .005468  I -.2161014  .0005511  3.3340 0.3071  P    41.860     .500     1.532     .300   .118000   .299000  -.2185000      .000      .000  
+7312 4 42020.00 I   .095789  .010215   .290100  .004816  I -.2194657  .0005511  3.3858 0.3656  P    41.731     .500     1.430     .300   .119000   .298000  -.2217000      .000      .000  
+7312 5 42021.00 I   .096336  .008982   .289208  .010398  I -.2228531  .0004805  3.3777 0.3634  P    41.515     .500     1.201     .300   .120000   .296000  -.2248000      .000      .000  
+7312 6 42022.00 I   .096871  .009560   .288288  .012004  I -.2261984  .0004739  3.3013 0.3374  P    41.311     .500     1.094     .300   .120000   .295000  -.2280000      .000      .000  
+7312 7 42023.00 I   .097393  .011093   .287336  .010844  I -.2294359  .0004739  3.1654 0.4072  P    41.281     .500     1.245     .300   .121000   .293000  -.2311000      .000      .000  
+7312 8 42024.00 I   .097902  .010067   .286351  .012250  I -.2325201  .0006623  3.0022 0.4372  P    41.489     .500     1.491     .300   .122000   .292000  -.2343000      .000      .000  
+7312 9 42025.00 I   .098396  .008771   .285330  .012807  I -.2354485  .0007348  2.8637 0.4946  P    41.900     .500     1.585     .300   .123000   .291000  -.2374000      .000      .000  
+731210 42026.00 I   .098876  .008782   .284272  .014222  I -.2382734  .0007348  2.8029 0.5603  P    42.391     .500     1.508     .300   .124000   .289000  -.2405000      .000      .000  
+731211 42027.00 I   .099341  .012400   .283177  .020406  I -.2410897  .0008460  2.8481 0.7522  P    42.740     .500     1.444     .300   .124000   .288000  -.2436000      .000      .000  
+731212 42028.00 I   .099789  .014205   .282043  .020838  I -.2440007  .0013128  2.9865 0.7558  P    42.751     .500     1.474     .300   .125000   .286000  -.2467000      .000      .000  
+731213 42029.00 I   .100218  .012509   .280870  .021160  I -.2470769  .0012528  3.1677 0.7808  P    42.499     .500     1.469     .300   .126000   .285000  -.2498000      .000      .000  
+731214 42030.00 I   .100626  .011661   .279656  .024172  I -.2503280  .0008456  3.3248 0.7557  P    42.301     .500     1.330     .300   .127000   .283000  -.2528000      .000      .000  
+731215 42031.00 I   .101013  .015848   .278397  .021122  I -.2537002  .0008456  3.4030 0.5979  P    42.358     .500     1.184     .300   .127000   .282000  -.2558000      .000      .000  
+731216 42032.00 I   .101377  .018266   .277095  .022939  I -.2570999  .0008456  3.3791 0.5979  P    42.537     .500     1.228     .300   .128000   .280000  -.2589000      .000      .000  
+731217 42033.00 I   .101720  .016975   .275751  .021608  I -.2604279  .0008456  3.2639 0.5979  P    42.603     .500     1.462     .300   .128000   .279000  -.2619000      .000      .000  
+731218 42034.00 I   .102043  .016009   .274366  .016421  I -.2636073  .0008456  3.0877 0.4271  P    42.509     .500     1.696     .300   .129000   .277000  -.2649000      .000      .000  
+731219 42035.00 I   .102347  .014896   .272944  .016593  I -.2665943  .0001206  2.8847 0.4440  P    42.350     .500     1.793     .300   .129000   .275000  -.2678000      .000      .000  
+731220 42036.00 I   .102630  .017000   .271487  .014296  I -.2693777  .0002710  2.6847 0.1483  P    42.178     .500     1.784     .300   .130000   .274000  -.2708000      .000      .000  
+731221 42037.00 I   .102890  .015245   .270000  .017143  I -.2719721  .0002710  2.5099 0.1916  P    42.000     .500     1.749     .300   .130000   .272000  -.2737000      .000      .000  
+731222 42038.00 I   .103124  .010535   .268487  .019527  I -.2744117  .0002710  2.3775 0.1916  P    41.879     .500     1.690     .300   .131000   .271000  -.2767000      .000      .000  
+731223 42039.00 I   .103328  .009394   .266952  .017178  I -.2767452  .0002710  2.2993 0.1916  P    41.897     .500     1.591     .300   .131000   .269000  -.2796000      .000      .000  
+731224 42040.00 I   .103502  .008193   .265400  .017236  I -.2790302  .0002710  2.2810 0.1916  P    42.071     .500     1.522     .300   .131000   .267000  -.2823000      .000      .000  
+731225 42041.00 I   .103641  .007382   .263832  .015412  I -.2813262  .0002710  2.3199 0.1916  P    42.365     .500     1.587     .300   .131000   .265000  -.2850000      .000      .000  
+731226 42042.00 I   .103746  .005753   .262251  .014806  I -.2836854  .0002710  2.4051 0.1916  P    42.717     .500     1.779     .300   .131000   .263000  -.2876000      .000      .000  
+731227 42043.00 I   .103816  .007123   .260657  .019758  I -.2861463  .0002710  2.5200 0.1916  P    42.993     .500     1.955     .300   .131000   .261000  -.2903000      .000      .000  
+731228 42044.00 I   .103849  .006838   .259051  .018249  I -.2887288  .0002710  2.6451 0.1916  P    43.040     .500     2.006     .300   .131000   .260000  -.2930000      .000      .000  
+731229 42045.00 I   .103845  .006838   .257437  .018249  I -.2914337  .0002710  2.7618 0.1916  P    42.865     .500     1.983     .300   .131000   .258000  -.2952000      .000      .000  
+731230 42046.00 I   .103805  .007755   .255813  .021940  I -.2942442  .0002710  2.8538 0.1916  P    42.663     .500     2.001     .300   .131000   .256000  -.2974000      .000      .000  
+731231 42047.00 I   .103728  .011371   .254183  .021829  I -.2971285  .0002710  2.9073 0.1916  P    42.577     .500     2.053     .300   .131000   .254000  -.2997000      .000      .000  
+74 1 1 42048.00 I   .103613  .013626   .252548  .026179  I  .6999577  .0002710  2.9112 0.1916  P    42.536     .500     2.028     .300   .131000   .252000   .6981000      .000      .000  
+74 1 2 42049.00 I   .103459  .012568   .250912  .023301  I  .6970678  .0002710  2.8589 0.1916  P    42.386     .500     1.917     .300   .131000   .250000   .6959000      .000      .000  
+74 1 3 42050.00 I   .103264  .013605   .249280  .019039  I  .6942575  .0002710  2.7537 0.1916  P    42.104     .500     1.876     .300   .130000   .248000   .6934000      .000      .000  
+74 1 4 42051.00 I   .103028  .012300   .247655  .015546  I  .6915715  .0002710  2.6152 0.1916  P    41.796     .500     2.011     .300   .129000   .246000   .6909000      .000      .000  
+74 1 5 42052.00 I   .102751  .012300   .246038  .015546  I  .6890254  .0002710  2.4818 0.1916  P    41.601     .500     2.176     .300   .129000   .243000   .6885000      .000      .000  
+74 1 6 42053.00 I   .102434  .016881   .244432  .013563  I  .6865897  .0002710  2.4028 0.1916  P    41.651     .500     2.135     .300   .128000   .241000   .6860000      .000      .000  
+74 1 7 42054.00 I   .102077  .017052   .242835  .009469  I  .6841878  .0002710  2.4196 0.1916  P    41.997     .500     1.890     .300   .127000   .239000   .6835000      .000      .000  
+74 1 8 42055.00 I   .101678  .014768   .241249  .009766  I  .6817150  .0002710  2.5430 0.1916  P    42.478     .500     1.691     .300   .126000   .237000   .6807000      .000      .000  
+74 1 9 42056.00 I   .101236  .016019   .239674  .006413  I  .6790766  .0002710  2.7420 0.1916  P    42.808     .500     1.697     .300   .125000   .235000   .6778000      .000      .000  
+74 110 42057.00 I   .100750  .014258   .238110  .011625  I  .6762273  .0002710  2.9521 0.1916  P    42.893     .500     1.772     .300   .125000   .232000   .6750000      .000      .000  
+74 111 42058.00 I   .100222  .015593   .236557  .013423  I  .6731927  .0002710  3.1015 0.1916  P    42.921     .500     1.726     .300   .124000   .230000   .6721000      .000      .000  
+74 112 42059.00 I   .099653  .014280   .235016  .011750  I  .6700606  .0002710  3.1421 0.1916  P    43.036     .500     1.610     .300   .123000   .228000   .6693000      .000      .000  
+74 113 42060.00 I   .099045  .006574   .233489  .013433  I  .6669475  .0002710  3.0656 0.1916  P    43.106     .500     1.629     .300   .122000   .226000   .6666000      .000      .000  
+74 114 42061.00 I   .098399  .006909   .231975  .012772  I  .6639589  .0002710  2.9004 0.1916  P    42.960     .500     1.814     .300   .120000   .224000   .6639000      .000      .000  
+74 115 42062.00 I   .097719  .007977   .230476  .013416  I  .6611611  .0002710  2.6920 0.1916  P    42.702     .500     1.961     .300   .119000   .222000   .6611000      .000      .000  
+74 116 42063.00 I   .097006  .014655   .228990  .012698  I  .6585751  .0002710  2.4830 0.1916  P    42.551     .500     1.913     .300   .118000   .220000   .6584000      .000      .000  
+74 117 42064.00 I   .096261  .016490   .227517  .008714  I  .6561854  .0002710  2.3030 0.1916  P    42.501     .500     1.745     .300   .117000   .218000   .6557000      .000      .000  
+74 118 42065.00 I   .095487  .016116   .226057  .011481  I  .6539538  .0002710  2.1687 0.1916  P    42.372     .500     1.610     .300   .115000   .216000   .6534000      .000      .000  
+74 119 42066.00 I   .094684  .017820   .224609  .013110  I  .6518298  .0002710  2.0890 0.1916  P    42.140     .500     1.530     .300   .114000   .214000   .6511000      .000      .000  
+74 120 42067.00 I   .093852  .019242   .223173  .011397  I  .6497560  .0002710  2.0688 0.1916  P    42.000     .500     1.434     .300   .113000   .212000   .6489000      .000      .000  
+74 121 42068.00 I   .092995  .021755   .221752  .011668  I  .6476724  .0002710  2.1080 0.1916  P    42.095     .500     1.347     .300   .111000   .210000   .6466000      .000      .000  
+74 122 42069.00 I   .092117  .020908   .220345  .012296  I  .6455229  .0002710  2.1986 0.1916  P    42.370     .500     1.385     .300   .110000   .208000   .6443000      .000      .000  
+74 123 42070.00 I   .091222  .018977   .218956  .012906  I  .6432632  .0002710  2.3253 0.1916  P    42.684     .500     1.572     .300   .109000   .207000   .6420000      .000      .000  
+74 124 42071.00 I   .090317  .016800   .217587  .013798  I  .6408669  .0002710  2.4681 0.1916  P    42.926     .500     1.757     .300   .108000   .205000   .6397000      .000      .000  
+74 125 42072.00 I   .089404  .017376   .216242  .012412  I  .6383288  .0002710  2.6054 0.1916  P    43.013     .500     1.775     .300   .106000   .204000   .6375000      .000      .000  
+74 126 42073.00 I   .088485  .015051   .214922  .011651  I  .6356643  .0002710  2.7180 0.1916  P    42.924     .500     1.642     .300   .105000   .202000   .6352000      .000      .000  
+74 127 42074.00 I   .087567  .011222   .213632  .013404  I  .6329062  .0002710  2.7905 0.1916  P    42.756     .500     1.513     .300   .104000   .201000   .6329000      .000      .000  
+74 128 42075.00 I   .086653  .018446   .212376  .011610  I  .6301000  .0002710  2.8129 0.1916  P    42.646     .500     1.491     .300   .103000   .200000   .6302000      .000      .000  
+74 129 42076.00 I   .085750  .018549   .211155  .010691  I  .6272985  .0002710  2.7812 0.1916  P    42.608     .500     1.536     .300   .102000   .198000   .6276000      .000      .000  
+74 130 42077.00 I   .084863  .026563   .209973  .014861  I  .6245540  .0002710  2.7005 0.1715  P    42.526     .500     1.583     .300   .100000   .197000   .6249000      .000      .000  
+74 131 42078.00 I   .083998  .030407   .208833  .014393  I  .6219084  .0002104  2.5873 0.1715  P    42.286     .500     1.647     .300   .099000   .195000   .6223000      .000      .000  
+74 2 1 42079.00 I   .083160  .026385   .207738  .012579  I  .6193803  .0002104  2.4714 0.1488  P    41.889     .500     1.741     .300   .098000   .194000   .6196000      .000      .000  
+74 2 2 42080.00 I   .082351  .030465   .206691  .013566  I  .6169531  .0002104  2.3930 0.1488  P    41.451     .500     1.752     .300   .097000   .193000   .6167000      .000      .000  
+74 2 3 42081.00 I   .081573  .027073   .205695  .015200  I  .6145682  .0002104  2.3930 0.1488  P    41.179     .500     1.531     .300   .096000   .193000   .6139000      .000      .000  
+74 2 4 42082.00 I   .080822  .025486   .204752  .017550  I  .6121330  .0002104  2.4954 0.1488  P    41.248     .500     1.134     .300   .095000   .192000   .6110000      .000      .000  
+74 2 5 42083.00 I   .080096  .022442   .203862  .015936  I  .6095460  .0002104  2.6918 0.1715  P    41.620     .500      .845     .300   .094000   .192000   .6082000      .000      .000  
+74 2 6 42084.00 I   .079390  .008650   .203027  .012589  I  .6067332  .0002710  2.9366 0.1280  P    42.053     .500      .877     .300   .093000   .191000   .6053000      .000      .000  
+74 2 7 42085.00 I   .078702  .009398   .202247  .012669  I  .6036800  .0001457  3.1598 0.1538  P    42.366     .500     1.122     .300   .092000   .190000   .6024000      .000      .000  
+74 2 8 42086.00 I   .078027  .010682   .201524  .014497  I  .6004433  .0001457  3.2939 0.1030  P    42.585     .500     1.301     .300   .091000   .190000   .5996000      .000      .000  
+74 2 9 42087.00 I   .077360  .016646   .200856  .012674  I  .5971340  .0001457  3.3026 0.1030  P    42.752     .500     1.300     .300   .090000   .189000   .5967000      .000      .000  
+74 210 42088.00 I   .076698  .017896   .200241  .009496  I  .5938779  .0001457  3.1920 0.0910  P    42.759     .500     1.237     .300   .089000   .189000   .5939000      .000      .000  
+74 211 42089.00 I   .076036  .015542   .199679  .011080  I  .5907764  .0001091  3.0024 0.0910  P    42.532     .500     1.215     .300   .088000   .188000   .5910000      .000      .000  
+74 212 42090.00 I   .075371  .017324   .199166  .011534  I  .5878817  .0001091  2.7871 0.0601  P    42.258     .500     1.163     .300   .087000   .188000   .5883000      .000      .000  
+74 213 42091.00 I   .074696  .015656   .198701  .010084  I  .5851957  .0000506  2.5912 0.0601  P    42.183     .500      .995     .300   .086000   .187000   .5856000      .000      .000  
+74 214 42092.00 I   .074011  .016848   .198281  .008948  I  .5826839  .0000506  2.4415 0.0358  P    42.254     .500      .768     .300   .086000   .187000   .5830000      .000      .000  
+74 215 42093.00 I   .073312  .017627   .197903  .008805  I  .5802936  .0000506  2.3492 0.0358  P    42.200     .500      .601     .300   .085000   .186000   .5803000      .000      .000  
+74 216 42094.00 I   .072601  .012607   .197565  .009969  I  .5779652  .0000506  2.3177 0.1378  P    41.966     .500      .495     .300   .084000   .186000   .5776000      .000      .000  
+74 217 42095.00 I   .071874  .011069   .197261  .008685  I  .5756383  .0002710  2.3459 0.1378  P    41.819     .500      .369     .300   .083000   .186000   .5750000      .000      .000  
+74 218 42096.00 I   .071131  .012710   .196990  .005202  I  .5732552  .0002710  2.4287 0.1916  P    41.977     .500      .235     .300   .082000   .185000   .5724000      .000      .000  
+74 219 42097.00 I   .070373  .011307   .196746  .005272  I  .5707666  .0002710  2.5544 0.1916  P    42.344     .500      .216     .300   .082000   .185000   .5697000      .000      .000  
+74 220 42098.00 I   .069596  .011991   .196527  .005875  I  .5681383  .0002710  2.7045 0.1916  P    42.693     .500      .359     .300   .081000   .184000   .5671000      .000      .000  
+74 221 42099.00 I   .068798  .010419   .196328  .014712  I  .5653568  .0002710  2.8570 0.1916  P    42.928     .500      .533     .300   .080000   .184000   .5645000      .000      .000  
+74 222 42100.00 I   .067976  .003786   .196145  .016288  I  .5624308  .0002710  2.9898 0.1916  P    43.065     .500      .565     .300   .079000   .184000   .5617000      .000      .000  
+74 223 42101.00 I   .067127  .013875   .195974  .014403  I  .5593901  .0002710  3.0837 0.1916  P    43.098     .500      .431     .300   .078000   .183000   .5589000      .000      .000  
+74 224 42102.00 I   .066248  .015883   .195811  .016595  I  .5562812  .0002710  3.1243 0.1916  P    43.020     .500      .263     .300   .077000   .183000   .5562000      .000      .000  
+74 225 42103.00 I   .065336  .013868   .195653  .014379  I  .5531613  .0002710  3.1056 0.1916  P    42.899     .500      .188     .300   .076000   .182000   .5534000      .000      .000  
+74 226 42104.00 I   .064391  .015732   .195500  .016299  I  .5500884  .0002710  3.0318 0.1916  P    42.814     .500      .218     .300   .076000   .182000   .5506000      .000      .000  
+74 227 42105.00 I   .063408  .015506   .195349  .015008  I  .5471104  .0002710  2.9198 0.1916  P    42.760     .500      .287     .300   .075000   .182000   .5476000      .000      .000  
+74 228 42106.00 I   .062390  .017878   .195202  .006799  I  .5442519  .0002710  2.7986 0.1916  P    42.654     .500      .333     .300   .074000   .181000   .5446000      .000      .000  
+74 3 1 42107.00 I   .061338  .016163   .195056  .007013  I  .5415040  .0002710  2.7050 0.1916  P    42.447     .500      .309     .300   .073000   .181000   .5416000      .000      .000  
+74 3 2 42108.00 I   .060251  .010292   .194913  .007368  I  .5388205  .0002710  2.6756 0.1916  P    42.193     .500      .150     .300   .072000   .180000   .5386000      .000      .000  
+74 3 3 42109.00 I   .059132  .027041   .194771  .018143  I  .5361227  .0002710  2.7367 0.1916  P    42.030     .500     -.189     .300   .071000   .180000   .5356000      .000      .000  
+74 3 4 42110.00 I   .057982  .031158   .194630  .020943  I  .5333157  .0002710  2.8922 0.1916  P    42.079     .500     -.620     .300   .070000   .180000   .5325000      .000      .000  
+74 3 5 42111.00 I   .056803  .038096   .194488  .020943  I  .5303155  .0002710  3.1162 0.1916  P    42.323     .500     -.906     .300   .068000   .180000   .5293000      .000      .000  
+74 3 6 42112.00 I   .055601  .043151   .194343  .024615  I  .5270781  .0002710  3.3558 0.1916  P    42.607     .500     -.845     .300   .067000   .180000   .5262000      .000      .000  
+74 3 7 42113.00 I   .054379  .037704   .194194  .024615  I  .5236205  .0002710  3.5456 0.1916  P    42.798     .500     -.495     .300   .066000   .180000   .5230000      .000      .000  
+74 3 8 42114.00 I   .053147  .043206   .194042  .033967  I  .5200213  .0002710  3.6321 0.1916  P    42.895     .500     -.139     .300   .065000   .180000   .5199000      .000      .000  
+74 3 9 42115.00 I   .051913  .037538   .193888  .024077  I  .5163977  .0002710  3.5942 0.1916  P    42.943     .500     -.023     .300   .063000   .179000   .5166000      .000      .000  
+74 310 42116.00 I   .050682  .031778   .193733  .002379  I  .5128685  .0002710  3.4494 0.1916  P    42.915     .500     -.159     .300   .062000   .179000   .5134000      .000      .000  
+74 311 42117.00 I   .049458  .027521   .193578  .005314  I  .5095191  .0002710  3.2440 0.1916  P    42.797     .500     -.399     .300   .061000   .179000   .5101000      .000      .000  
+74 312 42118.00 I   .048242  .006752   .193426  .005314  I  .5063829  .0002710  3.0313 0.1916  P    42.704     .500     -.623     .300   .059000   .179000   .5069000      .000      .000  
+74 313 42119.00 I   .047038  .013642   .193276  .004602  I  .5034451  .0002710  2.8527 0.1916  P    42.750     .500     -.791     .300   .058000   .179000   .5036000      .000      .000  
+74 314 42120.00 I   .045847  .014652   .193131  .004602  I  .5006586  .0002710  2.7308 0.1916  P    42.845     .500     -.893     .300   .056000   .179000   .5004000      .000      .000  
+74 315 42121.00 I   .044672  .012816   .192991  .004964  I  .4979625  .0002710  2.6719 0.1916  P    42.795     .500     -.943     .300   .055000   .179000   .4972000      .000      .000  
+74 316 42122.00 I   .043517  .014384   .192859  .005565  I  .4952943  .0002710  2.6744 0.1916  P    42.620     .500    -1.011     .300   .053000   .180000   .4940000      .000      .000  
+74 317 42123.00 I   .042385  .015412   .192733  .020190  I  .4925950  .0002710  2.7329 0.1916  P    42.601     .500    -1.158     .300   .052000   .180000   .4908000      .000      .000  
+74 318 42124.00 I   .041274  .017795   .192617  .022947  I  .4898130  .0002710  2.8379 0.1916  P    42.912     .500    -1.331     .300   .050000   .180000   .4876000      .000      .000  
+74 319 42125.00 I   .040185  .017050   .192508  .024768  I  .4869085  .0002710  2.9749 0.1916  P    43.394     .500    -1.393     .300   .048000   .180000   .4846000      .000      .000  
+74 320 42126.00 I   .039119  .013603   .192409  .028558  I  .4838591  .0002710  3.1242 0.1916  P    43.753     .500    -1.298     .300   .047000   .180000   .4815000      .000      .000  
+74 321 42127.00 I   .038076  .011800   .192317  .027239  I  .4806634  .0002710  3.2638 0.1916  P    43.896     .500    -1.153     .300   .045000   .181000   .4785000      .000      .000  
+74 322 42128.00 I   .037057  .013467   .192231  .031267  I  .4773418  .0002710  3.3726 0.1916  P    43.931     .500    -1.099     .300   .044000   .181000   .4754000      .000      .000  
+74 323 42129.00 I   .036067  .013705   .192146  .027163  I  .4739344  .0002710  3.4327 0.1916  P    43.944     .500    -1.155     .300   .042000   .181000   .4724000      .000      .000  
+74 324 42130.00 I   .035104  .011859   .192061  .021708  I  .4704966  .0002710  3.4322 0.1916  P    43.909     .500    -1.236     .300   .040000   .182000   .4695000      .000      .000  
+74 325 42131.00 I   .034171  .010731   .191977  .018931  I  .4670908  .0002710  3.3694 0.1916  P    43.802     .500    -1.277     .300   .039000   .182000   .4666000      .000      .000  
+74 326 42132.00 I   .033267  .009089   .191893  .013656  I  .4637744  .0002710  3.2569 0.1916  P    43.678     .500    -1.290     .300   .037000   .183000   .4636000      .000      .000  
+74 327 42133.00 I   .032395  .008238   .191811  .012197  I  .4605841  .0002710  3.1231 0.1916  P    43.611     .500    -1.327     .300   .036000   .183000   .4607000      .000      .000  
+74 328 42134.00 I   .031552  .009470   .191732  .004136  I  .4575226  .0002710  3.0061 0.1916  P    43.617     .500    -1.415     .300   .034000   .184000   .4578000      .000      .000  
+74 329 42135.00 I   .030738  .009314   .191656  .007292  I  .4545535  .0002710  2.9443 0.1916  P    43.662     .500    -1.559     .300   .032000   .184000   .4549000      .000      .000  
+74 330 42136.00 I   .029953  .006876   .191584  .008136  I  .4516067  .0002710  2.9645 0.1916  P    43.720     .500    -1.767     .300   .031000   .185000   .4520000      .000      .000  
+74 331 42137.00 I   .029197  .005985   .191517  .008342  I  .4485951  .0002710  3.0730 0.1916  P    43.804     .500    -2.037     .300   .029000   .185000   .4491000      .000      .000  
+74 4 1 42138.00 I   .028470  .005907   .191456  .009467  I  .4454372  .0002710  3.2520 0.1916  P    43.947     .500    -2.323     .300   .028000   .186000   .4462000      .000      .000  
+74 4 2 42139.00 I   .027772  .005426   .191399  .008635  I  .4420806  .0002710  3.4624 0.1916  P    44.140     .500    -2.508     .300   .026000   .186000   .4433000      .000      .000  
+74 4 3 42140.00 I   .027104  .005567   .191349  .009764  I  .4385193  .0002710  3.6522 0.1916  P    44.313     .500    -2.462     .300   .024000   .187000   .4404000      .000      .000  
+74 4 4 42141.00 I   .026463  .015459   .191303  .009925  I  .4347997  .0002710  3.7714 0.1916  P    44.379     .500    -2.172     .300   .023000   .187000   .4375000      .000      .000  
+74 4 5 42142.00 I   .025851  .017106   .191261  .008521  I  .4310112  .0002710  3.7866 0.1916  P    44.321     .500    -1.813     .300   .021000   .188000   .4347000      .000      .000  
+74 4 6 42143.00 I   .025266  .014854   .191223  .007498  I  .4272623  .0002710  3.6944 0.1916  P    44.201     .500    -1.636     .300   .020000   .188000   .4318000      .000      .000  
+74 4 7 42144.00 I   .024707  .017135   .191187  .006940  I  .4236496  .0002710  3.5208 0.1916  P    44.112     .500    -1.758     .300   .018000   .189000   .4289000      .000      .000  
+74 4 8 42145.00 I   .024174  .015766   .191153  .013682  I  .4202328  .0002710  3.3111 0.1916  P    44.124     .500    -2.066     .300   .016000   .190000   .4259000      .000      .000  
+74 4 9 42146.00 I   .023660  .018085   .191121  .015486  I  .4170238  .0002710  3.1123 0.1916  P    44.244     .500    -2.336     .300   .015000   .190000   .4229000      .000      .000  
+74 410 42147.00 I   .023163  .018826   .191091  .017114  I  .4139931  .0002710  2.9587 0.1916  P    44.388     .500    -2.424     .300   .013000   .191000   .4199000      .000      .000  
+74 411 42148.00 I   .022678  .013599   .191064  .018829  I  .4110859  .0002710  2.8666 0.1916  P    44.422     .500    -2.349     .300   .012000   .191000   .4169000      .000      .000  
+74 412 42149.00 I   .022199  .014932   .191040  .017408  I  .4082387  .0002710  2.8380 0.1916  P    44.295     .500    -2.249     .300   .010000   .192000   .4139000      .000      .000  
+74 413 42150.00 I   .021724  .017196   .191017  .020043  I  .4053908  .0002710  2.8667 0.1916  P    44.145     .500    -2.268     .300   .009000   .193000   .4106000      .000      .000  
+74 414 42151.00 I   .021250  .018893   .190994  .019873  I  .4024893  .0002710  2.9434 0.1916  P    44.197     .500    -2.435     .300   .008000   .193000   .4074000      .000      .000  
+74 415 42152.00 I   .020770  .020931   .190971  .018032  I  .3994923  .0002710  3.0552 0.1916  P    44.526     .500    -2.632     .300   .006000   .194000   .4041000      .000      .000  
+74 416 42153.00 I   .020280  .018912   .190949  .017368  I  .3963728  .0002710  3.1853 0.1916  P    44.958     .500    -2.704     .300   .005000   .194000   .4009000      .000      .000  
+74 417 42154.00 I   .019776  .018203   .190925  .015858  I  .3931219  .0002710  3.3148 0.1916  P    45.229     .500    -2.623     .300   .004000   .195000   .3976000      .000      .000  
+74 418 42155.00 I   .019254  .023277   .190901  .014414  I  .3897500  .0002710  3.4239 0.1916  P    45.224     .500    -2.516     .300   .003000   .196000   .3941000      .000      .000  
+74 419 42156.00 I   .018715  .024700   .190875  .015083  I  .3862870  .0002710  3.4942 0.1916  P    45.042     .500    -2.495     .300   .002000   .196000   .3906000      .000      .000  
+74 420 42157.00 I   .018156  .021552   .190850  .017211  I  .3827794  .0002710  3.5110 0.1916  P    44.843     .500    -2.528     .300   .000000   .197000   .3872000      .000      .000  
+74 421 42158.00 I   .017577  .020955   .190827  .016434  I  .3792856  .0002710  3.4661 0.1916  P    44.693     .500    -2.507     .300  -.001000   .197000   .3837000      .000      .000  
+74 422 42159.00 I   .016976  .022133   .190808  .014292  I  .3758664  .0002710  3.3637 0.1916  P    44.557     .500    -2.427     .300  -.002000   .198000   .3802000      .000      .000  
+74 423 42160.00 I   .016356  .024787   .190795  .013974  I  .3725704  .0002710  3.2247 0.1916  P    44.413     .500    -2.400     .300  -.003000   .198000   .3767000      .000      .000  
+74 424 42161.00 I   .015719  .021688   .190790  .016509  I  .3694168  .0002710  3.0862 0.1916  P    44.330     .500    -2.516     .300  -.004000   .199000   .3732000      .000      .000  
+74 425 42162.00 I   .015068  .015365   .190796  .018381  I  .3663835  .0002710  2.9912 0.1916  P    44.397     .500    -2.735     .300  -.005000   .199000   .3696000      .000      .000  
+74 426 42163.00 I   .014407  .013327   .190812  .016118  I  .3634087  .0002710  2.9734 0.1916  P    44.612     .500    -2.942     .300  -.006000   .200000   .3661000      .000      .000  
+74 427 42164.00 I   .013735  .015084   .190839  .013376  I  .3604073  .0002710  3.0437 0.1916  P    44.856     .500    -3.060     .300  -.007000   .200000   .3626000      .000      .000  
+74 428 42165.00 I   .013053  .014065   .190877  .012786  I  .3572975  .0002710  3.1853 0.1916  P    45.006     .500    -3.102     .300  -.007000   .200000   .3592000      .000      .000  
+74 429 42166.00 I   .012362  .007053   .190927  .014687  I  .3540256  .0002710  3.3603 0.1916  P    45.051     .500    -3.122     .300  -.008000   .201000   .3558000      .000      .000  
+74 430 42167.00 I   .011662  .011509   .190986  .013042  I  .3505813  .0002710  3.5220 0.1425  P    45.085     .500    -3.140     .300  -.009000   .201000   .3524000      .000      .000  
+74 5 1 42168.00 I   .010954  .012799   .191053  .007661  I  .3470003  .0000881  3.6277 0.1425  P    45.178     .500    -3.110     .300  -.010000   .202000   .3490000      .000      .000  
+74 5 2 42169.00 I   .010240  .018678   .191129  .007753  I  .3433539  .0000881  3.6495 0.0623  P    45.285     .500    -2.968     .300  -.011000   .202000   .3456000      .000      .000  
+74 5 3 42170.00 I   .009519  .021551   .191213  .008464  I  .3397321  .0000881  3.5789 0.0623  P    45.283     .500    -2.742     .300  -.012000   .202000   .3424000      .000      .000  
+74 5 4 42171.00 I   .008791  .021913   .191305  .008412  I  .3362223  .0000881  3.4296 0.0623  P    45.127     .500    -2.576     .300  -.013000   .203000   .3392000      .000      .000  
+74 5 5 42172.00 I   .008058  .024577   .191406  .007435  I  .3328887  .0000881  3.2328 0.0623  P    44.938     .500    -2.611     .300  -.014000   .203000   .3359000      .000      .000  
+74 5 6 42173.00 I   .007323  .021470   .191517  .007172  I  .3297594  .0000881  3.0277 0.1425  P    44.900     .500    -2.829     .300  -.015000   .203000   .3327000      .000      .000  
+74 5 7 42174.00 I   .006592  .022085   .191636  .007583  I  .3268237  .0002710  2.8512 0.1425  P    45.050     .500    -3.057     .300  -.016000   .204000   .3295000      .000      .000  
+74 5 8 42175.00 I   .005869  .019262   .191765  .010305  I  .3240393  .0002710  2.7278 0.1916  P    45.225     .500    -3.122     .300  -.016000   .204000   .3264000      .000      .000  
+74 5 9 42176.00 I   .005159  .013904   .191901  .010960  I  .3213473  .0002710  2.6669 0.1916  P    45.247     .500    -3.008     .300  -.017000   .204000   .3233000      .000      .000  
+74 510 42177.00 I   .004465  .014818   .192046  .010584  I  .3186855  .0002710  2.6660 0.1916  P    45.125     .500    -2.860     .300  -.018000   .204000   .3201000      .000      .000  
+74 511 42178.00 I   .003788  .010815   .192197  .011254  I  .3159986  .0002710  2.7151 0.1916  P    45.019     .500    -2.846     .300  -.019000   .205000   .3170000      .000      .000  
+74 512 42179.00 I   .003132  .011523   .192354  .010429  I  .3132432  .0002710  2.8005 0.1916  P    45.046     .500    -2.998     .300  -.020000   .205000   .3139000      .000      .000  
+74 513 42180.00 I   .002499  .012901   .192516  .011476  I  .3103906  .0002710  2.9068 0.1916  P    45.195     .500    -3.182     .300  -.021000   .205000   .3109000      .000      .000  
+74 514 42181.00 I   .001889  .011268   .192683  .011647  I  .3074284  .0002710  3.0167 0.1916  P    45.385     .500    -3.228     .300  -.021000   .206000   .3079000      .000      .000  
+74 515 42182.00 I   .001303  .012742   .192856  .009837  I  .3043618  .0002710  3.1127 0.1916  P    45.511     .500    -3.119     .300  -.022000   .206000   .3050000      .000      .000  
+74 516 42183.00 I   .000740  .016443   .193037  .009532  I  .3012128  .0002710  3.1791 0.1916  P    45.452     .500    -3.010     .300  -.022000   .206000   .3020000      .000      .000  
+74 517 42184.00 I   .000202  .016157   .193225  .009587  I  .2980181  .0002710  3.2019 0.1916  P    45.147     .500    -3.032     .300  -.023000   .207000   .2990000      .000      .000  
+74 518 42185.00 I  -.000310  .014963   .193423  .008862  I  .2948268  .0002710  3.1711 0.1916  P    44.695     .500    -3.108     .300  -.023000   .207000   .2960000      .000      .000  
+74 519 42186.00 I  -.000794  .015442   .193631  .009292  I  .2916945  .0002710  3.0844 0.1916  P    44.289     .500    -3.055     .300  -.024000   .207000   .2930000      .000      .000  
+74 520 42187.00 I  -.001250  .013655   .193850  .008115  I  .2886731  .0002710  2.9525 0.1916  P    44.030     .500    -2.848     .300  -.024000   .207000   .2900000      .000      .000  
+74 521 42188.00 I  -.001679  .015677   .194079  .006217  I  .2857950  .0002710  2.8040 0.1916  P    43.889     .500    -2.686     .300  -.025000   .208000   .2870000      .000      .000  
+74 522 42189.00 I  -.002080  .014529   .194321  .015539  I  .2830565  .0002710  2.6813 0.1916  P    43.849     .500    -2.760     .300  -.025000   .208000   .2840000      .000      .000  
+74 523 42190.00 I  -.002456  .009128   .194577  .017250  I  .2804098  .0002710  2.6265 0.1916  P    43.978     .500    -3.022     .300  -.025000   .208000   .2810000      .000      .000  
+74 524 42191.00 I  -.002805  .016048   .194845  .017075  I  .2777733  .0002710  2.6625 0.1916  P    44.281     .500    -3.240     .300  -.026000   .209000   .2779000      .000      .000  
+74 525 42192.00 I  -.003130  .017490   .195128  .019389  I  .2750574  .0002710  2.7807 0.1916  P    44.586     .500    -3.251     .300  -.026000   .209000   .2749000      .000      .000  
+74 526 42193.00 I  -.003430  .017449   .195427  .017028  I  .2721975  .0002710  2.9419 0.1916  P    44.673     .500    -3.086     .300  -.026000   .209000   .2718000      .000      .000  
+74 527 42194.00 I  -.003708  .019894   .195744  .019625  I  .2691772  .0002710  3.0922 0.1916  P    44.498     .500    -2.882     .300  -.027000   .210000   .2688000      .000      .000  
+74 528 42195.00 I  -.003966  .017240   .196082  .019346  I  .2660328  .0002710  3.1835 0.1916  P    44.226     .500    -2.737     .300  -.027000   .210000   .2659000      .000      .000  
+74 529 42196.00 I  -.004202  .018990   .196445  .014688  I  .2628389  .0002710  3.1888 0.1916  P    44.069     .500    -2.659     .300  -.027000   .210000   .2630000      .000      .000  
+74 530 42197.00 I  -.004414  .016925   .196839  .019995  I  .2596849  .0002710  3.1052 0.1916  P    44.081     .500    -2.607     .300  -.027000   .210000   .2600000      .000      .000  
+74 531 42198.00 I  -.004600  .011040   .197266  .021022  I  .2566525  .0002710  2.9497 0.1916  P    44.123     .500    -2.544     .300  -.028000   .211000   .2571000      .000      .000  
+74 6 1 42199.00 I  -.004756  .010111   .197730  .018305  I  .2538000  .0002710  2.7507 0.1916  P    44.013     .500    -2.486     .300  -.028000   .211000   .2542000      .000      .000  
+74 6 2 42200.00 I  -.004877  .006021   .198235  .020882  I  .2511548  .0002710  2.5405 0.1916  P    43.737     .500    -2.491     .300  -.028000   .211000   .2515000      .000      .000  
+74 6 3 42201.00 I  -.004960  .010249   .198781  .018236  I  .2487125  .0002710  2.3498 0.1916  P    43.476     .500    -2.592     .300  -.027000   .211000   .2488000      .000      .000  
+74 6 4 42202.00 I  -.005000  .011813   .199370  .018152  I  .2464406  .0002710  2.2030 0.1916  P    43.390     .500    -2.748     .300  -.027000   .212000   .2462000      .000      .000  
+74 6 5 42203.00 I  -.004992  .011720   .200001  .018491  I  .2442871  .0002710  2.1143 0.1916  P    43.438     .500    -2.852     .300  -.027000   .212000   .2435000      .000      .000  
+74 6 6 42204.00 I  -.004932  .012721   .200676  .011772  I  .2421917  .0002710  2.0864 0.1916  P    43.475     .500    -2.829     .300  -.027000   .212000   .2408000      .000      .000  
+74 6 7 42205.00 I  -.004816  .014625   .201393  .017165  I  .2400963  .0002710  2.1123 0.1755  P    43.459     .500    -2.712     .300  -.026000   .212000   .2384000      .000      .000  
+74 6 8 42206.00 I  -.004643  .016455   .202153  .019698  I  .2379537  .0002230  2.1782 0.2303  P    43.439     .500    -2.624     .300  -.026000   .212000   .2359000      .000      .000  
+74 6 9 42207.00 I  -.004410  .022004   .202956  .018278  I  .2357321  .0003724  2.2674 0.2236  P    43.400     .500    -2.659     .300  -.026000   .213000   .2335000      .000      .000  
+74 610 42208.00 I  -.004117  .023275   .203801  .020931  I  .2334170  .0003877  2.3623 0.2688  P    43.285     .500    -2.770     .300  -.025000   .213000   .2310000      .000      .000  
+74 611 42209.00 I  -.003764  .020291   .204685  .026681  I  .2310113  .0003877  2.4459 0.2741  P    43.153     .500    -2.811     .300  -.025000   .213000   .2286000      .000      .000  
+74 612 42210.00 I  -.003348  .021673   .205605  .025030  I  .2285338  .0003877  2.5038 0.2741  P    43.119     .500    -2.716     .300  -.024000   .213000   .2264000      .000      .000  
+74 613 42211.00 I  -.002866  .019413   .206557  .022434  I  .2260158  .0003877  2.5254 0.2962  P    43.109     .500    -2.602     .300  -.024000   .213000   .2242000      .000      .000  
+74 614 42212.00 I  -.002321  .021726   .207536  .023739  I  .2234977  .0004478  2.5030 0.2845  P    42.864     .500    -2.623     .300  -.023000   .214000   .2220000      .000      .000  
+74 615 42213.00 I  -.001713  .025217   .208538  .021821  I  .2210256  .0004166  2.4333 0.2617  P    42.283     .500    -2.735     .300  -.023000   .214000   .2198000      .000      .000  
+74 616 42214.00 I  -.001045  .021277   .209555  .023255  I  .2186454  .0002710  2.3207 0.2485  P    41.601     .500    -2.723     .300  -.022000   .214000   .2176000      .000      .000  
+74 617 42215.00 I  -.000315  .019995   .210579  .026815  I  .2163925  .0002710  2.1832 0.1916  P    41.133     .500    -2.496     .300  -.021000   .214000   .2155000      .000      .000  
+74 618 42216.00 I   .000476  .022788   .211604  .023660  I  .2142759  .0002710  2.0550 0.1916  P    40.981     .500    -2.251     .300  -.021000   .214000   .2135000      .000      .000  
+74 619 42217.00 I   .001331  .021696   .212624  .024142  I  .2122651  .0002710  1.9791 0.1916  P    41.067     .500    -2.249     .300  -.020000   .215000   .2114000      .000      .000  
+74 620 42218.00 I   .002251  .021628   .213636  .026501  I  .2102885  .0002710  1.9910 0.1916  P    41.313     .500    -2.484     .300  -.020000   .215000   .2094000      .000      .000  
+74 621 42219.00 I   .003234  .018701   .214635  .023710  I  .2082511  .0002710  2.0991 0.1916  P    41.637     .500    -2.689     .300  -.019000   .215000   .2073000      .000      .000  
+74 622 42220.00 I   .004277  .013963   .215616  .024857  I  .2060678  .0002710  2.2747 0.1916  P    41.876     .500    -2.659     .300  -.018000   .215000   .2053000      .000      .000  
+74 623 42221.00 I   .005373  .013889   .216573  .029033  I  .2036984  .0002710  2.4600 0.1916  P    41.859     .500    -2.437     .300  -.017000   .215000   .2032000      .000      .000  
+74 624 42222.00 I   .006518  .015027   .217503  .027734  I  .2011655  .0002710  2.5921 0.1916  P    41.552     .500    -2.187     .300  -.016000   .215000   .2012000      .000      .000  
+74 625 42223.00 I   .007703  .010841   .218405  .026756  I  .1985464  .0002710  2.6277 0.1416  P    41.071     .500    -1.986     .300  -.015000   .215000   .1991000      .000      .000  
+74 626 42224.00 I   .008924  .015788   .219276  .027568  I  .1959452  .0000821  2.5579 0.1788  P    40.592     .500    -1.838     .300  -.014000   .216000   .1971000      .000      .000  
+74 627 42225.00 I   .010171  .016579   .220115  .025758  I  .1934584  .0002334  2.4047 0.1237  P    40.266     .500    -1.767     .300  -.013000   .216000   .1951000      .000      .000  
+74 628 42226.00 I   .011437  .016493   .220919  .027148  I  .1911510  .0002334  2.2059 0.1817  P    40.148     .500    -1.819     .300  -.012000   .216000   .1930000      .000      .000  
+74 629 42227.00 I   .012711  .015665   .221686  .026593  I  .1890489  .0002785  2.0003 0.1817  P    40.115     .500    -1.959     .300  -.011000   .216000   .1910000      .000      .000  
+74 630 42228.00 I   .013984  .019691   .222416  .020071  I  .1871428  .0002785  1.8176 0.1969  P    39.970     .500    -2.094     .300  -.010000   .216000   .1889000      .000      .000  
+74 7 1 42229.00 I   .015250  .022024   .223106  .014871  I  .1853992  .0002785  1.6782 0.2182  P    39.657     .500    -2.176     .300  -.009000   .216000   .1869000      .000      .000  
+74 7 2 42230.00 I   .016503  .021654   .223758  .015564  I  .1837679  .0003361  1.5941 0.2243  P    39.329     .500    -2.247     .300  -.008000   .216000   .1848000      .000      .000  
+74 7 3 42231.00 I   .017736  .018392   .224372  .016211  I  .1821913  .0003518  1.5691 0.2433  P    39.149     .500    -2.332     .300  -.007000   .216000   .1827000      .000      .000  
+74 7 4 42232.00 I   .018940  .022670   .224947  .020112  I  .1806110  .0003518  1.6001 0.2220  P    39.134     .500    -2.365     .300  -.006000   .216000   .1805000      .000      .000  
+74 7 5 42233.00 I   .020113  .023557   .225484  .019281  I  .1789761  .0002710  1.6760 0.2220  P    39.202     .500    -2.263     .300  -.005000   .216000   .1784000      .000      .000  
+74 7 6 42234.00 I   .021252  .023881   .225982  .020073  I  .1772496  .0002710  1.7801 0.1916  P    39.257     .500    -2.069     .300  -.004000   .216000   .1763000      .000      .000  
+74 7 7 42235.00 I   .022358  .020722   .226444  .020776  I  .1754130  .0002710  1.8931 0.2576  P    39.185     .500    -1.942     .300  -.002000   .216000   .1742000      .000      .000  
+74 7 8 42236.00 I   .023430  .019542   .226867  .021383  I  .1734666  .0004381  1.9967 0.2576  P    38.916     .500    -1.978     .300  -.001000   .216000   .1721000      .000      .000  
+74 7 9 42237.00 I   .024465  .019545   .227255  .021367  I  .1714277  .0004381  2.0760 0.2723  P    38.579     .500    -2.095     .300   .000000   .216000   .1699000      .000      .000  
+74 710 42238.00 I   .025459  .023284   .227607  .022373  I  .1693264  .0003235  2.1200 0.2723  P    38.425     .500    -2.147     .300   .001000   .216000   .1678000      .000      .000  
+74 711 42239.00 I   .026407  .018951   .227925  .019316  I  .1672016  .0003235  2.1224 0.2287  P    38.479     .500    -2.122     .300   .002000   .216000   .1657000      .000      .000  
+74 712 42240.00 I   .027305  .019040   .228211  .018536  I  .1650959  .0003235  2.0819 0.2287  P    38.418     .500    -2.139     .300   .003000   .216000   .1636000      .000      .000  
+74 713 42241.00 I   .028151  .020244   .228464  .016780  I  .1630508  .0003235  2.0025 0.1747  P    37.945     .500    -2.237     .300   .004000   .216000   .1616000      .000      .000  
+74 714 42242.00 I   .028942  .020973   .228683  .016039  I  .1610997  .0001319  1.8967 0.1747  P    37.181     .500    -2.280     .300   .005000   .216000   .1595000      .000      .000  
+74 715 42243.00 I   .029674  .018768   .228869  .016737  I  .1592580  .0001319  1.7890 0.1507  P    36.551     .500    -2.161     .300   .006000   .216000   .1575000      .000      .000  
+74 716 42244.00 I   .030340  .019179   .229023  .022235  I  .1575102  .0002710  1.7157 0.1507  P    36.355     .500    -2.000     .300   .007000   .217000   .1554000      .000      .000  
+74 717 42245.00 I   .030935  .014328   .229145  .022155  I  .1558022  .0002710  1.7156 0.1916  P    36.571     .500    -2.015     .300   .007000   .217000   .1534000      .000      .000  
+74 718 42246.00 I   .031459  .014630   .229236  .021440  I  .1540466  .0002710  1.8127 0.1916  P    36.975     .500    -2.212     .300   .008000   .217000   .1515000      .000      .000  
+74 719 42247.00 I   .031910  .013291   .229297  .020905  I  .1521472  .0002710  1.9987 0.1916  P    37.310     .500    -2.356     .300   .009000   .217000   .1495000      .000      .000  
+74 720 42248.00 I   .032289  .014634   .229326  .021094  I  .1500348  .0002710  2.2280 0.1916  P    37.402     .500    -2.274     .300   .010000   .217000   .1476000      .000      .000  
+74 721 42249.00 I   .032598  .014228   .229326  .021864  I  .1476996  .0002710  2.4321 0.1916  P    37.243     .500    -2.058     .300   .011000   .217000   .1456000      .000      .000  
+74 722 42250.00 I   .032838  .014040   .229296  .021349  I  .1452006  .0002710  2.5464 0.1916  P    36.943     .500    -1.879     .300   .012000   .217000   .1437000      .000      .000  
+74 723 42251.00 I   .033012  .016313   .229237  .014736  I  .1426478  .0002710  2.5378 0.1916  P    36.550     .500    -1.748     .300   .012000   .217000   .1418000      .000      .000  
+74 724 42252.00 I   .033124  .019029   .229150  .009664  I  .1401629  .0002710  2.4154 0.1916  P    36.020     .500    -1.579     .300   .013000   .218000   .1399000      .000      .000  
+74 725 42253.00 I   .033179  .021126   .229032  .009283  I  .1378411  .0002710  2.2206 0.1916  P    35.445     .500    -1.427     .300   .013000   .218000   .1380000      .000      .000  
+74 726 42254.00 I   .033183  .021243   .228884  .011548  I  .1357282  .0002710  2.0061 0.1916  P    35.112     .500    -1.465     .300   .014000   .218000   .1361000      .000      .000  
+74 727 42255.00 I   .033140  .018248   .228705  .013064  I  .1338212  .0002710  1.8146 0.1916  P    35.180     .500    -1.731     .300   .015000   .218000   .1342000      .000      .000  
+74 728 42256.00 I   .033052  .017860   .228495  .013045  I  .1320826  .0002710  1.6722 0.1916  P    35.413     .500    -2.030     .300   .015000   .218000   .1323000      .000      .000  
+74 729 42257.00 I   .032919  .017940   .228251  .012110  I  .1304569  .0002710  1.5895 0.1916  P    35.435     .500    -2.161     .300   .016000   .219000   .1305000      .000      .000  
+74 730 42258.00 I   .032742  .016762   .227975  .016195  I  .1288833  .0002710  1.5678 0.1916  P    35.179     .500    -2.138     .300   .016000   .219000   .1286000      .000      .000  
+74 731 42259.00 I   .032525  .018798   .227666  .016409  I  .1273020  .0002710  1.6040 0.3212  P    34.905     .500    -2.096     .300   .017000   .219000   .1267000      .000      .000  
+74 8 1 42260.00 I   .032268  .018396   .227323  .020372  I  .1256589  .0005824  1.6895 0.3212  P    34.827     .500    -2.062     .300   .017000   .219000   .1247000      .000      .000  
+74 8 2 42261.00 I   .031975  .018801   .226948  .020518  I  .1239113  .0005824  1.8101 0.4118  P    34.913     .500    -1.938     .300   .017000   .219000   .1227000      .000      .000  
+74 8 3 42262.00 I   .031645  .019145   .226540  .020465  I  .1220332  .0005824  1.9470 0.4118  P    34.999     .500    -1.700     .300   .017000   .220000   .1206000      .000      .000  
+74 8 4 42263.00 I   .031279  .019682   .226103  .019788  I  .1200186  .0005824  2.0798 0.4118  P    34.949     .500    -1.504     .300   .017000   .220000   .1186000      .000      .000  
+74 8 5 42264.00 I   .030879  .019654   .225640  .020278  I  .1178811  .0005824  2.1901 0.3899  P    34.709     .500    -1.521     .300   .017000   .220000   .1166000      .000      .000  
+74 8 6 42265.00 I   .030451  .019101   .225155  .018481  I  .1156503  .0005186  2.2649 0.3667  P    34.374     .500    -1.735     .300   .017000   .220000   .1143000      .000      .000  
+74 8 7 42266.00 I   .029999  .013944   .224651  .018267  I  .1133655  .0004457  2.2972 0.3419  P    34.161     .500    -1.957     .300   .017000   .220000   .1121000      .000      .000  
+74 8 8 42267.00 I   .029528  .010255   .224133  .014559  I  .1110705  .0004457  2.2856 0.3152  P    34.188     .500    -2.055     .300   .017000   .221000   .1098000      .000      .000  
+74 8 9 42268.00 I   .029038  .009143   .223605  .014356  I  .1088073  .0004457  2.2348 0.3152  P    34.267     .500    -2.070     .300   .017000   .221000   .1076000      .000      .000  
+74 810 42269.00 I   .028531  .007967   .223069  .013214  I  .1066102  .0004457  2.1559 0.3152  P    34.080     .500    -2.100     .300   .017000   .221000   .1053000      .000      .000  
+74 811 42270.00 I   .028009  .009880   .222528  .020923  I  .1044981  .0004457  2.0690 0.2608  P    33.561     .500    -2.146     .300   .017000   .221000   .1029000      .000      .000  
+74 812 42271.00 I   .027475  .010686   .221983  .021551  I  .1024651  .0002710  2.0032 0.2608  P    33.005     .500    -2.159     .300   .018000   .220000   .1005000      .000      .000  
+74 813 42272.00 I   .026931  .009509   .221433  .022808  I  .1004733  .0002710  1.9925 0.1916  P    32.777     .500    -2.181     .300   .018000   .220000   .0980000      .000      .000  
+74 814 42273.00 I   .026380  .010620   .220880  .023672  I  .0984520  .0002710  2.0660 0.1916  P    32.986     .500    -2.301     .300   .019000   .220000   .0956000      .000      .000  
+74 815 42274.00 I   .025824  .010394   .220324  .023604  I  .0963103  .0002710  2.2324 0.1916  P    33.422     .500    -2.475     .300   .019000   .220000   .0932000      .000      .000  
+74 816 42275.00 I   .025264  .011064   .219770  .023051  I  .0939641  .0002710  2.4680 0.1916  P    33.721     .500    -2.510     .300   .019000   .219000   .0908000      .000      .000  
+74 817 42276.00 I   .024699  .011121   .219221  .024604  I  .0913700  .0002710  2.7166 0.1916  P    33.663     .500    -2.309     .300   .020000   .219000   .0884000      .000      .000  
+74 818 42277.00 I   .024131  .010702   .218679  .019065  I  .0885501  .0002710  2.9077 0.1916  P    33.364     .500    -2.032     .300   .020000   .219000   .0860000      .000      .000  
+74 819 42278.00 I   .023558  .011811   .218150  .018781  I  .0855929  .0002710  2.9839 0.1916  P    33.119     .500    -1.890     .300   .021000   .218000   .0836000      .000      .000  
+74 820 42279.00 I   .022981  .012083   .217635  .019144  I  .0826272  .0002710  2.9253 0.1916  P    32.997     .500    -1.863     .300   .021000   .218000   .0812000      .000      .000  
+74 821 42280.00 I   .022400  .011322   .217136  .019905  I  .0797792  .0002710  2.7559 0.1916  P    32.754     .500    -1.769     .300   .021000   .218000   .0789000      .000      .000  
+74 822 42281.00 I   .021818  .012378   .216657  .019415  I  .0771343  .0002710  2.5296 0.1916  P    32.259     .500    -1.581     .300   .021000   .218000   .0766000      .000      .000  
+74 823 42282.00 I   .021237  .024803   .216199  .019773  I  .0747195  .0002710  2.3047 0.1916  P    31.830     .500    -1.506     .300   .020000   .218000   .0743000      .000      .000  
+74 824 42283.00 I   .020664  .025425   .215762  .018400  I  .0725103  .0002710  2.1236 0.1916  P    31.882     .500    -1.688     .300   .020000   .218000   .0720000      .000      .000  
+74 825 42284.00 I   .020105  .024355   .215347  .021438  I  .0704511  .0002710  2.0060 0.1916  P    32.354     .500    -1.987     .300   .020000   .218000   .0697000      .000      .000  
+74 826 42285.00 I   .019567  .023519   .214953  .023762  I  .0684765  .0002710  1.9538 0.1916  P    32.762     .500    -2.140     .300   .020000   .218000   .0675000      .000      .000  
+74 827 42286.00 I   .019055  .023334   .214582  .021494  I  .0665239  .0002710  1.9606 0.7695  P    32.811     .500    -2.079     .300   .020000   .218000   .0653000      .000      .000  
+74 828 42287.00 I   .018573  .023669   .214234  .019573  I  .0645387  .0015149  2.0173 0.7695  P    32.675     .500    -1.945     .300   .019000   .218000   .0632000      .000      .000  
+74 829 42288.00 I   .018120  .023046   .213910  .021051  I  .0624767  .0015149  2.1118 1.0712  P    32.641     .500    -1.847     .300   .019000   .218000   .0610000      .000      .000  
+74 830 42289.00 I   .017700  .008170   .213614  .020349  I  .0603081  .0015149  2.2273 0.9339  P    32.732     .500    -1.744     .300   .019000   .218000   .0588000      .000      .000  
+74 831 42290.00 I   .017314  .007840   .213344  .019573  I  .0580213  .0010926  2.3453 0.9339  P    32.797     .500    -1.590     .300   .019000   .218000   .0566000      .000      .000  
+74 9 1 42291.00 I   .016963  .008178   .213104  .021503  I  .0556227  .0010926  2.4477 0.7066  P    32.753     .500    -1.470     .300   .019000   .218000   .0543000      .000      .000  
+74 9 2 42292.00 I   .016648  .008503   .212894  .017844  I  .0531363  .0008964  2.5188 0.5617  P    32.606     .500    -1.516     .300   .018000   .218000   .0521000      .000      .000  
+74 9 3 42293.00 I   .016370  .011932   .212717  .017893  I  .0505988  .0002616  2.5487 0.4691  P    32.381     .500    -1.725     .300   .018000   .218000   .0498000      .000      .000  
+74 9 4 42294.00 I   .016129  .013144   .212577  .018114  I  .0480536  .0002772  2.5344 0.1906  P    32.152     .500    -1.944     .300   .018000   .218000   .0476000      .000      .000  
+74 9 5 42295.00 I   .015927  .015742   .212477  .017267  I  .0455436  .0002772  2.4794 0.2929  P    32.043     .500    -2.035     .300   .018000   .218000   .0452000      .000      .000  
+74 9 6 42296.00 I   .015762  .015177   .212418  .019806  I  .0431045  .0005161  2.3953 0.2692  P    32.090     .500    -2.002     .300   .018000   .218000   .0428000      .000      .000  
+74 9 7 42297.00 I   .015632  .017581   .212401  .021649  I  .0407563  .0004616  2.3013 0.3629  P    32.160     .500    -1.949     .300   .018000   .218000   .0403000      .000      .000  
+74 9 8 42298.00 I   .015532  .018825   .212427  .015538  I  .0384965  .0005104  2.2236 0.3643  P    32.098     .500    -1.957     .300   .018000   .218000   .0379000      .000      .000  
+74 9 9 42299.00 I   .015456  .019919   .212495  .017464  I  .0362936  .0005636  2.1923 0.4141  P    31.934     .500    -2.042     .300   .018000   .218000   .0355000      .000      .000  
+74 910 42300.00 I   .015400  .020041   .212606  .018153  I  .0340879  .0006522  2.2330 0.4310  P    31.865     .500    -2.204     .300   .018000   .218000   .0330000      .000      .000  
+74 911 42301.00 I   .015358  .020773   .212761  .019557  I  .0317988  .0006522  2.3600 0.3261  P    32.036     .500    -2.418     .300   .018000   .218000   .0304000      .000      .000  
+74 912 42302.00 I   .015324  .018865   .212960  .019760  I  .0293420  .0000072  2.5648 0.3531  P    32.361     .500    -2.583     .300   .019000   .218000   .0279000      .000      .000  
+74 913 42303.00 I   .015293  .021151   .213203  .020303  I  .0266552  .0002710  2.8116 0.1355  P    32.561     .500    -2.543     .300   .019000   .218000   .0253000      .000      .000  
+74 914 42304.00 I   .015256  .018523   .213488  .019536  I  .0237243  .0002710  3.0420 0.1916  P    32.438     .500    -2.256     .300   .019000   .218000   .0228000      .000      .000  
+74 915 42305.00 I   .015206  .019698   .213815  .022084  I  .0205976  .0002710  3.1934 0.1916  P    32.118     .500    -1.903     .300   .019000   .218000   .0201000      .000      .000  
+74 916 42306.00 I   .015133  .019916   .214184  .020900  I  .0173782  .0002710  3.2229 0.1916  P    31.946     .500    -1.726     .300   .019000   .218000   .0175000      .000      .000  
+74 917 42307.00 I   .015032  .020853   .214591  .023551  I  .0141941  .0002710  3.1256 0.1916  P    32.054     .500    -1.762     .300   .020000   .219000   .0148000      .000      .000  
+74 918 42308.00 I   .014897  .020123   .215036  .025793  I  .0111579  .0002710  2.9358 0.1916  P    32.171     .500    -1.814     .300   .020000   .219000   .0122000      .000      .000  
+74 919 42309.00 I   .014725  .020191   .215514  .025145  I  .0083342  .0002710  2.7111 0.1916  P    32.000     .500    -1.735     .300   .020000   .219000   .0095000      .000      .000  
+74 920 42310.00 I   .014510  .021988   .216019  .026337  I  .0057286  .0002710  2.5078 0.1916  P    31.682     .500    -1.606     .300   .020000   .219000   .0068000      .000      .000  
+74 921 42311.00 I   .014246  .022170   .216544  .036599  I  .0032992  .0002710  2.3628 0.1916  P    31.644     .500    -1.598     .300   .020000   .220000   .0041000      .000      .000  
+74 922 42312.00 I   .013932  .019840   .217082  .040434  I  .0009794  .0002710  2.2886 0.1916  P    32.035     .500    -1.718     .300   .019000   .220000   .0013000      .000      .000  
+74 923 42313.00 I   .013565  .024273   .217628  .040316  I -.0013001  .0002710  2.2806 0.1916  P    32.555     .500    -1.817     .300   .019000   .221000  -.0014000      .000      .000  
+74 924 42314.00 I   .013142  .022758   .218176  .039421  I -.0036001  .0002710  2.3274 0.3591  P    32.888     .500    -1.805     .300   .019000   .221000  -.0041000      .000      .000  
+74 925 42315.00 I   .012664  .022647   .218720  .037207  I -.0059688  .0006651  2.4157 0.3591  P    33.047     .500    -1.740     .300   .019000   .222000  -.0068000      .000      .000  
+74 926 42316.00 I   .012129  .024434   .219255  .038349  I -.0084405  .0006651  2.5308 0.4703  P    33.191     .500    -1.701     .300   .019000   .222000  -.0095000      .000      .000  
+74 927 42317.00 I   .011540  .021385   .219774  .036125  I -.0110335  .0006651  2.6552 0.4703  P    33.322     .500    -1.682     .300   .018000   .223000  -.0122000      .000      .000  
+74 928 42318.00 I   .010901  .021482   .220274  .027141  I -.0137479  .0006651  2.7706 0.4703  P    33.336     .500    -1.655     .300   .018000   .223000  -.0149000      .000      .000  
+74 929 42319.00 I   .010218  .023056   .220751  .018389  I -.0165659  .0006651  2.8596 0.4101  P    33.242     .500    -1.647     .300   .018000   .224000  -.0176000      .000      .000  
+74 930 42320.00 I   .009497  .016849   .221202  .019571  I -.0194541  .0004800  2.9096 0.3394  P    33.135     .500    -1.698     .300   .018000   .225000  -.0203000      .000      .000  
+7410 1 42321.00 I   .008739  .016810   .221628  .019070  I -.0223698  .0001360  2.9138 0.2494  P    33.024     .500    -1.776     .300   .018000   .225000  -.0230000      .000      .000  
+7410 2 42322.00 I   .007946  .021855   .222027  .020845  I -.0252664  .0001360  2.8722 0.2058  P    32.856     .500    -1.794     .300   .017000   .226000  -.0258000      .000      .000  
+7410 3 42323.00 I   .007119  .024480   .222401  .021298  I -.0281018  .0003884  2.7934 0.2058  P    32.676     .500    -1.713     .300   .017000   .226000  -.0285000      .000      .000  
+7410 4 42324.00 I   .006262  .026627   .222753  .026640  I -.0308468  .0003884  2.6952 0.2746  P    32.634     .500    -1.580     .300   .017000   .227000  -.0312000      .000      .000  
+7410 5 42325.00 I   .005380  .026705   .223082  .026249  I -.0334946  .0003884  2.6041 0.3201  P    32.805     .500    -1.479     .300   .016000   .228000  -.0341000      .000      .000  
+7410 6 42326.00 I   .004477  .027347   .223392  .028180  I -.0360675  .0005089  2.5504 0.3201  P    33.102     .500    -1.466     .300   .016000   .229000  -.0370000      .000      .000  
+7410 7 42327.00 I   .003560  .027406   .223685  .028061  I -.0386168  .0005089  2.5607 0.3599  P    33.393     .500    -1.554     .300   .015000   .230000  -.0398000      .000      .000  
+7410 8 42328.00 I   .002633  .028959   .223963  .029114  I -.0412151  .0005091  2.6495 0.3557  P    33.640     .500    -1.722     .300   .015000   .231000  -.0427000      .000      .000  
+7410 9 42329.00 I   .001704  .031157   .224230  .028425  I -.0439406  .0004972  2.8127 0.3558  P    33.881     .500    -1.911     .300   .014000   .232000  -.0456000      .000      .000  
+741010 42330.00 I   .000778  .029067   .224491  .028453  I -.0468567  .0004972  3.0247 0.3516  P    34.116     .500    -2.027     .300   .013000   .233000  -.0487000      .000      .000  
+741011 42331.00 I  -.000138  .024667   .224747  .019351  I -.0499919  .0004972  3.2426 0.3560  P    34.245     .500    -1.963     .300   .012000   .234000  -.0518000      .000      .000  
+741012 42332.00 I  -.001038  .028001   .225001  .015849  I -.0533268  .0005096  3.4152 0.3560  P    34.178     .500    -1.693     .300   .012000   .236000  -.0548000      .000      .000  
+741013 42333.00 I  -.001917  .024583   .225253  .014307  I -.0567922  .0005096  3.4976 0.2886  P    33.988     .500    -1.340     .300   .011000   .237000  -.0579000      .000      .000  
+741014 42334.00 I  -.002775  .028298   .225504  .013369  I -.0602843  .0002710  3.4671 0.2886  P    33.896     .500    -1.110     .300   .010000   .238000  -.0610000      .000      .000  
+741015 42335.00 I  -.003611  .028052   .225755  .014799  I -.0636919  .0002710  3.3332 0.1916  P    34.031     .500    -1.114     .300   .009000   .239000  -.0641000      .000      .000  
+741016 42336.00 I  -.004427  .016520   .226006  .013857  I -.0669295  .0002710  3.1357 0.1916  P    34.266     .500    -1.259     .300   .008000   .240000  -.0673000      .000      .000  
+741017 42337.00 I  -.005222  .014475   .226259  .014188  I -.0699599  .0002710  2.9279 0.1916  P    34.370     .500    -1.351     .300   .007000   .242000  -.0704000      .000      .000  
+741018 42338.00 I  -.005998  .016631   .226515  .014539  I -.0727978  .0002710  2.7575 0.1916  P    34.319     .500    -1.298     .300   .006000   .243000  -.0736000      .000      .000  
+741019 42339.00 I  -.006755  .016868   .226777  .012659  I -.0754965  .0002710  2.6520 0.1916  P    34.331     .500    -1.169     .300   .005000   .244000  -.0767000      .000      .000  
+741020 42340.00 I  -.007498  .018912   .227044  .013854  I -.0781253  .0002710  2.6170 0.1916  P    34.583     .500    -1.071     .300   .004000   .245000  -.0798000      .000      .000  
+741021 42341.00 I  -.008231  .016527   .227318  .012244  I -.0807508  .0002710  2.6428 0.1916  P    35.022     .500    -1.042     .300   .003000   .246000  -.0830000      .000      .000  
+741022 42342.00 I  -.008959  .010758   .227600  .009307  I -.0834263  .0002710  2.7146 0.1916  P    35.482     .500    -1.066     .300   .002000   .247000  -.0861000      .000      .000  
+741023 42343.00 I  -.009685  .011828   .227891  .009580  I -.0861902  .0002710  2.8169 0.1916  P    35.866     .500    -1.121     .300   .001000   .248000  -.0893000      .000      .000  
+741024 42344.00 I  -.010412  .013420   .228192  .006781  I -.0890648  .0002710  2.9334 0.1916  P    36.134     .500    -1.181     .300   .000000   .249000  -.0924000      .000      .000  
+741025 42345.00 I  -.011141  .012912   .228506  .006374  I -.0920563  .0002710  3.0476 0.1916  P    36.232     .500    -1.215     .300  -.001000   .250000  -.0955000      .000      .000  
+741026 42346.00 I  -.011873  .010931   .228834  .007203  I -.0951537  .0002710  3.1427 0.1916  P    36.132     .500    -1.223     .300  -.002000   .251000  -.0986000      .000      .000  
+741027 42347.00 I  -.012609  .016719   .229178  .006323  I -.0983305  .0002710  3.2043 0.1916  P    35.930     .500    -1.238     .300  -.003000   .252000  -.1017000      .000      .000  
+741028 42348.00 I  -.013350  .019137   .229538  .006734  I -.1015481  .0002710  3.2233 0.1916  P    35.772     .500    -1.259     .300  -.004000   .253000  -.1048000      .000      .000  
+741029 42349.00 I  -.014093  .016633   .229916  .009104  I -.1047621  .0002710  3.1972 0.1916  P    35.697     .500    -1.210     .300  -.005000   .254000  -.1079000      .000      .000  
+741030 42350.00 I  -.014838  .017265   .230312  .008647  I -.1079286  .0002710  3.1295 0.1916  P    35.635     .500    -1.031     .300  -.006000   .255000  -.1110000      .000      .000  
+741031 42351.00 I  -.015582  .017431   .230727  .007820  I -.1110115  .0002710  3.0331 0.2168  P    35.555     .500     -.777     .300  -.007000   .256000  -.1140000      .000      .000  
+7411 1 42352.00 I  -.016326  .019051   .231161  .008565  I -.1139930  .0003384  2.9314 0.2168  P    35.548     .500     -.580     .300  -.008000   .256000  -.1171000      .000      .000  
+7411 2 42353.00 I  -.017073  .016536   .231616  .007419  I -.1168828  .0003384  2.8552 0.2393  P    35.724     .500     -.519     .300  -.009000   .257000  -.1201000      .000      .000  
+7411 3 42354.00 I  -.017822  .010554   .232090  .008483  I -.1197222  .0003384  2.8354 0.2393  P    36.079     .500     -.567     .300  -.010000   .258000  -.1232000      .000      .000  
+7411 4 42355.00 I  -.018574  .010175   .232584  .008942  I -.1225786  .0003384  2.8906 0.2393  P    36.484     .500     -.651     .300  -.011000   .259000  -.1262000      .000      .000  
+7411 5 42356.00 I  -.019330  .011635   .233097  .006439  I -.1255277  .0003384  3.0187 0.2393  P    36.804     .500     -.726     .300  -.012000   .259000  -.1293000      .000      .000  
+7411 6 42357.00 I  -.020086  .010298   .233628  .006083  I -.1286323  .0003384  3.1958 0.2168  P    36.995     .500     -.776     .300  -.012000   .260000  -.1323000      .000      .000  
+7411 7 42358.00 I  -.020843  .005859   .234176  .006523  I -.1319226  .0002710  3.3827 0.2168  P    37.092     .500     -.780     .300  -.013000   .260000  -.1354000      .000      .000  
+7411 8 42359.00 I  -.021598  .019559   .234741  .012920  I -.1353865  .0002710  3.5358 0.1916  P    37.136     .500     -.700     .300  -.014000   .261000  -.1384000      .000      .000  
+7411 9 42360.00 I  -.022348  .022548   .235320  .014917  I -.1389706  .0002710  3.6179 0.1916  P    37.135     .500     -.509     .300  -.015000   .261000  -.1415000      .000      .000  
+741110 42361.00 I  -.023091  .019937   .235914  .012975  I -.1425916  .0002710  3.6078 0.1916  P    37.085     .500     -.240     .300  -.015000   .262000  -.1445000      .000      .000  
+741111 42362.00 I  -.023823  .022435   .236519  .013778  I -.1461556  .0002710  3.5061 0.1916  P    37.016     .500     -.005     .300  -.016000   .262000  -.1476000      .000      .000  
+741112 42363.00 I  -.024543  .024254   .237136  .022801  I -.1495809  .0002710  3.3359 0.1916  P    36.982     .500      .067     .300  -.016000   .263000  -.1506000      .000      .000  
+741113 42364.00 I  -.025251  .027899   .237761  .026178  I -.1528176  .0002710  3.1363 0.1916  P    37.025     .500     -.047     .300  -.017000   .263000  -.1537000      .000      .000  
+741114 42365.00 I  -.025948  .024211   .238390  .022738  I -.1558584  .0002710  2.9512 0.1916  P    37.146     .500     -.221     .300  -.018000   .263000  -.1568000      .000      .000  
+741115 42366.00 I  -.026638  .017488   .239023  .022569  I -.1587363  .0002710  2.8149 0.1916  P    37.319     .500     -.280     .300  -.018000   .264000  -.1599000      .000      .000  
+741116 42367.00 I  -.027322  .015223   .239655  .021575  I -.1615100  .0002710  2.7439 0.1916  P    37.523     .500     -.160     .300  -.019000   .264000  -.1629000      .000      .000  
+741117 42368.00 I  -.027999  .016952   .240288  .024873  I -.1642452  .0002710  2.7364 0.1916  P    37.778     .500      .047     .300  -.019000   .265000  -.1660000      .000      .000  
+741118 42369.00 I  -.028670  .015219   .240920  .021700  I -.1669996  .0002710  2.7795 0.1916  P    38.116     .500      .197     .300  -.020000   .265000  -.1691000      .000      .000  
+741119 42370.00 I  -.029332  .005271   .241553  .011159  I -.1698154  .0002710  2.8561 0.1916  P    38.519     .500      .215     .300  -.021000   .265000  -.1722000      .000      .000  
+741120 42371.00 I  -.029984  .007877   .242187  .009697  I -.1727172  .0002710  2.9489 0.1916  P    38.874     .500      .129     .300  -.021000   .266000  -.1753000      .000      .000  
+741121 42372.00 I  -.030624  .008918   .242822  .011014  I -.1757133  .0002710  3.0422 0.1916  P    39.038     .500      .037     .300  -.022000   .266000  -.1783000      .000      .000  
+741122 42373.00 I  -.031252  .007784   .243455  .011306  I -.1787966  .0002710  3.1207 0.1916  P    38.959     .500      .013     .300  -.022000   .267000  -.1814000      .000      .000  
+741123 42374.00 I  -.031866  .008811   .244087  .007691  I -.1819454  .0002710  3.1714 0.1916  P    38.721     .500      .042     .300  -.023000   .267000  -.1845000      .000      .000  
+741124 42375.00 I  -.032463  .008922   .244716  .016418  I -.1851271  .0002710  3.1852 0.2967  P    38.457     .500      .046     .300  -.024000   .267000  -.1876000      .000      .000  
+741125 42376.00 I  -.033043  .009202   .245339  .018715  I -.1883019  .0005279  3.1574 0.2967  P    38.251     .500      .007     .300  -.025000   .268000  -.1906000      .000      .000  
+741126 42377.00 I  -.033605  .011661   .245957  .018537  I -.1914286  .0005279  3.0896 0.3733  P    38.129     .500      .026     .300  -.025000   .268000  -.1937000      .000      .000  
+741127 42378.00 I  -.034149  .011242   .246568  .021384  I -.1944705  .0005279  2.9898 0.3733  P    38.095     .500      .205     .300  -.026000   .269000  -.1967000      .000      .000  
+741128 42379.00 I  -.034674  .010017   .247172  .018721  I -.1974034  .0005279  2.8754 0.3733  P    38.147     .500      .477     .300  -.027000   .269000  -.1998000      .000      .000  
+741129 42380.00 I  -.035178  .011512   .247771  .020449  I -.2002257  .0005279  2.7742 0.3733  P    38.287     .500      .641     .300  -.028000   .269000  -.2029000      .000      .000  
+741130 42381.00 I  -.035660  .011259   .248366  .019127  I -.2029672  .0005279  2.7191 0.2967  P    38.522     .500      .578     .300  -.029000   .270000  -.2059000      .000      .000  
+7412 1 42382.00 I  -.036119  .011855   .248959  .013694  I -.2056880  .0002710  2.7362 0.2967  P    38.831     .500      .381     .300  -.029000   .270000  -.2090000      .000      .000  
+7412 2 42383.00 I  -.036555  .014117   .249549  .011865  I -.2084660  .0002710  2.8324 0.1916  P    39.120     .500      .242     .300  -.030000   .271000  -.2120000      .000      .000  
+7412 3 42384.00 I  -.036969  .013003   .250136  .008934  I -.2113722  .0002710  2.9868 0.1916  P    39.263     .500      .251     .300  -.031000   .271000  -.2151000      .000      .000  
+7412 4 42385.00 I  -.037360  .011264   .250720  .008184  I -.2144449  .0002710  3.1571 0.1916  P    39.218     .500      .355     .300  -.031000   .271000  -.2180000      .000      .000  
+7412 5 42386.00 I  -.037727  .012718   .251301  .008905  I -.2176753  .0002710  3.2941 0.1916  P    39.079     .500      .466     .300  -.032000   .272000  -.2210000      .000      .000  
+7412 6 42387.00 I  -.038067  .013288   .251878  .018719  I -.2210090  .0002710  3.3588 0.1916  P    38.979     .500      .560     .300  -.032000   .272000  -.2239000      .000      .000  
+7412 7 42388.00 I  -.038382  .014103   .252448  .019939  I -.2243632  .0002710  3.3343 0.1916  P    38.961     .500      .669     .300  -.033000   .273000  -.2269000      .000      .000  
+7412 8 42389.00 I  -.038673  .015565   .253012  .017587  I -.2276498  .0002710  3.2262 0.1916  P    38.957     .500      .815     .300  -.033000   .273000  -.2298000      .000      .000  
+7412 9 42390.00 I  -.038940  .014067   .253568  .020304  I -.2307956  .0002710  3.0579 0.1916  P    38.867     .500      .961     .300  -.033000   .273000  -.2326000      .000      .000  
+741210 42391.00 I  -.039184  .014547   .254115  .018221  I -.2337566  .0002710  2.8625 0.1916  P    38.676     .500     1.027     .300  -.034000   .274000  -.2354000      .000      .000  
+741211 42392.00 I  -.039408  .016796   .254656  .020813  I -.2365234  .0002710  2.6754 0.1916  P    38.495     .500      .963     .300  -.034000   .274000  -.2381000      .000      .000  
+741212 42393.00 I  -.039614  .016993   .255193  .025832  I -.2391202  .0002710  2.5268 0.1916  P    38.486     .500      .819     .300  -.035000   .275000  -.2409000      .000      .000  
+741213 42394.00 I  -.039809  .017645   .255726  .022401  I -.2415963  .0002710  2.4361 0.1916  P    38.704     .500      .724     .300  -.035000   .275000  -.2437000      .000      .000  
+741214 42395.00 I  -.039996  .015983   .256257  .019487  I -.2440136  .0002710  2.4090 0.1916  P    39.036     .500      .776     .300  -.035000   .275000  -.2463000      .000      .000  
+741215 42396.00 I  -.040178  .014713   .256789  .022169  I -.2464328  .0002710  2.4375 0.1916  P    39.343     .500      .954     .300  -.035000   .276000  -.2490000      .000      .000  
+741216 42397.00 I  -.040360  .014467   .257323  .021215  I -.2489018  .0002710  2.5056 0.1916  P    39.606     .500     1.142     .300  -.036000   .276000  -.2516000      .000      .000  
+741217 42398.00 I  -.040542  .013955   .257858  .023867  I -.2514511  .0002710  2.5949 0.1916  P    39.857     .500     1.228     .300  -.036000   .277000  -.2543000      .000      .000  
+741218 42399.00 I  -.040724  .012341   .258394  .021131  I -.2540928  .0002710  2.6877 0.1916  P    40.025     .500     1.194     .300  -.036000   .277000  -.2569000      .000      .000  
+741219 42400.00 I  -.040910  .010006   .258930  .011782  I -.2568225  .0002710  2.7686 0.1916  P    39.984     .500     1.121     .300  -.036000   .277000  -.2595000      .000      .000  
+741220 42401.00 I  -.041101  .011267   .259466  .012572  I -.2596221  .0002710  2.8257 0.1916  P    39.751     .500     1.100     .300  -.036000   .278000  -.2621000      .000      .000  
+741221 42402.00 I  -.041297  .011834   .260000  .014361  I -.2624630  .0002710  2.8502 0.1916  P    39.503     .500     1.135     .300  -.037000   .278000  -.2648000      .000      .000  
+741222 42403.00 I  -.041498  .012767   .260534  .013773  I -.2653103  .0002710  2.8382 0.1916  P    39.346     .500     1.128     .300  -.037000   .279000  -.2674000      .000      .000  
+741223 42404.00 I  -.041705  .012439   .261069  .012013  I -.2681275  .0002710  2.7907 0.1916  P    39.210     .500     1.013     .300  -.037000   .279000  -.2700000      .000      .000  
+741224 42405.00 I  -.041917  .016573   .261606  .010522  I -.2708818  .0002710  2.7137 0.1916  P    39.019     .500      .889     .300  -.037000   .279000  -.2726000      .000      .000  
+741225 42406.00 I  -.042136  .018919   .262144  .011042  I -.2735492  .0002710  2.6195 0.1916  P    38.851     .500      .924     .300  -.037000   .279000  -.2752000      .000      .000  
+741226 42407.00 I  -.042362  .021855   .262684  .009594  I -.2761222  .0002710  2.5293 0.1916  P    38.830     .500     1.117     .300  -.038000   .280000  -.2777000      .000      .000  
+741227 42408.00 I  -.042596  .023827   .263227  .007128  I -.2786190  .0002710  2.4727 0.1916  P    38.977     .500     1.240     .300  -.038000   .280000  -.2803000      .000      .000  
+741228 42409.00 I  -.042837  .023827   .263773  .007128  I -.2810892  .0002710  2.4807 0.1916  P    39.237     .500     1.096     .300  -.038000   .280000  -.2829000      .000      .000  
+741229 42410.00 I  -.043081  .027122   .264322  .002483  I -.2836080  .0002710  2.5713 0.1916  P    39.556     .500      .777     .300  -.038000   .280000  -.2855000      .000      .000  
+741230 42411.00 I  -.043325  .028310   .264876  .023533  I -.2862566  .0002710  2.7363 0.1916  P    39.851     .500      .568     .300  -.038000   .280000  -.2882000      .000      .000  
+741231 42412.00 I  -.043569  .029749   .265436  .028736  I -.2890927  .0002710  2.9375 0.1916  P    39.981     .500      .627     .300  -.039000   .281000  -.2908000      .000      .000  
+75 1 1 42413.00 I  -.043813  .024593   .266001  .023470  I  .7078756  .0002710  3.1172 0.1916  P    39.881     .500      .847     .300  -.039000   .281000   .7065000      .000      .000  
+75 1 2 42414.00 I  -.044056  .022109   .266573  .028724  I  .7046980  .0002710  3.2216 0.1916  P    39.658     .500     1.037     .300  -.039000   .281000   .7039000      .000      .000  
+75 1 3 42415.00 I  -.044299  .018390   .267153  .024374  I  .7014674  .0002710  3.2212 0.1916  P    39.483     .500     1.129     .300  -.039000   .281000   .7012000      .000      .000  
+75 1 4 42416.00 I  -.044538  .018390   .267744  .024374  I  .6982891  .0002710  3.1205 0.1916  P    39.405     .500     1.174     .300  -.039000   .282000   .6986000      .000      .000  
+75 1 5 42417.00 I  -.044768  .020644   .268350  .029016  I  .6952497  .0002710  2.9500 0.1916  P    39.348     .500     1.204     .300  -.040000   .282000   .6959000      .000      .000  
+75 1 6 42418.00 I  -.044988  .016038   .268975  .023935  I  .6923984  .0002710  2.7517 0.1916  P    39.226     .500     1.192     .300  -.040000   .283000   .6933000      .000      .000  
+75 1 7 42419.00 I  -.045193  .015936   .269624  .020759  I  .6897425  .0002710  2.5648 0.1916  P    39.023     .500     1.112     .300  -.040000   .283000   .6906000      .000      .000  
+75 1 8 42420.00 I  -.045381  .017994   .270298  .023963  I  .6872556  .0002710  2.4175 0.1916  P    38.799     .500      .992     .300  -.040000   .283000   .6879000      .000      .000  
+75 1 9 42421.00 I  -.045545  .016918   .271002  .020839  I  .6848888  .0002710  2.3263 0.1916  P    38.672     .500      .884     .300  -.040000   .284000   .6853000      .000      .000  
+75 110 42422.00 I  -.045681  .017869   .271735  .020617  I  .6825825  .0002710  2.2967 0.1916  P    38.736     .500      .825     .300  -.039000   .284000   .6826000      .000      .000  
+75 111 42423.00 I  -.045780  .016065   .272497  .018874  I  .6802763  .0002710  2.3246 0.1916  P    38.961     .500      .838     .300  -.039000   .285000   .6800000      .000      .000  
+75 112 42424.00 I  -.045838  .011104   .273288  .007385  I  .6779183  .0002710  2.3977 0.1916  P    39.219     .500      .932     .300  -.039000   .285000   .6773000      .000      .000  
+75 113 42425.00 I  -.045849  .017543   .274108  .008335  I  .6754717  .0002710  2.4984 0.1916  P    39.431     .500     1.082     .300  -.039000   .286000   .6746000      .000      .000  
+75 114 42426.00 I  -.045810  .018481   .274956  .009561  I  .6729187  .0002710  2.6074 0.1916  P    39.588     .500     1.210     .300  -.038000   .286000   .6719000      .000      .000  
+75 115 42427.00 I  -.045718  .017283   .275833  .009310  I  .6702599  .0002710  2.7072 0.1916  P    39.642     .500     1.239     .300  -.038000   .287000   .6691000      .000      .000  
+75 116 42428.00 I  -.045572  .017033   .276739  .010330  I  .6675120  .0002710  2.7838 0.1916  P    39.522     .500     1.167     .300  -.037000   .287000   .6664000      .000      .000  
+75 117 42429.00 I  -.045372  .018276   .277675  .012408  I  .6647030  .0002710  2.8284 0.1916  P    39.297     .500     1.079     .300  -.037000   .288000   .6637000      .000      .000  
+75 118 42430.00 I  -.045120  .019795   .278643  .014775  I  .6618672  .0002710  2.8371 0.3211  P    39.166     .500     1.035     .300  -.036000   .289000   .6610000      .000      .000  
+75 119 42431.00 I  -.044818  .022021   .279643  .014884  I  .6590403  .0005823  2.8112 0.3211  P    39.193     .500      .979     .300  -.036000   .289000   .6582000      .000      .000  
+75 120 42432.00 I  -.044467  .019029   .280677  .014510  I  .6562544  .0005823  2.7565 0.4117  P    39.185     .500      .819     .300  -.035000   .290000   .6555000      .000      .000  
+75 121 42433.00 I  -.044070  .018518   .281746  .013774  I  .6535334  .0005823  2.6836 0.4117  P    38.957     .500      .601     .300  -.035000   .290000   .6527000      .000      .000  
+75 122 42434.00 I  -.043628  .019424   .282851  .014309  I  .6508876  .0005823  2.6093 0.4117  P    38.595     .500      .511     .300  -.034000   .291000   .6500000      .000      .000  
+75 123 42435.00 I  -.043138  .019011   .283988  .015448  I  .6483073  .0005823  2.5573 0.4117  P    38.326     .500      .626     .300  -.033000   .292000   .6472000      .000      .000  
+75 124 42436.00 I  -.042603  .023491   .285155  .013692  I  .6457559  .0005823  2.5567 0.3211  P    38.256     .500      .752     .300  -.032000   .292000   .6443000      .000      .000  
+75 125 42437.00 I  -.042021  .022965   .286350  .010985  I  .6431682  .0002710  2.6332 0.3211  P    38.354     .500      .637     .300  -.032000   .293000   .6415000      .000      .000  
+75 126 42438.00 I  -.041394  .027165   .287570  .009970  I  .6404612  .0002710  2.7945 0.1916  P    38.593     .500      .314     .300  -.031000   .293000   .6386000      .000      .000  
+75 127 42439.00 I  -.040726  .026099   .288813  .009830  I  .6375585  .0002710  3.0179 0.1916  P    38.925     .500      .093     .300  -.030000   .294000   .6358000      .000      .000  
+75 128 42440.00 I  -.040018  .025657   .290078  .012892  I  .6344222  .0002710  3.2507 0.1916  P    39.206     .500      .188     .300  -.029000   .295000   .6328000      .000      .000  
+75 129 42441.00 I  -.039271  .024739   .291366  .011992  I  .6310758  .0002710  3.4272 0.1916  P    39.306     .500      .475     .300  -.028000   .295000   .6299000      .000      .000  
+75 130 42442.00 I  -.038487  .027779   .292676  .010691  I  .6276040  .0002710  3.4949 0.1916  P    39.260     .500      .689     .300  -.026000   .296000   .6269000      .000      .000  
+75 131 42443.00 I  -.037672  .023350   .294007  .018348  I  .6241280  .0002710  3.4366 0.1916  P    39.181     .500      .734     .300  -.025000   .296000   .6240000      .000      .000  
+75 2 1 42444.00 I  -.036831  .022707   .295362  .018633  I  .6207651  .0002710  3.2755 0.1916  P    39.094     .500      .697     .300  -.024000   .297000   .6210000      .000      .000  
+75 2 2 42445.00 I  -.035972  .014775   .296738  .019207  I  .6175948  .0002710  3.0610 0.1916  P    38.964     .500      .628     .300  -.023000   .298000   .6181000      .000      .000  
+75 2 3 42446.00 I  -.035098  .017407   .298134  .019805  I  .6146428  .0002710  2.8472 0.1916  P    38.826     .500      .468     .300  -.022000   .299000   .6151000      .000      .000  
+75 2 4 42447.00 I  -.034215  .016949   .299551  .018489  I  .6118869  .0002710  2.6737 0.1916  P    38.736     .500      .203     .300  -.022000   .300000   .6122000      .000      .000  
+75 2 5 42448.00 I  -.033323  .020700   .300984  .018641  I  .6092753  .0002710  2.5603 0.1916  P    38.642     .500     -.053     .300  -.021000   .301000   .6092000      .000      .000  
+75 2 6 42449.00 I  -.032428  .016985   .302432  .017931  I  .6067448  .0002710  2.5112 0.1916  P    38.471     .500     -.185     .300  -.020000   .302000   .6063000      .000      .000  
+75 2 7 42450.00 I  -.031533  .016188   .303890  .013287  I  .6042334  .0002710  2.5205 0.1916  P    38.296     .500     -.206     .300  -.019000   .303000   .6034000      .000      .000  
+75 2 8 42451.00 I  -.030641  .016046   .305355  .012596  I  .6016879  .0002710  2.5775 0.1916  P    38.280     .500     -.197     .300  -.018000   .304000   .6005000      .000      .000  
+75 2 9 42452.00 I  -.029752  .021826   .306822  .014655  I  .5990674  .0002710  2.6675 0.1916  P    38.470     .500     -.171     .300  -.018000   .306000   .5975000      .000      .000  
+75 210 42453.00 I  -.028867  .019896   .308289  .014059  I  .5963479  .0002710  2.7723 0.1916  P    38.756     .500     -.075     .300  -.017000   .307000   .5946000      .000      .000  
+75 211 42454.00 I  -.027985  .020009   .309752  .013988  I  .5935241  .0002710  2.8730 0.1916  P    39.002     .500      .075     .300  -.016000   .308000   .5917000      .000      .000  
+75 212 42455.00 I  -.027107  .017072   .311208  .013989  I  .5906088  .0002710  2.9528 0.1916  P    39.124     .500      .152     .300  -.015000   .309000   .5888000      .000      .000  
+75 213 42456.00 I  -.026233  .017678   .312651  .016142  I  .5876293  .0002710  3.0001 0.1916  P    39.092     .500      .059     .300  -.014000   .310000   .5859000      .000      .000  
+75 214 42457.00 I  -.025359  .018935   .314078  .014714  I  .5846213  .0002710  3.0094 0.1916  P    38.986     .500     -.146     .300  -.014000   .312000   .5830000      .000      .000  
+75 215 42458.00 I  -.024481  .020649   .315489  .017452  I  .5816232  .0002710  2.9808 0.1916  P    38.969     .500     -.328     .300  -.013000   .313000   .5801000      .000      .000  
+75 216 42459.00 I  -.023595  .014177   .316880  .015465  I  .5786704  .0002710  2.9202 0.1916  P    39.099     .500     -.448     .300  -.012000   .314000   .5772000      .000      .000  
+75 217 42460.00 I  -.022698  .014375   .318250  .015363  I  .5757901  .0002710  2.8377 0.1916  P    39.194     .500     -.588     .300  -.011000   .315000   .5743000      .000      .000  
+75 218 42461.00 I  -.021785  .015949   .319596  .014755  I  .5729971  .0002710  2.7488 0.1916  P    39.041     .500     -.782     .300  -.011000   .316000   .5714000      .000      .000  
+75 219 42462.00 I  -.020854  .017702   .320913  .014759  I  .5702878  .0002710  2.6741 0.1916  P    38.674     .500     -.915     .300  -.010000   .318000   .5686000      .000      .000  
+75 220 42463.00 I  -.019901  .018204   .322199  .013429  I  .5676357  .0002710  2.6390 0.1916  P    38.323     .500     -.883     .300  -.010000   .319000   .5657000      .000      .000  
+75 221 42464.00 I  -.018922  .017853   .323451  .014297  I  .5649878  .0002710  2.6697 0.1916  P    38.140     .500     -.796     .300  -.009000   .320000   .5628000      .000      .000  
+75 222 42465.00 I  -.017916  .015959   .324668  .011230  I  .5622687  .0002710  2.7831 0.4960  P    38.127     .500     -.867     .300  -.008000   .321000   .5600000      .000      .000  
+75 223 42466.00 I  -.016879  .016534   .325847  .010394  I  .5593957  .0009542  2.9744 0.4960  P    38.252     .500    -1.110     .300  -.008000   .322000   .5572000      .000      .000  
+75 224 42467.00 I  -.015812  .016512   .326987  .012503  I  .5563054  .0009542  3.2094 0.6747  P    38.485     .500    -1.267     .300  -.007000   .323000   .5543000      .000      .000  
+75 225 42468.00 I  -.014712  .027310   .328087  .013680  I  .5529823  .0009542  3.4284 0.6747  P    38.732     .500    -1.130     .300  -.007000   .324000   .5515000      .000      .000  
+75 226 42469.00 I  -.013581  .026073   .329149  .015755  I  .5494757  .0009542  3.5663 0.6747  P    38.893     .500     -.821     .300  -.006000   .325000   .5487000      .000      .000  
+75 227 42470.00 I  -.012420  .025357   .330173  .014861  I  .5458914  .0009542  3.5793 0.5872  P    38.975     .500     -.635     .300  -.006000   .326000   .5459000      .000      .000  
+75 228 42471.00 I  -.011231  .024959   .331158  .012962  I  .5423600  .0006845  3.4636 0.4840  P    39.018     .500     -.681     .300  -.005000   .327000   .5432000      .000      .000  
+75 3 1 42472.00 I  -.010016  .025611   .332105  .014933  I  .5389947  .0001625  3.2562 0.3518  P    38.985     .500     -.828     .300  -.005000   .327000   .5404000      .000      .000  
+75 3 2 42473.00 I  -.008773  .026568   .333012  .014809  I  .5358580  .0001625  3.0174 0.1472  P    38.853     .500     -.969     .300  -.004000   .328000   .5377000      .000      .000  
+75 3 3 42474.00 I  -.007500  .026451   .333880  .013388  I  .5329514  .0002456  2.8042 0.1472  P    38.758     .500    -1.159     .300  -.004000   .329000   .5349000      .000      .000  
+75 3 4 42475.00 I  -.006197  .015960   .334705  .012026  I  .5302293  .0002456  2.6521 0.1737  P    38.824     .500    -1.454     .300  -.004000   .330000   .5321000      .000      .000  
+75 3 5 42476.00 I  -.004863  .017065   .335489  .009368  I  .5276233  .0002456  2.5719 0.1965  P    38.914     .500    -1.745     .300  -.003000   .331000   .5292000      .000      .000  
+75 3 6 42477.00 I  -.003500  .023307   .336232  .009321  I  .5250636  .0003069  2.5574 0.1965  P    38.778     .500    -1.889     .300  -.003000   .331000   .5264000      .000      .000  
+75 3 7 42478.00 I  -.002108  .029753   .336934  .009360  I  .5224911  .0003069  2.5950 0.2170  P    38.452     .500    -1.896     .300  -.002000   .332000   .5235000      .000      .000  
+75 3 8 42479.00 I  -.000692  .029555   .337597  .005197  I  .5198611  .0003069  2.6700 0.2047  P    38.286     .500    -1.890     .300  -.002000   .333000   .5207000      .000      .000  
+75 3 9 42480.00 I   .000744  .028481   .338223  .005257  I  .5171438  .0002710  2.7668 0.2047  P    38.513     .500    -1.901     .300  -.002000   .334000   .5178000      .000      .000  
+75 310 42481.00 I   .002194  .028602   .338812  .010660  I  .5143260  .0002710  2.8681 0.1916  P    38.986     .500    -1.835     .300  -.001000   .334000   .5149000      .000      .000  
+75 311 42482.00 I   .003653  .028150   .339365  .010763  I  .5114119  .0002710  2.9564 0.1916  P    39.396     .500    -1.665     .300  -.001000   .335000   .5121000      .000      .000  
+75 312 42483.00 I   .005126  .026852   .339885  .010375  I  .5084225  .0002710  3.0167 0.1916  P    39.591     .500    -1.533     .300   .000000   .335000   .5092000      .000      .000  
+75 313 42484.00 I   .006613  .021501   .340372  .011366  I  .5053905  .0002710  3.0408 0.1916  P    39.605     .500    -1.605     .300   .000000   .336000   .5063000      .000      .000  
+75 314 42485.00 I   .008116  .009967   .340829  .013656  I  .5023538  .0002710  3.0262 0.1916  P    39.548     .500    -1.867     .300   .001000   .337000   .5033000      .000      .000  
+75 315 42486.00 I   .009635  .010404   .341255  .014170  I  .4993497  .0002710  2.9769 0.1916  P    39.541     .500    -2.147     .300   .001000   .337000   .5003000      .000      .000  
+75 316 42487.00 I   .011171  .014487   .341651  .014443  I  .4964084  .0002710  2.9024 0.1916  P    39.650     .500    -2.319     .300   .002000   .338000   .4974000      .000      .000  
+75 317 42488.00 I   .012726  .015678   .342017  .010889  I  .4935487  .0002710  2.8166 0.1916  P    39.795     .500    -2.415     .300   .002000   .338000   .4944000      .000      .000  
+75 318 42489.00 I   .014304  .014246   .342352  .011073  I  .4907725  .0002710  2.7389 0.1916  P    39.814     .500    -2.520     .300   .003000   .339000   .4914000      .000      .000  
+75 319 42490.00 I   .015905  .014675   .342660  .011739  I  .4880607  .0002710  2.6919 0.1916  P    39.657     .500    -2.629     .300   .004000   .340000   .4883000      .000      .000  
+75 320 42491.00 I   .017531  .014824   .342942  .013082  I  .4853706  .0002710  2.6993 0.1916  P    39.464     .500    -2.682     .300   .005000   .340000   .4852000      .000      .000  
+75 321 42492.00 I   .019180  .018094   .343198  .011215  I  .4826378  .0002710  2.7795 0.1916  P    39.396     .500    -2.701     .300   .005000   .341000   .4821000      .000      .000  
+75 322 42493.00 I   .020849  .018025   .343430  .011563  I  .4797859  .0002710  2.9369 0.2593  P    39.488     .500    -2.786     .300   .006000   .341000   .4790000      .000      .000  
+75 323 42494.00 I   .022537  .015014   .343638  .011325  I  .4767436  .0004421  3.1554 0.2593  P    39.668     .500    -2.936     .300   .007000   .342000   .4759000      .000      .000  
+75 324 42495.00 I   .024242  .013963   .343820  .013510  I  .4734686  .0004421  3.3932 0.3126  P    39.827     .500    -2.979     .300   .008000   .342000   .4727000      .000      .000  
+75 325 42496.00 I   .025962  .015343   .343976  .014857  I  .4699702  .0004421  3.5919 0.3126  P    39.877     .500    -2.780     .300   .009000   .343000   .4695000      .000      .000  
+75 326 42497.00 I   .027694  .014774   .344104  .017618  I  .4663166  .0004421  3.6952 0.3126  P    39.812     .500    -2.461     .300   .010000   .343000   .4664000      .000      .000  
+75 327 42498.00 I   .029437  .015044   .344201  .016367  I  .4626221  .0004421  3.6715 0.3126  P    39.733     .500    -2.302     .300   .011000   .344000   .4632000      .000      .000  
+75 328 42499.00 I   .031187  .016712   .344266  .015578  I  .4590129  .0004421  3.5298 0.2593  P    39.715     .500    -2.422     .300   .012000   .344000   .4600000      .000      .000  
+75 329 42500.00 I   .032941  .015697   .344294  .015187  I  .4555869  .0002710  3.3150 0.2932  P    39.702     .500    -2.665     .300   .013000   .344000   .4569000      .000      .000  
+75 330 42501.00 I   .034696  .015756   .344283  .015494  I  .4523866  .0003853  3.0890 0.2355  P    39.636     .500    -2.841     .300   .015000   .344000   .4538000      .000      .000  
+75 331 42502.00 I   .036448  .019185   .344232  .013966  I  .4493950  .0003853  2.9046 0.2724  P    39.626     .500    -2.938     .300   .016000   .344000   .4507000      .000      .000  
+75 4 1 42503.00 I   .038197  .018087   .344141  .012700  I  .4465544  .0003853  2.7893 0.2724  P    39.785     .500    -3.052     .300   .018000   .344000   .4476000      .000      .000  
+75 4 2 42504.00 I   .039936  .018807   .344009  .008052  I  .4437925  .0003853  2.7456 0.2724  P    39.958     .500    -3.190     .300   .019000   .344000   .4445000      .000      .000  
+75 4 3 42505.00 I   .041661  .018590   .343836  .007529  I  .4410437  .0003853  2.7603 0.2724  P    39.852     .500    -3.280     .300   .020000   .344000   .4415000      .000      .000  
+75 4 4 42506.00 I   .043367  .015648   .343622  .008367  I  .4382584  .0003853  2.8156 0.2355  P    39.493     .500    -3.320     .300   .021000   .344000   .4386000      .000      .000  
+75 4 5 42507.00 I   .045053  .015515   .343367  .008001  I  .4354043  .0002710  2.8954 0.2355  P    39.294     .500    -3.379     .300   .023000   .345000   .4356000      .000      .000  
+75 4 6 42508.00 I   .046719  .017748   .343070  .008399  I  .4324646  .0002710  2.9843 0.1916  P    39.556     .500    -3.449     .300   .024000   .345000   .4327000      .000      .000  
+75 4 7 42509.00 I   .048364  .013572   .342730  .011161  I  .4294378  .0002710  3.0668 0.1916  P    40.091     .500    -3.423     .300   .025000   .345000   .4297000      .000      .000  
+75 4 8 42510.00 I   .049985  .017553   .342348  .011085  I  .4263381  .0002710  3.1278 0.1916  P    40.474     .500    -3.259     .300   .026000   .345000   .4268000      .000      .000  
+75 4 9 42511.00 I   .051578  .018329   .341921  .010870  I  .4231931  .0002710  3.1560 0.1916  P    40.524     .500    -3.090     .300   .027000   .345000   .4239000      .000      .000  
+75 410 42512.00 I   .053137  .022640   .341449  .010892  I  .4200387  .0002710  3.1464 0.1916  P    40.372     .500    -3.094     .300   .029000   .345000   .4211000      .000      .000  
+75 411 42513.00 I   .054661  .023079   .340931  .010201  I  .4169125  .0002710  3.1004 0.1916  P    40.203     .500    -3.293     .300   .030000   .345000   .4182000      .000      .000  
+75 412 42514.00 I   .056146  .024106   .340369  .012818  I  .4138476  .0002710  3.0255 0.1916  P    40.109     .500    -3.548     .300   .031000   .345000   .4153000      .000      .000  
+75 413 42515.00 I   .057593  .022407   .339764  .011848  I  .4108669  .0002710  2.9344 0.1916  P    40.136     .500    -3.724     .300   .032000   .345000   .4124000      .000      .000  
+75 414 42516.00 I   .058999  .022761   .339119  .009958  I  .4079785  .0002710  2.8443 0.1916  P    40.285     .500    -3.809     .300   .033000   .345000   .4095000      .000      .000  
+75 415 42517.00 I   .060367  .019979   .338435  .010111  I  .4051706  .0002710  2.7773 0.1916  P    40.460     .500    -3.869     .300   .035000   .344000   .4065000      .000      .000  
+75 416 42518.00 I   .061701  .019270   .337716  .010759  I  .4024088  .0002710  2.7557 0.1916  P    40.538     .500    -3.941     .300   .036000   .344000   .4036000      .000      .000  
+75 417 42519.00 I   .063009  .019183   .336966  .020934  I  .3996382  .0002710  2.7970 0.1916  P    40.515     .500    -4.017     .300   .037000   .344000   .4007000      .000      .000  
+75 418 42520.00 I   .064296  .016990   .336186  .021301  I  .3967917  .0002710  2.9075 0.1356  P    40.515     .500    -4.089     .300   .038000   .343000   .3977000      .000      .000  
+75 419 42521.00 I   .065567  .015814   .335382  .019725  I  .3938035  .0000076  3.0772 0.1356  P    40.648     .500    -4.168     .300   .039000   .343000   .3947000      .000      .000  
+75 420 42522.00 I   .066826  .019725   .334554  .019875  I  .3906270  .0000076  3.2780 0.0054  P    40.892     .500    -4.224     .300   .041000   .342000   .3917000      .000      .000  
+75 421 42523.00 I   .068077  .020744   .333704  .019108  I  .3872515  .0000076  3.4669 0.1804  P    41.099     .500    -4.160     .300   .042000   .342000   .3887000      .000      .000  
+75 422 42524.00 I   .069321  .023399   .332833  .021009  I  .3837133  .0003608  3.5956 0.1804  P    41.112     .500    -3.916     .300   .043000   .341000   .3857000      .000      .000  
+75 423 42525.00 I   .070557  .023884   .331940  .020543  I  .3800930  .0003608  3.6261 0.2551  P    40.908     .500    -3.593     .300   .044000   .340000   .3826000      .000      .000  
+75 424 42526.00 I   .071788  .020385   .331024  .011059  I  .3764981  .0003608  3.5455 0.3124  P    40.627     .500    -3.417     .300   .045000   .339000   .3796000      .000      .000  
+75 425 42527.00 I   .073014  .021086   .330086  .021849  I  .3730323  .0005102  3.3741 0.3124  P    40.429     .500    -3.518     .300   .046000   .338000   .3765000      .000      .000  
+75 426 42528.00 I   .074238  .022092   .329124  .022757  I  .3697646  .0005102  3.1587 0.3157  P    40.357     .500    -3.783     .300   .047000   .337000   .3735000      .000      .000  
+75 427 42529.00 I   .075463  .023969   .328141  .022638  I  .3667112  .0003719  2.9545 0.2630  P    40.374     .500    -3.977     .300   .048000   .336000   .3704000      .000      .000  
+75 428 42530.00 I   .076690  .024582   .327137  .023180  I  .3638376  .0001276  2.8041 0.1935  P    40.490     .500    -3.987     .300   .049000   .335000   .3674000      .000      .000  
+75 429 42531.00 I   .077921  .021790   .326113  .021730  I  .3610792  .0001069  2.7249 0.0832  P    40.706     .500    -3.887     .300   .050000   .334000   .3643000      .000      .000  
+75 430 42532.00 I   .079157  .020791   .325068  .023010  I  .3583660  .0001069  2.7111 0.0771  P    40.870     .500    -3.810     .300   .051000   .332000   .3613000      .000      .000  
+75 5 1 42533.00 I   .080398  .020809   .324001  .022596  I  .3556415  .0001112  2.7439 0.0771  P    40.772     .500    -3.829     .300   .052000   .331000   .3582000      .000      .000  
+75 5 2 42534.00 I   .081641  .025199   .322911  .014921  I  .3528694  .0001112  2.8032 0.2490  P    40.455     .500    -3.952     .300   .053000   .330000   .3552000      .000      .000  
+75 5 3 42535.00 I   .082882  .025309   .321798  .013709  I  .3500319  .0004854  2.8721 0.2490  P    40.256     .500    -4.145     .300   .054000   .329000   .3522000      .000      .000  
+75 5 4 42536.00 I   .084121  .023017   .320663  .017797  I  .3471267  .0004854  2.9364 0.3827  P    40.414     .500    -4.312     .300   .055000   .327000   .3492000      .000      .000  
+75 5 5 42537.00 I   .085356  .020825   .319504  .017220  I  .3441649  .0005918  2.9832 0.3827  P    40.754     .500    -4.337     .300   .055000   .326000   .3462000      .000      .000  
+75 5 6 42538.00 I   .086586  .021746   .318325  .016862  I  .3411700  .0005918  3.0010 0.5090  P    40.897     .500    -4.200     .300   .056000   .324000   .3432000      .000      .000  
+75 5 7 42539.00 I   .087811  .021790   .317127  .021524  I  .3381746  .0008283  2.9837 0.5090  P    40.691     .500    -4.027     .300   .057000   .323000   .3402000      .000      .000  
+75 5 8 42540.00 I   .089031  .024637   .315913  .021903  I  .3352143  .0008283  2.9312 0.4358  P    40.305     .500    -3.963     .300   .058000   .322000   .3373000      .000      .000  
+75 5 9 42541.00 I   .090241  .019422   .314689  .020433  I  .3323221  .0002710  2.8489 0.4358  P    39.960     .500    -4.026     .300   .059000   .321000   .3344000      .000      .000  
+75 510 42542.00 I   .091439  .019385   .313459  .021471  I  .3295229  .0002710  2.7474 0.1916  P    39.749     .500    -4.136     .300   .059000   .319000   .3314000      .000      .000  
+75 511 42543.00 I   .092621  .016215   .312226  .020481  I  .3268285  .0002710  2.6424 0.1916  P    39.691     .500    -4.231     .300   .060000   .318000   .3285000      .000      .000  
+75 512 42544.00 I   .093786  .025007   .310993  .021438  I  .3242325  .0002710  2.5543 0.1916  P    39.806     .500    -4.320     .300   .061000   .317000   .3256000      .000      .000  
+75 513 42545.00 I   .094932  .024534   .309761  .021070  I  .3217068  .0002710  2.5056 0.1916  P    40.054     .500    -4.417     .300   .062000   .316000   .3228000      .000      .000  
+75 514 42546.00 I   .096058  .025432   .308531  .015751  I  .3192016  .0002710  2.5159 0.1916  P    40.291     .500    -4.493     .300   .063000   .314000   .3200000      .000      .000  
+75 515 42547.00 I   .097163  .022993   .307303  .016795  I  .3166529  .0002710  2.5924 0.1916  P    40.377     .500    -4.511     .300   .064000   .313000   .3172000      .000      .000  
+75 516 42548.00 I   .098247  .023162   .306076  .018229  I  .3139979  .0002710  2.7256 0.1916  P    40.308     .500    -4.470     .300   .065000   .311000   .3144000      .000      .000  
+75 517 42549.00 I   .099311  .022905   .304848  .018864  I  .3111915  .0002710  2.8895 0.1916  P    40.209     .500    -4.401     .300   .066000   .310000   .3116000      .000      .000  
+75 518 42550.00 I   .100359  .023467   .303619  .016544  I  .3082210  .0002710  3.0471 0.1485  P    40.208     .500    -4.319     .300   .067000   .309000   .3089000      .000      .000  
+75 519 42551.00 I   .101397  .013929   .302388  .015767  I  .3051124  .0001217  3.1593 0.1485  P    40.312     .500    -4.196     .300   .068000   .308000   .3061000      .000      .000  
+75 520 42552.00 I   .102426  .013407   .301158  .018793  I  .3019278  .0001217  3.1951 0.0861  P    40.399     .500    -3.995     .300   .069000   .306000   .3034000      .000      .000  
+75 521 42553.00 I   .103450  .015856   .299929  .017598  I  .2987524  .0001217  3.1401 0.0861  P    40.331     .500    -3.742     .300   .070000   .305000   .3006000      .000      .000  
+75 522 42554.00 I   .104473  .016796   .298699  .016208  I  .2956753  .0001217  3.0020 0.0861  P    40.074     .500    -3.556     .300   .071000   .304000   .2979000      .000      .000  
+75 523 42555.00 I   .105500  .016462   .297467  .016761  I  .2927661  .0001217  2.8107 0.0810  P    39.733     .500    -3.562     .300   .072000   .303000   .2952000      .000      .000  
+75 524 42556.00 I   .106539  .015430   .296233  .017860  I  .2900570  .0001068  2.6099 0.0755  P    39.479     .500    -3.748     .300   .073000   .302000   .2926000      .000      .000  
+75 525 42557.00 I   .107595  .016900   .294997  .017778  I  .2875349  .0000895  2.4433 0.0697  P    39.434     .500    -3.941     .300   .074000   .300000   .2899000      .000      .000  
+75 526 42558.00 I   .108671  .017884   .293758  .017764  I  .2851496  .0000895  2.3392 0.0633  P    39.610     .500    -3.962     .300   .075000   .299000   .2873000      .000      .000  
+75 527 42559.00 I   .109773  .017986   .292518  .014607  I  .2828336  .0000895  2.3039 0.0633  P    39.883     .500    -3.800     .300   .076000   .298000   .2846000      .000      .000  
+75 528 42560.00 I   .110906  .014728   .291275  .015041  I  .2805229  .0000895  2.3253 0.1133  P    40.054     .500    -3.609     .300   .077000   .297000   .2820000      .000      .000  
+75 529 42561.00 I   .112075  .013825   .290031  .014718  I  .2781713  .0002081  2.3819 0.1937  P    39.990     .500    -3.564     .300   .079000   .295000   .2795000      .000      .000  
+75 530 42562.00 I   .113283  .016841   .288785  .014134  I  .2757543  .0003770  2.4529 0.3109  P    39.751     .500    -3.721     .300   .080000   .294000   .2769000      .000      .000  
+75 531 42563.00 I   .114533  .016471   .287537  .012143  I  .2732663  .0005859  2.5216 0.3490  P    39.531     .500    -3.991     .300   .082000   .292000   .2744000      .000      .000  
+75 6 1 42564.00 I   .115825  .018141   .286288  .011891  I  .2707160  .0005875  2.5757 0.4149  P    39.455     .500    -4.207     .300   .083000   .291000   .2718000      .000      .000  
+75 6 2 42565.00 I   .117160  .021320   .285035  .012244  I  .2681232  .0005875  2.6050 0.4154  P    39.452     .500    -4.244     .300   .084000   .290000   .2693000      .000      .000  
+75 6 3 42566.00 I   .118536  .022033   .283780  .019172  I  .2655170  .0005875  2.6015 0.4414  P    39.340     .500    -4.116     .300   .086000   .289000   .2668000      .000      .000  
+75 6 4 42567.00 I   .119950  .022356   .282521  .020437  I  .2629321  .0006588  2.5624 0.4726  P    39.017     .500    -3.955     .300   .087000   .287000   .2643000      .000      .000  
+75 6 5 42568.00 I   .121398  .024367   .281258  .020572  I  .2604028  .0007404  2.4916 0.4429  P    38.532     .500    -3.872     .300   .089000   .286000   .2618000      .000      .000  
+75 6 6 42569.00 I   .122879  .022303   .279990  .019558  I  .2579562  .0005922  2.3988 0.3942  P    38.028     .500    -3.851     .300   .090000   .285000   .2593000      .000      .000  
+75 6 7 42570.00 I   .124388  .025349   .278717  .018663  I  .2556079  .0002710  2.2978 0.3256  P    37.638     .500    -3.820     .300   .092000   .284000   .2568000      .000      .000  
+75 6 8 42571.00 I   .125921  .027449   .277438  .019318  I  .2533572  .0002710  2.2069 0.1916  P    37.447     .500    -3.788     .300   .093000   .282000   .2544000      .000      .000  
+75 6 9 42572.00 I   .127474  .024856   .276154  .026624  I  .2511834  .0002710  2.1481 0.1916  P    37.489     .500    -3.842     .300   .095000   .281000   .2519000      .000      .000  
+75 610 42573.00 I   .129037  .027006   .274864  .021990  I  .2490428  .0002710  2.1437 0.1916  P    37.726     .500    -3.999     .300   .096000   .279000   .2495000      .000      .000  
+75 611 42574.00 I   .130603  .029281   .273567  .021064  I  .2468736  .0002710  2.2063 0.1916  P    38.032     .500    -4.133     .300   .098000   .278000   .2470000      .000      .000  
+75 612 42575.00 I   .132165  .026834   .272260  .021442  I  .2446096  .0002710  2.3307 0.1916  P    38.207     .500    -4.097     .300   .100000   .277000   .2446000      .000      .000  
+75 613 42576.00 I   .133713  .029198   .270945  .023301  I  .2422005  .0002710  2.4903 0.1916  P    38.093     .500    -3.870     .300   .101000   .275000   .2422000      .000      .000  
+75 614 42577.00 I   .135237  .026775   .269625  .026334  I  .2396310  .0002710  2.6440 0.5153  P    37.703     .500    -3.571     .300   .103000   .274000   .2398000      .000      .000  
+75 615 42578.00 I   .136725  .026548   .268302  .026009  I  .2369286  .0009943  2.7494 0.4036  P    37.236     .500    -3.338     .300   .104000   .272000   .2374000      .000      .000  
+75 616 42579.00 I   .138167  .025969   .266980  .023202  I  .2341584  .0007603  2.7764 0.6258  P    36.936     .500    -3.225     .300   .106000   .271000   .2350000      .000      .000  
+75 617 42580.00 I   .139554  .025914   .265660  .026829  I  .2314051  .0007603  2.7156 0.5376  P    36.893     .500    -3.183     .300   .108000   .270000   .2326000      .000      .000  
+75 618 42581.00 I   .140882  .023994   .264345  .028703  I  .2287524  .0007603  2.5790 0.5376  P    36.960     .500    -3.137     .300   .109000   .268000   .2303000      .000      .000  
+75 619 42582.00 I   .142146  .030650   .263038  .031243  I  .2262630  .0007603  2.3945 0.5350  P    36.889     .500    -3.073     .300   .111000   .267000   .2279000      .000      .000  
+75 620 42583.00 I   .143336  .029711   .261738  .029269  I  .2239675  .0007530  2.1975 0.4833  P    36.559     .500    -3.057     .300   .112000   .265000   .2256000      .000      .000  
+75 621 42584.00 I   .144446  .029705   .260444  .026524  I  .2218601  .0005969  2.0240 0.5272  P    36.107     .500    -3.149     .300   .114000   .264000   .2232000      .000      .000  
+75 622 42585.00 I   .145469  .025687   .259152  .026820  I  .2199022  .0007382  1.9022 0.4747  P    35.815     .500    -3.303     .300   .115000   .263000   .2209000      .000      .000  
+75 623 42586.00 I   .146405  .027583   .257856  .024668  I  .2180341  .0007382  1.8450 0.5220  P    35.839     .500    -3.385     .300   .117000   .261000   .2187000      .000      .000  
+75 624 42587.00 I   .147255  .026242   .256553  .021921  I  .2161921  .0007382  1.8480 0.5220  P    36.067     .500    -3.310     .300   .118000   .260000   .2164000      .000      .000  
+75 625 42588.00 I   .148021  .030116   .255237  .019152  I  .2143237  .0007382  1.8943 0.5840  P    36.253     .500    -3.142     .300   .120000   .258000   .2142000      .000      .000  
+75 626 42589.00 I   .148702  .023205   .253903  .014634  I  .2123966  .0009052  1.9615 0.5840  P    36.257     .500    -3.036     .300   .121000   .257000   .2119000      .000      .000  
+75 627 42590.00 I   .149300  .024080   .252549  .018273  I  .2104005  .0009052  2.0293 0.6401  P    36.105     .500    -3.092     .300   .122000   .255000   .2098000      .000      .000  
+75 628 42591.00 I   .149817  .024227   .251173  .019908  I  .2083430  .0009052  2.0820 0.6401  P    35.867     .500    -3.276     .300   .123000   .254000   .2077000      .000      .000  
+75 629 42592.00 I   .150256  .026242   .249773  .027163  I  .2062449  .0009052  2.1096 0.6401  P    35.587     .500    -3.452     .300   .125000   .252000   .2055000      .000      .000  
+75 630 42593.00 I   .150620  .024327   .248350  .025556  I  .2041341  .0009052  2.1064 0.6401  P    35.326     .500    -3.499     .300   .126000   .251000   .2034000      .000      .000  
+75 7 1 42594.00 I   .150907  .022889   .246906  .024865  I  .2020430  .0009052  2.0704 0.4724  P    35.137     .500    -3.419     .300   .127000   .249000   .2013000      .000      .000  
+75 7 2 42595.00 I   .151121  .023680   .245438  .026638  I  .2000033  .0002710  2.0044 0.4724  P    34.943     .500    -3.326     .300   .128000   .247000   .1993000      .000      .000  
+75 7 3 42596.00 I   .151264  .026477   .243945  .026940  I  .1980417  .0002710  1.9160 0.1916  P    34.572     .500    -3.321     .300   .129000   .246000   .1973000      .000      .000  
+75 7 4 42597.00 I   .151341  .024358   .242428  .024600  I  .1961746  .0002710  1.8178 0.1916  P    33.978     .500    -3.360     .300   .129000   .244000   .1953000      .000      .000  
+75 7 5 42598.00 I   .151357  .025867   .240886  .024994  I  .1944039  .0002710  1.7261 0.1916  P    33.370     .500    -3.330     .300   .130000   .243000   .1933000      .000      .000  
+75 7 6 42599.00 I   .151316  .026980   .239321  .021832  I  .1927134  .0002710  1.6612 0.1916  P    33.030     .500    -3.230     .300   .131000   .241000   .1913000      .000      .000  
+75 7 7 42600.00 I   .151218  .027831   .237734  .022291  I  .1910650  .0002710  1.6456 0.1916  P    33.057     .500    -3.206     .300   .131000   .239000   .1893000      .000      .000  
+75 7 8 42601.00 I   .151067  .028588   .236130  .022331  I  .1893995  .0002710  1.6979 0.1916  P    33.337     .500    -3.350     .300   .132000   .238000   .1874000      .000      .000  
+75 7 9 42602.00 I   .150864  .023536   .234510  .022270  I  .1876449  .0002710  1.8229 0.1916  P    33.678     .500    -3.532     .300   .132000   .236000   .1854000      .000      .000  
+75 710 42603.00 I   .150608  .020407   .232880  .025206  I  .1857359  .0002710  2.0013 0.1916  P    33.892     .500    -3.509     .300   .133000   .235000   .1835000      .000      .000  
+75 711 42604.00 I   .150303  .020456   .231240  .025791  I  .1836383  .0002710  2.1915 0.1916  P    33.802     .500    -3.201     .300   .133000   .233000   .1815000      .000      .000  
+75 712 42605.00 I   .149951  .019155   .229592  .024384  I  .1813664  .0002710  2.3410 0.1916  P    33.336     .500    -2.778     .300   .133000   .231000   .1796000      .000      .000  
+75 713 42606.00 I   .149556  .021203   .227935  .019476  I  .1789845  .0002710  2.4060 0.1916  P    32.638     .500    -2.481     .300   .133000   .230000   .1777000      .000      .000  
+75 714 42607.00 I   .149123  .020441   .226270  .018441  I  .1765882  .0002710  2.3696 0.1916  P    32.010     .500    -2.412     .300   .134000   .228000   .1758000      .000      .000  
+75 715 42608.00 I   .148659  .023203   .224596  .018318  I  .1742749  .0002710  2.2444 0.1916  P    31.697     .500    -2.514     .300   .134000   .227000   .1739000      .000      .000  
+75 716 42609.00 I   .148167  .022357   .222915  .016658  I  .1721174  .0002710  2.0650 0.1916  P    31.705     .500    -2.672     .300   .134000   .225000   .1720000      .000      .000  
+75 717 42610.00 I   .147651  .022529   .221225  .011073  I  .1701488  .0002710  1.8737 0.1916  P    31.813     .500    -2.809     .300   .134000   .223000   .1702000      .000      .000  
+75 718 42611.00 I   .147119  .022850   .219529  .011508  I  .1683616  .0002710  1.7076 0.1916  P    31.758     .500    -2.908     .300   .134000   .221000   .1683000      .000      .000  
+75 719 42612.00 I   .146579  .022336   .217826  .010793  I  .1667168  .0002710  1.5920 0.1916  P    31.465     .500    -2.988     .300   .135000   .220000   .1665000      .000      .000  
+75 720 42613.00 I   .146036  .015432   .216118  .012428  I  .1651568  .0002710  1.5390 0.1916  P    31.118     .500    -3.063     .300   .135000   .218000   .1646000      .000      .000  
+75 721 42614.00 I   .145495  .017941   .214404  .014705  I  .1636182  .0002710  1.5479 0.1916  P    30.958     .500    -3.114     .300   .135000   .216000   .1628000      .000      .000  
+75 722 42615.00 I   .144958  .015196   .212684  .014862  I  .1620442  .0002710  1.6071 0.1916  P    31.029     .500    -3.095     .300   .135000   .214000   .1610000      .000      .000  
+75 723 42616.00 I   .144430  .015453   .210958  .013235  I  .1603935  .0002710  1.6977 0.1916  P    31.170     .500    -2.985     .300   .135000   .213000   .1592000      .000      .000  
+75 724 42617.00 I   .143917  .015271   .209226  .014678  I  .1586456  .0002710  1.7979 0.1916  P    31.223     .500    -2.825     .300   .135000   .211000   .1573000      .000      .000  
+75 725 42618.00 I   .143422  .017232   .207487  .013351  I  .1568008  .0002710  1.8887 0.4314  P    31.149     .500    -2.704     .300   .135000   .210000   .1555000      .000      .000  
+75 726 42619.00 I   .142948  .017121   .205744  .013281  I  .1548759  .0008191  1.9565 0.4314  P    30.942     .500    -2.698     .300   .135000   .208000   .1537000      .000      .000  
+75 727 42620.00 I   .142495  .020242   .203995  .011738  I  .1528981  .0008191  1.9936 0.5792  P    30.617     .500    -2.799     .300   .135000   .206000   .1518000      .000      .000  
+75 728 42621.00 I   .142061  .020845   .202241  .008943  I  .1508998  .0008191  1.9975 0.5792  P    30.316     .500    -2.919     .300   .135000   .204000   .1499000      .000      .000  
+75 729 42622.00 I   .141647  .019441   .200481  .010228  I  .1489135  .0008191  1.9702 0.5792  P    30.229     .500    -2.988     .300   .136000   .203000   .1480000      .000      .000  
+75 730 42623.00 I   .141250  .019943   .198715  .009985  I  .1469678  .0008191  1.9178 0.5792  P    30.303     .500    -3.042     .300   .136000   .201000   .1461000      .000      .000  
+75 731 42624.00 I   .140866  .020137   .196941  .009761  I  .1450827  .0008191  1.8512 0.4314  P    30.190     .500    -3.161     .300   .136000   .199000   .1442000      .000      .000  
+75 8 1 42625.00 I   .140495  .018143   .195159  .009683  I  .1432652  .0002710  1.7852 0.4314  P    29.655     .500    -3.324     .300   .136000   .197000   .1422000      .000      .000  
+75 8 2 42626.00 I   .140131  .021024   .193370  .010410  I  .1415062  .0002710  1.7375 0.1916  P    28.937     .500    -3.394     .300   .136000   .195000   .1402000      .000      .000  
+75 8 3 42627.00 I   .139771  .018077   .191574  .012753  I  .1397771  .0002710  1.7291 0.1916  P    28.525     .500    -3.304     .300   .136000   .194000   .1383000      .000      .000  
+75 8 4 42628.00 I   .139409  .017944   .189773  .012977  I  .1380281  .0002710  1.7806 0.1916  P    28.634     .500    -3.183     .300   .136000   .192000   .1363000      .000      .000  
+75 8 5 42629.00 I   .139043  .017124   .187967  .013652  I  .1361916  .0002710  1.9052 0.1916  P    29.054     .500    -3.205     .300   .136000   .190000   .1343000      .000      .000  
+75 8 6 42630.00 I   .138669  .022640   .186160  .013717  I  .1341949  .0002710  2.0981 0.1916  P    29.439     .500    -3.327     .300   .136000   .188000   .1322000      .000      .000  
+75 8 7 42631.00 I   .138283  .022450   .184355  .014082  I  .1319829  .0002710  2.3283 0.1916  P    29.583     .500    -3.320     .300   .136000   .186000   .1301000      .000      .000  
+75 8 8 42632.00 I   .137886  .022251   .182552  .014325  I  .1295436  .0002710  2.5426 0.1916  P    29.436     .500    -3.059     .300   .137000   .185000   .1279000      .000      .000  
+75 8 9 42633.00 I   .137474  .022840   .180753  .013750  I  .1269223  .0002710  2.6831 0.1916  P    29.046     .500    -2.692     .300   .137000   .183000   .1258000      .000      .000  
+75 810 42634.00 I   .137044  .022963   .178960  .011623  I  .1242150  .0002710  2.7107 0.1916  P    28.527     .500    -2.455     .300   .137000   .181000   .1237000      .000      .000  
+75 811 42635.00 I   .136594  .020171   .177173  .011802  I  .1215397  .0002710  2.6219 0.1916  P    28.016     .500    -2.414     .300   .137000   .179000   .1215000      .000      .000  
+75 812 42636.00 I   .136127  .025956   .175389  .012163  I  .1189993  .0002710  2.4488 0.1916  P    27.617     .500    -2.481     .300   .137000   .178000   .1193000      .000      .000  
+75 813 42637.00 I   .135643  .020715   .173609  .012551  I  .1166529  .0002710  2.2434 0.1916  P    27.419     .500    -2.591     .300   .137000   .176000   .1172000      .000      .000  
+75 814 42638.00 I   .135138  .020951   .171833  .010654  I  .1145063  .0002710  2.0566 0.1916  P    27.478     .500    -2.759     .300   .137000   .175000   .1150000      .000      .000  
+75 815 42639.00 I   .134611  .020805   .170059  .010889  I  .1125222  .0002710  1.9222 0.1916  P    27.724     .500    -2.968     .300   .137000   .173000   .1128000      .000      .000  
+75 816 42640.00 I   .134057  .017200   .168287  .010837  I  .1106400  .0002710  1.8535 0.1916  P    27.938     .500    -3.119     .300   .137000   .172000   .1106000      .000      .000  
+75 817 42641.00 I   .133477  .017380   .166517  .010796  I  .1087940  .0002710  1.8483 0.1916  P    27.962     .500    -3.138     .300   .137000   .170000   .1084000      .000      .000  
+75 818 42642.00 I   .132872  .017505   .164748  .010647  I  .1069262  .0002710  1.8947 0.1916  P    27.861     .500    -3.062     .300   .136000   .169000   .1063000      .000      .000  
+75 819 42643.00 I   .132241  .006851   .162980  .007233  I  .1049929  .0002710  1.9761 0.1916  P    27.810     .500    -2.969     .300   .136000   .167000   .1041000      .000      .000  
+75 820 42644.00 I   .131582  .008878   .161210  .006966  I  .1029686  .0002710  2.0736 0.1916  P    27.857     .500    -2.863     .300   .136000   .166000   .1019000      .000      .000  
+75 821 42645.00 I   .130895  .016443   .159439  .006546  I  .1008470  .0002710  2.1674 0.1916  P    27.903     .500    -2.693     .300   .136000   .165000   .0998000      .000      .000  
+75 822 42646.00 I   .130180  .019536   .157663  .013390  I  .0986407  .0002710  2.2407 0.1916  P    27.854     .500    -2.477     .300   .136000   .163000   .0976000      .000      .000  
+75 823 42647.00 I   .129438  .019720   .155884  .013430  I  .0963759  .0002710  2.2830 0.3416  P    27.677     .500    -2.344     .300   .135000   .162000   .0955000      .000      .000  
+75 824 42648.00 I   .128669  .019531   .154099  .020073  I  .0940867  .0006271  2.2893 0.3416  P    27.403     .500    -2.405     .300   .135000   .160000   .0933000      .000      .000  
+75 825 42649.00 I   .127872  .019371   .152307  .020009  I  .0918087  .0006271  2.2614 0.4434  P    27.172     .500    -2.623     .300   .135000   .159000   .0912000      .000      .000  
+75 826 42650.00 I   .127042  .020107   .150509  .020119  I  .0895730  .0006271  2.2060 0.3942  P    27.183     .500    -2.857     .300   .134000   .158000   .0890000      .000      .000  
+75 827 42651.00 I   .126175  .021462   .148704  .020071  I  .0874023  .0004778  2.1336 0.3766  P    27.423     .500    -3.033     .300   .134000   .156000   .0869000      .000      .000  
+75 828 42652.00 I   .125270  .020517   .146895  .020025  I  .0853067  .0004173  2.0585 0.3172  P    27.550     .500    -3.201     .300   .133000   .155000   .0847000      .000      .000  
+75 829 42653.00 I   .124326  .021597   .145082  .015990  I  .0832809  .0004173  1.9967 0.2443  P    27.248     .500    -3.396     .300   .133000   .153000   .0826000      .000      .000  
+75 830 42654.00 I   .123343  .023402   .143270  .016835  I  .0813027  .0002541  1.9667 0.2443  P    26.664     .500    -3.527     .300   .132000   .152000   .0804000      .000      .000  
+75 831 42655.00 I   .122316  .024394   .141461  .009961  I  .0793306  .0002541  1.9876 0.1797  P    26.303     .500    -3.484     .300   .131000   .151000   .0781000      .000      .000  
+75 9 1 42656.00 I   .121242  .025299   .139659  .010617  I  .0773052  .0002541  2.0756 0.1806  P    26.468     .500    -3.325     .300   .130000   .149000   .0758000      .000      .000  
+75 9 2 42657.00 I   .120119  .026575   .137868  .010905  I  .0751549  .0002566  2.2370 0.1857  P    26.965     .500    -3.221     .300   .128000   .148000   .0735000      .000      .000  
+75 9 3 42658.00 I   .118946  .024728   .136090  .014194  I  .0728116  .0002710  2.4572 0.1866  P    27.361     .500    -3.219     .300   .127000   .146000   .0712000      .000      .000  
+75 9 4 42659.00 I   .117724  .021603   .134331  .014060  I  .0702342  .0002710  2.6963 0.1916  P    27.395     .500    -3.177     .300   .126000   .145000   .0689000      .000      .000  
+75 9 5 42660.00 I   .116450  .018392   .132594  .019354  I  .0674318  .0002710  2.8969 0.1916  P    27.125     .500    -2.992     .300   .125000   .144000   .0665000      .000      .000  
+75 9 6 42661.00 I   .115122  .015947   .130881  .018430  I  .0644718  .0002710  3.0031 0.1916  P    26.806     .500    -2.774     .300   .123000   .143000   .0641000      .000      .000  
+75 9 7 42662.00 I   .113735  .021923   .129198  .019283  I  .0614672  .0002710  2.9843 0.1916  P    26.652     .500    -2.685     .300   .122000   .141000   .0618000      .000      .000  
+75 9 8 42663.00 I   .112285  .021763   .127549  .018556  I  .0585415  .0002710  2.8505 0.1916  P    26.621     .500    -2.694     .300   .120000   .140000   .0594000      .000      .000  
+75 9 9 42664.00 I   .110770  .019606   .125938  .018569  I  .0557892  .0002710  2.6476 0.1916  P    26.478     .500    -2.635     .300   .119000   .139000   .0570000      .000      .000  
+75 910 42665.00 I   .109188  .020552   .124368  .016534  I  .0532491  .0002710  2.4364 0.1916  P    26.144     .500    -2.494     .300   .117000   .138000   .0546000      .000      .000  
+75 911 42666.00 I   .107540  .020747   .122843  .016919  I  .0509018  .0002710  2.2689 0.1916  P    25.913     .500    -2.458     .300   .116000   .137000   .0521000      .000      .000  
+75 912 42667.00 I   .105831  .021163   .121362  .023017  I  .0486878  .0002710  2.1719 0.1916  P    26.119     .500    -2.640     .300   .114000   .135000   .0497000      .000      .000  
+75 913 42668.00 I   .104064  .022424   .119928  .023663  I  .0465338  .0002710  2.1474 0.1916  P    26.679     .500    -2.891     .300   .113000   .134000   .0472000      .000      .000  
+75 914 42669.00 I   .102244  .021471   .118541  .022066  I  .0443734  .0002710  2.1816 0.2164  P    27.169     .500    -2.977     .300   .111000   .133000   .0448000      .000      .000  
+75 915 42670.00 I   .100377  .023134   .117203  .022328  I  .0421573  .0003375  2.2557 0.2164  P    27.340     .500    -2.860     .300   .109000   .132000   .0423000      .000      .000  
+75 916 42671.00 I   .098468  .022834   .115914  .022023  I  .0398549  .0003375  2.3512 0.2386  P    27.333     .500    -2.689     .300   .107000   .131000   .0398000      .000      .000  
+75 917 42672.00 I   .096524  .022272   .114671  .021669  I  .0374535  .0003375  2.4507 0.2386  P    27.363     .500    -2.566     .300   .106000   .130000   .0374000      .000      .000  
+75 918 42673.00 I   .094556  .021722   .113472  .021296  I  .0349574  .0003375  2.5383 0.2386  P    27.426     .500    -2.442     .300   .104000   .129000   .0349000      .000      .000  
+75 919 42674.00 I   .092568  .020850   .112315  .009853  I  .0323854  .0003375  2.6005 0.2386  P    27.398     .500    -2.269     .300   .102000   .128000   .0324000      .000      .000  
+75 920 42675.00 I   .090562  .020559   .111197  .008617  I  .0297676  .0003375  2.6293 0.1691  P    27.245     .500    -2.138     .300   .100000   .127000   .0298000      .000      .000  
+75 921 42676.00 I   .088541  .015420   .110116  .009317  I  .0271382  .0000206  2.6241 0.1691  P    27.039     .500    -2.181     .300   .098000   .126000   .0272000      .000      .000  
+75 922 42677.00 I   .086507  .011918   .109068  .009059  I  .0245291  .0000206  2.5899 0.0146  P    26.888     .500    -2.395     .300   .097000   .124000   .0247000      .000      .000  
+75 923 42678.00 I   .084463  .016149   .108051  .010960  I  .0219647  .0000206  2.5367 0.2542  P    26.908     .500    -2.632     .300   .095000   .123000   .0221000      .000      .000  
+75 924 42679.00 I   .082411  .016596   .107063  .010773  I  .0194578  .0005080  2.4773 0.2398  P    27.127     .500    -2.776     .300   .093000   .122000   .0195000      .000      .000  
+75 925 42680.00 I   .080351  .023567   .106103  .012355  I  .0170073  .0004791  2.4265 0.3491  P    27.376     .500    -2.859     .300   .091000   .121000   .0168000      .000      .000  
+75 926 42681.00 I   .078281  .023322   .105169  .009325  I  .0145964  .0004791  2.4010 0.3787  P    27.412     .500    -2.962     .300   .089000   .120000   .0141000      .000      .000  
+75 927 42682.00 I   .076200  .023726   .104262  .010817  I  .0121912  .0005866  2.4178 0.3787  P    27.224     .500    -3.069     .300   .087000   .119000   .0114000      .000      .000  
+75 928 42683.00 I   .074109  .022409   .103379  .012421  I  .0097417  .0005866  2.4917 0.4148  P    27.096     .500    -3.086     .300   .085000   .118000   .0087000      .000      .000  
+75 929 42684.00 I   .072008  .022385   .102523  .012949  I  .0071859  .0005866  2.6311 0.3594  P    27.287     .500    -2.990     .300   .083000   .117000   .0060000      .000      .000  
+75 930 42685.00 I   .069891  .019461   .101693  .014099  I  .0044591  .0004154  2.8318 0.3231  P    27.730     .500    -2.870     .300   .081000   .116000   .0032000      .000      .000  
+7510 1 42686.00 I   .067753  .019003   .100891  .016291  I  .0015094  .0002710  3.0713 0.2480  P    28.100     .500    -2.778     .300   .079000   .115000   .0004000      .000      .000  
+7510 2 42687.00 I   .065591  .009604   .100115  .015106  I -.0016819  .0002710  3.3061 0.1916  P    28.134     .500    -2.657     .300   .077000   .114000  -.0023000      .000      .000  
+7510 3 42688.00 I   .063400  .014906   .099364  .015200  I -.0050831  .0002710  3.4819 0.1916  P    27.870     .500    -2.469     .300   .075000   .113000  -.0051000      .000      .000  
+7510 4 42689.00 I   .061177  .013008   .098637  .014220  I -.0086107  .0002710  3.5527 0.1916  P    27.631     .500    -2.328     .300   .073000   .112000  -.0079000      .000      .000  
+7510 5 42690.00 I   .058918  .013185   .097935  .013350  I -.0121475  .0002710  3.5005 0.1916  P    27.737     .500    -2.357     .300   .071000   .111000  -.0108000      .000      .000  
+7510 6 42691.00 I   .056619  .014942   .097260  .012933  I -.0155777  .0002710  3.3464 0.1916  P    28.141     .500    -2.465     .300   .069000   .110000  -.0137000      .000      .000  
+7510 7 42692.00 I   .054278  .015263   .096614  .011629  I -.0188238  .0002710  3.1428 0.1916  P    28.408     .500    -2.407     .300   .066000   .110000  -.0167000      .000      .000  
+7510 8 42693.00 I   .051893  .016599   .095998  .012287  I -.0218672  .0002710  2.9508 0.1916  P    28.222     .500    -2.123     .300   .064000   .109000  -.0196000      .000      .000  
+7510 9 42694.00 I   .049466  .017675   .095416  .012491  I -.0247445  .0002710  2.8161 0.1916  P    27.839     .500    -1.865     .300   .062000   .108000  -.0225000      .000      .000  
+751010 42695.00 I   .046997  .013812   .094868  .013567  I -.0275243  .0002710  2.7562 0.3300  P    27.822     .500    -1.894     .300   .060000   .107000  -.0255000      .000      .000  
+751011 42696.00 I   .044489  .018819   .094358  .015391  I -.0302791  .0006019  2.7629 0.2532  P    28.345     .500    -2.158     .300   .057000   .107000  -.0285000      .000      .000  
+751012 42697.00 I   .041945  .019113   .093886  .015401  I -.0330653  .0004277  2.8150 0.3692  P    29.005     .500    -2.373     .300   .055000   .106000  -.0315000      .000      .000  
+751013 42698.00 I   .039363  .021381   .093452  .015620  I -.0359169  .0004277  2.8904 0.3024  P    29.382     .500    -2.375     .300   .052000   .106000  -.0345000      .000      .000  
+751014 42699.00 I   .036746  .021577   .093054  .014291  I -.0388482  .0004277  2.9720 0.3024  P    29.494     .500    -2.249     .300   .050000   .105000  -.0375000      .000      .000  
+751015 42700.00 I   .034093  .020685   .092693  .012976  I -.0418584  .0004277  3.0460 0.3024  P    29.578     .500    -2.132     .300   .047000   .105000  -.0406000      .000      .000  
+751016 42701.00 I   .031402  .020663   .092367  .015041  I -.0449336  .0004277  3.1000 0.2160  P    29.679     .500    -2.038     .300   .045000   .104000  -.0437000      .000      .000  
+751017 42702.00 I   .028671  .022301   .092077  .014046  I -.0480485  .0000606  3.1241 0.2532  P    29.671     .500    -1.920     .300   .042000   .104000  -.0469000      .000      .000  
+751018 42703.00 I   .025899  .018015   .091825  .012042  I -.0511704  .0002710  3.1140 0.1388  P    29.538     .500    -1.810     .300   .040000   .103000  -.0500000      .000      .000  
+751019 42704.00 I   .023088  .025107   .091609  .011344  I -.0542659  .0002710  3.0722 0.1916  P    29.396     .500    -1.786     .300   .037000   .103000  -.0531000      .000      .000  
+751020 42705.00 I   .020236  .022015   .091433  .011044  I -.0573070  .0002710  3.0072 0.1916  P    29.319     .500    -1.848     .300   .034000   .103000  -.0563000      .000      .000  
+751021 42706.00 I   .017343  .024763   .091295  .020572  I -.0602766  .0002710  2.9313 0.1916  P    29.308     .500    -1.903     .300   .032000   .103000  -.0594000      .000      .000  
+751022 42707.00 I   .014408  .024511   .091196  .020956  I -.0631707  .0002710  2.8586 0.1916  P    29.393     .500    -1.888     .300   .029000   .102000  -.0626000      .000      .000  
+751023 42708.00 I   .011430  .024041   .091136  .022092  I -.0660001  .0002710  2.8046 0.1457  P    29.600     .500    -1.846     .300   .027000   .102000  -.0657000      .000      .000  
+751024 42709.00 I   .008415  .022281   .091113  .023521  I -.0687916  .0001072  2.7857 0.1457  P    29.863     .500    -1.857     .300   .024000   .102000  -.0689000      .000      .000  
+751025 42710.00 I   .005366  .025589   .091128  .023675  I -.0715879  .0001072  2.8162 0.1656  P    30.073     .500    -1.929     .300   .021000   .102000  -.0721000      .000      .000  
+751026 42711.00 I   .002284  .018221   .091180  .024643  I -.0744434  .0003134  2.9050 0.1656  P    30.229     .500    -1.990     .300   .018000   .102000  -.0753000      .000      .000  
+751027 42712.00 I  -.000828  .020257   .091271  .024852  I -.0774171  .0003134  3.0513 0.2216  P    30.428     .500    -1.982     .300   .016000   .102000  -.0785000      .000      .000  
+751028 42713.00 I  -.003970  .016502   .091400  .017716  I -.0805602  .0003134  3.2403 0.2216  P    30.714     .500    -1.903     .300   .013000   .102000  -.0817000      .000      .000  
+751029 42714.00 I  -.007140  .020348   .091566  .016086  I -.0839023  .0003134  3.4430 0.2449  P    30.982     .500    -1.764     .300   .010000   .102000  -.0849000      .000      .000  
+751030 42715.00 I  -.010330  .020296   .091769  .012218  I -.0874367  .0003763  3.6172 0.2449  P    31.066     .500    -1.546     .300   .007000   .102000  -.0881000      .000      .000  
+751031 42716.00 I  -.013536  .020907   .092013  .015480  I -.0911128  .0003763  3.7198 0.2319  P    30.926     .500    -1.273     .300   .004000   .102000  -.0913000      .000      .000  
+7511 1 42717.00 I  -.016752  .016677   .092297  .015355  I -.0948426  .0002710  3.7213 0.2319  P    30.755     .500    -1.077     .300   .001000   .103000  -.0945000      .000      .000  
+7511 2 42718.00 I  -.019973  .016852   .092625  .013346  I -.0985208  .0002710  3.6191 0.1916  P    30.838     .500    -1.097     .300  -.002000   .103000  -.0977000      .000      .000  
+7511 3 42719.00 I  -.023191  .014464   .092996  .013846  I -.1020561  .0002710  3.4428 0.1916  P    31.237     .500    -1.281     .300  -.005000   .103000  -.1009000      .000      .000  
+7511 4 42720.00 I  -.026399  .019220   .093412  .013924  I -.1053988  .0002710  3.2437 0.1916  P    31.649     .500    -1.381     .300  -.008000   .104000  -.1041000      .000      .000  
+7511 5 42721.00 I  -.029590  .016092   .093876  .017300  I -.1085538  .0002710  3.0754 0.1916  P    31.733     .500    -1.225     .300  -.011000   .105000  -.1073000      .000      .000  
+7511 6 42722.00 I  -.032760  .019046   .094391  .017656  I -.1115712  .0002710  2.9720 0.1916  P    31.560     .500     -.937     .300  -.013000   .105000  -.1106000      .000      .000  
+7511 7 42723.00 I  -.035902  .022159   .094961  .012633  I -.1145216  .0002710  2.9400 0.1916  P    31.549     .500     -.794     .300  -.016000   .106000  -.1138000      .000      .000  
+7511 8 42724.00 I  -.039010  .022266   .095587  .014269  I -.1174698  .0002710  2.9637 0.1916  P    31.932     .500     -.909     .300  -.019000   .107000  -.1170000      .000      .000  
+7511 9 42725.00 I  -.042077  .022402   .096271  .016171  I -.1204590  .0002710  3.0175 0.1916  P    32.475     .500    -1.133     .300  -.022000   .108000  -.1202000      .000      .000  
+751110 42726.00 I  -.045090  .022756   .097017  .015950  I -.1235075  .0002710  3.0793 0.1916  P    32.824     .500    -1.274     .300  -.025000   .110000  -.1234000      .000      .000  
+751111 42727.00 I  -.048044  .018617   .097829  .016001  I -.1266150  .0002710  3.1334 0.1584  P    32.930     .500    -1.283     .300  -.027000   .111000  -.1266000      .000      .000  
+751112 42728.00 I  -.050932  .019412   .098710  .012043  I -.1297683  .0001642  3.1694 0.1584  P    32.958     .500    -1.220     .300  -.030000   .113000  -.1298000      .000      .000  
+751113 42729.00 I  -.053751  .020194   .099660  .013092  I -.1329450  .0001642  3.1790 0.1035  P    32.967     .500    -1.125     .300  -.033000   .114000  -.1330000      .000      .000  
+751114 42730.00 I  -.056499  .016215   .100680  .016603  I -.1361156  .0001262  3.1566 0.1036  P    32.886     .500    -1.006     .300  -.036000   .116000  -.1362000      .000      .000  
+751115 42731.00 I  -.059173  .016433   .101771  .016948  I -.1392475  .0001265  3.1021 0.0893  P    32.735     .500     -.890     .300  -.039000   .117000  -.1393000      .000      .000  
+751116 42732.00 I  -.061773  .017450   .102933  .015413  I -.1423112  .0001265  3.0217 0.0894  P    32.641     .500     -.802     .300  -.041000   .119000  -.1425000      .000      .000  
+751117 42733.00 I  -.064300  .017370   .104164  .017321  I -.1452861  .0001265  2.9268 0.0815  P    32.635     .500     -.723     .300  -.044000   .120000  -.1456000      .000      .000  
+751118 42734.00 I  -.066758  .024230   .105465  .017692  I -.1481645  .0001027  2.8311 0.0769  P    32.626     .500     -.618     .300  -.047000   .122000  -.1488000      .000      .000  
+751119 42735.00 I  -.069154  .023483   .106830  .018050  I -.1509530  .0000876  2.7496 0.0700  P    32.596     .500     -.512     .300  -.050000   .124000  -.1519000      .000      .000  
+751120 42736.00 I  -.071496  .026012   .108256  .017179  I -.1536738  .0000951  2.6984 0.2431  P    32.670     .500     -.476     .300  -.053000   .126000  -.1550000      .000      .000  
+751121 42737.00 I  -.073792  .027358   .109737  .013581  I -.1563645  .0004782  2.6915 0.2438  P    32.934     .500     -.540     .300  -.055000   .127000  -.1582000      .000      .000  
+751122 42738.00 I  -.076051  .027336   .111268  .011999  I -.1590747  .0004782  2.7385 0.3381  P    33.292     .500     -.650     .300  -.058000   .129000  -.1613000      .000      .000  
+751123 42739.00 I  -.078276  .030164   .112848  .011354  I -.1618592  .0004782  2.8387 0.3381  P    33.569     .500     -.722     .300  -.061000   .131000  -.1644000      .000      .000  
+751124 42740.00 I  -.080474  .030179   .114472  .011018  I -.1647655  .0004782  2.9789 0.4136  P    33.697     .500     -.709     .300  -.064000   .133000  -.1674000      .000      .000  
+751125 42741.00 I  -.082652  .025827   .116140  .015525  I -.1678220  .0006749  3.1339 0.4136  P    33.739     .500     -.613     .300  -.066000   .135000  -.1705000      .000      .000  
+751126 42742.00 I  -.084820  .025313   .117848  .015519  I -.1710272  .0006749  3.2706 0.3636  P    33.773     .500     -.438     .300  -.069000   .136000  -.1735000      .000      .000  
+751127 42743.00 I  -.086983  .019199   .119596  .015388  I -.1743461  .0002710  3.3559 0.3636  P    33.791     .500     -.186     .300  -.071000   .138000  -.1766000      .000      .000  
+751128 42744.00 I  -.089145  .017040   .121384  .019244  I -.1777136  .0002710  3.3649 0.1916  P    33.735     .500      .112     .300  -.074000   .140000  -.1796000      .000      .000  
+751129 42745.00 I  -.091308  .017353   .123210  .020907  I -.1810477  .0002710  3.2894 0.1916  P    33.609     .500      .348     .300  -.077000   .142000  -.1826000      .000      .000  
+751130 42746.00 I  -.093472  .010537   .125073  .021761  I -.1842687  .0002710  3.1430 0.1916  P    33.523     .500      .389     .300  -.079000   .144000  -.1855000      .000      .000  
+7512 1 42747.00 I  -.095638  .013659   .126970  .020126  I -.1873216  .0002710  2.9604 0.1916  P    33.583     .500      .209     .300  -.082000   .145000  -.1885000      .000      .000  
+7512 2 42748.00 I  -.097804  .011946   .128899  .016733  I -.1901925  .0002710  2.7867 0.1916  P    33.763     .500     -.037     .300  -.084000   .147000  -.1914000      .000      .000  
+7512 3 42749.00 I  -.099969  .011717   .130854  .017512  I -.1929110  .0002710  2.6611 0.1916  P    33.946     .500     -.121     .300  -.087000   .149000  -.1944000      .000      .000  
+7512 4 42750.00 I  -.102128  .011789   .132833  .020827  I -.1955375  .0002710  2.6039 0.1916  P    34.104     .500      .028     .300  -.089000   .151000  -.1972000      .000      .000  
+7512 5 42751.00 I  -.104281  .011812   .134833  .017899  I -.1981401  .0002710  2.6107 0.1916  P    34.334     .500      .264     .300  -.091000   .152000  -.2000000      .000      .000  
+7512 6 42752.00 I  -.106423  .012843   .136852  .016085  I -.2007731  .0002710  2.6601 0.1916  P    34.688     .500      .380     .300  -.093000   .154000  -.2029000      .000      .000  
+7512 7 42753.00 I  -.108550  .011600   .138887  .015526  I -.2034657  .0002710  2.7256 0.1916  P    35.044     .500      .309     .300  -.095000   .155000  -.2057000      .000      .000  
+7512 8 42754.00 I  -.110656  .014017   .140936  .017409  I -.2062227  .0002710  2.7862 0.1916  P    35.233     .500      .144     .300  -.097000   .157000  -.2085000      .000      .000  
+7512 9 42755.00 I  -.112735  .019088   .142996  .017600  I -.2090323  .0002710  2.8293 0.1916  P    35.220     .500      .012     .300  -.099000   .159000  -.2113000      .000      .000  
+751210 42756.00 I  -.114783  .019234   .145066  .016374  I -.2118730  .0002710  2.8477 0.2693  P    35.090     .500     -.023     .300  -.100000   .160000  -.2141000      .000      .000  
+751211 42757.00 I  -.116794  .019189   .147142  .012163  I -.2147182  .0004655  2.8378 0.2693  P    34.915     .500      .034     .300  -.102000   .162000  -.2168000      .000      .000  
+751212 42758.00 I  -.118762  .019864   .149221  .011741  I -.2175390  .0004655  2.7991 0.3292  P    34.726     .500      .128     .300  -.103000   .163000  -.2196000      .000      .000  
+751213 42759.00 I  -.120682  .019543   .151303  .010811  I -.2203080  .0004655  2.7353 0.3292  P    34.587     .500      .196     .300  -.105000   .165000  -.2224000      .000      .000  
+751214 42760.00 I  -.122549  .020240   .153388  .014069  I -.2230042  .0004655  2.6554 0.3292  P    34.567     .500      .232     .300  -.107000   .167000  -.2252000      .000      .000  
+751215 42761.00 I  -.124360  .018935   .155474  .011612  I -.2256178  .0004655  2.5725 0.3292  P    34.630     .500      .288     .300  -.108000   .169000  -.2279000      .000      .000  
+751216 42762.00 I  -.126111  .017967   .157562  .014048  I -.2281532  .0004655  2.5014 0.2693  P    34.658     .500      .392     .300  -.110000   .170000  -.2307000      .000      .000  
+751217 42763.00 I  -.127800  .017891   .159653  .014440  I -.2306297  .0002710  2.4574 0.2693  P    34.618     .500      .466     .300  -.111000   .172000  -.2334000      .000      .000  
+751218 42764.00 I  -.129423  .019098   .161749  .014423  I -.2330821  .0002710  2.4556 0.1916  P    34.630     .500      .399     .300  -.113000   .174000  -.2362000      .000      .000  
+751219 42765.00 I  -.130977  .021330   .163852  .013762  I -.2355587  .0002710  2.5073 0.1916  P    34.823     .500      .196     .300  -.114000   .176000  -.2389000      .000      .000  
+751220 42766.00 I  -.132461  .020970   .165965  .015005  I -.2381153  .0002710  2.6150 0.1916  P    35.160     .500      .004     .300  -.116000   .178000  -.2416000      .000      .000  
+751221 42767.00 I  -.133879  .020276   .168089  .019798  I -.2408033  .0002710  2.7667 0.1916  P    35.443     .500     -.031     .300  -.117000   .180000  -.2444000      .000      .000  
+751222 42768.00 I  -.135231  .017999   .170225  .020846  I -.2436542  .0002710  2.9350 0.1916  P    35.502     .500      .108     .300  -.119000   .182000  -.2471000      .000      .000  
+751223 42769.00 I  -.136520  .015591   .172373  .021188  I -.2466668  .0002710  3.0837 0.1916  P    35.340     .500      .328     .300  -.120000   .184000  -.2498000      .000      .000  
+751224 42770.00 I  -.137749  .017060   .174535  .021074  I -.2498037  .0002710  3.1786 0.1916  P    35.106     .500      .535     .300  -.121000   .186000  -.2525000      .000      .000  
+751225 42771.00 I  -.138922  .016117   .176708  .023143  I -.2529990  .0002710  3.1985 0.1916  P    34.943     .500      .706     .300  -.122000   .188000  -.2551000      .000      .000  
+751226 42772.00 I  -.140046  .011635   .178891  .023424  I -.2561747  .0002710  3.1404 0.1916  P    34.869     .500      .856     .300  -.123000   .191000  -.2578000      .000      .000  
+751227 42773.00 I  -.141125  .013889   .181081  .023376  I -.2592587  .0002710  3.0189 0.1916  P    34.796     .500      .972     .300  -.124000   .193000  -.2604000      .000      .000  
+751228 42774.00 I  -.142162  .017653   .183277  .017474  I -.2622010  .0002710  2.8628 0.1916  P    34.646     .500      .995     .300  -.125000   .195000  -.2631000      .000      .000  
+751229 42775.00 I  -.143157  .024671   .185479  .022726  I -.2649847  .0002710  2.7081 0.1916  P    34.452     .500      .864     .300  -.126000   .197000  -.2657000      .000      .000  
+751230 42776.00 I  -.144114  .024174   .187689  .020654  I -.2676290  .0002710  2.5890 0.1916  P    34.340     .500      .618     .300  -.127000   .199000  -.2683000      .000      .000  
+751231 42777.00 I  -.145035  .026013   .189909  .024262  I -.2701822  .0002710  2.5284 0.1916  P    34.425     .500      .421     .300  -.128000   .202000  -.2710000      .000      .000  
+76 1 1 42778.00 I  -.145922  .027744   .192143  .023998  I  .7272928  .0002710  2.5319 0.1916  P    34.708     .500      .435     .300  -.129000   .204000   .7264000      .000      .000  
+76 1 2 42779.00 I  -.146779  .031985   .194393  .023882  I  .7247370  .0002710  2.5864 0.1916  P    35.073     .500      .657     .300  -.130000   .206000   .7238000      .000      .000  
+76 1 3 42780.00 I  -.147599  .035403   .196662  .022891  I  .7221112  .0002710  2.6674 0.1916  P    35.373     .500      .909     .300  -.131000   .208000   .7211000      .000      .000  
+76 1 4 42781.00 I  -.148380  .033483   .198951  .024308  I  .7194019  .0002710  2.7494 0.1916  P    35.531     .500     1.005     .300  -.131000   .210000   .7185000      .000      .000  
+76 1 5 42782.00 I  -.149117  .028982   .201257  .017352  I  .7166183  .0002710  2.8136 0.1916  P    35.547     .500      .908     .300  -.132000   .213000   .7158000      .000      .000  
+76 1 6 42783.00 I  -.149810  .029323   .203580  .021269  I  .7137839  .0002710  2.8500 0.1916  P    35.439     .500      .728     .300  -.132000   .215000   .7132000      .000      .000  
+76 1 7 42784.00 I  -.150451  .031620   .205917  .016665  I  .7109287  .0002710  2.8551 0.1916  P    35.221     .500      .594     .300  -.133000   .217000   .7105000      .000      .000  
+76 1 8 42785.00 I  -.151041  .029530   .208267  .015592  I  .7080839  .0002710  2.8296 0.1916  P    34.957     .500      .551     .300  -.133000   .219000   .7078000      .000      .000  
+76 1 9 42786.00 I  -.151577  .025456   .210631  .016068  I  .7052786  .0002710  2.7770 0.1916  P    34.765     .500      .540     .300  -.134000   .221000   .7051000      .000      .000  
+76 110 42787.00 I  -.152057  .019713   .213008  .017090  I  .7025362  .0002710  2.7056 0.3409  P    34.716     .500      .476     .300  -.134000   .224000   .7024000      .000      .000  
+76 111 42788.00 I  -.152481  .019619   .215400  .014602  I  .6998696  .0006256  2.6275 0.3409  P    34.767     .500      .353     .300  -.135000   .226000   .6997000      .000      .000  
+76 112 42789.00 I  -.152852  .018850   .217808  .018479  I  .6972785  .0006256  2.5574 0.4424  P    34.811     .500      .267     .300  -.135000   .228000   .6970000      .000      .000  
+76 113 42790.00 I  -.153173  .019967   .220234  .014358  I  .6947468  .0006256  2.5111 0.4424  P    34.794     .500      .300     .300  -.135000   .230000   .6942000      .000      .000  
+76 114 42791.00 I  -.153446  .013855   .222679  .014233  I  .6922431  .0006256  2.5043 0.4211  P    34.754     .500      .377     .300  -.135000   .232000   .6915000      .000      .000  
+76 115 42792.00 I  -.153675  .013816   .225144  .014771  I  .6897202  .0005639  2.5514 0.4641  P    34.769     .500      .325     .300  -.136000   .235000   .6887000      .000      .000  
+76 116 42793.00 I  -.153862  .013765   .227632  .014258  I  .6871198  .0006856  2.6599 0.4548  P    34.906     .500      .089     .300  -.136000   .237000   .6860000      .000      .000  
+76 117 42794.00 I  -.154011  .013716   .230140  .015580  I  .6843817  .0007137  2.8244 0.4948  P    35.170     .500     -.155     .300  -.136000   .239000   .6832000      .000      .000  
+76 118 42795.00 I  -.154124  .015049   .232668  .020301  I  .6814605  .0007137  3.0204 0.5047  P    35.454     .500     -.171     .300  -.136000   .241000   .6803000      .000      .000  
+76 119 42796.00 I  -.154204  .018636   .235217  .016831  I  .6783439  .0007137  3.2073 0.5047  P    35.579     .500      .086     .300  -.136000   .243000   .6775000      .000      .000  
+76 120 42797.00 I  -.154253  .016248   .237786  .017702  I  .6750641  .0007137  3.3396 0.5664  P    35.440     .500      .431     .300  -.137000   .246000   .6746000      .000      .000  
+76 121 42798.00 I  -.154273  .014295   .240376  .017099  I  .6716935  .0008798  3.3855 0.3817  P    35.124     .500      .646     .300  -.137000   .248000   .6718000      .000      .000  
+76 122 42799.00 I  -.154264  .014284   .242988  .016999  I  .6683242  .0002710  3.3379 0.4603  P    34.836     .500      .665     .300  -.137000   .250000   .6689000      .000      .000  
+76 123 42800.00 I  -.154226  .016091   .245617  .016843  I  .6650428  .0002710  3.2149 0.1916  P    34.694     .500      .568     .300  -.137000   .252000   .6660000      .000      .000  
+76 124 42801.00 I  -.154162  .022566   .248261  .015025  I  .6619076  .0002710  3.0523 0.2230  P    34.641     .500      .454     .300  -.137000   .255000   .6630000      .000      .000  
+76 125 42802.00 I  -.154076  .022431   .250916  .010501  I  .6589383  .0003543  2.8895 0.2230  P    34.536     .500      .352     .300  -.138000   .257000   .6601000      .000      .000  
+76 126 42803.00 I  -.153970  .019010   .253580  .013465  I  .6561175  .0003543  2.7601 0.2505  P    34.323     .500      .228     .300  -.138000   .260000   .6571000      .000      .000  
+76 127 42804.00 I  -.153848  .018940   .256250  .014309  I  .6533998  .0003543  2.6856 0.2505  P    34.108     .500      .060     .300  -.138000   .262000   .6542000      .000      .000  
+76 128 42805.00 I  -.153715  .019674   .258922  .015134  I  .6507259  .0003543  2.6724 0.2505  P    34.068     .500     -.096     .300  -.138000   .264000   .6512000      .000      .000  
+76 129 42806.00 I  -.153574  .020069   .261594  .016652  I  .6480368  .0003543  2.7138 0.2505  P    34.263     .500     -.133     .300  -.138000   .267000   .6482000      .000      .000  
+76 130 42807.00 I  -.153428  .027449   .264265  .017661  I  .6452861  .0003543  2.7916 0.2230  P    34.553     .500     -.010     .300  -.138000   .269000   .6453000      .000      .000  
+76 131 42808.00 I  -.153279  .022599   .266934  .017278  I  .6424496  .0002710  2.8812 0.2230  P    34.735     .500      .192     .300  -.138000   .272000   .6423000      .000      .000  
+76 2 1 42809.00 I  -.153131  .024773   .269604  .018088  I  .6395274  .0002710  2.9598 0.1916  P    34.750     .500      .323     .300  -.138000   .274000   .6393000      .000      .000  
+76 2 2 42810.00 I  -.152986  .024613   .272274  .016586  I  .6365390  .0002710  3.0115 0.1916  P    34.685     .500      .294     .300  -.138000   .277000   .6363000      .000      .000  
+76 2 3 42811.00 I  -.152842  .027576   .274945  .015890  I  .6335159  .0002710  3.0288 0.1916  P    34.593     .500      .135     .300  -.138000   .279000   .6333000      .000      .000  
+76 2 4 42812.00 I  -.152695  .027962   .277617  .015073  I  .6304930  .0002710  3.0114 0.1475  P    34.446     .500     -.061     .300  -.138000   .282000   .6302000      .000      .000  
+76 2 5 42813.00 I  -.152540  .029022   .280290  .022401  I  .6275034  .0001165  2.9633 0.1475  P    34.274     .500     -.229     .300  -.138000   .284000   .6272000      .000      .000  
+76 2 6 42814.00 I  -.152375  .020871   .282961  .021750  I  .6245740  .0001165  2.8924 0.0824  P    34.208     .500     -.383     .300  -.138000   .287000   .6242000      .000      .000  
+76 2 7 42815.00 I  -.152197  .022280   .285628  .021834  I  .6217225  .0001165  2.8096 0.0824  P    34.293     .500     -.590     .300  -.138000   .290000   .6213000      .000      .000  
+76 2 8 42816.00 I  -.152000  .020205   .288288  .019899  I  .6189541  .0001165  2.7288 0.0824  P    34.380     .500     -.858     .300  -.138000   .292000   .6184000      .000      .000  
+76 2 9 42817.00 I  -.151781  .024814   .290936  .019500  I  .6162592  .0001165  2.6652 0.3020  P    34.325     .500    -1.072     .300  -.137000   .295000   .6155000      .000      .000  
+76 210 42818.00 I  -.151533  .021592   .293573  .019727  I  .6136127  .0005927  2.6346 0.4191  P    34.190     .500    -1.078     .300  -.137000   .297000   .6126000      .000      .000  
+76 211 42819.00 I  -.151251  .022318   .296199  .019903  I  .6109741  .0008300  2.6517 0.5099  P    34.139     .500     -.896     .300  -.137000   .300000   .6097000      .000      .000  
+76 212 42820.00 I  -.150933  .023046   .298814  .008227  I  .6082897  .0008300  2.7278 0.5515  P    34.206     .500     -.757     .300  -.137000   .302000   .6069000      .000      .000  
+76 213 42821.00 I  -.150575  .023444   .301418  .009201  I  .6054976  .0007263  2.8667 0.5515  P    34.312     .500     -.860     .300  -.136000   .305000   .6040000      .000      .000  
+76 214 42822.00 I  -.150174  .022883   .304014  .010289  I  .6025395  .0007263  3.0558 0.5136  P    34.448     .500    -1.114     .300  -.136000   .307000   .6012000      .000      .000  
+76 215 42823.00 I  -.149726  .022415   .306599  .013488  I  .5993805  .0007263  3.2612 0.4399  P    34.660     .500    -1.217     .300  -.135000   .310000   .5983000      .000      .000  
+76 216 42824.00 I  -.149229  .019353   .309176  .013318  I  .5960279  .0004964  3.4343 0.4593  P    34.884     .500    -1.014     .300  -.135000   .312000   .5955000      .000      .000  
+76 217 42825.00 I  -.148684  .020516   .311742  .012157  I  .5925383  .0005623  3.5283 0.3750  P    34.957     .500     -.678     .300  -.134000   .314000   .5927000      .000      .000  
+76 218 42826.00 I  -.148094  .018395   .314296  .012154  I  .5890064  .0005623  3.5170 0.3897  P    34.822     .500     -.500     .300  -.134000   .317000   .5899000      .000      .000  
+76 219 42827.00 I  -.147460  .027753   .316836  .011996  I  .5855373  .0005398  3.4066 0.3897  P    34.595     .500     -.593     .300  -.133000   .319000   .5871000      .000      .000  
+76 220 42828.00 I  -.146784  .027597   .319360  .012263  I  .5822144  .0005398  3.2327 0.3817  P    34.424     .500     -.844     .300  -.133000   .322000   .5843000      .000      .000  
+76 221 42829.00 I  -.146073  .027579   .321867  .011442  I  .5790765  .0005398  3.0449 0.4322  P    34.339     .500    -1.102     .300  -.132000   .324000   .5815000      .000      .000  
+76 222 42830.00 I  -.145331  .028228   .324357  .008838  I  .5761146  .0006751  2.8872 0.3020  P    34.283     .500    -1.312     .300  -.131000   .326000   .5787000      .000      .000  
+76 223 42831.00 I  -.144566  .027037   .326827  .010557  I  .5732827  .0002710  2.7875 0.3637  P    34.198     .500    -1.485     .300  -.131000   .328000   .5759000      .000      .000  
+76 224 42832.00 I  -.143778  .026292   .329279  .014138  I  .5705177  .0002710  2.7533 0.1916  P    34.084     .500    -1.619     .300  -.130000   .331000   .5731000      .000      .000  
+76 225 42833.00 I  -.142971  .028828   .331710  .016565  I  .5677568  .0002710  2.7771 0.1916  P    34.017     .500    -1.698     .300  -.130000   .333000   .5703000      .000      .000  
+76 226 42834.00 I  -.142145  .019992   .334119  .016758  I  .5649494  .0002710  2.8431 0.1916  P    34.082     .500    -1.716     .300  -.129000   .335000   .5675000      .000      .000  
+76 227 42835.00 I  -.141302  .021732   .336505  .015875  I  .5620635  .0002710  2.9305 0.1916  P    34.266     .500    -1.682     .300  -.128000   .337000   .5646000      .000      .000  
+76 228 42836.00 I  -.140442  .021616   .338863  .015840  I  .5590883  .0002710  3.0182 0.1916  P    34.445     .500    -1.606     .300  -.128000   .339000   .5617000      .000      .000  
+76 229 42837.00 I  -.139563  .023839   .341194  .015307  I  .5560332  .0002710  3.0876 0.1916  P    34.527     .500    -1.516     .300  -.127000   .341000   .5589000      .000      .000  
+76 3 1 42838.00 I  -.138660  .025223   .343496  .016603  I  .5529235  .0002710  3.1259 0.1916  P    34.541     .500    -1.471     .300  -.127000   .343000   .5560000      .000      .000  
+76 3 2 42839.00 I  -.137733  .026716   .345769  .017604  I  .5497932  .0002710  3.1287 0.1916  P    34.536     .500    -1.539     .300  -.126000   .345000   .5531000      .000      .000  
+76 3 3 42840.00 I  -.136781  .025231   .348013  .017350  I  .5466772  .0002710  3.0982 0.1916  P    34.508     .500    -1.735     .300  -.125000   .347000   .5501000      .000      .000  
+76 3 4 42841.00 I  -.135807  .022954   .350227  .017060  I  .5436056  .0002710  3.0415 0.1916  P    34.481     .500    -2.002     .300  -.124000   .349000   .5471000      .000      .000  
+76 3 5 42842.00 I  -.134811  .021359   .352411  .017042  I  .5405995  .0002710  2.9690 0.1916  P    34.561     .500    -2.272     .300  -.124000   .350000   .5441000      .000      .000  
+76 3 6 42843.00 I  -.133796  .020792   .354565  .017960  I  .5376686  .0002710  2.8934 0.1916  P    34.759     .500    -2.538     .300  -.123000   .352000   .5411000      .000      .000  
+76 3 7 42844.00 I  -.132760  .016235   .356692  .017907  I  .5348089  .0002710  2.8292 0.1916  P    34.880     .500    -2.824     .300  -.122000   .354000   .5381000      .000      .000  
+76 3 8 42845.00 I  -.131707  .013653   .358793  .015608  I  .5320016  .0002710  2.7909 0.1916  P    34.772     .500    -3.058     .300  -.121000   .356000   .5350000      .000      .000  
+76 3 9 42846.00 I  -.130636  .011786   .360869  .015417  I  .5292134  .0002710  2.7936 0.1916  P    34.585     .500    -3.076     .300  -.120000   .358000   .5319000      .000      .000  
+76 310 42847.00 I  -.129551  .018724   .362923  .013113  I  .5263966  .0002710  2.8498 0.1916  P    34.595     .500    -2.822     .300  -.120000   .359000   .5288000      .000      .000  
+76 311 42848.00 I  -.128452  .018696   .364956  .013617  I  .5234931  .0002710  2.9680 0.1916  P    34.818     .500    -2.505     .300  -.119000   .361000   .5257000      .000      .000  
+76 312 42849.00 I  -.127341  .020624   .366971  .013536  I  .5204408  .0002710  3.1456 0.1916  P    35.016     .500    -2.426     .300  -.118000   .363000   .5226000      .000      .000  
+76 313 42850.00 I  -.126221  .020315   .368970  .013093  I  .5171889  .0002710  3.3623 0.1916  P    35.059     .500    -2.626     .300  -.117000   .365000   .5194000      .000      .000  
+76 314 42851.00 I  -.125094  .024892   .370954  .013170  I  .5137165  .0002710  3.5783 0.1916  P    35.068     .500    -2.830     .300  -.116000   .367000   .5163000      .000      .000  
+76 315 42852.00 I  -.123959  .025303   .372922  .013194  I  .5100498  .0002710  3.7419 0.1916  P    35.167     .500    -2.783     .300  -.116000   .368000   .5131000      .000      .000  
+76 316 42853.00 I  -.122815  .026578   .374874  .015764  I  .5062651  .0002710  3.8081 0.1916  P    35.289     .500    -2.563     .300  -.115000   .370000   .5100000      .000      .000  
+76 317 42854.00 I  -.121658  .021103   .376808  .016142  I  .5024721  .0002710  3.7586 0.1916  P    35.306     .500    -2.443     .300  -.114000   .372000   .5068000      .000      .000  
+76 318 42855.00 I  -.120484  .022236   .378726  .016388  I  .4987803  .0002710  3.6120 0.1916  P    35.190     .500    -2.552     .300  -.113000   .374000   .5036000      .000      .000  
+76 319 42856.00 I  -.119284  .019972   .380628  .016285  I  .4952644  .0002710  3.4166 0.1916  P    35.006     .500    -2.776     .300  -.112000   .376000   .5003000      .000      .000  
+76 320 42857.00 I  -.118052  .021091   .382514  .015835  I  .4919446  .0002710  3.2289 0.1916  P    34.848     .500    -2.980     .300  -.112000   .377000   .4971000      .000      .000  
+76 321 42858.00 I  -.116778  .016806   .384388  .015902  I  .4887897  .0002710  3.0921 0.1916  P    34.805     .500    -3.161     .300  -.111000   .379000   .4938000      .000      .000  
+76 322 42859.00 I  -.115450  .019674   .386253  .015930  I  .4857373  .0002710  3.0246 0.1916  P    34.892     .500    -3.358     .300  -.110000   .381000   .4906000      .000      .000  
+76 323 42860.00 I  -.114059  .017426   .388112  .021129  I  .4827192  .0002710  3.0210 0.1916  P    34.984     .500    -3.521     .300  -.109000   .383000   .4873000      .000      .000  
+76 324 42861.00 I  -.112595  .018859   .389968  .022575  I  .4796800  .0002710  3.0635 0.1916  P    34.953     .500    -3.577     .300  -.108000   .385000   .4839000      .000      .000  
+76 325 42862.00 I  -.111052  .017496   .391823  .023131  I  .4765838  .0002710  3.1314 0.1916  P    34.861     .500    -3.551     .300  -.107000   .386000   .4806000      .000      .000  
+76 326 42863.00 I  -.109424  .017660   .393681  .024201  I  .4734152  .0002710  3.2053 0.1916  P    34.903     .500    -3.524     .300  -.106000   .388000   .4772000      .000      .000  
+76 327 42864.00 I  -.107709  .016876   .395542  .023938  I  .4701765  .0002710  3.2692 0.1916  P    35.128     .500    -3.502     .300  -.105000   .390000   .4739000      .000      .000  
+76 328 42865.00 I  -.105906  .019459   .397406  .024321  I  .4668847  .0002710  3.3096 0.1916  P    35.376     .500    -3.418     .300  -.104000   .392000   .4705000      .000      .000  
+76 329 42866.00 I  -.104018  .020254   .399271  .024936  I  .4635681  .0002710  3.3178 0.1916  P    35.485     .500    -3.279     .300  -.103000   .394000   .4671000      .000      .000  
+76 330 42867.00 I  -.102047  .020075   .401134  .015593  I  .4602603  .0002710  3.2924 0.1916  P    35.452     .500    -3.219     .300  -.102000   .395000   .4638000      .000      .000  
+76 331 42868.00 I  -.099995  .019682   .402994  .013104  I  .4569929  .0002710  3.2381 0.1916  P    35.370     .500    -3.366     .300  -.101000   .397000   .4604000      .000      .000  
+76 4 1 42869.00 I  -.097866  .022869   .404852  .010940  I  .4537904  .0002710  3.1647 0.1916  P    35.343     .500    -3.687     .300  -.100000   .399000   .4570000      .000      .000  
+76 4 2 42870.00 I  -.095669  .023134   .406706  .009676  I  .4506658  .0002710  3.0843 0.1916  P    35.454     .500    -4.023     .300  -.099000   .401000   .4536000      .000      .000  
+76 4 3 42871.00 I  -.093413  .029528   .408553  .010259  I  .4476198  .0002710  3.0098 0.1916  P    35.683     .500    -4.271     .300  -.097000   .403000   .4502000      .000      .000  
+76 4 4 42872.00 I  -.091109  .027848   .410392  .013521  I  .4446395  .0002710  2.9552 0.1916  P    35.842     .500    -4.453     .300  -.096000   .405000   .4467000      .000      .000  
+76 4 5 42873.00 I  -.088767  .027254   .412218  .015908  I  .4416984  .0002710  2.9334 0.1916  P    35.769     .500    -4.601     .300  -.094000   .407000   .4433000      .000      .000  
+76 4 6 42874.00 I  -.086392  .027282   .414029  .016508  I  .4387576  .0002710  2.9567 0.1916  P    35.592     .500    -4.633     .300  -.093000   .409000   .4399000      .000      .000  
+76 4 7 42875.00 I  -.083990  .026590   .415821  .016570  I  .4357669  .0002710  3.0343 0.1916  P    35.623     .500    -4.456     .300  -.091000   .411000   .4366000      .000      .000  
+76 4 8 42876.00 I  -.081562  .025638   .417591  .016427  I  .4326701  .0002710  3.1686 0.1916  P    35.957     .500    -4.164     .300  -.090000   .413000   .4332000      .000      .000  
+76 4 9 42877.00 I  -.079110  .025479   .419335  .018981  I  .4294138  .0002710  3.3508 0.1916  P    36.333     .500    -3.998     .300  -.088000   .415000   .4299000      .000      .000  
+76 410 42878.00 I  -.076635  .017470   .421048  .018549  I  .4259609  .0002710  3.5560 0.1364  P    36.470     .500    -4.066     .300  -.087000   .417000   .4265000      .000      .000  
+76 411 42879.00 I  -.074138  .017454   .422728  .016428  I  .4223079  .0000313  3.7430 0.1364  P    36.362     .500    -4.200     .300  -.085000   .419000   .4232000      .000      .000  
+76 412 42880.00 I  -.071621  .013801   .424368  .013859  I  .4184967  .0000313  3.8647 0.0221  P    36.184     .500    -4.178     .300  -.083000   .421000   .4199000      .000      .000  
+76 413 42881.00 I  -.069088  .019246   .425965  .012853  I  .4146124  .0000313  3.8848 0.0221  P    36.049     .500    -4.022     .300  -.081000   .423000   .4166000      .000      .000  
+76 414 42882.00 I  -.066544  .021378   .427516  .012722  I  .4107633  .0000313  3.7961 0.0221  P    35.947     .500    -3.945     .300  -.080000   .424000   .4132000      .000      .000  
+76 415 42883.00 I  -.063992  .021303   .429019  .019956  I  .4070470  .0000313  3.6268 0.0221  P    35.821     .500    -4.045     .300  -.078000   .426000   .4099000      .000      .000  
+76 416 42884.00 I  -.061439  .021056   .430471  .017183  I  .4035190  .0000313  3.4296 0.0909  P    35.634     .500    -4.194     .300  -.076000   .428000   .4066000      .000      .000  
+76 417 42885.00 I  -.058886  .024179   .431870  .017536  I  .4001787  .0001791  3.2597 0.0702  P    35.448     .500    -4.264     .300  -.074000   .430000   .4033000      .000      .000  
+76 418 42886.00 I  -.056337  .023067   .433213  .017025  I  .3969785  .0001368  3.1529 0.1078  P    35.437     .500    -4.314     .300  -.072000   .431000   .4000000      .000      .000  
+76 419 42887.00 I  -.053792  .023358   .434496  .017256  I  .3938495  .0001202  3.1162 0.0911  P    35.686     .500    -4.457     .300  -.071000   .433000   .3968000      .000      .000  
+76 420 42888.00 I  -.051253  .018740   .435720  .017254  I  .3907280  .0001202  3.1339 0.0850  P    35.980     .500    -4.652     .300  -.069000   .434000   .3935000      .000      .000  
+76 421 42889.00 I  -.048720  .017063   .436883  .017983  I  .3875718  .0001202  3.1813 0.0850  P    35.988     .500    -4.762     .300  -.067000   .436000   .3902000      .000      .000  
+76 422 42890.00 I  -.046197  .015392   .437983  .009674  I  .3843629  .0001202  3.2364 0.0709  P    35.700     .500    -4.754     .300  -.065000   .437000   .3870000      .000      .000  
+76 423 42891.00 I  -.043688  .019258   .439018  .009643  I  .3811017  .0000752  3.2836 0.0714  P    35.482     .500    -4.722     .300  -.063000   .439000   .3837000      .000      .000  
+76 424 42892.00 I  -.041199  .019207   .439986  .009190  I  .3778019  .0000770  3.3122 0.1406  P    35.596     .500    -4.700     .300  -.061000   .440000   .3805000      .000      .000  
+76 425 42893.00 I  -.038736  .022299   .440883  .012492  I  .3744861  .0002710  3.3145 0.1409  P    35.865     .500    -4.608     .300  -.059000   .442000   .3772000      .000      .000  
+76 426 42894.00 I  -.036303  .021863   .441706  .010986  I  .3711830  .0002710  3.2866 0.1916  P    35.938     .500    -4.418     .300  -.057000   .443000   .3740000      .000      .000  
+76 427 42895.00 I  -.033903  .023053   .442451  .010729  I  .3679226  .0002710  3.2298 0.1916  P    35.729     .500    -4.275     .300  -.055000   .444000   .3707000      .000      .000  
+76 428 42896.00 I  -.031534  .022153   .443115  .010928  I  .3647305  .0002710  3.1517 0.1916  P    35.441     .500    -4.356     .300  -.053000   .445000   .3675000      .000      .000  
+76 429 42897.00 I  -.029191  .023138   .443696  .011384  I  .3616222  .0002710  3.0645 0.1916  P    35.289     .500    -4.659     .300  -.050000   .446000   .3642000      .000      .000  
+76 430 42898.00 I  -.026867  .024223   .444191  .012930  I  .3586003  .0002710  2.9810 0.1916  P    35.342     .500    -4.994     .300  -.048000   .447000   .3610000      .000      .000  
+76 5 1 42899.00 I  -.024555  .021533   .444600  .014059  I  .3556546  .0002710  2.9143 0.1916  P    35.544     .500    -5.191     .300  -.046000   .448000   .3577000      .000      .000  
+76 5 2 42900.00 I  -.022248  .019638   .444920  .010883  I  .3527621  .0002710  2.8764 0.1916  P    35.744     .500    -5.254     .300  -.044000   .449000   .3545000      .000      .000  
+76 5 3 42901.00 I  -.019943  .019551   .445150  .010874  I  .3498887  .0002710  2.8779 0.1916  P    35.771     .500    -5.278     .300  -.042000   .450000   .3512000      .000      .000  
+76 5 4 42902.00 I  -.017638  .019515   .445288  .010778  I  .3469905  .0002710  2.9269 0.1916  P    35.618     .500    -5.294     .300  -.039000   .450000   .3480000      .000      .000  
+76 5 5 42903.00 I  -.015335  .029887   .445331  .014184  I  .3440182  .0002710  3.0261 0.1916  P    35.509     .500    -5.242     .300  -.037000   .451000   .3447000      .000      .000  
+76 5 6 42904.00 I  -.013036  .032615   .445276  .013640  I  .3409233  .0002710  3.1702 0.1916  P    35.660     .500    -5.106     .300  -.035000   .452000   .3415000      .000      .000  
+76 5 7 42905.00 I  -.010745  .031145   .445122  .015107  I  .3376682  .0002710  3.3430 0.1916  P    36.018     .500    -4.963     .300  -.032000   .452000   .3381000      .000      .000  
+76 5 8 42906.00 I  -.008465  .032311   .444867  .014822  I  .3342371  .0002710  3.5165 0.1361  P    36.316     .500    -4.873     .300  -.030000   .453000   .3347000      .000      .000  
+76 5 9 42907.00 I  -.006202  .031974   .444511  .015973  I  .3306472  .0000251  3.6541 0.1361  P    36.340     .500    -4.773     .300  -.027000   .453000   .3314000      .000      .000  
+76 510 42908.00 I  -.003954  .031749   .444053  .015863  I  .3269529  .0000251  3.7198 0.0177  P    36.081     .500    -4.577     .300  -.025000   .454000   .3280000      .000      .000  
+76 511 42909.00 I  -.001718  .034863   .443494  .018669  I  .3232386  .0000251  3.6924 0.0177  P    35.686     .500    -4.353     .300  -.022000   .454000   .3246000      .000      .000  
+76 512 42910.00 I   .000512  .027128   .442837  .015306  I  .3195973  .0000251  3.5774 0.0177  P    35.326     .500    -4.278     .300  -.019000   .454000   .3212000      .000      .000  
+76 513 42911.00 I   .002734  .023574   .442084  .016928  I  .3161017  .0000251  3.4087 0.0177  P    35.081     .500    -4.407     .300  -.017000   .454000   .3177000      .000      .000  
+76 514 42912.00 I   .004949  .022560   .441237  .018179  I  .3127807  .0000251  3.2374 0.1361  P    34.920     .500    -4.573     .300  -.014000   .454000   .3143000      .000      .000  
+76 515 42913.00 I   .007154  .025115   .440300  .017685  I  .3096121  .0002710  3.1103 0.1361  P    34.829     .500    -4.601     .300  -.012000   .454000   .3108000      .000      .000  
+76 516 42914.00 I   .009354  .025886   .439276  .017374  I  .3065373  .0002710  3.0514 0.5838  P    34.921     .500    -4.531     .300  -.009000   .454000   .3074000      .000      .000  
+76 517 42915.00 I   .011554  .015228   .438172  .024085  I  .3034880  .0011357  3.0564 0.5838  P    35.272     .500    -4.538     .300  -.006000   .454000   .3041000      .000      .000  
+76 518 42916.00 I   .013761  .013212   .436993  .021861  I  .3004110  .0011357  3.1018 0.8031  P    35.653     .500    -4.680     .300  -.003000   .454000   .3007000      .000      .000  
+76 519 42917.00 I   .015983  .012736   .435748  .023128  I  .2972803  .0011357  3.1595 0.7826  P    35.662     .500    -4.847     .300   .002000   .453000   .2940000      .000      .000  
+76 520 42918.00 I   .018227  .011988   .434445  .021843  I  .2940956  .0010770  3.2064 0.7826  P    35.218     .500    -4.940     .300   .002000   .453000   .2940000      .000      .000  
+76 521 42919.00 I   .020497  .013350   .433093  .019769  I  .2908756  .0010770  3.2288 0.7616  P    34.722     .500    -4.973     .300   .005000   .453000   .2907000      .000      .000  
+76 522 42920.00 I   .022791  .010961   .431707  .020316  I  .2876480  .0010770  3.2211 0.7112  P    34.569     .500    -4.973     .300   .008000   .452000   .2876000      .000      .000  
+76 523 42921.00 I   .025112  .017028   .430297  .025592  I  .2844442  .0009290  3.1811 0.7112  P    34.662     .500    -4.898     .300   .011000   .452000   .2845000      .000      .000  
+76 524 42922.00 I   .027462  .018765   .428878  .021431  I  .2812960  .0009290  3.1104 0.6569  P    34.604     .500    -4.727     .300   .014000   .451000   .2813000      .000      .000  
+76 525 42923.00 I   .029845  .021464   .427465  .023084  I  .2782318  .0009290  3.0144 0.4839  P    34.243     .500    -4.571     .300   .017000   .451000   .2782000      .000      .000  
+76 526 42924.00 I   .032266  .021326   .426071  .026544  I  .2752722  .0002710  2.9034 0.5321  P    33.798     .500    -4.578     .300   .020000   .450000   .2751000      .000      .000  
+76 527 42925.00 I   .034735  .019010   .424714  .031487  I  .2724254  .0005192  2.7911 0.2928  P    33.522     .500    -4.764     .300   .023000   .449000   .2721000      .000      .000  
+76 528 42926.00 I   .037259  .017697   .423411  .032194  I  .2696860  .0005192  2.6909 0.3671  P    33.468     .500    -4.989     .300   .026000   .448000   .2692000      .000      .000  
+76 529 42927.00 I   .039850  .017832   .422181  .032774  I  .2670353  .0005192  2.6155 0.3671  P    33.572     .500    -5.113     .300   .029000   .447000   .2662000      .000      .000  
+76 530 42928.00 I   .042519  .018091   .421041  .032189  I  .2644432  .0005192  2.5754 0.3671  P    33.756     .500    -5.119     .300   .032000   .446000   .2633000      .000      .000  
+76 531 42929.00 I   .045268  .017790   .419990  .032522  I  .2618698  .0005192  2.5793 0.3671  P    33.886     .500    -5.076     .300   .035000   .445000   .2603000      .000      .000  
+76 6 1 42930.00 I   .048095  .016824   .419011  .032820  I  .2592691  .0005192  2.6297 0.2928  P    33.816     .500    -5.034     .300   .038000   .444000   .2575000      .000      .000  
+76 6 2 42931.00 I   .050998  .029671   .418092  .038316  I  .2565967  .0002710  2.7211 0.2928  P    33.554     .500    -4.990     .300   .041000   .443000   .2547000      .000      .000  
+76 6 3 42932.00 I   .053973  .014562   .417222  .032233  I  .2538185  .0002710  2.8377 0.1916  P    33.306     .500    -4.919     .300   .044000   .441000   .2518000      .000      .000  
+76 6 4 42933.00 I   .057023  .016750   .416390  .030196  I  .2509208  .0002710  2.9557 0.2772  P    33.274     .500    -4.811     .300   .047000   .440000   .2490000      .000      .000  
+76 6 5 42934.00 I   .060145  .010769   .415586  .026172  I  .2479160  .0004837  3.0468 0.2772  P    33.439     .500    -4.650     .300   .050000   .439000   .2462000      .000      .000  
+76 6 6 42935.00 I   .063339  .010144   .414802  .024184  I  .2448453  .0004837  3.0834 0.3156  P    33.580     .500    -4.407     .300   .053000   .438000   .2436000      .000      .000  
+76 6 7 42936.00 I   .066601  .010178   .414032  .026245  I  .2417737  .0004054  3.0464 0.3173  P    33.474     .500    -4.092     .300   .056000   .436000   .2411000      .000      .000  
+76 6 8 42937.00 I   .069929  .009029   .413270  .024375  I  .2387777  .0004107  2.9338 0.2885  P    33.081     .500    -3.817     .300   .060000   .435000   .2385000      .000      .000  
+76 6 9 42938.00 I   .073319  .008816   .412510  .021824  I  .2359248  .0004107  2.7650 0.2904  P    32.557     .500    -3.744     .300   .063000   .433000   .2360000      .000      .000  
+76 610 42939.00 I   .076764  .009057   .411747  .019391  I  .2332542  .0004107  2.5767 0.2562  P    32.112     .500    -3.916     .300   .066000   .432000   .2334000      .000      .000  
+76 611 42940.00 I   .080261  .026762   .410977  .017018  I  .2307632  .0003065  2.4129 0.2562  P    31.856     .500    -4.169     .300   .069000   .430000   .2310000      .000      .000  
+76 612 42941.00 I   .083804  .023827   .410197  .019613  I  .2284091  .0003065  2.3070 0.2631  P    31.804     .500    -4.279     .300   .072000   .428000   .2286000      .000      .000  
+76 613 42942.00 I   .087388  .020718   .409404  .020443  I  .2261262  .0004277  2.2700 0.2046  P    31.968     .500    -4.188     .300   .076000   .427000   .2262000      .000      .000  
+76 614 42943.00 I   .091007  .023104   .408596  .014955  I  .2238509  .0002710  2.2876 0.2532  P    32.315     .500    -4.048     .300   .079000   .425000   .2238000      .000      .000  
+76 615 42944.00 I   .094657  .020057   .407772  .016181  I  .2215422  .0002710  2.3315 0.5257  P    32.631     .500    -4.035     .300   .082000   .423000   .2214000      .000      .000  
+76 616 42945.00 I   .098336  .010221   .406929  .008280  I  .2191885  .0010159  2.3734 0.5257  P    32.594     .500    -4.168     .300   .085000   .421000   .2192000      .000      .000  
+76 617 42946.00 I   .102046  .010927   .406065  .008886  I  .2168023  .0010159  2.3945 0.7183  P    32.118     .500    -4.349     .300   .089000   .419000   .2170000      .000      .000  
+76 618 42947.00 I   .105785  .006070   .405180  .009023  I  .2144087  .0010159  2.3878 0.7183  P    31.502     .500    -4.488     .300   .092000   .417000   .2147000      .000      .000  
+76 619 42948.00 I   .109553  .006764   .404273  .010024  I  .2120361  .0010159  2.3528 0.7183  P    31.108     .500    -4.546     .300   .096000   .415000   .2125000      .000      .000  
+76 620 42949.00 I   .113344  .006896   .403338  .008907  I  .2097117  .0010159  2.2918 0.7183  P    30.959     .500    -4.508     .300   .099000   .413000   .2103000      .000      .000  
+76 621 42950.00 I   .117150  .006919   .402367  .008774  I  .2074596  .0010159  2.2093 0.5257  P    30.791     .500    -4.394     .300   .102000   .411000   .2082000      .000      .000  
+76 622 42951.00 I   .120965  .014599   .401350  .016242  I  .2052974  .0002710  2.1139 0.5257  P    30.440     .500    -4.282     .300   .106000   .409000   .2060000      .000      .000  
+76 623 42952.00 I   .124783  .014148   .400278  .018873  I  .2032318  .0002710  2.0184 0.1916  P    30.009     .500    -4.253     .300   .109000   .407000   .2039000      .000      .000  
+76 624 42953.00 I   .128599  .011801   .399142  .019498  I  .2012559  .0002710  1.9371 0.2842  P    29.662     .500    -4.305     .300   .113000   .405000   .2017000      .000      .000  
+76 625 42954.00 I   .132409  .009464   .397934  .013822  I  .1993482  .0004996  1.8840 0.2842  P    29.449     .500    -4.373     .300   .116000   .403000   .1996000      .000      .000  
+76 626 42955.00 I   .136210  .009118   .396646  .013289  I  .1974747  .0004996  1.8704 0.3533  P    29.376     .500    -4.417     .300   .119000   .401000   .1974000      .000      .000  
+76 627 42956.00 I   .139998  .010044   .395270  .013855  I  .1955915  .0004996  1.9044 0.3533  P    29.465     .500    -4.443     .300   .123000   .399000   .1952000      .000      .000  
+76 628 42957.00 I   .143772  .010177   .393797  .014147  I  .1936489  .0004996  1.9894 0.3533  P    29.664     .500    -4.447     .300   .126000   .396000   .1931000      .000      .000  
+76 629 42958.00 I   .147529  .009946   .392219  .014527  I  .1915975  .0004996  2.1200 0.3533  P    29.768     .500    -4.392     .300   .130000   .394000   .1909000      .000      .000  
+76 630 42959.00 I   .151267  .009767   .390543  .013771  I  .1893993  .0004996  2.2795 0.2842  P    29.579     .500    -4.262     .300   .133000   .392000   .1887000      .000      .000  
+76 7 1 42960.00 I   .154984  .019830   .388776  .017706  I  .1870376  .0002710  2.4419 0.2842  P    29.122     .500    -4.100     .300   .136000   .390000   .1865000      .000      .000  
+76 7 2 42961.00 I   .158679  .012035   .386923  .018126  I  .1845248  .0002710  2.5765 0.1916  P    28.647     .500    -3.961     .300   .140000   .387000   .1843000      .000      .000  
+76 7 3 42962.00 I   .162352  .025314   .384992  .017509  I  .1819028  .0002710  2.6567 0.1916  P    28.398     .500    -3.850     .300   .143000   .385000   .1821000      .000      .000  
+76 7 4 42963.00 I   .166004  .026766   .382986  .015606  I  .1792345  .0002710  2.6678 0.1916  P    28.401     .500    -3.727     .300   .147000   .382000   .1799000      .000      .000  
+76 7 5 42964.00 I   .169636  .023622   .380910  .013515  I  .1765898  .0002710  2.6111 0.1916  P    28.460     .500    -3.574     .300   .150000   .380000   .1777000      .000      .000  
+76 7 6 42965.00 I   .173247  .027171   .378770  .010076  I  .1740294  .0002710  2.5031 0.4874  P    28.341     .500    -3.441     .300   .153000   .378000   .1753000      .000      .000  
+76 7 7 42966.00 I   .176837  .023531   .376569  .010530  I  .1715909  .0009363  2.3731 0.4874  P    27.962     .500    -3.432     .300   .156000   .376000   .1730000      .000      .000  
+76 7 8 42967.00 I   .180401  .027149   .374315  .011249  I  .1692790  .0009363  2.2558 0.6621  P    27.439     .500    -3.606     .300   .159000   .373000   .1706000      .000      .000  
+76 7 9 42968.00 I   .183934  .023688   .372014  .012146  I  .1670645  .0009363  2.1828 0.6621  P    26.996     .500    -3.885     .300   .162000   .371000   .1683000      .000      .000  
+76 710 42969.00 I   .187428  .006215   .369671  .010793  I  .1648930  .0009363  2.1709 0.6621  P    26.810     .500    -4.080     .300   .165000   .369000   .1659000      .000      .000  
+76 711 42970.00 I   .190877  .013048   .367294  .021545  I  .1627037  .0009363  2.2161 0.6621  P    26.920     .500    -4.053     .300   .168000   .367000   .1635000      .000      .000  
+76 712 42971.00 I   .194274  .014123   .364887  .024878  I  .1604486  .0009363  2.2978 0.4874  P    27.202     .500    -3.857     .300   .171000   .365000   .1611000      .000      .000  
+76 713 42972.00 I   .197611  .012369   .362456  .021578  I  .1581059  .0002710  2.3862 0.4874  P    27.424     .500    -3.682     .300   .173000   .362000   .1586000      .000      .000  
+76 714 42973.00 I   .200882  .014282   .360005  .023968  I  .1556828  .0002710  2.4549 0.1916  P    27.379     .500    -3.672     .300   .176000   .360000   .1562000      .000      .000  
+76 715 42974.00 I   .204078  .012459   .357538  .021185  I  .1532076  .0002710  2.4891 0.1916  P    27.028     .500    -3.813     .300   .179000   .358000   .1538000      .000      .000  
+76 716 42975.00 I   .207189  .013996   .355057  .022984  I  .1507172  .0002710  2.4854 0.1916  P    26.525     .500    -3.987     .300   .182000   .356000   .1514000      .000      .000  
+76 717 42976.00 I   .210205  .013428   .352562  .022192  I  .1482482  .0002710  2.4474 0.1916  P    26.082     .500    -4.096     .300   .184000   .354000   .1489000      .000      .000  
+76 718 42977.00 I   .213113  .007213   .350055  .012419  I  .1458315  .0002710  2.3820 0.2024  P    25.800     .500    -4.114     .300   .187000   .351000   .1465000      .000      .000  
+76 719 42978.00 I   .215903  .011449   .347537  .011023  I  .1434907  .0003008  2.2972 0.2024  P    25.637     .500    -4.084     .300   .189000   .349000   .1440000      .000      .000  
+76 720 42979.00 I   .218565  .011737   .345008  .012654  I  .1412396  .0003008  2.2047 0.2127  P    25.480     .500    -4.067     .300   .192000   .347000   .1416000      .000      .000  
+76 721 42980.00 I   .221086  .013109   .342468  .011130  I  .1390792  .0003008  2.1183 0.2127  P    25.243     .500    -4.085     .300   .194000   .345000   .1392000      .000      .000  
+76 722 42981.00 I   .223456  .013457   .339916  .011884  I  .1369961  .0003008  2.0527 0.2127  P    24.912     .500    -4.097     .300   .197000   .343000   .1368000      .000      .000  
+76 723 42982.00 I   .225666  .014000   .337350  .010613  I  .1349622  .0003008  2.0218 0.2127  P    24.574     .500    -4.063     .300   .199000   .340000   .1343000      .000      .000  
+76 724 42983.00 I   .227725  .014125   .334770  .004666  I  .1329375  .0003008  2.0358 0.2024  P    24.377     .500    -4.020     .300   .202000   .338000   .1319000      .000      .000  
+76 725 42984.00 I   .229645  .018683   .332174  .004836  I  .1308736  .0002710  2.1007 0.2024  P    24.427     .500    -4.043     .300   .204000   .336000   .1295000      .000      .000  
+76 726 42985.00 I   .231435  .021550   .329559  .004837  I  .1287194  .0002710  2.2157 0.1916  P    24.679     .500    -4.122     .300   .206000   .334000   .1271000      .000      .000  
+76 727 42986.00 I   .233101  .018726   .326925  .006796  I  .1264293  .0002710  2.3694 0.1916  P    24.928     .500    -4.128     .300   .209000   .332000   .1247000      .000      .000  
+76 728 42987.00 I   .234651  .014478   .324267  .007520  I  .1239761  .0002710  2.5366 0.1916  P    24.933     .500    -3.959     .300   .211000   .329000   .1223000      .000      .000  
+76 729 42988.00 I   .236088  .014191   .321585  .008238  I  .1213634  .0002710  2.6819 0.1916  P    24.587     .500    -3.672     .300   .214000   .327000   .1199000      .000      .000  
+76 730 42989.00 I   .237420  .010745   .318877  .009031  I  .1186313  .0002710  2.7702 0.1916  P    24.008     .500    -3.435     .300   .216000   .325000   .1175000      .000      .000  
+76 731 42990.00 I   .238655  .009757   .316140  .017333  I  .1158493  .0002710  2.7796 0.1916  P    23.474     .500    -3.362     .300   .218000   .323000   .1151000      .000      .000  
+76 8 1 42991.00 I   .239798  .008575   .313373  .019777  I  .1130985  .0002710  2.7097 0.1916  P    23.222     .500    -3.427     .300   .220000   .320000   .1128000      .000      .000  
+76 8 2 42992.00 I   .240858  .015887   .310575  .021115  I  .1104494  .0002710  2.5814 0.5479  P    23.278     .500    -3.528     .300   .223000   .318000   .1104000      .000      .000  
+76 8 3 42993.00 I   .241840  .018258   .307745  .023586  I  .1079439  .0010618  2.4286 0.4141  P    23.444     .500    -3.601     .300   .225000   .315000   .1081000      .000      .000  
+76 8 4 42994.00 I   .242751  .017501   .304881  .020428  I  .1055884  .0007826  2.2872 0.6595  P    23.466     .500    -3.664     .300   .227000   .313000   .1057000      .000      .000  
+76 8 5 42995.00 I   .243595  .018695   .301983  .022857  I  .1033558  .0007826  2.1868 0.5638  P    23.237     .500    -3.774     .300   .229000   .310000   .1034000      .000      .000  
+76 8 6 42996.00 I   .244380  .016191   .299052  .020758  I  .1011959  .0008117  2.1431 0.5368  P    22.881     .500    -3.946     .300   .231000   .308000   .1011000      .000      .000  
+76 8 7 42997.00 I   .245108  .018386   .296091  .015984  I  .0990505  .0007349  2.1567 0.5328  P    22.645     .500    -4.097     .300   .233000   .305000   .0989000      .000      .000  
+76 8 8 42998.00 I   .245781  .018222   .293101  .014653  I  .0968681  .0006904  2.2136 0.4648  P    22.668     .500    -4.107     .300   .235000   .303000   .0966000      .000      .000  
+76 8 9 42999.00 I   .246402  .013405   .290085  .009107  I  .0946168  .0005694  2.2900 0.4437  P    22.859     .500    -3.942     .300   .237000   .300000   .0943000      .000      .000  
+76 810 43000.00 I   .246970  .013248   .287047  .008296  I  .0922901  .0005576  2.3605 0.3884  P    23.000     .500    -3.703     .300   .239000   .297000   .0921000      .000      .000  
+76 811 43001.00 I   .247487  .012610   .283988  .009573  I  .0899044  .0005284  2.4052 0.3624  P    22.955     .500    -3.540     .300   .241000   .294000   .0898000      .000      .000  
+76 812 43002.00 I   .247953  .010924   .280913  .012004  I  .0874919  .0004629  2.4132 0.3405  P    22.739     .500    -3.523     .300   .242000   .292000   .0876000      .000      .000  
+76 813 43003.00 I   .248371  .012612   .277825  .011836  I  .0850903  .0004295  2.3843 0.3379  P    22.425     .500    -3.612     .300   .244000   .289000   .0853000      .000      .000  
+76 814 43004.00 I   .248745  .013997   .274725  .010724  I  .0827333  .0004923  2.3255 0.3486  P    22.079     .500    -3.732     .300   .246000   .286000   .0831000      .000      .000  
+76 815 43005.00 I   .249075  .012514   .271617  .011071  I  .0804458  .0005491  2.2472 0.3934  P    21.816     .500    -3.839     .300   .248000   .283000   .0809000      .000      .000  
+76 816 43006.00 I   .249363  .013555   .268503  .010565  I  .0782417  .0006137  2.1605 0.4251  P    21.756     .500    -3.934     .300   .249000   .280000   .0786000      .000      .000  
+76 817 43007.00 I   .249611  .013808   .265386  .011833  I  .0761236  .0006492  2.0775 0.4414  P    21.858     .500    -4.040     .300   .251000   .278000   .0764000      .000      .000  
+76 818 43008.00 I   .249819  .012405   .262269  .010582  I  .0740805  .0006345  2.0131 0.4272  P    21.880     .500    -4.150     .300   .252000   .275000   .0741000      .000      .000  
+76 819 43009.00 I   .249988  .014321   .259157  .006985  I  .0720864  .0005554  1.9818 0.4157  P    21.641     .500    -4.205     .300   .254000   .272000   .0719000      .000      .000  
+76 820 43010.00 I   .250115  .013783   .256052  .007315  I  .0701021  .0005373  1.9951 0.3826  P    21.274     .500    -4.142     .300   .255000   .269000   .0696000      .000      .000  
+76 821 43011.00 I   .250199  .012293   .252957  .007622  I  .0680790  .0005263  2.0602 0.3761  P    21.091     .500    -4.001     .300   .256000   .266000   .0673000      .000      .000  
+76 822 43012.00 I   .250237  .011947   .249874  .007182  I  .0659637  .0005263  2.1795 0.3886  P    21.229     .500    -3.918     .300   .258000   .263000   .0649000      .000      .000  
+76 823 43013.00 I   .250226  .010096   .246806  .006520  I  .0637037  .0005719  2.3479 0.2960  P    21.531     .500    -3.972     .300   .259000   .260000   .0626000      .000      .000  
+76 824 43014.00 I   .250164  .009780   .243753  .007338  I  .0612575  .0002710  2.5476 0.3164  P    21.749     .500    -4.050     .300   .260000   .257000   .0603000      .000      .000  
+76 825 43015.00 I   .250047  .010630   .240718  .007907  I  .0586089  .0002710  2.7460 0.1916  P    21.756     .500    -3.960     .300   .261000   .254000   .0579000      .000      .000  
+76 826 43016.00 I   .249873  .014868   .237703  .007438  I  .0557798  .0002710  2.9015 0.1916  P    21.547     .500    -3.674     .300   .262000   .251000   .0555000      .000      .000  
+76 827 43017.00 I   .249635  .015702   .234708  .007157  I  .0528321  .0002710  2.9783 0.1916  P    21.178     .500    -3.375     .300   .263000   .248000   .0530000      .000      .000  
+76 828 43018.00 I   .249330  .014287   .231736  .009845  I  .0498545  .0002710  2.9610 0.1916  P    20.757     .500    -3.256     .300   .264000   .245000   .0506000      .000      .000  
+76 829 43019.00 I   .248952  .015263   .228790  .010887  I  .0469369  .0002710  2.8632 0.1916  P    20.435     .500    -3.331     .300   .265000   .242000   .0482000      .000      .000  
+76 830 43020.00 I   .248499  .013659   .225872  .013501  I  .0441424  .0002710  2.7223 0.1916  P    20.321     .500    -3.468     .300   .266000   .239000   .0456000      .000      .000  
+76 831 43021.00 I   .247962  .014938   .222984  .014621  I  .0414915  .0002710  2.5836 0.1916  P    20.414     .500    -3.565     .300   .266000   .236000   .0431000      .000      .000  
+76 9 1 43022.00 I   .247335  .014419   .220128  .012947  I  .0389619  .0002710  2.4848 0.1916  P    20.621     .500    -3.626     .300   .267000   .233000   .0405000      .000      .000  
+76 9 2 43023.00 I   .246611  .009771   .217308  .014569  I  .0365018  .0002710  2.4465 0.1916  P    20.817     .500    -3.692     .300   .267000   .230000   .0380000      .000      .000  
+76 9 3 43024.00 I   .245781  .009661   .214527  .012626  I  .0340482  .0002710  2.4705 0.1916  P    20.930     .500    -3.767     .300   .268000   .227000   .0354000      .000      .000  
+76 9 4 43025.00 I   .244837  .009943   .211786  .011600  I  .0315440  .0002710  2.5449 0.1865  P    20.991     .500    -3.811     .300   .268000   .224000   .0326000      .000      .000  
+76 9 5 43026.00 I   .243773  .012131   .209088  .010047  I  .0289484  .0002564  2.6494 0.1802  P    21.076     .500    -3.777     .300   .268000   .222000   .0299000      .000      .000  
+76 9 6 43027.00 I   .242580  .012361   .206434  .003174  I  .0262430  .0002377  2.7604 0.1748  P    21.182     .500    -3.653     .300   .267000   .219000   .0271000      .000      .000  
+76 9 7 43028.00 I   .241249  .013597   .203825  .003342  I  .0234329  .0002377  2.8554 0.1681  P    21.213     .500    -3.465     .300   .267000   .217000   .0244000      .000      .000  
+76 9 8 43029.00 I   .239773  .013644   .201263  .002271  I  .0205429  .0002377  2.9183 0.1681  P    21.109     .500    -3.267     .300   .267000   .214000   .0216000      .000      .000  
+76 9 9 43030.00 I   .238153  .013768   .198749  .002677  I  .0176095  .0002377  2.9418 0.1829  P    20.922     .500    -3.125     .300   .266000   .212000   .0186000      .000      .000  
+76 910 43031.00 I   .236405  .013977   .196285  .003042  I  .0146718  .0002781  2.9279 0.2098  P    20.716     .500    -3.095     .300   .266000   .209000   .0157000      .000      .000  
+76 911 43032.00 I   .234546  .015939   .193873  .014380  I  .0117630  .0003457  2.8860 0.2444  P    20.512     .500    -3.195     .300   .265000   .207000   .0127000      .000      .000  
+76 912 43033.00 I   .232589  .018403   .191512  .016603  I  .0089050  .0004019  2.8285 0.2651  P    20.385     .500    -3.388     .300   .265000   .204000   .0098000      .000      .000  
+76 913 43034.00 I   .230549  .017623   .189206  .016110  I  .0061070  .0004019  2.7681 0.2842  P    20.482     .500    -3.603     .300   .264000   .202000   .0068000      .000      .000  
+76 914 43035.00 I   .228436  .012796   .186953  .018473  I  .0033653  .0004019  2.7183 0.2842  P    20.795     .500    -3.791     .300   .263000   .200000   .0037000      .000      .000  
+76 915 43036.00 I   .226262  .011136   .184756  .018093  I  .0006625  .0004019  2.6923 0.2911  P    21.035     .500    -3.944     .300   .262000   .197000   .0006000      .000      .000  
+76 916 43037.00 I   .224040  .009070   .182613  .020786  I -.0020313  .0004212  2.7022 0.2424  P    20.940     .500    -4.032     .300   .262000   .195000  -.0024000      .000      .000  
+76 917 43038.00 I   .221780  .009682   .180523  .018237  I -.0047568  .0002710  2.7569 0.2504  P    20.654     .500    -3.981     .300   .261000   .192000  -.0055000      .000      .000  
+76 918 43039.00 I   .219493  .010943   .178483  .013304  I -.0075618  .0002710  2.8618 0.1916  P    20.582     .500    -3.778     .300   .260000   .190000  -.0086000      .000      .000  
+76 919 43040.00 I   .217189  .011320   .176491  .017030  I -.0104971  .0002710  3.0170 0.1916  P    20.877     .500    -3.559     .300   .259000   .187000  -.0118000      .000      .000  
+76 920 43041.00 I   .214879  .009769   .174542  .017785  I -.0136096  .0002710  3.2136 0.1916  P    21.259     .500    -3.495     .300   .258000   .185000  -.0150000      .000      .000  
+76 921 43042.00 I   .212572  .010696   .172634  .017341  I -.0169307  .0002710  3.4292 0.1916  P    21.396     .500    -3.579     .300   .257000   .182000  -.0183000      .000      .000  
+76 922 43043.00 I   .210280  .012285   .170763  .017485  I -.0204622  .0002710  3.6272 0.1916  P    21.270     .500    -3.611     .300   .256000   .180000  -.0215000      .000      .000  
+76 923 43044.00 I   .208015  .029307   .168926  .028284  I -.0241649  .0002710  3.7647 0.1916  P    21.096     .500    -3.456     .300   .255000   .177000  -.0247000      .000      .000  
+76 924 43045.00 I   .205788  .033204   .167116  .032485  I -.0279605  .0002710  3.8090 0.1916  P    21.034     .500    -3.213     .300   .254000   .175000  -.0280000      .000      .000  
+76 925 43046.00 I   .203607  .035532   .165330  .028962  I -.0317496  .0002710  3.7533 0.2476  P    21.062     .500    -3.065     .300   .252000   .172000  -.0313000      .000      .000  
+76 926 43047.00 I   .201482  .018900   .163560  .012018  I -.0354420  .0004145  3.6223 0.2476  P    21.047     .500    -3.041     .300   .251000   .170000  -.0345000      .000      .000  
+76 927 43048.00 I   .199423  .018532   .161799  .012591  I -.0389851  .0004145  3.4638 0.2931  P    20.891     .500    -3.023     .300   .249000   .167000  -.0378000      .000      .000  
+76 928 43049.00 I   .197443  .018794   .160038  .012397  I -.0423772  .0004145  3.3279 0.2931  P    20.665     .500    -2.964     .300   .248000   .165000  -.0411000      .000      .000  
+76 929 43050.00 I   .195556  .019277   .158267  .012136  I -.0456595  .0004145  3.2478 0.2541  P    20.606     .500    -2.958     .300   .246000   .163000  -.0444000      .000      .000  
+76 930 43051.00 I   .193761  .012188   .156476  .007973  I -.0488942  .0002940  3.2319 0.2541  P    20.896     .500    -3.072     .300   .245000   .161000  -.0477000      .000      .000  
+7610 1 43052.00 I   .192049  .012048   .154657  .009238  I -.0521409  .0002940  3.2687 0.1479  P    21.436     .500    -3.219     .300   .243000   .158000  -.0509000      .000      .000  
+7610 2 43053.00 I   .190412  .009765   .152802  .012088  I -.0554420  .0000331  3.3368 0.1479  P    21.930     .500    -3.253     .300   .242000   .156000  -.0542000      .000      .000  
+7610 3 43054.00 I   .188844  .009539   .150901  .013958  I -.0588172  .0000331  3.4131 0.4891  P    22.190     .500    -3.150     .300   .240000   .154000  -.0575000      .000      .000  
+7610 4 43055.00 I   .187338  .009510   .148947  .013512  I -.0622645  .0009776  3.4782 0.4891  P    22.245     .500    -2.998     .300   .238000   .152000  -.0609000      .000      .000  
+7610 5 43056.00 I   .185878  .013209   .146941  .013651  I -.0657649  .0009776  3.5171 0.7151  P    22.189     .500    -2.862     .300   .236000   .150000  -.0642000      .000      .000  
+7610 6 43057.00 I   .184444  .014620   .144886  .011245  I -.0692867  .0010440  3.5200 0.6729  P    22.062     .500    -2.722     .300   .233000   .147000  -.0676000      .000      .000  
+7610 7 43058.00 I   .183018  .014982   .142781  .011933  I -.0727925  .0009248  3.4858 0.6845  P    21.900     .500    -2.563     .300   .231000   .145000  -.0709000      .000      .000  
+7610 8 43059.00 I   .181581  .015335   .140626  .010248  I -.0762483  .0008855  3.4215 0.5864  P    21.769     .500    -2.455     .300   .229000   .143000  -.0743000      .000      .000  
+7610 9 43060.00 I   .180116  .012133   .138420  .011026  I -.0796288  .0007212  3.3370 0.4895  P    21.712     .500    -2.490     .300   .227000   .141000  -.0777000      .000      .000  
+761010 43061.00 I   .178626  .012302   .136163  .009655  I -.0829199  .0004176  3.2451 0.4167  P    21.765     .500    -2.662     .300   .224000   .139000  -.0811000      .000      .000  
+761011 43062.00 I   .177119  .012169   .133857  .009566  I -.0861213  .0004176  3.1599 0.2917  P    21.997     .500    -2.862     .300   .222000   .137000  -.0846000      .000      .000  
+761012 43063.00 I   .175602  .008273   .131502  .012266  I -.0892462  .0004073  3.0942 0.2998  P    22.391     .500    -2.999     .300   .219000   .135000  -.0880000      .000      .000  
+761013 43064.00 I   .174075  .008049   .129107  .013162  I -.0923197  .0004302  3.0585 0.2558  P    22.727     .500    -3.081     .300   .217000   .133000  -.0914000      .000      .000  
+761014 43065.00 I   .172531  .006712   .126686  .012604  I -.0953760  .0003097  3.0613 0.2580  P    22.777     .500    -3.141     .300   .214000   .131000  -.0948000      .000      .000  
+761015 43066.00 I   .170964  .003370   .124257  .008581  I -.0984571  .0002851  3.1086 0.2105  P    22.640     .500    -3.124     .300   .212000   .129000  -.0982000      .000      .000  
+761016 43067.00 I   .169366  .003350   .121837  .008654  I -.1016087  .0002851  3.2025 0.2016  P    22.677     .500    -2.955     .300   .209000   .128000  -.1017000      .000      .000  
+761017 43068.00 I   .167730  .005942   .119440  .008450  I -.1048764  .0002851  3.3393 0.2016  P    23.050     .500    -2.691     .300   .207000   .126000  -.1051000      .000      .000  
+761018 43069.00 I   .166052  .005904   .117081  .008576  I -.1082973  .0002851  3.5062 0.2016  P    23.493     .500    -2.506     .300   .204000   .124000  -.1085000      .000      .000  
+761019 43070.00 I   .164323  .007678   .114771  .008591  I -.1118907  .0002851  3.6790 0.2016  P    23.650     .500    -2.486     .300   .201000   .122000  -.1119000      .000      .000  
+761020 43071.00 I   .162540  .007891   .112517  .006782  I -.1156453  .0002851  3.8219 0.1967  P    23.501     .500    -2.509     .300   .198000   .121000  -.1153000      .000      .000  
+761021 43072.00 I   .160699  .020995   .110324  .007254  I -.1195118  .0002710  3.8967 0.2557  P    23.339     .500    -2.429     .300   .196000   .119000  -.1188000      .000      .000  
+761022 43073.00 I   .158798  .009683   .108199  .012443  I -.1234077  .0004246  3.8784 0.2519  P    23.443     .500    -2.279     .300   .193000   .118000  -.1222000      .000      .000  
+761023 43074.00 I   .156836  .009738   .106147  .013048  I -.1272383  .0004246  3.7691 0.3002  P    23.824     .500    -2.196     .300   .190000   .116000  -.1256000      .000      .000  
+761024 43075.00 I   .154807  .008609   .104176  .013369  I -.1309265  .0004246  3.6016 0.3002  P    24.216     .500    -2.181     .300   .187000   .114000  -.1290000      .000      .000  
+761025 43076.00 I   .152708  .008552   .102291  .013094  I -.1344389  .0004246  3.4264 0.3002  P    24.282     .500    -2.095     .300   .184000   .113000  -.1324000      .000      .000  
+761026 43077.00 I   .150532  .007060   .100493  .013272  I -.1377922  .0004246  3.2899 0.3822  P    23.954     .500    -1.914     .300   .181000   .111000  -.1358000      .000      .000  
+761027 43078.00 I   .148275  .006551   .098774  .010333  I -.1410399  .0006357  3.2169 0.4495  P    23.600     .500    -1.829     .300   .178000   .110000  -.1392000      .000      .000  
+761028 43079.00 I   .145933  .006382   .097124  .007214  I -.1442462  .0007924  3.2046 0.4807  P    23.695     .500    -1.992     .300   .175000   .108000  -.1426000      .000      .000  
+761029 43080.00 I   .143504  .005654   .095532  .007883  I -.1474621  .0007213  3.2313 0.5358  P    24.277     .500    -2.275     .300   .172000   .106000  -.1459000      .000      .000  
+761030 43081.00 I   .140986  .005425   .093990  .007130  I -.1507129  .0007213  3.2704 0.5100  P    24.901     .500    -2.404     .300   .169000   .104000  -.1492000      .000      .000  
+761031 43082.00 I   .138378  .005348   .092491  .007074  I -.1540004  .0007213  3.3022 0.5100  P    25.164     .500    -2.280     .300   .165000   .103000  -.1526000      .000      .000  
+7611 1 43083.00 I   .135685  .005270   .091033  .007118  I -.1573108  .0007213  3.3147 0.4368  P    25.097     .500    -2.055     .300   .162000   .101000  -.1559000      .000      .000  
+7611 2 43084.00 I   .132909  .004707   .089609  .007308  I -.1606205  .0004930  3.2995 0.4354  P    24.967     .500    -1.893     .300   .159000   .099000  -.1592000      .000      .000  
+7611 3 43085.00 I   .130046  .003837   .088210  .007363  I -.1638992  .0004879  3.2527 0.2975  P    24.889     .500    -1.793     .300   .156000   .097000  -.1624000      .000      .000  
+7611 4 43086.00 I   .127091  .002721   .086820  .008642  I -.1671159  .0003330  3.1761 0.3158  P    24.821     .500    -1.676     .300   .152000   .096000  -.1656000      .000      .000  
+7611 5 43087.00 I   .124040  .008496   .085427  .009488  I -.1702435  .0004012  3.0760 0.2607  P    24.763     .500    -1.551     .300   .149000   .094000  -.1687000      .000      .000  
+7611 6 43088.00 I   .120887  .008986   .084023  .010297  I -.1732639  .0004012  2.9639 0.2837  P    24.785     .500    -1.504     .300   .145000   .093000  -.1719000      .000      .000  
+7611 7 43089.00 I   .117629  .009121   .082602  .010409  I -.1761719  .0004012  2.8536 0.2728  P    24.913     .500    -1.554     .300   .142000   .091000  -.1751000      .000      .000  
+7611 8 43090.00 I   .114259  .010208   .081160  .010291  I -.1789766  .0003698  2.7597 0.2663  P    25.125     .500    -1.616     .300   .139000   .090000  -.1782000      .000      .000  
+7611 9 43091.00 I   .110789  .010174   .079701  .010405  I -.1817006  .0003503  2.6938 0.2579  P    25.391     .500    -1.620     .300   .135000   .088000  -.1813000      .000      .000  
+761110 43092.00 I   .107237  .010159   .078236  .010538  I -.1843763  .0003596  2.6642 0.2061  P    25.640     .500    -1.606     .300   .132000   .087000  -.1843000      .000      .000  
+761111 43093.00 I   .103622  .008311   .076775  .008726  I -.1870431  .0002171  2.6768 0.2100  P    25.763     .500    -1.642     .300   .128000   .085000  -.1874000      .000      .000  
+761112 43094.00 I   .099976  .008401   .075327  .009751  I -.1897447  .0002171  2.7336 0.1535  P    25.770     .500    -1.696     .300   .125000   .084000  -.1905000      .000      .000  
+761113 43095.00 I   .096332  .007855   .073900  .008875  I -.1925243  .0002171  2.8322 0.4672  P    25.843     .500    -1.655     .300   .122000   .083000  -.1935000      .000      .000  
+761114 43096.00 I   .092723  .014996   .072502  .010644  I -.1954200  .0009088  2.9635 0.4672  P    26.113     .500    -1.472     .300   .118000   .081000  -.1965000      .000      .000  
+761115 43097.00 I   .089176  .015215   .071137  .010295  I -.1984565  .0009088  3.1102 0.6426  P    26.458     .500    -1.241     .300   .115000   .080000  -.1995000      .000      .000  
+761116 43098.00 I   .085713  .015082   .069805  .010457  I -.2016370  .0009088  3.2465 0.6716  P    26.637     .500    -1.063     .300   .111000   .078000  -.2025000      .000      .000  
+761117 43099.00 I   .082352  .014765   .068506  .008835  I -.2049362  .0009891  3.3429 0.6716  P    26.571     .500     -.922     .300   .108000   .077000  -.2055000      .000      .000  
+761118 43100.00 I   .079093  .015244   .067245  .010547  I -.2083012  .0009891  3.3745 0.6994  P    26.419     .500     -.764     .300   .105000   .076000  -.2085000      .000      .000  
+761119 43101.00 I   .075922  .015359   .066036  .009630  I -.2116598  .0009891  3.3297 0.5968  P    26.418     .500     -.646     .300   .101000   .075000  -.2115000      .000      .000  
+761120 43102.00 I   .072820  .007022   .064892  .011208  I -.2149386  .0006682  3.2187 0.5968  P    26.677     .500     -.685     .300   .098000   .073000  -.2145000      .000      .000  
+761121 43103.00 I   .069783  .006899   .063821  .011310  I -.2180867  .0006682  3.0762 0.4313  P    27.070     .500     -.844     .300   .094000   .072000  -.2175000      .000      .000  
+761122 43104.00 I   .066805  .005955   .062834  .009785  I -.2210963  .0005456  2.9497 0.4169  P    27.292     .500     -.914     .300   .091000   .071000  -.2205000      .000      .000  
+761123 43105.00 I   .063885  .005695   .061943  .011439  I -.2240040  .0004988  2.8768 0.3696  P    27.163     .500     -.789     .300   .088000   .070000  -.2235000      .000      .000  
+761124 43106.00 I   .061019  .005783   .061152  .012820  I -.2268716  .0004988  2.8689 0.3527  P    26.907     .500     -.636     .300   .084000   .070000  -.2265000      .000      .000  
+761125 43107.00 I   .058197  .003590   .060458  .011516  I -.2297588  .0004988  2.9118 0.2713  P    26.960     .500     -.697     .300   .081000   .069000  -.2294000      .000      .000  
+761126 43108.00 I   .055414  .006921   .059859  .008629  I -.2327027  .0002136  2.9770 0.2713  P    27.420     .500     -.954     .300   .077000   .069000  -.2324000      .000      .000  
+761127 43109.00 I   .052661  .006979   .059348  .007629  I -.2357106  .0002136  3.0356 0.1849  P    27.886     .500    -1.144     .300   .074000   .068000  -.2354000      .000      .000  
+761128 43110.00 I   .049933  .010931   .058916  .010545  I -.2387657  .0003018  3.0698 0.1511  P    27.954     .500    -1.089     .300   .071000   .068000  -.2384000      .000      .000  
+761129 43111.00 I   .047221  .008194   .058557  .008893  I -.2418399  .0002137  3.0733 0.1849  P    27.696     .500     -.881     .300   .068000   .067000  -.2414000      .000      .000  
+761130 43112.00 I   .044512  .008211   .058263  .010860  I -.2449021  .0002137  3.0462 0.1560  P    27.472     .500     -.710     .300   .064000   .067000  -.2444000      .000      .000  
+7612 1 43113.00 I   .041779  .009528   .058026  .007925  I -.2479232  .0002273  2.9918 0.1393  P    27.432     .500     -.632     .300   .061000   .066000  -.2474000      .000      .000  
+7612 2 43114.00 I   .038999  .009757   .057837  .009928  I -.2508785  .0001788  2.9156 0.1446  P    27.453     .500     -.578     .300   .058000   .066000  -.2504000      .000      .000  
+7612 3 43115.00 I   .036147  .009663   .057695  .009980  I -.2537501  .0001788  2.8264 0.1264  P    27.450     .500     -.507     .300   .054000   .066000  -.2534000      .000      .000  
+7612 4 43116.00 I   .033197  .009538   .057603  .010269  I -.2565310  .0001788  2.7365 0.1775  P    27.491     .500     -.453     .300   .051000   .066000  -.2564000      .000      .000  
+7612 5 43117.00 I   .030129  .012103   .057561  .009428  I -.2592275  .0003067  2.6600 0.1775  P    27.602     .500     -.428     .300   .047000   .066000  -.2595000      .000      .000  
+7612 6 43118.00 I   .026940  .012277   .057570  .010037  I -.2618595  .0003067  2.6090 0.2337  P    27.705     .500     -.394     .300   .044000   .066000  -.2625000      .000      .000  
+7612 7 43119.00 I   .023629  .012729   .057629  .009892  I -.2644568  .0003528  2.5918 0.2178  P    27.768     .500     -.342     .300   .040000   .066000  -.2655000      .000      .000  
+7612 8 43120.00 I   .020197  .010318   .057738  .007337  I -.2670559  .0003092  2.6129 0.2346  P    27.862     .500     -.330     .300   .036000   .066000  -.2685000      .000      .000  
+7612 9 43121.00 I   .016660  .010332   .057894  .006445  I -.2696957  .0003092  2.6731 0.2186  P    28.020     .500     -.410     .300   .033000   .066000  -.2715000      .000      .000  
+761210 43122.00 I   .013042  .010437   .058091  .006756  I -.2724142  .0003092  2.7694 0.1936  P    28.177     .500     -.537     .300   .029000   .066000  -.2745000      .000      .000  
+761211 43123.00 I   .009367  .009044   .058325  .006742  I -.2752438  .0002330  2.8934 0.1936  P    28.281     .500     -.597     .300   .026000   .066000  -.2775000      .000      .000  
+761212 43124.00 I   .005650  .008907   .058591  .007972  I -.2782053  .0002330  3.0302 0.1648  P    28.363     .500     -.511     .300   .022000   .066000  -.2805000      .000      .000  
+761213 43125.00 I   .001900  .008537   .058889  .007119  I -.2813018  .0002330  3.1596 0.1549  P    28.457     .500     -.303     .300   .018000   .066000  -.2834000      .000      .000  
+761214 43126.00 I  -.001873  .011472   .059217  .009787  I -.2845144  .0002043  3.2585 0.1402  P    28.527     .500     -.040     .300   .015000   .066000  -.2864000      .000      .000  
+761215 43127.00 I  -.005671  .008470   .059580  .008588  I -.2878015  .0001561  3.3053 0.1286  P    28.505     .500      .238     .300   .011000   .067000  -.2893000      .000      .000  
+761216 43128.00 I  -.009501  .008367   .059986  .008573  I -.2911032  .0001561  3.2867 0.0886  P    28.376     .500      .488     .300   .008000   .067000  -.2923000      .000      .000  
+761217 43129.00 I  -.013371  .006129   .060446  .009323  I -.2943538  .0000838  3.2049 0.0886  P    28.200     .500      .605     .300   .004000   .067000  -.2952000      .000      .000  
+761218 43130.00 I  -.017289  .006035   .060970  .009173  I -.2974989  .0000838  3.0808 0.0593  P    28.088     .500      .475     .300   .000000   .067000  -.2981000      .000      .000  
+761219 43131.00 I  -.021259  .006203   .061568  .007193  I -.3005132  .0000838  2.9502 0.2498  P    28.099     .500      .143     .300  -.003000   .068000  -.3010000      .000      .000  
+761220 43132.00 I  -.025285  .004932   .062241  .005312  I -.3034101  .0004926  2.8521 0.3483  P    28.163     .500     -.144     .300  -.007000   .068000  -.3038000      .000      .000  
+761221 43133.00 I  -.029368  .003025   .062994  .002563  I -.3062365  .0006916  2.8114 0.4245  P    28.178     .500     -.162     .300  -.010000   .069000  -.3067000      .000      .000  
+761222 43134.00 I  -.033512  .005234   .063830  .004679  I -.3090520  .0006916  2.8281 0.4890  P    28.196     .500      .045     .300  -.014000   .069000  -.3096000      .000      .000  
+761223 43135.00 I  -.037719  .005306   .064751  .004444  I -.3119048  .0006916  2.8811 0.4573  P    28.399     .500      .220     .300  -.018000   .070000  -.3124000      .000      .000  
+761224 43136.00 I  -.041989  .006582   .065763  .009015  I -.3148158  .0005986  2.9390 0.4573  P    28.792     .500      .197     .300  -.021000   .070000  -.3153000      .000      .000  
+761225 43137.00 I  -.046322  .006645   .066870  .009093  I -.3177753  .0005986  2.9745 0.3862  P    29.086     .500      .057     .300  -.025000   .071000  -.3181000      .000      .000  
+761226 43138.00 I  -.050717  .008696   .068076  .012141  I -.3207530  .0004882  2.9745 0.3862  P    29.013     .500     -.023     .300  -.028000   .071000  -.3210000      .000      .000  
+761227 43139.00 I  -.055176  .008729   .069388  .012427  I -.3237125  .0004882  2.9390 0.3452  P    28.672     .500      .007     .300  -.032000   .072000  -.3238000      .000      .000  
+761228 43140.00 I  -.059698  .011773   .070808  .012281  I -.3266212  .0004882  2.8741 0.3452  P    28.384     .500      .065     .300  -.035000   .073000  -.3265000      .000      .000  
+761229 43141.00 I  -.064273  .011254   .072331  .011917  I -.3294534  .0004882  2.7873 0.2792  P    28.294     .500      .083     .300  -.039000   .074000  -.3293000      .000      .000  
+761230 43142.00 I  -.068888  .020907   .073951  .015322  I -.3321916  .0002710  2.6878 0.2792  P    28.296     .500      .066     .300  -.042000   .074000  -.3320000      .000      .000  
+761231 43143.00 I  -.073529  .020756   .075660  .007038  I -.3348284  .0002710  2.5865 0.1916  P    28.308     .500      .040     .300  -.046000   .075000  -.3348000      .000      .000  
+77 1 1 43144.00 I  -.078182  .020756   .077451  .007038  I  .6626318  .0002710  2.4961 0.1916  P    28.381     .500      .022     .300  -.049000   .076000   .6625000      .000      .000  
+77 1 2 43145.00 I  -.082831  .024669   .079316  .005364  I  .6601714  .0002710  2.4297 0.1916  P    28.520     .500      .028     .300  -.052000   .077000   .6597000      .000      .000  
+77 1 3 43146.00 I  -.087456  .026664   .081248  .004964  I  .6577609  .0002710  2.3977 0.1916  P    28.608     .500      .065     .300  -.056000   .079000   .6569000      .000      .000  
+77 1 4 43147.00 I  -.092040  .023122   .083241  .002516  I  .6553626  .0002710  2.4058 0.1916  P    28.591     .500      .088     .300  -.059000   .080000   .6542000      .000      .000  
+77 1 5 43148.00 I  -.096564  .021201   .085288  .007954  I  .6529353  .0002710  2.4559 0.1916  P    28.606     .500      .025     .300  -.063000   .082000   .6514000      .000      .000  
+77 1 6 43149.00 I  -.101010  .021201   .087382  .007954  I  .6504376  .0002710  2.5457 0.1916  P    28.788     .500     -.122     .300  -.066000   .083000   .6486000      .000      .000  
+77 1 7 43150.00 I  -.105357  .021200   .089515  .017413  I  .6478336  .0002710  2.6665 0.1916  P    29.069     .500     -.260     .300  -.069000   .085000   .6458000      .000      .000  
+77 1 8 43151.00 I  -.109588  .021200   .091680  .017413  I  .6450997  .0002710  2.8020 0.1916  P    29.249     .500     -.289     .300  -.073000   .087000   .6430000      .000      .000  
+77 1 9 43152.00 I  -.113685  .022765   .093870  .021309  I  .6422322  .0002710  2.9297 0.1358  P    29.230     .500     -.188     .300  -.076000   .088000   .6403000      .000      .000  
+77 110 43153.00 I  -.117633  .019540   .096076  .012970  I  .6392508  .0000175  3.0258 0.1358  P    29.088     .500     -.007     .300  -.080000   .090000   .6375000      .000      .000  
+77 111 43154.00 I  -.121416  .021251   .098289  .012654  I  .6361975  .0000175  3.0710 0.0124  P    28.954     .500      .201     .300  -.083000   .092000   .6347000      .000      .000  
+77 112 43155.00 I  -.125019  .021592   .100498  .012505  I  .6331285  .0000175  3.0571 0.0124  P    28.867     .500      .410     .300  -.086000   .094000   .6319000      .000      .000  
+77 113 43156.00 I  -.128428  .022678   .102693  .012348  I  .6301016  .0000175  2.9885 0.0124  P    28.767     .500      .582     .300  -.090000   .096000   .6291000      .000      .000  
+77 114 43157.00 I  -.131651  .023308   .104872  .010561  I  .6271638  .0000175  2.8831 0.0124  P    28.577     .500      .633     .300  -.093000   .098000   .6264000      .000      .000  
+77 115 43158.00 I  -.134713  .022823   .107036  .013000  I  .6243384  .0000175  2.7688 0.1358  P    28.301     .500      .473     .300  -.097000   .100000   .6236000      .000      .000  
+77 116 43159.00 I  -.137636  .032519   .109191  .021442  I  .6216184  .0002710  2.6778 0.1358  P    28.032     .500      .121     .300  -.100000   .102000   .6208000      .000      .000  
+77 117 43160.00 I  -.140438  .029047   .111338  .028518  I  .6189663  .0002710  2.6363 0.1916  P    27.867     .500     -.236     .300  -.103000   .104000   .6180000      .000      .000  
+77 118 43161.00 I  -.143137  .023743   .113481  .032929  I  .6163259  .0002710  2.6544 0.1866  P    27.845     .500     -.354     .300  -.106000   .107000   .6152000      .000      .000  
+77 119 43162.00 I  -.145749  .011772   .115623  .014238  I  .6136413  .0002567  2.7210 0.1866  P    27.959     .500     -.157     .300  -.110000   .109000   .6125000      .000      .000  
+77 120 43163.00 I  -.148288  .008320   .117769  .014462  I  .6108770  .0002567  2.8081 0.1815  P    28.187     .500      .173     .300  -.113000   .112000   .6097000      .000      .000  
+77 121 43164.00 I  -.150769  .009529   .119923  .014441  I  .6080291  .0002567  2.8830 0.1815  P    28.445     .500      .361     .300  -.116000   .114000   .6069000      .000      .000  
+77 122 43165.00 I  -.153209  .009424   .122089  .012373  I  .6051233  .0002567  2.9210 0.1815  P    28.582     .500      .293     .300  -.119000   .117000   .6042000      .000      .000  
+77 123 43166.00 I  -.155619  .013496   .124269  .013654  I  .6022025  .0002567  2.9129 0.1815  P    28.498     .500      .069     .300  -.122000   .120000   .6015000      .000      .000  
+77 124 43167.00 I  -.158001  .013453   .126466  .010047  I  .5993115  .0002567  2.8629 0.1866  P    28.252     .500     -.145     .300  -.126000   .122000   .5987000      .000      .000  
+77 125 43168.00 I  -.160358  .024519   .128681  .025391  I  .5964868  .0002710  2.7825 0.1866  P    27.995     .500     -.276     .300  -.129000   .125000   .5960000      .000      .000  
+77 126 43169.00 I  -.162693  .027971   .130919  .023779  I  .5937527  .0002710  2.6836 0.1916  P    27.810     .500     -.353     .300  -.132000   .128000   .5933000      .000      .000  
+77 127 43170.00 I  -.165008  .024230   .133184  .028017  I  .5911218  .0002710  2.5782 0.3047  P    27.702     .500     -.435     .300  -.135000   .131000   .5906000      .000      .000  
+77 128 43171.00 I  -.167302  .011592   .135480  .012220  I  .5885942  .0005459  2.4791 0.3047  P    27.693     .500     -.542     .300  -.138000   .134000   .5879000      .000      .000  
+77 129 43172.00 I  -.169575  .011391   .137814  .012965  I  .5861572  .0005459  2.3992 0.3623  P    27.829     .500     -.641     .300  -.142000   .137000   .5853000      .000      .000  
+77 130 43173.00 I  -.171822  .005783   .140189  .011568  I  .5837852  .0004765  2.3510 0.3623  P    28.064     .500     -.672     .300  -.145000   .140000   .5826000      .000      .000  
+77 131 43174.00 I  -.174043  .008497   .142610  .012645  I  .5814415  .0004765  2.3440 0.3369  P    28.252     .500     -.625     .300  -.148000   .143000   .5799000      .000      .000  
+77 2 1 43175.00 I  -.176244  .008584   .145082  .011611  I  .5790819  .0004765  2.3831 0.3369  P    28.313     .500     -.591     .300  -.151000   .146000   .5773000      .000      .000  
+77 2 2 43176.00 I  -.178434  .009857   .147612  .013004  I  .5766600  .0004765  2.4681 0.2700  P    28.338     .500     -.679     .300  -.154000   .149000   .5746000      .000      .000  
+77 2 3 43177.00 I  -.180620  .020941   .150203  .026200  I  .5741326  .0002541  2.5925 0.2700  P    28.479     .500     -.874     .300  -.157000   .153000   .5720000      .000      .000  
+77 2 4 43178.00 I  -.182809  .018695   .152861  .023468  I  .5714666  .0002541  2.7421 0.1601  P    28.750     .500    -1.022     .300  -.160000   .156000   .5693000      .000      .000  
+77 2 5 43179.00 I  -.185006  .010647   .155592  .013575  I  .5686478  .0001950  2.8934 0.1601  P    28.993     .500     -.992     .300  -.163000   .159000   .5667000      .000      .000  
+77 2 6 43180.00 I  -.187216  .010921   .158401  .014592  I  .5656889  .0001950  3.0173 0.1307  P    29.049     .500     -.811     .300  -.166000   .162000   .5641000      .000      .000  
+77 2 7 43181.00 I  -.189444  .009120   .161298  .013766  I  .5626312  .0001741  3.0872 0.1307  P    28.902     .500     -.629     .300  -.169000   .166000   .5614000      .000      .000  
+77 2 8 43182.00 I  -.191697  .008975   .164290  .013470  I  .5595370  .0001741  3.0894 0.1231  P    28.679     .500     -.551     .300  -.172000   .169000   .5588000      .000      .000  
+77 2 9 43183.00 I  -.193973  .007492   .167373  .012156  I  .5564734  .0001741  3.0285 0.1231  P    28.516     .500     -.575     .300  -.175000   .173000   .5561000      .000      .000  
+77 210 43184.00 I  -.196266  .007294   .170544  .011866  I  .5534939  .0001741  2.9260 0.1036  P    28.433     .500     -.641     .300  -.178000   .176000   .5535000      .000      .000  
+77 211 43185.00 I  -.198571  .009297   .173796  .016363  I  .5506249  .0001125  2.8130 0.2395  P    28.350     .500     -.730     .300  -.181000   .180000   .5509000      .000      .000  
+77 212 43186.00 I  -.200881  .007912   .177122  .006975  I  .5478609  .0004462  2.7210 0.2708  P    28.185     .500     -.876     .300  -.184000   .183000   .5482000      .000      .000  
+77 213 43187.00 I  -.203191  .007313   .180515  .003420  I  .5451674  .0005297  2.6754 0.3463  P    27.964     .500    -1.107     .300  -.186000   .187000   .5456000      .000      .000  
+77 214 43188.00 I  -.205494  .010447   .183966  .003672  I  .5424907  .0005297  2.6880 0.3746  P    27.807     .500    -1.365     .300  -.189000   .190000   .5429000      .000      .000  
+77 215 43189.00 I  -.207785  .010649   .187470  .003611  I  .5397734  .0005297  2.7545 0.3746  P    27.820     .500    -1.502     .300  -.192000   .194000   .5403000      .000      .000  
+77 216 43190.00 I  -.210053  .012242   .191017  .003705  I  .5369705  .0005297  2.8545 0.3746  P    27.986     .500    -1.407     .300  -.194000   .198000   .5376000      .000      .000  
+77 217 43191.00 I  -.212281  .012580   .194602  .003778  I  .5340632  .0005297  2.9582 0.2975  P    28.176     .500    -1.146     .300  -.197000   .201000   .5349000      .000      .000  
+77 218 43192.00 I  -.214452  .025281   .198216  .009410  I  .5310624  .0002710  3.0370 0.2975  P    28.270     .500     -.943     .300  -.199000   .205000   .5322000      .000      .000  
+77 219 43193.00 I  -.216553  .025418   .201853  .007189  I  .5280040  .0002710  3.0714 0.1916  P    28.258     .500     -.986     .300  -.202000   .208000   .5295000      .000      .000  
+77 220 43194.00 I  -.218572  .024741   .205506  .006873  I  .5249359  .0002710  3.0568 0.1916  P    28.206     .500    -1.260     .300  -.204000   .212000   .5268000      .000      .000  
+77 221 43195.00 I  -.220498  .021266   .209170  .006837  I  .5219041  .0002710  3.0009 0.1916  P    28.145     .500    -1.593     .300  -.206000   .216000   .5240000      .000      .000  
+77 222 43196.00 I  -.222323  .019259   .212838  .009589  I  .5189433  .0002710  2.9172 0.1916  P    28.031     .500    -1.837     .300  -.208000   .219000   .5212000      .000      .000  
+77 223 43197.00 I  -.224035  .015166   .216503  .010653  I  .5160743  .0002710  2.8197 0.1916  P    27.853     .500    -1.978     .300  -.210000   .223000   .5185000      .000      .000  
+77 224 43198.00 I  -.225626  .013190   .220158  .027018  I  .5133038  .0002710  2.7224 0.2912  P    27.705     .500    -2.092     .300  -.212000   .226000   .5157000      .000      .000  
+77 225 43199.00 I  -.227088  .009991   .223796  .013388  I  .5106251  .0005156  2.6382 0.2912  P    27.713     .500    -2.234     .300  -.214000   .230000   .5129000      .000      .000  
+77 226 43200.00 I  -.228413  .010191   .227410  .013740  I  .5080187  .0005156  2.5801 0.3401  P    27.903     .500    -2.371     .300  -.216000   .234000   .5100000      .000      .000  
+77 227 43201.00 I  -.229592  .008990   .230994  .014023  I  .5054527  .0004438  2.5586 0.3401  P    28.188     .500    -2.407     .300  -.217000   .237000   .5071000      .000      .000  
+77 228 43202.00 I  -.230618  .008921   .234542  .015210  I  .5028868  .0004438  2.5812 0.3138  P    28.465     .500    -2.296     .300  -.219000   .241000   .5041000      .000      .000  
+77 3 1 43203.00 I  -.231493  .008770   .238056  .015216  I  .5002744  .0004438  2.6514 0.3138  P    28.675     .500    -2.144     .300  -.220000   .244000   .5012000      .000      .000  
+77 3 2 43204.00 I  -.232225  .009383   .241545  .014921  I  .4975693  .0004438  2.7658 0.2430  P    28.796     .500    -2.137     .300  -.222000   .248000   .4983000      .000      .000  
+77 3 3 43205.00 I  -.232824  .013131   .245014  .021137  I  .4947312  .0001982  2.9150 0.2430  P    28.857     .500    -2.334     .300  -.223000   .252000   .4954000      .000      .000  
+77 3 4 43206.00 I  -.233299  .014034   .248473  .018665  I  .4917340  .0001982  3.0799 0.1679  P    28.937     .500    -2.567     .300  -.224000   .256000   .4925000      .000      .000  
+77 3 5 43207.00 I  -.233660  .014292   .251931  .018405  I  .4885759  .0002710  3.2312 0.1679  P    29.093     .500    -2.604     .300  -.226000   .259000   .4895000      .000      .000  
+77 3 6 43208.00 I  -.233915  .012379   .255398  .016966  I  .4852872  .0002710  3.3356 0.1916  P    29.261     .500    -2.412     .300  -.227000   .263000   .4866000      .000      .000  
+77 3 7 43209.00 I  -.234077  .013604   .258884  .008857  I  .4819292  .0002710  3.3666 0.1916  P    29.307     .500    -2.195     .300  -.228000   .267000   .4837000      .000      .000  
+77 3 8 43210.00 I  -.234156  .016745   .262400  .007705  I  .4785808  .0002710  3.3173 0.2889  P    29.187     .500    -2.172     .300  -.229000   .271000   .4807000      .000      .000  
+77 3 9 43211.00 I  -.234164  .007237   .265954  .012964  I  .4753155  .0005102  3.2052 0.2889  P    29.005     .500    -2.365     .300  -.230000   .275000   .4777000      .000      .000  
+77 310 43212.00 I  -.234116  .007071   .269558  .013246  I  .4721797  .0005102  3.0652 0.3608  P    28.887     .500    -2.630     .300  -.231000   .278000   .4748000      .000      .000  
+77 311 43213.00 I  -.234025  .006124   .273222  .013477  I  .4691810  .0005102  2.9373 0.3608  P    28.848     .500    -2.826     .300  -.232000   .282000   .4718000      .000      .000  
+77 312 43214.00 I  -.233903  .009348   .276956  .013689  I  .4662904  .0005102  2.8533 0.3125  P    28.811     .500    -2.931     .300  -.233000   .286000   .4688000      .000      .000  
+77 313 43215.00 I  -.233757  .010982   .280757  .010289  I  .4634546  .0003610  2.8287 0.3125  P    28.743     .500    -3.005     .300  -.234000   .290000   .4658000      .000      .000  
+77 314 43216.00 I  -.233593  .010816   .284619  .010199  I  .4606137  .0003610  2.8620 0.1808  P    28.716     .500    -3.095     .300  -.235000   .294000   .4627000      .000      .000  
+77 315 43217.00 I  -.233417  .013554   .288535  .006243  I  .4577165  .0000194  2.9377 0.1808  P    28.835     .500    -3.172     .300  -.235000   .297000   .4597000      .000      .000  
+77 316 43218.00 I  -.233234  .013247   .292501  .006631  I  .4547318  .0000194  3.0329 0.0137  P    29.092     .500    -3.168     .300  -.236000   .301000   .4566000      .000      .000  
+77 317 43219.00 I  -.233050  .013600   .296512  .005470  I  .4516527  .0000194  3.1221 0.3554  P    29.335     .500    -3.069     .300  -.237000   .305000   .4536000      .000      .000  
+77 318 43220.00 I  -.232852  .013934   .300562  .009396  I  .4484970  .0007106  3.1831 0.5025  P    29.406     .500    -2.961     .300  -.237000   .309000   .4505000      .000      .000  
+77 319 43221.00 I  -.232628  .011358   .304642  .012115  I  .4453000  .0010048  3.2037 0.6153  P    29.323     .500    -2.962     .300  -.237000   .313000   .4474000      .000      .000  
+77 320 43222.00 I  -.232363  .010448   .308747  .012000  I  .4421034  .0010048  3.1831 0.7105  P    29.246     .500    -3.111     .300  -.238000   .316000   .4444000      .000      .000  
+77 321 43223.00 I  -.232043  .012063   .312871  .012224  I  .4389447  .0010048  3.1300 0.7105  P    29.252     .500    -3.341     .300  -.238000   .320000   .4413000      .000      .000  
+77 322 43224.00 I  -.231654  .010611   .317004  .012224  I  .4358503  .0010048  3.0564 0.7105  P    29.254     .500    -3.559     .300  -.238000   .324000   .4382000      .000      .000  
+77 323 43225.00 I  -.231184  .011834   .321135  .012239  I  .4328343  .0010048  2.9756 0.5204  P    29.177     .500    -3.724     .300  -.238000   .328000   .4350000      .000      .000  
+77 324 43226.00 I  -.230620  .020829   .325247  .029484  I  .4298967  .0002710  2.9018 0.5204  P    29.111     .500    -3.862     .300  -.238000   .332000   .4319000      .000      .000  
+77 325 43227.00 I  -.229953  .021438   .329327  .007713  I  .4270241  .0002710  2.8476 0.3225  P    29.180     .500    -4.007     .300  -.237000   .335000   .4287000      .000      .000  
+77 326 43228.00 I  -.229171  .010363   .333361  .013201  I  .4241914  .0005852  2.8237 0.3073  P    29.347     .500    -4.144     .300  -.237000   .339000   .4256000      .000      .000  
+77 327 43229.00 I  -.228262  .010520   .337335  .013372  I  .4213638  .0005517  2.8385 0.4021  P    29.515     .500    -4.188     .300  -.237000   .343000   .4224000      .000      .000  
+77 328 43230.00 I  -.227216  .011487   .341235  .014594  I  .4184999  .0005517  2.8967 0.3901  P    29.708     .500    -4.053     .300  -.237000   .347000   .4192000      .000      .000  
+77 329 43231.00 I  -.226025  .011775   .345047  .014594  I  .4155560  .0005517  2.9981 0.3901  P    30.002     .500    -3.795     .300  -.236000   .351000   .4160000      .000      .000  
+77 330 43232.00 I  -.224684  .011524   .348760  .014261  I  .4124907  .0005517  3.1386 0.3901  P    30.295     .500    -3.633     .300  -.236000   .354000   .4129000      .000      .000  
+77 331 43233.00 I  -.223197  .008112   .352373  .014566  I  .4092696  .0005517  3.3068 0.3611  P    30.373     .500    -3.746     .300  -.235000   .358000   .4097000      .000      .000  
+77 4 1 43234.00 I  -.221567  .015056   .355890  .025045  I  .4058751  .0004660  3.4809 0.3073  P    30.223     .500    -4.042     .300  -.235000   .362000   .4065000      .000      .000  
+77 4 2 43235.00 I  -.219801  .013625   .359314  .017534  I  .4023164  .0002710  3.6292 0.2472  P    30.088     .500    -4.219     .300  -.234000   .365000   .4033000      .000      .000  
+77 4 3 43236.00 I  -.217905  .010485   .362650  .009604  I  .3986364  .0001649  3.7182 0.1522  P    30.143     .500    -4.103     .300  -.234000   .369000   .4000000      .000      .000  
+77 4 4 43237.00 I  -.215888  .009349   .365903  .007328  I  .3949074  .0001386  3.7249 0.2105  P    30.266     .500    -3.853     .300  -.233000   .372000   .3968000      .000      .000  
+77 4 5 43238.00 I  -.213757  .009523   .369077  .007233  I  .3912141  .0003873  3.6493 0.2057  P    30.238     .500    -3.769     .300  -.233000   .376000   .3935000      .000      .000  
+77 4 6 43239.00 I  -.211521  .009703   .372177  .007365  I  .3876271  .0003873  3.5190 0.2611  P    30.031     .500    -3.961     .300  -.232000   .379000   .3903000      .000      .000  
+77 4 7 43240.00 I  -.209204  .016548   .375211  .009990  I  .3841797  .0003502  3.3780 0.2611  P    29.805     .500    -4.268     .300  -.231000   .382000   .3870000      .000      .000  
+77 4 8 43241.00 I  -.206833  .016784   .378192  .010051  I  .3808609  .0003502  3.2677 0.2820  P    29.696     .500    -4.487     .300  -.230000   .385000   .3838000      .000      .000  
+77 4 9 43242.00 I  -.204436  .020317   .381129  .013166  I  .3776260  .0004421  3.2124 0.3223  P    29.703     .500    -4.562     .300  -.228000   .389000   .3805000      .000      .000  
+77 410 43243.00 I  -.202037  .020762   .384034  .012049  I  .3744170  .0005411  3.2144 0.2242  P    29.750     .500    -4.563     .300  -.227000   .392000   .3773000      .000      .000  
+77 411 43244.00 I  -.199634  .020225   .386910  .011755  I  .3711831  .0000743  3.2586 0.2759  P    29.790     .500    -4.552     .300  -.226000   .395000   .3740000      .000      .000  
+77 412 43245.00 I  -.197223  .015223   .389761  .009177  I  .3678933  .0001081  3.3222 0.0705  P    29.848     .500    -4.544     .300  -.224000   .398000   .3707000      .000      .000  
+77 413 43246.00 I  -.194800  .009539   .392590  .009871  I  .3645398  .0001199  3.3825 0.0807  P    29.978     .500    -4.535     .300  -.222000   .401000   .3674000      .000      .000  
+77 414 43247.00 I  -.192364  .002535   .395402  .004852  I  .3611356  .0001199  3.4210 0.0848  P    30.160     .500    -4.521     .300  -.221000   .405000   .3641000      .000      .000  
+77 415 43248.00 I  -.189909  .006708   .398198  .008110  I  .3577092  .0001199  3.4255 0.0848  P    30.269     .500    -4.491     .300  -.219000   .408000   .3608000      .000      .000  
+77 416 43249.00 I  -.187432  .006883   .400979  .007774  I  .3542975  .0001199  3.3914 0.0848  P    30.213     .500    -4.440     .300  -.217000   .411000   .3575000      .000      .000  
+77 417 43250.00 I  -.184928  .006859   .403743  .008093  I  .3509383  .0001199  3.3217 0.2928  P    30.054     .500    -4.400     .300  -.215000   .414000   .3542000      .000      .000  
+77 418 43251.00 I  -.182393  .006948   .406489  .007601  I  .3476626  .0005731  3.2266 0.2928  P    29.923     .500    -4.434     .300  -.213000   .417000   .3509000      .000      .000  
+77 419 43252.00 I  -.179824  .006793   .409217  .011127  I  .3444889  .0005731  3.1202 0.4052  P    29.860     .500    -4.576     .300  -.210000   .420000   .3476000      .000      .000  
+77 420 43253.00 I  -.177220  .006631   .411927  .011266  I  .3414210  .0005731  3.0172 0.4052  P    29.846     .500    -4.787     .300  -.208000   .423000   .3443000      .000      .000  
+77 421 43254.00 I  -.174581  .007115   .414621  .012381  I  .3384487  .0005731  2.9314 0.3698  P    29.908     .500    -4.982     .300  -.206000   .426000   .3410000      .000      .000  
+77 422 43255.00 I  -.171908  .006734   .417300  .008576  I  .3355486  .0004675  2.8745 0.3698  P    30.055     .500    -5.120     .300  -.204000   .429000   .3377000      .000      .000  
+77 423 43256.00 I  -.169202  .010042   .419965  .008512  I  .3326873  .0004675  2.8548 0.2788  P    30.160     .500    -5.222     .300  -.201000   .432000   .3345000      .000      .000  
+77 424 43257.00 I  -.166465  .013233   .422621  .010330  I  .3298248  .0003038  2.8776 0.2788  P    30.111     .500    -5.286     .300  -.199000   .435000   .3312000      .000      .000  
+77 425 43258.00 I  -.163700  .014531   .425272  .012124  I  .3269178  .0003038  2.9435 0.2148  P    30.061     .500    -5.235     .300  -.196000   .438000   .3280000      .000      .000  
+77 426 43259.00 I  -.160921  .014745   .427918  .010578  I  .3239247  .0003038  3.0489 0.2148  P    30.276     .500    -5.026     .300  -.194000   .441000   .3247000      .000      .000  
+77 427 43260.00 I  -.158151  .014698   .430559  .010746  I  .3208092  .0003038  3.1866 0.2208  P    30.714     .500    -4.790     .300  -.191000   .444000   .3215000      .000      .000  
+77 428 43261.00 I  -.155409  .013458   .433193  .009807  I  .3175457  .0003205  3.3417 0.2208  P    30.982     .500    -4.741     .300  -.189000   .446000   .3183000      .000      .000  
+77 429 43262.00 I  -.152699  .015055   .435805  .009703  I  .3141276  .0003205  3.4913 0.3197  P    30.823     .500    -4.916     .300  -.186000   .449000   .3150000      .000      .000  
+77 430 43263.00 I  -.150019  .013703   .438383  .010901  I  .3105747  .0005533  3.6059 0.3197  P    30.438     .500    -5.080     .300  -.184000   .451000   .3118000      .000      .000  
+77 5 1 43264.00 I  -.147367  .013764   .440911  .010825  I  .3069376  .0005533  3.6550 0.3912  P    30.183     .500    -5.000     .300  -.181000   .454000   .3086000      .000      .000  
+77 5 2 43265.00 I  -.144737  .011059   .443377  .008722  I  .3032920  .0005533  3.6221 0.3912  P    30.125     .500    -4.748     .300  -.178000   .457000   .3054000      .000      .000  
+77 5 3 43266.00 I  -.142125  .020285   .445774  .008722  I  .2997180  .0005533  3.5155 0.3757  P    30.058     .500    -4.613     .300  -.175000   .459000   .3022000      .000      .000  
+77 5 4 43267.00 I  -.139531  .020968   .448096  .008363  I  .2962739  .0005084  3.3701 0.3757  P    29.841     .500    -4.743     .300  -.173000   .462000   .2991000      .000      .000  
+77 5 5 43268.00 I  -.136957  .021823   .450348  .008539  I  .2929751  .0005084  3.2327 0.3003  P    29.561     .500    -4.998     .300  -.170000   .464000   .2959000      .000      .000  
+77 5 6 43269.00 I  -.134402  .020176   .452536  .004878  I  .2897933  .0003199  3.1410 0.3104  P    29.403     .500    -5.171     .300  -.167000   .467000   .2927000      .000      .000  
+77 5 7 43270.00 I  -.131868  .015461   .454667  .005910  I  .2866728  .0003562  3.1101 0.2394  P    29.463     .500    -5.225     .300  -.164000   .469000   .2896000      .000      .000  
+77 5 8 43271.00 I  -.129341  .015481   .456743  .005856  I  .2835566  .0003562  3.1288 0.2519  P    29.663     .500    -5.242     .300  -.161000   .471000   .2865000      .000      .000  
+77 5 9 43272.00 I  -.126805  .016083   .458766  .006168  I  .2804070  .0003562  3.1720 0.2688  P    29.784     .500    -5.249     .300  -.158000   .474000   .2833000      .000      .000  
+77 510 43273.00 I  -.124248  .012527   .460739  .007725  I  .2772138  .0004026  3.2116 0.2634  P    29.666     .500    -5.211     .300  -.155000   .476000   .2802000      .000      .000  
+77 511 43274.00 I  -.121648  .012635   .462667  .008167  I  .2739915  .0003881  3.2280 0.2796  P    29.409     .500    -5.147     .300  -.152000   .478000   .2771000      .000      .000  
+77 512 43275.00 I  -.118986  .011396   .464559  .007977  I  .2707687  .0003881  3.2115 0.2691  P    29.264     .500    -5.124     .300  -.149000   .480000   .2741000      .000      .000  
+77 513 43276.00 I  -.116243  .014237   .466423  .010539  I  .2675802  .0003730  3.1597 0.2691  P    29.312     .500    -5.141     .300  -.145000   .482000   .2710000      .000      .000  
+77 514 43277.00 I  -.113404  .013935   .468267  .009643  I  .2644600  .0003730  3.0757 0.2638  P    29.349     .500    -5.110     .300  -.142000   .483000   .2680000      .000      .000  
+77 515 43278.00 I  -.110466  .015815   .470091  .009597  I  .2614370  .0003730  2.9669 0.2638  P    29.175     .500    -4.999     .300  -.138000   .485000   .2649000      .000      .000  
+77 516 43279.00 I  -.107435  .014657   .471893  .009386  I  .2585308  .0003730  2.8442 0.2305  P    28.849     .500    -4.918     .300  -.135000   .487000   .2619000      .000      .000  
+77 517 43280.00 I  -.104316  .029701   .473673  .016075  I  .2557486  .0002710  2.7213 0.2305  P    28.587     .500    -5.003     .300  -.131000   .488000   .2590000      .000      .000  
+77 518 43281.00 I  -.101114  .024953   .475428  .014447  I  .2530837  .0002710  2.6117 0.1916  P    28.527     .500    -5.236     .300  -.128000   .490000   .2560000      .000      .000  
+77 519 43282.00 I  -.097835  .024953   .477158  .014447  I  .2505171  .0002710  2.5264 0.1916  P    28.662     .500    -5.456     .300  -.124000   .491000   .2531000      .000      .000  
+77 520 43283.00 I  -.094479  .035178   .478858  .008647  I  .2480201  .0002710  2.4734 0.1916  P    28.875     .500    -5.542     .300  -.121000   .493000   .2501000      .000      .000  
+77 521 43284.00 I  -.091047  .035178   .480525  .008647  I  .2455580  .0002710  2.4573 0.1916  P    28.964     .500    -5.539     .300  -.117000   .494000   .2472000      .000      .000  
+77 522 43285.00 I  -.087541  .003310   .482158  .002690  I  .2430929  .0002710  2.4792 0.1916  P    28.791     .500    -5.558     .300  -.113000   .495000   .2444000      .000      .000  
+77 523 43286.00 I  -.083960  .003310   .483754  .002690  I  .2405877  .0002710  2.5369 0.1916  P    28.503     .500    -5.599     .300  -.109000   .496000   .2416000      .000      .000  
+77 524 43287.00 I  -.080306  .003310   .485308  .002690  I  .2380093  .0002710  2.6241 0.1916  P    28.458     .500    -5.552     .300  -.105000   .497000   .2388000      .000      .000  
+77 525 43288.00 I  -.076579  .003310   .486820  .002690  I  .2353333  .0002710  2.7299 0.1916  P    28.791     .500    -5.382     .300  -.101000   .498000   .2360000      .000      .000  
+77 526 43289.00 I  -.072781  .003310   .488284  .002690  I  .2325485  .0002710  2.8386 0.3725  P    29.185     .500    -5.204     .300  -.097000   .499000   .2332000      .000      .000  
+77 527 43290.00 I  -.068911  .003525   .489700  .000995  I  .2296621  .0006939  2.9291 0.3725  P    29.219     .500    -5.118     .300  -.093000   .500000   .2305000      .000      .000  
+77 528 43291.00 I  -.064971  .003525   .491064  .000995  I  .2267043  .0006939  2.9774 0.4907  P    28.839     .500    -5.056     .300  -.089000   .500000   .2278000      .000      .000  
+77 529 43292.00 I  -.060961  .003525   .492372  .000995  I  .2237282  .0006939  2.9631 0.4907  P    28.339     .500    -4.892     .300  -.084000   .501000   .2251000      .000      .000  
+77 530 43293.00 I  -.056883  .003525   .493623  .000995  I  .2208005  .0006939  2.8818 0.4907  P    27.967     .500    -4.673     .300  -.080000   .501000   .2224000      .000      .000  
+77 531 43294.00 I  -.052743  .003525   .494815  .000995  I  .2179811  .0006939  2.7511 0.4907  P    27.728     .500    -4.602     .300  -.076000   .502000   .2197000      .000      .000  
+77 6 1 43295.00 I  -.048549  .003525   .495946  .000995  I  .2153028  .0006939  2.6069 0.3725  P    27.514     .500    -4.759     .300  -.072000   .503000   .2172000      .000      .000  
+77 6 2 43296.00 I  -.044308  .003310   .497014  .002690  I  .2127578  .0002710  2.4912 0.3725  P    27.293     .500    -4.979     .300  -.067000   .503000   .2146000      .000      .000  
+77 6 3 43297.00 I  -.040027  .003310   .498019  .002690  I  .2103014  .0002710  2.4325 0.1916  P    27.156     .500    -5.066     .300  -.063000   .504000   .2121000      .000      .000  
+77 6 4 43298.00 I  -.035714  .003310   .498957  .002690  I  .2078726  .0002710  2.4343 0.4973  P    27.237     .500    -5.035     .300  -.058000   .504000   .2095000      .000      .000  
+77 6 5 43299.00 I  -.031377  .002283   .499829  .000094  I  .2054199  .0009569  2.4749 0.4651  P    27.520     .500    -5.035     .300  -.054000   .505000   .2070000      .000      .000  
+77 6 6 43300.00 I  -.027023  .002283   .500632  .000094  I  .2029206  .0008898  2.5220 0.6533  P    27.719     .500    -5.097     .300  -.050000   .505000   .2046000      .000      .000  
+77 6 7 43301.00 I  -.022658  .002283   .501365  .000094  I  .2003829  .0008898  2.5481 0.6292  P    27.497     .500    -5.117     .300  -.045000   .506000   .2021000      .000      .000  
+77 6 8 43302.00 I  -.018292  .002283   .502026  .000094  I  .1978364  .0008898  2.5384 0.5611  P    26.888     .500    -5.058     .300  -.041000   .506000   .1997000      .000      .000  
+77 6 9 43303.00 I  -.013929  .002274   .502613  .004000  I  .1953189  .0006838  2.4905 0.5611  P    26.346     .500    -5.015     .300  -.036000   .507000   .1972000      .000      .000  
+77 610 43304.00 I  -.009571  .002274   .503126  .004000  I  .1928660  .0006838  2.4107 0.3948  P    26.217     .500    -5.058     .300  -.032000   .507000   .1948000      .000      .000  
+77 611 43305.00 I  -.005223  .002264   .503562  .005656  I  .1905050  .0003948  2.3083 0.3955  P    26.322     .500    -5.108     .300  -.027000   .507000   .1925000      .000      .000  
+77 612 43306.00 I  -.000887  .002913   .503920  .004782  I  .1882536  .0003978  2.1931 0.2802  P    26.229     .500    -5.068     .300  -.023000   .507000   .1902000      .000      .000  
+77 613 43307.00 I   .003430  .002913   .504204  .004782  I  .1861192  .0003978  2.0765 0.2813  P    25.824     .500    -4.992     .300  -.018000   .508000   .1878000      .000      .000  
+77 614 43308.00 I   .007721  .002913   .504419  .004782  I  .1840966  .0003978  1.9718 0.3438  P    25.389     .500    -5.022     .300  -.014000   .508000   .1855000      .000      .000  
+77 615 43309.00 I   .011979  .003442   .504571  .003709  I  .1821681  .0005608  1.8897 0.3496  P    25.207     .500    -5.179     .300  -.009000   .508000   .1832000      .000      .000  
+77 616 43310.00 I   .016202  .003297   .504661  .005862  I  .1803069  .0005751  1.8384 0.4016  P    25.294     .500    -5.320     .300  -.004000   .508000   .1810000      .000      .000  
+77 617 43311.00 I   .020388  .003297   .504691  .005862  I  .1784795  .0005751  1.8225 0.4116  P    25.485     .500    -5.314     .300   .000000   .508000   .1788000      .000      .000  
+77 618 43312.00 I   .024538  .003145   .504661  .007414  I  .1766499  .0005890  1.8427 0.4116  P    25.593     .500    -5.203     .300   .005000   .508000   .1765000      .000      .000  
+77 619 43313.00 I   .028650  .003145   .504573  .007414  I  .1747829  .0005890  1.8966 0.4165  P    25.475     .500    -5.137     .300   .009000   .508000   .1743000      .000      .000  
+77 620 43314.00 I   .032724  .003145   .504425  .007414  I  .1728472  .0005890  1.9789 0.3835  P    25.145     .500    -5.184     .300   .014000   .508000   .1721000      .000      .000  
+77 621 43315.00 I   .036766  .002336   .504209  .005245  I  .1708190  .0004913  2.0795 0.3474  P    24.834     .500    -5.257     .300   .018000   .507000   .1700000      .000      .000  
+77 622 43316.00 I   .040780  .001011   .503916  .000238  I  .1686870  .0003686  2.1837 0.3095  P    24.795     .500    -5.233     .300   .023000   .507000   .1679000      .000      .000  
+77 623 43317.00 I   .044771  .001011   .503537  .000238  I  .1664562  .0003765  2.2740 0.3442  P    25.004     .500    -5.082     .300   .027000   .506000   .1658000      .000      .000  
+77 624 43318.00 I   .048745  .004864   .503064  .000406  I  .1641497  .0005813  2.3320 0.3463  P    25.155     .500    -4.860     .300   .032000   .506000   .1637000      .000      .000  
+77 625 43319.00 I   .052704  .004864   .502488  .000406  I  .1618082  .0005813  2.3419 0.4110  P    24.986     .500    -4.612     .300   .036000   .505000   .1616000      .000      .000  
+77 626 43320.00 I   .056653  .004864   .501798  .000406  I  .1594844  .0005813  2.2964 0.4518  P    24.508     .500    -4.373     .300   .040000   .504000   .1596000      .000      .000  
+77 627 43321.00 I   .060594  .006804   .500987  .000522  I  .1572312  .0006917  2.2034 0.4186  P    23.933     .500    -4.239     .300   .045000   .503000   .1576000      .000      .000  
+77 628 43322.00 I   .064541  .008208   .500045  .007675  I  .1550854  .0006025  2.0870 0.4709  P    23.461     .500    -4.329     .300   .049000   .503000   .1556000      .000      .000  
+77 629 43323.00 I   .068508  .008208   .498965  .007675  I  .1530532  .0006391  1.9825 0.3742  P    23.157     .500    -4.613     .300   .054000   .502000   .1536000      .000      .000  
+77 630 43324.00 I   .072512  .009404   .497736  .010841  I  .1511055  .0004439  1.9227 0.4782  P    22.968     .500    -4.869     .300   .058000   .501000   .1516000      .000      .000  
+77 7 1 43325.00 I   .076569  .009404   .496352  .010841  I  .1491874  .0007116  1.9240 0.4194  P    22.854     .500    -4.890     .300   .062000   .500000   .1497000      .000      .000  
+77 7 2 43326.00 I   .080691  .009404   .494806  .010841  I  .1472403  .0007116  1.9768 0.4898  P    22.878     .500    -4.726     .300   .067000   .498000   .1478000      .000      .000  
+77 7 3 43327.00 I   .084878  .009155   .493103  .010095  I  .1452269  .0006731  2.0504 0.4981  P    23.087     .500    -4.606     .300   .071000   .497000   .1458000      .000      .000  
+77 7 4 43328.00 I   .089128  .008899   .491249  .009289  I  .1431446  .0006971  2.1088 0.4388  P    23.282     .500    -4.652     .300   .076000   .495000   .1439000      .000      .000  
+77 7 5 43329.00 I   .093441  .006458   .489249  .007229  I  .1410233  .0005631  2.1253 0.4404  P    23.101     .500    -4.759     .300   .080000   .494000   .1420000      .000      .000  
+77 7 6 43330.00 I   .097811  .006458   .487111  .007229  I  .1389103  .0005385  2.0929 0.3415  P    22.459     .500    -4.794     .300   .084000   .493000   .1401000      .000      .000  
+77 7 7 43331.00 I   .102226  .006458   .484849  .007229  I  .1368509  .0003865  2.0202 0.3314  P    21.758     .500    -4.779     .300   .089000   .491000   .1382000      .000      .000  
+77 7 8 43332.00 I   .106665  .006458   .482482  .007229  I  .1348787  .0003865  1.9211 0.2169  P    21.455     .500    -4.809     .300   .093000   .490000   .1364000      .000      .000  
+77 7 9 43333.00 I   .111111  .002892   .480027  .003875  I  .1330132  .0001971  1.8087 0.2200  P    21.511     .500    -4.884     .300   .098000   .488000   .1345000      .000      .000  
+77 710 43334.00 I   .115549  .002892   .477496  .003875  I  .1312618  .0002104  1.6949 0.1684  P    21.501     .500    -4.925     .300   .102000   .487000   .1326000      .000      .000  
+77 711 43335.00 I   .119963  .003538   .474902  .003434  I  .1296198  .0002732  1.5918 0.1501  P    21.196     .500    -4.906     .300   .106000   .485000   .1307000      .000      .000  
+77 712 43336.00 I   .124338  .008811   .472259  .004510  I  .1280705  .0002142  1.5118 0.1736  P    20.794     .500    -4.894     .300   .111000   .483000   .1289000      .000      .000  
+77 713 43337.00 I   .128654  .008811   .469581  .004510  I  .1265848  .0002142  1.4661 0.1515  P    20.574     .500    -4.922     .300   .115000   .482000   .1270000      .000      .000  
+77 714 43338.00 I   .132889  .008811   .466887  .004510  I  .1251247  .0002142  1.4613 0.1256  P    20.569     .500    -4.938     .300   .120000   .480000   .1252000      .000      .000  
+77 715 43339.00 I   .137022  .008773   .464193  .007298  I  .1236482  .0001313  1.4986 0.1256  P    20.660     .500    -4.885     .300   .124000   .478000   .1233000      .000      .000  
+77 716 43340.00 I   .141046  .008773   .461511  .007298  I  .1221143  .0001313  1.5754 0.0928  P    20.764     .500    -4.786     .300   .128000   .476000   .1215000      .000      .000  
+77 717 43341.00 I   .144961  .008773   .458851  .007298  I  .1204865  .0001313  1.6849 0.2357  P    20.810     .500    -4.717     .300   .132000   .474000   .1196000      .000      .000  
+77 718 43342.00 I   .148769  .002495   .456223  .006823  I  .1187374  .0004528  1.8158 0.2357  P    20.686     .500    -4.720     .300   .137000   .472000   .1178000      .000      .000  
+77 719 43343.00 I   .152475  .002495   .453630  .006823  I  .1168530  .0004528  1.9523 0.2925  P    20.370     .500    -4.765     .300   .141000   .470000   .1159000      .000      .000  
+77 720 43344.00 I   .156086  .003354   .451069  .005733  I  .1148374  .0003704  2.0750 0.3202  P    20.040     .500    -4.791     .300   .145000   .468000   .1141000      .000      .000  
+77 721 43345.00 I   .159611  .003359   .448538  .003239  I  .1127143  .0004529  2.1639 0.2913  P    19.913     .500    -4.744     .300   .149000   .466000   .1123000      .000      .000  
+77 722 43346.00 I   .163059  .003359   .446031  .003239  I  .1105254  .0004496  2.2053 0.3086  P    19.993     .500    -4.607     .300   .153000   .464000   .1105000      .000      .000  
+77 723 43347.00 I   .166440  .003359   .443541  .003239  I  .1083208  .0004192  2.1955 0.2518  P    20.061     .500    -4.408     .300   .157000   .461000   .1086000      .000      .000  
+77 724 43348.00 I   .169759  .004615   .441062  .002345  I  .1061490  .0002267  2.1419 0.2383  P    19.897     .500    -4.232     .300   .161000   .459000   .1068000      .000      .000  
+77 725 43349.00 I   .173020  .004615   .438590  .002345  I  .1040455  .0002267  2.0626 0.1999  P    19.477     .500    -4.202     .300   .165000   .457000   .1050000      .000      .000  
+77 726 43350.00 I   .176223  .003310   .436122  .002690  I  .1020235  .0003293  1.9840 0.2457  P    18.967     .500    -4.397     .300   .169000   .454000   .1031000      .000      .000  
+77 727 43351.00 I   .179368  .001299   .433652  .005142  I  .1000677  .0004360  1.9348 0.2734  P    18.552     .500    -4.749     .300   .172000   .452000   .1012000      .000      .000  
+77 728 43352.00 I   .182457  .001299   .431178  .005142  I  .0981372  .0004365  1.9359 0.3851  P    18.297     .500    -5.033     .300   .176000   .449000   .0994000      .000      .000  
+77 729 43353.00 I   .185491  .001299   .428696  .005142  I  .0961782  .0006348  1.9903 0.3584  P    18.170     .500    -5.041     .300   .179000   .447000   .0975000      .000      .000  
+77 730 43354.00 I   .188469  .001873   .426202  .003945  I  .0941448  .0005685  2.0800 0.4211  P    18.158     .500    -4.792     .300   .183000   .444000   .0956000      .000      .000  
+77 731 43355.00 I   .191393  .001873   .423697  .003945  I  .0920173  .0005536  2.1723 0.3968  P    18.280     .500    -4.525     .300   .186000   .441000   .0937000      .000      .000  
+77 8 1 43356.00 I   .194260  .001873   .421184  .003945  I  .0898110  .0005536  2.2323 0.3686  P    18.439     .500    -4.453     .300   .190000   .439000   .0918000      .000      .000  
+77 8 2 43357.00 I   .197068  .002767   .418666  .004987  I  .0875704  .0004869  2.2392 0.3686  P    18.387     .500    -4.562     .300   .193000   .436000   .0900000      .000      .000  
+77 8 3 43358.00 I   .199812  .002767   .416148  .004987  I  .0853505  .0004869  2.1925 0.3161  P    17.984     .500    -4.682     .300   .197000   .434000   .0881000      .000      .000  
+77 8 4 43359.00 I   .202487  .002767   .413635  .004987  I  .0831987  .0004033  2.1058 0.2811  P    17.416     .500    -4.714     .300   .200000   .431000   .0862000      .000      .000  
+77 8 5 43360.00 I   .205086  .002292   .411134  .005120  I  .0811463  .0002812  1.9968 0.2324  P    17.021     .500    -4.698     .300   .203000   .428000   .0843000      .000      .000  
+77 8 6 43361.00 I   .207607  .002292   .408645  .005120  I  .0792069  .0002312  1.8822 0.1820  P    16.907     .500    -4.707     .300   .207000   .425000   .0824000      .000      .000  
+77 8 7 43362.00 I   .210050  .002292   .406167  .005120  I  .0773793  .0002312  1.7753 0.2785  P    16.893     .500    -4.744     .300   .210000   .422000   .0804000      .000      .000  
+77 8 8 43363.00 I   .212415  .007256   .403695  .002685  I  .0756495  .0005068  1.6887 0.2785  P    16.806     .500    -4.770     .300   .214000   .419000   .0785000      .000      .000  
+77 8 9 43364.00 I   .214700  .007256   .401224  .002685  I  .0739912  .0005068  1.6342 0.3584  P    16.673     .500    -4.762     .300   .217000   .416000   .0766000      .000      .000  
+77 810 43365.00 I   .216906  .007256   .398749  .002685  I  .0723674  .0005068  1.6207 0.4170  P    16.589     .500    -4.724     .300   .220000   .413000   .0746000      .000      .000  
+77 811 43366.00 I   .219033  .010236   .396262  .002654  I  .0707352  .0006624  1.6508 0.3794  P    16.550     .500    -4.672     .300   .223000   .410000   .0726000      .000      .000  
+77 812 43367.00 I   .221096  .009367   .393754  .005785  I  .0690521  .0005648  1.7219 0.4353  P    16.522     .500    -4.641     .300   .227000   .406000   .0705000      .000      .000  
+77 813 43368.00 I   .223113  .009367   .391214  .005785  I  .0672798  .0005648  1.8280 0.3599  P    16.551     .500    -4.654     .300   .230000   .403000   .0685000      .000      .000  
+77 814 43369.00 I   .225102  .008408   .388632  .007738  I  .0653877  .0004463  1.9595 0.3599  P    16.664     .500    -4.681     .300   .233000   .400000   .0665000      .000      .000  
+77 815 43370.00 I   .227082  .008408   .385999  .007738  I  .0633572  .0004463  2.1017 0.3156  P    16.737     .500    -4.656     .300   .236000   .397000   .0644000      .000      .000  
+77 816 43371.00 I   .229062  .008408   .383309  .007738  I  .0611873  .0004463  2.2348 0.3156  P    16.599     .500    -4.555     .300   .239000   .393000   .0622000      .000      .000  
+77 817 43372.00 I   .231045  .008408   .380563  .007738  I  .0588980  .0004463  2.3365 0.2611  P    16.261     .500    -4.439     .300   .241000   .390000   .0601000      .000      .000  
+77 818 43373.00 I   .233032  .003310   .377760  .002690  I  .0565309  .0002710  2.3882 0.2611  P    15.942     .500    -4.372     .300   .244000   .386000   .0579000      .000      .000  
+77 819 43374.00 I   .235027  .003310   .374900  .002690  I  .0541403  .0002710  2.3837 0.1916  P    15.845     .500    -4.351     .300   .247000   .383000   .0558000      .000      .000  
+77 820 43375.00 I   .237031  .003310   .371983  .002690  I  .0517795  .0002710  2.3314 0.1750  P    15.961     .500    -4.328     .300   .250000   .380000   .0536000      .000      .000  
+77 821 43376.00 I   .239047  .009904   .369011  .003391  I  .0494863  .0002215  2.2529 0.1750  P    16.094     .500    -4.298     .300   .252000   .377000   .0514000      .000      .000  
+77 822 43377.00 I   .241077  .009904   .365981  .003391  I  .0472730  .0002215  2.1765 0.1566  P    16.061     .500    -4.324     .300   .255000   .373000   .0491000      .000      .000  
+77 823 43378.00 I   .243123  .009904   .362896  .003391  I  .0451234  .0002215  2.1298 0.1566  P    15.837     .500    -4.470     .300   .257000   .370000   .0469000      .000      .000  
+77 824 43379.00 I   .245184  .009904   .359754  .003391  I  .0429967  .0002215  2.1332 0.1566  P    15.536     .500    -4.713     .300   .260000   .367000   .0447000      .000      .000  
+77 825 43380.00 I   .247249  .009904   .356560  .003391  I  .0408378  .0002215  2.1942 0.1566  P    15.302     .500    -4.922     .300   .262000   .364000   .0423000      .000      .000  
+77 826 43381.00 I   .249300  .009904   .353319  .003391  I  .0385923  .0002215  2.3033 0.2772  P    15.206     .500    -4.939     .300   .265000   .360000   .0400000      .000      .000  
+77 827 43382.00 I   .251321  .003466   .350034  .002468  I  .0362236  .0005082  2.4353 0.2772  P    15.240     .500    -4.726     .300   .267000   .357000   .0376000      .000      .000  
+77 828 43383.00 I   .253295  .003466   .346710  .002468  I  .0337251  .0005082  2.5571 0.3594  P    15.354     .500    -4.423     .300   .270000   .353000   .0353000      .000      .000  
+77 829 43384.00 I   .255206  .003466   .343352  .002468  I  .0311225  .0005082  2.6394 0.3594  P    15.465     .500    -4.240     .300   .272000   .350000   .0329000      .000      .000  
+77 830 43385.00 I   .257037  .003466   .339965  .002468  I  .0284644  .0005082  2.6673 0.3594  P    15.470     .500    -4.258     .300   .274000   .346000   .0304000      .000      .000  
+77 831 43386.00 I   .258773  .003466   .336553  .002468  I  .0258056  .0005082  2.6422 0.4092  P    15.298     .500    -4.371     .300   .276000   .343000   .0279000      .000      .000  
+77 9 1 43387.00 I   .260403  .003466   .333124  .002468  I  .0231927  .0006414  2.5791 0.3341  P    14.974     .500    -4.433     .300   .278000   .339000   .0254000      .000      .000  
+77 9 2 43388.00 I   .261918  .010931   .329686  .016021  I  .0206533  .0004339  2.4984 0.3872  P    14.625     .500    -4.409     .300   .280000   .336000   .0229000      .000      .000  
+77 9 3 43389.00 I   .263308  .010931   .326247  .016021  I  .0181958  .0004339  2.4181 0.3068  P    14.398     .500    -4.377     .300   .282000   .332000   .0204000      .000      .000  
+77 9 4 43390.00 I   .264561  .010931   .322814  .016021  I  .0158123  .0004339  2.3522 0.3068  P    14.379     .500    -4.401     .300   .283000   .329000   .0177000      .000      .000  
+77 9 5 43391.00 I   .265669  .010931   .319396  .016021  I  .0134830  .0004339  2.3115 0.2987  P    14.547     .500    -4.468     .300   .285000   .325000   .0150000      .000      .000  
+77 9 6 43392.00 I   .266628  .010931   .315994  .016021  I  .0111780  .0004106  2.3048 0.2338  P    14.777     .500    -4.517     .300   .286000   .322000   .0123000      .000      .000  
+77 9 7 43393.00 I   .267445  .010931   .312596  .016021  I  .0088600  .0001741  2.3383 0.2515  P    14.924     .500    -4.507     .300   .288000   .318000   .0096000      .000      .000  
+77 9 8 43394.00 I   .268133  .003310   .309189  .002690  I  .0064876  .0002905  2.4132 0.1401  P    14.926     .500    -4.459     .300   .289000   .315000   .0069000      .000      .000  
+77 9 9 43395.00 I   .268701  .005556   .305760  .015372  I  .0040210  .0002195  2.5258 0.1821  P    14.854     .500    -4.448     .300   .290000   .311000   .0041000      .000      .000  
+77 910 43396.00 I   .269160  .005556   .302295  .015372  I  .0014261  .0002195  2.6682 0.1552  P    14.824     .500    -4.529     .300   .291000   .308000   .0013000      .000      .000  
+77 911 43397.00 I   .269522  .005556   .298782  .015372  I -.0013213  .0002195  2.8284 0.1419  P    14.877     .500    -4.641     .300   .292000   .304000  -.0015000      .000      .000  
+77 912 43398.00 I   .269796  .005556   .295208  .015372  I -.0042306  .0001799  2.9881 0.1419  P    14.937     .500    -4.634     .300   .293000   .301000  -.0043000      .000      .000  
+77 913 43399.00 I   .269986  .005556   .291573  .015372  I -.0072892  .0001799  3.1227 0.1272  P    14.900     .500    -4.427     .300   .294000   .297000  -.0071000      .000      .000  
+77 914 43400.00 I   .270092  .005556   .287884  .015372  I -.0104594  .0001799  3.2074 0.1626  P    14.738     .500    -4.120     .300   .295000   .293000  -.0100000      .000      .000  
+77 915 43401.00 I   .270114  .003310   .284148  .002690  I -.0136818  .0002710  3.2254 0.1626  P    14.527     .500    -3.911     .300   .296000   .289000  -.0129000      .000      .000  
+77 916 43402.00 I   .270054  .003310   .280373  .002690  I -.0168882  .0002710  3.1773 0.1916  P    14.387     .500    -3.895     .300   .296000   .286000  -.0157000      .000      .000  
+77 917 43403.00 I   .269909  .003310   .276564  .002690  I -.0200210  .0002710  3.0829 0.3706  P    14.390     .500    -3.997     .300   .297000   .282000  -.0186000      .000      .000  
+77 918 43404.00 I   .269682  .002806   .272729  .006509  I -.0230495  .0006899  2.9749 0.3706  P    14.505     .500    -4.089     .300   .298000   .278000  -.0215000      .000      .000  
+77 919 43405.00 I   .269372  .002806   .268874  .006509  I -.0259776  .0006899  2.8872 0.4878  P    14.640     .500    -4.125     .300   .298000   .274000  -.0244000      .000      .000  
+77 920 43406.00 I   .268979  .002806   .265007  .006509  I -.0288387  .0006899  2.8439 0.4878  P    14.717     .500    -4.148     .300   .298000   .271000  -.0274000      .000      .000  
+77 921 43407.00 I   .268504  .002806   .261134  .006509  I -.0316835  .0006899  2.8549 0.4878  P    14.737     .500    -4.204     .300   .299000   .267000  -.0303000      .000      .000  
+77 922 43408.00 I   .267952  .002806   .257254  .006509  I -.0345648  .0006899  2.9148 0.4309  P    14.764     .500    -4.273     .300   .299000   .264000  -.0333000      .000      .000  
+77 923 43409.00 I   .267328  .004994   .253366  .006890  I -.0375231  .0005166  3.0046 0.3653  P    14.858     .500    -4.277     .300   .299000   .260000  -.0362000      .000      .000  
+77 924 43410.00 I   .266637  .006481   .249467  .007251  I -.0405750  .0002405  3.0974 0.2849  P    15.015     .500    -4.160     .300   .299000   .256000  -.0392000      .000      .000  
+77 925 43411.00 I   .265886  .006481   .245557  .007251  I -.0437097  .0002405  3.1657 0.1701  P    15.153     .500    -3.956     .300   .299000   .252000  -.0422000      .000      .000  
+77 926 43412.00 I   .265079  .006481   .241635  .007251  I -.0468915  .0002405  3.1892 0.1701  P    15.196     .500    -3.779     .300   .299000   .249000  -.0451000      .000      .000  
+77 927 43413.00 I   .264214  .006481   .237704  .007251  I -.0500708  .0002405  3.1608 0.2556  P    15.146     .500    -3.714     .300   .299000   .245000  -.0481000      .000      .000  
+77 928 43414.00 I   .263284  .005080   .233771  .005733  I -.0531981  .0004510  3.0874 0.3731  P    15.070     .500    -3.741     .300   .299000   .241000  -.0511000      .000      .000  
+77 929 43415.00 I   .262283  .003100   .229846  .003625  I -.0562362  .0007063  2.9857 0.3685  P    14.988     .500    -3.771     .300   .298000   .237000  -.0541000      .000      .000  
+77 930 43416.00 I   .261204  .008030   .225936  .007837  I -.0591666  .0005828  2.8753 0.4579  P    14.877     .500    -3.768     .300   .298000   .233000  -.0571000      .000      .000  
+7710 1 43417.00 I   .260040  .008030   .222048  .007837  I -.0619897  .0005828  2.7735 0.4121  P    14.800     .500    -3.768     .300   .297000   .230000  -.0601000      .000      .000  
+7710 2 43418.00 I   .258791  .008030   .218186  .007837  I -.0647210  .0005828  2.6939 0.4121  P    14.924     .500    -3.819     .300   .297000   .226000  -.0631000      .000      .000  
+7710 3 43419.00 I   .257454  .008030   .214353  .007837  I -.0673890  .0005828  2.6487 0.3989  P    15.321     .500    -3.911     .300   .296000   .222000  -.0661000      .000      .000  
+7710 4 43420.00 I   .256033  .007860   .210549  .007426  I -.0700321  .0005447  2.6447 0.3364  P    15.803     .500    -3.993     .300   .295000   .218000  -.0692000      .000      .000  
+7710 5 43421.00 I   .254546  .007860   .206766  .007426  I -.0726932  .0003362  2.6851 0.3469  P    16.099     .500    -4.018     .300   .294000   .214000  -.0723000      .000      .000  
+7710 6 43422.00 I   .253012  .002056   .202993  .000778  I -.0754167  .0004298  2.7688 0.5658  P    16.159     .500    -3.975     .300   .293000   .211000  -.0755000      .000      .000  
+7710 7 43423.00 I   .251451  .012307   .199220  .007154  I -.0782432  .0010804  2.8899 0.5814  P    16.166     .500    -3.913     .300   .292000   .207000  -.0786000      .000      .000  
+7710 8 43424.00 I   .249883  .012307   .195435  .007154  I -.0812060  .0010804  3.0397 0.7640  P    16.242     .500    -3.911     .300   .291000   .203000  -.0817000      .000      .000  
+7710 9 43425.00 I   .248334  .012307   .191630  .007154  I -.0843280  .0010804  3.2057 0.9106  P    16.310     .500    -3.978     .300   .289000   .199000  -.0849000      .000      .000  
+771010 43426.00 I   .246824  .017283   .187794  .010087  I -.0876157  .0014662  3.3664 0.7496  P    16.275     .500    -3.990     .300   .288000   .195000  -.0881000      .000      .000  
+771011 43427.00 I   .245357  .012486   .183928  .007458  I -.0910496  .0010395  3.4933 0.8987  P    16.203     .500    -3.803     .300   .286000   .192000  -.0912000      .000      .000  
+771012 43428.00 I   .243924  .012486   .180034  .007458  I -.0945828  .0010395  3.5615 0.5225  P    16.224     .500    -3.445     .300   .285000   .188000  -.0944000      .000      .000  
+771013 43429.00 I   .242517  .003619   .176116  .003080  I -.0981487  .0001064  3.5579 0.5225  P    16.342     .500    -3.139     .300   .283000   .184000  -.0976000      .000      .000  
+771014 43430.00 I   .241125  .003619   .172177  .003080  I -.1016771  .0001064  3.4897 0.1951  P    16.450     .500    -3.076     .300   .281000   .180000  -.1009000      .000      .000  
+771015 43431.00 I   .239742  .010825   .168223  .004041  I -.1051158  .0003754  3.3848 0.1951  P    16.462     .500    -3.218     .300   .279000   .177000  -.1041000      .000      .000  
+771016 43432.00 I   .238365  .010825   .164261  .004041  I -.1084474  .0003754  3.2822 0.3207  P    16.392     .500    -3.368     .300   .277000   .173000  -.1074000      .000      .000  
+771017 43433.00 I   .236992  .014874   .160299  .004814  I -.1116924  .0005201  3.2161 0.3207  P    16.318     .500    -3.396     .300   .275000   .170000  -.1106000      .000      .000  
+771018 43434.00 I   .235622  .014874   .156343  .004814  I -.1148973  .0005201  3.2030 0.3201  P    16.332     .500    -3.337     .300   .273000   .166000  -.1139000      .000      .000  
+771019 43435.00 I   .234244  .011193   .152405  .005267  I -.1181151  .0003732  3.2401 0.3201  P    16.487     .500    -3.282     .300   .271000   .163000  -.1172000      .000      .000  
+771020 43436.00 I   .232834  .011193   .148495  .005267  I -.1213882  .0003732  3.3094 0.1920  P    16.752     .500    -3.254     .300   .268000   .159000  -.1204000      .000      .000  
+771021 43437.00 I   .231360  .005414   .144629  .005683  I -.1247362  .0000904  3.3857 0.2110  P    17.032     .500    -3.211     .300   .266000   .156000  -.1237000      .000      .000  
+771022 43438.00 I   .229791  .004175   .140821  .004043  I -.1281541  .0001971  3.4456 0.1084  P    17.238     .500    -3.125     .300   .263000   .152000  -.1269000      .000      .000  
+771023 43439.00 I   .228100  .004175   .137082  .004043  I -.1316161  .0001971  3.4715 0.1330  P    17.321     .500    -3.018     .300   .261000   .149000  -.1302000      .000      .000  
+771024 43440.00 I   .226268  .004175   .133418  .004043  I -.1350826  .0001786  3.4538 0.1331  P    17.276     .500    -2.930     .300   .258000   .146000  -.1334000      .000      .000  
+771025 43441.00 I   .224273  .009785   .129837  .000726  I -.1385092  .0001789  3.3924 0.1264  P    17.170     .500    -2.864     .300   .256000   .142000  -.1367000      .000      .000  
+771026 43442.00 I   .222098  .009785   .126344  .000726  I -.1418558  .0001789  3.2961 0.1265  P    17.123     .500    -2.800     .300   .253000   .139000  -.1399000      .000      .000  
+771027 43443.00 I   .219726  .009785   .122945  .000726  I -.1450950  .0001789  3.1806 0.0974  P    17.199     .500    -2.729     .300   .251000   .135000  -.1432000      .000      .000  
+771028 43444.00 I   .217146  .013637   .119647  .000809  I -.1482166  .0000769  3.0638 0.2663  P    17.342     .500    -2.681     .300   .248000   .132000  -.1464000      .000      .000  
+771029 43445.00 I   .214360  .016366   .116453  .007386  I -.1512272  .0005016  2.9609 0.2751  P    17.510     .500    -2.686     .300   .245000   .129000  -.1496000      .000      .000  
+771030 43446.00 I   .211380  .016366   .113368  .007386  I -.1541470  .0005447  2.8838 0.4327  P    17.780     .500    -2.737     .300   .242000   .126000  -.1528000      .000      .000  
+771031 43447.00 I   .208216  .018702   .110397  .010414  I -.1570059  .0007052  2.8401 0.4455  P    18.214     .500    -2.798     .300   .240000   .122000  -.1559000      .000      .000  
+7711 1 43448.00 I   .204878  .018702   .107544  .010414  I -.1598398  .0007052  2.8343 0.4987  P    18.658     .500    -2.850     .300   .237000   .119000  -.1591000      .000      .000  
+7711 2 43449.00 I   .201393  .018702   .104809  .010414  I -.1626876  .0007052  2.8678 0.4598  P    18.882     .500    -2.875     .300   .234000   .116000  -.1623000      .000      .000  
+7711 3 43450.00 I   .197804  .017105   .102181  .007368  I -.1655874  .0005903  2.9373 0.3975  P    18.912     .500    -2.837     .300   .231000   .113000  -.1654000      .000      .000  
+7711 4 43451.00 I   .194157  .015343   .099653  .000364  I -.1685717  .0003669  3.0353 0.3475  P    19.006     .500    -2.712     .300   .228000   .110000  -.1685000      .000      .000  
+7711 5 43452.00 I   .190500  .015343   .097216  .000364  I -.1716640  .0003669  3.1513 0.2594  P    19.255     .500    -2.559     .300   .226000   .108000  -.1716000      .000      .000  
+7711 6 43453.00 I   .186872  .015343   .094859  .000364  I -.1748758  .0003669  3.2718 0.2249  P    19.438     .500    -2.478     .300   .223000   .105000  -.1747000      .000      .000  
+7711 7 43454.00 I   .183296  .015307   .092575  .000364  I -.1782032  .0002603  3.3790 0.2249  P    19.362     .500    -2.456     .300   .220000   .102000  -.1778000      .000      .000  
+7711 8 43455.00 I   .179789  .015307   .090356  .000364  I -.1816217  .0002603  3.4500 0.1310  P    19.183     .500    -2.354     .300   .217000   .099000  -.1809000      .000      .000  
+7711 9 43456.00 I   .176367  .015270   .088191  .002690  I -.1850845  .0000303  3.4648 0.1310  P    19.208     .500    -2.099     .300   .214000   .097000  -.1840000      .000      .000  
+771110 43457.00 I   .173044  .015270   .086073  .002690  I -.1885299  .0000303  3.4154 0.0214  P    19.508     .500    -1.837     .300   .212000   .094000  -.1870000      .000      .000  
+771111 43458.00 I   .169819  .015270   .083993  .002690  I -.1918985  .0000303  3.3154 0.0214  P    19.863     .500    -1.785     .300   .209000   .092000  -.1901000      .000      .000  
+771112 43459.00 I   .166678  .015270   .081943  .002690  I -.1951549  .0000303  3.1978 0.1363  P    20.019     .500    -1.953     .300   .206000   .089000  -.1932000      .000      .000  
+771113 43460.00 I   .163610  .003310   .079914  .002690  I -.1983014  .0002710  3.1021 0.1394  P    19.895     .500    -2.131     .300   .203000   .087000  -.1963000      .000      .000  
+771114 43461.00 I   .160601  .001793   .077898  .009681  I -.2013761  .0002771  3.0573 0.1938  P    19.608     .500    -2.148     .300   .200000   .084000  -.1994000      .000      .000  
+771115 43462.00 I   .157639  .001793   .075885  .009681  I -.2044350  .0002771  3.0694 0.1959  P    19.395     .500    -2.056     .300   .198000   .082000  -.2024000      .000      .000  
+771116 43463.00 I   .154712  .001793   .073867  .009681  I -.2075283  .0002771  3.1217 0.1744  P    19.442     .500    -1.988     .300   .195000   .079000  -.2055000      .000      .000  
+771117 43464.00 I   .151806  .001272   .071837  .006865  I -.2106822  .0002117  3.1855 0.1744  P    19.708     .500    -1.958     .300   .192000   .077000  -.2086000      .000      .000  
+771118 43465.00 I   .148908  .001272   .069796  .006865  I -.2138939  .0002117  3.2333 0.1436  P    19.954     .500    -1.884     .300   .189000   .075000  -.2117000      .000      .000  
+771119 43466.00 I   .146001  .001272   .067748  .006865  I -.2171378  .0001942  3.2482 0.1176  P    20.005     .500    -1.753     .300   .186000   .073000  -.2148000      .000      .000  
+771120 43467.00 I   .143069  .000144   .065696  .000735  I -.2203774  .0001026  3.2243 0.1361  P    19.906     .500    -1.659     .300   .184000   .070000  -.2178000      .000      .000  
+771121 43468.00 I   .140096  .012232   .063645  .004452  I -.2235741  .0001907  3.1634 0.1083  P    19.796     .500    -1.657     .300   .181000   .068000  -.2209000      .000      .000  
+771122 43469.00 I   .137068  .012232   .061601  .004452  I -.2266946  .0001907  3.0736 0.1460  P    19.743     .500    -1.679     .300   .178000   .066000  -.2240000      .000      .000  
+771123 43470.00 I   .133967  .017298   .059568  .006253  I -.2297155  .0002211  2.9663 0.1613  P    19.756     .500    -1.626     .300   .175000   .064000  -.2271000      .000      .000  
+771124 43471.00 I   .130783  .012959   .057551  .004867  I -.2326260  .0002603  2.8554 0.1776  P    19.850     .500    -1.493     .300   .172000   .062000  -.2302000      .000      .000  
+771125 43472.00 I   .127525  .012959   .055548  .004867  I -.2354300  .0002780  2.7556 0.1904  P    20.022     .500    -1.374     .300   .169000   .060000  -.2332000      .000      .000  
+771126 43473.00 I   .124210  .012959   .053556  .004867  I -.2381449  .0002780  2.6789 0.2060  P    20.229     .500    -1.331     .300   .166000   .058000  -.2363000      .000      .000  
+771127 43474.00 I   .120857  .006052   .051573  .002877  I -.2407984  .0003040  2.6340 0.1849  P    20.458     .500    -1.338     .300   .163000   .056000  -.2394000      .000      .000  
+771128 43475.00 I   .117476  .005817   .049596  .002041  I -.2434254  .0002440  2.6266 0.1949  P    20.722     .500    -1.348     .300   .160000   .054000  -.2424000      .000      .000  
+771129 43476.00 I   .114076  .005817   .047626  .002041  I -.2460646  .0002440  2.6583 0.1340  P    20.952     .500    -1.369     .300   .157000   .052000  -.2455000      .000      .000  
+771130 43477.00 I   .110660  .005571   .045664  .000242  I -.2487541  .0001108  2.7264 0.1340  P    21.035     .500    -1.426     .300   .153000   .051000  -.2485000      .000      .000  
+7712 1 43478.00 I   .107236  .005571   .043711  .000242  I -.2515275  .0001108  2.8249 0.0783  P    21.023     .500    -1.466     .300   .150000   .049000  -.2516000      .000      .000  
+7712 2 43479.00 I   .103810  .005571   .041766  .000242  I -.2544109  .0001108  2.9445 0.1077  P    21.134     .500    -1.387     .300   .147000   .047000  -.2546000      .000      .000  
+7712 3 43480.00 I   .100399  .005206   .039832  .006273  I -.2574196  .0001848  3.0734 0.1306  P    21.426     .500    -1.184     .300   .143000   .045000  -.2577000      .000      .000  
+7712 4 43481.00 I   .097018  .004815   .037907  .008868  I -.2605561  .0002366  3.1976 0.1501  P    21.652     .500     -.985     .300   .140000   .043000  -.2608000      .000      .000  
+7712 5 43482.00 I   .093685  .004815   .035992  .008868  I -.2638080  .0002366  3.3013 0.2804  P    21.575     .500     -.889     .300   .136000   .042000  -.2640000      .000      .000  
+7712 6 43483.00 I   .090413  .003622   .034089  .006659  I -.2671458  .0005084  3.3664 0.2804  P    21.310     .500     -.833     .300   .133000   .040000  -.2671000      .000      .000  
+7712 7 43484.00 I   .087214  .003622   .032206  .006659  I -.2705236  .0005084  3.3798 0.4687  P    21.178     .500     -.707     .300   .129000   .038000  -.2702000      .000      .000  
+7712 8 43485.00 I   .084094  .003411   .030357  .005560  I -.2738882  .0007876  3.3414 0.5387  P    21.308     .500     -.569     .300   .125000   .036000  -.2734000      .000      .000  
+7712 9 43486.00 I   .081061  .002421   .028552  .002656  I -.2771957  .0009500  3.2709 0.6170  P    21.537     .500     -.595     .300   .121000   .035000  -.2766000      .000      .000  
+771210 43487.00 I   .078120  .002421   .026806  .002656  I -.2804311  .0009500  3.2038 0.6135  P    21.638     .500     -.809     .300   .117000   .033000  -.2797000      .000      .000  
+771211 43488.00 I   .075273  .002604   .025137  .007517  I -.2836161  .0007764  3.1752 0.6277  P    21.523     .500    -1.002     .300   .113000   .032000  -.2829000      .000      .000  
+771212 43489.00 I   .072525  .002940   .023559  .008929  I -.2867999  .0008208  3.2018 0.5649  P    21.276     .500     -.988     .300   .109000   .030000  -.2861000      .000      .000  
+771213 43490.00 I   .069874  .002940   .022086  .008929  I -.2900354  .0008208  3.2754 0.4114  P    21.109     .500     -.838     .300   .105000   .029000  -.2893000      .000      .000  
+771214 43491.00 I   .067317  .002937   .020731  .012466  I -.2933573  .0000587  3.3686 0.4110  P    21.205     .500     -.746     .300   .101000   .028000  -.2925000      .000      .000  
+771215 43492.00 I   .064853  .010476   .019504  .009938  I -.2967677  .0000428  3.4469 0.0363  P    21.494     .500     -.746     .300   .096000   .026000  -.2957000      .000      .000  
+771216 43493.00 I   .062474  .010476   .018405  .009938  I -.3002377  .0000428  3.4849 0.0226  P    21.663     .500     -.703     .300   .092000   .025000  -.2989000      .000      .000  
+771217 43494.00 I   .060173  .014522   .017429  .006491  I -.3037211  .0000143  3.4736 0.0226  P    21.518     .500     -.559     .300   .088000   .024000  -.3021000      .000      .000  
+771218 43495.00 I   .057942  .014522   .016575  .006491  I -.3071703  .0000143  3.4184 0.0101  P    21.229     .500     -.443     .300   .084000   .023000  -.3053000      .000      .000  
+771219 43496.00 I   .055757  .014522   .015844  .006491  I -.3105474  .0000143  3.3318 0.0101  P    21.094     .500     -.480     .300   .080000   .022000  -.3086000      .000      .000  
+771220 43497.00 I   .053585  .014522   .015243  .006491  I -.3138279  .0000143  3.2274 0.0839  P    21.163     .500     -.610     .300   .075000   .021000  -.3118000      .000      .000  
+771221 43498.00 I   .051390  .021222   .014776  .011623  I -.3170006  .0001672  3.1183 0.0839  P    21.256     .500     -.672     .300   .071000   .020000  -.3151000      .000      .000  
+771222 43499.00 I   .049138  .021222   .014450  .011623  I -.3200671  .0001672  3.0171 0.1182  P    21.280     .500     -.607     .300   .067000   .019000  -.3183000      .000      .000  
+771223 43500.00 I   .046792  .021222   .014270  .011623  I -.3230414  .0001672  2.9357 0.1182  P    21.309     .500     -.502     .300   .063000   .018000  -.3215000      .000      .000  
+771224 43501.00 I   .044321  .021222   .014241  .011623  I -.3259482  .0001672  2.8833 0.1182  P    21.402     .500     -.441     .300   .058000   .018000  -.3248000      .000      .000  
+771225 43502.00 I   .041712  .021222   .014360  .011623  I -.3288195  .0001672  2.8654 0.1182  P    21.527     .500     -.417     .300   .054000   .017000  -.3280000      .000      .000  
+771226 43503.00 I   .038970  .021222   .014618  .011623  I -.3316910  .0001672  2.8834 0.1592  P    21.649     .500     -.399     .300   .049000   .017000  -.3313000      .000      .000  
+771227 43504.00 I   .036101  .003310   .015005  .002690  I -.3345972  .0002710  2.9342 0.1592  P    21.769     .500     -.424     .300   .045000   .016000  -.3345000      .000      .000  
+771228 43505.00 I   .033110  .003310   .015512  .002690  I -.3375686  .0002710  3.0125 0.1916  P    21.867     .500     -.535     .300   .041000   .016000  -.3377000      .000      .000  
+771229 43506.00 I   .030003  .003310   .016128  .002690  I -.3406283  .0002710  3.1092 0.1916  P    21.936     .500     -.679     .300   .036000   .016000  -.3410000      .000      .000  
+771230 43507.00 I   .026786  .003310   .016844  .002690  I -.3437893  .0002710  3.2129 0.1916  P    22.033     .500     -.718     .300   .032000   .015000  -.3442000      .000      .000  
+771231 43508.00 I   .023463  .003310   .017651  .002690  I -.3470520  .0002710  3.3102 0.1916  P    22.183     .500     -.586     .300   .027000   .015000  -.3475000      .000      .000  
+78 1 1 43509.00 I   .020040  .003310   .018540  .002690  I  .6495968  .0002710  3.3879 0.1916  P    22.271     .500     -.376     .300   .023000   .015000   .6493000      .000      .000  
+78 1 2 43510.00 I   .016522  .003310   .019499  .002690  I  .6461826  .0002710  3.4342 0.1916  P    22.160     .500     -.223     .300   .019000   .015000   .6461000      .000      .000  
+78 1 3 43511.00 I   .012916  .003310   .020520  .002690  I  .6427420  .0002710  3.4396 0.1916  P    21.900     .500     -.148     .300   .015000   .015000   .6429000      .000      .000  
+78 1 4 43512.00 I   .009227  .003310   .021594  .002690  I  .6393177  .0002710  3.4021 0.1916  P    21.668     .500     -.089     .300   .011000   .015000   .6398000      .000      .000  
+78 1 5 43513.00 I   .005460  .003310   .022710  .002690  I  .6359491  .0002710  3.3308 0.1916  P    21.535     .500     -.063     .300   .007000   .015000   .6366000      .000      .000  
+78 1 6 43514.00 I   .001620  .003310   .023858  .002690  I  .6326596  .0002710  3.2488 0.3493  P    21.412     .500     -.176     .300   .003000   .015000   .6334000      .000      .000  
+78 1 7 43515.00 I  -.002286  .000685   .025031  .007140  I  .6294446  .0006439  3.1873 0.3493  P    21.213     .500     -.431     .300  -.001000   .016000   .6303000      .000      .000  
+78 1 8 43516.00 I  -.006254  .000685   .026216  .007140  I  .6262694  .0006439  3.1726 0.4553  P    20.960     .500     -.624     .300  -.005000   .016000   .6271000      .000      .000  
+78 1 9 43517.00 I  -.010278  .000685   .027406  .007140  I  .6230813  .0006439  3.2121 0.4553  P    20.763     .500     -.565     .300  -.008000   .017000   .6240000      .000      .000  
+78 110 43518.00 I  -.014352  .000685   .028591  .007140  I  .6198327  .0006439  3.2892 0.4553  P    20.769     .500     -.324     .300  -.012000   .017000   .6208000      .000      .000  
+78 111 43519.00 I  -.018472  .000685   .029769  .007140  I  .6165018  .0006439  3.3698 0.4553  P    21.062     .500     -.155     .300  -.016000   .018000   .6177000      .000      .000  
+78 112 43520.00 I  -.022634  .000685   .030938  .007140  I  .6131041  .0006439  3.4175 0.3493  P    21.495     .500     -.169     .300  -.020000   .019000   .6146000      .000      .000  
+78 113 43521.00 I  -.026834  .003310   .032100  .002690  I  .6096852  .0002710  3.4101 0.3493  P    21.719     .500     -.232     .300  -.024000   .020000   .6115000      .000      .000  
+78 114 43522.00 I  -.031067  .003310   .033253  .002690  I  .6063026  .0002710  3.3466 0.1916  P    21.535     .500     -.203     .300  -.027000   .021000   .6083000      .000      .000  
+78 115 43523.00 I  -.035329  .003310   .034397  .002690  I  .6030057  .0002710  3.2419 0.1916  P    21.165     .500     -.136     .300  -.031000   .022000   .6052000      .000      .000  
+78 116 43524.00 I  -.039617  .003310   .035533  .002690  I  .5998260  .0002710  3.1156 0.1916  P    20.984     .500     -.177     .300  -.035000   .023000   .6021000      .000      .000  
+78 117 43525.00 I  -.043925  .003310   .036659  .002690  I  .5967754  .0002710  2.9865 0.1916  P    21.054     .500     -.342     .300  -.039000   .024000   .5990000      .000      .000  
+78 118 43526.00 I  -.048250  .003310   .037777  .002690  I  .5938494  .0002710  2.8683 0.1916  P    21.131     .500     -.503     .300  -.042000   .026000   .5960000      .000      .000  
+78 119 43527.00 I  -.052587  .003310   .038885  .002690  I  .5910312  .0002710  2.7728 0.1373  P    21.080     .500     -.569     .300  -.046000   .027000   .5929000      .000      .000  
+78 120 43528.00 I  -.056933  .003644   .039983  .004005  I  .5882930  .0000447  2.7096 0.1373  P    21.041     .500     -.567     .300  -.049000   .029000   .5899000      .000      .000  
+78 121 43529.00 I  -.061283  .003644   .041071  .004005  I  .5855990  .0000447  2.6852 0.0316  P    21.149     .500     -.552     .300  -.053000   .030000   .5868000      .000      .000  
+78 122 43530.00 I  -.065632  .003644   .042149  .004005  I  .5829089  .0000447  2.7018 0.0316  P    21.333     .500     -.537     .300  -.057000   .032000   .5838000      .000      .000  
+78 123 43531.00 I  -.069978  .003644   .043217  .004005  I  .5801827  .0000447  2.7566 0.0316  P    21.483     .500     -.528     .300  -.060000   .033000   .5807000      .000      .000  
+78 124 43532.00 I  -.074314  .003644   .044276  .004005  I  .5773848  .0000447  2.8441 0.0316  P    21.623     .500     -.570     .300  -.064000   .035000   .5777000      .000      .000  
+78 125 43533.00 I  -.078629  .003644   .045329  .004005  I  .5744866  .0000447  2.9553 0.1373  P    21.814     .500     -.698     .300  -.067000   .036000   .5746000      .000      .000  
+78 126 43534.00 I  -.082914  .003310   .046382  .002690  I  .5714703  .0002710  3.0781 0.1373  P    22.007     .500     -.860     .300  -.071000   .038000   .5716000      .000      .000  
+78 127 43535.00 I  -.087156  .003310   .047440  .002690  I  .5683313  .0002710  3.1981 0.1916  P    22.102     .500     -.947     .300  -.075000   .040000   .5685000      .000      .000  
+78 128 43536.00 I  -.091345  .003310   .048508  .002690  I  .5650802  .0002710  3.2998 0.4703  P    22.073     .500     -.902     .300  -.079000   .042000   .5654000      .000      .000  
+78 129 43537.00 I  -.095469  .003457   .049592  .000177  I  .5617421  .0009008  3.3704 0.4703  P    21.961     .500     -.776     .300  -.082000   .045000   .5623000      .000      .000  
+78 130 43538.00 I  -.099518  .003457   .050695  .000177  I  .5583520  .0009008  3.4032 0.6370  P    21.805     .500     -.660     .300  -.086000   .047000   .5592000      .000      .000  
+78 131 43539.00 I  -.103479  .003457   .051823  .000177  I  .5549479  .0009008  3.3994 0.6370  P    21.635     .500     -.596     .300  -.090000   .049000   .5561000      .000      .000  
+78 2 1 43540.00 I  -.107343  .003457   .052982  .000177  I  .5515624  .0009008  3.3679 0.6370  P    21.479     .500     -.580     .300  -.094000   .051000   .5529000      .000      .000  
+78 2 2 43541.00 I  -.111101  .003457   .054176  .000177  I  .5482159  .0009008  3.3250 0.6370  P    21.316     .500     -.635     .300  -.097000   .054000   .5497000      .000      .000  
+78 2 3 43542.00 I  -.114749  .003457   .055410  .000177  I  .5449082  .0009008  3.2948 0.4703  P    21.088     .500     -.813     .300  -.101000   .056000   .5465000      .000      .000  
+78 2 4 43543.00 I  -.118282  .003310   .056689  .002690  I  .5416135  .0002710  3.3029 0.4703  P    20.784     .500    -1.087     .300  -.104000   .059000   .5433000      .000      .000  
+78 2 5 43544.00 I  -.121695  .003310   .058017  .002690  I  .5382847  .0002710  3.3642 0.1916  P    20.482     .500    -1.282     .300  -.108000   .061000   .5401000      .000      .000  
+78 2 6 43545.00 I  -.124985  .003310   .059400  .002690  I  .5348688  .0002710  3.4743 0.1916  P    20.298     .500    -1.222     .300  -.111000   .063000   .5367000      .000      .000  
+78 2 7 43546.00 I  -.128145  .003310   .060842  .002690  I  .5313286  .0002710  3.6067 0.1916  P    20.338     .500     -.955     .300  -.114000   .066000   .5333000      .000      .000  
+78 2 8 43547.00 I  -.131173  .003310   .062348  .002690  I  .5276610  .0002710  3.7223 0.1916  P    20.638     .500     -.739     .300  -.118000   .068000   .5300000      .000      .000  
+78 2 9 43548.00 I  -.134063  .003310   .063923  .002690  I  .5239011  .0002710  3.7865 0.2103  P    21.060     .500     -.771     .300  -.121000   .071000   .5266000      .000      .000  
+78 210 43549.00 I  -.136811  .010342   .065571  .010800  I  .5201109  .0003216  3.7820 0.2103  P    21.321     .500     -.984     .300  -.124000   .073000   .5232000      .000      .000  
+78 211 43550.00 I  -.139412  .010342   .067299  .010800  I  .5163583  .0003216  3.7140 0.2274  P    21.242     .500    -1.172     .300  -.127000   .076000   .5197000      .000      .000  
+78 212 43551.00 I  -.141862  .010342   .069109  .010800  I  .5126973  .0003216  3.6030 0.2274  P    20.955     .500    -1.244     .300  -.130000   .078000   .5162000      .000      .000  
+78 213 43552.00 I  -.144157  .010342   .071007  .010800  I  .5091584  .0003216  3.4739 0.2274  P    20.740     .500    -1.279     .300  -.133000   .081000   .5128000      .000      .000  
+78 214 43553.00 I  -.146306  .010342   .072987  .010800  I  .5057484  .0003216  3.3481 0.2274  P    20.680     .500    -1.371     .300  -.136000   .083000   .5093000      .000      .000  
+78 215 43554.00 I  -.148325  .010342   .075040  .010800  I  .5024562  .0003216  3.2402 0.2103  P    20.642     .500    -1.512     .300  -.139000   .086000   .5058000      .000      .000  
+78 216 43555.00 I  -.150229  .003310   .077157  .002690  I  .4992585  .0002710  3.1608 0.2103  P    20.588     .500    -1.643     .300  -.142000   .089000   .5023000      .000      .000  
+78 217 43556.00 I  -.152032  .003310   .079328  .002690  I  .4961223  .0002710  3.1183 0.2583  P    20.682     .500    -1.728     .300  -.145000   .091000   .4988000      .000      .000  
+78 218 43557.00 I  -.153750  .000711   .081544  .010230  I  .4930084  .0004399  3.1165 0.2583  P    21.016     .500    -1.762     .300  -.148000   .094000   .4952000      .000      .000  
+78 219 43558.00 I  -.155398  .000711   .083795  .010230  I  .4898759  .0004399  3.1551 0.3111  P    21.422     .500    -1.760     .300  -.151000   .096000   .4917000      .000      .000  
+78 220 43559.00 I  -.156991  .000711   .086073  .010230  I  .4866864  .0004399  3.2291 0.3111  P    21.685     .500    -1.766     .300  -.154000   .099000   .4882000      .000      .000  
+78 221 43560.00 I  -.158545  .000711   .088367  .010230  I  .4834090  .0004399  3.3292 0.3111  P    21.815     .500    -1.830     .300  -.157000   .102000   .4847000      .000      .000  
+78 222 43561.00 I  -.160073  .000711   .090673  .010230  I  .4800234  .0004399  3.4430 0.3924  P    21.962     .500    -1.949     .300  -.160000   .104000   .4812000      .000      .000  
+78 223 43562.00 I  -.161591  .002779   .092993  .007757  I  .4765236  .0006499  3.5549 0.4596  P    22.154     .500    -2.048     .300  -.162000   .107000   .4776000      .000      .000  
+78 224 43563.00 I  -.163112  .003866   .095331  .003961  I  .4729200  .0008070  3.6476 0.5181  P    22.267     .500    -2.064     .300  -.165000   .109000   .4741000      .000      .000  
+78 225 43564.00 I  -.164649  .003866   .097691  .003961  I  .4692407  .0008070  3.7035 0.5706  P    22.224     .500    -2.018     .300  -.168000   .112000   .4706000      .000      .000  
+78 226 43565.00 I  -.166217  .003866   .100078  .003961  I  .4655291  .0008070  3.7113 0.5706  P    22.088     .500    -1.983     .300  -.171000   .115000   .4671000      .000      .000  
+78 227 43566.00 I  -.167826  .003866   .102497  .003961  I  .4618338  .0008070  3.6722 0.5706  P    21.968     .500    -1.998     .300  -.174000   .118000   .4636000      .000      .000  
+78 228 43567.00 I  -.169483  .003866   .104958  .003961  I  .4581963  .0008070  3.5985 0.4256  P    21.902     .500    -2.045     .300  -.176000   .120000   .4602000      .000      .000  
+78 3 1 43568.00 I  -.171196  .003310   .107469  .002690  I  .4546412  .0002710  3.5116 0.4256  P    21.862     .500    -2.101     .300  -.179000   .123000   .4567000      .000      .000  
+78 3 2 43569.00 I  -.172969  .003310   .110041  .002690  I  .4511691  .0002710  3.4368 0.1916  P    21.804     .500    -2.186     .300  -.182000   .126000   .4532000      .000      .000  
+78 3 3 43570.00 I  -.174810  .003310   .112681  .002690  I  .4477555  .0002710  3.3983 0.2620  P    21.717     .500    -2.341     .300  -.185000   .129000   .4498000      .000      .000  
+78 3 4 43571.00 I  -.176725  .014722   .115401  .010929  I  .4443550  .0004485  3.4124 0.2620  P    21.632     .500    -2.554     .300  -.187000   .132000   .4464000      .000      .000  
+78 3 5 43572.00 I  -.178721  .014722   .118208  .010929  I  .4409123  .0004485  3.4816 0.3171  P    21.597     .500    -2.714     .300  -.190000   .136000   .4429000      .000      .000  
+78 3 6 43573.00 I  -.180803  .014722   .121112  .010929  I  .4373785  .0004485  3.5908 0.3171  P    21.640     .500    -2.692     .300  -.192000   .139000   .4395000      .000      .000  
+78 3 7 43574.00 I  -.182979  .014722   .124123  .010929  I  .4337276  .0004485  3.7094 0.3171  P    21.757     .500    -2.489     .300  -.195000   .142000   .4361000      .000      .000  
+78 3 8 43575.00 I  -.185247  .014722   .127245  .010929  I  .4299692  .0004485  3.7996 0.3171  P    21.925     .500    -2.292     .300  -.197000   .146000   .4328000      .000      .000  
+78 3 9 43576.00 I  -.187587  .014722   .130475  .010929  I  .4261477  .0004485  3.8318 0.2268  P    22.100     .500    -2.316     .300  -.199000   .149000   .4294000      .000      .000  
+78 310 43577.00 I  -.189978  .002182   .133808  .002690  I  .4223286  .0000680  3.7951 0.2268  P    22.209     .500    -2.585     .300  -.202000   .153000   .4261000      .000      .000  
+78 311 43578.00 I  -.192398  .002182   .137237  .002690  I  .4185771  .0000680  3.6997 0.0481  P    22.202     .500    -2.908     .300  -.204000   .156000   .4227000      .000      .000  
+78 312 43579.00 I  -.194826  .002182   .140760  .002690  I  .4149412  .0000680  3.5683 0.0481  P    22.099     .500    -3.088     .300  -.206000   .160000   .4194000      .000      .000  
+78 313 43580.00 I  -.197240  .002182   .144369  .002690  I  .4114441  .0000680  3.4262 0.0481  P    21.959     .500    -3.101     .300  -.208000   .164000   .4161000      .000      .000  
+78 314 43581.00 I  -.199617  .002182   .148061  .002690  I  .4080856  .0000680  3.2937 0.3286  P    21.809     .500    -3.069     .300  -.210000   .168000   .4128000      .000      .000  
+78 315 43582.00 I  -.201929  .008840   .151830  .004015  I  .4048488  .0006536  3.1848 0.4622  P    21.670     .500    -3.102     .300  -.212000   .172000   .4096000      .000      .000  
+78 316 43583.00 I  -.204152  .012310   .155670  .004015  I  .4017049  .0009218  3.1091 0.5650  P    21.649     .500    -3.207     .300  -.214000   .176000   .4063000      .000      .000  
+78 317 43584.00 I  -.206260  .012310   .159578  .004015  I  .3986177  .0009218  3.0722 0.6518  P    21.885     .500    -3.318     .300  -.216000   .180000   .4030000      .000      .000  
+78 318 43585.00 I  -.208229  .012310   .163547  .004015  I  .3955460  .0009218  3.0786 0.6518  P    22.368     .500    -3.368     .300  -.218000   .184000   .3997000      .000      .000  
+78 319 43586.00 I  -.210050  .012310   .167578  .004015  I  .3924463  .0009218  3.1274 0.6208  P    22.875     .500    -3.353     .300  -.220000   .188000   .3964000      .000      .000  
+78 320 43587.00 I  -.211723  .010773   .171670  .006169  I  .3892796  .0008318  3.2111 0.5882  P    23.167     .500    -3.344     .300  -.222000   .192000   .3930000      .000      .000  
+78 321 43588.00 I  -.213243  .008977   .175824  .007745  I  .3860160  .0007308  3.3191 0.5536  P    23.209     .500    -3.415     .300  -.224000   .196000   .3897000      .000      .000  
+78 322 43589.00 I  -.214610  .008977   .180039  .007745  I  .3826376  .0007308  3.4384 0.5168  P    23.155     .500    -3.539     .300  -.226000   .200000   .3864000      .000      .000  
+78 323 43590.00 I  -.215820  .008977   .184315  .007745  I  .3791411  .0007308  3.5520 0.5168  P    23.148     .500    -3.599     .300  -.228000   .204000   .3830000      .000      .000  
+78 324 43591.00 I  -.216879  .008977   .188649  .007745  I  .3755424  .0007308  3.6391 0.5168  P    23.197     .500    -3.520     .300  -.229000   .208000   .3796000      .000      .000  
+78 325 43592.00 I  -.217801  .008977   .193031  .007745  I  .3718781  .0007308  3.6804 0.4053  P    23.236     .500    -3.384     .300  -.231000   .212000   .3762000      .000      .000  
+78 326 43593.00 I  -.218600  .001138   .197451  .000868  I  .3681999  .0003505  3.6666 0.4053  P    23.223     .500    -3.352     .300  -.232000   .216000   .3728000      .000      .000  
+78 327 43594.00 I  -.219292  .001138   .201898  .000868  I  .3645615  .0003505  3.6029 0.2478  P    23.173     .500    -3.486     .300  -.234000   .220000   .3694000      .000      .000  
+78 328 43595.00 I  -.219892  .001138   .206364  .000868  I  .3610038  .0003505  3.5100 0.2975  P    23.110     .500    -3.699     .300  -.235000   .224000   .3660000      .000      .000  
+78 329 43596.00 I  -.220414  .000902   .210837  .008212  I  .3575414  .0004807  3.4175 0.2975  P    23.037     .500    -3.862     .300  -.236000   .228000   .3625000      .000      .000  
+78 330 43597.00 I  -.220871  .000902   .215307  .008212  I  .3541595  .0004807  3.3531 0.3399  P    22.950     .500    -3.926     .300  -.238000   .232000   .3591000      .000      .000  
+78 331 43598.00 I  -.221278  .000902   .219764  .008212  I  .3508197  .0004807  3.3354 0.3776  P    22.876     .500    -3.942     .300  -.239000   .236000   .3556000      .000      .000  
+78 4 1 43599.00 I  -.221646  .000576   .224195  .011581  I  .3474716  .0005825  3.3692 0.3629  P    22.887     .500    -3.972     .300  -.240000   .240000   .3522000      .000      .000  
+78 4 2 43600.00 I  -.221987  .010198   .228597  .008229  I  .3440670  .0005437  3.4459 0.3984  P    23.052     .500    -4.020     .300  -.241000   .244000   .3487000      .000      .000  
+78 4 3 43601.00 I  -.222313  .010198   .232972  .008229  I  .3405726  .0005437  3.5440 0.3700  P    23.356     .500    -4.021     .300  -.242000   .248000   .3452000      .000      .000  
+78 4 4 43602.00 I  -.222636  .014410   .237325  .001150  I  .3369818  .0005020  3.6336 0.3664  P    23.669     .500    -3.927     .300  -.242000   .253000   .3416000      .000      .000  
+78 4 5 43603.00 I  -.222965  .010405   .241659  .002529  I  .3333181  .0004912  3.6851 0.3512  P    23.827     .500    -3.797     .300  -.243000   .257000   .3381000      .000      .000  
+78 4 6 43604.00 I  -.223290  .010405   .245977  .002529  I  .3296311  .0004912  3.6782 0.3473  P    23.771     .500    -3.770     .300  -.244000   .261000   .3346000      .000      .000  
+78 4 7 43605.00 I  -.223596  .010405   .250283  .002529  I  .3259824  .0004912  3.6094 0.3435  P    23.608     .500    -3.924     .300  -.245000   .265000   .3311000      .000      .000  
+78 4 8 43606.00 I  -.223867  .002983   .254578  .003386  I  .3224283  .0004802  3.4926 0.3435  P    23.502     .500    -4.168     .300  -.245000   .269000   .3276000      .000      .000  
+78 4 9 43607.00 I  -.224091  .002983   .258862  .003386  I  .3190052  .0004802  3.3517 0.3564  P    23.503     .500    -4.332     .300  -.246000   .274000   .3240000      .000      .000  
+78 410 43608.00 I  -.224257  .010007   .263134  .004621  I  .3157250  .0005268  3.2104 0.3725  P    23.508     .500    -4.338     .300  -.246000   .278000   .3205000      .000      .000  
+78 411 43609.00 I  -.224355  .013835   .267391  .005589  I  .3125785  .0005695  3.0869 0.3879  P    23.417     .500    -4.271     .300  -.247000   .282000   .3170000      .000      .000  
+78 412 43610.00 I  -.224376  .013835   .271631  .005589  I  .3095413  .0005695  2.9932 0.4819  P    23.290     .500    -4.260     .300  -.247000   .286000   .3135000      .000      .000  
+78 413 43611.00 I  -.224308  .011313   .275854  .004613  I  .3065796  .0007776  2.9370 0.4819  P    23.284     .500    -4.351     .300  -.247000   .290000   .3101000      .000      .000  
+78 414 43612.00 I  -.224149  .011313   .280058  .004613  I  .3036531  .0007776  2.9235 0.5498  P    23.476     .500    -4.483     .300  -.248000   .293000   .3066000      .000      .000  
+78 415 43613.00 I  -.223913  .011313   .284249  .004613  I  .3007180  .0007776  2.9537 0.6102  P    23.800     .500    -4.564     .300  -.248000   .297000   .3032000      .000      .000  
+78 416 43614.00 I  -.223616  .008036   .288433  .003364  I  .2977329  .0009407  3.0222 0.5117  P    24.131     .500    -4.553     .300  -.248000   .301000   .2997000      .000      .000  
+78 417 43615.00 I  -.223270  .008171   .292613  .007570  I  .2946647  .0006652  3.1175 0.5761  P    24.361     .500    -4.511     .300  -.248000   .305000   .2964000      .000      .000  
+78 418 43616.00 I  -.222878  .008171   .296791  .007570  I  .2914932  .0006652  3.2269 0.3340  P    24.408     .500    -4.537     .300  -.248000   .309000   .2930000      .000      .000  
+78 419 43617.00 I  -.222440  .008304   .300969  .010164  I  .2882108  .0000621  3.3367 0.3340  P    24.247     .500    -4.649     .300  -.247000   .313000   .2897000      .000      .000  
+78 420 43618.00 I  -.221956  .008304   .305144  .010164  I  .2848250  .0000621  3.4308 0.1241  P    23.983     .500    -4.723     .300  -.247000   .317000   .2863000      .000      .000  
+78 421 43619.00 I  -.221413  .006931   .309310  .007190  I  .2813607  .0002404  3.4902 0.1436  P    23.805     .500    -4.626     .300  -.247000   .321000   .2830000      .000      .000  
+78 422 43620.00 I  -.220797  .006931   .313452  .007190  I  .2778616  .0002805  3.4984 0.2065  P    23.798     .500    -4.406     .300  -.246000   .325000   .2798000      .000      .000  
+78 423 43621.00 I  -.220093  .005209   .317558  .000296  I  .2743831  .0003357  3.4490 0.2187  P    23.859     .500    -4.285     .300  -.246000   .328000   .2765000      .000      .000  
+78 424 43622.00 I  -.219285  .005209   .321617  .000296  I  .2709789  .0003357  3.3537 0.2494  P    23.832     .500    -4.429     .300  -.245000   .332000   .2733000      .000      .000  
+78 425 43623.00 I  -.218367  .005209   .325616  .000296  I  .2676812  .0003689  3.2417 0.2494  P    23.689     .500    -4.757     .300  -.245000   .335000   .2700000      .000      .000  
+78 426 43624.00 I  -.217331  .005209   .329543  .000296  I  .2644895  .0003689  3.1475 0.2382  P    23.510     .500    -5.028     .300  -.244000   .339000   .2668000      .000      .000  
+78 427 43625.00 I  -.216175  .009203   .333387  .014647  I  .2613712  .0003013  3.0981 0.2074  P    23.351     .500    -5.074     .300  -.243000   .342000   .2636000      .000      .000  
+78 428 43626.00 I  -.214891  .009203   .337134  .014647  I  .2582750  .0001898  3.1034 0.1780  P    23.208     .500    -4.933     .300  -.242000   .346000   .2605000      .000      .000  
+78 429 43627.00 I  -.213476  .009203   .340775  .014647  I  .2551491  .0001898  3.1544 0.1342  P    23.102     .500    -4.758     .300  -.241000   .349000   .2573000      .000      .000  
+78 430 43628.00 I  -.211925  .009203   .344296  .014647  I  .2519580  .0001898  3.2299 0.1342  P    23.124     .500    -4.668     .300  -.240000   .353000   .2542000      .000      .000  
+78 5 1 43629.00 I  -.210242  .009203   .347698  .014647  I  .2486897  .0001898  3.3043 0.1222  P    23.344     .500    -4.669     .300  -.239000   .356000   .2510000      .000      .000  
+78 5 2 43630.00 I  -.208441  .006650   .350988  .010457  I  .2453578  .0001540  3.3536 0.1089  P    23.682     .500    -4.691     .300  -.238000   .359000   .2478000      .000      .000  
+78 5 3 43631.00 I  -.206533  .001935   .354173  .002038  I  .2419965  .0001067  3.3609 0.0937  P    23.915     .500    -4.678     .300  -.237000   .363000   .2446000      .000      .000  
+78 5 4 43632.00 I  -.204531  .001935   .357260  .002038  I  .2386522  .0001067  3.3195 0.0754  P    23.857     .500    -4.645     .300  -.235000   .366000   .2415000      .000      .000  
+78 5 5 43633.00 I  -.202448  .001935   .360257  .002038  I  .2353720  .0001067  3.2344 0.0754  P    23.555     .500    -4.642     .300  -.234000   .370000   .2383000      .000      .000  
+78 5 6 43634.00 I  -.200298  .001935   .363172  .002038  I  .2321928  .0001067  3.1211 0.3062  P    23.260     .500    -4.683     .300  -.233000   .373000   .2351000      .000      .000  
+78 5 7 43635.00 I  -.198095  .004273   .366014  .002267  I  .2291324  .0006030  3.0002 0.4264  P    23.160     .500    -4.736     .300  -.232000   .376000   .2319000      .000      .000  
+78 5 8 43636.00 I  -.195857  .005724   .368795  .002474  I  .2261885  .0008460  2.8911 0.5195  P    23.206     .500    -4.770     .300  -.230000   .380000   .2287000      .000      .000  
+78 5 9 43637.00 I  -.193599  .005724   .371523  .002474  I  .2233411  .0008460  2.8091 0.5982  P    23.250     .500    -4.800     .300  -.229000   .383000   .2256000      .000      .000  
+78 510 43638.00 I  -.191337  .005724   .374210  .002474  I  .2205588  .0008460  2.7614 0.5250  P    23.266     .500    -4.858     .300  -.227000   .387000   .2224000      .000      .000  
+78 511 43639.00 I  -.189077  .008974   .376868  .002554  I  .2178060  .0006220  2.7506 0.5250  P    23.319     .500    -4.958     .300  -.226000   .390000   .2192000      .000      .000  
+78 512 43640.00 I  -.186824  .008974   .379510  .002554  I  .2150448  .0006220  2.7780 0.3335  P    23.388     .500    -5.083     .300  -.224000   .393000   .2160000      .000      .000  
+78 513 43641.00 I  -.184585  .011327   .382150  .002630  I  .2122382  .0002408  2.8406 0.3252  P    23.402     .500    -5.189     .300  -.222000   .396000   .2128000      .000      .000  
+78 514 43642.00 I  -.182362  .008262   .384800  .005647  I  .2093543  .0001901  2.9309 0.1534  P    23.423     .500    -5.217     .300  -.220000   .399000   .2095000      .000      .000  
+78 515 43643.00 I  -.180143  .008262   .387471  .005647  I  .2063708  .0001901  3.0379 0.1330  P    23.583     .500    -5.156     .300  -.218000   .402000   .2063000      .000      .000  
+78 516 43644.00 I  -.177914  .008262   .390173  .005647  I  .2032768  .0001862  3.1499 0.1168  P    23.796     .500    -5.083     .300  -.216000   .405000   .2031000      .000      .000  
+78 517 43645.00 I  -.175657  .002870   .392915  .007541  I  .2000735  .0001357  3.2543 0.1137  P    23.764     .500    -5.088     .300  -.214000   .408000   .2000000      .000      .000  
+78 518 43646.00 I  -.173361  .004343   .395700  .008610  I  .1967754  .0001305  3.3369 0.0941  P    23.364     .500    -5.132     .300  -.212000   .410000   .1969000      .000      .000  
+78 519 43647.00 I  -.171014  .004343   .398527  .008610  I  .1934123  .0001305  3.3816 0.0948  P    22.868     .500    -5.063     .300  -.210000   .413000   .1937000      .000      .000  
+78 520 43648.00 I  -.168606  .005431   .401396  .009560  I  .1900291  .0001376  3.3757 0.0948  P    22.612     .500    -4.827     .300  -.208000   .415000   .1906000      .000      .000  
+78 521 43649.00 I  -.166125  .005431   .404308  .009560  I  .1866781  .0001376  3.3183 0.0922  P    22.600     .500    -4.609     .300  -.206000   .418000   .1875000      .000      .000  
+78 522 43650.00 I  -.163564  .005431   .407259  .009560  I  .1834043  .0001228  3.2256 0.0922  P    22.571     .500    -4.650     .300  -.203000   .420000   .1845000      .000      .000  
+78 523 43651.00 I  -.160919  .005431   .410238  .009560  I  .1802282  .0001228  3.1290 0.1416  P    22.389     .500    -4.954     .300  -.201000   .422000   .1815000      .000      .000  
+78 524 43652.00 I  -.158192  .010862   .413233  .001924  I  .1771364  .0002552  3.0621 0.1416  P    22.164     .500    -5.251     .300  -.198000   .425000   .1786000      .000      .000  
+78 525 43653.00 I  -.155381  .010862   .416231  .001924  I  .1740874  .0002552  3.0451 0.2477  P    22.028     .500    -5.291     .300  -.196000   .427000   .1756000      .000      .000  
+78 526 43654.00 I  -.152485  .010862   .419219  .001924  I  .1710302  .0004246  3.0761 0.2477  P    21.956     .500    -5.079     .300  -.193000   .429000   .1726000      .000      .000  
+78 527 43655.00 I  -.149505  .010862   .422184  .001924  I  .1679265  .0004246  3.1330 0.3341  P    21.840     .500    -4.815     .300  -.190000   .431000   .1697000      .000      .000  
+78 528 43656.00 I  -.146444  .010862   .425115  .001924  I  .1647655  .0005159  3.1858 0.4782  P    21.660     .500    -4.666     .300  -.187000   .433000   .1669000      .000      .000  
+78 529 43657.00 I  -.143321  .009179   .428001  .005834  I  .1615647  .0008569  3.2090 0.5826  P    21.518     .500    -4.663     .300  -.185000   .435000   .1640000      .000      .000  
+78 530 43658.00 I  -.140155  .007109   .430832  .008023  I  .1583622  .0010447  3.1881 0.6756  P    21.532     .500    -4.750     .300  -.182000   .437000   .1612000      .000      .000  
+78 531 43659.00 I  -.136967  .007109   .433598  .008023  I  .1552040  .0010447  3.1207 0.7713  P    21.675     .500    -4.858     .300  -.179000   .439000   .1583000      .000      .000  
+78 6 1 43660.00 I  -.133776  .007109   .436289  .008023  I  .1521349  .0011351  3.0110 0.7713  P    21.748     .500    -4.924     .300  -.176000   .440000   .1556000      .000      .000  
+78 6 2 43661.00 I  -.130589  .007109   .438906  .008023  I  .1491926  .0011351  2.8695 0.8515  P    21.568     .500    -4.905     .300  -.173000   .442000   .1530000      .000      .000  
+78 6 3 43662.00 I  -.127415  .007109   .441447  .008023  I  .1464011  .0012695  2.7122 0.5835  P    21.184     .500    -4.824     .300  -.170000   .443000   .1503000      .000      .000  
+78 6 4 43663.00 I  -.124258  .003310   .443914  .002690  I  .1437676  .0002710  2.5565 0.9577  P    20.832     .500    -4.767     .300  -.167000   .445000   .1477000      .000      .000  
+78 6 5 43664.00 I  -.121127  .008912   .446307  .002690  I  .1412826  .0014344  2.4174 0.7299  P    20.687     .500    -4.810     .300  -.164000   .446000   .1450000      .000      .000  
+78 6 6 43665.00 I  -.118027  .008912   .448625  .002690  I  .1389238  .0014344  2.3054 1.0143  P    20.735     .500    -4.938     .300  -.161000   .448000   .1424000      .000      .000  
+78 6 7 43666.00 I  -.114966  .008912   .450871  .002690  I  .1366611  .0014344  2.2257 1.0143  P    20.881     .500    -5.055     .300  -.158000   .450000   .1399000      .000      .000  
+78 6 8 43667.00 I  -.111946  .008912   .453043  .002690  I  .1344602  .0014344  2.1827 1.0143  P    21.029     .500    -5.100     .300  -.154000   .451000   .1373000      .000      .000  
+78 6 9 43668.00 I  -.108962  .008912   .455143  .002690  I  .1322833  .0014344  2.1770 0.8794  P    21.041     .500    -5.111     .300  -.151000   .453000   .1348000      .000      .000  
+78 610 43669.00 I  -.106002  .008541   .457171  .000301  I  .1300956  .0010179  2.2031 0.7198  P    20.838     .500    -5.161     .300  -.148000   .455000   .1322000      .000      .000  
+78 611 43670.00 I  -.103056  .008154   .459126  .000301  I  .1278696  .0001211  2.2517 0.5125  P    20.593     .500    -5.230     .300  -.144000   .457000   .1298000      .000      .000  
+78 612 43671.00 I  -.100114  .008154   .461011  .000301  I  .1255884  .0001211  2.3115 0.0753  P    20.612     .500    -5.220     .300  -.141000   .458000   .1274000      .000      .000  
+78 613 43672.00 I  -.097167  .006486   .462824  .001917  I  .1232466  .0000895  2.3711 0.0753  P    20.898     .500    -5.104     .300  -.137000   .460000   .1250000      .000      .000  
+78 614 43673.00 I  -.094212  .006486   .464567  .001917  I  .1208500  .0000895  2.4192 0.0633  P    21.022     .500    -4.984     .300  -.134000   .461000   .1226000      .000      .000  
+78 615 43674.00 I  -.091255  .006486   .466241  .001917  I  .1184157  .0000895  2.4446 0.0484  P    20.623     .500    -4.936     .300  -.130000   .463000   .1202000      .000      .000  
+78 616 43675.00 I  -.088300  .004203   .467846  .002695  I  .1159719  .0000370  2.4367 0.0487  P    19.883     .500    -4.882     .300  -.126000   .464000   .1179000      .000      .000  
+78 617 43676.00 I  -.085345  .003000   .469387  .002130  I  .1135555  .0000382  2.3894 0.0266  P    19.302     .500    -4.713     .300  -.122000   .466000   .1156000      .000      .000  
+78 618 43677.00 I  -.082389  .003000   .470867  .002130  I  .1112044  .0000382  2.3084 0.0274  P    19.093     .500    -4.503     .300  -.118000   .467000   .1134000      .000      .000  
+78 619 43678.00 I  -.079428  .000578   .472291  .001346  I  .1089430  .0000393  2.2146 0.0274  P    19.043     .500    -4.466     .300  -.114000   .469000   .1111000      .000      .000  
+78 620 43679.00 I  -.076459  .000578   .473663  .001346  I  .1067689  .0000393  2.1397 0.1773  P    18.901     .500    -4.663     .300  -.110000   .470000   .1088000      .000      .000  
+78 621 43680.00 I  -.073480  .000578   .474988  .001346  I  .1046477  .0003525  2.1125 0.1773  P    18.682     .500    -4.883     .300  -.106000   .471000   .1066000      .000      .000  
+78 622 43681.00 I  -.070485  .000578   .476267  .001346  I  .1025246  .0003525  2.1433 0.3638  P    18.545     .500    -4.892     .300  -.102000   .473000   .1044000      .000      .000  
+78 623 43682.00 I  -.067473  .003310   .477504  .002690  I  .1003467  .0006365  2.2175 0.2808  P    18.544     .500    -4.698     .300  -.098000   .474000   .1023000      .000      .000  
+78 624 43683.00 I  -.064438  .000423   .478702  .003672  I  .0980864  .0004371  2.3014 0.3861  P    18.553     .500    -4.502     .300  -.094000   .476000   .1001000      .000      .000  
+78 625 43684.00 I  -.061377  .000423   .479862  .003672  I  .0957528  .0004371  2.3586 0.3091  P    18.388     .500    -4.428     .300  -.090000   .477000   .0979000      .000      .000  
+78 626 43685.00 I  -.058285  .000423   .480987  .003672  I  .0933861  .0004371  2.3651 0.2686  P    17.998     .500    -4.445     .300  -.086000   .478000   .0958000      .000      .000  
+78 627 43686.00 I  -.055159  .000423   .482079  .003672  I  .0910414  .0003122  2.3153 0.2686  P    17.580     .500    -4.503     .300  -.082000   .479000   .0937000      .000      .000  
+78 628 43687.00 I  -.051996  .000423   .483137  .003672  I  .0887710  .0003122  2.2192 0.1916  P    17.420     .500    -4.616     .300  -.077000   .480000   .0916000      .000      .000  
+78 629 43688.00 I  -.048792  .000459   .484159  .002611  I  .0866126  .0002221  2.0943 0.1571  P    17.548     .500    -4.775     .300  -.073000   .481000   .0895000      .000      .000  
+78 630 43689.00 I  -.045544  .000493   .485142  .000392  I  .0845858  .0000354  1.9591 0.1125  P    17.649     .500    -4.884     .300  -.069000   .482000   .0874000      .000      .000  
+78 7 1 43690.00 I  -.042250  .000493   .486085  .000392  I  .0826924  .0000354  1.8300 0.0250  P    17.420     .500    -4.868     .300  -.065000   .483000   .0854000      .000      .000  
+78 7 2 43691.00 I  -.038905  .000493   .486984  .000392  I  .0809192  .0000354  1.7207 0.0250  P    16.936     .500    -4.798     .300  -.061000   .484000   .0834000      .000      .000  
+78 7 3 43692.00 I  -.035507  .000493   .487837  .000392  I  .0792409  .0000354  1.6418 0.1836  P    16.544     .500    -4.810     .300  -.056000   .484000   .0814000      .000      .000  
+78 7 4 43693.00 I  -.032052  .000356   .488642  .002848  I  .0776234  .0003654  1.5996 0.2584  P    16.467     .500    -4.924     .300  -.052000   .485000   .0794000      .000      .000  
+78 7 5 43694.00 I  -.028535  .000102   .489396  .004008  I  .0760289  .0005156  1.5957 0.3160  P    16.642     .500    -5.004     .300  -.048000   .486000   .0774000      .000      .000  
+78 7 6 43695.00 I  -.024953  .000102   .490096  .004008  I  .0744199  .0005156  1.6280 0.3236  P    16.858     .500    -4.940     .300  -.044000   .486000   .0755000      .000      .000  
+78 7 7 43696.00 I  -.021301  .004578   .490739  .003196  I  .0727630  .0003913  1.6900 0.3236  P    16.909     .500    -4.799     .300  -.039000   .486000   .0736000      .000      .000  
+78 7 8 43697.00 I  -.017575  .004578   .491319  .003196  I  .0710331  .0003913  1.7724 0.2767  P    16.701     .500    -4.747     .300  -.035000   .487000   .0718000      .000      .000  
+78 7 9 43698.00 I  -.013772  .004578   .491827  .003196  I  .0692151  .0003913  1.8642 0.2448  P    16.367     .500    -4.838     .300  -.030000   .487000   .0699000      .000      .000  
+78 710 43699.00 I  -.009888  .004872   .492256  .005841  I  .0673059  .0002942  1.9525 0.2448  P    16.204     .500    -4.943     .300  -.026000   .487000   .0680000      .000      .000  
+78 711 43700.00 I  -.005928  .004872   .492599  .005841  I  .0653151  .0002942  2.0257 0.1989  P    16.336     .500    -4.926     .300  -.022000   .487000   .0662000      .000      .000  
+78 712 43701.00 I  -.001900  .004483   .492850  .004874  I  .0632630  .0002677  2.0735 0.2085  P    16.474     .500    -4.807     .300  -.017000   .487000   .0644000      .000      .000  
+78 713 43702.00 I   .002188  .003031   .493007  .005784  I  .0611786  .0002955  2.0897 0.1994  P    16.214     .500    -4.703     .300  -.013000   .487000   .0626000      .000      .000  
+78 714 43703.00 I   .006322  .003031   .493071  .005784  I  .0590949  .0002955  2.0718 0.2090  P    15.538     .500    -4.648     .300  -.008000   .487000   .0608000      .000      .000  
+78 715 43704.00 I   .010492  .003031   .493048  .005784  I  .0570456  .0002955  2.0221 0.1798  P    14.839     .500    -4.581     .300  -.004000   .487000   .0590000      .000      .000  
+78 716 43705.00 I   .014681  .003580   .492942  .001737  I  .0550569  .0002049  1.9537 0.2609  P    14.448     .500    -4.503     .300   .000000   .487000   .0572000      .000      .000  
+78 717 43706.00 I   .018873  .007094   .492757  .003159  I  .0531365  .0004300  1.8903 0.3041  P    14.327     .500    -4.521     .300   .005000   .487000   .0554000      .000      .000  
+78 718 43707.00 I   .023046  .009372   .492495  .004115  I  .0512652  .0005726  1.8602 0.3580  P    14.242     .500    -4.665     .300   .009000   .486000   .0537000      .000      .000  
+78 719 43708.00 I   .027181  .009372   .492160  .004115  I  .0493981  .0005726  1.8839 0.4049  P    14.073     .500    -4.783     .300   .014000   .486000   .0519000      .000      .000  
+78 720 43709.00 I   .031258  .009372   .491754  .004115  I  .0474797  .0005726  1.9605 0.4049  P    13.895     .500    -4.718     .300   .018000   .486000   .0501000      .000      .000  
+78 721 43710.00 I   .035262  .009372   .491279  .004115  I  .0454676  .0005726  2.0655 0.3879  P    13.840     .500    -4.534     .300   .022000   .485000   .0483000      .000      .000  
+78 722 43711.00 I   .039190  .008265   .490733  .002933  I  .0433524  .0005233  2.1592 0.3715  P    13.919     .500    -4.436     .300   .027000   .485000   .0465000      .000      .000  
+78 723 43712.00 I   .043039  .006986   .490114  .000523  I  .0411655  .0004734  2.2039 0.3528  P    13.925     .500    -4.489     .300   .031000   .484000   .0447000      .000      .000  
+78 724 43713.00 I   .046808  .006986   .489419  .000523  I  .0389671  .0004734  2.1811 0.3047  P    13.607     .500    -4.548     .300   .036000   .484000   .0429000      .000      .000  
+78 725 43714.00 I   .050496  .004993   .488646  .004001  I  .0368240  .0003836  2.0964 0.3047  P    13.009     .500    -4.505     .300   .040000   .483000   .0411000      .000      .000  
+78 726 43715.00 I   .054113  .004993   .487792  .004001  I  .0347876  .0003836  1.9720 0.2564  P    12.544     .500    -4.453     .300   .044000   .482000   .0392000      .000      .000  
+78 727 43716.00 I   .057670  .006109   .486857  .003612  I  .0328847  .0003404  1.8335 0.2347  P    12.545     .500    -4.534     .300   .049000   .482000   .0374000      .000      .000  
+78 728 43717.00 I   .061179  .005619   .485838  .004408  I  .0311179  .0002706  1.7029 0.1962  P    12.822     .500    -4.719     .300   .053000   .481000   .0355000      .000      .000  
+78 729 43718.00 I   .064651  .005619   .484736  .004408  I  .0294711  .0001952  1.5955 0.1653  P    12.890     .500    -4.855     .300   .058000   .481000   .0337000      .000      .000  
+78 730 43719.00 I   .068101  .004589   .483559  .003602  I  .0279158  .0001898  1.5214 0.1359  P    12.577     .500    -4.881     .300   .062000   .480000   .0318000      .000      .000  
+78 731 43720.00 I   .071536  .005573   .482311  .001896  I  .0264152  .0001890  1.4867 0.1339  P    12.193     .500    -4.878     .300   .066000   .479000   .0298000      .000      .000  
+78 8 1 43721.00 I   .074958  .005573   .481001  .001896  I  .0249285  .0001890  1.4936 0.1143  P    12.081     .500    -4.908     .300   .071000   .478000   .0278000      .000      .000  
+78 8 2 43722.00 I   .078364  .001100   .479640  .004737  I  .0234147  .0001285  1.5403 0.1143  P    12.240     .500    -4.905     .300   .075000   .477000   .0259000      .000      .000  
+78 8 3 43723.00 I   .081753  .001100   .478236  .004737  I  .0218367  .0001285  1.6206 0.0909  P    12.449     .500    -4.785     .300   .080000   .476000   .0239000      .000      .000  
+78 8 4 43724.00 I   .085123  .001100   .476798  .004737  I  .0201654  .0001285  1.7254 0.0666  P    12.539     .500    -4.596     .300   .084000   .475000   .0219000      .000      .000  
+78 8 5 43725.00 I   .088473  .001544   .475336  .006694  I  .0183812  .0000351  1.8445 0.0666  P    12.458     .500    -4.486     .300   .088000   .474000   .0197000      .000      .000  
+78 8 6 43726.00 I   .091802  .001544   .473857  .006694  I  .0164758  .0000351  1.9654 0.1333  P    12.237     .500    -4.536     .300   .092000   .472000   .0175000      .000      .000  
+78 8 7 43727.00 I   .095104  .001520   .472363  .004827  I  .0144542  .0002642  2.0749 0.1868  P    12.007     .500    -4.668     .300   .097000   .471000   .0154000      .000      .000  
+78 8 8 43728.00 I   .098376  .001496   .470854  .001335  I  .0123337  .0003719  2.1613 0.2281  P    11.923     .500    -4.743     .300   .101000   .469000   .0132000      .000      .000  
+78 8 9 43729.00 I   .101614  .001496   .469331  .001335  I  .0101418  .0003719  2.2169 0.2630  P    11.968     .500    -4.709     .300   .105000   .468000   .0110000      .000      .000  
+78 810 43730.00 I   .104814  .001496   .467794  .001335  I  .0079106  .0003719  2.2403 0.2630  P    11.924     .500    -4.624     .300   .109000   .466000   .0087000      .000      .000  
+78 811 43731.00 I   .107971  .001496   .466245  .001335  I  .0056707  .0003719  2.2353 0.2323  P    11.626     .500    -4.563     .300   .113000   .465000   .0063000      .000      .000  
+78 812 43732.00 I   .111084  .003483   .464682  .003795  I  .0034456  .0002783  2.2134 0.1968  P    11.162     .500    -4.550     .300   .116000   .463000   .0040000      .000      .000  
+78 813 43733.00 I   .114151  .004693   .463104  .005198  I  .0012434  .0001287  2.1930 0.1533  P    10.759     .500    -4.599     .300   .120000   .462000   .0016000      .000      .000  
+78 814 43734.00 I   .117171  .004693   .461510  .005198  I -.0009488  .0001287  2.1976 0.0795  P    10.541     .500    -4.729     .300   .124000   .460000  -.0007000      .000      .000  
+78 815 43735.00 I   .120145  .003439   .459899  .004155  I -.0031673  .0000932  2.2485 0.0795  P    10.451     .500    -4.894     .300   .127000   .458000  -.0031000      .000      .000  
+78 816 43736.00 I   .123077  .003439   .458278  .004155  I -.0054643  .0000932  2.3548 0.0659  P    10.363     .500    -4.949     .300   .131000   .457000  -.0055000      .000      .000  
+78 817 43737.00 I   .125976  .003439   .456650  .004155  I -.0078913  .0000932  2.5043 0.1075  P    10.226     .500    -4.799     .300   .134000   .455000  -.0080000      .000      .000  
+78 818 43738.00 I   .128849  .000906   .455022  .002419  I -.0104762  .0001938  2.6636 0.1863  P    10.132     .500    -4.556     .300   .138000   .454000  -.0104000      .000      .000  
+78 819 43739.00 I   .131701  .000906   .453397  .002419  I -.0132074  .0003607  2.7897 0.2505  P    10.195     .500    -4.450     .300   .141000   .452000  -.0128000      .000      .000  
+78 820 43740.00 I   .134538  .000906   .451778  .002419  I -.0160330  .0004620  2.8479 0.2960  P    10.330     .500    -4.546     .300   .144000   .450000  -.0153000      .000      .000  
+78 821 43741.00 I   .137366  .000655   .450165  .002675  I -.0188762  .0004694  2.8252 0.3293  P    10.244     .500    -4.648     .300   .147000   .448000  -.0178000      .000      .000  
+78 822 43742.00 I   .140189  .000655   .448559  .002675  I -.0216605  .0004694  2.7339 0.3215  P     9.784     .500    -4.557     .300   .151000   .447000  -.0202000      .000      .000  
+78 823 43743.00 I   .143012  .002346   .446960  .002612  I -.0243301  .0004393  2.6010 0.3371  P     9.223     .500    -4.334     .300   .154000   .445000  -.0227000      .000      .000  
+78 824 43744.00 I   .145841  .002873   .445366  .002853  I -.0268586  .0004840  2.4564 0.2943  P     9.000     .500    -4.218     .300   .157000   .443000  -.0252000      .000      .000  
+78 825 43745.00 I   .148680  .002873   .443773  .002853  I -.0292468  .0003917  2.3236 0.2709  P     9.183     .500    -4.329     .300   .160000   .441000  -.0277000      .000      .000  
+78 826 43746.00 I   .151531  .002873   .442177  .002853  I -.0315147  .0002437  2.2175 0.2582  P     9.420     .500    -4.554     .300   .163000   .439000  -.0302000      .000      .000  
+78 827 43747.00 I   .154396  .005558   .440571  .001798  I -.0336935  .0003364  2.1466 0.2077  P     9.440     .500    -4.726     .300   .166000   .437000  -.0326000      .000      .000  
+78 828 43748.00 I   .157271  .005558   .438948  .001798  I -.0358210  .0003364  2.1150 0.2374  P     9.353     .500    -4.793     .300   .169000   .435000  -.0351000      .000      .000  
+78 829 43749.00 I   .160151  .006792   .437299  .000551  I -.0379363  .0003352  2.1218 0.2374  P     9.387     .500    -4.798     .300   .172000   .433000  -.0376000      .000      .000  
+78 830 43750.00 I   .163031  .006792   .435617  .000551  I -.0400759  .0003352  2.1626 0.4673  P     9.535     .500    -4.767     .300   .175000   .431000  -.0401000      .000      .000  
+78 831 43751.00 I   .165899  .005469   .433894  .007063  I -.0422703  .0008724  2.2297 0.4673  P     9.641     .500    -4.692     .300   .177000   .428000  -.0426000      .000      .000  
+78 9 1 43752.00 I   .168737  .005469   .432123  .007063  I -.0445405  .0008724  2.3122 0.7300  P     9.664     .500    -4.584     .300   .180000   .426000  -.0452000      .000      .000  
+78 9 2 43753.00 I   .171528  .003701   .430297  .009973  I -.0468958  .0011706  2.3978 0.7300  P     9.660     .500    -4.480     .300   .182000   .423000  -.0477000      .000      .000  
+78 9 3 43754.00 I   .174256  .003701   .428408  .009973  I -.0493332  .0011706  2.4746 0.8277  P     9.614     .500    -4.409     .300   .185000   .421000  -.0502000      .000      .000  
+78 9 4 43755.00 I   .176908  .003701   .426457  .009973  I -.0518383  .0011706  2.5314 0.7554  P     9.467     .500    -4.375     .300   .188000   .419000  -.0527000      .000      .000  
+78 9 5 43756.00 I   .179473  .009571   .424449  .008102  I -.0543860  .0009551  2.5581 0.6754  P     9.284     .500    -4.366     .300   .191000   .417000  -.0552000      .000      .000  
+78 9 6 43757.00 I   .181941  .013020   .422390  .005642  I -.0569425  .0006740  2.5489 0.5413  P     9.212     .500    -4.367     .300   .193000   .414000  -.0577000      .000      .000  
+78 9 7 43758.00 I   .184304  .009207   .420286  .005266  I -.0594734  .0005095  2.5086 0.4225  P     9.280     .500    -4.357     .300   .196000   .412000  -.0602000      .000      .000  
+78 9 8 43759.00 I   .186550  .009207   .418143  .005266  I -.0619536  .0005095  2.4502 0.3603  P     9.343     .500    -4.336     .300   .199000   .410000  -.0627000      .000      .000  
+78 9 9 43760.00 I   .188684  .009207   .415963  .005266  I -.0643739  .0005095  2.3923 0.3364  P     9.258     .500    -4.336     .300   .202000   .408000  -.0652000      .000      .000  
+78 910 43761.00 I   .190718  .009270   .413744  .004782  I -.0667459  .0004394  2.3575 0.2838  P     9.047     .500    -4.406     .300   .205000   .406000  -.0677000      .000      .000  
+78 911 43762.00 I   .192669  .006644   .411482  .004287  I -.0691035  .0002500  2.3666 0.2528  P     8.850     .500    -4.556     .300   .207000   .403000  -.0703000      .000      .000  
+78 912 43763.00 I   .194550  .006644   .409169  .004287  I -.0714977  .0002500  2.4316 0.1751  P     8.777     .500    -4.714     .300   .210000   .401000  -.0728000      .000      .000  
+78 913 43764.00 I   .196378  .009395   .406797  .003623  I -.0739843  .0002453  2.5495 0.1528  P     8.809     .500    -4.740     .300   .213000   .399000  -.0753000      .000      .000  
+78 914 43765.00 I   .198163  .006744   .404359  .003863  I -.0766076  .0001757  2.7001 0.1509  P     8.848     .500    -4.556     .300   .216000   .397000  -.0779000      .000      .000  
+78 915 43766.00 I   .199903  .006744   .401853  .003863  I -.0793833  .0001757  2.8472 0.0901  P     8.867     .500    -4.262     .300   .218000   .394000  -.0805000      .000      .000  
+78 916 43767.00 I   .201596  .001640   .399274  .004088  I -.0822877  .0000398  2.9513 0.0901  P     8.934     .500    -4.077     .300   .221000   .392000  -.0831000      .000      .000  
+78 917 43768.00 I   .203239  .001640   .396620  .004088  I -.0852623  .0000398  2.9845 0.0281  P     9.074     .500    -4.113     .300   .223000   .389000  -.0857000      .000      .000  
+78 918 43769.00 I   .204826  .001640   .393892  .004088  I -.0882315  .0000398  2.9420 0.2303  P     9.144     .500    -4.239     .300   .226000   .387000  -.0883000      .000      .000  
+78 919 43770.00 I   .206351  .004235   .391093  .002912  I -.0911272  .0004589  2.8421 0.3245  P     8.975     .500    -4.224     .300   .228000   .384000  -.0910000      .000      .000  
+78 920 43771.00 I   .207809  .005760   .388224  .000489  I -.0939069  .0006478  2.7158 0.3969  P     8.630     .500    -4.015     .300   .230000   .382000  -.0937000      .000      .000  
+78 921 43772.00 I   .209195  .005760   .385287  .000489  I -.0965604  .0006478  2.5943 0.4581  P     8.387     .500    -3.803     .300   .233000   .379000  -.0964000      .000      .000  
+78 922 43773.00 I   .210502  .005760   .382285  .000489  I -.0991042  .0006478  2.4990 0.4069  P     8.436     .500    -3.796     .300   .235000   .377000  -.0991000      .000      .000  
+78 923 43774.00 I   .211732  .005337   .379220  .002204  I -.1015708  .0004925  2.4410 0.4069  P     8.708     .500    -4.002     .300   .237000   .374000  -.1018000      .000      .000  
+78 924 43775.00 I   .212889  .005337   .376092  .002204  I -.1040003  .0004925  2.4254 0.2776  P     9.031     .500    -4.261     .300   .239000   .371000  -.1046000      .000      .000  
+78 925 43776.00 I   .213980  .004878   .372904  .003079  I -.1064361  .0002561  2.4533 0.2776  P     9.336     .500    -4.428     .300   .241000   .369000  -.1074000      .000      .000  
+78 926 43777.00 I   .215010  .004878   .369658  .003079  I -.1089203  .0002561  2.5213 0.2022  P     9.609     .500    -4.477     .300   .243000   .366000  -.1101000      .000      .000  
+78 927 43778.00 I   .215989  .004846   .366356  .003526  I -.1114893  .0003130  2.6210 0.2022  P     9.780     .500    -4.465     .300   .245000   .364000  -.1129000      .000      .000  
+78 928 43779.00 I   .216932  .004846   .363006  .003526  I -.1141692  .0003130  2.7412 0.2389  P     9.795     .500    -4.447     .300   .247000   .361000  -.1157000      .000      .000  
+78 929 43780.00 I   .217853  .004814   .359612  .003922  I -.1169746  .0003610  2.8699 0.2389  P     9.736     .500    -4.416     .300   .249000   .358000  -.1186000      .000      .000  
+78 930 43781.00 I   .218767  .004814   .356179  .003922  I -.1199073  .0003610  2.9936 0.2553  P     9.732     .500    -4.315     .300   .250000   .356000  -.1214000      .000      .000  
+7810 1 43782.00 I   .219684  .004814   .352717  .003922  I -.1229554  .0003610  3.0983 0.2239  P     9.780     .500    -4.097     .300   .252000   .353000  -.1243000      .000      .000  
+7810 2 43783.00 I   .220609  .007654   .349234  .006082  I -.1260928  .0002649  3.1699 0.1873  P     9.760     .500    -3.813     .300   .253000   .351000  -.1271000      .000      .000  
+7810 3 43784.00 I   .221550  .009695   .345743  .007655  I -.1292806  .0000999  3.1978 0.1416  P     9.639     .500    -3.603     .300   .255000   .348000  -.1300000      .000      .000  
+7810 4 43785.00 I   .222509  .009695   .342253  .007655  I -.1324730  .0000999  3.1796 0.0706  P     9.543     .500    -3.570     .300   .256000   .345000  -.1329000      .000      .000  
+7810 5 43786.00 I   .223491  .009695   .338774  .007655  I -.1356278  .0000999  3.1253 0.2062  P     9.593     .500    -3.671     .300   .257000   .342000  -.1359000      .000      .000  
+7810 6 43787.00 I   .224485  .007366   .335309  .005525  I -.1387186  .0004002  3.0561 0.2062  P     9.743     .500    -3.779     .300   .259000   .340000  -.1388000      .000      .000  
+7810 7 43788.00 I   .225478  .007366   .331858  .005525  I -.1417440  .0004002  2.9990 0.3429  P     9.843     .500    -3.814     .300   .260000   .337000  -.1418000      .000      .000  
+7810 8 43789.00 I   .226457  .003813   .328422  .001570  I -.1447283  .0005570  2.9770 0.3429  P     9.815     .500    -3.807     .300   .261000   .334000  -.1447000      .000      .000  
+7810 9 43790.00 I   .227409  .003813   .325001  .001570  I -.1477144  .0005570  3.0041 0.3423  P     9.738     .500    -3.821     .300   .262000   .331000  -.1477000      .000      .000  
+781010 43791.00 I   .228323  .006141   .321596  .001802  I -.1507530  .0003980  3.0808 0.3714  P     9.750     .500    -3.852     .300   .263000   .328000  -.1507000      .000      .000  
+781011 43792.00 I   .229191  .006141   .318206  .001802  I -.1538881  .0004914  3.1937 0.2966  P     9.906     .500    -3.825     .300   .263000   .324000  -.1536000      .000      .000  
+781012 43793.00 I   .230008  .007802   .314828  .002008  I -.1571436  .0004399  3.3161 0.3525  P    10.132     .500    -3.675     .300   .264000   .321000  -.1566000      .000      .000  
+781013 43794.00 I   .230768  .006157   .311463  .004014  I -.1605123  .0005055  3.4143 0.3351  P    10.314     .500    -3.432     .300   .265000   .318000  -.1596000      .000      .000  
+781014 43795.00 I   .231468  .006157   .308107  .004014  I -.1639545  .0005055  3.4592 0.3918  P    10.403     .500    -3.231     .300   .265000   .315000  -.1626000      .000      .000  
+781015 43796.00 I   .232115  .006157   .304757  .004014  I -.1674075  .0005988  3.4345 0.4855  P    10.440     .500    -3.193     .300   .266000   .311000  -.1656000      .000      .000  
+781016 43797.00 I   .232718  .003407   .301409  .009129  I -.1708012  .0008291  3.3431 0.5074  P    10.477     .500    -3.288     .300   .266000   .308000  -.1687000      .000      .000  
+781017 43798.00 I   .233283  .003407   .298057  .009129  I -.1740780  .0008193  3.2048 0.5828  P    10.514     .500    -3.351     .300   .267000   .304000  -.1717000      .000      .000  
+781018 43799.00 I   .233814  .003407   .294691  .009129  I -.1772045  .0008193  3.0477 0.6091  P    10.529     .500    -3.260     .300   .267000   .301000  -.1747000      .000      .000  
+781019 43800.00 I   .234310  .002876   .291299  .011768  I -.1801762  .0009014  2.8989 0.6091  P    10.545     .500    -3.085     .300   .267000   .297000  -.1778000      .000      .000  
+781020 43801.00 I   .234773  .002876   .287874  .011768  I -.1830117  .0009014  2.7784 0.6842  P    10.648     .500    -3.007     .300   .267000   .294000  -.1809000      .000      .000  
+781021 43802.00 I   .235200  .002056   .284417  .009204  I -.1857462  .0010296  2.6976 0.7179  P    10.924     .500    -3.116     .300   .268000   .290000  -.1839000      .000      .000  
+781022 43803.00 I   .235586  .000423   .280934  .005562  I -.1884211  .0011175  2.6593 0.8119  P    11.378     .500    -3.327     .300   .268000   .287000  -.1870000      .000      .000  
+781023 43804.00 I   .235928  .000423   .277428  .005562  I -.1910785  .0012556  2.6622 0.8404  P    11.889     .500    -3.494     .300   .268000   .283000  -.1901000      .000      .000  
+781024 43805.00 I   .236222  .000423   .273904  .005562  I -.1937577  .0012556  2.7019 0.8878  P    12.283     .500    -3.548     .300   .268000   .279000  -.1932000      .000      .000  
+781025 43806.00 I   .236463  .000423   .270369  .005562  I -.1964924  .0012556  2.7720 0.7598  P    12.465     .500    -3.521     .300   .268000   .276000  -.1963000      .000      .000  
+781026 43807.00 I   .236650  .001163   .266835  .005621  I -.1993084  .0008558  2.8622 0.6766  P    12.479     .500    -3.475     .300   .267000   .272000  -.1994000      .000      .000  
+781027 43808.00 I   .236778  .001590   .263312  .005679  I -.2022192  .0005045  2.9596 0.4967  P    12.444     .500    -3.422     .300   .267000   .269000  -.2025000      .000      .000  
+781028 43809.00 I   .236845  .001590   .259814  .005679  I -.2052260  .0005045  3.0522 0.3326  P    12.426     .500    -3.296     .300   .267000   .265000  -.2056000      .000      .000  
+781029 43810.00 I   .236847  .002330   .256349  .005552  I -.2083172  .0004335  3.1257 0.3326  P    12.414     .500    -3.017     .300   .267000   .261000  -.2087000      .000      .000  
+781030 43811.00 I   .236778  .002330   .252925  .005552  I -.2114663  .0004335  3.1660 0.3065  P    12.383     .500    -2.619     .300   .266000   .258000  -.2118000      .000      .000  
+781031 43812.00 I   .236632  .002330   .249544  .005552  I -.2146351  .0004335  3.1642 0.2541  P    12.351     .500    -2.287     .300   .266000   .254000  -.2149000      .000      .000  
+7811 1 43813.00 I   .236404  .002886   .246213  .005422  I -.2177810  .0002653  3.1215 0.2418  P    12.358     .500    -2.216     .300   .265000   .251000  -.2180000      .000      .000  
+7811 2 43814.00 I   .236086  .002886   .242932  .005422  I -.2208692  .0002145  3.0523 0.1706  P    12.415     .500    -2.416     .300   .265000   .247000  -.2211000      .000      .000  
+7811 3 43815.00 I   .235680  .002886   .239702  .005422  I -.2238856  .0002145  2.9831 0.1227  P    12.482     .500    -2.683     .300   .264000   .243000  -.2243000      .000      .000  
+7811 4 43816.00 I   .235182  .003310   .236519  .002690  I -.2268452  .0001193  2.9432 0.1227  P    12.503     .500    -2.792     .300   .264000   .240000  -.2274000      .000      .000  
+7811 5 43817.00 I   .234594  .003310   .233379  .002690  I -.2297885  .0001193  2.9526 0.0844  P    12.451     .500    -2.693     .300   .263000   .236000  -.2306000      .000      .000  
+7811 6 43818.00 I   .233914  .003310   .230281  .002690  I -.2327680  .0001193  3.0148 0.0852  P    12.373     .500    -2.499     .300   .263000   .233000  -.2337000      .000      .000  
+7811 7 43819.00 I   .233142  .003310   .227222  .002690  I -.2358311  .0001218  3.1161 0.0817  P    12.365     .500    -2.337     .300   .262000   .229000  -.2369000      .000      .000  
+7811 8 43820.00 I   .232276  .003310   .224198  .002690  I -.2390052  .0001117  3.2323 0.0826  P    12.490     .500    -2.240     .300   .261000   .225000  -.2401000      .000      .000  
+7811 9 43821.00 I   .231317  .003310   .221208  .002690  I -.2422912  .0001117  3.3350 0.1462  P    12.709     .500    -2.166     .300   .260000   .222000  -.2432000      .000      .000  
+781110 43822.00 I   .230263  .003809   .218247  .001759  I -.2456624  .0002702  3.3992 0.1462  P    12.898     .500    -2.078     .300   .259000   .218000  -.2464000      .000      .000  
+781111 43823.00 I   .229114  .003809   .215313  .001759  I -.2490712  .0002702  3.4084 0.1911  P    12.945     .500    -1.998     .300   .258000   .215000  -.2495000      .000      .000  
+781112 43824.00 I   .227870  .003809   .212404  .001759  I -.2524596  .0002702  3.3590 0.2021  P    12.853     .500    -1.978     .300   .257000   .211000  -.2527000      .000      .000  
+781113 43825.00 I   .226529  .003809   .209516  .001759  I -.2557732  .0003006  3.2615 0.2230  P    12.753     .500    -2.025     .300   .256000   .207000  -.2559000      .000      .000  
+781114 43826.00 I   .225095  .003809   .206646  .001759  I -.2589735  .0003548  3.1365 0.2325  P    12.796     .500    -2.061     .300   .255000   .204000  -.2590000      .000      .000  
+781115 43827.00 I   .223575  .003809   .203788  .001759  I -.2620454  .0003548  3.0091 0.2134  P    12.999     .500    -2.005     .300   .253000   .200000  -.2622000      .000      .000  
+781116 43828.00 I   .221976  .003310   .200937  .002690  I -.2649981  .0002374  2.9010 0.2695  P    13.240     .500    -1.876     .300   .252000   .197000  -.2653000      .000      .000  
+781117 43829.00 I   .220303  .003310   .198088  .002690  I -.2678583  .0004058  2.8257 0.1941  P    13.430     .500    -1.785     .300   .251000   .193000  -.2685000      .000      .000  
+781118 43830.00 I   .218564  .000942   .195236  .005539  I -.2706623  .0003072  2.7889 0.2545  P    13.644     .500    -1.811     .300   .249000   .190000  -.2716000      .000      .000  
+781119 43831.00 I   .216764  .000942   .192375  .005539  I -.2734491  .0003072  2.7911 0.2172  P    13.988     .500    -1.918     .300   .248000   .186000  -.2748000      .000      .000  
+781120 43832.00 I   .214912  .000942   .189501  .005539  I -.2762562  .0003072  2.8285 0.2172  P    14.399     .500    -2.012     .300   .246000   .183000  -.2779000      .000      .000  
+781121 43833.00 I   .213012  .000942   .186609  .005539  I -.2791156  .0003072  2.8943 0.2238  P    14.697     .500    -2.033     .300   .245000   .179000  -.2811000      .000      .000  
+781122 43834.00 I   .211071  .000942   .183701  .005539  I -.2820508  .0003255  2.9782 0.1784  P    14.825     .500    -1.983     .300   .243000   .176000  -.2842000      .000      .000  
+781123 43835.00 I   .209093  .000942   .180776  .005539  I -.2850740  .0001816  3.0681 0.3488  P    14.898     .500    -1.893     .300   .241000   .173000  -.2873000      .000      .000  
+781124 43836.00 I   .207082  .003725   .177839  .000902  I -.2881851  .0006169  3.1522 0.3215  P    14.978     .500    -1.794     .300   .239000   .169000  -.2904000      .000      .000  
+781125 43837.00 I   .205044  .003725   .174892  .000902  I -.2913729  .0006169  3.2199 0.4362  P    14.963     .500    -1.683     .300   .238000   .166000  -.2936000      .000      .000  
+781126 43838.00 I   .202984  .003725   .171935  .000902  I -.2946162  .0006169  3.2614 0.4362  P    14.780     .500    -1.509     .300   .236000   .162000  -.2967000      .000      .000  
+781127 43839.00 I   .200905  .003725   .168972  .000902  I -.2978839  .0006169  3.2674 0.4362  P    14.562     .500    -1.233     .300   .234000   .159000  -.2998000      .000      .000  
+781128 43840.00 I   .198815  .003725   .166005  .000902  I -.3011377  .0006169  3.2336 0.4362  P    14.505     .500     -.942     .300   .232000   .156000  -.3029000      .000      .000  
+781129 43841.00 I   .196725  .003725   .163037  .000902  I -.3043399  .0006169  3.1663 0.3369  P    14.620     .500     -.836     .300   .230000   .153000  -.3060000      .000      .000  
+781130 43842.00 I   .194646  .003310   .160071  .002690  I -.3074654  .0002710  3.0844 0.3369  P    14.744     .500    -1.024     .300   .228000   .149000  -.3091000      .000      .000  
+7812 1 43843.00 I   .192590  .003310   .157112  .002690  I -.3105135  .0002710  3.0170 0.1916  P    14.760     .500    -1.356     .300   .226000   .146000  -.3122000      .000      .000  
+7812 2 43844.00 I   .190570  .003310   .154161  .002690  I -.3135135  .0002710  2.9921 0.1728  P    14.688     .500    -1.534     .300   .224000   .143000  -.3153000      .000      .000  
+7812 3 43845.00 I   .188596  .010013   .151222  .001921  I -.3165158  .0002144  3.0217 0.1728  P    14.593     .500    -1.404     .300   .222000   .140000  -.3184000      .000      .000  
+7812 4 43846.00 I   .186681  .010013   .148300  .001921  I -.3195721  .0002144  3.0969 0.1516  P    14.513     .500    -1.082     .300   .220000   .137000  -.3214000      .000      .000  
+7812 5 43847.00 I   .184837  .010013   .145396  .001921  I -.3227160  .0002144  3.1912 0.1516  P    14.472     .500     -.795     .300   .217000   .134000  -.3245000      .000      .000  
+7812 6 43848.00 I   .183075  .010013   .142515  .001921  I -.3259501  .0002144  3.2721 0.1516  P    14.488     .500     -.663     .300   .215000   .131000  -.3275000      .000      .000  
+7812 7 43849.00 I   .181394  .010013   .139662  .001921  I -.3292471  .0002144  3.3135 0.1516  P    14.541     .500     -.656     .300   .213000   .128000  -.3306000      .000      .000  
+7812 8 43850.00 I   .179786  .010013   .136842  .001921  I -.3325594  .0002144  3.3018 0.2269  P    14.574     .500     -.707     .300   .211000   .125000  -.3336000      .000      .000  
+7812 9 43851.00 I   .178245  .003110   .134062  .002384  I -.3358331  .0004000  3.2372 0.2533  P    14.537     .500     -.785     .300   .209000   .122000  -.3366000      .000      .000  
+781210 43852.00 I   .176763  .003110   .131326  .002384  I -.3390196  .0004589  3.1300 0.3044  P    14.428     .500     -.878     .300   .206000   .120000  -.3397000      .000      .000  
+781211 43853.00 I   .175333  .003110   .128642  .002384  I -.3420848  .0004589  2.9978 0.3245  P    14.314     .500     -.945     .300   .204000   .117000  -.3427000      .000      .000  
+781212 43854.00 I   .173948  .003110   .126014  .002384  I -.3450138  .0004589  2.8613 0.3245  P    14.308     .500     -.933     .300   .202000   .114000  -.3457000      .000      .000  
+781213 43855.00 I   .172598  .003110   .123448  .002384  I -.3478125  .0004589  2.7400 0.3245  P    14.459     .500     -.835     .300   .200000   .112000  -.3487000      .000      .000  
+781214 43856.00 I   .171269  .003110   .120945  .002384  I -.3505033  .0004589  2.6473 0.3832  P    14.676     .500     -.714     .300   .198000   .109000  -.3517000      .000      .000  
+781215 43857.00 I   .169949  .003310   .118509  .002690  I -.3531192  .0006139  2.5909 0.3497  P    14.832     .500     -.651     .300   .195000   .107000  -.3547000      .000      .000  
+781216 43858.00 I   .168623  .005190   .116141  .006718  I -.3556976  .0005278  2.5721 0.4048  P    14.937     .500     -.670     .300   .193000   .104000  -.3577000      .000      .000  
+781217 43859.00 I   .167280  .005190   .113846  .006718  I -.3582751  .0005278  2.5884 0.3732  P    15.096     .500     -.727     .300   .191000   .102000  -.3607000      .000      .000  
+781218 43860.00 I   .165906  .005190   .111626  .006718  I -.3608843  .0005278  2.6342 0.3732  P    15.313     .500     -.777     .300   .189000   .100000  -.3637000      .000      .000  
+781219 43861.00 I   .164489  .005190   .109482  .006718  I -.3635510  .0005278  2.7024 0.3732  P    15.469     .500     -.805     .300   .187000   .098000  -.3667000      .000      .000  
+781220 43862.00 I   .163023  .005190   .107410  .006718  I -.3662935  .0005278  2.7839 0.3732  P    15.545     .500     -.799     .300   .184000   .096000  -.3696000      .000      .000  
+781221 43863.00 I   .161506  .005190   .105405  .006718  I -.3691193  .0005278  2.8670 0.2967  P    15.659     .500     -.740     .300   .182000   .094000  -.3726000      .000      .000  
+781222 43864.00 I   .159933  .003310   .103460  .002690  I -.3720247  .0002710  2.9416 0.2967  P    15.812     .500     -.654     .300   .180000   .092000  -.3756000      .000      .000  
+781223 43865.00 I   .158303  .003310   .101569  .002690  I -.3749969  .0002710  2.9995 0.1916  P    15.782     .500     -.608     .300   .178000   .090000  -.3786000      .000      .000  
+781224 43866.00 I   .156610  .003310   .099725  .002690  I -.3780160  .0002710  3.0344 0.1916  P    15.448     .500     -.609     .300   .176000   .088000  -.3815000      .000      .000  
+781225 43867.00 I   .154854  .003310   .097924  .002690  I -.3810565  .0002710  3.0416 0.1916  P    15.042     .500     -.554     .300   .173000   .087000  -.3845000      .000      .000  
+781226 43868.00 I   .153029  .003310   .096158  .002690  I -.3840898  .0002710  3.0207 0.5804  P    14.892     .500     -.375     .300   .171000   .085000  -.3874000      .000      .000  
+781227 43869.00 I   .151133  .000746   .094422  .009705  I -.3870918  .0011288  2.9814 0.5804  P    14.995     .500     -.196     .300   .169000   .083000  -.3904000      .000      .000  
+781228 43870.00 I   .149163  .000746   .092709  .009705  I -.3900537  .0011288  2.9453 0.7063  P    15.069     .500     -.222     .300   .167000   .082000  -.3933000      .000      .000  
+781229 43871.00 I   .147115  .000746   .091014  .009705  I -.3929930  .0008494  2.9410 0.7063  P    14.958     .500     -.461     .300   .164000   .080000  -.3962000      .000      .000  
+781230 43872.00 I   .144987  .000746   .089332  .009705  I -.3959529  .0008494  2.9883 0.6006  P    14.798     .500     -.658     .300   .162000   .079000  -.3992000      .000      .000  
+781231 43873.00 I   .142776  .000746   .087666  .009705  I -.3989868  .0008494  3.0871 0.6006  P    14.781     .500     -.583     .300   .159000   .077000  -.4021000      .000      .000  
+79 1 1 43874.00 I   .140480  .000746   .086025  .009705  I  .5978633  .0008494  3.2148 0.4248  P    14.925     .500     -.286     .300   .157000   .076000   .5950000      .000      .000  
+79 1 2 43875.00 I   .138099  .003310   .084414  .002690  I  .5945863  .0000180  3.3343 0.4248  P    15.115     .500     -.007     .300   .155000   .075000   .5921000      .000      .000  
+79 1 3 43876.00 I   .135629  .003310   .082840  .002690  I  .5912098  .0000180  3.4086 0.1358  P    15.221     .500      .113     .300   .152000   .074000   .5892000      .000      .000  
+79 1 4 43877.00 I   .133069  .003310   .081309  .002690  I  .5877910  .0002710  3.4172 0.1358  P    15.172     .500      .114     .300   .150000   .072000   .5863000      .000      .000  
+79 1 5 43878.00 I   .130417  .003310   .079829  .002690  I  .5843976  .0002710  3.3593 0.2373  P    15.003     .500      .067     .300   .147000   .071000   .5834000      .000      .000  
+79 1 6 43879.00 I   .127672  .006757   .078406  .008005  I  .5810892  .0003897  3.2510 0.2373  P    14.845     .500     -.040     .300   .145000   .070000   .5805000      .000      .000  
+79 1 7 43880.00 I   .124831  .006757   .077047  .008005  I  .5779048  .0003897  3.1151 0.2756  P    14.795     .500     -.219     .300   .143000   .069000   .5776000      .000      .000  
+79 1 8 43881.00 I   .121894  .006757   .075758  .008005  I  .5748607  .0003897  2.9740 0.2756  P    14.818     .500     -.390     .300   .140000   .068000   .5747000      .000      .000  
+79 1 9 43882.00 I   .118858  .006757   .074545  .008005  I  .5719519  .0003897  2.8474 0.2756  P    14.832     .500     -.443     .300   .138000   .067000   .5719000      .000      .000  
+79 110 43883.00 I   .115732  .006757   .073408  .008005  I  .5691563  .0003897  2.7494 0.2756  P    14.836     .500     -.374     .300   .135000   .066000   .5690000      .000      .000  
+79 111 43884.00 I   .112525  .006757   .072343  .008005  I  .5664409  .0003897  2.6879 0.2373  P    14.878     .500     -.289     .300   .133000   .065000   .5661000      .000      .000  
+79 112 43885.00 I   .109250  .003310   .071345  .002690  I  .5637676  .0002710  2.6651 0.2373  P    14.957     .500     -.277     .300   .131000   .064000   .5632000      .000      .000  
+79 113 43886.00 I   .105917  .003310   .070411  .002690  I  .5610988  .0002710  2.6781 0.1916  P    15.047     .500     -.322     .300   .128000   .063000   .5604000      .000      .000  
+79 114 43887.00 I   .102538  .003310   .069537  .002690  I  .5584014  .0002710  2.7212 0.1916  P    15.168     .500     -.362     .300   .126000   .063000   .5575000      .000      .000  
+79 115 43888.00 I   .099123  .003310   .068719  .002690  I  .5556491  .0002710  2.7864 0.1916  P    15.321     .500     -.392     .300   .123000   .062000   .5547000      .000      .000  
+79 116 43889.00 I   .095684  .003310   .067954  .002690  I  .5528245  .0002710  2.8639 0.1916  P    15.441     .500     -.450     .300   .121000   .061000   .5518000      .000      .000  
+79 117 43890.00 I   .092231  .003310   .067237  .002690  I  .5499209  .0002710  2.9425 0.1916  P    15.501     .500     -.529     .300   .118000   .060000   .5489000      .000      .000  
+79 118 43891.00 I   .088776  .003310   .066565  .002690  I  .5469430  .0002710  3.0107 0.1916  P    15.561     .500     -.563     .300   .116000   .060000   .5461000      .000      .000  
+79 119 43892.00 I   .085330  .003310   .065933  .002690  I  .5439059  .0002710  3.0596 0.1916  P    15.613     .500     -.537     .300   .113000   .059000   .5432000      .000      .000  
+79 120 43893.00 I   .081903  .003310   .065338  .002690  I  .5408321  .0002710  3.0836 0.1400  P    15.489     .500     -.541     .300   .111000   .059000   .5404000      .000      .000  
+79 121 43894.00 I   .078507  .006923   .064776  .005908  I  .5377474  .0000706  3.0814 0.1400  P    15.107     .500     -.639     .300   .108000   .058000   .5375000      .000      .000  
+79 122 43895.00 I   .075153  .006923   .064243  .005908  I  .5346777  .0000706  3.0541 0.0499  P    14.700     .500     -.733     .300   .105000   .057000   .5346000      .000      .000  
+79 123 43896.00 I   .071853  .006923   .063735  .005908  I  .5316455  .0000706  3.0081 0.0499  P    14.567     .500     -.660     .300   .102000   .057000   .5318000      .000      .000  
+79 124 43897.00 I   .068616  .006923   .063248  .005908  I  .5286629  .0000706  2.9580 0.0499  P    14.653     .500     -.448     .300   .100000   .056000   .5289000      .000      .000  
+79 125 43898.00 I   .065446  .006923   .062784  .005908  I  .5257234  .0000706  2.9264 0.0499  P    14.607     .500     -.324     .300   .097000   .056000   .5261000      .000      .000  
+79 126 43899.00 I   .062342  .006923   .062344  .005908  I  .5227957  .0000706  2.9381 0.1400  P    14.276     .500     -.433     .300   .094000   .055000   .5232000      .000      .000  
+79 127 43900.00 I   .059301  .003310   .061935  .002690  I  .5198283  .0002710  3.0067 0.1400  P    13.919     .500     -.628     .300   .091000   .055000   .5203000      .000      .000  
+79 128 43901.00 I   .056322  .003310   .061559  .002690  I  .5167664  .0002710  3.1231 0.1916  P    13.885     .500     -.664     .300   .088000   .054000   .5175000      .000      .000  
+79 129 43902.00 I   .053402  .003310   .061220  .002690  I  .5135772  .0002710  3.2541 0.2257  P    14.245     .500     -.510     .300   .085000   .054000   .5146000      .000      .000  
+79 130 43903.00 I   .050539  .001000   .060923  .004615  I  .5102684  .0003611  3.3545 0.2257  P    14.767     .500     -.354     .300   .082000   .053000   .5118000      .000      .000  
+79 131 43904.00 I   .047732  .001000   .060670  .004615  I  .5068909  .0003611  3.3869 0.2553  P    15.125     .500     -.312     .300   .079000   .053000   .5089000      .000      .000  
+79 2 1 43905.00 I   .044977  .001000   .060467  .004615  I  .5035221  .0003611  3.3368 0.2211  P    15.115     .500     -.313     .300   .076000   .053000   .5060000      .000      .000  
+79 2 2 43906.00 I   .042272  .000786   .060316  .004555  I  .5002411  .0002553  3.2154 0.2211  P    14.803     .500     -.278     .300   .073000   .053000   .5031000      .000      .000  
+79 2 3 43907.00 I   .039616  .000786   .060220  .004555  I  .4971054  .0002553  3.0519 0.1805  P    14.502     .500     -.286     .300   .070000   .052000   .5003000      .000      .000  
+79 2 4 43908.00 I   .037003  .000786   .060177  .004555  I  .4941406  .0002553  2.8786 0.1277  P    14.473     .500     -.449     .300   .067000   .052000   .4974000      .000      .000  
+79 2 5 43909.00 I   .034431  .002510   .060183  .005218  I  .4913431  .0000077  2.7208 0.1277  P    14.640     .500     -.721     .300   .064000   .052000   .4945000      .000      .000  
+79 2 6 43910.00 I   .031894  .002510   .060235  .005218  I  .4886884  .0000077  2.5950 0.0054  P    14.731     .500     -.937     .300   .061000   .052000   .4916000      .000      .000  
+79 2 7 43911.00 I   .029391  .002510   .060324  .005218  I  .4861395  .0000077  2.5099 0.0058  P    14.659     .500    -1.017     .300   .058000   .053000   .4887000      .000      .000  
+79 2 8 43912.00 I   .026917  .003516   .060443  .005852  I  .4836543  .0000088  2.4676 0.0464  P    14.607     .500    -1.030     .300   .054000   .053000   .4859000      .000      .000  
+79 2 9 43913.00 I   .024464  .004495   .060590  .004142  I  .4811906  .0000924  2.4662 0.0464  P    14.735     .500    -1.060     .300   .051000   .054000   .4830000      .000      .000  
+79 210 43914.00 I   .022021  .004495   .060766  .004142  I  .4787103  .0000924  2.4995 0.0799  P    14.988     .500    -1.092     .300   .048000   .054000   .4801000      .000      .000  
+79 211 43915.00 I   .019579  .005296   .060969  .000260  I  .4761830  .0001304  2.5587 0.0799  P    15.238     .500    -1.077     .300   .044000   .055000   .4772000      .000      .000  
+79 212 43916.00 I   .017129  .005296   .061199  .000260  I  .4735876  .0001304  2.6339 0.0922  P    15.439     .500    -1.046     .300   .041000   .055000   .4743000      .000      .000  
+79 213 43917.00 I   .014664  .005296   .061456  .000260  I  .4709136  .0001304  2.7140 0.0922  P    15.584     .500    -1.081     .300   .037000   .056000   .4714000      .000      .000  
+79 214 43918.00 I   .012186  .005296   .061739  .000260  I  .4681619  .0001304  2.7874 0.1504  P    15.645     .500    -1.193     .300   .034000   .056000   .4685000      .000      .000  
+79 215 43919.00 I   .009695  .003310   .062047  .002690  I  .4653447  .0002710  2.8431 0.1504  P    15.611     .500    -1.300     .300   .030000   .057000   .4656000      .000      .000  
+79 216 43920.00 I   .007190  .003310   .062380  .002690  I  .4624842  .0002710  2.8731 0.2580  P    15.492     .500    -1.344     .300   .026000   .058000   .4627000      .000      .000  
+79 217 43921.00 I   .004672  .001796   .062736  .000100  I  .4596078  .0004390  2.8750 0.2580  P    15.275     .500    -1.376     .300   .023000   .058000   .4598000      .000      .000  
+79 218 43922.00 I   .002142  .001796   .063115  .000100  I  .4567426  .0004390  2.8516 0.3104  P    14.975     .500    -1.477     .300   .019000   .059000   .4569000      .000      .000  
+79 219 43923.00 I  -.000401  .001796   .063517  .000100  I  .4539100  .0004390  2.8118 0.3104  P    14.755     .500    -1.605     .300   .016000   .059000   .4540000      .000      .000  
+79 220 43924.00 I  -.002956  .001796   .063940  .000100  I  .4511200  .0004390  2.7689 0.3104  P    14.791     .500    -1.625     .300   .012000   .060000   .4511000      .000      .000  
+79 221 43925.00 I  -.005524  .001796   .064384  .000100  I  .4483673  .0004390  2.7405 0.3104  P    14.998     .500    -1.509     .300   .008000   .061000   .4482000      .000      .000  
+79 222 43926.00 I  -.008108  .001796   .064848  .000100  I  .4456269  .0004390  2.7482 0.2580  P    15.060     .500    -1.412     .300   .005000   .062000   .4453000      .000      .000  
+79 223 43927.00 I  -.010711  .003310   .065332  .002690  I  .4428528  .0002710  2.8101 0.3388  P    14.807     .500    -1.483     .300   .001000   .062000   .4423000      .000      .000  
+79 224 43928.00 I  -.013336  .002521   .065834  .010697  I  .4399875  .0005162  2.9296 0.2915  P    14.447     .500    -1.657     .300  -.002000   .063000   .4394000      .000      .000  
+79 225 43929.00 I  -.015987  .002521   .066356  .010697  I  .4369807  .0005162  3.0877 0.3650  P    14.336     .500    -1.743     .300  -.006000   .064000   .4365000      .000      .000  
+79 226 43930.00 I  -.018666  .002521   .066895  .010697  I  .4338127  .0005162  3.2439 0.3650  P    14.622     .500    -1.695     .300  -.010000   .065000   .4336000      .000      .000  
+79 227 43931.00 I  -.021378  .002521   .067451  .010697  I  .4305092  .0005162  3.3512 0.3650  P    15.137     .500    -1.657     .300  -.014000   .066000   .4306000      .000      .000  
+79 228 43932.00 I  -.024122  .002521   .068028  .010697  I  .4271378  .0005162  3.3762 0.3650  P    15.544     .500    -1.728     .300  -.017000   .068000   .4277000      .000      .000  
+79 3 1 43933.00 I  -.026899  .002521   .068637  .010697  I  .4237864  .0005162  3.3125 0.2915  P    15.574     .500    -1.808     .300  -.021000   .069000   .4247000      .000      .000  
+79 3 2 43934.00 I  -.029706  .003310   .069293  .002690  I  .4205356  .0002710  3.1802 0.2772  P    15.252     .500    -1.774     .300  -.025000   .070000   .4218000      .000      .000  
+79 3 3 43935.00 I  -.032543  .003063   .070009  .006290  I  .4174369  .0002023  3.0150 0.1691  P    14.917     .500    -1.692     .300  -.029000   .072000   .4189000      .000      .000  
+79 3 4 43936.00 I  -.035406  .003063   .070797  .006290  I  .4145046  .0002023  2.8527 0.1430  P    14.896     .500    -1.750     .300  -.032000   .073000   .4159000      .000      .000  
+79 3 5 43937.00 I  -.038296  .003063   .071672  .006290  I  .4117220  .0002023  2.7191 0.1551  P    15.130     .500    -2.004     .300  -.036000   .075000   .4130000      .000      .000  
+79 3 6 43938.00 I  -.041208  .003977   .072647  .009776  I  .4090524  .0002352  2.6277 0.1551  P    15.287     .500    -2.314     .300  -.039000   .076000   .4100000      .000      .000  
+79 3 7 43939.00 I  -.044139  .003977   .073730  .009776  I  .4064513  .0002352  2.5823 0.1663  P    15.239     .500    -2.529     .300  -.043000   .078000   .4071000      .000      .000  
+79 3 8 43940.00 I  -.047081  .003977   .074925  .009776  I  .4038728  .0002352  2.5819 0.1737  P    15.231     .500    -2.627     .300  -.046000   .080000   .4041000      .000      .000  
+79 3 9 43941.00 I  -.050025  .004716   .076239  .012312  I  .4012742  .0002556  2.6215 0.1737  P    15.501     .500    -2.654     .300  -.050000   .082000   .4012000      .000      .000  
+79 310 43942.00 I  -.052969  .004716   .077670  .012312  I  .3986191  .0002556  2.6933 0.1807  P    15.948     .500    -2.622     .300  -.053000   .083000   .3982000      .000      .000  
+79 311 43943.00 I  -.055911  .004716   .079210  .012312  I  .3958803  .0002556  2.7869 0.1863  P    16.305     .500    -2.525     .300  -.057000   .085000   .3953000      .000      .000  
+79 312 43944.00 I  -.058854  .003310   .080847  .002690  I  .3930421  .0002710  2.8900 0.6688  P    16.484     .500    -2.410     .300  -.060000   .087000   .3923000      .000      .000  
+79 313 43945.00 I  -.061800  .008930   .082570  .000884  I  .3901010  .0013130  2.9909 0.6703  P    16.567     .500    -2.360     .300  -.063000   .089000   .3893000      .000      .000  
+79 314 43946.00 I  -.064750  .008930   .084368  .000884  I  .3870650  .0013130  3.0778 0.9284  P    16.592     .500    -2.402     .300  -.066000   .091000   .3863000      .000      .000  
+79 315 43947.00 I  -.067704  .008930   .086231  .000884  I  .3839535  .0013130  3.1403 0.9284  P    16.514     .500    -2.489     .300  -.070000   .093000   .3834000      .000      .000  
+79 316 43948.00 I  -.070664  .008930   .088147  .000884  I  .3807956  .0013130  3.1692 0.9284  P    16.332     .500    -2.572     .300  -.073000   .095000   .3804000      .000      .000  
+79 317 43949.00 I  -.073618  .008930   .090106  .000884  I  .3776271  .0013130  3.1620 0.9284  P    16.126     .500    -2.654     .300  -.076000   .097000   .3774000      .000      .000  
+79 318 43950.00 I  -.076549  .008930   .092098  .000884  I  .3744811  .0013130  3.1263 0.6697  P    15.965     .500    -2.761     .300  -.079000   .099000   .3744000      .000      .000  
+79 319 43951.00 I  -.079444  .010706   .094114  .008790  I  .3713788  .0002644  3.0778 0.6697  P    15.904     .500    -2.874     .300  -.082000   .101000   .3714000      .000      .000  
+79 320 43952.00 I  -.082286  .010706   .096143  .008790  I  .3683230  .0002644  3.0367 0.1708  P    15.990     .500    -2.939     .300  -.084000   .104000   .3683000      .000      .000  
+79 321 43953.00 I  -.085059  .008098   .098177  .006523  I  .3652961  .0002163  3.0235 0.1708  P    16.209     .500    -2.944     .300  -.087000   .106000   .3653000      .000      .000  
+79 322 43954.00 I  -.087749  .008098   .100204  .006523  I  .3622606  .0002163  3.0563 0.1529  P    16.442     .500    -2.956     .300  -.090000   .108000   .3623000      .000      .000  
+79 323 43955.00 I  -.090350  .008098   .102221  .006523  I  .3591650  .0002163  3.1445 0.1529  P    16.574     .500    -3.034     .300  -.093000   .110000   .3592000      .000      .000  
+79 324 43956.00 I  -.092865  .008098   .104229  .006523  I  .3559556  .0002163  3.2808 0.1327  P    16.610     .500    -3.124     .300  -.096000   .113000   .3562000      .000      .000  
+79 325 43957.00 I  -.095296  .004064   .106231  .002797  I  .3525963  .0001538  3.4382 0.4103  P    16.648     .500    -3.117     .300  -.098000   .115000   .3531000      .000      .000  
+79 326 43958.00 I  -.097642  .004889   .108233  .002308  I  .3490860  .0007915  3.5750 0.5597  P    16.753     .500    -3.014     .300  -.101000   .118000   .3501000      .000      .000  
+79 327 43959.00 I  -.099898  .005593   .110239  .001682  I  .3454675  .0011088  3.6483 0.6812  P    16.895     .500    -2.964     .300  -.104000   .120000   .3470000      .000      .000  
+79 328 43960.00 I  -.102064  .005593   .112255  .001682  I  .3418196  .0011088  3.6312 0.7840  P    16.969     .500    -3.080     .300  -.106000   .123000   .3439000      .000      .000  
+79 329 43961.00 I  -.104136  .005593   .114286  .001682  I  .3382344  .0011088  3.5262 0.7840  P    16.872     .500    -3.273     .300  -.109000   .125000   .3409000      .000      .000  
+79 330 43962.00 I  -.106120  .005593   .116336  .001682  I  .3347871  .0011088  3.3615 0.7840  P    16.630     .500    -3.355     .300  -.111000   .128000   .3378000      .000      .000  
+79 331 43963.00 I  -.108024  .005593   .118409  .001682  I  .3315186  .0011088  3.1751 0.5707  P    16.440     .500    -3.290     .300  -.114000   .130000   .3348000      .000      .000  
+79 4 1 43964.00 I  -.109856  .003310   .120506  .002690  I  .3284323  .0002710  3.0024 0.5853  P    16.487     .500    -3.238     .300  -.116000   .133000   .3317000      .000      .000  
+79 4 2 43965.00 I  -.111624  .004700   .122632  .003826  I  .3255016  .0003754  2.8664 0.2315  P    16.698     .500    -3.352     .300  -.118000   .136000   .3286000      .000      .000  
+79 4 3 43966.00 I  -.113335  .004700   .124790  .003826  I  .3226839  .0003754  2.7773 0.2654  P    16.815     .500    -3.605     .300  -.120000   .139000   .3255000      .000      .000  
+79 4 4 43967.00 I  -.114998  .004700   .126982  .003826  I  .3199310  .0003754  2.7364 0.2654  P    16.762     .500    -3.853     .300  -.123000   .141000   .3223000      .000      .000  
+79 4 5 43968.00 I  -.116619  .004700   .129213  .003826  I  .3171962  .0003754  2.7404 0.2654  P    16.775     .500    -3.993     .300  -.125000   .144000   .3192000      .000      .000  
+79 4 6 43969.00 I  -.118202  .004700   .131482  .003826  I  .3144374  .0003754  2.7830 0.2447  P    17.069     .500    -4.014     .300  -.127000   .147000   .3161000      .000      .000  
+79 4 7 43970.00 I  -.119746  .004700   .133788  .003826  I  .3116208  .0003141  2.8539 0.2407  P    17.518     .500    -3.947     .300  -.129000   .150000   .3130000      .000      .000  
+79 4 8 43971.00 I  -.121251  .003106   .136129  .000016  I  .3087243  .0003015  2.9407 0.2177  P    17.817     .500    -3.826     .300  -.131000   .153000   .3099000      .000      .000  
+79 4 9 43972.00 I  -.122714  .003106   .138504  .000016  I  .3057383  .0003015  3.0308 0.2132  P    17.856     .500    -3.697     .300  -.133000   .155000   .3068000      .000      .000  
+79 410 43973.00 I  -.124135  .003106   .140910  .000016  I  .3026656  .0003015  3.1123 0.2132  P    17.769     .500    -3.594     .300  -.135000   .158000   .3037000      .000      .000  
+79 411 43974.00 I  -.125512  .003106   .143345  .000016  I  .2995202  .0003015  3.1743 0.2728  P    17.678     .500    -3.526     .300  -.137000   .161000   .3006000      .000      .000  
+79 412 43975.00 I  -.126849  .003106   .145809  .000016  I  .2963268  .0004548  3.2068 0.3663  P    17.569     .500    -3.504     .300  -.139000   .164000   .2975000      .000      .000  
+79 413 43976.00 I  -.128150  .003106   .148298  .000016  I  .2931183  .0006677  3.2042 0.5035  P    17.426     .500    -3.558     .300  -.141000   .166000   .2943000      .000      .000  
+79 414 43977.00 I  -.129419  .003310   .150811  .002690  I  .2899290  .0008985  3.1698 0.4876  P    17.309     .500    -3.702     .300  -.142000   .169000   .2912000      .000      .000  
+79 415 43978.00 I  -.130661  .004198   .153347  .002319  I  .2867850  .0007109  3.1164 0.5729  P    17.260     .500    -3.888     .300  -.144000   .171000   .2880000      .000      .000  
+79 416 43979.00 I  -.131882  .004198   .155903  .002319  I  .2836958  .0007109  3.0640 0.5027  P    17.229     .500    -4.029     .300  -.146000   .174000   .2849000      .000      .000  
+79 417 43980.00 I  -.133085  .004198   .158477  .002319  I  .2806490  .0007109  3.0354 0.4443  P    17.165     .500    -4.083     .300  -.148000   .177000   .2818000      .000      .000  
+79 418 43981.00 I  -.134274  .003059   .161067  .002158  I  .2776110  .0005331  3.0486 0.3960  P    17.119     .500    -4.081     .300  -.149000   .179000   .2787000      .000      .000  
+79 419 43982.00 I  -.135449  .003059   .163669  .002158  I  .2745349  .0003493  3.1123 0.3187  P    17.205     .500    -4.086     .300  -.151000   .182000   .2755000      .000      .000  
+79 420 43983.00 I  -.136606  .003059   .166279  .002158  I  .2713707  .0003493  3.2229 0.1779  P    17.483     .500    -4.111     .300  -.152000   .184000   .2724000      .000      .000  
+79 421 43984.00 I  -.137741  .002933   .168891  .004908  I  .2680793  .0000678  3.3628 0.1779  P    17.885     .500    -4.101     .300  -.154000   .187000   .2693000      .000      .000  
+79 422 43985.00 I  -.138853  .002933   .171502  .004908  I  .2646455  .0000678  3.5016 0.0479  P    18.239     .500    -3.988     .300  -.155000   .190000   .2662000      .000      .000  
+79 423 43986.00 I  -.139941  .002933   .174110  .004908  I  .2610886  .0000678  3.6027 0.3528  P    18.370     .500    -3.795     .300  -.157000   .192000   .2631000      .000      .000  
+79 424 43987.00 I  -.141004  .005579   .176715  .006599  I  .2574631  .0007023  3.6346 0.3528  P    18.217     .500    -3.659     .300  -.158000   .195000   .2601000      .000      .000  
+79 425 43988.00 I  -.142046  .005579   .179318  .006599  I  .2538475  .0007023  3.5823 0.4966  P    17.874     .500    -3.714     .300  -.160000   .197000   .2570000      .000      .000  
+79 426 43989.00 I  -.143074  .005579   .181927  .006599  I  .2503237  .0007023  3.4544 0.6068  P    17.521     .500    -3.929     .300  -.161000   .200000   .2539000      .000      .000  
+79 427 43990.00 I  -.144092  .006793   .184548  .006546  I  .2469541  .0009898  3.2804 0.4967  P    17.320     .500    -4.122     .300  -.162000   .203000   .2506000      .000      .000  
+79 428 43991.00 I  -.145100  .005079   .187182  .004675  I  .2437655  .0007025  3.0986 0.6069  P    17.344     .500    -4.153     .300  -.163000   .205000   .2473000      .000      .000  
+79 429 43992.00 I  -.146089  .005079   .189825  .004675  I  .2407493  .0007025  2.9397 0.3539  P    17.534     .500    -4.077     .300  -.164000   .208000   .2440000      .000      .000  
+79 430 43993.00 I  -.147054  .002334   .192477  .000929  I  .2378725  .0000862  2.8217 0.3539  P    17.721     .500    -4.064     .300  -.165000   .210000   .2407000      .000      .000  
+79 5 1 43994.00 I  -.147988  .002334   .195134  .000929  I  .2350903  .0000862  2.7506 0.0610  P    17.755     .500    -4.198     .300  -.142000   .213000   .2374000      .000      .000  
+79 5 2 43995.00 I  -.148886  .002334   .197796  .000929  I  .2323562  .0000862  2.7248 0.0610  P    17.658     .500    -4.409     .300  -.143000   .215000   .2344000      .000      .000  
+79 5 3 43996.00 I  -.149745  .002334   .200461  .000929  I  .2296276  .0000862  2.7383 0.2460  P    17.615     .500    -4.573     .300  -.143000   .218000   .2314000      .000      .000  
+79 5 4 43997.00 I  -.150564  .003310   .203128  .002690  I  .2268695  .0004843  2.7822 0.1781  P    17.765     .500    -4.628     .300  -.144000   .220000   .2283000      .000      .000  
+79 5 5 43998.00 I  -.151339  .001531   .205796  .000143  I  .2240570  .0003456  2.8447 0.2915  P    18.027     .500    -4.594     .300  -.144000   .223000   .2253000      .000      .000  
+79 5 6 43999.00 I  -.152070  .001531   .208464  .000143  I  .2211782  .0003245  2.9127 0.2489  P    18.196     .500    -4.521     .300  -.145000   .225000   .2223000      .000      .000  
+79 5 7 44000.00 I  -.152753  .001531   .211131  .000143  I  .2182336  .0003584  2.9745 0.2417  P    18.152     .500    -4.440     .300  -.145000   .227000   .2194000      .000      .000  
+79 5 8 44001.00 I  -.153387  .001531   .213797  .000143  I  .2152346  .0003584  3.0199 0.2534  P    17.938     .500    -4.343     .300  -.146000   .230000   .2164000      .000      .000  
+79 5 9 44002.00 I  -.153973  .001531   .216460  .000143  I  .2122023  .0003584  3.0398 0.2433  P    17.668     .500    -4.200     .300  -.146000   .232000   .2135000      .000      .000  
+79 510 44003.00 I  -.154510  .001531   .219120  .000143  I  .2091655  .0003292  3.0282 0.3234  P    17.430     .500    -4.039     .300  -.147000   .235000   .2105000      .000      .000  
+79 511 44004.00 I  -.154999  .000312   .221774  .002626  I  .2061571  .0005385  2.9830 0.3439  P    17.280     .500    -3.969     .300  -.147000   .237000   .2076000      .000      .000  
+79 512 44005.00 I  -.155442  .000312   .224422  .002626  I  .2032085  .0006039  2.9106 0.4196  P    17.239     .500    -4.081     .300  -.147000   .239000   .2047000      .000      .000  
+79 513 44006.00 I  -.155839  .000312   .227063  .002626  I  .2003390  .0006437  2.8287 0.4413  P    17.267     .500    -4.329     .300  -.148000   .242000   .2019000      .000      .000  
+79 514 44007.00 I  -.156190  .000312   .229696  .002626  I  .1975461  .0006437  2.7619 0.3991  P    17.257     .500    -4.539     .300  -.148000   .244000   .1990000      .000      .000  
+79 515 44008.00 I  -.156498  .000222   .232317  .002459  I  .1948025  .0004720  2.7332 0.3991  P    17.119     .500    -4.575     .300  -.149000   .247000   .1962000      .000      .000  
+79 516 44009.00 I  -.156760  .000222   .234922  .002459  I  .1920627  .0004720  2.7555 0.2673  P    16.876     .500    -4.455     .300  -.149000   .249000   .1933000      .000      .000  
+79 517 44010.00 I  -.156979  .001591   .237507  .007610  I  .1892751  .0002512  2.8271 0.2673  P    16.676     .500    -4.300     .300  -.149000   .251000   .1905000      .000      .000  
+79 518 44011.00 I  -.157154  .001591   .240066  .007610  I  .1863978  .0002512  2.9307 0.1776  P    16.693     .500    -4.203     .300  -.149000   .253000   .1878000      .000      .000  
+79 519 44012.00 I  -.157284  .001591   .242593  .007610  I  .1834122  .0002512  3.0386 0.1776  P    16.984     .500    -4.158     .300  -.149000   .256000   .1850000      .000      .000  
+79 520 44013.00 I  -.157372  .001591   .245080  .007610  I  .1803290  .0002512  3.1211 0.1970  P    17.407     .500    -4.098     .300  -.149000   .258000   .1823000      .000      .000  
+79 521 44014.00 I  -.157415  .001962   .247523  .007616  I  .1771873  .0003035  3.1516 0.1970  P    17.678     .500    -3.985     .300  -.149000   .260000   .1795000      .000      .000  
+79 522 44015.00 I  -.157410  .001962   .249924  .007616  I  .1740488  .0003035  3.1133 0.2128  P    17.565     .500    -3.866     .300  -.149000   .262000   .1768000      .000      .000  
+79 523 44016.00 I  -.157353  .001625   .252291  .002321  I  .1709837  .0002984  3.0062 0.2128  P    17.079     .500    -3.841     .300  -.149000   .264000   .1742000      .000      .000  
+79 524 44017.00 I  -.157240  .001625   .254629  .002321  I  .1680538  .0002984  2.8470 0.2110  P    16.499     .500    -3.953     .300  -.149000   .267000   .1715000      .000      .000  
+79 525 44018.00 I  -.157071  .001625   .256943  .002321  I  .1652975  .0002984  2.6643 0.3381  P    16.161     .500    -4.121     .300  -.149000   .269000   .1689000      .000      .000  
+79 526 44019.00 I  -.156842  .002407   .259234  .002062  I  .1627230  .0006069  2.4881 0.4291  P    16.197     .500    -4.217     .300  -.149000   .271000   .1662000      .000      .000  
+79 527 44020.00 I  -.156555  .002991   .261507  .001764  I  .1603115  .0008047  2.3412 0.5040  P    16.450     .500    -4.209     .300  -.149000   .273000   .1637000      .000      .000  
+79 528 44021.00 I  -.156206  .002991   .263765  .001764  I  .1580270  .0008047  2.2350 0.5575  P    16.656     .500    -4.185     .300  -.149000   .275000   .1611000      .000      .000  
+79 529 44022.00 I  -.155797  .002821   .266011  .001362  I  .1558269  .0007719  2.1725 0.5575  P    16.690     .500    -4.236     .300  -.148000   .278000   .1586000      .000      .000  
+79 530 44023.00 I  -.155330  .002821   .268245  .001362  I  .1536684  .0007719  2.1509 0.5458  P    16.608     .500    -4.356     .300  -.148000   .280000   .1560000      .000      .000  
+79 531 44024.00 I  -.154810  .002821   .270470  .001362  I  .1515140  .0007719  2.1627 0.5339  P    16.509     .500    -4.476     .300  -.148000   .282000   .1535000      .000      .000  
+79 6 1 44025.00 I  -.154242  .002639   .272685  .000771  I  .1493351  .0007377  2.1983 0.5339  P    16.445     .500    -4.546     .300  -.147000   .284000   .1511000      .000      .000  
+79 6 2 44026.00 I  -.153628  .002639   .274892  .000771  I  .1471131  .0007377  2.2470 0.5216  P    16.437     .500    -4.562     .300  -.147000   .286000   .1486000      .000      .000  
+79 6 3 44027.00 I  -.152969  .002639   .277094  .000771  I  .1448408  .0007377  2.2968 0.3930  P    16.474     .500    -4.542     .300  -.146000   .289000   .1462000      .000      .000  
+79 6 4 44028.00 I  -.152263  .003310   .279291  .002690  I  .1425226  .0002710  2.3373 0.4250  P    16.448     .500    -4.499     .300  -.146000   .291000   .1437000      .000      .000  
+79 6 5 44029.00 I  -.151511  .003310   .281486  .002690  I  .1401719  .0004222  2.3607 0.3096  P    16.196     .500    -4.419     .300  -.145000   .293000   .1413000      .000      .000  
+79 6 6 44030.00 I  -.150712  .003618   .283680  .001226  I  .1378086  .0005568  2.3620 0.3494  P    15.694     .500    -4.266     .300  -.144000   .295000   .1389000      .000      .000  
+79 6 7 44031.00 I  -.149866  .003618   .285876  .001226  I  .1354564  .0005568  2.3380 0.3937  P    15.157     .500    -4.032     .300  -.143000   .298000   .1365000      .000      .000  
+79 6 8 44032.00 I  -.148972  .003618   .288076  .001226  I  .1331408  .0005568  2.2894 0.3937  P    14.844     .500    -3.813     .300  -.142000   .300000   .1341000      .000      .000  
+79 6 9 44033.00 I  -.148031  .003618   .290280  .001226  I  .1308829  .0005568  2.2248 0.3937  P    14.802     .500    -3.765     .300  -.141000   .303000   .1317000      .000      .000  
+79 610 44034.00 I  -.147047  .003618   .292494  .001226  I  .1286901  .0005568  2.1634 0.4116  P    14.870     .500    -3.941     .300  -.140000   .305000   .1293000      .000      .000  
+79 611 44035.00 I  -.146027  .003618   .294720  .001226  I  .1265461  .0006064  2.1320 0.3350  P    14.886     .500    -4.183     .300  -.139000   .307000   .1270000      .000      .000  
+79 612 44036.00 I  -.144979  .001747   .296961  .005060  I  .1244090  .0003725  2.1519 0.3643  P    14.804     .500    -4.255     .300  -.138000   .310000   .1246000      .000      .000  
+79 613 44037.00 I  -.143907  .001747   .299222  .005060  I  .1222235  .0004038  2.2280 0.2747  P    14.634     .500    -4.078     .300  -.137000   .312000   .1223000      .000      .000  
+79 614 44038.00 I  -.142819  .001747   .301505  .005060  I  .1199394  .0004038  2.3447 0.2855  P    14.393     .500    -3.792     .300  -.136000   .315000   .1199000      .000      .000  
+79 615 44039.00 I  -.141721  .001747   .303814  .005060  I  .1175309  .0004038  2.4711 0.2855  P    14.146     .500    -3.603     .300  -.135000   .317000   .1176000      .000      .000  
+79 616 44040.00 I  -.140619  .001747   .306150  .005060  I  .1150055  .0004038  2.5727 0.2855  P    14.028     .500    -3.593     .300  -.134000   .319000   .1154000      .000      .000  
+79 617 44041.00 I  -.139515  .001747   .308510  .005060  I  .1124028  .0004038  2.6226 0.2438  P    14.118     .500    -3.693     .300  -.133000   .321000   .1131000      .000      .000  
+79 618 44042.00 I  -.138413  .003956   .310891  .003754  I  .1097815  .0002732  2.6090 0.2090  P    14.316     .500    -3.789     .300  -.132000   .324000   .1109000      .000      .000  
+79 619 44043.00 I  -.137315  .003956   .313290  .003754  I  .1072050  .0001084  2.5348 0.1470  P    14.369     .500    -3.826     .300  -.131000   .326000   .1086000      .000      .000  
+79 620 44044.00 I  -.136226  .003956   .315703  .003754  I  .1047273  .0001084  2.4145 0.0767  P    14.079     .500    -3.828     .300  -.130000   .328000   .1064000      .000      .000  
+79 621 44045.00 I  -.135149  .003956   .318127  .003754  I  .1023839  .0001084  2.2707 0.0666  P    13.513     .500    -3.851     .300  -.129000   .330000   .1042000      .000      .000  
+79 622 44046.00 I  -.134082  .003280   .320558  .005181  I  .1001851  .0000773  2.1294 0.0666  P    12.983     .500    -3.917     .300  -.128000   .332000   .1020000      .000      .000  
+79 623 44047.00 I  -.133023  .003280   .322987  .005181  I  .0981170  .0000773  2.0124 0.0393  P    12.767     .500    -4.005     .300  -.126000   .335000   .0997000      .000      .000  
+79 624 44048.00 I  -.131967  .002422   .325406  .006292  I  .0961475  .0000140  1.9337 0.0393  P    12.865     .500    -4.084     .300  -.125000   .337000   .0975000      .000      .000  
+79 625 44049.00 I  -.130909  .002422   .327807  .006292  I  .0942354  .0000140  1.8975 0.0899  P    13.061     .500    -4.139     .300  -.124000   .339000   .0953000      .000      .000  
+79 626 44050.00 I  -.129846  .002407   .330183  .004512  I  .0923394  .0001792  1.9007 0.0899  P    13.187     .500    -4.159     .300  -.123000   .341000   .0932000      .000      .000  
+79 627 44051.00 I  -.128778  .002407   .332535  .004512  I  .0904232  .0001792  1.9364 0.1551  P    13.209     .500    -4.140     .300  -.122000   .343000   .0910000      .000      .000  
+79 628 44052.00 I  -.127706  .002392   .334862  .001059  I  .0884588  .0002531  1.9954 0.1551  P    13.114     .500    -4.110     .300  -.120000   .345000   .0889000      .000      .000  
+79 629 44053.00 I  -.126628  .002392   .337163  .001059  I  .0864284  .0002531  2.0663 0.1559  P    12.886     .500    -4.119     .300  -.119000   .347000   .0867000      .000      .000  
+79 630 44054.00 I  -.125542  .002155   .339439  .000950  I  .0843264  .0001821  2.1365 0.1559  P    12.635     .500    -4.176     .300  -.118000   .349000   .0846000      .000      .000  
+79 7 1 44055.00 I  -.124442  .002155   .341688  .000950  I  .0821596  .0001821  2.1941 0.0941  P    12.542     .500    -4.232     .300  -.117000   .351000   .0825000      .000      .000  
+79 7 2 44056.00 I  -.123326  .001888   .343909  .000826  I  .0799453  .0000477  2.2306 0.0941  P    12.554     .500    -4.237     .300  -.116000   .353000   .0805000      .000      .000  
+79 7 3 44057.00 I  -.122188  .001888   .346100  .000826  I  .0777069  .0000477  2.2417 0.0337  P    12.335     .500    -4.194     .300  -.114000   .355000   .0784000      .000      .000  
+79 7 4 44058.00 I  -.121023  .001888   .348261  .000826  I  .0754707  .0000477  2.2263 0.0337  P    11.678     .500    -4.108     .300  -.113000   .357000   .0764000      .000      .000  
+79 7 5 44059.00 I  -.119823  .001888   .350392  .000826  I  .0732628  .0000477  2.1852 0.0244  P    10.853     .500    -3.942     .300  -.112000   .359000   .0743000      .000      .000  
+79 7 6 44060.00 I  -.118580  .003037   .352492  .002178  I  .0711070  .0000099  2.1238 0.0244  P    10.345     .500    -3.697     .300  -.111000   .361000   .0723000      .000      .000  
+79 7 7 44061.00 I  -.117286  .003037   .354562  .002178  I  .0690175  .0000099  2.0555 0.0070  P    10.295     .500    -3.506     .300  -.109000   .363000   .0703000      .000      .000  
+79 7 8 44062.00 I  -.115933  .003037   .356601  .002178  I  .0669908  .0000099  2.0028 0.0070  P    10.425     .500    -3.526     .300  -.108000   .364000   .0684000      .000      .000  
+79 7 9 44063.00 I  -.114514  .003037   .358609  .002178  I  .0649984  .0000099  1.9908 0.0070  P    10.456     .500    -3.727     .300  -.106000   .366000   .0664000      .000      .000  
+79 710 44064.00 I  -.113023  .003037   .360584  .002178  I  .0629905  .0000099  2.0351 0.2899  P    10.384     .500    -3.876     .300  -.105000   .368000   .0644000      .000      .000  
+79 711 44065.00 I  -.111458  .002152   .362525  .002131  I  .0609115  .0005797  2.1296 0.4099  P    10.318     .500    -3.790     .300  -.103000   .370000   .0624000      .000      .000  
+79 712 44066.00 I  -.109817  .000193   .364427  .002082  I  .0587243  .0008197  2.2451 0.5020  P    10.231     .500    -3.546     .300  -.101000   .371000   .0605000      .000      .000  
+79 713 44067.00 I  -.108098  .000193   .366288  .002082  I  .0564281  .0008197  2.3401 0.5796  P    10.016     .500    -3.371     .300  -.100000   .373000   .0585000      .000      .000  
+79 714 44068.00 I  -.106300  .000193   .368105  .002082  I  .0540628  .0008197  2.3790 0.5796  P     9.674     .500    -3.389     .300  -.098000   .374000   .0566000      .000      .000  
+79 715 44069.00 I  -.104419  .000193   .369877  .002082  I  .0516943  .0008197  2.3452 0.5796  P     9.359     .500    -3.533     .300  -.096000   .376000   .0546000      .000      .000  
+79 716 44070.00 I  -.102454  .000193   .371605  .002082  I  .0493954  .0008197  2.2423 0.4196  P     9.234     .500    -3.688     .300  -.094000   .377000   .0527000      .000      .000  
+79 717 44071.00 I  -.100404  .005905   .373287  .005117  I  .0472259  .0001794  2.0909 0.4196  P     9.299     .500    -3.811     .300  -.092000   .379000   .0507000      .000      .000  
+79 718 44072.00 I  -.098267  .005905   .374923  .005117  I  .0452206  .0001794  1.9187 0.1269  P     9.356     .500    -3.913     .300  -.090000   .380000   .0488000      .000      .000  
+79 719 44073.00 I  -.096040  .005905   .376514  .005117  I  .0433866  .0001794  1.7523 0.1269  P     9.183     .500    -3.994     .300  -.088000   .382000   .0468000      .000      .000  
+79 720 44074.00 I  -.093725  .005905   .378060  .005117  I  .0417069  .0001794  1.6132 0.1269  P     8.783     .500    -4.049     .300  -.086000   .383000   .0449000      .000      .000  
+79 721 44075.00 I  -.091327  .005905   .379565  .005117  I  .0401465  .0001794  1.5153 0.1269  P     8.405     .500    -4.110     .300  -.084000   .384000   .0430000      .000      .000  
+79 722 44076.00 I  -.088856  .005905   .381037  .005117  I  .0386609  .0001794  1.4637 0.1190  P     8.286     .500    -4.208     .300  -.081000   .386000   .0410000      .000      .000  
+79 723 44077.00 I  -.086321  .001209   .382482  .000154  I  .0372045  .0001564  1.4560 0.1190  P     8.427     .500    -4.304     .300  -.079000   .387000   .0391000      .000      .000  
+79 724 44078.00 I  -.083733  .001209   .383905  .000154  I  .0357367  .0001564  1.4850 0.1106  P     8.660     .500    -4.293     .300  -.075990   .389000   .0371000      .000      .000  
+79 725 44079.00 I  -.081101  .001209   .385315  .000154  I  .0342253  .0001564  1.5416 0.1106  P     8.822     .500    -4.127     .300  -.074000   .390000   .0352000      .000      .000  
+79 726 44080.00 I  -.078433  .001209   .386717  .000154  I  .0326479  .0001564  1.6152 0.1106  P     8.799     .500    -3.905     .300  -.071000   .391000   .0333000      .000      .000  
+79 727 44081.00 I  -.075739  .001209   .388117  .000154  I  .0309929  .0001564  1.6950 0.1320  P     8.553     .500    -3.801     .300  -.069000   .392000   .0313990      .000      .000  
+79 728 44082.00 I  -.073026  .002451   .389522  .006269  I  .0292595  .0002128  1.7700 0.1505  P     8.225     .500    -3.882     .300  -.066000   .394000   .0294000      .000      .000  
+79 729 44083.00 I  -.070302  .003248   .390939  .008864  I  .0274579  .0002571  1.8300 0.1669  P     8.073     .500    -4.039     .300  -.064000   .395000   .0275000      .000      .000  
+79 730 44084.00 I  -.067573  .003248   .392373  .008864  I  .0256065  .0002571  1.8692 0.2934  P     8.128     .500    -4.130     .300  -.061000   .396000   .0256000      .000      .000  
+79 731 44085.00 I  -.064847  .002315   .393830  .006471  I  .0237269  .0005275  1.8863 0.2934  P     8.041     .500    -4.142     .300  -.058000   .397000   .0236000      .000      .000  
+79 8 1 44086.00 I  -.062126  .002315   .395308  .006471  I  .0218404  .0005275  1.8838 0.3730  P     7.489     .500    -4.138     .300  -.055000   .398000   .0216000      .000      .000  
+79 8 2 44087.00 I  -.059411  .002315   .396802  .006471  I  .0199639  .0005275  1.8676 0.4383  P     6.665     .500    -4.105     .300  -.053000   .400000   .0197000      .000      .000  
+79 8 3 44088.00 I  -.056703  .000406   .398306  .002277  I  .0181066  .0007002  1.8473 0.4475  P     6.111     .500    -3.972     .300  -.050000   .401000   .0177000      .000      .000  
+79 8 4 44089.00 I  -.054003  .000406   .399814  .002277  I  .0162656  .0007231  1.8379 0.5617  P     6.076     .500    -3.777     .300  -.047000   .402000   .0156990      .000      .000  
+79 8 5 44090.00 I  -.051312  .000406   .401319  .002277  I  .0144201  .0008785  1.8604 0.6357  P     6.280     .500    -3.693     .300  -.044000   .403000   .0137000      .000      .000  
+79 8 6 44091.00 I  -.048629  .003310   .402812  .002690  I  .0125271  .0010458  1.9359 0.6903  P     6.349     .500    -3.803     .300  -.041000   .404000   .0117000      .000      .000  
+79 8 7 44092.00 I  -.045956  .007342   .404284  .001414  I  .0105286  .0010651  2.0705 0.7463  P     6.239     .500    -3.963     .300  -.039000   .405000   .0096000      .000      .000  
+79 8 8 44093.00 I  -.043291  .007342   .405727  .001414  I  .0083720  .0010651  2.2473 0.7531  P     6.139     .500    -3.973     .300  -.035990   .406000   .0076000      .000      .000  
+79 8 9 44094.00 I  -.040636  .007342   .407132  .001414  I  .0060328  .0010651  2.4276 0.7798  P     6.130     .500    -3.837     .300  -.033000   .407000   .0056000      .000      .000  
+79 810 44095.00 I  -.037989  .007342   .408492  .001414  I  .0035321  .0011392  2.5620 0.7590  P     6.091     .500    -3.730     .300  -.030000   .408000   .0035000      .000      .000  
+79 811 44096.00 I  -.035345  .007342   .409799  .001414  I  .0009371  .0010817  2.6115 0.7855  P     5.853     .500    -3.731     .300  -.027000   .409000   .0015000      .000      .000  
+79 812 44097.00 I  -.032689  .007342   .411047  .001414  I -.0016589  .0010817  2.5651 0.7414  P     5.401     .500    -3.746     .300  -.025000   .409000  -.0006000      .000      .000  
+79 813 44098.00 I  -.030008  .013625   .412228  .008250  I -.0041672  .0010141  2.4411 0.7414  P     4.945     .500    -3.700     .300  -.022000   .410000  -.0026000      .000      .000  
+79 814 44099.00 I  -.027287  .013625   .413337  .008250  I -.0065267  .0010141  2.2741 0.7171  P     4.781     .500    -3.683     .300  -.018990   .411000  -.0047000      .000      .000  
+79 815 44100.00 I  -.024514  .013625   .414367  .008250  I -.0087132  .0010141  2.1006 0.7171  P     4.988     .500    -3.813     .300  -.016000   .412000  -.0068000      .000      .000  
+79 816 44101.00 I  -.021675  .013625   .415312  .008250  I -.0107356  .0010141  1.9502 0.7171  P     5.287     .500    -4.058     .300  -.013000   .413000  -.0089000      .000      .000  
+79 817 44102.00 I  -.018775  .013625   .416172  .008250  I -.0126275  .0010141  1.8416 0.7171  P     5.326     .500    -4.268     .300  -.011000   .413000  -.0110000      .000      .000  
+79 818 44103.00 I  -.015826  .013625   .416953  .008250  I -.0144346  .0010141  1.7805 0.5248  P     5.090     .500    -4.374     .300  -.008000   .414000  -.0131000      .000      .000  
+79 819 44104.00 I  -.012839  .003310   .417659  .002690  I -.0162036  .0002710  1.7647 0.5248  P     4.893     .500    -4.427     .300  -.005000   .415000  -.0152000      .000      .000  
+79 820 44105.00 I  -.009828  .003310   .418293  .002690  I -.0179767  .0002710  1.7869 0.1916  P     4.971     .500    -4.455     .300  -.002000   .416000  -.0173000      .000      .000  
+79 821 44106.00 I  -.006804  .003310   .418860  .002690  I -.0197865  .0002710  1.8365 0.1916  P     5.245     .500    -4.378     .300   .000000   .416000  -.0194000      .000      .000  
+79 822 44107.00 I  -.003779  .003310   .419365  .002690  I -.0216552  .0002710  1.9025 0.1916  P     5.486     .500    -4.127     .300   .003000   .417000  -.0215000      .000      .000  
+79 823 44108.00 I  -.000767  .003310   .419812  .002690  I -.0235931  .0002710  1.9731 0.4315  P     5.543     .500    -3.798     .300   .005000   .417000  -.0236000      .000      .000  
+79 824 44109.00 I   .002222  .007366   .420205  .003760  I -.0255994  .0008193  2.0375 0.4315  P     5.404     .500    -3.604     .300   .008000   .418000  -.0257000      .000      .000  
+79 825 44110.00 I   .005175  .007366   .420548  .003760  I -.0276627  .0008193  2.0856 0.5793  P     5.182     .500    -3.653     .300   .011000   .418000  -.0278000      .000      .000  
+79 826 44111.00 I   .008079  .007366   .420847  .003760  I -.0297624  .0008193  2.1091 0.5793  P     5.069     .500    -3.841     .300   .013000   .419000  -.0300000      .000      .000  
+79 827 44112.00 I   .010923  .007366   .421105  .003760  I -.0318720  .0008193  2.1059 0.5793  P     5.142     .500    -3.984     .300   .016000   .419000  -.0321000      .000      .000  
+79 828 44113.00 I   .013703  .007366   .421323  .003760  I -.0339667  .0008193  2.0803 0.5793  P     5.199     .500    -4.027     .300   .017990   .420000  -.0343000      .000      .000  
+79 829 44114.00 I   .016420  .007366   .421501  .003760  I -.0360279  .0008193  2.0405 0.4315  P     4.952     .500    -4.047     .300   .021000   .420000  -.0364000      .000      .000  
+79 830 44115.00 I   .019077  .003310   .421639  .002690  I -.0380466  .0002710  1.9975 0.5166  P     4.426     .500    -4.087     .300   .024000   .420000  -.0386000      .000      .000  
+79 831 44116.00 I   .021674  .003310   .421735  .002690  I -.0400268  .0006294  1.9662 0.3426  P     3.990     .500    -4.086     .300   .026000   .420000  -.0407000      .000      .000  
+79 9 1 44117.00 I   .024215  .003310   .421790  .002690  I -.0419887  .0006294  1.9641 0.4451  P     3.920     .500    -4.009     .300   .029000   .420000  -.0429000      .000      .000  
+79 9 2 44118.00 I   .026700  .003310   .421802  .002690  I -.0439715  .0006294  2.0113 0.3967  P     4.098     .500    -3.943     .300   .031000   .420000  -.0450000      .000      .000  
+79 9 3 44119.00 I   .029132  .001039   .421771  .000637  I -.0460322  .0004830  2.1210 0.3828  P     4.224     .500    -3.970     .300   .034000   .420000  -.0472000      .000      .000  
+79 9 4 44120.00 I   .031511  .001039   .421697  .000637  I -.0482331  .0004360  2.2896 0.3535  P     4.180     .500    -4.024     .300   .037000   .420000  -.0494000      .000      .000  
+79 9 5 44121.00 I   .033842  .001039   .421579  .000637  I -.0506223  .0005163  2.4909 0.3147  P     4.083     .500    -3.977     .300   .039000   .420000  -.0516000      .000      .000  
+79 9 6 44122.00 I   .036124  .001039   .421415  .000637  I -.0532098  .0004540  2.6771 0.3438  P     4.068     .500    -3.844     .300   .042000   .419000  -.0539000      .000      .000  
+79 9 7 44123.00 I   .038362  .001039   .421208  .000637  I -.0559546  .0004540  2.7978 0.3137  P     4.134     .500    -3.770     .300   .044000   .419000  -.0561000      .000      .000  
+79 9 8 44124.00 I   .040559  .001039   .420956  .000637  I -.0587727  .0004329  2.8205 0.2920  P     4.123     .500    -3.780     .300   .047000   .419000  -.0583000      .000      .000  
+79 9 9 44125.00 I   .042720  .001895   .420659  .004941  I -.0615625  .0003672  2.7438 0.2940  P     3.855     .500    -3.719     .300   .049000   .419000  -.0606000      .000      .000  
+79 910 44126.00 I   .044847  .001895   .420319  .004941  I -.0642366  .0003979  2.5961 0.2403  P     3.364     .500    -3.491     .300   .052000   .419000  -.0627990      .000      .000  
+79 911 44127.00 I   .046946  .003521   .419936  .003727  I -.0667455  .0003102  2.4210 0.2582  P     2.996     .500    -3.273     .300   .054000   .418000  -.0651000      .000      .000  
+79 912 44128.00 I   .049019  .003521   .419508  .003727  I -.0690829  .0003293  2.2589 0.2262  P     3.090     .500    -3.333     .300   .057000   .418000  -.0673000      .000      .000  
+79 913 44129.00 I   .051074  .003521   .419032  .003727  I -.0712768  .0003293  2.1372 0.2366  P     3.552     .500    -3.698     .300   .059000   .418000  -.0696000      .000      .000  
+79 914 44130.00 I   .053117  .003521   .418502  .003727  I -.0733744  .0003397  2.0668 0.3102  P     3.930     .500    -4.120     .300   .061000   .418000  -.0720000      .000      .000  
+79 915 44131.00 I   .055153  .003632   .417912  .005270  I -.0754270  .0005259  2.0462 0.3237  P     3.963     .500    -4.359     .300   .063000   .418000  -.0743000      .000      .000  
+79 916 44132.00 I   .057180  .003632   .417258  .005270  I -.0774808  .0005511  2.0676 0.4205  P     3.858     .500    -4.392     .300   .066000   .417000  -.0767000      .000      .000  
+79 917 44133.00 I   .059199  .002276   .416536  .007223  I -.0795726  .0006562  2.1202 0.3791  P     3.938     .500    -4.314     .300   .068000   .417000  -.0790000      .000      .000  
+79 918 44134.00 I   .061206  .001611   .415743  .005343  I -.0817274  .0005207  2.1915 0.4188  P     4.217     .500    -4.163     .300   .070000   .417000  -.0814000      .000      .000  
+79 919 44135.00 I   .063200  .001611   .414878  .005343  I -.0839581  .0005207  2.2703 0.3682  P     4.478     .500    -3.911     .300   .071990   .416000  -.0838000      .000      .000  
+79 920 44136.00 I   .065176  .001611   .413944  .005343  I -.0862669  .0005207  2.3458 0.3309  P     4.594     .500    -3.602     .300   .074000   .416000  -.0863000      .000      .000  
+79 921 44137.00 I   .067126  .000173   .412949  .001668  I -.0886452  .0004086  2.4079 0.3309  P     4.603     .500    -3.367     .300   .075990   .415000  -.0887000      .000      .000  
+79 922 44138.00 I   .069047  .000173   .411900  .001668  I -.0910757  .0004086  2.4489 0.2889  P     4.566     .500    -3.305     .300   .078000   .415000  -.0912000      .000      .000  
+79 923 44139.00 I   .070931  .000173   .410806  .001668  I -.0935341  .0004086  2.4632 0.2895  P     4.529     .500    -3.379     .300   .080000   .414000  -.0936000      .000      .000  
+79 924 44140.00 I   .072773  .003214   .409675  .002695  I -.0959929  .0004103  2.4499 0.2895  P     4.554     .500    -3.472     .300   .082000   .413000  -.0961000      .000      .000  
+79 925 44141.00 I   .074567  .003214   .408515  .002695  I -.0984269  .0004103  2.4156 0.3003  P     4.637     .500    -3.519     .300   .083000   .412000  -.0987000      .000      .000  
+79 926 44142.00 I   .076307  .002742   .407335  .003737  I -.1008215  .0004387  2.3734 0.2952  P     4.656     .500    -3.547     .300   .085000   .412000  -.1012000      .000      .000  
+79 927 44143.00 I   .077989  .003355   .406142  .004542  I -.1031763  .0004245  2.3391 0.3052  P     4.516     .500    -3.594     .300   .086000   .411000  -.1038000      .000      .000  
+79 928 44144.00 I   .079608  .003355   .404944  .004542  I -.1055084  .0004245  2.3308 0.3002  P     4.301     .500    -3.649     .300   .088000   .410000  -.1063000      .000      .000  
+79 929 44145.00 I   .081169  .003355   .403754  .004542  I -.1078519  .0004245  2.3645 0.2806  P     4.197     .500    -3.676     .300   .089000   .409000  -.1089000      .000      .000  
+79 930 44146.00 I   .082675  .002602   .402580  .006364  I -.1102558  .0003670  2.4532 0.2806  P     4.278     .500    -3.677     .300   .091000   .408000  -.1116000      .000      .000  
+7910 1 44147.00 I   .084132  .002602   .401428  .006364  I -.1127779  .0003670  2.6005 0.1858  P     4.464     .500    -3.653     .300   .092000   .408000  -.1142000      .000      .000  
+7910 2 44148.00 I   .085546  .002654   .400303  .005275  I -.1154722  .0000578  2.7938 0.1858  P     4.628     .500    -3.551     .300   .094000   .407000  -.1169000      .000      .000  
+7910 3 44149.00 I   .086922  .002654   .399210  .005275  I -.1183698  .0000578  3.0000 0.0409  P     4.709     .500    -3.330     .300   .095000   .406000  -.1195000      .000      .000  
+7910 4 44150.00 I   .088261  .002654   .398147  .005275  I -.1214611  .0000578  3.1727 0.0409  P     4.736     .500    -3.081     .300   .096000   .405000  -.1222000      .000      .000  
+7910 5 44151.00 I   .089562  .002654   .397110  .005275  I -.1246893  .0000578  3.2675 0.1876  P     4.787     .500    -2.976     .300   .097000   .404000  -.1249000      .000      .000  
+7910 6 44152.00 I   .090826  .002995   .396094  .001458  I -.1279624  .0003707  3.2612 0.1876  P     4.870     .500    -3.047     .300   .098000   .404000  -.1275000      .000      .000  
+7910 7 44153.00 I   .092056  .002995   .395093  .001458  I -.1311808  .0003707  3.1622 0.3034  P     4.861     .500    -3.100     .300   .099000   .403000  -.1302000      .000      .000  
+7910 8 44154.00 I   .093254  .003937   .394100  .001496  I -.1342675  .0004805  3.0054 0.2817  P     4.659     .500    -2.948     .300   .100000   .402000  -.1329000      .000      .000  
+7910 9 44155.00 I   .094421  .003937   .393111  .001496  I -.1371874  .0004242  2.8360 0.3205  P     4.418     .500    -2.693     .300   .101000   .401000  -.1356000      .000      .000  
+791010 44156.00 I   .095564  .003937   .392119  .001496  I -.1399479  .0004242  2.6916 0.2743  P     4.450     .500    -2.643     .300   .102000   .400000  -.1383000      .000      .000  
+791011 44157.00 I   .096691  .003162   .391120  .001447  I -.1425862  .0003480  2.5938 0.2187  P     4.829     .500    -2.943     .300   .103000   .400000  -.1409000      .000      .000  
+791012 44158.00 I   .097813  .002121   .390111  .001397  I -.1451529  .0001063  2.5481 0.1819  P     5.266     .500    -3.407     .300   .104000   .399000  -.1436000      .000      .000  
+791013 44159.00 I   .098939  .002121   .389088  .001397  I -.1476981  .0001063  2.5495 0.0776  P     5.486     .500    -3.723     .300   .105000   .398000  -.1463000      .000      .000  
+791014 44160.00 I   .100079  .002121   .388046  .001397  I -.1502641  .0001131  2.5875 0.0840  P     5.558     .500    -3.764     .300   .106000   .397000  -.1490000      .000      .000  
+791015 44161.00 I   .101241  .001834   .386981  .001811  I -.1528811  .0001301  2.6495 0.0862  P     5.720     .500    -3.616     .300   .107000   .396000  -.1517000      .000      .000  
+791016 44162.00 I   .102432  .001834   .385888  .001811  I -.1555665  .0001301  2.7217 0.2196  P     6.001     .500    -3.406     .300   .108000   .395000  -.1545000      .000      .000  
+791017 44163.00 I   .103656  .005483   .384759  .002324  I -.1583234  .0004194  2.7906 0.2196  P     6.238     .500    -3.179     .300   .109000   .394000  -.1572000      .000      .000  
+791018 44164.00 I   .104919  .005483   .383589  .002324  I -.1611426  .0004194  2.8443 0.2966  P     6.353     .500    -2.930     .300   .110000   .393000  -.1599000      .000      .000  
+791019 44165.00 I   .106230  .005483   .382375  .002324  I -.1640036  .0004194  2.8729 0.3108  P     6.416     .500    -2.673     .300   .111000   .392000  -.1626000      .000      .000  
+791020 44166.00 I   .107594  .005483   .381114  .002324  I -.1668783  .0004587  2.8713 0.3119  P     6.458     .500    -2.455     .300   .112000   .391000  -.1653000      .000      .000  
+791021 44167.00 I   .109010  .005398   .379805  .002210  I -.1697354  .0004618  2.8374 0.3254  P     6.423     .500    -2.328     .300   .113000   .389000  -.1681000      .000      .000  
+791022 44168.00 I   .110472  .005398   .378448  .002210  I -.1725428  .0004618  2.7727 0.3337  P     6.334     .500    -2.314     .300   .114000   .388000  -.1708000      .000      .000  
+791023 44169.00 I   .111973  .001530   .377043  .001906  I -.1752734  .0004817  2.6858 0.3337  P     6.317     .500    -2.392     .300   .115000   .387000  -.1735000      .000      .000  
+791024 44170.00 I   .113508  .001530   .375592  .001906  I -.1779123  .0004817  2.5927 0.3406  P     6.422     .500    -2.497     .300   .116000   .386000  -.1762000      .000      .000  
+791025 44171.00 I   .115071  .001530   .374096  .001906  I -.1804638  .0004817  2.5146 0.3406  P     6.533     .500    -2.569     .300   .117000   .385000  -.1790000      .000      .000  
+791026 44172.00 I   .116658  .001530   .372558  .001906  I -.1829532  .0004817  2.4715 0.3485  P     6.520     .500    -2.592     .300   .117000   .383000  -.1817000      .000      .000  
+791027 44173.00 I   .118264  .002580   .370981  .001917  I -.1854237  .0005037  2.4791 0.3485  P     6.423     .500    -2.591     .300   .118000   .382000  -.1845000      .000      .000  
+791028 44174.00 I   .119881  .002580   .369370  .001917  I -.1879304  .0005037  2.5438 0.2691  P     6.402     .500    -2.578     .300   .119000   .381000  -.1872000      .000      .000  
+791029 44175.00 I   .121499  .002312   .367730  .001860  I -.1905278  .0001894  2.6580 0.2691  P     6.568     .500    -2.513     .300   .120000   .380000  -.1899000      .000      .000  
+791030 44176.00 I   .123110  .002312   .366067  .001860  I -.1932557  .0001894  2.8001 0.1339  P     6.860     .500    -2.329     .300   .121000   .378000  -.1927000      .000      .000  
+791031 44177.00 I   .124704  .002312   .364386  .001860  I -.1961259  .0001894  2.9361 0.1339  P     7.101     .500    -2.019     .300   .121000   .377000  -.1954000      .000      .000  
+7911 1 44178.00 I   .126267  .002312   .362696  .001860  I -.1991127  .0001894  3.0267 0.1310  P     7.157     .500    -1.706     .300   .122000   .375000  -.1982000      .000      .000  
+7911 2 44179.00 I   .127786  .002905   .361002  .002850  I -.2021533  .0001811  3.0395 0.1310  P     7.065     .500    -1.576     .300   .123000   .374000  -.2009000      .000      .000  
+7911 3 44180.00 I   .129247  .002905   .359310  .002850  I -.2051622  .0001811  2.9638 0.1568  P     6.971     .500    -1.696     .300   .124000   .372000  -.2036000      .000      .000  
+7911 4 44181.00 I   .130640  .003898   .357627  .003603  I -.2080566  .0002561  2.8153 0.1285  P     6.958     .500    -1.906     .300   .125000   .370000  -.2063000      .000      .000  
+7911 5 44182.00 I   .131952  .003677   .355957  .003851  I -.2107808  .0001823  2.6308 0.1572  P     6.990     .500    -1.963     .300   .126000   .369000  -.2090000      .000      .000  
+7911 6 44183.00 I   .133174  .003677   .354305  .003851  I -.2133200  .0001823  2.4518 0.1289  P     7.040     .500    -1.814     .300   .127000   .367000  -.2117000      .000      .000  
+7911 7 44184.00 I   .134298  .003677   .352671  .003851  I -.2156970  .0001823  2.3106 0.0924  P     7.178     .500    -1.669     .300   .128000   .365000  -.2144000      .000      .000  
+7911 8 44185.00 I   .135323  .003442   .351057  .004083  I -.2179589  .0000301  2.2226 0.0924  P     7.454     .500    -1.745     .300   .128990   .363000  -.2170000      .000      .000  
+7911 9 44186.00 I   .136248  .003442   .349458  .004083  I -.2201601  .0000301  2.1883 0.0450  P     7.786     .500    -2.017     .300   .130000   .361000  -.2197000      .000      .000  
+791110 44187.00 I   .137075  .002449   .347869  .003046  I -.2223508  .0000849  2.1998 0.0600  P     8.056     .500    -2.260     .300   .131000   .358000  -.2223000      .000      .000  
+791111 44188.00 I   .137808  .000384   .346286  .001372  I -.2245710  .0001162  2.2452 0.0720  P     8.269     .500    -2.296     .300   .132000   .356000  -.2250000      .000      .000  
+791112 44189.00 I   .138446  .000384   .344704  .001372  I -.2268483  .0001162  2.3118 0.1840  P     8.495     .500    -2.148     .300   .133000   .354000  -.2276000      .000      .000  
+791113 44190.00 I   .138994  .002275   .343119  .001146  I -.2291972  .0003491  2.3861 0.1840  P     8.715     .500    -1.941     .300   .134000   .352000  -.2302000      .000      .000  
+791114 44191.00 I   .139451  .002275   .341524  .001146  I -.2316187  .0003491  2.4551 0.2469  P     8.840     .500    -1.758     .300   .135000   .350000  -.2328000      .000      .000  
+791115 44192.00 I   .139821  .002275   .339914  .001146  I -.2341023  .0003491  2.5090 0.2967  P     8.850     .500    -1.578     .300   .135000   .347000  -.2355000      .000      .000  
+791116 44193.00 I   .140103  .003195   .338282  .000863  I -.2366291  .0004799  2.5403 0.2564  P     8.811     .500    -1.341     .300   .136000   .345000  -.2381000      .000      .000  
+791117 44194.00 I   .140302  .002377   .336622  .002374  I -.2391737  .0003756  2.5441 0.3047  P     8.744     .500    -1.044     .300   .136990   .343000  -.2407000      .000      .000  
+791118 44195.00 I   .140426  .002377   .334928  .002374  I -.2417079  .0003756  2.5196 0.2103  P     8.607     .500     -.783     .300   .138000   .341000  -.2433000      .000      .000  
+791119 44196.00 I   .140482  .001435   .333196  .002297  I -.2442046  .0001892  2.4702 0.2103  P     8.429     .500     -.697     .300   .138000   .339000  -.2459000      .000      .000  
+791120 44197.00 I   .140477  .001435   .331420  .002297  I -.2466437  .0001892  2.4071 0.1261  P     8.351     .500     -.835     .300   .139000   .336000  -.2485000      .000      .000  
+791121 44198.00 I   .140419  .001435   .329595  .002297  I -.2490207  .0001669  2.3498 0.1261  P     8.464     .500    -1.080     .300   .139000   .334000  -.2511000      .000      .000  
+791122 44199.00 I   .140318  .001435   .327721  .002297  I -.2513531  .0001669  2.3218 0.0850  P     8.669     .500    -1.238     .300   .140000   .332000  -.2536990      .000      .000  
+791123 44200.00 I   .140180  .000510   .325795  .001795  I -.2536803  .0000325  2.3419 0.0873  P     8.780     .500    -1.219     .300   .140000   .330000  -.2563000      .000      .000  
+791124 44201.00 I   .140012  .000510   .323818  .001795  I -.2560557  .0000510  2.4183 0.0278  P     8.730     .500    -1.087     .300   .140000   .328000  -.2588990      .000      .000  
+791125 44202.00 I   .139821  .000184   .321787  .001899  I -.2585334  .0000451  2.5441 0.0345  P     8.640     .500     -.952     .300   .141000   .324990  -.2615000      .000      .000  
+791126 44203.00 I   .139611  .000704   .319701  .002263  I -.2611536  .0000466  2.6990 0.0319  P     8.674     .500     -.845     .300   .141000   .323000  -.2641000      .000      .000  
+791127 44204.00 I   .139390  .000704   .317562  .002263  I -.2639311  .0000452  2.8530 0.0393  P     8.863     .500     -.719     .300   .141000   .321000  -.2667000      .000      .000  
+791128 44205.00 I   .139167  .000772   .315386  .003455  I -.2668483  .0000632  2.9732 0.0388  P     9.060     .500     -.540     .300   .141000   .319000  -.2693000      .000      .000  
+791129 44206.00 I   .138953  .000772   .313192  .003455  I -.2698572  .0000632  3.0325 0.0981  P     9.075     .500     -.363     .300   .141000   .316000  -.2718000      .000      .000  
+791130 44207.00 I   .138753  .002006   .310995  .006822  I -.2728880  .0001857  3.0158 0.0981  P     8.850     .500     -.306     .300   .141000   .314000  -.2744000      .000      .000  
+7912 1 44208.00 I   .138573  .002006   .308809  .006822  I -.2758646  .0001857  2.9266 0.1813  P     8.526     .500     -.436     .300   .141000   .310990  -.2769000      .000      .000  
+7912 2 44209.00 I   .138418  .001687   .306639  .006543  I -.2787243  .0003114  2.7869 0.1813  P     8.316     .500     -.670     .300   .141000   .308990  -.2795000      .000      .000  
+7912 3 44210.00 I   .138289  .001687   .304489  .006543  I -.2814329  .0003114  2.6309 0.2203  P     8.335     .500     -.819     .300   .141000   .307000  -.2821000      .000      .000  
+7912 4 44211.00 I   .138190  .002264   .302360  .002854  I -.2839919  .0003116  2.4925 0.2203  P     8.530     .500     -.763     .300   .141000   .305000  -.2846000      .000      .000  
+7912 5 44212.00 I   .138124  .002264   .300255  .002854  I -.2864315  .0003116  2.3949 0.2119  P     8.772     .500     -.586     .300   .140000   .303000  -.2872000      .000      .000  
+7912 6 44213.00 I   .138091  .002264   .298174  .002854  I -.2887981  .0002872  2.3466 0.2051  P     8.983     .500     -.484     .300   .140000   .301000  -.2897000      .000      .000  
+7912 7 44214.00 I   .138089  .002264   .296114  .002854  I -.2911396  .0002669  2.3432 0.1763  P     9.180     .500     -.545     .300   .140000   .299000  -.2923000      .000      .000  
+7912 8 44215.00 I   .138117  .002089   .294075  .001784  I -.2934961  .0002045  2.3748 0.1681  P     9.411     .500     -.670     .300   .140000   .297000  -.2949000      .000      .000  
+7912 9 44216.00 I   .138168  .002089   .292058  .001784  I -.2958970  .0002045  2.4299 0.1655  P     9.671     .500     -.711     .300   .140000   .294990  -.2974000      .000      .000  
+791210 44217.00 I   .138238  .001369   .290066  .002530  I -.2983595  .0002603  2.4959 0.1655  P     9.884     .500     -.636     .300   .139000   .293000  -.3000000      .000      .000  
+791211 44218.00 I   .138320  .001369   .288099  .002530  I -.3008881  .0002603  2.5600 0.1894  P     9.982     .500     -.520     .300   .139000   .291000  -.3025000      .000      .000  
+791212 44219.00 I   .138410  .001369   .286159  .002530  I -.3034748  .0002751  2.6102 0.1972  P     9.963     .500     -.433     .300   .139000   .289000  -.3051000      .000      .000  
+791213 44220.00 I   .138505  .001369   .284248  .002530  I -.3061010  .0002962  2.6381 0.2368  P     9.862     .500     -.359     .300   .139000   .287000  -.3076000      .000      .000  
+791214 44221.00 I   .138603  .001227   .282368  .003533  I -.3087421  .0003856  2.6395 0.2431  P     9.698     .500     -.227     .300   .138000   .285000  -.3102000      .000      .000  
+791215 44222.00 I   .138703  .001227   .280516  .003533  I -.3113708  .0003856  2.6135 0.2269  P     9.476     .500      .004     .300   .138000   .283000  -.3127000      .000      .000  
+791216 44223.00 I   .138805  .002109   .278690  .000876  I -.3139607  .0002392  2.5624 0.2269  P     9.245     .500      .271     .300   .136990   .280990  -.3153000      .000      .000  
+791217 44224.00 I   .138909  .002109   .276887  .000876  I -.3164895  .0002392  2.4929 0.2904  P     9.098     .500      .417     .300   .136990   .279000  -.3178000      .000      .000  
+791218 44225.00 I   .139014  .002109   .275106  .000876  I -.3189447  .0005293  2.4179 0.3238  P     9.097     .500      .316     .300   .136990   .277000  -.3203000      .000      .000  
+791219 44226.00 I   .139120  .001512   .273342  .001091  I -.3213305  .0006018  2.3584 0.4007  P     9.230     .500      .024     .300   .136000   .275000  -.3229000      .000      .000  
+791220 44227.00 I   .139225  .001512   .271595  .001091  I -.3236743  .0006018  2.3374 0.4255  P     9.429     .500     -.230     .300   .136000   .273990  -.3254000      .000      .000  
+791221 44228.00 I   .139326  .001512   .269861  .001091  I -.3260234  .0006018  2.3707 0.4735  P     9.610     .500     -.242     .300   .135000   .272000  -.3280000      .000      .000  
+791222 44229.00 I   .139418  .000357   .268135  .001271  I -.3284335  .0007313  2.4576 0.4735  P     9.711     .500     -.017     .300   .135000   .270000  -.3305000      .000      .000  
+791223 44230.00 I   .139498  .000357   .266416  .001271  I -.3309502  .0007313  2.5794 0.5104  P     9.722     .500      .264     .300   .134000   .268000  -.3330000      .000      .000  
+791224 44231.00 I   .139560  .000357   .264700  .001271  I -.3335935  .0007121  2.7046 0.3989  P     9.694     .500      .434     .300   .134000   .266000  -.3355000      .000      .000  
+791225 44232.00 I   .139603  .003310   .262986  .002690  I -.3363494  .0003188  2.7996 0.3794  P     9.686     .500      .468     .300   .133000   .264000  -.3380000      .000      .000  
+791226 44233.00 I   .139621  .001759   .261273  .003757  I -.3391744  .0002620  2.8398 0.1984  P     9.689     .500      .434     .300   .133000   .262000  -.3405000      .000      .000  
+791227 44234.00 I   .139611  .001759   .259557  .003757  I -.3420076  .0002363  2.8158 0.1764  P     9.614     .500      .385     .300   .132000   .260000  -.3430000      .000      .000  
+791228 44235.00 I   .139569  .001759   .257838  .003757  I -.3447863  .0002363  2.7328 0.1666  P     9.389     .500      .313     .300   .131000   .257990  -.3455000      .000      .000  
+791229 44236.00 I   .139492  .001759   .256114  .003757  I -.3474594  .0002349  2.6083 0.1666  P     9.058     .500      .190     .300   .131000   .256000  -.3480000      .000      .000  
+791230 44237.00 I   .139373  .001759   .254387  .003757  I -.3499978  .0002349  2.4684 0.1398  P     8.791     .500      .041     .300   .130000   .255000  -.3506000      .000      .000  
+791231 44238.00 I   .139205  .002692   .252659  .002880  I -.3524007  .0001516  2.3421 0.1471  P     8.751     .500     -.051     .300   .130000   .253000  -.3531000      .000      .000  
+80 1 1 44239.00 I   .138980  .003377   .250935  .001572  I  .6453058  .0001770  2.2525 0.1299  P     8.940     .500     -.017     .300   .128990   .250990   .6444000      .000      .000  
+80 1 2 44240.00 I   .138693  .003377   .249216  .001572  I  .6430784  .0002110  2.2106 0.1797  P     9.190     .500      .106     .300   .128000   .249000   .6419000      .000      .000  
+80 1 3 44241.00 I   .138335  .003377   .247506  .001572  I  .6408691  .0003129  2.2154 0.1982  P     9.345     .500      .200     .300   .127000   .247000   .6394000      .000      .000  
+80 1 4 44242.00 I   .137902  .003377   .245807  .001572  I  .6386352  .0003355  2.2576 0.2294  P     9.427     .500      .185     .300   .127000   .246000   .6368000      .000      .000  
+80 1 5 44243.00 I   .137395  .003377   .244120  .001572  I  .6363457  .0003355  2.3246 0.2104  P     9.562     .500      .103     .300   .126000   .244000   .6343000      .000      .000  
+80 1 6 44244.00 I   .136811  .005031   .242446  .000749  I  .6339818  .0002540  2.4042 0.2104  P     9.761     .500      .041     .300   .125000   .242000   .6318000      .000      .000  
+80 1 7 44245.00 I   .136151  .005031   .240786  .000749  I  .6315374  .0002540  2.4836 0.1796  P     9.887     .500      .030     .300   .124000   .240000   .6293000      .000      .000  
+80 1 8 44246.00 I   .135413  .005031   .239142  .000749  I  .6290184  .0002540  2.5516 0.1793  P     9.853     .500      .029     .300   .123000   .239000   .6267000      .000      .000  
+80 1 9 44247.00 I   .134598  .003779   .237513  .001582  I  .6264412  .0002531  2.5988 0.1691  P     9.728     .500      .005     .300   .122000   .237000   .6242000      .000      .000  
+80 110 44248.00 I   .133709  .003779   .235902  .001582  I  .6238294  .0002232  2.6204 0.1687  P     9.586     .500     -.031     .300   .121000   .236000   .6216000      .000      .000  
+80 111 44249.00 I   .132757  .003779   .234310  .001582  I  .6212086  .0002232  2.6173 0.1867  P     9.381     .500     -.038     .300   .120000   .234000   .6191000      .000      .000  
+80 112 44250.00 I   .131748  .001806   .232740  .002108  I  .6186020  .0002993  2.5926 0.1714  P     9.088     .500      .037     .300   .119000   .232000   .6166000      .000      .000  
+80 113 44251.00 I   .130692  .001323   .231191  .001528  I  .6160289  .0002601  2.5513 0.1983  P     8.847     .500      .223     .300   .118000   .231000   .6141000      .000      .000  
+80 114 44252.00 I   .129593  .001323   .229665  .001528  I  .6135018  .0002601  2.5026 0.1474  P     8.811     .500      .449     .300   .116000   .229000   .6115000      .000      .000  
+80 115 44253.00 I   .128457  .002049   .228159  .000338  I  .6110210  .0001389  2.4619 0.1521  P     8.917     .500      .539     .300   .115000   .228000   .6090000      .000      .000  
+80 116 44254.00 I   .127290  .002049   .226672  .000338  I  .6085683  .0001579  2.4503 0.1051  P     8.977     .500      .376     .300   .114000   .226000   .6065000      .000      .000  
+80 117 44255.00 I   .126096  .002049   .225205  .000338  I  .6061039  .0001579  2.4882 0.1117  P     8.964     .500      .074     .300   .113000   .224000   .6040000      .000      .000  
+80 118 44256.00 I   .124881  .002049   .223755  .000338  I  .6035730  .0001579  2.5829 0.2100  P     9.054     .500     -.093     .300   .111000   .223000   .6015000      .000      .000  
+80 119 44257.00 I   .123646  .003572   .222321  .000859  I  .6009239  .0003892  2.7203 0.2100  P     9.340     .500      .037     .300   .110000   .221000   .5989000      .000      .000  
+80 120 44258.00 I   .122392  .003572   .220902  .000859  I  .5981297  .0003892  2.8658 0.3292  P     9.674     .500      .347     .300   .108000   .220000   .5964000      .000      .000  
+80 121 44259.00 I   .121118  .004167   .219496  .001213  I  .5952043  .0005311  2.9755 0.2738  P     9.832     .500      .585     .300   .107000   .218000   .5939000      .000      .000  
+80 122 44260.00 I   .119821  .003819   .218103  .001099  I  .5922023  .0003852  3.0145 0.3027  P     9.750     .500      .620     .300   .106000   .216000   .5914000      .000      .000  
+80 123 44261.00 I   .118501  .003819   .216720  .001099  I  .5892033  .0002905  2.9693 0.2374  P     9.532     .500      .504     .300   .104000   .215000   .5889000      .000      .000  
+80 124 44262.00 I   .117150  .003819   .215348  .001099  I  .5862886  .0002777  2.8492 0.1871  P     9.301     .500      .348     .300   .103000   .213000   .5863000      .000      .000  
+80 125 44263.00 I   .115758  .003435   .213987  .000970  I  .5835214  .0002360  2.6796 0.1786  P     9.107     .500      .196     .300   .101000   .212000   .5838000      .000      .000  
+80 126 44264.00 I   .114323  .003435   .212638  .000970  I  .5809352  .0002247  2.4926 0.1571  P     8.949     .500      .046     .300   .100000   .210000   .5813000      .000      .000  
+80 127 44265.00 I   .112841  .002468   .211304  .001808  I  .5785319  .0002074  2.3185 0.1574  P     8.845     .500     -.083     .300   .099000   .209000   .5788000      .000      .000  
+80 128 44266.00 I   .111310  .000614   .209984  .002365  I  .5762861  .0002206  2.1806 0.1663  P     8.849     .500     -.149     .300   .097000   .207000   .5764000      .000      .000  
+80 129 44267.00 I   .109728  .000614   .208682  .002365  I  .5741545  .0002601  2.0915 0.1617  P     8.993     .500     -.145     .300   .096000   .206000   .5739000      .000      .000  
+80 130 44268.00 I   .108092  .004099   .207398  .002045  I  .5720865  .0002364  2.0524 0.1392  P     9.205     .500     -.124     .300   .094000   .204000   .5715000      .000      .000  
+80 131 44269.00 I   .106402  .004099   .206132  .002045  I  .5700354  .0000992  2.0561 0.1366  P     9.365     .500     -.147     .300   .093000   .203000   .5690000      .000      .000  
+80 2 1 44270.00 I   .104655  .004099   .204884  .002045  I  .5679641  .0001369  2.0903 0.1554  P     9.447     .500     -.215     .300   .092000   .202000   .5665000      .000      .000  
+80 2 2 44271.00 I   .102851  .005765   .203651  .001665  I  .5658492  .0002945  2.1415 0.1471  P     9.533     .500     -.280     .300   .090000   .201000   .5641000      .000      .000  
+80 2 3 44272.00 I   .100993  .005130   .202433  .001274  I  .5636796  .0002604  2.1974 0.1912  P     9.645     .500     -.312     .300   .089000   .199000   .5616000      .000      .000  
+80 2 4 44273.00 I   .099091  .005130   .201231  .001274  I  .5614565  .0002440  2.2469 0.1956  P     9.674     .500     -.344     .300   .087000   .198000   .5592000      .000      .000  
+80 2 5 44274.00 I   .097155  .004404   .200045  .000689  I  .5591909  .0002919  2.2809 0.1751  P     9.553     .500     -.413     .300   .086000   .197000   .5567000      .000      .000  
+80 2 6 44275.00 I   .095195  .003150   .198875  .000981  I  .5569018  .0002511  2.2934 0.1929  P     9.380     .500     -.508     .300   .085000   .196000   .5543000      .000      .000  
+80 2 7 44276.00 I   .093226  .003150   .197723  .000981  I  .5546116  .0002522  2.2834 0.1433  P     9.239     .500     -.605     .300   .084000   .195000   .5519000      .000      .000  
+80 2 8 44277.00 I   .091266  .003150   .196591  .000981  I  .5523411  .0001381  2.2550 0.2027  P     9.059     .500     -.706     .300   .083000   .193000   .5494000      .000      .000  
+80 2 9 44278.00 I   .089333  .008667   .195479  .001230  I  .5501051  .0003175  2.2160 0.1876  P     8.803     .500     -.787     .300   .082000   .192000   .5470000      .000      .000  
+80 210 44279.00 I   .087446  .008667   .194388  .001230  I  .5479092  .0003489  2.1766 0.2488  P     8.657     .500     -.748     .300   .081000   .191000   .5446000      .000      .000  
+80 211 44280.00 I   .085620  .007085   .193319  .001032  I  .5457478  .0003831  2.1494 0.3863  P     8.806     .500     -.528     .300   .080000   .190000   .5422000      .000      .000  
+80 212 44281.00 I   .083873  .008664   .192271  .000934  I  .5436007  .0006894  2.1513 0.3943  P     9.070     .500     -.271     .300   .079000   .189000   .5397000      .000      .000  
+80 213 44282.00 I   .082218  .008664   .191244  .000934  I  .5414283  .0006894  2.2039 0.4875  P     9.070     .500     -.245     .300   .079000   .188000   .5373000      .000      .000  
+80 214 44283.00 I   .080651  .008664   .190240  .000934  I  .5391704  .0006894  2.3241 0.5040  P     8.773     .500     -.538     .300   .078000   .187000   .5348000      .000      .000  
+80 215 44284.00 I   .079166  .000589   .189260  .000412  I  .5367591  .0007355  2.5074 0.5040  P     8.600     .500     -.902     .300   .077000   .186000   .5324000      .000      .000  
+80 216 44285.00 I   .077756  .000589   .188305  .000412  I  .5341446  .0007355  2.7237 0.5100  P     8.907     .500    -1.017     .300   .075990   .185000   .5300000      .000      .000  
+80 217 44286.00 I   .076414  .000053   .187376  .001721  I  .5313165  .0007068  2.9257 0.3822  P     9.531     .500     -.834     .300   .075000   .184000   .5276000      .000      .000  
+80 218 44287.00 I   .075131  .000053   .186474  .001721  I  .5283146  .0002082  3.0635 0.3684  P     9.988     .500     -.589     .300   .075000   .184000   .5251000      .000      .000  
+80 219 44288.00 I   .073900  .000053   .185601  .001721  I  .5252221  .0002082  3.1034 0.1693  P     9.984     .500     -.494     .300   .074000   .183000   .5227000      .000      .000  
+80 220 44289.00 I   .072715  .000611   .184756  .001318  I  .5221418  .0002671  3.0412 0.1627  P     9.620     .500     -.546     .300   .073000   .182000   .5202990      .000      .000  
+80 221 44290.00 I   .071567  .000611   .183944  .001318  I  .5191657  .0002501  2.9011 0.1843  P     9.213     .500     -.653     .300   .071990   .181000   .5179000      .000      .000  
+80 222 44291.00 I   .070449  .000611   .183165  .001318  I  .5163523  .0002541  2.7231 0.1788  P     9.023     .500     -.799     .300   .071000   .180000   .5155000      .000      .000  
+80 223 44292.00 I   .069354  .000863   .182425  .000714  I  .5137186  .0002557  2.5479 0.1843  P     9.088     .500    -1.012     .300   .071000   .180000   .5130000      .000      .000  
+80 224 44293.00 I   .068273  .000614   .181726  .001319  I  .5112459  .0002669  2.4044 0.1848  P     9.253     .500    -1.247     .300   .070000   .179000   .5105990      .000      .000  
+80 225 44294.00 I   .067199  .000614   .181072  .001319  I  .5088943  .0002669  2.3073 0.1808  P     9.363     .500    -1.406     .300   .069000   .178000   .5082000      .000      .000  
+80 226 44295.00 I   .066122  .000099   .180469  .001723  I  .5066145  .0002439  2.2604 0.2011  P     9.428     .500    -1.462     .300   .068000   .177000   .5058000      .000      .000  
+80 227 44296.00 I   .065033  .002118   .179919  .001673  I  .5043588  .0003008  2.2575 0.2012  P     9.567     .500    -1.485     .300   .067000   .177000   .5034000      .000      .000  
+80 228 44297.00 I   .063923  .002118   .179427  .001673  I  .5020888  .0003201  2.2868 0.2254  P     9.807     .500    -1.531     .300   .067000   .176000   .5010000      .000      .000  
+80 229 44298.00 I   .062782  .002118   .178993  .001673  I  .4997791  .0003359  2.3343 0.2170  P    10.059     .500    -1.561     .300   .066000   .176000   .4986000      .000      .000  
+80 3 1 44299.00 I   .061603  .002628   .178619  .002590  I  .4974185  .0002932  2.3868 0.2229  P    10.245     .500    -1.512     .300   .065000   .175000   .4962000      .000      .000  
+80 3 2 44300.00 I   .060380  .002628   .178307  .002590  I  .4950075  .0002932  2.4334 0.2101  P    10.341     .500    -1.411     .300   .064000   .175000   .4938000      .000      .000  
+80 3 3 44301.00 I   .059110  .002628   .178054  .002590  I  .4925570  .0003011  2.4642 0.2117  P    10.322     .500    -1.368     .300   .063000   .175000   .4913000      .000      .000  
+80 3 4 44302.00 I   .057789  .002398   .177863  .002360  I  .4900871  .0003054  2.4712 0.2144  P    10.183     .500    -1.438     .300   .062000   .175000   .4889000      .000      .000  
+80 3 5 44303.00 I   .056416  .002398   .177730  .002360  I  .4876240  .0003054  2.4501 0.2160  P    10.003     .500    -1.566     .300   .061000   .175000   .4864000      .000      .000  
+80 3 6 44304.00 I   .054990  .002398   .177653  .002360  I  .4851957  .0003054  2.4025 0.2769  P     9.859     .500    -1.683     .300   .060000   .175000   .4840000      .000      .000  
+80 3 7 44305.00 I   .053512  .002132   .177625  .002369  I  .4828251  .0004620  2.3367 0.2769  P     9.709     .500    -1.805     .300   .059000   .175000   .4815000      .000      .000  
+80 3 8 44306.00 I   .051987  .002132   .177643  .002369  I  .4805241  .0004620  2.2657 0.3389  P     9.529     .500    -1.967     .300   .057000   .175000   .4790000      .000      .000  
+80 3 9 44307.00 I   .050421  .002132   .177702  .002369  I  .4782909  .0004960  2.2033 0.3425  P     9.501     .500    -2.083     .300   .056000   .176000   .4766000      .000      .000  
+80 310 44308.00 I   .048818  .001193   .177795  .002528  I  .4761094  .0005057  2.1652 0.3542  P     9.821     .500    -2.009     .300   .054000   .176000   .4741000      .000      .000  
+80 311 44309.00 I   .047184  .001193   .177919  .002528  I  .4739461  .0005057  2.1703 0.3576  P    10.311     .500    -1.778     .300   .053000   .176000   .4716000      .000      .000  
+80 312 44310.00 I   .045521  .001193   .178073  .002528  I  .4717485  .0005057  2.2364 0.3351  P    10.511     .500    -1.652     .300   .052000   .176000   .4691000      .000      .000  
+80 313 44311.00 I   .043833  .000463   .178255  .001422  I  .4694499  .0004397  2.3726 0.3351  P    10.260     .500    -1.839     .300   .050000   .177000   .4666000      .000      .000  
+80 314 44312.00 I   .042121  .000463   .178468  .001422  I  .4669834  .0004397  2.5685 0.3109  P     9.959     .500    -2.210     .300   .049000   .177000   .4641000      .000      .000  
+80 315 44313.00 I   .040391  .000463   .178710  .001422  I  .4643042  .0004397  2.7904 0.3098  P    10.086     .500    -2.436     .300   .047000   .178000   .4616000      .000      .000  
+80 316 44314.00 I   .038646  .001144   .178983  .001158  I  .4614115  .0004365  2.9856 0.3098  P    10.612     .500    -2.372     .300   .046000   .178000   .4591000      .000      .000  
+80 317 44315.00 I   .036890  .001144   .179286  .001158  I  .4583594  .0004365  3.1018 0.3199  P    11.062     .500    -2.187     .300   .044000   .179000   .4566000      .000      .000  
+80 318 44316.00 I   .035126  .001327   .179618  .000964  I  .4552437  .0004678  3.1108 0.3196  P    11.045     .500    -2.093     .300   .042000   .179000   .4541000      .000      .000  
+80 319 44317.00 I   .033358  .001622   .179979  .000571  I  .4521716  .0004669  3.0185 0.3305  P    10.598     .500    -2.105     .300   .041000   .180000   .4515000      .000      .000  
+80 320 44318.00 I   .031588  .001622   .180365  .000571  I  .4492286  .0004669  2.8605 0.3301  P    10.098     .500    -2.141     .300   .039000   .180000   .4490000      .000      .000  
+80 321 44319.00 I   .029816  .001622   .180776  .000571  I  .4464563  .0004669  2.6855 0.3097  P     9.936     .500    -2.226     .300   .037000   .181000   .4465000      .000      .000  
+80 322 44320.00 I   .028044  .001737   .181209  .000946  I  .4438491  .0004069  2.5361 0.3097  P    10.203     .500    -2.450     .300   .035000   .182000   .4439000      .000      .000  
+80 323 44321.00 I   .026277  .001737   .181661  .000946  I  .4413673  .0004069  2.4373 0.2352  P    10.612     .500    -2.780     .300   .033000   .182000   .4413000      .000      .000  
+80 324 44322.00 I   .024517  .001836   .182131  .001299  I  .4389552  .0002361  2.3965 0.2421  P    10.790     .500    -3.045     .300   .032000   .183000   .4388000      .000      .000  
+80 325 44323.00 I   .022769  .002040   .182616  .001004  I  .4365571  .0002624  2.4074 0.1765  P    10.696     .500    -3.135     .300   .030000   .183000   .4362000      .000      .000  
+80 326 44324.00 I   .021032  .002040   .183114  .001004  I  .4341277  .0002624  2.4566 0.1829  P    10.646     .500    -3.102     .300   .028000   .184000   .4336000      .000      .000  
+80 327 44325.00 I   .019308  .002851   .183625  .001550  I  .4316361  .0002549  2.5292 0.1860  P    10.888     .500    -3.033     .300   .026000   .185000   .4310000      .000      .000  
+80 328 44326.00 I   .017596  .003241   .184149  .001661  I  .4290667  .0002638  2.6095 0.1834  P    11.307     .500    -2.922     .300   .024000   .186000   .4284000      .000      .000  
+80 329 44327.00 I   .015900  .003241   .184683  .001661  I  .4264192  .0002638  2.6834 0.1865  P    11.621     .500    -2.720     .300   .021000   .186000   .4258000      .000      .000  
+80 330 44328.00 I   .014225  .003241   .185227  .001661  I  .4237058  .0002638  2.7396 0.2025  P    11.707     .500    -2.479     .300   .018990   .187000   .4232000      .000      .000  
+80 331 44329.00 I   .012573  .002856   .185779  .001611  I  .4209487  .0003074  2.7698 0.2025  P    11.627     .500    -2.341     .300   .017000   .188000   .4206000      .000      .000  
+80 4 1 44330.00 I   .010942  .002856   .186341  .001611  I  .4181764  .0003074  2.7693 0.2349  P    11.467     .500    -2.383     .300   .014000   .189000   .4180000      .000      .000  
+80 4 2 44331.00 I   .009330  .000378   .186913  .000975  I  .4154210  .0003552  2.7362 0.2349  P    11.284     .500    -2.532     .300   .012000   .190000   .4154000      .000      .000  
+80 4 3 44332.00 I   .007732  .000378   .187499  .000975  I  .4127132  .0003552  2.6754 0.2468  P    11.125     .500    -2.677     .300   .008990   .191000   .4127000      .000      .000  
+80 4 4 44333.00 I   .006145  .000378   .188098  .000975  I  .4100757  .0003428  2.5979 0.2468  P    10.989     .500    -2.801     .300   .007000   .192000   .4101000      .000      .000  
+80 4 5 44334.00 I   .004564  .000378   .188713  .000975  I  .4075181  .0003428  2.5183 0.2629  P    10.859     .500    -2.962     .300   .004000   .193000   .4075000      .000      .000  
+80 4 6 44335.00 I   .002985  .000116   .189344  .001015  I  .4050339  .0003987  2.4542 0.2629  P    10.829     .500    -3.143     .300   .002000   .194000   .4049000      .000      .000  
+80 4 7 44336.00 I   .001404  .000116   .189993  .001015  I  .4025986  .0003987  2.4232 0.2630  P    11.067     .500    -3.227     .300   .000000   .195000   .4022000      .000      .000  
+80 4 8 44337.00 I  -.000184  .003244   .190657  .000441  I  .4001715  .0003431  2.4401 0.2630  P    11.551     .500    -3.157     .300  -.003000   .196000   .3996000      .000      .000  
+80 4 9 44338.00 I  -.001784  .003244   .191338  .000441  I  .3976986  .0003431  2.5164 0.2470  P    11.991     .500    -3.051     .300  -.005000   .197000   .3969000      .000      .000  
+80 410 44339.00 I  -.003399  .003244   .192036  .000441  I  .3951184  .0003555  2.6537 0.2470  P    12.138     .500    -3.067     .300  -.007000   .198000   .3943000      .000      .000  
+80 411 44340.00 I  -.005035  .003244   .192749  .000441  I  .3923766  .0003555  2.8348 0.1860  P    12.078     .500    -3.185     .300  -.008990   .199000   .3916000      .000      .000  
+80 412 44341.00 I  -.006693  .003553   .193480  .000840  I  .3894468  .0001094  3.0217 0.1860  P    12.069     .500    -3.228     .300  -.011000   .200000   .3889000      .000      .000  
+80 413 44342.00 I  -.008371  .003553   .194228  .000840  I  .3863481  .0001094  3.1638 0.0630  P    12.169     .500    -3.123     .300  -.012000   .202000   .3863000      .000      .000  
+80 414 44343.00 I  -.010064  .002050   .194996  .001089  I  .3831491  .0000624  3.2162 0.0627  P    12.176     .500    -3.007     .300  -.014000   .203000   .3836000      .000      .000  
+80 415 44344.00 I  -.011767  .002405   .195783  .000950  I  .3799519  .0000613  3.1599 0.0437  P    11.904     .500    -3.031     .300  -.016000   .204000   .3809000      .000      .000  
+80 416 44345.00 I  -.013473  .002405   .196591  .000950  I  .3768602  .0000613  3.0107 0.1356  P    11.408     .500    -3.148     .300  -.017990   .205000   .3782000      .000      .000  
+80 417 44346.00 I  -.015173  .002923   .197424  .002939  I  .3739470  .0002642  2.8119 0.1632  P    10.976     .500    -3.216     .300  -.018990   .206000   .3756000      .000      .000  
+80 418 44347.00 I  -.016861  .003274   .198283  .003516  I  .3712357  .0003205  2.6154 0.2077  P    10.925     .500    -3.240     .300  -.021000   .208000   .3729000      .000      .000  
+80 419 44348.00 I  -.018531  .003274   .199172  .003516  I  .3687020  .0003205  2.4617 0.2070  P    11.322     .500    -3.367     .300  -.022000   .209000   .3703000      .000      .000  
+80 420 44349.00 I  -.020180  .003395   .200093  .003038  I  .3662917  .0002621  2.3699 0.2258  P    11.839     .500    -3.647     .300  -.024000   .210000   .3676000      .000      .000  
+80 421 44350.00 I  -.021803  .003688   .201050  .003679  I  .3639420  .0003181  2.3389 0.2061  P    12.018     .500    -3.925     .300  -.025000   .211000   .3650000      .000      .000  
+80 422 44351.00 I  -.023391  .003688   .202038  .003679  I  .3615979  .0003181  2.3561 0.2047  P    11.772     .500    -4.027     .300  -.027000   .213000   .3623000      .000      .000  
+80 423 44352.00 I  -.024933  .003606   .203054  .002158  I  .3592189  .0002576  2.4060 0.2047  P    11.503     .500    -3.946     .300  -.028000   .214000   .3597000      .000      .000  
+80 424 44353.00 I  -.026421  .003606   .204098  .002158  I  .3567803  .0002576  2.4727 0.1822  P    11.610     .500    -3.787     .300  -.030000   .216000   .3570000      .000      .000  
+80 425 44354.00 I  -.027852  .003606   .205166  .002158  I  .3542727  .0002576  2.5417 0.2268  P    12.018     .500    -3.604     .300  -.031000   .217000   .3544000      .000      .000  
+80 426 44355.00 I  -.029222  .003588   .206260  .002519  I  .3517004  .0003733  2.6001 0.2268  P    12.332     .500    -3.379     .300  -.032000   .218000   .3518000      .000      .000  
+80 427 44356.00 I  -.030530  .003588   .207376  .002519  I  .3490794  .0003733  2.6376 0.2640  P    12.341     .500    -3.135     .300  -.033000   .220000   .3492000      .000      .000  
+80 428 44357.00 I  -.031780  .003588   .208512  .002519  I  .3464344  .0003733  2.6474 0.2186  P    12.156     .500    -2.967     .300  -.035000   .221000   .3465000      .000      .000  
+80 429 44358.00 I  -.032974  .000383   .209662  .001127  I  .3437946  .0002276  2.6273 0.2186  P    11.947     .500    -2.950     .300  -.035990   .223000   .3439000      .000      .000  
+80 430 44359.00 I  -.034117  .000383   .210823  .001127  I  .3411890  .0002276  2.5795 0.1609  P    11.769     .500    -3.060     .300  -.037000   .224000   .3413000      .000      .000  
+80 5 1 44360.00 I  -.035211  .000383   .211990  .001127  I  .3386427  .0002276  2.5105 0.1207  P    11.635     .500    -3.213     .300  -.037990   .225000   .3387000      .000      .000  
+80 5 2 44361.00 I  -.036260  .000383   .213160  .001127  I  .3361710  .0000802  2.4327 0.1896  P    11.567     .500    -3.356     .300  -.039000   .226000   .3362000      .000      .000  
+80 5 3 44362.00 I  -.037268  .000710   .214328  .001256  I  .3337745  .0003033  2.3633 0.1569  P    11.534     .500    -3.489     .300  -.040000   .228000   .3336000      .000      .000  
+80 5 4 44363.00 I  -.038237  .000710   .215493  .001256  I  .3314354  .0003033  2.3209 0.2468  P    11.476     .500    -3.617     .300  -.041000   .229000   .3311000      .000      .000  
+80 5 5 44364.00 I  -.039170  .000929   .216651  .001372  I  .3291184  .0003893  2.3215 0.2247  P    11.438     .500    -3.710     .300  -.042000   .230000   .3285000      .000      .000  
+80 5 6 44365.00 I  -.040070  .002420   .217799  .001039  I  .3267747  .0003316  2.3753 0.2557  P    11.552     .500    -3.734     .300  -.043000   .231000   .3260000      .000      .000  
+80 5 7 44366.00 I  -.040940  .002420   .218938  .001039  I  .3243499  .0003316  2.4829 0.2675  P    11.871     .500    -3.689     .300  -.044000   .232000   .3235000      .000      .000  
+80 5 8 44367.00 I  -.041786  .002115   .220064  .000854  I  .3217946  .0004199  2.6335 0.2757  P    12.282     .500    -3.599     .300  -.044000   .234000   .3210000      .000      .000  
+80 5 9 44368.00 I  -.042610  .002505   .221179  .000392  I  .3190770  .0004406  2.8018 0.3043  P    12.601     .500    -3.453     .300  -.045000   .235000   .3185000      .000      .000  
+80 510 44369.00 I  -.043412  .002505   .222281  .000392  I  .3161979  .0004406  2.9492 0.2980  P    12.684     .500    -3.232     .300  -.046000   .236000   .3160000      .000      .000  
+80 511 44370.00 I  -.044191  .002781   .223371  .000980  I  .3131995  .0004013  3.0338 0.3204  P    12.464     .500    -3.001     .300  -.047000   .237000   .3135000      .000      .000  
+80 512 44371.00 I  -.044944  .002485   .224447  .001141  I  .3101614  .0004652  3.0253 0.3072  P    11.970     .500    -2.918     .300  -.047000   .238000   .3111000      .000      .000  
+80 513 44372.00 I  -.045667  .002485   .225511  .001141  I  .3071817  .0004652  2.9186 0.2686  P    11.347     .500    -3.075     .300  -.048000   .240000   .3086000      .000      .000  
+80 514 44373.00 I  -.046356  .002451   .226563  .001650  I  .3043487  .0002685  2.7383 0.2686  P    10.806     .500    -3.353     .300  -.048000   .241000   .3062000      .000      .000  
+80 515 44374.00 I  -.047008  .002451   .227603  .001650  I  .3017146  .0002685  2.5295 0.1899  P    10.542     .500    -3.528     .300  -.049000   .242000   .3037000      .000      .000  
+80 516 44375.00 I  -.047627  .002451   .228634  .001650  I  .2992833  .0002685  2.3399 0.1743  P    10.660     .500    -3.527     .300  -.050000   .243000   .3014000      .000      .000  
+80 517 44376.00 I  -.048213  .001173   .229657  .001694  I  .2970177  .0002223  2.2016 0.1556  P    11.099     .500    -3.498     .300  -.050000   .244000   .2990000      .000      .000  
+80 518 44377.00 I  -.048768  .001357   .230674  .001407  I  .2948597  .0001572  2.1246 0.1361  P    11.564     .500    -3.596     .300  -.051000   .245000   .2967000      .000      .000  
+80 519 44378.00 I  -.049291  .001357   .231685  .001407  I  .2927505  .0001572  2.1018 0.0803  P    11.695     .500    -3.784     .300  -.051000   .246000   .2943000      .000      .000  
+80 520 44379.00 I  -.049783  .001641   .232689  .001000  I  .2906432  .0000329  2.1179 0.0803  P    11.414     .500    -3.897     .300  -.052000   .247000   .2920000      .000      .000  
+80 521 44380.00 I  -.050242  .001641   .233687  .001000  I  .2885074  .0000329  2.1559 0.0233  P    11.044     .500    -3.859     .300  -.052000   .248000   .2897000      .000      .000  
+80 522 44381.00 I  -.050670  .001641   .234679  .001000  I  .2863292  .0000329  2.2004 0.0447  P    10.958     .500    -3.738     .300  -.052000   .249000   .2874000      .000      .000  
+80 523 44382.00 I  -.051071  .001641   .235667  .001000  I  .2841089  .0000832  2.2380 0.0860  P    11.144     .500    -3.616     .300  -.053000   .250000   .2852000      .000      .000  
+80 524 44383.00 I  -.051448  .001657   .236653  .000683  I  .2818591  .0001688  2.2579 0.0941  P    11.281     .500    -3.499     .300  -.053000   .250990   .2829000      .000      .000  
+80 525 44384.00 I  -.051806  .001657   .237638  .000683  I  .2796014  .0001688  2.2529 0.1186  P    11.158     .500    -3.354     .300  -.053000   .252000   .2806000      .000      .000  
+80 526 44385.00 I  -.052152  .003978   .238627  .000900  I  .2773624  .0001667  2.2206 0.1186  P    10.860     .500    -3.186     .300  -.053000   .253000   .2784000      .000      .000  
+80 527 44386.00 I  -.052492  .003978   .239621  .000900  I  .2751687  .0001667  2.1628 0.1179  P    10.559     .500    -3.045     .300  -.053000   .254000   .2762000      .000      .000  
+80 528 44387.00 I  -.052829  .003978   .240622  .000900  I  .2730435  .0001667  2.0849 0.1167  P    10.331     .500    -2.990     .300  -.054000   .255000   .2741000      .000      .000  
+80 529 44388.00 I  -.053166  .003978   .241634  .000900  I  .2710025  .0001635  1.9961 0.1250  P    10.201     .500    -3.048     .300  -.054000   .256000   .2719000      .000      .000  
+80 530 44389.00 I  -.053503  .004237   .242657  .001801  I  .2690501  .0001863  1.9107 0.1239  P    10.206     .500    -3.188     .300  -.054000   .257000   .2697000      .000      .000  
+80 531 44390.00 I  -.053835  .004237   .243694  .001801  I  .2671735  .0001863  1.8479 0.1851  P    10.305     .500    -3.328     .300  -.054000   .257990   .2676000      .000      .000  
+80 6 1 44391.00 I  -.054155  .002580   .244745  .002210  I  .2653405  .0003200  1.8264 0.1609  P    10.330     .500    -3.394     .300  -.054000   .259000   .2655000      .000      .000  
+80 6 2 44392.00 I  -.054454  .002290   .245810  .001568  I  .2635027  .0002624  1.8589 0.2069  P    10.163     .500    -3.384     .300  -.054000   .260000   .2634000      .000      .000  
+80 6 3 44393.00 I  -.054729  .002290   .246888  .001568  I  .2616043  .0002624  1.9465 0.1695  P     9.916     .500    -3.348     .300  -.054000   .261000   .2613000      .000      .000  
+80 6 4 44394.00 I  -.054978  .002256   .247978  .001657  I  .2595953  .0002145  2.0772 0.1634  P     9.844     .500    -3.314     .300  -.054000   .262000   .2592000      .000      .000  
+80 6 5 44395.00 I  -.055198  .002074   .249076  .001294  I  .2574431  .0001947  2.2282 0.1448  P    10.078     .500    -3.245     .300  -.054000   .263000   .2572000      .000      .000  
+80 6 6 44396.00 I  -.055390  .002074   .250181  .001294  I  .2551422  .0001947  2.3692 0.1125  P    10.469     .500    -3.083     .300  -.054000   .264000   .2551000      .000      .000  
+80 6 7 44397.00 I  -.055555  .002074   .251291  .001294  I  .2527187  .0001129  2.4681 0.1774  P    10.684     .500    -2.835     .300  -.054000   .264000   .2531000      .000      .000  
+80 6 8 44398.00 I  -.055697  .004688   .252403  .001294  I  .2502291  .0002966  2.4977 0.1587  P    10.457     .500    -2.607     .300  -.054000   .264990   .2509990      .000      .000  
+80 6 9 44399.00 I  -.055819  .004688   .253518  .001294  I  .2477506  .0002966  2.4454 0.2197  P     9.787     .500    -2.552     .300  -.054000   .266000   .2490000      .000      .000  
+80 610 44400.00 I  -.055929  .004586   .254635  .001408  I  .2453624  .0003241  2.3207 0.2197  P     8.946     .500    -2.741     .300  -.054000   .266990   .2470000      .000      .000  
+80 611 44401.00 I  -.056030  .004586   .255754  .001408  I  .2431236  .0003241  2.1528 0.2292  P     8.299     .500    -3.070     .300  -.054000   .268000   .2451000      .000      .000  
+80 612 44402.00 I  -.056121  .004586   .256876  .001408  I  .2410578  .0003241  1.9819 0.2292  P     8.073     .500    -3.317     .300  -.053000   .268000   .2431000      .000      .000  
+80 613 44403.00 I  -.056197  .004586   .258000  .001408  I  .2391486  .0003241  1.8446 0.1662  P     8.267     .500    -3.350     .300  -.053000   .269000   .2412000      .000      .000  
+80 614 44404.00 I  -.056252  .002177   .259130  .001585  I  .2373506  .0000740  1.7614 0.1662  P     8.683     .500    -3.247     .300  -.053000   .270000   .2392000      .000      .000  
+80 615 44405.00 I  -.056283  .002177   .260267  .001585  I  .2356071  .0000740  1.7341 0.0445  P     9.045     .500    -3.188     .300  -.053000   .271000   .2373000      .000      .000  
+80 616 44406.00 I  -.056288  .001876   .261414  .001590  I  .2338680  .0000494  1.7498 0.0445  P     9.135     .500    -3.248     .300  -.053000   .271000   .2355000      .000      .000  
+80 617 44407.00 I  -.056263  .001876   .262575  .001590  I  .2320990  .0000494  1.7910 0.0349  P     8.920     .500    -3.340     .300  -.052000   .272000   .2336000      .000      .000  
+80 618 44408.00 I  -.056206  .001876   .263751  .001590  I  .2302829  .0000494  1.8415 0.1129  P     8.566     .500    -3.371     .300  -.052000   .272000   .2318000      .000      .000  
+80 619 44409.00 I  -.056120  .001783   .264944  .001318  I  .2284177  .0002204  1.8870 0.1350  P     8.280     .500    -3.351     .300  -.052000   .273000   .2299000      .000      .000  
+80 620 44410.00 I  -.056007  .001211   .266154  .001435  I  .2265144  .0002654  1.9161 0.1725  P     8.121     .500    -3.343     .300  -.051000   .273990   .2281000      .000      .000  
+80 621 44411.00 I  -.055869  .001211   .267379  .001435  I  .2245938  .0002654  1.9203 0.1906  P     7.988     .500    -3.349     .300  -.051000   .273990   .2263000      .000      .000  
+80 622 44412.00 I  -.055710  .004611   .268620  .000645  I  .2226833  .0002737  1.8958 0.1906  P     7.765     .500    -3.300     .300  -.050000   .275000   .2245000      .000      .000  
+80 623 44413.00 I  -.055531  .004611   .269874  .000645  I  .2208110  .0002737  1.8448 0.1935  P     7.422     .500    -3.137     .300  -.050000   .275000   .2227000      .000      .000  
+80 624 44414.00 I  -.055334  .004611   .271140  .000645  I  .2190006  .0002737  1.7731 0.1448  P     7.010     .500    -2.883     .300  -.049000   .276000   .2209000      .000      .000  
+80 625 44415.00 I  -.055118  .006326   .272416  .000823  I  .2172690  .0000947  1.6887 0.2162  P     6.629     .500    -2.646     .300  -.048000   .277000   .2192000      .000      .000  
+80 626 44416.00 I  -.054881  .005269   .273700  .000678  I  .2156238  .0003348  1.6024 0.1740  P     6.395     .500    -2.556     .300  -.048000   .277000   .2175000      .000      .000  
+80 627 44417.00 I  -.054612  .005269   .274989  .000678  I  .2140596  .0003348  1.5299 0.2861  P     6.382     .500    -2.662     .300  -.047000   .278000   .2157000      .000      .000  
+80 628 44418.00 I  -.054299  .003938   .276282  .000493  I  .2125530  .0004640  1.4905 0.2413  P     6.533     .500    -2.864     .300  -.047000   .278000   .2140000      .000      .000  
+80 629 44419.00 I  -.053930  .011309   .277574  .003053  I  .2110616  .0003477  1.5022 0.2899  P     6.666     .500    -2.992     .300  -.046000   .279000   .2123000      .000      .000  
+80 630 44420.00 I  -.053497  .011309   .278865  .003053  I  .2095287  .0003477  1.5736 0.2904  P     6.614     .500    -2.956     .300  -.045000   .280000   .2106000      .000      .000  
+80 7 1 44421.00 I  -.052996  .011321   .280150  .003820  I  .2078977  .0004653  1.6952 0.2907  P     6.375     .500    -2.827     .300  -.044000   .280000   .2089000      .000      .000  
+80 7 2 44422.00 I  -.052422  .013582   .281429  .004665  I  .2061299  .0004659  1.8419 0.3292  P     6.114     .500    -2.732     .300  -.044000   .280990   .2073000      .000      .000  
+80 7 3 44423.00 I  -.051780  .013582   .282702  .004665  I  .2042170  .0004659  1.9794 0.3294  P     6.016     .500    -2.716     .300  -.043000   .280990   .2056000      .000      .000  
+80 7 4 44424.00 I  -.051095  .013582   .283971  .004665  I  .2021850  .0004659  2.0751 0.3591  P     6.120     .500    -2.723     .300  -.042000   .282000   .2039000      .000      .000  
+80 7 5 44425.00 I  -.050384  .008098   .285238  .003602  I  .2000888  .0005465  2.1048 0.3591  P     6.263     .500    -2.691     .300  -.041000   .283000   .2022000      .000      .000  
+80 7 6 44426.00 I  -.049652  .008098   .286501  .003602  I  .1980003  .0005465  2.0600 0.3730  P     6.193     .500    -2.637     .300  -.041000   .283000   .2006000      .000      .000  
+80 7 7 44427.00 I  -.048902  .004104   .287755  .003600  I  .1959907  .0005077  1.9497 0.3730  P     5.761     .500    -2.644     .300  -.040000   .284000   .1989000      .000      .000  
+80 7 8 44428.00 I  -.048137  .004104   .288998  .003600  I  .1941150  .0005077  1.7970 0.3590  P     5.068     .500    -2.776     .300  -.040000   .284000   .1973000      .000      .000  
+80 7 9 44429.00 I  -.047357  .004104   .290226  .003600  I  .1924001  .0005077  1.6340 0.3590  P     4.420     .500    -3.011     .300  -.039000   .285000   .1956000      .000      .000  
+80 710 44430.00 I  -.046564  .004104   .291435  .003600  I  .1908393  .0005077  1.4941 0.3638  P     4.120     .500    -3.234     .300  -.037990   .286000   .1939000      .000      .000  
+80 711 44431.00 I  -.045762  .005388   .292623  .003541  I  .1893957  .0005212  1.4027 0.3638  P     4.256     .500    -3.328     .300  -.037990   .287000   .1923000      .000      .000  
+80 712 44432.00 I  -.044962  .005388   .293793  .003541  I  .1880149  .0005212  1.3683 0.3127  P     4.644     .500    -3.288     .300  -.037000   .287000   .1906000      .000      .000  
+80 713 44433.00 I  -.044175  .004264   .294946  .001270  I  .1866427  .0003457  1.3831 0.3127  P     5.002     .500    -3.203     .300  -.037000   .287990   .1890000      .000      .000  
+80 714 44434.00 I  -.043412  .004264   .296085  .001270  I  .1852377  .0003457  1.4310 0.2444  P     5.152     .500    -3.154     .300  -.035990   .289000   .1873000      .000      .000  
+80 715 44435.00 I  -.042680  .004264   .297212  .001270  I  .1837753  .0003457  1.4952 0.2444  P     5.073     .500    -3.137     .300  -.035000   .290000   .1857000      .000      .000  
+80 716 44436.00 I  -.041982  .004264   .298330  .001270  I  .1822469  .0003457  1.5607 0.2423  P     4.808     .500    -3.125     .300  -.035000   .291000   .1841000      .000      .000  
+80 717 44437.00 I  -.041317  .004120   .299440  .002369  I  .1806576  .0003396  1.6153 0.2423  P     4.418     .500    -3.142     .300  -.034000   .291000   .1824000      .000      .000  
+80 718 44438.00 I  -.040682  .004120   .300543  .002369  I  .1790231  .0003396  1.6496 0.2386  P     4.024     .500    -3.220     .300  -.034000   .292000   .1808000      .000      .000  
+80 719 44439.00 I  -.040070  .003623   .301639  .002290  I  .1773670  .0003352  1.6582 0.2386  P     3.763     .500    -3.320     .300  -.033000   .293000   .1792000      .000      .000  
+80 720 44440.00 I  -.039481  .003623   .302728  .002290  I  .1757154  .0003352  1.6408 0.2370  P     3.629     .500    -3.341     .300  -.032000   .294000   .1776000      .000      .000  
+80 721 44441.00 I  -.038915  .003623   .303805  .002290  I  .1740930  .0003352  1.6006 0.2274  P     3.428     .500    -3.218     .300  -.032000   .294000   .1760000      .000      .000  
+80 722 44442.00 I  -.038378  .004011   .304868  .002431  I  .1725194  .0003074  1.5448 0.3275  P     3.007     .500    -2.976     .300  -.031000   .294990   .1743000      .000      .000  
+80 723 44443.00 I  -.037876  .003453   .305911  .002205  I  .1710052  .0005628  1.4835 0.1701  P     2.484     .500    -2.713     .300  -.031000   .294990   .1727000      .000      .000  
+80 724 44444.00 I  -.037416  .001017   .306930  .000822  I  .1695499  .0001457  1.4295 0.2870  P     2.138     .500    -2.558     .300  -.030000   .296000   .1711000      .000      .000  
+80 725 44445.00 I  -.037005  .000753   .307918  .001028  I  .1681384  .0001127  1.3988 0.0923  P     2.101     .500    -2.609     .300  -.030000   .297000   .1695000      .000      .000  
+80 726 44446.00 I  -.036652  .000749   .308869  .001035  I  .1667384  .0001133  1.4097 0.0798  P     2.251     .500    -2.840     .300  -.029000   .297000   .1679000      .000      .000  
+80 727 44447.00 I  -.036373  .000749   .309774  .001035  I  .1653007  .0001129  1.4755 0.0795  P     2.396     .500    -3.078     .300  -.029000   .298000   .1662000      .000      .000  
+80 728 44448.00 I  -.036176  .000571   .310620  .001099  I  .1637689  .0001116  1.5970 0.0587  P     2.457     .500    -3.132     .300  -.028000   .298000   .1646000      .000      .000  
+80 729 44449.00 I  -.036043  .000571   .311387  .001099  I  .1620941  .0000322  1.7564 0.0603  P     2.433     .500    -2.977     .300  -.028000   .299000   .1630000      .000      .000  
+80 730 44450.00 I  -.035959  .000571   .312081  .001099  I  .1602557  .0000457  1.9169 0.0441  P     2.307     .500    -2.780     .300  -.028000   .299000   .1614000      .000      .000  
+80 731 44451.00 I  -.035911  .000476   .312715  .001427  I  .1582745  .0000822  2.0349 0.1115  P     2.085     .500    -2.715     .300  -.027000   .300000   .1598000      .000      .000  
+80 8 1 44452.00 I  -.035885  .002027   .313299  .003060  I  .1562108  .0002183  2.0783 0.1242  P     1.853     .500    -2.803     .300  -.027000   .300000   .1581000      .000      .000  
+80 8 2 44453.00 I  -.035873  .002027   .313843  .003060  I  .1541461  .0002343  2.0372 0.1779  P     1.712     .500    -2.935     .300  -.026000   .301000   .1565000      .000      .000  
+80 8 3 44454.00 I  -.035866  .001859   .314353  .001591  I  .1521605  .0002809  1.9239 0.1829  P     1.663     .500    -3.022     .300  -.026000   .301000   .1549000      .000      .000  
+80 8 4 44455.00 I  -.035856  .001859   .314838  .001591  I  .1503126  .0002809  1.7676 0.1897  P     1.582     .500    -3.072     .300  -.026000   .301990   .1533000      .000      .000  
+80 8 5 44456.00 I  -.035834  .001859   .315303  .001591  I  .1486280  .0002549  1.6034 0.1619  P     1.357     .500    -3.143     .300  -.025000   .301990   .1517000      .000      .000  
+80 8 6 44457.00 I  -.035796  .002414   .315753  .001929  I  .1470977  .0001612  1.4637 0.1603  P     1.028     .500    -3.262     .300  -.025000   .303000   .1500000      .000      .000  
+80 8 7 44458.00 I  -.035736  .002722   .316194  .001863  I  .1456845  .0001945  1.3722 0.1263  P      .797     .500    -3.398     .300  -.024000   .303000   .1484000      .000      .000  
+80 8 8 44459.00 I  -.035652  .002722   .316631  .001863  I  .1443340  .0001945  1.3386 0.0999  P      .852     .500    -3.500     .300  -.024000   .303990   .1468000      .000      .000  
+80 8 9 44460.00 I  -.035543  .003253   .317071  .002470  I  .1429894  .0000461  1.3586 0.1023  P     1.178     .500    -3.533     .300  -.024000   .305000   .1451000      .000      .000  
+80 810 44461.00 I  -.035410  .002307   .317518  .001896  I  .1416036  .0000636  1.4181 0.0393  P     1.569     .500    -3.487     .300  -.023000   .305000   .1435000      .000      .000  
+80 811 44462.00 I  -.035258  .002307   .317974  .001896  I  .1401463  .0000636  1.4984 0.0533  P     1.827     .500    -3.358     .300  -.023000   .306000   .1418000      .000      .000  
+80 812 44463.00 I  -.035091  .000542   .318443  .001027  I  .1386056  .0000855  1.5823 0.0533  P     1.881     .500    -3.163     .300  -.022000   .306000   .1402000      .000      .000  
+80 813 44464.00 I  -.034914  .000542   .318927  .001027  I  .1369849  .0000855  1.6566 0.0605  P     1.728     .500    -2.979     .300  -.022000   .307000   .1385000      .000      .000  
+80 814 44465.00 I  -.034730  .000542   .319428  .001027  I  .1352991  .0000855  1.7110 0.0605  P     1.393     .500    -2.921     .300  -.022000   .308000   .1368000      .000      .000  
+80 815 44466.00 I  -.034545  .000542   .319948  .001027  I  .1335716  .0000855  1.7394 0.0978  P     1.033     .500    -3.029     .300  -.021000   .308000   .1351000      .000      .000  
+80 816 44467.00 I  -.034361  .000944   .320488  .001281  I  .1318295  .0001759  1.7401 0.0978  P      .895     .500    -3.205     .300  -.021000   .308990   .1333000      .000      .000  
+80 817 44468.00 I  -.034185  .000944   .321048  .001281  I  .1300996  .0001759  1.7162 0.1451  P     1.017     .500    -3.297     .300  -.020000   .308990   .1316000      .000      .000  
+80 818 44469.00 I  -.034021  .001122   .321629  .001503  I  .1284021  .0002307  1.6772 0.1201  P     1.082     .500    -3.255     .300  -.020000   .310000   .1298990      .000      .000  
+80 819 44470.00 I  -.033876  .001473   .322231  .002151  I  .1267463  .0001635  1.6349 0.1414  P      .771     .500    -3.136     .300  -.020000   .310990   .1280990      .000      .000  
+80 820 44471.00 I  -.033753  .001473   .322852  .002151  I  .1251295  .0001635  1.6011 0.1082  P      .200     .500    -3.009     .300  -.020000   .310990   .1263000      .000      .000  
+80 821 44472.00 I  -.033655  .002643   .323491  .001843  I  .1235369  .0001418  1.5891 0.0870  P     -.191     .500    -2.910     .300  -.018990   .312000   .1244000      .000      .000  
+80 822 44473.00 I  -.033585  .003139   .324146  .001991  I  .1219387  .0000597  1.6150 0.0769  P     -.189     .500    -2.895     .300  -.018990   .312000   .1226000      .000      .000  
+80 823 44474.00 I  -.033544  .003139   .324811  .001991  I  .1202889  .0000597  1.6951 0.0422  P      .000     .500    -3.025     .300  -.018990   .313000   .1208000      .000      .000  
+80 824 44475.00 I  -.033532  .003139   .325482  .001991  I  .1185273  .0000597  1.8389 0.0595  P      .109     .500    -3.242     .300  -.018990   .313000   .1189000      .000      .000  
+80 825 44476.00 I  -.033545  .003095   .326154  .002490  I  .1165928  .0001030  2.0377 0.0595  P      .140     .500    -3.348     .300  -.018990   .314000   .1170000      .000      .000  
+80 826 44477.00 I  -.033575  .003095   .326823  .002490  I  .1144442  .0001030  2.2596 0.0760  P      .207     .500    -3.213     .300  -.017990   .314000   .1151000      .000      .000  
+80 827 44478.00 I  -.033616  .002868   .327484  .002436  I  .1120823  .0001117  2.4553 0.0760  P      .265     .500    -2.945     .300  -.017990   .315000   .1132000      .000      .000  
+80 828 44479.00 I  -.033658  .002868   .328135  .002436  I  .1095587  .0001117  2.5758 0.0790  P      .145     .500    -2.779     .300  -.017990   .315000   .1113000      .000      .000  
+80 829 44480.00 I  -.033692  .002868   .328774  .002436  I  .1069650  .0001117  2.5933 0.0790  P     -.195     .500    -2.809     .300  -.017990   .315000   .1093000      .000      .000  
+80 830 44481.00 I  -.033706  .002868   .329403  .002436  I  .1044053  .0001117  2.5113 0.0703  P     -.591     .500    -2.925     .300  -.017990   .316000   .1073000      .000      .000  
+80 831 44482.00 I  -.033692  .002928   .330022  .000447  I  .1019650  .0000854  2.3616 0.0703  P     -.829     .500    -2.997     .300  -.017000   .316000   .1052000      .000      .000  
+80 9 1 44483.00 I  -.033648  .002928   .330632  .000447  I  .0996895  .0000854  2.1897 0.0456  P     -.830     .500    -3.032     .300  -.017000   .317000   .1032000      .000      .000  
+80 9 2 44484.00 I  -.033568  .001883   .331235  .000068  I  .0975787  .0000320  2.0384 0.0456  P     -.689     .500    -3.114     .300  -.017000   .317000   .1012000      .000      .000  
+80 9 3 44485.00 I  -.033449  .001883   .331832  .000068  I  .0955965  .0000320  1.9358 0.0226  P     -.583     .500    -3.254     .300  -.017000   .317990   .0991000      .000      .000  
+80 9 4 44486.00 I  -.033291  .001883   .332424  .000068  I  .0936871  .0000320  1.8934 0.0226  P     -.580     .500    -3.380     .300  -.016000   .317990   .0969000      .000      .000  
+80 9 5 44487.00 I  -.033093  .001883   .333013  .000068  I  .0917909  .0000320  1.9076 0.0192  P     -.562     .500    -3.445     .300  -.016000   .319000   .0948000      .000      .000  
+80 9 6 44488.00 I  -.032856  .001388   .333598  .000202  I  .0898578  .0000212  1.9643 0.0192  P     -.375     .500    -3.457     .300  -.015000   .319000   .0926000      .000      .000  
+80 9 7 44489.00 I  -.032585  .001388   .334183  .000202  I  .0878542  .0000212  2.0453 0.0157  P     -.035     .500    -3.409     .300  -.015000   .320000   .0905000      .000      .000  
+80 9 8 44490.00 I  -.032281  .000025   .334766  .000279  I  .0857654  .0000231  2.1318 0.0464  P      .288     .500    -3.246     .300  -.015000   .321000   .0883000      .000      .000  
+80 9 9 44491.00 I  -.031950  .000932   .335350  .000197  I  .0835940  .0000903  2.2082 0.0466  P      .450     .500    -2.942     .300  -.014000   .321000   .0861000      .000      .000  
+80 910 44492.00 I  -.031593  .000932   .335936  .000197  I  .0813562  .0000903  2.2632 0.0998  P      .421     .500    -2.612     .300  -.014000   .322000   .0838000      .000      .000  
+80 911 44493.00 I  -.031215  .000901   .336526  .000813  I  .0790771  .0001779  2.2898 0.1177  P      .264     .500    -2.449     .300  -.013000   .322000   .0816000      .000      .000  
+80 912 44494.00 I  -.030818  .001104   .337119  .000976  I  .0767870  .0002173  2.2852 0.1404  P      .133     .500    -2.537     .300  -.013000   .323000   .0794000      .000      .000  
+80 913 44495.00 I  -.030404  .001104   .337719  .000976  I  .0745165  .0002173  2.2511 0.1751  P      .227     .500    -2.753     .300  -.013000   .324000   .0771000      .000      .000  
+80 914 44496.00 I  -.029974  .000902   .338327  .001336  I  .0722922  .0002747  2.1948 0.1953  P      .562     .500    -2.904     .300  -.012000   .324000   .0748000      .000      .000  
+80 915 44497.00 I  -.029527  .000594   .338943  .001637  I  .0701300  .0003245  2.1293 0.2219  P      .823     .500    -2.937     .300  -.012000   .324990   .0724000      .000      .000  
+80 916 44498.00 I  -.029065  .000594   .339567  .001637  I  .0680318  .0003485  2.0693 0.2334  P      .659     .500    -2.944     .300  -.011000   .324990   .0701000      .000      .000  
+80 917 44499.00 I  -.028584  .002438   .340199  .002022  I  .0659849  .0003355  2.0289 0.2381  P      .159     .500    -2.978     .300  -.011000   .326000   .0678000      .000      .000  
+80 918 44500.00 I  -.028086  .002438   .340837  .002022  I  .0639626  .0003246  2.0227 0.2277  P     -.207     .500    -2.983     .300  -.011000   .327000   .0653990      .000      .000  
+80 919 44501.00 I  -.027570  .002438   .341480  .002022  I  .0619229  .0003079  2.0662 0.2126  P     -.154     .500    -2.921     .300  -.010000   .327000   .0630000      .000      .000  
+80 920 44502.00 I  -.027034  .002693   .342124  .004047  I  .0598094  .0002745  2.1721 0.1997  P      .119     .500    -2.873     .300  -.010000   .328000   .0607000      .000      .000  
+80 921 44503.00 I  -.026481  .002693   .342766  .004047  I  .0575568  .0002544  2.3439 0.1775  P      .289     .500    -2.903     .300  -.008990   .328000   .0583000      .000      .000  
+80 922 44504.00 I  -.025918  .002693   .343399  .004047  I  .0551051  .0002252  2.5654 0.1603  P      .329     .500    -2.918     .300  -.008990   .329000   .0559000      .000      .000  
+80 923 44505.00 I  -.025350  .001619   .344019  .005294  I  .0524227  .0001951  2.7968 0.1311  P      .411     .500    -2.770     .300  -.008990   .330000   .0534000      .000      .000  
+80 924 44506.00 I  -.024784  .000801   .344617  .001255  I  .0495267  .0001342  2.9828 0.1101  P      .563     .500    -2.503     .300  -.008000   .331000   .0510000      .000      .000  
+80 925 44507.00 I  -.024228  .000543   .345183  .001540  I  .0464885  .0001023  3.0748 0.0822  P      .623     .500    -2.327     .300  -.008000   .332000   .0485000      .000      .000  
+80 926 44508.00 I  -.023692  .000467   .345704  .001118  I  .0434152  .0000950  3.0524 0.0700  P      .467     .500    -2.344     .300  -.007000   .333000   .0461000      .000      .000  
+80 927 44509.00 I  -.023185  .000570   .346167  .001768  I  .0404165  .0000956  2.9316 0.0660  I     -.660    1.471    -2.476     .528  -.007000   .334000   .0436000      .000      .000  
+80 928 44510.00 I  -.022722  .000515   .346558  .001644  I  .0375738  .0000917  2.7456 0.0680  I     -.993    1.386    -2.515     .626  -.007000   .335000   .0411000      .000      .000  
+80 929 44511.00 I  -.022320  .000514   .346877  .001673  I  .0349343  .0000966  2.5328 0.0661  I    -1.152    1.658    -2.512     .660  -.007000   .336000   .0385000      .000      .000  
+80 930 44512.00 I  -.021988  .000499   .347173  .001613  I  .0324995  .0000951  2.3463 0.0637  I    -1.074    1.927    -2.591     .647  -.006000   .337000   .0360000      .000      .000  
+8010 1 44513.00 I  -.021717  .000547   .347498  .001781  I  .0302196  .0000831  2.2263 0.0661  I     -.882    1.882    -2.771     .648  -.006000   .338000   .0334000      .000      .000  
+8010 2 44514.00 I  -.021472  .000633   .347867  .001801  I  .0280224  .0000919  2.1799 0.0644  I     -.806    1.681    -2.929     .620  -.006000   .339000   .0309000      .000      .000  
+8010 3 44515.00 I  -.021217  .001128   .348281  .002333  I  .0258395  .0000985  2.1946 0.0666  I     -.930    2.409    -2.945     .977  -.006000   .340000   .0283000      .000      .000  
+8010 4 44516.00 I  -.020922  .001231   .348738  .000922  I  .0236201  .0000965  2.2486 0.0740  I    -1.047    2.764    -2.867     .787  -.006000   .341000   .0258000      .000      .000  
+8010 5 44517.00 I  -.020573  .002357   .349238  .001086  I  .0213366  .0001105  2.3195 0.0734  I     -.949    2.622    -2.792     .618  -.005000   .341000   .0232000      .000      .000  
+8010 6 44518.00 I  -.020162  .002357   .349784  .001086  I  .0189812  .0001105  2.3900 0.1465  I     -.721    1.266    -2.706     .792  -.005000   .342000   .0207000      .000      .000  
+8010 7 44519.00 I  -.019683  .005552   .350378  .002087  I  .0165613  .0002714  2.4464 0.1954  I     -.580    1.982    -2.539     .868  -.005000   .343000   .0181000      .000      .000  
+8010 8 44520.00 I  -.019138  .004820   .351018  .002289  I  .0140960  .0003749  2.4799 0.2553  I     -.600    1.982    -2.332     .868  -.005000   .344000   .0155000      .000      .000  
+8010 9 44521.00 I  -.018535  .003477   .351705  .002418  I  .0116109  .0004325  2.4853 0.2862  I     -.682    1.982    -2.248     .868  -.005000   .345000   .0129000      .000      .000  
+801010 44522.00 I  -.017881  .003477   .352436  .002418  I  .0091350  .0004325  2.4618 0.3161  I     -.679    1.982    -2.389     .868  -.004000   .345000   .0103000      .000      .000  
+801011 44523.00 I  -.017190  .002022   .353206  .003017  I  .0066954  .0004610  2.4138 0.3161  I     -.488    1.982    -2.663     .868  -.004000   .346000   .0077000      .000      .000  
+801012 44524.00 I  -.016473  .002022   .354013  .003017  I  .0043126  .0004610  2.3501 0.3260  I     -.112    1.982    -2.889     .868  -.004000   .347000   .0051000      .000      .000  
+801013 44525.00 I  -.015748  .002022   .354848  .003017  I  .0019960  .0004610  2.2842 0.2345  I      .270    1.982    -2.996     .868  -.004000   .348000   .0025000      .000      .000  
+801014 44526.00 I  -.015032  .000542   .355706  .001021  I -.0002604  .0000860  2.2323 0.2344  I      .426    1.982    -3.053     .868  -.004000   .349000  -.0002000      .000      .000  
+801015 44527.00 I  -.014340  .001289   .356578  .000752  I -.0024781  .0000855  2.2089 0.0589  I      .377    1.428    -3.098     .685  -.004000   .349000  -.0028000      .000      .000  
+801016 44528.00 I  -.013690  .001154   .357455  .001460  I -.0046917  .0000804  2.2261 0.0557  I      .448    1.401    -3.038     .727  -.004000   .350000  -.0055000      .000      .000  
+801017 44529.00 I  -.013099  .001067   .358326  .001278  I -.0069477  .0000715  2.2954 0.0538  I      .914    1.613    -2.765     .714  -.004000   .351000  -.0081000      .000      .000  
+801018 44530.00 I  -.012591  .000945   .359173  .001190  I -.0093009  .0000716  2.4198 0.0501  I     1.707    1.554    -2.315     .717  -.004000   .352000  -.0108000      .000      .000  
+801019 44531.00 I  -.012196  .001057   .359957  .001123  I -.0118060  .0000702  2.6002 0.0460  I     2.454    1.415    -1.924     .606  -.004000   .353000  -.0135000      .000      .000  
+801020 44532.00 I  -.011860  .000983   .360634  .001100  I -.0145143  .0000577  2.8197 0.0470  I     2.932    1.617    -1.681     .569  -.004000   .353000  -.0161000      .000      .000  
+801021 44533.00 I  -.011534  .001043   .361203  .001153  I -.0174444  .0000626  3.0362 0.0400  I     3.217    1.901    -1.473     .482  -.004000   .354000  -.0188000      .000      .000  
+801022 44534.00 I  -.011167  .000798   .361676  .001287  I -.0205670  .0000553  3.1937 0.0420  I     3.424    2.029    -1.304     .346  -.004000   .355000  -.0215000      .000      .000  
+801023 44535.00 I  -.010731  .000829   .362085  .000778  I -.0237945  .0000559  3.2395 0.0421  I     3.623    1.954    -1.282     .349  -.004000   .356000  -.0242000      .000      .000  
+801024 44536.00 I  -.010254  .000889   .362467  .000840  I -.0270050  .0000635  3.1625 0.0405  I     3.776    2.014    -1.448     .327  -.004000   .357000  -.0268000      .000      .000  
+801025 44537.00 I  -.009746  .001057   .362830  .000886  I -.0300888  .0000587  2.9935 0.0428  I     3.846    2.362    -1.637     .369  -.005000   .358000  -.0295000      .000      .000  
+801026 44538.00 I  -.009207  .000638   .363175  .001019  I -.0329788  .0000575  2.7850 0.1426  I     3.880    2.538    -1.654     .296  -.005000   .359000  -.0321000      .000      .000  
+801027 44539.00 I  -.008637  .002485   .363503  .000490  I -.0356645  .0002791  2.5936 0.1425  I     3.991    1.982    -1.576     .868  -.005000   .360000  -.0348000      .000      .000  
+801028 44540.00 I  -.008038  .002485   .363816  .000490  I -.0381850  .0002791  2.4590 0.1804  I     4.303    1.982    -1.656     .868  -.005000   .361000  -.0375000      .000      .000  
+801029 44541.00 I  -.007413  .002371   .364115  .000823  I -.0406058  .0002287  2.3941 0.1435  I     4.754    1.982    -1.974     .868  -.006000   .362000  -.0402000      .000      .000  
+801030 44542.00 I  -.006765  .002722   .364402  .000935  I -.0429935  .0000669  2.3899 0.1191  I     5.083    1.982    -2.304     .868  -.006000   .363000  -.0428000      .000      .000  
+801031 44543.00 I  -.006092  .002722   .364677  .000935  I -.0453991  .0000669  2.4261 0.0473  I     5.150    1.982    -2.395     .868  -.007000   .364000  -.0455000      .000      .000  
+8011 1 44544.00 I  -.005390  .002722   .364943  .000935  I -.0478520  .0000669  2.4812 0.0724  I     5.151    1.982    -2.247     .868  -.007000   .365000  -.0482000      .000      .000  
+8011 2 44545.00 I  -.004658  .002255   .365200  .001130  I -.0503616  .0001285  2.5366 0.0724  I     5.359    1.982    -2.037     .868  -.007000   .366000  -.0508000      .000      .000  
+8011 3 44546.00 I  -.003896  .002255   .365451  .001130  I -.0529205  .0001285  2.5778 0.1866  I     5.749    1.982    -1.870     .868  -.007000   .366000  -.0534000      .000      .000  
+8011 4 44547.00 I  -.003106  .001864   .365698  .000858  I -.0555091  .0003503  2.5948 0.1866  I     6.058    1.982    -1.705     .868  -.006000   .367000  -.0560000      .000      .000  
+8011 5 44548.00 I  -.002287  .001864   .365945  .000858  I -.0581001  .0003503  2.5820 0.2477  I     6.152    1.982    -1.504     .868  -.006000   .367000  -.0586000      .000      .000  
+8011 6 44549.00 I  -.001437  .001864   .366193  .000858  I -.0606628  .0003503  2.5383 0.2477  I     6.138    1.982    -1.333     .868  -.006000   .368000  -.0612000      .000      .000  
+8011 7 44550.00 I  -.000553  .001864   .366443  .000858  I -.0631675  .0003503  2.4671 0.2490  I     6.149    1.982    -1.285     .868  -.006000   .369000  -.0638000      .000      .000  
+8011 8 44551.00 I   .000371  .002807   .366696  .000524  I -.0655907  .0003539  2.3770 0.2490  I     6.215    1.982    -1.363     .868  -.005000   .369000  -.0664000      .000      .000  
+8011 9 44552.00 I   .001340  .002807   .366953  .000524  I -.0679193  .0003539  2.2802 0.2014  I     6.325    1.982    -1.489     .868  -.005000   .370000  -.0689000      .000      .000  
+801110 44553.00 I   .002361  .003802   .367214  .000272  I -.0701540  .0001923  2.1920 0.1896  I     6.457    1.982    -1.602     .868  -.004000   .370000  -.0715000      .000      .000  
+801111 44554.00 I   .003438  .002688   .367480  .000333  I -.0723119  .0001360  2.1295 0.1178  I     6.532    1.982    -1.710     .868  -.004000   .371000  -.0741000      .000      .000  
+801112 44555.00 I   .004576  .002688   .367750  .000333  I -.0744269  .0001360  2.1086 0.0962  I     6.468    1.982    -1.825     .868  -.003000   .371000  -.0767000      .000      .000  
+801113 44556.00 I   .005773  .002688   .368025  .000333  I -.0765465  .0001360  2.1400 0.1146  I     6.313    1.982    -1.899     .868  -.002000   .372000  -.0792000      .000      .000  
+801114 44557.00 I   .007027  .000517   .368305  .002281  I -.0787259  .0001846  2.2285 0.1146  I     6.222    1.982    -1.867     .868  -.002000   .372000  -.0818000      .000      .000  
+801115 44558.00 I   .008338  .000517   .368590  .002281  I -.0810214  .0001846  2.3709 0.1305  I     6.284    1.982    -1.724     .868  -.001000   .373000  -.0843000      .000      .000  
+801116 44559.00 I   .009704  .000517   .368879  .002281  I -.0834809  .0001846  2.5530 0.1482  I     6.454    1.982    -1.520     .868   .000000   .373000  -.0869000      .000      .000  
+801117 44560.00 I   .011124  .000573   .369171  .002338  I -.0861313  .0002319  2.7467 0.1482  I     6.627    1.982    -1.287     .868   .001000   .373000  -.0894000      .000      .000  
+801118 44561.00 I   .012595  .000573   .369466  .002338  I -.0889644  .0002319  2.9105 0.1531  I     6.698    1.982    -1.036     .868   .002000   .374000  -.0919000      .000      .000  
+801119 44562.00 I   .014116  .001322   .369758  .002084  I -.0919282  .0002000  3.0018 0.1543  I     6.591    1.982     -.847     .868   .004000   .374000  -.0945000      .000      .000  
+801120 44563.00 I   .015682  .001534   .370042  .001178  I -.0949346  .0002036  2.9928 0.1427  I     6.321    1.982     -.861     .868   .005000   .375000  -.0970000      .000      .000  
+801121 44564.00 I   .017292  .001534   .370316  .001178  I -.0978809  .0002036  2.8849 0.1440  I     6.026    1.982    -1.095     .868   .006000   .375000  -.0995000      .000      .000  
+801122 44565.00 I   .018944  .001534   .370574  .001178  I -.1006828  .0002036  2.7120 0.1311  I     5.843    1.982    -1.340     .868   .007000   .375000  -.1020000      .000      .000  
+801123 44566.00 I   .020631  .003481   .370816  .001025  I -.1033006  .0001652  2.5260 0.1311  I     5.802    1.982    -1.351     .868   .008000   .376000  -.1045000      .000      .000  
+801124 44567.00 I   .022349  .003481   .371039  .001025  I -.1057468  .0001652  2.3759 0.1161  I     5.887    1.982    -1.149     .868   .010000   .376000  -.1069000      .000      .000  
+801125 44568.00 I   .024091  .003403   .371242  .000366  I -.1080740  .0001633  2.2905 0.0905  I     6.122    1.982    -1.010     .868   .011000   .377000  -.1094000      .000      .000  
+801126 44569.00 I   .025851  .003403   .371423  .000366  I -.1103500  .0000740  2.2717 0.0896  I     6.463    1.982    -1.120     .868   .012000   .377000  -.1119000      .000      .000  
+801127 44570.00 I   .027614  .003403   .371580  .000366  I -.1126341  .0000740  2.3029 0.0523  I     6.723    1.982    -1.343     .868   .013000   .377000  -.1143000      .000      .000  
+801128 44571.00 I   .029368  .003403   .371712  .000366  I -.1149645  .0000740  2.3603 0.0427  I     6.755    1.982    -1.404     .868   .014000   .377000  -.1168000      .000      .000  
+801129 44572.00 I   .031095  .002329   .371818  .000982  I -.1173563  .0000428  2.4224 0.0427  I     6.668    1.982    -1.216     .868   .016000   .378000  -.1192000      .000      .000  
+801130 44573.00 I   .032776  .002329   .371896  .000982  I -.1198056  .0000428  2.4733 0.0286  I     6.682    1.982     -.931     .868   .017000   .378000  -.1217000      .000      .000  
+8012 1 44574.00 I   .034394  .002365   .371947  .001015  I -.1222956  .0000378  2.5022 0.0288  I     6.810    1.982     -.720     .868   .018000   .378000  -.1241000      .000      .000  
+8012 2 44575.00 I   .035930  .002270   .371968  .000974  I -.1248005  .0000384  2.5025 0.0269  I     6.859    1.982     -.593     .868   .019000   .378000  -.1265000      .000      .000  
+8012 3 44576.00 I   .037371  .002270   .371959  .000974  I -.1272907  .0000384  2.4731 0.0272  I     6.738    1.982     -.464     .868   .021000   .378000  -.1289000      .000      .000  
+8012 4 44577.00 I   .038728  .002270   .371917  .000974  I -.1297379  .0000384  2.4174 0.0472  I     6.567    1.982     -.297     .868   .022000   .377000  -.1314000      .000      .000  
+8012 5 44578.00 I   .040017  .002221   .371841  .000850  I -.1321190  .0000863  2.3421 0.1378  I     6.467    1.982     -.144     .868   .024000   .377000  -.1338000      .000      .000  
+8012 6 44579.00 I   .041254  .002669   .371728  .001991  I -.1344185  .0002729  2.2561 0.1431  I     6.424    1.982     -.084     .868   .025000   .377000  -.1362000      .000      .000  
+8012 7 44580.00 I   .042454  .002669   .371577  .001991  I -.1366321  .0002729  2.1728 0.1968  I     6.414    1.982     -.147     .868   .026000   .377000  -.1386000      .000      .000  
+8012 8 44581.00 I   .043634  .002673   .371385  .002008  I -.1387701  .0002835  2.1076 0.1968  I     6.513    1.982     -.292     .868   .028000   .376000  -.1410000      .000      .000  
+8012 9 44582.00 I   .044806  .002673   .371153  .002008  I -.1408587  .0002835  2.0765 0.1881  I     6.753    1.982     -.430     .868   .029000   .376000  -.1434000      .000      .000  
+801210 44583.00 I   .045978  .004254   .370882  .001797  I -.1429387  .0002474  2.0923 0.1573  I     7.011    1.982     -.487     .868   .031000   .375000  -.1458000      .000      .000  
+801211 44584.00 I   .047160  .004480   .370575  .000960  I -.1450613  .0001363  2.1620 0.1412  I     7.125    1.982     -.447     .868   .032000   .375000  -.1482000      .000      .000  
+801212 44585.00 I   .048360  .004480   .370233  .000960  I -.1472792  .0001363  2.2813 0.0964  I     7.097    1.982     -.348     .868   .033000   .374000  -.1506000      .000      .000  
+801213 44586.00 I   .049583  .004480   .369860  .000960  I -.1496355  .0001363  2.4356 0.0944  I     7.073    1.982     -.226     .868   .034000   .374000  -.1530000      .000      .000  
+801214 44587.00 I   .050829  .004472   .369458  .001345  I -.1521542  .0001305  2.6014 0.1027  I     7.173    1.982     -.082     .868   .036000   .373000  -.1553000      .000      .000  
+801215 44588.00 I   .052094  .004472   .369033  .001345  I -.1548320  .0001536  2.7484 0.0906  I     7.355    1.982      .104     .868   .037000   .373000  -.1577000      .000      .000  
+801216 44589.00 I   .053373  .003725   .368587  .001228  I -.1576339  .0001256  2.8442 0.0801  I     7.447    1.982      .314     .868   .038000   .372000  -.1601000      .000      .000  
+801217 44590.00 I   .054663  .001492   .368127  .001099  I -.1604947  .0000456  2.8631 0.0668  I     7.287    1.982      .459     .868   .039000   .371000  -.1625000      .000      .000  
+801218 44591.00 I   .055958  .001492   .367656  .001099  I -.1633315  .0000456  2.7964 0.0322  I     6.876    1.982      .426     .868   .040000   .371000  -.1649000      .000      .000  
+801219 44592.00 I   .057255  .001492   .367181  .001099  I -.1660643  .0000456  2.6600 0.0339  I     6.414    1.982      .208     .868   .042000   .370000  -.1672000      .000      .000  
+801220 44593.00 I   .058546  .001492   .366708  .001261  I -.1686409  .0000502  2.4916 0.0291  I     6.137    1.982     -.028     .868   .043000   .370000  -.1696000      .000      .000  
+801221 44594.00 I   .059819  .001492   .366243  .001261  I -.1710521  .0000363  2.3370 0.0302  I     6.146    1.982     -.061     .868   .044000   .369000  -.1720000      .000      .000  
+801222 44595.00 I   .061068  .000472   .365777  .001847  I -.1733318  .0000336  2.2332 0.0247  I     6.389    1.982      .151     .868   .045000   .368000  -.1744000      .000      .000  
+801223 44596.00 I   .062292  .000472   .365303  .001847  I -.1755406  .0000336  2.1956 0.0526  I     6.780    1.982      .399     .868   .046000   .368000  -.1768000      .000      .000  
+801224 44597.00 I   .063487  .000121   .364811  .004080  I -.1777423  .0000997  2.2160 0.0526  I     7.231    1.982      .452     .868   .048000   .367000  -.1791000      .000      .000  
+801225 44598.00 I   .064652  .000121   .364297  .004080  I -.1799847  .0000997  2.2726 0.0505  I     7.625    1.982      .317     .868   .049000   .367000  -.1815000      .000      .000  
+801226 44599.00 I   .065782  .000172   .363758  .005104  I -.1822914  .0000163  2.3408 0.0505  I     7.853    1.982      .204     .868   .050000   .366000  -.1839000      .000      .000  
+801227 44600.00 I   .066876  .000172   .363194  .005104  I -.1846637  .0000163  2.4013 0.0261  I     7.910    1.982      .267     .868   .051000   .365000  -.1863000      .000      .000  
+801228 44601.00 I   .067929  .000629   .362608  .000838  I -.1870873  .0000496  2.4419 0.0261  I     7.867    1.982      .445     .868   .052000   .364000  -.1886000      .000      .000  
+801229 44602.00 I   .068940  .000629   .362000  .000838  I -.1895385  .0000496  2.4556 0.0351  I     7.749    1.982      .587     .868   .053000   .364000  -.1910000      .000      .000  
+801230 44603.00 I   .069905  .000629   .361371  .000838  I -.1919885  .0000496  2.4395 0.0351  I     7.536    1.982      .639     .868   .054000   .363000  -.1933000      .000      .000  
+801231 44604.00 I   .070820  .000629   .360722  .000838  I -.1944082  .0000496  2.3955 0.0351  I     7.275    1.982      .677     .868   .055000   .362000  -.1957000      .000      .000  
+81 1 1 44605.00 I   .071683  .000629   .360054  .000838  I -.1967724  .0000496  2.3300 0.0306  I     7.091    1.982      .780     .868   .056000   .361000  -.1981000      .000      .000  
+81 1 2 44606.00 I   .072490  .003327   .359365  .001604  I -.1990643  .0000357  2.2527 0.0252  I     7.042    1.982      .932     .868   .057000   .360000  -.2004000      .000      .000  
+81 1 3 44607.00 I   .073235  .004662   .358658  .002109  I -.2012778  .0000091  2.1753 0.0184  I     7.058    1.982     1.024     .868   .057000   .360000  -.2028000      .000      .000  
+81 1 4 44608.00 I   .073915  .004662   .357930  .002109  I -.2034193  .0000091  2.1112 0.0064  I     7.082    1.982      .949     .868   .058000   .359000  -.2051000      .000      .000  
+81 1 5 44609.00 I   .074525  .004662   .357183  .002109  I -.2055098  .0000091  2.0759 0.0064  I     7.173    1.982      .707     .868   .059000   .358000  -.2075000      .000      .000  
+81 1 6 44610.00 I   .075064  .004662   .356414  .002109  I -.2075860  .0000091  2.0852 0.0064  I     7.410    1.982      .436     .868   .060000   .357000  -.2099000      .000      .000  
+81 1 7 44611.00 I   .075536  .004662   .355623  .002109  I -.2096986  .0000091  2.1496 0.2433  I     7.738    1.982      .309     .868   .060000   .356000  -.2122000      .000      .000  
+81 1 8 44612.00 I   .075945  .001337   .354805  .004055  I -.2119034  .0004866  2.2686 0.2433  I     7.998    1.982      .377     .868   .061000   .355000  -.2146000      .000      .000  
+81 1 9 44613.00 I   .076296  .001337   .353958  .004055  I -.2142488  .0004866  2.4267 0.3441  I     8.095    1.982      .534     .868   .061000   .354000  -.2169000      .000      .000  
+81 110 44614.00 I   .076594  .001337   .353079  .004055  I -.2167605  .0004866  2.5959 0.3441  I     8.075    1.982      .642     .868   .062000   .353000  -.2193000      .000      .000  
+81 111 44615.00 I   .076842  .001337   .352166  .004055  I -.2194331  .0004866  2.7425 0.3119  I     8.039    1.982      .663     .868   .062000   .352000  -.2216000      .000      .000  
+81 112 44616.00 I   .077049  .001157   .351219  .004521  I -.2222276  .0003903  2.8352 0.3119  I     8.014    1.982      .650     .868   .063000   .351000  -.2239000      .000      .000  
+81 113 44617.00 I   .077220  .001157   .350241  .004521  I -.2250792  .0003903  2.8548 0.2347  I     7.922    1.982      .651     .868   .063000   .350000  -.2263000      .000      .000  
+81 114 44618.00 I   .077364  .000943   .349233  .004943  I -.2279115  .0002606  2.7972 0.2347  I     7.666    1.982      .642     .868   .064000   .349000  -.2286000      .000      .000  
+81 115 44619.00 I   .077487  .000943   .348200  .004943  I -.2306522  .0002606  2.6753 0.1843  I     7.246    1.982      .563     .868   .064000   .348000  -.2309000      .000      .000  
+81 116 44620.00 I   .077597  .000943   .347144  .004943  I -.2332501  .0002606  2.5174 0.1843  I     6.809    1.982      .392     .868   .064000   .347000  -.2332000      .000      .000  
+81 117 44621.00 I   .077698  .000943   .346074  .004943  I -.2356873  .0002606  2.3605 0.1507  I     6.555    1.982      .207     .868   .065000   .346000  -.2355000      .000      .000  
+81 118 44622.00 I   .077796  .001051   .345000  .000397  I -.2379834  .0001514  2.2404 0.1507  I     6.596    1.982      .130     .868   .065000   .346000  -.2379000      .000      .000  
+81 119 44623.00 I   .077897  .001051   .343929  .000397  I -.2401875  .0001514  2.1784 0.0818  I     6.874    1.982      .209     .868   .066000   .345000  -.2402000      .000      .000  
+81 120 44624.00 I   .078006  .000865   .342872  .001453  I -.2423598  .0000620  2.1752 0.0949  I     7.240    1.982      .336     .868   .066000   .344000  -.2425000      .000      .000  
+81 121 44625.00 I   .078128  .000973   .341837  .001453  I -.2445519  .0001145  2.2140 0.0651  I     7.575    1.982      .340     .868   .066000   .343000  -.2448000      .000      .000  
+81 122 44626.00 I   .078270  .000973   .340832  .001453  I -.2467935  .0001145  2.2699 0.0810  I     7.843    1.982      .174     .868   .067000   .342000  -.2471000      .000      .000  
+81 123 44627.00 I   .078438  .000973   .339867  .001453  I -.2490897  .0001145  2.3197 0.0798  I     8.038    1.982     -.033     .868   .067000   .342000  -.2493000      .000      .000  
+81 124 44628.00 I   .078639  .000961   .338947  .001529  I -.2514260  .0001111  2.3487 0.0784  I     8.108    1.982     -.131     .868   .068000   .341000  -.2516000      .000      .000  
+81 125 44629.00 I   .078874  .000996   .338070  .001649  I -.2537780  .0001070  2.3502 0.0791  I     7.982    1.982     -.106     .868   .068000   .340000  -.2539000      .000      .000  
+81 126 44630.00 I   .079143  .000996   .337230  .001649  I -.2561161  .0001127  2.3207 0.0722  I     7.664    1.982     -.062     .868   .068000   .339000  -.2562000      .000      .000  
+81 127 44631.00 I   .079447  .003128   .336422  .001942  I -.2584095  .0000969  2.2614 0.0743  I     7.283    1.982     -.065     .868   .069000   .339000  -.2584000      .000      .000  
+81 128 44632.00 I   .079787  .003128   .335641  .001942  I -.2606311  .0000969  2.1786 0.0685  I     7.014    1.982     -.078     .868   .069000   .338000  -.2607000      .000      .000  
+81 129 44633.00 I   .080160  .003128   .334884  .001942  I -.2627623  .0000969  2.0827 0.0685  I     6.942    1.982     -.036     .868   .070000   .338000  -.2629000      .000      .000  
+81 130 44634.00 I   .080567  .003128   .334149  .001942  I -.2647967  .0000969  1.9873 0.0707  I     7.028    1.982      .070     .868   .070000   .337000  -.2652000      .000      .000  
+81 131 44635.00 I   .081002  .003175   .333433  .001215  I -.2667414  .0001030  1.9055 0.0523  I     7.181    1.982      .164     .868   .070000   .336000  -.2674000      .000      .000  
+81 2 1 44636.00 I   .081459  .003175   .332735  .001215  I -.2686169  .0000394  1.8512 0.1544  I     7.331    1.982      .130     .868   .071000   .335000  -.2697000      .000      .000  
+81 2 2 44637.00 I   .081926  .004944   .332049  .000859  I -.2704577  .0002912  1.8387 0.1469  I     7.448    1.982     -.091     .868   .071000   .335000  -.2719000      .000      .000  
+81 2 3 44638.00 I   .082394  .004944   .331372  .000859  I -.2723128  .0002912  1.8818 0.2059  I     7.552    1.982     -.421     .868   .072000   .334000  -.2742000      .000      .000  
+81 2 4 44639.00 I   .082853  .004944   .330701  .000859  I -.2742421  .0002912  1.9872 0.2059  I     7.718    1.982     -.665     .868   .072000   .333000  -.2764000      .000      .000  
+81 2 5 44640.00 I   .083296  .004944   .330031  .000859  I -.2763049  .0002912  2.1457 0.2323  I     8.005    1.982     -.668     .868   .073000   .332000  -.2787000      .000      .000  
+81 2 6 44641.00 I   .083721  .006842   .329357  .000263  I -.2785419  .0003620  2.3293 0.2323  I     8.358    1.982     -.470     .868   .073000   .331000  -.2810000      .000      .000  
+81 2 7 44642.00 I   .084131  .006842   .328675  .000263  I -.2809579  .0003620  2.4962 0.3602  I     8.617    1.982     -.271     .868   .074000   .330000  -.2833000      .000      .000  
+81 2 8 44643.00 I   .084534  .009490   .327978  .003544  I -.2835154  .0006228  2.6063 0.3602  I     8.647    1.982     -.236     .868   .074000   .329000  -.2856000      .000      .000  
+81 2 9 44644.00 I   .084935  .009490   .327264  .003544  I -.2861427  .0006228  2.6331 0.4404  I     8.459    1.982     -.366     .868   .075000   .328000  -.2879000      .000      .000  
+81 210 44645.00 I   .085339  .009490   .326526  .003544  I -.2887526  .0006228  2.5730 0.3814  I     8.165    1.982     -.551     .868   .076000   .327000  -.2902000      .000      .000  
+81 211 44646.00 I   .085753  .007697   .325761  .003145  I -.2912661  .0004404  2.4452 0.3814  I     7.869    1.982     -.700     .868   .076000   .326000  -.2925000      .000      .000  
+81 212 44647.00 I   .086171  .007697   .324966  .003145  I -.2936321  .0004404  2.2847 0.3114  I     7.620    1.982     -.801     .868   .077000   .325000  -.2949000      .000      .000  
+81 213 44648.00 I   .086582  .007697   .324142  .003145  I -.2958376  .0004404  2.1304 0.2202  I     7.469    1.982     -.885     .868   .077000   .324000  -.2972000      .000      .000  
+81 214 44649.00 I   .086975  .005331   .323288  .002687  I -.2979063  .0000014  2.0161 0.2202  I     7.494    1.982     -.968     .868   .078000   .323000  -.2995000      .000      .000  
+81 215 44650.00 I   .087342  .005331   .322406  .002687  I -.2998904  .0000014  1.9635 0.0010  I     7.751    1.982    -1.034     .868   .079000   .322000  -.3019000      .000      .000  
+81 216 44651.00 I   .087683  .005331   .321500  .002687  I -.3018556  .0000014  1.9777 0.1176  I     8.178    1.982    -1.070     .868   .079000   .321000  -.3043000      .000      .000  
+81 217 44652.00 I   .087995  .002863   .320574  .000780  I -.3038641  .0002351  2.0469 0.1176  I     8.604    1.982    -1.112     .868   .080000   .320000  -.3066000      .000      .000  
+81 218 44653.00 I   .088275  .002863   .319631  .000780  I -.3059601  .0002351  2.1484 0.1662  I     8.878    1.982    -1.220     .868   .080000   .319000  -.3090000      .000      .000  
+81 219 44654.00 I   .088523  .002863   .318674  .000780  I -.3081632  .0002351  2.2569 0.1662  I     9.003    1.982    -1.401     .868   .081000   .318000  -.3114000      .000      .000  
+81 220 44655.00 I   .088735  .002863   .317707  .000780  I -.3104694  .0002351  2.3519 0.2364  I     9.078    1.982    -1.577     .868   .082000   .317000  -.3138000      .000      .000  
+81 221 44656.00 I   .088911  .002312   .316734  .000681  I -.3128585  .0004103  2.4212 0.2364  I     9.115    1.982    -1.662     .868   .082000   .316000  -.3162000      .000      .000  
+81 222 44657.00 I   .089055  .002312   .315759  .000681  I -.3153014  .0004103  2.4592 0.3354  I     9.008    1.982    -1.663     .868   .083000   .315000  -.3187000      .000      .000  
+81 223 44658.00 I   .089169  .001579   .314787  .000566  I -.3177663  .0005306  2.4655 0.3067  I     8.725    1.982    -1.653     .868   .083000   .314000  -.3211000      .000      .000  
+81 224 44659.00 I   .089258  .003146   .313822  .000451  I -.3202234  .0004560  2.4448 0.3498  I     8.427    1.982    -1.678     .868   .084000   .313000  -.3235000      .000      .000  
+81 225 44660.00 I   .089324  .003146   .312869  .000451  I -.3226500  .0004560  2.4063 0.4189  I     8.301    1.982    -1.722     .868   .084000   .312000  -.3260000      .000      .000  
+81 226 44661.00 I   .089374  .004341   .311931  .001623  I -.3250343  .0007029  2.3628 0.4496  I     8.363    1.982    -1.757     .868   .085000   .311000  -.3285000      .000      .000  
+81 227 44662.00 I   .089414  .005198   .311013  .001947  I -.3273788  .0007749  2.3290 0.5231  I     8.520    1.982    -1.768     .868   .085000   .311000  -.3309000      .000      .000  
+81 228 44663.00 I   .089444  .005198   .310118  .001947  I -.3297000  .0007749  2.3184 0.5132  I     8.753    1.982    -1.751     .868   .086000   .310000  -.3334000      .000      .000  
+81 3 1 44664.00 I   .089465  .004331   .309250  .001603  I -.3320271  .0006730  2.3423 0.5506  I     9.072    1.982    -1.734     .868   .086000   .309000  -.3359000      .000      .000  
+81 3 2 44665.00 I   .089485  .004414   .308410  .001952  I -.3343997  .0007824  2.4114 0.5160  I     9.347    1.982    -1.809     .868   .086000   .308000  -.3384000      .000      .000  
+81 3 3 44666.00 I   .089511  .004414   .307600  .001952  I -.3368684  .0007824  2.5361 0.4387  I     9.410    1.982    -2.049     .868   .087000   .307000  -.3410000      .000      .000  
+81 3 4 44667.00 I   .089556  .001491   .306819  .000351  I -.3394912  .0003972  2.7186 0.4156  I     9.351    1.982    -2.368     .868   .087000   .307000  -.3435000      .000      .000  
+81 3 5 44668.00 I   .089628  .001760   .306068  .003608  I -.3423190  .0002809  2.9412 0.2432  I     9.494    1.982    -2.537     .868   .088000   .306000  -.3461000      .000      .000  
+81 3 6 44669.00 I   .089735  .001760   .305347  .003608  I -.3453741  .0002809  3.1652 0.1406  I     9.979    1.982    -2.422     .868   .088000   .305000  -.3486000      .000      .000  
+81 3 7 44670.00 I   .089884  .001992   .304656  .005090  I -.3486333  .0000108  3.3407 0.1889  I    10.513    1.982    -2.158     .868   .088000   .304000  -.3512000      .000      .000  
+81 3 8 44671.00 I   .090081  .003957   .303995  .003771  I -.3520246  .0002526  3.4234 0.1264  I    10.673    1.982    -2.024     .868   .088000   .303000  -.3537000      .000      .000  
+81 3 9 44672.00 I   .090330  .003957   .303357  .003771  I -.3554424  .0002526  3.3931 0.2131  I    10.361    1.982    -2.153     .868   .089000   .303000  -.3563000      .000      .000  
+81 310 44673.00 I   .090635  .003231   .302736  .003399  I -.3587773  .0003434  3.2622 0.2453  I     9.865    1.982    -2.435     .868   .089000   .302000  -.3588000      .000      .000  
+81 311 44674.00 I   .090999  .003698   .302126  .002091  I -.3619463  .0004205  3.0696 0.2715  I     9.521    1.982    -2.679     .868   .089000   .301000  -.3614000      .000      .000  
+81 312 44675.00 I   .091420  .003698   .301521  .002091  I -.3649125  .0004205  2.8649 0.2973  I     9.448    1.982    -2.802     .868   .089000   .300000  -.3640000      .000      .000  
+81 313 44676.00 I   .091892  .003698   .300917  .002091  I -.3676865  .0004205  2.6914 0.3380  I     9.568    1.982    -2.843     .868   .089000   .299000  -.3666000      .000      .000  
+81 314 44677.00 I   .092409  .000511   .300309  .001763  I -.3703147  .0005293  2.5763 0.3380  I     9.786    1.982    -2.862     .868   .089000   .299000  -.3691000      .000      .000  
+81 315 44678.00 I   .092963  .000511   .299696  .001763  I -.3728610  .0005293  2.5271 0.3759  I    10.086    1.982    -2.887     .868   .089000   .298000  -.3717000      .000      .000  
+81 316 44679.00 I   .093548  .000549   .299077  .000556  I -.3753878  .0005339  2.5346 0.3759  I    10.482    1.982    -2.933     .868   .089000   .297000  -.3743000      .000      .000  
+81 317 44680.00 I   .094158  .000549   .298450  .000556  I -.3779422  .0005339  2.5782 0.3775  I    10.910    1.982    -3.018     .868   .089000   .296000  -.3769000      .000      .000  
+81 318 44681.00 I   .094786  .000549   .297814  .000556  I -.3805484  .0005339  2.6344 0.3582  I    11.232    1.982    -3.130     .868   .089000   .296000  -.3795000      .000      .000  
+81 319 44682.00 I   .095427  .000455   .297169  .002017  I -.3832082  .0004776  2.6821 0.3392  I    11.369    1.982    -3.209     .868   .089000   .295000  -.3821000      .000      .000  
+81 320 44683.00 I   .096077  .000226   .296513  .002470  I -.3859045  .0004184  2.7056 0.3175  I    11.377    1.982    -3.191     .868   .089000   .295000  -.3847000      .000      .000  
+81 321 44684.00 I   .096730  .000226   .295846  .002470  I -.3886086  .0004184  2.6966 0.2689  I    11.335    1.982    -3.088     .868   .089000   .294000  -.3873000      .000      .000  
+81 322 44685.00 I   .097382  .000129   .295168  .003403  I -.3912862  .0003380  2.6530 0.2446  I    11.230    1.982    -2.995     .868   .089000   .293000  -.3899000      .000      .000  
+81 323 44686.00 I   .098029  .000731   .294476  .002657  I -.3939040  .0002536  2.5777 0.2113  I    11.045    1.982    -2.988     .868   .089000   .292000  -.3926000      .000      .000  
+81 324 44687.00 I   .098666  .000731   .293764  .002657  I -.3964337  .0002536  2.4788 0.1337  I    10.884    1.982    -3.060     .868   .089000   .292000  -.3952000      .000      .000  
+81 325 44688.00 I   .099288  .000762   .293029  .001538  I -.3988580  .0000847  2.3693 0.1337  I    10.855    1.982    -3.161     .868   .089000   .291000  -.3979000      .000      .000  
+81 326 44689.00 I   .099892  .000762   .292266  .001538  I -.4011740  .0000847  2.2651 0.0599  I    10.907    1.982    -3.285     .868   .089000   .290000  -.4005000      .000      .000  
+81 327 44690.00 I   .100472  .000762   .291472  .001538  I -.4033956  .0000847  2.1832 0.0599  I    10.952    1.982    -3.444     .868   .089000   .289000  -.4031000      .000      .000  
+81 328 44691.00 I   .101022  .000762   .290643  .001538  I -.4055526  .0000847  2.1379 0.0467  I    11.097    1.982    -3.573     .868   .089000   .288000  -.4058000      .000      .000  
+81 329 44692.00 I   .101536  .001438   .289778  .001910  I -.4076876  .0000394  2.1411 0.0467  I    11.502    1.982    -3.573     .868   .088000   .288000  -.4084000      .000      .000  
+81 330 44693.00 I   .102008  .001438   .288877  .001910  I -.4098543  .0000394  2.2029 0.0341  I    12.021    1.982    -3.482     .868   .088000   .287000  -.4111000      .000      .000  
+81 331 44694.00 I   .102433  .002007   .287939  .002259  I -.4121152  .0000556  2.3303 0.1498  I    12.267    1.982    -3.493     .868   .088000   .286000  -.4137000      .000      .000  
+81 4 1 44695.00 I   .102804  .002506   .286963  .002112  I -.4145355  .0002970  2.5195 0.1511  I    12.143    1.982    -3.708     .868   .088000   .285000  -.4164000      .000      .000  
+81 4 2 44696.00 I   .103118  .002506   .285951  .002112  I -.4171670  .0002970  2.7471 0.2100  I    12.038    1.982    -3.955     .868   .088000   .284000  -.4191000      .000      .000  
+81 4 3 44697.00 I   .103374  .002506   .284904  .002112  I -.4200277  .0002970  2.9688 0.2232  I    12.305    1.982    -3.967     .868   .087000   .283000  -.4217000      .000      .000  
+81 4 4 44698.00 I   .103570  .002105   .283826  .001456  I -.4230844  .0003333  3.1299 0.2232  I    12.740    1.982    -3.735     .868   .087000   .282000  -.4244000      .000      .000  
+81 4 5 44699.00 I   .103706  .002105   .282720  .001456  I -.4262527  .0003333  3.1867 0.2357  I    12.817    1.982    -3.539     .868   .087000   .281000  -.4271000      .000      .000  
+81 4 6 44700.00 I   .103787  .002105   .281591  .001456  I -.4294194  .0003333  3.1282 0.2039  I    12.349    1.982    -3.610     .868   .087000   .280000  -.4298000      .000      .000  
+81 4 7 44701.00 I   .103815  .000740   .280444  .001019  I -.4324794  .0002351  2.9807 0.2039  I    11.686    1.982    -3.883     .868   .087000   .279000  -.4326000      .000      .000  
+81 4 8 44702.00 I   .103796  .000740   .279284  .001019  I -.4353684  .0002351  2.7962 0.2191  I    11.319    1.982    -4.131     .868   .087000   .279000  -.4353000      .000      .000  
+81 4 9 44703.00 I   .103731  .001025   .278118  .001173  I -.4380784  .0003698  2.6315 0.2429  I    11.417    1.982    -4.246     .868   .087000   .278000  -.4381000      .000      .000  
+81 410 44704.00 I   .103622  .001187   .276950  .001361  I -.4406514  .0004251  2.5269 0.2817  I    11.779    1.982    -4.286     .868   .087000   .277000  -.4408000      .000      .000  
+81 411 44705.00 I   .103472  .001187   .275789  .001361  I -.4431571  .0004251  2.4972 0.3006  I    12.088    1.982    -4.313     .868   .087000   .276000  -.4435000      .000      .000  
+81 412 44706.00 I   .103281  .001187   .274641  .001361  I -.4456681  .0004251  2.5346 0.3033  I    12.198    1.982    -4.317     .868   .087000   .276000  -.4462000      .000      .000  
+81 413 44707.00 I   .103048  .001773   .273513  .001374  I -.4482414  .0004328  2.6173 0.3033  I    12.231    1.982    -4.291     .868   .087000   .275000  -.4490000      .000      .000  
+81 414 44708.00 I   .102772  .001773   .272412  .001374  I -.4509090  .0004328  2.7190 0.3431  I    12.391    1.982    -4.274     .868   .087000   .275000  -.4517000      .000      .000  
+81 415 44709.00 I   .102451  .003506   .271342  .005022  I -.4536782  .0005325  2.8171 0.3431  I    12.692    1.982    -4.275     .868   .087000   .274000  -.4544000      .000      .000  
+81 416 44710.00 I   .102084  .003506   .270310  .005022  I -.4565359  .0005325  2.8934 0.3765  I    12.941    1.982    -4.214     .868   .087000   .273000  -.4571000      .000      .000  
+81 417 44711.00 I   .101671  .003506   .269319  .005022  I -.4594538  .0005325  2.9361 0.3765  I    12.972    1.982    -4.018     .868   .087000   .273000  -.4598000      .000      .000  
+81 418 44712.00 I   .101215  .003506   .268373  .005022  I -.4623949  .0005325  2.9393 0.3930  I    12.813    1.982    -3.749     .868   .087000   .272000  -.4626000      .000      .000  
+81 419 44713.00 I   .100723  .003367   .267472  .004999  I -.4653187  .0005781  2.9016 0.3930  I    12.589    1.982    -3.577     .868   .087000   .272000  -.4653000      .000      .000  
+81 420 44714.00 I   .100204  .003367   .266611  .004999  I -.4681860  .0005781  2.8276 0.3869  I    12.391    1.982    -3.604     .868   .087000   .271000  -.4680000      .000      .000  
+81 421 44715.00 I   .099670  .002566   .265784  .001453  I -.4709654  .0005144  2.7280 0.3869  I    12.277    1.982    -3.762     .868   .087000   .270000  -.4707000      .000      .000  
+81 422 44716.00 I   .099132  .002566   .264986  .001453  I -.4736384  .0005144  2.6175 0.3637  I    12.253    1.982    -3.930     .868   .087000   .270000  -.4734000      .000      .000  
+81 423 44717.00 I   .098598  .002566   .264212  .001453  I -.4762027  .0005144  2.5140 0.3637  I    12.221    1.982    -4.089     .868   .087000   .269000  -.4761000      .000      .000  
+81 424 44718.00 I   .098078  .002566   .263458  .001453  I -.4786745  .0005144  2.4349 0.3930  I    12.100    1.982    -4.295     .868   .087000   .269000  -.4788000      .000      .000  
+81 425 44719.00 I   .097577  .003294   .262721  .001723  I -.4810851  .0005942  2.3937 0.3459  I    12.031    1.982    -4.510     .868   .087000   .268000  -.4815000      .000      .000  
+81 426 44720.00 I   .097098  .002585   .262000  .001247  I -.4834781  .0004626  2.4010 0.3271  I    12.278    1.982    -4.572     .868   .087000   .267000  -.4841000      .000      .000  
+81 427 44721.00 I   .096643  .001585   .261292  .000374  I -.4859053  .0002739  2.4627 0.3155  I    12.818    1.982    -4.416     .868   .087000   .266000  -.4868000      .000      .000  
+81 428 44722.00 I   .096213  .002760   .260597  .000294  I -.4884219  .0004291  2.5795 0.2545  I    13.242    1.982    -4.213     .868   .087000   .266000  -.4894000      .000      .000  
+81 429 44723.00 I   .095810  .002760   .259912  .000294  I -.4910793  .0004291  2.7415 0.3034  I    13.240    1.982    -4.179     .868   .087000   .265000  -.4921000      .000      .000  
+81 430 44724.00 I   .095437  .002760   .259235  .000294  I -.4939106  .0004291  2.9208 0.2888  I    12.987    1.982    -4.292     .868   .087000   .264000  -.4947000      .000      .000  
+81 5 1 44725.00 I   .095099  .002331   .258566  .000634  I -.4969117  .0003865  3.0725 0.3044  I    12.840    1.982    -4.323     .868   .087000   .263000  -.4973000      .000      .000  
+81 5 2 44726.00 I   .094796  .002625   .257901  .000731  I -.5000299  .0004319  3.1470 0.2898  I    12.801    1.982    -4.175     .868   .087000   .263000  -.4999000      .000      .000  
+81 5 3 44727.00 I   .094526  .002625   .257240  .000731  I -.5031687  .0004319  3.1103 0.2500  I    12.536    1.982    -4.030     .868   .086000   .262000  -.5025000      .000      .000  
+81 5 4 44728.00 I   .094287  .001886   .256579  .000760  I -.5062135  .0002520  2.9626 0.2500  I    11.898    1.982    -4.094     .868   .086000   .262000  -.5051000      .000      .000  
+81 5 5 44729.00 I   .094077  .001886   .255917  .000760  I -.5090697  .0002520  2.7424 0.1738  I    11.189    1.982    -4.313     .868   .086000   .261000  -.5077000      .000      .000  
+81 5 6 44730.00 I   .093897  .001559   .255250  .001048  I -.5116939  .0002393  2.5091 0.1655  I    10.860    1.982    -4.477     .868   .086000   .260000  -.5102000      .000      .000  
+81 5 7 44731.00 I   .093746  .001765   .254576  .001064  I -.5141026  .0002146  2.3198 0.1607  I    11.088    1.982    -4.511     .868   .086000   .259000  -.5127000      .000      .000  
+81 5 8 44732.00 I   .093621  .001765   .253891  .001064  I -.5163592  .0002146  2.2075 0.1517  I    11.638    1.982    -4.530     .868   .086000   .259000  -.5153000      .000      .000  
+81 5 9 44733.00 I   .093517  .001765   .253193  .001064  I -.5185444  .0002146  2.1754 0.1337  I    12.052    1.982    -4.604     .868   .086000   .258000  -.5178000      .000      .000  
+81 510 44734.00 I   .093428  .000332   .252480  .001047  I -.5207305  .0001594  2.2047 0.1337  I    12.015    1.982    -4.650     .868   .086000   .257000  -.5203000      .000      .000  
+81 511 44735.00 I   .093349  .000332   .251752  .001047  I -.5229648  .0001594  2.2670 0.0886  I    11.639    1.982    -4.579     .868   .086000   .256000  -.5227000      .000      .000  
+81 512 44736.00 I   .093274  .000202   .251007  .000219  I -.5252670  .0000774  2.3366 0.2351  I    11.356    1.982    -4.441     .868   .086000   .255000  -.5251000      .000      .000  
+81 513 44737.00 I   .093197  .000563   .250245  .000270  I -.5276341  .0004424  2.3943 0.2037  I    11.432    1.982    -4.330     .868   .086000   .255000  -.5276000      .000      .000  
+81 514 44738.00 I   .093113  .000563   .249466  .000270  I -.5300478  .0003999  2.4284 0.2982  I    11.674    1.982    -4.222     .868   .086000   .254000  -.5300000      .000      .000  
+81 515 44739.00 I   .093014  .000563   .248669  .000270  I -.5324811  .0003999  2.4329 0.3179  I    11.700    1.982    -4.027     .868   .086000   .253000  -.5324000      .000      .000  
+81 516 44740.00 I   .092896  .000652   .247853  .001354  I -.5349032  .0004944  2.4061 0.3179  I    11.398    1.982    -3.762     .868   .086000   .252000  -.5348000      .000      .000  
+81 517 44741.00 I   .092753  .000652   .247018  .001354  I -.5372836  .0004944  2.3503 0.3496  I    10.979    1.982    -3.586     .868   .086000   .251000  -.5371000      .000      .000  
+81 518 44742.00 I   .092580  .000652   .246162  .001354  I -.5395967  .0004944  2.2732 0.3149  I    10.670    1.982    -3.616     .868   .086000   .251000  -.5395000      .000      .000  
+81 519 44743.00 I   .092374  .001741   .245286  .001547  I -.5418269  .0003903  2.1868 0.3277  I    10.523    1.982    -3.792     .868   .086000   .250000  -.5418000      .000      .000  
+81 520 44744.00 I   .092128  .001741   .244389  .001547  I -.5439719  .0004304  2.1054 0.2905  I    10.471    1.982    -3.961     .868   .086000   .249000  -.5442000      .000      .000  
+81 521 44745.00 I   .091841  .001741   .243473  .001547  I -.5460448  .0004304  2.0454 0.2810  I    10.403    1.982    -4.067     .868   .086000   .248000  -.5465000      .000      .000  
+81 522 44746.00 I   .091507  .002409   .242539  .001103  I -.5480747  .0003615  2.0214 0.2510  I    10.221    1.982    -4.171     .868   .086000   .247000  -.5488000      .000      .000  
+81 523 44747.00 I   .091128  .002447   .241590  .001791  I -.5501027  .0002582  2.0428 0.2221  I     9.963    1.982    -4.305     .868   .086000   .246000  -.5511000      .000      .000  
+81 524 44748.00 I   .090703  .002447   .240630  .001791  I -.5521769  .0002582  2.1141 0.1316  I     9.834    1.982    -4.371     .868   .086000   .245000  -.5534000      .000      .000  
+81 525 44749.00 I   .090233  .002485   .239660  .002280  I -.5543473  .0000510  2.2345 0.1316  I     9.977    1.982    -4.259     .868   .086000   .244000  -.5557000      .000      .000  
+81 526 44750.00 I   .089719  .002485   .238686  .002280  I -.5566596  .0000510  2.3961 0.0361  I    10.240    1.982    -4.015     .868   .086000   .243000  -.5580000      .000      .000  
+81 527 44751.00 I   .089165  .002485   .237709  .002280  I -.5591475  .0000510  2.5816 0.0361  I    10.320    1.982    -3.798     .868   .086000   .242000  -.5602000      .000      .000  
+81 528 44752.00 I   .088574  .002485   .236737  .002280  I -.5618204  .0000510  2.7599 0.1674  I    10.094    1.982    -3.684     .868   .085000   .241000  -.5625000      .000      .000  
+81 529 44753.00 I   .087953  .003310   .235775  .002690  I -.5646512  .0003308  2.8900 0.1119  I     9.659    1.982    -3.604     .868   .085000   .240000  -.5647000      .000      .000  
+81 530 44754.00 I   .087307  .001168   .234829  .007887  I -.5675712  .0002180  2.9325 0.1981  I     9.099    1.982    -3.510     .868   .085000   .239000  -.5670000      .000      .000  
+81 531 44755.00 I   .086642  .001168   .233906  .007887  I -.5704801  .0002180  2.8668 0.1541  I     8.398    1.982    -3.492     .868   .085000   .238000  -.5692000      .000      .000  
+81 6 1 44756.00 I   .085963  .001168   .233012  .007887  I -.5732731  .0002180  2.7061 0.1541  I     7.611    1.982    -3.636     .868   .085000   .237000  -.5713000      .000      .000  
+81 6 2 44757.00 I   .085277  .001168   .232152  .007887  I -.5758756  .0002180  2.4954 0.1575  I     6.967    1.982    -3.838     .868   .085000   .236000  -.5735000      .000      .000  
+81 6 3 44758.00 I   .084589  .004077   .231328  .005654  I -.5782669  .0002274  2.2936 0.1388  I     6.715    1.982    -3.902     .868   .085000   .235000  -.5756000      .000      .000  
+81 6 4 44759.00 I   .083908  .004077   .230536  .005654  I -.5804817  .0001720  2.1485 0.1664  I     6.930    1.982    -3.808     .868   .085000   .234000  -.5778000      .000      .000  
+81 6 5 44760.00 I   .083242  .005646   .229771  .001316  I -.5825897  .0002430  2.0807 0.1219  I     7.427    1.982    -3.743     .868   .085000   .233000  -.5799000      .000      .000  
+81 6 6 44761.00 I   .082595  .004014   .229030  .001189  I -.5846656  .0001729  2.0805 0.1491  I     7.812    1.982    -3.829     .868   .085000   .232000  -.5819000      .000      .000  
+81 6 7 44762.00 I   .081969  .004014   .228306  .001189  I -.5867638  .0001729  2.1197 0.1122  I     7.712    1.982    -3.947     .868   .084000   .232000  -.5840000      .000      .000  
+81 6 8 44763.00 I   .081359  .003385   .227593  .001213  I -.5889077  .0001430  2.1670 0.0881  I     7.121    1.982    -3.918     .868   .084000   .231000  -.5860000      .000      .000  
+81 6 9 44764.00 I   .080762  .001117   .226886  .001159  I -.5910926  .0000341  2.1985 0.0735  I     6.457    1.982    -3.744     .868   .084000   .230000  -.5881000      .000      .000  
+81 610 44765.00 I   .080177  .001117   .226178  .001159  I -.5932950  .0000341  2.2007 0.0241  I     6.132    1.982    -3.579     .868   .084000   .229000  -.5900000      .000      .000  
+81 611 44766.00 I   .079601  .001117   .225466  .001159  I -.5954823  .0000341  2.1678 0.0861  I     6.094    1.982    -3.497     .868   .083000   .228000  -.5920000      .000      .000  
+81 612 44767.00 I   .079033  .002493   .224744  .003089  I -.5976188  .0001687  2.0995 0.0861  I     5.952    1.982    -3.419     .868   .083000   .227000  -.5939000      .000      .000  
+81 613 44768.00 I   .078473  .002493   .224009  .003089  I -.5996709  .0001687  1.9998 0.1343  I     5.503    1.982    -3.267     .868   .082000   .226000  -.5959000      .000      .000  
+81 614 44769.00 I   .077923  .003206   .223258  .004183  I -.6016105  .0002090  1.8762 0.1310  I     4.929    1.982    -3.098     .868   .082000   .225000  -.5978000      .000      .000  
+81 615 44770.00 I   .077383  .002495   .222489  .003090  I -.6034192  .0002004  1.7403 0.1448  I     4.485    1.982    -3.030     .868   .082000   .224000  -.5996000      .000      .000  
+81 616 44771.00 I   .076854  .002495   .221699  .003090  I -.6050920  .0002004  1.6070 0.1327  I     4.218    1.982    -3.088     .868   .081000   .223000  -.6014000      .000      .000  
+81 617 44772.00 I   .076331  .002196   .220890  .003278  I -.6066392  .0001739  1.4918 0.1210  I     4.044    1.982    -3.193     .868   .081000   .223000  -.6033000      .000      .000  
+81 618 44773.00 I   .075810  .001446   .220065  .002716  I -.6080868  .0001356  1.4101 0.1103  I     3.901    1.982    -3.259     .868   .080000   .222000  -.6051000      .000      .000  
+81 619 44774.00 I   .075287  .001446   .219227  .002716  I -.6094747  .0001356  1.3743 0.0949  I     3.722    1.982    -3.272     .868   .080000   .221000  -.6069000      .000      .000  
+81 620 44775.00 I   .074760  .001901   .218381  .002219  I -.6108528  .0001328  1.3908 0.0856  I     3.418    1.982    -3.268     .868   .080000   .220000  -.6086000      .000      .000  
+81 621 44776.00 I   .074228  .002082   .217529  .002566  I -.6122734  .0001045  1.4584 0.0845  I     3.002    1.982    -3.254     .868   .079000   .219000  -.6103000      .000      .000  
+81 622 44777.00 I   .073692  .002082   .216671  .002566  I -.6137833  .0001045  1.5669 0.0829  I     2.643    1.982    -3.198     .868   .079000   .218000  -.6120000      .000      .000  
+81 623 44778.00 I   .073151  .002581   .215806  .000137  I -.6154147  .0001287  1.6979 0.1435  I     2.482    1.982    -3.070     .868   .078000   .217000  -.6137000      .000      .000  
+81 624 44779.00 I   .072607  .001826   .214934  .001702  I -.6171786  .0002672  1.8272 0.1483  I     2.444    1.982    -2.886     .868   .078000   .216000  -.6154000      .000      .000  
+81 625 44780.00 I   .072064  .001826   .214053  .001702  I -.6190588  .0002672  1.9254 0.2353  I     2.289    1.982    -2.686     .868   .078000   .215000  -.6170000      .000      .000  
+81 626 44781.00 I   .071529  .000076   .213163  .002404  I -.6210088  .0003875  1.9619 0.2172  I     1.816    1.982    -2.515     .868   .077000   .214000  -.6186000      .000      .000  
+81 627 44782.00 I   .071005  .005605   .212264  .001880  I -.6229551  .0003425  1.9159 0.2586  I     1.002    1.982    -2.437     .868   .077000   .213000  -.6201000      .000      .000  
+81 628 44783.00 I   .070500  .005605   .211356  .001880  I -.6248128  .0003425  1.7866 0.2422  I      .012    1.982    -2.522     .868   .076000   .212000  -.6217000      .000      .000  
+81 629 44784.00 I   .070017  .005605   .210444  .001880  I -.6265089  .0003425  1.5991 0.2157  I     -.884    1.982    -2.761     .868   .076000   .211000  -.6233000      .000      .000  
+81 630 44785.00 I   .069562  .006753   .209527  .000803  I -.6280070  .0002624  1.3997 0.2157  I    -1.453    1.982    -2.995     .868   .076000   .210000  -.6248000      .000      .000  
+81 7 1 44786.00 I   .069135  .006753   .208610  .000803  I  .3706787  .0002624  1.2393 0.1855  I    -1.627    1.982    -3.033     .868   .075000   .209000   .3738000      .000      .000  
+81 7 2 44787.00 I   .068727  .006753   .207692  .000803  I  .3694899  .0002624  1.1523 0.1598  I    -1.491    1.982    -2.871     .868   .075000   .208000   .3723000      .000      .000  
+81 7 3 44788.00 I   .068327  .004254   .206774  .000564  I  .3683480  .0001826  1.1434 0.1598  I    -1.212    1.982    -2.716     .868   .074000   .207000   .3709000      .000      .000  
+81 7 4 44789.00 I   .067935  .004254   .205857  .000564  I  .3671843  .0001826  1.1909 0.1291  I    -1.024    1.982    -2.743     .868   .074000   .206000   .3694000      .000      .000  
+81 7 5 44790.00 I   .067552  .004254   .204942  .000564  I  .3659587  .0001826  1.2610 0.1121  I    -1.184    1.982    -2.885     .868   .073000   .205000   .3680000      .000      .000  
+81 7 6 44791.00 I   .067176  .002161   .204031  .000663  I  .3646653  .0001301  1.3222 0.1121  I    -1.778    1.982    -2.932     .868   .073000   .204000   .3666000      .000      .000  
+81 7 7 44792.00 I   .066808  .002161   .203123  .000663  I  .3633237  .0001301  1.3551 0.1057  I    -2.583    1.982    -2.810     .868   .072000   .204000   .3651000      .000      .000  
+81 7 8 44793.00 I   .066442  .001782   .202222  .000960  I  .3619672  .0001666  1.3515 0.1138  I    -3.251    1.982    -2.653     .868   .072000   .203000   .3637000      .000      .000  
+81 7 9 44794.00 I   .066073  .000926   .201328  .001032  I  .3606327  .0001868  1.3119 0.1251  I    -3.671    1.982    -2.597     .868   .071000   .202000   .3623000      .000      .000  
+81 710 44795.00 I   .065696  .000926   .200444  .001032  I  .3593538  .0001868  1.2413 0.1321  I    -4.022    1.982    -2.603     .868   .070000   .201000   .3609000      .000      .000  
+81 711 44796.00 I   .065302  .000926   .199571  .001032  I  .3581575  .0001868  1.1486 0.1223  I    -4.472    1.982    -2.541     .868   .069000   .200000   .3596000      .000      .000  
+81 712 44797.00 I   .064885  .000683   .198710  .001549  I  .3570599  .0001580  1.0460 0.1223  I    -4.978    1.982    -2.366     .868   .069000   .200000   .3582000      .000      .000  
+81 713 44798.00 I   .064440  .000683   .197866  .001549  I  .3560642  .0001580  0.9474 0.1063  I    -5.431    1.982    -2.175     .868   .068000   .199000   .3569000      .000      .000  
+81 714 44799.00 I   .063959  .002177   .197041  .002598  I  .3551590  .0001421  0.8673 0.1063  I    -5.825    1.982    -2.097     .868   .067000   .198000   .3555000      .000      .000  
+81 715 44800.00 I   .063435  .002177   .196238  .002598  I  .3543187  .0001421  0.8201 0.1005  I    -6.181    1.982    -2.168     .868   .066000   .197000   .3542000      .000      .000  
+81 716 44801.00 I   .062865  .002177   .195458  .002598  I  .3535035  .0001421  0.8190 0.1015  I    -6.448    1.982    -2.309     .868   .065000   .196000   .3529000      .000      .000  
+81 717 44802.00 I   .062243  .002177   .194704  .002598  I  .3526621  .0001451  0.8738 0.1851  I    -6.597    1.982    -2.393     .868   .064000   .196000   .3515000      .000      .000  
+81 718 44803.00 I   .061567  .002092   .193973  .002319  I  .3517366  .0003418  0.9866 0.1857  I    -6.749    1.982    -2.353     .868   .063000   .195000   .3502000      .000      .000  
+81 719 44804.00 I   .060837  .002092   .193262  .002319  I  .3506726  .0003418  1.1482 0.2633  I    -7.057    1.982    -2.232     .868   .062000   .194000   .3489000      .000      .000  
+81 720 44805.00 I   .060054  .000154   .192568  .000416  I  .3494308  .0004005  1.3380 0.2766  I    -7.495    1.982    -2.129     .868   .061000   .193000   .3476000      .000      .000  
+81 721 44806.00 I   .059219  .000603   .191888  .001887  I  .3479970  .0004350  1.5267 0.2956  I    -7.868    1.982    -2.086     .868   .060000   .193000   .3462000      .000      .000  
+81 722 44807.00 I   .058334  .000603   .191218  .001887  I  .3463884  .0004350  1.6823 0.3324  I    -8.062    1.982    -2.051     .868   .059000   .192000   .3449000      .000      .000  
+81 723 44808.00 I   .057398  .000603   .190553  .001887  I  .3446521  .0005028  1.7786 0.2763  I    -8.198    1.982    -1.963     .868   .058000   .192000   .3435000      .000      .000  
+81 724 44809.00 I   .056412  .000604   .189891  .003506  I  .3428561  .0003407  1.8002 0.3037  I    -8.523    1.982    -1.839     .868   .057000   .191000   .3422000      .000      .000  
+81 725 44810.00 I   .055375  .000604   .189230  .003506  I  .3410767  .0003407  1.7468 0.2409  I    -9.169    1.982    -1.774     .868   .056000   .190000   .3408000      .000      .000  
+81 726 44811.00 I   .054287  .000604   .188569  .003506  I  .3393814  .0003407  1.6368 0.2073  I   -10.015    1.982    -1.854     .868   .055000   .190000   .3394000      .000      .000  
+81 727 44812.00 I   .053147  .002078   .187908  .003162  I  .3378102  .0002363  1.5054 0.2073  I   -10.769    1.982    -2.063     .868   .054000   .189000   .3380000      .000      .000  
+81 728 44813.00 I   .051952  .002078   .187248  .003162  I  .3363637  .0002363  1.3946 0.1603  I   -11.185    1.982    -2.267     .868   .053000   .189000   .3366000      .000      .000  
+81 729 44814.00 I   .050703  .001805   .186592  .003082  I  .3350022  .0002166  1.3403 0.1926  I   -11.222    1.982    -2.316     .868   .052000   .188000   .3352000      .000      .000  
+81 730 44815.00 I   .049399  .002208   .185946  .002330  I  .3336592  .0003043  1.3579 0.1619  I   -11.029    1.982    -2.180     .868   .051000   .187000   .3337000      .000      .000  
+81 731 44816.00 I   .048043  .002208   .185316  .002330  I  .3322658  .0002407  1.4373 0.1940  I   -10.802    1.982    -1.997     .868   .050000   .187000   .3323000      .000      .000  
+81 8 1 44817.00 I   .046639  .002208   .184711  .002330  I  .3307738  .0002407  1.5491 0.1586  I   -10.691    1.982    -1.930     .868   .049000   .186000   .3308000      .000      .000  
+81 8 2 44818.00 I   .045190  .000952   .184134  .002538  I  .3291684  .0002066  1.6585 0.1586  I   -10.809    1.982    -1.983     .868   .048000   .186000   .3294000      .000      .000  
+81 8 3 44819.00 I   .043700  .000952   .183590  .002538  I  .3274667  .0002066  1.7382 0.1508  I   -11.207    1.982    -2.018     .868   .047000   .185000   .3279000      .000      .000  
+81 8 4 44820.00 I   .042171  .000819   .183082  .002095  I  .3257067  .0002196  1.7739 0.1089  I   -11.829    1.982    -1.944     .868   .046000   .185000   .3264000      .000      .000  
+81 8 5 44821.00 I   .040604  .001400   .182613  .002322  I  .3239344  .0000688  1.7632 0.1108  I   -12.498    1.982    -1.835     .868   .045000   .184000   .3250000      .000      .000  
+81 8 6 44822.00 I   .039001  .001400   .182187  .002322  I  .3221940  .0000302  1.7113 0.0376  I   -13.030    1.982    -1.807     .868   .043000   .184000   .3235000      .000      .000  
+81 8 7 44823.00 I   .037364  .001400   .181810  .002322  I  .3205223  .0000302  1.6277 0.0158  I   -13.351    1.982    -1.847     .868   .042000   .183000   .3221000      .000      .000  
+81 8 8 44824.00 I   .035693  .001624   .181488  .005717  I  .3189449  .0000091  1.5251 0.0158  I   -13.520    1.982    -1.826     .868   .041000   .183000   .3206000      .000      .000  
+81 8 9 44825.00 I   .033992  .001624   .181224  .005717  I  .3174735  .0000091  1.4183 0.0064  I   -13.674    1.982    -1.670     .868   .040000   .183000   .3191000      .000      .000  
+81 810 44826.00 I   .032265  .001624   .181021  .005717  I  .3161045  .0000091  1.3229 0.1604  I   -13.941    1.982    -1.459     .868   .038000   .183000   .3176000      .000      .000  
+81 811 44827.00 I   .030516  .002006   .180881  .005495  I  .3148191  .0003207  1.2531 0.1604  I   -14.349    1.982    -1.356     .868   .037000   .182000   .3161000      .000      .000  
+81 812 44828.00 I   .028750  .002006   .180802  .005495  I  .3135857  .0003207  1.2209 0.2268  I   -14.780    1.982    -1.455     .868   .035000   .182000   .3146000      .000      .000  
+81 813 44829.00 I   .026974  .002006   .180777  .005495  I  .3123613  .0003207  1.2366 0.2561  I   -15.058    1.982    -1.692     .868   .034000   .182000   .3131000      .000      .000  
+81 814 44830.00 I   .025195  .002714   .180800  .002200  I  .3110942  .0003995  1.3073 0.2561  I   -15.112    1.982    -1.888     .868   .033000   .182000   .3116000      .000      .000  
+81 815 44831.00 I   .023416  .002714   .180862  .002200  I  .3097288  .0003995  1.4318 0.2825  I   -15.047    1.982    -1.880     .868   .031000   .182000   .3100000      .000      .000  
+81 816 44832.00 I   .021640  .002714   .180959  .002200  I  .3082181  .0003995  1.5938 0.2329  I   -15.044    1.982    -1.668     .868   .030000   .181000   .3085000      .000      .000  
+81 817 44833.00 I   .019869  .002573   .181085  .002192  I  .3065392  .0002396  1.7619 0.2329  I   -15.192    1.982    -1.420     .868   .028000   .181000   .3069000      .000      .000  
+81 818 44834.00 I   .018106  .002573   .181235  .002192  I  .3047050  .0002396  1.8978 0.1555  I   -15.445    1.982    -1.312     .868   .027000   .181000   .3054000      .000      .000  
+81 819 44835.00 I   .016361  .002595   .181406  .001884  I  .3027657  .0001984  1.9673 0.1222  I   -15.702    1.982    -1.367     .868   .025000   .181000   .3038000      .000      .000  
+81 820 44836.00 I   .014640  .002398   .181598  .001087  I  .3007986  .0000480  1.9521 0.1021  I   -15.925    1.982    -1.466     .868   .024000   .181000   .3022000      .000      .000  
+81 821 44837.00 I   .012948  .002398   .181808  .001087  I  .2988884  .0000480  1.8561 0.0339  I   -16.160    1.982    -1.501     .868   .022000   .181000   .3006000      .000      .000  
+81 822 44838.00 I   .011288  .002398   .182037  .001087  I  .2971055  .0000480  1.7030 0.0961  I   -16.474    1.982    -1.473     .868   .021000   .181000   .2990000      .000      .000  
+81 823 44839.00 I   .009661  .002387   .182284  .000767  I  .2954891  .0001861  1.5300 0.0961  I   -16.855    1.982    -1.456     .868   .019000   .181000   .2974000      .000      .000  
+81 824 44840.00 I   .008067  .002387   .182551  .000767  I  .2940387  .0001861  1.3774 0.1577  I   -17.191    1.982    -1.495     .868   .017000   .181000   .2958000      .000      .000  
+81 825 44841.00 I   .006502  .001489   .182837  .001621  I  .2927164  .0002546  1.2785 0.1577  I   -17.331    1.982    -1.561     .868   .016000   .181000   .2941000      .000      .000  
+81 826 44842.00 I   .004967  .001489   .183144  .001621  I  .2914576  .0002546  1.2518 0.1800  I   -17.205    1.982    -1.584     .868   .014000   .182000   .2925000      .000      .000  
+81 827 44843.00 I   .003459  .001489   .183472  .001621  I  .2901894  .0002546  1.2953 0.1800  I   -16.882    1.982    -1.519     .868   .013000   .182000   .2908000      .000      .000  
+81 828 44844.00 I   .001971  .001489   .183822  .001621  I  .2888507  .0002546  1.3877 0.1700  I   -16.534    1.982    -1.399     .868   .011000   .182000   .2892000      .000      .000  
+81 829 44845.00 I   .000498  .001452   .184192  .002333  I  .2874083  .0002253  1.4970 0.1700  I   -16.316    1.982    -1.290     .868   .009000   .182000   .2875000      .000      .000  
+81 830 44846.00 I  -.000964  .001452   .184580  .002333  I  .2858615  .0002253  1.5917 0.1378  I   -16.283    1.982    -1.215     .868   .008000   .182000   .2858000      .000      .000  
+81 831 44847.00 I  -.002421  .002707   .184983  .002725  I  .2842370  .0001589  1.6500 0.1378  I   -16.412    1.982    -1.135     .868   .006000   .183000   .2841000      .000      .000  
+81 9 1 44848.00 I  -.003878  .002707   .185399  .002725  I  .2825765  .0001589  1.6634 0.1124  I   -16.670    1.982    -1.035     .868   .005000   .183000   .2824000      .000      .000  
+81 9 2 44849.00 I  -.005341  .002707   .185825  .002725  I  .2809244  .0001589  1.6343 0.1205  I   -17.002    1.982     -.980     .868   .003000   .183000   .2807000      .000      .000  
+81 9 3 44850.00 I  -.006820  .002371   .186262  .003254  I  .2793189  .0001813  1.5721 0.1179  I   -17.260    1.982    -1.033     .868   .001000   .183000   .2789000      .000      .000  
+81 9 4 44851.00 I  -.008321  .002515   .186711  .003605  I  .2777869  .0001742  1.4897 0.1257  I   -17.259    1.982    -1.147     .868   .000000   .184000   .2771000      .000      .000  
+81 9 5 44852.00 I  -.009847  .002515   .187177  .003605  I  .2763411  .0001742  1.4026 0.1400  I   -16.985    1.982    -1.195     .868  -.002000   .184000   .2754000      .000      .000  
+81 9 6 44853.00 I  -.011401  .001488   .187664  .004112  I  .2749774  .0002192  1.3284 0.1241  I   -16.700    1.982    -1.121     .868  -.003000   .185000   .2736000      .000      .000  
+81 9 7 44854.00 I  -.012986  .001062   .188175  .003021  I  .2736749  .0001768  1.2825 0.1408  I   -16.698    1.982    -1.009     .868  -.005000   .185000   .2718000      .000      .000  
+81 9 8 44855.00 I  -.014601  .001062   .188708  .003021  I  .2723988  .0001768  1.2773 0.1513  I   -16.980    1.982     -.988     .868  -.007000   .186000   .2699000      .000      .000  
+81 9 9 44856.00 I  -.016248  .000659   .189263  .000854  I  .2711036  .0002456  1.3222 0.1513  I   -17.252    1.982    -1.106     .868  -.008000   .186000   .2681000      .000      .000  
+81 910 44857.00 I  -.017925  .000659   .189838  .000854  I  .2697354  .0002456  1.4242 0.1737  I   -17.272    1.982    -1.306     .868  -.010000   .187000   .2662000      .000      .000  
+81 911 44858.00 I  -.019633  .000659   .190433  .000854  I  .2682354  .0002456  1.5857 0.1737  I   -17.063    1.982    -1.463     .868  -.011000   .187000   .2644000      .000      .000  
+81 912 44859.00 I  -.021374  .000659   .191049  .000854  I  .2665468  .0002456  1.7989 0.2203  I   -16.790    1.982    -1.446     .868  -.013000   .188000   .2625000      .000      .000  
+81 913 44860.00 I  -.023145  .000878   .191686  .000257  I  .2646284  .0003657  2.0397 0.2203  I   -16.550    1.982    -1.211     .868  -.015000   .189000   .2606000      .000      .000  
+81 914 44861.00 I  -.024947  .000878   .192346  .000257  I  .2624718  .0003657  2.2674 0.2742  I   -16.371    1.982     -.880     .868  -.016000   .190000   .2586000      .000      .000  
+81 915 44862.00 I  -.026777  .000666   .193028  .000960  I  .2601132  .0004086  2.4362 0.2742  I   -16.300    1.982     -.683     .868  -.018000   .191000   .2567000      .000      .000  
+81 916 44863.00 I  -.028635  .000666   .193735  .000960  I  .2576309  .0004086  2.5104 0.2889  I   -16.378    1.982     -.758     .868  -.019000   .192000   .2547000      .000      .000  
+81 917 44864.00 I  -.030519  .000666   .194466  .000960  I  .2551270  .0004086  2.4807 0.2889  I   -16.544    1.982    -1.015     .868  -.021000   .193000   .2528000      .000      .000  
+81 918 44865.00 I  -.032426  .000666   .195223  .000960  I  .2526969  .0004086  2.3689 0.2687  I   -16.666    1.982    -1.233     .868  -.023000   .194000   .2508000      .000      .000  
+81 919 44866.00 I  -.034352  .000382   .196006  .001011  I  .2504021  .0003491  2.2184 0.2687  I   -16.666    1.982    -1.274     .868  -.024000   .195000   .2488000      .000      .000  
+81 920 44867.00 I  -.036297  .000382   .196814  .001011  I  .2482567  .0003491  2.0782 0.2196  I   -16.562    1.982    -1.181     .868  -.026000   .197000   .2467000      .000      .000  
+81 921 44868.00 I  -.038258  .000344   .197645  .000477  I  .2462289  .0002666  1.9884 0.1986  I   -16.403    1.982    -1.081     .868  -.027000   .198000   .2447000      .000      .000  
+81 922 44869.00 I  -.040233  .000507   .198500  .000453  I  .2442564  .0001896  1.9692 0.1636  I   -16.184    1.982    -1.045     .868  -.029000   .199000   .2427000      .000      .000  
+81 923 44870.00 I  -.042219  .000507   .199377  .000453  I  .2422674  .0001896  2.0194 0.1417  I   -15.851    1.982    -1.061     .868  -.031000   .200000   .2406000      .000      .000  
+81 924 44871.00 I  -.044215  .001548   .200276  .000552  I  .2402008  .0002107  2.1202 0.1294  I   -15.377    1.982    -1.086     .868  -.033000   .201000   .2385000      .000      .000  
+81 925 44872.00 I  -.046217  .001880   .201196  .000586  I  .2380198  .0001761  2.2428 0.1373  I   -14.834    1.982    -1.092     .868  -.034000   .203000   .2365000      .000      .000  
+81 926 44873.00 I  -.048222  .001880   .202137  .000586  I  .2357184  .0001761  2.3559 0.1874  I   -14.361    1.982    -1.057     .868  -.036000   .204000   .2344000      .000      .000  
+81 927 44874.00 I  -.050225  .001755   .203100  .000936  I  .2333195  .0003308  2.4345 0.2206  I   -14.040    1.982     -.956     .868  -.038000   .205000   .2323000      .000      .000  
+81 928 44875.00 I  -.052222  .002103   .204084  .001106  I  .2308657  .0004046  2.4643 0.2613  I   -13.835    1.982     -.787     .868  -.040000   .206000   .2301000      .000      .000  
+81 929 44876.00 I  -.054203  .002103   .205092  .001106  I  .2284081  .0004046  2.4426 0.3443  I   -13.666    1.982     -.622     .868  -.042000   .207000   .2279000      .000      .000  
+81 930 44877.00 I  -.056160  .001213   .206123  .001181  I  .2259958  .0005573  2.3752 0.3443  I   -13.482    1.982     -.587     .868  -.043000   .209000   .2258000      .000      .000  
+8110 1 44878.00 I  -.058084  .001213   .207180  .001181  I  .2236689  .0005573  2.2744 0.3941  I   -13.205    1.982     -.736     .868  -.045000   .210000   .2236000      .000      .000  
+8110 2 44879.00 I  -.059970  .001213   .208266  .001181  I  .2214526  .0005573  2.1568 0.4079  I   -12.702    1.982     -.969     .868  -.047000   .211000   .2214000      .000      .000  
+8110 3 44880.00 I  -.061812  .000881   .209382  .000922  I  .2193548  .0005958  2.0406 0.3575  I   -11.976    1.982    -1.126     .868  -.049000   .212000   .2192000      .000      .000  
+8110 4 44881.00 I  -.063603  .001432   .210532  .000926  I  .2173644  .0004478  1.9453 0.3727  I   -11.306    1.982    -1.161     .868  -.050000   .213000   .2169000      .000      .000  
+8110 5 44882.00 I  -.065341  .001432   .211718  .000926  I  .2154516  .0004478  1.8876 0.2483  I   -11.003    1.982    -1.168     .868  -.052000   .215000   .2147000      .000      .000  
+8110 6 44883.00 I  -.067020  .001824   .212941  .000929  I  .2135733  .0002146  1.8775 0.2397  I   -10.996    1.982    -1.230     .868  -.053000   .216000   .2124000      .000      .000  
+8110 7 44884.00 I  -.068636  .002727   .214202  .001927  I  .2116786  .0001712  1.9214 0.1373  I   -10.879    1.982    -1.314     .868  -.055000   .217000   .2102000      .000      .000  
+8110 8 44885.00 I  -.070186  .002727   .215504  .001927  I  .2097112  .0001712  2.0232 0.1211  I   -10.405    1.982    -1.349     .868  -.056000   .218000   .2079000      .000      .000  
+8110 9 44886.00 I  -.071670  .002727   .216846  .001927  I  .2076132  .0001712  2.1819 0.1727  I    -9.746    1.982    -1.327     .868  -.058000   .219000   .2056000      .000      .000  
+811010 44887.00 I  -.073087  .002406   .218228  .001834  I  .2053325  .0002999  2.3853 0.1727  I    -9.179    1.982    -1.255     .868  -.059000   .221000   .2032000      .000      .000  
+811011 44888.00 I  -.074442  .002406   .219649  .001834  I  .2028375  .0002999  2.6041 0.2121  I    -8.722    1.982    -1.096     .868  -.061000   .222000   .2009000      .000      .000  
+811012 44889.00 I  -.075740  .002406   .221105  .001834  I  .2001341  .0002999  2.7934 0.2243  I    -8.238    1.982     -.850     .868  -.062000   .223000   .1986000      .000      .000  
+811013 44890.00 I  -.076987  .000538   .222593  .000475  I  .1972769  .0003337  2.9041 0.2243  I    -7.731    1.982     -.667     .868  -.063000   .224000   .1962000      .000      .000  
+811014 44891.00 I  -.078189  .000538   .224110  .000475  I  .1943629  .0003337  2.9040 0.2203  I    -7.332    1.982     -.740     .868  -.064000   .226000   .1939000      .000      .000  
+811015 44892.00 I  -.079350  .000836   .225653  .000388  I  .1915051  .0002878  2.7955 0.1949  I    -7.055    1.982    -1.057     .868  -.066000   .227000   .1915000      .000      .000  
+811016 44893.00 I  -.080477  .001017   .227218  .000378  I  .1887956  .0002015  2.6161 0.1757  I    -6.750    1.982    -1.370     .868  -.067000   .229000   .1892000      .000      .000  
+811017 44894.00 I  -.081573  .001017   .228801  .000378  I  .1862774  .0002015  2.4233 0.1335  I    -6.302    1.982    -1.455     .868  -.068000   .230000   .1868000      .000      .000  
+811018 44895.00 I  -.082642  .000922   .230398  .000536  I  .1839350  .0001752  2.2724 0.1214  I    -5.734    1.982    -1.343     .868  -.069000   .231000   .1844000      .000      .000  
+811019 44896.00 I  -.083687  .001000   .232006  .000536  I  .1817077  .0001355  2.1963 0.1107  I    -5.134    1.982    -1.234     .868  -.070000   .233000   .1820000      .000      .000  
+811020 44897.00 I  -.084709  .001000   .233618  .000536  I  .1795157  .0001355  2.2002 0.0843  I    -4.548     .110    -1.249     .868  -.072000   .234000   .1797000      .000      .000  
+811021 44898.00 I  -.085710  .000797   .235233  .001396  I  .1772865  .0001003  2.2664 0.0843  I    -3.957     .110    -1.347     .868  -.073000   .236000   .1773000      .000      .000  
+811022 44899.00 I  -.086693  .000797   .236845  .001396  I  .1749720  .0001003  2.3653 0.0709  I    -3.296     .110    -1.445     .868  -.074000   .237000   .1749000      .000      .000  
+811023 44900.00 I  -.087659  .000797   .238452  .001396  I  .1725556  .0001003  2.4652 0.0694  I    -2.525     .110    -1.525     .868  -.075000   .239000   .1725000      .000      .000  
+811024 44901.00 I  -.088611  .000888   .240050  .001823  I  .1700496  .0000960  2.5411 0.0608  I    -1.709     .110    -1.585     .868  -.076000   .240000   .1700000      .000      .000  
+811025 44902.00 I  -.089553  .003430   .241637  .002271  I  .1674868  .0000687  2.5767 0.0590  I     -.980     .110    -1.570     .868  -.078000   .242000   .1676000      .000      .000  
+811026 44903.00 I  -.090490  .003430   .243214  .002271  I  .1649119  .0000687  2.5651 0.0352  I     -.394    1.982    -1.436     .868  -.079000   .243000   .1651000      .000      .000  
+811027 44904.00 I  -.091427  .004769   .244778  .002643  I  .1623716  .0000150  2.5083 0.1127  I      .130    1.982    -1.258     .868  -.080000   .245000   .1627000      .000      .000  
+811028 44905.00 I  -.092366  .003412   .246330  .001888  I  .1599077  .0002146  2.4142 0.1076  I      .702    1.982    -1.208     .868  -.081000   .247000   .1603000      .000      .000  
+811029 44906.00 I  -.093305  .003412   .247871  .001888  I  .1575515  .0002146  2.2953 0.1517  I     1.390    1.982    -1.377     .868  -.082000   .248000   .1579000      .000      .000  
+811030 44907.00 I  -.094240  .003412   .249406  .001888  I  .1553197  .0002146  2.1685 0.1857  I     2.224    1.982    -1.659     .868  -.083000   .250000   .1554000      .000      .000  
+811031 44908.00 I  -.095166  .000738   .250935  .000375  I  .1532109  .0003031  2.0525 0.1887  I     3.143    1.982    -1.868     .868  -.084000   .251000   .1530000      .000      .000  
+8111 1 44909.00 I  -.096079  .001179   .252462  .001699  I  .1512050  .0003104  1.9656 0.2169  I     3.925    1.982    -1.946     .868  -.085000   .253000   .1506000      .000      .000  
+8111 2 44910.00 I  -.096977  .001179   .253991  .001699  I  .1492653  .0003104  1.9218 0.1993  I     4.339    1.982    -1.982     .868  -.086000   .255000   .1482000      .000      .000  
+8111 3 44911.00 I  -.097855  .001057   .255525  .002302  I  .1473445  .0002502  1.9286 0.1993  I     4.467    1.982    -2.035     .868  -.087000   .257000   .1459000      .000      .000  
+8111 4 44912.00 I  -.098712  .001057   .257066  .002302  I  .1453902  .0002502  1.9890 0.1630  I     4.675    1.982    -2.028     .868  -.087000   .258000   .1435000      .000      .000  
+8111 5 44913.00 I  -.099541  .001668   .258616  .001938  I  .1433488  .0002090  2.1024 0.1630  I     5.169    1.982    -1.878     .868  -.088000   .260000   .1412000      .000      .000  
+8111 6 44914.00 I  -.100337  .001668   .260174  .001938  I  .1411696  .0002090  2.2632 0.1212  I     5.739    1.982    -1.652     .868  -.089000   .262000   .1388000      .000      .000  
+8111 7 44915.00 I  -.101093  .001748   .261743  .001679  I  .1388120  .0001228  2.4553 0.1477  I     6.083    1.982    -1.478     .868  -.090000   .264000   .1365000      .000      .000  
+8111 8 44916.00 I  -.101804  .002179   .263326  .001374  I  .1362590  .0002089  2.6473 0.1307  I     6.200    1.982    -1.350     .868  -.090000   .266000   .1342000      .000      .000  
+8111 9 44917.00 I  -.102468  .002669   .264926  .000590  I  .1335327  .0002308  2.7935 0.1557  I     6.278    1.982    -1.160     .868  -.091000   .268000   .1319000      .000      .000  
+811110 44918.00 I  -.103083  .002669   .266547  .000590  I  .1307020  .0002308  2.8498 0.2266  I     6.344    1.982     -.924     .868  -.091000   .270000   .1296000      .000      .000  
+811111 44919.00 I  -.103648  .002515   .268194  .003197  I  .1278706  .0003900  2.7937 0.2266  I     6.262    1.982     -.814     .868  -.092000   .272000   .1273000      .000      .000  
+811112 44920.00 I  -.104163  .002515   .269872  .003197  I  .1251477  .0003900  2.6384 0.2758  I     6.013    1.982     -.901     .868  -.093000   .274000   .1250000      .000      .000  
+811113 44921.00 I  -.104631  .002515   .271582  .003197  I  .1226108  .0003900  2.4323 0.2982  I     5.748    1.982     -.992     .868  -.093000   .276000   .1228000      .000      .000  
+811114 44922.00 I  -.105057  .002127   .273331  .004518  I  .1202790  .0004512  2.2386 0.2637  I     5.557    1.982     -.852     .868  -.094000   .278000   .1205000      .000      .000  
+811115 44923.00 I  -.105442  .002864   .275117  .003202  I  .1181126  .0003550  2.1081 0.2871  I     5.364    1.982     -.511     .868  -.094000   .280000   .1183000      .000      .000  
+811116 44924.00 I  -.105788  .002864   .276940  .003202  I  .1160345  .0003550  2.0626 0.1789  I     5.046    1.982     -.211     .868  -.095000   .282000   .1160000      .000      .000  
+811117 44925.00 I  -.106093  .000562   .278798  .000100  I  .1139627  .0000454  2.0913 0.1789  I     4.531     .905     -.080     .113  -.096000   .284000   .1138000      .000      .000  
+811118 44926.00 I  -.106359  .000562   .280687  .000100  I  .1118375  .0000454  2.1631 0.0321  I     3.789     .921      .007     .102  -.096000   .286000   .1115000      .000      .000  
+811119 44927.00 I  -.106590  .000562   .282607  .000100  I  .1096341  .0000454  2.2421 0.0321  I     2.864     .921      .220     .102  -.097000   .288000   .1093000      .000      .000  
+811120 44928.00 I  -.106792  .000562   .284556  .000100  I  .1073603  .0000454  2.3002 0.0262  I     1.890     .921      .546     .102  -.097000   .290000   .1070000      .000      .000  
+811121 44929.00 I  -.106971  .000678   .286533  .000095  I  .1050456  .0000261  2.3226 0.0262  I     1.018     .921      .857     .102  -.098000   .292000   .1048000      .000      .000  
+811122 44930.00 I  -.107133  .000678   .288535  .000095  I  .1027286  .0000261  2.3046 0.0161  I      .179     .921     1.130     .102  -.099000   .294000   .1026000      .000      .000  
+811123 44931.00 I  -.107280  .000579   .290560  .000056  I  .1004497  .0000189  2.2469 0.0590  I     -.792     .936     1.452     .868  -.099000   .296000   .1004000      .000      .000  
+811124 44932.00 I  -.107416  .004625   .292608  .000273  I  .0982459  .0001151  2.1560 0.0583  I    -1.873    1.982     1.837     .868  -.100000   .299000   .0982000      .000      .000  
+811125 44933.00 I  -.107540  .004625   .294677  .000273  I  .0961454  .0001151  2.0422 0.0814  I    -2.879    1.982     2.155     .868  -.100000   .301000   .0960000      .000      .000  
+811126 44934.00 I  -.107648  .004625   .296764  .000273  I  .0941645  .0001151  1.9195 0.1472  I    -3.679    1.982     2.291     .868  -.101000   .303000   .0938000      .000      .000  
+811127 44935.00 I  -.107733  .003310   .298869  .002690  I  .0923040  .0002710  1.8042 0.0628  I    -4.285    1.982     2.297     .868  -.101000   .305000   .0916000      .000      .000  
+811128 44936.00 I  -.107791  .004135   .300991  .002312  I  .0905479  .0000501  1.7136 0.1378  I    -4.795    1.982     2.328     .868  -.102000   .307000   .0894000      .000      .000  
+811129 44937.00 I  -.107815  .004135   .303127  .002312  I  .0888633  .0000501  1.6635 0.0354  I    -5.338    1.982     2.460     .868  -.102000   .310000   .0872000      .000      .000  
+811130 44938.00 I  -.107800  .004135   .305278  .002312  I  .0872040  .0000501  1.6643 0.0354  I    -6.041    1.982     2.629     .868  -.103000   .312000   .0850000      .000      .000  
+8112 1 44939.00 I  -.107740  .004135   .307440  .002312  I  .0855165  .0000501  1.7199 0.0385  I    -6.891    1.982     2.779     .868  -.103000   .314000   .0828000      .000      .000  
+8112 2 44940.00 I  -.107632  .007051   .309614  .002234  I  .0837467  .0000586  1.8279 0.0385  I    -7.700    1.982     2.968     .868  -.103000   .314000   .0806000      .000      .000  
+8112 3 44941.00 I  -.107476  .007051   .311800  .002234  I  .0818456  .0000586  1.9811 0.0441  I    -8.322    1.982     3.266     .868  -.103000   .314000   .0785000      .000      .000  
+8112 4 44942.00 I  -.107274  .009073   .314001  .002153  I  .0797734  .0000660  2.1676 0.0441  I    -8.835    1.982     3.608     .868  -.104000   .314000   .0763000      .000      .000  
+8112 5 44943.00 I  -.107030  .009073   .316218  .002153  I  .0775061  .0000660  2.3669 0.3207  I    -9.399    1.982     3.858     .868  -.104000   .314000   .0742000      .000      .000  
+8112 6 44944.00 I  -.106757  .009266   .318450  .001575  I  .0750458  .0006380  2.5477 0.3207  I   -10.018    1.982     4.003     .868  -.104000   .314000   .0720000      .000      .000  
+8112 7 44945.00 I  -.106473  .009266   .320697  .001575  I  .0724298  .0006380  2.6712 0.5516  I   -10.612    1.982     4.174     .868  -.104000   .318000   .0699000      .000      .000  
+8112 8 44946.00 I  -.106199  .009455   .322958  .000569  I  .0697333  .0008999  2.7048 0.4686  I   -11.231    1.982     4.430     .868  -.104000   .323000   .0677000      .000      .000  
+8112 9 44947.00 I  -.105953  .009107   .325231  .001187  I  .0670535  .0006864  2.6384 0.5659  I   -11.999    1.982     4.641     .868  -.104000   .327000   .0656000      .000      .000  
+811210 44948.00 I  -.105744  .009107   .327514  .001187  I  .0644823  .0006864  2.4945 0.4854  I   -12.839    1.982     4.690     .868  -.104000   .332000   .0634000      .000      .000  
+811211 44949.00 I  -.105574  .009107   .329807  .001187  I  .0620725  .0006864  2.3265 0.3667  I   -13.484    1.982     4.686     .868  -.104000   .336000   .0613000      .000      .000  
+811212 44950.00 I  -.105442  .006184   .332106  .001657  I  .0598174  .0002584  2.1942 0.3667  I   -13.767    1.982     4.833     .868  -.104000   .338000   .0592000      .000      .000  
+811213 44951.00 I  -.105335  .006184   .334407  .001657  I  .0576587  .0002584  2.1380 0.1827  I   -13.762    1.982     5.121     .868  -.104000   .340000   .0570000      .000      .000  
+811214 44952.00 I  -.105240  .006184   .336708  .001657  I  .0555139  .0002584  2.1644 0.1349  I   -13.655    1.982     5.314     .868  -.103000   .342000   .0549000      .000      .000  
+811215 44953.00 I  -.105141  .001281   .339004  .001285  I  .0533108  .0000774  2.2482 0.1672  I   -13.612    1.982     5.283     .868  -.103000   .344000   .0527000      .000      .000  
+811216 44954.00 I  -.105022  .001281   .341291  .001285  I  .0510120  .0002121  2.3487 0.1577  I   -13.767    1.982     5.201     .868  -.103000   .346000   .0506000      .000      .000  
+811217 44955.00 I  -.104869  .002934   .343568  .001323  I  .0486201  .0003057  2.4292 0.2072  I   -14.153    1.982     5.309     .868  -.102000   .348000   .0485000      .000      .000  
+811218 44956.00 I  -.104667  .003592   .345832  .001062  I  .0461677  .0003560  2.4674 0.2346  I   -14.622    1.982     5.604     .868  -.102000   .350000   .0463000      .000      .000  
+811219 44957.00 I  -.104404  .003592   .348081  .001062  I  .0437014  .0003560  2.4571 0.2517  I   -14.989    1.982     5.872     .868  -.101000   .352000   .0442000      .000      .000  
+811220 44958.00 I  -.104069  .003592   .350313  .001062  I  .0412683  .0003560  2.4022 0.2540  I   -15.283    1.982     5.981     .868  -.101000   .354000   .0420000      .000      .000  
+811221 44959.00 I  -.103653  .003435   .352526  .001021  I  .0389087  .0003623  2.3120 0.2510  I   -15.681    1.982     6.003     .868  -.100000   .356000   .0399000      .000      .000  
+811222 44960.00 I  -.103155  .003435   .354720  .001021  I  .0366522  .0003540  2.1980 0.1965  I   -16.206    1.982     6.050     .868  -.099000   .358000   .0378000      .000      .000  
+811223 44961.00 I  -.102571  .001027   .356893  .000364  I  .0345166  .0001521  2.0724 0.1926  I   -16.649    1.982     6.108     .868  -.099000   .360000   .0357000      .000      .000  
+811224 44962.00 I  -.101899  .001027   .359045  .000364  I  .0325064  .0001521  1.9500 0.1076  I   -16.839    1.982     6.083     .868  -.098000   .362000   .0335000      .000      .000  
+811225 44963.00 I  -.101139  .001027   .361177  .000364  I  .0306103  .0001521  1.8466 0.1648  I   -16.827    1.982     5.958     .868  -.098000   .364000   .0314000      .000      .000  
+811226 44964.00 I  -.100290  .002534   .363287  .000530  I  .0288017  .0002923  1.7776 0.2067  I   -16.746    1.982     5.823     .868  -.097000   .366000   .0293000      .000      .000  
+811227 44965.00 I  -.099351  .003433   .365377  .000655  I  .0270397  .0003844  1.7548 0.2415  I   -16.654    1.982     5.756     .868  -.096000   .368000   .0271000      .000      .000  
+811228 44966.00 I  -.098323  .003433   .367444  .000655  I  .0252743  .0003844  1.7852 0.2461  I   -16.581    1.982     5.752     .868  -.095000   .370000   .0249000      .000      .000  
+811229 44967.00 I  -.097204  .006823   .369491  .001586  I  .0234518  .0003073  1.8679 0.2461  I   -16.589    1.982     5.769     .868  -.094000   .372000   .0228000      .000      .000  
+811230 44968.00 I  -.095993  .006823   .371516  .001586  I  .0215243  .0003073  1.9931 0.2173  I   -16.706    1.982     5.798     .868  -.093000   .374000   .0206000      .000      .000  
+811231 44969.00 I  -.094684  .006823   .373520  .001586  I  .0194563  .0003073  2.1460 0.1841  I   -16.873    1.982     5.852     .868  -.092000   .376000   .0184000      .000      .000  
+82 1 1 44970.00 I  -.093270  .009017   .375504  .002146  I  .0172296  .0002029  2.3070 0.2160  I   -17.013    1.982     5.904     .868  -.091000   .378000   .0163000      .000      .000  
+82 1 2 44971.00 I  -.091756  .006377   .377467  .001876  I  .0148474  .0003035  2.4529 0.1825  I   -17.095    1.982     5.903     .868  -.090000   .380000   .0141000      .000      .000  
+82 1 3 44972.00 I  -.090151  .006377   .379406  .001876  I  .0123377  .0003035  2.5572 0.2425  I   -17.120    1.982     5.863     .868  -.089000   .382000   .0120000      .000      .000  
+82 1 4 44973.00 I  -.088467  .000096   .381320  .001559  I  .0097557  .0003782  2.5936 0.2120  I   -17.145    1.982     5.867     .868  -.088000   .384000   .0098000      .000      .000  
+82 1 5 44974.00 I  -.086713  .000784   .383207  .001120  I  .0071781  .0002961  2.5473 0.2424  I   -17.319    1.982     5.947     .868  -.087000   .386000   .0077000      .000      .000  
+82 1 6 44975.00 I  -.084900  .001117   .385064  .000992  I  .0046864  .0003034  2.4250 0.2120  I   -17.752    1.982     6.005     .868  -.086000   .388000   .0052000      .000      .000  
+82 1 7 44976.00 I  -.083037  .001117   .386892  .000992  I  .0023421  .0003034  2.2605 0.2069  I   -18.316    1.982     5.936     .868  -.085000   .390000   .0028000      .000      .000  
+82 1 8 44977.00 I  -.081135  .001366   .388691  .000510  I  .0001620  .0002814  2.1060 0.2069  I   -18.684    1.982     5.800     .868  -.084000   .391000   .0003000      .000      .000  
+82 1 9 44978.00 I  -.079203  .001366   .390460  .000510  I -.0018896  .0002814  2.0104 0.1886  I   -18.614    1.982     5.759     .868  -.083000   .393000  -.0021000      .000      .000  
+82 110 44979.00 I  -.077248  .001907   .392198  .000759  I -.0038869  .0002513  1.9990 0.1937  I   -18.119    1.982     5.834     .868  -.082000   .395000  -.0046000      .000      .000  
+82 111 44980.00 I  -.075276  .002201   .393905  .000908  I -.0059126  .0002664  2.0627 0.1257  I   -17.380    1.982     5.843     .868  -.081000   .396000  -.0071000      .000      .000  
+82 112 44981.00 I  -.073292  .002678   .395579  .001099  I -.0080250  .0000029  2.1646 0.1500  I   -16.626    1.982     5.660     .868  -.080000   .398000  -.0096000      .000      .000  
+82 113 44982.00 I  -.071301  .002587   .397219  .000823  I -.0102397  .0001380  2.2602 0.0690  I   -16.081    1.982     5.423     .868  -.078000   .399000  -.0121000      .000      .000  
+82 114 44983.00 I  -.069308  .002587   .398823  .000823  I -.0125318  .0001380  2.3151 0.0976  I   -15.882    1.982     5.383     .868  -.077000   .401000  -.0146000      .000      .000  
+82 115 44984.00 I  -.067313  .002587   .400393  .000823  I -.0148514  .0001380  2.3145 0.0993  I   -15.953    1.982     5.587     .868  -.076000   .402000  -.0171000      .000      .000  
+82 116 44985.00 I  -.065316  .001850   .401928  .000494  I -.0171431  .0001428  2.2607 0.0993  I   -16.090    1.982     5.816     .868  -.074000   .403000  -.0192000      .000      .000  
+82 117 44986.00 I  -.063321  .001850   .403428  .000494  I -.0193587  .0001428  2.1648 0.1010  I   -16.205    1.982     5.859     .868  -.073000   .404000  -.0213000      .000      .000  
+82 118 44987.00 I  -.061331  .001850   .404895  .000494  I -.0214634  .0001428  2.0412 0.0760  I   -16.350    1.982     5.725     .868  -.071000   .406000  -.0235000      .000      .000  
+82 119 44988.00 I  -.059352  .000794   .406328  .000583  I -.0234369  .0000519  1.9050 0.0760  I   -16.501    1.982     5.560     .868  -.070000   .407000  -.0256000      .000      .000  
+82 120 44989.00 I  -.057388  .000794   .407730  .000583  I -.0252742  .0000519  1.7712 0.2480  I   -16.468    1.982     5.440     .868  -.068000   .408000  -.0277000      .000      .000  
+82 121 44990.00 I  -.055443  .000794   .409100  .000583  I -.0269851  .0004932  1.6547 0.3741  I   -16.135    1.982     5.317     .868  -.066000   .409000  -.0289000      .000      .000  
+82 122 44991.00 I  -.053521  .003310   .410441  .002690  I -.0285942  .0007463  1.5698 0.3496  I   -15.627    1.982     5.127     .868  -.064000   .410000  -.0301000      .000      .000  
+82 123 44992.00 I  -.051625  .007194   .411754  .002014  I -.0301393  .0004955  1.5285 0.4479  I   -15.135    1.982     4.888     .868  -.062000   .412000  -.0313000      .000      .000  
+82 124 44993.00 I  -.049757  .007194   .413040  .002014  I -.0316687  .0004955  1.5397 0.3504  I   -14.689    1.982     4.679     .868  -.060000   .413000  -.0325000      .000      .000  
+82 125 44994.00 I  -.047923  .007194   .414302  .002014  I -.0332374  .0004955  1.6070 0.3174  I   -14.220    1.982     4.568     .868  -.058000   .414000  -.0337000      .000      .000  
+82 126 44995.00 I  -.046124  .005135   .415539  .001426  I -.0348993  .0003967  1.7243 0.2499  I   -13.760    1.982     4.555     .868  -.056000   .415000  -.0357000      .000      .000  
+82 127 44996.00 I  -.044360  .005135   .416754  .001426  I -.0366974  .0000647  1.8759 0.2010  I   -13.430    1.982     4.572     .868  -.054000   .416000  -.0378000      .000      .000  
+82 128 44997.00 I  -.042622  .005135   .417944  .001426  I -.0386546  .0000647  2.0379 0.0381  I   -13.265    1.982     4.534     .868  -.051000   .417000  -.0398000      .000      .000  
+82 129 44998.00 I  -.040900  .000989   .419110  .000107  I -.0407674  .0000403  2.1826 0.0625  I   -13.161    1.982     4.403     .868  -.049000   .418000  -.0419000      .000      .000  
+82 130 44999.00 I  -.039185  .001420   .420248  .000744  I -.0430055  .0001070  2.2844 0.0572  I   -13.006    1.982     4.219     .868  -.047000   .419000  -.0439000      .000      .000  
+82 131 45000.00 I  -.037469  .001420   .421359  .000744  I -.0453154  .0001070  2.3239 0.0905  I   -12.789    1.982     4.062     .868  -.045000   .420000  -.0462000      .000      .000  
+82 2 1 45001.00 I  -.035743  .001747   .422440  .001046  I -.0476297  .0001459  2.2928 0.0905  I   -12.590    1.982     3.982     .868  -.043000   .421000  -.0485000      .000      .000  
+82 2 2 45002.00 I  -.033998  .001747   .423491  .001046  I -.0498798  .0001459  2.1981 0.1033  I   -12.514    1.982     3.955     .868  -.040000   .422000  -.0507000      .000      .000  
+82 2 3 45003.00 I  -.032228  .001382   .424510  .000741  I -.0520130  .0001462  2.0647 0.1033  I   -12.588    1.982     3.892     .868  -.038000   .423000  -.0530000      .000      .000  
+82 2 4 45004.00 I  -.030426  .001382   .425498  .000741  I -.0540096  .0001462  1.9327 0.1035  I   -12.694    1.982     3.728     .868  -.036000   .424000  -.0553000      .000      .000  
+82 2 5 45005.00 I  -.028587  .000876   .426453  .000053  I -.0558938  .0001466  1.8470 0.0954  I   -12.625    1.982     3.501     .868  -.034000   .425000  -.0574000      .000      .000  
+82 2 6 45006.00 I  -.026708  .000876   .427377  .000053  I -.0577298  .0001226  1.8398 0.0893  I   -12.250    1.982     3.322     .868  -.032000   .426000  -.0596000      .000      .000  
+82 2 7 45007.00 I  -.024782  .001713   .428269  .001486  I -.0596014  .0001019  1.9165 0.0797  I   -11.600    1.982     3.225     .868  -.029000   .426000  -.0617000      .000      .000  
+82 2 8 45008.00 I  -.022809  .001713   .429130  .001486  I -.0615825  .0001019  2.0524 0.0602  I   -10.801    1.982     3.104     .868  -.027000   .427000  -.0639000      .000      .000  
+82 2 9 45009.00 I  -.020783  .002259   .429960  .002101  I -.0637115  .0000640  2.2043 0.0617  I    -9.992    1.982     2.850     .868  -.025000   .428000  -.0660000      .000      .000  
+82 210 45010.00 I  -.018701  .001677   .430758  .001618  I -.0659818  .0000697  2.3285 0.0715  I    -9.307    1.982     2.530     .868  -.023000   .429000  -.0686000      .000      .000  
+82 211 45011.00 I  -.016564  .001677   .431527  .001618  I -.0683497  .0001279  2.3965 0.0760  I    -8.860    1.982     2.346     .868  -.021000   .430000  -.0711000      .000      .000  
+82 212 45012.00 I  -.014371  .001677   .432269  .001618  I -.0707537  .0001351  2.4012 0.0928  I    -8.680    1.982     2.391     .868  -.018000   .430000  -.0737000      .000      .000  
+82 213 45013.00 I  -.012124  .001763   .432987  .001385  I -.0731338  .0001344  2.3511 0.0953  I    -8.688    1.982     2.530     .868  -.016000   .431000  -.0762000      .000      .000  
+82 214 45014.00 I  -.009825  .001763   .433684  .001385  I -.0754433  .0001344  2.2631 0.0975  I    -8.782    1.982     2.559     .868  -.014000   .432000  -.0788000      .000      .000  
+82 215 45015.00 I  -.007476  .001459   .434361  .001395  I -.0776534  .0001414  2.1552 0.1019  I    -8.864    1.982     2.423     .868  -.012000   .433000  -.0809000      .000      .000  
+82 216 45016.00 I  -.005079  .001712   .435019  .001584  I -.0797529  .0001532  2.0451 0.0929  I    -8.799    1.982     2.228     .868  -.010000   .433000  -.0830000      .000      .000  
+82 217 45017.00 I  -.002636  .001712   .435659  .001584  I -.0817487  .0001204  1.9505 0.1114  I    -8.435    1.982     2.072     .868  -.007000   .434000  -.0852000      .000      .000  
+82 218 45018.00 I  -.000144  .001712   .436282  .001584  I -.0836642  .0001617  1.8869 0.2000  I    -7.754    1.982     1.943     .868  -.005000   .434000  -.0873000      .000      .000  
+82 219 45019.00 I   .002399  .000413   .436885  .001416  I -.0855371  .0003814  1.8670 0.1932  I    -6.945    1.982     1.769     .868  -.003000   .435000  -.0894000      .000      .000  
+82 220 45020.00 I   .004994  .004493   .437468  .001830  I -.0874157  .0003509  1.8994 0.2713  I    -6.239    1.982     1.526     .868  -.001000   .435000  -.0915000      .000      .000  
+82 221 45021.00 I   .007642  .006341   .438026  .002166  I -.0893546  .0003858  1.9877 0.2608  I    -5.696    1.982     1.275     .868   .001000   .436000  -.0935000      .000      .000  
+82 222 45022.00 I   .010346  .006341   .438557  .002166  I -.0914086  .0003858  2.1285 0.2728  I    -5.220    1.982     1.121     .868   .004000   .436000  -.0956000      .000      .000  
+82 223 45023.00 I   .013106  .006341   .439060  .002166  I -.0936249  .0003858  2.3091 0.3136  I    -4.739    1.982     1.122     .868   .006000   .437000  -.0976000      .000      .000  
+82 224 45024.00 I   .015915  .004499   .439529  .001870  I -.0960319  .0004946  2.5050 0.2589  I    -4.281    1.982     1.212     .868   .008000   .437000  -.0997000      .000      .000  
+82 225 45025.00 I   .018763  .004499   .439959  .001870  I -.0986291  .0003454  2.6834 0.4592  I    -3.909    1.982     1.240     .868   .010000   .437000  -.1023000      .000      .000  
+82 226 45026.00 I   .021638  .000528   .440346  .001519  I -.1013812  .0007739  2.8095 0.4237  I    -3.639    1.982     1.098     .868   .012000   .438000  -.1049000      .000      .000  
+82 227 45027.00 I   .024531  .000528   .440682  .001519  I -.1042217  .0007739  2.8566 0.4982  I    -3.454    1.982      .826     .868   .015000   .438000  -.1075000      .000      .000  
+82 228 45028.00 I   .027431  .000722   .440966  .003324  I -.1070648  .0006275  2.8148 0.4982  I    -3.341    1.982      .558     .868   .017000   .439000  -.1101000      .000      .000  
+82 3 1 45029.00 I   .030329  .000722   .441192  .003324  I -.1098255  .0006275  2.6957 0.4394  I    -3.284    1.982      .397     .868   .019000   .439000  -.1127000      .000      .000  
+82 3 2 45030.00 I   .033215  .003015   .441358  .003167  I -.1124409  .0006153  2.5307 0.4498  I    -3.235    1.982      .332     .868   .021000   .439000  -.1149000      .000      .000  
+82 3 3 45031.00 I   .036080  .003015   .441461  .003167  I -.1148853  .0006447  2.3610 0.3782  I    -3.108    1.982      .282     .868   .023000   .439000  -.1170000      .000      .000  
+82 3 4 45032.00 I   .038915  .003015   .441502  .003167  I -.1171751  .0004401  2.2280 0.3903  I    -2.811    1.982      .183     .868   .026000   .440000  -.1192000      .000      .000  
+82 3 5 45033.00 I   .041713  .003015   .441483  .003167  I -.1193640  .0004401  2.1632 0.3100  I    -2.293    1.982      .031     .868   .028000   .440000  -.1213000      .000      .000  
+82 3 6 45034.00 I   .044468  .003593   .441406  .000566  I -.1215290  .0004368  2.1807 0.3100  I    -1.605    1.982     -.129     .868   .030000   .440000  -.1235000      .000      .000  
+82 3 7 45035.00 I   .047179  .003593   .441276  .000566  I -.1237490  .0004368  2.2688 0.2990  I     -.894    1.982     -.266     .868   .024000   .446000  -.1259000      .000      .000  
+82 3 8 45036.00 I   .049845  .002240   .441095  .000834  I -.1260787  .0004083  2.3933 0.2509  I     -.304    1.982     -.412     .868   .026000   .445000  -.1282000      .000      .000  
+82 3 9 45037.00 I   .052468  .002240   .440866  .000834  I -.1285333  .0002470  2.5110 0.2386  I      .118    1.982     -.618     .868   .028000   .445000  -.1306000      .000      .000  
+82 310 45038.00 I   .055050  .002240   .440593  .000834  I -.1310860  .0002470  2.5847 0.1761  I      .433    1.982     -.858     .868   .030000   .445000  -.1329000      .000      .000  
+82 311 45039.00 I   .057596  .003482   .440277  .000681  I -.1336814  .0002511  2.5947 0.1894  I      .698    1.982    -1.018     .868   .042000   .440000  -.1353000      .000      .000  
+82 312 45040.00 I   .060110  .003740   .439922  .000713  I -.1362541  .0002873  2.5409 0.1908  I      .888    1.982    -1.015     .868   .045000   .440000  -.1376000      .000      .000  
+82 313 45041.00 I   .062597  .003740   .439531  .000713  I -.1387466  .0002873  2.4373 0.1935  I      .922    1.982     -.910     .868   .047000   .440000  -.1399000      .000      .000  
+82 314 45042.00 I   .065059  .005133   .439108  .000033  I -.1411186  .0002593  2.3035 0.1479  I      .794    1.982     -.848     .868   .050000   .439000  -.1423000      .000      .000  
+82 315 45043.00 I   .067495  .001797   .438656  .000634  I -.1433509  .0000701  2.1616 0.1343  I      .644    1.982     -.899     .868   .052000   .439000  -.1446000      .000      .000  
+82 316 45044.00 I   .069900  .001797   .438180  .000634  I -.1454461  .0000701  2.0326 0.0432  I      .680    1.982    -1.011     .868   .055000   .439000  -.1469000      .000      .000  
+82 317 45045.00 I   .072266  .001105   .437682  .000749  I -.1474266  .0000505  1.9350 0.0432  I     1.020    1.982    -1.114     .868   .057000   .439000  -.1489000      .000      .000  
+82 318 45046.00 I   .074588  .001105   .437168  .000749  I -.1493315  .0000505  1.8834 0.0357  I     1.624    1.982    -1.198     .868   .060000   .438000  -.1509000      .000      .000  
+82 319 45047.00 I   .076865  .001105   .436637  .000749  I -.1512116  .0000505  1.8862 0.0357  I     2.346    1.982    -1.297     .868   .062000   .438000  -.1529000      .000      .000  
+82 320 45048.00 I   .079099  .001105   .436091  .000749  I -.1531232  .0000505  1.9467 0.0349  I     3.017    1.982    -1.425     .868   .065000   .437000  -.1549000      .000      .000  
+82 321 45049.00 I   .081299  .001979   .435531  .000561  I -.1551240  .0000482  2.0642 0.0664  I     3.496    1.982    -1.558     .868   .067000   .437000  -.1569000      .000      .000  
+82 322 45050.00 I   .083474  .004444   .434956  .001274  I -.1572687  .0001229  2.2330 0.0393  I     3.743    1.982    -1.648     .868   .069000   .437000  -.1595000      .000      .000  
+82 323 45051.00 I   .085634  .005848   .434365  .001265  I -.1596019  .0000622  2.4376 0.0706  I     3.857    1.982    -1.636     .868   .072000   .436000  -.1621000      .000      .000  
+82 324 45052.00 I   .087787  .005848   .433758  .001265  I -.1621463  .0000696  2.6494 0.0467  I     4.009    1.982    -1.511     .868   .074000   .436000  -.1646000      .000      .000  
+82 325 45053.00 I   .089939  .005848   .433136  .001265  I -.1648898  .0000696  2.8286 0.0676  I     4.250    1.982    -1.368     .868   .077000   .435000  -.1672000      .000      .000  
+82 326 45054.00 I   .092088  .004256   .432499  .001672  I -.1677794  .0001159  2.9357 0.1516  I     4.443    1.982    -1.361     .868   .079000   .435000  -.1698000      .000      .000  
+82 327 45055.00 I   .094233  .001421   .431849  .001998  I -.1707293  .0002952  2.9471 0.1586  I     4.410    1.982    -1.558     .868   .081000   .434000  -.1725000      .000      .000  
+82 328 45056.00 I   .096372  .001421   .431186  .001998  I -.1736428  .0002952  2.8660 0.2087  I     4.147    1.982    -1.856     .868   .084000   .434000  -.1752000      .000      .000  
+82 329 45057.00 I   .098502  .001421   .430514  .001998  I -.1764405  .0002952  2.7226 0.2320  I     3.827    1.982    -2.077     .868   .086000   .433000  -.1778000      .000      .000  
+82 330 45058.00 I   .100624  .001344   .429830  .001622  I -.1790828  .0003580  2.5635 0.2320  I     3.644    1.982    -2.124     .868   .089000   .433000  -.1805000      .000      .000  
+82 331 45059.00 I   .102737  .001344   .429134  .001622  I -.1815781  .0003580  2.4362 0.2770  I     3.680    1.982    -2.037     .868   .091000   .432000  -.1832000      .000      .000  
+82 4 1 45060.00 I   .104842  .001262   .428425  .001125  I -.1839775  .0004228  2.3759 0.2059  I     3.930    1.982    -1.926     .868   .093000   .431000  -.1857000      .000      .000  
+82 4 2 45061.00 I   .106941  .001262   .427702  .001125  I -.1863567  .0002037  2.3962 0.2347  I     4.362    1.982    -1.876     .868   .096000   .430000  -.1881000      .000      .000  
+82 4 3 45062.00 I   .109031  .001262   .426961  .001125  I -.1887936  .0002037  2.4877 0.1629  I     4.912    1.982    -1.902     .868   .098000   .430000  -.1906000      .000      .000  
+82 4 4 45063.00 I   .111112  .002211   .426199  .001229  I -.1913466  .0002542  2.6227 0.1798  I     5.442    1.982    -1.976     .868   .101000   .429000  -.1930000      .000      .000  
+82 4 5 45064.00 I   .113181  .002860   .425415  .001326  I -.1940409  .0002963  2.7635 0.2270  I     5.772    1.982    -2.060     .868   .103000   .428000  -.1955000      .000      .000  
+82 4 6 45065.00 I   .115237  .002860   .424605  .001326  I -.1968630  .0003762  2.8727 0.2394  I     5.807    1.982    -2.127     .868   .105000   .427000  -.1981000      .000      .000  
+82 4 7 45066.00 I   .117279  .002860   .423766  .001326  I -.1997669  .0003762  2.9239 0.2660  I     5.636    1.982    -2.146     .868   .107000   .426000  -.2009000      .000      .000  
+82 4 8 45067.00 I   .119306  .002860   .422896  .001326  I -.2026883  .0003762  2.9076 0.2660  I     5.453    1.982    -2.084     .868   .110000   .426000  -.2038000      .000      .000  
+82 4 9 45068.00 I   .121322  .002860   .421994  .001326  I -.2055617  .0003762  2.8300 0.2249  I     5.351    1.982    -1.949     .868   .112000   .425000  -.2066000      .000      .000  
+82 410 45069.00 I   .123331  .003310   .421059  .002690  I -.2083333  .0002466  2.7075 0.2435  I     5.237    1.982    -1.814     .868   .114000   .424000  -.2093000      .000      .000  
+82 411 45070.00 I   .125337  .001441   .420090  .000690  I -.2109687  .0003094  2.5611 0.1777  I     5.011    1.982    -1.762     .868   .116000   .423000  -.2118000      .000      .000  
+82 412 45071.00 I   .127343  .001441   .419085  .000690  I -.2134548  .0002560  2.4125 0.2008  I     4.740    1.982    -1.807     .868   .118000   .422000  -.2143000      .000      .000  
+82 413 45072.00 I   .129354  .001441   .418044  .000690  I -.2158001  .0002560  2.2830 0.1821  I     4.590    1.982    -1.895     .868   .121000   .422000  -.2165000      .000      .000  
+82 414 45073.00 I   .131372  .001624   .416966  .000642  I -.2180335  .0002590  2.1916 0.1821  I     4.623    1.982    -1.987     .868   .123000   .421000  -.2187000      .000      .000  
+82 415 45074.00 I   .133400  .001624   .415850  .000642  I -.2202005  .0002590  2.1517 0.2226  I     4.795    1.982    -2.084     .868   .125000   .420000  -.2209000      .000      .000  
+82 416 45075.00 I   .135437  .001624   .414696  .000642  I -.2223560  .0003620  2.1689 0.2027  I     5.101    1.982    -2.166     .868   .127000   .419000  -.2230000      .000      .000  
+82 417 45076.00 I   .137486  .001267   .413503  .000742  I -.2245576  .0003120  2.2438 0.2389  I     5.541    1.982    -2.188     .868   .130000   .418000  -.2252000      .000      .000  
+82 418 45077.00 I   .139544  .001267   .412274  .000742  I -.2268617  .0003120  2.3729 0.2206  I     5.936    1.982    -2.151     .868   .132000   .416000  -.2274000      .000      .000  
+82 419 45078.00 I   .141609  .001267   .411007  .000742  I -.2293184  .0003120  2.5471 0.2740  I     5.998    1.982    -2.129     .868   .135000   .415000  -.2299000      .000      .000  
+82 420 45079.00 I   .143679  .000337   .409704  .000824  I -.2319647  .0004505  2.7479 0.2740  I     5.685    1.982    -2.155     .868   .137000   .414000  -.2325000      .000      .000  
+82 421 45080.00 I   .145750  .000337   .408365  .000824  I -.2348120  .0004505  2.9422 0.3166  I     5.308    1.982    -2.147     .868   .139000   .413000  -.2353000      .000      .000  
+82 422 45081.00 I   .147821  .000656   .406989  .001036  I -.2378327  .0004450  3.0872 0.3311  I     5.144    1.982    -2.031     .868   .141000   .411000  -.2383000      .000      .000  
+82 423 45082.00 I   .149889  .000799   .405577  .001111  I -.2409566  .0004853  3.1428 0.3292  I     5.065    1.982    -1.898     .868   .143000   .410000  -.2415000      .000      .000  
+82 424 45083.00 I   .151952  .000799   .404127  .001111  I -.2440824  .0004853  3.0906 0.3432  I     4.745    1.982    -1.932     .868   .145000   .408000  -.2446000      .000      .000  
+82 425 45084.00 I   .154008  .000799   .402641  .001111  I -.2471068  .0004853  2.9455 0.3016  I     4.135    1.982    -2.176     .868   .147000   .407000  -.2476000      .000      .000  
+82 426 45085.00 I   .156054  .000794   .401118  .000971  I -.2499578  .0003581  2.7536 0.3016  I     3.551    1.982    -2.449     .868   .149000   .406000  -.2504000      .000      .000  
+82 427 45086.00 I   .158087  .000794   .399556  .000971  I -.2526180  .0003581  2.5738 0.2015  I     3.295    1.982    -2.541     .868   .151000   .404000  -.2531000      .000      .000  
+82 428 45087.00 I   .160102  .001001   .397954  .000177  I -.2551261  .0001847  2.4560 0.2015  I     3.354    1.982    -2.423     .868   .153000   .403000  -.2556000      .000      .000  
+82 429 45088.00 I   .162096  .001001   .396311  .000177  I -.2575582  .0001847  2.4229 0.1306  I     3.508    1.982    -2.239     .868   .155000   .401000  -.2580000      .000      .000  
+82 430 45089.00 I   .164065  .001001   .394625  .000177  I -.2599978  .0001847  2.4676 0.1306  I     3.610    1.982    -2.129     .868   .157000   .400000  -.2604000      .000      .000  
+82 5 1 45090.00 I   .166004  .001001   .392896  .000177  I -.2625100  .0001847  2.5621 0.1125  I     3.683    1.982    -2.123     .868   .159000   .398000  -.2628000      .000      .000  
+82 5 2 45091.00 I   .167910  .001034   .391120  .001044  I -.2651262  .0001284  2.6692 0.1125  I     3.795    1.982    -2.180     .868   .161000   .397000  -.2653000      .000      .000  
+82 5 3 45092.00 I   .169780  .001034   .389297  .001044  I -.2678408  .0001284  2.7536 0.1763  I     3.901    1.982    -2.240     .868   .163000   .395000  -.2680000      .000      .000  
+82 5 4 45093.00 I   .171613  .000431   .387425  .002773  I -.2706173  .0003284  2.7896 0.1463  I     3.845    1.982    -2.244     .868   .165000   .394000  -.2706000      .000      .000  
+82 5 5 45094.00 I   .173407  .000431   .385501  .002773  I -.2733995  .0002630  2.7641 0.2104  I     3.538    1.982    -2.138     .868   .167000   .392000  -.2733000      .000      .000  
+82 5 6 45095.00 I   .175159  .000431   .383526  .002773  I -.2761253  .0002630  2.6779 0.1860  I     3.079    1.982    -1.920     .868   .169000   .390000  -.2759000      .000      .000  
+82 5 7 45096.00 I   .176870  .000431   .381499  .002773  I -.2787385  .0002630  2.5412 0.2724  I     2.657    1.982    -1.688     .868   .171000   .388000  -.2784000      .000      .000  
+82 5 8 45097.00 I   .178538  .003207   .379421  .003546  I -.2811970  .0004772  2.3723 0.2724  I     2.348    1.982    -1.583     .868   .173000   .387000  -.2807000      .000      .000  
+82 5 9 45098.00 I   .180164  .003207   .377297  .003546  I -.2834795  .0004772  2.1926 0.3236  I     2.102    1.982    -1.664     .868   .175000   .385000  -.2829000      .000      .000  
+82 510 45099.00 I   .181745  .003659   .375131  .002548  I -.2855857  .0004371  2.0233 0.3914  I     1.894    1.982    -1.848     .868   .177000   .383000  -.2849000      .000      .000  
+82 511 45100.00 I   .183283  .003659   .372928  .002548  I -.2875363  .0006205  1.8845 0.3795  I     1.747    1.982    -2.008     .868   .179000   .381000  -.2868000      .000      .000  
+82 512 45101.00 I   .184779  .003659   .370692  .002548  I -.2893706  .0006205  1.7935 0.4108  I     1.624    1.982    -2.115     .868   .181000   .379000  -.2885000      .000      .000  
+82 513 45102.00 I   .186242  .003044   .368423  .002281  I -.2911426  .0005386  1.7605 0.3681  I     1.471    1.982    -2.224     .868   .183000   .377000  -.2901000      .000      .000  
+82 514 45103.00 I   .187678  .001907   .366121  .001359  I -.2929113  .0003962  1.7867 0.3343  I     1.397    1.982    -2.327     .868   .185000   .375000  -.2918000      .000      .000  
+82 515 45104.00 I   .189092  .001907   .363786  .001359  I -.2947347  .0003962  1.8690 0.3087  I     1.589    1.982    -2.320     .868   .187000   .373000  -.2936000      .000      .000  
+82 516 45105.00 I   .190487  .001007   .361416  .001618  I -.2966654  .0004735  1.9997 0.2556  I     1.948    1.982    -2.170     .868   .189000   .371000  -.2954000      .000      .000  
+82 517 45106.00 I   .191868  .001637   .359012  .002112  I -.2987462  .0003231  2.1666 0.2866  I     2.051    1.982    -2.026     .868   .191000   .369000  -.2975000      .000      .000  
+82 518 45107.00 I   .193238  .001637   .356574  .002112  I -.3010038  .0003231  2.3489 0.2458  I     1.647    1.982    -2.047     .868   .192000   .366000  -.2997000      .000      .000  
+82 519 45108.00 I   .194605  .001510   .354105  .002059  I -.3034383  .0003704  2.5139 0.2458  I     1.008    1.982    -2.166     .868   .194000   .364000  -.3021000      .000      .000  
+82 520 45109.00 I   .195973  .001510   .351604  .002059  I -.3060123  .0003704  2.6209 0.2760  I      .566    1.982    -2.165     .868   .196000   .362000  -.3046000      .000      .000  
+82 521 45110.00 I   .197343  .001510   .349077  .002059  I -.3086493  .0004092  2.6356 0.2691  I      .336    1.982    -1.992     .868   .198000   .360000  -.3072000      .000      .000  
+82 522 45111.00 I   .198718  .001510   .346526  .002059  I -.3112500  .0003905  2.5500 0.2762  I     -.016    1.982    -1.857     .868   .200000   .357000  -.3098000      .000      .000  
+82 523 45112.00 I   .200099  .000681   .343956  .001076  I -.3137251  .0003712  2.3920 0.2694  I     -.591    1.982    -1.947     .868   .201000   .355000  -.3121000      .000      .000  
+82 524 45113.00 I   .201486  .000681   .341371  .001076  I -.3160281  .0003712  2.2164 0.2682  I    -1.049    1.982    -2.173     .868   .203000   .352000  -.3144000      .000      .000  
+82 525 45114.00 I   .202880  .000845   .338771  .000374  I -.3181723  .0003871  2.0839 0.2613  I    -1.033    1.982    -2.294     .868   .205000   .350000  -.3164000      .000      .000  
+82 526 45115.00 I   .204280  .001049   .336160  .000299  I -.3202241  .0003679  2.0358 0.2453  I     -.595    1.982    -2.234     .868   .206000   .348000  -.3184000      .000      .000  
+82 527 45116.00 I   .205687  .001049   .333541  .000299  I -.3222740  .0003015  2.0779 0.2269  I     -.118    1.982    -2.129     .868   .208000   .345000  -.3204000      .000      .000  
+82 528 45117.00 I   .207099  .001679   .330914  .000328  I -.3244012  .0002656  2.1838 0.1875  I      .080    1.982    -2.104     .868   .209000   .343000  -.3225000      .000      .000  
+82 529 45118.00 I   .208516  .001968   .328282  .000302  I -.3266486  .0002231  2.3105 0.1734  I     -.009    1.982    -2.130     .868   .211000   .340000  -.3247000      .000      .000  
+82 530 45119.00 I   .209939  .001968   .325647  .000302  I -.3290153  .0002231  2.4164 0.1578  I     -.151    1.982    -2.127     .868   .212000   .338000  -.3270000      .000      .000  
+82 531 45120.00 I   .211368  .001968   .323011  .000302  I -.3314653  .0002231  2.4738 0.1644  I     -.128    1.982    -2.086     .868   .213000   .335000  -.3294000      .000      .000  
+82 6 1 45121.00 I   .212803  .002515   .320375  .000366  I -.3339430  .0002416  2.4714 0.1644  I      .030    1.982    -2.033     .868   .214000   .332000  -.3318000      .000      .000  
+82 6 2 45122.00 I   .214243  .002515   .317740  .000366  I -.3363887  .0002416  2.4107 0.2165  I      .080    1.982    -1.932     .868   .216000   .330000  -.3342000      .000      .000  
+82 6 3 45123.00 I   .215683  .002974   .315108  .002232  I -.3387481  .0003594  2.3012 0.2165  I     -.132    1.982    -1.739     .868   .217000   .327000  -.3365000      .000      .000  
+82 6 4 45124.00 I   .217119  .002974   .312481  .002232  I -.3409797  .0003594  2.1577 0.2541  I     -.484    1.982    -1.527     .868   .218000   .324000  -.3387000      .000      .000  
+82 6 5 45125.00 I   .218546  .002974   .309859  .002232  I -.3430580  .0003594  1.9977 0.2541  I     -.716    1.982    -1.464     .868   .219000   .321000  -.3408000      .000      .000  
+82 6 6 45126.00 I   .219954  .002974   .307245  .002232  I -.3449760  .0003594  1.8403 0.2442  I     -.705    1.982    -1.624     .868   .220000   .318000  -.3427000      .000      .000  
+82 6 7 45127.00 I   .221334  .002377   .304638  .002653  I -.3467460  .0003308  1.7049 0.2442  I     -.509    1.982    -1.877     .868   .221000   .315000  -.3445000      .000      .000  
+82 6 8 45128.00 I   .222672  .002377   .302037  .002653  I -.3483989  .0003308  1.6087 0.1872  I     -.251    1.982    -2.030     .868   .222000   .312000  -.3461000      .000      .000  
+82 6 9 45129.00 I   .223952  .000704   .299440  .001543  I -.3499803  .0001753  1.5633 0.1872  I     -.066    1.982    -2.039     .868   .223000   .309000  -.3477000      .000      .000  
+82 610 45130.00 I   .225160  .000704   .296844  .001543  I -.3515439  .0001753  1.5731 0.1240  I     -.030    1.982    -2.022     .868   .224000   .306000  -.3492000      .000      .000  
+82 611 45131.00 I   .226281  .000704   .294244  .001543  I -.3531437  .0001753  1.6346 0.1240  I     -.037    1.982    -2.051     .868   .225000   .303000  -.3507000      .000      .000  
+82 612 45132.00 I   .227300  .000704   .291637  .001543  I -.3548271  .0001753  1.7382 0.0903  I      .165    1.982    -2.031     .868   .225000   .300000  -.3523000      .000      .000  
+82 613 45133.00 I   .228203  .000898   .289017  .000653  I -.3566297  .0000434  1.8708 0.0993  I      .637    1.982    -1.869     .868   .226000   .297000  -.3541000      .000      .000  
+82 614 45134.00 I   .228977  .001650   .286377  .000446  I -.3585730  .0000934  2.0165 0.0520  I     1.066    1.982    -1.662     .868   .227000   .294000  -.3559000      .000      .000  
+82 615 45135.00 I   .229609  .001409   .283712  .000369  I -.3606600  .0000946  2.1541 0.0617  I     1.111     .329    -1.606     .211   .227000   .291000  -.3579000      .000      .000  
+82 616 45136.00 I   .230087  .000999   .281016  .000910  I -.3628686  .0000806  2.2541 0.0619  I      .844     .329    -1.717     .211   .228000   .288000  -.3600000      .000      .000  
+82 617 45137.00 I   .230396  .001374   .278281  .000807  I -.3651449  .0000799  2.2844 0.0530  I      .631     .217    -1.788     .868   .228000   .284000  -.3620000      .000      .000  
+82 618 45138.00 I   .230535  .001074   .275502  .000751  I -.3674097  .0000688  2.2317 0.0531  I      .622     .217    -1.683     .868   .229000   .281000  -.3642000      .000      .000  
+82 619 45139.00 I   .230552  .001067   .272663  .000766  I -.3695846  .0000699  2.1078 0.0490  I      .644     .548    -1.526     .235   .229000   .278000  -.3663000      .000      .000  
+82 620 45140.00 I   .230505  .001067   .269756  .000766  I -.3716098  .0000699  1.9373 0.0476  I      .590     .862    -1.512     .239   .229000   .275000  -.3682000      .000      .000  
+82 621 45141.00 I   .230433  .000930   .266803  .000796  I -.3734581  .0000646  1.7634 0.0473  I      .653     .892    -1.599     .240   .230000   .272000  -.3699000      .000      .000  
+82 622 45142.00 I   .230327  .000956   .263830  .000753  I -.3751547  .0000636  1.6437 0.0439  I     1.058     .892    -1.570     .240   .230000   .268000  -.3716000      .000      .000  
+82 623 45143.00 I   .230183  .001111   .260847  .000596  I -.3767764  .0000594  1.6167 0.0417  I     1.797    1.064    -1.400     .288   .231000   .265000  -.3732000      .000      .000  
+82 624 45144.00 I   .230002  .000615   .257860  .000830  I -.3784170  .0000541  1.6763 0.0454  I     2.571    1.064    -1.255     .288   .231000   .262000  -.3748000      .000      .000  
+82 625 45145.00 I   .229786  .000436   .254873  .000890  I -.3801438  .0000686  1.7802 0.0580  I     3.028    1.239    -1.219     .248   .231000   .259000  -.3766000      .000      .000  
+82 626 45146.00 I   .229539  .001290   .251890  .002389  I -.3819751  .0001025  1.8771 0.0617  I     3.035    1.982    -1.165     .868   .231000   .255000  -.3784000      .000      .000  
+82 627 45147.00 I   .229263  .001290   .248915  .002389  I -.3838827  .0001025  1.9280 0.0797  I     2.772    1.982     -.945     .868   .231000   .252000  -.3804000      .000      .000  
+82 628 45148.00 I   .228962  .001214   .245950  .002294  I -.3858102  .0001222  1.9160 0.0797  I     2.601    1.982     -.617     .868   .231000   .248000  -.3824000      .000      .000  
+82 629 45149.00 I   .228635  .001214   .242994  .002294  I -.3876947  .0001222  1.8438 0.0892  I     2.729    1.982     -.363     .868   .231000   .245000  -.3843000      .000      .000  
+82 630 45150.00 I   .228282  .000158   .240048  .000278  I -.3894825  .0001300  1.7257 0.0892  I     2.979    1.982     -.237     .868   .231000   .242000  -.3860000      .000      .000  
+82 7 1 45151.00 I   .227903  .000158   .237109  .000278  I  .6088635  .0001300  1.5789 0.0919  I     3.013    1.982     -.130     .868   .231000   .239000   .6123000      .000      .000  
+82 7 2 45152.00 I   .227500  .000158   .234178  .000278  I  .6073635  .0001300  1.4206 0.0919  I     2.769    1.982      .029     .868   .230000   .235000   .6110000      .000      .000  
+82 7 3 45153.00 I   .227071  .000158   .231255  .000278  I  .6060205  .0001300  1.2676 0.0845  I     2.524    1.982      .152     .868   .230000   .232000   .6097000      .000      .000  
+82 7 4 45154.00 I   .226617  .001194   .228339  .001166  I  .6048210  .0001081  1.1363 0.0845  I     2.531    1.982      .134     .868   .230000   .229000   .6085000      .000      .000  
+82 7 5 45155.00 I   .226138  .001194   .225430  .001166  I  .6037356  .0001081  1.0419 0.0795  I     2.763    1.982      .036     .868   .230000   .226000   .6074000      .000      .000  
+82 7 6 45156.00 I   .225636  .001673   .222527  .001641  I  .6027209  .0001165  0.9966 0.0763  I     3.038    1.982      .032     .868   .229000   .223000   .6063000      .000      .000  
+82 7 7 45157.00 I   .225110  .001580   .219631  .001335  I  .6017239  .0001077  1.0069 0.0793  I     3.216    1.982      .196     .868   .229000   .220000   .6053000      .000      .000  
+82 7 8 45158.00 I   .224558  .001580   .216742  .001335  I  .6006889  .0001077  1.0717 0.0762  I     3.242    1.982      .421     .868   .228000   .217000   .6042000      .000      .000  
+82 7 9 45159.00 I   .223980  .001580   .213861  .001335  I  .5995655  .0001077  1.1814 0.0772  I     3.147    1.982      .577     .868   .228000   .214000   .6031000      .000      .000  
+82 710 45160.00 I   .223370  .001116   .210992  .000785  I  .5983163  .0001105  1.3204 0.0772  I     3.069    1.982      .674     .868   .227000   .211000   .6018000      .000      .000  
+82 711 45161.00 I   .222726  .001116   .208136  .000785  I  .5969212  .0001105  1.4699 0.0781  I     3.146    1.982      .810     .868   .227000   .208000   .6003000      .000      .000  
+82 712 45162.00 I   .222040  .001116   .205296  .000785  I  .5953796  .0001105  1.6101 0.0764  I     3.308    1.982     1.000     .868   .226000   .206000   .5988000      .000      .000  
+82 713 45163.00 I   .221308  .002457   .202475  .001012  I  .5937112  .0001055  1.7196 0.0764  I     3.322    1.982     1.143     .868   .226000   .203000   .5971000      .000      .000  
+82 714 45164.00 I   .220525  .002457   .199677  .001012  I  .5919581  .0001055  1.7759 0.1431  I     3.066    1.982     1.174     .868   .225000   .200000   .5953000      .000      .000  
+82 715 45165.00 I   .219686  .002178   .196902  .000868  I  .5901832  .0002660  1.7606 0.2385  I     2.652    1.982     1.165     .868   .224000   .197000   .5934000      .000      .000  
+82 716 45166.00 I   .218788  .002640   .194154  .000974  I  .5884624  .0004651  1.6687 0.2679  I     2.252    1.982     1.201     .868   .223000   .194000   .5917000      .000      .000  
+82 717 45167.00 I   .217832  .002640   .191432  .000974  I  .5868650  .0004651  1.5193 0.3289  I     1.939    1.982     1.243     .868   .223000   .192000   .5900000      .000      .000  
+82 718 45168.00 I   .216819  .002640   .188738  .000974  I  .5854280  .0004651  1.3573 0.3300  I     1.762    1.982     1.202     .868   .222000   .189000   .5885000      .000      .000  
+82 719 45169.00 I   .215754  .001276   .186071  .000411  I  .5841359  .0004682  1.2389 0.3300  I     1.809    1.982     1.124     .868   .221000   .186000   .5872000      .000      .000  
+82 720 45170.00 I   .214638  .001276   .183431  .000411  I  .5829209  .0004682  1.2083 0.3101  I     2.115    1.982     1.140     .868   .220000   .183000   .5859000      .000      .000  
+82 721 45171.00 I   .213479  .000775   .180819  .000252  I  .5816866  .0004068  1.2756 0.2523  I     2.576    1.982     1.251     .868   .219000   .181000   .5846000      .000      .000  
+82 722 45172.00 I   .212281  .000775   .178235  .000252  I  .5803469  .0001881  1.4112 0.2241  I     3.015    1.982     1.289     .868   .219000   .178000   .5833000      .000      .000  
+82 723 45173.00 I   .211046  .000775   .175677  .000252  I  .5788593  .0001881  1.5614 0.1330  I     3.258    1.982     1.167     .868   .218000   .176000   .5817000      .000      .000  
+82 724 45174.00 I   .209779  .000775   .173145  .000252  I  .5772372  .0001881  1.6723 0.1353  I     3.166    1.982     1.055     .868   .217000   .173000   .5801000      .000      .000  
+82 725 45175.00 I   .208482  .000244   .170639  .000799  I  .5755388  .0001944  1.7107 0.1353  I     2.752    1.982     1.168     .868   .216000   .170000   .5783000      .000      .000  
+82 726 45176.00 I   .207157  .000244   .168158  .000799  I  .5738419  .0001944  1.6706 0.1711  I     2.278    1.982     1.463     .868   .215000   .168000   .5765000      .000      .000  
+82 727 45177.00 I   .205807  .001130   .165701  .000804  I  .5722188  .0002815  1.5670 0.1711  I     2.060    1.982     1.665     .868   .213000   .165000   .5749000      .000      .000  
+82 728 45178.00 I   .204434  .001130   .163268  .000804  I  .5707209  .0002815  1.4244 0.1991  I     2.120    1.982     1.610     .868   .212000   .163000   .5733000      .000      .000  
+82 729 45179.00 I   .203041  .001130   .160858  .000804  I  .5693752  .0002815  1.2662 0.1991  I     2.177    1.982     1.421     .868   .211000   .160000   .5719000      .000      .000  
+82 730 45180.00 I   .201628  .001130   .158467  .000804  I  .5681868  .0002815  1.1129 0.2433  I     2.038    1.982     1.305     .868   .210000   .157000   .5706000      .000      .000  
+82 731 45181.00 I   .200198  .001716   .156095  .001069  I  .5671419  .0003969  0.9819 0.2433  I     1.831    1.982     1.304     .868   .209000   .155000   .5695000      .000      .000  
+82 8 1 45182.00 I   .198750  .001716   .153738  .001069  I  .5662108  .0003969  0.8876 0.2885  I     1.765    1.982     1.300     .868   .207000   .152000   .5685000      .000      .000  
+82 8 2 45183.00 I   .197283  .001830   .151396  .001507  I  .5653507  .0004187  0.8414 0.2538  I     1.839    1.982     1.224     .868   .206000   .150000   .5675000      .000      .000  
+82 8 3 45184.00 I   .195796  .001531   .149065  .001119  I  .5645097  .0003165  0.8501 0.2624  I     1.923    1.982     1.147     .868   .205000   .147000   .5666000      .000      .000  
+82 8 4 45185.00 I   .194287  .001531   .146746  .001119  I  .5636315  .0003165  0.9158 0.2238  I     1.976    1.982     1.174     .868   .203000   .145000   .5656000      .000      .000  
+82 8 5 45186.00 I   .192753  .001531   .144436  .001119  I  .5626608  .0003165  1.0333 0.1965  I     2.028    1.982     1.306     .868   .202000   .142000   .5646000      .000      .000  
+82 8 6 45187.00 I   .191188  .001198   .142138  .000404  I  .5615525  .0002331  1.1881 0.1965  I     2.047    1.982     1.448     .868   .200000   .140000   .5634000      .000      .000  
+82 8 7 45188.00 I   .189587  .001198   .139850  .000404  I  .5602790  .0002331  1.3598 0.2013  I     1.981    1.982     1.514     .868   .199000   .137000   .5620000      .000      .000  
+82 8 8 45189.00 I   .187942  .001332   .137574  .000538  I  .5588353  .0003283  1.5241 0.2255  I     1.883    1.982     1.505     .868   .197000   .135000   .5605000      .000      .000  
+82 8 9 45190.00 I   .186248  .001411   .135311  .000563  I  .5572413  .0003862  1.6567 0.2534  I     1.849    1.982     1.474     .868   .195000   .133000   .5589000      .000      .000  
+82 810 45191.00 I   .184499  .001411   .133061  .000563  I  .5555391  .0003862  1.7378 0.4669  I     1.848    1.982     1.461     .868   .193000   .130000   .5572000      .000      .000  
+82 811 45192.00 I   .182691  .001985   .130826  .000497  I  .5537867  .0008502  1.7559 0.5414  I     1.724    1.982     1.462     .868   .191000   .128000   .5556000      .000      .000  
+82 812 45193.00 I   .180820  .002268   .128606  .000570  I  .5520488  .0010115  1.7094 0.6574  I     1.381    1.982     1.448     .868   .189000   .125000   .5538000      .000      .000  
+82 813 45194.00 I   .178885  .002268   .126404  .000570  I  .5503848  .0010029  1.6122 0.7031  I      .904    1.982     1.384     .868   .187000   .123000   .5522000      .000      .000  
+82 814 45195.00 I   .176885  .001987   .124221  .000267  I  .5488306  .0009770  1.4965 0.7001  I      .507    1.982     1.249     .868   .185000   .121000   .5506000      .000      .000  
+82 815 45196.00 I   .174821  .001987   .122061  .000267  I  .5473828  .0009770  1.4078 0.6908  I      .384    1.982     1.071     .868   .182000   .119000   .5492000      .000      .000  
+82 816 45197.00 I   .172698  .001987   .119925  .000267  I  .5459912  .0009770  1.3905 0.5194  I      .570    1.982      .959     .868   .180000   .116000   .5479000      .000      .000  
+82 817 45198.00 I   .170519  .000566   .117816  .000723  I  .5445700  .0003531  1.4687 0.5194  I      .904    1.982     1.019     .868   .177000   .114000   .5464000      .000      .000  
+82 818 45199.00 I   .168290  .000566   .115737  .000723  I  .5430252  .0003531  1.6326 0.2296  I     1.170    1.982     1.205     .868   .175000   .112000   .5448000      .000      .000  
+82 819 45200.00 I   .166012  .000566   .113689  .000723  I  .5412908  .0002937  1.8386 0.2226  I     1.277    1.982     1.320     .868   .172000   .110000   .5430000      .000      .000  
+82 820 45201.00 I   .163690  .000762   .111677  .001006  I  .5393529  .0002710  2.0298 0.1754  I     1.264    1.982     1.234     .868   .169000   .108000   .5409000      .000      .000  
+82 821 45202.00 I   .161328  .001474   .109701  .000929  I  .5372528  .0001917  2.1563 0.1660  I     1.135    1.982     1.063     .868   .167000   .106000   .5386000      .000      .000  
+82 822 45203.00 I   .158931  .001474   .107765  .000929  I  .5350698  .0001917  2.1943 0.0959  I      .830    1.982     1.033     .868   .164000   .104000   .5363000      .000      .000  
+82 823 45204.00 I   .156504  .001940   .105868  .000846  I  .5328919  .0000039  2.1491 0.1284  I      .396    1.982     1.178     .868   .161000   .102000   .5340000      .000      .000  
+82 824 45205.00 I   .154050  .001642   .104013  .000741  I  .5307914  .0001708  2.0446 0.0854  I      .036    1.982     1.281     .868   .158000   .100000   .5318000      .000      .000  
+82 825 45206.00 I   .151574  .001642   .102200  .000741  I  .5288123  .0001708  1.9112 0.1152  I     -.097    1.982     1.151     .868   .155000   .098000   .5297000      .000      .000  
+82 826 45207.00 I   .149075  .001458   .100430  .000762  I  .5269696  .0001545  1.7758 0.1274  I     -.065    1.982      .861     .868   .153000   .097000   .5277000      .000      .000  
+82 827 45208.00 I   .146556  .001144   .098701  .000715  I  .5252541  .0001892  1.6601 0.1221  I     -.017    1.982      .643     .868   .150000   .095000   .5259000      .000      .000  
+82 828 45209.00 I   .144019  .001144   .097016  .000715  I  .5236373  .0001892  1.5808 0.1338  I      .000    1.982      .609     .868   .147000   .093000   .5243000      .000      .000  
+82 829 45210.00 I   .141467  .001144   .095372  .000715  I  .5220765  .0001892  1.5496 0.1378  I      .012    1.982      .649     .868   .144000   .091000   .5228000      .000      .000  
+82 830 45211.00 I   .138905  .001461   .093769  .000676  I  .5205198  .0002005  1.5733 0.1378  I     -.004    1.982      .607     .868   .141000   .090000   .5213000      .000      .000  
+82 831 45212.00 I   .136334  .001461   .092209  .000676  I  .5189112  .0002005  1.6532 0.2503  I     -.075    1.982      .462     .868   .139000   .088000   .5198000      .000      .000  
+82 9 1 45213.00 I   .133756  .002642   .090691  .000457  I  .5171961  .0004587  1.7851 0.2503  I     -.127    1.982      .337     .868   .136000   .087000   .5182000      .000      .000  
+82 9 2 45214.00 I   .131172  .002642   .089216  .000457  I  .5153275  .0004587  1.9577 0.3243  I     -.065    1.982      .355     .868   .133000   .085000   .5165000      .000      .000  
+82 9 3 45215.00 I   .128584  .002642   .087785  .000457  I  .5132734  .0004587  2.1523 0.3243  I      .056    1.982      .510     .868   .130000   .083000   .5145000      .000      .000  
+82 9 4 45216.00 I   .125988  .002642   .086396  .000457  I  .5110245  .0004587  2.3423 0.3803  I      .077    1.982      .668     .868   .127000   .082000   .5124000      .000      .000  
+82 9 5 45217.00 I   .123382  .004241   .085050  .000935  I  .5086007  .0006068  2.4967 0.3803  I     -.056    1.982      .683     .868   .124000   .080000   .5101000      .000      .000  
+82 9 6 45218.00 I   .120758  .004241   .083746  .000935  I  .5060521  .0006068  2.5881 0.4333  I     -.235    1.982      .538     .868   .121000   .079000   .5077000      .000      .000  
+82 9 7 45219.00 I   .118109  .005028   .082484  .001266  I  .5034506  .0006186  2.6014 0.4044  I     -.366    1.982      .350     .868   .118000   .077000   .5052000      .000      .000  
+82 9 8 45220.00 I   .115426  .006145   .081262  .001327  I  .5008748  .0005347  2.5384 0.4088  I     -.506    1.982      .246     .868   .115000   .076000   .5027000      .000      .000  
+82 9 9 45221.00 I   .112698  .006145   .080080  .001327  I  .4983934  .0005347  2.4166 0.3781  I     -.771    1.982      .237     .868   .112000   .074000   .5003000      .000      .000  
+82 910 45222.00 I   .109909  .006145   .078941  .001327  I  .4960501  .0005347  2.2691 0.3644  I    -1.150    1.982      .232     .868   .108000   .073000   .4980000      .000      .000  
+82 911 45223.00 I   .107038  .008720   .077844  .000983  I  .4938502  .0004952  2.1365 0.3644  I    -1.461    1.982      .159     .868   .105000   .071000   .4959000      .000      .000  
+82 912 45224.00 I   .104060  .008720   .076792  .000983  I  .4917594  .0004952  2.0570 0.3502  I    -1.508    1.982      .046     .868   .102000   .070000   .4939000      .000      .000  
+82 913 45225.00 I   .100941  .008720   .075789  .000983  I  .4897097  .0004952  2.0570 0.3808  I    -1.266    1.982     -.001     .868   .099000   .069000   .4919000      .000      .000  
+82 914 45226.00 I   .097653  .008554   .074836  .000519  I  .4876187  .0005787  2.1373 0.3808  I     -.933    1.982      .100     .868   .095000   .068000   .4899000      .000      .000  
+82 915 45227.00 I   .094171  .008554   .073937  .000519  I  .4854146  .0005787  2.2792 0.4202  I     -.758    1.982      .311     .868   .092000   .067000   .4877000      .000      .000  
+82 916 45228.00 I   .090519  .008190   .073093  .000848  I  .4830529  .0006094  2.4432 0.4135  I     -.827    1.982      .484     .868   .088000   .066000   .4854000      .000      .000  
+82 917 45229.00 I   .086735  .008106   .072309  .001035  I  .4805389  .0005909  2.5749 0.6037  I    -1.028    1.982      .493     .868   .085000   .065000   .4828000      .000      .000  
+82 918 45230.00 I   .082848  .005251   .071586  .001035  I  .4779277  .0010424  2.6327 0.5991  I    -1.222    1.982      .368     .868   .082000   .064000   .4802000      .000      .000  
+82 919 45231.00 I   .078886  .005251   .070926  .001035  I  .4753023  .0010424  2.6039 0.6181  I    -1.398    1.982      .256     .868   .078000   .064000   .4775000      .000      .000  
+82 920 45232.00 I   .074873  .004731   .070329  .001050  I  .4727448  .0006647  2.5002 0.6181  I    -1.624    1.982      .231     .868   .075000   .063000   .4750000      .000      .000  
+82 921 45233.00 I   .070826  .004731   .069797  .001050  I  .4703178  .0006647  2.3486 0.3553  I    -1.892    1.982      .198     .868   .071000   .063000   .4725000      .000      .000  
+82 922 45234.00 I   .066765  .003617   .069330  .000592  I  .4680526  .0002512  2.1819 0.3553  I    -2.087    1.982      .037     .868   .068000   .062000   .4702000      .000      .000  
+82 923 45235.00 I   .062704  .003617   .068926  .000592  I  .4659500  .0002512  2.0274 0.1737  I    -2.092    1.982     -.209     .868   .064000   .062000   .4680000      .000      .000  
+82 924 45236.00 I   .058656  .003617   .068587  .000592  I  .4639867  .0002401  1.9064 0.1737  I    -1.916    1.982     -.369     .868   .061000   .062000   .4660000      .000      .000  
+82 925 45237.00 I   .054630  .003617   .068310  .000592  I  .4621210  .0002401  1.8340 0.1633  I    -1.687    1.982     -.357     .868   .057000   .061000   .4640000      .000      .000  
+82 926 45238.00 I   .050631  .002748   .068095  .000548  I  .4603001  .0002213  1.8174 0.1633  I    -1.556    1.982     -.277     .868   .054000   .061000   .4622000      .000      .000  
+82 927 45239.00 I   .046665  .002748   .067940  .000548  I  .4584668  .0002213  1.8588 0.1423  I    -1.582    1.982     -.292     .868   .050000   .061000   .4602000      .000      .000  
+82 928 45240.00 I   .042735  .002986   .067845  .000701  I  .4565644  .0001789  1.9544 0.1335  I    -1.693    1.982     -.439     .868   .046000   .061000   .4583000      .000      .000  
+82 929 45241.00 I   .038844  .002146   .067806  .000721  I  .4545431  .0001493  2.0948 0.1047  I    -1.764    1.982     -.591     .868   .043000   .061000   .4562000      .000      .000  
+82 930 45242.00 I   .034995  .002146   .067825  .000721  I  .4523646  .0001088  2.2659 0.1299  I    -1.750    1.982     -.588     .868   .039000   .060000   .4539000      .000      .000  
+8210 1 45243.00 I   .031186  .002146   .067899  .000721  I  .4500084  .0002126  2.4459 0.1095  I    -1.725    1.982     -.385     .868   .036000   .060000   .4514000      .000      .000  
+8210 2 45244.00 I   .027414  .000673   .068028  .000997  I  .4474796  .0001901  2.6055 0.1426  I    -1.793    1.982     -.107     .868   .032000   .060000   .4488000      .000      .000  
+8210 3 45245.00 I   .023680  .000673   .068212  .000997  I  .4448154  .0001901  2.7110 0.1344  I    -1.973    1.982      .036     .868   .028000   .060000   .4461000      .000      .000  
+8210 4 45246.00 I   .019981  .000673   .068449  .000997  I  .4420846  .0001901  2.7356 0.1335  I    -2.195    1.982     -.075     .868   .025000   .060000   .4433000      .000      .000  
+8210 5 45247.00 I   .016317  .000606   .068737  .000859  I  .4393739  .0001875  2.6711 0.1335  I    -2.395    1.982     -.355     .868   .021000   .061000   .4406000      .000      .000  
+8210 6 45248.00 I   .012688  .000606   .069075  .000859  I  .4367670  .0001875  2.5329 0.1024  I    -2.569    1.982     -.591     .868   .018000   .061000   .4379000      .000      .000  
+8210 7 45249.00 I   .009093  .001205   .069459  .000726  I  .4343200  .0000822  2.3592 0.0939  I    -2.756    1.982     -.641     .868   .014000   .061000   .4354000      .000      .000  
+8210 8 45250.00 I   .005535  .001369   .069887  .000268  I  .4320443  .0000090  2.1985 0.0413  I    -2.958    1.982     -.535     .868   .010000   .062000   .4331000      .000      .000  
+8210 9 45251.00 I   .002014  .001369   .070356  .000268  I  .4299041  .0000090  2.0946 0.0064  I    -3.107    1.982     -.404     .868   .007000   .062000   .4310000      .000      .000  
+821010 45252.00 I  -.001469  .001369   .070862  .000268  I  .4278270  .0000090  2.0750 0.0510  I    -3.109    1.982     -.327     .868   .003000   .063000   .4288000      .000      .000  
+821011 45253.00 I  -.004914  .001869   .071405  .000349  I  .4257247  .0001017  2.1435 0.0510  I    -2.946    1.982     -.287     .868   .000000   .063000   .4267000      .000      .000  
+821012 45254.00 I  -.008321  .001869   .071980  .000349  I  .4235175  .0001017  2.2795 0.0878  I    -2.724    1.982     -.228     .868  -.004000   .064000   .4245000      .000      .000  
+821013 45255.00 I  -.011694  .002787   .072585  .000965  I  .4211563  .0001431  2.4439 0.0878  I    -2.612    1.982     -.132     .868  -.008000   .065000   .4221000      .000      .000  
+821014 45256.00 I  -.015035  .002787   .073219  .000965  I  .4186360  .0001431  2.5896 0.1012  I    -2.717    1.982     -.039     .868  -.011000   .066000   .4196000      .000      .000  
+821015 45257.00 I  -.018348  .002787   .073880  .000965  I  .4159972  .0001431  2.6749 0.0759  I    -2.995    1.982      .004     .868  -.015000   .067000   .4169000      .000      .000  
+821016 45258.00 I  -.021639  .000799   .074564  .000314  I  .4133142  .0000504  2.6761 0.0751  I    -3.294    1.982     -.010     .868  -.018000   .068000   .4142000      .000      .000  
+821017 45259.00 I  -.024914  .000893   .075271  .000788  I  .4106733  .0000454  2.5925 0.0339  I    -3.496     .841     -.038     .224  -.022000   .069000   .4115000      .000      .000  
+821018 45260.00 I  -.028185  .000893   .076001  .000788  I  .4081512  .0000454  2.4429 0.0299  I    -3.609     .841     -.063     .224  -.025000   .070000   .4089000      .000      .000  
+821019 45261.00 I  -.031465  .000657   .076753  .000749  I  .4057997  .0000390  2.2568 0.0299  I    -3.720     .841     -.132     .224  -.029000   .072000   .4065000      .000      .000  
+821020 45262.00 I  -.034762  .000697   .077527  .000798  I  .4036387  .0000388  2.0675 0.0275  I    -3.832     .841     -.279     .224  -.032000   .073000   .4042000      .000      .000  
+821021 45263.00 I  -.038074  .000697   .078327  .000798  I  .4016561  .0000388  1.9040 0.0274  I    -3.830     .841     -.435     .224  -.036000   .075000   .4022000      .000      .000  
+821022 45264.00 I  -.041396  .000697   .079157  .000798  I  .3998154  .0000388  1.7863 0.0709  I    -3.641     .841     -.470     .224  -.039000   .076000   .4002000      .000      .000  
+821023 45265.00 I  -.044721  .001303   .080019  .002444  I  .3980639  .0001364  1.7273 0.0709  I    -3.387    1.982     -.352     .868  -.042000   .078000   .3984000      .000      .000  
+821024 45266.00 I  -.048047  .001303   .080921  .002444  I  .3963395  .0001364  1.7322 0.0964  I    -3.281    1.982     -.199     .868  -.046000   .079000   .3965000      .000      .000  
+821025 45267.00 I  -.051372  .001303   .081867  .002444  I  .3945793  .0001364  1.7978 0.1180  I    -3.367    1.982     -.142     .868  -.049000   .081000   .3947000      .000      .000  
+821026 45268.00 I  -.054691  .001285   .082863  .002297  I  .3927267  .0001927  1.9150 0.1180  I    -3.488    1.982     -.180     .868  -.053000   .082000   .3927000      .000      .000  
+821027 45269.00 I  -.058002  .001285   .083912  .002297  I  .3907363  .0001927  2.0711 0.1277  I    -3.532    1.982     -.197     .868  -.056000   .084000   .3906000      .000      .000  
+821028 45270.00 I  -.061300  .001192   .085016  .002031  I  .3885770  .0001676  2.2498 0.1236  I    -3.589    1.982     -.089     .868  -.059000   .086000   .3884000      .000      .000  
+821029 45271.00 I  -.064579  .001231   .086176  .001103  I  .3862366  .0001548  2.4289 0.1141  I    -3.792    1.982      .167     .868  -.063000   .088000   .3860000      .000      .000  
+821030 45272.00 I  -.067838  .001231   .087394  .001103  I  .3837292  .0001548  2.5780 0.1095  I    -4.107    1.982      .510     .868  -.066000   .090000   .3834000      .000      .000  
+821031 45273.00 I  -.071075  .001231   .088669  .001103  I  .3811019  .0001548  2.6631 0.1458  I    -4.388    1.982      .810     .868  -.070000   .092000   .3807000      .000      .000  
+8211 1 45274.00 I  -.074288  .000701   .090002  .000960  I  .3784328  .0002472  2.6590 0.1458  I    -4.575    1.982      .915     .868  -.073000   .094000   .3780000      .000      .000  
+8211 2 45275.00 I  -.077476  .000701   .091392  .000960  I  .3758140  .0002472  2.5648 0.2268  I    -4.717    1.982      .790     .868  -.076000   .096000   .3754000      .000      .000  
+8211 3 45276.00 I  -.080641  .000628   .092837  .000722  I  .3733233  .0003804  2.4102 0.1895  I    -4.839    1.982      .589     .868  -.080000   .097000   .3729000      .000      .000  
+8211 4 45277.00 I  -.083781  .000628   .094337  .000722  I  .3709964  .0002872  2.2472 0.2383  I    -4.908    1.982      .543     .868  -.083000   .099000   .3706000      .000      .000  
+8211 5 45278.00 I  -.086897  .000628   .095891  .000722  I  .3688131  .0002872  2.1316 0.2206  I    -4.922    1.982      .748     .868  -.087000   .100000   .3685000      .000      .000  
+8211 6 45279.00 I  -.089988  .000917   .097496  .000589  I  .3667045  .0003350  2.1021 0.2207  I    -4.938    1.982     1.082     .868  -.090000   .102000   .3663000      .000      .000  
+8211 7 45280.00 I  -.093053  .001118   .099153  .000717  I  .3645773  .0003351  2.1674 0.2249  I    -4.983    1.982     1.351     .868  -.093000   .104000   .3642000      .000      .000  
+8211 8 45281.00 I  -.096090  .001118   .100860  .000717  I  .3623449  .0003003  2.3073 0.2110  I    -5.018    1.982     1.471     .868  -.097000   .105000   .3619000      .000      .000  
+8211 9 45282.00 I  -.099097  .001318   .102619  .000016  I  .3599507  .0002564  2.4834 0.2041  I    -5.008    1.982     1.494     .868  -.100000   .107000   .3594000      .000      .000  
+821110 45283.00 I  -.102073  .001950   .104429  .001924  I  .3573813  .0002764  2.6501 0.1885  I    -4.993    1.982     1.506     .868  -.104000   .108000   .3568000      .000      .000  
+821111 45284.00 I  -.105017  .001950   .106290  .001924  I  .3546666  .0002764  2.7686 0.1605  I    -5.075    1.982     1.546     .868  -.107000   .110000   .3541000      .000      .000  
+821112 45285.00 I  -.107930  .002422   .108203  .002721  I  .3518680  .0001631  2.8154 0.1605  I    -5.314    1.982     1.621     .868  -.110000   .112000   .3513000      .000      .000  
+821113 45286.00 I  -.110814  .002422   .110166  .002721  I  .3490618  .0001631  2.7843 0.1205  I    -5.654    1.982     1.740     .868  -.114000   .114000   .3485000      .000      .000  
+821114 45287.00 I  -.113671  .002190   .112177  .002052  I  .3463220  .0001774  2.6856 0.1205  I    -5.943    1.982     1.898     .868  -.117000   .116000   .3457000      .000      .000  
+821115 45288.00 I  -.116507  .002190   .114233  .002052  I  .3437057  .0001774  2.5416 0.1276  I    -6.068    1.982     2.039     .868  -.121000   .118000   .3431000      .000      .000  
+821116 45289.00 I  -.119327  .002593   .116329  .000879  I  .3412446  .0001834  2.3800 0.1276  I    -6.049    1.982     2.077     .868  -.124000   .120000   .3407000      .000      .000  
+821117 45290.00 I  -.122137  .002593   .118463  .000879  I  .3389427  .0001834  2.2272 0.1485  I    -5.965    1.982     1.994     .868  -.127000   .122000   .3384000      .000      .000  
+821118 45291.00 I  -.124937  .002223   .120632  .002259  I  .3367799  .0002336  2.1052 0.1485  I    -5.818    1.982     1.901     .868  -.130000   .124000   .3362000      .000      .000  
+821119 45292.00 I  -.127729  .002223   .122834  .002259  I  .3347163  .0002336  2.0312 0.1791  I    -5.576    1.982     1.941     .868  -.134000   .126000   .3342000      .000      .000  
+821120 45293.00 I  -.130510  .002356   .125067  .002673  I  .3326984  .0002716  2.0146 0.1791  I    -5.332    1.982     2.130     .868  -.137000   .128000   .3322000      .000      .000  
+821121 45294.00 I  -.133273  .002356   .127330  .002673  I  .3306678  .0002716  2.0560 0.1963  I    -5.247    1.982     2.332     .868  -.140000   .130000   .3302000      .000      .000  
+821122 45295.00 I  -.136016  .002729   .129623  .002623  I  .3285691  .0002835  2.1491 0.1781  I    -5.301    1.982     2.436     .868  -.143000   .132000   .3281000      .000      .000  
+821123 45296.00 I  -.138730  .002729   .131948  .002623  I  .3263564  .0002306  2.2816 0.1609  I    -5.281    1.982     2.475     .868  -.146000   .135000   .3259000      .000      .000  
+821124 45297.00 I  -.141410  .003676   .134311  .000025  I  .3239977  .0001524  2.4386 0.1382  I    -5.094    1.982     2.547     .868  -.150000   .137000   .3236000      .000      .000  
+821125 45298.00 I  -.144048  .003676   .136713  .000025  I  .3214765  .0001524  2.6035 0.1123  I    -4.936    1.982     2.672     .868  -.153000   .140000   .3211000      .000      .000  
+821126 45299.00 I  -.146643  .003676   .139159  .000025  I  .3187951  .0001650  2.7550 0.1092  I    -5.003    1.982     2.816     .868  -.156000   .142000   .3184000      .000      .000  
+821127 45300.00 I  -.149194  .002929   .141652  .001571  I  .3159804  .0001564  2.8648 0.1199  I    -5.185    1.982     3.002     .868  -.159000   .144000   .3156000      .000      .000  
+821128 45301.00 I  -.151702  .001908   .144196  .002222  I  .3130895  .0001739  2.9026 0.1197  I    -5.231    1.982     3.272     .868  -.162000   .147000   .3128000      .000      .000  
+821129 45302.00 I  -.154167  .001908   .146794  .002222  I  .3102055  .0001813  2.8495 0.1310  I    -5.108    1.982     3.537     .868  -.165000   .149000   .3099000      .000      .000  
+821130 45303.00 I  -.156589  .001536   .149450  .001790  I  .3074182  .0001960  2.7133 0.1335  I    -4.961    1.982     3.616     .868  -.168000   .152000   .3071000      .000      .000  
+8212 1 45304.00 I  -.158966  .001536   .152166  .001790  I  .3047930  .0001960  2.5347 0.1577  I    -4.801    1.982     3.471     .868  -.171000   .154000   .3045000      .000      .000  
+8212 2 45305.00 I  -.161296  .001536   .154943  .001790  I  .3023427  .0002472  2.3745 0.1681  I    -4.454    1.982     3.306     .868  -.173000   .157000   .3021000      .000      .000  
+8212 3 45306.00 I  -.163575  .001039   .157781  .001214  I  .3000190  .0002732  2.2891 0.1867  I    -3.859    1.982     3.343     .868  -.175000   .159000   .2997000      .000      .000  
+8212 4 45307.00 I  -.165800  .001039   .160681  .001214  I  .2977304  .0002799  2.3058 0.1827  I    -3.200    1.982     3.557     .868  -.177000   .162000   .2974000      .000      .000  
+8212 5 45308.00 I  -.167968  .000889   .163642  .000878  I  .2953770  .0002426  2.4138 0.1816  I    -2.684    1.982     3.729     .868  -.179000   .164000   .2950000      .000      .000  
+8212 6 45309.00 I  -.170080  .000513   .166663  .001080  I  .2928865  .0002316  2.5707 0.1677  I    -2.326    1.982     3.721     .868  -.181000   .167000   .2925000      .000      .000  
+8212 7 45310.00 I  -.172133  .000513   .169742  .001080  I  .2902369  .0002316  2.7237 0.1357  I    -2.005    1.982     3.607     .868  -.183000   .170000   .2899000      .000      .000  
+8212 8 45311.00 I  -.174126  .000513   .172880  .001080  I  .2874545  .0001413  2.8304 0.1342  I    -1.641    1.982     3.517     .868  -.185000   .173000   .2872000      .000      .000  
+8212 9 45312.00 I  -.176059  .001548   .176075  .001061  I  .2845995  .0001355  2.8670 0.1003  I    -1.257    1.982     3.475     .868  -.186000   .175000   .2844000      .000      .000  
+821210 45313.00 I  -.177931  .001548   .179324  .001061  I  .2817447  .0001425  2.8311 0.1042  I     -.929    1.982     3.433     .868  -.188000   .178000   .2816000      .000      .000  
+821211 45314.00 I  -.179743  .001828   .182626  .001286  I  .2789577  .0001583  2.7341 0.1010  I     -.697    1.982     3.388     .868  -.190000   .181000   .2789000      .000      .000  
+821212 45315.00 I  -.181493  .002581   .185976  .001021  I  .2762903  .0001433  2.5958 0.0833  I     -.486    1.982     3.378     .868  -.191000   .184000   .2764000      .000      .000  
+821213 45316.00 I  -.183181  .000447   .189370  .000527  I  .2737720  .0000521  2.4397 0.0743  I     -.134    1.982     3.370     .868  -.193000   .187000   .2740000      .000      .000  
+821214 45317.00 I  -.184801  .000323   .192806  .000496  I  .2714093  .0000395  2.2885 0.0320  I      .468     .515     3.255     .367  -.194000   .190000   .2719000      .000      .000  
+821215 45318.00 I  -.186349  .000171   .196277  .000497  I  .2691863  .0000370  2.1633 0.0261  I     1.276     .509     2.983     .264  -.196000   .193000   .2698000      .000      .000  
+821216 45319.00 I  -.187819  .000150   .199780  .000514  I  .2670684  .0000340  2.0808 0.0251  I     2.180     .509     2.663     .264  -.197000   .196000   .2678000      .000      .000  
+821217 45320.00 I  -.189206  .000150   .203308  .000514  I  .2650073  .0000338  2.0503 0.0240  I     3.089     .509     2.463     .264  -.198000   .199000   .2658000      .000      .000  
+821218 45321.00 I  -.190511  .000150   .206851  .000514  I  .2629497  .0000338  2.0739 0.0238  I     3.871     .509     2.424     .264  -.199000   .202000   .2638000      .000      .000  
+821219 45322.00 I  -.191733  .000235   .210394  .000528  I  .2608427  .0000334  2.1478 0.0235  I     4.429     .509     2.414     .264  -.201000   .205000   .2617000      .000      .000  
+821220 45323.00 I  -.192882  .000275   .213927  .000542  I  .2586404  .0000326  2.2626 0.0261  I     4.819     .502     2.320     .868  -.202000   .208000   .2596000      .000      .000  
+821221 45324.00 I  -.193966  .000387   .217450  .000551  I  .2563087  .0000400  2.4037 0.0286  I     5.242    1.982     2.183     .868  -.203000   .211000   .2572000      .000      .000  
+821222 45325.00 I  -.194995  .000423   .220960  .000574  I  .2538298  .0000471  2.5542 0.0255  I     5.787    1.982     2.088     .868  -.204000   .214000   .2547000      .000      .000  
+821223 45326.00 I  -.195974  .001580   .224458  .000675  I  .2512028  .0000317  2.6970 0.0284  I     6.278    1.982     2.012     .868  -.205000   .218000   .2521000      .000      .000  
+821224 45327.00 I  -.196909  .001580   .227945  .000675  I  .2484449  .0000317  2.8123 0.0239  I     6.528    1.982     1.880     .868  -.206000   .221000   .2493000      .000      .000  
+821225 45328.00 I  -.197805  .001166   .231421  .000526  I  .2455952  .0000357  2.8765 0.0239  I     6.624    1.982     1.758     .868  -.207000   .225000   .2464000      .000      .000  
+821226 45329.00 I  -.198664  .001166   .234887  .000526  I  .2427162  .0000357  2.8677 0.0877  I     6.753    1.982     1.819     .868  -.208000   .228000   .2434000      .000      .000  
+821227 45330.00 I  -.199490  .002915   .238344  .000515  I  .2398866  .0001717  2.7784 0.0877  I     6.848    1.982     2.070     .868  -.209000   .231000   .2404000      .000      .000  
+821228 45331.00 I  -.200286  .002915   .241793  .000515  I  .2371797  .0001717  2.6283 0.1214  I     6.705    1.982     2.253     .868  -.209000   .235000   .2376000      .000      .000  
+821229 45332.00 I  -.201053  .002915   .245236  .000515  I  .2346342  .0001717  2.4658 0.1214  I     6.417    1.982     2.141     .868  -.210000   .238000   .2347000      .000      .000  
+821230 45333.00 I  -.201797  .002915   .248673  .000515  I  .2322319  .0001717  2.3521 0.1012  I     6.398    1.982     1.833     .868  -.210000   .242000   .2321000      .000      .000  
+821231 45334.00 I  -.202517  .002915   .252106  .000515  I  .2298981  .0001072  2.3342 0.1012  I     6.899    1.982     1.624     .868  -.211000   .245000   .2295000      .000      .000  
+83 1 1 45335.00 I  -.203212  .002915   .255534  .000515  I  .2275282  .0001072  2.4222 0.1100  I     7.695    1.982     1.630     .868  -.211000   .249000   .2269000      .000      .000  
+83 1 2 45336.00 I  -.203881  .002158   .258959  .001033  I  .2250294  .0001922  2.5833 0.1100  I     8.358    1.982     1.688     .868  -.212000   .252000   .2242000      .000      .000  
+83 1 3 45337.00 I  -.204519  .002158   .262381  .001033  I  .2223567  .0001922  2.7593 0.1359  I     8.666    1.982     1.656     .868  -.212000   .256000   .2222000      .000      .000  
+83 1 4 45338.00 I  -.205125  .002158   .265800  .001033  I  .2195252  .0001922  2.8923 0.1526  I     8.662    1.982     1.614     .868  -.213000   .259000   .2194000      .000      .000  
+83 1 5 45339.00 I  -.205695  .001526   .269217  .003380  I  .2165984  .0002370  2.9466 0.1595  I     8.483    1.982     1.702     .868  -.213000   .263000   .2150000      .000      .000  
+83 1 6 45340.00 I  -.206227  .001526   .272632  .003380  I  .2136601  .0002547  2.9167 0.1740  I     8.244    1.982     1.872     .868  -.213000   .267000   .2120000      .000      .000  
+83 1 7 45341.00 I  -.206714  .001526   .276045  .003380  I  .2107876  .0002547  2.8191 0.1705  I     7.987    1.982     1.950     .868  -.213000   .271000   .2092000      .000      .000  
+83 1 8 45342.00 I  -.207150  .003310   .279453  .004667  I  .2080355  .0002267  2.6808 0.1961  I     7.667    1.982     1.869     .868  -.212000   .275000   .2068000      .000      .000  
+83 1 9 45343.00 I  -.207528  .000663   .282860  .003542  I  .2054302  .0002982  2.5300 0.1873  I     7.247    1.982     1.739     .868  -.212000   .279000   .2044000      .000      .000  
+83 110 45344.00 I  -.207840  .000663   .286269  .003542  I  .2029718  .0002982  2.3904 0.2236  I     6.840    1.982     1.654     .868  -.212000   .283000   .2021000      .000      .000  
+83 111 45345.00 I  -.208081  .001547   .289686  .001815  I  .2006395  .0003333  2.2806 0.2570  I     6.649    1.982     1.567     .868  -.212000   .287000   .2000000      .000      .000  
+83 112 45346.00 I  -.208244  .001547   .293116  .001815  I  .1983961  .0004186  2.2144 0.2675  I     6.733    1.982     1.401     .868  -.212000   .291000   .1980000      .000      .000  
+83 113 45347.00 I  -.208322  .001547   .296563  .001815  I  .1961929  .0004186  2.2017 0.2960  I     6.936    1.982     1.211     .868  -.211000   .295000   .1962000      .000      .000  
+83 114 45348.00 I  -.208311  .001547   .300030  .001815  I  .1939732  .0004186  2.2477 0.3748  I     7.065    1.982     1.140     .868  -.211000   .299000   .1943000      .000      .000  
+83 115 45349.00 I  -.208208  .002241   .303518  .001940  I  .1916788  .0006219  2.3498 0.3748  I     7.029    1.982     1.229     .868  -.211000   .303000   .1923000      .000      .000  
+83 116 45350.00 I  -.208010  .002241   .307029  .001940  I  .1892581  .0006219  2.4983 0.4537  I     6.829    1.982     1.357     .868  -.210000   .307000   .1901000      .000      .000  
+83 117 45351.00 I  -.207718  .002337   .310562  .001588  I  .1866722  .0006608  2.6769 0.4537  I     6.521    1.982     1.397     .868  -.210000   .311000   .1879000      .000      .000  
+83 118 45352.00 I  -.207328  .002337   .314118  .001588  I  .1839011  .0006608  2.8653 0.4673  I     6.219    1.982     1.362     .868  -.209000   .315000   .1855000      .000      .000  
+83 119 45353.00 I  -.206842  .002337   .317697  .001588  I  .1809453  .0006608  3.0428 0.4294  I     6.003    1.982     1.332     .868  -.209000   .319000   .1829000      .000      .000  
+83 120 45354.00 I  -.206262  .002068   .321296  .001369  I  .1778254  .0005486  3.1905 0.3802  I     5.817    1.982     1.307     .868  -.208000   .323000   .1800000      .000      .000  
+83 121 45355.00 I  -.205593  .001829   .324915  .000826  I  .1745799  .0003761  3.2912 0.3482  I     5.568    1.982     1.223     .868  -.207000   .327000   .1771000      .000      .000  
+83 122 45356.00 I  -.204842  .001829   .328552  .000826  I  .1712638  .0004289  3.3294 0.2325  I     5.290    1.982     1.128     .868  -.207000   .331000   .1740000      .000      .000  
+83 123 45357.00 I  -.204017  .001379   .332205  .000756  I  .1679448  .0002736  3.2964 0.2522  I     5.029    1.982     1.193     .868  -.206000   .335000   .1710000      .000      .000  
+83 124 45358.00 I  -.203126  .001079   .335874  .000535  I  .1646928  .0002654  3.1981 0.1906  I     4.633    1.982     1.467     .868  -.206000   .339000   .1679000      .000      .000  
+83 125 45359.00 I  -.202180  .001079   .339560  .000535  I  .1615602  .0002654  3.0650 0.1864  I     3.886    1.982     1.732     .868  -.205000   .343000   .1649000      .000      .000  
+83 126 45360.00 I  -.201190  .004400   .343261  .003693  I  .1585570  .0002618  2.9494 0.1785  I     2.925    1.982     1.715     .868  -.204000   .347000   .1619000      .000      .000  
+83 127 45361.00 I  -.200166  .004400   .346978  .003693  I  .1556373  .0002389  2.9060 0.1527  I     2.273    1.982     1.438     .868  -.204000   .351000   .1589000      .000      .000  
+83 128 45362.00 I  -.199118  .004400   .350711  .003693  I  .1527105  .0001573  2.9659 0.1513  I     2.332    1.982     1.183     .868  -.203000   .354000   .1558000      .000      .000  
+83 129 45363.00 I  -.198059  .004400   .354459  .003693  I  .1496744  .0001857  3.1189 0.1111  I     2.972    1.982     1.139     .868  -.203000   .358000   .1526000      .000      .000  
+83 130 45364.00 I  -.196995  .004394   .358220  .003694  I  .1464584  .0001570  3.3147 0.1216  I     3.714    1.982     1.214     .868  -.202000   .362000   .1491000      .000      .000  
+83 131 45365.00 I  -.195926  .004394   .361986  .003694  I  .1430533  .0001570  3.4854 0.1127  I     4.169    1.982     1.269     .868  -.201000   .366000   .1455000      .000      .000  
+83 2 1 45366.00 I  -.194851  .000566   .365751  .000131  I  .1395149  .0001618  3.5740 0.0963  I     4.222    1.982     1.363     .868  -.200000   .369000   .1416000      .000      .000  
+83 2 2 45367.00 I  -.193771  .000890   .369508  .000155  I  .1359409  .0001114  3.5556 0.1255  I     3.959    1.982     1.628     .868  -.199000   .373000   .1374000      .000      .000  
+83 2 3 45368.00 I  -.192684  .000890   .373250  .000155  I  .1324362  .0001918  3.4396 0.1135  I     3.572    1.982     1.993     .868  -.198000   .376000   .1335000      .000      .000  
+83 2 4 45369.00 I  -.191588  .000890   .376969  .000155  I  .1290835  .0001979  3.2581 0.1238  I     3.240    1.982     2.200     .868  -.197000   .380000   .1298000      .000      .000  
+83 2 5 45370.00 I  -.190484  .000629   .380659  .002277  I  .1259296  .0001566  3.0479 0.1262  I     2.983    1.982     2.117     .868  -.196000   .383000   .1264000      .000      .000  
+83 2 6 45371.00 I  -.189367  .000629   .384312  .002277  I  .1229869  .0001566  2.8403 0.1190  I     2.712     .115     1.881     .868  -.195000   .386000   .1233000      .000      .000  
+83 2 7 45372.00 I  -.188234  .000795   .387921  .002104  I  .1202404  .0001792  2.6586 0.1199  I     2.474     .115     1.704     .868  -.193000   .390000   .1205000      .000      .000  
+83 2 8 45373.00 I  -.187082  .000765   .391479  .002278  I  .1176558  .0001815  2.5185 0.1236  I     2.501     .115     1.638     .868  -.192000   .393000   .1178000      .000      .000  
+83 2 9 45374.00 I  -.185908  .000765   .394981  .002278  I  .1151858  .0001704  2.4312 0.1204  I     2.928     .115     1.601     .868  -.191000   .396000   .1152000      .000      .000  
+83 210 45375.00 I  -.184713  .001330   .398433  .003276  I  .1127737  .0001582  2.4032 0.1047  I     3.581     .115     1.571     .868  -.190000   .399000   .1127000      .000      .000  
+83 211 45376.00 I  -.183498  .001263   .401844  .003426  I  .1103595  .0001217  2.4351 0.1560  I     4.159     .115     1.624     .868  -.188000   .402000   .1103000      .000      .000  
+83 212 45377.00 I  -.182269  .003306   .405222  .004628  I  .1078857  .0002689  2.5205 0.0718  I     4.536    1.982     1.808     .868  -.187000   .406000   .1079000      .000      .000  
+83 213 45378.00 I  -.181029  .004242   .408577  .006541  I  .1053057  .0000762  2.6445 0.1387  I     4.766    1.982     2.038     .868  -.185000   .409000   .1053000      .000      .000  
+83 214 45379.00 I  -.179780  .003088   .411914  .004643  I  .1025905  .0000680  2.7873 0.0511  I     4.919    1.982     2.186     .868  -.184000   .412000   .1025000      .000      .000  
+83 215 45380.00 I  -.178518  .003088   .415234  .004643  I  .0997325  .0000680  2.9259 0.1113  I     5.026    1.982     2.203     .868  -.182000   .415000   .0996000      .000      .000  
+83 216 45381.00 I  -.177241  .000821   .418537  .000936  I  .0967476  .0002120  3.0379 0.1113  I     5.132    1.982     2.140     .868  -.181000   .418000   .0965000      .000      .000  
+83 217 45382.00 I  -.175944  .000821   .421823  .000936  I  .0936712  .0002120  3.1063 0.1499  I     5.281    1.982     2.053     .868  -.179000   .421000   .0934000      .000      .000  
+83 218 45383.00 I  -.174625  .000821   .425092  .000936  I  .0905532  .0002120  3.1201 0.1545  I     5.469    1.982     1.959     .868  -.178000   .424000   .0902000      .000      .000  
+83 219 45384.00 I  -.173282  .000821   .428344  .000936  I  .0874499  .0002249  3.0770 0.2929  I     5.676    1.982     1.888     .868  -.176000   .427000   .0870000      .000      .000  
+83 220 45385.00 I  -.171913  .000524   .431577  .000847  I  .0844157  .0005460  2.9842 0.2953  I     5.865    1.982     1.908     .868  -.174000   .430000   .0840000      .000      .000  
+83 221 45386.00 I  -.170518  .000524   .434794  .000847  I  .0814906  .0005460  2.8641 0.4075  I     5.933    1.982     2.024     .868  -.172000   .433000   .0810000      .000      .000  
+83 222 45387.00 I  -.169096  .000524   .437994  .000092  I  .0786836  .0006050  2.7557 0.3876  I     5.770    1.982     2.106     .868  -.171000   .436000   .0782000      .000      .000  
+83 223 45388.00 I  -.167646  .000383   .441179  .001618  I  .0759597  .0005503  2.7058 0.4089  I     5.459    1.982     1.996     .868  -.169000   .439000   .0755000      .000      .000  
+83 224 45389.00 I  -.166167  .000383   .444350  .001618  I  .0732408  .0005503  2.7493 0.3891  I     5.311    1.982     1.711     .868  -.167000   .442000   .0728000      .000      .000  
+83 225 45390.00 I  -.164660  .000383   .447507  .001618  I  .0704274  .0005503  2.8937 0.2792  I     5.580    1.982     1.453     .868  -.165000   .445000   .0700000      .000      .000  
+83 226 45391.00 I  -.163125  .000542   .450652  .000761  I  .0674296  .0000950  3.1096 0.2792  I     6.197    1.982     1.363     .868  -.163000   .448000   .0670000      .000      .000  
+83 227 45392.00 I  -.161563  .000542   .453782  .000761  I  .0642052  .0000950  3.3346 0.0672  I     6.862     .187     1.369     .868  -.162000   .451000   .0637000      .000      .000  
+83 228 45393.00 I  -.159973  .000542   .456896  .000761  I  .0607805  .0000950  3.4993 0.0656  I     7.307     .187     1.338     .868  -.160000   .454000   .0603000      .000      .000  
+83 3 1 45394.00 I  -.158356  .000625   .459991  .000572  I  .0572429  .0000905  3.5550 0.0656  I     7.414     .187     1.296     .868  -.158000   .457000   .0567000      .000      .000  
+83 3 2 45395.00 I  -.156711  .000625   .463065  .000572  I  .0537102  .0000905  3.4915 0.0727  I     7.194     .187     1.378     .868  -.156000   .460000   .0531000      .000      .000  
+83 3 3 45396.00 I  -.155027  .001403   .466114  .001870  I  .0502915  .0001139  3.3331 0.0736  I     6.767     .187     1.568     .868  -.154000   .463000   .0496000      .000      .000  
+83 3 4 45397.00 I  -.153292  .001410   .469131  .001955  I  .0470614  .0001162  3.1223 0.1340  I     6.298     .187     1.650     .868  -.152000   .466000   .0462000      .000      .000  
+83 3 5 45398.00 I  -.151495  .003480   .472111  .004355  I  .0440498  .0002426  2.9026 0.1345  I     5.851    1.982     1.462     .868  -.150000   .469000   .0431000      .000      .000  
+83 3 6 45399.00 I  -.149620  .003480   .475047  .004355  I  .0412480  .0002426  2.7075 0.1533  I     5.385    1.982     1.098     .868  -.148000   .472000   .0403000      .000      .000  
+83 3 7 45400.00 I  -.147661  .003431   .477937  .004401  I  .0386193  .0001876  2.5590 0.1533  I     4.949    1.982      .789     .868  -.146000   .475000   .0376000      .000      .000  
+83 3 8 45401.00 I  -.145613  .003431   .480781  .004401  I  .0361107  .0001876  2.4686 0.1434  I     4.763    1.982      .637     .868  -.144000   .478000   .0351000      .000      .000  
+83 3 9 45402.00 I  -.143471  .002039   .483580  .001492  I  .0336612  .0002170  2.4409 0.1434  I     4.963    1.982      .572     .868  -.141000   .481000   .0326000      .000      .000  
+83 310 45403.00 I  -.141231  .002039   .486336  .001492  I  .0312083  .0002170  2.4749 0.1534  I     5.363    1.982      .510     .868  -.139000   .484000   .0302000      .000      .000  
+83 311 45404.00 I  -.138889  .002039   .489050  .001492  I  .0286930  .0002170  2.5639 0.1144  I     5.604    1.982      .472     .868  -.137000   .487000   .0277000      .000      .000  
+83 312 45405.00 I  -.136442  .001122   .491725  .000702  I  .0260663  .0000726  2.6953 0.1160  I     5.520    1.982      .516     .868  -.134000   .490000   .0251000      .000      .000  
+83 313 45406.00 I  -.133885  .001107   .494364  .000579  I  .0232944  .0000819  2.8507 0.0547  I     5.211     .120      .628     .868  -.132000   .493000   .0224000      .000      .000  
+83 314 45407.00 I  -.131210  .001107   .496969  .000579  I  .0203649  .0000819  3.0062 0.0468  I     4.824     .120      .709     .868  -.129000   .496000   .0197000      .000      .000  
+83 315 45408.00 I  -.128410  .000742   .499543  .000606  I  .0172904  .0000455  3.1364 0.0468  I     4.419     .120      .656     .868  -.127000   .499000   .0167000      .000      .000  
+83 316 45409.00 I  -.125478  .000742   .502086  .000606  I  .0141085  .0000455  3.2173 0.0322  I     4.034     .120      .448     .868  -.124000   .502000   .0136000      .000      .000  
+83 317 45410.00 I  -.122418  .000742   .504602  .000606  I  .0108778  .0000455  3.2322 0.0322  I     3.722     .120      .156     .868  -.121000   .505000   .0104000      .000      .000  
+83 318 45411.00 I  -.119235  .000742   .507091  .000606  I  .0076674  .0000455  3.1773 0.0574  I     3.482     .120     -.105     .868  -.118000   .507000   .0073000      .000      .000  
+83 319 45412.00 I  -.115937  .000322   .509555  .000960  I  .0045425  .0001053  3.0645 0.0574  I     3.245    1.982     -.262     .868  -.115000   .510000   .0043000      .000      .000  
+83 320 45413.00 I  -.112530  .000322   .511993  .000960  I  .0015490  .0001053  2.9199 0.0862  I     2.965    1.982     -.321     .868  -.112000   .512000   .0014000      .000      .000  
+83 321 45414.00 I  -.109022  .000050   .514404  .000777  I -.0012990  .0001364  2.7804 0.0915  I     2.690    1.982     -.350     .868  -.109000   .515000  -.0014000      .000      .000  
+83 322 45415.00 I  -.105420  .000646   .516789  .000796  I -.0040274  .0001497  2.6878 0.1319  I     2.519    1.982     -.435     .868  -.106000   .517000  -.0041000      .000      .000  
+83 323 45416.00 I  -.101731  .000646   .519147  .000796  I -.0067025  .0002259  2.6790 0.1260  I     2.531    1.982     -.609     .868  -.102000   .519000  -.0068000      .000      .000  
+83 324 45417.00 I  -.097962  .000656   .521477  .001889  I -.0094192  .0002028  2.7718 0.1564  I     2.738    1.982     -.816     .868  -.099000   .522000  -.0095000      .000      .000  
+83 325 45418.00 I  -.094119  .000802   .523776  .002247  I -.0122760  .0002164  2.9544 0.1483  I     3.049    1.982     -.948     .868  -.095000   .524000  -.0124000      .000      .000  
+83 326 45419.00 I  -.090209  .000802   .526043  .002247  I -.0153433  .0002164  3.1830 0.1530  I     3.301    1.982     -.955     .868  -.092000   .526000  -.0154000      .000      .000  
+83 327 45420.00 I  -.086237  .000802   .528276  .002247  I -.0186359  .0002164  3.3933 0.1479  I     3.380    1.982     -.916     .868  -.088000   .528000  -.0187000      .000      .000  
+83 328 45421.00 I  -.082209  .001142   .530471  .002405  I -.0221034  .0002018  3.5242 0.1105  I     3.304    1.982     -.942     .868  -.084000   .530000  -.0222000      .000      .000  
+83 329 45422.00 I  -.078130  .001142   .532621  .002405  I -.0256461  .0000450  3.5406 0.1034  I     3.171    1.982    -1.028     .868  -.081000   .532000  -.0257000      .000      .000  
+83 330 45423.00 I  -.074009  .001062   .534721  .001033  I -.0291468  .0000448  3.4436 0.0317  I     3.035    1.982    -1.055     .868  -.077000   .534000  -.0292000      .000      .000  
+83 331 45424.00 I  -.069850  .001062   .536763  .001033  I -.0325059  .0000448  3.2644 0.0317  I     2.891    1.982     -.968     .868  -.073000   .536000  -.0326000      .000      .000  
+83 4 1 45425.00 I  -.065659  .001062   .538743  .001033  I -.0356630  .0000448  3.0476 0.0317  I     2.723    1.982     -.881     .868  -.069000   .538000  -.0358000      .000      .000  
+83 4 2 45426.00 I  -.061440  .001062   .540657  .001033  I -.0386029  .0000448  2.8363 0.0940  I     2.532    1.982     -.931     .868  -.065000   .539000  -.0387000      .000      .000  
+83 4 3 45427.00 I  -.057195  .000454   .542501  .000976  I -.0413476  .0001825  2.6610 0.0940  I     2.344    1.982    -1.100     .868  -.060000   .541000  -.0415000      .000      .000  
+83 4 4 45428.00 I  -.052928  .000454   .544268  .000976  I -.0439429  .0001825  2.5396 0.1565  I     2.274    1.982    -1.238     .868  -.056000   .542000  -.0441000      .000      .000  
+83 4 5 45429.00 I  -.048642  .000555   .545956  .001380  I -.0464476  .0002542  2.4804 0.1404  I     2.501    1.982    -1.256     .868  -.052000   .544000  -.0466000      .000      .000  
+83 4 6 45430.00 I  -.044341  .000911   .547559  .001490  I -.0489244  .0002133  2.4833 0.1659  I     3.093    1.982    -1.208     .868  -.048000   .545000  -.0491000      .000      .000  
+83 4 7 45431.00 I  -.040027  .000911   .549075  .001490  I -.0514330  .0002133  2.5427 0.1508  I     3.864    1.982    -1.184     .868  -.044000   .547000  -.0516000      .000      .000  
+83 4 8 45432.00 I  -.035702  .000911   .550499  .001490  I -.0540247  .0002133  2.6468 0.1398  I     4.481    1.982    -1.184     .868  -.040000   .548000  -.0542000      .000      .000  
+83 4 9 45433.00 I  -.031369  .001542   .551829  .001346  I -.0567364  .0001807  2.7802 0.1398  I     4.733    1.982    -1.138     .868  -.036000   .550000  -.0568000      .000      .000  
+83 410 45434.00 I  -.027031  .001542   .553065  .001346  I -.0595887  .0001807  2.9244 0.1287  I     4.664    1.982    -1.005     .868  -.032000   .551000  -.0596000      .000      .000  
+83 411 45435.00 I  -.022693  .001542   .554205  .001346  I -.0625809  .0001833  3.0558 0.1308  I     4.461    1.982     -.834     .868  -.028000   .552000  -.0625000      .000      .000  
+83 412 45436.00 I  -.018358  .001890   .555249  .000766  I -.0656872  .0001891  3.1480 0.1317  I     4.290    1.982     -.733     .868  -.024000   .553000  -.0656000      .000      .000  
+83 413 45437.00 I  -.014034  .001890   .556197  .000766  I -.0688558  .0001891  3.1769 0.1457  I     4.235    1.982     -.790     .868  -.020000   .555000  -.0686000      .000      .000  
+83 414 45438.00 I  -.009727  .001920   .557050  .000941  I -.0720153  .0002217  3.1286 0.1532  I     4.287    1.982     -.994     .868  -.016000   .556000  -.0716000      .000      .000  
+83 415 45439.00 I  -.005446  .001957   .557808  .000886  I -.0750885  .0002410  3.0067 0.1637  I     4.358    1.982    -1.231     .868  -.012000   .557000  -.0746000      .000      .000  
+83 416 45440.00 I  -.001195  .001957   .558473  .000886  I -.0780126  .0002410  2.8363 0.1670  I     4.341    1.982    -1.372     .868  -.008000   .558000  -.0774000      .000      .000  
+83 417 45441.00 I   .003020  .001691   .559045  .001048  I -.0807588  .0002313  2.6588 0.1652  I     4.226    1.982    -1.383     .868  -.004000   .559000  -.0800000      .000      .000  
+83 418 45442.00 I   .007198  .001556   .559527  .001266  I -.0833430  .0002261  2.5197 0.1617  I     4.150    1.982    -1.340     .868   .001000   .559000  -.0825000      .000      .000  
+83 419 45443.00 I   .011338  .001556   .559922  .001266  I -.0858234  .0002261  2.4561 0.1139  I     4.301    1.982    -1.327     .868   .005000   .560000  -.0849000      .000      .000  
+83 420 45444.00 I   .015440  .000805   .560231  .001116  I -.0882865  .0000283  2.4863 0.2799  I     4.772    1.982    -1.361     .868   .009000   .561000  -.0873000      .000      .000  
+83 421 45445.00 I   .019503  .000805   .560459  .001116  I -.0908251  .0005120  2.6036 0.2564  I     5.469    1.982    -1.391     .868   .013000   .561000  -.0897000      .000      .000  
+83 422 45446.00 I   .023529  .000805   .560610  .001116  I -.0935121  .0005120  2.7760 0.3891  I     6.141    1.982    -1.364     .868   .017000   .562000  -.0924000      .000      .000  
+83 423 45447.00 I   .027520  .000608   .560689  .000875  I -.0963788  .0005860  2.9534 0.3632  I     6.524    1.982    -1.273     .868   .022000   .562000  -.0952000      .000      .000  
+83 424 45448.00 I   .031477  .001150   .560698  .000944  I -.0994022  .0005154  3.0807 0.3902  I     6.510    1.982    -1.164     .868   .026000   .563000  -.0982000      .000      .000  
+83 425 45449.00 I   .035403  .001150   .560642  .000944  I -.1025100  .0005154  3.1176 0.3916  I     6.219    1.982    -1.098     .868   .030000   .563000  -.1013000      .000      .000  
+83 426 45450.00 I   .039300  .001509   .560525  .001009  I -.1056022  .0005898  3.0490 0.2662  I     5.910    1.982    -1.088     .868   .034000   .563000  -.1044000      .000      .000  
+83 427 45451.00 I   .043172  .001177   .560348  .000745  I -.1085773  .0001333  2.8883 0.3023  I     5.781    1.982    -1.080     .868   .038000   .563000  -.1074000      .000      .000  
+83 428 45452.00 I   .047021  .001177   .560116  .000745  I -.1113600  .0001333  2.6713 0.0943  I     5.828    1.982    -1.028     .868   .043000   .564000  -.1102000      .000      .000  
+83 429 45453.00 I   .050854  .001177   .559830  .000745  I -.1139153  .0001333  2.4407 0.0973  I     5.897    1.982     -.971     .868   .047000   .564000  -.1128000      .000      .000  
+83 430 45454.00 I   .054675  .000704   .559493  .000304  I -.1162496  .0001417  2.2348 0.0973  I     5.863    1.982     -.981     .868   .051000   .564000  -.1153000      .000      .000  
+83 5 1 45455.00 I   .058491  .000704   .559106  .000304  I -.1184020  .0001417  2.0802 0.1276  I     5.755    1.982    -1.059     .868   .055000   .564000  -.1175000      .000      .000  
+83 5 2 45456.00 I   .062309  .000649   .558672  .000671  I -.1204319  .0002123  1.9913 0.0757  I     5.725    1.982    -1.129     .868   .059000   .564000  -.1197000      .000      .000  
+83 5 3 45457.00 I   .066136  .000165   .558194  .000379  I -.1224077  .0000536  1.9719 0.1095  I     5.902    1.982    -1.151     .868   .064000   .564000  -.1219000      .000      .000  
+83 5 4 45458.00 I   .069979  .000165   .557674  .000379  I -.1243973  .0000536  2.0175 0.0405  I     6.293    1.982    -1.169     .868   .068000   .564000  -.1240000      .000      .000  
+83 5 5 45459.00 I   .073844  .000700   .557115  .000397  I -.1264606  .0000608  2.1170 0.0405  I     6.795    1.982    -1.234     .868   .072000   .564000  -.1262000      .000      .000  
+83 5 6 45460.00 I   .077738  .000700   .556519  .000397  I -.1286443  .0000608  2.2555 0.0430  I     7.231    1.982    -1.316     .868   .076000   .563000  -.1285000      .000      .000  
+83 5 7 45461.00 I   .081669  .000700   .555888  .000397  I -.1309783  .0000608  2.4139 0.0347  I     7.403    1.982    -1.342     .868   .080000   .563000  -.1310000      .000      .000  
+83 5 8 45462.00 I   .085642  .000705   .555220  .000356  I -.1334714  .0000336  2.5701 0.0449  I     7.199    1.982    -1.282     .868   .085000   .562000  -.1336000      .000      .000  
+83 5 9 45463.00 I   .089658  .000942   .554509  .000366  I -.1361100  .0000662  2.7008 0.1815  I     6.714    1.982    -1.164     .868   .089000   .562000  -.1363000      .000      .000  
+83 510 45464.00 I   .093715  .003000   .553751  .000610  I -.1388562  .0003615  2.7811 0.1858  I     6.220    1.982    -1.041     .868   .093000   .561000  -.1392000      .000      .000  
+83 511 45465.00 I   .097812  .002066   .552942  .000645  I -.1416479  .0003656  2.7885 0.2571  I     5.938    1.982     -.976     .868   .097000   .560000  -.1421000      .000      .000  
+83 512 45466.00 I   .101946  .002066   .552078  .000645  I -.1444055  .0003656  2.7130 0.2585  I     5.837    1.982    -1.031     .868   .101000   .559000  -.1450000      .000      .000  
+83 513 45467.00 I   .106112  .002066   .551155  .000645  I -.1470507  .0003656  2.5681 0.2585  I     5.722    1.982    -1.214     .868   .105000   .559000  -.1478000      .000      .000  
+83 514 45468.00 I   .110302  .002066   .550170  .000645  I -.1495316  .0003656  2.3930 0.2062  I     5.489    1.982    -1.438     .868   .109000   .558000  -.1504000      .000      .000  
+83 515 45469.00 I   .114509  .000312   .549120  .000770  I -.1518442  .0001910  2.2404 0.2062  I     5.232    1.982    -1.581     .868   .113000   .557000  -.1528000      .000      .000  
+83 516 45470.00 I   .118726  .000312   .547998  .000770  I -.1540358  .0001910  2.1580 0.1081  I     5.105    1.982    -1.601     .868   .117000   .556000  -.1551000      .000      .000  
+83 517 45471.00 I   .122945  .000361   .546802  .000799  I -.1561922  .0001015  2.1718 0.1425  I     5.172    1.982    -1.554     .868   .121000   .555000  -.1573000      .000      .000  
+83 518 45472.00 I   .127159  .000272   .545527  .002039  I -.1584097  .0002116  2.2767 0.1173  I     5.391    1.982    -1.518     .868   .125000   .554000  -.1597000      .000      .000  
+83 519 45473.00 I   .131360  .000272   .544168  .002039  I -.1607653  .0002116  2.4409 0.1564  I     5.686    1.982    -1.512     .868   .129000   .553000  -.1621000      .000      .000  
+83 520 45474.00 I   .135539  .000272   .542719  .002039  I -.1632953  .0002304  2.6166 0.2434  I     5.960    1.982    -1.509     .868   .133000   .552000  -.1647000      .000      .000  
+83 521 45475.00 I   .139689  .001183   .541175  .003105  I -.1659860  .0004384  2.7549 0.2226  I     6.076    1.982    -1.476     .868   .137000   .551000  -.1675000      .000      .000  
+83 522 45476.00 I   .143801  .001183   .539534  .003105  I -.1687803  .0003810  2.8187 0.2904  I     5.901    1.982    -1.406     .868   .141000   .549000  -.1704000      .000      .000  
+83 523 45477.00 I   .147867  .001183   .537793  .003105  I -.1715926  .0003810  2.7901 0.2700  I     5.417    1.982    -1.308     .868   .144000   .548000  -.1733000      .000      .000  
+83 524 45478.00 I   .151878  .001630   .535950  .002590  I -.1743313  .0003828  2.6738 0.2700  I     4.793    1.982    -1.199     .868   .148000   .546000  -.1760000      .000      .000  
+83 525 45479.00 I   .155826  .001630   .534004  .002590  I -.1769185  .0003828  2.4924 0.2717  I     4.289    1.982    -1.104     .868   .152000   .545000  -.1787000      .000      .000  
+83 526 45480.00 I   .159706  .001776   .531958  .002117  I -.1793060  .0003856  2.2809 0.1973  I     4.048    1.982    -1.058     .868   .156000   .543000  -.1811000      .000      .000  
+83 527 45481.00 I   .163513  .001827   .529815  .000960  I -.1814826  .0000959  2.0764 0.1964  I     3.977    1.982    -1.099     .868   .159000   .541000  -.1833000      .000      .000  
+83 528 45482.00 I   .167243  .001827   .527577  .000960  I -.1834712  .0000752  1.9090 0.0609  I     3.888    1.982    -1.223     .868   .163000   .540000  -.1852000      .000      .000  
+83 529 45483.00 I   .170895  .001827   .525249  .000960  I -.1853193  .0000752  1.7978 0.0457  I     3.710    1.982    -1.360     .868   .166000   .538000  -.1871000      .000      .000  
+83 530 45484.00 I   .174469  .001582   .522836  .001735  I -.1870888  .0000520  1.7525 0.1181  I     3.515    1.982    -1.429     .868   .170000   .536000  -.1889000      .000      .000  
+83 531 45485.00 I   .177966  .001582   .520342  .001735  I -.1888461  .0002240  1.7725 0.1155  I     3.361    1.982    -1.439     .868   .174000   .534000  -.1906000      .000      .000  
+83 6 1 45486.00 I   .181388  .001512   .517771  .002038  I -.1906526  .0002251  1.8488 0.1588  I     3.238    1.982    -1.472     .868   .177000   .532000  -.1924000      .000      .000  
+83 6 2 45487.00 I   .184737  .001512   .515127  .002038  I -.1925570  .0002251  1.9651 0.1592  I     3.174    1.982    -1.561     .868   .181000   .529000  -.1942000      .000      .000  
+83 6 3 45488.00 I   .188016  .001512   .512417  .002038  I -.1945898  .0002251  2.1024 0.1592  I     3.220    1.982    -1.625     .868   .184000   .527000  -.1962000      .000      .000  
+83 6 4 45489.00 I   .191228  .001512   .509648  .002038  I -.1967628  .0002251  2.2425 0.1966  I     3.258    1.982    -1.583     .868   .188000   .525000  -.1984000      .000      .000  
+83 6 5 45490.00 I   .194379  .001406   .506829  .001455  I -.1990697  .0003223  2.3671 0.1787  I     2.994    1.982    -1.463     .868   .191000   .522000  -.2007000      .000      .000  
+83 6 6 45491.00 I   .197476  .001406   .503969  .001455  I -.2014855  .0002775  2.4570 0.2532  I     2.308    1.982    -1.346     .868   .195000   .520000  -.2032000      .000      .000  
+83 6 7 45492.00 I   .200525  .000482   .501077  .001388  I -.2039651  .0003907  2.4910 0.2022  I     1.481    1.982    -1.231     .868   .198000   .517000  -.2058000      .000      .000  
+83 6 8 45493.00 I   .203534  .003437   .498163  .001262  I -.2064431  .0002943  2.4516 0.2446  I      .902    1.982    -1.065     .868   .202000   .515000  -.2083000      .000      .000  
+83 6 9 45494.00 I   .206511  .003437   .495238  .001262  I -.2088431  .0002943  2.3364 0.2081  I      .616    1.982     -.892     .868   .205000   .512000  -.2107000      .000      .000  
+83 610 45495.00 I   .209463  .003437   .492312  .001262  I -.2110986  .0002943  2.1692 0.1495  I      .368    1.982     -.857     .868   .208000   .509000  -.2129000      .000      .000  
+83 611 45496.00 I   .212398  .002297   .489397  .002117  I -.2131805  .0000532  1.9990 0.1495  I      .041    1.982    -1.014     .868   .212000   .506000  -.2150000      .000      .000  
+83 612 45497.00 I   .215316  .002297   .486502  .002117  I -.2151148  .0000532  1.8834 0.0376  I     -.175    1.982    -1.218     .868   .215000   .503000  -.2169000      .000      .000  
+83 613 45498.00 I   .218216  .002297   .483639  .002117  I -.2169799  .0000532  1.8654 0.0399  I     -.095    1.982    -1.275     .868   .219000   .500000  -.2188000      .000      .000  
+83 614 45499.00 I   .221098  .000931   .480815  .001173  I -.2188808  .0000596  1.9529 0.0399  I      .171    1.982    -1.159     .868   .222000   .497000  -.2206000      .000      .000  
+83 615 45500.00 I   .223959  .000931   .478037  .001173  I -.2209105  .0000596  2.1150 0.0387  I      .351    1.982     -.995     .868   .225000   .494000  -.2226000      .000      .000  
+83 616 45501.00 I   .226807  .000896   .475297  .000881  I -.2231172  .0000494  2.2965 0.0389  I      .322    1.982     -.882     .868   .228000   .490000  -.2247000      .000      .000  
+83 617 45502.00 I   .229649  .000766   .472583  .000824  I -.2254904  .0000500  2.4386 0.0372  I      .179    1.982     -.795     .868   .232000   .487000  -.2270000      .000      .000  
+83 618 45503.00 I   .232469  .000690   .469865  .000451  I -.2279672  .0000557  2.4989 0.0374  I      .052    1.982     -.673     .868   .235000   .483000  -.2294000      .000      .000  
+83 619 45504.00 I   .235245  .000690   .467113  .000451  I -.2304555  .0000557  2.4611 0.0510  I     -.072    1.982     -.500     .868   .238000   .480000  -.2318000      .000      .000  
+83 620 45505.00 I   .237965  .001422   .464296  .001535  I -.2328591  .0000855  2.3326 0.0510  I     -.322    1.982     -.303     .868   .241000   .476000  -.2340000      .000      .000  
+83 621 45506.00 I   .240656  .001422   .461383  .001535  I -.2350984  .0000855  2.1373 0.0611  I     -.773    1.982     -.093     .868   .244000   .473000  -.2361000      .000      .000  
+83 622 45507.00 I   .243352  .001795   .458346  .001746  I -.2371218  .0000873  1.9063 0.0611  I    -1.306    1.982      .107     .868   .246000   .469000  -.2380000      .000      .000  
+83 623 45508.00 I   .246079  .001795   .455162  .001746  I -.2389102  .0000873  1.6730 0.0617  I    -1.693    1.982      .232     .868   .249000   .466000  -.2397000      .000      .000  
+83 624 45509.00 I   .248790  .001795   .451851  .001746  I -.2404772  .0000873  1.4677 0.0617  I    -1.824    1.982      .204     .868   .252000   .462000  -.2411000      .000      .000  
+83 625 45510.00 I   .251403  .001795   .448455  .001746  I -.2418619  .0000873  1.3111 0.0539  I    -1.806    1.982      .051     .868   .255000   .458000  -.2424000      .000      .000  
+83 626 45511.00 I   .253904  .001314   .444994  .000863  I -.2431196  .0000633  1.2151 0.0539  I    -1.807    1.982     -.077     .868   .257000   .455000  -.2435000      .000      .000  
+83 627 45512.00 I   .256323  .001314   .441473  .000863  I -.2443137  .0000633  1.1837 0.0554  I    -1.913    1.982     -.039     .868   .260000   .451000  -.2446000      .000      .000  
+83 628 45513.00 I   .258689  .000409   .437896  .000709  I -.2455067  .0000910  1.2112 0.0554  I    -2.152    1.982      .137     .868   .262000   .448000  -.2458000      .000      .000  
+83 629 45514.00 I   .261034  .000409   .434269  .000709  I -.2467514  .0000910  1.2846 0.0643  I    -2.517    1.982      .286     .868   .265000   .444000  -.2470000      .000      .000  
+83 630 45515.00 I   .263368  .000409   .430601  .000709  I -.2480856  .0000910  1.3870 0.0643  I    -2.883    1.982      .325     .868   .267000   .440000  -.2483000      .000      .000  
+83 7 1 45516.00 I   .265685  .000409   .426907  .000709  I  .7504719  .0000910  1.4976 0.0662  I    -3.047    1.982      .353     .868   .269000   .436000   .7503000      .000      .000  
+83 7 2 45517.00 I   .267977  .000035   .423195  .000953  I  .7489233  .0000961  1.5959 0.0662  I    -3.031    1.982      .491     .868   .272000   .433000   .7487000      .000      .000  
+83 7 3 45518.00 I   .270239  .000035   .419450  .000953  I  .7472900  .0000961  1.6646 0.0788  I    -3.200    1.982      .682     .868   .274000   .429000   .7470000      .000      .000  
+83 7 4 45519.00 I   .272465  .000302   .415657  .001360  I  .7456089  .0001250  1.6889 0.0788  I    -3.864    1.982      .772     .868   .276000   .425000   .7453000      .000      .000  
+83 7 5 45520.00 I   .274650  .000302   .411797  .001360  I  .7439316  .0001250  1.6549 0.0911  I    -4.842    1.982      .749     .868   .278000   .421000   .7436000      .000      .000  
+83 7 6 45521.00 I   .276789  .000302   .407855  .001360  I  .7423215  .0001325  1.5538 0.0911  I    -5.649    1.982      .771     .868   .280000   .417000   .7419000      .000      .000  
+83 7 7 45522.00 I   .278877  .000302   .403817  .001360  I  .7408431  .0001325  1.3956 0.0937  I    -6.088    1.982      .904     .868   .283000   .413000   .7403000      .000      .000  
+83 7 8 45523.00 I   .280924  .000302   .399698  .001360  I  .7395374  .0001325  1.2163 0.0937  I    -6.368    1.982      .986     .868   .285000   .409000   .7389000      .000      .000  
+83 7 9 45524.00 I   .282943  .000302   .395528  .001360  I  .7383994  .0001325  1.0705 0.0814  I    -6.657    1.982      .846     .868   .287000   .405000   .7376000      .000      .000  
+83 710 45525.00 I   .284950  .000235   .391334  .001169  I  .7373669  .0000947  1.0134 0.0814  I    -6.806    1.982      .570     .868   .289000   .401000   .7365000      .000      .000  
+83 711 45526.00 I   .286959  .000235   .387145  .001169  I  .7363329  .0000947  1.0754 0.0630  I    -6.648    1.982      .403     .868   .291000   .397000   .7353000      .000      .000  
+83 712 45527.00 I   .288985  .000235   .382991  .001169  I  .7351809  .0000832  1.2431 0.0883  I    -6.338    1.982      .433     .868   .294000   .392000   .7340000      .000      .000  
+83 713 45528.00 I   .291042  .000467   .378900  .000847  I  .7338288  .0001491  1.4644 0.1302  I    -6.223    1.982      .515     .868   .296000   .388000   .7325000      .000      .000  
+83 714 45529.00 I   .293139  .000467   .374884  .000847  I  .7322570  .0002468  1.6708 0.1455  I    -6.469    1.982      .521     .868   .298000   .384000   .7309000      .000      .000  
+83 715 45530.00 I   .295275  .000467   .370936  .000847  I  .7305113  .0002498  1.8047 0.2106  I    -6.938    1.982      .507     .868   .300000   .380000   .7290000      .000      .000  
+83 716 45531.00 I   .297449  .000618   .367044  .000258  I  .7286812  .0003414  1.8376 0.1846  I    -7.368    1.982      .577     .868   .302000   .376000   .7271000      .000      .000  
+83 717 45532.00 I   .299642  .000535   .363202  .000284  I  .7268689  .0002718  1.7720 0.2182  I    -7.596    1.982      .692     .868   .305000   .371000   .7253000      .000      .000  
+83 718 45533.00 I   .301814  .000535   .359408  .000284  I  .7251607  .0002718  1.6360 0.2140  I    -7.668    1.982      .726     .868   .307000   .367000   .7236000      .000      .000  
+83 719 45534.00 I   .303922  .000437   .355660  .000307  I  .7236072  .0003305  1.4691 0.1573  I    -7.777    1.982      .651     .868   .309000   .363000   .7221000      .000      .000  
+83 720 45535.00 I   .305929  .000410   .351954  .000268  I  .7222224  .0001583  1.3025 0.1820  I    -8.041    1.982      .552     .868   .311000   .359000   .7208000      .000      .000  
+83 721 45536.00 I   .307817  .000410   .348280  .000268  I  .7209944  .0001527  1.1592 0.1014  I    -8.338    1.982      .465     .868   .313000   .354000   .7197000      .000      .000  
+83 722 45537.00 I   .309571  .000347   .344626  .000305  I  .7198906  .0001267  1.0562 0.1278  I    -8.428    1.982      .317     .868   .315000   .350000   .7188000      .000      .000  
+83 723 45538.00 I   .311184  .000291   .340978  .000304  I  .7188644  .0002050  1.0061 0.1456  I    -8.230    1.982      .073     .868   .317000   .345000   .7179000      .000      .000  
+83 724 45539.00 I   .312662  .000291   .337319  .000304  I  .7178588  .0002621  1.0150 0.1515  I    -7.898     .184     -.142     .868   .319000   .341000   .7171000      .000      .000  
+83 725 45540.00 I   .314018  .000305   .333629  .000322  I  .7168157  .0002231  1.0801 0.1836  I    -7.626     .184     -.156     .868   .320000   .337000   .7163000      .000      .000  
+83 726 45541.00 I   .315265  .000260   .329890  .000362  I  .7156832  .0002572  1.1915 0.1702  I    -7.490     .184      .029     .868   .322000   .332000   .7153000      .000      .000  
+83 727 45542.00 I   .316426  .000260   .326094  .000362  I  .7144231  .0002572  1.3317 0.1872  I    -7.454     .184      .215     .868   .323000   .328000   .7143000      .000      .000  
+83 728 45543.00 I   .317524  .000270   .322234  .000897  I  .7130171  .0002720  1.4799 0.1640  I    -7.386     .184      .246     .868   .325000   .323000   .7131000      .000      .000  
+83 729 45544.00 I   .318573  .000270   .318298  .000897  I  .7114668  .0002035  1.6175 0.1486  I    -7.111     .184      .186     .868   .326000   .319000   .7117000      .000      .000  
+83 730 45545.00 I   .319575  .000270   .314267  .000897  I  .7097910  .0001200  1.7284 0.1125  I    -6.616    1.982      .188     .868   .327000   .315000   .7101000      .000      .000  
+83 731 45546.00 I   .320531  .000247   .310123  .000903  I  .7080234  .0000962  1.7990 0.0883  I    -6.190    1.982      .250     .868   .328000   .311000   .7085000      .000      .000  
+83 8 1 45547.00 I   .321434  .000247   .305872  .000903  I  .7062103  .0001297  1.8178 0.0807  I    -6.177    1.982      .209     .868   .328000   .306000   .7067000      .000      .000  
+83 8 2 45548.00 I   .322273  .000247   .301533  .000903  I  .7044070  .0001297  1.7790 0.0800  I    -6.542    1.982     -.001     .868   .329000   .302000   .7050000      .000      .000  
+83 8 3 45549.00 I   .323036  .000945   .297129  .000334  I  .7026705  .0000937  1.6856 0.0800  I    -6.882    1.982     -.229     .868   .330000   .298000   .7033000      .000      .000  
+83 8 4 45550.00 I   .323703  .000945   .292676  .000334  I  .7010479  .0000937  1.5559 0.0663  I    -6.892    1.982     -.322     .868   .331000   .294000   .7017000      .000      .000  
+83 8 5 45551.00 I   .324245  .000945   .288185  .000334  I  .6995577  .0000937  1.4293 0.0792  I    -6.628    1.982     -.342     .868   .331000   .290000   .7003000      .000      .000  
+83 8 6 45552.00 I   .324630  .001304   .283662  .000274  I  .6981705  .0001278  1.3592 0.0572  I    -6.264    1.982     -.443     .868   .332000   .285000   .6989000      .000      .000  
+83 8 7 45553.00 I   .324867  .001395   .279123  .000493  I  .6968051  .0000656  1.3916 0.0718  I    -5.827     .210     -.602     .868   .332000   .281000   .6975000      .000      .000  
+83 8 8 45554.00 I   .325008  .001395   .274583  .000493  I  .6953489  .0000656  1.5391 0.0913  I    -5.313     .210     -.642     .868   .333000   .277000   .6960000      .000      .000  
+83 8 9 45555.00 I   .325109  .001481   .270061  .000642  I  .6936998  .0001704  1.7679 0.0707  I    -4.876     .210     -.522     .868   .333000   .273000   .6943000      .000      .000  
+83 810 45556.00 I   .325220  .001076   .265574  .000463  I  .6918090  .0001252  2.0091 0.1057  I    -4.724     .210     -.418     .868   .333000   .269000   .6923000      .000      .000  
+83 811 45557.00 I   .325345  .001076   .261129  .000463  I  .6897026  .0001252  2.1874 0.0885  I    -4.903     .210     -.461     .868   .333000   .264000   .6901000      .000      .000  
+83 812 45558.00 I   .325442  .001076   .256722  .000463  I  .6874726  .0001252  2.2505 0.0846  I    -5.306     .210     -.527     .868   .333000   .260000   .6878000      .000      .000  
+83 813 45559.00 I   .325463  .002327   .252350  .000924  I  .6852440  .0001139  2.1865 0.0846  I    -5.779    1.982     -.436     .868   .333000   .256000   .6854000      .000      .000  
+83 814 45560.00 I   .325347  .002327   .248012  .000924  I  .6831328  .0001139  2.0231 0.0610  I    -6.162    1.982     -.247     .868   .333000   .252000   .6832000      .000      .000  
+83 815 45561.00 I   .325027  .002287   .243710  .001216  I  .6812146  .0000435  1.8094 0.0607  I    -6.358    1.982     -.203     .868   .332000   .248000   .6812000      .000      .000  
+83 816 45562.00 I   .324439  .002790   .239444  .001487  I  .6795146  .0000421  1.5940 0.0303  I    -6.459    1.982     -.398     .868   .332000   .243000   .6794000      .000      .000  
+83 817 45563.00 I   .323570  .002790   .235203  .001487  I  .6780156  .0000421  1.4115 0.0512  I    -6.683    1.982     -.653     .868   .331000   .239000   .6778000      .000      .000  
+83 818 45564.00 I   .322552  .002285   .230949  .001487  I  .6766742  .0000933  1.2811 0.1399  I    -7.100    1.982     -.762     .868   .331000   .235000   .6764000      .000      .000  
+83 819 45565.00 I   .321508  .001576   .226648  .001653  I  .6754331  .0002767  1.2117 0.1460  I    -7.513    1.982     -.734     .868   .330000   .231000   .6751000      .000      .000  
+83 820 45566.00 I   .320461  .001576   .222306  .001653  I  .6742298  .0002767  1.2052 0.1973  I    -7.732    1.982     -.703     .868   .330000   .227000   .6739000      .000      .000  
+83 821 45567.00 I   .319418  .000555   .217934  .002690  I  .6730031  .0002814  1.2576 0.1973  I    -7.819    1.982     -.687     .868   .329000   .222000   .6726000      .000      .000  
+83 822 45568.00 I   .318373  .000555   .213545  .002690  I  .6716981  .0002814  1.3596 0.1990  I    -7.973    1.982     -.566     .868   .329000   .218000   .6713000      .000      .000  
+83 823 45569.00 I   .317312  .000555   .209152  .002690  I  .6702728  .0002814  1.4951 0.1725  I    -8.275    1.982     -.282     .868   .328000   .214000   .6698000      .000      .000  
+83 824 45570.00 I   .316217  .001200   .204768  .000753  I  .6687035  .0001995  1.6439 0.1481  I    -8.654    1.982      .039     .868   .327000   .210000   .6682000      .000      .000  
+83 825 45571.00 I   .315057  .001200   .200403  .000753  I  .6669878  .0000927  1.7845 0.1188  I    -9.026    1.982      .229     .868   .326000   .206000   .6665000      .000      .000  
+83 826 45572.00 I   .313769  .001200   .196072  .000753  I  .6651441  .0001292  1.8965 0.1000  I    -9.346    1.982      .270     .868   .324000   .201000   .6646000      .000      .000  
+83 827 45573.00 I   .312292  .001538   .191785  .000753  I  .6632099  .0001772  1.9632 0.0924  I    -9.614    1.982      .285     .868   .323000   .197000   .6627000      .000      .000  
+83 828 45574.00 I   .310611  .001111   .187543  .001035  I  .6612365  .0001320  1.9736 0.1105  I    -9.938    1.982      .341     .868   .322000   .193000   .6608000      .000      .000  
+83 829 45575.00 I   .308761  .001111   .183334  .001035  I  .6592822  .0001320  1.9256 0.0990  I   -10.500    1.982      .368     .868   .320000   .189000   .6590000      .000      .000  
+83 830 45576.00 I   .306780  .000322   .179145  .001254  I  .6574024  .0001477  1.8263 0.0857  I   -11.346    1.982      .286     .868   .319000   .185000   .6572000      .000      .000  
+83 831 45577.00 I   .304707  .000572   .174963  .001020  I  .6556410  .0001094  1.6927 0.0802  I   -12.265    1.982      .144     .868   .317000   .180000   .6556000      .000      .000  
+83 9 1 45578.00 I   .302568  .000572   .170795  .001020  I  .6540182  .0000624  1.5556 0.0601  I   -12.966    1.982      .058     .868   .316000   .176000   .6541000      .000      .000  
+83 9 2 45579.00 I   .300382  .000572   .166667  .001020  I  .6525168  .0000499  1.4575 0.0381  I   -13.323    1.982      .065     .868   .314000   .172000   .6528000      .000      .000  
+83 9 3 45580.00 I   .298158  .000742   .162606  .000711  I  .6510751  .0000436  1.4436 0.0778  I   -13.395    1.982      .129     .868   .312000   .168000   .6514000      .000      .000  
+83 9 4 45581.00 I   .295874  .001655   .158623  .001131  I  .6495919  .0001473  1.5427 0.0778  I   -13.328    1.982      .271     .868   .310000   .164000   .6501000      .000      .000  
+83 9 5 45582.00 I   .293495  .001655   .154721  .001131  I  .6479549  .0001494  1.7462 0.1130  I   -13.320    1.982      .558     .868   .308000   .159000   .6486000      .000      .000  
+83 9 6 45583.00 I   .290991  .001770   .150908  .001023  I  .6460815  .0001713  2.0036 0.1148  I   -13.546    1.982      .923     .868   .306000   .155000   .6468000      .000      .000  
+83 9 7 45584.00 I   .288340  .001622   .147183  .001320  I  .6439545  .0001744  2.2405 0.1222  I   -14.009    1.982     1.136     .868   .304000   .151000   .6448000      .000      .000  
+83 9 8 45585.00 I   .285620  .001622   .143517  .001320  I  .6416305  .0001744  2.3873 0.1233  I   -14.524    1.982     1.062     .868   .302000   .147000   .6425000      .000      .000  
+83 9 9 45586.00 I   .282932  .001622   .139868  .001320  I  .6392241  .0001744  2.4015 0.1177  I   -14.948    1.982      .868     .868   .300000   .143000   .6402000      .000      .000  
+83 910 45587.00 I   .280329  .001218   .136199  .001260  I  .6368703  .0001580  2.2872 0.1170  I   -15.305    1.982      .822     .868   .297000   .139000   .6380000      .000      .000  
+83 911 45588.00 I   .277835  .001218   .132485  .001260  I  .6346791  .0001561  2.0847 0.1016  I   -15.634    1.982      .936     .868   .295000   .135000   .6359000      .000      .000  
+83 912 45589.00 I   .275415  .000920   .128738  .001259  I  .6327116  .0001277  1.8499 0.0781  I   -15.836    1.982      .950     .868   .293000   .131000   .6340000      .000      .000  
+83 913 45590.00 I   .273024  .000249   .124983  .000181  I  .6309726  .0000052  1.6350 0.0795  I   -15.828    1.982      .695     .868   .290000   .127000   .6323000      .000      .000  
+83 914 45591.00 I   .270614  .000321   .121243  .000478  I  .6294242  .0000946  1.4724 0.0474  I   -15.706    1.982      .335     .868   .288000   .123000   .6308000      .000      .000  
+83 915 45592.00 I   .268140  .000321   .117541  .000478  I  .6280058  .0000946  1.3758 0.0669  I   -15.598    1.982      .157     .868   .285000   .120000   .6295000      .000      .000  
+83 916 45593.00 I   .265569  .000321   .113896  .000478  I  .6266502  .0000946  1.3463 0.0714  I   -15.453    1.982      .226     .868   .283000   .116000   .6282000      .000      .000  
+83 917 45594.00 I   .262872  .000321   .110324  .000478  I  .6252925  .0001069  1.3790 0.0724  I   -15.133    1.982      .358     .868   .280000   .112000   .6268000      .000      .000  
+83 918 45595.00 I   .260033  .000612   .106829  .000472  I  .6238741  .0001097  1.4662 0.0766  I   -14.655    1.982      .394     .868   .277000   .109000   .6254000      .000      .000  
+83 919 45596.00 I   .257047  .000612   .103408  .000472  I  .6223466  .0001097  1.5940 0.0637  I   -14.168    1.982      .371     .868   .274000   .105000   .6238000      .000      .000  
+83 920 45597.00 I   .253908  .000630   .100056  .000330  I  .6206790  .0000647  1.7432 0.1082  I   -13.710    1.982      .412     .868   .271000   .102000   .6221000      .000      .000  
+83 921 45598.00 I   .250619  .000630   .096769  .000330  I  .6188601  .0001866  1.8929 0.0987  I   -13.188     .720      .531     .234   .268000   .098000   .6202000      .000      .000  
+83 922 45599.00 I   .247218  .000630   .093546  .000330  I  .6169004  .0001866  2.0212 0.1301  I   -12.558     .720      .618     .234   .265000   .095000   .6181000      .000      .000  
+83 923 45600.00 I   .243752  .000630   .090388  .000330  I  .6148318  .0001814  2.1074 0.1305  I   -11.888     .720      .566     .234   .262000   .092000   .6159000      .000      .000  
+83 924 45601.00 I   .240255  .000546   .087290  .000334  I  .6127044  .0001825  2.1373 0.1287  I   -11.219     .720      .383     .234   .259000   .089000   .6136000      .000      .000  
+83 925 45602.00 I   .236747  .000546   .084238  .000334  I  .6105772  .0001825  2.1073 0.1346  I   -10.540     .720      .159     .234   .255000   .086000   .6112000      .000      .000  
+83 926 45603.00 I   .233246  .000564   .081217  .000958  I  .6085069  .0001978  2.0260 0.1025  I    -9.876     .722     -.035     .270   .252000   .083000   .6090000      .000      .000  
+83 927 45604.00 I   .229770  .000564   .078212  .000958  I  .6065357  .0000932  1.9133 0.1093  I    -9.313     .724     -.193     .301   .249000   .080000   .6069000      .000      .000  
+83 928 45605.00 I   .226324  .000564   .075212  .000958  I  .6046808  .0000930  1.7990 0.0610  I    -8.870     .724     -.335     .301   .245000   .077000   .6049000      .000      .000  
+83 929 45606.00 I   .222887  .000486   .072205  .000942  I  .6029261  .0000787  1.7195 0.0638  I    -8.422     .724     -.457     .301   .242000   .074000   .6031000      .000      .000  
+83 930 45607.00 I   .219443  .000387   .069196  .001148  I  .6012183  .0000874  1.7106 0.0588  I    -7.793     .724     -.523     .301   .238000   .072000   .6012000      .000      .000  
+8310 1 45608.00 I   .215995  .000387   .066215  .001148  I  .5994726  .0000874  1.7987 0.0493  I    -6.930     .724     -.475     .301   .235000   .069000   .5995000      .000      .000  
+8310 2 45609.00 I   .212552  .000191   .063299  .000780  I  .5975868  .0000456  1.9893 0.0488  I    -5.999    1.982     -.251     .868   .231000   .066000   .5976000      .000      .000  
+8310 3 45610.00 I   .209116  .000191   .060476  .000780  I  .5954696  .0000433  2.2533 0.0336  I    -5.303    1.982      .157     .868   .227000   .064000   .5955000      .000      .000  
+8310 4 45611.00 I   .205677  .000191   .057756  .000780  I  .5930760  .0000494  2.5298 0.0579  I    -5.058    1.982      .620     .868   .223000   .061000   .5931000      .000      .000  
+8310 5 45612.00 I   .202226  .000161   .055143  .000678  I  .5904304  .0001075  2.7449 0.0592  I    -5.177    1.982      .900     .868   .219000   .059000   .5905000      .000      .000  
+8310 6 45613.00 I   .198751  .000161   .052641  .000678  I  .5876271  .0001075  2.8371 0.0760  I    -5.331    1.982      .866     .868   .215000   .056000   .5878000      .000      .000  
+8310 7 45614.00 I   .195241  .000161   .050236  .000678  I  .5848052  .0001075  2.7822 0.0892  I    -5.286    1.982      .651     .868   .211000   .054000   .5851000      .000      .000  
+8310 8 45615.00 I   .191681  .000225   .047915  .000728  I  .5821044  .0001423  2.6020 0.0755  I    -5.122    1.982      .527     .868   .207000   .052000   .5825000      .000      .000  
+8310 9 45616.00 I   .188069  .000162   .045677  .000709  I  .5796249  .0001060  2.3506 0.0880  I    -5.047    1.982      .595     .868   .202000   .050000   .5800000      .000      .000  
+831010 45617.00 I   .184406  .000162   .043530  .000709  I  .5774064  .0001036  2.0897 0.0723  I    -5.099    1.982      .687     .868   .198000   .047000   .5779000      .000      .000  
+831011 45618.00 I   .180694  .000043   .041484  .000689  I  .5754327  .0000983  1.8674 0.0858  I    -5.137    1.982      .623     .124   .193000   .045000   .5760000      .000      .000  
+831012 45619.00 I   .176934  .000201   .039547  .000579  I  .5736494  .0001369  1.7118 0.0843  I    -5.069    1.982      .474     .124   .189000   .043000   .5742000      .000      .000  
+831013 45620.00 I   .173127  .000201   .037715  .000579  I  .5719840  .0001369  1.6317 0.0968  I    -4.933    1.982      .464     .124   .185000   .041000   .5726000      .000      .000  
+831014 45621.00 I   .169272  .000201   .035973  .000579  I  .5703624  .0001369  1.6225 0.1072  I    -4.785    1.982      .667     .124   .180000   .039000   .5710000      .000      .000  
+831015 45622.00 I   .165367  .000498   .034308  .000537  I  .5687185  .0001650  1.6748 0.1072  I    -4.643    1.982      .916     .124   .176000   .038000   .5693000      .000      .000  
+831016 45623.00 I   .161397  .000498   .032717  .000537  I  .5669967  .0001650  1.7755 0.1126  I    -4.559    1.982     1.020     .124   .171000   .036000   .5675000      .000      .000  
+831017 45624.00 I   .157343  .000498   .031201  .000537  I  .5651578  .0001534  1.9054 0.1116  I    -4.605    1.982      .984     .868   .167000   .034000   .5656000      .000      .000  
+831018 45625.00 I   .153187  .000483   .029760  .001069  I  .5631825  .0001502  2.0454 0.1093  I    -4.766    1.982      .977     .868   .163000   .033000   .5635000      .000      .000  
+831019 45626.00 I   .148934  .000483   .028382  .001069  I  .5610699  .0001556  2.1768 0.1004  I    -4.944    1.982     1.123     .868   .158000   .031000   .5612000      .000      .000  
+831020 45627.00 I   .144606  .000409   .027048  .000953  I  .5588385  .0001332  2.2796 0.1016  I    -5.109    1.982     1.374     .868   .154000   .030000   .5588000      .000      .000  
+831021 45628.00 I   .140224  .000206   .025746  .001083  I  .5565266  .0001306  2.3347 0.0933  I    -5.325    1.982     1.562     .868   .149000   .028000   .5563000      .000      .000  
+831022 45629.00 I   .135800  .000206   .024495  .001083  I  .5541889  .0001306  2.3303 0.0923  I    -5.613    1.982     1.561     .868   .145000   .027000   .5537000      .000      .000  
+831023 45630.00 I   .131340  .000206   .023320  .001083  I  .5518854  .0001306  2.2677 0.1070  I    -5.883    1.982     1.395     .868   .141000   .026000   .5513000      .000      .000  
+831024 45631.00 I   .126852  .000228   .022244  .000758  I  .5496675  .0001696  2.1631 0.0890  I    -6.047    1.982     1.211     .868   .136000   .025000   .5489000      .000      .000  
+831025 45632.00 I   .122332  .000249   .021273  .000737  I  .5475627  .0001208  2.0480 0.1110  I    -6.141    1.982     1.135     .868   .132000   .024000   .5467000      .000      .000  
+831026 45633.00 I   .117777  .000242   .020411  .000617  I  .5455610  .0001434  1.9645 0.0937  I    -6.246    1.982     1.169     .868   .127000   .023000   .5447000      .000      .000  
+831027 45634.00 I   .113183  .000242   .019661  .000617  I  .5436110  .0001434  1.9493 0.1014  I    -6.334    1.982     1.230     .868   .123000   .022000   .5427000      .000      .000  
+831028 45635.00 I   .108558  .000242   .019010  .000617  I  .5416323  .0001434  2.0245 0.1014  I    -6.275    1.982     1.268     .868   .118000   .021000   .5407000      .000      .000  
+831029 45636.00 I   .103917  .000242   .018434  .000617  I  .5395291  .0001434  2.1983 0.0897  I    -5.994    1.982     1.331     .868   .114000   .020000   .5386000      .000      .000  
+831030 45637.00 I   .099285  .000685   .017915  .000351  I  .5372094  .0001079  2.4511 0.0893  I    -5.605    1.982     1.503     .868   .109000   .020000   .5364000      .000      .000  
+831031 45638.00 I   .094682  .000685   .017444  .000351  I  .5346166  .0001064  2.7350 0.0681  I    -5.371    1.982     1.804     .868   .105000   .019000   .5339000      .000      .000  
+8311 1 45639.00 I   .090127  .001256   .017010  .000275  I  .5317491  .0000832  2.9898 0.0913  I    -5.491    1.982     2.140     .868   .100000   .018000   .5311000      .000      .000  
+8311 2 45640.00 I   .085635  .001256   .016605  .000275  I  .5286668  .0001485  3.1551 0.0910  I    -5.903    1.982     2.359     .868   .095000   .018000   .5282000      .000      .000  
+8311 3 45641.00 I   .081180  .001256   .016226  .000275  I  .5254822  .0001618  3.1904 0.1098  I    -6.312    1.982     2.371     .868   .091000   .018000   .5252000      .000      .000  
+8311 4 45642.00 I   .076707  .001256   .015875  .000275  I  .5223304  .0001618  3.0924 0.1374  I    -6.449    1.982     2.236     .868   .086000   .017000   .5222000      .000      .000  
+8311 5 45643.00 I   .072188  .001035   .015555  .000140  I  .5193312  .0002222  2.8928 0.1374  I    -6.303    1.982     2.120     .868   .082000   .017000   .5194000      .000      .000  
+8311 6 45644.00 I   .067650  .001035   .015274  .000140  I  .5165611  .0002222  2.6443 0.1574  I    -6.073    1.982     2.122     .868   .077000   .017000   .5167000      .000      .000  
+8311 7 45645.00 I   .063133  .000605   .015041  .000302  I  .5140408  .0002230  2.4013 0.1451  I    -5.911    1.982     2.184     .868   .073000   .017000   .5143000      .000      .000  
+8311 8 45646.00 I   .058673  .000605   .014863  .000302  I  .5117429  .0001868  2.2049 0.1419  I    -5.773    1.982     2.201     .868   .068000   .017000   .5121000      .000      .000  
+8311 9 45647.00 I   .054298  .000605   .014750  .000302  I  .5096069  .0001755  2.0806 0.1222  I    -5.517    1.982     2.193     .868   .064000   .018000   .5099000      .000      .000  
+831110 45648.00 I   .050016  .000631   .014711  .000904  I  .5075559  .0001576  2.0338 0.1000  I    -5.078    1.982     2.275     .868   .059000   .018000   .5079000      .000      .000  
+831111 45649.00 I   .045825  .000703   .014760  .001107  I  .5055162  .0000959  2.0562 0.0922  I    -4.537    1.982     2.479     .868   .055000   .018000   .5058000      .000      .000  
+831112 45650.00 I   .041690  .000703   .014919  .001107  I  .5034252  .0000959  2.1334 0.0751  I    -4.027    1.982     2.667     .868   .051000   .018000   .5037000      .000      .000  
+831113 45651.00 I   .037570  .000679   .015212  .001507  I  .5012379  .0001155  2.2452 0.0740  I    -3.631    1.982     2.698     .868   .046000   .018000   .5015000      .000      .000  
+831114 45652.00 I   .033436  .000724   .015651  .001011  I  .4989301  .0001128  2.3712 0.0808  I    -3.335    1.982     2.603     .868   .042000   .019000   .4991000      .000      .000  
+831115 45653.00 I   .029287  .000724   .016216  .001011  I  .4964974  .0001129  2.4915 0.0782  I    -3.084     .510     2.560     .284   .037000   .019000   .4966000      .000      .000  
+831116 45654.00 I   .025129  .000652   .016880  .000328  I  .4939555  .0001082  2.5867 0.0779  I    -2.850     .510     2.708     .284   .033000   .019000   .4940000      .000      .000  
+831117 45655.00 I   .020959  .000652   .017618  .000328  I  .4913389  .0001075  2.6373 0.0783  I    -2.642     .510     3.014     .284   .029000   .020000   .4913000      .000      .000  
+831118 45656.00 I   .016746  .000652   .018418  .000328  I  .4887009  .0001133  2.6279 0.0782  I    -2.452     .510     3.303     .284   .025000   .020000   .4887000      .000      .000  
+831119 45657.00 I   .012470  .000652   .019266  .000328  I  .4861057  .0001136  2.5508 0.0654  I    -2.233     .510     3.392     .284   .020000   .021000   .4861000      .000      .000  
+831120 45658.00 I   .008132  .000478   .020152  .000519  I  .4836202  .0000652  2.4109 0.0717  I    -1.918     .670     3.227     .305   .016000   .021000   .4836000      .000      .000  
+831121 45659.00 I   .003743  .000380   .021065  .000573  I  .4812962  .0000876  2.2341 0.0444  I    -1.491     .798     2.924     .325   .012000   .022000   .4812000      .000      .000  
+831122 45660.00 I  -.000682  .000397   .021994  .000661  I  .4791497  .0000604  2.0643 0.0531  I    -1.004     .798     2.688     .325   .008000   .023000   .4790000      .000      .000  
+831123 45661.00 I  -.005128  .000397   .022932  .000661  I  .4771491  .0000599  1.9501 0.0331  I     -.538     .798     2.643     .325   .004000   .024000   .4770000      .000      .000  
+831124 45662.00 I  -.009563  .000397   .023887  .000661  I  .4752188  .0000270  1.9281 0.0367  I     -.136     .798     2.751     .325  -.001000   .024000   .4749000      .000      .000  
+831125 45663.00 I  -.013953  .000397   .024877  .000661  I  .4732586  .0000425  2.0089 0.0258  I      .206     .798     2.886     .325  -.005000   .025000   .4729000      .000      .000  
+831126 45664.00 I  -.018277  .000472   .025911  .000445  I  .4711735  .0000439  2.1723 0.0901  I      .500    1.982     2.984     .868  -.009000   .026000   .4707000      .000      .000  
+831127 45665.00 I  -.022529  .000472   .026991  .000445  I  .4689010  .0001751  2.3749 0.1223  I      .717    1.982     3.070     .868  -.013000   .027000   .4684000      .000      .000  
+831128 45666.00 I  -.026704  .000480   .028118  .000421  I  .4664286  .0002407  2.5628 0.1265  I      .771    1.982     3.192     .868  -.017000   .028000   .4659000      .000      .000  
+831129 45667.00 I  -.030799  .000587   .029291  .000575  I  .4637977  .0001827  2.6839 0.1511  I      .573    1.982     3.349     .868  -.021000   .030000   .4633000      .000      .000  
+831130 45668.00 I  -.034830  .000587   .030504  .000575  I  .4610947  .0001827  2.7034 0.1286  I      .138     .371     3.504     .868  -.025000   .031000   .4606000      .000      .000  
+8312 1 45669.00 I  -.038822  .000587   .031742  .000575  I  .4584273  .0001809  2.6136 0.1806  I     -.374     .371     3.619     .868  -.029000   .032000   .4579000      .000      .000  
+8312 2 45670.00 I  -.042803  .000524   .032994  .000495  I  .4558981  .0003115  2.4319 0.1610  I     -.740     .371     3.696     .868  -.033000   .033000   .4554000      .000      .000  
+8312 3 45671.00 I  -.046774  .000524   .034259  .000495  I  .4535817  .0002663  2.1956 0.2049  I     -.826     .371     3.762     .868  -.036000   .035000   .4531000      .000      .000  
+8312 4 45672.00 I  -.050719  .000524   .035547  .000495  I  .4515093  .0002663  1.9520 0.1881  I     -.682     .371     3.829     .868  -.040000   .036000   .4511000      .000      .000  
+8312 5 45673.00 I  -.054619  .000447   .036867  .000332  I  .4496656  .0002657  1.7448 0.1881  I     -.472     .371     3.872     .868  -.043000   .038000   .4493000      .000      .000  
+8312 6 45674.00 I  -.058443  .000447   .038228  .000332  I  .4479977  .0002657  1.6036 0.1716  I     -.302    1.982     3.875     .868  -.047000   .039000   .4476000      .000      .000  
+8312 7 45675.00 I  -.062153  .000487   .039638  .000873  I  .4464330  .0002172  1.5387 0.1354  I     -.132    1.982     3.890     .868  -.050000   .041000   .4461000      .000      .000  
+8312 8 45676.00 I  -.065717  .000558   .041105  .001068  I  .4448954  .0000522  1.5484 0.1302  I      .122    1.982     3.994     .868  -.054000   .042000   .4446000      .000      .000  
+8312 9 45677.00 I  -.069128  .000558   .042651  .001068  I  .4433152  .0001438  1.6211 0.0765  I      .432    1.982     4.171     .868  -.057000   .044000   .4431000      .000      .000  
+831210 45678.00 I  -.072386  .000558   .044297  .001068  I  .4416385  .0001438  1.7379 0.0987  I      .678    1.982     4.300     .868  -.061000   .045000   .4414000      .000      .000  
+831211 45679.00 I  -.075499  .000546   .046056  .001059  I  .4398322  .0001353  1.8764 0.0987  I      .821    1.982     4.289     .868  -.064000   .047000   .4395000      .000      .000  
+831212 45680.00 I  -.078500  .000546   .047907  .001059  I  .4378858  .0001353  2.0145 0.1043  I      .948    1.982     4.206     .868  -.067000   .049000   .4375000      .000      .000  
+831213 45681.00 I  -.081426  .000484   .049824  .000522  I  .4358100  .0001589  2.1320 0.1045  I     1.109    1.982     4.207     .868  -.070000   .051000   .4354000      .000      .000  
+831214 45682.00 I  -.084310  .000484   .051784  .000522  I  .4336338  .0001592  2.2133 0.0909  I     1.200    1.982     4.376     .868  -.074000   .052000   .4331000      .000      .000  
+831215 45683.00 I  -.087163  .000484   .053773  .000522  I  .4313994  .0000885  2.2466 0.0922  I     1.110    1.982     4.663     .868  -.077000   .054000   .4307000      .000      .000  
+831216 45684.00 I  -.089984  .000484   .055779  .000522  I  .4291600  .0000929  2.2219 0.0668  I      .904    1.982     4.956     .868  -.080000   .056000   .4284000      .000      .000  
+831217 45685.00 I  -.092784  .000988   .057796  .000774  I  .4269767  .0001000  2.1340 0.0682  I      .748    1.982     5.139     .868  -.083000   .058000   .4261000      .000      .000  
+831218 45686.00 I  -.095588  .000988   .059831  .000774  I  .4249091  .0001000  1.9946 0.0667  I      .708    1.982     5.107     .868  -.086000   .060000   .4240000      .000      .000  
+831219 45687.00 I  -.098428  .000964   .061893  .000745  I  .4229931  .0000882  1.8382 0.0664  I      .744    1.982     4.827     .868  -.089000   .062000   .4219000      .000      .000  
+831220 45688.00 I  -.101331  .000964   .063991  .000745  I  .4212216  .0000875  1.7151 0.0621  I      .883     .207     4.420     .234  -.092000   .064000   .4201000      .000      .000  
+831221 45689.00 I  -.104285  .000964   .066120  .000745  I  .4195351  .0000874  1.6754 0.0591  I     1.220     .207     4.106     .234  -.095000   .066000   .4183000      .000      .000  
+831222 45690.00 I  -.107234  .000817   .068258  .000743  I  .4178346  .0000796  1.7443 0.0607  I     1.725     .207     4.012     .234  -.098000   .068000   .4165000      .000      .000  
+831223 45691.00 I  -.110135  .000447   .070392  .000658  I  .4160138  .0000843  1.9115 0.0580  I     2.184     .207     4.053     .234  -.101000   .070000   .4147000      .000      .000  
+831224 45692.00 I  -.112977  .000447   .072525  .000658  I  .4139933  .0000843  2.1338 0.0665  I     2.392     .207     4.045     .234  -.103000   .072000   .4125000      .000      .000  
+831225 45693.00 I  -.115751  .000249   .074659  .000635  I  .4117490  .0001028  2.3478 0.0683  I     2.331     .207     3.903     .234  -.106000   .074000   .4102000      .000      .000  
+831226 45694.00 I  -.118457  .000287   .076816  .000885  I  .4093198  .0001076  2.4954 0.0744  I     2.113    1.982     3.682     .868  -.109000   .076000   .4078000      .000      .000  
+831227 45695.00 I  -.121102  .000287   .079021  .000885  I  .4067917  .0001077  2.5423 0.0835  I     1.810    1.982     3.480     .868  -.112000   .078000   .4053000      .000      .000  
+831228 45696.00 I  -.123689  .000298   .081302  .000891  I  .4042707  .0001278  2.4825 0.0836  I     1.414    1.982     3.336     .868  -.114000   .080000   .4029000      .000      .000  
+831229 45697.00 I  -.126226  .000298   .083687  .000891  I  .4018558  .0001278  2.3352 0.0904  I      .937    1.982     3.242     .868  -.117000   .083000   .4005000      .000      .000  
+831230 45698.00 I  -.128720  .000298   .086194  .000891  I  .3996181  .0001278  2.1346 0.0820  I      .478    1.982     3.184     .868  -.119000   .085000   .3984000      .000      .000  
+831231 45699.00 I  -.131198  .000298   .088822  .000891  I  .3975912  .0001028  1.9204 0.0774  I      .198    1.982     3.150     .868  -.122000   .087000   .3966000      .000      .000  
+84 1 1 45700.00 I  -.133693  .001671   .091556  .000915  I  .3957700  .0000875  1.7282 0.0674  I      .182    1.982     3.101     .868  -.125000   .089000   .3950000      .000      .000  
+84 1 2 45701.00 I  -.136248  .001671   .094364  .000915  I  .3941189  .0000873  1.5837 0.0540  I      .347     .791     2.996     .298  -.127000   .092000   .3937000      .000      .000  
+84 1 3 45702.00 I  -.138908  .001885   .097214  .001002  I  .3925820  .0000633  1.5009 0.0521  I      .515     .791     2.862     .298  -.130000   .091000   .3928000      .000      .000  
+84 1 4 45703.00 I  -.141713  .001538   .100076  .000736  I  .3910960  .0000568  1.4813 0.0425  I      .586     .791     2.816     .298  -.132000   .094000   .3908000      .000      .000  
+84 1 5 45704.00 I  -.144634  .001538   .102933  .000736  I  .3896011  .0000568  1.5168 0.0402  I      .598     .791     2.975     .298  -.135000   .099000   .3900000      .000      .000  
+84 1 6 45705.00 I  -.147567  .001538   .105787  .000736  I  .3880487  .0000568  1.5936 0.0380  I      .606     .791     3.323     .298  -.137000   .102000   .3886000      .000      .000  
+84 1 7 45706.00 I  -.150445  .000712   .108641  .000327  I  .3864062  .0000506  1.6935 0.0362  I      .619     .791     3.691     .298  -.140000   .104000   .3871000      .000      .000  
+84 1 8 45707.00 I  -.153237  .000804   .111497  .000278  I  .3846611  .0000450  1.7951 0.0324  I      .701     .791     3.943     .298  -.142000   .107000   .3854000      .000      .000  
+84 1 9 45708.00 I  -.155921  .000698   .114358  .000261  I  .3828226  .0000406  1.8770 0.0398  I      .998     .111     4.102     .298  -.145000   .110000   .3836000      .000      .000  
+84 110 45709.00 I  -.158475  .000772   .117229  .000521  I  .3809185  .0000657  1.9246 0.0389  I     1.545     .111     4.239     .298  -.147000   .113000   .3816000      .000      .000  
+84 111 45710.00 I  -.160879  .000772   .120116  .000521  I  .3789884  .0000663  1.9273 0.0467  I     2.145     .111     4.321     .298  -.150000   .116000   .3797000      .000      .000  
+84 112 45711.00 I  -.163135  .000834   .123034  .000517  I  .3770820  .0000663  1.8757 0.0459  I     2.564     .111     4.283     .298  -.152000   .119000   .3777000      .000      .000  
+84 113 45712.00 I  -.165270  .000920   .125996  .000535  I  .3752552  .0000636  1.7694 0.0805  I     2.823     .119     4.147     .298  -.154000   .122000   .3757000      .000      .000  
+84 114 45713.00 I  -.167340  .000871   .128998  .000709  I  .3735584  .0001467  1.6176 0.0799  I     3.075     .126     4.000     .298  -.157000   .125000   .3739000      .000      .000  
+84 115 45714.00 I  -.169412  .000871   .132027  .000709  I  .3720280  .0001467  1.4419 0.0947  I     3.274     .126     3.828     .298  -.159000   .128000   .3722000      .000      .000  
+84 116 45715.00 I  -.171529  .000709   .135077  .000742  I  .3706685  .0001198  1.2844 0.0940  I     3.245     .126     3.487     .298  -.161000   .131000   .3707000      .000      .000  
+84 117 45716.00 I  -.173696  .000709   .138154  .000742  I  .3694355  .0001177  1.1979 0.0809  I     3.103     .126     2.931     .298  -.164000   .134000   .3693000      .000      .000  
+84 118 45717.00 I  -.175913  .000035   .141261  .000872  I  .3682349  .0001088  1.2247 0.0801  I     3.236     .126     2.387     .298  -.166000   .138000   .3679000      .000      .000  
+84 119 45718.00 I  -.178181  .000035   .144398  .000872  I  .3669465  .0001088  1.3704 0.0780  I     3.792     .791     2.171     .298  -.168000   .141000   .3664000      .000      .000  
+84 120 45719.00 I  -.180499  .000035   .147546  .000872  I  .3654672  .0001119  1.5968 0.1337  I     4.429     .791     2.340     .298  -.171000   .144000   .3648000      .000      .000  
+84 121 45720.00 I  -.182868  .000035   .150678  .000872  I  .3637489  .0002443  1.8351 0.0879  I     4.676     .791     2.656     .298  -.173000   .147000   .3629000      .000      .000  
+84 122 45721.00 I  -.185285  .000652   .153776  .000605  I  .3618180  .0001355  2.0104 0.1298  I     4.420     .791     2.896     .298  -.175000   .150000   .3609000      .000      .000  
+84 123 45722.00 I  -.187747  .000576   .156841  .000501  I  .3597665  .0000880  2.0706 0.0808  I     3.921     .791     3.067     .298  -.177000   .153000   .3589000      .000      .000  
+84 124 45723.00 I  -.190250  .000624   .159874  .000315  I  .3577188  .0000879  2.0048 0.0622  I     3.467     .791     3.301     .298  -.180000   .157000   .3567000      .000      .000  
+84 125 45724.00 I  -.192791  .000624   .162876  .000315  I  .3557903  .0000879  1.8388 0.0619  I     3.155     .791     3.642     .298  -.182000   .160000   .3548000      .000      .000  
+84 126 45725.00 I  -.195341  .000624   .165856  .000315  I  .3540603  .0000873  1.6153 0.0467  I     2.967     .791     4.032     .298  -.184000   .163000   .3530000      .000      .000  
+84 127 45726.00 I  -.197857  .000603   .168829  .000302  I  .3525635  .0000316  1.3803 0.0476  I     2.892     .791     4.395     .298  -.186000   .166000   .3515000      .000      .000  
+84 128 45727.00 I  -.200310  .000434   .171811  .000261  I  .3512901  .0000382  1.1742 0.0294  I     3.013     .121     4.698     .298  -.189000   .169000   .3501000      .000      .000  
+84 129 45728.00 I  -.202689  .000468   .174810  .000301  I  .3501969  .0000497  1.0227 0.0321  I     3.459     .165     4.876     .298  -.191000   .173000   .3490000      .000      .000  
+84 130 45729.00 I  -.204988  .000474   .177835  .000320  I  .3492225  .0000517  0.9377 0.0352  I     4.264     .165     4.798     .298  -.193000   .176000   .3481000      .000      .000  
+84 131 45730.00 I  -.207201  .000425   .180895  .000889  I  .3482974  .0000499  0.9250 0.0347  I     5.271     .165     4.396     .298  -.195000   .179000   .3472000      .000      .000  
+84 2 1 45731.00 I  -.209302  .000487   .184010  .000856  I  .3473493  .0000464  0.9820 0.0407  I     6.169     .165     3.835     .298  -.197000   .183000   .3464000      .000      .000  
+84 2 2 45732.00 I  -.211263  .000694   .187209  .000841  I  .3463147  .0000642  1.0953 0.0496  I     6.729     .380     3.352     .298  -.200000   .186000   .3457000      .000      .000  
+84 2 3 45733.00 I  -.213058  .000813   .190510  .001115  I  .3451465  .0000876  1.2454 0.0543  I     6.862     .511     3.040     .298  -.202000   .189000   .3446000      .000      .000  
+84 2 4 45734.00 I  -.214671  .000813   .193897  .001115  I  .3438190  .0000876  1.4102 0.0619  I     6.524     .511     2.835     .298  -.204000   .193000   .3434000      .000      .000  
+84 2 5 45735.00 I  -.216102  .000813   .197345  .001115  I  .3423294  .0000876  1.5649 0.0657  I     5.700     .511     2.706     .298  -.206000   .196000   .3420000      .000      .000  
+84 2 6 45736.00 I  -.217398  .000838   .200842  .001302  I  .3407013  .0000980  1.6832 0.0644  I     4.621     .511     2.704     .298  -.208000   .200000   .3404000      .000      .000  
+84 2 7 45737.00 I  -.218614  .000911   .204396  .001220  I  .3389802  .0000943  1.7498 0.0691  I     3.543     .571     2.888     .298  -.210000   .203000   .3387000      .000      .000  
+84 2 8 45738.00 I  -.219801  .000740   .208015  .001808  I  .3372199  .0000975  1.7617 0.0663  I     2.534     .626     3.189     .298  -.212000   .207000   .3370000      .000      .000  
+84 2 9 45739.00 I  -.221010  .000740   .211703  .001808  I  .3354758  .0000933  1.7168 0.0685  I     1.682     .626     3.454     .298  -.214000   .210000   .3354000      .000      .000  
+84 210 45740.00 I  -.222283  .000740   .215418  .001808  I  .3338026  .0000962  1.6232 0.0661  I     1.311     .626     3.656     .298  -.216000   .214000   .3337000      .000      .000  
+84 211 45741.00 I  -.223623  .000791   .219088  .001758  I  .3322386  .0000937  1.5020 0.0625  I     1.545     .626     3.921     .298  -.217000   .217000   .3322000      .000      .000  
+84 212 45742.00 I  -.225009  .000927   .222662  .001651  I  .3307985  .0000798  1.3809 0.0674  I     2.123     .534     4.256     .298  -.219000   .221000   .3307000      .000      .000  
+84 213 45743.00 I  -.226395  .000748   .226137  .001946  I  .3294628  .0000968  1.3017 0.0679  I     2.619     .423     4.401     .298  -.221000   .225000   .3294000      .000      .000  
+84 214 45744.00 I  -.227735  .000913   .229512  .001604  I  .3281652  .0001100  1.3121 0.0773  I     2.911     .423     4.101     .298  -.223000   .228000   .3281000      .000      .000  
+84 215 45745.00 I  -.228996  .000691   .232798  .001413  I  .3267982  .0001206  1.4436 0.0687  I     3.276     .423     3.457     .298  -.224000   .232000   .3268000      .000      .000  
+84 216 45746.00 I  -.230184  .000651   .236043  .001426  I  .3252405  .0000823  1.6876 0.0699  I     3.991     .423     2.879     .298  -.226000   .236000   .3252000      .000      .000  
+84 217 45747.00 I  -.231313  .000291   .239301  .001397  I  .3234042  .0000708  1.9881 0.0677  I     4.812     .315     2.613     .298  -.227000   .239000   .3234000      .000      .000  
+84 218 45748.00 I  -.232399  .000440   .242625  .001108  I  .3212741  .0001076  2.2593 0.0644  I     5.195     .140     2.518     .298  -.229000   .243000   .3213000      .000      .000  
+84 219 45749.00 I  -.233470  .000440   .246041  .001108  I  .3189226  .0001076  2.4195 0.0761  I     4.947     .140     2.357     .298  -.230000   .247000   .3190000      .000      .000  
+84 220 45750.00 I  -.234563  .000440   .249561  .001108  I  .3164862  .0001076  2.4263 0.0656  I     4.377     .140     2.144     .298  -.231000   .250000   .3167000      .000      .000  
+84 221 45751.00 I  -.235703  .000396   .253172  .001015  I  .3141195  .0000752  2.2845 0.0654  I     3.871     .140     2.033     .298  -.233000   .254000   .3144000      .000      .000  
+84 222 45752.00 I  -.236884  .000361   .256861  .001018  I  .3119521  .0000744  2.0379 0.0644  I     3.602     .615     2.053     .298  -.234000   .258000   .3123000      .000      .000  
+84 223 45753.00 I  -.238091  .000393   .260612  .000772  I  .3100573  .0001045  1.7504 0.0593  I     3.549    1.090     2.085     .100  -.235000   .261000   .3105000      .000      .000  
+84 224 45754.00 I  -.239304  .000214   .264417  .000864  I  .3084469  .0000924  1.4762 0.0697  I     3.615    1.090     2.083     .100  -.236000   .265000   .3089000      .000      .000  
+84 225 45755.00 I  -.240498  .000214   .268293  .000864  I  .3070853  .0000924  1.2607 0.0694  I     3.700    1.090     2.145     .100  -.237000   .269000   .3075000      .000      .000  
+84 226 45756.00 I  -.241649  .000346   .272247  .000772  I  .3058959  .0001036  1.1341 0.0705  I     3.473    1.090     2.222     .100  -.238000   .273000   .3063000      .000      .000  
+84 227 45757.00 I  -.242735  .000404   .276271  .000588  I  .3047850  .0001065  1.1038 0.0936  I     3.065     .924     2.233     .298  -.238000   .277000   .3051000      .000      .000  
+84 228 45758.00 I  -.243735  .000505   .280348  .000358  I  .3036583  .0001558  1.1634 0.0821  I     2.748     .956     2.146     .298  -.239000   .280000   .3039000      .000      .000  
+84 229 45759.00 I  -.244627  .001082   .284464  .000348  I  .3024328  .0001251  1.2990 0.0992  I     2.557     .460     2.054     .298  -.240000   .284000   .3026000      .000      .000  
+84 3 1 45760.00 I  -.245397  .001082   .288604  .000348  I  .3010452  .0001228  1.4798 0.0796  I     2.482     .460     2.132     .298  -.241000   .288000   .3011000      .000      .000  
+84 3 2 45761.00 I  -.246066  .001240   .292756  .000428  I  .2994704  .0000983  1.6690 0.0737  I     2.507     .460     2.395     .298  -.241000   .292000   .2996000      .000      .000  
+84 3 3 45762.00 I  -.246663  .001315   .296911  .000448  I  .2977127  .0000816  1.8419 0.0685  I     2.658     .347     2.659     .298  -.241000   .296000   .2978000      .000      .000  
+84 3 4 45763.00 I  -.247186  .001483   .301065  .000415  I  .2957984  .0000953  1.9796 0.0627  I     2.971     .170     2.740     .298  -.242000   .300000   .2959000      .000      .000  
+84 3 5 45764.00 I  -.247564  .001483   .305215  .000415  I  .2937702  .0000953  2.0671 0.0675  I     3.409     .170     2.639     .298  -.242000   .304000   .2939000      .000      .000  
+84 3 6 45765.00 I  -.247740  .001431   .309367  .000454  I  .2916832  .0000956  2.0974 0.0648  I     3.855     .170     2.468     .298  -.242000   .308000   .2919000      .000      .000  
+84 3 7 45766.00 I  -.247738  .001409   .313525  .000369  I  .2895946  .0000879  2.0701 0.0632  I     4.170     .170     2.284     .298  -.242000   .312000   .2899000      .000      .000  
+84 3 8 45767.00 I  -.247545  .001359   .317689  .000353  I  .2875612  .0000828  1.9883 0.0771  I     4.258     .121     2.043     .298  -.242000   .316000   .2880000      .000      .000  
+84 3 9 45768.00 I  -.247117  .001390   .321851  .000256  I  .2856316  .0001267  1.8659 0.0511  I     4.195     .791     1.769     .298  -.241000   .320000   .2861000      .000      .000  
+84 310 45769.00 I  -.246412  .001014   .326007  .000431  I  .2838347  .0000600  1.7277 0.0701  I     4.164     .791     1.629     .298  -.241000   .324000   .2844000      .000      .000  
+84 311 45770.00 I  -.245453  .001014   .330153  .000431  I  .2821681  .0000600  1.6139 0.0385  I     4.182     .791     1.733     .298  -.240000   .328000   .2827000      .000      .000  
+84 312 45771.00 I  -.244301  .001366   .334287  .000376  I  .2805828  .0000483  1.5725 0.0348  I     4.088     .791     1.910     .298  -.240000   .332000   .2811000      .000      .000  
+84 313 45772.00 I  -.243017  .001325   .338411  .000602  I  .2789864  .0000351  1.6411 0.0280  I     3.894     .143     1.892     .159  -.239000   .336000   .2795000      .000      .000  
+84 314 45773.00 I  -.241646  .001446   .342540  .000659  I  .2772601  .0000283  1.8313 0.0198  I     3.940     .176     1.660     .199  -.239000   .340000   .2777000      .000      .000  
+84 315 45774.00 I  -.240224  .001446   .346696  .000659  I  .2752929  .0000183  2.1141 0.0276  I     4.510     .176     1.460     .199  -.238000   .344000   .2757000      .000      .000  
+84 316 45775.00 I  -.238804  .001672   .350899  .000642  I  .2730242  .0000475  2.4200 0.0240  I     5.415     .176     1.448     .199  -.237000   .347000   .2733000      .000      .000  
+84 317 45776.00 I  -.237426  .001540   .355140  .000594  I  .2704742  .0000444  2.6621 0.0321  I     6.114     .176     1.493     .199  -.236000   .351000   .2706000      .000      .000  
+84 318 45777.00 I  -.236099  .001073   .359395  .000609  I  .2677449  .0000433  2.7697 0.0412  I     6.267     .963     1.367     .162  -.235000   .355000   .2677000      .000      .000  
+84 319 45778.00 I  -.234833  .000504   .363640  .000346  I  .2649881  .0000694  2.7176 0.0464  I     5.933    1.350     1.060     .113  -.234000   .359000   .2649000      .000      .000  
+84 320 45779.00 I  -.233638  .000504   .367852  .000346  I  .2623533  .0000820  2.5348 0.0567  I     5.325    1.350      .756     .113  -.233000   .363000   .2621000      .000      .000  
+84 321 45780.00 I  -.232516  .001037   .372008  .000403  I  .2599421  .0000898  2.2812 0.0523  I     4.562    1.350      .530     .113  -.231000   .367000   .2596000      .000      .000  
+84 322 45781.00 I  -.231434  .000996   .376092  .000507  I  .2577934  .0000649  2.0200 0.0545  I     3.727    1.350      .259     .113  -.230000   .371000   .2574000      .000      .000  
+84 323 45782.00 I  -.230332  .000908   .380098  .000475  I  .2558878  .0000617  1.8017 0.0495  I     2.824     .972     -.121     .220  -.228000   .375000   .2554000      .000      .000  
+84 324 45783.00 I  -.229142  .001034   .384027  .000547  I  .2541670  .0000747  1.6523 0.0574  I     1.819     .257     -.434     .290  -.227000   .379000   .2536000      .000      .000  
+84 325 45784.00 I  -.227828  .001019   .387876  .000520  I  .2525587  .0000968  1.5763 0.0580  I      .843     .257     -.457     .290  -.225000   .383000   .2520000      .000      .000  
+84 326 45785.00 I  -.226424  .001019   .391632  .000520  I  .2509899  .0000888  1.5736 0.0629  I      .230     .257     -.167     .290  -.223000   .387000   .2503000      .000      .000  
+84 327 45786.00 I  -.224943  .000382   .395303  .000553  I  .2493888  .0000803  1.6388 0.0597  I      .162     .257      .266     .290  -.221000   .390000   .2487000      .000      .000  
+84 328 45787.00 I  -.223387  .000382   .398901  .000553  I  .2476965  .0000799  1.7515 0.0991  I      .455     .257      .734     .290  -.219000   .394000   .2469000      .000      .000  
+84 329 45788.00 I  -.221753  .000192   .402445  .000510  I  .2458792  .0001811  1.8841 0.1014  I      .741     .791     1.270     .298  -.218000   .398000   .2450000      .000      .000  
+84 330 45789.00 I  -.220027  .000192   .405961  .000510  I  .2439299  .0001863  2.0119 0.0953  I      .859     .791     1.874     .298  -.216000   .402000   .2430000      .000      .000  
+84 331 45790.00 I  -.218203  .000167   .409467  .000497  I  .2418646  .0000596  2.1122 0.0960  I      .942     .791     2.386     .298  -.213000   .406000   .2409000      .000      .000  
+84 4 1 45791.00 I  -.216277  .000369   .412970  .000787  I  .2397213  .0000461  2.1650 0.0353  I     1.186     .791     2.587     .298  -.211000   .410000   .2386000      .000      .000  
+84 4 2 45792.00 I  -.214248  .000673   .416473  .000865  I  .2375544  .0000377  2.1583 0.0412  I     1.668     .116     2.395     .298  -.209000   .414000   .2363000      .000      .000  
+84 4 3 45793.00 I  -.212116  .000791   .419980  .001333  I  .2354255  .0000682  2.0893 0.0383  I     2.373     .116     1.886     .298  -.206000   .417000   .2341000      .000      .000  
+84 4 4 45794.00 I  -.209885  .000791   .423499  .001333  I  .2333936  .0000667  1.9670 0.0517  I     3.241     .116     1.144     .298  -.204000   .421000   .2320000      .000      .000  
+84 4 5 45795.00 I  -.207558  .000791   .427047  .001333  I  .2315025  .0000776  1.8116 0.0557  I     4.171     .116      .165     .298  -.202000   .425000   .2301000      .000      .000  
+84 4 6 45796.00 I  -.205116  .000828   .430657  .001285  I  .2297717  .0000893  1.6522 0.0563  I     5.044     .116     -.964     .298  -.199000   .428000   .2283000      .000      .000  
+84 4 7 45797.00 I  -.202564  .000936   .434329  .001211  I  .2281875  .0000817  1.5245 0.0689  I     5.821     .247    -2.041     .298  -.197000   .432000   .2268000      .000      .000  
+84 4 8 45798.00 I  -.199927  .000914   .438042  .001183  I  .2267002  .0001049  1.4644 0.0729  I     6.491     .330    -2.846     .114  -.195000   .436000   .2252000      .000      .000  
+84 4 9 45799.00 I  -.197234  .000940   .441776  .000921  I  .2252257  .0001207  1.5032 0.0805  I     6.949     .330    -3.227     .114  -.192000   .439000   .2238000      .000      .000  
+84 410 45800.00 I  -.194512  .000940   .445521  .000921  I  .2236558  .0001221  1.6559 0.0833  I     7.063     .330    -3.109     .114  -.190000   .443000   .2222000      .000      .000  
+84 411 45801.00 I  -.191747  .000878   .449274  .000963  I  .2218794  .0001148  1.9121 0.0768  I     6.909     .330    -2.583     .114  -.187000   .446000   .2204000      .000      .000  
+84 412 45802.00 I  -.188910  .000824   .453024  .000984  I  .2198122  .0000933  2.2264 0.0836  I     6.623     .349    -1.726     .114  -.185000   .450000   .2184000      .000      .000  
+84 413 45803.00 I  -.186018  .000629   .456733  .001073  I  .2174328  .0001216  2.5220 0.0770  I     6.224     .367     -.678     .113  -.182000   .453000   .2161000      .000      .000  
+84 414 45804.00 I  -.183103  .000629   .460348  .001073  I  .2148017  .0001224  2.7172 0.0803  I     5.713     .367      .222     .113  -.179000   .457000   .2136000      .000      .000  
+84 415 45805.00 I  -.180195  .000231   .463824  .000725  I  .2120503  .0001050  2.7566 0.0736  I     5.247     .367      .592     .113  -.177000   .460000   .2109000      .000      .000  
+84 416 45806.00 I  -.177307  .000309   .467156  .000706  I  .2093423  .0000816  2.6344 0.0580  I     4.967     .367      .474     .113  -.174000   .463000   .2084000      .000      .000  
+84 417 45807.00 I  -.174447  .000774   .470354  .000769  I  .2068199  .0000493  2.3969 0.0574  I     4.911     .809      .194     .219  -.171000   .466000   .2061000      .000      .000  
+84 418 45808.00 I  -.171620  .000899   .473431  .000726  I  .2045618  .0000808  2.1195 0.0430  I     5.012    1.044     -.006     .271  -.168000   .469000   .2039000      .000      .000  
+84 419 45809.00 I  -.168823  .000899   .476398  .000726  I  .2025697  .0000705  1.8759 0.0536  I     5.125    1.044     -.070     .271  -.165000   .473000   .2020000      .000      .000  
+84 420 45810.00 I  -.166061  .000899   .479278  .000726  I  .2007854  .0000704  1.7062 0.0484  I     5.088    1.044      .016     .271  -.162000   .475000   .2003000      .000      .000  
+84 421 45811.00 I  -.163372  .000905   .482112  .000731  I  .1991292  .0000662  1.6208 0.0475  I     5.144    1.044      .005     .271  -.159000   .479000   .1987000      .000      .000  
+84 422 45812.00 I  -.160723  .000936   .484922  .000740  I  .1975172  .0000638  1.6153 0.0549  I     5.455     .957     -.128     .231  -.156000   .481000   .1970000      .000      .000  
+84 423 45813.00 I  -.158061  .001071   .487723  .000472  I  .1958781  .0000875  1.6712 0.0402  I     5.953     .951     -.199     .194  -.153000   .484000   .1953000      .000      .000  
+84 424 45814.00 I  -.155331  .000641   .490533  .000480  I  .1941616  .0000489  1.7665 0.0499  I     6.565     .650     -.198     .298  -.150000   .488000   .1936000      .000      .000  
+84 425 45815.00 I  -.152483  .000641   .493366  .000480  I  .1923383  .0000482  1.8820 0.0326  I     6.994     .761     -.115     .298  -.146000   .490000   .1917000      .000      .000  
+84 426 45816.00 I  -.149499  .000549   .496226  .000477  I  .1903968  .0000432  1.9998 0.0306  I     7.055     .761      .066     .298  -.143000   .493000   .1898000      .000      .000  
+84 427 45817.00 I  -.146378  .000598   .499108  .000487  I  .1883442  .0000378  2.1009 0.0307  I     6.831     .688      .348     .298  -.140000   .496000   .1876000      .000      .000  
+84 428 45818.00 I  -.143112  .000309   .502004  .000338  I  .1862065  .0000435  2.1673 0.0273  I     6.676     .707      .616     .298  -.136000   .499000   .1854000      .000      .000  
+84 429 45819.00 I  -.139694  .000309   .504907  .000338  I  .1840258  .0000393  2.1851 0.0359  I     6.677     .707      .723     .298  -.133000   .501000   .1832000      .000      .000  
+84 430 45820.00 I  -.136117  .000374   .507802  .000566  I  .1818567  .0000571  2.1417 0.0366  I     6.634     .707      .603     .298  -.129000   .504000   .1810000      .000      .000  
+84 5 1 45821.00 I  -.132404  .000374   .510670  .000566  I  .1797638  .0000617  2.0341 0.0444  I     6.501     .521      .310     .298  -.126000   .506000   .1788000      .000      .000  
+84 5 2 45822.00 I  -.128584  .000563   .513487  .000626  I  .1778052  .0000681  1.8765 0.0609  I     6.311     .521     -.013     .298  -.122000   .509000   .1767000      .000      .000  
+84 5 3 45823.00 I  -.124685  .000857   .516235  .000741  I  .1760190  .0001050  1.6944 0.0620  I     6.039     .791     -.240     .298  -.119000   .511000   .1749000      .000      .000  
+84 5 4 45824.00 I  -.120721  .000857   .518909  .000741  I  .1744128  .0001036  1.5232 0.0736  I     5.620     .791     -.352     .298  -.115000   .514000   .1732000      .000      .000  
+84 5 5 45825.00 I  -.116696  .000857   .521516  .000741  I  .1729556  .0001031  1.4031 0.0628  I     5.087     .791     -.411     .298  -.112000   .516000   .1717000      .000      .000  
+84 5 6 45826.00 I  -.112618  .000835   .524062  .000475  I  .1715775  .0000711  1.3702 0.0594  I     4.643     .791     -.481     .298  -.108000   .518000   .1703000      .000      .000  
+84 5 7 45827.00 I  -.108541  .000895   .526540  .000422  I  .1701798  .0000589  1.4436 0.0440  I     4.535     .250     -.569     .171  -.104000   .521000   .1689000      .000      .000  
+84 5 8 45828.00 I  -.104534  .000873   .528942  .000373  I  .1686564  .0000519  1.6186 0.0460  I     4.848     .250     -.625     .171  -.101000   .523000   .1673000      .000      .000  
+84 5 9 45829.00 I  -.100665  .000806   .531257  .000295  I  .1669190  .0000706  1.8643 0.0592  I     5.448     .250     -.578     .171  -.097000   .525000   .1655000      .000      .000  
+84 510 45830.00 I  -.096980  .000806   .533468  .000295  I  .1649239  .0001065  2.1218 0.0601  I     6.096     .250     -.386     .171  -.094000   .527000   .1635000      .000      .000  
+84 511 45831.00 I  -.093484  .000857   .535562  .000330  I  .1626958  .0000973  2.3181 0.0692  I     6.529     .250     -.088     .171  -.090000   .529000   .1612000      .000      .000  
+84 512 45832.00 I  -.090126  .000861   .537536  .000351  I  .1603279  .0000883  2.3936 0.0734  I     6.635     .325      .192     .178  -.086000   .531000   .1587000      .000      .000  
+84 513 45833.00 I  -.086832  .000810   .539392  .000396  I  .1579581  .0001100  2.3205 0.0733  I     6.526     .386      .329     .186  -.083000   .533000   .1563000      .000      .000  
+84 514 45834.00 I  -.083528  .000737   .541130  .000408  I  .1557314  .0001171  2.1138 0.0744  I     6.352     .386      .310     .186  -.079000   .535000   .1541000      .000      .000  
+84 515 45835.00 I  -.080144  .000670   .542753  .000339  I  .1537564  .0001002  1.8293 0.0637  I     6.125     .386      .229     .186  -.075000   .537000   .1521000      .000      .000  
+84 516 45836.00 I  -.076659  .000688   .544280  .000343  I  .1520742  .0000503  1.5404 0.0557  I     5.837     .386      .153     .186  -.071000   .538000   .1504000      .000      .000  
+84 517 45837.00 I  -.073068  .000773   .545737  .000735  I  .1506565  .0000488  1.3086 0.0382  I     5.497     .522      .028     .134  -.067000   .540000   .1490000      .000      .000  
+84 518 45838.00 I  -.069372  .000812   .547148  .000804  I  .1494269  .0000575  1.1669 0.0375  I     5.139     .629     -.219     .298  -.064000   .542000   .1477000      .000      .000  
+84 519 45839.00 I  -.065593  .000812   .548539  .000804  I  .1482916  .0000569  1.1185 0.0406  I     4.810     .629     -.520     .298  -.060000   .544000   .1466000      .000      .000  
+84 520 45840.00 I  -.061753  .000812   .549930  .000804  I  .1471636  .0000572  1.1489 0.0374  I     4.588     .629     -.705     .298  -.056000   .545000   .1454000      .000      .000  
+84 521 45841.00 I  -.057842  .000767   .551303  .000815  I  .1459754  .0000487  1.2344 0.0364  I     4.521     .629     -.714     .298  -.052000   .546000   .1442000      .000      .000  
+84 522 45842.00 I  -.053862  .000893   .552630  .000787  I  .1446855  .0000449  1.3479 0.0349  I     4.632     .705     -.650     .298  -.048000   .548000   .1429000      .000      .000  
+84 523 45843.00 I  -.049830  .000803   .553883  .000425  I  .1432785  .0000499  1.4648 0.0305  I     4.820     .774     -.620     .298  -.044000   .549000   .1416000      .000      .000  
+84 524 45844.00 I  -.045764  .000793   .555039  .000445  I  .1417625  .0000413  1.5620 0.0340  I     4.832     .774     -.590     .298  -.040000   .550000   .1401000      .000      .000  
+84 525 45845.00 I  -.041679  .000793   .556087  .000445  I  .1401662  .0000463  1.6240 0.0333  I     4.443     .774     -.459     .298  -.036000   .552000   .1385000      .000      .000  
+84 526 45846.00 I  -.037550  .000745   .557031  .000428  I  .1385293  .0000522  1.6417 0.0336  I     3.700     .774     -.213     .298  -.032000   .553000   .1368000      .000      .000  
+84 527 45847.00 I  -.033346  .000963   .557886  .000765  I  .1368996  .0000488  1.6089 0.0409  I     2.843     .591      .023     .298  -.028000   .554000   .1352000      .000      .000  
+84 528 45848.00 I  -.029063  .000865   .558661  .000818  I  .1353285  .0000631  1.5249 0.0395  I     2.126     .315      .099     .298  -.024000   .555000   .1337000      .000      .000  
+84 529 45849.00 I  -.024702  .000946   .559368  .000991  I  .1338643  .0000622  1.3973 0.0451  I     1.736     .315     -.034     .298  -.020000   .556000   .1322000      .000      .000  
+84 530 45850.00 I  -.020261  .000861   .560019  .000901  I  .1325442  .0000644  1.2389 0.0414  I     1.760     .315     -.289     .298  -.016000   .557000   .1310000      .000      .000  
+84 531 45851.00 I  -.015736  .000784   .560616  .000824  I  .1313877  .0000546  1.0769 0.0393  I     2.069     .315     -.516     .298  -.012000   .557000   .1299000      .000      .000  
+84 6 1 45852.00 I  -.011164  .000661   .561137  .000700  I  .1303775  .0000450  0.9537 0.0403  I     2.429     .333     -.606     .298  -.007000   .558000   .1289000      .000      .000  
+84 6 2 45853.00 I  -.006584  .000375   .561557  .000428  I  .1294549  .0000594  0.9068 0.0360  I     2.681     .350     -.562     .298  -.003000   .559000   .1280000      .000      .000  
+84 6 3 45854.00 I  -.002004  .000375   .561867  .000428  I  .1285322  .0000562  0.9552 0.0434  I     2.810     .350     -.462     .298   .001000   .559000   .1272000      .000      .000  
+84 6 4 45855.00 I   .002574  .000375   .562062  .000428  I  .1275139  .0000633  1.0956 0.0390  I     2.870     .350     -.354     .298   .005000   .560000   .1262000      .000      .000  
+84 6 5 45856.00 I   .007150  .000282   .562137  .000244  I  .1263199  .0000540  1.2994 0.0407  I     2.931     .350     -.229     .298   .009000   .560000   .1250000      .000      .000  
+84 6 6 45857.00 I   .011713  .000288   .562095  .000238  I  .1249107  .0000512  1.5165 0.0486  I     2.935     .293     -.057     .551   .014000   .560000   .1236000      .000      .000  
+84 6 7 45858.00 I   .016250  .000380   .561940  .000202  I  .1233020  .0000808  1.6885 0.0589  I     2.720     .223      .139     .778   .018000   .560000   .1220000      .000      .000  
+84 6 8 45859.00 I   .020744  .000652   .561678  .000281  I  .1215661  .0001060  1.7633 0.0665  I     2.185     .223      .264     .778   .022000   .560000   .1203000      .000      .000  
+84 6 9 45860.00 I   .025167  .000652   .561321  .000281  I  .1198165  .0001056  1.7147 0.0678  I     1.416     .223      .209     .778   .026000   .560000   .1185000      .000      .000  
+84 610 45861.00 I   .029479  .000526   .560886  .000441  I  .1181750  .0000846  1.5513 0.0649  I      .642     .223     -.027     .778   .030000   .560000   .1169000      .000      .000  
+84 611 45862.00 I   .033651  .000595   .560392  .000571  I  .1167397  .0000755  1.3106 0.0636  I      .129     .506     -.356     .690   .035000   .560000   .1154000      .000      .000  
+84 612 45863.00 I   .037698  .000634   .559870  .000680  I  .1155606  .0000949  1.0494 0.0581  I      .024     .679     -.653     .588   .039000   .560000   .1142000      .000      .000  
+84 613 45864.00 I   .041648  .000630   .559352  .000595  I  .1146282  .0000884  0.8261 0.0550  I      .278     .679     -.799     .588   .043000   .560000   .1132000      .000      .000  
+84 614 45865.00 I   .045528  .000467   .558866  .000641  I  .1138831  .0000558  0.6787 0.0501  I      .686     .679     -.800     .588   .047000   .559000   .1125000      .000      .000  
+84 615 45866.00 I   .049374  .000533   .558416  .000569  I  .1132413  .0000471  0.6200 0.0344  I     1.028     .679     -.827     .588   .052000   .559000   .1118000      .000      .000  
+84 616 45867.00 I   .053228  .000711   .557996  .000563  I  .1126155  .0000401  0.6442 0.0334  I     1.229     .575     -.861     .421   .056000   .558000   .1112000      .000      .000  
+84 617 45868.00 I   .057118  .000775   .557597  .000272  I  .1119315  .0000473  0.7325 0.0278  I     1.293     .448     -.847     .298   .060000   .558000   .1105000      .000      .000  
+84 618 45869.00 I   .061049  .000775   .557210  .000272  I  .1111373  .0000384  0.8605 0.0274  I     1.249     .448     -.799     .298   .064000   .557000   .1097000      .000      .000  
+84 619 45870.00 I   .065011  .000824   .556822  .000312  I  .1102061  .0000275  1.0018 0.0243  I     1.124     .448     -.817     .298   .069000   .556000   .1088000      .000      .000  
+84 620 45871.00 I   .068961  .000944   .556410  .000475  I  .1091371  .0000299  1.1329 0.0270  I      .980     .448     -.935     .298   .073000   .555000   .1077000      .000      .000  
+84 621 45872.00 I   .072888  .000886   .555944  .000440  I  .1079499  .0000464  1.2352 0.0405  I      .849     .958    -1.046     .167   .077000   .555000   .1066000      .000      .000  
+84 622 45873.00 I   .076789  .000955   .555397  .000557  I  .1066807  .0000752  1.2953 0.0437  I      .654    1.279    -1.009     .219   .081000   .554000   .1053000      .000      .000  
+84 623 45874.00 I   .080672  .000808   .554742  .000625  I  .1053753  .0000740  1.3073 0.0532  I      .256    1.279     -.800     .219   .086000   .553000   .1041000      .000      .000  
+84 624 45875.00 I   .084588  .000808   .553970  .000625  I  .1040846  .0000754  1.2639 0.0495  I     -.363    1.279     -.521     .219   .090000   .552000   .1029000      .000      .000  
+84 625 45876.00 I   .088574  .000919   .553073  .000580  I  .1028675  .0000658  1.1605 0.0492  I     -.993    1.279     -.319     .219   .094000   .551000   .1017000      .000      .000  
+84 626 45877.00 I   .092657  .000791   .552046  .000377  I  .1017801  .0000633  1.0074 0.0503  I    -1.337    1.223     -.268     .164   .098000   .549000   .1006000      .000      .000  
+84 627 45878.00 I   .096871  .000826   .550896  .000421  I  .1008610  .0000760  0.8293 0.0461  I    -1.273    1.165     -.359     .298   .102000   .548000   .0998000      .000      .000  
+84 628 45879.00 I   .101258  .000957   .549641  .000433  I  .1001166  .0000671  0.6659 0.0512  I     -.893    1.165     -.549     .298   .107000   .547000   .0991000      .000      .000  
+84 629 45880.00 I   .105838  .001070   .548297  .000287  I  .0995091  .0000685  0.5627 0.0470  I     -.328    1.165     -.761     .298   .111000   .546000   .0986000      .000      .000  
+84 630 45881.00 I   .110541  .000967   .546878  .000287  I  .0989598  .0000657  0.5538 0.0457  I      .317    1.165     -.897     .298   .115000   .544000   .0981000      .000      .000  
+84 7 1 45882.00 I   .115262  .000814   .545401  .000256  I  .0983676  .0000604  0.6466 0.0484  I      .940    1.001     -.925     .298   .119000   .543000   .0975000      .000      .000  
+84 7 2 45883.00 I   .119923  .000701   .543875  .000300  I  .0976423  .0000710  0.8123 0.0392  I     1.377     .804     -.895     .298   .123000   .541000   .0967000      .000      .000  
+84 7 3 45884.00 I   .124503  .000701   .542301  .000300  I  .0967379  .0000501  0.9932 0.0471  I     1.422     .804     -.855     .298   .128000   .540000   .0957000      .000      .000  
+84 7 4 45885.00 I   .128981  .000284   .540676  .000360  I  .0956692  .0000618  1.1340 0.0375  I      .940     .804     -.777     .298   .132000   .538000   .0946000      .000      .000  
+84 7 5 45886.00 I   .133340  .000404   .538990  .000311  I  .0944962  .0000557  1.1958 0.0438  I      .045     .804     -.625     .298   .136000   .536000   .0932000      .000      .000  
+84 7 6 45887.00 I   .137574  .000526   .537225  .000437  I  .0933116  .0000621  1.1557 0.0451  I    -1.071    1.211     -.404     .189   .140000   .535000   .0919000      .000      .000  
+84 7 7 45888.00 I   .141680  .000673   .535361  .000562  I  .0922166  .0000709  1.0201 0.0482  I    -2.249    1.423     -.166     .245   .145000   .533000   .0907000      .000      .000  
+84 7 8 45889.00 I   .145664  .000601   .533389  .000529  I  .0912929  .0000737  0.8198 0.0511  I    -3.299    1.423      .021     .245   .149000   .531000   .0897000      .000      .000  
+84 7 9 45890.00 I   .149545  .000601   .531308  .000529  I  .0905856  .0000737  0.5937 0.0490  I    -3.991    1.423      .091     .245   .153000   .529000   .0889000      .000      .000  
+84 710 45891.00 I   .153348  .000587   .529131  .000651  I  .0900997  .0000646  0.3849 0.0468  I    -4.274    1.423      .014     .245   .157000   .527000   .0884000      .000      .000  
+84 711 45892.00 I   .157110  .000551   .526879  .000668  I  .0897970  .0000577  0.2324 0.0439  I    -4.148    1.105     -.212     .223   .161000   .525000   .0881000      .000      .000  
+84 712 45893.00 I   .160862  .000330   .524579  .000742  I  .0896094  .0000594  0.1565 0.0414  I    -3.775     .182     -.546     .187   .165000   .523000   .0880000      .000      .000  
+84 713 45894.00 I   .164632  .000330   .522263  .000742  I  .0894579  .0000594  0.1589 0.0449  I    -3.430     .182     -.882     .187   .169000   .521000   .0878000      .000      .000  
+84 714 45895.00 I   .168441  .000362   .519958  .000714  I  .0892686  .0000674  0.2305 0.0420  I    -3.330     .182    -1.071     .187   .173000   .518000   .0877000      .000      .000  
+84 715 45896.00 I   .172283  .000505   .517656  .000661  I  .0889796  .0000593  0.3542 0.0422  I    -3.470     .182    -1.037     .187   .177000   .516000   .0874000      .000      .000  
+84 716 45897.00 I   .176152  .000446   .515337  .000729  I  .0885517  .0000507  0.5035 0.0415  I    -3.744     .172     -.851     .132   .181000   .514000   .0870000      .000      .000  
+84 717 45898.00 I   .180041  .000577   .512981  .000366  I  .0879727  .0000580  0.6525 0.0365  I    -4.050     .161     -.669     .298   .185000   .511000   .0865000      .000      .000  
+84 718 45899.00 I   .183948  .000577   .510566  .000366  I  .0872532  .0000526  0.7821 0.0464  I    -4.238     .161     -.566     .298   .189000   .509000   .0858000      .000      .000  
+84 719 45900.00 I   .187878  .000536   .508072  .000708  I  .0864211  .0000725  0.8739 0.0442  I    -4.150     .149     -.465     .298   .193000   .507000   .0850000      .000      .000  
+84 720 45901.00 I   .191806  .000536   .505497  .000707  I  .0855229  .0000711  0.9131 0.0508  I    -3.888     .130     -.259     .298   .197000   .504000   .0842000      .000      .000  
+84 721 45902.00 I   .195733  .000536   .502847  .000707  I  .0846132  .0000711  0.8974 0.0609  I    -3.829     .130      .007     .298   .201000   .502000   .0834000      .000      .000  
+84 722 45903.00 I   .199670  .000477   .500128  .000832  I  .0837447  .0000990  0.8318 0.0620  I    -4.258     .791      .174     .298   .204000   .499000   .0826000      .000      .000  
+84 723 45904.00 I   .203624  .000413   .497351  .000935  I  .0829616  .0001016  0.7302 0.0709  I    -5.006     .791      .163     .298   .208000   .496000   .0819000      .000      .000  
+84 724 45905.00 I   .207573  .000413   .494543  .000935  I  .0822899  .0001016  0.6118 0.0735  I    -5.582     .791      .027     .298   .212000   .494000   .0813000      .000      .000  
+84 725 45906.00 I   .211481  .000481   .491731  .001050  I  .0817349  .0001061  0.5029 0.0534  I    -5.734     .791     -.150     .298   .215000   .491000   .0808000      .000      .000  
+84 726 45907.00 I   .215311  .000821   .488936  .000509  I  .0812672  .0000332  0.4448 0.0561  I    -5.627     .506     -.379     .489   .219000   .488000   .0804000      .000      .000  
+84 727 45908.00 I   .219051  .000743   .486154  .000467  I  .0808141  .0000363  0.4802 0.0252  I    -5.503     .506     -.684     .489   .223000   .485000   .0801000      .000      .000  
+84 728 45909.00 I   .222688  .000809   .483378  .000147  I  .0802680  .0000379  0.6321 0.0290  I    -5.402     .417     -.991     .439   .226000   .483000   .0796000      .000      .000  
+84 729 45910.00 I   .226221  .000787   .480603  .000226  I  .0795154  .0000453  0.8874 0.0275  I    -5.267     .417    -1.153     .439   .230000   .479000   .0789000      .000      .000  
+84 730 45911.00 I   .229681  .000767   .477813  .000285  I  .0784771  .0000398  1.1908 0.0286  I    -5.078     .417     -.887     .439   .233000   .476000   .0780000      .000      .000  
+84 731 45912.00 I   .233082  .000724   .474988  .000321  I  .0771460  .0000349  1.4575 0.0267  I    -5.046     .542     -.715     .342   .236000   .473000   .0768000      .000      .000  
+84 8 1 45913.00 I   .236413  .000584   .472105  .000381  I  .0755994  .0000357  1.6124 0.0267  I    -5.231     .565     -.787     .176   .240000   .470000   .0753000      .000      .000  
+84 8 2 45914.00 I   .239692  .000370   .469146  .000344  I  .0739710  .0000405  1.6181 0.0262  I    -5.508     .515     -.933     .161   .243000   .467000   .0737000      .000      .000  
+84 8 3 45915.00 I   .242944  .000551   .466103  .000484  I  .0724111  .0000383  1.4801 0.0273  I    -5.788     .592     -.954     .298   .246000   .464000   .0722000      .000      .000  
+84 8 4 45916.00 I   .246165  .000556   .462984  .000571  I  .0710446  .0000365  1.2407 0.0256  I    -6.044     .840     -.811     .185   .249000   .461000   .0708000      .000      .000  
+84 8 5 45917.00 I   .249335  .000543   .459789  .000560  I  .0699438  .0000341  0.9591 0.0268  I    -6.298     .996     -.586     .220   .252000   .458000   .0695000      .000      .000  
+84 8 6 45918.00 I   .252427  .000553   .456515  .000564  I  .0691185  .0000392  0.7011 0.0258  I    -6.455    1.122     -.274     .263   .255000   .454000   .0686000      .000      .000  
+84 8 7 45919.00 I   .255424  .000556   .453164  .000533  I  .0685157  .0000388  0.5207 0.0272  I    -6.273    1.122      .211     .263   .258000   .451000   .0679000      .000      .000  
+84 8 8 45920.00 I   .258353  .000556   .449761  .000533  I  .0680443  .0000378  0.4388 0.0316  I    -6.014    1.278      .447     .294   .261000   .448000   .0674000      .000      .000  
+84 8 9 45921.00 I   .261229  .000753   .446324  .000711  I  .0676057  .0000498  0.4541 0.0358  I    -5.757    1.278      .300     .294   .264000   .444000   .0669000      .000      .000  
+84 810 45922.00 I   .264070  .000677   .442875  .000615  I  .0671077  .0000607  0.5545 0.0479  I    -5.544     .921     -.069     .236   .266000   .441000   .0666000      .000      .000  
+84 811 45923.00 I   .266901  .000813   .439437  .000718  I  .0664755  .0000819  0.7186 0.0510  I    -5.493     .385     -.405     .194   .269000   .438000   .0660000      .000      .000  
+84 812 45924.00 I   .269751  .000813   .436036  .000718  I  .0656580  .0000819  0.9204 0.0663  I    -5.615     .385     -.498     .194   .272000   .434000   .0652000      .000      .000  
+84 813 45925.00 I   .272629  .000818   .432674  .000749  I  .0646337  .0001043  1.1252 0.0560  I    -5.804     .385     -.337     .194   .274000   .431000   .0642000      .000      .000  
+84 814 45926.00 I   .275486  .000727   .429332  .000693  I  .0634174  .0000764  1.3005 0.0601  I    -5.989     .385     -.125     .194   .276000   .427000   .0631000      .000      .000  
+84 815 45927.00 I   .278259  .000678   .425990  .000514  I  .0620488  .0000596  1.4273 0.0493  I    -6.126     .908     -.019     .212   .279000   .424000   .0619000      .000      .000  
+84 816 45928.00 I   .280889  .000312   .422626  .000500  I  .0605835  .0000622  1.4919 0.0431  I    -6.173    1.225      .040     .229   .281000   .420000   .0605000      .000      .000  
+84 817 45929.00 I   .283325  .000312   .419206  .000500  I  .0590876  .0000622  1.4889 0.0440  I    -6.253    1.225      .169     .229   .283000   .417000   .0591000      .000      .000  
+84 818 45930.00 I   .285528  .000312   .415699  .000500  I  .0576264  .0000622  1.4240 0.0447  I    -6.727    1.225      .311     .229   .285000   .413000   .0578000      .000      .000  
+84 819 45931.00 I   .287484  .000327   .412093  .000452  I  .0562564  .0000641  1.3088 0.0459  I    -7.793    1.225      .277     .229   .287000   .410000   .0565000      .000      .000  
+84 820 45932.00 I   .289188  .000370   .408397  .000433  I  .0550201  .0000674  1.1596 0.0588  I    -9.128    1.042      .015     .289   .289000   .406000   .0552000      .000      .000  
+84 821 45933.00 I   .290636  .000409   .404617  .000298  I  .0539412  .0000986  0.9985 0.0496  I   -10.055     .819     -.290     .339   .291000   .403000   .0541000      .000      .000  
+84 822 45934.00 I   .291826  .000646   .400762  .000402  I  .0530166  .0000729  0.8571 0.0618  I   -10.135     .819     -.452     .339   .293000   .399000   .0531000      .000      .000  
+84 823 45935.00 I   .292763  .000646   .396846  .000402  I  .0522015  .0000746  0.7923 0.0491  I    -9.488     .749     -.505     .286   .295000   .395000   .0521000      .000      .000  
+84 824 45936.00 I   .293494  .000855   .392898  .000372  I  .0513881  .0000658  0.8593 0.0474  I    -8.615     .749     -.559     .286   .297000   .392000   .0511000      .000      .000  
+84 825 45937.00 I   .294091  .000860   .388946  .000500  I  .0504355  .0000585  1.0687 0.0359  I    -7.887     .894     -.571     .283   .298000   .388000   .0499000      .000      .000  
+84 826 45938.00 I   .294653  .000954   .385010  .000524  I  .0492161  .0000289  1.3821 0.0326  I    -7.502     .942     -.390     .235   .300000   .384000   .0485000      .000      .000  
+84 827 45939.00 I   .295269  .000954   .381094  .000524  I  .0476622  .0000289  1.7228 0.0157  I    -7.558     .824     -.050     .212   .301000   .380000   .0468000      .000      .000  
+84 828 45940.00 I   .295999  .000598   .377203  .000502  I  .0457925  .0000122  1.9976 0.0151  I    -7.946     .827      .174     .199   .303000   .377000   .0448000      .000      .000  
+84 829 45941.00 I   .296808  .000574   .373365  .000490  I  .0437138  .0000091  2.1321 0.0085  I    -8.531     .877      .097     .219   .304000   .373000   .0426000      .000      .000  
+84 830 45942.00 I   .297631  .000579   .369631  .000475  I  .0415824  .0000119  2.1042 0.0064  I    -9.160    1.224     -.179     .205   .305000   .369000   .0404000      .000      .000  
+84 831 45943.00 I   .298357  .000367   .366043  .000423  I  .0395489  .0000089  1.9456 0.0074  I    -9.733    1.262     -.343     .139   .307000   .365000   .0384000      .000      .000  
+84 9 1 45944.00 I   .298912  .000367   .362592  .000423  I  .0377174  .0000089  1.7082 0.0063  I   -10.120    1.262     -.286     .139   .308000   .362000   .0367000      .000      .000  
+84 9 2 45945.00 I   .299411  .000325   .359180  .000427  I  .0361407  .0000090  1.4460 0.0074  I    -9.912    1.405     -.294     .146   .309000   .358000   .0353000      .000      .000  
+84 9 3 45946.00 I   .299981  .000327   .355697  .000346  I  .0348172  .0000118  1.2084 0.0094  I    -9.420    1.543     -.451     .152   .310000   .354000   .0341000      .000      .000  
+84 9 4 45947.00 I   .300693  .000302   .352060  .000375  I  .0337007  .0000165  1.0405 0.0097  I    -9.152    1.250     -.597     .153   .311000   .350000   .0330000      .000      .000  
+84 9 5 45948.00 I   .301537  .000380   .348292  .000425  I  .0327062  .0000153  0.9628 0.0113  I    -9.011     .801     -.637     .133   .312000   .346000   .0321000      .000      .000  
+84 9 6 45949.00 I   .302483  .000380   .344438  .000425  I  .0317496  .0000153  0.9618 0.0252  I    -8.773     .594     -.620     .154   .313000   .342000   .0312000      .000      .000  
+84 9 7 45950.00 I   .303491  .000732   .340541  .000565  I  .0307616  .0000481  1.0240 0.0242  I    -8.330     .594     -.622     .154   .313000   .338000   .0302000      .000      .000  
+84 9 8 45951.00 I   .304482  .000639   .336627  .000503  I  .0296857  .0000459  1.1341 0.0305  I    -7.829     .594     -.574     .154   .314000   .334000   .0291000      .000      .000  
+84 9 9 45952.00 I   .305408  .000598   .332703  .000457  I  .0284850  .0000374  1.2694 0.0284  I    -7.469     .479     -.330     .160   .314000   .331000   .0279000      .000      .000  
+84 910 45953.00 I   .306254  .000631   .328765  .000411  I  .0271466  .0000336  1.4057 0.0296  I    -7.296     .327      .104     .166   .315000   .327000   .0266000      .000      .000  
+84 911 45954.00 I   .307012  .000467   .324806  .000190  I  .0256802  .0000458  1.5224 0.0284  I    -7.257     .327      .526     .166   .315000   .323000   .0251000      .000      .000  
+84 912 45955.00 I   .307671  .000467   .320822  .000190  I  .0241161  .0000458  1.5964 0.0326  I    -7.313     .327      .762     .166   .316000   .319000   .0236000      .000      .000  
+84 913 45956.00 I   .308251  .000495   .316811  .000433  I  .0225070  .0000463  1.6116 0.0326  I    -7.402     .327      .844     .166   .316000   .315000   .0220000      .000      .000  
+84 914 45957.00 I   .308790  .000495   .312776  .000433  I  .0209113  .0000463  1.5714 0.0462  I    -7.512     .300      .922     .269   .316000   .311000   .0206000      .000      .000  
+84 915 45958.00 I   .309318  .000660   .308721  .000581  I  .0193787  .0000800  1.4876 0.0462  I    -7.751     .269     1.025     .343   .317000   .307000   .0192000      .000      .000  
+84 916 45959.00 I   .309831  .000660   .304651  .000581  I  .0179451  .0000800  1.3767 0.0483  I    -8.202     .269     1.015     .343   .317000   .303000   .0179000      .000      .000  
+84 917 45960.00 I   .310317  .000533   .300575  .000744  I  .0166281  .0000540  1.2574 0.0826  I    -8.658     .269      .826     .343   .317000   .299000   .0168000      .000      .000  
+84 918 45961.00 I   .310782  .000630   .296516  .000644  I  .0154253  .0001445  1.1532 0.0661  I    -8.740     .269      .627     .343   .317000   .295000   .0157000      .000      .000  
+84 919 45962.00 I   .311226  .000623   .292500  .000651  I  .0143055  .0001206  1.0976 0.0968  I    -8.267     .266      .637     .272   .317000   .291000   .0147000      .000      .000  
+84 920 45963.00 I   .311631  .000529   .288546  .000455  I  .0132022  .0001288  1.1255 0.0901  I    -7.486     .260      .851     .298   .317000   .288000   .0137000      .000      .000  
+84 921 45964.00 I   .311986  .000562   .284672  .000503  I  .0120182  .0001340  1.2621 0.0929  I    -6.863     .260     1.096     .298   .317000   .284000   .0126000      .000      .000  
+84 922 45965.00 I   .312306  .000562   .280886  .000503  I  .0106403  .0001340  1.5117 0.0848  I    -6.709     .260     1.288     .298   .317000   .280000   .0112000      .000      .000  
+84 923 45966.00 I   .312596  .000475   .277175  .000506  I  .0089703  .0001038  1.8347 0.0722  I    -7.026     .260     1.483     .298   .317000   .276000   .0095000      .000      .000  
+84 924 45967.00 I   .312847  .000368   .273513  .000497  I  .0069740  .0000537  2.1483 0.0573  I    -7.703     .236     1.659     .287   .317000   .272000   .0075000      .000      .000  
+84 925 45968.00 I   .313046  .000305   .269870  .000409  I  .0047065  .0000487  2.3634 0.0373  I    -8.540     .223     1.623     .361   .316000   .268000   .0052000      .000      .000  
+84 926 45969.00 I   .313180  .000420   .266215  .000388  I  .0022988  .0000519  2.4238 0.0356  I    -9.191     .223     1.280     .361   .316000   .265000   .0028000      .000      .000  
+84 927 45970.00 I   .313234  .000420   .262524  .000388  I -.0000854  .0000519  2.3173 0.0349  I    -9.381     .223      .844     .361   .315000   .261000   .0004000      .000      .000  
+84 928 45971.00 I   .313173  .000387   .258798  .000357  I -.0022935  .0000468  2.0839 0.0341  I    -9.212     .223      .631     .361   .315000   .257000  -.0017000      .000      .000  
+84 929 45972.00 I   .312953  .000435   .255048  .000355  I -.0042383  .0000441  1.8059 0.0302  I    -8.964    1.208      .665     .256   .314000   .253000  -.0037000      .000      .000  
+84 930 45973.00 I   .312541  .000490   .251287  .000203  I -.0059163  .0000382  1.5610 0.0292  I    -8.751    1.694      .678     .298   .314000   .249000  -.0052000      .000      .000  
+8410 1 45974.00 I   .311931  .000490   .247524  .000203  I -.0073872  .0000382  1.3967 0.0254  I    -8.525    1.694      .506     .298   .313000   .246000  -.0066000      .000      .000  
+8410 2 45975.00 I   .311122  .000435   .243769  .000231  I -.0087419  .0000336  1.3291 0.0239  I    -8.289    1.694      .320     .298   .312000   .242000  -.0079000      .000      .000  
+8410 3 45976.00 I   .310139  .000355   .240020  .000347  I -.0100752  .0000286  1.3510 0.0209  I    -8.079    1.694      .362     .298   .311000   .238000  -.0091000      .000      .000  
+8410 4 45977.00 I   .309014  .000401   .236272  .000342  I -.0114658  .0000249  1.4387 0.0217  I    -7.847    1.259      .627     .298   .311000   .234000  -.0105000      .000      .000  
+8410 5 45978.00 I   .307765  .000364   .232514  .000373  I -.0129651  .0000326  1.5639 0.0241  I    -7.518     .549      .914     .298   .310000   .231000  -.0119000      .000      .000  
+8410 6 45979.00 I   .306411  .000392   .228737  .000430  I -.0145974  .0000412  1.7003 0.0263  I    -7.137     .549     1.104     .298   .309000   .227000  -.0135000      .000      .000  
+8410 7 45980.00 I   .304973  .000392   .224926  .000430  I -.0163618  .0000412  1.8249 0.0304  I    -6.826     .549     1.264     .298   .308000   .223000  -.0152000      .000      .000  
+8410 8 45981.00 I   .303439  .000612   .221082  .000434  I -.0182367  .0000446  1.9180 0.0304  I    -6.608     .549     1.481     .298   .307000   .219000  -.0170000      .000      .000  
+8410 9 45982.00 I   .301786  .000657   .217214  .000452  I -.0201825  .0000447  1.9653 0.0394  I    -6.383     .511     1.674     .298   .305000   .216000  -.0189000      .000      .000  
+841010 45983.00 I   .300011  .000761   .213339  .000447  I -.0221498  .0000650  1.9601 0.0396  I    -6.093     .470     1.690     .298   .304000   .212000  -.0208000      .000      .000  
+841011 45984.00 I   .298118  .000674   .209481  .000398  I -.0240852  .0000655  1.9026 0.0557  I    -5.789     .470     1.517     .298   .303000   .209000  -.0227000      .000      .000  
+841012 45985.00 I   .296138  .000726   .205665  .000388  I -.0259385  .0000904  1.7958 0.0557  I    -5.533     .470     1.310     .298   .302000   .205000  -.0245000      .000      .000  
+841013 45986.00 I   .294132  .000826   .201920  .000444  I -.0276638  .0000900  1.6501 0.0627  I    -5.362     .470     1.184     .298   .300000   .201000  -.0261000      .000      .000  
+841014 45987.00 I   .292159  .000940   .198270  .000484  I -.0292338  .0000868  1.4896 0.0824  I    -5.302     .362     1.110     .298   .299000   .198000  -.0276000      .000      .000  
+841015 45988.00 I   .290281  .001187   .194738  .000490  I -.0306484  .0001380  1.3454 0.0895  I    -5.324     .201     1.029     .107   .298000   .194000  -.0290000      .000      .000  
+841016 45989.00 I   .288571  .001187   .191344  .000490  I -.0319410  .0001565  1.2503 0.1038  I    -5.304     .201      .982     .107   .296000   .191000  -.0303000      .000      .000  
+841017 45990.00 I   .287079  .001315   .188101  .000490  I -.0331759  .0001552  1.2358 0.1016  I    -5.132     .201     1.071     .107   .294000   .187000  -.0316000      .000      .000  
+841018 45991.00 I   .285717  .001189   .184988  .000599  I -.0344489  .0001296  1.3300 0.0937  I    -4.843     .201     1.312     .107   .293000   .184000  -.0329000      .000      .000  
+841019 45992.00 I   .284400  .001115   .181961  .000576  I -.0358756  .0001050  1.5431 0.0915  I    -4.601     .397     1.610     .113   .291000   .180000  -.0343000      .000      .000  
+841020 45993.00 I   .283074  .001041   .178971  .000558  I -.0375672  .0001292  1.8524 0.0681  I    -4.567     .524     1.903     .119   .290000   .177000  -.0361000      .000      .000  
+841021 45994.00 I   .281715  .000863   .175971  .000577  I -.0395921  .0000869  2.1968 0.0683  I    -4.839     .524     2.207     .119   .288000   .174000  -.0381000      .000      .000  
+841022 45995.00 I   .280336  .000863   .172924  .000577  I -.0419415  .0000446  2.4833 0.0483  I    -5.427     .524     2.483     .119   .286000   .170000  -.0405000      .000      .000  
+841023 45996.00 I   .278889  .001057   .169829  .000586  I -.0445100  .0000420  2.6237 0.0286  I    -6.147     .524     2.569     .119   .284000   .167000  -.0431000      .000      .000  
+841024 45997.00 I   .277303  .000961   .166697  .000529  I -.0471278  .0000358  2.5808 0.0264  I    -6.646     .536     2.373     .195   .282000   .164000  -.0457000      .000      .000  
+841025 45998.00 I   .275547  .001119   .163527  .000391  I -.0496179  .0000321  2.3767 0.0240  I    -6.695     .548     2.076     .249   .280000   .160000  -.0482000      .000      .000  
+841026 45999.00 I   .273605  .001119   .160317  .000391  I -.0518502  .0000321  2.0797 0.0273  I    -6.431     .548     1.974     .249   .279000   .157000  -.0504000      .000      .000  
+841027 46000.00 I   .271474  .001101   .157067  .000338  I -.0537756  .0000442  1.7775 0.0260  I    -6.145     .548     2.113     .249   .277000   .154000  -.0524000      .000      .000  
+841028 46001.00 I   .269197  .001105   .153794  .000347  I -.0554279  .0000410  1.5434 0.0273  I    -5.933     .548     2.219     .249   .274000   .151000  -.0541000      .000      .000  
+841029 46002.00 I   .266819  .000730   .150514  .000346  I -.0568970  .0000322  1.4133 0.0292  I    -5.653     .409     2.076     .238   .272000   .148000  -.0557000      .000      .000  
+841030 46003.00 I   .264389  .000850   .147245  .000367  I -.0582891  .0000417  1.3871 0.0263  I    -5.232     .183     1.817     .226   .270000   .145000  -.0571000      .000      .000  
+841031 46004.00 I   .261986  .000850   .144010  .000367  I -.0596984  .0000417  1.4424 0.0338  I    -4.804     .183     1.741     .226   .268000   .142000  -.0586000      .000      .000  
+8411 1 46005.00 I   .259695  .000762   .140827  .000456  I -.0611907  .0000533  1.5480 0.0316  I    -4.514     .183     1.923     .226   .266000   .139000  -.0602000      .000      .000  
+8411 2 46006.00 I   .257508  .000720   .137697  .000470  I -.0628018  .0000475  1.6756 0.0347  I    -4.335     .183     2.161     .226   .264000   .136000  -.0619000      .000      .000  
+8411 3 46007.00 I   .255389  .000726   .134606  .000511  I -.0645409  .0000443  1.8001 0.0387  I    -4.220     .498     2.271     .161   .261000   .133000  -.0638000      .000      .000  
+8411 4 46008.00 I   .253304  .001183   .131541  .000705  I -.0663943  .0000610  1.9014 0.0377  I    -4.192     .680     2.299     .298   .259000   .130000  -.0657000      .000      .000  
+8411 5 46009.00 I   .251214  .001183   .128501  .000705  I -.0683312  .0000610  1.9653 0.0431  I    -4.222     .680     2.398     .298   .257000   .127000  -.0678000      .000      .000  
+8411 6 46010.00 I   .249079  .001183   .125494  .000705  I -.0703066  .0000610  1.9745 0.0390  I    -4.185     .680     2.588     .298   .254000   .124000  -.0698000      .000      .000  
+8411 7 46011.00 I   .246833  .001205   .122520  .000562  I -.0722578  .0000487  1.9166 0.0397  I    -4.051     .680     2.727     .298   .252000   .121000  -.0719000      .000      .000  
+8411 8 46012.00 I   .244423  .001180   .119576  .000530  I -.0741189  .0000509  1.7959 0.0354  I    -3.927     .502     2.691     .214   .249000   .119000  -.0738000      .000      .000  
+8411 9 46013.00 I   .241881  .001272   .116679  .000525  I -.0758335  .0000514  1.6268 0.0368  I    -3.887     .206     2.512     .302   .246000   .116000  -.0756000      .000      .000  
+841110 46014.00 I   .239258  .000963   .113852  .000300  I -.0773639  .0000532  1.4320 0.0427  I    -3.862     .206     2.322     .302   .244000   .113000  -.0771000      .000      .000  
+841111 46015.00 I   .236613  .000839   .111116  .000319  I -.0787022  .0000683  1.2512 0.0405  I    -3.758     .206     2.226     .302   .241000   .110000  -.0786000      .000      .000  
+841112 46016.00 I   .233977  .000784   .108480  .000308  I -.0798857  .0000610  1.1284 0.0472  I    -3.560     .206     2.234     .302   .238000   .108000  -.0798000      .000      .000  
+841113 46017.00 I   .231360  .000684   .105945  .000566  I -.0809883  .0000653  1.0933 0.0473  I    -3.311     .269     2.304     .344   .235000   .105000  -.0810000      .000      .000  
+841114 46018.00 I   .228770  .000527   .103517  .000641  I -.0821065  .0000722  1.1609 0.0487  I    -3.016     .319     2.405     .382   .233000   .103000  -.0822000      .000      .000  
+841115 46019.00 I   .226210  .000527   .101208  .000641  I -.0833444  .0000722  1.3316 0.0511  I    -2.634     .319     2.536     .382   .230000   .100000  -.0835000      .000      .000  
+841116 46020.00 I   .223677  .000527   .099029  .000641  I -.0847991  .0000722  1.5906 0.0509  I    -2.166     .319     2.706     .382   .227000   .098000  -.0850000      .000      .000  
+841117 46021.00 I   .221139  .000527   .096966  .000573  I -.0865409  .0000718  1.8956 0.0468  I    -1.726     .319     2.936     .382   .224000   .095000  -.0868000      .000      .000  
+841118 46022.00 I   .218568  .000528   .094989  .000508  I -.0885838  .0000595  2.1811 0.0505  I    -1.495     .588     3.230     .276   .221000   .092000  -.0888000      .000      .000  
+841119 46023.00 I   .215938  .000908   .093066  .000193  I -.0908741  .0000709  2.3796 0.0463  I    -1.585     .768     3.521     .298   .218000   .090000  -.0911000      .000      .000  
+841120 46024.00 I   .213225  .000908   .091166  .000193  I -.0932968  .0000709  2.4394 0.0501  I    -1.905     .768     3.660     .298   .215000   .088000  -.0934000      .000      .000  
+841121 46025.00 I   .210406  .000908   .089264  .000193  I -.0957003  .0000709  2.3414 0.0476  I    -2.181     .768     3.544     .298   .211000   .085000  -.0957000      .000      .000  
+841122 46026.00 I   .207423  .000845   .087336  .000204  I -.0979370  .0000636  2.1156 0.0444  I    -2.179     .768     3.270     .298   .208000   .083000  -.0978000      .000      .000  
+841123 46027.00 I   .204236  .001016   .085360  .000274  I -.0999119  .0000536  1.8310 0.0473  I    -1.952     .556     3.062     .184   .205000   .081000  -.0996000      .000      .000  
+841124 46028.00 I   .200873  .001212   .083317  .000313  I -.1016052  .0000699  1.5651 0.0399  I    -1.733     .165     3.023     .246   .202000   .078000  -.1012000      .000      .000  
+841125 46029.00 I   .197372  .001027   .081189  .000345  I -.1030670  .0000590  1.3741 0.0465  I    -1.593     .165     3.036     .246   .198000   .076000  -.1026000      .000      .000  
+841126 46030.00 I   .193765  .001048   .078961  .000378  I -.1043881  .0000613  1.2873 0.0424  I    -1.371     .165     2.976     .246   .195000   .074000  -.1039000      .000      .000  
+841127 46031.00 I   .190075  .001002   .076633  .000340  I -.1056759  .0000608  1.3034 0.0396  I     -.975     .165     2.906     .246   .192000   .072000  -.1052000      .000      .000  
+841128 46032.00 I   .186314  .000933   .074211  .000457  I -.1070185  .0000500  1.3904 0.0367  I     -.532     .230     3.015     .232   .188000   .069000  -.1066000      .000      .000  
+841129 46033.00 I   .182505  .000851   .071705  .000523  I -.1084686  .0000411  1.5133 0.0330  I     -.244     .280     3.343     .217   .185000   .067000  -.1081000      .000      .000  
+841130 46034.00 I   .178719  .000851   .069134  .000523  I -.1100477  .0000431  1.6440 0.0298  I     -.202     .280     3.690     .217   .181000   .065000  -.1098000      .000      .000  
+8412 1 46035.00 I   .175026  .000851   .066518  .000523  I -.1117507  .0000431  1.7568 0.0278  I     -.402     .280     3.842     .217   .178000   .063000  -.1117000      .000      .000  
+8412 2 46036.00 I   .171408  .000625   .063884  .000573  I -.1135490  .0000351  1.8325 0.0277  I     -.783     .280     3.831     .217   .174000   .061000  -.1136000      .000      .000  
+8412 3 46037.00 I   .167834  .000603   .061277  .000614  I -.1153998  .0000349  1.8604 0.0309  I    -1.250     .215     3.845     .157   .170000   .059000  -.1156000      .000      .000  
+8412 4 46038.00 I   .164269  .000368   .058741  .000617  I -.1172522  .0000509  1.8355 0.0309  I    -1.696     .118     3.975     .298   .166000   .057000  -.1176000      .000      .000  
+8412 5 46039.00 I   .160686  .000368   .056322  .000617  I -.1190543  .0000509  1.7613 0.0354  I    -2.072     .118     4.128     .298   .163000   .055000  -.1194000      .000      .000  
+8412 6 46040.00 I   .157068  .000368   .054065  .000617  I -.1207603  .0000491  1.6437 0.0335  I    -2.405     .118     4.148     .298   .159000   .053000  -.1211000      .000      .000  
+8412 7 46041.00 I   .153378  .000333   .051970  .000571  I -.1223307  .0000436  1.4930 0.0367  I    -2.710     .118     3.973     .298   .155000   .051000  -.1227000      .000      .000  
+8412 8 46042.00 I   .149571  .000630   .050022  .000637  I -.1237441  .0000545  1.3357 0.0380  I    -2.885     .408     3.696     .211   .151000   .050000  -.1241000      .000      .000  
+8412 9 46043.00 I   .145616  .000737   .048212  .000521  I -.1250117  .0000623  1.2070 0.0411  I    -2.802     .565     3.480     .295   .147000   .048000  -.1253000      .000      .000  
+841210 46044.00 I   .141486  .000811   .046529  .000582  I -.1261785  .0000615  1.1393 0.0455  I    -2.482     .565     3.418     .295   .143000   .046000  -.1265000      .000      .000  
+841211 46045.00 I   .137154  .000815   .044964  .000523  I -.1273183  .0000662  1.1556 0.0433  I    -2.088     .565     3.464     .295   .139000   .045000  -.1276000      .000      .000  
+841212 46046.00 I   .132626  .000739   .043500  .000605  I -.1285200  .0000610  1.2628 0.0433  I    -1.747     .565     3.503     .295   .135000   .043000  -.1287000      .000      .000  
+841213 46047.00 I   .127941  .000629   .042103  .000657  I -.1298686  .0000559  1.4441 0.0395  I    -1.474     .418     3.474     .214   .131000   .042000  -.1300000      .000      .000  
+841214 46048.00 I   .123137  .000426   .040739  .000717  I -.1314199  .0000502  1.6605 0.0415  I    -1.242     .173     3.420     .298   .126000   .040000  -.1315000      .000      .000  
+841215 46049.00 I   .118217  .000426   .039369  .000717  I -.1331843  .0000614  1.8609 0.0382  I    -1.064     .173     3.434     .298   .122000   .039000  -.1333000      .000      .000  
+841216 46050.00 I   .113171  .000691   .037956  .000670  I -.1351183  .0000577  1.9910 0.0384  I     -.995     .173     3.574     .298   .118000   .037000  -.1352000      .000      .000  
+841217 46051.00 I   .108005  .000605   .036506  .000689  I -.1371294  .0000461  2.0102 0.0357  I    -1.081     .173     3.798     .298   .114000   .036000  -.1372000      .000      .000  
+841218 46052.00 I   .102735  .000618   .035042  .000658  I -.1390966  .0000419  1.9030 0.0353  I    -1.250     .329     4.011     .108   .110000   .035000  -.1392000      .000      .000  
+841219 46053.00 I   .097379  .000828   .033587  .000777  I -.1408996  .0000536  1.6882 0.0327  I    -1.317     .431     4.124     .137   .106000   .034000  -.1410000      .000      .000  
+841220 46054.00 I   .091986  .000703   .032161  .000668  I -.1424543  .0000501  1.4172 0.0307  I    -1.119     .431     4.119     .137   .102000   .033000  -.1426000      .000      .000  
+841221 46055.00 I   .086657  .000877   .030775  .000768  I -.1437381  .0000299  1.1583 0.0358  I     -.658     .360     4.044     .227   .097000   .032000  -.1439000      .000      .000  
+841222 46056.00 I   .081481  .000953   .029451  .001247  I -.1447949  .0000511  0.9712 0.0296  I     -.104     .360     3.958     .227   .093000   .031000  -.1449000      .000      .000  
+841223 46057.00 I   .076553  .000953   .028198  .001247  I -.1457150  .0000511  0.8874 0.0381  I      .385     .360     3.861     .227   .089000   .030000  -.1458000      .000      .000  
+841224 46058.00 I   .071971  .001038   .027005  .001380  I -.1466072  .0000566  0.9160 0.0405  I      .772     .270     3.742     .290   .085000   .029000  -.1468000      .000      .000  
+841225 46059.00 I   .067706  .001017   .025917  .001285  I -.1475790  .0000629  1.0406 0.0423  I     1.096     .270     3.661     .290   .081000   .028000  -.1478000      .000      .000  
+841226 46060.00 I   .063659  .001017   .024995  .001285  I -.1487065  .0000629  1.2194 0.0816  I     1.344     .270     3.718     .290   .076000   .028000  -.1489000      .000      .000  
+841227 46061.00 I   .059795  .001196   .024242  .001751  I -.1500226  .0001505  1.4127 0.0693  I     1.428     .791     3.920     .298   .072000   .027000  -.1503000      .000      .000  
+841228 46062.00 I   .056087  .000649   .023657  .000210  I -.1515275  .0001235  1.5929 0.0973  I     1.300     .791     4.137     .286   .068000   .026000  -.1517000      .000      .000  
+841229 46063.00 I   .052510  .000649   .023235  .000210  I -.1531963  .0001235  1.7369 0.0873  I     1.033     .791     4.246     .286   .064000   .026000  -.1533000      .000      .000  
+841230 46064.00 I   .049040  .000649   .022967  .000210  I -.1549845  .0001235  1.8304 0.0786  I      .766     .791     4.277     .286   .060000   .025000  -.1550000      .000      .000  
+841231 46065.00 I   .045647  .000773   .022839  .000394  I -.1568370  .0000972  1.8637 0.0705  I      .603     .791     4.351     .286   .055000   .025000  -.1568000      .000      .000  
+85 1 1 46066.00 I   .042277  .000661   .022841  .000334  I -.1586909  .0000681  1.8340 0.0537  I      .541     .791     4.509     .286   .051000   .025000  -.1585000      .000      .000  
+85 1 2 46067.00 I   .038867  .000583   .022960  .000652  I -.1604870  .0000457  1.7502 0.0353  I      .515     .868     4.639     .202   .047000   .025000  -.1601000      .000      .000  
+85 1 3 46068.00 I   .035355  .000649   .023183  .000627  I -.1621783  .0000189  1.6274 0.0247  I      .487    1.227     4.588     .298   .043000   .025000  -.1617000      .000      .000  
+85 1 4 46069.00 I   .031690  .000649   .023492  .000627  I -.1637360  .0000189  1.4872 0.0134  I      .490    1.227     4.301     .298   .039000   .025000  -.1631000      .000      .000  
+85 1 5 46070.00 I   .027848  .000649   .023864  .000627  I -.1651577  .0000189  1.3620 0.0152  I      .604    1.227     3.862     .298   .035000   .025000  -.1645000      .000      .000  
+85 1 6 46071.00 I   .023839  .000506   .024297  .000743  I -.1664779  .0000238  1.2905 0.0134  I      .873    1.227     3.451     .298   .030000   .025000  -.1657000      .000      .000  
+85 1 7 46072.00 I   .019696  .000554   .024802  .000650  I -.1677671  .0000191  1.3043 0.0150  I     1.278     .897     3.244     .298   .026000   .025000  -.1670000      .000      .000  
+85 1 8 46073.00 I   .015499  .000605   .025390  .000580  I -.1691195  .0000184  1.4173 0.0150  I     1.721     .323     3.317     .298   .022000   .025000  -.1683000      .000      .000  
+85 1 9 46074.00 I   .011336  .000467   .026070  .000580  I -.1706301  .0000231  1.6156 0.0148  I     2.021     .323     3.607     .298   .018000   .025000  -.1699000      .000      .000  
+85 110 46075.00 I   .007290  .000467   .026845  .000580  I -.1723661  .0000231  1.8601 0.0225  I     1.970     .323     3.983     .298   .014000   .026000  -.1716000      .000      .000  
+85 111 46076.00 I   .003381  .000603   .027703  .000682  I -.1743467  .0000386  2.0938 0.0231  I     1.522     .323     4.333     .298   .010000   .027000  -.1736000      .000      .000  
+85 112 46077.00 I  -.000400  .000734   .028635  .000648  I -.1765293  .0000399  2.2544 0.0401  I      .800     .297     4.626     .298   .006000   .027000  -.1758000      .000      .000  
+85 113 46078.00 I  -.004039  .000966   .029631  .000929  I -.1788167  .0000702  2.2987 0.0404  I      .003     .242     4.884     .298   .003000   .028000  -.1781000      .000      .000  
+85 114 46079.00 I  -.007510  .000966   .030685  .000929  I -.1810844  .0000702  2.2163 0.0504  I     -.671     .242     5.090     .298  -.001000   .029000  -.1804000      .000      .000  
+85 115 46080.00 I  -.010793  .001151   .031794  .001180  I -.1832128  .0000723  2.0245 0.0473  I    -1.063     .242     5.179     .298  -.005000   .029000  -.1825000      .000      .000  
+85 116 46081.00 I  -.013922  .000977   .032971  .001407  I -.1851106  .0000634  1.7642 0.0417  I    -1.137     .242     5.122     .298  -.009000   .030000  -.1844000      .000      .000  
+85 117 46082.00 I  -.016965  .000806   .034224  .001224  I -.1867379  .0000415  1.4940 0.0348  I     -.903     .840     4.914     .298  -.013000   .031000  -.1861000      .000      .000  
+85 118 46083.00 I  -.019994  .000510   .035558  .001247  I -.1881139  .0000287  1.2698 0.0258  I     -.402    1.022     4.564     .115  -.016000   .032000  -.1875000      .000      .000  
+85 119 46084.00 I  -.023076  .000534   .036972  .001211  I -.1893057  .0000307  1.1303 0.0210  I      .239    1.022     4.119     .115  -.020000   .033000  -.1888000      .000      .000  
+85 120 46085.00 I  -.026261  .000534   .038429  .001211  I -.1904083  .0000307  1.0923 0.0215  I      .831    1.022     3.671     .115  -.024000   .034000  -.1900000      .000      .000  
+85 121 46086.00 I  -.029573  .000969   .039922  .001113  I -.1915209  .0000300  1.1460 0.0178  I     1.249    1.022     3.320     .115  -.027000   .035000  -.1912000      .000      .000  
+85 122 46087.00 I  -.033034  .001011   .041461  .000798  I -.1927203  .0000180  1.2596 0.0168  I     1.475     .991     3.169     .235  -.031000   .036000  -.1925000      .000      .000  
+85 123 46088.00 I  -.036654  .001179   .043045  .000730  I -.1940474  .0000153  1.3951 0.0361  I     1.548     .838     3.278     .283  -.034000   .037000  -.1939000      .000      .000  
+85 124 46089.00 I  -.040417  .001179   .044650  .000730  I -.1955065  .0000699  1.5186 0.0378  I     1.472     .838     3.607     .283  -.037000   .039000  -.1955000      .000      .000  
+85 125 46090.00 I  -.044273  .001357   .046244  .000554  I -.1970727  .0000741  1.6063 0.0486  I     1.226     .838     4.012     .283  -.041000   .040000  -.1971000      .000      .000  
+85 126 46091.00 I  -.048135  .001206   .047808  .000669  I -.1987025  .0000676  1.6442 0.0465  I      .992     .838     4.190     .283  -.044000   .041000  -.1987000      .000      .000  
+85 127 46092.00 I  -.051928  .000513   .049331  .000692  I -.2003427  .0000561  1.6268 0.0515  I      .912     .658     4.128     .266  -.047000   .043000  -.2003000      .000      .000  
+85 128 46093.00 I  -.055578  .000601   .050805  .000943  I -.2019384  .0000776  1.5561 0.0479  I      .963     .322     4.026     .228  -.050000   .044000  -.2018000      .000      .000  
+85 129 46094.00 I  -.059013  .000601   .052219  .000943  I -.2034409  .0000776  1.4432 0.0500  I      .991     .190     3.978     .240  -.053000   .046000  -.2032000      .000      .000  
+85 130 46095.00 I  -.062163  .000541   .053572  .000990  I -.2048137  .0000631  1.2969 0.0507  I      .832     .190     3.961     .240  -.056000   .048000  -.2044000      .000      .000  
+85 131 46096.00 I  -.065008  .000600   .054912  .000960  I -.2060277  .0000652  1.1296 0.0414  I      .549     .190     3.906     .240  -.060000   .049000  -.2055000      .000      .000  
+85 2 1 46097.00 I  -.067595  .000540   .056280  .000887  I -.2070748  .0000537  0.9678 0.0470  I      .323     .281     3.793     .190  -.063000   .051000  -.2064000      .000      .000  
+85 2 2 46098.00 I  -.069992  .000651   .057704  .000975  I -.2079760  .0000677  0.8439 0.0381  I      .225     .348     3.626     .120  -.066000   .053000  -.2072000      .000      .000  
+85 2 3 46099.00 I  -.072265  .000521   .059200  .000715  I -.2087876  .0000541  0.7950 0.0433  I      .241     .348     3.383     .120  -.068000   .055000  -.2080000      .000      .000  
+85 2 4 46100.00 I  -.074472  .000521   .060763  .000715  I -.2096027  .0000541  0.8563 0.0335  I      .467     .348     3.090     .120  -.072000   .057000  -.2089000      .000      .000  
+85 2 5 46101.00 I  -.076633  .000541   .062402  .000671  I -.2105400  .0000395  1.0370 0.0317  I     1.034     .348     2.895     .120  -.075000   .059000  -.2101000      .000      .000  
+85 2 6 46102.00 I  -.078755  .000458   .064139  .000570  I -.2117058  .0000331  1.3049 0.0242  I     1.873     .268     2.916     .313  -.078000   .061000  -.2115000      .000      .000  
+85 2 7 46103.00 I  -.080874  .000425   .066000  .000564  I -.2131574  .0000278  1.5955 0.0256  I     2.619     .150     3.081     .426  -.082000   .063000  -.2132000      .000      .000  
+85 2 8 46104.00 I  -.083041  .000425   .068013  .000564  I -.2148787  .0000390  1.8319 0.0291  I     2.885     .150     3.215     .426  -.085000   .065000  -.2151000      .000      .000  
+85 2 9 46105.00 I  -.085300  .000318   .070194  .000588  I -.2167819  .0000511  1.9503 0.0300  I     2.599     .150     3.245     .426  -.088000   .067000  -.2172000      .000      .000  
+85 210 46106.00 I  -.087660  .000368   .072510  .000552  I -.2187311  .0000455  1.9239 0.0316  I     2.041     .150     3.244     .426  -.091000   .069000  -.2193000      .000      .000  
+85 211 46107.00 I  -.090126  .000423   .074917  .000406  I -.2205888  .0000373  1.7748 0.0338  I     1.506     .252     3.328     .394  -.094000   .071000  -.2212000      .000      .000  
+85 212 46108.00 I  -.092701  .000453   .077370  .000500  I -.2222578  .0000500  1.5570 0.0312  I     1.084     .323     3.526     .360  -.097000   .073000  -.2230000      .000      .000  
+85 213 46109.00 I  -.095382  .000453   .079814  .000500  I -.2237016  .0000500  1.3356 0.0326  I      .759     .323     3.752     .360  -.100000   .075000  -.2244000      .000      .000  
+85 214 46110.00 I  -.098160  .000487   .082196  .000461  I -.2249468  .0000417  1.1676 0.0278  I      .557     .323     3.889     .360  -.103000   .077000  -.2258000      .000      .000  
+85 215 46111.00 I  -.101037  .000553   .084501  .000414  I -.2260661  .0000244  1.0873 0.0243  I      .559     .323     3.866     .360  -.106000   .080000  -.2269000      .000      .000  
+85 216 46112.00 I  -.104051  .000488   .086729  .000436  I -.2271542  .0000248  1.1053 0.0201  I      .807     .234     3.671     .308  -.109000   .082000  -.2280000      .000      .000  
+85 217 46113.00 I  -.107245  .000471   .088881  .000469  I -.2283057  .0000319  1.2104 0.0202  I     1.223     .791     3.349     .246  -.112000   .084000  -.2291000      .000      .000  
+85 218 46114.00 I  -.110647  .000471   .090957  .000469  I -.2295951  .0000319  1.3758 0.0226  I     1.638     .791     3.020     .246  -.114000   .086000  -.2304000      .000      .000  
+85 219 46115.00 I  -.114250  .000471   .092963  .000469  I -.2310654  .0000319  1.5656 0.0225  I     1.941     .791     2.836     .246  -.117000   .088000  -.2316000      .000      .000  
+85 220 46116.00 I  -.118004  .000441   .094931  .000468  I -.2327217  .0000318  1.7415 0.0211  I     2.152     .791     2.870     .246  -.119000   .091000  -.2331000      .000      .000  
+85 221 46117.00 I  -.121853  .000475   .096905  .000480  I -.2345343  .0000275  1.8750 0.0208  I     2.339     .132     3.038     .214  -.122000   .093000  -.2347000      .000      .000  
+85 222 46118.00 I  -.125726  .000498   .098912  .000533  I -.2364516  .0000267  1.9483 0.0176  I     2.508     .172     3.169     .176  -.125000   .096000  -.2364000      .000      .000  
+85 223 46119.00 I  -.129547  .000486   .100973  .000651  I -.2384076  .0000221  1.9518 0.0173  I     2.621     .172     3.173     .176  -.127000   .098000  -.2382000      .000      .000  
+85 224 46120.00 I  -.133243  .000486   .103110  .000651  I -.2403331  .0000221  1.8892 0.0161  I     2.680     .172     3.124     .176  -.130000   .101000  -.2400000      .000      .000  
+85 225 46121.00 I  -.136777  .000479   .105344  .000595  I -.2421679  .0000235  1.7725 0.0148  I     2.716     .172     3.115     .176  -.132000   .103000  -.2418000      .000      .000  
+85 226 46122.00 I  -.140144  .000505   .107701  .000510  I -.2438655  .0000196  1.6182 0.0146  I     2.673     .404     3.108     .219  -.135000   .106000  -.2435000      .000      .000  
+85 227 46123.00 I  -.143341  .000496   .110196  .000553  I -.2453988  .0000173  1.4474 0.0132  I     2.520     .544     2.986     .255  -.138000   .109000  -.2450000      .000      .000  
+85 228 46124.00 I  -.146379  .000496   .112815  .000553  I -.2467622  .0000177  1.2824 0.0124  I     2.441     .544     2.741     .255  -.140000   .111000  -.2464000      .000      .000  
+85 3 1 46125.00 I  -.149266  .000524   .115542  .000292  I -.2479762  .0000177  1.1554 0.0170  I     2.681     .544     2.498     .255  -.143000   .114000  -.2477000      .000      .000  
+85 3 2 46126.00 I  -.152035  .000502   .118359  .000316  I -.2490984  .0000291  1.1048 0.0163  I     3.134     .544     2.321     .255  -.145000   .117000  -.2489000      .000      .000  
+85 3 3 46127.00 I  -.154732  .000553   .121245  .000525  I -.2502217  .0000274  1.1621 0.0224  I     3.441    1.297     2.091     .324  -.148000   .119000  -.2501000      .000      .000  
+85 3 4 46128.00 I  -.157401  .000540   .124178  .000659  I -.2514646  .0000341  1.3455 0.0219  I     3.475    1.464     1.706     .320  -.150000   .122000  -.2514000      .000      .000  
+85 3 5 46129.00 I  -.160087  .000540   .127139  .000659  I -.2529506  .0000341  1.6427 0.0240  I     3.458    1.464     1.324     .320  -.153000   .125000  -.2530000      .000      .000  
+85 3 6 46130.00 I  -.162838  .000540   .130105  .000659  I -.2547729  .0000339  2.0087 0.0240  I     3.513    1.464     1.232     .320  -.155000   .128000  -.2549000      .000      .000  
+85 3 7 46131.00 I  -.165701  .000540   .133042  .000659  I -.2569614  .0000339  2.3551 0.0293  I     3.527    1.464     1.484     .320  -.158000   .131000  -.2572000      .000      .000  
+85 3 8 46132.00 I  -.168632  .000605   .135964  .000693  I -.2594436  .0000478  2.5832 0.0306  I     3.198    1.464     1.803     .320  -.160000   .134000  -.2597000      .000      .000  
+85 3 9 46133.00 I  -.171568  .000606   .138910  .000651  I -.2620707  .0000509  2.6402 0.1376  I     2.450     .454     1.910     .298  -.162000   .137000  -.2623000      .000      .000  
+85 310 46134.00 I  -.174442  .000781   .141921  .000640  I -.2646679  .0002710  2.5291 0.1002  I     1.659     .791     1.807     .298  -.164000   .141000  -.2649000      .000      .000  
+85 311 46135.00 I  -.177192  .001034   .145035  .000541  I -.2670902  .0001939  2.3020 0.1438  I     1.208     .791     1.694     .298  -.166000   .144000  -.2673000      .000      .000  
+85 312 46136.00 I  -.179774  .000885   .148284  .000459  I -.2692583  .0000962  2.0341 0.1015  I     1.145     .791     1.676     .298  -.168000   .147000  -.2693000      .000      .000  
+85 313 46137.00 I  -.182174  .000916   .151687  .000516  I -.2711697  .0000602  1.8001 0.0516  I     1.296    1.168     1.687     .482  -.170000   .150000  -.2712000      .000      .000  
+85 314 46138.00 I  -.184390  .000946   .155262  .000486  I -.2728870  .0000372  1.6515 0.0354  I     1.542    1.168     1.644     .482  -.172000   .154000  -.2728000      .000      .000  
+85 315 46139.00 I  -.186475  .000946   .159014  .000486  I -.2745066  .0000372  1.6045 0.0200  I     1.916    1.168     1.546     .482  -.174000   .157000  -.2743000      .000      .000  
+85 316 46140.00 I  -.188489  .000946   .162944  .000486  I -.2761266  .0000147  1.6494 0.0202  I     2.525    1.168     1.418     .482  -.176000   .161000  -.2759000      .000      .000  
+85 317 46141.00 I  -.190425  .000893   .167016  .000559  I -.2778277  .0000159  1.7612 0.0102  I     3.359    1.168     1.263     .482  -.178000   .164000  -.2775000      .000      .000  
+85 318 46142.00 I  -.192241  .000921   .171174  .000579  I -.2796601  .0000141  1.9063 0.0186  I     4.232    1.031     1.117     .342  -.179000   .168000  -.2793000      .000      .000  
+85 319 46143.00 I  -.193893  .000979   .175364  .000601  I -.2816404  .0000336  2.0518 0.0182  I     4.892     .872     1.094     .298  -.181000   .171000  -.2813000      .000      .000  
+85 320 46144.00 I  -.195330  .000979   .179529  .000601  I -.2837540  .0000336  2.1683 0.0238  I     5.209     .872     1.287     .298  -.182000   .175000  -.2834000      .000      .000  
+85 321 46145.00 I  -.196459  .000979   .183619  .000601  I -.2859606  .0000336  2.2358 0.0364  I     5.231     .872     1.619     .298  -.184000   .178000  -.2856000      .000      .000  
+85 322 46146.00 I  -.197257  .000809   .187641  .000525  I -.2882065  .0000645  2.2460 0.0361  I     5.113     .872     1.860     .298  -.185000   .182000  -.2879000      .000      .000  
+85 323 46147.00 I  -.197770  .000660   .191620  .000547  I -.2904336  .0000640  2.1990 0.0608  I     4.972     .761     1.862     .162  -.187000   .186000  -.2901000      .000      .000  
+85 324 46148.00 I  -.198078  .000525   .195575  .000323  I -.2925881  .0001032  2.1027 0.0572  I     4.868     .630     1.700     .227  -.188000   .189000  -.2923000      .000      .000  
+85 325 46149.00 I  -.198263  .000527   .199521  .000490  I -.2946278  .0000948  1.9730 0.0732  I     4.822     .630     1.537     .227  -.189000   .193000  -.2944000      .000      .000  
+85 326 46150.00 I  -.198402  .000527   .203478  .000490  I -.2965273  .0001039  1.8231 0.0624  I     4.771     .630     1.408     .227  -.190000   .197000  -.2963000      .000      .000  
+85 327 46151.00 I  -.198546  .000463   .207460  .000447  I -.2982722  .0000813  1.6677 0.0585  I     4.651     .630     1.217     .227  -.192000   .200000  -.2980000      .000      .000  
+85 328 46152.00 I  -.198758  .000420   .211475  .000404  I -.2998687  .0000538  1.5303 0.0501  I     4.587     .499      .966     .276  -.192000   .204000  -.2996000      .000      .000  
+85 329 46153.00 I  -.199088  .000586   .215521  .000492  I -.3013471  .0000585  1.4357 0.0500  I     4.795     .317      .815     .318  -.193000   .208000  -.3011000      .000      .000  
+85 330 46154.00 I  -.199546  .000586   .219579  .000492  I -.3027625  .0000843  1.4084 0.0525  I     5.236     .317      .840     .318  -.194000   .212000  -.3026000      .000      .000  
+85 331 46155.00 I  -.200125  .000475   .223631  .000373  I -.3041967  .0000871  1.4794 0.0541  I     5.587     .317      .850     .318  -.195000   .216000  -.3041000      .000      .000  
+85 4 1 46156.00 I  -.200799  .000464   .227676  .000321  I -.3057583  .0000679  1.6615 0.0522  I     5.687     .317      .609     .318  -.196000   .220000  -.3057000      .000      .000  
+85 4 2 46157.00 I  -.201506  .000725   .231711  .000349  I -.3075487  .0000574  1.9305 0.0463  I     5.794     .575      .202     .228  -.197000   .223000  -.3077000      .000      .000  
+85 4 3 46158.00 I  -.202157  .000859   .235725  .000364  I -.3096280  .0000629  2.2257 0.0429  I     6.171     .748     -.010     .298  -.197000   .227000  -.3099000      .000      .000  
+85 4 4 46159.00 I  -.202656  .000848   .239703  .000316  I -.3119810  .0000639  2.4636 0.0367  I     6.598     .748      .176     .298  -.198000   .231000  -.3124000      .000      .000  
+85 4 5 46160.00 I  -.202894  .000848   .243632  .000316  I -.3145091  .0000378  2.5631 0.0359  I     6.582     .748      .542     .298  -.198000   .235000  -.3151000      .000      .000  
+85 4 6 46161.00 I  -.202887  .000768   .247510  .000284  I -.3170467  .0000326  2.4811 0.0226  I     6.007     .748      .734     .298  -.198000   .239000  -.3177000      .000      .000  
+85 4 7 46162.00 I  -.202694  .000661   .251352  .000454  I -.3194193  .0000249  2.2430 0.0211  I     5.270     .583      .674     .298  -.198000   .243000  -.3202000      .000      .000  
+85 4 8 46163.00 I  -.202363  .000391   .255174  .000517  I -.3215064  .0000268  1.9261 0.0191  I     4.817     .346      .549     .113  -.198000   .247000  -.3224000      .000      .000  
+85 4 9 46164.00 I  -.201945  .000312   .258993  .000556  I -.3232768  .0000291  1.6252 0.0190  I     4.747     .346      .484     .113  -.198000   .251000  -.3242000      .000      .000  
+85 410 46165.00 I  -.201479  .000312   .262823  .000556  I -.3247880  .0000268  1.4177 0.0187  I     4.879     .346      .410     .113  -.198000   .255000  -.3258000      .000      .000  
+85 411 46166.00 I  -.200979  .000347   .266659  .000499  I -.3261551  .0000235  1.3387 0.0179  I     5.000     .346      .264     .113  -.198000   .259000  -.3272000      .000      .000  
+85 412 46167.00 I  -.200452  .000335   .270482  .000554  I -.3275061  .0000237  1.3817 0.0176  I     5.018     .552      .147     .106  -.198000   .263000  -.3286000      .000      .000  
+85 413 46168.00 I  -.199907  .000346   .274270  .000588  I -.3289482  .0000261  1.5139 0.0175  I     5.002     .700      .178     .298  -.198000   .267000  -.3300000      .000      .000  
+85 414 46169.00 I  -.199368  .000346   .277987  .000588  I -.3305500  .0000258  1.6946 0.0194  I     5.118     .700      .305     .298  -.198000   .271000  -.3316000      .000      .000  
+85 415 46170.00 I  -.198855  .000438   .281599  .000559  I -.3323403  .0000288  1.8842 0.0184  I     5.435     .700      .385     .298  -.198000   .275000  -.3333000      .000      .000  
+85 416 46171.00 I  -.198376  .000412   .285115  .000517  I -.3343101  .0000263  2.0489 0.0197  I     5.792     .700      .427     .298  -.198000   .279000  -.3352000      .000      .000  
+85 417 46172.00 I  -.197935  .000555   .288574  .000471  I -.3364221  .0000268  2.1657 0.0209  I     5.963     .504      .559     .125  -.197000   .283000  -.3372000      .000      .000  
+85 418 46173.00 I  -.197529  .000627   .292023  .000397  I -.3386206  .0000324  2.2197 0.0212  I     5.914     .138      .798     .147  -.197000   .286000  -.3393000      .000      .000  
+85 419 46174.00 I  -.197147  .000661   .295507  .000319  I -.3408390  .0000329  2.2060 0.0237  I     5.798     .138      .988     .147  -.197000   .290000  -.3414000      .000      .000  
+85 420 46175.00 I  -.196748  .000661   .299057  .000319  I -.3430114  .0000346  2.1286 0.0223  I     5.751     .138      .996     .147  -.196000   .294000  -.3434000      .000      .000  
+85 421 46176.00 I  -.196341  .000625   .302665  .000300  I -.3450778  .0000301  1.9959 0.0224  I     5.808     .138      .823     .147  -.196000   .298000  -.3454000      .000      .000  
+85 422 46177.00 I  -.195970  .000611   .306310  .000325  I -.3469911  .0000284  1.8268 0.0213  I     5.945     .405      .577     .279  -.195000   .302000  -.3472000      .000      .000  
+85 423 46178.00 I  -.195653  .000572   .309964  .000314  I -.3487283  .0000302  1.6483 0.0269  I     6.100     .606      .270     .424  -.194000   .305000  -.3489000      .000      .000  
+85 424 46179.00 I  -.195403  .000682   .313600  .000313  I -.3502938  .0000457  1.4881 0.0327  I     6.220     .606     -.280     .424  -.193000   .309000  -.3504000      .000      .000  
+85 425 46180.00 I  -.195218  .000682   .317194  .000313  I -.3517206  .0000579  1.3763 0.0354  I     6.345     .606    -1.178     .424  -.193000   .313000  -.3518000      .000      .000  
+85 426 46181.00 I  -.195070  .000684   .320749  .000304  I -.3530704  .0000542  1.3367 0.0397  I     6.419     .606    -1.710     .424  -.192000   .316000  -.3532000      .000      .000  
+85 427 46182.00 I  -.194934  .000684   .324277  .000304  I -.3544233  .0000542  1.3851 0.0592  I     6.466     .537    -1.571     .332  -.191000   .320000  -.3546000      .000      .000  
+85 428 46183.00 I  -.194754  .000908   .327794  .000206  I -.3558732  .0001053  1.5313 0.0602  I     6.454     .524    -1.093     .306  -.190000   .324000  -.3561000      .000      .000  
+85 429 46184.00 I  -.194430  .000908   .331318  .000206  I -.3575151  .0001074  1.7653 0.0692  I     6.334     .415     -.701     .111  -.189000   .327000  -.3578000      .000      .000  
+85 430 46185.00 I  -.193875  .000747   .334866  .000814  I -.3594226  .0000898  2.0558 0.0617  I     6.266     .415     -.602     .111  -.188000   .331000  -.3599000      .000      .000  
+85 5 1 46186.00 I  -.193064  .000678   .338446  .000829  I -.3616246  .0000609  2.3399 0.0533  I     6.366     .415     -.563     .111  -.187000   .335000  -.3622000      .000      .000  
+85 5 2 46187.00 I  -.192022  .000675   .342059  .000767  I -.3640725  .0000575  2.5341 0.0458  I     6.471     .304     -.335     .162  -.185000   .338000  -.3648000      .000      .000  
+85 5 3 46188.00 I  -.190796  .000665   .345705  .000873  I -.3666421  .0000684  2.5761 0.0413  I     6.279     .115     -.010     .200  -.184000   .342000  -.3675000      .000      .000  
+85 5 4 46189.00 I  -.189423  .001150   .349371  .000892  I -.3691694  .0000594  2.4522 0.0462  I     5.732     .115      .155     .200  -.183000   .345000  -.3702000      .000      .000  
+85 5 5 46190.00 I  -.187921  .001056   .353018  .001040  I -.3715021  .0000621  2.1949 0.0403  I     5.101     .115      .103     .200  -.181000   .349000  -.3725000      .000      .000  
+85 5 6 46191.00 I  -.186343  .001073   .356639  .000803  I -.3735395  .0000546  1.8783 0.0383  I     4.715     .116     -.028     .188  -.180000   .352000  -.3745000      .000      .000  
+85 5 7 46192.00 I  -.184758  .000881   .360244  .000583  I -.3752701  .0000448  1.5959 0.0344  I     4.668     .697     -.177     .291  -.178000   .355000  -.3761000      .000      .000  
+85 5 8 46193.00 I  -.183180  .000955   .363836  .000547  I -.3767639  .0000419  1.4114 0.0300  I     4.843     .855     -.456     .314  -.177000   .359000  -.3775000      .000      .000  
+85 5 9 46194.00 I  -.181540  .000955   .367403  .000547  I -.3781335  .0000399  1.3487 0.0290  I     5.042     .855     -.895     .314  -.175000   .362000  -.3788000      .000      .000  
+85 510 46195.00 I  -.179759  .000595   .370913  .000608  I -.3794931  .0000400  1.3814 0.0273  I     5.124     .855    -1.102     .314  -.174000   .365000  -.3801000      .000      .000  
+85 511 46196.00 I  -.177855  .000610   .374344  .000604  I -.3809154  .0000372  1.4713 0.0263  I     5.190     .855     -.987     .314  -.172000   .369000  -.3815000      .000      .000  
+85 512 46197.00 I  -.175860  .000566   .377706  .000403  I -.3824452  .0000342  1.5898 0.0242  I     5.403     .891     -.726     .327  -.170000   .372000  -.3830000      .000      .000  
+85 513 46198.00 I  -.173806  .000324   .381008  .000453  I -.3840934  .0000309  1.7035 0.0217  I     5.748     .728     -.464     .270  -.169000   .375000  -.3847000      .000      .000  
+85 514 46199.00 I  -.171735  .000345   .384244  .000490  I -.3858435  .0000268  1.7909 0.0205  I     5.977     .662     -.260     .251  -.167000   .378000  -.3864000      .000      .000  
+85 515 46200.00 I  -.169684  .000495   .387395  .000472  I -.3876593  .0000270  1.8304 0.0191  I     5.669     .662      .011     .251  -.165000   .382000  -.3883000      .000      .000  
+85 516 46201.00 I  -.167665  .000623   .390431  .000483  I -.3894825  .0000271  1.8043 0.0191  I     4.864     .662      .368     .251  -.163000   .385000  -.3901000      .000      .000  
+85 517 46202.00 I  -.165657  .000812   .393334  .000462  I -.3912474  .0000270  1.7167 0.0191  I     4.003     .530      .615     .198  -.161000   .388000  -.3918000      .000      .000  
+85 518 46203.00 I  -.163573  .000909   .396137  .000483  I -.3928999  .0000268  1.5811 0.0196  I     3.394     .319      .551     .298  -.159000   .391000  -.3935000      .000      .000  
+85 519 46204.00 I  -.161262  .000865   .398882  .000537  I -.3943990  .0000284  1.4138 0.0231  I     3.070     .319      .192     .298  -.157000   .394000  -.3950000      .000      .000  
+85 520 46205.00 I  -.158584  .001205   .401605  .000631  I -.3957248  .0000377  1.2384 0.0271  I     2.955     .219     -.236     .298  -.155000   .397000  -.3964000      .000      .000  
+85 521 46206.00 I  -.155578  .001130   .404325  .000641  I -.3968812  .0000461  1.0792 0.0269  I     2.968     .219     -.514     .298  -.153000   .400000  -.3975000      .000      .000  
+85 522 46207.00 I  -.152367  .001011   .407057  .000637  I -.3978971  .0000385  0.9618 0.0326  I     3.020     .160     -.613     .298  -.151000   .403000  -.3986000      .000      .000  
+85 523 46208.00 I  -.149070  .000702   .409800  .000652  I -.3988270  .0000460  0.9109 0.0350  I     3.030     .791     -.644     .298  -.149000   .406000  -.3995000      .000      .000  
+85 524 46209.00 I  -.145811  .000702   .412542  .000652  I -.3997466  .0000584  0.9431 0.0402  I     3.009     .791     -.692     .298  -.147000   .409000  -.4005000      .000      .000  
+85 525 46210.00 I  -.142687  .000757   .415266  .000582  I -.4007451  .0000660  1.0710 0.0428  I     3.070     .791     -.751     .298  -.144000   .412000  -.4015000      .000      .000  
+85 526 46211.00 I  -.139715  .000679   .417959  .000555  I -.4019197  .0000625  1.2922 0.0427  I     3.289     .791     -.800     .298  -.142000   .415000  -.4027000      .000      .000  
+85 527 46212.00 I  -.136898  .000376   .420617  .000533  I -.4033516  .0000542  1.5795 0.0463  I     3.602     .124     -.845     .298  -.140000   .418000  -.4042000      .000      .000  
+85 528 46213.00 I  -.134239  .000421   .423234  .000555  I -.4050843  .0000684  1.8834 0.0440  I     3.868     .165     -.851     .298  -.137000   .420000  -.4059000      .000      .000  
+85 529 46214.00 I  -.131710  .000421   .425794  .000555  I -.4071018  .0000693  2.1375 0.0454  I     3.957     .165     -.718     .298  -.135000   .423000  -.4079000      .000      .000  
+85 530 46215.00 I  -.129268  .000393   .428277  .000511  I -.4093187  .0000598  2.2698 0.0454  I     3.789     .165     -.395     .298  -.132000   .426000  -.4100000      .000      .000  
+85 531 46216.00 I  -.126862  .000306   .430697  .000518  I -.4115847  .0000588  2.2321 0.0375  I     3.370     .165     -.014     .298  -.130000   .429000  -.4122000      .000      .000  
+85 6 1 46217.00 I  -.124466  .000373   .433064  .000470  I -.4137295  .0000453  2.0344 0.0409  I     2.877     .194      .217     .179  -.127000   .431000  -.4142000      .000      .000  
+85 6 2 46218.00 I  -.122062  .000396   .435383  .000374  I -.4156205  .0000568  1.7378 0.0370  I     2.564     .219      .234     .239  -.125000   .434000  -.4159000      .000      .000  
+85 6 3 46219.00 I  -.119627  .000383   .437662  .000411  I -.4172008  .0000586  1.4282 0.0405  I     2.540     .219      .149     .239  -.122000   .436000  -.4174000      .000      .000  
+85 6 4 46220.00 I  -.117138  .000383   .439906  .000411  I -.4185018  .0000578  1.1934 0.0409  I     2.724     .219      .039     .239  -.119000   .439000  -.4186000      .000      .000  
+85 6 5 46221.00 I  -.114629  .000501   .442113  .000485  I -.4196298  .0000570  1.0854 0.0361  I     3.011     .219     -.165     .239  -.117000   .441000  -.4198000      .000      .000  
+85 6 6 46222.00 I  -.112156  .000453   .444281  .000425  I -.4207131  .0000434  1.0991 0.0375  I     3.301     .172     -.511     .180  -.114000   .443000  -.4209000      .000      .000  
+85 6 7 46223.00 I  -.109765  .000456   .446419  .000424  I -.4218551  .0000487  1.1943 0.0331  I     3.412     .106     -.837     .298  -.112000   .445000  -.4221000      .000      .000  
+85 6 8 46224.00 I  -.107492  .000456   .448543  .000424  I -.4231118  .0000500  1.3199 0.0339  I     3.171     .106     -.907     .298  -.109000   .447000  -.4234000      .000      .000  
+85 6 9 46225.00 I  -.105357  .000437   .450662  .000414  I -.4244918  .0000473  1.4362 0.0322  I     2.626     .106     -.699     .298  -.106000   .449000  -.4248000      .000      .000  
+85 610 46226.00 I  -.103325  .000397   .452758  .000381  I -.4259725  .0000406  1.5174 0.0263  I     2.037     .106     -.430     .298  -.104000   .451000  -.4263000      .000      .000  
+85 611 46227.00 I  -.101352  .000405   .454805  .000470  I -.4275097  .0000230  1.5478 0.0276  I     1.575     .379     -.279     .175  -.101000   .453000  -.4279000      .000      .000  
+85 612 46228.00 I  -.099393  .000221   .456780  .000478  I -.4290493  .0000374  1.5218 0.0217  I     1.164     .525     -.203     .233  -.098000   .455000  -.4295000      .000      .000  
+85 613 46229.00 I  -.097404  .000221   .458668  .000478  I -.4305347  .0000367  1.4401 0.0254  I      .668     .525     -.062     .233  -.095000   .456000  -.4310000      .000      .000  
+85 614 46230.00 I  -.095335  .000221   .460461  .000478  I -.4319136  .0000344  1.3107 0.0279  I      .128     .525      .145     .233  -.093000   .458000  -.4324000      .000      .000  
+85 615 46231.00 I  -.093149  .000540   .462163  .000512  I -.4331459  .0000421  1.1507 0.0351  I     -.309     .525      .237     .233  -.090000   .460000  -.4337000      .000      .000  
+85 616 46232.00 I  -.090825  .000672   .463779  .000625  I -.4342128  .0000612  0.9842 0.0265  I     -.576     .742      .084     .327  -.087000   .462000  -.4348000      .000      .000  
+85 617 46233.00 I  -.088349  .000444   .465312  .000331  I -.4351203  .0000321  0.8359 0.0342  I     -.683    1.046     -.247     .396  -.084000   .464000  -.4358000      .000      .000  
+85 618 46234.00 I  -.085711  .000446   .466761  .000331  I -.4359015  .0000305  0.7383 0.0228  I     -.629     .986     -.591     .363  -.082000   .465000  -.4365000      .000      .000  
+85 619 46235.00 I  -.082936  .000446   .468118  .000331  I -.4366149  .0000325  0.6946 0.0228  I     -.406     .986     -.840     .363  -.079000   .467000  -.4372000      .000      .000  
+85 620 46236.00 I  -.080122  .000425   .469408  .000334  I -.4373028  .0000340  0.6872 0.0243  I      .100     .986     -.766     .363  -.076000   .468000  -.4378000      .000      .000  
+85 621 46237.00 I  -.077361  .000467   .470667  .000289  I -.4380153  .0000362  0.7579 0.0223  I      .599     .809     -.619     .297  -.073000   .470000  -.4385000      .000      .000  
+85 622 46238.00 I  -.074610  .000377   .471903  .000153  I -.4388551  .0000290  0.9381 0.0267  I      .909     .753     -.661     .221  -.070000   .471000  -.4393000      .000      .000  
+85 623 46239.00 I  -.071793  .000377   .473116  .000153  I -.4399191  .0000392  1.2010 0.0565  I     1.188     .465     -.790     .137  -.067000   .473000  -.4403000      .000      .000  
+85 624 46240.00 I  -.068839  .000698   .474303  .000403  I -.4412630  .0001093  1.4817 0.0499  I     1.488     .190     -.818     .298  -.064000   .474000  -.4416000      .000      .000  
+85 625 46241.00 I  -.065753  .000784   .475472  .000466  I -.4428618  .0000918  1.7003 0.0682  I     1.671     .190     -.649     .298  -.062000   .475000  -.4431000      .000      .000  
+85 626 46242.00 I  -.062576  .000731   .476631  .000452  I -.4446257  .0000815  1.8053 0.0647  I     1.531     .398     -.300     .169  -.058000   .477000  -.4447000      .000      .000  
+85 627 46243.00 I  -.059354  .000657   .477788  .000537  I -.4464248  .0000913  1.7675 0.0607  I     1.000     .530      .123     .220  -.056000   .478000  -.4463000      .000      .000  
+85 628 46244.00 I  -.056153  .000657   .478938  .000537  I -.4481124  .0000899  1.5850 0.0573  I      .250     .530      .479     .220  -.053000   .479000  -.4478000      .000      .000  
+85 629 46245.00 I  -.053034  .000657   .480065  .000537  I -.4495582  .0000692  1.2928 0.0554  I     -.387     .530      .652     .220  -.050000   .480000  -.4491000      .000      .000  
+85 630 46246.00 I  -.050009  .000610   .481156  .000405  I -.4506836  .0000646  0.9573 0.0475  I     -.679     .530      .642     .220  -.047000   .481000  -.4501000      .000      .000  
+85 7 1 46247.00 I  -.047069  .000610   .482203  .000405  I  .5485152  .0000650  0.6579 0.0516  I     -.633     .581      .540     .193  -.044000   .483000   .5492000      .000      .000  
+85 7 2 46248.00 I  -.044201  .000451   .483202  .000152  I  .5479681  .0000806  0.4560 0.0494  I     -.425     .628      .413     .161  -.041000   .484000   .5486000      .000      .000  
+85 7 3 46249.00 I  -.041392  .000502   .484143  .000204  I  .5475631  .0000743  0.3744 0.0568  I     -.210     .628      .237     .161  -.038000   .484000   .5482000      .000      .000  
+85 7 4 46250.00 I  -.038612  .000621   .485025  .000419  I  .5471829  .0000801  0.4020 0.0495  I     -.067     .628     -.021     .161  -.034000   .485000   .5477000      .000      .000  
+85 7 5 46251.00 I  -.035784  .000585   .485851  .000489  I  .5467352  .0000655  0.5011 0.0503  I     -.070     .518     -.285     .143  -.031000   .486000   .5472000      .000      .000  
+85 7 6 46252.00 I  -.032827  .000539   .486625  .000464  I  .5461737  .0000607  0.6211 0.0450  I     -.338     .578     -.419     .261  -.028000   .487000   .5465000      .000      .000  
+85 7 7 46253.00 I  -.029687  .000542   .487346  .000500  I  .5455003  .0000616  0.7193 0.0466  I     -.908     .542     -.411     .313  -.025000   .488000   .5458000      .000      .000  
+85 7 8 46254.00 I  -.026333  .000542   .488016  .000500  I  .5447512  .0000708  0.7694 0.0465  I    -1.633     .542     -.397     .313  -.022000   .489000   .5449000      .000      .000  
+85 7 9 46255.00 I  -.022800  .000492   .488669  .000542  I  .5439789  .0000697  0.7675 0.0433  I    -2.329     .542     -.374     .313  -.019000   .489000   .5440000      .000      .000  
+85 710 46256.00 I  -.019130  .000519   .489314  .000511  I  .5432315  .0000499  0.7198 0.0432  I    -2.910     .542     -.288     .313  -.016000   .490000   .5431000      .000      .000  
+85 711 46257.00 I  -.015371  .000463   .489951  .000569  I  .5425526  .0000512  0.6321 0.0379  I    -3.406     .682     -.087     .281  -.013000   .490000   .5423000      .000      .000  
+85 712 46258.00 I  -.011572  .000538   .490575  .000628  I  .5419778  .0000571  0.5127 0.0383  I    -3.850     .705      .168     .153  -.010000   .491000   .5416000      .000      .000  
+85 713 46259.00 I  -.007792  .000538   .491171  .000628  I  .5415318  .0000571  0.3793 0.0369  I    -4.185     .705      .273     .153  -.006000   .492000   .5411000      .000      .000  
+85 714 46260.00 I  -.004082  .000538   .491721  .000628  I  .5412161  .0000466  0.2553 0.0366  I    -4.296     .705      .059     .153  -.003000   .492000   .5408000      .000      .000  
+85 715 46261.00 I  -.000464  .000526   .492239  .000659  I  .5410125  .0000457  0.1576 0.0302  I    -4.144     .705     -.401     .153   .000000   .493000   .5405000      .000      .000  
+85 716 46262.00 I   .003063  .000533   .492745  .000573  I  .5408855  .0000384  0.1062 0.0297  I    -3.766     .636     -.865     .112   .003000   .493000   .5404000      .000      .000  
+85 717 46263.00 I   .006507  .000674   .493256  .000546  I  .5407766  .0000381  0.1253 0.0268  I    -3.285     .557    -1.122     .298   .006000   .493000   .5403000      .000      .000  
+85 718 46264.00 I   .009872  .000603   .493788  .000595  I  .5406063  .0000375  0.2303 0.0297  I    -2.914     .557    -1.097     .298   .010000   .494000   .5401000      .000      .000  
+85 719 46265.00 I   .013176  .000603   .494340  .000595  I  .5402860  .0000455  0.4254 0.0285  I    -2.846     .509     -.871     .298   .013000   .494000   .5398000      .000      .000  
+85 720 46266.00 I   .016429  .000573   .494873  .000572  I  .5397323  .0000430  0.6900 0.0301  I    -3.036     .509     -.635     .298   .016000   .494000   .5393000      .000      .000  
+85 721 46267.00 I   .019647  .000631   .495332  .000533  I  .5389012  .0000394  0.9691 0.0307  I    -3.290     .732     -.527     .519   .019000   .495000   .5386000      .000      .000  
+85 722 46268.00 I   .022886  .000672   .495665  .000535  I  .5378134  .0000437  1.1903 0.0301  I    -3.438     .829     -.549     .677   .023000   .495000   .5375000      .000      .000  
+85 723 46269.00 I   .026158  .000546   .495886  .000518  I  .5365587  .0000456  1.2973 0.0315  I    -3.518     .829     -.583     .677   .026000   .495000   .5363000      .000      .000  
+85 724 46270.00 I   .029459  .000557   .496025  .000563  I  .5352637  .0000453  1.2695 0.0354  I    -3.755     .829     -.485     .677   .029000   .495000   .5351000      .000      .000  
+85 725 46271.00 I   .032763  .000501   .496114  .000441  I  .5340619  .0000542  1.1149 0.0428  I    -4.208     .971     -.295     .804   .033000   .495000   .5339000      .000      .000  
+85 726 46272.00 I   .036041  .000556   .496176  .000490  I  .5330642  .0000726  0.8694 0.0533  I    -4.758     .662     -.117     .521   .036000   .495000   .5329000      .000      .000  
+85 727 46273.00 I   .039272  .000573   .496233  .000556  I  .5323336  .0000918  0.5925 0.0586  I    -5.211     .312     -.007     .298   .039000   .495000   .5321000      .000      .000  
+85 728 46274.00 I   .042463  .000573   .496285  .000556  I  .5318666  .0000920  0.3534 0.0640  I    -5.413     .312      .030     .298   .043000   .495000   .5316000      .000      .000  
+85 729 46275.00 I   .045629  .000573   .496323  .000556  I  .5315935  .0000892  0.2140 0.0608  I    -5.330     .312      .010     .298   .046000   .495000   .5313000      .000      .000  
+85 730 46276.00 I   .048765  .000639   .496335  .000462  I  .5313965  .0000794  0.2007 0.0557  I    -5.056     .312     -.077     .298   .049000   .495000   .5310000      .000      .000  
+85 731 46277.00 I   .051872  .000698   .496310  .000632  I  .5311553  .0000668  0.2978 0.0445  I    -4.763     .312     -.188     .298   .053000   .495000   .5307000      .000      .000  
+85 8 1 46278.00 I   .054974  .000788   .496231  .000833  I  .5307762  .0000400  0.4690 0.0369  I    -4.578     .313     -.274     .298   .056000   .495000   .5303000      .000      .000  
+85 8 2 46279.00 I   .058100  .000776   .496081  .000894  I  .5302084  .0000316  0.6669 0.0262  I    -4.597     .313     -.270     .298   .059000   .495000   .5297000      .000      .000  
+85 8 3 46280.00 I   .061323  .000776   .495838  .000894  I  .5294499  .0000339  0.8424 0.0257  I    -4.918     .313     -.138     .298   .063000   .494000   .5289000      .000      .000  
+85 8 4 46281.00 I   .064658  .000677   .495523  .000821  I  .5285432  .0000405  0.9590 0.0268  I    -5.541     .313      .067     .298   .066000   .494000   .5280000      .000      .000  
+85 8 5 46282.00 I   .068084  .000630   .495159  .000784  I  .5275565  .0000414  1.0016 0.0322  I    -6.339     .660      .220     .298   .069000   .494000   .5271000      .000      .000  
+85 8 6 46283.00 I   .071580  .000565   .494755  .000706  I  .5265648  .0000501  0.9697 0.0388  I    -7.081     .879      .252     .298   .073000   .493000   .5261000      .000      .000  
+85 8 7 46284.00 I   .075122  .000598   .494320  .000422  I  .5256392  .0000657  0.8715 0.0410  I    -7.519     .879      .238     .298   .076000   .493000   .5252000      .000      .000  
+85 8 8 46285.00 I   .078697  .000454   .493855  .000467  I  .5248374  .0000648  0.7264 0.0450  I    -7.551     .879      .285     .298   .080000   .493000   .5244000      .000      .000  
+85 8 9 46286.00 I   .082279  .000602   .493336  .000447  I  .5241943  .0000615  0.5575 0.0442  I    -7.398     .915      .369     .298   .083000   .492000   .5237000      .000      .000  
+85 810 46287.00 I   .085829  .000586   .492728  .000427  I  .5237231  .0000600  0.3866 0.0442  I    -7.340     .905      .341     .213   .086000   .492000   .5232000      .000      .000  
+85 811 46288.00 I   .089317  .000520   .491994  .000602  I  .5234146  .0000636  0.2354 0.0440  I    -7.451     .921      .110     .269   .090000   .491000   .5229000      .000      .000  
+85 812 46289.00 I   .092722  .000520   .491108  .000602  I  .5232339  .0000645  0.1394 0.0424  I    -7.600     .921     -.239     .269   .093000   .491000   .5226000      .000      .000  
+85 813 46290.00 I   .096012  .000518   .490110  .000686  I  .5231072  .0000562  0.1290 0.0377  I    -7.355     .921     -.509     .269   .096000   .490000   .5224000      .000      .000  
+85 814 46291.00 I   .099202  .000548   .489066  .000680  I  .5229433  .0000390  0.2162 0.0339  I    -6.762     .921     -.587     .269   .099000   .489000   .5222000      .000      .000  
+85 815 46292.00 I   .102330  .000824   .488030  .000752  I  .5226398  .0000378  0.4082 0.0247  I    -6.136     .772     -.485     .243   .103000   .488000   .5219000      .000      .000  
+85 816 46293.00 I   .105445  .000782   .487036  .000859  I  .5220976  .0000303  0.6881 0.0255  I    -5.663     .633     -.281     .126   .106000   .488000   .5213000      .000      .000  
+85 817 46294.00 I   .108604  .000758   .486110  .000698  I  .5212499  .0000342  1.0093 0.0228  I    -5.411     .633     -.089     .126   .109000   .487000   .5205000      .000      .000  
+85 818 46295.00 I   .111863  .000758   .485251  .000698  I  .5200893  .0000340  1.2997 0.0226  I    -5.438     .633     -.017     .126   .112000   .486000   .5194000      .000      .000  
+85 819 46296.00 I   .115192  .000864   .484438  .000665  I  .5186855  .0000295  1.4851 0.0234  I    -5.741     .633     -.086     .126   .115000   .485000   .5180000      .000      .000  
+85 820 46297.00 I   .118524  .000802   .483639  .000877  I  .5171687  .0000321  1.5217 0.0239  I    -6.235     .525     -.200     .298   .118000   .484000   .5166000      .000      .000  
+85 821 46298.00 I   .121791  .000696   .482814  .001017  I  .5156920  .0000375  1.4084 0.0286  I    -6.791     .390     -.226     .298   .121000   .483000   .5152000      .000      .000  
+85 822 46299.00 I   .124926  .000585   .481908  .001298  I  .5143879  .0000473  1.1869 0.0299  I    -7.304     .390     -.115     .298   .124000   .482000   .5140000      .000      .000  
+85 823 46300.00 I   .127884  .000622   .480877  .001369  I  .5133339  .0000467  0.9182 0.0329  I    -7.716     .340      .077     .298   .127000   .481000   .5130000      .000      .000  
+85 824 46301.00 I   .130691  .000614   .479741  .001284  I  .5125465  .0000456  0.6643 0.0370  I    -7.995     .340      .235     .298   .130000   .479000   .5123000      .000      .000  
+85 825 46302.00 I   .133380  .000789   .478546  .001402  I  .5119814  .0000574  0.4819 0.0426  I    -8.094     .900      .269     .242   .133000   .478000   .5117000      .000      .000  
+85 826 46303.00 I   .136005  .000809   .477310  .001369  I  .5115435  .0000719  0.4170 0.0453  I    -7.964    1.120      .140     .316   .136000   .477000   .5113000      .000      .000  
+85 827 46304.00 I   .138660  .000809   .475975  .001369  I  .5111038  .0000701  0.4828 0.0498  I    -7.674    1.120     -.116     .316   .139000   .476000   .5108000      .000      .000  
+85 828 46305.00 I   .141430  .000957   .474480  .001334  I  .5105460  .0000690  0.6442 0.0489  I    -7.395    1.120     -.406     .316   .142000   .474000   .5102000      .000      .000  
+85 829 46306.00 I   .144270  .001073   .472834  .000972  I  .5098009  .0000683  0.8489 0.0500  I    -7.260    1.354     -.616     .375   .145000   .473000   .5094000      .000      .000  
+85 830 46307.00 I   .147121  .001039   .471079  .000924  I  .5088480  .0000724  1.0540 0.0520  I    -7.334    1.098     -.651     .298   .148000   .471000   .5084000      .000      .000  
+85 831 46308.00 I   .149942  .001041   .469255  .000421  I  .5077043  .0000783  1.2249 0.0521  I    -7.600     .791     -.504     .298   .150000   .470000   .5072000      .000      .000  
+85 9 1 46309.00 I   .152721  .000950   .467398  .000411  I  .5064174  .0000749  1.3381 0.0525  I    -8.019     .791     -.290     .298   .153000   .468000   .5060000      .000      .000  
+85 9 2 46310.00 I   .155498  .001175   .465536  .001400  I  .5050530  .0000700  1.3767 0.0529  I    -8.558     .791     -.157     .298   .156000   .467000   .5047000      .000      .000  
+85 9 3 46311.00 I   .158276  .000975   .463694  .001430  I  .5036912  .0000746  1.3339 0.0479  I    -9.102     .541     -.153     .101   .159000   .465000   .5035000      .000      .000  
+85 9 4 46312.00 I   .161038  .000957   .461899  .001131  I  .5024070  .0000655  1.2258 0.0538  I    -9.450     .749     -.155     .144   .161000   .464000   .5023000      .000      .000  
+85 9 5 46313.00 I   .163789  .001020   .460177  .001227  I  .5012528  .0000776  1.0781 0.0507  I    -9.462     .870     -.023     .172   .164000   .462000   .5013000      .000      .000  
+85 9 6 46314.00 I   .166536  .001020   .458544  .001227  I  .5002573  .0000775  0.9108 0.0527  I    -9.194     .870      .214     .172   .166000   .460000   .5005000      .000      .000  
+85 9 7 46315.00 I   .169227  .001043   .456971  .001237  I  .4994287  .0000714  0.7511 0.0517  I    -8.915     .870      .276     .172   .169000   .458000   .4997000      .000      .000  
+85 9 8 46316.00 I   .171822  .000959   .455409  .001169  I  .4987417  .0000686  0.6318 0.0469  I    -8.668     .870      .043     .172   .171000   .456000   .4991000      .000      .000  
+85 9 9 46317.00 I   .174282  .000672   .453812  .000865  I  .4981437  .0000607  0.5768 0.0475  I    -8.179     .873     -.281     .176   .174000   .455000   .4985000      .000      .000  
+85 910 46318.00 I   .176573  .000450   .452131  .001043  I  .4975589  .0000657  0.6094 0.0373  I    -7.382     .833     -.477     .173   .176000   .453000   .4979000      .000      .000  
+85 911 46319.00 I   .178677  .000450   .450315  .001043  I  .4968903  .0000432  0.7458 0.0423  I    -6.597     .833     -.497     .173   .178000   .451000   .4971000      .000      .000  
+85 912 46320.00 I   .180611  .000543   .448316  .000954  I  .4960317  .0000532  0.9890 0.0341  I    -6.201     .833     -.409     .173   .181000   .449000   .4962000      .000      .000  
+85 913 46321.00 I   .182398  .000449   .446159  .000957  I  .4948855  .0000527  1.3124 0.0350  I    -6.236     .833     -.270     .173   .183000   .447000   .4949000      .000      .000  
+85 914 46322.00 I   .184053  .000505   .443888  .000839  I  .4934018  .0000454  1.6509 0.0379  I    -6.504     .798     -.091     .308   .185000   .445000   .4934000      .000      .000  
+85 915 46323.00 I   .185592  .000571   .441539  .000448  I  .4916065  .0000546  1.9209 0.0370  I    -6.869     .762      .049     .400   .187000   .442000   .4915000      .000      .000  
+85 916 46324.00 I   .187053  .000571   .439148  .000359  I  .4896077  .0000584  2.0476 0.0393  I    -7.295     .762      .022     .400   .189000   .440000   .4894000      .000      .000  
+85 917 46325.00 I   .188508  .000571   .436747  .000359  I  .4875697  .0000566  1.9989 0.0383  I    -7.705     .762     -.180     .400   .191000   .438000   .4873000      .000      .000  
+85 918 46326.00 I   .189998  .000433   .434355  .000428  I  .4856603  .0000496  1.7991 0.0359  I    -7.985     .762     -.373     .400   .193000   .436000   .4854000      .000      .000  
+85 919 46327.00 I   .191546  .000654   .431996  .000385  I  .4839986  .0000443  1.5182 0.0347  I    -8.120     .555     -.384     .347   .195000   .434000   .4837000      .000      .000  
+85 920 46328.00 I   .193176  .000719   .429680  .000381  I  .4826222  .0000484  1.2424 0.0332  I    -8.189     .191     -.243     .285   .197000   .431000   .4823000      .000      .000  
+85 921 46329.00 I   .194912  .000719   .427417  .000381  I  .4814891  .0000495  1.0408 0.0339  I    -8.223     .191     -.117     .285   .199000   .429000   .4812000      .000      .000  
+85 922 46330.00 I   .196776  .000818   .425207  .000457  I  .4805008  .0000475  0.9588 0.0335  I    -8.153     .191     -.099     .285   .200000   .427000   .4802000      .000      .000  
+85 923 46331.00 I   .198726  .000723   .423023  .000448  I  .4795289  .0000453  1.0047 0.0310  I    -7.918     .191     -.143     .285   .202000   .424000   .4791000      .000      .000  
+85 924 46332.00 I   .200685  .000669   .420838  .000464  I  .4784586  .0000400  1.1490 0.0317  I    -7.543     .268     -.167     .244   .204000   .422000   .4780000      .000      .000  
+85 925 46333.00 I   .202577  .000512   .418621  .000542  I  .4772123  .0000444  1.3493 0.0302  I    -7.144     .327     -.134     .195   .205000   .419000   .4767000      .000      .000  
+85 926 46334.00 I   .204362  .000512   .416327  .000542  I  .4757559  .0000452  1.5621 0.0311  I    -6.895     .327     -.024     .195   .207000   .417000   .4752000      .000      .000  
+85 927 46335.00 I   .206018  .000512   .413909  .000542  I  .4740976  .0000436  1.7464 0.0298  I    -6.938     .327      .214     .195   .208000   .414000   .4736000      .000      .000  
+85 928 46336.00 I   .207522  .000376   .411358  .000372  I  .4722834  .0000390  1.8697 0.0290  I    -7.223     .387      .595     .170   .210000   .412000   .4718000      .000      .000  
+85 929 46337.00 I   .208873  .000507   .408682  .000359  I  .4703842  .0000384  1.9149 0.0302  I    -7.566     .362     1.000     .145   .211000   .409000   .4699000      .000      .000  
+85 930 46338.00 I   .210079  .000543   .405896  .000284  I  .4684802  .0000461  1.8801 0.0307  I    -7.810     .384     1.225     .298   .212000   .406000   .4681000      .000      .000  
+8510 1 46339.00 I   .211149  .000527   .403012  .000278  I  .4666470  .0000480  1.7761 0.0343  I    -7.853     .384     1.188     .298   .214000   .404000   .4663000      .000      .000  
+8510 2 46340.00 I   .212122  .000527   .400053  .000278  I  .4649418  .0000508  1.6308 0.0356  I    -7.726     .384      .958     .298   .215000   .401000   .4646000      .000      .000  
+8510 3 46341.00 I   .213067  .000538   .397048  .000327  I  .4633893  .0000526  1.4739 0.0350  I    -7.482     .384      .712     .298   .216000   .398000   .4631000      .000      .000  
+8510 4 46342.00 I   .214036  .000602   .394029  .000251  I  .4619896  .0000482  1.3301 0.0420  I    -7.214     .372      .520     .298   .217000   .395000   .4617000      .000      .000  
+8510 5 46343.00 I   .215075  .000683   .391019  .000365  I  .4607163  .0000656  1.2246 0.0403  I    -7.045     .416      .283     .298   .219000   .392000   .4604000      .000      .000  
+8510 6 46344.00 I   .216228  .000701   .388042  .000774  I  .4595225  .0000647  1.1730 0.0449  I    -6.908     .416     -.018     .298   .220000   .390000   .4592000      .000      .000  
+8510 7 46345.00 I   .217527  .000701   .385111  .000774  I  .4583458  .0000613  1.1951 0.0436  I    -6.553     .416     -.203     .298   .220000   .387000   .4580000      .000      .000  
+8510 8 46346.00 I   .218911  .000738   .382221  .000793  I  .4571011  .0000584  1.3107 0.0406  I    -5.916     .416     -.111     .298   .221000   .384000   .4568000      .000      .000  
+8510 9 46347.00 I   .220280  .000686   .379362  .001027  I  .4556925  .0000534  1.5218 0.0425  I    -5.310     .312      .181     .298   .222000   .381000   .4554000      .000      .000  
+851010 46348.00 I   .221542  .000549   .376513  .001256  I  .4540317  .0000618  1.8103 0.0413  I    -5.105     .148      .459     .110   .223000   .378000   .4538000      .000      .000  
+851011 46349.00 I   .222619  .000549   .373620  .001256  I  .4520607  .0000631  2.1323 0.0435  I    -5.336     .148      .655     .110   .224000   .375000   .4518000      .000      .000  
+851012 46350.00 I   .223455  .000584   .370637  .001192  I  .4497784  .0000613  2.4204 0.0441  I    -5.772     .148      .876     .110   .225000   .372000   .4496000      .000      .000  
+851013 46351.00 I   .224080  .000469   .367587  .001083  I  .4472576  .0000617  2.5955 0.0400  I    -6.224     .148     1.148     .110   .226000   .369000   .4471000      .000      .000  
+851014 46352.00 I   .224562  .000588   .364512  .000947  I  .4446451  .0000513  2.5977 0.0416  I    -6.600     .249     1.303     .164   .226000   .366000   .4444000      .000      .000  
+851015 46353.00 I   .224966  .000535   .361454  .000691  I  .4421210  .0000559  2.4235 0.0392  I    -6.774     .320     1.227     .204   .227000   .363000   .4419000      .000      .000  
+851016 46354.00 I   .225359  .000535   .358452  .000691  I  .4398379  .0000593  2.1298 0.0548  I    -6.636     .320     1.060     .204   .228000   .360000   .4396000      .000      .000  
+851017 46355.00 I   .225798  .000535   .355520  .000691  I  .4378696  .0000942  1.8116 0.0510  I    -6.277     .320     1.023     .204   .228000   .358000   .4376000      .000      .000  
+851018 46356.00 I   .226285  .000494   .352648  .000620  I  .4361921  .0000830  1.5614 0.0585  I    -5.943     .320     1.111     .204   .229000   .355000   .4359000      .000      .000  
+851019 46357.00 I   .226795  .000572   .349824  .000554  I  .4347040  .0000694  1.4396 0.0660  I    -5.711     .346     1.102     .314   .229000   .352000   .4344000      .000      .000  
+851020 46358.00 I   .227307  .000499   .347014  .000612  I  .4332664  .0001027  1.4572 0.0636  I    -5.420     .370      .892     .394   .230000   .349000   .4329000      .000      .000  
+851021 46359.00 I   .227800  .000551   .344182  .000558  I  .4317540  .0001066  1.5817 0.0727  I    -4.949     .370      .659     .394   .230000   .346000   .4314000      .000      .000  
+851022 46360.00 I   .228257  .000508   .341300  .000568  I  .4300833  .0001030  1.7655 0.0615  I    -4.379     .370      .642     .394   .231000   .343000   .4297000      .000      .000  
+851023 46361.00 I   .228671  .000466   .338380  .000503  I  .4282195  .0000612  1.9600 0.0581  I    -3.874     .370      .848     .394   .231000   .340000   .4279000      .000      .000  
+851024 46362.00 I   .229030  .000475   .335455  .000454  I  .4261722  .0000538  2.1278 0.0461  I    -3.555     .501     1.112     .309   .231000   .337000   .4258000      .000      .000  
+851025 46363.00 I   .229326  .000410   .332557  .000354  I  .4239808  .0000690  2.2450 0.0307  I    -3.492     .604     1.337     .190   .232000   .334000   .4237000      .000      .000  
+851026 46364.00 I   .229560  .000410   .329701  .000354  I  .4217036  .0000296  2.2980 0.0367  I    -3.692     .604     1.533     .190   .232000   .331000   .4215000      .000      .000  
+851027 46365.00 I   .229736  .000400   .326901  .000293  I  .4194097  .0000252  2.2764 0.0210  I    -4.077     .543     1.653     .199   .232000   .328000   .4192000      .000      .000  
+851028 46366.00 I   .229840  .000410   .324156  .000239  I  .4171761  .0000299  2.1788 0.0225  I    -4.493     .543     1.613     .199   .232000   .326000   .4171000      .000      .000  
+851029 46367.00 I   .229859  .000512   .321447  .000386  I  .4150728  .0000373  2.0192 0.0262  I    -4.842     .480     1.419     .335   .232000   .323000   .4150000      .000      .000  
+851030 46368.00 I   .229785  .000547   .318755  .000429  I  .4131510  .0000430  1.8198 0.0293  I    -5.076     .373     1.301     .407   .233000   .320000   .4132000      .000      .000  
+851031 46369.00 I   .229620  .000547   .316060  .000429  I  .4114356  .0000451  1.6131 0.0310  I    -5.191     .373     1.444     .407   .233000   .317000   .4115000      .000      .000  
+8511 1 46370.00 I   .229408  .000547   .313351  .000429  I  .4099157  .0000447  1.4338 0.0351  I    -5.313     .373     1.612     .407   .233000   .314000   .4100000      .000      .000  
+8511 2 46371.00 I   .229171  .000616   .310637  .000511  I  .4085510  .0000539  1.3055 0.0383  I    -5.461     .368     1.635     .463   .233000   .312000   .4086000      .000      .000  
+8511 3 46372.00 I   .228924  .000717   .307937  .000551  I  .4072826  .0000623  1.2435 0.0413  I    -5.536     .467     1.503     .407   .233000   .309000   .4073000      .000      .000  
+8511 4 46373.00 I   .228693  .000657   .305271  .000445  I  .4060380  .0000627  1.2593 0.0460  I    -5.374     .548     1.373     .341   .233000   .306000   .4060000      .000      .000  
+8511 5 46374.00 I   .228504  .000633   .302658  .000783  I  .4047364  .0000677  1.3577 0.0482  I    -4.916     .548     1.442     .341   .232000   .303000   .4046000      .000      .000  
+8511 6 46375.00 I   .228386  .000633   .300114  .000783  I  .4032939  .0000731  1.5420 0.0476  I    -4.313     .548     1.672     .341   .232000   .301000   .4030000      .000      .000  
+8511 7 46376.00 I   .228334  .000637   .297638  .000693  I  .4016286  .0000670  1.7977 0.0490  I    -3.818     .548     1.820     .341   .232000   .298000   .4012000      .000      .000  
+8511 8 46377.00 I   .228320  .000638   .295220  .000661  I  .3996907  .0000653  2.0769 0.0469  I    -3.533     .728     1.855     .287   .232000   .295000   .3990000      .000      .000  
+8511 9 46378.00 I   .228317  .000677   .292843  .000737  I  .3974904  .0000657  2.3093 0.0463  I    -3.405     .872     1.947     .220   .232000   .293000   .3967000      .000      .000  
+851110 46379.00 I   .228298  .000677   .290458  .000737  I  .3951109  .0000657  2.4253 0.0462  I    -3.451     .872     2.194     .220   .232000   .290000   .3942000      .000      .000  
+851111 46380.00 I   .228247  .000736   .288015  .000560  I  .3926938  .0000650  2.3791 0.0457  I    -3.703     .872     2.441     .220   .231000   .288000   .3917000      .000      .000  
+851112 46381.00 I   .228135  .000741   .285484  .000485  I  .3904061  .0000635  2.1725 0.0440  I    -3.959     .872     2.484     .220   .231000   .285000   .3893000      .000      .000  
+851113 46382.00 I   .227954  .000777   .282861  .000633  I  .3883798  .0000594  1.8729 0.0430  I    -3.977     .638     2.380     .156   .231000   .282000   .3873000      .000      .000  
+851114 46383.00 I   .227722  .000821   .280152  .000772  I  .3866578  .0000580  1.5809 0.0426  I    -3.803     .234     2.359     .298   .230000   .280000   .3855000      .000      .000  
+851115 46384.00 I   .227464  .000756   .277366  .000781  I  .3851853  .0000611  1.3870 0.0449  I    -3.671     .234     2.445     .298   .230000   .277000   .3841000      .000      .000  
+851116 46385.00 I   .227247  .000756   .274515  .000781  I  .3838348  .0000685  1.3401 0.0411  I    -3.605     .234     2.394     .298   .230000   .275000   .3827000      .000      .000  
+851117 46386.00 I   .227107  .000780   .271641  .000971  I  .3824592  .0000551  1.4310 0.0441  I    -3.421     .234     2.080     .298   .229000   .272000   .3814000      .000      .000  
+851118 46387.00 I   .227067  .000985   .268788  .001078  I  .3809433  .0000557  1.6105 0.0296  I    -3.035     .681     1.731     .131   .229000   .270000   .3799000      .000      .000  
+851119 46388.00 I   .227161  .000543   .265981  .000614  I  .3792292  .0000219  1.8172 0.0300  I    -2.636     .958     1.676     .212   .229000   .267000   .3783000      .000      .000  
+851120 46389.00 I   .227422  .000540   .263244  .000583  I  .3773162  .0000224  2.0021 0.0189  I    -2.489     .885     1.955     .198   .228000   .265000   .3765000      .000      .000  
+851121 46390.00 I   .227857  .000540   .260599  .000583  I  .3752469  .0000307  2.1213 0.0225  I    -2.672     .885     2.339     .198   .228000   .262000   .3746000      .000      .000  
+851122 46391.00 I   .228289  .000539   .258093  .000578  I  .3731068  .0000390  2.1408 0.0246  I    -2.886     .885     2.792     .198   .227000   .260000   .3726000      .000      .000  
+851123 46392.00 I   .228513  .000559   .255777  .000457  I  .3709919  .0000385  2.0806 0.0268  I    -3.109     .761     3.227     .270   .227000   .257000   .3705000      .000      .000  
+851124 46393.00 I   .228522  .000309   .253611  .000305  I  .3689618  .0000367  1.9718 0.0266  I    -3.346     .654     3.575     .307   .226000   .255000   .3686000      .000      .000  
+851125 46394.00 I   .228351  .000309   .251535  .000305  I  .3670608  .0000368  1.8255 0.0574  I    -3.396     .491     3.770     .317   .226000   .252000   .3667000      .000      .000  
+851126 46395.00 I   .228034  .000506   .249492  .000456  I  .3653185  .0001087  1.6560 0.0453  I    -3.139     .426     3.674     .367   .225000   .250000   .3650000      .000      .000  
+851127 46396.00 I   .227578  .000642   .247438  .000422  I  .3637506  .0000827  1.4810 0.0581  I    -2.705     .426     3.317     .367   .225000   .247000   .3635000      .000      .000  
+851128 46397.00 I   .226974  .000593   .245348  .000553  I  .3623496  .0000413  1.3267 0.0487  I    -2.239     .364     2.914     .291   .224000   .245000   .3622000      .000      .000  
+851129 46398.00 I   .226214  .000534   .243204  .000602  I  .3610822  .0000514  1.2175 0.0386  I    -1.746     .195     2.650     .298   .224000   .243000   .3609000      .000      .000  
+851130 46399.00 I   .225289  .000686   .240987  .000554  I  .3598928  .0000653  1.1738 0.0429  I    -1.217     .195     2.540     .298   .223000   .240000   .3598000      .000      .000  
+8512 1 46400.00 I   .224203  .000686   .238690  .000554  I  .3587090  .0000687  1.2070 0.0454  I     -.735     .195     2.506     .298   .222000   .238000   .3586000      .000      .000  
+8512 2 46401.00 I   .222985  .000686   .236330  .000572  I  .3574534  .0000630  1.3164 0.0463  I     -.370     .195     2.514     .298   .222000   .235000   .3574000      .000      .000  
+8512 3 46402.00 I   .221664  .000963   .233938  .000528  I  .3560531  .0000620  1.4950 0.0466  I     -.163     .461     2.592     .114   .221000   .233000   .3560000      .000      .000  
+8512 4 46403.00 I   .220295  .001076   .231542  .000402  I  .3544448  .0000686  1.7292 0.0485  I     -.158     .551     2.724     .143   .220000   .231000   .3544000      .000      .000  
+8512 5 46404.00 I   .218965  .000978   .229164  .000369  I  .3525858  .0000746  1.9899 0.0481  I     -.361     .551     2.828     .143   .219000   .228000   .3526000      .000      .000  
+8512 6 46405.00 I   .217750  .000994   .226823  .000388  I  .3504737  .0000675  2.2243 0.0477  I     -.703     .551     2.892     .143   .219000   .226000   .3505000      .000      .000  
+8512 7 46406.00 I   .216636  .000992   .224519  .000391  I  .3481682  .0000595  2.3656 0.0438  I    -1.141     .551     3.029     .143   .218000   .224000   .3482000      .000      .000  
+8512 8 46407.00 I   .215563  .000910   .222242  .000435  I  .3457903  .0000557  2.3634 0.0417  I    -1.720     .611     3.297     .305   .217000   .221000   .3459000      .000      .000  
+8512 9 46408.00 I   .214475  .000550   .219989  .000409  I  .3434927  .0000583  2.2071 0.0413  I    -2.431     .665     3.548     .407   .216000   .219000   .3436000      .000      .000  
+851210 46409.00 I   .213331  .000550   .217755  .000409  I  .3414142  .0000609  1.9365 0.0407  I    -3.044     .665     3.586     .407   .215000   .217000   .3416000      .000      .000  
+851211 46410.00 I   .212100  .000532   .215538  .000403  I  .3396322  .0000567  1.6286 0.0420  I    -3.266     .665     3.442     .407   .215000   .215000   .3398000      .000      .000  
+851212 46411.00 I   .210811  .000515   .213345  .000434  I  .3381405  .0000578  1.3703 0.0387  I    -3.079     .665     3.334     .407   .214000   .213000   .3383000      .000      .000  
+851213 46412.00 I   .209523  .001023   .211181  .000403  I  .3368527  .0000527  1.2289 0.0414  I    -2.738     .479     3.366     .296   .212000   .211000   .3371000      .000      .000  
+851214 46413.00 I   .208303  .001161   .209052  .000319  I  .3356368  .0000593  1.2253 0.0406  I    -2.413     .132     3.390     .298   .211000   .208000   .3358000      .000      .000  
+851215 46414.00 I   .207217  .001156   .206963  .000635  I  .3343657  .0000617  1.3309 0.0426  I    -2.045     .132     3.257     .298   .210000   .206000   .3345000      .000      .000  
+851216 46415.00 I   .206324  .001156   .204913  .000635  I  .3329571  .0000613  1.4902 0.0431  I    -1.605     .132     3.081     .298   .209000   .204000   .3331000      .000      .000  
+851217 46416.00 I   .205587  .001105   .202891  .000565  I  .3313867  .0000603  1.6451 0.0409  I    -1.270     .132     3.127     .298   .208000   .202000   .3315000      .000      .000  
+851218 46417.00 I   .204918  .000955   .200878  .000926  I  .3296829  .0000541  1.7518 0.0423  I    -1.220     .791     3.430     .261   .207000   .200000   .3297000      .000      .000  
+851219 46418.00 I   .204245  .000571   .198834  .001048  I  .3279056  .0000592  1.7908 0.0410  I    -1.390     .791     3.731     .356   .206000   .198000   .3279000      .000      .000  
+851220 46419.00 I   .203505  .000571   .196704  .001048  I  .3261229  .0000617  1.7649 0.0423  I    -1.570     .791     3.809     .356   .205000   .196000   .3261000      .000      .000  
+851221 46420.00 I   .202651  .000561   .194441  .001030  I  .3243953  .0000603  1.6805 0.0426  I    -1.641     .791     3.722     .356   .203000   .194000   .3244000      .000      .000  
+851222 46421.00 I   .201682  .000561   .192067  .001030  I  .3227800  .0000587  1.5419 0.0388  I    -1.586     .791     3.656     .356   .202000   .192000   .3228000      .000      .000  
+851223 46422.00 I   .200599  .000491   .189640  .001141  I  .3213244  .0000490  1.3648 0.0547  I    -1.409     .791     3.653     .356   .201000   .190000   .3213000      .000      .000  
+851224 46423.00 I   .199401  .000472   .187217  .001061  I  .3200557  .0000924  1.1720 0.0475  I    -1.159     .791     3.596     .298   .199000   .188000   .3201000      .000      .000  
+851225 46424.00 I   .198074  .000472   .184830  .001061  I  .3189776  .0000813  0.9877 0.0535  I     -.970     .791     3.410     .298   .198000   .186000   .3191000      .000      .000  
+851226 46425.00 I   .196602  .000635   .182503  .000870  I  .3180691  .0000540  0.8371 0.0565  I     -.918     .791     3.190     .298   .196000   .184000   .3182000      .000      .000  
+851227 46426.00 I   .194969  .000648   .180259  .000787  I  .3172844  .0000786  0.7436 0.0373  I     -.892     .791     3.094     .298   .195000   .182000   .3174000      .000      .000  
+851228 46427.00 I   .193183  .000748   .178098  .000734  I  .3165573  .0000516  0.7238 0.0470  I     -.713     .329     3.174     .102   .193000   .180000   .3167000      .000      .000  
+851229 46428.00 I   .191268  .000748   .176008  .000734  I  .3158105  .0000516  0.7828 0.0356  I     -.363     .329     3.344     .102   .192000   .178000   .3159000      .000      .000  
+851230 46429.00 I   .189274  .000752   .173979  .000740  I  .3149682  .0000491  0.9123 0.0356  I     -.003     .329     3.484     .102   .190000   .176000   .3150000      .000      .000  
+851231 46430.00 I   .187278  .000752   .172001  .000740  I  .3139669  .0000492  1.0989 0.0348  I      .207     .329     3.534     .102   .188000   .174000   .3139000      .000      .000  
+86 1 1 46431.00 I   .185312  .000642   .170079  .000696  I  .3127601  .0000493  1.3163 0.0346  I      .236     .329     3.517     .102   .187000   .172000   .3126000      .000      .000  
+86 1 2 46432.00 I   .183379  .000595   .168223  .000660  I  .3113387  .0000486  1.5204 0.0433  I      .156     .414     3.491     .298   .185000   .170000   .3111000      .000      .000  
+86 1 3 46433.00 I   .181454  .000475   .166418  .000631  I  .3097389  .0000712  1.6656 0.0453  I      .041     .484     3.521     .298   .183000   .169000   .3094000      .000      .000  
+86 1 4 46434.00 I   .179503  .000475   .164642  .000631  I  .3080397  .0000765  1.7141 0.0523  I     -.089     .484     3.653     .298   .181000   .167000   .3076000      .000      .000  
+86 1 5 46435.00 I   .177500  .000370   .162872  .000611  I  .3063498  .0000767  1.6452 0.0530  I     -.269     .484     3.862     .298   .179000   .165000   .3058000      .000      .000  
+86 1 6 46436.00 I   .175449  .000429   .161098  .000572  I  .3047858  .0000735  1.4668 0.0505  I     -.522     .484     4.033     .298   .177000   .163000   .3042000      .000      .000  
+86 1 7 46437.00 I   .173353  .000327   .159317  .000634  I  .3034362  .0000656  1.2284 0.0574  I     -.722     .705     4.047     .191   .175000   .161000   .3028000      .000      .000  
+86 1 8 46438.00 I   .171218  .000280   .157523  .000652  I  .3023221  .0000882  1.0106 0.0432  I     -.672     .847     3.930     .260   .173000   .159000   .3017000      .000      .000  
+86 1 9 46439.00 I   .169057  .000280   .155692  .000652  I  .3013826  .0000563  0.8898 0.0485  I     -.314     .847     3.872     .260   .171000   .157000   .3008000      .000      .000  
+86 110 46440.00 I   .166891  .000280   .153788  .000652  I  .3004973  .0000405  0.9045 0.0361  I      .206     .847     4.034     .260   .169000   .155000   .2999000      .000      .000  
+86 111 46441.00 I   .164758  .000342   .151817  .000543  I  .2995308  .0000452  1.0476 0.0311  I      .543     .847     4.165     .260   .168000   .153000   .2990000      .000      .000  
+86 112 46442.00 I   .162690  .000556   .149796  .000624  I  .2983744  .0000473  1.2737 0.0436  I      .604     .739     4.065     .209   .165000   .151000   .2979000      .000      .000  
+86 113 46443.00 I   .160722  .000631   .147740  .000382  I  .2969782  .0000746  1.5156 0.0453  I      .507     .635     3.896     .154   .164000   .149000   .2966000      .000      .000  
+86 114 46444.00 I   .158878  .000714   .145663  .000459  I  .2953575  .0000773  1.7148 0.0568  I      .243     .468     3.916     .102   .161000   .147000   .2950000      .000      .000  
+86 115 46445.00 I   .157141  .000714   .143587  .000459  I  .2935775  .0000856  1.8272 0.0564  I     -.189     .468     4.236     .102   .159000   .145000   .2933000      .000      .000  
+86 116 46446.00 I   .155372  .000837   .141583  .000474  I  .2917394  .0000821  1.8306 0.0583  I     -.755     .468     4.589     .102   .157000   .144000   .2916000      .000      .000  
+86 117 46447.00 I   .153408  .000752   .139731  .000382  I  .2899452  .0000791  1.7471 0.0667  I    -1.339     .710     4.650     .298   .155000   .142000   .2898000      .000      .000  
+86 118 46448.00 I   .151200  .000744   .138054  .000278  I  .2882630  .0001051  1.6100 0.0653  I    -1.765     .699     4.474     .298   .153000   .141000   .2882000      .000      .000  
+86 119 46449.00 I   .148727  .000744   .136557  .000278  I  .2867365  .0001040  1.4390 0.0699  I    -1.930     .699     4.317     .298   .150000   .139000   .2867000      .000      .000  
+86 120 46450.00 I   .145986  .000897   .135246  .000254  I  .2853861  .0000922  1.2646 0.0627  I    -1.808     .792     4.296     .298   .148000   .137000   .2853000      .000      .000  
+86 121 46451.00 I   .143091  .000835   .134110  .000250  I  .2842001  .0000702  1.1117 0.0545  I    -1.489     .792     4.257     .298   .145000   .136000   .2842000      .000      .000  
+86 122 46452.00 I   .140167  .000798   .133107  .000350  I  .2831507  .0000581  0.9948 0.0466  I    -1.131     .619     4.052     .103   .142000   .135000   .2831000      .000      .000  
+86 123 46453.00 I   .137314  .000566   .132188  .000310  I  .2821915  .0000612  0.9348 0.0338  I     -.855     .129     3.712     .127   .140000   .133000   .2822000      .000      .000  
+86 124 46454.00 I   .134567  .000745   .131298  .000505  I  .2812568  .0000345  0.9478 0.0355  I     -.630     .149     3.382     .149   .137000   .132000   .2813000      .000      .000  
+86 125 46455.00 I   .131939  .000745   .130388  .000505  I  .2802680  .0000358  1.0444 0.0247  I     -.308     .149     3.167     .149   .134000   .131000   .2803000      .000      .000  
+86 126 46456.00 I   .129401  .000490   .129446  .000538  I  .2791405  .0000354  1.2236 0.0262  I      .160     .149     3.094     .149   .131000   .130000   .2793000      .000      .000  
+86 127 46457.00 I   .126889  .000501   .128481  .000637  I  .2777997  .0000383  1.4662 0.0295  I      .659     .426     3.108     .188   .128000   .128000   .2780000      .000      .000  
+86 128 46458.00 I   .124344  .000561   .127502  .000644  I  .2761995  .0000473  1.7345 0.0302  I     1.007     .542     3.158     .242   .125000   .127000   .2764000      .000      .000  
+86 129 46459.00 I   .121701  .000561   .126519  .000644  I  .2743377  .0000467  1.9818 0.0401  I     1.077     .542     3.280     .242   .122000   .126000   .2747000      .000      .000  
+86 130 46460.00 I   .118895  .000561   .125549  .000644  I  .2722597  .0000648  2.1578 0.0367  I      .840     .542     3.564     .242   .119000   .125000   .2727000      .000      .000  
+86 131 46461.00 I   .115908  .000521   .124658  .000619  I  .2700604  .0000566  2.2188 0.0399  I      .484     .542     3.764     .242   .116000   .124000   .2707000      .000      .000  
+86 2 1 46462.00 I   .112821  .000486   .123850  .000563  I  .2678653  .0000466  2.1502 0.0366  I      .107     .634     3.821     .249   .113000   .124000   .2686000      .000      .000  
+86 2 2 46463.00 I   .109714  .000475   .123099  .000433  I  .2657978  .0000465  1.9684 0.0338  I     -.289     .612     3.821     .239   .111000   .123000   .2668000      .000      .000  
+86 2 3 46464.00 I   .106661  .000394   .122378  .000463  I  .2639515  .0000490  1.7177 0.0360  I     -.711     .658     3.812     .222   .108000   .122000   .2651000      .000      .000  
+86 2 4 46465.00 I   .103734  .000398   .121667  .000452  I  .2623630  .0000550  1.4651 0.0326  I    -1.141     .658     3.826     .222   .105000   .122000   .2636000      .000      .000  
+86 2 5 46466.00 I   .100944  .000411   .121002  .000439  I  .2609992  .0000429  1.2787 0.0341  I    -1.376     .658     3.744     .222   .103000   .121000   .2624000      .000      .000  
+86 2 6 46467.00 I   .098291  .000439   .120373  .000502  I  .2597681  .0000403  1.2048 0.0325  I    -1.344     .531     3.558     .227   .100000   .121000   .2612000      .000      .000  
+86 2 7 46468.00 I   .095777  .000398   .119754  .000407  I  .2585474  .0000489  1.2574 0.0334  I    -1.119     .307     3.376     .203   .098000   .120000   .2600000      .000      .000  
+86 2 8 46469.00 I   .093387  .000515   .119115  .000614  I  .2572194  .0000532  1.4117 0.0364  I     -.767     .246     3.265     .234   .095000   .120000   .2587000      .000      .000  
+86 2 9 46470.00 I   .091103  .000565   .118430  .000633  I  .2557082  .0000538  1.6136 0.0344  I     -.320     .246     3.233     .234   .093000   .120000   .2571000      .000      .000  
+86 210 46471.00 I   .088893  .000544   .117719  .000601  I  .2539971  .0000436  1.8010 0.0334  I      .158     .246     3.270     .234   .091000   .119000   .2554000      .000      .000  
+86 211 46472.00 I   .086712  .000525   .117033  .000610  I  .2521272  .0000395  1.9254 0.0313  I      .523     .554     3.368     .221   .088000   .119000   .2535000      .000      .000  
+86 212 46473.00 I   .084518  .000536   .116424  .000566  I  .2501744  .0000448  1.9656 0.0329  I      .624     .744     3.479     .208   .086000   .119000   .2515000      .000      .000  
+86 213 46474.00 I   .082279  .000536   .115931  .000566  I  .2482237  .0000527  1.9227 0.0346  I      .422     .744     3.518     .208   .084000   .119000   .2495000      .000      .000  
+86 214 46475.00 I   .080014  .000536   .115531  .000566  I  .2463535  .0000527  1.8064 0.0381  I      .027     .744     3.457     .208   .081000   .119000   .2477000      .000      .000  
+86 215 46476.00 I   .077728  .000570   .115215  .000558  I  .2446300  .0000551  1.6327 0.0346  I     -.355     .744     3.380     .208   .079000   .118000   .2459000      .000      .000  
+86 216 46477.00 I   .075396  .000468   .114980  .000587  I  .2431000  .0000448  1.4234 0.0381  I     -.552     .867     3.389     .211   .076000   .118000   .2443000      .000      .000  
+86 217 46478.00 I   .072972  .000541   .114814  .000613  I  .2417861  .0000526  1.2054 0.0359  I     -.499     .976     3.459     .215   .074000   .118000   .2430000      .000      .000  
+86 218 46479.00 I   .070407  .000508   .114705  .000594  I  .2406830  .0000562  1.0058 0.0365  I     -.228     .976     3.437     .215   .072000   .118000   .2417000      .000      .000  
+86 219 46480.00 I   .067671  .000508   .114639  .000594  I  .2397571  .0000506  0.8583 0.0409  I      .166     .976     3.206     .215   .069000   .118000   .2406000      .000      .000  
+86 220 46481.00 I   .064784  .000612   .114612  .000574  I  .2389393  .0000594  0.7920 0.0356  I      .536     .976     2.825     .215   .066000   .118000   .2395000      .000      .000  
+86 221 46482.00 I   .061769  .000568   .114632  .000532  I  .2381421  .0000500  0.8186 0.0416  I      .759     .844     2.450     .170   .063000   .118000   .2385000      .000      .000  
+86 222 46483.00 I   .058642  .000530   .114705  .000354  I  .2372709  .0000583  0.9387 0.0382  I      .824     .687     2.201     .109   .060000   .118000   .2373000      .000      .000  
+86 223 46484.00 I   .055401  .000530   .114826  .000354  I  .2362378  .0000578  1.1395 0.0419  I      .838     .687     2.122     .109   .057000   .118000   .2360000      .000      .000  
+86 224 46485.00 I   .052054  .000498   .114988  .000325  I  .2349740  .0000601  1.3941 0.0402  I      .924     .687     2.206     .109   .054000   .118000   .2346000      .000      .000  
+86 225 46486.00 I   .048662  .000454   .115180  .000304  I  .2334475  .0000558  1.6549 0.0388  I     1.083     .687     2.375     .109   .051000   .118000   .2330000      .000      .000  
+86 226 46487.00 I   .045283  .000569   .115387  .000537  I  .2316829  .0000492  1.8595 0.0487  I     1.159     .643     2.525     .119   .048000   .118000   .2312000      .000      .000  
+86 227 46488.00 I   .041965  .000518   .115589  .000746  I  .2297646  .0000798  1.9558 0.0462  I      .987     .595     2.592     .128   .045000   .118000   .2292000      .000      .000  
+86 228 46489.00 I   .038757  .000544   .115766  .000792  I  .2278141  .0000781  1.9237 0.0571  I      .571     .595     2.581     .128   .042000   .118000   .2273000      .000      .000  
+86 3 1 46490.00 I   .035706  .000544   .115906  .000792  I  .2259578  .0000817  1.7698 0.0542  I      .096     .595     2.537     .128   .039000   .118000   .2255000      .000      .000  
+86 3 2 46491.00 I   .032791  .000758   .116044  .000781  I  .2243030  .0000751  1.5303 0.0517  I     -.230     .595     2.493     .128   .036000   .118000   .2239000      .000      .000  
+86 3 3 46492.00 I   .029953  .000634   .116217  .000748  I  .2229021  .0000634  1.2763 0.0536  I     -.313     .435     2.454     .298   .032000   .118000   .2226000      .000      .000  
+86 3 4 46493.00 I   .027128  .000616   .116443  .000749  I  .2217315  .0000766  1.0792 0.0397  I     -.187     .156     2.396     .298   .029000   .118000   .2216000      .000      .000  
+86 3 5 46494.00 I   .024253  .000639   .116739  .000623  I  .2207104  .0000478  0.9819 0.0548  I      .069     .156     2.293     .298   .026000   .118000   .2206000      .000      .000  
+86 3 6 46495.00 I   .021283  .000639   .117115  .000623  I  .2197275  .0000783  1.0051 0.0422  I      .386     .156     2.137     .298   .023000   .119000   .2197000      .000      .000  
+86 3 7 46496.00 I   .018245  .000581   .117561  .000557  I  .2186638  .0000696  1.1375 0.0508  I      .708     .156     1.968     .298   .020000   .119000   .2187000      .000      .000  
+86 3 8 46497.00 I   .015184  .000586   .118063  .000673  I  .2174311  .0000648  1.3341 0.0530  I      .981     .356     1.875     .168   .017000   .119000   .2175000      .000      .000  
+86 3 9 46498.00 I   .012129  .000489   .118590  .000678  I  .2159936  .0000799  1.5367 0.0500  I     1.169     .478     1.943     .237   .015000   .119000   .2161000      .000      .000  
+86 310 46499.00 I   .009097  .000632   .119104  .000677  I  .2143741  .0000762  1.6902 0.0598  I     1.282     .478     2.192     .237   .012000   .120000   .2145000      .000      .000  
+86 311 46500.00 I   .006107  .000708   .119568  .000741  I  .2126434  .0000890  1.7533 0.0515  I     1.367     .476     2.551     .222   .009000   .120000   .2128000      .000      .000  
+86 312 46501.00 I   .003162  .000685   .119982  .000721  I  .2109038  .0000694  1.7076 0.0552  I     1.453     .576     2.825     .209   .006000   .121000   .2111000      .000      .000  
+86 313 46502.00 I   .000266  .000709   .120366  .000701  I  .2092616  .0000653  1.5617 0.0528  I     1.529     .555     2.810     .278   .004000   .121000   .2095000      .000      .000  
+86 314 46503.00 I  -.002553  .000816   .120732  .000679  I  .2078046  .0000797  1.3431 0.0530  I     1.595     .590     2.444     .298   .001000   .121000   .2081000      .000      .000  
+86 315 46504.00 I  -.005233  .000792   .121082  .000853  I  .2065820  .0000834  1.1047 0.0575  I     1.577     .590     2.029     .298  -.002000   .122000   .2068000      .000      .000  
+86 316 46505.00 I  -.007745  .000792   .121426  .000853  I  .2055882  .0000828  0.8872 0.0588  I     1.638     .590     1.785     .298  -.004000   .123000   .2057000      .000      .000  
+86 317 46506.00 I  -.010088  .000697   .121808  .000841  I  .2047961  .0000828  0.7043 0.0509  I     1.906     .623     1.663     .325  -.007000   .123000   .2048000      .000      .000  
+86 318 46507.00 I  -.012282  .000481   .122274  .000853  I  .2041610  .0000592  0.5773 0.0517  I     2.331     .610     1.526     .311  -.009000   .124000   .2041000      .000      .000  
+86 319 46508.00 I  -.014357  .000340   .122843  .000967  I  .2036164  .0000618  0.5255 0.0453  I     2.858     .694     1.326     .232  -.011000   .124000   .2034000      .000      .000  
+86 320 46509.00 I  -.016346  .000455   .123521  .001003  I  .2030807  .0000687  0.5617 0.0467  I     3.406     .694     1.150     .232  -.014000   .125000   .2028000      .000      .000  
+86 321 46510.00 I  -.018278  .000485   .124312  .000913  I  .2024589  .0000699  0.7004 0.0451  I     3.784     .694     1.080     .232  -.016000   .126000   .2021000      .000      .000  
+86 322 46511.00 I  -.020183  .000664   .125208  .000806  I  .2016446  .0000584  0.9450 0.0471  I     3.803     .694     1.080     .232  -.018000   .127000   .2012000      .000      .000  
+86 323 46512.00 I  -.022093  .000562   .126208  .000746  I  .2005405  .0000632  1.2746 0.0446  I     3.525     .568     1.087     .168  -.021000   .128000   .2001000      .000      .000  
+86 324 46513.00 I  -.024062  .000663   .127293  .000681  I  .1990832  .0000674  1.6406 0.0461  I     3.267     .404     1.146     .298  -.023000   .129000   .1987000      .000      .000  
+86 325 46514.00 I  -.026177  .000663   .128425  .000681  I  .1972693  .0000671  1.9767 0.0458  I     3.229     .404     1.327     .298  -.025000   .130000   .1970000      .000      .000  
+86 326 46515.00 I  -.028501  .000612   .129563  .000559  I  .1951654  .0000619  2.2062 0.0463  I     3.234     .404     1.550     .298  -.027000   .131000   .1950000      .000      .000  
+86 327 46516.00 I  -.030986  .000551   .130692  .000460  I  .1929143  .0000637  2.2636 0.0443  I     2.965    1.057     1.619     .361  -.030000   .132000   .1930000      .000      .000  
+86 328 46517.00 I  -.033545  .000551   .131826  .000460  I  .1906985  .0000635  2.1401 0.0481  I     2.404    1.057     1.416     .361  -.032000   .134000   .1910000      .000      .000  
+86 329 46518.00 I  -.036090  .000432   .132981  .000340  I  .1886785  .0000722  1.8834 0.0508  I     1.896    1.439     1.028     .507  -.034000   .135000   .1892000      .000      .000  
+86 330 46519.00 I  -.038555  .000707   .134187  .000967  I  .1869491  .0000794  1.5745 0.0537  I     1.779    1.439      .660     .507  -.036000   .136000   .1878000      .000      .000  
+86 331 46520.00 I  -.040914  .000707   .135472  .000967  I  .1855148  .0000795  1.3096 0.0519  I     2.070    1.184      .432     .427  -.039000   .137000   .1865000      .000      .000  
+86 4 1 46521.00 I  -.043172  .000851   .136853  .000919  I  .1842927  .0000669  1.1563 0.0457  I     2.538    1.184      .328     .427  -.041000   .139000   .1854000      .000      .000  
+86 4 2 46522.00 I  -.045336  .000693   .138344  .000839  I  .1831580  .0000452  1.1357 0.0392  I     2.972     .799      .287     .307  -.043000   .140000   .1844000      .000      .000  
+86 4 3 46523.00 I  -.047454  .000739   .139934  .000889  I  .1819794  .0000407  1.2407 0.0303  I     3.279     .835      .268     .271  -.045000   .141000   .1832000      .000      .000  
+86 4 4 46524.00 I  -.049568  .000739   .141566  .000889  I  .1806466  .0000403  1.4357 0.0261  I     3.407     .835      .246     .271  -.047000   .143000   .1819000      .000      .000  
+86 4 5 46525.00 I  -.051700  .000666   .143185  .000878  I  .1790974  .0000328  1.6626 0.0241  I     3.293     .835      .228     .271  -.049000   .145000   .1803000      .000      .000  
+86 4 6 46526.00 I  -.053825  .000585   .144820  .000591  I  .1773314  .0000265  1.8596 0.0217  I     3.190     .960      .304     .308  -.051000   .146000   .1785000      .000      .000  
+86 4 7 46527.00 I  -.055874  .000509   .146521  .000656  I  .1754022  .0000283  1.9847 0.0189  I     3.276    1.193      .545     .235  -.053000   .148000   .1766000      .000      .000  
+86 4 8 46528.00 I  -.057773  .000441   .148339  .000558  I  .1733924  .0000270  2.0188 0.0217  I     3.503    1.292      .891     .112  -.055000   .150000   .1745000      .000      .000  
+86 4 9 46529.00 I  -.059477  .000481   .150309  .000655  I  .1713959  .0000329  1.9590 0.0251  I     3.852    1.388     1.175     .127  -.057000   .152000   .1725000      .000      .000  
+86 410 46530.00 I  -.060969  .000456   .152445  .000737  I  .1694985  .0000423  1.8268 0.0242  I     4.223    1.388     1.239     .127  -.059000   .154000   .1705000      .000      .000  
+86 411 46531.00 I  -.062290  .000459   .154704  .000682  I  .1677555  .0000355  1.6550 0.0274  I     4.511    1.388     1.075     .127  -.060000   .155000   .1687000      .000      .000  
+86 412 46532.00 I  -.063503  .000407   .157021  .000599  I  .1661917  .0000348  1.4737 0.0297  I     4.699    1.073      .844     .125  -.062000   .157000   .1671000      .000      .000  
+86 413 46533.00 I  -.064673  .000372   .159335  .000491  I  .1648015  .0000476  1.3121 0.0296  I     4.841     .106      .702     .123  -.064000   .159000   .1656000      .000      .000  
+86 414 46534.00 I  -.065863  .000384   .161602  .000515  I  .1635526  .0000480  1.1952 0.0338  I     4.954     .106      .624     .123  -.065000   .161000   .1643000      .000      .000  
+86 415 46535.00 I  -.067116  .000384   .163798  .000515  I  .1623914  .0000479  1.1375 0.0327  I     5.009     .106      .471     .123  -.067000   .163000   .1631000      .000      .000  
+86 416 46536.00 I  -.068423  .000363   .165915  .000232  I  .1612565  .0000443  1.1430 0.0342  I     5.081     .106      .213     .123  -.068000   .165000   .1619000      .000      .000  
+86 417 46537.00 I  -.069777  .000392   .167954  .000305  I  .1600837  .0000487  1.2136 0.0417  I     5.290     .147     -.016     .104  -.070000   .167000   .1607000      .000      .000  
+86 418 46538.00 I  -.071187  .000382   .169929  .000403  I  .1588076  .0000707  1.3492 0.0406  I     5.558     .179     -.121     .298  -.071000   .169000   .1594000      .000      .000  
+86 419 46539.00 I  -.072663  .000355   .171851  .000390  I  .1573670  .0000649  1.5398 0.0569  I     5.616     .179     -.211     .298  -.072000   .171000   .1579000      .000      .000  
+86 420 46540.00 I  -.074202  .000402   .173729  .000365  I  .1557132  .0000893  1.7749 0.0496  I     5.386     .179     -.414     .298  -.074000   .173000   .1562000      .000      .000  
+86 421 46541.00 I  -.075759  .000378   .175573  .000358  I  .1538128  .0000749  2.0234 0.0544  I     5.129     .179     -.609     .298  -.075000   .175000   .1541000      .000      .000  
+86 422 46542.00 I  -.077279  .000376   .177399  .000293  I  .1516836  .0000620  2.2204 0.0483  I     5.095     .338     -.507     .298  -.077000   .177000   .1519000      .000      .000  
+86 423 46543.00 I  -.078707  .000373   .179220  .000203  I  .1494123  .0000609  2.2967 0.0425  I     5.106     .443     -.038     .298  -.078000   .179000   .1495000      .000      .000  
+86 424 46544.00 I  -.080012  .000373   .181058  .000203  I  .1471433  .0000582  2.2138 0.0431  I     4.743     .443      .507     .298  -.079000   .181000   .1471000      .000      .000  
+86 425 46545.00 I  -.081171  .000373   .182934  .000203  I  .1450321  .0000611  1.9888 0.0322  I     3.941     .443      .786     .298  -.081000   .183000   .1449000      .000      .000  
+86 426 46546.00 I  -.082168  .000382   .184865  .000186  I  .1431903  .0000274  1.6900 0.0330  I     3.160     .443      .733     .298  -.082000   .185000   .1430000      .000      .000  
+86 427 46547.00 I  -.083015  .000386   .186866  .000483  I  .1416451  .0000251  1.4121 0.0210  I     2.866     .692      .546     .298  -.083000   .187000   .1414000      .000      .000  
+86 428 46548.00 I  -.083728  .000445   .188951  .000576  I  .1403312  .0000319  1.2389 0.0203  I     3.089     .872      .386     .298  -.084000   .189000   .1400000      .000      .000  
+86 429 46549.00 I  -.084328  .000445   .191137  .000576  I  .1391180  .0000319  1.2135 0.0212  I     3.553     .872      .224     .298  -.085000   .191000   .1388000      .000      .000  
+86 430 46550.00 I  -.084841  .000455   .193434  .000834  I  .1378587  .0000278  1.3246 0.0203  I     4.032     .872     -.009     .298  -.086000   .193000   .1376000      .000      .000  
+86 5 1 46551.00 I  -.085302  .000636   .195807  .000796  I  .1364402  .0000250  1.5216 0.0172  I     4.423     .784     -.239     .298  -.087000   .195000   .1362000      .000      .000  
+86 5 2 46552.00 I  -.085766  .000660   .198188  .000836  I  .1348073  .0000203  1.7433 0.0194  I     4.716     .709     -.359     .298  -.088000   .197000   .1346000      .000      .000  
+86 5 3 46553.00 I  -.086310  .000888   .200499  .000978  I  .1329628  .0000297  1.9374 0.0206  I     4.895     .496     -.350     .298  -.089000   .199000   .1328000      .000      .000  
+86 5 4 46554.00 I  -.087006  .001011   .202681  .001077  I  .1309539  .0000359  2.0672 0.0268  I     4.888     .496     -.240     .298  -.090000   .201000   .1309000      .000      .000  
+86 5 5 46555.00 I  -.087865  .000839   .204743  .000956  I  .1288565  .0000445  2.1128 0.0259  I     4.777     .496     -.085     .298  -.090000   .203000   .1289000      .000      .000  
+86 5 6 46556.00 I  -.088838  .000672   .206708  .000870  I  .1267570  .0000374  2.0722 0.0295  I     4.610     .496      .108     .298  -.091000   .205000   .1268000      .000      .000  
+86 5 7 46557.00 I  -.089873  .000225   .208598  .000224  I  .1247376  .0000388  1.9551 0.0275  I     4.468     .257      .263     .109  -.092000   .207000   .1248000      .000      .000  
+86 5 8 46558.00 I  -.090917  .000225   .210433  .000224  I  .1228653  .0000404  1.7824 0.0311  I     4.441     .791      .233     .134  -.092000   .210000   .1230000      .000      .000  
+86 5 9 46559.00 I  -.091923  .000225   .212232  .000224  I  .1211815  .0000486  1.5834 0.0306  I     4.507     .791     -.005     .134  -.093000   .212000   .1214000      .000      .000  
+86 510 46560.00 I  -.092849  .000225   .214013  .000224  I  .1196996  .0000461  1.3810 0.0305  I     4.574     .791     -.246     .134  -.094000   .214000   .1199000      .000      .000  
+86 511 46561.00 I  -.093688  .000275   .215808  .000204  I  .1184135  .0000370  1.1966 0.0366  I     4.600     .791     -.292     .134  -.094000   .216000   .1187000      .000      .000  
+86 512 46562.00 I  -.094451  .000623   .217648  .000550  I  .1172924  .0000569  1.0543 0.0384  I     4.567     .342     -.178     .262  -.095000   .218000   .1176000      .000      .000  
+86 513 46563.00 I  -.095149  .000771   .219567  .000658  I  .1162853  .0000673  0.9707 0.0443  I     4.458     .434     -.148     .375  -.095000   .221000   .1167000      .000      .000  
+86 514 46564.00 I  -.095796  .000726   .221597  .000626  I  .1153295  .0000679  0.9516 0.0443  I     4.353     .434     -.395     .375  -.096000   .223000   .1157000      .000      .000  
+86 515 46565.00 I  -.096430  .000617   .223764  .000699  I  .1143641  .0000575  0.9864 0.0446  I     4.420     .577     -.856     .313  -.096000   .225000   .1147000      .000      .000  
+86 516 46566.00 I  -.097129  .000617   .226072  .000699  I  .1133334  .0000578  1.0910 0.0421  I     4.631     .577     -.962     .313  -.097000   .227000   .1135000      .000      .000  
+86 517 46567.00 I  -.097864  .000627   .228443  .000700  I  .1121536  .0000616  1.2810 0.0477  I     4.761     .577     -.606     .313  -.097000   .229000   .1122000      .000      .000  
+86 518 46568.00 I  -.098581  .000702   .230775  .000824  I  .1107561  .0000760  1.5170 0.0463  I     4.713     .634     -.336     .287  -.098000   .232000   .1107000      .000      .000  
+86 519 46569.00 I  -.099267  .000362   .233012  .000701  I  .1091256  .0000692  1.7350 0.0547  I     4.612     .739     -.291     .193  -.098000   .234000   .1089000      .000      .000  
+86 520 46570.00 I  -.099946  .000418   .235158  .000780  I  .1073146  .0000787  1.8676 0.0537  I     4.623     .739     -.162     .193  -.099000   .236000   .1070000      .000      .000  
+86 521 46571.00 I  -.100619  .000345   .237225  .000474  I  .1054365  .0000821  1.8619 0.0557  I     4.658     .791      .222     .298  -.099000   .238000   .1051000      .000      .000  
+86 522 46572.00 I  -.101277  .000516   .239225  .000479  I  .1036423  .0000789  1.7018 0.0579  I     4.430     .292      .623     .411  -.100000   .240000   .1033000      .000      .000  
+86 523 46573.00 I  -.101901  .000508   .241178  .000515  I  .1020719  .0000816  1.4247 0.0564  I     3.913     .292      .668     .411  -.100000   .242000   .1018000      .000      .000  
+86 524 46574.00 I  -.102451  .000508   .243121  .000515  I  .1008047  .0000806  1.1122 0.0545  I     3.446     .292      .302     .411  -.100000   .244000   .1006000      .000      .000  
+86 525 46575.00 I  -.102876  .000508   .245094  .000515  I  .0998261  .0000723  0.8639 0.0492  I     3.318     .292     -.189     .411  -.101000   .246000   .0997000      .000      .000  
+86 526 46576.00 I  -.103160  .000430   .247103  .000351  I  .0990329  .0000565  0.7476 0.0438  I     3.503     .292     -.570     .411  -.102000   .248000   .0990000      .000      .000  
+86 527 46577.00 I  -.103325  .000412   .249134  .000348  I  .0982836  .0000493  0.7731 0.0427  I     3.748     .445     -.844     .373  -.102000   .250000   .0983000      .000      .000  
+86 528 46578.00 I  -.103399  .000294   .251173  .000337  I  .0974527  .0000640  0.9007 0.0359  I     3.846     .558    -1.049     .329  -.103000   .252000   .0976000      .000      .000  
+86 529 46579.00 I  -.103404  .000294   .253206  .000337  I  .0964718  .0000523  1.0595 0.0420  I     3.766     .558    -1.078     .329  -.103000   .253000   .0967000      .000      .000  
+86 530 46580.00 I  -.103346  .000294   .255218  .000337  I  .0953424  .0000545  1.1922 0.0370  I     3.622     .558     -.820     .329  -.103000   .255000   .0956000      .000      .000  
+86 531 46581.00 I  -.103243  .000340   .257218  .000427  I  .0941066  .0000523  1.2672 0.0335  I     3.537     .558     -.380     .329  -.104000   .257000   .0944000      .000      .000  
+86 6 1 46582.00 I  -.103123  .000329   .259234  .000478  I  .0928334  .0000390  1.2660 0.0381  I     3.595     .666      .001     .297  -.104000   .259000   .0932000      .000      .000  
+86 6 2 46583.00 I  -.103011  .000363   .261304  .000555  I  .0915998  .0000554  1.1893 0.0294  I     3.723     .760      .209     .260  -.104000   .261000   .0919000      .000      .000  
+86 6 3 46584.00 I  -.102934  .000361   .263462  .000531  I  .0904755  .0000439  1.0504 0.0354  I     3.703     .760      .326     .260  -.104000   .263000   .0908000      .000      .000  
+86 6 4 46585.00 I  -.102910  .000361   .265735  .000531  I  .0895140  .0000442  0.8663 0.0291  I     3.396     .760      .412     .260  -.104000   .265000   .0899000      .000      .000  
+86 6 5 46586.00 I  -.102914  .000325   .268094  .000538  I  .0887517  .0000383  0.6557 0.0257  I     2.922     .760      .368     .260  -.104000   .267000   .0891000      .000      .000  
+86 6 6 46587.00 I  -.102903  .000303   .270487  .000637  I  .0882035  .0000261  0.4423 0.0380  I     2.444     .541      .103     .354  -.103000   .269000   .0885000      .000      .000  
+86 6 7 46588.00 I  -.102833  .000277   .272860  .000635  I  .0878589  .0000657  0.2534 0.0409  I     1.995     .791     -.247     .427  -.103000   .271000   .0881000      .000      .000  
+86 6 8 46589.00 I  -.102660  .000277   .275152  .000635  I  .0876797  .0000776  0.1155 0.0515  I     1.551     .791     -.400     .427  -.102000   .274000   .0879000      .000      .000  
+86 6 9 46590.00 I  -.102342  .000308   .277314  .000691  I  .0876058  .0000793  0.0440 0.0558  I     1.124     .791     -.231     .427  -.101000   .276000   .0878000      .000      .000  
+86 610 46591.00 I  -.101845  .000295   .279349  .000590  I  .0875678  .0000801  0.0442 0.0536  I      .738     .791      .072     .427  -.100000   .278000   .0877000      .000      .000  
+86 611 46592.00 I  -.101155  .000745   .281292  .000608  I  .0874923  .0000721  0.1197 0.0682  I      .452     .352      .230     .389  -.100000   .280000   .0875000      .000      .000  
+86 612 46593.00 I  -.100277  .000891   .283176  .000502  I  .0873049  .0001104  0.2659 0.0766  I      .407     .412      .137     .318  -.099000   .282000   .0872000      .000      .000  
+86 613 46594.00 I  -.099225  .000948   .285031  .000543  I  .0869416  .0001352  0.4690 0.0864  I      .725     .412     -.181     .318  -.098000   .284000   .0867000      .000      .000  
+86 614 46595.00 I  -.098024  .000948   .286885  .000543  I  .0863563  .0001329  0.7039 0.0865  I     1.320     .412     -.729     .318  -.096000   .287000   .0859000      .000      .000  
+86 615 46596.00 I  -.096693  .000804   .288773  .000483  I  .0855339  .0001080  0.9385 0.0698  I     1.819     .537    -1.207     .412  -.095000   .289000   .0850000      .000      .000  
+86 616 46597.00 I  -.095276  .000468   .290712  .000299  I  .0844919  .0000425  1.1354 0.0582  I     1.940     .615    -1.369     .526  -.094000   .291000   .0838000      .000      .000  
+86 617 46598.00 I  -.093812  .000488   .292705  .000264  I  .0832929  .0000433  1.2429 0.0290  I     1.603     .601     -.949     .562  -.093000   .293000   .0826000      .000      .000  
+86 618 46599.00 I  -.092335  .000253   .294749  .000213  I  .0820471  .0000394  1.2274 0.0249  I      .806     .667      .112     .613  -.092000   .296000   .0814000      .000      .000  
+86 619 46600.00 I  -.090889  .000253   .296847  .000213  I  .0808817  .0000246  1.0809 0.0240  I     -.121     .667      .732     .613  -.090000   .298000   .0803000      .000      .000  
+86 620 46601.00 I  -.089542  .000276   .299006  .000219  I  .0799154  .0000275  0.8439 0.0183  I     -.865     .667      .731     .613  -.089000   .300000   .0794000      .000      .000  
+86 621 46602.00 I  -.088276  .000304   .301210  .000214  I  .0791929  .0000271  0.6097 0.0182  I    -1.169     .484      .461     .464  -.088000   .303000   .0788000      .000      .000  
+86 622 46603.00 I  -.087034  .000261   .303439  .000158  I  .0786670  .0000237  0.4625 0.0451  I     -.954     .129      .146     .187  -.087000   .305000   .0784000      .000      .000  
+86 623 46604.00 I  -.085751  .000473   .305684  .000297  I  .0782238  .0000861  0.4477 0.0466  I     -.436     .157     -.058     .298  -.085000   .307000   .0781000      .000      .000  
+86 624 46605.00 I  -.084370  .000482   .307936  .000555  I  .0777276  .0000901  0.5650 0.0586  I      .083     .157     -.227     .298  -.084000   .309000   .0777000      .000      .000  
+86 625 46606.00 I  -.082897  .000437   .310196  .000500  I  .0770662  .0000795  0.7650 0.0619  I      .416     .157     -.434     .298  -.083000   .311000   .0771000      .000      .000  
+86 626 46607.00 I  -.081352  .000387   .312466  .000695  I  .0761962  .0000850  0.9692 0.0674  I      .433     .340     -.528     .239  -.081000   .313000   .0762000      .000      .000  
+86 627 46608.00 I  -.079745  .000223   .314743  .000834  I  .0751471  .0001089  1.1157 0.0723  I      .037     .454     -.300     .336  -.080000   .316000   .0752000      .000      .000  
+86 628 46609.00 I  -.078095  .000337   .317015  .000862  I  .0739938  .0001171  1.1754 0.0766  I     -.667     .454      .201     .336  -.079000   .318000   .0740000      .000      .000  
+86 629 46610.00 I  -.076437  .000337   .319251  .000862  I  .0728272  .0001078  1.1426 0.0760  I    -1.368     .454      .677     .336  -.077000   .320000   .0728000      .000      .000  
+86 630 46611.00 I  -.074819  .000515   .321453  .000722  I  .0717335  .0000968  1.0352 0.0692  I    -1.836     .454      .896     .336  -.076000   .322000   .0717000      .000      .000  
+86 7 1 46612.00 I  -.073288  .000485   .323644  .000715  I  .0707726  .0000867  0.8803 0.0602  I    -2.137     .406      .909     .272  -.075000   .324000   .0707000      .000      .000  
+86 7 2 46613.00 I  -.071864  .000618   .325834  .000591  I  .0699821  .0000717  0.6979 0.0504  I    -2.431     .352      .853     .189  -.073000   .326000   .0699000      .000      .000  
+86 7 3 46614.00 I  -.070558  .000571   .328031  .000431  I  .0693782  .0000516  0.5115 0.0401  I    -2.703     .352      .686     .189  -.072000   .328000   .0693000      .000      .000  
+86 7 4 46615.00 I  -.069363  .000568   .330236  .000420  I  .0689524  .0000358  0.3452 0.0312  I    -2.815     .294      .256     .170  -.070000   .330000   .0689000      .000      .000  
+86 7 5 46616.00 I  -.068207  .000531   .332442  .000447  I  .0686737  .0000351  0.2210 0.0260  I    -2.748     .294     -.343     .170  -.069000   .332000   .0686000      .000      .000  
+86 7 6 46617.00 I  -.067004  .000402   .334648  .000425  I  .0684897  .0000376  0.1588 0.0268  I    -2.588     .305     -.765     .276  -.067000   .334000   .0684000      .000      .000  
+86 7 7 46618.00 I  -.065692  .000478   .336846  .000284  I  .0683299  .0000404  0.1751 0.0290  I    -2.382     .267     -.724     .324  -.066000   .336000   .0683000      .000      .000  
+86 7 8 46619.00 I  -.064318  .000478   .339016  .000284  I  .0681120  .0000442  0.2738 0.0300  I    -2.168     .267     -.355     .324  -.064000   .338000   .0681000      .000      .000  
+86 7 9 46620.00 I  -.062954  .000899   .341131  .000989  I  .0677608  .0000444  0.4369 0.0400  I    -2.023     .267     -.012     .324  -.063000   .340000   .0677000      .000      .000  
+86 710 46621.00 I  -.061644  .000820   .343144  .000973  I  .0672256  .0000666  0.6377 0.0394  I    -1.974     .320      .132     .378  -.061000   .342000   .0672000      .000      .000  
+86 711 46622.00 I  -.060394  .000826   .344996  .000934  I  .0664822  .0000652  0.8482 0.0482  I    -1.955     .498      .138     .262  -.060000   .344000   .0665000      .000      .000  
+86 712 46623.00 I  -.059201  .000921   .346626  .001008  I  .0655386  .0000698  1.0305 0.0475  I    -1.915     .589      .140     .127  -.058000   .346000   .0656000      .000      .000  
+86 713 46624.00 I  -.057992  .000905   .348012  .001004  I  .0644446  .0000690  1.1426 0.0489  I    -1.927     .589      .210     .127  -.056000   .348000   .0645000      .000      .000  
+86 714 46625.00 I  -.056638  .000905   .349195  .001004  I  .0632836  .0000685  1.1641 0.0470  I    -2.155     .589      .343     .127  -.054000   .350000   .0633000      .000      .000  
+86 715 46626.00 I  -.055124  .000455   .350248  .000640  I  .0621501  .0000639  1.0844 0.0462  I    -2.699     .519      .484     .135  -.053000   .351000   .0622000      .000      .000  
+86 716 46627.00 I  -.053477  .000449   .351247  .000655  I  .0611486  .0000619  0.9034 0.0393  I    -3.492     .486      .574     .161  -.051000   .353000   .0611000      .000      .000  
+86 717 46628.00 I  -.051711  .000343   .352262  .000696  I  .0603652  .0000458  0.6566 0.0417  I    -4.316     .353      .505     .189  -.049000   .354000   .0602000      .000      .000  
+86 718 46629.00 I  -.049825  .000343   .353364  .000696  I  .0598363  .0000560  0.4071 0.0364  I    -4.909     .353      .203     .189  -.047000   .356000   .0597000      .000      .000  
+86 719 46630.00 I  -.047823  .000337   .354603  .000725  I  .0595248  .0000566  0.2361 0.0375  I    -5.199     .353     -.040     .189  -.045000   .358000   .0593000      .000      .000  
+86 720 46631.00 I  -.045742  .000314   .355959  .000674  I  .0593177  .0000499  0.2042 0.0368  I    -5.252     .353     -.015     .189  -.043000   .359000   .0591000      .000      .000  
+86 721 46632.00 I  -.043634  .000447   .357389  .000576  I  .0590660  .0000471  0.3234 0.0363  I    -5.208     .824      .239     .228  -.042000   .360000   .0588000      .000      .000  
+86 722 46633.00 I  -.041552  .000504   .358849  .000394  I  .0586337  .0000527  0.5541 0.0352  I    -5.075    1.091      .470     .253  -.040000   .362000   .0584000      .000      .000  
+86 723 46634.00 I  -.039560  .000504   .360304  .000394  I  .0579461  .0000522  0.8198 0.0323  I    -4.673    1.330      .409     .241  -.038000   .363000   .0577000      .000      .000  
+86 724 46635.00 I  -.037728  .000341   .361725  .000391  I  .0570104  .0000374  1.0368 0.0309  I    -3.925    1.330      .028     .241  -.036000   .364000   .0568000      .000      .000  
+86 725 46636.00 I  -.036067  .000542   .363091  .000362  I  .0559092  .0000329  1.1439 0.0268  I    -3.423    1.164     -.284     .216  -.034000   .365000   .0558000      .000      .000  
+86 726 46637.00 I  -.034531  .000524   .364382  .000338  I  .0547645  .0000385  1.1252 0.0262  I    -3.883    1.015     -.189     .176  -.033000   .367000   .0547000      .000      .000  
+86 727 46638.00 I  -.033067  .000538   .365577  .000314  I  .0536947  .0000407  0.9987 0.0276  I    -5.065     .975      .139     .112  -.031000   .368000   .0536000      .000      .000  
+86 728 46639.00 I  -.031637  .000538   .366669  .000314  I  .0527888  .0000396  0.8070 0.0286  I    -6.121     .975      .350     .112  -.029000   .368000   .0527000      .000      .000  
+86 729 46640.00 I  -.030274  .000538   .367690  .000314  I  .0520890  .0000403  0.5904 0.0283  I    -6.605     .542      .482     .298  -.028000   .369000   .0520000      .000      .000  
+86 730 46641.00 I  -.028996  .000495   .368666  .000545  I  .0516086  .0000405  0.3719 0.0321  I    -6.661     .476      .679     .298  -.026000   .370000   .0515000      .000      .000  
+86 731 46642.00 I  -.027795  .000367   .369619  .000914  I  .0513373  .0000501  0.1771 0.0348  I    -6.537     .581      .890     .146  -.025000   .371000   .0511000      .000      .000  
+86 8 1 46643.00 I  -.026634  .000390   .370570  .001029  I  .0512372  .0000565  0.0338 0.0385  I    -6.350     .507      .876     .203  -.024000   .372000   .0509000      .000      .000  
+86 8 2 46644.00 I  -.025468  .000348   .371543  .001071  I  .0512451  .0000585 -0.0358 0.0406  I    -6.215     .507      .458     .203  -.022000   .372000   .0509000      .000      .000  
+86 8 3 46645.00 I  -.024242  .000334   .372545  .001074  I  .0512849  .0000583 -0.0336 0.0396  I    -6.247     .507     -.223     .203  -.021000   .373000   .0509000      .000      .000  
+86 8 4 46646.00 I  -.022891  .000315   .373498  .001009  I  .0512841  .0000533  0.0534 0.0384  I    -6.523     .507     -.616     .203  -.020000   .374000   .0508000      .000      .000  
+86 8 5 46647.00 I  -.021434  .000340   .374402  .000948  I  .0511452  .0000501  0.2392 0.0354  I    -6.937     .504     -.530     .178  -.019000   .375000   .0506000      .000      .000  
+86 8 6 46648.00 I  -.019918  .000366   .375285  .000653  I  .0507817  .0000467  0.4970 0.0325  I    -7.341     .369     -.184     .141  -.018000   .376000   .0502000      .000      .000  
+86 8 7 46649.00 I  -.018396  .000306   .376154  .000546  I  .0501389  .0000415  0.7916 0.0299  I    -7.655     .370      .158     .298  -.017000   .377000   .0496000      .000      .000  
+86 8 8 46650.00 I  -.016918  .000306   .377001  .000546  I  .0492042  .0000375  1.0690 0.0376  I    -7.769     .370      .353     .298  -.016000   .378000   .0487000      .000      .000  
+86 8 9 46651.00 I  -.015510  .000422   .377825  .000475  I  .0480271  .0000626  1.2678 0.0339  I    -7.657     .370      .451     .298  -.014000   .379000   .0476000      .000      .000  
+86 810 46652.00 I  -.014168  .000409   .378641  .000444  I  .0467073  .0000564  1.3504 0.0493  I    -7.410     .317      .569     .298  -.013000   .380000   .0464000      .000      .000  
+86 811 46653.00 I  -.012882  .000525   .379462  .000548  I  .0453699  .0000762  1.3023 0.0473  I    -7.225     .252      .745     .298  -.012000   .381000   .0452000      .000      .000  
+86 812 46654.00 I  -.011640  .000455   .380306  .000591  I  .0441420  .0000760  1.1363 0.0523  I    -7.301     .252      .902     .298  -.011000   .382000   .0440000      .000      .000  
+86 813 46655.00 I  -.010403  .000455   .381186  .000591  I  .0431236  .0000717  0.8913 0.0503  I    -7.673     .252      .923     .298  -.009000   .383000   .0430000      .000      .000  
+86 814 46656.00 I  -.009141  .000380   .382083  .000560  I  .0423668  .0000658  0.6239 0.0384  I    -8.099     .252      .758     .298  -.008000   .384000   .0423000      .000      .000  
+86 815 46657.00 I  -.007839  .000200   .382970  .000597  I  .0418592  .0000277  0.4061 0.0369  I    -8.275     .434      .462     .140  -.007000   .385000   .0419000      .000      .000  
+86 816 46658.00 I  -.006482  .000084   .383837  .000578  I  .0415167  .0000336  0.3019 0.0229  I    -8.092     .560      .162     .198  -.005000   .386000   .0415000      .000      .000  
+86 817 46659.00 I  -.005055  .000259   .384681  .000673  I  .0412078  .0000364  0.3404 0.0254  I    -7.676     .604     -.014     .174  -.004000   .387000   .0412000      .000      .000  
+86 818 46660.00 I  -.003544  .000287   .385493  .000660  I  .0407924  .0000381  0.5094 0.0255  I    -7.233     .604     -.032     .174  -.002000   .388000   .0407000      .000      .000  
+86 819 46661.00 I  -.001936  .000312   .386285  .000680  I  .0401629  .0000356  0.7566 0.0238  I    -7.009     .604      .056     .174   .000000   .389000   .0401000      .000      .000  
+86 820 46662.00 I  -.000222  .000346   .387076  .000622  I  .0392789  .0000284  1.0047 0.0258  I    -7.149     .908      .191     .147   .001000   .390000   .0391000      .000      .000  
+86 821 46663.00 I   .001602  .000431   .387884  .000692  I  .0381772  .0000374  1.1819 0.0257  I    -7.574    1.082      .310     .298   .003000   .391000   .0380000      .000      .000  
+86 822 46664.00 I   .003514  .000431   .388702  .000692  I  .0369529  .0000429  1.2458 0.0259  I    -8.197    1.082      .361     .298   .005000   .391000   .0368000      .000      .000  
+86 823 46665.00 I   .005484  .000369   .389514  .000555  I  .0357240  .0000359  1.1945 0.0261  I    -8.983    1.226      .266     .298   .006000   .392000   .0355000      .000      .000  
+86 824 46666.00 I   .007473  .000712   .390301  .000519  I  .0345931  .0000299  1.0557 0.0233  I    -9.754    1.336     -.003     .119   .008000   .393000   .0344000      .000      .000  
+86 825 46667.00 I   .009457  .000800   .391054  .000540  I  .0336291  .0000296  0.8676 0.0241  I   -10.164    1.378     -.383     .108   .010000   .394000   .0334000      .000      .000  
+86 826 46668.00 I   .011415  .001113   .391764  .000520  I  .0328618  .0000378  0.6678 0.0253  I    -9.916    1.515     -.667     .116   .011000   .394000   .0327000      .000      .000  
+86 827 46669.00 I   .013324  .000934   .392421  .000443  I  .0322875  .0000410  0.4859 0.0332  I    -9.015    1.515     -.619     .116   .013000   .395000   .0321000      .000      .000  
+86 828 46670.00 I   .015140  .000934   .393021  .000443  I  .0318770  .0000546  0.3429 0.0344  I    -8.206    1.515     -.369     .116   .015000   .395000   .0317000      .000      .000  
+86 829 46671.00 I   .016870  .000765   .393579  .000647  I  .0315836  .0000553  0.2543 0.0372  I    -7.786    1.515     -.154     .116   .016000   .396000   .0314000      .000      .000  
+86 830 46672.00 I   .018538  .000695   .394122  .000655  I  .0313464  .0000506  0.2318 0.0396  I    -7.673     .903     -.097     .197   .018000   .396000   .0312000      .000      .000  
+86 831 46673.00 I   .020155  .000287   .394677  .000653  I  .0310971  .0000567  0.2782 0.0374  I    -7.751     .284     -.137     .241   .020000   .397000   .0310000      .000      .000  
+86 9 1 46674.00 I   .021728  .000374   .395271  .000610  I  .0307690  .0000550  0.3877 0.0389  I    -7.880     .284     -.104     .241   .021000   .397000   .0306000      .000      .000  
+86 9 2 46675.00 I   .023265  .000385   .395918  .000671  I  .0302994  .0000533  0.5640 0.0325  I    -7.919     .284      .089     .241   .023000   .397000   .0301000      .000      .000  
+86 9 3 46676.00 I   .024777  .000347   .396582  .000553  I  .0296206  .0000348  0.8013 0.0331  I    -7.869     .284      .367     .241   .025000   .398000   .0293000      .000      .000  
+86 9 4 46677.00 I   .026280  .000345   .397211  .000792  I  .0286889  .0000394  1.0622 0.0298  I    -7.808     .777      .565     .253   .026000   .398000   .0283000      .000      .000  
+86 9 5 46678.00 I   .027776  .000373   .397750  .000911  I  .0275048  .0000485  1.2973 0.0375  I    -7.794     .979      .561     .261   .028000   .398000   .0270000      .000      .000  
+86 9 6 46679.00 I   .029242  .000373   .398137  .000911  I  .0261182  .0000639  1.4606 0.0425  I    -7.873     .979      .347     .261   .030000   .398000   .0256000      .000      .000  
+86 9 7 46680.00 I   .030660  .000315   .398317  .000952  I  .0246201  .0000699  1.5143 0.0459  I    -8.114     .979      .048     .261   .031000   .399000   .0240000      .000      .000  
+86 9 8 46681.00 I   .032040  .000365   .398304  .001017  I  .0231308  .0000659  1.4445 0.0471  I    -8.540     .979     -.151     .261   .033000   .399000   .0226000      .000      .000  
+86 9 9 46682.00 I   .033398  .000368   .398165  .000983  I  .0217642  .0000630  1.2754 0.0509  I    -9.071    1.091     -.214     .212   .034000   .399000   .0213000      .000      .000  
+86 910 46683.00 I   .034748  .000417   .397969  .001018  I  .0205972  .0000776  1.0548 0.0487  I    -9.543    1.238     -.197     .109   .036000   .399000   .0202000      .000      .000  
+86 911 46684.00 I   .036109  .000417   .397793  .001018  I  .0196517  .0000743  0.8428 0.0494  I    -9.743    1.238     -.137     .109   .037000   .399000   .0194000      .000      .000  
+86 912 46685.00 I   .037511  .000417   .397718  .001018  I  .0188843  .0000612  0.7126 0.0439  I    -9.535    1.238      .004     .109   .038000   .399000   .0186000      .000      .000  
+86 913 46686.00 I   .038937  .000375   .397755  .000925  I  .0181818  .0000466  0.7166 0.0380  I    -9.018    1.238      .219     .109   .040000   .399000   .0180000      .000      .000  
+86 914 46687.00 I   .040369  .000331   .397869  .000803  I  .0174055  .0000449  0.8574 0.0328  I    -8.459    1.118      .428     .406   .041000   .399000   .0172000      .000      .000  
+86 915 46688.00 I   .041792  .000231   .398011  .000610  I  .0164323  .0000461  1.1024 0.0317  I    -8.112    1.259      .498     .852   .043000   .399000   .0161000      .000      .000  
+86 916 46689.00 I   .043195  .000173   .398133  .000476  I  .0151853  .0000448  1.3936 0.0295  I    -8.084    1.164      .253     .803   .044000   .399000   .0149000      .000      .000  
+86 917 46690.00 I   .044565  .000173   .398189  .000476  I  .0136551  .0000368  1.6549 0.0286  I    -8.296    1.164     -.352     .803   .045000   .399000   .0133000      .000      .000  
+86 918 46691.00 I   .045892  .000157   .398157  .000500  I  .0119068  .0000357  1.8222 0.0248  I    -8.272    1.164     -.317     .803   .046000   .399000   .0115000      .000      .000  
+86 919 46692.00 I   .047175  .000265   .398031  .000431  I  .0100508  .0000333  1.8690 0.0259  I    -8.133    1.044      .085     .646   .048000   .399000   .0097000      .000      .000  
+86 920 46693.00 I   .048412  .000309   .397812  .000473  I  .0082069  .0000375  1.8013 0.0242  I    -8.186    1.075      .299     .686   .049000   .399000   .0079000      .000      .000  
+86 921 46694.00 I   .049596  .000309   .397519  .000473  I  .0064771  .0000350  1.6467 0.0279  I    -8.448     .772      .356     .329   .050000   .399000   .0062000      .000      .000  
+86 922 46695.00 I   .050721  .000351   .397166  .000368  I  .0049286  .0000414  1.4467 0.0246  I    -8.762     .757      .350     .298   .051000   .399000   .0047000      .000      .000  
+86 923 46696.00 I   .051787  .000311   .396760  .000442  I  .0035841  .0000347  1.2455 0.0253  I    -8.891     .757      .407     .298   .052000   .398000   .0034000      .000      .000  
+86 924 46697.00 I   .052821  .000288   .396311  .000430  I  .0024267  .0000291  1.0769 0.0234  I    -8.700     .642      .600     .334   .054000   .398000   .0022000      .000      .000  
+86 925 46698.00 I   .053854  .000196   .395831  .000490  I  .0014112  .0000313  0.9656 0.0285  I    -8.267     .502      .852     .471   .055000   .398000   .0012000      .000      .000  
+86 926 46699.00 I   .054917  .000236   .395336  .000437  I  .0004703  .0000491  0.9301 0.0284  I    -7.799     .502      .972     .471   .056000   .398000   .0003000      .000      .000  
+86 927 46700.00 I   .056028  .000236   .394854  .000437  I -.0004763  .0000475  0.9767 0.0309  I    -7.441     .502      .860     .471   .057000   .397000  -.0007000      .000      .000  
+86 928 46701.00 I   .057188  .000210   .394417  .000640  I -.0015092  .0000375  1.1017 0.0302  I    -7.190     .502      .634     .471   .058000   .397000  -.0017000      .000      .000  
+86 929 46702.00 I   .058390  .000277   .394051  .000640  I -.0027028  .0000373  1.2960 0.0337  I    -7.034     .717      .492     .335   .060000   .396000  -.0029000      .000      .000  
+86 930 46703.00 I   .059614  .000306   .393782  .000758  I -.0041178  .0000561  1.5402 0.0339  I    -7.031     .882      .521     .298   .061000   .396000  -.0043000      .000      .000  
+8610 1 46704.00 I   .060833  .000288   .393642  .000729  I -.0057892  .0000565  1.8024 0.0337  I    -7.188     .882      .674     .298   .062000   .395000  -.0060000      .000      .000  
+8610 2 46705.00 I   .062023  .000279   .393644  .000804  I -.0077152  .0000373  2.0423 0.0355  I    -7.361     .882      .871     .298   .063000   .395000  -.0080000      .000      .000  
+8610 3 46706.00 I   .063183  .000252   .393743  .000711  I -.0098497  .0000429  2.2100 0.0289  I    -7.407     .882     1.035     .298   .064000   .395000  -.0101000      .000      .000  
+8610 4 46707.00 I   .064319  .000229   .393870  .000765  I -.0120944  .0000442  2.2555 0.0329  I    -7.329     .637     1.095     .270   .066000   .394000  -.0124000      .000      .000  
+8610 5 46708.00 I   .065439  .000122   .393967  .000637  I -.0143128  .0000500  2.1574 0.0336  I    -7.253     .185     1.017     .377   .067000   .394000  -.0146000      .000      .000  
+8610 6 46709.00 I   .066561  .000122   .393983  .000637  I -.0163691  .0000506  1.9391 0.0372  I    -7.298     .185      .842     .377   .068000   .393000  -.0167000      .000      .000  
+8610 7 46710.00 I   .067700  .000188   .393877  .000662  I -.0181709  .0000551  1.6606 0.0352  I    -7.481     .185      .649     .377   .069000   .393000  -.0184000      .000      .000  
+8610 8 46711.00 I   .068857  .000272   .393644  .000590  I -.0196953  .0000489  1.3971 0.0348  I    -7.687     .185      .498     .377   .071000   .392000  -.0200000      .000      .000  
+8610 9 46712.00 I   .070031  .000283   .393309  .000507  I -.0209933  .0000425  1.2184 0.0332  I    -7.781     .204      .383     .276   .072000   .392000  -.0212000      .000      .000  
+861010 46713.00 I   .071220  .000339   .392901  .000377  I -.0221744  .0000450  1.1668 0.0307  I    -7.663     .222      .286     .298   .073000   .392000  -.0224000      .000      .000  
+861011 46714.00 I   .072432  .000401   .392455  .000361  I -.0233677  .0000443  1.2377 0.0301  I    -7.283     .222      .249     .298   .074000   .391000  -.0237000      .000      .000  
+861012 46715.00 I   .073692  .000401   .392017  .000361  I -.0246816  .0000400  1.4038 0.0271  I    -6.668     .222      .339     .298   .076000   .391000  -.0251000      .000      .000  
+861013 46716.00 I   .075028  .000596   .391609  .000323  I -.0261924  .0000311  1.6210 0.0248  I    -5.993     .222      .547     .298   .077000   .391000  -.0267000      .000      .000  
+861014 46717.00 I   .076466  .000597   .391242  .000254  I -.0279202  .0000292  1.8281 0.0200  I    -5.429     .357      .813     .152   .078000   .391000  -.0285000      .000      .000  
+861015 46718.00 I   .078018  .000669   .390927  .000259  I -.0298285  .0000250  1.9749 0.0200  I    -5.071     .391     1.070     .185   .079000   .390000  -.0305000      .000      .000  
+861016 46719.00 I   .079677  .000669   .390666  .000259  I -.0318410  .0000274  2.0347 0.0187  I    -4.953     .391     1.232     .185   .081000   .390000  -.0326000      .000      .000  
+861017 46720.00 I   .081418  .000662   .390457  .000266  I -.0338647  .0000278  1.9948 0.0211  I    -5.071     .391     1.201     .185   .082000   .390000  -.0347000      .000      .000  
+861018 46721.00 I   .083132  .000760   .390277  .000255  I -.0358018  .0000322  1.8684 0.0206  I    -5.309     .391     1.085     .185   .083000   .389000  -.0367000      .000      .000  
+861019 46722.00 I   .084741  .000716   .390107  .000230  I -.0375854  .0000305  1.6936 0.0226  I    -5.595     .346      .969     .244   .085000   .389000  -.0384000      .000      .000  
+861020 46723.00 I   .086193  .000638   .389931  .000134  I -.0391847  .0000318  1.5058 0.0245  I    -5.920     .249      .829     .276   .086000   .389000  -.0400000      .000      .000  
+861021 46724.00 I   .087450  .000578   .389740  .000126  I -.0406038  .0000384  1.3383 0.0239  I    -6.152     .266      .737     .309   .087000   .388000  -.0413000      .000      .000  
+861022 46725.00 I   .088503  .000654   .389529  .000199  I -.0418764  .0000357  1.2160 0.0281  I    -6.104     .219      .742     .263   .088000   .388000  -.0425000      .000      .000  
+861023 46726.00 I   .089430  .000649   .389295  .000195  I -.0430563  .0000410  1.1551 0.0282  I    -5.762     .219      .811     .263   .090000   .388000  -.0435000      .000      .000  
+861024 46727.00 I   .090340  .000620   .389034  .000205  I -.0442099  .0000437  1.1642 0.0320  I    -5.297     .496      .850     .271   .091000   .387000  -.0445000      .000      .000  
+861025 46728.00 I   .091325  .000501   .388742  .000245  I -.0454034  .0000491  1.2293 0.0326  I    -4.856     .605      .860     .240   .092000   .387000  -.0455000      .000      .000  
+861026 46729.00 I   .092387  .000539   .388414  .000259  I -.0466797  .0000483  1.3279 0.0347  I    -4.473     .605      .920     .240   .094000   .387000  -.0467000      .000      .000  
+861027 46730.00 I   .093479  .000539   .388037  .000259  I -.0480733  .0000490  1.4687 0.0357  I    -4.226     .605     1.082     .240   .095000   .387000  -.0480000      .000      .000  
+861028 46731.00 I   .094579  .000535   .387595  .000350  I -.0496329  .0000527  1.6567 0.0335  I    -4.287     .735     1.307     .281   .096000   .386000  -.0495000      .000      .000  
+861029 46732.00 I   .095684  .000443   .387071  .000302  I -.0513921  .0000457  1.8608 0.0300  I    -4.725     .548     1.480     .397   .097000   .386000  -.0512000      .000      .000  
+861030 46733.00 I   .096822  .000479   .386457  .000309  I -.0533440  .0000285  2.0333 0.0270  I    -5.310     .213     1.572     .432   .099000   .385000  -.0532000      .000      .000  
+861031 46734.00 I   .098035  .000479   .385746  .000309  I -.0554304  .0000286  2.1210 0.0202  I    -5.665     .213     1.661     .432   .100000   .385000  -.0553000      .000      .000  
+8611 1 46735.00 I   .099348  .001097   .384936  .000490  I -.0575419  .0000286  2.0766 0.0185  I    -5.603     .213     1.789     .432   .101000   .385000  -.0574000      .000      .000  
+8611 2 46736.00 I   .100727  .000967   .384042  .000541  I -.0595353  .0000236  1.8875 0.0155  I    -5.247     .359     2.027     .435   .103000   .384000  -.0594000      .000      .000  
+8611 3 46737.00 I   .102130  .000565   .383079  .000564  I -.0612828  .0000120  1.5961 0.0126  I    -4.795     .608     2.200     .380   .104000   .383000  -.0612000      .000      .000  
+8611 4 46738.00 I   .103520  .000555   .382064  .000553  I -.0627206  .0000090  1.2839 0.0096  I    -4.383     .763     2.101     .279   .105000   .383000  -.0627000      .000      .000  
+8611 5 46739.00 I   .104920  .000610   .381025  .000589  I -.0638732  .0000149  1.0395 0.0109  I    -4.163     .849     1.671     .282   .106000   .382000  -.0638000      .000      .000  
+8611 6 46740.00 I   .106443  .000619   .380021  .000580  I -.0648435  .0000199  0.9268 0.0126  I    -4.070     .872     1.343     .268   .108000   .382000  -.0648000      .000      .000  
+8611 7 46741.00 I   .108160  .000313   .379146  .000550  I -.0657776  .0000204  0.9663 0.0155  I    -3.884     .872     1.189     .268   .109000   .381000  -.0659000      .000      .000  
+8611 8 46742.00 I   .110029  .000313   .378363  .000550  I -.0668165  .0000238  1.1268 0.0173  I    -3.586     .852     1.186     .466   .111000   .380000  -.0670000      .000      .000  
+8611 9 46743.00 I   .111974  .000337   .377602  .000501  I -.0680527  .0000279  1.3517 0.0481  I    -3.452     .817     1.514     .550   .113000   .379000  -.0683000      .000      .000  
+861110 46744.00 I   .113883  .000607   .376827  .000529  I -.0695212  .0000932  1.5804 0.0496  I    -3.482     .788     2.068     .624   .114000   .378000  -.0698000      .000      .000  
+861111 46745.00 I   .115670  .000607   .376009  .000529  I -.0711957  .0000951  1.7557 0.0639  I    -3.573     .788     2.524     .624   .116000   .377000  -.0716000      .000      .000  
+861112 46746.00 I   .117284  .000555   .375126  .000341  I -.0730039  .0000875  1.8448 0.0549  I    -3.730     .693     2.747     .732   .117000   .376000  -.0734000      .000      .000  
+861113 46747.00 I   .118681  .000491   .374161  .000311  I -.0748528  .0000550  1.8364 0.0513  I    -3.938     .538     2.787     .546   .118000   .374000  -.0753000      .000      .000  
+861114 46748.00 I   .119822  .000521   .373111  .000301  I -.0766462  .0000534  1.7364 0.0370  I    -4.109     .313     2.724     .244   .119000   .373000  -.0770000      .000      .000  
+861115 46749.00 I   .120675  .000521   .371975  .000301  I -.0783024  .0000494  1.5668 0.0300  I    -4.187     .313     2.591     .244   .120000   .372000  -.0786000      .000      .000  
+861116 46750.00 I   .121222  .000703   .370755  .000419  I -.0797678  .0000274  1.3612 0.0276  I    -4.231     .313     2.376     .244   .121000   .371000  -.0800000      .000      .000  
+861117 46751.00 I   .121525  .000689   .369473  .000388  I -.0810249  .0000247  1.1559 0.0175  I    -4.336     .313     2.087     .244   .121000   .370000  -.0813000      .000      .000  
+861118 46752.00 I   .121669  .000649   .368161  .000345  I -.0820903  .0000217  0.9828 0.0197  I    -4.500     .322     1.850     .290   .122000   .368000  -.0823000      .000      .000  
+861119 46753.00 I   .121731  .000672   .366845  .000439  I -.0830098  .0000308  0.8676 0.0182  I    -4.578     .332     1.810     .330   .122000   .367000  -.0832000      .000      .000  
+861120 46754.00 I   .121735  .000672   .365532  .000439  I -.0838496  .0000293  0.8247 0.0214  I    -4.401     .332     1.935     .330   .123000   .366000  -.0840000      .000      .000  
+861121 46755.00 I   .121695  .000672   .364223  .000439  I -.0846851  .0000296  0.8595 0.0180  I    -3.925     .332     2.033     .330   .123000   .365000  -.0848000      .000      .000  
+861122 46756.00 I   .121645  .000393   .362924  .000177  I -.0855930  .0000208  0.9675 0.0184  I    -3.228     .332     2.015     .330   .123000   .364000  -.0857000      .000      .000  
+861123 46757.00 I   .121615  .000459   .361638  .000166  I -.0866396  .0000218  1.1340 0.0193  I    -2.399     .259     2.005     .609   .124000   .362000  -.0868000      .000      .000  
+861124 46758.00 I   .121636  .000352   .360361  .000190  I -.0878742  .0000326  1.3400 0.0211  I    -1.596     .157     2.141     .796   .124000   .361000  -.0881000      .000      .000  
+861125 46759.00 I   .121737  .000397   .359088  .000060  I -.0893248  .0000362  1.5616 0.0245  I    -1.127     .157     2.365     .796   .124000   .360000  -.0895000      .000      .000  
+861126 46760.00 I   .121951  .000397   .357817  .000060  I -.0909912  .0000367  1.7645 0.0276  I    -1.218     .157     2.495     .796   .125000   .359000  -.0912000      .000      .000  
+861127 46761.00 I   .122300  .000318   .356546  .000126  I -.0928325  .0000418  1.9033 0.0244  I    -1.718     .157     2.511     .796   .125000   .358000  -.0931000      .000      .000  
+861128 46762.00 I   .122802  .000360   .355271  .000152  I -.0947608  .0000322  1.9311 0.0274  I    -2.288     .288     2.584     .576   .126000   .356000  -.0950000      .000      .000  
+861129 46763.00 I   .123482  .000291   .353996  .000173  I -.0966481  .0000354  1.8193 0.0234  I    -2.768     .376     2.799     .175   .126000   .355000  -.0969000      .000      .000  
+861130 46764.00 I   .124368  .000304   .352720  .000180  I -.0983574  .0000339  1.5817 0.0248  I    -3.167     .376     2.989     .175   .127000   .354000  -.0986000      .000      .000  
+8612 1 46765.00 I   .125479  .000281   .351444  .000335  I -.0997919  .0000348  1.2853 0.0228  I    -3.401     .376     2.977     .175   .127000   .352000  -.1001000      .000      .000  
+8612 2 46766.00 I   .126780  .000314   .350165  .000330  I -.1009402  .0000305  1.0254 0.0237  I    -3.328     .376     2.828     .175   .128000   .351000  -.1012000      .000      .000  
+8612 3 46767.00 I   .128205  .000423   .348882  .000436  I -.1018824  .0000321  0.8847 0.0265  I    -3.030     .571     2.765     .449   .129000   .350000  -.1022000      .000      .000  
+8612 4 46768.00 I   .129688  .000523   .347592  .000582  I -.1027627  .0000434  0.9033 0.0278  I    -2.817     .699     2.813     .542   .130000   .348000  -.1031000      .000      .000  
+8612 5 46769.00 I   .131165  .000523   .346274  .000582  I -.1037358  .0000454  1.0621 0.0314  I    -2.876     .699     2.716     .542   .131000   .347000  -.1041000      .000      .000  
+8612 6 46770.00 I   .132580  .000523   .344903  .000582  I -.1049099  .0000454  1.2898 0.0299  I    -3.056     .699     2.302     .542   .132000   .346000  -.1052000      .000      .000  
+8612 7 46771.00 I   .133924  .000504   .343466  .000466  I -.1063124  .0000390  1.5087 0.0288  I    -2.962     .648     2.037     .476   .133000   .344000  -.1066000      .000      .000  
+8612 8 46772.00 I   .135176  .000458   .341972  .000433  I -.1079059  .0000355  1.6636 0.0296  I    -2.605     .670     2.200     .392   .134000   .343000  -.1082000      .000      .000  
+8612 9 46773.00 I   .136306  .000468   .340435  .000420  I -.1096072  .0000445  1.7215 0.0239  I    -2.239     .645     2.655     .184   .135000   .341000  -.1099000      .000      .000  
+861210 46774.00 I   .137286  .000222   .338871  .000225  I -.1113158  .0000321  1.6803 0.0264  I    -2.014     .639     3.083     .118   .136000   .340000  -.1115000      .000      .000  
+861211 46775.00 I   .138103  .000222   .337292  .000225  I -.1129402  .0000285  1.5563 0.0467  I    -2.097     .639     3.282     .118   .137000   .339000  -.1131000      .000      .000  
+861212 46776.00 I   .138777  .000231   .335713  .000235  I -.1144085  .0000877  1.3724 0.0394  I    -2.396     .639     3.306     .118   .138000   .337000  -.1146000      .000      .000  
+861213 46777.00 I   .139334  .000265   .334158  .000202  I -.1156739  .0000735  1.1551 0.0639  I    -2.713     .553     3.256     .145   .138000   .336000  -.1158000      .000      .000  
+861214 46778.00 I   .139803  .000280   .332651  .000167  I -.1167165  .0000930  0.9313 0.0598  I    -2.944     .332     3.107     .150   .139000   .335000  -.1168000      .000      .000  
+861215 46779.00 I   .140216  .000305   .331220  .000166  I -.1175448  .0000943  0.7324 0.0674  I    -3.081     .332     2.826     .150   .140000   .334000  -.1177000      .000      .000  
+861216 46780.00 I   .140605  .000279   .329888  .000468  I -.1182030  .0000976  0.5987 0.0631  I    -3.127     .332     2.533     .150   .140000   .332000  -.1184000      .000      .000  
+861217 46781.00 I   .140997  .000241   .328664  .000424  I -.1187732  .0000840  0.5579 0.0575  I    -3.062     .332     2.424     .150   .141000   .331000  -.1191000      .000      .000  
+861218 46782.00 I   .141411  .000302   .327549  .000347  I -.1193512  .0000607  0.6144 0.0562  I    -2.802     .279     2.556     .183   .141000   .330000  -.1197000      .000      .000  
+861219 46783.00 I   .141868  .000301   .326542  .000441  I -.1200310  .0000748  0.7581 0.0480  I    -2.301     .214     2.787     .211   .142000   .329000  -.1204000      .000      .000  
+861220 46784.00 I   .142385  .000301   .325615  .000441  I -.1208896  .0000743  0.9686 0.0479  I    -1.635     .214     2.969     .211   .142000   .328000  -.1213000      .000      .000  
+861221 46785.00 I   .142978  .000369   .324735  .000440  I -.1219795  .0000597  1.2131 0.0466  I     -.951     .555     3.119     .163   .142000   .327000  -.1223000      .000      .000  
+861222 46786.00 I   .143609  .000387   .323868  .000309  I -.1233149  .0000561  1.4551 0.0410  I     -.381     .555     3.318     .163   .143000   .326000  -.1236000      .000      .000  
+861223 46787.00 I   .144204  .000387   .322977  .000309  I -.1248792  .0000562  1.6657 0.0319  I     -.066     .555     3.501     .163   .143000   .325000  -.1251000      .000      .000  
+861224 46788.00 I   .144684  .000450   .322025  .000439  I -.1266263  .0000303  1.8163 0.0409  I     -.063     .756     3.487     .298   .144000   .325000  -.1267000      .000      .000  
+861225 46789.00 I   .145013  .000450   .321001  .000439  I -.1284839  .0000594  1.8831 0.0348  I     -.257     .756     3.258     .298   .144000   .323000  -.1285000      .000      .000  
+861226 46790.00 I   .145222  .000450   .319917  .000439  I -.1303569  .0000626  1.8432 0.0490  I     -.498     .756     3.023     .298   .144000   .322000  -.1303000      .000      .000  
+861227 46791.00 I   .145351  .000366   .318788  .000232  I -.1321329  .0000779  1.6913 0.0444  I     -.810     .791     2.936     .298   .145000   .321000  -.1321000      .000      .000  
+861228 46792.00 I   .145443  .000417   .317630  .000216  I -.1337127  .0000629  1.4592 0.0499  I    -1.293     .350     2.867     .298   .145000   .320000  -.1336000      .000      .000  
+861229 46793.00 I   .145537  .000417   .316458  .000216  I -.1350465  .0000623  1.2127 0.0441  I    -1.816     .350     2.612     .298   .145000   .319000  -.1349000      .000      .000  
+861230 46794.00 I   .145675  .000417   .315287  .000216  I -.1361608  .0000617  1.0342 0.0343  I    -2.078     .350     2.249     .298   .145000   .317000  -.1360000      .000      .000  
+861231 46795.00 I   .145891  .000417   .314129  .000216  I -.1371607  .0000287  0.9931 0.0321  I    -2.023     .350     2.113     .298   .146000   .316000  -.1369000      .000      .000  
+87 1 1 46796.00 I   .146164  .000350   .312978  .000374  I -.1381993  .0000175  1.1088 0.0192  I    -1.921     .350     2.344     .298   .146000   .315000  -.1379000      .000      .000  
+87 1 2 46797.00 I   .146446  .000350   .311819  .000374  I -.1394157  .0000256  1.3366 0.0210  I    -2.019     .455     2.725     .276   .146000   .314000  -.1391000      .000      .000  
+87 1 3 46798.00 I   .146692  .000160   .310639  .000557  I -.1408817  .0000381  1.5921 0.0246  I    -2.244     .541     2.996     .387   .146000   .312000  -.1406000      .000      .000  
+87 1 4 46799.00 I   .146854  .000160   .309420  .000557  I -.1425808  .0000419  1.7903 0.0303  I    -2.388     .541     3.176     .387   .146000   .311000  -.1423000      .000      .000  
+87 1 5 46800.00 I   .146890  .000443   .308156  .000455  I -.1444251  .0000471  1.8770 0.0277  I    -2.406     .541     3.440     .387   .146000   .309000  -.1441000      .000      .000  
+87 1 6 46801.00 I   .146762  .000393   .306858  .000406  I -.1462932  .0000361  1.8389 0.0280  I    -2.419     .541     3.783     .387   .146000   .308000  -.1460000      .000      .000  
+87 1 7 46802.00 I   .146447  .000343   .305532  .000346  I -.1480683  .0000303  1.6969 0.0224  I    -2.418     .437     3.968     .280   .145000   .307000  -.1478000      .000      .000  
+87 1 8 46803.00 I   .145930  .000362   .304171  .000242  I -.1496648  .0000265  1.4881 0.0218  I    -2.267     .299     3.844     .298   .145000   .305000  -.1493000      .000      .000  
+87 1 9 46804.00 I   .145216  .000388   .302764  .000135  I -.1510340  .0000314  1.2476 0.0196  I    -1.948     .299     3.542     .298   .145000   .304000  -.1507000      .000      .000  
+87 110 46805.00 I   .144363  .000388   .301309  .000135  I -.1521611  .0000290  1.0103 0.0197  I    -1.598     .299     3.273     .298   .144000   .303000  -.1518000      .000      .000  
+87 111 46806.00 I   .143461  .000389   .299808  .000229  I -.1530660  .0000238  0.8072 0.0200  I    -1.314     .299     3.066     .298   .144000   .302000  -.1528000      .000      .000  
+87 112 46807.00 I   .142592  .000621   .298270  .000481  I -.1537942  .0000276  0.6603 0.0234  I    -1.168     .680     2.818     .298   .143000   .300000  -.1535000      .000      .000  
+87 113 46808.00 I   .141826  .000772   .296709  .000587  I -.1544114  .0000402  0.5879 0.0247  I    -1.258     .864     2.538     .298   .143000   .299000  -.1542000      .000      .000  
+87 114 46809.00 I   .141231  .000762   .295141  .000645  I -.1549984  .0000410  0.6008 0.0276  I    -1.612     .864     2.391     .298   .142000   .297000  -.1548000      .000      .000  
+87 115 46810.00 I   .140855  .000762   .293585  .000645  I -.1556391  .0000378  0.6919 0.0271  I    -2.059     .864     2.498     .298   .141000   .296000  -.1555000      .000      .000  
+87 116 46811.00 I   .140624  .000821   .292056  .000630  I -.1564038  .0000354  0.8478 0.0269  I    -2.160     .864     2.779     .298   .141000   .295000  -.1563000      .000      .000  
+87 117 46812.00 I   .140450  .000806   .290534  .000630  I -.1573502  .0000384  1.0503 0.0273  I    -1.797     .868     3.034     .141   .140000   .293000  -.1573000      .000      .000  
+87 118 46813.00 I   .140262  .000719   .289004  .000583  I -.1585097  .0000415  1.2687 0.0285  I    -1.227     .727     3.150     .247   .140000   .292000  -.1585000      .000      .000  
+87 119 46814.00 I   .139989  .000795   .287471  .000449  I -.1598827  .0000422  1.4722 0.0303  I     -.725     .647     3.136     .257   .139000   .290000  -.1598000      .000      .000  
+87 120 46815.00 I   .139575  .000887   .285944  .000507  I -.1614379  .0000441  1.6269 0.0285  I     -.460     .647     2.994     .257   .138000   .289000  -.1614000      .000      .000  
+87 121 46816.00 I   .139026  .000779   .284463  .000483  I -.1631089  .0000383  1.6987 0.0282  I     -.434     .647     2.959     .257   .138000   .288000  -.1631000      .000      .000  
+87 122 46817.00 I   .138418  .000724   .283070  .000512  I -.1648016  .0000352  1.6695 0.0252  I     -.627     .590     3.006     .211   .137000   .286000  -.1647000      .000      .000  
+87 123 46818.00 I   .137857  .000663   .281786  .000493  I -.1664139  .0000329  1.5384 0.0251  I     -.939     .369     3.089     .210   .137000   .285000  -.1664000      .000      .000  
+87 124 46819.00 I   .137431  .000761   .280616  .000974  I -.1678506  .0000358  1.3241 0.0229  I    -1.338     .421     3.264     .102   .136000   .284000  -.1678000      .000      .000  
+87 125 46820.00 I   .137166  .000807   .279539  .001125  I -.1690519  .0000319  1.0794 0.0227  I    -1.833     .458     3.406     .298   .136000   .282000  -.1690000      .000      .000  
+87 126 46821.00 I   .137038  .000710   .278561  .001084  I -.1700244  .0000278  0.8799 0.0206  I    -2.308     .458     3.324     .298   .135000   .281000  -.1700000      .000      .000  
+87 127 46822.00 I   .137011  .000732   .277704  .000597  I -.1708510  .0000262  0.7984 0.0210  I    -2.492     .422     3.018     .117   .135000   .280000  -.1708000      .000      .000  
+87 128 46823.00 I   .137001  .000813   .276949  .000608  I -.1716741  .0000315  0.8757 0.0204  I    -2.264     .329     2.722     .157   .135000   .279000  -.1717000      .000      .000  
+87 129 46824.00 I   .136835  .000769   .276208  .000599  I -.1726509  .0000313  1.0986 0.0209  I    -1.856     .329     2.595     .157   .134000   .277000  -.1727000      .000      .000  
+87 130 46825.00 I   .136335  .000648   .275387  .000272  I -.1738984  .0000274  1.4029 0.0207  I    -1.619     .329     2.529     .157   .134000   .276000  -.1740000      .000      .000  
+87 131 46826.00 I   .135381  .000663   .274410  .000333  I -.1754526  .0000270  1.6949 0.0198  I    -1.688     .329     2.507     .157   .133000   .275000  -.1756000      .000      .000  
+87 2 1 46827.00 I   .134106  .000779   .273266  .000425  I -.1772565  .0000285  1.8918 0.0196  I    -2.003     .647     2.552     .132   .133000   .274000  -.1774000      .000      .000  
+87 2 2 46828.00 I   .132707  .000783   .271968  .000325  I -.1791915  .0000284  1.9545 0.0207  I    -2.522     .869     2.706     .106   .132000   .273000  -.1793000      .000      .000  
+87 2 3 46829.00 I   .131373  .000713   .270544  .000400  I -.1811235  .0000301  1.8911 0.0205  I    -3.146    1.121     2.899     .116   .132000   .271000  -.1812000      .000      .000  
+87 2 4 46830.00 I   .130288  .000755   .269034  .000391  I -.1829432  .0000297  1.7363 0.0205  I    -3.543    1.121     2.877     .116   .132000   .270000  -.1830000      .000      .000  
+87 2 5 46831.00 I   .129572  .000756   .267504  .000383  I -.1845796  .0000279  1.5320 0.0379  I    -3.415    1.121     2.624     .116   .131000   .269000  -.1846000      .000      .000  
+87 2 6 46832.00 I   .129204  .000678   .266010  .000329  I -.1860049  .0000697  1.3209 0.0405  I    -3.125    1.099     2.476     .192   .131000   .268000  -.1860000      .000      .000  
+87 2 7 46833.00 I   .129075  .000661   .264586  .000256  I -.1872302  .0000761  1.1362 0.0547  I    -2.914    1.077     2.582     .240   .130000   .267000  -.1872000      .000      .000  
+87 2 8 46834.00 I   .129034  .000464   .263271  .000194  I -.1882929  .0000843  0.9981 0.0633  I    -2.667    1.068     2.719     .266   .130000   .266000  -.1882000      .000      .000  
+87 2 9 46835.00 I   .128903  .000572   .262120  .000247  I -.1892463  .0001011  0.9195 0.0609  I    -2.261     .916     2.539     .282   .129000   .265000  -.1891000      .000      .000  
+87 210 46836.00 I   .128587  .000512   .261167  .000283  I -.1901571  .0000879  0.9163 0.0647  I    -1.922     .916     2.259     .282   .129000   .264000  -.1900000      .000      .000  
+87 211 46837.00 I   .128150  .000504   .260373  .000272  I -.1911065  .0000807  0.9959 0.0548  I    -1.844     .839     2.163     .325   .128000   .263000  -.1909000      .000      .000  
+87 212 46838.00 I   .127667  .000465   .259684  .000266  I -.1921723  .0000655  1.1458 0.0526  I    -1.933     .593     2.319     .310   .128000   .262000  -.1920000      .000      .000  
+87 213 46839.00 I   .127184  .000435   .259047  .000316  I -.1934137  .0000675  1.3426 0.0480  I    -1.942     .616     2.635     .319   .128000   .262000  -.1933000      .000      .000  
+87 214 46840.00 I   .126747  .000356   .258408  .000315  I -.1948653  .0000703  1.5630 0.0409  I    -1.689     .616     2.886     .319   .127000   .261000  -.1948000      .000      .000  
+87 215 46841.00 I   .126370  .000531   .257736  .000338  I -.1965376  .0000461  1.7772 0.0404  I    -1.180     .616     2.971     .319   .127000   .260000  -.1965000      .000      .000  
+87 216 46842.00 I   .126024  .000444   .257013  .000290  I -.1984046  .0000398  1.9460 0.0328  I     -.623     .619     2.910     .245   .127000   .259000  -.1984000      .000      .000  
+87 217 46843.00 I   .125673  .000443   .256225  .000260  I -.2004034  .0000466  2.0363 0.0252  I     -.217     .513     2.767     .108   .126000   .258000  -.2004000      .000      .000  
+87 218 46844.00 I   .125290  .000447   .255354  .000286  I -.2024439  .0000309  2.0269 0.0281  I     -.066     .548     2.590     .119   .126000   .257000  -.2025000      .000      .000  
+87 219 46845.00 I   .124857  .000442   .254391  .000291  I -.2044244  .0000313  1.9191 0.0191  I     -.227     .548     2.391     .119   .125000   .256000  -.2045000      .000      .000  
+87 220 46846.00 I   .124399  .000436   .253371  .000304  I -.2062584  .0000223  1.7400 0.0181  I     -.559     .548     2.235     .119   .125000   .255000  -.2064000      .000      .000  
+87 221 46847.00 I   .123945  .000358   .252313  .000329  I -.2078958  .0000180  1.5349 0.0141  I     -.942     .507     2.147     .245   .124000   .254000  -.2081000      .000      .000  
+87 222 46848.00 I   .123508  .000276   .251228  .000304  I -.2093397  .0000173  1.3644 0.0122  I    -1.330     .478     2.078     .320   .124000   .253000  -.2096000      .000      .000  
+87 223 46849.00 I   .123087  .000318   .250117  .000382  I -.2106572  .0000166  1.2919 0.0118  I    -1.615     .570     1.967     .331   .123000   .252000  -.2109000      .000      .000  
+87 224 46850.00 I   .122661  .000318   .248976  .000382  I -.2119707  .0000160  1.3611 0.0114  I    -1.620     .570     1.819     .331   .123000   .251000  -.2122000      .000      .000  
+87 225 46851.00 I   .122246  .000355   .247844  .000390  I -.2134289  .0000157  1.5788 0.0118  I    -1.372     .570     1.562     .331   .122000   .250000  -.2137000      .000      .000  
+87 226 46852.00 I   .121872  .000386   .246727  .000395  I -.2151634  .0000173  1.9017 0.0129  I     -.824     .500     1.458     .267   .122000   .249000  -.2153000      .000      .000  
+87 227 46853.00 I   .121495  .000396   .245613  .000288  I -.2172400  .0000205  2.2476 0.0148  I     -.069     .537     1.607     .177   .121000   .247000  -.2173000      .000      .000  
+87 228 46854.00 I   .121053  .000572   .244482  .000489  I -.2196369  .0000239  2.5284 0.0169  I      .667     .455     1.802     .298   .121000   .246000  -.2196000      .000      .000  
+87 3 1 46855.00 I   .120474  .000502   .243307  .000416  I -.2222510  .0000269  2.6719 0.0172  I     1.163     .324     1.907     .298   .120000   .245000  -.2220000      .000      .000  
+87 3 2 46856.00 I   .119739  .000494   .242064  .000392  I -.2249249  .0000248  2.6481 0.0196  I     1.253     .324     1.940     .298   .119000   .243000  -.2245000      .000      .000  
+87 3 3 46857.00 I   .118859  .000602   .240737  .000344  I -.2274987  .0000285  2.4790 0.0228  I      .895     .362     1.931     .133   .118000   .242000  -.2268000      .000      .000  
+87 3 4 46858.00 I   .117846  .000632   .239311  .000335  I -.2298512  .0000383  2.2148 0.0280  I      .264     .396     1.831     .188   .118000   .240000  -.2290000      .000      .000  
+87 3 5 46859.00 I   .116699  .000632   .237782  .000335  I -.2319140  .0000481  1.9076 0.0318  I     -.342     .396     1.610     .188   .117000   .239000  -.2309000      .000      .000  
+87 3 6 46860.00 I   .115417  .000632   .236156  .000335  I -.2336699  .0000507  1.6109 0.0315  I     -.742     .396     1.381     .188   .116000   .237000  -.2326000      .000      .000  
+87 3 7 46861.00 I   .114084  .000539   .234471  .000347  I -.2351542  .0000408  1.3693 0.0308  I     -.914     .396     1.287     .188   .115000   .236000  -.2341000      .000      .000  
+87 3 8 46862.00 I   .112799  .000648   .232769  .000373  I -.2364341  .0000349  1.2044 0.0275  I     -.872     .547     1.312     .143   .115000   .235000  -.2355000      .000      .000  
+87 3 9 46863.00 I   .111657  .000608   .231094  .000414  I -.2375923  .0000368  1.1275 0.0253  I     -.623     .548     1.288     .298   .114000   .234000  -.2368000      .000      .000  
+87 310 46864.00 I   .110751  .000608   .229489  .000414  I -.2387201  .0000365  1.1437 0.0237  I     -.259     .548     1.122     .298   .113000   .233000  -.2382000      .000      .000  
+87 311 46865.00 I   .110161  .000608   .227994  .000414  I -.2399098  .0000298  1.2503 0.0210  I      .046     .548      .910     .298   .113000   .231000  -.2395000      .000      .000  
+87 312 46866.00 I   .109870  .000516   .226654  .000366  I -.2412443  .0000209  1.4278 0.0171  I      .167     .548      .815     .298   .112000   .230000  -.2411000      .000      .000  
+87 313 46867.00 I   .109779  .000476   .225503  .000307  I -.2427787  .0000167  1.6454 0.0146  I      .146     .437      .884     .298   .111000   .229000  -.2428000      .000      .000  
+87 314 46868.00 I   .109810  .000494   .224548  .000323  I -.2445374  .0000205  1.8700 0.0122  I      .100     .147     1.018     .298   .111000   .228000  -.2447000      .000      .000  
+87 315 46869.00 I   .109899  .000220   .223794  .000247  I -.2465079  .0000178  2.0621 0.0132  I      .054     .175     1.078     .298   .110000   .227000  -.2468000      .000      .000  
+87 316 46870.00 I   .109988  .000220   .223232  .000247  I -.2486381  .0000165  2.1838 0.0146  I     -.092     .175     1.006     .298   .109000   .226000  -.2490000      .000      .000  
+87 317 46871.00 I   .110020  .000225   .222818  .000342  I -.2508431  .0000231  2.2083 0.0135  I     -.389     .175      .864     .298   .109000   .225000  -.2512000      .000      .000  
+87 318 46872.00 I   .109928  .000465   .222495  .000380  I -.2530193  .0000213  2.1266 0.0209  I     -.803     .382      .771     .166   .108000   .224000  -.2534000      .000      .000  
+87 319 46873.00 I   .109637  .000595   .222199  .000472  I -.2550668  .0000349  1.9565 0.0205  I    -1.226     .422      .825     .261   .107000   .223000  -.2553000      .000      .000  
+87 320 46874.00 I   .109055  .000595   .221849  .000472  I -.2569179  .0000350  1.7431 0.0254  I    -1.483     .422     1.081     .261   .107000   .223000  -.2571000      .000      .000  
+87 321 46875.00 I   .108093  .000642   .221367  .000476  I -.2585563  .0000370  1.5396 0.0240  I    -1.407     .422     1.511     .261   .106000   .222000  -.2586000      .000      .000  
+87 322 46876.00 I   .106728  .000628   .220718  .000631  I -.2600186  .0000329  1.4006 0.0222  I     -.987     .422     1.678     .261   .105000   .221000  -.2599000      .000      .000  
+87 323 46877.00 I   .105080  .000703   .219945  .000615  I -.2613939  .0000247  1.3709 0.0210  I     -.374     .641     1.436     .279   .104000   .220000  -.2612000      .000      .000  
+87 324 46878.00 I   .103299  .000849   .219106  .000650  I -.2628015  .0000262  1.4646 0.0186  I      .211     .666      .920     .385   .104000   .219000  -.2624000      .000      .000  
+87 325 46879.00 I   .101537  .000737   .218262  .000651  I -.2643567  .0000279  1.6592 0.0192  I      .563     .669      .279     .390   .103000   .218000  -.2639000      .000      .000  
+87 326 46880.00 I   .099933  .000737   .217460  .000651  I -.2661370  .0000281  1.9052 0.0177  I      .565     .669     -.283     .390   .102000   .217000  -.2656000      .000      .000  
+87 327 46881.00 I   .098585  .000740   .216712  .000613  I -.2681613  .0000218  2.1337 0.0172  I      .453     .669     -.256     .390   .101000   .216000  -.2676000      .000      .000  
+87 328 46882.00 I   .097540  .000701   .216016  .000580  I -.2703756  .0000197  2.2758 0.0149  I      .446     .569      .102     .325   .100000   .215000  -.2698000      .000      .000  
+87 329 46883.00 I   .096745  .000568   .215368  .000214  I -.2726712  .0000202  2.2928 0.0165  I      .536     .286      .362     .345   .099000   .215000  -.2722000      .000      .000  
+87 330 46884.00 I   .096120  .000574   .214758  .000436  I -.2749188  .0000265  2.1827 0.0175  I      .600     .153      .500     .190   .098000   .214000  -.2745000      .000      .000  
+87 331 46885.00 I   .095597  .000478   .214178  .000519  I -.2770051  .0000285  1.9781 0.0189  I      .514     .148      .543     .298   .097000   .213000  -.2766000      .000      .000  
+87 4 1 46886.00 I   .095139  .000479   .213641  .000606  I -.2788608  .0000269  1.7308 0.0238  I      .296     .148      .506     .298   .096000   .212000  -.2785000      .000      .000  
+87 4 2 46887.00 I   .094713  .000526   .213178  .000636  I -.2804693  .0000381  1.4914 0.0329  I      .081     .148      .431     .142   .095000   .211000  -.2801000      .000      .000  
+87 4 3 46888.00 I   .094270  .000586   .212808  .000855  I -.2818591  .0000600  1.2985 0.0356  I      .009     .148      .408     .199   .094000   .211000  -.2815000      .000      .000  
+87 4 4 46889.00 I   .093722  .000586   .212509  .000855  I -.2830897  .0000601  1.1757 0.0405  I      .160     .148      .481     .199   .093000   .210000  -.2828000      .000      .000  
+87 4 5 46890.00 I   .092988  .000581   .212263  .000799  I -.2842360  .0000545  1.1293 0.0354  I      .550     .148      .552     .199   .092000   .210000  -.2839000      .000      .000  
+87 4 6 46891.00 I   .092064  .000439   .212060  .000776  I -.2853731  .0000375  1.1572 0.0303  I     1.122     .148      .464     .199   .091000   .209000  -.2850000      .000      .000  
+87 4 7 46892.00 I   .090975  .000389   .211868  .000591  I -.2865731  .0000263  1.2532 0.0196  I     1.729     .282      .166     .212   .090000   .209000  -.2862000      .000      .000  
+87 4 8 46893.00 I   .089743  .000262   .211650  .000501  I -.2878977  .0000113  1.4038 0.0148  I     2.151     .415     -.215     .199   .089000   .209000  -.2875000      .000      .000  
+87 4 9 46894.00 I   .088394  .000262   .211366  .000501  I -.2893924  .0000136  1.5894 0.0094  I     2.182     .415     -.513     .199   .088000   .208000  -.2890000      .000      .000  
+87 410 46895.00 I   .086971  .000262   .210974  .000501  I -.2910801  .0000149  1.7858 0.0102  I     1.782     .415     -.670     .199   .087000   .208000  -.2907000      .000      .000  
+87 411 46896.00 I   .085500  .000245   .210491  .000572  I -.2929587  .0000151  1.9663 0.0114  I     1.289     .415     -.610     .199   .086000   .208000  -.2926000      .000      .000  
+87 412 46897.00 I   .083991  .000195   .209938  .000697  I -.2949955  .0000173  2.0954 0.0143  I     1.040     .460     -.328     .300   .085000   .207000  -.2946000      .000      .000  
+87 413 46898.00 I   .082464  .000079   .209321  .000755  I -.2971198  .0000242  2.1356 0.0167  I     1.042     .472      .059     .310   .084000   .207000  -.2968000      .000      .000  
+87 414 46899.00 I   .080935  .000075   .208641  .000866  I -.2992297  .0000285  2.0650 0.0179  I     1.075     .464      .427     .346   .083000   .206000  -.2989000      .000      .000  
+87 415 46900.00 I   .079424  .000075   .207916  .000866  I -.3012155  .0000263  1.8917 0.0185  I      .888     .464      .634     .346   .082000   .206000  -.3009000      .000      .000  
+87 416 46901.00 I   .077952  .000107   .207220  .000774  I -.3029897  .0000235  1.6483 0.0187  I      .584     .603      .506     .366   .081000   .206000  -.3027000      .000      .000  
+87 417 46902.00 I   .076542  .000107   .206595  .000774  I -.3045084  .0000266  1.3937 0.0290  I      .436     .603      .085     .366   .080000   .206000  -.3043000      .000      .000  
+87 418 46903.00 I   .075219  .000140   .206060  .000777  I -.3057977  .0000530  1.2009 0.0453  I      .618     .654     -.416     .337   .078000   .205000  -.3055000      .000      .000  
+87 419 46904.00 I   .074010  .000333   .205614  .000467  I -.3069486  .0000866  1.1233 0.0506  I     1.113     .763     -.792     .391   .077000   .205000  -.3067000      .000      .000  
+87 420 46905.00 I   .072932  .000381   .205255  .000453  I -.3080894  .0000861  1.1812 0.0564  I     1.760     .668     -.887     .335   .076000   .205000  -.3079000      .000      .000  
+87 421 46906.00 I   .071990  .000437   .204990  .000679  I -.3093493  .0000724  1.3542 0.0543  I     2.315     .668     -.814     .335   .075000   .204000  -.3092000      .000      .000  
+87 422 46907.00 I   .071179  .000431   .204811  .000663  I -.3108178  .0000661  1.5874 0.0531  I     2.617     .615     -.744     .104   .074000   .204000  -.3107000      .000      .000  
+87 423 46908.00 I   .070473  .000461   .204690  .000707  I -.3125279  .0000777  1.8322 0.0485  I     2.629     .615     -.798     .104   .073000   .204000  -.3125000      .000      .000  
+87 424 46909.00 I   .069810  .000492   .204601  .000701  I -.3144718  .0000709  2.0460 0.0526  I     2.530     .615     -.853     .104   .072000   .203000  -.3145000      .000      .000  
+87 425 46910.00 I   .069116  .000492   .204498  .000701  I -.3165887  .0000710  2.1662 0.0436  I     2.565     .615     -.712     .104   .071000   .203000  -.3166000      .000      .000  
+87 426 46911.00 I   .068329  .000484   .204384  .000743  I -.3187598  .0000508  2.1533 0.0423  I     2.743     .696     -.408     .298   .070000   .203000  -.3187000      .000      .000  
+87 427 46912.00 I   .067396  .000538   .204269  .000780  I -.3208546  .0000461  2.0183 0.0412  I     2.986    1.105     -.124     .537   .069000   .202000  -.3207000      .000      .000  
+87 428 46913.00 I   .066290  .000560   .204134  .000855  I -.3227685  .0000650  1.7998 0.0286  I     3.201    1.248     -.041     .634   .068000   .202000  -.3225000      .000      .000  
+87 429 46914.00 I   .064990  .000469   .203955  .000781  I -.3244426  .0000337  1.5467 0.0363  I     3.229    1.248     -.241     .634   .067000   .202000  -.3241000      .000      .000  
+87 430 46915.00 I   .063489  .000422   .203714  .000795  I -.3258673  .0000325  1.3098 0.0233  I     2.930    1.090     -.662     .558   .066000   .202000  -.3254000      .000      .000  
+87 5 1 46916.00 I   .061855  .000400   .203438  .000720  I -.3270799  .0000323  1.1261 0.0206  I     2.627    1.006    -1.030     .513   .064000   .201000  -.3265000      .000      .000  
+87 5 2 46917.00 I   .060205  .000490   .203149  .000754  I -.3281429  .0000253  1.0126 0.0211  I     2.551    1.025    -1.156     .463   .063000   .201000  -.3275000      .000      .000  
+87 5 3 46918.00 I   .058669  .000431   .202858  .000682  I -.3291293  .0000273  0.9718 0.0240  I     2.695     .756    -1.062     .226   .062000   .201000  -.3284000      .000      .000  
+87 5 4 46919.00 I   .057350  .000398   .202549  .000674  I -.3301078  .0000407  0.9948 0.0254  I     2.917     .736     -.954     .245   .060000   .201000  -.3293000      .000      .000  
+87 5 5 46920.00 I   .056318  .000420   .202180  .000716  I -.3311396  .0000428  1.0799 0.0291  I     3.246     .674    -1.220     .229   .059000   .201000  -.3304000      .000      .000  
+87 5 6 46921.00 I   .055534  .000517   .201759  .000754  I -.3322852  .0000416  1.2180 0.0303  I     3.674     .731    -1.582     .248   .058000   .200000  -.3316000      .000      .000  
+87 5 7 46922.00 I   .054880  .000536   .201348  .000707  I -.3335849  .0000430  1.3842 0.0358  I     3.998     .706    -1.634     .256   .056000   .200000  -.3330000      .000      .000  
+87 5 8 46923.00 I   .054226  .000469   .201005  .000804  I -.3350588  .0000583  1.5661 0.0428  I     3.928     .409    -1.353     .211   .055000   .200000  -.3346000      .000      .000  
+87 5 9 46924.00 I   .053433  .000540   .200748  .000747  I -.3367160  .0000741  1.7447 0.0473  I     3.409     .463     -.962     .227   .054000   .200000  -.3363000      .000      .000  
+87 510 46925.00 I   .052428  .000540   .200544  .000747  I -.3385294  .0000746  1.8668 0.0444  I     2.699     .463     -.637     .227   .052000   .199000  -.3382000      .000      .000  
+87 511 46926.00 I   .051219  .000467   .200369  .000698  I -.3404133  .0000488  1.8800 0.0428  I     2.101     .558     -.335     .263   .051000   .199000  -.3401000      .000      .000  
+87 512 46927.00 I   .049840  .000374   .200207  .000485  I -.3422469  .0000418  1.7658 0.0325  I     1.637     .653     -.061     .204   .049000   .199000  -.3420000      .000      .000  
+87 513 46928.00 I   .048329  .000279   .200022  .000507  I -.3439092  .0000428  1.5445 0.0250  I     1.152     .735      .027     .118   .048000   .198000  -.3437000      .000      .000  
+87 514 46929.00 I   .046729  .000254   .199778  .000464  I -.3453195  .0000275  1.2738 0.0371  I      .704     .735     -.178     .118   .047000   .198000  -.3451000      .000      .000  
+87 515 46930.00 I   .045091  .000274   .199449  .000479  I -.3464683  .0000607  1.0374 0.0295  I      .633     .735     -.561     .118   .045000   .198000  -.3462000      .000      .000  
+87 516 46931.00 I   .043468  .000318   .199072  .000469  I -.3474324  .0000522  0.9151 0.0383  I     1.138     .735     -.884     .118   .043000   .197000  -.3472000      .000      .000  
+87 517 46932.00 I   .041909  .000513   .198704  .000638  I -.3483486  .0000466  0.9430 0.0424  I     2.025     .568    -1.007     .304   .042000   .197000  -.3482000      .000      .000  
+87 518 46933.00 I   .040463  .000551   .198405  .000837  I -.3493633  .0000669  1.1054 0.0406  I     2.882     .323     -.959     .413   .041000   .197000  -.3492000      .000      .000  
+87 519 46934.00 I   .039181  .000551   .198239  .000837  I -.3505857  .0000665  1.3466 0.0568  I     3.403     .323     -.849     .413   .039000   .197000  -.3505000      .000      .000  
+87 520 46935.00 I   .038100  .000622   .198265  .000994  I -.3520593  .0000917  1.5962 0.0447  I     3.536     .323     -.750     .413   .038000   .196000  -.3520000      .000      .000  
+87 521 46936.00 I   .037168  .000813   .198481  .001149  I -.3537602  .0000597  1.7922 0.0514  I     3.418     .323     -.675     .413   .037000   .196000  -.3538000      .000      .000  
+87 522 46937.00 I   .036280  .000865   .198815  .001210  I -.3556124  .0000465  1.8942 0.0415  I     3.161     .350     -.597     .345   .036000   .196000  -.3557000      .000      .000  
+87 523 46938.00 I   .035329  .000895   .199181  .001320  I -.3575135  .0000576  1.8907 0.0371  I     2.770     .401     -.481     .224   .035000   .196000  -.3576000      .000      .000  
+87 524 46939.00 I   .034223  .000897   .199476  .001206  I -.3593644  .0000578  1.7988 0.0413  I     2.225     .401     -.308     .224   .034000   .195000  -.3594000      .000      .000  
+87 525 46940.00 I   .032936  .000897   .199579  .001206  I -.3610880  .0000593  1.6377 0.0331  I     1.611     .401     -.140     .224   .034000   .195000  -.3611000      .000      .000  
+87 526 46941.00 I   .031586  .000867   .199492  .001159  I -.3626238  .0000324  1.4288 0.0341  I     1.208     .401     -.193     .224   .033000   .195000  -.3625000      .000      .000  
+87 527 46942.00 I   .030268  .000693   .199271  .001069  I -.3639418  .0000337  1.2087 0.0240  I     1.113     .690     -.549     .216   .032000   .195000  -.3637000      .000      .000  
+87 528 46943.00 I   .029042  .000405   .198973  .000674  I -.3650490  .0000353  1.0122 0.0265  I     1.161     .730    -1.032     .168   .031000   .195000  -.3647000      .000      .000  
+87 529 46944.00 I   .027961  .000237   .198658  .000747  I -.3659816  .0000410  0.8619 0.0270  I     1.179     .800    -1.340     .184   .030000   .195000  -.3655000      .000      .000  
+87 530 46945.00 I   .027069  .000233   .198384  .000842  I -.3667955  .0000408  0.7798 0.0279  I     1.103     .800    -1.262     .184   .030000   .195000  -.3663000      .000      .000  
+87 531 46946.00 I   .026356  .000210   .198192  .000781  I -.3675670  .0000378  0.7751 0.0306  I      .974     .800    -1.017     .184   .029000   .195000  -.3670000      .000      .000  
+87 6 1 46947.00 I   .025775  .000224   .198083  .000727  I -.3683667  .0000457  0.8332 0.0331  I      .852     .665     -.875     .201   .029000   .195000  -.3678000      .000      .000  
+87 6 2 46948.00 I   .025279  .000173   .198053  .000671  I -.3692478  .0000543  0.9344 0.0377  I      .828     .323     -.884     .199   .028000   .195000  -.3687000      .000      .000  
+87 6 3 46949.00 I   .024820  .000191   .198093  .000419  I -.3702416  .0000599  1.0539 0.0408  I     1.019     .388     -.894     .224   .027000   .195000  -.3698000      .000      .000  
+87 6 4 46950.00 I   .024353  .000268   .198199  .000477  I -.3713598  .0000608  1.1861 0.0431  I     1.395     .522     -.770     .191   .027000   .195000  -.3711000      .000      .000  
+87 6 5 46951.00 I   .023855  .000268   .198360  .000477  I -.3726176  .0000621  1.3299 0.0434  I     1.621     .522     -.588     .191   .026000   .195000  -.3726000      .000      .000  
+87 6 6 46952.00 I   .023324  .000268   .198545  .000477  I -.3740154  .0000620  1.4612 0.0427  I     1.389     .522     -.519     .191   .025000   .196000  -.3742000      .000      .000  
+87 6 7 46953.00 I   .022759  .000811   .198715  .000462  I -.3755227  .0000586  1.5407 0.0443  I      .772     .629     -.539     .151   .025000   .196000  -.3759000      .000      .000  
+87 6 8 46954.00 I   .022130  .000848   .198843  .000468  I -.3770620  .0000632  1.5158 0.0434  I      .124     .532     -.444     .128   .024000   .196000  -.3775000      .000      .000  
+87 6 9 46955.00 I   .021384  .000848   .198929  .000468  I -.3785134  .0000640  1.3683 0.0422  I     -.348     .532     -.171     .128   .023000   .197000  -.3790000      .000      .000  
+87 610 46956.00 I   .020463  .000920   .198976  .000403  I -.3797706  .0000559  1.1367 0.0369  I     -.710     .218      .050     .298   .022000   .197000  -.3802000      .000      .000  
+87 611 46957.00 I   .019334  .000928   .198993  .000378  I -.3807825  .0000368  0.8922 0.0349  I     -.928     .449     -.054     .149   .021000   .198000  -.3812000      .000      .000  
+87 612 46958.00 I   .018054  .000928   .199008  .000378  I -.3815793  .0000418  0.7205 0.0321  I     -.807     .449     -.419     .149   .020000   .198000  -.3819000      .000      .000  
+87 613 46959.00 I   .016708  .000928   .199060  .000378  I -.3822681  .0000525  0.6826 0.0334  I     -.282     .449     -.717     .149   .019000   .199000  -.3826000      .000      .000  
+87 614 46960.00 I   .015382  .000514   .199185  .000416  I -.3829938  .0000520  0.7926 0.0420  I      .350     .524     -.739     .176   .018000   .199000  -.3833000      .000      .000  
+87 615 46961.00 I   .014115  .000474   .199396  .000386  I -.3838894  .0000657  1.0108 0.0368  I      .694     .524     -.581     .176   .017000   .200000  -.3842000      .000      .000  
+87 616 46962.00 I   .012925  .000470   .199696  .000453  I -.3850249  .0000521  1.2576 0.0482  I      .593     .422     -.420     .125   .016000   .200000  -.3853000      .000      .000  
+87 617 46963.00 I   .011828  .000445   .200086  .000452  I -.3863871  .0000706  1.4519 0.0448  I      .179     .415     -.295     .298   .014000   .201000  -.3867000      .000      .000  
+87 618 46964.00 I   .010807  .000445   .200548  .000452  I -.3878939  .0000728  1.5417 0.0486  I     -.311     .415     -.177     .298   .013000   .201000  -.3883000      .000      .000  
+87 619 46965.00 I   .009827  .000445   .201057  .000452  I -.3894316  .0000669  1.5150 0.0459  I     -.683     .415     -.125     .298   .012000   .202000  -.3898000      .000      .000  
+87 620 46966.00 I   .008835  .000389   .201586  .000672  I -.3908886  .0000560  1.3826 0.0380  I     -.751     .415     -.236     .298   .011000   .202000  -.3912000      .000      .000  
+87 621 46967.00 I   .007817  .000405   .202110  .000738  I -.3921712  .0000359  1.1733 0.0295  I     -.609     .831     -.463     .275   .010000   .203000  -.3925000      .000      .000  
+87 622 46968.00 I   .006773  .000227   .202608  .000483  I -.3932229  .0000183  0.9271 0.0192  I     -.539    1.065     -.641     .359   .008000   .203000  -.3935000      .000      .000  
+87 623 46969.00 I   .005702  .000236   .203054  .000491  I -.3940250  .0000136  0.6799 0.0102  I     -.718    1.051     -.657     .361   .007000   .204000  -.3942000      .000      .000  
+87 624 46970.00 I   .004581  .000236   .203435  .000491  I -.3945922  .0000088  0.4613 0.0106  I    -1.184    1.051     -.532     .361   .006000   .205000  -.3948000      .000      .000  
+87 625 46971.00 I   .003328  .000253   .203807  .000561  I -.3949640  .0000162  0.2919 0.0108  I    -1.594    1.051     -.649     .361   .005000   .205000  -.3951000      .000      .000  
+87 626 46972.00 I   .001879  .000364   .204234  .000645  I -.3952013  .0000197  0.1984 0.0131  I    -1.945     .875     -.891     .300   .003000   .206000  -.3954000      .000      .000  
+87 627 46973.00 I   .000318  .000364   .204697  .000554  I -.3953915  .0000205  0.1971 0.0145  I    -2.344     .709     -.879     .216   .002000   .206000  -.3956000      .000      .000  
+87 628 46974.00 I  -.001239  .000373   .205162  .000580  I -.3956235  .0000214  0.2798 0.0293  I    -2.655     .516     -.559     .152   .001000   .207000  -.3959000      .000      .000  
+87 629 46975.00 I  -.002680  .000603   .205607  .000943  I -.3959716  .0000549  0.4240 0.0279  I    -2.707     .568     -.154     .171   .000000   .207000  -.3963000      .000      .000  
+87 630 46976.00 I  -.003968  .000629   .206069  .000923  I -.3964826  .0000515  0.6014 0.0330  I    -2.274     .568     -.082     .171  -.002000   .208000  -.3969000      .000      .000  
+87 7 1 46977.00 I  -.005103  .000608   .206556  .000784  I -.3971767  .0000366  0.7857 0.0325  I    -1.457     .553     -.241     .299  -.003000   .209000  -.3976000      .000      .000  
+87 7 2 46978.00 I  -.006110  .000382   .207053  .000896  I -.3980465  .0000396  0.9475 0.0328  I     -.698     .623     -.195     .350  -.004000   .209000  -.3985000      .000      .000  
+87 7 3 46979.00 I  -.007044  .000444   .207548  .000632  I -.3990551  .0000545  1.0596 0.0343  I     -.394     .518      .046     .363  -.005000   .210000  -.3996000      .000      .000  
+87 7 4 46980.00 I  -.007966  .000426   .208033  .000457  I -.4001420  .0000559  1.1007 0.0353  I     -.789     .591      .147     .413  -.007000   .210000  -.4006000      .000      .000  
+87 7 5 46981.00 I  -.008911  .000359   .208509  .000314  I -.4012269  .0000448  1.0528 0.0365  I    -1.793     .513      .018     .474  -.008000   .211000  -.4017000      .000      .000  
+87 7 6 46982.00 I  -.009909  .000300   .208988  .000275  I -.4022166  .0000470  0.9117 0.0337  I    -2.994     .635     -.114     .343  -.009000   .211000  -.4026000      .000      .000  
+87 7 7 46983.00 I  -.010986  .000223   .209478  .000207  I -.4030268  .0000504  0.7002 0.0388  I    -4.034     .686     -.045     .298  -.010000   .212000  -.4034000      .000      .000  
+87 7 8 46984.00 I  -.012169  .000320   .209989  .000400  I -.4036106  .0000617  0.4697 0.0392  I    -4.800     .686      .136     .298  -.012000   .213000  -.4039000      .000      .000  
+87 7 9 46985.00 I  -.013472  .000349   .210517  .000487  I -.4039816  .0000600  0.2854 0.0434  I    -5.220     .686      .197     .298  -.013000   .213000  -.4042000      .000      .000  
+87 710 46986.00 I  -.014873  .000429   .211044  .000464  I -.4042189  .0000610  0.2135 0.0432  I    -5.067     .686      .109     .298  -.014000   .214000  -.4044000      .000      .000  
+87 711 46987.00 I  -.016356  .000589   .211553  .000454  I -.4044596  .0000622  0.2947 0.0485  I    -4.402     .739      .074     .298  -.016000   .215000  -.4046000      .000      .000  
+87 712 46988.00 I  -.017869  .000681   .212064  .000521  I -.4048559  .0000753  0.5186 0.0552  I    -3.672     .740      .191     .298  -.017000   .216000  -.4050000      .000      .000  
+87 713 46989.00 I  -.019344  .000783   .212606  .000599  I -.4055222  .0000913  0.8188 0.0609  I    -3.319     .810      .291     .110  -.018000   .216000  -.4057000      .000      .000  
+87 714 46990.00 I  -.020705  .000756   .213196  .000479  I -.4064820  .0000958  1.0846 0.0658  I    -3.523     .810      .203     .110  -.019000   .217000  -.4066000      .000      .000  
+87 715 46991.00 I  -.021913  .000742   .213841  .000532  I -.4076496  .0000949  1.2249 0.0600  I    -4.130    1.046      .029     .224  -.020000   .218000  -.4078000      .000      .000  
+87 716 46992.00 I  -.022946  .000600   .214544  .000297  I -.4088811  .0000721  1.2130 0.0610  I    -4.927    1.293     -.021     .290  -.021000   .219000  -.4090000      .000      .000  
+87 717 46993.00 I  -.023784  .000453   .215306  .000302  I -.4100321  .0000768  1.0706 0.0520  I    -5.712    1.336      .047     .323  -.022000   .219000  -.4101000      .000      .000  
+87 718 46994.00 I  -.024434  .000453   .216111  .000302  I -.4109970  .0000750  0.8523 0.0538  I    -6.226    1.336      .012     .323  -.023000   .220000  -.4111000      .000      .000  
+87 719 46995.00 I  -.024929  .000413   .216938  .000327  I -.4117266  .0000753  0.6039 0.0473  I    -6.433    1.336     -.129     .323  -.023000   .221000  -.4118000      .000      .000  
+87 720 46996.00 I  -.025340  .000429   .217783  .000392  I -.4122057  .0000576  0.3584 0.0442  I    -6.574    1.214     -.172     .355  -.024000   .222000  -.4123000      .000      .000  
+87 721 46997.00 I  -.025680  .000366   .218647  .000366  I -.4124557  .0000463  0.1500 0.0354  I    -6.743     .954     -.130     .484  -.024000   .222000  -.4126000      .000      .000  
+87 722 46998.00 I  -.025937  .000302   .219537  .000334  I -.4125270  .0000412  0.0054 0.0329  I    -6.845     .261     -.246     .502  -.025000   .223000  -.4126000      .000      .000  
+87 723 46999.00 I  -.026102  .000270   .220452  .000394  I -.4124929  .0000468 -0.0602 0.0313  I    -6.713     .290     -.728     .556  -.025000   .224000  -.4126000      .000      .000  
+87 724 47000.00 I  -.026180  .000270   .221376  .000394  I -.4124338  .0000471 -0.0442 0.0303  I    -6.470     .290     -.981     .556  -.025000   .225000  -.4125000      .000      .000  
+87 725 47001.00 I  -.026210  .000268   .222271  .000388  I -.4124291  .0000386  0.0454 0.0302  I    -6.292     .290     -.888     .556  -.025000   .226000  -.4125000      .000      .000  
+87 726 47002.00 I  -.026216  .000266   .223132  .000432  I -.4125424  .0000378  0.1882 0.0266  I    -6.218     .457     -.512     .494  -.026000   .226000  -.4126000      .000      .000  
+87 727 47003.00 I  -.026225  .000136   .223964  .000322  I -.4128161  .0000365  0.3627 0.0335  I    -6.222     .552     -.040     .326  -.026000   .227000  -.4129000      .000      .000  
+87 728 47004.00 I  -.026262  .000176   .224772  .000483  I -.4132713  .0000553  0.5476 0.0393  I    -6.281     .668      .264     .342  -.026000   .228000  -.4133000      .000      .000  
+87 729 47005.00 I  -.026357  .000139   .225559  .000398  I -.4139051  .0000696  0.7139 0.0332  I    -6.363     .668      .338     .342  -.026000   .229000  -.4140000      .000      .000  
+87 730 47006.00 I  -.026538  .000353   .226339  .000367  I -.4146832  .0000367  0.8326 0.0396  I    -6.430     .668      .314     .342  -.026000   .230000  -.4148000      .000      .000  
+87 731 47007.00 I  -.026828  .000392   .227130  .000548  I -.4155480  .0000378  0.8845 0.0274  I    -6.528     .788      .273     .232  -.027000   .230000  -.4156000      .000      .000  
+87 8 1 47008.00 I  -.027249  .000413   .227951  .000608  I -.4164262  .0000407  0.8583 0.0280  I    -6.793     .859      .148     .298  -.027000   .231000  -.4165000      .000      .000  
+87 8 2 47009.00 I  -.027824  .000413   .228830  .000608  I -.4172396  .0000413  0.7571 0.0315  I    -7.282     .859     -.111     .298  -.027000   .232000  -.4174000      .000      .000  
+87 8 3 47010.00 I  -.028553  .000413   .229784  .000608  I -.4179193  .0000482  0.5928 0.0336  I    -7.851     .859     -.391     .298  -.028000   .233000  -.4181000      .000      .000  
+87 8 4 47011.00 I  -.029366  .000478   .230769  .000672  I -.4184132  .0000531  0.3927 0.0356  I    -8.282     .859     -.534     .298  -.028000   .234000  -.4186000      .000      .000  
+87 8 5 47012.00 I  -.030185  .000552   .231733  .000647  I -.4187114  .0000525  0.2128 0.0530  I    -8.423     .747     -.533     .166  -.028000   .234000  -.4189000      .000      .000  
+87 8 6 47013.00 I  -.030950  .000568   .232651  .000627  I -.4188688  .0000917  0.1229 0.0437  I    -8.236     .540     -.506     .232  -.029000   .235000  -.4191000      .000      .000  
+87 8 7 47014.00 I  -.031605  .000482   .233510  .000421  I -.4190079  .0000699  0.1852 0.0578  I    -7.793     .540     -.467     .232  -.030000   .236000  -.4193000      .000      .000  
+87 8 8 47015.00 I  -.032125  .000482   .234318  .000421  I -.4192911  .0000705  0.4030 0.0481  I    -7.319     .564     -.311     .203  -.030000   .237000  -.4195000      .000      .000  
+87 8 9 47016.00 I  -.032557  .000471   .235103  .000414  I -.4198449  .0000661  0.7136 0.0464  I    -7.053     .564     -.078     .203  -.030000   .238000  -.4200000      .000      .000  
+87 810 47017.00 I  -.032972  .000595   .235882  .000593  I -.4207195  .0000604  1.0279 0.0425  I    -6.993    1.691     -.052     .762  -.031000   .239000  -.4209000      .000      .000  
+87 811 47018.00 I  -.033433  .000435   .236668  .000552  I -.4218732  .0000535  1.2599 0.0371  I    -6.859    2.145     -.466     .976  -.032000   .239000  -.4221000      .000      .000  
+87 812 47019.00 I  -.033981  .000487   .237483  .000592  I -.4231936  .0000430  1.3549 0.0355  I    -6.603    2.145    -1.100     .976  -.032000   .240000  -.4234000      .000      .000  
+87 813 47020.00 I  -.034635  .000438   .238350  .000530  I -.4245314  .0000467  1.2953 0.0430  I    -6.641    2.145    -1.438     .976  -.032000   .241000  -.4248000      .000      .000  
+87 814 47021.00 I  -.035353  .000827   .239274  .000758  I -.4257428  .0000745  1.1117 0.0428  I    -7.136    2.572    -1.366    1.159  -.033000   .242000  -.4261000      .000      .000  
+87 815 47022.00 I  -.036075  .000856   .240246  .000732  I -.4267350  .0000718  0.8687 0.0520  I    -7.828    1.994    -1.180    1.018  -.034000   .243000  -.4271000      .000      .000  
+87 816 47023.00 I  -.036740  .000785   .241261  .000407  I -.4274817  .0000726  0.6301 0.0520  I    -8.349    1.158    -1.141     .855  -.034000   .244000  -.4279000      .000      .000  
+87 817 47024.00 I  -.037298  .000785   .242313  .000407  I -.4280123  .0000752  0.4429 0.0515  I    -8.597    1.158    -1.197     .855  -.034000   .245000  -.4284000      .000      .000  
+87 818 47025.00 I  -.037712  .000785   .243403  .000407  I -.4283918  .0000731  0.3286 0.0512  I    -8.723    1.158    -1.160     .855  -.035000   .246000  -.4288000      .000      .000  
+87 819 47026.00 I  -.038015  .000830   .244553  .000469  I -.4286951  .0000696  0.2909 0.0431  I    -8.859    1.158    -1.005     .855  -.035000   .247000  -.4291000      .000      .000  
+87 820 47027.00 I  -.038232  .000815   .245777  .000529  I -.4289996  .0000455  0.3310 0.0411  I    -8.969     .925     -.880     .691  -.035000   .248000  -.4293000      .000      .000  
+87 821 47028.00 I  -.038367  .000666   .247084  .000493  I -.4293826  .0000438  0.4476 0.0415  I    -9.025     .519     -.842     .414  -.036000   .249000  -.4297000      .000      .000  
+87 822 47029.00 I  -.038417  .000800   .248479  .000512  I -.4299181  .0000694  0.6340 0.0426  I    -9.120     .519     -.749     .414  -.036000   .250000  -.4301000      .000      .000  
+87 823 47030.00 I  -.038349  .000800   .249945  .000512  I -.4306659  .0000731  0.8664 0.0471  I    -9.337     .519     -.483     .414  -.036000   .251000  -.4308000      .000      .000  
+87 824 47031.00 I  -.038177  .000727   .251444  .000659  I -.4316518  .0000636  1.1016 0.0493  I    -9.611     .870     -.287     .409  -.036000   .252000  -.4317000      .000      .000  
+87 825 47032.00 I  -.037996  .000643   .252925  .000899  I -.4328582  .0000662  1.3043 0.0498  I    -9.766     .819     -.312     .388  -.036000   .253000  -.4327000      .000      .000  
+87 826 47033.00 I  -.037882  .000586   .254343  .000889  I -.4342427  .0000767  1.4540 0.0588  I    -9.610     .876     -.402     .301  -.036000   .254000  -.4340000      .000      .000  
+87 827 47034.00 I  -.037847  .000519   .255669  .000950  I -.4357424  .0000973  1.5322 0.0591  I    -9.027     .969     -.281     .316  -.036000   .256000  -.4354000      .000      .000  
+87 828 47035.00 I  -.037895  .000313   .256887  .001041  I -.4372807  .0000899  1.5311 0.0626  I    -8.509     .969     -.174     .316  -.037000   .257000  -.4369000      .000      .000  
+87 829 47036.00 I  -.038023  .000355   .258032  .000954  I -.4387741  .0000787  1.4384 0.0582  I    -8.480     .969     -.151     .316  -.037000   .258000  -.4383000      .000      .000  
+87 830 47037.00 I  -.038225  .000375   .259111  .001024  I -.4401286  .0000738  1.2589 0.0602  I    -8.932     .697     -.194     .241  -.037000   .259000  -.4395000      .000      .000  
+87 831 47038.00 I  -.038498  .000303   .260125  .000969  I -.4412756  .0000911  1.0306 0.0532  I    -9.637     .688     -.308     .122  -.037000   .260000  -.4406000      .000      .000  
+87 9 1 47039.00 I  -.038840  .000351   .261097  .000696  I -.4421910  .0000767  0.8061 0.0544  I   -10.255     .670     -.450     .143  -.037000   .261000  -.4415000      .000      .000  
+87 9 2 47040.00 I  -.039245  .000378   .262047  .000682  I -.4429115  .0000595  0.6527 0.0495  I   -10.417     .670     -.573     .143  -.037000   .262000  -.4423000      .000      .000  
+87 9 3 47041.00 I  -.039685  .000408   .262965  .000782  I -.4435399  .0000626  0.6296 0.0406  I   -10.029     .670     -.651     .143  -.038000   .263000  -.4430000      .000      .000  
+87 9 4 47042.00 I  -.040124  .000411   .263832  .000746  I -.4442230  .0000554  0.7633 0.0673  I    -9.290     .797     -.624     .358  -.038000   .264000  -.4437000      .000      .000  
+87 9 5 47043.00 I  -.040523  .000354   .264630  .000626  I -.4451130  .0001191  1.0366 0.0657  I    -8.587     .906     -.416     .485  -.038000   .265000  -.4447000      .000      .000  
+87 9 6 47044.00 I  -.040855  .000526   .265354  .000657  I -.4463229  .0001191  1.3900 0.0842  I    -8.290     .906     -.075     .485  -.039000   .266000  -.4460000      .000      .000  
+87 9 7 47045.00 I  -.041118  .000526   .266020  .000657  I -.4478847  .0001191  1.7187 0.0789  I    -8.450     .906      .183     .485  -.039000   .267000  -.4476000      .000      .000  
+87 9 8 47046.00 I  -.041363  .000552   .266679  .000644  I -.4497182  .0001035  1.9213 0.0728  I    -8.761     .906      .165     .485  -.040000   .268000  -.4495000      .000      .000  
+87 9 9 47047.00 I  -.041653  .000547   .267387  .000655  I -.4516703  .0000836  1.9531 0.0694  I    -8.990     .662     -.054     .475  -.040000   .269000  -.4514000      .000      .000  
+87 910 47048.00 I  -.042021  .000569   .268187  .000561  I -.4535705  .0000926  1.8233 0.0512  I    -9.275     .216     -.206     .390  -.040000   .270000  -.4534000      .000      .000  
+87 911 47049.00 I  -.042457  .000569   .269114  .000561  I -.4552813  .0000591  1.5866 0.0630  I    -9.842     .216     -.165     .390  -.041000   .271000  -.4551000      .000      .000  
+87 912 47050.00 I  -.042953  .000446   .270192  .000563  I -.4567302  .0000854  1.3093 0.0492  I   -10.563     .216     -.089     .390  -.041000   .272000  -.4565000      .000      .000  
+87 913 47051.00 I  -.043493  .000504   .271416  .000723  I -.4579047  .0000786  1.0462 0.0568  I   -11.005     .216     -.149     .390  -.042000   .273000  -.4577000      .000      .000  
+87 914 47052.00 I  -.044063  .000506   .272731  .001045  I -.4588415  .0000750  0.8397 0.0572  I   -10.949     .281     -.292     .309  -.042000   .274000  -.4587000      .000      .000  
+87 915 47053.00 I  -.044648  .000502   .274073  .001134  I -.4596119  .0000830  0.7165 0.0611  I   -10.581     .309     -.333     .106  -.043000   .275000  -.4595000      .000      .000  
+87 916 47054.00 I  -.045227  .000583   .275365  .001194  I -.4603080  .0000965  0.6937 0.0674  I   -10.176     .355     -.225     .126  -.043000   .276000  -.4603000      .000      .000  
+87 917 47055.00 I  -.045787  .000540   .276532  .001062  I -.4610335  .0001062  0.7733 0.0635  I    -9.859     .355     -.114     .126  -.044000   .277000  -.4611000      .000      .000  
+87 918 47056.00 I  -.046373  .000617   .277570  .001111  I -.4618809  .0000827  0.9316 0.0632  I    -9.614     .355     -.112     .126  -.045000   .278000  -.4620000      .000      .000  
+87 919 47057.00 I  -.046997  .000643   .278534  .001047  I -.4629139  .0000685  1.1414 0.0616  I    -9.438     .341     -.129     .130  -.045000   .279000  -.4631000      .000      .000  
+87 920 47058.00 I  -.047655  .000632   .279488  .001034  I -.4641732  .0000912  1.3796 0.0502  I    -9.309     .327     -.007     .134  -.046000   .280000  -.4644000      .000      .000  
+87 921 47059.00 I  -.048324  .000481   .280493  .000494  I -.4656749  .0000734  1.6231 0.0583  I    -9.117     .327      .263     .134  -.046000   .281000  -.4659000      .000      .000  
+87 922 47060.00 I  -.048973  .000481   .281599  .000494  I -.4674083  .0000725  1.8331 0.0448  I    -8.764     .348      .515     .113  -.047000   .282000  -.4676000      .000      .000  
+87 923 47061.00 I  -.049614  .000491   .282841  .000577  I -.4693152  .0000513  1.9653 0.0426  I    -8.383     .348      .580     .113  -.048000   .284000  -.4694000      .000      .000  
+87 924 47062.00 I  -.050272  .000492   .284240  .000634  I -.4713061  .0000449  1.9989 0.0392  I    -8.196     .365      .436     .136  -.048000   .285000  -.4714000      .000      .000  
+87 925 47063.00 I  -.050944  .000420   .285787  .000679  I -.4732788  .0000593  1.9298 0.0382  I    -8.331     .501      .203     .121  -.049000   .286000  -.4732000      .000      .000  
+87 926 47064.00 I  -.051614  .000420   .287435  .000679  I -.4751360  .0000618  1.7717 0.0488  I    -8.724     .501      .020     .121  -.050000   .288000  -.4750000      .000      .000  
+87 927 47065.00 I  -.052266  .000494   .289135  .000754  I -.4768015  .0000776  1.5516 0.0507  I    -9.242     .501     -.074     .121  -.050000   .289000  -.4765000      .000      .000  
+87 928 47066.00 I  -.052910  .000618   .290855  .000780  I -.4782346  .0000804  1.3176 0.0527  I    -9.577     .532     -.147     .137  -.051000   .291000  -.4779000      .000      .000  
+87 929 47067.00 I  -.053555  .000726   .292544  .000861  I -.4794534  .0000713  1.1338 0.0563  I    -9.584     .676     -.248     .385  -.052000   .292000  -.4791000      .000      .000  
+87 930 47068.00 I  -.054200  .000669   .294149  .000798  I -.4805379  .0000787  1.0572 0.0489  I    -9.251     .816     -.374     .484  -.052000   .294000  -.4802000      .000      .000  
+8710 1 47069.00 I  -.054800  .000720   .295654  .000744  I -.4816162  .0000668  1.1257 0.0513  I    -8.618     .846     -.444     .576  -.053000   .295000  -.4813000      .000      .000  
+8710 2 47070.00 I  -.055299  .000720   .297063  .000744  I -.4828365  .0000659  1.3358 0.0396  I    -7.876     .846     -.359     .576  -.054000   .296000  -.4826000      .000      .000  
+8710 3 47071.00 I  -.055709  .000743   .298407  .000497  I -.4843190  .0000427  1.6393 0.0426  I    -7.311     .846     -.089     .576  -.055000   .298000  -.4842000      .000      .000  
+8710 4 47072.00 I  -.056069  .000717   .299702  .000478  I -.4861217  .0000541  1.9624 0.0440  I    -7.129     .688      .293     .457  -.055000   .299000  -.4861000      .000      .000  
+8710 5 47073.00 I  -.056419  .000557   .300959  .000379  I -.4882227  .0000769  2.2222 0.0470  I    -7.287     .100      .627     .298  -.056000   .300000  -.4883000      .000      .000  
+8710 6 47074.00 I  -.056798  .000570   .302186  .000027  I -.4905233  .0000769  2.3536 0.0563  I    -7.541     .100      .756     .298  -.056000   .302000  -.4906000      .000      .000  
+8710 7 47075.00 I  -.057215  .000570   .303393  .000027  I -.4928758  .0000822  2.3228 0.0538  I    -7.731     .100      .651     .298  -.057000   .303000  -.4930000      .000      .000  
+8710 8 47076.00 I  -.057662  .000494   .304588  .000144  I -.4951190  .0000754  2.1424 0.0519  I    -7.946     .100      .444     .298  -.058000   .304000  -.4952000      .000      .000  
+8710 9 47077.00 I  -.058140  .000359   .305779  .000249  I -.4971304  .0000633  1.8714 0.0467  I    -8.366     .822      .274     .298  -.058000   .305000  -.4971000      .000      .000  
+871010 47078.00 I  -.058658  .000276   .306976  .000268  I -.4988550  .0000552  1.5800 0.0552  I    -8.949    1.011      .160     .375  -.059000   .307000  -.4988000      .000      .000  
+871011 47079.00 I  -.059234  .000276   .308184  .000268  I -.5003025  .0000904  1.3249 0.0632  I    -9.362    1.011      .082     .375  -.059000   .308000  -.5002000      .000      .000  
+871012 47080.00 I  -.059879  .000621   .309408  .000643  I -.5015304  .0001136  1.1467 0.0617  I    -9.281    1.011      .097     .375  -.060000   .309000  -.5014000      .000      .000  
+871013 47081.00 I  -.060578  .000534   .310627  .000544  I -.5026280  .0000839  1.0649 0.0642  I    -8.711    1.011      .264     .375  -.060000   .310000  -.5025000      .000      .000  
+871014 47082.00 I  -.061318  .000527   .311812  .000542  I -.5036915  .0000599  1.0770 0.0531  I    -7.906     .811      .515     .284  -.060000   .311000  -.5035000      .000      .000  
+871015 47083.00 I  -.062070  .000570   .312940  .000562  I -.5048089  .0000651  1.1697 0.0456  I    -7.139     .590      .670     .124  -.061000   .313000  -.5046000      .000      .000  
+871016 47084.00 I  -.062740  .000570   .314034  .000562  I -.5060519  .0000687  1.3253 0.0410  I    -6.603     .590      .608     .124  -.061000   .314000  -.5059000      .000      .000  
+871017 47085.00 I  -.063223  .000511   .315126  .000550  I -.5074719  .0000500  1.5180 0.0371  I    -6.414     .590      .389     .124  -.062000   .315000  -.5073000      .000      .000  
+871018 47086.00 I  -.063481  .000354   .316244  .000459  I -.5090887  .0000278  1.7132 0.0289  I    -6.384     .513      .270     .115  -.062000   .316000  -.5089000      .000      .000  
+871019 47087.00 I  -.063542  .000364   .317388  .000478  I -.5108898  .0000288  1.8830 0.0249  I    -6.344     .640      .390     .124  -.062000   .317000  -.5107000      .000      .000  
+871020 47088.00 I  -.063443  .000286   .318552  .000537  I -.5128381  .0000412  2.0031 0.0282  I    -6.341     .618      .658     .121  -.062000   .318000  -.5127000      .000      .000  
+871021 47089.00 I  -.063229  .000268   .319720  .000567  I -.5148723  .0000484  2.0520 0.0286  I    -6.444     .542      .948     .139  -.062000   .319000  -.5147000      .000      .000  
+871022 47090.00 I  -.062982  .000268   .320871  .000567  I -.5169156  .0000398  2.0215 0.0327  I    -6.725     .542     1.123     .139  -.063000   .320000  -.5168000      .000      .000  
+871023 47091.00 I  -.062783  .000281   .322005  .000537  I -.5188895  .0000439  1.9137 0.0311  I    -7.055     .542     1.224     .139  -.063000   .321000  -.5187000      .000      .000  
+871024 47092.00 I  -.062657  .000325   .323114  .000574  I -.5207186  .0000479  1.7328 0.0352  I    -7.282     .549     1.206     .127  -.063000   .322000  -.5205000      .000      .000  
+871025 47093.00 I  -.062589  .000351   .324213  .000599  I -.5223417  .0000551  1.5116 0.0352  I    -7.361     .318     1.096     .120  -.063000   .323000  -.5220000      .000      .000  
+871026 47094.00 I  -.062553  .000342   .325320  .000373  I -.5237487  .0000516  1.3111 0.0397  I    -7.273     .355     1.006     .109  -.063000   .325000  -.5234000      .000      .000  
+871027 47095.00 I  -.062531  .000434   .326452  .000453  I -.5249939  .0000571  1.2005 0.0365  I    -6.979     .420      .973     .298  -.063000   .326000  -.5246000      .000      .000  
+871028 47096.00 I  -.062507  .000436   .327621  .000406  I -.5261949  .0000515  1.2255 0.0349  I    -6.469     .420      .959     .298  -.063000   .327000  -.5257000      .000      .000  
+871029 47097.00 I  -.062459  .000626   .328833  .000365  I -.5274888  .0000400  1.3822 0.0307  I    -5.804     .713      .947     .115  -.063000   .328000  -.5271000      .000      .000  
+871030 47098.00 I  -.062370  .000697   .330089  .000266  I -.5289897  .0000335  1.6301 0.0266  I    -5.128     .776      .961     .132  -.063000   .329000  -.5286000      .000      .000  
+871031 47099.00 I  -.062261  .000697   .331385  .000266  I -.5307583  .0000351  1.9060 0.0248  I    -4.629     .776     1.007     .132  -.063000   .331000  -.5304000      .000      .000  
+8711 1 47100.00 I  -.062173  .000673   .332711  .000724  I -.5327890  .0000365  2.1439 0.0239  I    -4.440     .776     1.060     .132  -.062000   .332000  -.5325000      .000      .000  
+8711 2 47101.00 I  -.062171  .000618   .334055  .000734  I -.5350140  .0000324  2.2854 0.0200  I    -4.597     .685     1.185     .116  -.062000   .333000  -.5348000      .000      .000  
+8711 3 47102.00 I  -.062204  .000450   .335394  .000654  I -.5373157  .0000163  2.2946 0.0179  I    -4.908     .674     1.365     .106  -.062000   .335000  -.5372000      .000      .000  
+8711 4 47103.00 I  -.062184  .000453   .336699  .000690  I -.5395601  .0000152  2.1746 0.0159  I    -5.121     .533     1.497     .298  -.062000   .336000  -.5394000      .000      .000  
+8711 5 47104.00 I  -.062019  .000252   .337962  .000725  I -.5416347  .0000272  1.9640 0.0162  I    -5.123     .572     1.489     .298  -.061000   .337000  -.5415000      .000      .000  
+8711 6 47105.00 I  -.061613  .000252   .339246  .000725  I -.5434731  .0000286  1.7083 0.0193  I    -5.033     .572     1.279     .298  -.061000   .339000  -.5434000      .000      .000  
+8711 7 47106.00 I  -.060956  .000322   .340659  .000564  I -.5450545  .0000274  1.4620 0.0197  I    -5.125     .572     1.015     .298  -.060000   .340000  -.5450000      .000      .000  
+8711 8 47107.00 I  -.060130  .000338   .342210  .000560  I -.5464189  .0000270  1.2809 0.0236  I    -5.393     .755      .856     .233  -.060000   .342000  -.5463000      .000      .000  
+8711 9 47108.00 I  -.059246  .000323   .343883  .000539  I -.5476474  .0000385  1.1930 0.0536  I    -5.526     .787      .869     .262  -.060000   .343000  -.5476000      .000      .000  
+871110 47109.00 I  -.058418  .000471   .345665  .000435  I -.5488370  .0001038  1.2015 0.0489  I    -5.240     .832     1.060     .293  -.059000   .345000  -.5487000      .000      .000  
+871111 47110.00 I  -.057743  .000471   .347539  .000435  I -.5500785  .0000898  1.2942 0.0646  I    -4.455     .832     1.315     .293  -.059000   .346000  -.5500000      .000      .000  
+871112 47111.00 I  -.057237  .000400   .349460  .000473  I -.5514459  .0000768  1.4486 0.0566  I    -3.587     .832     1.430     .293  -.059000   .348000  -.5513000      .000      .000  
+871113 47112.00 I  -.056859  .000444   .351377  .000526  I -.5529858  .0000689  1.6335 0.0557  I    -2.974     .643     1.360     .239  -.058000   .350000  -.5528000      .000      .000  
+871114 47113.00 I  -.056557  .000410   .353241  .000442  I -.5547122  .0000806  1.8162 0.0490  I    -2.673     .389     1.272     .110  -.058000   .351000  -.5545000      .000      .000  
+871115 47114.00 I  -.056266  .000386   .355008  .000494  I -.5566074  .0000697  1.9666 0.0463  I    -2.695     .791     1.326     .125  -.058000   .353000  -.5564000      .000      .000  
+871116 47115.00 I  -.055923  .000422   .356643  .000569  I -.5586307  .0000457  2.0730 0.0407  I    -3.032     .791     1.518     .125  -.057000   .355000  -.5584000      .000      .000  
+871117 47116.00 I  -.055519  .000376   .358163  .000520  I -.5607359  .0000420  2.1271 0.0325  I    -3.601     .791     1.699     .125  -.057000   .356000  -.5605000      .000      .000  
+871118 47117.00 I  -.055096  .000448   .359613  .000501  I -.5628610  .0000461  2.1097 0.0384  I    -4.190     .166     1.766     .196  -.056000   .358000  -.5627000      .000      .000  
+871119 47118.00 I  -.054714  .000455   .361041  .000320  I -.5649276  .0000643  2.0093 0.0404  I    -4.579     .233     1.733     .248  -.056000   .360000  -.5648000      .000      .000  
+871120 47119.00 I  -.054428  .000445   .362491  .000355  I -.5668549  .0000664  1.8348 0.0426  I    -4.704     .233     1.656     .248  -.056000   .362000  -.5667000      .000      .000  
+871121 47120.00 I  -.054270  .000416   .363988  .000365  I -.5685829  .0000558  1.6173 0.0423  I    -4.653     .233     1.566     .248  -.056000   .363000  -.5685000      .000      .000  
+871122 47121.00 I  -.054283  .000374   .365542  .000334  I -.5700928  .0000523  1.4096 0.0402  I    -4.532     .242     1.498     .209  -.056000   .365000  -.5700000      .000      .000  
+871123 47122.00 I  -.054500  .000545   .367150  .000462  I -.5714266  .0000579  1.2753 0.0408  I    -4.375     .253     1.518     .261  -.056000   .366000  -.5713000      .000      .000  
+871124 47123.00 I  -.054941  .000534   .368800  .000491  I -.5726827  .0000626  1.2590 0.0407  I    -4.212     .266     1.647     .270  -.056000   .368000  -.5726000      .000      .000  
+871125 47124.00 I  -.055621  .000512   .370474  .000759  I -.5739870  .0000571  1.3698 0.0585  I    -4.126     .266     1.807     .270  -.057000   .369000  -.5740000      .000      .000  
+871126 47125.00 I  -.056525  .000512   .372135  .000759  I -.5754571  .0000989  1.5849 0.0487  I    -4.098     .266     1.910     .270  -.057000   .371000  -.5756000      .000      .000  
+871127 47126.00 I  -.057559  .000466   .373744  .000688  I -.5771728  .0000788  1.8480 0.0627  I    -4.076     .266     1.935     .270  -.057000   .373000  -.5774000      .000      .000  
+871128 47127.00 I  -.058610  .000710   .375255  .000722  I -.5791443  .0000772  2.0846 0.0574  I    -4.039     .389     1.941     .229  -.058000   .374000  -.5795000      .000      .000  
+871129 47128.00 I  -.059560  .000662   .376646  .000700  I -.5813132  .0000836  2.2349 0.0568  I    -3.996     .418     2.006     .298  -.058000   .375000  -.5817000      .000      .000  
+871130 47129.00 I  -.060283  .000662   .377940  .000700  I -.5835738  .0000834  2.2642 0.0589  I    -3.955     .418     2.164     .298  -.058000   .377000  -.5840000      .000      .000  
+8712 1 47130.00 I  -.060669  .000663   .379173  .000354  I -.5857988  .0000831  2.1652 0.0442  I    -3.876     .418     2.389     .298  -.058000   .378000  -.5863000      .000      .000  
+8712 2 47131.00 I  -.060705  .000598   .380381  .000326  I -.5878707  .0000291  1.9656 0.0515  I    -3.763     .418     2.548     .298  -.058000   .379000  -.5884000      .000      .000  
+8712 3 47132.00 I  -.060455  .000599   .381576  .000330  I -.5897125  .0000607  1.7133 0.0478  I    -3.563     .454     2.569     .141  -.058000   .380000  -.5903000      .000      .000  
+8712 4 47133.00 I  -.059990  .000409   .382762  .000332  I -.5912961  .0000910  1.4573 0.0582  I    -3.235     .435     2.470     .180  -.057000   .382000  -.5918000      .000      .000  
+8712 5 47134.00 I  -.059370  .000378   .383937  .000367  I -.5926399  .0000993  1.2396 0.0637  I    -2.848     .503     2.352     .207  -.057000   .383000  -.5931000      .000      .000  
+8712 6 47135.00 I  -.058644  .000376   .385103  .000434  I -.5937993  .0000893  1.0941 0.0609  I    -2.527     .627     2.391     .428  -.056000   .385000  -.5942000      .000      .000  
+8712 7 47136.00 I  -.057828  .000563   .386266  .000417  I -.5948576  .0000706  1.0373 0.0553  I    -2.336     .684     2.569     .491  -.056000   .386000  -.5952000      .000      .000  
+8712 8 47137.00 I  -.056931  .000515   .387435  .000439  I -.5959009  .0000653  1.0614 0.0443  I    -2.222     .783     2.660     .414  -.055000   .387000  -.5962000      .000      .000  
+8712 9 47138.00 I  -.055941  .000572   .388625  .000474  I -.5970021  .0000536  1.1506 0.0396  I    -2.123     .893     2.326     .492  -.054000   .389000  -.5972000      .000      .000  
+871210 47139.00 I  -.054829  .000572   .389872  .000474  I -.5982189  .0000447  1.2901 0.0348  I    -1.873     .893     1.954     .492  -.053000   .390000  -.5985000      .000      .000  
+871211 47140.00 I  -.053586  .000584   .391201  .000584  I -.5995910  .0000444  1.4557 0.0290  I    -1.522     .893     1.794     .492  -.052000   .391000  -.5998000      .000      .000  
+871212 47141.00 I  -.052243  .000571   .392604  .000492  I -.6011298  .0000369  1.6199 0.0253  I    -1.224     .913     1.859     .400  -.051000   .393000  -.6013000      .000      .000  
+871213 47142.00 I  -.050835  .000559   .394060  .000426  I -.6028227  .0000242  1.7599 0.0237  I    -1.099     .947     2.151     .384  -.050000   .394000  -.6030000      .000      .000  
+871214 47143.00 I  -.049410  .000501   .395542  .000574  I -.6046343  .0000297  1.8540 0.0215  I    -1.287     .803     2.483     .421  -.049000   .395000  -.6048000      .000      .000  
+871215 47144.00 I  -.048052  .000501   .396989  .000574  I -.6065087  .0000355  1.8823 0.0223  I    -1.826     .803     2.586     .421  -.048000   .396000  -.6067000      .000      .000  
+871216 47145.00 I  -.046844  .000422   .398339  .000476  I -.6083731  .0000332  1.8334 0.0248  I    -2.532     .803     2.373     .421  -.047000   .397000  -.6086000      .000      .000  
+871217 47146.00 I  -.045784  .000380   .399552  .000423  I -.6101502  .0000346  1.7085 0.0238  I    -3.189     .699     2.099     .402  -.045000   .399000  -.6104000      .000      .000  
+871218 47147.00 I  -.044816  .000620   .400625  .000408  I -.6117713  .0000340  1.5270 0.0362  I    -3.696     .848     2.006     .403  -.044000   .400000  -.6120000      .000      .000  
+871219 47148.00 I  -.043878  .000621   .401565  .000398  I -.6132009  .0000637  1.3355 0.0327  I    -4.066     .756     2.118     .306  -.043000   .401000  -.6135000      .000      .000  
+871220 47149.00 I  -.042903  .000599   .402385  .000261  I -.6144610  .0000559  1.2001 0.0366  I    -4.232     .742     2.356     .307  -.042000   .402000  -.6147000      .000      .000  
+871221 47150.00 I  -.041828  .000567   .403123  .000252  I -.6156405  .0000362  1.1827 0.0329  I    -3.987     .648     2.350     .262  -.040000   .403000  -.6159000      .000      .000  
+871222 47151.00 I  -.040607  .000584   .403827  .000252  I -.6168739  .0000348  1.3076 0.0235  I    -3.544     .648     2.226     .262  -.039000   .404000  -.6170000      .000      .000  
+871223 47152.00 I  -.039281  .000626   .404537  .000213  I -.6182946  .0000300  1.5493 0.0275  I    -3.221     .698     2.218     .250  -.038000   .405000  -.6184000      .000      .000  
+871224 47153.00 I  -.037899  .000626   .405269  .000213  I -.6199903  .0000425  1.8444 0.0248  I    -3.113     .371     2.251     .298  -.036000   .406000  -.6201000      .000      .000  
+871225 47154.00 I  -.036458  .000367   .406039  .000222  I -.6219738  .0000396  2.1105 0.0393  I    -3.119     .268     2.212     .298  -.035000   .407000  -.6221000      .000      .000  
+871226 47155.00 I  -.034936  .000407   .406865  .000201  I -.6241775  .0000661  2.2750 0.0541  I    -3.094     .316     2.148     .106  -.033000   .408000  -.6243000      .000      .000  
+871227 47156.00 I  -.033335  .000267   .407754  .000421  I -.6264776  .0001007  2.3010 0.0518  I    -3.027     .791     2.192     .298  -.032000   .409000  -.6266000      .000      .000  
+871228 47157.00 I  -.031657  .000102   .408711  .000430  I -.6287351  .0000797  2.1940 0.0644  I    -3.027     .994     2.368     .169  -.030000   .410000  -.6288000      .000      .000  
+871229 47158.00 I  -.029907  .000102   .409744  .000430  I -.6308325  .0000802  1.9879 0.0540  I    -3.147     .994     2.575     .169  -.028000   .411000  -.6309000      .000      .000  
+871230 47159.00 I  -.028088  .000102   .410856  .000430  I -.6326933  .0000730  1.7289 0.0605  I    -3.321     .994     2.709     .169  -.027000   .412000  -.6327000      .000      .000  
+871231 47160.00 I  -.026206  .000102   .412048  .000430  I -.6342906  .0000907  1.4706 0.0456  I    -3.441     .994     2.728     .169  -.025000   .413000  -.6343000      .000      .000  
+88 1 1 47161.00 I  -.024282  .000105   .413287  .000466  I  .3643500  .0000548  1.2587 0.0530  I    -3.420     .994     2.636     .169  -.023000   .414000   .3643000      .000      .000  
+88 1 2 47162.00 I  -.022333  .000380   .414528  .000515  I  .3631681  .0000549  1.1186 0.0443  I    -3.284     .866     2.451     .221  -.021000   .415000   .3631000      .000      .000  
+88 1 3 47163.00 I  -.020379  .000487   .415724  .000509  I  .3620846  .0000696  1.0630 0.0437  I    -3.151     .590     2.267     .292  -.019000   .416000   .3621000      .000      .000  
+88 1 4 47164.00 I  -.018437  .000487   .416831  .000509  I  .3610156  .0000680  1.0870 0.0473  I    -3.083     .590     2.276     .292  -.017000   .417000   .3610000      .000      .000  
+88 1 5 47165.00 I  -.016529  .000345   .417809  .000284  I  .3598894  .0000641  1.1746 0.0408  I    -2.964     .590     2.600     .292  -.015000   .418000   .3598000      .000      .000  
+88 1 6 47166.00 I  -.014674  .000379   .418643  .000650  I  .3586506  .0000450  1.3098 0.0386  I    -2.683     .582     2.845     .311  -.013000   .419000   .3586000      .000      .000  
+88 1 7 47167.00 I  -.012861  .000371   .419338  .000643  I  .3572612  .0000430  1.4710 0.0514  I    -2.267     .646     2.817     .285  -.011000   .420000   .3571000      .000      .000  
+88 1 8 47168.00 I  -.011080  .000428   .419907  .000749  I  .3557089  .0000925  1.6313 0.0513  I    -1.882     .606     2.728     .297  -.010000   .421000   .3555000      .000      .000  
+88 1 9 47169.00 I  -.009315  .000360   .420360  .000778  I  .3540054  .0000931  1.7713 0.0658  I    -1.681     .631     2.872     .246  -.008000   .422000   .3537000      .000      .000  
+88 110 47170.00 I  -.007555  .000401   .420728  .000743  I  .3521806  .0000936  1.8684 0.0616  I    -1.559     .631     3.005     .246  -.006000   .423000   .3519000      .000      .000  
+88 111 47171.00 I  -.005836  .000538   .421099  .000731  I  .3502919  .0000808  1.8956 0.0607  I    -1.647     .631     2.958     .247  -.004000   .423000   .3500000      .000      .000  
+88 112 47172.00 I  -.004197  .000663   .421557  .000736  I  .3484143  .0000772  1.8480 0.0591  I    -2.132     .761     2.731     .215  -.003000   .424000   .3481000      .000      .000  
+88 113 47173.00 I  -.002659  .000777   .422118  .000736  I  .3466188  .0000862  1.7318 0.0473  I    -2.832     .764     2.446     .206  -.001000   .425000   .3464000      .000      .000  
+88 114 47174.00 I  -.001282  .000729   .422756  .000635  I  .3449689  .0000547  1.5609 0.0533  I    -3.436     .691     2.380     .187   .000000   .425000   .3447000      .000      .000  
+88 115 47175.00 I  -.000119  .000650   .423392  .000395  I  .3435070  .0000628  1.3601 0.0392  I    -3.626     .679     2.377     .236   .002000   .426000   .3434000      .000      .000  
+88 116 47176.00 I   .000915  .000608   .423966  .000399  I  .3422443  .0000562  1.1726 0.0404  I    -3.527     .759     2.294     .224   .003000   .426000   .3422000      .000      .000  
+88 117 47177.00 I   .001971  .000562   .424454  .000396  I  .3411366  .0000509  1.0606 0.0392  I    -3.273     .746     2.121     .262   .005000   .427000   .3412000      .000      .000  
+88 118 47178.00 I   .003149  .000430   .424857  .000370  I  .3400813  .0000548  1.0739 0.0372  I    -2.855     .608     2.083     .265   .006000   .427000   .3403000      .000      .000  
+88 119 47179.00 I   .004431  .000410   .425192  .000354  I  .3389456  .0000542  1.2168 0.0390  I    -2.454     .608     2.135     .265   .008000   .428000   .3392000      .000      .000  
+88 120 47180.00 I   .005795  .000311   .425472  .000311  I  .3376186  .0000556  1.4469 0.0323  I    -2.190     .658     2.134     .289   .009000   .428000   .3379000      .000      .000  
+88 121 47181.00 I   .007263  .000220   .425747  .000327  I  .3360472  .0000352  1.6909 0.0314  I    -2.200     .677     2.117     .254   .011000   .429000   .3363000      .000      .000  
+88 122 47182.00 I   .008856  .000229   .426060  .000356  I  .3342621  .0000293  1.8592 0.0247  I    -2.504     .567     2.021     .232   .012000   .429000   .3344000      .000      .000  
+88 123 47183.00 I   .010591  .000216   .426454  .000303  I  .3323757  .0000347  1.8869 0.0232  I    -2.961     .516     1.918     .140   .014000   .430000   .3324000      .000      .000  
+88 124 47184.00 I   .012479  .000323   .426949  .000298  I  .3305363  .0000359  1.7705 0.0241  I    -3.497     .562     2.019     .123   .016000   .430000   .3305000      .000      .000  
+88 125 47185.00 I   .014531  .000369   .427485  .000296  I  .3288699  .0000335  1.5484 0.0243  I    -3.997     .562     2.221     .123   .018000   .431000   .3287000      .000      .000  
+88 126 47186.00 I   .016729  .000360   .428019  .000302  I  .3274564  .0000328  1.2755 0.0217  I    -4.368     .491     2.345     .149   .020000   .431000   .3272000      .000      .000  
+88 127 47187.00 I   .019043  .000384   .428523  .000384  I  .3263147  .0000276  1.0153 0.0269  I    -4.502     .417     2.359     .158   .022000   .431000   .3260000      .000      .000  
+88 128 47188.00 I   .021473  .000470   .428978  .000451  I  .3254055  .0000427  0.8162 0.0228  I    -4.355     .177     2.416     .177   .024000   .432000   .3250000      .000      .000  
+88 129 47189.00 I   .024050  .000470   .429387  .000451  I  .3246553  .0000363  0.6982 0.0258  I    -4.003     .177     2.642     .177   .027000   .432000   .3242000      .000      .000  
+88 130 47190.00 I   .026750  .000357   .429743  .000412  I  .3239802  .0000291  0.6669 0.0208  I    -3.540     .177     2.728     .177   .029000   .433000   .3235000      .000      .000  
+88 131 47191.00 I   .029541  .000348   .430052  .000355  I  .3232923  .0000205  0.7231 0.0168  I    -3.070     .177     2.534     .177   .031000   .433000   .3227000      .000      .000  
+88 2 1 47192.00 I   .032380  .000336   .430341  .000451  I  .3225081  .0000167  0.8568 0.0133  I    -2.683     .243     2.208     .184   .033000   .433000   .3220000      .000      .000  
+88 2 2 47193.00 I   .035225  .000359   .430638  .000408  I  .3215594  .0000168  1.0483 0.0111  I    -2.379     .263     1.975     .181   .036000   .434000   .3210000      .000      .000  
+88 2 3 47194.00 I   .038029  .000359   .430972  .000408  I  .3204005  .0000145  1.2726 0.0112  I    -2.042     .263     1.928     .181   .038000   .434000   .3199000      .000      .000  
+88 2 4 47195.00 I   .040717  .000359   .431369  .000408  I  .3190133  .0000149  1.4995 0.0108  I    -1.592     .263     1.964     .181   .041000   .435000   .3185000      .000      .000  
+88 2 5 47196.00 I   .043197  .000366   .431846  .000498  I  .3174101  .0000161  1.7007 0.0111  I    -1.177     .263     2.000     .181   .044000   .435000   .3169000      .000      .000  
+88 2 6 47197.00 I   .045436  .000358   .432383  .000547  I  .3156276  .0000164  1.8549 0.0126  I     -.958     .264     2.033     .151   .046000   .435000   .3152000      .000      .000  
+88 2 7 47198.00 I   .047417  .000409   .432934  .000612  I  .3137210  .0000193  1.9471 0.0138  I     -.985     .256     2.086     .298   .049000   .435000   .3133000      .000      .000  
+88 2 8 47199.00 I   .049127  .000382   .433448  .000685  I  .3117564  .0000222  1.9705 0.0148  I    -1.242     .265     2.077     .298   .051000   .435000   .3114000      .000      .000  
+88 2 9 47200.00 I   .050562  .000518   .433883  .000614  I  .3098046  .0000225  1.9201 0.0160  I    -1.663     .265     1.831     .298   .053000   .435000   .3095000      .000      .000  
+88 210 47201.00 I   .051772  .000506   .434212  .000668  I  .3079399  .0000231  1.7985 0.0167  I    -2.093     .222     1.400     .126   .054000   .435000   .3077000      .000      .000  
+88 211 47202.00 I   .052828  .000452   .434415  .000635  I  .3062239  .0000248  1.6281 0.0178  I    -2.409     .210     1.094     .127   .056000   .435000   .3061000      .000      .000  
+88 212 47203.00 I   .053789  .000480   .434472  .000610  I  .3046859  .0000271  1.4510 0.0227  I    -2.685     .163     1.172     .146   .057000   .435000   .3046000      .000      .000  
+88 213 47204.00 I   .054660  .000480   .434371  .000610  I  .3033032  .0000380  1.3298 0.0238  I    -3.087     .163     1.546     .146   .058000   .434000   .3033000      .000      .000  
+88 214 47205.00 I   .055477  .000531   .434080  .000638  I  .3019846  .0000392  1.3335 0.0256  I    -3.499     .163     1.716     .146   .059000   .434000   .3019000      .000      .000  
+88 215 47206.00 I   .056309  .000411   .433626  .000640  I  .3005816  .0000343  1.5010 0.0249  I    -3.561     .163     1.551     .146   .060000   .434000   .3005000      .000      .000  
+88 216 47207.00 I   .057220  .000458   .433069  .000575  I  .2989343  .0000307  1.8134 0.0252  I    -3.088     .723     1.375     .212   .061000   .434000   .2988000      .000      .000  
+88 217 47208.00 I   .058272  .000554   .432465  .000478  I  .2969319  .0000368  2.1945 0.0289  I    -2.366    1.004     1.432     .271   .062000   .433000   .2967000      .000      .000  
+88 218 47209.00 I   .059504  .000501   .431860  .000506  I  .2945576  .0000489  2.5386 0.0278  I    -1.903     .833     1.610     .228   .063000   .433000   .2943000      .000      .000  
+88 219 47210.00 I   .060894  .000501   .431273  .000506  I  .2919006  .0000418  2.7449 0.0308  I    -1.942     .833     1.665     .228   .064000   .433000   .2916000      .000      .000  
+88 220 47211.00 I   .062344  .000497   .430743  .000468  I  .2891320  .0000373  2.7585 0.0266  I    -2.322     .833     1.560     .228   .065000   .433000   .2889000      .000      .000  
+88 221 47212.00 I   .063722  .000415   .430316  .000555  I  .2864434  .0000328  2.5926 0.0271  I    -2.798     .775     1.458     .186   .066000   .432000   .2862000      .000      .000  
+88 222 47213.00 I   .064928  .000405   .430027  .000620  I  .2839871  .0000394  2.3059 0.0261  I    -3.213     .576     1.399     .298   .067000   .432000   .2838000      .000      .000  
+88 223 47214.00 I   .065945  .000465   .429861  .000593  I  .2818466  .0000405  1.9741 0.0231  I    -3.384     .576     1.199     .298   .068000   .432000   .2817000      .000      .000  
+88 224 47215.00 I   .066799  .000489   .429796  .000634  I  .2800276  .0000243  1.6762 0.0393  I    -3.133     .653      .738     .298   .069000   .432000   .2798000      .000      .000  
+88 225 47216.00 I   .067596  .000514   .429844  .000575  I  .2784642  .0000674  1.4683 0.0358  I    -2.691     .653      .267     .298   .071000   .432000   .2782000      .000      .000  
+88 226 47217.00 I   .068476  .000511   .429993  .000573  I  .2770556  .0000673  1.3668 0.0608  I    -2.334     .622      .043     .298   .072000   .432000   .2768000      .000      .000  
+88 227 47218.00 I   .069557  .000579   .430227  .000677  I  .2756960  .0001011  1.3693 0.0668  I    -2.133     .580      .049     .298   .073000   .431000   .2754000      .000      .000  
+88 228 47219.00 I   .070903  .000651   .430544  .000372  I  .2742860  .0001154  1.4650 0.0761  I    -2.008     .572      .107     .298   .075000   .431000   .2739000      .000      .000  
+88 229 47220.00 I   .072553  .000496   .430941  .000434  I  .2727442  .0001137  1.6262 0.0711  I    -1.886     .572      .152     .298   .076000   .432000   .2724000      .000      .000  
+88 3 1 47221.00 I   .074468  .000541   .431406  .000383  I  .2710225  .0000830  1.8207 0.0573  I    -1.806     .572      .305     .298   .078000   .432000   .2707000      .000      .000  
+88 3 2 47222.00 I   .076565  .000505   .431907  .000399  I  .2691009  .0000139  2.0207 0.0469  I    -1.780     .429      .644     .129   .080000   .432000   .2688000      .000      .000  
+88 3 3 47223.00 I   .078739  .000435   .432401  .000413  I  .2669896  .0000439  2.1950 0.0227  I    -1.746     .202     1.027     .181   .082000   .432000   .2667000      .000      .000  
+88 3 4 47224.00 I   .080892  .000427   .432834  .000389  I  .2647288  .0000432  2.3156 0.0306  I    -1.693     .202     1.236     .181   .084000   .432000   .2646000      .000      .000  
+88 3 5 47225.00 I   .082956  .000427   .433137  .000389  I  .2623834  .0000425  2.3613 0.0276  I    -1.690     .202     1.215     .181   .086000   .432000   .2624000      .000      .000  
+88 3 6 47226.00 I   .084978  .000381   .433274  .000360  I  .2600346  .0000343  2.3216 0.0291  I    -1.765     .202     1.079     .181   .088000   .432000   .2602000      .000      .000  
+88 3 7 47227.00 I   .087034  .000445   .433225  .000380  I  .2577686  .0000397  2.1965 0.0311  I    -1.843     .273      .932     .136   .090000   .432000   .2581000      .000      .000  
+88 3 8 47228.00 I   .089182  .000396   .432984  .000393  I  .2556665  .0000519  1.9967 0.0305  I    -1.821     .332      .760     .298   .092000   .432000   .2562000      .000      .000  
+88 3 9 47229.00 I   .091479  .000403   .432548  .000530  I  .2537920  .0000463  1.7463 0.0348  I    -1.631     .332      .521     .298   .095000   .432000   .2544000      .000      .000  
+88 310 47230.00 I   .093968  .000403   .431925  .000530  I  .2521810  .0000465  1.4744 0.0339  I    -1.299     .332      .274     .298   .097000   .432000   .2530000      .000      .000  
+88 311 47231.00 I   .096616  .000392   .431178  .000515  I  .2508327  .0000494  1.2339 0.0324  I    -1.074     .332      .205     .298   .100000   .431000   .2516000      .000      .000  
+88 312 47232.00 I   .099373  .000355   .430378  .000777  I  .2496800  .0000451  1.0930 0.0399  I    -1.146     .493      .257     .126   .102000   .431000   .2505000      .000      .000  
+88 313 47233.00 I   .102178  .000341   .429573  .000879  I  .2485988  .0000626  1.0957 0.0363  I    -1.442     .567      .181     .189   .104000   .430000   .2493000      .000      .000  
+88 314 47234.00 I   .104954  .000323   .428784  .000936  I  .2474383  .0000570  1.2492 0.0350  I    -1.670     .623     -.115     .206   .107000   .429000   .2480000      .000      .000  
+88 315 47235.00 I   .107628  .000353   .428032  .000676  I  .2460608  .0000315  1.5214 0.0340  I    -1.614     .623     -.447     .206   .109000   .428000   .2465000      .000      .000  
+88 316 47236.00 I   .110146  .000327   .427325  .000716  I  .2443810  .0000371  1.8370 0.0206  I    -1.494     .624     -.338     .183   .112000   .428000   .2446000      .000      .000  
+88 317 47237.00 I   .112463  .000294   .426598  .000938  I  .2424056  .0000266  2.0961 0.0245  I    -1.542     .532      .149     .256   .114000   .427000   .2424000      .000      .000  
+88 318 47238.00 I   .114535  .000312   .425771  .000979  I  .2402340  .0000321  2.2196 0.0259  I    -1.726     .404      .531     .292   .116000   .425000   .2401000      .000      .000  
+88 319 47239.00 I   .116348  .000272   .424764  .000925  I  .2380222  .0000444  2.1755 0.0280  I    -1.862     .366      .477     .296   .118000   .424000   .2378000      .000      .000  
+88 320 47240.00 I   .117957  .000272   .423510  .000925  I  .2359328  .0000459  1.9818 0.0383  I    -1.998     .366      .030     .296   .120000   .423000   .2356000      .000      .000  
+88 321 47241.00 I   .119427  .000182   .422058  .000900  I  .2340876  .0000625  1.7009 0.0393  I    -2.134     .366     -.358     .296   .122000   .422000   .2338000      .000      .000  
+88 322 47242.00 I   .120827  .000354   .420480  .000894  I  .2325317  .0000639  1.4177 0.0525  I    -2.077     .373     -.610     .260   .123000   .420000   .2322000      .000      .000  
+88 323 47243.00 I   .122229  .000460   .418839  .000703  I  .2312297  .0000843  1.2020 0.0545  I    -1.661     .427     -.857     .168   .125000   .419000   .2309000      .000      .000  
+88 324 47244.00 I   .123705  .000468   .417199  .000628  I  .2300952  .0000884  1.0838 0.0585  I    -1.017     .519    -1.026     .298   .126000   .418000   .2298000      .000      .000  
+88 325 47245.00 I   .125305  .000468   .415613  .000628  I  .2290276  .0000810  1.0692 0.0554  I     -.501     .519     -.986     .298   .128000   .417000   .2287000      .000      .000  
+88 326 47246.00 I   .126960  .000422   .414115  .000561  I  .2279249  .0000669  1.1502 0.0458  I     -.273     .519     -.762     .298   .129000   .415000   .2276000      .000      .000  
+88 327 47247.00 I   .128550  .000439   .412734  .000472  I  .2267026  .0000426  1.3049 0.0395  I     -.204     .403     -.548     .113   .130000   .414000   .2264000      .000      .000  
+88 328 47248.00 I   .129982  .000359   .411461  .000594  I  .2252995  .0000422  1.5065 0.0300  I     -.151     .237     -.456     .144   .131000   .413000   .2250000      .000      .000  
+88 329 47249.00 I   .131179  .000359   .410263  .000594  I  .2236844  .0000422  1.7238 0.0249  I     -.140     .237     -.392     .144   .132000   .412000   .2233000      .000      .000  
+88 330 47250.00 I   .132077  .000302   .409106  .000235  I  .2218552  .0000264  1.9314 0.0282  I     -.229     .237     -.239     .144   .133000   .410000   .2215000      .000      .000  
+88 331 47251.00 I   .132689  .000256   .407969  .000376  I  .2198328  .0000374  2.1055 0.0224  I     -.383     .256     -.046     .198   .134000   .409000   .2195000      .000      .000  
+88 4 1 47252.00 I   .133060  .000256   .406819  .000376  I  .2176635  .0000363  2.2217 0.0335  I     -.525     .256      .020     .198   .134000   .407000   .2173000      .000      .000  
+88 4 2 47253.00 I   .133242  .000153   .405621  .000461  I  .2154137  .0000557  2.2649 0.0337  I     -.657     .274     -.109     .240   .135000   .406000   .2151000      .000      .000  
+88 4 3 47254.00 I   .133291  .000329   .404331  .000421  I  .2131608  .0000569  2.2268 0.0397  I     -.822     .274     -.300     .240   .136000   .405000   .2128000      .000      .000  
+88 4 4 47255.00 I   .133276  .000329   .402927  .000421  I  .2109864  .0000567  2.1099 0.0375  I     -.987     .274     -.393     .240   .136000   .403000   .2107000      .000      .000  
+88 4 5 47256.00 I   .133296  .000464   .401435  .000411  I  .2089597  .0000488  1.9370 0.0309  I    -1.071     .274     -.373     .240   .137000   .402000   .2087000      .000      .000  
+88 4 6 47257.00 I   .133451  .000520   .399885  .000383  I  .2071178  .0000246  1.7478 0.0321  I    -1.048     .932     -.340     .153   .137000   .400000   .2069000      .000      .000  
+88 4 7 47258.00 I   .133796  .000630   .398302  .000215  I  .2054537  .0000416  1.5897 0.0219  I     -.947     .932     -.433     .153   .138000   .399000   .2052000      .000      .000  
+88 4 8 47259.00 I   .134366  .000630   .396706  .000215  I  .2039126  .0000363  1.5090 0.0281  I     -.807     .773     -.769     .207   .138000   .397000   .2037000      .000      .000  
+88 4 9 47260.00 I   .135164  .000719   .395107  .000284  I  .2023987  .0000379  1.5394 0.0240  I     -.636     .773    -1.421     .207   .139000   .396000   .2021000      .000      .000  
+88 410 47261.00 I   .136105  .000647   .393495  .000262  I  .2007934  .0000314  1.6909 0.0224  I     -.403     .773    -2.123     .207   .140000   .394000   .2005000      .000      .000  
+88 411 47262.00 I   .137096  .000495   .391851  .000211  I  .1989811  .0000237  1.9497 0.0216  I     -.055     .692    -2.436     .220   .141000   .392000   .1987000      .000      .000  
+88 412 47263.00 I   .138122  .000527   .390169  .000221  I  .1968751  .0000298  2.2652 0.0180  I      .346     .525    -2.302     .249   .142000   .391000   .1965000      .000      .000  
+88 413 47264.00 I   .139252  .000527   .388462  .000221  I  .1944597  .0000271  2.5536 0.0186  I      .616     .525    -1.924     .249   .143000   .389000   .1941000      .000      .000  
+88 414 47265.00 I   .140573  .000492   .386753  .000236  I  .1918060  .0000222  2.7278 0.0167  I      .594     .596    -1.606     .231   .144000   .388000   .1914000      .000      .000  
+88 415 47266.00 I   .142124  .000372   .385078  .000291  I  .1890631  .0000196  2.7249 0.0160  I      .456     .596    -1.322     .231   .146000   .386000   .1887000      .000      .000  
+88 416 47267.00 I   .143839  .000365   .383464  .000312  I  .1864171  .0000231  2.5391 0.0170  I      .301     .650    -1.090     .276   .147000   .385000   .1862000      .000      .000  
+88 417 47268.00 I   .145638  .000393   .381931  .000377  I  .1840284  .0000278  2.2227 0.0195  I      .038     .633     -.979     .265   .148000   .383000   .1838000      .000      .000  
+88 418 47269.00 I   .147446  .000417   .380503  .000512  I  .1819888  .0000313  1.8551 0.0280  I     -.402     .618     -.982     .277   .150000   .382000   .1818000      .000      .000  
+88 419 47270.00 I   .149227  .000475   .379205  .000571  I  .1803083  .0000485  1.5171 0.0265  I     -.975     .968    -1.118     .245   .151000   .381000   .1802000      .000      .000  
+88 420 47271.00 I   .150923  .000545   .378018  .000570  I  .1789243  .0000428  1.2698 0.0306  I    -1.409     .914    -1.409     .227   .153000   .379000   .1788000      .000      .000  
+88 421 47272.00 I   .152480  .000547   .376907  .000636  I  .1777309  .0000372  1.1358 0.0303  I    -1.415     .961    -1.748     .251   .154000   .378000   .1776000      .000      .000  
+88 422 47273.00 I   .153883  .000609   .375832  .000638  I  .1766178  .0000430  1.1066 0.0275  I     -.920    1.031    -1.979     .215   .156000   .377000   .1764000      .000      .000  
+88 423 47274.00 I   .155182  .000616   .374728  .000619  I  .1754892  .0000404  1.1630 0.0299  I     -.472    1.119    -2.042     .233   .157000   .374000   .1751000      .000      .000  
+88 424 47275.00 I   .156463  .000638   .373523  .000823  I  .1742706  .0000415  1.2832 0.0240  I     -.354    1.119    -2.148     .233   .159000   .373000   .1738000      .000      .000  
+88 425 47276.00 I   .157752  .000679   .372218  .000785  I  .1729094  .0000258  1.4437 0.0279  I     -.410     .961    -2.343     .278   .160000   .372000   .1724000      .000      .000  
+88 426 47277.00 I   .159044  .000677   .370851  .000735  I  .1713784  .0000374  1.6185 0.0341  I     -.513     .956    -2.398     .279   .162000   .370000   .1708000      .000      .000  
+88 427 47278.00 I   .160340  .000560   .369461  .000704  I  .1696762  .0000631  1.7819 0.0366  I     -.625     .893    -2.050     .275   .163000   .369000   .1690000      .000      .000  
+88 428 47279.00 I   .161671  .000560   .368081  .000704  I  .1678264  .0000630  1.9099 0.0441  I     -.626     .893    -1.265     .275   .165000   .368000   .1671000      .000      .000  
+88 429 47280.00 I   .163064  .000970   .366725  .000795  I  .1658776  .0000616  1.9742 0.0379  I     -.652     .893     -.638     .275   .166000   .367000   .1652000      .000      .000  
+88 430 47281.00 I   .164477  .000896   .365389  .000684  I  .1639065  .0000423  1.9529 0.0347  I     -.733     .803     -.478     .251   .167000   .366000   .1633000      .000      .000  
+88 5 1 47282.00 I   .165855  .000763   .364063  .000248  I  .1620006  .0000319  1.8453 0.0238  I     -.802     .638     -.687     .185   .169000   .364000   .1614000      .000      .000  
+88 5 2 47283.00 I   .167147  .000720   .362735  .000456  I  .1602385  .0000217  1.6698 0.0190  I     -.839     .277    -1.071     .298   .170000   .363000   .1597000      .000      .000  
+88 5 3 47284.00 I   .168285  .000780   .361394  .000499  I  .1586712  .0000208  1.4637 0.0156  I     -.812     .277    -1.447     .298   .171000   .363000   .1582000      .000      .000  
+88 5 4 47285.00 I   .169162  .000780   .360021  .000499  I  .1573034  .0000225  1.2808 0.0139  I     -.632     .277    -1.624     .298   .172000   .362000   .1569000      .000      .000  
+88 5 5 47286.00 I   .169788  .000744   .358587  .000447  I  .1560843  .0000184  1.1737 0.0150  I     -.298     .277    -1.616     .298   .173000   .360000   .1557000      .000      .000  
+88 5 6 47287.00 I   .170224  .000606   .357071  .000419  I  .1549187  .0000198  1.1786 0.0163  I      .129     .287    -1.546     .152   .173000   .359000   .1545000      .000      .000  
+88 5 7 47288.00 I   .170572  .000664   .355490  .000540  I  .1536860  .0000270  1.3070 0.0163  I      .572     .247    -1.493     .193   .174000   .357000   .1533000      .000      .000  
+88 5 8 47289.00 I   .170939  .000693   .353873  .000207  I  .1522705  .0000260  1.5380 0.0198  I      .911     .247    -1.503     .193   .174000   .355000   .1519000      .000      .000  
+88 5 9 47290.00 I   .171422  .000657   .352246  .000264  I  .1505918  .0000290  1.8235 0.0177  I     1.015     .247    -1.596     .193   .175000   .354000   .1502000      .000      .000  
+88 510 47291.00 I   .172031  .000687   .350624  .000235  I  .1486276  .0000240  2.0966 0.0195  I      .865     .247    -1.710     .193   .176000   .352000   .1482000      .000      .000  
+88 511 47292.00 I   .172740  .000669   .349018  .000241  I  .1464257  .0000261  2.2882 0.0204  I      .517     .436    -1.748     .395   .176000   .351000   .1460000      .000      .000  
+88 512 47293.00 I   .173522  .000650   .347441  .000264  I  .1440946  .0000331  2.3494 0.0214  I      .070     .565    -1.642     .524   .177000   .349000   .1436000      .000      .000  
+88 513 47294.00 I   .174315  .000650   .345886  .000264  I  .1417745  .0000340  2.2678 0.0231  I     -.326     .565    -1.402     .524   .177000   .347000   .1413000      .000      .000  
+88 514 47295.00 I   .175061  .000752   .344342  .000698  I  .1396002  .0000323  2.0625 0.0223  I     -.508     .565    -1.109     .524   .178000   .346000   .1392000      .000      .000  
+88 515 47296.00 I   .175731  .000747   .342790  .000758  I  .1376748  .0000288  1.7813 0.0256  I     -.454     .519     -.913     .457   .178000   .344000   .1373000      .000      .000  
+88 516 47297.00 I   .176269  .000713   .341207  .000751  I  .1360396  .0000397  1.4942 0.0332  I     -.221     .840     -.918     .494   .178000   .342000   .1357000      .000      .000  
+88 517 47298.00 I   .176616  .000673   .339565  .000879  I  .1346682  .0000599  1.2617 0.0355  I      .118     .916    -1.132     .419   .179000   .340000   .1345000      .000      .000  
+88 518 47299.00 I   .176737  .000673   .337839  .000879  I  .1334901  .0000588  1.1076 0.0383  I      .454     .916    -1.465     .419   .179000   .339000   .1333000      .000      .000  
+88 519 47300.00 I   .176689  .000655   .336003  .000699  I  .1324249  .0000479  1.0378 0.0381  I      .772     .912    -1.567     .354   .179000   .337000   .1323000      .000      .000  
+88 520 47301.00 I   .176571  .000516   .334072  .000661  I  .1313853  .0000486  1.0554 0.0369  I      .863     .866    -1.530     .333   .179000   .335000   .1313000      .000      .000  
+88 521 47302.00 I   .176472  .000520   .332078  .000387  I  .1302903  .0000561  1.1443 0.0418  I      .630     .918    -1.513     .346   .179000   .333000   .1301000      .000      .000  
+88 522 47303.00 I   .176453  .000528   .330055  .000270  I  .1290823  .0000680  1.2764 0.0426  I      .237     .764    -1.614     .158   .179000   .331000   .1288000      .000      .000  
+88 523 47304.00 I   .176504  .000574   .328048  .000290  I  .1277310  .0000640  1.4281 0.0479  I     -.041     .794    -1.736     .166   .178000   .330000   .1274000      .000      .000  
+88 524 47305.00 I   .176508  .000623   .326097  .000277  I  .1262273  .0000674  1.5763 0.0485  I     -.139     .794    -1.718     .166   .178000   .328000   .1258000      .000      .000  
+88 525 47306.00 I   .176371  .000534   .324224  .000256  I  .1245896  .0000730  1.6911 0.0537  I     -.219     .491    -1.497     .126   .177000   .326000   .1241000      .000      .000  
+88 526 47307.00 I   .176036  .000463   .322405  .000337  I  .1228631  .0000837  1.7521 0.0533  I     -.421     .910    -1.172     .334   .177000   .324000   .1224000      .000      .000  
+88 527 47308.00 I   .175458  .000428   .320609  .000291  I  .1211064  .0000776  1.7503 0.0554  I     -.728     .910     -.940     .334   .176000   .323000   .1206000      .000      .000  
+88 528 47309.00 I   .174650  .000460   .318806  .000395  I  .1193840  .0000726  1.6842 0.0528  I     -.988     .910     -.921     .334   .176000   .321000   .1189000      .000      .000  
+88 529 47310.00 I   .173647  .000460   .316974  .000395  I  .1177611  .0000715  1.5488 0.0458  I    -1.079     .910    -1.093     .334   .175000   .319000   .1174000      .000      .000  
+88 530 47311.00 I   .172508  .000183   .315109  .000348  I  .1163064  .0000560  1.3535 0.0425  I    -1.045     .910    -1.351     .334   .174000   .317000   .1161000      .000      .000  
+88 531 47312.00 I   .171313  .000234   .313217  .000290  I  .1150594  .0000458  1.1422 0.0365  I    -1.024     .693    -1.623     .240   .174000   .315000   .1149000      .000      .000  
+88 6 1 47313.00 I   .170143  .000299   .311304  .000159  I  .1140094  .0000467  0.9687 0.0321  I    -1.092     .363    -1.871     .298   .173000   .313000   .1140000      .000      .000  
+88 6 2 47314.00 I   .169074  .000282   .309379  .000156  I  .1130943  .0000450  0.8781 0.0357  I    -1.225     .363    -2.034     .298   .172000   .311000   .1132000      .000      .000  
+88 6 3 47315.00 I   .168160  .000354   .307456  .000407  I  .1122126  .0000541  0.9091 0.0316  I    -1.407     .562    -2.049     .298   .171000   .309000   .1122000      .000      .000  
+88 6 4 47316.00 I   .167385  .000327   .305554  .000430  I  .1112338  .0000445  1.0669 0.0340  I    -1.579     .562    -1.964     .298   .170000   .307000   .1112000      .000      .000  
+88 6 5 47317.00 I   .166735  .000302   .303687  .000433  I  .1100538  .0000413  1.2998 0.0336  I    -1.653     .569    -1.895     .253   .170000   .304000   .1099000      .000      .000  
+88 6 6 47318.00 I   .166213  .000328   .301859  .000543  I  .1086331  .0000504  1.5361 0.0328  I    -1.499     .674    -1.945     .327   .169000   .302000   .1083000      .000      .000  
+88 6 7 47319.00 I   .165809  .000367   .300064  .000534  I  .1070061  .0000509  1.6988 0.0354  I    -1.232     .674    -2.061     .327   .168000   .300000   .1066000      .000      .000  
+88 6 8 47320.00 I   .165500  .000367   .298286  .000534  I  .1052785  .0000496  1.7326 0.0361  I    -1.091     .674    -2.097     .327   .168000   .298000   .1048000      .000      .000  
+88 6 9 47321.00 I   .165260  .000349   .296515  .000518  I  .1035866  .0000513  1.6294 0.0296  I    -1.117     .580    -1.979     .385   .168000   .296000   .1030000      .000      .000  
+88 610 47322.00 I   .165075  .000321   .294741  .000302  I  .1020572  .0000324  1.4138 0.0306  I    -1.291     .445    -1.717     .317   .168000   .294000   .1015000      .000      .000  
+88 611 47323.00 I   .164939  .000373   .292954  .000149  I  .1007806  .0000335  1.1335 0.0237  I    -1.580     .244    -1.402     .229   .167000   .292000   .1002000      .000      .000  
+88 612 47324.00 I   .164891  .000373   .291145  .000149  I  .0997917  .0000346  0.8486 0.0238  I    -1.849     .244    -1.181     .229   .167000   .290000   .0992000      .000      .000  
+88 613 47325.00 I   .164964  .000333   .289308  .000248  I  .0990674  .0000338  0.6115 0.0249  I    -1.906     .244    -1.144     .229   .167000   .289000   .0985000      .000      .000  
+88 614 47326.00 I   .165103  .000555   .287445  .000282  I  .0985414  .0000359  0.4562 0.0201  I    -1.707     .244    -1.243     .229   .167000   .287000   .0980000      .000      .000  
+88 615 47327.00 I   .165220  .000729   .285551  .000340  I  .0981234  .0000216  0.3958 0.0212  I    -1.391     .361    -1.326     .270   .167000   .285000   .0976000      .000      .000  
+88 616 47328.00 I   .165235  .000926   .283612  .000331  I  .0977212  .0000226  0.4214 0.0182  I    -1.161     .420    -1.263     .257   .167000   .283000   .0973000      .000      .000  
+88 617 47329.00 I   .165078  .000930   .281610  .000350  I  .0972599  .0000292  0.5092 0.0200  I    -1.154     .365    -1.080     .229   .168000   .281000   .0969000      .000      .000  
+88 618 47330.00 I   .164740  .000922   .279509  .000347  I  .0966944  .0000331  0.6222 0.0228  I    -1.407     .365     -.964     .229   .168000   .279000   .0964000      .000      .000  
+88 619 47331.00 I   .164408  .000907   .277292  .000332  I  .0960175  .0000349  0.7293 0.0233  I    -1.763     .358    -1.049     .239   .168000   .277000   .0957000      .000      .000  
+88 620 47332.00 I   .164308  .000884   .274976  .000482  I  .0952407  .0000327  0.8219 0.0256  I    -2.111     .339    -1.318     .230   .168000   .275000   .0950000      .000      .000  
+88 621 47333.00 I   .164459  .000734   .272627  .000514  I  .0943817  .0000374  0.8907 0.0250  I    -2.451     .298    -1.542     .172   .169000   .273000   .0941000      .000      .000  
+88 622 47334.00 I   .164844  .000688   .270336  .000546  I  .0934727  .0000378  0.9194 0.0370  I    -2.872     .286    -1.467     .187   .169000   .271000   .0932000      .000      .000  
+88 623 47335.00 I   .165440  .000701   .268181  .000789  I  .0925620  .0000639  0.8907 0.0319  I    -3.436     .319    -1.377     .205   .169000   .269000   .0922000      .000      .000  
+88 624 47336.00 I   .166198  .000737   .266171  .000731  I  .0917134  .0000514  0.7955 0.0389  I    -4.059     .287    -1.476     .204   .170000   .267000   .0914000      .000      .000  
+88 625 47337.00 I   .167033  .000712   .264291  .000713  I  .0909916  .0000444  0.6385 0.0345  I    -4.558     .557    -1.672     .383   .170000   .265000   .0907000      .000      .000  
+88 626 47338.00 I   .167857  .000651   .262495  .000607  I  .0904523  .0000460  0.4338 0.0324  I    -4.718     .653    -1.735     .451   .170000   .263000   .0901000      .000      .000  
+88 627 47339.00 I   .168577  .000678   .260716  .000646  I  .0901316  .0000472  0.2064 0.0334  I    -4.521     .721    -1.491     .513   .171000   .261000   .0898000      .000      .000  
+88 628 47340.00 I   .169078  .000689   .258899  .000503  I  .0900288  .0000484  0.0110 0.0297  I    -4.186     .721    -1.094     .513   .171000   .259000   .0897000      .000      .000  
+88 629 47341.00 I   .169346  .000636   .257053  .000469  I  .0900763  .0000362 -0.0845 0.0266  I    -3.914     .721     -.826     .513   .171000   .257000   .0897000      .000      .000  
+88 630 47342.00 I   .169407  .000506   .255191  .000473  I  .0901508  .0000220 -0.0390 0.0449  I    -3.730    1.137     -.750     .449   .171000   .255000   .0897000      .000      .000  
+88 7 1 47343.00 I   .169293  .000985   .253312  .000510  I  .0901073  .0000822  0.1477 0.0421  I    -3.662    1.285     -.827     .305   .171000   .253000   .0897000      .000      .000  
+88 7 2 47344.00 I   .169043  .001107   .251413  .000604  I  .0898241  .0000812  0.4284 0.0603  I    -3.921    1.120    -1.103     .346   .171000   .251000   .0893000      .000      .000  
+88 7 3 47345.00 I   .168718  .001428   .249492  .000600  I  .0892455  .0000882  0.7239 0.0564  I    -4.717    1.067    -1.679     .332   .171000   .249000   .0887000      .000      .000  
+88 7 4 47346.00 I   .168392  .001353   .247551  .000649  I  .0883989  .0000784  0.9514 0.0590  I    -5.741    1.011    -2.148     .343   .171000   .247000   .0878000      .000      .000  
+88 7 5 47347.00 I   .168128  .001305   .245587  .000619  I  .0873872  .0000785  1.0454 0.0565  I    -6.628     .946    -2.040     .362   .171000   .246000   .0868000      .000      .000  
+88 7 6 47348.00 I   .167947  .001442   .243581  .000613  I  .0863579  .0000815  0.9901 0.0558  I    -7.024     .717    -1.525     .363   .171000   .244000   .0858000      .000      .000  
+88 7 7 47349.00 I   .167849  .001346   .241539  .000564  I  .0854474  .0000793  0.8136 0.0522  I    -7.052     .717     -.787     .363   .170000   .242000   .0849000      .000      .000  
+88 7 8 47350.00 I   .167747  .001246   .239484  .000563  I  .0847557  .0000653  0.5619 0.0497  I    -6.886     .768     -.459     .332   .170000   .240000   .0842000      .000      .000  
+88 7 9 47351.00 I   .167560  .001227   .237432  .000427  I  .0843280  .0000598  0.2968 0.0437  I    -6.928     .758     -.619     .343   .169000   .239000   .0838000      .000      .000  
+88 710 47352.00 I   .167240  .001103   .235399  .000458  I  .0841458  .0000581  0.0804 0.0441  I    -7.301    1.191     -.988     .331   .169000   .237000   .0836000      .000      .000  
+88 711 47353.00 I   .166830  .001311   .233390  .000572  I  .0841389  .0000649 -0.0513 0.0442  I    -7.643    1.252    -1.347     .259   .169000   .235000   .0837000      .000      .000  
+88 712 47354.00 I   .166361  .001311   .231408  .000572  I  .0842164  .0000667 -0.0872 0.0476  I    -7.765    1.201    -1.655     .291   .168000   .233000   .0838000      .000      .000  
+88 713 47355.00 I   .165858  .001700   .229461  .000641  I  .0842809  .0000696 -0.0259 0.0453  I    -7.874    1.201    -2.100     .291   .168000   .231000   .0838000      .000      .000  
+88 714 47356.00 I   .165381  .001451   .227575  .000443  I  .0842424  .0000612  0.1127 0.0477  I    -7.869    1.295    -2.410     .296   .167000   .229000   .0838000      .000      .000  
+88 715 47357.00 I   .164937  .001472   .225745  .000434  I  .0840428  .0000652  0.2895 0.0510  I    -7.635     .995    -2.093     .264   .167000   .228000   .0837000      .000      .000  
+88 716 47358.00 I   .164436  .001581   .223927  .000403  I  .0836617  .0000815  0.4713 0.0503  I    -7.327     .406    -1.325     .224   .166000   .226000   .0833000      .000      .000  
+88 717 47359.00 I   .163829  .001510   .222063  .000382  I  .0831075  .0000767  0.6313 0.0574  I    -7.175     .361     -.574     .240   .165000   .223000   .0828000      .000      .000  
+88 718 47360.00 I   .163209  .001322   .220095  .000282  I  .0824115  .0000808  0.7541 0.0549  I    -7.375     .287     -.135     .215   .165000   .221000   .0821000      .000      .000  
+88 719 47361.00 I   .162581  .000835   .218034  .000323  I  .0816152  .0000785  0.8291 0.0543  I    -7.818     .287      .132     .215   .164000   .219000   .0813000      .000      .000  
+88 720 47362.00 I   .161910  .000803   .215909  .000364  I  .0807731  .0000727  0.8447 0.0565  I    -8.289     .535      .326     .198   .163000   .217000   .0804000      .000      .000  
+88 721 47363.00 I   .161156  .000470   .213768  .000522  I  .0799456  .0000813  0.8010 0.0445  I    -8.751     .648      .346     .156   .162000   .215000   .0796000      .000      .000  
+88 722 47364.00 I   .160277  .000407   .211659  .000525  I  .0791869  .0000512  0.7101 0.0482  I    -9.220     .756     -.010     .158   .161000   .213000   .0788000      .000      .000  
+88 723 47365.00 I   .159233  .000391   .209618  .000558  I  .0785392  .0000518  0.5780 0.0320  I    -9.503     .756     -.741     .158   .160000   .211000   .0782000      .000      .000  
+88 724 47366.00 I   .158046  .000376   .207629  .000550  I  .0780408  .0000384  0.4164 0.0311  I    -9.535     .737    -1.369     .150   .159000   .209000   .0777000      .000      .000  
+88 725 47367.00 I   .156759  .000574   .205662  .000508  I  .0777049  .0000345  0.2594 0.0260  I    -9.456     .664    -1.491     .181   .158000   .207000   .0775000      .000      .000  
+88 726 47368.00 I   .155411  .000676   .203688  .000440  I  .0775034  .0000350  0.1583 0.0259  I    -9.497     .573    -1.227     .180   .156000   .205000   .0773000      .000      .000  
+88 727 47369.00 I   .154067  .000863   .201711  .000446  I  .0773500  .0000386  0.1722 0.0249  I    -9.521     .573    -1.108     .183   .155000   .203000   .0772000      .000      .000  
+88 728 47370.00 I   .152797  .000800   .199746  .000353  I  .0771104  .0000353  0.3318 0.0249  I    -9.421     .434    -1.333     .186   .154000   .201000   .0770000      .000      .000  
+88 729 47371.00 I   .151642  .000799   .197803  .000302  I  .0766462  .0000316  0.6119 0.0235  I    -9.136     .426    -1.485     .171   .153000   .199000   .0765000      .000      .000  
+88 730 47372.00 I   .150613  .000796   .195889  .000297  I  .0758730  .0000311  0.9329 0.0226  I    -8.803     .403    -1.305     .237   .152000   .198000   .0758000      .000      .000  
+88 731 47373.00 I   .149680  .000827   .193991  .000295  I  .0748029  .0000323  1.1863 0.0230  I    -8.733     .389    -1.059     .237   .150000   .196000   .0747000      .000      .000  
+88 8 1 47374.00 I   .148737  .000793   .192093  .000331  I  .0735477  .0000340  1.2976 0.0234  I    -9.075     .412    -1.083     .251   .149000   .194000   .0734000      .000      .000  
+88 8 2 47375.00 I   .147679  .000728   .190193  .000371  I  .0722613  .0000340  1.2481 0.0231  I    -9.672     .435    -1.442     .280   .148000   .192000   .0720000      .000      .000  
+88 8 3 47376.00 I   .146460  .000547   .188283  .000349  I  .0710986  .0000312  1.0573 0.0234  I   -10.262     .435    -1.842     .280   .147000   .190000   .0708000      .000      .000  
+88 8 4 47377.00 I   .145064  .000496   .186359  .000300  I  .0701735  .0000323  0.7861 0.0261  I   -10.662     .408    -1.939     .289   .145000   .188000   .0698000      .000      .000  
+88 8 5 47378.00 I   .143549  .000560   .184427  .000314  I  .0695288  .0000419  0.5076 0.0272  I   -10.747     .307    -1.632     .250   .144000   .185000   .0691000      .000      .000  
+88 8 6 47379.00 I   .141975  .000560   .182503  .000314  I  .0691416  .0000437  0.2791 0.0300  I   -10.588     .307    -1.303     .250   .142000   .184000   .0687000      .000      .000  
+88 8 7 47380.00 I   .140372  .000436   .180588  .000328  I  .0689507  .0000429  0.1104 0.0296  I   -10.368     .307    -1.330     .250   .141000   .182000   .0686000      .000      .000  
+88 8 8 47381.00 I   .138711  .000431   .178690  .000273  I  .0688957  .0000398  0.0171 0.0282  I   -10.192     .266    -1.527     .224   .140000   .180000   .0685000      .000      .000  
+88 8 9 47382.00 I   .137032  .000510   .176831  .000240  I  .0688826  .0000367  0.0254 0.0281  I   -10.022     .207    -1.683     .181   .138000   .178000   .0685000      .000      .000  
+88 810 47383.00 I   .135399  .000487   .175036  .000267  I  .0688161  .0000397  0.1202 0.0225  I    -9.794     .791    -1.786     .114   .137000   .177000   .0684000      .000      .000  
+88 811 47384.00 I   .133883  .000583   .173345  .000378  I  .0686211  .0000260  0.2784 0.0219  I    -9.552     .791    -1.731     .298   .135000   .175000   .0682000      .000      .000  
+88 812 47385.00 I   .132534  .000583   .171798  .000378  I  .0682485  .0000186  0.4691 0.0159  I    -9.397     .791    -1.403     .298   .134000   .174000   .0678000      .000      .000  
+88 813 47386.00 I   .131275  .000616   .170397  .000308  I  .0676839  .0000182  0.6568 0.0143  I    -9.376     .791     -.883     .298   .132000   .172000   .0672000      .000      .000  
+88 814 47387.00 I   .130008  .000563   .169109  .000296  I  .0669456  .0000218  0.8123 0.0178  I    -9.491     .258     -.448     .298   .131000   .171000   .0665000      .000      .000  
+88 815 47388.00 I   .128643  .000470   .167903  .000138  I  .0660771  .0000306  0.9144 0.0198  I    -9.720     .362     -.316     .298   .129000   .169000   .0656000      .000      .000  
+88 816 47389.00 I   .127093  .000445   .166742  .000234  I  .0651379  .0000331  0.9534 0.0211  I    -9.971     .362     -.437     .298   .127000   .168000   .0647000      .000      .000  
+88 817 47390.00 I   .125331  .000445   .165595  .000234  I  .0641926  .0000291  0.9257 0.0231  I   -10.123     .362     -.604     .298   .125000   .167000   .0637000      .000      .000  
+88 818 47391.00 I   .123406  .000449   .164434  .000206  I  .0633086  .0000322  0.8318 0.0199  I   -10.205     .362     -.747     .298   .124000   .165000   .0629000      .000      .000  
+88 819 47392.00 I   .121374  .000301   .163241  .000187  I  .0625467  .0000272  0.6847 0.0214  I   -10.397     .370     -.966     .298   .122000   .164000   .0622000      .000      .000  
+88 820 47393.00 I   .119274  .000339   .162008  .000195  I  .0619491  .0000282  0.5079 0.0194  I   -10.766     .378    -1.291     .298   .120000   .163000   .0616000      .000      .000  
+88 821 47394.00 I   .117135  .000339   .160741  .000195  I  .0615310  .0000276  0.3307 0.0192  I   -11.131     .378    -1.542     .298   .118000   .161000   .0612000      .000      .000  
+88 822 47395.00 I   .114975  .000367   .159443  .000170  I  .0612741  .0000261  0.1943 0.0183  I   -11.277     .378    -1.537     .298   .116000   .160000   .0610000      .000      .000  
+88 823 47396.00 I   .112786  .000331   .158136  .000160  I  .0611109  .0000241  0.1523 0.0148  I   -11.185     .378    -1.335     .298   .114000   .159000   .0608000      .000      .000  
+88 824 47397.00 I   .110555  .000400   .156842  .000173  I  .0609245  .0000141  0.2452 0.0170  I   -10.990     .447    -1.151     .298   .112000   .158000   .0606000      .000      .000  
+88 825 47398.00 I   .108275  .000463   .155581  .000218  I  .0605739  .0000241  0.4778 0.0138  I   -10.810     .506    -1.050     .298   .110000   .156000   .0602000      .000      .000  
+88 826 47399.00 I   .105966  .000463   .154361  .000218  I  .0599372  .0000238  0.8056 0.0206  I   -10.733     .506     -.886     .298   .108000   .155000   .0595000      .000      .000  
+88 827 47400.00 I   .103668  .000451   .153183  .000226  I  .0589596  .0000335  1.1429 0.0241  I   -10.846     .506     -.589     .298   .105000   .154000   .0584000      .000      .000  
+88 828 47401.00 I   .101413  .000389   .152048  .000191  I  .0576822  .0000418  1.3879 0.0275  I   -11.141     .506     -.362     .298   .103000   .153000   .0570000      .000      .000  
+88 829 47402.00 I   .099179  .000357   .150947  .000223  I  .0562406  .0000435  1.4625 0.0392  I   -11.436     .358     -.409     .190   .101000   .152000   .0555000      .000      .000  
+88 830 47403.00 I   .096931  .000236   .149870  .000259  I  .0548202  .0000664  1.3483 0.0409  I   -11.607     .148     -.636     .252   .099000   .151000   .0540000      .000      .000  
+88 831 47404.00 I   .094639  .000313   .148808  .000364  I  .0535890  .0000692  1.0993 0.0478  I   -11.795     .148     -.832     .252   .097000   .150000   .0527000      .000      .000  
+88 9 1 47405.00 I   .092289  .000313   .147762  .000364  I  .0526372  .0000687  0.8036 0.0467  I   -12.200     .148    -1.020     .252   .094000   .149000   .0517000      .000      .000  
+88 9 2 47406.00 I   .089921  .000285   .146743  .000373  I  .0519722  .0000626  0.5368 0.0435  I   -12.762     .148    -1.204     .252   .092000   .148000   .0511000      .000      .000  
+88 9 3 47407.00 I   .087577  .000295   .145762  .000537  I  .0515357  .0000535  0.3539 0.0453  I   -13.165     .270    -1.448     .202   .090000   .147000   .0507000      .000      .000  
+88 9 4 47408.00 I   .085267  .000307   .144806  .000638  I  .0512297  .0000654  0.2751 0.0377  I   -13.239     .349    -1.700     .147   .088000   .146000   .0504000      .000      .000  
+88 9 5 47409.00 I   .082984  .000318   .143851  .000673  I  .0509546  .0000532  0.2888 0.0396  I   -13.053     .384    -1.797     .298   .086000   .145000   .0503000      .000      .000  
+88 9 6 47410.00 I   .080727  .000257   .142877  .000594  I  .0506274  .0000448  0.3765 0.0321  I   -12.622     .384    -1.765     .298   .083000   .144000   .0501000      .000      .000  
+88 9 7 47411.00 I   .078490  .000226   .141894  .000541  I  .0501843  .0000359  0.5162 0.0403  I   -11.938     .350    -1.708     .126   .081000   .143000   .0497000      .000      .000  
+88 9 8 47412.00 I   .076267  .000314   .140924  .000476  I  .0495867  .0000669  0.6809 0.0425  I   -11.080     .279    -1.588     .124   .079000   .142000   .0492000      .000      .000  
+88 9 9 47413.00 I   .074057  .000347   .139990  .000165  I  .0488225  .0000770  0.8455 0.0510  I   -10.257     .175    -1.228     .141   .076000   .141000   .0485000      .000      .000  
+88 910 47414.00 I   .071886  .000347   .139112  .000165  I  .0479034  .0000769  0.9870 0.0555  I    -9.698     .175     -.574     .141   .074000   .141000   .0476000      .000      .000  
+88 911 47415.00 I   .069777  .000347   .138302  .000165  I  .0468630  .0000800  1.0852 0.0515  I    -9.448     .175     -.053     .141   .071000   .140000   .0466000      .000      .000  
+88 912 47416.00 I   .067686  .000406   .137557  .000256  I  .0457511  .0000686  1.1293 0.0509  I    -9.473     .175      .009     .141   .069000   .139000   .0454000      .000      .000  
+88 913 47417.00 I   .065546  .000372   .136864  .000241  I  .0446227  .0000631  1.1185 0.0538  I    -9.709     .115     -.336     .298   .067000   .138000   .0442000      .000      .000  
+88 914 47418.00 I   .063293  .000339   .136209  .000241  I  .0435312  .0000830  1.0565 0.0354  I   -10.030     .121     -.813     .298   .064000   .138000   .0431000      .000      .000  
+88 915 47419.00 I   .060869  .000350   .135577  .000369  I  .0425233  .0000321  0.9537 0.0447  I   -10.321     .121    -1.176     .298   .062000   .137000   .0420000      .000      .000  
+88 916 47420.00 I   .058265  .000350   .134961  .000369  I  .0416315  .0000331  0.8277 0.0219  I   -10.584     .180    -1.381     .298   .059000   .136000   .0411000      .000      .000  
+88 917 47421.00 I   .055502  .000347   .134348  .000426  I  .0408676  .0000298  0.7025 0.0216  I   -10.851     .180    -1.522     .298   .056000   .136000   .0404000      .000      .000  
+88 918 47422.00 I   .052603  .000157   .133723  .000395  I  .0402159  .0000277  0.6092 0.0225  I   -11.036     .516    -1.624     .298   .053000   .135000   .0397000      .000      .000  
+88 919 47423.00 I   .049581  .000191   .133086  .000425  I  .0396256  .0000337  0.5867 0.0235  I   -10.958     .663    -1.642     .109   .050000   .135000   .0392000      .000      .000  
+88 920 47424.00 I   .046436  .000206   .132471  .000460  I  .0390073  .0000379  0.6697 0.0259  I   -10.562     .663    -1.580     .109   .047000   .134000   .0386000      .000      .000  
+88 921 47425.00 I   .043170  .000204   .131913  .000466  I  .0382443  .0000394  0.8783 0.0339  I    -9.966     .663    -1.506     .109   .044000   .134000   .0379000      .000      .000  
+88 922 47426.00 I   .039824  .000210   .131419  .000386  I  .0372149  .0000563  1.1943 0.0326  I    -9.532     .747    -1.382     .122   .041000   .133000   .0369000      .000      .000  
+88 923 47427.00 I   .036435  .000336   .130977  .000351  I  .0358406  .0000519  1.5556 0.0417  I    -9.523     .717    -1.096     .118   .037000   .133000   .0355000      .000      .000  
+88 924 47428.00 I   .033043  .000377   .130578  .000317  I  .0341172  .0000616  1.8766 0.0412  I    -9.996     .668     -.668     .298   .034000   .133000   .0338000      .000      .000  
+88 925 47429.00 I   .029697  .000425   .130234  .000333  I  .0321301  .0000641  2.0697 0.0433  I   -10.757     .669     -.330     .112   .031000   .132000   .0318000      .000      .000  
+88 926 47430.00 I   .026438  .000519   .129962  .000468  I  .0300408  .0000608  2.0737 0.0407  I   -11.373     .669     -.294     .112   .027000   .132000   .0297000      .000      .000  
+88 927 47431.00 I   .023217  .000537   .129768  .000556  I  .0280465  .0000503  1.8862 0.0314  I   -11.611     .669     -.456     .112   .024000   .132000   .0277000      .000      .000  
+88 928 47432.00 I   .019958  .000480   .129647  .000563  I  .0263097  .0000161  1.5747 0.0373  I   -11.680     .769     -.521     .179   .021000   .132000   .0260000      .000      .000  
+88 929 47433.00 I   .016604  .000523   .129578  .000643  I  .0249050  .0000552  1.2396 0.0306  I   -11.885     .858     -.427     .227   .018000   .132000   .0245000      .000      .000  
+88 930 47434.00 I   .013117  .000549   .129525  .000669  I  .0238086  .0000590  0.9702 0.0402  I   -12.136     .858     -.450     .227   .014000   .132000   .0234000      .000      .000  
+8810 1 47435.00 I   .009537  .000549   .129435  .000669  I  .0229268  .0000584  0.8144 0.0391  I   -12.027     .858     -.829     .227   .011000   .132000   .0225000      .000      .000  
+8810 2 47436.00 I   .005981  .000476   .129326  .000550  I  .0221395  .0000512  0.7797 0.0380  I   -11.425     .858    -1.362     .227   .008000   .132000   .0216000      .000      .000  
+8810 3 47437.00 I   .002559  .000523   .129250  .000548  I  .0213314  .0000486  0.8529 0.0417  I   -10.659     .843    -1.612     .271   .005000   .132000   .0207000      .000      .000  
+8810 4 47438.00 I  -.000668  .000851   .129269  .000668  I  .0204069  .0000659  1.0064 0.0308  I   -10.096     .684    -1.346     .396   .002000   .132000   .0198000      .000      .000  
+8810 5 47439.00 I  -.003644  .000847   .129446  .000731  I  .0193018  .0000377  1.2103 0.0365  I    -9.802     .684     -.615     .396  -.001600   .132100   .0186300      .000      .000  
+8810 6 47440.00 I  -.006348  .000833   .129831  .000796  I  .0179812  .0000315  1.4296 0.0233  I    -9.680     .684      .472     .396  -.004800   .132500   .0172900      .000      .000  
+8810 7 47441.00 I  -.008941  .000775   .130419  .000736  I  .0164502  .0000273  1.6262 0.0207  I    -9.673     .684     1.342     .396  -.008000   .133000   .0157700      .000      .000  
+8810 8 47442.00 I  -.011635  .000721   .131184  .000732  I  .0147438  .0000269  1.7779 0.0199  I    -9.803     .533     1.470     .322  -.011200   .133500   .0141000      .000      .000  
+8810 9 47443.00 I  -.014534  .000788   .132069  .000819  I  .0129147  .0000290  1.8687 0.0196  I   -10.097     .112     1.079     .331  -.014400   .134100   .0123300      .000      .000  
+881010 47444.00 I  -.017668  .000788   .132983  .000819  I  .0110303  .0000285  1.8879 0.0197  I   -10.541     .116      .424     .166  -.017600   .134700   .0105200      .000      .000  
+881011 47445.00 I  -.021041  .000312   .133834  .000641  I  .0091639  .0000266  1.8320 0.0208  I   -11.122     .116     -.145     .166  -.020800   .135300   .0087500      .000      .000  
+881012 47446.00 I  -.024606  .000361   .134593  .000628  I  .0073898  .0000304  1.7055 0.0215  I   -11.735     .116     -.439     .166  -.024000   .136000   .0070800      .000      .000  
+881013 47447.00 I  -.028288  .000335   .135265  .000533  I  .0057691  .0000339  1.5302 0.0319  I   -12.164     .835     -.406     .729  -.027200   .136700   .0055600      .000      .000  
+881014 47448.00 I  -.031998  .000399   .135860  .000433  I  .0043350  .0000561  1.3380 0.0338  I   -12.223    1.176     -.145    1.017  -.030400   .137400   .0042200      .000      .000  
+881015 47449.00 I  -.035649  .000462   .136389  .000483  I  .0030862  .0000584  1.1663 0.0326  I   -11.874    1.176      .093    1.017  -.033600   .138100   .0030300      .000      .000  
+881016 47450.00 I  -.039166  .000550   .136885  .000671  I  .0019811  .0000331  1.0584 0.0332  I   -11.175    1.176      .064    1.017  -.036800   .138800   .0019600      .000      .000  
+881017 47451.00 I  -.042495  .000600   .137399  .000829  I  .0009354  .0000318  1.0526 0.0234  I   -10.311    1.215     -.235     .856  -.039900   .139500   .0009200      .000      .000  
+881018 47452.00 I  -.045595  .000713   .137986  .001057  I -.0001641  .0000332  1.1669 0.0213  I    -9.469    1.150     -.659     .720  -.043000   .140300  -.0002100      .000      .000  
+881019 47453.00 I  -.048446  .000713   .138691  .001104  I -.0014361  .0000282  1.3942 0.0233  I    -8.822    1.125    -1.050     .298  -.046100   .141100  -.0015300      .000      .000  
+881020 47454.00 I  -.051072  .000713   .139535  .001104  I -.0029797  .0000327  1.7032 0.0219  I    -8.561    1.125    -1.229     .298  -.049200   .141900  -.0031300      .000      .000  
+881021 47455.00 I  -.053561  .000771   .140503  .001105  I -.0048462  .0000335  2.0235 0.0231  I    -8.456    1.125    -1.100     .298  -.052300   .142800  -.0050600      .000      .000  
+881022 47456.00 I  -.056022  .000790   .141580  .000971  I -.0069989  .0000327  2.2606 0.0250  I    -8.480    1.125     -.713     .298  -.055300   .143700  -.0072600      .000      .000  
+881023 47457.00 I  -.058573  .000718   .142753  .000824  I -.0093158  .0000370  2.3428 0.0239  I    -8.623     .615     -.290     .298  -.058300   .144700  -.0096200      .000      .000  
+881024 47458.00 I  -.061320  .000661   .144005  .000413  I -.0116231  .0000348  2.2406 0.0254  I    -8.619     .334     -.065     .298  -.061300   .145700  -.0119800      .000      .000  
+881025 47459.00 I  -.064320  .000661   .145306  .000413  I -.0137447  .0000348  1.9813 0.0224  I    -8.291     .334     -.055     .298  -.064300   .146800  -.0141400      .000      .000  
+881026 47460.00 I  -.067585  .000603   .146623  .000432  I -.0155610  .0000283  1.6478 0.0250  I    -7.836     .334     -.072     .298  -.067300   .148000  -.0160000      .000      .000  
+881027 47461.00 I  -.071008  .000511   .147942  .000477  I -.0170483  .0000358  1.3382 0.0229  I    -7.589     .334      .022     .298  -.070300   .149200  -.0175400      .000      .000  
+881028 47462.00 I  -.074448  .000511   .149283  .000492  I -.0182697  .0000359  1.1255 0.0267  I    -7.577     .305      .130     .175  -.073200   .150600  -.0188100      .000      .000  
+881029 47463.00 I  -.077762  .000455   .150669  .000522  I -.0193425  .0000397  1.0424 0.0264  I    -7.490     .284      .088     .214  -.076200   .151900  -.0199300      .000      .000  
+881030 47464.00 I  -.080813  .000750   .152136  .000507  I -.0203951  .0000387  1.0811 0.0282  I    -7.131     .284     -.066     .214  -.079100   .153400  -.0210200      .000      .000  
+881031 47465.00 I  -.083525  .000750   .153718  .000507  I -.0215348  .0000401  1.2103 0.0265  I    -6.675     .316     -.142     .188  -.082000   .154900  -.0222000      .000      .000  
+8811 1 47466.00 I  -.086039  .000685   .155397  .000443  I -.0228325  .0000361  1.3901 0.0232  I    -6.359     .316     -.035     .188  -.084900   .156500  -.0235300      .000      .000  
+8811 2 47467.00 I  -.088557  .000640   .157148  .000405  I -.0243200  .0000233  1.5851 0.0218  I    -6.152     .283      .163     .183  -.087700   .158200  -.0250200      .000      .000  
+8811 3 47468.00 I  -.091194  .000758   .158948  .000239  I -.0259991  .0000245  1.7695 0.0235  I    -5.850     .348      .359     .214  -.090500   .159900  -.0266900      .000      .000  
+8811 4 47469.00 I  -.093909  .000714   .160779  .000576  I -.0278487  .0000408  1.9231 0.0248  I    -5.480     .348      .629     .214  -.093200   .161700  -.0285100      .000      .000  
+8811 5 47470.00 I  -.096631  .000657   .162627  .000584  I -.0298275  .0000432  2.0233 0.0280  I    -5.301     .365     1.072     .213  -.095900   .163500  -.0304200      .000      .000  
+8811 6 47471.00 I  -.099338  .000303   .164502  .000597  I -.0318693  .0000383  2.0456 0.0282  I    -5.472     .356     1.329     .236  -.098600   .165400  -.0323700      .000      .000  
+8811 7 47472.00 I  -.102060  .000318   .166418  .000750  I -.0338902  .0000363  1.9823 0.0230  I    -5.851     .398     1.258     .235  -.101300   .167300  -.0343100      .000      .000  
+8811 8 47473.00 I  -.104826  .000283   .168374  .000608  I -.0358126  .0000253  1.8549 0.0220  I    -6.198     .567     1.090     .241  -.103900   .169200  -.0361700      .000      .000  
+8811 9 47474.00 I  -.107616  .000265   .170322  .000621  I -.0375893  .0000249  1.6954 0.0166  I    -6.467     .574      .902     .195  -.106400   .171200  -.0378900      .000      .000  
+881110 47475.00 I  -.110370  .000265   .172220  .000621  I -.0391988  .0000215  1.5222 0.0150  I    -6.609     .574      .694     .195  -.108800   .173200  -.0394700      .000      .000  
+881111 47476.00 I  -.112960  .000250   .174102  .000506  I -.0406350  .0000168  1.3531 0.0137  I    -6.371     .605      .536     .192  -.111200   .175300  -.0408900      .000      .000  
+881112 47477.00 I  -.115258  .000247   .176073  .000492  I -.0419216  .0000169  1.2339 0.0117  I    -5.850     .496      .561     .162  -.113400   .177400  -.0421800      .000      .000  
+881113 47478.00 I  -.117269  .000220   .178146  .000455  I -.0431352  .0000162  1.2120 0.0121  I    -5.318     .509      .737     .105  -.115700   .179600  -.0434200      .000      .000  
+881114 47479.00 I  -.119034  .000221   .180309  .000290  I -.0443845  .0000174  1.3067 0.0204  I    -4.851     .321      .864     .108  -.117800   .181800  -.0447200      .000      .000  
+881115 47480.00 I  -.120585  .000244   .182550  .000357  I -.0457852  .0000374  1.5112 0.0146  I    -4.436     .108      .840     .298  -.119900   .184100  -.0461700      .000      .000  
+881116 47481.00 I  -.121991  .000239   .184885  .000336  I -.0474319  .0000234  1.7908 0.0219  I    -4.045     .108      .730     .298  -.121900   .186400  -.0478600      .000      .000  
+881117 47482.00 I  -.123340  .000242   .187332  .000331  I -.0493727  .0000229  2.0880 0.0425  I    -3.721     .791      .670     .298  -.123900   .188800  -.0498400      .000      .000  
+881118 47483.00 I  -.124708  .000235   .189888  .000359  I -.0515897  .0000817  2.3306 0.0422  I    -3.585     .791      .753     .298  -.125800   .191300  -.0520900      .000      .000  
+881119 47484.00 I  -.126172  .000235   .192541  .000359  I -.0539944  .0000813  2.4547 0.0568  I    -3.753     .791      .979     .298  -.127700   .193800  -.0545100      .000      .000  
+881120 47485.00 I  -.127798  .000564   .195270  .000415  I -.0564475  .0000789  2.4240 0.0524  I    -4.185     .791     1.249     .298  -.129600   .196400  -.0569700      .000      .000  
+881121 47486.00 I  -.129602  .000515   .198043  .000373  I -.0587926  .0000661  2.2439 0.0513  I    -4.658     .791     1.407     .298  -.131400   .199000  -.0593200      .000      .000  
+881122 47487.00 I  -.131586  .000565   .200833  .000368  I -.0609012  .0000656  1.9616 0.0576  I    -4.955     .136     1.378     .298  -.133300   .201700  -.0614200      .000      .000  
+881123 47488.00 I  -.133739  .000626   .203614  .000711  I -.0627064  .0000944  1.6512 0.0346  I    -5.071     .182     1.231     .298  -.135100   .204400  -.0632200      .000      .000  
+881124 47489.00 I  -.135980  .000626   .206392  .000711  I -.0642198  .0000222  1.3893 0.0485  I    -5.156     .182     1.098     .298  -.136900   .207200  -.0647300      .000      .000  
+881125 47490.00 I  -.138213  .000626   .209184  .000711  I -.0655199  .0000225  1.2322 0.0149  I    -5.282     .182     1.044     .298  -.138700   .210000  -.0660300      .000      .000  
+881126 47491.00 I  -.140403  .000331   .212013  .000569  I -.0667258  .0000199  1.1998 0.0203  I    -5.325     .182     1.064     .298  -.140500   .212800  -.0672500      .000      .000  
+881127 47492.00 I  -.142552  .000305   .214861  .000503  I -.0679543  .0000339  1.2718 0.0217  I    -5.158     .232     1.158     .153  -.142300   .215700  -.0684900      .000      .000  
+881128 47493.00 I  -.144665  .000241   .217698  .000512  I -.0692912  .0000386  1.4094 0.0258  I    -4.809     .231     1.342     .178  -.144000   .218500  -.0698400      .000      .000  
+881129 47494.00 I  -.146749  .000229   .220493  .000308  I -.0707816  .0000389  1.5727 0.0273  I    -4.386     .231     1.581     .178  -.145700   .221400  -.0713400      .000      .000  
+881130 47495.00 I  -.148794  .000229   .223228  .000308  I -.0724359  .0000386  1.7339 0.0273  I    -3.903     .231     1.784     .178  -.147400   .224300  -.0729900      .000      .000  
+8812 1 47496.00 I  -.150745  .000592   .225929  .000287  I -.0742397  .0000384  1.8659 0.0272  I    -3.338     .231     1.883     .178  -.149000   .227100  -.0747800      .000      .000  
+8812 2 47497.00 I  -.152550  .000616   .228623  .000235  I -.0761494  .0000382  1.9429 0.0250  I    -2.752     .475     1.935     .299  -.150600   .230000  -.0766700      .000      .000  
+8812 3 47498.00 I  -.154162  .000691   .231337  .000160  I -.0781025  .0000321  1.9509 0.0257  I    -2.286     .572     2.025     .348  -.152100   .232900  -.0785900      .000      .000  
+8812 4 47499.00 I  -.155533  .000965   .234098  .000232  I -.0800263  .0000344  1.8842 0.0231  I    -2.072     .693     2.101     .414  -.153600   .235800  -.0804900      .000      .000  
+8812 5 47500.00 I  -.156686  .000931   .236928  .000273  I -.0818496  .0000333  1.7535 0.0221  I    -2.170     .693     2.024     .414  -.155100   .238700  -.0822900      .000      .000  
+8812 6 47501.00 I  -.157701  .000787   .239829  .000384  I -.0835181  .0000276  1.5773 0.0230  I    -2.503     .693     1.759     .414  -.156400   .241500  -.0839300      .000      .000  
+8812 7 47502.00 I  -.158659  .000318   .242801  .000505  I -.0849965  .0000316  1.3779 0.0191  I    -2.969     .498     1.422     .302  -.157700   .244400  -.0853800      .000      .000  
+8812 8 47503.00 I  -.159628  .000298   .245841  .000350  I -.0862774  .0000263  1.1888 0.0234  I    -3.490     .131     1.180     .103  -.158900   .247200  -.0866400      .000      .000  
+8812 9 47504.00 I  -.160621  .000298   .248931  .000350  I -.0873914  .0000346  1.0516 0.0221  I    -3.964     .318     1.131     .298  -.160000   .250100  -.0877300      .000      .000  
+881210 47505.00 I  -.161634  .000298   .252042  .000350  I -.0884065  .0000355  0.9921 0.0241  I    -4.273     .318     1.279     .298  -.160900   .253000  -.0887000      .000      .000  
+881211 47506.00 I  -.162667  .000200   .255108  .000371  I -.0894034  .0000335  1.0161 0.0237  I    -4.278     .318     1.485     .298  -.161700   .255900  -.0896700      .000      .000  
+881212 47507.00 I  -.163707  .000493   .258085  .000365  I -.0904717  .0000315  1.1392 0.0231  I    -3.896     .397     1.577     .298  -.162400   .258800  -.0907500      .000      .000  
+881213 47508.00 I  -.164702  .000577   .260986  .000266  I -.0917109  .0000319  1.3496 0.0223  I    -3.323     .442     1.530     .298  -.163000   .261700  -.0920300      .000      .000  
+881214 47509.00 I  -.165583  .000577   .263835  .000266  I -.0931807  .0000317  1.5895 0.0220  I    -2.854     .442     1.438     .298  -.163500   .264600  -.0935700      .000      .000  
+881215 47510.00 I  -.166239  .000696   .266649  .000375  I -.0948778  .0000303  1.7932 0.0198  I    -2.721     .412     1.420     .298  -.164000   .267500  -.0953200      .000      .000  
+881216 47511.00 I  -.166572  .000586   .269463  .000337  I -.0967332  .0000238  1.8953 0.0181  I    -2.887     .412     1.446     .298  -.164400   .270400  -.0972300      .000      .000  
+881217 47512.00 I  -.166652  .000594   .272299  .000294  I -.0986221  .0000199  1.8584 0.0186  I    -3.226     .394     1.524     .182  -.164700   .273300  -.0991700      .000      .000  
+881218 47513.00 I  -.166579  .000652   .275166  .000209  I -.1004058  .0000285  1.6888 0.0157  I    -3.616     .294     1.717     .254  -.164900   .276200  -.1009900      .000      .000  
+881219 47514.00 I  -.166451  .000447   .278072  .000218  I -.1019672  .0000243  1.4218 0.0187  I    -3.893     .330     2.052     .282  -.165000   .279100  -.1025800      .000      .000  
+881220 47515.00 I  -.166364  .000446   .281028  .000300  I -.1032387  .0000242  1.1227 0.0149  I    -3.901     .330     2.485     .282  -.165000   .282000  -.1038800      .000      .000  
+881221 47516.00 I  -.166345  .000389   .284038  .000337  I -.1042255  .0000174  0.8624 0.0149  I    -3.670     .449     2.594     .222  -.165000   .284900  -.1049000      .000      .000  
+881222 47517.00 I  -.166322  .000389   .287090  .000337  I -.1049930  .0000175  0.6907 0.0136  I    -3.282     .449     2.315     .222  -.164800   .287700  -.1057000      .000      .000  
+881223 47518.00 I  -.166208  .000474   .290178  .000429  I -.1056444  .0000210  0.6314 0.0183  I    -2.825     .497     1.921     .186  -.164600   .290600  -.1063800      .000      .000  
+881224 47519.00 I  -.165936  .000322   .293325  .000429  I -.1062911  .0000321  0.6782 0.0192  I    -2.395     .582     1.664     .298  -.164300   .293500  -.1070400      .000      .000  
+881225 47520.00 I  -.165480  .000322   .296533  .000429  I -.1070274  .0000322  0.8050 0.0236  I    -2.047     .582     1.631     .298  -.163900   .296400  -.1078000      .000      .000  
+881226 47521.00 I  -.164879  .000247   .299756  .000537  I -.1079153  .0000346  0.9743 0.0258  I    -1.787     .582     1.731     .298  -.163400   .299300  -.1087200      .000      .000  
+881227 47522.00 I  -.164185  .000250   .302943  .000570  I -.1089782  .0000404  1.1501 0.0291  I    -1.611     .182     1.817     .217  -.162800   .302200  -.1098000      .000      .000  
+881228 47523.00 I  -.163448  .000364   .306042  .000601  I -.1102095  .0000467  1.3079 0.0353  I    -1.541     .182     1.788     .217  -.162200   .305100  -.1110300      .000      .000  
+881229 47524.00 I  -.162718  .000364   .309000  .000601  I -.1115825  .0000578  1.4312 0.0318  I    -1.610     .182     1.679     .217  -.161500   .308000  -.1123800      .000      .000  
+881230 47525.00 I  -.162014  .000364   .311771  .000601  I -.1130535  .0000432  1.4993 0.0339  I    -1.815     .182     1.629     .217  -.160700   .310800  -.1138000      .000      .000  
+881231 47526.00 I  -.161329  .000386   .314379  .000510  I -.1145574  .0000356  1.4965 0.0274  I    -2.118     .182     1.714     .217  -.159900   .313700  -.1152300      .000      .000  
+89 1 1 47527.00 I  -.160623  .000365   .316868  .000435  I -.1160242  .0000337  1.4270 0.0270  I    -2.471     .203     1.844     .154  -.159100   .316500  -.1166000      .000      .000  
+89 1 2 47528.00 I  -.159834  .000411   .319279  .000120  I -.1173940  .0000405  1.3055 0.0267  I    -2.806     .222     1.872     .298  -.158200   .319200  -.1178600      .000      .000  
+89 1 3 47529.00 I  -.158899  .000368   .321651  .000104  I -.1186247  .0000415  1.1525 0.0245  I    -3.020     .222     1.781     .298  -.157300   .322000  -.1189700    -1.200      .700  
+89 1 4 47530.00 I  -.157777  .000368   .324021  .000104  I -.1196954  .0000277  0.9885 0.0245  I    -3.061     .222     1.702     .298  -.156100   .324500  -.1200400    -1.200      .600  
+89 1 5 47531.00 I  -.156514  .000324   .326406  .000149  I -.1206076  .0000262  0.8421 0.0200  I    -3.009     .222     1.731     .298  -.154900   .327000  -.1209400    -1.300      .500  
+89 1 6 47532.00 I  -.155183  .000292   .328817  .000139  I -.1213994  .0000288  0.7552 0.0233  I    -2.991     .184     1.814     .298  -.153700   .329500  -.1217400    -1.500      .400  
+89 1 7 47533.00 I  -.153835  .000396   .331261  .000158  I -.1221507  .0000386  0.7663 0.0237  I    -3.001     .136     1.855     .298  -.152500   .332000  -.1225100    -1.600      .300  
+89 1 8 47534.00 I  -.152507  .000396   .333745  .000158  I -.1229689  .0000377  0.8879 0.0268  I    -2.909     .136     1.834     .298  -.151300   .334600  -.1233600    -1.700      .200  
+89 1 9 47535.00 I  -.151241  .000398   .336273  .000176  I -.1239605  .0000372  1.1113 0.0246  I    -2.668     .136     1.789     .298  -.150200   .337300  -.1243300    -1.800      .300  
+89 110 47536.00 I  -.150107  .000336   .338829  .000194  I -.1252112  .0000316  1.3937 0.0221  I    -2.437     .136     1.734     .298  -.149300   .340000  -.1255800    -1.900      .300  
+89 111 47537.00 I  -.149139  .000263   .341389  .000145  I -.1267405  .0000238  1.6537 0.0188  I    -2.425     .387     1.635     .130  -.148400   .342700  -.1271300    -2.100      .400  
+89 112 47538.00 I  -.148319  .000302   .343925  .000138  I -.1284866  .0000202  1.8175 0.0150  I    -2.674     .488     1.500     .155  -.147600   .345300  -.1288800    -2.100      .600  
+89 113 47539.00 I  -.147620  .000155   .346411  .000139  I -.1303312  .0000181  1.8484 0.0135  I    -3.060     .488     1.435     .155  -.146800   .347900  -.1307300    -2.200      .700  
+89 114 47540.00 I  -.146987  .000155   .348832  .000139  I -.1321353  .0000180  1.7352 0.0122  I    -3.433     .488     1.548     .155  -.146000   .350300  -.1325300    -2.100      .800  
+89 115 47541.00 I  -.146334  .000134   .351191  .000157  I -.1337636  .0000165  1.5081 0.0116  I    -3.619     .488     1.685     .155  -.145100   .352700  -.1341600    -2.000      .800  
+89 116 47542.00 I  -.145597  .000165   .353501  .000181  I -.1351367  .0000147  1.2366 0.0109  I    -3.626     .514     1.772     .144  -.144200   .355100  -.1355200    -1.900      .900  
+89 117 47543.00 I  -.144734  .000187   .355784  .000173  I -.1362438  .0000141  0.9859 0.0115  I    -3.488     .549     1.762     .127  -.143300   .357400  -.1366300    -1.800     1.000  
+89 118 47544.00 I  -.143704  .000202   .358063  .000271  I -.1371317  .0000178  0.8046 0.0114  I    -3.220     .549     1.622     .127  -.142300   .359600  -.1375100    -1.700     1.000  
+89 119 47545.00 I  -.142476  .000202   .360360  .000271  I -.1378875  .0000178  0.7267 0.0128  I    -2.864     .549     1.380     .127  -.141100   .361800  -.1382600    -1.700     1.000  
+89 120 47546.00 I  -.141091  .000279   .362676  .000407  I -.1386235  .0000183  0.7638 0.0124  I    -2.500     .549     1.145     .127  -.140000   .364000  -.1389800    -1.700     1.000  
+89 121 47547.00 I  -.139636  .000437   .364995  .000361  I -.1394478  .0000172  0.8989 0.0147  I    -2.255     .428     1.065     .109  -.138700   .366200  -.1397900    -1.700     1.000  
+89 122 47548.00 I  -.138188  .000567   .367291  .000392  I -.1404436  .0000230  1.1008 0.0132  I    -2.205     .262     1.229     .109  -.137500   .368300  -.1407900    -1.700      .900  
+89 123 47549.00 I  -.136813  .000567   .369529  .000392  I -.1416598  .0000201  1.3338 0.0150  I    -2.270     .262     1.593     .109  -.136300   .370400  -.1419900    -1.800      .800  
+89 124 47550.00 I  -.135556  .000602   .371683  .000398  I -.1431067  .0000193  1.5532 0.0136  I    -2.289     .262     1.987     .109  -.135100   .372400  -.1435100    -2.100      .700  
+89 125 47551.00 I  -.134376  .000558   .373769  .000422  I -.1447478  .0000183  1.7173 0.0135  I    -2.170     .262     2.095     .109  -.134000   .374400  -.1452100    -2.400      .600  
+89 126 47552.00 I  -.133268  .000519   .375796  .000397  I -.1465163  .0000190  1.8063 0.0213  I    -2.029     .640     1.896     .121  -.132900   .376400  -.1470300    -2.600      .500  
+89 127 47553.00 I  -.132239  .000635   .377769  .000385  I -.1483335  .0000385  1.8148 0.0205  I    -2.004     .802     1.627     .141  -.131800   .378400  -.1488800    -2.900      .400  
+89 128 47554.00 I  -.131292  .000326   .379698  .000354  I -.1501200  .0000364  1.7458 0.0265  I    -2.144     .955     1.468     .137  -.130800   .380300  -.1507100    -3.000      .300  
+89 129 47555.00 I  -.130378  .000326   .381620  .000354  I -.1518051  .0000365  1.6168 0.0245  I    -2.479     .955     1.417     .137  -.129800   .382400  -.1523400    -2.700      .300  
+89 130 47556.00 I  -.129424  .000460   .383583  .000421  I -.1533415  .0000327  1.4513 0.0246  I    -2.938     .955     1.312     .137  -.128800   .384500  -.1538200    -2.300      .400  
+89 131 47557.00 I  -.128349  .000378   .385633  .000381  I -.1547032  .0000331  1.2721 0.0279  I    -3.355     .841     1.124     .145  -.127700   .386700  -.1551400    -1.900      .500  
+89 2 1 47558.00 I  -.127087  .000460   .387818  .000425  I -.1558913  .0000452  1.1096 0.0245  I    -3.579     .594      .996     .179  -.126500   .388900  -.1562700    -1.400      .600  
+89 2 2 47559.00 I  -.125585  .000454   .390188  .000450  I -.1569400  .0000362  0.9997 0.0300  I    -3.623     .594      .965     .179  -.125100   .391200  -.1572800    -1.000      .700  
+89 2 3 47560.00 I  -.123832  .000478   .392773  .000479  I -.1579212  .0000396  0.9811 0.0236  I    -3.594     .594      .840     .179  -.123500   .393600  -.1583500     -.300     1.000  
+89 2 4 47561.00 I  -.121911  .000425   .395525  .000435  I -.1589440  .0000304  1.0879 0.0239  I    -3.554     .594      .681     .179  -.121600   .396200  -.1593900      .000     1.100  
+89 2 5 47562.00 I  -.119903  .000220   .398354  .000387  I -.1601397  .0000266  1.3230 0.0201  I    -3.323     .564      .617     .211  -.119600   .398900  -.1606200      .200     1.100  
+89 2 6 47563.00 I  -.117871  .000194   .401156  .000348  I -.1616185  .0000264  1.6437 0.0187  I    -2.796     .480      .756     .254  -.117500   .401600  -.1621400      .400     1.100  
+89 2 7 47564.00 I  -.115849  .000189   .403803  .000379  I -.1634295  .0000263  1.9716 0.0185  I    -2.277     .541     1.069     .260  -.115300   .404100  -.1639800      .300     1.100  
+89 2 8 47565.00 I  -.113860  .000143   .406177  .000366  I -.1655334  .0000258  2.2145 0.0179  I    -2.200     .541     1.304     .260  -.113200   .406500  -.1661000     -.200      .900  
+89 2 9 47566.00 I  -.111876  .000141   .408262  .000366  I -.1678033  .0000244  2.2917 0.0172  I    -2.483     .481     1.477     .284  -.111000   .408700  -.1683600     -.800      .700  
+89 210 47567.00 I  -.109852  .000261   .410131  .000349  I -.1700525  .0000228  2.1760 0.0205  I    -2.843     .486     1.548     .252  -.108800   .410800  -.1705800    -1.500      .500  
+89 211 47568.00 I  -.107744  .000334   .411869  .000450  I -.1721051  .0000329  1.9096 0.0179  I    -3.115     .469     1.371     .253  -.106600   .412700  -.1726000    -2.200      .300  
+89 212 47569.00 I  -.105503  .000409   .413566  .000610  I -.1738461  .0000277  1.5664 0.0217  I    -3.280     .424      .854     .243  -.104300   .414600  -.1743200    -2.800      .100  
+89 213 47570.00 I  -.103089  .000409   .415308  .000610  I -.1752415  .0000284  1.2341 0.0205  I    -3.317     .424      .336     .243  -.101800   .416200  -.1757100    -2.800     -.100  
+89 214 47571.00 I  -.100531  .000487   .417146  .000627  I -.1763413  .0000303  0.9828 0.0195  I    -3.205     .424     -.036     .243  -.099200   .417700  -.1768200    -2.800     -.200  
+89 215 47572.00 I  -.097904  .000451   .419098  .000474  I -.1772436  .0000266  0.8410 0.0216  I    -2.952     .938     -.259     .166  -.096700   .419300  -.1777600    -2.700     -.300  
+89 216 47573.00 I  -.095312  .000372   .421131  .000421  I -.1780595  .0000308  0.8079 0.0268  I    -2.609    1.064     -.320     .174  -.094100   .420900  -.1786100    -2.600     -.300  
+89 217 47574.00 I  -.092857  .000366   .423210  .000338  I -.1788889  .0000466  0.8634 0.0276  I    -2.269    1.044     -.242     .160  -.091600   .422600  -.1794900    -2.500     -.400  
+89 218 47575.00 I  -.090612  .000607   .425283  .000405  I -.1798109  .0000458  0.9927 0.0313  I    -2.044    1.044     -.055     .160  -.089600   .425000  -.1803500    -2.500     -.300  
+89 219 47576.00 I  -.088536  .000571   .427269  .000399  I -.1808903  .0000417  1.1699 0.0300  I    -2.020    1.039      .113     .145  -.087600   .427400  -.1813500    -2.600     -.200  
+89 220 47577.00 I  -.086538  .000559   .429119  .000360  I -.1821532  .0000387  1.3547 0.0291  I    -1.960    1.020      .328     .125  -.085500   .429900  -.1825200    -2.800     -.100  
+89 221 47578.00 I  -.084432  .000574   .430932  .000390  I -.1835922  .0000405  1.5169 0.0282  I    -1.794     .919      .592     .110  -.083400   .432500  -.1838500    -2.900     -.100  
+89 222 47579.00 I  -.082059  .000620   .432797  .000432  I -.1851673  .0000409  1.6200 0.0267  I    -1.752     .985      .733     .298  -.081100   .435000  -.1852900    -3.000      .000  
+89 223 47580.00 I  -.079410  .000759   .434757  .000603  I -.1868075  .0000349  1.6490 0.0269  I    -1.737     .988      .631     .298  -.078000   .436900  -.1870700    -3.000     -.200  
+89 224 47581.00 I  -.076519  .000777   .436825  .000420  I -.1884434  .0000350  1.6123 0.0223  I    -1.716     .988      .394     .298  -.074800   .438700  -.1888600    -3.100     -.400  
+89 225 47582.00 I  -.073472  .000378   .438984  .000437  I -.1900135  .0000277  1.5199 0.0262  I    -1.682     .791      .190     .298  -.071500   .440400  -.1905900    -3.100     -.600  
+89 226 47583.00 I  -.070384  .000611   .441200  .000513  I -.1914703  .0000389  1.3889 0.0243  I    -1.614     .791      .022     .112  -.068200   .442200  -.1922000    -3.000     -.800  
+89 227 47584.00 I  -.067355  .000590   .443424  .000469  I -.1927852  .0000399  1.2396 0.0277  I    -1.562     .791     -.203     .112  -.065000   .444000  -.1936400    -2.900    -1.000  
+89 228 47585.00 I  -.064462  .000590   .445590  .000469  I -.1939514  .0000394  1.0958 0.0256  I    -1.565     .791     -.471     .112  -.062400   .446200  -.1946700    -2.700    -1.100  
+89 3 1 47586.00 I  -.061777  .000496   .447654  .000341  I -.1949889  .0000320  0.9881 0.0231  I    -1.585     .791     -.744     .112  -.060000   .448300  -.1955700    -2.500    -1.100  
+89 3 2 47587.00 I  -.059322  .000503   .449590  .000237  I -.1959522  .0000240  0.9541 0.0207  I    -1.712     .503     -.899     .125  -.057700   .450300  -.1963900    -2.200    -1.200  
+89 3 3 47588.00 I  -.057032  .000527   .451392  .000183  I -.1969334  .0000264  1.0290 0.0171  I    -2.125     .542    -1.004     .136  -.055600   .452100  -.1972600    -2.100    -1.200  
+89 3 4 47589.00 I  -.054827  .000415   .453056  .000124  I -.1980522  .0000244  1.2297 0.0186  I    -2.779     .622    -1.219     .133  -.053500   .453900  -.1983000    -1.900    -1.100  
+89 3 5 47590.00 I  -.052640  .000405   .454584  .000118  I -.1994315  .0000261  1.5463 0.0170  I    -3.303     .622    -1.423     .133  -.051500   .455300  -.1997600    -2.200    -1.000  
+89 3 6 47591.00 I  -.050464  .000372   .455997  .000143  I -.2011648  .0000236  1.9229 0.0180  I    -3.291     .622    -1.420     .133  -.049300   .456600  -.2015700    -2.400     -.800  
+89 3 7 47592.00 I  -.048237  .000456   .457318  .000232  I -.2032656  .0000248  2.2643 0.0183  I    -2.920     .500    -1.089     .104  -.047100   .457700  -.2037500    -2.600     -.700  
+89 3 8 47593.00 I  -.045879  .000485   .458566  .000252  I -.2056514  .0000281  2.4796 0.0210  I    -2.722     .288     -.613     .298  -.044800   .458800  -.2061700    -2.800     -.500  
+89 3 9 47594.00 I  -.043333  .000470   .459762  .000327  I -.2081660  .0000340  2.5184 0.0214  I    -2.909     .220     -.340     .298  -.042400   .459900  -.2087000    -2.900     -.500  
+89 310 47595.00 I  -.040559  .000470   .460928  .000327  I -.2106262  .0000322  2.3713 0.0282  I    -3.250     .220     -.371     .298  -.039700   .461200  -.2111500    -2.600     -.700  
+89 311 47596.00 I  -.037601  .000500   .462108  .000353  I -.2128614  .0000451  2.0825 0.0277  I    -3.438     .220     -.559     .298  -.037000   .462600  -.2133400    -2.300    -1.000  
+89 312 47597.00 I  -.034537  .000500   .463328  .000353  I -.2147751  .0000451  1.7454 0.0434  I    -3.346     .254     -.792     .298  -.034100   .464000  -.2151900    -2.000    -1.400  
+89 313 47598.00 I  -.031444  .000485   .464609  .000445  I -.2163651  .0000741  1.4469 0.0431  I    -2.976     .284    -1.099     .298  -.031100   .465500  -.2167300    -1.600    -1.700  
+89 314 47599.00 I  -.028399  .000485   .465972  .000445  I -.2176977  .0000734  1.2348 0.0525  I    -2.402     .284    -1.481     .298  -.028100   .467000  -.2180500    -1.300    -2.100  
+89 315 47600.00 I  -.025444  .000485   .467418  .000445  I -.2188749  .0000743  1.1432 0.0467  I    -1.825     .284    -1.792     .298  -.025000   .468400  -.2192200    -1.200    -2.300  
+89 316 47601.00 I  -.022537  .000373   .468923  .000478  I -.2200257  .0000577  1.1762 0.0447  I    -1.467     .284    -1.894     .298  -.021800   .469800  -.2204100    -1.100    -2.500  
+89 317 47602.00 I  -.019637  .000359   .470447  .000491  I -.2212566  .0000497  1.2969 0.0349  I    -1.370     .300    -1.811     .298  -.018700   .471100  -.2217300    -1.100    -2.700  
+89 318 47603.00 I  -.016728  .000253   .471924  .000525  I -.2226366  .0000394  1.4688 0.0312  I    -1.411     .310    -1.674     .108  -.015600   .472300  -.2232000    -1.100    -2.800  
+89 319 47604.00 I  -.013793  .000195   .473291  .000504  I -.2242018  .0000377  1.6636 0.0276  I    -1.450     .310    -1.500     .108  -.012500   .473500  -.2248600    -1.100    -2.800  
+89 320 47605.00 I  -.010811  .000180   .474489  .000487  I -.2259581  .0000386  1.8412 0.0253  I    -1.426     .310    -1.205     .108  -.009500   .474800  -.2265900    -1.100    -2.700  
+89 321 47606.00 I  -.007772  .000178   .475523  .000436  I -.2278645  .0000336  1.9597 0.0228  I    -1.333     .310     -.837     .108  -.006400   .475900  -.2284400    -1.100    -2.500  
+89 322 47607.00 I  -.004680  .000169   .476423  .000394  I -.2298524  .0000244  2.0030 0.0212  I    -1.191     .429     -.622     .214  -.003400   .476900  -.2303600    -1.100    -2.400  
+89 323 47608.00 I  -.001536  .000165   .477221  .000210  I -.2318442  .0000258  1.9673 0.0256  I    -1.062     .560     -.755     .306  -.000400   .477800  -.2322500    -1.000    -2.200  
+89 324 47609.00 I   .001662  .000586   .477931  .000339  I -.2337629  .0000449  1.8593 0.0239  I     -.992     .461    -1.208     .276   .002600   .478600  -.2340800     -.800    -2.100  
+89 325 47610.00 I   .004910  .000567   .478562  .000360  I -.2355462  .0000402  1.7015 0.0294  I     -.932     .461    -1.799     .276   .005700   .479300  -.2359200     -.400    -2.200  
+89 326 47611.00 I   .008163  .000514   .479117  .000437  I -.2371585  .0000379  1.5214 0.0269  I     -.817     .402    -2.283     .244   .008700   .479800  -.2375800      .100    -2.300  
+89 327 47612.00 I   .011358  .000460   .479605  .000433  I -.2385892  .0000357  1.3419 0.0301  I     -.676     .723    -2.505     .230   .011700   .480300  -.2390200      .500    -2.500  
+89 328 47613.00 I   .014456  .000563   .480025  .000526  I -.2398493  .0000469  1.1833 0.0284  I     -.589     .715    -2.497     .176   .014800   .480700  -.2402700      .900    -2.700  
+89 329 47614.00 I   .017512  .000597   .480344  .000558  I -.2409700  .0000441  1.0672 0.0275  I     -.601     .715    -2.379     .176   .017900   .481100  -.2413800     1.300    -2.900  
+89 330 47615.00 I   .020572  .000597   .480580  .000558  I -.2420101  .0000289  1.0303 0.0289  I     -.747     .719    -2.296     .157   .021100   .481400  -.2424700     1.400    -2.900  
+89 331 47616.00 I   .023676  .000384   .480793  .000506  I -.2430699  .0000373  1.1111 0.0228  I    -1.083     .719    -2.205     .157   .024400   .481700  -.2436200     1.300    -2.900  
+89 4 1 47617.00 I   .026828  .000419   .481018  .000408  I -.2442733  .0000354  1.3147 0.0267  I    -1.483     .662    -2.227     .146   .027700   .481900  -.2449400     1.100    -2.800  
+89 4 2 47618.00 I   .030002  .000464   .481275  .000377  I -.2457298  .0000383  1.6096 0.0257  I    -1.605     .181    -2.406     .104   .031100   .482200  -.2465400      .900    -2.800  
+89 4 3 47619.00 I   .033252  .000505   .481540  .000405  I -.2475001  .0000374  1.9273 0.0268  I    -1.274     .190    -2.457     .298   .034500   .482400  -.2484400      .500    -2.700  
+89 4 4 47620.00 I   .036645  .000445   .481775  .000404  I -.2495596  .0000376  2.1704 0.0258  I     -.737     .190    -2.163     .298   .037900   .482600  -.2503600     -.400    -2.600  
+89 4 5 47621.00 I   .040156  .000333   .481968  .000204  I -.2517880  .0000356  2.2546 0.0203  I     -.446     .191    -1.693     .298   .041300   .482700  -.2524200    -1.100    -2.700  
+89 4 6 47622.00 I   .043695  .000482   .482123  .000244  I -.2540059  .0000153  2.1501 0.0210  I     -.585     .148    -1.429     .165   .044800   .482900  -.2544400    -1.700    -2.900  
+89 4 7 47623.00 I   .047168  .000609   .482245  .000303  I -.2560372  .0000224  1.8927 0.0138  I     -.953     .791    -1.531     .221   .048200   .483000  -.2563000    -2.200    -3.000  
+89 4 8 47624.00 I   .050497  .000609   .482334  .000303  I -.2577692  .0000230  1.5690 0.0162  I    -1.275     .791    -1.831     .221   .051600   .483100  -.2578500    -2.500    -3.200  
+89 4 9 47625.00 I   .053617  .000609   .482389  .000303  I -.2591858  .0000235  1.2772 0.0134  I    -1.416     .791    -2.156     .221   .054700   .483200  -.2594100    -2.200    -3.300  
+89 410 47626.00 I   .056542  .000461   .482418  .000289  I -.2603588  .0000136  1.0909 0.0127  I    -1.283     .791    -2.540     .221   .057800   .483200  -.2607300    -1.600    -3.400  
+89 411 47627.00 I   .059357  .000405   .482421  .000265  I -.2614125  .0000097  1.0392 0.0084  I     -.880     .190    -2.963     .255   .060900   .483200  -.2619200    -1.000    -3.400  
+89 412 47628.00 I   .062146  .000201   .482398  .000212  I -.2624770  .0000098  1.1070 0.0075  I     -.458     .255    -3.231     .285   .063900   .483200  -.2630900     -.400    -3.500  
+89 413 47629.00 I   .064996  .000201   .482348  .000212  I -.2636536  .0000114  1.2560 0.0116  I     -.354     .255    -3.152     .285   .066900   .483200  -.2643500      .200    -3.500  
+89 414 47630.00 I   .067974  .000201   .482275  .000212  I -.2650022  .0000211  1.4445 0.0108  I     -.609     .255    -2.809     .285   .069900   .483100  -.2656000      .400    -3.400  
+89 415 47631.00 I   .071056  .000176   .482182  .000209  I -.2665444  .0000184  1.6384 0.0134  I     -.926     .255    -2.470     .285   .072900   .483000  -.2670200      .600    -3.300  
+89 416 47632.00 I   .074175  .000259   .482084  .000278  I -.2682722  .0000165  1.8121 0.0152  I    -1.006     .190    -2.277     .211   .075800   .482900  -.2686400      .600    -3.100  
+89 417 47633.00 I   .077261  .000278   .481993  .000300  I -.2701558  .0000243  1.9476 0.0159  I     -.847     .791    -2.136     .134   .078700   .482800  -.2704300      .600    -3.000  
+89 418 47634.00 I   .080242  .000269   .481921  .000346  I -.2721509  .0000273  2.0338 0.0214  I     -.624     .791    -1.949     .134   .081400   .482800  -.2723800      .600    -2.900  
+89 419 47635.00 I   .083051  .000384   .481881  .000391  I -.2742048  .0000352  2.0643 0.0197  I     -.455     .791    -1.834     .120   .084000   .482900  -.2745500      .500    -2.900  
+89 420 47636.00 I   .085654  .000373   .481862  .000449  I -.2762618  .0000284  2.0416 0.0231  I     -.352     .298    -2.123     .166   .086500   .483000  -.2767500      .500    -2.900  
+89 421 47637.00 I   .088070  .000404   .481819  .000480  I -.2782747  .0000298  1.9789 0.0235  I     -.307     .380    -2.737     .251   .088800   .483100  -.2789200      .400    -2.900  
+89 422 47638.00 I   .090333  .000398   .481716  .000490  I -.2802104  .0000375  1.8886 0.0246  I     -.262     .437    -3.226     .289   .091000   .483200  -.2809800      .400    -2.900  
+89 423 47639.00 I   .092486  .000423   .481533  .000502  I -.2820442  .0000391  1.7750 0.0272  I     -.105     .445    -3.333     .297   .093100   .483100  -.2829000      .400    -2.900  
+89 424 47640.00 I   .094494  .000437   .481236  .000498  I -.2837585  .0000393  1.6555 0.0259  I     -.029     .445    -3.419     .297   .095200   .482700  -.2844400      .400    -2.900  
+89 425 47641.00 I   .096371  .000412   .480834  .000530  I -.2853637  .0000339  1.5616 0.0224  I     -.132     .479    -3.434     .324   .097200   .482100  -.2858300      .400    -2.900  
+89 426 47642.00 I   .098163  .000289   .480347  .000502  I -.2869023  .0000217  1.5297 0.0208  I     -.305     .437    -3.219     .297   .099200   .481400  -.2871600      .400    -2.800  
+89 427 47643.00 I   .099938  .000233   .479781  .000386  I -.2884530  .0000240  1.5876 0.0161  I     -.448     .397    -2.993     .253   .101100   .480700  -.2885100      .300    -2.800  
+89 428 47644.00 I   .101770  .000233   .479145  .000443  I -.2901074  .0000239  1.7353 0.0169  I     -.460     .397    -3.073     .253   .103100   .479800  -.2899900      .100    -2.800  
+89 429 47645.00 I   .103681  .000292   .478475  .000583  I -.2919493  .0000237  1.9599 0.0158  I     -.417     .441    -3.312     .249   .104900   .479400  -.2919500     -.500    -2.700  
+89 430 47646.00 I   .105679  .000266   .477783  .000577  I -.2940401  .0000207  2.2230 0.0150  I     -.329     .441    -3.531     .249   .106900   .478800  -.2942000    -1.200    -2.600  
+89 5 1 47647.00 I   .107778  .000283   .477063  .000565  I -.2963841  .0000183  2.4525 0.0161  I     -.221     .393    -3.544     .198   .109000   .478300  -.2966900    -1.900    -2.600  
+89 5 2 47648.00 I   .110015  .000376   .476300  .000687  I -.2989080  .0000247  2.5708 0.0136  I     -.259     .347    -3.226     .193   .111300   .477700  -.2993400    -2.500    -2.600  
+89 5 3 47649.00 I   .112428  .000345   .475470  .000721  I -.3014717  .0000202  2.5272 0.0160  I     -.592     .347    -2.738     .193   .113600   .477000  -.3020200    -3.000    -2.600  
+89 5 4 47650.00 I   .115060  .000345   .474545  .000721  I -.3039073  .0000202  2.3184 0.0127  I    -1.131     .347    -2.414     .193   .116100   .476000  -.3044400    -2.900    -3.000  
+89 5 5 47651.00 I   .117874  .000304   .473559  .000677  I -.3060707  .0000154  1.9962 0.0133  I    -1.632     .347    -2.428     .193   .118800   .474900  -.3065900    -2.500    -3.300  
+89 5 6 47652.00 I   .120803  .000311   .472567  .000522  I -.3078923  .0000173  1.6520 0.0138  I    -1.911     .451    -2.665     .157   .121600   .473800  -.3084100    -2.000    -3.600  
+89 5 7 47653.00 I   .123774  .000281   .471615  .000447  I -.3093978  .0000230  1.3773 0.0144  I    -1.927     .527    -2.937     .298   .124400   .472800  -.3099400    -1.500    -3.900  
+89 5 8 47654.00 I   .126711  .000281   .470731  .000447  I -.3106890  .0000229  1.2290 0.0162  I    -1.697     .527    -3.193     .298   .127300   .471800  -.3112700    -1.100    -4.100  
+89 5 9 47655.00 I   .129543  .000300   .469925  .000431  I -.3119010  .0000227  1.2162 0.0145  I    -1.315     .527    -3.433     .298   .130200   .470900  -.3124200    -1.000    -4.100  
+89 510 47656.00 I   .132250  .000245   .469156  .000410  I -.3131560  .0000177  1.3072 0.0162  I     -.908     .527    -3.552     .298   .133100   .470000  -.3136000    -1.000    -3.900  
+89 511 47657.00 I   .134873  .000264   .468363  .000358  I -.3145339  .0000232  1.4539 0.0163  I     -.807     .392    -3.416     .112   .135900   .469100  -.3148900    -1.000    -3.800  
+89 512 47658.00 I   .137457  .000232   .467478  .000276  I -.3160676  .0000273  1.6122 0.0209  I    -1.149     .293    -3.086     .113   .138700   .468100  -.3163400    -1.100    -3.600  
+89 513 47659.00 I   .140051  .000284   .466439  .000383  I -.3177515  .0000348  1.7503 0.0232  I    -1.591     .172    -2.817     .128   .141500   .467000  -.3179100    -1.300    -3.400  
+89 514 47660.00 I   .142692  .000284   .465202  .000383  I -.3195541  .0000374  1.8463 0.0250  I    -1.730     .172    -2.761     .128   .144100   .465800  -.3197900    -1.400    -3.400  
+89 515 47661.00 I   .145352  .000367   .463771  .000501  I -.3214257  .0000359  1.8873 0.0252  I    -1.542     .172    -2.817     .128   .146600   .464600  -.3217400    -1.600    -3.400  
+89 516 47662.00 I   .147974  .000432   .462165  .000483  I -.3233090  .0000337  1.8694 0.0288  I    -1.304     .138    -2.821     .103   .149000   .463200  -.3236900    -1.800    -3.400  
+89 517 47663.00 I   .150536  .000574   .460428  .000628  I -.3251465  .0000451  1.7977 0.0290  I    -1.217     .791    -2.794     .298   .151400   .461700  -.3255900    -1.900    -3.500  
+89 518 47664.00 I   .153032  .000574   .458624  .000580  I -.3268908  .0000471  1.6854 0.0304  I    -1.289     .791    -2.880     .298   .153700   .460100  -.3274000    -1.900    -3.500  
+89 519 47665.00 I   .155458  .000576   .456813  .000554  I -.3285086  .0000409  1.5470 0.0290  I    -1.474     .791    -3.109     .298   .156000   .458200  -.3290600    -1.800    -3.600  
+89 520 47666.00 I   .157792  .000511   .455046  .000534  I -.3299836  .0000337  1.4048 0.0250  I    -1.742     .791    -3.325     .298   .158100   .456200  -.3305900    -1.500    -3.800  
+89 521 47667.00 I   .159992  .000470   .453368  .000576  I -.3313262  .0000289  1.2864 0.0219  I    -2.029     .108    -3.351     .298   .160200   .454200  -.3320200    -1.300    -3.900  
+89 522 47668.00 I   .161991  .000454   .451794  .000549  I -.3325726  .0000281  1.2167 0.0202  I    -2.271     .161    -3.175     .298   .162200   .452200  -.3333900    -1.100    -3.900  
+89 523 47669.00 I   .163797  .000454   .450258  .000549  I -.3337839  .0000281  1.2200 0.0156  I    -2.461     .197    -2.953     .298   .164100   .450300  -.3347300    -1.000    -3.900  
+89 524 47670.00 I   .165449  .000383   .448686  .000565  I -.3350409  .0000134  1.3081 0.0158  I    -2.646     .197    -2.856     .298   .166000   .449200  -.3357500    -1.000    -3.600  
+89 525 47671.00 I   .167014  .000349   .447059  .000563  I -.3364270  .0000146  1.4767 0.0104  I    -2.844     .214    -2.924     .298   .167900   .448100  -.3368900    -1.200    -3.300  
+89 526 47672.00 I   .168630  .000359   .445410  .000531  I -.3380170  .0000158  1.7133 0.0154  I    -2.892     .378    -3.049     .298   .169700   .447100  -.3382400    -1.300    -3.000  
+89 527 47673.00 I   .170353  .000383   .443761  .000436  I -.3398651  .0000272  1.9842 0.0180  I    -2.671     .454    -3.159     .298   .171500   .446000  -.3398400    -1.600    -2.600  
+89 528 47674.00 I   .172213  .000408   .442138  .000471  I -.3419779  .0000323  2.2324 0.0233  I    -2.250     .505    -3.256     .298   .173300   .444800  -.3417200    -1.900    -2.300  
+89 529 47675.00 I   .174223  .000286   .440579  .000499  I -.3443007  .0000379  2.3930 0.0220  I    -1.815     .515    -3.331     .298   .175100   .442700  -.3443400    -2.000    -2.300  
+89 530 47676.00 I   .176326  .000321   .439081  .000507  I -.3467165  .0000299  2.4113 0.0233  I    -1.617     .515    -3.317     .298   .176900   .440500  -.3470700    -2.000    -2.400  
+89 531 47677.00 I   .178441  .000313   .437618  .000468  I -.3490693  .0000271  2.2675 0.0237  I    -1.819     .415    -3.206     .387   .178800   .438300  -.3496900    -2.000    -2.500  
+89 6 1 47678.00 I   .180503  .000351   .436141  .000435  I -.3512058  .0000369  1.9867 0.0197  I    -2.379     .258    -3.079     .458   .180600   .436100  -.3520600    -1.900    -2.700  
+89 6 2 47679.00 I   .182458  .000333   .434592  .000469  I -.3530186  .0000287  1.6338 0.0325  I    -3.020     .234    -3.004     .414   .182600   .434100  -.3540600    -1.700    -2.900  
+89 6 3 47680.00 I   .184277  .000333   .432933  .000469  I -.3544779  .0000535  1.2946 0.0275  I    -3.500     .349    -2.928     .387   .184700   .432400  -.3555200    -2.500    -4.000  
+89 6 4 47681.00 I   .185968  .000360   .431184  .000428  I -.3556373  .0000469  1.0439 0.0355  I    -3.764     .349    -2.961     .421   .186700   .431000  -.3567100    -1.800    -4.200  
+89 6 5 47682.00 I   .187552  .000324   .429384  .000373  I -.3566092  .0000467  0.9238 0.0430  I    -3.751     .312    -3.207     .357   .188800   .429700  -.3577100    -1.100    -4.200  
+89 6 6 47683.00 I   .189112  .000373   .427581  .000393  I -.3575300  .0000722  0.9391 0.0424  I    -3.297     .331    -3.377     .150   .190900   .428500  -.3586700     -.400    -4.300  
+89 6 7 47684.00 I   .190740  .000373   .425782  .000393  I -.3585215  .0000709  1.0567 0.0487  I    -2.656     .341    -3.340     .117   .192900   .427200  -.3597100      .100    -4.300  
+89 6 8 47685.00 I   .192506  .000445   .423983  .000278  I -.3596579  .0000655  1.2179 0.0423  I    -2.366     .378    -3.131     .128   .195000   .425500  -.3608800     -.100    -4.100  
+89 6 9 47686.00 I   .194400  .000407   .422163  .000179  I -.3609551  .0000462  1.3724 0.0388  I    -2.653     .175    -2.815     .105   .197000   .423800  -.3621600     -.400    -3.900  
+89 610 47687.00 I   .196393  .000386   .420297  .000164  I -.3623900  .0000417  1.4889 0.0333  I    -3.246     .258    -2.562     .105   .199000   .421900  -.3635400     -.900    -3.600  
+89 611 47688.00 I   .198458  .000498   .418355  .000136  I -.3639148  .0000479  1.5512 0.0265  I    -3.702     .285    -2.517     .298   .201000   .420000  -.3649900    -1.500    -3.500  
+89 612 47689.00 I   .200570  .000498   .416317  .000136  I -.3654695  .0000326  1.5447 0.0295  I    -3.868     .307    -2.623     .298   .202900   .417900  -.3664500    -2.000    -3.300  
+89 613 47690.00 I   .202666  .000498   .414182  .000136  I -.3669805  .0000345  1.4669 0.0226  I    -3.926     .307    -2.667     .298   .204700   .415500  -.3678700    -2.500    -3.400  
+89 614 47691.00 I   .204677  .000403   .411958  .000103  I -.3683846  .0000314  1.3330 0.0189  I    -4.068     .307    -2.620     .298   .206400   .413100  -.3691700    -2.800    -3.600  
+89 615 47692.00 I   .206570  .000362   .409656  .000106  I -.3696329  .0000155  1.1583 0.0213  I    -4.307     .273    -2.620     .298   .208100   .410600  -.3703100    -3.200    -3.800  
+89 616 47693.00 I   .208381  .000459   .407288  .000128  I -.3706947  .0000288  0.9642 0.0162  I    -4.571     .114    -2.736     .298   .209700   .408000  -.3712700    -3.500    -4.000  
+89 617 47694.00 I   .210155  .000118   .404868  .000141  I -.3715637  .0000284  0.7772 0.0200  I    -4.813     .114    -2.873     .298   .211400   .405400  -.3720900    -3.800    -4.200  
+89 618 47695.00 I   .211929  .000143   .402408  .000148  I -.3722632  .0000277  0.6324 0.0188  I    -5.008     .114    -2.898     .298   .213100   .402800  -.3727600    -3.700    -4.100  
+89 619 47696.00 I   .213726  .000456   .399916  .000171  I -.3728549  .0000247  0.5667 0.0179  I    -5.133     .114    -2.772     .298   .214900   .400300  -.3733200    -3.700    -3.900  
+89 620 47697.00 I   .215569  .000600   .397397  .000233  I -.3734306  .0000228  0.6031 0.0201  I    -5.205     .269    -2.578     .129   .216700   .397700  -.3738500    -3.600    -3.800  
+89 621 47698.00 I   .217478  .000753   .394856  .000281  I -.3740968  .0000318  0.7465 0.0168  I    -5.312     .356    -2.425     .143   .218500   .395100  -.3744500    -3.600    -3.600  
+89 622 47699.00 I   .219460  .000753   .392288  .000281  I -.3749524  .0000247  0.9764 0.0251  I    -5.569     .356    -2.370     .143   .220400   .392400  -.3752200    -3.600    -3.500  
+89 623 47700.00 I   .221490  .000753   .389688  .000281  I -.3760604  .0000388  1.2388 0.0222  I    -6.026     .356    -2.393     .143   .222400   .389800  -.3764300    -4.000    -3.400  
+89 624 47701.00 I   .223484  .000684   .387050  .000248  I -.3774185  .0000368  1.4667 0.0255  I    -6.518     .356    -2.412     .143   .224500   .387200  -.3778900    -4.500    -3.400  
+89 625 47702.00 I   .225443  .000744   .384378  .000359  I -.3789637  .0000332  1.6044 0.0270  I    -6.923     .334    -2.389     .122   .226600   .384600  -.3795300    -5.000    -3.400  
+89 626 47703.00 I   .227389  .000758   .381680  .000374  I -.3805834  .0000395  1.6106 0.0280  I    -7.211     .275    -2.343     .298   .228800   .382000  -.3812500    -5.300    -3.500  
+89 627 47704.00 I   .229349  .000672   .378961  .000378  I -.3821356  .0000451  1.4690 0.0299  I    -7.374     .250    -2.319     .298   .230900   .379300  -.3829100    -5.500    -3.600  
+89 628 47705.00 I   .231358  .000672   .376225  .000378  I -.3834821  .0000450  1.2095 0.0254  I    -7.405     .250    -2.351     .298   .232900   .376700  -.3841500    -5.100    -3.700  
+89 629 47706.00 I   .233388  .000685   .373459  .000363  I -.3845358  .0000232  0.8936 0.0262  I    -7.320     .250    -2.350     .298   .234800   .374000  -.3851100    -4.500    -3.900  
+89 630 47707.00 I   .235346  .000718   .370661  .000387  I -.3852727  .0000267  0.5881 0.0177  I    -7.167     .751    -2.340     .134   .236600   .371300  -.3857600    -3.800    -4.100  
+89 7 1 47708.00 I   .237174  .000830   .367822  .000449  I -.3857380  .0000268  0.3607 0.0193  I    -7.011     .852    -2.417     .150   .238400   .368600  -.3861700    -3.000    -4.300  
+89 7 2 47709.00 I   .238840  .000729   .364929  .000326  I -.3860344  .0000280  0.2541 0.0184  I    -6.922     .979    -2.596     .156   .240100   .365800  -.3864300    -2.300    -4.400  
+89 7 3 47710.00 I   .240365  .000633   .361986  .000367  I -.3862903  .0000253  0.2798 0.0185  I    -6.962     .979    -2.833     .156   .241800   .363000  -.3867200    -2.100    -3.700  
+89 7 4 47711.00 I   .241816  .000575   .359017  .000380  I -.3866311  .0000241  0.4167 0.0200  I    -6.994     .853    -2.920     .138   .243400   .359800  -.3870900    -1.800    -3.400  
+89 7 5 47712.00 I   .243232  .000679   .356043  .000464  I -.3871441  .0000309  0.6148 0.0208  I    -7.040     .743    -2.777     .343   .244900   .356500  -.3876300    -1.800    -3.100  
+89 7 6 47713.00 I   .244637  .000700   .353083  .000473  I -.3878642  .0000339  0.8233 0.0197  I    -7.290     .456    -2.500     .364   .246400   .353200  -.3883600    -1.900    -2.900  
+89 7 7 47714.00 I   .246029  .000508   .350152  .000338  I -.3887809  .0000244  1.0023 0.0208  I    -7.804     .433    -2.239     .368   .247800   .350000  -.3892600    -2.200    -2.700  
+89 7 8 47715.00 I   .247390  .000508   .347247  .000338  I -.3898499  .0000242  1.1244 0.0173  I    -8.394     .403    -2.153     .348   .249100   .347000  -.3903000    -3.200    -2.700  
+89 7 9 47716.00 I   .248711  .000480   .344346  .000349  I -.3910046  .0000244  1.1710 0.0180  I    -8.816     .403    -2.192     .348   .250400   .344100  -.3914000    -4.400    -2.800  
+89 710 47717.00 I   .249981  .000556   .341423  .000323  I -.3921652  .0000266  1.1376 0.0190  I    -8.905     .571    -2.159     .321   .251500   .341300  -.3925200    -5.600    -3.000  
+89 711 47718.00 I   .251214  .000534   .338475  .000257  I -.3932617  .0000291  1.0500 0.0200  I    -8.809     .573    -2.140     .116   .252600   .338500  -.3935800    -6.900    -3.100  
+89 712 47719.00 I   .252378  .000535   .335505  .000237  I -.3942564  .0000300  0.9361 0.0225  I    -8.886     .631    -2.266     .165   .253600   .335700  -.3945600    -8.000    -3.200  
+89 713 47720.00 I   .253441  .000629   .332538  .000350  I -.3951311  .0000342  0.8138 0.0340  I    -9.428     .620    -2.596     .169   .254500   .333000  -.3954500    -8.400    -3.000  
+89 714 47721.00 I   .254448  .000803   .329617  .000442  I -.3958903  .0000611  0.7105 0.0343  I   -10.190     .753    -2.930     .224   .255400   .330200  -.3962100    -8.600    -2.900  
+89 715 47722.00 I   .255471  .000864   .326783  .000453  I -.3965658  .0000594  0.6484 0.0396  I   -10.698     .737    -2.919     .317   .256100   .327500  -.3968500    -8.700    -2.700  
+89 716 47723.00 I   .256523  .000804   .324049  .000491  I -.3972030  .0000504  0.6342 0.0392  I   -10.795     .683    -2.614     .377   .256900   .324700  -.3975300    -8.800    -2.500  
+89 717 47724.00 I   .257510  .000798   .321393  .000499  I -.3978523  .0000511  0.6745 0.0356  I   -10.463     .625    -2.132     .364   .257500   .322000  -.3980000    -8.900    -2.300  
+89 718 47725.00 I   .258280  .000782   .318751  .000522  I -.3985792  .0000502  0.7964 0.0344  I   -10.059     .627    -2.055     .378   .258000   .319100  -.3986800    -9.200    -2.100  
+89 719 47726.00 I   .258834  .000604   .316059  .000495  I -.3994760  .0000460  1.0108 0.0293  I    -9.743     .691    -2.295     .409   .258500   .316200  -.3995800    -9.600    -2.000  
+89 720 47727.00 I   .259242  .000486   .313273  .000520  I -.4006205  .0000303  1.2842 0.0349  I    -9.567     .498    -2.371     .342   .258900   .313200  -.4007400   -10.000    -1.900  
+89 721 47728.00 I   .259520  .000908   .310377  .000880  I -.4020440  .0000525  1.5564 0.0353  I    -9.661     .293    -2.255     .219   .259300   .310100  -.4022100   -10.300    -1.900  
+89 722 47729.00 I   .259677  .000894   .307373  .000812  I -.4037092  .0000637  1.7563 0.0489  I   -10.131     .282    -2.180     .200   .259700   .307100  -.4039200   -10.600    -1.900  
+89 723 47730.00 I   .259721  .001211   .304260  .000887  I -.4055103  .0000825  1.8174 0.0466  I   -10.909     .393    -2.338     .217   .260100   .304000  -.4057500   -10.800    -2.000  
+89 724 47731.00 I   .259656  .000970   .301045  .000750  I -.4072883  .0000681  1.7115 0.0525  I   -11.646     .377    -2.566     .271   .260500   .300900  -.4075500   -10.900    -2.200  
+89 725 47732.00 I   .259516  .000946   .297755  .000746  I -.4088916  .0000651  1.4806 0.0491  I   -11.967     .366    -2.561     .236   .260800   .297800  -.4092000   -11.000    -2.400  
+89 726 47733.00 I   .259411  .001136   .294397  .000786  I -.4102297  .0000707  1.1904 0.0446  I   -11.822     .385    -2.305     .239   .261100   .294700  -.4105700   -10.900    -2.700  
+89 727 47734.00 I   .259400  .000986   .290980  .000721  I -.4112703  .0000611  0.8938 0.0445  I   -11.589     .385    -2.280     .239   .261200   .291500  -.4116300   -10.600    -2.900  
+89 728 47735.00 I   .259475  .000723   .287550  .000526  I -.4120367  .0000542  0.6553 0.0393  I   -11.568     .388    -2.484     .237   .261100   .288400  -.4122900    -9.900    -3.000  
+89 729 47736.00 I   .259578  .000669   .284153  .000535  I -.4126159  .0000494  0.5217 0.0352  I   -11.665     .354    -2.690     .219   .260900   .285300  -.4127600    -9.100    -3.100  
+89 730 47737.00 I   .259598  .000484   .280826  .000480  I -.4131170  .0000450  0.4987 0.0344  I   -11.771     .511    -2.791     .186   .260600   .282100  -.4131300    -8.200    -3.200  
+89 731 47738.00 I   .259486  .000634   .277618  .000540  I -.4136479  .0000480  0.5794 0.0323  I   -11.868     .698    -2.721     .190   .260300   .279000  -.4135600    -7.400    -3.200  
+89 8 1 47739.00 I   .259283  .000634   .274517  .000420  I -.4142997  .0000463  0.7317 0.0332  I   -11.954     .669    -2.494     .214   .259900   .275800  -.4141200    -6.700    -3.200  
+89 8 2 47740.00 I   .259062  .000597   .271488  .000399  I -.4151187  .0000459  0.9060 0.0260  I   -12.066     .676    -2.239     .205   .259600   .272500  -.4149900    -7.500    -3.000  
+89 8 3 47741.00 I   .258932  .000620   .268482  .000316  I -.4161049  .0000237  1.0598 0.0310  I   -12.031     .841    -2.043     .205   .259400   .269200  -.4160500    -7.300    -2.900  
+89 8 4 47742.00 I   .258981  .000616   .265471  .000322  I -.4172229  .0000416  1.1673 0.0267  I   -11.897     .748    -1.859     .207   .259300   .266000  -.4172400    -7.300    -2.800  
+89 8 5 47743.00 I   .259177  .000731   .262452  .000384  I -.4184194  .0000478  1.2146 0.0319  I   -11.788     .744    -1.900     .188   .259200   .262800  -.4185100    -7.500    -2.700  
+89 8 6 47744.00 I   .259382  .000731   .259419  .000385  I -.4196321  .0000485  1.2021 0.0362  I   -11.989     .629    -2.102     .241   .259200   .259600  -.4197900    -7.800    -2.600  
+89 8 7 47745.00 I   .259502  .000828   .256372  .000395  I -.4208062  .0000544  1.1375 0.0354  I   -12.279     .657    -2.116     .247   .259300   .256400  -.4210000    -8.900    -2.900  
+89 8 8 47746.00 I   .259528  .000722   .253308  .000518  I -.4218918  .0000515  1.0269 0.0373  I   -12.396     .670    -2.014     .240   .259400   .253200  -.4220600   -10.100    -3.100  
+89 8 9 47747.00 I   .259514  .000757   .250247  .000530  I -.4228527  .0000511  0.8944 0.0341  I   -12.372     .605    -2.120     .206   .259400   .250000  -.4229700   -11.300    -3.400  
+89 810 47748.00 I   .259562  .000817   .247205  .000590  I -.4236824  .0000446  0.7671 0.0338  I   -12.374     .669    -2.245     .203   .259500   .246800  -.4237400   -12.500    -3.600  
+89 811 47749.00 I   .259708  .000849   .244204  .000586  I -.4243916  .0000444  0.6537 0.0316  I   -12.301     .669    -2.371     .203   .259500   .243700  -.4243800   -13.400    -3.800  
+89 812 47750.00 I   .259841  .000805   .241279  .000562  I -.4250039  .0000449  0.5826 0.0295  I   -12.112     .730    -2.497     .135   .259400   .240800  -.4250300   -13.400    -3.500  
+89 813 47751.00 I   .259861  .000719   .238419  .000647  I -.4255850  .0000389  0.5960 0.0259  I   -11.765     .778    -2.541     .298   .259300   .237900  -.4256300   -13.100    -3.200  
+89 814 47752.00 I   .259701  .000415   .235585  .000673  I -.4262314  .0000259  0.7159 0.0272  I   -11.373     .641    -2.544     .227   .259000   .235100  -.4263200   -12.700    -2.800  
+89 815 47753.00 I   .259331  .000494   .232721  .000665  I -.4270534  .0000381  0.9455 0.0218  I   -11.104     .357    -2.612     .348   .258700   .232200  -.4271700   -12.200    -2.500  
+89 816 47754.00 I   .258722  .000486   .229769  .000628  I -.4281495  .0000351  1.2563 0.0259  I   -11.035     .295    -2.702     .294   .258400   .229400  -.4283300   -11.500    -2.200  
+89 817 47755.00 I   .257874  .000486   .226673  .000628  I -.4295740  .0000351  1.5911 0.0245  I   -11.202     .295    -2.649     .294   .257800   .226300  -.4297400   -11.900    -2.100  
+89 818 47756.00 I   .256866  .000490   .223437  .000609  I -.4313153  .0000343  1.8766 0.0252  I   -11.658     .295    -2.397     .294   .257200   .223000  -.4314600   -12.300    -2.100  
+89 819 47757.00 I   .255786  .000452   .220100  .000549  I -.4332828  .0000361  2.0288 0.0319  I   -12.438     .470    -2.064     .245   .256500   .219700  -.4333800   -12.900    -2.100  
+89 820 47758.00 I   .254697  .000638   .216697  .000322  I -.4353113  .0000539  1.9962 0.0327  I   -13.390     .534    -1.855     .130   .255700   .216300  -.4353500   -13.400    -2.200  
+89 821 47759.00 I   .253687  .000638   .213255  .000322  I -.4372182  .0000545  1.7926 0.0320  I   -14.183     .803    -1.884     .150   .255000   .213000  -.4372000   -13.900    -2.300  
+89 822 47760.00 I   .252831  .000521   .209803  .000354  I -.4388607  .0000345  1.4816 0.0301  I   -14.540     .923    -2.158     .168   .254100   .209600  -.4389300   -14.000    -2.400  
+89 823 47761.00 I   .252154  .000387   .206380  .000337  I -.4401749  .0000255  1.1511 0.0200  I   -14.651    1.210    -2.453     .148   .253200   .206300  -.4403400   -14.000    -2.600  
+89 824 47762.00 I   .251620  .000324   .203035  .000545  I -.4411822  .0000201  0.8783 0.0146  I   -14.908    1.186    -2.502     .145   .252400   .203000  -.4414600   -13.900    -2.700  
+89 825 47763.00 I   .251154  .000291   .199820  .000563  I -.4419658  .0000141  0.7083 0.0124  I   -15.105    1.383    -2.373     .141   .251500   .199900  -.4423900   -13.700    -2.800  
+89 826 47764.00 I   .250680  .000298   .196789  .000599  I -.4426360  .0000144  0.6499 0.0099  I   -14.867    1.383    -2.227     .141   .250600   .196800  -.4431800   -13.400    -2.800  
+89 827 47765.00 I   .250131  .000245   .193995  .000550  I -.4433011  .0000138  0.6978 0.0098  I   -14.528    1.401    -2.188     .116   .250000   .193900  -.4436700   -12.800    -2.600  
+89 828 47766.00 I   .249428  .000225   .191364  .000552  I -.4440612  .0000133  0.8344 0.0114  I   -14.207    1.221    -2.234     .103   .249300   .191100  -.4442400   -12.100    -2.300  
+89 829 47767.00 I   .248493  .000286   .188770  .000646  I -.4449861  .0000181  1.0198 0.0146  I   -13.819     .848    -2.244     .211   .248500   .188300  -.4449600   -11.500    -2.000  
+89 830 47768.00 I   .247289  .000392   .186106  .000636  I -.4461029  .0000259  1.2117 0.0165  I   -13.393     .548    -2.093     .234   .247600   .185500  -.4458700   -11.000    -1.600  
+89 831 47769.00 I   .245810  .000498   .183287  .000599  I -.4473984  .0000277  1.3703 0.0191  I   -12.986     .548    -1.746     .234   .246500   .182700  -.4469500   -10.600    -1.300  
+89 9 1 47770.00 I   .244066  .000452   .180279  .000594  I -.4488220  .0000281  1.4642 0.0214  I   -12.682     .548    -1.276     .234   .245000   .179700  -.4486000   -11.100    -1.300  
+89 9 2 47771.00 I   .242130  .000406   .177130  .000535  I -.4502998  .0000326  1.4770 0.0194  I   -12.674     .548    -1.056     .234   .243300   .176800  -.4503200   -11.700    -1.300  
+89 9 3 47772.00 I   .240098  .000386   .173910  .000496  I -.4517486  .0000268  1.4078 0.0217  I   -12.995     .844    -1.235     .264   .241400   .173700  -.4520100   -12.500    -1.300  
+89 9 4 47773.00 I   .238027  .000377   .170686  .000460  I -.4530928  .0000287  1.2710 0.0196  I   -13.447     .935    -1.600     .237   .239400   .170700  -.4536000   -13.200    -1.400  
+89 9 5 47774.00 I   .235922  .000394   .167512  .000460  I -.4542755  .0000286  1.0890 0.0204  I   -13.798    1.091    -1.912     .262   .237200   .167600  -.4550100   -14.000    -1.600  
+89 9 6 47775.00 I   .233773  .000351   .164445  .000454  I -.4552687  .0000289  0.9007 0.0193  I   -13.998     .905    -2.114     .221   .234900   .164200  -.4556800   -15.200    -2.200  
+89 9 7 47776.00 I   .231549  .000317   .161528  .000413  I -.4560882  .0000259  0.7462 0.0183  I   -14.180     .905    -2.328     .221   .232600   .161100  -.4563700   -15.200    -2.400  
+89 9 8 47777.00 I   .229223  .000308   .158754  .000324  I -.4567806  .0000223  0.6502 0.0185  I   -14.405     .796    -2.593     .269   .230100   .158100  -.4569300   -15.000    -2.600  
+89 9 9 47778.00 I   .226787  .000375   .156103  .000387  I -.4574131  .0000264  0.6277 0.0173  I   -14.475     .589    -2.758     .248   .227600   .155200  -.4574300   -14.700    -2.800  
+89 910 47779.00 I   .224295  .000366   .153554  .000153  I -.4580653  .0000264  0.6930 0.0192  I   -14.179     .589    -2.633     .248   .225000   .152400  -.4579600   -14.200    -2.900  
+89 911 47780.00 I   .221831  .000366   .151091  .000153  I -.4588307  .0000279  0.8530 0.0191  I   -13.567     .589    -2.263     .248   .222500   .149900  -.4587600   -13.600    -2.700  
+89 912 47781.00 I   .219415  .000387   .148691  .000149  I -.4598036  .0000277  1.1098 0.0200  I   -13.092     .668    -2.005     .282   .220000   .147500  -.4597900   -12.900    -2.500  
+89 913 47782.00 I   .217025  .000383   .146348  .000175  I -.4610755  .0000288  1.4420 0.0201  I   -12.949     .553    -1.963     .247   .217400   .145200  -.4611000   -12.200    -2.300  
+89 914 47783.00 I   .214648  .000358   .144057  .000175  I -.4626902  .0000291  1.7819 0.0242  I   -13.034     .519    -1.931     .171   .214900   .142900  -.4627700   -11.500    -2.100  
+89 915 47784.00 I   .212275  .000396   .141805  .000200  I -.4646152  .0000390  2.0496 0.0254  I   -13.265     .378    -1.787     .162   .212400   .140700  -.4647300   -11.000    -2.000  
+89 916 47785.00 I   .209901  .000396   .139576  .000356  I -.4667389  .0000416  2.1657 0.0260  I   -13.568     .393    -1.646     .142   .210100   .138600  -.4669400   -11.000    -2.200  
+89 917 47786.00 I   .207490  .000373   .137349  .000325  I -.4688831  .0000345  2.0914 0.0253  I   -13.888     .393    -1.689     .142   .207900   .136500  -.4691500   -11.200    -2.400  
+89 918 47787.00 I   .205003  .000316   .135107  .000362  I -.4708694  .0000287  1.8601 0.0216  I   -14.181     .355    -1.879     .136   .205500   .134400  -.4711900   -11.400    -2.700  
+89 919 47788.00 I   .202444  .000251   .132834  .000371  I -.4725772  .0000261  1.5504 0.0187  I   -14.344     .355    -1.963     .124   .203100   .132300  -.4729500   -11.600    -2.900  
+89 920 47789.00 I   .199818  .000251   .130546  .000371  I -.4739759  .0000239  1.2579 0.0191  I   -14.445     .355    -1.837     .124   .200600   .130100  -.4744000   -11.800    -3.200  
+89 921 47790.00 I   .197123  .000319   .128280  .000439  I -.4751244  .0000278  1.0597 0.0284  I   -14.505     .316    -1.616     .134   .197800   .127600  -.4754200   -11.800    -3.200  
+89 922 47791.00 I   .194319  .000297   .126036  .000344  I -.4761386  .0000516  0.9913 0.0251  I   -14.337     .265    -1.591     .152   .194800   .125000  -.4763200   -11.700    -3.200  
+89 923 47792.00 I   .191399  .000266   .123797  .000303  I -.4771475  .0000419  1.0444 0.0353  I   -13.938     .220    -1.739     .120   .191800   .122400  -.4772200   -11.500    -3.100  
+89 924 47793.00 I   .188364  .000246   .121549  .000236  I -.4782554  .0000482  1.1815 0.0320  I   -13.522     .182    -1.829     .117   .188700   .119800  -.4782300   -11.400    -3.000  
+89 925 47794.00 I   .185238  .000284   .119268  .000272  I -.4795257  .0000484  1.3642 0.0348  I   -13.256     .707    -1.784     .118   .185500   .117200  -.4794200   -11.300    -2.800  
+89 926 47795.00 I   .182078  .000284   .116925  .000272  I -.4809871  .0000502  1.5569 0.0329  I   -13.175    1.094    -1.648     .156   .182400   .115100  -.4809700   -11.400    -2.500  
+89 927 47796.00 I   .178927  .000390   .114535  .000361  I -.4826303  .0000446  1.7222 0.0270  I   -13.275    1.094    -1.498     .156   .179300   .113000  -.4827000   -11.500    -2.100  
+89 928 47797.00 I   .175801  .000368   .112143  .000429  I -.4844125  .0000201  1.8305 0.0259  I   -13.537     .945    -1.356     .185   .176100   .111000  -.4845500   -11.600    -1.800  
+89 929 47798.00 I   .172692  .000468   .109843  .000496  I -.4862662  .0000263  1.8634 0.0166  I   -13.477    1.159    -1.040     .228   .172900   .109100  -.4864500   -11.800    -1.500  
+89 930 47799.00 I   .169578  .000468   .107752  .000496  I -.4881118  .0000263  1.8137 0.0197  I   -13.140    1.159     -.722     .228   .169700   .107400  -.4883400   -11.900    -1.400  
+8910 1 47800.00 I   .166400  .000509   .105964  .000653  I -.4898709  .0000293  1.6959 0.0161  I   -12.924    1.135     -.700     .234   .166600   .105800  -.4901000   -12.000    -1.500  
+8910 2 47801.00 I   .163140  .000422   .104437  .000609  I -.4914920  .0000185  1.5432 0.0162  I   -12.882     .550     -.934     .228   .163500   .104400  -.4917400   -12.000    -1.700  
+8910 3 47802.00 I   .159817  .000270   .103076  .000633  I -.4929552  .0000137  1.3843 0.0128  I   -12.851     .708    -1.204     .213   .160300   .103000  -.4932500   -12.000    -2.000  
+8910 4 47803.00 I   .156445  .000252   .101784  .000556  I -.4942671  .0000178  1.2450 0.0139  I   -12.770     .899    -1.428     .236   .157100   .101700  -.4946200   -12.000    -2.300  
+8910 5 47804.00 I   .153030  .000252   .100460  .000556  I -.4954603  .0000241  1.1512 0.0132  I   -12.802     .899    -1.725     .236   .153800   .100400  -.4958600   -11.900    -2.600  
+8910 6 47805.00 I   .149568  .000402   .099020  .000503  I -.4965907  .0000195  1.1212 0.0160  I   -13.131     .899    -2.168     .236   .150400   .099000  -.4968500   -11.200    -2.500  
+8910 7 47806.00 I   .146082  .000354   .097493  .000528  I -.4977285  .0000210  1.1686 0.0135  I   -13.389     .792    -2.349     .220   .146900   .097700  -.4978400   -10.800    -2.500  
+8910 8 47807.00 I   .142608  .000362   .095962  .000444  I -.4989574  .0000186  1.3043 0.0151  I   -13.249     .652    -2.073     .181   .143300   .096400  -.4988900   -10.500    -2.400  
+8910 9 47808.00 I   .139183  .000446   .094510  .000395  I -.5003659  .0000216  1.5263 0.0136  I   -12.736     .686    -1.633     .163   .139600   .095100  -.5001200   -10.200    -2.400  
+891010 47809.00 I   .135807  .000444   .093205  .000369  I -.5020325  .0000198  1.8157 0.0136  I   -12.048     .518    -1.419     .221   .135800   .093800  -.5016400   -10.000    -2.300  
+891011 47810.00 I   .132325  .000444   .092049  .000369  I -.5040085  .0000164  2.1387 0.0129  I   -11.547     .488    -1.452     .214   .131900   .092500  -.5037300   -10.200    -2.200  
+891012 47811.00 I   .128573  .000497   .090993  .000385  I -.5062987  .0000164  2.4280 0.0149  I   -11.609     .488    -1.575     .214   .127900   .091200  -.5062100   -10.400    -2.200  
+891013 47812.00 I   .124506  .000547   .089968  .000309  I -.5088255  .0000250  2.6002 0.0158  I   -12.103     .532    -1.596     .195   .123800   .090000  -.5089400   -10.700    -2.100  
+891014 47813.00 I   .120219  .000588   .088938  .000320  I -.5114430  .0000271  2.6042 0.0170  I   -12.606     .566    -1.465     .211   .119600   .088700  -.5117600   -11.000    -2.100  
+891015 47814.00 I   .115844  .000507   .087877  .000279  I -.5139777  .0000231  2.4397 0.0174  I   -12.726     .382    -1.359     .208   .115400   .087500  -.5145000   -11.200    -2.000  
+891016 47815.00 I   .111554  .000468   .086777  .000314  I -.5162918  .0000217  2.1835 0.0164  I   -12.292     .384    -1.330     .298   .111300   .086400  -.5167800   -10.800    -2.000  
+891017 47816.00 I   .107593  .000476   .085697  .000346  I -.5183447  .0000232  1.9273 0.0158  I   -11.657     .390    -1.269     .298   .107300   .085300  -.5187500   -10.400    -2.000  
+891018 47817.00 I   .103907  .000457   .084674  .000484  I -.5201702  .0000229  1.7425 0.0149  I   -11.310     .359    -1.163     .105   .103300   .084300  -.5204900   -10.000    -2.000  
+891019 47818.00 I   .100289  .000445   .083678  .000499  I -.5218716  .0000188  1.6835 0.0143  I   -11.338     .244    -1.147     .110   .099300   .083200  -.5220800    -9.700    -2.000  
+891020 47819.00 I   .096530  .000279   .082687  .000513  I -.5235770  .0000170  1.7439 0.0153  I   -11.348     .268    -1.336     .115   .095500   .082100  -.5236700    -9.500    -1.900  
+891021 47820.00 I   .092643  .000369   .081623  .000515  I -.5253861  .0000241  1.8844 0.0145  I   -11.157     .284    -1.486     .116   .091800   .081100  -.5255000    -9.900    -1.700  
+891022 47821.00 I   .088758  .000374   .080515  .000566  I -.5273585  .0000235  2.0628 0.0168  I   -10.927     .238    -1.355     .125   .088200   .080000  -.5275000   -10.400    -1.500  
+891023 47822.00 I   .084999  .000329   .079469  .000494  I -.5295096  .0000234  2.2347 0.0170  I   -10.805     .206    -1.037     .181   .084600   .079100  -.5296700   -11.000    -1.300  
+891024 47823.00 I   .081461  .000323   .078569  .000341  I -.5318132  .0000245  2.3625 0.0158  I   -10.745     .225     -.752     .177   .081100   .078200  -.5319700   -11.600    -1.100  
+891025 47824.00 I   .078112  .000322   .077817  .000292  I -.5342076  .0000211  2.4094 0.0152  I   -10.569     .255     -.451     .166   .077600   .077400  -.5343600   -12.100     -.900  
+891026 47825.00 I   .074806  .000300   .077207  .000274  I -.5366070  .0000179  2.3813 0.0140  I   -10.252     .232     -.166     .164   .074300   .076900  -.5368100   -12.300     -.900  
+891027 47826.00 I   .071438  .000306   .076761  .000328  I -.5389626  .0000183  2.3303 0.0112  I   -10.005     .234      .038     .163   .071000   .076500  -.5392300   -12.400    -1.000  
+891028 47827.00 I   .068006  .000271   .076490  .000386  I -.5412601  .0000133  2.2569 0.0106  I    -9.895     .464      .103     .155   .067700   .076300  -.5415600   -12.300    -1.000  
+891029 47828.00 I   .064380  .000308   .076301  .000407  I -.5434609  .0000108  2.1370 0.0089  I    -9.975     .578     -.046     .273   .064400   .076100  -.5437800   -12.200    -1.100  
+891030 47829.00 I   .060604  .000303   .076052  .000429  I -.5455241  .0000118  1.9871 0.0088  I   -10.292     .563     -.433     .278   .061100   .076000  -.5458500   -12.000    -1.200  
+891031 47830.00 I   .056867  .000350   .075662  .000435  I -.5474344  .0000140  1.8353 0.0098  I   -10.684     .592     -.863     .288   .057500   .075700  -.5476900   -11.600    -1.200  
+8911 1 47831.00 I   .053306  .000363   .075251  .000472  I -.5492010  .0000157  1.7025 0.0110  I   -10.804     .632    -1.026     .305   .053800   .075500  -.5493800   -11.100    -1.200  
+8911 2 47832.00 I   .049948  .000386   .074957  .000480  I -.5508516  .0000171  1.6062 0.0128  I   -10.512     .743     -.958     .291   .050100   .075200  -.5510000   -10.600    -1.200  
+8911 3 47833.00 I   .046609  .000392   .074778  .000318  I -.5524322  .0000202  1.5664 0.0146  I    -9.907     .720     -.740     .337   .046300   .074900  -.5525700    -9.900    -1.200  
+8911 4 47834.00 I   .043062  .000444   .074689  .000334  I -.5540111  .0000237  1.6066 0.0194  I    -9.335     .658     -.504     .160   .042500   .074600  -.5541900    -9.300    -1.200  
+8911 5 47835.00 I   .039172  .000518   .074657  .000191  I -.5556779  .0000332  1.7444 0.0195  I    -9.139     .676     -.445     .164   .039800   .074600  -.5558600    -8.700    -1.300  
+8911 6 47836.00 I   .034976  .000518   .074651  .000167  I -.5575302  .0000310  1.9733 0.0213  I    -9.190     .625     -.484     .182   .035900   .074300  -.5577500    -8.100    -1.300  
+8911 7 47837.00 I   .030594  .000393   .074651  .000184  I -.5596418  .0000268  2.2541 0.0231  I    -9.193     .687     -.478     .185   .031900   .074100  -.5599000    -7.400    -1.200  
+8911 8 47838.00 I   .026170  .000454   .074658  .000210  I -.5620377  .0000342  2.5326 0.0217  I    -9.015     .559     -.393     .180   .027900   .074000  -.5623200    -7.000    -1.100  
+8911 9 47839.00 I   .021873  .000578   .074685  .000208  I -.5646849  .0000342  2.7446 0.0254  I    -8.806     .559     -.334     .180   .023800   .074000  -.5649700    -6.500    -2.000  
+891110 47840.00 I   .017774  .000609   .074750  .000182  I -.5674802  .0000376  2.8164 0.0235  I    -8.863     .592     -.142     .189   .019800   .074100  -.5676900    -6.100    -2.100  
+891111 47841.00 I   .013797  .000633   .074867  .000178  I -.5702598  .0000323  2.7145 0.0225  I    -8.961     .723      .032     .220   .015700   .074400  -.5703800    -5.600    -2.200  
+891112 47842.00 I   .009853  .000591   .075052  .000151  I -.5728625  .0000248  2.4723 0.0212  I    -8.674     .758     -.059     .190   .011800   .074600  -.5728800    -5.200    -2.300  
+891113 47843.00 I   .005935  .000679   .075329  .000172  I -.5751842  .0000275  2.1693 0.0181  I    -7.872     .736     -.305     .189   .007900   .075000  -.5751000    -4.700    -2.200  
+891114 47844.00 I   .002118  .000716   .075723  .000189  I -.5772119  .0000265  1.8987 0.0178  I    -7.039     .773     -.195     .205   .004000   .075500  -.5770200    -4.300    -2.100  
+891115 47845.00 I  -.001536  .000698   .076257  .000225  I -.5790178  .0000227  1.7369 0.0166  I    -6.495     .833      .191     .200   .000400   .076000  -.5789500    -4.300    -1.900  
+891116 47846.00 I  -.005052  .000581   .076920  .000233  I -.5807332  .0000201  1.7178 0.0135  I    -6.337     .845      .431     .226  -.003100   .076600  -.5807900    -4.300    -1.700  
+891117 47847.00 I  -.008515  .000551   .077690  .000217  I -.5824945  .0000148  1.8219 0.0124  I    -6.434     .799      .300     .194  -.006600   .077300  -.5826900    -4.300    -1.600  
+891118 47848.00 I  -.011982  .000491   .078552  .000268  I -.5844024  .0000145  2.0021 0.0103  I    -6.643     .824     -.055     .197  -.010200   .078100  -.5847500    -4.400    -1.400  
+891119 47849.00 I  -.015443  .000478   .079520  .000323  I -.5865052  .0000144  2.2017 0.0103  I    -6.754     .824     -.067     .197  -.013700   .079000  -.5870000    -4.400    -1.300  
+891120 47850.00 I  -.018894  .000546   .080613  .000361  I -.5887973  .0000145  2.3757 0.0105  I    -6.776     .755      .284     .194  -.017400   .080300  -.5891500    -4.600    -1.200  
+891121 47851.00 I  -.022304  .000489   .081830  .000332  I -.5912393  .0000153  2.4979 0.0104  I    -6.885     .669      .718     .198  -.021200   .081600  -.5914300    -4.900    -1.100  
+891122 47852.00 I  -.025738  .000438   .083181  .000273  I -.5937721  .0000148  2.5570 0.0123  I    -6.957     .560      .939     .169  -.025100   .083100  -.5938300    -5.100    -1.000  
+891123 47853.00 I  -.029284  .000501   .084672  .000215  I -.5963324  .0000192  2.5534 0.0120  I    -6.907     .357      .842     .163  -.028900   .084500  -.5962600    -5.300    -1.000  
+891124 47854.00 I  -.032975  .000393   .086275  .000230  I -.5988612  .0000189  2.4967 0.0136  I    -6.854     .117      .687     .164  -.032900   .086100  -.5986900    -5.400    -1.100  
+891125 47855.00 I  -.036766  .000393   .087923  .000230  I -.6013089  .0000192  2.3894 0.0140  I    -6.879     .117      .709     .164  -.036700   .087500  -.6012100    -5.400    -1.200  
+891126 47856.00 I  -.040644  .000344   .089531  .000183  I -.6036224  .0000206  2.2295 0.0129  I    -6.941     .125      .758     .161  -.040400   .088800  -.6036100    -5.400    -1.300  
+891127 47857.00 I  -.044621  .000327   .091021  .000211  I -.6057624  .0000171  2.0531 0.0149  I    -6.964     .135      .658     .127  -.044100   .090200  -.6058300    -5.400    -1.400  
+891128 47858.00 I  -.048622  .000347   .092360  .000242  I -.6077381  .0000215  1.9050 0.0139  I    -6.926     .152      .529     .298  -.047700   .091400  -.6078900    -5.200    -1.600  
+891129 47859.00 I  -.052504  .000357   .093533  .000237  I -.6095892  .0000219  1.8071 0.0171  I    -6.771     .152      .530     .298  -.051200   .092700  -.6098000    -5.000    -1.600  
+891130 47860.00 I  -.056142  .000428   .094538  .000440  I -.6113724  .0000266  1.7693 0.0173  I    -6.457     .149      .638     .298  -.054600   .093900  -.6115700    -4.600    -1.600  
+8912 1 47861.00 I  -.059499  .000363   .095445  .000369  I -.6131492  .0000269  1.7957 0.0174  I    -6.052     .149      .723     .298  -.057800   .095100  -.6133100    -4.100    -1.500  
+8912 2 47862.00 I  -.062559  .000340   .096349  .000367  I -.6149856  .0000224  1.8873 0.0178  I    -5.744     .233      .715     .298  -.060800   .096300  -.6150900    -3.700    -1.300  
+8912 3 47863.00 I  -.065327  .000277   .097344  .000301  I -.6169418  .0000233  2.0327 0.0204  I    -5.673     .284      .678     .298  -.063700   .097700  -.6169800    -3.300    -1.200  
+8912 4 47864.00 I  -.067830  .000277   .098522  .000301  I -.6190600  .0000340  2.2052 0.0242  I    -5.830     .284      .730     .298  -.066400   .099100  -.6190500    -3.100    -1.100  
+8912 5 47865.00 I  -.070117  .000385   .099965  .000330  I -.6213521  .0000424  2.3776 0.0308  I    -6.112     .284      .942     .298  -.069000   .100400  -.6214400    -2.800     -.500  
+8912 6 47866.00 I  -.072305  .000385   .101669  .000330  I -.6238043  .0000513  2.5173 0.0341  I    -6.361     .284     1.201     .298  -.071500   .102000  -.6238700    -3.700     -.200  
+8912 7 47867.00 I  -.074486  .000385   .103589  .000330  I -.6263590  .0000533  2.5740 0.0810  I    -6.593     .284     1.458     .298  -.074000   .103700  -.6264000    -4.700      .100  
+8912 8 47868.00 I  -.076739  .000748   .105674  .000318  I -.6289126  .0001537  2.5115 0.1026  I    -6.927     .259     1.700     .298  -.076500   .105600  -.6289500    -5.600      .000  
+8912 9 47869.00 I  -.079122  .001151   .107881  .000538  I -.6313409  .0001982  2.3258 0.0780  I    -7.324     .791     1.798     .298  -.078900   .107700  -.6313800    -6.100     -.100  
+891210 47870.00 I  -.081630  .000396   .110183  .000207  I -.6335356  .0000265  2.0544 0.0997  I    -7.520     .791     1.614     .298  -.081300   .109900  -.6335700    -6.400     -.300  
+891211 47871.00 I  -.084241  .000334   .112555  .000231  I -.6354462  .0000226  1.7725 0.0157  I    -7.271     .140     1.201     .298  -.083700   .112300  -.6354900    -6.200     -.500  
+891212 47872.00 I  -.086932  .000342   .114974  .000227  I -.6371037  .0000169  1.5598 0.0133  I    -6.656     .279      .818     .298  -.086200   .114800  -.6371500    -5.400     -.800  
+891213 47873.00 I  -.089614  .000342   .117435  .000227  I -.6386064  .0000140  1.4687 0.0090  I    -6.017     .279      .674     .298  -.088800   .117400  -.6386400    -4.300     -.900  
+891214 47874.00 I  -.092151  .000363   .119956  .000221  I -.6400823  .0000062  1.5010 0.0080  I    -5.577     .279      .722     .298  -.091100   .120000  -.6401300    -3.100     -.900  
+891215 47875.00 I  -.094464  .000259   .122557  .000174  I -.6416399  .0000077  1.6278 0.0054  I    -5.311     .279      .809     .298  -.093500   .122400  -.6416800    -1.900    -1.000  
+891216 47876.00 I  -.096596  .000223   .125204  .000155  I -.6433545  .0000088  1.8045 0.0069  I    -5.099     .310      .845     .298  -.095800   .125200  -.6434200    -1.100     -.900  
+891217 47877.00 I  -.098647  .000279   .127845  .000160  I -.6452473  .0000114  1.9764 0.0074  I    -4.999     .393      .886     .298  -.098100   .127800  -.6453100     -.600     -.800  
+891218 47878.00 I  -.100700  .000272   .130424  .000132  I -.6472936  .0000118  2.1073 0.0084  I    -5.115     .388      .980     .298  -.100200   .130300  -.6473600     -.700     -.600  
+891219 47879.00 I  -.102791  .000265   .132890  .000156  I -.6494431  .0000124  2.1818 0.0085  I    -5.335     .388     1.034     .298  -.102300   .132800  -.6495200    -1.100     -.500  
+891220 47880.00 I  -.104932  .000269   .135228  .000159  I -.6516350  .0000121  2.1897 0.0084  I    -5.551     .462      .928     .298  -.104300   .135100  -.6517000    -1.600     -.200  
+891221 47881.00 I  -.107038  .000272   .137530  .000155  I -.6537996  .0000112  2.1290 0.0083  I    -5.702     .473      .781     .132  -.106300   .137500  -.6538500    -2.200     -.100  
+891222 47882.00 I  -.109166  .000279   .139802  .000156  I -.6558744  .0000114  2.0126 0.0086  I    -5.778     .483      .770     .140  -.108600   .139700  -.6559100    -2.800     -.100  
+891223 47883.00 I  -.111425  .000358   .142033  .000182  I -.6578097  .0000130  1.8511 0.0103  I    -5.733     .518      .914     .169  -.110900   .141800  -.6578200    -3.200     -.300  
+891224 47884.00 I  -.113908  .000348   .144250  .000249  I -.6595674  .0000171  1.6621 0.0106  I    -5.662     .586      .990     .192  -.113200   .144100  -.6595900    -3.200     -.500  
+891225 47885.00 I  -.116617  .000342   .146490  .000244  I -.6611365  .0000168  1.4811 0.0106  I    -5.698     .586      .868     .192  -.115800   .146300  -.6611500    -3.300     -.800  
+891226 47886.00 I  -.119446  .000328   .148785  .000110  I -.6625434  .0000126  1.3417 0.0115  I    -5.835     .425      .701     .185  -.118400   .148800  -.6625900    -3.100     -.900  
+891227 47887.00 I  -.122271  .000358   .151162  .000239  I -.6638408  .0000157  1.2651 0.0092  I    -6.002     .159      .667     .170  -.120900   .151100  -.6639200    -2.800     -.800  
+891228 47888.00 I  -.124968  .000349   .153651  .000260  I -.6650994  .0000134  1.2657 0.0111  I    -6.036     .159      .809     .170  -.123500   .153800  -.6651700    -2.300     -.700  
+891229 47889.00 I  -.127413  .000349   .156281  .000260  I -.6663989  .0000158  1.3462 0.0104  I    -5.836     .159     1.041     .170  -.126200   .156700  -.6664800    -1.900     -.500  
+891230 47890.00 I  -.129524  .000349   .159074  .000260  I -.6678172  .0000158  1.5028 0.0101  I    -5.536     .159     1.174     .170  -.128600   .159700  -.6679000    -1.600     -.300  
+891231 47891.00 I  -.131349  .000268   .161999  .000202  I -.6694241  .0000127  1.7184 0.0109  I    -5.317     .159     1.154     .170  -.130600   .162500  -.6695100    -1.700     -.200  
+90 1 1 47892.00 I  -.132974  .000234   .164998  .000286  I  .3287404  .0000150  1.9510 0.0105  I    -5.258     .217     1.052     .144  -.132500   .165300   .3286400    -2.100     -.100  
+90 1 2 47893.00 I  -.134485  .000173   .168017  .000291  I  .3266860  .0000168  2.1474 0.0120  I    -5.325     .268      .955     .298  -.134100   .168000   .3265900    -2.700     -.100  
+90 1 3 47894.00 I  -.135970  .000173   .170997  .000291  I  .3244717  .0000188  2.2655 0.0135  I    -5.434     .268      .921     .298  -.135500   .170600   .3243500    -3.500     -.100  
+90 1 4 47895.00 I  -.137516  .000173   .173884  .000291  I  .3221932  .0000211  2.2691 0.0131  I    -5.532     .268      .960     .298  -.136800   .173400   .3221100    -4.500     1.000  
+90 1 5 47896.00 I  -.139181  .000210   .176642  .000295  I  .3199771  .0000182  2.1420 0.0139  I    -5.645     .268     1.037     .298  -.138200   .176000   .3199100    -6.100      .400  
+90 1 6 47897.00 I  -.140984  .000214   .179271  .000312  I  .3179432  .0000180  1.9131 0.0136  I    -5.798     .588     1.083     .127  -.139900   .178800   .3178800    -6.300      .000  
+90 1 7 47898.00 I  -.142938  .000344   .181783  .000529  I  .3161659  .0000203  1.6394 0.0135  I    -5.935     .787     1.027     .172  -.141800   .181300   .3160700    -5.300    -1.100  
+90 1 8 47899.00 I  -.145050  .000368   .184190  .000570  I  .3146584  .0000201  1.3838 0.0137  I    -5.982     .648      .875     .144  -.143800   .183400   .3146100    -3.200    -1.500  
+90 1 9 47900.00 I  -.147283  .000368   .186517  .000570  I  .3133695  .0000185  1.2147 0.0129  I    -5.952     .677      .752     .127  -.146100   .185800   .3133200    -2.100    -2.000  
+90 110 47901.00 I  -.149527  .000376   .188891  .000491  I  .3121848  .0000163  1.1782 0.0113  I    -5.846     .677      .787     .127  -.148400   .188200   .3121100     -.600    -2.100  
+90 111 47902.00 I  -.151664  .000297   .191448  .000431  I  .3109700  .0000131  1.2711 0.0109  I    -5.614     .726      .990     .129  -.150600   .191000   .3108600      .500    -1.600  
+90 112 47903.00 I  -.153666  .000338   .194203  .000459  I  .3096123  .0000146  1.4548 0.0098  I    -5.156     .692     1.202     .298  -.152500   .193700   .3095300      .700     -.500  
+90 113 47904.00 I  -.155469  .000338   .197091  .000459  I  .3080493  .0000147  1.6716 0.0107  I    -4.657     .692     1.186     .298  -.154400   .196600   .3079800      .300      .600  
+90 114 47905.00 I  -.157038  .000306   .200038  .000379  I  .3062812  .0000156  1.8520 0.0101  I    -4.558     .764      .791     .237  -.156200   .199900   .3062400      .300     1.300  
+90 115 47906.00 I  -.158489  .000244   .203022  .000149  I  .3043732  .0000138  1.9486 0.0120  I    -4.895     .765      .227     .269  -.157600   .203200   .3043100     -.500     1.700  
+90 116 47907.00 I  -.159972  .000314   .206036  .000165  I  .3024133  .0000183  1.9571 0.0139  I    -5.367     .602     -.097     .325  -.159500   .206100   .3023500    -1.900     1.600  
+90 117 47908.00 I  -.161637  .000356   .209075  .000196  I  .3004836  .0000241  1.8916 0.0147  I    -5.625     .612      .174     .358  -.161100   .208900   .3004300    -3.500     1.200  
+90 118 47909.00 I  -.163648  .000356   .212119  .000196  I  .2986485  .0000231  1.7709 0.0167  I    -5.688     .612      .676     .358  -.162600   .211200   .2985800    -4.900      .500  
+90 119 47910.00 I  -.166171  .000356   .215135  .000196  I  .2969497  .0000230  1.6265 0.0151  I    -5.794     .786      .749     .359  -.165400   .214500   .2968900    -6.500     -.200  
+90 120 47911.00 I  -.169172  .000439   .218109  .000309  I  .2953954  .0000195  1.4824 0.0142  I    -6.115     .741      .316     .326  -.168400   .217500   .2952300    -7.100     -.900  
+90 121 47912.00 I  -.172428  .000388   .221071  .000324  I  .2939803  .0000165  1.3521 0.0138  I    -6.348     .687     -.220     .368  -.172300   .220900   .2936200    -6.600    -1.300  
+90 122 47913.00 I  -.175694  .000417   .224056  .000493  I  .2926783  .0000195  1.2606 0.0103  I    -6.056     .798     -.296     .353  -.174900   .223800   .2925700    -5.100    -1.600  
+90 123 47914.00 I  -.178725  .000442   .227102  .000542  I  .2914388  .0000122  1.2299 0.0122  I    -5.523     .709      .153     .471  -.177600   .227000   .2915700    -3.400    -1.600  
+90 124 47915.00 I  -.181309  .000500   .230256  .000623  I  .2901924  .0000147  1.2776 0.0095  I    -5.199     .683      .610     .513  -.180000   .230000   .2903300    -2.100    -1.600  
+90 125 47916.00 I  -.183495  .000441   .233556  .000565  I  .2888525  .0000146  1.4187 0.0106  I    -5.239     .532      .833     .480  -.182500   .233400   .2889000    -1.300    -1.500  
+90 126 47917.00 I  -.185427  .000391   .236998  .000491  I  .2873251  .0000152  1.6495 0.0135  I    -5.306     .513      .528     .432  -.185100   .236700   .2873100     -.800    -1.200  
+90 127 47918.00 I  -.187215  .000426   .240537  .000473  I  .2855331  .0000226  1.9414 0.0148  I    -5.072     .492      .255     .431  -.187400   .239900   .2855600    -1.000     -.700  
+90 128 47919.00 I  -.188973  .000497   .244118  .000507  I  .2834373  .0000253  2.2482 0.0168  I    -4.695     .421      .241     .423  -.189600   .243100   .2835100    -1.500     -.300  
+90 129 47920.00 I  -.190812  .000565   .247664  .000613  I  .2810477  .0000249  2.5222 0.0183  I    -4.513     .435      .380     .321  -.191700   .246300   .2811600    -2.000      .000  
+90 130 47921.00 I  -.192611  .000563   .251151  .000585  I  .2784173  .0000264  2.7232 0.0218  I    -4.646     .443      .543     .156  -.193400   .249600   .2785100    -2.600      .100  
+90 131 47922.00 I  -.194191  .000553   .254600  .000497  I  .2756436  .0000357  2.7972 0.0288  I    -4.979     .342      .595     .174  -.195100   .253200   .2757500    -3.500      .200  
+90 2 1 47923.00 I  -.195576  .000729   .258070  .000590  I  .2728727  .0000512  2.7217 0.0314  I    -5.387     .338      .569     .172  -.196100   .256800   .2729000    -4.100     -.100  
+90 2 2 47924.00 I  -.196900  .000729   .261580  .000590  I  .2702385  .0000516  2.5312 0.0375  I    -5.757     .338      .544     .172  -.196400   .260600   .2701800    -4.400     -.600  
+90 2 3 47925.00 I  -.198266  .000702   .265115  .000732  I  .2678273  .0000547  2.2897 0.0356  I    -5.924     .343      .521     .184  -.197300   .264100   .2678600    -5.600    -1.100  
+90 2 4 47926.00 I  -.199681  .000600   .268675  .000605  I  .2656487  .0000490  2.0795 0.0351  I    -5.909     .314      .493     .171  -.198600   .268000   .2657200    -5.000    -1.900  
+90 2 5 47927.00 I  -.201065  .000480   .272274  .000274  I  .2636380  .0000440  1.9604 0.0305  I    -5.812     .480      .395     .246  -.200000   .271900   .2637700    -3.700    -2.300  
+90 2 6 47928.00 I  -.202333  .000409   .275932  .000393  I  .2616887  .0000363  1.9591 0.0296  I    -5.695     .546      .180     .249  -.201400   .275700   .2617500    -2.100    -2.300  
+90 2 7 47929.00 I  -.203403  .000412   .279667  .000396  I  .2596837  .0000395  2.0662 0.0266  I    -5.608     .600     -.101     .263  -.202800   .279500   .2597000     -.800    -2.100  
+90 2 8 47930.00 I  -.204211  .000412   .283483  .000396  I  .2575309  .0000389  2.2494 0.0269  I    -5.613     .625     -.236     .303  -.203900   .283200   .2574600      .200    -1.900  
+90 2 9 47931.00 I  -.204694  .000411   .287359  .000390  I  .2551758  .0000365  2.4597 0.0243  I    -5.538     .844     -.095     .340  -.204500   .287000   .2550700      .400    -1.500  
+90 210 47932.00 I  -.204841  .000347   .291287  .000274  I  .2526216  .0000291  2.6396 0.0225  I    -5.155     .862      .128     .325  -.204300   .290600   .2525600     -.300    -1.100  
+90 211 47933.00 I  -.204676  .000350   .295263  .000311  I  .2499181  .0000263  2.7550 0.0194  I    -4.645     .867      .420     .335  -.203800   .294500   .2499100    -1.600     -.800  
+90 212 47934.00 I  -.204224  .000272   .299284  .000324  I  .2471377  .0000258  2.7920 0.0176  I    -4.496     .890      .322     .369  -.202800   .298600   .2471500    -3.000     -.500  
+90 213 47935.00 I  -.203533  .000284   .303354  .000268  I  .2443607  .0000233  2.7493 0.0169  I    -4.550     .871      .047     .367  -.202200   .302700   .2443800    -3.700     -.300  
+90 214 47936.00 I  -.202713  .000269   .307486  .000269  I  .2416612  .0000218  2.6402 0.0155  I    -4.588     .824     -.052     .328  -.201500   .306700   .2416800    -4.100     -.500  
+90 215 47937.00 I  -.201903  .000324   .311642  .000284  I  .2390961  .0000205  2.4838 0.0150  I    -4.580     .513     -.123     .251  -.200900   .310800   .2390900    -3.600     -.800  
+90 216 47938.00 I  -.201203  .000307   .315725  .000271  I  .2366996  .0000205  2.3096 0.0178  I    -4.658     .391     -.063     .266  -.200500   .314800   .2367000    -2.100    -1.400  
+90 217 47939.00 I  -.200751  .000374   .319639  .000354  I  .2344775  .0000291  2.1338 0.0170  I    -4.771     .417     -.063     .243  -.200500   .318800   .2344600     -.200    -1.800  
+90 218 47940.00 I  -.200722  .000365   .323310  .000303  I  .2324294  .0000271  1.9657 0.0198  I    -4.891     .467     -.211     .174  -.200300   .322600   .2324500     1.400    -2.300  
+90 219 47941.00 I  -.201068  .000448   .326771  .000282  I  .2305399  .0000269  1.8160 0.0177  I    -5.017     .440     -.584     .148  -.200400   .326300   .2306200     2.700    -2.700  
+90 220 47942.00 I  -.201659  .000427   .330102  .000285  I  .2287872  .0000227  1.6968 0.0190  I    -5.124     .550     -.975     .140  -.200600   .329800   .2289000     3.900    -3.000  
+90 221 47943.00 I  -.202289  .000455   .333378  .000237  I  .2271173  .0000269  1.6644 0.0206  I    -5.061     .594    -1.128     .136  -.200900   .333100   .2272200     4.800    -3.000  
+90 222 47944.00 I  -.202612  .000505   .336678  .000228  I  .2254160  .0000344  1.7591 0.0239  I    -4.895     .649    -1.067     .123  -.201300   .336400   .2254900     5.000    -2.700  
+90 223 47945.00 I  -.202312  .000558   .340074  .000252  I  .2235642  .0000395  1.9586 0.0248  I    -4.818     .696    -1.115     .135  -.200400   .339400   .2236000     4.500    -2.400  
+90 224 47946.00 I  -.201390  .000514   .343597  .000252  I  .2214781  .0000357  2.2204 0.0260  I    -4.681     .669    -1.271     .153  -.199300   .342800   .2214800     3.100    -2.100  
+90 225 47947.00 I  -.199994  .000487   .347250  .000302  I  .2191223  .0000337  2.4856 0.0304  I    -4.374     .535    -1.311     .142  -.198100   .346400   .2191200     1.100    -1.700  
+90 226 47948.00 I  -.198336  .000751   .351023  .000359  I  .2165307  .0000492  2.6796 0.0298  I    -4.120     .198    -1.136     .142  -.197000   .350000   .2165100    -1.500    -1.600  
+90 227 47949.00 I  -.196637  .000720   .354907  .000364  I  .2138054  .0000491  2.7468 0.0295  I    -4.212     .182     -.833     .151  -.195800   .353800   .2138000    -3.200    -1.600  
+90 228 47950.00 I  -.195118  .000689   .358888  .000626  I  .2110894  .0000326  2.6571 0.0276  I    -4.643     .182     -.531     .151  -.194700   .357900   .2111100    -4.200    -1.800  
+90 3 1 47951.00 I  -.193973  .000641   .362910  .000538  I  .2085379  .0000252  2.4273 0.0209  I    -5.149     .182     -.441     .151  -.193800   .361900   .2085800    -4.700    -2.000  
+90 3 2 47952.00 I  -.193306  .000527   .366897  .000465  I  .2062554  .0000262  2.1357 0.0188  I    -5.455     .206     -.687     .147  -.193100   .365800   .2063000    -4.700    -2.400  
+90 3 3 47953.00 I  -.192965  .000613   .370776  .000539  I  .2042577  .0000280  1.8706 0.0194  I    -5.458     .212    -1.084     .150  -.192500   .369800   .2043200    -4.000    -2.800  
+90 3 4 47954.00 I  -.192737  .000613   .374532  .000539  I  .2024849  .0000287  1.6936 0.0197  I    -5.273     .212    -1.425     .150  -.192000   .373700   .2025600    -3.700    -3.100  
+90 3 5 47955.00 I  -.192439  .000268   .378169  .000536  I  .2008309  .0000278  1.6354 0.0194  I    -5.072     .238    -1.603     .140  -.191800   .377700   .2009100    -2.900    -4.400  
+90 3 6 47956.00 I  -.192013  .000269   .381747  .000316  I  .1991734  .0000262  1.6992 0.0198  I    -4.927     .205    -1.679     .134  -.191000   .381600   .1992000    -1.600    -4.500  
+90 3 7 47957.00 I  -.191447  .000229   .385333  .000330  I  .1973997  .0000283  1.8612 0.0197  I    -4.810     .271    -1.754     .109  -.190400   .385100   .1974000     -.500    -4.200  
+90 3 8 47958.00 I  -.190752  .000206   .388961  .000386  I  .1954329  .0000293  2.0774 0.0202  I    -4.685     .291    -1.871     .298  -.189800   .388800   .1954000     -.100    -3.900  
+90 3 9 47959.00 I  -.189934  .000188   .392658  .000293  I  .1932407  .0000289  2.3060 0.0203  I    -4.569     .291    -2.021     .298  -.188800   .392400   .1932300     -.800    -2.900  
+90 310 47960.00 I  -.188990  .000188   .396433  .000293  I  .1908357  .0000282  2.4900 0.0206  I    -4.455     .291    -2.075     .298  -.187800   .395700   .1908200     -.200    -2.200  
+90 311 47961.00 I  -.187975  .000423   .400222  .000516  I  .1882909  .0000293  2.5833 0.0218  I    -4.336     .291    -2.058     .298  -.186900   .399300   .1882700    -1.100    -1.800  
+90 312 47962.00 I  -.186968  .000434   .403938  .000509  I  .1857013  .0000333  2.5801 0.0279  I    -4.191     .540    -2.087     .289  -.186100   .402900   .1856700    -2.300    -2.000  
+90 313 47963.00 I  -.186071  .000637   .407506  .000690  I  .1831593  .0000476  2.4910 0.0322  I    -4.072     .760    -2.190     .361  -.185500   .406600   .1831000    -3.200    -2.800  
+90 314 47964.00 I  -.185394  .000639   .410852  .000680  I  .1807412  .0000552  2.3360 0.0367  I    -4.119     .722    -2.247     .318  -.184900   .410200   .1806400    -4.100    -3.500  
+90 315 47965.00 I  -.184985  .000639   .413929  .000680  I  .1784922  .0000558  2.1661 0.0372  I    -4.374     .722    -2.114     .318  -.184800   .413200   .1783300    -5.400    -4.000  
+90 316 47966.00 I  -.184660  .000772   .416814  .000652  I  .1763986  .0000498  2.0274 0.0374  I    -4.518     .722    -2.007     .318  -.184200   .416100   .1762300    -6.100    -4.400  
+90 317 47967.00 I  -.184220  .000772   .419631  .000652  I  .1744241  .0000498  1.9286 0.0375  I    -4.489     .793    -2.115     .353  -.183700   .419200   .1743500    -5.800    -5.100  
+90 318 47968.00 I  -.183515  .000712   .422474  .000493  I  .1725242  .0000561  1.8815 0.0353  I    -4.359     .845    -2.468     .321  -.182800   .422100   .1724700    -4.700    -5.400  
+90 319 47969.00 I  -.182424  .000773   .425419  .000587  I  .1706383  .0000500  1.9028 0.0299  I    -4.103     .825    -2.917     .344  -.181800   .424900   .1706200    -3.400    -5.600  
+90 320 47970.00 I  -.180871  .000469   .428535  .000234  I  .1686948  .0000206  1.9954 0.0269  I    -3.685     .779    -3.155     .344  -.180100   .428200   .1687600    -1.600    -5.500  
+90 321 47971.00 I  -.178945  .000419   .431863  .000231  I  .1666247  .0000200  2.1563 0.0134  I    -3.270     .714    -3.080     .311  -.178400   .431500   .1667000     -.400    -5.400  
+90 322 47972.00 I  -.176800  .000453   .435421  .000293  I  .1643610  .0000172  2.3806 0.0130  I    -3.127     .702    -2.907     .257  -.176300   .434900   .1644100     -.100    -4.700  
+90 323 47973.00 I  -.174577  .000324   .439208  .000285  I  .1618486  .0000165  2.6495 0.0117  I    -3.345     .561    -2.908     .102  -.174200   .438600   .1618200     -.500    -4.000  
+90 324 47974.00 I  -.172343  .000349   .443146  .000315  I  .1590562  .0000158  2.9356 0.0103  I    -3.641     .561    -3.098     .102  -.171900   .442500   .1590600    -1.200    -3.500  
+90 325 47975.00 I  -.170198  .000291   .447045  .000249  I  .1559934  .0000124  3.1735 0.0097  I    -3.630     .561    -3.103     .102  -.169500   .446100   .1559800    -1.700    -3.100  
+90 326 47976.00 I  -.168148  .000247   .450794  .000234  I  .1527522  .0000114  3.2824 0.0093  I    -3.450     .539    -2.746     .104  -.167100   .449700   .1527600    -2.600    -2.900  
+90 327 47977.00 I  -.166137  .000369   .454332  .000375  I  .1494856  .0000138  3.2205 0.0087  I    -3.530     .690    -2.289     .298  -.164900   .453400   .1494900    -3.400    -2.800  
+90 328 47978.00 I  -.164136  .000354   .457615  .000354  I  .1463661  .0000132  2.9941 0.0096  I    -3.969     .626    -2.087     .298  -.162600   .456800   .1463300    -3.900    -3.200  
+90 329 47979.00 I  -.162161  .000354   .460647  .000354  I  .1435361  .0000133  2.6516 0.0115  I    -4.431     .626    -2.231     .298  -.160400   .460000   .1435100    -4.100    -3.600  
+90 330 47980.00 I  -.160228  .000322   .463506  .000351  I  .1410660  .0000189  2.2997 0.0110  I    -4.584     .626    -2.575     .298  -.158300   .463100   .1410500    -4.000    -4.100  
+90 331 47981.00 I  -.158241  .000306   .466349  .000337  I  .1389047  .0000176  2.0437 0.0134  I    -4.402     .626    -2.928     .298  -.156200   .466100   .1388900    -3.400    -4.700  
+90 4 1 47982.00 I  -.156117  .000418   .469229  .000441  I  .1369332  .0000190  1.9238 0.0161  I    -4.078     .617    -3.196     .298  -.154000   .469000   .1369100    -2.400    -4.800  
+90 4 2 47983.00 I  -.153796  .000396   .472157  .000493  I  .1350106  .0000269  1.9436 0.0165  I    -3.828     .491    -3.361     .136  -.151900   .471900   .1350100    -1.100    -4.700  
+90 4 3 47984.00 I  -.151225  .000385   .475109  .000307  I  .1330082  .0000270  2.0770 0.0191  I    -3.771     .511    -3.404     .159  -.149800   .474800   .1329900     -.300    -4.700  
+90 4 4 47985.00 I  -.148374  .000374   .478055  .000296  I  .1308397  .0000270  2.2611 0.0171  I    -3.878     .511    -3.323     .159  -.147600   .477600   .1308000     1.800    -4.900  
+90 4 5 47986.00 I  -.145312  .000355   .480999  .000164  I  .1284925  .0000210  2.4258 0.0162  I    -3.883     .511    -3.167     .159  -.145300   .480200   .1284300     2.300    -4.600  
+90 4 6 47987.00 I  -.142123  .000317   .483957  .000242  I  .1260024  .0000180  2.5475 0.0165  I    -3.741     .450    -3.132     .220  -.142500   .483200   .1259600     1.700    -4.100  
+90 4 7 47988.00 I  -.138849  .000329   .486959  .000319  I  .1234139  .0000254  2.6199 0.0161  I    -3.512     .464    -3.186     .248  -.139400   .486300   .1233900      .200    -3.700  
+90 4 8 47989.00 I  -.135526  .000252   .490037  .000293  I  .1207829  .0000266  2.6312 0.0166  I    -3.248     .304    -3.205     .270  -.136300   .489800   .1207400    -2.000    -3.800  
+90 4 9 47990.00 I  -.132195  .000359   .493212  .000316  I  .1181738  .0000214  2.5755 0.0162  I    -2.983     .297    -3.162     .301  -.132700   .493100   .1181400    -3.500    -3.700  
+90 410 47991.00 I  -.128937  .000397   .496456  .000358  I  .1156518  .0000186  2.4599 0.0123  I    -2.750     .245    -3.182     .257  -.129200   .496400   .1156300    -4.500    -3.700  
+90 411 47992.00 I  -.125835  .000308   .499714  .000340  I  .1132670  .0000123  2.3051 0.0118  I    -2.623     .202    -3.343     .234  -.125500   .499800   .1132800    -4.700    -4.100  
+90 412 47993.00 I  -.122922  .000357   .502925  .000341  I  .1110453  .0000146  2.1390 0.0090  I    -2.629     .791    -3.572     .152  -.122400   .502900   .1110100    -3.400    -4.700  
+90 413 47994.00 I  -.120184  .000357   .506020  .000341  I  .1089861  .0000132  1.9816 0.0128  I    -2.656     .791    -3.761     .152  -.119500   .506000   .1089800    -2.500    -5.400  
+90 414 47995.00 I  -.117489  .000344   .508907  .000342  I  .1070738  .0000211  1.8491 0.0122  I    -2.600     .791    -3.839     .152  -.116800   .508700   .1070600    -1.600    -6.000  
+90 415 47996.00 I  -.114801  .000341   .511621  .000319  I  .1052702  .0000205  1.7697 0.0136  I    -2.500     .791    -3.965     .147  -.114200   .511600   .1052700     -.500    -6.500  
+90 416 47997.00 I  -.112127  .000276   .514204  .000299  I  .1035097  .0000173  1.7642 0.0146  I    -2.449     .402    -4.201     .186  -.111600   .514200   .1035000      .700    -6.700  
+90 417 47998.00 I  -.109471  .000325   .516685  .000294  I  .1017159  .0000209  1.8363 0.0137  I    -2.440     .578    -4.385     .235  -.109200   .516200   .1016800     1.900    -6.300  
+90 418 47999.00 I  -.106858  .000346   .519103  .000319  I  .0998076  .0000213  1.9970 0.0149  I    -2.420     .633    -4.363     .234  -.106600   .518400   .0998100     2.400    -5.700  
+90 419 48000.00 I  -.104324  .000339   .521523  .000348  I  .0976962  .0000213  2.2349 0.0143  I    -2.360     .633    -4.108     .234  -.104100   .520900   .0977300     3.000    -4.900  
+90 420 48001.00 I  -.101893  .000293   .523999  .000333  I  .0953261  .0000191  2.5080 0.0129  I    -2.168     .633    -4.005     .234  -.101700   .523200   .0953800     2.700    -4.400  
+90 421 48002.00 I  -.099610  .000283   .526519  .000305  I  .0926861  .0000146  2.7636 0.0124  I    -2.009     .595    -4.077     .224  -.099500   .525300   .0927600     1.800    -3.800  
+90 422 48003.00 I  -.097463  .000276   .528988  .000358  I  .0898268  .0000157  2.9356 0.0113  I    -1.889     .513    -4.052     .208  -.097200   .527700   .0899300      .300    -3.500  
+90 423 48004.00 I  -.095416  .000274   .531306  .000368  I  .0868628  .0000172  2.9637 0.0121  I    -1.920     .363    -3.759     .122  -.094900   .530100   .0868500    -1.300    -3.600  
+90 424 48005.00 I  -.093418  .000231   .533400  .000354  I  .0839541  .0000185  2.8275 0.0123  I    -2.345     .241    -3.414     .124  -.092700   .532300   .0838600    -2.700    -3.900  
+90 425 48006.00 I  -.091348  .000215   .535243  .000316  I  .0812546  .0000175  2.5510 0.0139  I    -3.129     .230    -3.306     .112  -.090600   .534500   .0811100    -3.600    -4.400  
+90 426 48007.00 I  -.089161  .000273   .536945  .000300  I  .0788778  .0000207  2.1976 0.0157  I    -3.837     .194    -3.545     .121  -.088400   .536700   .0787500    -3.700    -4.800  
+90 427 48008.00 I  -.086878  .000303   .538638  .000332  I  .0768512  .0000261  1.8688 0.0186  I    -4.046     .171    -3.976     .106  -.086000   .538500   .0767500    -3.000    -5.500  
+90 428 48009.00 I  -.084572  .000304   .540379  .000348  I  .0751104  .0000308  1.6295 0.0199  I    -3.799     .183    -4.347     .106  -.083800   .540300   .0750700    -2.000    -5.900  
+90 429 48010.00 I  -.082361  .000273   .542122  .000345  I  .0735487  .0000300  1.5208 0.0204  I    -3.343     .183    -4.605     .106  -.081600   .541900   .0736400    -1.000    -6.200  
+90 430 48011.00 I  -.080182  .000277   .543839  .000270  I  .0720199  .0000268  1.5589 0.0199  I    -2.922     .791    -4.770     .104  -.079200   .543400   .0720700     -.400    -6.300  
+90 5 1 48012.00 I  -.077877  .000256   .545523  .000262  I  .0703975  .0000263  1.6971 0.0195  I    -2.749     .192    -4.768     .146  -.076700   .545100   .0704400      .000    -5.900  
+90 5 2 48013.00 I  -.075287  .000184   .547166  .000300  I  .0686133  .0000282  1.8724 0.0198  I    -2.935     .300    -4.540     .141  -.073900   .546600   .0686400     -.400    -5.300  
+90 5 3 48014.00 I  -.072276  .000184   .548758  .000300  I  .0666583  .0000295  2.0307 0.0182  I    -3.341     .300    -4.205     .141  -.070800   .548100   .0666600     -.800    -5.100  
+90 5 4 48015.00 I  -.068759  .000183   .550281  .000242  I  .0645693  .0000230  2.1367 0.0181  I    -3.624     .300    -4.009     .141  -.067100   .549600   .0645800    -2.400    -5.100  
+90 5 5 48016.00 I  -.064784  .000209   .551772  .000244  I  .0624088  .0000210  2.1710 0.0162  I    -3.476     .305    -3.930     .143  -.063000   .551100   .0623900    -2.000    -5.300  
+90 5 6 48017.00 I  -.060468  .000371   .553258  .000220  I  .0602525  .0000229  2.1295 0.0176  I    -3.004     .346    -3.852     .157  -.058800   .552700   .0602400    -1.600    -5.500  
+90 5 7 48018.00 I  -.055942  .000445   .554752  .000241  I  .0581712  .0000282  2.0237 0.0171  I    -2.551     .694    -3.796     .149  -.054600   .554200   .0581700    -1.100    -5.700  
+90 5 8 48019.00 I  -.051343  .000453   .556267  .000227  I  .0562209  .0000255  1.8706 0.0179  I    -2.348     .735    -3.915     .156  -.050100   .555700   .0562200     -.600    -5.800  
+90 5 9 48020.00 I  -.046853  .000453   .557798  .000227  I  .0544325  .0000222  1.7102 0.0163  I    -2.366     .735    -4.162     .156  -.045800   .557300   .0544100     -.300    -5.900  
+90 510 48021.00 I  -.042609  .000435   .559319  .000288  I  .0527930  .0000204  1.5725 0.0150  I    -2.447     .735    -4.518     .156  -.041600   .558800   .0527700      .100    -5.800  
+90 511 48022.00 I  -.038544  .000425   .560777  .000336  I  .0512772  .0000202  1.4659 0.0151  I    -2.499     .713    -4.814     .194  -.037200   .560300   .0512600      .300    -5.800  
+90 512 48023.00 I  -.034545  .000456   .562139  .000391  I  .0498442  .0000222  1.4104 0.0155  I    -2.506     .839    -4.900     .212  -.032900   .561800   .0498300      .500    -5.600  
+90 513 48024.00 I  -.030505  .000373   .563381  .000472  I  .0484348  .0000236  1.4198 0.0168  I    -2.579     .460    -4.840     .216  -.028600   .563100   .0484100      .700    -5.500  
+90 514 48025.00 I  -.026329  .000361   .564505  .000478  I  .0469792  .0000253  1.5054 0.0165  I    -2.889     .439    -4.732     .192  -.024200   .564300   .0469400      .600    -5.100  
+90 515 48026.00 I  -.022010  .000350   .565557  .000391  I  .0453965  .0000230  1.6737 0.0182  I    -3.287     .439    -4.619     .192  -.019800   .565300   .0453300      .500    -4.800  
+90 516 48027.00 I  -.017588  .000330   .566569  .000387  I  .0436153  .0000263  1.8917 0.0191  I    -3.416     .432    -4.493     .186  -.015600   .566300   .0435700      .300    -4.400  
+90 517 48028.00 I  -.013173  .000353   .567518  .000398  I  .0416069  .0000304  2.1282 0.0204  I    -3.169     .399    -4.325     .142  -.011300   .567200   .0415600      .000    -4.000  
+90 518 48029.00 I  -.008793  .000353   .568420  .000398  I  .0393602  .0000313  2.3608 0.0203  I    -2.805     .399    -4.245     .142  -.007000   .568000   .0393400     -.400    -3.700  
+90 519 48030.00 I  -.004462  .000316   .569293  .000294  I  .0369007  .0000268  2.5473 0.0204  I    -2.654     .403    -4.302     .151  -.002800   .568800   .0368700     -.900    -3.600  
+90 520 48031.00 I  -.000214  .000217   .570103  .000291  I  .0342940  .0000262  2.6487 0.0165  I    -2.790     .345    -4.313     .147   .001200   .569500   .0342700    -1.400    -3.500  
+90 521 48032.00 I   .003913  .000183   .570813  .000254  I  .0316432  .0000193  2.6302 0.0152  I    -3.185     .429    -4.110     .155   .005100   .570100   .0316000    -1.900    -3.400  
+90 522 48033.00 I   .007879  .000146   .571392  .000190  I  .0290757  .0000155  2.4852 0.0124  I    -3.788     .429    -3.830     .129   .009200   .570600   .0290200    -2.400    -3.400  
+90 523 48034.00 I   .011670  .000160   .571830  .000189  I  .0267069  .0000157  2.2379 0.0108  I    -4.365     .394    -3.772     .120   .013000   .571000   .0266500    -2.700    -3.500  
+90 524 48035.00 I   .015380  .000160   .572205  .000189  I  .0246173  .0000149  1.9384 0.0106  I    -4.574     .394    -4.002     .120   .016600   .571100   .0246100    -2.400    -3.700  
+90 525 48036.00 I   .019079  .000165   .572518  .000213  I  .0228185  .0000143  1.6737 0.0096  I    -4.438     .394    -4.247     .120   .020300   .571200   .0228400    -2.100    -4.000  
+90 526 48037.00 I   .022725  .000165   .572767  .000271  I  .0212270  .0000120  1.5376 0.0091  I    -4.175     .387    -4.290     .177   .023700   .571200   .0212300    -1.700    -4.200  
+90 527 48038.00 I   .026334  .000192   .572981  .000260  I  .0196908  .0000114  1.5590 0.0164  I    -3.933     .271    -4.241     .188   .027200   .571300   .0196800    -1.300    -4.500  
+90 528 48039.00 I   .029941  .000198   .573192  .000318  I  .0180715  .0000305  1.6930 0.0262  I    -3.807     .353    -4.307     .196   .030800   .571300   .0180200    -1.100    -4.700  
+90 529 48040.00 I   .033584  .000204   .573433  .000511  I  .0162917  .0000512  1.8663 0.0272  I    -3.956     .404    -4.500     .222   .034500   .571700   .0162200    -1.600    -4.700  
+90 530 48041.00 I   .037283  .000228   .573697  .000450  I  .0143478  .0000451  2.0128 0.0320  I    -4.445     .404    -4.561     .222   .038100   .572000   .0142600    -2.300    -4.700  
+90 531 48042.00 I   .041030  .000231   .573946  .000393  I  .0122870  .0000384  2.0967 0.0340  I    -5.012     .434    -4.352     .174   .041900   .572400   .0122100    -2.900    -4.600  
+90 6 1 48043.00 I   .044816  .000244   .574165  .000259  I  .0101794  .0000510  2.1057 0.0315  I    -5.291     .523    -4.111     .298   .045600   .572700   .0101000    -3.500    -4.600  
+90 6 2 48044.00 I   .048642  .000236   .574355  .000457  I  .0080994  .0000499  2.0433 0.0314  I    -5.121     .523    -4.051     .298   .049400   .573000   .0080500    -4.000    -4.500  
+90 6 3 48045.00 I   .052531  .000248   .574522  .000441  I  .0061118  .0000366  1.9238 0.0261  I    -4.782     .516    -4.117     .298   .053300   .573300   .0060900    -4.200    -4.500  
+90 6 4 48046.00 I   .056477  .000246   .574617  .000406  I  .0042663  .0000155  1.7609 0.0196  I    -4.617     .516    -4.167     .298   .057200   .573600   .0042500    -3.800    -4.600  
+90 6 5 48047.00 I   .060427  .000241   .574560  .000365  I  .0025991  .0000143  1.5707 0.0105  I    -4.691     .614    -4.241     .298   .061100   .573700   .0025500    -3.500    -4.700  
+90 6 6 48048.00 I   .064325  .000400   .574288  .000491  I  .0011235  .0000141  1.3846 0.0108  I    -4.816     .694    -4.484     .298   .065000   .573700   .0010700    -3.200    -4.800  
+90 6 7 48049.00 I   .068136  .000433   .573790  .000485  I -.0001825  .0000162  1.2356 0.0116  I    -4.988     .613    -4.810     .298   .068900   .573700  -.0002400    -2.800    -4.900  
+90 6 8 48050.00 I   .071863  .000440   .573089  .000514  I -.0013675  .0000184  1.1461 0.0111  I    -5.352     .637    -4.919     .108   .072800   .572500  -.0014200    -3.100    -5.000  
+90 6 9 48051.00 I   .075621  .000412   .572246  .000287  I -.0025001  .0000153  1.1328 0.0119  I    -5.733     .600    -4.713     .123   .076700   .571500  -.0025700    -3.200    -5.100  
+90 610 48052.00 I   .079542  .000366   .571331  .000403  I -.0036596  .0000151  1.1989 0.0117  I    -5.847     .582    -4.407     .116   .080600   .570500  -.0037300    -3.500    -5.200  
+90 611 48053.00 I   .083643  .000411   .570420  .000473  I -.0049200  .0000177  1.3313 0.0117  I    -5.677     .492    -4.286     .127   .084400   .569500  -.0049900    -3.400    -5.200  
+90 612 48054.00 I   .087869  .000420   .569582  .000487  I -.0063350  .0000178  1.5021 0.0127  I    -5.566     .492    -4.224     .127   .088400   .568400  -.0063900    -3.600    -5.100  
+90 613 48055.00 I   .092108  .000342   .568860  .000464  I -.0079295  .0000183  1.6887 0.0121  I    -5.668     .529    -4.056     .138   .092200   .567900  -.0080100    -3.900    -5.000  
+90 614 48056.00 I   .096265  .000276   .568224  .000587  I -.0097134  .0000164  1.8782 0.0115  I    -5.743     .468    -3.892     .118   .096200   .567300  -.0098000    -4.200    -4.900  
+90 615 48057.00 I   .100309  .000228   .567608  .000586  I -.0116770  .0000138  2.0412 0.0125  I    -5.677     .417    -3.856     .120   .100100   .566600  -.0117500    -4.500    -5.000  
+90 616 48058.00 I   .104234  .000264   .566950  .000681  I -.0137740  .0000189  2.1390 0.0132  I    -5.610     .312    -3.958     .133   .104100   .565300  -.0138400    -4.600    -5.100  
+90 617 48059.00 I   .108071  .000251   .566198  .000682  I -.0159224  .0000226  2.1390 0.0158  I    -5.738     .385    -4.124     .267   .108100   .564300  -.0159800    -4.700    -5.100  
+90 618 48060.00 I   .111870  .000302   .565323  .000664  I -.0180150  .0000252  2.0279 0.0177  I    -6.171     .508    -4.257     .326   .112100   .563000  -.0180900    -4.700    -5.000  
+90 619 48061.00 I   .115674  .000279   .564316  .000629  I -.0199498  .0000273  1.8315 0.0175  I    -6.752     .517    -4.225     .309   .116100   .561900  -.0200200    -4.500    -5.300  
+90 620 48062.00 I   .119509  .000319   .563148  .000493  I -.0216658  .0000244  1.5985 0.0216  I    -7.158     .468    -3.999     .281   .119900   .560700  -.0217500    -4.500    -5.300  
+90 621 48063.00 I   .123347  .000391   .561823  .000368  I -.0231539  .0000335  1.3868 0.0208  I    -7.316     .499    -4.027     .305   .123700   .559800  -.0232500    -4.400    -5.500  
+90 622 48064.00 I   .127096  .000417   .560361  .000373  I -.0244627  .0000338  1.2450 0.0224  I    -7.168     .499    -4.136     .305   .127300   .558400  -.0245600    -4.500    -5.400  
+90 623 48065.00 I   .130620  .000492   .558791  .000411  I -.0256832  .0000298  1.2213 0.0217  I    -6.926     .482    -4.188     .271   .130600   .556900  -.0257500    -4.800    -5.200  
+90 624 48066.00 I   .134018  .000499   .557053  .000398  I -.0269483  .0000273  1.3267 0.0181  I    -6.675     .451    -4.120     .187   .133800   .555400  -.0269900    -5.400    -5.000  
+90 625 48067.00 I   .137425  .000430   .555162  .000371  I -.0283598  .0000204  1.5016 0.0202  I    -6.414     .443    -4.020     .163   .137100   .553600  -.0283900    -5.800    -4.800  
+90 626 48068.00 I   .140913  .000396   .553151  .000354  I -.0299500  .0000298  1.6721 0.0176  I    -6.327     .479    -3.953     .144   .140600   .551900  -.0299700    -6.400    -4.300  
+90 627 48069.00 I   .144519  .000487   .551067  .000391  I -.0316821  .0000288  1.7770 0.0211  I    -6.739     .448    -3.849     .132   .144000   .549800  -.0317100    -6.800    -4.300  
+90 628 48070.00 I   .148236  .000508   .549015  .000400  I -.0334770  .0000298  1.8011 0.0201  I    -7.601     .436    -3.766     .132   .148100   .547900  -.0335000    -7.100    -4.200  
+90 629 48071.00 I   .152136  .000472   .547071  .000406  I -.0352622  .0000281  1.7591 0.0212  I    -8.430     .451    -3.773     .134   .152300   .546000  -.0352800    -7.200    -4.500  
+90 630 48072.00 I   .156303  .000383   .545287  .000356  I -.0369802  .0000301  1.6721 0.0226  I    -8.728     .370    -3.828     .113   .156400   .544100  -.0370400    -7.300    -4.500  
+90 7 1 48073.00 I   .160777  .000413   .543635  .000384  I -.0385964  .0000355  1.5552 0.0210  I    -8.542     .290    -3.825     .111   .161100   .542400  -.0386700    -7.600    -4.700  
+90 7 2 48074.00 I   .165414  .000413   .542060  .000384  I -.0400777  .0000293  1.3995 0.0244  I    -8.459     .290    -3.787     .111   .165400   .540500  -.0401500    -7.500    -4.800  
+90 7 3 48075.00 I   .169947  .000490   .540503  .000416  I -.0413918  .0000336  1.2330 0.0209  I    -8.787     .314    -3.754     .117   .170000   .539600  -.0414200    -7.300    -4.900  
+90 7 4 48076.00 I   .174278  .000330   .538913  .000387  I -.0425512  .0000299  1.0891 0.0212  I    -9.397     .495    -3.703     .118   .174600   .538700  -.0425100    -7.900    -4.700  
+90 7 5 48077.00 I   .178387  .000231   .537236  .000331  I -.0435793  .0000260  0.9732 0.0234  I    -9.992     .586    -3.676     .122   .179100   .537200  -.0435200    -8.400    -4.300  
+90 7 6 48078.00 I   .182250  .000222   .535415  .000287  I -.0445130  .0000359  0.9034 0.0203  I   -10.323     .709    -3.672     .144   .182800   .535400  -.0445600    -8.800    -4.000  
+90 7 7 48079.00 I   .185852  .000431   .533390  .000291  I -.0454012  .0000312  0.8789 0.0240  I   -10.246     .813    -3.639     .140   .186200   .533000  -.0454800    -9.200    -4.100  
+90 7 8 48080.00 I   .189216  .000440   .531114  .000407  I -.0462908  .0000320  0.9146 0.0209  I   -10.004     .952    -3.487     .208   .189300   .530300  -.0463400    -9.700    -4.000  
+90 7 9 48081.00 I   .192463  .000407   .528646  .000394  I -.0472579  .0000278  1.0330 0.0219  I    -9.772     .919    -3.317     .192   .192800   .527400  -.0473200    -9.700    -4.100  
+90 710 48082.00 I   .195765  .000414   .526086  .000360  I -.0483778  .0000298  1.2145 0.0232  I    -9.655     .813    -3.273     .178   .196300   .525100  -.0484700    -9.800    -4.200  
+90 711 48083.00 I   .199218  .000546   .523520  .000426  I -.0496942  .0000371  1.4180 0.0221  I    -9.746    1.138    -3.366     .177   .199700   .522400  -.0497600    -9.400    -4.300  
+90 712 48084.00 I   .202743  .000534   .521000  .000465  I -.0512015  .0000327  1.5845 0.0246  I   -10.081    1.175    -3.539     .170   .202900   .520000  -.0512800    -9.100    -4.400  
+90 713 48085.00 I   .206192  .000503   .518522  .000463  I -.0528385  .0000324  1.6768 0.0229  I   -10.332    1.175    -3.763     .170   .206000   .517200  -.0529500    -9.100    -4.500  
+90 714 48086.00 I   .209567  .000392   .516057  .000444  I -.0545233  .0000320  1.6738 0.0216  I   -10.065    1.191    -3.973     .298   .209200   .514500  -.0546100    -9.300    -4.700  
+90 715 48087.00 I   .212890  .000335   .513585  .000415  I -.0561489  .0000287  1.5591 0.0215  I    -9.812    1.064    -4.033     .104   .212500   .511900  -.0562100    -9.600    -4.800  
+90 716 48088.00 I   .216181  .000356   .511092  .000591  I -.0576099  .0000288  1.3497 0.0250  I    -9.970    1.134    -3.942     .298   .216100   .510000  -.0576800    -9.800    -4.900  
+90 717 48089.00 I   .219452  .000200   .508596  .000458  I -.0588309  .0000409  1.0881 0.0238  I   -10.401     .738    -3.848     .298   .219900   .507900  -.0588900   -10.000    -4.700  
+90 718 48090.00 I   .222704  .000204   .506113  .000331  I -.0597892  .0000378  0.8357 0.0272  I   -10.858     .318    -3.894     .109   .223700   .505900  -.0598600   -10.000    -4.200  
+90 719 48091.00 I   .225900  .000194   .503614  .000323  I -.0605297  .0000358  0.6656 0.0249  I   -11.204     .429    -4.072     .101   .227400   .503400  -.0605700   -10.000    -4.100  
+90 720 48092.00 I   .229029  .000173   .501038  .000311  I -.0611658  .0000323  0.6319 0.0256  I   -11.449     .722    -4.181     .127   .230500   .500700  -.0612600    -9.400    -4.000  
+90 721 48093.00 I   .232094  .000233   .498320  .000411  I -.0618410  .0000367  0.7409 0.0240  I   -11.626     .821    -4.029     .134   .233600   .497600  -.0619500    -9.200    -3.900  
+90 722 48094.00 I   .235100  .000290   .495415  .000398  I -.0626823  .0000356  0.9540 0.0223  I   -11.579     .822    -3.786     .159   .236200   .494500  -.0627700    -9.000    -3.800  
+90 723 48095.00 I   .238069  .000286   .492348  .000415  I -.0637592  .0000252  1.1976 0.0218  I   -11.343     .754    -3.696     .181   .238800   .491200  -.0638100    -9.600    -4.100  
+90 724 48096.00 I   .241052  .000259   .489190  .000445  I -.0650623  .0000250  1.3957 0.0164  I   -11.146     .777    -3.725     .173   .241800   .488000  -.0651100   -10.100    -4.300  
+90 725 48097.00 I   .244089  .000265   .486004  .000452  I -.0665222  .0000211  1.5085 0.0175  I   -11.354     .751    -3.702     .247   .244900   .484600  -.0665400   -10.700    -4.500  
+90 726 48098.00 I   .247129  .000317   .482782  .000503  I -.0680495  .0000246  1.5319 0.0192  I   -12.138     .556    -3.742     .277   .248000   .481400  -.0680900   -10.800    -5.100  
+90 727 48099.00 I   .250068  .000317   .479505  .000503  I -.0695657  .0000320  1.4945 0.0211  I   -13.139     .556    -3.769     .277   .251000   .478200  -.0695900   -10.900    -5.400  
+90 728 48100.00 I   .252813  .000270   .476174  .000331  I -.0710254  .0000342  1.4177 0.0243  I   -13.962     .596    -3.601     .287   .253800   .474900  -.0710300   -11.200    -5.500  
+90 729 48101.00 I   .255333  .000245   .472800  .000284  I -.0723894  .0000365  1.3059 0.0234  I   -14.262     .578    -3.468     .292   .256300   .471800  -.0724200   -11.600    -5.200  
+90 730 48102.00 I   .257658  .000231   .469387  .000251  I -.0736311  .0000320  1.1760 0.0288  I   -14.137     .753    -3.410     .286   .258500   .468500  -.0736800   -12.000    -4.800  
+90 731 48103.00 I   .259827  .000415   .465943  .000403  I -.0747407  .0000446  1.0442 0.0271  I   -13.945     .730    -3.297     .233   .260500   .465200  -.0748300   -12.200    -4.000  
+90 8 1 48104.00 I   .261882  .000374   .462474  .000398  I -.0757207  .0000437  0.9160 0.0285  I   -13.870     .730    -3.145     .198   .262500   .462100  -.0757800   -12.900    -3.600  
+90 8 2 48105.00 I   .263860  .000371   .458987  .000379  I -.0765851  .0000356  0.8248 0.0288  I   -13.848     .715    -3.185     .184   .264200   .457800  -.0766300   -13.200    -3.300  
+90 8 3 48106.00 I   .265854  .000381   .455485  .000394  I -.0773983  .0000375  0.8174 0.0258  I   -13.945     .715    -3.272     .184   .266000   .454300  -.0774500   -13.400    -2.800  
+90 8 4 48107.00 I   .267940  .000393   .451994  .000406  I -.0782502  .0000373  0.9010 0.0243  I   -14.230     .758    -3.269     .182   .268700   .451400  -.0782800   -13.500    -2.500  
+90 8 5 48108.00 I   .270121  .000427   .448524  .000426  I -.0792279  .0000308  1.0675 0.0266  I   -14.425     .512    -3.215     .109   .271900   .448500  -.0792400   -14.000    -2.300  
+90 8 6 48109.00 I   .272360  .000524   .445084  .000560  I -.0804064  .0000378  1.2975 0.0270  I   -14.370     .536    -3.177     .298   .274300   .445500  -.0804500   -14.000    -2.400  
+90 8 7 48110.00 I   .274589  .000390   .441685  .000522  I -.0818318  .0000444  1.5542 0.0298  I   -14.208     .400    -3.200     .247   .276500   .442500  -.0818700   -14.200    -2.400  
+90 8 8 48111.00 I   .276741  .000360   .438343  .000506  I -.0835090  .0000461  1.7934 0.0278  I   -14.182     .250    -3.268     .318   .278200   .439000  -.0835500   -14.400    -2.600  
+90 8 9 48112.00 I   .278754  .000292   .435072  .000648  I -.0853967  .0000333  1.9667 0.0315  I   -14.459     .287    -3.311     .238   .279800   .435300  -.0854300   -14.700    -2.900  
+90 810 48113.00 I   .280596  .000292   .431901  .000648  I -.0874084  .0000430  2.0380 0.0264  I   -14.914     .289    -3.134     .220   .281200   .431200  -.0874800   -14.700    -3.500  
+90 811 48114.00 I   .282279  .000333   .428841  .000699  I -.0894342  .0000411  1.9938 0.0303  I   -15.264     .289    -3.016     .220   .282600   .427500  -.0894900   -14.800    -3.800  
+90 812 48115.00 I   .283818  .000399   .425877  .000724  I -.0913622  .0000428  1.8481 0.0285  I   -15.387     .260    -3.111     .222   .284000   .424500  -.0914600   -14.400    -4.000  
+90 813 48116.00 I   .285247  .000319   .422970  .000641  I -.0931091  .0000396  1.6384 0.0258  I   -15.368     .299    -3.360     .152   .285700   .421600  -.0933000   -13.900    -3.900  
+90 814 48117.00 I   .286585  .000372   .420014  .000600  I -.0946352  .0000288  1.4172 0.0261  I   -15.286     .530    -3.611     .107   .286900   .418600  -.0948000   -13.400    -3.900  
+90 815 48118.00 I   .287859  .000423   .416916  .000672  I -.0959629  .0000340  1.2543 0.0180  I   -15.186     .580    -3.664     .119   .288200   .416000  -.0960600   -12.600    -3.700  
+90 816 48119.00 I   .289172  .000436   .413704  .000561  I -.0971804  .0000217  1.2013 0.0226  I   -15.126     .621    -3.537     .126   .290000   .413000  -.0972400   -11.500    -4.100  
+90 817 48120.00 I   .290686  .000436   .410418  .000561  I -.0984078  .0000298  1.2753 0.0125  I   -15.245     .621    -3.377     .126   .291700   .409300  -.0984100   -11.200    -4.400  
+90 818 48121.00 I   .292427  .000296   .407051  .000291  I -.0997677  .0000123  1.4593 0.0164  I   -15.362     .692    -3.271     .123   .293400   .405500  -.0998400   -11.800    -4.500  
+90 819 48122.00 I   .294320  .000452   .403618  .000273  I -.1013457  .0000137  1.7011 0.0106  I   -15.271     .625    -3.181     .134   .295400   .401900  -.1014400   -12.800    -4.400  
+90 820 48123.00 I   .296284  .000458   .400149  .000219  I -.1031677  .0000172  1.9361 0.0110  I   -14.941     .455    -3.074     .118   .297500   .398400  -.1032600   -14.100    -4.200  
+90 821 48124.00 I   .298236  .000471   .396673  .000117  I -.1051968  .0000173  2.1077 0.0122  I   -14.468     .441    -2.992     .114   .299600   .395700  -.1053400   -15.100    -3.700  
+90 822 48125.00 I   .300054  .000471   .393217  .000117  I -.1073506  .0000173  2.1816 0.0112  I   -14.067     .441    -2.996     .114   .301500   .392900  -.1074500   -15.300    -3.600  
+90 823 48126.00 I   .301644  .000535   .389767  .000169  I -.1095274  .0000143  2.1576 0.0111  I   -14.020     .441    -3.104     .114   .303000   .389800  -.1096500   -15.100    -3.200  
+90 824 48127.00 I   .302975  .000571   .386306  .000172  I -.1116384  .0000140  2.0516 0.0178  I   -14.442     .379    -3.273     .103   .304100   .386400  -.1117600   -15.100    -3.600  
+90 825 48128.00 I   .304034  .000774   .382824  .000286  I -.1136104  .0000327  1.8852 0.0153  I   -15.057     .314    -3.432     .298   .305000   .382300  -.1137100   -14.900    -4.000  
+90 826 48129.00 I   .304812  .000807   .379313  .000279  I -.1153995  .0000271  1.6908 0.0211  I   -15.493     .314    -3.501     .298   .305800   .378400  -.1154700   -14.700    -4.300  
+90 827 48130.00 I   .305343  .000830   .375769  .000344  I -.1169930  .0000267  1.4993 0.0179  I   -15.571     .194    -3.458     .298   .305800   .375100  -.1170600   -15.000    -4.100  
+90 828 48131.00 I   .305706  .000725   .372194  .000306  I -.1184076  .0000235  1.3362 0.0156  I   -15.369     .194    -3.368     .298   .306000   .371900  -.1184500   -14.900    -4.000  
+90 829 48132.00 I   .305957  .000533   .368585  .000271  I -.1196803  .0000163  1.2179 0.0143  I   -15.088     .171    -3.322     .298   .306200   .368500  -.1197400   -14.500    -3.600  
+90 830 48133.00 I   .306169  .000395   .364943  .000212  I -.1208648  .0000162  1.1637 0.0126  I   -14.878     .140    -3.311     .298   .306400   .364700  -.1209200   -13.100    -3.600  
+90 831 48134.00 I   .306493  .000395   .361281  .000212  I -.1220331  .0000191  1.1856 0.0130  I   -14.829     .140    -3.260     .298   .307000   .360600  -.1220800   -12.500    -3.600  
+90 9 1 48135.00 I   .307079  .000395   .357616  .000212  I -.1232639  .0000204  1.2912 0.0167  I   -14.952     .140    -3.135     .298   .307700   .356600  -.1233000   -12.400    -3.500  
+90 9 2 48136.00 I   .307923  .000356   .353948  .000293  I -.1246436  .0000273  1.4811 0.0160  I   -15.171     .129    -2.994     .298   .308300   .352500  -.1246200   -12.600    -3.400  
+90 9 3 48137.00 I   .308928  .000368   .350259  .000284  I -.1262465  .0000247  1.7321 0.0217  I   -15.405     .416    -2.924     .206   .309300   .348600  -.1261700   -13.000    -3.300  
+90 9 4 48138.00 I   .309992  .000434   .346527  .000358  I -.1281148  .0000338  2.0040 0.0209  I   -15.643     .560    -2.938     .394   .310300   .344800  -.1280700   -13.200    -3.400  
+90 9 5 48139.00 I   .311003  .000431   .342728  .000340  I -.1302441  .0000338  2.2447 0.0224  I   -15.972     .504    -2.998     .389   .311700   .341400  -.1303100   -13.700    -3.300  
+90 9 6 48140.00 I   .311833  .000403   .338838  .000279  I -.1325698  .0000294  2.3821 0.0227  I   -16.510     .504    -3.067     .389   .312100   .337500  -.1327600   -14.300    -3.300  
+90 9 7 48141.00 I   .312470  .000430   .334859  .000304  I -.1349571  .0000302  2.3658 0.0196  I   -17.064     .460    -2.839     .352   .312800   .333600  -.1351200   -14.500    -3.500  
+90 9 8 48142.00 I   .312954  .000463   .330804  .000370  I -.1372534  .0000260  2.2057 0.0184  I   -17.382     .591    -2.650     .316   .313500   .329700  -.1374100   -14.200    -3.600  
+90 9 9 48143.00 I   .313259  .000442   .326689  .000364  I -.1393367  .0000209  1.9504 0.0178  I   -17.322     .712    -2.727     .317   .313600   .325700  -.1394800   -14.500    -3.600  
+90 910 48144.00 I   .313337  .000442   .322545  .000351  I -.1411452  .0000242  1.6680 0.0173  I   -16.910     .726    -2.871     .232   .313700   .321600  -.1412500   -14.600    -3.900  
+90 911 48145.00 I   .313177  .000443   .318438  .000365  I -.1426925  .0000275  1.4449 0.0195  I   -16.405     .776    -2.998     .203   .313700   .317500  -.1427300   -14.900    -3.500  
+90 912 48146.00 I   .312883  .000413   .314378  .000348  I -.1440792  .0000307  1.3545 0.0202  I   -15.884     .776    -3.069     .203   .313400   .313500  -.1441000   -15.100    -3.500  
+90 913 48147.00 I   .312523  .000418   .310356  .000386  I -.1454500  .0000295  1.4097 0.0219  I   -15.574     .732    -3.121     .182   .312900   .309400  -.1454700   -15.200    -3.400  
+90 914 48148.00 I   .312119  .000440   .306392  .000372  I -.1469374  .0000312  1.5813 0.0230  I   -15.571     .690    -3.195     .167   .312600   .305600  -.1469700   -15.200    -3.800  
+90 915 48149.00 I   .311661  .000307   .302501  .000262  I -.1486353  .0000352  1.8210 0.0229  I   -15.637     .456    -3.255     .298   .311800   .301500  -.1486700   -14.800    -3.800  
+90 916 48150.00 I   .311131  .000336   .298699  .000256  I -.1505805  .0000334  2.0641 0.0230  I   -15.505     .325    -3.212     .298   .310800   .297400  -.1505900   -14.600    -4.000  
+90 917 48151.00 I   .310531  .000404   .294983  .000247  I -.1527464  .0000296  2.2559 0.0225  I   -15.167     .325    -3.000     .298   .310000   .293700  -.1527900   -14.700    -4.000  
+90 918 48152.00 I   .309871  .000464   .291347  .000268  I -.1550642  .0000303  2.3635 0.0226  I   -14.817     .493    -2.653     .298   .309500   .290500  -.1551600   -14.800    -3.900  
+90 919 48153.00 I   .309160  .000847   .287783  .000283  I -.1574408  .0000342  2.3734 0.0234  I   -14.667     .622    -2.311     .298   .309400   .287000  -.1575100   -14.800    -3.600  
+90 920 48154.00 I   .308393  .000847   .284282  .000283  I -.1597815  .0000357  2.2949 0.0268  I   -14.846     .622    -2.125     .298   .309100   .283700  -.1598600   -14.800    -3.400  
+90 921 48155.00 I   .307506  .000847   .280822  .000283  I -.1620083  .0000412  2.1496 0.0231  I   -15.359     .622    -2.145     .298   .308700   .280400  -.1620200   -14.800    -3.300  
+90 922 48156.00 I   .306397  .000611   .277373  .000480  I -.1640705  .0000294  1.9736 0.0223  I   -15.866     .622    -2.293     .298   .307900   .277000  -.1641000   -14.700    -3.300  
+90 923 48157.00 I   .305056  .000409   .273887  .000460  I -.1659581  .0000169  1.8055 0.0177  I   -16.053     .523    -2.428     .298   .306500   .273600  -.1660200   -14.500    -3.200  
+90 924 48158.00 I   .303574  .000416   .270303  .000481  I -.1676926  .0000196  1.6709 0.0114  I   -15.806     .395    -2.481     .298   .304900   .270000  -.1677500   -14.200    -3.200  
+90 925 48159.00 I   .302063  .000205   .266557  .000403  I -.1693171  .0000154  1.5880 0.0128  I   -15.223     .279    -2.527     .298   .303100   .266300  -.1694200   -14.300    -3.200  
+90 926 48160.00 I   .300634  .000205   .262617  .000403  I -.1708895  .0000166  1.5678 0.0107  I   -14.637     .282    -2.687     .298   .301000   .262200  -.1710400   -14.300    -3.300  
+90 927 48161.00 I   .299388  .000186   .258587  .000372  I -.1724761  .0000149  1.6178 0.0128  I   -14.285     .282    -2.973     .298   .299600   .257900  -.1726200   -14.300    -3.500  
+90 928 48162.00 I   .298364  .000168   .254585  .000423  I -.1741494  .0000195  1.7409 0.0147  I   -14.164     .420    -3.200     .298   .298000   .253500  -.1742800   -14.100    -3.500  
+90 929 48163.00 I   .297561  .000209   .250709  .000353  I -.1759802  .0000254  1.9311 0.0164  I   -14.147     .460    -3.201     .298   .297700   .249800  -.1760800   -14.000    -3.800  
+90 930 48164.00 I   .296905  .000196   .247030  .000343  I -.1780282  .0000264  2.1711 0.0183  I   -14.274     .524    -3.043     .298   .297700   .246300  -.1781200   -13.900    -3.700  
+9010 1 48165.00 I   .296302  .000185   .243594  .000354  I -.1803265  .0000263  2.4233 0.0189  I   -14.698     .581    -2.874     .298   .297400   .243000  -.1804100   -14.100    -3.700  
+9010 2 48166.00 I   .295654  .000237   .240360  .000444  I -.1828631  .0000270  2.6404 0.0170  I   -15.259     .647    -2.748     .103   .297000   .240100  -.1829400   -14.400    -3.300  
+9010 3 48167.00 I   .294851  .000270   .237241  .000299  I -.1855792  .0000216  2.7730 0.0165  I   -15.616     .611    -2.614     .298   .295900   .236900  -.1856200   -14.500    -3.200  
+9010 4 48168.00 I   .293782  .000339   .234151  .000224  I -.1883677  .0000188  2.7812 0.0142  I   -15.537     .575    -2.492     .298   .294300   .233700  -.1884200   -14.300    -3.100  
+9010 5 48169.00 I   .292376  .000344   .230984  .000227  I -.1910975  .0000185  2.6569 0.0142  I   -15.169     .575    -2.451     .298   .292300   .230000  -.1911500   -13.900    -3.300  
+9010 6 48170.00 I   .290636  .000344   .227640  .000227  I -.1936458  .0000214  2.4253 0.0133  I   -14.752     .600    -2.508     .111   .290100   .226000  -.1937100   -14.400    -3.700  
+9010 7 48171.00 I   .288711  .000310   .224110  .000203  I -.1959332  .0000192  2.1488 0.0181  I   -14.406     .747    -2.580     .197   .287700   .221900  -.1960100   -13.700    -3.600  
+9010 8 48172.00 I   .286692  .000376   .220434  .000196  I -.1979555  .0000291  1.9086 0.0208  I   -14.125     .691    -2.585     .222   .285800   .218400  -.1980200   -13.000    -3.700  
+9010 9 48173.00 I   .284630  .000383   .216660  .000144  I -.1997832  .0000369  1.7670 0.0258  I   -13.940     .697    -2.523     .290   .283800   .214900  -.1998800   -12.600    -3.400  
+901010 48174.00 I   .282572  .000419   .212839  .000204  I -.2015301  .0000426  1.7474 0.0294  I   -14.111     .685    -2.253     .321   .282000   .211800  -.2016300   -12.800    -2.600  
+901011 48175.00 I   .280541  .000419   .209022  .000204  I -.2033154  .0000458  1.8401 0.0293  I   -14.374     .685    -2.129     .321   .280300   .208800  -.2033300   -12.800    -2.400  
+901012 48176.00 I   .278421  .000375   .205271  .000217  I -.2052338  .0000402  2.0034 0.0283  I   -14.419     .679    -2.386     .337   .278700   .205400  -.2052200   -13.200    -1.900  
+901013 48177.00 I   .276142  .000326   .201622  .000224  I -.2073263  .0000332  2.1789 0.0231  I   -14.192     .356    -2.584     .261   .276800   .202000  -.2073700   -13.100    -2.100  
+901014 48178.00 I   .273732  .000362   .198072  .000311  I -.2095793  .0000226  2.3177 0.0193  I   -13.791     .259    -2.460     .250   .274400   .198200  -.2096700   -13.000    -2.300  
+901015 48179.00 I   .271236  .000285   .194613  .000323  I -.2119396  .0000195  2.3904 0.0151  I   -13.375     .256    -2.186     .185   .271700   .194200  -.2120200   -12.900    -2.500  
+901016 48180.00 I   .268687  .000237   .191236  .000365  I -.2143357  .0000200  2.3898 0.0116  I   -13.114     .276    -1.953     .298   .269000   .190700  -.2143600   -12.900    -2.400  
+901017 48181.00 I   .266124  .000214   .187938  .000336  I -.2166969  .0000127  2.3223 0.0119  I   -13.025     .243    -1.816     .106   .266300   .187300  -.2167500   -12.700    -2.200  
+901018 48182.00 I   .263546  .000232   .184709  .000401  I -.2189627  .0000128  2.2019 0.0103  I   -12.995     .299    -1.782     .166   .263500   .184100  -.2190000   -12.600    -2.200  
+901019 48183.00 I   .260909  .000271   .181498  .000458  I -.2210914  .0000163  2.0537 0.0118  I   -12.987     .302    -1.859     .193   .260700   .180900  -.2211300   -12.100    -2.200  
+901020 48184.00 I   .258171  .000428   .178283  .000459  I -.2230666  .0000198  1.8952 0.0135  I   -13.034     .302    -1.984     .193   .258000   .178100  -.2231500   -11.900    -2.500  
+901021 48185.00 I   .255334  .000448   .175151  .000463  I -.2248874  .0000214  1.7536 0.0139  I   -13.137     .367    -2.195     .197   .255400   .175300  -.2249700   -12.000    -2.300  
+901022 48186.00 I   .252529  .000404   .172099  .000426  I -.2265925  .0000194  1.6683 0.0133  I   -13.082     .367    -2.385     .197   .252600   .172300  -.2266200   -12.400    -2.100  
+901023 48187.00 I   .249944  .000374   .169070  .000357  I -.2282489  .0000159  1.6578 0.0127  I   -12.685     .629    -2.458     .162   .250000   .169100  -.2282900   -12.000    -2.100  
+901024 48188.00 I   .247695  .000424   .166030  .000281  I -.2299310  .0000165  1.7161 0.0160  I   -12.047     .750    -2.444     .298   .247600   .165700  -.2300200   -10.800    -2.300  
+901025 48189.00 I   .245667  .000431   .163016  .000288  I -.2316994  .0000277  1.8294 0.0178  I   -11.556     .750    -2.427     .298   .245400   .162000  -.2317700    -9.700    -2.900  
+901026 48190.00 I   .243703  .000432   .160079  .000377  I -.2336061  .0000316  1.9916 0.0201  I   -11.444     .712    -2.398     .111   .244100   .158900  -.2337400    -9.300    -2.900  
+901027 48191.00 I   .241754  .000251   .157249  .000361  I -.2356992  .0000291  2.2038 0.0203  I   -11.368     .960    -2.274     .136   .242200   .155800  -.2357700    -9.400    -3.000  
+901028 48192.00 I   .239851  .000240   .154550  .000326  I -.2380273  .0000256  2.4570 0.0216  I   -11.158     .944    -2.056     .143   .240300   .153400  -.2381500    -9.900    -2.900  
+901029 48193.00 I   .238015  .000258   .152003  .000377  I -.2406142  .0000319  2.7132 0.0215  I   -11.030     .981    -1.851     .169   .238600   .151400  -.2406500   -10.600    -2.800  
+901030 48194.00 I   .236208  .000272   .149592  .000419  I -.2434364  .0000346  2.9176 0.0210  I   -11.317     .923    -1.900     .169   .236800   .149200  -.2435300   -10.900    -2.800  
+901031 48195.00 I   .234410  .000307   .147255  .000441  I -.2464136  .0000272  3.0145 0.0189  I   -11.651     .923    -2.035     .169   .235100   .147300  -.2465500   -10.800    -2.600  
+9011 1 48196.00 I   .232557  .000257   .144959  .000404  I -.2494178  .0000150  2.9686 0.0157  I   -11.755     .996    -2.037     .152   .233000   .144000  -.2494400   -10.600    -2.600  
+9011 2 48197.00 I   .230548  .000360   .142681  .000270  I -.2523024  .0000157  2.7777 0.0124  I   -11.620     .692    -1.949     .111   .231200   .141800  -.2522500   -10.100    -2.600  
+9011 3 48198.00 I   .228263  .000473   .140412  .000220  I -.2549381  .0000197  2.4816 0.0132  I   -11.270     .500    -1.920     .298   .228500   .139400  -.2549800    -9.600    -2.400  
+9011 4 48199.00 I   .225562  .000484   .138140  .000201  I -.2572554  .0000213  2.1550 0.0145  I   -10.804     .500    -1.935     .298   .226000   .137100  -.2573500    -9.500    -2.400  
+9011 5 48200.00 I   .222305  .000514   .135834  .000200  I -.2592738  .0000212  1.9056 0.0184  I   -10.492     .500    -1.842     .298   .222400   .134500  -.2594700   -10.000    -2.600  
+9011 6 48201.00 I   .218641  .000438   .133500  .000141  I -.2611209  .0000300  1.8190 0.0169  I   -10.567     .500    -1.633     .298   .218900   .132000  -.2611900   -10.900    -2.300  
+9011 7 48202.00 I   .214857  .000376   .131159  .000170  I -.2629680  .0000264  1.9008 0.0214  I   -10.943     .372    -1.501     .107   .214800   .129500  -.2631600   -11.200    -2.100  
+9011 8 48203.00 I   .211202  .000292   .128824  .000186  I -.2649608  .0000306  2.0973 0.0202  I   -11.255     .142    -1.575     .123   .211000   .127600  -.2650800   -11.100    -2.100  
+9011 9 48204.00 I   .207788  .000292   .126509  .000186  I -.2671750  .0000306  2.3308 0.0216  I   -11.248     .142    -1.724     .123   .207300   .125300  -.2672500   -10.900    -2.200  
+901110 48205.00 I   .204666  .000291   .124230  .000226  I -.2696089  .0000306  2.5237 0.0207  I   -10.997     .142    -1.723     .123   .203900   .123000  -.2697100   -10.300    -2.300  
+901111 48206.00 I   .201775  .000188   .121988  .000232  I -.2721936  .0000278  2.6300 0.0171  I   -10.717     .162    -1.513     .140   .201100   .120800  -.2724300    -9.800    -2.200  
+901112 48207.00 I   .199017  .000158   .119764  .000203  I -.2748376  .0000154  2.6422 0.0149  I   -10.492     .152    -1.218     .133   .198000   .118600  -.2750100    -9.400    -2.100  
+901113 48208.00 I   .196297  .000141   .117541  .000204  I -.2774490  .0000108  2.5673 0.0094  I   -10.299     .206     -.945     .136   .195400   .116400  -.2775800    -9.000    -2.100  
+901114 48209.00 I   .193519  .000141   .115309  .000204  I -.2799492  .0000107  2.4233 0.0083  I   -10.141     .206     -.687     .136   .192800   .113800  -.2800400    -9.100    -1.900  
+901115 48210.00 I   .190608  .000190   .113086  .000250  I -.2822820  .0000126  2.2383 0.0090  I   -10.061     .206     -.459     .136   .189900   .111800  -.2823400    -9.000    -1.800  
+901116 48211.00 I   .187568  .000177   .110916  .000220  I -.2844222  .0000145  2.0425 0.0102  I   -10.119     .185     -.484     .135   .186900   .109500  -.2844000    -8.900    -1.800  
+901117 48212.00 I   .184445  .000189   .108853  .000350  I -.2863721  .0000161  1.8622 0.0127  I   -10.250     .399     -.798     .116   .183900   .107900  -.2863600    -8.900    -1.900  
+901118 48213.00 I   .181286  .000218   .106953  .000483  I -.2881592  .0000209  1.7198 0.0138  I   -10.285     .481    -1.136     .112   .180700   .106100  -.2881300    -8.900    -1.800  
+901119 48214.00 I   .178131  .000225   .105240  .000506  I -.2898352  .0000224  1.6481 0.0152  I   -10.021     .580    -1.186     .298   .177700   .104400  -.2898400    -9.000    -1.900  
+901120 48215.00 I   .175047  .000225   .103600  .000506  I -.2914843  .0000221  1.6632 0.0149  I    -9.368     .580     -.974     .298   .174700   .102800  -.2915300    -9.100    -1.900  
+901121 48216.00 I   .172026  .000230   .102002  .000474  I -.2931847  .0000197  1.7475 0.0149  I    -8.648     .580     -.732     .298   .171500   .101200  -.2932900    -9.200    -1.600  
+901122 48217.00 I   .169017  .000223   .100466  .000494  I -.2949979  .0000200  1.8874 0.0142  I    -8.373     .575     -.651     .298   .168400   .099600  -.2951400    -9.300    -1.600  
+901123 48218.00 I   .165974  .000244   .098992  .000421  I -.2969738  .0000204  2.0701 0.0126  I    -8.595     .531     -.685     .298   .165400   .097800  -.2970900    -9.300    -1.500  
+901124 48219.00 I   .162854  .000230   .097582  .000272  I -.2991467  .0000154  2.2785 0.0134  I    -8.985     .531     -.695     .298   .162300   .096300  -.2992100    -9.400    -1.300  
+901125 48220.00 I   .159599  .000272   .096223  .000143  I -.3015319  .0000174  2.4903 0.0131  I    -9.224     .338     -.690     .126   .159200   .094800  -.3015500    -9.200    -1.300  
+901126 48221.00 I   .156136  .000258   .094901  .000139  I -.3041180  .0000211  2.6743 0.0128  I    -9.307     .305     -.762     .115   .155800   .093300  -.3041400    -9.000    -1.300  
+901127 48222.00 I   .152413  .000305   .093609  .000234  I -.3068584  .0000188  2.7920 0.0143  I    -9.369     .391     -.846     .177   .152200   .092400  -.3068700    -8.800    -1.300  
+901128 48223.00 I   .148427  .000326   .092345  .000242  I -.3096706  .0000193  2.8154 0.0137  I    -9.474     .401     -.709     .200   .147900   .091200  -.3097300    -8.300    -1.500  
+901129 48224.00 I   .144337  .000326   .091103  .000242  I -.3124545  .0000199  2.7348 0.0139  I    -9.602     .401     -.429     .200   .143600   .090000  -.3125400    -7.900    -1.500  
+901130 48225.00 I   .140317  .000326   .089885  .000242  I -.3151098  .0000199  2.5632 0.0153  I    -9.691     .401     -.318     .200   .139300   .088800  -.3152100    -7.500    -1.400  
+9012 1 48226.00 I   .136535  .000383   .088739  .000354  I -.3175645  .0000233  2.3426 0.0116  I    -9.439     .458     -.431     .206   .135500   .087700  -.3176400    -7.000    -1.400  
+9012 2 48227.00 I   .132960  .000365   .087668  .000326  I -.3198018  .0000119  2.1426 0.0145  I    -8.764     .507     -.601     .213   .131700   .086600  -.3198800    -6.600    -1.400  
+9012 3 48228.00 I   .129504  .000444   .086654  .000331  I -.3218807  .0000171  2.0357 0.0111  I    -8.039     .479     -.585     .164   .128400   .085500  -.3219400    -6.200    -1.200  
+9012 4 48229.00 I   .126079  .000380   .085679  .000266  I -.3239147  .0000188  2.0532 0.0119  I    -7.766     .422     -.311     .165   .125100   .084500  -.3240300    -6.000    -1.200  
+9012 5 48230.00 I   .122590  .000380   .084722  .000266  I -.3260221  .0000165  2.1756 0.0126  I    -8.074     .422     -.016     .165   .121500   .083500  -.3261200    -6.900    -1.500  
+9012 6 48231.00 I   .119050  .000390   .083780  .000334  I -.3282816  .0000169  2.3450 0.0108  I    -8.507     .422     -.030     .165   .117900   .082600  -.3284000    -7.000    -1.600  
+9012 7 48232.00 I   .115520  .000313   .082857  .000347  I -.3307054  .0000140  2.4941 0.0121  I    -8.601     .461     -.364     .136   .114300   .081700  -.3308400    -7.100    -1.600  
+9012 8 48233.00 I   .112032  .000233   .081940  .000312  I -.3332465  .0000173  2.5733 0.0106  I    -8.434     .448     -.652     .298   .110800   .080800  -.3333800    -7.100    -1.700  
+9012 9 48234.00 I   .108594  .000290   .081004  .000385  I -.3358221  .0000160  2.5629 0.0121  I    -8.327     .417     -.652     .298   .107300   .079900  -.3359400    -7.200    -1.700  
+901210 48235.00 I   .105159  .000275   .080000  .000365  I -.3383410  .0000168  2.4586 0.0111  I    -8.364     .417     -.441     .298   .103800   .078900  -.3384200    -7.200    -1.600  
+901211 48236.00 I   .101696  .000249   .078953  .000359  I -.3407106  .0000153  2.2684 0.0102  I    -8.415     .417     -.259     .298   .100400   .077900  -.3407500    -7.200    -1.600  
+901212 48237.00 I   .098177  .000162   .077921  .000443  I -.3428633  .0000116  2.0349 0.0099  I    -8.443     .421     -.200     .298   .097100   .076900  -.3429000    -7.200    -1.500  
+901213 48238.00 I   .094582  .000187   .076908  .000480  I -.3447823  .0000127  1.8071 0.0085  I    -8.454     .353     -.113     .114   .093700   .075800  -.3448300    -7.100    -1.400  
+901214 48239.00 I   .090989  .000187   .075839  .000480  I -.3464901  .0000125  1.6170 0.0108  I    -8.431     .353      .047     .114   .090400   .074700  -.3465700    -7.100    -1.300  
+901215 48240.00 I   .087493  .000169   .074656  .000501  I -.3480344  .0000174  1.4813 0.0097  I    -8.305     .364      .185     .116   .087200   .073500  -.3481300    -7.100    -1.200  
+901216 48241.00 I   .084124  .000160   .073460  .000484  I -.3494722  .0000149  1.4040 0.0108  I    -8.147     .427      .135     .113   .083900   .072500  -.3495700    -7.100    -1.100  
+901217 48242.00 I   .080833  .000146   .072344  .000434  I -.3508638  .0000128  1.3907 0.0110  I    -8.037     .423      .003     .129   .080600   .071500  -.3509700    -7.100     -.900  
+901218 48243.00 I   .077561  .000184   .071380  .000364  I -.3522759  .0000163  1.4443 0.0107  I    -7.999     .421     -.026     .139   .077200   .070600  -.3523800    -7.100     -.800  
+901219 48244.00 I   .074250  .000186   .070638  .000308  I -.3537777  .0000171  1.5737 0.0138  I    -8.092     .476      .036     .124   .073700   .069800  -.3538900    -7.200     -.700  
+901220 48245.00 I   .070866  .000186   .070146  .000308  I -.3554434  .0000222  1.7633 0.0142  I    -8.252     .476      .117     .124   .070200   .069200  -.3555600    -7.200     -.700  
+901221 48246.00 I   .067377  .000185   .069860  .000333  I -.3573110  .0000227  1.9729 0.0146  I    -8.381     .515      .132     .134   .066500   .068600  -.3574000    -7.100     -.800  
+901222 48247.00 I   .063775  .000185   .069730  .000375  I -.3593874  .0000191  2.1770 0.0253  I    -8.297     .514      .063     .144   .062800   .068200  -.3594600    -7.100     -.900  
+901223 48248.00 I   .060069  .000201   .069705  .000436  I -.3616542  .0000452  2.3489 0.0235  I    -7.960     .594     -.016     .140   .058900   .068000  -.3617100    -7.100     -.900  
+901224 48249.00 I   .056270  .000389   .069732  .000258  I -.3640664  .0000430  2.4646 0.0320  I    -7.504     .594     -.072     .140   .055000   .067800  -.3641200    -7.000    -1.000  
+901225 48250.00 I   .052379  .000366   .069786  .000243  I -.3665589  .0000454  2.5067 0.0269  I    -7.092     .571     -.118     .134   .050900   .067700  -.3666200    -7.000    -1.100  
+901226 48251.00 I   .048355  .000299   .069869  .000328  I -.3690509  .0000322  2.4621 0.0256  I    -6.893     .571     -.101     .134   .046900   .067700  -.3691300    -6.900    -1.100  
+901227 48252.00 I   .044145  .000321   .069989  .000425  I -.3714556  .0000237  2.3349 0.0211  I    -7.061     .528      .023     .211   .042800   .067800  -.3715300    -6.900    -1.200  
+901228 48253.00 I   .039730  .000325   .070144  .000434  I -.3737009  .0000272  2.1483 0.0185  I    -7.614     .528      .125     .211   .038700   .067900  -.3737700    -6.800    -1.100  
+901229 48254.00 I   .035225  .000325   .070309  .000434  I -.3757491  .0000285  1.9523 0.0197  I    -8.167     .528      .061     .211   .034600   .068100  -.3757900    -6.800    -1.100  
+901230 48255.00 I   .030776  .000325   .070470  .000434  I -.3776271  .0000286  1.8211 0.0184  I    -8.243     .528     -.090     .211   .030700   .068400  -.3776600    -6.800    -1.000  
+901231 48256.00 I   .026474  .000249   .070678  .000529  I -.3794330  .0000234  1.8149 0.0166  I    -7.885     .538     -.098     .250   .026900   .068800  -.3794600    -6.700     -.900  
+91 1 1 48257.00 I   .022389  .000235   .070986  .000487  I  .6186975  .0000170  1.9454 0.0151  I    -7.510     .598      .134     .204   .023100   .069300   .6186700    -6.700     -.800  
+91 1 2 48258.00 I   .018591  .000253   .071447  .000317  I  .6166447  .0000190  2.1705 0.0106  I    -7.378     .754      .394     .171   .019500   .070000   .6166000    -6.600     -.800  
+91 1 3 48259.00 I   .015151  .000253   .072113  .000317  I  .6143495  .0000125  2.4165 0.0174  I    -7.377     .754      .386     .171   .016100   .070700   .6142800    -6.600     -.700  
+91 1 4 48260.00 I   .012118  .000334   .073018  .000392  I  .6118302  .0000292  2.6071 0.0133  I    -7.330     .737      .106     .191   .013200   .072200   .6117600    -6.600     -.900  
+91 1 5 48261.00 I   .009382  .000291   .074132  .000359  I  .6091699  .0000235  2.6940 0.0174  I    -7.116     .737     -.012     .191   .010000   .073200   .6091200    -6.700     -.900  
+91 1 6 48262.00 I   .006782  .000345   .075384  .000278  I  .6064782  .0000191  2.6730 0.0195  I    -6.952     .657      .157     .181   .006800   .074300   .6064400    -6.700     -.900  
+91 1 7 48263.00 I   .004177  .000391   .076691  .000295  I  .6038514  .0000310  2.5695 0.0184  I    -7.033     .591      .248     .179   .003600   .075500   .6038400    -6.600    -1.000  
+91 1 8 48264.00 I   .001418  .000381   .077970  .000288  I  .6013588  .0000315  2.4071 0.0221  I    -7.208     .473      .045     .168   .000400   .076600   .6013600    -6.600    -1.000  
+91 1 9 48265.00 I  -.001661  .000381   .079172  .000288  I  .5990451  .0000315  2.2209 0.0230  I    -7.248     .428     -.143     .152  -.002800   .077800   .5990600    -6.500    -1.000  
+91 110 48266.00 I  -.005050  .000366   .080296  .000301  I  .5969117  .0000334  2.0505 0.0204  I    -7.294     .339     -.146     .121  -.006100   .078800   .5969200    -6.500    -1.000  
+91 111 48267.00 I  -.008653  .000300   .081354  .000296  I  .5949329  .0000258  1.9138 0.0255  I    -7.460     .521     -.042     .102  -.009500   .079800   .5949300    -6.400    -1.000  
+91 112 48268.00 I  -.012377  .000206   .082340  .000345  I  .5930695  .0000386  1.8211 0.0196  I    -7.638     .548      .008     .298  -.013000   .080700   .5930700    -6.400    -1.000  
+91 113 48269.00 I  -.016122  .000208   .083186  .000428  I  .5912743  .0000294  1.7778 0.0235  I    -7.753     .629     -.007     .298  -.016600   .081500   .5912800    -6.400    -1.000  
+91 114 48270.00 I  -.019806  .000292   .083830  .000431  I  .5894949  .0000267  1.7917 0.0187  I    -7.869     .559      .062     .122  -.020300   .082100   .5895000    -6.500     -.900  
+91 115 48271.00 I  -.023464  .000256   .084317  .000436  I  .5876705  .0000230  1.8668 0.0144  I    -7.962     .571      .261     .147  -.024000   .082700   .5876600    -6.600     -.900  
+91 116 48272.00 I  -.027175  .000208   .084736  .000445  I  .5857450  .0000107  1.9909 0.0134  I    -7.901     .499      .404     .136  -.027700   .083300   .5857400    -6.700     -.800  
+91 117 48273.00 I  -.031011  .000231   .085171  .000444  I  .5836807  .0000136  2.1392 0.0093  I    -7.606     .284      .232     .165  -.031400   .083700   .5836800    -6.800     -.800  
+91 118 48274.00 I  -.034995  .000236   .085646  .000456  I  .5814692  .0000151  2.2799 0.0132  I    -7.207     .284     -.097     .165  -.035100   .084200   .5814600    -6.900     -.700  
+91 119 48275.00 I  -.039044  .000236   .086098  .000456  I  .5791302  .0000227  2.3929 0.0134  I    -6.976     .284     -.338     .165  -.038700   .084800   .5791000    -7.000     -.700  
+91 120 48276.00 I  -.043017  .000347   .086553  .000364  I  .5766972  .0000221  2.4646 0.0149  I    -6.944     .299     -.403     .134  -.042200   .085400   .5766400    -7.100     -.700  
+91 121 48277.00 I  -.046776  .000253   .087092  .000319  I  .5742211  .0000193  2.4758 0.0163  I    -6.989     .275     -.314     .142  -.045600   .086100   .5741300    -7.200     -.700  
+91 122 48278.00 I  -.050215  .000318   .087788  .000285  I  .5717685  .0000240  2.4181 0.0159  I    -7.048     .218     -.151     .144  -.049000   .086900   .5716400    -7.300     -.700  
+91 123 48279.00 I  -.053236  .000351   .088712  .000283  I  .5694044  .0000253  2.3020 0.0172  I    -7.174     .218      .019     .144  -.052200   .087800   .5692800    -7.300     -.700  
+91 124 48280.00 I  -.055812  .000351   .089927  .000283  I  .5671813  .0000246  2.1356 0.0164  I    -7.469     .218      .128     .144  -.055300   .088900   .5670700    -7.400     -.800  
+91 125 48281.00 I  -.058173  .000330   .091415  .000261  I  .5651398  .0000210  1.9494 0.0156  I    -7.933     .218      .155     .144  -.058500   .090200   .5650600    -7.300     -.800  
+91 126 48282.00 I  -.060588  .000331   .093097  .000376  I  .5632680  .0000191  1.8067 0.0160  I    -8.348     .378      .015     .123  -.061800   .091500   .5632300    -7.200     -.900  
+91 127 48283.00 I  -.063289  .000353   .094881  .000497  I  .5614935  .0000241  1.7625 0.0134  I    -8.406     .449     -.300     .298  -.065100   .092900   .5614900    -7.100     -.900  
+91 128 48284.00 I  -.066451  .000364   .096671  .000449  I  .5597015  .0000189  1.8426 0.0146  I    -7.969     .515     -.610     .298  -.068600   .094400   .5597000    -6.800    -1.000  
+91 129 48285.00 I  -.070208  .000311   .098382  .000447  I  .5577729  .0000164  2.0287 0.0132  I    -7.170     .450     -.738     .298  -.072100   .096000   .5577700    -6.500    -1.100  
+91 130 48286.00 I  -.074442  .000361   .100022  .000411  I  .5556263  .0000184  2.2681 0.0104  I    -6.388     .450     -.746     .298  -.075800   .097500   .5556000    -6.200    -1.200  
+91 131 48287.00 I  -.078910  .000338   .101594  .000385  I  .5532423  .0000127  2.4906 0.0121  I    -5.811     .431     -.753     .298  -.079600   .099100   .5531700    -5.800    -1.400  
+91 2 1 48288.00 I  -.083389  .000392   .103081  .000366  I  .5506707  .0000157  2.6362 0.0098  I    -5.482     .335     -.738     .103  -.083500   .100600   .5505600    -5.500    -1.500  
+91 2 2 48289.00 I  -.087740  .000394   .104469  .000213  I  .5480040  .0000150  2.6794 0.0109  I    -5.521     .326     -.698     .104  -.087400   .102200   .5478600    -5.100    -1.600  
+91 2 3 48290.00 I  -.091885  .000394   .105752  .000213  I  .5453487  .0000152  2.6123 0.0127  I    -5.999     .288     -.667     .298  -.090900   .103500   .5452100    -5.600    -1.800  
+91 2 4 48291.00 I  -.095784  .000408   .106978  .000237  I  .5428091  .0000205  2.4562 0.0117  I    -6.696     .328     -.669     .298  -.094400   .104800   .5426800    -5.500    -1.900  
+91 2 5 48292.00 I  -.099377  .000380   .108224  .000248  I  .5404512  .0000177  2.2555 0.0143  I    -7.245     .293     -.728     .162  -.097900   .106200   .5403600    -5.400    -1.900  
+91 2 6 48293.00 I  -.102658  .000371   .109555  .000275  I  .5382971  .0000198  2.0577 0.0135  I    -7.480     .176     -.807     .201  -.101500   .107800   .5382100    -5.300    -2.000  
+91 2 7 48294.00 I  -.105703  .000371   .110999  .000275  I  .5363232  .0000205  1.8976 0.0146  I    -7.517     .176     -.780     .201  -.105000   .109400   .5362300    -5.200    -2.000  
+91 2 8 48295.00 I  -.108620  .000327   .112573  .000278  I  .5344856  .0000215  1.7864 0.0129  I    -7.461     .176     -.625     .201  -.108400   .111100   .5343900    -5.100    -2.100  
+91 2 9 48296.00 I  -.111491  .000290   .114302  .000256  I  .5327295  .0000155  1.7379 0.0121  I    -7.282     .193     -.686     .227  -.111700   .112900   .5326300    -5.000    -2.100  
+91 210 48297.00 I  -.114367  .000311   .116185  .000203  I  .5309856  .0000111  1.7621 0.0090  I    -6.970     .337    -1.042     .209  -.114900   .114800   .5308900    -5.000    -2.200  
+91 211 48298.00 I  -.117315  .000292   .118198  .000224  I  .5291822  .0000090  1.8558 0.0070  I    -6.671     .363    -1.419     .200  -.118000   .116900   .5290900    -4.900    -2.200  
+91 212 48299.00 I  -.120404  .000290   .120310  .000180  I  .5272551  .0000085  2.0063 0.0061  I    -6.553     .349    -1.570     .179  -.121100   .119100   .5271700    -4.900    -2.200  
+91 213 48300.00 I  -.123664  .000287   .122513  .000181  I  .5251586  .0000083  2.1898 0.0058  I    -6.611     .349    -1.453     .179  -.124100   .121400   .5251000    -5.000    -2.200  
+91 214 48301.00 I  -.126908  .000302   .124910  .000179  I  .5228707  .0000078  2.3875 0.0072  I    -6.635     .349    -1.368     .179  -.127100   .123900   .5228300    -5.100    -2.200  
+91 215 48302.00 I  -.130112  .000295   .127563  .000171  I  .5203904  .0000118  2.5646 0.0084  I    -6.576     .570    -1.369     .157  -.130100   .126500   .5203900    -5.200    -2.200  
+91 216 48303.00 I  -.133270  .000322   .130449  .000145  I  .5177638  .0000149  2.6748 0.0122  I    -6.571     .637    -1.365     .133  -.133100   .129200   .5177900    -5.300    -2.300  
+91 217 48304.00 I  -.136368  .000261   .133521  .000309  I  .5150737  .0000214  2.6861 0.0148  I    -6.721     .697    -1.356     .103  -.136100   .132000   .5151300    -5.500    -2.300  
+91 218 48305.00 I  -.139405  .000324   .136727  .000397  I  .5124253  .0000256  2.5961 0.0156  I    -6.999     .793    -1.374     .298  -.139100   .134900   .5124700    -5.600    -2.300  
+91 219 48306.00 I  -.142389  .000285   .140004  .000487  I  .5099051  .0000226  2.4353 0.0163  I    -7.288     .793    -1.409     .298  -.142200   .137800   .5099100    -5.800    -2.400  
+91 220 48307.00 I  -.145325  .000301   .143291  .000462  I  .5075665  .0000202  2.2393 0.0175  I    -7.482     .651    -1.429     .298  -.145300   .140800   .5075200    -5.900    -2.400  
+91 221 48308.00 I  -.148250  .000290   .146514  .000534  I  .5054215  .0000267  2.0584 0.0165  I    -7.553     .302    -1.416     .298  -.148300   .143800   .5053200    -6.100    -2.400  
+91 222 48309.00 I  -.151190  .000252   .149542  .000462  I  .5034249  .0000260  1.9520 0.0193  I    -7.587     .302    -1.468     .298  -.151300   .146800   .5033000    -6.200    -2.500  
+91 223 48310.00 I  -.154175  .000251   .152268  .000453  I  .5014858  .0000278  1.9409 0.0185  I    -7.667     .280    -1.725     .298  -.154300   .149800   .5013600    -6.300    -2.500  
+91 224 48311.00 I  -.157177  .000232   .154778  .000401  I  .4995116  .0000264  2.0244 0.0184  I    -7.708     .306    -2.149     .298  -.157100   .152800   .4994000    -6.300    -2.600  
+91 225 48312.00 I  -.160098  .000243   .157240  .000364  I  .4974054  .0000241  2.2026 0.0199  I    -7.582     .333    -2.536     .298  -.159900   .155700   .4973000    -6.400    -2.600  
+91 226 48313.00 I  -.162850  .000202   .159794  .000263  I  .4950844  .0000299  2.4467 0.0166  I    -7.253     .446    -2.630     .298  -.162600   .158600   .4949800    -6.400    -2.700  
+91 227 48314.00 I  -.165376  .000202   .162467  .000263  I  .4925069  .0000229  2.7060 0.0182  I    -6.828     .473    -2.375     .298  -.165200   .161500   .4923900    -6.400    -2.700  
+91 228 48315.00 I  -.167647  .000200   .165250  .000262  I  .4896908  .0000208  2.9102 0.0158  I    -6.463     .473    -1.961     .298  -.167700   .164300   .4895600    -6.400    -2.800  
+91 3 1 48316.00 I  -.169720  .000266   .168114  .000262  I  .4867258  .0000217  2.9967 0.0145  I    -6.350     .518    -1.712     .298  -.170100   .167200   .4866100    -6.400    -2.800  
+91 3 2 48317.00 I  -.171679  .000249   .171052  .000247  I  .4837438  .0000203  2.9440 0.0181  I    -6.423     .439    -1.710     .298  -.172400   .170100   .4836600    -6.400    -2.800  
+91 3 3 48318.00 I  -.173596  .000372   .174060  .000264  I  .4808788  .0000289  2.7683 0.0192  I    -6.584     .470    -1.861     .298  -.174500   .173000   .4808300    -6.400    -2.900  
+91 3 4 48319.00 I  -.175545  .000380   .177130  .000164  I  .4782346  .0000326  2.5103 0.0217  I    -6.804     .367    -2.056     .298  -.176500   .175900   .4782300    -6.500    -3.000  
+91 3 5 48320.00 I  -.177585  .000393   .180250  .000174  I  .4758656  .0000323  2.2301 0.0214  I    -7.014     .223    -2.173     .298  -.178400   .179300   .4758600    -6.300    -2.400  
+91 3 6 48321.00 I  -.179691  .000431   .183430  .000208  I  .4737648  .0000277  1.9787 0.0187  I    -7.138     .223    -2.170     .298  -.180200   .182700   .4737500    -6.300    -2.400  
+91 3 7 48322.00 I  -.181814  .000322   .186689  .000199  I  .4718903  .0000188  1.7808 0.0168  I    -7.128     .186    -2.125     .298  -.181900   .186200   .4718600    -6.300    -2.500  
+91 3 8 48323.00 I  -.183873  .000316   .190040  .000202  I  .4701765  .0000191  1.6629 0.0135  I    -6.910     .167    -2.205     .298  -.183500   .189700   .4701000    -6.400    -2.600  
+91 3 9 48324.00 I  -.185715  .000315   .193494  .000269  I  .4685319  .0000194  1.6428 0.0139  I    -6.464     .167    -2.473     .298  -.185200   .193200   .4684200    -6.500    -2.600  
+91 310 48325.00 I  -.187247  .000310   .197079  .000269  I  .4668623  .0000203  1.7085 0.0117  I    -5.902     .150    -2.802     .298  -.186800   .196700   .4667300    -6.600    -2.700  
+91 311 48326.00 I  -.188552  .000232   .200801  .000263  I  .4650913  .0000132  1.8449 0.0130  I    -5.448     .791    -3.012     .298  -.188400   .200300   .4649500    -6.700    -2.800  
+91 312 48327.00 I  -.189749  .000424   .204643  .000187  I  .4631528  .0000163  2.0402 0.0112  I    -5.317     .460    -3.024     .298  -.189900   .203900   .4630100    -6.900    -2.900  
+91 313 48328.00 I  -.190961  .000510   .208577  .000182  I  .4610003  .0000182  2.2672 0.0124  I    -5.544     .561    -2.927     .298  -.191400   .207600   .4608400    -7.000    -3.000  
+91 314 48329.00 I  -.192341  .000510   .212539  .000182  I  .4586217  .0000186  2.4843 0.0130  I    -5.948     .650    -2.852     .298  -.192800   .211300   .4584300    -7.100    -3.200  
+91 315 48330.00 I  -.193994  .000510   .216441  .000182  I  .4560330  .0000185  2.6975 0.0129  I    -6.350     .650    -2.822     .298  -.194200   .215000   .4557900    -7.100    -3.200  
+91 316 48331.00 I  -.195667  .000505   .220202  .000135  I  .4532397  .0000178  2.8718 0.0126  I    -6.707     .710    -2.766     .298  -.195600   .218700   .4529900    -7.100    -3.300  
+91 317 48332.00 I  -.197292  .000468   .223842  .000131  I  .4503304  .0000171  2.9231 0.0140  I    -6.887     .634    -2.692     .298  -.197000   .222400   .4501100    -7.000    -3.400  
+91 318 48333.00 I  -.198813  .000379   .227397  .000167  I  .4474393  .0000216  2.8371 0.0183  I    -6.928     .627    -2.682     .298  -.198400   .226100   .4472800    -6.900    -3.500  
+91 319 48334.00 I  -.200148  .000360   .230902  .000232  I  .4446940  .0000323  2.6379 0.0196  I    -6.963     .562    -2.791     .298  -.199700   .229900   .4445900    -6.800    -3.600  
+91 320 48335.00 I  -.201247  .000255   .234395  .000242  I  .4421798  .0000326  2.3900 0.0227  I    -6.974     .324    -3.001     .298  -.201100   .233600   .4421300    -6.600    -3.600  
+91 321 48336.00 I  -.202195  .000227   .237934  .000224  I  .4399037  .0000318  2.1730 0.0211  I    -6.848     .324    -3.244     .298  -.202600   .237300   .4398900    -6.400    -3.700  
+91 322 48337.00 I  -.203113  .000305   .241573  .000191  I  .4378071  .0000267  2.0360 0.0247  I    -6.577     .607    -3.461     .298  -.204000   .241100   .4378100    -6.200    -3.800  
+91 323 48338.00 I  -.204155  .000306   .245328  .000213  I  .4357970  .0000378  2.0029 0.0208  I    -6.261     .692    -3.657     .298  -.205400   .245000   .4358000    -6.000    -3.800  
+91 324 48339.00 I  -.205483  .000305   .249211  .000200  I  .4337687  .0000319  2.0676 0.0247  I    -5.961     .718    -3.888     .298  -.206900   .248800   .4337400    -5.800    -3.900  
+91 325 48340.00 I  -.207237  .000298   .253232  .000168  I  .4316295  .0000317  2.2293 0.0205  I    -5.617     .801    -4.176     .298  -.208400   .252800   .4315400    -5.600    -3.900  
+91 326 48341.00 I  -.209344  .000362   .257362  .000170  I  .4292805  .0000257  2.4797 0.0205  I    -5.165     .801    -4.393     .298  -.209800   .256700   .4291300    -5.400    -4.000  
+91 327 48342.00 I  -.211542  .000365   .261519  .000166  I  .4266726  .0000260  2.7224 0.0191  I    -4.907     .976    -4.402     .298  -.211300   .260700   .4265000    -5.200    -4.000  
+91 328 48343.00 I  -.213596  .000394   .265659  .000159  I  .4238689  .0000282  2.8655 0.0199  I    -4.920    1.093    -4.183     .112  -.212600   .264700   .4237100    -5.000    -4.100  
+91 329 48344.00 I  -.215298  .000386   .269752  .000176  I  .4209839  .0000301  2.8818 0.0181  I    -5.118    1.093    -3.877     .112  -.214000   .268800   .4208500    -4.900    -4.200  
+91 330 48345.00 I  -.216509  .000438   .273776  .000358  I  .4181445  .0000227  2.7806 0.0176  I    -5.334    1.168    -3.696     .127  -.215100   .272900   .4180100    -4.600    -4.200  
+91 331 48346.00 I  -.217320  .000427   .277756  .000350  I  .4154460  .0000183  2.6097 0.0144  I    -5.428    1.033    -3.744     .112  -.216200   .277000   .4152800    -4.400    -4.300  
+91 4 1 48347.00 I  -.217857  .000403   .281739  .000324  I  .4129329  .0000177  2.4156 0.0111  I    -5.355     .958    -3.941     .165  -.217200   .281000   .4127500    -4.200    -4.400  
+91 4 2 48348.00 I  -.218249  .000376   .285770  .000441  I  .4106103  .0000127  2.2350 0.0109  I    -5.172     .683    -4.111     .170  -.218100   .285200   .4104000    -4.100    -4.400  
+91 4 3 48349.00 I  -.218610  .000376   .289880  .000441  I  .4084511  .0000128  2.0897 0.0088  I    -4.967     .683    -4.150     .170  -.218800   .289300   .4082400    -4.000    -4.500  
+91 4 4 48350.00 I  -.219006  .000376   .294038  .000441  I  .4064165  .0000123  1.9875 0.0108  I    -4.883     .683    -4.132     .170  -.219600   .293400   .4062000    -4.000    -4.600  
+91 4 5 48351.00 I  -.219449  .000336   .298196  .000410  I  .4044592  .0000174  1.9362 0.0103  I    -4.834     .683    -4.203     .170  -.220200   .297300   .4042500    -4.100    -4.600  
+91 4 6 48352.00 I  -.219906  .000303   .302322  .000261  I  .4025264  .0000164  1.9382 0.0144  I    -4.711     .606    -4.438     .172  -.220600   .301400   .4023300    -4.100    -4.700  
+91 4 7 48353.00 I  -.220303  .000213   .306406  .000221  I  .4005663  .0000229  1.9897 0.0145  I    -4.535     .118    -4.731     .114  -.220700   .305400   .4004000    -4.100    -4.700  
+91 4 8 48354.00 I  -.220558  .000200   .310445  .000166  I  .3985331  .0000240  2.0828 0.0166  I    -4.408     .237    -4.865     .118  -.220700   .309400   .3983700    -4.100    -4.800  
+91 4 9 48355.00 I  -.220598  .000200   .314438  .000166  I  .3963880  .0000240  2.2140 0.0160  I    -4.435     .237    -4.746     .118  -.220400   .313400   .3962200    -4.100    -4.900  
+91 410 48356.00 I  -.220373  .000230   .318404  .000143  I  .3940960  .0000211  2.3725 0.0133  I    -4.593     .237    -4.552     .118  -.219900   .317500   .3939200    -4.100    -4.900  
+91 411 48357.00 I  -.219857  .000198   .322358  .000115  I  .3916419  .0000114  2.5343 0.0124  I    -4.697     .276    -4.512     .107  -.219300   .321500   .3914500    -4.200    -5.000  
+91 412 48358.00 I  -.219056  .000227   .326309  .000163  I  .3890362  .0000129  2.6696 0.0080  I    -4.612     .339    -4.584     .298  -.218600   .325500   .3888200    -4.200    -5.000  
+91 413 48359.00 I  -.218014  .000174   .330253  .000132  I  .3863229  .0000111  2.7444 0.0085  I    -4.379     .435    -4.544     .298  -.217800   .329500   .3861200    -4.300    -5.100  
+91 414 48360.00 I  -.216806  .000153   .334184  .000121  I  .3835812  .0000112  2.7178 0.0081  I    -4.256     .528    -4.288     .298  -.216900   .333500   .3834300    -4.400    -5.200  
+91 415 48361.00 I  -.215546  .000147   .338103  .000157  I  .3809266  .0000117  2.5733 0.0086  I    -4.453     .528    -4.023     .298  -.216000   .337400   .3808300    -4.500    -5.200  
+91 416 48362.00 I  -.214356  .000252   .342027  .000159  I  .3784616  .0000130  2.3479 0.0092  I    -4.898     .468    -4.030     .298  -.215200   .341400   .3784200    -4.600    -5.300  
+91 417 48363.00 I  -.213352  .000271   .345978  .000216  I  .3762352  .0000141  2.1094 0.0096  I    -5.316     .472    -4.368     .298  -.214500   .345300   .3762400    -4.800    -5.400  
+91 418 48364.00 I  -.212598  .000271   .349971  .000204  I  .3742255  .0000142  1.9229 0.0103  I    -5.479     .472    -4.811     .298  -.213800   .349200   .3742100    -5.100    -5.500  
+91 419 48365.00 I  -.212116  .000271   .353997  .000204  I  .3723417  .0000151  1.8796 0.0099  I    -5.340     .419    -5.119     .298  -.213200   .353200   .3722700    -5.200    -5.600  
+91 420 48366.00 I  -.211712  .000325   .357991  .000226  I  .3704127  .0000138  1.9971 0.0101  I    -5.100     .310    -5.305     .298  -.212800   .357100   .3702800    -5.400    -5.800  
+91 421 48367.00 I  -.211353  .000303   .361955  .000229  I  .3683187  .0000133  2.2009 0.0089  I    -4.950     .310    -5.450     .298  -.212400   .361000   .3681400    -5.500    -5.900  
+91 422 48368.00 I  -.211093  .000262   .365896  .000232  I  .3660009  .0000113  2.4348 0.0090  I    -4.888     .308    -5.578     .298  -.212200   .365000   .3657900    -5.600    -6.100  
+91 423 48369.00 I  -.210987  .000445   .369820  .000321  I  .3634567  .0000121  2.6459 0.0083  I    -4.781     .352    -5.646     .298  -.212000   .368900   .3632200    -5.600    -6.300  
+91 424 48370.00 I  -.211028  .000445   .373708  .000321  I  .3607315  .0000121  2.7896 0.0075  I    -4.551     .316    -5.561     .298  -.211900   .372700   .3605000    -5.500    -6.600  
+91 425 48371.00 I  -.211077  .000445   .377499  .000321  I  .3579095  .0000089  2.8371 0.0099  I    -4.358     .316    -5.267     .298  -.211800   .376600   .3576800    -5.400    -6.800  
+91 426 48372.00 I  -.211001  .000484   .381195  .000341  I  .3550906  .0000156  2.7847 0.0077  I    -4.312     .252    -4.897     .298  -.211700   .380400   .3548800    -5.200    -7.000  
+91 427 48373.00 I  -.210716  .000413   .384817  .000306  I  .3523675  .0000126  2.6501 0.0103  I    -4.342     .380    -4.727     .299  -.211500   .384200   .3521800    -5.000    -7.300  
+91 428 48374.00 I  -.210235  .000490   .388395  .000348  I  .3498073  .0000134  2.4647 0.0094  I    -4.325     .397    -4.873     .338  -.211200   .388000   .3496500    -4.800    -7.400  
+91 429 48375.00 I  -.209581  .000188   .391966  .000369  I  .3474433  .0000139  2.2638 0.0101  I    -4.234     .397    -5.223     .338  -.210700   .391700   .3473000    -4.600    -7.600  
+91 430 48376.00 I  -.208780  .000178   .395564  .000303  I  .3452739  .0000152  2.0804 0.0103  I    -4.196     .399    -5.528     .346  -.210000   .395400   .3451300    -4.500    -7.700  
+91 5 1 48377.00 I  -.207855  .000178   .399210  .000303  I  .3432674  .0000152  1.9424 0.0101  I    -4.323     .352    -5.593     .310  -.209200   .399100   .3431200    -4.300    -7.800  
+91 5 2 48378.00 I  -.206791  .000178   .402890  .000303  I  .3413683  .0000134  1.8669 0.0123  I    -4.506     .352    -5.526     .310  -.208200   .402800   .3412100    -4.200    -7.800  
+91 5 3 48379.00 I  -.205572  .000108   .406589  .000417  I  .3395114  .0000193  1.8580 0.0106  I    -4.559     .146    -5.577     .153  -.207000   .406500   .3393200    -4.100    -7.800  
+91 5 4 48380.00 I  -.204205  .000148   .410310  .000422  I  .3376298  .0000164  1.9166 0.0111  I    -4.478     .257    -5.739     .202  -.205400   .409500   .3374200    -3.800    -7.600  
+91 5 5 48381.00 I  -.202702  .000149   .414042  .000292  I  .3356575  .0000109  2.0373 0.0101  I    -4.345     .257    -5.881     .202  -.203900   .413200   .3354200    -3.900    -7.400  
+91 5 6 48382.00 I  -.201075  .000138   .417773  .000260  I  .3335389  .0000117  2.2068 0.0075  I    -4.170     .426    -5.861     .199  -.202400   .417000   .3332900    -4.000    -7.300  
+91 5 7 48383.00 I  -.199327  .000207   .421520  .000251  I  .3312343  .0000104  2.4052 0.0075  I    -3.938     .472    -5.643     .212  -.200700   .420700   .3309700    -4.200    -7.100  
+91 5 8 48384.00 I  -.197475  .000211   .425296  .000252  I  .3287302  .0000093  2.5987 0.0071  I    -3.766     .429    -5.402     .193  -.198900   .424400   .3284700    -4.300    -7.000  
+91 5 9 48385.00 I  -.195569  .000215   .429075  .000204  I  .3260494  .0000097  2.7548 0.0069  I    -3.882     .429    -5.315     .193  -.197000   .428200   .3257900    -4.400    -6.800  
+91 510 48386.00 I  -.193643  .000212   .432845  .000216  I  .3232425  .0000101  2.8454 0.0076  I    -4.231     .487    -5.414     .150  -.195100   .431900   .3229800    -4.500    -6.600  
+91 511 48387.00 I  -.191707  .000242   .436597  .000136  I  .3203892  .0000116  2.8444 0.0081  I    -4.546     .410    -5.495     .142  -.193000   .435600   .3201200    -4.700    -6.400  
+91 512 48388.00 I  -.189725  .000249   .440306  .000143  I  .3175869  .0000127  2.7439 0.0086  I    -4.762     .204    -5.377     .105  -.190700   .439200   .3173100    -4.900    -6.300  
+91 513 48389.00 I  -.187655  .000249   .443949  .000143  I  .3149288  .0000127  2.5613 0.0109  I    -5.019     .204    -5.165     .105  -.188400   .442800   .3146500    -5.100    -6.100  
+91 514 48390.00 I  -.185453  .000225   .447502  .000166  I  .3124747  .0000178  2.3474 0.0109  I    -5.347     .215    -5.087     .116  -.185900   .446400   .3122100    -5.400    -6.000  
+91 515 48391.00 I  -.183061  .000220   .450942  .000164  I  .3102256  .0000178  2.1587 0.0126  I    -5.545     .353    -5.200     .298  -.183200   .449800   .3099900    -5.800    -5.800  
+91 516 48392.00 I  -.180442  .000220   .454273  .000164  I  .3081325  .0000178  2.0444 0.0151  I    -5.432     .353    -5.414     .298  -.180500   .453200   .3079300    -6.200    -5.600  
+91 517 48393.00 I  -.177606  .000238   .457530  .000191  I  .3061030  .0000244  2.0315 0.0127  I    -5.108     .403    -5.555     .298  -.177600   .456500   .3059200    -6.700    -5.500  
+91 518 48394.00 I  -.174586  .000267   .460741  .000158  I  .3040388  .0000181  2.1108 0.0137  I    -4.869     .623    -5.615     .298  -.174600   .459700   .3038700    -7.100    -5.400  
+91 519 48395.00 I  -.171472  .000218   .463903  .000134  I  .3018647  .0000126  2.2402 0.0112  I    -4.892     .623    -5.662     .298  -.171700   .462800   .3017100    -7.400    -5.300  
+91 520 48396.00 I  -.168371  .000215   .467004  .000132  I  .2995630  .0000132  2.3556 0.0078  I    -5.140     .607    -5.695     .298  -.168700   .465900   .2994200    -7.700    -5.200  
+91 521 48397.00 I  -.165388  .000212   .470030  .000114  I  .2971748  .0000091  2.4069 0.0079  I    -5.432     .675    -5.668     .298  -.165700   .468900   .2970500    -7.900    -5.100  
+91 522 48398.00 I  -.162556  .000212   .472974  .000114  I  .2947821  .0000086  2.3594 0.0063  I    -5.630     .550    -5.571     .298  -.162800   .471900   .2946900    -8.000    -5.000  
+91 523 48399.00 I  -.159759  .000212   .475856  .000114  I  .2924858  .0000087  2.2226 0.0065  I    -5.810     .550    -5.435     .298  -.159800   .474800   .2924200    -8.000    -5.000  
+91 524 48400.00 I  -.156924  .000113   .478719  .000125  I  .2903538  .0000097  2.0351 0.0062  I    -5.978     .380    -5.284     .298  -.156900   .477700   .2902800    -7.900    -5.000  
+91 525 48401.00 I  -.154015  .000118   .481596  .000116  I  .2884229  .0000089  1.8258 0.0080  I    -6.086     .313    -5.144     .298  -.154000   .480600   .2883200    -7.700    -5.100  
+91 526 48402.00 I  -.151055  .000160   .484485  .000185  I  .2866991  .0000128  1.6258 0.0078  I    -6.133     .231    -5.105     .109  -.151100   .483400   .2865400    -7.500    -5.200  
+91 527 48403.00 I  -.148081  .000160   .487372  .000181  I  .2851582  .0000129  1.4650 0.0104  I    -6.087     .231    -5.301     .109  -.148200   .486200   .2849100    -7.300    -5.300  
+91 528 48404.00 I  -.145115  .000157   .490241  .000170  I  .2837485  .0000163  1.3660 0.0119  I    -5.953     .273    -5.782     .180  -.145200   .489000   .2834100    -7.000    -5.400  
+91 529 48405.00 I  -.142177  .000152   .493080  .000171  I  .2824062  .0000199  1.3271 0.0173  I    -5.781     .422    -6.379     .172  -.142300   .491800   .2819600    -6.800    -5.500  
+91 530 48406.00 I  -.139273  .000146   .495891  .000177  I  .2810759  .0000305  1.3433 0.0255  I    -5.569     .422    -6.709     .172  -.139400   .494600   .2805200    -6.500    -5.600  
+91 531 48407.00 I  -.136397  .000198   .498678  .000226  I  .2797012  .0000469  1.4146 0.0208  I    -5.318     .579    -6.566     .207  -.136400   .497400   .2790300    -6.300    -5.700  
+91 6 1 48408.00 I  -.133530  .000321   .501446  .000242  I  .2782301  .0000282  1.5357 0.0276  I    -5.291     .457    -6.261     .197  -.133300   .500200   .2774600    -6.100    -5.900  
+91 6 2 48409.00 I  -.130632  .000320   .504185  .000269  I  .2766170  .0000291  1.6951 0.0203  I    -5.610     .428    -6.039     .181  -.130200   .502900   .2758000    -5.900    -6.100  
+91 6 3 48410.00 I  -.127650  .000320   .506887  .000269  I  .2748345  .0000291  1.8705 0.0196  I    -6.055     .432    -5.823     .160  -.127300   .505700   .2751600    -6.500    -6.000  
+91 6 4 48411.00 I  -.124536  .000327   .509546  .000294  I  .2728759  .0000263  2.0461 0.0175  I    -6.284     .292    -5.518     .164  -.124100   .508500   .2730300    -6.700    -5.800  
+91 6 5 48412.00 I  -.121236  .000327   .512145  .000294  I  .2707460  .0000194  2.2107 0.0163  I    -6.168     .393    -5.250     .145  -.120800   .511200   .2707400    -6.800    -5.700  
+91 6 6 48413.00 I  -.117799  .000327   .514711  .000294  I  .2684654  .0000193  2.3425 0.0140  I    -6.030     .393    -5.246     .145  -.117500   .513900   .2683000    -7.000    -5.500  
+91 6 7 48414.00 I  -.114309  .000344   .517299  .000260  I  .2660808  .0000202  2.4150 0.0127  I    -6.211     .447    -5.496     .104  -.114000   .516500   .2657700    -7.200    -5.400  
+91 6 8 48415.00 I  -.110827  .000563   .519947  .000464  I  .2636634  .0000165  2.4034 0.0128  I    -6.785     .599    -5.717     .114  -.110500   .519100   .2633500    -7.400    -5.300  
+91 6 9 48416.00 I  -.107321  .000554   .522631  .000423  I  .2613040  .0000157  2.3017 0.0113  I    -7.525     .599    -5.661     .114  -.106900   .521700   .2610100    -7.700    -5.200  
+91 610 48417.00 I  -.103738  .000562   .525310  .000417  I  .2590792  .0000155  2.1425 0.0107  I    -8.189     .591    -5.415     .298  -.103200   .524200   .2588000    -8.000    -5.100  
+91 611 48418.00 I  -.100023  .000588   .527945  .000391  I  .2570190  .0000146  1.9833 0.0106  I    -8.576     .630    -5.255     .298  -.099400   .526700   .2567700    -8.300    -5.100  
+91 612 48419.00 I  -.096172  .000588   .530474  .000391  I  .2551011  .0000145  1.8587 0.0103  I    -8.545     .515    -5.269     .298  -.095600   .529000   .2549000    -8.600    -5.000  
+91 613 48420.00 I  -.092407  .000593   .532808  .000433  I  .2532746  .0000146  1.8152 0.0109  I    -8.255     .515    -5.288     .298  -.091800   .531300   .2530800    -9.000    -5.000  
+91 614 48421.00 I  -.088697  .000518   .534938  .000423  I  .2514330  .0000162  1.8846 0.0103  I    -7.917     .406    -5.209     .298  -.088100   .533500   .2512000    -9.200    -5.000  
+91 615 48422.00 I  -.084948  .000419   .536894  .000368  I  .2494815  .0000146  2.0255 0.0108  I    -7.706     .339    -5.161     .115  -.084400   .535600   .2492100    -9.400    -5.100  
+91 616 48423.00 I  -.081217  .000355   .538697  .000372  I  .2473810  .0000143  2.1693 0.0105  I    -7.679     .113    -5.232     .134  -.080700   .537500   .2470600    -9.600    -5.100  
+91 617 48424.00 I  -.077580  .000356   .540381  .000347  I  .2451650  .0000151  2.2466 0.0113  I    -7.830     .113    -5.299     .134  -.077200   .539300   .2448100    -9.600    -5.200  
+91 618 48425.00 I  -.074071  .000264   .542020  .000390  I  .2429220  .0000175  2.2213 0.0116  I    -8.136     .134    -5.176     .180  -.073700   .541100   .2425200    -9.500    -5.200  
+91 619 48426.00 I  -.070701  .000211   .543663  .000307  I  .2407553  .0000175  2.0975 0.0124  I    -8.462     .471    -4.875     .310  -.070300   .542700   .2403400    -9.300    -5.300  
+91 620 48427.00 I  -.067473  .000211   .545292  .000307  I  .2387508  .0000175  1.9025 0.0149  I    -8.565     .471    -4.645     .310  -.067100   .544300   .2383200    -9.000    -5.400  
+91 621 48428.00 I  -.064420  .000263   .546876  .000301  I  .2369620  .0000240  1.6723 0.0145  I    -8.332     .653    -4.638     .399  -.063900   .545900   .2365500    -8.700    -5.500  
+91 622 48429.00 I  -.061563  .000297   .548392  .000495  I  .2354087  .0000232  1.4344 0.0160  I    -7.965     .656    -4.800     .306  -.060900   .547300   .2350300    -8.300    -5.600  
+91 623 48430.00 I  -.058826  .000265   .549874  .000379  I  .2340892  .0000213  1.2084 0.0165  I    -7.811     .656    -4.982     .306  -.057800   .548800   .2337300    -7.900    -5.700  
+91 624 48431.00 I  -.056103  .000338   .551379  .000418  I  .2329812  .0000235  1.0145 0.0162  I    -8.017     .646    -5.152     .287  -.054800   .550300   .2326600    -7.400    -5.800  
+91 625 48432.00 I  -.053290  .000370   .552965  .000391  I  .2320435  .0000244  0.8707 0.0135  I    -8.521     .563    -5.326     .248  -.051700   .551800   .2317300    -7.000    -5.900  
+91 626 48433.00 I  -.050301  .000261   .554667  .000331  I  .2312179  .0000133  0.7928 0.0138  I    -9.139     .487    -5.398     .233  -.048700   .553200   .2309100    -6.700    -6.100  
+91 627 48434.00 I  -.047131  .000261   .556431  .000331  I  .2304329  .0000131  0.7901 0.0100  I    -9.525     .455    -5.267     .225  -.045600   .554700   .2301000    -6.400    -6.200  
+91 628 48435.00 I  -.043799  .000271   .558138  .000322  I  .2296136  .0000150  0.8599 0.0101  I    -9.661     .323    -5.170     .241  -.042500   .556200   .2292700    -6.200    -6.400  
+91 629 48436.00 I  -.040312  .000264   .559642  .000410  I  .2286955  .0000154  0.9826 0.0117  I    -9.769     .339    -5.053     .216  -.039300   .557600   .2283500    -6.100    -6.600  
+91 630 48437.00 I  -.036690  .000356   .560847  .000438  I  .2276412  .0000180  1.1269 0.0119  I   -10.016     .284    -4.882     .222  -.036000   .559000   .2272900    -6.100    -6.800  
+91 7 1 48438.00 I  -.033013  .000341   .561856  .000417  I  .2264439  .0000182  1.2645 0.0127  I   -10.402     .345    -4.829     .196  -.032600   .560300   .2260700    -6.200    -6.900  
+91 7 2 48439.00 I  -.029366  .000322   .562824  .000430  I  .2251163  .0000180  1.3898 0.0160  I   -10.710     .362    -4.824     .193  -.029100   .561600   .2247200    -6.300    -7.100  
+91 7 3 48440.00 I  -.025727  .000433   .563843  .000543  I  .2236695  .0000262  1.4997 0.0159  I   -10.699     .391    -4.686     .200  -.025000   .563100   .2234700    -6.800    -7.000  
+91 7 4 48441.00 I  -.021941  .000433   .564872  .000543  I  .2221343  .0000263  1.5575 0.0213  I   -10.451     .418    -4.601     .196  -.021200   .564100   .2219200    -7.200    -6.800  
+91 7 5 48442.00 I  -.017994  .000512   .565876  .000239  I  .2205824  .0000335  1.5317 0.0196  I   -10.264     .452    -4.665     .245  -.017400   .565000   .2203700    -7.900    -6.600  
+91 7 6 48443.00 I  -.013950  .000445   .566824  .000198  I  .2190993  .0000291  1.4209 0.0197  I   -10.327     .986    -4.746     .177  -.013500   .565900   .2189100    -8.400    -6.400  
+91 7 7 48444.00 I  -.009878  .000182   .567683  .000208  I  .2177630  .0000207  1.2430 0.0155  I   -10.606    1.319    -4.691     .298  -.009600   .566700   .2176000    -8.800    -6.200  
+91 7 8 48445.00 I  -.005846  .000158   .568421  .000135  I  .2166216  .0000109  1.0402 0.0117  I   -10.986    1.119    -4.555     .298  -.005700   .567400   .2164800    -9.600    -6.200  
+91 7 9 48446.00 I  -.001914  .000187   .569021  .000146  I  .2156705  .0000109  0.8736 0.0079  I   -11.405     .986    -4.539     .298  -.001700   .568100   .2155300   -10.200    -6.100  
+91 710 48447.00 I   .001903  .000183   .569477  .000280  I  .2148371  .0000115  0.8187 0.0102  I   -11.798     .892    -4.726     .183   .002300   .568700   .2146700   -10.900    -5.800  
+91 711 48448.00 I   .005725  .000317   .569812  .000273  I  .2139795  .0000172  0.9245 0.0108  I   -11.999     .780    -4.998     .193   .006300   .569200   .2137800   -11.400    -5.700  
+91 712 48449.00 I   .009670  .000328   .570109  .000284  I  .2129437  .0000182  1.1634 0.0123  I   -12.132     .841    -5.069     .211   .010300   .569700   .2127100   -11.800    -5.600  
+91 713 48450.00 I   .013729  .000305   .570442  .000518  I  .2116343  .0000175  1.4575 0.0122  I   -12.357     .919    -4.983     .196   .014400   .570200   .2113800   -11.500    -5.500  
+91 714 48451.00 I   .017946  .000282   .570858  .000548  I  .2100398  .0000163  1.7183 0.0152  I   -12.478     .959    -4.854     .201   .018700   .570600   .2097900   -11.600    -5.400  
+91 715 48452.00 I   .022375  .000425   .571352  .000699  I  .2082363  .0000249  1.8633 0.0140  I   -12.266     .920    -4.788     .207   .023000   .570900   .2080100   -11.700    -5.300  
+91 716 48453.00 I   .026968  .000321   .571904  .000611  I  .2063631  .0000227  1.8587 0.0165  I   -12.268     .929    -4.726     .222   .027400   .571200   .2061600   -11.800    -5.400  
+91 717 48454.00 I   .031649  .000327   .572418  .000593  I  .2045564  .0000217  1.7417 0.0160  I   -12.998    1.072    -4.642     .209   .031800   .571500   .2043600   -11.800    -5.500  
+91 718 48455.00 I   .036358  .000250   .572701  .000600  I  .2029001  .0000226  1.5636 0.0153  I   -13.903     .835    -4.660     .192   .036400   .571700   .2027300   -12.000    -5.500  
+91 719 48456.00 I   .041044  .000262   .572782  .000406  I  .2014419  .0000215  1.3476 0.0159  I   -14.393     .720    -4.676     .209   .041000   .571900   .2012900   -12.100    -5.600  
+91 720 48457.00 I   .045589  .000312   .572739  .000526  I  .2002059  .0000223  1.1288 0.0171  I   -14.254     .712    -4.778     .186   .045600   .572000   .2000600   -12.300    -5.600  
+91 721 48458.00 I   .050029  .000360   .572650  .000533  I  .1991700  .0000267  0.9531 0.0163  I   -14.009     .725    -4.872     .210   .050300   .572000   .1990200   -12.600    -5.600  
+91 722 48459.00 I   .054497  .000276   .572540  .000537  I  .1982781  .0000239  0.8422 0.0212  I   -14.205     .768    -4.856     .207   .054900   .572000   .1981300   -12.900    -5.500  
+91 723 48460.00 I   .059109  .000440   .572417  .000734  I  .1974633  .0000329  0.7981 0.0162  I   -14.833     .628    -4.836     .218   .059500   .571900   .1973100   -13.300    -5.500  
+91 724 48461.00 I   .063817  .000450   .572247  .000700  I  .1966611  .0000219  0.8163 0.0207  I   -15.457     .610    -4.746     .236   .064000   .571700   .1965100   -13.700    -5.400  
+91 725 48462.00 I   .068502  .000426   .572009  .000698  I  .1958101  .0000252  0.8963 0.0200  I   -15.667     .610    -4.748     .236   .068500   .571500   .1956600   -14.100    -5.400  
+91 726 48463.00 I   .073105  .000320   .571718  .000535  I  .1948501  .0000335  1.0315 0.0185  I   -15.531     .527    -4.763     .286   .072800   .571200   .1947100   -14.600    -5.300  
+91 727 48464.00 I   .077590  .000260   .571383  .000358  I  .1937368  .0000272  1.1975 0.0236  I   -15.331     .583    -4.566     .331   .076900   .570800   .1936000   -15.000    -5.300  
+91 728 48465.00 I   .081901  .000312   .571007  .000318  I  .1924553  .0000332  1.3628 0.0219  I   -15.227     .693    -4.295     .259   .081000   .570400   .1923400   -15.300    -5.300  
+91 729 48466.00 I   .085971  .000323   .570583  .000412  I  .1910240  .0000344  1.4898 0.0252  I   -15.260     .678    -4.151     .251   .084800   .569800   .1909400   -15.700    -5.300  
+91 730 48467.00 I   .089710  .000339   .570085  .000444  I  .1895032  .0000380  1.5344 0.0256  I   -15.242     .723    -4.454     .280   .088500   .569200   .1894300   -16.000    -5.300  
+91 731 48468.00 I   .093032  .000335   .569494  .000501  I  .1879815  .0000378  1.5000 0.0260  I   -15.100     .637    -4.834     .258   .092000   .568400   .1878800   -16.200    -5.300  
+91 8 1 48469.00 I   .096042  .000322   .568777  .000476  I  .1865172  .0000354  1.4237 0.0264  I   -14.997     .629    -4.921     .247   .095400   .567600   .1863600   -16.400    -5.400  
+91 8 2 48470.00 I   .098933  .000331   .567909  .000479  I  .1851435  .0000370  1.3193 0.0244  I   -15.069     .594    -4.824     .178   .098700   .566700   .1849200   -16.600    -5.500  
+91 8 3 48471.00 I   .101871  .000419   .566886  .000584  I  .1838886  .0000336  1.1848 0.0232  I   -15.354     .477    -4.773     .182   .101900   .565600   .1836600   -16.800    -5.600  
+91 8 4 48472.00 I   .104958  .000412   .565705  .000356  I  .1827794  .0000281  1.0339 0.0217  I   -15.846     .458    -4.704     .182   .105100   .564500   .1825800   -17.000    -5.600  
+91 8 5 48473.00 I   .108217  .000412   .564427  .000356  I  .1818143  .0000275  0.9025 0.0171  I   -16.345     .420    -4.719     .161   .108400   .563400   .1816700   -17.200    -5.700  
+91 8 6 48474.00 I   .111662  .000420   .563106  .000306  I  .1809531  .0000194  0.8348 0.0175  I   -16.595     .442    -4.836     .145   .112300   .562700   .1807900   -15.800    -5.400  
+91 8 7 48475.00 I   .115248  .000432   .561778  .000249  I  .1801100  .0000216  0.8711 0.0145  I   -16.529     .411    -4.860     .280   .115600   .561500   .1799900   -16.000    -5.400  
+91 8 8 48476.00 I   .118816  .000470   .560444  .000254  I  .1791690  .0000215  1.0330 0.0165  I   -16.317     .442    -4.781     .288   .118900   .560200   .1790600   -16.200    -5.300  
+91 8 9 48477.00 I   .122395  .000391   .559084  .000128  I  .1780101  .0000249  1.2965 0.0134  I   -16.217     .214    -4.613     .341   .122300   .558900   .1778800   -16.400    -5.200  
+91 810 48478.00 I   .126042  .000293   .557680  .000372  I  .1765680  .0000161  1.5840 0.0151  I   -16.291     .207    -4.488     .285   .125800   .557500   .1764200   -16.700    -5.000  
+91 811 48479.00 I   .129721  .000206   .556237  .000483  I  .1748620  .0000171  1.8117 0.0117  I   -16.385     .169    -4.495     .343   .129300   .556000   .1746800   -16.900    -4.900  
+91 812 48480.00 I   .133366  .000206   .554770  .000483  I  .1729817  .0000169  1.9279 0.0112  I   -16.460     .169    -4.625     .343   .132700   .554500   .1727600   -17.200    -4.700  
+91 813 48481.00 I   .136914  .000108   .553290  .000495  I  .1710455  .0000145  1.9261 0.0122  I   -16.781     .193    -4.687     .298   .136200   .552900   .1708200   -17.500    -4.600  
+91 814 48482.00 I   .140316  .000209   .551783  .000497  I  .1691646  .0000177  1.8190 0.0106  I   -17.533     .286    -4.580     .402   .139500   .551200   .1689400   -17.800    -4.400  
+91 815 48483.00 I   .143560  .000204   .550210  .000519  I  .1674311  .0000155  1.6410 0.0146  I   -18.378     .282    -4.443     .363   .142800   .549400   .1672400   -18.100    -4.300  
+91 816 48484.00 I   .146642  .000233   .548540  .000504  I  .1658892  .0000231  1.4432 0.0168  I   -18.744     .327    -4.439     .455   .146000   .547600   .1657200   -18.300    -4.300  
+91 817 48485.00 I   .149543  .000420   .546773  .000502  I  .1645384  .0000297  1.2642 0.0185  I   -18.442     .649    -4.516     .354   .149000   .545700   .1644000   -18.400    -4.200  
+91 818 48486.00 I   .152226  .000407   .544914  .000434  I  .1633450  .0000289  1.1325 0.0172  I   -17.924     .649    -4.500     .354   .151800   .543800   .1632200   -18.400    -4.300  
+91 819 48487.00 I   .154714  .000316   .542974  .000271  I  .1622537  .0000173  1.0597 0.0179  I   -17.630     .603    -4.334     .342   .154600   .541800   .1621400   -18.300    -4.300  
+91 820 48488.00 I   .157052  .000334   .540992  .000293  I  .1612062  .0000211  1.0449 0.0128  I   -17.572     .724    -4.122     .170   .157200   .539800   .1611000   -18.200    -4.400  
+91 821 48489.00 I   .159312  .000290   .538993  .000235  I  .1601450  .0000188  1.0867 0.0132  I   -17.533     .895    -4.009     .239   .159700   .537800   .1600400   -18.100    -4.500  
+91 822 48490.00 I   .161609  .000290   .536939  .000235  I  .1590155  .0000159  1.1803 0.0136  I   -17.306     .895    -4.081     .239   .162200   .535800   .1588800   -17.900    -4.600  
+91 823 48491.00 I   .164054  .000326   .534799  .000118  I  .1577638  .0000197  1.3355 0.0115  I   -16.927     .871    -4.043     .289   .164500   .533700   .1575700   -17.800    -4.700  
+91 824 48492.00 I   .166659  .000282   .532583  .000292  I  .1563302  .0000166  1.5335 0.0129  I   -16.758     .743    -3.944     .221   .166900   .531700   .1561000   -17.700    -4.800  
+91 825 48493.00 I   .169344  .000285   .530338  .000303  I  .1546978  .0000167  1.7287 0.0167  I   -16.866     .738    -3.992     .237   .169300   .529600   .1544400   -17.600    -4.900  
+91 826 48494.00 I   .171997  .000348   .528109  .000351  I  .1528838  .0000290  1.8911 0.0149  I   -17.094     .724    -4.229     .235   .171700   .527600   .1525900   -17.600    -5.000  
+91 827 48495.00 I   .174560  .000335   .525956  .000357  I  .1509325  .0000248  2.0029 0.0190  I   -17.324     .537    -4.543     .230   .174100   .525600   .1506300   -17.500    -5.100  
+91 828 48496.00 I   .177137  .000329   .523935  .000371  I  .1489024  .0000246  2.0416 0.0163  I   -17.565     .621    -4.617     .212   .176600   .523500   .1486100   -17.600    -5.200  
+91 829 48497.00 I   .179726  .000329   .521986  .000371  I  .1468790  .0000213  1.9912 0.0201  I   -17.813     .621    -4.468     .212   .179200   .521400   .1466000   -17.600    -5.300  
+91 830 48498.00 I   .182299  .000283   .520033  .000311  I  .1449414  .0000318  1.8767 0.0208  I   -18.113     .682    -4.510     .276   .181800   .519400   .1446900   -17.700    -5.300  
+91 831 48499.00 I   .184849  .000307   .518012  .000544  I  .1431336  .0000358  1.7383 0.0217  I   -18.328     .634    -4.642     .190   .184500   .517300   .1429000   -17.800    -5.300  
+91 9 1 48500.00 I   .187398  .000307   .515918  .000544  I  .1414584  .0000296  1.6192 0.0197  I   -18.443     .634    -4.739     .190   .187300   .515200   .1412500   -18.000    -5.300  
+91 9 2 48501.00 I   .189978  .000246   .513764  .000420  I  .1398743  .0000164  1.5629 0.0177  I   -18.529     .597    -4.849     .116   .190100   .513100   .1396800   -18.100    -5.300  
+91 9 3 48502.00 I   .192616  .000243   .511566  .000386  I  .1383010  .0000194  1.6015 0.0106  I   -18.582     .884    -4.977     .298   .192900   .510900   .1381200   -18.400    -5.300  
+91 9 4 48503.00 I   .195337  .000193   .509352  .000297  I  .1366345  .0000135  1.7504 0.0116  I   -18.582     .828    -5.070     .298   .195700   .508800   .1364500   -18.700    -5.200  
+91 9 5 48504.00 I   .198209  .000193   .507148  .000297  I  .1347696  .0000129  1.9910 0.0096  I   -18.493     .771    -5.058     .298   .198400   .506600   .1345800   -19.000    -5.100  
+91 9 6 48505.00 I   .201270  .000208   .504976  .000244  I  .1326407  .0000137  2.2669 0.0099  I   -18.352     .895    -4.901     .107   .201400   .504300   .1324500   -19.100    -5.100  
+91 9 7 48506.00 I   .204388  .000238   .502847  .000267  I  .1302495  .0000150  2.5019 0.0089  I   -18.377     .924    -4.586     .114   .204100   .502100   .1300500   -19.300    -4.900  
+91 9 8 48507.00 I   .207393  .000250   .500743  .000270  I  .1276691  .0000115  2.6405 0.0092  I   -18.509     .971    -4.302     .130   .206700   .499800   .1274400   -19.500    -4.800  
+91 9 9 48508.00 I   .210161  .000252   .498606  .000240  I  .1250076  .0000108  2.6618 0.0077  I   -18.510     .887    -4.146     .132   .209100   .497500   .1247500   -19.600    -4.700  
+91 910 48509.00 I   .212566  .000297   .496400  .000231  I  .1223822  .0000102  2.5731 0.0093  I   -18.391     .951    -3.983     .147   .211300   .495200   .1221100   -19.700    -4.500  
+91 911 48510.00 I   .214480  .000366   .494106  .000365  I  .1198897  .0000152  2.3994 0.0097  I   -18.644     .915    -3.835     .137   .213300   .492800   .1196300   -19.600    -4.500  
+91 912 48511.00 I   .215997  .000375   .491708  .000342  I  .1175991  .0000164  2.1785 0.0112  I   -19.249     .858    -3.777     .139   .215100   .490300   .1173700   -19.400    -4.400  
+91 913 48512.00 I   .217312  .000338   .489190  .000349  I  .1155326  .0000164  1.9578 0.0119  I   -19.719     .821    -3.871     .138   .216900   .487800   .1153500   -19.300    -4.400  
+91 914 48513.00 I   .218598  .000315   .486539  .000256  I  .1136722  .0000173  1.7711 0.0120  I   -19.703     .373    -4.107     .102   .218600   .485200   .1135500   -19.000    -4.400  
+91 915 48514.00 I   .219935  .000309   .483763  .000246  I  .1119721  .0000175  1.6392 0.0123  I   -19.204     .373    -4.236     .102   .220200   .482500   .1119000   -18.700    -4.400  
+91 916 48515.00 I   .221414  .000309   .480892  .000246  I  .1103748  .0000176  1.5643 0.0133  I   -18.511     .373    -4.178     .102   .221900   .479800   .1103500   -18.400    -4.500  
+91 917 48516.00 I   .223135  .000381   .477963  .000258  I  .1088260  .0000201  1.5418 0.0119  I   -17.877     .194    -4.070     .103   .223700   .477000   .1088200   -18.100    -4.500  
+91 918 48517.00 I   .225137  .000394   .475008  .000145  I  .1072693  .0000160  1.5851 0.0126  I   -17.416     .347    -4.011     .139   .225500   .474200   .1072500   -17.900    -4.600  
+91 919 48518.00 I   .227290  .000394   .472047  .000145  I  .1056320  .0000153  1.6998 0.0136  I   -17.214     .347    -3.972     .139   .227400   .471300   .1055800   -17.700    -4.700  
+91 920 48519.00 I   .229438  .000457   .469103  .000174  I  .1038529  .0000220  1.8647 0.0144  I   -17.332     .490    -3.912     .182   .229400   .468400   .1037400   -17.600    -4.700  
+91 921 48520.00 I   .231466  .000403   .466196  .000482  I  .1018945  .0000243  2.0538 0.0162  I   -17.725     .484    -3.871     .183   .231400   .465600   .1017200   -17.600    -4.700  
+91 922 48521.00 I   .233424  .000389   .463342  .000461  I  .0997466  .0000237  2.2392 0.0161  I   -18.181     .484    -3.907     .183   .233500   .462700   .0995100   -17.700    -4.700  
+91 923 48522.00 I   .235406  .000473   .460554  .000503  I  .0974257  .0000211  2.3960 0.0179  I   -18.536     .436    -4.007     .180   .235600   .459800   .0971300   -17.800    -4.700  
+91 924 48523.00 I   .237502  .000402   .457846  .000568  I  .0949725  .0000268  2.4991 0.0172  I   -18.737     .311    -4.092     .170   .237800   .456900   .0946600   -17.900    -4.600  
+91 925 48524.00 I   .239748  .000402   .455199  .000568  I  .0924587  .0000272  2.5087 0.0193  I   -18.768     .298    -4.082     .169   .239800   .454000   .0921500   -18.100    -4.600  
+91 926 48525.00 I   .242034  .000405   .452492  .000560  I  .0899884  .0000277  2.4185 0.0188  I   -18.671     .298    -3.937     .169   .241800   .451000   .0897100   -18.100    -4.600  
+91 927 48526.00 I   .244219  .000444   .449613  .000623  I  .0876444  .0000260  2.2601 0.0181  I   -18.468     .177    -3.834     .162   .243600   .448100   .0874100   -18.100    -4.600  
+91 928 48527.00 I   .246208  .000374   .446617  .000483  I  .0854745  .0000232  2.0827 0.0171  I   -18.199     .298    -3.786     .145   .245300   .445000   .0852900   -18.100    -4.600  
+91 929 48528.00 I   .247973  .000382   .443544  .000494  I  .0834657  .0000222  1.9451 0.0162  I   -17.883     .320    -3.782     .142   .246900   .442000   .0833200   -18.000    -4.700  
+91 930 48529.00 I   .249478  .000306   .440410  .000471  I  .0815602  .0000225  1.8797 0.0149  I   -17.537     .387    -3.835     .136   .248300   .438900   .0814500   -17.800    -4.700  
+9110 1 48530.00 I   .250664  .000364   .437218  .000392  I  .0796781  .0000200  1.8990 0.0151  I   -17.176     .425    -3.925     .158   .249500   .435700   .0795600   -17.700    -4.800  
+9110 2 48531.00 I   .251533  .000347   .433958  .000384  I  .0777307  .0000200  2.0127 0.0141  I   -16.831     .616    -4.028     .160   .250700   .432500   .0775900   -17.600    -4.800  
+9110 3 48532.00 I   .252261  .000347   .430611  .000384  I  .0756290  .0000200  2.1976 0.0155  I   -16.627     .616    -4.184     .160   .251700   .429200   .0754400   -17.500    -4.900  
+9110 4 48533.00 I   .253026  .000407   .427190  .000415  I  .0733329  .0000238  2.3905 0.0136  I   -16.658     .695    -4.398     .193   .252700   .425900   .0731100   -17.400    -5.000  
+9110 5 48534.00 I   .253919  .000279   .423732  .000271  I  .0708653  .0000185  2.5315 0.0153  I   -16.845     .545    -4.365     .149   .253500   .422600   .0706100   -17.400    -5.000  
+9110 6 48535.00 I   .254908  .000281   .420246  .000373  I  .0683008  .0000191  2.5799 0.0131  I   -17.038     .515    -4.030     .139   .254600   .419100   .0680400   -17.400    -4.400  
+9110 7 48536.00 I   .255934  .000246   .416738  .000368  I  .0657398  .0000185  2.5254 0.0129  I   -17.147     .541    -3.632     .101   .255600   .415600   .0655000   -17.400    -4.300  
+9110 8 48537.00 I   .256938  .000169   .413216  .000377  I  .0632768  .0000173  2.3904 0.0127  I   -17.156     .312    -3.380     .298   .256600   .412100   .0630400   -17.400    -4.300  
+9110 9 48538.00 I   .257857  .000190   .409694  .000378  I  .0609769  .0000173  2.2016 0.0111  I   -17.118     .366    -3.353     .298   .257500   .408700   .0607800   -17.300    -4.200  
+911010 48539.00 I   .258653  .000190   .406205  .000378  I  .0588820  .0000138  1.9875 0.0120  I   -17.198     .366    -3.475     .298   .258400   .405300   .0587400   -17.200    -4.200  
+911011 48540.00 I   .259307  .000215   .402771  .000454  I  .0569980  .0000165  1.7851 0.0092  I   -17.302     .436    -3.597     .298   .259000   .401800   .0569100   -17.100    -4.200  
+911012 48541.00 I   .259816  .000249   .399401  .000356  I  .0552983  .0000123  1.6231 0.0090  I   -17.215     .460    -3.614     .298   .259600   .398400   .0552600   -17.000    -4.200  
+911013 48542.00 I   .260215  .000207   .396078  .000143  I  .0537336  .0000070  1.5155 0.0068  I   -16.857     .405    -3.533     .298   .260100   .395000   .0537300   -16.800    -4.200  
+911014 48543.00 I   .260541  .000175   .392784  .000122  I  .0522502  .0000058  1.4590 0.0045  I   -16.315     .405    -3.440     .298   .260600   .391600   .0522600   -16.600    -4.100  
+911015 48544.00 I   .260834  .000189   .389497  .000059  I  .0508005  .0000056  1.4479 0.0039  I   -15.775     .428    -3.412     .298   .260900   .388200   .0507900   -16.300    -4.100  
+911016 48545.00 I   .261131  .000170   .386204  .000071  I  .0493325  .0000053  1.5027 0.0038  I   -15.401     .694    -3.440     .298   .261200   .384800   .0492500   -16.100    -4.100  
+911017 48546.00 I   .261471  .000170   .382917  .000071  I  .0477694  .0000052  1.6346 0.0034  I   -15.230     .644    -3.454     .298   .261400   .381500   .0476200   -15.900    -4.100  
+911018 48547.00 I   .261748  .000161   .379673  .000104  I  .0460491  .0000041  1.8092 0.0047  I   -15.191     .662    -3.447     .298   .261500   .378100   .0458400   -15.600    -4.000  
+911019 48548.00 I   .261878  .000214   .376475  .000157  I  .0441486  .0000078  1.9911 0.0048  I   -15.376     .618    -3.513     .298   .261500   .374800   .0439100   -15.400    -4.000  
+911020 48549.00 I   .261867  .000198   .373298  .000181  I  .0420742  .0000087  2.1510 0.0064  I   -15.685     .579    -3.635     .108   .261400   .371400   .0418300   -15.300    -3.900  
+911021 48550.00 I   .261762  .000206   .370065  .000195  I  .0398639  .0000101  2.2590 0.0067  I   -15.882     .579    -3.698     .114   .261200   .368100   .0396300   -15.200    -3.800  
+911022 48551.00 I   .261585  .000188   .366705  .000197  I  .0375816  .0000101  2.2907 0.0075  I   -15.900     .174    -3.618     .103   .261000   .364800   .0373800   -15.000    -3.800  
+911023 48552.00 I   .261298  .000215   .363280  .000223  I  .0353079  .0000110  2.2462 0.0074  I   -15.848     .190    -3.452     .108   .260700   .361500   .0351300   -14.900    -3.700  
+911024 48553.00 I   .260952  .000217   .359926  .000223  I  .0331125  .0000109  2.1319 0.0093  I   -15.783     .123    -3.372     .108   .260400   .358200   .0329600   -14.800    -3.600  
+911025 48554.00 I   .260565  .000098   .356662  .000266  I  .0310547  .0000150  1.9857 0.0083  I   -15.673     .791    -3.291     .135   .260100   .355000   .0309200   -14.800    -3.500  
+911026 48555.00 I   .260157  .000092   .353463  .000178  I  .0291278  .0000124  1.8794 0.0105  I   -15.454     .216    -3.183     .298   .259800   .351800   .0289900   -14.700    -3.500  
+911027 48556.00 I   .259771  .000149   .350310  .000168  I  .0272670  .0000147  1.8597 0.0099  I   -15.125     .216    -3.064     .298   .259700   .348700   .0271200   -14.700    -3.400  
+911028 48557.00 I   .259457  .000159   .347183  .000177  I  .0253742  .0000154  1.9426 0.0114  I   -14.759     .225    -2.967     .123   .259700   .345600   .0252200   -14.700    -3.400  
+911029 48558.00 I   .259269  .000285   .344065  .000169  I  .0233532  .0000175  2.1111 0.0107  I   -14.422     .225    -2.955     .123   .259900   .342600   .0231900   -14.700    -3.400  
+911030 48559.00 I   .259278  .000242   .340934  .000153  I  .0211389  .0000150  2.3187 0.0103  I   -14.129     .382    -3.040     .113   .260100   .339600   .0209600   -14.700    -3.400  
+911031 48560.00 I   .259575  .000242   .337805  .000153  I  .0187158  .0000110  2.5261 0.0097  I   -13.868     .392    -3.116     .106   .260400   .336700   .0185000   -14.800    -3.400  
+9111 1 48561.00 I   .260184  .000267   .334747  .000159  I  .0160973  .0000122  2.7015 0.0082  I   -13.691     .424    -3.089     .116   .260800   .333800   .0158700   -14.800    -3.400  
+9111 2 48562.00 I   .261067  .000325   .331831  .000191  I  .0133398  .0000122  2.7959 0.0094  I   -13.684     .595    -2.916     .140   .261100   .330900   .0131100   -14.700    -3.300  
+9111 3 48563.00 I   .262021  .000363   .329086  .000215  I  .0105434  .0000142  2.7766 0.0087  I   -13.719     .770    -2.618     .115   .261500   .328100   .0103500   -14.600    -3.300  
+9111 4 48564.00 I   .262838  .000359   .326446  .000227  I  .0078236  .0000123  2.6462 0.0089  I   -13.698     .770    -2.313     .115   .261800   .325200   .0076700   -14.400    -3.300  
+9111 5 48565.00 I   .263316  .000286   .323824  .000219  I  .0052780  .0000107  2.4346 0.0086  I   -13.595     .859    -2.146     .138   .262300   .322400   .0051600   -14.400    -3.300  
+9111 6 48566.00 I   .263351  .000337   .321155  .000272  I  .0029617  .0000119  2.2011 0.0080  I   -13.471     .836    -2.165     .139   .262400   .319700   .0028700   -14.400    -3.200  
+9111 7 48567.00 I   .263058  .000336   .318417  .000350  I  .0008641  .0000118  2.0029 0.0094  I   -13.386     .834    -2.313     .139   .262400   .317000   .0007600   -14.400    -3.200  
+9111 8 48568.00 I   .262580  .000304   .315600  .000394  I -.0010654  .0000146  1.8688 0.0074  I   -13.287     .809    -2.488     .108   .262100   .314300  -.0011900   -14.100    -3.100  
+9111 9 48569.00 I   .262019  .000290   .312716  .000437  I -.0028975  .0000089  1.8067 0.0080  I   -13.136     .990    -2.610     .103   .261800   .311400  -.0030400   -13.800    -3.100  
+911110 48570.00 I   .261375  .000200   .309796  .000277  I -.0047002  .0000066  1.8089 0.0056  I   -13.035     .990    -2.539     .103   .261200   .308500  -.0048500   -13.500    -3.000  
+911111 48571.00 I   .260618  .000200   .306885  .000277  I -.0065338  .0000068  1.8667 0.0042  I   -12.898     .856    -2.346     .298   .260500   .305600  -.0066900   -13.200    -3.000  
+911112 48572.00 I   .259733  .000138   .303992  .000279  I -.0084483  .0000053  1.9687 0.0045  I   -12.593     .936    -2.227     .298   .259700   .302600  -.0086100   -13.000    -2.900  
+911113 48573.00 I   .258711  .000145   .301113  .000274  I -.0104806  .0000058  2.0991 0.0052  I   -12.210     .876    -2.225     .298   .258800   .299700  -.0106500   -12.800    -2.900  
+911114 48574.00 I   .257557  .000145   .298217  .000274  I -.0126521  .0000090  2.2465 0.0054  I   -12.014     .814    -2.201     .298   .257800   .296700  -.0128400   -12.600    -2.800  
+911115 48575.00 I   .256324  .000132   .295259  .000276  I -.0149750  .0000091  2.3981 0.0064  I   -11.987     .476    -2.108     .298   .256800   .293800  -.0151700   -12.500    -2.800  
+911116 48576.00 I   .255081  .000275   .292194  .000336  I -.0174429  .0000090  2.5336 0.0083  I   -12.041     .406    -2.059     .298   .255700   .290800  -.0176400   -12.400    -2.900  
+911117 48577.00 I   .253909  .000412   .289017  .000356  I -.0200270  .0000139  2.6234 0.0081  I   -12.194     .442    -2.232     .105   .254700   .287800  -.0202100   -12.400    -2.900  
+911118 48578.00 I   .252920  .000399   .285821  .000373  I -.0226646  .0000135  2.6379 0.0097  I   -12.421     .429    -2.529     .104   .253700   .284700  -.0228200   -12.400    -2.900  
+911119 48579.00 I   .252234  .000378   .282720  .000381  I -.0252746  .0000135  2.5678 0.0096  I   -12.615     .479    -2.634     .105   .252700   .281700  -.0253900   -12.400    -2.900  
+911120 48580.00 I   .251872  .000399   .279772  .000361  I -.0277784  .0000136  2.4324 0.0096  I   -12.702     .475    -2.403     .116   .251800   .278600  -.0278700   -12.400    -2.800  
+911121 48581.00 I   .251571  .000399   .276910  .000361  I -.0301254  .0000136  2.2549 0.0111  I   -12.665     .475    -2.051     .116   .250900   .275500  -.0302000   -12.400    -2.700  
+911122 48582.00 I   .251059  .000350   .274132  .000274  I -.0322901  .0000176  2.0829 0.0131  I   -12.373     .546    -1.836     .109   .250100   .272400  -.0323700   -12.400    -2.600  
+911123 48583.00 I   .250193  .000409   .271398  .000419  I -.0343196  .0000223  1.9959 0.0146  I   -11.997     .643    -1.823     .298   .249200   .269300  -.0344300   -12.400    -2.500  
+911124 48584.00 I   .249052  .000340   .268621  .000541  I -.0363251  .0000232  2.0385 0.0179  I   -11.728     .705    -1.850     .298   .248400   .266200  -.0364800   -12.400    -2.400  
+911125 48585.00 I   .247766  .000355   .265706  .000554  I -.0384389  .0000280  2.2080 0.0207  I   -11.627     .831    -1.807     .150   .247500   .263100  -.0386300   -12.400    -2.300  
+911126 48586.00 I   .246464  .000455   .262558  .000630  I -.0407691  .0000344  2.4616 0.0224  I   -11.648     .980    -1.716     .200   .246700   .260000  -.0409800   -12.400    -2.300  
+911127 48587.00 I   .245276  .000455   .259134  .000630  I -.0433617  .0000349  2.7142 0.0240  I   -11.670     .980    -1.590     .200   .246000   .256900  -.0435600   -12.500    -2.200  
+911128 48588.00 I   .244270  .000455   .255563  .000630  I -.0461708  .0000336  2.8869 0.0244  I   -11.741     .980    -1.381     .200   .245200   .253800  -.0463600   -12.500    -2.200  
+911129 48589.00 I   .243445  .000411   .251970  .000853  I -.0491002  .0000340  2.9537 0.0202  I   -11.722     .913    -1.306     .232   .244400   .250800  -.0492700   -12.500    -2.100  
+911130 48590.00 I   .242748  .000348   .248441  .000682  I -.0520428  .0000223  2.9144 0.0217  I   -11.670     .767    -1.345     .236   .243600   .247800  -.0522000   -12.400    -2.100  
+9112 1 48591.00 I   .242116  .000386   .245061  .000668  I -.0548992  .0000270  2.7858 0.0131  I   -11.714     .395    -1.423     .242   .242700   .244800  -.0550500   -12.400    -2.100  
+9112 2 48592.00 I   .241483  .000254   .241909  .000387  I -.0575943  .0000136  2.5968 0.0151  I   -11.882     .428    -1.498     .297   .241600   .241900  -.0577600   -12.400    -2.100  
+9112 3 48593.00 I   .240748  .000365   .239028  .000423  I -.0600857  .0000137  2.3864 0.0097  I   -12.099     .406    -1.604     .282   .240500   .239100  -.0602600   -12.300    -2.100  
+9112 4 48594.00 I   .239785  .000367   .236379  .000438  I -.0623717  .0000137  2.1897 0.0097  I   -12.168     .363    -1.767     .290   .239100   .236300  -.0625700   -12.200    -2.100  
+9112 5 48595.00 I   .238404  .000355   .233887  .000431  I -.0644791  .0000138  2.0349 0.0094  I   -11.861     .390    -1.645     .306   .237500   .233600  -.0646900   -12.000    -2.000  
+9112 6 48596.00 I   .236477  .000381   .231434  .000310  I -.0664603  .0000130  1.9366 0.0089  I   -11.349     .418    -1.441     .336   .235800   .230800  -.0666800   -11.800    -1.900  
+9112 7 48597.00 I   .234014  .000394   .228899  .000367  I -.0683727  .0000114  1.8995 0.0075  I   -10.898     .356    -1.435     .366   .233800   .228000  -.0685900   -11.700    -1.800  
+9112 8 48598.00 I   .231202  .000346   .226236  .000379  I -.0702803  .0000073  1.9256 0.0074  I   -10.537     .226    -1.527     .342   .231700   .225200  -.0704900   -11.600    -1.800  
+9112 9 48599.00 I   .228292  .000381   .223448  .000385  I -.0722415  .0000093  2.0047 0.0056  I   -10.209     .207    -1.561     .360   .229500   .222400  -.0724600   -11.500    -1.800  
+911210 48600.00 I   .225542  .000270   .220545  .000313  I -.0743029  .0000084  2.1233 0.0070  I    -9.989     .312    -1.435     .351   .227200   .219600  -.0745200   -11.400    -1.700  
+911211 48601.00 I   .223142  .000267   .217573  .000316  I -.0764947  .0000105  2.2616 0.0074  I   -10.029     .337    -1.154     .305   .224800   .216800  -.0767200   -11.300    -1.700  
+911212 48602.00 I   .221062  .000279   .214672  .000328  I -.0788245  .0000122  2.3951 0.0093  I   -10.288     .337     -.990     .305   .222400   .214100  -.0790600   -11.300    -1.700  
+911213 48603.00 I   .219187  .000274   .211939  .000222  I -.0812771  .0000154  2.5053 0.0111  I   -10.438     .478     -.795     .226   .220000   .211400  -.0815300   -11.300    -1.700  
+911214 48604.00 I   .217366  .000265   .209355  .000271  I -.0838232  .0000185  2.5797 0.0110  I   -10.313     .424     -.721     .207   .217900   .208800  -.0841000   -11.200    -1.700  
+911215 48605.00 I   .215521  .000214   .206838  .000232  I -.0864216  .0000156  2.6092 0.0114  I   -10.178     .446     -.909     .184   .215700   .206200  -.0867100   -11.200    -1.700  
+911216 48606.00 I   .213630  .000186   .204303  .000223  I -.0890221  .0000133  2.5800 0.0104  I   -10.387     .412    -1.177     .135   .213700   .203800  -.0893100   -11.100    -1.700  
+911217 48607.00 I   .211809  .000191   .201740  .000213  I -.0915598  .0000138  2.4854 0.0091  I   -10.792     .416    -1.313     .131   .211700   .201400  -.0918400   -11.100    -1.700  
+911218 48608.00 I   .210191  .000239   .199201  .000240  I -.0939742  .0000125  2.3347 0.0091  I   -11.055     .389    -1.229     .135   .209800   .199100  -.0942200   -11.100    -1.600  
+911219 48609.00 I   .208711  .000232   .196874  .000243  I -.0962138  .0000119  2.1379 0.0085  I   -11.019     .255     -.986     .129   .207900   .196800  -.0964200   -11.100    -1.600  
+911220 48610.00 I   .207235  .000244   .194795  .000250  I -.0982561  .0000114  1.9592 0.0073  I   -10.627     .275     -.790     .121   .206000   .194600  -.0984300   -11.000    -1.600  
+911221 48611.00 I   .205507  .000194   .192814  .000202  I -.1001693  .0000086  1.8916 0.0078  I   -10.018     .428     -.874     .107   .204100   .192400  -.1003400   -11.000    -1.600  
+911222 48612.00 I   .203369  .000249   .190776  .000238  I -.1020840  .0000106  1.9582 0.0102  I    -9.412     .461    -1.084     .115   .202200   .190200  -.1022700   -11.000    -1.600  
+911223 48613.00 I   .200948  .000400   .188654  .000371  I -.1041185  .0000184  2.1232 0.0085  I    -9.100     .473    -1.190     .102   .200300   .187900  -.1043100   -11.000    -1.600  
+911224 48614.00 I   .198454  .000415   .186472  .000375  I -.1063444  .0000132  2.3301 0.0133  I    -9.251     .556    -1.222     .298   .198300   .185700  -.1065500   -10.900    -1.600  
+911225 48615.00 I   .196072  .000297   .184253  .000251  I -.1087701  .0000191  2.5113 0.0172  I    -9.653     .652    -1.291     .298   .196300   .183400  -.1089900   -10.800    -1.600  
+911226 48616.00 I   .193885  .000297   .182012  .000251  I -.1113399  .0000317  2.6112 0.0276  I    -9.981     .652    -1.355     .298   .194400   .181200  -.1115800   -10.600    -1.600  
+911227 48617.00 I   .191929  .000393   .179752  .000327  I -.1139584  .0000518  2.6088 0.0236  I   -10.162     .637    -1.266     .298   .192400   .178900  -.1142000   -10.500    -1.600  
+911228 48618.00 I   .190212  .000615   .177484  .000274  I -.1165251  .0000351  2.5092 0.0322  I   -10.284     .473    -1.032     .174   .190400   .176600  -.1167500   -10.300    -1.700  
+911229 48619.00 I   .188613  .000711   .175240  .000404  I -.1189540  .0000383  2.3412 0.0258  I   -10.401     .473     -.823     .174   .188400   .174400  -.1191500   -10.200    -1.700  
+911230 48620.00 I   .186972  .000711   .173043  .000404  I -.1211998  .0000378  2.1500 0.0258  I   -10.471     .473     -.767     .174   .186500   .172200  -.1213700   -10.100    -1.700  
+911231 48621.00 I   .185126  .000714   .170911  .000381  I -.1232581  .0000346  1.9712 0.0215  I   -10.473     .203     -.831     .231   .184500   .170000  -.1234200   -10.000    -1.700  
+92 1 1 48622.00 I   .182965  .000672   .168856  .000345  I -.1251559  .0000207  1.8335 0.0201  I   -10.437     .507     -.917     .165   .182400   .167900  -.1253000    -9.900    -1.700  
+92 1 2 48623.00 I   .180592  .000672   .166857  .000345  I -.1269451  .0000203  1.7556 0.0144  I   -10.354     .507     -.996     .165   .180300   .165900  -.1270800    -9.900    -1.700  
+92 1 3 48624.00 I   .178161  .000672   .164885  .000345  I -.1286896  .0000200  1.7450 0.0107  I   -10.201     .688    -1.068     .298   .178200   .163900  -.1288200    -9.900    -1.700  
+92 1 4 48625.00 I   .175799  .000264   .162915  .000341  I -.1304568  .0000070  1.7995 0.0105  I   -10.003     .529    -1.066     .298   .175700   .161600  -.1305800   -10.100    -1.500  
+92 1 5 48626.00 I   .173506  .000192   .160942  .000246  I -.1323066  .0000063  1.9081 0.0045  I    -9.781     .529     -.909     .298   .173500   .159600  -.1324300   -10.100    -1.400  
+92 1 6 48627.00 I   .171249  .000200   .158962  .000246  I -.1342857  .0000055  2.0548 0.0044  I    -9.535     .475     -.646     .298   .171100   .157800  -.1344200   -10.000    -1.400  
+92 1 7 48628.00 I   .168993  .000169   .156979  .000254  I -.1364224  .0000061  2.2201 0.0041  I    -9.315     .241     -.461     .298   .168700   .156000  -.1365600    -9.900    -1.400  
+92 1 8 48629.00 I   .166663  .000169   .155043  .000254  I -.1387244  .0000061  2.3807 0.0044  I    -9.222     .197     -.468     .107   .166200   .154200  -.1388600    -9.900    -1.400  
+92 1 9 48630.00 I   .164123  .000172   .153294  .000254  I -.1411761  .0000063  2.5180 0.0059  I    -9.265     .197     -.513     .107   .163600   .152600  -.1413200    -9.800    -1.400  
+92 110 48631.00 I   .161402  .000185   .151714  .000220  I -.1437490  .0000102  2.6210 0.0053  I    -9.283     .791     -.499     .134   .160900   .151000  -.1439000    -9.800    -1.400  
+92 111 48632.00 I   .158585  .000149   .150245  .000208  I -.1464011  .0000085  2.6729 0.0085  I    -9.144     .166     -.527     .121   .158100   .149500  -.1465400    -9.800    -1.400  
+92 112 48633.00 I   .155692  .000357   .148849  .000334  I -.1490736  .0000135  2.6613 0.0082  I    -8.960     .184     -.691     .123   .155300   .148100  -.1491800    -9.800    -1.400  
+92 113 48634.00 I   .152741  .000365   .147494  .000339  I -.1517024  .0000141  2.5859 0.0101  I    -8.956     .304     -.927     .115   .152300   .146700  -.1518000    -9.800    -1.400  
+92 114 48635.00 I   .149763  .000359   .146138  .000332  I -.1542271  .0000151  2.4555 0.0101  I    -9.257     .367     -.997     .298   .149300   .145400  -.1543000    -9.900    -1.300  
+92 115 48636.00 I   .146774  .000366   .144772  .000263  I -.1566078  .0000145  2.3083 0.0098  I    -9.832     .369     -.773     .133   .146200   .144200  -.1566900   -10.000    -1.300  
+92 116 48637.00 I   .143765  .000366   .143469  .000263  I -.1588545  .0000126  2.1937 0.0103  I   -10.496     .343     -.556     .125   .143100   .142900  -.1589500   -10.200    -1.300  
+92 117 48638.00 I   .140654  .000403   .142244  .000248  I -.1610204  .0000147  2.1548 0.0086  I   -10.968     .378     -.626     .134   .139900   .141700  -.1611400   -10.400    -1.300  
+92 118 48639.00 I   .137345  .000298   .141095  .000326  I -.1632032  .0000117  2.2332 0.0085  I   -10.999     .421     -.965     .123   .136700   .140500  -.1633600   -10.500    -1.300  
+92 119 48640.00 I   .133813  .000193   .139997  .000287  I -.1655276  .0000086  2.4339 0.0069  I   -10.616     .479    -1.297     .125   .133500   .139300  -.1657200   -10.500    -1.400  
+92 120 48641.00 I   .130220  .000191   .138870  .000286  I -.1680973  .0000075  2.7136 0.0057  I   -10.135     .465    -1.374     .135   .130300   .138000  -.1683300   -10.500    -1.400  
+92 121 48642.00 I   .126773  .000203   .137616  .000282  I -.1709548  .0000076  2.9935 0.0056  I    -9.818     .493    -1.239     .113   .127200   .136700  -.1712100   -10.500    -1.500  
+92 122 48643.00 I   .123633  .000164   .136222  .000333  I -.1740492  .0000084  3.1682 0.0057  I    -9.600     .460    -1.120     .122   .124100   .135400  -.1742900   -10.400    -1.600  
+92 123 48644.00 I   .120838  .000164   .134840  .000333  I -.1772390  .0000084  3.1864 0.0060  I    -9.442     .460    -1.125     .122   .121000   .134000  -.1774700   -10.300    -1.700  
+92 124 48645.00 I   .118239  .000176   .133514  .000294  I -.1803757  .0000086  3.0656 0.0070  I    -9.437     .437    -1.097     .132   .118000   .132700  -.1805900   -10.200    -1.800  
+92 125 48646.00 I   .115660  .000171   .132246  .000378  I -.1833389  .0000112  2.8511 0.0086  I    -9.644     .344     -.960     .191   .115100   .131300  -.1835400   -10.100    -1.800  
+92 126 48647.00 I   .113031  .000172   .131007  .000394  I -.1860675  .0000148  2.6056 0.0093  I    -9.925     .371     -.876     .326   .112300   .129900  -.1862800    -9.900    -1.900  
+92 127 48648.00 I   .110308  .000172   .129756  .000394  I -.1885557  .0000148  2.3768 0.0102  I   -10.025     .418     -.983     .303   .109500   .128600  -.1887700    -9.800    -2.000  
+92 128 48649.00 I   .107447  .000190   .128450  .000390  I -.1908372  .0000141  2.1964 0.0103  I    -9.890     .477    -1.190     .347   .106800   .127300  -.1910600    -9.700    -2.000  
+92 129 48650.00 I   .104483  .000190   .127120  .000390  I -.1929756  .0000143  2.0974 0.0100  I    -9.674     .466    -1.436     .301   .104200   .126100  -.1932200    -9.600    -2.100  
+92 130 48651.00 I   .101609  .000199   .125938  .000387  I -.1950580  .0000142  2.0764 0.0119  I    -9.421     .466    -1.643     .301   .101600   .125000  -.1953000    -9.500    -2.100  
+92 131 48652.00 I   .098935  .000227   .124947  .000371  I -.1971464  .0000189  2.1095 0.0115  I    -9.104     .487    -1.771     .316   .099100   .123900  -.1973700    -9.500    -2.200  
+92 2 1 48653.00 I   .096518  .000235   .124143  .000387  I -.1992921  .0000181  2.1877 0.0104  I    -8.786     .515    -1.815     .172   .096700   .123000  -.1994900    -9.500    -2.200  
+92 2 2 48654.00 I   .094302  .000203   .123506  .000278  I -.2015317  .0000089  2.2954 0.0102  I    -8.534     .503    -1.695     .158   .094300   .122200  -.2017000    -9.700    -2.300  
+92 2 3 48655.00 I   .092183  .000204   .123008  .000277  I -.2038871  .0000096  2.4158 0.0069  I    -8.416     .465    -1.427     .144   .091700   .121400  -.2040200    -9.600    -2.200  
+92 2 4 48656.00 I   .090027  .000214   .122615  .000274  I -.2063606  .0000106  2.5280 0.0075  I    -8.473     .484    -1.213     .168   .089300   .120700  -.2065100    -9.400    -2.200  
+92 2 5 48657.00 I   .087698  .000216   .122252  .000272  I -.2089429  .0000115  2.6394 0.0080  I    -8.697     .400    -1.266     .128   .086900   .120100  -.2091300    -9.200    -2.300  
+92 2 6 48658.00 I   .085120  .000216   .121749  .000272  I -.2116347  .0000119  2.7366 0.0082  I    -9.004     .380    -1.552     .119   .084500   .119600  -.2118600    -9.000    -2.300  
+92 2 7 48659.00 I   .082425  .000212   .121095  .000251  I -.2143996  .0000118  2.7841 0.0075  I    -9.303     .236    -1.864     .298   .082000   .119100  -.2146100    -9.100    -2.300  
+92 2 8 48660.00 I   .079747  .000145   .120336  .000202  I -.2171790  .0000092  2.7599 0.0077  I    -9.505     .258    -2.042     .298   .079400   .118600  -.2173600    -9.200    -2.400  
+92 2 9 48661.00 I   .077048  .000177   .119538  .000228  I -.2198943  .0000100  2.6606 0.0071  I    -9.550     .260    -2.086     .298   .076700   .118200  -.2200300    -9.400    -2.400  
+92 210 48662.00 I   .074254  .000177   .118767  .000228  I -.2224826  .0000108  2.5086 0.0072  I    -9.572     .306    -2.036     .298   .073900   .117700  -.2225800    -9.500    -2.400  
+92 211 48663.00 I   .071296  .000113   .118085  .000239  I -.2249019  .0000103  2.3279 0.0067  I    -9.777     .335    -1.844     .120   .071100   .117300  -.2249800    -9.700    -2.400  
+92 212 48664.00 I   .068126  .000124   .117511  .000189  I -.2271426  .0000080  2.1597 0.0065  I   -10.210     .329    -1.526     .116   .068100   .116900  -.2272000    -9.800    -2.400  
+92 213 48665.00 I   .064769  .000124   .117034  .000189  I -.2292410  .0000080  2.0505 0.0064  I   -10.677     .303    -1.413     .109   .065100   .116600  -.2293000   -10.000    -2.300  
+92 214 48666.00 I   .061346  .000159   .116670  .000140  I -.2312755  .0000100  2.0371 0.0062  I   -11.010     .307    -1.693     .114   .062000   .116300  -.2313500   -10.200    -2.300  
+92 215 48667.00 I   .057994  .000218   .116441  .000174  I -.2333549  .0000095  2.1427 0.0091  I   -11.097     .271    -2.234     .298   .058900   .116100  -.2334600   -10.300    -2.400  
+92 216 48668.00 I   .054803  .000246   .116362  .000155  I -.2355963  .0000153  2.3546 0.0093  I   -10.912     .178    -2.651     .298   .055800   .115900  -.2357400   -10.500    -2.400  
+92 217 48669.00 I   .051751  .000246   .116424  .000155  I -.2380810  .0000159  2.6173 0.0102  I   -10.611     .161    -2.670     .298   .052600   .115700  -.2382600   -10.600    -2.500  
+92 218 48670.00 I   .048799  .000290   .116604  .000149  I -.2408220  .0000134  2.8532 0.0099  I   -10.353     .137    -2.396     .298   .049500   .115700  -.2410200   -10.700    -2.500  
+92 219 48671.00 I   .045888  .000321   .116854  .000342  I -.2437544  .0000119  2.9900 0.0089  I   -10.123     .173    -2.147     .298   .046300   .115600  -.2439800   -10.700    -2.600  
+92 220 48672.00 I   .042907  .000325   .117120  .000331  I -.2467553  .0000117  2.9867 0.0085  I    -9.889     .190    -2.105     .298   .043000   .115500  -.2469800   -10.800    -2.600  
+92 221 48673.00 I   .039772  .000332   .117341  .000296  I -.2496841  .0000122  2.8523 0.0094  I    -9.710     .195    -2.142     .110   .039800   .115500  -.2499100   -10.800    -2.700  
+92 222 48674.00 I   .036468  .000333   .117447  .000203  I -.2524364  .0000146  2.6473 0.0101  I    -9.651     .260    -2.107     .151   .036500   .115400  -.2526400   -10.800    -2.700  
+92 223 48675.00 I   .033121  .000299   .117372  .000194  I -.2549754  .0000160  2.4325 0.0108  I    -9.670     .283    -2.212     .162   .033200   .115300  -.2551400   -10.800    -2.800  
+92 224 48676.00 I   .029796  .000295   .117134  .000205  I -.2573113  .0000159  2.2473 0.0125  I    -9.614     .423    -2.581     .175   .029900   .115300  -.2574300   -10.700    -2.800  
+92 225 48677.00 I   .026512  .000262   .116772  .000198  I -.2594898  .0000192  2.1213 0.0135  I    -9.548     .486    -3.032     .198   .026600   .115200  -.2595300   -10.700    -2.900  
+92 226 48678.00 I   .023303  .000264   .116361  .000149  I -.2615661  .0000219  2.0317 0.0149  I    -9.711     .442    -3.300     .183   .023200   .115100  -.2615300   -10.600    -3.000  
+92 227 48679.00 I   .020120  .000267   .116041  .000189  I -.2635649  .0000228  1.9770 0.0186  I   -10.007     .442    -3.272     .183   .019800   .115000  -.2634800   -10.500    -3.000  
+92 228 48680.00 I   .016870  .000283   .115871  .000204  I -.2655401  .0000301  1.9822 0.0179  I   -10.167     .482    -3.161     .169   .016400   .115000  -.2654600   -10.300    -3.100  
+92 229 48681.00 I   .013480  .000161   .115880  .000229  I -.2675507  .0000275  2.0516 0.0165  I   -10.006     .538    -3.175     .178   .013000   .115100  -.2675100   -10.100    -3.200  
+92 3 1 48682.00 I   .009978  .000153   .116087  .000159  I -.2696648  .0000136  2.1854 0.0145  I    -9.601     .468    -3.219     .165   .009500   .115200  -.2697000    -9.900    -3.200  
+92 3 2 48683.00 I   .006393  .000153   .116477  .000159  I -.2719343  .0000093  2.3575 0.0080  I    -9.196     .422    -3.154     .150   .006000   .115400  -.2720500    -9.700    -3.300  
+92 3 3 48684.00 I   .002747  .000135   .117026  .000169  I -.2743831  .0000084  2.5395 0.0075  I    -8.927     .523    -3.034     .163   .002500   .115700  -.2745600    -9.500    -3.400  
+92 3 4 48685.00 I  -.000960  .000172   .117699  .000122  I -.2770061  .0000118  2.6999 0.0072  I    -8.780     .444    -3.013     .136  -.000900   .116200  -.2772200    -8.800    -3.500  
+92 3 5 48686.00 I  -.004773  .000172   .118416  .000122  I -.2797652  .0000116  2.8073 0.0084  I    -8.712     .444    -3.165     .131  -.004400   .116700  -.2799900    -8.700    -3.600  
+92 3 6 48687.00 I  -.008589  .000172   .119105  .000122  I -.2825980  .0000120  2.8466 0.0095  I    -8.712     .304    -3.375     .298  -.008000   .117300  -.2828200    -8.600    -3.700  
+92 3 7 48688.00 I  -.012262  .000181   .119710  .000131  I -.2854369  .0000150  2.8212 0.0122  I    -8.720     .304    -3.487     .140  -.011500   .118000  -.2856300    -8.500    -3.800  
+92 3 8 48689.00 I  -.015689  .000206   .120230  .000146  I -.2882203  .0000212  2.7353 0.0131  I    -8.570     .388    -3.404     .226  -.015000   .118800  -.2883600    -8.500    -3.900  
+92 3 9 48690.00 I  -.018919  .000209   .120750  .000143  I -.2908904  .0000214  2.5979 0.0153  I    -8.316     .369    -3.238     .239  -.018400   .119700  -.2910000    -8.500    -4.000  
+92 310 48691.00 I  -.022035  .000261   .121373  .000134  I -.2934116  .0000220  2.4468 0.0153  I    -8.202     .414    -3.195     .256  -.021900   .120700  -.2935400    -8.600    -4.100  
+92 311 48692.00 I  -.025117  .000254   .122197  .000140  I -.2958109  .0000220  2.3764 0.0170  I    -8.423     .481    -3.444     .244  -.025300   .121800  -.2959800    -8.700    -4.200  
+92 312 48693.00 I  -.028234  .000254   .123272  .000140  I -.2982033  .0000258  2.4228 0.0165  I    -8.890     .463    -3.756     .232  -.028700   .123000  -.2984000    -8.700    -4.300  
+92 313 48694.00 I  -.031378  .000263   .124589  .000118  I -.3006878  .0000247  2.5630 0.0170  I    -9.379     .501    -4.126     .238  -.032100   .124300  -.3008900    -8.800    -4.400  
+92 314 48695.00 I  -.034530  .000228   .126117  .000114  I -.3033568  .0000221  2.7858 0.0179  I    -9.542     .533    -4.570     .158  -.035400   .125700  -.3035600    -8.900    -4.500  
+92 315 48696.00 I  -.037731  .000252   .127806  .000135  I -.3062763  .0000260  3.0595 0.0164  I    -9.272     .589    -4.835     .100  -.038700   .127300  -.3064700    -9.000    -4.600  
+92 316 48697.00 I  -.040970  .000268   .129629  .000200  I -.3094750  .0000242  3.3309 0.0169  I    -8.884     .582    -4.740     .101  -.042000   .128900  -.3096600    -9.000    -4.600  
+92 317 48698.00 I  -.044230  .000193   .131570  .000220  I -.3129125  .0000217  3.5254 0.0134  I    -8.774     .546    -4.405     .298  -.045300   .130600  -.3130800    -9.000    -4.700  
+92 318 48699.00 I  -.047505  .000155   .133592  .000206  I -.3164823  .0000113  3.5892 0.0122  I    -9.030     .590    -4.136     .298  -.048500   .132400  -.3166600    -9.000    -4.800  
+92 319 48700.00 I  -.050798  .000150   .135598  .000207  I -.3200428  .0000112  3.5085 0.0084  I    -9.299     .554    -4.072     .298  -.051600   .134300  -.3202100    -8.900    -4.800  
+92 320 48701.00 I  -.054100  .000189   .137506  .000215  I -.3234626  .0000125  3.3178 0.0078  I    -9.392     .490    -4.157     .298  -.054600   .136300  -.3236400    -8.900    -4.900  
+92 321 48702.00 I  -.057350  .000189   .139342  .000226  I -.3266588  .0000110  3.0685 0.0088  I    -9.326     .404    -4.250     .115  -.057600   .138300  -.3268300    -8.800    -5.000  
+92 322 48703.00 I  -.060446  .000211   .141156  .000229  I -.3296001  .0000123  2.8209 0.0077  I    -9.135     .388    -4.393     .123  -.060400   .140300  -.3297700    -8.600    -5.000  
+92 323 48704.00 I  -.063319  .000174   .143002  .000157  I -.3323193  .0000109  2.6295 0.0086  I    -8.781     .388    -4.595     .123  -.063100   .142400  -.3324800    -8.500    -5.100  
+92 324 48705.00 I  -.065917  .000265   .144942  .000164  I -.3348843  .0000119  2.5136 0.0096  I    -8.367     .198    -4.743     .141  -.065700   .144600  -.3350400    -8.400    -5.100  
+92 325 48706.00 I  -.068216  .000310   .147021  .000196  I -.3373685  .0000158  2.4638 0.0104  I    -8.153     .301    -4.766     .126  -.068200   .146800  -.3375000    -8.400    -5.100  
+92 326 48707.00 I  -.070314  .000310   .149236  .000196  I -.3398287  .0000171  2.4643 0.0146  I    -8.233     .301    -4.741     .126  -.070600   .149000  -.3399300    -8.300    -5.100  
+92 327 48708.00 I  -.072339  .000373   .151570  .000240  I -.3423103  .0000245  2.5044 0.0136  I    -8.380     .412    -4.791     .108  -.072800   .151200  -.3424000    -8.300    -5.100  
+92 328 48709.00 I  -.074391  .000401   .153996  .000305  I -.3448509  .0000212  2.5847 0.0169  I    -8.381     .345    -4.931     .298  -.074900   .153400  -.3449700    -8.400    -5.100  
+92 329 48710.00 I  -.076467  .000408   .156449  .000302  I -.3474917  .0000233  2.7012 0.0157  I    -8.272     .345    -5.027     .298  -.077000   .155600  -.3476400    -8.400    -5.100  
+92 330 48711.00 I  -.078543  .000408   .158854  .000302  I -.3502571  .0000232  2.8293 0.0157  I    -8.252     .469    -4.980     .298  -.079000   .157800  -.3504400    -8.500    -5.200  
+92 331 48712.00 I  -.080594  .000266   .161135  .000331  I -.3531461  .0000209  2.9448 0.0148  I    -8.359     .505    -4.865     .298  -.080900   .159900  -.3533400    -8.600    -5.200  
+92 4 1 48713.00 I  -.082596  .000266   .163229  .000331  I -.3561338  .0000184  3.0214 0.0137  I    -8.384     .656    -4.838     .148  -.082800   .161900  -.3563400    -8.700    -5.300  
+92 4 2 48714.00 I  -.084556  .000322   .165149  .000316  I -.3591684  .0000177  3.0364 0.0179  I    -8.108     .656    -4.966     .148  -.084600   .163900  -.3593600    -8.800    -5.400  
+92 4 3 48715.00 I  -.086492  .000417   .166920  .000264  I -.3621836  .0000307  2.9824 0.0154  I    -7.774     .822    -5.110     .187  -.086500   .165900  -.3623500    -8.600    -5.600  
+92 4 4 48716.00 I  -.088401  .000265   .168583  .000385  I -.3651128  .0000253  2.8673 0.0192  I    -7.780     .813    -5.096     .234  -.088200   .167700  -.3652700    -8.500    -5.700  
+92 4 5 48717.00 I  -.090251  .000264   .170205  .000376  I -.3679050  .0000230  2.7127 0.0172  I    -8.052     .816    -4.950     .256  -.090000   .169600  -.3680400    -8.300    -5.800  
+92 4 6 48718.00 I  -.092014  .000347   .171858  .000359  I -.3705355  .0000233  2.5499 0.0171  I    -8.319     .713    -4.813     .326  -.091800   .171500  -.3706600    -8.200    -5.900  
+92 4 7 48719.00 I  -.093706  .000336   .173611  .000324  I -.3730152  .0000252  2.4183 0.0179  I    -8.369     .644    -4.828     .371  -.093500   .173400  -.3731300    -8.200    -6.000  
+92 4 8 48720.00 I  -.095351  .000286   .175516  .000343  I -.3753975  .0000272  2.3630 0.0184  I    -8.188     .603    -5.034     .316  -.095300   .175300  -.3755200    -8.200    -6.000  
+92 4 9 48721.00 I  -.096976  .000279   .177569  .000327  I -.3777761  .0000268  2.4123 0.0203  I    -7.961     .603    -5.431     .316  -.097000   .177300  -.3779200    -8.300    -6.100  
+92 410 48722.00 I  -.098597  .000279   .179745  .000327  I -.3802556  .0000301  2.5621 0.0176  I    -7.720     .470    -5.849     .330  -.098800   .179300  -.3804300    -8.400    -6.100  
+92 411 48723.00 I  -.100207  .000260   .182020  .000220  I -.3829267  .0000228  2.7913 0.0212  I    -7.475     .433    -6.328     .305  -.100600   .181500  -.3831500    -8.500    -6.100  
+92 412 48724.00 I  -.101809  .000203   .184383  .000152  I -.3858506  .0000299  3.0578 0.0182  I    -7.264     .583    -6.729     .394  -.102300   .183800  -.3861300    -8.600    -6.000  
+92 413 48725.00 I  -.103423  .000230   .186819  .000191  I -.3890352  .0000284  3.3030 0.0207  I    -7.173     .559    -6.812     .368  -.104100   .186100  -.3893700    -8.600    -6.000  
+92 414 48726.00 I  -.105076  .000239   .189311  .000237  I -.3924319  .0000285  3.4741 0.0208  I    -7.289     .467    -6.448     .331  -.105900   .188500  -.3927900    -8.700    -5.900  
+92 415 48727.00 I  -.106793  .000240   .191842  .000240  I -.3959418  .0000303  3.5204 0.0211  I    -7.598     .467    -5.794     .331  -.107700   .190800  -.3962800    -8.700    -5.800  
+92 416 48728.00 I  -.108599  .000240   .194378  .000240  I -.3994216  .0000311  3.4134 0.0219  I    -7.914     .467    -5.348     .331  -.109500   .193200  -.3997000    -8.700    -5.800  
+92 417 48729.00 I  -.110484  .000241   .196883  .000233  I -.4027295  .0000316  3.1891 0.0185  I    -8.160     .495    -5.304     .349  -.111300   .195700  -.4029400    -8.700    -5.700  
+92 418 48730.00 I  -.112402  .000213   .199323  .000253  I -.4057833  .0000199  2.9153 0.0178  I    -8.288     .530    -5.535     .139  -.113100   .198100  -.4059300    -8.600    -5.700  
+92 419 48731.00 I  -.114309  .000196   .201692  .000292  I -.4085627  .0000166  2.6495 0.0128  I    -8.269     .578    -5.795     .156  -.114800   .200500  -.4086600    -8.500    -5.800  
+92 420 48732.00 I  -.116160  .000120   .203983  .000278  I -.4110990  .0000161  2.4340 0.0106  I    -8.171     .681    -5.904     .190  -.116500   .202800  -.4111700    -8.400    -5.800  
+92 421 48733.00 I  -.117913  .000163   .206196  .000264  I -.4134536  .0000133  2.2873 0.0106  I    -8.150     .681    -5.835     .190  -.118100   .205200  -.4135300    -8.300    -5.900  
+92 422 48734.00 I  -.119538  .000163   .208379  .000264  I -.4157038  .0000137  2.2313 0.0098  I    -8.251     .659    -5.760     .154  -.119700   .207600  -.4158200    -8.200    -6.000  
+92 423 48735.00 I  -.121032  .000164   .210673  .000278  I -.4179446  .0000143  2.2606 0.0107  I    -8.374     .659    -5.847     .154  -.121300   .209900  -.4181000    -8.100    -6.100  
+92 424 48736.00 I  -.122480  .000174   .213058  .000288  I -.4202420  .0000165  2.3410 0.0105  I    -8.323     .564    -6.084     .112  -.122800   .212300  -.4204300    -7.900    -6.300  
+92 425 48737.00 I  -.123975  .000206   .215479  .000249  I -.4226378  .0000154  2.4551 0.0118  I    -7.965     .505    -6.341     .298  -.124300   .214700  -.4228500    -7.800    -6.400  
+92 426 48738.00 I  -.125501  .000273   .217910  .000244  I -.4251565  .0000170  2.5820 0.0109  I    -7.453     .559    -6.459     .298  -.125900   .217100  -.4253900    -7.700    -6.500  
+92 427 48739.00 I  -.127017  .000275   .220342  .000249  I -.4277973  .0000153  2.6954 0.0106  I    -7.106     .681    -6.406     .102  -.127400   .219400  -.4280300    -7.600    -6.600  
+92 428 48740.00 I  -.128494  .000278   .222791  .000292  I -.4305358  .0000126  2.7743 0.0095  I    -7.126     .714    -6.319     .126  -.129000   .221800  -.4307400    -7.500    -6.700  
+92 429 48741.00 I  -.129927  .000284   .225263  .000283  I -.4333245  .0000112  2.7891 0.0084  I    -7.404     .635    -6.331     .127  -.130500   .224100  -.4335000    -7.500    -6.700  
+92 430 48742.00 I  -.131420  .000284   .227741  .000283  I -.4360890  .0000112  2.7291 0.0086  I    -7.558     .635    -6.360     .127  -.132100   .226500  -.4362300    -7.500    -6.800  
+92 5 1 48743.00 I  -.133096  .000324   .230149  .000304  I -.4387615  .0000131  2.6056 0.0083  I    -7.533     .695    -6.293     .155  -.133800   .228800  -.4388700    -7.500    -6.800  
+92 5 2 48744.00 I  -.135028  .000302   .232420  .000382  I -.4412846  .0000122  2.4352 0.0090  I    -7.501     .639    -6.120     .151  -.135400   .231100  -.4413800    -7.500    -6.900  
+92 5 3 48745.00 I  -.137123  .000289   .234572  .000262  I -.4436273  .0000122  2.2509 0.0080  I    -7.542     .408    -5.969     .131  -.137200   .233300  -.4437200    -7.700    -7.000  
+92 5 4 48746.00 I  -.139228  .000289   .236665  .000262  I -.4457947  .0000103  2.0915 0.0085  I    -7.620     .392    -5.988     .130  -.138800   .235700  -.4458900    -7.800    -7.000  
+92 5 5 48747.00 I  -.141185  .000285   .238758  .000302  I -.4478320  .0000119  1.9970 0.0078  I    -7.679     .353    -6.229     .130  -.140500   .238100  -.4479500    -7.800    -7.100  
+92 5 6 48748.00 I  -.142849  .000285   .240919  .000302  I -.4498196  .0000118  1.9950 0.0122  I    -7.682     .349    -6.579     .109  -.142000   .240500  -.4499600    -7.900    -7.100  
+92 5 7 48749.00 I  -.144143  .000285   .243238  .000302  I -.4518569  .0000214  2.0977 0.0142  I    -7.567     .349    -6.751     .109  -.143500   .243000  -.4520300    -7.900    -7.000  
+92 5 8 48750.00 I  -.145138  .000283   .245766  .000257  I -.4540441  .0000258  2.2879 0.0179  I    -7.420     .355    -6.728     .104  -.144900   .245500  -.4542500    -7.900    -7.000  
+92 5 9 48751.00 I  -.145941  .000387   .248520  .000284  I -.4564424  .0000287  2.5074 0.0176  I    -7.278     .616    -6.665     .298  -.146200   .248000  -.4566700    -7.900    -6.900  
+92 510 48752.00 I  -.146679  .000318   .251420  .000297  I -.4590478  .0000240  2.6935 0.0188  I    -7.084     .717    -6.613     .298  -.147400   .250600  -.4592700    -7.900    -6.900  
+92 511 48753.00 I  -.147478  .000283   .254362  .000232  I -.4618024  .0000244  2.7985 0.0173  I    -6.797     .681    -6.520     .298  -.148400   .253100  -.4620200    -7.900    -6.800  
+92 512 48754.00 I  -.148460  .000345   .257247  .000198  I -.4646084  .0000249  2.7943 0.0162  I    -6.485     .778    -6.319     .298  -.149400   .255700  -.4648100    -7.800    -6.700  
+92 513 48755.00 I  -.149655  .000371   .259981  .000224  I -.4673633  .0000212  2.7070 0.0156  I    -6.393     .658    -6.038     .112  -.150200   .258200  -.4675800    -7.700    -6.700  
+92 514 48756.00 I  -.150888  .000384   .262487  .000233  I -.4700007  .0000189  2.5547 0.0126  I    -6.689     .628    -5.780     .106  -.151000   .260700  -.4702000    -7.700    -6.700  
+92 515 48757.00 I  -.151944  .000332   .264796  .000219  I -.4724541  .0000135  2.3465 0.0112  I    -7.140     .482    -5.779     .135  -.151600   .263100  -.4726300    -7.600    -6.600  
+92 516 48758.00 I  -.152674  .000286   .266971  .000205  I -.4746929  .0000122  2.1360 0.0105  I    -7.495     .377    -6.172     .125  -.152200   .265600  -.4748600    -7.600    -6.600  
+92 517 48759.00 I  -.153100  .000363   .269090  .000249  I -.4767418  .0000162  1.9727 0.0109  I    -7.641     .284    -6.650     .138  -.152800   .268000  -.4769000    -7.700    -6.600  
+92 518 48760.00 I  -.153324  .000371   .271238  .000247  I -.4786626  .0000180  1.8823 0.0124  I    -7.555     .284    -6.759     .138  -.153300   .270400  -.4788200    -7.700    -6.600  
+92 519 48761.00 I  -.153492  .000278   .273491  .000426  I -.4805333  .0000189  1.8725 0.0129  I    -7.372     .664    -6.486     .109  -.153700   .272800  -.4806900    -7.900    -6.700  
+92 520 48762.00 I  -.153702  .000230   .275896  .000335  I -.4824287  .0000186  1.9261 0.0133  I    -7.283     .699    -6.167     .159  -.154200   .275200  -.4825800    -8.100    -6.700  
+92 521 48763.00 I  -.153937  .000211   .278419  .000325  I -.4843968  .0000186  2.0138 0.0142  I    -7.418     .683    -6.020     .137  -.154600   .277600  -.4845400    -8.400    -6.700  
+92 522 48764.00 I  -.154207  .000172   .281007  .000357  I -.4864569  .0000214  2.1033 0.0135  I    -7.812     .798    -6.119     .157  -.155000   .280000  -.4865900    -8.700    -6.700  
+92 523 48765.00 I  -.154584  .000204   .283623  .000449  I -.4886033  .0000196  2.1926 0.0144  I    -8.062     .723    -6.315     .144  -.155400   .282400  -.4887500    -8.900    -6.700  
+92 524 48766.00 I  -.155104  .000204   .286252  .000449  I -.4908421  .0000194  2.2821 0.0119  I    -8.052     .723    -6.411     .144  -.155900   .284700  -.4910000    -9.100    -6.700  
+92 525 48767.00 I  -.155760  .000183   .288822  .000442  I -.4931589  .0000135  2.3460 0.0124  I    -7.984     .568    -6.373     .154  -.156300   .287100  -.4933200    -9.400    -6.700  
+92 526 48768.00 I  -.156535  .000364   .291241  .000355  I -.4955207  .0000156  2.3696 0.0110  I    -8.160     .448    -6.321     .298  -.156600   .289500  -.4956700    -9.500    -6.700  
+92 527 48769.00 I  -.157366  .000389   .293461  .000460  I -.4978772  .0000174  2.3304 0.0107  I    -8.719     .388    -6.393     .101  -.157000   .291800  -.4980000    -9.700    -6.700  
+92 528 48770.00 I  -.158048  .000384   .295568  .000530  I -.5001556  .0000146  2.2136 0.0117  I    -9.404     .333    -6.533     .141  -.157300   .294200  -.5002600    -9.800    -6.700  
+92 529 48771.00 I  -.158364  .000387   .297671  .000451  I -.5022890  .0000155  2.0504 0.0102  I    -9.853     .308    -6.541     .145  -.157500   .296500  -.5023900    -9.900    -6.700  
+92 530 48772.00 I  -.158224  .000403   .299872  .000431  I -.5042519  .0000143  1.8735 0.0108  I   -10.001     .318    -6.260     .167  -.157600   .298900  -.5043500    -9.900    -6.600  
+92 531 48773.00 I  -.157794  .000380   .302214  .000367  I -.5060354  .0000151  1.6949 0.0108  I   -10.019     .302    -5.954     .168  -.157700   .301200  -.5061400    -9.900    -6.600  
+92 6 1 48774.00 I  -.157251  .000377   .304723  .000406  I -.5076563  .0000163  1.5601 0.0111  I   -10.041     .293    -5.989     .163  -.157600   .303500  -.5077700   -10.300    -6.900  
+92 6 2 48775.00 I  -.156693  .000352   .307325  .000450  I -.5091858  .0000164  1.5159 0.0117  I    -9.928     .316    -6.266     .175  -.157400   .306000  -.5093000    -9.600    -6.800  
+92 6 3 48776.00 I  -.156213  .000370   .309905  .000462  I -.5107243  .0000167  1.5803 0.0126  I    -9.536     .383    -6.524     .152  -.157200   .308800  -.5108600    -9.200    -6.700  
+92 6 4 48777.00 I  -.155865  .000419   .312371  .000384  I -.5123786  .0000192  1.7411 0.0138  I    -9.196     .354    -6.637     .158  -.156900   .311500  -.5125300    -8.900    -6.500  
+92 6 5 48778.00 I  -.155629  .000398   .314694  .000394  I -.5142194  .0000220  1.9404 0.0153  I    -9.147     .367    -6.518     .106  -.156600   .314100  -.5143800    -8.700    -6.400  
+92 6 6 48779.00 I  -.155420  .000354   .316894  .000381  I -.5162500  .0000238  2.1114 0.0246  I    -9.249     .358    -6.320     .298  -.156300   .316300  -.5164300    -8.700    -6.200  
+92 6 7 48780.00 I  -.155182  .000412   .319021  .000533  I -.5184166  .0000440  2.2054 0.0263  I    -9.325     .363    -6.156     .107  -.156000   .318300  -.5186000    -8.900    -6.000  
+92 6 8 48781.00 I  -.154897  .000421   .321135  .000431  I -.5206263  .0000470  2.1957 0.0319  I    -9.268     .363    -6.017     .107  -.155500   .320200  -.5208200    -9.300    -6.000  
+92 6 9 48782.00 I  -.154597  .000386   .323300  .000289  I -.5227758  .0000463  2.0892 0.0320  I    -9.130     .234    -5.843     .125  -.154800   .322200  -.5229400    -9.800    -6.000  
+92 610 48783.00 I  -.154299  .000257   .325574  .000366  I -.5247841  .0000435  1.9209 0.0285  I    -9.122     .234    -5.605     .125  -.154200   .324500  -.5249100   -10.200    -6.100  
+92 611 48784.00 I  -.153976  .000226   .327985  .000404  I -.5266096  .0000331  1.7287 0.0292  I    -9.404     .225    -5.387     .113  -.153700   .327100  -.5266900   -10.700    -6.300  
+92 612 48785.00 I  -.153631  .000235   .330557  .000464  I -.5282452  .0000389  1.5475 0.0178  I    -9.962     .473    -5.328     .289  -.153500   .330000  -.5282800   -11.000    -6.600  
+92 613 48786.00 I  -.153301  .000288   .333315  .000424  I -.5297193  .0000130  1.4102 0.0206  I   -10.577     .701    -5.546     .238  -.153400   .333000  -.5297300   -11.100    -6.900  
+92 614 48787.00 I  -.153029  .000219   .336272  .000432  I -.5310856  .0000134  1.3327 0.0098  I   -11.015     .701    -6.052     .238  -.153200   .336000  -.5311000   -10.900    -7.100  
+92 615 48788.00 I  -.152876  .000219   .339376  .000432  I -.5324041  .0000147  1.3134 0.0105  I   -11.238     .774    -6.525     .222  -.153000   .339100  -.5324500   -10.600    -7.300  
+92 616 48789.00 I  -.152878  .000246   .342509  .000504  I -.5337292  .0000162  1.3445 0.0124  I   -11.461     .774    -6.625     .222  -.152900   .342000  -.5338200   -10.300    -7.300  
+92 617 48790.00 I  -.153016  .000639   .345557  .000575  I -.5351059  .0000200  1.4141 0.0131  I   -11.671    1.055    -6.476     .250  -.153100   .344800  -.5352300   -10.100    -7.200  
+92 618 48791.00 I  -.153169  .000729   .348440  .000574  I -.5365664  .0000205  1.5105 0.0163  I   -11.576    1.079    -6.302     .312  -.153300   .347400  -.5367200   -10.000    -7.000  
+92 619 48792.00 I  -.153196  .000753   .351097  .000566  I -.5381314  .0000257  1.6202 0.0176  I   -11.402    1.167    -6.297     .423  -.153400   .349900  -.5383100   -10.200    -6.800  
+92 620 48793.00 I  -.152947  .000761   .353491  .000584  I -.5398079  .0000285  1.7333 0.0186  I   -11.581    1.023    -6.449     .356  -.153300   .352200  -.5400000   -10.500    -6.500  
+92 621 48794.00 I  -.152328  .000696   .355688  .000419  I -.5415918  .0000268  1.8280 0.0196  I   -11.896    1.006    -6.230     .382  -.153000   .354400  -.5417800   -11.100    -6.300  
+92 622 48795.00 I  -.151443  .000748   .357814  .000401  I -.5434488  .0000270  1.8774 0.0176  I   -11.841     .876    -5.916     .339  -.152200   .356600  -.5436200   -11.800    -6.100  
+92 623 48796.00 I  -.150489  .000616   .359987  .000336  I -.5453287  .0000229  1.8731 0.0167  I   -11.617     .639    -5.875     .372  -.151200   .358800  -.5454800   -12.600    -6.000  
+92 624 48797.00 I  -.149658  .000587   .362268  .000327  I -.5471758  .0000196  1.8111 0.0148  I   -11.860     .722    -6.016     .259  -.150200   .361000  -.5473200   -13.400    -6.000  
+92 625 48798.00 I  -.148926  .000548   .364635  .000317  I -.5489337  .0000187  1.6975 0.0145  I   -12.582     .552    -6.266     .170  -.149200   .363400  -.5490800   -14.200    -6.100  
+92 626 48799.00 I  -.148103  .000580   .367069  .000288  I -.5505592  .0000214  1.5491 0.0150  I   -13.435     .564    -6.367     .199  -.148000   .365800  -.5507200   -14.700    -6.300  
+92 627 48800.00 I  -.147055  .000584   .369542  .000262  I -.5520272  .0000235  1.3867 0.0149  I   -14.003     .645    -6.152     .157  -.146800   .368400  -.5521800   -14.900    -6.400  
+92 628 48801.00 I  -.145800  .000433   .372031  .000236  I -.5533401  .0000208  1.2467 0.0157  I   -14.186     .756    -5.812     .171  -.145700   .371000  -.5535000   -14.700    -6.600  
+92 629 48802.00 I  -.144519  .000421   .374531  .000214  I -.5545415  .0000208  1.1695 0.0152  I   -14.124     .692    -5.677     .163  -.144700   .373500  -.5547000   -14.500    -6.700  
+92 630 48803.00 I  -.143342  .000393   .377023  .000216  I -.5557122  .0000223  1.1918 0.0152  I   -13.968     .607    -5.833     .298  -.143600   .375900  -.5558700   -14.300    -6.800  
+92 7 1 48804.00 I  -.142256  .000389   .379477  .000214  I  .4430472  .0000222  1.2973 0.0162  I   -13.824     .607    -6.085     .298  -.142500   .378200   .4429100   -13.900    -6.900  
+92 7 2 48805.00 I  -.141189  .000376   .381860  .000187  I  .4416753  .0000236  1.4565 0.0147  I   -13.758     .607    -6.227     .298  -.141300   .380500   .4415300   -13.600    -7.000  
+92 7 3 48806.00 I  -.140045  .000301   .384172  .000200  I  .4401262  .0000194  1.6397 0.0159  I   -13.855     .436    -6.156     .102  -.140200   .382700   .4399700   -13.900    -7.000  
+92 7 4 48807.00 I  -.138748  .000262   .386425  .000242  I  .4384135  .0000214  1.7702 0.0195  I   -14.145     .432    -5.945     .159  -.139200   .384900   .4382400   -14.300    -6.800  
+92 7 5 48808.00 I  -.137348  .000411   .388614  .000349  I  .4366213  .0000339  1.7941 0.0225  I   -14.556     .433    -5.731     .154  -.138000   .387100   .4364400   -14.800    -6.500  
+92 7 6 48809.00 I  -.135865  .000387   .390743  .000267  I  .4348628  .0000396  1.7055 0.0251  I   -14.958     .434    -5.560     .166  -.136700   .389400   .4346700   -15.400    -6.400  
+92 7 7 48810.00 I  -.134255  .000355   .392840  .000256  I  .4332363  .0000371  1.5389 0.0262  I   -15.276     .399    -5.493     .174  -.135000   .391500   .4330500   -16.000    -6.300  
+92 7 8 48811.00 I  -.132501  .000343   .394965  .000255  I  .4317956  .0000343  1.3405 0.0254  I   -15.475     .356    -5.591     .152  -.133200   .393700   .4316200   -16.400    -6.300  
+92 7 9 48812.00 I  -.130806  .000342   .397220  .000241  I  .4305555  .0000346  1.1414 0.0250  I   -15.508     .356    -5.743     .152  -.131400   .396100   .4304000   -16.600    -6.200  
+92 710 48813.00 I  -.129424  .000359   .399651  .000284  I  .4294993  .0000363  0.9827 0.0208  I   -15.635     .329    -5.839     .120  -.129900   .398800   .4293600   -16.800    -6.200  
+92 711 48814.00 I  -.128330  .000418   .402171  .000254  I  .4285694  .0000232  0.8860 0.0216  I   -15.918     .318    -5.844     .166  -.128700   .401700   .4284400   -16.700    -6.200  
+92 712 48815.00 I  -.127463  .000428   .404642  .000263  I  .4277093  .0000236  0.8432 0.0147  I   -16.200     .237    -5.827     .175  -.128000   .404500   .4275900   -16.400    -6.200  
+92 713 48816.00 I  -.126732  .000409   .406920  .000243  I  .4268671  .0000182  0.8482 0.0145  I   -16.348     .189    -5.829     .168  -.127500   .406800   .4267600   -16.200    -6.200  
+92 714 48817.00 I  -.126065  .000423   .408912  .000245  I  .4259970  .0000169  0.9010 0.0122  I   -16.372     .169    -5.812     .202  -.127000   .408600   .4258900   -16.000    -6.200  
+92 715 48818.00 I  -.125322  .000427   .410633  .000287  I  .4250476  .0000163  1.0063 0.0117  I   -16.368     .289    -5.720     .239  -.126200   .410100   .4249200   -16.200    -6.200  
+92 716 48819.00 I  -.124191  .000421   .412277  .000272  I  .4239735  .0000161  1.1444 0.0123  I   -16.389     .268    -5.603     .221  -.124900   .411600   .4238400   -16.500    -6.300  
+92 717 48820.00 I  -.122472  .000330   .414066  .000295  I  .4227595  .0000185  1.2806 0.0102  I   -16.483     .300    -5.600     .215  -.123100   .413300   .4226200   -17.000    -6.300  
+92 718 48821.00 I  -.120237  .000226   .416097  .000278  I  .4214188  .0000124  1.3974 0.0106  I   -16.639     .263    -5.650     .206  -.120700   .415400   .4212700   -17.500    -6.200  
+92 719 48822.00 I  -.117661  .000206   .418425  .000237  I  .4199735  .0000104  1.4877 0.0077  I   -16.815     .261    -5.698     .202  -.118100   .417800   .4198100   -18.200    -6.200  
+92 720 48823.00 I  -.114962  .000173   .420939  .000237  I  .4184560  .0000092  1.5402 0.0068  I   -16.864     .258    -5.707     .202  -.115400   .420400   .4182900   -19.000    -6.200  
+92 721 48824.00 I  -.112339  .000197   .423477  .000249  I  .4169068  .0000087  1.5515 0.0063  I   -16.785     .178    -5.748     .142  -.112800   .422900   .4167400   -19.600    -6.200  
+92 722 48825.00 I  -.110008  .000206   .425890  .000194  I  .4153668  .0000086  1.5213 0.0057  I   -16.887     .473    -5.896     .186  -.110400   .425200   .4152100   -20.100    -6.200  
+92 723 48826.00 I  -.108033  .000211   .428109  .000198  I  .4138765  .0000073  1.4542 0.0056  I   -17.380     .464    -6.042     .175  -.108200   .427400   .4137200   -20.500    -6.200  
+92 724 48827.00 I  -.106077  .000218   .430216  .000178  I  .4124657  .0000073  1.3653 0.0053  I   -18.060     .527    -6.100     .158  -.106000   .429500   .4122900   -20.600    -6.300  
+92 725 48828.00 I  -.103972  .000217   .432230  .000185  I  .4111448  .0000076  1.2797 0.0066  I   -18.518     .502    -6.026     .135  -.104000   .431500   .4109600   -20.400    -6.300  
+92 726 48829.00 I  -.101805  .000263   .434165  .000173  I  .4098930  .0000111  1.2340 0.0062  I   -18.481     .487    -5.905     .127  -.102100   .433400   .4097000   -20.000    -6.400  
+92 727 48830.00 I  -.099751  .000271   .436034  .000263  I  .4086562  .0000097  1.2501 0.0074  I   -18.074     .509    -5.913     .133  -.100000   .435300   .4084800   -19.600    -6.400  
+92 728 48831.00 I  -.097900  .000263   .437831  .000254  I  .4073690  .0000097  1.3376 0.0065  I   -17.673     .305    -6.096     .298  -.098000   .437200   .4072100   -19.100    -6.400  
+92 729 48832.00 I  -.096176  .000241   .439589  .000222  I  .4059513  .0000087  1.5142 0.0064  I   -17.470     .281    -6.281     .298  -.096100   .439000   .4058000   -18.600    -6.400  
+92 730 48833.00 I  -.094340  .000238   .441446  .000225  I  .4043197  .0000083  1.7533 0.0057  I   -17.567     .224    -6.235     .298  -.094300   .440800   .4041700   -18.400    -6.200  
+92 731 48834.00 I  -.092328  .000233   .443549  .000221  I  .4024494  .0000075  1.9781 0.0078  I   -17.998     .280    -5.994     .108  -.092500   .442700   .4023000   -18.300    -6.100  
+92 8 1 48835.00 I  -.090223  .000324   .445839  .000240  I  .4003910  .0000131  2.1204 0.0073  I   -18.641     .288    -5.745     .137  -.090400   .444900   .4002500   -18.400    -5.900  
+92 8 2 48836.00 I  -.088082  .000285   .448188  .000237  I  .3982501  .0000125  2.1384 0.0091  I   -19.285     .265    -5.597     .135  -.088300   .447300   .3981000   -18.700    -5.700  
+92 8 3 48837.00 I  -.085895  .000284   .450460  .000166  I  .3961543  .0000127  2.0362 0.0089  I   -19.786     .283    -5.452     .149  -.086200   .449700   .3959900   -19.100    -5.600  
+92 8 4 48838.00 I  -.083755  .000283   .452563  .000180  I  .3942075  .0000127  1.8445 0.0089  I   -20.107     .260    -5.315     .128  -.084100   .451900   .3940300   -19.400    -5.500  
+92 8 5 48839.00 I  -.081828  .000278   .454576  .000184  I  .3924681  .0000125  1.6442 0.0093  I   -20.223     .257    -5.378     .123  -.082200   .454100   .3922700   -19.900    -5.500  
+92 8 6 48840.00 I  -.080003  .000270   .456571  .000182  I  .3909099  .0000135  1.4714 0.0079  I   -20.052     .173    -5.604     .124  -.080400   .456100   .3907400   -20.200    -5.700  
+92 8 7 48841.00 I  -.078139  .000178   .458634  .000144  I  .3895165  .0000097  1.3248 0.0089  I   -19.775     .204    -5.851     .298  -.078500   .457900   .3893600   -20.500    -5.800  
+92 8 8 48842.00 I  -.076208  .000201   .460875  .000172  I  .3882434  .0000115  1.2287 0.0082  I   -19.707     .269    -6.000     .163  -.076500   .459800   .3881300   -20.400    -5.800  
+92 8 9 48843.00 I  -.074290  .000207   .463332  .000186  I  .3870412  .0000131  1.1862 0.0097  I   -19.894     .304    -5.974     .157  -.074400   .462000   .3869300   -20.300    -5.900  
+92 810 48844.00 I  -.072315  .000219   .465924  .000210  I  .3858530  .0000157  1.1978 0.0104  I   -20.048     .360    -5.886     .159  -.072500   .464700   .3857400   -19.800    -6.000  
+92 811 48845.00 I  -.070241  .000222   .468541  .000207  I  .3846145  .0000161  1.3029 0.0119  I   -19.997     .414    -5.892     .171  -.070700   .467200   .3844400   -19.700    -5.900  
+92 812 48846.00 I  -.068261  .000235   .471062  .000240  I  .3832183  .0000178  1.4949 0.0121  I   -19.901     .409    -5.885     .188  -.068900   .469700   .3830000   -19.800    -5.700  
+92 813 48847.00 I  -.066397  .000236   .473325  .000232  I  .3816262  .0000181  1.6825 0.0134  I   -19.828     .401    -5.694     .199  -.067100   .471800   .3814100   -20.100    -5.700  
+92 814 48848.00 I  -.064466  .000200   .475307  .000290  I  .3798709  .0000201  1.8172 0.0120  I   -19.995     .411    -5.393     .158  -.065100   .473800   .3796700   -20.500    -5.700  
+92 815 48849.00 I  -.062333  .000208   .477088  .000358  I  .3780113  .0000157  1.8934 0.0129  I   -20.418     .627    -5.267     .159  -.063000   .475900   .3778100   -21.100    -5.600  
+92 816 48850.00 I  -.060005  .000234   .478776  .000329  I  .3761010  .0000162  1.9188 0.0121  I   -20.925     .646    -5.393     .172  -.060700   .477800   .3759100   -21.700    -5.700  
+92 817 48851.00 I  -.057474  .000241   .480454  .000313  I  .3741898  .0000185  1.8958 0.0115  I   -21.248     .609    -5.604     .167  -.058100   .479700   .3740100   -22.200    -5.900  
+92 818 48852.00 I  -.054730  .000224   .482120  .000313  I  .3723218  .0000163  1.8354 0.0118  I   -21.189     .757    -5.773     .123  -.055400   .481500   .3721400   -22.600    -6.100  
+92 819 48853.00 I  -.051810  .000200   .483699  .000302  I  .3705234  .0000148  1.7616 0.0134  I   -20.899     .859    -5.909     .173  -.052500   .483100   .3703400   -22.700    -6.200  
+92 820 48854.00 I  -.048783  .000190   .485162  .000241  I  .3687999  .0000213  1.6840 0.0162  I   -20.838    1.089    -5.998     .160  -.049300   .484600   .3686300   -22.400    -6.400  
+92 821 48855.00 I  -.045664  .000274   .486491  .000200  I  .3671538  .0000289  1.6114 0.0190  I   -21.209    1.131    -6.045     .157  -.046100   .485900   .3669900   -21.900    -6.600  
+92 822 48856.00 I  -.042499  .000354   .487683  .000395  I  .3655657  .0000314  1.5732 0.0214  I   -21.780     .952    -6.043     .173  -.043100   .487100   .3654300   -21.300    -6.700  
+92 823 48857.00 I  -.039354  .000484   .488789  .000510  I  .3639866  .0000316  1.5976 0.0204  I   -21.812     .951    -6.065     .175  -.040100   .488200   .3638700   -20.800    -6.800  
+92 824 48858.00 I  -.036252  .000463   .489888  .000498  I  .3623445  .0000262  1.7001 0.0207  I   -21.320     .951    -6.229     .175  -.037200   .489200   .3622400   -20.300    -6.800  
+92 825 48859.00 I  -.033146  .000462   .491085  .000495  I  .3605595  .0000268  1.8833 0.0165  I   -20.771     .856    -6.454     .149  -.034200   .490300   .3604500   -20.000    -6.700  
+92 826 48860.00 I  -.030036  .000388   .492464  .000551  I  .3585519  .0000199  2.1444 0.0161  I   -20.499     .446    -6.459     .176  -.031000   .491600   .3584100   -20.000    -6.600  
+92 827 48861.00 I  -.026957  .000302   .493979  .000507  I  .3562597  .0000179  2.4385 0.0121  I   -20.712     .298    -6.126     .208  -.027700   .493200   .3560900   -20.300    -6.500  
+92 828 48862.00 I  -.023903  .000203   .495593  .000344  I  .3536961  .0000136  2.6692 0.0109  I   -21.237     .416    -5.714     .197  -.024400   .494900   .3535100   -20.700    -6.200  
+92 829 48863.00 I  -.020858  .000309   .497302  .000425  I  .3509702  .0000124  2.7534 0.0093  I   -21.607     .488    -5.375     .185  -.021300   .496700   .3507800   -21.400    -6.100  
+92 830 48864.00 I  -.017903  .000323   .499041  .000391  I  .3482488  .0000127  2.6592 0.0091  I   -21.624     .488    -5.364     .185  -.018300   .498500   .3480800   -22.100    -6.000  
+92 831 48865.00 I  -.015192  .000345   .500593  .000399  I  .3457035  .0000134  2.4097 0.0093  I   -21.714     .488    -5.457     .185  -.015600   .499900   .3455300   -22.700    -6.000  
+92 9 1 48866.00 I  -.012886  .000353   .501710  .000449  I  .3434557  .0000137  2.0811 0.0098  I   -22.079     .499    -5.363     .177  -.013200   .500900   .3432800   -23.200    -6.100  
+92 9 2 48867.00 I  -.010966  .000387   .502220  .000438  I  .3415326  .0000142  1.7786 0.0105  I   -22.354     .454    -5.245     .137  -.011000   .501200   .3413000   -23.300    -6.200  
+92 9 3 48868.00 I  -.008939  .000416   .502278  .000473  I  .3398721  .0000160  1.5552 0.0119  I   -22.168     .386    -5.472     .144  -.008900   .501100   .3396100   -23.200    -6.400  
+92 9 4 48869.00 I  -.006749  .000354   .502235  .000546  I  .3383956  .0000191  1.4117 0.0108  I   -21.532     .119    -5.923     .167  -.006700   .500900   .3381600   -23.000    -6.400  
+92 9 5 48870.00 I  -.004454  .000335   .502390  .000385  I  .3370185  .0000146  1.3589 0.0127  I   -20.903     .650    -6.154     .167  -.004100   .501200   .3368300   -22.700    -6.500  
+92 9 6 48871.00 I  -.002028  .000303   .502831  .000447  I  .3356478  .0000168  1.3963 0.0111  I   -20.689     .721    -6.054     .168  -.001500   .501600   .3355000   -22.000    -6.300  
+92 9 7 48872.00 I   .000513  .000303   .503509  .000390  I  .3342017  .0000167  1.5064 0.0115  I   -20.853     .686    -5.840     .161   .001000   .502500   .3340600   -21.400    -6.100  
+92 9 8 48873.00 I   .003059  .000287   .504279  .000318  I  .3326178  .0000158  1.6681 0.0117  I   -21.168     .884    -5.726     .155   .003300   .503500   .3324700   -20.900    -5.800  
+92 9 9 48874.00 I   .005476  .000276   .504990  .000274  I  .3308625  .0000163  1.8389 0.0112  I   -21.529     .686    -5.696     .133   .005600   .504400   .3307100   -20.800    -5.600  
+92 910 48875.00 I   .007814  .000433   .505575  .000346  I  .3289492  .0000158  1.9822 0.0113  I   -21.797     .686    -5.542     .133   .008000   .505100   .3287900   -20.900    -5.600  
+92 911 48876.00 I   .010098  .000561   .506007  .000397  I  .3269116  .0000157  2.0848 0.0093  I   -21.955     .308    -5.319     .103   .010500   .505500   .3267400   -21.200    -5.500  
+92 912 48877.00 I   .012363  .000451   .506266  .000560  I  .3247966  .0000100  2.1362 0.0089  I   -22.048     .272    -5.271     .298   .012800   .505700   .3246300   -21.600    -5.600  
+92 913 48878.00 I   .014709  .000446   .506388  .000563  I  .3226585  .0000084  2.1298 0.0065  I   -22.091     .166    -5.423     .298   .015100   .505700   .3225000   -22.200    -5.700  
+92 914 48879.00 I   .017122  .000428   .506485  .000554  I  .3205567  .0000083  2.0643 0.0050  I   -22.054     .275    -5.592     .298   .017300   .505700   .3204100   -22.500    -5.800  
+92 915 48880.00 I   .019557  .000390   .506712  .000547  I  .3185458  .0000056  1.9510 0.0055  I   -21.857     .359    -5.597     .105   .019400   .505700   .3184100   -22.900    -6.000  
+92 916 48881.00 I   .022043  .000267   .507108  .000505  I  .3166597  .0000072  1.8225 0.0048  I   -21.544     .359    -5.438     .105   .021800   .506100   .3165100   -22.800    -6.300  
+92 917 48882.00 I   .024591  .000160   .507480  .000515  I  .3148939  .0000078  1.7147 0.0058  I   -21.401     .359    -5.292     .105   .024400   .506500   .3147400   -22.500    -6.300  
+92 918 48883.00 I   .027139  .000188   .507675  .000351  I  .3132183  .0000090  1.6431 0.0069  I   -21.524     .416    -5.297     .128   .027200   .506800   .3130700   -22.200    -6.400  
+92 919 48884.00 I   .029623  .000331   .507617  .000414  I  .3115916  .0000114  1.6199 0.0072  I   -21.760     .463    -5.428     .104   .029900   .506900   .3114600   -21.800    -6.500  
+92 920 48885.00 I   .032003  .000308   .507391  .000330  I  .3099566  .0000113  1.6625 0.0078  I   -21.891     .450    -5.629     .113   .032400   .506700   .3098500   -21.300    -6.500  
+92 921 48886.00 I   .034238  .000321   .507135  .000336  I  .3082435  .0000107  1.7746 0.0079  I   -21.759     .732    -5.859     .119   .034600   .506500   .3081500   -21.000    -6.500  
+92 922 48887.00 I   .036273  .000345   .507005  .000324  I  .3063870  .0000111  1.9480 0.0077  I   -21.433     .628    -6.023     .120   .036500   .506300   .3062800   -20.800    -6.300  
+92 923 48888.00 I   .038147  .000346   .507048  .000314  I  .3043250  .0000110  2.1888 0.0078  I   -21.182     .628    -5.954     .120   .038300   .506100   .3041800   -20.700    -6.200  
+92 924 48889.00 I   .040098  .000340   .507093  .000325  I  .3020052  .0000110  2.4420 0.0073  I   -21.242     .628    -5.550     .120   .040200   .506100   .3018300   -20.800    -6.000  
+92 925 48890.00 I   .042174  .000265   .507081  .000320  I  .2994677  .0000096  2.6150 0.0070  I   -21.562     .667    -5.104     .148   .042200   .506100   .2992800   -21.000    -5.800  
+92 926 48891.00 I   .044339  .000247   .506983  .000330  I  .2968178  .0000087  2.6602 0.0062  I   -21.819     .558    -4.999     .315   .044500   .506200   .2966300   -21.300    -5.700  
+92 927 48892.00 I   .046531  .000269   .506715  .000420  I  .2941925  .0000078  2.5700 0.0062  I   -21.780     .288    -5.210     .357   .046600   .505900   .2940000   -21.600    -5.600  
+92 928 48893.00 I   .048707  .000269   .506217  .000405  I  .2917083  .0000088  2.3885 0.0062  I   -21.641     .219    -5.436     .490   .048700   .505500   .2915200   -21.800    -5.700  
+92 929 48894.00 I   .050938  .000271   .505528  .000409  I  .2894253  .0000096  2.1777 0.0065  I   -21.721     .155    -5.411     .397   .050800   .504800   .2892500   -21.900    -5.700  
+92 930 48895.00 I   .053292  .000280   .504791  .000387  I  .2873458  .0000095  1.9882 0.0064  I   -21.956     .155    -5.178     .397   .053000   .504000   .2872000   -21.800    -5.700  
+9210 1 48896.00 I   .055692  .000242   .504145  .000345  I  .2854308  .0000086  1.8530 0.0070  I   -21.949     .155    -5.002     .397   .055400   .503200   .2853100   -21.500    -5.800  
+9210 2 48897.00 I   .058118  .000308   .503680  .000361  I  .2836186  .0000104  1.7815 0.0060  I   -21.509     .791    -4.989     .275   .057800   .502500   .2835100   -21.100    -5.800  
+9210 3 48898.00 I   .060608  .000308   .503410  .000368  I  .2818446  .0000085  1.7795 0.0063  I   -20.922     .165    -5.033     .210   .060400   .502300   .2817300   -20.600    -5.700  
+9210 4 48899.00 I   .063234  .000303   .503229  .000389  I  .2800370  .0000072  1.8454 0.0064  I   -20.563     .165    -5.014     .210   .063100   .502100   .2799300   -20.100    -5.700  
+9210 5 48900.00 I   .066052  .000305   .503051  .000382  I  .2781375  .0000096  1.9602 0.0058  I   -20.472     .233    -4.978     .113   .066200   .501900   .2780900   -20.000    -5.600  
+9210 6 48901.00 I   .069055  .000326   .502853  .000348  I  .2761060  .0000090  2.1067 0.0068  I   -20.475     .202    -5.009     .208   .069200   .501900   .2760600   -19.900    -5.500  
+9210 7 48902.00 I   .072135  .000340   .502609  .000291  I  .2739224  .0000096  2.2581 0.0067  I   -20.520     .202    -5.090     .208   .072300   .501800   .2738600   -20.200    -5.300  
+9210 8 48903.00 I   .075164  .000329   .502249  .000357  I  .2715976  .0000099  2.3859 0.0082  I   -20.652     .202    -5.160     .208   .075300   .501600   .2715000   -20.600    -5.200  
+9210 9 48904.00 I   .078011  .000336   .501719  .000414  I  .2691643  .0000133  2.4727 0.0065  I   -20.838     .165    -5.226     .272   .078100   .501100   .2690300   -21.200    -5.100  
+921010 48905.00 I   .080592  .000333   .500975  .000368  I  .2666714  .0000085  2.5021 0.0071  I   -20.948     .184    -5.288     .217   .080600   .500400   .2665000   -21.700    -5.100  
+921011 48906.00 I   .082938  .000227   .500005  .000273  I  .2641812  .0000051  2.4682 0.0050  I   -20.956     .184    -5.317     .217   .082800   .499300   .2640000   -21.900    -5.100  
+921012 48907.00 I   .085182  .000227   .498864  .000273  I  .2617535  .0000052  2.3789 0.0034  I   -20.915     .213    -5.241     .121   .085100   .498100   .2615900   -22.000    -5.200  
+921013 48908.00 I   .087534  .000215   .497713  .000255  I  .2594361  .0000045  2.2516 0.0035  I   -20.796     .205    -5.015     .298   .087500   .496700   .2592900   -21.900    -5.200  
+921014 48909.00 I   .090137  .000191   .496752  .000206  I  .2572455  .0000048  2.1387 0.0034  I   -20.515     .205    -4.702     .298   .090200   .495600   .2571100   -21.400    -5.400  
+921015 48910.00 I   .092869  .000181   .496097  .000161  I  .2551454  .0000052  2.0656 0.0040  I   -20.151     .205    -4.438     .298   .093100   .495000   .2550400   -20.700    -5.500  
+921016 48911.00 I   .095524  .000153   .495655  .000176  I  .2531016  .0000064  2.0304 0.0045  I   -19.851     .208    -4.337     .298   .095800   .494800   .2530300   -19.800    -5.500  
+921017 48912.00 I   .097959  .000186   .495300  .000184  I  .2510598  .0000074  2.0696 0.0062  I   -19.728     .293    -4.431     .153   .098300   .494700   .2509900   -19.200    -5.500  
+921018 48913.00 I   .100177  .000242   .494912  .000177  I  .2489308  .0000106  2.2037 0.0065  I   -19.704     .624    -4.645     .159   .100400   .494500   .2488400   -18.600    -5.500  
+921019 48914.00 I   .102242  .000251   .494385  .000198  I  .2466266  .0000108  2.4151 0.0075  I   -19.601     .663    -4.865     .231   .102200   .493800   .2465000   -18.200    -5.400  
+921020 48915.00 I   .104231  .000250   .493641  .000242  I  .2440833  .0000105  2.6784 0.0075  I   -19.281     .763    -4.958     .223   .103900   .492900   .2439300   -18.000    -5.100  
+921021 48916.00 I   .106221  .000257   .492669  .000269  I  .2412656  .0000104  2.9543 0.0075  I   -18.761     .763    -4.843     .223   .106000   .491700   .2410900   -18.000    -4.900  
+921022 48917.00 I   .108349  .000293   .491575  .000269  I  .2381997  .0000106  3.1553 0.0085  I   -18.351     .722    -4.507     .214   .108200   .490400   .2380300   -18.200    -4.600  
+921023 48918.00 I   .110632  .000297   .490517  .000304  I  .2350047  .0000134  3.2071 0.0079  I   -18.228     .795    -4.019     .208   .110700   .489400   .2348600   -18.600    -4.400  
+921024 48919.00 I   .112984  .000304   .489593  .000324  I  .2318337  .0000118  3.1144 0.0084  I   -18.293     .601    -3.578     .228   .113300   .488500   .2317100   -18.900    -4.300  
+921025 48920.00 I   .115243  .000322   .488773  .000379  I  .2288108  .0000101  2.9169 0.0079  I   -18.350     .659    -3.468     .199   .115600   .487700   .2286900   -19.100    -4.200  
+921026 48921.00 I   .117297  .000301   .487948  .000331  I  .2260199  .0000105  2.6592 0.0071  I   -18.391     .232    -3.642     .199   .117500   .487000   .2259100   -19.200    -4.300  
+921027 48922.00 I   .119065  .000291   .486996  .000282  I  .2234917  .0000099  2.4035 0.0077  I   -18.517     .254    -3.834     .262   .119000   .486000   .2233700   -19.100    -4.400  
+921028 48923.00 I   .120544  .000258   .485856  .000302  I  .2211912  .0000113  2.2130 0.0077  I   -18.692     .270    -3.901     .283   .120200   .484800   .2210600   -18.700    -4.500  
+921029 48924.00 I   .121936  .000290   .484560  .000303  I  .2190355  .0000119  2.1131 0.0088  I   -18.711     .264    -3.915     .265   .121400   .483500   .2188900   -18.200    -4.600  
+921030 48925.00 I   .123457  .000259   .483156  .000359  I  .2169378  .0000135  2.0947 0.0081  I   -18.381     .269    -3.992     .290   .123000   .482200   .2167700   -17.700    -4.700  
+921031 48926.00 I   .125267  .000347   .481680  .000326  I  .2148240  .0000110  2.1427 0.0089  I   -17.788     .277    -4.127     .239   .125000   .480900   .2146500   -17.100    -4.700  
+9211 1 48927.00 I   .127408  .000345   .480182  .000359  I  .2126421  .0000117  2.2218 0.0086  I   -17.256     .277    -4.159     .239   .127400   .479500   .2124900   -16.600    -4.800  
+9211 2 48928.00 I   .129736  .000330   .478689  .000348  I  .2103838  .0000131  2.2909 0.0081  I   -16.939     .286    -4.125     .129   .129900   .478100   .2102600   -16.300    -4.600  
+9211 3 48929.00 I   .132018  .000301   .477293  .000348  I  .2080688  .0000113  2.3347 0.0081  I   -16.823     .479    -4.195     .197   .132200   .476700   .2079700   -16.300    -4.600  
+9211 4 48930.00 I   .134034  .000269   .476071  .000330  I  .2057129  .0000096  2.3832 0.0074  I   -16.880     .451    -4.389     .177   .134000   .475600   .2056100   -15.800    -4.600  
+9211 5 48931.00 I   .135730  .000275   .474916  .000299  I  .2032926  .0000096  2.4613 0.0068  I   -17.026     .451    -4.474     .177   .135500   .474200   .2031600   -16.200    -4.600  
+9211 6 48932.00 I   .137164  .000181   .473676  .000284  I  .2007989  .0000095  2.5136 0.0064  I   -17.230     .502    -4.389     .192   .136900   .473000   .2006600   -16.800    -4.700  
+9211 7 48933.00 I   .138539  .000217   .472270  .000266  I  .1982865  .0000085  2.5026 0.0063  I   -17.402     .481    -4.300     .216   .138100   .471500   .1981600   -17.400    -4.700  
+9211 8 48934.00 I   .140013  .000204   .470709  .000214  I  .1958095  .0000084  2.4441 0.0070  I   -17.483     .502    -4.223     .229   .139500   .470000   .1956900   -18.000    -4.800  
+9211 9 48935.00 I   .141637  .000290   .469027  .000222  I  .1934112  .0000112  2.3467 0.0081  I   -17.500     .317    -4.032     .181   .141100   .468300   .1932900   -18.500    -4.800  
+921110 48936.00 I   .143375  .000321   .467265  .000250  I  .1911216  .0000139  2.2326 0.0087  I   -17.451     .361    -3.687     .225   .142900   .466500   .1909900   -18.400    -4.700  
+921111 48937.00 I   .145215  .000299   .465487  .000244  I  .1889393  .0000133  2.1385 0.0098  I   -17.249     .423    -3.316     .259   .144900   .464700   .1887800   -18.000    -4.600  
+921112 48938.00 I   .147211  .000334   .463795  .000244  I  .1868318  .0000137  2.0828 0.0121  I   -16.860     .477    -3.215     .324   .147000   .463000   .1866800   -17.300    -4.400  
+921113 48939.00 I   .149308  .000353   .462245  .000264  I  .1847543  .0000202  2.0851 0.0104  I   -16.307     .501    -3.488     .353   .149200   .461500   .1846000   -16.700    -4.100  
+921114 48940.00 I   .151459  .000315   .460843  .000272  I  .1826347  .0000156  2.1680 0.0125  I   -15.731     .434    -4.053     .305   .151300   .460100   .1824900   -16.100    -3.900  
+921115 48941.00 I   .153688  .000336   .459540  .000290  I  .1803904  .0000146  2.3348 0.0094  I   -15.464     .468    -4.279     .328   .153500   .458900   .1802400   -15.800    -3.700  
+921116 48942.00 I   .155993  .000267   .458291  .000235  I  .1779453  .0000106  2.5612 0.0102  I   -15.578     .430    -4.006     .303   .155800   .457700   .1778000   -15.600    -3.500  
+921117 48943.00 I   .158277  .000331   .457088  .000228  I  .1752648  .0000143  2.7974 0.0085  I   -15.855     .388    -3.657     .304   .158200   .456500   .1751100   -15.600    -3.300  
+921118 48944.00 I   .160480  .000250   .455924  .000207  I  .1723679  .0000134  2.9815 0.0096  I   -16.111     .167    -3.492     .123   .160600   .455400   .1722100   -16.000    -3.300  
+921119 48945.00 I   .162663  .000270   .454751  .000216  I  .1693369  .0000128  3.0604 0.0104  I   -16.326     .161    -3.368     .114   .163000   .454200   .1691800   -16.600    -3.300  
+921120 48946.00 I   .164781  .000328   .453500  .000210  I  .1662885  .0000160  3.0152 0.0089  I   -16.531     .791    -3.183     .298   .165200   .452900   .1661400   -17.200    -3.400  
+921121 48947.00 I   .166706  .000318   .452072  .000244  I  .1633407  .0000124  2.8676 0.0099  I   -16.739     .130    -2.949     .298   .167200   .451300   .1632000   -17.300    -3.500  
+921122 48948.00 I   .168352  .000314   .450398  .000256  I  .1605728  .0000118  2.6615 0.0086  I   -16.915     .138    -2.788     .298   .168700   .449600   .1604400   -17.300    -3.700  
+921123 48949.00 I   .169592  .000324   .448510  .000255  I  .1580229  .0000120  2.4396 0.0063  I   -16.980     .138    -2.771     .298   .169600   .447800   .1578900   -17.100    -3.800  
+921124 48950.00 I   .170409  .000294   .446462  .000247  I  .1556831  .0000044  2.2491 0.0066  I   -16.881     .176    -2.821     .298   .170200   .445800   .1555500   -16.600    -4.100  
+921125 48951.00 I   .170909  .000326   .444279  .000286  I  .1535019  .0000056  2.1271 0.0038  I   -16.620     .195    -2.799     .298   .170600   .443700   .1533300   -15.900    -4.100  
+921126 48952.00 I   .171329  .000285   .441971  .000279  I  .1514019  .0000061  2.0861 0.0056  I   -16.254     .195    -2.636     .298   .170900   .441400   .1512000   -15.200    -4.100  
+921127 48953.00 I   .171871  .000348   .439582  .000265  I  .1493071  .0000097  2.1130 0.0051  I   -15.821     .791    -2.416     .298   .171400   .439000   .1490900   -14.400    -4.000  
+921128 48954.00 I   .172586  .000311   .437181  .000229  I  .1471611  .0000081  2.1845 0.0089  I   -15.352     .845    -2.292     .298   .172000   .436600   .1469400   -13.600    -3.900  
+921129 48955.00 I   .173419  .000420   .434829  .000254  I  .1449299  .0000149  2.2807 0.0085  I   -14.899     .845    -2.352     .298   .172700   .434200   .1447300   -13.000    -3.600  
+921130 48956.00 I   .174288  .000399   .432567  .000291  I  .1425977  .0000149  2.3830 0.0109  I   -14.560     .896    -2.573     .298   .173500   .432000   .1424200   -12.700    -3.300  
+9212 1 48957.00 I   .175124  .000426   .430416  .000329  I  .1401658  .0000158  2.4796 0.0109  I   -14.452     .738    -2.842     .105   .174400   .429900   .1400100   -12.700    -3.100  
+9212 2 48958.00 I   .175909  .000437   .428369  .000331  I  .1376364  .0000158  2.5825 0.0104  I   -14.536     .655    -3.012     .102   .175600   .427800   .1374800   -13.100    -3.000  
+9212 3 48959.00 I   .176811  .000414   .426428  .000331  I  .1350035  .0000136  2.6773 0.0117  I   -14.543     .655    -2.958     .102   .176900   .425800   .1348500   -13.600    -2.800  
+9212 4 48960.00 I   .178006  .000457   .424602  .000360  I  .1323019  .0000172  2.7116 0.0095  I   -14.584     .513    -2.749     .298   .178200   .424000   .1321700   -14.400    -2.800  
+9212 5 48961.00 I   .179261  .000406   .422835  .000335  I  .1296009  .0000133  2.6839 0.0100  I   -14.752     .483    -2.609     .104   .179500   .422400   .1294800   -15.100    -2.800  
+9212 6 48962.00 I   .180442  .000356   .421016  .000320  I  .1269445  .0000101  2.6249 0.0082  I   -14.959     .358    -2.530     .109   .180600   .420700   .1268200   -15.500    -3.000  
+9212 7 48963.00 I   .181507  .000358   .419048  .000275  I  .1243624  .0000097  2.5322 0.0068  I   -15.060     .341    -2.371     .102   .181600   .418900   .1242500   -15.700    -3.200  
+9212 8 48964.00 I   .182424  .000332   .416981  .000277  I  .1218870  .0000090  2.4190 0.0066  I   -14.963     .318    -2.137     .106   .182400   .416800   .1217800   -15.700    -3.200  
+9212 9 48965.00 I   .183234  .000320   .414896  .000283  I  .1195148  .0000089  2.3347 0.0068  I   -14.659     .293    -2.023     .101   .183300   .414600   .1194100   -15.600    -3.300  
+921210 48966.00 I   .184075  .000322   .412781  .000254  I  .1171967  .0000101  2.3130 0.0089  I   -14.290     .320    -2.251     .112   .184100   .412300   .1170700   -15.300    -3.300  
+921211 48967.00 I   .185114  .000334   .410653  .000234  I  .1148636  .0000154  2.3668 0.0070  I   -13.928     .237    -2.668     .102   .185100   .410100   .1147100   -14.900    -3.200  
+921212 48968.00 I   .186391  .000267   .408560  .000296  I  .1124375  .0000098  2.4973 0.0093  I   -13.673     .557    -2.930     .261   .186200   .407900   .1122700   -14.500    -3.100  
+921213 48969.00 I   .187772  .000286   .406530  .000273  I  .1098522  .0000104  2.6782 0.0069  I   -13.636     .657    -2.892     .389   .187400   .405800   .1096700   -14.200    -3.100  
+921214 48970.00 I   .189068  .000243   .404548  .000264  I  .1070804  .0000097  2.8614 0.0071  I   -13.827     .607    -2.614     .421   .188600   .403800   .1069000   -13.900    -3.000  
+921215 48971.00 I   .190156  .000223   .402565  .000254  I  .1041438  .0000097  3.0016 0.0071  I   -14.091     .604    -2.203     .462   .189800   .401900   .1039600   -13.900    -3.000  
+921216 48972.00 I   .190995  .000233   .400504  .000243  I  .1011071  .0000104  3.0522 0.0077  I   -14.260     .604    -1.834     .462   .190800   .400000   .1009100   -13.900    -2.700  
+921217 48973.00 I   .191741  .000264   .398313  .000254  I  .0980773  .0000119  2.9892 0.0098  I   -14.219     .604    -1.402     .462   .191700   .397900   .0978900   -14.200    -2.700  
+921218 48974.00 I   .192464  .000295   .395974  .000268  I  .0951610  .0000167  2.8295 0.0093  I   -14.027     .438    -1.186     .470   .192700   .395500   .0949800   -14.400    -2.600  
+921219 48975.00 I   .193139  .000313   .393493  .000203  I  .0924394  .0000144  2.6066 0.0108  I   -13.866     .327    -1.286     .323   .193500   .393000   .0922800   -14.700    -2.600  
+921220 48976.00 I   .193720  .000258   .390895  .000276  I  .0899542  .0000137  2.3646 0.0101  I   -13.858     .326    -1.557     .249   .194200   .390300   .0898200   -14.800    -2.600  
+921221 48977.00 I   .194234  .000265   .388228  .000275  I  .0877011  .0000142  2.1501 0.0089  I   -13.984     .565    -1.858     .111   .194800   .387700   .0875800   -14.800    -2.500  
+921222 48978.00 I   .194827  .000266   .385566  .000272  I  .0856314  .0000114  2.0034 0.0087  I   -14.040     .565    -2.110     .111   .195500   .385200   .0855100   -14.700    -2.600  
+921223 48979.00 I   .195638  .000224   .382963  .000270  I  .0836635  .0000100  1.9490 0.0069  I   -13.887     .565    -2.222     .111   .196100   .382700   .0835200   -14.500    -2.600  
+921224 48980.00 I   .196651  .000235   .380395  .000261  I  .0817043  .0000078  1.9820 0.0073  I   -13.621     .615    -2.154     .114   .196700   .380300   .0815400   -14.200    -2.500  
+921225 48981.00 I   .197901  .000240   .377836  .000272  I  .0796786  .0000106  2.0779 0.0054  I   -13.390     .764    -1.948     .298   .197700   .377700   .0794900   -13.800    -2.400  
+921226 48982.00 I   .199439  .000187   .375287  .000213  I  .0775356  .0000075  2.2126 0.0070  I   -13.226     .551    -1.735     .298   .199200   .375100   .0773400   -13.500    -2.200  
+921227 48983.00 I   .201252  .000152   .372765  .000191  I  .0752484  .0000090  2.3624 0.0063  I   -13.070     .153    -1.652     .134   .201000   .372400   .0750600   -13.200    -2.100  
+921228 48984.00 I   .203210  .000172   .370284  .000214  I  .0728132  .0000100  2.5050 0.0069  I   -12.926     .376    -1.731     .114   .203100   .369800   .0726400   -13.100    -1.900  
+921229 48985.00 I   .205074  .000173   .367837  .000218  I  .0702468  .0000104  2.6225 0.0073  I   -12.865     .512    -1.879     .189   .205100   .367200   .0701000   -13.100    -1.800  
+921230 48986.00 I   .206599  .000146   .365331  .000225  I  .0675835  .0000106  2.6940 0.0073  I   -12.859     .512    -1.962     .189   .206700   .364700   .0674400   -13.000    -1.800  
+921231 48987.00 I   .207631  .000152   .362604  .000242  I  .0648749  .0000103  2.7170 0.0088  I   -12.761     .512    -1.923     .189   .207800   .362000   .0647400   -13.100    -1.800  
+93 1 1 48988.00 I   .208194  .000172   .359648  .000240  I  .0621615  .0000141  2.7038 0.0075  I   -12.718     .651    -1.862     .219   .208500   .359100   .0620200   -13.300    -1.900  
+93 1 2 48989.00 I   .208431  .000166   .356562  .000241  I  .0594783  .0000108  2.6575 0.0094  I   -12.881     .587    -1.893     .180   .208700   .355900   .0593100   -13.400    -2.000  
+93 1 3 48990.00 I   .208526  .000197   .353449  .000252  I  .0568545  .0000124  2.5872 0.0081  I   -13.238     .578    -1.969     .198   .208800   .352600   .0566700   -13.400    -2.200  
+93 1 4 48991.00 I   .208647  .000207   .350396  .000251  I  .0543068  .0000120  2.5083 0.0105  I   -13.660     .393    -1.947     .298   .208900   .349600   .0541300   -13.500    -2.500  
+93 1 5 48992.00 I   .208921  .000289   .347431  .000241  I  .0518327  .0000170  2.4451 0.0104  I   -13.951     .377    -1.822     .298   .209000   .346600   .0516600   -13.400    -2.600  
+93 1 6 48993.00 I   .209421  .000313   .344530  .000237  I  .0494074  .0000169  2.4096 0.0116  I   -14.002     .377    -1.780     .298   .209300   .343800   .0492500   -13.400    -2.700  
+93 1 7 48994.00 I   .210159  .000312   .341695  .000223  I  .0469999  .0000158  2.4148 0.0126  I   -13.838     .377    -1.928     .298   .209700   .341100   .0468700   -13.400    -2.700  
+93 1 8 48995.00 I   .211067  .000323   .338925  .000221  I  .0445590  .0000187  2.4764 0.0109  I   -13.503     .290    -2.188     .298   .210600   .338400   .0444300   -13.400    -2.700  
+93 1 9 48996.00 I   .212049  .000299   .336234  .000240  I  .0420253  .0000149  2.6034 0.0122  I   -13.108     .235    -2.304     .298   .211600   .335800   .0418800   -13.400    -2.500  
+93 110 48997.00 I   .213045  .000365   .333641  .000276  I  .0393377  .0000158  2.7739 0.0136  I   -12.856     .261    -2.140     .298   .212800   .333200   .0392000   -13.500    -2.300  
+93 111 48998.00 I   .213955  .000354   .331154  .000273  I  .0364839  .0000227  2.9251 0.0127  I   -12.921     .114    -1.841     .298   .213900   .330800   .0363500   -13.700    -2.100  
+93 112 48999.00 I   .214684  .000225   .328784  .000464  I  .0335118  .0000199  3.0034 0.0151  I   -13.266     .114    -1.665     .298   .214800   .328400   .0333800   -14.000    -2.000  
+93 113 49000.00 I   .215132  .000204   .326497  .000462  I  .0305107  .0000198  2.9810 0.0140  I   -13.680     .216    -1.722     .298   .215300   .326200   .0303900   -14.200    -2.000  
+93 114 49001.00 I   .215226  .000206   .324183  .000462  I  .0275822  .0000196  2.8614 0.0177  I   -13.987     .216    -1.890     .298   .215500   .324100   .0274700   -14.400    -2.100  
+93 115 49002.00 I   .214978  .000303   .321737  .000557  I  .0248090  .0000293  2.6787 0.0136  I   -14.172     .283    -2.023     .298   .215300   .321800   .0247000   -14.600    -2.200  
+93 116 49003.00 I   .214461  .000289   .319091  .000435  I  .0222319  .0000190  2.4749 0.0149  I   -14.290     .207    -2.050     .298   .214500   .319200   .0221400   -14.500    -2.400  
+93 117 49004.00 I   .213815  .000202   .316306  .000317  I  .0198540  .0000056  2.2867 0.0099  I   -14.398     .207    -2.028     .298   .213700   .316400   .0197600   -14.300    -2.600  
+93 118 49005.00 I   .213184  .000208   .313454  .000306  I  .0176442  .0000055  2.1414 0.0039  I   -14.485     .186    -2.037     .298   .212800   .313300   .0175500   -14.000    -2.700  
+93 119 49006.00 I   .212639  .000206   .310580  .000242  I  .0155523  .0000053  2.0527 0.0039  I   -14.469     .791    -2.128     .298   .212300   .310100   .0154500   -13.700    -2.800  
+93 120 49007.00 I   .212180  .000206   .307690  .000254  I  .0135130  .0000056  2.0414 0.0040  I   -14.282     .152    -2.283     .298   .212000   .306900   .0133900   -13.600    -2.800  
+93 121 49008.00 I   .211925  .000182   .304822  .000258  I  .0114464  .0000059  2.0995 0.0043  I   -13.979     .152    -2.328     .298   .211900   .303900   .0113300   -13.500    -2.700  
+93 122 49009.00 I   .211898  .000133   .302089  .000223  I  .0093022  .0000066  2.1932 0.0051  I   -13.722     .187    -2.199     .298   .212000   .301000   .0091800   -13.500    -2.500  
+93 123 49010.00 I   .211999  .000142   .299570  .000282  I  .0070530  .0000083  2.3081 0.0078  I   -13.625     .210    -1.974     .134   .212100   .298500   .0069300   -13.600    -2.300  
+93 124 49011.00 I   .212110  .000240   .297312  .000313  I  .0046827  .0000141  2.4329 0.0081  I   -13.642     .227    -1.772     .175   .212300   .296300   .0045600   -13.700    -2.200  
+93 125 49012.00 I   .212144  .000228   .295279  .000312  I  .0021893  .0000140  2.5515 0.0099  I   -13.705     .212    -1.700     .188   .212400   .294300   .0020500   -13.900    -2.000  
+93 126 49013.00 I   .212037  .000245   .293336  .000316  I -.0004160  .0000138  2.6570 0.0106  I   -13.793     .235    -1.778     .272   .212300   .292300  -.0005600   -14.200    -2.000  
+93 127 49014.00 I   .211751  .000254   .291318  .000305  I -.0031141  .0000158  2.7305 0.0103  I   -13.835     .253    -1.980     .234   .211800   .290300  -.0032600   -14.500    -2.100  
+93 128 49015.00 I   .211304  .000267   .289155  .000302  I -.0058559  .0000154  2.7408 0.0127  I   -13.777     .253    -2.246     .234   .211100   .288300  -.0059900   -14.600    -2.200  
+93 129 49016.00 I   .210612  .000316   .286843  .000326  I -.0085770  .0000200  2.6949 0.0116  I   -13.629     .258    -2.350     .248   .210200   .286100  -.0087000   -14.800    -2.400  
+93 130 49017.00 I   .209635  .000364   .284374  .000254  I -.0112341  .0000173  2.6141 0.0127  I   -13.471     .556    -2.481     .197   .209100   .283700  -.0113600   -15.000    -2.700  
+93 131 49018.00 I   .208394  .000343   .281767  .000275  I -.0137992  .0000158  2.5152 0.0124  I   -13.492     .605    -2.715     .187   .208000   .281100  -.0139300   -14.900    -2.900  
+93 2 1 49019.00 I   .207041  .000355   .279023  .000271  I -.0162659  .0000177  2.4203 0.0109  I   -13.725     .591    -2.840     .298   .206800   .278400  -.0164000   -14.900    -3.200  
+93 2 2 49020.00 I   .205890  .000341   .276161  .000271  I -.0186504  .0000151  2.3570 0.0116  I   -14.044     .846    -2.728     .298   .205800   .275500  -.0187800      .000      .000  
+93 2 3 49021.00 I   .205272  .000326   .273272  .000285  I -.0210032  .0000150  2.3635 0.0106  I   -14.312     .901    -2.545     .185   .205600   .272600  -.0211300   -14.700    -3.500  
+93 2 4 49022.00 I   .205181  .000303   .270501  .000277  I -.0234080  .0000150  2.4618 0.0119  I   -14.286     .901    -2.595     .185   .205600   .269600  -.0235400   -14.400    -3.600  
+93 2 5 49023.00 I   .205410  .000354   .267923  .000288  I -.0259570  .0000186  2.6506 0.0094  I   -13.832     .911    -2.859     .217   .205700   .266800  -.0261000   -14.100    -3.500  
+93 2 6 49024.00 I   .205674  .000251   .265552  .000266  I -.0287298  .0000112  2.9011 0.0113  I   -13.309     .785    -3.090     .181   .205700   .264600  -.0288900   -13.800    -3.400  
+93 2 7 49025.00 I   .205728  .000216   .263317  .000278  I -.0317594  .0000127  3.1521 0.0083  I   -12.956     .843    -2.999     .192   .205700   .262400  -.0319500   -13.600    -3.100  
+93 2 8 49026.00 I   .205400  .000200   .261104  .000271  I -.0350095  .0000122  3.3296 0.0092  I   -12.944     .662    -2.688     .178   .205400   .260200  -.0352200   -13.600    -3.000  
+93 2 9 49027.00 I   .204693  .000244   .258794  .000243  I -.0383773  .0000133  3.3832 0.0079  I   -13.242     .285    -2.450     .298   .204900   .257800  -.0386000   -13.500    -2.900  
+93 210 49028.00 I   .203779  .000228   .256316  .000213  I -.0417285  .0000100  3.2948 0.0083  I   -13.628     .321    -2.430     .298   .204200   .255300  -.0419400   -13.700    -3.000  
+93 211 49029.00 I   .202761  .000220   .253763  .000218  I -.0449247  .0000099  3.0800 0.0075  I   -13.898     .301    -2.563     .298   .203400   .252700  -.0451200   -14.000    -3.100  
+93 212 49030.00 I   .201616  .000226   .251195  .000215  I -.0478655  .0000112  2.7963 0.0072  I   -14.001     .299    -2.714     .298   .202200   .250100  -.0480400   -14.200    -3.300  
+93 213 49031.00 I   .200385  .000208   .248588  .000190  I -.0505214  .0000105  2.5248 0.0072  I   -14.073     .275    -2.963     .298   .200900   .247500  -.0506900   -14.500    -3.500  
+93 214 49032.00 I   .199315  .000256   .245908  .000186  I -.0529393  .0000092  2.3260 0.0070  I   -14.148     .314    -3.302     .298   .199500   .245000  -.0531000   -14.600    -3.800  
+93 215 49033.00 I   .198417  .000267   .243224  .000178  I -.0552035  .0000092  2.2176 0.0061  I   -14.258     .295    -3.616     .298   .198400   .242500  -.0553600   -14.600    -3.900  
+93 216 49034.00 I   .197692  .000252   .240590  .000178  I -.0574059  .0000081  2.2032 0.0074  I   -14.457     .225    -3.825     .298   .197600   .240100  -.0575600   -14.600    -4.100  
+93 217 49035.00 I   .197110  .000271   .238066  .000256  I -.0596344  .0000115  2.2621 0.0070  I   -14.627     .340    -3.899     .298   .197100   .237400  -.0597700   -14.400    -4.100  
+93 218 49036.00 I   .196581  .000298   .235758  .000255  I -.0619457  .0000114  2.3679 0.0095  I   -14.554     .340    -3.815     .298   .196800   .234900  -.0620600   -14.400    -4.000  
+93 219 49037.00 I   .195886  .000367   .233727  .000297  I -.0643816  .0000151  2.5080 0.0084  I   -14.280     .412    -3.669     .298   .196300   .232700  -.0644800   -14.300    -3.900  
+93 220 49038.00 I   .194803  .000374   .232000  .000347  I -.0669627  .0000124  2.6510 0.0091  I   -14.013     .382    -3.503     .298   .195400   .230900  -.0670500   -14.200    -3.700  
+93 221 49039.00 I   .193264  .000290   .230511  .000308  I -.0696740  .0000102  2.7651 0.0079  I   -13.856     .382    -3.342     .298   .193900   .229400  -.0697600   -14.100    -3.700  
+93 222 49040.00 I   .191321  .000291   .229092  .000313  I -.0724767  .0000097  2.8306 0.0068  I   -13.793     .382    -3.277     .298   .191900   .228000  -.0725800   -14.100    -3.700  
+93 223 49041.00 I   .189105  .000232   .227541  .000294  I -.0753148  .0000091  2.8350 0.0065  I   -13.752     .324    -3.382     .298   .189600   .226700  -.0754400   -14.200    -3.700  
+93 224 49042.00 I   .186790  .000206   .225705  .000282  I -.0781292  .0000087  2.7869 0.0054  I   -13.630     .364    -3.583     .298   .187300   .224800  -.0782800   -14.000    -3.900  
+93 225 49043.00 I   .184497  .000205   .223638  .000279  I -.0808761  .0000059  2.7011 0.0059  I   -13.369     .364    -3.741     .298   .184900   .222900  -.0810400   -13.900    -4.000  
+93 226 49044.00 I   .182313  .000195   .221451  .000305  I -.0835222  .0000081  2.5876 0.0041  I   -13.021     .400    -3.814     .298   .182600   .220800  -.0836700   -13.600    -4.300  
+93 227 49045.00 I   .180270  .000174   .219255  .000209  I -.0860470  .0000056  2.4613 0.0050  I   -12.853     .377    -3.892     .161   .180600   .218600  -.0861700   -13.600    -4.500  
+93 228 49046.00 I   .178323  .000206   .217119  .000197  I -.0884464  .0000059  2.3397 0.0051  I   -13.068     .377    -4.038     .161   .178600   .216500  -.0885500   -13.500    -4.600  
+93 3 1 49047.00 I   .176433  .000203   .215094  .000201  I -.0907343  .0000085  2.2419 0.0060  I   -13.574     .349    -4.168     .152   .176600   .214400  -.0908200   -13.500    -4.800  
+93 3 2 49048.00 I   .174589  .000224   .213215  .000182  I -.0929467  .0000104  2.1938 0.0067  I   -14.056     .311    -4.186     .198   .174600   .212500  -.0930500   -13.500    -4.900  
+93 3 3 49049.00 I   .172837  .000217   .211506  .000180  I -.0951493  .0000104  2.2280 0.0074  I   -14.283     .523    -4.184     .171   .172700   .210700  -.0952700   -13.600    -4.900  
+93 3 4 49050.00 I   .171272  .000225   .209920  .000175  I -.0974343  .0000104  2.3571 0.0084  I   -14.290     .523    -4.308     .171   .171200   .209000  -.0975700   -13.300    -5.100  
+93 3 5 49051.00 I   .169878  .000277   .208394  .000166  I -.0998884  .0000133  2.5611 0.0088  I   -14.149     .613    -4.555     .116   .169800   .207600  -.1000400   -13.500    -5.000  
+93 3 6 49052.00 I   .168575  .000261   .206865  .000176  I -.1025715  .0000142  2.8103 0.0086  I   -13.856     .476    -4.781     .298   .168400   .206100  -.1027400   -13.700    -5.000  
+93 3 7 49053.00 I   .167251  .000275   .205305  .000209  I -.1055072  .0000108  3.0541 0.0097  I   -13.524     .521    -4.761     .298   .167000   .204500  -.1056700   -14.000    -4.800  
+93 3 8 49054.00 I   .165878  .000279   .203710  .000207  I -.1086556  .0000131  3.2254 0.0074  I   -13.331     .480    -4.526     .298   .165800   .202900  -.1088200   -13.900    -4.800  
+93 3 9 49055.00 I   .164621  .000289   .202094  .000212  I -.1119204  .0000102  3.2838 0.0084  I   -13.303     .155    -4.325     .298   .164700   .201400  -.1120700   -14.000    -4.800  
+93 310 49056.00 I   .163704  .000289   .200494  .000211  I -.1151810  .0000106  3.2157 0.0082  I   -13.360     .492    -4.288     .298   .163700   .199800  -.1153000   -14.100    -4.800  
+93 311 49057.00 I   .163151  .000260   .198951  .000204  I -.1183182  .0000128  3.0467 0.0083  I   -13.491     .492    -4.377     .298   .163100   .198300  -.1184100   -14.200    -4.900  
+93 312 49058.00 I   .162596  .000258   .197466  .000197  I -.1212618  .0000128  2.8398 0.0110  I   -13.631     .633    -4.483     .298   .162600   .196900  -.1213400   -14.200    -5.000  
+93 313 49059.00 I   .161644  .000294   .196015  .000192  I -.1240068  .0000178  2.6600 0.0110  I   -13.616     .529    -4.644     .107   .161900   .195500  -.1240900   -14.100    -5.100  
+93 314 49060.00 I   .160152  .000258   .194585  .000306  I -.1266037  .0000179  2.5461 0.0126  I   -13.364     .577    -4.923     .116   .160500   .194100  -.1267000   -13.900    -5.400  
+93 315 49061.00 I   .158171  .000259   .193139  .000304  I -.1291206  .0000177  2.4971 0.0124  I   -13.045     .478    -5.234     .158   .158500   .192700  -.1292200   -13.500    -5.600  
+93 316 49062.00 I   .155860  .000272   .191669  .000310  I -.1316158  .0000171  2.5020 0.0119  I   -12.943     .248    -5.445     .170   .156000   .191200  -.1317200   -13.300    -5.600  
+93 317 49063.00 I   .153408  .000283   .190202  .000311  I -.1341389  .0000159  2.5499 0.0118  I   -13.092     .328    -5.523     .152   .153600   .189700  -.1342400   -13.000    -5.700  
+93 318 49064.00 I   .150961  .000286   .188755  .000311  I -.1367249  .0000163  2.6256 0.0107  I   -13.231     .328    -5.469     .152   .151100   .188200  -.1368200   -12.900    -5.700  
+93 319 49065.00 I   .148646  .000274   .187318  .000331  I -.1393946  .0000142  2.7147 0.0102  I   -13.129     .332    -5.414     .157   .148600   .186700  -.1394800   -12.800    -5.700  
+93 320 49066.00 I   .146522  .000303   .185882  .000328  I -.1421530  .0000121  2.8001 0.0101  I   -12.810     .347    -5.324     .149   .146500   .185300  -.1422400   -12.700    -5.500  
+93 321 49067.00 I   .144578  .000329   .184458  .000195  I -.1449878  .0000144  2.8647 0.0072  I   -12.526     .404    -5.138     .108   .144600   .183900  -.1450800   -12.700    -5.500  
+93 322 49068.00 I   .142711  .000254   .183056  .000178  I -.1478704  .0000077  2.8934 0.0082  I   -12.435     .391    -4.961     .160   .142700   .182600  -.1479800   -12.600    -5.500  
+93 323 49069.00 I   .140784  .000245   .181682  .000176  I -.1507614  .0000080  2.8826 0.0055  I   -12.483     .348    -4.949     .216   .140900   .181100  -.1508900   -12.700    -5.600  
+93 324 49070.00 I   .138650  .000249   .180349  .000178  I -.1536223  .0000078  2.8320 0.0057  I   -12.558     .340    -5.167     .184   .138700   .179700  -.1537700   -13.000    -5.700  
+93 325 49071.00 I   .136190  .000258   .179107  .000178  I -.1564082  .0000081  2.7300 0.0058  I   -12.610     .340    -5.614     .184   .136200   .178400  -.1565700   -13.000    -5.900  
+93 326 49072.00 I   .133300  .000213   .177912  .000189  I -.1590735  .0000086  2.6017 0.0054  I   -12.565     .321    -5.919     .204   .133300   .177200  -.1592400   -13.100    -6.100  
+93 327 49073.00 I   .130164  .000193   .176669  .000221  I -.1616137  .0000071  2.4798 0.0055  I   -12.393     .277    -6.054     .174   .130200   .175900  -.1617700   -13.100    -6.400  
+93 328 49074.00 I   .126954  .000190   .175365  .000224  I -.1640387  .0000070  2.3746 0.0076  I   -12.261     .291    -6.159     .149   .127000   .174400  -.1641800   -12.900    -6.600  
+93 329 49075.00 I   .123795  .000206   .174030  .000268  I -.1663745  .0000134  2.3040 0.0076  I   -12.291     .239    -6.262     .298   .123700   .173000  -.1665100   -12.700    -6.800  
+93 330 49076.00 I   .120808  .000168   .172734  .000260  I -.1686651  .0000135  2.2885 0.0093  I   -12.384     .112    -6.312     .298   .120500   .171600  -.1687800   -12.300    -6.800  
+93 331 49077.00 I   .118065  .000182   .171571  .000256  I -.1709796  .0000129  2.3573 0.0088  I   -12.374     .112    -6.328     .298   .117700   .170700  -.1711000   -12.000    -6.900  
+93 4 1 49078.00 I   .115461  .000161   .170608  .000249  I -.1734106  .0000113  2.5188 0.0121  I   -12.193     .112    -6.406     .298   .115200   .169800  -.1735300   -11.700    -6.800  
+93 4 2 49079.00 I   .112819  .000189   .169850  .000226  I -.1760396  .0000204  2.7474 0.0110  I   -11.913     .791    -6.562     .298   .112800   .169100  -.1761600   -11.600    -6.600  
+93 4 3 49080.00 I   .109985  .000251   .169234  .000161  I -.1789125  .0000189  2.9973 0.0128  I   -11.669     .310    -6.630     .298   .110400   .168500  -.1790400   -11.000    -6.500  
+93 4 4 49081.00 I   .106929  .000258   .168672  .000135  I -.1820214  .0000155  3.2089 0.0124  I   -11.588     .310    -6.450     .298   .107500   .167900  -.1821500   -11.400    -6.400  
+93 4 5 49082.00 I   .103742  .000253   .168107  .000178  I -.1852993  .0000160  3.3277 0.0111  I   -11.705     .310    -6.115     .298   .104400   .167300  -.1854200   -12.000    -6.300  
+93 4 6 49083.00 I   .100497  .000243   .167543  .000195  I -.1886393  .0000160  3.3340 0.0113  I   -11.894     .236    -5.905     .298   .101000   .166800  -.1887400   -12.300    -6.300  
+93 4 7 49084.00 I   .097190  .000266   .166999  .000196  I -.1919310  .0000159  3.2312 0.0107  I   -12.000     .236    -5.965     .298   .097400   .166300  -.1920200   -12.600    -6.300  
+93 4 8 49085.00 I   .093870  .000272   .166460  .000200  I -.1950761  .0000143  3.0515 0.0127  I   -12.022     .236    -6.176     .298   .093800   .165900  -.1951500   -12.700    -6.500  
+93 4 9 49086.00 I   .090617  .000223   .165924  .000225  I -.1980306  .0000198  2.8618 0.0107  I   -12.033     .125    -6.353     .298   .090200   .165400  -.1981000   -12.700    -6.700  
+93 410 49087.00 I   .087503  .000279   .165434  .000265  I -.2008148  .0000158  2.7176 0.0129  I   -11.973     .153    -6.465     .134   .087100   .164900  -.2008700   -12.700    -6.800  
+93 411 49088.00 I   .084599  .000288   .165031  .000277  I -.2034890  .0000165  2.6431 0.0131  I   -11.743     .187    -6.582     .122   .084300   .164400  -.2035500   -12.500    -6.900  
+93 412 49089.00 I   .081980  .000304   .164749  .000212  I -.2061209  .0000208  2.6282 0.0128  I   -11.481     .220    -6.689     .142   .081800   .163900  -.2061900   -12.300    -7.100  
+93 413 49090.00 I   .079691  .000297   .164583  .000244  I -.2087601  .0000195  2.6572 0.0142  I   -11.477     .306    -6.677     .145   .079700   .163600  -.2088500   -12.000    -7.200  
+93 414 49091.00 I   .077753  .000287   .164501  .000247  I -.2114531  .0000194  2.7395 0.0138  I   -11.738     .303    -6.562     .132   .077900   .163600  -.2115600   -11.900    -7.200  
+93 415 49092.00 I   .076037  .000287   .164432  .000236  I -.2142464  .0000195  2.8438 0.0158  I   -11.886     .303    -6.561     .132   .076200   .163600  -.2143700   -11.800    -7.200  
+93 416 49093.00 I   .074297  .000303   .164311  .000202  I -.2171315  .0000250  2.9204 0.0121  I   -11.677     .342    -6.775     .112   .074400   .163600  -.2172500   -11.800    -7.200  
+93 417 49094.00 I   .072364  .000233   .164130  .000208  I -.2200758  .0000142  2.9628 0.0134  I   -11.179     .413    -6.919     .121   .072400   .163500  -.2201900   -11.700    -7.100  
+93 418 49095.00 I   .070167  .000252   .163952  .000226  I -.2230453  .0000096  2.9699 0.0102  I   -10.809     .430    -6.854     .130   .070300   .163500  -.2231600   -11.600    -7.100  
+93 419 49096.00 I   .067678  .000203   .163854  .000248  I -.2260020  .0000146  2.9362 0.0091  I   -10.838     .559    -6.730     .159   .068000   .163400  -.2261100   -11.600    -7.100  
+93 420 49097.00 I   .064991  .000208   .163886  .000265  I -.2289063  .0000155  2.8684 0.0107  I   -11.190     .581    -6.775     .256   .065500   .163400  -.2290100   -11.700    -7.200  
+93 421 49098.00 I   .062269  .000234   .164046  .000266  I -.2317394  .0000156  2.8024 0.0111  I   -11.576     .570    -7.003     .222   .062800   .163400  -.2318600   -11.700    -7.400  
+93 422 49099.00 I   .059560  .000208   .164214  .000266  I -.2345184  .0000159  2.7584 0.0146  I   -11.622     .570    -7.146     .222   .060000   .163300  -.2346600   -11.700    -7.600  
+93 423 49100.00 I   .056815  .000247   .164291  .000279  I -.2372510  .0000248  2.6990 0.0132  I   -11.470     .579    -7.299     .251   .057000   .163100  -.2373800   -11.500    -7.700  
+93 424 49101.00 I   .054017  .000269   .164249  .000247  I -.2399097  .0000212  2.6196 0.0165  I   -11.390     .636    -7.341     .298   .054000   .162900  -.2400300   -11.300    -8.000  
+93 425 49102.00 I   .051235  .000294   .164158  .000262  I -.2424968  .0000218  2.5600 0.0131  I   -11.502     .551    -7.297     .300   .051100   .162800  -.2426200   -11.000    -8.200  
+93 426 49103.00 I   .048568  .000275   .164102  .000202  I -.2450409  .0000153  2.5339 0.0132  I   -11.837     .829    -7.303     .345   .048300   .163000  -.2451500   -10.800    -8.200  
+93 427 49104.00 I   .046083  .000262   .164147  .000183  I -.2475844  .0000149  2.5672 0.0106  I   -12.288     .845    -7.420     .379   .045800   .163400  -.2477200   -10.500    -8.300  
+93 428 49105.00 I   .043828  .000260   .164335  .000186  I -.2502105  .0000148  2.7060 0.0106  I   -12.520     .776    -7.610     .316   .043400   .163800  -.2503800   -10.400    -8.200  
+93 429 49106.00 I   .041787  .000279   .164665  .000190  I -.2530275  .0000151  2.9383 0.0106  I   -12.123     .776    -7.690     .316   .041400   .164200  -.2532100   -10.500    -8.200  
+93 430 49107.00 I   .039911  .000278   .165073  .000192  I -.2560917  .0000151  3.1846 0.0099  I   -11.325     .783    -7.647     .280   .039500   .164600  -.2562600   -10.700    -8.000  
+93 5 1 49108.00 I   .038162  .000254   .165485  .000180  I -.2593800  .0000129  3.3808 0.0089  I   -10.625     .783    -7.446     .280   .038000   .165000  -.2595300   -11.100    -7.900  
+93 5 2 49109.00 I   .036530  .000228   .165871  .000096  I -.2628226  .0000095  3.4850 0.0090  I   -10.323     .410    -7.069     .298   .036600   .165300  -.2629600   -11.600    -7.700  
+93 5 3 49110.00 I   .034937  .000282   .166200  .000124  I -.2663070  .0000126  3.4602 0.0091  I   -10.460     .410    -6.657     .298   .035100   .165600  -.2664400   -12.200    -7.700  
+93 5 4 49111.00 I   .033243  .000329   .166454  .000202  I -.2696980  .0000156  3.3004 0.0099  I   -10.874     .264    -6.478     .298   .033300   .165800  -.2698200   -12.800    -7.600  
+93 5 5 49112.00 I   .031379  .000322   .166619  .000197  I -.2728791  .0000152  3.0546 0.0109  I   -11.347     .334    -6.692     .298   .031400   .166100  -.2730100   -13.300    -7.600  
+93 5 6 49113.00 I   .029478  .000322   .166678  .000199  I -.2758004  .0000151  2.7886 0.0107  I   -11.792     .334    -7.115     .298   .029500   .166200  -.2759200   -13.500    -7.700  
+93 5 7 49114.00 I   .027545  .000315   .166609  .000212  I -.2784700  .0000152  2.5638 0.0113  I   -12.174     .334    -7.366     .298   .027700   .166400  -.2785800   -13.500    -7.800  
+93 5 8 49115.00 I   .025583  .000327   .166474  .000238  I -.2809558  .0000167  2.4224 0.0117  I   -12.284     .373    -7.404     .105   .025900   .166400  -.2810600   -13.200    -7.800  
+93 5 9 49116.00 I   .023567  .000292   .166356  .000262  I -.2833422  .0000178  2.3632 0.0110  I   -12.050     .439    -7.370     .141   .024000   .166400  -.2834500   -12.800    -7.900  
+93 510 49117.00 I   .021584  .000244   .166332  .000218  I -.2857034  .0000144  2.3678 0.0104  I   -11.693     .381    -7.354     .298   .022100   .166300  -.2858100   -12.300    -7.800  
+93 511 49118.00 I   .019770  .000179   .166462  .000185  I -.2880885  .0000106  2.4047 0.0089  I   -11.533     .125    -7.374     .298   .020100   .166200  -.2882100   -11.800    -7.800  
+93 512 49119.00 I   .018154  .000181   .166749  .000181  I -.2905120  .0000106  2.4394 0.0076  I   -11.656     .495    -7.402     .155   .018200   .166100  -.2906300   -11.400    -7.700  
+93 513 49120.00 I   .016659  .000192   .167191  .000169  I -.2929677  .0000108  2.4754 0.0070  I   -11.782     .495    -7.402     .155   .016600   .166400  -.2931100   -11.100    -7.500  
+93 514 49121.00 I   .015280  .000186   .167765  .000158  I -.2954686  .0000092  2.5290 0.0069  I   -11.599     .495    -7.368     .155   .015300   .166800  -.2956200   -10.900    -7.500  
+93 515 49122.00 I   .014000  .000185   .168440  .000164  I -.2980239  .0000087  2.5773 0.0063  I   -11.239     .495    -7.276     .155   .014000   .167400  -.2981900   -11.000    -7.400  
+93 516 49123.00 I   .012715  .000192   .169193  .000153  I -.3006133  .0000086  2.5961 0.0077  I   -11.088     .507    -7.121     .164   .012700   .168200  -.3007600   -11.300    -7.400  
+93 517 49124.00 I   .011395  .000270   .170002  .000179  I -.3032040  .0000127  2.5788 0.0064  I   -11.308     .508    -7.010     .180   .011400   .169000  -.3033500   -11.700    -7.500  
+93 518 49125.00 I   .010122  .000263   .170851  .000161  I -.3057593  .0000094  2.5268 0.0076  I   -11.718     .206    -7.106     .135   .010200   .170000  -.3059000   -12.300    -7.600  
+93 519 49126.00 I   .008962  .000260   .171744  .000138  I -.3082467  .0000083  2.4422 0.0060  I   -12.046     .206    -7.431     .135   .009000   .170900  -.3083700   -12.900    -7.800  
+93 520 49127.00 I   .007802  .000272   .172669  .000138  I -.3106349  .0000074  2.3312 0.0056  I   -12.255     .195    -7.694     .110   .007600   .171900  -.3107400   -13.300    -7.900  
+93 521 49128.00 I   .006488  .000306   .173605  .000145  I -.3129097  .0000074  2.2219 0.0056  I   -12.370     .195    -7.751     .110   .006000   .172900  -.3130200   -13.500    -8.100  
+93 522 49129.00 I   .004962  .000323   .174529  .000121  I -.3150881  .0000085  2.1407 0.0056  I   -12.385     .166    -7.664     .105   .004000   .173900  -.3152100   -13.500    -8.300  
+93 523 49130.00 I   .003180  .000307   .175435  .000147  I -.3172081  .0000083  2.1104 0.0050  I   -12.340     .374    -7.541     .298   .001900   .174900  -.3173300   -13.300    -8.300  
+93 524 49131.00 I   .001001  .000288   .176264  .000158  I -.3193324  .0000051  2.1505 0.0049  I   -12.299     .357    -7.459     .298  -.000400   .175700  -.3194600   -13.000    -8.300  
+93 525 49132.00 I  -.001543  .000293   .176968  .000147  I -.3215329  .0000052  2.2621 0.0039  I   -12.297     .309    -7.467     .298  -.002700   .176500  -.3216700   -12.700    -8.200  
+93 526 49133.00 I  -.004186  .000271   .177552  .000173  I -.3238725  .0000058  2.4214 0.0039  I   -12.264     .343    -7.597     .298  -.004900   .177000  -.3240100   -12.500    -8.000  
+93 527 49134.00 I  -.006612  .000255   .178039  .000168  I -.3263804  .0000058  2.5948 0.0056  I   -12.208     .343    -7.764     .298  -.006900   .177400  -.3265300   -12.300    -7.900  
+93 528 49135.00 I  -.008664  .000254   .178485  .000165  I -.3290562  .0000095  2.7504 0.0062  I   -12.087     .343    -7.860     .298  -.008700   .177700  -.3292300   -12.300    -7.600  
+93 529 49136.00 I  -.010426  .000279   .178935  .000144  I -.3318619  .0000110  2.8481 0.0100  I   -11.910     .228    -7.834     .298  -.010400   .178000  -.3320500   -12.500    -7.400  
+93 530 49137.00 I  -.012046  .000327   .179405  .000164  I -.3347233  .0000176  2.8585 0.0095  I   -11.812     .791    -7.665     .298  -.012000   .178400  -.3349100   -12.900    -7.300  
+93 531 49138.00 I  -.013693  .000317   .179884  .000236  I -.3375466  .0000156  2.7720 0.0114  I   -11.935     .122    -7.392     .298  -.013700   .178900  -.3377400   -13.300    -7.200  
+93 6 1 49139.00 I  -.015457  .000320   .180333  .000303  I -.3402389  .0000145  2.6002 0.0110  I   -12.301     .122    -7.129     .298  -.015400   .179500  -.3404000   -13.600    -7.300  
+93 6 2 49140.00 I  -.017306  .000327   .180721  .000305  I -.3427283  .0000154  2.3724 0.0098  I   -12.803     .791    -6.996     .298  -.017100   .180000  -.3428600   -13.800    -7.300  
+93 6 3 49141.00 I  -.019162  .000308   .181046  .000313  I -.3449825  .0000131  2.1410 0.0097  I   -13.288     .791    -6.985     .298  -.018900   .180500  -.3450900   -13.900    -7.300  
+93 6 4 49142.00 I  -.020994  .000281   .181454  .000317  I -.3470279  .0000117  1.9623 0.0091  I   -13.599     .791    -6.988     .298  -.020900   .180900  -.3471100   -14.000    -7.500  
+93 6 5 49143.00 I  -.022821  .000274   .182091  .000324  I -.3489347  .0000126  1.8665 0.0114  I   -13.654     .791    -6.902     .298  -.022800   .181500  -.3489900   -13.800    -7.600  
+93 6 6 49144.00 I  -.024651  .000361   .182945  .000336  I -.3507899  .0000196  1.8576 0.0088  I   -13.514     .283    -6.721     .298  -.024600   .182400  -.3508500   -13.600    -7.500  
+93 6 7 49145.00 I  -.026472  .000260   .183944  .000245  I -.3526721  .0000122  1.9154 0.0117  I   -13.344     .292    -6.582     .298  -.026500   .183300  -.3527500   -13.500    -7.500  
+93 6 8 49146.00 I  -.028260  .000292   .184996  .000179  I -.3546329  .0000129  2.0099 0.0089  I   -13.296     .298    -6.641     .298  -.028300   .184300  -.3547500   -13.300    -7.500  
+93 6 9 49147.00 I  -.029986  .000296   .186010  .000178  I -.3566907  .0000130  2.1009 0.0099  I   -13.369     .298    -6.942     .298  -.030200   .185300  -.3568300   -13.300    -7.400  
+93 610 49148.00 I  -.031655  .000290   .186928  .000197  I -.3588295  .0000149  2.1764 0.0098  I   -13.533     .298    -7.344     .298  -.032000   .186200  -.3590000   -13.500    -7.300  
+93 611 49149.00 I  -.033229  .000292   .187816  .000194  I -.3610373  .0000148  2.2334 0.0091  I   -13.633     .298    -7.653     .298  -.033500   .187000  -.3612300   -13.800    -7.300  
+93 612 49150.00 I  -.034528  .000240   .188782  .000156  I -.3632832  .0000106  2.2510 0.0109  I   -13.643     .258    -7.716     .298  -.034700   .188100  -.3634800   -14.300    -7.300  
+93 613 49151.00 I  -.035578  .000210   .189930  .000218  I -.3655243  .0000161  2.2235 0.0080  I   -13.730     .791    -7.560     .298  -.035600   .189300  -.3657100   -14.700    -7.500  
+93 614 49152.00 I  -.036543  .000172   .191288  .000197  I -.3677157  .0000119  2.1525 0.0101  I   -14.024     .791    -7.349     .102  -.036600   .190600  -.3678700   -15.200    -7.600  
+93 615 49153.00 I  -.037651  .000163   .192787  .000205  I -.3698172  .0000122  2.0451 0.0082  I   -14.497     .791    -7.256     .102  -.037800   .192000  -.3699400   -15.700    -7.800  
+93 616 49154.00 I  -.039083  .000163   .194308  .000190  I -.3718005  .0000114  1.9214 0.0082  I   -15.026     .791    -7.312     .102  -.039200   .193500  -.3719100   -16.000    -8.000  
+93 617 49155.00 I  -.040805  .000159   .195682  .000185  I -.3736641  .0000111  1.8101 0.0077  I   -15.473     .791    -7.313     .102  -.040900   .194800  -.3737700   -16.200    -8.200  
+93 618 49156.00 I  -.042804  .000146   .196851  .000181  I -.3754291  .0000104  1.7240 0.0075  I   -15.752     .791    -7.207     .102  -.042900   .195900  -.3755400   -16.200    -8.300  
+93 619 49157.00 I  -.045006  .000178   .197823  .000239  I -.3771254  .0000101  1.6779 0.0084  I   -15.816     .791    -7.109     .106  -.045100   .196900  -.3772600   -16.200    -8.400  
+93 620 49158.00 I  -.047278  .000179   .198658  .000185  I -.3788066  .0000132  1.6968 0.0083  I   -15.676     .298    -7.109     .182  -.047200   .197800  -.3789600   -16.000    -8.400  
+93 621 49159.00 I  -.049500  .000171   .199429  .000186  I -.3805425  .0000132  1.7863 0.0080  I   -15.454     .511    -7.179     .208  -.049300   .198600  -.3807100   -15.900    -8.400  
+93 622 49160.00 I  -.051507  .000202   .200208  .000178  I -.3823984  .0000090  1.9333 0.0076  I   -15.366     .512    -7.253     .173  -.051300   .199300  -.3825600   -15.800    -8.200  
+93 623 49161.00 I  -.053139  .000189   .201109  .000146  I -.3844143  .0000076  2.0959 0.0062  I   -15.564     .512    -7.291     .173  -.053000   .200200  -.3845700   -15.900    -7.900  
+93 624 49162.00 I  -.054384  .000192   .202161  .000157  I -.3865801  .0000084  2.2283 0.0057  I   -15.910     .399    -7.107     .145  -.054400   .201400  -.3867400   -16.000    -7.700  
+93 625 49163.00 I  -.055378  .000192   .203307  .000153  I -.3888537  .0000085  2.3092 0.0060  I   -16.328     .399    -6.821     .145  -.055600   .202600  -.3890300   -16.400    -7.400  
+93 626 49164.00 I  -.056273  .000190   .204479  .000159  I -.3911756  .0000087  2.3215 0.0057  I   -16.764     .420    -6.642     .134  -.056600   .203800  -.3913600   -16.800    -7.200  
+93 627 49165.00 I  -.057333  .000176   .205615  .000149  I -.3934676  .0000075  2.2464 0.0057  I   -17.057     .286    -6.586     .298  -.057700   .204800  -.3936400   -17.200    -7.100  
+93 628 49166.00 I  -.058551  .000209   .206700  .000193  I -.3956403  .0000073  2.0868 0.0054  I   -17.229     .138    -6.567     .298  -.058800   .205900  -.3958000   -17.700    -7.000  
+93 629 49167.00 I  -.059828  .000181   .207760  .000201  I -.3976239  .0000077  1.8751 0.0050  I   -17.427     .138    -6.535     .298  -.060000   .206900  -.3977900   -18.100    -7.100  
+93 630 49168.00 I  -.061112  .000200   .208846  .000269  I -.3993921  .0000069  1.6680 0.0055  I   -17.718     .182    -6.527     .298  -.061200   .208100  -.3995700   -18.300    -7.100  
+93 7 1 49169.00 I  -.062437  .000190   .210047  .000264  I  .5990240  .0000079  1.5090 0.0053  I   -18.047     .182    -6.655     .298  -.062300   .209300   .5988300   -18.400    -7.200  
+93 7 2 49170.00 I  -.063739  .000190   .211328  .000263  I  .5975692  .0000080  1.4121 0.0050  I   -18.203     .182    -6.887     .298  -.063500   .210600   .5974000   -18.400    -7.300  
+93 7 3 49171.00 I  -.064926  .000177   .212596  .000240  I  .5961771  .0000060  1.3833 0.0058  I   -18.031     .105    -7.056     .298  -.064700   .211800   .5960200   -18.200    -7.300  
+93 7 4 49172.00 I  -.065948  .000087   .213794  .000140  I  .5947836  .0000084  1.4115 0.0050  I   -17.620     .791    -7.038     .298  -.065800   .213000   .5946400   -17.900    -7.300  
+93 7 5 49173.00 I  -.066764  .000179   .214898  .000198  I  .5933425  .0000079  1.4745 0.0080  I   -17.220     .791    -6.855     .187  -.066800   .214100   .5932100   -17.800    -7.300  
+93 7 6 49174.00 I  -.067351  .000224   .215906  .000200  I  .5918315  .0000136  1.5469 0.0081  I   -17.022     .107    -6.637     .209  -.067600   .215200   .5917300   -17.700    -7.300  
+93 7 7 49175.00 I  -.067751  .000238   .216822  .000198  I  .5902532  .0000142  1.6057 0.0102  I   -17.051     .151    -6.473     .171  -.068100   .216100   .5901800   -17.700    -7.200  
+93 7 8 49176.00 I  -.068022  .000234   .217671  .000199  I  .5886301  .0000151  1.6344 0.0108  I   -17.247     .151    -6.350     .171  -.068300   .216800   .5885900   -17.900    -7.100  
+93 7 9 49177.00 I  -.068127  .000242   .218538  .000195  I  .5869959  .0000163  1.6288 0.0107  I   -17.535     .151    -6.400     .171  -.068400   .217600   .5869700   -18.400    -6.900  
+93 710 49178.00 I  -.068091  .000226   .219466  .000175  I  .5853818  .0000151  1.5955 0.0113  I   -17.884     .151    -6.558     .171  -.068500   .218600   .5853600   -18.800    -6.900  
+93 711 49179.00 I  -.068029  .000196   .220478  .000137  I  .5838113  .0000157  1.5430 0.0093  I   -18.225     .190    -6.700     .142  -.068500   .219600   .5837500   -19.300    -6.900  
+93 712 49180.00 I  -.068167  .000183   .221597  .000096  I  .5822997  .0000108  1.4789 0.0091  I   -18.552     .252    -6.842     .298  -.068700   .220900   .5821800   -19.800    -6.900  
+93 713 49181.00 I  -.068638  .000162   .222851  .000095  I  .5808530  .0000093  1.4162 0.0072  I   -18.970     .295    -7.001     .140  -.069000   .222300   .5806900   -20.100    -7.000  
+93 714 49182.00 I  -.069396  .000163   .224261  .000143  I  .5794633  .0000096  1.3654 0.0067  I   -19.529     .256    -7.099     .205  -.069500   .223800   .5792900   -20.300    -7.100  
+93 715 49183.00 I  -.070293  .000161   .225760  .000142  I  .5781232  .0000096  1.3117 0.0068  I   -20.135     .259    -7.114     .203  -.070200   .225100   .5779600   -20.400    -7.300  
+93 716 49184.00 I  -.071136  .000161   .227328  .000144  I  .5768387  .0000096  1.2618 0.0069  I   -20.478     .259    -7.131     .203  -.071100   .226600   .5767200   -20.300    -7.400  
+93 717 49185.00 I  -.071804  .000215   .228951  .000177  I  .5755861  .0000099  1.2525 0.0088  I   -20.439     .271    -7.089     .222  -.071900   .228000   .5755000   -20.200    -7.500  
+93 718 49186.00 I  -.072163  .000256   .230617  .000215  I  .5743088  .0000147  1.3178 0.0070  I   -20.201     .339    -7.122     .204  -.072400   .229700   .5742500   -20.100    -7.500  
+93 719 49187.00 I  -.072376  .000219   .232328  .000235  I  .5729212  .0000100  1.4709 0.0088  I   -19.960     .315    -7.267     .179  -.072800   .231500   .5728500   -20.100    -7.500  
+93 720 49188.00 I  -.072659  .000216   .234071  .000224  I  .5713467  .0000096  1.6847 0.0062  I   -19.857     .317    -7.238     .102  -.073100   .233300   .5712500   -20.100    -7.400  
+93 721 49189.00 I  -.073162  .000228   .235815  .000201  I  .5695413  .0000074  1.9299 0.0060  I   -20.031     .327    -6.900     .298  -.073400   .235100   .5694000   -20.300    -7.300  
+93 722 49190.00 I  -.073761  .000231   .237549  .000190  I  .5674973  .0000071  2.1440 0.0055  I   -20.523     .327    -6.462     .298  -.073800   .236700   .5673200   -20.700    -7.100  
+93 723 49191.00 I  -.074331  .000234   .239305  .000193  I  .5652901  .0000082  2.2478 0.0059  I   -21.227     .327    -6.173     .298  -.074300   .238300   .5651100   -21.100    -7.000  
+93 724 49192.00 I  -.074925  .000150   .241023  .000158  I  .5630454  .0000093  2.2204 0.0103  I   -21.856     .147    -6.120     .298  -.074900   .239900   .5628700   -21.500    -7.000  
+93 725 49193.00 I  -.075668  .000146   .242640  .000135  I  .5608853  .0000190  2.0849 0.0133  I   -22.149     .791    -6.240     .298  -.075600   .241500   .5607100   -22.000    -6.900  
+93 726 49194.00 I  -.076631  .000150   .244148  .000158  I  .5588963  .0000250  1.8872 0.0128  I   -22.081     .791    -6.417     .298  -.076500   .243100   .5587400   -22.400    -7.000  
+93 727 49195.00 I  -.077778  .000133   .245624  .000153  I  .5571142  .0000171  1.6798 0.0151  I   -21.870     .159    -6.574     .115  -.077700   .244800   .5569700   -22.500    -7.000  
+93 728 49196.00 I  -.078981  .000129   .247191  .000156  I  .5555234  .0000171  1.5125 0.0119  I   -21.791     .186    -6.700     .121  -.078900   .246600   .5553900   -22.600    -7.200  
+93 729 49197.00 I  -.080118  .000138   .248935  .000159  I  .5540600  .0000166  1.4327 0.0118  I   -21.953     .186    -6.824     .121  -.080000   .248400   .5539300   -22.500    -7.200  
+93 730 49198.00 I  -.081227  .000132   .250760  .000163  I  .5526319  .0000163  1.4312 0.0115  I   -22.231     .186    -7.024     .121  -.081100   .250200   .5525200   -22.400    -7.300  
+93 731 49199.00 I  -.082366  .000211   .252510  .000201  I  .5511802  .0000159  1.4819 0.0099  I   -22.339     .186    -7.165     .121  -.082200   .252100   .5510800   -22.100    -7.300  
+93 8 1 49200.00 I  -.083461  .000233   .254212  .000223  I  .5496530  .0000113  1.5778 0.0093  I   -22.196     .206    -7.121     .122  -.083200   .253900   .5495600   -22.000    -7.300  
+93 8 2 49201.00 I  -.084451  .000305   .255956  .000259  I  .5480175  .0000096  1.6950 0.0094  I   -21.996     .162    -6.932     .298  -.084100   .255600   .5479300   -21.900    -7.200  
+93 8 3 49202.00 I  -.085351  .000369   .257807  .000301  I  .5462633  .0000149  1.8114 0.0088  I   -21.952     .791    -6.722     .298  -.085100   .257300   .5461500   -22.000    -7.000  
+93 8 4 49203.00 I  -.086260  .000372   .259752  .000304  I  .5443991  .0000147  1.9146 0.0105  I   -22.146     .134    -6.650     .298  -.086300   .259100   .5442500   -22.300    -6.900  
+93 8 5 49204.00 I  -.087499  .000376   .261732  .000301  I  .5424427  .0000147  1.9919 0.0104  I   -22.525     .134    -6.750     .298  -.087800   .261100   .5422800   -22.700    -6.900  
+93 8 6 49205.00 I  -.089023  .000378   .263722  .000271  I  .5404353  .0000146  2.0093 0.0118  I   -22.986     .134    -6.888     .298  -.089300   .263000   .5402800   -22.600    -6.700  
+93 8 7 49206.00 I  -.090640  .000330   .265695  .000231  I  .5384455  .0000185  1.9624 0.0138  I   -23.322     .124    -6.985     .298  -.090700   .265000   .5382800   -23.000    -6.800  
+93 8 8 49207.00 I  -.092153  .000247   .267658  .000183  I  .5365244  .0000235  1.8739 0.0165  I   -23.344     .279    -7.016     .298  -.092100   .267000   .5363500   -23.500    -6.900  
+93 8 9 49208.00 I  -.093437  .000225   .269647  .000135  I  .5347066  .0000273  1.7586 0.0187  I   -23.125     .326    -7.016     .298  -.093100   .268900   .5345300   -23.800    -7.200  
+93 810 49209.00 I  -.094417  .000248   .271698  .000134  I  .5330118  .0000291  1.6295 0.0204  I   -23.045     .316    -7.069     .298  -.094100   .270900   .5328700   -24.100    -7.400  
+93 811 49210.00 I  -.095113  .000241   .273838  .000134  I  .5314421  .0000302  1.5168 0.0224  I   -23.423     .316    -7.159     .298  -.094700   .273000   .5313200   -24.200    -7.700  
+93 812 49211.00 I  -.095676  .000242   .276076  .000128  I  .5299608  .0000340  1.4562 0.0212  I   -24.027     .316    -7.143     .298  -.095300   .275200   .5298800   -24.200    -8.000  
+93 813 49212.00 I  -.096200  .000228   .278363  .000122  I  .5285077  .0000299  1.4617 0.0216  I   -24.426     .316    -7.005     .298  -.095700   .277400   .5284700   -24.100    -8.100  
+93 814 49213.00 I  -.096752  .000187   .280621  .000106  I  .5270114  .0000266  1.5454 0.0185  I   -24.397     .260    -6.890     .298  -.096300   .279500   .5270100   -23.900    -8.200  
+93 815 49214.00 I  -.097412  .000160   .282790  .000094  I  .5253905  .0000217  1.7083 0.0186  I   -24.072     .110    -6.957     .298  -.097000   .281600   .5254000   -23.800    -8.200  
+93 816 49215.00 I  -.098178  .000209   .284807  .000167  I  .5235760  .0000260  1.9276 0.0133  I   -23.742     .309    -7.175     .167  -.097800   .283500   .5235700   -23.700    -8.100  
+93 817 49216.00 I  -.098964  .000158   .286624  .000135  I  .5215295  .0000155  2.1641 0.0144  I   -23.598     .444    -7.312     .185  -.098800   .285400   .5214800   -23.700    -8.100  
+93 818 49217.00 I  -.099720  .000155   .288258  .000134  I  .5192544  .0000125  2.3806 0.0102  I   -23.687     .406    -7.198     .169  -.099800   .287100   .5191600   -23.900    -7.900  
+93 819 49218.00 I  -.100408  .000153   .289796  .000136  I  .5167887  .0000134  2.5358 0.0090  I   -23.953     .406    -6.829     .169  -.100700   .288800   .5166500   -24.200    -7.700  
+93 820 49219.00 I  -.101032  .000140   .291317  .000134  I  .5142204  .0000129  2.5781 0.0093  I   -24.412     .406    -6.574     .169  -.101400   .290500   .5140600   -24.600    -7.600  
+93 821 49220.00 I  -.101549  .000162   .292889  .000180  I  .5116758  .0000128  2.4904 0.0095  I   -24.882     .468    -6.507     .190  -.101800   .292100   .5115200   -25.000    -7.500  
+93 822 49221.00 I  -.101885  .000154   .294559  .000187  I  .5092718  .0000140  2.3059 0.0082  I   -25.156     .466    -6.484     .157  -.102100   .293700   .5091100   -25.300    -7.400  
+93 823 49222.00 I  -.102012  .000155   .296341  .000245  I  .5070777  .0000102  2.0803 0.0109  I   -25.153     .330    -6.494     .109  -.102100   .295500   .5069000   -25.500    -7.400  
+93 824 49223.00 I  -.101942  .000202   .298233  .000312  I  .5051082  .0000166  1.8639 0.0091  I   -24.816     .777    -6.634     .290  -.102000   .297300   .5049300   -25.500    -7.300  
+93 825 49224.00 I  -.101719  .000205   .300269  .000311  I  .5033333  .0000151  1.6974 0.0109  I   -24.203     .777    -6.953     .290  -.101700   .299400   .5031500   -25.400    -7.400  
+93 826 49225.00 I  -.101402  .000213   .302496  .000320  I  .5016905  .0000141  1.5997 0.0102  I   -23.690     .777    -7.229     .290  -.101500   .301700   .5015000   -25.100    -7.400  
+93 827 49226.00 I  -.101072  .000241   .304851  .000309  I  .5001094  .0000138  1.5756 0.0104  I   -23.590     .777    -7.299     .290  -.101100   .304100   .4999300   -24.700    -7.300  
+93 828 49227.00 I  -.100733  .000300   .307233  .000306  I  .4985168  .0000152  1.6191 0.0107  I   -23.844     .862    -7.191     .328  -.100800   .306500   .4983600   -24.400    -7.200  
+93 829 49228.00 I  -.100362  .000302   .309577  .000261  I  .4968559  .0000163  1.7086 0.0103  I   -24.192     .739    -7.003     .368  -.100500   .308900   .4967200   -24.100    -7.100  
+93 830 49229.00 I  -.099972  .000246   .311833  .000224  I  .4950917  .0000140  1.8219 0.0106  I   -24.464     .449    -6.777     .288  -.100100   .311100   .4949600   -24.000    -6.900  
+93 831 49230.00 I  -.099671  .000258   .313947  .000242  I  .4932110  .0000135  1.9384 0.0098  I   -24.611     .449    -6.508     .288  -.099800   .313100   .4930800   -24.000    -6.700  
+93 9 1 49231.00 I  -.099584  .000250   .315892  .000248  I  .4912200  .0000137  2.0395 0.0101  I   -24.610     .446    -6.203     .258  -.099500   .315100   .4910800   -24.200    -6.600  
+93 9 2 49232.00 I  -.099550  .000241   .317749  .000249  I  .4891461  .0000149  2.0983 0.0102  I   -24.508     .446    -6.013     .258  -.099300   .316900   .4890000   -24.500    -6.600  
+93 9 3 49233.00 I  -.099476  .000251   .319598  .000249  I  .4870423  .0000152  2.1003 0.0101  I   -24.446     .446    -6.060     .258  -.099200   .318800   .4868900   -24.800    -6.700  
+93 9 4 49234.00 I  -.099417  .000231   .321454  .000216  I  .4849612  .0000136  2.0551 0.0116  I   -24.520     .567    -6.269     .187  -.099200   .320600   .4847900   -25.200    -6.800  
+93 9 5 49235.00 I  -.099508  .000242   .323283  .000169  I  .4829426  .0000176  1.9783 0.0092  I   -24.583     .317    -6.497     .298  -.099400   .322300   .4827600   -25.600    -6.800  
+93 9 6 49236.00 I  -.099829  .000223   .325038  .000160  I  .4810086  .0000123  1.8895 0.0107  I   -24.514     .261    -6.687     .298  -.099800   .324000   .4808200   -25.600    -7.200  
+93 9 7 49237.00 I  -.100319  .000228   .326663  .000149  I  .4791607  .0000120  1.8095 0.0078  I   -24.510     .791    -6.907     .298  -.100300   .325600   .4789900   -25.600    -7.500  
+93 9 8 49238.00 I  -.100783  .000217   .328160  .000144  I  .4773845  .0000097  1.7449 0.0075  I   -24.824     .791    -7.199     .298  -.100900   .327100   .4772400   -25.400    -7.700  
+93 9 9 49239.00 I  -.101141  .000274   .329689  .000144  I  .4756590  .0000091  1.7159 0.0077  I   -25.359     .791    -7.424     .298  -.101300   .328700   .4755400   -25.100    -7.900  
+93 910 49240.00 I  -.101269  .000250   .331310  .000159  I  .4739299  .0000120  1.7553 0.0072  I   -25.685     .791    -7.440     .298  -.101400   .330300   .4738300   -24.800    -7.900  
+93 911 49241.00 I  -.101089  .000237   .333037  .000156  I  .4721218  .0000111  1.8747 0.0085  I   -25.513     .791    -7.296     .298  -.101200   .332100   .4720200   -24.600    -8.000  
+93 912 49242.00 I  -.100565  .000275   .334903  .000139  I  .4701547  .0000119  2.0716 0.0067  I   -25.009     .791    -7.185     .298  -.100600   .334000   .4700600   -24.300    -7.900  
+93 913 49243.00 I  -.099728  .000235   .336973  .000117  I  .4679612  .0000076  2.3206 0.0079  I   -24.590     .177    -7.190     .298  -.099800   .336100   .4678600   -24.300    -7.700  
+93 914 49244.00 I  -.098778  .000246   .339250  .000156  I  .4655123  .0000103  2.5730 0.0065  I   -24.535     .132    -7.185     .149  -.099000   .338400   .4654000   -24.400    -7.600  
+93 915 49245.00 I  -.097920  .000227   .341636  .000166  I  .4628345  .0000106  2.7673 0.0070  I   -24.830     .122    -7.050     .155  -.098100   .340900   .4627000   -24.800    -7.500  
+93 916 49246.00 I  -.097307  .000211   .344011  .000146  I  .4600161  .0000095  2.8462 0.0072  I   -25.253     .122    -6.860     .155  -.097400   .343300   .4598700   -25.200    -7.300  
+93 917 49247.00 I  -.096914  .000224   .346228  .000166  I  .4571881  .0000097  2.7869 0.0067  I   -25.517     .122    -6.685     .155  -.096900   .345600   .4570400   -25.700    -7.100  
+93 918 49248.00 I  -.096709  .000224   .348151  .000175  I  .4544796  .0000095  2.6157 0.0099  I   -25.554     .122    -6.637     .155  -.096700   .347600   .4543300   -26.200    -7.000  
+93 919 49249.00 I  -.096650  .000225   .349767  .000236  I  .4519736  .0000173  2.3938 0.0065  I   -25.586     .791    -6.634     .183  -.096700   .349400   .4518200   -26.500    -7.100  
+93 920 49250.00 I  -.096757  .000183   .351130  .000192  I  .4496859  .0000089  2.1901 0.0101  I   -25.778     .255    -6.554     .220  -.096800   .350800   .4495400   -26.700    -7.000  
+93 921 49251.00 I  -.096961  .000189   .352364  .000187  I  .4475688  .0000106  2.0603 0.0069  I   -25.920     .481    -6.489     .267  -.097100   .352000   .4474300   -26.700    -7.000  
+93 922 49252.00 I  -.097137  .000166   .353660  .000186  I  .4455356  .0000106  2.0195 0.0076  I   -25.653     .608    -6.490     .265  -.097300   .353200   .4454100   -26.500    -7.100  
+93 923 49253.00 I  -.097226  .000156   .355198  .000177  I  .4435103  .0000108  2.0370 0.0076  I   -24.982     .608    -6.457     .265  -.097300   .354400   .4434000   -26.200    -7.000  
+93 924 49254.00 I  -.097154  .000176   .356944  .000175  I  .4414471  .0000109  2.0979 0.0074  I   -24.493     .608    -6.516     .265  -.097200   .355900   .4413300   -25.800    -7.000  
+93 925 49255.00 I  -.096846  .000165   .358816  .000183  I  .4393042  .0000102  2.1898 0.0125  I   -24.450     .608    -6.519     .265  -.096800   .357700   .4391800   -25.400    -6.900  
+93 926 49256.00 I  -.096384  .000227   .360749  .000236  I  .4370666  .0000226  2.2843 0.0103  I   -24.583     .645    -6.379     .241  -.096400   .359600   .4369400   -25.000    -6.800  
+93 927 49257.00 I  -.095887  .000291   .362707  .000215  I  .4347408  .0000180  2.3632 0.0122  I   -24.665     .687    -6.258     .181  -.095900   .361700   .4346100   -24.800    -6.700  
+93 928 49258.00 I  -.095487  .000216   .364679  .000178  I  .4323504  .0000092  2.4115 0.0100  I   -24.652     .633    -6.169     .163  -.095600   .363900   .4322300   -24.800    -6.500  
+93 929 49259.00 I  -.095344  .000215   .366640  .000172  I  .4299340  .0000089  2.4112 0.0064  I   -24.637     .829    -6.102     .189  -.095400   .366000   .4298200   -24.900    -6.500  
+93 930 49260.00 I  -.095565  .000219   .368552  .000172  I  .4275414  .0000088  2.3708 0.0063  I   -24.633     .829    -6.150     .189  -.095400   .368000   .4274400   -25.100    -6.500  
+9310 1 49261.00 I  -.095760  .000218   .370405  .000176  I  .4251976  .0000088  2.3148 0.0056  I   -24.496     .829    -6.232     .189  -.095400   .369900   .4250900   -25.300    -6.600  
+9310 2 49262.00 I  -.095500  .000226   .372243  .000166  I  .4229157  .0000070  2.2470 0.0061  I   -24.490     .908    -6.368     .207  -.095300   .371700   .4228100   -25.400    -6.700  
+9310 3 49263.00 I  -.094925  .000203   .374109  .000172  I  .4207044  .0000084  2.1768 0.0046  I   -24.506     .986    -6.599     .250  -.094900   .373400   .4206100   -25.400    -6.900  
+9310 4 49264.00 I  -.094225  .000169   .376028  .000164  I  .4185569  .0000061  2.1223 0.0083  I   -24.422     .918    -6.768     .195  -.094300   .375200   .4184500   -25.300    -7.100  
+9310 5 49265.00 I  -.093568  .000206   .377975  .000149  I  .4164492  .0000144  2.0995 0.0088  I   -24.311     .492    -6.860     .298  -.093900   .377100   .4163300   -25.100    -7.300  
+9310 6 49266.00 I  -.093027  .000228   .379897  .000142  I  .4143430  .0000165  2.1215 0.0111  I   -24.354     .530    -6.912     .298  -.093500   .378900   .4142100   -24.600    -7.400  
+9310 7 49267.00 I  -.092536  .000212   .381742  .000134  I  .4121963  .0000169  2.1732 0.0118  I   -24.537     .530    -6.871     .298  -.092800   .380700   .4120700   -24.200    -7.400  
+9310 8 49268.00 I  -.091935  .000197   .383500  .000125  I  .4099864  .0000168  2.2556 0.0113  I   -24.531     .530    -6.708     .298  -.092100   .382500   .4098600   -23.900    -7.400  
+9310 9 49269.00 I  -.091076  .000194   .385238  .000194  I  .4076651  .0000151  2.3978 0.0115  I   -24.249     .530    -6.498     .298  -.091100   .384200   .4075300   -23.500    -7.300  
+931010 49270.00 I  -.089912  .000169   .387006  .000184  I  .4051709  .0000157  2.5995 0.0102  I   -23.848     .538    -6.358     .298  -.089900   .386000   .4050400   -23.400    -7.200  
+931011 49271.00 I  -.088541  .000172   .388858  .000201  I  .4024546  .0000137  2.8358 0.0094  I   -23.561     .363    -6.329     .116  -.088500   .387900   .4023200   -23.400    -6.900  
+931012 49272.00 I  -.087093  .000176   .390877  .000231  I  .3995030  .0000104  3.0611 0.0085  I   -23.573     .294    -6.317     .157  -.087000   .390000   .3993700   -23.600    -6.700  
+931013 49273.00 I  -.085687  .000145   .393093  .000231  I  .3963491  .0000102  3.2365 0.0074  I   -23.811     .318    -6.234     .139  -.085600   .392300   .3962100   -23.900    -6.600  
+931014 49274.00 I  -.084433  .000167   .395382  .000234  I  .3930678  .0000106  3.2986 0.0074  I   -24.012     .318    -6.229     .139  -.084300   .394500   .3929500   -24.200    -6.400  
+931015 49275.00 I  -.083389  .000175   .397498  .000232  I  .3898032  .0000106  3.2069 0.0063  I   -23.934     .318    -6.287     .139  -.083200   .396600   .3897000   -24.600    -6.300  
+931016 49276.00 I  -.082597  .000163   .399324  .000180  I  .3866909  .0000067  3.0044 0.0058  I   -23.489     .352    -6.331     .155  -.082400   .398400   .3865900   -24.800    -6.300  
+931017 49277.00 I  -.082066  .000161   .400879  .000175  I  .3838085  .0000048  2.7596 0.0040  I   -23.037     .383    -6.208     .134  -.081800   .399900   .3837000   -24.900    -6.300  
+931018 49278.00 I  -.081697  .000155   .402206  .000165  I  .3811629  .0000044  2.5414 0.0033  I   -23.032     .313    -5.863     .121  -.081400   .401200   .3810500   -24.800    -6.300  
+931019 49279.00 I  -.081249  .000152   .403378  .000172  I  .3787015  .0000044  2.3959 0.0030  I   -23.383     .248    -5.557     .125  -.081000   .402400   .3785800   -24.600    -6.300  
+931020 49280.00 I  -.080501  .000142   .404517  .000178  I  .3763403  .0000040  2.3427 0.0030  I   -23.567     .248    -5.575     .125  -.080700   .403700   .3762200   -24.200    -6.300  
+931021 49281.00 I  -.079780  .000138   .405850  .000185  I  .3739861  .0000042  2.3794 0.0029  I   -23.227     .248    -5.774     .125  -.080300   .405100   .3738500   -23.600    -6.300  
+931022 49282.00 I  -.079255  .000139   .407354  .000188  I  .3715641  .0000041  2.4684 0.0028  I   -22.639     .248    -5.927     .125  -.079800   .406700   .3714300   -23.000    -6.300  
+931023 49283.00 I  -.078848  .000146   .408918  .000222  I  .3690462  .0000038  2.5669 0.0033  I   -22.252     .116    -5.911     .125  -.079300   .408300   .3689200   -22.500    -6.300  
+931024 49284.00 I  -.078395  .000174   .410502  .000250  I  .3664339  .0000051  2.6548 0.0040  I   -22.117     .791    -5.793     .298  -.078600   .410000   .3663200   -22.100    -6.200  
+931025 49285.00 I  -.077753  .000194   .412128  .000213  I  .3637438  .0000071  2.7212 0.0045  I   -21.998     .158    -5.717     .298  -.077900   .411700   .3636400   -21.900    -6.200  
+931026 49286.00 I  -.076914  .000191   .413836  .000207  I  .3610009  .0000075  2.7592 0.0052  I   -21.814     .158    -5.684     .298  -.077100   .413400   .3609000   -21.900    -6.100  
+931027 49287.00 I  -.076031  .000218   .415576  .000201  I  .3582377  .0000077  2.7601 0.0054  I   -21.706     .158    -5.613     .298  -.076400   .415100   .3581400   -22.000    -6.100  
+931028 49288.00 I  -.075370  .000203   .417185  .000175  I  .3554951  .0000077  2.7178 0.0055  I   -21.801     .158    -5.524     .298  -.075800   .416700   .3554000   -22.300    -6.000  
+931029 49289.00 I  -.074954  .000197   .418609  .000151  I  .3528138  .0000079  2.6404 0.0054  I   -22.010     .158    -5.508     .298  -.075300   .418000   .3527000   -22.500    -5.900  
+931030 49290.00 I  -.074635  .000306   .419832  .000127  I  .3502215  .0000077  2.5413 0.0071  I   -22.205     .184    -5.578     .298  -.074900   .419100   .3500800   -22.700    -6.000  
+931031 49291.00 I  -.074213  .000306   .420862  .000122  I  .3477349  .0000119  2.4312 0.0066  I   -22.328     .136    -5.637     .141  -.074400   .420000   .3475800   -22.700    -6.000  
+9311 1 49292.00 I  -.073492  .000322   .421760  .000135  I  .3453578  .0000106  2.3250 0.0079  I   -22.310     .137    -5.610     .125  -.073600   .420800   .3451900   -22.600    -6.000  
+9311 2 49293.00 I  -.072270  .000336   .422619  .000171  I  .3430772  .0000103  2.2420 0.0075  I   -22.086     .131    -5.541     .113  -.072500   .421500   .3429200   -22.400    -6.100  
+9311 3 49294.00 I  -.070455  .000327   .423522  .000174  I  .3408636  .0000105  2.1897 0.0074  I   -21.692     .131    -5.534     .113  -.071000   .422300   .3407300   -22.000    -6.000  
+9311 4 49295.00 I  -.068458  .000329   .424564  .000177  I  .3386838  .0000105  2.1794 0.0077  I   -21.259     .131    -5.651     .113  -.069100   .423400   .3385700   -21.800    -6.200  
+9311 5 49296.00 I  -.066409  .000337   .425838  .000177  I  .3364799  .0000113  2.2439 0.0078  I   -20.892     .131    -5.748     .113  -.066900   .424700   .3363600   -21.500    -6.000  
+9311 6 49297.00 I  -.064303  .000265   .427336  .000206  I  .3341689  .0000115  2.3895 0.0079  I   -20.567     .125    -5.708     .298  -.064600   .426300   .3340500   -21.200    -5.800  
+9311 7 49298.00 I  -.062188  .000220   .428971  .000218  I  .3316825  .0000109  2.5901 0.0068  I   -20.264     .332    -5.554     .298  -.062300   .428100   .3315700   -21.100    -5.600  
+9311 8 49299.00 I  -.060083  .000174   .430629  .000147  I  .3289829  .0000071  2.8082 0.0064  I   -20.108     .451    -5.336     .298  -.060100   .429800   .3288600   -21.200    -5.400  
+9311 9 49300.00 I  -.058051  .000181   .432202  .000118  I  .3260761  .0000068  2.9964 0.0048  I   -20.288     .451    -5.072     .298  -.058100   .431400   .3259500   -21.400    -5.300  
+931110 49301.00 I  -.056232  .000183   .433615  .000131  I  .3230175  .0000065  3.1022 0.0048  I   -20.836     .451    -4.786     .298  -.056400   .432900   .3229000   -21.600    -5.300  
+931111 49302.00 I  -.054719  .000168   .434848  .000140  I  .3199125  .0000068  3.0854 0.0046  I   -21.361     .451    -4.585     .298  -.054900   .434200   .3197900   -21.800    -5.200  
+931112 49303.00 I  -.053383  .000156   .435925  .000138  I  .3168850  .0000066  2.9536 0.0052  I   -21.490     .451    -4.602     .298  -.053500   .435300   .3167600   -22.000    -5.100  
+931113 49304.00 I  -.052073  .000128   .436873  .000134  I  .3140291  .0000078  2.7505 0.0103  I   -21.142     .446    -4.799     .298  -.052100   .436100   .3139000   -22.000    -4.900  
+931114 49305.00 I  -.050757  .000171   .437726  .000152  I  .3113888  .0000196  2.5331 0.0062  I   -20.615     .791    -4.935     .298  -.050800   .436900   .3112500   -21.800    -4.900  
+931115 49306.00 I  -.049472  .000175   .438542  .000145  I  .3089486  .0000096  2.3585 0.0109  I   -20.322     .791    -4.825     .298  -.049500   .437600   .3088100   -21.500    -4.900  
+931116 49307.00 I  -.048279  .000162   .439395  .000150  I  .3066469  .0000096  2.2587 0.0064  I   -20.309     .791    -4.579     .298  -.048500   .438500   .3065200   -21.000    -4.900  
+931117 49308.00 I  -.047288  .000169   .440342  .000164  I  .3044064  .0000084  2.2332 0.0064  I   -20.213     .791    -4.482     .298  -.047700   .439400   .3042900   -20.400    -4.800  
+931118 49309.00 I  -.046610  .000169   .441395  .000156  I  .3021613  .0000085  2.2653 0.0060  I   -19.782     .791    -4.655     .298  -.047000   .440400   .3020400   -19.900    -4.800  
+931119 49310.00 I  -.046115  .000190   .442500  .000154  I  .2998652  .0000086  2.3293 0.0073  I   -19.221     .791    -4.918     .298  -.046400   .441500   .2997400   -19.400    -4.800  
+931120 49311.00 I  -.045686  .000223   .443609  .000166  I  .2975016  .0000118  2.3966 0.0103  I   -18.897     .791    -5.055     .298  -.045900   .442600   .2973700   -19.000    -4.800  
+931121 49312.00 I  -.045176  .000239   .444669  .000186  I  .2950769  .0000188  2.4494 0.0110  I   -18.869     .791    -5.032     .298  -.045300   .443700   .2949600   -18.800    -4.700  
+931122 49313.00 I  -.044412  .000252   .445671  .000164  I  .2926107  .0000185  2.4787 0.0133  I   -18.924     .791    -4.930     .298  -.044600   .444800   .2925000   -18.800    -4.800  
+931123 49314.00 I  -.043359  .000254   .446638  .000168  I  .2901289  .0000187  2.4798 0.0134  I   -18.947     .791    -4.794     .298  -.043700   .445900   .2900300   -19.000    -4.800  
+931124 49315.00 I  -.042190  .000257   .447596  .000157  I  .2876619  .0000195  2.4483 0.0134  I   -19.013     .791    -4.619     .298  -.042700   .447000   .2875600   -19.200    -4.900  
+931125 49316.00 I  -.041254  .000245   .448548  .000155  I  .2852456  .0000191  2.3768 0.0133  I   -19.151     .791    -4.431     .298  -.041700   .448000   .2851600   -19.500    -4.900  
+931126 49317.00 I  -.040560  .000237   .449434  .000162  I  .2829184  .0000182  2.2751 0.0109  I   -19.261     .791    -4.283     .298  -.040900   .448900   .2828300   -19.800    -4.900  
+931127 49318.00 I  -.039980  .000226   .450216  .000121  I  .2806996  .0000106  2.1610 0.0107  I   -19.290     .791    -4.178     .298  -.040100   .449600   .2806200   -19.800    -4.900  
+931128 49319.00 I  -.039440  .000209   .450907  .000127  I  .2785978  .0000113  2.0429 0.0074  I   -19.308     .143    -4.071     .298  -.039300   .450300   .2785100   -19.800    -4.800  
+931129 49320.00 I  -.038813  .000222   .451524  .000099  I  .2766129  .0000102  1.9275 0.0075  I   -19.336     .219    -3.958     .298  -.038600   .450800   .2765200   -19.500    -4.700  
+931130 49321.00 I  -.037886  .000229   .452118  .000088  I  .2747398  .0000098  1.8211 0.0070  I   -19.259     .191    -3.909     .298  -.037700   .451300   .2746400   -19.200    -4.600  
+9312 1 49322.00 I  -.036491  .000226   .452767  .000087  I  .2729459  .0000095  1.7893 0.0061  I   -18.993     .191    -3.986     .298  -.036600   .451900   .2728200   -18.800    -4.500  
+9312 2 49323.00 I  -.035037  .000221   .453502  .000081  I  .2711337  .0000074  1.8401 0.0060  I   -18.689     .191    -4.162     .298  -.035300   .452600   .2710000   -18.400    -4.400  
+9312 3 49324.00 I  -.033629  .000216   .454320  .000080  I  .2692482  .0000074  1.9434 0.0065  I   -18.501     .191    -4.304     .298  -.033800   .453400   .2690900   -18.300    -4.300  
+9312 4 49325.00 I  -.032184  .000207   .455219  .000093  I  .2672266  .0000108  2.1076 0.0078  I   -18.472     .211    -4.324     .298  -.032100   .454600   .2671000   -18.100    -4.000  
+9312 5 49326.00 I  -.030695  .000292   .456183  .000199  I  .2650228  .0000137  2.3025 0.0078  I   -18.535     .791    -4.221     .298  -.030600   .455600   .2648700   -18.200    -4.000  
+9312 6 49327.00 I  -.029197  .000284   .457189  .000184  I  .2626230  .0000113  2.4933 0.0088  I   -18.592     .791    -4.020     .298  -.029000   .456600   .2624600   -18.400    -4.000  
+9312 7 49328.00 I  -.027689  .000286   .458224  .000189  I  .2600475  .0000110  2.6501 0.0079  I   -18.624     .791    -3.748     .298  -.027600   .457600   .2598800   -18.700    -3.900  
+9312 8 49329.00 I  -.026169  .000294   .459296  .000202  I  .2573503  .0000110  2.7245 0.0080  I   -18.670     .791    -3.454     .298  -.026300   .458600   .2572000   -19.000    -4.000  
+9312 9 49330.00 I  -.024876  .000313   .460349  .000201  I  .2546337  .0000115  2.6932 0.0081  I   -18.735     .791    -3.262     .298  -.025000   .459500   .2545100   -19.300    -4.000  
+931210 49331.00 I  -.023654  .000316   .461368  .000221  I  .2519902  .0000120  2.5829 0.0089  I   -18.736     .791    -3.232     .298  -.023700   .460400   .2518700   -19.400    -4.200  
+931211 49332.00 I  -.022373  .000323   .462389  .000273  I  .2494811  .0000135  2.4331 0.0091  I   -18.590     .791    -3.287     .115  -.022400   .461400   .2493700   -19.300    -4.300  
+931212 49333.00 I  -.021116  .000199   .463459  .000226  I  .2471210  .0000136  2.2924 0.0084  I   -18.334     .791    -3.351     .111  -.021200   .462400   .2470100   -19.100    -4.200  
+931213 49334.00 I  -.019978  .000171   .464619  .000189  I  .2448779  .0000101  2.2070 0.0087  I   -18.112     .791    -3.402     .114  -.020100   .463600   .2447600   -18.700    -4.200  
+931214 49335.00 I  -.018938  .000200   .465875  .000240  I  .2426803  .0000109  2.2019 0.0077  I   -17.959     .791    -3.356     .104  -.019000   .465000   .2425400   -18.100    -4.100  
+931215 49336.00 I  -.017978  .000189   .467130  .000238  I  .2404463  .0000117  2.2803 0.0074  I   -17.747     .791    -3.247     .298  -.017900   .466300   .2403000   -17.600    -3.900  
+931216 49337.00 I  -.016999  .000162   .468233  .000226  I  .2381032  .0000101  2.4082 0.0079  I   -17.388     .791    -3.138     .298  -.017000   .467500   .2379400   -17.000    -3.700  
+931217 49338.00 I  -.015881  .000177   .469162  .000207  I  .2356355  .0000106  2.5194 0.0067  I   -17.021     .791    -3.137     .298  -.016000   .468500   .2354700   -16.800    -3.600  
+931218 49339.00 I  -.014635  .000223   .469955  .000259  I  .2330778  .0000088  2.5903 0.0087  I   -16.866     .791    -3.278     .298  -.014800   .469300   .2329100   -16.700    -3.600  
+931219 49340.00 I  -.013258  .000252   .470683  .000292  I  .2304656  .0000138  2.6290 0.0070  I   -16.964     .148    -3.465     .150  -.013500   .470000   .2303000   -16.800    -3.500  
+931220 49341.00 I  -.011691  .000209   .471433  .000245  I  .2278282  .0000109  2.6425 0.0087  I   -17.184     .133    -3.572     .131  -.011700   .470700   .2276700   -17.100    -3.500  
+931221 49342.00 I  -.009752  .000176   .472284  .000203  I  .2251854  .0000107  2.6415 0.0074  I   -17.423     .152    -3.527     .146  -.009700   .471500   .2250500   -17.500    -3.500  
+931222 49343.00 I  -.007342  .000180   .473280  .000202  I  .2225628  .0000101  2.5875 0.0072  I   -17.655     .152    -3.359     .146  -.007400   .472500   .2224700   -17.900    -3.600  
+931223 49344.00 I  -.004758  .000189   .474365  .000201  I  .2200279  .0000096  2.4810 0.0069  I   -17.813     .152    -3.224     .146  -.005000   .473600   .2199400   -18.300    -3.700  
+931224 49345.00 I  -.002260  .000188   .475357  .000198  I  .2176001  .0000094  2.3767 0.0062  I   -17.835     .152    -3.182     .146  -.002700   .474600   .2175100   -18.600    -3.800  
+931225 49346.00 I  -.000079  .000128   .476105  .000129  I  .2152727  .0000078  2.2779 0.0092  I   -17.752     .791    -3.188     .298  -.000600   .475300   .2151800   -18.700    -3.900  
+931226 49347.00 I   .001645  .000162   .476538  .000152  I  .2130411  .0000158  2.1885 0.0049  I   -17.692     .791    -3.178     .298   .001200   .475800   .2129400   -18.700    -4.000  
+931227 49348.00 I   .002979  .000134   .476647  .000114  I  .2108865  .0000059  2.1265 0.0084  I   -17.717     .149    -3.171     .298   .002600   .475900   .2107800   -18.400    -4.000  
+931228 49349.00 I   .004130  .000125   .476509  .000113  I  .2087733  .0000059  2.1089 0.0043  I   -17.717     .179    -3.245     .298   .003900   .475800   .2086600   -18.100    -3.900  
+931229 49350.00 I   .005326  .000128   .476268  .000110  I  .2066509  .0000063  2.1448 0.0043  I   -17.537     .179    -3.412     .298   .005000   .475600   .2065100   -17.900    -3.800  
+931230 49351.00 I   .006736  .000104   .476099  .000089  I  .2044548  .0000063  2.2673 0.0044  I   -17.187     .179    -3.556     .298   .006200   .475500   .2042600   -17.600    -3.700  
+931231 49352.00 I   .008448  .000106   .476147  .000089  I  .2020948  .0000062  2.4544 0.0046  I   -16.805     .179    -3.580     .298   .007800   .475500   .2018500   -17.300    -3.600  
+94 1 1 49353.00 I   .010488  .000152   .476399  .000131  I  .1995489  .0000067  2.6327 0.0049  I   -16.588     .179    -3.467     .298   .009700   .475600   .1992800   -17.200    -3.400  
+94 1 2 49354.00 I   .012823  .000198   .476816  .000148  I  .1968449  .0000076  2.7646 0.0055  I   -16.618     .204    -3.280     .298   .012000   .476000   .1965900   -17.300    -3.300  
+94 1 3 49355.00 I   .015382  .000219   .477358  .000131  I  .1940457  .0000087  2.8187 0.0056  I   -16.799     .166    -3.093     .104   .014700   .476700   .1938000   -17.500    -3.100  
+94 1 4 49356.00 I   .018130  .000221   .477976  .000131  I  .1912390  .0000082  2.7783 0.0062  I   -17.011     .186    -2.927     .181   .017600   .477300   .1910200   -17.800    -3.100  
+94 1 5 49357.00 I   .021020  .000223   .478639  .000131  I  .1885171  .0000088  2.6539 0.0061  I   -17.249     .252    -2.762     .174   .020600   .478000   .1883300   -18.100    -3.100  
+94 1 6 49358.00 I   .023887  .000233   .479288  .000129  I  .1859460  .0000091  2.4852 0.0064  I   -17.614     .252    -2.611     .174   .023600   .478600   .1857800   -18.500    -3.100  
+94 1 7 49359.00 I   .026706  .000226   .479806  .000138  I  .1835517  .0000092  2.3015 0.0067  I   -18.139     .252    -2.669     .174   .026400   .479000   .1834100   -18.700    -3.200  
+94 1 8 49360.00 I   .029429  .000197   .480131  .000128  I  .1813388  .0000098  2.1303 0.0079  I   -18.653     .252    -2.888     .174   .029100   .479200   .1812100   -18.900    -3.200  
+94 1 9 49361.00 I   .031915  .000185   .480235  .000174  I  .1792719  .0000129  2.0168 0.0065  I   -18.969     .233    -3.116     .165   .031600   .479300   .1791600   -18.900    -3.200  
+94 110 49362.00 I   .034135  .000162   .480135  .000219  I  .1772787  .0000085  1.9828 0.0071  I   -19.013     .210    -3.245     .298   .033900   .479200   .1771700   -18.800    -3.200  
+94 111 49363.00 I   .036207  .000130   .479908  .000191  I  .1752855  .0000061  2.0110 0.0050  I   -18.808     .232    -3.165     .298   .036200   .479000   .1751800   -18.600    -3.200  
+94 112 49364.00 I   .038357  .000117   .479664  .000179  I  .1732344  .0000052  2.1059 0.0039  I   -18.485     .227    -2.917     .298   .038400   .478900   .1731100   -18.400    -3.200  
+94 113 49365.00 I   .040806  .000110   .479395  .000162  I  .1710573  .0000048  2.2498 0.0037  I   -18.199     .270    -2.670     .298   .040800   .478700   .1709500   -18.300    -3.100  
+94 114 49366.00 I   .043564  .000103   .479149  .000151  I  .1687462  .0000052  2.3594 0.0035  I   -18.008     .247    -2.589     .298   .043200   .478700   .1686700   -18.300    -3.000  
+94 115 49367.00 I   .046270  .000103   .479033  .000136  I  .1663712  .0000052  2.3710 0.0037  I   -17.898     .246    -2.705     .298   .045600   .478600   .1663300   -18.400    -3.000  
+94 116 49368.00 I   .048614  .000087   .479092  .000142  I  .1640261  .0000052  2.3168 0.0036  I   -17.900     .257    -2.905     .298   .047900   .478700   .1639700   -18.500    -3.000  
+94 117 49369.00 I   .050696  .000099   .479199  .000136  I  .1617348  .0000049  2.2710 0.0039  I   -18.030     .234    -3.045     .298   .050100   .478700   .1616500   -18.700    -3.000  
+94 118 49370.00 I   .052590  .000105   .479158  .000141  I  .1594831  .0000057  2.2281 0.0037  I   -18.224     .235    -3.039     .108   .052300   .478500   .1593800   -18.900    -3.100  
+94 119 49371.00 I   .054280  .000109   .478859  .000134  I  .1572956  .0000055  2.1342 0.0039  I   -18.379     .208    -2.996     .125   .054300   .478200   .1572000   -19.100    -3.300  
+94 120 49372.00 I   .055909  .000109   .478392  .000172  I  .1552205  .0000054  2.0228 0.0039  I   -18.417     .197    -3.058     .144   .056300   .477600   .1551100   -19.300    -3.500  
+94 121 49373.00 I   .057689  .000106   .477780  .000197  I  .1532311  .0000054  1.9679 0.0036  I   -18.335     .191    -3.289     .146   .058400   .477000   .1531100   -19.400    -3.700  
+94 122 49374.00 I   .059822  .000103   .477049  .000209  I  .1512759  .0000048  1.9394 0.0036  I   -18.256     .163    -3.491     .148   .060500   .476400   .1511700   -19.300    -3.800  
+94 123 49375.00 I   .062349  .000105   .476481  .000219  I  .1493481  .0000047  1.9236 0.0034  I   -18.261     .175    -3.495     .142   .062700   .475900   .1492600   -19.200    -4.100  
+94 124 49376.00 I   .065142  .000101   .476263  .000210  I  .1474173  .0000049  1.9419 0.0034  I   -18.317     .156    -3.434     .132   .065100   .475500   .1473300   -18.800    -4.100  
+94 125 49377.00 I   .067938  .000101   .476205  .000223  I  .1454482  .0000049  2.0084 0.0037  I   -18.314     .133    -3.467     .119   .067700   .475200   .1453500   -18.600    -4.200  
+94 126 49378.00 I   .070662  .000095   .475982  .000238  I  .1433702  .0000055  2.1658 0.0040  I   -18.145     .145    -3.654     .298   .070400   .474900   .1432400   -18.300    -4.100  
+94 127 49379.00 I   .073391  .000096   .475402  .000214  I  .1410971  .0000063  2.3817 0.0045  I   -17.786     .154    -3.898     .298   .073200   .474500   .1409600   -18.100    -4.000  
+94 128 49380.00 I   .076083  .000112   .474665  .000188  I  .1386113  .0000070  2.5843 0.0057  I   -17.406     .163    -3.954     .298   .076000   .473900   .1384800   -18.100    -3.900  
+94 129 49381.00 I   .078769  .000143   .473851  .000179  I  .1359433  .0000094  2.7427 0.0094  I   -17.259     .108    -3.737     .298   .078700   .473200   .1358100   -18.200    -3.700  
+94 130 49382.00 I   .081448  .000162   .472951  .000128  I  .1331513  .0000175  2.8249 0.0075  I   -17.486     .112    -3.416     .298   .081500   .472300   .1330100   -18.500    -3.600  
+94 131 49383.00 I   .084148  .000161   .471983  .000128  I  .1303264  .0000118  2.8085 0.0102  I   -18.006     .244    -3.203     .298   .084200   .471400   .1301900   -18.800    -3.600  
+94 2 1 49384.00 I   .086895  .000155   .471012  .000109  I  .1275677  .0000105  2.6919 0.0078  I   -18.573     .258    -3.170     .298   .086900   .470400   .1274300   -19.200    -3.500  
+94 2 2 49385.00 I   .089671  .000170   .470130  .000132  I  .1249677  .0000101  2.4999 0.0073  I   -19.000     .258    -3.232     .298   .089600   .469600   .1248200   -19.800    -3.400  
+94 2 3 49386.00 I   .092442  .000180   .469412  .000139  I  .1225727  .0000101  2.2935 0.0073  I   -19.285     .258    -3.282     .298   .092300   .468800   .1224200   -20.000    -3.600  
+94 2 4 49387.00 I   .095098  .000180   .468762  .000143  I  .1203722  .0000105  2.1126 0.0074  I   -19.509     .258    -3.312     .298   .095000   .468000   .1202300   -20.100    -3.900  
+94 2 5 49388.00 I   .097505  .000183   .468057  .000150  I  .1183323  .0000108  1.9773 0.0088  I   -19.753     .258    -3.357     .298   .097500   .467300   .1182000   -19.900    -4.100  
+94 2 6 49389.00 I   .099674  .000189   .467277  .000175  I  .1163942  .0000141  1.9123 0.0079  I   -19.927     .195    -3.485     .298   .099900   .466600   .1162700   -19.800    -4.200  
+94 2 7 49390.00 I   .101698  .000179   .466450  .000133  I  .1144788  .0000116  1.9341 0.0092  I   -19.846     .245    -3.683     .298   .102000   .465800   .1143600   -19.400    -4.300  
+94 2 8 49391.00 I   .103663  .000198   .465580  .000108  I  .1125030  .0000118  2.0249 0.0082  I   -19.415     .245    -3.875     .298   .104100   .464900   .1123800   -19.100    -4.400  
+94 2 9 49392.00 I   .105628  .000200   .464636  .000123  I  .1104216  .0000115  2.1377 0.0081  I   -18.747     .309    -3.988     .298   .106100   .464000   .1103000   -18.800    -4.400  
+94 210 49393.00 I   .107685  .000189   .463574  .000119  I  .1082301  .0000111  2.2428 0.0082  I   -18.069     .309    -3.912     .298   .108000   .463000   .1081000   -18.500    -4.400  
+94 211 49394.00 I   .109662  .000184   .462451  .000122  I  .1059464  .0000117  2.3166 0.0069  I   -17.606     .309    -3.787     .298   .109800   .462000   .1058200   -18.400    -4.300  
+94 212 49395.00 I   .111429  .000183   .461331  .000114  I  .1036106  .0000083  2.3494 0.0085  I   -17.486     .380    -3.812     .103   .111500   .460800   .1034800   -18.500    -4.400  
+94 213 49396.00 I   .113118  .000190   .460239  .000142  I  .1012573  .0000124  2.3532 0.0066  I   -17.668     .387    -3.999     .298   .113100   .459700   .1011200   -18.700    -4.500  
+94 214 49397.00 I   .114866  .000193   .459172  .000137  I  .0989138  .0000102  2.3283 0.0079  I   -18.062     .335    -4.224     .298   .114700   .458500   .0987800   -19.100    -4.600  
+94 215 49398.00 I   .116741  .000209   .458065  .000153  I  .0966117  .0000097  2.2704 0.0074  I   -18.546     .267    -4.383     .298   .116500   .457300   .0964700   -19.400    -4.800  
+94 216 49399.00 I   .118747  .000202   .456839  .000140  I  .0943824  .0000107  2.1842 0.0066  I   -18.900     .267    -4.473     .298   .118300   .456100   .0942400   -19.700    -5.000  
+94 217 49400.00 I   .120837  .000212   .455491  .000149  I  .0922419  .0000089  2.1020 0.0075  I   -18.964     .267    -4.576     .298   .120200   .454800   .0920800   -19.900    -5.300  
+94 218 49401.00 I   .122767  .000221   .454064  .000161  I  .0901704  .0000106  2.0437 0.0083  I   -18.792     .267    -4.715     .298   .122200   .453400   .0900000   -20.100    -5.500  
+94 219 49402.00 I   .124543  .000228   .452625  .000170  I  .0881463  .0000139  2.0099 0.0112  I   -18.583     .140    -4.813     .298   .124200   .452000   .0879700   -20.200    -5.700  
+94 220 49403.00 I   .126444  .000223   .451326  .000199  I  .0861344  .0000197  2.0247 0.0107  I   -18.411     .242    -4.749     .298   .126400   .450800   .0859700   -20.000    -5.900  
+94 221 49404.00 I   .128682  .000208   .450311  .000207  I  .0840749  .0000164  2.1054 0.0125  I   -18.227     .226    -4.549     .298   .128800   .449800   .0839300   -19.900    -5.900  
+94 222 49405.00 I   .131239  .000220   .449616  .000208  I  .0819021  .0000155  2.2504 0.0112  I   -18.057     .226    -4.460     .298   .131400   .449100   .0817700   -19.700    -5.900  
+94 223 49406.00 I   .133898  .000213   .449154  .000213  I  .0795498  .0000154  2.4681 0.0103  I   -17.986     .226    -4.706     .298   .134000   .448600   .0794300   -19.700    -5.900  
+94 224 49407.00 I   .136340  .000246   .448793  .000270  I  .0769470  .0000135  2.7425 0.0095  I   -17.926     .226    -5.112     .298   .136400   .448300   .0768400   -19.500    -5.700  
+94 225 49408.00 I   .138371  .000251   .448401  .000257  I  .0740647  .0000111  3.0174 0.0073  I   -17.790     .226    -5.340     .298   .138400   .447900   .0739700   -19.400    -5.600  
+94 226 49409.00 I   .139965  .000254   .447866  .000290  I  .0709302  .0000055  3.2385 0.0084  I   -17.651     .155    -5.222     .298   .140100   .447400   .0708400   -19.300    -5.500  
+94 227 49410.00 I   .141211  .000249   .447137  .000267  I  .0676205  .0000126  3.3612 0.0049  I   -17.683     .791    -4.921     .298   .141400   .446600   .0675100   -19.400    -5.300  
+94 228 49411.00 I   .142256  .000207   .446175  .000230  I  .0642490  .0000081  3.3603 0.0074  I   -17.934     .791    -4.737     .298   .142500   .445600   .0641200   -19.500    -5.300  
+94 3 1 49412.00 I   .143219  .000197   .444899  .000224  I  .0609375  .0000078  3.2465 0.0062  I   -18.226     .791    -4.796     .298   .143400   .444200   .0607900   -19.600    -5.400  
+94 3 2 49413.00 I   .144190  .000180   .443314  .000229  I  .0577774  .0000095  3.0684 0.0069  I   -18.342     .791    -4.976     .298   .144300   .442700   .0576300   -19.500    -5.500  
+94 3 3 49414.00 I   .145240  .000149   .441509  .000185  I  .0548062  .0000113  2.8736 0.0075  I   -18.225     .791    -5.096     .298   .145200   .440900   .0546700   -19.600    -5.600  
+94 3 4 49415.00 I   .146278  .000148   .439625  .000149  I  .0520263  .0000117  2.6904 0.0080  I   -18.003     .791    -5.108     .298   .146200   .439000   .0519500   -19.400    -5.800  
+94 3 5 49416.00 I   .147211  .000154   .437777  .000188  I  .0494116  .0000113  2.5485 0.0092  I   -17.834     .791    -5.075     .298   .147300   .437200   .0493600   -19.300    -6.000  
+94 3 6 49417.00 I   .148071  .000135   .436001  .000188  I  .0469051  .0000143  2.4792 0.0080  I   -17.782     .274    -5.066     .159   .148200   .435400   .0468600   -19.100    -6.000  
+94 3 7 49418.00 I   .148970  .000145   .434307  .000171  I  .0444290  .0000112  2.4825 0.0087  I   -17.814     .196    -5.126     .158   .149100   .433800   .0443700   -18.900    -6.100  
+94 3 8 49419.00 I   .149918  .000151   .432679  .000160  I  .0419256  .0000098  2.5294 0.0072  I   -17.885     .196    -5.293     .158   .150000   .432200   .0418500   -18.700    -6.100  
+94 3 9 49420.00 I   .150889  .000156   .431067  .000164  I  .0393615  .0000092  2.6025 0.0066  I   -18.033     .277    -5.567     .129   .150900   .430500   .0392600   -18.600    -6.100  
+94 310 49421.00 I   .151945  .000155   .429415  .000167  I  .0367221  .0000089  2.6713 0.0064  I   -18.286     .277    -5.728     .129   .151800   .428800   .0366200   -18.400    -6.100  
+94 311 49422.00 I   .153095  .000168   .427708  .000171  I  .0340371  .0000090  2.6857 0.0056  I   -18.576     .277    -5.730     .129   .153000   .427100   .0339500   -18.200    -6.000  
+94 312 49423.00 I   .154380  .000191   .425975  .000140  I  .0313733  .0000069  2.6323 0.0063  I   -18.702     .279    -5.692     .111   .154200   .425200   .0312900   -18.100    -6.000  
+94 313 49424.00 I   .155842  .000215   .424297  .000208  I  .0287840  .0000089  2.5445 0.0070  I   -18.580     .284    -5.719     .298   .155700   .423500   .0286800   -18.100    -6.200  
+94 314 49425.00 I   .157393  .000201   .422761  .000197  I  .0262872  .0000121  2.4480 0.0074  I   -18.319     .347    -5.848     .298   .157200   .421800   .0261500   -18.100    -6.300  
+94 315 49426.00 I   .158931  .000204   .421377  .000203  I  .0238883  .0000117  2.3507 0.0085  I   -18.031     .284    -6.038     .298   .158800   .420400   .0237300   -18.100    -6.500  
+94 316 49427.00 I   .160366  .000209   .420007  .000205  I  .0215796  .0000119  2.2720 0.0084  I   -17.744     .392    -6.239     .298   .160300   .419000   .0214200   -18.000    -6.700  
+94 317 49428.00 I   .161723  .000212   .418500  .000199  I  .0193435  .0000120  2.1956 0.0085  I   -17.558     .392    -6.430     .298   .161500   .417700   .0192100   -17.900    -7.000  
+94 318 49429.00 I   .162780  .000198   .416933  .000193  I  .0171856  .0000120  2.1275 0.0091  I   -17.573     .392    -6.625     .298   .162500   .416200   .0170800   -17.700    -7.100  
+94 319 49430.00 I   .163469  .000193   .415334  .000235  I  .0150740  .0000137  2.1027 0.0106  I   -17.734     .436    -6.821     .298   .163100   .414700   .0149800   -17.600    -7.300  
+94 320 49431.00 I   .163895  .000179   .413673  .000201  I  .0129631  .0000174  2.1291 0.0075  I   -17.862     .433    -6.888     .298   .163500   .413100   .0128700   -17.200    -7.300  
+94 321 49432.00 I   .164155  .000146   .411919  .000205  I  .0107951  .0000063  2.2177 0.0092  I   -17.766     .482    -6.727     .298   .163800   .411400   .0107000   -16.900    -7.300  
+94 322 49433.00 I   .164345  .000159   .410066  .000233  I  .0085070  .0000061  2.3686 0.0043  I   -17.460     .384    -6.496     .298   .164200   .409600   .0084200   -16.800    -7.300  
+94 323 49434.00 I   .164664  .000150   .408178  .000255  I  .0060379  .0000058  2.5797 0.0042  I   -17.222     .314    -6.469     .298   .164700   .407700   .0059400   -16.600    -7.200  
+94 324 49435.00 I   .165351  .000149   .406360  .000248  I  .0033379  .0000058  2.8199 0.0041  I   -17.252     .314    -6.681     .298   .165600   .405800   .0032300   -16.600    -7.000  
+94 325 49436.00 I   .166358  .000135   .404603  .000240  I  .0004004  .0000059  3.0532 0.0041  I   -17.354     .314    -6.848     .298   .166500   .403900   .0002800   -16.800    -6.900  
+94 326 49437.00 I   .167468  .000155   .402813  .000235  I -.0027475  .0000059  3.2234 0.0052  I   -17.361     .314    -6.747     .298   .167500   .402000  -.0028700   -17.100    -6.800  
+94 327 49438.00 I   .168527  .000149   .400966  .000268  I -.0060032  .0000086  3.2638 0.0054  I   -17.347     .251    -6.479     .298   .168400   .400100  -.0061200   -17.500    -6.900  
+94 328 49439.00 I   .169439  .000181   .399053  .000224  I -.0092285  .0000090  3.1643 0.0060  I   -17.417     .791    -6.336     .298   .169300   .398200  -.0093300   -17.800    -6.900  
+94 329 49440.00 I   .170178  .000194   .397074  .000207  I -.0122952  .0000084  2.9551 0.0063  I   -17.544     .791    -6.472     .298   .170300   .396300  -.0124100   -18.100    -7.100  
+94 330 49441.00 I   .170917  .000197   .395070  .000188  I -.0151299  .0000089  2.7197 0.0062  I   -17.627     .791    -6.763     .298   .171400   .394400  -.0152600   -18.200    -7.400  
+94 331 49442.00 I   .172023  .000217   .393179  .000204  I -.0177504  .0000092  2.5319 0.0063  I   -17.603     .791    -7.030     .298   .172600   .392600  -.0178900   -18.300    -7.600  
+94 4 1 49443.00 I   .173479  .000204   .391451  .000220  I -.0202159  .0000088  2.4109 0.0059  I   -17.464     .791    -7.234     .298   .174000   .390800  -.0203400   -18.200    -7.800  
+94 4 2 49444.00 I   .175073  .000196   .389822  .000165  I -.0225980  .0000073  2.3673 0.0081  I   -17.254     .791    -7.413     .298   .175300   .389100  -.0227200   -17.900    -7.900  
+94 4 3 49445.00 I   .176575  .000191   .388195  .000209  I -.0249739  .0000137  2.3938 0.0056  I   -17.090     .791    -7.541     .298   .176500   .387500  -.0251000   -17.700    -8.000  
+94 4 4 49446.00 I   .177850  .000184   .386499  .000206  I -.0273956  .0000086  2.4502 0.0078  I   -17.076     .791    -7.561     .298   .177700   .385800  -.0274900   -17.500    -8.100  
+94 4 5 49447.00 I   .178909  .000184   .384736  .000239  I -.0298724  .0000075  2.5010 0.0054  I   -17.153     .791    -7.499     .298   .178800   .384200  -.0299700   -17.500    -8.000  
+94 4 6 49448.00 I   .179853  .000164   .382938  .000221  I -.0323972  .0000064  2.5505 0.0049  I   -17.148     .791    -7.436     .298   .179800   .382400  -.0325000   -17.500    -7.900  
+94 4 7 49449.00 I   .180783  .000174   .381137  .000230  I -.0349731  .0000064  2.5993 0.0038  I   -17.013     .791    -7.383     .298   .180800   .380700  -.0350900   -17.500    -7.900  
+94 4 8 49450.00 I   .181636  .000172   .379343  .000241  I -.0375888  .0000042  2.6273 0.0039  I   -16.894     .791    -7.280     .298   .181700   .379000  -.0377100   -17.400    -7.800  
+94 4 9 49451.00 I   .182329  .000218   .377572  .000239  I -.0402176  .0000044  2.6249 0.0031  I   -16.937     .791    -7.124     .298   .182400   .377300  -.0403500   -17.400    -7.800  
+94 410 49452.00 I   .182867  .000240   .375874  .000405  I -.0428274  .0000045  2.5890 0.0036  I   -17.124     .791    -7.045     .298   .183000   .375600  -.0429600   -17.500    -7.800  
+94 411 49453.00 I   .183229  .000219   .374257  .000344  I -.0453837  .0000056  2.5175 0.0049  I   -17.334     .791    -7.171     .298   .183300   .373900  -.0455200   -17.500    -7.900  
+94 412 49454.00 I   .183341  .000212   .372623  .000339  I -.0478529  .0000087  2.4177 0.0055  I   -17.448     .791    -7.473     .298   .183400   .372200  -.0479800   -17.400    -8.000  
+94 413 49455.00 I   .183248  .000230   .370836  .000334  I -.0502164  .0000094  2.3099 0.0064  I   -17.371     .791    -7.792     .298   .183300   .370400  -.0503400   -17.200    -8.200  
+94 414 49456.00 I   .183142  .000236   .368777  .000321  I -.0524756  .0000093  2.2107 0.0066  I   -17.103     .791    -8.018     .298   .183100   .368500  -.0525900   -17.000    -8.400  
+94 415 49457.00 I   .183089  .000200   .366542  .000316  I -.0546441  .0000092  2.1304 0.0072  I   -16.833     .791    -8.179     .298   .183100   .366300  -.0547500   -16.800    -8.500  
+94 416 49458.00 I   .183155  .000188   .364319  .000350  I -.0567524  .0000109  2.0982 0.0069  I   -16.769     .791    -8.318     .298   .183200   .364000  -.0568600   -16.500    -8.400  
+94 417 49459.00 I   .183364  .000191   .362224  .000243  I -.0588633  .0000104  2.1345 0.0064  I   -16.844     .791    -8.365     .298   .183400   .361800  -.0589700   -16.300    -8.400  
+94 418 49460.00 I   .183638  .000193   .360311  .000201  I -.0610425  .0000068  2.2343 0.0062  I   -16.757     .791    -8.215     .298   .183600   .359700  -.0611500   -16.000    -8.300  
+94 419 49461.00 I   .183851  .000186   .358589  .000193  I -.0633504  .0000066  2.3898 0.0050  I   -16.367     .791    -7.933     .298   .183800   .357800  -.0634500   -15.900    -8.200  
+94 420 49462.00 I   .183927  .000170   .357041  .000191  I -.0658290  .0000072  2.5660 0.0051  I   -15.908     .791    -7.744     .298   .184000   .356200  -.0659100   -16.000    -8.100  
+94 421 49463.00 I   .183893  .000169   .355593  .000196  I -.0684853  .0000079  2.7509 0.0050  I   -15.709     .791    -7.768     .298   .183900   .354800  -.0685800   -16.100    -7.900  
+94 422 49464.00 I   .183783  .000172   .354125  .000143  I -.0713343  .0000070  2.9463 0.0054  I   -15.837     .791    -7.849     .298   .183800   .353400  -.0714500   -16.400    -7.700  
+94 423 49465.00 I   .183580  .000185   .352535  .000137  I -.0743644  .0000073  3.1014 0.0068  I   -16.130     .791    -7.766     .298   .183600   .351900  -.0744800   -16.600    -7.700  
+94 424 49466.00 I   .183329  .000200   .350751  .000180  I -.0775031  .0000117  3.1546 0.0068  I   -16.435     .791    -7.537     .298   .183300   .350200  -.0776000   -17.000    -7.700  
+94 425 49467.00 I   .183076  .000199   .348730  .000149  I -.0806300  .0000114  3.0769 0.0077  I   -16.680     .119    -7.404     .298   .183000   .348200  -.0806900   -17.300    -7.800  
+94 426 49468.00 I   .182904  .000177   .346445  .000155  I -.0836211  .0000101  2.8917 0.0075  I   -16.834     .272    -7.499     .298   .182800   .345900  -.0836600   -17.500    -7.900  
+94 427 49469.00 I   .182861  .000178   .343925  .000163  I -.0864020  .0000098  2.6725 0.0071  I   -16.894     .259    -7.699     .205   .182700   .343200  -.0864600   -17.600    -8.200  
+94 428 49470.00 I   .182883  .000173   .341266  .000166  I -.0889845  .0000099  2.5087 0.0072  I   -16.887     .259    -7.817     .205   .182700   .340400  -.0890600   -17.500    -8.300  
+94 429 49471.00 I   .183010  .000168   .338645  .000153  I -.0914518  .0000106  2.4420 0.0073  I   -16.831     .259    -7.940     .205   .183000   .337700  -.0915600   -17.400    -8.500  
+94 430 49472.00 I   .183316  .000151   .336208  .000152  I -.0938945  .0000106  2.4531 0.0074  I   -16.631     .280    -8.134     .224   .183300   .335200  -.0940100   -17.200    -8.600  
+94 5 1 49473.00 I   .183751  .000175   .333988  .000186  I -.0963720  .0000102  2.5061 0.0069  I   -16.392     .305    -8.311     .247   .183800   .332900  -.0964900   -16.900    -8.600  
+94 5 2 49474.00 I   .184268  .000144   .331918  .000169  I -.0989092  .0000089  2.5664 0.0067  I   -16.413     .212    -8.351     .240   .184300   .330900  -.0990100   -16.900    -8.600  
+94 5 3 49475.00 I   .184802  .000148   .329910  .000163  I -.1014984  .0000088  2.6074 0.0062  I   -16.728     .791    -8.242     .298   .184400   .329300  -.1016100   -17.000    -8.700  
+94 5 4 49476.00 I   .185248  .000158   .327875  .000171  I -.1041177  .0000087  2.6293 0.0056  I   -16.996     .791    -8.111     .298   .184700   .327300  -.1042400   -17.200    -8.600  
+94 5 5 49477.00 I   .185493  .000164   .325771  .000175  I -.1067517  .0000070  2.6351 0.0056  I   -16.932     .791    -8.031     .298   .184900   .325100  -.1068800   -17.400    -8.500  
+94 5 6 49478.00 I   .185617  .000167   .323560  .000181  I -.1093766  .0000070  2.6069 0.0045  I   -16.682     .791    -7.929     .298   .185200   .322800  -.1095100   -17.600    -8.400  
+94 5 7 49479.00 I   .185787  .000150   .321227  .000153  I -.1119535  .0000056  2.5427 0.0044  I   -16.611     .791    -7.751     .298   .185500   .320400  -.1120800   -17.900    -8.400  
+94 5 8 49480.00 I   .186127  .000153   .318824  .000169  I -.1144563  .0000053  2.4613 0.0039  I   -16.842     .791    -7.619     .298   .186000   .318000  -.1145800   -18.000    -8.400  
+94 5 9 49481.00 I   .186656  .000118   .316455  .000178  I -.1168720  .0000053  2.3677 0.0044  I   -17.177     .282    -7.719     .298   .186700   .315600  -.1169900   -18.200    -8.600  
+94 510 49482.00 I   .187338  .000130   .314204  .000206  I -.1191899  .0000070  2.2686 0.0044  I   -17.383     .612    -8.067     .147   .187400   .313400  -.1193000   -18.200    -8.800  
+94 511 49483.00 I   .188084  .000125   .312099  .000195  I -.1214190  .0000070  2.1990 0.0050  I   -17.392     .548    -8.476     .137   .188200   .311300  -.1215400   -18.100    -8.900  
+94 512 49484.00 I   .188701  .000131   .310098  .000190  I -.1236014  .0000071  2.1700 0.0050  I   -17.311     .548    -8.763     .137   .188700   .309300  -.1237200   -17.800    -9.100  
+94 513 49485.00 I   .189149  .000139   .308105  .000196  I -.1257618  .0000072  2.1493 0.0054  I   -17.209     .548    -8.917     .137   .189000   .307400  -.1258600   -17.400    -9.200  
+94 514 49486.00 I   .189254  .000145   .306043  .000202  I -.1279101  .0000081  2.1590 0.0058  I   -17.242     .611    -8.959     .153   .189000   .305400  -.1280100   -17.100    -9.300  
+94 515 49487.00 I   .188985  .000130   .303929  .000199  I -.1300973  .0000092  2.2213 0.0091  I   -17.469     .669    -8.904     .177   .188800   .303300  -.1301900   -16.700    -9.300  
+94 516 49488.00 I   .188471  .000243   .301845  .000148  I -.1323644  .0000162  2.3187 0.0089  I   -17.675     .116    -8.750     .298   .188400   .301200  -.1324700   -16.600    -9.200  
+94 517 49489.00 I   .187907  .000233   .299837  .000120  I -.1347430  .0000152  2.4411 0.0112  I   -17.613     .168    -8.515     .298   .188000   .299100  -.1348500   -16.600    -9.100  
+94 518 49490.00 I   .187447  .000226   .297844  .000120  I -.1372496  .0000155  2.5725 0.0109  I   -17.309     .168    -8.325     .298   .187600   .297000  -.1373600   -16.800    -9.000  
+94 519 49491.00 I   .187258  .000219   .295802  .000108  I -.1398852  .0000155  2.6955 0.0110  I   -17.047     .168    -8.289     .298   .187300   .295000  -.1400100   -17.000    -8.800  
+94 520 49492.00 I   .187165  .000222   .293799  .000125  I -.1426253  .0000155  2.7725 0.0115  I   -17.028     .168    -8.248     .298   .187000   .293100  -.1427500   -17.300    -8.600  
+94 521 49493.00 I   .186911  .000221   .291936  .000139  I -.1454033  .0000170  2.7688 0.0121  I   -17.269     .161    -8.051     .298   .186600   .291300  -.1455300   -17.800    -8.500  
+94 522 49494.00 I   .186381  .000133   .290234  .000209  I -.1481329  .0000187  2.6751 0.0117  I   -17.634     .164    -7.775     .298   .186000   .289700  -.1482500   -18.100    -8.500  
+94 523 49495.00 I   .185530  .000136   .288644  .000188  I -.1507284  .0000162  2.5062 0.0122  I   -17.930     .140    -7.622     .298   .185200   .288100  -.1508300   -18.300    -8.400  
+94 524 49496.00 I   .184389  .000139   .287063  .000200  I -.1531330  .0000157  2.3005 0.0112  I   -18.058     .115    -7.683     .298   .184200   .286400  -.1532300   -18.500    -8.400  
+94 525 49497.00 I   .183055  .000153   .285359  .000203  I -.1553305  .0000155  2.0982 0.0115  I   -18.066     .115    -7.809     .298   .183100   .284700  -.1554300   -18.500    -8.500  
+94 526 49498.00 I   .181653  .000151   .283438  .000200  I -.1573496  .0000168  1.9565 0.0111  I   -17.983     .115    -7.803     .298   .181900   .282700  -.1574600   -18.400    -8.600  
+94 527 49499.00 I   .180293  .000163   .281331  .000202  I -.1592708  .0000160  1.8965 0.0117  I   -17.762     .791    -7.691     .298   .180600   .280600  -.1593900   -18.100    -8.600  
+94 528 49500.00 I   .179012  .000173   .279090  .000188  I -.1611620  .0000164  1.8946 0.0136  I   -17.346     .791    -7.651     .298   .179200   .278400  -.1612800   -17.900    -8.700  
+94 529 49501.00 I   .177800  .000187   .276742  .000174  I -.1630720  .0000220  1.9287 0.0113  I   -16.919     .791    -7.749     .298   .177900   .276100  -.1632000   -17.800    -8.600  
+94 530 49502.00 I   .176635  .000174   .274317  .000121  I -.1650226  .0000156  1.9725 0.0135  I   -16.872     .101    -7.874     .298   .176700   .273600  -.1651600   -17.700    -8.600  
+94 531 49503.00 I   .175513  .000231   .271880  .000103  I -.1670147  .0000158  2.0096 0.0105  I   -17.343     .791    -7.936     .298   .175500   .271300  -.1671600   -17.900    -8.500  
+94 6 1 49504.00 I   .174487  .000230   .269528  .000095  I -.1690326  .0000140  2.0193 0.0104  I   -17.975     .791    -7.981     .298   .174500   .268900  -.1691800   -18.200    -8.400  
+94 6 2 49505.00 I   .173610  .000218   .267345  .000087  I -.1710389  .0000134  1.9860 0.0093  I   -18.333     .791    -8.073     .298   .173500   .266700  -.1711600   -18.700    -8.500  
+94 6 3 49506.00 I   .172730  .000204   .265339  .000102  I -.1729923  .0000122  1.9159 0.0072  I   -18.405     .791    -8.130     .298   .172400   .264700  -.1731100   -19.200    -8.500  
+94 6 4 49507.00 I   .171669  .000195   .263474  .000095  I -.1748627  .0000051  1.8219 0.0080  I   -18.540     .791    -8.049     .298   .171400   .262700  -.1749800   -19.600    -8.500  
+94 6 5 49508.00 I   .170453  .000245   .261702  .000155  I -.1766318  .0000104  1.7148 0.0046  I   -18.938     .791    -7.915     .298   .170200   .260900  -.1767500   -20.000    -8.600  
+94 6 6 49509.00 I   .169134  .000261   .259973  .000143  I -.1782903  .0000076  1.6015 0.0066  I   -19.405     .791    -7.902     .298   .169100   .259100  -.1784000   -20.300    -8.600  
+94 6 7 49510.00 I   .167779  .000220   .258226  .000159  I -.1798374  .0000081  1.4961 0.0057  I   -19.659     .116    -8.062     .298   .167900   .257300  -.1799400   -20.400    -8.800  
+94 6 8 49511.00 I   .166542  .000220   .256394  .000161  I -.1812913  .0000085  1.4172 0.0058  I   -19.626     .116    -8.274     .298   .166800   .255500  -.1813900   -20.300    -8.900  
+94 6 9 49512.00 I   .165561  .000220   .254458  .000146  I -.1826856  .0000084  1.3798 0.0061  I   -19.394     .116    -8.404     .298   .165700   .253600  -.1827900   -20.200    -9.000  
+94 610 49513.00 I   .164659  .000222   .252447  .000149  I -.1840720  .0000088  1.4058 0.0056  I   -19.114     .116    -8.469     .298   .164600   .251700  -.1842000   -20.000    -9.100  
+94 611 49514.00 I   .163719  .000226   .250366  .000146  I -.1855180  .0000074  1.4943 0.0076  I   -18.937     .116    -8.546     .298   .163600   .249600  -.1856600   -19.800    -9.100  
+94 612 49515.00 I   .162763  .000227   .248207  .000185  I -.1870737  .0000125  1.6222 0.0054  I   -18.989     .132    -8.653     .298   .162600   .247400  -.1872300   -19.600    -9.100  
+94 613 49516.00 I   .161851  .000150   .245977  .000231  I -.1887704  .0000080  1.7741 0.0074  I   -19.243     .276    -8.717     .249   .161800   .245200  -.1889200   -19.600    -9.000  
+94 614 49517.00 I   .161026  .000149   .243751  .000232  I -.1906238  .0000078  1.9318 0.0062  I   -19.475     .271    -8.624     .254   .161000   .243100  -.1907700   -19.800    -8.800  
+94 615 49518.00 I   .160281  .000153   .241641  .000241  I -.1926234  .0000094  2.0577 0.0058  I   -19.454     .271    -8.279     .254   .160200   .241000  -.1927500   -20.100    -8.700  
+94 616 49519.00 I   .159534  .000141   .239746  .000235  I -.1947203  .0000085  2.1269 0.0062  I   -19.190     .271    -7.649     .254   .159500   .239100  -.1948300   -20.500    -8.400  
+94 617 49520.00 I   .158676  .000159   .237991  .000257  I -.1968565  .0000082  2.1340 0.0049  I   -19.016     .271    -7.061     .254   .158700   .237400  -.1969500   -21.000    -8.300  
+94 618 49521.00 I   .157611  .000147   .236226  .000220  I -.1989637  .0000049  2.0671 0.0052  I   -19.208     .271    -6.696     .254   .157700   .235600  -.1990500   -21.400    -8.100  
+94 619 49522.00 I   .156276  .000146   .234349  .000184  I -.2009653  .0000065  1.9239 0.0038  I   -19.769     .192    -6.573     .185   .156500   .233800  -.2010400   -21.800    -8.000  
+94 620 49523.00 I   .154689  .000127   .232316  .000179  I -.2027923  .0000057  1.7232 0.0041  I   -20.493     .148    -6.755     .298   .155100   .231800  -.2028700   -22.000    -8.000  
+94 621 49524.00 I   .152998  .000139   .230146  .000171  I -.2044062  .0000049  1.5059 0.0038  I   -21.146     .148    -7.190     .298   .153500   .229600  -.2045000   -22.100    -8.000  
+94 622 49525.00 I   .151432  .000135   .227937  .000170  I -.2058193  .0000049  1.3341 0.0039  I   -21.641     .148    -7.629     .298   .151900   .227300  -.2059300   -22.100    -8.000  
+94 623 49526.00 I   .149986  .000123   .225843  .000155  I -.2071000  .0000061  1.2392 0.0040  I   -22.029     .289    -7.815     .298   .150100   .225100  -.2072300   -21.900    -8.100  
+94 624 49527.00 I   .148533  .000122   .223884  .000147  I -.2083200  .0000062  1.2114 0.0059  I   -22.261     .289    -7.712     .298   .148300   .223100  -.2084500   -21.800    -8.100  
+94 625 49528.00 I   .146973  .000158   .222011  .000151  I -.2095412  .0000102  1.2389 0.0079  I   -22.210     .316    -7.516     .298   .146500   .221200  -.2096800   -21.600    -8.100  
+94 626 49529.00 I   .145298  .000261   .220177  .000205  I -.2108058  .0000145  1.2903 0.0088  I   -21.905     .359    -7.442     .298   .144800   .219300  -.2109400   -21.700    -8.000  
+94 627 49530.00 I   .143565  .000270   .218360  .000251  I -.2121185  .0000144  1.3319 0.0106  I   -21.637     .293    -7.526     .298   .143000   .217500  -.2122400   -21.800    -8.000  
+94 628 49531.00 I   .141813  .000248   .216582  .000252  I -.2134590  .0000156  1.3419 0.0105  I   -21.735     .488    -7.650     .298   .141400   .215800  -.2135700   -22.100    -8.100  
+94 629 49532.00 I   .140036  .000246   .214909  .000253  I -.2147803  .0000153  1.2859 0.0112  I   -22.113     .470    -7.727     .336   .139800   .214200  -.2148800   -22.600    -8.000  
+94 630 49533.00 I   .138313  .000256   .213438  .000261  I -.2160203  .0000160  1.1984 0.0107  I   -22.429     .470    -7.778     .336   .138300   .212700  -.2161400   -23.100    -8.100  
+94 7 1 49534.00 I   .136704  .000246   .212123  .000260  I  .7828134  .0000151  1.1396 0.0112  I   -22.586     .495    -7.896     .359   .136800   .211500   .7826700   -23.700    -8.200  
+94 7 2 49535.00 I   .135090  .000228   .210874  .000257  I  .7817000  .0000158  1.0824 0.0111  I   -22.711     .495    -7.977     .359   .135000   .210300   .7815500   -24.300    -7.700  
+94 7 3 49536.00 I   .133370  .000217   .209627  .000206  I  .7806540  .0000164  1.0089 0.0098  I   -22.984     .535    -7.891     .387   .133300   .209000   .7805200   -24.300    -7.800  
+94 7 4 49537.00 I   .131521  .000171   .208338  .000169  I  .7796814  .0000116  0.9377 0.0094  I   -23.345     .396    -7.780     .416   .131400   .207600   .7795600   -24.200    -7.800  
+94 7 5 49538.00 I   .129613  .000140   .206974  .000120  I  .7787730  .0000093  0.8833 0.0074  I   -23.627     .251    -7.733     .241   .129500   .206200   .7786700   -23.900    -7.900  
+94 7 6 49539.00 I   .127726  .000134   .205520  .000147  I  .7779060  .0000092  0.8552 0.0065  I   -23.785     .265    -7.754     .244   .127700   .204600   .7778100   -23.700    -7.900  
+94 7 7 49540.00 I   .125890  .000123   .203972  .000139  I  .7770472  .0000090  0.8732 0.0065  I   -23.846     .265    -7.837     .244   .125900   .203000   .7769300   -23.400    -7.900  
+94 7 8 49541.00 I   .124100  .000119   .202429  .000137  I  .7761321  .0000091  0.9738 0.0073  I   -23.815     .265    -7.887     .244   .124100   .201400   .7759900   -23.100    -7.800  
+94 7 9 49542.00 I   .122316  .000122   .200998  .000145  I  .7750765  .0000114  1.1439 0.0081  I   -23.717     .265    -7.840     .244   .122400   .199900   .7749200   -22.900    -7.700  
+94 710 49543.00 I   .120582  .000120   .199702  .000172  I  .7738352  .0000133  1.3414 0.0086  I   -23.683     .266    -7.763     .236   .120600   .198700   .7737000   -22.900    -7.600  
+94 711 49544.00 I   .118900  .000197   .198504  .000149  I  .7723924  .0000129  1.5430 0.0098  I   -23.895     .171    -7.649     .144   .118800   .197600   .7722700   -23.100    -7.600  
+94 712 49545.00 I   .117262  .000212   .197367  .000155  I  .7707577  .0000144  1.7193 0.0098  I   -24.337     .288    -7.524     .154   .117100   .196600   .7706400   -23.400    -7.400  
+94 713 49546.00 I   .115585  .000219   .196254  .000144  I  .7689693  .0000147  1.8492 0.0108  I   -24.771     .289    -7.427     .146   .115300   .195500   .7688400   -23.900    -7.400  
+94 714 49547.00 I   .113774  .000210   .195114  .000147  I  .7670815  .0000162  1.9124 0.0108  I   -24.962     .289    -7.384     .146   .113500   .194400   .7669300   -24.500    -7.400  
+94 715 49548.00 I   .111917  .000204   .193886  .000157  I  .7651629  .0000159  1.9204 0.0112  I   -24.879     .289    -7.363     .146   .111700   .193100   .7649800   -25.000    -7.400  
+94 716 49549.00 I   .110060  .000186   .192527  .000164  I  .7632581  .0000156  1.8763 0.0113  I   -24.790     .316    -7.261     .160   .109900   .191700   .7630900   -25.500    -7.400  
+94 717 49550.00 I   .108157  .000190   .191009  .000196  I  .7614317  .0000160  1.7680 0.0105  I   -24.951     .324    -7.108     .164   .108000   .190200   .7613000   -25.900    -7.500  
+94 718 49551.00 I   .106172  .000114   .189314  .000232  I  .7597348  .0000142  1.6217 0.0104  I   -25.392     .196    -7.070     .298   .106000   .188400   .7596400   -26.100    -7.700  
+94 719 49552.00 I   .104134  .000078   .187488  .000220  I  .7581907  .0000132  1.4681 0.0097  I   -25.979     .394    -7.267     .298   .104000   .186600   .7581200   -26.000    -7.800  
+94 720 49553.00 I   .102165  .000080   .185697  .000223  I  .7567906  .0000131  1.3386 0.0094  I   -26.503     .426    -7.666     .298   .102000   .184800   .7567200   -25.900    -7.900  
+94 721 49554.00 I   .100269  .000084   .184109  .000224  I  .7554917  .0000133  1.2743 0.0083  I   -26.720     .426    -8.016     .298   .100100   .183100   .7553900   -25.700    -7.900  
+94 722 49555.00 I   .098391  .000080   .182709  .000195  I  .7542115  .0000102  1.3013 0.0100  I   -26.485     .426    -8.144     .298   .098200   .181700   .7540600   -25.500    -8.000  
+94 723 49556.00 I   .096537  .000087   .181392  .000201  I  .7528672  .0000150  1.3941 0.0124  I   -26.031     .482    -8.003     .298   .096400   .180400   .7526900   -25.300    -8.000  
+94 724 49557.00 I   .094755  .000094   .180140  .000155  I  .7514222  .0000227  1.4901 0.0110  I   -25.675     .589    -7.741     .298   .094600   .179200   .7512600   -25.300    -7.900  
+94 725 49558.00 I   .092961  .000095   .178983  .000129  I  .7499005  .0000161  1.5457 0.0129  I   -25.608     .365    -7.572     .102   .092700   .178100   .7497800   -25.400    -7.800  
+94 726 49559.00 I   .091017  .000095   .177952  .000101  I  .7483472  .0000123  1.5521 0.0099  I   -25.894     .791    -7.555     .105   .090700   .177100   .7482500   -25.700    -7.700  
+94 727 49560.00 I   .088891  .000094   .177080  .000117  I  .7468139  .0000114  1.5058 0.0086  I   -26.385     .175    -7.649     .140   .088500   .176200   .7467100   -26.200    -7.700  
+94 728 49561.00 I   .086705  .000104   .176385  .000121  I  .7453424  .0000120  1.4390 0.0071  I   -26.828     .175    -7.806     .140   .086300   .175400   .7451900   -26.700    -7.600  
+94 729 49562.00 I   .084616  .000106   .175803  .000130  I  .7439290  .0000083  1.3929 0.0086  I   -27.103     .175    -7.879     .140   .084200   .174700   .7437300   -27.200    -7.600  
+94 730 49563.00 I   .082635  .000104   .175254  .000134  I  .7425566  .0000122  1.3467 0.0095  I   -27.271     .175    -7.739     .140   .082100   .174200   .7423500   -27.600    -7.600  
+94 731 49564.00 I   .080660  .000113   .174710  .000181  I  .7412436  .0000172  1.2766 0.0086  I   -27.440     .169    -7.519     .169   .080200   .173800   .7410500   -27.800    -7.700  
+94 8 1 49565.00 I   .078707  .000115   .174217  .000167  I  .7400066  .0000122  1.1969 0.0105  I   -27.676     .146    -7.396     .155   .078500   .173400   .7398500   -28.000    -7.700  
+94 8 2 49566.00 I   .076835  .000114   .173815  .000233  I  .7388476  .0000122  1.1236 0.0089  I   -27.985     .272    -7.481     .128   .076800   .173100   .7387200   -27.800    -7.700  
+94 8 3 49567.00 I   .075074  .000115   .173500  .000238  I  .7377391  .0000130  1.1110 0.0089  I   -28.297     .369    -7.815     .120   .075100   .172800   .7376000   -27.700    -7.700  
+94 8 4 49568.00 I   .073460  .000112   .173232  .000230  I  .7366003  .0000130  1.1742 0.0088  I   -28.465     .369    -8.208     .120   .073400   .172500   .7364400   -27.500    -7.700  
+94 8 5 49569.00 I   .071866  .000127   .172970  .000229  I  .7353776  .0000119  1.2766 0.0094  I   -28.347     .369    -8.552     .120   .071600   .172200   .7352000   -27.100    -7.700  
+94 8 6 49570.00 I   .070233  .000141   .172666  .000192  I  .7340370  .0000137  1.4092 0.0103  I   -28.089     .425    -8.744     .298   .069900   .171700   .7339000   -27.600    -7.400  
+94 8 7 49571.00 I   .068588  .000160   .172309  .000195  I  .7325559  .0000169  1.5517 0.0102  I   -27.916     .469    -8.671     .298   .068300   .171400   .7324300   -27.700    -7.400  
+94 8 8 49572.00 I   .067030  .000164   .171954  .000213  I  .7309394  .0000151  1.6768 0.0114  I   -27.955     .419    -8.318     .298   .066800   .171300   .7308300   -27.800    -7.400  
+94 8 9 49573.00 I   .065656  .000172   .171684  .000181  I  .7292203  .0000153  1.7480 0.0108  I   -28.228     .547    -7.808     .169   .065400   .171200   .7291200   -28.000    -7.200  
+94 810 49574.00 I   .064458  .000175   .171547  .000180  I  .7274593  .0000155  1.7713 0.0111  I   -28.560     .658    -7.362     .182   .064100   .171200   .7273400   -28.200    -7.300  
+94 811 49575.00 I   .063177  .000176   .171524  .000190  I  .7256921  .0000162  1.7512 0.0106  I   -28.757     .658    -7.088     .182   .062700   .171200   .7255600   -28.500    -7.400  
+94 812 49576.00 I   .061639  .000167   .171505  .000195  I  .7239814  .0000145  1.6577 0.0103  I   -28.588     .658    -6.841     .182   .061100   .171000   .7238400   -28.800    -7.500  
+94 813 49577.00 I   .059681  .000189   .171353  .000175  I  .7223951  .0000126  1.5089 0.0112  I   -28.281     .734    -6.720     .209   .059100   .170700   .7222500   -29.100    -7.600  
+94 814 49578.00 I   .057308  .000206   .170981  .000140  I  .7209662  .0000170  1.3523 0.0091  I   -28.145     .718    -6.823     .202   .056900   .170200   .7208100   -29.300    -7.700  
+94 815 49579.00 I   .054665  .000188   .170386  .000139  I  .7196757  .0000132  1.2402 0.0107  I   -28.281     .538    -7.082     .126   .054500   .169600   .7195100   -29.300    -7.900  
+94 816 49580.00 I   .052050  .000176   .169688  .000119  I  .7184603  .0000130  1.2047 0.0089  I   -28.667     .130    -7.455     .298   .052000   .168900   .7183000   -29.200    -7.900  
+94 817 49581.00 I   .049759  .000195   .169084  .000115  I  .7172468  .0000118  1.2276 0.0088  I   -29.099     .130    -7.862     .298   .049700   .168300   .7171100   -29.100    -7.900  
+94 818 49582.00 I   .047661  .000195   .168749  .000091  I  .7159904  .0000119  1.2947 0.0084  I   -29.330     .130    -8.157     .298   .047300   .168000   .7158700   -28.800    -7.900  
+94 819 49583.00 I   .045502  .000198   .168670  .000093  I  .7146430  .0000119  1.4050 0.0079  I   -29.250     .130    -8.214     .298   .045000   .167800   .7145300   -28.500    -7.800  
+94 820 49584.00 I   .043003  .000174   .168739  .000106  I  .7131745  .0000105  1.5329 0.0071  I   -28.961     .126    -8.018     .298   .042400   .167900   .7130500   -28.400    -7.700  
+94 821 49585.00 I   .040105  .000156   .168840  .000130  I  .7115798  .0000078  1.6529 0.0077  I   -28.685     .791    -7.697     .298   .039800   .168000   .7114500   -28.400    -7.600  
+94 822 49586.00 I   .036966  .000256   .168869  .000241  I  .7098798  .0000114  1.7397 0.0071  I   -28.600     .278    -7.439     .298   .037000   .168000   .7097400   -28.600    -7.400  
+94 823 49587.00 I   .033817  .000249   .168787  .000242  I  .7081159  .0000118  1.7799 0.0083  I   -28.752     .271    -7.346     .298   .034200   .167900   .7079800   -28.900    -7.300  
+94 824 49588.00 I   .030911  .000250   .168608  .000243  I  .7063369  .0000122  1.7693 0.0085  I   -29.122     .315    -7.395     .298   .031400   .167600   .7062200   -29.400    -7.300  
+94 825 49589.00 I   .028467  .000253   .168424  .000243  I  .7045966  .0000123  1.7009 0.0086  I   -29.669     .315    -7.508     .298   .029000   .167400   .7044700   -29.800    -7.300  
+94 826 49590.00 I   .026502  .000277   .168362  .000243  I  .7029378  .0000122  1.6244 0.0084  I   -30.183     .315    -7.619     .298   .026800   .167300   .7027900   -30.200    -7.400  
+94 827 49591.00 I   .024679  .000269   .168471  .000226  I  .7013413  .0000114  1.5674 0.0090  I   -30.349     .315    -7.719     .298   .024700   .167400   .7011900   -30.500    -7.500  
+94 828 49592.00 I   .022800  .000288   .168698  .000224  I  .6998036  .0000132  1.5086 0.0075  I   -30.126     .331    -7.837     .298   .022700   .167700   .6996800   -30.600    -7.700  
+94 829 49593.00 I   .020795  .000197   .169007  .000125  I  .6983214  .0000097  1.4578 0.0081  I   -29.812     .357    -7.971     .298   .020600   .168100   .6982400   -30.500    -7.800  
+94 830 49594.00 I   .018609  .000185   .169415  .000116  I  .6968824  .0000093  1.4237 0.0066  I   -29.713     .266    -8.053     .298   .018400   .168600   .6968200   -30.200    -7.900  
+94 831 49595.00 I   .016183  .000172   .169907  .000115  I  .6954573  .0000090  1.4398 0.0064  I   -29.858     .245    -8.001     .298   .016100   .169000   .6953800   -30.000    -7.900  
+94 9 1 49596.00 I   .013552  .000149   .170355  .000120  I  .6939768  .0000089  1.5340 0.0061  I   -29.913     .245    -7.856     .298   .013700   .169400   .6938700   -29.600    -7.900  
+94 9 2 49597.00 I   .010952  .000128   .170717  .000126  I  .6923683  .0000083  1.6913 0.0066  I   -29.700     .245    -7.829     .298   .011200   .169800   .6922400   -29.200    -7.800  
+94 9 3 49598.00 I   .008574  .000125   .171044  .000126  I  .6905787  .0000097  1.8952 0.0065  I   -29.379     .202    -7.949     .298   .008800   .170200   .6904400   -29.100    -7.700  
+94 9 4 49599.00 I   .006431  .000122   .171426  .000121  I  .6885696  .0000101  2.1240 0.0074  I   -29.182     .132    -8.049     .107   .006400   .170700   .6884300   -29.000    -7.500  
+94 9 5 49600.00 I   .004323  .000130   .171935  .000116  I  .6863372  .0000111  2.3334 0.0077  I   -29.213     .122    -7.953     .298   .004000   .171000   .6862300   -29.400    -7.400  
+94 9 6 49601.00 I   .002002  .000148   .172597  .000123  I  .6839238  .0000117  2.4798 0.0081  I   -29.478     .285    -7.625     .263   .001600   .171800   .6838300   -29.700    -7.300  
+94 9 7 49602.00 I  -.000616  .000165   .173385  .000129  I  .6814098  .0000119  2.5294 0.0085  I   -29.918     .269    -7.240     .237  -.000800   .172700   .6813000   -30.100    -7.200  
+94 9 8 49603.00 I  -.003456  .000162   .174249  .000122  I  .6788784  .0000122  2.5387 0.0085  I   -30.414     .269    -7.010     .237  -.003500   .173600   .6787400   -30.400    -7.200  
+94 9 9 49604.00 I  -.006148  .000167   .175135  .000119  I  .6763470  .0000122  2.5042 0.0086  I   -30.813     .269    -7.039     .237  -.006100   .174600   .6762100   -30.700    -7.200  
+94 910 49605.00 I  -.008596  .000172   .176085  .000124  I  .6738930  .0000122  2.4007 0.0097  I   -30.956     .269    -7.180     .237  -.008500   .175500   .6737700   -30.800    -7.400  
+94 911 49606.00 I  -.010833  .000180   .177119  .000121  I  .6715460  .0000150  2.2959 0.0079  I   -30.831     .270    -7.279     .236  -.010800   .176500   .6714500   -30.900    -7.400  
+94 912 49607.00 I  -.013072  .000198   .178169  .000123  I  .6692901  .0000101  2.2243 0.0092  I   -30.566     .133    -7.349     .298  -.013100   .177400   .6692100   -30.600    -7.500  
+94 913 49608.00 I  -.015556  .000172   .179143  .000122  I  .6670788  .0000106  2.2084 0.0069  I   -30.308     .791    -7.449     .298  -.015600   .178200   .6670100   -30.400    -7.600  
+94 914 49609.00 I  -.018422  .000167   .179980  .000116  I  .6648563  .0000094  2.2434 0.0071  I   -30.158     .151    -7.589     .298  -.018400   .179100   .6647800   -30.100    -7.500  
+94 915 49610.00 I  -.021599  .000162   .180790  .000122  I  .6625777  .0000095  2.3212 0.0065  I   -30.105     .151    -7.710     .298  -.021400   .179800   .6624700   -29.800    -7.500  
+94 916 49611.00 I  -.024813  .000164   .181577  .000124  I  .6601997  .0000091  2.4414 0.0066  I   -30.049     .151    -7.730     .298  -.024700   .180600   .6600700   -29.600    -7.300  
+94 917 49612.00 I  -.027798  .000153   .182332  .000142  I  .6576960  .0000092  2.5583 0.0067  I   -29.920     .178    -7.609     .298  -.027800   .181300   .6575600   -29.400    -7.200  
+94 918 49613.00 I  -.030505  .000136   .183089  .000153  I  .6551011  .0000098  2.6213 0.0054  I   -29.808     .235    -7.388     .298  -.030700   .182200   .6549800   -29.400    -7.100  
+94 919 49614.00 I  -.033007  .000153   .183934  .000145  I  .6524739  .0000057  2.6229 0.0055  I   -29.836     .195    -7.172     .298  -.033300   .183100   .6523600   -29.500    -6.900  
+94 920 49615.00 I  -.035461  .000150   .184962  .000153  I  .6498753  .0000050  2.5646 0.0039  I   -30.017     .177    -7.061     .298  -.035800   .184200   .6497700   -29.700    -7.000  
+94 921 49616.00 I  -.038015  .000154   .186147  .000148  I  .6473536  .0000053  2.4796 0.0036  I   -30.328     .236    -7.099     .298  -.038400   .185400   .6472300   -30.100    -7.000  
+94 922 49617.00 I  -.040832  .000163   .187296  .000151  I  .6449207  .0000053  2.3806 0.0040  I   -30.690     .236    -7.186     .298  -.041000   .186600   .6447800   -30.300    -7.100  
+94 923 49618.00 I  -.043818  .000160   .188375  .000146  I  .6426013  .0000060  2.2548 0.0040  I   -30.923     .236    -7.290     .298  -.043800   .187700   .6424600   -30.600    -7.200  
+94 924 49619.00 I  -.046775  .000165   .189470  .000129  I  .6404117  .0000059  2.1271 0.0049  I   -30.778     .232    -7.429     .298  -.046600   .188700   .6402600   -30.600    -7.300  
+94 925 49620.00 I  -.049585  .000145   .190626  .000157  I  .6383387  .0000078  2.0244 0.0041  I   -30.261     .309    -7.585     .298  -.049400   .189700   .6381900   -30.500    -7.600  
+94 926 49621.00 I  -.052280  .000127   .191848  .000143  I  .6363505  .0000056  1.9587 0.0047  I   -29.706     .264    -7.744     .298  -.052300   .190900   .6362000   -30.200    -7.700  
+94 927 49622.00 I  -.054909  .000132   .193105  .000143  I  .6344068  .0000054  1.9365 0.0041  I   -29.502     .229    -7.860     .298  -.055100   .192100   .6342700   -29.900    -7.700  
+94 928 49623.00 I  -.057521  .000134   .194405  .000155  I  .6324646  .0000061  1.9532 0.0052  I   -29.675     .229    -7.841     .298  -.057900   .193600   .6323400   -29.500    -7.700  
+94 929 49624.00 I  -.060233  .000131   .195865  .000160  I  .6304856  .0000088  2.0144 0.0053  I   -29.819     .229    -7.680     .298  -.060700   .195100   .6303600   -29.100    -7.600  
+94 930 49625.00 I  -.062857  .000132   .197484  .000168  I  .6284157  .0000086  2.1359 0.0065  I   -29.697     .229    -7.504     .298  -.063300   .196800   .6282800   -28.800    -7.500  
+9410 1 49626.00 I  -.065164  .000139   .199217  .000171  I  .6261970  .0000096  2.3078 0.0071  I   -29.482     .135    -7.481     .298  -.065500   .198500   .6260500   -28.700    -7.300  
+9410 2 49627.00 I  -.067149  .000138   .201047  .000165  I  .6237941  .0000114  2.4978 0.0070  I   -29.431     .221    -7.604     .298  -.067400   .200300   .6236400   -28.700    -7.100  
+9410 3 49628.00 I  -.068989  .000137   .202944  .000165  I  .6212049  .0000101  2.6771 0.0076  I   -29.544     .210    -7.670     .298  -.069200   .202200   .6210500   -28.800    -7.000  
+9410 4 49629.00 I  -.070976  .000189   .204837  .000163  I  .6184532  .0000100  2.8163 0.0064  I   -29.597     .617    -7.515     .298  -.071200   .204000   .6183100   -29.100    -6.900  
+9410 5 49630.00 I  -.073424  .000189   .206629  .000149  I  .6155998  .0000077  2.8730 0.0063  I   -29.430     .636    -7.233     .298  -.073900   .205500   .6155100   -29.300    -6.700  
+9410 6 49631.00 I  -.076446  .000186   .208213  .000149  I  .6127461  .0000077  2.8130 0.0052  I   -29.179     .636    -7.115     .298  -.076800   .207100   .6126800   -29.600    -6.900  
+9410 7 49632.00 I  -.079838  .000186   .209601  .000144  I  .6100058  .0000070  2.6571 0.0049  I   -29.178     .636    -7.176     .298  -.080000   .208600   .6099500   -29.800    -6.900  
+9410 8 49633.00 I  -.083262  .000194   .210886  .000134  I  .6074385  .0000060  2.4813 0.0045  I   -29.386     .723    -7.226     .298  -.083300   .210000   .6073700   -29.800    -7.100  
+9410 9 49634.00 I  -.086479  .000211   .212130  .000184  I  .6050286  .0000057  2.3492 0.0038  I   -29.605     .874    -7.178     .298  -.086500   .211300   .6049500   -29.600    -7.200  
+941010 49635.00 I  -.089290  .000169   .213380  .000144  I  .6027164  .0000046  2.2882 0.0037  I   -29.663     .487    -7.125     .298  -.089300   .212600   .6026200   -29.300    -7.200  
+941011 49636.00 I  -.091505  .000134   .214693  .000114  I  .6004284  .0000047  2.2986 0.0033  I   -29.374     .791    -7.157     .298  -.091600   .214000   .6003300   -29.000    -7.200  
+941012 49637.00 I  -.093166  .000133   .216160  .000114  I  .5981027  .0000047  2.3584 0.0050  I   -28.789     .791    -7.217     .105  -.093400   .215500   .5980000   -28.500    -7.100  
+941013 49638.00 I  -.094538  .000137   .217881  .000124  I  .5957062  .0000088  2.4344 0.0052  I   -28.195     .791    -7.171     .105  -.094800   .217200   .5956100   -28.100    -7.000  
+941014 49639.00 I  -.095750  .000120   .219840  .000120  I  .5932373  .0000092  2.5003 0.0063  I   -27.833     .791    -6.981     .105  -.095900   .219100   .5931400   -27.800    -6.700  
+941015 49640.00 I  -.096889  .000115   .221990  .000123  I  .5907151  .0000091  2.5377 0.0070  I   -27.732     .791    -6.730     .298  -.096900   .221100   .5906300   -27.500    -6.600  
+941016 49641.00 I  -.098078  .000120   .224264  .000151  I  .5881772  .0000106  2.5292 0.0068  I   -27.799     .791    -6.522     .113  -.098000   .223400   .5881000   -27.400    -6.400  
+941017 49642.00 I  -.099501  .000137   .226604  .000138  I  .5856753  .0000101  2.4650 0.0079  I   -27.949     .791    -6.388     .100  -.099500   .225700   .5856200   -27.400    -6.300  
+941018 49643.00 I  -.101377  .000139   .228955  .000166  I  .5832655  .0000117  2.3458 0.0066  I   -28.097     .145    -6.342     .298  -.101500   .228000   .5832200   -27.600    -6.200  
+941019 49644.00 I  -.103841  .000157   .231268  .000168  I  .5809929  .0000084  2.1989 0.0077  I   -28.159     .146    -6.428     .298  -.104100   .230300   .5809500   -27.600    -6.200  
+941020 49645.00 I  -.106752  .000150   .233466  .000159  I  .5788597  .0000099  2.0761 0.0065  I   -28.151     .146    -6.598     .298  -.107100   .232600   .5788000   -27.800    -6.300  
+941021 49646.00 I  -.109750  .000145   .235599  .000154  I  .5768260  .0000100  1.9973 0.0065  I   -28.099     .152    -6.777     .298  -.110100   .234900   .5767600   -27.900    -6.600  
+941022 49647.00 I  -.112530  .000130   .237770  .000135  I  .5748551  .0000085  1.9483 0.0080  I   -27.906     .152    -6.895     .298  -.112800   .237100   .5747800   -27.900    -6.700  
+941023 49648.00 I  -.114973  .000108   .239947  .000137  I  .5729195  .0000124  1.9288 0.0060  I   -27.529     .200    -6.919     .298  -.115100   .239300   .5728500   -27.700    -6.900  
+941024 49649.00 I  -.117092  .000113   .242100  .000147  I  .5709849  .0000085  1.9471 0.0077  I   -27.136     .189    -6.900     .298  -.117200   .241300   .5709100   -27.400    -7.000  
+941025 49650.00 I  -.119084  .000118   .244217  .000210  I  .5690110  .0000090  2.0083 0.0058  I   -26.957     .181    -6.902     .298  -.119200   .243300   .5689300   -27.100    -7.100  
+941026 49651.00 I  -.121195  .000117   .246300  .000210  I  .5669543  .0000078  2.1115 0.0060  I   -26.972     .347    -6.898     .298  -.121400   .245300   .5668700   -26.800    -7.100  
+941027 49652.00 I  -.123525  .000121   .248390  .000209  I  .5647789  .0000079  2.2419 0.0056  I   -26.961     .347    -6.781     .298  -.123800   .247300   .5646900   -26.600    -6.900  
+941028 49653.00 I  -.125949  .000123   .250477  .000214  I  .5624625  .0000079  2.3964 0.0054  I   -26.804     .347    -6.581     .298  -.126100   .249400   .5623800   -26.400    -6.700  
+941029 49654.00 I  -.128152  .000152   .252528  .000235  I  .5599782  .0000074  2.5748 0.0061  I   -26.673     .366    -6.388     .298  -.128300   .251500   .5599200   -26.500    -6.600  
+941030 49655.00 I  -.130001  .000159   .254583  .000231  I  .5573138  .0000094  2.7507 0.0051  I   -26.803     .447    -6.270     .104  -.130200   .253700   .5572700   -26.600    -6.300  
+941031 49656.00 I  -.131520  .000155   .256710  .000201  I  .5544892  .0000071  2.8894 0.0057  I   -27.115     .480    -6.190     .101  -.131800   .255900   .5544400   -26.900    -6.300  
+9411 1 49657.00 I  -.132859  .000160   .258913  .000127  I  .5515578  .0000065  2.9599 0.0051  I   -27.224     .424    -6.064     .298  -.133200   .258200   .5515000   -27.100    -6.200  
+9411 2 49658.00 I  -.134179  .000156   .261087  .000129  I  .5485981  .0000073  2.9445 0.0051  I   -26.818     .424    -5.963     .298  -.134500   .260400   .5485300   -27.300    -6.200  
+9411 3 49659.00 I  -.135582  .000161   .263155  .000113  I  .5457003  .0000079  2.8346 0.0053  I   -26.109     .424    -5.946     .298  -.135800   .262600   .5456100   -27.500    -6.200  
+9411 4 49660.00 I  -.136997  .000157   .265187  .000106  I  .5429500  .0000077  2.6615 0.0057  I   -25.467     .424    -5.987     .298  -.137200   .264900   .5428600   -28.000    -6.100  
+9411 5 49661.00 I  -.138425  .000121   .267286  .000088  I  .5403769  .0000081  2.4897 0.0079  I   -25.234     .297    -5.951     .298  -.138600   .267000   .5402800   -27.700    -6.200  
+9411 6 49662.00 I  -.139887  .000157   .269503  .000130  I  .5379537  .0000137  2.3687 0.0062  I   -25.520     .791    -5.795     .298  -.140100   .269100   .5378600   -27.200    -6.200  
+9411 7 49663.00 I  -.141344  .000139   .271822  .000107  I  .5356169  .0000094  2.3154 0.0082  I   -26.008     .157    -5.692     .298  -.141700   .271300   .5355300   -26.700    -6.100  
+9411 8 49664.00 I  -.142740  .000149   .274220  .000101  I  .5333062  .0000089  2.3121 0.0062  I   -26.181     .157    -5.819     .298  -.143100   .273600   .5332300   -26.100    -6.100  
+9411 9 49665.00 I  -.143972  .000163   .276693  .000095  I  .5309772  .0000081  2.3554 0.0062  I   -25.847     .141    -6.093     .298  -.144300   .276000   .5309100   -25.600    -5.900  
+941110 49666.00 I  -.144804  .000165   .279285  .000090  I  .5285867  .0000085  2.4250 0.0058  I   -25.301     .141    -6.270     .298  -.145200   .278700   .5285300   -25.300    -5.800  
+941111 49667.00 I  -.145287  .000167   .281983  .000089  I  .5261314  .0000084  2.4822 0.0060  I   -24.982     .141    -6.215     .298  -.145700   .281400   .5260800   -25.100    -5.500  
+941112 49668.00 I  -.145653  .000176   .284744  .000100  I  .5236320  .0000084  2.5105 0.0093  I   -24.995     .165    -6.033     .298  -.146200   .284200   .5236000   -24.900    -5.400  
+941113 49669.00 I  -.146085  .000137   .287529  .000106  I  .5211225  .0000166  2.5025 0.0067  I   -25.125     .100    -5.890     .298  -.146500   .286900   .5210900   -25.000    -5.300  
+941114 49670.00 I  -.146623  .000138   .290267  .000131  I  .5186373  .0000104  2.4635 0.0098  I   -25.220     .791    -5.802     .298  -.146800   .289600   .5186000   -25.200    -5.300  
+941115 49671.00 I  -.147213  .000135   .292902  .000140  I  .5162031  .0000105  2.4019 0.0078  I   -25.299     .791    -5.682     .298  -.147200   .292300   .5161600   -25.300    -5.400  
+941116 49672.00 I  -.147808  .000101   .295464  .000142  I  .5138394  .0000116  2.3228 0.0080  I   -25.366     .791    -5.524     .298  -.147700   .294900   .5137800   -25.400    -5.500  
+941117 49673.00 I  -.148488  .000101   .298075  .000147  I  .5115623  .0000122  2.2293 0.0084  I   -25.355     .791    -5.410     .298  -.148300   .297500   .5114900   -25.500    -5.500  
+941118 49674.00 I  -.149331  .000109   .300760  .000141  I  .5093815  .0000122  2.1336 0.0073  I   -25.239     .791    -5.379     .298  -.149200   .300200   .5093100   -25.600    -5.700  
+941119 49675.00 I  -.150308  .000100   .303477  .000122  I  .5072894  .0000079  2.0548 0.0103  I   -25.045     .791    -5.368     .298  -.150300   .302900   .5072100   -25.400    -5.800  
+941120 49676.00 I  -.151335  .000092   .306191  .000112  I  .5052594  .0000166  2.0133 0.0065  I   -24.808     .165    -5.328     .298  -.151400   .305600   .5051700   -25.200    -5.900  
+941121 49677.00 I  -.152336  .000133   .308941  .000110  I  .5032454  .0000102  2.0239 0.0093  I   -24.601     .175    -5.319     .298  -.152500   .308400   .5031400   -24.900    -5.800  
+941122 49678.00 I  -.153136  .000129   .311793  .000113  I  .5011934  .0000082  2.0891 0.0063  I   -24.547     .175    -5.435     .298  -.153400   .311100   .5010800   -24.500    -5.800  
+941123 49679.00 I  -.153511  .000141   .314720  .000109  I  .4990493  .0000075  2.2081 0.0057  I   -24.659     .175    -5.642     .298  -.153800   .313900   .4989500   -24.200    -5.600  
+941124 49680.00 I  -.153354  .000165   .317579  .000122  I  .4967655  .0000078  2.3621 0.0047  I   -24.704     .175    -5.716     .298  -.153700   .316700   .4967000   -24.000    -5.400  
+941125 49681.00 I  -.152777  .000179   .320381  .000118  I  .4943244  .0000057  2.5182 0.0069  I   -24.517     .175    -5.571     .298  -.153100   .319500   .4942900   -23.700    -5.200  
+941126 49682.00 I  -.152113  .000199   .323160  .000175  I  .4917358  .0000113  2.6543 0.0066  I   -24.210     .185    -5.329     .298  -.152300   .322300   .4917300   -23.600    -5.000  
+941127 49683.00 I  -.151650  .000230   .325909  .000179  I  .4890285  .0000120  2.7525 0.0077  I   -24.031     .130    -5.127     .298  -.151600   .325100   .4890400   -23.700    -4.800  
+941128 49684.00 I  -.151460  .000193   .328635  .000162  I  .4862510  .0000106  2.7901 0.0080  I   -24.087     .121    -4.977     .298  -.151200   .327900   .4862600   -23.800    -4.800  
+941129 49685.00 I  -.151383  .000184   .331360  .000163  I  .4834753  .0000107  2.7465 0.0076  I   -24.250     .121    -4.831     .298  -.151200   .330600   .4834500   -23.900    -4.700  
+941130 49686.00 I  -.151275  .000171   .334074  .000169  I  .4807701  .0000109  2.6664 0.0076  I   -24.308     .121    -4.744     .298  -.151400   .333400   .4806900   -23.900    -4.700  
+9412 1 49687.00 I  -.151498  .000148   .336727  .000158  I  .4781455  .0000109  2.5772 0.0074  I   -24.154     .110    -4.797     .298  -.151700   .336100   .4780300   -24.000    -4.900  
+9412 2 49688.00 I  -.152003  .000145   .339262  .000158  I  .4756244  .0000100  2.4620 0.0066  I   -23.860     .110    -4.966     .298  -.152200   .338700   .4755000   -24.000    -5.000  
+9412 3 49689.00 I  -.152556  .000125   .341652  .000123  I  .4732183  .0000076  2.3565 0.0075  I   -23.675     .791    -5.060     .298  -.152500   .341100   .4730900   -23.900    -5.100  
+9412 4 49690.00 I  -.152865  .000092   .343888  .000153  I  .4708950  .0000111  2.3003 0.0052  I   -23.792     .162    -4.944     .298  -.152900   .343200   .4707300   -24.000    -5.300  
+9412 5 49691.00 I  -.152737  .000097   .346018  .000149  I  .4685954  .0000072  2.3109 0.0068  I   -24.054     .252    -4.767     .298  -.152900   .345300   .4684300   -23.500    -5.300  
+9412 6 49692.00 I  -.152319  .000106   .348133  .000148  I  .4662553  .0000079  2.3752 0.0053  I   -24.048     .230    -4.791     .298  -.152600   .347400   .4661100   -23.300    -5.200  
+9412 7 49693.00 I  -.151855  .000104   .350338  .000142  I  .4638417  .0000079  2.4492 0.0054  I   -23.616     .265    -5.034     .298  -.152200   .349600   .4637200   -23.300    -5.000  
+9412 8 49694.00 I  -.151502  .000124   .352762  .000150  I  .4613657  .0000075  2.4966 0.0055  I   -23.189     .265    -5.183     .298  -.151900   .352100   .4612800   -23.000    -4.800  
+9412 9 49695.00 I  -.151377  .000150   .355413  .000160  I  .4588597  .0000077  2.5104 0.0046  I   -23.153     .265    -5.046     .298  -.151700   .354700   .4587800   -22.900    -4.700  
+941210 49696.00 I  -.151519  .000160   .358227  .000137  I  .4563534  .0000052  2.4986 0.0052  I   -23.433     .282    -4.750     .298  -.151700   .357600   .4562800   -22.800    -4.400  
+941211 49697.00 I  -.152018  .000164   .361091  .000124  I  .4538684  .0000069  2.4690 0.0037  I   -23.665     .182    -4.531     .298  -.152000   .360500   .4537800   -22.900    -4.400  
+941212 49698.00 I  -.152813  .000156   .363880  .000124  I  .4514189  .0000052  2.4288 0.0043  I   -23.655     .220    -4.470     .298  -.152600   .363300   .4513200   -22.900    -4.300  
+941213 49699.00 I  -.153503  .000156   .366531  .000131  I  .4490111  .0000052  2.3877 0.0040  I   -23.518     .220    -4.502     .298  -.153200   .366000   .4489200   -22.900    -4.400  
+941214 49700.00 I  -.153781  .000150   .369106  .000142  I  .4466544  .0000062  2.3139 0.0040  I   -23.379     .181    -4.584     .298  -.153800   .368500   .4465900   -23.000    -4.400  
+941215 49701.00 I  -.153973  .000146   .371747  .000149  I  .4443857  .0000062  2.2330 0.0043  I   -23.276     .181    -4.656     .298  -.154400   .370900   .4443300   -23.000    -4.500  
+941216 49702.00 I  -.154240  .000148   .374469  .000154  I  .4421722  .0000059  2.2006 0.0045  I   -23.179     .181    -4.710     .298  -.154900   .373300   .4421100   -23.000    -4.800  
+941217 49703.00 I  -.154662  .000116   .377245  .000159  I  .4399678  .0000064  2.2182 0.0049  I   -23.123     .164    -4.723     .298  -.155400   .375900   .4398900   -22.800    -4.900  
+941218 49704.00 I  -.155272  .000130   .380014  .000181  I  .4377180  .0000077  2.2892 0.0047  I   -23.120     .183    -4.675     .298  -.156000   .378700   .4376300   -22.700    -4.900  
+941219 49705.00 I  -.156060  .000119   .382715  .000166  I  .4353743  .0000070  2.4056 0.0047  I   -23.084     .194    -4.632     .112  -.156700   .381500   .4352700   -22.500    -5.000  
+941220 49706.00 I  -.156932  .000122   .385263  .000184  I  .4328925  .0000055  2.5650 0.0045  I   -22.946     .237    -4.670     .135  -.157400   .384300   .4327900   -22.400    -4.900  
+941221 49707.00 I  -.157709  .000119   .387602  .000171  I  .4302489  .0000056  2.7106 0.0039  I   -22.740     .237    -4.765     .135  -.158000   .386800   .4301800   -22.300    -4.700  
+941222 49708.00 I  -.158271  .000100   .389863  .000142  I  .4274840  .0000055  2.8181 0.0039  I   -22.605     .237    -4.798     .135  -.158600   .389100   .4274400   -22.300    -4.400  
+941223 49709.00 I  -.158674  .000098   .392127  .000145  I  .4246131  .0000055  2.9243 0.0043  I   -22.550     .237    -4.680     .135  -.159000   .391400   .4245700   -22.200    -4.100  
+941224 49710.00 I  -.158946  .000107   .394483  .000172  I  .4216396  .0000065  3.0178 0.0051  I   -22.525     .215    -4.434     .185  -.159200   .393700   .4215900   -22.300    -3.800  
+941225 49711.00 I  -.159032  .000143   .397043  .000170  I  .4185905  .0000087  3.0722 0.0048  I   -22.553     .791    -4.146     .298  -.159300   .396200   .4185400   -22.500    -3.500  
+941226 49712.00 I  -.158912  .000146   .399861  .000124  I  .4155133  .0000070  3.0723 0.0059  I   -22.682     .791    -3.874     .298  -.159200   .399100   .4154600   -22.600    -3.300  
+941227 49713.00 I  -.158656  .000148   .402918  .000211  I  .4124665  .0000080  3.0106 0.0054  I   -22.908     .791    -3.651     .298  -.159000   .402200   .4124000   -22.700    -3.200  
+941228 49714.00 I  -.158336  .000147   .406112  .000211  I  .4095072  .0000081  2.9037 0.0057  I   -23.150     .162    -3.573     .298  -.158700   .405500   .4094300   -22.700    -3.100  
+941229 49715.00 I  -.157891  .000153   .409294  .000210  I  .4066683  .0000082  2.7694 0.0057  I   -23.281     .162    -3.761     .298  -.158100   .408700   .4065700   -22.600    -3.200  
+941230 49716.00 I  -.156905  .000153   .412426  .000207  I  .4039580  .0000081  2.6665 0.0058  I   -23.240     .162    -4.218     .298  -.157100   .411700   .4038300   -22.300    -3.300  
+941231 49717.00 I  -.155298  .000148   .415519  .000209  I  .4013094  .0000081  2.6414 0.0059  I   -23.114     .162    -4.629     .298  -.155600   .414800   .4011600   -21.900    -3.300  
+95 1 1 49718.00 I  -.153189  .000141   .418559  .000222  I  .3986542  .0000085  2.6795 0.0055  I   -23.041     .180    -4.690     .298  -.153600   .417700   .3985000   -21.600    -3.400  
+95 1 2 49719.00 I  -.150825  .000118   .421482  .000225  I  .3959327  .0000075  2.7708 0.0064  I   -23.011     .179    -4.436     .298  -.151300   .420500   .3957900   -21.200    -3.400  
+95 1 3 49720.00 I  -.148493  .000091   .424222  .000141  I  .3931052  .0000095  2.8841 0.0059  I   -22.859     .791    -4.143     .298  -.148900   .423300   .3929800   -22.600    -3.900  
+95 1 4 49721.00 I  -.146361  .000074   .426771  .000140  I  .3901717  .0000092  2.9756 0.0069  I   -22.540     .791    -4.023     .298  -.146700   .426000   .3900700   -22.700    -3.800  
+95 1 5 49722.00 I  -.144479  .000075   .429174  .000140  I  .3871759  .0000099  3.0014 0.0069  I   -22.305     .791    -4.043     .298  -.144700   .428500   .3870900   -22.800    -3.900  
+95 1 6 49723.00 I  -.142828  .000071   .431398  .000139  I  .3841933  .0000104  2.9540 0.0075  I   -22.431     .791    -4.051     .298  -.143100   .430800   .3841100   -22.900    -3.900  
+95 1 7 49724.00 I  -.141374  .000109   .433434  .000199  I  .3812858  .0000113  2.8529 0.0096  I   -22.839     .791    -4.004     .298  -.141600   .432800   .3812000   -23.000    -3.900  
+95 1 8 49725.00 I  -.140045  .000146   .435337  .000266  I  .3785005  .0000162  2.7128 0.0069  I   -23.190     .791    -3.985     .298  -.140300   .434700   .3784200   -23.300    -4.000  
+95 1 9 49726.00 I  -.138689  .000123   .437218  .000223  I  .3758672  .0000080  2.5516 0.0091  I   -23.310     .791    -4.048     .298  -.138900   .436700   .3757900   -23.500    -4.100  
+95 110 49727.00 I  -.137139  .000123   .439265  .000231  I  .3734000  .0000081  2.3824 0.0056  I   -23.314     .791    -4.168     .298  -.137400   .438800   .3733300   -23.500    -4.300  
+95 111 49728.00 I  -.135392  .000122   .441655  .000235  I  .3710942  .0000078  2.2379 0.0054  I   -23.318     .791    -4.303     .298  -.135800   .441100   .3710100   -23.500    -4.600  
+95 112 49729.00 I  -.133709  .000124   .444245  .000232  I  .3689076  .0000072  2.1433 0.0051  I   -23.243     .791    -4.386     .298  -.134100   .443500   .3688100   -23.300    -4.800  
+95 113 49730.00 I  -.132167  .000114   .446876  .000228  I  .3667940  .0000067  2.0895 0.0055  I   -23.043     .791    -4.399     .298  -.132600   .446100   .3666900   -23.100    -5.000  
+95 114 49731.00 I  -.130820  .000091   .449483  .000178  I  .3647144  .0000083  2.0783 0.0083  I   -22.842     .791    -4.343     .298  -.131200   .448700   .3646100   -22.800    -5.100  
+95 115 49732.00 I  -.129771  .000120   .452053  .000158  I  .3626227  .0000152  2.1111 0.0073  I   -22.760     .791    -4.265     .298  -.130200   .451300   .3625200   -22.400    -5.200  
+95 116 49733.00 I  -.129050  .000211   .454549  .000164  I  .3604814  .0000120  2.1762 0.0096  I   -22.734     .483    -4.270     .144  -.129400   .453800   .3603800   -22.100    -5.200  
+95 117 49734.00 I  -.128552  .000213   .456895  .000160  I  .3582618  .0000117  2.2669 0.0085  I   -22.655     .513    -4.429     .151  -.128800   .456200   .3581600   -21.900    -5.000  
+95 118 49735.00 I  -.128075  .000216   .459036  .000143  I  .3559323  .0000119  2.4035 0.0084  I   -22.589     .513    -4.717     .151  -.128200   .458300   .3558300   -21.800    -4.800  
+95 119 49736.00 I  -.127274  .000216   .460979  .000134  I  .3534489  .0000120  2.5576 0.0077  I   -22.721     .513    -5.033     .151  -.127500   .460200   .3533500   -21.800    -4.600  
+95 120 49737.00 I  -.126173  .000222   .462741  .000144  I  .3508263  .0000097  2.6839 0.0070  I   -22.958     .513    -5.129     .151  -.126600   .461900   .3507400   -21.900    -4.300  
+95 121 49738.00 I  -.124927  .000169   .464397  .000124  I  .3480913  .0000073  2.7794 0.0060  I   -23.146     .513    -4.947     .151  -.125400   .463400   .3480000   -22.200    -4.100  
+95 122 49739.00 I  -.123597  .000096   .466094  .000096  I  .3452808  .0000070  2.8348 0.0050  I   -23.225     .276    -4.613     .114  -.124000   .465200   .3452000   -22.400    -4.000  
+95 123 49740.00 I  -.122176  .000098   .468000  .000105  I  .3424368  .0000069  2.8447 0.0053  I   -23.209     .101    -4.237     .298  -.122500   .467100   .3423600   -22.800    -3.900  
+95 124 49741.00 I  -.120697  .000099   .470190  .000110  I  .3396079  .0000079  2.8050 0.0052  I   -23.207     .101    -3.924     .298  -.120900   .469400   .3395300   -22.900    -3.900  
+95 125 49742.00 I  -.119243  .000101   .472586  .000109  I  .3368351  .0000078  2.7404 0.0055  I   -23.344     .791    -3.810     .298  -.119300   .471900   .3367500   -22.900    -3.900  
+95 126 49743.00 I  -.117856  .000104   .475101  .000110  I  .3341227  .0000077  2.6891 0.0053  I   -23.656     .791    -3.985     .298  -.117900   .474400   .3340300   -22.900    -4.100  
+95 127 49744.00 I  -.116658  .000100   .477515  .000108  I  .3314510  .0000071  2.6555 0.0060  I   -24.026     .791    -4.436     .298  -.116700   .476800   .3313600   -22.800    -4.200  
+95 128 49745.00 I  -.115778  .000118   .479680  .000113  I  .3287997  .0000093  2.6578 0.0071  I   -24.304     .128    -4.978     .298  -.115800   .479000   .3287100   -22.700    -4.200  
+95 129 49746.00 I  -.115216  .000159   .481614  .000120  I  .3261178  .0000123  2.7130 0.0058  I   -24.434     .160    -5.290     .138  -.115300   .480900   .3260400   -22.600    -4.300  
+95 130 49747.00 I  -.114986  .000179   .483338  .000179  I  .3233651  .0000069  2.7940 0.0084  I   -24.403     .180    -5.194     .143  -.115200   .482600   .3233000   -22.500    -4.200  
+95 131 49748.00 I  -.115087  .000228   .484913  .000183  I  .3205334  .0000114  2.8640 0.0066  I   -24.191     .223    -4.772     .276  -.115400   .484200   .3204800   -22.500    -4.200  
+95 2 1 49749.00 I  -.115431  .000254   .486423  .000184  I  .3176520  .0000113  2.8891 0.0082  I   -23.847     .193    -4.282     .232  -.115900   .485700   .3175900   -22.700    -4.100  
+95 2 2 49750.00 I  -.115770  .000254   .487929  .000181  I  .3147682  .0000117  2.8750 0.0081  I   -23.596     .193    -4.132     .232  -.116200   .487200   .3146800   -23.200    -4.200  
+95 2 3 49751.00 I  -.115750  .000254   .489384  .000183  I  .3119068  .0000116  2.8464 0.0085  I   -23.576     .193    -4.355     .232  -.116300   .488600   .3118000   -23.400    -4.200  
+95 2 4 49752.00 I  -.115037  .000257   .490757  .000184  I  .3090844  .0000123  2.7908 0.0092  I   -23.713     .190    -4.654     .237  -.115800   .489900   .3089800   -23.800    -4.300  
+95 2 5 49753.00 I  -.113739  .000256   .492107  .000188  I  .3063359  .0000144  2.7030 0.0088  I   -23.852     .186    -4.843     .246  -.114600   .491300   .3062500   -24.100    -4.300  
+95 2 6 49754.00 I  -.111844  .000240   .493562  .000164  I  .3036856  .0000125  2.5936 0.0097  I   -23.933     .115    -4.939     .298  -.112700   .492800   .3036200   -24.200    -4.500  
+95 2 7 49755.00 I  -.109299  .000204   .495255  .000188  I  .3011561  .0000131  2.4622 0.0091  I   -24.006     .132    -5.004     .298  -.110100   .494600   .3011100   -24.300    -4.700  
+95 2 8 49756.00 I  -.106276  .000199   .497280  .000189  I  .2987650  .0000133  2.3196 0.0093  I   -24.099     .132    -5.090     .298  -.107000   .496600   .2987300   -24.200    -5.000  
+95 2 9 49757.00 I  -.103092  .000192   .499653  .000191  I  .2965034  .0000133  2.2176 0.0094  I   -24.164     .132    -5.204     .298  -.103800   .498900   .2964500   -24.100    -5.200  
+95 210 49758.00 I  -.100159  .000195   .502148  .000184  I  .2943105  .0000133  2.1735 0.0092  I   -24.165     .132    -5.293     .298  -.100900   .501300   .2942500   -23.900    -5.500  
+95 211 49759.00 I  -.097808  .000179   .504465  .000170  I  .2921455  .0000127  2.1621 0.0104  I   -24.181     .132    -5.306     .298  -.098400   .503500   .2920700   -23.600    -5.600  
+95 212 49760.00 I  -.096094  .000176   .506447  .000116  I  .2899714  .0000160  2.1955 0.0081  I   -24.282     .370    -5.286     .298  -.096600   .505500   .2899000   -23.400    -5.800  
+95 213 49761.00 I  -.094893  .000205   .508087  .000126  I  .2877376  .0000100  2.2797 0.0095  I   -24.354     .264    -5.329     .130  -.095200   .507300   .2876600   -23.200    -5.800  
+95 214 49762.00 I  -.093920  .000195   .509472  .000118  I  .2853989  .0000102  2.4033 0.0071  I   -24.172     .262    -5.453     .126  -.094100   .508700   .2853100   -23.200    -5.700  
+95 215 49763.00 I  -.092755  .000186   .510757  .000109  I  .2829181  .0000102  2.5657 0.0070  I   -23.653     .262    -5.564     .126  -.092800   .510100   .2828300   -23.200    -5.700  
+95 216 49764.00 I  -.091000  .000187   .512165  .000108  I  .2802679  .0000095  2.7271 0.0066  I   -23.077     .262    -5.637     .126  -.091300   .511400   .2801800   -23.300    -5.600  
+95 217 49765.00 I  -.088903  .000188   .513700  .000117  I  .2774850  .0000085  2.8252 0.0071  I   -22.779     .262    -5.567     .126  -.089500   .512800   .2774100   -23.500    -5.400  
+95 218 49766.00 I  -.086820  .000187   .515241  .000112  I  .2746413  .0000105  2.8517 0.0077  I   -22.832     .187    -5.402     .146  -.087700   .514200   .2745700   -23.700    -5.400  
+95 219 49767.00 I  -.084959  .000152   .516735  .000116  I  .2718026  .0000128  2.8151 0.0059  I   -23.087     .259    -5.282     .117  -.085900   .515600   .2717300   -23.900    -5.300  
+95 220 49768.00 I  -.083343  .000119   .518078  .000151  I  .2690284  .0000055  2.7265 0.0072  I   -23.374     .791    -5.248     .298  -.084200   .517000   .2689500   -23.900    -5.300  
+95 221 49769.00 I  -.081869  .000138   .519239  .000157  I  .2663575  .0000066  2.6142 0.0043  I   -23.630     .791    -5.279     .298  -.082600   .518400   .2662800   -23.800    -5.400  
+95 222 49770.00 I  -.080396  .000138   .520331  .000168  I  .2637974  .0000066  2.5099 0.0048  I   -23.905     .137    -5.384     .298  -.081000   .519800   .2637300   -23.500    -5.400  
+95 223 49771.00 I  -.078734  .000126   .521570  .000165  I  .2613248  .0000071  2.4445 0.0045  I   -24.254     .137    -5.613     .298  -.079200   .521300   .2612700   -23.200    -5.500  
+95 224 49772.00 I  -.076638  .000133   .523062  .000185  I  .2588847  .0000062  2.4502 0.0051  I   -24.606     .137    -5.941     .298  -.077000   .522800   .2588400   -22.800    -5.600  
+95 225 49773.00 I  -.073891  .000140   .524836  .000192  I  .2564009  .0000074  2.5262 0.0079  I   -24.792     .137    -6.236     .298  -.074300   .524500   .2563800   -22.400    -5.600  
+95 226 49774.00 I  -.070608  .000164   .526809  .000182  I  .2538179  .0000145  2.6453 0.0072  I   -24.734     .170    -6.357     .298  -.071300   .526200   .2538100   -22.100    -5.600  
+95 227 49775.00 I  -.067041  .000180   .528787  .000183  I  .2511060  .0000123  2.7774 0.0127  I   -24.473     .124    -6.212     .298  -.067900   .528000   .2511100   -21.900    -5.600  
+95 228 49776.00 I  -.063404  .000248   .530614  .000173  I  .2482696  .0000208  2.8902 0.0119  I   -24.144     .791    -5.883     .298  -.064300   .529700   .2482600   -21.800    -5.500  
+95 3 1 49777.00 I  -.059834  .000244   .532244  .000179  I  .2453351  .0000204  2.9747 0.0138  I   -23.881     .791    -5.624     .298  -.060400   .531300   .2452600   -23.600    -5.400  
+95 3 2 49778.00 I  -.056421  .000241   .533667  .000166  I  .2423301  .0000182  3.0295 0.0134  I   -23.719     .791    -5.663     .298  -.057000   .532700   .2422100   -23.700    -5.400  
+95 3 3 49779.00 I  -.053150  .000235   .534943  .000164  I  .2392855  .0000173  3.0562 0.0099  I   -23.603     .791    -5.974     .298  -.053700   .534200   .2391700   -24.000    -5.500  
+95 3 4 49780.00 I  -.049859  .000199   .536159  .000119  I  .2362316  .0000078  3.0412 0.0093  I   -23.497     .791    -6.334     .298  -.050300   .535400   .2361300   -24.100    -5.600  
+95 3 5 49781.00 I  -.046533  .000180   .537369  .000118  I  .2332219  .0000070  2.9698 0.0050  I   -23.450     .791    -6.566     .298  -.047000   .536600   .2331600   -24.300    -5.800  
+95 3 6 49782.00 I  -.043210  .000146   .538620  .000118  I  .2303048  .0000063  2.8598 0.0041  I   -23.513     .791    -6.647     .298  -.043600   .537800   .2302700   -24.300    -6.100  
+95 3 7 49783.00 I  -.039960  .000117   .539942  .000115  I  .2275100  .0000044  2.7265 0.0041  I   -23.639     .101    -6.679     .298  -.040400   .539000   .2274800   -24.100    -6.300  
+95 3 8 49784.00 I  -.036857  .000115   .541301  .000111  I  .2248388  .0000051  2.6323 0.0036  I   -23.701     .101    -6.770     .298  -.037300   .540300   .2247700   -23.700    -6.600  
+95 3 9 49785.00 I  -.034054  .000114   .542584  .000113  I  .2222167  .0000058  2.6244 0.0038  I   -23.581     .101    -6.931     .298  -.034500   .541600   .2221100   -23.300    -6.900  
+95 310 49786.00 I  -.031586  .000115   .543697  .000122  I  .2195729  .0000057  2.6680 0.0053  I   -23.314     .101    -7.060     .298  -.032000   .542800   .2194600   -23.000    -7.000  
+95 311 49787.00 I  -.029449  .000176   .544584  .000129  I  .2168735  .0000089  2.7332 0.0071  I   -23.030     .791    -7.060     .298  -.029900   .543800   .2167900   -22.600    -7.200  
+95 312 49788.00 I  -.027596  .000253   .545229  .000117  I  .2141008  .0000131  2.8155 0.0071  I   -22.835     .268    -6.971     .149  -.028000   .544400   .2140400   -22.300    -7.200  
+95 313 49789.00 I  -.025967  .000243   .545574  .000124  I  .2112397  .0000110  2.9063 0.0085  I   -22.769     .247    -6.939     .135  -.026300   .544800   .2112100   -22.100    -7.300  
+95 314 49790.00 I  -.024318  .000251   .545700  .000124  I  .2082900  .0000107  2.9916 0.0074  I   -22.794     .247    -7.025     .135  -.024500   .545000   .2082700   -22.100    -7.200  
+95 315 49791.00 I  -.022230  .000250   .545858  .000126  I  .2052493  .0000099  3.0986 0.0086  I   -22.814     .247    -7.093     .135  -.022400   .545200   .2052000   -22.200    -7.200  
+95 316 49792.00 I  -.019570  .000241   .546291  .000101  I  .2020894  .0000134  3.2157 0.0083  I   -22.722     .247    -7.002     .135  -.019900   .545500   .2020200   -22.300    -7.100  
+95 317 49793.00 I  -.016638  .000245   .547022  .000103  I  .1988327  .0000133  3.2882 0.0098  I   -22.567     .247    -6.745     .135  -.017100   .546100   .1987600   -22.500    -7.100  
+95 318 49794.00 I  -.013712  .000197   .547927  .000102  I  .1955371  .0000144  3.2882 0.0112  I   -22.488     .134    -6.507     .298  -.014100   .547000   .1954600   -22.700    -7.000  
+95 319 49795.00 I  -.010970  .000160   .548911  .000093  I  .1922824  .0000181  3.2097 0.0097  I   -22.534     .791    -6.498     .298  -.011300   .548000   .1922100   -22.800    -7.100  
+95 320 49796.00 I  -.008609  .000144   .549912  .000087  I  .1891428  .0000129  3.0559 0.0111  I   -22.617     .166    -6.743     .298  -.009000   .549000   .1890800   -22.800    -7.100  
+95 321 49797.00 I  -.006664  .000206   .550852  .000085  I  .1861914  .0000129  2.8397 0.0080  I   -22.639     .166    -7.087     .298  -.007200   .550000   .1861400   -22.700    -7.300  
+95 322 49798.00 I  -.004915  .000209   .551625  .000086  I  .1834651  .0000095  2.6183 0.0080  I   -22.633     .175    -7.372     .298  -.005500   .550700   .1834100   -22.300    -7.300  
+95 323 49799.00 I  -.003080  .000214   .552167  .000111  I  .1809253  .0000093  2.4855 0.0066  I   -22.722     .175    -7.560     .298  -.003700   .551200   .1808400   -22.100    -7.400  
+95 324 49800.00 I  -.000718  .000208   .552558  .000117  I  .1784517  .0000093  2.4799 0.0060  I   -22.899     .175    -7.700     .298  -.001100   .551600   .1783400   -21.800    -7.400  
+95 325 49801.00 I   .002665  .000211   .552945  .000137  I  .1759392  .0000077  2.5532 0.0065  I   -23.001     .175    -7.829     .298   .002200   .552000   .1758500   -21.700    -7.500  
+95 326 49802.00 I   .007068  .000233   .553526  .000191  I  .1733344  .0000092  2.6591 0.0051  I   -22.894     .160    -7.922     .298   .006500   .552600   .1732600   -21.600    -7.400  
+95 327 49803.00 I   .012125  .000209   .554424  .000185  I  .1706200  .0000066  2.7678 0.0051  I   -22.605     .144    -7.910     .298   .011300   .553600   .1705600   -21.600    -7.300  
+95 328 49804.00 I   .017209  .000170   .555609  .000213  I  .1678072  .0000045  2.8512 0.0040  I   -22.317     .118    -7.772     .298   .016300   .554800   .1677500   -21.800    -7.300  
+95 329 49805.00 I   .021783  .000146   .556881  .000202  I  .1649300  .0000045  2.8974 0.0035  I   -22.216     .118    -7.598     .298   .021000   .556000   .1648600   -22.100    -7.300  
+95 330 49806.00 I   .025737  .000154   .557853  .000196  I  .1620269  .0000053  2.9002 0.0034  I   -22.259     .118    -7.539     .298   .025100   .557000   .1619500   -22.500    -7.300  
+95 331 49807.00 I   .029145  .000154   .558411  .000200  I  .1591455  .0000051  2.8554 0.0036  I   -22.270     .118    -7.660     .298   .028700   .557600   .1590500   -22.700    -7.400  
+95 4 1 49808.00 I   .032223  .000131   .558606  .000178  I  .1563266  .0000050  2.7793 0.0064  I   -22.159     .104    -7.887     .298   .031800   .557800   .1562300   -23.000    -7.500  
+95 4 2 49809.00 I   .035253  .000123   .558563  .000124  I  .1535919  .0000118  2.6884 0.0074  I   -22.027     .791    -8.095     .298   .034800   .557700   .1535000   -23.000    -7.700  
+95 4 3 49810.00 I   .038395  .000124   .558415  .000121  I  .1509506  .0000139  2.5952 0.0092  I   -22.004     .791    -8.223     .298   .037700   .557500   .1508600   -22.900    -8.000  
+95 4 4 49811.00 I   .041610  .000121   .558191  .000127  I  .1484005  .0000140  2.5050 0.0100  I   -22.061     .791    -8.307     .298   .041000   .557300   .1483300   -22.600    -8.200  
+95 4 5 49812.00 I   .044799  .000114   .557877  .000129  I  .1459346  .0000144  2.4328 0.0104  I   -22.084     .791    -8.415     .298   .044300   .557000   .1458700   -22.200    -8.400  
+95 4 6 49813.00 I   .048055  .000105   .557657  .000118  I  .1435147  .0000153  2.4210 0.0106  I   -22.077     .791    -8.566     .298   .047800   .556900   .1434500   -21.800    -8.600  
+95 4 7 49814.00 I   .051330  .000106   .557646  .000117  I  .1410720  .0000155  2.4708 0.0103  I   -22.107     .791    -8.676     .298   .051100   .556800   .1410100   -21.400    -8.700  
+95 4 8 49815.00 I   .054471  .000086   .557796  .000160  I  .1385650  .0000137  2.5448 0.0119  I   -22.142     .791    -8.634     .298   .054200   .557000   .1385200   -21.000    -8.700  
+95 4 9 49816.00 I   .057417  .000111   .557972  .000177  I  .1359808  .0000180  2.6234 0.0110  I   -22.082     .225    -8.449     .298   .057100   .557200   .1359400   -20.800    -8.600  
+95 410 49817.00 I   .060287  .000181   .558056  .000180  I  .1333095  .0000173  2.7281 0.0121  I   -21.956     .318    -8.302     .298   .059800   .557300   .1332500   -20.600    -8.600  
+95 411 49818.00 I   .063186  .000199   .557998  .000181  I  .1305124  .0000162  2.8696 0.0114  I   -21.911     .489    -8.361     .298   .062500   .557300   .1304400   -20.700    -8.500  
+95 412 49819.00 I   .066106  .000203   .557795  .000180  I  .1275648  .0000150  3.0278 0.0112  I   -21.966     .505    -8.550     .298   .065300   .557100   .1274900   -21.000    -8.400  
+95 413 49820.00 I   .069162  .000206   .557477  .000186  I  .1244732  .0000155  3.1369 0.0108  I   -21.985     .505    -8.591     .298   .068300   .556600   .1244100   -21.400    -8.400  
+95 414 49821.00 I   .072319  .000220   .557059  .000188  I  .1213199  .0000156  3.1592 0.0109  I   -21.738     .505    -8.385     .298   .071600   .556200   .1212700   -21.700    -8.400  
+95 415 49822.00 I   .075646  .000222   .556623  .000130  I  .1181739  .0000152  3.1240 0.0108  I   -21.434     .568    -8.108     .298   .075100   .555700   .1181200   -22.100    -8.400  
+95 416 49823.00 I   .079115  .000187   .556274  .000143  I  .1150863  .0000150  3.0455 0.0085  I   -21.370     .639    -8.040     .298   .078700   .555400   .1150300   -22.400    -8.500  
+95 417 49824.00 I   .082588  .000187   .556036  .000088  I  .1120940  .0000074  2.9337 0.0082  I   -21.526     .404    -8.275     .298   .082200   .555100   .1120400   -22.400    -8.500  
+95 418 49825.00 I   .085904  .000165   .555871  .000118  I  .1092209  .0000067  2.8158 0.0048  I   -21.732     .262    -8.624     .298   .085600   .555000   .1091800   -22.400    -8.700  
+95 419 49826.00 I   .088995  .000164   .555759  .000123  I  .1064576  .0000061  2.7122 0.0045  I   -21.871     .428    -8.839     .298   .088700   .555000   .1064300   -22.100    -8.800  
+95 420 49827.00 I   .091859  .000167   .555687  .000126  I  .1037831  .0000061  2.6488 0.0041  I   -21.966     .428    -8.843     .298   .091600   .554900   .1037200   -21.800    -8.800  
+95 421 49828.00 I   .094840  .000154   .555488  .000128  I  .1011338  .0000055  2.6640 0.0041  I   -22.131     .428    -8.791     .298   .094700   .554700   .1010300   -21.400    -8.800  
+95 422 49829.00 I   .098282  .000142   .555027  .000123  I  .0984390  .0000055  2.7276 0.0039  I   -22.304     .391    -8.765     .298   .097900   .554300   .0983000   -21.100    -8.800  
+95 423 49830.00 I   .101923  .000120   .554313  .000155  I  .0956750  .0000056  2.8020 0.0040  I   -22.350     .423    -8.753     .298   .101300   .553600   .0955200   -20.900    -8.700  
+95 424 49831.00 I   .105677  .000118   .553421  .000134  I  .0928361  .0000059  2.8729 0.0043  I   -22.220     .400    -8.741     .298   .105100   .552800   .0926800   -20.900    -8.600  
+95 425 49832.00 I   .109648  .000110   .552409  .000117  I  .0899362  .0000065  2.9226 0.0044  I   -21.969     .103    -8.709     .298   .109200   .551800   .0897900   -21.100    -8.600  
+95 426 49833.00 I   .113828  .000093   .551295  .000118  I  .0870060  .0000066  2.9271 0.0059  I   -21.778     .103    -8.637     .298   .113400   .550600   .0869000   -21.300    -8.500  
+95 427 49834.00 I   .118052  .000094   .550083  .000113  I  .0841042  .0000098  2.8651 0.0058  I   -21.811     .103    -8.532     .298   .117600   .549400   .0840200   -21.700    -8.600  
+95 428 49835.00 I   .122201  .000095   .548781  .000115  I  .0812932  .0000096  2.7508 0.0070  I   -22.006     .128    -8.444     .298   .121800   .548000   .0812200   -22.100    -8.600  
+95 429 49836.00 I   .126200  .000085   .547400  .000115  I  .0786103  .0000100  2.6133 0.0070  I   -22.183     .128    -8.443     .298   .125900   .546600   .0785400   -22.300    -8.700  
+95 430 49837.00 I   .130004  .000104   .545963  .000085  I  .0760682  .0000102  2.4709 0.0063  I   -22.260     .791    -8.560     .298   .129800   .545100   .0759800   -22.500    -8.900  
+95 5 1 49838.00 I   .133625  .000099   .544472  .000076  I  .0736575  .0000077  2.3614 0.0064  I   -22.260     .791    -8.763     .298   .133600   .543700   .0735500   -22.500    -9.100  
+95 5 2 49839.00 I   .137151  .000102   .542978  .000085  I  .0713226  .0000078  2.3203 0.0044  I   -22.173     .791    -8.993     .298   .137100   .542200   .0712000   -22.300    -9.200  
+95 5 3 49840.00 I   .140652  .000105   .541540  .000084  I  .0689971  .0000041  2.3387 0.0067  I   -21.978     .791    -9.223     .298   .140500   .540700   .0688500   -21.800    -9.200  
+95 5 4 49841.00 I   .144150  .000115   .540101  .000081  I  .0666340  .0000108  2.3906 0.0064  I   -21.787     .791    -9.398     .298   .144000   .539100   .0664900   -21.400    -9.300  
+95 5 5 49842.00 I   .147689  .000127   .538598  .000080  I  .0642119  .0000122  2.4545 0.0086  I   -21.736     .791    -9.496     .298   .147600   .537600   .0640600   -21.000    -9.300  
+95 5 6 49843.00 I   .151386  .000099   .537040  .000079  I  .0617241  .0000135  2.5210 0.0174  I   -21.732     .791    -9.460     .298   .151400   .536000   .0615800   -20.600    -9.200  
+95 5 7 49844.00 I   .155353  .000183   .535497  .000096  I  .0591702  .0000325  2.5865 0.0125  I   -21.524     .791    -9.247     .298   .155400   .534400   .0590300   -20.500    -9.100  
+95 5 8 49845.00 I   .159560  .000268   .533999  .000154  I  .0565425  .0000211  2.6779 0.0194  I   -21.105     .160    -8.972     .298   .159500   .533000   .0564200   -20.400    -9.000  
+95 5 9 49846.00 I   .163824  .000268   .532527  .000154  I  .0538021  .0000213  2.8062 0.0135  I   -20.845     .149    -8.852     .298   .163600   .531600   .0536900   -20.600    -8.900  
+95 510 49847.00 I   .167886  .000258   .531033  .000152  I  .0509297  .0000169  2.9355 0.0136  I   -21.061     .149    -8.949     .298   .167600   .530200   .0508200   -21.000    -8.900  
+95 511 49848.00 I   .171598  .000255   .529473  .000154  I  .0479442  .0000168  3.0254 0.0118  I   -21.632     .149    -9.068     .298   .171400   .528700   .0478400   -21.400    -8.800  
+95 512 49849.00 I   .174931  .000252   .527820  .000159  I  .0449067  .0000164  3.0320 0.0117  I   -22.134     .149    -8.967     .298   .175000   .527100   .0448200   -22.000    -8.700  
+95 513 49850.00 I   .178042  .000252   .526120  .000170  I  .0419048  .0000164  2.9650 0.0105  I   -22.377     .149    -8.702     .298   .178400   .525500   .0418100   -22.300    -8.700  
+95 514 49851.00 I   .181104  .000127   .524458  .000133  I  .0389846  .0000132  2.8743 0.0091  I   -22.490     .138    -8.566     .298   .181500   .523800   .0388900   -22.600    -8.900  
+95 515 49852.00 I   .184123  .000119   .522872  .000105  I  .0361612  .0000079  2.7684 0.0077  I   -22.604     .791    -8.710     .298   .184300   .522100   .0360800   -22.700    -8.900  
+95 516 49853.00 I   .187027  .000113   .521341  .000116  I  .0334480  .0000080  2.6617 0.0047  I   -22.693     .791    -8.980     .298   .186900   .520400   .0333900   -22.700    -8.900  
+95 517 49854.00 I   .189688  .000112   .519782  .000143  I  .0308279  .0000050  2.5846 0.0044  I   -22.662     .791    -9.132     .298   .189300   .518700   .0307800   -22.500    -8.900  
+95 518 49855.00 I   .191958  .000104   .518055  .000144  I  .0282646  .0000035  2.5502 0.0036  I   -22.480     .791    -9.105     .298   .191600   .516900   .0282100   -22.100    -8.900  
+95 519 49856.00 I   .193890  .000110   .516107  .000149  I  .0257150  .0000051  2.5534 0.0030  I   -22.234     .791    -9.000     .298   .193700   .514900   .0256500   -21.700    -8.800  
+95 520 49857.00 I   .195623  .000096   .513903  .000139  I  .0231537  .0000049  2.5689 0.0065  I   -22.089     .791    -8.885     .298   .195700   .512800   .0230700   -21.500    -8.800  
+95 521 49858.00 I   .197336  .000114   .511469  .000163  I  .0205831  .0000119  2.5666 0.0057  I   -22.162     .791    -8.757     .298   .197600   .510400   .0204900   -21.300    -8.700  
+95 522 49859.00 I   .199225  .000111   .508960  .000140  I  .0180327  .0000104  2.5277 0.0095  I   -22.379     .261    -8.644     .298   .199500   .508100   .0179500   -21.300    -8.600  
+95 523 49860.00 I   .201339  .000112   .506500  .000116  I  .0155409  .0000147  2.4494 0.0094  I   -22.542     .257    -8.621     .298   .201300   .505700   .0154600   -21.500    -8.500  
+95 524 49861.00 I   .203530  .000114   .504116  .000113  I  .0131463  .0000156  2.3341 0.0103  I   -22.610     .257    -8.696     .298   .203100   .503400   .0130500   -21.800    -8.600  
+95 525 49862.00 I   .205615  .000105   .501788  .000100  I  .0108704  .0000145  2.2256 0.0113  I   -22.787     .257    -8.781     .298   .205000   .501000   .0107500   -22.300    -8.600  
+95 526 49863.00 I   .207613  .000104   .499451  .000097  I  .0086859  .0000164  2.1446 0.0109  I   -23.171     .257    -8.783     .298   .207000   .498600   .0085600   -22.700    -8.700  
+95 527 49864.00 I   .209581  .000104   .497026  .000089  I  .0065837  .0000164  2.0562 0.0109  I   -23.641     .257    -8.767     .298   .209000   .496100   .0064700   -23.100    -8.700  
+95 528 49865.00 I   .211530  .000060   .494489  .000106  I  .0045724  .0000143  1.9711 0.0095  I   -23.974     .252    -8.865     .298   .211100   .493600   .0044800   -23.300    -8.800  
+95 529 49866.00 I   .213501  .000074   .491824  .000139  I  .0026326  .0000096  1.9128 0.0085  I   -24.035     .791    -9.068     .298   .213200   .491000   .0025600   -23.400    -9.000  
+95 530 49867.00 I   .215531  .000072   .489023  .000150  I  .0007373  .0000092  1.8831 0.0070  I   -23.855     .791    -9.227     .298   .215300   .488400   .0006700   -23.300    -9.100  
+95 531 49868.00 I   .217624  .000069   .486128  .000154  I -.0011437  .0000102  1.8837 0.0071  I   -23.581     .791    -9.231     .298   .217400   .485500  -.0012200   -23.100    -9.100  
+95 6 1 49869.00 I   .219839  .000068   .483227  .000154  I -.0030435  .0000107  1.9245 0.0074  I   -23.435     .791    -9.142     .298   .219700   .482600  -.0031400   -22.800    -9.100  
+95 6 2 49870.00 I   .222301  .000067   .480281  .000151  I -.0050071  .0000107  2.0086 0.0076  I   -23.587     .791    -9.132     .298   .222200   .479500  -.0051200   -22.600    -9.100  
+95 6 3 49871.00 I   .225108  .000070   .477193  .000153  I -.0070698  .0000108  2.1199 0.0093  I   -23.919     .791    -9.219     .298   .224900   .476300  -.0071900   -22.400    -9.100  
+95 6 4 49872.00 I   .228205  .000095   .473977  .000167  I -.0092459  .0000153  2.2283 0.0082  I   -24.056     .791    -9.259     .298   .227900   .473100  -.0093500   -22.400    -8.900  
+95 6 5 49873.00 I   .231450  .000116   .470731  .000189  I -.0115205  .0000124  2.3191 0.0097  I   -23.793     .147    -9.158     .298   .231000   .469800  -.0116100   -22.700    -8.800  
+95 6 6 49874.00 I   .234633  .000122   .467602  .000186  I -.0138775  .0000118  2.3900 0.0080  I   -23.391     .147    -8.974     .298   .234200   .466700  -.0139500   -22.900    -8.800  
+95 6 7 49875.00 I   .237641  .000132   .464714  .000187  I -.0162951  .0000101  2.4446 0.0080  I   -23.280     .142    -8.779     .298   .237400   .463800  -.0163700   -23.400    -8.800  
+95 6 8 49876.00 I   .240594  .000133   .462046  .000191  I -.0187550  .0000109  2.4642 0.0074  I   -23.560     .142    -8.498     .298   .240300   .461000  -.0188200   -23.900    -8.700  
+95 6 9 49877.00 I   .243439  .000131   .459261  .000186  I -.0212012  .0000107  2.4171 0.0074  I   -23.983     .142    -8.092     .298   .243100   .458200  -.0212500   -24.300    -8.700  
+95 610 49878.00 I   .246051  .000125   .456323  .000186  I -.0235719  .0000099  2.3183 0.0082  I   -24.310     .142    -7.727     .298   .245600   .455300  -.0236100   -24.700    -8.700  
+95 611 49879.00 I   .248386  .000079   .453343  .000162  I -.0258309  .0000123  2.1989 0.0084  I   -24.504     .136    -7.645     .298   .247900   .452300  -.0258700   -24.900    -8.800  
+95 612 49880.00 I   .250452  .000088   .450340  .000155  I -.0279733  .0000136  2.0905 0.0089  I   -24.670     .285    -7.906     .298   .250100   .449300  -.0280200   -24.900    -8.800  
+95 613 49881.00 I   .252350  .000068   .447248  .000142  I -.0300289  .0000130  2.0333 0.0092  I   -24.913     .427    -8.312     .298   .252100   .446300  -.0300900   -24.900    -8.800  
+95 614 49882.00 I   .254267  .000068   .444027  .000135  I -.0320660  .0000125  2.0546 0.0095  I   -25.237     .427    -8.609     .298   .254200   .443200  -.0321300   -24.700    -8.700  
+95 615 49883.00 I   .256310  .000064   .440739  .000132  I -.0341466  .0000138  2.1014 0.0093  I   -25.532     .427    -8.757     .298   .256200   .440000  -.0342100   -24.500    -8.600  
+95 616 49884.00 I   .258509  .000068   .437481  .000131  I -.0362715  .0000139  2.1562 0.0098  I   -25.586     .427    -8.817     .298   .258400   .436800  -.0363500   -24.300    -8.500  
+95 617 49885.00 I   .260839  .000064   .434277  .000136  I -.0384633  .0000139  2.2237 0.0137  I   -25.507     .386    -8.823     .298   .260600   .433600  -.0385600   -24.300    -8.300  
+95 618 49886.00 I   .263215  .000076   .431106  .000130  I -.0407064  .0000235  2.2537 0.0137  I   -25.630     .389    -8.728     .298   .262900   .430300  -.0408200   -24.300    -8.200  
+95 619 49887.00 I   .265545  .000112   .427896  .000148  I -.0429534  .0000237  2.2319 0.0159  I   -26.013     .324    -8.539     .298   .265100   .427000  -.0430700   -24.600    -8.100  
+95 620 49888.00 I   .267697  .000117   .424553  .000151  I -.0451547  .0000214  2.1635 0.0151  I   -26.320     .324    -8.406     .298   .267300   .423600  -.0452600   -25.100    -8.000  
+95 621 49889.00 I   .269577  .000126   .421018  .000161  I -.0472665  .0000186  2.0535 0.0155  I   -26.224     .324    -8.444     .298   .269200   .420100  -.0473600   -25.500    -8.000  
+95 622 49890.00 I   .271154  .000126   .417398  .000173  I -.0492487  .0000225  1.9044 0.0151  I   -25.768     .324    -8.550     .298   .270800   .416500  -.0493200   -26.100    -8.000  
+95 623 49891.00 I   .272392  .000107   .413796  .000169  I -.0510626  .0000238  1.7170 0.0162  I   -25.413     .359    -8.583     .298   .272100   .412900  -.0511200   -26.600    -8.200  
+95 624 49892.00 I   .273290  .000101   .410267  .000169  I -.0526763  .0000232  1.5102 0.0142  I   -25.425     .359    -8.560     .298   .273000   .409400  -.0527200   -26.900    -8.300  
+95 625 49893.00 I   .273966  .000136   .406811  .000169  I -.0540931  .0000154  1.3337 0.0133  I   -25.639    1.012    -8.617     .298   .273700   .405800  -.0541400   -27.100    -8.400  
+95 626 49894.00 I   .274637  .000145   .403337  .000153  I -.0553614  .0000129  1.2104 0.0099  I   -25.850     .866    -8.795     .404   .274400   .402300  -.0554100   -27.200    -8.500  
+95 627 49895.00 I   .275453  .000145   .399721  .000150  I -.0565304  .0000126  1.1366 0.0085  I   -26.137     .893    -8.961     .319   .275100   .398700  -.0565800   -27.100    -8.600  
+95 628 49896.00 I   .276446  .000144   .395963  .000144  I -.0576556  .0000111  1.1259 0.0087  I   -26.700     .893    -8.958     .319   .276100   .395100  -.0577100   -26.900    -8.600  
+95 629 49897.00 I   .277574  .000151   .392210  .000148  I -.0588041  .0000121  1.1811 0.0082  I   -27.309     .893    -8.713     .319   .277300   .391400  -.0588700   -26.700    -8.400  
+95 630 49898.00 I   .278839  .000162   .388463  .000144  I -.0600344  .0000121  1.2863 0.0085  I   -27.865     .893    -8.474     .319   .278600   .387600  -.0601100   -26.500    -8.300  
+95 7 1 49899.00 I   .280135  .000175   .384623  .000138  I -.0613867  .0000118  1.4216 0.0106  I   -28.378     .861    -8.417     .354   .279900   .383700  -.0614700   -26.400    -8.200  
+95 7 2 49900.00 I   .281307  .000150   .380660  .000089  I -.0628822  .0000174  1.5707 0.0123  I   -28.702     .932    -8.450     .298   .281100   .379700  -.0629700   -26.400    -8.000  
+95 7 3 49901.00 I   .282279  .000132   .376569  .000109  I -.0645201  .0000215  1.6960 0.0134  I   -28.656     .791    -8.429     .298   .282100   .375600  -.0646000   -26.600    -7.900  
+95 7 4 49902.00 I   .283155  .000160   .372366  .000099  I -.0662537  .0000205  1.7600 0.0130  I   -28.335     .288    -8.308     .298   .283000   .371400  -.0663200   -27.000    -7.900  
+95 7 5 49903.00 I   .284080  .000157   .368160  .000105  I -.0680185  .0000146  1.7593 0.0126  I   -28.129     .288    -8.148     .298   .283900   .367200  -.0680800   -27.500    -7.900  
+95 7 6 49904.00 I   .284998  .000146   .364071  .000101  I -.0697585  .0000148  1.7171 0.0117  I   -28.393     .288    -8.005     .298   .284700   .363000  -.0698300   -27.900    -8.000  
+95 7 7 49905.00 I   .285752  .000113   .360096  .000104  I -.0714445  .0000182  1.6502 0.0113  I   -29.156     .288    -7.910     .298   .285500   .358900  -.0715200   -28.500    -8.000  
+95 7 8 49906.00 I   .286264  .000126   .356144  .000107  I -.0730519  .0000172  1.5624 0.0128  I   -30.083     .288    -7.923     .298   .286100   .354900  -.0731300   -28.900    -8.100  
+95 7 9 49907.00 I   .286592  .000155   .352185  .000101  I -.0745701  .0000179  1.4770 0.0111  I   -30.805     .580    -8.127     .298   .286500   .351000  -.0746500   -29.300    -8.300  
+95 710 49908.00 I   .286847  .000152   .348271  .000101  I -.0760160  .0000140  1.4218 0.0117  I   -31.152     .672    -8.474     .147   .286800   .347200  -.0760900   -29.500    -8.400  
+95 711 49909.00 I   .287167  .000150   .344456  .000090  I -.0774314  .0000150  1.4198 0.0101  I   -31.126     .549    -8.724     .134   .287100   .343500  -.0774900   -29.600    -8.400  
+95 712 49910.00 I   .287522  .000146   .340770  .000095  I -.0788750  .0000147  1.4759 0.0104  I   -30.798     .549    -8.676     .134   .287200   .339900  -.0789200   -29.800    -8.400  
+95 713 49911.00 I   .287691  .000147   .337184  .000124  I -.0803920  .0000144  1.5585 0.0103  I   -30.419     .549    -8.516     .134   .287400   .336400  -.0804300   -29.700    -8.400  
+95 714 49912.00 I   .287724  .000131   .333635  .000125  I -.0819965  .0000143  1.6546 0.0091  I   -30.024     .549    -8.405     .134   .287400   .332800  -.0820500   -29.500    -8.300  
+95 715 49913.00 I   .287795  .000125   .330040  .000134  I -.0836972  .0000110  1.7387 0.0103  I   -29.694     .325    -8.404     .124   .287500   .329200  -.0837700   -29.500    -8.200  
+95 716 49914.00 I   .287949  .000102   .326344  .000170  I -.0854542  .0000149  1.7638 0.0079  I   -29.729     .791    -8.440     .298   .287600   .325500  -.0855200   -29.700    -8.200  
+95 717 49915.00 I   .288082  .000135   .322556  .000174  I -.0872007  .0000114  1.7167 0.0097  I   -30.260     .791    -8.406     .298   .287700   .321700  -.0872600   -30.000    -8.200  
+95 718 49916.00 I   .288062  .000140   .318743  .000174  I -.0888665  .0000124  1.6065 0.0080  I   -30.944     .791    -8.365     .298   .287800   .317800  -.0889200   -30.300    -8.300  
+95 719 49917.00 I   .287868  .000139   .314950  .000156  I -.0904009  .0000113  1.4580 0.0084  I   -31.292     .791    -8.442     .298   .287700   .313900  -.0904600   -30.700    -8.400  
+95 720 49918.00 I   .287689  .000148   .311145  .000156  I -.0917787  .0000114  1.2981 0.0075  I   -31.247     .791    -8.575     .298   .287600   .309900  -.0918600   -31.400    -8.500  
+95 721 49919.00 I   .287565  .000154   .307292  .000155  I -.0929977  .0000099  1.1401 0.0068  I   -31.216     .791    -8.638     .298   .287400   .306000  -.0931000   -31.900    -8.600  
+95 722 49920.00 I   .287387  .000132   .303396  .000155  I -.0940641  .0000075  0.9976 0.0059  I   -31.487     .791    -8.598     .298   .287100   .302100  -.0941900   -32.400    -8.800  
+95 723 49921.00 I   .287031  .000127   .299471  .000155  I -.0950056  .0000065  0.8932 0.0049  I   -31.891     .123    -8.540     .298   .286700   .298300  -.0951400   -32.700    -8.900  
+95 724 49922.00 I   .286566  .000138   .295521  .000170  I -.0958652  .0000063  0.8330 0.0049  I   -32.115     .168    -8.534     .117   .286300   .294500  -.0959900   -32.800    -8.900  
+95 725 49923.00 I   .286095  .000149   .291575  .000168  I -.0966853  .0000074  0.8139 0.0049  I   -32.100     .168    -8.554     .117   .285800   .290600  -.0968000   -32.800    -8.900  
+95 726 49924.00 I   .285505  .000144   .287660  .000163  I -.0975064  .0000075  0.8349 0.0057  I   -31.971     .168    -8.512     .117   .285100   .286800  -.0975900   -32.800    -8.900  
+95 727 49925.00 I   .284645  .000141   .283792  .000157  I -.0983658  .0000088  0.8882 0.0064  I   -31.774     .168    -8.272     .117   .284300   .282900  -.0984300   -32.500    -8.700  
+95 728 49926.00 I   .283658  .000138   .280001  .000145  I -.0992918  .0000104  0.9687 0.0084  I   -31.577     .168    -7.928     .117   .283300   .279100  -.0993500   -32.200    -8.500  
+95 729 49927.00 I   .282595  .000165   .276263  .000102  I -.1003121  .0000144  1.0759 0.0135  I   -31.515     .203    -7.639     .131   .282200   .275300  -.1003800   -31.900    -8.400  
+95 730 49928.00 I   .281448  .000113   .272477  .000062  I -.1014508  .0000249  1.2049 0.0105  I   -31.664     .565    -7.469     .273   .281100   .271500  -.1015400   -31.900    -8.300  
+95 731 49929.00 I   .280368  .000091   .268586  .000071  I -.1027208  .0000154  1.3308 0.0146  I   -31.932     .552    -7.431     .266   .280100   .267700  -.1028100   -32.000    -8.200  
+95 8 1 49930.00 I   .279541  .000088   .264644  .000075  I -.1041002  .0000153  1.4200 0.0104  I   -32.183     .552    -7.568     .266   .279200   .263800  -.1041800   -32.000    -8.200  
+95 8 2 49931.00 I   .278952  .000083   .260708  .000068  I -.1055396  .0000140  1.4455 0.0100  I   -32.433     .552    -7.912     .266   .278500   .259900  -.1056100   -32.300    -8.200  
+95 8 3 49932.00 I   .278360  .000084   .256799  .000081  I -.1069717  .0000130  1.4125 0.0089  I   -32.662     .552    -8.138     .266   .277900   .255900  -.1070400   -32.700    -8.400  
+95 8 4 49933.00 I   .277631  .000069   .252861  .000085  I -.1083570  .0000109  1.3567 0.0085  I   -32.963     .552    -8.181     .266   .277200   .251900  -.1084400   -33.200    -8.500  
+95 8 5 49934.00 I   .276791  .000065   .248912  .000099  I -.1096881  .0000110  1.3099 0.0079  I   -33.362     .380    -8.205     .189   .276500   .248000  -.1097900   -33.500    -8.600  
+95 8 6 49935.00 I   .275892  .000094   .245043  .000144  I -.1109876  .0000113  1.2957 0.0074  I   -33.726     .791    -8.336     .298   .275900   .244100  -.1110900   -33.800    -8.800  
+95 8 7 49936.00 I   .274915  .000117   .241303  .000159  I -.1122929  .0000100  1.3219 0.0076  I   -33.948     .272    -8.565     .298   .274800   .240400  -.1123800   -34.000    -8.800  
+95 8 8 49937.00 I   .273771  .000126   .237673  .000152  I -.1136461  .0000101  1.3923 0.0064  I   -34.077     .316    -8.742     .298   .273500   .236700  -.1137100   -34.000    -8.800  
+95 8 9 49938.00 I   .272359  .000128   .234099  .000141  I -.1150900  .0000079  1.5002 0.0065  I   -34.252     .316    -8.709     .298   .272100   .233100  -.1151400   -34.200    -8.700  
+95 810 49939.00 I   .270663  .000124   .230520  .000137  I -.1166522  .0000082  1.6251 0.0056  I   -34.508     .316    -8.427     .298   .270600   .229600  -.1167000   -34.100    -8.600  
+95 811 49940.00 I   .269001  .000119   .226934  .000142  I -.1183333  .0000078  1.7294 0.0057  I   -34.609     .387    -8.133     .298   .269100   .226000  -.1183800   -34.000    -8.500  
+95 812 49941.00 I   .267541  .000124   .223342  .000134  I -.1200937  .0000078  1.7818 0.0065  I   -34.488     .387    -8.056     .298   .267600   .222500  -.1201600   -34.000    -8.300  
+95 813 49942.00 I   .266166  .000126   .219764  .000117  I -.1218769  .0000103  1.7740 0.0046  I   -34.401     .389    -8.171     .298   .266100   .218900  -.1219600   -34.200    -8.200  
+95 814 49943.00 I   .264644  .000100   .216284  .000150  I -.1236236  .0000048  1.7117 0.0057  I   -34.593     .233    -8.298     .298   .264400   .215300  -.1237100   -34.400    -8.200  
+95 815 49944.00 I   .262691  .000095   .212933  .000155  I -.1252897  .0000050  1.6177 0.0043  I   -34.989     .217    -8.335     .298   .262400   .211900  -.1253800   -34.700    -8.200  
+95 816 49945.00 I   .260241  .000091   .209642  .000156  I -.1268567  .0000072  1.5169 0.0045  I   -35.290     .217    -8.333     .298   .260100   .208500  -.1269500   -34.900    -8.300  
+95 817 49946.00 I   .257691  .000095   .206449  .000149  I -.1283241  .0000075  1.4178 0.0057  I   -35.361     .217    -8.370     .298   .257700   .205300  -.1284100   -35.200    -8.400  
+95 818 49947.00 I   .255336  .000102   .203412  .000147  I -.1296985  .0000088  1.3374 0.0062  I   -35.305     .217    -8.443     .298   .255300   .202300  -.1297800   -35.400    -8.500  
+95 819 49948.00 I   .253179  .000098   .200506  .000137  I -.1310131  .0000098  1.2997 0.0065  I   -35.293     .217    -8.503     .298   .253000   .199500  -.1311000   -35.500    -8.700  
+95 820 49949.00 I   .251097  .000111   .197685  .000081  I -.1323117  .0000097  1.3034 0.0062  I   -35.336     .199    -8.530     .298   .250800   .196800  -.1324000   -35.400    -8.700  
+95 821 49950.00 I   .249107  .000162   .194904  .000115  I -.1336314  .0000076  1.3416 0.0059  I   -35.346     .428    -8.527     .298   .248900   .194000  -.1337000   -35.200    -8.700  
+95 822 49951.00 I   .247201  .000178   .192091  .000122  I -.1350051  .0000067  1.4103 0.0052  I   -35.347     .535    -8.499     .298   .246900   .191200  -.1350600   -35.000    -8.700  
+95 823 49952.00 I   .245183  .000187   .189208  .000122  I -.1364567  .0000072  1.4933 0.0046  I   -35.427     .438    -8.466     .298   .244800   .188400  -.1364900   -34.900    -8.500  
+95 824 49953.00 I   .242878  .000175   .186348  .000176  I -.1379952  .0000063  1.5870 0.0046  I   -35.563     .379    -8.460     .298   .242600   .185400  -.1380200   -34.700    -8.400  
+95 825 49954.00 I   .240438  .000168   .183450  .000174  I -.1396425  .0000058  1.7160 0.0051  I   -35.521     .374    -8.475     .298   .240300   .182400  -.1396900   -34.700    -8.200  
+95 826 49955.00 I   .238156  .000165   .180477  .000169  I -.1414378  .0000079  1.8769 0.0050  I   -35.362     .356    -8.394     .298   .238000   .179500  -.1414900   -34.800    -8.100  
+95 827 49956.00 I   .236101  .000158   .177546  .000167  I -.1433880  .0000082  2.0131 0.0057  I   -35.373     .311    -8.223     .298   .235800   .176700  -.1434400   -35.100    -8.000  
+95 828 49957.00 I   .234106  .000107   .174753  .000163  I -.1454513  .0000081  2.1114 0.0059  I   -35.688     .193    -8.026     .124   .233600   .173900  -.1454900   -35.300    -8.000  
+95 829 49958.00 I   .232124  .000099   .172120  .000177  I -.1475858  .0000086  2.1347 0.0062  I   -36.091     .360    -7.956     .176   .231500   .171200  -.1476000   -35.700    -8.100  
+95 830 49959.00 I   .229971  .000107   .169548  .000176  I -.1496976  .0000094  2.0887 0.0068  I   -36.370     .417    -8.076     .175   .229300   .168500  -.1497300   -36.000    -8.200  
+95 831 49960.00 I   .227437  .000105   .166958  .000120  I -.1517621  .0000106  2.0392 0.0063  I   -36.548     .427    -8.135     .185   .227000   .165700  -.1518200   -36.200    -8.400  
+95 9 1 49961.00 I   .224672  .000120   .164364  .000112  I -.1537776  .0000085  1.9944 0.0082  I   -36.726     .454    -8.080     .201   .224600   .163100  -.1538500   -36.500    -8.600  
+95 9 2 49962.00 I   .221943  .000131   .161813  .000119  I -.1557561  .0000125  1.9654 0.0105  I   -36.847     .507    -8.078     .210   .222000   .160600  -.1558300   -36.600    -8.800  
+95 9 3 49963.00 I   .219408  .000149   .159389  .000131  I -.1577167  .0000193  1.9615 0.0087  I   -36.861     .576    -8.229     .216   .219600   .158400  -.1577800   -36.500    -9.000  
+95 9 4 49964.00 I   .217128  .000142   .157140  .000126  I -.1596912  .0000121  1.9941 0.0115  I   -36.779     .455    -8.488     .298   .217200   .156300  -.1597400   -36.400    -9.100  
+95 9 5 49965.00 I   .215002  .000142   .155058  .000111  I -.1617171  .0000124  2.0633 0.0086  I   -36.615     .263    -8.714     .298   .214800   .154300  -.1617900   -36.300    -9.100  
+95 9 6 49966.00 I   .212740  .000142   .153069  .000109  I -.1638234  .0000121  2.1491 0.0091  I   -36.445     .263    -8.750     .298   .212500   .152300  -.1638800   -36.200    -9.100  
+95 9 7 49967.00 I   .210029  .000131   .151075  .000109  I -.1660164  .0000134  2.2381 0.0082  I   -36.352     .263    -8.556     .298   .209800   .150200  -.1660900   -36.000    -8.800  
+95 9 8 49968.00 I   .206969  .000128   .148852  .000109  I -.1682977  .0000110  2.3215 0.0086  I   -36.269     .263    -8.263     .298   .206900   .147800  -.1684000   -35.900    -8.700  
+95 9 9 49969.00 I   .203795  .000118   .146375  .000110  I -.1706431  .0000109  2.3561 0.0121  I   -36.151     .263    -8.079     .298   .203600   .145200  -.1707500   -36.000    -8.500  
+95 910 49970.00 I   .200570  .000147   .143742  .000112  I -.1729846  .0000215  2.3147 0.0080  I   -36.077     .185    -8.092     .298   .200300   .142400  -.1730900   -36.000    -8.300  
+95 911 49971.00 I   .197305  .000134   .140984  .000123  I -.1752536  .0000116  2.2166 0.0127  I   -36.148     .791    -8.197     .298   .197000   .139500  -.1753400   -36.100    -8.200  
+95 912 49972.00 I   .194074  .000119   .138110  .000129  I -.1774091  .0000134  2.0924 0.0082  I   -36.373     .791    -8.241     .298   .193700   .136700  -.1774800   -36.200    -8.100  
+95 913 49973.00 I   .191035  .000115   .135293  .000134  I -.1794394  .0000117  1.9710 0.0087  I   -36.631     .791    -8.195     .298   .190800   .134100  -.1794900   -36.200    -8.200  
+95 914 49974.00 I   .188269  .000110   .132860  .000142  I -.1813611  .0000111  1.8794 0.0081  I   -36.762     .791    -8.150     .298   .188000   .131900  -.1814000   -36.200    -8.300  
+95 915 49975.00 I   .185662  .000101   .130861  .000132  I -.1832127  .0000112  1.8312 0.0066  I   -36.676     .791    -8.190     .298   .185400   .129800  -.1832300   -36.100    -8.400  
+95 916 49976.00 I   .182997  .000104   .129117  .000146  I -.1850363  .0000072  1.8213 0.0067  I   -36.397     .791    -8.304     .298   .182800   .127900  -.1850200   -35.900    -8.600  
+95 917 49977.00 I   .180140  .000133   .127395  .000142  I -.1868638  .0000073  1.8370 0.0047  I   -36.035     .791    -8.419     .298   .180200   .126100  -.1868200   -35.600    -8.600  
+95 918 49978.00 I   .177142  .000144   .125569  .000181  I -.1887169  .0000059  1.8726 0.0044  I   -35.742     .791    -8.462     .134   .177500   .124300  -.1886600   -35.300    -8.600  
+95 919 49979.00 I   .174227  .000150   .123629  .000197  I -.1906144  .0000050  1.9245 0.0038  I   -35.624     .791    -8.408     .134   .174600   .122600  -.1905900   -35.000    -8.500  
+95 920 49980.00 I   .171426  .000156   .121661  .000205  I -.1925842  .0000048  2.0314 0.0035  I   -35.667     .791    -8.328     .121   .171500   .120800  -.1926200   -34.800    -8.400  
+95 921 49981.00 I   .168433  .000161   .119799  .000208  I -.1946974  .0000048  2.1987 0.0034  I   -35.733     .791    -8.430     .121   .168300   .119100  -.1947900   -34.700    -8.300  
+95 922 49982.00 I   .165227  .000150   .118066  .000205  I -.1969832  .0000047  2.3706 0.0036  I   -35.721     .791    -8.631     .121   .165000   .117300  -.1971000   -34.700    -8.000  
+95 923 49983.00 I   .161888  .000153   .116469  .000202  I -.1994317  .0000055  2.5218 0.0046  I   -35.649     .791    -8.651     .132   .161700   .115600  -.1995500   -34.900    -7.800  
+95 924 49984.00 I   .158666  .000103   .114917  .000179  I -.2020139  .0000080  2.6345 0.0043  I   -35.618     .791    -8.403     .298   .158400   .113900  -.2021200   -35.100    -7.700  
+95 925 49985.00 I   .155648  .000109   .113415  .000199  I -.2046817  .0000066  2.6903 0.0056  I   -35.683     .791    -8.016     .298   .155400   .112400  -.2047700   -35.500    -7.600  
+95 926 49986.00 I   .152758  .000088   .112022  .000191  I -.2073726  .0000078  2.6805 0.0052  I   -35.797     .791    -7.726     .298   .152500   .111000  -.2074300   -35.700    -7.600  
+95 927 49987.00 I   .149886  .000084   .110801  .000185  I -.2100182  .0000081  2.5973 0.0059  I   -35.857     .791    -7.672     .298   .149700   .109800  -.2100500   -35.900    -7.600  
+95 928 49988.00 I   .147073  .000089   .109840  .000186  I -.2125541  .0000089  2.4749 0.0057  I   -35.792     .791    -7.761     .298   .146900   .108800  -.2125800   -36.000    -7.700  
+95 929 49989.00 I   .144280  .000091   .108970  .000184  I -.2149738  .0000081  2.3701 0.0067  I   -35.636     .791    -7.849     .298   .144100   .107800  -.2150100   -36.100    -7.900  
+95 930 49990.00 I   .141336  .000102   .108038  .000171  I -.2173092  .0000100  2.3101 0.0066  I   -35.486     .791    -7.879     .298   .141100   .106900  -.2173700   -35.900    -8.000  
+9510 1 49991.00 I   .138111  .000091   .107025  .000131  I -.2196143  .0000104  2.3110 0.0064  I   -35.414     .791    -7.885     .298   .137900   .105900  -.2196900   -35.700    -8.000  
+9510 2 49992.00 I   .134567  .000131   .105987  .000110  I -.2219501  .0000079  2.3687 0.0063  I   -35.417     .791    -7.910     .298   .134300   .105000  -.2220200   -35.500    -8.100  
+9510 3 49993.00 I   .130695  .000129   .105001  .000111  I -.2243638  .0000070  2.4627 0.0055  I   -35.442     .791    -7.940     .298   .130600   .104100  -.2244200   -35.300    -8.000  
+9510 4 49994.00 I   .126575  .000127   .104045  .000111  I -.2268727  .0000076  2.5481 0.0061  I   -35.442     .791    -7.919     .298   .126600   .103100  -.2269100   -35.200    -7.900  
+9510 5 49995.00 I   .122609  .000128   .103062  .000114  I -.2294525  .0000100  2.6108 0.0062  I   -35.406     .791    -7.857     .298   .122500   .102000  -.2295000   -35.000    -7.700  
+9510 6 49996.00 I   .118773  .000127   .101939  .000117  I -.2320905  .0000098  2.6619 0.0070  I   -35.359     .791    -7.743     .298   .118500   .100900  -.2321600   -35.000    -7.600  
+9510 7 49997.00 I   .114860  .000126   .100643  .000105  I -.2347659  .0000097  2.6817 0.0091  I   -35.325     .791    -7.601     .298   .114600   .099600  -.2348500   -35.000    -7.400  
+9510 8 49998.00 I   .110837  .000098   .099201  .000116  I -.2374358  .0000154  2.6473 0.0091  I   -35.303     .121    -7.521     .298   .110600   .098100  -.2375100   -35.100    -7.400  
+9510 9 49999.00 I   .106690  .000169   .097625  .000155  I -.2400381  .0000155  2.5456 0.0107  I   -35.274     .101    -7.504     .298   .106400   .096500  -.2401000   -35.200    -7.400  
+951010 50000.00 I   .102471  .000212   .095946  .000161  I -.2425086  .0000148  2.3888 0.0109  I   -35.261     .133    -7.468     .126   .102200   .094900  -.2425500   -35.300    -7.400  
+951011 50001.00 I   .098323  .000219   .094278  .000180  I -.2448171  .0000154  2.2362 0.0108  I   -35.331     .116    -7.377     .138   .098200   .093200  -.2448700   -35.200    -7.600  
+951012 50002.00 I   .094472  .000228   .092742  .000174  I -.2469890  .0000158  2.1077 0.0110  I   -35.412     .116    -7.317     .138   .094400   .091700  -.2470300   -35.100    -7.700  
+951013 50003.00 I   .090997  .000231   .091469  .000182  I -.2490365  .0000158  1.9911 0.0121  I   -35.282     .116    -7.447     .138   .090900   .090200  -.2490800   -34.900    -7.800  
+951014 50004.00 I   .087895  .000229   .090594  .000182  I -.2509869  .0000183  1.9215 0.0115  I   -34.828     .106    -7.641     .160   .087800   .089400  -.2510300   -34.700    -7.900  
+951015 50005.00 I   .084727  .000197   .090020  .000153  I -.2528981  .0000166  1.9076 0.0115  I   -34.210     .127    -7.787     .194   .084800   .088800  -.2529600   -34.300    -7.900  
+951016 50006.00 I   .081140  .000165   .089428  .000142  I -.2548170  .0000140  1.9383 0.0107  I   -33.717     .791    -7.838     .121   .081100   .088200  -.2548900   -34.000    -7.900  
+951017 50007.00 I   .077223  .000152   .088633  .000115  I -.2567910  .0000136  2.0179 0.0099  I   -33.484     .791    -7.776     .298   .077100   .087500  -.2568600   -33.700    -7.800  
+951018 50008.00 I   .073319  .000124   .087696  .000122  I -.2588592  .0000140  2.1168 0.0097  I   -33.416     .791    -7.655     .298   .072900   .086700  -.2589200   -33.600    -7.600  
+951019 50009.00 I   .069832  .000125   .086810  .000106  I -.2610189  .0000137  2.1986 0.0089  I   -33.396     .791    -7.580     .298   .069400   .085700  -.2610700   -33.400    -7.400  
+951020 50010.00 I   .066975  .000143   .086104  .000108  I -.2632595  .0000110  2.2898 0.0088  I   -33.437     .791    -7.586     .298   .066600   .084900  -.2633200   -33.400    -7.200  
+951021 50011.00 I   .064561  .000151   .085696  .000106  I -.2656028  .0000109  2.3939 0.0092  I   -33.575     .118    -7.568     .298   .064500   .084600  -.2656600   -33.400    -6.900  
+951022 50012.00 I   .062087  .000193   .085544  .000129  I -.2680337  .0000147  2.4573 0.0079  I   -33.726     .158    -7.383     .298   .062100   .084500  -.2680800   -33.500    -6.800  
+951023 50013.00 I   .059125  .000151   .085440  .000138  I -.2705006  .0000114  2.4705 0.0086  I   -33.747     .157    -7.048     .298   .059000   .084300  -.2705500   -33.500    -6.600  
+951024 50014.00 I   .055535  .000146   .085180  .000131  I -.2729630  .0000091  2.4488 0.0075  I   -33.596     .157    -6.774     .298   .055100   .084100  -.2730200   -33.400    -6.700  
+951025 50015.00 I   .051426  .000130   .084676  .000130  I -.2753887  .0000096  2.3988 0.0060  I   -33.367     .157    -6.750     .298   .051100   .083700  -.2754500   -33.200    -6.700  
+951026 50016.00 I   .047101  .000122   .084034  .000150  I -.2777537  .0000079  2.3282 0.0059  I   -33.227     .157    -6.921     .298   .046900   .083200  -.2778100   -33.100    -6.700  
+951027 50017.00 I   .042802  .000110   .083316  .000146  I -.2800474  .0000068  2.2645 0.0052  I   -33.224     .155    -7.077     .298   .042600   .082400  -.2800900   -33.000    -6.900  
+951028 50018.00 I   .038761  .000099   .082671  .000148  I -.2823000  .0000069  2.2526 0.0048  I   -33.307     .155    -7.080     .298   .038600   .081800  -.2823500   -32.800    -6.900  
+951029 50019.00 I   .035078  .000106   .082295  .000131  I -.2845748  .0000067  2.3071 0.0046  I   -33.384     .791    -6.962     .298   .034900   .081400  -.2846300   -32.500    -6.900  
+951030 50020.00 I   .031665  .000092   .082253  .000105  I -.2869319  .0000060  2.4145 0.0048  I   -33.363     .791    -6.831     .298   .031500   .081300  -.2870000   -32.300    -6.800  
+951031 50021.00 I   .028365  .000097   .082439  .000106  I -.2894134  .0000069  2.5505 0.0046  I   -33.213     .791    -6.740     .298   .028200   .081400  -.2894800   -32.100    -6.700  
+9511 1 50022.00 I   .025113  .000097   .082725  .000098  I -.2920343  .0000071  2.6907 0.0050  I   -32.986     .791    -6.667     .298   .025000   .081700  -.2921000   -32.200    -6.600  
+9511 2 50023.00 I   .021946  .000089   .083061  .000097  I -.2947758  .0000073  2.7741 0.0051  I   -32.769     .791    -6.592     .298   .021800   .082100  -.2948200   -32.100    -6.400  
+9511 3 50024.00 I   .018673  .000089   .083419  .000100  I -.2975496  .0000073  2.7590 0.0050  I   -32.641     .791    -6.528     .298   .018300   .082400  -.2975700   -32.100    -6.200  
+9511 4 50025.00 I   .015135  .000085   .083780  .000104  I -.3002725  .0000069  2.6800 0.0073  I   -32.633     .791    -6.500     .298   .014900   .082700  -.3003000   -32.100    -6.100  
+9511 5 50026.00 I   .011387  .000095   .084118  .000185  I -.3028973  .0000126  2.5639 0.0086  I   -32.694     .791    -6.508     .298   .011200   .083000  -.3029300   -32.200    -6.000  
+9511 6 50027.00 I   .007541  .000086   .084428  .000184  I -.3053956  .0000158  2.4335 0.0100  I   -32.713     .357    -6.507     .298   .007600   .083300  -.3054500   -32.200    -6.100  
+9511 7 50028.00 I   .003739  .000098   .084751  .000188  I -.3077684  .0000156  2.3155 0.0109  I   -32.643     .357    -6.442     .298   .003700   .083600  -.3078300   -32.000    -6.100  
+9511 8 50029.00 I   .000001  .000104   .085124  .000181  I -.3100311  .0000151  2.2112 0.0108  I   -32.577     .384    -6.293     .298  -.000200   .083900  -.3100700   -31.700    -6.100  
+9511 9 50030.00 I  -.003744  .000106   .085488  .000179  I -.3121888  .0000149  2.1011 0.0108  I   -32.616     .384    -6.082     .298  -.004100   .084300  -.3122000   -31.500    -6.400  
+951110 50031.00 I  -.007475  .000111   .085790  .000182  I -.3142379  .0000154  2.0049 0.0103  I   -32.588     .384    -5.914     .298  -.007800   .084600  -.3142500   -31.200    -6.500  
+951111 50032.00 I  -.011231  .000132   .086077  .000175  I -.3162171  .0000143  1.9643 0.0087  I   -32.224     .384    -5.906     .298  -.011500   .084900  -.3162400   -30.700    -6.600  
+951112 50033.00 I  -.014987  .000180   .086408  .000142  I -.3181895  .0000081  1.9927 0.0078  I   -31.607     .362    -6.055     .298  -.015200   .085300  -.3182300   -30.400    -6.700  
+951113 50034.00 I  -.018569  .000198   .086804  .000161  I -.3202225  .0000062  2.0812 0.0050  I   -31.082     .295    -6.260     .298  -.018800   .085700  -.3202700   -30.100    -6.600  
+951114 50035.00 I  -.021862  .000177   .087327  .000169  I -.3223659  .0000058  2.2116 0.0044  I   -30.819     .192    -6.394     .298  -.022300   .086300  -.3224300   -29.900    -6.600  
+951115 50036.00 I  -.025065  .000182   .088127  .000170  I -.3246626  .0000063  2.3926 0.0040  I   -30.711     .168    -6.366     .298  -.025800   .087100  -.3247200   -29.900    -6.400  
+951116 50037.00 I  -.028782  .000189   .089292  .000170  I -.3271535  .0000054  2.5806 0.0041  I   -30.607     .168    -6.214     .298  -.029500   .088100  -.3271800   -30.000    -6.200  
+951117 50038.00 I  -.033035  .000171   .090654  .000162  I -.3298032  .0000054  2.7066 0.0037  I   -30.601     .168    -6.085     .298  -.033600   .089400  -.3298000   -30.100    -5.900  
+951118 50039.00 I  -.037476  .000174   .092091  .000160  I -.3325547  .0000050  2.7965 0.0048  I   -30.807     .791    -6.032     .298  -.037800   .090800  -.3325600   -30.300    -5.800  
+951119 50040.00 I  -.041719  .000156   .093516  .000157  I -.3353883  .0000079  2.8626 0.0055  I   -31.079     .791    -5.930     .298  -.042100   .092200  -.3354100   -30.500    -5.600  
+951120 50041.00 I  -.045724  .000152   .094850  .000153  I -.3382631  .0000097  2.8784 0.0074  I   -31.117     .791    -5.695     .298  -.046300   .093600  -.3383100   -30.700    -5.500  
+951121 50042.00 I  -.049751  .000177   .096014  .000189  I -.3411295  .0000125  2.8476 0.0078  I   -30.820     .791    -5.463     .298  -.050400   .094800  -.3411800   -30.600    -5.600  
+951122 50043.00 I  -.053914  .000163   .096986  .000212  I -.3439446  .0000122  2.7759 0.0087  I   -30.385     .791    -5.474     .298  -.054400   .096000  -.3440000   -30.500    -5.600  
+951123 50044.00 I  -.057976  .000171   .097979  .000217  I -.3466769  .0000122  2.6912 0.0090  I   -30.102     .791    -5.804     .298  -.058300   .097200  -.3467200   -30.400    -5.600  
+951124 50045.00 I  -.061727  .000179   .099130  .000223  I -.3493369  .0000133  2.6362 0.0090  I   -30.101     .791    -6.219     .298  -.061900   .098300  -.3493700   -30.200    -5.800  
+951125 50046.00 I  -.065201  .000197   .100487  .000251  I -.3519652  .0000131  2.6288 0.0084  I   -30.323     .791    -6.466     .298  -.065400   .099600  -.3519800   -29.900    -5.900  
+951126 50047.00 I  -.068566  .000211   .102026  .000157  I -.3546099  .0000101  2.6677 0.0083  I   -30.582     .791    -6.517     .109  -.068900   .101000  -.3546300   -29.800    -5.900  
+951127 50048.00 I  -.071992  .000199   .103675  .000136  I -.3573086  .0000102  2.7305 0.0074  I   -30.681     .791    -6.465     .101  -.072400   .102600  -.3573300   -29.600    -5.900  
+951128 50049.00 I  -.075682  .000271   .105386  .000112  I -.3600689  .0000109  2.7872 0.0075  I   -30.591     .791    -6.310     .101  -.076300   .104400  -.3601100   -29.600    -5.800  
+951129 50050.00 I  -.079882  .000284   .107134  .000105  I -.3628755  .0000110  2.8213 0.0079  I   -30.483     .791    -5.984     .101  -.080600   .106100  -.3629200   -29.800    -5.700  
+951130 50051.00 I  -.084668  .000292   .108887  .000088  I -.3656937  .0000115  2.8019 0.0078  I   -30.525     .791    -5.636     .101  -.085300   .107800  -.3657400   -30.000    -5.600  
+9512 1 50052.00 I  -.089793  .000278   .110581  .000107  I -.3684577  .0000112  2.7177 0.0080  I   -30.702     .791    -5.408     .101  -.090300   .109500  -.3685100   -30.200    -5.400  
+9512 2 50053.00 I  -.094910  .000269   .112190  .000102  I -.3711199  .0000110  2.6059 0.0122  I   -30.883     .791    -5.347     .298  -.095300   .111200  -.3711900   -30.400    -5.200  
+9512 3 50054.00 I  -.099728  .000269   .113810  .000111  I -.3736715  .0000216  2.4999 0.0094  I   -30.973     .791    -5.378     .298  -.100100   .112800  -.3737600   -30.600    -5.100  
+9512 4 50055.00 I  -.104255  .000249   .115578  .000145  I -.3761191  .0000153  2.3919 0.0130  I   -30.935     .299    -5.380     .298  -.104800   .114500  -.3762000   -30.600    -5.200  
+9512 5 50056.00 I  -.108571  .000228   .117528  .000152  I -.3784535  .0000146  2.2785 0.0107  I   -30.736     .314    -5.315     .298  -.109200   .116400  -.3785200   -30.600    -5.200  
+9512 6 50057.00 I  -.112580  .000228   .119567  .000159  I -.3806794  .0000151  2.1748 0.0105  I   -30.376     .314    -5.244     .298  -.113200   .118500  -.3807300   -30.300    -5.200  
+9512 7 50058.00 I  -.116132  .000230   .121605  .000164  I -.3828140  .0000151  2.1036 0.0107  I   -29.921     .314    -5.220     .298  -.116600   .120700  -.3828500   -30.100    -5.400  
+9512 8 50059.00 I  -.119291  .000224   .123582  .000165  I -.3849046  .0000151  2.0863 0.0092  I   -29.527     .314    -5.230     .298  -.119700   .122700  -.3849300   -29.600    -5.400  
+9512 9 50060.00 I  -.122360  .000237   .125522  .000166  I -.3870040  .0000105  2.1211 0.0092  I   -29.226     .314    -5.249     .298  -.122600   .124600  -.3870300   -29.300    -5.500  
+951210 50061.00 I  -.125428  .000269   .127453  .000175  I -.3891584  .0000106  2.1906 0.0062  I   -29.022     .329    -5.293     .298  -.125800   .126400  -.3891800   -29.000    -5.500  
+951211 50062.00 I  -.128714  .000217   .129439  .000150  I -.3913900  .0000065  2.2746 0.0062  I   -28.989     .122    -5.385     .298  -.129100   .128400  -.3914100   -28.600    -5.500  
+951212 50063.00 I  -.132294  .000191   .131545  .000153  I -.3937117  .0000063  2.3708 0.0047  I   -29.081     .102    -5.472     .298  -.132600   .130400  -.3937500   -28.600    -5.400  
+951213 50064.00 I  -.135762  .000195   .133872  .000147  I -.3961394  .0000068  2.4904 0.0052  I   -29.082     .102    -5.462     .298  -.135900   .132800  -.3961900   -28.600    -5.300  
+951214 50065.00 I  -.138554  .000179   .136542  .000145  I -.3986872  .0000084  2.5940 0.0051  I   -28.888     .102    -5.347     .298  -.138900   .135500  -.3987300   -28.800    -5.100  
+951215 50066.00 I  -.140929  .000162   .139485  .000140  I -.4013079  .0000077  2.6389 0.0057  I   -28.737     .102    -5.185     .298  -.141300   .138400  -.4013500   -28.900    -5.000  
+951216 50067.00 I  -.143210  .000193   .142573  .000191  I -.4039535  .0000077  2.6492 0.0083  I   -28.889     .102    -5.061     .298  -.143500   .141400  -.4040000   -29.100    -4.800  
+951217 50068.00 I  -.145513  .000210   .145731  .000237  I -.4066048  .0000146  2.6551 0.0087  I   -29.254     .791    -4.953     .298  -.145700   .144600  -.4066600   -29.200    -4.800  
+951218 50069.00 I  -.147835  .000228   .148873  .000240  I -.4092583  .0000155  2.6447 0.0105  I   -29.504     .791    -4.784     .298  -.148000   .147700  -.4093200   -29.200    -4.800  
+951219 50070.00 I  -.150201  .000257   .151908  .000242  I -.4118837  .0000150  2.6029 0.0095  I   -29.474     .791    -4.651     .298  -.150400   .150800  -.4119500   -29.100    -4.800  
+951220 50071.00 I  -.152541  .000252   .154799  .000250  I -.4144558  .0000110  2.5363 0.0099  I   -29.300     .791    -4.766     .298  -.152900   .153700  -.4145200   -28.900    -4.800  
+951221 50072.00 I  -.154776  .000258   .157666  .000255  I -.4169546  .0000128  2.4645 0.0086  I   -29.200     .791    -5.091     .298  -.155200   .156600  -.4170000   -28.700    -4.900  
+951222 50073.00 I  -.156826  .000233   .160665  .000254  I -.4193989  .0000133  2.4351 0.0088  I   -29.275     .791    -5.380     .298  -.157100   .159500  -.4194400   -28.400    -5.000  
+951223 50074.00 I  -.158669  .000175   .163912  .000148  I -.4218509  .0000120  2.4842 0.0080  I   -29.480     .791    -5.421     .298  -.158900   .162800  -.4218800   -28.300    -5.100  
+951224 50075.00 I  -.160459  .000145   .167387  .000129  I -.4243901  .0000090  2.6018 0.0065  I   -29.656     .791    -5.252     .298  -.160700   .166200  -.4244100   -28.200    -5.100  
+951225 50076.00 I  -.162335  .000113   .170951  .000119  I -.4270547  .0000049  2.7202 0.0052  I   -29.628     .791    -5.083     .298  -.162700   .169900  -.4270700   -28.200    -5.100  
+951226 50077.00 I  -.164330  .000069   .174443  .000101  I -.4298117  .0000053  2.7824 0.0027  I   -29.412     .791    -4.994     .298  -.164800   .173400  -.4298400   -28.400    -4.900  
+951227 50078.00 I  -.166407  .000055   .177742  .000094  I -.4325949  .0000024  2.7709 0.0033  I   -29.256     .791    -4.890     .298  -.167000   .176600  -.4326300   -28.700    -4.900  
+951228 50079.00 I  -.168495  .000074   .180798  .000093  I -.4353285  .0000039  2.6844 0.0024  I   -29.357     .791    -4.719     .298  -.169000   .179500  -.4353800   -29.000    -4.800  
+951229 50080.00 I  -.170527  .000064   .183633  .000091  I -.4379429  .0000042  2.5354 0.0029  I   -29.591     .791    -4.596     .298  -.170900   .182300  -.4379900   -29.100    -4.700  
+951230 50081.00 I  -.172465  .000108   .186350  .000088  I -.4403853  .0000043  2.3442 0.0056  I   -29.680     .791    -4.643     .298  -.172700   .185100  -.4404300   -29.400    -4.600  
+951231 50082.00 I  -.174304  .000169   .189077  .000146  I -.4426252  .0000103  2.1347 0.0044  I   -29.557     .791    -4.797     .298  -.174500   .188000  -.4426700   -29.500    -4.500  
+96 1 1 50083.00 I  -.175934  .000172   .191874  .000177  I  .5553429  .0000076  1.9325 0.0065  I   -29.394     .791    -4.888     .298  -.176200   .190800   .5552900   -29.400    -4.600  
+96 1 2 50084.00 I  -.177203  .000171   .194733  .000187  I  .5534992  .0000080  1.7620 0.0050  I   -29.306     .791    -4.849     .298  -.177700   .193700   .5534400   -29.300    -4.600  
+96 1 3 50085.00 I  -.178219  .000167   .197661  .000231  I  .5518040  .0000066  1.6361 0.0057  I   -29.226     .791    -4.768     .298  -.178700   .196600   .5517600   -28.800    -4.700  
+96 1 4 50086.00 I  -.179271  .000201   .200769  .000265  I  .5502108  .0000082  1.5587 0.0058  I   -29.079     .791    -4.739     .298  -.179700   .199600   .5501600   -28.400    -4.800  
+96 1 5 50087.00 I  -.180413  .000175   .204061  .000270  I  .5486679  .0000096  1.5374 0.0061  I   -28.892     .791    -4.756     .298  -.180700   .202900   .5486300   -28.000    -5.000  
+96 1 6 50088.00 I  -.181716  .000200   .207436  .000272  I  .5471137  .0000089  1.5831 0.0084  I   -28.710     .791    -4.783     .298  -.182100   .206200   .5471000   -27.600    -5.200  
+96 1 7 50089.00 I  -.183392  .000165   .210670  .000268  I  .5454827  .0000137  1.6859 0.0068  I   -28.546     .791    -4.849     .298  -.183900   .209600   .5454800   -27.400    -5.300  
+96 1 8 50090.00 I  -.185233  .000158   .213575  .000255  I  .5437364  .0000102  1.8052 0.0086  I   -28.421     .791    -5.007     .298  -.185700   .212600   .5437200   -27.400    -5.200  
+96 1 9 50091.00 I  -.186902  .000161   .216171  .000229  I  .5418803  .0000103  1.9004 0.0071  I   -28.349     .791    -5.208     .298  -.187100   .215200   .5418400   -27.600    -5.300  
+96 110 50092.00 I  -.188610  .000139   .218633  .000185  I  .5399478  .0000098  1.9590 0.0070  I   -28.276     .791    -5.310     .298  -.189000   .217500   .5399000   -27.800    -5.300  
+96 111 50093.00 I  -.190544  .000143   .221323  .000184  I  .5379721  .0000096  1.9883 0.0070  I   -28.168     .791    -5.232     .298  -.191000   .220100   .5379200   -28.100    -5.200  
+96 112 50094.00 I  -.192621  .000131   .224329  .000240  I  .5359773  .0000101  1.9993 0.0063  I   -28.132     .791    -5.062     .298  -.192700   .223000   .5359300   -28.600    -5.100  
+96 113 50095.00 I  -.194690  .000122   .227472  .000226  I  .5339774  .0000082  1.9986 0.0095  I   -28.313     .791    -4.945     .298  -.194800   .226200   .5339400   -28.900    -5.000  
+96 114 50096.00 I  -.196600  .000139   .230482  .000225  I  .5319852  .0000160  1.9827 0.0087  I   -28.673     .791    -4.904     .298  -.197000   .229500   .5319200   -29.100    -5.000  
+96 115 50097.00 I  -.198256  .000192   .233199  .000221  I  .5300178  .0000154  1.9494 0.0118  I   -29.010     .791    -4.864     .298  -.198600   .232300   .5299700   -29.300    -4.900  
+96 116 50098.00 I  -.199573  .000179   .235746  .000221  I  .5280928  .0000173  1.8968 0.0116  I   -29.212     .791    -4.833     .298  -.200000   .234700   .5280700   -29.200    -4.900  
+96 117 50099.00 I  -.200722  .000180   .238434  .000215  I  .5262338  .0000173  1.8155 0.0121  I   -29.356     .791    -4.937     .298  -.201300   .237100   .5262100   -29.100    -5.000  
+96 118 50100.00 I  -.202042  .000179   .241575  .000178  I  .5244563  .0000169  1.7506 0.0117  I   -29.552     .791    -5.217     .298  -.202500   .240200   .5244100   -28.800    -5.000  
+96 119 50101.00 I  -.203464  .000175   .245190  .000185  I  .5227037  .0000157  1.7723 0.0121  I   -29.802     .791    -5.482     .298  -.203700   .244000   .5227000   -28.700    -5.000  
+96 120 50102.00 I  -.204972  .000215   .249073  .000239  I  .5208840  .0000173  1.8771 0.0124  I   -30.012     .791    -5.505     .298  -.205300   .248100   .5209000   -28.500    -5.000  
+96 121 50103.00 I  -.206515  .000183   .252890  .000244  I  .5189387  .0000193  2.0143 0.0112  I   -30.053     .791    -5.306     .298  -.207100   .252000   .5189200   -28.300    -5.000  
+96 122 50104.00 I  -.208097  .000203   .256437  .000255  I  .5168645  .0000143  2.1240 0.0117  I   -29.834     .791    -5.112     .298  -.208500   .255500   .5168300   -28.400    -5.000  
+96 123 50105.00 I  -.209673  .000198   .259782  .000264  I  .5147185  .0000131  2.1502 0.0096  I   -29.454     .791    -5.049     .298  -.209900   .258800   .5146800   -28.600    -4.900  
+96 124 50106.00 I  -.210988  .000196   .263176  .000257  I  .5125896  .0000129  2.1000 0.0087  I   -29.222     .791    -5.015     .298  -.211400   .262100   .5125500   -29.000    -4.900  
+96 125 50107.00 I  -.211914  .000199   .266751  .000251  I  .5105347  .0000115  2.0013 0.0087  I   -29.365     .791    -4.949     .298  -.212400   .265600   .5104800   -29.300    -4.900  
+96 126 50108.00 I  -.212703  .000195   .270456  .000263  I  .5085976  .0000118  1.8707 0.0064  I   -29.717     .791    -4.913     .298  -.213000   .269400   .5085400   -29.700    -5.000  
+96 127 50109.00 I  -.213735  .000128   .274297  .000255  I  .5067973  .0000058  1.7280 0.0066  I   -29.911     .791    -5.020     .298  -.213900   .273300   .5067400   -29.900    -5.100  
+96 128 50110.00 I  -.215159  .000098   .278183  .000253  I  .5051407  .0000061  1.5880 0.0045  I   -29.841     .158    -5.262     .298  -.215500   .277300   .5051000   -30.000    -5.200  
+96 129 50111.00 I  -.216851  .000099   .281901  .000234  I  .5036132  .0000069  1.4725 0.0050  I   -29.729     .163    -5.495     .298  -.217200   .281000   .5035800   -29.900    -5.400  
+96 130 50112.00 I  -.218493  .000109   .285363  .000237  I  .5021832  .0000078  1.3947 0.0052  I   -29.714     .197    -5.618     .298  -.218800   .284400   .5021500   -29.600    -5.600  
+96 131 50113.00 I  -.219824  .000099   .288726  .000235  I  .5008057  .0000078  1.3714 0.0054  I   -29.645     .197    -5.663     .298  -.220200   .287700   .5007700   -29.200    -5.700  
+96 2 1 50114.00 I  -.220800  .000088   .292186  .000183  I  .4994203  .0000075  1.4085 0.0058  I   -29.423     .197    -5.681     .298  -.221300   .290900   .4993900   -28.700    -5.800  
+96 2 2 50115.00 I  -.221440  .000087   .295824  .000163  I  .4979729  .0000085  1.4932 0.0069  I   -29.133     .197    -5.670     .298  -.221800   .294600   .4979800   -28.500    -5.800  
+96 2 3 50116.00 I  -.221815  .000102   .299586  .000186  I  .4964256  .0000117  1.6030 0.0061  I   -28.932     .174    -5.620     .298  -.222200   .298700   .4964100   -28.200    -5.800  
+96 2 4 50117.00 I  -.222065  .000106   .303384  .000196  I  .4947668  .0000088  1.7133 0.0066  I   -28.852     .110    -5.589     .298  -.222300   .302300   .4947300   -28.100    -5.800  
+96 2 5 50118.00 I  -.222381  .000097   .307187  .000164  I  .4930004  .0000061  1.8194 0.0055  I   -28.845     .576    -5.645     .298  -.222400   .305900   .4929300   -28.000    -5.800  
+96 2 6 50119.00 I  -.222896  .000103   .310942  .000182  I  .4911259  .0000066  1.9318 0.0045  I   -28.935     .670    -5.767     .298  -.223200   .309700   .4910300   -28.200    -5.800  
+96 2 7 50120.00 I  -.223554  .000137   .314574  .000187  I  .4891368  .0000066  2.0444 0.0043  I   -29.209     .670    -5.857     .298  -.223900   .313300   .4890800   -28.300    -5.800  
+96 2 8 50121.00 I  -.224342  .000139   .318023  .000180  I  .4870476  .0000056  2.1257 0.0042  I   -29.711     .670    -5.902     .298  -.224600   .316900   .4870400   -28.200    -5.900  
+96 2 9 50122.00 I  -.225044  .000162   .321171  .000182  I  .4849035  .0000051  2.1529 0.0040  I   -30.118     .670    -5.896     .298  -.225300   .320300   .4848600   -28.200    -6.000  
+96 210 50123.00 I  -.225181  .000161   .323983  .000167  I  .4827588  .0000056  2.1291 0.0068  I   -30.281     .817    -5.882     .298  -.225300   .322900   .4827400   -28.200    -6.100  
+96 211 50124.00 I  -.224580  .000171   .326681  .000187  I  .4806567  .0000127  2.0711 0.0053  I   -30.265     .663    -5.893     .298  -.224700   .325500   .4806600   -28.300    -6.200  
+96 212 50125.00 I  -.223400  .000164   .329470  .000151  I  .4786206  .0000091  2.0010 0.0076  I   -30.117     .533    -5.894     .298  -.223900   .328400   .4786100   -28.600    -6.100  
+96 213 50126.00 I  -.221975  .000135   .332497  .000148  I  .4766505  .0000083  1.9436 0.0063  I   -29.920     .533    -5.875     .298  -.222400   .331400   .4766200   -29.100    -6.000  
+96 214 50127.00 I  -.220650  .000133   .335894  .000146  I  .4747223  .0000086  1.9194 0.0057  I   -29.779     .483    -5.885     .298  -.221000   .334800   .4746900   -29.600    -5.900  
+96 215 50128.00 I  -.219519  .000084   .339747  .000120  I  .4727933  .0000079  1.9504 0.0054  I   -29.609     .483    -5.960     .298  -.219800   .338500   .4727600   -29.800    -5.700  
+96 216 50129.00 I  -.218710  .000092   .344051  .000123  I  .4707968  .0000064  2.0554 0.0051  I   -29.461     .483    -6.013     .298  -.219100   .342700   .4707600   -29.800    -5.600  
+96 217 50130.00 I  -.218381  .000093   .348607  .000176  I  .4686632  .0000065  2.2182 0.0050  I   -29.437     .502    -5.924     .298  -.218900   .347600   .4686900   -29.700    -5.600  
+96 218 50131.00 I  -.218571  .000096   .353126  .000188  I  .4663566  .0000078  2.3924 0.0047  I   -29.438     .365    -5.710     .298  -.219000   .352200   .4664100   -29.300    -5.600  
+96 219 50132.00 I  -.219284  .000139   .357369  .000168  I  .4638910  .0000067  2.5287 0.0046  I   -29.353     .262    -5.582     .298  -.219800   .356500   .4639200   -29.000    -5.700  
+96 220 50133.00 I  -.220255  .000132   .361221  .000179  I  .4613243  .0000050  2.5896 0.0043  I   -29.218     .791    -5.715     .298  -.220800   .360200   .4613000   -28.800    -5.900  
+96 221 50134.00 I  -.221031  .000133   .364694  .000191  I  .4587397  .0000055  2.5668 0.0040  I   -29.233     .791    -6.025     .298  -.221300   .363600   .4586900   -28.800    -6.000  
+96 222 50135.00 I  -.221356  .000127   .367982  .000191  I  .4562191  .0000062  2.4586 0.0044  I   -29.540     .791    -6.278     .298  -.221700   .366900   .4562000   -29.100    -6.100  
+96 223 50136.00 I  -.221356  .000128   .371356  .000161  I  .4538542  .0000068  2.2551 0.0048  I   -30.009     .791    -6.389     .298  -.221500   .369900   .4538500   -29.500    -6.300  
+96 224 50137.00 I  -.221173  .000122   .375065  .000174  I  .4517135  .0000074  2.0378 0.0053  I   -30.356     .791    -6.464     .298  -.221400   .373500   .4516400   -30.000    -6.400  
+96 225 50138.00 I  -.220760  .000100   .379108  .000194  I  .4497550  .0000082  1.8915 0.0056  I   -30.495     .791    -6.594     .298  -.221200   .378000   .4496300   -30.300    -6.500  
+96 226 50139.00 I  -.220267  .000096   .383241  .000183  I  .4479084  .0000084  1.8116 0.0117  I   -30.591     .791    -6.764     .298  -.220700   .382200   .4477600   -30.500    -6.600  
+96 227 50140.00 I  -.219849  .000130   .387230  .000182  I  .4461162  .0000220  1.7783 0.0114  I   -30.729     .791    -6.920     .298  -.220100   .386100   .4459900   -30.500    -6.900  
+96 228 50141.00 I  -.219416  .000138   .391075  .000184  I  .4443430  .0000212  1.7712 0.0149  I   -30.727     .791    -7.034     .298  -.219800   .390000   .4442800   -30.100    -7.000  
+96 229 50142.00 I  -.218720  .000146   .394877  .000190  I  .4425576  .0000202  1.8128 0.0142  I   -30.420     .791    -7.097     .298  -.219200   .393500   .4425900   -29.700    -7.100  
+96 3 1 50143.00 I  -.217592  .000138   .398724  .000167  I  .4406961  .0000190  1.9185 0.0133  I   -29.944     .791    -7.096     .298  -.218100   .397500   .4407400   -29.200    -7.100  
+96 3 2 50144.00 I  -.216046  .000143   .402709  .000173  I  .4387105  .0000173  2.0545 0.0111  I   -29.568     .791    -7.053     .298  -.216400   .401800   .4386800   -28.700    -7.200  
+96 3 3 50145.00 I  -.214256  .000143   .406820  .000157  I  .4365826  .0000113  2.2041 0.0090  I   -29.366     .791    -7.034     .298  -.214400   .405800   .4365700   -28.400    -7.200  
+96 3 4 50146.00 I  -.212377  .000114   .410989  .000146  I  .4343027  .0000052  2.3526 0.0062  I   -29.210     .791    -7.087     .298  -.212700   .409800   .4343200   -28.200    -7.100  
+96 3 5 50147.00 I  -.210462  .000108   .415165  .000159  I  .4318862  .0000052  2.4747 0.0042  I   -29.035     .791    -7.179     .298  -.210800   .413800   .4318900   -28.200    -7.100  
+96 3 6 50148.00 I  -.208540  .000104   .419342  .000163  I  .4293659  .0000065  2.5588 0.0039  I   -28.924     .791    -7.249     .298  -.209000   .418200   .4293400   -28.400    -7.200  
+96 3 7 50149.00 I  -.206795  .000103   .423380  .000159  I  .4267812  .0000057  2.6050 0.0049  I   -28.931     .791    -7.285     .298  -.207100   .422300   .4267300   -28.700    -7.200  
+96 3 8 50150.00 I  -.205259  .000102   .427213  .000154  I  .4241680  .0000073  2.6150 0.0053  I   -29.022     .791    -7.314     .298  -.205900   .425900   .4241600   -29.100    -7.300  
+96 3 9 50151.00 I  -.203908  .000117   .430867  .000202  I  .4215619  .0000090  2.5927 0.0076  I   -29.113     .321    -7.363     .298  -.204300   .429800   .4216000   -29.400    -7.300  
+96 310 50152.00 I  -.202582  .000126   .434377  .000214  I  .4189899  .0000133  2.5483 0.0092  I   -29.170     .367    -7.426     .298  -.203000   .433300   .4190100   -29.500    -7.400  
+96 311 50153.00 I  -.201172  .000142   .437787  .000233  I  .4164748  .0000160  2.4755 0.0100  I   -29.216     .367    -7.480     .298  -.201800   .436600   .4164900   -29.500    -7.500  
+96 312 50154.00 I  -.199681  .000153   .441159  .000243  I  .4140508  .0000150  2.3672 0.0109  I   -29.273     .367    -7.534     .298  -.199800   .440100   .4140600   -29.400    -7.600  
+96 313 50155.00 I  -.198181  .000161   .444555  .000234  I  .4117438  .0000148  2.2488 0.0098  I   -29.332     .367    -7.631     .298  -.198600   .443400   .4117000   -29.100    -7.600  
+96 314 50156.00 I  -.196547  .000168   .448062  .000231  I  .4095361  .0000125  2.1818 0.0091  I   -29.352     .367    -7.780     .298  -.197100   .447000   .4094800   -28.700    -7.800  
+96 315 50157.00 I  -.194698  .000164   .451546  .000228  I  .4073526  .0000105  2.1975 0.0079  I   -29.321     .791    -7.891     .298  -.195100   .450500   .4073300   -28.400    -7.800  
+96 316 50158.00 I  -.192737  .000188   .454954  .000212  I  .4051230  .0000098  2.2674 0.0076  I   -29.256     .791    -7.841     .298  -.193100   .453800   .4051100   -28.100    -7.900  
+96 317 50159.00 I  -.190621  .000202   .458387  .000229  I  .4028131  .0000111  2.3515 0.0059  I   -29.180     .791    -7.622     .298  -.191100   .457400   .4028100   -28.000    -7.900  
+96 318 50160.00 I  -.188103  .000190   .461977  .000198  I  .4004263  .0000067  2.4167 0.0076  I   -29.102     .791    -7.415     .298  -.188700   .460700   .4004400   -28.100    -7.900  
+96 319 50161.00 I  -.185015  .000175   .465952  .000201  I  .3979922  .0000103  2.4444 0.0068  I   -29.037     .791    -7.436     .298  -.185500   .464600   .3979900   -28.200    -7.900  
+96 320 50162.00 I  -.181736  .000174   .470274  .000220  I  .3955522  .0000118  2.4279 0.0083  I   -29.044     .791    -7.720     .298  -.182000   .469400   .3955200   -28.400    -8.000  
+96 321 50163.00 I  -.178926  .000199   .474524  .000225  I  .3931553  .0000129  2.3547 0.0088  I   -29.179     .791    -8.078     .298  -.179100   .473800   .3931500   -28.500    -7.900  
+96 322 50164.00 I  -.176775  .000150   .478401  .000200  I  .3908599  .0000131  2.2303 0.0087  I   -29.403     .791    -8.294     .298  -.177000   .477600   .3908500   -28.700    -7.900  
+96 323 50165.00 I  -.175051  .000160   .481739  .000189  I  .3886987  .0000118  2.0938 0.0088  I   -29.629     .791    -8.320     .298  -.175600   .480800   .3886500   -28.800    -8.000  
+96 324 50166.00 I  -.173268  .000164   .484606  .000166  I  .3866632  .0000117  1.9845 0.0068  I   -29.829     .369    -8.268     .298  -.173900   .483500   .3866500   -28.800    -8.000  
+96 325 50167.00 I  -.171139  .000176   .487249  .000143  I  .3847174  .0000067  1.9120 0.0066  I   -30.011     .496    -8.254     .298  -.171600   .486200   .3847200   -28.700    -8.100  
+96 326 50168.00 I  -.168588  .000169   .489916  .000116  I  .3828287  .0000061  1.8711 0.0043  I   -30.084     .440    -8.305     .298  -.169100   .488800   .3828000   -28.600    -8.200  
+96 327 50169.00 I  -.165644  .000155   .492745  .000120  I  .3809636  .0000055  1.8650 0.0043  I   -29.876     .440    -8.364     .298  -.166000   .491600   .3809300   -28.300    -8.300  
+96 328 50170.00 I  -.162586  .000142   .495671  .000102  I  .3790850  .0000060  1.9002 0.0040  I   -29.464     .440    -8.392     .298  -.162900   .494600   .3790600   -27.900    -8.500  
+96 329 50171.00 I  -.159679  .000133   .498650  .000098  I  .3771505  .0000057  1.9737 0.0053  I   -28.989     .440    -8.361     .298  -.160200   .497700   .3771400   -27.700    -8.500  
+96 330 50172.00 I  -.156908  .000114   .501603  .000097  I  .3751298  .0000088  2.0707 0.0090  I   -28.666     .472    -8.305     .298  -.157200   .500500   .3751100   -27.400    -8.500  
+96 331 50173.00 I  -.154212  .000101   .504539  .000100  I  .3730040  .0000171  2.1829 0.0079  I   -28.606     .298    -8.301     .298  -.154600   .503400   .3729600   -27.400    -8.500  
+96 4 1 50174.00 I  -.151663  .000117   .507519  .000123  I  .3707596  .0000131  2.3081 0.0110  I   -28.693     .247    -8.367     .298  -.152300   .506400   .3708000   -27.500    -8.400  
+96 4 2 50175.00 I  -.149362  .000124   .510501  .000125  I  .3683888  .0000137  2.4303 0.0093  I   -28.784     .246    -8.423     .298  -.149700   .509400   .3685000   -28.000    -8.300  
+96 4 3 50176.00 I  -.147360  .000128   .513289  .000134  I  .3659173  .0000133  2.4977 0.0095  I   -28.867     .246    -8.396     .298  -.147900   .512200   .3659300   -28.400    -8.300  
+96 4 4 50177.00 I  -.145638  .000137   .515645  .000143  I  .3634127  .0000133  2.5073 0.0086  I   -28.994     .246    -8.338     .298  -.146000   .514500   .3633400   -28.700    -8.400  
+96 4 5 50178.00 I  -.143920  .000148   .517579  .000142  I  .3609107  .0000110  2.4928 0.0081  I   -29.092     .246    -8.369     .298  -.144200   .516300   .3609000   -29.100    -8.400  
+96 4 6 50179.00 I  -.142117  .000183   .519318  .000155  I  .3584370  .0000093  2.4487 0.0086  I   -29.093     .246    -8.541     .298  -.142300   .518100   .3584400   -29.400    -8.500  
+96 4 7 50180.00 I  -.140191  .000181   .521063  .000161  I  .3560213  .0000131  2.3808 0.0059  I   -29.012     .245    -8.775     .298  -.140400   .519900   .3560200   -29.500    -8.700  
+96 4 8 50181.00 I  -.137977  .000180   .522959  .000139  I  .3536761  .0000071  2.3108 0.0075  I   -28.909     .791    -8.941     .298  -.138500   .521600   .3536600   -29.400    -8.800  
+96 4 9 50182.00 I  -.135234  .000179   .525188  .000133  I  .3513918  .0000075  2.2646 0.0055  I   -28.840     .791    -8.991     .298  -.135700   .523700   .3513800   -29.200    -8.800  
+96 410 50183.00 I  -.132187  .000195   .527816  .000131  I  .3491286  .0000085  2.2733 0.0059  I   -28.802     .791    -8.973     .298  -.132700   .526700   .3491000   -28.900    -8.900  
+96 411 50184.00 I  -.129341  .000205   .530702  .000141  I  .3468257  .0000090  2.3407 0.0060  I   -28.733     .791    -8.959     .298  -.129400   .529800   .3468200   -28.400    -8.900  
+96 412 50185.00 I  -.126573  .000181   .533654  .000131  I  .3444367  .0000085  2.4398 0.0059  I   -28.558     .791    -8.964     .298  -.126700   .532700   .3444800   -28.000    -8.900  
+96 413 50186.00 I  -.123540  .000182   .536510  .000120  I  .3419479  .0000076  2.5335 0.0094  I   -28.286     .791    -8.932     .298  -.123800   .535500   .3419800   -27.700    -8.900  
+96 414 50187.00 I  -.120077  .000180   .539229  .000133  I  .3393835  .0000168  2.5859 0.0086  I   -28.040     .791    -8.816     .298  -.120300   .538200   .3393300   -27.500    -8.800  
+96 415 50188.00 I  -.116351  .000192   .541835  .000124  I  .3367947  .0000154  2.5827 0.0112  I   -27.977     .791    -8.672     .298  -.116700   .540600   .3367600   -27.500    -8.800  
+96 416 50189.00 I  -.112714  .000165   .544371  .000136  I  .3342362  .0000147  2.5252 0.0103  I   -28.144     .791    -8.650     .298  -.112900   .543100   .3342400   -27.600    -8.800  
+96 417 50190.00 I  -.109479  .000154   .546890  .000134  I  .3317556  .0000138  2.4338 0.0100  I   -28.426     .791    -8.844     .298  -.109600   .545800   .3317400   -27.800    -8.900  
+96 418 50191.00 I  -.106534  .000154   .549353  .000153  I  .3293821  .0000136  2.3020 0.0112  I   -28.662     .791    -9.175     .298  -.107000   .548400   .3293200   -28.100    -9.000  
+96 419 50192.00 I  -.103718  .000163   .551690  .000158  I  .3271622  .0000176  2.1385 0.0114  I   -28.763     .791    -9.444     .298  -.104200   .550600   .3271400   -28.400    -9.100  
+96 420 50193.00 I  -.100881  .000147   .553900  .000169  I  .3250953  .0000184  2.0044 0.0108  I   -28.796     .791    -9.531     .298  -.100900   .552900   .3250900   -28.500    -9.300  
+96 421 50194.00 I  -.097922  .000130   .556020  .000150  I  .3231337  .0000126  1.9294 0.0106  I   -28.874     .791    -9.490     .298  -.098000   .554900   .3231400   -28.500    -9.300  
+96 422 50195.00 I  -.094702  .000133   .558058  .000135  I  .3212225  .0000104  1.8964 0.0082  I   -28.979     .466    -9.454     .255  -.095100   .556600   .3212000   -28.500    -9.400  
+96 423 50196.00 I  -.091203  .000148   .559985  .000143  I  .3193323  .0000104  1.8890 0.0074  I   -28.959     .427    -9.480     .223  -.091300   .558900   .3192800   -28.200    -9.400  
+96 424 50197.00 I  -.087651  .000165   .561722  .000132  I  .3174315  .0000104  1.9204 0.0063  I   -28.674     .382    -9.499     .200  -.088000   .560600   .3174000   -27.800    -9.400  
+96 425 50198.00 I  -.084232  .000163   .563198  .000149  I  .3154816  .0000071  1.9813 0.0062  I   -28.166     .382    -9.450     .200  -.084800   .562300   .3154700   -27.500    -9.300  
+96 426 50199.00 I  -.080698  .000158   .564540  .000154  I  .3134595  .0000066  2.0704 0.0048  I   -27.711     .382    -9.384     .200  -.081100   .563800   .3134500   -27.200    -9.200  
+96 427 50200.00 I  -.076772  .000158   .565959  .000155  I  .3113307  .0000064  2.1896 0.0053  I   -27.474     .382    -9.296     .200  -.077100   .564900   .3113000   -27.000    -9.100  
+96 428 50201.00 I  -.072472  .000156   .567693  .000185  I  .3090793  .0000084  2.3116 0.0058  I   -27.509     .199    -9.247     .298  -.072700   .566400   .3090500   -27.000    -9.100  
+96 429 50202.00 I  -.068033  .000137   .569841  .000182  I  .3067111  .0000096  2.4227 0.0065  I   -27.810     .243    -9.282     .298  -.068300   .568500   .3066900   -27.100    -9.000  
+96 430 50203.00 I  -.063732  .000100   .572237  .000178  I  .3042392  .0000099  2.5177 0.0069  I   -28.257     .523    -9.318     .298  -.064000   .571100   .3042100   -27.500    -9.100  
+96 5 1 50204.00 I  -.059829  .000118   .574547  .000157  I  .3016817  .0000099  2.5946 0.0071  I   -28.644     .523    -9.243     .298  -.059900   .573600   .3016500   -27.900    -9.200  
+96 5 2 50205.00 I  -.056414  .000130   .576487  .000138  I  .2990626  .0000102  2.6336 0.0074  I   -28.806     .523    -9.089     .298  -.056600   .575600   .2990300   -28.400    -9.300  
+96 5 3 50206.00 I  -.053179  .000140   .578097  .000127  I  .2964375  .0000111  2.6037 0.0076  I   -28.598     .523    -8.975     .298  -.053500   .577000   .2964200   -28.900    -9.500  
+96 5 4 50207.00 I  -.049736  .000144   .579512  .000115  I  .2938736  .0000112  2.5186 0.0085  I   -28.151     .523    -9.038     .298  -.049900   .578500   .2938600   -29.300    -9.600  
+96 5 5 50208.00 I  -.045973  .000147   .580829  .000104  I  .2914053  .0000128  2.4185 0.0087  I   -27.721     .931    -9.255     .298  -.046000   .579900   .2913700   -29.400    -9.700  
+96 5 6 50209.00 I  -.042012  .000153   .582102  .000126  I  .2890282  .0000133  2.3435 0.0093  I   -27.502    1.043    -9.442     .298  -.042100   .581000   .2890300   -29.400    -9.800  
+96 5 7 50210.00 I  -.037918  .000135   .583347  .000133  I  .2866998  .0000135  2.3239 0.0095  I   -27.703    1.043    -9.490     .298  -.038000   .582200   .2867100   -29.300    -9.700  
+96 5 8 50211.00 I  -.033632  .000123   .584594  .000137  I  .2843591  .0000136  2.3681 0.0098  I   -28.404    1.043    -9.460     .298  -.033800   .583500   .2843400   -29.000    -9.700  
+96 5 9 50212.00 I  -.029180  .000115   .585848  .000152  I  .2819499  .0000141  2.4533 0.0099  I   -29.094    1.043    -9.383     .298  -.029300   .584800   .2819500   -28.700    -9.500  
+96 510 50213.00 I  -.024728  .000110   .587025  .000157  I  .2794478  .0000144  2.5525 0.0098  I   -29.457    1.043    -9.335     .298  -.024900   .586000   .2794900   -28.400    -9.300  
+96 511 50214.00 I  -.020330  .000086   .588093  .000151  I  .2768482  .0000135  2.6416 0.0093  I   -29.424     .934    -9.336     .298  -.020800   .587000   .2768600   -28.300    -9.200  
+96 512 50215.00 I  -.015922  .000091   .589125  .000121  I  .2741811  .0000117  2.6811 0.0084  I   -29.110     .791    -9.319     .298  -.016300   .587800   .2741700   -28.100    -9.100  
+96 513 50216.00 I  -.011521  .000088   .590154  .000137  I  .2715088  .0000101  2.6523 0.0078  I   -28.799     .791    -9.232     .298  -.011700   .589000   .2714900   -28.100    -9.000  
+96 514 50217.00 I  -.007268  .000104   .591099  .000148  I  .2688973  .0000103  2.5610 0.0069  I   -28.748     .791    -9.102     .298  -.007800   .589800   .2688800   -28.300    -8.900  
+96 515 50218.00 I  -.003399  .000112   .591911  .000133  I  .2663992  .0000095  2.4324 0.0070  I   -28.967     .791    -9.008     .298  -.004000   .590700   .2663800   -28.500    -9.000  
+96 516 50219.00 I  -.000024  .000114   .592626  .000134  I  .2640413  .0000095  2.2775 0.0065  I   -29.226     .791    -8.988     .298  -.000300   .591600   .2640100   -28.600    -9.000  
+96 517 50220.00 I   .003144  .000109   .593209  .000140  I  .2618504  .0000090  2.1039 0.0068  I   -29.296     .791    -9.005     .298   .003000   .592300   .2618600   -28.800    -9.000  
+96 518 50221.00 I   .006435  .000110   .593685  .000131  I  .2598275  .0000096  1.9484 0.0077  I   -29.186     .791    -9.005     .298   .006000   .592600   .2598300   -28.800    -9.200  
+96 519 50222.00 I   .009919  .000123   .594127  .000116  I  .2579410  .0000125  1.8307 0.0067  I   -29.065     .791    -8.998     .298   .009700   .592900   .2579500   -28.700    -9.300  
+96 520 50223.00 I   .013491  .000122   .594555  .000111  I  .2561562  .0000094  1.7428 0.0083  I   -29.007     .791    -9.042     .298   .013400   .593600   .2561500   -28.500    -9.300  
+96 521 50224.00 I   .017124  .000103   .594917  .000120  I  .2544473  .0000109  1.6793 0.0069  I   -28.956     .791    -9.186     .298   .017100   .593900   .2544200   -28.300    -9.300  
+96 522 50225.00 I   .020937  .000098   .595164  .000115  I  .2527826  .0000102  1.6609 0.0078  I   -28.895     .791    -9.420     .298   .020800   .594100   .2527500   -28.000    -9.300  
+96 523 50226.00 I   .025152  .000109   .595261  .000115  I  .2511090  .0000112  1.6920 0.0082  I   -28.900     .791    -9.618     .298   .024800   .594000   .2511000   -27.900    -9.200  
+96 524 50227.00 I   .029779  .000105   .595317  .000111  I  .2493911  .0000129  1.7456 0.0083  I   -28.934     .791    -9.690     .298   .029600   .594000   .2493600   -27.900    -9.200  
+96 525 50228.00 I   .034665  .000098   .595469  .000115  I  .2476132  .0000122  1.8132 0.0114  I   -28.871     .791    -9.625     .298   .034400   .594300   .2476200   -28.000    -9.000  
+96 526 50229.00 I   .039753  .000092   .595702  .000149  I  .2457632  .0000188  1.8854 0.0098  I   -28.756     .791    -9.503     .298   .039400   .594600   .2457400   -28.300    -9.000  
+96 527 50230.00 I   .044841  .000092   .595957  .000175  I  .2438479  .0000153  1.9409 0.0115  I   -28.864     .791    -9.426     .298   .044700   .594700   .2438100   -28.600    -9.000  
+96 528 50231.00 I   .049615  .000087   .596238  .000155  I  .2418917  .0000134  1.9653 0.0100  I   -29.358     .791    -9.384     .298   .049500   .594900   .2418500   -29.000    -9.000  
+96 529 50232.00 I   .053882  .000096   .596541  .000156  I  .2399269  .0000128  1.9610 0.0088  I   -30.023     .791    -9.256     .298   .053800   .595400   .2398900   -29.400    -9.100  
+96 530 50233.00 I   .057700  .000094   .596714  .000163  I  .2379830  .0000114  1.9168 0.0085  I   -30.487     .791    -9.008     .298   .057500   .595600   .2379800   -29.700    -9.100  
+96 531 50234.00 I   .061444  .000097   .596642  .000164  I  .2361074  .0000111  1.8304 0.0077  I   -30.610     .791    -8.791     .298   .061200   .595600   .2361100   -30.000    -9.200  
+96 6 1 50235.00 I   .065503  .000113   .596277  .000155  I  .2343259  .0000105  1.7330 0.0075  I   -30.561     .791    -8.810     .298   .065300   .595400   .2343000   -30.100    -9.200  
+96 6 2 50236.00 I   .069860  .000121   .595604  .000121  I  .2326331  .0000101  1.6606 0.0068  I   -30.532     .791    -9.069     .298   .069800   .594500   .2326100   -30.200    -9.200  
+96 6 3 50237.00 I   .074230  .000146   .594696  .000164  I  .2309860  .0000085  1.6445 0.0073  I   -30.547     .791    -9.326     .298   .074300   .593500   .2309700   -30.100    -9.100  
+96 6 4 50238.00 I   .078467  .000146   .593622  .000190  I  .2293212  .0000105  1.6973 0.0072  I   -30.581     .791    -9.359     .298   .078400   .592900   .2292900   -29.900    -9.100  
+96 6 5 50239.00 I   .082604  .000148   .592449  .000190  I  .2275791  .0000116  1.7872 0.0087  I   -30.692     .791    -9.192     .298   .082300   .591600   .2275400   -30.000    -9.000  
+96 6 6 50240.00 I   .086784  .000143   .591323  .000184  I  .2257463  .0000138  1.8786 0.0088  I   -30.930     .791    -8.975     .298   .086400   .590000   .2257100   -29.900    -8.900  
+96 6 7 50241.00 I   .090816  .000143   .590282  .000182  I  .2238242  .0000133  1.9631 0.0097  I   -31.233     .791    -8.864     .298   .090500   .589000   .2237900   -30.000    -8.800  
+96 6 8 50242.00 I   .094546  .000115   .589194  .000162  I  .2218261  .0000136  2.0296 0.0099  I   -31.444     .791    -8.892     .298   .094500   .588000   .2218100   -30.200    -8.700  
+96 6 9 50243.00 I   .098025  .000073   .587957  .000130  I  .2197756  .0000148  2.0643 0.0094  I   -31.444     .791    -8.991     .298   .097900   .586900   .2198100   -30.500    -8.700  
+96 610 50244.00 I   .101457  .000100   .586564  .000172  I  .2177168  .0000129  2.0411 0.0099  I   -31.287     .166    -9.077     .172   .101200   .585400   .2177500   -30.900    -8.800  
+96 611 50245.00 I   .105120  .000094   .585084  .000178  I  .2157148  .0000131  1.9536 0.0088  I   -31.193     .165    -9.087     .177   .104900   .583900   .2156800   -31.200    -8.800  
+96 612 50246.00 I   .109158  .000086   .583575  .000171  I  .2138240  .0000121  1.8228 0.0092  I   -31.343     .165    -8.964     .177   .108900   .582500   .2137800   -31.500    -9.000  
+96 613 50247.00 I   .113468  .000083   .581998  .000178  I  .2120760  .0000130  1.6714 0.0088  I   -31.651     .165    -8.626     .177   .113200   .580900   .2121100   -31.700    -9.200  
+96 614 50248.00 I   .117895  .000076   .580426  .000178  I  .2104819  .0000128  1.5179 0.0093  I   -31.912     .165    -8.354     .177   .117800   .579200   .2104800   -31.900    -9.300  
+96 615 50249.00 I   .122258  .000086   .578845  .000182  I  .2090393  .0000134  1.3673 0.0099  I   -31.982     .197    -8.356     .211   .122200   .577800   .2089500   -32.000    -9.400  
+96 616 50250.00 I   .126467  .000109   .577104  .000144  I  .2077336  .0000150  1.2579 0.0086  I   -31.881     .162    -8.552     .187   .126100   .576400   .2077400   -31.800    -9.500  
+96 617 50251.00 I   .130498  .000090   .575237  .000125  I  .2065038  .0000108  1.2075 0.0101  I   -31.732     .791    -8.801     .298   .130300   .574100   .2064900   -31.800    -9.400  
+96 618 50252.00 I   .134268  .000094   .573331  .000167  I  .2053055  .0000136  1.1962 0.0093  I   -31.645     .791    -8.996     .298   .134300   .572000   .2052500   -31.600    -9.400  
+96 619 50253.00 I   .137862  .000123   .571399  .000193  I  .2040955  .0000151  1.2324 0.0103  I   -31.733     .383    -9.125     .185   .137800   .570400   .2040700   -31.500    -9.200  
+96 620 50254.00 I   .141523  .000125   .569469  .000193  I  .2028277  .0000155  1.3076 0.0107  I   -32.068     .361    -9.204     .160   .141400   .568400   .2028700   -31.500    -9.000  
+96 621 50255.00 I   .145303  .000121   .567674  .000189  I  .2014758  .0000151  1.3962 0.0111  I   -32.526     .361    -9.185     .160   .145100   .566600   .2015300   -31.600    -8.900  
+96 622 50256.00 I   .149172  .000116   .566173  .000189  I  .2000356  .0000159  1.4838 0.0110  I   -32.804     .361    -9.013     .160   .148900   .565100   .2000600   -31.800    -8.900  
+96 623 50257.00 I   .153039  .000102   .564948  .000191  I  .1985142  .0000161  1.5532 0.0095  I   -32.842     .465    -8.803     .173   .152900   .564000   .1984900   -32.100    -8.800  
+96 624 50258.00 I   .156765  .000108   .563751  .000167  I  .1969418  .0000103  1.5847 0.0084  I   -32.954     .463    -8.676     .169   .156600   .562700   .1969100   -32.500    -8.800  
+96 625 50259.00 I   .160185  .000088   .562310  .000087  I  .1953602  .0000050  1.5701 0.0056  I   -33.423     .458    -8.732     .116   .159800   .561300   .1953400   -32.800    -8.900  
+96 626 50260.00 I   .163281  .000085   .560423  .000094  I  .1938095  .0000045  1.5319 0.0035  I   -34.065     .429    -8.894     .116   .162900   .559500   .1937800   -33.200    -8.900  
+96 627 50261.00 I   .166362  .000090   .558025  .000101  I  .1923025  .0000050  1.4755 0.0034  I   -34.561     .429    -8.855     .116   .166200   .556800   .1923000   -33.700    -8.900  
+96 628 50262.00 I   .169493  .000098   .555334  .000099  I  .1908709  .0000050  1.3818 0.0035  I   -34.691     .429    -8.649     .116   .169200   .554100   .1908900   -34.100    -8.900  
+96 629 50263.00 I   .172608  .000096   .552597  .000113  I  .1895423  .0000048  1.2778 0.0045  I   -34.607     .319    -8.556     .108   .172200   .551400   .1895400   -34.500    -8.900  
+96 630 50264.00 I   .175817  .000090   .549915  .000137  I  .1883068  .0000074  1.1992 0.0050  I   -34.604     .791    -8.675     .298   .175600   .548600   .1882900   -34.800    -8.700  
+96 7 1 50265.00 I   .179070  .000128   .547255  .000148  I  .1871278  .0000087  1.1689 0.0109  I   -34.769     .791    -8.814     .298   .179000   .545900   .1871200   -34.900    -8.600  
+96 7 2 50266.00 I   .182205  .000154   .544555  .000191  I  .1859475  .0000205  1.2031 0.0113  I   -34.999     .791    -8.744     .298   .182300   .543100   .1859300   -35.000    -8.500  
+96 7 3 50267.00 I   .185266  .000151   .541804  .000203  I  .1846984  .0000209  1.3070 0.0149  I   -35.206     .791    -8.482     .298   .185200   .540600   .1846700   -35.000    -8.400  
+96 7 4 50268.00 I   .188487  .000146   .539052  .000212  I  .1833305  .0000216  1.4201 0.0148  I   -35.411     .791    -8.248     .298   .188100   .537900   .1833800   -35.000    -8.400  
+96 7 5 50269.00 I   .191979  .000141   .536334  .000193  I  .1818802  .0000209  1.4673 0.0146  I   -35.707     .791    -8.181     .298   .191700   .534600   .1820100   -35.000    -8.400  
+96 7 6 50270.00 I   .195778  .000138   .533729  .000179  I  .1804193  .0000195  1.4444 0.0127  I   -36.123     .791    -8.244     .298   .195600   .531800   .1805700   -35.200    -8.300  
+96 7 7 50271.00 I   .199792  .000133   .531295  .000169  I  .1790079  .0000146  1.3721 0.0106  I   -36.514     .791    -8.360     .298   .199700   .529500   .1791100   -35.200    -8.500  
+96 7 8 50272.00 I   .203823  .000149   .528995  .000150  I  .1776848  .0000085  1.2706 0.0090  I   -36.655     .791    -8.526     .298   .203900   .527500   .1777200   -35.400    -8.600  
+96 7 9 50273.00 I   .207687  .000170   .526712  .000172  I  .1764712  .0000105  1.1554 0.0067  I   -36.524     .791    -8.726     .298   .207800   .525300   .1764400   -35.500    -8.800  
+96 710 50274.00 I   .211388  .000184   .524315  .000175  I  .1753711  .0000103  1.0487 0.0071  I   -36.416     .164    -8.858     .298   .211100   .523000   .1753400   -35.700    -8.800  
+96 711 50275.00 I   .215158  .000179   .521696  .000172  I  .1743692  .0000097  0.9557 0.0071  I   -36.639     .164    -8.827     .298   .215000   .520300   .1743700   -35.900    -9.000  
+96 712 50276.00 I   .218752  .000171   .518866  .000170  I  .1734575  .0000097  0.8694 0.0067  I   -37.114     .164    -8.713     .298   .218500   .517300   .1734500   -36.000    -9.000  
+96 713 50277.00 I   .221889  .000168   .515895  .000155  I  .1726196  .0000091  0.8157 0.0076  I   -37.464     .164    -8.688     .298   .221500   .514400   .1725800   -36.000    -8.900  
+96 714 50278.00 I   .224827  .000136   .512845  .000160  I  .1718092  .0000116  0.8127 0.0065  I   -37.448     .179    -8.781     .298   .224800   .511400   .1718100   -36.100    -8.800  
+96 715 50279.00 I   .227709  .000132   .509712  .000143  I  .1709819  .0000092  0.8465 0.0066  I   -37.134     .189    -8.855     .298   .227600   .508500   .1710000   -36.100    -8.700  
+96 716 50280.00 I   .230519  .000104   .506559  .000117  I  .1701089  .0000062  0.9022 0.0056  I   -36.745     .152    -8.790     .298   .230200   .505200   .1701000   -36.100    -8.600  
+96 717 50281.00 I   .233085  .000110   .503531  .000097  I  .1691727  .0000063  0.9725 0.0048  I   -36.504     .152    -8.636     .298   .232800   .502000   .1691400   -36.200    -8.600  
+96 718 50282.00 I   .235301  .000117   .500701  .000087  I  .1681581  .0000074  1.0603 0.0048  I   -36.580     .152    -8.534     .298   .235000   .499200   .1681300   -36.200    -8.400  
+96 719 50283.00 I   .237275  .000121   .497932  .000086  I  .1670524  .0000073  1.1472 0.0048  I   -36.866     .152    -8.572     .298   .237200   .497000   .1670400   -36.300    -8.400  
+96 720 50284.00 I   .238918  .000102   .495123  .000149  I  .1658696  .0000061  1.2163 0.0054  I   -37.048     .155    -8.664     .298   .239100   .493900   .1658600   -36.500    -8.400  
+96 721 50285.00 I   .240184  .000110   .492260  .000180  I  .1646247  .0000079  1.2707 0.0047  I   -36.970     .456    -8.684     .134   .240000   .490700   .1645800   -36.700    -8.500  
+96 722 50286.00 I   .241314  .000111   .489368  .000202  I  .1633338  .0000072  1.3085 0.0047  I   -36.881     .468    -8.648     .148   .241100   .487900   .1632900   -36.900    -8.500  
+96 723 50287.00 I   .242591  .000086   .486495  .000169  I  .1620133  .0000051  1.3296 0.0044  I   -37.183     .468    -8.681     .148   .242800   .484800   .1620200   -37.200    -8.700  
+96 724 50288.00 I   .244009  .000084   .483674  .000170  I  .1606780  .0000049  1.3405 0.0037  I   -37.914     .406    -8.810     .130   .244000   .482100   .1606700   -37.500    -8.900  
+96 725 50289.00 I   .245469  .000087   .480888  .000191  I  .1593401  .0000053  1.3279 0.0036  I   -38.712     .406    -8.841     .130   .245000   .479800   .1593400   -37.800    -9.000  
+96 726 50290.00 I   .247079  .000090   .478037  .000195  I  .1580361  .0000054  1.2735 0.0037  I   -39.162     .406    -8.761     .130   .246800   .476700   .1580200   -38.100    -9.200  
+96 727 50291.00 I   .248835  .000088   .475059  .000168  I  .1567921  .0000053  1.2222 0.0040  I   -39.230     .139    -8.752     .298   .248700   .473500   .1567500   -38.200    -9.300  
+96 728 50292.00 I   .250734  .000066   .472110  .000160  I  .1555719  .0000059  1.2304 0.0038  I   -39.206     .791    -8.875     .298   .250700   .470400   .1555600   -38.500    -9.300  
+96 729 50293.00 I   .252661  .000068   .469292  .000148  I  .1543073  .0000054  1.3107 0.0050  I   -39.316     .791    -8.994     .298   .252700   .467600   .1542900   -38.700    -9.200  
+96 730 50294.00 I   .254453  .000072   .466543  .000190  I  .1529305  .0000080  1.4510 0.0052  I   -39.543     .791    -8.940     .298   .254300   .465200   .1529300   -38.900    -9.000  
+96 731 50295.00 I   .256087  .000063   .463725  .000180  I  .1513964  .0000089  1.6182 0.0071  I   -39.717     .791    -8.754     .298   .255900   .462600   .1513900   -39.200    -8.800  
+96 8 1 50296.00 I   .257649  .000058   .460694  .000139  I  .1497082  .0000117  1.7433 0.0075  I   -39.727     .791    -8.625     .298   .257700   .459300   .1496800   -39.500    -8.700  
+96 8 2 50297.00 I   .259242  .000055   .457382  .000130  I  .1479439  .0000121  1.7662 0.0083  I   -39.698     .791    -8.628     .298   .259000   .456300   .1479100   -39.800    -8.400  
+96 8 3 50298.00 I   .260754  .000066   .453772  .000118  I  .1462136  .0000118  1.6758 0.0142  I   -39.895     .791    -8.631     .298   .260500   .452800   .1461800   -40.100    -8.400  
+96 8 4 50299.00 I   .262152  .000057   .449899  .000094  I  .1446201  .0000258  1.5020 0.0127  I   -40.375     .791    -8.529     .298   .262200   .448300   .1445800   -40.300    -8.300  
+96 8 5 50300.00 I   .263615  .000070   .445865  .000177  I  .1432182  .0000225  1.3024 0.0186  I   -40.820     .397    -8.427     .298   .263600   .444600   .1432100   -40.300    -8.300  
+96 8 6 50301.00 I   .265323  .000090   .441767  .000171  I  .1420121  .0000268  1.1126 0.0185  I   -40.895     .405    -8.496     .298   .265100   .440500   .1420100   -40.300    -8.400  
+96 8 7 50302.00 I   .267376  .000103   .437702  .000177  I  .1409883  .0000293  0.9371 0.0204  I   -40.729     .405    -8.727     .298   .267100   .436500   .1410100   -40.300    -8.400  
+96 8 8 50303.00 I   .269796  .000111   .433842  .000176  I  .1401274  .0000308  0.7933 0.0215  I   -40.798     .405    -8.954     .298   .269400   .432600   .1401400   -40.400    -8.600  
+96 8 9 50304.00 I   .272298  .000105   .430200  .000197  I  .1393817  .0000314  0.7096 0.0204  I   -41.176     .405    -9.030     .298   .272200   .429000   .1394400   -40.600    -8.800  
+96 810 50305.00 I   .274464  .000112   .426635  .000172  I  .1386936  .0000267  0.6697 0.0222  I   -41.526     .405    -9.004     .298   .274400   .425200   .1386800   -40.700    -8.800  
+96 811 50306.00 I   .276292  .000104   .423082  .000163  I  .1380287  .0000314  0.6707 0.0171  I   -41.524     .294    -8.971     .298   .276000   .421400   .1379900   -40.800    -8.900  
+96 812 50307.00 I   .278048  .000114   .419545  .000113  I  .1373368  .0000215  0.7178 0.0178  I   -41.175     .791    -8.898     .298   .277800   .418000   .1372800   -40.800    -8.800  
+96 813 50308.00 I   .279980  .000102   .416016  .000103  I  .1365864  .0000168  0.7850 0.0129  I   -40.735     .791    -8.723     .298   .279900   .414800   .1365800   -40.600    -8.800  
+96 814 50309.00 I   .282112  .000117   .412506  .000110  I  .1357628  .0000142  0.8642 0.0107  I   -40.421     .791    -8.510     .298   .282000   .411200   .1357600   -40.100    -8.700  
+96 815 50310.00 I   .284194  .000105   .409021  .000089  I  .1348547  .0000133  0.9535 0.0091  I   -40.320     .791    -8.397     .298   .283900   .407800   .1348200   -39.600    -8.500  
+96 816 50311.00 I   .285973  .000100   .405504  .000084  I  .1338546  .0000115  1.0465 0.0078  I   -40.398     .791    -8.468     .298   .286100   .404200   .1338600   -39.400    -8.400  
+96 817 50312.00 I   .287390  .000103   .401913  .000088  I  .1327661  .0000083  1.1262 0.0072  I   -40.518     .791    -8.647     .298   .287200   .400700   .1327800   -39.400    -8.400  
+96 818 50313.00 I   .288667  .000072   .398273  .000095  I  .1316146  .0000085  1.1688 0.0056  I   -40.537     .791    -8.782     .298   .288100   .396900   .1315700   -39.400    -8.400  
+96 819 50314.00 I   .290024  .000078   .394658  .000078  I  .1304407  .0000074  1.1749 0.0054  I   -40.479     .791    -8.808     .298   .289900   .393200   .1304000   -39.500    -8.400  
+96 820 50315.00 I   .291404  .000066   .391108  .000078  I  .1292722  .0000066  1.1588 0.0058  I   -40.559     .791    -8.782     .298   .291000   .389900   .1292800   -39.800    -8.500  
+96 821 50316.00 I   .292692  .000065   .387592  .000071  I  .1281259  .0000089  1.1341 0.0064  I   -40.933     .791    -8.773     .298   .292200   .386400   .1281100   -40.100    -8.700  
+96 822 50317.00 I   .293933  .000065   .384110  .000067  I  .1270006  .0000109  1.1194 0.0071  I   -41.481     .791    -8.794     .298   .293900   .382600   .1269900   -40.200    -8.800  
+96 823 50318.00 I   .295088  .000063   .380662  .000085  I  .1258849  .0000111  1.1111 0.0084  I   -41.919     .791    -8.842     .298   .294800   .379300   .1258700   -40.300    -9.000  
+96 824 50319.00 I   .296087  .000096   .377192  .000122  I  .1247746  .0000128  1.1140 0.0121  I   -42.099     .791    -8.937     .298   .295600   .376000   .1247200   -40.500    -9.100  
+96 825 50320.00 I   .296841  .000105   .373579  .000148  I  .1236414  .0000215  1.1633 0.0098  I   -42.109     .767    -9.062     .298   .296700   .372300   .1235900   -40.700    -9.200  
+96 826 50321.00 I   .297290  .000157   .369723  .000144  I  .1224278  .0000148  1.2731 0.0126  I   -42.127     .661    -9.102     .298   .297100   .368300   .1224000   -41.000    -9.100  
+96 827 50322.00 I   .297493  .000158   .365659  .000148  I  .1210837  .0000131  1.4173 0.0092  I   -42.204     .575    -8.971     .298   .297000   .364100   .1210700   -41.300    -9.100  
+96 828 50323.00 I   .297670  .000164   .361446  .000146  I  .1195813  .0000110  1.5972 0.0092  I   -42.215     .575    -8.755     .298   .297300   .360100   .1195700   -41.600    -8.900  
+96 829 50324.00 I   .298033  .000165   .357036  .000140  I  .1178957  .0000130  1.7578 0.0084  I   -42.082     .575    -8.621     .298   .297900   .355700   .1179000   -41.900    -8.700  
+96 830 50325.00 I   .298180  .000167   .352481  .000139  I  .1160999  .0000128  1.8157 0.0086  I   -41.825     .575    -8.648     .298   .297700   .351500   .1161200   -42.100    -8.500  
+96 831 50326.00 I   .297996  .000153   .347920  .000095  I  .1142992  .0000114  1.7689 0.0083  I   -41.710     .269    -8.670     .298   .297500   .346700   .1143200   -42.200    -8.300  
+96 9 1 50327.00 I   .297595  .000102   .343439  .000088  I  .1125912  .0000107  1.6347 0.0072  I   -41.977     .143    -8.489     .298   .297200   .342200   .1126200   -42.200    -8.100  
+96 9 2 50328.00 I   .297111  .000110   .339045  .000075  I  .1110459  .0000089  1.4523 0.0068  I   -42.430     .277    -8.184     .298   .296800   .337900   .1111500   -42.200    -8.000  
+96 9 3 50329.00 I   .296552  .000117   .334745  .000077  I  .1096902  .0000083  1.2592 0.0056  I   -42.608     .234    -8.023     .298   .296500   .333200   .1098300   -42.100    -8.100  
+96 9 4 50330.00 I   .295960  .000112   .330523  .000078  I  .1085160  .0000067  1.1007 0.0053  I   -42.366     .305    -8.154     .152   .295700   .329200   .1085500   -42.000    -8.100  
+96 9 5 50331.00 I   .295473  .000114   .326376  .000077  I  .1074717  .0000067  0.9935 0.0041  I   -42.104     .279    -8.470     .146   .295100   .325300   .1073800   -41.700    -8.300  
+96 9 6 50332.00 I   .294897  .000109   .322302  .000078  I  .1065122  .0000048  0.9367 0.0042  I   -42.107     .279    -8.807     .146   .294600   .321100   .1064600   -41.700    -8.500  
+96 9 7 50333.00 I   .294281  .000118   .318273  .000083  I  .1055830  .0000051  0.9258 0.0042  I   -42.159     .299    -8.926     .163   .294000   .316900   .1055800   -41.700    -8.600  
+96 9 8 50334.00 I   .293581  .000101   .314370  .000080  I  .1046463  .0000068  0.9578 0.0047  I   -42.023     .248    -8.902     .163   .293300   .313300   .1046500   -41.600    -8.800  
+96 9 9 50335.00 I   .292918  .000102   .310562  .000082  I  .1036476  .0000079  1.0491 0.0062  I   -41.746     .243    -8.853     .140   .292600   .309500   .1036700   -41.600    -8.700  
+96 910 50336.00 I   .292468  .000093   .306814  .000071  I  .1025295  .0000103  1.1963 0.0094  I   -41.537     .791    -8.756     .298   .292200   .305500   .1025400   -41.600    -8.700  
+96 911 50337.00 I   .292078  .000087   .303180  .000065  I  .1012360  .0000170  1.4005 0.0096  I   -41.497     .791    -8.620     .298   .291700   .302000   .1012300   -41.700    -8.600  
+96 912 50338.00 I   .291441  .000082   .299621  .000075  I  .0997288  .0000162  1.6039 0.0115  I   -41.534     .791    -8.506     .298   .291100   .298400   .0997500   -41.700    -8.400  
+96 913 50339.00 I   .290440  .000076   .295973  .000076  I  .0980515  .0000154  1.7374 0.0094  I   -41.571     .791    -8.430     .298   .290200   .294600   .0980600   -41.800    -8.300  
+96 914 50340.00 I   .289166  .000060   .292145  .000096  I  .0962769  .0000094  1.8023 0.0085  I   -41.639     .791    -8.378     .298   .288800   .291300   .0962500   -41.900    -8.200  
+96 915 50341.00 I   .287719  .000074   .288083  .000095  I  .0944635  .0000074  1.8175 0.0053  I   -41.718     .791    -8.343     .298   .287500   .287200   .0944700   -41.900    -8.200  
+96 916 50342.00 I   .286237  .000072   .283819  .000095  I  .0926574  .0000048  1.7863 0.0042  I   -41.709     .791    -8.328     .298   .286000   .282600   .0927000   -41.800    -8.200  
+96 917 50343.00 I   .284921  .000075   .279497  .000105  I  .0909065  .0000038  1.7084 0.0029  I   -41.606     .791    -8.354     .298   .284000   .278100   .0908900   -41.800    -8.200  
+96 918 50344.00 I   .283911  .000076   .275292  .000097  I  .0892429  .0000033  1.6237 0.0028  I   -41.559     .791    -8.432     .298   .283300   .274100   .0892200   -41.600    -8.400  
+96 919 50345.00 I   .283203  .000081   .271200  .000093  I  .0876477  .0000042  1.5732 0.0026  I   -41.688     .791    -8.488     .298   .282900   .270000   .0876400   -41.200    -8.500  
+96 920 50346.00 I   .282657  .000078   .267301  .000096  I  .0860787  .0000039  1.5759 0.0031  I   -41.923     .791    -8.491     .298   .282500   .266000   .0860000   -41.000    -8.500  
+96 921 50347.00 I   .282139  .000071   .263790  .000096  I  .0844801  .0000045  1.6258 0.0040  I   -42.120     .122    -8.456     .298   .281900   .262400   .0844400   -40.700    -8.600  
+96 922 50348.00 I   .281419  .000060   .260549  .000110  I  .0828080  .0000069  1.7330 0.0040  I   -42.210     .129    -8.452     .298   .281100   .259300   .0828300   -40.700    -8.500  
+96 923 50349.00 I   .280372  .000066   .257324  .000102  I  .0809917  .0000066  1.9075 0.0052  I   -42.221     .139    -8.439     .298   .280100   .256600   .0810400   -40.700    -8.500  
+96 924 50350.00 I   .278936  .000060   .253900  .000086  I  .0789841  .0000077  2.1086 0.0060  I   -42.204     .161    -8.344     .298   .278500   .253000   .0790100   -41.000    -8.400  
+96 925 50351.00 I   .277230  .000067   .250239  .000094  I  .0767836  .0000101  2.2825 0.0064  I   -42.146     .191    -8.206     .298   .276800   .249000   .0767800   -41.300    -8.200  
+96 926 50352.00 I   .275516  .000087   .246473  .000150  I  .0744490  .0000102  2.3668 0.0069  I   -42.005     .191    -8.075     .298   .275400   .245200   .0744500   -41.700    -8.100  
+96 927 50353.00 I   .273808  .000091   .242655  .000150  I  .0720875  .0000095  2.3387 0.0060  I   -41.738     .152    -8.036     .298   .273500   .241500   .0720500   -42.100    -7.900  
+96 928 50354.00 I   .272150  .000094   .238863  .000154  I  .0698002  .0000064  2.2247 0.0058  I   -41.488     .152    -8.011     .298   .271400   .237300   .0697300   -42.300    -7.700  
+96 929 50355.00 I   .270516  .000093   .235209  .000170  I  .0676504  .0000068  2.0738 0.0044  I   -41.480     .791    -7.819     .115   .269700   .233500   .0676500   -42.300    -7.600  
+96 930 50356.00 I   .268914  .000103   .231685  .000142  I  .0656491  .0000059  1.9333 0.0040  I   -41.709     .173    -7.466     .101   .268400   .230500   .0656900   -42.200    -7.400  
+9610 1 50357.00 I   .267380  .000095   .228141  .000148  I  .0637705  .0000043  1.8328 0.0036  I   -41.890     .285    -7.213     .298   .266800   .227100   .0638000   -41.900    -7.400  
+9610 2 50358.00 I   .265754  .000082   .224491  .000134  I  .0619873  .0000041  1.7209 0.0031  I   -41.789     .250    -7.323     .298   .265200   .223300   .0619900   -41.500    -7.500  
+9610 3 50359.00 I   .263829  .000079   .220650  .000110  I  .0603299  .0000044  1.6054 0.0030  I   -41.471     .247    -7.677     .298   .263400   .219300   .0603100   -41.000    -7.600  
+9610 4 50360.00 I   .261799  .000074   .216746  .000105  I  .0587553  .0000043  1.5537 0.0032  I   -41.054     .247    -8.029     .298   .261400   .215700   .0587300   -40.700    -7.800  
+9610 5 50361.00 I   .259851  .000093   .213089  .000101  I  .0572015  .0000047  1.5651 0.0032  I   -40.668     .276    -8.307     .298   .259500   .212000   .0571500   -40.300    -8.100  
+9610 6 50362.00 I   .257961  .000070   .209664  .000114  I  .0556113  .0000048  1.6178 0.0035  I   -40.416     .249    -8.470     .298   .257600   .208500   .0555600   -40.000    -8.300  
+9610 7 50363.00 I   .256087  .000067   .206436  .000116  I  .0539591  .0000053  1.6910 0.0038  I   -40.347     .131    -8.503     .298   .255700   .205200   .0539600   -39.900    -8.400  
+9610 8 50364.00 I   .254144  .000068   .203440  .000088  I  .0522227  .0000058  1.7840 0.0048  I   -40.475     .125    -8.431     .298   .253800   .202300   .0522300   -39.900    -8.300  
+9610 9 50365.00 I   .252026  .000068   .200631  .000093  I  .0503866  .0000080  1.8904 0.0050  I   -40.692     .791    -8.256     .298   .251600   .199400   .0503900   -40.100    -8.200  
+961010 50366.00 I   .249757  .000067   .197861  .000089  I  .0484432  .0000081  1.9928 0.0054  I   -40.814     .791    -7.997     .298   .249400   .196800   .0484400   -40.300    -8.000  
+961011 50367.00 I   .247358  .000077   .194971  .000084  I  .0464105  .0000074  2.0668 0.0047  I   -40.798     .791    -7.678     .298   .246900   .193900   .0463800   -40.500    -7.800  
+961012 50368.00 I   .244908  .000068   .191925  .000084  I  .0443206  .0000048  2.1079 0.0046  I   -40.751     .791    -7.368     .298   .244400   .190700   .0443200   -40.500    -7.500  
+961013 50369.00 I   .242479  .000074   .188831  .000085  I  .0422045  .0000056  2.1196 0.0034  I   -40.738     .791    -7.164     .298   .242000   .187700   .0422100   -40.500    -7.300  
+961014 50370.00 I   .239981  .000080   .185792  .000080  I  .0400921  .0000047  2.0990 0.0034  I   -40.669     .180    -7.141     .298   .239500   .184700   .0401100   -40.400    -7.200  
+961015 50371.00 I   .237451  .000084   .182854  .000086  I  .0380178  .0000039  2.0444 0.0030  I   -40.444     .188    -7.256     .298   .236900   .181500   .0380400   -40.200    -7.100  
+961016 50372.00 I   .235135  .000084   .180027  .000084  I  .0360083  .0000037  1.9747 0.0029  I   -40.135     .216    -7.379     .298   .234600   .178800   .0360100   -39.800    -7.100  
+961017 50373.00 I   .232875  .000088   .177326  .000086  I  .0340670  .0000044  1.9090 0.0030  I   -39.988     .193    -7.476     .298   .232300   .176200   .0340600   -39.400    -7.200  
+961018 50374.00 I   .230420  .000093   .174678  .000087  I  .0321772  .0000046  1.8826 0.0038  I   -40.099     .193    -7.516     .298   .230000   .173400   .0321500   -39.100    -7.300  
+961019 50375.00 I   .227845  .000088   .172031  .000109  I  .0302706  .0000062  1.9499 0.0043  I   -40.282     .207    -7.501     .298   .227500   .170800   .0302700   -38.900    -7.400  
+961020 50376.00 I   .225250  .000099   .169455  .000113  I  .0282566  .0000073  2.0797 0.0056  I   -40.347     .191    -7.413     .298   .224900   .168300   .0283100   -38.800    -7.300  
+961021 50377.00 I   .222714  .000104   .166943  .000105  I  .0261129  .0000094  2.2044 0.0070  I   -40.237     .180    -7.237     .298   .222200   .165600   .0261100   -38.700    -7.300  
+961022 50378.00 I   .220149  .000108   .164399  .000106  I  .0238554  .0000120  2.3063 0.0091  I   -40.009     .128    -7.016     .298   .219700   .163000   .0238100   -38.800    -7.200  
+961023 50379.00 I   .217347  .000119   .161682  .000118  I  .0215014  .0000155  2.4050 0.0106  I   -39.770     .155    -6.840     .298   .217100   .160500   .0215000   -39.000    -6.900  
+961024 50380.00 I   .214308  .000116   .158809  .000111  I  .0190585  .0000175  2.4645 0.0113  I   -39.617     .155    -6.724     .298   .213900   .157900   .0190400   -39.100    -6.700  
+961025 50381.00 I   .211321  .000120   .155815  .000110  I  .0166062  .0000164  2.4228 0.0117  I   -39.515     .155    -6.738     .298   .210900   .154600   .0165600   -39.300    -6.500  
+961026 50382.00 I   .208747  .000111   .152758  .000096  I  .0142398  .0000154  2.3005 0.0122  I   -39.402     .154    -6.863     .298   .208300   .151400   .0142000   -39.400    -6.400  
+961027 50383.00 I   .206648  .000096   .149723  .000113  I  .0120193  .0000181  2.1361 0.0091  I   -39.287     .791    -6.935     .298   .206100   .148400   .0119700   -39.500    -6.300  
+961028 50384.00 I   .204727  .000077   .146782  .000151  I  .0099692  .0000096  1.9670 0.0106  I   -39.198     .791    -6.828     .298   .204300   .145500   .0099500   -39.300    -6.300  
+961029 50385.00 I   .202616  .000079   .143945  .000153  I  .0080787  .0000112  1.8177 0.0066  I   -39.110     .791    -6.614     .298   .202100   .142900   .0080900   -39.000    -6.400  
+961030 50386.00 I   .200095  .000059   .141147  .000163  I  .0063248  .0000090  1.6953 0.0074  I   -38.940     .791    -6.509     .298   .199500   .139900   .0063400   -38.600    -6.500  
+961031 50387.00 I   .197246  .000058   .138301  .000162  I  .0046700  .0000096  1.6272 0.0066  I   -38.613     .791    -6.647     .298   .197100   .137000   .0046300   -38.200    -6.600  
+9611 1 50388.00 I   .194360  .000064   .135259  .000165  I  .0030512  .0000096  1.6166 0.0064  I   -38.142     .791    -6.945     .298   .194300   .134100   .0030100   -37.700    -6.700  
+9611 2 50389.00 I   .191481  .000054   .132248  .000148  I  .0014209  .0000086  1.6535 0.0065  I   -37.631     .791    -7.213     .298   .191000   .130900   .0014500   -37.300    -6.800  
+9611 3 50390.00 I   .188491  .000062   .129471  .000149  I -.0002731  .0000087  1.7422 0.0055  I   -37.232     .791    -7.315     .130   .188200   .128200  -.0002500   -37.000    -7.000  
+9611 4 50391.00 I   .185317  .000109   .126988  .000090  I -.0020740  .0000068  1.8625 0.0054  I   -37.058     .791    -7.226     .106   .185100   .125800  -.0021100   -36.800    -7.100  
+9611 5 50392.00 I   .181928  .000106   .124826  .000082  I -.0040039  .0000063  2.0003 0.0043  I   -37.116     .277    -7.019     .298   .181500   .123400  -.0040700   -36.700    -7.000  
+9611 6 50393.00 I   .178262  .000102   .122939  .000131  I -.0060643  .0000053  2.1074 0.0041  I   -37.305     .294    -6.899     .298   .177700   .121700  -.0060700   -36.800    -7.000  
+9611 7 50394.00 I   .174164  .000103   .121176  .000133  I -.0082014  .0000054  2.1626 0.0035  I   -37.469     .273    -6.823     .298   .173600   .120000  -.0081500   -36.900    -7.000  
+9611 8 50395.00 I   .170037  .000105   .119377  .000142  I -.0103803  .0000046  2.1900 0.0036  I   -37.495     .299    -6.638     .298   .169500   .118000  -.0104100   -37.000    -6.900  
+9611 9 50396.00 I   .166197  .000103   .117456  .000151  I -.0125639  .0000048  2.1648 0.0032  I   -37.514     .327    -6.265     .298   .165800   .116000  -.0126300   -37.100    -6.800  
+961110 50397.00 I   .162466  .000078   .115589  .000163  I -.0146986  .0000045  2.1056 0.0031  I   -37.607     .376    -5.870     .298   .162100   .114300  -.0147400   -37.200    -6.700  
+961111 50398.00 I   .158663  .000099   .113955  .000160  I -.0167781  .0000040  2.0555 0.0030  I   -37.670     .328    -5.722     .126   .158200   .112600  -.0168200   -37.100    -6.700  
+961112 50399.00 I   .154633  .000103   .112544  .000165  I -.0188187  .0000039  2.0328 0.0029  I   -37.586     .319    -5.928     .120   .154300   .111200  -.0188400   -37.000    -6.700  
+961113 50400.00 I   .150422  .000133   .111200  .000162  I -.0208427  .0000042  2.0071 0.0032  I   -37.337     .329    -6.343     .120   .150200   .109900  -.0208200   -36.800    -6.600  
+961114 50401.00 I   .146079  .000131   .109862  .000152  I -.0228148  .0000051  1.9270 0.0033  I   -37.116     .294    -6.538     .108   .145700   .108800  -.0228400   -36.600    -6.600  
+961115 50402.00 I   .141568  .000135   .108374  .000150  I -.0246957  .0000052  1.8437 0.0039  I   -37.000     .294    -6.398     .108   .141500   .107300  -.0247200   -36.300    -6.500  
+961116 50403.00 I   .137457  .000152   .106632  .000152  I -.0265370  .0000058  1.8646 0.0043  I   -37.006     .271    -6.100     .298   .137400   .105400  -.0264900   -36.200    -6.400  
+961117 50404.00 I   .134081  .000153   .104805  .000166  I -.0284527  .0000068  1.9688 0.0046  I   -37.069     .219    -5.847     .298   .133700   .103500  -.0284100   -36.200    -6.100  
+961118 50405.00 I   .131054  .000146   .103105  .000195  I -.0304736  .0000072  2.0698 0.0047  I   -37.076     .203    -5.711     .298   .130800   .101900  -.0304600   -36.300    -6.000  
+961119 50406.00 I   .128026  .000130   .101643  .000190  I -.0325821  .0000066  2.1400 0.0047  I   -37.013     .179    -5.659     .298   .127800   .100400  -.0325900   -36.500    -5.800  
+961120 50407.00 I   .125019  .000101   .100437  .000173  I -.0347399  .0000060  2.1689 0.0046  I   -36.968     .343    -5.653     .167   .124600   .099200  -.0347400   -36.700    -5.600  
+961121 50408.00 I   .122162  .000095   .099507  .000171  I -.0369011  .0000065  2.1414 0.0043  I   -37.042     .343    -5.707     .167   .121700   .098300  -.0369000   -36.900    -5.400  
+961122 50409.00 I   .119269  .000090   .098733  .000172  I -.0390000  .0000062  2.0456 0.0047  I   -37.352     .343    -5.838     .167   .118800   .097400  -.0390000   -37.000    -5.300  
+961123 50410.00 I   .116042  .000090   .097932  .000158  I -.0409795  .0000067  1.9112 0.0046  I   -37.890     .343    -6.207     .167   .115600   .096900  -.0409600   -37.000    -5.200  
+961124 50411.00 I   .112575  .000075   .097007  .000143  I -.0428249  .0000067  1.7844 0.0043  I   -38.389    1.034    -6.721     .328   .112100   .096000  -.0427700   -36.800    -5.300  
+961125 50412.00 I   .108895  .000065   .096055  .000124  I -.0445572  .0000055  1.6845 0.0045  I   -38.547    1.319    -7.006     .393   .108500   .094800  -.0444900   -36.400    -5.300  
+961126 50413.00 I   .105076  .000056   .095273  .000104  I -.0462060  .0000059  1.6209 0.0035  I   -38.213    1.575    -6.785     .452   .104700   .094000  -.0461600   -35.900    -5.300  
+961127 50414.00 I   .101293  .000054   .094701  .000094  I -.0478085  .0000044  1.5857 0.0038  I   -37.349    1.575    -6.024     .452   .100900   .093400  -.0478000   -35.400    -5.400  
+961128 50415.00 I   .097465  .000062   .094238  .000094  I -.0493838  .0000049  1.5698 0.0030  I   -36.506    1.575    -5.425     .452   .097000   .093200  -.0493900   -34.800    -5.500  
+961129 50416.00 I   .093540  .000069   .093769  .000087  I -.0509576  .0000042  1.5826 0.0033  I   -35.843    1.575    -5.250     .452   .093000   .092800  -.0509700   -34.300    -5.700  
+961130 50417.00 I   .089593  .000068   .093199  .000087  I -.0525574  .0000043  1.6207 0.0038  I   -35.312    1.423    -5.330     .411   .089100   .092000  -.0525600   -34.000    -5.800  
+9612 1 50418.00 I   .085827  .000073   .092517  .000111  I -.0542025  .0000064  1.6692 0.0041  I   -35.002     .404    -5.499     .298   .085800   .091500  -.0541800   -33.700    -5.900  
+9612 2 50419.00 I   .082281  .000112   .091772  .000131  I -.0558923  .0000069  1.7071 0.0053  I   -34.933     .499    -5.663     .133   .082300   .090600  -.0558700   -33.700    -6.000  
+9612 3 50420.00 I   .078743  .000120   .091073  .000145  I -.0576114  .0000085  1.7289 0.0053  I   -34.965     .499    -5.790     .133   .078300   .089700  -.0576100   -33.800    -6.000  
+9612 4 50421.00 I   .074984  .000110   .090512  .000155  I -.0593535  .0000080  1.7607 0.0058  I   -34.992     .459    -5.849     .123   .074600   .089400  -.0593300   -34.000    -6.000  
+9612 5 50422.00 I   .070877  .000107   .089989  .000148  I -.0611357  .0000079  1.8011 0.0054  I   -35.211     .459    -5.693     .123   .070700   .089000  -.0611100   -34.400    -6.000  
+9612 6 50423.00 I   .066593  .000114   .089367  .000150  I -.0629445  .0000073  1.8077 0.0063  I   -35.635     .459    -5.341     .123   .066600   .088100  -.0629300   -34.700    -5.900  
+9612 7 50424.00 I   .062411  .000125   .088604  .000183  I -.0647376  .0000097  1.7738 0.0053  I   -35.977     .484    -4.941     .143   .062400   .087300  -.0647300   -35.100    -5.800  
+9612 8 50425.00 I   .058416  .000100   .087729  .000146  I -.0664852  .0000077  1.7194 0.0056  I   -36.008     .281    -4.632     .298   .058100   .086500  -.0664800   -35.300    -5.700  
+9612 9 50426.00 I   .054504  .000107   .086825  .000109  I -.0681764  .0000056  1.6651 0.0046  I   -35.762     .230    -4.574     .298   .054200   .085500  -.0681700   -35.300    -5.700  
+961210 50427.00 I   .050574  .000087   .085999  .000107  I -.0698227  .0000052  1.6326 0.0041  I   -35.447     .109    -4.849     .298   .050200   .084500  -.0697800   -35.200    -5.600  
+961211 50428.00 I   .046689  .000087   .085384  .000136  I -.0714549  .0000061  1.6400 0.0042  I   -35.251     .109    -5.289     .298   .046200   .084100  -.0714300   -35.000    -5.500  
+961212 50429.00 I   .043010  .000072   .085082  .000135  I -.0731165  .0000067  1.6888 0.0046  I   -35.188     .109    -5.548     .298   .042500   .084000  -.0731400   -34.700    -5.500  
+961213 50430.00 I   .039688  .000075   .085081  .000133  I -.0748463  .0000069  1.7791 0.0047  I   -35.216     .109    -5.447     .298   .039400   .083000  -.0748400   -34.500    -5.400  
+961214 50431.00 I   .036684  .000072   .085362  .000110  I -.0766865  .0000065  1.9048 0.0081  I   -35.316     .791    -5.104     .298   .036500   .083600  -.0766400   -34.300    -5.300  
+961215 50432.00 I   .033789  .000075   .085870  .000136  I -.0786548  .0000147  2.0272 0.0056  I   -35.447     .791    -4.768     .298   .033500   .084600  -.0786500   -34.300    -5.100  
+961216 50433.00 I   .030822  .000083   .086510  .000124  I -.0807293  .0000090  2.1149 0.0086  I   -35.548     .791    -4.590     .298   .030700   .085300  -.0807400   -34.400    -5.000  
+961217 50434.00 I   .027731  .000068   .087197  .000091  I -.0828705  .0000089  2.1602 0.0064  I   -35.597     .791    -4.559     .298   .027600   .085900  -.0828800   -34.700    -4.900  
+961218 50435.00 I   .024552  .000067   .087895  .000080  I -.0850383  .0000091  2.1711 0.0064  I   -35.631     .791    -4.607     .298   .024300   .086600  -.0850300   -35.100    -4.800  
+961219 50436.00 I   .021384  .000063   .088618  .000083  I -.0871961  .0000092  2.1322 0.0066  I   -35.708     .791    -4.704     .298   .020900   .087200  -.0871800   -35.500    -4.700  
+961220 50437.00 I   .018204  .000063   .089314  .000083  I -.0892816  .0000096  2.0299 0.0066  I   -35.843     .791    -4.837     .298   .017800   .088000  -.0892900   -35.900    -4.700  
+961221 50438.00 I   .015098  .000069   .089938  .000077  I -.0912487  .0000095  1.9060 0.0086  I   -35.975     .791    -4.973     .298   .014900   .088500  -.0912500   -36.200    -4.600  
+961222 50439.00 I   .012264  .000074   .090507  .000088  I -.0931030  .0000143  1.8104 0.0083  I   -35.988     .791    -5.054     .298   .012000   .089100  -.0930700   -36.300    -4.700  
+961223 50440.00 I   .009778  .000072   .091040  .000090  I -.0948805  .0000137  1.7477 0.0093  I   -35.829     .791    -5.042     .298   .009400   .089700  -.0948400   -36.100    -4.700  
+961224 50441.00 I   .007387  .000072   .091534  .000117  I -.0966031  .0000118  1.6989 0.0090  I   -35.594     .791    -4.967     .298   .007100   .090300  -.0965900   -35.800    -4.800  
+961225 50442.00 I   .004683  .000088   .091983  .000124  I -.0982859  .0000117  1.6728 0.0076  I   -35.436     .791    -4.904     .298   .004500   .090800  -.0982600   -35.400    -4.800  
+961226 50443.00 I   .001482  .000082   .092365  .000119  I -.0999606  .0000096  1.6825 0.0074  I   -35.367     .791    -4.907     .298   .001200   .091300  -.0999300   -34.900    -4.900  
+961227 50444.00 I  -.002138  .000090   .092697  .000124  I -.1016613  .0000089  1.7234 0.0082  I   -35.263     .791    -4.967     .298  -.002300   .091500  -.1016500   -34.400    -4.900  
+961228 50445.00 I  -.006054  .000136   .093050  .000178  I -.1034141  .0000134  1.7844 0.0073  I   -35.073     .791    -5.038     .298  -.006000   .091700  -.1034200   -34.100    -4.800  
+961229 50446.00 I  -.010233  .000136   .093503  .000167  I -.1052325  .0000116  1.8527 0.0090  I   -34.891     .791    -5.087     .298  -.010500   .092100  -.1052300   -33.900    -4.900  
+961230 50447.00 I  -.014631  .000130   .094090  .000157  I -.1071181  .0000119  1.9167 0.0094  I   -34.767     .791    -5.091     .298  -.014800   .092900  -.1071000   -33.900    -5.000  
+961231 50448.00 I  -.019065  .000142   .094720  .000174  I -.1090616  .0000148  1.9677 0.0100  I   -34.607     .791    -5.044     .298  -.019400   .093700  -.1090300   -34.000    -5.000  
+97 1 1 50449.00 I  -.023125  .000146   .095292  .000182  I -.1110467  .0000160  1.9984 0.0113  I   -34.381     .791    -4.984     .298  -.023120   .095270  -.1110260   -34.400    -5.000  
+97 1 2 50450.00 I  -.026846  .000142   .095921  .000187  I -.1130512  .0000172  2.0075 0.0115  I   -34.279     .791    -4.977     .298  -.026650   .095730  -.1129910   -34.600    -4.900  
+97 1 3 50451.00 I  -.030356  .000162   .096804  .000162  I -.1150536  .0000165  1.9923 0.0133  I   -34.450     .791    -5.015     .298  -.030320   .096580  -.1150660   -34.900    -4.900  
+97 1 4 50452.00 I  -.033659  .000118   .098009  .000196  I -.1170274  .0000202  1.9518 0.0125  I   -34.718     .791    -4.984     .298  -.033580   .097740  -.1170900   -35.100    -5.000  
+97 1 5 50453.00 I  -.036894  .000155   .099459  .000190  I -.1189536  .0000187  1.9006 0.0112  I   -34.770     .791    -4.808     .298  -.036610   .099330  -.1189530   -35.100    -5.000  
+97 1 6 50454.00 I  -.040341  .000118   .100969  .000158  I -.1208302  .0000095  1.8544 0.0101  I   -34.580     .149    -4.610     .298  -.040400   .100800  -.1208340   -35.000    -5.000  
+97 1 7 50455.00 I  -.043963  .000104   .102347  .000140  I -.1226704  .0000074  1.8324 0.0061  I   -34.425     .133    -4.619     .298  -.044180   .102110  -.1226990   -34.800    -5.000  
+97 1 8 50456.00 I  -.047384  .000102   .103560  .000133  I -.1245101  .0000075  1.8557 0.0054  I   -34.505     .133    -4.870     .298  -.047410   .103440  -.1245240   -34.500    -4.900  
+97 1 9 50457.00 I  -.050363  .000099   .104719  .000127  I -.1263955  .0000080  1.9202 0.0055  I   -34.731     .133    -5.121     .298  -.050390   .104490  -.1264190   -34.300    -4.900  
+97 110 50458.00 I  -.053191  .000093   .105897  .000096  I -.1283614  .0000081  2.0173 0.0060  I   -34.874     .133    -5.094     .298  -.053080   .105700  -.1283790   -34.100    -4.700  
+97 111 50459.00 I  -.056069  .000096   .107078  .000093  I -.1304323  .0000090  2.1208 0.0055  I   -34.878     .133    -4.806     .298  -.055890   .106970  -.1304310   -33.900    -4.600  
+97 112 50460.00 I  -.058933  .000100   .108271  .000094  I -.1325930  .0000073  2.1942 0.0070  I   -34.848     .114    -4.504     .298  -.058900   .108160  -.1326170   -34.000    -4.600  
+97 113 50461.00 I  -.061619  .000116   .109534  .000101  I -.1348093  .0000107  2.2333 0.0061  I   -34.887     .791    -4.366     .298  -.061840   .109360  -.1347970   -34.200    -4.400  
+97 114 50462.00 I  -.063963  .000119   .110918  .000107  I -.1370449  .0000098  2.2282 0.0074  I   -35.030     .791    -4.371     .298  -.063990   .110710  -.1370150   -34.700    -4.500  
+97 115 50463.00 I  -.066046  .000156   .112506  .000139  I -.1392469  .0000103  2.1668 0.0071  I   -35.228     .791    -4.443     .298  -.065980   .112380  -.1392600   -35.100    -4.500  
+97 116 50464.00 I  -.068034  .000125   .114400  .000139  I -.1413615  .0000104  2.0543 0.0070  I   -35.360     .791    -4.572     .298  -.068080   .114440  -.1413620   -35.500    -4.500  
+97 117 50465.00 I  -.069960  .000132   .116470  .000138  I -.1433426  .0000094  1.9031 0.0071  I   -35.345     .791    -4.767     .298  -.069680   .115950  -.1433430   -35.900    -4.600  
+97 118 50466.00 I  -.071941  .000130   .118545  .000136  I -.1451623  .0000096  1.7359 0.0067  I   -35.228     .791    -4.960     .298  -.071350   .117780  -.1451910   -36.000    -4.600  
+97 119 50467.00 I  -.074152  .000130   .120610  .000244  I -.1468202  .0000095  1.5863 0.0059  I   -35.108     .791    -5.052     .298  -.074030   .120500  -.1468210   -36.000    -4.800  
+97 120 50468.00 I  -.076773  .000166   .122686  .000205  I -.1483487  .0000068  1.4781 0.0055  I   -35.019     .223    -5.031     .298  -.076670   .122510  -.1483560   -35.700    -4.900  
+97 121 50469.00 I  -.079660  .000171   .124753  .000176  I -.1497922  .0000055  1.4171 0.0043  I   -34.944     .216    -4.987     .298  -.079820   .124740  -.1498140   -35.400    -4.900  
+97 122 50470.00 I  -.082335  .000166   .126769  .000179  I -.1512048  .0000052  1.4217 0.0039  I   -34.909     .216    -5.005     .298  -.082480   .126830  -.1512110   -34.800    -5.000  
+97 123 50471.00 I  -.084929  .000156   .128732  .000181  I -.1526485  .0000054  1.4650 0.0036  I   -34.952     .216    -5.080     .298  -.084950   .128440  -.1526570   -34.300    -5.000  
+97 124 50472.00 I  -.087687  .000162   .130552  .000187  I -.1541269  .0000051  1.4847 0.0043  I   -34.969     .216    -5.153     .298  -.087820   .130140  -.1541470   -33.800    -5.100  
+97 125 50473.00 I  -.090542  .000161   .132279  .000096  I -.1556175  .0000066  1.5031 0.0043  I   -34.899     .216    -5.216     .298  -.090550   .132210  -.1556260   -33.400    -5.100  
+97 126 50474.00 I  -.093642  .000141   .133992  .000107  I -.1571430  .0000070  1.5513 0.0057  I   -34.808     .209    -5.307     .298  -.093280   .134020  -.1571430   -33.300    -5.200  
+97 127 50475.00 I  -.096798  .000113   .135756  .000122  I -.1587242  .0000093  1.6119 0.0051  I   -34.755     .189    -5.425     .298  -.096530   .135560  -.1586830   -33.400    -5.300  
+97 128 50476.00 I  -.099828  .000118   .137597  .000122  I -.1603627  .0000073  1.6602 0.0062  I   -34.704     .189    -5.513     .298  -.099770   .137440  -.1603380   -33.700    -5.400  
+97 129 50477.00 I  -.102756  .000123   .139487  .000119  I -.1620217  .0000082  1.6399 0.0056  I   -34.655     .189    -5.554     .298  -.102820   .139450  -.1620400   -34.100    -5.500  
+97 130 50478.00 I  -.105545  .000111   .141428  .000117  I -.1636253  .0000085  1.5680 0.0055  I   -34.763     .189    -5.622     .298  -.105760   .141240  -.1636150   -34.700    -5.600  
+97 131 50479.00 I  -.108317  .000105   .143490  .000121  I -.1651635  .0000072  1.5136 0.0054  I   -35.132     .189    -5.764     .298  -.108290   .143260  -.1651560   -35.300    -5.600  
+97 2 1 50480.00 I  -.111349  .000102   .145610  .000116  I -.1666459  .0000067  1.4394 0.0048  I   -35.556     .189    -5.875     .298  -.111150   .145580  -.1666790   -35.800    -5.700  
+97 2 2 50481.00 I  -.114391  .000113   .147746  .000155  I -.1680324  .0000065  1.3356 0.0046  I   -35.706     .791    -5.791     .298  -.114590   .147850  -.1680380   -36.100    -5.700  
+97 2 3 50482.00 I  -.117215  .000107   .149884  .000140  I -.1693291  .0000062  1.2680 0.0046  I   -35.581     .791    -5.537     .298  -.117340   .149870  -.1693300   -36.200    -5.700  
+97 2 4 50483.00 I  -.119869  .000110   .152077  .000176  I -.1705907  .0000065  1.2675 0.0043  I   -35.525     .791    -5.360     .298  -.119820   .151850  -.1705910   -36.200    -5.600  
+97 2 5 50484.00 I  -.122471  .000109   .154427  .000179  I -.1718955  .0000061  1.3612 0.0049  I   -35.763     .791    -5.423     .298  -.122580   .154440  -.1718900   -36.000    -5.500  
+97 2 6 50485.00 I  -.124786  .000109   .156838  .000172  I -.1733379  .0000073  1.5294 0.0048  I   -36.095     .791    -5.534     .298  -.124840   .156950  -.1733440   -35.700    -5.400  
+97 2 7 50486.00 I  -.126743  .000113   .159259  .000180  I -.1749635  .0000075  1.7251 0.0072  I   -36.191     .791    -5.494     .298  -.126880   .159370  -.1749570   -35.400    -5.200  
+97 2 8 50487.00 I  -.128511  .000105   .161777  .000137  I -.1767825  .0000125  1.9039 0.0060  I   -35.962     .791    -5.348     .298  -.128590   .161690  -.1767640   -35.100    -5.200  
+97 2 9 50488.00 I  -.130350  .000069   .164433  .000142  I -.1787477  .0000093  2.0120 0.0074  I   -35.581     .138    -5.255     .298  -.130260   .164120  -.1787810   -35.000    -5.100  
+97 210 50489.00 I  -.132250  .000067   .167200  .000123  I -.1807865  .0000081  2.0603 0.0061  I   -35.311     .109    -5.312     .298  -.132220   .167330  -.1807960   -35.000    -5.100  
+97 211 50490.00 I  -.134165  .000084   .170000  .000171  I -.1828595  .0000078  2.0824 0.0054  I   -35.302     .148    -5.428     .298  -.134060   .170390  -.1828460   -35.200    -5.200  
+97 212 50491.00 I  -.136191  .000085   .172752  .000174  I -.1849226  .0000070  2.0184 0.0057  I   -35.471     .148    -5.471     .298  -.136190   .172770  -.1849320   -35.600    -5.300  
+97 213 50492.00 I  -.138295  .000075   .175444  .000183  I -.1868678  .0000084  1.8689 0.0056  I   -35.584     .148    -5.462     .298  -.138400   .175240  -.1868910   -35.900    -5.400  
+97 214 50493.00 I  -.140379  .000071   .178160  .000181  I -.1886653  .0000087  1.7342 0.0060  I   -35.487     .148    -5.565     .298  -.140490   .178200  -.1886420   -36.100    -5.600  
+97 215 50494.00 I  -.142530  .000067   .180941  .000181  I -.1903477  .0000085  1.6342 0.0083  I   -35.305     .139    -5.819     .298  -.142460   .181110  -.1903170   -36.300    -5.700  
+97 216 50495.00 I  -.144884  .000101   .183697  .000184  I -.1919402  .0000141  1.5538 0.0071  I   -35.287     .226    -6.058     .298  -.144880   .183840  -.1919650   -36.400    -5.800  
+97 217 50496.00 I  -.147478  .000102   .186326  .000174  I -.1934698  .0000113  1.5171 0.0085  I   -35.505     .155    -6.179     .298  -.147590   .186540  -.1934630   -36.300    -6.000  
+97 218 50497.00 I  -.150122  .000101   .188791  .000102  I -.1949925  .0000096  1.5349 0.0067  I   -35.739     .155    -6.232     .298  -.150110   .188740  -.1949620   -36.000    -6.100  
+97 219 50498.00 I  -.152594  .000105   .191120  .000090  I -.1965482  .0000073  1.5785 0.0060  I   -35.750     .123    -6.277     .298  -.152560   .191020  -.1965500   -35.600    -6.200  
+97 220 50499.00 I  -.154965  .000116   .193390  .000078  I -.1981573  .0000072  1.6453 0.0049  I   -35.525     .123    -6.279     .298  -.155120   .193450  -.1981660   -35.200    -6.200  
+97 221 50500.00 I  -.157097  .000134   .195697  .000078  I -.1998452  .0000065  1.7311 0.0048  I   -35.228     .123    -6.218     .298  -.157190   .195650  -.1998380   -34.800    -6.300  
+97 222 50501.00 I  -.158915  .000124   .198140  .000088  I -.2016223  .0000062  1.8254 0.0056  I   -34.977     .123    -6.173     .298  -.158970   .197900  -.2016180   -34.500    -6.400  
+97 223 50502.00 I  -.160453  .000083   .200800  .000118  I -.2034968  .0000090  1.9221 0.0054  I   -34.788     .791    -6.245     .298  -.160360   .200690  -.2034930   -34.300    -6.400  
+97 224 50503.00 I  -.161818  .000148   .203733  .000118  I -.2054597  .0000089  1.9982 0.0067  I   -34.681     .791    -6.450     .298  -.161690   .203580  -.2054440   -34.300    -6.500  
+97 225 50504.00 I  -.163299  .000153   .206941  .000124  I -.2074795  .0000100  2.0331 0.0067  I   -34.661     .791    -6.689     .298  -.163220   .206860  -.2074620   -34.400    -6.700  
+97 226 50505.00 I  -.165215  .000153   .210308  .000136  I -.2095110  .0000101  2.0232 0.0073  I   -34.711     .791    -6.868     .298  -.165150   .210200  -.2095060   -34.600    -6.800  
+97 227 50506.00 I  -.167652  .000151   .213624  .000136  I -.2115238  .0000105  2.0070 0.0071  I   -34.862     .791    -7.007     .298  -.167740   .213480  -.2115180   -34.900    -6.900  
+97 228 50507.00 I  -.170138  .000162   .216857  .000122  I -.2135309  .0000101  2.0085 0.0073  I   -35.126     .791    -7.176     .298  -.170330   .216900  -.2135090   -35.000    -7.000  
+97 3 1 50508.00 I  -.172256  .000163   .220043  .000110  I -.2155422  .0000102  2.0143 0.0075  I   -35.357     .791    -7.340     .298  -.172380   .219970  -.2155140   -35.200    -7.200  
+97 3 2 50509.00 I  -.173879  .000105   .223231  .000067  I -.2175595  .0000110  2.0202 0.0064  I   -35.337     .791    -7.364     .298  -.173970   .223050  -.2175420   -35.100    -7.300  
+97 3 3 50510.00 I  -.174995  .000091   .226453  .000089  I -.2195849  .0000076  2.0331 0.0065  I   -35.080     .791    -7.214     .298  -.175070   .226410  -.2195720   -35.100    -7.200  
+97 3 4 50511.00 I  -.175740  .000099   .229709  .000083  I -.2216355  .0000068  2.0753 0.0048  I   -34.900     .791    -7.053     .298  -.175650   .229730  -.2216320   -34.800    -7.200  
+97 3 5 50512.00 I  -.176415  .000096   .232987  .000080  I -.2237518  .0000059  2.1662 0.0055  I   -35.052     .791    -7.057     .298  -.176420   .232950  -.2237540   -34.600    -7.100  
+97 3 6 50513.00 I  -.177300  .000079   .236295  .000083  I -.2259897  .0000086  2.3223 0.0051  I   -35.424     .791    -7.189     .298  -.177190   .236190  -.2259670   -34.400    -7.000  
+97 3 7 50514.00 I  -.178558  .000073   .239568  .000090  I -.2284127  .0000084  2.5272 0.0063  I   -35.676     .791    -7.254     .298  -.178250   .239750  -.2283680   -34.300    -6.800  
+97 3 8 50515.00 I  -.180253  .000078   .242757  .000087  I -.2310411  .0000091  2.7230 0.0064  I   -35.608     .791    -7.179     .298  -.180110   .242900  -.2310240   -34.200    -6.700  
+97 3 9 50516.00 I  -.182213  .000109   .245858  .000072  I -.2338346  .0000097  2.8466 0.0058  I   -35.322     .791    -7.099     .298  -.182130   .245820  -.2338510   -34.300    -6.700  
+97 310 50517.00 I  -.184152  .000128   .248905  .000135  I -.2367006  .0000071  2.8693 0.0059  I   -35.098     .103    -7.134     .298  -.184210   .248920  -.2366890   -34.600    -6.800  
+97 311 50518.00 I  -.185660  .000126   .251986  .000127  I -.2395438  .0000068  2.8040 0.0043  I   -35.175     .103    -7.215     .298  -.185880   .251900  -.2395060   -34.800    -6.900  
+97 312 50519.00 I  -.186433  .000131   .255167  .000121  I -.2422867  .0000047  2.6730 0.0045  I   -35.526     .103    -7.215     .298  -.186520   .255110  -.2422750   -35.100    -7.100  
+97 313 50520.00 I  -.186654  .000150   .258479  .000124  I -.2448840  .0000058  2.5247 0.0034  I   -35.821     .103    -7.181     .298  -.186640   .258650  -.2449000   -35.400    -7.300  
+97 314 50521.00 I  -.186547  .000147   .262016  .000128  I -.2473473  .0000050  2.4100 0.0039  I   -35.740     .103    -7.281     .298  -.186430   .261920  -.2473450   -35.700    -7.600  
+97 315 50522.00 I  -.186532  .000144   .265890  .000134  I -.2497212  .0000051  2.3468 0.0061  I   -35.356     .103    -7.561     .298  -.186230   .265770  -.2496900   -35.800    -7.800  
+97 316 50523.00 I  -.186927  .000126   .270001  .000109  I -.2520565  .0000111  2.3304 0.0043  I   -35.063     .791    -7.881     .298  -.186860   .270210  -.2520300   -35.800    -8.000  
+97 317 50524.00 I  -.187669  .000129   .274026  .000103  I -.2543915  .0000070  2.3424 0.0064  I   -35.074     .791    -8.085     .298  -.187830   .274290  -.2543900   -35.600    -8.100  
+97 318 50525.00 I  -.188374  .000175   .277782  .000095  I -.2567473  .0000064  2.3724 0.0048  I   -35.173     .791    -8.150     .298  -.188480   .277770  -.2567630   -35.400    -8.100  
+97 319 50526.00 I  -.188751  .000173   .281365  .000092  I -.2591447  .0000066  2.4278 0.0046  I   -35.067     .791    -8.134     .298  -.188700   .281390  -.2591520   -35.000    -8.000  
+97 320 50527.00 I  -.188948  .000172   .284964  .000075  I -.2615966  .0000065  2.4644 0.0049  I   -34.768     .791    -8.117     .298  -.188980   .285030  -.2615730   -34.600    -7.800  
+97 321 50528.00 I  -.189277  .000165   .288636  .000056  I -.2640664  .0000073  2.4797 0.0047  I   -34.492     .791    -8.026     .298  -.189010   .288660  -.2640260   -34.200    -7.800  
+97 322 50529.00 I  -.189584  .000178   .292340  .000082  I -.2665641  .0000068  2.5191 0.0051  I   -34.366     .791    -7.875     .298  -.189180   .292380  -.2665350   -34.000    -7.700  
+97 323 50530.00 I  -.189715  .000191   .296049  .000073  I -.2691041  .0000070  2.5568 0.0051  I   -34.331     .101    -7.790     .298  -.189770   .296020  -.2691000   -33.800    -7.700  
+97 324 50531.00 I  -.189650  .000163   .299799  .000107  I -.2716708  .0000076  2.5736 0.0050  I   -34.332     .103    -7.831     .298  -.189710   .299790  -.2716640   -33.800    -7.700  
+97 325 50532.00 I  -.189501  .000164   .303650  .000113  I -.2742439  .0000071  2.5680 0.0053  I   -34.402     .103    -7.949     .298  -.189510   .303670  -.2742150   -34.000    -7.800  
+97 326 50533.00 I  -.189576  .000159   .307593  .000127  I -.2767977  .0000073  2.5349 0.0047  I   -34.559     .103    -8.070     .298  -.189610   .307610  -.2767820   -34.200    -8.000  
+97 327 50534.00 I  -.190011  .000151   .311542  .000132  I -.2793072  .0000061  2.4822 0.0048  I   -34.749     .103    -8.162     .298  -.190060   .311790  -.2793000   -34.400    -8.200  
+97 328 50535.00 I  -.190465  .000149   .315430  .000127  I -.2817635  .0000062  2.4336 0.0041  I   -34.921     .124    -8.255     .298  -.190390   .315590  -.2817270   -34.500    -8.300  
+97 329 50536.00 I  -.190817  .000110   .319244  .000137  I -.2841799  .0000055  2.4013 0.0044  I   -35.031     .124    -8.350     .298  -.190700   .319190  -.2841550   -34.700    -8.500  
+97 330 50537.00 I  -.191111  .000083   .322923  .000142  I -.2865724  .0000063  2.3877 0.0038  I   -34.999     .791    -8.398     .298  -.191090   .323120  -.2865830   -34.700    -8.600  
+97 331 50538.00 I  -.191277  .000104   .326401  .000163  I -.2889662  .0000053  2.4069 0.0041  I   -34.783     .791    -8.379     .298  -.191330   .326200  -.2889710   -34.600    -8.600  
+97 4 1 50539.00 I  -.191095  .000120   .329761  .000156  I -.2913990  .0000053  2.4646 0.0037  I   -34.468     .791    -8.361     .298  -.191030   .329370  -.2913530   -34.400    -8.500  
+97 4 2 50540.00 I  -.190396  .000123   .333126  .000160  I -.2939066  .0000052  2.5558 0.0038  I   -34.207     .791    -8.419     .298  -.190470   .333060  -.2938890   -34.200    -8.400  
+97 4 3 50541.00 I  -.189369  .000135   .336798  .000177  I -.2965213  .0000054  2.6789 0.0035  I   -34.058     .791    -8.522     .298  -.189510   .336850  -.2965170   -34.100    -8.300  
+97 4 4 50542.00 I  -.188326  .000135   .340644  .000164  I -.2992707  .0000046  2.8209 0.0037  I   -33.981     .791    -8.529     .298  -.188320   .340750  -.2992520   -34.000    -8.100  
+97 4 5 50543.00 I  -.187324  .000171   .344421  .000165  I -.3021543  .0000051  2.9366 0.0037  I   -33.916     .791    -8.416     .298  -.186950   .344770  -.3021410   -34.000    -8.100  
+97 4 6 50544.00 I  -.186426  .000170   .348044  .000128  I -.3051186  .0000058  2.9763 0.0034  I   -33.866     .791    -8.336     .298  -.186080   .348490  -.3050560   -34.200    -8.200  
+97 4 7 50545.00 I  -.185573  .000167   .351535  .000123  I -.3080759  .0000045  2.9231 0.0037  I   -33.907     .120    -8.419     .110  -.185710   .351620  -.3080380   -34.300    -8.200  
+97 4 8 50546.00 I  -.184596  .000184   .354973  .000117  I -.3109377  .0000046  2.7887 0.0034  I   -34.134     .120    -8.601     .110  -.184670   .355100  -.3109070   -34.600    -8.400  
+97 4 9 50547.00 I  -.183491  .000179   .358473  .000107  I -.3136437  .0000051  2.6256 0.0036  I   -34.522     .120    -8.700     .110  -.183910   .358510  -.3136330   -34.800    -8.500  
+97 410 50548.00 I  -.182447  .000185   .362076  .000103  I -.3161928  .0000056  2.4741 0.0038  I   -34.817     .120    -8.675     .110  -.182710   .362170  -.3162020   -35.000    -8.700  
+97 411 50549.00 I  -.181423  .000179   .365823  .000104  I -.3185995  .0000056  2.3455 0.0042  I   -34.799     .120    -8.670     .110  -.181650   .365730  -.3186020   -35.200    -8.900  
+97 412 50550.00 I  -.180458  .000153   .369697  .000100  I -.3208959  .0000062  2.2531 0.0080  I   -34.553     .109    -8.825     .135  -.180750   .369460  -.3209070   -35.200    -9.100  
+97 413 50551.00 I  -.179741  .000104   .373586  .000106  I -.3231184  .0000150  2.1989 0.0054  I   -34.400     .791    -9.111     .298  -.179540   .373610  -.3231080   -35.200    -9.200  
+97 414 50552.00 I  -.179301  .000071   .377335  .000092  I -.3253059  .0000088  2.1815 0.0083  I   -34.496     .130    -9.379     .298  -.179130   .377460  -.3253080   -35.100    -9.300  
+97 415 50553.00 I  -.178935  .000074   .380843  .000086  I -.3274896  .0000069  2.1887 0.0055  I   -34.605     .139    -9.516     .298  -.179170   .381090  -.3275180   -34.900    -9.300  
+97 416 50554.00 I  -.178449  .000052   .384082  .000085  I -.3296974  .0000065  2.2383 0.0048  I   -34.418     .139    -9.494     .298  -.178510   .384090  -.3297100   -34.700    -9.300  
+97 417 50555.00 I  -.177770  .000058   .387200  .000086  I -.3319711  .0000067  2.3027 0.0045  I   -33.981     .139    -9.320     .298  -.177840   .387160  -.3319570   -34.500    -9.100  
+97 418 50556.00 I  -.176894  .000064   .390339  .000084  I -.3342906  .0000063  2.3307 0.0043  I   -33.660     .139    -9.081     .298  -.177080   .390390  -.3342830   -34.400    -9.000  
+97 419 50557.00 I  -.175898  .000106   .393568  .000075  I -.3366294  .0000055  2.3495 0.0042  I   -33.642     .139    -8.863     .298  -.175800   .393490  -.3366160   -34.100    -8.900  
+97 420 50558.00 I  -.174918  .000117   .396920  .000067  I -.3389891  .0000056  2.3670 0.0043  I   -33.799     .118    -8.727     .298  -.174820   .396880  -.3389690   -34.000    -8.800  
+97 421 50559.00 I  -.174074  .000129   .400408  .000141  I -.3413517  .0000066  2.3495 0.0044  I   -33.964     .791    -8.693     .298  -.173790   .400430  -.3413440   -34.000    -8.700  
+97 422 50560.00 I  -.173393  .000135   .404014  .000143  I -.3436733  .0000069  2.2876 0.0044  I   -34.105     .791    -8.741     .298  -.173130   .404030  -.3436830   -33.800    -8.700  
+97 423 50561.00 I  -.172759  .000132   .407606  .000146  I -.3459204  .0000059  2.2062 0.0046  I   -34.233     .791    -8.856     .298  -.172750   .407590  -.3459270   -33.800    -8.700  
+97 424 50562.00 I  -.171839  .000139   .410966  .000142  I -.3480859  .0000061  2.1254 0.0060  I   -34.323     .791    -9.017     .298  -.172230   .411360  -.3480680   -33.800    -8.900  
+97 425 50563.00 I  -.170499  .000140   .414152  .000134  I -.3501739  .0000105  2.0526 0.0064  I   -34.355     .791    -9.186     .298  -.170760   .414200  -.3501490   -33.800    -9.000  
+97 426 50564.00 I  -.168831  .000107   .417314  .000137  I -.3521945  .0000113  1.9901 0.0097  I   -34.397     .791    -9.300     .298  -.168870   .417240  -.3521830   -33.800    -9.100  
+97 427 50565.00 I  -.167106  .000096   .420468  .000094  I -.3541611  .0000163  1.9485 0.0081  I   -34.519     .791    -9.323     .298  -.167060   .420570  -.3541560   -33.800    -9.200  
+97 428 50566.00 I  -.165634  .000081   .423541  .000096  I -.3561064  .0000117  1.9516 0.0098  I   -34.669     .172    -9.280     .298  -.165470   .423620  -.3560980   -33.900    -9.300  
+97 429 50567.00 I  -.164540  .000088   .426430  .000106  I -.3580823  .0000110  2.0086 0.0081  I   -34.708     .214    -9.228     .298  -.164390   .426550  -.3580740   -34.000    -9.300  
+97 430 50568.00 I  -.163574  .000089   .429110  .000123  I -.3601397  .0000112  2.1139 0.0075  I   -34.556     .214    -9.186     .298  -.163620   .429130  -.3601370   -34.100    -9.200  
+97 5 1 50569.00 I  -.162447  .000089   .431668  .000129  I -.3623133  .0000101  2.2290 0.0077  I   -34.273     .214    -9.110     .298  -.162550   .431430  -.3623130   -34.200    -9.100  
+97 5 2 50570.00 I  -.160959  .000087   .434208  .000131  I -.3645947  .0000106  2.3352 0.0072  I   -33.968     .214    -8.955     .298  -.161010   .434320  -.3645950   -34.400    -9.000  
+97 5 3 50571.00 I  -.158952  .000103   .436863  .000138  I -.3669830  .0000102  2.4391 0.0082  I   -33.815     .204    -8.747     .298  -.159020   .437110  -.3669560   -34.600    -8.900  
+97 5 4 50572.00 I  -.156442  .000109   .439744  .000143  I -.3694605  .0000124  2.5056 0.0085  I   -33.919     .219    -8.616     .298  -.156530   .439490  -.3694140   -34.600    -8.900  
+97 5 5 50573.00 I  -.153614  .000126   .442881  .000121  I -.3719702  .0000136  2.5002 0.0095  I   -34.226     .138    -8.691     .298  -.153640   .442850  -.3719270   -34.700    -8.900  
+97 5 6 50574.00 I  -.150798  .000129   .446180  .000107  I -.3744440  .0000143  2.4443 0.0095  I   -34.595     .138    -8.937     .298  -.150610   .446380  -.3744430   -34.600    -9.000  
+97 5 7 50575.00 I  -.148127  .000122   .449423  .000102  I -.3768402  .0000132  2.3327 0.0096  I   -34.882     .138    -9.159     .298  -.148120   .449590  -.3768500   -34.600    -9.200  
+97 5 8 50576.00 I  -.145405  .000122   .452426  .000094  I -.3790965  .0000129  2.1824 0.0092  I   -34.940     .138    -9.207     .298  -.145420   .452510  -.3790580   -34.500    -9.300  
+97 5 9 50577.00 I  -.142482  .000119   .455307  .000094  I -.3812199  .0000127  2.0768 0.0093  I   -34.779     .138    -9.127     .298  -.142440   .455210  -.3811930   -34.500    -9.500  
+97 510 50578.00 I  -.139426  .000104   .458227  .000094  I -.3832642  .0000134  2.0135 0.0087  I   -34.582     .108    -9.090     .121  -.139410   .458130  -.3832900   -34.600    -9.700  
+97 511 50579.00 I  -.136461  .000055   .461179  .000059  I -.3852533  .0000118  1.9693 0.0071  I   -34.566     .791    -9.201     .298  -.136280   .461250  -.3852540   -34.600    -9.800  
+97 512 50580.00 I  -.133867  .000058   .464047  .000065  I -.3872115  .0000048  1.9511 0.0062  I   -34.773     .791    -9.406     .298  -.133860   .464070  -.3872040   -34.700    -9.800  
+97 513 50581.00 I  -.131687  .000055   .466720  .000053  I -.3891616  .0000040  1.9510 0.0032  I   -35.004     .791    -9.580     .298  -.131640   .466690  -.3891660   -34.800    -9.800  
+97 514 50582.00 I  -.129668  .000054   .469178  .000053  I -.3911154  .0000042  1.9564 0.0034  I   -35.037     .791    -9.646     .298  -.129560   .469170  -.3911180   -34.900    -9.700  
+97 515 50583.00 I  -.127578  .000064   .471457  .000066  I -.3930758  .0000056  1.9659 0.0035  I   -34.869     .791    -9.605     .298  -.127760   .471830  -.3930820   -35.000    -9.500  
+97 516 50584.00 I  -.125217  .000065   .473621  .000072  I -.3950526  .0000056  1.9916 0.0036  I   -34.723     .791    -9.498     .298  -.125190   .473650  -.3950390   -35.000    -9.300  
+97 517 50585.00 I  -.122492  .000065   .475779  .000070  I -.3970639  .0000045  2.0319 0.0040  I   -34.766     .791    -9.369     .298  -.122280   .475780  -.3970140   -35.200    -9.100  
+97 518 50586.00 I  -.119535  .000070   .478059  .000106  I -.3991144  .0000058  2.0661 0.0040  I   -34.977     .791    -9.233     .298  -.119350   .478040  -.3990670   -35.200    -8.900  
+97 519 50587.00 I  -.116559  .000102   .480544  .000135  I -.4011911  .0000066  2.0855 0.0042  I   -35.249     .791    -9.077     .147  -.116500   .480480  -.4011750   -35.400    -8.900  
+97 520 50588.00 I  -.113641  .000104   .483188  .000134  I -.4032818  .0000061  2.0943 0.0041  I   -35.502     .791    -8.914     .147  -.113540   .483140  -.4032990   -35.600    -8.800  
+97 521 50589.00 I  -.110776  .000101   .485865  .000136  I -.4053710  .0000050  2.0769 0.0040  I   -35.680     .791    -8.828     .147  -.110730   .485760  -.4053930   -35.700    -8.800  
+97 522 50590.00 I  -.108256  .000098   .488391  .000130  I -.4074257  .0000052  2.0298 0.0036  I   -35.739     .791    -8.904     .147  -.108270   .488390  -.4074370   -35.900    -9.000  
+97 523 50591.00 I  -.105963  .000097   .490720  .000133  I -.4094314  .0000052  1.9853 0.0048  I   -35.696     .791    -9.106     .147  -.105880   .490770  -.4094310   -36.000    -9.100  
+97 524 50592.00 I  -.103700  .000115   .492983  .000123  I -.4114046  .0000080  1.9658 0.0062  I   -35.675     .791    -9.283     .147  -.103560   .492970  -.4114080   -36.200    -9.100  
+97 525 50593.00 I  -.101447  .000098   .495252  .000136  I -.4133742  .0000112  1.9798 0.0065  I   -35.820     .791    -9.309     .298  -.101400   .495370  -.4133980   -36.300    -9.100  
+97 526 50594.00 I  -.099172  .000097   .497478  .000145  I -.4153798  .0000103  2.0406 0.0076  I   -36.147     .791    -9.202     .298  -.099110   .497570  -.4154060   -36.300    -9.100  
+97 527 50595.00 I  -.096785  .000094   .499650  .000144  I -.4174722  .0000103  2.1520 0.0076  I   -36.494     .791    -9.088     .298  -.096900   .499300  -.4174680   -36.400    -9.000  
+97 528 50596.00 I  -.094267  .000110   .501741  .000136  I -.4196953  .0000112  2.2981 0.0079  I   -36.635     .791    -9.060     .298  -.094180   .501500  -.4197000   -36.400    -8.800  
+97 529 50597.00 I  -.091850  .000123   .503791  .000125  I -.4220672  .0000120  2.4406 0.0078  I   -36.461     .791    -9.109     .298  -.091740   .504070  -.4220830   -36.500    -8.700  
+97 530 50598.00 I  -.089584  .000109   .505799  .000132  I -.4245581  .0000110  2.5279 0.0080  I   -36.098     .791    -9.146     .298  -.089680   .506070  -.4245640   -36.400    -8.500  
+97 531 50599.00 I  -.087350  .000082   .507760  .000100  I -.4270965  .0000106  2.5357 0.0091  I   -35.840     .791    -9.106     .298  -.087270   .507660  -.4271100   -36.500    -8.500  
+97 6 1 50600.00 I  -.085071  .000094   .509688  .000110  I -.4296072  .0000144  2.4765 0.0085  I   -35.945     .791    -9.018     .298  -.084900   .509870  -.4295920   -36.700    -8.400  
+97 6 2 50601.00 I  -.082698  .000126   .511540  .000111  I -.4320282  .0000134  2.3532 0.0097  I   -36.426     .791    -8.965     .118  -.082550   .511740  -.4320310   -36.800    -8.400  
+97 6 3 50602.00 I  -.080141  .000125   .513310  .000102  I -.4342951  .0000131  2.1742 0.0092  I   -37.021     .791    -8.971     .118  -.080290   .513170  -.4342640   -36.900    -8.400  
+97 6 4 50603.00 I  -.077450  .000117   .515008  .000106  I -.4363661  .0000127  1.9635 0.0091  I   -37.381     .791    -8.954     .118  -.077560   .514830  -.4363590   -37.000    -8.600  
+97 6 5 50604.00 I  -.074955  .000129   .516512  .000110  I -.4382224  .0000125  1.7536 0.0089  I   -37.331     .791    -8.885     .118  -.074960   .516480  -.4382470   -36.900    -8.600  
+97 6 6 50605.00 I  -.072662  .000138   .517746  .000111  I -.4398921  .0000125  1.6002 0.0080  I   -37.001     .121    -8.751     .135  -.072650   .517730  -.4398790   -36.800    -8.700  
+97 6 7 50606.00 I  -.070423  .000137   .518722  .000113  I -.4414443  .0000101  1.5113 0.0070  I   -36.680     .121    -8.626     .135  -.070340   .518680  -.4414520   -36.600    -8.800  
+97 6 8 50607.00 I  -.068053  .000133   .519422  .000101  I -.4429291  .0000062  1.4654 0.0056  I   -36.563     .791    -8.615     .298  -.068210   .519640  -.4429350   -36.600    -8.900  
+97 6 9 50608.00 I  -.065268  .000206   .519887  .000104  I -.4443891  .0000047  1.4613 0.0041  I   -36.649     .791    -8.724     .298  -.065500   .520040  -.4443870   -36.500    -8.900  
+97 610 50609.00 I  -.061898  .000192   .520349  .000101  I -.4458636  .0000053  1.4930 0.0043  I   -36.832     .791    -8.869     .298  -.061880   .520140  -.4458620   -36.600    -8.900  
+97 611 50610.00 I  -.058127  .000198   .521097  .000100  I -.4473822  .0000071  1.5460 0.0045  I   -37.022     .791    -8.965     .298  -.058090   .520920  -.4473900   -36.800    -8.800  
+97 612 50611.00 I  -.054367  .000194   .522302  .000102  I -.4489535  .0000073  1.5925 0.0066  I   -37.171     .791    -8.983     .298  -.054330   .522280  -.4489650   -37.100    -8.800  
+97 613 50612.00 I  -.050642  .000188   .523897  .000099  I -.4505582  .0000111  1.6118 0.0083  I   -37.269     .791    -8.943     .298  -.050440   .523870  -.4505490   -37.600    -8.600  
+97 614 50613.00 I  -.046970  .000196   .525560  .000130  I -.4521676  .0000149  1.6024 0.0087  I   -37.401     .791    -8.877     .298  -.046980   .525830  -.4521290   -37.900    -8.500  
+97 615 50614.00 I  -.043365  .000091   .526958  .000122  I -.4537530  .0000133  1.5628 0.0097  I   -37.713     .791    -8.789     .298  -.043510   .527200  -.4537240   -38.300    -8.300  
+97 616 50615.00 I  -.039765  .000164   .528003  .000117  I -.4552828  .0000124  1.4920 0.0090  I   -38.254     .211    -8.660     .298  -.039660   .528020  -.4552880   -38.600    -8.200  
+97 617 50616.00 I  -.036136  .000141   .528829  .000118  I -.4567309  .0000122  1.4028 0.0086  I   -38.847     .211    -8.493     .298  -.036070   .528570  -.4567500   -38.800    -8.200  
+97 618 50617.00 I  -.032476  .000130   .529592  .000112  I -.4580759  .0000119  1.2760 0.0081  I   -39.225     .211    -8.376     .298  -.032510   .529440  -.4580800   -38.900    -8.200  
+97 619 50618.00 I  -.028867  .000131   .530411  .000105  I -.4592748  .0000108  1.1248 0.0082  I   -39.279     .211    -8.393     .298  -.028920   .530430  -.4592590   -38.900    -8.200  
+97 620 50619.00 I  -.025152  .000126   .531246  .000092  I -.4603396  .0000112  1.0159 0.0071  I   -39.131     .211    -8.572     .298  -.025010   .531400  -.4603310   -38.800    -8.300  
+97 621 50620.00 I  -.021281  .000121   .532003  .000070  I -.4613282  .0000092  0.9717 0.0075  I   -38.983     .258    -8.777     .298  -.021080   .532140  -.4613360   -38.700    -8.300  
+97 622 50621.00 I  -.017250  .000072   .532620  .000070  I -.4623065  .0000099  0.9978 0.0059  I   -38.971     .791    -8.793     .298  -.017230   .532690  -.4623090   -38.700    -8.200  
+97 623 50622.00 I  -.013076  .000103   .533105  .000076  I -.4633442  .0000075  1.0850 0.0062  I   -39.142     .791    -8.558     .298  -.012820   .533010  -.4633470   -38.800    -8.200  
+97 624 50623.00 I  -.008959  .000096   .533538  .000073  I -.4644849  .0000076  1.1976 0.0054  I   -39.470     .791    -8.230     .298  -.008700   .533480  -.4644800   -39.000    -8.100  
+97 625 50624.00 I  -.005037  .000089   .533969  .000079  I -.4657361  .0000077  1.3005 0.0054  I   -39.836     .791    -8.028     .298  -.004870   .533880  -.4657440   -39.400    -7.900  
+97 626 50625.00 I  -.001305  .000106   .534422  .000086  I -.4670736  .0000076  1.3666 0.0055  I   -40.063     .791    -8.040     .298  -.001160   .534400  -.4670770   -39.800    -7.800  
+97 627 50626.00 I   .002419  .000096   .534850  .000092  I -.4684479  .0000078  1.3687 0.0056  I   -40.048     .791    -8.189     .298   .002430   .534990  -.4684540   -40.300    -7.800  
+97 628 50627.00 I   .006322  .000094   .535197  .000093  I -.4697869  .0000083  1.2987 0.0057  I   -39.896     .791    -8.344     .298   .006390   .535310  -.4698040   -40.700    -7.800  
+97 629 50628.00 I   .010476  .000105   .535489  .000106  I -.4710285  .0000084  1.1784 0.0061  I   -39.879     .791    -8.442     .298   .010520   .535600  -.4710160   -41.100    -8.000  
+97 630 50629.00 I   .014809  .000151   .535883  .000141  I -.4721332  .0000089  1.0266 0.0061  I   -40.213     .791    -8.514     .193   .014850   .535860  -.4721370   -41.200    -8.100  
+97 7 1 50630.00 I   .019205  .000148   .536419  .000137  I  .5269220  .0000088  0.8635 0.0060  I   -40.843     .791    -8.615     .193   .019150   .536250   .5268940   -41.200    -8.200  
+97 7 2 50631.00 I   .023493  .000143   .536912  .000142  I  .5261374  .0000080  0.7075 0.0060  I   -41.454     .791    -8.756     .193   .023390   .536680   .5261270   -41.200    -8.500  
+97 7 3 50632.00 I   .027452  .000138   .537141  .000140  I  .5254967  .0000083  0.5826 0.0058  I   -41.739     .791    -8.881     .193   .027540   .537280   .5255080   -41.100    -8.600  
+97 7 4 50633.00 I   .031223  .000137   .537076  .000141  I  .5249515  .0000085  0.5200 0.0063  I   -41.681     .791    -8.937     .193   .031140   .536960   .5249520   -41.000    -8.700  
+97 7 5 50634.00 I   .034962  .000149   .536773  .000149  I  .5244340  .0000096  0.5256 0.0070  I   -41.507     .791    -8.914     .193   .034850   .536560   .5244230   -40.900    -8.800  
+97 7 6 50635.00 I   .038689  .000134   .536291  .000078  I  .5238814  .0000111  0.5879 0.0061  I   -41.429     .791    -8.843     .298   .038740   .536120   .5238950   -40.900    -8.400  
+97 7 7 50636.00 I   .042534  .000138   .535696  .000119  I  .5232476  .0000076  0.6822 0.0066  I   -41.502     .328    -8.758     .298   .042370   .535810   .5232340   -41.000    -8.400  
+97 7 8 50637.00 I   .046663  .000142   .535063  .000132  I  .5225157  .0000073  0.7806 0.0053  I   -41.723     .394    -8.697     .298   .046380   .534930   .5224760   -41.300    -8.400  
+97 7 9 50638.00 I   .050873  .000151   .534487  .000141  I  .5216906  .0000073  0.8665 0.0056  I   -42.093     .394    -8.706     .298   .050830   .534450   .5216790   -41.800    -8.500  
+97 710 50639.00 I   .054750  .000149   .534055  .000145  I  .5207857  .0000084  0.9432 0.0054  I   -42.500     .394    -8.795     .298   .054960   .534310   .5207760   -42.300    -8.700  
+97 711 50640.00 I   .058275  .000144   .533596  .000152  I  .5198074  .0000080  1.0101 0.0065  I   -42.623     .394    -8.870     .298   .058500   .533840   .5198110   -42.900    -8.900  
+97 712 50641.00 I   .061703  .000152   .532970  .000144  I  .5187691  .0000099  1.0661 0.0067  I   -42.452     .387    -8.876     .298   .061880   .533060   .5187780   -43.400    -9.000  
+97 713 50642.00 I   .065250  .000140   .532212  .000114  I  .5176801  .0000107  1.1072 0.0067  I   -42.384     .414    -8.829     .298   .065180   .532240   .5176940   -43.700    -9.100  
+97 714 50643.00 I   .068880  .000155   .531426  .000113  I  .5165642  .0000091  1.1197 0.0075  I   -42.759     .288    -8.755     .224   .068750   .531420   .5166260   -44.000    -9.100  
+97 715 50644.00 I   .072463  .000151   .530698  .000105  I  .5154546  .0000104  1.0906 0.0066  I   -43.473     .288    -8.658     .224   .072390   .530670   .5154970   -44.100    -9.000  
+97 716 50645.00 I   .075783  .000151   .530020  .000105  I  .5143902  .0000096  1.0401 0.0071  I   -44.093     .288    -8.558     .224   .075690   .529910   .5143660   -44.000    -8.900  
+97 717 50646.00 I   .078739  .000165   .529321  .000102  I  .5133592  .0000097  1.0352 0.0062  I   -44.273     .288    -8.484     .224   .078780   .529110   .5133850   -43.900    -8.800  
+97 718 50647.00 I   .081527  .000162   .528578  .000106  I  .5122953  .0000079  1.1038 0.0063  I   -44.177     .234    -8.552     .269   .081560   .528620   .5123300   -43.700    -8.700  
+97 719 50648.00 I   .084482  .000141   .527746  .000106  I  .5111334  .0000081  1.2269 0.0093  I   -44.120     .234    -8.742     .269   .084430   .527980   .5111090   -43.600    -8.600  
+97 720 50649.00 I   .087863  .000117   .526792  .000101  I  .5098259  .0000169  1.3969 0.0068  I   -44.182     .791    -8.836     .298   .087470   .526420   .5098570   -43.500    -8.400  
+97 721 50650.00 I   .091630  .000118   .525731  .000126  I  .5083296  .0000110  1.5969 0.0096  I   -44.278     .433    -8.661     .298   .091370   .525420   .5083920   -43.600    -8.100  
+97 722 50651.00 I   .095462  .000129   .524636  .000152  I  .5066364  .0000093  1.7839 0.0072  I   -44.372     .459    -8.299     .298   .095540   .524670   .5066460   -43.800    -8.000  
+97 723 50652.00 I   .099070  .000127   .523593  .000153  I  .5047789  .0000093  1.9195 0.0071  I   -44.489     .459    -7.986     .298   .099300   .523600   .5047620   -44.100    -7.900  
+97 724 50653.00 I   .102369  .000116   .522632  .000144  I  .5028128  .0000108  2.0090 0.0070  I   -44.602     .459    -7.865     .298   .102360   .522590   .5028580   -44.700    -7.900  
+97 725 50654.00 I   .105406  .000111   .521769  .000147  I  .5007884  .0000105  2.0160 0.0075  I   -44.750     .459    -7.940     .298   .105250   .521650   .5008370   -45.100    -8.000  
+97 726 50655.00 I   .108028  .000112   .520860  .000139  I  .4988149  .0000105  1.9208 0.0072  I   -44.868     .459    -8.105     .298   .108100   .520900   .4987890   -45.600    -8.100  
+97 727 50656.00 I   .110314  .000115   .519815  .000128  I  .4969636  .0000099  1.7750 0.0061  I   -44.921     .484    -8.291     .298   .110350   .519920   .4969520   -45.900    -8.400  
+97 728 50657.00 I   .112515  .000114   .518611  .000089  I  .4952704  .0000062  1.6125 0.0062  I   -45.040     .131    -8.493     .170   .112490   .518700   .4952740   -46.000    -8.600  
+97 729 50658.00 I   .114866  .000119   .517276  .000095  I  .4937342  .0000074  1.4633 0.0040  I   -45.376     .131    -8.698     .170   .114770   .517170   .4937570   -45.900    -8.800  
+97 730 50659.00 I   .117460  .000113   .515918  .000093  I  .4923373  .0000050  1.3338 0.0049  I   -45.887     .131    -8.873     .170   .117530   .515740   .4923430   -45.700    -8.900  
+97 731 50660.00 I   .120245  .000108   .514597  .000092  I  .4910524  .0000064  1.2471 0.0041  I   -46.307     .131    -9.000     .170   .120280   .514540   .4910370   -45.400    -9.000  
+97 8 1 50661.00 I   .123226  .000113   .513301  .000116  I  .4898217  .0000064  1.2247 0.0046  I   -46.412     .131    -9.089     .170   .123130   .513310   .4898480   -45.000    -9.000  
+97 8 2 50662.00 I   .126325  .000131   .512004  .000129  I  .4885897  .0000065  1.2422 0.0059  I   -46.220     .131    -9.118     .170   .126390   .512030   .4885980   -44.700    -8.800  
+97 8 3 50663.00 I   .129373  .000118   .510695  .000159  I  .4873339  .0000098  1.2699 0.0050  I   -45.914     .791    -9.024     .298   .129470   .510800   .4872900   -44.600    -8.700  
+97 8 4 50664.00 I   .132300  .000125   .509356  .000172  I  .4860454  .0000077  1.3112 0.0064  I   -45.657     .109    -8.792     .298   .132500   .509470   .4860610   -44.700    -8.600  
+97 8 5 50665.00 I   .135125  .000131   .507996  .000161  I  .4847079  .0000083  1.3632 0.0053  I   -45.547     .109    -8.534     .298   .135210   .508000   .4847340   -45.000    -8.300  
+97 8 6 50666.00 I   .137790  .000141   .506654  .000155  I  .4833214  .0000074  1.4079 0.0056  I   -45.628     .109    -8.427     .298   .137730   .506730   .4833070   -45.300    -8.300  
+97 8 7 50667.00 I   .140168  .000141   .505311  .000147  I  .4818941  .0000074  1.4464 0.0051  I   -45.837     .109    -8.524     .298   .140190   .505620   .4819060   -45.800    -8.400  
+97 8 8 50668.00 I   .142406  .000119   .503863  .000127  I  .4804318  .0000071  1.4752 0.0046  I   -45.947     .109    -8.720     .298   .142330   .503990   .4804660   -46.300    -8.500  
+97 8 9 50669.00 I   .144656  .000098   .502196  .000100  I  .4789539  .0000055  1.4732 0.0063  I   -45.881     .791    -8.870     .298   .144720   .502370   .4789680   -46.600    -8.600  
+97 810 50670.00 I   .146894  .000086   .500298  .000107  I  .4774990  .0000104  1.4303 0.0045  I   -45.936     .791    -8.931     .298   .146900   .500350   .4775170   -46.900    -8.700  
+97 811 50671.00 I   .149084  .000121   .498268  .000164  I  .4761027  .0000071  1.3593 0.0063  I   -46.450     .250    -8.946     .298   .149040   .498160   .4761580   -47.100    -8.600  
+97 812 50672.00 I   .151262  .000122   .496249  .000171  I  .4747824  .0000070  1.2823 0.0051  I   -47.283     .250    -8.912     .298   .151260   .496060   .4748590   -47.200    -8.600  
+97 813 50673.00 I   .153451  .000127   .494316  .000178  I  .4735354  .0000072  1.2132 0.0062  I   -47.883     .250    -8.784     .298   .153290   .494020   .4735610   -47.200    -8.500  
+97 814 50674.00 I   .155554  .000128   .492263  .000186  I  .4723490  .0000102  1.1649 0.0063  I   -47.935     .250    -8.623     .298   .155510   .492230   .4723190   -47.100    -8.400  
+97 815 50675.00 I   .157518  .000128   .490077  .000189  I  .4711881  .0000103  1.1691 0.0071  I   -47.688     .305    -8.592     .298   .157600   .489950   .4711990   -47.200    -8.300  
+97 816 50676.00 I   .159400  .000136   .487885  .000192  I  .4699843  .0000099  1.2526 0.0105  I   -47.577     .305    -8.760     .298   .159390   .487510   .4700320   -47.200    -8.300  
+97 817 50677.00 I   .161219  .000099   .485756  .000141  I  .4686609  .0000184  1.4020 0.0082  I   -47.732     .791    -8.968     .298   .161220   .485780   .4686570   -47.200    -8.300  
+97 818 50678.00 I   .163022  .000114   .483664  .000200  I  .4671734  .0000131  1.5723 0.0106  I   -47.978     .181    -8.989     .298   .162940   .483860   .4671290   -47.400    -8.300  
+97 819 50679.00 I   .164917  .000123   .481520  .000219  I  .4655203  .0000107  1.7308 0.0076  I   -48.167     .185    -8.786     .298   .165070   .481530   .4655210   -47.700    -8.400  
+97 820 50680.00 I   .166942  .000116   .479299  .000206  I  .4637208  .0000078  1.8625 0.0068  I   -48.355     .185    -8.502     .298   .167120   .479130   .4637370   -48.000    -8.500  
+97 821 50681.00 I   .169141  .000117   .476973  .000199  I  .4618231  .0000085  1.9110 0.0057  I   -48.686     .185    -8.226     .298   .169090   .476780   .4617800   -48.300    -8.500  
+97 822 50682.00 I   .171583  .000112   .474577  .000210  I  .4599375  .0000082  1.8436 0.0059  I   -49.146     .185    -8.005     .298   .171650   .474590   .4599200   -48.600    -8.500  
+97 823 50683.00 I   .174167  .000121   .472261  .000220  I  .4581597  .0000082  1.7049 0.0069  I   -49.556     .185    -7.831     .298   .174220   .472300   .4581840   -48.700    -8.500  
+97 824 50684.00 I   .176778  .000119   .470154  .000232  I  .4565369  .0000112  1.5388 0.0089  I   -49.654     .144    -7.781     .298   .176740   .470020   .4564810   -48.600    -8.400  
+97 825 50685.00 I   .179283  .000126   .468296  .000231  I  .4550755  .0000157  1.3926 0.0099  I   -49.313     .113    -7.978     .298   .179480   .468220   .4549860   -48.400    -8.500  
+97 826 50686.00 I   .181563  .000124   .466641  .000233  I  .4537300  .0000164  1.3114 0.0111  I   -48.751     .113    -8.393     .298   .181730   .466700   .4537580   -47.900    -8.500  
+97 827 50687.00 I   .183704  .000117   .465033  .000241  I  .4524304  .0000158  1.2969 0.0111  I   -48.336     .113    -8.850     .298   .183670   .465180   .4524560   -47.400    -8.600  
+97 828 50688.00 I   .185879  .000134   .463308  .000248  I  .4511285  .0000149  1.3054 0.0110  I   -48.213     .113    -9.148     .298   .186040   .463220   .4510470   -46.700    -8.600  
+97 829 50689.00 I   .188047  .000144   .461515  .000245  I  .4498180  .0000152  1.3186 0.0101  I   -48.164     .113    -9.285     .298   .188200   .461540   .4497610   -46.200    -8.700  
+97 830 50690.00 I   .190182  .000149   .459681  .000224  I  .4484854  .0000136  1.3496 0.0096  I   -47.964     .127    -9.314     .298   .190040   .459870   .4484800   -45.700    -8.700  
+97 831 50691.00 I   .192397  .000160   .457851  .000154  I  .4471108  .0000117  1.4047 0.0078  I   -47.662     .791    -9.193     .298   .192810   .457580   .4470950   -45.500    -8.500  
+97 9 1 50692.00 I   .194835  .000174   .456075  .000171  I  .4456687  .0000076  1.4816 0.0070  I   -47.462     .254    -8.877     .298   .195190   .455900   .4456580   -45.500    -8.500  
+97 9 2 50693.00 I   .197512  .000171   .454304  .000189  I  .4441490  .0000077  1.5544 0.0054  I   -47.492     .270    -8.473     .298   .197410   .454390   .4441620   -45.800    -8.400  
+97 9 3 50694.00 I   .200273  .000164   .452464  .000209  I  .4425676  .0000078  1.6042 0.0059  I   -47.751     .270    -8.201     .298   .199960   .452670   .4425770   -46.500    -8.300  
+97 9 4 50695.00 I   .202819  .000142   .450531  .000186  I  .4409528  .0000090  1.6175 0.0058  I   -48.120     .270    -8.192     .298   .202790   .450800   .4409470   -47.100    -8.300  
+97 9 5 50696.00 I   .204834  .000143   .448415  .000196  I  .4393440  .0000086  1.5964 0.0058  I   -48.315     .270    -8.349     .298   .204910   .448760   .4393220   -47.900    -8.200  
+97 9 6 50697.00 I   .206425  .000166   .446053  .000203  I  .4377641  .0000074  1.5628 0.0057  I   -48.217     .270    -8.481     .298   .206370   .446300   .4377530   -48.500    -8.300  
+97 9 7 50698.00 I   .207950  .000174   .443508  .000201  I  .4362179  .0000074  1.5308 0.0048  I   -48.043     .285    -8.514     .298   .207950   .443560   .4362150   -49.000    -8.200  
+97 9 8 50699.00 I   .209613  .000162   .440941  .000193  I  .4347090  .0000060  1.4795 0.0048  I   -48.124     .483    -8.512     .298   .209570   .440850   .4347020   -49.200    -8.200  
+97 9 9 50700.00 I   .211333  .000170   .438467  .000190  I  .4332717  .0000060  1.3899 0.0041  I   -48.493     .483    -8.521     .298   .211080   .438240   .4332700   -49.200    -8.400  
+97 910 50701.00 I   .212799  .000167   .435949  .000193  I  .4319120  .0000057  1.3521 0.0045  I   -48.809     .483    -8.492     .298   .212530   .435910   .4319150   -48.900    -8.400  
+97 911 50702.00 I   .214129  .000165   .433249  .000189  I  .4305354  .0000068  1.4108 0.0044  I   -48.779     .483    -8.397     .298   .213980   .433250   .4305350   -48.500    -8.400  
+97 912 50703.00 I   .215443  .000153   .430595  .000177  I  .4290757  .0000068  1.5137 0.0053  I   -48.508     .483    -8.319     .298   .215450   .430440   .4290670   -48.000    -8.400  
+97 913 50704.00 I   .216636  .000129   .428209  .000196  I  .4274979  .0000082  1.6470 0.0090  I   -48.333     .396    -8.347     .298   .216880   .428020   .4275020   -47.600    -8.300  
+97 914 50705.00 I   .217447  .000131   .426056  .000196  I  .4257653  .0000167  1.8295 0.0084  I   -48.407     .791    -8.418     .298   .217650   .426110   .4257870   -47.300    -8.300  
+97 915 50706.00 I   .217825  .000126   .423914  .000238  I  .4238243  .0000146  2.0557 0.0106  I   -48.587     .791    -8.382     .298   .218030   .424210   .4238360   -47.200    -8.100  
+97 916 50707.00 I   .217939  .000126   .421578  .000230  I  .4216578  .0000130  2.2703 0.0089  I   -48.653     .791    -8.215     .298   .218030   .421720   .4216490   -47.300    -8.000  
+97 917 50708.00 I   .218042  .000125   .419053  .000230  I  .4193071  .0000103  2.4149 0.0090  I   -48.544     .791    -8.038     .298   .217980   .419020   .4192990   -47.600    -8.000  
+97 918 50709.00 I   .218405  .000133   .416554  .000223  I  .4168661  .0000124  2.4454 0.0081  I   -48.435     .791    -7.928     .298   .218320   .416550   .4168570   -48.000    -7.900  
+97 919 50710.00 I   .219060  .000129   .414120  .000198  I  .4144571  .0000126  2.3536 0.0086  I   -48.570     .791    -7.763     .298   .219070   .414120   .4144540   -48.300    -7.900  
+97 920 50711.00 I   .219824  .000096   .411705  .000193  I  .4121859  .0000119  2.1809 0.0080  I   -48.985     .791    -7.455     .298   .219840   .411700   .4122050   -48.500    -7.900  
+97 921 50712.00 I   .220552  .000104   .409271  .000134  I  .4100988  .0000100  1.9976 0.0070  I   -49.361     .791    -7.175     .298   .220580   .409270   .4101310   -48.600    -7.900  
+97 922 50713.00 I   .221159  .000144   .406759  .000213  I  .4081784  .0000074  1.8512 0.0066  I   -49.293     .235    -7.201     .298   .221230   .406690   .4081940   -48.500    -8.100  
+97 923 50714.00 I   .221544  .000146   .404116  .000221  I  .4063782  .0000087  1.7595 0.0053  I   -48.763     .235    -7.580     .298   .221670   .403970   .4063660   -48.200    -8.100  
+97 924 50715.00 I   .221639  .000140   .401267  .000227  I  .4046411  .0000076  1.7227 0.0058  I   -48.192     .235    -8.065     .298   .221680   .400980   .4046340   -47.700    -8.100  
+97 925 50716.00 I   .221427  .000141   .398075  .000233  I  .4029151  .0000078  1.7389 0.0054  I   -47.921     .235    -8.404     .298   .221290   .397770   .4029280   -47.200    -8.200  
+97 926 50717.00 I   .221148  .000144   .394691  .000238  I  .4011444  .0000076  1.8119 0.0065  I   -47.835     .235    -8.550     .298   .221180   .394520   .4011560   -46.700    -8.100  
+97 927 50718.00 I   .220967  .000146   .391340  .000234  I  .3992871  .0000104  1.8975 0.0108  I   -47.628     .235    -8.589     .298   .220850   .391110   .3992790   -46.300    -8.000  
+97 928 50719.00 I   .220896  .000092   .388141  .000257  I  .3973575  .0000203  1.9588 0.0101  I   -47.248     .791    -8.553     .298   .220760   .387900   .3973340   -46.100    -7.900  
+97 929 50720.00 I   .220936  .000073   .385125  .000253  I  .3953779  .0000174  1.9950 0.0139  I   -46.903     .791    -8.401     .298   .220990   .385200   .3953510   -46.100    -7.800  
+97 930 50721.00 I   .221029  .000117   .382236  .000255  I  .3933771  .0000189  2.0023 0.0127  I   -46.737     .791    -8.154     .298   .221110   .382080   .3933600   -46.300    -7.700  
+9710 1 50722.00 I   .221183  .000102   .379339  .000249  I  .3913652  .0000184  2.0337 0.0124  I   -46.719     .791    -7.924     .298   .221130   .379260   .3913550   -46.500    -7.700  
+9710 2 50723.00 I   .221438  .000101   .376317  .000250  I  .3893063  .0000162  2.0751 0.0110  I   -46.774     .791    -7.794     .298   .221440   .376660   .3893070   -47.000    -7.600  
+9710 3 50724.00 I   .221678  .000109   .373215  .000250  I  .3872347  .0000122  2.0574 0.0096  I   -46.842     .791    -7.740     .298   .221760   .373380   .3872330   -47.400    -7.600  
+9710 4 50725.00 I   .221852  .000108   .370134  .000229  I  .3852065  .0000103  1.9948 0.0088  I   -46.861     .791    -7.668     .298   .221910   .370090   .3852180   -47.600    -7.600  
+9710 5 50726.00 I   .222066  .000119   .367211  .000128  I  .3832492  .0000126  1.9198 0.0072  I   -46.822     .154    -7.544     .298   .222050   .367100   .3832650   -47.700    -7.700  
+9710 6 50727.00 I   .222328  .000137   .364524  .000163  I  .3813624  .0000100  1.8583 0.0080  I   -46.825     .262    -7.430     .298   .222270   .364270   .3813700   -47.600    -7.600  
+9710 7 50728.00 I   .222531  .000105   .362045  .000157  I  .3795218  .0000097  1.8292 0.0073  I   -46.942     .262    -7.398     .298   .222490   .361950   .3795040   -47.400    -7.600  
+9710 8 50729.00 I   .222583  .000122   .359663  .000155  I  .3776878  .0000105  1.8486 0.0078  I   -47.072     .262    -7.443     .298   .222450   .359630   .3776800   -47.000    -7.500  
+9710 9 50730.00 I   .222463  .000134   .357334  .000156  I  .3758081  .0000121  1.9175 0.0082  I   -47.075     .262    -7.459     .298   .222590   .357400   .3758620   -46.700    -7.400  
+971010 50731.00 I   .222364  .000146   .354973  .000158  I  .3738415  .0000127  2.0202 0.0082  I   -46.915     .262    -7.420     .298   .222250   .355160   .3739320   -46.300    -7.200  
+971011 50732.00 I   .222546  .000146   .352483  .000161  I  .3717573  .0000112  2.1539 0.0098  I   -46.705     .302    -7.356     .298   .222270   .352650   .3718190   -46.100    -6.900  
+971012 50733.00 I   .223066  .000141   .349874  .000130  I  .3695248  .0000150  2.3141 0.0087  I   -46.585     .791    -7.242     .298   .223130   .349980   .3695390   -45.900    -6.800  
+971013 50734.00 I   .223742  .000163   .347247  .000161  I  .3671319  .0000133  2.4658 0.0099  I   -46.587     .791    -7.041     .298   .224030   .347190   .3671270   -46.100    -6.700  
+971014 50735.00 I   .224350  .000149   .344654  .000155  I  .3646101  .0000129  2.5668 0.0084  I   -46.630     .791    -6.818     .298   .224420   .344320   .3646070   -46.400    -6.600  
+971015 50736.00 I   .224829  .000146   .342047  .000165  I  .3620202  .0000102  2.6020 0.0084  I   -46.608     .791    -6.732     .298   .224770   .341830   .3620180   -46.700    -6.700  
+971016 50737.00 I   .225233  .000116   .339341  .000149  I  .3594312  .0000107  2.5619 0.0071  I   -46.513     .791    -6.824     .298   .225390   .339510   .3594170   -47.200    -6.700  
+971017 50738.00 I   .225513  .000127   .336514  .000151  I  .3569238  .0000099  2.4395 0.0065  I   -46.494     .791    -6.907     .298   .225690   .336490   .3568930   -47.400    -6.900  
+971018 50739.00 I   .225723  .000153   .333587  .000161  I  .3545707  .0000074  2.2617 0.0058  I   -46.687     .791    -6.789     .298   .225510   .333780   .3545530   -47.600    -7.000  
+971019 50740.00 I   .226071  .000166   .330617  .000142  I  .3524006  .0000061  2.0834 0.0056  I   -46.951     .139    -6.552     .298   .225840   .330710   .3524200   -47.500    -7.000  
+971020 50741.00 I   .226734  .000169   .327713  .000135  I  .3503925  .0000084  1.9394 0.0052  I   -46.924     .245    -6.497     .298   .226660   .327500   .3504260   -47.200    -7.200  
+971021 50742.00 I   .227583  .000172   .324971  .000135  I  .3485072  .0000083  1.8391 0.0057  I   -46.449     .245    -6.781     .298   .227620   .324710   .3485250   -46.700    -7.200  
+971022 50743.00 I   .228135  .000168   .322377  .000130  I  .3467023  .0000078  1.7747 0.0058  I   -45.796     .245    -7.228     .298   .228130   .322290   .3467090   -46.000    -7.100  
+971023 50744.00 I   .228073  .000160   .319805  .000131  I  .3449452  .0000081  1.7482 0.0058  I   -45.361     .245    -7.559     .298   .227930   .319980   .3449410   -45.300    -7.000  
+971024 50745.00 I   .227639  .000155   .317177  .000124  I  .3431894  .0000085  1.7711 0.0061  I   -45.163     .245    -7.637     .298   .227590   .317140   .3431750   -44.600    -6.900  
+971025 50746.00 I   .227015  .000136   .314451  .000099  I  .3413928  .0000091  1.8246 0.0066  I   -44.955     .283    -7.529     .298   .227000   .314360   .3413770   -44.100    -6.800  
+971026 50747.00 I   .226260  .000090   .311590  .000078  I  .3395366  .0000101  1.8888 0.0054  I   -44.661     .791    -7.347     .298   .226170   .311650   .3395010   -43.800    -6.600  
+971027 50748.00 I   .225349  .000099   .308591  .000118  I  .3376163  .0000058  1.9498 0.0061  I   -44.450     .112    -7.124     .298   .225500   .308760   .3375650   -43.900    -6.500  
+971028 50749.00 I   .224117  .000108   .305464  .000188  I  .3356391  .0000067  2.0046 0.0042  I   -44.442     .791    -6.847     .298   .224230   .305610   .3356010   -44.000    -6.400  
+971029 50750.00 I   .222553  .000123   .302189  .000185  I  .3336090  .0000061  2.0538 0.0060  I   -44.579     .124    -6.528     .298   .222490   .302310   .3336030   -44.400    -6.400  
+971030 50751.00 I   .220887  .000128   .298780  .000192  I  .3315353  .0000100  2.0916 0.0059  I   -44.793     .124    -6.227     .298   .221120   .298860   .3315420   -44.900    -6.400  
+971031 50752.00 I   .219360  .000133   .295439  .000201  I  .3294279  .0000100  2.1230 0.0073  I   -45.044     .124    -6.085     .298   .219130   .295250   .3294120   -45.300    -6.500  
+9711 1 50753.00 I   .218197  .000144   .292331  .000193  I  .3272972  .0000106  2.1305 0.0073  I   -45.234     .142    -6.067     .102   .217830   .292330   .3272540   -45.500    -6.500  
+9711 2 50754.00 I   .217440  .000167   .289537  .000207  I  .3251797  .0000106  2.0995 0.0076  I   -45.248     .134    -6.117     .116   .217660   .290260   .3251270   -45.700    -6.700  
+9711 3 50755.00 I   .216911  .000178   .287060  .000151  I  .3231026  .0000109  2.0551 0.0076  I   -45.061     .268    -6.203     .298   .217200   .287420   .3230750   -45.500    -6.700  
+9711 4 50756.00 I   .216413  .000166   .284799  .000148  I  .3210639  .0000109  2.0274 0.0071  I   -44.809     .300    -6.281     .298   .216380   .285030   .3210520   -45.200    -6.600  
+9711 5 50757.00 I   .215856  .000183   .282591  .000139  I  .3190230  .0000090  2.0742 0.0071  I   -44.657     .300    -6.329     .298   .215990   .282700   .3190130   -44.800    -6.500  
+9711 6 50758.00 I   .215208  .000179   .280313  .000127  I  .3168940  .0000092  2.1854 0.0061  I   -44.621     .300    -6.355     .298   .215420   .280340   .3168880   -44.400    -6.300  
+9711 7 50759.00 I   .214575  .000162   .278014  .000127  I  .3146522  .0000083  2.2964 0.0061  I   -44.564     .300    -6.363     .298   .214490   .278000   .3146430   -43.900    -6.100  
+9711 8 50760.00 I   .213973  .000157   .275719  .000131  I  .3123008  .0000081  2.4085 0.0076  I   -44.381     .300    -6.318     .298   .213790   .275840   .3122920   -43.600    -5.900  
+9711 9 50761.00 I   .213355  .000122   .273388  .000123  I  .3098278  .0000127  2.5429 0.0064  I   -44.109     .791    -6.162     .298   .213340   .273380   .3098240   -43.400    -5.700  
+971110 50762.00 I   .212621  .000117   .271003  .000143  I  .3072218  .0000098  2.6569 0.0075  I   -43.886     .104    -5.878     .298   .212890   .271220   .3072180   -43.400    -5.500  
+971111 50763.00 I   .211614  .000138   .268548  .000158  I  .3045421  .0000079  2.6864 0.0059  I   -43.815     .127    -5.559     .298   .211850   .268880   .3045330   -43.400    -5.500  
+971112 50764.00 I   .210284  .000105   .266043  .000160  I  .3018805  .0000067  2.6213 0.0057  I   -43.858     .127    -5.363     .298   .210220   .266070   .3018760   -43.600    -5.400  
+971113 50765.00 I   .208730  .000107   .263564  .000159  I  .2993329  .0000081  2.4560 0.0053  I   -43.885     .127    -5.357     .298   .208840   .263480   .2993360   -43.900    -5.400  
+971114 50766.00 I   .207088  .000125   .261177  .000153  I  .2969961  .0000082  2.2080 0.0053  I   -43.872     .127    -5.503     .298   .207230   .261170   .2969980   -44.000    -5.500  
+971115 50767.00 I   .205438  .000123   .258919  .000153  I  .2949190  .0000068  1.9536 0.0052  I   -43.864     .127    -5.592     .298   .205490   .258980   .2949020   -44.100    -5.600  
+971116 50768.00 I   .203918  .000123   .256761  .000123  I  .2930689  .0000065  1.7592 0.0043  I   -43.844     .109    -5.507     .298   .203880   .256780   .2930260   -44.000    -5.700  
+971117 50769.00 I   .202655  .000104   .254669  .000127  I  .2913779  .0000051  1.6329 0.0044  I   -43.683     .271    -5.404     .108   .202760   .254780   .2913250   -43.800    -5.700  
+971118 50770.00 I   .201619  .000108   .252564  .000122  I  .2897821  .0000060  1.5697 0.0036  I   -43.276     .271    -5.471     .108   .201850   .252560   .2897440   -43.300    -5.700  
+971119 50771.00 I   .200584  .000112   .250318  .000124  I  .2882163  .0000050  1.5730 0.0043  I   -42.698     .319    -5.700     .298   .200620   .250230   .2882030   -42.800    -5.700  
+971120 50772.00 I   .199174  .000111   .247864  .000127  I  .2866280  .0000061  1.6004 0.0039  I   -42.119     .319    -5.990     .298   .199210   .248060   .2866450   -42.300    -5.600  
+971121 50773.00 I   .197451  .000106   .245209  .000124  I  .2850227  .0000059  1.6060 0.0043  I   -41.701     .319    -6.141     .298   .197520   .245450   .2850530   -41.800    -5.400  
+971122 50774.00 I   .195727  .000110   .242394  .000118  I  .2834162  .0000062  1.6110 0.0054  I   -41.511     .325    -6.071     .298   .195750   .242480   .2834300   -41.400    -5.300  
+971123 50775.00 I   .194034  .000111   .239527  .000111  I  .2817959  .0000091  1.6303 0.0046  I   -41.492     .319    -5.886     .298   .194200   .239640   .2817920   -41.400    -5.200  
+971124 50776.00 I   .192232  .000123   .236767  .000135  I  .2801566  .0000068  1.6466 0.0057  I   -41.639     .262    -5.687     .298   .192380   .236780   .2801520   -41.500    -5.200  
+971125 50777.00 I   .190303  .000103   .234238  .000142  I  .2785077  .0000068  1.6479 0.0042  I   -41.900     .791    -5.487     .298   .190440   .234200   .2785100   -41.800    -5.200  
+971126 50778.00 I   .188296  .000131   .231988  .000160  I  .2768699  .0000049  1.6218 0.0044  I   -42.131     .791    -5.255     .298   .188400   .232120   .2768720   -42.200    -5.200  
+971127 50779.00 I   .186082  .000138   .230043  .000159  I  .2752722  .0000055  1.5715 0.0036  I   -42.271     .791    -5.001     .298   .186160   .230400   .2752670   -42.600    -5.400  
+971128 50780.00 I   .183599  .000139   .228284  .000160  I  .2737303  .0000053  1.5111 0.0040  I   -42.382     .791    -4.787     .298   .183680   .228470   .2737230   -43.000    -5.400  
+971129 50781.00 I   .180925  .000158   .226584  .000185  I  .2722504  .0000057  1.4497 0.0042  I   -42.490     .791    -4.714     .298   .181050   .226750   .2722450   -43.300    -5.400  
+971130 50782.00 I   .178200  .000180   .224851  .000167  I  .2708259  .0000066  1.4034 0.0042  I   -42.496     .791    -4.830     .298   .178370   .225150   .2708160   -43.300    -5.500  
+9712 1 50783.00 I   .175672  .000204   .223009  .000148  I  .2694351  .0000063  1.3825 0.0046  I   -42.322     .390    -5.038     .298   .175500   .223390   .2694290   -43.100    -5.400  
+9712 2 50784.00 I   .173588  .000180   .221047  .000138  I  .2680505  .0000064  1.3926 0.0040  I   -42.080     .390    -5.155     .298   .173170   .221480   .2680540   -42.700    -5.300  
+9712 3 50785.00 I   .171942  .000168   .219053  .000126  I  .2666417  .0000050  1.4271 0.0049  I   -42.006     .390    -5.068     .298   .171810   .219080   .2666530   -42.200    -5.100  
+9712 4 50786.00 I   .170344  .000166   .217157  .000119  I  .2651830  .0000073  1.5013 0.0044  I   -42.230     .390    -4.811     .298   .170440   .217090   .2651940   -41.700    -4.900  
+9712 5 50787.00 I   .168527  .000155   .215369  .000116  I  .2636186  .0000072  1.6368 0.0051  I   -42.618     .390    -4.511     .298   .168750   .215580   .2636170   -41.300    -4.700  
+9712 6 50788.00 I   .166342  .000185   .213626  .000103  I  .2618905  .0000072  1.8291 0.0059  I   -42.925     .390    -4.247     .298   .166520   .213890   .2618910   -41.000    -4.400  
+9712 7 50789.00 I   .163903  .000169   .211872  .000089  I  .2599495  .0000093  2.0543 0.0051  I   -43.016     .588    -4.024     .112   .164000   .212020   .2599740   -41.000    -4.200  
+9712 8 50790.00 I   .161422  .000179   .210090  .000105  I  .2577994  .0000073  2.2272 0.0060  I   -42.932     .560    -3.850     .109   .161480   .210280   .2578130   -41.000    -4.100  
+9712 9 50791.00 I   .159046  .000187   .208306  .000115  I  .2555327  .0000077  2.2874 0.0047  I   -42.783     .560    -3.813     .109   .159250   .208410   .2555200   -41.300    -4.000  
+971210 50792.00 I   .157016  .000194   .206578  .000113  I  .2532611  .0000058  2.2380 0.0048  I   -42.626     .560    -4.029     .109   .157260   .206590   .2532500   -41.500    -4.000  
+971211 50793.00 I   .155360  .000209   .204964  .000149  I  .2510794  .0000058  2.1204 0.0041  I   -42.600     .560    -4.398     .109   .155610   .204990   .2510800   -41.900    -4.100  
+971212 50794.00 I   .153813  .000205   .203422  .000172  I  .2490314  .0000058  1.9696 0.0040  I   -42.606     .560    -4.778     .109   .154140   .203490   .2490330   -42.100    -4.100  
+971213 50795.00 I   .151960  .000160   .201840  .000174  I  .2471484  .0000055  1.7943 0.0047  I   -42.494     .375    -4.990     .298   .152290   .202230   .2471530   -42.200    -4.300  
+971214 50796.00 I   .149526  .000143   .200084  .000214  I  .2454378  .0000074  1.6339 0.0038  I   -42.261     .791    -4.916     .298   .149870   .200740   .2454510   -42.200    -4.400  
+971215 50797.00 I   .146669  .000119   .198079  .000168  I  .2438609  .0000052  1.5325 0.0046  I   -41.983     .791    -4.655     .298   .146680   .198370   .2438760   -42.000    -4.400  
+971216 50798.00 I   .143768  .000116   .195933  .000171  I  .2423544  .0000054  1.4862 0.0040  I   -41.722     .791    -4.447     .298   .143740   .196060   .2423610   -41.800    -4.400  
+971217 50799.00 I   .141075  .000119   .193902  .000158  I  .2408754  .0000060  1.4792 0.0048  I   -41.476     .791    -4.454     .298   .141160   .194160   .2408750   -41.500    -4.400  
+971218 50800.00 I   .138876  .000106   .192194  .000152  I  .2393864  .0000079  1.5008 0.0048  I   -41.221     .791    -4.656     .298   .139040   .192400   .2393930   -41.200    -4.400  
+971219 50801.00 I   .137047  .000112   .190980  .000155  I  .2378658  .0000076  1.5462 0.0056  I   -40.967     .791    -4.871     .298   .137340   .191070   .2378620   -41.000    -4.200  
+971220 50802.00 I   .134949  .000111   .190057  .000154  I  .2362873  .0000078  1.6115 0.0053  I   -40.779     .791    -4.977     .298   .135090   .190480   .2362660   -40.900    -4.200  
+971221 50803.00 I   .132348  .000123   .189130  .000155  I  .2346470  .0000075  1.6640 0.0060  I   -40.730     .301    -4.984     .125   .132320   .189640   .2346450   -40.900    -4.100  
+971222 50804.00 I   .129498  .000142   .188011  .000183  I  .2329639  .0000091  1.7025 0.0058  I   -40.851     .296    -4.928     .119   .129690   .188190   .2329880   -41.000    -4.100  
+971223 50805.00 I   .126543  .000131   .186609  .000184  I  .2312498  .0000088  1.7176 0.0055  I   -41.124     .296    -4.778     .119   .126820   .186830   .2312730   -41.300    -4.100  
+971224 50806.00 I   .123555  .000132   .184907  .000171  I  .2295451  .0000062  1.6837 0.0055  I   -41.502     .296    -4.467     .119   .123590   .185080   .2295430   -41.600    -4.200  
+971225 50807.00 I   .120723  .000124   .183142  .000166  I  .2278943  .0000065  1.6143 0.0042  I   -41.843     .296    -4.114     .119   .120750   .183220   .2278720   -41.800    -4.400  
+971226 50808.00 I   .118041  .000125   .181462  .000170  I  .2263238  .0000058  1.5231 0.0045  I   -42.089     .296    -3.801     .119   .118120   .181490   .2263070   -42.100    -4.500  
+971227 50809.00 I   .115429  .000087   .179926  .000125  I  .2248520  .0000063  1.4203 0.0040  I   -42.204     .292    -3.644     .112   .115510   .179870   .2248460   -42.200    -4.500  
+971228 50810.00 I   .112782  .000088   .178571  .000111  I  .2234795  .0000054  1.3285 0.0042  I   -42.139     .791    -3.756     .298   .112950   .178530   .2234750   -42.200    -4.600  
+971229 50811.00 I   .110042  .000095   .177409  .000110  I  .2221795  .0000055  1.2833 0.0039  I   -41.895     .137    -4.090     .298   .110410   .177530   .2221700   -42.000    -4.500  
+971230 50812.00 I   .107282  .000105   .176420  .000120  I  .2208913  .0000055  1.3029 0.0037  I   -41.541     .137    -4.423     .298   .107600   .176500   .2208800   -41.800    -4.500  
+971231 50813.00 I   .104669  .000106   .175520  .000121  I  .2195567  .0000050  1.3734 0.0041  I   -41.195     .137    -4.529     .298   .104840   .175500   .2195510   -41.500    -4.400  
+98 1 1 50814.00 I   .102330  .000113   .174610  .000130  I  .2181268  .0000062  1.4968 0.0040  I   -40.962     .137    -4.383     .298   .102620   .174590   .2181430   -40.900    -4.300  
+98 1 2 50815.00 I   .100067  .000111   .173756  .000125  I  .2165474  .0000063  1.6672 0.0048  I   -40.873     .137    -4.154     .298   .100400   .173810   .2165920   -40.700    -4.200  
+98 1 3 50816.00 I   .097717  .000110   .173046  .000119  I  .2147880  .0000074  1.8510 0.0080  I   -40.872     .137    -4.018     .298   .097860   .173110   .2148370   -40.500    -4.200  
+98 1 4 50817.00 I   .095308  .000125   .172486  .000151  I  .2128524  .0000148  2.0140 0.0064  I   -40.876     .791    -4.010     .298   .095580   .172660   .2128680   -40.400    -4.100  
+98 1 5 50818.00 I   .092881  .000076   .172032  .000104  I  .2107892  .0000104  2.0893 0.0094  I   -40.869     .791    -4.068     .298   .093160   .172300   .2107640   -40.500    -4.100  
+98 1 6 50819.00 I   .090425  .000082   .171596  .000107  I  .2087156  .0000116  2.0391 0.0073  I   -40.929     .791    -4.136     .298   .090530   .171710   .2086890   -40.600    -4.100  
+98 1 7 50820.00 I   .087912  .000087   .171078  .000123  I  .2067344  .0000102  1.9187 0.0078  I   -41.141     .791    -4.226     .298   .088120   .171270   .2067320   -40.800    -4.300  
+98 1 8 50821.00 I   .085272  .000073   .170438  .000113  I  .2048885  .0000105  1.7672 0.0066  I   -41.482     .791    -4.375     .298   .085520   .170630   .2048730   -41.200    -4.300  
+98 1 9 50822.00 I   .082407  .000089   .169723  .000115  I  .2032072  .0000084  1.5940 0.0065  I   -41.800     .791    -4.566     .298   .082510   .169920   .2031800   -41.500    -4.300  
+98 110 50823.00 I   .079324  .000146   .169046  .000104  I  .2016899  .0000078  1.4528 0.0056  I   -41.925     .791    -4.700     .298   .079420   .168960   .2016870   -41.700    -4.400  
+98 111 50824.00 I   .076072  .000175   .168515  .000120  I  .2002746  .0000074  1.3928 0.0047  I   -41.828     .791    -4.677     .298   .076390   .168470   .2002920   -41.700    -4.300  
+98 112 50825.00 I   .072675  .000164   .168147  .000132  I  .1988820  .0000054  1.3996 0.0045  I   -41.652     .791    -4.508     .298   .072880   .168310   .1988680   -41.700    -4.300  
+98 113 50826.00 I   .069398  .000165   .167910  .000141  I  .1974576  .0000052  1.4598 0.0037  I   -41.555     .791    -4.315     .298   .069500   .167940   .1974300   -41.600    -4.200  
+98 114 50827.00 I   .066566  .000164   .167768  .000128  I  .1959508  .0000050  1.5547 0.0037  I   -41.530     .791    -4.216     .298   .066770   .167790   .1959580   -41.300    -4.100  
+98 115 50828.00 I   .063657  .000165   .167608  .000131  I  .1943544  .0000052  1.6311 0.0034  I   -41.436     .791    -4.261     .298   .063900   .167680   .1943530   -41.100    -4.000  
+98 116 50829.00 I   .060477  .000169   .167464  .000144  I  .1927001  .0000047  1.6730 0.0038  I   -41.243     .791    -4.363     .298   .060510   .167550   .1926850   -41.000    -3.900  
+98 117 50830.00 I   .057260  .000124   .167422  .000157  I  .1910127  .0000055  1.7019 0.0050  I   -41.092     .791    -4.439     .298   .057290   .167510   .1910200   -41.000    -3.900  
+98 118 50831.00 I   .054151  .000098   .167516  .000142  I  .1892952  .0000089  1.7342 0.0044  I   -41.102     .791    -4.498     .298   .054110   .167560   .1893100   -41.000    -4.100  
+98 119 50832.00 I   .051100  .000093   .167743  .000212  I  .1875474  .0000069  1.7574 0.0057  I   -41.230     .791    -4.579     .298   .051120   .167890   .1875500   -41.100    -4.300  
+98 120 50833.00 I   .047984  .000098   .167986  .000188  I  .1857901  .0000072  1.7517 0.0051  I   -41.383     .791    -4.688     .298   .048350   .168320   .1857890   -41.200    -4.500  
+98 121 50834.00 I   .044715  .000094   .168028  .000189  I  .1840492  .0000076  1.7304 0.0051  I   -41.575     .791    -4.776     .298   .044980   .168210   .1840490   -41.400    -4.700  
+98 122 50835.00 I   .041334  .000141   .167746  .000194  I  .1823291  .0000072  1.7098 0.0053  I   -41.846     .791    -4.761     .298   .041680   .167720   .1823160   -41.500    -4.900  
+98 123 50836.00 I   .037958  .000129   .167314  .000200  I  .1806273  .0000074  1.6963 0.0054  I   -42.097     .791    -4.600     .298   .038150   .167320   .1806180   -41.600    -5.000  
+98 124 50837.00 I   .034688  .000147   .166906  .000193  I  .1789316  .0000080  1.6976 0.0061  I   -42.179     .791    -4.367     .298   .034730   .167260   .1789340   -41.600    -5.100  
+98 125 50838.00 I   .031556  .000204   .166612  .000198  I  .1772322  .0000097  1.6985 0.0062  I   -42.109     .252    -4.251     .298   .031770   .167010   .1772150   -41.500    -5.100  
+98 126 50839.00 I   .028551  .000255   .166534  .000136  I  .1755271  .0000096  1.7217 0.0065  I   -42.024     .325    -4.396     .298   .028770   .166600   .1754970   -41.600    -5.100  
+98 127 50840.00 I   .025795  .000237   .166733  .000149  I  .1737632  .0000087  1.8216 0.0069  I   -41.932     .309    -4.717     .298   .025910   .166860   .1737480   -41.600    -5.000  
+98 128 50841.00 I   .023234  .000233   .167166  .000172  I  .1718530  .0000098  2.0142 0.0066  I   -41.669     .309    -4.952     .298   .023200   .167300   .1718700   -41.700    -4.900  
+98 129 50842.00 I   .020394  .000227   .167717  .000153  I  .1697221  .0000099  2.2450 0.0069  I   -41.232     .309    -4.896     .298   .020430   .167790   .1697400   -41.700    -4.600  
+98 130 50843.00 I   .017343  .000215   .168286  .000145  I  .1673762  .0000096  2.4363 0.0073  I   -40.858     .309    -4.609     .298   .017520   .168400   .1673530   -41.800    -4.500  
+98 131 50844.00 I   .014234  .000225   .168811  .000174  I  .1648804  .0000108  2.5347 0.0070  I   -40.815     .324    -4.312     .298   .014380   .168980   .1648510   -41.900    -4.300  
+98 2 1 50845.00 I   .011108  .000100   .169359  .000193  I  .1623325  .0000103  2.5558 0.0073  I   -41.100     .288    -4.186     .298   .011350   .169560   .1623420   -41.800    -4.300  
+98 2 2 50846.00 I   .007955  .000132   .170019  .000191  I  .1597821  .0000098  2.5371 0.0071  I   -41.504     .236    -4.230     .298   .007820   .170180   .1597890   -41.800    -4.200  
+98 2 3 50847.00 I   .004686  .000139   .170837  .000204  I  .1572725  .0000099  2.4757 0.0070  I   -41.792     .210    -4.374     .298   .004450   .170980   .1572640   -41.800    -4.300  
+98 2 4 50848.00 I   .001321  .000137   .171691  .000178  I  .1548339  .0000099  2.4045 0.0072  I   -41.848     .210    -4.585     .298   .001740   .171850   .1548260   -41.700    -4.500  
+98 2 5 50849.00 I  -.001925  .000138   .172410  .000177  I  .1524679  .0000105  2.3200 0.0073  I   -41.771     .210    -4.780     .298  -.001740   .172650   .1524600   -41.700    -4.700  
+98 2 6 50850.00 I  -.004907  .000126   .173114  .000172  I  .1502065  .0000106  2.1976 0.0071  I   -41.668     .126    -4.940     .298  -.005010   .173440   .1501780   -41.600    -4.800  
+98 2 7 50851.00 I  -.007577  .000105   .173869  .000152  I  .1480662  .0000096  2.0947 0.0075  I   -41.528     .126    -5.048     .298  -.007560   .174140   .1480560   -41.500    -5.000  
+98 2 8 50852.00 I  -.010035  .000090   .174566  .000151  I  .1459967  .0000107  2.0529 0.0067  I   -41.311     .177    -5.089     .298  -.009850   .174770   .1460250   -41.400    -5.100  
+98 2 9 50853.00 I  -.012460  .000097   .175079  .000142  I  .1439594  .0000093  2.0142 0.0071  I   -41.075     .791    -5.100     .298  -.012370   .175200   .1439480   -41.300    -5.200  
+98 210 50854.00 I  -.015089  .000090   .175334  .000147  I  .1419780  .0000092  1.9465 0.0063  I   -40.931     .791    -5.144     .298  -.014930   .175270   .1419500   -41.200    -5.300  
+98 211 50855.00 I  -.017954  .000089   .175401  .000148  I  .1400520  .0000085  1.9221 0.0062  I   -40.897     .791    -5.254     .298  -.017950   .175420   .1400530   -41.100    -5.200  
+98 212 50856.00 I  -.020654  .000094   .175617  .000154  I  .1381159  .0000084  1.9516 0.0053  I   -40.867     .791    -5.403     .298  -.020750   .175750   .1381030   -41.100    -5.300  
+98 213 50857.00 I  -.023038  .000090   .176036  .000150  I  .1361486  .0000062  1.9818 0.0058  I   -40.806     .791    -5.533     .298  -.022900   .176290   .1361190   -41.100    -5.300  
+98 214 50858.00 I  -.025089  .000118   .176594  .000151  I  .1341574  .0000080  1.9969 0.0053  I   -40.836     .791    -5.620     .298  -.025110   .176620   .1341540   -41.100    -5.200  
+98 215 50859.00 I  -.026885  .000111   .177371  .000136  I  .1321610  .0000086  1.9935 0.0052  I   -41.044     .791    -5.694     .298  -.026860   .177210   .1321700   -41.200    -5.300  
+98 216 50860.00 I  -.028529  .000171   .178429  .000123  I  .1301747  .0000067  1.9773 0.0081  I   -41.337     .791    -5.766     .298  -.028500   .178670   .1302110   -41.300    -5.300  
+98 217 50861.00 I  -.030138  .000190   .179743  .000109  I  .1282129  .0000137  1.9415 0.0082  I   -41.576     .791    -5.835     .298  -.030170   .179970   .1282310   -41.400    -5.600  
+98 218 50862.00 I  -.032005  .000202   .181204  .000103  I  .1263079  .0000149  1.8572 0.0104  I   -41.767     .791    -5.900     .298  -.031880   .181340   .1262970   -41.600    -5.700  
+98 219 50863.00 I  -.034594  .000199   .182632  .000110  I  .1244965  .0000157  1.7789 0.0107  I   -41.950     .791    -5.932     .298  -.034580   .182820   .1244970   -41.800    -5.900  
+98 220 50864.00 I  -.037751  .000197   .183914  .000100  I  .1227247  .0000153  1.7767 0.0109  I   -41.988     .791    -5.839     .298  -.037650   .184250   .1227710   -41.900    -6.200  
+98 221 50865.00 I  -.041186  .000192   .185022  .000103  I  .1209348  .0000151  1.7994 0.0105  I   -41.714     .791    -5.577     .298  -.040900   .185400   .1210210   -41.800    -6.400  
+98 222 50866.00 I  -.044703  .000143   .185960  .000109  I  .1191234  .0000144  1.8295 0.0087  I   -41.280     .791    -5.296     .298  -.044630   .186210   .1191930   -41.800    -6.500  
+98 223 50867.00 I  -.047998  .000131   .186807  .000109  I  .1172605  .0000085  1.9055 0.0088  I   -41.081     .229    -5.276     .298  -.048200   .186940   .1172860   -41.700    -6.400  
+98 224 50868.00 I  -.050931  .000139   .187634  .000118  I  .1152941  .0000100  2.0362 0.0066  I   -41.243     .229    -5.624     .298  -.051200   .187930   .1152930   -41.400    -6.300  
+98 225 50869.00 I  -.053569  .000134   .188438  .000112  I  .1131771  .0000101  2.1997 0.0073  I   -41.415     .229    -6.106     .298  -.053470   .188800   .1131760   -41.300    -6.200  
+98 226 50870.00 I  -.055810  .000128   .189277  .000117  I  .1108978  .0000106  2.3538 0.0074  I   -41.196     .229    -6.323     .298  -.055720   .189430   .1109010   -41.200    -6.000  
+98 227 50871.00 I  -.057486  .000137   .190283  .000119  I  .1084770  .0000109  2.4855 0.0076  I   -40.664     .229    -6.183     .298  -.057560   .190280   .1084740   -41.300    -5.800  
+98 228 50872.00 I  -.058657  .000135   .191598  .000113  I  .1059310  .0000108  2.6046 0.0094  I   -40.261     .277    -5.936     .298  -.058660   .191770   .1059310   -41.200    -5.800  
+98 3 1 50873.00 I  -.059602  .000103   .193205  .000109  I  .1032905  .0000154  2.6554 0.0076  I   -40.292     .791    -5.822     .298  -.059380   .193340   .1033060   -41.300    -5.700  
+98 3 2 50874.00 I  -.060660  .000087   .194960  .000136  I  .1006586  .0000108  2.5909 0.0086  I   -40.673     .791    -5.862     .298  -.060390   .194970   .1006710   -41.300    -5.800  
+98 3 3 50875.00 I  -.062008  .000077   .196729  .000124  I  .0981386  .0000077  2.4367 0.0062  I   -41.088     .791    -5.956     .298  -.061790   .196830   .0981390   -41.300    -5.900  
+98 3 4 50876.00 I  -.063592  .000074   .198476  .000115  I  .0957946  .0000060  2.2542 0.0049  I   -41.276     .791    -6.067     .298  -.063460   .198530   .0957850   -41.200    -6.100  
+98 3 5 50877.00 I  -.065267  .000080   .200360  .000110  I  .0936210  .0000062  2.0992 0.0045  I   -41.195     .791    -6.227     .298  -.065140   .200500   .0935970   -41.200    -6.300  
+98 3 6 50878.00 I  -.066905  .000067   .202319  .000108  I  .0915841  .0000067  1.9806 0.0049  I   -41.001     .791    -6.417     .298  -.066730   .202460   .0915420   -41.000    -6.500  
+98 3 7 50879.00 I  -.068490  .000066   .204312  .000108  I  .0896482  .0000076  1.8969 0.0059  I   -40.864     .791    -6.560     .298  -.068240   .204350   .0895940   -40.700    -6.700  
+98 3 8 50880.00 I  -.070085  .000086   .206386  .000066  I  .0877786  .0000098  1.8483 0.0057  I   -40.799     .791    -6.628     .298  -.070080   .206330   .0877340   -40.500    -6.800  
+98 3 9 50881.00 I  -.071696  .000104   .208509  .000068  I  .0859377  .0000085  1.8416 0.0059  I   -40.701     .791    -6.676     .298  -.071740   .208600   .0859110   -40.300    -6.800  
+98 310 50882.00 I  -.073337  .000111   .210604  .000120  I  .0840788  .0000066  1.8849 0.0054  I   -40.530     .791    -6.748     .298  -.073230   .210690   .0840630   -40.100    -6.800  
+98 311 50883.00 I  -.074912  .000123   .212602  .000121  I  .0821452  .0000066  1.9965 0.0046  I   -40.360     .791    -6.807     .298  -.074840   .212610   .0821340   -40.100    -6.700  
+98 312 50884.00 I  -.076183  .000114   .214536  .000116  I  .0800910  .0000064  2.0925 0.0045  I   -40.252     .791    -6.791     .298  -.076150   .214770   .0801100   -40.200    -6.600  
+98 313 50885.00 I  -.077239  .000124   .216649  .000119  I  .0779831  .0000061  2.1197 0.0044  I   -40.181     .791    -6.707     .298  -.077210   .216810   .0780040   -40.400    -6.500  
+98 314 50886.00 I  -.078422  .000136   .218857  .000119  I  .0758586  .0000059  2.1257 0.0039  I   -40.158     .791    -6.655     .298  -.078270   .219010   .0758610   -40.500    -6.500  
+98 315 50887.00 I  -.080159  .000123   .220952  .000138  I  .0737412  .0000048  2.1031 0.0045  I   -40.221     .106    -6.703     .298  -.079990   .221170   .0737280   -40.600    -6.500  
+98 316 50888.00 I  -.082383  .000121   .222816  .000107  I  .0716611  .0000068  2.0544 0.0040  I   -40.319     .791    -6.811     .298  -.082370   .222800   .0716340   -40.700    -6.600  
+98 317 50889.00 I  -.084734  .000121   .224483  .000123  I  .0696389  .0000063  1.9862 0.0042  I   -40.378     .791    -6.915     .298  -.084700   .224290   .0696090   -40.600    -6.800  
+98 318 50890.00 I  -.086987  .000126   .226085  .000126  I  .0676945  .0000048  1.9006 0.0042  I   -40.443     .791    -7.026     .298  -.086850   .226100   .0676700   -40.400    -7.000  
+98 319 50891.00 I  -.089008  .000130   .227692  .000133  I  .0658367  .0000055  1.8181 0.0036  I   -40.573     .791    -7.176     .298  -.088830   .227490   .0658220   -40.200    -7.100  
+98 320 50892.00 I  -.090879  .000139   .229385  .000141  I  .0640498  .0000053  1.7609 0.0042  I   -40.611     .791    -7.293     .298  -.090580   .229270   .0640470   -39.900    -7.300  
+98 321 50893.00 I  -.092870  .000157   .231116  .000134  I  .0623018  .0000064  1.7428 0.0044  I   -40.309     .791    -7.236     .298  -.092640   .231340   .0623090   -39.700    -7.400  
+98 322 50894.00 I  -.094860  .000153   .232676  .000110  I  .0605486  .0000069  1.7716 0.0041  I   -39.756     .791    -7.022     .298  -.094790   .232860   .0605620   -39.500    -7.400  
+98 323 50895.00 I  -.096558  .000146   .234047  .000099  I  .0587419  .0000050  1.8506 0.0047  I   -39.397     .145    -6.895     .298  -.096640   .234260   .0587590   -39.500    -7.400  
+98 324 50896.00 I  -.097957  .000140   .235445  .000099  I  .0568313  .0000063  1.9780 0.0043  I   -39.491     .149    -7.066     .298  -.097950   .235530   .0568400   -39.600    -7.300  
+98 325 50897.00 I  -.099289  .000141   .237069  .000085  I  .0547597  .0000070  2.1842 0.0051  I   -39.743     .149    -7.426     .298  -.099210   .237070   .0547480   -39.800    -7.300  
+98 326 50898.00 I  -.100687  .000151   .238870  .000088  I  .0524515  .0000079  2.4248 0.0053  I   -39.699     .149    -7.644     .298  -.100620   .239000   .0524510   -39.900    -7.200  
+98 327 50899.00 I  -.102256  .000142   .240823  .000094  I  .0499414  .0000079  2.5714 0.0060  I   -39.350     .149    -7.571     .298  -.102090   .240920   .0499410   -40.100    -7.100  
+98 328 50900.00 I  -.104010  .000132   .242915  .000090  I  .0473499  .0000089  2.5942 0.0076  I   -39.095     .165    -7.379     .298  -.103850   .242890   .0473420   -40.300    -7.100  
+98 329 50901.00 I  -.105925  .000136   .245145  .000100  I  .0447784  .0000131  2.5408 0.0085  I   -39.277     .157    -7.307     .298  -.105760   .245180   .0447980   -40.400    -7.100  
+98 330 50902.00 I  -.107733  .000123   .247444  .000093  I  .0422919  .0000145  2.4168 0.0097  I   -39.840     .337    -7.389     .298  -.107670   .247570   .0423000   -40.400    -7.300  
+98 331 50903.00 I  -.109077  .000114   .249741  .000098  I  .0399650  .0000142  2.2323 0.0097  I   -40.383     .362    -7.530     .298  -.109050   .249770   .0399470   -40.300    -7.500  
+98 4 1 50904.00 I  -.109935  .000111   .252103  .000095  I  .0378239  .0000129  2.0578 0.0093  I   -40.478     .362    -7.721     .298  -.109830   .252060   .0378020   -40.100    -7.700  
+98 4 2 50905.00 I  -.110527  .000083   .254548  .000079  I  .0358353  .0000120  1.9254 0.0084  I   -40.005     .362    -8.040     .298  -.110280   .254420   .0358140   -39.900    -8.000  
+98 4 3 50906.00 I  -.111154  .000073   .256961  .000079  I  .0339580  .0000109  1.8384 0.0082  I   -39.385     .362    -8.425     .298  -.110870   .256870   .0339240   -39.700    -8.200  
+98 4 4 50907.00 I  -.112007  .000086   .259254  .000094  I  .0321401  .0000112  1.8066 0.0084  I   -39.175     .362    -8.682     .298  -.111810   .259280   .0321020   -39.500    -8.300  
+98 4 5 50908.00 I  -.112987  .000120   .261411  .000091  I  .0303301  .0000127  1.8188 0.0081  I   -39.426     .386    -8.722     .298  -.112870   .261520   .0303230   -39.300    -8.300  
+98 4 6 50909.00 I  -.113778  .000166   .263513  .000111  I  .0284947  .0000117  1.8544 0.0084  I   -39.763     .203    -8.616     .298  -.113770   .263420   .0285300   -39.300    -8.300  
+98 4 7 50910.00 I  -.114131  .000163   .265742  .000152  I  .0266181  .0000111  1.8996 0.0081  I   -39.820     .167    -8.467     .298  -.114090   .265490   .0266580   -39.400    -8.300  
+98 4 8 50911.00 I  -.114147  .000163   .268209  .000160  I  .0246935  .0000112  1.9507 0.0078  I   -39.588     .167    -8.277     .298  -.114030   .268270   .0247080   -39.500    -8.100  
+98 4 9 50912.00 I  -.113999  .000165   .270830  .000160  I  .0227298  .0000111  1.9623 0.0078  I   -39.282     .167    -8.007     .298  -.113910   .270980   .0227410   -39.600    -8.000  
+98 410 50913.00 I  -.113829  .000164   .273649  .000153  I  .0207804  .0000109  1.9392 0.0075  I   -39.061     .167    -7.717     .298  -.113910   .273640   .0207910   -39.700    -7.900  
+98 411 50914.00 I  -.113728  .000177   .276606  .000148  I  .0188422  .0000102  1.9437 0.0070  I   -38.940     .270    -7.557     .298  -.113670   .276770   .0188450   -39.900    -7.800  
+98 412 50915.00 I  -.113850  .000138   .279529  .000145  I  .0168902  .0000088  1.9565 0.0061  I   -38.906     .323    -7.612     .298  -.113640   .279590   .0168970   -39.900    -7.800  
+98 413 50916.00 I  -.114218  .000141   .282316  .000112  I  .0149437  .0000068  1.9257 0.0057  I   -38.984     .383    -7.808     .298  -.114090   .282260   .0149670   -39.900    -7.800  
+98 414 50917.00 I  -.114694  .000144   .284973  .000101  I  .0130558  .0000074  1.8438 0.0048  I   -39.226     .383    -8.019     .298  -.114540   .285160   .0130720   -39.800    -8.000  
+98 415 50918.00 I  -.115071  .000147   .287594  .000099  I  .0112541  .0000067  1.7678 0.0051  I   -39.680     .383    -8.204     .298  -.114800   .287640   .0112440   -39.600    -8.100  
+98 416 50919.00 I  -.114962  .000153   .290211  .000098  I  .0095180  .0000069  1.6983 0.0049  I   -40.211     .383    -8.376     .298  -.114880   .290140   .0095240   -39.200    -8.300  
+98 417 50920.00 I  -.114593  .000156   .292907  .000094  I  .0078497  .0000072  1.6521 0.0055  I   -40.640     .293    -8.529     .298  -.114520   .292890   .0078650   -38.900    -8.400  
+98 418 50921.00 I  -.114123  .000135   .295738  .000096  I  .0061926  .0000085  1.6695 0.0058  I   -40.732     .337    -8.569     .298  -.113800   .295860   .0061990   -38.600    -8.500  
+98 419 50922.00 I  -.113765  .000095   .298599  .000096  I  .0044955  .0000092  1.7326 0.0062  I   -40.401     .377    -8.438     .298  -.113500   .298690   .0044940   -38.500    -8.500  
+98 420 50923.00 I  -.113651  .000105   .301376  .000113  I  .0027115  .0000089  1.8435 0.0062  I   -39.886     .626    -8.255     .298  -.113460   .301360   .0027230   -38.400    -8.500  
+98 421 50924.00 I  -.113687  .000096   .304101  .000110  I  .0007922  .0000082  2.0033 0.0060  I   -39.482     .542    -8.204     .298  -.113590   .304190   .0008070   -38.500    -8.400  
+98 422 50925.00 I  -.113745  .000092   .306874  .000121  I -.0013031  .0000080  2.1872 0.0058  I   -39.217     .542    -8.300     .298  -.113720   .307070  -.0012960   -38.800    -8.300  
+98 423 50926.00 I  -.113785  .000082   .309763  .000124  I -.0035829  .0000082  2.3732 0.0056  I   -39.031     .542    -8.347     .298  -.113540   .309850  -.0035750   -39.200    -8.100  
+98 424 50927.00 I  -.113731  .000085   .312527  .000127  I -.0060392  .0000077  2.5285 0.0056  I   -38.874     .587    -8.235     .298  -.113670   .312610  -.0060240   -39.600    -8.100  
+98 425 50928.00 I  -.113542  .000083   .314955  .000126  I -.0086030  .0000075  2.5733 0.0053  I   -38.863     .587    -8.093     .298  -.113670   .315030  -.0085900   -39.900    -8.000  
+98 426 50929.00 I  -.113192  .000051   .317088  .000093  I -.0111380  .0000074  2.4748 0.0060  I   -39.145     .791    -8.093     .298  -.113000   .317070  -.0111280   -40.200    -8.000  
+98 427 50930.00 I  -.112849  .000081   .319179  .000117  I -.0135214  .0000093  2.2828 0.0062  I   -39.657     .791    -8.207     .298  -.112520   .319060  -.0135040   -40.200    -8.100  
+98 428 50931.00 I  -.112779  .000081   .321423  .000099  I -.0156958  .0000099  2.0673 0.0064  I   -40.104     .791    -8.288     .298  -.112730   .321280  -.0156750   -40.200    -8.200  
+98 429 50932.00 I  -.113003  .000070   .323784  .000094  I -.0176699  .0000089  1.8934 0.0065  I   -40.145     .791    -8.321     .298  -.113080   .323640  -.0176610   -40.000    -8.400  
+98 430 50933.00 I  -.113272  .000070   .326044  .000083  I -.0195105  .0000085  1.8032 0.0064  I   -39.678     .791    -8.452     .298  -.113090   .326010  -.0195140   -39.900    -8.500  
+98 5 1 50934.00 I  -.113419  .000076   .328142  .000084  I -.0212989  .0000091  1.7809 0.0055  I   -39.036     .791    -8.741     .298  -.113480   .328220  -.0213010   -39.600    -8.700  
+98 5 2 50935.00 I  -.113532  .000086   .330140  .000083  I -.0230801  .0000069  1.7821 0.0073  I   -38.752     .151    -9.045     .298  -.113460   .330150  -.0230680   -39.400    -8.800  
+98 5 3 50936.00 I  -.113724  .000063   .332146  .000070  I -.0248627  .0000115  1.7822 0.0060  I   -39.008     .203    -9.187     .298  -.113500   .332250  -.0248360   -39.400    -8.900  
+98 5 4 50937.00 I  -.113999  .000076   .334250  .000100  I -.0266435  .0000097  1.7793 0.0072  I   -39.441     .430    -9.146     .298  -.113900   .334350  -.0266060   -39.400    -8.800  
+98 5 5 50938.00 I  -.114283  .000077   .336511  .000100  I -.0284218  .0000086  1.7779 0.0065  I   -39.601     .373    -9.007     .298  -.114060   .336460  -.0283880   -39.500    -8.700  
+98 5 6 50939.00 I  -.114503  .000074   .338910  .000102  I -.0302130  .0000086  1.8177 0.0060  I   -39.484     .373    -8.819     .298  -.114270   .338950  -.0301970   -39.600    -8.600  
+98 5 7 50940.00 I  -.114596  .000078   .341219  .000098  I -.0320567  .0000083  1.8561 0.0060  I   -39.383     .373    -8.633     .298  -.114420   .341170  -.0320350   -39.800    -8.500  
+98 5 8 50941.00 I  -.114527  .000073   .343367  .000094  I -.0339048  .0000083  1.8333 0.0059  I   -39.509     .414    -8.437     .298  -.114350   .343360  -.0338790   -40.100    -8.400  
+98 5 9 50942.00 I  -.114308  .000066   .345406  .000088  I -.0357187  .0000085  1.7968 0.0048  I   -39.774     .414    -8.301     .298  -.114230   .345460  -.0357040   -40.200    -8.400  
+98 510 50943.00 I  -.113923  .000064   .347417  .000060  I -.0374953  .0000050  1.7510 0.0050  I   -39.995     .791    -8.307     .298  -.113610   .347380  -.0374910   -40.300    -8.400  
+98 511 50944.00 I  -.113420  .000059   .349476  .000043  I -.0392108  .0000052  1.6757 0.0031  I   -40.117     .791    -8.424     .298  -.113120   .349430  -.0392160   -40.200    -8.400  
+98 512 50945.00 I  -.112913  .000064   .351594  .000043  I -.0408403  .0000038  1.5814 0.0036  I   -40.162     .791    -8.554     .298  -.112850   .351680  -.0408540   -40.000    -8.600  
+98 513 50946.00 I  -.112428  .000064   .353738  .000046  I -.0423730  .0000049  1.4853 0.0039  I   -40.147     .791    -8.644     .298  -.112340   .353770  -.0423860   -39.800    -8.700  
+98 514 50947.00 I  -.111946  .000060   .355832  .000045  I -.0438200  .0000069  1.4165 0.0042  I   -40.133     .791    -8.716     .298  -.111790   .355760  -.0438250   -39.400    -8.700  
+98 515 50948.00 I  -.111435  .000061   .357812  .000045  I -.0452267  .0000069  1.4100 0.0050  I   -40.186     .791    -8.797     .298  -.111280   .357820  -.0452220   -39.100    -8.700  
+98 516 50949.00 I  -.110968  .000058   .359665  .000050  I -.0466667  .0000071  1.4838 0.0052  I   -40.257     .791    -8.860     .298  -.110670   .359770  -.0466610   -38.700    -8.700  
+98 517 50950.00 I  -.110639  .000053   .361433  .000086  I -.0482169  .0000079  1.6253 0.0046  I   -40.187     .791    -8.854     .298  -.110410   .361540  -.0482240   -38.600    -8.700  
+98 518 50951.00 I  -.110376  .000062   .363189  .000111  I -.0499317  .0000060  1.8098 0.0067  I   -39.900     .378    -8.767     .298  -.110290   .363160  -.0499590   -38.700    -8.600  
+98 519 50952.00 I  -.110102  .000065   .365018  .000125  I -.0518421  .0000109  2.0111 0.0061  I   -39.516     .309    -8.630     .298  -.110140   .365110  -.0518730   -38.900    -8.500  
+98 520 50953.00 I  -.109967  .000063   .367001  .000125  I -.0539483  .0000106  2.1957 0.0075  I   -39.247     .309    -8.461     .298  -.109960   .367090  -.0539550   -39.300    -8.300  
+98 521 50954.00 I  -.109945  .000065   .369171  .000127  I -.0562109  .0000104  2.3126 0.0074  I   -39.244     .309    -8.261     .298  -.109810   .369190  -.0561900   -39.800    -8.200  
+98 522 50955.00 I  -.109673  .000079   .371698  .000127  I -.0585571  .0000104  2.3804 0.0073  I   -39.540     .309    -8.064     .298  -.109650   .371850  -.0585430   -40.300    -8.100  
+98 523 50956.00 I  -.109234  .000075   .374455  .000122  I -.0609492  .0000103  2.3805 0.0079  I   -40.078     .309    -8.007     .298  -.109220   .374630  -.0609400   -40.800    -8.100  
+98 524 50957.00 I  -.108731  .000069   .377218  .000099  I -.0632756  .0000118  2.2529 0.0067  I   -40.715     .791    -8.186     .298  -.108590   .377330  -.0632740   -41.100    -8.100  
+98 525 50958.00 I  -.108142  .000074   .379851  .000092  I -.0654284  .0000087  2.0455 0.0073  I   -41.260     .791    -8.483     .298  -.107930   .379900  -.0654430   -41.200    -8.300  
+98 526 50959.00 I  -.107668  .000073   .382295  .000092  I -.0673610  .0000086  1.8211 0.0064  I   -41.535     .791    -8.665     .298  -.107430   .382270  -.0673860   -41.200    -8.400  
+98 527 50960.00 I  -.107472  .000072   .384492  .000108  I -.0690754  .0000095  1.6109 0.0075  I   -41.425     .791    -8.644     .298  -.107250   .384510  -.0690950   -41.100    -8.500  
+98 528 50961.00 I  -.107423  .000062   .386358  .000125  I -.0705961  .0000124  1.4405 0.0081  I   -40.965     .791    -8.568     .298  -.107410   .386640  -.0706060   -40.900    -8.600  
+98 529 50962.00 I  -.107151  .000056   .387984  .000127  I -.0719801  .0000130  1.3411 0.0092  I   -40.441     .791    -8.616     .298  -.107110   .388050  -.0719760   -40.600    -8.700  
+98 530 50963.00 I  -.106549  .000057   .389639  .000126  I -.0733016  .0000137  1.3117 0.0082  I   -40.264     .791    -8.772     .298  -.106410   .389480  -.0732880   -40.500    -8.800  
+98 531 50964.00 I  -.105883  .000054   .391519  .000103  I -.0746174  .0000099  1.3241 0.0080  I   -40.588     .791    -8.883     .298  -.105720   .391520  -.0746120   -40.400    -8.900  
+98 6 1 50965.00 I  -.105316  .000050   .393568  .000109  I -.0759485  .0000081  1.3327 0.0065  I   -41.107     .108    -8.865     .298  -.105150   .393650  -.0759530   -40.400    -8.800  
+98 6 2 50966.00 I  -.104823  .000055   .395623  .000097  I -.0772754  .0000085  1.3190 0.0053  I   -41.375     .108    -8.773     .298  -.104610   .395670  -.0772840   -40.700    -8.800  
+98 6 3 50967.00 I  -.104525  .000053   .397545  .000079  I -.0785861  .0000068  1.3039 0.0057  I   -41.311     .108    -8.683     .298  -.104580   .397600  -.0785930   -41.000    -8.700  
+98 6 4 50968.00 I  -.104589  .000055   .399252  .000086  I -.0798820  .0000076  1.2851 0.0048  I   -41.222     .108    -8.594     .298  -.104650   .399280  -.0798900   -41.500    -8.700  
+98 6 5 50969.00 I  -.104719  .000054   .400837  .000086  I -.0811497  .0000068  1.2466 0.0051  I   -41.360     .108    -8.470     .298  -.104610   .400860  -.0811560   -41.800    -8.500  
+98 6 6 50970.00 I  -.104591  .000055   .402402  .000087  I -.0823602  .0000067  1.1630 0.0054  I   -41.667     .108    -8.319     .298  -.104480   .402480  -.0823650   -42.200    -8.400  
+98 6 7 50971.00 I  -.104185  .000051   .403981  .000073  I -.0834622  .0000084  1.0389 0.0048  I   -41.952     .791    -8.190     .298  -.104060   .404030  -.0834740   -42.300    -8.400  
+98 6 8 50972.00 I  -.103655  .000047   .405577  .000069  I -.0844369  .0000069  0.9114 0.0053  I   -42.133     .791    -8.127     .298  -.103460   .405670  -.0844450   -42.400    -8.300  
+98 6 9 50973.00 I  -.103042  .000047   .407182  .000075  I -.0852883  .0000066  0.7938 0.0055  I   -42.198     .791    -8.147     .298  -.102880   .407220  -.0852860   -42.200    -8.200  
+98 610 50974.00 I  -.102217  .000050   .408801  .000072  I -.0860368  .0000086  0.7131 0.0059  I   -42.112     .791    -8.230     .298  -.102140   .408820  -.0860440   -41.900    -8.200  
+98 611 50975.00 I  -.101272  .000059   .410408  .000074  I -.0867308  .0000099  0.6813 0.0068  I   -41.898     .791    -8.318     .298  -.101130   .410530  -.0867380   -41.600    -8.100  
+98 612 50976.00 I  -.100513  .000063   .411926  .000077  I -.0874101  .0000106  0.6815 0.0071  I   -41.737     .791    -8.358     .298  -.100270   .412130  -.0873920   -41.200    -8.100  
+98 613 50977.00 I  -.100010  .000067   .413302  .000091  I -.0881062  .0000102  0.7188 0.0085  I   -41.806     .239    -8.341     .298  -.099840   .413470  -.0880890   -41.100    -8.000  
+98 614 50978.00 I  -.099407  .000072   .414567  .000098  I -.0888650  .0000133  0.8080 0.0082  I   -42.057     .334    -8.306     .298  -.099300   .414620  -.0888680   -41.100    -7.900  
+98 615 50979.00 I  -.098389  .000094   .415830  .000113  I -.0897238  .0000129  0.9019 0.0082  I   -42.265     .353    -8.274     .112  -.098200   .415820  -.0897280   -41.300    -7.900  
+98 616 50980.00 I  -.097022  .000098   .417175  .000110  I -.0906571  .0000097  0.9608 0.0079  I   -42.306     .318    -8.214     .298  -.096830   .417220  -.0906520   -41.700    -7.900  
+98 617 50981.00 I  -.095357  .000093   .418640  .000107  I -.0916396  .0000091  1.0022 0.0066  I   -42.294     .318    -8.064     .298  -.095290   .418670  -.0916240   -42.200    -7.800  
+98 618 50982.00 I  -.093646  .000092   .420329  .000110  I -.0926459  .0000089  0.9969 0.0064  I   -42.385     .318    -7.755     .298  -.093450   .420380  -.0926230   -42.900    -7.800  
+98 619 50983.00 I  -.091783  .000089   .421990  .000104  I -.0936208  .0000089  0.9539 0.0063  I   -42.737     .313    -7.381     .110  -.091580   .422120  -.0936100   -43.500    -7.900  
+98 620 50984.00 I  -.089921  .000082   .423490  .000101  I -.0945457  .0000090  0.8871 0.0051  I   -43.376     .271    -7.149     .115  -.089720   .423670  -.0945390   -44.000    -8.000  
+98 621 50985.00 I  -.088168  .000060   .424852  .000108  I -.0953771  .0000051  0.7668 0.0057  I   -44.109     .125    -7.200     .298  -.087960   .425010  -.0953740   -44.500    -8.000  
+98 622 50986.00 I  -.086454  .000066   .426143  .000102  I -.0960672  .0000071  0.6101 0.0048  I   -44.651     .791    -7.494     .114  -.086300   .426230  -.0960770   -44.700    -8.200  
+98 623 50987.00 I  -.084694  .000068   .427473  .000109  I -.0966007  .0000082  0.4635 0.0057  I   -44.835     .791    -7.869     .114  -.084560   .427490  -.0966180   -44.800    -8.300  
+98 624 50988.00 I  -.082934  .000075   .428940  .000114  I -.0970187  .0000090  0.3905 0.0061  I   -44.696     .791    -8.192     .114  -.082690   .428930  -.0970360   -44.600    -8.400  
+98 625 50989.00 I  -.081371  .000074   .430507  .000121  I -.0974038  .0000091  0.3838 0.0061  I   -44.427     .791    -8.360     .114  -.081120   .430630  -.0974240   -44.400    -8.500  
+98 626 50990.00 I  -.079860  .000077   .431951  .000122  I -.0977963  .0000083  0.4069 0.0067  I   -44.265     .139    -8.489     .298  -.079670   .432110  -.0978250   -44.100    -8.600  
+98 627 50991.00 I  -.078218  .000080   .433227  .000145  I -.0982229  .0000097  0.4457 0.0071  I   -44.404     .139    -8.676     .298  -.078070   .433380  -.0982420   -44.000    -8.700  
+98 628 50992.00 I  -.076251  .000088   .434408  .000137  I -.0986901  .0000114  0.4916 0.0069  I   -44.877     .506    -8.839     .298  -.076120   .434520  -.0986920   -44.000    -8.800  
+98 629 50993.00 I  -.073849  .000085   .435647  .000141  I -.0992107  .0000098  0.5513 0.0071  I   -45.473     .582    -8.861     .158  -.073650   .435640  -.0992050   -44.100    -8.800  
+98 630 50994.00 I  -.071100  .000086   .437082  .000153  I -.0997910  .0000086  0.6059 0.0065  I   -45.877     .511    -8.727     .139  -.070940   .437030  -.0997880   -44.400    -8.700  
+98 7 1 50995.00 I  -.068239  .000082   .438694  .000153  I -.1004131  .0000085  0.6322 0.0061  I   -45.942     .511    -8.503     .139  -.068160   .438840  -.1004110   -44.800    -8.700  
+98 7 2 50996.00 I  -.065567  .000082   .440347  .000157  I -.1010373  .0000086  0.6041 0.0056  I   -45.929     .511    -8.285     .139  -.065400   .440690  -.1010300   -45.200    -8.400  
+98 7 3 50997.00 I  -.063009  .000079   .441996  .000130  I -.1016024  .0000073  0.5193 0.0049  I   -45.994     .511    -8.101     .139  -.062830   .442190  -.1015890   -45.700    -8.200  
+98 7 4 50998.00 I  -.060511  .000080   .443674  .000135  I -.1020711  .0000049  0.4202 0.0043  I   -46.149     .513    -7.903     .158  -.060370   .443770  -.1020530   -46.000    -8.000  
+98 7 5 50999.00 I  -.057993  .000063   .445381  .000155  I -.1024447  .0000046  0.3268 0.0042  I   -46.368     .168    -7.676     .298  -.057850   .445490  -.1024230   -46.300    -7.800  
+98 7 6 51000.00 I  -.055404  .000098   .447048  .000156  I -.1027229  .0000069  0.2281 0.0042  I   -46.595     .791    -7.491     .298  -.055190   .447270  -.1027270   -46.900    -7.800  
+98 7 7 51001.00 I  -.052822  .000104   .448568  .000155  I -.1029010  .0000071  0.1297 0.0060  I   -46.748     .791    -7.448     .298  -.052640   .448880  -.1029200   -46.900    -7.700  
+98 7 8 51002.00 I  -.050272  .000103   .449909  .000152  I -.1029867  .0000099  0.0445 0.0061  I   -46.743     .791    -7.578     .298  -.050110   .450080  -.1030040   -46.600    -7.600  
+98 7 9 51003.00 I  -.047789  .000113   .451171  .000154  I -.1030078  .0000099  0.0129 0.0071  I   -46.598     .791    -7.777     .298  -.047580   .451160  -.1030060   -46.400    -7.600  
+98 710 51004.00 I  -.045284  .000107   .452559  .000144  I -.1030458  .0000102  0.0813 0.0067  I   -46.477     .791    -7.881     .298  -.045060   .452530  -.1030150   -46.200    -7.500  
+98 711 51005.00 I  -.042770  .000103   .454154  .000134  I -.1031990  .0000090  0.2354 0.0066  I   -46.574     .791    -7.811     .298  -.042630   .454360  -.1031510   -46.100    -7.600  
+98 712 51006.00 I  -.040237  .000073   .455835  .000120  I -.1035270  .0000083  0.4207 0.0062  I   -46.925     .791    -7.646     .298  -.040080   .456150  -.1034910   -46.100    -7.500  
+98 713 51007.00 I  -.037743  .000061   .457466  .000119  I -.1040342  .0000084  0.5875 0.0052  I   -47.361     .237    -7.531     .108  -.037610   .457660  -.1040260   -46.300    -7.600  
+98 714 51008.00 I  -.035317  .000060   .458998  .000113  I -.1046856  .0000062  0.7053 0.0052  I   -47.653     .239    -7.530     .298  -.035190   .459100  -.1046950   -46.600    -7.600  
+98 715 51009.00 I  -.032985  .000056   .460388  .000106  I -.1054234  .0000063  0.7591 0.0046  I   -47.720     .239    -7.593     .298  -.032820   .460470  -.1054320   -47.100    -7.700  
+98 716 51010.00 I  -.030768  .000055   .461506  .000101  I -.1061780  .0000069  0.7356 0.0046  I   -47.690     .239    -7.644     .298  -.030630   .461620  -.1061790   -47.600    -7.700  
+98 717 51011.00 I  -.028607  .000060   .462383  .000098  I -.1068703  .0000066  0.6392 0.0049  I   -47.745     .276    -7.711     .109  -.028420   .462510  -.1068730   -48.200    -7.800  
+98 718 51012.00 I  -.026513  .000066   .463176  .000094  I -.1074437  .0000070  0.5047 0.0044  I   -48.045     .276    -7.865     .109  -.026280   .463320  -.1074530   -48.700    -8.000  
+98 719 51013.00 I  -.024528  .000079   .463998  .000071  I -.1078768  .0000059  0.3615 0.0060  I   -48.570     .283    -8.132     .298  -.024350   .464190  -.1078910   -49.200    -8.100  
+98 720 51014.00 I  -.022578  .000108   .464858  .000082  I -.1081687  .0000097  0.2245 0.0062  I   -49.098     .280    -8.442     .298  -.022400   .465070  -.1081780   -49.500    -8.200  
+98 721 51015.00 I  -.020654  .000115   .465732  .000078  I -.1083355  .0000110  0.1168 0.0074  I   -49.392     .280    -8.620     .298  -.020390   .465930  -.1083390   -49.500    -8.300  
+98 722 51016.00 I  -.018742  .000107   .466609  .000081  I -.1084270  .0000112  0.0833 0.0078  I   -49.390     .280    -8.515     .298  -.018520   .466820  -.1084240   -49.500    -8.300  
+98 723 51017.00 I  -.016591  .000104   .467461  .000080  I -.1085268  .0000112  0.1239 0.0079  I   -49.144     .280    -8.246     .298  -.016390   .467730  -.1085030   -49.200    -8.400  
+98 724 51018.00 I  -.014288  .000101   .468234  .000078  I -.1086888  .0000112  0.2065 0.0082  I   -48.871     .280    -7.991     .298  -.014030   .468560  -.1086470   -48.900    -8.400  
+98 725 51019.00 I  -.011898  .000096   .468963  .000081  I -.1089490  .0000119  0.3169 0.0080  I   -48.771     .238    -7.853     .298  -.011710   .469190  -.1089050   -48.700    -8.400  
+98 726 51020.00 I  -.009354  .000054   .469790  .000064  I -.1093187  .0000113  0.4158 0.0078  I   -48.896     .791    -7.836     .298  -.009170   .469900  -.1092880   -48.700    -8.400  
+98 727 51021.00 I  -.006753  .000057   .470803  .000106  I -.1097667  .0000102  0.4729 0.0072  I   -49.207     .344    -7.885     .298  -.006510   .470970  -.1097590   -48.900    -8.400  
+98 728 51022.00 I  -.004257  .000119   .471952  .000148  I -.1102513  .0000088  0.4902 0.0074  I   -49.631     .281    -7.988     .298  -.004050   .472140  -.1102550   -49.400    -8.300  
+98 729 51023.00 I  -.001928  .000122   .473168  .000154  I -.1107348  .0000106  0.4705 0.0068  I   -50.038     .281    -8.169     .298  -.001800   .473270  -.1107300   -50.100    -8.200  
+98 730 51024.00 I   .000141  .000124   .474366  .000153  I -.1111979  .0000105  0.4675 0.0075  I   -50.280     .281    -8.393     .298   .000400   .474440  -.1111900   -51.000    -8.200  
+98 731 51025.00 I   .002045  .000122   .475412  .000157  I -.1116748  .0000106  0.4796 0.0074  I   -50.344     .281    -8.509     .298   .002240   .475590  -.1116620   -51.800    -8.200  
+98 8 1 51026.00 I   .003902  .000118   .476287  .000160  I -.1121413  .0000105  0.4444 0.0070  I   -50.405     .281    -8.419     .298   .004030   .476470  -.1121250   -52.400    -8.100  
+98 8 2 51027.00 I   .005810  .000139   .476934  .000165  I -.1125566  .0000092  0.3883 0.0084  I   -50.653     .791    -8.153     .298   .006030   .477150  -.1125390   -52.600    -8.100  
+98 8 3 51028.00 I   .007707  .000096   .477354  .000122  I -.1129220  .0000130  0.3444 0.0055  I   -51.055     .791    -7.825     .298   .007910   .477580  -.1129010   -52.500    -7.900  
+98 8 4 51029.00 I   .009695  .000101   .477689  .000120  I -.1132513  .0000060  0.3181 0.0072  I   -51.373     .791    -7.595     .298   .009780   .477780  -.1132420   -52.000    -7.700  
+98 8 5 51030.00 I   .011888  .000102   .478048  .000120  I -.1135649  .0000060  0.3117 0.0045  I   -51.435     .791    -7.588     .298   .011970   .478280  -.1135780   -51.300    -7.600  
+98 8 6 51031.00 I   .014036  .000107   .478378  .000108  I -.1138882  .0000067  0.3457 0.0044  I   -51.304     .791    -7.798     .298   .014310   .478670  -.1138850   -50.900    -7.500  
+98 8 7 51032.00 I   .016013  .000116   .478564  .000101  I -.1142787  .0000065  0.4469 0.0038  I   -51.165     .791    -8.045     .298   .016310   .478810  -.1142650   -50.600    -7.400  
+98 8 8 51033.00 I   .017857  .000099   .478532  .000092  I -.1147998  .0000035  0.6015 0.0040  I   -51.134     .791    -8.123     .298   .018000   .478750  -.1147840   -50.500    -7.400  
+98 8 9 51034.00 I   .019846  .000062   .478394  .000090  I -.1154884  .0000045  0.7763 0.0027  I   -51.238     .791    -7.997     .298   .020000   .478530  -.1154780   -50.400    -7.400  
+98 810 51035.00 I   .022136  .000106   .478349  .000116  I -.1163435  .0000040  0.9243 0.0032  I   -51.474     .130    -7.824     .298   .022360   .478550  -.1163610   -50.700    -7.500  
+98 811 51036.00 I   .024683  .000113   .478428  .000116  I -.1173135  .0000046  1.0016 0.0029  I   -51.813     .130    -7.773     .298   .024920   .478620  -.1172870   -51.100    -7.600  
+98 812 51037.00 I   .027507  .000118   .478537  .000120  I -.1183214  .0000043  1.0030 0.0035  I   -52.172     .130    -7.849     .298   .027750   .478650  -.1183140   -51.700    -7.800  
+98 813 51038.00 I   .030469  .000115   .478490  .000114  I -.1192916  .0000053  0.9207 0.0038  I   -52.470     .130    -7.924     .298   .030740   .478710  -.1193330   -52.400    -7.900  
+98 814 51039.00 I   .033161  .000123   .478373  .000115  I -.1201373  .0000062  0.7619 0.0048  I   -52.696     .130    -7.916     .298   .033470   .478530  -.1201380   -53.000    -8.000  
+98 815 51040.00 I   .035385  .000126   .478230  .000116  I -.1208043  .0000081  0.5699 0.0104  I   -52.929     .195    -7.861     .298   .035640   .478380  -.1208020   -53.400    -8.200  
+98 816 51041.00 I   .037338  .000076   .477954  .000077  I -.1212799  .0000198  0.3864 0.0104  I   -53.235     .284    -7.851     .298   .037440   .478200  -.1212930   -53.600    -8.200  
+98 817 51042.00 I   .039383  .000058   .477571  .000082  I -.1215970  .0000191  0.2625 0.0144  I   -53.541     .273    -7.944     .298   .039480   .477780  -.1215910   -53.600    -8.300  
+98 818 51043.00 I   .041616  .000039   .477282  .000079  I -.1218310  .0000209  0.2168 0.0146  I   -53.635     .273    -8.126     .298   .041850   .477460  -.1217910   -53.300    -8.300  
+98 819 51044.00 I   .043877  .000038   .477170  .000093  I -.1220399  .0000221  0.1988 0.0147  I   -53.354     .273    -8.330     .298   .044010   .477310  -.1220280   -52.900    -8.400  
+98 820 51045.00 I   .046118  .000032   .477172  .000087  I -.1222411  .0000206  0.2182 0.0153  I   -52.848     .273    -8.426     .298   .046250   .477350  -.1222380   -52.400    -8.400  
+98 821 51046.00 I   .048308  .000029   .477138  .000083  I -.1224999  .0000212  0.3085 0.0123  I   -52.357     .262    -8.392     .298   .048530   .477440  -.1224530   -52.100    -8.500  
+98 822 51047.00 I   .050364  .000033   .476926  .000086  I -.1228631  .0000134  0.4139 0.0121  I   -52.053     .207    -8.266     .298   .050550   .477220  -.1228260   -51.800    -8.500  
+98 823 51048.00 I   .052280  .000047   .476613  .000099  I -.1233193  .0000117  0.4943 0.0078  I   -51.975     .130    -8.090     .298   .052440   .476810  -.1233090   -51.700    -8.500  
+98 824 51049.00 I   .054145  .000049   .476412  .000124  I -.1238454  .0000078  0.5559 0.0069  I   -52.093     .310    -7.930     .144   .054320   .476560  -.1238350   -51.800    -8.500  
+98 825 51050.00 I   .056077  .000065   .476410  .000117  I -.1244283  .0000072  0.6093 0.0054  I   -52.360     .278    -7.882     .126   .056240   .476540  -.1244130   -52.200    -8.400  
+98 826 51051.00 I   .058154  .000067   .476479  .000122  I -.1250667  .0000074  0.6709 0.0053  I   -52.646     .278    -7.984     .126   .058240   .476620  -.1250660   -52.500    -8.200  
+98 827 51052.00 I   .060476  .000068   .476406  .000123  I -.1257468  .0000078  0.6626 0.0053  I   -52.766     .278    -8.121     .126   .060590   .476610  -.1257590   -52.900    -8.000  
+98 828 51053.00 I   .063022  .000067   .476301  .000123  I -.1263679  .0000075  0.5822 0.0056  I   -52.600     .278    -8.189     .126   .063220   .476500  -.1263670   -53.200    -7.900  
+98 829 51054.00 I   .065457  .000061   .476258  .000123  I -.1269255  .0000080  0.5446 0.0057  I   -52.391     .312    -8.140     .145   .065630   .476440  -.1268960   -53.500    -7.800  
+98 830 51055.00 I   .067554  .000058   .476216  .000070  I -.1274719  .0000086  0.5515 0.0072  I   -52.500     .145    -8.006     .298   .067680   .476380  -.1274620   -53.600    -7.700  
+98 831 51056.00 I   .069401  .000048   .476025  .000068  I -.1280318  .0000120  0.5684 0.0076  I   -52.913     .791    -7.856     .298   .069550   .476230  -.1280370   -53.500    -7.600  
+98 9 1 51057.00 I   .071120  .000054   .475561  .000064  I -.1286135  .0000126  0.5999 0.0086  I   -53.253     .791    -7.741     .298   .071240   .475620  -.1285890   -53.300    -8.100  
+98 9 2 51058.00 I   .072844  .000059   .474730  .000062  I -.1292386  .0000123  0.6526 0.0093  I   -53.270     .791    -7.722     .298   .073020   .474780  -.1292390   -53.100    -7.800  
+98 9 3 51059.00 I   .074764  .000068   .473551  .000055  I -.1299286  .0000137  0.7349 0.0093  I   -53.117     .791    -7.848     .298   .074860   .473590  -.1299930   -52.900    -7.400  
+98 9 4 51060.00 I   .077100  .000073   .472242  .000060  I -.1307263  .0000139  0.8707 0.0093  I   -53.060     .791    -8.050     .298   .077130   .472220  -.1307450   -52.800    -7.200  
+98 9 5 51061.00 I   .079771  .000071   .471042  .000062  I -.1316873  .0000126  1.0583 0.0090  I   -53.119     .791    -8.139     .298   .079940   .471050  -.1316510   -52.700    -7.200  
+98 9 6 51062.00 I   .082436  .000081   .470009  .000080  I -.1328413  .0000113  1.2412 0.0080  I   -53.159     .791    -7.991     .298   .082560   .470090  -.1328540   -52.700    -7.100  
+98 9 7 51063.00 I   .084904  .000090   .469113  .000105  I -.1341544  .0000099  1.3782 0.0076  I   -53.169     .791    -7.718     .298   .084950   .469130  -.1341840   -52.900    -7.300  
+98 9 8 51064.00 I   .087182  .000093   .468379  .000112  I -.1355772  .0000103  1.4537 0.0070  I   -53.291     .791    -7.561     .298   .087280   .468310  -.1355640   -53.200    -7.400  
+98 9 9 51065.00 I   .089300  .000094   .467798  .000116  I -.1370359  .0000099  1.4516 0.0075  I   -53.597     .791    -7.628     .298   .089440   .467860  -.1370290   -53.500    -7.700  
+98 910 51066.00 I   .091338  .000094   .467196  .000119  I -.1384475  .0000108  1.3507 0.0075  I   -53.976     .791    -7.806     .298   .091430   .467320  -.1384850   -53.900    -7.800  
+98 911 51067.00 I   .093191  .000104   .466586  .000113  I -.1397068  .0000112  1.1583 0.0078  I   -54.241     .791    -7.942     .298   .093290   .466610  -.1397250   -54.200    -8.000  
+98 912 51068.00 I   .094945  .000100   .466045  .000106  I -.1407607  .0000112  0.9558 0.0099  I   -54.286     .791    -8.017     .298   .095020   .466090  -.1407430   -54.300    -8.200  
+98 913 51069.00 I   .096838  .000077   .465596  .000083  I -.1416295  .0000163  0.7866 0.0082  I   -54.155     .791    -8.103     .298   .096750   .465690  -.1416630   -54.400    -8.300  
+98 914 51070.00 I   .099104  .000082   .465229  .000089  I -.1423579  .0000121  0.6895 0.0103  I   -53.982     .791    -8.212     .298   .099100   .465260  -.1423780   -54.200    -8.300  
+98 915 51071.00 I   .101649  .000086   .464944  .000092  I -.1430406  .0000127  0.6886 0.0089  I   -53.857     .791    -8.264     .298   .101750   .464930  -.1430220   -53.900    -8.300  
+98 916 51072.00 I   .104134  .000081   .464679  .000099  I -.1437528  .0000130  0.7410 0.0091  I   -53.728     .791    -8.182     .298   .104290   .464720  -.1437630   -53.600    -8.200  
+98 917 51073.00 I   .106262  .000070   .464282  .000096  I -.1445295  .0000129  0.8143 0.0091  I   -53.494     .791    -7.960     .298   .106540   .464300  -.1445660   -53.400    -8.000  
+98 918 51074.00 I   .107886  .000062   .463595  .000095  I -.1453877  .0000128  0.9064 0.0090  I   -53.178     .791    -7.703     .298   .108060   .463730  -.1453830   -53.200    -7.800  
+98 919 51075.00 I   .109157  .000064   .462458  .000095  I -.1463485  .0000126  1.0172 0.0084  I   -52.920     .791    -7.466     .298   .109190   .462570  -.1463160   -53.000    -7.500  
+98 920 51076.00 I   .110451  .000074   .461014  .000077  I -.1474139  .0000109  1.1035 0.0072  I   -52.815     .791    -7.210     .298   .110510   .460960  -.1474310   -52.900    -7.300  
+98 921 51077.00 I   .112012  .000069   .459494  .000120  I -.1485386  .0000068  1.1390 0.0060  I   -52.853     .791    -6.993     .298   .112080   .459540  -.1485550   -52.900    -7.200  
+98 922 51078.00 I   .113860  .000067   .457995  .000116  I -.1496770  .0000049  1.1299 0.0040  I   -52.965     .791    -6.951     .298   .113860   .458050  -.1496660   -52.800    -7.100  
+98 923 51079.00 I   .115813  .000066   .456545  .000116  I -.1507847  .0000044  1.0798 0.0047  I   -53.020     .791    -7.135     .298   .115840   .456520  -.1507800   -52.900    -7.100  
+98 924 51080.00 I   .117554  .000070   .455099  .000114  I -.1518337  .0000080  1.0211 0.0046  I   -52.833     .791    -7.414     .298   .117640   .455060  -.1518410   -53.000    -7.200  
+98 925 51081.00 I   .119055  .000074   .453760  .000119  I -.1528303  .0000080  0.9725 0.0054  I   -52.371     .791    -7.604     .298   .119170   .453760  -.1528260   -53.100    -7.300  
+98 926 51082.00 I   .120278  .000072   .452516  .000114  I -.1537788  .0000072  0.9240 0.0068  I   -51.923     .791    -7.638     .298   .120390   .452570  -.1537680   -53.100    -7.400  
+98 927 51083.00 I   .121282  .000062   .451171  .000065  I -.1546743  .0000110  0.8635 0.0060  I   -51.872     .791    -7.595     .298   .121340   .451320  -.1546930   -53.100    -7.500  
+98 928 51084.00 I   .122230  .000077   .449599  .000070  I -.1555100  .0000096  0.8156 0.0066  I   -52.222     .791    -7.548     .298   .122300   .449720  -.1555430   -53.100    -7.500  
+98 929 51085.00 I   .123196  .000068   .447930  .000083  I -.1563226  .0000073  0.8189 0.0051  I   -52.567     .791    -7.473     .298   .123320   .447910  -.1563210   -52.800    -7.400  
+98 930 51086.00 I   .124155  .000072   .446382  .000086  I -.1571765  .0000032  0.9082 0.0042  I   -52.603     .105    -7.352     .298   .124320   .446400  -.1571750   -52.500    -7.300  
+9810 1 51087.00 I   .125228  .000076   .445043  .000088  I -.1581667  .0000041  1.0806 0.0026  I   -52.453     .105    -7.258     .298   .125350   .445040  -.1581770   -52.100    -7.200  
+9810 2 51088.00 I   .126461  .000068   .443833  .000088  I -.1593503  .0000041  1.2909 0.0029  I   -52.389     .105    -7.256     .298   .126530   .443810  -.1593500   -51.600    -6.900  
+9810 3 51089.00 I   .128001  .000074   .442525  .000107  I -.1607548  .0000041  1.5201 0.0036  I   -52.397     .113    -7.265     .298   .128040   .442560  -.1607750   -51.300    -6.800  
+9810 4 51090.00 I   .129722  .000090   .441128  .000122  I -.1623864  .0000059  1.7371 0.0032  I   -52.287     .113    -7.141     .298   .129790   .441260  -.1623690   -51.000    -6.600  
+9810 5 51091.00 I   .131406  .000089   .439608  .000122  I -.1642040  .0000050  1.8792 0.0039  I   -52.014     .103    -6.918     .298   .131470   .439610  -.1641980   -51.000    -6.600  
+9810 6 51092.00 I   .132907  .000097   .437892  .000123  I -.1661050  .0000052  1.9019 0.0036  I   -51.778     .791    -6.808     .298   .132950   .438040  -.1661190   -51.100    -6.600  
+9810 7 51093.00 I   .134223  .000094   .435948  .000126  I -.1679813  .0000051  1.8451 0.0043  I   -51.803     .791    -6.917     .298   .134300   .436030  -.1679800   -51.300    -6.800  
+9810 8 51094.00 I   .135605  .000097   .433878  .000128  I -.1697762  .0000069  1.7314 0.0043  I   -52.125     .791    -7.060     .298   .135650   .433830  -.1697670   -51.700    -7.000  
+9810 9 51095.00 I   .137157  .000103   .431974  .000127  I -.1714343  .0000069  1.5884 0.0055  I   -52.567     .791    -7.073     .298   .137210   .431860  -.1714380   -52.000    -7.200  
+981010 51096.00 I   .138748  .000101   .430520  .000117  I -.1729566  .0000085  1.4561 0.0060  I   -52.863     .157    -7.019     .298   .138840   .430600  -.1729550   -52.100    -7.400  
+981011 51097.00 I   .140117  .000083   .429469  .000105  I -.1743488  .0000098  1.3307 0.0083  I   -52.836     .203    -7.074     .298   .140170   .429510  -.1743740   -52.200    -7.600  
+981012 51098.00 I   .141200  .000072   .428517  .000099  I -.1756317  .0000143  1.2465 0.0095  I   -52.544     .266    -7.283     .298   .141300   .428710  -.1756750   -52.200    -7.700  
+981013 51099.00 I   .142006  .000072   .427407  .000091  I -.1768635  .0000162  1.2275 0.0102  I   -52.205     .266    -7.500     .298   .142080   .427600  -.1768890   -51.900    -7.800  
+981014 51100.00 I   .142798  .000065   .426003  .000093  I -.1781129  .0000146  1.2870 0.0113  I   -51.932     .266    -7.589     .298   .142800   .426040  -.1781180   -51.700    -7.500  
+981015 51101.00 I   .143900  .000067   .424493  .000097  I -.1794441  .0000158  1.3663 0.0103  I   -51.698     .266    -7.537     .298   .144040   .424490  -.1794610   -51.300    -7.400  
+981016 51102.00 I   .145221  .000060   .423152  .000084  I -.1808316  .0000144  1.4038 0.0107  I   -51.366     .244    -7.426     .298   .145380   .423230  -.1808420   -51.100    -7.100  
+981017 51103.00 I   .146618  .000044   .422003  .000070  I -.1822482  .0000145  1.4308 0.0100  I   -50.973     .244    -7.266     .298   .146710   .422100  -.1822120   -50.800    -6.700  
+981018 51104.00 I   .147994  .000079   .420910  .000066  I -.1836933  .0000140  1.4580 0.0081  I   -50.694     .791    -7.001     .298   .148110   .420990  -.1836610   -50.700    -6.500  
+981019 51105.00 I   .149208  .000080   .419738  .000108  I -.1851581  .0000071  1.4667 0.0077  I   -50.590     .791    -6.664     .298   .149290   .419730  -.1851800   -50.600    -6.300  
+981020 51106.00 I   .150207  .000089   .418399  .000108  I -.1866206  .0000065  1.4571 0.0044  I   -50.562     .791    -6.414     .298   .150230   .418400  -.1866130   -50.500    -6.300  
+981021 51107.00 I   .151112  .000088   .416821  .000109  I -.1880692  .0000053  1.4383 0.0043  I   -50.471     .791    -6.367     .298   .151150   .416880  -.1880530   -50.500    -6.200  
+981022 51108.00 I   .151751  .000102   .414917  .000124  I -.1894838  .0000056  1.3794 0.0037  I   -50.226     .791    -6.463     .298   .151950   .414940  -.1895090   -50.500    -6.300  
+981023 51109.00 I   .152151  .000102   .412904  .000123  I -.1908182  .0000053  1.2913 0.0040  I   -49.858     .791    -6.543     .298   .152320   .412880  -.1908230   -50.500    -6.400  
+981024 51110.00 I   .152450  .000095   .411039  .000121  I -.1920780  .0000058  1.2380 0.0051  I   -49.542     .791    -6.540     .298   .152530   .411040  -.1920590   -50.600    -6.500  
+981025 51111.00 I   .152867  .000075   .409395  .000106  I -.1933079  .0000087  1.2257 0.0077  I   -49.513     .791    -6.517     .298   .152960   .409450  -.1933040   -50.600    -6.500  
+981026 51112.00 I   .153419  .000061   .407837  .000105  I -.1945276  .0000142  1.2080 0.0099  I   -49.786     .791    -6.526     .298   .153510   .407950  -.1945460   -50.500    -6.500  
+981027 51113.00 I   .154100  .000056   .406206  .000097  I -.1957206  .0000177  1.1804 0.0124  I   -50.066     .791    -6.493     .298   .154190   .406270  -.1957380   -50.400    -6.400  
+981028 51114.00 I   .154951  .000043   .404482  .000084  I -.1969058  .0000204  1.2052 0.0137  I   -50.074     .791    -6.323     .298   .155000   .404560  -.1969190   -50.100    -6.300  
+981029 51115.00 I   .155988  .000040   .402752  .000080  I -.1981645  .0000209  1.3307 0.0144  I   -49.866     .791    -6.052     .298   .156040   .402790  -.1981300   -49.700    -6.100  
+981030 51116.00 I   .157099  .000041   .401147  .000081  I -.1995944  .0000203  1.5378 0.0130  I   -49.718     .791    -5.815     .298   .157170   .401180  -.1995050   -49.200    -5.700  
+981031 51117.00 I   .158205  .000047   .399656  .000085  I -.2012498  .0000156  1.7739 0.0121  I   -49.732     .791    -5.650     .298   .158280   .399690  -.2011920   -48.800    -5.400  
+9811 1 51118.00 I   .159372  .000050   .398227  .000101  I -.2031347  .0000133  1.9874 0.0086  I   -49.763     .157    -5.481     .298   .159470   .398270  -.2031340   -48.600    -5.200  
+9811 2 51119.00 I   .160608  .000060   .396796  .000095  I -.2051970  .0000074  2.1180 0.0075  I   -49.695     .174    -5.314     .298   .160720   .396800  -.2052100   -48.500    -5.100  
+9811 3 51120.00 I   .161800  .000099   .395350  .000114  I -.2073295  .0000069  2.1252 0.0049  I   -49.557     .158    -5.299     .298   .161840   .395320  -.2073330   -48.800    -5.200  
+9811 4 51121.00 I   .162759  .000108   .393866  .000116  I -.2094137  .0000065  2.0315 0.0052  I   -49.432     .144    -5.497     .298   .162790   .393910  -.2094130   -48.900    -5.300  
+9811 5 51122.00 I   .163186  .000105   .392206  .000121  I -.2113694  .0000078  1.8684 0.0052  I   -49.428     .144    -5.680     .298   .163190   .392310  -.2113550   -49.100    -5.600  
+9811 6 51123.00 I   .163127  .000107   .390338  .000130  I -.2131451  .0000082  1.6890 0.0057  I   -49.549     .144    -5.581     .298   .163130   .390500  -.2131330   -49.200    -5.900  
+9811 7 51124.00 I   .163177  .000103   .388193  .000131  I -.2147595  .0000083  1.5458 0.0056  I   -49.636     .125    -5.360     .104   .163230   .388320  -.2147600   -49.200    -6.100  
+9811 8 51125.00 I   .163540  .000100   .385840  .000108  I -.2162531  .0000077  1.4518 0.0064  I   -49.512     .791    -5.337     .115   .163570   .385860  -.2162550   -49.200    -6.200  
+9811 9 51126.00 I   .164135  .000088   .383444  .000093  I -.2176863  .0000097  1.4273 0.0061  I   -49.208     .791    -5.588     .298   .164150   .383480  -.2176810   -49.100    -6.200  
+981110 51127.00 I   .164793  .000054   .381095  .000082  I -.2191246  .0000094  1.4534 0.0059  I   -48.999     .118    -5.897     .298   .164860   .381130  -.2191100   -49.000    -6.100  
+981111 51128.00 I   .165431  .000047   .378844  .000080  I -.2205953  .0000067  1.4861 0.0059  I   -49.097     .139    -5.996     .298   .165440   .378810  -.2205850   -48.900    -6.000  
+981112 51129.00 I   .166094  .000042   .376752  .000078  I -.2220940  .0000072  1.5104 0.0049  I   -49.362     .139    -5.854     .298   .166110   .376800  -.2220960   -48.800    -5.700  
+981113 51130.00 I   .166560  .000039   .374724  .000068  I -.2236125  .0000071  1.5240 0.0051  I   -49.450     .139    -5.638     .298   .166620   .374820  -.2236190   -48.700    -5.500  
+981114 51131.00 I   .166577  .000039   .372674  .000077  I -.2251363  .0000071  1.5206 0.0067  I   -49.255     .139    -5.453     .298   .166590   .372680  -.2251430   -48.600    -5.200  
+981115 51132.00 I   .166129  .000059   .370621  .000104  I -.2266458  .0000113  1.4936 0.0065  I   -48.998     .158    -5.261     .298   .166180   .370690  -.2266690   -48.500    -5.000  
+981116 51133.00 I   .165389  .000074   .368567  .000127  I -.2281187  .0000108  1.4521 0.0078  I   -48.866     .277    -5.020     .168   .165440   .368620  -.2281310   -48.400    -4.800  
+981117 51134.00 I   .164616  .000078   .366565  .000147  I -.2295496  .0000108  1.4095 0.0074  I   -48.796     .320    -4.794     .206   .164590   .366530  -.2295470   -48.300    -4.700  
+981118 51135.00 I   .164092  .000082   .364644  .000150  I -.2309382  .0000100  1.3685 0.0074  I   -48.669     .320    -4.680     .206   .164060   .364670  -.2309380   -48.200    -4.800  
+981119 51136.00 I   .163768  .000094   .362711  .000152  I -.2322849  .0000100  1.3225 0.0071  I   -48.483     .320    -4.688     .206   .163740   .362710  -.2322770   -48.200    -4.800  
+981120 51137.00 I   .163194  .000105   .360797  .000147  I -.2335826  .0000102  1.2746 0.0071  I   -48.271     .320    -4.743     .206   .163200   .360760  -.2335820   -48.000    -4.900  
+981121 51138.00 I   .161963  .000096   .358907  .000136  I -.2348381  .0000101  1.2386 0.0082  I   -48.057     .320    -4.794     .206   .162040   .359040  -.2348520   -47.900    -5.100  
+981122 51139.00 I   .160085  .000077   .356946  .000110  I -.2360666  .0000129  1.2230 0.0072  I   -47.909     .791    -4.855     .298   .160030   .357130  -.2360610   -47.900    -5.100  
+981123 51140.00 I   .158115  .000073   .354896  .000096  I -.2372925  .0000104  1.2326 0.0083  I   -47.900     .791    -4.940     .298   .158090   .354910  -.2372750   -47.800    -5.200  
+981124 51141.00 I   .156354  .000073   .352913  .000095  I -.2385373  .0000106  1.2587 0.0077  I   -47.984     .791    -4.990     .298   .156480   .352940  -.2385630   -47.800    -5.000  
+981125 51142.00 I   .154814  .000070   .351026  .000107  I -.2398232  .0000113  1.3249 0.0079  I   -48.015     .791    -4.929     .298   .154930   .351080  -.2398440   -47.800    -4.900  
+981126 51143.00 I   .153691  .000061   .349091  .000104  I -.2412084  .0000116  1.4552 0.0081  I   -47.909     .791    -4.754     .298   .153770   .349160  -.2411550   -47.900    -4.600  
+981127 51144.00 I   .152791  .000066   .347042  .000109  I -.2427449  .0000117  1.6196 0.0072  I   -47.717     .791    -4.534     .298   .152870   .347140  -.2427040   -48.000    -4.300  
+981128 51145.00 I   .151834  .000075   .344872  .000114  I -.2444448  .0000086  1.7758 0.0075  I   -47.529     .791    -4.314     .298   .151860   .344890  -.2444480   -48.200    -4.200  
+981129 51146.00 I   .150915  .000079   .342720  .000125  I -.2462737  .0000093  1.8635 0.0057  I   -47.408     .791    -4.096     .298   .150870   .342630  -.2462790   -48.300    -4.100  
+981130 51147.00 I   .150141  .000120   .340779  .000149  I -.2481367  .0000076  1.8457 0.0058  I   -47.416     .172    -3.926     .298   .150250   .340730  -.2481490   -48.300    -4.100  
+9812 1 51148.00 I   .149184  .000115   .339098  .000146  I -.2499346  .0000068  1.7362 0.0049  I   -47.585     .172    -3.925     .298   .149440   .339290  -.2499460   -48.200    -4.100  
+9812 2 51149.00 I   .147951  .000122   .337562  .000148  I -.2515983  .0000061  1.5942 0.0046  I   -47.851     .172    -4.124     .298   .148060   .337590  -.2516030   -48.000    -4.100  
+9812 3 51150.00 I   .147004  .000127   .336146  .000141  I -.2531202  .0000061  1.4438 0.0041  I   -48.101     .172    -4.343     .298   .146980   .336120  -.2531290   -47.600    -4.300  
+9812 4 51151.00 I   .146455  .000127   .335017  .000137  I -.2544842  .0000055  1.2884 0.0044  I   -48.253     .172    -4.343     .298   .146520   .335080  -.2544910   -47.100    -4.400  
+9812 5 51152.00 I   .145863  .000128   .334151  .000152  I -.2557114  .0000063  1.1762 0.0056  I   -48.247     .175    -4.125     .298   .145960   .334300  -.2557150   -46.600    -4.400  
+9812 6 51153.00 I   .144933  .000091   .333320  .000153  I -.2568539  .0000097  1.1161 0.0056  I   -48.011     .182    -3.953     .298   .144940   .333360  -.2568680   -46.200    -4.500  
+9812 7 51154.00 I   .143695  .000088   .332385  .000137  I -.2579548  .0000093  1.0898 0.0071  I   -47.577     .184    -4.035     .298   .143730   .332270  -.2579490   -46.100    -4.500  
+9812 8 51155.00 I   .142269  .000076   .331265  .000131  I -.2590365  .0000103  1.0724 0.0072  I   -47.158     .184    -4.267     .298   .142260   .331140  -.2590450   -46.200    -4.500  
+9812 9 51156.00 I   .140845  .000072   .329776  .000124  I -.2601098  .0000109  1.0855 0.0076  I   -46.970     .184    -4.371     .298   .140850   .329720  -.2601250   -46.600    -4.400  
+981210 51157.00 I   .139654  .000065   .327889  .000116  I -.2612229  .0000113  1.1448 0.0075  I   -47.019     .184    -4.194     .298   .139700   .327880  -.2611980   -47.000    -4.200  
+981211 51158.00 I   .138670  .000065   .325829  .000111  I -.2623954  .0000103  1.1922 0.0076  I   -47.070     .184    -3.875     .298   .138680   .325810  -.2623830   -47.500    -3.900  
+981212 51159.00 I   .137880  .000067   .323810  .000082  I -.2635872  .0000102  1.1795 0.0070  I   -47.029     .187    -3.617     .298   .137890   .323810  -.2636020   -48.000    -3.700  
+981213 51160.00 I   .137344  .000046   .321899  .000062  I -.2647402  .0000095  1.1244 0.0059  I   -47.057     .109    -3.473     .298   .137390   .321940  -.2647510   -47.800    -3.600  
+981214 51161.00 I   .137118  .000048   .320090  .000090  I -.2658320  .0000061  1.0574 0.0055  I   -47.250     .150    -3.394     .298   .137150   .320130  -.2658350   -47.800    -3.500  
+981215 51162.00 I   .137191  .000056   .318439  .000094  I -.2668510  .0000054  0.9784 0.0039  I   -47.470     .133    -3.369     .298   .137240   .318410  -.2668620   -47.700    -3.400  
+981216 51163.00 I   .137482  .000059   .317021  .000101  I -.2677836  .0000047  0.8839 0.0037  I   -47.551     .133    -3.440     .298   .137450   .316970  -.2677810   -47.500    -3.500  
+981217 51164.00 I   .137993  .000065   .315738  .000105  I -.2686203  .0000051  0.7938 0.0035  I   -47.540     .133    -3.572     .298   .137950   .315730  -.2686130   -47.200    -3.600  
+981218 51165.00 I   .138867  .000071   .314494  .000109  I -.2693765  .0000051  0.7196 0.0034  I   -47.491     .133    -3.726     .298   .138870   .314470  -.2693900   -46.900    -3.800  
+981219 51166.00 I   .140070  .000066   .313420  .000137  I -.2700640  .0000045  0.6589 0.0047  I   -47.356     .140    -3.882     .298   .140080   .313340  -.2700750   -46.700    -3.900  
+981220 51167.00 I   .141362  .000066   .312536  .000132  I -.2707054  .0000078  0.6316 0.0049  I   -47.095     .791    -3.999     .298   .141430   .312550  -.2706980   -46.500    -4.000  
+981221 51168.00 I   .142330  .000074   .311541  .000129  I -.2713404  .0000087  0.6439 0.0059  I   -46.816     .791    -4.034     .298   .142400   .311680  -.2713370   -46.400    -4.000  
+981222 51169.00 I   .142795  .000070   .310097  .000128  I -.2720051  .0000088  0.6921 0.0063  I   -46.683     .791    -3.973     .298   .142860   .310170  -.2720570   -46.500    -3.800  
+981223 51170.00 I   .142988  .000067   .308356  .000126  I -.2727487  .0000090  0.8128 0.0067  I   -46.726     .791    -3.851     .298   .143050   .308250  -.2727810   -46.700    -3.700  
+981224 51171.00 I   .143090  .000066   .306710  .000126  I -.2736544  .0000100  1.0047 0.0067  I   -46.816     .791    -3.722     .298   .143130   .306690  -.2735780   -47.000    -3.600  
+981225 51172.00 I   .143080  .000068   .305222  .000119  I -.2747547  .0000099  1.1863 0.0069  I   -46.819     .791    -3.604     .298   .143110   .305330  -.2746410   -47.300    -3.400  
+981226 51173.00 I   .142815  .000082   .303796  .000074  I -.2760051  .0000096  1.3021 0.0065  I   -46.732     .791    -3.485     .298   .142820   .303820  -.2759310   -47.700    -3.400  
+981227 51174.00 I   .142282  .000099   .302444  .000087  I -.2773357  .0000085  1.3481 0.0062  I   -46.676     .101    -3.368     .298   .142260   .302430  -.2773300   -47.900    -3.400  
+981228 51175.00 I   .141721  .000102   .301186  .000088  I -.2786798  .0000078  1.3295 0.0056  I   -46.797     .384    -3.313     .131   .141690   .301160  -.2787160   -48.200    -3.400  
+981229 51176.00 I   .141207  .000101   .299985  .000105  I -.2799819  .0000074  1.2726 0.0049  I   -47.126     .384    -3.412     .131   .141210   .299910  -.2800170   -48.200    -3.600  
+981230 51177.00 I   .140598  .000106   .298726  .000102  I -.2812143  .0000060  1.1838 0.0048  I   -47.528     .384    -3.676     .131   .140690   .298710  -.2812110   -48.000    -3.800  
+981231 51178.00 I   .139675  .000101   .297292  .000109  I -.2823385  .0000062  1.0620 0.0038  I   -47.820     .384    -3.956     .131   .139760   .297390  -.2823330   -47.600    -3.900  
+99 1 1 51179.00 I   .138577  .000110   .295556  .000106  I  .7166587  .0000048  0.9492 0.0055  I   -47.878     .384    -4.035     .131   .138510   .295650   .7166370   -47.500    -4.100  
+99 1 2 51180.00 I   .137785  .000081   .293577  .000107  I  .7157494  .0000091  0.8776 0.0069  I   -47.682     .465    -3.856     .160   .137710   .293550   .7157410   -47.100    -4.300  
+99 1 3 51181.00 I   .137421  .000087   .291696  .000111  I  .7148885  .0000130  0.8510 0.0081  I   -47.278     .791    -3.620     .298   .137480   .291660   .7148720   -46.700    -4.400  
+99 1 4 51182.00 I   .137132  .000091   .290124  .000104  I  .7140379  .0000135  0.8529 0.0099  I   -46.762     .791    -3.573     .298   .137190   .290230   .7139820   -46.300    -4.300  
+99 1 5 51183.00 I   .136733  .000083   .288814  .000104  I  .7131775  .0000149  0.8702 0.0106  I   -46.302     .791    -3.734     .298   .136690   .288940   .7131390   -46.100    -4.200  
+99 1 6 51184.00 I   .136397  .000085   .287754  .000094  I  .7122751  .0000163  0.9546 0.0118  I   -46.058     .791    -3.893     .298   .136360   .287820   .7122810   -46.000    -4.000  
+99 1 7 51185.00 I   .136247  .000073   .287027  .000097  I  .7112608  .0000182  1.0616 0.0117  I   -46.047     .791    -3.871     .298   .136280   .287070   .7112410   -45.900    -3.600  
+99 1 8 51186.00 I   .136118  .000062   .286554  .000090  I  .7101793  .0000169  1.0866 0.0127  I   -46.166     .791    -3.703     .298   .136140   .286610   .7101380   -46.000    -3.400  
+99 1 9 51187.00 I   .135752  .000055   .286182  .000095  I  .7091003  .0000177  1.0737 0.0118  I   -46.356     .791    -3.545     .298   .135710   .286270   .7091040   -46.200    -3.200  
+99 110 51188.00 I   .134909  .000076   .285701  .000092  I  .7080310  .0000165  1.0635 0.0108  I   -46.640     .791    -3.475     .298   .134860   .285720   .7080490   -46.400    -3.100  
+99 111 51189.00 I   .133471  .000118   .284873  .000094  I  .7069893  .0000125  1.0051 0.0105  I   -46.985     .181    -3.444     .136   .133490   .284910   .7069560   -46.700    -3.100  
+99 112 51190.00 I   .131464  .000115   .283567  .000090  I  .7060440  .0000130  0.8769 0.0083  I   -47.259     .176    -3.366     .112   .131450   .283640   .7060060   -46.900    -3.100  
+99 113 51191.00 I   .129180  .000120   .281889  .000095  I  .7052302  .0000109  0.7646 0.0085  I   -47.387     .176    -3.229     .112   .129100   .281870   .7052330   -47.000    -3.300  
+99 114 51192.00 I   .126962  .000119   .279990  .000100  I  .7044958  .0000109  0.7091 0.0073  I   -47.455     .176    -3.108     .112   .126900   .280070   .7044610   -47.000    -3.400  
+99 115 51193.00 I   .124851  .000120   .277989  .000092  I  .7038139  .0000096  0.6477 0.0074  I   -47.512     .176    -3.137     .112   .124920   .278020   .7037620   -47.000    -3.500  
+99 116 51194.00 I   .122714  .000123   .276071  .000093  I  .7032033  .0000100  0.5777 0.0074  I   -47.503     .176    -3.349     .112   .122820   .276030   .7031910   -46.900    -3.600  
+99 117 51195.00 I   .120630  .000073   .274356  .000090  I  .7026480  .0000113  0.5392 0.0064  I   -47.340     .166    -3.626     .298   .120620   .274400   .7026250   -46.700    -3.600  
+99 118 51196.00 I   .118887  .000096   .272823  .000106  I  .7021026  .0000080  0.5676 0.0069  I   -47.048     .791    -3.800     .298   .118870   .272900   .7020740   -46.600    -3.600  
+99 119 51197.00 I   .117525  .000094   .271405  .000098  I  .7014865  .0000080  0.6747 0.0069  I   -46.777     .791    -3.794     .298   .117530   .271450   .7014750   -46.500    -3.600  
+99 120 51198.00 I   .116539  .000099   .270022  .000113  I  .7007330  .0000112  0.8423 0.0084  I   -46.640     .791    -3.676     .298   .116510   .270050   .7007330   -46.500    -3.600  
+99 121 51199.00 I   .116083  .000100   .268687  .000100  I  .6997928  .0000147  1.0373 0.0091  I   -46.604     .791    -3.568     .298   .116100   .268630   .6997900   -46.600    -3.600  
+99 122 51200.00 I   .116118  .000102   .267493  .000102  I  .6986675  .0000144  1.2050 0.0121  I   -46.568     .791    -3.522     .298   .116140   .267460   .6986490   -46.700    -3.600  
+99 123 51201.00 I   .116223  .000124   .266420  .000119  I  .6973983  .0000193  1.3262 0.0144  I   -46.497     .791    -3.504     .298   .116330   .266480   .6973720   -46.800    -3.600  
+99 124 51202.00 I   .115937  .000140   .265363  .000117  I  .6960300  .0000249  1.4029 0.0134  I   -46.465     .791    -3.479     .298   .116040   .265470   .6960030   -47.000    -3.600  
+99 125 51203.00 I   .115117  .000162   .264256  .000133  I  .6946208  .0000187  1.3948 0.0141  I   -46.584     .200    -3.478     .106   .115100   .264350   .6945500   -47.100    -3.600  
+99 126 51204.00 I   .113991  .000180   .263174  .000146  I  .6932696  .0000133  1.2991 0.0108  I   -46.893     .296    -3.577     .115   .113920   .263120   .6931850   -47.100    -3.700  
+99 127 51205.00 I   .112826  .000169   .262237  .000149  I  .6920205  .0000109  1.2098 0.0087  I   -47.300     .312    -3.820     .100   .112830   .262250   .6919960   -47.000    -3.800  
+99 128 51206.00 I   .111620  .000171   .261398  .000146  I  .6908379  .0000111  1.1568 0.0062  I   -47.630     .312    -4.136     .100   .111640   .261450   .6908520   -46.800    -3.900  
+99 129 51207.00 I   .110525  .000159   .260526  .000142  I  .6896941  .0000057  1.1422 0.0066  I   -47.705     .312    -4.271     .100   .110480   .260550   .6896900   -46.600    -4.000  
+99 130 51208.00 I   .109379  .000160   .259573  .000132  I  .6885405  .0000072  1.1665 0.0048  I   -47.600     .312    -4.157     .100   .109400   .259590   .6885240   -46.300    -4.100  
+99 131 51209.00 I   .108080  .000135   .258531  .000117  I  .6873571  .0000077  1.2029 0.0058  I   -47.418     .348    -3.950     .298   .108160   .258590   .6873410   -46.100    -4.200  
+99 2 1 51210.00 I   .106598  .000138   .257341  .000121  I  .6861313  .0000092  1.2494 0.0086  I   -47.214     .262    -3.884     .298   .106640   .257490   .6861150   -46.900    -4.200  
+99 2 2 51211.00 I   .105004  .000172   .256005  .000104  I  .6848593  .0000153  1.2930 0.0090  I   -46.983     .171    -4.080     .298   .105030   .256080   .6848460   -46.700    -4.300  
+99 2 3 51212.00 I   .103396  .000174   .254659  .000128  I  .6835503  .0000155  1.3218 0.0108  I   -46.725     .171    -4.430     .298   .103380   .254690   .6835470   -46.500    -4.500  
+99 2 4 51213.00 I   .101922  .000189   .253439  .000157  I  .6822214  .0000153  1.3336 0.0105  I   -46.559     .171    -4.657     .298   .101750   .253390   .6822120   -46.600    -4.700  
+99 2 5 51214.00 I   .100916  .000190   .252566  .000161  I  .6808880  .0000142  1.3308 0.0105  I   -46.571     .171    -4.685     .298   .100770   .252400   .6808730   -47.200    -4.400  
+99 2 6 51215.00 I   .100335  .000184   .252224  .000166  I  .6795667  .0000143  1.3073 0.0109  I   -46.749     .129    -4.628     .298   .100380   .252260   .6795660   -47.200    -4.500  
+99 2 7 51216.00 I   .099624  .000192   .252238  .000170  I  .6782837  .0000165  1.2529 0.0096  I   -47.008     .244    -4.601     .298   .099720   .252380   .6782890   -46.900    -5.000  
+99 2 8 51217.00 I   .098384  .000190   .252265  .000170  I  .6770716  .0000129  1.1665 0.0107  I   -47.202     .301    -4.608     .166   .098340   .252260   .6770550   -47.200    -4.900  
+99 2 9 51218.00 I   .096675  .000188   .252190  .000162  I  .6759507  .0000137  1.0800 0.0096  I   -47.252     .301    -4.589     .166   .096530   .252090   .6759100   -47.300    -4.600  
+99 210 51219.00 I   .094706  .000186   .251925  .000143  I  .6749074  .0000142  1.0062 0.0103  I   -47.200     .261    -4.537     .157   .094590   .252050   .6748970   -47.300    -4.400  
+99 211 51220.00 I   .092622  .000185   .251225  .000147  I  .6739383  .0000155  0.9326 0.0105  I   -47.053     .261    -4.638     .157   .092500   .251370   .6739270   -47.200    -4.300  
+99 212 51221.00 I   .090736  .000180   .250235  .000147  I  .6730319  .0000154  0.8901 0.0103  I   -46.899     .261    -4.883     .157   .090610   .250190   .6730310   -46.700    -4.200  
+99 213 51222.00 I   .089163  .000171   .249217  .000149  I  .6721348  .0000135  0.9176 0.0121  I   -46.812     .232    -5.137     .175   .089120   .249330   .6721840   -46.300    -4.400  
+99 214 51223.00 I   .087881  .000120   .248238  .000112  I  .6711759  .0000186  1.0075 0.0096  I   -46.760     .791    -5.353     .125   .087860   .248370   .6711830   -45.900    -4.400  
+99 215 51224.00 I   .086783  .000124   .247431  .000101  I  .6701095  .0000137  1.1284 0.0114  I   -46.648     .791    -5.413     .298   .086770   .247460   .6701030   -45.600    -4.500  
+99 216 51225.00 I   .085708  .000113   .246965  .000111  I  .6689138  .0000131  1.2651 0.0090  I   -46.401     .134    -5.227     .298   .085630   .246990   .6689060   -45.600    -4.700  
+99 217 51226.00 I   .084445  .000109   .246805  .000094  I  .6675690  .0000117  1.4327 0.0090  I   -46.049     .134    -4.889     .298   .084480   .246820   .6675580   -45.700    -4.700  
+99 218 51227.00 I   .082689  .000111   .246707  .000096  I  .6660476  .0000124  1.6028 0.0084  I   -45.728     .134    -4.641     .298   .082810   .246830   .6660510   -46.100    -4.700  
+99 219 51228.00 I   .080806  .000104   .246425  .000086  I  .6643896  .0000121  1.6944 0.0087  I   -45.613     .134    -4.616     .298   .080790   .246630   .6643680   -46.500    -4.700  
+99 220 51229.00 I   .079313  .000097   .245935  .000081  I  .6626922  .0000121  1.6860 0.0105  I   -45.768     .134    -4.750     .298   .079250   .246020   .6626600   -46.900    -4.700  
+99 221 51230.00 I   .078445  .000095   .245457  .000104  I  .6610367  .0000171  1.6205 0.0095  I   -46.092     .144    -4.918     .298   .078400   .245460   .6610490   -47.400    -4.700  
+99 222 51231.00 I   .078153  .000092   .245134  .000087  I  .6594679  .0000147  1.5049 0.0111  I   -46.465     .791    -5.026     .298   .078140   .245200   .6594700   -47.500    -4.700  
+99 223 51232.00 I   .078078  .000088   .244906  .000087  I  .6580462  .0000142  1.3315 0.0099  I   -46.815     .791    -5.072     .298   .078080   .244950   .6580360   -47.400    -4.900  
+99 224 51233.00 I   .077632  .000084   .244669  .000081  I  .6568065  .0000133  1.1532 0.0099  I   -47.075     .791    -5.107     .298   .077660   .244710   .6568110   -47.100    -5.000  
+99 225 51234.00 I   .076472  .000088   .244314  .000081  I  .6557266  .0000137  1.0145 0.0096  I   -47.155     .791    -5.161     .298   .076510   .244390   .6557030   -46.700    -5.200  
+99 226 51235.00 I   .074875  .000093   .243781  .000079  I  .6547633  .0000139  0.9184 0.0097  I   -47.000     .791    -5.216     .298   .074890   .243870   .6547300   -46.200    -5.400  
+99 227 51236.00 I   .073082  .000090   .243098  .000081  I  .6538706  .0000136  0.8800 0.0110  I   -46.668     .791    -5.242     .298   .073090   .243170   .6538810   -45.800    -5.500  
+99 228 51237.00 I   .071378  .000063   .242384  .000056  I  .6529831  .0000170  0.9022 0.0088  I   -46.327     .791    -5.260     .298   .071330   .242420   .6529950   -45.500    -5.700  
+99 3 1 51238.00 I   .069983  .000071   .241806  .000065  I  .6520627  .0000113  0.9350 0.0116  I   -46.124     .791    -5.336     .298   .069960   .241870   .6520380   -45.400    -5.700  
+99 3 2 51239.00 I   .068909  .000072   .241487  .000067  I  .6511207  .0000158  0.9451 0.0102  I   -46.061     .791    -5.504     .298   .068880   .241600   .6510780   -45.400    -5.700  
+99 3 3 51240.00 I   .068114  .000078   .241469  .000077  I  .6501709  .0000171  0.9601 0.0113  I   -46.029     .791    -5.696     .298   .068060   .241560   .6501610   -45.700    -5.700  
+99 3 4 51241.00 I   .067407  .000076   .241688  .000069  I  .6491932  .0000162  0.9971 0.0115  I   -46.000     .791    -5.803     .298   .067400   .241730   .6492320   -46.000    -5.700  
+99 3 5 51242.00 I   .066561  .000073   .242023  .000068  I  .6481793  .0000153  1.0262 0.0098  I   -46.084     .791    -5.799     .298   .066570   .242140   .6481930   -46.300    -5.600  
+99 3 6 51243.00 I   .065483  .000102   .242354  .000090  I  .6471690  .0000110  0.9708 0.0095  I   -46.347     .791    -5.754     .298   .065460   .242450   .6471360   -46.500    -5.600  
+99 3 7 51244.00 I   .064348  .000125   .242547  .000088  I  .6462538  .0000113  0.8672 0.0066  I   -46.648     .791    -5.748     .298   .064360   .242600   .6462500   -46.600    -5.600  
+99 3 8 51245.00 I   .063278  .000145   .242556  .000090  I  .6454247  .0000074  0.7933 0.0062  I   -46.764     .791    -5.789     .298   .063280   .242620   .6454270   -46.600    -5.700  
+99 3 9 51246.00 I   .062192  .000158   .242377  .000085  I  .6446631  .0000049  0.7318 0.0043  I   -46.623     .791    -5.839     .298   .062040   .242430   .6446490   -46.400    -5.700  
+99 310 51247.00 I   .061032  .000159   .242009  .000087  I  .6439529  .0000045  0.6951 0.0034  I   -46.311     .791    -5.857     .298   .060890   .242050   .6439460   -46.200    -5.800  
+99 311 51248.00 I   .059969  .000168   .241610  .000090  I  .6432600  .0000048  0.6971 0.0033  I   -45.903     .791    -5.815     .298   .059840   .241620   .6432690   -46.000    -5.800  
+99 312 51249.00 I   .058807  .000157   .241239  .000067  I  .6425445  .0000047  0.7417 0.0036  I   -45.456     .791    -5.726     .298   .058710   .241350   .6425460   -45.800    -5.900  
+99 313 51250.00 I   .057514  .000158   .240861  .000080  I  .6417607  .0000054  0.8340 0.0035  I   -45.108     .791    -5.693     .298   .057520   .241090   .6417470   -45.700    -6.000  
+99 314 51251.00 I   .056092  .000126   .240433  .000098  I  .6408596  .0000052  0.9770 0.0039  I   -45.028     .791    -5.818     .298   .056150   .240550   .6408520   -45.500    -6.000  
+99 315 51252.00 I   .054562  .000114   .239984  .000120  I  .6397960  .0000055  1.1522 0.0040  I   -45.165     .791    -6.058     .298   .054620   .239970   .6397940   -45.200    -6.100  
+99 316 51253.00 I   .052907  .000112   .239553  .000136  I  .6385563  .0000061  1.3240 0.0041  I   -45.220     .791    -6.234     .298   .052900   .239580   .6385570   -45.000    -6.200  
+99 317 51254.00 I   .051136  .000104   .239142  .000136  I  .6371559  .0000062  1.4721 0.0048  I   -44.996     .791    -6.233     .298   .051100   .239140   .6371530   -44.700    -6.200  
+99 318 51255.00 I   .049793  .000103   .238932  .000138  I  .6356238  .0000073  1.5850 0.0048  I   -44.655     .791    -6.111     .298   .049790   .238830   .6356030   -44.600    -6.200  
+99 319 51256.00 I   .048941  .000108   .239050  .000123  I  .6340022  .0000073  1.6489 0.0061  I   -44.570     .791    -6.095     .298   .049020   .238990   .6339940   -44.700    -6.200  
+99 320 51257.00 I   .048186  .000086   .239430  .000114  I  .6323403  .0000098  1.6697 0.0075  I   -44.878     .106    -6.311     .298   .048260   .239470   .6323600   -44.900    -6.300  
+99 321 51258.00 I   .047327  .000075   .239931  .000093  I  .6306782  .0000130  1.6442 0.0067  I   -45.346     .791    -6.634     .298   .047260   .239980   .6306790   -45.100    -6.400  
+99 322 51259.00 I   .046514  .000071   .240468  .000077  I  .6290778  .0000091  1.5409 0.0081  I   -45.660     .791    -6.856     .298   .046430   .240490   .6290540   -45.300    -6.400  
+99 323 51260.00 I   .045565  .000101   .240966  .000097  I  .6276165  .0000096  1.3774 0.0064  I   -45.699     .791    -6.887     .298   .045540   .241010   .6275870   -45.400    -6.500  
+99 324 51261.00 I   .044085  .000107   .241305  .000094  I  .6263131  .0000090  1.2436 0.0065  I   -45.537     .791    -6.777     .298   .044080   .241400   .6263030   -45.400    -6.700  
+99 325 51262.00 I   .042017  .000112   .241415  .000105  I  .6251109  .0000087  1.1648 0.0060  I   -45.278     .791    -6.621     .298   .041950   .241450   .6251350   -45.100    -6.800  
+99 326 51263.00 I   .039295  .000116   .241416  .000107  I  .6239616  .0000080  1.1516 0.0063  I   -44.959     .791    -6.551     .298   .039180   .241430   .6239720   -44.700    -7.000  
+99 327 51264.00 I   .036347  .000107   .241357  .000125  I  .6227854  .0000090  1.2054 0.0066  I   -44.580     .791    -6.601     .298   .036230   .241480   .6227770   -44.200    -7.000  
+99 328 51265.00 I   .033747  .000103   .241145  .000129  I  .6215430  .0000106  1.2825 0.0063  I   -44.207     .791    -6.741     .298   .033680   .241250   .6215430   -43.800    -7.100  
+99 329 51266.00 I   .031676  .000060   .240915  .000124  I  .6202226  .0000089  1.3530 0.0076  I   -43.975     .791    -6.930     .298   .031690   .240850   .6202090   -43.600    -7.200  
+99 330 51267.00 I   .029843  .000062   .240902  .000124  I  .6188504  .0000108  1.3831 0.0071  I   -43.952     .791    -7.096     .298   .029860   .240820   .6188340   -43.600    -7.100  
+99 331 51268.00 I   .027952  .000047   .241025  .000114  I  .6174612  .0000110  1.3986 0.0074  I   -44.055     .791    -7.163     .298   .028000   .241080   .6174570   -43.900    -7.100  
+99 4 1 51269.00 I   .025972  .000046   .240966  .000119  I  .6160514  .0000102  1.4196 0.0071  I   -44.177     .791    -7.111     .298   .026030   .241020   .6160780   -44.100    -7.100  
+99 4 2 51270.00 I   .023889  .000045   .240663  .000104  I  .6146313  .0000091  1.4128 0.0069  I   -44.333     .791    -7.012     .298   .023870   .240740   .6146500   -44.600    -7.100  
+99 4 3 51271.00 I   .021820  .000048   .240215  .000098  I  .6132443  .0000094  1.3505 0.0076  I   -44.574     .791    -6.956     .298   .021760   .240220   .6132240   -45.000    -7.100  
+99 4 4 51272.00 I   .020052  .000105   .239794  .000087  I  .6119391  .0000121  1.2617 0.0072  I   -44.827     .791    -6.963     .298   .019960   .239760   .6119380   -45.200    -7.100  
+99 4 5 51273.00 I   .018652  .000146   .239541  .000087  I  .6107150  .0000110  1.1907 0.0081  I   -44.962     .791    -7.003     .298   .018570   .239620   .6107220   -45.300    -7.200  
+99 4 6 51274.00 I   .017384  .000149   .239548  .000084  I  .6095457  .0000107  1.1558 0.0077  I   -44.989     .791    -7.069     .298   .017320   .239570   .6095590   -45.100    -7.200  
+99 4 7 51275.00 I   .015829  .000147   .239833  .000081  I  .6084018  .0000107  1.1257 0.0074  I   -45.007     .791    -7.166     .298   .015740   .239860   .6084080   -44.900    -7.100  
+99 4 8 51276.00 I   .013791  .000150   .240165  .000085  I  .6072974  .0000103  1.0862 0.0073  I   -44.959     .791    -7.240     .298   .013730   .240310   .6072760   -44.500    -7.100  
+99 4 9 51277.00 I   .012055  .000153   .240386  .000095  I  .6062115  .0000098  1.1002 0.0069  I   -44.678     .791    -7.199     .298   .011990   .240520   .6061980   -44.200    -7.100  
+99 410 51278.00 I   .010998  .000155   .240635  .000095  I  .6050749  .0000092  1.1804 0.0068  I   -44.248     .791    -7.066     .298   .010940   .240690   .6050670   -43.900    -7.100  
+99 411 51279.00 I   .010475  .000088   .241143  .000134  I  .6038335  .0000095  1.3121 0.0078  I   -44.036     .791    -7.015     .298   .010500   .241200   .6038210   -43.700    -7.000  
+99 412 51280.00 I   .010119  .000083   .241969  .000151  I  .6024322  .0000127  1.4991 0.0061  I   -44.206     .791    -7.154     .298   .010210   .242090   .6024510   -43.700    -7.000  
+99 413 51281.00 I   .009565  .000082   .242944  .000147  I  .6008268  .0000078  1.7116 0.0076  I   -44.423     .791    -7.346     .298   .009610   .243030   .6008480   -43.800    -7.100  
+99 414 51282.00 I   .008800  .000080   .243956  .000148  I  .5990280  .0000084  1.8672 0.0061  I   -44.271     .791    -7.351     .298   .008830   .243840   .5990220   -44.000    -7.200  
+99 415 51283.00 I   .008074  .000078   .245070  .000131  I  .5971222  .0000095  1.9336 0.0060  I   -43.819     .791    -7.158     .298   .008020   .244910   .5971310   -44.100    -7.300  
+99 416 51284.00 I   .007323  .000066   .246324  .000126  I  .5951849  .0000086  1.9279 0.0065  I   -43.559     .791    -7.024     .298   .007300   .246280   .5951890   -44.100    -7.500  
+99 417 51285.00 I   .006257  .000079   .247512  .000132  I  .5932963  .0000088  1.8325 0.0065  I   -43.772     .791    -7.166     .298   .006360   .247560   .5932790   -44.100    -7.600  
+99 418 51286.00 I   .004782  .000089   .248353  .000086  I  .5915380  .0000098  1.6829 0.0063  I   -44.219     .251    -7.503     .298   .004820   .248450   .5915350   -44.100    -7.800  
+99 419 51287.00 I   .003071  .000099   .248755  .000092  I  .5899323  .0000091  1.5280 0.0073  I   -44.483     .325    -7.783     .298   .002980   .248890   .5899240   -43.900    -7.900  
+99 420 51288.00 I   .001508  .000100   .248848  .000098  I  .5884751  .0000108  1.3936 0.0069  I   -44.426     .295    -7.869     .298   .001420   .248930   .5884800   -43.800    -7.800  
+99 421 51289.00 I   .000190  .000098   .248839  .000093  I  .5871312  .0000105  1.3007 0.0076  I   -44.255     .295    -7.827     .298   .000130   .248850   .5871390   -43.800    -7.700  
+99 422 51290.00 I  -.001057  .000101   .248911  .000095  I  .5858655  .0000106  1.2325 0.0077  I   -44.189     .295    -7.787     .298  -.001090   .248950   .5858710   -43.600    -7.600  
+99 423 51291.00 I  -.002271  .000103   .249270  .000091  I  .5846479  .0000112  1.2194 0.0079  I   -44.270     .295    -7.720     .298  -.002300   .249360   .5846520   -43.500    -7.500  
+99 424 51292.00 I  -.003651  .000095   .249966  .000081  I  .5834051  .0000116  1.2713 0.0088  I   -44.363     .268    -7.615     .298  -.003630   .250120   .5833930   -43.300    -7.300  
+99 425 51293.00 I  -.005339  .000082   .250849  .000052  I  .5820993  .0000136  1.3412 0.0103  I   -44.286     .126    -7.538     .298  -.005340   .251010   .5820920   -43.200    -7.300  
+99 426 51294.00 I  -.006985  .000083   .251766  .000048  I  .5807227  .0000170  1.4110 0.0108  I   -44.026     .791    -7.532     .298  -.007100   .251870   .5807220   -43.200    -7.400  
+99 427 51295.00 I  -.008027  .000082   .252694  .000051  I  .5792838  .0000169  1.4614 0.0123  I   -43.778     .791    -7.563     .298  -.008140   .252780   .5792780   -43.200    -7.400  
+99 428 51296.00 I  -.008362  .000084   .253742  .000048  I  .5778108  .0000179  1.4793 0.0112  I   -43.721     .791    -7.570     .298  -.008440   .253770   .5777930   -43.400    -7.500  
+99 429 51297.00 I  -.008472  .000088   .255001  .000051  I  .5763380  .0000146  1.4590 0.0110  I   -43.841     .791    -7.479     .298  -.008530   .255000   .5763270   -43.500    -7.500  
+99 430 51298.00 I  -.008673  .000085   .256408  .000053  I  .5749065  .0000127  1.3976 0.0087  I   -44.012     .791    -7.403     .298  -.008740   .256480   .5749090   -43.600    -7.400  
+99 5 1 51299.00 I  -.009270  .000083   .257734  .000058  I  .5735522  .0000095  1.3080 0.0078  I   -44.149     .791    -7.461     .298  -.009340   .257860   .5735560   -43.700    -7.500  
+99 5 2 51300.00 I  -.010432  .000074   .258759  .000078  I  .5722963  .0000090  1.2009 0.0063  I   -44.211     .791    -7.610     .298  -.010510   .258900   .5723070   -44.600    -7.600  
+99 5 3 51301.00 I  -.011958  .000109   .259424  .000083  I  .5711562  .0000082  1.0765 0.0060  I   -44.192     .791    -7.742     .298  -.011990   .259570   .5711640   -43.800    -7.600  
+99 5 4 51302.00 I  -.013543  .000106   .259790  .000092  I  .5701485  .0000080  0.9365 0.0058  I   -44.182     .791    -7.836     .298  -.013550   .260020   .5701520   -44.000    -7.800  
+99 5 5 51303.00 I  -.014882  .000102   .260006  .000094  I  .5692803  .0000081  0.8051 0.0057  I   -44.287     .791    -7.953     .298  -.014970   .260010   .5692870   -44.100    -7.900  
+99 5 6 51304.00 I  -.015809  .000105   .260357  .000096  I  .5685207  .0000081  0.7264 0.0059  I   -44.407     .791    -8.060     .298  -.015880   .260350   .5685460   -44.200    -7.900  
+99 5 7 51305.00 I  -.016511  .000098   .260980  .000098  I  .5677978  .0000085  0.7369 0.0056  I   -44.268     .791    -8.067     .298  -.016510   .261130   .5678080   -44.200    -7.900  
+99 5 8 51306.00 I  -.017204  .000086   .261793  .000100  I  .5670197  .0000078  0.8292 0.0056  I   -43.824     .791    -7.917     .298  -.017230   .261940   .5670120   -44.100    -8.000  
+99 5 9 51307.00 I  -.017955  .000070   .262620  .000088  I  .5661215  .0000072  0.9753 0.0053  I   -43.452     .791    -7.735     .298  -.018020   .262790   .5661330   -44.000    -8.000  
+99 510 51308.00 I  -.018562  .000059   .263437  .000080  I  .5650617  .0000071  1.1437 0.0051  I   -43.527     .791    -7.720     .298  -.018650   .263510   .5650480   -43.900    -7.900  
+99 511 51309.00 I  -.018908  .000060   .264417  .000084  I  .5638338  .0000071  1.3131 0.0050  I   -43.943     .791    -7.868     .298  -.019000   .264410   .5638010   -44.000    -7.900  
+99 512 51310.00 I  -.019144  .000058   .265626  .000080  I  .5624372  .0000071  1.4776 0.0057  I   -44.298     .791    -7.963     .298  -.019220   .265740   .5624390   -44.100    -7.900  
+99 513 51311.00 I  -.019272  .000063   .267017  .000079  I  .5608976  .0000089  1.5852 0.0051  I   -44.466     .791    -7.888     .298  -.019370   .267170   .5609190   -44.500    -7.900  
+99 514 51312.00 I  -.019234  .000065   .268489  .000053  I  .5593032  .0000074  1.5837 0.0077  I   -44.718     .791    -7.796     .298  -.019350   .268670   .5593160   -44.800    -7.900  
+99 515 51313.00 I  -.019058  .000060   .270015  .000054  I  .5577666  .0000126  1.4732 0.0075  I   -45.251     .791    -7.884     .298  -.019090   .270160   .5577750   -45.100    -7.900  
+99 516 51314.00 I  -.019061  .000071   .271612  .000076  I  .5563793  .0000131  1.2952 0.0086  I   -45.840     .791    -8.099     .298  -.019060   .271710   .5563890   -45.300    -8.000  
+99 517 51315.00 I  -.019409  .000093   .273248  .000087  I  .5551731  .0000118  1.1264 0.0086  I   -46.060     .243    -8.216     .298  -.019510   .273340   .5551900   -45.300    -8.000  
+99 518 51316.00 I  -.019872  .000093   .274767  .000100  I  .5541002  .0000112  1.0364 0.0075  I   -45.710     .245    -8.136     .298  -.019990   .274890   .5541190   -45.200    -8.000  
+99 519 51317.00 I  -.020213  .000090   .275981  .000098  I  .5530726  .0000094  1.0296 0.0076  I   -44.993     .245    -7.971     .298  -.020290   .276130   .5530890   -44.800    -8.000  
+99 520 51318.00 I  -.020417  .000091   .276839  .000102  I  .5520267  .0000104  1.0657 0.0074  I   -44.367     .245    -7.836     .298  -.020500   .276930   .5520360   -44.400    -7.900  
+99 521 51319.00 I  -.020523  .000081   .277505  .000098  I  .5509281  .0000115  1.1411 0.0080  I   -44.264     .245    -7.766     .298  -.020570   .277570   .5509490   -44.000    -7.800  
+99 522 51320.00 I  -.020535  .000083   .278185  .000095  I  .5497378  .0000121  1.2366 0.0094  I   -44.634     .245    -7.706     .298  -.020560   .278270   .5497680   -43.700    -7.600  
+99 523 51321.00 I  -.020552  .000059   .278928  .000089  I  .5484707  .0000149  1.2848 0.0102  I   -45.026     .249    -7.668     .298  -.020600   .279020   .5484720   -43.700    -7.600  
+99 524 51322.00 I  -.020768  .000045   .279657  .000087  I  .5471797  .0000164  1.2986 0.0110  I   -45.105     .791    -7.703     .298  -.020760   .279750   .5471860   -43.800    -7.500  
+99 525 51323.00 I  -.021347  .000045   .280333  .000097  I  .5458784  .0000161  1.2976 0.0116  I   -44.999     .791    -7.756     .298  -.021300   .280390   .5459010   -44.300    -7.600  
+99 526 51324.00 I  -.022250  .000048   .280942  .000097  I  .5446124  .0000165  1.2129 0.0110  I   -45.073     .791    -7.702     .298  -.022280   .280980   .5446230   -44.900    -7.600  
+99 527 51325.00 I  -.023138  .000056   .281436  .000095  I  .5434745  .0000149  1.0624 0.0111  I   -45.450     .791    -7.524     .298  -.023170   .281490   .5434710   -45.500    -7.700  
+99 528 51326.00 I  -.023752  .000054   .281994  .000095  I  .5424832  .0000149  0.9251 0.0100  I   -45.914     .791    -7.374     .298  -.023750   .282100   .5424970   -46.100    -7.800  
+99 529 51327.00 I  -.024118  .000055   .282646  .000095  I  .5416162  .0000134  0.8120 0.0112  I   -46.216     .791    -7.389     .298  -.024110   .282830   .5416450   -46.500    -7.900  
+99 530 51328.00 I  -.024418  .000078   .283263  .000065  I  .5408527  .0000167  0.7183 0.0099  I   -46.294     .791    -7.528     .298  -.024450   .283410   .5408500   -46.600    -8.000  
+99 531 51329.00 I  -.024737  .000101   .283829  .000084  I  .5401746  .0000146  0.6394 0.0114  I   -46.230     .297    -7.652     .189  -.024820   .283930   .5401390   -46.600    -8.000  
+99 6 1 51330.00 I  -.025164  .000109   .284461  .000087  I  .5395663  .0000154  0.5832 0.0112  I   -46.156     .297    -7.711     .189  -.025220   .284540   .5395750   -46.300    -8.000  
+99 6 2 51331.00 I  -.025839  .000103   .285250  .000092  I  .5389945  .0000171  0.5682 0.0111  I   -46.188     .297    -7.788     .189  -.025920   .285380   .5390250   -45.900    -8.000  
+99 6 3 51332.00 I  -.026663  .000099   .286131  .000092  I  .5384164  .0000161  0.5937 0.0118  I   -46.313     .297    -7.945     .189  -.026790   .286290   .5383850   -45.400    -7.900  
+99 6 4 51333.00 I  -.027370  .000103   .287157  .000101  I  .5377925  .0000162  0.6631 0.0109  I   -46.331     .297    -8.086     .189  -.027450   .287220   .5377750   -45.100    -7.700  
+99 6 5 51334.00 I  -.027956  .000102   .288463  .000097  I  .5370730  .0000146  0.7841 0.0109  I   -46.074     .297    -8.070     .189  -.027980   .288510   .5371050   -44.800    -7.600  
+99 6 6 51335.00 I  -.028608  .000059   .290007  .000066  I  .5362194  .0000145  0.9199 0.0093  I   -45.676     .791    -7.905     .298  -.028550   .290050   .5362130   -45.000    -7.500  
+99 6 7 51336.00 I  -.029271  .000063   .291489  .000075  I  .5352299  .0000115  1.0656 0.0094  I   -45.471     .791    -7.737     .298  -.029220   .291540   .5352240   -45.300    -7.400  
+99 6 8 51337.00 I  -.029839  .000057   .292673  .000069  I  .5340830  .0000121  1.2269 0.0085  I   -45.625     .791    -7.657     .298  -.029720   .292750   .5341110   -45.500    -7.500  
+99 6 9 51338.00 I  -.030385  .000065   .293489  .000065  I  .5327898  .0000125  1.3471 0.0101  I   -46.017     .791    -7.604     .298  -.030240   .293620   .5327920   -45.900    -7.500  
+99 610 51339.00 I  -.030823  .000065   .293963  .000053  I  .5314166  .0000162  1.3839 0.0105  I   -46.500     .791    -7.512     .298  -.030730   .294060   .5314210   -46.200    -7.500  
+99 611 51340.00 I  -.031123  .000067   .294357  .000057  I  .5300536  .0000168  1.3260 0.0113  I   -47.061     .791    -7.455     .298  -.031020   .294390   .5300850   -46.600    -7.600  
+99 612 51341.00 I  -.031394  .000085   .294908  .000056  I  .5287990  .0000158  1.1650 0.0112  I   -47.695     .791    -7.529     .298  -.031350   .295020   .5287960   -46.900    -7.600  
+99 613 51342.00 I  -.031599  .000084   .295656  .000066  I  .5277405  .0000149  0.9534 0.0104  I   -48.241     .791    -7.651     .298  -.031630   .295780   .5277610   -47.100    -7.500  
+99 614 51343.00 I  -.031741  .000097   .296616  .000091  I  .5268796  .0000135  0.7795 0.0102  I   -48.468     .207    -7.639     .298  -.031650   .296690   .5269420   -47.300    -7.500  
+99 615 51344.00 I  -.032060  .000092   .297675  .000093  I  .5261601  .0000138  0.6697 0.0089  I   -48.269     .207    -7.472     .298  -.031880   .297780   .5261980   -47.300    -7.400  
+99 616 51345.00 I  -.032633  .000091   .298575  .000103  I  .5255218  .0000116  0.6151 0.0090  I   -47.774     .207    -7.348     .298  -.032610   .298690   .5255170   -47.400    -7.200  
+99 617 51346.00 I  -.033005  .000086   .299226  .000107  I  .5249077  .0000116  0.6271 0.0078  I   -47.313     .207    -7.410     .298  -.033010   .299280   .5249170   -47.400    -7.200  
+99 618 51347.00 I  -.033064  .000088   .299759  .000105  I  .5242518  .0000104  0.6865 0.0072  I   -47.275     .207    -7.561     .298  -.032930   .299810   .5242620   -47.500    -7.100  
+99 619 51348.00 I  -.032912  .000071   .300307  .000091  I  .5235385  .0000084  0.7347 0.0062  I   -47.735     .249    -7.611     .298  -.032790   .300340   .5235260   -47.600    -7.000  
+99 620 51349.00 I  -.032633  .000047   .301003  .000058  I  .5227939  .0000069  0.7486 0.0051  I   -48.309     .791    -7.538     .298  -.032530   .301030   .5228120   -47.700    -7.000  
+99 621 51350.00 I  -.032416  .000053   .301872  .000056  I  .5220497  .0000059  0.7375 0.0048  I   -48.556     .791    -7.477     .298  -.032260   .301940   .5220930   -47.900    -7.100  
+99 622 51351.00 I  -.032382  .000054   .302784  .000051  I  .5213298  .0000068  0.6938 0.0044  I   -48.490     .791    -7.492     .298  -.032230   .302870   .5213500   -48.100    -7.200  
+99 623 51352.00 I  -.032414  .000061   .303630  .000043  I  .5206856  .0000065  0.5797 0.0055  I   -48.534     .791    -7.487     .298  -.032430   .303730   .5206850   -48.400    -7.300  
+99 624 51353.00 I  -.032237  .000061   .304449  .000044  I  .5201823  .0000086  0.4301 0.0050  I   -48.969     .791    -7.358     .298  -.032270   .304480   .5202060   -48.800    -7.400  
+99 625 51354.00 I  -.032009  .000066   .305351  .000051  I  .5198199  .0000077  0.2972 0.0079  I   -49.610     .791    -7.161     .298  -.031920   .305360   .5198390   -49.100    -7.500  
+99 626 51355.00 I  -.032072  .000073   .306343  .000046  I  .5195874  .0000133  0.1658 0.0085  I   -50.118     .241    -7.027     .298  -.031990   .306370   .5195890   -49.400    -7.600  
+99 627 51356.00 I  -.032424  .000106   .307330  .000063  I  .5194846  .0000152  0.0453 0.0087  I   -50.367     .325    -7.009     .298  -.032390   .307400   .5195020   -49.700    -7.700  
+99 628 51357.00 I  -.032681  .000110   .308172  .000069  I  .5194888  .0000112 -0.0514 0.0094  I   -50.404     .209    -7.053     .121  -.032680   .308260   .5194870   -49.900    -7.600  
+99 629 51358.00 I  -.032643  .000108   .308831  .000083  I  .5195759  .0000112 -0.1138 0.0082  I   -50.260     .202    -7.108     .105  -.032600   .308870   .5196000   -49.900    -7.500  
+99 630 51359.00 I  -.032439  .000107   .309415  .000080  I  .5196994  .0000120 -0.1253 0.0086  I   -49.982     .202    -7.181     .105  -.032410   .309380   .5197040   -49.700    -7.300  
+99 7 1 51360.00 I  -.032311  .000104   .310020  .000081  I  .5198139  .0000131 -0.0989 0.0089  I   -49.792     .202    -7.248     .105  -.032200   .309950   .5198250   -49.400    -7.100  
+99 7 2 51361.00 I  -.032153  .000104   .310745  .000081  I  .5198820  .0000132 -0.0269 0.0090  I   -49.812     .202    -7.308     .105  -.032030   .310750   .5199040   -49.100    -6.800  
+99 7 3 51362.00 I  -.031784  .000099   .311739  .000082  I  .5198545  .0000123  0.0849 0.0102  I   -49.908     .139    -7.323     .119  -.031690   .311740   .5198140   -48.900    -6.600  
+99 7 4 51363.00 I  -.031170  .000062   .313045  .000072  I  .5196951  .0000155  0.2482 0.0115  I   -49.912     .179    -7.252     .298  -.031120   .313080   .5197340   -48.700    -6.500  
+99 7 5 51364.00 I  -.030442  .000060   .314529  .000047  I  .5193487  .0000194  0.4396 0.0104  I   -49.865     .791    -7.109     .298  -.030430   .314630   .5194090   -48.900    -6.500  
+99 7 6 51365.00 I  -.029704  .000062   .315956  .000057  I  .5188292  .0000139  0.5910 0.0111  I   -49.964     .791    -6.948     .298  -.029680   .316030   .5188420   -49.600    -6.500  
+99 7 7 51366.00 I  -.028910  .000063   .317201  .000047  I  .5181918  .0000109  0.6672 0.0106  I   -50.356     .791    -6.819     .298  -.028900   .317270   .5181920   -50.100    -6.700  
+99 7 8 51367.00 I  -.027983  .000062   .318324  .000048  I  .5175273  .0000159  0.6461 0.0100  I   -51.019     .791    -6.775     .298  -.028030   .318330   .5175160   -50.800    -6.800  
+99 7 9 51368.00 I  -.027037  .000063   .319481  .000048  I  .5169244  .0000168  0.5508 0.0115  I   -51.790     .791    -6.877     .298  -.027030   .319480   .5169230   -51.400    -7.000  
+99 710 51369.00 I  -.026224  .000073   .320703  .000082  I  .5164345  .0000165  0.4291 0.0107  I   -52.452     .791    -7.115     .298  -.026250   .320820   .5164500   -51.800    -7.100  
+99 711 51370.00 I  -.025557  .000062   .321908  .000082  I  .5160590  .0000133  0.3291 0.0098  I   -52.823     .791    -7.344     .298  -.025590   .321960   .5160600   -52.100    -7.100  
+99 712 51371.00 I  -.025019  .000067   .323101  .000077  I  .5157613  .0000105  0.2742 0.0084  I   -52.850     .106    -7.379     .111  -.024980   .323000   .5157550   -52.100    -7.100  
+99 713 51372.00 I  -.024667  .000087   .324344  .000137  I  .5154946  .0000104  0.2674 0.0065  I   -52.595     .118    -7.216     .298  -.024670   .324210   .5154940   -52.000    -7.000  
+99 714 51373.00 I  -.024535  .000085   .325578  .000146  I  .5152068  .0000075  0.3196 0.0078  I   -52.187     .118    -7.077     .298  -.024560   .325580   .5152140   -51.800    -6.900  
+99 715 51374.00 I  -.024744  .000084   .326635  .000143  I  .5148456  .0000116  0.4012 0.0068  I   -51.829     .118    -7.158     .298  -.024670   .326630   .5148690   -51.700    -6.800  
+99 716 51375.00 I  -.025238  .000077   .327339  .000132  I  .5144052  .0000114  0.4803 0.0083  I   -51.750     .118    -7.340     .298  -.025120   .327330   .5144310   -51.500    -6.800  
+99 717 51376.00 I  -.025708  .000078   .327855  .000133  I  .5138917  .0000120  0.5392 0.0096  I   -52.082     .118    -7.389     .298  -.025670   .327860   .5138980   -51.600    -6.800  
+99 718 51377.00 I  -.025892  .000083   .328401  .000146  I  .5133447  .0000155  0.5443 0.0112  I   -52.651     .167    -7.243     .298  -.025820   .328410   .5133180   -51.900    -6.800  
+99 719 51378.00 I  -.025770  .000061   .329054  .000067  I  .5128171  .0000189  0.5073 0.0123  I   -53.103     .179    -7.063     .298  -.025650   .329040   .5127800   -52.300    -6.900  
+99 720 51379.00 I  -.025384  .000061   .329837  .000060  I  .5123367  .0000192  0.4506 0.0115  I   -53.303     .179    -7.029     .298  -.025280   .329830   .5123250   -52.900    -6.900  
+99 721 51380.00 I  -.024803  .000063   .330652  .000064  I  .5119213  .0000131  0.3778 0.0123  I   -53.444     .179    -7.135     .298  -.024770   .330670   .5119280   -53.500    -7.000  
+99 722 51381.00 I  -.024166  .000066   .331389  .000055  I  .5115879  .0000155  0.2847 0.0110  I   -53.672     .179    -7.196     .298  -.024170   .331470   .5115740   -54.000    -7.100  
+99 723 51382.00 I  -.023612  .000066   .332029  .000048  I  .5113555  .0000177  0.1809 0.0120  I   -53.947     .179    -7.123     .298  -.023650   .332070   .5113690   -54.400    -7.200  
+99 724 51383.00 I  -.023436  .000062   .332554  .000046  I  .5112222  .0000184  0.0887 0.0126  I   -54.161     .164    -6.993     .298  -.023290   .332570   .5112600   -54.700    -7.300  
+99 725 51384.00 I  -.023690  .000060   .332988  .000049  I  .5111749  .0000179  0.0061 0.0119  I   -54.310     .791    -6.929     .298  -.023610   .333050   .5111350   -54.800    -7.400  
+99 726 51385.00 I  -.023985  .000068   .333417  .000062  I  .5111988  .0000150 -0.0428 0.0112  I   -54.453     .169    -6.980     .187  -.023970   .333480   .5111610   -54.700    -7.400  
+99 727 51386.00 I  -.024026  .000079   .333921  .000073  I  .5112401  .0000133 -0.0304 0.0109  I   -54.561     .139    -7.092     .153  -.023980   .333980   .5112580   -54.700    -7.300  
+99 728 51387.00 I  -.023857  .000080   .334593  .000073  I  .5112419  .0000158  0.0350 0.0118  I   -54.587     .139    -7.161     .153  -.023810   .334630   .5112540   -54.700    -7.300  
+99 729 51388.00 I  -.023510  .000081   .335462  .000078  I  .5111595  .0000195  0.1321 0.0126  I   -54.624     .139    -7.130     .153  -.023400   .335520   .5111360   -54.800    -7.200  
+99 730 51389.00 I  -.023000  .000083   .336427  .000080  I  .5109628  .0000197  0.2739 0.0120  I   -54.828     .139    -7.049     .153  -.022860   .336460   .5109910   -55.000    -7.000  
+99 731 51390.00 I  -.022362  .000078   .337453  .000067  I  .5105973  .0000140  0.4589 0.0123  I   -55.189     .139    -7.009     .153  -.022280   .337490   .5106410   -55.000    -6.900  
+99 8 1 51391.00 I  -.021640  .000062   .338517  .000066  I  .5100551  .0000147  0.6137 0.0103  I   -55.507     .791    -7.042     .298  -.021570   .338540   .5100190   -55.200    -6.900  
+99 8 2 51392.00 I  -.020859  .000053   .339539  .000045  I  .5093789  .0000151  0.7414 0.0098  I   -55.621     .791    -7.098     .298  -.020830   .339690   .5093670   -55.300    -6.800  
+99 8 3 51393.00 I  -.019878  .000055   .340497  .000049  I  .5085788  .0000130  0.8496 0.0085  I   -55.601     .791    -7.107     .298  -.019910   .340720   .5086130   -55.500    -6.900  
+99 8 4 51394.00 I  -.018583  .000051   .341387  .000050  I  .5077202  .0000079  0.8365 0.0079  I   -55.652     .791    -7.071     .298  -.018720   .341550   .5077120   -55.700    -7.000  
+99 8 5 51395.00 I  -.017112  .000050   .342266  .000049  I  .5069471  .0000089  0.6996 0.0054  I   -55.892     .791    -7.068     .298  -.017190   .342340   .5069180   -55.600    -7.100  
+99 8 6 51396.00 I  -.015757  .000051   .343305  .000056  I  .5063317  .0000074  0.5306 0.0072  I   -56.243     .791    -7.181     .298  -.015620   .343440   .5063360   -55.700    -7.300  
+99 8 7 51397.00 I  -.014781  .000051   .344488  .000060  I  .5058809  .0000113  0.3766 0.0084  I   -56.493     .791    -7.401     .298  -.014670   .344680   .5058930   -55.600    -7.400  
+99 8 8 51398.00 I  -.014169  .000062   .345595  .000064  I  .5055680  .0000151  0.2542 0.0086  I   -56.471     .214    -7.598     .298  -.014300   .345840   .5055380   -55.600    -7.400  
+99 8 9 51399.00 I  -.013827  .000059   .346439  .000059  I  .5053520  .0000130  0.1932 0.0102  I   -56.196     .151    -7.622     .298  -.013890   .346680   .5053180   -55.500    -7.500  
+99 810 51400.00 I  -.013570  .000065   .347008  .000059  I  .5051508  .0000138  0.2247 0.0095  I   -55.853     .144    -7.450     .298  -.013640   .347170   .5051770   -55.500    -7.400  
+99 811 51401.00 I  -.013229  .000067   .347413  .000060  I  .5048772  .0000139  0.3325 0.0096  I   -55.639     .144    -7.233     .298  -.013310   .347500   .5048890   -55.500    -7.300  
+99 812 51402.00 I  -.012743  .000086   .347767  .000061  I  .5044897  .0000134  0.4288 0.0098  I   -55.608     .144    -7.139     .298  -.012860   .347800   .5044840   -55.500    -7.000  
+99 813 51403.00 I  -.012239  .000092   .348141  .000064  I  .5040260  .0000138  0.5060 0.0091  I   -55.764     .144    -7.231     .298  -.012470   .348220   .5040580   -55.700    -6.900  
+99 814 51404.00 I  -.011835  .000098   .348680  .000078  I  .5034709  .0000123  0.6037 0.0120  I   -56.134     .184    -7.367     .298  -.011940   .348780   .5034900   -55.800    -6.700  
+99 815 51405.00 I  -.011719  .000090   .349523  .000078  I  .5028289  .0000196  0.6707 0.0114  I   -56.653     .225    -7.390     .298  -.011760   .349630   .5028440   -56.000    -6.700  
+99 816 51406.00 I  -.011590  .000088   .350631  .000073  I  .5021460  .0000193  0.6882 0.0149  I   -57.117     .298    -7.320     .298  -.011790   .350780   .5021740   -56.300    -6.700  
+99 817 51407.00 I  -.011034  .000089   .351884  .000073  I  .5014710  .0000225  0.6500 0.0164  I   -57.303     .298    -7.253     .298  -.011220   .352100   .5014320   -56.400    -6.800  
+99 818 51408.00 I  -.010319  .000072   .353153  .000075  I  .5008619  .0000264  0.5639 0.0175  I   -57.153     .298    -7.195     .298  -.010320   .353250   .5008390   -56.700    -7.000  
+99 819 51409.00 I  -.009797  .000066   .354359  .000072  I  .5003492  .0000267  0.4597 0.0192  I   -56.878     .298    -7.109     .298  -.009880   .354600   .5003400   -57.000    -7.200  
+99 820 51410.00 I  -.009297  .000063   .355503  .000073  I  .4999451  .0000279  0.3476 0.0172  I   -56.660     .298    -6.936     .298  -.009530   .355730   .4999570   -57.100    -7.400  
+99 821 51411.00 I  -.008671  .000065   .356678  .000060  I  .4996400  .0000217  0.2776 0.0184  I   -56.613     .304    -6.727     .298  -.008740   .356860   .4997250   -57.300    -7.600  
+99 822 51412.00 I  -.008248  .000084   .357883  .000068  I  .4993711  .0000241  0.2642 0.0143  I   -56.776     .113    -6.641     .298  -.008330   .358130   .4993600   -57.300    -7.700  
+99 823 51413.00 I  -.008243  .000087   .358996  .000068  I  .4991033  .0000185  0.2759 0.0142  I   -57.052     .791    -6.790     .298  -.008270   .359220   .4990810   -57.300    -7.800  
+99 824 51414.00 I  -.008483  .000103   .359983  .000065  I  .4988082  .0000151  0.3211 0.0114  I   -57.239     .791    -7.145     .298  -.008450   .360160   .4988010   -57.200    -7.800  
+99 825 51415.00 I  -.008694  .000105   .360823  .000067  I  .4984339  .0000132  0.4479 0.0108  I   -57.195     .791    -7.533     .298  -.008880   .360930   .4984360   -57.200    -7.600  
+99 826 51416.00 I  -.008598  .000104   .361514  .000062  I  .4978839  .0000155  0.6604 0.0101  I   -57.012     .791    -7.700     .298  -.008690   .361790   .4979120   -57.000    -7.500  
+99 827 51417.00 I  -.008393  .000100   .362115  .000056  I  .4971095  .0000154  0.8839 0.0109  I   -56.883     .791    -7.596     .298  -.008440   .362310   .4971170   -56.900    -7.400  
+99 828 51418.00 I  -.008182  .000097   .362641  .000055  I  .4961321  .0000152  1.0594 0.0109  I   -56.917     .791    -7.396     .298  -.008280   .362810   .4961240   -57.000    -7.300  
+99 829 51419.00 I  -.007823  .000074   .363098  .000081  I  .4950086  .0000154  1.1810 0.0100  I   -57.065     .791    -7.297     .298  -.007930   .363190   .4950170   -56.900    -7.200  
+99 830 51420.00 I  -.007289  .000058   .363548  .000088  I  .4937904  .0000130  1.2416 0.0099  I   -57.212     .791    -7.341     .298  -.007340   .363690   .4937990   -57.000    -7.100  
+99 831 51421.00 I  -.006771  .000061   .364020  .000086  I  .4925551  .0000125  1.2133 0.0071  I   -57.308     .791    -7.416     .298  -.006770   .364210   .4925550   -57.100    -7.200  
+99 9 1 51422.00 I  -.006488  .000058   .364447  .000089  I  .4913924  .0000059  1.0994 0.0092  I   -57.404     .791    -7.409     .298  -.006490   .364650   .4913850   -57.200    -7.300  
+99 9 2 51423.00 I  -.006386  .000060   .364778  .000102  I  .4903690  .0000136  0.9476 0.0078  I   -57.570     .791    -7.321     .298  -.006430   .364930   .4903750   -57.300    -7.300  
+99 9 3 51424.00 I  -.006220  .000056   .365077  .000095  I  .4894913  .0000145  0.8137 0.0100  I   -57.793     .791    -7.237     .298  -.006220   .365200   .4895020   -57.400    -7.400  
+99 9 4 51425.00 I  -.005751  .000045   .365411  .000091  I  .4887284  .0000147  0.7195 0.0108  I   -57.956     .791    -7.211     .298  -.005850   .365580   .4887250   -56.800    -9.400  
+99 9 5 51426.00 I  -.004880  .000053   .365869  .000083  I  .4880370  .0000160  0.6711 0.0103  I   -57.921     .791    -7.216     .298  -.004960   .366010   .4880420   -56.200    -9.400  
+99 9 6 51427.00 I  -.003703  .000047   .366428  .000092  I  .4873721  .0000145  0.6650 0.0109  I   -57.637     .176    -7.174     .191  -.003810   .366600   .4873840   -55.800    -9.000  
+99 9 7 51428.00 I  -.002464  .000048   .367003  .000095  I  .4866972  .0000149  0.6883 0.0087  I   -57.197     .176    -7.042     .191  -.002570   .367190   .4867060   -55.700    -8.200  
+99 9 8 51429.00 I  -.001309  .000049   .367620  .000085  I  .4859923  .0000095  0.7211 0.0090  I   -56.771     .176    -6.869     .191  -.001440   .367610   .4860000   -55.900    -7.100  
+99 9 9 51430.00 I  -.000411  .000049   .368267  .000086  I  .4852548  .0000101  0.7545 0.0068  I   -56.497     .176    -6.756     .191  -.000550   .368300   .4852780   -56.300    -5.900  
+99 910 51431.00 I   .000061  .000059   .368863  .000087  I  .4844846  .0000096  0.7841 0.0071  I   -56.414     .176    -6.745     .191   .000030   .369070   .4845120   -56.900    -5.000  
+99 911 51432.00 I   .000383  .000065   .369397  .000095  I  .4836996  .0000101  0.7749 0.0071  I   -56.488     .176    -6.782     .191   .000460   .369580   .4837120   -57.700    -4.500  
+99 912 51433.00 I   .000863  .000058   .369937  .000070  I  .4829502  .0000105  0.7195 0.0070  I   -56.684     .791    -6.805     .298   .000800   .370170   .4829480   -58.400    -4.500  
+99 913 51434.00 I   .001600  .000058   .370608  .000102  I  .4822679  .0000098  0.6420 0.0075  I   -56.957     .791    -6.839     .298   .001620   .370730   .4822670   -58.700    -4.900  
+99 914 51435.00 I   .002414  .000058   .371490  .000109  I  .4816712  .0000108  0.5494 0.0070  I   -57.187     .791    -6.950     .298   .002450   .371490   .4816770   -58.600    -5.800  
+99 915 51436.00 I   .003040  .000055   .372432  .000110  I  .4811759  .0000100  0.4365 0.0075  I   -57.197     .791    -7.113     .298   .003040   .372620   .4811780   -58.100    -6.800  
+99 916 51437.00 I   .003503  .000049   .373142  .000117  I  .4807967  .0000103  0.3283 0.0070  I   -56.947     .791    -7.205     .298   .003510   .373430   .4807760   -57.400    -8.000  
+99 917 51438.00 I   .003889  .000044   .373599  .000101  I  .4805028  .0000099  0.2697 0.0070  I   -56.642     .791    -7.142     .298   .003850   .373750   .4804930   -56.500    -9.000  
+99 918 51439.00 I   .004184  .000053   .373979  .000097  I  .4802355  .0000094  0.2764 0.0066  I   -56.571     .791    -6.984     .298   .004070   .374060   .4802480   -55.600    -9.500  
+99 919 51440.00 I   .004345  .000057   .374430  .000069  I  .4799329  .0000086  0.3345 0.0057  I   -56.794     .243    -6.865     .298   .004280   .374520   .4799360   -54.900    -9.600  
+99 920 51441.00 I   .004513  .000061   .374913  .000065  I  .4795506  .0000066  0.4404 0.0052  I   -57.069     .248    -6.869     .298   .004470   .375080   .4795610   -54.500    -9.100  
+99 921 51442.00 I   .004887  .000065   .375305  .000061  I  .4790321  .0000059  0.6064 0.0047  I   -57.122     .248    -6.971     .298   .004820   .375420   .4790480   -54.700    -8.300  
+99 922 51443.00 I   .005344  .000059   .375576  .000057  I  .4783296  .0000068  0.7971 0.0048  I   -56.919     .248    -7.059     .298   .005330   .375590   .4783330   -55.400    -7.200  
+99 923 51444.00 I   .005458  .000058   .375778  .000063  I  .4774428  .0000076  0.9730 0.0050  I   -56.693     .248    -7.003     .298   .005560   .375850   .4774500   -56.400    -6.000  
+99 924 51445.00 I   .005210  .000048   .375829  .000070  I  .4763994  .0000073  1.1015 0.0056  I   -56.571     .248    -6.753     .298   .005150   .376030   .4764010   -57.500    -5.100  
+99 925 51446.00 I   .004983  .000048   .375759  .000060  I  .4752638  .0000081  1.1581 0.0076  I   -56.552     .251    -6.423     .298   .004960   .375910   .4752540   -58.500    -4.500  
+99 926 51447.00 I   .005018  .000048   .375787  .000092  I  .4740970  .0000134  1.1735 0.0087  I   -56.643     .791    -6.241     .298   .005000   .375900   .4741130   -59.300    -4.400  
+99 927 51448.00 I   .005262  .000043   .376086  .000100  I  .4729339  .0000153  1.1377 0.0099  I   -56.864     .791    -6.341     .298   .005160   .376130   .4729480   -59.600    -4.800  
+99 928 51449.00 I   .005564  .000051   .376625  .000102  I  .4718474  .0000147  1.0245 0.0106  I   -57.166     .791    -6.617     .298   .005430   .376760   .4718160   -59.300    -5.600  
+99 929 51450.00 I   .005826  .000056   .377307  .000101  I  .4708876  .0000147  0.9034 0.0106  I   -57.432     .791    -6.823     .298   .005810   .377530   .4708750   -58.400    -6.600  
+99 930 51451.00 I   .006099  .000059   .378097  .000099  I  .4700343  .0000154  0.8014 0.0106  I   -57.567     .791    -6.800     .298   .006070   .378340   .4700530   -57.300    -7.600  
+9910 1 51452.00 I   .006366  .000064   .378984  .000099  I  .4692888  .0000152  0.6876 0.0098  I   -57.566     .791    -6.600     .298   .006260   .379200   .4692770   -56.000    -8.500  
+9910 2 51453.00 I   .006616  .000061   .379890  .000105  I  .4686406  .0000121  0.6295 0.0091  I   -57.458     .791    -6.380     .298   .006580   .380060   .4686480   -54.800    -8.900  
+9910 3 51454.00 I   .007091  .000060   .380748  .000084  I  .4679841  .0000099  0.7086 0.0083  I   -57.245     .791    -6.243     .298   .007070   .380920   .4680100   -54.000    -8.900  
+9910 4 51455.00 I   .007760  .000092   .381484  .000097  I  .4671962  .0000115  0.8692 0.0074  I   -56.917     .313    -6.196     .298   .007850   .381800   .4672270   -52.300    -6.000  
+9910 5 51456.00 I   .008441  .000096   .382034  .000096  I  .4662445  .0000110  1.0335 0.0076  I   -56.508     .313    -6.211     .298   .008400   .382310   .4662570   -53.600    -6.000  
+9910 6 51457.00 I   .009156  .000102   .382437  .000104  I  .4651338  .0000099  1.1840 0.0076  I   -56.129     .313    -6.271     .298   .009120   .382600   .4651320   -55.400    -6.200  
+9910 7 51458.00 I   .009792  .000100   .382579  .000105  I  .4638922  .0000106  1.2876 0.0074  I   -55.896     .313    -6.304     .298   .010140   .382930   .4639000   -56.800    -6.300  
+9910 8 51459.00 I   .010453  .000102   .382483  .000108  I  .4625759  .0000109  1.3394 0.0084  I   -55.847     .313    -6.270     .298   .010710   .382670   .4625900   -57.600    -6.200  
+9910 9 51460.00 I   .011302  .000118   .382442  .000095  I  .4612270  .0000131  1.3502 0.0076  I   -55.898     .315    -6.163     .298   .011250   .382540   .4612430   -57.600    -6.200  
+991010 51461.00 I   .012327  .000087   .382576  .000077  I  .4598931  .0000106  1.3080 0.0081  I   -55.943     .791    -6.021     .298   .012270   .382700   .4599020   -57.200    -6.000  
+991011 51462.00 I   .013291  .000088   .382712  .000077  I  .4586308  .0000094  1.2064 0.0077  I   -55.939     .791    -5.932     .298   .013270   .382940   .4586320   -56.500    -6.000  
+991012 51463.00 I   .013933  .000083   .382739  .000053  I  .4574905  .0000112  1.0741 0.0066  I   -55.842     .791    -5.953     .298   .013950   .382940   .4574970   -55.800    -5.900  
+991013 51464.00 I   .014160  .000085   .382696  .000052  I  .4564699  .0000094  0.9797 0.0072  I   -55.544     .791    -6.029     .298   .014140   .382830   .4564730   -55.300    -5.900  
+991014 51465.00 I   .014011  .000090   .382620  .000050  I  .4555245  .0000092  0.9049 0.0065  I   -55.045     .791    -6.071     .298   .013960   .382790   .4555120   -54.300    -5.900  
+991015 51466.00 I   .013764  .000093   .382574  .000049  I  .4546679  .0000091  0.8066 0.0063  I   -54.573     .791    -6.029     .298   .013670   .382780   .4546620   -52.700    -5.800  
+991016 51467.00 I   .013723  .000093   .382518  .000048  I  .4539027  .0000086  0.7339 0.0064  I   -54.432     .791    -5.960     .298   .013670   .382760   .4539230   -51.100    -5.600  
+991017 51468.00 I   .013998  .000082   .382379  .000048  I  .4531777  .0000089  0.7283 0.0057  I   -54.628     .791    -5.945     .298   .014010   .382650   .4531920   -50.300    -5.600  
+991018 51469.00 I   .014481  .000090   .382265  .000051  I  .4524251  .0000074  0.7857 0.0059  I   -54.817     .791    -5.976     .298   .014510   .382440   .4524180   -50.700    -5.600  
+991019 51470.00 I   .015066  .000087   .382334  .000050  I  .4515871  .0000077  0.9008 0.0052  I   -54.729     .791    -5.994     .298   .015050   .382360   .4515800   -52.000    -5.800  
+991020 51471.00 I   .015704  .000088   .382570  .000052  I  .4505951  .0000073  1.1013 0.0053  I   -54.466     .791    -5.968     .298   .015740   .382680   .4505970   -53.800    -5.800  
+991021 51472.00 I   .016335  .000079   .382806  .000059  I  .4493644  .0000074  1.3623 0.0049  I   -54.269     .791    -5.880     .298   .016400   .382990   .4493660   -55.300    -5.900  
+991022 51473.00 I   .016759  .000077   .382957  .000053  I  .4478747  .0000066  1.6108 0.0053  I   -54.163     .791    -5.685     .298   .016850   .383150   .4478740   -56.100    -5.900  
+991023 51474.00 I   .017150  .000065   .383056  .000064  I  .4461607  .0000076  1.8056 0.0057  I   -54.007     .791    -5.385     .298   .017130   .383230   .4461670   -55.800    -5.700  
+991024 51475.00 I   .017702  .000061   .383229  .000064  I  .4442931  .0000092  1.9114 0.0057  I   -53.796     .176    -5.130     .298   .017730   .383390   .4442970   -54.900    -5.500  
+991025 51476.00 I   .018291  .000058   .383481  .000062  I  .4423756  .0000086  1.9040 0.0064  I   -53.705     .168    -5.112     .298   .018330   .383650   .4423640   -54.000    -5.300  
+991026 51477.00 I   .018863  .000064   .383621  .000064  I  .4405168  .0000089  1.8015 0.0062  I   -53.831     .168    -5.329     .298   .018810   .383830   .4405100   -53.500    -5.300  
+991027 51478.00 I   .019452  .000065   .383532  .000057  I  .4388010  .0000089  1.6137 0.0064  I   -54.074     .168    -5.541     .298   .019430   .383710   .4387960   -54.000    -5.500  
+991028 51479.00 I   .019978  .000073   .383305  .000058  I  .4372960  .0000092  1.4062 0.0065  I   -54.225     .168    -5.543     .298   .019970   .383500   .4372900   -54.500    -5.600  
+991029 51480.00 I   .020327  .000077   .383128  .000059  I  .4359633  .0000095  1.2747 0.0069  I   -54.232     .168    -5.353     .298   .020230   .383360   .4359710   -54.800    -5.700  
+991030 51481.00 I   .020502  .000073   .383004  .000063  I  .4347173  .0000102  1.2311 0.0071  I   -54.157     .159    -5.162     .298   .020480   .383150   .4347180   -54.800    -5.800  
+991031 51482.00 I   .020765  .000076   .382805  .000106  I  .4334775  .0000105  1.2582 0.0072  I   -54.049     .791    -5.102     .298   .020760   .382990   .4334870   -54.600    -5.700  
+9911 1 51483.00 I   .021271  .000102   .382449  .000116  I  .4321898  .0000102  1.3188 0.0073  I   -53.920     .791    -5.144     .298   .021280   .382720   .4321920   -54.100    -5.600  
+9911 2 51484.00 I   .021918  .000097   .381946  .000117  I  .4308357  .0000100  1.3922 0.0070  I   -53.758     .791    -5.195     .298   .021890   .382230   .4308260   -53.700    -5.300  
+9911 3 51485.00 I   .022609  .000092   .381443  .000121  I  .4294020  .0000097  1.4758 0.0070  I   -53.560     .791    -5.220     .298   .022700   .381380   .4293980   -53.500    -5.200  
+9911 4 51486.00 I   .023219  .000089   .380905  .000120  I  .4278975  .0000098  1.5193 0.0067  I   -53.385     .791    -5.213     .298   .023300   .380950   .4279030   -53.100    -5.000  
+9911 5 51487.00 I   .023757  .000086   .380406  .000121  I  .4263817  .0000091  1.5080 0.0071  I   -53.322     .791    -5.134     .298   .023730   .380400   .4263920   -52.900    -4.800  
+9911 6 51488.00 I   .024151  .000095   .380035  .000121  I  .4248891  .0000102  1.4740 0.0065  I   -53.379     .791    -4.942     .298   .024130   .380020   .4249070   -52.900    -4.600  
+9911 7 51489.00 I   .024358  .000091   .379606  .000080  I  .4234446  .0000092  1.4073 0.0069  I   -53.452     .791    -4.689     .298   .024420   .379640   .4234540   -52.900    -4.600  
+9911 8 51490.00 I   .024501  .000073   .378912  .000122  I  .4220772  .0000094  1.3323 0.0075  I   -53.430     .791    -4.523     .298   .024490   .378880   .4220890   -52.900    -4.500  
+9911 9 51491.00 I   .024892  .000085   .378025  .000132  I  .4207713  .0000119  1.2833 0.0071  I   -53.264     .791    -4.539     .298   .024840   .377880   .4207840   -52.900    -4.600  
+991110 51492.00 I   .025657  .000089   .377145  .000141  I  .4195125  .0000107  1.2288 0.0082  I   -52.931     .791    -4.668     .298   .025610   .377150   .4195120   -52.800    -4.600  
+991111 51493.00 I   .026741  .000099   .376460  .000151  I  .4183198  .0000113  1.1562 0.0074  I   -52.458     .791    -4.749     .298   .026750   .376460   .4183170   -52.500    -4.700  
+991112 51494.00 I   .027764  .000108   .376262  .000156  I  .4171923  .0000103  1.1071 0.0082  I   -52.027     .791    -4.713     .298   .027750   .376140   .4172030   -52.100    -4.700  
+991113 51495.00 I   .028474  .000113   .376609  .000153  I  .4160811  .0000120  1.1317 0.0077  I   -51.874     .791    -4.640     .298   .028440   .376550   .4160980   -51.800    -4.800  
+991114 51496.00 I   .028809  .000125   .377310  .000129  I  .4149095  .0000114  1.2147 0.0079  I   -51.991     .791    -4.607     .298   .028950   .377350   .4149150   -51.500    -4.800  
+991115 51497.00 I   .028761  .000121   .377949  .000113  I  .4136514  .0000104  1.2986 0.0076  I   -52.073     .791    -4.572     .298   .028830   .378060   .4136300   -51.300    -4.600  
+991116 51498.00 I   .028712  .000105   .378224  .000111  I  .4123109  .0000100  1.3866 0.0069  I   -51.914     .791    -4.469     .298   .028600   .378260   .4122870   -51.300    -4.500  
+991117 51499.00 I   .029229  .000100   .378250  .000100  I  .4108591  .0000092  1.5319 0.0068  I   -51.686     .791    -4.342     .298   .029220   .378260   .4108540   -51.500    -4.400  
+991118 51500.00 I   .030311  .000085   .378225  .000091  I  .4092440  .0000093  1.6865 0.0057  I   -51.638     .791    -4.256     .298   .030320   .378220   .4092360   -51.800    -4.200  
+991119 51501.00 I   .031599  .000085   .378298  .000081  I  .4075068  .0000069  1.7789 0.0058  I   -51.743     .791    -4.188     .298   .031550   .378290   .4074990   -52.100    -4.000  
+991120 51502.00 I   .032630  .000070   .378479  .000070  I  .4057008  .0000068  1.8273 0.0067  I   -51.774     .791    -4.034     .298   .032670   .378520   .4057080   -52.400    -3.800  
+991121 51503.00 I   .033130  .000073   .378618  .000055  I  .4038769  .0000116  1.8015 0.0057  I   -51.673     .791    -3.805     .298   .033180   .378650   .4038770   -52.500    -3.900  
+991122 51504.00 I   .033152  .000080   .378618  .000052  I  .4021328  .0000092  1.6708 0.0075  I   -51.620     .791    -3.685     .298   .033160   .378630   .4021340   -52.400    -3.800  
+991123 51505.00 I   .032879  .000082   .378417  .000055  I  .4005584  .0000096  1.4707 0.0066  I   -51.707     .791    -3.783     .298   .032830   .378490   .4005630   -52.100    -3.800  
+991124 51506.00 I   .032516  .000075   .378016  .000054  I  .3991948  .0000095  1.2605 0.0070  I   -51.795     .791    -3.944     .298   .032520   .378050   .3991930   -51.700    -3.900  
+991125 51507.00 I   .032158  .000081   .377578  .000064  I  .3980249  .0000102  1.0878 0.0070  I   -51.724     .791    -3.926     .298   .032220   .377580   .3980150   -51.300    -4.000  
+991126 51508.00 I   .031840  .000081   .377205  .000066  I  .3969956  .0000103  0.9858 0.0068  I   -51.496     .791    -3.714     .298   .031880   .377270   .3969800   -50.800    -4.000  
+991127 51509.00 I   .031731  .000084   .376900  .000065  I  .3960227  .0000089  0.9757 0.0076  I   -51.223     .791    -3.529     .298   .031730   .376960   .3960080   -50.500    -4.000  
+991128 51510.00 I   .032013  .000080   .376716  .000076  I  .3950159  .0000112  1.0505 0.0069  I   -51.008     .791    -3.520     .298   .031980   .376690   .3950130   -50.300    -4.000  
+991129 51511.00 I   .032624  .000068   .376739  .000074  I  .3939021  .0000105  1.1841 0.0077  I   -50.914     .791    -3.599     .298   .032620   .376770   .3939120   -50.300    -3.900  
+991130 51512.00 I   .033305  .000076   .377007  .000074  I  .3926455  .0000107  1.3244 0.0073  I   -50.926     .791    -3.611     .298   .033360   .377030   .3926480   -50.400    -3.700  
+9912 1 51513.00 I   .033866  .000080   .377511  .000070  I  .3912784  .0000101  1.3893 0.0083  I   -50.925     .791    -3.552     .298   .033910   .377480   .3912670   -50.700    -3.500  
+9912 2 51514.00 I   .034243  .000076   .378168  .000064  I  .3898971  .0000126  1.3637 0.0083  I   -50.824     .791    -3.522     .298   .034260   .378180   .3898730   -51.000    -3.400  
+9912 3 51515.00 I   .034482  .000070   .378767  .000060  I  .3885654  .0000132  1.2948 0.0081  I   -50.710     .791    -3.534     .298   .034480   .378850   .3885010   -51.300    -3.200  
+9912 4 51516.00 I   .034712  .000069   .379145  .000084  I  .3873141  .0000101  1.2061 0.0094  I   -50.740     .791    -3.497     .298   .034700   .379180   .3872730   -51.500    -3.100  
+9912 5 51517.00 I   .034806  .000064   .379274  .000088  I  .3861571  .0000133  1.1056 0.0074  I   -50.909     .791    -3.374     .298   .034850   .379330   .3861610   -51.500    -3.000  
+9912 6 51518.00 I   .034636  .000073   .379187  .000085  I  .3851032  .0000108  1.0043 0.0086  I   -51.049     .791    -3.267     .298   .034710   .379240   .3851200   -51.400    -3.000  
+9912 7 51519.00 I   .034509  .000074   .378991  .000086  I  .3841467  .0000109  0.9086 0.0072  I   -51.030     .791    -3.288     .298   .034490   .378970   .3841480   -51.200    -3.200  
+9912 8 51520.00 I   .034839  .000075   .378900  .000087  I  .3832822  .0000096  0.8243 0.0076  I   -50.877     .791    -3.408     .298   .034790   .378900   .3832790   -50.800    -3.300  
+9912 9 51521.00 I   .035705  .000077   .379108  .000089  I  .3824822  .0000105  0.7878 0.0073  I   -50.690     .791    -3.522     .298   .035700   .379150   .3824670   -50.300    -3.500  
+991210 51522.00 I   .036626  .000078   .379542  .000089  I  .3816877  .0000109  0.8082 0.0077  I   -50.579     .791    -3.565     .298   .036690   .379600   .3816790   -50.000    -3.600  
+991211 51523.00 I   .037157  .000103   .379986  .000071  I  .3808536  .0000113  0.8652 0.0076  I   -50.647     .791    -3.582     .298   .037230   .380060   .3808610   -49.800    -3.600  
+991212 51524.00 I   .037313  .000105   .380340  .000073  I  .3799565  .0000105  0.9244 0.0071  I   -50.882     .791    -3.625     .298   .037340   .380370   .3799460   -49.700    -3.600  
+991213 51525.00 I   .037388  .000116   .380650  .000091  I  .3789967  .0000086  1.0077 0.0065  I   -51.095     .791    -3.633     .298   .037370   .380650   .3790130   -49.900    -3.500  
+991214 51526.00 I   .037709  .000113   .381013  .000090  I  .3779240  .0000075  1.1421 0.0054  I   -51.109     .791    -3.518     .298   .037680   .380980   .3779550   -50.300    -3.400  
+991215 51527.00 I   .038233  .000110   .381469  .000086  I  .3767143  .0000064  1.2709 0.0052  I   -50.970     .791    -3.325     .298   .038290   .381490   .3767130   -50.700    -3.200  
+991216 51528.00 I   .038411  .000118   .381831  .000085  I  .3753863  .0000073  1.3872 0.0045  I   -50.851     .791    -3.220     .298   .038470   .381890   .3753720   -51.100    -3.100  
+991217 51529.00 I   .038307  .000124   .381983  .000091  I  .3739443  .0000063  1.4902 0.0043  I   -50.764     .791    -3.231     .298   .038300   .381920   .3739430   -51.500    -3.000  
+991218 51530.00 I   .038151  .000112   .382020  .000084  I  .3724233  .0000045  1.5412 0.0046  I   -50.606     .791    -3.214     .298   .038120   .381980   .3724420   -51.800    -3.000  
+991219 51531.00 I   .037966  .000114   .382019  .000076  I  .3708867  .0000068  1.5180 0.0047  I   -50.434     .791    -3.085     .298   .037990   .382080   .3709520   -51.800    -3.000  
+991220 51532.00 I   .037613  .000104   .381863  .000104  I  .3694136  .0000083  1.4159 0.0053  I   -50.456     .791    -2.967     .298   .037700   .381940   .3694790   -51.700    -3.000  
+991221 51533.00 I   .037076  .000112   .381420  .000101  I  .3680734  .0000082  1.2581 0.0056  I   -50.710     .791    -3.008     .298   .037210   .381360   .3680520   -51.400    -3.000  
+991222 51534.00 I   .036608  .000121   .380682  .000118  I  .3668939  .0000074  1.1106 0.0055  I   -50.948     .791    -3.136     .298   .036610   .380730   .3668750   -50.900    -3.100  
+991223 51535.00 I   .036570  .000122   .379666  .000122  I  .3658297  .0000074  1.0306 0.0052  I   -50.913     .791    -3.137     .298   .036540   .379730   .3658610   -50.400    -3.100  
+991224 51536.00 I   .037112  .000109   .378618  .000115  I  .3648087  .0000074  1.0226 0.0079  I   -50.581     .791    -2.970     .298   .037160   .378560   .3647670   -49.900    -3.100  
+991225 51537.00 I   .038004  .000116   .377845  .000126  I  .3637629  .0000139  1.0793 0.0063  I   -50.118     .791    -2.834     .298   .038060   .377680   .3636580   -49.500    -3.100  
+991226 51538.00 I   .039000  .000125   .377510  .000119  I  .3626369  .0000103  1.1755 0.0079  I   -49.742     .791    -2.876     .298   .039020   .377410   .3625410   -49.400    -2.900  
+991227 51539.00 I   .040049  .000117   .377548  .000129  I  .3614129  .0000075  1.2687 0.0068  I   -49.636     .791    -2.972     .298   .040050   .377580   .3613690   -49.400    -2.800  
+991228 51540.00 I   .041137  .000109   .377788  .000125  I  .3601152  .0000090  1.3147 0.0062  I   -49.841     .791    -2.907     .298   .041120   .377740   .3601150   -49.800    -2.700  
+991229 51541.00 I   .042052  .000088   .378106  .000111  I  .3588103  .0000099  1.2804 0.0067  I   -50.176     .791    -2.678     .298   .041930   .378160   .3588120   -50.100    -2.600  
+991230 51542.00 I   .042547  .000089   .378200  .000110  I  .3575773  .0000100  1.1776 0.0068  I   -50.392     .791    -2.493     .298   .042450   .378270   .3575540   -50.500    -2.500  
+991231 51543.00 I   .042890  .000090   .377991  .000108  I  .3564633  .0000093  1.0504 0.0070  I   -50.473     .791    -2.486     .298   .042860   .377980   .3564530   -50.800    -2.400  
+ 0 1 1 51544.00 I   .043215  .000092   .377697  .000099  I  .3554732  .0000099  0.9333 0.0076  I   -50.607     .791    -2.585     .298   .043190   .377700   .3554990   -50.900    -2.500  
+ 0 1 2 51545.00 I   .043455  .000058   .377468  .000073  I  .3545966  .0000119  0.8165 0.0074  I   -50.218     .740    -2.679     .340   .043480   .377510   .3546330   -50.800    -2.500  
+ 0 1 3 51546.00 I   .043512  .000069   .377238  .000077  I  .3538464  .0000109  0.6813 0.0083  I   -50.459     .740    -2.699     .340   .043590   .377270   .3538640   -50.600    -2.500  
+ 0 1 4 51547.00 I   .043363  .000071   .376945  .000089  I  .3532360  .0000115  0.5403 0.0107  I   -50.437     .740    -2.766     .340   .043410   .376940   .3532310   -50.300    -2.800  
+ 0 1 5 51548.00 I   .043134  .000080   .376623  .000088  I  .3527537  .0000184  0.4358 0.0106  I   -50.188     .740    -2.893     .340   .043160   .376600   .3527960   -49.900    -2.900  
+ 0 1 6 51549.00 I   .043149  .000087   .376297  .000093  I  .3523431  .0000177  0.3954 0.0127  I   -49.678     .740    -3.066     .340   .043140   .376270   .3524010   -49.400    -2.900  
+ 0 1 7 51550.00 I   .043422  .000076   .376104  .000091  I  .3519484  .0000176  0.3987 0.0121  I   -49.409     .740    -3.103     .340   .043440   .376070   .3519450   -49.000    -2.900  
+ 0 1 8 51551.00 I   .043659  .000106   .375969  .000093  I  .3515404  .0000164  0.4181 0.0125  I   -49.211     .740    -3.090     .340   .043730   .376020   .3515040   -48.500    -2.800  
+ 0 1 9 51552.00 I   .043675  .000124   .375686  .000099  I  .3510966  .0000177  0.4845 0.0103  I   -49.134     .740    -3.078     .340   .043690   .375760   .3510900   -48.400    -2.600  
+ 0 110 51553.00 I   .043604  .000128   .375254  .000094  I  .3505534  .0000125  0.6050 0.0098  I   -49.197     .740    -3.071     .340   .043590   .375250   .3505590   -48.300    -2.400  
+ 0 111 51554.00 I   .043745  .000128   .374881  .000096  I  .3498790  .0000082  0.7484 0.0073  I   -49.336     .740    -3.037     .340   .043740   .374760   .3498330   -48.600    -2.200  
+ 0 112 51555.00 I   .044251  .000132   .374731  .000092  I  .3490532  .0000074  0.9018 0.0057  I   -49.474     .740    -2.995     .340   .044220   .374640   .3489670   -48.900    -2.100  
+ 0 113 51556.00 I   .045178  .000133   .374726  .000097  I  .3480742  .0000078  1.0586 0.0052  I   -49.629     .142    -2.979     .112   .045170   .374690   .3479980   -49.400    -2.100  
+ 0 114 51557.00 I   .046378  .000128   .374757  .000097  I  .3469483  .0000073  1.1786 0.0069  I   -49.677     .142    -3.035     .112   .046490   .374730   .3469090   -49.900    -2.100  
+ 0 115 51558.00 I   .047518  .000120   .374783  .000091  I  .3457480  .0000113  1.2057 0.0077  I   -49.689     .740    -3.048     .340   .047640   .374810   .3457280   -50.400    -2.200  
+ 0 116 51559.00 I   .048487  .000104   .374789  .000081  I  .3445662  .0000136  1.1447 0.0091  I   -49.800     .740    -2.966     .340   .048510   .374820   .3445610   -50.700    -2.300  
+ 0 117 51560.00 I   .049484  .000107   .374848  .000094  I  .3434739  .0000143  1.0376 0.0102  I   -50.181     .427    -2.879     .247   .049450   .374840   .3435070   -50.900    -2.500  
+ 0 118 51561.00 I   .050671  .000095   .375099  .000098  I  .3424895  .0000152  0.9349 0.0111  I   -50.789     .427    -2.914     .247   .050690   .375130   .3425460   -50.800    -2.600  
+ 0 119 51562.00 I   .051944  .000097   .375468  .000094  I  .3415968  .0000169  0.8541 0.0109  I   -51.314     .427    -3.044     .247   .051980   .375540   .3416250   -50.500    -2.600  
+ 0 120 51563.00 I   .053115  .000095   .375682  .000096  I  .3407635  .0000157  0.8269 0.0103  I   -51.604     .220    -3.008     .340   .053160   .375720   .3407420   -50.200    -2.600  
+ 0 121 51564.00 I   .054190  .000089   .375869  .000089  I  .3399193  .0000118  0.8709 0.0106  I   -51.228     .220    -2.945     .340   .054210   .375830   .3398860   -49.700    -2.500  
+ 0 122 51565.00 I   .055094  .000090   .376229  .000090  I  .3390041  .0000143  0.9677 0.0097  I   -50.536     .220    -2.903     .340   .055110   .376210   .3389880   -49.300    -2.500  
+ 0 123 51566.00 I   .055780  .000082   .376695  .000064  I  .3379742  .0000155  1.0937 0.0100  I   -49.812     .740    -3.019     .340   .055820   .376690   .3379660   -49.100    -2.300  
+ 0 124 51567.00 I   .056228  .000090   .377100  .000063  I  .3368184  .0000141  1.2145 0.0106  I   -49.344     .740    -3.190     .340   .056210   .377100   .3368040   -49.200    -2.100  
+ 0 125 51568.00 I   .056440  .000089   .377321  .000064  I  .3355604  .0000145  1.2895 0.0105  I   -49.289     .740    -3.182     .340   .056420   .377350   .3355310   -49.500    -2.000  
+ 0 126 51569.00 I   .056569  .000089   .377302  .000061  I  .3342584  .0000155  1.3073 0.0110  I   -49.551     .740    -2.941     .340   .056570   .377290   .3342110   -49.800    -2.000  
+ 0 127 51570.00 I   .056930  .000091   .377024  .000065  I  .3329659  .0000166  1.2647 0.0109  I   -49.778     .740    -2.721     .340   .056980   .376990   .3329220   -50.400    -1.900  
+ 0 128 51571.00 I   .057279  .000089   .376691  .000067  I  .3317549  .0000153  1.1442 0.0114  I   -50.052     .740    -2.653     .340   .057300   .376720   .3317330   -50.800    -2.100  
+ 0 129 51572.00 I   .057260  .000083   .376406  .000067  I  .3306897  .0000155  0.9869 0.0123  I   -50.347     .740    -2.785     .340   .057180   .376380   .3306810   -51.100    -2.300  
+ 0 130 51573.00 I   .057053  .000088   .376159  .000060  I  .3297764  .0000193  0.8438 0.0097  I   -50.674     .740    -2.964     .340   .056980   .376130   .3297760   -51.200    -2.500  
+ 0 131 51574.00 I   .056920  .000110   .375899  .000086  I  .3289928  .0000117  0.7287 0.0110  I   -50.834     .740    -3.087     .147   .056930   .375950   .3290060   -51.000    -2.700  
+ 0 2 1 51575.00 I   .056955  .000111   .375515  .000086  I  .3283083  .0000105  0.6455 0.0073  I   -50.661     .740    -3.175     .147   .056890   .375520   .3283220   -50.700    -3.000  
+ 0 2 2 51576.00 I   .057214  .000109   .374985  .000084  I  .3276983  .0000086  0.5726 0.0069  I   -50.262     .740    -3.274     .147   .057200   .375010   .3276990   -50.300    -3.100  
+ 0 2 3 51577.00 I   .057620  .000109   .374341  .000083  I  .3271605  .0000091  0.5076 0.0062  I   -49.874     .740    -3.397     .166   .057660   .374400   .3271500   -49.800    -3.100  
+ 0 2 4 51578.00 I   .058222  .000106   .373714  .000086  I  .3266641  .0000088  0.4997 0.0066  I   -49.607     .740    -3.461     .166   .058190   .373750   .3266670   -49.400    -3.000  
+ 0 2 5 51579.00 I   .058993  .000109   .373135  .000091  I  .3261312  .0000095  0.5813 0.0076  I   -49.395     .740    -3.453     .166   .059040   .373130   .3261480   -49.000    -2.900  
+ 0 2 6 51580.00 I   .059938  .000098   .372624  .000092  I  .3254829  .0000123  0.7185 0.0070  I   -49.234     .740    -3.387     .340   .059970   .372620   .3254630   -48.600    -3.100  
+ 0 2 7 51581.00 I   .061017  .000103   .372235  .000095  I  .3246859  .0000104  0.8805 0.0080  I   -49.211     .170    -3.314     .340   .061040   .372220   .3245860   -48.400    -3.300  
+ 0 2 8 51582.00 I   .062195  .000108   .371971  .000091  I  .3237181  .0000101  1.0540 0.0082  I   -49.352     .170    -3.296     .340   .062240   .371940   .3236430   -48.300    -3.300  
+ 0 2 9 51583.00 I   .063502  .000107   .371823  .000091  I  .3225902  .0000128  1.1908 0.0085  I   -49.554     .170    -3.361     .340   .063470   .371980   .3225890   -48.700    -3.300  
+ 0 210 51584.00 I   .064771  .000109   .371580  .000086  I  .3213657  .0000136  1.2402 0.0092  I   -49.669     .140    -3.503     .340   .064720   .371710   .3213750   -49.200    -3.300  
+ 0 211 51585.00 I   .065761  .000109   .371153  .000089  I  .3201477  .0000132  1.1759 0.0087  I   -49.735     .140    -3.605     .340   .065790   .371160   .3201260   -49.800    -3.500  
+ 0 212 51586.00 I   .066202  .000092   .370649  .000093  I  .3190448  .0000108  1.0187 0.0094  I   -49.789     .140    -3.637     .340   .066240   .370670   .3190220   -50.400    -3.600  
+ 0 213 51587.00 I   .066157  .000113   .370171  .000074  I  .3181117  .0000133  0.8572 0.0077  I   -49.927     .740    -3.614     .340   .066190   .370140   .3181430   -50.800    -3.700  
+ 0 214 51588.00 I   .066000  .000151   .369722  .000093  I  .3173178  .0000109  0.7336 0.0080  I   -50.204     .131    -3.618     .340   .065970   .369710   .3173170   -51.000    -3.900  
+ 0 215 51589.00 I   .066136  .000148   .369254  .000097  I  .3166298  .0000090  0.6541 0.0065  I   -50.548     .131    -3.721     .340   .066020   .369250   .3166280   -50.800    -3.900  
+ 0 216 51590.00 I   .066699  .000155   .368822  .000099  I  .3159886  .0000069  0.6376 0.0066  I   -50.779     .131    -3.891     .340   .066650   .368810   .3159960   -50.600    -3.900  
+ 0 217 51591.00 I   .067329  .000159   .368509  .000103  I  .3153378  .0000097  0.6714 0.0059  I   -50.742     .131    -4.014     .340   .067380   .368490   .3153000   -50.200    -3.900  
+ 0 218 51592.00 I   .067939  .000142   .368369  .000104  I  .3146275  .0000096  0.7600 0.0072  I   -50.430     .131    -4.036     .340   .067960   .368340   .3145900   -49.700    -3.900  
+ 0 219 51593.00 I   .068516  .000127   .368291  .000092  I  .3137951  .0000107  0.9168 0.0102  I   -49.958     .131    -4.056     .340   .068520   .368310   .3138080   -49.400    -4.000  
+ 0 220 51594.00 I   .069027  .000069   .368146  .000076  I  .3127835  .0000179  1.1050 0.0101  I   -49.483     .740    -4.198     .340   .069000   .368190   .3128270   -49.100    -4.000  
+ 0 221 51595.00 I   .069214  .000071   .367844  .000076  I  .3116045  .0000172  1.2351 0.0124  I   -49.155     .184    -4.423     .340   .069170   .367900   .3116160   -49.000    -4.000  
+ 0 222 51596.00 I   .069035  .000071   .367356  .000078  I  .3103486  .0000173  1.2591 0.0121  I   -49.085     .184    -4.532     .340   .068980   .367350   .3103220   -49.100    -4.200  
+ 0 223 51597.00 I   .068730  .000069   .366746  .000074  I  .3091149  .0000169  1.1971 0.0119  I   -49.273     .184    -4.415     .340   .068720   .366770   .3091040   -49.300    -4.300  
+ 0 224 51598.00 I   .068361  .000058   .366024  .000067  I  .3079714  .0000164  1.0840 0.0117  I   -49.615     .184    -4.191     .340   .068400   .366050   .3079750   -49.600    -4.500  
+ 0 225 51599.00 I   .067890  .000060   .365197  .000066  I  .3069563  .0000163  0.9427 0.0125  I   -50.009     .184    -4.080     .340   .067930   .365220   .3069360   -49.900    -4.600  
+ 0 226 51600.00 I   .067390  .000070   .364288  .000067  I  .3060864  .0000188  0.8002 0.0125  I   -50.396     .184    -4.160     .340   .067440   .364350   .3060680   -50.100    -4.700  
+ 0 227 51601.00 I   .066951  .000060   .363382  .000069  I  .3053466  .0000190  0.6857 0.0119  I   -50.665     .740    -4.331     .340   .066970   .363430   .3053490   -50.200    -4.700  
+ 0 228 51602.00 I   .066617  .000067   .362566  .000102  I  .3047064  .0000147  0.5970 0.0113  I   -50.640     .740    -4.465     .340   .066620   .362640   .3046720   -50.100    -4.700  
+ 0 229 51603.00 I   .066422  .000081   .361905  .000110  I  .3041427  .0000124  0.5380 0.0096  I   -50.248     .740    -4.535     .340   .066450   .361910   .3041150   -49.800    -4.600  
+ 0 3 1 51604.00 I   .066401  .000092   .361388  .000115  I  .3036098  .0000123  0.5409 0.0111  I   -49.671     .740    -4.593     .340   .066400   .361470   .3036080   -49.500    -4.600  
+ 0 3 2 51605.00 I   .066648  .000097   .360890  .000117  I  .3030436  .0000184  0.5956 0.0099  I   -49.399     .167    -4.629     .340   .066580   .360960   .3030390   -49.200    -4.500  
+ 0 3 3 51606.00 I   .067130  .000097   .360477  .000115  I  .3024079  .0000156  0.6822 0.0118  I   -49.141     .167    -4.709     .340   .067140   .360330   .3024040   -48.900    -4.500  
+ 0 3 4 51607.00 I   .067620  .000095   .360236  .000123  I  .3016646  .0000149  0.8126 0.0122  I   -49.024     .167    -4.718     .340   .067760   .360170   .3016670   -48.700    -4.400  
+ 0 3 5 51608.00 I   .067948  .000130   .360099  .000108  I  .3007691  .0000187  0.9838 0.0105  I   -48.940     .740    -4.618     .340   .067950   .360180   .3007680   -48.600    -4.400  
+ 0 3 6 51609.00 I   .068216  .000141   .359961  .000113  I  .2996940  .0000148  1.1639 0.0120  I   -48.886     .399    -4.461     .192   .068160   .360020   .2996990   -48.700    -4.400  
+ 0 3 7 51610.00 I   .068525  .000136   .359801  .000111  I  .2984518  .0000149  1.3123 0.0080  I   -48.900     .399    -4.379     .192   .068600   .359770   .2984570   -48.900    -4.500  
+ 0 3 8 51611.00 I   .068828  .000132   .359586  .000115  I  .2970918  .0000061  1.3933 0.0088  I   -48.978     .399    -4.470     .192   .068820   .359720   .2970870   -49.200    -4.600  
+ 0 3 9 51612.00 I   .069387  .000128   .359217  .000117  I  .2956919  .0000095  1.3941 0.0062  I   -49.184     .311    -4.698     .189   .069280   .359300   .2956890   -49.500    -4.700  
+ 0 310 51613.00 I   .070402  .000135   .358866  .000109  I  .2943263  .0000107  1.3268 0.0056  I   -49.341     .311    -4.918     .189   .070270   .358810   .2943390   -49.700    -4.900  
+ 0 311 51614.00 I   .071773  .000106   .358686  .000135  I  .2930544  .0000061  1.2113 0.0064  I   -49.548     .311    -5.030     .189   .071690   .358680   .2930720   -49.900    -5.000  
+ 0 312 51615.00 I   .073083  .000099   .358599  .000130  I  .2919128  .0000070  1.0687 0.0049  I   -49.769     .740    -5.045     .340   .073060   .358650   .2919190   -49.900    -5.000  
+ 0 313 51616.00 I   .073990  .000101   .358364  .000130  I  .2909174  .0000076  0.9250 0.0052  I   -49.912     .250    -5.047     .139   .073940   .358480   .2909220   -49.800    -5.100  
+ 0 314 51617.00 I   .074480  .000102   .357854  .000132  I  .2900542  .0000077  0.8072 0.0051  I   -49.873     .250    -5.102     .139   .074370   .357960   .2900640   -49.500    -5.100  
+ 0 315 51618.00 I   .074671  .000109   .357111  .000133  I  .2892761  .0000067  0.7701 0.0052  I   -49.604     .250    -5.206     .139   .074620   .357200   .2892770   -49.200    -5.100  
+ 0 316 51619.00 I   .074758  .000099   .356241  .000136  I  .2884848  .0000071  0.8205 0.0048  I   -48.898     .740    -5.234     .340   .074740   .356290   .2884850   -48.800    -5.100  
+ 0 317 51620.00 I   .074596  .000088   .355401  .000127  I  .2876281  .0000068  0.8920 0.0074  I   -48.468     .740    -5.282     .340   .074570   .355470   .2876310   -48.400    -5.000  
+ 0 318 51621.00 I   .074245  .000098   .354616  .000106  I  .2867043  .0000130  0.9529 0.0072  I   -48.190     .740    -5.320     .340   .074260   .354760   .2867060   -48.100    -5.100  
+ 0 319 51622.00 I   .073913  .000081   .353859  .000087  I  .2857300  .0000126  0.9908 0.0087  I   -48.112     .740    -5.425     .340   .073980   .353950   .2857400   -47.900    -5.200  
+ 0 320 51623.00 I   .073747  .000083   .353172  .000077  I  .2847254  .0000117  1.0207 0.0087  I   -48.156     .178    -5.601     .340   .073730   .353110   .2847510   -47.800    -5.300  
+ 0 321 51624.00 I   .073826  .000089   .352606  .000074  I  .2836875  .0000120  1.0539 0.0084  I   -48.231     .178    -5.732     .340   .073800   .352620   .2837170   -47.900    -5.500  
+ 0 322 51625.00 I   .073986  .000082   .352100  .000070  I  .2826302  .0000121  1.0495 0.0099  I   -48.329     .178    -5.708     .340   .074010   .352130   .2826370   -48.000    -5.600  
+ 0 323 51626.00 I   .073990  .000085   .351575  .000076  I  .2816146  .0000158  0.9669 0.0098  I   -48.514     .166    -5.621     .340   .073980   .351510   .2815880   -48.100    -5.900  
+ 0 324 51627.00 I   .073949  .000092   .351028  .000071  I  .2807146  .0000154  0.8296 0.0116  I   -48.847     .166    -5.510     .340   .073900   .351030   .2807060   -48.400    -6.000  
+ 0 325 51628.00 I   .073762  .000089   .350394  .000081  I  .2799580  .0000169  0.6845 0.0140  I   -49.222     .166    -5.532     .340   .073770   .350450   .2799650   -48.500    -6.000  
+ 0 326 51629.00 I   .073420  .000085   .349596  .000075  I  .2793488  .0000234  0.5296 0.0131  I   -49.440     .740    -5.651     .340   .073380   .349600   .2793210   -48.600    -6.100  
+ 0 327 51630.00 I   .073080  .000079   .348740  .000068  I  .2788852  .0000201  0.4153 0.0155  I   -49.344     .740    -5.769     .340   .073100   .348650   .2789080   -48.500    -6.000  
+ 0 328 51631.00 I   .072772  .000078   .347935  .000072  I  .2784878  .0000204  0.3922 0.0125  I   -48.936     .740    -5.841     .340   .072860   .347950   .2785310   -48.500    -5.900  
+ 0 329 51632.00 I   .072757  .000081   .347135  .000068  I  .2780890  .0000149  0.4043 0.0125  I   -48.369     .740    -5.887     .340   .072710   .347190   .2780890   -48.300    -5.800  
+ 0 330 51633.00 I   .073380  .000091   .346415  .000064  I  .2776678  .0000145  0.4504 0.0086  I   -47.929     .740    -5.952     .104   .073380   .346410   .2776610   -47.900    -5.600  
+ 0 331 51634.00 I   .074374  .000102   .345977  .000056  I  .2771617  .0000086  0.5760 0.0087  I   -47.625     .740    -5.998     .104   .074460   .346060   .2771740   -47.600    -5.500  
+ 0 4 1 51635.00 I   .075198  .000105   .345904  .000046  I  .2764928  .0000096  0.7705 0.0078  I   -47.582     .740    -6.012     .104   .075220   .345980   .2765170   -47.200    -5.400  
+ 0 4 2 51636.00 I   .075808  .000117   .346131  .000055  I  .2756134  .0000130  0.9868 0.0074  I   -47.702     .740    -5.949     .340   .075680   .346120   .2756560   -47.000    -5.300  
+ 0 4 3 51637.00 I   .076481  .000128   .346510  .000060  I  .2745277  .0000113  1.1777 0.0088  I   -47.809     .351    -5.803     .340   .076340   .346510   .2745730   -46.900    -5.400  
+ 0 4 4 51638.00 I   .076985  .000129   .346828  .000063  I  .2732774  .0000119  1.3104 0.0080  I   -47.813     .351    -5.668     .340   .077030   .346880   .2732930   -47.000    -5.500  
+ 0 4 5 51639.00 I   .077059  .000113   .346914  .000075  I  .2719400  .0000112  1.3436 0.0082  I   -47.797     .351    -5.690     .340   .077060   .346950   .2719320   -47.200    -5.600  
+ 0 4 6 51640.00 I   .077093  .000094   .346707  .000077  I  .2706251  .0000113  1.2720 0.0077  I   -47.915     .351    -5.922     .340   .077060   .346750   .2706330   -47.500    -5.800  
+ 0 4 7 51641.00 I   .077296  .000096   .346262  .000083  I  .2694147  .0000105  1.1443 0.0077  I   -48.219     .352    -6.267     .340   .077310   .346310   .2694350   -47.800    -6.000  
+ 0 4 8 51642.00 I   .077573  .000097   .345685  .000098  I  .2683416  .0000104  1.0013 0.0077  I   -48.592     .352    -6.499     .340   .077600   .345730   .2683450   -48.100    -6.200  
+ 0 4 9 51643.00 I   .077806  .000093   .345015  .000092  I  .2674068  .0000113  0.8740 0.0065  I   -48.875     .740    -6.543     .340   .077800   .345120   .2674040   -48.200    -6.300  
+ 0 410 51644.00 I   .078238  .000094   .344262  .000097  I  .2665760  .0000078  0.7993 0.0069  I   -48.961     .392    -6.454     .340   .078180   .344290   .2665780   -48.200    -6.300  
+ 0 411 51645.00 I   .079142  .000110   .343638  .000098  I  .2657834  .0000078  0.7990 0.0056  I   -48.819     .392    -6.348     .340   .079090   .343600   .2657810   -48.100    -6.400  
+ 0 412 51646.00 I   .080330  .000125   .343365  .000091  I  .2649542  .0000080  0.8700 0.0061  I   -48.458     .392    -6.306     .340   .080370   .343360   .2649460   -47.900    -6.400  
+ 0 413 51647.00 I   .081333  .000126   .343380  .000089  I  .2640252  .0000093  0.9957 0.0061  I   -48.173     .625    -6.329     .340   .081460   .343390   .2640320   -47.600    -6.300  
+ 0 414 51648.00 I   .081906  .000121   .343576  .000084  I  .2629513  .0000091  1.1558 0.0065  I   -47.670     .625    -6.383     .340   .081990   .343570   .2629550   -47.400    -6.200  
+ 0 415 51649.00 I   .082086  .000111   .343849  .000077  I  .2617145  .0000092  1.3133 0.0074  I   -47.392     .625    -6.431     .340   .082090   .343870   .2617140   -47.400    -6.100  
+ 0 416 51650.00 I   .082136  .000096   .344069  .000100  I  .2603384  .0000117  1.4297 0.0071  I   -47.442     .740    -6.469     .340   .082110   .344100   .2603470   -47.500    -6.100  
+ 0 417 51651.00 I   .082226  .000127   .344150  .000109  I  .2588795  .0000109  1.4728 0.0085  I   -47.718     .379    -6.494     .340   .082280   .344150   .2588640   -47.600    -6.100  
+ 0 418 51652.00 I   .082276  .000131   .344044  .000108  I  .2574198  .0000122  1.4348 0.0083  I   -47.987     .379    -6.477     .340   .082430   .344110   .2574370   -48.000    -6.100  
+ 0 419 51653.00 I   .082219  .000131   .343715  .000108  I  .2560309  .0000124  1.3337 0.0087  I   -48.118     .379    -6.400     .340   .082280   .343740   .2560440   -48.300    -6.200  
+ 0 420 51654.00 I   .082294  .000139   .343161  .000107  I  .2547592  .0000124  1.2120 0.0087  I   -48.421     .149    -6.275     .340   .082350   .343120   .2547520   -48.600    -6.400  
+ 0 421 51655.00 I   .082424  .000141   .342461  .000101  I  .2536047  .0000123  1.0968 0.0086  I   -48.584     .149    -6.241     .340   .082580   .342510   .2536740   -48.800    -6.600  
+ 0 422 51656.00 I   .082541  .000134   .341696  .000093  I  .2525701  .0000118  0.9681 0.0097  I   -48.813     .149    -6.308     .340   .082560   .341730   .2526650   -48.800    -6.700  
+ 0 423 51657.00 I   .082838  .000127   .340923  .000060  I  .2516714  .0000149  0.8306 0.0072  I   -48.944     .740    -6.435     .340   .082870   .340860   .2517210   -48.800    -6.900  
+ 0 424 51658.00 I   .083396  .000099   .340229  .000058  I  .2509021  .0000083  0.7134 0.0093  I   -48.882     .179    -6.565     .111   .083440   .340130   .2509180   -48.500    -6.900  
+ 0 425 51659.00 I   .084129  .000080   .339694  .000057  I  .2502312  .0000111  0.6365 0.0073  I   -48.658     .179    -6.675     .111   .084160   .339640   .2502580   -48.200    -6.900  
+ 0 426 51660.00 I   .084942  .000061   .339305  .000058  I  .2496080  .0000119  0.6229 0.0090  I   -48.308     .179    -6.752     .111   .084990   .339270   .2496080   -47.900    -6.700  
+ 0 427 51661.00 I   .085776  .000055   .338979  .000069  I  .2489548  .0000142  0.7012 0.0093  I   -47.776     .109    -6.773     .118   .085840   .338870   .2489720   -47.600    -6.400  
+ 0 428 51662.00 I   .086596  .000053   .338677  .000074  I  .2481768  .0000144  0.8660 0.0100  I   -47.357     .109    -6.727     .118   .086640   .338570   .2481970   -47.400    -6.200  
+ 0 429 51663.00 I   .087438  .000097   .338335  .000089  I  .2472104  .0000142  1.0679 0.0124  I   -47.247     .109    -6.683     .118   .087450   .338270   .2471880   -47.300    -6.100  
+ 0 430 51664.00 I   .088310  .000091   .337912  .000088  I  .2460469  .0000202  1.2521 0.0103  I   -47.527     .740    -6.672     .340   .088320   .337850   .2460670   -47.200    -5.900  
+ 0 5 1 51665.00 I   .089074  .000090   .337501  .000097  I  .2447165  .0000148  1.4056 0.0133  I   -47.919     .740    -6.638     .186   .089060   .337400   .2447320   -47.300    -5.900  
+ 0 5 2 51666.00 I   .089646  .000093   .337119  .000103  I  .2432550  .0000172  1.5014 0.0105  I   -48.105     .740    -6.532     .186   .089650   .337110   .2432530   -47.500    -5.900  
+ 0 5 3 51667.00 I   .089943  .000096   .336653  .000107  I  .2417404  .0000149  1.5171 0.0112  I   -48.118     .740    -6.439     .186   .089980   .336700   .2417460   -47.800    -6.200  
+ 0 5 4 51668.00 I   .089876  .000100   .335967  .000104  I  .2402498  .0000143  1.4458 0.0101  I   -48.260     .740    -6.541     .206   .089850   .336090   .2402460   -48.100    -6.300  
+ 0 5 5 51669.00 I   .089512  .000061   .335028  .000093  I  .2388797  .0000137  1.2819 0.0097  I   -48.636     .740    -6.820     .206   .089490   .334990   .2388380   -48.500    -6.500  
+ 0 5 6 51670.00 I   .089040  .000060   .333967  .000084  I  .2376950  .0000131  1.0912 0.0105  I   -49.026     .740    -7.107     .206   .089050   .333810   .2376060   -48.600    -6.800  
+ 0 5 7 51671.00 I   .088496  .000057   .332907  .000085  I  .2366841  .0000159  0.9403 0.0087  I   -49.157     .740    -7.191     .340   .088530   .332910   .2365990   -48.500    -6.900  
+ 0 5 8 51672.00 I   .087926  .000071   .331857  .000107  I  .2357910  .0000115  0.8598 0.0098  I   -49.011     .740    -7.051     .109   .087960   .331860   .2357550   -48.600    -7.000  
+ 0 5 9 51673.00 I   .087469  .000061   .330886  .000093  I  .2349382  .0000113  0.8583 0.0082  I   -48.770     .740    -6.842     .109   .087530   .330830   .2349480   -48.500    -6.900  
+ 0 510 51674.00 I   .087221  .000051   .330148  .000083  I  .2340443  .0000118  0.9472 0.0091  I   -48.563     .740    -6.721     .109   .087260   .330140   .2340480   -48.400    -6.800  
+ 0 511 51675.00 I   .087388  .000050   .329677  .000082  I  .2330322  .0000143  1.0710 0.0093  I   -48.366     .740    -6.722     .109   .087380   .329760   .2330110   -48.400    -6.700  
+ 0 512 51676.00 I   .088025  .000069   .329575  .000088  I  .2319108  .0000144  1.1694 0.0121  I   -48.124     .740    -6.789     .109   .088070   .329580   .2318930   -48.400    -6.400  
+ 0 513 51677.00 I   .088812  .000067   .329617  .000091  I  .2307012  .0000196  1.2444 0.0157  I   -47.896     .740    -6.855     .109   .088870   .329580   .2307180   -48.500    -6.300  
+ 0 514 51678.00 I   .089475  .000070   .329668  .000078  I  .2294361  .0000278  1.2772 0.0170  I   -47.849     .740    -6.865     .340   .089470   .329690   .2294520   -48.600    -6.200  
+ 0 515 51679.00 I   .090028  .000086   .329588  .000044  I  .2281687  .0000278  1.2444 0.0200  I   -48.073     .623    -6.784     .182   .090050   .329610   .2281330   -48.800    -6.100  
+ 0 516 51680.00 I   .090488  .000085   .329187  .000044  I  .2269698  .0000288  1.1440 0.0194  I   -48.453     .623    -6.617     .182   .090540   .329170   .2269170   -49.000    -6.200  
+ 0 517 51681.00 I   .090846  .000086   .328477  .000042  I  .2258826  .0000272  1.0377 0.0195  I   -48.775     .623    -6.439     .182   .090870   .328450   .2258710   -49.200    -6.300  
+ 0 518 51682.00 I   .091393  .000068   .327755  .000039  I  .2248928  .0000262  0.9362 0.0159  I   -49.026     .535    -6.400     .146   .091390   .327710   .2248910   -49.300    -6.600  
+ 0 519 51683.00 I   .092217  .000068   .327154  .000038  I  .2240194  .0000163  0.8072 0.0136  I   -49.101     .535    -6.484     .146   .092280   .327100   .2239890   -49.400    -6.800  
+ 0 520 51684.00 I   .093187  .000087   .326636  .000045  I  .2232798  .0000074  0.6739 0.0086  I   -49.147     .535    -6.658     .146   .093220   .326590   .2232440   -49.300    -7.000  
+ 0 521 51685.00 I   .093994  .000065   .326187  .000045  I  .2226631  .0000056  0.5661 0.0046  I   -49.147     .740    -6.808     .340   .094040   .326130   .2226540   -49.000    -7.100  
+ 0 522 51686.00 I   .094457  .000067   .325675  .000053  I  .2221314  .0000056  0.5070 0.0044  I   -49.124     .184    -6.895     .340   .094520   .325650   .2221350   -48.800    -7.200  
+ 0 523 51687.00 I   .094541  .000067   .324805  .000055  I  .2216301  .0000069  0.5048 0.0046  I   -49.145     .184    -6.969     .340   .094640   .324730   .2216290   -48.400    -7.200  
+ 0 524 51688.00 I   .094765  .000064   .323507  .000053  I  .2211125  .0000074  0.5306 0.0052  I   -49.144     .184    -7.041     .340   .094850   .323410   .2210940   -48.000    -7.100  
+ 0 525 51689.00 I   .095304  .000062   .322391  .000053  I  .2205648  .0000077  0.5689 0.0053  I   -48.814     .740    -6.995     .340   .095340   .322360   .2205220   -47.800    -6.800  
+ 0 526 51690.00 I   .096112  .000055   .321571  .000055  I  .2199668  .0000076  0.6310 0.0074  I   -48.451     .740    -6.855     .340   .096140   .321540   .2199430   -47.800    -6.600  
+ 0 527 51691.00 I   .097312  .000036   .320835  .000054  I  .2192941  .0000127  0.7193 0.0109  I   -48.306     .740    -6.697     .340   .097340   .320780   .2193000   -47.900    -6.500  
+ 0 528 51692.00 I   .098918  .000035   .320093  .000035  I  .2185232  .0000205  0.8225 0.0108  I   -48.673     .740    -6.666     .340   .098910   .320120   .2185070   -48.200    -6.400  
+ 0 529 51693.00 I   .100678  .000044   .319359  .000037  I  .2176552  .0000174  0.9072 0.0135  I   -49.336     .542    -6.731     .142   .100690   .319400   .2176300   -48.500    -6.300  
+ 0 530 51694.00 I   .102331  .000055   .318691  .000051  I  .2167245  .0000175  0.9446 0.0127  I   -49.820     .542    -6.713     .142   .102300   .318690   .2167470   -48.900    -6.400  
+ 0 531 51695.00 I   .103800  .000060   .318055  .000053  I  .2157888  .0000185  0.9134 0.0126  I   -50.005     .542    -6.561     .142   .103790   .318060   .2157980   -49.200    -6.600  
+ 0 6 1 51696.00 I   .105087  .000063   .317341  .000055  I  .2149209  .0000180  0.8126 0.0134  I   -49.884     .207    -6.457     .140   .105050   .317360   .2149210   -49.600    -6.700  
+ 0 6 2 51697.00 I   .106400  .000062   .316492  .000053  I  .2141761  .0000193  0.6743 0.0115  I   -50.305     .207    -6.564     .140   .106310   .316510   .2141970   -49.700    -6.800  
+ 0 6 3 51698.00 I   .107684  .000054   .315507  .000055  I  .2135716  .0000142  0.5381 0.0119  I   -50.689     .207    -6.793     .140   .107760   .315500   .2135470   -49.800    -6.800  
+ 0 6 4 51699.00 I   .108770  .000048   .314486  .000074  I  .2130846  .0000139  0.4479 0.0087  I   -50.700     .740    -6.902     .340   .108820   .314500   .2130840   -49.700    -6.800  
+ 0 6 5 51700.00 I   .109818  .000055   .313510  .000073  I  .2126473  .0000101  0.4432 0.0083  I   -50.344     .740    -6.805     .143   .109820   .313540   .2126560   -49.600    -6.800  
+ 0 6 6 51701.00 I   .110928  .000054   .312639  .000077  I  .2121691  .0000092  0.5257 0.0080  I   -49.961     .740    -6.645     .143   .110970   .312620   .2121930   -49.600    -6.600  
+ 0 6 7 51702.00 I   .111937  .000063   .311860  .000087  I  .2115752  .0000123  0.6704 0.0080  I   -49.858     .740    -6.578     .143   .111870   .311870   .2115840   -49.600    -6.400  
+ 0 6 8 51703.00 I   .112461  .000059   .311070  .000088  I  .2108262  .0000131  0.8215 0.0091  I   -50.050     .740    -6.599     .143   .112450   .311120   .2108200   -49.800    -6.300  
+ 0 6 9 51704.00 I   .112535  .000063   .310143  .000085  I  .2099522  .0000134  0.9125 0.0092  I   -50.304     .740    -6.626     .143   .112510   .310180   .2099400   -49.900    -6.200  
+ 0 610 51705.00 I   .112490  .000070   .308914  .000079  I  .2090299  .0000128  0.9172 0.0121  I   -50.397     .740    -6.629     .143   .112470   .308970   .2090050   -50.200    -6.000  
+ 0 611 51706.00 I   .112729  .000070   .307475  .000066  I  .2081422  .0000202  0.8485 0.0125  I   -50.353     .740    -6.624     .340   .112680   .307450   .2081520   -50.600    -6.000  
+ 0 612 51707.00 I   .113194  .000112   .306099  .000065  I  .2073506  .0000214  0.7266 0.0151  I   -50.414     .413    -6.581     .114   .113130   .306060   .2073440   -50.900    -6.100  
+ 0 613 51708.00 I   .113500  .000106   .304864  .000059  I  .2067048  .0000225  0.5574 0.0192  I   -50.757     .413    -6.452     .114   .113470   .304900   .2067100   -51.300    -6.200  
+ 0 614 51709.00 I   .113577  .000106   .303639  .000060  I  .2062475  .0000320  0.3531 0.0203  I   -51.267     .413    -6.293     .114   .113620   .303680   .2062480   -51.600    -6.300  
+ 0 615 51710.00 I   .113645  .000101   .302472  .000061  I  .2060009  .0000339  0.1417 0.0243  I   -51.963     .740    -6.236     .125   .113600   .302480   .2059850   -51.800    -6.500  
+ 0 616 51711.00 I   .113161  .000093   .301332  .000067  I  .2059520  .0000367 -0.0336 0.0233  I   -52.091     .740    -6.379     .125   .113100   .301300   .2059900   -51.900    -6.700  
+ 0 617 51712.00 I   .112189  .000089   .300267  .000086  I  .2060449  .0000319 -0.1394 0.0229  I   -52.031     .740    -6.599     .125   .112160   .300250   .2060860   -51.900    -6.700  
+ 0 618 51713.00 I   .110999  .000056   .299135  .000090  I  .2062115  .0000274 -0.1873 0.0196  I   -51.918     .740    -6.712     .340   .111010   .299210   .2061740   -52.000    -6.800  
+ 0 619 51714.00 I   .109831  .000049   .297643  .000093  I  .2064062  .0000227 -0.1952 0.0176  I   -51.892     .740    -6.675     .212   .109870   .297710   .2063480   -51.900    -6.700  
+ 0 620 51715.00 I   .108880  .000040   .295971  .000092  I  .2065859  .0000221 -0.1552 0.0145  I   -52.050     .740    -6.612     .212   .108870   .296020   .2065770   -52.000    -6.600  
+ 0 621 51716.00 I   .108124  .000037   .294316  .000092  I  .2066983  .0000182 -0.0604 0.0141  I   -52.318     .740    -6.615     .212   .108140   .294340   .2067080   -52.100    -6.400  
+ 0 622 51717.00 I   .107741  .000036   .292556  .000087  I  .2067001  .0000176  0.0543 0.0115  I   -52.368     .740    -6.578     .180   .107770   .292570   .2066590   -52.300    -6.200  
+ 0 623 51718.00 I   .107635  .000032   .290771  .000074  I  .2065948  .0000142  0.1537 0.0117  I   -52.267     .740    -6.453     .180   .107700   .290810   .2065550   -52.600    -6.000  
+ 0 624 51719.00 I   .107822  .000023   .289158  .000053  I  .2063949  .0000153  0.2466 0.0131  I   -52.198     .740    -6.262     .180   .107890   .289170   .2064170   -52.900    -5.900  
+ 0 625 51720.00 I   .108185  .000024   .287884  .000045  I  .2061000  .0000220  0.3445 0.0102  I   -52.525     .740    -6.186     .340   .108190   .287890   .2061060   -53.300    -5.800  
+ 0 626 51721.00 I   .108554  .000038   .286664  .000076  I  .2057138  .0000135  0.4187 0.0130  I   -53.213     .114    -6.273     .152   .108550   .286670   .2056990   -53.600    -5.800  
+ 0 627 51722.00 I   .108995  .000037   .285324  .000078  I  .2052783  .0000137  0.4457 0.0103  I   -53.860     .114    -6.351     .152   .108990   .285330   .2053220   -53.900    -5.900  
+ 0 628 51723.00 I   .109531  .000041   .283989  .000077  I  .2048415  .0000156  0.4155 0.0103  I   -54.227     .114    -6.282     .152   .109520   .283980   .2048650   -54.000    -6.000  
+ 0 629 51724.00 I   .110044  .000040   .282821  .000076  I  .2044716  .0000155  0.3125 0.0111  I   -54.412     .740    -6.220     .207   .110020   .282840   .2044680   -54.000    -6.200  
+ 0 630 51725.00 I   .110221  .000041   .281535  .000076  I  .2042304  .0000157  0.1678 0.0102  I   -54.720     .740    -6.243     .207   .110210   .281560   .2042410   -54.000    -6.400  
+ 0 7 1 51726.00 I   .110169  .000046   .280039  .000081  I  .2041293  .0000133  0.0432 0.0142  I   -54.966     .740    -6.397     .207   .110140   .280000   .2040530   -53.800    -6.500  
+ 0 7 2 51727.00 I   .109967  .000048   .278617  .000054  I  .2041166  .0000236  0.0009 0.0139  I   -54.896     .740    -6.493     .340   .109940   .278620   .2039720   -53.600    -6.600  
+ 0 7 3 51728.00 I   .109546  .000047   .277387  .000044  I  .2040917  .0000244  0.0662 0.0142  I   -54.496     .740    -6.450     .340   .109520   .277410   .2039550   -53.700    -6.700  
+ 0 7 4 51729.00 I   .108963  .000068   .276322  .000064  I  .2039568  .0000157  0.2139 0.0143  I   -54.053     .740    -6.399     .340   .108970   .276340   .2038820   -53.700    -6.700  
+ 0 7 5 51730.00 I   .108195  .000068   .275448  .000064  I  .2036533  .0000151  0.3933 0.0111  I   -53.906     .740    -6.453     .340   .108210   .275460   .2036680   -53.800    -6.600  
+ 0 7 6 51731.00 I   .107386  .000068   .274682  .000062  I  .2031755  .0000157  0.5566 0.0109  I   -54.247     .740    -6.583     .340   .107390   .274680   .2031930   -54.200    -6.500  
+ 0 7 7 51732.00 I   .107012  .000068   .273910  .000062  I  .2025619  .0000157  0.6544 0.0111  I   -54.786     .740    -6.527     .340   .106990   .273890   .2025540   -54.500    -6.400  
+ 0 7 8 51733.00 I   .106830  .000058   .273235  .000070  I  .2018964  .0000156  0.6630 0.0094  I   -55.211     .740    -6.382     .340   .106810   .273230   .2018930   -55.000    -6.400  
+ 0 7 9 51734.00 I   .106345  .000056   .272676  .000075  I  .2012574  .0000105  0.6070 0.0090  I   -55.289     .740    -6.317     .340   .106320   .272700   .2012680   -55.300    -6.300  
+ 0 710 51735.00 I   .105472  .000041   .272081  .000062  I  .2006965  .0000088  0.5085 0.0068  I   -55.187     .740    -6.389     .340   .105450   .272070   .2007080   -55.600    -6.300  
+ 0 711 51736.00 I   .104471  .000049   .271366  .000070  I  .2002445  .0000087  0.3976 0.0068  I   -55.276     .740    -6.480     .340   .104450   .271300   .2002440   -55.700    -6.400  
+ 0 712 51737.00 I   .103658  .000051   .270383  .000072  I  .1999051  .0000103  0.2753 0.0069  I   -55.675     .740    -6.494     .340   .103620   .270380   .1999000   -55.700    -6.500  
+ 0 713 51738.00 I   .102881  .000054   .269207  .000075  I  .1996952  .0000106  0.1490 0.0075  I   -56.100     .740    -6.514     .340   .102910   .269240   .1996870   -55.700    -6.600  
+ 0 714 51739.00 I   .102127  .000065   .268078  .000082  I  .1996037  .0000108  0.0330 0.0081  I   -56.296     .740    -6.606     .340   .102150   .268100   .1996080   -55.500    -6.700  
+ 0 715 51740.00 I   .101213  .000073   .266972  .000078  I  .1996296  .0000123 -0.0841 0.0086  I   -56.234     .740    -6.749     .340   .101200   .267020   .1996010   -55.400    -6.700  
+ 0 716 51741.00 I   .100163  .000071   .265843  .000081  I  .1997601  .0000133 -0.1659 0.0088  I   -56.104     .740    -6.790     .340   .100110   .265850   .1997040   -55.300    -6.800  
+ 0 717 51742.00 I   .099235  .000060   .264837  .000089  I  .1999437  .0000126 -0.1947 0.0088  I   -56.067     .257    -6.666     .340   .099230   .264830   .1999110   -55.500    -6.700  
+ 0 718 51743.00 I   .098285  .000059   .263948  .000091  I  .2001382  .0000114 -0.1896 0.0079  I   -56.188     .257    -6.490     .340   .098270   .263900   .2001430   -55.700    -6.500  
+ 0 719 51744.00 I   .097161  .000061   .262947  .000094  I  .2003128  .0000096 -0.1541 0.0073  I   -56.443     .257    -6.405     .340   .097120   .262910   .2003170   -56.000    -6.400  
+ 0 720 51745.00 I   .096019  .000039   .261634  .000077  I  .2004413  .0000091 -0.1032 0.0066  I   -56.616     .168    -6.395     .340   .096020   .261600   .2004180   -56.500    -6.300  
+ 0 721 51746.00 I   .094818  .000032   .260257  .000076  I  .2005212  .0000091 -0.0584 0.0074  I   -56.737     .168    -6.364     .340   .094860   .260160   .2005040   -56.900    -6.100  
+ 0 722 51747.00 I   .093439  .000036   .259074  .000087  I  .2005555  .0000116 -0.0057 0.0091  I   -56.768     .168    -6.262     .340   .093450   .259050   .2005770   -57.500    -6.000  
+ 0 723 51748.00 I   .092112  .000070   .258017  .000080  I  .2005297  .0000157  0.0558 0.0078  I   -56.942     .740    -6.187     .340   .092080   .258090   .2005480   -57.900    -6.000  
+ 0 724 51749.00 I   .091249  .000083   .256975  .000078  I  .2004521  .0000105  0.0926 0.0100  I   -57.381     .192    -6.224     .340   .091250   .257010   .2004300   -58.200    -6.000  
+ 0 725 51750.00 I   .090774  .000082   .256140  .000077  I  .2003567  .0000124  0.0929 0.0081  I   -57.939     .192    -6.319     .340   .090800   .256130   .2003190   -58.500    -6.100  
+ 0 726 51751.00 I   .090467  .000078   .255547  .000079  I  .2002801  .0000124  0.0519 0.0087  I   -58.399     .192    -6.373     .340   .090420   .255640   .2002770   -58.500    -6.300  
+ 0 727 51752.00 I   .090291  .000079   .255049  .000082  I  .2002659  .0000123 -0.0281 0.0078  I   -58.696     .192    -6.403     .340   .090210   .255130   .2002820   -58.500    -6.500  
+ 0 728 51753.00 I   .089877  .000082   .254516  .000073  I  .2003391  .0000096 -0.1165 0.0073  I   -58.859     .192    -6.486     .340   .089820   .254560   .2003350   -58.200    -6.600  
+ 0 729 51754.00 I   .089117  .000059   .253907  .000077  I  .2004866  .0000080 -0.1679 0.0076  I   -58.870     .192    -6.593     .340   .089090   .253970   .2004870   -58.100    -6.700  
+ 0 730 51755.00 I   .088353  .000032   .253164  .000072  I  .2006483  .0000119 -0.1395 0.0064  I   -58.697     .740    -6.594     .340   .088320   .253210   .2006530   -57.800    -6.700  
+ 0 731 51756.00 I   .087624  .000072   .252369  .000069  I  .2007368  .0000100 -0.0249 0.0075  I   -58.397     .194    -6.476     .340   .087600   .252400   .2007420   -57.700    -6.800  
+ 0 8 1 51757.00 I   .086922  .000075   .251692  .000063  I  .2006819  .0000091  0.1382 0.0068  I   -58.112     .194    -6.405     .340   .086920   .251760   .2006950   -57.800    -6.800  
+ 0 8 2 51758.00 I   .086416  .000080   .251127  .000061  I  .2004629  .0000093  0.2938 0.0066  I   -58.002     .194    -6.492     .340   .086350   .251190   .2004710   -58.000    -6.600  
+ 0 8 3 51759.00 I   .085879  .000081   .250675  .000062  I  .2001140  .0000095  0.3904 0.0071  I   -58.228     .161    -6.610     .340   .085880   .250750   .2000900   -58.300    -6.400  
+ 0 8 4 51760.00 I   .085277  .000084   .250228  .000029  I  .1997081  .0000107  0.4090 0.0070  I   -58.724     .161    -6.528     .340   .085310   .250310   .1997160   -58.600    -6.300  
+ 0 8 5 51761.00 I   .084583  .000083   .249655  .000030  I  .1993192  .0000103  0.3579 0.0079  I   -59.261     .161    -6.281     .340   .084600   .249680   .1993260   -59.000    -6.200  
+ 0 8 6 51762.00 I   .083909  .000039   .249042  .000030  I  .1990109  .0000116  0.2512 0.0070  I   -59.498     .740    -6.134     .340   .083890   .249060   .1990050   -59.400    -6.200  
+ 0 8 7 51763.00 I   .083208  .000040   .248525  .000053  I  .1988276  .0000094  0.1123 0.0073  I   -59.391     .245    -6.259     .340   .083200   .248580   .1988220   -59.600    -6.200  
+ 0 8 8 51764.00 I   .082305  .000039   .248115  .000054  I  .1987890  .0000089 -0.0348 0.0064  I   -59.255     .245    -6.536     .340   .082270   .248180   .1987940   -59.600    -6.400  
+ 0 8 9 51765.00 I   .081267  .000037   .247773  .000056  I  .1988874  .0000086 -0.1527 0.0062  I   -59.347     .245    -6.728     .340   .081170   .247790   .1988930   -59.500    -6.600  
+ 0 810 51766.00 I   .079976  .000035   .247487  .000060  I  .1990782  .0000086 -0.2222 0.0059  I   -59.413     .420    -6.725     .340   .079980   .247550   .1990860   -59.300    -6.800  
+ 0 811 51767.00 I   .078346  .000038   .247089  .000058  I  .1993185  .0000081 -0.2518 0.0056  I   -59.538     .420    -6.702     .340   .078360   .247210   .1993320   -59.000    -6.900  
+ 0 812 51768.00 I   .076607  .000037   .246398  .000061  I  .1995682  .0000072 -0.2405 0.0073  I   -59.497     .420    -6.712     .340   .076600   .246450   .1995820   -58.600    -7.000  
+ 0 813 51769.00 I   .075050  .000033   .245638  .000053  I  .1997864  .0000122 -0.1898 0.0074  I   -59.430     .740    -6.715     .340   .075080   .245660   .1997900   -58.400    -6.900  
+ 0 814 51770.00 I   .073685  .000070   .245040  .000049  I  .1999357  .0000130 -0.1026 0.0095  I   -59.411     .835    -6.628     .340   .073680   .245120   .1999360   -58.200    -6.800  
+ 0 815 51771.00 I   .072650  .000075   .244535  .000046  I  .1999812  .0000145  0.0159 0.0090  I   -59.410     .835    -6.458     .340   .072610   .244590   .1999960   -58.200    -6.600  
+ 0 816 51772.00 I   .071939  .000079   .244191  .000043  I  .1998923  .0000124  0.1694 0.0095  I   -59.437     .835    -6.297     .340   .071990   .244180   .1999100   -58.400    -6.400  
+ 0 817 51773.00 I   .071315  .000076   .244107  .000044  I  .1996358  .0000123  0.3429 0.0090  I   -59.385     .669    -6.235     .340   .071320   .244120   .1996310   -58.700    -6.100  
+ 0 818 51774.00 I   .070374  .000074   .244145  .000044  I  .1992137  .0000131  0.4948 0.0095  I   -59.542     .669    -6.225     .340   .070350   .244190   .1992030   -59.200    -6.000  
+ 0 819 51775.00 I   .069083  .000076   .244139  .000033  I  .1986598  .0000144  0.6058 0.0076  I   -59.648     .669    -6.231     .340   .069080   .244150   .1986760   -59.600    -5.900  
+ 0 820 51776.00 I   .067529  .000032   .244006  .000031  I  .1980179  .0000077  0.6696 0.0080  I   -59.722     .740    -6.224     .340   .067510   .244020   .1980460   -60.100    -5.900  
+ 0 821 51777.00 I   .065843  .000033   .243813  .000036  I  .1973375  .0000071  0.6829 0.0066  I   -59.896     .740    -6.218     .340   .065840   .243870   .1973380   -60.400    -6.000  
+ 0 822 51778.00 I   .063909  .000033   .243619  .000044  I  .1966686  .0000108  0.6467 0.0065  I   -60.247     .740    -6.239     .340   .063950   .243660   .1966380   -60.700    -6.100  
+ 0 823 51779.00 I   .062076  .000034   .243350  .000045  I  .1960529  .0000109  0.5841 0.0076  I   -60.681     .740    -6.304     .340   .062070   .243450   .1960370   -60.700    -6.200  
+ 0 824 51780.00 I   .060596  .000037   .243028  .000053  I  .1955095  .0000108  0.4940 0.0075  I   -61.006     .740    -6.416     .340   .060540   .243110   .1955580   -60.600    -6.300  
+ 0 825 51781.00 I   .059118  .000031   .242771  .000052  I  .1950637  .0000102  0.4073 0.0086  I   -61.072     .740    -6.543     .340   .059070   .242770   .1951390   -60.500    -6.400  
+ 0 826 51782.00 I   .057453  .000040   .242702  .000055  I  .1946679  .0000133  0.4015 0.0107  I   -60.870     .740    -6.584     .340   .057380   .242750   .1946870   -60.300    -6.500  
+ 0 827 51783.00 I   .055584  .000041   .242638  .000057  I  .1942311  .0000187  0.4844 0.0084  I   -60.556     .740    -6.441     .340   .055540   .242700   .1942120   -60.300    -6.400  
+ 0 828 51784.00 I   .053762  .000061   .242461  .000045  I  .1936784  .0000101  0.6295 0.0109  I   -60.326     .857    -6.159     .170   .053770   .242480   .1936680   -60.400    -6.200  
+ 0 829 51785.00 I   .052242  .000063   .242168  .000040  I  .1929644  .0000111  0.7977 0.0076  I   -60.255     .857    -5.940     .170   .052240   .242200   .1929680   -60.600    -6.000  
+ 0 830 51786.00 I   .051091  .000062   .241829  .000034  I  .1920968  .0000113  0.9246 0.0078  I   -60.295     .857    -5.939     .170   .051050   .241840   .1920900   -60.900    -5.800  
+ 0 831 51787.00 I   .050026  .000063   .241689  .000036  I  .1911429  .0000110  0.9686 0.0079  I   -60.525     .673    -5.991     .340   .050050   .241700   .1911300   -61.300    -5.700  
+ 0 9 1 51788.00 I   .049004  .000063   .241787  .000036  I  .1901885  .0000111  0.9259 0.0076  I   -60.780     .673    -5.998     .340   .049000   .241830   .1902050   -61.600    -5.600  
+ 0 9 2 51789.00 I   .047868  .000064   .241878  .000038  I  .1893152  .0000104  0.8109 0.0093  I   -61.135     .673    -5.832     .340   .047870   .241900   .1893390   -62.300    -5.500  
+ 0 9 3 51790.00 I   .046627  .000053   .241895  .000040  I  .1885815  .0000150  0.6516 0.0067  I   -61.383     .349    -5.698     .189   .046610   .241930   .1885410   -62.500    -5.700  
+ 0 9 4 51791.00 I   .045163  .000067   .241966  .000053  I  .1880169  .0000086  0.4775 0.0095  I   -61.369     .260    -5.808     .177   .045120   .242050   .1879720   -61.700    -5.900  
+ 0 9 5 51792.00 I   .043394  .000068   .242041  .000052  I  .1876245  .0000116  0.3095 0.0069  I   -61.176     .260    -6.107     .177   .043370   .242120   .1875600   -61.400    -6.200  
+ 0 9 6 51793.00 I   .041253  .000070   .242044  .000048  I  .1873924  .0000108  0.1581 0.0080  I   -60.996     .260    -6.344     .177   .041300   .242150   .1873680   -61.100    -6.500  
+ 0 9 7 51794.00 I   .038987  .000070   .241874  .000050  I  .1872994  .0000111  0.0333 0.0077  I   -60.682     .249    -6.379     .178   .038960   .241980   .1873270   -60.600    -6.600  
+ 0 9 8 51795.00 I   .036646  .000072   .241519  .000057  I  .1873119  .0000110 -0.0499 0.0084  I   -60.586     .249    -6.270     .178   .036650   .241590   .1873080   -60.100    -6.700  
+ 0 9 9 51796.00 I   .034228  .000066   .241045  .000056  I  .1873757  .0000126 -0.0627 0.0094  I   -60.499     .249    -6.197     .178   .034220   .241120   .1874040   -59.800    -6.700  
+ 0 910 51797.00 I   .031863  .000042   .240490  .000049  I  .1874162  .0000153 -0.0122 0.0078  I   -60.471     .740    -6.213     .191   .031860   .240520   .1874630   -59.600    -6.600  
+ 0 911 51798.00 I   .029800  .000047   .240042  .000056  I  .1873909  .0000092  0.0660 0.0089  I   -60.459     .274    -6.227     .143   .029850   .240070   .1874080   -59.700    -6.400  
+ 0 912 51799.00 I   .027756  .000046   .239711  .000062  I  .1872765  .0000092  0.1672 0.0067  I   -60.358     .274    -6.125     .143   .027770   .239730   .1872670   -59.900    -6.100  
+ 0 913 51800.00 I   .025131  .000066   .239553  .000069  I  .1870392  .0000097  0.3203 0.0067  I   -60.185     .274    -5.898     .143   .025180   .239550   .1870400   -60.300    -5.900  
+ 0 914 51801.00 I   .022100  .000068   .239613  .000070  I  .1866261  .0000097  0.5028 0.0061  I   -60.105     .261    -5.689     .156   .022170   .239660   .1866420   -60.600    -5.700  
+ 0 915 51802.00 I   .019235  .000065   .239702  .000068  I  .1860446  .0000075  0.6525 0.0067  I   -60.160     .261    -5.586     .156   .019230   .239770   .1860490   -61.000    -5.600  
+ 0 916 51803.00 I   .016892  .000062   .239768  .000070  I  .1853451  .0000092  0.7304 0.0051  I   -60.265     .261    -5.648     .156   .016920   .239800   .1853450   -61.300    -5.600  
+ 0 917 51804.00 I   .015146  .000050   .239926  .000085  I  .1846132  .0000069  0.7203 0.0059  I   -60.308     .109    -5.775     .340   .015190   .239960   .1845970   -61.400    -5.600  
+ 0 918 51805.00 I   .013673  .000055   .240390  .000083  I  .1839280  .0000074  0.6397 0.0050  I   -60.331     .740    -5.843     .340   .013700   .240450   .1839060   -61.300    -5.700  
+ 0 919 51806.00 I   .012234  .000046   .241177  .000078  I  .1833480  .0000072  0.5165 0.0053  I   -60.453     .740    -5.826     .340   .012240   .241170   .1833410   -61.000    -5.700  
+ 0 920 51807.00 I   .010639  .000049   .242107  .000084  I  .1828855  .0000077  0.4218 0.0053  I   -60.681     .740    -5.794     .340   .010580   .242100   .1828890   -60.700    -5.800  
+ 0 921 51808.00 I   .008784  .000049   .242995  .000082  I  .1824901  .0000079  0.3702 0.0053  I   -60.780     .125    -5.845     .340   .008730   .243030   .1824890   -60.100    -5.800  
+ 0 922 51809.00 I   .006877  .000049   .243489  .000079  I  .1821322  .0000073  0.3574 0.0065  I   -60.690     .125    -5.890     .340   .006910   .243550   .1821650   -59.600    -5.800  
+ 0 923 51810.00 I   .005374  .000058   .243521  .000063  I  .1817526  .0000102  0.4127 0.0060  I   -60.319     .125    -5.852     .340   .005410   .243510   .1817180   -59.300    -5.700  
+ 0 924 51811.00 I   .004180  .000061   .243406  .000056  I  .1812846  .0000096  0.5348 0.0072  I   -59.864     .222    -5.649     .137   .004180   .243400   .1812110   -59.000    -5.700  
+ 0 925 51812.00 I   .002961  .000071   .243379  .000042  I  .1806641  .0000102  0.7138 0.0067  I   -59.581     .289    -5.324     .158   .002940   .243410   .1806320   -58.900    -5.500  
+ 0 926 51813.00 I   .001685  .000068   .243522  .000042  I  .1798529  .0000094  0.9053 0.0074  I   -59.566     .289    -5.044     .158   .001720   .243530   .1798730   -59.000    -5.300  
+ 0 927 51814.00 I   .000637  .000065   .243908  .000034  I  .1788651  .0000107  1.0620 0.0069  I   -59.696     .289    -4.961     .158   .000670   .243960   .1788750   -59.200    -5.100  
+ 0 928 51815.00 I  -.000618  .000065   .244567  .000036  I  .1777557  .0000102  1.1383 0.0074  I   -59.804     .289    -5.055     .158  -.000600   .244620   .1777340   -59.400    -5.000  
+ 0 929 51816.00 I  -.002327  .000067   .245461  .000042  I  .1766239  .0000101  1.1083 0.0081  I   -59.878     .297    -5.130     .188  -.002350   .245470   .1766000   -59.600    -4.900  
+ 0 930 51817.00 I  -.004224  .000059   .246291  .000072  I  .1755666  .0000126  0.9957 0.0135  I   -59.920     .297    -5.130     .188  -.004230   .246310   .1756310   -59.800    -4.900  
+ 010 1 51818.00 I  -.005825  .000065   .246948  .000107  I  .1746510  .0000250  0.8278 0.0089  I   -59.969     .176    -5.101     .119  -.005830   .246970   .1747260   -59.800    -5.000  
+ 010 2 51819.00 I  -.007317  .000079   .247621  .000126  I  .1739216  .0000126  0.6283 0.0136  I   -59.939     .239    -5.189     .340  -.007300   .247640   .1739250   -59.700    -5.100  
+ 010 3 51820.00 I  -.009224  .000082   .248297  .000128  I  .1733949  .0000107  0.4272 0.0084  I   -59.745     .239    -5.387     .340  -.009170   .248320   .1733650   -59.400    -5.200  
+ 010 4 51821.00 I  -.011143  .000084   .248950  .000125  I  .1730499  .0000112  0.2778 0.0078  I   -59.402     .239    -5.525     .340  -.011180   .248870   .1730460   -58.900    -5.400  
+ 010 5 51822.00 I  -.013069  .000084   .249438  .000126  I  .1728087  .0000114  0.2201 0.0079  I   -59.020     .245    -5.434     .340  -.013050   .249390   .1728150   -58.600    -5.500  
+ 010 6 51823.00 I  -.014665  .000080   .249912  .000114  I  .1725813  .0000111  0.2476 0.0070  I   -58.714     .245    -5.280     .340  -.014670   .249930   .1725740   -58.100    -5.500  
+ 010 7 51824.00 I  -.016139  .000064   .250291  .000085  I  .1722903  .0000080  0.3446 0.0156  I   -58.558     .245    -5.181     .340  -.016150   .250310   .1723010   -57.800    -5.400  
+ 010 8 51825.00 I  -.017636  .000033   .250548  .000036  I  .1718754  .0000291  0.4916 0.0078  I   -58.518     .292    -5.207     .340  -.017650   .250520   .1718640   -57.600    -5.300  
+ 010 9 51826.00 I  -.019065  .000053   .250992  .000078  I  .1712972  .0000135  0.6682 0.0155  I   -58.483     .285    -5.261     .106  -.019100   .250930   .1712420   -57.700    -5.200  
+ 01010 51827.00 I  -.020494  .000061   .251829  .000106  I  .1705340  .0000104  0.8597 0.0086  I   -58.380     .285    -5.183     .106  -.020520   .251850   .1704830   -57.800    -5.000  
+ 01011 51828.00 I  -.021762  .000063   .253062  .000105  I  .1695809  .0000106  1.0417 0.0077  I   -58.247     .285    -4.908     .106  -.021790   .253120   .1695750   -58.100    -4.800  
+ 01012 51829.00 I  -.022955  .000061   .254629  .000103  I  .1684621  .0000114  1.1891 0.0077  I   -58.260     .333    -4.550     .105  -.022930   .254700   .1684640   -58.500    -4.600  
+ 01013 51830.00 I  -.024334  .000062   .256374  .000104  I  .1672188  .0000111  1.2883 0.0075  I   -58.296     .333    -4.314     .105  -.024370   .256430   .1672620   -58.800    -4.500  
+ 01014 51831.00 I  -.026199  .000063   .257929  .000105  I  .1659060  .0000097  1.3260 0.0073  I   -58.363     .314    -4.345     .173  -.026230   .257910   .1658840   -59.000    -4.400  
+ 01015 51832.00 I  -.028276  .000043   .259197  .000087  I  .1645897  .0000094  1.2951 0.0066  I   -58.380     .320    -4.573     .211  -.028270   .259150   .1644540   -59.100    -4.400  
+ 01016 51833.00 I  -.030364  .000046   .260226  .000042  I  .1633355  .0000090  1.2053 0.0061  I   -58.349     .341    -4.784     .193  -.030370   .260220   .1631760   -59.000    -4.400  
+ 01017 51834.00 I  -.032237  .000041   .261068  .000050  I  .1621903  .0000078  1.0821 0.0062  I   -58.332     .341    -4.817     .193  -.032240   .261070   .1621250   -58.700    -4.500  
+ 01018 51835.00 I  -.034006  .000040   .261825  .000051  I  .1611638  .0000085  0.9816 0.0056  I   -58.350     .341    -4.690     .193  -.033940   .261820   .1611760   -58.100    -4.500  
+ 01019 51836.00 I  -.035697  .000040   .262610  .000050  I  .1602119  .0000081  0.9269 0.0054  I   -58.430     .396    -4.520     .194  -.035650   .262640   .1601930   -57.600    -4.600  
+ 01020 51837.00 I  -.037440  .000042   .263490  .000056  I  .1592914  .0000067  0.9281 0.0059  I   -58.265     .396    -4.410     .194  -.037410   .263500   .1593100   -57.100    -4.500  
+ 01021 51838.00 I  -.039119  .000047   .264415  .000053  I  .1583268  .0000085  1.0159 0.0043  I   -57.924     .474    -4.329     .101  -.039160   .264420   .1584290   -56.800    -4.500  
+ 01022 51839.00 I  -.040594  .000031   .265452  .000052  I  .1572384  .0000054  1.1673 0.0048  I   -57.520     .740    -4.219     .340  -.040620   .265410   .1573430   -56.600    -4.400  
+ 01023 51840.00 I  -.041999  .000037   .266789  .000047  I  .1559864  .0000046  1.3361 0.0032  I   -57.248     .740    -4.066     .105  -.042050   .266770   .1560110   -56.600    -4.200  
+ 01024 51841.00 I  -.043325  .000037   .268351  .000047  I  .1545737  .0000034  1.4824 0.0030  I   -57.230     .740    -3.925     .105  -.043340   .268370   .1545450   -56.900    -4.100  
+ 01025 51842.00 I  -.044307  .000038   .269937  .000058  I  .1530409  .0000037  1.5707 0.0024  I   -57.410     .740    -3.869     .105  -.044330   .269950   .1530330   -57.300    -4.000  
+ 01026 51843.00 I  -.045559  .000044   .271645  .000058  I  .1514582  .0000035  1.5812 0.0023  I   -57.603     .740    -3.911     .105  -.045520   .271650   .1514710   -57.600    -3.900  
+ 01027 51844.00 I  -.046947  .000037   .273406  .000063  I  .1499040  .0000027  1.5152 0.0035  I   -57.650     .740    -3.985     .105  -.046990   .273440   .1499100   -57.800    -3.900  
+ 01028 51845.00 I  -.048312  .000042   .274938  .000068  I  .1484473  .0000060  1.3905 0.0034  I   -57.545     .740    -4.029     .105  -.048330   .274930   .1484300   -58.000    -3.900  
+ 01029 51846.00 I  -.049258  .000049   .276441  .000065  I  .1471312  .0000062  1.2411 0.0050  I   -57.393     .242    -4.061     .145  -.049290   .276360   .1471610   -57.900    -4.000  
+ 01030 51847.00 I  -.050029  .000053   .278336  .000063  I  .1459646  .0000079  1.0933 0.0048  I   -57.247     .197    -4.138     .178  -.050100   .278260   .1460480   -57.600    -4.100  
+ 01031 51848.00 I  -.051245  .000056   .280534  .000055  I  .1449376  .0000074  0.9666 0.0053  I   -57.032     .197    -4.240     .178  -.051190   .280530   .1449780   -57.200    -4.200  
+ 011 1 51849.00 I  -.052365  .000053   .282579  .000069  I  .1440273  .0000070  0.8524 0.0051  I   -56.665     .197    -4.258     .178  -.052430   .282600   .1440070   -56.600    -4.500  
+ 011 2 51850.00 I  -.053768  .000049   .284278  .000065  I  .1432139  .0000071  0.7951 0.0050  I   -56.224     .197    -4.134     .178  -.053760   .284260   .1432280   -55.800    -4.300  
+ 011 3 51851.00 I  -.055168  .000049   .285920  .000067  I  .1424100  .0000071  0.8192 0.0054  I   -55.902     .197    -3.954     .178  -.055120   .285960   .1424240   -55.300    -4.200  
+ 011 4 51852.00 I  -.056466  .000041   .287605  .000071  I  .1415673  .0000081  0.8678 0.0046  I   -55.779     .197    -3.855     .178  -.056420   .287660   .1415700   -55.000    -4.100  
+ 011 5 51853.00 I  -.057701  .000038   .289318  .000071  I  .1406684  .0000059  0.9344 0.0049  I   -55.737     .435    -3.867     .340  -.057720   .289250   .1406590   -54.900    -4.000  
+ 011 6 51854.00 I  -.059197  .000032   .291235  .000073  I  .1396914  .0000054  1.0221 0.0047  I   -55.656     .391    -3.893     .340  -.059220   .291140   .1396830   -55.000    -4.000  
+ 011 7 51855.00 I  -.060735  .000034   .293436  .000055  I  .1386201  .0000072  1.1219 0.0048  I   -55.577     .391    -3.811     .340  -.060760   .293410   .1386150   -55.300    -4.000  
+ 011 8 51856.00 I  -.062207  .000032   .295705  .000054  I  .1374452  .0000080  1.2287 0.0051  I   -55.610     .391    -3.571     .340  -.062220   .295680   .1374380   -55.700    -4.000  
+ 011 9 51857.00 I  -.063703  .000031   .297752  .000052  I  .1361688  .0000072  1.3172 0.0066  I   -55.736     .391    -3.226     .340  -.063730   .297700   .1361610   -56.100    -3.900  
+ 01110 51858.00 I  -.065070  .000045   .299403  .000065  I  .1348301  .0000105  1.3480 0.0095  I   -55.822     .391    -2.921     .340  -.065100   .299370   .1348130   -56.600    -3.800  
+ 01111 51859.00 I  -.065971  .000044   .300644  .000081  I  .1335009  .0000176  1.2946 0.0123  I   -55.801     .409    -2.825     .340  -.066020   .300590   .1334650   -56.800    -3.700  
+ 01112 51860.00 I  -.066267  .000059   .301799  .000080  I  .1322709  .0000222  1.1511 0.0107  I   -55.718     .369    -2.987     .340  -.066280   .301690   .1322310   -56.900    -3.500  
+ 01113 51861.00 I  -.066492  .000068   .303333  .000075  I  .1312182  .0000122  0.9491 0.0125  I   -55.618     .389    -3.254     .340  -.066450   .303290   .1312040   -56.600    -3.400  
+ 01114 51862.00 I  -.067493  .000071   .305215  .000075  I  .1303689  .0000116  0.7585 0.0085  I   -55.481     .389    -3.380     .340  -.067400   .305250   .1303790   -56.200    -3.300  
+ 01115 51863.00 I  -.069107  .000069   .306966  .000073  I  .1296774  .0000119  0.6393 0.0080  I   -55.297     .389    -3.254     .340  -.069160   .307050   .1296860   -55.700    -3.200  
+ 01116 51864.00 I  -.071252  .000069   .308424  .000065  I  .1290646  .0000111  0.5971 0.0069  I   -55.106     .389    -2.984     .340  -.071220   .308460   .1290580   -55.000    -3.200  
+ 01117 51865.00 I  -.073154  .000075   .309840  .000046  I  .1284567  .0000071  0.6344 0.0067  I   -54.940     .389    -2.766     .340  -.073120   .309810   .1284520   -54.500    -3.100  
+ 01118 51866.00 I  -.074727  .000064   .311485  .000040  I  .1277697  .0000074  0.7501 0.0072  I   -54.776     .358    -2.695     .340  -.074710   .311500   .1277780   -54.100    -3.100  
+ 01119 51867.00 I  -.075653  .000057   .313425  .000046  I  .1269444  .0000126  0.9020 0.0071  I   -54.594     .740    -2.727     .103  -.075660   .313440   .1269430   -54.000    -3.200  
+ 01120 51868.00 I  -.075902  .000065   .315632  .000067  I  .1259690  .0000122  1.0441 0.0087  I   -54.447     .740    -2.780     .103  -.075870   .315600   .1259530   -54.000    -3.100  
+ 01121 51869.00 I  -.075832  .000065   .317969  .000067  I  .1248704  .0000120  1.1438 0.0087  I   -54.435     .740    -2.817     .103  -.075810   .317980   .1248720   -54.200    -3.100  
+ 01122 51870.00 I  -.075847  .000066   .320194  .000067  I  .1236988  .0000124  1.1914 0.0087  I   -54.603     .740    -2.842     .103  -.075840   .320240   .1237180   -54.600    -3.000  
+ 01123 51871.00 I  -.076126  .000052   .322251  .000070  I  .1225155  .0000127  1.1555 0.0088  I   -54.868     .740    -2.850     .103  -.076120   .322250   .1224790   -54.900    -2.900  
+ 01124 51872.00 I  -.076569  .000052   .324131  .000071  I  .1214167  .0000124  1.0330 0.0091  I   -55.054     .740    -2.830     .103  -.076580   .324110   .1213050   -55.200    -2.800  
+ 01125 51873.00 I  -.077090  .000052   .325916  .000070  I  .1204631  .0000129  0.8696 0.0073  I   -55.037     .740    -2.798     .103  -.077060   .325860   .1203310   -55.300    -2.700  
+ 01126 51874.00 I  -.077734  .000046   .327749  .000049  I  .1196786  .0000076  0.7027 0.0071  I   -54.853     .194    -2.810     .254  -.077740   .327710   .1195830   -55.200    -2.700  
+ 01127 51875.00 I  -.078464  .000053   .329650  .000070  I  .1190476  .0000061  0.5661 0.0053  I   -54.621     .194    -2.900     .254  -.078510   .329660   .1190050   -54.900    -2.700  
+ 01128 51876.00 I  -.079156  .000052   .331507  .000069  I  .1185260  .0000073  0.4908 0.0049  I   -54.377     .194    -3.003     .254  -.079060   .331530   .1185190   -54.300    -2.700  
+ 01129 51877.00 I  -.079387  .000049   .333385  .000065  I  .1180405  .0000076  0.4920 0.0053  I   -54.081     .194    -3.001     .254  -.079330   .333330   .1180470   -53.600    -2.700  
+ 01130 51878.00 I  -.079572  .000049   .335195  .000064  I  .1175256  .0000077  0.5425 0.0052  I   -53.785     .194    -2.868     .254  -.079610   .335150   .1175220   -53.000    -2.700  
+ 012 1 51879.00 I  -.080077  .000052   .336962  .000063  I  .1169465  .0000071  0.6199 0.0060  I   -53.640     .194    -2.711     .254  -.080070   .336980   .1169220   -52.500    -2.700  
+ 012 2 51880.00 I  -.080633  .000053   .338725  .000066  I  .1162730  .0000093  0.7357 0.0092  I   -53.606     .155    -2.570     .158  -.080610   .338690   .1162800   -52.500    -2.800  
+ 012 3 51881.00 I  -.080874  .000041   .340453  .000038  I  .1154659  .0000170  0.8793 0.0068  I   -53.633     .142    -2.597     .340  -.080890   .340360   .1155090   -52.500    -2.700  
+ 012 4 51882.00 I  -.080959  .000066   .342134  .000071  I  .1145151  .0000100  1.0210 0.0099  I   -53.534     .133    -2.617     .340  -.081000   .342100   .1145360   -52.700    -2.700  
+ 012 5 51883.00 I  -.081277  .000097   .343792  .000082  I  .1134289  .0000103  1.1477 0.0071  I   -53.453     .177    -2.579     .190  -.081290   .343710   .1134120   -53.100    -2.600  
+ 012 6 51884.00 I  -.081778  .000099   .345435  .000083  I  .1122263  .0000102  1.2545 0.0074  I   -53.580     .177    -2.488     .190  -.081830   .345320   .1122210   -53.400    -2.500  
+ 012 7 51885.00 I  -.082321  .000100   .347178  .000086  I  .1109317  .0000105  1.3258 0.0072  I   -53.798     .211    -2.360     .166  -.082340   .347130   .1109530   -53.700    -2.400  
+ 012 8 51886.00 I  -.082764  .000097   .349073  .000087  I  .1095995  .0000102  1.3226 0.0073  I   -53.940     .211    -2.098     .166  -.082810   .349020   .1095820   -54.000    -2.200  
+ 012 9 51887.00 I  -.083349  .000097   .350969  .000089  I  .1083132  .0000102  1.2392 0.0063  I   -53.926     .211    -1.843     .166  -.083330   .350940   .1083340   -54.100    -2.200  
+ 01210 51888.00 I  -.083714  .000094   .352612  .000108  I  .1071406  .0000073  1.0974 0.0057  I   -53.922     .247    -1.782     .292  -.083680   .352570   .1071950   -54.100    -2.100  
+ 01211 51889.00 I  -.083829  .000083   .353999  .000106  I  .1061295  .0000049  0.9222 0.0043  I   -53.971     .236    -1.964     .268  -.083840   .354000   .1061520   -53.900    -2.000  
+ 01212 51890.00 I  -.083649  .000088   .355350  .000103  I  .1052914  .0000044  0.7614 0.0037  I   -53.885     .221    -2.184     .278  -.083610   .355370   .1052740   -53.600    -2.000  
+ 01213 51891.00 I  -.082749  .000087   .357031  .000098  I  .1045855  .0000056  0.6643 0.0036  I   -53.532     .221    -2.197     .278  -.082670   .356990   .1045790   -53.100    -2.000  
+ 01214 51892.00 I  -.081454  .000086   .359066  .000096  I  .1039318  .0000056  0.6601 0.0039  I   -52.962     .139    -1.961     .254  -.081380   .359130   .1039370   -52.500    -1.900  
+ 01215 51893.00 I  -.080187  .000089   .361234  .000096  I  .1032411  .0000055  0.7284 0.0042  I   -52.615     .139    -1.742     .254  -.080170   .361250   .1032250   -52.100    -1.900  
+ 01216 51894.00 I  -.079088  .000083   .363461  .000065  I  .1024684  .0000062  0.8166 0.0046  I   -52.487     .373    -1.678     .220  -.079090   .363400   .1024390   -51.700    -1.800  
+ 01217 51895.00 I  -.078140  .000064   .365712  .000067  I  .1016101  .0000074  0.8984 0.0066  I   -52.494     .381    -1.737     .163  -.078160   .365680   .1014840   -51.700    -1.800  
+ 01218 51896.00 I  -.077838  .000071   .367832  .000075  I  .1006813  .0000117  0.9512 0.0065  I   -52.538     .373    -1.801     .151  -.077860   .367890   .1004880   -51.800    -1.800  
+ 01219 51897.00 I  -.078183  .000072   .369725  .000074  I  .0997235  .0000107  0.9567 0.0083  I   -52.608     .373    -1.834     .151  -.078140   .369680   .0996230   -52.200    -1.900  
+ 01220 51898.00 I  -.078693  .000069   .371616  .000074  I  .0987847  .0000118  0.9117 0.0080  I   -52.751     .373    -1.870     .151  -.078760   .371540   .0987910   -52.600    -2.000  
+ 01221 51899.00 I  -.078656  .000068   .373822  .000074  I  .0979190  .0000118  0.8099 0.0083  I   -52.968     .397    -1.954     .161  -.078790   .373900   .0978530   -53.000    -2.100  
+ 01222 51900.00 I  -.078397  .000073   .376311  .000077  I  .0971744  .0000118  0.6794 0.0087  I   -53.238     .397    -1.956     .161  -.078300   .376360   .0971970   -53.400    -2.300  
+ 01223 51901.00 I  -.078015  .000076   .378911  .000064  I  .0965589  .0000128  0.5527 0.0095  I   -53.380     .162    -1.922     .116  -.077960   .378920   .0966350   -53.600    -2.300  
+ 01224 51902.00 I  -.077568  .000053   .381524  .000051  I  .0960664  .0000150  0.4337 0.0109  I   -53.296     .740    -1.938     .340  -.077570   .381510   .0961140   -53.500    -2.300  
+ 01225 51903.00 I  -.077052  .000056   .384097  .000057  I  .0956855  .0000176  0.3328 0.0080  I   -53.041     .209    -2.062     .340  -.077090   .384100   .0956820   -53.300    -2.300  
+ 01226 51904.00 I  -.076627  .000087   .386538  .000077  I  .0953894  .0000055  0.2661 0.0093  I   -52.739     .192    -2.219     .340  -.076580   .386520   .0953610   -53.100    -2.300  
+ 01227 51905.00 I  -.076313  .000079   .388743  .000073  I  .0951401  .0000060  0.2388 0.0043  I   -52.473     .192    -2.267     .340  -.076400   .388660   .0951180   -52.600    -2.300  
+ 01228 51906.00 I  -.076058  .000079   .390710  .000072  I  .0948989  .0000065  0.2500 0.0043  I   -52.307     .192    -2.175     .340  -.076070   .390660   .0948940   -52.300    -2.100  
+ 01229 51907.00 I  -.075340  .000079   .392637  .000074  I  .0946252  .0000063  0.3057 0.0048  I   -52.316     .192    -2.062     .340  -.075390   .392710   .0946300   -51.900    -2.000  
+ 01230 51908.00 I  -.074867  .000076   .394535  .000076  I  .0942721  .0000070  0.4076 0.0047  I   -52.467     .192    -2.049     .340  -.074860   .394520   .0942860   -51.700    -2.000  
+ 01231 51909.00 I  -.074232  .000073   .396311  .000078  I  .0938013  .0000069  0.5356 0.0038  I   -52.572     .191    -2.112     .340  -.074200   .396280   .0938240   -51.600    -1.900  
+ 1 1 1 51910.00 I  -.073475  .000040   .398000  .000052  I  .0932012  .0000032  0.6628 0.0037  I   -52.513     .174    -2.159     .340  -.073450   .397930   .0932210   -51.600    -2.000  
+ 1 1 2 51911.00 I  -.072616  .000042   .399776  .000057  I  .0924807  .0000029  0.7749 0.0022  I   -52.431     .174    -2.184     .340  -.072570   .399630   .0924880   -51.800    -2.100  
+ 1 1 3 51912.00 I  -.071574  .000046   .401696  .000058  I  .0916585  .0000029  0.8655 0.0022  I   -52.522     .174    -2.242     .340  -.071560   .401750   .0916580   -52.100    -2.300  
+ 1 1 4 51913.00 I  -.071043  .000043   .403552  .000055  I  .0907643  .0000033  0.9123 0.0022  I   -52.722     .174    -2.278     .340  -.071020   .403630   .0907650   -52.600    -2.400  
+ 1 1 5 51914.00 I  -.070727  .000043   .405169  .000052  I  .0898571  .0000033  0.8897 0.0036  I   -52.837     .174    -2.140     .340  -.070740   .405100   .0898580   -53.100    -1.900  
+ 1 1 6 51915.00 I  -.070375  .000043   .406607  .000044  I  .0890085  .0000064  0.7965 0.0061  I   -52.917     .189    -1.821     .340  -.070400   .406550   .0890200   -53.500    -1.800  
+ 1 1 7 51916.00 I  -.070175  .000047   .407955  .000050  I  .0882806  .0000117  0.6539 0.0053  I   -53.215     .183    -1.575     .340  -.070180   .407910   .0883060   -53.700    -1.800  
+ 1 1 8 51917.00 I  -.070202  .000045   .409286  .000070  I  .0876993  .0000084  0.5154 0.0068  I   -53.713     .196    -1.647     .340  -.070120   .409250   .0877260   -53.800    -1.800  
+ 1 1 9 51918.00 I  -.070110  .000056   .410656  .000066  I  .0872305  .0000069  0.4348 0.0056  I   -53.979     .196    -1.955     .340  -.070060   .410700   .0872420   -53.500    -2.000  
+ 1 110 51919.00 I  -.069867  .000052   .412121  .000066  I  .0868107  .0000075  0.4113 0.0051  I   -53.649     .196    -2.180     .340  -.069810   .412100   .0868070   -53.200    -2.200  
+ 1 111 51920.00 I  -.069253  .000052   .413913  .000065  I  .0863871  .0000074  0.4502 0.0048  I   -52.624     .740    -2.182     .340  -.069330   .413860   .0863720   -52.700    -2.400  
+ 1 112 51921.00 I  -.068491  .000054   .415946  .000067  I  .0858811  .0000061  0.5766 0.0053  I   -51.878     .740    -2.036     .340  -.068490   .415910   .0858980   -52.300    -2.600  
+ 1 113 51922.00 I  -.067476  .000048   .418035  .000067  I  .0852171  .0000075  0.7532 0.0059  I   -51.498     .740    -1.953     .340  -.067480   .418010   .0852290   -52.000    -2.400  
+ 1 114 51923.00 I  -.066439  .000049   .420036  .000049  I  .0843862  .0000101  0.8952 0.0050  I   -51.499     .330    -1.918     .206  -.066440   .420030   .0843870   -51.900    -2.300  
+ 1 115 51924.00 I  -.065330  .000036   .421837  .000061  I  .0834544  .0000067  0.9543 0.0062  I   -51.709     .311    -1.818     .182  -.065340   .421820   .0834490   -51.900    -2.100  
+ 1 116 51925.00 I  -.063996  .000041   .423433  .000081  I  .0825093  .0000072  0.9185 0.0055  I   -51.949     .311    -1.677     .182  -.064050   .423420   .0825050   -52.000    -1.900  
+ 1 117 51926.00 I  -.062707  .000040   .424929  .000081  I  .0816517  .0000088  0.7799 0.0056  I   -52.141     .311    -1.643     .182  -.062730   .424880   .0816480   -52.200    -1.900  
+ 1 118 51927.00 I  -.061468  .000041   .426305  .000081  I  .0809688  .0000085  0.5836 0.0059  I   -52.315     .332    -1.770     .181  -.061460   .426190   .0809690   -52.400    -1.900  
+ 1 119 51928.00 I  -.060311  .000045   .427747  .000088  I  .0804814  .0000080  0.3968 0.0058  I   -52.581     .332    -1.948     .181  -.060340   .427710   .0804850   -52.600    -2.100  
+ 1 120 51929.00 I  -.059229  .000050   .429112  .000088  I  .0801680  .0000078  0.2317 0.0061  I   -52.834     .332    -2.065     .181  -.059270   .429150   .0801190   -52.600    -2.200  
+ 1 121 51930.00 I  -.058108  .000049   .430179  .000088  I  .0800094  .0000093  0.0923 0.0060  I   -52.871     .122    -2.149     .189  -.058160   .430160   .0799550   -52.500    -2.300  
+ 1 122 51931.00 I  -.056802  .000062   .431143  .000063  I  .0799699  .0000090 -0.0066 0.0057  I   -52.610     .125    -2.279     .211  -.056820   .431050   .0799820   -52.400    -2.400  
+ 1 123 51932.00 I  -.055433  .000062   .432399  .000068  I  .0800133  .0000065 -0.0777 0.0055  I   -52.196     .125    -2.422     .211  -.055400   .432420   .0800690   -52.100    -2.400  
+ 1 124 51933.00 I  -.054105  .000061   .434088  .000066  I  .0800967  .0000064 -0.0631 0.0046  I   -51.846     .125    -2.457     .211  -.054080   .434170   .0801060   -51.700    -2.300  
+ 1 125 51934.00 I  -.052244  .000061   .435907  .000063  I  .0801067  .0000064  0.0500 0.0045  I   -51.605     .196    -2.312     .172  -.052310   .435870   .0800960   -51.400    -2.100  
+ 1 126 51935.00 I  -.050480  .000061   .437795  .000065  I  .0799898  .0000062  0.1837 0.0052  I   -51.624     .196    -2.188     .172  -.050530   .437790   .0799840   -51.000    -2.100  
+ 1 127 51936.00 I  -.049071  .000061   .439653  .000076  I  .0797378  .0000083  0.3217 0.0047  I   -51.770     .196    -2.174     .172  -.049080   .439600   .0797570   -50.900    -2.100  
+ 1 128 51937.00 I  -.047516  .000040   .441457  .000081  I  .0793490  .0000070  0.4518 0.0054  I   -51.917     .125    -2.262     .200  -.047500   .441380   .0794010   -50.800    -2.100  
+ 1 129 51938.00 I  -.045591  .000037   .443202  .000100  I  .0788464  .0000068  0.5454 0.0048  I   -51.961     .176    -2.358     .171  -.045590   .443170   .0789010   -50.900    -2.300  
+ 1 130 51939.00 I  -.043693  .000038   .444798  .000100  I  .0782754  .0000067  0.5875 0.0048  I   -51.946     .176    -2.440     .171  -.043680   .444700   .0782950   -51.100    -2.400  
+ 1 131 51940.00 I  -.042033  .000035   .446206  .000097  I  .0776959  .0000069  0.5562 0.0048  I   -51.980     .176    -2.569     .171  -.042080   .446190   .0776930   -51.600    -2.700  
+ 1 2 1 51941.00 I  -.040636  .000032   .447190  .000096  I  .0771815  .0000069  0.4696 0.0044  I   -51.985     .124    -2.765     .137  -.040620   .447160   .0771880   -52.100    -3.000  
+ 1 2 2 51942.00 I  -.039126  .000029   .447931  .000089  I  .0767659  .0000053  0.3556 0.0043  I   -51.998     .124    -2.769     .137  -.039100   .447830   .0767630   -52.600    -3.200  
+ 1 2 3 51943.00 I  -.037703  .000032   .448626  .000084  I  .0764797  .0000051  0.2136 0.0036  I   -52.080     .124    -2.567     .137  -.037700   .448620   .0764750   -52.900    -3.400  
+ 1 2 4 51944.00 I  -.036061  .000043   .449368  .000035  I  .0763355  .0000049  0.0814 0.0038  I   -52.499     .740    -2.361     .340  -.036070   .449360   .0763320   -53.300    -3.500  
+ 1 2 5 51945.00 I  -.034020  .000069   .450341  .000038  I  .0762962  .0000055  0.0113 0.0035  I   -53.224     .740    -2.435     .152  -.034080   .450270   .0763010   -53.400    -3.500  
+ 1 2 6 51946.00 I  -.032180  .000068   .451589  .000039  I  .0762796  .0000049  0.0409 0.0038  I   -53.761     .740    -2.795     .152  -.032090   .451620   .0762880   -53.500    -3.500  
+ 1 2 7 51947.00 I  -.030365  .000068   .453000  .000040  I  .0761678  .0000053  0.2102 0.0037  I   -53.620     .740    -3.153     .152  -.030410   .453010   .0761720   -53.400    -3.300  
+ 1 2 8 51948.00 I  -.028369  .000069   .454523  .000037  I  .0758262  .0000056  0.4784 0.0039  I   -52.834     .740    -3.243     .180  -.028520   .454470   .0758360   -53.200    -3.100  
+ 1 2 9 51949.00 I  -.026513  .000069   .456074  .000063  I  .0752100  .0000057  0.7497 0.0046  I   -51.910     .740    -3.188     .180  -.026520   .456090   .0751990   -52.900    -3.000  
+ 1 210 51950.00 I  -.024700  .000065   .457538  .000069  I  .0743443  .0000074  0.9684 0.0047  I   -51.319     .176    -3.125     .149  -.024720   .457560   .0743150   -52.600    -2.600  
+ 1 211 51951.00 I  -.023433  .000034   .458809  .000078  I  .0733026  .0000076  1.0990 0.0051  I   -51.218     .179    -3.057     .340  -.023390   .458870   .0732830   -52.300    -2.500  
+ 1 212 51952.00 I  -.022363  .000038   .459792  .000083  I  .0721740  .0000069  1.1465 0.0052  I   -51.475     .175    -2.877     .340  -.022340   .459760   .0721790   -52.100    -2.400  
+ 1 213 51953.00 I  -.020906  .000039   .460725  .000082  I  .0710272  .0000071  1.1411 0.0054  I   -51.830     .175    -2.633     .340  -.020910   .460680   .0710400   -51.900    -2.500  
+ 1 214 51954.00 I  -.019204  .000041   .461937  .000080  I  .0699186  .0000084  1.0554 0.0057  I   -52.076     .175    -2.547     .340  -.019230   .461970   .0699210   -51.900    -2.600  
+ 1 215 51955.00 I  -.017628  .000038   .463232  .000068  I  .0689386  .0000089  0.9030 0.0060  I   -52.241     .170    -2.717     .340  -.017580   .463260   .0689260   -51.700    -2.700  
+ 1 216 51956.00 I  -.015910  .000038   .464556  .000068  I  .0681089  .0000085  0.7617 0.0064  I   -52.437     .170    -3.066     .340  -.015900   .464530   .0681100   -51.700    -3.000  
+ 1 217 51957.00 I  -.014070  .000038   .465865  .000067  I  .0674058  .0000092  0.6487 0.0109  I   -52.687     .107    -3.340     .340  -.014070   .465820   .0673560   -51.500    -3.300  
+ 1 218 51958.00 I  -.012282  .000030   .467076  .000057  I  .0667945  .0000200  0.5868 0.0067  I   -52.746     .740    -3.470     .182  -.012260   .467050   .0667340   -51.400    -3.400  
+ 1 219 51959.00 I  -.010501  .000041   .468197  .000057  I  .0662114  .0000097  0.5874 0.0104  I   -52.415     .139    -3.529     .178  -.010490   .468140   .0661950   -51.200    -3.500  
+ 1 220 51960.00 I  -.008318  .000059   .469373  .000058  I  .0656072  .0000059  0.6255 0.0056  I   -51.832     .139    -3.558     .178  -.008260   .469310   .0656190   -51.000    -3.500  
+ 1 221 51961.00 I  -.005520  .000056   .470698  .000052  I  .0649585  .0000054  0.6693 0.0038  I   -51.326     .139    -3.500     .178  -.005540   .470720   .0649590   -50.800    -3.500  
+ 1 222 51962.00 I  -.002296  .000056   .472165  .000052  I  .0642607  .0000048  0.7366 0.0037  I   -50.976     .171    -3.335     .157  -.002380   .472160   .0642450   -50.700    -3.400  
+ 1 223 51963.00 I   .000948  .000058   .473902  .000050  I  .0634634  .0000051  0.8694 0.0036  I   -50.956     .171    -3.147     .157   .001010   .473850   .0634730   -50.500    -3.200  
+ 1 224 51964.00 I   .004069  .000059   .475723  .000048  I  .0625081  .0000053  1.0437 0.0038  I   -51.055     .171    -3.074     .157   .004070   .475750   .0625000   -50.500    -3.200  
+ 1 225 51965.00 I   .006803  .000060   .477346  .000044  I  .0613757  .0000057  1.2189 0.0042  I   -51.200     .740    -3.150     .116   .006820   .477360   .0613410   -50.600    -3.200  
+ 1 226 51966.00 I   .009390  .000056   .478757  .000069  I  .0600802  .0000066  1.3642 0.0055  I   -51.325     .169    -3.303     .340   .009410   .478700   .0600530   -50.700    -3.300  
+ 1 227 51967.00 I   .011992  .000059   .479986  .000071  I  .0586678  .0000093  1.4479 0.0057  I   -51.384     .169    -3.467     .340   .011990   .479910   .0586680   -50.900    -3.500  
+ 1 228 51968.00 I   .014200  .000057   .481045  .000070  I  .0572087  .0000093  1.4586 0.0063  I   -51.395     .169    -3.630     .340   .014300   .481000   .0572140   -51.300    -3.800  
+ 1 3 1 51969.00 I   .016153  .000057   .481998  .000072  I  .0557767  .0000086  1.3911 0.0064  I   -51.668     .685    -3.826     .106   .016090   .481990   .0557520   -51.600    -4.100  
+ 1 3 2 51970.00 I   .017276  .000071   .482700  .000077  I  .0544494  .0000087  1.2550 0.0062  I   -51.632     .685    -3.900     .106   .017280   .482630   .0544200   -51.800    -4.400  
+ 1 3 3 51971.00 I   .018496  .000066   .483232  .000083  I  .0532711  .0000088  1.1058 0.0053  I   -51.638     .145    -3.870     .340   .018470   .483100   .0532710   -52.000    -4.700  
+ 1 3 4 51972.00 I   .020341  .000053   .483840  .000087  I  .0522268  .0000060  0.9897 0.0061  I   -51.810     .740    -3.842     .340   .020380   .483750   .0522360   -52.200    -4.800  
+ 1 3 5 51973.00 I   .022588  .000087   .484558  .000097  I  .0512724  .0000084  0.9316 0.0051  I   -52.135     .412    -3.975     .340   .022620   .484550   .0512640   -52.200    -4.900  
+ 1 3 6 51974.00 I   .024503  .000096   .485112  .000093  I  .0503386  .0000083  0.9484 0.0059  I   -52.357     .412    -4.273     .340   .024500   .485160   .0503260   -52.100    -4.800  
+ 1 3 7 51975.00 I   .026284  .000095   .485380  .000093  I  .0493333  .0000083  1.0920 0.0059  I   -52.202     .412    -4.545     .340   .026380   .485330   .0493410   -52.000    -4.500  
+ 1 3 8 51976.00 I   .028795  .000088   .485434  .000088  I  .0481232  .0000083  1.3296 0.0058  I   -51.688     .412    -4.630     .340   .028660   .485440   .0481510   -51.800    -4.300  
+ 1 3 9 51977.00 I   .031018  .000088   .485399  .000083  I  .0466901  .0000082  1.5191 0.0071  I   -51.107     .412    -4.587     .340   .031050   .485380   .0466690   -51.600    -4.100  
+ 1 310 51978.00 I   .033359  .000092   .485373  .000062  I  .0451120  .0000116  1.6277 0.0063  I   -50.747     .412    -4.572     .340   .033350   .485300   .0451310   -51.400    -3.900  
+ 1 311 51979.00 I   .035564  .000055   .485413  .000035  I  .0434664  .0000096  1.6413 0.0069  I   -50.712     .740    -4.590     .340   .035550   .485400   .0435500   -51.300    -3.800  
+ 1 312 51980.00 I   .038022  .000034   .485524  .000052  I  .0418693  .0000075  1.5354 0.0068  I   -50.933     .412    -4.513     .340   .037980   .485480   .0419400   -51.100    -3.800  
+ 1 313 51981.00 I   .040915  .000033   .485734  .000052  I  .0404265  .0000096  1.3370 0.0064  I   -51.229     .412    -4.330     .340   .040870   .485670   .0404350   -51.000    -3.900  
+ 1 314 51982.00 I   .043874  .000028   .486103  .000048  I  .0392186  .0000104  1.0688 0.0072  I   -51.433     .412    -4.233     .340   .043920   .486220   .0392130   -50.900    -4.200  
+ 1 315 51983.00 I   .046406  .000027   .486377  .000050  I  .0382843  .0000107  0.8144 0.0074  I   -51.535     .412    -4.391     .340   .046450   .486420   .0383080   -50.700    -4.500  
+ 1 316 51984.00 I   .048681  .000028   .486655  .000054  I  .0375617  .0000106  0.6443 0.0073  I   -51.665     .412    -4.724     .340   .048650   .486610   .0375840   -50.600    -4.800  
+ 1 317 51985.00 I   .050978  .000030   .487043  .000053  I  .0369778  .0000099  0.5279 0.0081  I   -51.841     .412    -4.996     .340   .050980   .487060   .0369820   -50.400    -5.100  
+ 1 318 51986.00 I   .053555  .000027   .487408  .000066  I  .0364941  .0000122  0.4468 0.0070  I   -51.824     .740    -5.080     .340   .053540   .487400   .0364890   -50.300    -5.200  
+ 1 319 51987.00 I   .056329  .000044   .487821  .000069  I  .0360676  .0000100  0.4153 0.0072  I   -51.399     .374    -5.031     .176   .056310   .487770   .0360630   -50.200    -5.300  
+ 1 320 51988.00 I   .059135  .000061   .488394  .000086  I  .0356430  .0000077  0.4451 0.0067  I   -50.698     .374    -4.944     .176   .059060   .488390   .0356370   -50.200    -5.100  
+ 1 321 51989.00 I   .061688  .000061   .488864  .000087  I  .0351568  .0000088  0.5365 0.0058  I   -50.111     .374    -4.828     .176   .061640   .488880   .0351550   -50.100    -5.000  
+ 1 322 51990.00 I   .064613  .000062   .489050  .000087  I  .0345635  .0000088  0.6473 0.0064  I   -49.860     .419    -4.696     .152   .064420   .489130   .0345770   -50.100    -4.800  
+ 1 323 51991.00 I   .067318  .000067   .489461  .000088  I  .0338698  .0000092  0.7354 0.0063  I   -49.913     .419    -4.489     .152   .067340   .489510   .0338570   -50.100    -4.600  
+ 1 324 51992.00 I   .070277  .000066   .490025  .000073  I  .0330839  .0000090  0.8498 0.0057  I   -50.077     .419    -4.351     .152   .070240   .490030   .0330900   -50.200    -4.500  
+ 1 325 51993.00 I   .073332  .000083   .490497  .000064  I  .0321623  .0000069  0.9878 0.0053  I   -50.258     .109    -4.368     .340   .073320   .490500   .0321940   -50.200    -4.500  
+ 1 326 51994.00 I   .076391  .000085   .490842  .000038  I  .0311235  .0000056  1.0803 0.0044  I   -50.411     .103    -4.541     .340   .076380   .490860   .0311380   -50.200    -4.600  
+ 1 327 51995.00 I   .079270  .000092   .491052  .000038  I  .0300255  .0000054  1.1015 0.0039  I   -50.482     .140    -4.793     .144   .079230   .491060   .0300160   -50.300    -4.800  
+ 1 328 51996.00 I   .081797  .000092   .491117  .000039  I  .0289424  .0000054  1.0571 0.0037  I   -50.483     .140    -5.020     .144   .081730   .491080   .0289390   -50.200    -5.000  
+ 1 329 51997.00 I   .084181  .000090   .491078  .000040  I  .0279322  .0000052  0.9502 0.0037  I   -50.420     .173    -5.139     .132   .084070   .491050   .0279420   -50.100    -5.300  
+ 1 330 51998.00 I   .086363  .000091   .490780  .000043  I  .0270475  .0000052  0.8270 0.0040  I   -50.514     .173    -5.190     .132   .086360   .490830   .0270520   -49.900    -5.600  
+ 1 331 51999.00 I   .088580  .000077   .490263  .000049  I  .0262681  .0000061  0.7341 0.0044  I   -50.623     .205    -5.212     .153   .088550   .490340   .0262730   -49.800    -5.700  
+ 1 4 1 52000.00 I   .090657  .000062   .489693  .000041  I  .0255680  .0000071  0.6750 0.0041  I   -50.626     .348    -5.274     .164   .090660   .489730   .0255590   -49.700    -5.800  
+ 1 4 2 52001.00 I   .092713  .000034   .489218  .000061  I  .0248977  .0000056  0.6770 0.0043  I   -50.444     .330    -5.404     .340   .092710   .489170   .0248780   -49.600    -5.800  
+ 1 4 3 52002.00 I   .094742  .000033   .488819  .000071  I  .0241865  .0000050  0.7616 0.0040  I   -50.089     .330    -5.549     .340   .094770   .488820   .0241770   -49.500    -5.800  
+ 1 4 4 52003.00 I   .096970  .000033   .488212  .000068  I  .0233415  .0000056  0.9453 0.0039  I   -49.680     .330    -5.609     .340   .097060   .488230   .0233470   -49.600    -5.600  
+ 1 4 5 52004.00 I   .099146  .000034   .487316  .000068  I  .0222831  .0000061  1.1674 0.0048  I   -49.398     .330    -5.542     .340   .099230   .487290   .0222820   -49.600    -5.400  
+ 1 4 6 52005.00 I   .101639  .000034   .486689  .000076  I  .0210200  .0000078  1.3495 0.0055  I   -49.370     .330    -5.440     .340   .101620   .486670   .0210190   -50.000    -5.500  
+ 1 4 7 52006.00 I   .104372  .000034   .486451  .000081  I  .0196018  .0000091  1.4786 0.0067  I   -49.565     .205    -5.436     .340   .104330   .486450   .0196170   -50.200    -5.500  
+ 1 4 8 52007.00 I   .106684  .000029   .486230  .000070  I  .0181065  .0000108  1.4768 0.0066  I   -49.839     .740    -5.535     .340   .106650   .486230   .0181290   -50.300    -5.500  
+ 1 4 9 52008.00 I   .108446  .000054   .485677  .000078  I  .0167021  .0000095  1.3133 0.0075  I   -50.069     .156    -5.600     .340   .108450   .485660   .0167110   -50.400    -5.500  
+ 1 410 52009.00 I   .110408  .000053   .484787  .000077  I  .0155036  .0000103  1.0787 0.0068  I   -50.216     .156    -5.543     .340   .110420   .484780   .0155010   -50.400    -5.500  
+ 1 411 52010.00 I   .112966  .000050   .483921  .000076  I  .0145483  .0000097  0.8332 0.0065  I   -50.299     .156    -5.457     .340   .113020   .483870   .0145520   -50.300    -5.600  
+ 1 412 52011.00 I   .115877  .000049   .483273  .000073  I  .0138282  .0000078  0.6148 0.0058  I   -50.502     .193    -5.557     .340   .115940   .483200   .0138300   -50.000    -5.600  
+ 1 413 52012.00 I   .118552  .000049   .482764  .000070  I  .0133060  .0000062  0.4346 0.0057  I   -50.635     .193    -5.740     .340   .118580   .482740   .0132910   -49.700    -5.600  
+ 1 414 52013.00 I   .120993  .000048   .482036  .000069  I  .0129373  .0000082  0.3195 0.0054  I   -50.769     .193    -5.911     .340   .121010   .481980   .0129400   -49.500    -5.600  
+ 1 415 52014.00 I   .123648  .000030   .481138  .000065  I  .0126343  .0000089  0.3024 0.0054  I   -50.707     .740    -5.950     .340   .123680   .481070   .0126510   -49.100    -5.700  
+ 1 416 52015.00 I   .126521  .000050   .480220  .000061  I  .0122983  .0000071  0.3877 0.0056  I   -50.303     .299    -5.886     .340   .126590   .480190   .0123230   -48.800    -5.800  
+ 1 417 52016.00 I   .129576  .000061   .479260  .000069  I  .0118375  .0000067  0.5371 0.0050  I   -49.685     .285    -5.814     .340   .129610   .479320   .0118590   -48.600    -5.800  
+ 1 418 52017.00 I   .132758  .000060   .478579  .000071  I  .0112160  .0000070  0.7109 0.0049  I   -49.187     .285    -5.762     .340   .132870   .478610   .0112190   -48.500    -5.800  
+ 1 419 52018.00 I   .136404  .000060   .478052  .000070  I  .0104241  .0000071  0.8595 0.0048  I   -49.053     .285    -5.683     .340   .136310   .478060   .0104330   -48.600    -5.900  
+ 1 420 52019.00 I   .139400  .000061   .477581  .000070  I  .0095180  .0000065  0.9450 0.0052  I   -49.257     .285    -5.545     .340   .139470   .477590   .0095310   -48.800    -5.900  
+ 1 421 52020.00 I   .142322  .000063   .476918  .000059  I  .0085454  .0000075  0.9967 0.0056  I   -49.603     .336    -5.390     .340   .142300   .476880   .0085640   -49.100    -5.900  
+ 1 422 52021.00 I   .144945  .000047   .476117  .000058  I  .0075411  .0000092  0.9988 0.0061  I   -49.917     .256    -5.317     .340   .144920   .476040   .0075520   -49.300    -5.900  
+ 1 423 52022.00 I   .147340  .000050   .475404  .000049  I  .0065665  .0000095  0.9449 0.0069  I   -50.103     .177    -5.408     .106   .147380   .475340   .0065630   -49.600    -5.900  
+ 1 424 52023.00 I   .149333  .000050   .474680  .000048  I  .0056600  .0000102  0.8648 0.0069  I   -50.147     .177    -5.648     .106   .149330   .474630   .0056590   -49.800    -6.000  
+ 1 425 52024.00 I   .151014  .000050   .473687  .000041  I  .0048331  .0000100  0.7961 0.0066  I   -50.130     .177    -5.922     .106   .151040   .473690   .0048440   -49.800    -6.000  
+ 1 426 52025.00 I   .153471  .000050   .472377  .000041  I  .0040681  .0000085  0.7267 0.0068  I   -50.319     .160    -6.143     .145   .153320   .472380   .0040670   -49.800    -6.000  
+ 1 427 52026.00 I   .155789  .000051   .471026  .000044  I  .0033913  .0000091  0.6227 0.0068  I   -50.514     .160    -6.178     .145   .155790   .470940   .0033730   -49.700    -6.100  
+ 1 428 52027.00 I   .157806  .000050   .469570  .000044  I  .0028082  .0000106  0.5622 0.0110  I   -50.740     .160    -6.152     .145   .157800   .469490   .0028290   -49.500    -6.100  
+ 1 429 52028.00 I   .159603  .000022   .467985  .000029  I  .0022319  .0000200  0.6068 0.0070  I   -50.776     .740    -6.154     .340   .159600   .467950   .0022510   -49.300    -6.200  
+ 1 430 52029.00 I   .161444  .000040   .466243  .000051  I  .0015624  .0000090  0.7479 0.0108  I   -50.478     .317    -6.198     .340   .161460   .466200   .0015540   -49.100    -6.100  
+ 1 5 1 52030.00 I   .163356  .000072   .464304  .000091  I  .0007169  .0000083  0.9465 0.0062  I   -49.916     .303    -6.223     .340   .163170   .464260   .0006960   -49.000    -6.200  
+ 1 5 2 52031.00 I   .164950  .000071   .462522  .000090  I -.0003369  .0000084  1.1639 0.0059  I   -49.361     .303    -6.169     .340   .164950   .462500  -.0003420   -49.000    -6.200  
+ 1 5 3 52032.00 I   .167277  .000072   .461283  .000090  I -.0016044  .0000083  1.3619 0.0056  I   -49.158     .335    -6.060     .103   .167170   .461160  -.0015850   -49.100    -6.100  
+ 1 5 4 52033.00 I   .169451  .000074   .460079  .000091  I -.0030462  .0000075  1.5163 0.0055  I   -49.369     .335    -5.928     .103   .169470   .460060  -.0030340   -49.400    -6.200  
+ 1 5 5 52034.00 I   .171731  .000074   .458504  .000091  I -.0046043  .0000071  1.5725 0.0053  I   -49.905     .335    -5.879     .103   .171710   .458490  -.0046170   -49.600    -6.200  
+ 1 5 6 52035.00 I   .173634  .000070   .456540  .000090  I -.0061441  .0000075  1.4874 0.0045  I   -50.461     .328    -5.930     .130   .173660   .456560  -.0061660   -49.800    -5.900  
+ 1 5 7 52036.00 I   .175770  .000036   .454417  .000040  I -.0075479  .0000055  1.3086 0.0051  I   -50.780     .740    -5.998     .103   .175750   .454430  -.0075520   -50.200    -5.900  
+ 1 5 8 52037.00 I   .178361  .000036   .452275  .000039  I -.0087514  .0000070  1.0999 0.0043  I   -50.827     .740    -6.001     .103   .178400   .452300  -.0087500   -50.400    -5.900  
+ 1 5 9 52038.00 I   .181152  .000037   .450055  .000041  I -.0097479  .0000067  0.8917 0.0047  I   -50.758     .740    -5.956     .103   .181190   .450110  -.0097520   -50.500    -6.100  
+ 1 510 52039.00 I   .183899  .000031   .447804  .000040  I -.0105429  .0000064  0.7078 0.0048  I   -50.800     .740    -5.985     .340   .183850   .447870  -.0105440   -50.400    -6.200  
+ 1 511 52040.00 I   .186558  .000031   .445713  .000041  I -.0111874  .0000068  0.5955 0.0057  I   -50.907     .740    -6.067     .340   .186520   .445780  -.0111840   -50.300    -6.300  
+ 1 512 52041.00 I   .189162  .000028   .444034  .000022  I -.0117606  .0000095  0.5633 0.0055  I   -51.016     .740    -6.164     .340   .189130   .444060  -.0117580   -50.000    -6.400  
+ 1 513 52042.00 I   .191399  .000066   .442523  .000038  I -.0123357  .0000086  0.5963 0.0061  I   -50.989     .740    -6.207     .340   .191380   .442540  -.0123210   -49.800    -6.400  
+ 1 514 52043.00 I   .193310  .000069   .440749  .000046  I -.0129715  .0000075  0.6841 0.0053  I   -50.779     .231    -6.214     .340   .193240   .440740  -.0129560   -49.600    -6.400  
+ 1 515 52044.00 I   .194797  .000077   .438595  .000063  I -.0137153  .0000062  0.8060 0.0048  I   -50.458     .268    -6.243     .113   .194970   .438620  -.0137180   -49.500    -6.300  
+ 1 516 52045.00 I   .196885  .000076   .436321  .000061  I -.0145805  .0000061  0.9189 0.0043  I   -50.181     .268    -6.288     .113   .196880   .436330  -.0145870   -49.500    -6.300  
+ 1 517 52046.00 I   .198612  .000076   .433526  .000061  I -.0155485  .0000061  1.0181 0.0040  I   -50.143     .269    -6.271     .114   .198680   .433650  -.0155280   -49.800    -6.100  
+ 1 518 52047.00 I   .200793  .000076   .430724  .000061  I -.0166117  .0000051  1.1022 0.0043  I   -50.403     .269    -6.182     .114   .200760   .430710  -.0166130   -50.200    -6.000  
+ 1 519 52048.00 I   .203161  .000053   .427891  .000058  I -.0177380  .0000061  1.1414 0.0038  I   -50.912     .324    -6.028     .134   .203180   .427890  -.0177410   -50.500    -5.900  
+ 1 520 52049.00 I   .205174  .000060   .425164  .000072  I -.0188736  .0000055  1.1179 0.0039  I   -51.429     .459    -5.874     .155   .205110   .425180  -.0188620   -50.900    -5.900  
+ 1 521 52050.00 I   .206955  .000057   .422557  .000053  I -.0199526  .0000049  1.0310 0.0037  I   -51.730     .417    -5.801     .104   .206910   .422590  -.0199380   -51.200    -5.900  
+ 1 522 52051.00 I   .208746  .000055   .420125  .000053  I -.0209135  .0000050  0.8779 0.0034  I   -51.794     .417    -5.870     .104   .208850   .420250  -.0209080   -51.400    -6.000  
+ 1 523 52052.00 I   .210426  .000056   .417989  .000061  I -.0216892  .0000048  0.6671 0.0035  I   -51.787     .389    -6.069     .111   .210410   .418040  -.0216940   -51.400    -6.100  
+ 1 524 52053.00 I   .212039  .000057   .415612  .000062  I -.0222479  .0000048  0.4568 0.0032  I   -51.841     .390    -6.275     .103   .211890   .415630  -.0222490   -51.300    -6.300  
+ 1 525 52054.00 I   .213256  .000058   .413088  .000063  I -.0226142  .0000042  0.2808 0.0030  I   -51.985     .390    -6.385     .103   .213350   .413120  -.0226100   -51.200    -6.400  
+ 1 526 52055.00 I   .214679  .000047   .410347  .000042  I -.0228347  .0000036  0.1805 0.0035  I   -52.084     .252    -6.357     .340   .214620   .410370  -.0228330   -50.900    -6.500  
+ 1 527 52056.00 I   .215942  .000032   .407372  .000047  I -.0230140  .0000056  0.1968 0.0032  I   -52.048     .298    -6.267     .114   .215880   .407350  -.0230120   -50.600    -6.500  
+ 1 528 52057.00 I   .217326  .000033   .404456  .000051  I -.0232574  .0000053  0.3006 0.0043  I   -51.860     .226    -6.203     .340   .217320   .404480  -.0232580   -50.500    -6.400  
+ 1 529 52058.00 I   .219019  .000037   .401751  .000063  I -.0236287  .0000065  0.4449 0.0041  I   -51.561     .333    -6.177     .117   .219030   .401800  -.0236350   -50.600    -6.300  
+ 1 530 52059.00 I   .220923  .000039   .399153  .000064  I -.0241428  .0000062  0.5758 0.0045  I   -51.251     .333    -6.150     .117   .220930   .399220  -.0241480   -50.900    -6.200  
+ 1 531 52060.00 I   .222844  .000037   .396603  .000062  I -.0247593  .0000062  0.6435 0.0043  I   -51.097     .331    -6.125     .340   .222860   .396660  -.0247580   -51.400    -6.000  
+ 1 6 1 52061.00 I   .224462  .000037   .394024  .000063  I -.0254085  .0000061  0.6472 0.0049  I   -51.244     .331    -6.036     .340   .224420   .394050  -.0253810   -52.000    -5.900  
+ 1 6 2 52062.00 I   .225856  .000043   .391301  .000067  I -.0260285  .0000075  0.5753 0.0047  I   -51.720     .331    -5.948     .340   .225790   .391340  -.0260010   -52.700    -5.800  
+ 1 6 3 52063.00 I   .227208  .000067   .388448  .000070  I -.0265294  .0000072  0.4143 0.0049  I   -52.338     .329    -5.884     .340   .227200   .388480  -.0265140   -53.100    -5.700  
+ 1 6 4 52064.00 I   .228755  .000066   .385506  .000065  I -.0268396  .0000062  0.2008 0.0050  I   -52.808     .154    -5.848     .340   .228700   .385520  -.0268270   -52.600    -5.600  
+ 1 6 5 52065.00 I   .230305  .000066   .382461  .000063  I -.0269233  .0000069 -0.0358 0.0047  I   -52.956     .154    -5.839     .340   .230520   .382550  -.0268950   -52.500    -5.700  
+ 1 6 6 52066.00 I   .232394  .000065   .379951  .000061  I -.0267701  .0000070 -0.2660 0.0050  I   -52.868     .154    -5.872     .340   .232380   .380060  -.0267660   -52.400    -5.800  
+ 1 6 7 52067.00 I   .234494  .000065   .377269  .000062  I -.0264129  .0000072 -0.4314 0.0045  I   -52.701     .175    -5.941     .340   .234400   .377400  -.0264180   -52.200    -6.100  
+ 1 6 8 52068.00 I   .236427  .000064   .374759  .000060  I -.0259398  .0000058 -0.4994 0.0049  I   -52.706     .175    -6.044     .340   .236450   .374730  -.0259510   -51.900    -6.400  
+ 1 6 9 52069.00 I   .238000  .000036   .372435  .000054  I -.0254444  .0000067 -0.4764 0.0048  I   -52.778     .211    -6.101     .340   .237980   .372450  -.0254460   -51.800    -6.600  
+ 1 610 52070.00 I   .239149  .000032   .370013  .000053  I -.0250118  .0000076 -0.3791 0.0043  I   -52.859     .194    -6.102     .108   .239120   .370100  -.0250090   -51.800    -6.700  
+ 1 611 52071.00 I   .240122  .000057   .367384  .000058  I -.0247004  .0000054 -0.2394 0.0049  I   -52.955     .130    -6.113     .155   .240140   .367450  -.0246970   -51.900    -6.800  
+ 1 612 52072.00 I   .241075  .000056   .364662  .000077  I -.0245354  .0000063 -0.0925 0.0046  I   -53.041     .159    -6.179     .154   .241010   .364630  -.0245310   -52.300    -6.700  
+ 1 613 52073.00 I   .241862  .000055   .361668  .000077  I -.0245107  .0000074  0.0404 0.0049  I   -53.044     .159    -6.245     .154   .241850   .361720  -.0245030   -52.700    -6.400  
+ 1 614 52074.00 I   .243205  .000058   .358359  .000078  I -.0245966  .0000074  0.1143 0.0053  I   -53.123     .135    -6.189     .172   .243170   .358550  -.0245960   -53.300    -6.200  
+ 1 615 52075.00 I   .244809  .000059   .355242  .000078  I -.0247260  .0000075  0.1481 0.0059  I   -53.318     .135    -6.073     .172   .244820   .355300  -.0247330   -53.700    -5.900  
+ 1 616 52076.00 I   .246266  .000086   .352304  .000074  I -.0248955  .0000093  0.1900 0.0064  I   -53.895     .132    -5.936     .196   .246230   .352330  -.0248900   -54.300    -5.700  
+ 1 617 52077.00 I   .247366  .000074   .349444  .000070  I -.0250968  .0000104  0.2043 0.0072  I   -54.637     .106    -5.811     .183   .247330   .349550  -.0250730   -54.600    -5.500  
+ 1 618 52078.00 I   .248189  .000080   .346490  .000067  I -.0252880  .0000111  0.1705 0.0069  I   -55.150     .280    -5.682     .128   .248170   .346560  -.0252650   -54.800    -5.400  
+ 1 619 52079.00 I   .248439  .000077   .343539  .000069  I -.0254205  .0000091  0.0850 0.0073  I   -55.314     .298    -5.593     .134   .248480   .343620  -.0254190   -54.900    -5.500  
+ 1 620 52080.00 I   .248322  .000073   .340726  .000069  I -.0254431  .0000094 -0.0451 0.0066  I   -55.352     .298    -5.648     .134   .248350   .340790  -.0254530   -54.900    -5.600  
+ 1 621 52081.00 I   .248209  .000073   .337798  .000069  I -.0253430  .0000096 -0.1369 0.0064  I   -55.457     .306    -5.813     .340   .248270   .337830  -.0253190   -54.800    -5.700  
+ 1 622 52082.00 I   .248422  .000039   .334848  .000063  I -.0251893  .0000086 -0.1686 0.0066  I   -55.519     .306    -6.047     .340   .248430   .334900  -.0252160   -54.500    -5.800  
+ 1 623 52083.00 I   .248662  .000040   .331828  .000064  I -.0250212  .0000092 -0.1540 0.0058  I   -55.387     .306    -6.118     .340   .248720   .331890  -.0249870   -54.400    -6.000  
+ 1 624 52084.00 I   .248931  .000042   .328775  .000072  I -.0249081  .0000078 -0.0592 0.0063  I   -55.131     .234    -6.019     .340   .248970   .328800  -.0248170   -54.300    -6.100  
+ 1 625 52085.00 I   .249514  .000047   .325692  .000079  I -.0249313  .0000085  0.1209 0.0056  I   -54.975     .134    -5.893     .340   .249480   .325730  -.0248560   -54.300    -6.100  
+ 1 626 52086.00 I   .250305  .000066   .322581  .000103  I -.0251681  .0000080  0.3557 0.0057  I   -55.024     .191    -5.851     .340   .250410   .322600  -.0251460   -54.600    -6.100  
+ 1 627 52087.00 I   .251263  .000065   .319736  .000103  I -.0256329  .0000077  0.5613 0.0054  I   -55.177     .191    -5.870     .340   .251270   .319770  -.0256330   -54.900    -6.000  
+ 1 628 52088.00 I   .252011  .000065   .317012  .000103  I -.0262455  .0000072  0.6315 0.0051  I   -55.395     .217    -5.880     .340   .251940   .316990  -.0262050   -55.500    -6.000  
+ 1 629 52089.00 I   .252360  .000066   .313934  .000104  I -.0268484  .0000066  0.5593 0.0053  I   -55.492     .217    -5.840     .340   .252380   .313920  -.0268050   -56.000    -5.900  
+ 1 630 52090.00 I   .252992  .000058   .310715  .000092  I -.0273415  .0000078  0.4193 0.0052  I   -55.700     .259    -5.779     .340   .252990   .310720  -.0273470   -56.400    -5.800  
+ 1 7 1 52091.00 I   .253731  .000063   .307575  .000087  I -.0276738  .0000081  0.2396 0.0058  I   -56.098     .425    -5.717     .340   .253780   .307610  -.0277010   -56.600    -5.700  
+ 1 7 2 52092.00 I   .253964  .000047   .304394  .000058  I -.0278178  .0000086  0.0511 0.0060  I   -56.574     .347    -5.664     .340   .253940   .304430  -.0278370   -56.600    -5.700  
+ 1 7 3 52093.00 I   .253753  .000046   .301145  .000057  I -.0277834  .0000088 -0.1151 0.0062  I   -56.892     .347    -5.662     .340   .253750   .301190  -.0277890   -56.300    -5.700  
+ 1 7 4 52094.00 I   .254215  .000045   .298188  .000056  I -.0276027  .0000088 -0.2358 0.0064  I   -56.929     .347    -5.763     .340  0.254090  0.298230 -0.0276160   -56.000    -5.800  
+ 1 7 5 52095.00 I   .254232  .000044   .295468  .000055  I -.0273324  .0000092 -0.2945 0.0065  I   -56.882     .421    -5.943     .340  0.254290  0.295550 -0.0273580   -56.900    -6.000  
+ 1 7 6 52096.00 I   .253911  .000046   .292761  .000059  I -.0270278  .0000095 -0.3110 0.0082  I   -56.746     .421    -6.098     .340  0.253890  0.292770 -0.0270370   -57.200    -6.100  
+ 1 7 7 52097.00 I   .253524  .000032   .290040  .000051  I -.0267282  .0000135 -0.2743 0.0061  I   -56.724     .740    -6.097     .340  0.253530  0.290050 -0.0267140   -57.300    -6.100  
+ 1 7 8 52098.00 I   .252708  .000038   .287256  .000034  I -.0264986  .0000075 -0.1795 0.0078  I   -56.847     .740    -5.961     .340  0.252700  0.287310 -0.0264760   -57.300    -6.000  
+ 1 7 9 52099.00 I   .251813  .000041   .284150  .000049  I -.0263669  .0000079 -0.0917 0.0050  I   -57.119     .195    -5.844     .127  0.251720  0.284140 -0.0263590   -57.300    -6.000  
+ 1 710 52100.00 I   .251686  .000041   .280793  .000052  I -.0263067  .0000067 -0.0296 0.0051  I   -57.433     .365    -5.847     .101  0.251690  0.280760 -0.0263210   -57.300    -6.000  
+ 1 711 52101.00 I   .251944  .000042   .277620  .000052  I -.0263047  .0000066  0.0234 0.0046  I   -57.574     .365    -5.891     .101  0.251980  0.277670 -0.0263080   -57.300    -5.900  
+ 1 712 52102.00 I   .251507  .000041   .274653  .000050  I -.0263530  .0000064  0.0747 0.0042  I   -57.562     .303    -5.843     .104  0.251470  0.274620 -0.0263440   -57.600    -5.900  
+ 1 713 52103.00 I   .250977  .000042   .271726  .000050  I -.0264534  .0000051  0.1238 0.0045  I   -57.597     .303    -5.707     .104  0.250880  0.271650 -0.0264360   -58.100    -5.800  
+ 1 714 52104.00 I   .250420  .000038   .268800  .000055  I -.0265857  .0000062  0.1281 0.0039  I   -58.082     .303    -5.628     .104  0.250360  0.268790 -0.0265840   -58.500    -5.800  
+ 1 715 52105.00 I   .249489  .000041   .265680  .000041  I -.0266888  .0000060  0.0699 0.0053  I   -58.901     .440    -5.654     .340  0.249470  0.265690 -0.0266870   -59.000    -5.900  
+ 1 716 52106.00 I   .248487  .000054   .262337  .000040  I -.0267108  .0000086 -0.0323 0.0048  I   -59.563     .317    -5.671     .340  0.248500  0.262310 -0.0266970   -59.300    -5.800  
+ 1 717 52107.00 I   .248045  .000064   .259044  .000056  I -.0266166  .0000074 -0.1572 0.0056  I   -59.795     .317    -5.608     .340  0.248020  0.259030 -0.0265990   -59.400    -5.700  
+ 1 718 52108.00 I   .247899  .000062   .255898  .000054  I -.0263879  .0000073 -0.3075 0.0052  I   -59.785     .317    -5.582     .340  0.247930  0.255930 -0.0263840   -59.300    -5.600  
+ 1 719 52109.00 I   .247886  .000061   .252693  .000054  I -.0260054  .0000073 -0.4463 0.0052  I   -59.727     .264    -5.746     .340  0.247880  0.252780 -0.0260360   -58.700    -5.500  
+ 1 720 52110.00 I   .247644  .000062   .249621  .000055  I -.0255194  .0000073 -0.5128 0.0049  I   -59.684     .264    -5.995     .340  0.247620  0.249630 -0.0255320   -58.100    -5.400  
+ 1 721 52111.00 I   .247124  .000055   .246549  .000058  I -.0250172  .0000066 -0.4672 0.0051  I   -59.436     .264    -6.113     .340  0.247110  0.246510 -0.0250070   -57.700    -5.400  
+ 1 722 52112.00 I   .246308  .000062   .243497  .000077  I -.0246244  .0000072 -0.3034 0.0066  I   -59.081     .417    -6.020     .138  0.246310  0.243480 -0.0245960   -57.500    -5.500  
+ 1 723 52113.00 I   .245303  .000050   .240604  .000071  I -.0244283  .0000115 -0.0859 0.0062  I   -58.929     .293    -5.875     .340  0.245290  0.240600 -0.0243980   -57.800    -5.500  
+ 1 724 52114.00 I   .244181  .000052   .237844  .000067  I -.0244490  .0000100  0.1207 0.0080  I   -59.145     .329    -5.833     .112  0.244230  0.237850 -0.0244370   -58.400    -5.700  
+ 1 725 52115.00 I   .243624  .000051   .235369  .000063  I -.0246366  .0000110  0.2279 0.0074  I   -59.594     .329    -5.858     .112  0.243550  0.235400 -0.0246340   -59.500    -5.900  
+ 1 726 52116.00 I   .242989  .000051   .232644  .000063  I -.0248666  .0000110  0.2204 0.0078  I   -60.059     .330    -5.815     .114  0.242970  0.232700 -0.0248580   -60.200    -6.000  
+ 1 727 52117.00 I   .242022  .000050   .229827  .000063  I -.0250474  .0000111  0.1229 0.0077  I   -60.239     .330    -5.745     .114  0.242000  0.229780 -0.0250340   -60.800    -6.100  
+ 1 728 52118.00 I   .240668  .000027   .226879  .000040  I -.0250822  .0000109 -0.0650 0.0077  I   -60.241     .230    -5.735     .113  0.240630  0.226830 -0.0250700   -61.100    -6.100  
+ 1 729 52119.00 I   .239018  .000029   .223779  .000041  I -.0249085  .0000107 -0.2794 0.0072  I   -60.276     .335    -5.819     .172  0.239010  0.223820 -0.0249070   -61.200    -6.000  
+ 1 730 52120.00 I   .237308  .000022   .220720  .000104  I -.0245315  .0000094 -0.4693 0.0060  I   -60.493     .414    -5.916     .340  0.237300  0.220680 -0.0245330   -61.000    -6.100  
+ 1 731 52121.00 I   .235872  .000045   .217961  .000107  I -.0239862  .0000053 -0.6102 0.0056  I   -60.798     .414    -5.972     .340  0.235850  0.217860 -0.0239860   -60.700    -6.100  
+ 1 8 1 52122.00 I   .234708  .000045   .215461  .000111  I -.0233285  .0000060 -0.6990 0.0040  I   -60.947     .414    -6.043     .340  0.234740  0.215420 -0.0233300   -60.300    -6.000  
+ 1 8 2 52123.00 I   .233413  .000045   .213496  .000111  I -.0226143  .0000060 -0.7095 0.0042  I   -60.854     .432    -6.157     .340  0.233290  0.213440 -0.0226280   -60.000    -6.100  
+ 1 8 3 52124.00 I   .230934  .000046   .211330  .000113  I -.0219419  .0000058 -0.6228 0.0042  I   -60.604     .415    -6.249     .340  0.230970  0.211380 -0.0219510   -59.900    -6.000  
+ 1 8 4 52125.00 I   .228252  .000047   .208668  .000113  I -.0213853  .0000059 -0.4862 0.0040  I   -60.455     .415    -6.162     .340  0.228190  0.208600 -0.0213740   -59.700    -5.900  
+ 1 8 5 52126.00 I   .225848  .000061   .205783  .000079  I -.0209760  .0000054 -0.3301 0.0050  I   -60.486     .151    -5.890     .340  0.225820  0.205680 -0.0209610   -59.700    -5.700  
+ 1 8 6 52127.00 I   .223854  .000045   .203137  .000065  I -.0207247  .0000080 -0.1752 0.0045  I   -60.672     .252    -5.623     .340  0.223840  0.203130 -0.0207250   -59.900    -5.700  
+ 1 8 7 52128.00 I   .221846  .000052   .200695  .000087  I -.0206206  .0000073 -0.0354 0.0057  I   -60.888     .234    -5.527     .340  0.221850  0.200830 -0.0206260   -60.000    -5.600  
+ 1 8 8 52129.00 I   .219641  .000050   .198602  .000082  I -.0206566  .0000081  0.1125 0.0055  I   -60.949     .234    -5.555     .340  0.219630  0.198630 -0.0206580   -60.300    -5.600  
+ 1 8 9 52130.00 I   .217156  .000050   .196301  .000081  I -.0208393  .0000082  0.2417 0.0057  I   -60.873     .149    -5.546     .340  0.217110  0.196290 -0.0208430   -60.600    -5.600  
+ 1 810 52131.00 I   .214270  .000052   .194048  .000082  I -.0211293  .0000079  0.3390 0.0061  I   -60.766     .149    -5.456     .340  0.214300  0.194010 -0.0211170   -60.900    -5.700  
+ 1 811 52132.00 I   .211292  .000038   .191558  .000079  I -.0214996  .0000089  0.3834 0.0058  I   -61.056     .175    -5.438     .340  0.211260  0.191530 -0.0215140   -61.300    -5.700  
+ 1 812 52133.00 I   .208443  .000041   .188809  .000082  I -.0218695  .0000086  0.3482 0.0053  I   -61.739     .114    -5.583     .340  0.208400  0.188780 -0.0219090   -61.600    -5.800  
+ 1 813 52134.00 I   .205986  .000044   .186155  .000048  I -.0221796  .0000059  0.2638 0.0048  I   -62.391     .185    -5.769     .340  0.206010  0.186150 -0.0222080   -61.900    -5.800  
+ 1 814 52135.00 I   .203661  .000076   .183652  .000046  I -.0223872  .0000042  0.1497 0.0036  I   -62.647     .185    -5.835     .340  0.203770  0.183640 -0.0223950   -62.000    -5.900  
+ 1 815 52136.00 I   .201030  .000075   .181204  .000047  I -.0224832  .0000042  0.0482 0.0030  I   -62.552     .185    -5.807     .340  0.201050  0.181170 -0.0224850   -62.000    -5.900  
+ 1 816 52137.00 I   .198726  .000076   .178978  .000052  I -.0225064  .0000042  0.0151 0.0030  I   -62.292     .173    -5.825     .340  0.198400  0.178940 -0.0225100   -62.000    -5.900  
+ 1 817 52138.00 I   .195935  .000076   .176831  .000047  I -.0225537  .0000044  0.1029 0.0033  I   -62.068     .173    -5.896     .340  0.196010  0.176810 -0.0225520   -61.800    -5.800  
+ 1 818 52139.00 I   .193417  .000076   .174597  .000045  I -.0227462  .0000050  0.2926 0.0029  I   -61.794     .172    -5.859     .340  0.193410  0.174570 -0.0227320   -61.700    -5.700  
+ 1 819 52140.00 I   .190985  .000121   .172340  .000074  I -.0231581  .0000037  0.5398 0.0032  I   -61.555     .740    -5.665     .340  0.190970  0.172310 -0.0231440   -61.600    -5.700  
+ 1 820 52141.00 I   .188799  .000103   .170234  .000072  I -.0238223  .0000041  0.7765 0.0031  I   -61.531     .219    -5.490     .340  0.188770  0.170270 -0.0238140   -61.700    -5.600  
+ 1 821 52142.00 I   .186205  .000098   .168172  .000069  I -.0246828  .0000050  0.9284 0.0033  I   -61.781     .318    -5.490     .340  0.186480  0.168150 -0.0246870   -62.000    -5.500  
+ 1 822 52143.00 I   .183852  .000096   .165911  .000064  I -.0256448  .0000051  0.9776 0.0035  I   -62.198     .318    -5.571     .340  0.183820  0.165890 -0.0256510   -62.300    -5.500  
+ 1 823 52144.00 I   .181210  .000098   .163907  .000064  I -.0265834  .0000049  0.8630 0.0034  I   -62.590     .233    -5.547     .340  0.181090  0.163910 -0.0265740   -62.800    -5.500  
+ 1 824 52145.00 I   .178677  .000099   .162045  .000065  I -.0273417  .0000045  0.6609 0.0040  I   -62.832     .233    -5.426     .340  0.178690  0.162090 -0.0273220   -63.200    -5.500  
+ 1 825 52146.00 I   .176475  .000040   .160131  .000038  I -.0278971  .0000064  0.4344 0.0045  I   -62.813     .233    -5.430     .340  0.176480  0.160180 -0.0279020   -63.600    -5.600  
+ 1 826 52147.00 I   .174361  .000038   .158092  .000099  I -.0282024  .0000077  0.1835 0.0048  I   -62.640     .213    -5.661     .340  0.174360  0.158120 -0.0282170   -63.700    -5.700  
+ 1 827 52148.00 I   .172421  .000039   .156000  .000101  I -.0282814  .0000072 -0.0154 0.0051  I   -62.562     .740    -5.953     .340  0.172380  0.156010 -0.0282800   -63.600    -5.800  
+ 1 828 52149.00 I   .170433  .000045   .153890  .000104  I -.0281922  .0000068 -0.1524 0.0050  I   -62.687     .740    -6.089     .340  0.170520  0.154080 -0.0281840   -63.300    -5.900  
+ 1 829 52150.00 I   .168322  .000042   .152401  .000102  I -.0279987  .0000070 -0.2230 0.0049  I   -62.825     .740    -6.058     .340  0.168310  0.152450 -0.0280010   -62.800    -6.000  
+ 1 830 52151.00 I   .166083  .000041   .150982  .000102  I -.0277811  .0000070 -0.1888 0.0048  I   -62.747     .740    -5.994     .340  0.165940  0.151010 -0.0277760   -62.300    -5.900  
+ 1 831 52152.00 I   .163282  .000042   .149983  .000105  I -.0276358  .0000066 -0.1106 0.0050  I   -62.479     .740    -5.946     .340  0.163320  0.150020 -0.0276410   -61.900    -5.800  
+ 1 9 1 52153.00 I   .160290  .000042   .149077  .000087  I -.0275677  .0000072 -0.0092 0.0055  I   -62.233     .525    -5.817     .123  0.160240  0.149120 -0.0275220   -61.500    -5.800  
+ 1 9 2 52154.00 I   .157071  .000044   .147756  .000091  I -.0276349  .0000089  0.1446 0.0062  I   -62.123     .772    -5.551     .180  0.157030  0.147790 -0.0275400   -61.300    -5.500  
+ 1 9 3 52155.00 I   .153925  .000051   .146230  .000078  I -.0278569  .0000101  0.2984 0.0063  I   -62.097     .537    -5.258     .116  0.153930  0.146230 -0.0278290   -61.700    -4.700  
+ 1 9 4 52156.00 I   .150804  .000061   .144646  .000078  I -.0282213  .0000089  0.4210 0.0066  I   -62.065     .446    -5.105     .113  0.150800  0.144700 -0.0282350   -61.800    -4.900  
+ 1 9 5 52157.00 I   .147452  .000061   .142777  .000078  I -.0286907  .0000086  0.5191 0.0062  I   -61.974     .446    -5.114     .113  0.147470  0.142820 -0.0286930   -61.800    -5.100  
+ 1 9 6 52158.00 I   .144611  .000061   .140770  .000079  I -.0292332  .0000086  0.5383 0.0056  I   -61.811     .438    -5.156     .110  0.144570  0.140680 -0.0292230   -61.700    -5.100  
+ 1 9 7 52159.00 I   .141812  .000057   .139100  .000041  I -.0297340  .0000071  0.4575 0.0055  I   -61.701     .127    -5.158     .340  0.141940  0.139040 -0.0296950   -61.500    -5.000  
+ 1 9 8 52160.00 I   .139469  .000054   .137762  .000045  I -.0301363  .0000067  0.3410 0.0059  I   -61.821     .127    -5.181     .340  0.139480  0.137780 -0.0301450   -61.400    -4.900  
+ 1 9 9 52161.00 I   .137173  .000049   .136680  .000079  I -.0304103  .0000093  0.2075 0.0060  I   -62.223     .247    -5.312     .110  0.137220  0.136710 -0.0304570   -61.500    -5.000  
+ 1 910 52162.00 I   .134793  .000057   .135598  .000084  I -.0305519  .0000099  0.0759 0.0068  I   -62.691     .427    -5.504     .130  0.134820  0.135600 -0.0305810   -61.600    -5.200  
+ 1 911 52163.00 I   .131937  .000083   .134534  .000088  I -.0305697  .0000099 -0.0328 0.0070  I   -62.921     .359    -5.625     .119  0.132050  0.134440 -0.0305690   -61.800    -5.400  
+ 1 912 52164.00 I   .128799  .000081   .133191  .000085  I -.0305005  .0000100 -0.0989 0.0070  I   -62.802     .359    -5.617     .119  0.128800  0.133200 -0.0304980   -61.900    -5.600  
+ 1 913 52165.00 I   .125569  .000081   .132151  .000083  I -.0304014  .0000100 -0.0765 0.0071  I   -62.508     .376    -5.557     .112  0.125660  0.132030 -0.0304240   -61.800    -5.700  
+ 1 914 52166.00 I   .122462  .000082   .130991  .000082  I -.0303880  .0000101  0.0674 0.0070  I   -62.083     .376    -5.391     .112  0.122490  0.130970 -0.0304260   -61.700    -5.700  
+ 1 915 52167.00 I   .118823  .000083   .129921  .000062  I -.0305704  .0000099  0.3140 0.0070  I   -61.758     .419    -5.100     .340  0.118860  0.129900 -0.0305830   -61.600    -5.500  
+ 1 916 52168.00 I   .115134  .000073   .129008  .000051  I -.0310339  .0000098  0.6144 0.0063  I   -61.672     .740    -4.738     .340  0.115160  0.129020 -0.0310310   -61.700    -5.400  
+ 1 917 52169.00 I   .111702  .000050   .128161  .000040  I -.0317828  .0000077  0.8655 0.0055  I   -61.835     .193    -4.519     .134  0.111710  0.128160 -0.0317820   -61.700    -5.200  
+ 1 918 52170.00 I   .108312  .000050   .127305  .000041  I -.0327193  .0000051  0.9797 0.0047  I   -62.089     .181    -4.590     .188  0.108320  0.127300 -0.0327230   -62.000    -5.100  
+ 1 919 52171.00 I   .104560  .000049   .126560  .000041  I -.0336945  .0000055  0.9507 0.0037  I   -62.278     .181    -4.809     .188  0.104560  0.126580 -0.0336970   -62.300    -5.000  
+ 1 920 52172.00 I   .101202  .000049   .125935  .000041  I -.0345894  .0000054  0.8276 0.0038  I   -62.399     .181    -4.899     .188  0.101130  0.125960 -0.0345850   -62.500    -4.900  
+ 1 921 52173.00 I   .097832  .000051   .125409  .000046  I -.0353300  .0000052  0.6454 0.0052  I   -62.485     .181    -4.809     .188  0.097880  0.125390 -0.0353410   -62.700    -4.900  
+ 1 922 52174.00 I   .094515  .000052   .124864  .000045  I -.0358762  .0000088  0.4514 0.0061  I   -62.467     .181    -4.784     .188  0.094530  0.124880 -0.0358710   -62.800    -5.000  
+ 1 923 52175.00 I   .091429  .000052   .124165  .000040  I -.0362401  .0000111  0.2794 0.0077  I   -62.293     .196    -5.012     .204  0.091460  0.124210 -0.0362300   -62.700    -5.000  
+ 1 924 52176.00 I   .088536  .000068   .123182  .000073  I -.0364427  .0000127  0.1304 0.0074  I   -62.084     .158    -5.354     .226  0.088580  0.123200 -0.0364470   -62.500    -5.200  
+ 1 925 52177.00 I   .085411  .000069   .122051  .000100  I -.0365260  .0000097  0.0565 0.0080  I   -61.995     .196    -5.511     .194  0.085470  0.122040 -0.0365380   -62.100    -5.400  
+ 1 926 52178.00 I   .082376  .000068   .120940  .000099  I -.0365832  .0000097  0.0649 0.0069  I   -61.970     .196    -5.388     .194  0.082290  0.120950 -0.0365820   -61.800    -5.500  
+ 1 927 52179.00 I   .078852  .000069   .119978  .000099  I -.0366762  .0000098  0.1343 0.0063  I   -61.826     .196    -5.158     .194  0.078960  0.119830 -0.0366910   -61.300    -5.600  
+ 1 928 52180.00 I   .075375  .000070   .119070  .000101  I -.0368739  .0000079  0.2699 0.0059  I   -61.540     .196    -5.002     .194  0.075340  0.118980 -0.0368680   -60.900    -5.400  
+ 1 929 52181.00 I   .071799  .000055   .118503  .000103  I -.0372183  .0000067  0.4125 0.0047  I   -61.327     .235    -4.868     .238  0.071810  0.118500 -0.0372090   -60.500    -5.300  
+ 1 930 52182.00 I   .068626  .000038   .118099  .000091  I -.0376932  .0000052  0.5382 0.0045  I   -61.159     .229    -4.730     .155  0.068640  0.118080 -0.0376640   -60.200    -5.100  
+ 110 1 52183.00 I   .065428  .000028   .117780  .000066  I -.0382971  .0000061  0.6713 0.0038  I   -61.020     .193    -4.515     .234  0.065420  0.117780 -0.0382510   -60.200    -4.800  
+ 110 2 52184.00 I   .061701  .000034   .117636  .000064  I -.0390380  .0000055  0.8111 0.0043  I   -60.852     .164    -4.319     .200  0.061680  0.117630 -0.0390180   -60.200    -4.600  
+ 110 3 52185.00 I   .057927  .000034   .117397  .000065  I -.0398955  .0000061  0.8794 0.0041  I   -60.708     .164    -4.243     .200  0.057890  0.117430 -0.0399000   -60.400    -4.400  
+ 110 4 52186.00 I   .054765  .000032   .117299  .000064  I -.0407777  .0000060  0.8904 0.0041  I   -60.638     .164    -4.286     .200  0.054770  0.117230 -0.0407620   -60.300    -4.300  
+ 110 5 52187.00 I   .052007  .000031   .117381  .000064  I -.0416711  .0000056  0.8858 0.0043  I   -60.609     .164    -4.376     .200  0.052010  0.117390 -0.0416520   -60.200    -4.300  
+ 110 6 52188.00 I   .048970  .000030   .117600  .000061  I -.0425184  .0000063  0.7883 0.0048  I   -60.594     .173    -4.416     .233  0.049030  0.117650 -0.0425430   -60.100    -4.300  
+ 110 7 52189.00 I   .045981  .000030   .117726  .000036  I -.0432326  .0000077  0.6454 0.0053  I   -60.665     .740    -4.487     .116  0.045990  0.117750 -0.0432790   -60.100    -4.400  
+ 110 8 52190.00 I   .043041  .000044   .117743  .000038  I -.0438207  .0000086  0.5370 0.0066  I   -60.806     .139    -4.557     .177  0.043020  0.117720 -0.0438420   -60.200    -4.500  
+ 110 9 52191.00 I   .039838  .000051   .117721  .000033  I -.0443233  .0000106  0.4788 0.0067  I   -60.881     .172    -4.608     .238  0.039870  0.117720 -0.0443200   -60.300    -4.500  
+ 11010 52192.00 I   .036029  .000043   .117573  .000037  I -.0448060  .0000104  0.5037 0.0075  I   -60.725     .172    -4.602     .238  0.036070  0.117610 -0.0447990   -60.500    -4.400  
+ 11011 52193.00 I   .031916  .000043   .117281  .000037  I -.0453585  .0000105  0.6119 0.0073  I   -60.301     .172    -4.494     .238  0.031890  0.117280 -0.0453630   -60.700    -4.100  
+ 11012 52194.00 I   .027453  .000044   .117238  .000040  I -.0460502  .0000102  0.7812 0.0074  I   -59.763     .172    -4.243     .238  0.027530  0.117290 -0.0460900   -60.700    -3.700  
+ 11013 52195.00 I   .023095  .000044   .117487  .000041  I -.0469466  .0000103  1.0276 0.0101  I   -59.434     .158    -3.774     .178  0.023160  0.117520 -0.0469310   -60.800    -3.200  
+ 11014 52196.00 I   .019346  .000048   .117756  .000045  I -.0481163  .0000174  1.3066 0.0067  I   -59.428     .161    -3.358     .168  0.019360  0.117720 -0.0480670   -60.700    -2.900  
+ 11015 52197.00 I   .015946  .000043   .118233  .000049  I -.0495361  .0000087  1.5143 0.0097  I   -59.739     .256    -3.137     .340  0.015960  0.118200 -0.0495160   -60.700    -2.900  
+ 11016 52198.00 I   .012831  .000046   .118897  .000053  I -.0511037  .0000084  1.5982 0.0059  I   -60.061     .214    -3.245     .222  0.012800  0.118850 -0.0511100   -60.500    -3.100  
+ 11017 52199.00 I   .009771  .000047   .119369  .000051  I -.0526870  .0000081  1.5455 0.0060  I   -60.138     .230    -3.553     .197  0.009780  0.119370 -0.0526840   -60.300    -3.600  
+ 11018 52200.00 I   .006624  .000051   .119915  .000054  I -.0541499  .0000087  1.3586 0.0060  I   -59.996     .230    -3.771     .197  0.006640  0.119920 -0.0541550   -60.100    -4.100  
+ 11019 52201.00 I   .003117  .000053   .120419  .000059  I -.0553755  .0000088  1.0858 0.0061  I   -59.832     .230    -3.767     .197  0.003130  0.120460 -0.0553510   -59.800    -4.500  
+ 11020 52202.00 I  -.000633  .000044   .121004  .000056  I -.0563214  .0000086  0.8128 0.0056  I   -59.724     .248    -3.718     .211 -0.000630  0.121030 -0.0563460   -59.700    -4.900  
+ 11021 52203.00 I  -.004548  .000066   .121787  .000067  I -.0570287  .0000070  0.6226 0.0053  I   -59.583     .218    -3.803     .208 -0.004550  0.121810 -0.0571110   -59.400    -5.000  
+ 11022 52204.00 I  -.008592  .000064   .122717  .000064  I -.0575979  .0000061  0.5264 0.0045  I   -59.362     .265    -3.998     .340 -0.008610  0.122720 -0.0576820   -59.200    -4.700  
+ 11023 52205.00 I  -.012764  .000089   .123691  .000066  I -.0581052  .0000056  0.5014 0.0039  I   -59.119     .217    -4.072     .340 -0.012680  0.123650 -0.0581450   -58.900    -4.400  
+ 11024 52206.00 I  -.016471  .000091   .124646  .000067  I -.0586147  .0000050  0.5183 0.0037  I   -58.891     .217    -3.907     .340 -0.016540  0.124620 -0.0586110   -58.500    -4.000  
+ 11025 52207.00 I  -.020057  .000088   .125720  .000060  I -.0591595  .0000048  0.5882 0.0032  I   -58.646     .217    -3.644     .340 -0.020140  0.125640 -0.0591720   -57.900    -3.700  
+ 11026 52208.00 I  -.023592  .000090   .126873  .000061  I -.0598171  .0000039  0.7361 0.0048  I   -58.399     .217    -3.492     .340 -0.023560  0.126840 -0.0598170   -57.300    -3.400  
+ 11027 52209.00 I  -.027016  .000080   .128062  .000050  I -.0606384  .0000083  0.9041 0.0036  I   -58.233     .199    -3.479     .340 -0.027010  0.128060 -0.0606310   -56.900    -3.300  
+ 11028 52210.00 I  -.030363  .000080   .129127  .000046  I -.0616118  .0000060  1.0317 0.0050  I   -58.165     .740    -3.457     .340 -0.030400  0.129080 -0.0616080   -56.600    -3.200  
+ 11029 52211.00 I  -.033489  .000047   .130207  .000045  I -.0626844  .0000056  1.1070 0.0041  I   -58.113     .127    -3.292     .209 -0.033430  0.130180 -0.0626800   -56.600    -3.200  
+ 11030 52212.00 I  -.036312  .000041   .131409  .000056  I -.0638054  .0000056  1.1210 0.0040  I   -58.035     .250    -3.013     .182 -0.036440  0.131310 -0.0637910   -56.900    -3.100  
+ 11031 52213.00 I  -.039723  .000040   .132495  .000054  I -.0649117  .0000057  1.0909 0.0040  I   -57.997     .250    -2.778     .182 -0.039670  0.132430 -0.0649050   -57.500    -3.000  
+ 111 1 52214.00 I  -.042998  .000039   .133687  .000053  I -.0659738  .0000056  1.0205 0.0035  I   -58.039     .250    -2.727     .182 -0.043040  0.133660 -0.0659630   -58.000    -2.800  
+ 111 2 52215.00 I  -.046638  .000037   .134773  .000054  I -.0669227  .0000041  0.8600 0.0040  I   -58.071     .250    -2.858     .182 -0.046640  0.134770 -0.0669370   -58.300    -2.900  
+ 111 3 52216.00 I  -.050417  .000025   .135809  .000053  I -.0676901  .0000057  0.6885 0.0036  I   -58.075     .223    -2.983     .238 -0.050340  0.135800 -0.0676910   -58.300    -2.900  
+ 111 4 52217.00 I  -.053930  .000091   .136813  .000047  I -.0683200  .0000060  0.5779 0.0039  I   -57.894     .173    -3.079     .149 -0.053880  0.136820 -0.0683050   -58.000    -3.000  
+ 111 5 52218.00 I  -.056874  .000095   .137877  .000043  I -.0688598  .0000053  0.5092 0.0042  I   -57.726     .277    -3.062     .340 -0.056890  0.137870 -0.0688520   -57.500    -3.100  
+ 111 6 52219.00 I  -.059567  .000094   .139242  .000055  I -.0693496  .0000058  0.4743 0.0038  I   -57.586     .256    -3.002     .116 -0.059350  0.139300 -0.0693540   -57.100    -3.100  
+ 111 7 52220.00 I  -.061636  .000095   .140902  .000054  I -.0698298  .0000055  0.5037 0.0038  I   -57.366     .256    -2.957     .116 -0.061630  0.140970 -0.0698350   -56.700    -3.000  
+ 111 8 52221.00 I  -.063465  .000094   .142802  .000059  I -.0704038  .0000050  0.6735 0.0037  I   -56.978     .256    -2.896     .116 -0.063600  0.142770 -0.0703970   -56.700    -2.700  
+ 111 9 52222.00 I  -.065483  .000095   .144986  .000060  I -.0712220  .0000050  0.9788 0.0038  I   -56.506     .256    -2.745     .116 -0.065480  0.145000 -0.0712120   -56.600    -2.300  
+ 11110 52223.00 I  -.067793  .000044   .147468  .000062  I -.0723560  .0000058  1.2679 0.0045  I   -56.183     .313    -2.422     .340 -0.067800  0.147470 -0.0723670   -56.400    -1.800  
+ 11111 52224.00 I  -.069810  .000044   .149958  .000070  I -.0737262  .0000076  1.4620 0.0040  I   -56.234     .305    -2.145     .340 -0.069820  0.149910 -0.0737430   -56.400    -1.500  
+ 11112 52225.00 I  -.071468  .000046   .152519  .000070  I -.0752515  .0000054  1.5704 0.0046  I   -56.621     .260    -1.998     .340 -0.071500  0.152520 -0.0752510   -56.400    -1.400  
+ 11113 52226.00 I  -.073350  .000062   .155089  .000081  I -.0768355  .0000051  1.5841 0.0037  I   -57.063     .246    -2.076     .340 -0.073310  0.155070 -0.0768330   -56.600    -1.700  
+ 11114 52227.00 I  -.075332  .000063   .157245  .000076  I -.0783711  .0000051  1.4520 0.0036  I   -57.250     .244    -2.311     .340 -0.075350  0.157260 -0.0783700   -56.800    -2.400  
+ 11115 52228.00 I  -.077750  .000063   .159099  .000076  I -.0796914  .0000050  1.1755 0.0035  I   -57.138     .244    -2.507     .340 -0.077860  0.159060 -0.0796860   -57.000    -2.600  
+ 11116 52229.00 I  -.080457  .000063   .160740  .000077  I -.0807265  .0000048  0.9122 0.0033  I   -56.888     .244    -2.540     .340 -0.080460  0.160730 -0.0807140   -56.900    -2.600  
+ 11117 52230.00 I  -.082630  .000055   .162556  .000067  I -.0815412  .0000042  0.7253 0.0035  I   -56.701     .132    -2.458     .340 -0.082630  0.162600 -0.0815400   -56.700    -2.700  
+ 11118 52231.00 I  -.084537  .000051   .164432  .000057  I -.0821981  .0000051  0.6015 0.0032  I   -56.544     .182    -2.428     .340 -0.084550  0.164490 -0.0822050   -56.500    -2.500  
+ 11119 52232.00 I  -.086599  .000052   .166367  .000063  I -.0827684  .0000048  0.5503 0.0036  I   -56.355     .740    -2.463     .340 -0.086610  0.166400 -0.0827700   -56.200    -2.500  
+ 11120 52233.00 I  -.088961  .000053   .168447  .000064  I -.0833152  .0000050  0.5485 0.0037  I   -56.088     .740    -2.443     .340 -0.088970  0.168490 -0.0833120   -55.900    -2.400  
+ 11121 52234.00 I  -.091666  .000051   .170548  .000062  I -.0838756  .0000057  0.5773 0.0038  I   -55.798     .740    -2.295     .340 -0.091650  0.170580 -0.0838760   -55.700    -2.300  
+ 11122 52235.00 I  -.094439  .000051   .172912  .000061  I -.0844874  .0000056  0.6589 0.0042  I   -55.576     .740    -2.119     .340 -0.094470  0.172930 -0.0844770   -55.400    -2.200  
+ 11123 52236.00 I  -.097417  .000053   .175528  .000066  I -.0852001  .0000061  0.7607 0.0039  I   -55.477     .740    -2.063     .340 -0.097430  0.175550 -0.0851540   -55.200    -1.800  
+ 11124 52237.00 I  -.100610  .000055   .178082  .000068  I -.0860027  .0000053  0.8441 0.0071  I   -55.480     .740    -2.121     .340 -0.100640  0.178070 -0.0859420   -55.100    -1.600  
+ 11125 52238.00 I  -.103621  .000023   .180536  .000046  I -.0868873  .0000128  0.9244 0.0041  I   -55.538     .740    -2.153     .340 -0.103680  0.180540 -0.0868450   -55.200    -1.500  
+ 11126 52239.00 I  -.106097  .000038   .183056  .000084  I -.0878437  .0000062  0.9813 0.0067  I   -55.601     .740    -1.994     .340 -0.106080  0.183040 -0.0878340   -55.300    -1.300  
+ 11127 52240.00 I  -.108161  .000040   .185529  .000085  I -.0888340  .0000040  0.9906 0.0037  I   -55.682     .308    -1.653     .340 -0.108120  0.185520 -0.0888440   -55.500    -1.300  
+ 11128 52241.00 I  -.110184  .000043   .187897  .000086  I -.0898046  .0000042  0.9389 0.0029  I   -55.807     .308    -1.298     .340 -0.110230  0.187940 -0.0898050   -55.600    -1.300  
+ 11129 52242.00 I  -.112626  .000044   .190242  .000084  I -.0906958  .0000041  0.8391 0.0029  I   -55.944     .308    -1.132     .340 -0.112570  0.190300 -0.0906720   -55.700    -1.400  
+ 11130 52243.00 I  -.115319  .000046   .192771  .000084  I -.0914748  .0000041  0.7155 0.0030  I   -56.001     .308    -1.236     .340 -0.115330  0.192810 -0.0914570   -55.600    -1.600  
+ 112 1 52244.00 I  -.118472  .000051   .195444  .000084  I -.0921087  .0000043  0.5378 0.0025  I   -55.854     .344    -1.497     .340 -0.118480  0.195510 -0.0921210   -55.400    -1.800  
+ 112 2 52245.00 I  -.121686  .000100   .197956  .000057  I -.0925504  .0000027  0.3601 0.0024  I   -55.603     .505    -1.723     .340 -0.121680  0.198010 -0.0925740   -55.000    -1.800  
+ 112 3 52246.00 I  -.124538  .000107   .200158  .000055  I -.0928592  .0000022  0.2733 0.0016  I   -55.272     .720    -1.766     .126 -0.124610  0.200230 -0.0928610   -54.600    -1.900  
+ 112 4 52247.00 I  -.127367  .000104   .202499  .000057  I -.0931227  .0000018  0.2637 0.0015  I   -54.934     .720    -1.659     .126 -0.127150  0.202470 -0.0931050   -54.200    -1.800  
+ 112 5 52248.00 I  -.129424  .000103   .205211  .000058  I -.0934180  .0000020  0.3484 0.0013  I   -54.617     .720    -1.531     .126 -0.129470  0.205230 -0.0934140   -53.800    -1.600  
+ 112 6 52249.00 I  -.131746  .000103   .208532  .000057  I -.0938524  .0000020  0.5318 0.0015  I   -54.321     .720    -1.461     .126 -0.131820  0.208530 -0.0938520   -53.600    -1.300  
+ 112 7 52250.00 I  -.134559  .000102   .211661  .000057  I -.0944922  .0000021  0.7472 0.0023  I   -54.076     .720    -1.430     .126 -0.134560  0.211710 -0.0944960   -53.700    -1.100  
+ 112 8 52251.00 I  -.137796  .000068   .214373  .000066  I -.0953455  .0000042  0.9589 0.0027  I   -53.894     .526    -1.389     .295 -0.137790  0.214400 -0.0953380   -54.000    -0.900  
+ 112 9 52252.00 I  -.140993  .000056   .216887  .000054  I -.0963972  .0000050  1.1321 0.0047  I   -54.018     .492    -1.326     .344 -0.140970  0.216840 -0.0963730   -54.400    -0.700  
+ 11210 52253.00 I  -.143845  .000070   .219614  .000052  I -.0975759  .0000085  1.2038 0.0055  I   -54.377     .413    -1.286     .288 -0.143840  0.219610 -0.0975250   -55.000    -0.500  
+ 11211 52254.00 I  -.146663  .000067   .222530  .000051  I -.0987595  .0000098  1.1397 0.0063  I   -54.824     .413    -1.304     .288 -0.146720  0.222550 -0.0986800   -55.500    -0.500  
+ 11212 52255.00 I  -.149955  .000071   .225288  .000059  I -.0998250  .0000094  0.9849 0.0067  I   -55.220     .293    -1.361     .268 -0.149810  0.225270 -0.0997520   -55.900    -0.600  
+ 11213 52256.00 I  -.152619  .000073   .227892  .000058  I -.1007198  .0000091  0.8018 0.0066  I   -55.247     .293    -1.421     .268 -0.152690  0.227810 -0.1006790   -56.100    -0.800  
+ 11214 52257.00 I  -.155312  .000077   .230578  .000060  I -.1014175  .0000093  0.5856 0.0063  I   -55.031     .293    -1.435     .268 -0.155270  0.230440 -0.1014000   -55.900    -1.000  
+ 11215 52258.00 I  -.157721  .000066   .233138  .000055  I -.1018974  .0000088  0.3888 0.0074  I   -54.743     .108    -1.424     .185 -0.157710  0.233150 -0.1018990   -55.500    -1.200  
+ 11216 52259.00 I  -.159985  .000041   .235805  .000052  I -.1022319  .0000115  0.3026 0.0054  I   -54.524     .740    -1.446     .187 -0.159980  0.235780 -0.1022370   -54.800    -1.400  
+ 11217 52260.00 I  -.161987  .000045   .238560  .000048  I -.1025397  .0000063  0.3278 0.0064  I   -54.370     .195    -1.487     .168 -0.161990  0.238560 -0.1025390   -54.200    -1.600  
+ 11218 52261.00 I  -.163912  .000064   .241535  .000043  I -.1029096  .0000058  0.4194 0.0044  I   -54.210     .264    -1.480     .152 -0.163910  0.241570 -0.1029110   -53.700    -1.600  
+ 11219 52262.00 I  -.165861  .000058   .244801  .000042  I -.1033804  .0000062  0.5169 0.0041  I   -54.050     .264    -1.401     .152 -0.165910  0.244800 -0.1033780   -53.400    -1.400  
+ 11220 52263.00 I  -.167850  .000056   .248402  .000047  I -.1039633  .0000059  0.6742 0.0043  I   -53.984     .264    -1.336     .152 -0.167810  0.248290 -0.1039500   -53.200    -1.200  
+ 11221 52264.00 I  -.169230  .000060   .251819  .000048  I -.1047528  .0000059  0.9034 0.0042  I   -54.043     .264    -1.379     .152 -0.169310  0.251770 -0.1047380   -53.500    -0.900  
+ 11222 52265.00 I  -.170330  .000062   .255332  .000051  I -.1057456  .0000059  1.0590 0.0045  I   -53.924     .740    -1.588     .340 -0.170420  0.255330 -0.1057660   -53.900    -0.600  
+ 11223 52266.00 I  -.171339  .000066   .258892  .000058  I -.1068441  .0000069  1.1347 0.0063  I   -53.942     .740    -1.631     .340 -0.171340  0.258950 -0.1068720   -54.200    -0.500  
+ 11224 52267.00 I  -.172082  .000030   .262522  .000046  I -.1080049  .0000112  1.1803 0.0052  I   -53.955     .740    -1.498     .340 -0.172130  0.262500 -0.1080060   -54.800    -0.400  
+ 11225 52268.00 I  -.172610  .000031   .266399  .000052  I -.1091917  .0000078  1.1868 0.0058  I   -54.085     .740    -1.216     .340 -0.172630  0.266380 -0.1091660   -55.100    -0.600  
+ 11226 52269.00 I  -.173029  .000037   .270501  .000068  I -.1103666  .0000027  1.1574 0.0041  I   -54.327     .194     -.902     .340 -0.172980  0.270520 -0.1103540   -55.400    -0.700  
+ 11227 52270.00 I  -.173564  .000043   .274604  .000066  I -.1114947  .0000027  1.0925 0.0021  I   -54.556     .194     -.691     .340 -0.173600  0.274890 -0.1114930   -55.500    -0.800  
+ 11228 52271.00 I  -.174569  .000043   .278560  .000066  I -.1125366  .0000031  0.9827 0.0035  I   -54.667     .165     -.692     .340 -0.174540  0.278470 -0.1125380   -55.500    -1.000  
+ 11229 52272.00 I  -.175316  .000040   .282350  .000086  I -.1134552  .0000065  0.8583 0.0037  I   -54.728     .165     -.941     .340 -0.175190  0.282350 -0.1134560   -55.200    -1.000  
+ 11230 52273.00 I  -.175984  .000040   .286373  .000079  I -.1142677  .0000067  0.7774 0.0048  I   -54.662     .165    -1.294     .340 -0.175920  0.286410 -0.1142540   -54.800    -1.000  
+ 11231 52274.00 I  -.176653  .000042   .290272  .000072  I -.1150324  .0000070  0.7636 0.0094  I   -54.357     .165    -1.518     .340 -0.176950  0.290250 -0.1149770   -54.300    -0.900  
+ 2 1 1 52275.00 I  -.177016  .000041   .293921  .000069  I -.1158152  .0000175  0.8108 0.0060  I   -53.821     .740    -1.481     .340 -0.177000  0.293620 -0.1158230   -52.800    -1.100  
+ 2 1 2 52276.00 I  -.177495  .000033   .297612  .000080  I -.1166808  .0000098  0.9385 0.0103  I   -53.265     .265    -1.268     .340 -0.177470  0.297200 -0.1166920   -52.600    -1.200  
+ 2 1 3 52277.00 I  -.178336  .000037   .300810  .000073  I -.1177100  .0000108  1.1198 0.0070  I   -52.938     .265    -1.076     .340 -0.178340  0.300940 -0.1177150   -52.600    -1.100  
+ 2 1 4 52278.00 I  -.179101  .000042   .303585  .000061  I -.1189101  .0000099  1.2704 0.0072  I   -52.906     .265    -1.021     .340 -0.179090  0.303680 -0.1189030   -52.800    -1.100  
+ 2 1 5 52279.00 I  -.179532  .000046   .306461  .000060  I -.1202228  .0000094  1.3372 0.0062  I   -53.091     .259    -1.064     .119 -0.179550  0.306440 -0.1202550   -53.100    -1.000  
+ 2 1 6 52280.00 I  -.180020  .000057   .309511  .000089  I -.1215588  .0000074  1.3270 0.0061  I   -53.330     .208    -1.116     .122 -0.179970  0.309560 -0.1216410   -53.500    -0.900  
+ 2 1 7 52281.00 I  -.180675  .000057   .312707  .000088  I -.1228480  .0000077  1.2304 0.0057  I   -53.622     .208    -1.132     .122 -0.180630  0.312730 -0.1229070   -53.800    -0.900  
+ 2 1 8 52282.00 I  -.181819  .000065   .315313  .000071  I -.1239725  .0000088  0.9923 0.0057  I   -53.953     .140    -1.120     .124 -0.181690  0.315560 -0.1239680   -54.100    -0.800  
+ 2 1 9 52283.00 I  -.182661  .000094   .318169  .000076  I -.1248182  .0000085  0.7108 0.0061  I   -54.210     .226    -1.105     .101 -0.182690  0.318280 -0.1248070   -54.100    -0.800  
+ 2 110 52284.00 I  -.183034  .000088   .321152  .000076  I -.1254127  .0000084  0.4850 0.0062  I   -54.304     .226    -1.081     .101 -0.183060  0.321190 -0.1254210   -54.000    -0.900  
+ 2 111 52285.00 I  -.183124  .000081   .324202  .000082  I -.1258003  .0000089  0.2955 0.0071  I   -54.136     .226    -1.087     .101 -0.183040  0.324220 -0.1257940   -53.700    -1.000  
+ 2 112 52286.00 I  -.182606  .000079   .327370  .000036  I -.1260104  .0000114  0.1261 0.0060  I   -53.756     .231    -1.161     .340 -0.182770  0.327380 -0.1260400   -53.500    -1.200  
+ 2 113 52287.00 I  -.182290  .000085   .330466  .000067  I -.1260705  .0000081  0.0106 0.0071  I   -53.448     .211    -1.310     .129 -0.182260  0.330390 -0.1261170   -53.300    -1.400  
+ 2 114 52288.00 I  -.181735  .000084   .333568  .000075  I -.1260606  .0000084 -0.0178 0.0052  I   -53.288     .211    -1.459     .129 -0.181660  0.333550 -0.1260720   -53.200    -1.500  
+ 2 115 52289.00 I  -.181305  .000047   .336868  .000079  I -.1260645  .0000066  0.0426 0.0047  I   -53.250     .189    -1.511     .174 -0.181260  0.336820 -0.1260550   -53.200    -1.600  
+ 2 116 52290.00 I  -.180666  .000048   .339816  .000072  I -.1261542  .0000042  0.1280 0.0039  I   -53.278     .149    -1.462     .133 -0.180660  0.339780 -0.1261430   -53.200    -1.600  
+ 2 117 52291.00 I  -.179799  .000050   .342945  .000074  I -.1263182  .0000041  0.2064 0.0029  I   -53.374     .149    -1.419     .133 -0.179880  0.342870 -0.1263090   -53.300    -1.600  
+ 2 118 52292.00 I  -.179235  .000049   .346080  .000082  I -.1265902  .0000040  0.3543 0.0029  I   -53.504     .149    -1.476     .133 -0.179240  0.346120 -0.1265880   -53.400    -1.500  
+ 2 119 52293.00 I  -.178756  .000032   .349176  .000059  I -.1270231  .0000040  0.4911 0.0027  I   -53.538     .740    -1.620     .340 -0.178740  0.349230 -0.1270260   -53.300    -1.400  
+ 2 120 52294.00 I  -.178420  .000029   .352206  .000054  I -.1275466  .0000037  0.5505 0.0027  I   -53.402     .740    -1.665     .340 -0.178410  0.352280 -0.1275570   -53.200    -1.300  
+ 2 121 52295.00 I  -.178175  .000098   .355254  .000052  I -.1281161  .0000036  0.5861 0.0024  I   -53.270     .223    -1.611     .340 -0.178170  0.355300 -0.1281260   -53.000    -1.200  
+ 2 122 52296.00 I  -.177717  .000100   .358445  .000045  I -.1287129  .0000032  0.6041 0.0024  I   -53.356     .302    -1.520     .340 -0.177750  0.358510 -0.1287150   -53.000    -1.200  
+ 2 123 52297.00 I  -.177120  .000106   .361868  .000045  I -.1293129  .0000032  0.5879 0.0023  I   -53.632     .244    -1.427     .340 -0.177120  0.361930 -0.1293080   -53.000    -1.200  
+ 2 124 52298.00 I  -.176579  .000107   .365288  .000045  I -.1298667  .0000032  0.5058 0.0022  I   -53.901     .244    -1.315     .340 -0.176510  0.365290 -0.1298590   -53.400    -1.200  
+ 2 125 52299.00 I  -.175468  .000109   .368698  .000047  I -.1303104  .0000031  0.3813 0.0023  I   -54.125     .244    -1.241     .340 -0.175730  0.368690 -0.1303060   -53.800    -1.200  
+ 2 126 52300.00 I  -.174998  .000119   .372115  .000048  I -.1306448  .0000032  0.3033 0.0030  I   -54.387     .223    -1.352     .340 -0.175000  0.372170 -0.1306280   -54.100    -1.400  
+ 2 127 52301.00 I  -.174316  .000076   .375411  .000057  I -.1309512  .0000051  0.3277 0.0032  I   -54.671     .321    -1.735     .340 -0.174370  0.375470 -0.1309230   -54.200    -1.700  
+ 2 128 52302.00 I  -.173598  .000075   .378730  .000059  I -.1313384  .0000055  0.4665 0.0044  I   -54.583     .321    -2.157     .340 -0.173550  0.378710 -0.1313120   -54.100    -1.900  
+ 2 129 52303.00 I  -.172607  .000062   .382056  .000058  I -.1319137  .0000071  0.6939 0.0046  I   -53.935     .421    -2.303     .340 -0.172820  0.382030 -0.1319070   -54.000    -2.200  
+ 2 130 52304.00 I  -.172389  .000111   .385066  .000051  I -.1327493  .0000073  0.9908 0.0051  I   -53.054     .401    -2.100     .159 -0.172060  0.385140 -0.1327840   -53.400    -2.100  
+ 2 131 52305.00 I  -.170719  .000113   .388310  .000051  I -.1338791  .0000074  1.2392 0.0052  I   -52.497     .401    -1.785     .159 -0.170750  0.388250 -0.1339120   -52.900    -1.900  
+ 2 2 1 52306.00 I  -.168875  .000103   .391546  .000048  I -.1351973  .0000073  1.3964 0.0047  I   -52.497     .401    -1.619     .159 -0.168940  0.391530 -0.1352080   -52.400    -1.600  
+ 2 2 2 52307.00 I  -.167477  .000110   .394739  .000066  I -.1366556  .0000057  1.5046 0.0044  I   -52.845     .379    -1.638     .212 -0.167400  0.394750 -0.1365590   -52.300    -1.500  
+ 2 2 3 52308.00 I  -.166425  .000068   .397897  .000101  I -.1381554  .0000049  1.4595 0.0038  I   -53.214     .337    -1.696     .224 -0.166390  0.397840 -0.1380160   -52.500    -1.400  
+ 2 2 4 52309.00 I  -.165568  .000064   .400893  .000101  I -.1395328  .0000049  1.2892 0.0034  I   -53.473     .337    -1.725     .224 -0.165460  0.400780 -0.1394740   -52.800    -1.400  
+ 2 2 5 52310.00 I  -.164218  .000045   .403149  .000104  I -.1407285  .0000048  1.1032 0.0034  I   -53.665     .290    -1.751     .236 -0.164370  0.403580 -0.1407190   -54.000    -1.400  
+ 2 2 6 52311.00 I  -.163276  .000056   .406446  .000100  I -.1417207  .0000046  0.8616 0.0033  I   -53.843     .263    -1.804     .168 -0.163320  0.406310 -0.1417360   -54.100    -1.500  
+ 2 2 7 52312.00 I  -.162284  .000055   .409364  .000101  I -.1424592  .0000045  0.6423 0.0031  I   -53.959     .263    -1.858     .168 -0.162230  0.409320 -0.1424540   -53.900    -1.600  
+ 2 2 8 52313.00 I  -.161022  .000053   .412491  .000100  I -.1430272  .0000043  0.4886 0.0044  I   -53.893     .263    -1.909     .168 -0.161130  0.412430 -0.1430230   -53.400    -1.800  
+ 2 2 9 52314.00 I  -.159842  .000049   .415394  .000050  I -.1434514  .0000075  0.3800 0.0047  I   -53.498     .134    -2.001     .340 -0.159750  0.415430 -0.1434440   -53.000    -1.900  
+ 2 210 52315.00 I  -.157943  .000056   .418781  .000106  I -.1438265  .0000084  0.3895 0.0054  I   -53.099     .454    -2.173     .165 -0.157950  0.418820 -0.1438150   -52.600    -2.000  
+ 2 211 52316.00 I  -.156070  .000058   .422412  .000119  I -.1442607  .0000077  0.4900 0.0058  I   -52.804     .454    -2.328     .165 -0.156050  0.422450 -0.1442500   -52.500    -2.100  
+ 2 212 52317.00 I  -.154331  .000050   .425633  .000119  I -.1448045  .0000079  0.5844 0.0052  I   -52.715     .628    -2.341     .233 -0.154400  0.425740 -0.1447930   -52.500    -2.100  
+ 2 213 52318.00 I  -.153348  .000073   .428706  .000121  I -.1454279  .0000071  0.6738 0.0052  I   -52.787     .451    -2.211     .174 -0.153250  0.428820 -0.1454300   -52.600    -2.100  
+ 2 214 52319.00 I  -.152471  .000068   .431713  .000120  I -.1461593  .0000069  0.7846 0.0045  I   -52.928     .451    -2.084     .174 -0.152390  0.431700 -0.1461620   -52.700    -2.000  
+ 2 215 52320.00 I  -.151431  .000074   .434433  .000119  I -.1469919  .0000055  0.8798 0.0038  I   -53.037     .451    -2.090     .174 -0.151390  0.434420 -0.1469910   -52.800    -2.000  
+ 2 216 52321.00 I  -.150089  .000069   .437078  .000077  I -.1479225  .0000033  0.9858 0.0033  I   -53.009     .122    -2.215     .340 -0.150100  0.437100 -0.1479090   -52.700    -2.000  
+ 2 217 52322.00 I  -.148485  .000065   .439730  .000045  I -.1489536  .0000035  1.0621 0.0032  I   -52.796     .122    -2.298     .340 -0.148490  0.439730 -0.1489370   -52.500    -2.100  
+ 2 218 52323.00 I  -.146818  .000112   .442441  .000075  I -.1500204  .0000054  1.0593 0.0035  I   -52.597     .740    -2.350     .340 -0.146780  0.442390 -0.1500170   -52.300    -2.100  
+ 2 219 52324.00 I  -.145248  .000100   .445256  .000077  I -.1510529  .0000060  0.9984 0.0040  I   -52.626     .740    -2.458     .340 -0.145260  0.445150 -0.1510560   -52.100    -2.100  
+ 2 220 52325.00 I  -.143908  .000104   .447804  .000077  I -.1520116  .0000060  0.9206 0.0043  I   -52.833     .226    -2.622     .340 -0.143730  0.447920 -0.1520210   -52.100    -2.200  
+ 2 221 52326.00 I  -.142017  .000105   .450844  .000075  I -.1528875  .0000061  0.8229 0.0043  I   -52.990     .226    -2.701     .340 -0.142030  0.450810 -0.1528980   -52.200    -2.400  
+ 2 222 52327.00 I  -.140236  .000105   .453903  .000075  I -.1536583  .0000061  0.7279 0.0042  I   -53.081     .226    -2.644     .340 -0.140240  0.453930 -0.1536530   -52.500    -2.700  
+ 2 223 52328.00 I  -.138470  .000104   .457214  .000070  I -.1543530  .0000058  0.6621 0.0039  I   -53.260     .187    -2.679     .340 -0.138440  0.457220 -0.1543870   -52.800    -3.000  
+ 2 224 52329.00 I  -.136564  .000139   .460595  .000023  I -.1550116  .0000047  0.6835 0.0038  I   -53.660     .294    -2.970     .340 -0.136510  0.460600 -0.1551080   -53.100    -3.300  
+ 2 225 52330.00 I  -.134094  .000156   .463762  .000021  I -.1557661  .0000049  0.8433 0.0031  I   -53.763     .294    -3.449     .340 -0.134050  0.463790 -0.1558460   -53.200    -3.600  
+ 2 226 52331.00 I  -.131075  .000147   .466899  .000032  I -.1567270  .0000040  1.0894 0.0031  I   -53.205     .335    -3.740     .340 -0.131080  0.466900 -0.1567280   -53.100    -3.700  
+ 2 227 52332.00 I  -.128411  .000142   .470196  .000051  I -.1579544  .0000038  1.3639 0.0028  I   -52.247     .241    -3.628     .340 -0.128360  0.470160 -0.1579220   -52.700    -3.700  
+ 2 228 52333.00 I  -.125976  .000133   .473454  .000051  I -.1594256  .0000038  1.5508 0.0027  I   -51.558     .241    -3.297     .340 -0.125970  0.473440 -0.1594490   -52.100    -3.400  
+ 2 3 1 52334.00 I  -.123473  .000133   .476420  .000052  I -.1610247  .0000039  1.6439 0.0026  I   -51.514     .241    -3.071     .340 -0.123360  0.476540 -0.1610230   -51.400    -3.000  
+ 2 3 2 52335.00 I  -.120773  .000034   .479750  .000055  I -.1626879  .0000035  1.6606 0.0024  I   -51.996     .740    -3.026     .340 -0.120890  0.479830 -0.1626750   -51.300    -2.700  
+ 2 3 3 52336.00 I  -.118537  .000073   .482904  .000054  I -.1642927  .0000028  1.5177 0.0022  I   -52.427     .168    -3.060     .340 -0.118380  0.482830 -0.1642830   -51.200    -2.400  
+ 2 3 4 52337.00 I  -.116662  .000087   .485901  .000053  I -.1656830  .0000025  1.2538 0.0022  I   -52.637     .152    -3.081     .340 -0.116640  0.485860 -0.1656820   -51.400    -2.400  
+ 2 3 5 52338.00 I  -.114402  .000076   .488895  .000075  I -.1668039  .0000034  1.0006 0.0018  I   -52.661     .183    -3.165     .340 -0.114530  0.488880 -0.1668110   -51.700    -2.500  
+ 2 3 6 52339.00 I  -.111601  .000075   .491674  .000054  I -.1677040  .0000027  0.8068 0.0021  I   -52.662     .217    -3.359     .340 -0.111870  0.491710 -0.1677050   -51.900    -2.800  
+ 2 3 7 52340.00 I  -.108721  .000076   .494389  .000053  I -.1684320  .0000025  0.6566 0.0018  I   -52.744     .217    -3.560     .340 -0.108770  0.494280 -0.1684280   -52.100    -3.100  
+ 2 3 8 52341.00 I  -.105539  .000074   .497043  .000053  I -.1690387  .0000023  0.5710 0.0018  I   -52.818     .217    -3.656     .340 -0.105510  0.497000 -0.1690330   -52.100    -3.500  
+ 2 3 9 52342.00 I  -.102297  .000069   .499702  .000054  I -.1695899  .0000025  0.5331 0.0019  I   -52.614     .172    -3.662     .340 -0.102260  0.499710 -0.1696080   -51.900    -3.700  
+ 2 310 52343.00 I  -.099240  .000088   .502427  .000058  I -.1701263  .0000031  0.5596 0.0020  I   -52.203     .160    -3.678     .340 -0.099160  0.502440 -0.1701600   -51.600    -3.800  
+ 2 311 52344.00 I  -.096907  .000097   .505134  .000050  I -.1707381  .0000032  0.6733 0.0023  I   -51.725     .160    -3.677     .340 -0.096810  0.505150 -0.1707500   -51.400    -3.700  
+ 2 312 52345.00 I  -.095010  .000103   .507537  .000040  I -.1714858  .0000035  0.8257 0.0023  I   -51.455     .740    -3.552     .340 -0.095040  0.507560 -0.1714790   -51.300    -3.500  
+ 2 313 52346.00 I  -.092703  .000098   .509844  .000045  I -.1723819  .0000034  0.9554 0.0025  I   -51.475     .206    -3.291     .340 -0.092840  0.509890 -0.1723820   -51.200    -3.300  
+ 2 314 52347.00 I  -.090280  .000108   .512133  .000050  I -.1733703  .0000036  1.0061 0.0025  I   -51.626     .206    -3.058     .340 -0.090220  0.512070 -0.1733690   -51.300    -3.200  
+ 2 315 52348.00 I  -.087647  .000109   .514321  .000054  I -.1743650  .0000037  0.9693 0.0025  I   -51.748     .206    -3.018     .340 -0.087660  0.514370 -0.1743580   -51.300    -3.100  
+ 2 316 52349.00 I  -.084887  .000041   .516458  .000050  I -.1753014  .0000036  0.9098 0.0030  I   -51.739     .247    -3.159     .340 -0.084860  0.516470 -0.1753050   -51.300    -3.000  
+ 2 317 52350.00 I  -.081872  .000095   .518429  .000045  I -.1761905  .0000047  0.8680 0.0030  I   -51.598     .141    -3.339     .340 -0.081840  0.518430 -0.1762050   -51.200    -3.100  
+ 2 318 52351.00 I  -.078750  .000095   .520307  .000058  I -.1770307  .0000047  0.8060 0.0034  I   -51.451     .141    -3.494     .340 -0.078700  0.520250 -0.1770390   -51.000    -3.200  
+ 2 319 52352.00 I  -.075580  .000088   .522229  .000057  I -.1777808  .0000048  0.6788 0.0032  I   -51.449     .140    -3.689     .340 -0.075630  0.522210 -0.1777670   -50.900    -3.300  
+ 2 320 52353.00 I  -.072564  .000086   .523982  .000061  I -.1783793  .0000042  0.5245 0.0031  I   -51.564     .233    -3.948     .340 -0.072570  0.523990 -0.1783600   -50.800    -3.500  
+ 2 321 52354.00 I  -.069255  .000081   .525681  .000057  I -.1788451  .0000040  0.4162 0.0029  I   -51.599     .233    -4.144     .340 -0.069250  0.525600 -0.1788340   -50.800    -3.700  
+ 2 322 52355.00 I  -.065799  .000084   .527523  .000057  I -.1792335  .0000039  0.3735 0.0024  I   -51.492     .233    -4.169     .340 -0.065770  0.527460 -0.1792290   -50.900    -4.000  
+ 2 323 52356.00 I  -.062329  .000036   .529144  .000062  I -.1796148  .0000026  0.3991 0.0023  I   -51.432     .298    -4.139     .122 -0.062270  0.529100 -0.1796230   -51.000    -4.400  
+ 2 324 52357.00 I  -.058837  .000046   .530650  .000056  I -.1800603  .0000024  0.5107 0.0018  I   -51.530     .214    -4.282     .127 -0.058810  0.530710 -0.1801030   -51.100    -4.700  
+ 2 325 52358.00 I  -.055246  .000055   .532291  .000056  I -.1806694  .0000026  0.7219 0.0019  I   -51.554     .214    -4.608     .127 -0.055180  0.532160 -0.1807120   -51.000    -4.900  
+ 2 326 52359.00 I  -.051312  .000054   .534075  .000049  I -.1815255  .0000030  0.9975 0.0021  I   -51.213     .201    -4.844     .340 -0.051350  0.533960 -0.1815250   -50.800    -4.900  
+ 2 327 52360.00 I  -.048010  .000062   .535792  .000049  I -.1826741  .0000033  1.3024 0.0023  I   -50.631     .200    -4.779     .340 -0.047900  0.535800 -0.1826590   -50.500    -4.800  
+ 2 328 52361.00 I  -.045031  .000063   .537281  .000048  I -.1841051  .0000034  1.5317 0.0024  I   -50.267     .200    -4.510     .340 -0.044850  0.537270 -0.1841020   -50.200    -4.500  
+ 2 329 52362.00 I  -.041718  .000069   .538545  .000050  I -.1856662  .0000036  1.5469 0.0028  I   -50.401     .200    -4.327     .340 -0.041730  0.538490 -0.1856720   -49.900    -4.300  
+ 2 330 52363.00 I  -.038236  .000045   .539546  .000037  I -.1871407  .0000044  1.3874 0.0030  I   -50.867     .278    -4.318     .340 -0.038250  0.539420 -0.1871400   -49.700    -4.100  
+ 2 331 52364.00 I  -.034512  .000028   .540256  .000052  I -.1884214  .0000047  1.1690 0.0043  I   -51.291     .278    -4.347     .340 -0.034510  0.540310 -0.1884220   -49.600    -4.100  
+ 2 4 1 52365.00 I  -.030784  .000064   .540741  .000079  I -.1894701  .0000074  0.9247 0.0037  I   -51.432     .440    -4.340     .340 -0.030760  0.540660 -0.1894800   -49.700    -4.200  
+ 2 4 2 52366.00 I  -.027006  .000076   .541124  .000079  I -.1902749  .0000058  0.6928 0.0045  I   -51.299     .385    -4.416     .130 -0.026850  0.541150 -0.1902860   -49.900    -4.400  
+ 2 4 3 52367.00 I  -.022763  .000073   .541626  .000083  I -.1908693  .0000052  0.5017 0.0039  I   -51.097     .319    -4.663     .111 -0.022980  0.541720 -0.1908570   -50.100    -4.700  
+ 2 4 4 52368.00 I  -.018616  .000073   .542855  .000085  I -.1913055  .0000052  0.3922 0.0037  I   -51.094     .326    -4.944     .340 -0.018830  0.542820 -0.1912760   -50.500    -4.900  
+ 2 4 5 52369.00 I  -.014936  .000076   .544230  .000079  I -.1916850  .0000053  0.3767 0.0034  I   -51.221     .326    -5.060     .340 -0.014960  0.544200 -0.1916810   -50.700    -5.000  
+ 2 4 6 52370.00 I  -.011584  .000083   .545683  .000068  I -.1920849  .0000044  0.4394 0.0031  I   -51.255     .326    -4.972     .340 -0.011580  0.545710 -0.1920770   -50.900    -5.000  
+ 2 4 7 52371.00 I  -.008818  .000102   .546912  .000047  I -.1925759  .0000034  0.5386 0.0027  I   -50.958     .324    -4.815     .340 -0.008710  0.546960 -0.1925570   -50.800    -4.900  
+ 2 4 8 52372.00 I  -.006177  .000099   .547837  .000058  I -.1931609  .0000033  0.6344 0.0024  I   -50.455     .282    -4.670     .340 -0.006160  0.547850 -0.1931530   -50.700    -4.700  
+ 2 4 9 52373.00 I  -.003471  .000102   .548651  .000057  I -.1938494  .0000035  0.7444 0.0023  I   -50.118     .337    -4.481     .340 -0.003780  0.548650 -0.1938450   -50.600    -4.400  
+ 2 410 52374.00 I  -.001639  .000100   .549319  .000064  I -.1946504  .0000031  0.8567 0.0023  I   -50.146     .276    -4.205     .340 -0.001790  0.549280 -0.1946360   -50.500    -4.100  
+ 2 411 52375.00 I   .000751  .000093   .549735  .000065  I -.1955552  .0000030  0.9464 0.0022  I   -50.402     .276    -3.956     .340  0.000630  0.549660 -0.1955480   -50.500    -4.000  
+ 2 412 52376.00 I   .003786  .000091   .550390  .000071  I -.1965192  .0000030  0.9642 0.0025  I   -50.645     .276    -3.903     .340  0.003750  0.550380 -0.1965140   -50.500    -3.900  
+ 2 413 52377.00 I   .006859  .000056   .551221  .000072  I -.1974561  .0000040  0.8995 0.0029  I   -50.849     .134    -4.084     .340  0.006850  0.551270 -0.1974570   -50.400    -4.000  
+ 2 414 52378.00 I   .009914  .000065   .551919  .000060  I -.1983019  .0000050  0.7859 0.0032  I   -50.826     .225    -4.365     .340  0.009940  0.551890 -0.1983280   -50.200    -4.200  
+ 2 415 52379.00 I   .012891  .000066   .552556  .000056  I -.1990194  .0000050  0.6467 0.0036  I   -50.741     .225    -4.611     .340  0.012910  0.552530 -0.1990500   -50.100    -4.400  
+ 2 416 52380.00 I   .015666  .000067   .553134  .000041  I -.1995747  .0000053  0.4458 0.0035  I   -50.701     .303    -4.802     .119  0.015700  0.553150 -0.1995690   -50.100    -4.600  
+ 2 417 52381.00 I   .018798  .000070   .553633  .000042  I -.1999273  .0000050  0.2940 0.0036  I   -50.764     .240    -4.957     .340  0.018850  0.553680 -0.1999170   -50.200    -4.800  
+ 2 418 52382.00 I   .022135  .000072   .554122  .000041  I -.2002060  .0000050  0.2722 0.0034  I   -50.844     .240    -5.110     .340  0.022150  0.554150 -0.2001990   -50.300    -5.000  
+ 2 419 52383.00 I   .025465  .000075   .554554  .000042  I -.2004662  .0000045  0.2341 0.0032  I   -50.793     .240    -5.191     .340  0.025500  0.554540 -0.2004610   -50.400    -5.100  
+ 2 420 52384.00 I   .028893  .000034   .554819  .000040  I -.2006861  .0000039  0.2318 0.0028  I   -50.580     .153    -5.218     .340  0.028950  0.554890 -0.2006920   -50.300    -5.200  
+ 2 421 52385.00 I   .032006  .000078   .554948  .000052  I -.2009777  .0000033  0.3734 0.0026  I   -50.295     .207    -5.273     .340  0.032050  0.555000 -0.2009790   -50.200    -5.300  
+ 2 422 52386.00 I   .034837  .000078   .554923  .000056  I -.2014742  .0000035  0.6391 0.0024  I   -50.010     .207    -5.370     .340  0.034890  0.554920 -0.2014710   -50.000    -5.300  
+ 2 423 52387.00 I   .037858  .000075   .554783  .000059  I -.2022657  .0000034  0.9341 0.0027  I   -49.772     .250    -5.391     .340  0.037860  0.554810 -0.2022590   -49.800    -5.300  
+ 2 424 52388.00 I   .041216  .000076   .554620  .000066  I -.2033246  .0000040  1.1756 0.0026  I   -49.700     .242    -5.246     .340  0.041250  0.554620 -0.2033180   -49.700    -5.200  
+ 2 425 52389.00 I   .044875  .000076   .554471  .000066  I -.2045984  .0000040  1.3617 0.0027  I   -49.933     .242    -5.033     .340  0.044890  0.554490 -0.2045770   -49.800    -5.100  
+ 2 426 52390.00 I   .048626  .000078   .554293  .000069  I -.2060056  .0000037  1.4204 0.0037  I   -50.438     .242    -4.937     .340  0.048700  0.554360 -0.2059990   -50.000    -4.900  
+ 2 427 52391.00 I   .052514  .000059   .553903  .000073  I -.2073772  .0000063  1.2929 0.0035  I   -51.044     .374    -4.990     .340  0.052510  0.553960 -0.2073770   -50.200    -4.800  
+ 2 428 52392.00 I   .056207  .000067   .553344  .000098  I -.2085449  .0000060  1.0260 0.0043  I   -51.380     .340    -5.040     .340  0.056270  0.553350 -0.2085470   -50.400    -4.800  
+ 2 429 52393.00 I   .059895  .000068   .552842  .000098  I -.2094192  .0000060  0.7292 0.0043  I   -51.411     .340    -5.008     .340  0.059990  0.552900 -0.2094170   -50.600    -4.900  
+ 2 430 52394.00 I   .063457  .000058   .552433  .000099  I -.2100075  .0000061  0.4450 0.0041  I   -51.188     .302    -5.017     .340  0.063540  0.552680 -0.2099850   -50.700    -5.100  
+ 2 5 1 52395.00 I   .066763  .000059   .552386  .000099  I -.2103409  .0000055  0.2560 0.0041  I   -50.882     .250    -5.204     .340  0.066810  0.552550 -0.2103280   -50.900    -5.400  
+ 2 5 2 52396.00 I   .069968  .000057   .552234  .000095  I -.2105649  .0000055  0.2032 0.0034  I   -50.717     .250    -5.482     .340  0.070040  0.552260 -0.2105750   -51.000    -5.600  
+ 2 5 3 52397.00 I   .073288  .000052   .551921  .000090  I -.2107657  .0000041  0.2057 0.0033  I   -50.781     .250    -5.625     .340  0.073400  0.551980 -0.2107650   -50.800    -5.600  
+ 2 5 4 52398.00 I   .076875  .000043   .551796  .000056  I -.2110038  .0000037  0.2908 0.0030  I   -50.900     .172    -5.519     .340  0.076890  0.551810 -0.2110110   -50.500    -5.500  
+ 2 5 5 52399.00 I   .080648  .000051   .551735  .000052  I -.2113748  .0000044  0.4585 0.0032  I   -50.784     .370    -5.340     .204  0.080730  0.551700 -0.2114160   -50.100    -5.300  
+ 2 5 6 52400.00 I   .084621  .000056   .551579  .000048  I -.2119226  .0000052  0.6317 0.0035  I   -50.470     .307    -5.202     .185  0.084750  0.551580 -0.2119720   -49.900    -4.900  
+ 2 5 7 52401.00 I   .088539  .000060   .551194  .000048  I -.2126279  .0000055  0.7740 0.0037  I   -50.271     .308    -5.088     .192  0.088540  0.551260 -0.2126300   -49.900    -4.500  
+ 2 5 8 52402.00 I   .091562  .000056   .550682  .000050  I -.2134579  .0000053  0.8781 0.0038  I   -50.404     .264    -4.919     .171  0.091560  0.550730 -0.2134090   -50.200    -4.400  
+ 2 5 9 52403.00 I   .094243  .000059   .549881  .000051  I -.2143723  .0000052  0.9469 0.0037  I   -50.790     .264    -4.708     .171  0.094320  0.549950 -0.2143480   -50.600    -4.400  
+ 2 510 52404.00 I   .097639  .000059   .549119  .000052  I -.2153390  .0000051  0.9776 0.0040  I   -51.167     .264    -4.598     .171  0.097670  0.549210 -0.2153350   -51.000    -4.600  
+ 2 511 52405.00 I   .101069  .000061   .548815  .000052  I -.2163055  .0000060  0.9424 0.0039  I   -51.344     .145    -4.696     .105  0.101130  0.548850 -0.2163140   -51.100    -4.800  
+ 2 512 52406.00 I   .103917  .000071   .548350  .000060  I -.2172079  .0000058  0.8597 0.0052  I   -51.418     .178    -4.959     .340  0.104010  0.548380 -0.2172330   -51.000    -5.000  
+ 2 513 52407.00 I   .106766  .000072   .547632  .000063  I -.2180235  .0000086  0.7730 0.0050  I   -51.369     .140    -5.248     .340  0.106820  0.547560 -0.2180410   -50.900    -5.200  
+ 2 514 52408.00 I   .109822  .000105   .546781  .000060  I -.2187407  .0000081  0.6468 0.0055  I   -51.284     .143    -5.441     .340  0.109690  0.546720 -0.2187190   -50.800    -5.300  
+ 2 515 52409.00 I   .112006  .000103   .545573  .000055  I -.2193284  .0000069  0.5543 0.0053  I   -51.291     .169    -5.527     .340  0.112130  0.545580 -0.2193030   -50.900    -5.400  
+ 2 516 52410.00 I   .114375  .000097   .544014  .000055  I -.2198677  .0000069  0.5168 0.0046  I   -51.445     .169    -5.558     .340  0.114200  0.544020 -0.2198500   -51.000    -5.500  
+ 2 517 52411.00 I   .116538  .000092   .542416  .000054  I -.2203632  .0000060  0.4829 0.0040  I   -51.589     .169    -5.604     .340  0.116510  0.542440 -0.2203590   -51.100    -5.500  
+ 2 518 52412.00 I   .119081  .000062   .541230  .000045  I -.2208752  .0000041  0.5741 0.0033  I   -51.504     .164    -5.670     .340  0.119110  0.541240 -0.2208620   -50.900    -5.500  
+ 2 519 52413.00 I   .121980  .000062   .540478  .000044  I -.2215514  .0000028  0.7854 0.0024  I   -51.131     .263    -5.711     .340  0.121990  0.540490 -0.2215070   -50.700    -5.500  
+ 2 520 52414.00 I   .125203  .000040   .539959  .000035  I -.2224608  .0000023  1.0412 0.0017  I   -50.660     .317    -5.665     .340  0.125270  0.539970 -0.2224240   -50.500    -5.400  
+ 2 521 52415.00 I   .128372  .000037   .539462  .000033  I -.2236311  .0000019  1.2889 0.0015  I   -50.405     .393    -5.503     .340  0.128480  0.539480 -0.2236270   -50.500    -5.300  
+ 2 522 52416.00 I   .131149  .000049   .538798  .000050  I -.2249998  .0000020  1.4200 0.0014  I   -50.596     .287    -5.264     .340  0.131230  0.538810 -0.2250060   -50.900    -5.300  
+ 2 523 52417.00 I   .133610  .000045   .537948  .000049  I -.2264286  .0000020  1.4234 0.0014  I   -51.214     .287    -5.064     .340  0.133700  0.537930 -0.2264180   -51.400    -5.200  
+ 2 524 52418.00 I   .135820  .000043   .537054  .000049  I -.2278096  .0000020  1.3158 0.0016  I   -51.985     .287    -5.008     .340  0.135990  0.537030 -0.2278030   -51.900    -5.100  
+ 2 525 52419.00 I   .138173  .000036   .536021  .000048  I -.2290156  .0000026  1.0744 0.0016  I   -52.570     .101    -5.081     .100  0.138220  0.536070 -0.2290250   -52.100    -4.900  
+ 2 526 52420.00 I   .140457  .000034   .534941  .000055  I -.2299334  .0000024  0.7581 0.0019  I   -52.794     .101    -5.152     .100  0.140550  0.534950 -0.2299640   -52.100    -4.800  
+ 2 527 52421.00 I   .143105  .000051   .533782  .000060  I -.2305356  .0000027  0.4533 0.0020  I   -52.706     .206    -5.138     .102  0.143240  0.533780 -0.2305660   -52.000    -4.800  
+ 2 528 52422.00 I   .146195  .000046   .532652  .000049  I -.2308616  .0000031  0.2133 0.0021  I   -52.458     .274    -5.122     .104  0.146250  0.532660 -0.2308730   -51.800    -4.900  
+ 2 529 52423.00 I   .148920  .000049   .531341  .000047  I -.2309940  .0000031  0.0685 0.0022  I   -52.198     .336    -5.234     .340  0.149140  0.531430 -0.2309950   -51.700    -5.000  
+ 2 530 52424.00 I   .151861  .000049   .529999  .000047  I -.2310346  .0000031  0.0315 0.0022  I   -52.057     .336    -5.455     .340  0.151940  0.530030 -0.2310410   -51.700    -5.300  
+ 2 531 52425.00 I   .154660  .000052   .528524  .000051  I -.2310732  .0000032  0.0429 0.0022  I   -52.101     .336    -5.618     .340  0.154720  0.528570 -0.2310720   -51.900    -5.600  
+ 2 6 1 52426.00 I   .157254  .000051   .526992  .000049  I -.2311274  .0000031  0.0753 0.0023  I   -52.252     .336    -5.620     .340  0.157340  0.527040 -0.2311240   -51.800    -5.700  
+ 2 6 2 52427.00 I   .159754  .000052   .525267  .000059  I -.2312328  .0000032  0.1348 0.0022  I   -52.354     .308    -5.534     .340  0.159880  0.525310 -0.2312140   -51.700    -5.600  
+ 2 6 3 52428.00 I   .162414  .000051   .523380  .000059  I -.2313968  .0000030  0.1936 0.0022  I   -52.360     .296    -5.478     .340  0.162500  0.523430 -0.2313740   -51.700    -5.500  
+ 2 6 4 52429.00 I   .165131  .000048   .521795  .000055  I -.2316129  .0000029  0.2312 0.0021  I   -52.404     .183    -5.446     .117  0.165300  0.521670 -0.2316120   -51.800    -5.300  
+ 2 6 5 52430.00 I   .168230  .000074   .520114  .000054  I -.2318286  .0000029  0.1769 0.0021  I   -52.639     .193    -5.335     .131  0.168340  0.520030 -0.2318370   -52.300    -5.100  
+ 2 6 6 52431.00 I   .171414  .000075   .518441  .000054  I -.2319476  .0000029  0.0654 0.0021  I   -53.061     .193    -5.113     .131  0.171450  0.518430 -0.2319380   -52.900    -5.000  
+ 2 6 7 52432.00 I   .174114  .000081   .516725  .000075  I -.2319645  .0000031 -0.0308 0.0028  I   -53.538     .193    -4.888     .131  0.174530  0.516740 -0.2319570   -53.500    -5.000  
+ 2 6 8 52433.00 I   .177634  .000075   .515071  .000060  I -.2318775  .0000049 -0.1524 0.0028  I   -53.804     .318    -4.835     .148  0.177650  0.515060 -0.2318840   -53.800    -5.100  
+ 2 6 9 52434.00 I   .180641  .000078   .513456  .000062  I -.2316492  .0000046 -0.3053 0.0042  I   -54.050     .247    -4.977     .103  0.180710  0.513450 -0.2316690   -53.800    -5.200  
+ 2 610 52435.00 I   .183530  .000090   .511787  .000067  I -.2312677  .0000068 -0.4556 0.0048  I   -54.114     .247    -5.253     .103  0.183570  0.511780 -0.2312790   -53.800    -5.300  
+ 2 611 52436.00 I   .186077  .000081   .509890  .000077  I -.2307375  .0000085 -0.6072 0.0054  I   -54.054     .173    -5.506     .340  0.186120  0.509890 -0.2307300   -53.800    -5.400  
+ 2 612 52437.00 I   .188424  .000085   .507805  .000080  I -.2300812  .0000083 -0.6750 0.0059  I   -54.008     .163    -5.620     .340  0.188420  0.507800 -0.2300660   -53.800    -5.500  
+ 2 613 52438.00 I   .190960  .000083   .505694  .000065  I -.2294015  .0000082 -0.7007 0.0058  I   -54.077     .163    -5.607     .340  0.190770  0.505750 -0.2293550   -53.900    -5.500  
+ 2 614 52439.00 I   .193075  .000086   .503992  .000071  I -.2287126  .0000081 -0.6280 0.0067  I   -54.204     .163    -5.568     .340  0.193220  0.503920 -0.2287030   -53.900    -5.500  
+ 2 615 52440.00 I   .195887  .000082   .502180  .000071  I -.2281968  .0000105 -0.4015 0.0054  I   -54.182     .221    -5.589     .340  0.195910  0.502180 -0.2282220   -53.700    -5.500  
+ 2 616 52441.00 I   .199050  .000072   .500101  .000063  I -.2279198  .0000072 -0.1445 0.0065  I   -53.994     .222    -5.603     .340  0.199100  0.500090 -0.2279630   -53.400    -5.500  
+ 2 617 52442.00 I   .202216  .000052   .497766  .000062  I -.2279049  .0000078  0.1038 0.0055  I   -53.706     .200    -5.541     .340  0.202290  0.497760 -0.2279310   -53.300    -5.500  
+ 2 618 52443.00 I   .204825  .000041   .495346  .000055  I -.2280920  .0000082  0.2461 0.0056  I   -53.574     .226    -5.371     .124  0.204940  0.495220 -0.2280790   -53.400    -5.400  
+ 2 619 52444.00 I   .207395  .000051   .492822  .000068  I -.2283708  .0000080  0.3097 0.0057  I   -53.810     .328    -5.149     .103  0.207500  0.492730 -0.2283380   -53.900    -5.200  
+ 2 620 52445.00 I   .210129  .000052   .490564  .000066  I -.2286949  .0000079  0.3240 0.0054  I   -54.417     .328    -4.970     .103  0.210240  0.490560 -0.2286600   -54.500    -5.000  
+ 2 621 52446.00 I   .212475  .000055   .488780  .000064  I -.2289991  .0000072  0.2792 0.0059  I   -55.163     .328    -4.896     .103  0.212630  0.488670 -0.2289890   -55.100    -4.800  
+ 2 622 52447.00 I   .214565  .000054   .486718  .000080  I -.2292301  .0000088  0.1649 0.0045  I   -55.677     .459    -4.937     .340  0.214630  0.486680 -0.2292480   -55.500    -4.700  
+ 2 623 52448.00 I   .216538  .000061   .484377  .000075  I -.2293139  .0000054  0.0058 0.0049  I   -55.889     .331    -4.997     .340  0.216550  0.484340 -0.2293260   -55.500    -4.700  
+ 2 624 52449.00 I   .218215  .000057   .481849  .000074  I -.2292565  .0000044 -0.1088 0.0032  I   -55.778     .331    -5.051     .340  0.218230  0.481840 -0.2292470   -55.300    -4.800  
+ 2 625 52450.00 I   .219488  .000047   .479106  .000056  I -.2291217  .0000036 -0.1472 0.0029  I   -55.532     .740    -5.117     .340  0.219580  0.479140 -0.2291160   -55.000    -5.000  
+ 2 626 52451.00 I   .220855  .000053   .476274  .000048  I -.2289744  .0000038 -0.1487 0.0026  I   -55.340     .178    -5.242     .140  0.220900  0.476260 -0.2289770   -54.800    -5.200  
+ 2 627 52452.00 I   .222495  .000050   .473233  .000048  I -.2288397  .0000038 -0.1040 0.0025  I   -55.293     .178    -5.406     .140  0.222530  0.473240 -0.2288370   -54.700    -5.500  
+ 2 628 52453.00 I   .224475  .000049   .470176  .000041  I -.2287886  .0000034  0.0072 0.0025  I   -55.398     .178    -5.518     .140  0.224420  0.470060 -0.2287840   -54.900    -5.600  
+ 2 629 52454.00 I   .225974  .000042   .467245  .000030  I -.2288471  .0000032  0.0974 0.0021  I   -55.673     .233    -5.563     .117  0.226010  0.467180 -0.2288750   -55.200    -5.700  
+ 2 630 52455.00 I   .227145  .000056   .464496  .000035  I -.2289808  .0000025  0.1799 0.0021  I   -55.957     .195    -5.524     .102  0.227260  0.464490 -0.2290160   -55.700    -5.600  
+ 2 7 1 52456.00 I   .228085  .000056   .461571  .000040  I -.2292183  .0000027  0.2966 0.0017  I   -56.223     .172    -5.510     .340  0.228170  0.461610 -0.2292270   -56.100    -5.400  
+ 2 7 2 52457.00 I   .228670  .000050   .458420  .000045  I -.2295755  .0000024  0.4177 0.0018  I   -56.422     .131    -5.490     .340  0.228800  0.458450 -0.2295720   -56.300    -5.300  
+ 2 7 3 52458.00 I   .229477  .000054   .455657  .000050  I -.2300230  .0000025  0.4468 0.0017  I   -56.604     .131    -5.365     .340  0.229470  0.455480 -0.2300200   -56.400    -5.300  
+ 2 7 4 52459.00 I   .229929  .000056   .452705  .000050  I -.2304413  .0000025  0.3926 0.0018  I   -56.916     .131    -5.120     .340  0.230020  0.452640 -0.2304250   -56.500    -5.300  
+ 2 7 5 52460.00 I   .230325  .000055   .449629  .000047  I -.2307979  .0000025  0.3073 0.0024  I   -57.440     .131    -4.873     .340  0.230440  0.449620 -0.2307870   -57.000    -5.300  
+ 2 7 6 52461.00 I   .230813  .000042   .446335  .000056  I -.2310385  .0000040  0.1696 0.0021  I   -58.055     .112    -4.771     .340  0.230840  0.446330 -0.2310450   -57.400    -5.300  
+ 2 7 7 52462.00 I   .231538  .000033   .442868  .000064  I -.2311346  .0000034  0.0245 0.0037  I   -58.514     .149    -4.874     .215  0.231560  0.442800 -0.2311160   -57.800    -5.300  
+ 2 7 8 52463.00 I   .232357  .000037   .439566  .000096  I -.2310913  .0000062 -0.1093 0.0034  I   -58.673     .149    -5.132     .215  0.232370  0.439500 -0.2310570   -58.200    -5.300  
+ 2 7 9 52464.00 I   .233101  .000043   .436299  .000090  I -.2309258  .0000060 -0.2139 0.0042  I   -58.599     .440    -5.431     .182  0.233070  0.436310 -0.2309210   -58.400    -5.300  
+ 2 710 52465.00 I   .234036  .000040   .433127  .000093  I -.2306797  .0000058 -0.2699 0.0042  I   -58.451     .427    -5.639     .150  0.234030  0.433250 -0.2306780   -58.300    -5.300  
+ 2 711 52466.00 I   .235477  .000040   .430263  .000093  I -.2304023  .0000058 -0.2769 0.0040  I   -58.317     .427    -5.675     .150  0.235400  0.430340 -0.2303350   -58.000    -5.400  
+ 2 712 52467.00 I   .236735  .000037   .427399  .000091  I -.2301805  .0000056 -0.1201 0.0045  I   -58.212     .427    -5.573     .150  0.236820  0.427380 -0.2301690   -57.800    -5.400  
+ 2 713 52468.00 I   .238121  .000045   .424430  .000081  I -.2301960  .0000068  0.1383 0.0038  I   -58.224     .449    -5.447     .171  0.238100  0.424380 -0.2302190   -57.600    -5.500  
+ 2 714 52469.00 I   .239167  .000063   .421365  .000053  I -.2304459  .0000051  0.3633 0.0047  I   -58.244     .421    -5.392     .340  0.239200  0.421320 -0.2304620   -57.700    -5.500  
+ 2 715 52470.00 I   .240194  .000061   .418308  .000040  I -.2309062  .0000064  0.5393 0.0039  I   -58.353     .338    -5.388     .340  0.240220  0.418270 -0.2308980   -57.900    -5.400  
+ 2 716 52471.00 I   .241186  .000066   .415505  .000037  I -.2314847  .0000060  0.5958 0.0041  I   -58.531     .121    -5.362     .340  0.241160  0.415450 -0.2314830   -58.200    -5.300  
+ 2 717 52472.00 I   .241880  .000062   .412784  .000043  I -.2320585  .0000050  0.5343 0.0039  I   -58.784     .150    -5.277     .109  0.241970  0.412750 -0.2320660   -58.500    -5.300  
+ 2 718 52473.00 I   .242880  .000069   .410344  .000044  I -.2325272  .0000050  0.3944 0.0035  I   -59.135     .150    -5.159     .109  0.242950  0.410280 -0.2324960   -58.800    -5.200  
+ 2 719 52474.00 I   .244016  .000068   .408159  .000041  I -.2328183  .0000049  0.1674 0.0036  I   -59.570     .150    -5.056     .109  0.243920  0.408040 -0.2328090   -59.100    -5.200  
+ 2 720 52475.00 I   .244296  .000055   .405615  .000045  I -.2328375  .0000052 -0.1331 0.0030  I   -59.978     .173    -5.050     .105  0.244380  0.405560 -0.2328360   -59.400    -5.100  
+ 2 721 52476.00 I   .244742  .000064   .402725  .000054  I -.2325613  .0000034 -0.4061 0.0031  I   -60.203     .201    -5.063     .340  0.244780  0.402680 -0.2325410   -59.700    -5.100  
+ 2 722 52477.00 I   .245495  .000067   .399749  .000060  I -.2320551  .0000034 -0.5896 0.0022  I   -60.157     .201    -5.150     .340  0.245540  0.399670 -0.2320260   -59.900    -5.100  
+ 2 723 52478.00 I   .246117  .000050   .396855  .000064  I -.2314115  .0000029 -0.6850 0.0022  I   -59.923     .242    -5.304     .340  0.246260  0.396850 -0.2314050   -59.800    -5.100  
+ 2 724 52479.00 I   .246666  .000063   .394095  .000071  I -.2307041  .0000029 -0.7235 0.0021  I   -59.694     .310    -5.477     .340  0.246670  0.394040 -0.2307260   -59.600    -5.200  
+ 2 725 52480.00 I   .246900  .000063   .391189  .000074  I -.2299998  .0000030 -0.6562 0.0021  I   -59.614     .310    -5.580     .340  0.246940  0.391050 -0.2300230   -59.200    -5.300  
+ 2 726 52481.00 I   .246744  .000068   .387877  .000069  I -.2294179  .0000030 -0.5102 0.0020  I   -59.699     .310    -5.544     .340  0.246920  0.387830 -0.2294130   -58.900    -5.400  
+ 2 727 52482.00 I   .246820  .000061   .384346  .000072  I -.2289761  .0000027 -0.3739 0.0020  I   -59.932     .349    -5.396     .340  0.246880  0.384320 -0.2289960   -58.700    -5.400  
+ 2 728 52483.00 I   .247096  .000068   .380592  .000076  I -.2286673  .0000025 -0.2460 0.0020  I   -60.218     .362    -5.262     .340  0.247190  0.380540 -0.2287050   -58.700    -5.300  
+ 2 729 52484.00 I   .247619  .000080   .376810  .000076  I -.2284689  .0000030 -0.1638 0.0019  I   -60.495     .412    -5.219     .340  0.247690  0.376780 -0.2284900   -59.000    -5.200  
+ 2 730 52485.00 I   .248459  .000054   .373119  .000067  I -.2283114  .0000029 -0.1664 0.0020  I   -60.621     .386    -5.202     .340  0.248530  0.373170 -0.2283280   -59.500    -5.100  
+ 2 731 52486.00 I   .249767  .000055   .369842  .000075  I -.2281178  .0000025 -0.2239 0.0019  I   -60.603     .462    -5.096     .119  0.249840  0.369800 -0.2281490   -60.200    -5.100  
+ 2 8 1 52487.00 I   .251195  .000055   .366848  .000072  I -.2278583  .0000025 -0.2971 0.0018  I   -60.708     .462    -4.915     .119  0.251250  0.366800 -0.2278600   -60.800    -5.000  
+ 2 8 2 52488.00 I   .252209  .000059   .364110  .000067  I -.2275238  .0000025 -0.3695 0.0024  I   -61.195     .462    -4.807     .119  0.252240  0.364080 -0.2275160   -61.400    -5.000  
+ 2 8 3 52489.00 I   .252951  .000045   .361548  .000041  I -.2271092  .0000042 -0.4721 0.0023  I   -61.936     .527    -4.876     .167  0.253020  0.361480 -0.2271160   -61.600    -5.100  
+ 2 8 4 52490.00 I   .253921  .000054   .358980  .000054  I -.2265683  .0000038 -0.6085 0.0028  I   -62.484     .559    -5.071     .141  0.253980  0.358920 -0.2265870   -61.700    -5.200  
+ 2 8 5 52491.00 I   .254925  .000055   .356325  .000053  I -.2259038  .0000036 -0.7099 0.0028  I   -62.551     .559    -5.284     .141  0.254980  0.356280 -0.2259130   -61.500    -5.300  
+ 2 8 6 52492.00 I   .255633  .000053   .353419  .000054  I -.2251723  .0000040 -0.7399 0.0026  I   -62.268     .590    -5.471     .107  0.255770  0.353310 -0.2251650   -61.200    -5.400  
+ 2 8 7 52493.00 I   .256726  .000055   .350230  .000068  I -.2244566  .0000038 -0.6723 0.0028  I   -61.992     .584    -5.630     .172  0.256720  0.350180 -0.2244500   -60.900    -5.400  
+ 2 8 8 52494.00 I   .257858  .000050   .347410  .000068  I -.2238681  .0000038 -0.4836 0.0025  I   -61.705     .584    -5.649     .172  0.257930  0.347350 -0.2238700   -60.700    -5.300  
+ 2 8 9 52495.00 I   .259013  .000051   .344903  .000071  I -.2235232  .0000032 -0.1934 0.0033  I   -61.472     .584    -5.498     .172  0.259060  0.344730 -0.2235210   -60.600    -5.300  
+ 2 810 52496.00 I   .259881  .000040   .342253  .000065  I -.2234895  .0000053  0.1214 0.0033  I   -61.376     .504    -5.272     .209  0.259930  0.342210 -0.2235000   -60.900    -5.200  
+ 2 811 52497.00 I   .260387  .000055   .339692  .000080  I -.2237494  .0000057  0.3863 0.0039  I   -61.547     .426    -5.161     .194  0.260430  0.339680 -0.2237760   -61.300    -5.200  
+ 2 812 52498.00 I   .260493  .000057   .336844  .000081  I -.2242302  .0000056  0.5554 0.0043  I   -61.955     .426    -5.238     .194  0.260510  0.336830 -0.2242470   -61.800    -5.200  
+ 2 813 52499.00 I   .260687  .000060   .333646  .000067  I -.2248094  .0000065  0.5720 0.0042  I   -62.386     .331    -5.385     .178  0.260660  0.333730 -0.2248020   -62.300    -5.200  
+ 2 814 52500.00 I   .260828  .000066   .330859  .000060  I -.2253333  .0000062  0.4658 0.0045  I   -62.664     .354    -5.440     .131  0.260880  0.330800 -0.2253290   -62.600    -5.200  
+ 2 815 52501.00 I   .260774  .000076   .328167  .000060  I -.2257140  .0000063  0.2786 0.0039  I   -62.794     .354    -5.369     .131  0.260800  0.328160 -0.2257190   -62.800    -5.200  
+ 2 816 52502.00 I   .260540  .000071   .325597  .000060  I -.2258714  .0000048  0.0340 0.0040  I   -62.898     .354    -5.259     .131  0.260590  0.325560 -0.2258670   -62.700    -5.300  
+ 2 817 52503.00 I   .260229  .000064   .322975  .000040  I -.2257922  .0000049 -0.1799 0.0031  I   -63.109     .336    -5.181     .340  0.260270  0.322960 -0.2258040   -62.600    -5.300  
+ 2 818 52504.00 I   .259728  .000064   .320286  .000048  I -.2255360  .0000039 -0.3204 0.0034  I   -63.271     .295    -5.171     .340  0.259760  0.320270 -0.2255640   -62.600    -5.300  
+ 2 819 52505.00 I   .259106  .000058   .317546  .000044  I -.2251760  .0000046 -0.3871 0.0028  I   -63.295     .295    -5.225     .340  0.259100  0.317490 -0.2251930   -62.500    -5.300  
+ 2 820 52506.00 I   .258503  .000059   .314720  .000047  I -.2247865  .0000041 -0.3797 0.0030  I   -63.114     .246    -5.344     .340  0.258500  0.314620 -0.2247810   -62.500    -5.300  
+ 2 821 52507.00 I   .257794  .000052   .311720  .000050  I -.2244519  .0000039 -0.2664 0.0028  I   -62.800     .214    -5.503     .340  0.257860  0.311680 -0.2244460   -62.500    -5.400  
+ 2 822 52508.00 I   .257201  .000051   .308634  .000050  I -.2242797  .0000039 -0.0752 0.0027  I   -62.594     .214    -5.530     .340  0.257220  0.308630 -0.2242690   -62.500    -5.300  
+ 2 823 52509.00 I   .256792  .000051   .305386  .000045  I -.2242788  .0000036  0.0478 0.0030  I   -62.554     .214    -5.346     .340  0.256760  0.305340 -0.2242730   -62.600    -5.300  
+ 2 824 52510.00 I   .256222  .000040   .302075  .000030  I -.2243658  .0000045  0.1422 0.0025  I   -62.624     .223    -5.006     .340  0.256260  0.302050 -0.2243560   -62.500    -5.100  
+ 2 825 52511.00 I   .255523  .000041   .298675  .000044  I -.2245688  .0000035  0.2534 0.0029  I   -62.760     .187    -4.726     .340  0.255550  0.298650 -0.2245560   -62.400    -5.000  
+ 2 826 52512.00 I   .254858  .000039   .295170  .000043  I -.2248545  .0000035  0.3102 0.0024  I   -62.855     .187    -4.640     .340  0.254880  0.295130 -0.2248520   -62.400    -4.800  
+ 2 827 52513.00 I   .254463  .000040   .291714  .000051  I -.2251742  .0000034  0.3218 0.0023  I   -62.799     .143    -4.680     .340  0.254570  0.291610 -0.2251720   -62.300    -4.700  
+ 2 828 52514.00 I   .254529  .000033   .288453  .000053  I -.2254807  .0000031  0.2811 0.0023  I   -62.610     .105    -4.689     .340  0.254600  0.288320 -0.2254850   -62.400    -4.600  
+ 2 829 52515.00 I   .254519  .000036   .285396  .000053  I -.2257157  .0000032  0.1784 0.0022  I   -62.614     .140    -4.648     .340  0.254560  0.285420 -0.2257490   -62.500    -4.600  
+ 2 830 52516.00 I   .254091  .000033   .282309  .000058  I -.2258262  .0000030  0.0419 0.0023  I   -63.009     .140    -4.718     .340  0.254150  0.282230 -0.2258220   -62.700    -4.700  
+ 2 831 52517.00 I   .253545  .000028   .279192  .000059  I -.2258030  .0000034 -0.0841 0.0028  I   -63.710     .740    -4.964     .340  0.253570  0.279080 -0.2258010   -62.800    -4.800  
+ 2 9 1 52518.00 I   .252756  .000028   .276056  .000060  I -.2256657  .0000047 -0.1871 0.0032  I   -64.185     .740    -5.236     .340  0.252800  0.276040 -0.2256610   -62.900    -4.900  
+ 2 9 2 52519.00 I   .251578  .000042   .272855  .000063  I -.2254402  .0000055 -0.2560 0.0041  I   -64.067     .740    -5.341     .340  0.251620  0.272820 -0.2254090   -62.800    -5.100  
+ 2 9 3 52520.00 I   .250129  .000052   .269689  .000070  I -.2251797  .0000067 -0.2468 0.0042  I   -63.531     .238    -5.274     .132  0.250140  0.269660 -0.2251190   -62.700    -5.100  
+ 2 9 4 52521.00 I   .248953  .000054   .266676  .000066  I -.2249860  .0000064 -0.1192 0.0046  I   -63.001     .233    -5.163     .175  0.248990  0.266590 -0.2249760   -62.600    -5.100  
+ 2 9 5 52522.00 I   .248303  .000058   .263660  .000068  I -.2249649  .0000064  0.0792 0.0045  I   -62.677     .233    -5.043     .175  0.248290  0.263550 -0.2249850   -62.500    -5.000  
+ 2 9 6 52523.00 I   .247358  .000064   .260693  .000059  I -.2251708  .0000062  0.3568 0.0043  I   -62.523     .233    -4.839     .175  0.247480  0.260610 -0.2251690   -62.600    -4.900  
+ 2 9 7 52524.00 I   .246202  .000078   .258028  .000064  I -.2257018  .0000057  0.7042 0.0042  I   -62.544     .233    -4.586     .175  0.246250  0.257990 -0.2256930   -62.800    -4.900  
+ 2 9 8 52525.00 I   .244623  .000075   .255658  .000047  I -.2265511  .0000056  0.9673 0.0040  I   -62.801     .239    -4.485     .170  0.244650  0.255640 -0.2265270   -62.900    -4.900  
+ 2 9 9 52526.00 I   .242763  .000070   .253201  .000041  I -.2275770  .0000056  1.0521 0.0042  I   -63.210     .172    -4.652     .172  0.242770  0.253220 -0.2275570   -63.000    -4.900  
+ 2 910 52527.00 I   .241036  .000074   .250576  .000074  I -.2285921  .0000062  0.9474 0.0038  I   -63.549     .650    -4.924     .340  0.241050  0.250530 -0.2286070   -63.100    -4.900  
+ 2 911 52528.00 I   .239272  .000075   .248027  .000075  I -.2294206  .0000052  0.6893 0.0040  I   -63.692     .544    -5.056     .340  0.239380  0.247960 -0.2294510   -63.300    -4.900  
+ 2 912 52529.00 I   .237442  .000068   .245443  .000075  I -.2299704  .0000052  0.4304 0.0036  I   -63.689     .544    -4.974     .340  0.237550  0.245520 -0.2299690   -63.400    -4.900  
+ 2 913 52530.00 I   .235727  .000062   .242781  .000069  I -.2303005  .0000051  0.2288 0.0032  I   -63.661     .544    -4.873     .340  0.235820  0.242720 -0.2302950   -63.400    -4.900  
+ 2 914 52531.00 I   .234195  .000049   .239697  .000073  I -.2304384  .0000038  0.0584 0.0029  I   -63.678     .663    -4.891     .106  0.234230  0.239620 -0.2304410   -63.300    -4.900  
+ 2 915 52532.00 I   .232872  .000048   .236809  .000070  I -.2304447  .0000028 -0.0298 0.0024  I   -63.738     .549    -4.972     .340  0.232900  0.236760 -0.2304400   -63.300    -4.900  
+ 2 916 52533.00 I   .231666  .000046   .234534  .000049  I -.2304053  .0000029 -0.0383 0.0022  I   -63.764     .165    -5.008     .340  0.231690  0.234540 -0.2303880   -63.100    -4.900  
+ 2 917 52534.00 I   .230134  .000044   .232605  .000039  I -.2303821  .0000033 -0.0046 0.0023  I   -63.641     .125    -4.999     .340  0.230150  0.232650 -0.2303780   -62.900    -4.800  
+ 2 918 52535.00 I   .227992  .000045   .230846  .000039  I -.2304091  .0000036  0.0681 0.0024  I   -63.353     .190    -4.995     .340  0.228000  0.230880 -0.2304330   -62.800    -4.800  
+ 2 919 52536.00 I   .225292  .000045   .229151  .000036  I -.2305297  .0000036  0.1751 0.0025  I   -63.037     .190    -4.949     .340  0.225360  0.229150 -0.2305380   -62.600    -4.700  
+ 2 920 52537.00 I   .222316  .000045   .227178  .000037  I -.2307597  .0000034  0.2835 0.0030  I   -62.845     .190    -4.740     .340  0.222380  0.227190 -0.2307560   -62.500    -4.600  
+ 2 921 52538.00 I   .219435  .000041   .224964  .000036  I -.2310915  .0000049  0.3763 0.0027  I   -62.688     .176    -4.357     .340  0.219440  0.224910 -0.2310880   -62.400    -4.400  
+ 2 922 52539.00 I   .216745  .000051   .222702  .000050  I -.2315018  .0000042  0.4375 0.0036  I   -62.654     .203    -4.030     .340  0.216770  0.222670 -0.2314890   -62.200    -4.300  
+ 2 923 52540.00 I   .214368  .000050   .220362  .000050  I -.2319528  .0000054  0.4577 0.0031  I   -62.560     .203    -3.932     .340  0.214380  0.220350 -0.2319350   -62.100    -4.100  
+ 2 924 52541.00 I   .212100  .000045   .217747  .000053  I -.2323967  .0000045  0.4166 0.0036  I   -62.376     .273    -4.040     .114  0.212310  0.217770 -0.2323930   -61.900    -4.100  
+ 2 925 52542.00 I   .210452  .000047   .215446  .000060  I -.2327672  .0000048  0.3192 0.0033  I   -62.154     .273    -4.177     .103  0.210510  0.215420 -0.2327630   -61.700    -4.100  
+ 2 926 52543.00 I   .208767  .000051   .213100  .000059  I -.2330159  .0000048  0.1643 0.0033  I   -62.067     .273    -4.266     .103  0.208750  0.213110 -0.2329580   -61.600    -4.200  
+ 2 927 52544.00 I   .206775  .000049   .210842  .000060  I -.2331152  .0000045  0.0676 0.0035  I   -62.297     .273    -4.404     .103  0.206800  0.210720 -0.2330990   -61.600    -4.400  
+ 2 928 52545.00 I   .204745  .000034   .208471  .000052  I -.2331567  .0000050 -0.0121 0.0030  I   -62.746     .297    -4.656     .340  0.204730  0.208400 -0.2332060   -61.700    -4.500  
+ 2 929 52546.00 I   .202677  .000043   .205888  .000058  I -.2330781  .0000041 -0.1304 0.0042  I   -63.007     .264    -4.880     .340  0.202690  0.205880 -0.2331410   -61.800    -4.600  
+ 2 930 52547.00 I   .200592  .000049   .203187  .000058  I -.2329247  .0000068 -0.1624 0.0033  I   -62.773     .231    -4.869     .340  0.200580  0.203140 -0.2329430   -61.800    -4.600  
+ 210 1 52548.00 I   .198430  .000053   .200445  .000053  I -.2327953  .0000052 -0.0683 0.0041  I   -62.175     .179    -4.617     .340  0.198520  0.200480 -0.2328000   -61.800    -4.500  
+ 210 2 52549.00 I   .196564  .000055   .198099  .000057  I -.2328142  .0000045  0.1040 0.0034  I   -61.543     .142    -4.279     .106  0.196610  0.198090 -0.2328330   -61.500    -4.200  
+ 210 3 52550.00 I   .194659  .000053   .195695  .000059  I -.2330134  .0000045  0.3065 0.0031  I   -61.224     .142    -4.028     .106  0.194670  0.195650 -0.2330330   -61.200    -3.800  
+ 210 4 52551.00 I   .192452  .000050   .193467  .000053  I -.2334663  .0000042  0.6264 0.0034  I   -61.158     .142    -3.786     .106  0.192520  0.193410 -0.2334550   -61.000    -3.600  
+ 210 5 52552.00 I   .189854  .000047   .191374  .000046  I -.2342676  .0000051  0.9507 0.0028  I   -61.357     .126    -3.547     .132  0.189930  0.191370 -0.2343080   -60.900    -3.600  
+ 210 6 52553.00 I   .187313  .000042   .189304  .000053  I -.2353188  .0000037  1.1285 0.0033  I   -61.641     .106    -3.467     .116  0.187340  0.189270 -0.2353840   -61.000    -3.800  
+ 210 7 52554.00 I   .184951  .000051   .187197  .000066  I -.2364692  .0000042  1.1403 0.0032  I   -61.884     .740    -3.665     .106  0.184980  0.187140 -0.2364880   -61.200    -4.000  
+ 210 8 52555.00 I   .182522  .000046   .185011  .000070  I -.2375451  .0000053  0.9894 0.0032  I   -61.896     .740    -3.967     .340  0.182620  0.184970 -0.2375410   -61.500    -4.100  
+ 210 9 52556.00 I   .180036  .000055   .182676  .000067  I -.2384155  .0000048  0.7411 0.0036  I   -61.714     .740    -4.071     .340  0.180170  0.182730 -0.2384380   -61.600    -4.000  
+ 21010 52557.00 I   .177936  .000056   .180677  .000067  I -.2390205  .0000049  0.4722 0.0035  I   -61.543     .740    -3.931     .340  0.177910  0.180620 -0.2390100   -61.700    -3.800  
+ 21011 52558.00 I   .175524  .000057   .178743  .000064  I -.2393753  .0000050  0.2493 0.0038  I   -61.483     .740    -3.811     .340  0.175550  0.178830 -0.2393640   -61.600    -3.700  
+ 21012 52559.00 I   .173126  .000067   .176892  .000062  I -.2395524  .0000057  0.1262 0.0031  I   -61.469     .143    -3.917     .340  0.173160  0.176910 -0.2395600   -61.400    -3.700  
+ 21013 52560.00 I   .170913  .000055   .175068  .000054  I -.2396689  .0000038  0.1265 0.0040  I   -61.444     .160    -4.130     .110  0.170950  0.175020 -0.2396870   -61.200    -3.700  
+ 21014 52561.00 I   .168481  .000055   .173411  .000070  I -.2398339  .0000055  0.2121 0.0033  I   -61.408     .173    -4.193     .120  0.168490  0.173340 -0.2398360   -61.100    -3.800  
+ 21015 52562.00 I   .165852  .000049   .171533  .000064  I -.2401034  .0000053  0.3284 0.0035  I   -61.316     .186    -4.051     .147  0.165930  0.171640 -0.2400990   -60.900    -3.900  
+ 21016 52563.00 I   .163384  .000053   .170132  .000062  I -.2404951  .0000043  0.4578 0.0032  I   -61.189     .240    -3.878     .149  0.163530  0.170080 -0.2405390   -60.900    -3.900  
+ 21017 52564.00 I   .161183  .000053   .168869  .000058  I -.2410285  .0000037  0.6158 0.0027  I   -60.879     .230    -3.750     .150  0.161140  0.168790 -0.2410910   -60.800    -3.700  
+ 21018 52565.00 I   .158396  .000053   .167813  .000057  I -.2417084  .0000034  0.7188 0.0027  I   -60.641     .228    -3.602     .145  0.158390  0.167740 -0.2417050   -60.700    -3.500  
+ 21019 52566.00 I   .154524  .000049   .166697  .000051  I -.2424420  .0000039  0.7493 0.0023  I   -60.525     .156    -3.349     .133  0.154650  0.166660 -0.2424460   -60.600    -3.300  
+ 21020 52567.00 I   .150245  .000047   .165404  .000045  I -.2432013  .0000030  0.7626 0.0025  I   -60.432     .159    -3.074     .120  0.150440  0.165330 -0.2432310   -60.500    -3.100  
+ 21021 52568.00 I   .146611  .000056   .163868  .000047  I -.2439578  .0000032  0.7479 0.0023  I   -60.281     .176    -2.956     .115  0.146600  0.163910 -0.2439770   -60.300    -3.100  
+ 21022 52569.00 I   .143148  .000054   .162588  .000052  I -.2446889  .0000034  0.7088 0.0024  I   -60.108     .218    -3.046     .101  0.143220  0.162700 -0.2446860   -60.100    -3.100  
+ 21023 52570.00 I   .139888  .000054   .161306  .000057  I -.2453597  .0000035  0.6228 0.0025  I   -59.977     .205    -3.223     .340  0.139950  0.161420 -0.2453520   -60.000    -3.100  
+ 21024 52571.00 I   .136555  .000056   .160043  .000065  I -.2459212  .0000036  0.4971 0.0023  I   -59.916     .181    -3.365     .340  0.136600  0.159880 -0.2459250   -59.900    -3.200  
+ 21025 52572.00 I   .132959  .000059   .158365  .000065  I -.2463482  .0000031  0.3545 0.0023  I   -59.933     .171    -3.478     .340  0.133050  0.158470 -0.2463450   -59.900    -3.400  
+ 21026 52573.00 I   .129479  .000059   .156684  .000064  I -.2466410  .0000030  0.2445 0.0021  I   -60.121     .186    -3.625     .340  0.129500  0.156810 -0.2466280   -59.800    -3.500  
+ 21027 52574.00 I   .125826  .000049   .155193  .000067  I -.2468584  .0000029  0.1982 0.0021  I   -60.069     .179    -3.722     .340  0.125880  0.155240 -0.2468390   -59.600    -3.500  
+ 21028 52575.00 I   .122277  .000045   .154017  .000060  I -.2470415  .0000029  0.1641 0.0020  I   -59.781     .185    -3.670     .340  0.122280  0.153930 -0.2470170   -59.400    -3.500  
+ 21029 52576.00 I   .118729  .000043   .152877  .000050  I -.2472156  .0000027  0.2170 0.0019  I   -59.302     .212    -3.449     .104  0.118900  0.152880 -0.2472120   -59.000    -3.300  
+ 21030 52577.00 I   .115378  .000042   .152147  .000042  I -.2475286  .0000026  0.4292 0.0019  I   -58.829     .260    -3.171     .340  0.115420  0.152150 -0.2475260   -58.600    -3.100  
+ 21031 52578.00 I   .111554  .000040   .151452  .000041  I -.2480936  .0000026  0.7003 0.0019  I   -58.526     .263    -2.923     .340  0.111560  0.151430 -0.2480760   -58.200    -2.800  
+ 211 1 52579.00 I   .107456  .000041   .150724  .000037  I -.2489322  .0000027  0.9806 0.0026  I   -58.468     .263    -2.682     .340  0.107540  0.150700 -0.2489260   -58.100    -2.600  
+ 211 2 52580.00 I   .103551  .000058   .149991  .000053  I -.2500339  .0000046  1.1983 0.0028  I   -58.713     .270    -2.440     .340  0.103570  0.149990 -0.2500350   -58.200    -2.500  
+ 211 3 52581.00 I   .099863  .000070   .149384  .000076  I -.2512752  .0000049  1.2554 0.0037  I   -59.078     .262    -2.330     .340  0.099910  0.149380 -0.2512750   -58.500    -2.400  
+ 211 4 52582.00 I   .096363  .000098   .148926  .000092  I -.2525032  .0000058  1.1882 0.0047  I   -59.338     .244    -2.461     .101  0.096410  0.148870 -0.2524980   -58.700    -2.500  
+ 211 5 52583.00 I   .092454  .000103   .148083  .000102  I -.2535988  .0000080  0.9627 0.0046  I   -59.264     .168    -2.700     .108  0.092750  0.148250 -0.2535730   -58.900    -2.500  
+ 211 6 52584.00 I   .088989  .000093   .147567  .000097  I -.2544123  .0000072  0.6882 0.0053  I   -58.934     .181    -2.773     .340  0.088800  0.147510 -0.2544100   -58.800    -2.400  
+ 211 7 52585.00 I   .084733  .000092   .146842  .000097  I -.2549895  .0000071  0.4567 0.0048  I   -58.632     .181    -2.613     .340  0.084780  0.146840 -0.2549740   -58.500    -2.400  
+ 211 8 52586.00 I   .080605  .000091   .146169  .000104  I -.2553384  .0000064  0.2633 0.0046  I   -58.494     .181    -2.470     .340  0.080700  0.146110 -0.2553240   -58.100    -2.400  
+ 211 9 52587.00 I   .076653  .000088   .145400  .000075  I -.2555385  .0000059  0.1369 0.0041  I   -58.406     .210    -2.575     .340  0.076660  0.145430 -0.2555430   -57.700    -2.400  
+ 21110 52588.00 I   .072792  .000055   .144872  .000074  I -.2556375  .0000050  0.0863 0.0041  I   -58.265     .283    -2.822     .340  0.072840  0.144860 -0.2556750   -57.500    -2.400  
+ 21111 52589.00 I   .069204  .000055   .144512  .000072  I -.2557455  .0000056  0.1388 0.0038  I   -58.127     .283    -2.898     .340  0.069250  0.144500 -0.2557700   -57.400    -2.500  
+ 21112 52590.00 I   .065865  .000057   .144240  .000077  I -.2559352  .0000056  0.2514 0.0038  I   -58.043     .365    -2.689     .340  0.065950  0.144170 -0.2559250   -57.500    -2.500  
+ 21113 52591.00 I   .062931  .000074   .143850  .000080  I -.2562653  .0000050  0.4149 0.0038  I   -58.046     .266    -2.389     .103  0.063020  0.143850 -0.2562560   -57.600    -2.500  
+ 21114 52592.00 I   .059962  .000071   .143707  .000079  I -.2567568  .0000050  0.5539 0.0035  I   -57.926     .266    -2.198     .103  0.059990  0.143740 -0.2567520   -57.900    -2.400  
+ 21115 52593.00 I   .056305  .000067   .143674  .000082  I -.2573501  .0000049  0.6238 0.0044  I   -57.843     .266    -2.109     .103  0.056470  0.143620 -0.2573380   -58.000    -2.200  
+ 21116 52594.00 I   .052983  .000072   .143654  .000094  I -.2579905  .0000073  0.6522 0.0038  I   -57.837     .274    -1.975     .116  0.053070  0.143640 -0.2579920   -58.000    -2.000  
+ 21117 52595.00 I   .049731  .000071   .143605  .000106  I -.2586403  .0000057  0.6382 0.0048  I   -57.825     .231    -1.757     .340  0.049760  0.143600 -0.2586500   -57.800    -1.700  
+ 21118 52596.00 I   .046266  .000075   .143164  .000109  I -.2592524  .0000063  0.5806 0.0046  I   -57.751     .231    -1.586     .340  0.046290  0.143150 -0.2592520   -57.500    -1.600  
+ 21119 52597.00 I   .042668  .000066   .142504  .000111  I -.2597790  .0000072  0.4556 0.0046  I   -57.685     .341    -1.590     .340  0.042760  0.142590 -0.2597580   -57.200    -1.600  
+ 21120 52598.00 I   .039023  .000068   .142080  .000100  I -.2601516  .0000066  0.2946 0.0049  I   -57.693     .440    -1.754     .125  0.039060  0.142050 -0.2601350   -57.000    -1.700  
+ 21121 52599.00 I   .035643  .000069   .141645  .000099  I -.2603927  .0000066  0.2072 0.0045  I   -57.695     .440    -1.957     .125  0.035610  0.141620 -0.2603750   -56.800    -1.900  
+ 21122 52600.00 I   .032382  .000070   .141439  .000086  I -.2605844  .0000062  0.1752 0.0047  I   -57.564     .440    -2.096     .125  0.032530  0.141440 -0.2605540   -56.700    -2.100  
+ 21123 52601.00 I   .029455  .000060   .141705  .000056  I -.2607451  .0000067  0.1493 0.0039  I   -57.270     .518    -2.145     .340  0.029500  0.141590 -0.2607550   -56.600    -2.200  
+ 21124 52602.00 I   .026278  .000057   .141919  .000061  I -.2609050  .0000047  0.1894 0.0040  I   -56.936     .422    -2.143     .340  0.026290  0.141920 -0.2609170   -56.600    -2.200  
+ 21125 52603.00 I   .023146  .000053   .142072  .000060  I -.2611561  .0000042  0.3263 0.0032  I   -56.599     .389    -2.102     .340  0.023140  0.142090 -0.2611320   -56.500    -2.100  
+ 21126 52604.00 I   .020419  .000036   .142111  .000058  I -.2615777  .0000042  0.5237 0.0030  I   -56.262     .228    -2.032     .340  0.020440  0.142180 -0.2615560   -56.400    -2.000  
+ 21127 52605.00 I   .017702  .000038   .141972  .000056  I -.2622236  .0000042  0.7814 0.0030  I   -55.941     .228    -1.938     .340  0.017780  0.141910 -0.2622010   -56.300    -2.000  
+ 21128 52606.00 I   .014598  .000038   .141668  .000055  I -.2631419  .0000042  1.0434 0.0029  I   -55.707     .228    -1.807     .340  0.014610  0.141600 -0.2631340   -56.300    -1.800  
+ 21129 52607.00 I   .011103  .000038   .141506  .000058  I -.2642958  .0000041  1.2617 0.0040  I   -55.671     .228    -1.616     .340  0.011120  0.141530 -0.2642190   -56.300    -1.600  
+ 21130 52608.00 I   .007579  .000035   .141384  .000061  I -.2656414  .0000067  1.4082 0.0024  I   -56.053     .199    -1.385     .340  0.007650  0.141380 -0.2655300   -56.300    -1.300  
+ 212 1 52609.00 I   .004190  .000043   .141181  .000057  I -.2670650  .0000023  1.4130 0.0036  I   -56.523     .273    -1.234     .340  0.004230  0.141160 -0.2669760   -56.400    -1.100  
+ 212 2 52610.00 I   .000976  .000043   .141175  .000064  I -.2684199  .0000028  1.2753 0.0028  I   -56.957     .273    -1.261     .340  0.000980  0.141150 -0.2683720   -56.700    -1.500  
+ 212 3 52611.00 I  -.002188  .000055   .141366  .000082  I -.2695781  .0000050  1.0250 0.0027  I   -57.095     .366    -1.407     .340 -0.002100  0.141540 -0.2695620   -56.800    -1.400  
+ 212 4 52612.00 I  -.005190  .000058   .142182  .000082  I -.2704599  .0000046  0.7448 0.0034  I   -56.926     .353    -1.485     .340 -0.005140  0.142250 -0.2704590   -56.600    -1.300  
+ 212 5 52613.00 I  -.008410  .000060   .143068  .000080  I -.2710687  .0000046  0.4678 0.0033  I   -56.663     .353    -1.411     .340 -0.008540  0.143130 -0.2710520   -56.300    -1.300  
+ 212 6 52614.00 I  -.012360  .000066   .144207  .000078  I -.2714357  .0000046  0.3116 0.0041  I   -56.452     .353    -1.326     .340 -0.012430  0.144160 -0.2714150   -55.900    -1.300  
+ 212 7 52615.00 I  -.016720  .000076   .145538  .000076  I -.2717517  .0000068  0.3349 0.0036  I   -56.242     .350    -1.406     .340 -0.016710  0.145520 -0.2717620   -55.600    -1.300  
+ 212 8 52616.00 I  -.020888  .000062   .146709  .000092  I -.2721330  .0000056  0.4408 0.0047  I   -55.972     .301    -1.596     .340 -0.020860  0.146750 -0.2721450   -55.500    -1.400  
+ 212 9 52617.00 I  -.024269  .000055   .147737  .000096  I -.2726535  .0000065  0.6073 0.0038  I   -55.727     .327    -1.660     .340 -0.024190  0.147790 -0.2726310   -55.500    -1.400  
+ 21210 52618.00 I  -.027099  .000052   .149028  .000066  I -.2733480  .0000050  0.7750 0.0041  I   -55.631     .145    -1.480     .340 -0.027050  0.149110 -0.2733250   -55.600    -1.400  
+ 21211 52619.00 I  -.030097  .000054   .150624  .000068  I -.2742030  .0000049  0.9413 0.0035  I   -55.665     .147    -1.203     .340 -0.029990  0.150660 -0.2742050   -55.700    -1.300  
+ 21212 52620.00 I  -.032910  .000054   .152253  .000070  I -.2751980  .0000049  1.0100 0.0034  I   -55.794     .147    -1.033     .340 -0.032910  0.152320 -0.2751850   -55.700    -1.200  
+ 21213 52621.00 I  -.036521  .000056   .153643  .000074  I -.2762097  .0000048  1.0389 0.0040  I   -55.943     .147     -.985     .340 -0.036380  0.153690 -0.2762010   -55.700    -1.000  
+ 21214 52622.00 I  -.040135  .000058   .154901  .000064  I -.2772696  .0000063  1.0493 0.0037  I   -56.075     .163     -.905     .340 -0.040130  0.154810 -0.2772850   -55.800    -0.800  
+ 21215 52623.00 I  -.044170  .000055   .155905  .000084  I -.2782719  .0000057  0.9506 0.0045  I   -56.135     .258     -.706     .340 -0.044120  0.155800 -0.2783150   -55.800    -0.600  
+ 21216 52624.00 I  -.048085  .000063   .156669  .000091  I -.2791553  .0000064  0.8055 0.0042  I   -56.122     .243     -.487     .340 -0.048100  0.156550 -0.2791780   -55.900    -0.400  
+ 21217 52625.00 I  -.051623  .000048   .157274  .000096  I -.2798786  .0000063  0.6475 0.0043  I   -56.130     .372     -.424     .340 -0.051560  0.157350 -0.2798630   -56.000    -0.500  
+ 21218 52626.00 I  -.054557  .000068   .158497  .000091  I -.2804448  .0000058  0.4730 0.0043  I   -56.238     .301     -.580     .340 -0.054500  0.158360 -0.2804270   -56.000    -0.600  
+ 21219 52627.00 I  -.056950  .000064   .159883  .000092  I -.2808192  .0000060  0.2824 0.0040  I   -56.288     .301     -.884     .340 -0.056950  0.159770 -0.2808220   -56.000    -0.800  
+ 21220 52628.00 I  -.059147  .000061   .161774  .000082  I -.2810419  .0000055  0.1889 0.0042  I   -56.129     .301    -1.142     .340 -0.059110  0.161760 -0.2810310   -55.900    -1.100  
+ 21221 52629.00 I  -.061584  .000055   .164084  .000047  I -.2812224  .0000058  0.1718 0.0041  I   -55.769     .274    -1.188     .340 -0.061540  0.164060 -0.2812280   -55.600    -1.300  
+ 21222 52630.00 I  -.064259  .000063   .166441  .000043  I -.2813994  .0000062  0.1965 0.0042  I   -55.283     .274    -1.132     .340 -0.064250  0.166410 -0.2814080   -55.000    -1.400  
+ 21223 52631.00 I  -.066758  .000059   .168646  .000046  I -.2816508  .0000061  0.3274 0.0110  I   -54.871     .104    -1.044     .340 -0.066770  0.168630 -0.2816380   -54.400    -1.500  
+ 21224 52632.00 I  -.069104  .000042   .170874  .000042  I -.2820935  .0000212  0.5763 0.0095  I   -54.583     .740    -1.015     .340 -0.069100  0.170830 -0.2820620   -53.900    -1.400  
+ 21225 52633.00 I  -.071648  .000041   .173153  .000039  I -.2828125  .0000180  0.8527 0.0135  I   -54.399     .740    -1.032     .340 -0.071640  0.173150 -0.2827880   -53.500    -1.300  
+ 21226 52634.00 I  -.074203  .000041   .175133  .000034  I -.2837772  .0000166  1.0642 0.0097  I   -54.322     .740    -1.015     .340 -0.074230  0.175140 -0.2837740   -53.300    -1.100  
+ 21227 52635.00 I  -.076492  .000044   .176860  .000026  I -.2849084  .0000072  1.1783 0.0095  I   -54.406     .740     -.910     .340 -0.076500  0.176820 -0.2849120   -53.500    -0.900  
+ 21228 52636.00 I  -.078749  .000059   .178859  .000039  I -.2860947  .0000092  1.1751 0.0049  I   -54.548     .237     -.740     .121 -0.078730  0.178830 -0.2860920   -54.000    -0.700  
+ 21229 52637.00 I  -.081140  .000060   .181116  .000050  I -.2872199  .0000067  1.0558 0.0057  I   -54.991     .160     -.587     .108 -0.081160  0.181130 -0.2872110   -54.600    -0.500  
+ 21230 52638.00 I  -.083425  .000058   .183254  .000051  I -.2881773  .0000068  0.8494 0.0044  I   -55.413     .160     -.527     .108 -0.083470  0.183210 -0.2881680   -55.100    -0.400  
+ 21231 52639.00 I  -.085587  .000075   .185612  .000050  I -.2889136  .0000058  0.6277 0.0042  I   -55.626     .141     -.568     .340 -0.085710  0.185460 -0.2889120   -55.500    -0.400  
+ 3 1 1 52640.00 I  -.088506  .000087   .187936  .000054  I -.2894400  .0000050  0.4280 0.0038  I   -55.580     .132     -.644     .340 -0.088460  0.187930 -0.2894480   -55.500    -0.500  
+ 3 1 2 52641.00 I  -.091525  .000081   .190250  .000054  I -.2897971  .0000050  0.3107 0.0035  I   -55.381     .132     -.698     .340 -0.091550  0.190200 -0.2897920   -55.300    -0.600  
+ 3 1 3 52642.00 I  -.094535  .000063   .192681  .000051  I -.2901029  .0000050  0.3178 0.0037  I   -55.151     .132     -.756     .340 -0.094510  0.192640 -0.2900920   -54.900    -0.700  
+ 3 1 4 52643.00 I  -.097547  .000065   .195185  .000044  I -.2904422  .0000055  0.3533 0.0035  I   -54.916     .740     -.876     .340 -0.097560  0.195210 -0.2904570   -54.500    -0.800  
+ 3 1 5 52644.00 I  -.100674  .000059   .197402  .000045  I -.2908236  .0000050  0.4311 0.0038  I   -54.663     .740    -1.025     .340 -0.100680  0.197410 -0.2908460   -54.300    -0.900  
+ 3 1 6 52645.00 I  -.103497  .000061   .199315  .000044  I -.2913364  .0000051  0.6049 0.0034  I   -54.443     .740    -1.079     .340 -0.103540  0.199310 -0.2913490   -54.100    -1.000  
+ 3 1 7 52646.00 I  -.105918  .000043   .201164  .000043  I -.2920312  .0000047  0.7721 0.0035  I   -54.366     .186     -.977     .136 -0.105960  0.201290 -0.2920180   -54.100    -1.000  
+ 3 1 8 52647.00 I  -.108609  .000049   .203326  .000045  I -.2928525  .0000047  0.8551 0.0033  I   -54.485     .194     -.817     .141 -0.108520  0.203380 -0.2928610   -54.300    -1.000  
+ 3 1 9 52648.00 I  -.111066  .000052   .205508  .000044  I -.2937266  .0000047  0.8936 0.0034  I   -54.737     .194     -.733     .141 -0.111060  0.205470 -0.2937380   -54.500    -0.900  
+ 3 110 52649.00 I  -.113231  .000046   .207881  .000043  I -.2946374  .0000048  0.9252 0.0035  I   -54.991     .194     -.724     .141 -0.113170  0.207880 -0.2946290   -54.700    -0.800  
+ 3 111 52650.00 I  -.115263  .000036   .210338  .000038  I -.2955678  .0000052  0.9293 0.0033  I   -55.122     .120     -.632     .195 -0.115240  0.210360 -0.2955520   -54.800    -0.600  
+ 3 112 52651.00 I  -.117288  .000031   .212631  .000038  I -.2964717  .0000044  0.8607 0.0034  I   -55.163     .120     -.462     .171 -0.117260  0.212610 -0.2964480   -54.900    -0.400  
+ 3 113 52652.00 I  -.118995  .000036   .214760  .000036  I -.2972660  .0000045  0.7227 0.0032  I   -55.158     .120     -.272     .154 -0.119000  0.214730 -0.2972470   -54.900    -0.300  
+ 3 114 52653.00 I  -.120321  .000035   .216851  .000046  I -.2979152  .0000046  0.5791 0.0030  I   -55.190     .121     -.227     .210 -0.120310  0.216890 -0.2979030   -55.000    -0.300  
+ 3 115 52654.00 I  -.121679  .000033   .219146  .000044  I -.2984219  .0000039  0.4288 0.0029  I   -55.273     .121     -.412     .181 -0.121570  0.219120 -0.2984020   -55.100    -0.600  
+ 3 116 52655.00 I  -.122808  .000035   .221634  .000041  I -.2987735  .0000035  0.2806 0.0024  I   -55.330     .121     -.762     .181 -0.122870  0.221530 -0.2987500   -55.200    -0.900  
+ 3 117 52656.00 I  -.124297  .000038   .224033  .000040  I -.2990067  .0000029  0.2030 0.0025  I   -55.258     .122    -1.113     .340 -0.124280  0.224060 -0.2989930   -55.100    -1.100  
+ 3 118 52657.00 I  -.126047  .000045   .226509  .000041  I -.2992149  .0000037  0.2315 0.0024  I   -54.974     .137    -1.297     .340 -0.125980  0.226530 -0.2992100   -54.900    -1.300  
+ 3 119 52658.00 I  -.127673  .000043   .228811  .000045  I -.2994968  .0000039  0.3411 0.0028  I   -54.527     .132    -1.257     .340 -0.127580  0.228790 -0.2994690   -54.500    -1.300  
+ 3 120 52659.00 I  -.128873  .000038   .231030  .000050  I -.2999075  .0000043  0.4818 0.0039  I   -54.053     .168    -1.086     .340 -0.128840  0.231010 -0.2998440   -54.100    -1.100  
+ 3 121 52660.00 I  -.129940  .000051   .233478  .000061  I -.3004639  .0000067  0.6331 0.0042  I   -53.724     .287     -.943     .340 -0.129910  0.233420 -0.3004010   -53.700    -1.000  
+ 3 122 52661.00 I  -.131006  .000056   .236356  .000068  I -.3011699  .0000072  0.7731 0.0052  I   -53.649     .308     -.913     .110 -0.130970  0.236350 -0.3011540   -53.400    -0.900  
+ 3 123 52662.00 I  -.132220  .000052   .239582  .000070  I -.3019920  .0000079  0.8588 0.0052  I   -53.817     .308     -.956     .110 -0.132140  0.239610 -0.3020130   -53.400    -0.900  
+ 3 124 52663.00 I  -.133567  .000049   .242395  .000071  I -.3028736  .0000076  0.9028 0.0054  I   -54.132     .308     -.979     .110 -0.133540  0.242440 -0.3028670   -53.600    -0.900  
+ 3 125 52664.00 I  -.135144  .000051   .244806  .000067  I -.3037659  .0000073  0.8515 0.0048  I   -54.457     .283     -.916     .101 -0.135120  0.244810 -0.3037500   -53.900    -0.900  
+ 3 126 52665.00 I  -.136792  .000049   .247042  .000053  I -.3045278  .0000059  0.6536 0.0045  I   -54.774     .287     -.812     .115 -0.136780  0.247020 -0.3045260   -54.400    -0.800  
+ 3 127 52666.00 I  -.138126  .000042   .249381  .000044  I -.3050546  .0000053  0.4003 0.0038  I   -54.991     .287     -.705     .115 -0.138090  0.249450 -0.3050560   -54.700    -0.700  
+ 3 128 52667.00 I  -.138992  .000037   .252107  .000042  I -.3053340  .0000049  0.1640 0.0034  I   -55.045     .181     -.652     .104 -0.138880  0.252210 -0.3053250   -54.900    -0.700  
+ 3 129 52668.00 I  -.139269  .000049   .255088  .000043  I -.3054123  .0000043  0.0170 0.0033  I   -54.910     .153     -.689     .101 -0.139280  0.255170 -0.3054140   -54.800    -0.800  
+ 3 130 52669.00 I  -.139478  .000051   .258219  .000043  I -.3054011  .0000043 -0.0306 0.0029  I   -54.642     .167     -.837     .340 -0.139380  0.258240 -0.3053970   -54.500    -0.900  
+ 3 131 52670.00 I  -.139794  .000051   .261292  .000044  I -.3053653  .0000039 -0.0356 0.0036  I   -54.354     .167    -1.031     .340 -0.139870  0.261290 -0.3053620   -54.200    -1.100  
+ 3 2 1 52671.00 I  -.141155  .000059   .264059  .000065  I -.3053500  .0000057  0.0198 0.0031  I   -54.147     .116    -1.238     .340 -0.141130  0.264050 -0.3053730   -53.900    -1.200  
+ 3 2 2 52672.00 I  -.142642  .000061   .266788  .000072  I -.3054336  .0000047  0.1613 0.0035  I   -54.035     .125    -1.388     .340 -0.142570  0.266750 -0.3054490   -53.800    -1.200  
+ 3 2 3 52673.00 I  -.144127  .000075   .269650  .000076  I -.3056955  .0000040  0.3714 0.0030  I   -53.981     .125    -1.417     .340 -0.144090  0.269670 -0.3056800   -53.800    -1.200  
+ 3 2 4 52674.00 I  -.145231  .000062   .272399  .000079  I -.3061850  .0000036  0.6074 0.0027  I   -53.980     .251    -1.337     .340 -0.145260  0.272440 -0.3061760   -53.800    -1.200  
+ 3 2 5 52675.00 I  -.146060  .000059   .275320  .000074  I -.3068810  .0000035  0.7555 0.0025  I   -54.077     .227    -1.247     .340 -0.146160  0.275280 -0.3068960   -53.900    -1.200  
+ 3 2 6 52676.00 I  -.147316  .000056   .277939  .000075  I -.3076581  .0000036  0.7898 0.0025  I   -54.265     .227    -1.235     .340 -0.147270  0.278000 -0.3076810   -54.000    -1.200  
+ 3 2 7 52677.00 I  -.148426  .000054   .280393  .000067  I -.3084369  .0000035  0.7530 0.0027  I   -54.433     .227    -1.276     .340 -0.148390  0.280430 -0.3084350   -54.000    -1.200  
+ 3 2 8 52678.00 I  -.149667  .000055   .283189  .000061  I -.3091443  .0000041  0.6567 0.0025  I   -54.482     .268    -1.273     .340 -0.149610  0.283160 -0.3091510   -53.900    -1.200  
+ 3 2 9 52679.00 I  -.151304  .000036   .285945  .000063  I -.3097464  .0000035  0.5485 0.0029  I   -54.451     .296    -1.207     .340 -0.151270  0.285920 -0.3097880   -53.900    -1.100  
+ 3 210 52680.00 I  -.152949  .000036   .288612  .000061  I -.3102376  .0000040  0.4292 0.0030  I   -54.446     .273    -1.168     .340 -0.152910  0.288570 -0.3102810   -53.900    -1.100  
+ 3 211 52681.00 I  -.154297  .000048   .291302  .000062  I -.3106009  .0000049  0.2984 0.0030  I   -54.478     .472    -1.246     .162 -0.154280  0.291370 -0.3106030   -54.000    -1.300  
+ 3 212 52682.00 I  -.155365  .000055   .294094  .000057  I -.3108547  .0000045  0.2286 0.0034  I   -54.442     .411    -1.434     .152 -0.155300  0.294100 -0.3108090   -54.200    -1.500  
+ 3 213 52683.00 I  -.155875  .000057   .296851  .000058  I -.3110916  .0000046  0.2591 0.0032  I   -54.381     .411    -1.706     .152 -0.155910  0.296780 -0.3110340   -54.300    -1.900  
+ 3 214 52684.00 I  -.156091  .000060   .299473  .000055  I -.3113852  .0000046  0.3263 0.0035  I   -54.325     .411    -2.010     .152 -0.156160  0.299500 -0.3113730   -54.300    -2.100  
+ 3 215 52685.00 I  -.156343  .000059   .302128  .000032  I -.3117429  .0000053  0.3897 0.0034  I   -54.237     .465    -2.272     .193 -0.156320  0.302110 -0.3117780   -54.100    -2.200  
+ 3 216 52686.00 I  -.156302  .000073   .304583  .000039  I -.3121947  .0000049  0.5434 0.0034  I   -53.957     .439    -2.366     .176 -0.156290  0.304550 -0.3122450   -53.700    -2.100  
+ 3 217 52687.00 I  -.155862  .000062   .307063  .000046  I -.3128650  .0000041  0.8029 0.0029  I   -53.456     .155    -2.230     .118 -0.155780  0.307060 -0.3128800   -53.300    -1.900  
+ 3 218 52688.00 I  -.155323  .000064   .310072  .000049  I -.3137985  .0000031  1.0565 0.0024  I   -52.998     .186    -1.976     .340 -0.155280  0.310030 -0.3137900   -53.000    -1.800  
+ 3 219 52689.00 I  -.154911  .000071   .313488  .000054  I -.3149478  .0000026  1.2194 0.0020  I   -52.877     .231    -1.828     .340 -0.154890  0.313550 -0.3149440   -52.900    -1.700  
+ 3 220 52690.00 I  -.154784  .000069   .317584  .000051  I -.3161986  .0000025  1.2662 0.0018  I   -53.220     .231    -1.863     .340 -0.154700  0.317550 -0.3161840   -53.100    -1.900  
+ 3 221 52691.00 I  -.155311  .000071   .321366  .000048  I -.3174385  .0000025  1.1880 0.0021  I   -53.721     .231    -2.012     .340 -0.155090  0.321380 -0.3174310   -53.400    -2.000  
+ 3 222 52692.00 I  -.155475  .000071   .324475  .000045  I -.3185303  .0000033  0.9769 0.0020  I   -54.093     .229    -2.117     .340 -0.155490  0.324470 -0.3185360   -53.800    -2.100  
+ 3 223 52693.00 I  -.155454  .000070   .327396  .000056  I -.3193753  .0000030  0.7149 0.0023  I   -54.254     .180    -2.103     .340 -0.155400  0.327390 -0.3193890   -54.100    -2.000  
+ 3 224 52694.00 I  -.155123  .000065   .330443  .000054  I -.3199700  .0000031  0.4827 0.0023  I   -54.273     .180    -2.014     .340 -0.155070  0.330430 -0.3199750   -54.200    -2.000  
+ 3 225 52695.00 I  -.154614  .000047   .333493  .000050  I -.3203602  .0000035  0.3088 0.0025  I   -54.202     .200    -1.938     .340 -0.154650  0.333430 -0.3203540   -54.000    -1.900  
+ 3 226 52696.00 I  -.154637  .000045   .336386  .000053  I -.3206182  .0000038  0.2265 0.0026  I   -54.016     .240    -1.948     .102 -0.154530  0.336370 -0.3206160   -53.700    -1.900  
+ 3 227 52697.00 I  -.154656  .000045   .339306  .000059  I -.3208399  .0000038  0.2244 0.0025  I   -53.693     .240    -2.073     .102 -0.154610  0.339280 -0.3208330   -53.200    -2.000  
+ 3 228 52698.00 I  -.154375  .000041   .342141  .000060  I -.3210741  .0000032  0.2437 0.0039  I   -53.310     .240    -2.286     .102 -0.154360  0.342110 -0.3210690   -52.800    -2.200  
+ 3 3 1 52699.00 I  -.153841  .000023   .344649  .000029  I -.3213467  .0000067  0.3212 0.0027  I   -53.008     .295    -2.471     .105 -0.153800  0.344630 -0.3213410   -52.500    -2.200  
+ 3 3 2 52700.00 I  -.153198  .000024   .347240  .000031  I -.3217410  .0000043  0.4720 0.0042  I   -52.919     .277    -2.570     .340 -0.153150  0.347190 -0.3217350   -52.600    -2.300  
+ 3 3 3 52701.00 I  -.152880  .000024   .350202  .000029  I -.3222894  .0000050  0.6188 0.0034  I   -52.973     .277    -2.491     .340 -0.152810  0.350190 -0.3222940   -52.800    -2.300  
+ 3 3 4 52702.00 I  -.153092  .000026   .353080  .000025  I -.3229464  .0000052  0.6689 0.0036  I   -53.052     .211    -2.302     .340 -0.153040  0.353130 -0.3229420   -53.000    -2.200  
+ 3 3 5 52703.00 I  -.153422  .000036   .355842  .000018  I -.3236106  .0000051  0.6690 0.0036  I   -53.122     .307    -2.166     .340 -0.153370  0.355830 -0.3236090   -53.200    -2.200  
+ 3 3 6 52704.00 I  -.153763  .000039   .358316  .000018  I -.3242961  .0000051  0.7040 0.0035  I   -53.174     .307    -2.176     .340 -0.153700  0.358310 -0.3242970   -53.300    -2.200  
+ 3 3 7 52705.00 I  -.154354  .000038   .360787  .000017  I -.3250005  .0000048  0.6846 0.0039  I   -53.177     .307    -2.289     .340 -0.154090  0.360750 -0.3249950   -53.300    -2.200  
+ 3 3 8 52706.00 I  -.154534  .000047   .363477  .000020  I -.3256463  .0000059  0.6082 0.0032  I   -53.092     .300    -2.393     .340 -0.154490  0.363470 -0.3256600   -53.100    -2.300  
+ 3 3 9 52707.00 I  -.154768  .000044   .366339  .000024  I -.3262172  .0000043  0.5326 0.0036  I   -53.001     .255    -2.479     .340 -0.154690  0.366290 -0.3262470   -53.000    -2.400  
+ 3 310 52708.00 I  -.154911  .000043   .369337  .000029  I -.3267117  .0000041  0.4574 0.0027  I   -53.008     .255    -2.630     .340 -0.154860  0.369300 -0.3267360   -52.800    -2.600  
+ 3 311 52709.00 I  -.155587  .000042   .372368  .000040  I -.3271255  .0000034  0.3627 0.0027  I   -53.033     .184    -2.864     .111 -0.155520  0.372380 -0.3271240   -52.800    -2.700  
+ 3 312 52710.00 I  -.156437  .000052   .375474  .000041  I -.3274535  .0000034  0.3174 0.0024  I   -52.883     .184    -3.071     .101 -0.156400  0.375480 -0.3274420   -52.700    -2.900  
+ 3 313 52711.00 I  -.157026  .000054   .378713  .000041  I -.3277792  .0000034  0.3289 0.0023  I   -52.580     .184    -3.187     .101 -0.157030  0.378590 -0.3277560   -52.700    -3.100  
+ 3 314 52712.00 I  -.157691  .000058   .381330  .000041  I -.3281342  .0000032  0.4089 0.0024  I   -52.385     .184    -3.316     .101 -0.157290  0.381370 -0.3281250   -52.500    -3.300  
+ 3 315 52713.00 I  -.157076  .000065   .384012  .000042  I -.3286353  .0000034  0.6036 0.0021  I   -52.390     .181    -3.571     .340 -0.157110  0.384010 -0.3286480   -52.100    -3.400  
+ 3 316 52714.00 I  -.156943  .000073   .386870  .000040  I -.3293660  .0000028  0.8722 0.0025  I   -52.324     .157    -3.839     .340 -0.156910  0.386880 -0.3293890   -51.700    -3.500  
+ 3 317 52715.00 I  -.156743  .000078   .389761  .000063  I -.3303950  .0000036  1.1868 0.0021  I   -51.935     .168    -3.868     .340 -0.156650  0.389760 -0.3304080   -51.300    -3.600  
+ 3 318 52716.00 I  -.155936  .000066   .392624  .000065  I -.3317189  .0000032  1.4392 0.0023  I   -51.450     .115    -3.601     .114 -0.155950  0.392630 -0.3317120   -51.200    -3.600  
+ 3 319 52717.00 I  -.154945  .000064   .395674  .000066  I -.3332271  .0000030  1.5525 0.0022  I   -51.354     .740    -3.289     .340 -0.154890  0.395810 -0.3332170   -51.300    -3.600  
+ 3 320 52718.00 I  -.153875  .000060   .399566  .000065  I -.3347675  .0000029  1.4965 0.0020  I   -51.788     .740    -3.210     .340 -0.153840  0.399600 -0.3347600   -51.700    -3.500  
+ 3 321 52719.00 I  -.153268  .000057   .403517  .000069  I -.3361673  .0000026  1.2819 0.0019  I   -52.385     .740    -3.369     .340 -0.153080  0.403390 -0.3361610   -52.100    -3.500  
+ 3 322 52720.00 I  -.152322  .000046   .406664  .000083  I -.3373037  .0000026  0.9843 0.0019  I   -52.733     .740    -3.562     .340 -0.152280  0.406640 -0.3373110   -52.500    -3.500  
+ 3 323 52721.00 I  -.151525  .000051   .409589  .000049  I -.3381325  .0000027  0.6764 0.0019  I   -52.701     .740    -3.638     .340 -0.151440  0.409600 -0.3381530   -52.600    -3.500  
+ 3 324 52722.00 I  -.150576  .000048   .412494  .000048  I -.3386755  .0000028  0.4255 0.0021  I   -52.520     .740    -3.643     .340 -0.150480  0.412410 -0.3386950   -52.500    -3.500  
+ 3 325 52723.00 I  -.148982  .000039   .415439  .000048  I -.3390145  .0000033  0.2677 0.0022  I   -52.377     .740    -3.669     .340 -0.149060  0.415390 -0.3390110   -52.200    -3.600  
+ 3 326 52724.00 I  -.147578  .000046   .418309  .000058  I -.3392556  .0000033  0.2439 0.0024  I   -52.275     .740    -3.735     .340 -0.147490  0.418350 -0.3392450   -51.900    -3.800  
+ 3 327 52725.00 I  -.145779  .000046   .421212  .000059  I -.3395425  .0000034  0.3405 0.0023  I   -52.098     .740    -3.813     .340 -0.145670  0.421160 -0.3395480   -51.700    -3.900  
+ 3 328 52726.00 I  -.143452  .000042   .424036  .000052  I -.3399480  .0000033  0.4712 0.0024  I   -51.784     .740    -3.895     .340 -0.143350  0.424030 -0.3399430   -51.500    -3.900  
+ 3 329 52727.00 I  -.140613  .000039   .426885  .000055  I -.3404906  .0000034  0.6191 0.0024  I   -51.437     .102    -3.957     .340 -0.140570  0.426870 -0.3404850   -51.500    -3.800  
+ 3 330 52728.00 I  -.137880  .000051   .429885  .000054  I -.3411865  .0000035  0.7679 0.0027  I   -51.244     .183    -3.908     .340 -0.137770  0.429840 -0.3412060   -51.500    -3.700  
+ 3 331 52729.00 I  -.135448  .000048   .432832  .000050  I -.3420147  .0000041  0.8816 0.0025  I   -51.280     .183    -3.679     .340 -0.135380  0.432830 -0.3420440   -51.500    -3.500  
+ 3 4 1 52730.00 I  -.133253  .000052   .435574  .000036  I -.3429313  .0000036  0.9401 0.0028  I   -51.438     .459    -3.347     .149 -0.133250  0.435620 -0.3429290   -51.400    -3.400  
+ 3 4 2 52731.00 I  -.131337  .000052   .438596  .000042  I -.3438876  .0000039  0.9767 0.0027  I   -51.553     .522    -3.109     .152 -0.131170  0.438590 -0.3438740   -51.200    -3.300  
+ 3 4 3 52732.00 I  -.129096  .000055   .441736  .000043  I -.3448712  .0000039  0.9728 0.0027  I   -51.586     .522    -3.153     .152 -0.129050  0.441740 -0.3448740   -51.000    -3.400  
+ 3 4 4 52733.00 I  -.127130  .000055   .444678  .000040  I -.3458013  .0000038  0.8732 0.0028  I   -51.514     .522    -3.390     .152 -0.126950  0.444670 -0.3457940   -50.800    -3.500  
+ 3 4 5 52734.00 I  -.124629  .000045   .447542  .000035  I -.3466152  .0000039  0.7663 0.0025  I   -51.368     .560    -3.641     .151 -0.124580  0.447540 -0.3466170   -50.800    -3.700  
+ 3 4 6 52735.00 I  -.122177  .000053   .450759  .000034  I -.3473352  .0000032  0.6632 0.0029  I   -51.258     .454    -3.842     .144 -0.122080  0.450760 -0.3473310   -50.900    -3.900  
+ 3 4 7 52736.00 I  -.119826  .000058   .454061  .000046  I -.3479283  .0000042  0.5202 0.0026  I   -51.285     .454    -4.074     .144 -0.119780  0.454050 -0.3479260   -51.000    -4.100  
+ 3 4 8 52737.00 I  -.117581  .000064   .456994  .000053  I -.3483759  .0000041  0.3781 0.0029  I   -51.342     .265    -4.359     .111 -0.117590  0.456990 -0.3483700   -51.100    -4.200  
+ 3 4 9 52738.00 I  -.116238  .000061   .459671  .000056  I -.3487087  .0000041  0.3087 0.0029  I   -51.174     .225    -4.558     .104 -0.115960  0.459710 -0.3487010   -50.900    -4.300  
+ 3 410 52739.00 I  -.114690  .000060   .462343  .000060  I -.3490285  .0000041  0.3449 0.0029  I   -50.751     .225    -4.567     .104 -0.114680  0.462350 -0.3490260   -50.700    -4.400  
+ 3 411 52740.00 I  -.113539  .000059   .464834  .000059  I -.3494229  .0000041  0.4544 0.0034  I   -50.391     .225    -4.532     .104 -0.113230  0.464850 -0.3494180   -50.300    -4.600  
+ 3 412 52741.00 I  -.111408  .000064   .467511  .000063  I -.3499690  .0000054  0.6588 0.0025  I   -50.343     .290    -4.688     .340 -0.111410  0.467490 -0.3499570   -49.900    -4.700  
+ 3 413 52742.00 I  -.109399  .000055   .470304  .000041  I -.3507694  .0000029  0.9497 0.0030  I   -50.418     .250    -5.004     .340 -0.109290  0.470290 -0.3507470   -49.600    -4.900  
+ 3 414 52743.00 I  -.107268  .000048   .472883  .000034  I -.3518708  .0000028  1.2479 0.0024  I   -50.297     .151    -5.153     .340 -0.107170  0.472880 -0.3518560   -49.600    -4.900  
+ 3 415 52744.00 I  -.105224  .000044   .475253  .000038  I -.3532336  .0000037  1.4514 0.0024  I   -50.073     .189    -4.923     .340 -0.105260  0.475280 -0.3532260   -49.800    -4.800  
+ 3 416 52745.00 I  -.103976  .000048   .477415  .000038  I -.3547178  .0000040  1.4874 0.0032  I   -50.363     .136    -4.461     .340 -0.103790  0.477410 -0.3547140   -50.200    -4.600  
+ 3 417 52746.00 I  -.102241  .000048   .479238  .000039  I -.3561391  .0000053  1.3154 0.0034  I   -50.934     .136    -4.223     .340 -0.102200  0.479230 -0.3561370   -50.700    -4.300  
+ 3 418 52747.00 I  -.100347  .000046   .481207  .000040  I -.3573084  .0000054  1.0228 0.0062  I   -51.604     .136    -4.276     .340 -0.100290  0.481160 -0.3572750   -51.000    -4.200  
+ 3 419 52748.00 I  -.098110  .000046   .483411  .000051  I -.3581655  .0000113  0.6726 0.0043  I   -51.877     .130    -4.406     .340 -0.098020  0.483390 -0.3581420   -51.100    -4.200  
+ 3 420 52749.00 I  -.095579  .000059   .485678  .000071  I -.3586492  .0000067  0.3093 0.0067  I   -51.679     .124    -4.532     .340 -0.095490  0.485660 -0.3586890   -50.900    -4.400  
+ 3 421 52750.00 I  -.093129  .000060   .487711  .000085  I -.3588349  .0000071  0.0983 0.0045  I   -51.252     .435    -4.668     .256 -0.093040  0.487740 -0.3589020   -50.700    -4.700  
+ 3 422 52751.00 I  -.090755  .000056   .489518  .000091  I -.3588929  .0000060  0.0284 0.0042  I   -50.908     .405    -4.882     .238 -0.090700  0.489620 -0.3588960   -50.500    -4.900  
+ 3 423 52752.00 I  -.088601  .000058   .491625  .000089  I -.3589248  .0000045  0.0578 0.0037  I   -50.782     .352    -5.082     .204 -0.088490  0.491700 -0.3588860   -50.400    -5.100  
+ 3 424 52753.00 I  -.086073  .000056   .493677  .000089  I -.3590416  .0000044  0.1867 0.0026  I   -50.792     .352    -5.122     .204 -0.085900  0.493740 -0.3590440   -50.400    -5.100  
+ 3 425 52754.00 I  -.082835  .000055   .495853  .000083  I -.3593016  .0000025  0.3259 0.0025  I   -50.741     .352    -5.002     .204 -0.082770  0.495770 -0.3592960   -50.500    -4.900  
+ 3 426 52755.00 I  -.080055  .000051   .497996  .000080  I -.3596948  .0000025  0.4691 0.0016  I   -50.540     .413    -4.824     .234 -0.079990  0.497960 -0.3596890   -50.400    -4.700  
+ 3 427 52756.00 I  -.077683  .000063   .500185  .000068  I -.3602410  .0000019  0.6157 0.0015  I   -50.334     .137    -4.628     .340 -0.077590  0.500160 -0.3602360   -50.300    -4.500  
+ 3 428 52757.00 I  -.075264  .000065   .502396  .000062  I -.3609113  .0000018  0.7175 0.0013  I   -50.344     .133    -4.349     .340 -0.075190  0.502440 -0.3609080   -50.300    -4.200  
+ 3 429 52758.00 I  -.072945  .000060   .504336  .000057  I -.3616574  .0000017  0.7635 0.0013  I   -50.590     .132    -4.013     .340 -0.072840  0.504420 -0.3616510   -50.400    -4.000  
+ 3 430 52759.00 I  -.070452  .000057   .506168  .000059  I -.3624152  .0000018  0.7402 0.0013  I   -50.875     .132    -3.814     .340 -0.070270  0.506180 -0.3624080   -50.800    -3.900  
+ 3 5 1 52760.00 I  -.066884  .000056   .508018  .000058  I -.3631068  .0000020  0.6237 0.0014  I   -51.014     .132    -3.925     .340 -0.066850  0.508020 -0.3631080   -51.100    -3.900  
+ 3 5 2 52761.00 I  -.063134  .000054   .509849  .000043  I -.3636406  .0000022  0.4410 0.0022  I   -50.976     .132    -4.288     .340 -0.063020  0.509870 -0.3636450   -51.200    -4.100  
+ 3 5 3 52762.00 I  -.059460  .000045   .511574  .000040  I -.3639858  .0000039  0.2491 0.0026  I   -50.818     .164    -4.673     .340 -0.059380  0.511610 -0.3639710   -51.100    -4.400  
+ 3 5 4 52763.00 I  -.056188  .000041   .513428  .000044  I -.3641403  .0000047  0.0615 0.0038  I   -50.705     .173    -4.909     .340 -0.056110  0.513430 -0.3640950   -50.900    -4.800  
+ 3 5 5 52764.00 I  -.053251  .000048   .515445  .000043  I -.3641271  .0000066 -0.0712 0.0037  I   -50.721     .173    -5.059     .340 -0.053140  0.515420 -0.3640860   -50.700    -5.100  
+ 3 5 6 52765.00 I  -.050102  .000064   .517481  .000047  I -.3640312  .0000057 -0.1038 0.0042  I   -50.831     .213    -5.218     .340 -0.050100  0.517520 -0.3640240   -50.600    -5.200  
+ 3 5 7 52766.00 I  -.047177  .000062   .519684  .000067  I -.3639292  .0000052 -0.1072 0.0038  I   -50.830     .284    -5.344     .340 -0.047150  0.519710 -0.3639140   -50.400    -5.300  
+ 3 5 8 52767.00 I  -.044759  .000066   .521707  .000067  I -.3638449  .0000051 -0.0264 0.0035  I   -50.584     .284    -5.339     .340 -0.044670  0.521610 -0.3638350   -50.300    -5.300  
+ 3 5 9 52768.00 I  -.042316  .000062   .523206  .000065  I -.3639183  .0000048  0.1802 0.0036  I   -50.240     .284    -5.263     .340 -0.042140  0.523330 -0.3639110   -50.300    -5.300  
+ 3 510 52769.00 I  -.039744  .000061   .525015  .000067  I -.3642129  .0000052  0.4095 0.0030  I   -49.972     .486    -5.277     .103 -0.039680  0.525050 -0.3642000   -50.100    -5.400  
+ 3 511 52770.00 I  -.037767  .000052   .526629  .000061  I -.3647435  .0000035  0.6574 0.0028  I   -49.993     .330    -5.449     .340 -0.037690  0.526600 -0.3647260   -49.900    -5.400  
+ 3 512 52771.00 I  -.036128  .000046   .527945  .000077  I -.3655317  .0000022  0.9174 0.0022  I   -50.086     .300    -5.525     .340 -0.036010  0.527970 -0.3655100   -49.900    -5.400  
+ 3 513 52772.00 I  -.034478  .000036   .529264  .000063  I -.3665666  .0000028  1.1423 0.0019  I   -50.269     .106    -5.298     .340 -0.034400  0.529290 -0.3665540   -50.000    -5.300  
+ 3 514 52773.00 I  -.032655  .000033   .530583  .000072  I -.3677702  .0000030  1.2291 0.0022  I   -50.726     .134    -4.887     .340 -0.032560  0.530530 -0.3677770   -50.600    -5.100  
+ 3 515 52774.00 I  -.030523  .000035   .531887  .000073  I -.3689547  .0000033  1.1058 0.0022  I   -51.457     .134    -4.605     .340 -0.030430  0.531850 -0.3689700   -51.200    -4.800  
+ 3 516 52775.00 I  -.028293  .000036   .533225  .000075  I -.3699223  .0000031  0.8039 0.0036  I   -52.127     .134    -4.587     .340 -0.028250  0.533180 -0.3699180   -51.700    -4.600  
+ 3 517 52776.00 I  -.025981  .000045   .534353  .000088  I -.3705531  .0000065  0.4736 0.0032  I   -52.379     .157    -4.675     .340 -0.025890  0.534300 -0.3705330   -51.900    -4.500  
+ 3 518 52777.00 I  -.023693  .000043   .535468  .000064  I -.3709000  .0000055  0.2347 0.0043  I   -52.128     .143    -4.799     .118 -0.023560  0.535470 -0.3708860   -51.600    -4.700  
+ 3 519 52778.00 I  -.021358  .000051   .536500  .000059  I -.3710701  .0000055  0.1385 0.0035  I   -51.589     .150    -4.999     .112 -0.021250  0.536550 -0.3710520   -51.200    -4.900  
+ 3 520 52779.00 I  -.018620  .000054   .537522  .000045  I -.3712217  .0000043  0.1764 0.0034  I   -51.061     .117    -5.335     .128 -0.018500  0.537530 -0.3712130   -50.800    -5.200  
+ 3 521 52780.00 I  -.015410  .000064   .538602  .000043  I -.3714380  .0000039  0.2598 0.0029  I   -50.794     .119    -5.642     .115 -0.015430  0.538610 -0.3714480   -50.600    -5.400  
+ 3 522 52781.00 I  -.012603  .000064   .539688  .000042  I -.3717551  .0000039  0.3847 0.0026  I   -50.863     .119    -5.672     .115 -0.012490  0.539640 -0.3717310   -50.600    -5.500  
+ 3 523 52782.00 I  -.009866  .000058   .540575  .000035  I -.3722105  .0000033  0.5188 0.0026  I   -51.090     .119    -5.399     .115 -0.009800  0.540440 -0.3722000   -50.900    -5.400  
+ 3 524 52783.00 I  -.007004  .000061   .540972  .000036  I -.3727809  .0000035  0.6174 0.0024  I   -51.212     .122    -5.042     .340 -0.006960  0.540960 -0.3727690   -51.200    -5.100  
+ 3 525 52784.00 I  -.004106  .000052   .541211  .000052  I -.3734260  .0000034  0.6579 0.0025  I   -51.203     .102    -4.775     .102 -0.004030  0.541340 -0.3733950   -51.400    -4.800  
+ 3 526 52785.00 I  -.001056  .000053   .541528  .000074  I -.3740728  .0000035  0.6265 0.0027  I   -51.287     .131    -4.572     .340 -0.000940  0.541610 -0.3740370   -51.700    -4.500  
+ 3 527 52786.00 I   .002298  .000052   .541977  .000096  I -.3746654  .0000042  0.5543 0.0024  I   -51.609     .154    -4.366     .197  0.002370  0.541990 -0.3746410   -51.800    -4.300  
+ 3 528 52787.00 I   .005837  .000072   .542598  .000087  I -.3751705  .0000032  0.4494 0.0026  I   -51.982     .214    -4.234     .172  0.005880  0.542640 -0.3751620   -52.000    -4.300  
+ 3 529 52788.00 I   .009260  .000080   .543591  .000086  I -.3755531  .0000032  0.3113 0.0022  I   -52.260     .214    -4.353     .172  0.009390  0.543690 -0.3755520   -52.100    -4.500  
+ 3 530 52789.00 I   .012429  .000072   .544507  .000081  I -.3757844  .0000029  0.1470 0.0021  I   -52.338     .214    -4.716     .172  0.012550  0.544580 -0.3757760   -52.200    -4.700  
+ 3 531 52790.00 I   .015576  .000071   .545546  .000078  I -.3758359  .0000027 -0.0510 0.0019  I   -52.300     .210    -5.116     .167  0.015640  0.545500 -0.3758550   -52.100    -5.000  
+ 3 6 1 52791.00 I   .018416  .000063   .546437  .000067  I -.3756855  .0000025 -0.2398 0.0018  I   -52.244     .210    -5.342     .172  0.018520  0.546410 -0.3757030   -52.000    -5.100  
+ 3 6 2 52792.00 I   .021231  .000064   .547100  .000061  I -.3753793  .0000025 -0.3595 0.0020  I   -52.247     .200    -5.371     .340  0.021340  0.546990 -0.3753690   -51.900    -5.200  
+ 3 6 3 52793.00 I   .024311  .000037   .547652  .000042  I -.3749825  .0000030 -0.4311 0.0022  I   -52.359     .154    -5.329     .135  0.024380  0.547540 -0.3749710   -51.900    -5.200  
+ 3 6 4 52794.00 I   .027719  .000039   .547855  .000057  I -.3745271  .0000037 -0.4726 0.0025  I   -52.524     .280    -5.312     .148  0.027810  0.547850 -0.3745520   -52.000    -5.300  
+ 3 6 5 52795.00 I   .031430  .000044   .547882  .000058  I -.3740730  .0000040 -0.4068 0.0028  I   -52.585     .280    -5.308     .148  0.031540  0.547890 -0.3740740   -52.100    -5.400  
+ 3 6 6 52796.00 I   .034917  .000044   .547818  .000051  I -.3737576  .0000042 -0.2085 0.0033  I   -52.455     .280    -5.286     .148  0.035020  0.547910 -0.3737490   -52.300    -5.400  
+ 3 6 7 52797.00 I   .038130  .000034   .547817  .000051  I -.3736737  .0000052  0.0429 0.0029  I   -52.218     .369    -5.218     .196  0.038190  0.547810 -0.3736780   -52.300    -5.300  
+ 3 6 8 52798.00 I   .041333  .000064   .547855  .000050  I -.3738447  .0000041  0.2983 0.0033  I   -52.115     .323    -5.183     .161  0.041410  0.547810 -0.3738780   -52.400    -5.200  
+ 3 6 9 52799.00 I   .044736  .000066   .547922  .000047  I -.3742503  .0000040  0.4937 0.0027  I   -52.278     .323    -5.064     .161  0.044810  0.547930 -0.3742770   -52.600    -4.900  
+ 3 610 52800.00 I   .048281  .000072   .548027  .000046  I -.3747833  .0000036  0.5426 0.0026  I   -52.767     .418    -4.808     .340  0.048330  0.548050 -0.3747790   -52.800    -4.700  
+ 3 611 52801.00 I   .051673  .000073   .548061  .000051  I -.3752832  .0000033  0.4346 0.0022  I   -53.549     .637    -4.534     .148  0.051790  0.548060 -0.3752700   -53.100    -4.500  
+ 3 612 52802.00 I   .055139  .000073   .547756  .000058  I -.3756082  .0000026  0.1937 0.0020  I   -54.346     .637    -4.383     .148  0.055260  0.547750 -0.3756120   -53.400    -4.500  
+ 3 613 52803.00 I   .058556  .000073   .547201  .000053  I -.3756412  .0000024 -0.1354 0.0030  I   -54.883     .637    -4.430     .148  0.058730  0.547230 -0.3756430   -53.700    -4.500  
+ 3 614 52804.00 I   .062094  .000037   .546689  .000057  I -.3753452  .0000054 -0.4411 0.0025  I   -55.004     .766    -4.554     .182  0.062170  0.546630 -0.3753230   -54.000    -4.700  
+ 3 615 52805.00 I   .065802  .000052   .546171  .000058  I -.3747957  .0000044 -0.6369 0.0035  I   -54.781     .667    -4.661     .159  0.065870  0.546100 -0.3747700   -54.100    -4.900  
+ 3 616 52806.00 I   .069733  .000051   .545588  .000054  I -.3741172  .0000044 -0.6955 0.0027  I   -54.378     .664    -4.826     .158  0.069830  0.545570 -0.3741000   -54.100    -5.100  
+ 3 617 52807.00 I   .074052  .000069   .545079  .000057  I -.3734464  .0000033 -0.6290 0.0027  I   -53.954     .405    -5.129     .128  0.074140  0.545040 -0.3734360   -54.100    -5.300  
+ 3 618 52808.00 I   .078547  .000067   .544862  .000057  I -.3728845  .0000032 -0.4864 0.0023  I   -53.629     .428    -5.435     .184  0.078630  0.544840 -0.3728820   -53.900    -5.400  
+ 3 619 52809.00 I   .082892  .000068   .544756  .000066  I -.3724844  .0000033 -0.3112 0.0023  I   -53.717     .428    -5.479     .184  0.083140  0.544680 -0.3724930   -53.800    -5.300  
+ 3 620 52810.00 I   .087700  .000069   .544532  .000061  I -.3722530  .0000032 -0.1633 0.0024  I   -54.102     .428    -5.203     .184  0.087770  0.544520 -0.3722550   -53.800    -5.200  
+ 3 621 52811.00 I   .091956  .000069   .544384  .000065  I -.3721348  .0000034 -0.0846 0.0022  I   -54.527     .391    -4.827     .199  0.092070  0.544420 -0.3721070   -53.800    -5.000  
+ 3 622 52812.00 I   .095888  .000078   .544085  .000066  I -.3720627  .0000031 -0.0694 0.0027  I   -54.812     .260    -4.589     .177  0.095980  0.544080 -0.3720050   -54.100    -4.800  
+ 3 623 52813.00 I   .099772  .000063   .543616  .000063  I -.3719772  .0000041 -0.1107 0.0025  I   -55.043     .308    -4.499     .227  0.099880  0.543620 -0.3719230   -54.400    -4.600  
+ 3 624 52814.00 I   .103554  .000057   .542996  .000067  I -.3718238  .0000038 -0.2046 0.0028  I   -55.376     .328    -4.425     .197  0.103640  0.543060 -0.3718090   -54.900    -4.400  
+ 3 625 52815.00 I   .107221  .000062   .542491  .000075  I -.3715540  .0000039 -0.3405 0.0030  I   -55.789     .345    -4.346     .212  0.107340  0.542480 -0.3715590   -55.400    -4.400  
+ 3 626 52816.00 I   .110928  .000058   .542076  .000073  I -.3711389  .0000046 -0.4880 0.0030  I   -56.129     .345    -4.388     .212  0.111030  0.542050 -0.3711060   -55.900    -4.400  
+ 3 627 52817.00 I   .114722  .000059   .541683  .000071  I -.3705786  .0000045 -0.6337 0.0030  I   -56.334     .345    -4.638     .212  0.114840  0.541520 -0.3705660   -56.200    -4.500  
+ 3 628 52818.00 I   .118619  .000038   .541064  .000064  I -.3698746  .0000040 -0.7700 0.0028  I   -56.407     .402    -4.976     .234  0.118730  0.540990 -0.3698540   -56.400    -4.700  
+ 3 629 52819.00 I   .122623  .000072   .540447  .000067  I -.3690496  .0000032 -0.8731 0.0025  I   -56.445     .270    -5.234     .165  0.122740  0.540420 -0.3690180   -56.300    -4.900  
+ 3 630 52820.00 I   .126689  .000078   .539883  .000064  I -.3681479  .0000029 -0.9175 0.0023  I   -56.421     .259    -5.271     .158  0.126790  0.539860 -0.3681090   -56.200    -5.100  
+ 3 7 1 52821.00 I   .130468  .000079   .539313  .000048  I -.3672420  .0000032 -0.8796 0.0020  I   -56.414     .226    -5.141     .340  0.130560  0.539290 -0.3672270   -56.200    -5.200  
+ 3 7 2 52822.00 I   .133821  .000080   .538582  .000051  I -.3664106  .0000027 -0.7761 0.0021  I   -56.477     .204    -5.030     .107  0.133980  0.538570 -0.3664210   -56.200    -5.100  
+ 3 7 3 52823.00 I   .136813  .000080   .537563  .000051  I -.3657010  .0000027 -0.6389 0.0020  I   -56.630     .204    -4.988     .107  0.137040  0.537500 -0.3656920   -56.400    -5.000  
+ 3 7 4 52824.00 I   .139880  .000072   .535923  .000049  I -.3651475  .0000029 -0.4576 0.0027  I   -56.681     .204    -5.024     .107  0.139980  0.535890 -0.3651290   -56.500    -4.800  
+ 3 7 5 52825.00 I   .143073  .000046   .534157  .000048  I -.3647861  .0000046 -0.2753 0.0029  I   -56.584     .238    -5.033     .101  0.143200  0.534100 -0.3647340   -56.500    -4.700  
+ 3 7 6 52826.00 I   .146403  .000056   .532623  .000055  I -.3645739  .0000050 -0.1620 0.0039  I   -56.504     .200    -4.928     .340  0.146510  0.532570 -0.3644890   -56.600    -4.600  
+ 3 7 7 52827.00 I   .149616  .000049   .531187  .000055  I -.3644331  .0000064 -0.1359 0.0031  I   -56.690     .740    -4.711     .340  0.149680  0.531190 -0.3643570   -56.800    -4.500  
+ 3 7 8 52828.00 I   .153014  .000057   .529717  .000057  I -.3642754  .0000038 -0.1901 0.0037  I   -57.246     .217    -4.463     .340  0.153090  0.529730 -0.3642560   -57.000    -4.500  
+ 3 7 9 52829.00 I   .156652  .000066   .528214  .000059  I -.3640177  .0000038 -0.3499 0.0027  I   -58.023     .280    -4.301     .340  0.156730  0.528180 -0.3640300   -57.400    -4.400  
+ 3 710 52830.00 I   .160400  .000070   .526692  .000060  I -.3635461  .0000037 -0.5983 0.0025  I   -58.701     .280    -4.300     .340  0.160450  0.526650 -0.3635320   -57.800    -4.400  
+ 3 711 52831.00 I   .163893  .000069   .525208  .000058  I -.3628283  .0000033 -0.8250 0.0022  I   -59.026     .280    -4.431     .340  0.164060  0.525270 -0.3628150   -58.100    -4.400  
+ 3 712 52832.00 I   .167447  .000065   .523922  .000055  I -.3619299  .0000025 -0.9503 0.0020  I   -58.947     .328    -4.642     .340  0.167540  0.523940 -0.3619300   -58.200    -4.400  
+ 3 713 52833.00 I   .170540  .000070   .522624  .000054  I -.3609656  .0000021 -0.9618 0.0018  I   -58.730     .298    -4.737     .129  0.170640  0.522650 -0.3609700   -58.100    -4.400  
+ 3 714 52834.00 I   .173119  .000070   .521200  .000052  I -.3600377  .0000025 -0.8791 0.0015  I   -58.502     .276    -4.826     .130  0.173240  0.521190 -0.3600350   -58.000    -4.500  
+ 3 715 52835.00 I   .175615  .000055   .519726  .000043  I -.3592355  .0000021 -0.7122 0.0016  I   -58.316     .380    -4.986     .138  0.175690  0.519660 -0.3592290   -58.000    -4.800  
+ 3 716 52836.00 I   .178216  .000065   .518207  .000044  I -.3586320  .0000020 -0.4892 0.0015  I   -58.214     .454    -5.159     .140  0.178280  0.518100 -0.3586240   -58.200    -5.100  
+ 3 717 52837.00 I   .180961  .000061   .516617  .000045  I -.3582506  .0000021 -0.2857 0.0014  I   -58.310     .454    -5.182     .140  0.180970  0.516510 -0.3582320   -58.500    -5.200  
+ 3 718 52838.00 I   .183442  .000058   .514713  .000042  I -.3580347  .0000019 -0.1600 0.0015  I   -58.665     .454    -4.996     .140  0.183560  0.514700 -0.3580200   -59.000    -5.000  
+ 3 719 52839.00 I   .186304  .000056   .512678  .000044  I -.3579064  .0000020 -0.1070 0.0014  I   -59.164     .523    -4.774     .340  0.186360  0.512610 -0.3579100   -59.500    -4.900  
+ 3 720 52840.00 I   .189291  .000067   .510645  .000045  I -.3577985  .0000020 -0.1208 0.0015  I   -59.610     .490    -4.637     .340  0.189360  0.510580 -0.3577950   -59.900    -4.700  
+ 3 721 52841.00 I   .191970  .000070   .508531  .000044  I -.3576469  .0000023 -0.1883 0.0022  I   -59.920     .518    -4.622     .340  0.192020  0.508560 -0.3576290   -60.300    -4.600  
+ 3 722 52842.00 I   .194308  .000050   .506211  .000049  I -.3574124  .0000040 -0.2841 0.0026  I   -60.157     .311    -4.602     .340  0.194430  0.506240 -0.3573990   -60.400    -4.500  
+ 3 723 52843.00 I   .197124  .000062   .503868  .000054  I -.3570731  .0000047 -0.3965 0.0032  I   -60.399     .340    -4.523     .179  0.197180  0.503790 -0.3570760   -60.400    -4.500  
+ 3 724 52844.00 I   .199921  .000062   .501622  .000059  I -.3566195  .0000049 -0.5085 0.0034  I   -60.655     .340    -4.497     .179  0.200020  0.501600 -0.3566200   -60.300    -4.500  
+ 3 725 52845.00 I   .202476  .000064   .499419  .000064  I -.3560571  .0000049 -0.6175 0.0046  I   -60.884     .340    -4.654     .179  0.202520  0.499500 -0.3560510   -60.300    -4.500  
+ 3 726 52846.00 I   .204685  .000051   .497220  .000070  I -.3554030  .0000079 -0.6711 0.0044  I   -60.932     .355    -4.999     .229  0.204770  0.497210 -0.3554020   -60.400    -4.600  
+ 3 727 52847.00 I   .206809  .000062   .494817  .000074  I -.3547428  .0000073 -0.6410 0.0051  I   -60.930     .390    -5.298     .194  0.206880  0.494770 -0.3547510   -60.600    -4.800  
+ 3 728 52848.00 I   .208980  .000069   .492100  .000073  I -.3541361  .0000066 -0.5655 0.0046  I   -60.779     .390    -5.410     .207  0.209050  0.492120 -0.3541420   -60.700    -5.000  
+ 3 729 52849.00 I   .211303  .000059   .489142  .000070  I -.3536200  .0000056 -0.4653 0.0042  I   -60.583     .409    -5.305     .340  0.211370  0.489240 -0.3536150   -60.800    -5.200  
+ 3 730 52850.00 I   .213815  .000065   .486413  .000070  I -.3532271  .0000053 -0.3001 0.0040  I   -60.430     .370    -5.113     .340  0.213900  0.486430 -0.3532260   -60.700    -5.200  
+ 3 731 52851.00 I   .216500  .000063   .483887  .000055  I -.3530459  .0000057 -0.0565 0.0040  I   -60.469     .370    -4.992     .340  0.216580  0.483900 -0.3530440   -60.500    -5.200  
+ 3 8 1 52852.00 I   .219112  .000056   .481538  .000058  I -.3531033  .0000060  0.1548 0.0047  I   -60.570     .370    -5.017     .340  0.219220  0.481570 -0.3530920   -60.300    -5.100  
+ 3 8 2 52853.00 I   .221386  .000042   .479513  .000049  I -.3533306  .0000075  0.2915 0.0046  I   -60.663     .116    -5.101     .340  0.221430  0.479470 -0.3533400   -60.300    -5.000  
+ 3 8 3 52854.00 I   .223071  .000054   .477318  .000053  I -.3536689  .0000071  0.3761 0.0051  I   -60.785     .740    -5.106     .340  0.223150  0.477200 -0.3537200   -60.500    -4.900  
+ 3 8 4 52855.00 I   .224748  .000056   .474861  .000051  I -.3540496  .0000069  0.3611 0.0053  I   -61.041     .740    -4.981     .340  0.224830  0.474730 -0.3540840   -60.900    -5.100  
+ 3 8 5 52856.00 I   .226443  .000051   .472367  .000048  I -.3543334  .0000080  0.1730 0.0051  I   -61.473     .156    -4.800     .101  0.226500  0.472310 -0.3543240   -61.300    -4.700  
+ 3 8 6 52857.00 I   .228150  .000054   .469614  .000060  I -.3543726  .0000074 -0.0840 0.0053  I   -61.973     .162    -4.676     .340  0.228230  0.469600 -0.3543660   -61.700    -4.600  
+ 3 8 7 52858.00 I   .230141  .000059   .466612  .000053  I -.3541745  .0000069 -0.3135 0.0046  I   -62.345     .162    -4.658     .340  0.230230  0.466580 -0.3541780   -62.000    -4.600  
+ 3 8 8 52859.00 I   .232124  .000064   .463704  .000055  I -.3537567  .0000056 -0.5096 0.0039  I   -62.450     .162    -4.723     .340  0.232240  0.463660 -0.3537490   -62.200    -4.700  
+ 3 8 9 52860.00 I   .234060  .000039   .461100  .000076  I -.3531909  .0000036 -0.5988 0.0033  I   -62.304     .178    -4.828     .340  0.234120  0.461030 -0.3531860   -62.200    -4.700  
+ 3 810 52861.00 I   .235882  .000049   .458865  .000093  I -.3526009  .0000035 -0.5626 0.0025  I   -62.063     .185    -4.892     .340  0.235980  0.458830 -0.3525970   -62.000    -4.800  
+ 3 811 52862.00 I   .237707  .000047   .456702  .000093  I -.3521001  .0000035 -0.4230 0.0022  I   -61.866     .269    -4.930     .126  0.237790  0.456760 -0.3520940   -61.800    -4.900  
+ 3 812 52863.00 I   .239487  .000044   .454309  .000095  I -.3517812  .0000028 -0.2043 0.0022  I   -61.759     .290    -4.952     .139  0.239600  0.454460 -0.3517730   -61.500    -4.900  
+ 3 813 52864.00 I   .241314  .000053   .452088  .000096  I -.3516894  .0000027  0.0082 0.0021  I   -61.729     .331    -4.936     .123  0.241370  0.452080 -0.3516780   -61.300    -5.000  
+ 3 814 52865.00 I   .243093  .000056   .449784  .000095  I -.3517784  .0000031  0.1630 0.0020  I   -61.792     .331    -4.837     .123  0.243160  0.449760 -0.3517770   -61.300    -4.900  
+ 3 815 52866.00 I   .244570  .000059   .447324  .000091  I -.3520012  .0000029  0.2750 0.0026  I   -62.004     .331    -4.668     .123  0.244710  0.447420 -0.3519870   -61.500    -4.700  
+ 3 816 52867.00 I   .246011  .000053   .444752  .000071  I -.3523064  .0000042  0.3208 0.0026  I   -62.371     .369    -4.537     .124  0.246050  0.444730 -0.3523300   -61.800    -4.500  
+ 3 817 52868.00 I   .247532  .000064   .441804  .000078  I -.3526161  .0000043  0.2865 0.0030  I   -62.774     .284    -4.520     .340  0.247620  0.441710 -0.3526850   -62.200    -4.400  
+ 3 818 52869.00 I   .249124  .000069   .438677  .000078  I -.3528512  .0000044  0.1676 0.0037  I   -63.052     .284    -4.575     .340  0.249190  0.438650 -0.3529040   -62.600    -4.400  
+ 3 819 52870.00 I   .250680  .000060   .435417  .000076  I -.3529173  .0000060 -0.0534 0.0035  I   -63.148     .187    -4.583     .126  0.250720  0.435430 -0.3529140   -63.000    -4.400  
+ 3 820 52871.00 I   .252254  .000061   .432462  .000075  I -.3527417  .0000055 -0.2824 0.0045  I   -63.177     .223    -4.521     .147  0.252330  0.432380 -0.3527250   -63.200    -4.500  
+ 3 821 52872.00 I   .253774  .000059   .429753  .000077  I -.3523732  .0000068 -0.4492 0.0042  I   -63.280     .223    -4.508     .147  0.253840  0.429680 -0.3523710   -63.300    -4.700  
+ 3 822 52873.00 I   .254928  .000054   .427262  .000067  I -.3518548  .0000064 -0.5814 0.0054  I   -63.427     .223    -4.657     .147  0.255050  0.427260 -0.3518440   -63.400    -4.800  
+ 3 823 52874.00 I   .255947  .000040   .424872  .000060  I -.3512339  .0000083 -0.6430 0.0049  I   -63.524     .351    -4.911     .174  0.255980  0.424890 -0.3512340   -63.300    -4.900  
+ 3 824 52875.00 I   .256958  .000042   .422061  .000081  I -.3505935  .0000073 -0.6306 0.0065  I   -63.294     .339    -5.146     .144  0.257020  0.422020 -0.3506380   -63.300    -5.000  
+ 3 825 52876.00 I   .258249  .000045   .418880  .000085  I -.3499998  .0000099 -0.5371 0.0056  I   -62.925     .383    -5.216     .135  0.258310  0.418840 -0.3500360   -63.100    -5.000  
+ 3 826 52877.00 I   .259210  .000049   .415542  .000081  I -.3495442  .0000085 -0.3689 0.0060  I   -62.620     .377    -5.104     .340  0.259350  0.415660 -0.3495410   -62.900    -5.000  
+ 3 827 52878.00 I   .260146  .000064   .412296  .000080  I -.3493055  .0000067 -0.0703 0.0055  I   -62.496     .330    -4.889     .340  0.260160  0.412320 -0.3493060   -62.700    -4.900  
+ 3 828 52879.00 I   .261170  .000065   .409038  .000080  I -.3494278  .0000070  0.3008 0.0048  I   -62.525     .334    -4.691     .340  0.261270  0.409070 -0.3493980   -62.500    -4.800  
+ 3 829 52880.00 I   .262134  .000067   .406067  .000072  I -.3498745  .0000069  0.5742 0.0051  I   -62.673     .334    -4.655     .340  0.262410  0.406130 -0.3498590   -62.400    -4.700  
+ 3 830 52881.00 I   .263337  .000073   .403308  .000053  I -.3505380  .0000075  0.7329 0.0043  I   -62.908     .291    -4.780     .340  0.263420  0.403290 -0.3505460   -62.400    -4.700  
+ 3 831 52882.00 I   .264430  .000064   .400496  .000055  I -.3512890  .0000050  0.7375 0.0043  I   -63.199     .164    -4.951     .136  0.264490  0.400450 -0.3513040   -62.700    -4.600  
+ 3 9 1 52883.00 I   .265244  .000064   .397526  .000047  I -.3519601  .0000040  0.5833 0.0031  I   -63.490     .170    -5.018     .127  0.265340  0.397440 -0.3519670   -63.000    -4.600  
+ 3 9 2 52884.00 I   .265514  .000047   .394414  .000040  I -.3524292  .0000035  0.3497 0.0025  I   -63.733     .299    -4.937     .148  0.265610  0.394360 -0.3524220   -63.300    -4.500  
+ 3 9 3 52885.00 I   .265529  .000049   .391195  .000047  I -.3526473  .0000031  0.0793 0.0024  I   -63.905     .364    -4.779     .120  0.265540  0.391190 -0.3526340   -63.500    -4.500  
+ 3 9 4 52886.00 I   .265386  .000049   .387938  .000051  I -.3525985  .0000034 -0.1589 0.0023  I   -63.983     .364    -4.648     .120  0.265490  0.387910 -0.3525990   -63.600    -4.500  
+ 3 9 5 52887.00 I   .265113  .000048   .384441  .000050  I -.3523713  .0000034 -0.2716 0.0022  I   -63.941     .364    -4.591     .120  0.265320  0.384430 -0.3523630   -63.500    -4.600  
+ 3 9 6 52888.00 I   .265182  .000048   .380910  .000043  I -.3520822  .0000027 -0.3037 0.0022  I   -63.670     .252    -4.587     .101  0.265190  0.380840 -0.3520800   -63.300    -4.600  
+ 3 9 7 52889.00 I   .265053  .000057   .377505  .000058  I -.3517877  .0000029 -0.2645 0.0020  I   -63.406     .240    -4.632     .340  0.265120  0.377410 -0.3518070   -63.100    -4.700  
+ 3 9 8 52890.00 I   .264911  .000058   .374278  .000057  I -.3515887  .0000030 -0.1189 0.0021  I   -63.134     .240    -4.670     .340  0.264960  0.374190 -0.3515900   -62.900    -4.700  
+ 3 9 9 52891.00 I   .264699  .000054   .371156  .000068  I -.3515693  .0000030  0.0850 0.0020  I   -62.942     .201    -4.645     .340  0.264780  0.371110 -0.3515600   -62.800    -4.600  
+ 3 910 52892.00 I   .264511  .000053   .367894  .000064  I -.3517499  .0000027  0.2625 0.0020  I   -62.871     .220    -4.506     .340  0.264640  0.367820 -0.3517590   -62.800    -4.500  
+ 3 911 52893.00 I   .264605  .000054   .364586  .000065  I -.3520732  .0000027  0.3768 0.0018  I   -62.895     .220    -4.260     .340  0.264740  0.364530 -0.3520710   -62.900    -4.300  
+ 3 912 52894.00 I   .264519  .000052   .361280  .000066  I -.3524733  .0000024  0.4005 0.0024  I   -62.988     .220    -4.007     .340  0.264560  0.361260 -0.3524620   -63.100    -4.100  
+ 3 913 52895.00 I   .264233  .000041   .357987  .000064  I -.3528459  .0000040  0.3393 0.0022  I   -63.229     .265    -3.929     .340  0.264300  0.357910 -0.3528470   -63.300    -3.900  
+ 3 914 52896.00 I   .264223  .000047   .354809  .000067  I -.3531448  .0000036  0.2568 0.0032  I   -63.451     .308    -4.011     .340  0.264280  0.354740 -0.3531440   -63.400    -3.800  
+ 3 915 52897.00 I   .264230  .000044   .351772  .000050  I -.3533557  .0000050  0.1627 0.0028  I   -63.600     .295    -4.181     .156  0.264320  0.351740 -0.3533550   -63.600    -3.900  
+ 3 916 52898.00 I   .264141  .000044   .348778  .000052  I -.3534664  .0000042  0.0571 0.0032  I   -63.576     .298    -4.279     .184  0.264230  0.348800 -0.3534580   -63.600    -4.100  
+ 3 917 52899.00 I   .264034  .000047   .345932  .000049  I -.3534705  .0000041 -0.0465 0.0030  I   -63.473     .299    -4.285     .161  0.264090  0.345900 -0.3534420   -63.600    -4.300  
+ 3 918 52900.00 I   .264003  .000050   .342995  .000049  I -.3533594  .0000044 -0.1919 0.0029  I   -63.463     .299    -4.331     .161  0.264010  0.342920 -0.3533250   -63.400    -4.500  
+ 3 919 52901.00 I   .263699  .000050   .339808  .000051  I -.3531016  .0000040 -0.2925 0.0031  I   -63.510     .299    -4.500     .161  0.263760  0.339770 -0.3530900   -63.100    -4.600  
+ 3 920 52902.00 I   .263057  .000045   .336422  .000048  I -.3528096  .0000043 -0.2876 0.0027  I   -63.385     .259    -4.688     .185  0.263100  0.336400 -0.3528150   -62.700    -4.700  
+ 3 921 52903.00 I   .262536  .000056   .332948  .000072  I -.3525464  .0000035 -0.2227 0.0030  I   -62.909     .227    -4.743     .113  0.262570  0.332800 -0.3525610   -62.300    -4.700  
+ 3 922 52904.00 I   .262588  .000059   .329728  .000078  I -.3524015  .0000041 -0.0457 0.0035  I   -62.352     .226    -4.629     .105  0.262610  0.329590 -0.3523970   -61.900    -4.600  
+ 3 923 52905.00 I   .262483  .000062   .326855  .000106  I -.3524815  .0000060  0.2110 0.0030  I   -62.056     .116    -4.439     .101  0.262550  0.326880 -0.3524690   -61.700    -4.500  
+ 3 924 52906.00 I   .261881  .000073   .324088  .000096  I -.3528272  .0000044  0.4787 0.0038  I   -62.092     .126    -4.242     .118  0.261930  0.324050 -0.3528410   -61.700    -4.400  
+ 3 925 52907.00 I   .260919  .000073   .320822  .000085  I -.3534321  .0000048  0.7259 0.0033  I   -62.279     .126    -4.059     .118  0.260980  0.320860 -0.3534380   -61.800    -4.200  
+ 3 926 52908.00 I   .260058  .000080   .317272  .000086  I -.3542544  .0000048  0.8992 0.0042  I   -62.478     .126    -3.950     .118  0.260120  0.317310 -0.3542520   -62.100    -4.100  
+ 3 927 52909.00 I   .259522  .000071   .314021  .000064  I -.3551846  .0000069  0.9349 0.0035  I   -62.681     .167    -4.013     .124  0.259650  0.313970 -0.3551960   -62.400    -4.100  
+ 3 928 52910.00 I   .259354  .000067   .311099  .000066  I -.3560733  .0000050  0.8178 0.0043  I   -62.868     .236    -4.232     .134  0.259430  0.311050 -0.3560970   -62.700    -4.100  
+ 3 929 52911.00 I   .259186  .000062   .308482  .000064  I -.3567895  .0000051  0.6085 0.0034  I   -62.960     .236    -4.424     .134  0.259270  0.308390 -0.3568040   -62.900    -4.200  
+ 3 930 52912.00 I   .259199  .000043   .306212  .000053  I -.3572758  .0000045  0.3558 0.0032  I   -62.943     .274    -4.416     .128  0.259180  0.306160 -0.3572700   -63.000    -4.300  
+ 310 1 52913.00 I   .258446  .000051   .304036  .000064  I -.3575077  .0000039  0.1228 0.0029  I   -62.900     .232    -4.236     .131  0.258530  0.304000 -0.3575060   -63.100    -4.300  
+ 310 2 52914.00 I   .257373  .000050   .301433  .000064  I -.3575563  .0000037 -0.0054 0.0023  I   -62.886     .232    -4.063     .131  0.257380  0.301390 -0.3575580   -63.000    -4.200  
+ 310 3 52915.00 I   .256284  .000049   .298629  .000065  I -.3575382  .0000024 -0.0096 0.0030  I   -62.846     .232    -4.019     .131  0.256250  0.298690 -0.3575300   -62.800    -4.200  
+ 310 4 52916.00 I   .254925  .000047   .296135  .000058  I -.3575692  .0000046  0.0824 0.0027  I   -62.688     .142    -4.072     .160  0.254990  0.296150 -0.3575800   -62.400    -4.100  
+ 310 5 52917.00 I   .253564  .000054   .293452  .000058  I -.3577244  .0000049  0.2384 0.0033  I   -62.392     .127    -4.127     .157  0.253630  0.293450 -0.3577210   -62.000    -4.000  
+ 310 6 52918.00 I   .252217  .000055   .290461  .000056  I -.3580632  .0000048  0.4459 0.0049  I   -62.034     .127    -4.134     .157  0.252280  0.290420 -0.3580400   -61.600    -4.000  
+ 310 7 52919.00 I   .250916  .000048   .287405  .000046  I -.3586134  .0000084  0.6449 0.0040  I   -61.739     .151    -4.070     .182  0.250960  0.287370 -0.3586000   -61.400    -3.800  
+ 310 8 52920.00 I   .249548  .000045   .284675  .000051  I -.3593205  .0000065  0.7465 0.0053  I   -61.621     .157    -3.933     .181  0.249600  0.284630 -0.3593330   -61.500    -3.700  
+ 310 9 52921.00 I   .248049  .000043   .282079  .000053  I -.3600671  .0000065  0.7304 0.0043  I   -61.614     .157    -3.630     .181  0.248110  0.282020 -0.3600770   -61.500    -3.600  
+ 31010 52922.00 I   .246399  .000042   .279260  .000055  I -.3607698  .0000057  0.6799 0.0041  I   -61.646     .157    -3.308     .181  0.246430  0.279220 -0.3607580   -61.300    -3.400  
+ 31011 52923.00 I   .244458  .000037   .276479  .000057  I -.3614181  .0000049  0.6031 0.0035  I   -61.667     .138    -3.140     .147  0.244420  0.276420 -0.3614210   -61.100    -3.300  
+ 31012 52924.00 I   .242041  .000041   .273677  .000061  I -.3619580  .0000041  0.4724 0.0028  I   -61.667     .147    -3.262     .152  0.242100  0.273640 -0.3619840   -61.100    -3.300  
+ 31013 52925.00 I   .239770  .000038   .270720  .000060  I -.3623574  .0000028  0.3253 0.0025  I   -61.634     .135    -3.533     .138  0.239820  0.270690 -0.3623750   -61.200    -3.400  
+ 31014 52926.00 I   .237782  .000038   .267465  .000058  I -.3626070  .0000028  0.1733 0.0019  I   -61.524     .177    -3.742     .115  0.237790  0.267490 -0.3625980   -61.300    -3.600  
+ 31015 52927.00 I   .235760  .000048   .264252  .000064  I -.3627098  .0000027  0.0387 0.0019  I   -61.380     .219    -3.818     .107  0.235850  0.264180 -0.3626930   -61.300    -3.800  
+ 31016 52928.00 I   .233828  .000049   .261079  .000063  I -.3626966  .0000027 -0.0591 0.0019  I   -61.312     .219    -3.880     .107  0.233880  0.261050 -0.3626940   -61.200    -4.000  
+ 31017 52929.00 I   .231726  .000054   .257910  .000063  I -.3626117  .0000027 -0.0965 0.0018  I   -61.273     .219    -4.010     .107  0.231840  0.257960 -0.3626070   -60.900    -4.100  
+ 31018 52930.00 I   .229788  .000052   .255053  .000063  I -.3625381  .0000025 -0.0305 0.0017  I   -61.048     .259    -4.108     .340  0.229830  0.254970 -0.3625330   -60.500    -4.000  
+ 31019 52931.00 I   .227911  .000056   .252528  .000058  I -.3625861  .0000021  0.1416 0.0016  I   -60.491     .259    -3.997     .340  0.227960  0.252450 -0.3626020   -60.000    -3.900  
+ 31020 52932.00 I   .225989  .000058   .250050  .000058  I -.3628492  .0000021  0.3973 0.0017  I   -59.908     .244    -3.728     .340  0.226020  0.250040 -0.3628760   -59.600    -3.700  
+ 31021 52933.00 I   .224050  .000066   .247358  .000060  I -.3633940  .0000027  0.6930 0.0018  I   -59.673     .196    -3.487     .340  0.224070  0.247350 -0.3633930   -59.400    -3.400  
+ 31022 52934.00 I   .221858  .000080   .244719  .000071  I -.3642305  .0000029  0.9746 0.0019  I   -59.826     .175    -3.349     .340  0.221970  0.244690 -0.3641960   -59.500    -3.200  
+ 31023 52935.00 I   .220267  .000077   .242197  .000071  I -.3653286  .0000027  1.2122 0.0020  I   -60.112     .175    -3.211     .340  0.220270  0.242220 -0.3652860   -59.700    -3.000  
+ 31024 52936.00 I   .219367  .000076   .239953  .000066  I -.3666147  .0000027  1.3290 0.0028  I   -60.338     .175    -3.020     .340  0.219290  0.239920 -0.3665910   -60.100    -2.900  
+ 31025 52937.00 I   .218599  .000082   .237824  .000080  I -.3679262  .0000049  1.2645 0.0028  I   -60.532     .179    -2.919     .340  0.218640  0.237720 -0.3679320   -60.300    -2.900  
+ 31026 52938.00 I   .218068  .000074   .235794  .000085  I -.3690870  .0000048  1.0298 0.0036  I   -60.561     .159    -3.018     .340  0.218130  0.235680 -0.3690970   -60.300    -2.900  
+ 31027 52939.00 I   .217046  .000066   .233766  .000079  I -.3699470  .0000054  0.6786 0.0038  I   -60.390     .287    -3.198     .135  0.217130  0.233710 -0.3699450   -60.200    -3.000  
+ 31028 52940.00 I   .215529  .000041   .231563  .000061  I -.3704375  .0000059  0.3074 0.0041  I   -60.090     .327    -3.224     .196  0.215490  0.231520 -0.3704240   -60.000    -3.100  
+ 31029 52941.00 I   .213730  .000046   .229233  .000065  I -.3705941  .0000061  0.0333 0.0043  I   -59.883     .287    -3.071     .217  0.213800  0.229150 -0.3705920   -59.900    -3.200  
+ 31030 52942.00 I   .212408  .000047   .226978  .000068  I -.3705533  .0000062 -0.0932 0.0043  I   -59.873     .287    -2.958     .217  0.212460  0.226900 -0.3705570   -59.700    -3.300  
+ 31031 52943.00 I   .210965  .000048   .225003  .000059  I -.3704455  .0000060 -0.1065 0.0051  I   -59.915     .287    -3.040     .217  0.211060  0.225010 -0.3704340   -59.600    -3.400  
+ 311 1 52944.00 I   .209202  .000048   .223344  .000043  I -.3703748  .0000082 -0.0165 0.0044  I   -59.866     .352    -3.211     .255  0.209260  0.223310 -0.3703860   -59.400    -3.400  
+ 311 2 52945.00 I   .207198  .000050   .221632  .000052  I -.3704382  .0000064  0.1505 0.0052  I   -59.622     .182    -3.240     .188  0.207240  0.221550 -0.3704470   -59.400    -3.200  
+ 311 3 52946.00 I   .205026  .000051   .219556  .000051  I -.3706830  .0000063  0.3392 0.0043  I   -59.334     .298    -3.088     .177  0.205080  0.219480 -0.3706680   -59.200    -3.100  
+ 311 4 52947.00 I   .202693  .000065   .217022  .000067  I -.3711065  .0000058  0.4975 0.0041  I   -59.110     .319    -2.873     .142  0.202740  0.216980 -0.3710900   -59.000    -2.900  
+ 311 5 52948.00 I   .200301  .000062   .214160  .000066  I -.3716507  .0000054  0.5740 0.0039  I   -59.009     .294    -2.665     .128  0.200360  0.214070 -0.3716580   -58.900    -2.800  
+ 311 6 52949.00 I   .198096  .000057   .211227  .000067  I -.3722245  .0000052  0.5605 0.0037  I   -59.020     .294    -2.429     .128  0.198250  0.211100 -0.3722220   -58.900    -2.700  
+ 311 7 52950.00 I   .196256  .000056   .208248  .000067  I -.3727506  .0000050  0.4838 0.0040  I   -59.050     .294    -2.170     .128  0.196320  0.208230 -0.3727430   -58.900    -2.300  
+ 311 8 52951.00 I   .194561  .000057   .205709  .000075  I -.3731858  .0000061  0.3880 0.0038  I   -59.077     .338    -2.023     .143  0.194580  0.205620 -0.3731760   -58.900    -2.000  
+ 311 9 52952.00 I   .192665  .000057   .203467  .000080  I -.3735243  .0000056  0.2851 0.0043  I   -58.943     .275    -2.138     .147  0.192750  0.203370 -0.3735510   -58.900    -2.100  
+ 31110 52953.00 I   .190182  .000045   .201124  .000068  I -.3737455  .0000061  0.1508 0.0044  I   -58.800     .276    -2.438     .340  0.190250  0.201140 -0.3737820   -58.900    -2.300  
+ 31111 52954.00 I   .187191  .000039   .198488  .000071  I -.3738187  .0000067 -0.0051 0.0044  I   -58.676     .291    -2.706     .103  0.187240  0.198490 -0.3738110   -58.800    -2.600  
+ 31112 52955.00 I   .184483  .000056   .196120  .000076  I -.3737645  .0000063 -0.0733 0.0046  I   -58.557     .323    -2.815     .340  0.184520  0.195980 -0.3737240   -58.600    -2.800  
+ 31113 52956.00 I   .182109  .000058   .193783  .000074  I -.3737076  .0000062 -0.0348 0.0041  I   -58.441     .323    -2.843     .340  0.182190  0.193700 -0.3736830   -58.300    -2.900  
+ 31114 52957.00 I   .179892  .000056   .191375  .000061  I -.3737002  .0000052  0.0197 0.0044  I   -58.287     .323    -2.892     .340  0.179870  0.191370 -0.3736890   -57.900    -2.800  
+ 31115 52958.00 I   .177373  .000063   .189100  .000045  I -.3737560  .0000063  0.1012 0.0033  I   -57.999     .352    -2.888     .340  0.177470  0.189040 -0.3737660   -57.600    -2.800  
+ 31116 52959.00 I   .175135  .000075   .187125  .000050  I -.3739256  .0000042  0.2518 0.0040  I   -57.520     .299    -2.754     .340  0.175190  0.187030 -0.3739370   -57.300    -2.600  
+ 31117 52960.00 I   .172811  .000080   .185478  .000049  I -.3742828  .0000049  0.4721 0.0033  I   -57.072     .299    -2.507     .340  0.172860  0.185420 -0.3742740   -57.000    -2.500  
+ 31118 52961.00 I   .170301  .000075   .183783  .000060  I -.3748732  .0000052  0.7026 0.0033  I   -56.911     .214    -2.325     .340  0.170180  0.183740 -0.3748600   -56.800    -2.300  
+ 31119 52962.00 I   .167255  .000066   .181967  .000073  I -.3756701  .0000043  0.8793 0.0034  I   -57.003     .328    -2.270     .340  0.167340  0.181890 -0.3756920   -56.800    -2.200  
+ 31120 52963.00 I   .164407  .000069   .180384  .000077  I -.3766149  .0000043  1.0052 0.0030  I   -57.258     .328    -2.177     .340  0.164430  0.180360 -0.3766400   -56.900    -2.000  
+ 31121 52964.00 I   .161871  .000068   .179057  .000075  I -.3776704  .0000042  1.1006 0.0031  I   -57.539     .328    -1.930     .340  0.161850  0.179120 -0.3776600   -57.100    -1.900  
+ 31122 52965.00 I   .159315  .000040   .178382  .000072  I -.3787681  .0000045  1.0519 0.0030  I   -57.855     .335    -1.673     .340  0.159410  0.178310 -0.3787760   -57.300    -1.900  
+ 31123 52966.00 I   .156598  .000049   .177794  .000067  I -.3797096  .0000042  0.8094 0.0030  I   -58.088     .267    -1.631     .340  0.156660  0.177700 -0.3797530   -57.500    -1.900  
+ 31124 52967.00 I   .153411  .000047   .176861  .000059  I -.3803632  .0000041  0.4958 0.0032  I   -58.025     .338    -1.781     .340  0.153490  0.176770 -0.3803940   -57.600    -1.900  
+ 31125 52968.00 I   .149829  .000054   .175601  .000048  I -.3807043  .0000049  0.1915 0.0032  I   -57.674     .316    -1.877     .340  0.149710  0.175550 -0.3806940   -57.400    -1.900  
+ 31126 52969.00 I   .145159  .000054   .174197  .000045  I -.3807785  .0000048 -0.0158 0.0034  I   -57.318     .316    -1.819     .340  0.145320  0.174190 -0.3807670   -57.100    -1.800  
+ 31127 52970.00 I   .141261  .000050   .172966  .000044  I -.3807255  .0000048 -0.0647 0.0032  I   -57.158     .316    -1.792     .340  0.141260  0.172870 -0.3807190   -56.700    -1.800  
+ 31128 52971.00 I   .137856  .000046   .171859  .000043  I -.3806939  .0000043  0.0208 0.0031  I   -57.100     .316    -1.954     .340  0.137930  0.171760 -0.3807010   -56.300    -1.700  
+ 31129 52972.00 I   .134327  .000046   .170606  .000042  I -.3807906  .0000040  0.1768 0.0027  I   -57.013     .420    -2.151     .340  0.134400  0.170550 -0.3808080   -56.200    -1.700  
+ 31130 52973.00 I   .130325  .000045   .169150  .000053  I -.3810472  .0000031  0.3320 0.0026  I   -56.869     .279    -2.095     .340  0.130400  0.169040 -0.3810580   -56.300    -1.600  
+ 312 1 52974.00 I   .126424  .000040   .167828  .000050  I -.3814438  .0000034  0.4547 0.0022  I   -56.817     .279    -1.743     .340  0.126440  0.167710 -0.3814390   -56.500    -1.400  
+ 312 2 52975.00 I   .123273  .000045   .166663  .000061  I -.3819391  .0000032  0.5247 0.0023  I   -56.871     .258    -1.344     .340  0.123160  0.166610 -0.3819270   -56.800    -1.300  
+ 312 3 52976.00 I   .120088  .000061   .165470  .000081  I -.3824681  .0000030  0.5193 0.0022  I   -56.964     .220    -1.114     .340  0.120170  0.165390 -0.3824720   -57.000    -1.100  
+ 312 4 52977.00 I   .116990  .000067   .164469  .000079  I -.3829558  .0000030  0.4481 0.0021  I   -57.058     .220    -1.023     .340  0.117050  0.164370 -0.3829730   -57.000    -1.000  
+ 312 5 52978.00 I   .113970  .000064   .163757  .000076  I -.3833545  .0000028  0.3475 0.0026  I   -57.110     .220     -.946     .340  0.114130  0.163830 -0.3833480   -57.000    -1.000  
+ 312 6 52979.00 I   .111335  .000070   .163476  .000071  I -.3836462  .0000043  0.2333 0.0025  I   -57.055     .137     -.894     .340  0.111400  0.163450 -0.3836440   -57.000    -1.000  
+ 312 7 52980.00 I   .108466  .000073   .163098  .000072  I -.3838085  .0000041  0.0814 0.0027  I   -56.885     .121    -1.002     .340  0.108520  0.162960 -0.3838250   -56.900    -1.200  
+ 312 8 52981.00 I   .105420  .000066   .162535  .000073  I -.3837934  .0000033 -0.1174 0.0026  I   -56.717     .116    -1.276     .340  0.105460  0.162450 -0.3837940   -56.800    -1.300  
+ 312 9 52982.00 I   .102491  .000054   .162009  .000057  I -.3835759  .0000033 -0.3097 0.0024  I   -56.625     .252    -1.554     .340  0.102520  0.162010 -0.3835510   -56.700    -1.500  
+ 31210 52983.00 I   .099884  .000058   .161513  .000066  I -.3832108  .0000034 -0.3917 0.0024  I   -56.545     .312    -1.686     .102  0.099840  0.161520 -0.3832000   -56.400    -1.600  
+ 31211 52984.00 I   .096736  .000057   .160989  .000064  I -.3828200  .0000035 -0.3913 0.0024  I   -56.362     .312    -1.683     .102  0.096870  0.160960 -0.3828340   -56.000    -1.700  
+ 31212 52985.00 I   .093238  .000055   .160263  .000072  I -.3824450  .0000033 -0.3407 0.0023  I   -56.048     .312    -1.653     .102  0.093360  0.160300 -0.3824450   -55.500    -1.700  
+ 31213 52986.00 I   .089737  .000051   .159501  .000077  I -.3821565  .0000029 -0.2364 0.0024  I   -55.658     .297    -1.633     .340  0.089740  0.159450 -0.3821680   -55.000    -1.700  
+ 31214 52987.00 I   .086417  .000050   .158868  .000094  I -.3819878  .0000034 -0.0852 0.0023  I   -55.274     .329    -1.574     .122  0.086450  0.158710 -0.3819980   -54.700    -1.600  
+ 31215 52988.00 I   .083454  .000050   .158563  .000088  I -.3820082  .0000036  0.1323 0.0023  I   -54.999     .321    -1.473     .139  0.083500  0.158510 -0.3820050   -54.500    -1.500  
+ 31216 52989.00 I   .080534  .000038   .158331  .000075  I -.3822631  .0000030  0.3820 0.0024  I   -54.906     .171    -1.405     .112  0.080610  0.158360 -0.3822560   -54.600    -1.400  
+ 31217 52990.00 I   .077537  .000044   .158131  .000076  I -.3827676  .0000032  0.6181 0.0022  I   -54.912     .180    -1.396     .340  0.077620  0.158050 -0.3827510   -54.800    -1.500  
+ 31218 52991.00 I   .074455  .000045   .157692  .000070  I -.3834652  .0000032  0.7520 0.0023  I   -55.073     .180    -1.304     .340  0.074480  0.157650 -0.3834390   -55.000    -1.300  
+ 31219 52992.00 I   .071386  .000045   .157191  .000065  I -.3842398  .0000032  0.7906 0.0026  I   -55.383     .180    -1.057     .340  0.071480  0.157210 -0.3842270   -55.200    -1.100  
+ 31220 52993.00 I   .068869  .000045   .156874  .000038  I -.3850195  .0000042  0.7485 0.0028  I   -55.907     .177     -.787     .340  0.068890  0.156860 -0.3850240   -55.500    -0.900  
+ 31221 52994.00 I   .066299  .000047   .156453  .000038  I -.3856933  .0000047  0.5758 0.0037  I   -56.487     .167     -.727     .340  0.066350  0.156400 -0.3857350   -55.800    -0.800  
+ 31222 52995.00 I   .063459  .000050   .155926  .000042  I -.3861387  .0000060  0.3058 0.0043  I   -56.792     .163     -.907     .340  0.063520  0.155850 -0.3861900   -56.000    -0.900  
+ 31223 52996.00 I   .060462  .000048   .155491  .000032  I -.3863147  .0000071  0.0651 0.0046  I   -56.671     .194    -1.113     .340  0.060390  0.155410 -0.3863100   -56.200    -1.000  
+ 31224 52997.00 I   .056600  .000045   .155110  .000034  I -.3863313  .0000071  0.0114 0.0050  I   -56.269     .167    -1.155     .340  0.056690  0.155070 -0.3862360   -56.100    -1.200  
+ 31225 52998.00 I   .052596  .000044   .154775  .000040  I -.3863873  .0000071  0.1069 0.0049  I   -55.891     .167    -1.176     .340  0.052620  0.154710 -0.3862160   -55.900    -1.400  
+ 31226 52999.00 I   .048916  .000048   .154525  .000036  I -.3865594  .0000067  0.2452 0.0047  I   -55.553     .167    -1.292     .340  0.048950  0.154440 -0.3863760   -55.800    -1.500  
+ 31227 53000.00 I   .045817  .000043   .154540  .000042  I -.3868836  .0000062  0.4011 0.0038  I   -55.263     .402    -1.407     .340  0.045870  0.154430 -0.3867280   -55.600    -1.400  
+ 31228 53001.00 I   .042882  .000042   .154743  .000044  I -.3873512  .0000034  0.5258 0.0037  I   -55.121     .288    -1.284     .340  0.042940  0.154660 -0.3872450   -55.600    -1.100  
+ 31229 53002.00 I   .039839  .000042   .154760  .000045  I -.3879174  .0000041  0.5970 0.0028  I   -55.265     .288     -.881     .340  0.039910  0.154710 -0.3878690   -55.600    -0.800  
+ 31230 53003.00 I   .037049  .000044   .154451  .000046  I -.3885246  .0000044  0.6066 0.0032  I   -55.612     .288     -.464     .340  0.037030  0.154430 -0.3885140   -55.800    -0.500  
+ 31231 53004.00 I   .034038  .000052   .154141  .000045  I -.3891136  .0000050  0.5654 0.0033  I   -55.957     .288     -.296     .340  0.034120  0.154100 -0.3890920   -55.900    -0.200  
+ 4 1 1 53005.00 I   .031243  .000047   .153836  .000043  I -.3896476  .0000049  0.5008 0.0035  I   -56.182     .288     -.356     .340  0.031250  0.153770 -0.3895920   -56.100    -0.100  
+ 4 1 2 53006.00 I   .028845  .000054   .153671  .000039  I -.3901039  .0000050  0.4025 0.0046  I   -56.267     .288     -.447     .340  0.028870  0.153550 -0.3900740   -56.100    -0.200  
+ 4 1 3 53007.00 I   .026638  .000051   .153848  .000031  I -.3904342  .0000077  0.2492 0.0037  I   -56.230     .740     -.510     .340  0.026700  0.153740 -0.3904550   -56.000    -0.400  
+ 4 1 4 53008.00 I   .024195  .000056   .154295  .000031  I -.3905978  .0000054  0.0825 0.0046  I   -56.014     .244     -.595     .340  0.024260  0.154230 -0.3906300   -55.900    -0.600  
+ 4 1 5 53009.00 I   .021490  .000054   .154845  .000028  I -.3906122  .0000051 -0.0453 0.0037  I   -55.791     .244     -.810     .340  0.021590  0.154800 -0.3906200   -55.700    -0.900  
+ 4 1 6 53010.00 I   .018789  .000053   .155467  .000041  I -.3905340  .0000051 -0.0926 0.0037  I   -55.682     .285    -1.079     .340  0.018790  0.155440 -0.3905240   -55.500    -1.000  
+ 4 1 7 53011.00 I   .015861  .000055   .156209  .000065  I -.3904593  .0000053 -0.0429 0.0037  I   -55.620     .244    -1.244     .340  0.015960  0.156150 -0.3904520   -55.200    -1.100  
+ 4 1 8 53012.00 I   .012902  .000050   .156907  .000066  I -.3904692  .0000053  0.0698 0.0035  I   -55.433     .244    -1.241     .340  0.012990  0.156850 -0.3904660   -54.900    -1.100  
+ 4 1 9 53013.00 I   .010072  .000046   .157332  .000060  I -.3906221  .0000047  0.2522 0.0038  I   -55.072     .244    -1.140     .340  0.010150  0.157360 -0.3906230   -54.600    -1.100  
+ 4 110 53014.00 I   .007588  .000057   .157654  .000069  I -.3909924  .0000054  0.4911 0.0033  I   -54.671     .255    -1.050     .340  0.007710  0.157630 -0.3909980   -54.400    -1.200  
+ 4 111 53015.00 I   .005350  .000068   .157928  .000068  I -.3916090  .0000045  0.7442 0.0035  I   -54.387     .266    -1.023     .340  0.005380  0.157840 -0.3916020   -54.200    -1.300  
+ 4 112 53016.00 I   .003047  .000066   .158344  .000065  I -.3924797  .0000046  0.9938 0.0029  I   -54.273     .252    -1.041     .149  0.003030  0.158320 -0.3924550   -54.100    -1.300  
+ 4 113 53017.00 I   .001080  .000059   .159023  .000048  I -.3935837  .0000038  1.2045 0.0030  I   -54.289     .258    -1.066     .169  0.001150  0.159010 -0.3935690   -54.100    -1.100  
+ 4 114 53018.00 I  -.001154  .000067   .160078  .000053  I -.3948469  .0000039  1.2899 0.0028  I   -54.306     .293    -1.052     .143 -0.000940  0.159990 -0.3948590   -54.100    -0.700  
+ 4 115 53019.00 I  -.003301  .000073   .161382  .000055  I -.3961148  .0000040  1.2293 0.0028  I   -54.461     .293     -.939     .143 -0.003280  0.161360 -0.3961320   -54.400    -0.600  
+ 4 116 53020.00 I  -.005375  .000068   .162622  .000050  I -.3972758  .0000039  1.0795 0.0033  I   -54.740     .293     -.738     .143 -0.005390  0.162610 -0.3972730   -54.900    -0.600  
+ 4 117 53021.00 I  -.007599  .000050   .163770  .000046  I -.3982441  .0000053  0.8407 0.0029  I   -55.192     .296     -.564     .179 -0.007540  0.163700 -0.3982610   -55.300    -0.700  
+ 4 118 53022.00 I  -.010223  .000049   .165081  .000059  I -.3989457  .0000042  0.5676 0.0031  I   -55.710     .282     -.569     .340 -0.010170  0.165030 -0.3989770   -55.700    -0.700  
+ 4 119 53023.00 I  -.013233  .000052   .166330  .000086  I -.3993949  .0000031  0.3415 0.0026  I   -56.056     .248     -.777     .340 -0.013220  0.166280 -0.3994140   -55.900    -0.800  
+ 4 120 53024.00 I  -.016197  .000051   .167243  .000092  I -.3996602  .0000031  0.2100 0.0023  I   -56.077     .220    -1.037     .340 -0.016180  0.167220 -0.3996580   -55.900    -0.900  
+ 4 121 53025.00 I  -.018658  .000061   .168258  .000104  I -.3998530  .0000033  0.1930 0.0023  I   -55.842     .244    -1.234     .117 -0.018640  0.168310 -0.3998410   -55.600    -1.100  
+ 4 122 53026.00 I  -.021139  .000064   .169988  .000103  I -.4000827  .0000035  0.2857 0.0024  I   -55.472     .244    -1.277     .117 -0.021090  0.169990 -0.4000790   -55.300    -1.200  
+ 4 123 53027.00 I  -.024162  .000059   .171751  .000102  I -.4004467  .0000035  0.4455 0.0030  I   -55.057     .244    -1.314     .117 -0.023830  0.171790 -0.4004350   -54.900    -1.300  
+ 4 124 53028.00 I  -.026309  .000058   .173183  .000099  I -.4009745  .0000048  0.6078 0.0032  I   -54.694     .266    -1.358     .123 -0.026220  0.173120 -0.4009750   -54.800    -1.300  
+ 4 125 53029.00 I  -.027928  .000065   .174510  .000053  I -.4016567  .0000053  0.7534 0.0036  I   -54.517     .338    -1.256     .340 -0.027880  0.174430 -0.4016610   -54.800    -1.100  
+ 4 126 53030.00 I  -.029159  .000066   .175921  .000048  I -.4024644  .0000054  0.8483 0.0038  I   -54.690     .338    -1.005     .340 -0.029110  0.175870 -0.4024540   -55.000    -0.900  
+ 4 127 53031.00 I  -.030234  .000040   .177464  .000025  I -.4033160  .0000055  0.8313 0.0037  I   -55.141     .329     -.780     .340 -0.030220  0.177420 -0.4033020   -55.300    -0.700  
+ 4 128 53032.00 I  -.031666  .000044   .179219  .000030  I -.4040869  .0000052  0.6940 0.0038  I   -55.636     .309     -.764     .340 -0.031610  0.179160 -0.4040940   -55.500    -0.700  
+ 4 129 53033.00 I  -.033515  .000046   .181091  .000030  I -.4046819  .0000052  0.4903 0.0030  I   -55.982     .309     -.922     .340 -0.033490  0.181000 -0.4046910   -55.700    -0.800  
+ 4 130 53034.00 I  -.036001  .000045   .182952  .000029  I -.4050549  .0000031  0.2489 0.0035  I   -56.103     .309    -1.066     .340 -0.035950  0.182930 -0.4050420   -55.700    -1.000  
+ 4 131 53035.00 I  -.038965  .000042   .184614  .000041  I -.4051878  .0000047  0.0319 0.0027  I   -55.988     .229    -1.133     .340 -0.038950  0.184640 -0.4051900   -55.600    -1.200  
+ 4 2 1 53036.00 I  -.042056  .000061   .185945  .000071  I -.4051408  .0000045 -0.1188 0.0033  I   -55.661     .215    -1.171     .127 -0.042020  0.185890 -0.4051460   -55.300    -1.300  
+ 4 2 2 53037.00 I  -.045030  .000060   .187071  .000067  I -.4049664  .0000047 -0.2210 0.0031  I   -55.286     .208    -1.332     .127 -0.044930  0.186970 -0.4049600   -55.000    -1.500  
+ 4 2 3 53038.00 I  -.047780  .000056   .188139  .000071  I -.4047150  .0000042 -0.2745 0.0039  I   -55.040     .161    -1.596     .149 -0.047970  0.188030 -0.4047120   -54.800    -1.600  
+ 4 2 4 53039.00 I  -.051232  .000058   .189043  .000077  I -.4044364  .0000063 -0.2709 0.0038  I   -54.939     .145    -1.815     .152 -0.051200  0.188970 -0.4044510   -54.600    -1.700  
+ 4 2 5 53040.00 I  -.054195  .000062   .189858  .000077  I -.4042062  .0000063 -0.1684 0.0045  I   -54.847     .145    -1.866     .152 -0.054160  0.189780 -0.4042020   -54.500    -1.700  
+ 4 2 6 53041.00 I  -.056738  .000060   .190689  .000076  I -.4041262  .0000064  0.0137 0.0046  I   -54.656     .145    -1.756     .152 -0.056640  0.190710 -0.4041170   -54.400    -1.800  
+ 4 2 7 53042.00 I  -.058821  .000042   .192020  .000065  I -.4042553  .0000066  0.2607 0.0044  I   -54.412     .137    -1.598     .151 -0.058780  0.191970 -0.4042390   -54.300    -1.800  
+ 4 2 8 53043.00 I  -.060682  .000050   .193628  .000083  I -.4046569  .0000059  0.5355 0.0045  I   -54.251     .190    -1.522     .140 -0.060610  0.193540 -0.4046350   -54.200    -1.700  
+ 4 2 9 53044.00 I  -.062590  .000053   .195344  .000085  I -.4053066  .0000060  0.7512 0.0035  I   -54.236     .190    -1.559     .140 -0.062540  0.195330 -0.4052940   -54.300    -1.600  
+ 4 210 53045.00 I  -.064870  .000048   .197068  .000078  I -.4061326  .0000036  0.8866 0.0034  I   -54.363     .194    -1.640     .155 -0.064880  0.197140 -0.4061210   -54.300    -1.500  
+ 4 211 53046.00 I  -.067746  .000048   .199078  .000087  I -.4070517  .0000033  0.9375 0.0025  I   -54.587     .170    -1.669     .161 -0.067650  0.199070 -0.4070350   -54.500    -1.400  
+ 4 212 53047.00 I  -.070770  .000045   .200926  .000090  I -.4079707  .0000034  0.8775 0.0024  I   -54.851     .170    -1.607     .161 -0.070720  0.200890 -0.4079620   -54.700    -1.300  
+ 4 213 53048.00 I  -.073863  .000045   .202589  .000084  I -.4087685  .0000034  0.7028 0.0021  I   -55.095     .170    -1.498     .161 -0.073760  0.202610 -0.4087570   -54.900    -1.300  
+ 4 214 53049.00 I  -.076809  .000031   .204460  .000067  I -.4093573  .0000026  0.4712 0.0021  I   -55.325     .132    -1.423     .150 -0.076740  0.204440 -0.4093720   -55.100    -1.300  
+ 4 215 53050.00 I  -.079498  .000033   .206272  .000075  I -.4097155  .0000025  0.2534 0.0018  I   -55.385     .116    -1.463     .129 -0.079460  0.206200 -0.4097500   -55.100    -1.400  
+ 4 216 53051.00 I  -.081563  .000035   .208061  .000076  I -.4098881  .0000025  0.1077 0.0020  I   -55.305     .169    -1.621     .116 -0.081510  0.208070 -0.4099010   -55.100    -1.500  
+ 4 217 53052.00 I  -.082858  .000041   .210006  .000090  I -.4099668  .0000031  0.0698 0.0020  I   -55.105     .348    -1.830     .130 -0.082870  0.210050 -0.4099550   -54.900    -1.800  
+ 4 218 53053.00 I  -.084378  .000051   .212353  .000110  I -.4100719  .0000031  0.1646 0.0023  I   -54.856     .313    -1.995     .117 -0.084210  0.212270 -0.4100770   -54.600    -2.000  
+ 4 219 53054.00 I  -.086640  .000048   .214811  .000105  I -.4103323  .0000033  0.3683 0.0023  I   -54.616     .313    -2.072     .117 -0.086570  0.214860 -0.4103380   -54.400    -2.100  
+ 4 220 53055.00 I  -.090048  .000045   .217043  .000093  I -.4108259  .0000034  0.6241 0.0030  I   -54.378     .311    -2.117     .113 -0.089840  0.217220 -0.4108150   -54.300    -2.100  
+ 4 221 53056.00 I  -.093073  .000054   .219531  .000095  I -.4115704  .0000049  0.8495 0.0024  I   -54.168     .359    -2.091     .118 -0.093010  0.219500 -0.4115850   -54.300    -2.100  
+ 4 222 53057.00 I  -.095702  .000062   .222041  .000102  I -.4125003  .0000034  1.0012 0.0029  I   -54.053     .333    -2.024     .122 -0.095640  0.221970 -0.4125160   -54.300    -2.000  
+ 4 223 53058.00 I  -.097955  .000056   .224286  .000092  I -.4135463  .0000032  1.0734 0.0022  I   -54.143     .209    -1.939     .340 -0.097910  0.224270 -0.4135320   -54.400    -1.900  
+ 4 224 53059.00 I  -.099789  .000055   .226364  .000068  I -.4146110  .0000027  1.0372 0.0022  I   -54.460     .378    -1.922     .340 -0.099810  0.226380 -0.4145990   -54.500    -1.900  
+ 4 225 53060.00 I  -.101338  .000077   .228642  .000070  I -.4155850  .0000029  0.8939 0.0021  I   -54.885     .338    -2.035     .340 -0.101260  0.228610 -0.4155980   -54.600    -2.000  
+ 4 226 53061.00 I  -.102537  .000074   .231016  .000075  I -.4163810  .0000032  0.6971 0.0022  I   -55.230     .338    -2.216     .340 -0.102480  0.230940 -0.4163790   -54.700    -2.200  
+ 4 227 53062.00 I  -.104291  .000071   .233424  .000069  I -.4169806  .0000033  0.5046 0.0028  I   -55.343     .338    -2.330     .340 -0.103900  0.233390 -0.4169680   -54.600    -2.400  
+ 4 228 53063.00 I  -.105954  .000069   .235830  .000049  I -.4173787  .0000047  0.2777 0.0027  I   -55.261     .455    -2.309     .340 -0.105970  0.235800 -0.4173890   -54.500    -2.500  
+ 4 229 53064.00 I  -.108397  .000066   .237913  .000045  I -.4175324  .0000042  0.0400 0.0032  I   -54.831     .373    -2.338     .340 -0.108330  0.237830 -0.4175520   -54.200    -2.600  
+ 4 3 1 53065.00 I  -.110491  .000060   .239912  .000044  I -.4174875  .0000042 -0.1112 0.0027  I   -54.292     .373    -2.495     .340 -0.110480  0.239820 -0.4174860   -53.900    -2.600  
+ 4 3 2 53066.00 I  -.112159  .000052   .242099  .000055  I -.4173486  .0000033 -0.1467 0.0026  I   -53.828     .305    -2.763     .340 -0.112280  0.242030 -0.4173340   -53.600    -2.700  
+ 4 3 3 53067.00 I  -.114042  .000064   .244217  .000063  I -.4172252  .0000030 -0.0890 0.0023  I   -53.572     .266    -3.017     .112 -0.113870  0.244170 -0.4172170   -53.400    -2.900  
+ 4 3 4 53068.00 I  -.115336  .000065   .246373  .000067  I -.4171986  .0000031  0.0525 0.0021  I   -53.530     .266    -3.146     .112 -0.115450  0.246340 -0.4171940   -53.300    -3.100  
+ 4 3 5 53069.00 I  -.117603  .000061   .248810  .000070  I -.4173536  .0000029  0.2640 0.0020  I   -53.585     .266    -3.125     .112 -0.117240  0.248810 -0.4173440   -53.100    -3.200  
+ 4 3 6 53070.00 I  -.118999  .000074   .251503  .000074  I -.4177371  .0000025  0.5068 0.0019  I   -53.658     .346    -2.977     .154 -0.118920  0.251420 -0.4177250   -53.000    -3.200  
+ 4 3 7 53071.00 I  -.120336  .000080   .254069  .000075  I -.4183644  .0000024  0.7412 0.0018  I   -53.590     .308    -2.832     .143 -0.120260  0.254030 -0.4183150   -52.900    -3.000  
+ 4 3 8 53072.00 I  -.121594  .000088   .256227  .000077  I -.4191954  .0000027  0.9035 0.0018  I   -53.561     .268    -2.758     .158 -0.121520  0.256150 -0.4191520   -53.000    -2.800  
+ 4 3 9 53073.00 I  -.122122  .000069   .258077  .000068  I -.4201289  .0000028  0.9385 0.0020  I   -53.713     .255    -2.786     .126 -0.122270  0.258000 -0.4201170   -53.300    -2.700  
+ 4 310 53074.00 I  -.123028  .000069   .260069  .000080  I -.4210231  .0000029  0.8256 0.0024  I   -54.060     .224    -2.873     .109 -0.122910  0.260000 -0.4210240   -54.000    -2.800  
+ 4 311 53075.00 I  -.123778  .000074   .262111  .000077  I -.4217423  .0000038  0.5994 0.0024  I   -54.444     .224    -2.951     .109 -0.123690  0.262090 -0.4217560   -54.400    -2.900  
+ 4 312 53076.00 I  -.124453  .000069   .264041  .000080  I -.4222139  .0000039  0.3490 0.0037  I   -54.663     .224    -2.992     .109 -0.124390  0.264080 -0.4222000   -54.600    -3.000  
+ 4 313 53077.00 I  -.125195  .000051   .266227  .000081  I -.4224543  .0000064  0.1404 0.0035  I   -54.689     .391    -2.989     .120 -0.125150  0.266190 -0.4224630   -54.500    -3.100  
+ 4 314 53078.00 I  -.126023  .000046   .268480  .000073  I -.4225155  .0000059 -0.0057 0.0043  I   -54.399     .414    -3.020     .340 -0.125960  0.268470 -0.4225910   -54.100    -3.100  
+ 4 315 53079.00 I  -.126916  .000045   .270668  .000069  I -.4224794  .0000058 -0.0423 0.0044  I   -53.973     .414    -3.087     .340 -0.126830  0.270610 -0.4225390   -53.500    -3.100  
+ 4 316 53080.00 I  -.128139  .000055   .272811  .000039  I -.4224683  .0000064  0.0333 0.0047  I   -53.526     .553    -3.199     .340 -0.128020  0.272740 -0.4224570   -52.900    -3.100  
+ 4 317 53081.00 I  -.129178  .000057   .274874  .000038  I -.4225790  .0000073  0.2078 0.0053  I   -53.153     .466    -3.328     .340 -0.129130  0.274780 -0.4225720   -52.600    -3.200  
+ 4 318 53082.00 I  -.130049  .000059   .277122  .000035  I -.4229104  .0000084  0.4619 0.0055  I   -52.919     .466    -3.416     .340 -0.130030  0.277030 -0.4229130   -52.600    -3.300  
+ 4 319 53083.00 I  -.131304  .000062   .279565  .000034  I -.4235105  .0000081  0.7390 0.0065  I   -52.835     .466    -3.414     .340 -0.131010  0.279470 -0.4234930   -52.700    -3.400  
+ 4 320 53084.00 I  -.131697  .000068   .281978  .000039  I -.4243780  .0000098  0.9848 0.0057  I   -52.840     .335    -3.307     .106 -0.131650  0.281880 -0.4243930   -52.800    -3.400  
+ 4 321 53085.00 I  -.131870  .000068   .284727  .000048  I -.4254451  .0000080  1.1257 0.0064  I   -52.883     .288    -3.163     .340 -0.131780  0.284630 -0.4255200   -53.000    -3.300  
+ 4 322 53086.00 I  -.131969  .000075   .287888  .000052  I -.4265916  .0000081  1.1531 0.0053  I   -52.936     .288    -3.065     .340 -0.131850  0.287800 -0.4266280   -53.100    -3.200  
+ 4 323 53087.00 I  -.131752  .000060   .291271  .000057  I -.4277318  .0000071  1.1220 0.0049  I   -53.051     .254    -3.096     .340 -0.131810  0.291260 -0.4277180   -53.100    -3.200  
+ 4 324 53088.00 I  -.132110  .000060   .294885  .000067  I -.4288185  .0000056  1.0395 0.0045  I   -53.258     .294    -3.257     .340 -0.132020  0.294870 -0.4288330   -53.100    -3.200  
+ 4 325 53089.00 I  -.132884  .000061   .298383  .000067  I -.4297922  .0000055  0.9013 0.0038  I   -53.471     .294    -3.447     .340 -0.132830  0.298330 -0.4298080   -53.000    -3.400  
+ 4 326 53090.00 I  -.134150  .000062   .301745  .000060  I -.4306106  .0000052  0.7315 0.0039  I   -53.538     .294    -3.556     .340 -0.134010  0.301770 -0.4306060   -53.000    -3.600  
+ 4 327 53091.00 I  -.135581  .000052   .305184  .000061  I -.4312531  .0000055  0.5554 0.0032  I   -53.405     .345    -3.587     .102 -0.135510  0.305200 -0.4312590   -52.800    -3.700  
+ 4 328 53092.00 I  -.136937  .000060   .308389  .000081  I -.4317347  .0000038  0.4193 0.0033  I   -53.051     .301    -3.674     .340 -0.136880  0.308330 -0.4317360   -52.600    -3.900  
+ 4 329 53093.00 I  -.137966  .000061   .311513  .000079  I -.4321212  .0000037  0.3719 0.0025  I   -52.560     .301    -3.881     .340 -0.137840  0.311480 -0.4321140   -52.400    -4.000  
+ 4 330 53094.00 I  -.138634  .000061   .314635  .000073  I -.4325099  .0000032  0.4188 0.0024  I   -52.010     .204    -4.140     .340 -0.138680  0.314710 -0.4325020   -52.000    -4.100  
+ 4 331 53095.00 I  -.139515  .000065   .317748  .000072  I -.4329864  .0000031  0.5484 0.0023  I   -51.575     .254    -4.347     .108 -0.139440  0.317740 -0.4329880   -51.700    -4.300  
+ 4 4 1 53096.00 I  -.140248  .000065   .320643  .000076  I -.4336295  .0000034  0.7464 0.0022  I   -51.461     .254    -4.481     .108 -0.140150  0.320590 -0.4336250   -51.400    -4.500  
+ 4 4 2 53097.00 I  -.140804  .000071   .323365  .000071  I -.4344855  .0000031  0.9634 0.0023  I   -51.665     .254    -4.562     .108 -0.140650  0.323290 -0.4344790   -51.300    -4.600  
+ 4 4 3 53098.00 I  -.140861  .000064   .326042  .000041  I -.4355652  .0000031  1.2070 0.0021  I   -51.948     .435    -4.493     .259 -0.140730  0.325970 -0.4355490   -51.400    -4.600  
+ 4 4 4 53099.00 I  -.141000  .000065   .328657  .000045  I -.4368965  .0000028  1.4414 0.0021  I   -52.016     .455    -4.318     .166 -0.140850  0.328620 -0.4368240   -51.600    -4.400  
+ 4 4 5 53100.00 I  -.141192  .000062   .331008  .000050  I -.4384084  .0000028  1.5570 0.0024  I   -52.007     .409    -4.039     .198 -0.141110  0.330940 -0.4383520   -52.100    -4.100  
+ 4 4 6 53101.00 I  -.140714  .000057   .333326  .000066  I -.4399626  .0000040  1.5290 0.0023  I   -52.215     .380    -3.846     .166 -0.140720  0.333270 -0.4399620   -52.500    -4.000  
+ 4 4 7 53102.00 I  -.140149  .000053   .336180  .000070  I -.4414172  .0000036  1.3535 0.0034  I   -52.703     .380    -3.878     .166 -0.140070  0.336140 -0.4414210   -52.700    -4.100  
+ 4 4 8 53103.00 I  -.139967  .000052   .339273  .000066  I -.4426289  .0000056  1.0558 0.0033  I   -53.187     .380    -4.088     .166 -0.139870  0.339300 -0.4426250   -53.000    -4.100  
+ 4 4 9 53104.00 I  -.139743  .000041   .342518  .000074  I -.4435322  .0000056  0.7682 0.0047  I   -53.342     .380    -4.317     .166 -0.139720  0.342460 -0.4435230   -53.300    -4.200  
+ 4 410 53105.00 I  -.139228  .000040   .345818  .000079  I -.4441832  .0000075  0.5344 0.0041  I   -53.112     .127    -4.460     .178 -0.139160  0.345730 -0.4441910   -53.200    -4.200  
+ 4 411 53106.00 I  -.138787  .000041   .349170  .000075  I -.4446215  .0000061  0.3621 0.0052  I   -52.691     .119    -4.524     .340 -0.138700  0.349120 -0.4446890   -52.800    -4.300  
+ 4 412 53107.00 I  -.138905  .000039   .352330  .000076  I -.4449578  .0000073  0.3411 0.0038  I   -52.262     .205    -4.562     .340 -0.138820  0.352320 -0.4450120   -52.300    -4.400  
+ 4 413 53108.00 I  -.139082  .000054   .355170  .000071  I -.4453570  .0000045  0.4801 0.0038  I   -51.886     .187    -4.603     .340 -0.139050  0.355180 -0.4453520   -51.800    -4.500  
+ 4 414 53109.00 I  -.139115  .000058   .357994  .000076  I -.4459439  .0000024  0.6968 0.0026  I   -51.560     .235    -4.641     .340 -0.139020  0.357970 -0.4459340   -51.500    -4.600  
+ 4 415 53110.00 I  -.138580  .000058   .360790  .000064  I -.4467417  .0000024  0.8869 0.0018  I   -51.317     .235    -4.643     .340 -0.138500  0.360750 -0.4467570   -51.300    -4.500  
+ 4 416 53111.00 I  -.137662  .000058   .363695  .000064  I -.4476964  .0000026  1.0131 0.0018  I   -51.236     .235    -4.559     .340 -0.137280  0.363660 -0.4476920   -51.200    -4.400  
+ 4 417 53112.00 I  -.135955  .000074   .367039  .000059  I -.4487422  .0000027  1.0621 0.0018  I   -51.344     .275    -4.359     .124 -0.135880  0.367000 -0.4487340   -51.200    -4.200  
+ 4 418 53113.00 I  -.134731  .000076   .370453  .000059  I -.4497902  .0000026  1.0198 0.0019  I   -51.543     .388    -4.089     .144 -0.134630  0.370400 -0.4498170   -51.300    -3.900  
+ 4 419 53114.00 I  -.133524  .000073   .373815  .000056  I -.4507553  .0000026  0.8978 0.0023  I   -51.689     .388    -3.888     .144 -0.133420  0.373690 -0.4507790   -51.300    -3.800  
+ 4 420 53115.00 I  -.132568  .000068   .377234  .000057  I -.4515622  .0000038  0.7048 0.0024  I   -51.740     .550    -3.894     .148 -0.132720  0.377200 -0.4515530   -51.300    -3.700  
+ 4 421 53116.00 I  -.132997  .000077   .380324  .000064  I -.4521541  .0000040  0.4794 0.0028  I   -51.660     .418    -4.075     .340 -0.132860  0.380270 -0.4521440   -51.300    -3.900  
+ 4 422 53117.00 I  -.133111  .000072   .382857  .000064  I -.4525177  .0000042  0.2442 0.0029  I   -51.707     .418    -4.367     .340 -0.133030  0.382740 -0.4525130   -51.200    -4.100  
+ 4 423 53118.00 I  -.132957  .000069   .385157  .000066  I -.4526419  .0000041  0.0072 0.0032  I   -51.718     .418    -4.562     .340 -0.132900  0.385140 -0.4526290   -51.200    -4.400  
+ 4 424 53119.00 I  -.132759  .000060   .387283  .000057  I -.4525565  .0000049 -0.1566 0.0031  I   -51.588     .353    -4.654     .340 -0.132680  0.387240 -0.4525500   -51.200    -4.700  
+ 4 425 53120.00 I  -.132086  .000067   .389107  .000055  I -.4523604  .0000046 -0.2251 0.0034  I   -51.481     .419    -4.778     .340 -0.132000  0.389000 -0.4523700   -51.200    -4.900  
+ 4 426 53121.00 I  -.130578  .000068   .390893  .000058  I -.4521354  .0000046 -0.2061 0.0033  I   -51.281     .419    -4.997     .340 -0.130460  0.390820 -0.4521400   -51.100    -5.100  
+ 4 427 53122.00 I  -.128362  .000068   .392863  .000040  I -.4519818  .0000047 -0.0861 0.0031  I   -50.896     .395    -5.203     .340 -0.128460  0.392810 -0.4519700   -51.000    -5.200  
+ 4 428 53123.00 I  -.126734  .000083   .395216  .000053  I -.4519886  .0000042  0.1101 0.0032  I   -50.413     .330    -5.284     .126 -0.126640  0.395120 -0.4519830   -50.700    -5.200  
+ 4 429 53124.00 I  -.125093  .000085   .398005  .000050  I -.4522144  .0000044  0.3436 0.0030  I   -50.160     .330    -5.302     .126 -0.125000  0.397910 -0.4522110   -50.400    -5.300  
+ 4 430 53125.00 I  -.123717  .000077   .401060  .000050  I -.4526883  .0000043  0.6147 0.0034  I   -50.344     .330    -5.381     .126 -0.123340  0.401040 -0.4526730   -50.300    -5.200  
+ 4 5 1 53126.00 I  -.121531  .000059   .404238  .000050  I -.4534459  .0000052  0.8921 0.0031  I   -50.751     .157    -5.461     .144 -0.121380  0.404210 -0.4534520   -50.300    -5.100  
+ 4 5 2 53127.00 I  -.119766  .000051   .407433  .000052  I -.4544442  .0000045  1.0845 0.0036  I   -51.038     .169    -5.319     .121 -0.119660  0.407360 -0.4544520   -50.500    -4.800  
+ 4 5 3 53128.00 I  -.118495  .000049   .410523  .000049  I -.4555747  .0000049  1.1563 0.0036  I   -51.220     .169    -4.895     .121 -0.118390  0.410450 -0.4555700   -51.000    -4.600  
+ 4 5 4 53129.00 I  -.117063  .000032   .413497  .000054  I -.4567189  .0000056  1.1145 0.0035  I   -51.608     .242    -4.458     .340 -0.117060  0.413470 -0.4567090   -51.600    -4.500  
+ 4 5 5 53130.00 I  -.115916  .000031   .416444  .000057  I -.4577677  .0000051  0.9647 0.0039  I   -52.325     .217    -4.360     .340 -0.115790  0.416380 -0.4577810   -52.200    -4.500  
+ 4 5 6 53131.00 I  -.115002  .000031   .419218  .000057  I -.4586251  .0000053  0.7453 0.0036  I   -52.882     .217    -4.611     .340 -0.114930  0.419100 -0.4586060   -52.600    -4.700  
+ 4 5 7 53132.00 I  -.113991  .000033   .421556  .000061  I -.4592559  .0000051  0.5187 0.0041  I   -52.928     .217    -4.982     .340 -0.113920  0.421550 -0.4592340   -52.800    -5.000  
+ 4 5 8 53133.00 I  -.112547  .000036   .423888  .000062  I -.4596849  .0000062  0.3594 0.0034  I   -52.484     .249    -5.252     .340 -0.112480  0.423880 -0.4597010   -52.700    -5.200  
+ 4 5 9 53134.00 I  -.111160  .000032   .426264  .000058  I -.4600193  .0000044  0.3339 0.0038  I   -51.911     .241    -5.400     .340 -0.111080  0.426160 -0.4600310   -52.300    -5.400  
+ 4 510 53135.00 I  -.109687  .000023   .428824  .000057  I -.4603924  .0000043  0.4274 0.0030  I   -51.517     .236    -5.483     .340 -0.109620  0.428730 -0.4603710   -51.900    -5.500  
+ 4 511 53136.00 I  -.107952  .000028   .431626  .000040  I -.4608927  .0000042  0.5765 0.0032  I   -51.348     .278    -5.489     .340 -0.107920  0.431630 -0.4608740   -51.400    -5.500  
+ 4 512 53137.00 I  -.106062  .000037   .434487  .000038  I -.4615510  .0000047  0.7423 0.0032  I   -51.294     .243    -5.393     .340 -0.105990  0.434460 -0.4615630   -51.100    -5.400  
+ 4 513 53138.00 I  -.103997  .000039   .437286  .000036  I -.4623751  .0000047  0.9016 0.0033  I   -51.244     .243    -5.179     .340 -0.103920  0.437210 -0.4623610   -51.000    -5.200  
+ 4 514 53139.00 I  -.102431  .000037   .440008  .000035  I -.4633384  .0000045  1.0135 0.0038  I   -51.228     .243    -4.938     .340 -0.102230  0.439990 -0.4633250   -51.100    -4.900  
+ 4 515 53140.00 I  -.101285  .000044   .442347  .000039  I -.4643778  .0000059  1.0526 0.0032  I   -51.342     .256    -4.688     .340 -0.101230  0.442280 -0.4643800   -51.400    -4.500  
+ 4 516 53141.00 I  -.100663  .000040   .444171  .000051  I -.4654145  .0000046  1.0045 0.0040  I   -51.607     .208    -4.428     .340 -0.100590  0.444050 -0.4654470   -51.700    -4.300  
+ 4 517 53142.00 I  -.100222  .000044   .445634  .000057  I -.4663622  .0000054  0.8825 0.0035  I   -51.895     .215    -4.242     .340 -0.100120  0.445550 -0.4663810   -52.000    -4.200  
+ 4 518 53143.00 I  -.099643  .000047   .446834  .000061  I -.4671623  .0000053  0.7090 0.0037  I   -52.053     .248    -4.287     .153 -0.099630  0.446880 -0.4671500   -52.100    -4.300  
+ 4 519 53144.00 I  -.098872  .000046   .448195  .000059  I -.4677718  .0000051  0.5104 0.0037  I   -52.067     .248    -4.613     .153 -0.098880  0.448150 -0.4677680   -52.100    -4.600  
+ 4 520 53145.00 I  -.097892  .000043   .449518  .000059  I -.4681787  .0000052  0.2987 0.0035  I   -52.023     .248    -5.047     .153 -0.097620  0.449480 -0.4681660   -52.100    -5.000  
+ 4 521 53146.00 I  -.096351  .000043   .451032  .000060  I -.4683770  .0000049  0.1103 0.0048  I   -51.996     .248    -5.335     .153 -0.096230  0.450990 -0.4683520   -52.200    -5.300  
+ 4 522 53147.00 I  -.095216  .000048   .452371  .000051  I -.4684214  .0000080 -0.0119 0.0042  I   -51.986     .245    -5.396     .196 -0.095120  0.452300 -0.4684340   -52.400    -5.400  
+ 4 523 53148.00 I  -.094283  .000055   .453634  .000062  I -.4683734  .0000067 -0.0734 0.0054  I   -52.101     .213    -5.402     .182 -0.094210  0.453520 -0.4684300   -52.600    -5.400  
+ 4 524 53149.00 I  -.093244  .000046   .455065  .000049  I -.4683010  .0000072 -0.0557 0.0049  I   -52.215     .451    -5.476     .211 -0.093170  0.454970 -0.4683400   -52.500    -5.400  
+ 4 525 53150.00 I  -.091746  .000047   .456635  .000045  I -.4682783  .0000072  0.0110 0.0050  I   -52.133     .408    -5.552     .192 -0.091820  0.456610 -0.4682760   -52.100    -5.400  
+ 4 526 53151.00 I  -.090929  .000056   .458356  .000048  I -.4683310  .0000070  0.1018 0.0050  I   -51.802     .412    -5.497     .195 -0.090800  0.458290 -0.4683110   -51.500    -5.600  
+ 4 527 53152.00 I  -.090161  .000057   .459926  .000050  I -.4685068  .0000070  0.2674 0.0045  I   -51.502     .412    -5.362     .195 -0.090100  0.459820 -0.4684840   -51.100    -5.600  
+ 4 528 53153.00 I  -.089505  .000054   .461504  .000054  I -.4688631  .0000057  0.4248 0.0054  I   -51.572     .412    -5.327     .195 -0.089290  0.461430 -0.4688530   -51.200    -5.500  
+ 4 529 53154.00 I  -.088327  .000043   .463072  .000046  I -.4693344  .0000081  0.5160 0.0042  I   -51.996     .529    -5.346     .275 -0.088260  0.463050 -0.4693440   -51.600    -5.200  
+ 4 530 53155.00 I  -.087159  .000044   .464429  .000059  I -.4698815  .0000063  0.5664 0.0048  I   -52.507     .324    -5.277     .193 -0.087050  0.464430 -0.4699190   -52.200    -4.900  
+ 4 531 53156.00 I  -.085652  .000058   .465710  .000072  I -.4704374  .0000052  0.5275 0.0040  I   -52.991     .275    -4.908     .161 -0.085550  0.465620 -0.4704730   -53.000    -4.600  
+ 4 6 1 53157.00 I  -.083861  .000049   .467217  .000076  I -.4708996  .0000050  0.3780 0.0036  I   -53.601     .170    -4.453     .340 -0.083740  0.467120 -0.4709090   -53.800    -4.300  
+ 4 6 2 53158.00 I  -.081805  .000050   .468919  .000081  I -.4711655  .0000049  0.1448 0.0035  I   -54.338     .141    -4.292     .340 -0.081900  0.468990 -0.4711550   -54.300    -4.200  
+ 4 6 3 53159.00 I  -.079966  .000054   .470697  .000072  I -.4711933  .0000049 -0.0760 0.0035  I   -54.846     .141    -4.528     .340 -0.079860  0.470660 -0.4711760   -54.600    -4.400  
+ 4 6 4 53160.00 I  -.077622  .000058   .472199  .000072  I -.4710285  .0000051 -0.2518 0.0035  I   -54.789     .141    -4.911     .340 -0.077750  0.472270 -0.4710280   -54.500    -4.700  
+ 4 6 5 53161.00 I  -.075844  .000053   .473768  .000069  I -.4707260  .0000050 -0.3185 0.0037  I   -54.246     .263    -5.194     .117 -0.075560  0.473570 -0.4707200   -54.400    -5.000  
+ 4 6 6 53162.00 I  -.074538  .000055   .475431  .000074  I -.4704486  .0000054 -0.2137 0.0037  I   -53.616     .376    -5.367     .145 -0.074410  0.475460 -0.4705960   -54.200    -5.100  
+ 4 6 7 53163.00 I  -.073384  .000058   .476953  .000070  I -.4703249  .0000054 -0.0300 0.0038  I   -53.236     .350    -5.497     .170 -0.073240  0.476850 -0.4704280   -54.000    -5.200  
+ 4 6 8 53164.00 I  -.071790  .000061   .478291  .000060  I -.4703857  .0000054  0.1452 0.0038  I   -53.205     .411    -5.507     .187 -0.071780  0.478280 -0.4703790   -53.700    -5.300  
+ 4 6 9 53165.00 I  -.070023  .000064   .479927  .000062  I -.4706120  .0000053  0.3106 0.0037  I   -53.438     .349    -5.272     .164 -0.069820  0.479820 -0.4706000   -53.300    -5.400  
+ 4 610 53166.00 I  -.068415  .000063   .481560  .000061  I -.4709900  .0000052  0.4251 0.0033  I   -53.752     .349    -4.856     .164 -0.068360  0.481590 -0.4710010   -53.400    -5.100  
+ 4 611 53167.00 I  -.066916  .000066   .483053  .000061  I -.4714385  .0000039  0.4683 0.0035  I   -53.995     .349    -4.488     .164 -0.066580  0.482870 -0.4714330   -53.700    -4.600  
+ 4 612 53168.00 I  -.064946  .000052   .484490  .000040  I -.4719083  .0000048  0.4566 0.0032  I   -54.173     .237    -4.302     .140 -0.064920  0.484510 -0.4719020   -53.900    -4.200  
+ 4 613 53169.00 I  -.062809  .000060   .485929  .000048  I -.4723215  .0000050  0.3544 0.0035  I   -54.418     .354    -4.242     .340 -0.062670  0.485760 -0.4723950   -54.000    -4.000  
+ 4 614 53170.00 I  -.060448  .000055   .487271  .000053  I -.4725890  .0000050  0.1679 0.0039  I   -54.761     .351    -4.239     .106 -0.060290  0.487340 -0.4726390   -54.100    -4.100  
+ 4 615 53171.00 I  -.057872  .000045   .488518  .000063  I -.4726355  .0000059 -0.0841 0.0039  I   -55.061     .424    -4.370     .113 -0.057860  0.488480 -0.4726280   -54.400    -4.300  
+ 4 616 53172.00 I  -.054925  .000049   .489957  .000067  I -.4724252  .0000061 -0.3231 0.0043  I   -55.187     .388    -4.723     .111 -0.054740  0.489970 -0.4724330   -55.000    -4.500  
+ 4 617 53173.00 I  -.051591  .000048   .491565  .000068  I -.4720151  .0000063 -0.4847 0.0045  I   -55.181     .388    -5.181     .111 -0.051580  0.491350 -0.4720090   -55.400    -4.900  
+ 4 618 53174.00 I  -.048338  .000050   .493356  .000060  I -.4714770  .0000065 -0.5826 0.0051  I   -55.174     .388    -5.476     .111 -0.048070  0.493340 -0.4714770   -55.300    -5.300  
+ 4 619 53175.00 I  -.045151  .000046   .495324  .000063  I -.4708767  .0000080 -0.6002 0.0048  I   -55.250     .308    -5.462     .125 -0.045250  0.495410 -0.4708420   -55.300    -5.400  
+ 4 620 53176.00 I  -.041917  .000078   .497013  .000075  I -.4702972  .0000071 -0.5561 0.0053  I   -55.425     .288    -5.272     .340 -0.041700  0.496900 -0.4702260   -55.300    -5.400  
+ 4 621 53177.00 I  -.038587  .000075   .498380  .000073  I -.4697795  .0000071 -0.4668 0.0051  I   -55.643     .288    -5.124     .340 -0.038620  0.498330 -0.4697110   -55.300    -5.300  
+ 4 622 53178.00 I  -.035038  .000080   .499642  .000083  I -.4693810  .0000074 -0.3251 0.0052  I   -55.762     .277    -5.064     .125 -0.035040  0.499680 -0.4693630   -55.200    -5.100  
+ 4 623 53179.00 I  -.031932  .000081   .500942  .000089  I -.4691325  .0000075 -0.1737 0.0053  I   -55.669     .312    -4.978     .164 -0.031760  0.500860 -0.4691500   -55.200    -5.000  
+ 4 624 53180.00 I  -.028534  .000080   .502083  .000090  I -.4690415  .0000075  0.0015 0.0051  I   -55.478     .312    -4.827     .164 -0.028540  0.502170 -0.4690560   -55.200    -5.000  
+ 4 625 53181.00 I  -.025193  .000078   .503189  .000078  I -.4691332  .0000070  0.1698 0.0054  I   -55.476     .312    -4.719     .164 -0.024900  0.503120 -0.4691160   -55.500    -4.900  
+ 4 626 53182.00 I  -.022008  .000050   .504710  .000071  I -.4693442  .0000079  0.2272 0.0048  I   -55.825     .282    -4.720     .207 -0.022050  0.504870 -0.4693900   -55.900    -4.800  
+ 4 627 53183.00 I  -.019193  .000068   .506084  .000082  I -.4695550  .0000065  0.1866 0.0054  I   -56.434     .231    -4.706     .184 -0.019040  0.505910 -0.4695710   -56.500    -4.500  
+ 4 628 53184.00 I  -.016272  .000064   .507094  .000078  I -.4696938  .0000073  0.0750 0.0055  I   -57.147     .231    -4.546     .184 -0.016150  0.507110 -0.4696610   -57.100    -4.300  
+ 4 629 53185.00 I  -.013092  .000059   .507954  .000066  I -.4696846  .0000088 -0.0979 0.0055  I   -57.873     .163    -4.337     .158 -0.013090  0.507900 -0.4696690   -57.700    -4.200  
+ 4 630 53186.00 I  -.010372  .000058   .509048  .000084  I -.4694788  .0000082 -0.3285 0.0060  I   -58.474     .210    -4.317     .164 -0.010180  0.508950 -0.4694860   -58.000    -4.300  
+ 4 7 1 53187.00 I  -.007575  .000058   .510126  .000084  I -.4690288  .0000083 -0.5554 0.0058  I   -58.723     .210    -4.542     .164 -0.007570  0.510130 -0.4689890   -58.100    -4.500  
+ 4 7 2 53188.00 I  -.004600  .000060   .510900  .000081  I -.4683871  .0000083 -0.7249 0.0084  I   -58.525     .210    -4.803     .164 -0.004540  0.510830 -0.4683790   -58.000    -4.800  
+ 4 7 3 53189.00 I  -.001920  .000037   .511647  .000070  I -.4676191  .0000146 -0.7742 0.0062  I   -58.071     .328    -4.925     .202 -0.001750  0.511710 -0.4676050   -57.900    -5.100  
+ 4 7 4 53190.00 I   .000401  .000040   .512396  .000071  I -.4669017  .0000091 -0.6345 0.0076  I   -57.656     .310    -4.981     .190  0.000410  0.512320 -0.4671130   -57.700    -5.200  
+ 4 7 5 53191.00 I   .002673  .000069   .513106  .000070  I -.4663809  .0000040 -0.4025 0.0047  I   -57.444     .279    -5.093     .165  0.002740  0.512910 -0.4665540   -57.700    -5.200  
+ 4 7 6 53192.00 I   .005049  .000075   .513764  .000052  I -.4660892  .0000025 -0.1930 0.0023  I   -57.499     .289    -5.165     .143  0.005140  0.513650 -0.4661270   -57.700    -5.100  
+ 4 7 7 53193.00 I   .007454  .000087   .514361  .000066  I -.4659612  .0000023 -0.0847 0.0017  I   -57.852     .362    -4.989     .120  0.007380  0.514200 -0.4659470   -57.900    -4.800  
+ 4 7 8 53194.00 I   .009556  .000097   .514766  .000064  I -.4658828  .0000022 -0.0873 0.0017  I   -58.406     .362    -4.582     .120  0.009680  0.514750 -0.4659020   -58.100    -4.500  
+ 4 7 9 53195.00 I   .012039  .000096   .515216  .000056  I -.4657611  .0000025 -0.1665 0.0017  I   -58.912     .350    -4.237     .340  0.012350  0.515160 -0.4657470   -58.300    -4.200  
+ 4 710 53196.00 I   .015246  .000094   .516120  .000052  I -.4655330  .0000027 -0.2962 0.0026  I   -59.201     .330    -4.182     .340  0.015460  0.516110 -0.4655440   -58.600    -4.000  
+ 4 711 53197.00 I   .018248  .000089   .517022  .000046  I -.4651594  .0000045 -0.4538 0.0028  I   -59.368     .340    -4.343     .340  0.018290  0.517010 -0.4651960   -59.000    -4.000  
+ 4 712 53198.00 I   .021364  .000088   .517837  .000045  I -.4646179  .0000049 -0.6341 0.0037  I   -59.584     .337    -4.515     .340  0.021370  0.517650 -0.4646290   -59.300    -4.200  
+ 4 713 53199.00 I   .024113  .000060   .518714  .000042  I -.4638838  .0000058 -0.8368 0.0037  I   -59.834     .195    -4.655     .340  0.024340  0.518770 -0.4638740   -59.600    -4.500  
+ 4 714 53200.00 I   .026250  .000061   .519365  .000056  I -.4629601  .0000056 -0.9921 0.0039  I   -59.973     .176    -4.874     .340  0.026250  0.519040 -0.4629580   -59.800    -4.900  
+ 4 715 53201.00 I   .028217  .000059   .519926  .000056  I -.4619325  .0000053 -1.0487 0.0039  I   -59.978     .176    -5.185     .340  0.028290  0.519920 -0.4619040   -59.800    -5.200  
+ 4 716 53202.00 I   .030203  .000058   .520327  .000054  I -.4608838  .0000054 -1.0421 0.0038  I   -59.958     .176    -5.409     .340  0.030460  0.520300 -0.4608800   -59.800    -5.400  
+ 4 717 53203.00 I   .032705  .000038   .520670  .000056  I -.4598706  .0000055 -0.9687 0.0035  I   -59.985     .214    -5.367     .102  0.032540  0.520650 -0.4598740   -59.800    -5.400  
+ 4 718 53204.00 I   .035672  .000056   .520840  .000054  I -.4589705  .0000043 -0.8230 0.0035  I   -60.037     .190    -5.103     .340  0.035970  0.520750 -0.4591510   -59.900    -5.200  
+ 4 719 53205.00 I   .038660  .000060   .520771  .000052  I -.4582343  .0000043 -0.6481 0.0030  I   -60.095     .330    -4.833     .340  0.038570  0.520680 -0.4583560   -59.900    -4.900  
+ 4 720 53206.00 I   .041511  .000057   .520529  .000041  I -.4576796  .0000043 -0.4574 0.0032  I   -60.153     .407    -4.704     .340  0.041520  0.520480 -0.4576720   -59.900    -4.700  
+ 4 721 53207.00 I   .043961  .000066   .520203  .000063  I -.4573299  .0000048 -0.2355 0.0032  I   -60.166     .391    -4.686     .340  0.044090  0.520190 -0.4573140   -59.900    -4.600  
+ 4 722 53208.00 I   .046939  .000067   .519847  .000064  I -.4571998  .0000048 -0.0400 0.0034  I   -60.113     .391    -4.669     .340  0.046900  0.519710 -0.4572010   -59.900    -4.600  
+ 4 723 53209.00 I   .049952  .000060   .519564  .000057  I -.4572198  .0000047  0.0651 0.0049  I   -60.105     .391    -4.615     .340  0.050240  0.519410 -0.4572220   -60.200    -4.600  
+ 4 724 53210.00 I   .053021  .000055   .519248  .000066  I -.4573009  .0000085  0.0829 0.0050  I   -60.320     .432    -4.562     .144  0.053030  0.519170 -0.4573080   -60.600    -4.600  
+ 4 725 53211.00 I   .056051  .000065   .519070  .000073  I -.4573547  .0000089  0.0078 0.0061  I   -60.829     .253    -4.530     .187  0.056170  0.518960 -0.4575160   -61.200    -4.500  
+ 4 726 53212.00 I   .059028  .000070   .519102  .000071  I -.4572835  .0000088 -0.1665 0.0065  I   -61.514     .253    -4.513     .187  0.059160  0.518990 -0.4573630   -61.700    -4.400  
+ 4 727 53213.00 I   .061412  .000057   .519119  .000062  I -.4570009  .0000096 -0.4032 0.0063  I   -62.137     .250    -4.549     .209  0.061620  0.519010 -0.4569860   -62.100    -4.300  
+ 4 728 53214.00 I   .063962  .000063   .518775  .000095  I -.4564814  .0000090 -0.6269 0.0067  I   -62.446     .326    -4.685     .192  0.064010  0.518560 -0.4565000   -62.000    -4.500  
+ 4 729 53215.00 I   .066369  .000063   .518305  .000107  I -.4557825  .0000094 -0.7442 0.0063  I   -62.337     .326    -4.863     .192  0.066520  0.518320 -0.4557640   -61.800    -4.700  
+ 4 730 53216.00 I   .068319  .000063   .517607  .000108  I -.4550403  .0000089 -0.7195 0.0061  I   -61.963     .326    -4.924     .192  0.068510  0.517600 -0.4550260   -61.400    -4.900  
+ 4 731 53217.00 I   .070361  .000047   .516935  .000098  I -.4543862  .0000078 -0.5666 0.0055  I   -61.633     .425    -4.800     .114  0.070360  0.516990 -0.4544200   -61.200    -5.100  
+ 4 8 1 53218.00 I   .072781  .000043   .516275  .000090  I -.4539457  .0000063 -0.2977 0.0052  I   -61.521     .372    -4.645     .340  0.073010  0.516150 -0.4539160   -61.200    -5.100  
+ 4 8 2 53219.00 I   .075510  .000043   .515710  .000083  I -.4538001  .0000070 -0.0008 0.0052  I   -61.553     .372    -4.644     .340  0.075510  0.515600 -0.4537780   -61.300    -5.000  
+ 4 8 3 53220.00 I   .078334  .000040   .515337  .000041  I -.4539125  .0000084  0.2015 0.0054  I   -61.649     .286    -4.753     .340                                                     
+ 4 8 4 53221.00 I   .081083  .000059   .515209  .000058  I -.4541573  .0000081  0.2665 0.0057  I   -61.898     .243    -4.747     .340                                                     
+ 4 8 5 53222.00 I   .083897  .000056   .515109  .000058  I -.4544068  .0000078  0.2155 0.0056  I   -62.389     .243    -4.551     .340                                                     
+ 4 8 6 53223.00 I   .086289  .000056   .514972  .000062  I -.4545710  .0000078  0.1127 0.0078  I   -62.967     .243    -4.364     .340                                                     
+ 4 8 7 53224.00 I   .088893  .000061   .514756  .000060  I -.4546235  .0000134 -0.0162 0.0066  I   -63.362     .198    -4.403     .131                                                     
+ 4 8 8 53225.00 I   .091703  .000068   .514261  .000055  I -.4545264  .0000107 -0.1816 0.0084  I   -63.499     .204    -4.619     .180                                                     
+ 4 8 9 53226.00 I   .094703  .000073   .513748  .000056  I -.4542593  .0000101 -0.3498 0.0077  I   -63.512     .204    -4.789     .180                                                     
+ 4 810 53227.00 I   .097328  .000057   .513284  .000048  I -.4538279  .0000110 -0.5146 0.0075  I   -63.499     .190    -4.820     .252                                                     
+ 4 811 53228.00 I   .099793  .000053   .512913  .000044  I -.4532509  .0000110 -0.6170 0.0077  I   -63.429     .190    -4.835     .252                                                     
+ 4 812 53229.00 I   .102671  .000053   .512912  .000045  I -.4526176  .0000109 -0.6481 0.0071  I   -63.295     .190    -4.959     .252                                                     
+ 4 813 53230.00 I   .105716  .000053   .513243  .000051  I -.4519727  .0000091 -0.6250 0.0075  I   -63.171     .190    -5.123     .252                                                     
+ 4 814 53231.00 I   .108723  .000025   .513578  .000059  I -.4513936  .0000103 -0.5240 0.0059  I   -63.092     .128    -5.149     .182                                                     
+ 4 815 53232.00 I   .111601  .000036   .513710  .000073  I -.4509461  .0000075 -0.3589 0.0063  I   -63.011     .740    -4.970     .131                                                     
+ 4 816 53233.00 I   .114518  .000039   .513525  .000078  I -.4506962  .0000074 -0.1327 0.0053  I   -62.912     .740    -4.710     .131                                                     
+ 4 817 53234.00 I   .117350  .000044   .513055  .000071  I -.4506875  .0000074  0.1139 0.0051  I   -62.857     .740    -4.550     .340                                                     
+ 4 818 53235.00 I   .119692  .000074   .512403  .000087  I -.4509139  .0000071  0.3302 0.0052  I   -62.883     .160    -4.566     .114                                                     
+ 4 819 53236.00 I   .122032  .000073   .511787  .000084  I -.4513301  .0000072  0.4931 0.0050  I   -62.940     .160    -4.674     .114                                                     
+ 4 820 53237.00 I   .124064  .000080   .511184  .000087  I -.4518682  .0000069  0.5603 0.0050  I   -63.005     .160    -4.739     .114                                                     
+ 4 821 53238.00 I   .126381  .000083   .510397  .000089  I -.4524049  .0000070  0.4901 0.0043  I   -63.161     .200    -4.703     .133                                                     
+ 4 822 53239.00 I   .128317  .000078   .509289  .000087  I -.4528121  .0000052  0.3109 0.0046  I   -63.495     .172    -4.622     .113                                                     
+ 4 823 53240.00 I   .130124  .000087   .507871  .000091  I -.4530115  .0000061  0.0861 0.0042  I   -63.939     .172    -4.597     .113                                                     
+ 4 824 53241.00 I   .132327  .000037   .506361  .000067  I -.4529954  .0000067 -0.1055 0.0050  I   -64.263     .740    -4.676     .340                                                     
+ 4 825 53242.00 I   .134350  .000050   .504927  .000068  I -.4528134  .0000080 -0.2584 0.0052  I   -64.246     .126    -4.815     .340                                                     
+ 4 826 53243.00 I   .136176  .000051   .503711  .000068  I -.4524934  .0000079 -0.3669 0.0057  I   -63.877     .126    -4.893     .340                                                     
+ 4 827 53244.00 I   .138473  .000054   .502455  .000068  I -.4521208  .0000080 -0.3518 0.0087  I   -63.406     .126    -4.799     .340                                                     
+ 4 828 53245.00 I   .141017  .000057   .501217  .000063  I -.4518467  .0000155 -0.1661 0.0076  P   -63.172     .600    -4.511     .600                                                     
+ 4 829 53246.00 I   .143724  .000058   .499942  .000066  I -.4518233  .0000130  0.1237 0.0100  P   -63.216     .600    -4.226     .600                                                     
+ 4 830 53247.00 I   .146735  .000058   .498642  .000065  I -.4520879  .0000126  0.3948 0.0091  P   -63.377     .600    -4.094     .600                                                     
+ 4 831 53248.00 I   .149528  .000048   .497266  .000060  I -.4525797  .0000126  0.5664 0.0090  P   -63.473     .600    -4.134     .600                                                     
+ 4 9 1 53249.00 I   .152127  .000048   .495657  .000060  I -.4531729  .0000128  0.5948 0.0103  P   -63.565     .600    -4.206     .600                                                     
+ 4 9 2 53250.00 I   .154737  .000045   .493902  .000060  I -.4537242  .0000163  0.4880 0.0104  P   -63.844     .600    -4.210     .600                                                     
+ 4 9 3 53251.00 I   .157024  .000046   .491950  .000057  I -.4541177  .0000163  0.2875 0.0116  P   -64.326     .600    -4.205     .600                                                     
+ 4 9 4 53252.00 I   .159212  .000045   .489734  .000056  I -.4542779  .0000166  0.0231 0.0115  P   -64.786     .600    -4.298     .600                                                     
+ 4 9 5 53253.00 I   .161557  .000043   .487316  .000049  I -.4541614  .0000163 -0.2489 0.0109  P   -64.991     .600    -4.446     .600                                                     
+ 4 9 6 53254.00 I   .163658  .000033   .484857  .000040  I -.4537921  .0000140 -0.4849 0.0108  P   -64.896     .600    -4.501     .600                                                     
+ 4 9 7 53255.00 I   .165419  .000032   .482637  .000037  I -.4532001  .0000143 -0.6952 0.0087  P   -64.606     .600    -4.416     .600                                                     
+ 4 9 8 53256.00 I   .167322  .000027   .480727  .000026  I -.4524551  .0000105 -0.7451 0.0087  P   -64.240     .600    -4.329     .600                                                     
+ 4 9 9 53257.00 I   .169420  .000023   .478990  .000018  I -.4516544  .0000098                 P   -63.885     .600    -4.385     .600                                                     
+ 4 910 53258.00 P  0.171467 0.004200  0.477353 0.004200  P -.4509247  .0000094                 P   -63.605     .600    -4.550     .600                                                     
+ 4 911 53259.00 P  0.173411 0.005100  0.475723 0.005100  P -.4503884  .0000096                 P   -63.419     .600    -4.649     .600                                                     
+ 4 912 53260.00 P  0.175264 0.005713  0.474087 0.005713  P -.4501214  .0000120                 P   -63.312     .600    -4.560     .600                                                     
+ 4 913 53261.00 P  0.177037 0.006192  0.472436 0.006192  P -.4501491  .0000114                 P   -63.272     .600    -4.327     .600                                                     
+ 4 914 53262.00 P  0.178738 0.006591  0.470764 0.006591  P -.4504461  .0000106                 P   -63.307     .600    -4.111     .600                                                     
+ 4 915 53263.00 P  0.180376 0.006936  0.469070 0.006936  P-0.4509294 0.0003000                 P   -63.406     .600    -4.047     .600                                                     
+ 4 916 53264.00 P  0.181956 0.007242  0.467351 0.007242  P-0.4514721 0.0005048                 P   -63.522     .600    -4.143     .600                                                     
+ 4 917 53265.00 P  0.183483 0.007518  0.465607 0.007518  P-0.4519581 0.0006844                 P   -63.631     .600    -4.283     .600                                                     
+ 4 918 53266.00 P  0.184961 0.007770  0.463838 0.007770  P-0.4523358 0.0008494                 P   -63.761     .600    -4.340     .600                                                     
+ 4 919 53267.00 P  0.186394 0.008003  0.462044 0.008003  P-0.4525694 0.0010043                 P   -63.935     .600    -4.296     .600                                                     
+ 4 920 53268.00 P  0.187784 0.008219  0.460226 0.008219  P-0.4526379 0.0011516                 P   -64.084     .600    -4.237     .600                                                     
+ 4 921 53269.00 P  0.189133 0.008422  0.458385 0.008422  P-0.4525611 0.0012929                 P   -64.063     .600    -4.241     .600                                                     
+ 4 922 53270.00 P  0.190444 0.008613  0.456520 0.008613  P-0.4524069 0.0014292                 P   -63.767     .600    -4.287     .600                                                     
+ 4 923 53271.00 P  0.191717 0.008794  0.454633 0.008794  P-0.4522814 0.0015613                 P   -63.254     .600    -4.291     .600                                                     
+ 4 924 53272.00 P  0.192953 0.008965  0.452724 0.008965  P-0.4523216 0.0016899                 P   -62.740     .600    -4.187     .600                                                     
+ 4 925 53273.00 P  0.194154 0.009129  0.450794 0.009129  P-0.4526384 0.0018152                 P   -62.445     .600    -3.986     .600                                                     
+ 4 926 53274.00 P  0.195320 0.009285  0.448843 0.009285  P-0.4532626 0.0019377                 P   -62.421     .600    -3.759     .600                                                     
+ 4 927 53275.00 P  0.196451 0.009435  0.446873 0.009435  P-0.4541610 0.0020577                 P   -62.529     .600    -3.584     .600                                                     
+ 4 928 53276.00 P  0.197548 0.009579  0.444882 0.009579  P-0.4552339 0.0021755                 P   -62.603     .600    -3.495     .600                                                     
+ 4 929 53277.00 P  0.198610 0.009717  0.442876 0.009717  P-0.4563520 0.0022911                 P   -62.624     .600    -3.476     .600                                                     
+ 4 930 53278.00 P  0.199639 0.009851  0.440847 0.009851  P-0.4573954 0.0024048                 P   -62.720     .600    -3.511     .600                                                     
+ 410 1 53279.00 P  0.200633 0.009980  0.438801 0.009980  P-0.4582793 0.0025168                 P   -62.992     .600    -3.612     .600                                                     
+ 410 2 53280.00 P  0.201593 0.010105  0.436738 0.010105  P-0.4589605 0.0026272                 P   -63.350     .600    -3.771     .600                                                     
+ 410 3 53281.00 P  0.202519 0.010226  0.434658 0.010226  P-0.4594370 0.0027360                 P   -63.560     .600    -3.904     .600                                                     
+ 410 4 53282.00 P  0.203410 0.010344  0.432562 0.010344  P-0.4597357 0.0028434                 P   -63.441     .600    -3.908     .600                                                     
+ 410 5 53283.00 P  0.204268 0.010458  0.430450 0.010458  P-0.4599121 0.0029495                 P   -63.020     .600    -3.802     .600                                                     
+ 410 6 53284.00 P  0.205090 0.010569  0.428324 0.010569  P-0.4600421 0.0030543                 P   -62.477     .600    -3.737     .600                                                     
+ 410 7 53285.00 P  0.205879 0.010677  0.426182 0.010677  P-0.4602003 0.0031580                 P   -61.967     .600    -3.823     .600                                                     
+ 410 8 53286.00 P  0.206632 0.010783  0.424026 0.010783  P-0.4604591 0.0032605                 P   -61.539     .600    -3.988     .600                                                     
+ 410 9 53287.00 P  0.207351 0.010885  0.421857 0.010885  P-0.4608814 0.0033620                 P   -61.222     .600    -4.054     .600                                                     
+ 41010 53288.00 P  0.208034 0.010986  0.419674 0.010986  P-0.4615152 0.0034624                 P   -61.099     .600    -3.928     .600                                                     
+ 41011 53289.00 P  0.208683 0.011084  0.417479 0.011084  P-0.4623817 0.0035619                 P   -61.220     .600    -3.664     .600                                                     
+ 41012 53290.00 P  0.209297 0.011180  0.415272 0.011180  P-0.4634664 0.0036605                 P   -61.490     .600    -3.385     .600                                                     
+ 41013 53291.00 P  0.209875 0.011274  0.413054 0.011274  P-0.4647095 0.0037582                 P   -61.727     .600    -3.195     .600                                                     
+ 41014 53292.00 P  0.210419 0.011365  0.410825 0.011365  P-0.4660094 0.0038551                 P   -61.835     .600    -3.154     .600                                                     
+ 41015 53293.00 P  0.210927 0.011455  0.408585 0.011455  P-0.4672379 0.0039512                 P   -61.854     .600    -3.251     .600                                                     
+ 41016 53294.00 P  0.211399 0.011544  0.406335 0.011544  P-0.4682771 0.0040465                 P   -61.852     .600    -3.399     .600                                                     
+ 41017 53295.00 P  0.211837 0.011630  0.404076 0.011630  P-0.4690588 0.0041411                 P   -61.826     .600    -3.484     .600                                                     
+ 41018 53296.00 P  0.212239 0.011715  0.401809 0.011715  P-0.4695842 0.0042349                 P   -61.727     .600    -3.468     .600                                                     
+ 41019 53297.00 P  0.212606 0.011798  0.399533 0.011798  P-0.4699288 0.0043281                 P   -61.512     .600    -3.407     .600                                                     
+ 41020 53298.00 P  0.212937 0.011880  0.397249 0.011880  P-0.4702173 0.0044206                 P   -61.163     .600    -3.369     .600                                                     
+ 41021 53299.00 P  0.213233 0.011961  0.394959 0.011961  P-0.4705836 0.0045125                 P   -60.705     .600    -3.358     .600                                                     
+ 41022 53300.00 P  0.213494 0.012040  0.392661 0.012040  P-0.4711389 0.0046037                 P   -60.231     .600    -3.329     .600                                                     
+ 41023 53301.00 P  0.213720 0.012118  0.390358 0.012118  P-0.4719346 0.0046944                 P   -59.867     .600    -3.247     .600                                                     
+ 41024 53302.00 P  0.213911 0.012194  0.388050 0.012194  P-0.4729557 0.0047844                 P   -59.696     .600    -3.112     .600                                                     
+ 41025 53303.00 P  0.214067 0.012269  0.385736 0.012269  P-0.4741376 0.0048740                 P   -59.701     .600    -2.940     .600                                                     
+ 41026 53304.00 P  0.214188 0.012343  0.383419 0.012343  P-0.4753802 0.0049629                 P   -59.782     .600    -2.749     .600                                                     
+ 41027 53305.00 P  0.214244 0.012416  0.381097 0.012416  P-0.4765759 0.0050514                 P   -59.837     .600    -2.585     .600                                                     
+ 41028 53306.00 P  0.214299 0.012488  0.378772 0.012488  P-0.4776326 0.0051393                 P   -59.839     .600    -2.523     .600                                                     
+ 41029 53307.00 P  0.214319 0.012559  0.376445 0.012559  P-0.4784898 0.0052268                 P   -59.858     .600    -2.623     .600                                                     
+ 41030 53308.00 P  0.214305 0.012629  0.374115 0.012629  P-0.4791295 0.0053137                 P   -59.949     .600    -2.851     .600                                                     
+ 41031 53309.00 P  0.214256 0.012698  0.371785 0.012698  P-0.4795725 0.0054002                 P   -60.031     .600    -3.063     .600                                                     
+ 411 1 53310.00 P  0.214173 0.012766  0.369453 0.012766  P-0.4798642 0.0054862                 P   -59.933     .600    -3.127     .600                                                     
+ 411 2 53311.00 P  0.214056 0.012833  0.367120 0.012833  P-0.4800693 0.0055718                 P   -59.593     .600    -3.064     .600                                                     
+ 411 3 53312.00 P  0.213905 0.012899  0.364788 0.012899  P-0.4802650 0.0056570                 P   -59.120     .600    -3.029     .600                                                     
+ 411 4 53313.00 P  0.213721 0.012964  0.362456 0.012964  P-0.4805271 0.0057417                 P   -58.635     .600    -3.108     .600                                                     
+ 411 5 53314.00 P  0.213503 0.013028  0.360126 0.013028  P-0.4809198 0.0058260                 P   -58.155     .600    -3.196     .600                                                     
+ 411 6 53315.00 P  0.213252 0.013092  0.357798 0.013092  P-0.4814890 0.0059099                 P   -57.729     .600    -3.129     .600                                                     
+ 411 7 53316.00 P  0.212968 0.013155  0.355472 0.013155  P-0.4822615 0.0059934                 P   -57.552     .600    -2.892     .600                                                     
+ 411 8 53317.00 P  0.212652 0.013217  0.353148 0.013217  P-0.4832419 0.0060766                 P   -57.772     .600    -2.612     .600                                                     
+ 411 9 53318.00 P  0.212303 0.013278  0.350829 0.013278  P-0.4844015 0.0061593                 P   -58.248     .600    -2.372     .600                                                     
+ 41110 53319.00 P  0.211922 0.013339  0.348513 0.013339  P-0.4856693 0.0062417                 P   -58.656     .600    -2.159     .600                                                     
+ 41111 53320.00 P  0.211509 0.013399  0.346202 0.013399  P-0.4869359 0.0063237                 P   -58.830     .600    -1.987     .600                                                     
+ 41112 53321.00 P  0.211064 0.013458  0.343895 0.013458  P-0.4880774 0.0064054                 P   -58.840     .600    -1.960     .600                                                     
+ 41113 53322.00 P  0.210588 0.013517  0.341595 0.013517  P-0.4889940 0.0064868                 P   -58.763     .600    -2.124     .600                                                     
+ 41114 53323.00 P  0.210080 0.013574  0.339300 0.013574  P-0.4896480 0.0065677                 P   -58.573     .600    -2.343     .600                                                     
+ 41115 53324.00 P  0.209542 0.013632  0.337013 0.013632  P-0.4900829 0.0066484                 P   -58.275     .600    -2.425     .600                                                     
+ 41116 53325.00 P  0.208973 0.013688  0.334732 0.013688  P-0.4904113 0.0067288                 P   -57.988     .600    -2.343     .600                                                     
+ 41117 53326.00 P  0.208374 0.013744  0.332459 0.013744  P-0.4907765 0.0068088                 P   -57.796     .600    -2.241     .600                                                     
+ 41118 53327.00 P  0.207745 0.013800  0.330195 0.013800  P-0.4913008 0.0068885                 P   -57.631     .600    -2.220     .600                                                     
+ 41119 53328.00 P  0.207086 0.013855  0.327939 0.013855  P-0.4920473 0.0069679                 P   -57.402     .600    -2.228     .600                                                     
+ 41120 53329.00 P  0.206397 0.013909  0.325692 0.013909  P-0.4930066 0.0070470                 P   -57.147     .600    -2.156     .600                                                     
+ 41121 53330.00 P  0.205680 0.013963  0.323456 0.013963  P-0.4941120 0.0071258                 P   -56.995     .600    -1.986     .600                                                     
+ 41122 53331.00 P  0.204933 0.014016  0.321229 0.014016  P-0.4952659 0.0072044                 P   -57.018     .600    -1.781     .600                                                     
+ 41123 53332.00 P  0.204158 0.014069  0.319013 0.014069  P-0.4963647 0.0072826                 P   -57.155     .600    -1.586     .600                                                     
+ 41124 53333.00 P  0.203355 0.014121  0.316809 0.014121  P-0.4973191 0.0073606                 P   -57.259     .600    -1.417     .600                                                     
+ 41125 53334.00 P  0.202524 0.014173  0.314617 0.014173  P-0.4980683 0.0074383                 P   -57.213     .600    -1.326     .600                                                     
+ 41126 53335.00 P  0.201665 0.014224  0.312436 0.014224  P-0.4985873 0.0075157                                                                                                             
+ 41127 53336.00 P  0.200779 0.014275  0.310269 0.014275  P-0.4988853 0.0075928                                                                                                             
+ 41128 53337.00 P  0.199866 0.014326  0.308115 0.014326  P-0.4990014 0.0076697                                                                                                             
+ 41129 53338.00 P  0.198926 0.014376  0.305974 0.014376  P-0.4989981 0.0077464                                                                                                             
+ 41130 53339.00 P  0.197960 0.014425  0.303848 0.014425  P-0.4989511 0.0078228                                                                                                             
+ 412 1 53340.00 P  0.196967 0.014474  0.301736 0.014474  P-0.4989372 0.0078989                                                                                                             
+ 412 2 53341.00 P  0.195949 0.014523  0.299639 0.014523  P-0.4990270 0.0079748                                                                                                             
+ 412 3 53342.00 P  0.194906 0.014571  0.297558 0.014571  P-0.4992734 0.0080505                                                                                                             
+ 412 4 53343.00 P  0.193837 0.014619  0.295494 0.014619  P-0.4997076 0.0081259                                                                                                             
+ 412 5 53344.00 P  0.192744 0.014666  0.293445 0.014666  P-0.5003367 0.0082011                                                                                                             
+ 412 6 53345.00 P  0.191626 0.014713  0.291413 0.014713  P-0.5011417 0.0082761                                                                                                             
+ 412 7 53346.00 P  0.190485 0.014760  0.289399 0.014760  P-0.5020732 0.0083508                                                                                                             
+ 412 8 53347.00 P  0.189319 0.014806  0.287403 0.014806  P-0.5030459 0.0084254                                                                                                             
+ 412 9 53348.00 P  0.188130 0.014852  0.285424 0.014852  P-0.5039492 0.0084997                                                                                                             
+ 41210 53349.00 P  0.186918 0.014897  0.283464 0.014897  P-0.5046735 0.0085737                                                                                                             
+ 41211 53350.00 P  0.185683 0.014943  0.281523 0.014943  P-0.5051471 0.0086476                                                                                                             
+ 41212 53351.00 P  0.184425 0.014987  0.279602 0.014987  P-0.5053720 0.0087213                                                                                                             
+ 41213 53352.00 P  0.183146 0.015032  0.277700 0.015032  P-0.5054332 0.0087948                                                                                                             
+ 41214 53353.00 P  0.181844 0.015076  0.275819 0.015076  P-0.5054706 0.0088680                                                                                                             
+ 41215 53354.00 P  0.180522 0.015120  0.273958 0.015120  P-0.5056282 0.0089411                                                                                                             
+ 41216 53355.00 P  0.179178 0.015163  0.272118 0.015163  P-0.5059987 0.0090139                                                                                                             
+ 41217 53356.00 P  0.177813 0.015206  0.270299 0.015206  P-0.5065953 0.0090866                                                                                                             
+ 41218 53357.00 P  0.176428 0.015249  0.268502 0.015249  P-0.5073581 0.0091591                                                                                                             
+ 41219 53358.00 P  0.175023 0.015292  0.266726 0.015292  P-0.5081832 0.0092314                                                                                                             
+ 41220 53359.00 P  0.173598 0.015334  0.264974 0.015334  P-0.5089593 0.0093035                                                                                                             
+ 41221 53360.00 P  0.172153 0.015376  0.263243 0.015376  P-0.5095954 0.0093754                                                                                                             
+ 41222 53361.00 P  0.170690 0.015418  0.261536 0.015418  P-0.5100343 0.0094471                                                                                                             
+ 41223 53362.00 P  0.169208 0.015459  0.259852 0.015459  P-0.5102545 0.0095186                                                                                                             
+ 41224 53363.00 P  0.167707 0.015500  0.258192 0.015500  P-0.5103288 0.0095900                                                                                                             
+ 41225 53364.00 P  0.166188 0.015541  0.256555 0.015541  P-0.5102251 0.0096612                                                                                                             
+ 41226 53365.00 P  0.164651 0.015581  0.254943 0.015581  P-0.5099981 0.0097322                                                                                                             
+ 41227 53366.00 P  0.163097 0.015622  0.253355 0.015622  P-0.5097180 0.0098031                                                                                                             
+ 41228 53367.00 P  0.161526 0.015662  0.251792 0.015662  P-0.5094608 0.0098738                                                                                                             
+ 41229 53368.00 P  0.159938 0.015701  0.250255 0.015701  P-0.5092973 0.0099443                                                                                                             
+ 41230 53369.00 P  0.158334 0.015741  0.248742 0.015741  P-0.5092826 0.0100146                                                                                                             
+ 41231 53370.00 P  0.156714 0.015780  0.247255 0.015780  P-0.5094488 0.0100848                                                                                                             
+ 5 1 1 53371.00 P  0.155077 0.015819  0.245794 0.015819  P-0.5098034 0.0101548                                                                                                             
+ 5 1 2 53372.00 P  0.153426 0.015858  0.244359 0.015858  P-0.5103293 0.0102247                                                                                                             
+ 5 1 3 53373.00 P  0.151759 0.015896  0.242950 0.015896  P-0.5109851 0.0102944                                                                                                             
+ 5 1 4 53374.00 P  0.150077 0.015935  0.241568 0.015935  P-0.5117037 0.0103639                                                                                                             
+ 5 1 5 53375.00 P  0.148381 0.015973  0.240213 0.015973  P-0.5123955 0.0104333                                                                                                             
+ 5 1 6 53376.00 P  0.146671 0.016010  0.238885 0.016010  P-0.5129620 0.0105026                                                                                                             
+ 5 1 7 53377.00 P  0.144947 0.016048  0.237584 0.016048  P-0.5133239 0.0105716                                                                                                             
+ 5 1 8 53378.00 P  0.143210 0.016085  0.236310 0.016085  P-0.5134554 0.0106406                                                                                                             
+ 5 1 9 53379.00 P  0.141459 0.016122  0.235064 0.016122  P-0.5134074 0.0107094                                                                                                             
+ 5 110 53380.00 P  0.139696 0.016159  0.233845 0.016159  P-0.5133019 0.0107780                                                                                                             
+ 5 111 53381.00 P  0.137920 0.016196  0.232655 0.016196  P-0.5132921 0.0108465                                                                                                             
+ 5 112 53382.00 P  0.136132 0.016232  0.231492 0.016232  P-0.5135043 0.0109149                                                                                                             
+ 5 113 53383.00 P  0.134333 0.016269  0.230358 0.016269  P-0.5139901 0.0109831                                                                                                             
+ 5 114 53384.00 P  0.132521 0.016305  0.229252 0.016305  P-0.5147105 0.0110512                                                                                                             
+ 5 115 53385.00 P  0.130699 0.016341  0.228175 0.016341  P-0.5155576 0.0111191                                                                                                             
+ 5 116 53386.00 P  0.128866 0.016376  0.227126 0.016376  P-0.5163974 0.0111869                                                                                                             
+ 5 117 53387.00 P  0.127022 0.016412  0.226107 0.016412  P-0.5171127 0.0112546                                                                                                             
+ 5 118 53388.00 P  0.125168 0.016447  0.225116 0.016447  P-0.5176277 0.0113221                                                                                                             
+ 5 119 53389.00 P  0.123305 0.016482  0.224154 0.016482  P-0.5179132 0.0113895                                                                                                             
+ 5 120 53390.00 P  0.121431 0.016517  0.223221 0.016517  P-0.5179776 0.0114567                                                                                                             
+ 5 121 53391.00 P  0.119549 0.016552  0.222318 0.016552  P-0.5178570 0.0115239                                                                                                             
+ 5 122 53392.00 P  0.117658 0.016586  0.221444 0.016586  P-0.5176063 0.0115909                                                                                                             
+ 5 123 53393.00 P  0.115758 0.016620  0.220599 0.016620  P-0.5172938 0.0116577                                                                                                             
+ 5 124 53394.00 P  0.113850 0.016654  0.219783 0.016654  P-0.5169945 0.0117245                                                                                                             
+ 5 125 53395.00 P  0.111934 0.016688  0.218998 0.016688  P-0.5167813 0.0117911                                                                                                             
+ 5 126 53396.00 P  0.110011 0.016722  0.218241 0.016722  P-0.5167145 0.0118576                                                                                                             
+ 5 127 53397.00 P  0.108080 0.016756  0.217515 0.016756  P-0.5168331 0.0119240                                                                                                             
+ 5 128 53398.00 P  0.106142 0.016789  0.216818 0.016789  P-0.5171485 0.0119902                                                                                                             
+ 5 129 53399.00 P  0.104198 0.016822  0.216151 0.016822  P-0.5176434 0.0120563                                                                                                             
+ 5 130 53400.00 P  0.102248 0.016856  0.215513 0.016856  P-0.5182740 0.0121223                                                                                                             
+ 5 131 53401.00 P  0.100292 0.016888  0.214906 0.016888  P-0.5189751 0.0121882                                                                                                             
+ 5 2 1 53402.00 P  0.098330 0.016921  0.214328 0.016921  P-0.5196660 0.0122540                                                                                                             
+ 5 2 2 53403.00 P  0.096363 0.016954  0.213780 0.016954  P-0.5202611 0.0123196                                                                                                             
+ 5 2 3 53404.00 P  0.094391 0.016986  0.213261 0.016986  P-0.5206869 0.0123852                                                                                                             
+ 5 2 4 53405.00 P  0.092415 0.017019  0.212773 0.017019  P-0.5209070 0.0124506                                                                                                             
+ 5 2 5 53406.00 P  0.090434 0.017051  0.212314 0.017051  P-0.5209454 0.0125159                                                                                                             
+ 5 2 6 53407.00 P  0.088449 0.017083  0.211885 0.017083  P-0.5208947 0.0125811                                                                                                             
+ 5 2 7 53408.00 P  0.086461 0.017114  0.211486 0.017114  P-0.5208967 0.0126462                                                                                                             
+ 5 2 8 53409.00 P  0.084470 0.017146  0.211116 0.017146  P-0.5210965 0.0127112                                                                                                             
+ 5 2 9 53410.00 P  0.082475 0.017178  0.210776 0.017178  P-0.5215885 0.0127760                                                                                                             
+ 5 210 53411.00 P  0.080479 0.017209  0.210465 0.017209  P-0.5223791 0.0128408                                                                                                             
+ 5 211 53412.00 P  0.078480 0.017240  0.210184 0.017240  P-0.5233845 0.0129054                                                                                                             
+ 5 212 53413.00 P  0.076479 0.017271  0.209933 0.017271  P-0.5244640 0.0129699                                                                                                             
+ 5 213 53414.00 P  0.074476 0.017302  0.209711 0.017302  P-0.5254701 0.0130344                                                                                                             
+ 5 214 53415.00 P  0.072473 0.017333  0.209518 0.017333  P-0.5262913 0.0130987                                                                                                             
+ 5 215 53416.00 P  0.070468 0.017364  0.209355 0.017364  P-0.5268723 0.0131629                                                                                                             
+ 5 216 53417.00 P  0.068463 0.017394  0.209221 0.017394  P-0.5272107 0.0132270                                                                                                             
+ 5 217 53418.00 P  0.066458 0.017425  0.209116 0.017425  P-0.5273423 0.0132910                                                                                                             
+ 5 218 53419.00 P  0.064453 0.017455  0.209039 0.017455  P-0.5273257 0.0133550                                                                                                             
+ 5 219 53420.00 P  0.062449 0.017485  0.208992 0.017485  P-0.5272315 0.0134188                                                                                                             
+ 5 220 53421.00 P  0.060445 0.017515  0.208974 0.017515  P-0.5271361 0.0134825                                                                                                             
+ 5 221 53422.00 P  0.058443 0.017545  0.208984 0.017545  P-0.5271148 0.0135461                                                                                                             
+ 5 222 53423.00 P  0.056442 0.017574  0.209023 0.017574  P-0.5272339 0.0136096                                                                                                             
+ 5 223 53424.00 P  0.054443 0.017604  0.209090 0.017604  P-0.5275409 0.0136730                                                                                                             
+ 5 224 53425.00 P  0.052447 0.017633  0.209186 0.017633  P-0.5280573 0.0137363                                                                                                             
+ 5 225 53426.00 P  0.050453 0.017663  0.209309 0.017663  P-0.5287729 0.0137995                                                                                                             
+ 5 226 53427.00 P  0.048462 0.017692  0.209461 0.017692  P-0.5296448 0.0138627                                                                                                             
+ 5 227 53428.00 P  0.046475 0.017721  0.209641 0.017721  P-0.5306033 0.0139257                                                                                                             
+ 5 228 53429.00 P  0.044491 0.017750  0.209848 0.017750  P-0.5315616 0.0139886                                                                                                             
+ 5 3 1 53430.00 P  0.042511 0.017779  0.210083 0.017779  P-0.5324305 0.0140514                                                                                                             
+ 5 3 2 53431.00 P  0.040536 0.017808  0.210346 0.017808  P-0.5331361 0.0141142                                                                                                             
+ 5 3 3 53432.00 P  0.038565 0.017836  0.210636 0.017836  P-0.5336392 0.0141768                                                                                                             
+ 5 3 4 53433.00 P  0.036600 0.017865  0.210953 0.017865  P-0.5339518 0.0142394                                                                                                             
+ 5 3 5 53434.00 P  0.034640 0.017893  0.211297 0.017893  P-0.5341455 0.0143019                                                                                                             
+ 5 3 6 53435.00 P  0.032686 0.017921  0.211667 0.017921  P-0.5343417 0.0143642                                                                                                             
+ 5 3 7 53436.00 P  0.030739 0.017949  0.212065 0.017949  P-0.5346819 0.0144265                                                                                                             
+ 5 3 8 53437.00 P  0.028797 0.017977  0.212488 0.017977  P-0.5352835 0.0144887                                                                                                             
+ 5 3 9 53438.00 P  0.026863 0.018005  0.212938 0.018005  P-0.5361962 0.0145508                                                                                                             
+ 5 310 53439.00 P  0.024936 0.018033  0.213414 0.018033  P-0.5373812 0.0146129                                                                                                             
+ 5 311 53440.00 P  0.023017 0.018061  0.213916 0.018061  P-0.5387212 0.0146748                                                                                                             
+ 5 312 53441.00 P  0.021106 0.018088  0.214444 0.018088  P-0.5400604 0.0147367                                                                                                             
+ 5 313 53442.00 P  0.019204 0.018116  0.214997 0.018116  P-0.5412527 0.0147984                                                                                                             
+ 5 314 53443.00 P  0.017310 0.018143  0.215575 0.018143  P-0.5421992 0.0148601                                                                                                             
+ 5 315 53444.00 P  0.015425 0.018170  0.216178 0.018170  P-0.5428621 0.0149217                                                                                                             
+ 5 316 53445.00 P  0.013550 0.018198  0.216807 0.018198  P-0.5432584 0.0149832                                                                                                             
+ 5 317 53446.00 P  0.011684 0.018225  0.217459 0.018225  P-0.5434432 0.0150446                                                                                                             
+ 5 318 53447.00 P  0.009829 0.018252  0.218137 0.018252  P-0.5434936 0.0151060                                                                                                             
+ 5 319 53448.00 P  0.008012 0.018278  0.218824 0.018278  P-0.5434951 0.0151672                                                                                                             
+ 5 320 53449.00 P  0.006205 0.018305  0.219536 0.018305  P-0.5435302 0.0152284                                                                                                             
+ 5 321 53450.00 P  0.004410 0.018332  0.220271 0.018332  P-0.5436681 0.0152895                                                                                                             
+ 5 322 53451.00 P  0.002626 0.018358  0.221030 0.018358  P-0.5439554 0.0153505                                                                                                             
+ 5 323 53452.00 P  0.000854 0.018385  0.221812 0.018385  P-0.5444110 0.0154114                                                                                                             
+ 5 324 53453.00 P -0.000905 0.018411  0.222617 0.018411  P-0.5450251 0.0154723                                                                                                             
+ 5 325 53454.00 P -0.002651 0.018437  0.223445 0.018437  P-0.5457597 0.0155331                                                                                                             
+ 5 326 53455.00 P -0.004384 0.018464  0.224295 0.018464  P-0.5465522 0.0155938                                                                                                             
+ 5 327 53456.00 P -0.006103 0.018490  0.225168 0.018490  P-0.5473227 0.0156544                                                                                                             
+ 5 328 53457.00 P -0.007809 0.018516  0.226063 0.018516  P-0.5479887 0.0157149                                                                                                             
+ 5 329 53458.00 P -0.009500 0.018541  0.226979 0.018541  P-0.5484844 0.0157754                                                                                                             
+ 5 330 53459.00 P -0.011177 0.018567  0.227918 0.018567  P-0.5487794 0.0158358                                                                                                             
+ 5 331 53460.00 P -0.012839 0.018593  0.228877 0.018593  P-0.5488933 0.0158961                                                                                                             
+ 5 4 1 53461.00 P -0.014485 0.018619  0.229858 0.018619  P-0.5488997 0.0159563                                                                                                             
+ 5 4 2 53462.00 P -0.016115 0.018644  0.230860 0.018644  P-0.5489169 0.0160165                                                                                                             
+ 5 4 3 53463.00 P -0.017730 0.018669  0.231882 0.018669  P-0.5490819 0.0160765                                                                                                             
+ 5 4 4 53464.00 P -0.019328 0.018695  0.232924 0.018695  P-0.5495117 0.0161366                                                                                                             
+ 5 4 5 53465.00 P -0.020909 0.018720  0.233987 0.018720  P-0.5502646 0.0161965                                                                                                             
+ 5 4 6 53466.00 P -0.022474 0.018745  0.235069 0.018745  P-0.5513150 0.0162563                                                                                                             
+ 5 4 7 53467.00 P -0.024020 0.018770  0.236171 0.018770  P-0.5525573 0.0163161                                                                                                             
+ 5 4 8 53468.00 P -0.025549 0.018795  0.237292 0.018795  P-0.5538381 0.0163758                                                                                                             
+ 5 4 9 53469.00 P -0.027060 0.018820  0.238432 0.018820  P-0.5550027 0.0164355                                                                                                             
+ 5 410 53470.00 P -0.028552 0.018845  0.239591 0.018845  P-0.5559384 0.0164951                                                                                                             
+ 5 411 53471.00 P -0.030026 0.018870  0.240768 0.018870  P-0.5565964 0.0165546                                                                                                             
+ 5 412 53472.00 P -0.031480 0.018894  0.241963 0.018894  P-0.5569916 0.0166140                                                                                                             
+ 5 413 53473.00 P -0.032915 0.018919  0.243176 0.018919  P-0.5571830 0.0166733                                                                                                             
+ 5 414 53474.00 P -0.034331 0.018943  0.244407 0.018943  P-0.5572454 0.0167326                                                                                                             
+ 5 415 53475.00 P -0.035726 0.018968  0.245656 0.018968  P-0.5572518 0.0167919                                                                                                             
+ 5 416 53476.00 P -0.037100 0.018992  0.246921 0.018992  P-0.5572716 0.0168510                                                                                                             
+ 5 417 53477.00 P -0.038454 0.019016  0.248203 0.019016  P-0.5573643 0.0169101                                                                                                             
+ 5 418 53478.00 P -0.039787 0.019041  0.249501 0.019041  P-0.5575677 0.0169691                                                                                                             
+ 5 419 53479.00 P -0.041099 0.019065  0.250816 0.019065  P-0.5579013 0.0170280                                                                                                             
+ 5 420 53480.00 P -0.042388 0.019089  0.252147 0.019089  P-0.5583943 0.0170869                                                                                                             
+ 5 421 53481.00 P -0.043656 0.019113  0.253493 0.019113  P-0.5590472 0.0171457                                                                                                             
+ 5 422 53482.00 P -0.044902 0.019136  0.254855 0.019136  P-0.5598039 0.0172045                                                                                                             
+ 5 423 53483.00 P -0.046125 0.019160  0.256232 0.019160  P-0.5605783 0.0172631                                                                                                             
+ 5 424 53484.00 P -0.047326 0.019184  0.257623 0.019184  P-0.5613063 0.0173218                                                                                                             
+ 5 425 53485.00 P -0.048503 0.019208  0.259029 0.019208  P-0.5618863 0.0173803                                                                                                             
+ 5 426 53486.00 P -0.049657 0.019231  0.260450 0.019231  P-0.5622709 0.0174388                                                                                                             
+ 5 427 53487.00 P -0.050788 0.019255  0.261884 0.019255  P-0.5624379 0.0174972                                                                                                             
+ 5 428 53488.00 P -0.051894 0.019278  0.263332 0.019278  P-0.5624141 0.0175555                                                                                                             
+ 5 429 53489.00 P -0.052977 0.019301  0.264793 0.019301  P-0.5622979 0.0176138                                                                                                             
+ 5 430 53490.00 P -0.054035 0.019325  0.266267 0.019325  P-0.5622364 0.0176720                                                                                                             
+ 5 5 1 53491.00 P -0.055069 0.019348  0.267754 0.019348  P-0.5623966 0.0177302                                                                                                             
+ 5 5 2 53492.00 P -0.056077 0.019371  0.269253 0.019371  P-0.5628463 0.0177883                                                                                                             
+ 5 5 3 53493.00 P -0.057061 0.019394  0.270764 0.019394  P-0.5635855 0.0178463                                                                                                             
+ 5 5 4 53494.00 P -0.058019 0.019417  0.272287 0.019417  P-0.5645240 0.0179043                                                                                                             
+ 5 5 5 53495.00 P -0.058952 0.019440  0.273822 0.019440  P-0.5655133 0.0179622                                                                                                             
+ 5 5 6 53496.00 P -0.059860 0.019463  0.275368 0.019463  P-0.5664359 0.0180200                                                                                                             
+ 5 5 7 53497.00 P -0.060741 0.019485  0.276925 0.019485  P-0.5672243 0.0180778                                                                                                             
+ 5 5 8 53498.00 P -0.061597 0.019508  0.278493 0.019508  P-0.5678252 0.0181355                                                                                                             
+ 5 5 9 53499.00 P -0.062426 0.019531  0.280071 0.019531  P-0.5682104 0.0181932                                                                                                             
+ 5 510 53500.00 P -0.063228 0.019553  0.281658 0.019553  P-0.5684041 0.0182508                                                                                                             
+ 5 511 53501.00 P -0.064004 0.019576  0.283256 0.019576  P-0.5684424 0.0183083                                                                                                             
+ 5 512 53502.00 P -0.064754 0.019598  0.284863 0.019598  P-0.5683919 0.0183658                                                                                                             
+ 5 513 53503.00 P -0.065476 0.019621  0.286479 0.019621  P-0.5683328 0.0184232                                                                                                             
+ 5 514 53504.00 P -0.066171 0.019643  0.288104 0.019643  P-0.5683574 0.0184806                                                                                                             
+ 5 515 53505.00 P -0.066840 0.019665  0.289738 0.019665  P-0.5685207 0.0185379                                                                                                             
+ 5 516 53506.00 P -0.067480 0.019687  0.291379 0.019687  P-0.5688847 0.0185951                                                                                                             
+ 5 517 53507.00 P -0.068094 0.019709  0.293029 0.019709  P-0.5694687 0.0186523                                                                                                             
+ 5 518 53508.00 P -0.068680 0.019731  0.294686 0.019731  P-0.5702051 0.0187094                                                                                                             
+ 5 519 53509.00 P -0.069238 0.019753  0.296350 0.019753  P-0.5710462 0.0187665                                                                                                             
+ 5 520 53510.00 P -0.069768 0.019775  0.298021 0.019775  P-0.5719304 0.0188235                                                                                                             
+ 5 521 53511.00 P -0.070271 0.019797  0.299699 0.019797  P-0.5727614 0.0188805                                                                                                             
+ 5 522 53512.00 P -0.070745 0.019819  0.301383 0.019819  P-0.5734194 0.0189374                                                                                                             
+ 5 523 53513.00 P -0.071192 0.019841  0.303073 0.019841  P-0.5738198 0.0189942                                                                                                             
+ 5 524 53514.00 P -0.071610 0.019862  0.304769 0.019862  P-0.5738968 0.0190510                                                                                                             
+ 5 525 53515.00 P -0.072001 0.019884  0.306470 0.019884  P-0.5736789 0.0191077                                                                                                             
+ 5 526 53516.00 P -0.072363 0.019906  0.308177 0.019906  P-0.5732932 0.0191644                                                                                                             
+ 5 527 53517.00 P -0.072697 0.019927  0.309888 0.019927  P-0.5728922 0.0192210                                                                                                             
+ 5 528 53518.00 P -0.073003 0.019948  0.311603 0.019948  P-0.5726124 0.0192776                                                                                                             
+ 5 529 53519.00 P -0.073281 0.019970  0.313323 0.019970  P-0.5725106 0.0193341                                                                                                             
+ 5 530 53520.00 P -0.073530 0.019991  0.315046 0.019991  P-0.5725870 0.0193905                                                                                                             
+ 5 531 53521.00 P -0.073751 0.020012  0.316773 0.020012  P-0.5728159 0.0194469                                                                                                             
+ 5 6 1 53522.00 P -0.073944 0.020034  0.318504 0.020034  P-0.5731251 0.0195032                                                                                                             
+ 5 6 2 53523.00 P -0.074109 0.020055  0.320237 0.020055  P-0.5734127 0.0195595                                                                                                             
+ 5 6 3 53524.00 P -0.074245 0.020076  0.321972 0.020076  P-0.5735879 0.0196158                                                                                                             
+ 5 6 4 53525.00 P -0.074354 0.020097  0.323710 0.020097  P-0.5735794 0.0196719                                                                                                             
+ 5 6 5 53526.00 P -0.074434 0.020118  0.325450 0.020118  P-0.5733438 0.0197281                                                                                                             
+ 5 6 6 53527.00 P -0.074486 0.020139  0.327191 0.020139  P-0.5728598 0.0197841                                                                                                             
+ 5 6 7 53528.00 P -0.074510 0.020160  0.328933 0.020160  P-0.5721281 0.0198402                                                                                                             
+ 5 6 8 53529.00 P -0.074506 0.020180  0.330677 0.020180  P-0.5712797 0.0198961                                                                                                             
+ 5 6 9 53530.00 P -0.074475 0.020201  0.332421 0.020201  P-0.5704031 0.0199521                                                                                                             
+ 5 610 53531.00 P -0.074416 0.020222  0.334166 0.020222  P-0.5695097 0.0200079                                                                                                             
+ 5 611 53532.00 P -0.074329 0.020242  0.335910 0.020242  P-0.5686014 0.0200637                                                                                                             
+ 5 612 53533.00 P -0.074214 0.020263  0.337654 0.020263  P-0.5677307 0.0201195                                                                                                             
+ 5 613 53534.00 P -0.074072 0.020284  0.339398 0.020284  P-0.5669817 0.0201752                                                                                                             
+ 5 614 53535.00 P -0.073903 0.020304  0.341141 0.020304  P-0.5663464 0.0202309                                                                                                             
+ 5 615 53536.00 P -0.073707 0.020324  0.342882 0.020324  P-0.5658082 0.0202865                                                                                                             
+ 5 616 53537.00 P -0.073484 0.020345  0.344622 0.020345  P-0.5653532 0.0203420                                                                                                             
+ 5 617 53538.00 P -0.073233 0.020365  0.346360 0.020365  P-0.5649379 0.0203975                                                                                                             
+ 5 618 53539.00 P -0.072956 0.020385  0.348095 0.020385  P-0.5644983 0.0204530                                                                                                             
+ 5 619 53540.00 P -0.072653 0.020406  0.349828 0.020406  P-0.5639137 0.0205084                                                                                                             
+ 5 620 53541.00 P -0.072323 0.020426  0.351559 0.020426  P-0.5631150 0.0205638                                                                                                             
+ 5 621 53542.00 P -0.071967 0.020446  0.353286 0.020446  P-0.5620583 0.0206191                                                                                                             
+ 5 622 53543.00 P -0.071585 0.020466  0.355009 0.020466  P-0.5608633 0.0206743                                                                                                             
+ 5 623 53544.00 P -0.071178 0.020486  0.356729 0.020486  P-0.5596658 0.0207295                                                                                                             
+ 5 624 53545.00 P -0.070745 0.020506  0.358445 0.020506  P-0.5585709 0.0207847                                                                                                             
+ 5 625 53546.00 P -0.070286 0.020526  0.360156 0.020526  P-0.5576565 0.0208398                                                                                                             
+ 5 626 53547.00 P -0.069802 0.020546  0.361863 0.020546  P-0.5569753 0.0208949                                                                                                             
+ 5 627 53548.00 P -0.069294 0.020566  0.363565 0.020566  P-0.5565155 0.0209499                                                                                                             
+ 5 628 53549.00 P -0.068761 0.020585  0.365261 0.020585  P-0.5561814 0.0210048                                                                                                             
+ 5 629 53550.00 P -0.068203 0.020605  0.366951 0.020605  P-0.5558311 0.0210598                                                                                                             
+ 5 630 53551.00 P -0.067621 0.020625  0.368636 0.020625  P-0.5553461 0.0211146                                                                                                             
+ 5 7 1 53552.00 P -0.067016 0.020644  0.370314 0.020644  P-0.5546563 0.0211695                                                                                                             
+ 5 7 2 53553.00 P -0.066386 0.020664  0.371986 0.020664  P-0.5537249 0.0212242                                                                                                             
+ 5 7 3 53554.00 P -0.065734 0.020683  0.373650 0.020683  P-0.5525553 0.0212790                                                                                                             
+ 5 7 4 53555.00 P -0.065058 0.020703  0.375308 0.020703  P-0.5511996 0.0213337                                                                                                             
+ 5 7 5 53556.00 P -0.064360 0.020722  0.376958 0.020722  P-0.5497363 0.0213883                                                                                                             
+ 5 7 6 53557.00 P -0.063639 0.020742  0.378600 0.020742  P-0.5482537 0.0214429                                                                                                             
+ 5 7 7 53558.00 P -0.062895 0.020761  0.380234 0.020761  P-0.5468062 0.0214974                                                                                                             
+ 5 7 8 53559.00 P -0.062130 0.020780  0.381860 0.020780  P-0.5454592 0.0215519                                                                                                             
+ 5 7 9 53560.00 P -0.061344 0.020800  0.383477 0.020800  P-0.5442381 0.0216064                                                                                                             
+ 5 710 53561.00 P -0.060536 0.020819  0.385084 0.020819  P-0.5431233 0.0216608                                                                                                             
+ 5 711 53562.00 P -0.059707 0.020838  0.386683 0.020838  P-0.5421922 0.0217152                                                                                                             
+ 5 712 53563.00 P -0.058858 0.020857  0.388272 0.020857  P-0.5414819 0.0217695                                                                                                             
+ 5 713 53564.00 P -0.057988 0.020876  0.389851 0.020876  P-0.5409254 0.0218238                                                                                                             
+ 5 714 53565.00 P -0.057099 0.020895  0.391419 0.020895  P-0.5404186 0.0218780                                                                                                             
+ 5 715 53566.00 P -0.056189 0.020914  0.392978 0.020914  P-0.5398830 0.0219322                                                                                                             
+ 5 716 53567.00 P -0.055261 0.020933  0.394525 0.020933  P-0.5392463 0.0219863                                                                                                             
+ 5 717 53568.00 P -0.054313 0.020952  0.396062 0.020952  P-0.5384172 0.0220404                                                                                                             
+ 5 718 53569.00 P -0.053347 0.020971  0.397587 0.020971  P-0.5373040 0.0220944                                                                                                             
+ 5 719 53570.00 P -0.052363 0.020989  0.399100 0.020989  P-0.5359209 0.0221485                                                                                                             
+ 5 720 53571.00 P -0.051361 0.021008  0.400601 0.021008  P-0.5344400 0.0222024                                                                                                             
+ 5 721 53572.00 P -0.050342 0.021027  0.402091 0.021027  P-0.5330005 0.0222563                                                                                                             
+ 5 722 53573.00 P -0.049305 0.021046  0.403567 0.021046  P-0.5317176 0.0223102                                                                                                             
+ 5 723 53574.00 P -0.048252 0.021064  0.405031 0.021064  P-0.5306862 0.0223640                                                                                                             
+ 5 724 53575.00 P -0.047182 0.021083  0.406482 0.021083  P-0.5299442 0.0224178                                                                                                             
+ 5 725 53576.00 P -0.046096 0.021101  0.407920 0.021101  P-0.5294145 0.0224716                                                                                                             
+ 5 726 53577.00 P -0.044994 0.021120  0.409344 0.021120  P-0.5289379 0.0225253                                                                                                             
+ 5 727 53578.00 P -0.043878 0.021138  0.410755 0.021138  P-0.5283369 0.0225790                                                                                                             
+ 5 728 53579.00 P -0.042746 0.021157  0.412151 0.021157  P-0.5274951 0.0226326                                                                                                             
+ 5 729 53580.00 P -0.041600 0.021175  0.413533 0.021175  P-0.5263843 0.0226862                                                                                                             
+ 5 730 53581.00 P -0.040439 0.021193  0.414900 0.021193  P-0.5250389 0.0227397                                                                                                             
+ 5 731 53582.00 P -0.039265 0.021212  0.416252 0.021212  P-0.5235308 0.0227932                                                                                                             
+ 5 8 1 53583.00 P -0.038078 0.021230  0.417590 0.021230  P-0.5219161 0.0228466                                                                                                             
+ 5 8 2 53584.00 P -0.036877 0.021248  0.418912 0.021248  P-0.5202708 0.0229000                                                                                                             
+ 5 8 3 53585.00 P -0.035664 0.021266  0.420218 0.021266  P-0.5187071 0.0229534                                                                                                             
+ 5 8 4 53586.00 P -0.034439 0.021285  0.421509 0.021285  P-0.5173021 0.0230067                                                                                                             
+ 5 8 5 53587.00 P -0.033202 0.021303  0.422783 0.021303  P-0.5161053 0.0230600                                                                                                             
+ 5 8 6 53588.00 P -0.031953 0.021321  0.424042 0.021321  P-0.5151366 0.0231133                                                                                                             
+ 5 8 7 53589.00 P -0.030693 0.021339  0.425283 0.021339  P-0.5143909 0.0231665                                                                                                             
+ 5 8 8 53590.00 P -0.029423 0.021357  0.426508 0.021357  P-0.5138229 0.0232197                                                                                                             
+ 5 8 9 53591.00 P -0.028142 0.021375  0.427717 0.021375  P-0.5133909 0.0232728                                                                                                             
+ 5 810 53592.00 P -0.026852 0.021393  0.428907 0.021393  P-0.5130107 0.0233259                                                                                                             
+ 5 811 53593.00 P -0.025551 0.021410  0.430081 0.021410  P-0.5125769 0.0233789                                                                                                             
+ 5 812 53594.00 P -0.024242 0.021428  0.431237 0.021428  P-0.5120121 0.0234319                                                                                                             
+ 5 813 53595.00 P -0.022924 0.021446  0.432375 0.021446  P-0.5112680 0.0234849                                                                                                             
+ 5 814 53596.00 P -0.021597 0.021464  0.433495 0.021464  P-0.5103416 0.0235378                                                                                                             
+ 5 815 53597.00 P -0.020262 0.021481  0.434597 0.021481  P-0.5092561 0.0235907                                                                                                             
+ 5 816 53598.00 P -0.018920 0.021499  0.435680 0.021499  P-0.5080685 0.0236435                                                                                                             
+ 5 817 53599.00 P -0.017570 0.021517  0.436745 0.021517  P-0.5068980 0.0236963                                                                                                             
+ 5 818 53600.00 P -0.016213 0.021534  0.437791 0.021534  P-0.5058864 0.0237491                                                                                                             
+ 5 819 53601.00 P -0.014850 0.021552  0.438819 0.021552  P-0.5051650 0.0238018                                                                                                             
+ 5 820 53602.00 P -0.013480 0.021569  0.439827 0.021569  P-0.5047915 0.0238545                                                                                                             
+ 5 821 53603.00 P -0.012105 0.021587  0.440815 0.021587  P-0.5047204 0.0239072                                                                                                             
+ 5 822 53604.00 P -0.010724 0.021604  0.441785 0.021604  P-0.5048754 0.0239598                                                                                                             
+ 5 823 53605.00 P -0.009338 0.021622  0.442734 0.021622  P-0.5050711 0.0240124                                                                                                             
+ 5 824 53606.00 P -0.007947 0.021639  0.443664 0.021639  P-0.5050958 0.0240649                                                                                                             
+ 5 825 53607.00 P -0.006551 0.021657  0.444574 0.021657  P-0.5048353 0.0241174                                                                                                             
+ 5 826 53608.00 P -0.005151 0.021674  0.445464 0.021674  P-0.5042904 0.0241699                                                                                                             
+ 5 827 53609.00 P -0.003748 0.021691  0.446334 0.021691  P-0.5035055 0.0242223                                                                                                             
+ 5 828 53610.00 P -0.002341 0.021708  0.447183 0.021708  P-0.5025326 0.0242747                                                                                                             
+ 5 829 53611.00 P -0.000930 0.021726  0.448012 0.021726  P-0.5014525 0.0243270                                                                                                             
+ 5 830 53612.00 P  0.000483 0.021743  0.448820 0.021743  P-0.5003552 0.0243793                                                                                                             
+ 5 831 53613.00 P  0.001898 0.021760  0.449608 0.021760  P-0.4993236 0.0244316                                                                                                             
+ 5 9 1 53614.00 P  0.003316 0.021777  0.450374 0.021777  P-0.4984066 0.0244838                                                                                                             
+ 5 9 2 53615.00 P  0.004736 0.021794  0.451120 0.021794  P-0.4976803 0.0245360                                                                                                             
+ 5 9 3 53616.00 P  0.006157 0.021811  0.451845 0.021811  P-0.4971752 0.0245882                                                                                                             
+ 5 9 4 53617.00 P  0.007580 0.021828  0.452548 0.021828  P-0.4968823 0.0246403                                                                                                             
+ 5 9 5 53618.00 P  0.009004 0.021845  0.453230 0.021845  P-0.4967654 0.0246924                                                                                                             
+ 5 9 6 53619.00 P  0.010428 0.021862  0.453891 0.021862  P-0.4967675 0.0247445                                                                                                             
+ 5 9 7 53620.00 P  0.011853 0.021879  0.454530 0.021879  P-0.4967874 0.0247965                                                                                                             
+ 5 9 8 53621.00 P  0.013278 0.021896  0.455148 0.021896  P-0.4967251 0.0248485                                                                                                             
+ 5 9 9 53622.00 P  0.014703 0.021912  0.455744 0.021912  P-0.4965391 0.0249004                                                                                                             
+ 5 910 53623.00 P  0.016128 0.021929  0.456319 0.021929  P-0.4961973 0.0249523                                                                                                             
+ 5 911 53624.00 P  0.017552 0.021946  0.456871 0.021946  P-0.4956907 0.0250042                                                                                                             
+ 5 912 53625.00 P  0.018975 0.021963  0.457402 0.021963  P-0.4951242 0.0250560                                                                                                             
+ 5 913 53626.00 P  0.020397 0.021979  0.457911 0.021979  P-0.4945260 0.0251078                                                                                                             
+ 5 914 53627.00 P  0.021817 0.021996  0.458399 0.021996  P-0.4940029 0.0251596                                                                                                             
+ 5 915 53628.00                                                                                                                                                                            
+ 5 916 53629.00                                                                                                                                                                            
+ 5 917 53630.00                                                                                                                                                                            
+ 5 918 53631.00                                                                                                                                                                            
+ 5 919 53632.00                                                                                                                                                                            
+ 5 920 53633.00                                                                                                                                                                            
+ 5 921 53634.00                                                                                                                                                                            
+ 5 922 53635.00                                                                                                                                                                            
+ 5 923 53636.00                                                                                                                                                                            
+ 5 924 53637.00                                                                                                                                                                            
+ 5 925 53638.00                                                                                                                                                                            
+ 5 926 53639.00                                                                                                                                                                            
+ 5 927 53640.00                                                                                                                                                                            
+ 5 928 53641.00                                                                                                                                                                            
+ 5 929 53642.00                                                                                                                                                                            
+ 5 930 53643.00                                                                                                                                                                            
+ 510 1 53644.00                                                                                                                                                                            
+ 510 2 53645.00                                                                                                                                                                            
+ 510 3 53646.00                                                                                                                                                                            
+ 510 4 53647.00                                                                                                                                                                            
+ 510 5 53648.00                                                                                                                                                                            
+ 510 6 53649.00                                                                                                                                                                            
+ 510 7 53650.00                                                                                                                                                                            
+ 510 8 53651.00                                                                                                                                                                            
+ 510 9 53652.00                                                                                                                                                                            
+ 51010 53653.00                                                                                                                                                                            
+ 51011 53654.00                                                                                                                                                                            
+ 51012 53655.00                                                                                                                                                                            
+ 51013 53656.00                                                                                                                                                                            
+ 51014 53657.00                                                                                                                                                                            
+ 51015 53658.00                                                                                                                                                                            
+ 51016 53659.00                                                                                                                                                                            
+ 51017 53660.00                                                                                                                                                                            
+ 51018 53661.00                                                                                                                                                                            
+ 51019 53662.00                                                                                                                                                                            
+ 51020 53663.00                                                                                                                                                                            
+ 51021 53664.00                                                                                                                                                                            
+ 51022 53665.00                                                                                                                                                                            
+ 51023 53666.00                                                                                                                                                                            
+ 51024 53667.00                                                                                                                                                                            
+ 51025 53668.00                                                                                                                                                                            
+ 51026 53669.00                                                                                                                                                                            
+ 51027 53670.00                                                                                                                                                                            
+ 51028 53671.00                                                                                                                                                                            
+ 51029 53672.00                                                                                                                                                                            
+ 51030 53673.00                                                                                                                                                                            
+ 51031 53674.00                                                                                                                                                                            
+ 511 1 53675.00                                                                                                                                                                            
+ 511 2 53676.00                                                                                                                                                                            
+ 511 3 53677.00                                                                                                                                                                            
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/iers_corr.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/iers_corr.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/iers_corr.dat	(revision 22158)
@@ -0,0 +1,11658 @@
+#
+#  Stripped version of finals.all.orig file
+#
+#
+#           Bull A  Bull A  Bull B  Bull B
+#  MJD        dX      dY      dX      dY
+#
+41684.00    44.969  2.839   0.000   0.000
+41685.00    45.005  2.762   0.000   0.000
+41686.00    45.122  2.851   0.000   0.000
+41687.00    45.344  3.02    0.000   0.000
+41688.00    45.623  3.115   0.000   0.000
+41689.00    45.812  3.086   0.000   0.000
+41690.00    45.804  3.014   0.000   0.000
+41691.00    45.647  2.993   0.000   0.000
+41692.00    45.466  3.049   0.000   0.000
+41693.00    45.326  3.164   0.000   0.000
+41694.00    45.177  3.328   0.000   0.000
+41695.00    44.931  3.504   0.000   0.000
+41696.00    44.607  3.585   0.000   0.000
+41697.00    44.381  3.456   0.000   0.000
+41698.00    44.444  3.159   0.000   0.000
+41699.00    44.789  2.911   0.000   0.000
+41700.00    45.213  2.902   0.000   0.000
+41701.00    45.571  3.082   0.000   0.000
+41702.00    45.88   3.232   0.000   0.000
+41703.00    46.144  3.212   0.000   0.000
+41704.00    46.215  3.08    0.000   0.000
+41705.00    45.986  2.953   0.000   0.000
+41706.00    45.602  2.872   0.000   0.000
+41707.00    45.321  2.83    0.000   0.000
+41708.00    45.204  2.845   0.000   0.000
+41709.00    45.127  2.911   0.000   0.000
+41710.00    45.037  2.932   0.000   0.000
+41711.00    45.034  2.807   0.000   0.000
+41712.00    45.159  2.575   0.000   0.000
+41713.00    45.302  2.396   0.000   0.000
+41714.00    45.368  2.374   0.000   0.000
+41715.00    45.424  2.457   0.000   0.000
+41716.00    45.573  2.528   0.000   0.000
+41717.00    45.777  2.546   0.000   0.000
+41718.00    45.873  2.551   0.000   0.000
+41719.00    45.754  2.591   0.000   0.000
+41720.00    45.463  2.668   0.000   0.000
+41721.00    45.133  2.756   0.000   0.000
+41722.00    44.868  2.829   0.000   0.000
+41723.00    44.688  2.858   0.000   0.000
+41724.00    44.561  2.796   0.000   0.000
+41725.00    44.488  2.592   0.000   0.000
+41726.00    44.523  2.256   0.000   0.000
+41727.00    44.706  1.91    0.000   0.000
+41728.00    45.014  1.74    0.000   0.000
+41729.00    45.369  1.834   0.000   0.000
+41730.00    45.69   2.09    0.000   0.000
+41731.00    45.896  2.292   0.000   0.000
+41732.00    45.915  2.292   0.000   0.000
+41733.00    45.743  2.108   0.000   0.000
+41734.00    45.478  1.871   0.000   0.000
+41735.00    45.236  1.717   0.000   0.000
+41736.00    45.062  1.699   0.000   0.000
+41737.00    44.96   1.744   0.000   0.000
+41738.00    44.978  1.702   0.000   0.000
+41739.00    45.179  1.485   0.000   0.000
+41740.00    45.518  1.18    0.000   0.000
+41741.00    45.826  0.966   0.000   0.000
+41742.00    45.957  0.925   0.000   0.000
+41743.00    45.948  0.981   0.000   0.000
+41744.00    45.972  1.036   0.000   0.000
+41745.00    46.134  1.098   0.000   0.000
+41746.00    46.333  1.23    0.000   0.000
+41747.00    46.349  1.411   0.000   0.000
+41748.00    46.073  1.53    0.000   0.000
+41749.00    45.63   1.491   0.000   0.000
+41750.00    45.282  1.305   0.000   0.000
+41751.00    45.2    1.053   0.000   0.000
+41752.00    45.348  0.809   0.000   0.000
+41753.00    45.567  0.583   0.000   0.000
+41754.00    45.749  0.342   0.000   0.000
+41755.00    45.908  0.085   0.000   0.000
+41756.00    46.111  -0.101  0.000   0.000
+41757.00    46.359  -0.097  0.000   0.000
+41758.00    46.565  0.113   0.000   0.000
+41759.00    46.646  0.377   0.000   0.000
+41760.00    46.625  0.491   0.000   0.000
+41761.00    46.599  0.371   0.000   0.000
+41762.00    46.602  0.123   0.000   0.000
+41763.00    46.573  -0.074  0.000   0.000
+41764.00    46.479  -0.128  0.000   0.000
+41765.00    46.407  -0.113  0.000   0.000
+41766.00    46.482  -0.191  0.000   0.000
+41767.00    46.738  -0.435  0.000   0.000
+41768.00    47.096  -0.719  0.000   0.000
+41769.00    47.439  -0.841  0.000   0.000
+41770.00    47.66   -0.755  0.000   0.000
+41771.00    47.708  -0.619  0.000   0.000
+41772.00    47.656  -0.586  0.000   0.000
+41773.00    47.657  -0.594  0.000   0.000
+41774.00    47.755  -0.472  0.000   0.000
+41775.00    47.777  -0.208  0.000   0.000
+41776.00    47.525  -0.014  0.000   0.000
+41777.00    47.067  -0.098  0.000   0.000
+41778.00    46.721  -0.445  0.000   0.000
+41779.00    46.735  -0.857  0.000   0.000
+41780.00    47.048  -1.157  0.000   0.000
+41781.00    47.407  -1.31   0.000   0.000
+41782.00    47.621  -1.381  0.000   0.000
+41783.00    47.697  -1.438  0.000   0.000
+41784.00    47.76   -1.487  0.000   0.000
+41785.00    47.893  -1.478  0.000   0.000
+41786.00    48.042  -1.369  0.000   0.000
+41787.00    48.11   -1.192  0.000   0.000
+41788.00    48.103  -1.063  0.000   0.000
+41789.00    48.13   -1.09   0.000   0.000
+41790.00    48.23   -1.274  0.000   0.000
+41791.00    48.307  -1.497  0.000   0.000
+41792.00    48.285  -1.633  0.000   0.000
+41793.00    48.252  -1.673  0.000   0.000
+41794.00    48.328  -1.729  0.000   0.000
+41795.00    48.496  -1.89   0.000   0.000
+41796.00    48.672  -2.069  0.000   0.000
+41797.00    48.855  -2.076  0.000   0.000
+41798.00    49.072  -1.865  0.000   0.000
+41799.00    49.227  -1.639  0.000   0.000
+41800.00    49.192  -1.624  0.000   0.000
+41801.00    49.002  -1.766  0.000   0.000
+41802.00    48.804  -1.785  0.000   0.000
+41803.00    48.609  -1.553  0.000   0.000
+41804.00    48.303  -1.283  0.000   0.000
+41805.00    47.912  -1.272  0.000   0.000
+41806.00    47.676  -1.556  0.000   0.000
+41807.00    47.783  -1.901  0.000   0.000
+41808.00    48.144  -2.105  0.000   0.000
+41809.00    48.506  -2.159  0.000   0.000
+41810.00    48.682  -2.135  0.000   0.000
+41811.00    48.646  -2.059  0.000   0.000
+41812.00    48.495  -1.934  0.000   0.000
+41813.00    48.38   -1.805  0.000   0.000
+41814.00    48.391  -1.724  0.000   0.000
+41815.00    48.47   -1.681  0.000   0.000
+41816.00    48.493  -1.642  0.000   0.000
+41817.00    48.429  -1.642  0.000   0.000
+41818.00    48.338  -1.764  0.000   0.000
+41819.00    48.257  -2.005  0.000   0.000
+41820.00    48.19   -2.232  0.000   0.000
+41821.00    48.184  -2.313  0.000   0.000
+41822.00    48.271  -2.27   0.000   0.000
+41823.00    48.355  -2.237  0.000   0.000
+41824.00    48.321  -2.263  0.000   0.000
+41825.00    48.237  -2.235  0.000   0.000
+41826.00    48.279  -2.059  0.000   0.000
+41827.00    48.438  -1.855  0.000   0.000
+41828.00    48.477  -1.837  0.000   0.000
+41829.00    48.233  -2.004  0.000   0.000
+41830.00    47.789  -2.097  0.000   0.000
+41831.00    47.316  -1.928  0.000   0.000
+41832.00    46.906  -1.643  0.000   0.000
+41833.00    46.634  -1.536  0.000   0.000
+41834.00    46.601  -1.673  0.000   0.000
+41835.00    46.812  -1.851  0.000   0.000
+41836.00    47.124  -1.909  0.000   0.000
+41837.00    47.384  -1.899  0.000   0.000
+41838.00    47.513  -1.906  0.000   0.000
+41839.00    47.43   -1.863  0.000   0.000
+41840.00    47.075  -1.675  0.000   0.000
+41841.00    46.583  -1.423  0.000   0.000
+41842.00    46.25   -1.296  0.000   0.000
+41843.00    46.209  -1.348  0.000   0.000
+41844.00    46.255  -1.447  0.000   0.000
+41845.00    46.116  -1.494  0.000   0.000
+41846.00    45.778  -1.564  0.000   0.000
+41847.00    45.432  -1.753  0.000   0.000
+41848.00    45.234  -1.978  0.000   0.000
+41849.00    45.208  -2.043  0.000   0.000
+41850.00    45.288  -1.886  0.000   0.000
+41851.00    45.332  -1.668  0.000   0.000
+41852.00    45.194  -1.573  0.000   0.000
+41853.00    44.903  -1.6    0.000   0.000
+41854.00    44.673  -1.617  0.000   0.000
+41855.00    44.646  -1.579  0.000   0.000
+41856.00    44.685  -1.573  0.000   0.000
+41857.00    44.53   -1.64   0.000   0.000
+41858.00    44.084  -1.662  0.000   0.000
+41859.00    43.488  -1.528  0.000   0.000
+41860.00    42.99   -1.336  0.000   0.000
+41861.00    42.793  -1.289  0.000   0.000
+41862.00    42.935  -1.412  0.000   0.000
+41863.00    43.238  -1.515  0.000   0.000
+41864.00    43.467  -1.477  0.000   0.000
+41865.00    43.568  -1.406  0.000   0.000
+41866.00    43.619  -1.435  0.000   0.000
+41867.00    43.555  -1.481  0.000   0.000
+41868.00    43.148  -1.365  0.000   0.000
+41869.00    42.41   -1.11   0.000   0.000
+41870.00    41.75   -0.951  0.000   0.000
+41871.00    41.54   -1.025  0.000   0.000
+41872.00    41.654  -1.203  0.000   0.000
+41873.00    41.661  -1.301  0.000   0.000
+41874.00    41.377  -1.323  0.000   0.000
+41875.00    41.003  -1.397  0.000   0.000
+41876.00    40.774  -1.523  0.000   0.000
+41877.00    40.719  -1.543  0.000   0.000
+41878.00    40.75   -1.368  0.000   0.000
+41879.00    40.772  -1.121  0.000   0.000
+41880.00    40.683  -1.011  0.000   0.000
+41881.00    40.421  -1.103  0.000   0.000
+41882.00    40.073  -1.28   0.000   0.000
+41883.00    39.825  -1.4    0.000   0.000
+41884.00    39.743  -1.425  0.000   0.000
+41885.00    39.684  -1.388  0.000   0.000
+41886.00    39.458  -1.31   0.000   0.000
+41887.00    39.044  -1.212  0.000   0.000
+41888.00    38.635  -1.178  0.000   0.000
+41889.00    38.475  -1.3    0.000   0.000
+41890.00    38.632  -1.529  0.000   0.000
+41891.00    38.911  -1.67   0.000   0.000
+41892.00    39.057  -1.601  0.000   0.000
+41893.00    39.048  -1.422  0.000   0.000
+41894.00    39.042  -1.32   0.000   0.000
+41895.00    39.03   -1.312  0.000   0.000
+41896.00    38.75   -1.259  0.000   0.000
+41897.00    38.079  -1.104  0.000   0.000
+41898.00    37.356  -0.98   0.000   0.000
+41899.00    37.053  -1.016  0.000   0.000
+41900.00    37.223  -1.147  0.000   0.000
+41901.00    37.493  -1.221  0.000   0.000
+41902.00    37.566  -1.207  0.000   0.000
+41903.00    37.487  -1.2    0.000   0.000
+41904.00    37.412  -1.241  0.000   0.000
+41905.00    37.363  -1.248  0.000   0.000
+41906.00    37.3    -1.156  0.000   0.000
+41907.00    37.253  -1.025  0.000   0.000
+41908.00    37.235  -0.981  0.000   0.000
+41909.00    37.148  -1.064  0.000   0.000
+41910.00    36.897  -1.202  0.000   0.000
+41911.00    36.55   -1.292  0.000   0.000
+41912.00    36.278  -1.285  0.000   0.000
+41913.00    36.167  -1.206  0.000   0.000
+41914.00    36.149  -1.113  0.000   0.000
+41915.00    36.119  -1.077  0.000   0.000
+41916.00    36.066  -1.158  0.000   0.000
+41917.00    36.072  -1.377  0.000   0.000
+41918.00    36.178  -1.657  0.000   0.000
+41919.00    36.302  -1.839  0.000   0.000
+41920.00    36.331  -1.793  0.000   0.000
+41921.00    36.274  -1.543  0.000   0.000
+41922.00    36.251  -1.253  0.000   0.000
+41923.00    36.267  -1.065  0.000   0.000
+41924.00    36.134  -0.987  0.000   0.000
+41925.00    35.708  -0.958  0.000   0.000
+41926.00    35.162  -0.955  0.000   0.000
+41927.00    34.859  -0.99   0.000   0.000
+41928.00    34.981  -1.038  0.000   0.000
+41929.00    35.383  -1.053  0.000   0.000
+41930.00    35.812  -1.041  0.000   0.000
+41931.00    36.129  -1.055  0.000   0.000
+41932.00    36.294  -1.103  0.000   0.000
+41933.00    36.287  -1.135  0.000   0.000
+41934.00    36.14   -1.123  0.000   0.000
+41935.00    35.984  -1.115  0.000   0.000
+41936.00    35.929  -1.153  0.000   0.000
+41937.00    35.93   -1.203  0.000   0.000
+41938.00    35.836  -1.194  0.000   0.000
+41939.00    35.575  -1.11   0.000   0.000
+41940.00    35.255  -0.996  0.000   0.000
+41941.00    35.063  -0.901  0.000   0.000
+41942.00    35.106  -0.851  0.000   0.000
+41943.00    35.349  -0.862  0.000   0.000
+41944.00    35.671  -0.95   0.000   0.000
+41945.00    35.952  -1.113  0.000   0.000
+41946.00    36.134  -1.315  0.000   0.000
+41947.00    36.213  -1.471  0.000   0.000
+41948.00    36.226  -1.476  0.000   0.000
+41949.00    36.225  -1.273  0.000   0.000
+41950.00    36.241  -0.933  0.000   0.000
+41951.00    36.243  -0.625  0.000   0.000
+41952.00    36.159  -0.491  0.000   0.000
+41953.00    35.95   -0.542  0.000   0.000
+41954.00    35.683  -0.681  0.000   0.000
+41955.00    35.517  -0.796  0.000   0.000
+41956.00    35.609  -0.833  0.000   0.000
+41957.00    36.017  -0.814  0.000   0.000
+41958.00    36.629  -0.805  0.000   0.000
+41959.00    37.213  -0.849  0.000   0.000
+41960.00    37.556  -0.911  0.000   0.000
+41961.00    37.6    -0.92   0.000   0.000
+41962.00    37.446  -0.881  0.000   0.000
+41963.00    37.245  -0.885  0.000   0.000
+41964.00    37.102  -0.977  0.000   0.000
+41965.00    37.042  -1.063  0.000   0.000
+41966.00    37.031  -1.003  0.000   0.000
+41967.00    37.007  -0.791  0.000   0.000
+41968.00    36.954  -0.561  0.000   0.000
+41969.00    36.937  -0.429  0.000   0.000
+41970.00    37.043  -0.391  0.000   0.000
+41971.00    37.283  -0.383  0.000   0.000
+41972.00    37.574  -0.385  0.000   0.000
+41973.00    37.828  -0.427  0.000   0.000
+41974.00    38.023  -0.522  0.000   0.000
+41975.00    38.185  -0.62   0.000   0.000
+41976.00    38.342  -0.634  0.000   0.000
+41977.00    38.486  -0.494  0.000   0.000
+41978.00    38.559  -0.216  0.000   0.000
+41979.00    38.511  0.08    0.000   0.000
+41980.00    38.369  0.243   0.000   0.000
+41981.00    38.235  0.206   0.000   0.000
+41982.00    38.179  0.031   0.000   0.000
+41983.00    38.212  -0.141  0.000   0.000
+41984.00    38.373  -0.207  0.000   0.000
+41985.00    38.756  -0.167  0.000   0.000
+41986.00    39.353  -0.103  0.000   0.000
+41987.00    39.94   -0.083  0.000   0.000
+41988.00    40.252  -0.079  0.000   0.000
+41989.00    40.248  -0.008  0.000   0.000
+41990.00    40.092  0.127   0.000   0.000
+41991.00    39.917  0.188   0.000   0.000
+41992.00    39.731  0.072   0.000   0.000
+41993.00    39.552  -0.116  0.000   0.000
+41994.00    39.482  -0.147  0.000   0.000
+41995.00    39.596  0.06    0.000   0.000
+41996.00    39.861  0.336   0.000   0.000
+41997.00    40.194  0.487   0.000   0.000
+41998.00    40.509  0.512   0.000   0.000
+41999.00    40.699  0.533   0.000   0.000
+42000.00    40.689  0.589   0.000   0.000
+42001.00    40.555  0.593   0.000   0.000
+42002.00    40.495  0.499   0.000   0.000
+42003.00    40.625  0.398   0.000   0.000
+42004.00    40.87   0.418   0.000   0.000
+42005.00    41.069  0.588   0.000   0.000
+42006.00    41.114  0.828   0.000   0.000
+42007.00    40.995  1.04    0.000   0.000
+42008.00    40.787  1.161   0.000   0.000
+42009.00    40.62   1.162   0.000   0.000
+42010.00    40.598  1.053   0.000   0.000
+42011.00    40.715  0.905   0.000   0.000
+42012.00    40.934  0.829   0.000   0.000
+42013.00    41.279  0.889   0.000   0.000
+42014.00    41.744  1.032   0.000   0.000
+42015.00    42.157  1.153   0.000   0.000
+42016.00    42.298  1.218   0.000   0.000
+42017.00    42.167  1.301   0.000   0.000
+42018.00    41.979  1.442   0.000   0.000
+42019.00    41.86   1.532   0.000   0.000
+42020.00    41.731  1.43    0.000   0.000
+42021.00    41.515  1.201   0.000   0.000
+42022.00    41.311  1.094   0.000   0.000
+42023.00    41.281  1.245   0.000   0.000
+42024.00    41.489  1.491   0.000   0.000
+42025.00    41.9    1.585   0.000   0.000
+42026.00    42.391  1.508   0.000   0.000
+42027.00    42.74   1.444   0.000   0.000
+42028.00    42.751  1.474   0.000   0.000
+42029.00    42.499  1.469   0.000   0.000
+42030.00    42.301  1.33    0.000   0.000
+42031.00    42.358  1.184   0.000   0.000
+42032.00    42.537  1.228   0.000   0.000
+42033.00    42.603  1.462   0.000   0.000
+42034.00    42.509  1.696   0.000   0.000
+42035.00    42.35   1.793   0.000   0.000
+42036.00    42.178  1.784   0.000   0.000
+42037.00    42.000  1.749   0.000   0.000
+42038.00    41.879  1.69    0.000   0.000
+42039.00    41.897  1.591   0.000   0.000
+42040.00    42.071  1.522   0.000   0.000
+42041.00    42.365  1.587   0.000   0.000
+42042.00    42.717  1.779   0.000   0.000
+42043.00    42.993  1.955   0.000   0.000
+42044.00    43.04   2.006   0.000   0.000
+42045.00    42.865  1.983   0.000   0.000
+42046.00    42.663  2.001   0.000   0.000
+42047.00    42.577  2.053   0.000   0.000
+42048.00    42.536  2.028   0.000   0.000
+42049.00    42.386  1.917   0.000   0.000
+42050.00    42.104  1.876   0.000   0.000
+42051.00    41.796  2.011   0.000   0.000
+42052.00    41.601  2.176   0.000   0.000
+42053.00    41.651  2.135   0.000   0.000
+42054.00    41.997  1.89    0.000   0.000
+42055.00    42.478  1.691   0.000   0.000
+42056.00    42.808  1.697   0.000   0.000
+42057.00    42.893  1.772   0.000   0.000
+42058.00    42.921  1.726   0.000   0.000
+42059.00    43.036  1.61    0.000   0.000
+42060.00    43.106  1.629   0.000   0.000
+42061.00    42.96   1.814   0.000   0.000
+42062.00    42.702  1.961   0.000   0.000
+42063.00    42.551  1.913   0.000   0.000
+42064.00    42.501  1.745   0.000   0.000
+42065.00    42.372  1.61    0.000   0.000
+42066.00    42.14   1.53    0.000   0.000
+42067.00    42.000  1.434   0.000   0.000
+42068.00    42.095  1.347   0.000   0.000
+42069.00    42.37   1.385   0.000   0.000
+42070.00    42.684  1.572   0.000   0.000
+42071.00    42.926  1.757   0.000   0.000
+42072.00    43.013  1.775   0.000   0.000
+42073.00    42.924  1.642   0.000   0.000
+42074.00    42.756  1.513   0.000   0.000
+42075.00    42.646  1.491   0.000   0.000
+42076.00    42.608  1.536   0.000   0.000
+42077.00    42.526  1.583   0.000   0.000
+42078.00    42.286  1.647   0.000   0.000
+42079.00    41.889  1.741   0.000   0.000
+42080.00    41.451  1.752   0.000   0.000
+42081.00    41.179  1.531   0.000   0.000
+42082.00    41.248  1.134   0.000   0.000
+42083.00    41.62   0.845   0.000   0.000
+42084.00    42.053  0.877   0.000   0.000
+42085.00    42.366  1.122   0.000   0.000
+42086.00    42.585  1.301   0.000   0.000
+42087.00    42.752  1.300   0.000   0.000
+42088.00    42.759  1.237   0.000   0.000
+42089.00    42.532  1.215   0.000   0.000
+42090.00    42.258  1.163   0.000   0.000
+42091.00    42.183  0.995   0.000   0.000
+42092.00    42.254  0.768   0.000   0.000
+42093.00    42.2    0.601   0.000   0.000
+42094.00    41.966  0.495   0.000   0.000
+42095.00    41.819  0.369   0.000   0.000
+42096.00    41.977  0.235   0.000   0.000
+42097.00    42.344  0.216   0.000   0.000
+42098.00    42.693  0.359   0.000   0.000
+42099.00    42.928  0.533   0.000   0.000
+42100.00    43.065  0.565   0.000   0.000
+42101.00    43.098  0.431   0.000   0.000
+42102.00    43.02   0.263   0.000   0.000
+42103.00    42.899  0.188   0.000   0.000
+42104.00    42.814  0.218   0.000   0.000
+42105.00    42.76   0.287   0.000   0.000
+42106.00    42.654  0.333   0.000   0.000
+42107.00    42.447  0.309   0.000   0.000
+42108.00    42.193  0.15    0.000   0.000
+42109.00    42.03   -0.189  0.000   0.000
+42110.00    42.079  -0.62   0.000   0.000
+42111.00    42.323  -0.906  0.000   0.000
+42112.00    42.607  -0.845  0.000   0.000
+42113.00    42.798  -0.495  0.000   0.000
+42114.00    42.895  -0.139  0.000   0.000
+42115.00    42.943  -0.023  0.000   0.000
+42116.00    42.915  -0.159  0.000   0.000
+42117.00    42.797  -0.399  0.000   0.000
+42118.00    42.704  -0.623  0.000   0.000
+42119.00    42.75   -0.791  0.000   0.000
+42120.00    42.845  -0.893  0.000   0.000
+42121.00    42.795  -0.943  0.000   0.000
+42122.00    42.62   -1.011  0.000   0.000
+42123.00    42.601  -1.158  0.000   0.000
+42124.00    42.912  -1.331  0.000   0.000
+42125.00    43.394  -1.393  0.000   0.000
+42126.00    43.753  -1.298  0.000   0.000
+42127.00    43.896  -1.153  0.000   0.000
+42128.00    43.931  -1.099  0.000   0.000
+42129.00    43.944  -1.155  0.000   0.000
+42130.00    43.909  -1.236  0.000   0.000
+42131.00    43.802  -1.277  0.000   0.000
+42132.00    43.678  -1.29   0.000   0.000
+42133.00    43.611  -1.327  0.000   0.000
+42134.00    43.617  -1.415  0.000   0.000
+42135.00    43.662  -1.559  0.000   0.000
+42136.00    43.72   -1.767  0.000   0.000
+42137.00    43.804  -2.037  0.000   0.000
+42138.00    43.947  -2.323  0.000   0.000
+42139.00    44.14   -2.508  0.000   0.000
+42140.00    44.313  -2.462  0.000   0.000
+42141.00    44.379  -2.172  0.000   0.000
+42142.00    44.321  -1.813  0.000   0.000
+42143.00    44.201  -1.636  0.000   0.000
+42144.00    44.112  -1.758  0.000   0.000
+42145.00    44.124  -2.066  0.000   0.000
+42146.00    44.244  -2.336  0.000   0.000
+42147.00    44.388  -2.424  0.000   0.000
+42148.00    44.422  -2.349  0.000   0.000
+42149.00    44.295  -2.249  0.000   0.000
+42150.00    44.145  -2.268  0.000   0.000
+42151.00    44.197  -2.435  0.000   0.000
+42152.00    44.526  -2.632  0.000   0.000
+42153.00    44.958  -2.704  0.000   0.000
+42154.00    45.229  -2.623  0.000   0.000
+42155.00    45.224  -2.516  0.000   0.000
+42156.00    45.042  -2.495  0.000   0.000
+42157.00    44.843  -2.528  0.000   0.000
+42158.00    44.693  -2.507  0.000   0.000
+42159.00    44.557  -2.427  0.000   0.000
+42160.00    44.413  -2.4    0.000   0.000
+42161.00    44.33   -2.516  0.000   0.000
+42162.00    44.397  -2.735  0.000   0.000
+42163.00    44.612  -2.942  0.000   0.000
+42164.00    44.856  -3.06   0.000   0.000
+42165.00    45.006  -3.102  0.000   0.000
+42166.00    45.051  -3.122  0.000   0.000
+42167.00    45.085  -3.14   0.000   0.000
+42168.00    45.178  -3.11   0.000   0.000
+42169.00    45.285  -2.968  0.000   0.000
+42170.00    45.283  -2.742  0.000   0.000
+42171.00    45.127  -2.576  0.000   0.000
+42172.00    44.938  -2.611  0.000   0.000
+42173.00    44.9    -2.829  0.000   0.000
+42174.00    45.05   -3.057  0.000   0.000
+42175.00    45.225  -3.122  0.000   0.000
+42176.00    45.247  -3.008  0.000   0.000
+42177.00    45.125  -2.86   0.000   0.000
+42178.00    45.019  -2.846  0.000   0.000
+42179.00    45.046  -2.998  0.000   0.000
+42180.00    45.195  -3.182  0.000   0.000
+42181.00    45.385  -3.228  0.000   0.000
+42182.00    45.511  -3.119  0.000   0.000
+42183.00    45.452  -3.01   0.000   0.000
+42184.00    45.147  -3.032  0.000   0.000
+42185.00    44.695  -3.108  0.000   0.000
+42186.00    44.289  -3.055  0.000   0.000
+42187.00    44.03   -2.848  0.000   0.000
+42188.00    43.889  -2.686  0.000   0.000
+42189.00    43.849  -2.76   0.000   0.000
+42190.00    43.978  -3.022  0.000   0.000
+42191.00    44.281  -3.24   0.000   0.000
+42192.00    44.586  -3.251  0.000   0.000
+42193.00    44.673  -3.086  0.000   0.000
+42194.00    44.498  -2.882  0.000   0.000
+42195.00    44.226  -2.737  0.000   0.000
+42196.00    44.069  -2.659  0.000   0.000
+42197.00    44.081  -2.607  0.000   0.000
+42198.00    44.123  -2.544  0.000   0.000
+42199.00    44.013  -2.486  0.000   0.000
+42200.00    43.737  -2.491  0.000   0.000
+42201.00    43.476  -2.592  0.000   0.000
+42202.00    43.39   -2.748  0.000   0.000
+42203.00    43.438  -2.852  0.000   0.000
+42204.00    43.475  -2.829  0.000   0.000
+42205.00    43.459  -2.712  0.000   0.000
+42206.00    43.439  -2.624  0.000   0.000
+42207.00    43.4    -2.659  0.000   0.000
+42208.00    43.285  -2.77   0.000   0.000
+42209.00    43.153  -2.811  0.000   0.000
+42210.00    43.119  -2.716  0.000   0.000
+42211.00    43.109  -2.602  0.000   0.000
+42212.00    42.864  -2.623  0.000   0.000
+42213.00    42.283  -2.735  0.000   0.000
+42214.00    41.601  -2.723  0.000   0.000
+42215.00    41.133  -2.496  0.000   0.000
+42216.00    40.981  -2.251  0.000   0.000
+42217.00    41.067  -2.249  0.000   0.000
+42218.00    41.313  -2.484  0.000   0.000
+42219.00    41.637  -2.689  0.000   0.000
+42220.00    41.876  -2.659  0.000   0.000
+42221.00    41.859  -2.437  0.000   0.000
+42222.00    41.552  -2.187  0.000   0.000
+42223.00    41.071  -1.986  0.000   0.000
+42224.00    40.592  -1.838  0.000   0.000
+42225.00    40.266  -1.767  0.000   0.000
+42226.00    40.148  -1.819  0.000   0.000
+42227.00    40.115  -1.959  0.000   0.000
+42228.00    39.97   -2.094  0.000   0.000
+42229.00    39.657  -2.176  0.000   0.000
+42230.00    39.329  -2.247  0.000   0.000
+42231.00    39.149  -2.332  0.000   0.000
+42232.00    39.134  -2.365  0.000   0.000
+42233.00    39.202  -2.263  0.000   0.000
+42234.00    39.257  -2.069  0.000   0.000
+42235.00    39.185  -1.942  0.000   0.000
+42236.00    38.916  -1.978  0.000   0.000
+42237.00    38.579  -2.095  0.000   0.000
+42238.00    38.425  -2.147  0.000   0.000
+42239.00    38.479  -2.122  0.000   0.000
+42240.00    38.418  -2.139  0.000   0.000
+42241.00    37.945  -2.237  0.000   0.000
+42242.00    37.181  -2.28   0.000   0.000
+42243.00    36.551  -2.161  0.000   0.000
+42244.00    36.355  -2.000  0.000   0.000
+42245.00    36.571  -2.015  0.000   0.000
+42246.00    36.975  -2.212  0.000   0.000
+42247.00    37.31   -2.356  0.000   0.000
+42248.00    37.402  -2.274  0.000   0.000
+42249.00    37.243  -2.058  0.000   0.000
+42250.00    36.943  -1.879  0.000   0.000
+42251.00    36.55   -1.748  0.000   0.000
+42252.00    36.02   -1.579  0.000   0.000
+42253.00    35.445  -1.427  0.000   0.000
+42254.00    35.112  -1.465  0.000   0.000
+42255.00    35.18   -1.731  0.000   0.000
+42256.00    35.413  -2.03   0.000   0.000
+42257.00    35.435  -2.161  0.000   0.000
+42258.00    35.179  -2.138  0.000   0.000
+42259.00    34.905  -2.096  0.000   0.000
+42260.00    34.827  -2.062  0.000   0.000
+42261.00    34.913  -1.938  0.000   0.000
+42262.00    34.999  -1.7    0.000   0.000
+42263.00    34.949  -1.504  0.000   0.000
+42264.00    34.709  -1.521  0.000   0.000
+42265.00    34.374  -1.735  0.000   0.000
+42266.00    34.161  -1.957  0.000   0.000
+42267.00    34.188  -2.055  0.000   0.000
+42268.00    34.267  -2.07   0.000   0.000
+42269.00    34.08   -2.1    0.000   0.000
+42270.00    33.561  -2.146  0.000   0.000
+42271.00    33.005  -2.159  0.000   0.000
+42272.00    32.777  -2.181  0.000   0.000
+42273.00    32.986  -2.301  0.000   0.000
+42274.00    33.422  -2.475  0.000   0.000
+42275.00    33.721  -2.51   0.000   0.000
+42276.00    33.663  -2.309  0.000   0.000
+42277.00    33.364  -2.032  0.000   0.000
+42278.00    33.119  -1.89   0.000   0.000
+42279.00    32.997  -1.863  0.000   0.000
+42280.00    32.754  -1.769  0.000   0.000
+42281.00    32.259  -1.581  0.000   0.000
+42282.00    31.83   -1.506  0.000   0.000
+42283.00    31.882  -1.688  0.000   0.000
+42284.00    32.354  -1.987  0.000   0.000
+42285.00    32.762  -2.14   0.000   0.000
+42286.00    32.811  -2.079  0.000   0.000
+42287.00    32.675  -1.945  0.000   0.000
+42288.00    32.641  -1.847  0.000   0.000
+42289.00    32.732  -1.744  0.000   0.000
+42290.00    32.797  -1.59   0.000   0.000
+42291.00    32.753  -1.47   0.000   0.000
+42292.00    32.606  -1.516  0.000   0.000
+42293.00    32.381  -1.725  0.000   0.000
+42294.00    32.152  -1.944  0.000   0.000
+42295.00    32.043  -2.035  0.000   0.000
+42296.00    32.09   -2.002  0.000   0.000
+42297.00    32.16   -1.949  0.000   0.000
+42298.00    32.098  -1.957  0.000   0.000
+42299.00    31.934  -2.042  0.000   0.000
+42300.00    31.865  -2.204  0.000   0.000
+42301.00    32.036  -2.418  0.000   0.000
+42302.00    32.361  -2.583  0.000   0.000
+42303.00    32.561  -2.543  0.000   0.000
+42304.00    32.438  -2.256  0.000   0.000
+42305.00    32.118  -1.903  0.000   0.000
+42306.00    31.946  -1.726  0.000   0.000
+42307.00    32.054  -1.762  0.000   0.000
+42308.00    32.171  -1.814  0.000   0.000
+42309.00    32.000  -1.735  0.000   0.000
+42310.00    31.682  -1.606  0.000   0.000
+42311.00    31.644  -1.598  0.000   0.000
+42312.00    32.035  -1.718  0.000   0.000
+42313.00    32.555  -1.817  0.000   0.000
+42314.00    32.888  -1.805  0.000   0.000
+42315.00    33.047  -1.74   0.000   0.000
+42316.00    33.191  -1.701  0.000   0.000
+42317.00    33.322  -1.682  0.000   0.000
+42318.00    33.336  -1.655  0.000   0.000
+42319.00    33.242  -1.647  0.000   0.000
+42320.00    33.135  -1.698  0.000   0.000
+42321.00    33.024  -1.776  0.000   0.000
+42322.00    32.856  -1.794  0.000   0.000
+42323.00    32.676  -1.713  0.000   0.000
+42324.00    32.634  -1.58   0.000   0.000
+42325.00    32.805  -1.479  0.000   0.000
+42326.00    33.102  -1.466  0.000   0.000
+42327.00    33.393  -1.554  0.000   0.000
+42328.00    33.64   -1.722  0.000   0.000
+42329.00    33.881  -1.911  0.000   0.000
+42330.00    34.116  -2.027  0.000   0.000
+42331.00    34.245  -1.963  0.000   0.000
+42332.00    34.178  -1.693  0.000   0.000
+42333.00    33.988  -1.34   0.000   0.000
+42334.00    33.896  -1.11   0.000   0.000
+42335.00    34.031  -1.114  0.000   0.000
+42336.00    34.266  -1.259  0.000   0.000
+42337.00    34.37   -1.351  0.000   0.000
+42338.00    34.319  -1.298  0.000   0.000
+42339.00    34.331  -1.169  0.000   0.000
+42340.00    34.583  -1.071  0.000   0.000
+42341.00    35.022  -1.042  0.000   0.000
+42342.00    35.482  -1.066  0.000   0.000
+42343.00    35.866  -1.121  0.000   0.000
+42344.00    36.134  -1.181  0.000   0.000
+42345.00    36.232  -1.215  0.000   0.000
+42346.00    36.132  -1.223  0.000   0.000
+42347.00    35.93   -1.238  0.000   0.000
+42348.00    35.772  -1.259  0.000   0.000
+42349.00    35.697  -1.21   0.000   0.000
+42350.00    35.635  -1.031  0.000   0.000
+42351.00    35.555  -0.777  0.000   0.000
+42352.00    35.548  -0.58   0.000   0.000
+42353.00    35.724  -0.519  0.000   0.000
+42354.00    36.079  -0.567  0.000   0.000
+42355.00    36.484  -0.651  0.000   0.000
+42356.00    36.804  -0.726  0.000   0.000
+42357.00    36.995  -0.776  0.000   0.000
+42358.00    37.092  -0.78   0.000   0.000
+42359.00    37.136  -0.7    0.000   0.000
+42360.00    37.135  -0.509  0.000   0.000
+42361.00    37.085  -0.24   0.000   0.000
+42362.00    37.016  -0.005  0.000   0.000
+42363.00    36.982  0.067   0.000   0.000
+42364.00    37.025  -0.047  0.000   0.000
+42365.00    37.146  -0.221  0.000   0.000
+42366.00    37.319  -0.28   0.000   0.000
+42367.00    37.523  -0.16   0.000   0.000
+42368.00    37.778  0.047   0.000   0.000
+42369.00    38.116  0.197   0.000   0.000
+42370.00    38.519  0.215   0.000   0.000
+42371.00    38.874  0.129   0.000   0.000
+42372.00    39.038  0.037   0.000   0.000
+42373.00    38.959  0.013   0.000   0.000
+42374.00    38.721  0.042   0.000   0.000
+42375.00    38.457  0.046   0.000   0.000
+42376.00    38.251  0.007   0.000   0.000
+42377.00    38.129  0.026   0.000   0.000
+42378.00    38.095  0.205   0.000   0.000
+42379.00    38.147  0.477   0.000   0.000
+42380.00    38.287  0.641   0.000   0.000
+42381.00    38.522  0.578   0.000   0.000
+42382.00    38.831  0.381   0.000   0.000
+42383.00    39.12   0.242   0.000   0.000
+42384.00    39.263  0.251   0.000   0.000
+42385.00    39.218  0.355   0.000   0.000
+42386.00    39.079  0.466   0.000   0.000
+42387.00    38.979  0.56    0.000   0.000
+42388.00    38.961  0.669   0.000   0.000
+42389.00    38.957  0.815   0.000   0.000
+42390.00    38.867  0.961   0.000   0.000
+42391.00    38.676  1.027   0.000   0.000
+42392.00    38.495  0.963   0.000   0.000
+42393.00    38.486  0.819   0.000   0.000
+42394.00    38.704  0.724   0.000   0.000
+42395.00    39.036  0.776   0.000   0.000
+42396.00    39.343  0.954   0.000   0.000
+42397.00    39.606  1.142   0.000   0.000
+42398.00    39.857  1.228   0.000   0.000
+42399.00    40.025  1.194   0.000   0.000
+42400.00    39.984  1.121   0.000   0.000
+42401.00    39.751  1.100   0.000   0.000
+42402.00    39.503  1.135   0.000   0.000
+42403.00    39.346  1.128   0.000   0.000
+42404.00    39.21   1.013   0.000   0.000
+42405.00    39.019  0.889   0.000   0.000
+42406.00    38.851  0.924   0.000   0.000
+42407.00    38.83   1.117   0.000   0.000
+42408.00    38.977  1.24    0.000   0.000
+42409.00    39.237  1.096   0.000   0.000
+42410.00    39.556  0.777   0.000   0.000
+42411.00    39.851  0.568   0.000   0.000
+42412.00    39.981  0.627   0.000   0.000
+42413.00    39.881  0.847   0.000   0.000
+42414.00    39.658  1.037   0.000   0.000
+42415.00    39.483  1.129   0.000   0.000
+42416.00    39.405  1.174   0.000   0.000
+42417.00    39.348  1.204   0.000   0.000
+42418.00    39.226  1.192   0.000   0.000
+42419.00    39.023  1.112   0.000   0.000
+42420.00    38.799  0.992   0.000   0.000
+42421.00    38.672  0.884   0.000   0.000
+42422.00    38.736  0.825   0.000   0.000
+42423.00    38.961  0.838   0.000   0.000
+42424.00    39.219  0.932   0.000   0.000
+42425.00    39.431  1.082   0.000   0.000
+42426.00    39.588  1.21    0.000   0.000
+42427.00    39.642  1.239   0.000   0.000
+42428.00    39.522  1.167   0.000   0.000
+42429.00    39.297  1.079   0.000   0.000
+42430.00    39.166  1.035   0.000   0.000
+42431.00    39.193  0.979   0.000   0.000
+42432.00    39.185  0.819   0.000   0.000
+42433.00    38.957  0.601   0.000   0.000
+42434.00    38.595  0.511   0.000   0.000
+42435.00    38.326  0.626   0.000   0.000
+42436.00    38.256  0.752   0.000   0.000
+42437.00    38.354  0.637   0.000   0.000
+42438.00    38.593  0.314   0.000   0.000
+42439.00    38.925  0.093   0.000   0.000
+42440.00    39.206  0.188   0.000   0.000
+42441.00    39.306  0.475   0.000   0.000
+42442.00    39.26   0.689   0.000   0.000
+42443.00    39.181  0.734   0.000   0.000
+42444.00    39.094  0.697   0.000   0.000
+42445.00    38.964  0.628   0.000   0.000
+42446.00    38.826  0.468   0.000   0.000
+42447.00    38.736  0.203   0.000   0.000
+42448.00    38.642  -0.053  0.000   0.000
+42449.00    38.471  -0.185  0.000   0.000
+42450.00    38.296  -0.206  0.000   0.000
+42451.00    38.28   -0.197  0.000   0.000
+42452.00    38.47   -0.171  0.000   0.000
+42453.00    38.756  -0.075  0.000   0.000
+42454.00    39.002  0.075   0.000   0.000
+42455.00    39.124  0.152   0.000   0.000
+42456.00    39.092  0.059   0.000   0.000
+42457.00    38.986  -0.146  0.000   0.000
+42458.00    38.969  -0.328  0.000   0.000
+42459.00    39.099  -0.448  0.000   0.000
+42460.00    39.194  -0.588  0.000   0.000
+42461.00    39.041  -0.782  0.000   0.000
+42462.00    38.674  -0.915  0.000   0.000
+42463.00    38.323  -0.883  0.000   0.000
+42464.00    38.14   -0.796  0.000   0.000
+42465.00    38.127  -0.867  0.000   0.000
+42466.00    38.252  -1.11   0.000   0.000
+42467.00    38.485  -1.267  0.000   0.000
+42468.00    38.732  -1.13   0.000   0.000
+42469.00    38.893  -0.821  0.000   0.000
+42470.00    38.975  -0.635  0.000   0.000
+42471.00    39.018  -0.681  0.000   0.000
+42472.00    38.985  -0.828  0.000   0.000
+42473.00    38.853  -0.969  0.000   0.000
+42474.00    38.758  -1.159  0.000   0.000
+42475.00    38.824  -1.454  0.000   0.000
+42476.00    38.914  -1.745  0.000   0.000
+42477.00    38.778  -1.889  0.000   0.000
+42478.00    38.452  -1.896  0.000   0.000
+42479.00    38.286  -1.89   0.000   0.000
+42480.00    38.513  -1.901  0.000   0.000
+42481.00    38.986  -1.835  0.000   0.000
+42482.00    39.396  -1.665  0.000   0.000
+42483.00    39.591  -1.533  0.000   0.000
+42484.00    39.605  -1.605  0.000   0.000
+42485.00    39.548  -1.867  0.000   0.000
+42486.00    39.541  -2.147  0.000   0.000
+42487.00    39.65   -2.319  0.000   0.000
+42488.00    39.795  -2.415  0.000   0.000
+42489.00    39.814  -2.52   0.000   0.000
+42490.00    39.657  -2.629  0.000   0.000
+42491.00    39.464  -2.682  0.000   0.000
+42492.00    39.396  -2.701  0.000   0.000
+42493.00    39.488  -2.786  0.000   0.000
+42494.00    39.668  -2.936  0.000   0.000
+42495.00    39.827  -2.979  0.000   0.000
+42496.00    39.877  -2.78   0.000   0.000
+42497.00    39.812  -2.461  0.000   0.000
+42498.00    39.733  -2.302  0.000   0.000
+42499.00    39.715  -2.422  0.000   0.000
+42500.00    39.702  -2.665  0.000   0.000
+42501.00    39.636  -2.841  0.000   0.000
+42502.00    39.626  -2.938  0.000   0.000
+42503.00    39.785  -3.052  0.000   0.000
+42504.00    39.958  -3.19   0.000   0.000
+42505.00    39.852  -3.28   0.000   0.000
+42506.00    39.493  -3.32   0.000   0.000
+42507.00    39.294  -3.379  0.000   0.000
+42508.00    39.556  -3.449  0.000   0.000
+42509.00    40.091  -3.423  0.000   0.000
+42510.00    40.474  -3.259  0.000   0.000
+42511.00    40.524  -3.09   0.000   0.000
+42512.00    40.372  -3.094  0.000   0.000
+42513.00    40.203  -3.293  0.000   0.000
+42514.00    40.109  -3.548  0.000   0.000
+42515.00    40.136  -3.724  0.000   0.000
+42516.00    40.285  -3.809  0.000   0.000
+42517.00    40.46   -3.869  0.000   0.000
+42518.00    40.538  -3.941  0.000   0.000
+42519.00    40.515  -4.017  0.000   0.000
+42520.00    40.515  -4.089  0.000   0.000
+42521.00    40.648  -4.168  0.000   0.000
+42522.00    40.892  -4.224  0.000   0.000
+42523.00    41.099  -4.16   0.000   0.000
+42524.00    41.112  -3.916  0.000   0.000
+42525.00    40.908  -3.593  0.000   0.000
+42526.00    40.627  -3.417  0.000   0.000
+42527.00    40.429  -3.518  0.000   0.000
+42528.00    40.357  -3.783  0.000   0.000
+42529.00    40.374  -3.977  0.000   0.000
+42530.00    40.49   -3.987  0.000   0.000
+42531.00    40.706  -3.887  0.000   0.000
+42532.00    40.87   -3.81   0.000   0.000
+42533.00    40.772  -3.829  0.000   0.000
+42534.00    40.455  -3.952  0.000   0.000
+42535.00    40.256  -4.145  0.000   0.000
+42536.00    40.414  -4.312  0.000   0.000
+42537.00    40.754  -4.337  0.000   0.000
+42538.00    40.897  -4.2    0.000   0.000
+42539.00    40.691  -4.027  0.000   0.000
+42540.00    40.305  -3.963  0.000   0.000
+42541.00    39.96   -4.026  0.000   0.000
+42542.00    39.749  -4.136  0.000   0.000
+42543.00    39.691  -4.231  0.000   0.000
+42544.00    39.806  -4.32   0.000   0.000
+42545.00    40.054  -4.417  0.000   0.000
+42546.00    40.291  -4.493  0.000   0.000
+42547.00    40.377  -4.511  0.000   0.000
+42548.00    40.308  -4.47   0.000   0.000
+42549.00    40.209  -4.401  0.000   0.000
+42550.00    40.208  -4.319  0.000   0.000
+42551.00    40.312  -4.196  0.000   0.000
+42552.00    40.399  -3.995  0.000   0.000
+42553.00    40.331  -3.742  0.000   0.000
+42554.00    40.074  -3.556  0.000   0.000
+42555.00    39.733  -3.562  0.000   0.000
+42556.00    39.479  -3.748  0.000   0.000
+42557.00    39.434  -3.941  0.000   0.000
+42558.00    39.61   -3.962  0.000   0.000
+42559.00    39.883  -3.8    0.000   0.000
+42560.00    40.054  -3.609  0.000   0.000
+42561.00    39.99   -3.564  0.000   0.000
+42562.00    39.751  -3.721  0.000   0.000
+42563.00    39.531  -3.991  0.000   0.000
+42564.00    39.455  -4.207  0.000   0.000
+42565.00    39.452  -4.244  0.000   0.000
+42566.00    39.34   -4.116  0.000   0.000
+42567.00    39.017  -3.955  0.000   0.000
+42568.00    38.532  -3.872  0.000   0.000
+42569.00    38.028  -3.851  0.000   0.000
+42570.00    37.638  -3.82   0.000   0.000
+42571.00    37.447  -3.788  0.000   0.000
+42572.00    37.489  -3.842  0.000   0.000
+42573.00    37.726  -3.999  0.000   0.000
+42574.00    38.032  -4.133  0.000   0.000
+42575.00    38.207  -4.097  0.000   0.000
+42576.00    38.093  -3.87   0.000   0.000
+42577.00    37.703  -3.571  0.000   0.000
+42578.00    37.236  -3.338  0.000   0.000
+42579.00    36.936  -3.225  0.000   0.000
+42580.00    36.893  -3.183  0.000   0.000
+42581.00    36.96   -3.137  0.000   0.000
+42582.00    36.889  -3.073  0.000   0.000
+42583.00    36.559  -3.057  0.000   0.000
+42584.00    36.107  -3.149  0.000   0.000
+42585.00    35.815  -3.303  0.000   0.000
+42586.00    35.839  -3.385  0.000   0.000
+42587.00    36.067  -3.31   0.000   0.000
+42588.00    36.253  -3.142  0.000   0.000
+42589.00    36.257  -3.036  0.000   0.000
+42590.00    36.105  -3.092  0.000   0.000
+42591.00    35.867  -3.276  0.000   0.000
+42592.00    35.587  -3.452  0.000   0.000
+42593.00    35.326  -3.499  0.000   0.000
+42594.00    35.137  -3.419  0.000   0.000
+42595.00    34.943  -3.326  0.000   0.000
+42596.00    34.572  -3.321  0.000   0.000
+42597.00    33.978  -3.36   0.000   0.000
+42598.00    33.37   -3.33   0.000   0.000
+42599.00    33.03   -3.23   0.000   0.000
+42600.00    33.057  -3.206  0.000   0.000
+42601.00    33.337  -3.35   0.000   0.000
+42602.00    33.678  -3.532  0.000   0.000
+42603.00    33.892  -3.509  0.000   0.000
+42604.00    33.802  -3.201  0.000   0.000
+42605.00    33.336  -2.778  0.000   0.000
+42606.00    32.638  -2.481  0.000   0.000
+42607.00    32.01   -2.412  0.000   0.000
+42608.00    31.697  -2.514  0.000   0.000
+42609.00    31.705  -2.672  0.000   0.000
+42610.00    31.813  -2.809  0.000   0.000
+42611.00    31.758  -2.908  0.000   0.000
+42612.00    31.465  -2.988  0.000   0.000
+42613.00    31.118  -3.063  0.000   0.000
+42614.00    30.958  -3.114  0.000   0.000
+42615.00    31.029  -3.095  0.000   0.000
+42616.00    31.17   -2.985  0.000   0.000
+42617.00    31.223  -2.825  0.000   0.000
+42618.00    31.149  -2.704  0.000   0.000
+42619.00    30.942  -2.698  0.000   0.000
+42620.00    30.617  -2.799  0.000   0.000
+42621.00    30.316  -2.919  0.000   0.000
+42622.00    30.229  -2.988  0.000   0.000
+42623.00    30.303  -3.042  0.000   0.000
+42624.00    30.19   -3.161  0.000   0.000
+42625.00    29.655  -3.324  0.000   0.000
+42626.00    28.937  -3.394  0.000   0.000
+42627.00    28.525  -3.304  0.000   0.000
+42628.00    28.634  -3.183  0.000   0.000
+42629.00    29.054  -3.205  0.000   0.000
+42630.00    29.439  -3.327  0.000   0.000
+42631.00    29.583  -3.32   0.000   0.000
+42632.00    29.436  -3.059  0.000   0.000
+42633.00    29.046  -2.692  0.000   0.000
+42634.00    28.527  -2.455  0.000   0.000
+42635.00    28.016  -2.414  0.000   0.000
+42636.00    27.617  -2.481  0.000   0.000
+42637.00    27.419  -2.591  0.000   0.000
+42638.00    27.478  -2.759  0.000   0.000
+42639.00    27.724  -2.968  0.000   0.000
+42640.00    27.938  -3.119  0.000   0.000
+42641.00    27.962  -3.138  0.000   0.000
+42642.00    27.861  -3.062  0.000   0.000
+42643.00    27.81   -2.969  0.000   0.000
+42644.00    27.857  -2.863  0.000   0.000
+42645.00    27.903  -2.693  0.000   0.000
+42646.00    27.854  -2.477  0.000   0.000
+42647.00    27.677  -2.344  0.000   0.000
+42648.00    27.403  -2.405  0.000   0.000
+42649.00    27.172  -2.623  0.000   0.000
+42650.00    27.183  -2.857  0.000   0.000
+42651.00    27.423  -3.033  0.000   0.000
+42652.00    27.55   -3.201  0.000   0.000
+42653.00    27.248  -3.396  0.000   0.000
+42654.00    26.664  -3.527  0.000   0.000
+42655.00    26.303  -3.484  0.000   0.000
+42656.00    26.468  -3.325  0.000   0.000
+42657.00    26.965  -3.221  0.000   0.000
+42658.00    27.361  -3.219  0.000   0.000
+42659.00    27.395  -3.177  0.000   0.000
+42660.00    27.125  -2.992  0.000   0.000
+42661.00    26.806  -2.774  0.000   0.000
+42662.00    26.652  -2.685  0.000   0.000
+42663.00    26.621  -2.694  0.000   0.000
+42664.00    26.478  -2.635  0.000   0.000
+42665.00    26.144  -2.494  0.000   0.000
+42666.00    25.913  -2.458  0.000   0.000
+42667.00    26.119  -2.64   0.000   0.000
+42668.00    26.679  -2.891  0.000   0.000
+42669.00    27.169  -2.977  0.000   0.000
+42670.00    27.34   -2.86   0.000   0.000
+42671.00    27.333  -2.689  0.000   0.000
+42672.00    27.363  -2.566  0.000   0.000
+42673.00    27.426  -2.442  0.000   0.000
+42674.00    27.398  -2.269  0.000   0.000
+42675.00    27.245  -2.138  0.000   0.000
+42676.00    27.039  -2.181  0.000   0.000
+42677.00    26.888  -2.395  0.000   0.000
+42678.00    26.908  -2.632  0.000   0.000
+42679.00    27.127  -2.776  0.000   0.000
+42680.00    27.376  -2.859  0.000   0.000
+42681.00    27.412  -2.962  0.000   0.000
+42682.00    27.224  -3.069  0.000   0.000
+42683.00    27.096  -3.086  0.000   0.000
+42684.00    27.287  -2.99   0.000   0.000
+42685.00    27.73   -2.87   0.000   0.000
+42686.00    28.1    -2.778  0.000   0.000
+42687.00    28.134  -2.657  0.000   0.000
+42688.00    27.87   -2.469  0.000   0.000
+42689.00    27.631  -2.328  0.000   0.000
+42690.00    27.737  -2.357  0.000   0.000
+42691.00    28.141  -2.465  0.000   0.000
+42692.00    28.408  -2.407  0.000   0.000
+42693.00    28.222  -2.123  0.000   0.000
+42694.00    27.839  -1.865  0.000   0.000
+42695.00    27.822  -1.894  0.000   0.000
+42696.00    28.345  -2.158  0.000   0.000
+42697.00    29.005  -2.373  0.000   0.000
+42698.00    29.382  -2.375  0.000   0.000
+42699.00    29.494  -2.249  0.000   0.000
+42700.00    29.578  -2.132  0.000   0.000
+42701.00    29.679  -2.038  0.000   0.000
+42702.00    29.671  -1.92   0.000   0.000
+42703.00    29.538  -1.81   0.000   0.000
+42704.00    29.396  -1.786  0.000   0.000
+42705.00    29.319  -1.848  0.000   0.000
+42706.00    29.308  -1.903  0.000   0.000
+42707.00    29.393  -1.888  0.000   0.000
+42708.00    29.6    -1.846  0.000   0.000
+42709.00    29.863  -1.857  0.000   0.000
+42710.00    30.073  -1.929  0.000   0.000
+42711.00    30.229  -1.99   0.000   0.000
+42712.00    30.428  -1.982  0.000   0.000
+42713.00    30.714  -1.903  0.000   0.000
+42714.00    30.982  -1.764  0.000   0.000
+42715.00    31.066  -1.546  0.000   0.000
+42716.00    30.926  -1.273  0.000   0.000
+42717.00    30.755  -1.077  0.000   0.000
+42718.00    30.838  -1.097  0.000   0.000
+42719.00    31.237  -1.281  0.000   0.000
+42720.00    31.649  -1.381  0.000   0.000
+42721.00    31.733  -1.225  0.000   0.000
+42722.00    31.56   -0.937  0.000   0.000
+42723.00    31.549  -0.794  0.000   0.000
+42724.00    31.932  -0.909  0.000   0.000
+42725.00    32.475  -1.133  0.000   0.000
+42726.00    32.824  -1.274  0.000   0.000
+42727.00    32.93   -1.283  0.000   0.000
+42728.00    32.958  -1.22   0.000   0.000
+42729.00    32.967  -1.125  0.000   0.000
+42730.00    32.886  -1.006  0.000   0.000
+42731.00    32.735  -0.89   0.000   0.000
+42732.00    32.641  -0.802  0.000   0.000
+42733.00    32.635  -0.723  0.000   0.000
+42734.00    32.626  -0.618  0.000   0.000
+42735.00    32.596  -0.512  0.000   0.000
+42736.00    32.67   -0.476  0.000   0.000
+42737.00    32.934  -0.54   0.000   0.000
+42738.00    33.292  -0.65   0.000   0.000
+42739.00    33.569  -0.722  0.000   0.000
+42740.00    33.697  -0.709  0.000   0.000
+42741.00    33.739  -0.613  0.000   0.000
+42742.00    33.773  -0.438  0.000   0.000
+42743.00    33.791  -0.186  0.000   0.000
+42744.00    33.735  0.112   0.000   0.000
+42745.00    33.609  0.348   0.000   0.000
+42746.00    33.523  0.389   0.000   0.000
+42747.00    33.583  0.209   0.000   0.000
+42748.00    33.763  -0.037  0.000   0.000
+42749.00    33.946  -0.121  0.000   0.000
+42750.00    34.104  0.028   0.000   0.000
+42751.00    34.334  0.264   0.000   0.000
+42752.00    34.688  0.38    0.000   0.000
+42753.00    35.044  0.309   0.000   0.000
+42754.00    35.233  0.144   0.000   0.000
+42755.00    35.22   0.012   0.000   0.000
+42756.00    35.09   -0.023  0.000   0.000
+42757.00    34.915  0.034   0.000   0.000
+42758.00    34.726  0.128   0.000   0.000
+42759.00    34.587  0.196   0.000   0.000
+42760.00    34.567  0.232   0.000   0.000
+42761.00    34.63   0.288   0.000   0.000
+42762.00    34.658  0.392   0.000   0.000
+42763.00    34.618  0.466   0.000   0.000
+42764.00    34.63   0.399   0.000   0.000
+42765.00    34.823  0.196   0.000   0.000
+42766.00    35.16   0.004   0.000   0.000
+42767.00    35.443  -0.031  0.000   0.000
+42768.00    35.502  0.108   0.000   0.000
+42769.00    35.34   0.328   0.000   0.000
+42770.00    35.106  0.535   0.000   0.000
+42771.00    34.943  0.706   0.000   0.000
+42772.00    34.869  0.856   0.000   0.000
+42773.00    34.796  0.972   0.000   0.000
+42774.00    34.646  0.995   0.000   0.000
+42775.00    34.452  0.864   0.000   0.000
+42776.00    34.34   0.618   0.000   0.000
+42777.00    34.425  0.421   0.000   0.000
+42778.00    34.708  0.435   0.000   0.000
+42779.00    35.073  0.657   0.000   0.000
+42780.00    35.373  0.909   0.000   0.000
+42781.00    35.531  1.005   0.000   0.000
+42782.00    35.547  0.908   0.000   0.000
+42783.00    35.439  0.728   0.000   0.000
+42784.00    35.221  0.594   0.000   0.000
+42785.00    34.957  0.551   0.000   0.000
+42786.00    34.765  0.54    0.000   0.000
+42787.00    34.716  0.476   0.000   0.000
+42788.00    34.767  0.353   0.000   0.000
+42789.00    34.811  0.267   0.000   0.000
+42790.00    34.794  0.300   0.000   0.000
+42791.00    34.754  0.377   0.000   0.000
+42792.00    34.769  0.325   0.000   0.000
+42793.00    34.906  0.089   0.000   0.000
+42794.00    35.17   -0.155  0.000   0.000
+42795.00    35.454  -0.171  0.000   0.000
+42796.00    35.579  0.086   0.000   0.000
+42797.00    35.44   0.431   0.000   0.000
+42798.00    35.124  0.646   0.000   0.000
+42799.00    34.836  0.665   0.000   0.000
+42800.00    34.694  0.568   0.000   0.000
+42801.00    34.641  0.454   0.000   0.000
+42802.00    34.536  0.352   0.000   0.000
+42803.00    34.323  0.228   0.000   0.000
+42804.00    34.108  0.06    0.000   0.000
+42805.00    34.068  -0.096  0.000   0.000
+42806.00    34.263  -0.133  0.000   0.000
+42807.00    34.553  -0.01   0.000   0.000
+42808.00    34.735  0.192   0.000   0.000
+42809.00    34.75   0.323   0.000   0.000
+42810.00    34.685  0.294   0.000   0.000
+42811.00    34.593  0.135   0.000   0.000
+42812.00    34.446  -0.061  0.000   0.000
+42813.00    34.274  -0.229  0.000   0.000
+42814.00    34.208  -0.383  0.000   0.000
+42815.00    34.293  -0.59   0.000   0.000
+42816.00    34.38   -0.858  0.000   0.000
+42817.00    34.325  -1.072  0.000   0.000
+42818.00    34.19   -1.078  0.000   0.000
+42819.00    34.139  -0.896  0.000   0.000
+42820.00    34.206  -0.757  0.000   0.000
+42821.00    34.312  -0.86   0.000   0.000
+42822.00    34.448  -1.114  0.000   0.000
+42823.00    34.66   -1.217  0.000   0.000
+42824.00    34.884  -1.014  0.000   0.000
+42825.00    34.957  -0.678  0.000   0.000
+42826.00    34.822  -0.5    0.000   0.000
+42827.00    34.595  -0.593  0.000   0.000
+42828.00    34.424  -0.844  0.000   0.000
+42829.00    34.339  -1.102  0.000   0.000
+42830.00    34.283  -1.312  0.000   0.000
+42831.00    34.198  -1.485  0.000   0.000
+42832.00    34.084  -1.619  0.000   0.000
+42833.00    34.017  -1.698  0.000   0.000
+42834.00    34.082  -1.716  0.000   0.000
+42835.00    34.266  -1.682  0.000   0.000
+42836.00    34.445  -1.606  0.000   0.000
+42837.00    34.527  -1.516  0.000   0.000
+42838.00    34.541  -1.471  0.000   0.000
+42839.00    34.536  -1.539  0.000   0.000
+42840.00    34.508  -1.735  0.000   0.000
+42841.00    34.481  -2.002  0.000   0.000
+42842.00    34.561  -2.272  0.000   0.000
+42843.00    34.759  -2.538  0.000   0.000
+42844.00    34.88   -2.824  0.000   0.000
+42845.00    34.772  -3.058  0.000   0.000
+42846.00    34.585  -3.076  0.000   0.000
+42847.00    34.595  -2.822  0.000   0.000
+42848.00    34.818  -2.505  0.000   0.000
+42849.00    35.016  -2.426  0.000   0.000
+42850.00    35.059  -2.626  0.000   0.000
+42851.00    35.068  -2.83   0.000   0.000
+42852.00    35.167  -2.783  0.000   0.000
+42853.00    35.289  -2.563  0.000   0.000
+42854.00    35.306  -2.443  0.000   0.000
+42855.00    35.19   -2.552  0.000   0.000
+42856.00    35.006  -2.776  0.000   0.000
+42857.00    34.848  -2.98   0.000   0.000
+42858.00    34.805  -3.161  0.000   0.000
+42859.00    34.892  -3.358  0.000   0.000
+42860.00    34.984  -3.521  0.000   0.000
+42861.00    34.953  -3.577  0.000   0.000
+42862.00    34.861  -3.551  0.000   0.000
+42863.00    34.903  -3.524  0.000   0.000
+42864.00    35.128  -3.502  0.000   0.000
+42865.00    35.376  -3.418  0.000   0.000
+42866.00    35.485  -3.279  0.000   0.000
+42867.00    35.452  -3.219  0.000   0.000
+42868.00    35.37   -3.366  0.000   0.000
+42869.00    35.343  -3.687  0.000   0.000
+42870.00    35.454  -4.023  0.000   0.000
+42871.00    35.683  -4.271  0.000   0.000
+42872.00    35.842  -4.453  0.000   0.000
+42873.00    35.769  -4.601  0.000   0.000
+42874.00    35.592  -4.633  0.000   0.000
+42875.00    35.623  -4.456  0.000   0.000
+42876.00    35.957  -4.164  0.000   0.000
+42877.00    36.333  -3.998  0.000   0.000
+42878.00    36.47   -4.066  0.000   0.000
+42879.00    36.362  -4.2    0.000   0.000
+42880.00    36.184  -4.178  0.000   0.000
+42881.00    36.049  -4.022  0.000   0.000
+42882.00    35.947  -3.945  0.000   0.000
+42883.00    35.821  -4.045  0.000   0.000
+42884.00    35.634  -4.194  0.000   0.000
+42885.00    35.448  -4.264  0.000   0.000
+42886.00    35.437  -4.314  0.000   0.000
+42887.00    35.686  -4.457  0.000   0.000
+42888.00    35.98   -4.652  0.000   0.000
+42889.00    35.988  -4.762  0.000   0.000
+42890.00    35.7    -4.754  0.000   0.000
+42891.00    35.482  -4.722  0.000   0.000
+42892.00    35.596  -4.7    0.000   0.000
+42893.00    35.865  -4.608  0.000   0.000
+42894.00    35.938  -4.418  0.000   0.000
+42895.00    35.729  -4.275  0.000   0.000
+42896.00    35.441  -4.356  0.000   0.000
+42897.00    35.289  -4.659  0.000   0.000
+42898.00    35.342  -4.994  0.000   0.000
+42899.00    35.544  -5.191  0.000   0.000
+42900.00    35.744  -5.254  0.000   0.000
+42901.00    35.771  -5.278  0.000   0.000
+42902.00    35.618  -5.294  0.000   0.000
+42903.00    35.509  -5.242  0.000   0.000
+42904.00    35.66   -5.106  0.000   0.000
+42905.00    36.018  -4.963  0.000   0.000
+42906.00    36.316  -4.873  0.000   0.000
+42907.00    36.34   -4.773  0.000   0.000
+42908.00    36.081  -4.577  0.000   0.000
+42909.00    35.686  -4.353  0.000   0.000
+42910.00    35.326  -4.278  0.000   0.000
+42911.00    35.081  -4.407  0.000   0.000
+42912.00    34.92   -4.573  0.000   0.000
+42913.00    34.829  -4.601  0.000   0.000
+42914.00    34.921  -4.531  0.000   0.000
+42915.00    35.272  -4.538  0.000   0.000
+42916.00    35.653  -4.68   0.000   0.000
+42917.00    35.662  -4.847  0.000   0.000
+42918.00    35.218  -4.94   0.000   0.000
+42919.00    34.722  -4.973  0.000   0.000
+42920.00    34.569  -4.973  0.000   0.000
+42921.00    34.662  -4.898  0.000   0.000
+42922.00    34.604  -4.727  0.000   0.000
+42923.00    34.243  -4.571  0.000   0.000
+42924.00    33.798  -4.578  0.000   0.000
+42925.00    33.522  -4.764  0.000   0.000
+42926.00    33.468  -4.989  0.000   0.000
+42927.00    33.572  -5.113  0.000   0.000
+42928.00    33.756  -5.119  0.000   0.000
+42929.00    33.886  -5.076  0.000   0.000
+42930.00    33.816  -5.034  0.000   0.000
+42931.00    33.554  -4.99   0.000   0.000
+42932.00    33.306  -4.919  0.000   0.000
+42933.00    33.274  -4.811  0.000   0.000
+42934.00    33.439  -4.65   0.000   0.000
+42935.00    33.58   -4.407  0.000   0.000
+42936.00    33.474  -4.092  0.000   0.000
+42937.00    33.081  -3.817  0.000   0.000
+42938.00    32.557  -3.744  0.000   0.000
+42939.00    32.112  -3.916  0.000   0.000
+42940.00    31.856  -4.169  0.000   0.000
+42941.00    31.804  -4.279  0.000   0.000
+42942.00    31.968  -4.188  0.000   0.000
+42943.00    32.315  -4.048  0.000   0.000
+42944.00    32.631  -4.035  0.000   0.000
+42945.00    32.594  -4.168  0.000   0.000
+42946.00    32.118  -4.349  0.000   0.000
+42947.00    31.502  -4.488  0.000   0.000
+42948.00    31.108  -4.546  0.000   0.000
+42949.00    30.959  -4.508  0.000   0.000
+42950.00    30.791  -4.394  0.000   0.000
+42951.00    30.44   -4.282  0.000   0.000
+42952.00    30.009  -4.253  0.000   0.000
+42953.00    29.662  -4.305  0.000   0.000
+42954.00    29.449  -4.373  0.000   0.000
+42955.00    29.376  -4.417  0.000   0.000
+42956.00    29.465  -4.443  0.000   0.000
+42957.00    29.664  -4.447  0.000   0.000
+42958.00    29.768  -4.392  0.000   0.000
+42959.00    29.579  -4.262  0.000   0.000
+42960.00    29.122  -4.1    0.000   0.000
+42961.00    28.647  -3.961  0.000   0.000
+42962.00    28.398  -3.85   0.000   0.000
+42963.00    28.401  -3.727  0.000   0.000
+42964.00    28.46   -3.574  0.000   0.000
+42965.00    28.341  -3.441  0.000   0.000
+42966.00    27.962  -3.432  0.000   0.000
+42967.00    27.439  -3.606  0.000   0.000
+42968.00    26.996  -3.885  0.000   0.000
+42969.00    26.81   -4.08   0.000   0.000
+42970.00    26.92   -4.053  0.000   0.000
+42971.00    27.202  -3.857  0.000   0.000
+42972.00    27.424  -3.682  0.000   0.000
+42973.00    27.379  -3.672  0.000   0.000
+42974.00    27.028  -3.813  0.000   0.000
+42975.00    26.525  -3.987  0.000   0.000
+42976.00    26.082  -4.096  0.000   0.000
+42977.00    25.8    -4.114  0.000   0.000
+42978.00    25.637  -4.084  0.000   0.000
+42979.00    25.48   -4.067  0.000   0.000
+42980.00    25.243  -4.085  0.000   0.000
+42981.00    24.912  -4.097  0.000   0.000
+42982.00    24.574  -4.063  0.000   0.000
+42983.00    24.377  -4.02   0.000   0.000
+42984.00    24.427  -4.043  0.000   0.000
+42985.00    24.679  -4.122  0.000   0.000
+42986.00    24.928  -4.128  0.000   0.000
+42987.00    24.933  -3.959  0.000   0.000
+42988.00    24.587  -3.672  0.000   0.000
+42989.00    24.008  -3.435  0.000   0.000
+42990.00    23.474  -3.362  0.000   0.000
+42991.00    23.222  -3.427  0.000   0.000
+42992.00    23.278  -3.528  0.000   0.000
+42993.00    23.444  -3.601  0.000   0.000
+42994.00    23.466  -3.664  0.000   0.000
+42995.00    23.237  -3.774  0.000   0.000
+42996.00    22.881  -3.946  0.000   0.000
+42997.00    22.645  -4.097  0.000   0.000
+42998.00    22.668  -4.107  0.000   0.000
+42999.00    22.859  -3.942  0.000   0.000
+43000.00    23.000  -3.703  0.000   0.000
+43001.00    22.955  -3.54   0.000   0.000
+43002.00    22.739  -3.523  0.000   0.000
+43003.00    22.425  -3.612  0.000   0.000
+43004.00    22.079  -3.732  0.000   0.000
+43005.00    21.816  -3.839  0.000   0.000
+43006.00    21.756  -3.934  0.000   0.000
+43007.00    21.858  -4.04   0.000   0.000
+43008.00    21.88   -4.15   0.000   0.000
+43009.00    21.641  -4.205  0.000   0.000
+43010.00    21.274  -4.142  0.000   0.000
+43011.00    21.091  -4.001  0.000   0.000
+43012.00    21.229  -3.918  0.000   0.000
+43013.00    21.531  -3.972  0.000   0.000
+43014.00    21.749  -4.05   0.000   0.000
+43015.00    21.756  -3.96   0.000   0.000
+43016.00    21.547  -3.674  0.000   0.000
+43017.00    21.178  -3.375  0.000   0.000
+43018.00    20.757  -3.256  0.000   0.000
+43019.00    20.435  -3.331  0.000   0.000
+43020.00    20.321  -3.468  0.000   0.000
+43021.00    20.414  -3.565  0.000   0.000
+43022.00    20.621  -3.626  0.000   0.000
+43023.00    20.817  -3.692  0.000   0.000
+43024.00    20.93   -3.767  0.000   0.000
+43025.00    20.991  -3.811  0.000   0.000
+43026.00    21.076  -3.777  0.000   0.000
+43027.00    21.182  -3.653  0.000   0.000
+43028.00    21.213  -3.465  0.000   0.000
+43029.00    21.109  -3.267  0.000   0.000
+43030.00    20.922  -3.125  0.000   0.000
+43031.00    20.716  -3.095  0.000   0.000
+43032.00    20.512  -3.195  0.000   0.000
+43033.00    20.385  -3.388  0.000   0.000
+43034.00    20.482  -3.603  0.000   0.000
+43035.00    20.795  -3.791  0.000   0.000
+43036.00    21.035  -3.944  0.000   0.000
+43037.00    20.94   -4.032  0.000   0.000
+43038.00    20.654  -3.981  0.000   0.000
+43039.00    20.582  -3.778  0.000   0.000
+43040.00    20.877  -3.559  0.000   0.000
+43041.00    21.259  -3.495  0.000   0.000
+43042.00    21.396  -3.579  0.000   0.000
+43043.00    21.27   -3.611  0.000   0.000
+43044.00    21.096  -3.456  0.000   0.000
+43045.00    21.034  -3.213  0.000   0.000
+43046.00    21.062  -3.065  0.000   0.000
+43047.00    21.047  -3.041  0.000   0.000
+43048.00    20.891  -3.023  0.000   0.000
+43049.00    20.665  -2.964  0.000   0.000
+43050.00    20.606  -2.958  0.000   0.000
+43051.00    20.896  -3.072  0.000   0.000
+43052.00    21.436  -3.219  0.000   0.000
+43053.00    21.93   -3.253  0.000   0.000
+43054.00    22.19   -3.15   0.000   0.000
+43055.00    22.245  -2.998  0.000   0.000
+43056.00    22.189  -2.862  0.000   0.000
+43057.00    22.062  -2.722  0.000   0.000
+43058.00    21.9    -2.563  0.000   0.000
+43059.00    21.769  -2.455  0.000   0.000
+43060.00    21.712  -2.49   0.000   0.000
+43061.00    21.765  -2.662  0.000   0.000
+43062.00    21.997  -2.862  0.000   0.000
+43063.00    22.391  -2.999  0.000   0.000
+43064.00    22.727  -3.081  0.000   0.000
+43065.00    22.777  -3.141  0.000   0.000
+43066.00    22.64   -3.124  0.000   0.000
+43067.00    22.677  -2.955  0.000   0.000
+43068.00    23.05   -2.691  0.000   0.000
+43069.00    23.493  -2.506  0.000   0.000
+43070.00    23.65   -2.486  0.000   0.000
+43071.00    23.501  -2.509  0.000   0.000
+43072.00    23.339  -2.429  0.000   0.000
+43073.00    23.443  -2.279  0.000   0.000
+43074.00    23.824  -2.196  0.000   0.000
+43075.00    24.216  -2.181  0.000   0.000
+43076.00    24.282  -2.095  0.000   0.000
+43077.00    23.954  -1.914  0.000   0.000
+43078.00    23.6    -1.829  0.000   0.000
+43079.00    23.695  -1.992  0.000   0.000
+43080.00    24.277  -2.275  0.000   0.000
+43081.00    24.901  -2.404  0.000   0.000
+43082.00    25.164  -2.28   0.000   0.000
+43083.00    25.097  -2.055  0.000   0.000
+43084.00    24.967  -1.893  0.000   0.000
+43085.00    24.889  -1.793  0.000   0.000
+43086.00    24.821  -1.676  0.000   0.000
+43087.00    24.763  -1.551  0.000   0.000
+43088.00    24.785  -1.504  0.000   0.000
+43089.00    24.913  -1.554  0.000   0.000
+43090.00    25.125  -1.616  0.000   0.000
+43091.00    25.391  -1.62   0.000   0.000
+43092.00    25.64   -1.606  0.000   0.000
+43093.00    25.763  -1.642  0.000   0.000
+43094.00    25.77   -1.696  0.000   0.000
+43095.00    25.843  -1.655  0.000   0.000
+43096.00    26.113  -1.472  0.000   0.000
+43097.00    26.458  -1.241  0.000   0.000
+43098.00    26.637  -1.063  0.000   0.000
+43099.00    26.571  -0.922  0.000   0.000
+43100.00    26.419  -0.764  0.000   0.000
+43101.00    26.418  -0.646  0.000   0.000
+43102.00    26.677  -0.685  0.000   0.000
+43103.00    27.07   -0.844  0.000   0.000
+43104.00    27.292  -0.914  0.000   0.000
+43105.00    27.163  -0.789  0.000   0.000
+43106.00    26.907  -0.636  0.000   0.000
+43107.00    26.96   -0.697  0.000   0.000
+43108.00    27.42   -0.954  0.000   0.000
+43109.00    27.886  -1.144  0.000   0.000
+43110.00    27.954  -1.089  0.000   0.000
+43111.00    27.696  -0.881  0.000   0.000
+43112.00    27.472  -0.71   0.000   0.000
+43113.00    27.432  -0.632  0.000   0.000
+43114.00    27.453  -0.578  0.000   0.000
+43115.00    27.45   -0.507  0.000   0.000
+43116.00    27.491  -0.453  0.000   0.000
+43117.00    27.602  -0.428  0.000   0.000
+43118.00    27.705  -0.394  0.000   0.000
+43119.00    27.768  -0.342  0.000   0.000
+43120.00    27.862  -0.33   0.000   0.000
+43121.00    28.02   -0.41   0.000   0.000
+43122.00    28.177  -0.537  0.000   0.000
+43123.00    28.281  -0.597  0.000   0.000
+43124.00    28.363  -0.511  0.000   0.000
+43125.00    28.457  -0.303  0.000   0.000
+43126.00    28.527  -0.04   0.000   0.000
+43127.00    28.505  0.238   0.000   0.000
+43128.00    28.376  0.488   0.000   0.000
+43129.00    28.2    0.605   0.000   0.000
+43130.00    28.088  0.475   0.000   0.000
+43131.00    28.099  0.143   0.000   0.000
+43132.00    28.163  -0.144  0.000   0.000
+43133.00    28.178  -0.162  0.000   0.000
+43134.00    28.196  0.045   0.000   0.000
+43135.00    28.399  0.22    0.000   0.000
+43136.00    28.792  0.197   0.000   0.000
+43137.00    29.086  0.057   0.000   0.000
+43138.00    29.013  -0.023  0.000   0.000
+43139.00    28.672  0.007   0.000   0.000
+43140.00    28.384  0.065   0.000   0.000
+43141.00    28.294  0.083   0.000   0.000
+43142.00    28.296  0.066   0.000   0.000
+43143.00    28.308  0.04    0.000   0.000
+43144.00    28.381  0.022   0.000   0.000
+43145.00    28.52   0.028   0.000   0.000
+43146.00    28.608  0.065   0.000   0.000
+43147.00    28.591  0.088   0.000   0.000
+43148.00    28.606  0.025   0.000   0.000
+43149.00    28.788  -0.122  0.000   0.000
+43150.00    29.069  -0.26   0.000   0.000
+43151.00    29.249  -0.289  0.000   0.000
+43152.00    29.23   -0.188  0.000   0.000
+43153.00    29.088  -0.007  0.000   0.000
+43154.00    28.954  0.201   0.000   0.000
+43155.00    28.867  0.41    0.000   0.000
+43156.00    28.767  0.582   0.000   0.000
+43157.00    28.577  0.633   0.000   0.000
+43158.00    28.301  0.473   0.000   0.000
+43159.00    28.032  0.121   0.000   0.000
+43160.00    27.867  -0.236  0.000   0.000
+43161.00    27.845  -0.354  0.000   0.000
+43162.00    27.959  -0.157  0.000   0.000
+43163.00    28.187  0.173   0.000   0.000
+43164.00    28.445  0.361   0.000   0.000
+43165.00    28.582  0.293   0.000   0.000
+43166.00    28.498  0.069   0.000   0.000
+43167.00    28.252  -0.145  0.000   0.000
+43168.00    27.995  -0.276  0.000   0.000
+43169.00    27.81   -0.353  0.000   0.000
+43170.00    27.702  -0.435  0.000   0.000
+43171.00    27.693  -0.542  0.000   0.000
+43172.00    27.829  -0.641  0.000   0.000
+43173.00    28.064  -0.672  0.000   0.000
+43174.00    28.252  -0.625  0.000   0.000
+43175.00    28.313  -0.591  0.000   0.000
+43176.00    28.338  -0.679  0.000   0.000
+43177.00    28.479  -0.874  0.000   0.000
+43178.00    28.75   -1.022  0.000   0.000
+43179.00    28.993  -0.992  0.000   0.000
+43180.00    29.049  -0.811  0.000   0.000
+43181.00    28.902  -0.629  0.000   0.000
+43182.00    28.679  -0.551  0.000   0.000
+43183.00    28.516  -0.575  0.000   0.000
+43184.00    28.433  -0.641  0.000   0.000
+43185.00    28.35   -0.73   0.000   0.000
+43186.00    28.185  -0.876  0.000   0.000
+43187.00    27.964  -1.107  0.000   0.000
+43188.00    27.807  -1.365  0.000   0.000
+43189.00    27.82   -1.502  0.000   0.000
+43190.00    27.986  -1.407  0.000   0.000
+43191.00    28.176  -1.146  0.000   0.000
+43192.00    28.27   -0.943  0.000   0.000
+43193.00    28.258  -0.986  0.000   0.000
+43194.00    28.206  -1.26   0.000   0.000
+43195.00    28.145  -1.593  0.000   0.000
+43196.00    28.031  -1.837  0.000   0.000
+43197.00    27.853  -1.978  0.000   0.000
+43198.00    27.705  -2.092  0.000   0.000
+43199.00    27.713  -2.234  0.000   0.000
+43200.00    27.903  -2.371  0.000   0.000
+43201.00    28.188  -2.407  0.000   0.000
+43202.00    28.465  -2.296  0.000   0.000
+43203.00    28.675  -2.144  0.000   0.000
+43204.00    28.796  -2.137  0.000   0.000
+43205.00    28.857  -2.334  0.000   0.000
+43206.00    28.937  -2.567  0.000   0.000
+43207.00    29.093  -2.604  0.000   0.000
+43208.00    29.261  -2.412  0.000   0.000
+43209.00    29.307  -2.195  0.000   0.000
+43210.00    29.187  -2.172  0.000   0.000
+43211.00    29.005  -2.365  0.000   0.000
+43212.00    28.887  -2.63   0.000   0.000
+43213.00    28.848  -2.826  0.000   0.000
+43214.00    28.811  -2.931  0.000   0.000
+43215.00    28.743  -3.005  0.000   0.000
+43216.00    28.716  -3.095  0.000   0.000
+43217.00    28.835  -3.172  0.000   0.000
+43218.00    29.092  -3.168  0.000   0.000
+43219.00    29.335  -3.069  0.000   0.000
+43220.00    29.406  -2.961  0.000   0.000
+43221.00    29.323  -2.962  0.000   0.000
+43222.00    29.246  -3.111  0.000   0.000
+43223.00    29.252  -3.341  0.000   0.000
+43224.00    29.254  -3.559  0.000   0.000
+43225.00    29.177  -3.724  0.000   0.000
+43226.00    29.111  -3.862  0.000   0.000
+43227.00    29.18   -4.007  0.000   0.000
+43228.00    29.347  -4.144  0.000   0.000
+43229.00    29.515  -4.188  0.000   0.000
+43230.00    29.708  -4.053  0.000   0.000
+43231.00    30.002  -3.795  0.000   0.000
+43232.00    30.295  -3.633  0.000   0.000
+43233.00    30.373  -3.746  0.000   0.000
+43234.00    30.223  -4.042  0.000   0.000
+43235.00    30.088  -4.219  0.000   0.000
+43236.00    30.143  -4.103  0.000   0.000
+43237.00    30.266  -3.853  0.000   0.000
+43238.00    30.238  -3.769  0.000   0.000
+43239.00    30.031  -3.961  0.000   0.000
+43240.00    29.805  -4.268  0.000   0.000
+43241.00    29.696  -4.487  0.000   0.000
+43242.00    29.703  -4.562  0.000   0.000
+43243.00    29.75   -4.563  0.000   0.000
+43244.00    29.79   -4.552  0.000   0.000
+43245.00    29.848  -4.544  0.000   0.000
+43246.00    29.978  -4.535  0.000   0.000
+43247.00    30.16   -4.521  0.000   0.000
+43248.00    30.269  -4.491  0.000   0.000
+43249.00    30.213  -4.44   0.000   0.000
+43250.00    30.054  -4.4    0.000   0.000
+43251.00    29.923  -4.434  0.000   0.000
+43252.00    29.86   -4.576  0.000   0.000
+43253.00    29.846  -4.787  0.000   0.000
+43254.00    29.908  -4.982  0.000   0.000
+43255.00    30.055  -5.12   0.000   0.000
+43256.00    30.16   -5.222  0.000   0.000
+43257.00    30.111  -5.286  0.000   0.000
+43258.00    30.061  -5.235  0.000   0.000
+43259.00    30.276  -5.026  0.000   0.000
+43260.00    30.714  -4.79   0.000   0.000
+43261.00    30.982  -4.741  0.000   0.000
+43262.00    30.823  -4.916  0.000   0.000
+43263.00    30.438  -5.08   0.000   0.000
+43264.00    30.183  -5.000  0.000   0.000
+43265.00    30.125  -4.748  0.000   0.000
+43266.00    30.058  -4.613  0.000   0.000
+43267.00    29.841  -4.743  0.000   0.000
+43268.00    29.561  -4.998  0.000   0.000
+43269.00    29.403  -5.171  0.000   0.000
+43270.00    29.463  -5.225  0.000   0.000
+43271.00    29.663  -5.242  0.000   0.000
+43272.00    29.784  -5.249  0.000   0.000
+43273.00    29.666  -5.211  0.000   0.000
+43274.00    29.409  -5.147  0.000   0.000
+43275.00    29.264  -5.124  0.000   0.000
+43276.00    29.312  -5.141  0.000   0.000
+43277.00    29.349  -5.11   0.000   0.000
+43278.00    29.175  -4.999  0.000   0.000
+43279.00    28.849  -4.918  0.000   0.000
+43280.00    28.587  -5.003  0.000   0.000
+43281.00    28.527  -5.236  0.000   0.000
+43282.00    28.662  -5.456  0.000   0.000
+43283.00    28.875  -5.542  0.000   0.000
+43284.00    28.964  -5.539  0.000   0.000
+43285.00    28.791  -5.558  0.000   0.000
+43286.00    28.503  -5.599  0.000   0.000
+43287.00    28.458  -5.552  0.000   0.000
+43288.00    28.791  -5.382  0.000   0.000
+43289.00    29.185  -5.204  0.000   0.000
+43290.00    29.219  -5.118  0.000   0.000
+43291.00    28.839  -5.056  0.000   0.000
+43292.00    28.339  -4.892  0.000   0.000
+43293.00    27.967  -4.673  0.000   0.000
+43294.00    27.728  -4.602  0.000   0.000
+43295.00    27.514  -4.759  0.000   0.000
+43296.00    27.293  -4.979  0.000   0.000
+43297.00    27.156  -5.066  0.000   0.000
+43298.00    27.237  -5.035  0.000   0.000
+43299.00    27.52   -5.035  0.000   0.000
+43300.00    27.719  -5.097  0.000   0.000
+43301.00    27.497  -5.117  0.000   0.000
+43302.00    26.888  -5.058  0.000   0.000
+43303.00    26.346  -5.015  0.000   0.000
+43304.00    26.217  -5.058  0.000   0.000
+43305.00    26.322  -5.108  0.000   0.000
+43306.00    26.229  -5.068  0.000   0.000
+43307.00    25.824  -4.992  0.000   0.000
+43308.00    25.389  -5.022  0.000   0.000
+43309.00    25.207  -5.179  0.000   0.000
+43310.00    25.294  -5.32   0.000   0.000
+43311.00    25.485  -5.314  0.000   0.000
+43312.00    25.593  -5.203  0.000   0.000
+43313.00    25.475  -5.137  0.000   0.000
+43314.00    25.145  -5.184  0.000   0.000
+43315.00    24.834  -5.257  0.000   0.000
+43316.00    24.795  -5.233  0.000   0.000
+43317.00    25.004  -5.082  0.000   0.000
+43318.00    25.155  -4.86   0.000   0.000
+43319.00    24.986  -4.612  0.000   0.000
+43320.00    24.508  -4.373  0.000   0.000
+43321.00    23.933  -4.239  0.000   0.000
+43322.00    23.461  -4.329  0.000   0.000
+43323.00    23.157  -4.613  0.000   0.000
+43324.00    22.968  -4.869  0.000   0.000
+43325.00    22.854  -4.89   0.000   0.000
+43326.00    22.878  -4.726  0.000   0.000
+43327.00    23.087  -4.606  0.000   0.000
+43328.00    23.282  -4.652  0.000   0.000
+43329.00    23.101  -4.759  0.000   0.000
+43330.00    22.459  -4.794  0.000   0.000
+43331.00    21.758  -4.779  0.000   0.000
+43332.00    21.455  -4.809  0.000   0.000
+43333.00    21.511  -4.884  0.000   0.000
+43334.00    21.501  -4.925  0.000   0.000
+43335.00    21.196  -4.906  0.000   0.000
+43336.00    20.794  -4.894  0.000   0.000
+43337.00    20.574  -4.922  0.000   0.000
+43338.00    20.569  -4.938  0.000   0.000
+43339.00    20.66   -4.885  0.000   0.000
+43340.00    20.764  -4.786  0.000   0.000
+43341.00    20.81   -4.717  0.000   0.000
+43342.00    20.686  -4.72   0.000   0.000
+43343.00    20.37   -4.765  0.000   0.000
+43344.00    20.04   -4.791  0.000   0.000
+43345.00    19.913  -4.744  0.000   0.000
+43346.00    19.993  -4.607  0.000   0.000
+43347.00    20.061  -4.408  0.000   0.000
+43348.00    19.897  -4.232  0.000   0.000
+43349.00    19.477  -4.202  0.000   0.000
+43350.00    18.967  -4.397  0.000   0.000
+43351.00    18.552  -4.749  0.000   0.000
+43352.00    18.297  -5.033  0.000   0.000
+43353.00    18.17   -5.041  0.000   0.000
+43354.00    18.158  -4.792  0.000   0.000
+43355.00    18.28   -4.525  0.000   0.000
+43356.00    18.439  -4.453  0.000   0.000
+43357.00    18.387  -4.562  0.000   0.000
+43358.00    17.984  -4.682  0.000   0.000
+43359.00    17.416  -4.714  0.000   0.000
+43360.00    17.021  -4.698  0.000   0.000
+43361.00    16.907  -4.707  0.000   0.000
+43362.00    16.893  -4.744  0.000   0.000
+43363.00    16.806  -4.77   0.000   0.000
+43364.00    16.673  -4.762  0.000   0.000
+43365.00    16.589  -4.724  0.000   0.000
+43366.00    16.55   -4.672  0.000   0.000
+43367.00    16.522  -4.641  0.000   0.000
+43368.00    16.551  -4.654  0.000   0.000
+43369.00    16.664  -4.681  0.000   0.000
+43370.00    16.737  -4.656  0.000   0.000
+43371.00    16.599  -4.555  0.000   0.000
+43372.00    16.261  -4.439  0.000   0.000
+43373.00    15.942  -4.372  0.000   0.000
+43374.00    15.845  -4.351  0.000   0.000
+43375.00    15.961  -4.328  0.000   0.000
+43376.00    16.094  -4.298  0.000   0.000
+43377.00    16.061  -4.324  0.000   0.000
+43378.00    15.837  -4.47   0.000   0.000
+43379.00    15.536  -4.713  0.000   0.000
+43380.00    15.302  -4.922  0.000   0.000
+43381.00    15.206  -4.939  0.000   0.000
+43382.00    15.24   -4.726  0.000   0.000
+43383.00    15.354  -4.423  0.000   0.000
+43384.00    15.465  -4.24   0.000   0.000
+43385.00    15.47   -4.258  0.000   0.000
+43386.00    15.298  -4.371  0.000   0.000
+43387.00    14.974  -4.433  0.000   0.000
+43388.00    14.625  -4.409  0.000   0.000
+43389.00    14.398  -4.377  0.000   0.000
+43390.00    14.379  -4.401  0.000   0.000
+43391.00    14.547  -4.468  0.000   0.000
+43392.00    14.777  -4.517  0.000   0.000
+43393.00    14.924  -4.507  0.000   0.000
+43394.00    14.926  -4.459  0.000   0.000
+43395.00    14.854  -4.448  0.000   0.000
+43396.00    14.824  -4.529  0.000   0.000
+43397.00    14.877  -4.641  0.000   0.000
+43398.00    14.937  -4.634  0.000   0.000
+43399.00    14.9    -4.427  0.000   0.000
+43400.00    14.738  -4.12   0.000   0.000
+43401.00    14.527  -3.911  0.000   0.000
+43402.00    14.387  -3.895  0.000   0.000
+43403.00    14.39   -3.997  0.000   0.000
+43404.00    14.505  -4.089  0.000   0.000
+43405.00    14.64   -4.125  0.000   0.000
+43406.00    14.717  -4.148  0.000   0.000
+43407.00    14.737  -4.204  0.000   0.000
+43408.00    14.764  -4.273  0.000   0.000
+43409.00    14.858  -4.277  0.000   0.000
+43410.00    15.015  -4.16   0.000   0.000
+43411.00    15.153  -3.956  0.000   0.000
+43412.00    15.196  -3.779  0.000   0.000
+43413.00    15.146  -3.714  0.000   0.000
+43414.00    15.07   -3.741  0.000   0.000
+43415.00    14.988  -3.771  0.000   0.000
+43416.00    14.877  -3.768  0.000   0.000
+43417.00    14.8    -3.768  0.000   0.000
+43418.00    14.924  -3.819  0.000   0.000
+43419.00    15.321  -3.911  0.000   0.000
+43420.00    15.803  -3.993  0.000   0.000
+43421.00    16.099  -4.018  0.000   0.000
+43422.00    16.159  -3.975  0.000   0.000
+43423.00    16.166  -3.913  0.000   0.000
+43424.00    16.242  -3.911  0.000   0.000
+43425.00    16.31   -3.978  0.000   0.000
+43426.00    16.275  -3.99   0.000   0.000
+43427.00    16.203  -3.803  0.000   0.000
+43428.00    16.224  -3.445  0.000   0.000
+43429.00    16.342  -3.139  0.000   0.000
+43430.00    16.45   -3.076  0.000   0.000
+43431.00    16.462  -3.218  0.000   0.000
+43432.00    16.392  -3.368  0.000   0.000
+43433.00    16.318  -3.396  0.000   0.000
+43434.00    16.332  -3.337  0.000   0.000
+43435.00    16.487  -3.282  0.000   0.000
+43436.00    16.752  -3.254  0.000   0.000
+43437.00    17.032  -3.211  0.000   0.000
+43438.00    17.238  -3.125  0.000   0.000
+43439.00    17.321  -3.018  0.000   0.000
+43440.00    17.276  -2.93   0.000   0.000
+43441.00    17.17   -2.864  0.000   0.000
+43442.00    17.123  -2.8    0.000   0.000
+43443.00    17.199  -2.729  0.000   0.000
+43444.00    17.342  -2.681  0.000   0.000
+43445.00    17.51   -2.686  0.000   0.000
+43446.00    17.78   -2.737  0.000   0.000
+43447.00    18.214  -2.798  0.000   0.000
+43448.00    18.658  -2.85   0.000   0.000
+43449.00    18.882  -2.875  0.000   0.000
+43450.00    18.912  -2.837  0.000   0.000
+43451.00    19.006  -2.712  0.000   0.000
+43452.00    19.255  -2.559  0.000   0.000
+43453.00    19.438  -2.478  0.000   0.000
+43454.00    19.362  -2.456  0.000   0.000
+43455.00    19.183  -2.354  0.000   0.000
+43456.00    19.208  -2.099  0.000   0.000
+43457.00    19.508  -1.837  0.000   0.000
+43458.00    19.863  -1.785  0.000   0.000
+43459.00    20.019  -1.953  0.000   0.000
+43460.00    19.895  -2.131  0.000   0.000
+43461.00    19.608  -2.148  0.000   0.000
+43462.00    19.395  -2.056  0.000   0.000
+43463.00    19.442  -1.988  0.000   0.000
+43464.00    19.708  -1.958  0.000   0.000
+43465.00    19.954  -1.884  0.000   0.000
+43466.00    20.005  -1.753  0.000   0.000
+43467.00    19.906  -1.659  0.000   0.000
+43468.00    19.796  -1.657  0.000   0.000
+43469.00    19.743  -1.679  0.000   0.000
+43470.00    19.756  -1.626  0.000   0.000
+43471.00    19.85   -1.493  0.000   0.000
+43472.00    20.022  -1.374  0.000   0.000
+43473.00    20.229  -1.331  0.000   0.000
+43474.00    20.458  -1.338  0.000   0.000
+43475.00    20.722  -1.348  0.000   0.000
+43476.00    20.952  -1.369  0.000   0.000
+43477.00    21.035  -1.426  0.000   0.000
+43478.00    21.023  -1.466  0.000   0.000
+43479.00    21.134  -1.387  0.000   0.000
+43480.00    21.426  -1.184  0.000   0.000
+43481.00    21.652  -0.985  0.000   0.000
+43482.00    21.575  -0.889  0.000   0.000
+43483.00    21.31   -0.833  0.000   0.000
+43484.00    21.178  -0.707  0.000   0.000
+43485.00    21.308  -0.569  0.000   0.000
+43486.00    21.537  -0.595  0.000   0.000
+43487.00    21.638  -0.809  0.000   0.000
+43488.00    21.523  -1.002  0.000   0.000
+43489.00    21.276  -0.988  0.000   0.000
+43490.00    21.109  -0.838  0.000   0.000
+43491.00    21.205  -0.746  0.000   0.000
+43492.00    21.494  -0.746  0.000   0.000
+43493.00    21.663  -0.703  0.000   0.000
+43494.00    21.518  -0.559  0.000   0.000
+43495.00    21.229  -0.443  0.000   0.000
+43496.00    21.094  -0.48   0.000   0.000
+43497.00    21.163  -0.61   0.000   0.000
+43498.00    21.256  -0.672  0.000   0.000
+43499.00    21.28   -0.607  0.000   0.000
+43500.00    21.309  -0.502  0.000   0.000
+43501.00    21.402  -0.441  0.000   0.000
+43502.00    21.527  -0.417  0.000   0.000
+43503.00    21.649  -0.399  0.000   0.000
+43504.00    21.769  -0.424  0.000   0.000
+43505.00    21.867  -0.535  0.000   0.000
+43506.00    21.936  -0.679  0.000   0.000
+43507.00    22.033  -0.718  0.000   0.000
+43508.00    22.183  -0.586  0.000   0.000
+43509.00    22.271  -0.376  0.000   0.000
+43510.00    22.16   -0.223  0.000   0.000
+43511.00    21.9    -0.148  0.000   0.000
+43512.00    21.668  -0.089  0.000   0.000
+43513.00    21.535  -0.063  0.000   0.000
+43514.00    21.412  -0.176  0.000   0.000
+43515.00    21.213  -0.431  0.000   0.000
+43516.00    20.96   -0.624  0.000   0.000
+43517.00    20.763  -0.565  0.000   0.000
+43518.00    20.769  -0.324  0.000   0.000
+43519.00    21.062  -0.155  0.000   0.000
+43520.00    21.495  -0.169  0.000   0.000
+43521.00    21.719  -0.232  0.000   0.000
+43522.00    21.535  -0.203  0.000   0.000
+43523.00    21.165  -0.136  0.000   0.000
+43524.00    20.984  -0.177  0.000   0.000
+43525.00    21.054  -0.342  0.000   0.000
+43526.00    21.131  -0.503  0.000   0.000
+43527.00    21.08   -0.569  0.000   0.000
+43528.00    21.041  -0.567  0.000   0.000
+43529.00    21.149  -0.552  0.000   0.000
+43530.00    21.333  -0.537  0.000   0.000
+43531.00    21.483  -0.528  0.000   0.000
+43532.00    21.623  -0.57   0.000   0.000
+43533.00    21.814  -0.698  0.000   0.000
+43534.00    22.007  -0.86   0.000   0.000
+43535.00    22.102  -0.947  0.000   0.000
+43536.00    22.073  -0.902  0.000   0.000
+43537.00    21.961  -0.776  0.000   0.000
+43538.00    21.805  -0.66   0.000   0.000
+43539.00    21.635  -0.596  0.000   0.000
+43540.00    21.479  -0.58   0.000   0.000
+43541.00    21.316  -0.635  0.000   0.000
+43542.00    21.088  -0.813  0.000   0.000
+43543.00    20.784  -1.087  0.000   0.000
+43544.00    20.482  -1.282  0.000   0.000
+43545.00    20.298  -1.222  0.000   0.000
+43546.00    20.338  -0.955  0.000   0.000
+43547.00    20.638  -0.739  0.000   0.000
+43548.00    21.06   -0.771  0.000   0.000
+43549.00    21.321  -0.984  0.000   0.000
+43550.00    21.242  -1.172  0.000   0.000
+43551.00    20.955  -1.244  0.000   0.000
+43552.00    20.74   -1.279  0.000   0.000
+43553.00    20.68   -1.371  0.000   0.000
+43554.00    20.642  -1.512  0.000   0.000
+43555.00    20.588  -1.643  0.000   0.000
+43556.00    20.682  -1.728  0.000   0.000
+43557.00    21.016  -1.762  0.000   0.000
+43558.00    21.422  -1.76   0.000   0.000
+43559.00    21.685  -1.766  0.000   0.000
+43560.00    21.815  -1.83   0.000   0.000
+43561.00    21.962  -1.949  0.000   0.000
+43562.00    22.154  -2.048  0.000   0.000
+43563.00    22.267  -2.064  0.000   0.000
+43564.00    22.224  -2.018  0.000   0.000
+43565.00    22.088  -1.983  0.000   0.000
+43566.00    21.968  -1.998  0.000   0.000
+43567.00    21.902  -2.045  0.000   0.000
+43568.00    21.862  -2.101  0.000   0.000
+43569.00    21.804  -2.186  0.000   0.000
+43570.00    21.717  -2.341  0.000   0.000
+43571.00    21.632  -2.554  0.000   0.000
+43572.00    21.597  -2.714  0.000   0.000
+43573.00    21.64   -2.692  0.000   0.000
+43574.00    21.757  -2.489  0.000   0.000
+43575.00    21.925  -2.292  0.000   0.000
+43576.00    22.1    -2.316  0.000   0.000
+43577.00    22.209  -2.585  0.000   0.000
+43578.00    22.202  -2.908  0.000   0.000
+43579.00    22.099  -3.088  0.000   0.000
+43580.00    21.959  -3.101  0.000   0.000
+43581.00    21.809  -3.069  0.000   0.000
+43582.00    21.67   -3.102  0.000   0.000
+43583.00    21.649  -3.207  0.000   0.000
+43584.00    21.885  -3.318  0.000   0.000
+43585.00    22.368  -3.368  0.000   0.000
+43586.00    22.875  -3.353  0.000   0.000
+43587.00    23.167  -3.344  0.000   0.000
+43588.00    23.209  -3.415  0.000   0.000
+43589.00    23.155  -3.539  0.000   0.000
+43590.00    23.148  -3.599  0.000   0.000
+43591.00    23.197  -3.52   0.000   0.000
+43592.00    23.236  -3.384  0.000   0.000
+43593.00    23.223  -3.352  0.000   0.000
+43594.00    23.173  -3.486  0.000   0.000
+43595.00    23.11   -3.699  0.000   0.000
+43596.00    23.037  -3.862  0.000   0.000
+43597.00    22.95   -3.926  0.000   0.000
+43598.00    22.876  -3.942  0.000   0.000
+43599.00    22.887  -3.972  0.000   0.000
+43600.00    23.052  -4.02   0.000   0.000
+43601.00    23.356  -4.021  0.000   0.000
+43602.00    23.669  -3.927  0.000   0.000
+43603.00    23.827  -3.797  0.000   0.000
+43604.00    23.771  -3.77   0.000   0.000
+43605.00    23.608  -3.924  0.000   0.000
+43606.00    23.502  -4.168  0.000   0.000
+43607.00    23.503  -4.332  0.000   0.000
+43608.00    23.508  -4.338  0.000   0.000
+43609.00    23.417  -4.271  0.000   0.000
+43610.00    23.29   -4.26   0.000   0.000
+43611.00    23.284  -4.351  0.000   0.000
+43612.00    23.476  -4.483  0.000   0.000
+43613.00    23.8    -4.564  0.000   0.000
+43614.00    24.131  -4.553  0.000   0.000
+43615.00    24.361  -4.511  0.000   0.000
+43616.00    24.408  -4.537  0.000   0.000
+43617.00    24.247  -4.649  0.000   0.000
+43618.00    23.983  -4.723  0.000   0.000
+43619.00    23.805  -4.626  0.000   0.000
+43620.00    23.798  -4.406  0.000   0.000
+43621.00    23.859  -4.285  0.000   0.000
+43622.00    23.832  -4.429  0.000   0.000
+43623.00    23.689  -4.757  0.000   0.000
+43624.00    23.51   -5.028  0.000   0.000
+43625.00    23.351  -5.074  0.000   0.000
+43626.00    23.208  -4.933  0.000   0.000
+43627.00    23.102  -4.758  0.000   0.000
+43628.00    23.124  -4.668  0.000   0.000
+43629.00    23.344  -4.669  0.000   0.000
+43630.00    23.682  -4.691  0.000   0.000
+43631.00    23.915  -4.678  0.000   0.000
+43632.00    23.857  -4.645  0.000   0.000
+43633.00    23.555  -4.642  0.000   0.000
+43634.00    23.26   -4.683  0.000   0.000
+43635.00    23.16   -4.736  0.000   0.000
+43636.00    23.206  -4.77   0.000   0.000
+43637.00    23.25   -4.8    0.000   0.000
+43638.00    23.266  -4.858  0.000   0.000
+43639.00    23.319  -4.958  0.000   0.000
+43640.00    23.388  -5.083  0.000   0.000
+43641.00    23.402  -5.189  0.000   0.000
+43642.00    23.423  -5.217  0.000   0.000
+43643.00    23.583  -5.156  0.000   0.000
+43644.00    23.796  -5.083  0.000   0.000
+43645.00    23.764  -5.088  0.000   0.000
+43646.00    23.364  -5.132  0.000   0.000
+43647.00    22.868  -5.063  0.000   0.000
+43648.00    22.612  -4.827  0.000   0.000
+43649.00    22.6    -4.609  0.000   0.000
+43650.00    22.571  -4.65   0.000   0.000
+43651.00    22.389  -4.954  0.000   0.000
+43652.00    22.164  -5.251  0.000   0.000
+43653.00    22.028  -5.291  0.000   0.000
+43654.00    21.956  -5.079  0.000   0.000
+43655.00    21.84   -4.815  0.000   0.000
+43656.00    21.66   -4.666  0.000   0.000
+43657.00    21.518  -4.663  0.000   0.000
+43658.00    21.532  -4.75   0.000   0.000
+43659.00    21.675  -4.858  0.000   0.000
+43660.00    21.748  -4.924  0.000   0.000
+43661.00    21.568  -4.905  0.000   0.000
+43662.00    21.184  -4.824  0.000   0.000
+43663.00    20.832  -4.767  0.000   0.000
+43664.00    20.687  -4.81   0.000   0.000
+43665.00    20.735  -4.938  0.000   0.000
+43666.00    20.881  -5.055  0.000   0.000
+43667.00    21.029  -5.1    0.000   0.000
+43668.00    21.041  -5.111  0.000   0.000
+43669.00    20.838  -5.161  0.000   0.000
+43670.00    20.593  -5.23   0.000   0.000
+43671.00    20.612  -5.22   0.000   0.000
+43672.00    20.898  -5.104  0.000   0.000
+43673.00    21.022  -4.984  0.000   0.000
+43674.00    20.623  -4.936  0.000   0.000
+43675.00    19.883  -4.882  0.000   0.000
+43676.00    19.302  -4.713  0.000   0.000
+43677.00    19.093  -4.503  0.000   0.000
+43678.00    19.043  -4.466  0.000   0.000
+43679.00    18.901  -4.663  0.000   0.000
+43680.00    18.682  -4.883  0.000   0.000
+43681.00    18.545  -4.892  0.000   0.000
+43682.00    18.544  -4.698  0.000   0.000
+43683.00    18.553  -4.502  0.000   0.000
+43684.00    18.388  -4.428  0.000   0.000
+43685.00    17.998  -4.445  0.000   0.000
+43686.00    17.58   -4.503  0.000   0.000
+43687.00    17.42   -4.616  0.000   0.000
+43688.00    17.548  -4.775  0.000   0.000
+43689.00    17.649  -4.884  0.000   0.000
+43690.00    17.42   -4.868  0.000   0.000
+43691.00    16.936  -4.798  0.000   0.000
+43692.00    16.544  -4.81   0.000   0.000
+43693.00    16.467  -4.924  0.000   0.000
+43694.00    16.642  -5.004  0.000   0.000
+43695.00    16.858  -4.94   0.000   0.000
+43696.00    16.909  -4.799  0.000   0.000
+43697.00    16.701  -4.747  0.000   0.000
+43698.00    16.367  -4.838  0.000   0.000
+43699.00    16.204  -4.943  0.000   0.000
+43700.00    16.336  -4.926  0.000   0.000
+43701.00    16.474  -4.807  0.000   0.000
+43702.00    16.214  -4.703  0.000   0.000
+43703.00    15.538  -4.648  0.000   0.000
+43704.00    14.839  -4.581  0.000   0.000
+43705.00    14.448  -4.503  0.000   0.000
+43706.00    14.327  -4.521  0.000   0.000
+43707.00    14.242  -4.665  0.000   0.000
+43708.00    14.073  -4.783  0.000   0.000
+43709.00    13.895  -4.718  0.000   0.000
+43710.00    13.84   -4.534  0.000   0.000
+43711.00    13.919  -4.436  0.000   0.000
+43712.00    13.925  -4.489  0.000   0.000
+43713.00    13.607  -4.548  0.000   0.000
+43714.00    13.009  -4.505  0.000   0.000
+43715.00    12.544  -4.453  0.000   0.000
+43716.00    12.545  -4.534  0.000   0.000
+43717.00    12.822  -4.719  0.000   0.000
+43718.00    12.89   -4.855  0.000   0.000
+43719.00    12.577  -4.881  0.000   0.000
+43720.00    12.193  -4.878  0.000   0.000
+43721.00    12.081  -4.908  0.000   0.000
+43722.00    12.24   -4.905  0.000   0.000
+43723.00    12.449  -4.785  0.000   0.000
+43724.00    12.539  -4.596  0.000   0.000
+43725.00    12.458  -4.486  0.000   0.000
+43726.00    12.237  -4.536  0.000   0.000
+43727.00    12.007  -4.668  0.000   0.000
+43728.00    11.923  -4.743  0.000   0.000
+43729.00    11.968  -4.709  0.000   0.000
+43730.00    11.924  -4.624  0.000   0.000
+43731.00    11.626  -4.563  0.000   0.000
+43732.00    11.162  -4.55   0.000   0.000
+43733.00    10.759  -4.599  0.000   0.000
+43734.00    10.541  -4.729  0.000   0.000
+43735.00    10.451  -4.894  0.000   0.000
+43736.00    10.363  -4.949  0.000   0.000
+43737.00    10.226  -4.799  0.000   0.000
+43738.00    10.132  -4.556  0.000   0.000
+43739.00    10.195  -4.45   0.000   0.000
+43740.00    10.33   -4.546  0.000   0.000
+43741.00    10.244  -4.648  0.000   0.000
+43742.00    9.784   -4.557  0.000   0.000
+43743.00    9.223   -4.334  0.000   0.000
+43744.00    9.000   -4.218  0.000   0.000
+43745.00    9.183   -4.329  0.000   0.000
+43746.00    9.42    -4.554  0.000   0.000
+43747.00    9.44    -4.726  0.000   0.000
+43748.00    9.353   -4.793  0.000   0.000
+43749.00    9.387   -4.798  0.000   0.000
+43750.00    9.535   -4.767  0.000   0.000
+43751.00    9.641   -4.692  0.000   0.000
+43752.00    9.664   -4.584  0.000   0.000
+43753.00    9.66    -4.48   0.000   0.000
+43754.00    9.614   -4.409  0.000   0.000
+43755.00    9.467   -4.375  0.000   0.000
+43756.00    9.284   -4.366  0.000   0.000
+43757.00    9.212   -4.367  0.000   0.000
+43758.00    9.28    -4.357  0.000   0.000
+43759.00    9.343   -4.336  0.000   0.000
+43760.00    9.258   -4.336  0.000   0.000
+43761.00    9.047   -4.406  0.000   0.000
+43762.00    8.85    -4.556  0.000   0.000
+43763.00    8.777   -4.714  0.000   0.000
+43764.00    8.809   -4.74   0.000   0.000
+43765.00    8.848   -4.556  0.000   0.000
+43766.00    8.867   -4.262  0.000   0.000
+43767.00    8.934   -4.077  0.000   0.000
+43768.00    9.074   -4.113  0.000   0.000
+43769.00    9.144   -4.239  0.000   0.000
+43770.00    8.975   -4.224  0.000   0.000
+43771.00    8.63    -4.015  0.000   0.000
+43772.00    8.387   -3.803  0.000   0.000
+43773.00    8.436   -3.796  0.000   0.000
+43774.00    8.708   -4.002  0.000   0.000
+43775.00    9.031   -4.261  0.000   0.000
+43776.00    9.336   -4.428  0.000   0.000
+43777.00    9.609   -4.477  0.000   0.000
+43778.00    9.78    -4.465  0.000   0.000
+43779.00    9.795   -4.447  0.000   0.000
+43780.00    9.736   -4.416  0.000   0.000
+43781.00    9.732   -4.315  0.000   0.000
+43782.00    9.78    -4.097  0.000   0.000
+43783.00    9.76    -3.813  0.000   0.000
+43784.00    9.639   -3.603  0.000   0.000
+43785.00    9.543   -3.57   0.000   0.000
+43786.00    9.593   -3.671  0.000   0.000
+43787.00    9.743   -3.779  0.000   0.000
+43788.00    9.843   -3.814  0.000   0.000
+43789.00    9.815   -3.807  0.000   0.000
+43790.00    9.738   -3.821  0.000   0.000
+43791.00    9.75    -3.852  0.000   0.000
+43792.00    9.906   -3.825  0.000   0.000
+43793.00    10.132  -3.675  0.000   0.000
+43794.00    10.314  -3.432  0.000   0.000
+43795.00    10.403  -3.231  0.000   0.000
+43796.00    10.44   -3.193  0.000   0.000
+43797.00    10.477  -3.288  0.000   0.000
+43798.00    10.514  -3.351  0.000   0.000
+43799.00    10.529  -3.26   0.000   0.000
+43800.00    10.545  -3.085  0.000   0.000
+43801.00    10.648  -3.007  0.000   0.000
+43802.00    10.924  -3.116  0.000   0.000
+43803.00    11.378  -3.327  0.000   0.000
+43804.00    11.889  -3.494  0.000   0.000
+43805.00    12.283  -3.548  0.000   0.000
+43806.00    12.465  -3.521  0.000   0.000
+43807.00    12.479  -3.475  0.000   0.000
+43808.00    12.444  -3.422  0.000   0.000
+43809.00    12.426  -3.296  0.000   0.000
+43810.00    12.414  -3.017  0.000   0.000
+43811.00    12.383  -2.619  0.000   0.000
+43812.00    12.351  -2.287  0.000   0.000
+43813.00    12.358  -2.216  0.000   0.000
+43814.00    12.415  -2.416  0.000   0.000
+43815.00    12.482  -2.683  0.000   0.000
+43816.00    12.503  -2.792  0.000   0.000
+43817.00    12.451  -2.693  0.000   0.000
+43818.00    12.373  -2.499  0.000   0.000
+43819.00    12.365  -2.337  0.000   0.000
+43820.00    12.49   -2.24   0.000   0.000
+43821.00    12.709  -2.166  0.000   0.000
+43822.00    12.898  -2.078  0.000   0.000
+43823.00    12.945  -1.998  0.000   0.000
+43824.00    12.853  -1.978  0.000   0.000
+43825.00    12.753  -2.025  0.000   0.000
+43826.00    12.796  -2.061  0.000   0.000
+43827.00    12.999  -2.005  0.000   0.000
+43828.00    13.24   -1.876  0.000   0.000
+43829.00    13.43   -1.785  0.000   0.000
+43830.00    13.644  -1.811  0.000   0.000
+43831.00    13.988  -1.918  0.000   0.000
+43832.00    14.399  -2.012  0.000   0.000
+43833.00    14.697  -2.033  0.000   0.000
+43834.00    14.825  -1.983  0.000   0.000
+43835.00    14.898  -1.893  0.000   0.000
+43836.00    14.978  -1.794  0.000   0.000
+43837.00    14.963  -1.683  0.000   0.000
+43838.00    14.78   -1.509  0.000   0.000
+43839.00    14.562  -1.233  0.000   0.000
+43840.00    14.505  -0.942  0.000   0.000
+43841.00    14.62   -0.836  0.000   0.000
+43842.00    14.744  -1.024  0.000   0.000
+43843.00    14.76   -1.356  0.000   0.000
+43844.00    14.688  -1.534  0.000   0.000
+43845.00    14.593  -1.404  0.000   0.000
+43846.00    14.513  -1.082  0.000   0.000
+43847.00    14.472  -0.795  0.000   0.000
+43848.00    14.488  -0.663  0.000   0.000
+43849.00    14.541  -0.656  0.000   0.000
+43850.00    14.574  -0.707  0.000   0.000
+43851.00    14.537  -0.785  0.000   0.000
+43852.00    14.428  -0.878  0.000   0.000
+43853.00    14.314  -0.945  0.000   0.000
+43854.00    14.308  -0.933  0.000   0.000
+43855.00    14.459  -0.835  0.000   0.000
+43856.00    14.676  -0.714  0.000   0.000
+43857.00    14.832  -0.651  0.000   0.000
+43858.00    14.937  -0.67   0.000   0.000
+43859.00    15.096  -0.727  0.000   0.000
+43860.00    15.313  -0.777  0.000   0.000
+43861.00    15.469  -0.805  0.000   0.000
+43862.00    15.545  -0.799  0.000   0.000
+43863.00    15.659  -0.74   0.000   0.000
+43864.00    15.812  -0.654  0.000   0.000
+43865.00    15.782  -0.608  0.000   0.000
+43866.00    15.448  -0.609  0.000   0.000
+43867.00    15.042  -0.554  0.000   0.000
+43868.00    14.892  -0.375  0.000   0.000
+43869.00    14.995  -0.196  0.000   0.000
+43870.00    15.069  -0.222  0.000   0.000
+43871.00    14.958  -0.461  0.000   0.000
+43872.00    14.798  -0.658  0.000   0.000
+43873.00    14.781  -0.583  0.000   0.000
+43874.00    14.925  -0.286  0.000   0.000
+43875.00    15.115  -0.007  0.000   0.000
+43876.00    15.221  0.113   0.000   0.000
+43877.00    15.172  0.114   0.000   0.000
+43878.00    15.003  0.067   0.000   0.000
+43879.00    14.845  -0.04   0.000   0.000
+43880.00    14.795  -0.219  0.000   0.000
+43881.00    14.818  -0.39   0.000   0.000
+43882.00    14.832  -0.443  0.000   0.000
+43883.00    14.836  -0.374  0.000   0.000
+43884.00    14.878  -0.289  0.000   0.000
+43885.00    14.957  -0.277  0.000   0.000
+43886.00    15.047  -0.322  0.000   0.000
+43887.00    15.168  -0.362  0.000   0.000
+43888.00    15.321  -0.392  0.000   0.000
+43889.00    15.441  -0.45   0.000   0.000
+43890.00    15.501  -0.529  0.000   0.000
+43891.00    15.561  -0.563  0.000   0.000
+43892.00    15.613  -0.537  0.000   0.000
+43893.00    15.489  -0.541  0.000   0.000
+43894.00    15.107  -0.639  0.000   0.000
+43895.00    14.7    -0.733  0.000   0.000
+43896.00    14.567  -0.66   0.000   0.000
+43897.00    14.653  -0.448  0.000   0.000
+43898.00    14.607  -0.324  0.000   0.000
+43899.00    14.276  -0.433  0.000   0.000
+43900.00    13.919  -0.628  0.000   0.000
+43901.00    13.885  -0.664  0.000   0.000
+43902.00    14.245  -0.51   0.000   0.000
+43903.00    14.767  -0.354  0.000   0.000
+43904.00    15.125  -0.312  0.000   0.000
+43905.00    15.115  -0.313  0.000   0.000
+43906.00    14.803  -0.278  0.000   0.000
+43907.00    14.502  -0.286  0.000   0.000
+43908.00    14.473  -0.449  0.000   0.000
+43909.00    14.64   -0.721  0.000   0.000
+43910.00    14.731  -0.937  0.000   0.000
+43911.00    14.659  -1.017  0.000   0.000
+43912.00    14.607  -1.03   0.000   0.000
+43913.00    14.735  -1.06   0.000   0.000
+43914.00    14.988  -1.092  0.000   0.000
+43915.00    15.238  -1.077  0.000   0.000
+43916.00    15.439  -1.046  0.000   0.000
+43917.00    15.584  -1.081  0.000   0.000
+43918.00    15.645  -1.193  0.000   0.000
+43919.00    15.611  -1.3    0.000   0.000
+43920.00    15.492  -1.344  0.000   0.000
+43921.00    15.275  -1.376  0.000   0.000
+43922.00    14.975  -1.477  0.000   0.000
+43923.00    14.755  -1.605  0.000   0.000
+43924.00    14.791  -1.625  0.000   0.000
+43925.00    14.998  -1.509  0.000   0.000
+43926.00    15.06   -1.412  0.000   0.000
+43927.00    14.807  -1.483  0.000   0.000
+43928.00    14.447  -1.657  0.000   0.000
+43929.00    14.336  -1.743  0.000   0.000
+43930.00    14.622  -1.695  0.000   0.000
+43931.00    15.137  -1.657  0.000   0.000
+43932.00    15.544  -1.728  0.000   0.000
+43933.00    15.574  -1.808  0.000   0.000
+43934.00    15.252  -1.774  0.000   0.000
+43935.00    14.917  -1.692  0.000   0.000
+43936.00    14.896  -1.75   0.000   0.000
+43937.00    15.13   -2.004  0.000   0.000
+43938.00    15.287  -2.314  0.000   0.000
+43939.00    15.239  -2.529  0.000   0.000
+43940.00    15.231  -2.627  0.000   0.000
+43941.00    15.501  -2.654  0.000   0.000
+43942.00    15.948  -2.622  0.000   0.000
+43943.00    16.305  -2.525  0.000   0.000
+43944.00    16.484  -2.41   0.000   0.000
+43945.00    16.567  -2.36   0.000   0.000
+43946.00    16.592  -2.402  0.000   0.000
+43947.00    16.514  -2.489  0.000   0.000
+43948.00    16.332  -2.572  0.000   0.000
+43949.00    16.126  -2.654  0.000   0.000
+43950.00    15.965  -2.761  0.000   0.000
+43951.00    15.904  -2.874  0.000   0.000
+43952.00    15.99   -2.939  0.000   0.000
+43953.00    16.209  -2.944  0.000   0.000
+43954.00    16.442  -2.956  0.000   0.000
+43955.00    16.574  -3.034  0.000   0.000
+43956.00    16.61   -3.124  0.000   0.000
+43957.00    16.648  -3.117  0.000   0.000
+43958.00    16.753  -3.014  0.000   0.000
+43959.00    16.895  -2.964  0.000   0.000
+43960.00    16.969  -3.08   0.000   0.000
+43961.00    16.872  -3.273  0.000   0.000
+43962.00    16.63   -3.355  0.000   0.000
+43963.00    16.44   -3.29   0.000   0.000
+43964.00    16.487  -3.238  0.000   0.000
+43965.00    16.698  -3.352  0.000   0.000
+43966.00    16.815  -3.605  0.000   0.000
+43967.00    16.762  -3.853  0.000   0.000
+43968.00    16.775  -3.993  0.000   0.000
+43969.00    17.069  -4.014  0.000   0.000
+43970.00    17.518  -3.947  0.000   0.000
+43971.00    17.817  -3.826  0.000   0.000
+43972.00    17.856  -3.697  0.000   0.000
+43973.00    17.769  -3.594  0.000   0.000
+43974.00    17.678  -3.526  0.000   0.000
+43975.00    17.569  -3.504  0.000   0.000
+43976.00    17.426  -3.558  0.000   0.000
+43977.00    17.309  -3.702  0.000   0.000
+43978.00    17.26   -3.888  0.000   0.000
+43979.00    17.229  -4.029  0.000   0.000
+43980.00    17.165  -4.083  0.000   0.000
+43981.00    17.119  -4.081  0.000   0.000
+43982.00    17.205  -4.086  0.000   0.000
+43983.00    17.483  -4.111  0.000   0.000
+43984.00    17.885  -4.101  0.000   0.000
+43985.00    18.239  -3.988  0.000   0.000
+43986.00    18.37   -3.795  0.000   0.000
+43987.00    18.217  -3.659  0.000   0.000
+43988.00    17.874  -3.714  0.000   0.000
+43989.00    17.521  -3.929  0.000   0.000
+43990.00    17.32   -4.122  0.000   0.000
+43991.00    17.344  -4.153  0.000   0.000
+43992.00    17.534  -4.077  0.000   0.000
+43993.00    17.721  -4.064  0.000   0.000
+43994.00    17.755  -4.198  0.000   0.000
+43995.00    17.658  -4.409  0.000   0.000
+43996.00    17.615  -4.573  0.000   0.000
+43997.00    17.765  -4.628  0.000   0.000
+43998.00    18.027  -4.594  0.000   0.000
+43999.00    18.196  -4.521  0.000   0.000
+44000.00    18.152  -4.44   0.000   0.000
+44001.00    17.938  -4.343  0.000   0.000
+44002.00    17.668  -4.2    0.000   0.000
+44003.00    17.43   -4.039  0.000   0.000
+44004.00    17.28   -3.969  0.000   0.000
+44005.00    17.239  -4.081  0.000   0.000
+44006.00    17.267  -4.329  0.000   0.000
+44007.00    17.257  -4.539  0.000   0.000
+44008.00    17.119  -4.575  0.000   0.000
+44009.00    16.876  -4.455  0.000   0.000
+44010.00    16.676  -4.3    0.000   0.000
+44011.00    16.693  -4.203  0.000   0.000
+44012.00    16.984  -4.158  0.000   0.000
+44013.00    17.407  -4.098  0.000   0.000
+44014.00    17.678  -3.985  0.000   0.000
+44015.00    17.565  -3.866  0.000   0.000
+44016.00    17.079  -3.841  0.000   0.000
+44017.00    16.499  -3.953  0.000   0.000
+44018.00    16.161  -4.121  0.000   0.000
+44019.00    16.197  -4.217  0.000   0.000
+44020.00    16.45   -4.209  0.000   0.000
+44021.00    16.656  -4.185  0.000   0.000
+44022.00    16.69   -4.236  0.000   0.000
+44023.00    16.608  -4.356  0.000   0.000
+44024.00    16.509  -4.476  0.000   0.000
+44025.00    16.445  -4.546  0.000   0.000
+44026.00    16.437  -4.562  0.000   0.000
+44027.00    16.474  -4.542  0.000   0.000
+44028.00    16.448  -4.499  0.000   0.000
+44029.00    16.196  -4.419  0.000   0.000
+44030.00    15.694  -4.266  0.000   0.000
+44031.00    15.157  -4.032  0.000   0.000
+44032.00    14.844  -3.813  0.000   0.000
+44033.00    14.802  -3.765  0.000   0.000
+44034.00    14.87   -3.941  0.000   0.000
+44035.00    14.886  -4.183  0.000   0.000
+44036.00    14.804  -4.255  0.000   0.000
+44037.00    14.634  -4.078  0.000   0.000
+44038.00    14.393  -3.792  0.000   0.000
+44039.00    14.146  -3.603  0.000   0.000
+44040.00    14.028  -3.593  0.000   0.000
+44041.00    14.118  -3.693  0.000   0.000
+44042.00    14.316  -3.789  0.000   0.000
+44043.00    14.369  -3.826  0.000   0.000
+44044.00    14.079  -3.828  0.000   0.000
+44045.00    13.513  -3.851  0.000   0.000
+44046.00    12.983  -3.917  0.000   0.000
+44047.00    12.767  -4.005  0.000   0.000
+44048.00    12.865  -4.084  0.000   0.000
+44049.00    13.061  -4.139  0.000   0.000
+44050.00    13.187  -4.159  0.000   0.000
+44051.00    13.209  -4.14   0.000   0.000
+44052.00    13.114  -4.11   0.000   0.000
+44053.00    12.886  -4.119  0.000   0.000
+44054.00    12.635  -4.176  0.000   0.000
+44055.00    12.542  -4.232  0.000   0.000
+44056.00    12.554  -4.237  0.000   0.000
+44057.00    12.335  -4.194  0.000   0.000
+44058.00    11.678  -4.108  0.000   0.000
+44059.00    10.853  -3.942  0.000   0.000
+44060.00    10.345  -3.697  0.000   0.000
+44061.00    10.295  -3.506  0.000   0.000
+44062.00    10.425  -3.526  0.000   0.000
+44063.00    10.456  -3.727  0.000   0.000
+44064.00    10.384  -3.876  0.000   0.000
+44065.00    10.318  -3.79   0.000   0.000
+44066.00    10.231  -3.546  0.000   0.000
+44067.00    10.016  -3.371  0.000   0.000
+44068.00    9.674   -3.389  0.000   0.000
+44069.00    9.359   -3.533  0.000   0.000
+44070.00    9.234   -3.688  0.000   0.000
+44071.00    9.299   -3.811  0.000   0.000
+44072.00    9.356   -3.913  0.000   0.000
+44073.00    9.183   -3.994  0.000   0.000
+44074.00    8.783   -4.049  0.000   0.000
+44075.00    8.405   -4.11   0.000   0.000
+44076.00    8.286   -4.208  0.000   0.000
+44077.00    8.427   -4.304  0.000   0.000
+44078.00    8.66    -4.293  0.000   0.000
+44079.00    8.822   -4.127  0.000   0.000
+44080.00    8.799   -3.905  0.000   0.000
+44081.00    8.553   -3.801  0.000   0.000
+44082.00    8.225   -3.882  0.000   0.000
+44083.00    8.073   -4.039  0.000   0.000
+44084.00    8.128   -4.13   0.000   0.000
+44085.00    8.041   -4.142  0.000   0.000
+44086.00    7.489   -4.138  0.000   0.000
+44087.00    6.665   -4.105  0.000   0.000
+44088.00    6.111   -3.972  0.000   0.000
+44089.00    6.076   -3.777  0.000   0.000
+44090.00    6.28    -3.693  0.000   0.000
+44091.00    6.349   -3.803  0.000   0.000
+44092.00    6.239   -3.963  0.000   0.000
+44093.00    6.139   -3.973  0.000   0.000
+44094.00    6.13    -3.837  0.000   0.000
+44095.00    6.091   -3.73   0.000   0.000
+44096.00    5.853   -3.731  0.000   0.000
+44097.00    5.401   -3.746  0.000   0.000
+44098.00    4.945   -3.7    0.000   0.000
+44099.00    4.781   -3.683  0.000   0.000
+44100.00    4.988   -3.813  0.000   0.000
+44101.00    5.287   -4.058  0.000   0.000
+44102.00    5.326   -4.268  0.000   0.000
+44103.00    5.09    -4.374  0.000   0.000
+44104.00    4.893   -4.427  0.000   0.000
+44105.00    4.971   -4.455  0.000   0.000
+44106.00    5.245   -4.378  0.000   0.000
+44107.00    5.486   -4.127  0.000   0.000
+44108.00    5.543   -3.798  0.000   0.000
+44109.00    5.404   -3.604  0.000   0.000
+44110.00    5.182   -3.653  0.000   0.000
+44111.00    5.069   -3.841  0.000   0.000
+44112.00    5.142   -3.984  0.000   0.000
+44113.00    5.199   -4.027  0.000   0.000
+44114.00    4.952   -4.047  0.000   0.000
+44115.00    4.426   -4.087  0.000   0.000
+44116.00    3.99    -4.086  0.000   0.000
+44117.00    3.92    -4.009  0.000   0.000
+44118.00    4.098   -3.943  0.000   0.000
+44119.00    4.224   -3.97   0.000   0.000
+44120.00    4.18    -4.024  0.000   0.000
+44121.00    4.083   -3.977  0.000   0.000
+44122.00    4.068   -3.844  0.000   0.000
+44123.00    4.134   -3.77   0.000   0.000
+44124.00    4.123   -3.78   0.000   0.000
+44125.00    3.855   -3.719  0.000   0.000
+44126.00    3.364   -3.491  0.000   0.000
+44127.00    2.996   -3.273  0.000   0.000
+44128.00    3.09    -3.333  0.000   0.000
+44129.00    3.552   -3.698  0.000   0.000
+44130.00    3.93    -4.12   0.000   0.000
+44131.00    3.963   -4.359  0.000   0.000
+44132.00    3.858   -4.392  0.000   0.000
+44133.00    3.938   -4.314  0.000   0.000
+44134.00    4.217   -4.163  0.000   0.000
+44135.00    4.478   -3.911  0.000   0.000
+44136.00    4.594   -3.602  0.000   0.000
+44137.00    4.603   -3.367  0.000   0.000
+44138.00    4.566   -3.305  0.000   0.000
+44139.00    4.529   -3.379  0.000   0.000
+44140.00    4.554   -3.472  0.000   0.000
+44141.00    4.637   -3.519  0.000   0.000
+44142.00    4.656   -3.547  0.000   0.000
+44143.00    4.516   -3.594  0.000   0.000
+44144.00    4.301   -3.649  0.000   0.000
+44145.00    4.197   -3.676  0.000   0.000
+44146.00    4.278   -3.677  0.000   0.000
+44147.00    4.464   -3.653  0.000   0.000
+44148.00    4.628   -3.551  0.000   0.000
+44149.00    4.709   -3.33   0.000   0.000
+44150.00    4.736   -3.081  0.000   0.000
+44151.00    4.787   -2.976  0.000   0.000
+44152.00    4.87    -3.047  0.000   0.000
+44153.00    4.861   -3.1    0.000   0.000
+44154.00    4.659   -2.948  0.000   0.000
+44155.00    4.418   -2.693  0.000   0.000
+44156.00    4.45    -2.643  0.000   0.000
+44157.00    4.829   -2.943  0.000   0.000
+44158.00    5.266   -3.407  0.000   0.000
+44159.00    5.486   -3.723  0.000   0.000
+44160.00    5.558   -3.764  0.000   0.000
+44161.00    5.72    -3.616  0.000   0.000
+44162.00    6.001   -3.406  0.000   0.000
+44163.00    6.238   -3.179  0.000   0.000
+44164.00    6.353   -2.93   0.000   0.000
+44165.00    6.416   -2.673  0.000   0.000
+44166.00    6.458   -2.455  0.000   0.000
+44167.00    6.423   -2.328  0.000   0.000
+44168.00    6.334   -2.314  0.000   0.000
+44169.00    6.317   -2.392  0.000   0.000
+44170.00    6.422   -2.497  0.000   0.000
+44171.00    6.533   -2.569  0.000   0.000
+44172.00    6.52    -2.592  0.000   0.000
+44173.00    6.423   -2.591  0.000   0.000
+44174.00    6.402   -2.578  0.000   0.000
+44175.00    6.568   -2.513  0.000   0.000
+44176.00    6.86    -2.329  0.000   0.000
+44177.00    7.101   -2.019  0.000   0.000
+44178.00    7.157   -1.706  0.000   0.000
+44179.00    7.065   -1.576  0.000   0.000
+44180.00    6.971   -1.696  0.000   0.000
+44181.00    6.958   -1.906  0.000   0.000
+44182.00    6.99    -1.963  0.000   0.000
+44183.00    7.04    -1.814  0.000   0.000
+44184.00    7.178   -1.669  0.000   0.000
+44185.00    7.454   -1.745  0.000   0.000
+44186.00    7.786   -2.017  0.000   0.000
+44187.00    8.056   -2.26   0.000   0.000
+44188.00    8.269   -2.296  0.000   0.000
+44189.00    8.495   -2.148  0.000   0.000
+44190.00    8.715   -1.941  0.000   0.000
+44191.00    8.84    -1.758  0.000   0.000
+44192.00    8.85    -1.578  0.000   0.000
+44193.00    8.811   -1.341  0.000   0.000
+44194.00    8.744   -1.044  0.000   0.000
+44195.00    8.607   -0.783  0.000   0.000
+44196.00    8.429   -0.697  0.000   0.000
+44197.00    8.351   -0.835  0.000   0.000
+44198.00    8.464   -1.08   0.000   0.000
+44199.00    8.669   -1.238  0.000   0.000
+44200.00    8.78    -1.219  0.000   0.000
+44201.00    8.73    -1.087  0.000   0.000
+44202.00    8.64    -0.952  0.000   0.000
+44203.00    8.674   -0.845  0.000   0.000
+44204.00    8.863   -0.719  0.000   0.000
+44205.00    9.06    -0.54   0.000   0.000
+44206.00    9.075   -0.363  0.000   0.000
+44207.00    8.85    -0.306  0.000   0.000
+44208.00    8.526   -0.436  0.000   0.000
+44209.00    8.316   -0.67   0.000   0.000
+44210.00    8.335   -0.819  0.000   0.000
+44211.00    8.53    -0.763  0.000   0.000
+44212.00    8.772   -0.586  0.000   0.000
+44213.00    8.983   -0.484  0.000   0.000
+44214.00    9.18    -0.545  0.000   0.000
+44215.00    9.411   -0.67   0.000   0.000
+44216.00    9.671   -0.711  0.000   0.000
+44217.00    9.884   -0.636  0.000   0.000
+44218.00    9.982   -0.52   0.000   0.000
+44219.00    9.963   -0.433  0.000   0.000
+44220.00    9.862   -0.359  0.000   0.000
+44221.00    9.698   -0.227  0.000   0.000
+44222.00    9.476   0.004   0.000   0.000
+44223.00    9.245   0.271   0.000   0.000
+44224.00    9.098   0.417   0.000   0.000
+44225.00    9.097   0.316   0.000   0.000
+44226.00    9.23    0.024   0.000   0.000
+44227.00    9.429   -0.23   0.000   0.000
+44228.00    9.61    -0.242  0.000   0.000
+44229.00    9.711   -0.017  0.000   0.000
+44230.00    9.722   0.264   0.000   0.000
+44231.00    9.694   0.434   0.000   0.000
+44232.00    9.686   0.468   0.000   0.000
+44233.00    9.689   0.434   0.000   0.000
+44234.00    9.614   0.385   0.000   0.000
+44235.00    9.389   0.313   0.000   0.000
+44236.00    9.058   0.19    0.000   0.000
+44237.00    8.791   0.041   0.000   0.000
+44238.00    8.751   -0.051  0.000   0.000
+44239.00    8.94    -0.017  0.000   0.000
+44240.00    9.19    0.106   0.000   0.000
+44241.00    9.345   0.200   0.000   0.000
+44242.00    9.427   0.185   0.000   0.000
+44243.00    9.562   0.103   0.000   0.000
+44244.00    9.761   0.041   0.000   0.000
+44245.00    9.887   0.03    0.000   0.000
+44246.00    9.853   0.029   0.000   0.000
+44247.00    9.728   0.005   0.000   0.000
+44248.00    9.586   -0.031  0.000   0.000
+44249.00    9.381   -0.038  0.000   0.000
+44250.00    9.088   0.037   0.000   0.000
+44251.00    8.847   0.223   0.000   0.000
+44252.00    8.811   0.449   0.000   0.000
+44253.00    8.917   0.539   0.000   0.000
+44254.00    8.977   0.376   0.000   0.000
+44255.00    8.964   0.074   0.000   0.000
+44256.00    9.054   -0.093  0.000   0.000
+44257.00    9.34    0.037   0.000   0.000
+44258.00    9.674   0.347   0.000   0.000
+44259.00    9.832   0.585   0.000   0.000
+44260.00    9.75    0.62    0.000   0.000
+44261.00    9.532   0.504   0.000   0.000
+44262.00    9.301   0.348   0.000   0.000
+44263.00    9.107   0.196   0.000   0.000
+44264.00    8.949   0.046   0.000   0.000
+44265.00    8.845   -0.083  0.000   0.000
+44266.00    8.849   -0.149  0.000   0.000
+44267.00    8.993   -0.145  0.000   0.000
+44268.00    9.205   -0.124  0.000   0.000
+44269.00    9.365   -0.147  0.000   0.000
+44270.00    9.447   -0.215  0.000   0.000
+44271.00    9.533   -0.28   0.000   0.000
+44272.00    9.645   -0.312  0.000   0.000
+44273.00    9.674   -0.344  0.000   0.000
+44274.00    9.553   -0.413  0.000   0.000
+44275.00    9.38    -0.508  0.000   0.000
+44276.00    9.239   -0.605  0.000   0.000
+44277.00    9.059   -0.706  0.000   0.000
+44278.00    8.803   -0.787  0.000   0.000
+44279.00    8.657   -0.748  0.000   0.000
+44280.00    8.806   -0.528  0.000   0.000
+44281.00    9.07    -0.271  0.000   0.000
+44282.00    9.07    -0.245  0.000   0.000
+44283.00    8.773   -0.538  0.000   0.000
+44284.00    8.600   -0.902  0.000   0.000
+44285.00    8.907   -1.017  0.000   0.000
+44286.00    9.531   -0.834  0.000   0.000
+44287.00    9.988   -0.589  0.000   0.000
+44288.00    9.984   -0.494  0.000   0.000
+44289.00    9.62    -0.546  0.000   0.000
+44290.00    9.213   -0.653  0.000   0.000
+44291.00    9.023   -0.799  0.000   0.000
+44292.00    9.088   -1.012  0.000   0.000
+44293.00    9.253   -1.247  0.000   0.000
+44294.00    9.363   -1.406  0.000   0.000
+44295.00    9.428   -1.462  0.000   0.000
+44296.00    9.567   -1.485  0.000   0.000
+44297.00    9.807   -1.531  0.000   0.000
+44298.00    10.059  -1.561  0.000   0.000
+44299.00    10.245  -1.512  0.000   0.000
+44300.00    10.341  -1.411  0.000   0.000
+44301.00    10.322  -1.368  0.000   0.000
+44302.00    10.183  -1.438  0.000   0.000
+44303.00    10.003  -1.566  0.000   0.000
+44304.00    9.859   -1.683  0.000   0.000
+44305.00    9.709   -1.805  0.000   0.000
+44306.00    9.529   -1.967  0.000   0.000
+44307.00    9.501   -2.083  0.000   0.000
+44308.00    9.821   -2.009  0.000   0.000
+44309.00    10.311  -1.778  0.000   0.000
+44310.00    10.511  -1.652  0.000   0.000
+44311.00    10.26   -1.839  0.000   0.000
+44312.00    9.959   -2.21   0.000   0.000
+44313.00    10.086  -2.436  0.000   0.000
+44314.00    10.612  -2.372  0.000   0.000
+44315.00    11.062  -2.187  0.000   0.000
+44316.00    11.045  -2.093  0.000   0.000
+44317.00    10.598  -2.105  0.000   0.000
+44318.00    10.098  -2.141  0.000   0.000
+44319.00    9.936   -2.226  0.000   0.000
+44320.00    10.203  -2.45   0.000   0.000
+44321.00    10.612  -2.78   0.000   0.000
+44322.00    10.79   -3.045  0.000   0.000
+44323.00    10.696  -3.135  0.000   0.000
+44324.00    10.646  -3.102  0.000   0.000
+44325.00    10.888  -3.033  0.000   0.000
+44326.00    11.307  -2.922  0.000   0.000
+44327.00    11.621  -2.72   0.000   0.000
+44328.00    11.707  -2.479  0.000   0.000
+44329.00    11.627  -2.341  0.000   0.000
+44330.00    11.467  -2.383  0.000   0.000
+44331.00    11.284  -2.532  0.000   0.000
+44332.00    11.125  -2.677  0.000   0.000
+44333.00    10.989  -2.801  0.000   0.000
+44334.00    10.859  -2.962  0.000   0.000
+44335.00    10.829  -3.143  0.000   0.000
+44336.00    11.067  -3.227  0.000   0.000
+44337.00    11.551  -3.157  0.000   0.000
+44338.00    11.991  -3.051  0.000   0.000
+44339.00    12.138  -3.067  0.000   0.000
+44340.00    12.078  -3.185  0.000   0.000
+44341.00    12.069  -3.228  0.000   0.000
+44342.00    12.169  -3.123  0.000   0.000
+44343.00    12.176  -3.007  0.000   0.000
+44344.00    11.904  -3.031  0.000   0.000
+44345.00    11.408  -3.148  0.000   0.000
+44346.00    10.976  -3.216  0.000   0.000
+44347.00    10.925  -3.24   0.000   0.000
+44348.00    11.322  -3.367  0.000   0.000
+44349.00    11.839  -3.647  0.000   0.000
+44350.00    12.018  -3.925  0.000   0.000
+44351.00    11.772  -4.027  0.000   0.000
+44352.00    11.503  -3.946  0.000   0.000
+44353.00    11.61   -3.787  0.000   0.000
+44354.00    12.018  -3.604  0.000   0.000
+44355.00    12.332  -3.379  0.000   0.000
+44356.00    12.341  -3.135  0.000   0.000
+44357.00    12.156  -2.967  0.000   0.000
+44358.00    11.947  -2.95   0.000   0.000
+44359.00    11.769  -3.06   0.000   0.000
+44360.00    11.635  -3.213  0.000   0.000
+44361.00    11.567  -3.356  0.000   0.000
+44362.00    11.534  -3.489  0.000   0.000
+44363.00    11.476  -3.617  0.000   0.000
+44364.00    11.438  -3.71   0.000   0.000
+44365.00    11.552  -3.734  0.000   0.000
+44366.00    11.871  -3.689  0.000   0.000
+44367.00    12.282  -3.599  0.000   0.000
+44368.00    12.601  -3.453  0.000   0.000
+44369.00    12.684  -3.232  0.000   0.000
+44370.00    12.464  -3.001  0.000   0.000
+44371.00    11.97   -2.918  0.000   0.000
+44372.00    11.347  -3.075  0.000   0.000
+44373.00    10.806  -3.353  0.000   0.000
+44374.00    10.542  -3.528  0.000   0.000
+44375.00    10.66   -3.527  0.000   0.000
+44376.00    11.099  -3.498  0.000   0.000
+44377.00    11.564  -3.596  0.000   0.000
+44378.00    11.695  -3.784  0.000   0.000
+44379.00    11.414  -3.897  0.000   0.000
+44380.00    11.044  -3.859  0.000   0.000
+44381.00    10.958  -3.738  0.000   0.000
+44382.00    11.144  -3.616  0.000   0.000
+44383.00    11.281  -3.499  0.000   0.000
+44384.00    11.158  -3.354  0.000   0.000
+44385.00    10.86   -3.186  0.000   0.000
+44386.00    10.559  -3.045  0.000   0.000
+44387.00    10.331  -2.99   0.000   0.000
+44388.00    10.201  -3.048  0.000   0.000
+44389.00    10.206  -3.188  0.000   0.000
+44390.00    10.305  -3.328  0.000   0.000
+44391.00    10.33   -3.394  0.000   0.000
+44392.00    10.163  -3.384  0.000   0.000
+44393.00    9.916   -3.348  0.000   0.000
+44394.00    9.844   -3.314  0.000   0.000
+44395.00    10.078  -3.245  0.000   0.000
+44396.00    10.469  -3.083  0.000   0.000
+44397.00    10.684  -2.835  0.000   0.000
+44398.00    10.457  -2.607  0.000   0.000
+44399.00    9.787   -2.552  0.000   0.000
+44400.00    8.946   -2.741  0.000   0.000
+44401.00    8.299   -3.07   0.000   0.000
+44402.00    8.073   -3.317  0.000   0.000
+44403.00    8.267   -3.35   0.000   0.000
+44404.00    8.683   -3.247  0.000   0.000
+44405.00    9.045   -3.188  0.000   0.000
+44406.00    9.135   -3.248  0.000   0.000
+44407.00    8.92    -3.34   0.000   0.000
+44408.00    8.566   -3.371  0.000   0.000
+44409.00    8.28    -3.351  0.000   0.000
+44410.00    8.121   -3.343  0.000   0.000
+44411.00    7.988   -3.349  0.000   0.000
+44412.00    7.765   -3.3    0.000   0.000
+44413.00    7.422   -3.137  0.000   0.000
+44414.00    7.01    -2.883  0.000   0.000
+44415.00    6.629   -2.646  0.000   0.000
+44416.00    6.395   -2.556  0.000   0.000
+44417.00    6.382   -2.662  0.000   0.000
+44418.00    6.533   -2.864  0.000   0.000
+44419.00    6.666   -2.992  0.000   0.000
+44420.00    6.614   -2.956  0.000   0.000
+44421.00    6.375   -2.827  0.000   0.000
+44422.00    6.114   -2.732  0.000   0.000
+44423.00    6.016   -2.716  0.000   0.000
+44424.00    6.12    -2.723  0.000   0.000
+44425.00    6.263   -2.691  0.000   0.000
+44426.00    6.193   -2.637  0.000   0.000
+44427.00    5.761   -2.644  0.000   0.000
+44428.00    5.068   -2.776  0.000   0.000
+44429.00    4.42    -3.011  0.000   0.000
+44430.00    4.12    -3.234  0.000   0.000
+44431.00    4.256   -3.328  0.000   0.000
+44432.00    4.644   -3.288  0.000   0.000
+44433.00    5.002   -3.203  0.000   0.000
+44434.00    5.152   -3.154  0.000   0.000
+44435.00    5.073   -3.137  0.000   0.000
+44436.00    4.808   -3.125  0.000   0.000
+44437.00    4.418   -3.142  0.000   0.000
+44438.00    4.024   -3.22   0.000   0.000
+44439.00    3.763   -3.32   0.000   0.000
+44440.00    3.629   -3.341  0.000   0.000
+44441.00    3.428   -3.218  0.000   0.000
+44442.00    3.007   -2.976  0.000   0.000
+44443.00    2.484   -2.713  0.000   0.000
+44444.00    2.138   -2.558  0.000   0.000
+44445.00    2.101   -2.609  0.000   0.000
+44446.00    2.251   -2.84   0.000   0.000
+44447.00    2.396   -3.078  0.000   0.000
+44448.00    2.457   -3.132  0.000   0.000
+44449.00    2.433   -2.977  0.000   0.000
+44450.00    2.307   -2.78   0.000   0.000
+44451.00    2.085   -2.715  0.000   0.000
+44452.00    1.853   -2.803  0.000   0.000
+44453.00    1.712   -2.935  0.000   0.000
+44454.00    1.663   -3.022  0.000   0.000
+44455.00    1.582   -3.072  0.000   0.000
+44456.00    1.357   -3.143  0.000   0.000
+44457.00    1.028   -3.262  0.000   0.000
+44458.00    0.797   -3.398  0.000   0.000
+44459.00    0.852   -3.5    0.000   0.000
+44460.00    1.178   -3.533  0.000   0.000
+44461.00    1.569   -3.487  0.000   0.000
+44462.00    1.827   -3.358  0.000   0.000
+44463.00    1.881   -3.163  0.000   0.000
+44464.00    1.728   -2.979  0.000   0.000
+44465.00    1.393   -2.921  0.000   0.000
+44466.00    1.033   -3.029  0.000   0.000
+44467.00    0.895   -3.205  0.000   0.000
+44468.00    1.017   -3.297  0.000   0.000
+44469.00    1.082   -3.255  0.000   0.000
+44470.00    0.771   -3.136  0.000   0.000
+44471.00    0.200   -3.009  0.000   0.000
+44472.00    -0.191  -2.91   0.000   0.000
+44473.00    -0.189  -2.895  0.000   0.000
+44474.00    0.000   -3.025  0.000   0.000
+44475.00    0.109   -3.242  0.000   0.000
+44476.00    0.14    -3.348  0.000   0.000
+44477.00    0.207   -3.213  0.000   0.000
+44478.00    0.265   -2.945  0.000   0.000
+44479.00    0.145   -2.779  0.000   0.000
+44480.00    -0.195  -2.809  0.000   0.000
+44481.00    -0.591  -2.925  0.000   0.000
+44482.00    -0.829  -2.997  0.000   0.000
+44483.00    -0.83   -3.032  0.000   0.000
+44484.00    -0.689  -3.114  0.000   0.000
+44485.00    -0.583  -3.254  0.000   0.000
+44486.00    -0.58   -3.38   0.000   0.000
+44487.00    -0.562  -3.445  0.000   0.000
+44488.00    -0.375  -3.457  0.000   0.000
+44489.00    -0.035  -3.409  0.000   0.000
+44490.00    0.288   -3.246  0.000   0.000
+44491.00    0.45    -2.942  0.000   0.000
+44492.00    0.421   -2.612  0.000   0.000
+44493.00    0.264   -2.449  0.000   0.000
+44494.00    0.133   -2.537  0.000   0.000
+44495.00    0.227   -2.753  0.000   0.000
+44496.00    0.562   -2.904  0.000   0.000
+44497.00    0.823   -2.937  0.000   0.000
+44498.00    0.659   -2.944  0.000   0.000
+44499.00    0.159   -2.978  0.000   0.000
+44500.00    -0.207  -2.983  0.000   0.000
+44501.00    -0.154  -2.921  0.000   0.000
+44502.00    0.119   -2.873  0.000   0.000
+44503.00    0.289   -2.903  0.000   0.000
+44504.00    0.329   -2.918  0.000   0.000
+44505.00    0.411   -2.77   0.000   0.000
+44506.00    0.563   -2.503  0.000   0.000
+44507.00    0.623   -2.327  0.000   0.000
+44508.00    0.467   -2.344  0.000   0.000
+44509.00    -0.66   -2.476  0.000   0.000
+44510.00    -0.993  -2.515  0.000   0.000
+44511.00    -1.152  -2.512  0.000   0.000
+44512.00    -1.074  -2.591  0.000   0.000
+44513.00    -0.882  -2.771  0.000   0.000
+44514.00    -0.806  -2.929  0.000   0.000
+44515.00    -0.93   -2.945  0.000   0.000
+44516.00    -1.047  -2.867  0.000   0.000
+44517.00    -0.949  -2.792  0.000   0.000
+44518.00    -0.721  -2.706  0.000   0.000
+44519.00    -0.58   -2.539  0.000   0.000
+44520.00    -0.6    -2.332  0.000   0.000
+44521.00    -0.682  -2.248  0.000   0.000
+44522.00    -0.679  -2.389  0.000   0.000
+44523.00    -0.488  -2.663  0.000   0.000
+44524.00    -0.112  -2.889  0.000   0.000
+44525.00    0.27    -2.996  0.000   0.000
+44526.00    0.426   -3.053  0.000   0.000
+44527.00    0.377   -3.098  0.000   0.000
+44528.00    0.448   -3.038  0.000   0.000
+44529.00    0.914   -2.765  0.000   0.000
+44530.00    1.707   -2.315  0.000   0.000
+44531.00    2.454   -1.924  0.000   0.000
+44532.00    2.932   -1.681  0.000   0.000
+44533.00    3.217   -1.473  0.000   0.000
+44534.00    3.424   -1.304  0.000   0.000
+44535.00    3.623   -1.282  0.000   0.000
+44536.00    3.776   -1.448  0.000   0.000
+44537.00    3.846   -1.637  0.000   0.000
+44538.00    3.88    -1.654  0.000   0.000
+44539.00    3.991   -1.576  0.000   0.000
+44540.00    4.303   -1.656  0.000   0.000
+44541.00    4.754   -1.974  0.000   0.000
+44542.00    5.083   -2.304  0.000   0.000
+44543.00    5.15    -2.395  0.000   0.000
+44544.00    5.151   -2.247  0.000   0.000
+44545.00    5.359   -2.037  0.000   0.000
+44546.00    5.749   -1.87   0.000   0.000
+44547.00    6.058   -1.705  0.000   0.000
+44548.00    6.152   -1.504  0.000   0.000
+44549.00    6.138   -1.333  0.000   0.000
+44550.00    6.149   -1.285  0.000   0.000
+44551.00    6.215   -1.363  0.000   0.000
+44552.00    6.325   -1.489  0.000   0.000
+44553.00    6.457   -1.602  0.000   0.000
+44554.00    6.532   -1.71   0.000   0.000
+44555.00    6.468   -1.825  0.000   0.000
+44556.00    6.313   -1.899  0.000   0.000
+44557.00    6.222   -1.867  0.000   0.000
+44558.00    6.284   -1.724  0.000   0.000
+44559.00    6.454   -1.52   0.000   0.000
+44560.00    6.627   -1.287  0.000   0.000
+44561.00    6.698   -1.036  0.000   0.000
+44562.00    6.591   -0.847  0.000   0.000
+44563.00    6.321   -0.861  0.000   0.000
+44564.00    6.026   -1.095  0.000   0.000
+44565.00    5.843   -1.34   0.000   0.000
+44566.00    5.802   -1.351  0.000   0.000
+44567.00    5.887   -1.149  0.000   0.000
+44568.00    6.122   -1.01   0.000   0.000
+44569.00    6.463   -1.12   0.000   0.000
+44570.00    6.723   -1.343  0.000   0.000
+44571.00    6.755   -1.404  0.000   0.000
+44572.00    6.668   -1.216  0.000   0.000
+44573.00    6.682   -0.931  0.000   0.000
+44574.00    6.81    -0.72   0.000   0.000
+44575.00    6.859   -0.593  0.000   0.000
+44576.00    6.738   -0.464  0.000   0.000
+44577.00    6.567   -0.297  0.000   0.000
+44578.00    6.467   -0.144  0.000   0.000
+44579.00    6.424   -0.084  0.000   0.000
+44580.00    6.414   -0.147  0.000   0.000
+44581.00    6.513   -0.292  0.000   0.000
+44582.00    6.753   -0.43   0.000   0.000
+44583.00    7.011   -0.487  0.000   0.000
+44584.00    7.125   -0.447  0.000   0.000
+44585.00    7.097   -0.348  0.000   0.000
+44586.00    7.073   -0.226  0.000   0.000
+44587.00    7.173   -0.082  0.000   0.000
+44588.00    7.355   0.104   0.000   0.000
+44589.00    7.447   0.314   0.000   0.000
+44590.00    7.287   0.459   0.000   0.000
+44591.00    6.876   0.426   0.000   0.000
+44592.00    6.414   0.208   0.000   0.000
+44593.00    6.137   -0.028  0.000   0.000
+44594.00    6.146   -0.061  0.000   0.000
+44595.00    6.389   0.151   0.000   0.000
+44596.00    6.78    0.399   0.000   0.000
+44597.00    7.231   0.452   0.000   0.000
+44598.00    7.625   0.317   0.000   0.000
+44599.00    7.853   0.204   0.000   0.000
+44600.00    7.91    0.267   0.000   0.000
+44601.00    7.867   0.445   0.000   0.000
+44602.00    7.749   0.587   0.000   0.000
+44603.00    7.536   0.639   0.000   0.000
+44604.00    7.275   0.677   0.000   0.000
+44605.00    7.091   0.78    0.000   0.000
+44606.00    7.042   0.932   0.000   0.000
+44607.00    7.058   1.024   0.000   0.000
+44608.00    7.082   0.949   0.000   0.000
+44609.00    7.173   0.707   0.000   0.000
+44610.00    7.41    0.436   0.000   0.000
+44611.00    7.738   0.309   0.000   0.000
+44612.00    7.998   0.377   0.000   0.000
+44613.00    8.095   0.534   0.000   0.000
+44614.00    8.075   0.642   0.000   0.000
+44615.00    8.039   0.663   0.000   0.000
+44616.00    8.014   0.65    0.000   0.000
+44617.00    7.922   0.651   0.000   0.000
+44618.00    7.666   0.642   0.000   0.000
+44619.00    7.246   0.563   0.000   0.000
+44620.00    6.809   0.392   0.000   0.000
+44621.00    6.555   0.207   0.000   0.000
+44622.00    6.596   0.13    0.000   0.000
+44623.00    6.874   0.209   0.000   0.000
+44624.00    7.24    0.336   0.000   0.000
+44625.00    7.575   0.34    0.000   0.000
+44626.00    7.843   0.174   0.000   0.000
+44627.00    8.038   -0.033  0.000   0.000
+44628.00    8.108   -0.131  0.000   0.000
+44629.00    7.982   -0.106  0.000   0.000
+44630.00    7.664   -0.062  0.000   0.000
+44631.00    7.283   -0.065  0.000   0.000
+44632.00    7.014   -0.078  0.000   0.000
+44633.00    6.942   -0.036  0.000   0.000
+44634.00    7.028   0.07    0.000   0.000
+44635.00    7.181   0.164   0.000   0.000
+44636.00    7.331   0.13    0.000   0.000
+44637.00    7.448   -0.091  0.000   0.000
+44638.00    7.552   -0.421  0.000   0.000
+44639.00    7.718   -0.665  0.000   0.000
+44640.00    8.005   -0.668  0.000   0.000
+44641.00    8.358   -0.47   0.000   0.000
+44642.00    8.617   -0.271  0.000   0.000
+44643.00    8.647   -0.236  0.000   0.000
+44644.00    8.459   -0.366  0.000   0.000
+44645.00    8.165   -0.551  0.000   0.000
+44646.00    7.869   -0.7    0.000   0.000
+44647.00    7.62    -0.801  0.000   0.000
+44648.00    7.469   -0.885  0.000   0.000
+44649.00    7.494   -0.968  0.000   0.000
+44650.00    7.751   -1.034  0.000   0.000
+44651.00    8.178   -1.07   0.000   0.000
+44652.00    8.604   -1.112  0.000   0.000
+44653.00    8.878   -1.22   0.000   0.000
+44654.00    9.003   -1.401  0.000   0.000
+44655.00    9.078   -1.577  0.000   0.000
+44656.00    9.115   -1.662  0.000   0.000
+44657.00    9.008   -1.663  0.000   0.000
+44658.00    8.725   -1.653  0.000   0.000
+44659.00    8.427   -1.678  0.000   0.000
+44660.00    8.301   -1.722  0.000   0.000
+44661.00    8.363   -1.757  0.000   0.000
+44662.00    8.52    -1.768  0.000   0.000
+44663.00    8.753   -1.751  0.000   0.000
+44664.00    9.072   -1.734  0.000   0.000
+44665.00    9.347   -1.809  0.000   0.000
+44666.00    9.41    -2.049  0.000   0.000
+44667.00    9.351   -2.368  0.000   0.000
+44668.00    9.494   -2.537  0.000   0.000
+44669.00    9.979   -2.422  0.000   0.000
+44670.00    10.513  -2.158  0.000   0.000
+44671.00    10.673  -2.024  0.000   0.000
+44672.00    10.361  -2.153  0.000   0.000
+44673.00    9.865   -2.435  0.000   0.000
+44674.00    9.521   -2.679  0.000   0.000
+44675.00    9.448   -2.802  0.000   0.000
+44676.00    9.568   -2.843  0.000   0.000
+44677.00    9.786   -2.862  0.000   0.000
+44678.00    10.086  -2.887  0.000   0.000
+44679.00    10.482  -2.933  0.000   0.000
+44680.00    10.91   -3.018  0.000   0.000
+44681.00    11.232  -3.13   0.000   0.000
+44682.00    11.369  -3.209  0.000   0.000
+44683.00    11.377  -3.191  0.000   0.000
+44684.00    11.335  -3.088  0.000   0.000
+44685.00    11.23   -2.995  0.000   0.000
+44686.00    11.045  -2.988  0.000   0.000
+44687.00    10.884  -3.06   0.000   0.000
+44688.00    10.855  -3.161  0.000   0.000
+44689.00    10.907  -3.285  0.000   0.000
+44690.00    10.952  -3.444  0.000   0.000
+44691.00    11.097  -3.573  0.000   0.000
+44692.00    11.502  -3.573  0.000   0.000
+44693.00    12.021  -3.482  0.000   0.000
+44694.00    12.267  -3.493  0.000   0.000
+44695.00    12.143  -3.708  0.000   0.000
+44696.00    12.038  -3.955  0.000   0.000
+44697.00    12.305  -3.967  0.000   0.000
+44698.00    12.74   -3.735  0.000   0.000
+44699.00    12.817  -3.539  0.000   0.000
+44700.00    12.349  -3.61   0.000   0.000
+44701.00    11.686  -3.883  0.000   0.000
+44702.00    11.319  -4.131  0.000   0.000
+44703.00    11.417  -4.246  0.000   0.000
+44704.00    11.779  -4.286  0.000   0.000
+44705.00    12.088  -4.313  0.000   0.000
+44706.00    12.198  -4.317  0.000   0.000
+44707.00    12.231  -4.291  0.000   0.000
+44708.00    12.391  -4.274  0.000   0.000
+44709.00    12.692  -4.275  0.000   0.000
+44710.00    12.941  -4.214  0.000   0.000
+44711.00    12.972  -4.018  0.000   0.000
+44712.00    12.813  -3.749  0.000   0.000
+44713.00    12.589  -3.577  0.000   0.000
+44714.00    12.391  -3.604  0.000   0.000
+44715.00    12.277  -3.762  0.000   0.000
+44716.00    12.253  -3.93   0.000   0.000
+44717.00    12.221  -4.089  0.000   0.000
+44718.00    12.1    -4.295  0.000   0.000
+44719.00    12.031  -4.51   0.000   0.000
+44720.00    12.278  -4.572  0.000   0.000
+44721.00    12.818  -4.416  0.000   0.000
+44722.00    13.242  -4.213  0.000   0.000
+44723.00    13.24   -4.179  0.000   0.000
+44724.00    12.987  -4.292  0.000   0.000
+44725.00    12.84   -4.323  0.000   0.000
+44726.00    12.801  -4.175  0.000   0.000
+44727.00    12.536  -4.03   0.000   0.000
+44728.00    11.898  -4.094  0.000   0.000
+44729.00    11.189  -4.313  0.000   0.000
+44730.00    10.86   -4.477  0.000   0.000
+44731.00    11.088  -4.511  0.000   0.000
+44732.00    11.638  -4.53   0.000   0.000
+44733.00    12.052  -4.604  0.000   0.000
+44734.00    12.015  -4.65   0.000   0.000
+44735.00    11.639  -4.579  0.000   0.000
+44736.00    11.356  -4.441  0.000   0.000
+44737.00    11.432  -4.33   0.000   0.000
+44738.00    11.674  -4.222  0.000   0.000
+44739.00    11.7    -4.027  0.000   0.000
+44740.00    11.398  -3.762  0.000   0.000
+44741.00    10.979  -3.586  0.000   0.000
+44742.00    10.67   -3.616  0.000   0.000
+44743.00    10.523  -3.792  0.000   0.000
+44744.00    10.471  -3.961  0.000   0.000
+44745.00    10.403  -4.067  0.000   0.000
+44746.00    10.221  -4.171  0.000   0.000
+44747.00    9.963   -4.305  0.000   0.000
+44748.00    9.834   -4.371  0.000   0.000
+44749.00    9.977   -4.259  0.000   0.000
+44750.00    10.24   -4.015  0.000   0.000
+44751.00    10.32   -3.798  0.000   0.000
+44752.00    10.094  -3.684  0.000   0.000
+44753.00    9.659   -3.604  0.000   0.000
+44754.00    9.099   -3.51   0.000   0.000
+44755.00    8.398   -3.492  0.000   0.000
+44756.00    7.611   -3.636  0.000   0.000
+44757.00    6.967   -3.838  0.000   0.000
+44758.00    6.715   -3.902  0.000   0.000
+44759.00    6.93    -3.808  0.000   0.000
+44760.00    7.427   -3.743  0.000   0.000
+44761.00    7.812   -3.829  0.000   0.000
+44762.00    7.712   -3.947  0.000   0.000
+44763.00    7.121   -3.918  0.000   0.000
+44764.00    6.457   -3.744  0.000   0.000
+44765.00    6.132   -3.579  0.000   0.000
+44766.00    6.094   -3.497  0.000   0.000
+44767.00    5.952   -3.419  0.000   0.000
+44768.00    5.503   -3.267  0.000   0.000
+44769.00    4.929   -3.098  0.000   0.000
+44770.00    4.485   -3.03   0.000   0.000
+44771.00    4.218   -3.088  0.000   0.000
+44772.00    4.044   -3.193  0.000   0.000
+44773.00    3.901   -3.259  0.000   0.000
+44774.00    3.722   -3.272  0.000   0.000
+44775.00    3.418   -3.268  0.000   0.000
+44776.00    3.002   -3.254  0.000   0.000
+44777.00    2.643   -3.198  0.000   0.000
+44778.00    2.482   -3.07   0.000   0.000
+44779.00    2.444   -2.886  0.000   0.000
+44780.00    2.289   -2.686  0.000   0.000
+44781.00    1.816   -2.515  0.000   0.000
+44782.00    1.002   -2.437  0.000   0.000
+44783.00    0.012   -2.522  0.000   0.000
+44784.00    -0.884  -2.761  0.000   0.000
+44785.00    -1.453  -2.995  0.000   0.000
+44786.00    -1.627  -3.033  0.000   0.000
+44787.00    -1.491  -2.871  0.000   0.000
+44788.00    -1.212  -2.716  0.000   0.000
+44789.00    -1.024  -2.743  0.000   0.000
+44790.00    -1.184  -2.885  0.000   0.000
+44791.00    -1.778  -2.932  0.000   0.000
+44792.00    -2.583  -2.81   0.000   0.000
+44793.00    -3.251  -2.653  0.000   0.000
+44794.00    -3.671  -2.597  0.000   0.000
+44795.00    -4.022  -2.603  0.000   0.000
+44796.00    -4.472  -2.541  0.000   0.000
+44797.00    -4.978  -2.366  0.000   0.000
+44798.00    -5.431  -2.175  0.000   0.000
+44799.00    -5.825  -2.097  0.000   0.000
+44800.00    -6.181  -2.168  0.000   0.000
+44801.00    -6.448  -2.309  0.000   0.000
+44802.00    -6.597  -2.393  0.000   0.000
+44803.00    -6.749  -2.353  0.000   0.000
+44804.00    -7.057  -2.232  0.000   0.000
+44805.00    -7.495  -2.129  0.000   0.000
+44806.00    -7.868  -2.086  0.000   0.000
+44807.00    -8.062  -2.051  0.000   0.000
+44808.00    -8.198  -1.963  0.000   0.000
+44809.00    -8.523  -1.839  0.000   0.000
+44810.00    -9.169  -1.774  0.000   0.000
+44811.00    -10.015 -1.854  0.000   0.000
+44812.00    -10.769 -2.063  0.000   0.000
+44813.00    -11.185 -2.267  0.000   0.000
+44814.00    -11.222 -2.316  0.000   0.000
+44815.00    -11.029 -2.18   0.000   0.000
+44816.00    -10.802 -1.997  0.000   0.000
+44817.00    -10.691 -1.93   0.000   0.000
+44818.00    -10.809 -1.983  0.000   0.000
+44819.00    -11.207 -2.018  0.000   0.000
+44820.00    -11.829 -1.944  0.000   0.000
+44821.00    -12.498 -1.835  0.000   0.000
+44822.00    -13.03  -1.807  0.000   0.000
+44823.00    -13.351 -1.847  0.000   0.000
+44824.00    -13.52  -1.826  0.000   0.000
+44825.00    -13.674 -1.67   0.000   0.000
+44826.00    -13.941 -1.459  0.000   0.000
+44827.00    -14.349 -1.356  0.000   0.000
+44828.00    -14.78  -1.455  0.000   0.000
+44829.00    -15.058 -1.692  0.000   0.000
+44830.00    -15.112 -1.888  0.000   0.000
+44831.00    -15.047 -1.88   0.000   0.000
+44832.00    -15.044 -1.668  0.000   0.000
+44833.00    -15.192 -1.42   0.000   0.000
+44834.00    -15.445 -1.312  0.000   0.000
+44835.00    -15.702 -1.367  0.000   0.000
+44836.00    -15.925 -1.466  0.000   0.000
+44837.00    -16.16  -1.501  0.000   0.000
+44838.00    -16.474 -1.473  0.000   0.000
+44839.00    -16.855 -1.456  0.000   0.000
+44840.00    -17.191 -1.495  0.000   0.000
+44841.00    -17.331 -1.561  0.000   0.000
+44842.00    -17.205 -1.584  0.000   0.000
+44843.00    -16.882 -1.519  0.000   0.000
+44844.00    -16.534 -1.399  0.000   0.000
+44845.00    -16.316 -1.29   0.000   0.000
+44846.00    -16.283 -1.215  0.000   0.000
+44847.00    -16.412 -1.135  0.000   0.000
+44848.00    -16.67  -1.035  0.000   0.000
+44849.00    -17.002 -0.98   0.000   0.000
+44850.00    -17.26  -1.033  0.000   0.000
+44851.00    -17.259 -1.147  0.000   0.000
+44852.00    -16.985 -1.195  0.000   0.000
+44853.00    -16.7   -1.121  0.000   0.000
+44854.00    -16.698 -1.009  0.000   0.000
+44855.00    -16.98  -0.988  0.000   0.000
+44856.00    -17.252 -1.106  0.000   0.000
+44857.00    -17.272 -1.306  0.000   0.000
+44858.00    -17.063 -1.463  0.000   0.000
+44859.00    -16.79  -1.446  0.000   0.000
+44860.00    -16.55  -1.211  0.000   0.000
+44861.00    -16.371 -0.88   0.000   0.000
+44862.00    -16.3   -0.683  0.000   0.000
+44863.00    -16.378 -0.758  0.000   0.000
+44864.00    -16.544 -1.015  0.000   0.000
+44865.00    -16.666 -1.233  0.000   0.000
+44866.00    -16.666 -1.274  0.000   0.000
+44867.00    -16.562 -1.181  0.000   0.000
+44868.00    -16.403 -1.081  0.000   0.000
+44869.00    -16.184 -1.045  0.000   0.000
+44870.00    -15.851 -1.061  0.000   0.000
+44871.00    -15.377 -1.086  0.000   0.000
+44872.00    -14.834 -1.092  0.000   0.000
+44873.00    -14.361 -1.057  0.000   0.000
+44874.00    -14.04  -0.956  0.000   0.000
+44875.00    -13.835 -0.787  0.000   0.000
+44876.00    -13.666 -0.622  0.000   0.000
+44877.00    -13.482 -0.587  0.000   0.000
+44878.00    -13.205 -0.736  0.000   0.000
+44879.00    -12.702 -0.969  0.000   0.000
+44880.00    -11.976 -1.126  0.000   0.000
+44881.00    -11.306 -1.161  0.000   0.000
+44882.00    -11.003 -1.168  0.000   0.000
+44883.00    -10.996 -1.23   0.000   0.000
+44884.00    -10.879 -1.314  0.000   0.000
+44885.00    -10.405 -1.349  0.000   0.000
+44886.00    -9.746  -1.327  0.000   0.000
+44887.00    -9.179  -1.255  0.000   0.000
+44888.00    -8.722  -1.096  0.000   0.000
+44889.00    -8.238  -0.85   0.000   0.000
+44890.00    -7.731  -0.667  0.000   0.000
+44891.00    -7.332  -0.74   0.000   0.000
+44892.00    -7.055  -1.057  0.000   0.000
+44893.00    -6.75   -1.37   0.000   0.000
+44894.00    -6.302  -1.455  0.000   0.000
+44895.00    -5.734  -1.343  0.000   0.000
+44896.00    -5.134  -1.234  0.000   0.000
+44897.00    -4.548  -1.249  0.000   0.000
+44898.00    -3.957  -1.347  0.000   0.000
+44899.00    -3.296  -1.445  0.000   0.000
+44900.00    -2.525  -1.525  0.000   0.000
+44901.00    -1.709  -1.585  0.000   0.000
+44902.00    -0.98   -1.57   0.000   0.000
+44903.00    -0.394  -1.436  0.000   0.000
+44904.00    0.13    -1.258  0.000   0.000
+44905.00    0.702   -1.208  0.000   0.000
+44906.00    1.39    -1.377  0.000   0.000
+44907.00    2.224   -1.659  0.000   0.000
+44908.00    3.143   -1.868  0.000   0.000
+44909.00    3.925   -1.946  0.000   0.000
+44910.00    4.339   -1.982  0.000   0.000
+44911.00    4.467   -2.035  0.000   0.000
+44912.00    4.675   -2.028  0.000   0.000
+44913.00    5.169   -1.878  0.000   0.000
+44914.00    5.739   -1.652  0.000   0.000
+44915.00    6.083   -1.478  0.000   0.000
+44916.00    6.200   -1.35   0.000   0.000
+44917.00    6.278   -1.16   0.000   0.000
+44918.00    6.344   -0.924  0.000   0.000
+44919.00    6.262   -0.814  0.000   0.000
+44920.00    6.013   -0.901  0.000   0.000
+44921.00    5.748   -0.992  0.000   0.000
+44922.00    5.557   -0.852  0.000   0.000
+44923.00    5.364   -0.511  0.000   0.000
+44924.00    5.046   -0.211  0.000   0.000
+44925.00    4.531   -0.08   0.000   0.000
+44926.00    3.789   0.007   0.000   0.000
+44927.00    2.864   0.22    0.000   0.000
+44928.00    1.89    0.546   0.000   0.000
+44929.00    1.018   0.857   0.000   0.000
+44930.00    0.179   1.13    0.000   0.000
+44931.00    -0.792  1.452   0.000   0.000
+44932.00    -1.873  1.837   0.000   0.000
+44933.00    -2.879  2.155   0.000   0.000
+44934.00    -3.679  2.291   0.000   0.000
+44935.00    -4.285  2.297   0.000   0.000
+44936.00    -4.795  2.328   0.000   0.000
+44937.00    -5.338  2.46    0.000   0.000
+44938.00    -6.041  2.629   0.000   0.000
+44939.00    -6.891  2.779   0.000   0.000
+44940.00    -7.7    2.968   0.000   0.000
+44941.00    -8.322  3.266   0.000   0.000
+44942.00    -8.835  3.608   0.000   0.000
+44943.00    -9.399  3.858   0.000   0.000
+44944.00    -10.018 4.003   0.000   0.000
+44945.00    -10.612 4.174   0.000   0.000
+44946.00    -11.231 4.43    0.000   0.000
+44947.00    -11.999 4.641   0.000   0.000
+44948.00    -12.839 4.69    0.000   0.000
+44949.00    -13.484 4.686   0.000   0.000
+44950.00    -13.767 4.833   0.000   0.000
+44951.00    -13.762 5.121   0.000   0.000
+44952.00    -13.655 5.314   0.000   0.000
+44953.00    -13.612 5.283   0.000   0.000
+44954.00    -13.767 5.201   0.000   0.000
+44955.00    -14.153 5.309   0.000   0.000
+44956.00    -14.622 5.604   0.000   0.000
+44957.00    -14.989 5.872   0.000   0.000
+44958.00    -15.283 5.981   0.000   0.000
+44959.00    -15.681 6.003   0.000   0.000
+44960.00    -16.206 6.05    0.000   0.000
+44961.00    -16.649 6.108   0.000   0.000
+44962.00    -16.839 6.083   0.000   0.000
+44963.00    -16.827 5.958   0.000   0.000
+44964.00    -16.746 5.823   0.000   0.000
+44965.00    -16.654 5.756   0.000   0.000
+44966.00    -16.581 5.752   0.000   0.000
+44967.00    -16.589 5.769   0.000   0.000
+44968.00    -16.706 5.798   0.000   0.000
+44969.00    -16.873 5.852   0.000   0.000
+44970.00    -17.013 5.904   0.000   0.000
+44971.00    -17.095 5.903   0.000   0.000
+44972.00    -17.12  5.863   0.000   0.000
+44973.00    -17.145 5.867   0.000   0.000
+44974.00    -17.319 5.947   0.000   0.000
+44975.00    -17.752 6.005   0.000   0.000
+44976.00    -18.316 5.936   0.000   0.000
+44977.00    -18.684 5.800   0.000   0.000
+44978.00    -18.614 5.759   0.000   0.000
+44979.00    -18.119 5.834   0.000   0.000
+44980.00    -17.38  5.843   0.000   0.000
+44981.00    -16.626 5.66    0.000   0.000
+44982.00    -16.081 5.423   0.000   0.000
+44983.00    -15.882 5.383   0.000   0.000
+44984.00    -15.953 5.587   0.000   0.000
+44985.00    -16.09  5.816   0.000   0.000
+44986.00    -16.205 5.859   0.000   0.000
+44987.00    -16.35  5.725   0.000   0.000
+44988.00    -16.501 5.56    0.000   0.000
+44989.00    -16.468 5.44    0.000   0.000
+44990.00    -16.135 5.317   0.000   0.000
+44991.00    -15.627 5.127   0.000   0.000
+44992.00    -15.135 4.888   0.000   0.000
+44993.00    -14.689 4.679   0.000   0.000
+44994.00    -14.22  4.568   0.000   0.000
+44995.00    -13.76  4.555   0.000   0.000
+44996.00    -13.43  4.572   0.000   0.000
+44997.00    -13.265 4.534   0.000   0.000
+44998.00    -13.161 4.403   0.000   0.000
+44999.00    -13.006 4.219   0.000   0.000
+45000.00    -12.789 4.062   0.000   0.000
+45001.00    -12.59  3.982   0.000   0.000
+45002.00    -12.514 3.955   0.000   0.000
+45003.00    -12.588 3.892   0.000   0.000
+45004.00    -12.694 3.728   0.000   0.000
+45005.00    -12.625 3.501   0.000   0.000
+45006.00    -12.25  3.322   0.000   0.000
+45007.00    -11.6   3.225   0.000   0.000
+45008.00    -10.801 3.104   0.000   0.000
+45009.00    -9.992  2.85    0.000   0.000
+45010.00    -9.307  2.53    0.000   0.000
+45011.00    -8.86   2.346   0.000   0.000
+45012.00    -8.68   2.391   0.000   0.000
+45013.00    -8.688  2.53    0.000   0.000
+45014.00    -8.782  2.559   0.000   0.000
+45015.00    -8.864  2.423   0.000   0.000
+45016.00    -8.799  2.228   0.000   0.000
+45017.00    -8.435  2.072   0.000   0.000
+45018.00    -7.754  1.943   0.000   0.000
+45019.00    -6.945  1.769   0.000   0.000
+45020.00    -6.239  1.526   0.000   0.000
+45021.00    -5.696  1.275   0.000   0.000
+45022.00    -5.22   1.121   0.000   0.000
+45023.00    -4.739  1.122   0.000   0.000
+45024.00    -4.281  1.212   0.000   0.000
+45025.00    -3.909  1.24    0.000   0.000
+45026.00    -3.639  1.098   0.000   0.000
+45027.00    -3.454  0.826   0.000   0.000
+45028.00    -3.341  0.558   0.000   0.000
+45029.00    -3.284  0.397   0.000   0.000
+45030.00    -3.235  0.332   0.000   0.000
+45031.00    -3.108  0.282   0.000   0.000
+45032.00    -2.811  0.183   0.000   0.000
+45033.00    -2.293  0.031   0.000   0.000
+45034.00    -1.605  -0.129  0.000   0.000
+45035.00    -0.894  -0.266  0.000   0.000
+45036.00    -0.304  -0.412  0.000   0.000
+45037.00    0.118   -0.618  0.000   0.000
+45038.00    0.433   -0.858  0.000   0.000
+45039.00    0.698   -1.018  0.000   0.000
+45040.00    0.888   -1.015  0.000   0.000
+45041.00    0.922   -0.91   0.000   0.000
+45042.00    0.794   -0.848  0.000   0.000
+45043.00    0.644   -0.899  0.000   0.000
+45044.00    0.68    -1.011  0.000   0.000
+45045.00    1.02    -1.114  0.000   0.000
+45046.00    1.624   -1.198  0.000   0.000
+45047.00    2.346   -1.297  0.000   0.000
+45048.00    3.017   -1.425  0.000   0.000
+45049.00    3.496   -1.558  0.000   0.000
+45050.00    3.743   -1.648  0.000   0.000
+45051.00    3.857   -1.636  0.000   0.000
+45052.00    4.009   -1.511  0.000   0.000
+45053.00    4.25    -1.368  0.000   0.000
+45054.00    4.443   -1.361  0.000   0.000
+45055.00    4.41    -1.558  0.000   0.000
+45056.00    4.147   -1.856  0.000   0.000
+45057.00    3.827   -2.077  0.000   0.000
+45058.00    3.644   -2.124  0.000   0.000
+45059.00    3.68    -2.037  0.000   0.000
+45060.00    3.93    -1.926  0.000   0.000
+45061.00    4.362   -1.876  0.000   0.000
+45062.00    4.912   -1.902  0.000   0.000
+45063.00    5.442   -1.976  0.000   0.000
+45064.00    5.772   -2.06   0.000   0.000
+45065.00    5.807   -2.127  0.000   0.000
+45066.00    5.636   -2.146  0.000   0.000
+45067.00    5.453   -2.084  0.000   0.000
+45068.00    5.351   -1.949  0.000   0.000
+45069.00    5.237   -1.814  0.000   0.000
+45070.00    5.011   -1.762  0.000   0.000
+45071.00    4.74    -1.807  0.000   0.000
+45072.00    4.59    -1.895  0.000   0.000
+45073.00    4.623   -1.987  0.000   0.000
+45074.00    4.795   -2.084  0.000   0.000
+45075.00    5.101   -2.166  0.000   0.000
+45076.00    5.541   -2.188  0.000   0.000
+45077.00    5.936   -2.151  0.000   0.000
+45078.00    5.998   -2.129  0.000   0.000
+45079.00    5.685   -2.155  0.000   0.000
+45080.00    5.308   -2.147  0.000   0.000
+45081.00    5.144   -2.031  0.000   0.000
+45082.00    5.065   -1.898  0.000   0.000
+45083.00    4.745   -1.932  0.000   0.000
+45084.00    4.135   -2.176  0.000   0.000
+45085.00    3.551   -2.449  0.000   0.000
+45086.00    3.295   -2.541  0.000   0.000
+45087.00    3.354   -2.423  0.000   0.000
+45088.00    3.508   -2.239  0.000   0.000
+45089.00    3.61    -2.129  0.000   0.000
+45090.00    3.683   -2.123  0.000   0.000
+45091.00    3.795   -2.18   0.000   0.000
+45092.00    3.901   -2.24   0.000   0.000
+45093.00    3.845   -2.244  0.000   0.000
+45094.00    3.538   -2.138  0.000   0.000
+45095.00    3.079   -1.92   0.000   0.000
+45096.00    2.657   -1.688  0.000   0.000
+45097.00    2.348   -1.583  0.000   0.000
+45098.00    2.102   -1.664  0.000   0.000
+45099.00    1.894   -1.848  0.000   0.000
+45100.00    1.747   -2.008  0.000   0.000
+45101.00    1.624   -2.115  0.000   0.000
+45102.00    1.471   -2.224  0.000   0.000
+45103.00    1.397   -2.327  0.000   0.000
+45104.00    1.589   -2.32   0.000   0.000
+45105.00    1.948   -2.17   0.000   0.000
+45106.00    2.051   -2.026  0.000   0.000
+45107.00    1.647   -2.047  0.000   0.000
+45108.00    1.008   -2.166  0.000   0.000
+45109.00    0.566   -2.165  0.000   0.000
+45110.00    0.336   -1.992  0.000   0.000
+45111.00    -0.016  -1.857  0.000   0.000
+45112.00    -0.591  -1.947  0.000   0.000
+45113.00    -1.049  -2.173  0.000   0.000
+45114.00    -1.033  -2.294  0.000   0.000
+45115.00    -0.595  -2.234  0.000   0.000
+45116.00    -0.118  -2.129  0.000   0.000
+45117.00    0.08    -2.104  0.000   0.000
+45118.00    -0.009  -2.13   0.000   0.000
+45119.00    -0.151  -2.127  0.000   0.000
+45120.00    -0.128  -2.086  0.000   0.000
+45121.00    0.03    -2.033  0.000   0.000
+45122.00    0.08    -1.932  0.000   0.000
+45123.00    -0.132  -1.739  0.000   0.000
+45124.00    -0.484  -1.527  0.000   0.000
+45125.00    -0.716  -1.464  0.000   0.000
+45126.00    -0.705  -1.624  0.000   0.000
+45127.00    -0.509  -1.877  0.000   0.000
+45128.00    -0.251  -2.03   0.000   0.000
+45129.00    -0.066  -2.039  0.000   0.000
+45130.00    -0.03   -2.022  0.000   0.000
+45131.00    -0.037  -2.051  0.000   0.000
+45132.00    0.165   -2.031  0.000   0.000
+45133.00    0.637   -1.869  0.000   0.000
+45134.00    1.066   -1.662  0.000   0.000
+45135.00    1.111   -1.606  0.000   0.000
+45136.00    0.844   -1.717  0.000   0.000
+45137.00    0.631   -1.788  0.000   0.000
+45138.00    0.622   -1.683  0.000   0.000
+45139.00    0.644   -1.526  0.000   0.000
+45140.00    0.59    -1.512  0.000   0.000
+45141.00    0.653   -1.599  0.000   0.000
+45142.00    1.058   -1.57   0.000   0.000
+45143.00    1.797   -1.4    0.000   0.000
+45144.00    2.571   -1.255  0.000   0.000
+45145.00    3.028   -1.219  0.000   0.000
+45146.00    3.035   -1.165  0.000   0.000
+45147.00    2.772   -0.945  0.000   0.000
+45148.00    2.601   -0.617  0.000   0.000
+45149.00    2.729   -0.363  0.000   0.000
+45150.00    2.979   -0.237  0.000   0.000
+45151.00    3.013   -0.13   0.000   0.000
+45152.00    2.769   0.029   0.000   0.000
+45153.00    2.524   0.152   0.000   0.000
+45154.00    2.531   0.134   0.000   0.000
+45155.00    2.763   0.036   0.000   0.000
+45156.00    3.038   0.032   0.000   0.000
+45157.00    3.216   0.196   0.000   0.000
+45158.00    3.242   0.421   0.000   0.000
+45159.00    3.147   0.577   0.000   0.000
+45160.00    3.069   0.674   0.000   0.000
+45161.00    3.146   0.81    0.000   0.000
+45162.00    3.308   1.000   0.000   0.000
+45163.00    3.322   1.143   0.000   0.000
+45164.00    3.066   1.174   0.000   0.000
+45165.00    2.652   1.165   0.000   0.000
+45166.00    2.252   1.201   0.000   0.000
+45167.00    1.939   1.243   0.000   0.000
+45168.00    1.762   1.202   0.000   0.000
+45169.00    1.809   1.124   0.000   0.000
+45170.00    2.115   1.14    0.000   0.000
+45171.00    2.576   1.251   0.000   0.000
+45172.00    3.015   1.289   0.000   0.000
+45173.00    3.258   1.167   0.000   0.000
+45174.00    3.166   1.055   0.000   0.000
+45175.00    2.752   1.168   0.000   0.000
+45176.00    2.278   1.463   0.000   0.000
+45177.00    2.06    1.665   0.000   0.000
+45178.00    2.12    1.61    0.000   0.000
+45179.00    2.177   1.421   0.000   0.000
+45180.00    2.038   1.305   0.000   0.000
+45181.00    1.831   1.304   0.000   0.000
+45182.00    1.765   1.300   0.000   0.000
+45183.00    1.839   1.224   0.000   0.000
+45184.00    1.923   1.147   0.000   0.000
+45185.00    1.976   1.174   0.000   0.000
+45186.00    2.028   1.306   0.000   0.000
+45187.00    2.047   1.448   0.000   0.000
+45188.00    1.981   1.514   0.000   0.000
+45189.00    1.883   1.505   0.000   0.000
+45190.00    1.849   1.474   0.000   0.000
+45191.00    1.848   1.461   0.000   0.000
+45192.00    1.724   1.462   0.000   0.000
+45193.00    1.381   1.448   0.000   0.000
+45194.00    0.904   1.384   0.000   0.000
+45195.00    0.507   1.249   0.000   0.000
+45196.00    0.384   1.071   0.000   0.000
+45197.00    0.57    0.959   0.000   0.000
+45198.00    0.904   1.019   0.000   0.000
+45199.00    1.17    1.205   0.000   0.000
+45200.00    1.277   1.32    0.000   0.000
+45201.00    1.264   1.234   0.000   0.000
+45202.00    1.135   1.063   0.000   0.000
+45203.00    0.83    1.033   0.000   0.000
+45204.00    0.396   1.178   0.000   0.000
+45205.00    0.036   1.281   0.000   0.000
+45206.00    -0.097  1.151   0.000   0.000
+45207.00    -0.065  0.861   0.000   0.000
+45208.00    -0.017  0.643   0.000   0.000
+45209.00    0.000   0.609   0.000   0.000
+45210.00    0.012   0.649   0.000   0.000
+45211.00    -0.004  0.607   0.000   0.000
+45212.00    -0.075  0.462   0.000   0.000
+45213.00    -0.127  0.337   0.000   0.000
+45214.00    -0.065  0.355   0.000   0.000
+45215.00    0.056   0.51    0.000   0.000
+45216.00    0.077   0.668   0.000   0.000
+45217.00    -0.056  0.683   0.000   0.000
+45218.00    -0.235  0.538   0.000   0.000
+45219.00    -0.366  0.35    0.000   0.000
+45220.00    -0.506  0.246   0.000   0.000
+45221.00    -0.771  0.237   0.000   0.000
+45222.00    -1.15   0.232   0.000   0.000
+45223.00    -1.461  0.159   0.000   0.000
+45224.00    -1.508  0.046   0.000   0.000
+45225.00    -1.266  -0.001  0.000   0.000
+45226.00    -0.933  0.100   0.000   0.000
+45227.00    -0.758  0.311   0.000   0.000
+45228.00    -0.827  0.484   0.000   0.000
+45229.00    -1.028  0.493   0.000   0.000
+45230.00    -1.222  0.368   0.000   0.000
+45231.00    -1.398  0.256   0.000   0.000
+45232.00    -1.624  0.231   0.000   0.000
+45233.00    -1.892  0.198   0.000   0.000
+45234.00    -2.087  0.037   0.000   0.000
+45235.00    -2.092  -0.209  0.000   0.000
+45236.00    -1.916  -0.369  0.000   0.000
+45237.00    -1.687  -0.357  0.000   0.000
+45238.00    -1.556  -0.277  0.000   0.000
+45239.00    -1.582  -0.292  0.000   0.000
+45240.00    -1.693  -0.439  0.000   0.000
+45241.00    -1.764  -0.591  0.000   0.000
+45242.00    -1.75   -0.588  0.000   0.000
+45243.00    -1.725  -0.385  0.000   0.000
+45244.00    -1.793  -0.107  0.000   0.000
+45245.00    -1.973  0.036   0.000   0.000
+45246.00    -2.195  -0.075  0.000   0.000
+45247.00    -2.395  -0.355  0.000   0.000
+45248.00    -2.569  -0.591  0.000   0.000
+45249.00    -2.756  -0.641  0.000   0.000
+45250.00    -2.958  -0.535  0.000   0.000
+45251.00    -3.107  -0.404  0.000   0.000
+45252.00    -3.109  -0.327  0.000   0.000
+45253.00    -2.946  -0.287  0.000   0.000
+45254.00    -2.724  -0.228  0.000   0.000
+45255.00    -2.612  -0.132  0.000   0.000
+45256.00    -2.717  -0.039  0.000   0.000
+45257.00    -2.995  0.004   0.000   0.000
+45258.00    -3.294  -0.01   0.000   0.000
+45259.00    -3.496  -0.038  0.000   0.000
+45260.00    -3.609  -0.063  0.000   0.000
+45261.00    -3.72   -0.132  0.000   0.000
+45262.00    -3.832  -0.279  0.000   0.000
+45263.00    -3.83   -0.435  0.000   0.000
+45264.00    -3.641  -0.47   0.000   0.000
+45265.00    -3.387  -0.352  0.000   0.000
+45266.00    -3.281  -0.199  0.000   0.000
+45267.00    -3.367  -0.142  0.000   0.000
+45268.00    -3.488  -0.18   0.000   0.000
+45269.00    -3.532  -0.197  0.000   0.000
+45270.00    -3.589  -0.089  0.000   0.000
+45271.00    -3.792  0.167   0.000   0.000
+45272.00    -4.107  0.51    0.000   0.000
+45273.00    -4.388  0.81    0.000   0.000
+45274.00    -4.575  0.915   0.000   0.000
+45275.00    -4.717  0.79    0.000   0.000
+45276.00    -4.839  0.589   0.000   0.000
+45277.00    -4.908  0.543   0.000   0.000
+45278.00    -4.922  0.748   0.000   0.000
+45279.00    -4.938  1.082   0.000   0.000
+45280.00    -4.983  1.351   0.000   0.000
+45281.00    -5.018  1.471   0.000   0.000
+45282.00    -5.008  1.494   0.000   0.000
+45283.00    -4.993  1.506   0.000   0.000
+45284.00    -5.075  1.546   0.000   0.000
+45285.00    -5.314  1.621   0.000   0.000
+45286.00    -5.654  1.74    0.000   0.000
+45287.00    -5.943  1.898   0.000   0.000
+45288.00    -6.068  2.039   0.000   0.000
+45289.00    -6.049  2.077   0.000   0.000
+45290.00    -5.965  1.994   0.000   0.000
+45291.00    -5.818  1.901   0.000   0.000
+45292.00    -5.576  1.941   0.000   0.000
+45293.00    -5.332  2.13    0.000   0.000
+45294.00    -5.247  2.332   0.000   0.000
+45295.00    -5.301  2.436   0.000   0.000
+45296.00    -5.281  2.475   0.000   0.000
+45297.00    -5.094  2.547   0.000   0.000
+45298.00    -4.936  2.672   0.000   0.000
+45299.00    -5.003  2.816   0.000   0.000
+45300.00    -5.185  3.002   0.000   0.000
+45301.00    -5.231  3.272   0.000   0.000
+45302.00    -5.108  3.537   0.000   0.000
+45303.00    -4.961  3.616   0.000   0.000
+45304.00    -4.801  3.471   0.000   0.000
+45305.00    -4.454  3.306   0.000   0.000
+45306.00    -3.859  3.343   0.000   0.000
+45307.00    -3.2    3.557   0.000   0.000
+45308.00    -2.684  3.729   0.000   0.000
+45309.00    -2.326  3.721   0.000   0.000
+45310.00    -2.005  3.607   0.000   0.000
+45311.00    -1.641  3.517   0.000   0.000
+45312.00    -1.257  3.475   0.000   0.000
+45313.00    -0.929  3.433   0.000   0.000
+45314.00    -0.697  3.388   0.000   0.000
+45315.00    -0.486  3.378   0.000   0.000
+45316.00    -0.134  3.37    0.000   0.000
+45317.00    0.468   3.255   0.000   0.000
+45318.00    1.276   2.983   0.000   0.000
+45319.00    2.18    2.663   0.000   0.000
+45320.00    3.089   2.463   0.000   0.000
+45321.00    3.871   2.424   0.000   0.000
+45322.00    4.429   2.414   0.000   0.000
+45323.00    4.819   2.32    0.000   0.000
+45324.00    5.242   2.183   0.000   0.000
+45325.00    5.787   2.088   0.000   0.000
+45326.00    6.278   2.012   0.000   0.000
+45327.00    6.528   1.88    0.000   0.000
+45328.00    6.624   1.758   0.000   0.000
+45329.00    6.753   1.819   0.000   0.000
+45330.00    6.848   2.07    0.000   0.000
+45331.00    6.705   2.253   0.000   0.000
+45332.00    6.417   2.141   0.000   0.000
+45333.00    6.398   1.833   0.000   0.000
+45334.00    6.899   1.624   0.000   0.000
+45335.00    7.695   1.63    0.000   0.000
+45336.00    8.358   1.688   0.000   0.000
+45337.00    8.666   1.656   0.000   0.000
+45338.00    8.662   1.614   0.000   0.000
+45339.00    8.483   1.702   0.000   0.000
+45340.00    8.244   1.872   0.000   0.000
+45341.00    7.987   1.95    0.000   0.000
+45342.00    7.667   1.869   0.000   0.000
+45343.00    7.247   1.739   0.000   0.000
+45344.00    6.84    1.654   0.000   0.000
+45345.00    6.649   1.567   0.000   0.000
+45346.00    6.733   1.401   0.000   0.000
+45347.00    6.936   1.211   0.000   0.000
+45348.00    7.065   1.14    0.000   0.000
+45349.00    7.029   1.229   0.000   0.000
+45350.00    6.829   1.357   0.000   0.000
+45351.00    6.521   1.397   0.000   0.000
+45352.00    6.219   1.362   0.000   0.000
+45353.00    6.003   1.332   0.000   0.000
+45354.00    5.817   1.307   0.000   0.000
+45355.00    5.568   1.223   0.000   0.000
+45356.00    5.29    1.128   0.000   0.000
+45357.00    5.029   1.193   0.000   0.000
+45358.00    4.633   1.467   0.000   0.000
+45359.00    3.886   1.732   0.000   0.000
+45360.00    2.925   1.715   0.000   0.000
+45361.00    2.273   1.438   0.000   0.000
+45362.00    2.332   1.183   0.000   0.000
+45363.00    2.972   1.139   0.000   0.000
+45364.00    3.714   1.214   0.000   0.000
+45365.00    4.169   1.269   0.000   0.000
+45366.00    4.222   1.363   0.000   0.000
+45367.00    3.959   1.628   0.000   0.000
+45368.00    3.572   1.993   0.000   0.000
+45369.00    3.24    2.200   0.000   0.000
+45370.00    2.983   2.117   0.000   0.000
+45371.00    2.712   1.881   0.000   0.000
+45372.00    2.474   1.704   0.000   0.000
+45373.00    2.501   1.638   0.000   0.000
+45374.00    2.928   1.601   0.000   0.000
+45375.00    3.581   1.571   0.000   0.000
+45376.00    4.159   1.624   0.000   0.000
+45377.00    4.536   1.808   0.000   0.000
+45378.00    4.766   2.038   0.000   0.000
+45379.00    4.919   2.186   0.000   0.000
+45380.00    5.026   2.203   0.000   0.000
+45381.00    5.132   2.14    0.000   0.000
+45382.00    5.281   2.053   0.000   0.000
+45383.00    5.469   1.959   0.000   0.000
+45384.00    5.676   1.888   0.000   0.000
+45385.00    5.865   1.908   0.000   0.000
+45386.00    5.933   2.024   0.000   0.000
+45387.00    5.77    2.106   0.000   0.000
+45388.00    5.459   1.996   0.000   0.000
+45389.00    5.311   1.711   0.000   0.000
+45390.00    5.58    1.453   0.000   0.000
+45391.00    6.197   1.363   0.000   0.000
+45392.00    6.862   1.369   0.000   0.000
+45393.00    7.307   1.338   0.000   0.000
+45394.00    7.414   1.296   0.000   0.000
+45395.00    7.194   1.378   0.000   0.000
+45396.00    6.767   1.568   0.000   0.000
+45397.00    6.298   1.65    0.000   0.000
+45398.00    5.851   1.462   0.000   0.000
+45399.00    5.385   1.098   0.000   0.000
+45400.00    4.949   0.789   0.000   0.000
+45401.00    4.763   0.637   0.000   0.000
+45402.00    4.963   0.572   0.000   0.000
+45403.00    5.363   0.51    0.000   0.000
+45404.00    5.604   0.472   0.000   0.000
+45405.00    5.52    0.516   0.000   0.000
+45406.00    5.211   0.628   0.000   0.000
+45407.00    4.824   0.709   0.000   0.000
+45408.00    4.419   0.656   0.000   0.000
+45409.00    4.034   0.448   0.000   0.000
+45410.00    3.722   0.156   0.000   0.000
+45411.00    3.482   -0.105  0.000   0.000
+45412.00    3.245   -0.262  0.000   0.000
+45413.00    2.965   -0.321  0.000   0.000
+45414.00    2.69    -0.35   0.000   0.000
+45415.00    2.519   -0.435  0.000   0.000
+45416.00    2.531   -0.609  0.000   0.000
+45417.00    2.738   -0.816  0.000   0.000
+45418.00    3.049   -0.948  0.000   0.000
+45419.00    3.301   -0.955  0.000   0.000
+45420.00    3.38    -0.916  0.000   0.000
+45421.00    3.304   -0.942  0.000   0.000
+45422.00    3.171   -1.028  0.000   0.000
+45423.00    3.035   -1.055  0.000   0.000
+45424.00    2.891   -0.968  0.000   0.000
+45425.00    2.723   -0.881  0.000   0.000
+45426.00    2.532   -0.931  0.000   0.000
+45427.00    2.344   -1.1    0.000   0.000
+45428.00    2.274   -1.238  0.000   0.000
+45429.00    2.501   -1.256  0.000   0.000
+45430.00    3.093   -1.208  0.000   0.000
+45431.00    3.864   -1.184  0.000   0.000
+45432.00    4.481   -1.184  0.000   0.000
+45433.00    4.733   -1.138  0.000   0.000
+45434.00    4.664   -1.005  0.000   0.000
+45435.00    4.461   -0.834  0.000   0.000
+45436.00    4.29    -0.733  0.000   0.000
+45437.00    4.235   -0.79   0.000   0.000
+45438.00    4.287   -0.994  0.000   0.000
+45439.00    4.358   -1.231  0.000   0.000
+45440.00    4.341   -1.372  0.000   0.000
+45441.00    4.226   -1.383  0.000   0.000
+45442.00    4.15    -1.34   0.000   0.000
+45443.00    4.301   -1.327  0.000   0.000
+45444.00    4.772   -1.361  0.000   0.000
+45445.00    5.469   -1.391  0.000   0.000
+45446.00    6.141   -1.364  0.000   0.000
+45447.00    6.524   -1.273  0.000   0.000
+45448.00    6.51    -1.164  0.000   0.000
+45449.00    6.219   -1.098  0.000   0.000
+45450.00    5.91    -1.088  0.000   0.000
+45451.00    5.781   -1.08   0.000   0.000
+45452.00    5.828   -1.028  0.000   0.000
+45453.00    5.897   -0.971  0.000   0.000
+45454.00    5.863   -0.981  0.000   0.000
+45455.00    5.755   -1.059  0.000   0.000
+45456.00    5.725   -1.129  0.000   0.000
+45457.00    5.902   -1.151  0.000   0.000
+45458.00    6.293   -1.169  0.000   0.000
+45459.00    6.795   -1.234  0.000   0.000
+45460.00    7.231   -1.316  0.000   0.000
+45461.00    7.403   -1.342  0.000   0.000
+45462.00    7.199   -1.282  0.000   0.000
+45463.00    6.714   -1.164  0.000   0.000
+45464.00    6.22    -1.041  0.000   0.000
+45465.00    5.938   -0.976  0.000   0.000
+45466.00    5.837   -1.031  0.000   0.000
+45467.00    5.722   -1.214  0.000   0.000
+45468.00    5.489   -1.438  0.000   0.000
+45469.00    5.232   -1.581  0.000   0.000
+45470.00    5.105   -1.601  0.000   0.000
+45471.00    5.172   -1.554  0.000   0.000
+45472.00    5.391   -1.518  0.000   0.000
+45473.00    5.686   -1.512  0.000   0.000
+45474.00    5.96    -1.509  0.000   0.000
+45475.00    6.076   -1.476  0.000   0.000
+45476.00    5.901   -1.406  0.000   0.000
+45477.00    5.417   -1.308  0.000   0.000
+45478.00    4.793   -1.199  0.000   0.000
+45479.00    4.289   -1.104  0.000   0.000
+45480.00    4.048   -1.058  0.000   0.000
+45481.00    3.977   -1.099  0.000   0.000
+45482.00    3.888   -1.223  0.000   0.000
+45483.00    3.71    -1.36   0.000   0.000
+45484.00    3.515   -1.429  0.000   0.000
+45485.00    3.361   -1.439  0.000   0.000
+45486.00    3.238   -1.472  0.000   0.000
+45487.00    3.174   -1.561  0.000   0.000
+45488.00    3.22    -1.625  0.000   0.000
+45489.00    3.258   -1.583  0.000   0.000
+45490.00    2.994   -1.463  0.000   0.000
+45491.00    2.308   -1.346  0.000   0.000
+45492.00    1.481   -1.231  0.000   0.000
+45493.00    0.902   -1.065  0.000   0.000
+45494.00    0.616   -0.892  0.000   0.000
+45495.00    0.368   -0.857  0.000   0.000
+45496.00    0.041   -1.014  0.000   0.000
+45497.00    -0.175  -1.218  0.000   0.000
+45498.00    -0.095  -1.275  0.000   0.000
+45499.00    0.171   -1.159  0.000   0.000
+45500.00    0.351   -0.995  0.000   0.000
+45501.00    0.322   -0.882  0.000   0.000
+45502.00    0.179   -0.795  0.000   0.000
+45503.00    0.052   -0.673  0.000   0.000
+45504.00    -0.072  -0.5    0.000   0.000
+45505.00    -0.322  -0.303  0.000   0.000
+45506.00    -0.773  -0.093  0.000   0.000
+45507.00    -1.306  0.107   0.000   0.000
+45508.00    -1.693  0.232   0.000   0.000
+45509.00    -1.824  0.204   0.000   0.000
+45510.00    -1.806  0.051   0.000   0.000
+45511.00    -1.807  -0.077  0.000   0.000
+45512.00    -1.913  -0.039  0.000   0.000
+45513.00    -2.152  0.137   0.000   0.000
+45514.00    -2.517  0.286   0.000   0.000
+45515.00    -2.883  0.325   0.000   0.000
+45516.00    -3.047  0.353   0.000   0.000
+45517.00    -3.031  0.491   0.000   0.000
+45518.00    -3.2    0.682   0.000   0.000
+45519.00    -3.864  0.772   0.000   0.000
+45520.00    -4.842  0.749   0.000   0.000
+45521.00    -5.649  0.771   0.000   0.000
+45522.00    -6.088  0.904   0.000   0.000
+45523.00    -6.368  0.986   0.000   0.000
+45524.00    -6.657  0.846   0.000   0.000
+45525.00    -6.806  0.57    0.000   0.000
+45526.00    -6.648  0.403   0.000   0.000
+45527.00    -6.338  0.433   0.000   0.000
+45528.00    -6.223  0.515   0.000   0.000
+45529.00    -6.469  0.521   0.000   0.000
+45530.00    -6.938  0.507   0.000   0.000
+45531.00    -7.368  0.577   0.000   0.000
+45532.00    -7.596  0.692   0.000   0.000
+45533.00    -7.668  0.726   0.000   0.000
+45534.00    -7.777  0.651   0.000   0.000
+45535.00    -8.041  0.552   0.000   0.000
+45536.00    -8.338  0.465   0.000   0.000
+45537.00    -8.428  0.317   0.000   0.000
+45538.00    -8.23   0.073   0.000   0.000
+45539.00    -7.898  -0.142  0.000   0.000
+45540.00    -7.626  -0.156  0.000   0.000
+45541.00    -7.49   0.029   0.000   0.000
+45542.00    -7.454  0.215   0.000   0.000
+45543.00    -7.386  0.246   0.000   0.000
+45544.00    -7.111  0.186   0.000   0.000
+45545.00    -6.616  0.188   0.000   0.000
+45546.00    -6.19   0.25    0.000   0.000
+45547.00    -6.177  0.209   0.000   0.000
+45548.00    -6.542  -0.001  0.000   0.000
+45549.00    -6.882  -0.229  0.000   0.000
+45550.00    -6.892  -0.322  0.000   0.000
+45551.00    -6.628  -0.342  0.000   0.000
+45552.00    -6.264  -0.443  0.000   0.000
+45553.00    -5.827  -0.602  0.000   0.000
+45554.00    -5.313  -0.642  0.000   0.000
+45555.00    -4.876  -0.522  0.000   0.000
+45556.00    -4.724  -0.418  0.000   0.000
+45557.00    -4.903  -0.461  0.000   0.000
+45558.00    -5.306  -0.527  0.000   0.000
+45559.00    -5.779  -0.436  0.000   0.000
+45560.00    -6.162  -0.247  0.000   0.000
+45561.00    -6.358  -0.203  0.000   0.000
+45562.00    -6.459  -0.398  0.000   0.000
+45563.00    -6.683  -0.653  0.000   0.000
+45564.00    -7.1    -0.762  0.000   0.000
+45565.00    -7.513  -0.734  0.000   0.000
+45566.00    -7.732  -0.703  0.000   0.000
+45567.00    -7.819  -0.687  0.000   0.000
+45568.00    -7.973  -0.566  0.000   0.000
+45569.00    -8.275  -0.282  0.000   0.000
+45570.00    -8.654  0.039   0.000   0.000
+45571.00    -9.026  0.229   0.000   0.000
+45572.00    -9.346  0.27    0.000   0.000
+45573.00    -9.614  0.285   0.000   0.000
+45574.00    -9.938  0.341   0.000   0.000
+45575.00    -10.5   0.368   0.000   0.000
+45576.00    -11.346 0.286   0.000   0.000
+45577.00    -12.265 0.144   0.000   0.000
+45578.00    -12.966 0.058   0.000   0.000
+45579.00    -13.323 0.065   0.000   0.000
+45580.00    -13.395 0.129   0.000   0.000
+45581.00    -13.328 0.271   0.000   0.000
+45582.00    -13.32  0.558   0.000   0.000
+45583.00    -13.546 0.923   0.000   0.000
+45584.00    -14.009 1.136   0.000   0.000
+45585.00    -14.524 1.062   0.000   0.000
+45586.00    -14.948 0.868   0.000   0.000
+45587.00    -15.305 0.822   0.000   0.000
+45588.00    -15.634 0.936   0.000   0.000
+45589.00    -15.836 0.95    0.000   0.000
+45590.00    -15.828 0.695   0.000   0.000
+45591.00    -15.706 0.335   0.000   0.000
+45592.00    -15.598 0.157   0.000   0.000
+45593.00    -15.453 0.226   0.000   0.000
+45594.00    -15.133 0.358   0.000   0.000
+45595.00    -14.655 0.394   0.000   0.000
+45596.00    -14.168 0.371   0.000   0.000
+45597.00    -13.71  0.412   0.000   0.000
+45598.00    -13.188 0.531   0.000   0.000
+45599.00    -12.558 0.618   0.000   0.000
+45600.00    -11.888 0.566   0.000   0.000
+45601.00    -11.219 0.383   0.000   0.000
+45602.00    -10.54  0.159   0.000   0.000
+45603.00    -9.876  -0.035  0.000   0.000
+45604.00    -9.313  -0.193  0.000   0.000
+45605.00    -8.87   -0.335  0.000   0.000
+45606.00    -8.422  -0.457  0.000   0.000
+45607.00    -7.793  -0.523  0.000   0.000
+45608.00    -6.93   -0.475  0.000   0.000
+45609.00    -5.999  -0.251  0.000   0.000
+45610.00    -5.303  0.157   0.000   0.000
+45611.00    -5.058  0.62    0.000   0.000
+45612.00    -5.177  0.900   0.000   0.000
+45613.00    -5.331  0.866   0.000   0.000
+45614.00    -5.286  0.651   0.000   0.000
+45615.00    -5.122  0.527   0.000   0.000
+45616.00    -5.047  0.595   0.000   0.000
+45617.00    -5.099  0.687   0.000   0.000
+45618.00    -5.137  0.623   0.000   0.000
+45619.00    -5.069  0.474   0.000   0.000
+45620.00    -4.933  0.464   0.000   0.000
+45621.00    -4.785  0.667   0.000   0.000
+45622.00    -4.643  0.916   0.000   0.000
+45623.00    -4.559  1.02    0.000   0.000
+45624.00    -4.605  0.984   0.000   0.000
+45625.00    -4.766  0.977   0.000   0.000
+45626.00    -4.944  1.123   0.000   0.000
+45627.00    -5.109  1.374   0.000   0.000
+45628.00    -5.325  1.562   0.000   0.000
+45629.00    -5.613  1.561   0.000   0.000
+45630.00    -5.883  1.395   0.000   0.000
+45631.00    -6.047  1.211   0.000   0.000
+45632.00    -6.141  1.135   0.000   0.000
+45633.00    -6.246  1.169   0.000   0.000
+45634.00    -6.334  1.23    0.000   0.000
+45635.00    -6.275  1.268   0.000   0.000
+45636.00    -5.994  1.331   0.000   0.000
+45637.00    -5.605  1.503   0.000   0.000
+45638.00    -5.371  1.804   0.000   0.000
+45639.00    -5.491  2.14    0.000   0.000
+45640.00    -5.903  2.359   0.000   0.000
+45641.00    -6.312  2.371   0.000   0.000
+45642.00    -6.449  2.236   0.000   0.000
+45643.00    -6.303  2.12    0.000   0.000
+45644.00    -6.073  2.122   0.000   0.000
+45645.00    -5.911  2.184   0.000   0.000
+45646.00    -5.773  2.201   0.000   0.000
+45647.00    -5.517  2.193   0.000   0.000
+45648.00    -5.078  2.275   0.000   0.000
+45649.00    -4.537  2.479   0.000   0.000
+45650.00    -4.027  2.667   0.000   0.000
+45651.00    -3.631  2.698   0.000   0.000
+45652.00    -3.335  2.603   0.000   0.000
+45653.00    -3.084  2.56    0.000   0.000
+45654.00    -2.85   2.708   0.000   0.000
+45655.00    -2.642  3.014   0.000   0.000
+45656.00    -2.452  3.303   0.000   0.000
+45657.00    -2.233  3.392   0.000   0.000
+45658.00    -1.918  3.227   0.000   0.000
+45659.00    -1.491  2.924   0.000   0.000
+45660.00    -1.004  2.688   0.000   0.000
+45661.00    -0.538  2.643   0.000   0.000
+45662.00    -0.136  2.751   0.000   0.000
+45663.00    0.206   2.886   0.000   0.000
+45664.00    0.500   2.984   0.000   0.000
+45665.00    0.717   3.07    0.000   0.000
+45666.00    0.771   3.192   0.000   0.000
+45667.00    0.573   3.349   0.000   0.000
+45668.00    0.138   3.504   0.000   0.000
+45669.00    -0.374  3.619   0.000   0.000
+45670.00    -0.74   3.696   0.000   0.000
+45671.00    -0.826  3.762   0.000   0.000
+45672.00    -0.682  3.829   0.000   0.000
+45673.00    -0.472  3.872   0.000   0.000
+45674.00    -0.302  3.875   0.000   0.000
+45675.00    -0.132  3.89    0.000   0.000
+45676.00    0.122   3.994   0.000   0.000
+45677.00    0.432   4.171   0.000   0.000
+45678.00    0.678   4.300   0.000   0.000
+45679.00    0.821   4.289   0.000   0.000
+45680.00    0.948   4.206   0.000   0.000
+45681.00    1.109   4.207   0.000   0.000
+45682.00    1.200   4.376   0.000   0.000
+45683.00    1.11    4.663   0.000   0.000
+45684.00    0.904   4.956   0.000   0.000
+45685.00    0.748   5.139   0.000   0.000
+45686.00    0.708   5.107   0.000   0.000
+45687.00    0.744   4.827   0.000   0.000
+45688.00    0.883   4.42    0.000   0.000
+45689.00    1.22    4.106   0.000   0.000
+45690.00    1.725   4.012   0.000   0.000
+45691.00    2.184   4.053   0.000   0.000
+45692.00    2.392   4.045   0.000   0.000
+45693.00    2.331   3.903   0.000   0.000
+45694.00    2.113   3.682   0.000   0.000
+45695.00    1.81    3.48    0.000   0.000
+45696.00    1.414   3.336   0.000   0.000
+45697.00    0.937   3.242   0.000   0.000
+45698.00    0.478   3.184   0.000   0.000
+45699.00    0.198   3.15    0.000   0.000
+45700.00    0.182   3.101   0.000   0.000
+45701.00    0.347   2.996   0.000   0.000
+45702.00    0.515   2.862   0.000   0.000
+45703.00    0.586   2.816   0.000   0.000
+45704.00    0.598   2.975   0.000   0.000
+45705.00    0.606   3.323   0.000   0.000
+45706.00    0.619   3.691   0.000   0.000
+45707.00    0.701   3.943   0.000   0.000
+45708.00    0.998   4.102   0.000   0.000
+45709.00    1.545   4.239   0.000   0.000
+45710.00    2.145   4.321   0.000   0.000
+45711.00    2.564   4.283   0.000   0.000
+45712.00    2.823   4.147   0.000   0.000
+45713.00    3.075   4.000   0.000   0.000
+45714.00    3.274   3.828   0.000   0.000
+45715.00    3.245   3.487   0.000   0.000
+45716.00    3.103   2.931   0.000   0.000
+45717.00    3.236   2.387   0.000   0.000
+45718.00    3.792   2.171   0.000   0.000
+45719.00    4.429   2.34    0.000   0.000
+45720.00    4.676   2.656   0.000   0.000
+45721.00    4.42    2.896   0.000   0.000
+45722.00    3.921   3.067   0.000   0.000
+45723.00    3.467   3.301   0.000   0.000
+45724.00    3.155   3.642   0.000   0.000
+45725.00    2.967   4.032   0.000   0.000
+45726.00    2.892   4.395   0.000   0.000
+45727.00    3.013   4.698   0.000   0.000
+45728.00    3.459   4.876   0.000   0.000
+45729.00    4.264   4.798   0.000   0.000
+45730.00    5.271   4.396   0.000   0.000
+45731.00    6.169   3.835   0.000   0.000
+45732.00    6.729   3.352   0.000   0.000
+45733.00    6.862   3.04    0.000   0.000
+45734.00    6.524   2.835   0.000   0.000
+45735.00    5.700   2.706   0.000   0.000
+45736.00    4.621   2.704   0.000   0.000
+45737.00    3.543   2.888   0.000   0.000
+45738.00    2.534   3.189   0.000   0.000
+45739.00    1.682   3.454   0.000   0.000
+45740.00    1.311   3.656   0.000   0.000
+45741.00    1.545   3.921   0.000   0.000
+45742.00    2.123   4.256   0.000   0.000
+45743.00    2.619   4.401   0.000   0.000
+45744.00    2.911   4.101   0.000   0.000
+45745.00    3.276   3.457   0.000   0.000
+45746.00    3.991   2.879   0.000   0.000
+45747.00    4.812   2.613   0.000   0.000
+45748.00    5.195   2.518   0.000   0.000
+45749.00    4.947   2.357   0.000   0.000
+45750.00    4.377   2.144   0.000   0.000
+45751.00    3.871   2.033   0.000   0.000
+45752.00    3.602   2.053   0.000   0.000
+45753.00    3.549   2.085   0.000   0.000
+45754.00    3.615   2.083   0.000   0.000
+45755.00    3.700   2.145   0.000   0.000
+45756.00    3.473   2.222   0.000   0.000
+45757.00    3.065   2.233   0.000   0.000
+45758.00    2.748   2.146   0.000   0.000
+45759.00    2.557   2.054   0.000   0.000
+45760.00    2.482   2.132   0.000   0.000
+45761.00    2.507   2.395   0.000   0.000
+45762.00    2.658   2.659   0.000   0.000
+45763.00    2.971   2.74    0.000   0.000
+45764.00    3.409   2.639   0.000   0.000
+45765.00    3.855   2.468   0.000   0.000
+45766.00    4.17    2.284   0.000   0.000
+45767.00    4.258   2.043   0.000   0.000
+45768.00    4.195   1.769   0.000   0.000
+45769.00    4.164   1.629   0.000   0.000
+45770.00    4.182   1.733   0.000   0.000
+45771.00    4.088   1.91    0.000   0.000
+45772.00    3.894   1.892   0.000   0.000
+45773.00    3.94    1.66    0.000   0.000
+45774.00    4.51    1.46    0.000   0.000
+45775.00    5.415   1.448   0.000   0.000
+45776.00    6.114   1.493   0.000   0.000
+45777.00    6.267   1.367   0.000   0.000
+45778.00    5.933   1.06    0.000   0.000
+45779.00    5.325   0.756   0.000   0.000
+45780.00    4.562   0.53    0.000   0.000
+45781.00    3.727   0.259   0.000   0.000
+45782.00    2.824   -0.121  0.000   0.000
+45783.00    1.819   -0.434  0.000   0.000
+45784.00    0.843   -0.457  0.000   0.000
+45785.00    0.23    -0.167  0.000   0.000
+45786.00    0.162   0.266   0.000   0.000
+45787.00    0.455   0.734   0.000   0.000
+45788.00    0.741   1.27    0.000   0.000
+45789.00    0.859   1.874   0.000   0.000
+45790.00    0.942   2.386   0.000   0.000
+45791.00    1.186   2.587   0.000   0.000
+45792.00    1.668   2.395   0.000   0.000
+45793.00    2.373   1.886   0.000   0.000
+45794.00    3.241   1.144   0.000   0.000
+45795.00    4.171   0.165   0.000   0.000
+45796.00    5.044   -0.964  0.000   0.000
+45797.00    5.821   -2.041  0.000   0.000
+45798.00    6.491   -2.846  0.000   0.000
+45799.00    6.949   -3.227  0.000   0.000
+45800.00    7.063   -3.109  0.000   0.000
+45801.00    6.909   -2.583  0.000   0.000
+45802.00    6.623   -1.726  0.000   0.000
+45803.00    6.224   -0.678  0.000   0.000
+45804.00    5.713   0.222   0.000   0.000
+45805.00    5.247   0.592   0.000   0.000
+45806.00    4.967   0.474   0.000   0.000
+45807.00    4.911   0.194   0.000   0.000
+45808.00    5.012   -0.006  0.000   0.000
+45809.00    5.125   -0.07   0.000   0.000
+45810.00    5.088   0.016   0.000   0.000
+45811.00    5.144   0.005   0.000   0.000
+45812.00    5.455   -0.128  0.000   0.000
+45813.00    5.953   -0.199  0.000   0.000
+45814.00    6.565   -0.198  0.000   0.000
+45815.00    6.994   -0.115  0.000   0.000
+45816.00    7.055   0.066   0.000   0.000
+45817.00    6.831   0.348   0.000   0.000
+45818.00    6.676   0.616   0.000   0.000
+45819.00    6.677   0.723   0.000   0.000
+45820.00    6.634   0.603   0.000   0.000
+45821.00    6.501   0.31    0.000   0.000
+45822.00    6.311   -0.013  0.000   0.000
+45823.00    6.039   -0.24   0.000   0.000
+45824.00    5.62    -0.352  0.000   0.000
+45825.00    5.087   -0.411  0.000   0.000
+45826.00    4.643   -0.481  0.000   0.000
+45827.00    4.535   -0.569  0.000   0.000
+45828.00    4.848   -0.625  0.000   0.000
+45829.00    5.448   -0.578  0.000   0.000
+45830.00    6.096   -0.386  0.000   0.000
+45831.00    6.529   -0.088  0.000   0.000
+45832.00    6.635   0.192   0.000   0.000
+45833.00    6.526   0.329   0.000   0.000
+45834.00    6.352   0.31    0.000   0.000
+45835.00    6.125   0.229   0.000   0.000
+45836.00    5.837   0.153   0.000   0.000
+45837.00    5.497   0.028   0.000   0.000
+45838.00    5.139   -0.219  0.000   0.000
+45839.00    4.81    -0.52   0.000   0.000
+45840.00    4.588   -0.705  0.000   0.000
+45841.00    4.521   -0.714  0.000   0.000
+45842.00    4.632   -0.65   0.000   0.000
+45843.00    4.82    -0.62   0.000   0.000
+45844.00    4.832   -0.59   0.000   0.000
+45845.00    4.443   -0.459  0.000   0.000
+45846.00    3.700   -0.213  0.000   0.000
+45847.00    2.843   0.023   0.000   0.000
+45848.00    2.126   0.099   0.000   0.000
+45849.00    1.736   -0.034  0.000   0.000
+45850.00    1.76    -0.289  0.000   0.000
+45851.00    2.069   -0.516  0.000   0.000
+45852.00    2.429   -0.606  0.000   0.000
+45853.00    2.681   -0.562  0.000   0.000
+45854.00    2.81    -0.462  0.000   0.000
+45855.00    2.87    -0.354  0.000   0.000
+45856.00    2.931   -0.229  0.000   0.000
+45857.00    2.935   -0.057  0.000   0.000
+45858.00    2.72    0.139   0.000   0.000
+45859.00    2.185   0.264   0.000   0.000
+45860.00    1.416   0.209   0.000   0.000
+45861.00    0.642   -0.027  0.000   0.000
+45862.00    0.129   -0.356  0.000   0.000
+45863.00    0.024   -0.653  0.000   0.000
+45864.00    0.278   -0.799  0.000   0.000
+45865.00    0.686   -0.8    0.000   0.000
+45866.00    1.028   -0.827  0.000   0.000
+45867.00    1.229   -0.861  0.000   0.000
+45868.00    1.293   -0.847  0.000   0.000
+45869.00    1.249   -0.799  0.000   0.000
+45870.00    1.124   -0.817  0.000   0.000
+45871.00    0.98    -0.935  0.000   0.000
+45872.00    0.849   -1.046  0.000   0.000
+45873.00    0.654   -1.009  0.000   0.000
+45874.00    0.256   -0.8    0.000   0.000
+45875.00    -0.363  -0.521  0.000   0.000
+45876.00    -0.993  -0.319  0.000   0.000
+45877.00    -1.337  -0.268  0.000   0.000
+45878.00    -1.273  -0.359  0.000   0.000
+45879.00    -0.893  -0.549  0.000   0.000
+45880.00    -0.328  -0.761  0.000   0.000
+45881.00    0.317   -0.897  0.000   0.000
+45882.00    0.94    -0.925  0.000   0.000
+45883.00    1.377   -0.895  0.000   0.000
+45884.00    1.422   -0.855  0.000   0.000
+45885.00    0.94    -0.777  0.000   0.000
+45886.00    0.045   -0.625  0.000   0.000
+45887.00    -1.071  -0.404  0.000   0.000
+45888.00    -2.249  -0.166  0.000   0.000
+45889.00    -3.299  0.021   0.000   0.000
+45890.00    -3.991  0.091   0.000   0.000
+45891.00    -4.274  0.014   0.000   0.000
+45892.00    -4.148  -0.212  0.000   0.000
+45893.00    -3.775  -0.546  0.000   0.000
+45894.00    -3.43   -0.882  0.000   0.000
+45895.00    -3.33   -1.071  0.000   0.000
+45896.00    -3.47   -1.037  0.000   0.000
+45897.00    -3.744  -0.851  0.000   0.000
+45898.00    -4.05   -0.669  0.000   0.000
+45899.00    -4.238  -0.566  0.000   0.000
+45900.00    -4.15   -0.465  0.000   0.000
+45901.00    -3.888  -0.259  0.000   0.000
+45902.00    -3.829  0.007   0.000   0.000
+45903.00    -4.258  0.174   0.000   0.000
+45904.00    -5.006  0.163   0.000   0.000
+45905.00    -5.582  0.027   0.000   0.000
+45906.00    -5.734  -0.15   0.000   0.000
+45907.00    -5.627  -0.379  0.000   0.000
+45908.00    -5.503  -0.684  0.000   0.000
+45909.00    -5.402  -0.991  0.000   0.000
+45910.00    -5.267  -1.153  0.000   0.000
+45911.00    -5.078  -0.887  0.000   0.000
+45912.00    -5.046  -0.715  0.000   0.000
+45913.00    -5.231  -0.787  0.000   0.000
+45914.00    -5.508  -0.933  0.000   0.000
+45915.00    -5.788  -0.954  0.000   0.000
+45916.00    -6.044  -0.811  0.000   0.000
+45917.00    -6.298  -0.586  0.000   0.000
+45918.00    -6.455  -0.274  0.000   0.000
+45919.00    -6.273  0.211   0.000   0.000
+45920.00    -6.014  0.447   0.000   0.000
+45921.00    -5.757  0.300   0.000   0.000
+45922.00    -5.544  -0.069  0.000   0.000
+45923.00    -5.493  -0.405  0.000   0.000
+45924.00    -5.615  -0.498  0.000   0.000
+45925.00    -5.804  -0.337  0.000   0.000
+45926.00    -5.989  -0.125  0.000   0.000
+45927.00    -6.126  -0.019  0.000   0.000
+45928.00    -6.173  0.04    0.000   0.000
+45929.00    -6.253  0.169   0.000   0.000
+45930.00    -6.727  0.311   0.000   0.000
+45931.00    -7.793  0.277   0.000   0.000
+45932.00    -9.128  0.015   0.000   0.000
+45933.00    -10.055 -0.29   0.000   0.000
+45934.00    -10.135 -0.452  0.000   0.000
+45935.00    -9.488  -0.505  0.000   0.000
+45936.00    -8.615  -0.559  0.000   0.000
+45937.00    -7.887  -0.571  0.000   0.000
+45938.00    -7.502  -0.39   0.000   0.000
+45939.00    -7.558  -0.05   0.000   0.000
+45940.00    -7.946  0.174   0.000   0.000
+45941.00    -8.531  0.097   0.000   0.000
+45942.00    -9.16   -0.179  0.000   0.000
+45943.00    -9.733  -0.343  0.000   0.000
+45944.00    -10.12  -0.286  0.000   0.000
+45945.00    -9.912  -0.294  0.000   0.000
+45946.00    -9.42   -0.451  0.000   0.000
+45947.00    -9.152  -0.597  0.000   0.000
+45948.00    -9.011  -0.637  0.000   0.000
+45949.00    -8.773  -0.62   0.000   0.000
+45950.00    -8.33   -0.622  0.000   0.000
+45951.00    -7.829  -0.574  0.000   0.000
+45952.00    -7.469  -0.33   0.000   0.000
+45953.00    -7.296  0.104   0.000   0.000
+45954.00    -7.257  0.526   0.000   0.000
+45955.00    -7.313  0.762   0.000   0.000
+45956.00    -7.402  0.844   0.000   0.000
+45957.00    -7.512  0.922   0.000   0.000
+45958.00    -7.751  1.025   0.000   0.000
+45959.00    -8.202  1.015   0.000   0.000
+45960.00    -8.658  0.826   0.000   0.000
+45961.00    -8.74   0.627   0.000   0.000
+45962.00    -8.267  0.637   0.000   0.000
+45963.00    -7.486  0.851   0.000   0.000
+45964.00    -6.863  1.096   0.000   0.000
+45965.00    -6.709  1.288   0.000   0.000
+45966.00    -7.026  1.483   0.000   0.000
+45967.00    -7.703  1.659   0.000   0.000
+45968.00    -8.54   1.623   0.000   0.000
+45969.00    -9.191  1.28    0.000   0.000
+45970.00    -9.381  0.844   0.000   0.000
+45971.00    -9.212  0.631   0.000   0.000
+45972.00    -8.964  0.665   0.000   0.000
+45973.00    -8.751  0.678   0.000   0.000
+45974.00    -8.525  0.506   0.000   0.000
+45975.00    -8.289  0.32    0.000   0.000
+45976.00    -8.079  0.362   0.000   0.000
+45977.00    -7.847  0.627   0.000   0.000
+45978.00    -7.518  0.914   0.000   0.000
+45979.00    -7.137  1.104   0.000   0.000
+45980.00    -6.826  1.264   0.000   0.000
+45981.00    -6.608  1.481   0.000   0.000
+45982.00    -6.383  1.674   0.000   0.000
+45983.00    -6.093  1.69    0.000   0.000
+45984.00    -5.789  1.517   0.000   0.000
+45985.00    -5.533  1.31    0.000   0.000
+45986.00    -5.362  1.184   0.000   0.000
+45987.00    -5.302  1.11    0.000   0.000
+45988.00    -5.324  1.029   0.000   0.000
+45989.00    -5.304  0.982   0.000   0.000
+45990.00    -5.132  1.071   0.000   0.000
+45991.00    -4.843  1.312   0.000   0.000
+45992.00    -4.601  1.61    0.000   0.000
+45993.00    -4.567  1.903   0.000   0.000
+45994.00    -4.839  2.207   0.000   0.000
+45995.00    -5.427  2.483   0.000   0.000
+45996.00    -6.147  2.569   0.000   0.000
+45997.00    -6.646  2.373   0.000   0.000
+45998.00    -6.695  2.076   0.000   0.000
+45999.00    -6.431  1.974   0.000   0.000
+46000.00    -6.145  2.113   0.000   0.000
+46001.00    -5.933  2.219   0.000   0.000
+46002.00    -5.653  2.076   0.000   0.000
+46003.00    -5.232  1.817   0.000   0.000
+46004.00    -4.804  1.741   0.000   0.000
+46005.00    -4.514  1.923   0.000   0.000
+46006.00    -4.335  2.161   0.000   0.000
+46007.00    -4.22   2.271   0.000   0.000
+46008.00    -4.192  2.299   0.000   0.000
+46009.00    -4.222  2.398   0.000   0.000
+46010.00    -4.185  2.588   0.000   0.000
+46011.00    -4.051  2.727   0.000   0.000
+46012.00    -3.927  2.691   0.000   0.000
+46013.00    -3.887  2.512   0.000   0.000
+46014.00    -3.862  2.322   0.000   0.000
+46015.00    -3.758  2.226   0.000   0.000
+46016.00    -3.56   2.234   0.000   0.000
+46017.00    -3.311  2.304   0.000   0.000
+46018.00    -3.016  2.405   0.000   0.000
+46019.00    -2.634  2.536   0.000   0.000
+46020.00    -2.166  2.706   0.000   0.000
+46021.00    -1.726  2.936   0.000   0.000
+46022.00    -1.495  3.23    0.000   0.000
+46023.00    -1.585  3.521   0.000   0.000
+46024.00    -1.905  3.66    0.000   0.000
+46025.00    -2.181  3.544   0.000   0.000
+46026.00    -2.179  3.27    0.000   0.000
+46027.00    -1.952  3.062   0.000   0.000
+46028.00    -1.733  3.023   0.000   0.000
+46029.00    -1.593  3.036   0.000   0.000
+46030.00    -1.371  2.976   0.000   0.000
+46031.00    -0.975  2.906   0.000   0.000
+46032.00    -0.532  3.015   0.000   0.000
+46033.00    -0.244  3.343   0.000   0.000
+46034.00    -0.202  3.69    0.000   0.000
+46035.00    -0.402  3.842   0.000   0.000
+46036.00    -0.783  3.831   0.000   0.000
+46037.00    -1.25   3.845   0.000   0.000
+46038.00    -1.696  3.975   0.000   0.000
+46039.00    -2.072  4.128   0.000   0.000
+46040.00    -2.405  4.148   0.000   0.000
+46041.00    -2.71   3.973   0.000   0.000
+46042.00    -2.885  3.696   0.000   0.000
+46043.00    -2.802  3.48    0.000   0.000
+46044.00    -2.482  3.418   0.000   0.000
+46045.00    -2.088  3.464   0.000   0.000
+46046.00    -1.747  3.503   0.000   0.000
+46047.00    -1.474  3.474   0.000   0.000
+46048.00    -1.242  3.42    0.000   0.000
+46049.00    -1.064  3.434   0.000   0.000
+46050.00    -0.995  3.574   0.000   0.000
+46051.00    -1.081  3.798   0.000   0.000
+46052.00    -1.25   4.011   0.000   0.000
+46053.00    -1.317  4.124   0.000   0.000
+46054.00    -1.119  4.119   0.000   0.000
+46055.00    -0.658  4.044   0.000   0.000
+46056.00    -0.104  3.958   0.000   0.000
+46057.00    0.385   3.861   0.000   0.000
+46058.00    0.772   3.742   0.000   0.000
+46059.00    1.096   3.661   0.000   0.000
+46060.00    1.344   3.718   0.000   0.000
+46061.00    1.428   3.92    0.000   0.000
+46062.00    1.300   4.137   0.000   0.000
+46063.00    1.033   4.246   0.000   0.000
+46064.00    0.766   4.277   0.000   0.000
+46065.00    0.603   4.351   0.000   0.000
+46066.00    0.541   4.509   0.000   0.000
+46067.00    0.515   4.639   0.000   0.000
+46068.00    0.487   4.588   0.000   0.000
+46069.00    0.49    4.301   0.000   0.000
+46070.00    0.604   3.862   0.000   0.000
+46071.00    0.873   3.451   0.000   0.000
+46072.00    1.278   3.244   0.000   0.000
+46073.00    1.721   3.317   0.000   0.000
+46074.00    2.021   3.607   0.000   0.000
+46075.00    1.97    3.983   0.000   0.000
+46076.00    1.522   4.333   0.000   0.000
+46077.00    0.800   4.626   0.000   0.000
+46078.00    0.003   4.884   0.000   0.000
+46079.00    -0.671  5.09    0.000   0.000
+46080.00    -1.063  5.179   0.000   0.000
+46081.00    -1.137  5.122   0.000   0.000
+46082.00    -0.903  4.914   0.000   0.000
+46083.00    -0.402  4.564   0.000   0.000
+46084.00    0.239   4.119   0.000   0.000
+46085.00    0.831   3.671   0.000   0.000
+46086.00    1.249   3.32    0.000   0.000
+46087.00    1.475   3.169   0.000   0.000
+46088.00    1.548   3.278   0.000   0.000
+46089.00    1.472   3.607   0.000   0.000
+46090.00    1.226   4.012   0.000   0.000
+46091.00    0.992   4.19    0.000   0.000
+46092.00    0.912   4.128   0.000   0.000
+46093.00    0.963   4.026   0.000   0.000
+46094.00    0.991   3.978   0.000   0.000
+46095.00    0.832   3.961   0.000   0.000
+46096.00    0.549   3.906   0.000   0.000
+46097.00    0.323   3.793   0.000   0.000
+46098.00    0.225   3.626   0.000   0.000
+46099.00    0.241   3.383   0.000   0.000
+46100.00    0.467   3.09    0.000   0.000
+46101.00    1.034   2.895   0.000   0.000
+46102.00    1.873   2.916   0.000   0.000
+46103.00    2.619   3.081   0.000   0.000
+46104.00    2.885   3.215   0.000   0.000
+46105.00    2.599   3.245   0.000   0.000
+46106.00    2.041   3.244   0.000   0.000
+46107.00    1.506   3.328   0.000   0.000
+46108.00    1.084   3.526   0.000   0.000
+46109.00    0.759   3.752   0.000   0.000
+46110.00    0.557   3.889   0.000   0.000
+46111.00    0.559   3.866   0.000   0.000
+46112.00    0.807   3.671   0.000   0.000
+46113.00    1.223   3.349   0.000   0.000
+46114.00    1.638   3.02    0.000   0.000
+46115.00    1.941   2.836   0.000   0.000
+46116.00    2.152   2.87    0.000   0.000
+46117.00    2.339   3.038   0.000   0.000
+46118.00    2.508   3.169   0.000   0.000
+46119.00    2.621   3.173   0.000   0.000
+46120.00    2.68    3.124   0.000   0.000
+46121.00    2.716   3.115   0.000   0.000
+46122.00    2.673   3.108   0.000   0.000
+46123.00    2.52    2.986   0.000   0.000
+46124.00    2.441   2.741   0.000   0.000
+46125.00    2.681   2.498   0.000   0.000
+46126.00    3.134   2.321   0.000   0.000
+46127.00    3.441   2.091   0.000   0.000
+46128.00    3.475   1.706   0.000   0.000
+46129.00    3.458   1.324   0.000   0.000
+46130.00    3.513   1.232   0.000   0.000
+46131.00    3.527   1.484   0.000   0.000
+46132.00    3.198   1.803   0.000   0.000
+46133.00    2.45    1.91    0.000   0.000
+46134.00    1.659   1.807   0.000   0.000
+46135.00    1.208   1.694   0.000   0.000
+46136.00    1.145   1.676   0.000   0.000
+46137.00    1.296   1.687   0.000   0.000
+46138.00    1.542   1.644   0.000   0.000
+46139.00    1.916   1.546   0.000   0.000
+46140.00    2.525   1.418   0.000   0.000
+46141.00    3.359   1.263   0.000   0.000
+46142.00    4.232   1.117   0.000   0.000
+46143.00    4.892   1.094   0.000   0.000
+46144.00    5.209   1.287   0.000   0.000
+46145.00    5.231   1.619   0.000   0.000
+46146.00    5.113   1.86    0.000   0.000
+46147.00    4.972   1.862   0.000   0.000
+46148.00    4.868   1.700   0.000   0.000
+46149.00    4.822   1.537   0.000   0.000
+46150.00    4.771   1.408   0.000   0.000
+46151.00    4.651   1.217   0.000   0.000
+46152.00    4.587   0.966   0.000   0.000
+46153.00    4.795   0.815   0.000   0.000
+46154.00    5.236   0.84    0.000   0.000
+46155.00    5.587   0.85    0.000   0.000
+46156.00    5.687   0.609   0.000   0.000
+46157.00    5.794   0.202   0.000   0.000
+46158.00    6.171   -0.01   0.000   0.000
+46159.00    6.598   0.176   0.000   0.000
+46160.00    6.582   0.542   0.000   0.000
+46161.00    6.007   0.734   0.000   0.000
+46162.00    5.27    0.674   0.000   0.000
+46163.00    4.817   0.549   0.000   0.000
+46164.00    4.747   0.484   0.000   0.000
+46165.00    4.879   0.41    0.000   0.000
+46166.00    5.000   0.264   0.000   0.000
+46167.00    5.018   0.147   0.000   0.000
+46168.00    5.002   0.178   0.000   0.000
+46169.00    5.118   0.305   0.000   0.000
+46170.00    5.435   0.385   0.000   0.000
+46171.00    5.792   0.427   0.000   0.000
+46172.00    5.963   0.559   0.000   0.000
+46173.00    5.914   0.798   0.000   0.000
+46174.00    5.798   0.988   0.000   0.000
+46175.00    5.751   0.996   0.000   0.000
+46176.00    5.808   0.823   0.000   0.000
+46177.00    5.945   0.577   0.000   0.000
+46178.00    6.100   0.27    0.000   0.000
+46179.00    6.22    -0.28   0.000   0.000
+46180.00    6.345   -1.178  0.000   0.000
+46181.00    6.419   -1.71   0.000   0.000
+46182.00    6.466   -1.571  0.000   0.000
+46183.00    6.454   -1.093  0.000   0.000
+46184.00    6.334   -0.701  0.000   0.000
+46185.00    6.266   -0.602  0.000   0.000
+46186.00    6.366   -0.563  0.000   0.000
+46187.00    6.471   -0.335  0.000   0.000
+46188.00    6.279   -0.01   0.000   0.000
+46189.00    5.732   0.155   0.000   0.000
+46190.00    5.101   0.103   0.000   0.000
+46191.00    4.715   -0.028  0.000   0.000
+46192.00    4.668   -0.177  0.000   0.000
+46193.00    4.843   -0.456  0.000   0.000
+46194.00    5.042   -0.895  0.000   0.000
+46195.00    5.124   -1.102  0.000   0.000
+46196.00    5.19    -0.987  0.000   0.000
+46197.00    5.403   -0.726  0.000   0.000
+46198.00    5.748   -0.464  0.000   0.000
+46199.00    5.977   -0.26   0.000   0.000
+46200.00    5.669   0.011   0.000   0.000
+46201.00    4.864   0.368   0.000   0.000
+46202.00    4.003   0.615   0.000   0.000
+46203.00    3.394   0.551   0.000   0.000
+46204.00    3.07    0.192   0.000   0.000
+46205.00    2.955   -0.236  0.000   0.000
+46206.00    2.968   -0.514  0.000   0.000
+46207.00    3.02    -0.613  0.000   0.000
+46208.00    3.03    -0.644  0.000   0.000
+46209.00    3.009   -0.692  0.000   0.000
+46210.00    3.07    -0.751  0.000   0.000
+46211.00    3.289   -0.8    0.000   0.000
+46212.00    3.602   -0.845  0.000   0.000
+46213.00    3.868   -0.851  0.000   0.000
+46214.00    3.957   -0.718  0.000   0.000
+46215.00    3.789   -0.395  0.000   0.000
+46216.00    3.37    -0.014  0.000   0.000
+46217.00    2.877   0.217   0.000   0.000
+46218.00    2.564   0.234   0.000   0.000
+46219.00    2.54    0.149   0.000   0.000
+46220.00    2.724   0.039   0.000   0.000
+46221.00    3.011   -0.165  0.000   0.000
+46222.00    3.301   -0.511  0.000   0.000
+46223.00    3.412   -0.837  0.000   0.000
+46224.00    3.171   -0.907  0.000   0.000
+46225.00    2.626   -0.699  0.000   0.000
+46226.00    2.037   -0.43   0.000   0.000
+46227.00    1.575   -0.279  0.000   0.000
+46228.00    1.164   -0.203  0.000   0.000
+46229.00    0.668   -0.062  0.000   0.000
+46230.00    0.128   0.145   0.000   0.000
+46231.00    -0.309  0.237   0.000   0.000
+46232.00    -0.576  0.084   0.000   0.000
+46233.00    -0.683  -0.247  0.000   0.000
+46234.00    -0.629  -0.591  0.000   0.000
+46235.00    -0.406  -0.84   0.000   0.000
+46236.00    0.100   -0.766  0.000   0.000
+46237.00    0.599   -0.619  0.000   0.000
+46238.00    0.909   -0.661  0.000   0.000
+46239.00    1.188   -0.79   0.000   0.000
+46240.00    1.488   -0.818  0.000   0.000
+46241.00    1.671   -0.649  0.000   0.000
+46242.00    1.531   -0.3    0.000   0.000
+46243.00    1.000   0.123   0.000   0.000
+46244.00    0.25    0.479   0.000   0.000
+46245.00    -0.387  0.652   0.000   0.000
+46246.00    -0.679  0.642   0.000   0.000
+46247.00    -0.633  0.54    0.000   0.000
+46248.00    -0.425  0.413   0.000   0.000
+46249.00    -0.21   0.237   0.000   0.000
+46250.00    -0.067  -0.021  0.000   0.000
+46251.00    -0.07   -0.285  0.000   0.000
+46252.00    -0.338  -0.419  0.000   0.000
+46253.00    -0.908  -0.411  0.000   0.000
+46254.00    -1.633  -0.397  0.000   0.000
+46255.00    -2.329  -0.374  0.000   0.000
+46256.00    -2.91   -0.288  0.000   0.000
+46257.00    -3.406  -0.087  0.000   0.000
+46258.00    -3.85   0.168   0.000   0.000
+46259.00    -4.185  0.273   0.000   0.000
+46260.00    -4.296  0.059   0.000   0.000
+46261.00    -4.144  -0.401  0.000   0.000
+46262.00    -3.766  -0.865  0.000   0.000
+46263.00    -3.285  -1.122  0.000   0.000
+46264.00    -2.914  -1.097  0.000   0.000
+46265.00    -2.846  -0.871  0.000   0.000
+46266.00    -3.036  -0.635  0.000   0.000
+46267.00    -3.29   -0.527  0.000   0.000
+46268.00    -3.438  -0.549  0.000   0.000
+46269.00    -3.518  -0.583  0.000   0.000
+46270.00    -3.755  -0.485  0.000   0.000
+46271.00    -4.208  -0.295  0.000   0.000
+46272.00    -4.758  -0.117  0.000   0.000
+46273.00    -5.211  -0.007  0.000   0.000
+46274.00    -5.413  0.03    0.000   0.000
+46275.00    -5.33   0.01    0.000   0.000
+46276.00    -5.056  -0.077  0.000   0.000
+46277.00    -4.763  -0.188  0.000   0.000
+46278.00    -4.578  -0.274  0.000   0.000
+46279.00    -4.597  -0.27   0.000   0.000
+46280.00    -4.918  -0.138  0.000   0.000
+46281.00    -5.541  0.067   0.000   0.000
+46282.00    -6.339  0.22    0.000   0.000
+46283.00    -7.081  0.252   0.000   0.000
+46284.00    -7.519  0.238   0.000   0.000
+46285.00    -7.551  0.285   0.000   0.000
+46286.00    -7.398  0.369   0.000   0.000
+46287.00    -7.34   0.341   0.000   0.000
+46288.00    -7.451  0.11    0.000   0.000
+46289.00    -7.6    -0.239  0.000   0.000
+46290.00    -7.355  -0.509  0.000   0.000
+46291.00    -6.762  -0.587  0.000   0.000
+46292.00    -6.136  -0.485  0.000   0.000
+46293.00    -5.663  -0.281  0.000   0.000
+46294.00    -5.411  -0.089  0.000   0.000
+46295.00    -5.438  -0.017  0.000   0.000
+46296.00    -5.741  -0.086  0.000   0.000
+46297.00    -6.235  -0.2    0.000   0.000
+46298.00    -6.791  -0.226  0.000   0.000
+46299.00    -7.304  -0.115  0.000   0.000
+46300.00    -7.716  0.077   0.000   0.000
+46301.00    -7.995  0.235   0.000   0.000
+46302.00    -8.094  0.269   0.000   0.000
+46303.00    -7.964  0.14    0.000   0.000
+46304.00    -7.674  -0.116  0.000   0.000
+46305.00    -7.395  -0.406  0.000   0.000
+46306.00    -7.26   -0.616  0.000   0.000
+46307.00    -7.334  -0.651  0.000   0.000
+46308.00    -7.6    -0.504  0.000   0.000
+46309.00    -8.019  -0.29   0.000   0.000
+46310.00    -8.558  -0.157  0.000   0.000
+46311.00    -9.102  -0.153  0.000   0.000
+46312.00    -9.45   -0.155  0.000   0.000
+46313.00    -9.462  -0.023  0.000   0.000
+46314.00    -9.194  0.214   0.000   0.000
+46315.00    -8.915  0.276   0.000   0.000
+46316.00    -8.668  0.043   0.000   0.000
+46317.00    -8.179  -0.281  0.000   0.000
+46318.00    -7.382  -0.477  0.000   0.000
+46319.00    -6.597  -0.497  0.000   0.000
+46320.00    -6.201  -0.409  0.000   0.000
+46321.00    -6.236  -0.27   0.000   0.000
+46322.00    -6.504  -0.091  0.000   0.000
+46323.00    -6.869  0.049   0.000   0.000
+46324.00    -7.295  0.022   0.000   0.000
+46325.00    -7.705  -0.18   0.000   0.000
+46326.00    -7.985  -0.373  0.000   0.000
+46327.00    -8.12   -0.384  0.000   0.000
+46328.00    -8.189  -0.243  0.000   0.000
+46329.00    -8.223  -0.117  0.000   0.000
+46330.00    -8.153  -0.099  0.000   0.000
+46331.00    -7.918  -0.143  0.000   0.000
+46332.00    -7.543  -0.167  0.000   0.000
+46333.00    -7.144  -0.134  0.000   0.000
+46334.00    -6.895  -0.024  0.000   0.000
+46335.00    -6.938  0.214   0.000   0.000
+46336.00    -7.223  0.595   0.000   0.000
+46337.00    -7.566  1.000   0.000   0.000
+46338.00    -7.81   1.225   0.000   0.000
+46339.00    -7.853  1.188   0.000   0.000
+46340.00    -7.726  0.958   0.000   0.000
+46341.00    -7.482  0.712   0.000   0.000
+46342.00    -7.214  0.52    0.000   0.000
+46343.00    -7.045  0.283   0.000   0.000
+46344.00    -6.908  -0.018  0.000   0.000
+46345.00    -6.553  -0.203  0.000   0.000
+46346.00    -5.916  -0.111  0.000   0.000
+46347.00    -5.31   0.181   0.000   0.000
+46348.00    -5.105  0.459   0.000   0.000
+46349.00    -5.336  0.655   0.000   0.000
+46350.00    -5.772  0.876   0.000   0.000
+46351.00    -6.224  1.148   0.000   0.000
+46352.00    -6.6    1.303   0.000   0.000
+46353.00    -6.774  1.227   0.000   0.000
+46354.00    -6.636  1.06    0.000   0.000
+46355.00    -6.277  1.023   0.000   0.000
+46356.00    -5.943  1.111   0.000   0.000
+46357.00    -5.711  1.102   0.000   0.000
+46358.00    -5.42   0.892   0.000   0.000
+46359.00    -4.949  0.659   0.000   0.000
+46360.00    -4.379  0.642   0.000   0.000
+46361.00    -3.874  0.848   0.000   0.000
+46362.00    -3.555  1.112   0.000   0.000
+46363.00    -3.492  1.337   0.000   0.000
+46364.00    -3.692  1.533   0.000   0.000
+46365.00    -4.077  1.653   0.000   0.000
+46366.00    -4.493  1.613   0.000   0.000
+46367.00    -4.842  1.419   0.000   0.000
+46368.00    -5.076  1.301   0.000   0.000
+46369.00    -5.191  1.444   0.000   0.000
+46370.00    -5.313  1.612   0.000   0.000
+46371.00    -5.461  1.635   0.000   0.000
+46372.00    -5.536  1.503   0.000   0.000
+46373.00    -5.374  1.373   0.000   0.000
+46374.00    -4.916  1.442   0.000   0.000
+46375.00    -4.313  1.672   0.000   0.000
+46376.00    -3.818  1.82    0.000   0.000
+46377.00    -3.533  1.855   0.000   0.000
+46378.00    -3.405  1.947   0.000   0.000
+46379.00    -3.451  2.194   0.000   0.000
+46380.00    -3.703  2.441   0.000   0.000
+46381.00    -3.959  2.484   0.000   0.000
+46382.00    -3.977  2.38    0.000   0.000
+46383.00    -3.803  2.359   0.000   0.000
+46384.00    -3.671  2.445   0.000   0.000
+46385.00    -3.605  2.394   0.000   0.000
+46386.00    -3.421  2.08    0.000   0.000
+46387.00    -3.035  1.731   0.000   0.000
+46388.00    -2.636  1.676   0.000   0.000
+46389.00    -2.489  1.955   0.000   0.000
+46390.00    -2.672  2.339   0.000   0.000
+46391.00    -2.886  2.792   0.000   0.000
+46392.00    -3.109  3.227   0.000   0.000
+46393.00    -3.346  3.575   0.000   0.000
+46394.00    -3.396  3.77    0.000   0.000
+46395.00    -3.139  3.674   0.000   0.000
+46396.00    -2.705  3.317   0.000   0.000
+46397.00    -2.239  2.914   0.000   0.000
+46398.00    -1.746  2.65    0.000   0.000
+46399.00    -1.217  2.54    0.000   0.000
+46400.00    -0.735  2.506   0.000   0.000
+46401.00    -0.37   2.514   0.000   0.000
+46402.00    -0.163  2.592   0.000   0.000
+46403.00    -0.158  2.724   0.000   0.000
+46404.00    -0.361  2.828   0.000   0.000
+46405.00    -0.703  2.892   0.000   0.000
+46406.00    -1.141  3.029   0.000   0.000
+46407.00    -1.72   3.297   0.000   0.000
+46408.00    -2.431  3.548   0.000   0.000
+46409.00    -3.044  3.586   0.000   0.000
+46410.00    -3.266  3.442   0.000   0.000
+46411.00    -3.079  3.334   0.000   0.000
+46412.00    -2.738  3.366   0.000   0.000
+46413.00    -2.413  3.39    0.000   0.000
+46414.00    -2.045  3.257   0.000   0.000
+46415.00    -1.605  3.081   0.000   0.000
+46416.00    -1.27   3.127   0.000   0.000
+46417.00    -1.22   3.43    0.000   0.000
+46418.00    -1.39   3.731   0.000   0.000
+46419.00    -1.57   3.809   0.000   0.000
+46420.00    -1.641  3.722   0.000   0.000
+46421.00    -1.586  3.656   0.000   0.000
+46422.00    -1.409  3.653   0.000   0.000
+46423.00    -1.159  3.596   0.000   0.000
+46424.00    -0.97   3.41    0.000   0.000
+46425.00    -0.918  3.19    0.000   0.000
+46426.00    -0.892  3.094   0.000   0.000
+46427.00    -0.713  3.174   0.000   0.000
+46428.00    -0.363  3.344   0.000   0.000
+46429.00    -0.003  3.484   0.000   0.000
+46430.00    0.207   3.534   0.000   0.000
+46431.00    0.236   3.517   0.000   0.000
+46432.00    0.156   3.491   0.000   0.000
+46433.00    0.041   3.521   0.000   0.000
+46434.00    -0.089  3.653   0.000   0.000
+46435.00    -0.269  3.862   0.000   0.000
+46436.00    -0.522  4.033   0.000   0.000
+46437.00    -0.722  4.047   0.000   0.000
+46438.00    -0.672  3.93    0.000   0.000
+46439.00    -0.314  3.872   0.000   0.000
+46440.00    0.206   4.034   0.000   0.000
+46441.00    0.543   4.165   0.000   0.000
+46442.00    0.604   4.065   0.000   0.000
+46443.00    0.507   3.896   0.000   0.000
+46444.00    0.243   3.916   0.000   0.000
+46445.00    -0.189  4.236   0.000   0.000
+46446.00    -0.755  4.589   0.000   0.000
+46447.00    -1.339  4.65    0.000   0.000
+46448.00    -1.765  4.474   0.000   0.000
+46449.00    -1.93   4.317   0.000   0.000
+46450.00    -1.808  4.296   0.000   0.000
+46451.00    -1.489  4.257   0.000   0.000
+46452.00    -1.131  4.052   0.000   0.000
+46453.00    -0.855  3.712   0.000   0.000
+46454.00    -0.63   3.382   0.000   0.000
+46455.00    -0.308  3.167   0.000   0.000
+46456.00    0.16    3.094   0.000   0.000
+46457.00    0.659   3.108   0.000   0.000
+46458.00    1.007   3.158   0.000   0.000
+46459.00    1.077   3.28    0.000   0.000
+46460.00    0.84    3.564   0.000   0.000
+46461.00    0.484   3.764   0.000   0.000
+46462.00    0.107   3.821   0.000   0.000
+46463.00    -0.289  3.821   0.000   0.000
+46464.00    -0.711  3.812   0.000   0.000
+46465.00    -1.141  3.826   0.000   0.000
+46466.00    -1.376  3.744   0.000   0.000
+46467.00    -1.344  3.558   0.000   0.000
+46468.00    -1.119  3.376   0.000   0.000
+46469.00    -0.767  3.265   0.000   0.000
+46470.00    -0.32   3.233   0.000   0.000
+46471.00    0.158   3.27    0.000   0.000
+46472.00    0.523   3.368   0.000   0.000
+46473.00    0.624   3.479   0.000   0.000
+46474.00    0.422   3.518   0.000   0.000
+46475.00    0.027   3.457   0.000   0.000
+46476.00    -0.355  3.38    0.000   0.000
+46477.00    -0.552  3.389   0.000   0.000
+46478.00    -0.499  3.459   0.000   0.000
+46479.00    -0.228  3.437   0.000   0.000
+46480.00    0.166   3.206   0.000   0.000
+46481.00    0.536   2.825   0.000   0.000
+46482.00    0.759   2.45    0.000   0.000
+46483.00    0.824   2.201   0.000   0.000
+46484.00    0.838   2.122   0.000   0.000
+46485.00    0.924   2.206   0.000   0.000
+46486.00    1.083   2.375   0.000   0.000
+46487.00    1.159   2.525   0.000   0.000
+46488.00    0.987   2.592   0.000   0.000
+46489.00    0.571   2.581   0.000   0.000
+46490.00    0.096   2.537   0.000   0.000
+46491.00    -0.23   2.493   0.000   0.000
+46492.00    -0.313  2.454   0.000   0.000
+46493.00    -0.187  2.396   0.000   0.000
+46494.00    0.069   2.293   0.000   0.000
+46495.00    0.386   2.137   0.000   0.000
+46496.00    0.708   1.968   0.000   0.000
+46497.00    0.981   1.875   0.000   0.000
+46498.00    1.169   1.943   0.000   0.000
+46499.00    1.282   2.192   0.000   0.000
+46500.00    1.367   2.551   0.000   0.000
+46501.00    1.453   2.825   0.000   0.000
+46502.00    1.529   2.81    0.000   0.000
+46503.00    1.595   2.444   0.000   0.000
+46504.00    1.577   2.029   0.000   0.000
+46505.00    1.638   1.785   0.000   0.000
+46506.00    1.906   1.663   0.000   0.000
+46507.00    2.331   1.526   0.000   0.000
+46508.00    2.858   1.326   0.000   0.000
+46509.00    3.406   1.15    0.000   0.000
+46510.00    3.784   1.08    0.000   0.000
+46511.00    3.803   1.08    0.000   0.000
+46512.00    3.525   1.087   0.000   0.000
+46513.00    3.267   1.146   0.000   0.000
+46514.00    3.229   1.327   0.000   0.000
+46515.00    3.234   1.55    0.000   0.000
+46516.00    2.965   1.619   0.000   0.000
+46517.00    2.404   1.416   0.000   0.000
+46518.00    1.896   1.028   0.000   0.000
+46519.00    1.779   0.66    0.000   0.000
+46520.00    2.07    0.432   0.000   0.000
+46521.00    2.538   0.328   0.000   0.000
+46522.00    2.972   0.287   0.000   0.000
+46523.00    3.279   0.268   0.000   0.000
+46524.00    3.407   0.246   0.000   0.000
+46525.00    3.293   0.228   0.000   0.000
+46526.00    3.19    0.304   0.000   0.000
+46527.00    3.276   0.545   0.000   0.000
+46528.00    3.503   0.891   0.000   0.000
+46529.00    3.852   1.175   0.000   0.000
+46530.00    4.223   1.239   0.000   0.000
+46531.00    4.511   1.075   0.000   0.000
+46532.00    4.699   0.844   0.000   0.000
+46533.00    4.841   0.702   0.000   0.000
+46534.00    4.954   0.624   0.000   0.000
+46535.00    5.009   0.471   0.000   0.000
+46536.00    5.081   0.213   0.000   0.000
+46537.00    5.29    -0.016  0.000   0.000
+46538.00    5.558   -0.121  0.000   0.000
+46539.00    5.616   -0.211  0.000   0.000
+46540.00    5.386   -0.414  0.000   0.000
+46541.00    5.129   -0.609  0.000   0.000
+46542.00    5.095   -0.507  0.000   0.000
+46543.00    5.106   -0.038  0.000   0.000
+46544.00    4.743   0.507   0.000   0.000
+46545.00    3.941   0.786   0.000   0.000
+46546.00    3.16    0.733   0.000   0.000
+46547.00    2.866   0.546   0.000   0.000
+46548.00    3.089   0.386   0.000   0.000
+46549.00    3.553   0.224   0.000   0.000
+46550.00    4.032   -0.009  0.000   0.000
+46551.00    4.423   -0.239  0.000   0.000
+46552.00    4.716   -0.359  0.000   0.000
+46553.00    4.895   -0.35   0.000   0.000
+46554.00    4.888   -0.24   0.000   0.000
+46555.00    4.777   -0.085  0.000   0.000
+46556.00    4.61    0.108   0.000   0.000
+46557.00    4.468   0.263   0.000   0.000
+46558.00    4.441   0.233   0.000   0.000
+46559.00    4.507   -0.005  0.000   0.000
+46560.00    4.574   -0.246  0.000   0.000
+46561.00    4.600   -0.292  0.000   0.000
+46562.00    4.567   -0.178  0.000   0.000
+46563.00    4.458   -0.148  0.000   0.000
+46564.00    4.353   -0.395  0.000   0.000
+46565.00    4.42    -0.856  0.000   0.000
+46566.00    4.631   -0.962  0.000   0.000
+46567.00    4.761   -0.606  0.000   0.000
+46568.00    4.713   -0.336  0.000   0.000
+46569.00    4.612   -0.291  0.000   0.000
+46570.00    4.623   -0.162  0.000   0.000
+46571.00    4.658   0.222   0.000   0.000
+46572.00    4.43    0.623   0.000   0.000
+46573.00    3.913   0.668   0.000   0.000
+46574.00    3.446   0.302   0.000   0.000
+46575.00    3.318   -0.189  0.000   0.000
+46576.00    3.503   -0.57   0.000   0.000
+46577.00    3.748   -0.844  0.000   0.000
+46578.00    3.846   -1.049  0.000   0.000
+46579.00    3.766   -1.078  0.000   0.000
+46580.00    3.622   -0.82   0.000   0.000
+46581.00    3.537   -0.38   0.000   0.000
+46582.00    3.595   0.001   0.000   0.000
+46583.00    3.723   0.209   0.000   0.000
+46584.00    3.703   0.326   0.000   0.000
+46585.00    3.396   0.412   0.000   0.000
+46586.00    2.922   0.368   0.000   0.000
+46587.00    2.444   0.103   0.000   0.000
+46588.00    1.995   -0.247  0.000   0.000
+46589.00    1.551   -0.4    0.000   0.000
+46590.00    1.124   -0.231  0.000   0.000
+46591.00    0.738   0.072   0.000   0.000
+46592.00    0.452   0.23    0.000   0.000
+46593.00    0.407   0.137   0.000   0.000
+46594.00    0.725   -0.181  0.000   0.000
+46595.00    1.32    -0.729  0.000   0.000
+46596.00    1.819   -1.207  0.000   0.000
+46597.00    1.94    -1.369  0.000   0.000
+46598.00    1.603   -0.949  0.000   0.000
+46599.00    0.806   0.112   0.000   0.000
+46600.00    -0.121  0.732   0.000   0.000
+46601.00    -0.865  0.731   0.000   0.000
+46602.00    -1.169  0.461   0.000   0.000
+46603.00    -0.954  0.146   0.000   0.000
+46604.00    -0.436  -0.058  0.000   0.000
+46605.00    0.083   -0.227  0.000   0.000
+46606.00    0.416   -0.434  0.000   0.000
+46607.00    0.433   -0.528  0.000   0.000
+46608.00    0.037   -0.3    0.000   0.000
+46609.00    -0.667  0.201   0.000   0.000
+46610.00    -1.368  0.677   0.000   0.000
+46611.00    -1.836  0.896   0.000   0.000
+46612.00    -2.137  0.909   0.000   0.000
+46613.00    -2.431  0.853   0.000   0.000
+46614.00    -2.703  0.686   0.000   0.000
+46615.00    -2.815  0.256   0.000   0.000
+46616.00    -2.748  -0.343  0.000   0.000
+46617.00    -2.588  -0.765  0.000   0.000
+46618.00    -2.382  -0.724  0.000   0.000
+46619.00    -2.168  -0.355  0.000   0.000
+46620.00    -2.023  -0.012  0.000   0.000
+46621.00    -1.974  0.132   0.000   0.000
+46622.00    -1.955  0.138   0.000   0.000
+46623.00    -1.915  0.14    0.000   0.000
+46624.00    -1.927  0.21    0.000   0.000
+46625.00    -2.155  0.343   0.000   0.000
+46626.00    -2.699  0.484   0.000   0.000
+46627.00    -3.492  0.574   0.000   0.000
+46628.00    -4.316  0.505   0.000   0.000
+46629.00    -4.909  0.203   0.000   0.000
+46630.00    -5.199  -0.04   0.000   0.000
+46631.00    -5.252  -0.015  0.000   0.000
+46632.00    -5.208  0.239   0.000   0.000
+46633.00    -5.075  0.47    0.000   0.000
+46634.00    -4.673  0.409   0.000   0.000
+46635.00    -3.925  0.028   0.000   0.000
+46636.00    -3.423  -0.284  0.000   0.000
+46637.00    -3.883  -0.189  0.000   0.000
+46638.00    -5.065  0.139   0.000   0.000
+46639.00    -6.121  0.35    0.000   0.000
+46640.00    -6.605  0.482   0.000   0.000
+46641.00    -6.661  0.679   0.000   0.000
+46642.00    -6.537  0.89    0.000   0.000
+46643.00    -6.35   0.876   0.000   0.000
+46644.00    -6.215  0.458   0.000   0.000
+46645.00    -6.247  -0.223  0.000   0.000
+46646.00    -6.523  -0.616  0.000   0.000
+46647.00    -6.937  -0.53   0.000   0.000
+46648.00    -7.341  -0.184  0.000   0.000
+46649.00    -7.655  0.158   0.000   0.000
+46650.00    -7.769  0.353   0.000   0.000
+46651.00    -7.657  0.451   0.000   0.000
+46652.00    -7.41   0.569   0.000   0.000
+46653.00    -7.225  0.745   0.000   0.000
+46654.00    -7.301  0.902   0.000   0.000
+46655.00    -7.673  0.923   0.000   0.000
+46656.00    -8.099  0.758   0.000   0.000
+46657.00    -8.275  0.462   0.000   0.000
+46658.00    -8.092  0.162   0.000   0.000
+46659.00    -7.676  -0.014  0.000   0.000
+46660.00    -7.233  -0.032  0.000   0.000
+46661.00    -7.009  0.056   0.000   0.000
+46662.00    -7.149  0.191   0.000   0.000
+46663.00    -7.574  0.31    0.000   0.000
+46664.00    -8.197  0.361   0.000   0.000
+46665.00    -8.983  0.266   0.000   0.000
+46666.00    -9.754  -0.003  0.000   0.000
+46667.00    -10.164 -0.383  0.000   0.000
+46668.00    -9.916  -0.667  0.000   0.000
+46669.00    -9.015  -0.619  0.000   0.000
+46670.00    -8.206  -0.369  0.000   0.000
+46671.00    -7.786  -0.154  0.000   0.000
+46672.00    -7.673  -0.097  0.000   0.000
+46673.00    -7.751  -0.137  0.000   0.000
+46674.00    -7.88   -0.104  0.000   0.000
+46675.00    -7.919  0.089   0.000   0.000
+46676.00    -7.869  0.367   0.000   0.000
+46677.00    -7.808  0.565   0.000   0.000
+46678.00    -7.794  0.561   0.000   0.000
+46679.00    -7.873  0.347   0.000   0.000
+46680.00    -8.114  0.048   0.000   0.000
+46681.00    -8.54   -0.151  0.000   0.000
+46682.00    -9.071  -0.214  0.000   0.000
+46683.00    -9.543  -0.197  0.000   0.000
+46684.00    -9.743  -0.137  0.000   0.000
+46685.00    -9.535  0.004   0.000   0.000
+46686.00    -9.018  0.219   0.000   0.000
+46687.00    -8.459  0.428   0.000   0.000
+46688.00    -8.112  0.498   0.000   0.000
+46689.00    -8.084  0.253   0.000   0.000
+46690.00    -8.296  -0.352  0.000   0.000
+46691.00    -8.272  -0.317  0.000   0.000
+46692.00    -8.133  0.085   0.000   0.000
+46693.00    -8.186  0.299   0.000   0.000
+46694.00    -8.448  0.356   0.000   0.000
+46695.00    -8.762  0.35    0.000   0.000
+46696.00    -8.891  0.407   0.000   0.000
+46697.00    -8.7    0.600   0.000   0.000
+46698.00    -8.267  0.852   0.000   0.000
+46699.00    -7.799  0.972   0.000   0.000
+46700.00    -7.441  0.86    0.000   0.000
+46701.00    -7.19   0.634   0.000   0.000
+46702.00    -7.034  0.492   0.000   0.000
+46703.00    -7.031  0.521   0.000   0.000
+46704.00    -7.188  0.674   0.000   0.000
+46705.00    -7.361  0.871   0.000   0.000
+46706.00    -7.407  1.035   0.000   0.000
+46707.00    -7.329  1.095   0.000   0.000
+46708.00    -7.253  1.017   0.000   0.000
+46709.00    -7.298  0.842   0.000   0.000
+46710.00    -7.481  0.649   0.000   0.000
+46711.00    -7.687  0.498   0.000   0.000
+46712.00    -7.781  0.383   0.000   0.000
+46713.00    -7.663  0.286   0.000   0.000
+46714.00    -7.283  0.249   0.000   0.000
+46715.00    -6.668  0.339   0.000   0.000
+46716.00    -5.993  0.547   0.000   0.000
+46717.00    -5.429  0.813   0.000   0.000
+46718.00    -5.071  1.07    0.000   0.000
+46719.00    -4.953  1.232   0.000   0.000
+46720.00    -5.071  1.201   0.000   0.000
+46721.00    -5.309  1.085   0.000   0.000
+46722.00    -5.595  0.969   0.000   0.000
+46723.00    -5.92   0.829   0.000   0.000
+46724.00    -6.152  0.737   0.000   0.000
+46725.00    -6.104  0.742   0.000   0.000
+46726.00    -5.762  0.811   0.000   0.000
+46727.00    -5.297  0.85    0.000   0.000
+46728.00    -4.856  0.86    0.000   0.000
+46729.00    -4.473  0.92    0.000   0.000
+46730.00    -4.226  1.082   0.000   0.000
+46731.00    -4.287  1.307   0.000   0.000
+46732.00    -4.725  1.48    0.000   0.000
+46733.00    -5.31   1.572   0.000   0.000
+46734.00    -5.665  1.661   0.000   0.000
+46735.00    -5.603  1.789   0.000   0.000
+46736.00    -5.247  2.027   0.000   0.000
+46737.00    -4.795  2.200   0.000   0.000
+46738.00    -4.383  2.101   0.000   0.000
+46739.00    -4.163  1.671   0.000   0.000
+46740.00    -4.07   1.343   0.000   0.000
+46741.00    -3.884  1.189   0.000   0.000
+46742.00    -3.586  1.186   0.000   0.000
+46743.00    -3.452  1.514   0.000   0.000
+46744.00    -3.482  2.068   0.000   0.000
+46745.00    -3.573  2.524   0.000   0.000
+46746.00    -3.73   2.747   0.000   0.000
+46747.00    -3.938  2.787   0.000   0.000
+46748.00    -4.109  2.724   0.000   0.000
+46749.00    -4.187  2.591   0.000   0.000
+46750.00    -4.231  2.376   0.000   0.000
+46751.00    -4.336  2.087   0.000   0.000
+46752.00    -4.5    1.85    0.000   0.000
+46753.00    -4.578  1.81    0.000   0.000
+46754.00    -4.401  1.935   0.000   0.000
+46755.00    -3.925  2.033   0.000   0.000
+46756.00    -3.228  2.015   0.000   0.000
+46757.00    -2.399  2.005   0.000   0.000
+46758.00    -1.596  2.141   0.000   0.000
+46759.00    -1.127  2.365   0.000   0.000
+46760.00    -1.218  2.495   0.000   0.000
+46761.00    -1.718  2.511   0.000   0.000
+46762.00    -2.288  2.584   0.000   0.000
+46763.00    -2.768  2.799   0.000   0.000
+46764.00    -3.167  2.989   0.000   0.000
+46765.00    -3.401  2.977   0.000   0.000
+46766.00    -3.328  2.828   0.000   0.000
+46767.00    -3.03   2.765   0.000   0.000
+46768.00    -2.817  2.813   0.000   0.000
+46769.00    -2.876  2.716   0.000   0.000
+46770.00    -3.056  2.302   0.000   0.000
+46771.00    -2.962  2.037   0.000   0.000
+46772.00    -2.605  2.200   0.000   0.000
+46773.00    -2.239  2.655   0.000   0.000
+46774.00    -2.014  3.083   0.000   0.000
+46775.00    -2.097  3.282   0.000   0.000
+46776.00    -2.396  3.306   0.000   0.000
+46777.00    -2.713  3.256   0.000   0.000
+46778.00    -2.944  3.107   0.000   0.000
+46779.00    -3.081  2.826   0.000   0.000
+46780.00    -3.127  2.533   0.000   0.000
+46781.00    -3.062  2.424   0.000   0.000
+46782.00    -2.802  2.556   0.000   0.000
+46783.00    -2.301  2.787   0.000   0.000
+46784.00    -1.635  2.969   0.000   0.000
+46785.00    -0.951  3.119   0.000   0.000
+46786.00    -0.381  3.318   0.000   0.000
+46787.00    -0.066  3.501   0.000   0.000
+46788.00    -0.063  3.487   0.000   0.000
+46789.00    -0.257  3.258   0.000   0.000
+46790.00    -0.498  3.023   0.000   0.000
+46791.00    -0.81   2.936   0.000   0.000
+46792.00    -1.293  2.867   0.000   0.000
+46793.00    -1.816  2.612   0.000   0.000
+46794.00    -2.078  2.249   0.000   0.000
+46795.00    -2.023  2.113   0.000   0.000
+46796.00    -1.921  2.344   0.000   0.000
+46797.00    -2.019  2.725   0.000   0.000
+46798.00    -2.244  2.996   0.000   0.000
+46799.00    -2.388  3.176   0.000   0.000
+46800.00    -2.406  3.44    0.000   0.000
+46801.00    -2.419  3.783   0.000   0.000
+46802.00    -2.418  3.968   0.000   0.000
+46803.00    -2.267  3.844   0.000   0.000
+46804.00    -1.948  3.542   0.000   0.000
+46805.00    -1.598  3.273   0.000   0.000
+46806.00    -1.314  3.066   0.000   0.000
+46807.00    -1.168  2.818   0.000   0.000
+46808.00    -1.258  2.538   0.000   0.000
+46809.00    -1.612  2.391   0.000   0.000
+46810.00    -2.059  2.498   0.000   0.000
+46811.00    -2.16   2.779   0.000   0.000
+46812.00    -1.797  3.034   0.000   0.000
+46813.00    -1.227  3.15    0.000   0.000
+46814.00    -0.725  3.136   0.000   0.000
+46815.00    -0.46   2.994   0.000   0.000
+46816.00    -0.434  2.959   0.000   0.000
+46817.00    -0.627  3.006   0.000   0.000
+46818.00    -0.939  3.089   0.000   0.000
+46819.00    -1.338  3.264   0.000   0.000
+46820.00    -1.833  3.406   0.000   0.000
+46821.00    -2.308  3.324   0.000   0.000
+46822.00    -2.492  3.018   0.000   0.000
+46823.00    -2.264  2.722   0.000   0.000
+46824.00    -1.856  2.595   0.000   0.000
+46825.00    -1.619  2.529   0.000   0.000
+46826.00    -1.688  2.507   0.000   0.000
+46827.00    -2.003  2.552   0.000   0.000
+46828.00    -2.522  2.706   0.000   0.000
+46829.00    -3.146  2.899   0.000   0.000
+46830.00    -3.543  2.877   0.000   0.000
+46831.00    -3.415  2.624   0.000   0.000
+46832.00    -3.125  2.476   0.000   0.000
+46833.00    -2.914  2.582   0.000   0.000
+46834.00    -2.667  2.719   0.000   0.000
+46835.00    -2.261  2.539   0.000   0.000
+46836.00    -1.922  2.259   0.000   0.000
+46837.00    -1.844  2.163   0.000   0.000
+46838.00    -1.933  2.319   0.000   0.000
+46839.00    -1.942  2.635   0.000   0.000
+46840.00    -1.689  2.886   0.000   0.000
+46841.00    -1.18   2.971   0.000   0.000
+46842.00    -0.623  2.91    0.000   0.000
+46843.00    -0.217  2.767   0.000   0.000
+46844.00    -0.066  2.59    0.000   0.000
+46845.00    -0.227  2.391   0.000   0.000
+46846.00    -0.559  2.235   0.000   0.000
+46847.00    -0.942  2.147   0.000   0.000
+46848.00    -1.33   2.078   0.000   0.000
+46849.00    -1.615  1.967   0.000   0.000
+46850.00    -1.62   1.819   0.000   0.000
+46851.00    -1.372  1.562   0.000   0.000
+46852.00    -0.824  1.458   0.000   0.000
+46853.00    -0.069  1.607   0.000   0.000
+46854.00    0.667   1.802   0.000   0.000
+46855.00    1.163   1.907   0.000   0.000
+46856.00    1.253   1.94    0.000   0.000
+46857.00    0.895   1.931   0.000   0.000
+46858.00    0.264   1.831   0.000   0.000
+46859.00    -0.342  1.61    0.000   0.000
+46860.00    -0.742  1.381   0.000   0.000
+46861.00    -0.914  1.287   0.000   0.000
+46862.00    -0.872  1.312   0.000   0.000
+46863.00    -0.623  1.288   0.000   0.000
+46864.00    -0.259  1.122   0.000   0.000
+46865.00    0.046   0.91    0.000   0.000
+46866.00    0.167   0.815   0.000   0.000
+46867.00    0.146   0.884   0.000   0.000
+46868.00    0.100   1.018   0.000   0.000
+46869.00    0.054   1.078   0.000   0.000
+46870.00    -0.092  1.006   0.000   0.000
+46871.00    -0.389  0.864   0.000   0.000
+46872.00    -0.803  0.771   0.000   0.000
+46873.00    -1.226  0.825   0.000   0.000
+46874.00    -1.483  1.081   0.000   0.000
+46875.00    -1.407  1.511   0.000   0.000
+46876.00    -0.987  1.678   0.000   0.000
+46877.00    -0.374  1.436   0.000   0.000
+46878.00    0.211   0.92    0.000   0.000
+46879.00    0.563   0.279   0.000   0.000
+46880.00    0.565   -0.283  0.000   0.000
+46881.00    0.453   -0.256  0.000   0.000
+46882.00    0.446   0.102   0.000   0.000
+46883.00    0.536   0.362   0.000   0.000
+46884.00    0.600   0.500   0.000   0.000
+46885.00    0.514   0.543   0.000   0.000
+46886.00    0.296   0.506   0.000   0.000
+46887.00    0.081   0.431   0.000   0.000
+46888.00    0.009   0.408   0.000   0.000
+46889.00    0.16    0.481   0.000   0.000
+46890.00    0.55    0.552   0.000   0.000
+46891.00    1.122   0.464   0.000   0.000
+46892.00    1.729   0.166   0.000   0.000
+46893.00    2.151   -0.215  0.000   0.000
+46894.00    2.182   -0.513  0.000   0.000
+46895.00    1.782   -0.67   0.000   0.000
+46896.00    1.289   -0.61   0.000   0.000
+46897.00    1.04    -0.328  0.000   0.000
+46898.00    1.042   0.059   0.000   0.000
+46899.00    1.075   0.427   0.000   0.000
+46900.00    0.888   0.634   0.000   0.000
+46901.00    0.584   0.506   0.000   0.000
+46902.00    0.436   0.085   0.000   0.000
+46903.00    0.618   -0.416  0.000   0.000
+46904.00    1.113   -0.792  0.000   0.000
+46905.00    1.76    -0.887  0.000   0.000
+46906.00    2.315   -0.814  0.000   0.000
+46907.00    2.617   -0.744  0.000   0.000
+46908.00    2.629   -0.798  0.000   0.000
+46909.00    2.53    -0.853  0.000   0.000
+46910.00    2.565   -0.712  0.000   0.000
+46911.00    2.743   -0.408  0.000   0.000
+46912.00    2.986   -0.124  0.000   0.000
+46913.00    3.201   -0.041  0.000   0.000
+46914.00    3.229   -0.241  0.000   0.000
+46915.00    2.93    -0.662  0.000   0.000
+46916.00    2.627   -1.03   0.000   0.000
+46917.00    2.551   -1.156  0.000   0.000
+46918.00    2.695   -1.062  0.000   0.000
+46919.00    2.917   -0.954  0.000   0.000
+46920.00    3.246   -1.22   0.000   0.000
+46921.00    3.674   -1.582  0.000   0.000
+46922.00    3.998   -1.634  0.000   0.000
+46923.00    3.928   -1.353  0.000   0.000
+46924.00    3.409   -0.962  0.000   0.000
+46925.00    2.699   -0.637  0.000   0.000
+46926.00    2.101   -0.335  0.000   0.000
+46927.00    1.637   -0.061  0.000   0.000
+46928.00    1.152   0.027   0.000   0.000
+46929.00    0.704   -0.178  0.000   0.000
+46930.00    0.633   -0.561  0.000   0.000
+46931.00    1.138   -0.884  0.000   0.000
+46932.00    2.025   -1.007  0.000   0.000
+46933.00    2.882   -0.959  0.000   0.000
+46934.00    3.403   -0.849  0.000   0.000
+46935.00    3.536   -0.75   0.000   0.000
+46936.00    3.418   -0.675  0.000   0.000
+46937.00    3.161   -0.597  0.000   0.000
+46938.00    2.77    -0.481  0.000   0.000
+46939.00    2.225   -0.308  0.000   0.000
+46940.00    1.611   -0.14   0.000   0.000
+46941.00    1.208   -0.193  0.000   0.000
+46942.00    1.113   -0.549  0.000   0.000
+46943.00    1.161   -1.032  0.000   0.000
+46944.00    1.179   -1.34   0.000   0.000
+46945.00    1.103   -1.262  0.000   0.000
+46946.00    0.974   -1.017  0.000   0.000
+46947.00    0.852   -0.875  0.000   0.000
+46948.00    0.828   -0.884  0.000   0.000
+46949.00    1.019   -0.894  0.000   0.000
+46950.00    1.395   -0.77   0.000   0.000
+46951.00    1.621   -0.588  0.000   0.000
+46952.00    1.389   -0.519  0.000   0.000
+46953.00    0.772   -0.539  0.000   0.000
+46954.00    0.124   -0.444  0.000   0.000
+46955.00    -0.348  -0.171  0.000   0.000
+46956.00    -0.71   0.05    0.000   0.000
+46957.00    -0.928  -0.054  0.000   0.000
+46958.00    -0.807  -0.419  0.000   0.000
+46959.00    -0.282  -0.717  0.000   0.000
+46960.00    0.35    -0.739  0.000   0.000
+46961.00    0.694   -0.581  0.000   0.000
+46962.00    0.593   -0.42   0.000   0.000
+46963.00    0.179   -0.295  0.000   0.000
+46964.00    -0.311  -0.177  0.000   0.000
+46965.00    -0.683  -0.125  0.000   0.000
+46966.00    -0.751  -0.236  0.000   0.000
+46967.00    -0.609  -0.463  0.000   0.000
+46968.00    -0.539  -0.641  0.000   0.000
+46969.00    -0.718  -0.657  0.000   0.000
+46970.00    -1.184  -0.532  0.000   0.000
+46971.00    -1.594  -0.649  0.000   0.000
+46972.00    -1.945  -0.891  0.000   0.000
+46973.00    -2.344  -0.879  0.000   0.000
+46974.00    -2.655  -0.559  0.000   0.000
+46975.00    -2.707  -0.154  0.000   0.000
+46976.00    -2.274  -0.082  0.000   0.000
+46977.00    -1.457  -0.241  0.000   0.000
+46978.00    -0.698  -0.195  0.000   0.000
+46979.00    -0.394  0.046   0.000   0.000
+46980.00    -0.789  0.147   0.000   0.000
+46981.00    -1.793  0.018   0.000   0.000
+46982.00    -2.994  -0.114  0.000   0.000
+46983.00    -4.034  -0.045  0.000   0.000
+46984.00    -4.8    0.136   0.000   0.000
+46985.00    -5.22   0.197   0.000   0.000
+46986.00    -5.067  0.109   0.000   0.000
+46987.00    -4.402  0.074   0.000   0.000
+46988.00    -3.672  0.191   0.000   0.000
+46989.00    -3.319  0.291   0.000   0.000
+46990.00    -3.523  0.203   0.000   0.000
+46991.00    -4.13   0.029   0.000   0.000
+46992.00    -4.927  -0.021  0.000   0.000
+46993.00    -5.712  0.047   0.000   0.000
+46994.00    -6.226  0.012   0.000   0.000
+46995.00    -6.433  -0.129  0.000   0.000
+46996.00    -6.574  -0.172  0.000   0.000
+46997.00    -6.743  -0.13   0.000   0.000
+46998.00    -6.845  -0.246  0.000   0.000
+46999.00    -6.713  -0.728  0.000   0.000
+47000.00    -6.47   -0.981  0.000   0.000
+47001.00    -6.292  -0.888  0.000   0.000
+47002.00    -6.218  -0.512  0.000   0.000
+47003.00    -6.222  -0.04   0.000   0.000
+47004.00    -6.281  0.264   0.000   0.000
+47005.00    -6.363  0.338   0.000   0.000
+47006.00    -6.43   0.314   0.000   0.000
+47007.00    -6.528  0.273   0.000   0.000
+47008.00    -6.793  0.148   0.000   0.000
+47009.00    -7.282  -0.111  0.000   0.000
+47010.00    -7.851  -0.391  0.000   0.000
+47011.00    -8.282  -0.534  0.000   0.000
+47012.00    -8.423  -0.533  0.000   0.000
+47013.00    -8.236  -0.506  0.000   0.000
+47014.00    -7.793  -0.467  0.000   0.000
+47015.00    -7.319  -0.311  0.000   0.000
+47016.00    -7.053  -0.078  0.000   0.000
+47017.00    -6.993  -0.052  0.000   0.000
+47018.00    -6.859  -0.466  0.000   0.000
+47019.00    -6.603  -1.1    0.000   0.000
+47020.00    -6.641  -1.438  0.000   0.000
+47021.00    -7.136  -1.366  0.000   0.000
+47022.00    -7.828  -1.18   0.000   0.000
+47023.00    -8.349  -1.141  0.000   0.000
+47024.00    -8.597  -1.197  0.000   0.000
+47025.00    -8.723  -1.16   0.000   0.000
+47026.00    -8.859  -1.005  0.000   0.000
+47027.00    -8.969  -0.88   0.000   0.000
+47028.00    -9.025  -0.842  0.000   0.000
+47029.00    -9.12   -0.749  0.000   0.000
+47030.00    -9.337  -0.483  0.000   0.000
+47031.00    -9.611  -0.287  0.000   0.000
+47032.00    -9.766  -0.312  0.000   0.000
+47033.00    -9.61   -0.402  0.000   0.000
+47034.00    -9.027  -0.281  0.000   0.000
+47035.00    -8.509  -0.174  0.000   0.000
+47036.00    -8.48   -0.151  0.000   0.000
+47037.00    -8.932  -0.194  0.000   0.000
+47038.00    -9.637  -0.308  0.000   0.000
+47039.00    -10.255 -0.45   0.000   0.000
+47040.00    -10.417 -0.573  0.000   0.000
+47041.00    -10.029 -0.651  0.000   0.000
+47042.00    -9.29   -0.624  0.000   0.000
+47043.00    -8.587  -0.416  0.000   0.000
+47044.00    -8.29   -0.075  0.000   0.000
+47045.00    -8.45   0.183   0.000   0.000
+47046.00    -8.761  0.165   0.000   0.000
+47047.00    -8.99   -0.054  0.000   0.000
+47048.00    -9.275  -0.206  0.000   0.000
+47049.00    -9.842  -0.165  0.000   0.000
+47050.00    -10.563 -0.089  0.000   0.000
+47051.00    -11.005 -0.149  0.000   0.000
+47052.00    -10.949 -0.292  0.000   0.000
+47053.00    -10.581 -0.333  0.000   0.000
+47054.00    -10.176 -0.225  0.000   0.000
+47055.00    -9.859  -0.114  0.000   0.000
+47056.00    -9.614  -0.112  0.000   0.000
+47057.00    -9.438  -0.129  0.000   0.000
+47058.00    -9.309  -0.007  0.000   0.000
+47059.00    -9.117  0.263   0.000   0.000
+47060.00    -8.764  0.515   0.000   0.000
+47061.00    -8.383  0.58    0.000   0.000
+47062.00    -8.196  0.436   0.000   0.000
+47063.00    -8.331  0.203   0.000   0.000
+47064.00    -8.724  0.02    0.000   0.000
+47065.00    -9.242  -0.074  0.000   0.000
+47066.00    -9.577  -0.147  0.000   0.000
+47067.00    -9.584  -0.248  0.000   0.000
+47068.00    -9.251  -0.374  0.000   0.000
+47069.00    -8.618  -0.444  0.000   0.000
+47070.00    -7.876  -0.359  0.000   0.000
+47071.00    -7.311  -0.089  0.000   0.000
+47072.00    -7.129  0.293   0.000   0.000
+47073.00    -7.287  0.627   0.000   0.000
+47074.00    -7.541  0.756   0.000   0.000
+47075.00    -7.731  0.651   0.000   0.000
+47076.00    -7.946  0.444   0.000   0.000
+47077.00    -8.366  0.274   0.000   0.000
+47078.00    -8.949  0.16    0.000   0.000
+47079.00    -9.362  0.082   0.000   0.000
+47080.00    -9.281  0.097   0.000   0.000
+47081.00    -8.711  0.264   0.000   0.000
+47082.00    -7.906  0.515   0.000   0.000
+47083.00    -7.139  0.67    0.000   0.000
+47084.00    -6.603  0.608   0.000   0.000
+47085.00    -6.414  0.389   0.000   0.000
+47086.00    -6.384  0.27    0.000   0.000
+47087.00    -6.344  0.39    0.000   0.000
+47088.00    -6.341  0.658   0.000   0.000
+47089.00    -6.444  0.948   0.000   0.000
+47090.00    -6.725  1.123   0.000   0.000
+47091.00    -7.055  1.224   0.000   0.000
+47092.00    -7.282  1.206   0.000   0.000
+47093.00    -7.361  1.096   0.000   0.000
+47094.00    -7.273  1.006   0.000   0.000
+47095.00    -6.979  0.973   0.000   0.000
+47096.00    -6.469  0.959   0.000   0.000
+47097.00    -5.804  0.947   0.000   0.000
+47098.00    -5.128  0.961   0.000   0.000
+47099.00    -4.629  1.007   0.000   0.000
+47100.00    -4.44   1.06    0.000   0.000
+47101.00    -4.597  1.185   0.000   0.000
+47102.00    -4.908  1.365   0.000   0.000
+47103.00    -5.121  1.497   0.000   0.000
+47104.00    -5.123  1.489   0.000   0.000
+47105.00    -5.033  1.279   0.000   0.000
+47106.00    -5.125  1.015   0.000   0.000
+47107.00    -5.393  0.856   0.000   0.000
+47108.00    -5.526  0.869   0.000   0.000
+47109.00    -5.24   1.06    0.000   0.000
+47110.00    -4.455  1.315   0.000   0.000
+47111.00    -3.587  1.43    0.000   0.000
+47112.00    -2.974  1.36    0.000   0.000
+47113.00    -2.673  1.272   0.000   0.000
+47114.00    -2.695  1.326   0.000   0.000
+47115.00    -3.032  1.518   0.000   0.000
+47116.00    -3.601  1.699   0.000   0.000
+47117.00    -4.19   1.766   0.000   0.000
+47118.00    -4.579  1.733   0.000   0.000
+47119.00    -4.704  1.656   0.000   0.000
+47120.00    -4.653  1.566   0.000   0.000
+47121.00    -4.532  1.498   0.000   0.000
+47122.00    -4.375  1.518   0.000   0.000
+47123.00    -4.212  1.647   0.000   0.000
+47124.00    -4.126  1.807   0.000   0.000
+47125.00    -4.098  1.91    0.000   0.000
+47126.00    -4.076  1.935   0.000   0.000
+47127.00    -4.039  1.941   0.000   0.000
+47128.00    -3.996  2.006   0.000   0.000
+47129.00    -3.955  2.164   0.000   0.000
+47130.00    -3.876  2.389   0.000   0.000
+47131.00    -3.763  2.548   0.000   0.000
+47132.00    -3.563  2.569   0.000   0.000
+47133.00    -3.235  2.47    0.000   0.000
+47134.00    -2.848  2.352   0.000   0.000
+47135.00    -2.527  2.391   0.000   0.000
+47136.00    -2.336  2.569   0.000   0.000
+47137.00    -2.222  2.66    0.000   0.000
+47138.00    -2.123  2.326   0.000   0.000
+47139.00    -1.873  1.954   0.000   0.000
+47140.00    -1.522  1.794   0.000   0.000
+47141.00    -1.224  1.859   0.000   0.000
+47142.00    -1.099  2.151   0.000   0.000
+47143.00    -1.287  2.483   0.000   0.000
+47144.00    -1.826  2.586   0.000   0.000
+47145.00    -2.532  2.373   0.000   0.000
+47146.00    -3.189  2.099   0.000   0.000
+47147.00    -3.696  2.006   0.000   0.000
+47148.00    -4.066  2.118   0.000   0.000
+47149.00    -4.232  2.356   0.000   0.000
+47150.00    -3.987  2.35    0.000   0.000
+47151.00    -3.544  2.226   0.000   0.000
+47152.00    -3.221  2.218   0.000   0.000
+47153.00    -3.113  2.251   0.000   0.000
+47154.00    -3.119  2.212   0.000   0.000
+47155.00    -3.094  2.148   0.000   0.000
+47156.00    -3.027  2.192   0.000   0.000
+47157.00    -3.027  2.368   0.000   0.000
+47158.00    -3.147  2.575   0.000   0.000
+47159.00    -3.321  2.709   0.000   0.000
+47160.00    -3.441  2.728   0.000   0.000
+47161.00    -3.42   2.636   0.000   0.000
+47162.00    -3.284  2.451   0.000   0.000
+47163.00    -3.151  2.267   0.000   0.000
+47164.00    -3.083  2.276   0.000   0.000
+47165.00    -2.964  2.600   0.000   0.000
+47166.00    -2.683  2.845   0.000   0.000
+47167.00    -2.267  2.817   0.000   0.000
+47168.00    -1.882  2.728   0.000   0.000
+47169.00    -1.681  2.872   0.000   0.000
+47170.00    -1.559  3.005   0.000   0.000
+47171.00    -1.647  2.958   0.000   0.000
+47172.00    -2.132  2.731   0.000   0.000
+47173.00    -2.832  2.446   0.000   0.000
+47174.00    -3.436  2.38    0.000   0.000
+47175.00    -3.626  2.377   0.000   0.000
+47176.00    -3.527  2.294   0.000   0.000
+47177.00    -3.273  2.121   0.000   0.000
+47178.00    -2.855  2.083   0.000   0.000
+47179.00    -2.454  2.135   0.000   0.000
+47180.00    -2.19   2.134   0.000   0.000
+47181.00    -2.2    2.117   0.000   0.000
+47182.00    -2.504  2.021   0.000   0.000
+47183.00    -2.961  1.918   0.000   0.000
+47184.00    -3.497  2.019   0.000   0.000
+47185.00    -3.997  2.221   0.000   0.000
+47186.00    -4.368  2.345   0.000   0.000
+47187.00    -4.502  2.359   0.000   0.000
+47188.00    -4.355  2.416   0.000   0.000
+47189.00    -4.003  2.642   0.000   0.000
+47190.00    -3.54   2.728   0.000   0.000
+47191.00    -3.07   2.534   0.000   0.000
+47192.00    -2.683  2.208   0.000   0.000
+47193.00    -2.379  1.975   0.000   0.000
+47194.00    -2.042  1.928   0.000   0.000
+47195.00    -1.592  1.964   0.000   0.000
+47196.00    -1.177  2.000   0.000   0.000
+47197.00    -0.958  2.033   0.000   0.000
+47198.00    -0.985  2.086   0.000   0.000
+47199.00    -1.242  2.077   0.000   0.000
+47200.00    -1.663  1.831   0.000   0.000
+47201.00    -2.093  1.400   0.000   0.000
+47202.00    -2.409  1.094   0.000   0.000
+47203.00    -2.685  1.172   0.000   0.000
+47204.00    -3.087  1.546   0.000   0.000
+47205.00    -3.499  1.716   0.000   0.000
+47206.00    -3.561  1.551   0.000   0.000
+47207.00    -3.088  1.375   0.000   0.000
+47208.00    -2.366  1.432   0.000   0.000
+47209.00    -1.903  1.61    0.000   0.000
+47210.00    -1.942  1.665   0.000   0.000
+47211.00    -2.322  1.56    0.000   0.000
+47212.00    -2.798  1.458   0.000   0.000
+47213.00    -3.213  1.399   0.000   0.000
+47214.00    -3.384  1.199   0.000   0.000
+47215.00    -3.133  0.738   0.000   0.000
+47216.00    -2.691  0.267   0.000   0.000
+47217.00    -2.334  0.043   0.000   0.000
+47218.00    -2.133  0.049   0.000   0.000
+47219.00    -2.008  0.107   0.000   0.000
+47220.00    -1.886  0.152   0.000   0.000
+47221.00    -1.806  0.305   0.000   0.000
+47222.00    -1.78   0.644   0.000   0.000
+47223.00    -1.746  1.027   0.000   0.000
+47224.00    -1.693  1.236   0.000   0.000
+47225.00    -1.69   1.215   0.000   0.000
+47226.00    -1.765  1.079   0.000   0.000
+47227.00    -1.843  0.932   0.000   0.000
+47228.00    -1.821  0.76    0.000   0.000
+47229.00    -1.631  0.521   0.000   0.000
+47230.00    -1.299  0.274   0.000   0.000
+47231.00    -1.074  0.205   0.000   0.000
+47232.00    -1.146  0.257   0.000   0.000
+47233.00    -1.442  0.181   0.000   0.000
+47234.00    -1.67   -0.115  0.000   0.000
+47235.00    -1.614  -0.447  0.000   0.000
+47236.00    -1.494  -0.338  0.000   0.000
+47237.00    -1.542  0.149   0.000   0.000
+47238.00    -1.726  0.531   0.000   0.000
+47239.00    -1.862  0.477   0.000   0.000
+47240.00    -1.998  0.03    0.000   0.000
+47241.00    -2.134  -0.358  0.000   0.000
+47242.00    -2.077  -0.61   0.000   0.000
+47243.00    -1.661  -0.857  0.000   0.000
+47244.00    -1.017  -1.026  0.000   0.000
+47245.00    -0.501  -0.986  0.000   0.000
+47246.00    -0.273  -0.762  0.000   0.000
+47247.00    -0.204  -0.548  0.000   0.000
+47248.00    -0.151  -0.456  0.000   0.000
+47249.00    -0.14   -0.392  0.000   0.000
+47250.00    -0.229  -0.239  0.000   0.000
+47251.00    -0.383  -0.046  0.000   0.000
+47252.00    -0.525  0.02    0.000   0.000
+47253.00    -0.657  -0.109  0.000   0.000
+47254.00    -0.822  -0.3    0.000   0.000
+47255.00    -0.987  -0.393  0.000   0.000
+47256.00    -1.071  -0.373  0.000   0.000
+47257.00    -1.048  -0.34   0.000   0.000
+47258.00    -0.947  -0.433  0.000   0.000
+47259.00    -0.807  -0.769  0.000   0.000
+47260.00    -0.636  -1.421  0.000   0.000
+47261.00    -0.403  -2.123  0.000   0.000
+47262.00    -0.055  -2.436  0.000   0.000
+47263.00    0.346   -2.302  0.000   0.000
+47264.00    0.616   -1.924  0.000   0.000
+47265.00    0.594   -1.606  0.000   0.000
+47266.00    0.456   -1.322  0.000   0.000
+47267.00    0.301   -1.09   0.000   0.000
+47268.00    0.038   -0.979  0.000   0.000
+47269.00    -0.402  -0.982  0.000   0.000
+47270.00    -0.975  -1.118  0.000   0.000
+47271.00    -1.409  -1.409  0.000   0.000
+47272.00    -1.415  -1.748  0.000   0.000
+47273.00    -0.92   -1.979  0.000   0.000
+47274.00    -0.472  -2.042  0.000   0.000
+47275.00    -0.354  -2.148  0.000   0.000
+47276.00    -0.41   -2.343  0.000   0.000
+47277.00    -0.513  -2.398  0.000   0.000
+47278.00    -0.625  -2.05   0.000   0.000
+47279.00    -0.626  -1.265  0.000   0.000
+47280.00    -0.652  -0.638  0.000   0.000
+47281.00    -0.733  -0.478  0.000   0.000
+47282.00    -0.802  -0.687  0.000   0.000
+47283.00    -0.839  -1.071  0.000   0.000
+47284.00    -0.812  -1.447  0.000   0.000
+47285.00    -0.632  -1.624  0.000   0.000
+47286.00    -0.298  -1.616  0.000   0.000
+47287.00    0.129   -1.546  0.000   0.000
+47288.00    0.572   -1.493  0.000   0.000
+47289.00    0.911   -1.503  0.000   0.000
+47290.00    1.015   -1.596  0.000   0.000
+47291.00    0.865   -1.71   0.000   0.000
+47292.00    0.517   -1.748  0.000   0.000
+47293.00    0.07    -1.642  0.000   0.000
+47294.00    -0.326  -1.402  0.000   0.000
+47295.00    -0.508  -1.109  0.000   0.000
+47296.00    -0.454  -0.913  0.000   0.000
+47297.00    -0.221  -0.918  0.000   0.000
+47298.00    0.118   -1.132  0.000   0.000
+47299.00    0.454   -1.465  0.000   0.000
+47300.00    0.772   -1.567  0.000   0.000
+47301.00    0.863   -1.53   0.000   0.000
+47302.00    0.63    -1.513  0.000   0.000
+47303.00    0.237   -1.614  0.000   0.000
+47304.00    -0.041  -1.736  0.000   0.000
+47305.00    -0.139  -1.718  0.000   0.000
+47306.00    -0.219  -1.497  0.000   0.000
+47307.00    -0.421  -1.172  0.000   0.000
+47308.00    -0.728  -0.94   0.000   0.000
+47309.00    -0.988  -0.921  0.000   0.000
+47310.00    -1.079  -1.093  0.000   0.000
+47311.00    -1.045  -1.351  0.000   0.000
+47312.00    -1.024  -1.623  0.000   0.000
+47313.00    -1.092  -1.871  0.000   0.000
+47314.00    -1.225  -2.034  0.000   0.000
+47315.00    -1.407  -2.049  0.000   0.000
+47316.00    -1.579  -1.964  0.000   0.000
+47317.00    -1.653  -1.895  0.000   0.000
+47318.00    -1.499  -1.945  0.000   0.000
+47319.00    -1.232  -2.061  0.000   0.000
+47320.00    -1.091  -2.097  0.000   0.000
+47321.00    -1.117  -1.979  0.000   0.000
+47322.00    -1.291  -1.717  0.000   0.000
+47323.00    -1.58   -1.402  0.000   0.000
+47324.00    -1.849  -1.181  0.000   0.000
+47325.00    -1.906  -1.144  0.000   0.000
+47326.00    -1.707  -1.243  0.000   0.000
+47327.00    -1.391  -1.326  0.000   0.000
+47328.00    -1.161  -1.263  0.000   0.000
+47329.00    -1.154  -1.08   0.000   0.000
+47330.00    -1.407  -0.964  0.000   0.000
+47331.00    -1.763  -1.049  0.000   0.000
+47332.00    -2.111  -1.318  0.000   0.000
+47333.00    -2.451  -1.542  0.000   0.000
+47334.00    -2.872  -1.467  0.000   0.000
+47335.00    -3.436  -1.377  0.000   0.000
+47336.00    -4.059  -1.476  0.000   0.000
+47337.00    -4.558  -1.672  0.000   0.000
+47338.00    -4.718  -1.735  0.000   0.000
+47339.00    -4.521  -1.491  0.000   0.000
+47340.00    -4.186  -1.094  0.000   0.000
+47341.00    -3.914  -0.826  0.000   0.000
+47342.00    -3.73   -0.75   0.000   0.000
+47343.00    -3.662  -0.827  0.000   0.000
+47344.00    -3.921  -1.103  0.000   0.000
+47345.00    -4.717  -1.679  0.000   0.000
+47346.00    -5.741  -2.148  0.000   0.000
+47347.00    -6.628  -2.04   0.000   0.000
+47348.00    -7.024  -1.525  0.000   0.000
+47349.00    -7.052  -0.787  0.000   0.000
+47350.00    -6.886  -0.459  0.000   0.000
+47351.00    -6.928  -0.619  0.000   0.000
+47352.00    -7.301  -0.988  0.000   0.000
+47353.00    -7.643  -1.347  0.000   0.000
+47354.00    -7.765  -1.655  0.000   0.000
+47355.00    -7.874  -2.1    0.000   0.000
+47356.00    -7.869  -2.41   0.000   0.000
+47357.00    -7.635  -2.093  0.000   0.000
+47358.00    -7.327  -1.325  0.000   0.000
+47359.00    -7.175  -0.574  0.000   0.000
+47360.00    -7.375  -0.135  0.000   0.000
+47361.00    -7.818  0.132   0.000   0.000
+47362.00    -8.289  0.326   0.000   0.000
+47363.00    -8.751  0.346   0.000   0.000
+47364.00    -9.22   -0.01   0.000   0.000
+47365.00    -9.503  -0.741  0.000   0.000
+47366.00    -9.535  -1.369  0.000   0.000
+47367.00    -9.456  -1.491  0.000   0.000
+47368.00    -9.497  -1.227  0.000   0.000
+47369.00    -9.521  -1.108  0.000   0.000
+47370.00    -9.421  -1.333  0.000   0.000
+47371.00    -9.136  -1.485  0.000   0.000
+47372.00    -8.803  -1.305  0.000   0.000
+47373.00    -8.733  -1.059  0.000   0.000
+47374.00    -9.075  -1.083  0.000   0.000
+47375.00    -9.672  -1.442  0.000   0.000
+47376.00    -10.262 -1.842  0.000   0.000
+47377.00    -10.662 -1.939  0.000   0.000
+47378.00    -10.747 -1.632  0.000   0.000
+47379.00    -10.588 -1.303  0.000   0.000
+47380.00    -10.368 -1.33   0.000   0.000
+47381.00    -10.192 -1.527  0.000   0.000
+47382.00    -10.022 -1.683  0.000   0.000
+47383.00    -9.794  -1.786  0.000   0.000
+47384.00    -9.552  -1.731  0.000   0.000
+47385.00    -9.397  -1.403  0.000   0.000
+47386.00    -9.376  -0.883  0.000   0.000
+47387.00    -9.491  -0.448  0.000   0.000
+47388.00    -9.72   -0.316  0.000   0.000
+47389.00    -9.971  -0.437  0.000   0.000
+47390.00    -10.123 -0.604  0.000   0.000
+47391.00    -10.205 -0.747  0.000   0.000
+47392.00    -10.397 -0.966  0.000   0.000
+47393.00    -10.766 -1.291  0.000   0.000
+47394.00    -11.131 -1.542  0.000   0.000
+47395.00    -11.277 -1.537  0.000   0.000
+47396.00    -11.185 -1.335  0.000   0.000
+47397.00    -10.99  -1.151  0.000   0.000
+47398.00    -10.81  -1.05   0.000   0.000
+47399.00    -10.733 -0.886  0.000   0.000
+47400.00    -10.846 -0.589  0.000   0.000
+47401.00    -11.141 -0.362  0.000   0.000
+47402.00    -11.436 -0.409  0.000   0.000
+47403.00    -11.607 -0.636  0.000   0.000
+47404.00    -11.795 -0.832  0.000   0.000
+47405.00    -12.2   -1.02   0.000   0.000
+47406.00    -12.762 -1.204  0.000   0.000
+47407.00    -13.165 -1.448  0.000   0.000
+47408.00    -13.239 -1.7    0.000   0.000
+47409.00    -13.053 -1.797  0.000   0.000
+47410.00    -12.622 -1.765  0.000   0.000
+47411.00    -11.938 -1.708  0.000   0.000
+47412.00    -11.08  -1.588  0.000   0.000
+47413.00    -10.257 -1.228  0.000   0.000
+47414.00    -9.698  -0.574  0.000   0.000
+47415.00    -9.448  -0.053  0.000   0.000
+47416.00    -9.473  0.009   0.000   0.000
+47417.00    -9.709  -0.336  0.000   0.000
+47418.00    -10.03  -0.813  0.000   0.000
+47419.00    -10.321 -1.176  0.000   0.000
+47420.00    -10.584 -1.381  0.000   0.000
+47421.00    -10.851 -1.522  0.000   0.000
+47422.00    -11.036 -1.624  0.000   0.000
+47423.00    -10.958 -1.642  0.000   0.000
+47424.00    -10.562 -1.58   0.000   0.000
+47425.00    -9.966  -1.506  0.000   0.000
+47426.00    -9.532  -1.382  0.000   0.000
+47427.00    -9.523  -1.096  0.000   0.000
+47428.00    -9.996  -0.668  0.000   0.000
+47429.00    -10.757 -0.33   0.000   0.000
+47430.00    -11.373 -0.294  0.000   0.000
+47431.00    -11.611 -0.456  0.000   0.000
+47432.00    -11.68  -0.521  0.000   0.000
+47433.00    -11.885 -0.427  0.000   0.000
+47434.00    -12.136 -0.45   0.000   0.000
+47435.00    -12.027 -0.829  0.000   0.000
+47436.00    -11.425 -1.362  0.000   0.000
+47437.00    -10.659 -1.612  0.000   0.000
+47438.00    -10.096 -1.346  0.000   0.000
+47439.00    -9.802  -0.615  0.000   0.000
+47440.00    -9.68   0.472   0.000   0.000
+47441.00    -9.673  1.342   0.000   0.000
+47442.00    -9.803  1.47    0.000   0.000
+47443.00    -10.097 1.079   0.000   0.000
+47444.00    -10.541 0.424   0.000   0.000
+47445.00    -11.122 -0.145  0.000   0.000
+47446.00    -11.735 -0.439  0.000   0.000
+47447.00    -12.164 -0.406  0.000   0.000
+47448.00    -12.223 -0.145  0.000   0.000
+47449.00    -11.874 0.093   0.000   0.000
+47450.00    -11.175 0.064   0.000   0.000
+47451.00    -10.311 -0.235  0.000   0.000
+47452.00    -9.469  -0.659  0.000   0.000
+47453.00    -8.822  -1.05   0.000   0.000
+47454.00    -8.561  -1.229  0.000   0.000
+47455.00    -8.456  -1.1    0.000   0.000
+47456.00    -8.48   -0.713  0.000   0.000
+47457.00    -8.623  -0.29   0.000   0.000
+47458.00    -8.619  -0.065  0.000   0.000
+47459.00    -8.291  -0.055  0.000   0.000
+47460.00    -7.836  -0.072  0.000   0.000
+47461.00    -7.589  0.022   0.000   0.000
+47462.00    -7.577  0.13    0.000   0.000
+47463.00    -7.49   0.088   0.000   0.000
+47464.00    -7.131  -0.066  0.000   0.000
+47465.00    -6.675  -0.142  0.000   0.000
+47466.00    -6.359  -0.035  0.000   0.000
+47467.00    -6.152  0.163   0.000   0.000
+47468.00    -5.85   0.359   0.000   0.000
+47469.00    -5.48   0.629   0.000   0.000
+47470.00    -5.301  1.072   0.000   0.000
+47471.00    -5.472  1.329   0.000   0.000
+47472.00    -5.851  1.258   0.000   0.000
+47473.00    -6.198  1.09    0.000   0.000
+47474.00    -6.467  0.902   0.000   0.000
+47475.00    -6.609  0.694   0.000   0.000
+47476.00    -6.371  0.536   0.000   0.000
+47477.00    -5.85   0.561   0.000   0.000
+47478.00    -5.318  0.737   0.000   0.000
+47479.00    -4.851  0.864   0.000   0.000
+47480.00    -4.436  0.84    0.000   0.000
+47481.00    -4.045  0.73    0.000   0.000
+47482.00    -3.721  0.67    0.000   0.000
+47483.00    -3.585  0.753   0.000   0.000
+47484.00    -3.753  0.979   0.000   0.000
+47485.00    -4.185  1.249   0.000   0.000
+47486.00    -4.658  1.407   0.000   0.000
+47487.00    -4.955  1.378   0.000   0.000
+47488.00    -5.071  1.231   0.000   0.000
+47489.00    -5.156  1.098   0.000   0.000
+47490.00    -5.282  1.044   0.000   0.000
+47491.00    -5.325  1.064   0.000   0.000
+47492.00    -5.158  1.158   0.000   0.000
+47493.00    -4.809  1.342   0.000   0.000
+47494.00    -4.386  1.581   0.000   0.000
+47495.00    -3.903  1.784   0.000   0.000
+47496.00    -3.338  1.883   0.000   0.000
+47497.00    -2.752  1.935   0.000   0.000
+47498.00    -2.286  2.025   0.000   0.000
+47499.00    -2.072  2.101   0.000   0.000
+47500.00    -2.17   2.024   0.000   0.000
+47501.00    -2.503  1.759   0.000   0.000
+47502.00    -2.969  1.422   0.000   0.000
+47503.00    -3.49   1.18    0.000   0.000
+47504.00    -3.964  1.131   0.000   0.000
+47505.00    -4.273  1.279   0.000   0.000
+47506.00    -4.278  1.485   0.000   0.000
+47507.00    -3.896  1.577   0.000   0.000
+47508.00    -3.323  1.53    0.000   0.000
+47509.00    -2.854  1.438   0.000   0.000
+47510.00    -2.721  1.42    0.000   0.000
+47511.00    -2.887  1.446   0.000   0.000
+47512.00    -3.226  1.524   0.000   0.000
+47513.00    -3.616  1.717   0.000   0.000
+47514.00    -3.893  2.052   0.000   0.000
+47515.00    -3.901  2.485   0.000   0.000
+47516.00    -3.67   2.594   0.000   0.000
+47517.00    -3.282  2.315   0.000   0.000
+47518.00    -2.825  1.921   0.000   0.000
+47519.00    -2.395  1.664   0.000   0.000
+47520.00    -2.047  1.631   0.000   0.000
+47521.00    -1.787  1.731   0.000   0.000
+47522.00    -1.611  1.817   0.000   0.000
+47523.00    -1.541  1.788   0.000   0.000
+47524.00    -1.61   1.679   0.000   0.000
+47525.00    -1.815  1.629   0.000   0.000
+47526.00    -2.118  1.714   0.000   0.000
+47527.00    -2.471  1.844   0.000   0.000
+47528.00    -2.806  1.872   0.000   0.000
+47529.00    -3.02   1.781   -1.200  0.700
+47530.00    -3.061  1.702   -1.200  0.600
+47531.00    -3.009  1.731   -1.300  0.500
+47532.00    -2.991  1.814   -1.500  0.400
+47533.00    -3.001  1.855   -1.600  0.300
+47534.00    -2.909  1.834   -1.700  0.200
+47535.00    -2.668  1.789   -1.800  0.300
+47536.00    -2.437  1.734   -1.900  0.300
+47537.00    -2.425  1.635   -2.100  0.400
+47538.00    -2.674  1.500   -2.100  0.600
+47539.00    -3.06   1.435   -2.200  0.700
+47540.00    -3.433  1.548   -2.100  0.800
+47541.00    -3.619  1.685   -2.000  0.800
+47542.00    -3.626  1.772   -1.900  0.900
+47543.00    -3.488  1.762   -1.800  1.000
+47544.00    -3.22   1.622   -1.700  1.000
+47545.00    -2.864  1.38    -1.700  1.000
+47546.00    -2.5    1.145   -1.700  1.000
+47547.00    -2.255  1.065   -1.700  1.000
+47548.00    -2.205  1.229   -1.700  0.900
+47549.00    -2.27   1.593   -1.800  0.800
+47550.00    -2.289  1.987   -2.100  0.700
+47551.00    -2.17   2.095   -2.400  0.600
+47552.00    -2.029  1.896   -2.600  0.500
+47553.00    -2.004  1.627   -2.900  0.400
+47554.00    -2.144  1.468   -3.000  0.300
+47555.00    -2.479  1.417   -2.700  0.300
+47556.00    -2.938  1.312   -2.300  0.400
+47557.00    -3.355  1.124   -1.900  0.500
+47558.00    -3.579  0.996   -1.400  0.600
+47559.00    -3.623  0.965   -1.000  0.700
+47560.00    -3.594  0.84    -0.300  1.000
+47561.00    -3.554  0.681   0.000   1.100
+47562.00    -3.323  0.617   0.200   1.100
+47563.00    -2.796  0.756   0.400   1.100
+47564.00    -2.277  1.069   0.300   1.100
+47565.00    -2.2    1.304   -0.200  0.900
+47566.00    -2.483  1.477   -0.800  0.700
+47567.00    -2.843  1.548   -1.500  0.500
+47568.00    -3.115  1.371   -2.200  0.300
+47569.00    -3.28   0.854   -2.800  0.100
+47570.00    -3.317  0.336   -2.800  -0.100
+47571.00    -3.205  -0.036  -2.800  -0.200
+47572.00    -2.952  -0.259  -2.700  -0.300
+47573.00    -2.609  -0.32   -2.600  -0.300
+47574.00    -2.269  -0.242  -2.500  -0.400
+47575.00    -2.044  -0.055  -2.500  -0.300
+47576.00    -2.02   0.113   -2.600  -0.200
+47577.00    -1.96   0.328   -2.800  -0.100
+47578.00    -1.794  0.592   -2.900  -0.100
+47579.00    -1.752  0.733   -3.000  0.000
+47580.00    -1.737  0.631   -3.000  -0.200
+47581.00    -1.716  0.394   -3.100  -0.400
+47582.00    -1.682  0.19    -3.100  -0.600
+47583.00    -1.614  0.022   -3.000  -0.800
+47584.00    -1.562  -0.203  -2.900  -1.000
+47585.00    -1.565  -0.471  -2.700  -1.100
+47586.00    -1.585  -0.744  -2.500  -1.100
+47587.00    -1.712  -0.899  -2.200  -1.200
+47588.00    -2.125  -1.004  -2.100  -1.200
+47589.00    -2.779  -1.219  -1.900  -1.100
+47590.00    -3.303  -1.423  -2.200  -1.000
+47591.00    -3.291  -1.42   -2.400  -0.800
+47592.00    -2.92   -1.089  -2.600  -0.700
+47593.00    -2.722  -0.613  -2.800  -0.500
+47594.00    -2.909  -0.34   -2.900  -0.500
+47595.00    -3.25   -0.371  -2.600  -0.700
+47596.00    -3.438  -0.559  -2.300  -1.000
+47597.00    -3.346  -0.792  -2.000  -1.400
+47598.00    -2.976  -1.099  -1.600  -1.700
+47599.00    -2.402  -1.481  -1.300  -2.100
+47600.00    -1.825  -1.792  -1.200  -2.300
+47601.00    -1.467  -1.894  -1.100  -2.500
+47602.00    -1.37   -1.811  -1.100  -2.700
+47603.00    -1.411  -1.674  -1.100  -2.800
+47604.00    -1.45   -1.5    -1.100  -2.800
+47605.00    -1.426  -1.205  -1.100  -2.700
+47606.00    -1.333  -0.837  -1.100  -2.500
+47607.00    -1.191  -0.622  -1.100  -2.400
+47608.00    -1.062  -0.755  -1.000  -2.200
+47609.00    -0.992  -1.208  -0.800  -2.100
+47610.00    -0.932  -1.799  -0.400  -2.200
+47611.00    -0.817  -2.283  0.100   -2.300
+47612.00    -0.676  -2.505  0.500   -2.500
+47613.00    -0.589  -2.497  0.900   -2.700
+47614.00    -0.601  -2.379  1.300   -2.900
+47615.00    -0.747  -2.296  1.400   -2.900
+47616.00    -1.083  -2.205  1.300   -2.900
+47617.00    -1.483  -2.227  1.100   -2.800
+47618.00    -1.605  -2.406  0.900   -2.800
+47619.00    -1.274  -2.457  0.500   -2.700
+47620.00    -0.737  -2.163  -0.400  -2.600
+47621.00    -0.446  -1.693  -1.100  -2.700
+47622.00    -0.585  -1.429  -1.700  -2.900
+47623.00    -0.953  -1.531  -2.200  -3.000
+47624.00    -1.275  -1.831  -2.500  -3.200
+47625.00    -1.416  -2.156  -2.200  -3.300
+47626.00    -1.283  -2.54   -1.600  -3.400
+47627.00    -0.88   -2.963  -1.000  -3.400
+47628.00    -0.458  -3.231  -0.400  -3.500
+47629.00    -0.354  -3.152  0.200   -3.500
+47630.00    -0.609  -2.809  0.400   -3.400
+47631.00    -0.926  -2.47   0.600   -3.300
+47632.00    -1.006  -2.277  0.600   -3.100
+47633.00    -0.847  -2.136  0.600   -3.000
+47634.00    -0.624  -1.949  0.600   -2.900
+47635.00    -0.455  -1.834  0.500   -2.900
+47636.00    -0.352  -2.123  0.500   -2.900
+47637.00    -0.307  -2.737  0.400   -2.900
+47638.00    -0.262  -3.226  0.400   -2.900
+47639.00    -0.105  -3.333  0.400   -2.900
+47640.00    -0.029  -3.419  0.400   -2.900
+47641.00    -0.132  -3.434  0.400   -2.900
+47642.00    -0.305  -3.219  0.400   -2.800
+47643.00    -0.448  -2.993  0.300   -2.800
+47644.00    -0.46   -3.073  0.100   -2.800
+47645.00    -0.417  -3.312  -0.500  -2.700
+47646.00    -0.329  -3.531  -1.200  -2.600
+47647.00    -0.221  -3.544  -1.900  -2.600
+47648.00    -0.259  -3.226  -2.500  -2.600
+47649.00    -0.592  -2.738  -3.000  -2.600
+47650.00    -1.131  -2.414  -2.900  -3.000
+47651.00    -1.632  -2.428  -2.500  -3.300
+47652.00    -1.911  -2.665  -2.000  -3.600
+47653.00    -1.927  -2.937  -1.500  -3.900
+47654.00    -1.697  -3.193  -1.100  -4.100
+47655.00    -1.315  -3.433  -1.000  -4.100
+47656.00    -0.908  -3.552  -1.000  -3.900
+47657.00    -0.807  -3.416  -1.000  -3.800
+47658.00    -1.149  -3.086  -1.100  -3.600
+47659.00    -1.591  -2.817  -1.300  -3.400
+47660.00    -1.73   -2.761  -1.400  -3.400
+47661.00    -1.542  -2.817  -1.600  -3.400
+47662.00    -1.304  -2.821  -1.800  -3.400
+47663.00    -1.217  -2.794  -1.900  -3.500
+47664.00    -1.289  -2.88   -1.900  -3.500
+47665.00    -1.474  -3.109  -1.800  -3.600
+47666.00    -1.742  -3.325  -1.500  -3.800
+47667.00    -2.029  -3.351  -1.300  -3.900
+47668.00    -2.271  -3.175  -1.100  -3.900
+47669.00    -2.461  -2.953  -1.000  -3.900
+47670.00    -2.646  -2.856  -1.000  -3.600
+47671.00    -2.844  -2.924  -1.200  -3.300
+47672.00    -2.892  -3.049  -1.300  -3.000
+47673.00    -2.671  -3.159  -1.600  -2.600
+47674.00    -2.25   -3.256  -1.900  -2.300
+47675.00    -1.815  -3.331  -2.000  -2.300
+47676.00    -1.617  -3.317  -2.000  -2.400
+47677.00    -1.819  -3.206  -2.000  -2.500
+47678.00    -2.379  -3.079  -1.900  -2.700
+47679.00    -3.02   -3.004  -1.700  -2.900
+47680.00    -3.5    -2.928  -2.500  -4.000
+47681.00    -3.764  -2.961  -1.800  -4.200
+47682.00    -3.751  -3.207  -1.100  -4.200
+47683.00    -3.297  -3.377  -0.400  -4.300
+47684.00    -2.656  -3.34   0.100   -4.300
+47685.00    -2.366  -3.131  -0.100  -4.100
+47686.00    -2.653  -2.815  -0.400  -3.900
+47687.00    -3.246  -2.562  -0.900  -3.600
+47688.00    -3.702  -2.517  -1.500  -3.500
+47689.00    -3.868  -2.623  -2.000  -3.300
+47690.00    -3.926  -2.667  -2.500  -3.400
+47691.00    -4.068  -2.62   -2.800  -3.600
+47692.00    -4.307  -2.62   -3.200  -3.800
+47693.00    -4.571  -2.736  -3.500  -4.000
+47694.00    -4.813  -2.873  -3.800  -4.200
+47695.00    -5.008  -2.898  -3.700  -4.100
+47696.00    -5.133  -2.772  -3.700  -3.900
+47697.00    -5.205  -2.578  -3.600  -3.800
+47698.00    -5.312  -2.425  -3.600  -3.600
+47699.00    -5.569  -2.37   -3.600  -3.500
+47700.00    -6.026  -2.393  -4.000  -3.400
+47701.00    -6.518  -2.412  -4.500  -3.400
+47702.00    -6.923  -2.389  -5.000  -3.400
+47703.00    -7.211  -2.343  -5.300  -3.500
+47704.00    -7.374  -2.319  -5.500  -3.600
+47705.00    -7.405  -2.351  -5.100  -3.700
+47706.00    -7.32   -2.35   -4.500  -3.900
+47707.00    -7.167  -2.34   -3.800  -4.100
+47708.00    -7.011  -2.417  -3.000  -4.300
+47709.00    -6.922  -2.596  -2.300  -4.400
+47710.00    -6.962  -2.833  -2.100  -3.700
+47711.00    -6.994  -2.92   -1.800  -3.400
+47712.00    -7.04   -2.777  -1.800  -3.100
+47713.00    -7.29   -2.5    -1.900  -2.900
+47714.00    -7.804  -2.239  -2.200  -2.700
+47715.00    -8.394  -2.153  -3.200  -2.700
+47716.00    -8.816  -2.192  -4.400  -2.800
+47717.00    -8.905  -2.159  -5.600  -3.000
+47718.00    -8.809  -2.14   -6.900  -3.100
+47719.00    -8.886  -2.266  -8.000  -3.200
+47720.00    -9.428  -2.596  -8.400  -3.000
+47721.00    -10.19  -2.93   -8.600  -2.900
+47722.00    -10.698 -2.919  -8.700  -2.700
+47723.00    -10.795 -2.614  -8.800  -2.500
+47724.00    -10.463 -2.132  -8.900  -2.300
+47725.00    -10.059 -2.055  -9.200  -2.100
+47726.00    -9.743  -2.295  -9.600  -2.000
+47727.00    -9.567  -2.371  -10.000 -1.900
+47728.00    -9.661  -2.255  -10.300 -1.900
+47729.00    -10.131 -2.18   -10.600 -1.900
+47730.00    -10.909 -2.338  -10.800 -2.000
+47731.00    -11.646 -2.566  -10.900 -2.200
+47732.00    -11.967 -2.561  -11.000 -2.400
+47733.00    -11.822 -2.305  -10.900 -2.700
+47734.00    -11.589 -2.28   -10.600 -2.900
+47735.00    -11.568 -2.484  -9.900  -3.000
+47736.00    -11.665 -2.69   -9.100  -3.100
+47737.00    -11.771 -2.791  -8.200  -3.200
+47738.00    -11.868 -2.721  -7.400  -3.200
+47739.00    -11.954 -2.494  -6.700  -3.200
+47740.00    -12.066 -2.239  -7.500  -3.000
+47741.00    -12.031 -2.043  -7.300  -2.900
+47742.00    -11.897 -1.859  -7.300  -2.800
+47743.00    -11.788 -1.9    -7.500  -2.700
+47744.00    -11.989 -2.102  -7.800  -2.600
+47745.00    -12.279 -2.116  -8.900  -2.900
+47746.00    -12.396 -2.014  -10.100 -3.100
+47747.00    -12.372 -2.12   -11.300 -3.400
+47748.00    -12.374 -2.245  -12.500 -3.600
+47749.00    -12.301 -2.371  -13.400 -3.800
+47750.00    -12.112 -2.497  -13.400 -3.500
+47751.00    -11.765 -2.541  -13.100 -3.200
+47752.00    -11.373 -2.544  -12.700 -2.800
+47753.00    -11.104 -2.612  -12.200 -2.500
+47754.00    -11.035 -2.702  -11.500 -2.200
+47755.00    -11.202 -2.649  -11.900 -2.100
+47756.00    -11.658 -2.397  -12.300 -2.100
+47757.00    -12.438 -2.064  -12.900 -2.100
+47758.00    -13.39  -1.855  -13.400 -2.200
+47759.00    -14.183 -1.884  -13.900 -2.300
+47760.00    -14.54  -2.158  -14.000 -2.400
+47761.00    -14.651 -2.453  -14.000 -2.600
+47762.00    -14.908 -2.502  -13.900 -2.700
+47763.00    -15.105 -2.373  -13.700 -2.800
+47764.00    -14.867 -2.227  -13.400 -2.800
+47765.00    -14.528 -2.188  -12.800 -2.600
+47766.00    -14.207 -2.234  -12.100 -2.300
+47767.00    -13.819 -2.244  -11.500 -2.000
+47768.00    -13.393 -2.093  -11.000 -1.600
+47769.00    -12.986 -1.746  -10.600 -1.300
+47770.00    -12.682 -1.276  -11.100 -1.300
+47771.00    -12.674 -1.056  -11.700 -1.300
+47772.00    -12.995 -1.235  -12.500 -1.300
+47773.00    -13.447 -1.6    -13.200 -1.400
+47774.00    -13.798 -1.912  -14.000 -1.600
+47775.00    -13.998 -2.114  -15.200 -2.200
+47776.00    -14.18  -2.328  -15.200 -2.400
+47777.00    -14.405 -2.593  -15.000 -2.600
+47778.00    -14.475 -2.758  -14.700 -2.800
+47779.00    -14.179 -2.633  -14.200 -2.900
+47780.00    -13.567 -2.263  -13.600 -2.700
+47781.00    -13.092 -2.005  -12.900 -2.500
+47782.00    -12.949 -1.963  -12.200 -2.300
+47783.00    -13.034 -1.931  -11.500 -2.100
+47784.00    -13.265 -1.787  -11.000 -2.000
+47785.00    -13.568 -1.646  -11.000 -2.200
+47786.00    -13.888 -1.689  -11.200 -2.400
+47787.00    -14.181 -1.879  -11.400 -2.700
+47788.00    -14.344 -1.963  -11.600 -2.900
+47789.00    -14.445 -1.837  -11.800 -3.200
+47790.00    -14.505 -1.616  -11.800 -3.200
+47791.00    -14.337 -1.591  -11.700 -3.200
+47792.00    -13.938 -1.739  -11.500 -3.100
+47793.00    -13.522 -1.829  -11.400 -3.000
+47794.00    -13.256 -1.784  -11.300 -2.800
+47795.00    -13.175 -1.648  -11.400 -2.500
+47796.00    -13.275 -1.498  -11.500 -2.100
+47797.00    -13.537 -1.356  -11.600 -1.800
+47798.00    -13.477 -1.04   -11.800 -1.500
+47799.00    -13.14  -0.722  -11.900 -1.400
+47800.00    -12.924 -0.7    -12.000 -1.500
+47801.00    -12.882 -0.934  -12.000 -1.700
+47802.00    -12.851 -1.204  -12.000 -2.000
+47803.00    -12.77  -1.428  -12.000 -2.300
+47804.00    -12.802 -1.725  -11.900 -2.600
+47805.00    -13.131 -2.168  -11.200 -2.500
+47806.00    -13.389 -2.349  -10.800 -2.500
+47807.00    -13.249 -2.073  -10.500 -2.400
+47808.00    -12.736 -1.633  -10.200 -2.400
+47809.00    -12.048 -1.419  -10.000 -2.300
+47810.00    -11.547 -1.452  -10.200 -2.200
+47811.00    -11.609 -1.575  -10.400 -2.200
+47812.00    -12.103 -1.596  -10.700 -2.100
+47813.00    -12.606 -1.465  -11.000 -2.100
+47814.00    -12.726 -1.359  -11.200 -2.000
+47815.00    -12.292 -1.33   -10.800 -2.000
+47816.00    -11.657 -1.269  -10.400 -2.000
+47817.00    -11.31  -1.163  -10.000 -2.000
+47818.00    -11.338 -1.147  -9.700  -2.000
+47819.00    -11.348 -1.336  -9.500  -1.900
+47820.00    -11.157 -1.486  -9.900  -1.700
+47821.00    -10.927 -1.355  -10.400 -1.500
+47822.00    -10.805 -1.037  -11.000 -1.300
+47823.00    -10.745 -0.752  -11.600 -1.100
+47824.00    -10.569 -0.451  -12.100 -0.900
+47825.00    -10.252 -0.166  -12.300 -0.900
+47826.00    -10.005 0.038   -12.400 -1.000
+47827.00    -9.895  0.103   -12.300 -1.000
+47828.00    -9.975  -0.046  -12.200 -1.100
+47829.00    -10.292 -0.433  -12.000 -1.200
+47830.00    -10.684 -0.863  -11.600 -1.200
+47831.00    -10.804 -1.026  -11.100 -1.200
+47832.00    -10.512 -0.958  -10.600 -1.200
+47833.00    -9.907  -0.74   -9.900  -1.200
+47834.00    -9.335  -0.504  -9.300  -1.200
+47835.00    -9.139  -0.445  -8.700  -1.300
+47836.00    -9.19   -0.484  -8.100  -1.300
+47837.00    -9.193  -0.478  -7.400  -1.200
+47838.00    -9.015  -0.393  -7.000  -1.100
+47839.00    -8.806  -0.334  -6.500  -2.000
+47840.00    -8.863  -0.142  -6.100  -2.100
+47841.00    -8.961  0.032   -5.600  -2.200
+47842.00    -8.674  -0.059  -5.200  -2.300
+47843.00    -7.872  -0.305  -4.700  -2.200
+47844.00    -7.039  -0.195  -4.300  -2.100
+47845.00    -6.495  0.191   -4.300  -1.900
+47846.00    -6.337  0.431   -4.300  -1.700
+47847.00    -6.434  0.300   -4.300  -1.600
+47848.00    -6.643  -0.055  -4.400  -1.400
+47849.00    -6.754  -0.067  -4.400  -1.300
+47850.00    -6.776  0.284   -4.600  -1.200
+47851.00    -6.885  0.718   -4.900  -1.100
+47852.00    -6.957  0.939   -5.100  -1.000
+47853.00    -6.907  0.842   -5.300  -1.000
+47854.00    -6.854  0.687   -5.400  -1.100
+47855.00    -6.879  0.709   -5.400  -1.200
+47856.00    -6.941  0.758   -5.400  -1.300
+47857.00    -6.964  0.658   -5.400  -1.400
+47858.00    -6.926  0.529   -5.200  -1.600
+47859.00    -6.771  0.53    -5.000  -1.600
+47860.00    -6.457  0.638   -4.600  -1.600
+47861.00    -6.052  0.723   -4.100  -1.500
+47862.00    -5.744  0.715   -3.700  -1.300
+47863.00    -5.673  0.678   -3.300  -1.200
+47864.00    -5.83   0.73    -3.100  -1.100
+47865.00    -6.112  0.942   -2.800  -0.500
+47866.00    -6.361  1.201   -3.700  -0.200
+47867.00    -6.593  1.458   -4.700  0.100
+47868.00    -6.927  1.700   -5.600  0.000
+47869.00    -7.324  1.798   -6.100  -0.100
+47870.00    -7.52   1.614   -6.400  -0.300
+47871.00    -7.271  1.201   -6.200  -0.500
+47872.00    -6.656  0.818   -5.400  -0.800
+47873.00    -6.017  0.674   -4.300  -0.900
+47874.00    -5.577  0.722   -3.100  -0.900
+47875.00    -5.311  0.809   -1.900  -1.000
+47876.00    -5.099  0.845   -1.100  -0.900
+47877.00    -4.999  0.886   -0.600  -0.800
+47878.00    -5.115  0.98    -0.700  -0.600
+47879.00    -5.335  1.034   -1.100  -0.500
+47880.00    -5.551  0.928   -1.600  -0.200
+47881.00    -5.702  0.781   -2.200  -0.100
+47882.00    -5.778  0.77    -2.800  -0.100
+47883.00    -5.733  0.914   -3.200  -0.300
+47884.00    -5.662  0.99    -3.200  -0.500
+47885.00    -5.698  0.868   -3.300  -0.800
+47886.00    -5.835  0.701   -3.100  -0.900
+47887.00    -6.002  0.667   -2.800  -0.800
+47888.00    -6.036  0.809   -2.300  -0.700
+47889.00    -5.836  1.041   -1.900  -0.500
+47890.00    -5.536  1.174   -1.600  -0.300
+47891.00    -5.317  1.154   -1.700  -0.200
+47892.00    -5.258  1.052   -2.100  -0.100
+47893.00    -5.325  0.955   -2.700  -0.100
+47894.00    -5.434  0.921   -3.500  -0.100
+47895.00    -5.532  0.96    -4.500  1.000
+47896.00    -5.645  1.037   -6.100  0.400
+47897.00    -5.798  1.083   -6.300  0.000
+47898.00    -5.935  1.027   -5.300  -1.100
+47899.00    -5.982  0.875   -3.200  -1.500
+47900.00    -5.952  0.752   -2.100  -2.000
+47901.00    -5.846  0.787   -0.600  -2.100
+47902.00    -5.614  0.99    0.500   -1.600
+47903.00    -5.156  1.202   0.700   -0.500
+47904.00    -4.657  1.186   0.300   0.600
+47905.00    -4.558  0.791   0.300   1.300
+47906.00    -4.895  0.227   -0.500  1.700
+47907.00    -5.367  -0.097  -1.900  1.600
+47908.00    -5.625  0.174   -3.500  1.200
+47909.00    -5.688  0.676   -4.900  0.500
+47910.00    -5.794  0.749   -6.500  -0.200
+47911.00    -6.115  0.316   -7.100  -0.900
+47912.00    -6.348  -0.22   -6.600  -1.300
+47913.00    -6.056  -0.296  -5.100  -1.600
+47914.00    -5.523  0.153   -3.400  -1.600
+47915.00    -5.199  0.61    -2.100  -1.600
+47916.00    -5.239  0.833   -1.300  -1.500
+47917.00    -5.306  0.528   -0.800  -1.200
+47918.00    -5.072  0.255   -1.000  -0.700
+47919.00    -4.695  0.241   -1.500  -0.300
+47920.00    -4.513  0.38    -2.000  0.000
+47921.00    -4.646  0.543   -2.600  0.100
+47922.00    -4.979  0.595   -3.500  0.200
+47923.00    -5.387  0.569   -4.100  -0.100
+47924.00    -5.757  0.544   -4.400  -0.600
+47925.00    -5.924  0.521   -5.600  -1.100
+47926.00    -5.909  0.493   -5.000  -1.900
+47927.00    -5.812  0.395   -3.700  -2.300
+47928.00    -5.695  0.18    -2.100  -2.300
+47929.00    -5.608  -0.101  -0.800  -2.100
+47930.00    -5.613  -0.236  0.200   -1.900
+47931.00    -5.538  -0.095  0.400   -1.500
+47932.00    -5.155  0.128   -0.300  -1.100
+47933.00    -4.645  0.42    -1.600  -0.800
+47934.00    -4.496  0.322   -3.000  -0.500
+47935.00    -4.55   0.047   -3.700  -0.300
+47936.00    -4.588  -0.052  -4.100  -0.500
+47937.00    -4.58   -0.123  -3.600  -0.800
+47938.00    -4.658  -0.063  -2.100  -1.400
+47939.00    -4.771  -0.063  -0.200  -1.800
+47940.00    -4.891  -0.211  1.400   -2.300
+47941.00    -5.017  -0.584  2.700   -2.700
+47942.00    -5.124  -0.975  3.900   -3.000
+47943.00    -5.061  -1.128  4.800   -3.000
+47944.00    -4.895  -1.067  5.000   -2.700
+47945.00    -4.818  -1.115  4.500   -2.400
+47946.00    -4.681  -1.271  3.100   -2.100
+47947.00    -4.374  -1.311  1.100   -1.700
+47948.00    -4.12   -1.136  -1.500  -1.600
+47949.00    -4.212  -0.833  -3.200  -1.600
+47950.00    -4.643  -0.531  -4.200  -1.800
+47951.00    -5.149  -0.441  -4.700  -2.000
+47952.00    -5.455  -0.687  -4.700  -2.400
+47953.00    -5.458  -1.084  -4.000  -2.800
+47954.00    -5.273  -1.425  -3.700  -3.100
+47955.00    -5.072  -1.603  -2.900  -4.400
+47956.00    -4.927  -1.679  -1.600  -4.500
+47957.00    -4.81   -1.754  -0.500  -4.200
+47958.00    -4.685  -1.871  -0.100  -3.900
+47959.00    -4.569  -2.021  -0.800  -2.900
+47960.00    -4.455  -2.075  -0.200  -2.200
+47961.00    -4.336  -2.058  -1.100  -1.800
+47962.00    -4.191  -2.087  -2.300  -2.000
+47963.00    -4.072  -2.19   -3.200  -2.800
+47964.00    -4.119  -2.247  -4.100  -3.500
+47965.00    -4.374  -2.114  -5.400  -4.000
+47966.00    -4.518  -2.007  -6.100  -4.400
+47967.00    -4.489  -2.115  -5.800  -5.100
+47968.00    -4.359  -2.468  -4.700  -5.400
+47969.00    -4.103  -2.917  -3.400  -5.600
+47970.00    -3.685  -3.155  -1.600  -5.500
+47971.00    -3.27   -3.08   -0.400  -5.400
+47972.00    -3.127  -2.907  -0.100  -4.700
+47973.00    -3.345  -2.908  -0.500  -4.000
+47974.00    -3.641  -3.098  -1.200  -3.500
+47975.00    -3.63   -3.103  -1.700  -3.100
+47976.00    -3.45   -2.746  -2.600  -2.900
+47977.00    -3.53   -2.289  -3.400  -2.800
+47978.00    -3.969  -2.087  -3.900  -3.200
+47979.00    -4.431  -2.231  -4.100  -3.600
+47980.00    -4.584  -2.575  -4.000  -4.100
+47981.00    -4.402  -2.928  -3.400  -4.700
+47982.00    -4.078  -3.196  -2.400  -4.800
+47983.00    -3.828  -3.361  -1.100  -4.700
+47984.00    -3.771  -3.404  -0.300  -4.700
+47985.00    -3.878  -3.323  1.800   -4.900
+47986.00    -3.883  -3.167  2.300   -4.600
+47987.00    -3.741  -3.132  1.700   -4.100
+47988.00    -3.512  -3.186  0.200   -3.700
+47989.00    -3.248  -3.205  -2.000  -3.800
+47990.00    -2.983  -3.162  -3.500  -3.700
+47991.00    -2.75   -3.182  -4.500  -3.700
+47992.00    -2.623  -3.343  -4.700  -4.100
+47993.00    -2.629  -3.572  -3.400  -4.700
+47994.00    -2.656  -3.761  -2.500  -5.400
+47995.00    -2.6    -3.839  -1.600  -6.000
+47996.00    -2.5    -3.965  -0.500  -6.500
+47997.00    -2.449  -4.201  0.700   -6.700
+47998.00    -2.44   -4.385  1.900   -6.300
+47999.00    -2.42   -4.363  2.400   -5.700
+48000.00    -2.36   -4.108  3.000   -4.900
+48001.00    -2.168  -4.005  2.700   -4.400
+48002.00    -2.009  -4.077  1.800   -3.800
+48003.00    -1.889  -4.052  0.300   -3.500
+48004.00    -1.92   -3.759  -1.300  -3.600
+48005.00    -2.345  -3.414  -2.700  -3.900
+48006.00    -3.129  -3.306  -3.600  -4.400
+48007.00    -3.837  -3.545  -3.700  -4.800
+48008.00    -4.046  -3.976  -3.000  -5.500
+48009.00    -3.799  -4.347  -2.000  -5.900
+48010.00    -3.343  -4.605  -1.000  -6.200
+48011.00    -2.922  -4.77   -0.400  -6.300
+48012.00    -2.749  -4.768  0.000   -5.900
+48013.00    -2.935  -4.54   -0.400  -5.300
+48014.00    -3.341  -4.205  -0.800  -5.100
+48015.00    -3.624  -4.009  -2.400  -5.100
+48016.00    -3.476  -3.93   -2.000  -5.300
+48017.00    -3.004  -3.852  -1.600  -5.500
+48018.00    -2.551  -3.796  -1.100  -5.700
+48019.00    -2.348  -3.915  -0.600  -5.800
+48020.00    -2.366  -4.162  -0.300  -5.900
+48021.00    -2.447  -4.518  0.100   -5.800
+48022.00    -2.499  -4.814  0.300   -5.800
+48023.00    -2.506  -4.9    0.500   -5.600
+48024.00    -2.579  -4.84   0.700   -5.500
+48025.00    -2.889  -4.732  0.600   -5.100
+48026.00    -3.287  -4.619  0.500   -4.800
+48027.00    -3.416  -4.493  0.300   -4.400
+48028.00    -3.169  -4.325  0.000   -4.000
+48029.00    -2.805  -4.245  -0.400  -3.700
+48030.00    -2.654  -4.302  -0.900  -3.600
+48031.00    -2.79   -4.313  -1.400  -3.500
+48032.00    -3.185  -4.11   -1.900  -3.400
+48033.00    -3.788  -3.83   -2.400  -3.400
+48034.00    -4.365  -3.772  -2.700  -3.500
+48035.00    -4.574  -4.002  -2.400  -3.700
+48036.00    -4.438  -4.247  -2.100  -4.000
+48037.00    -4.175  -4.29   -1.700  -4.200
+48038.00    -3.933  -4.241  -1.300  -4.500
+48039.00    -3.807  -4.307  -1.100  -4.700
+48040.00    -3.956  -4.5    -1.600  -4.700
+48041.00    -4.445  -4.561  -2.300  -4.700
+48042.00    -5.012  -4.352  -2.900  -4.600
+48043.00    -5.291  -4.111  -3.500  -4.600
+48044.00    -5.121  -4.051  -4.000  -4.500
+48045.00    -4.782  -4.117  -4.200  -4.500
+48046.00    -4.617  -4.167  -3.800  -4.600
+48047.00    -4.691  -4.241  -3.500  -4.700
+48048.00    -4.816  -4.484  -3.200  -4.800
+48049.00    -4.988  -4.81   -2.800  -4.900
+48050.00    -5.352  -4.919  -3.100  -5.000
+48051.00    -5.733  -4.713  -3.200  -5.100
+48052.00    -5.847  -4.407  -3.500  -5.200
+48053.00    -5.677  -4.286  -3.400  -5.200
+48054.00    -5.566  -4.224  -3.600  -5.100
+48055.00    -5.668  -4.056  -3.900  -5.000
+48056.00    -5.743  -3.892  -4.200  -4.900
+48057.00    -5.677  -3.856  -4.500  -5.000
+48058.00    -5.61   -3.958  -4.600  -5.100
+48059.00    -5.738  -4.124  -4.700  -5.100
+48060.00    -6.171  -4.257  -4.700  -5.000
+48061.00    -6.752  -4.225  -4.500  -5.300
+48062.00    -7.158  -3.999  -4.500  -5.300
+48063.00    -7.316  -4.027  -4.400  -5.500
+48064.00    -7.168  -4.136  -4.500  -5.400
+48065.00    -6.926  -4.188  -4.800  -5.200
+48066.00    -6.675  -4.12   -5.400  -5.000
+48067.00    -6.414  -4.02   -5.800  -4.800
+48068.00    -6.327  -3.953  -6.400  -4.300
+48069.00    -6.739  -3.849  -6.800  -4.300
+48070.00    -7.601  -3.766  -7.100  -4.200
+48071.00    -8.43   -3.773  -7.200  -4.500
+48072.00    -8.728  -3.828  -7.300  -4.500
+48073.00    -8.542  -3.825  -7.600  -4.700
+48074.00    -8.459  -3.787  -7.500  -4.800
+48075.00    -8.787  -3.754  -7.300  -4.900
+48076.00    -9.397  -3.703  -7.900  -4.700
+48077.00    -9.992  -3.676  -8.400  -4.300
+48078.00    -10.323 -3.672  -8.800  -4.000
+48079.00    -10.246 -3.639  -9.200  -4.100
+48080.00    -10.004 -3.487  -9.700  -4.000
+48081.00    -9.772  -3.317  -9.700  -4.100
+48082.00    -9.655  -3.273  -9.800  -4.200
+48083.00    -9.746  -3.366  -9.400  -4.300
+48084.00    -10.081 -3.539  -9.100  -4.400
+48085.00    -10.332 -3.763  -9.100  -4.500
+48086.00    -10.065 -3.973  -9.300  -4.700
+48087.00    -9.812  -4.033  -9.600  -4.800
+48088.00    -9.97   -3.942  -9.800  -4.900
+48089.00    -10.401 -3.848  -10.000 -4.700
+48090.00    -10.858 -3.894  -10.000 -4.200
+48091.00    -11.204 -4.072  -10.000 -4.100
+48092.00    -11.449 -4.181  -9.400  -4.000
+48093.00    -11.626 -4.029  -9.200  -3.900
+48094.00    -11.579 -3.786  -9.000  -3.800
+48095.00    -11.343 -3.696  -9.600  -4.100
+48096.00    -11.146 -3.725  -10.100 -4.300
+48097.00    -11.354 -3.702  -10.700 -4.500
+48098.00    -12.138 -3.742  -10.800 -5.100
+48099.00    -13.139 -3.769  -10.900 -5.400
+48100.00    -13.962 -3.601  -11.200 -5.500
+48101.00    -14.262 -3.468  -11.600 -5.200
+48102.00    -14.137 -3.41   -12.000 -4.800
+48103.00    -13.945 -3.297  -12.200 -4.000
+48104.00    -13.87  -3.145  -12.900 -3.600
+48105.00    -13.848 -3.185  -13.200 -3.300
+48106.00    -13.945 -3.272  -13.400 -2.800
+48107.00    -14.23  -3.269  -13.500 -2.500
+48108.00    -14.425 -3.215  -14.000 -2.300
+48109.00    -14.37  -3.177  -14.000 -2.400
+48110.00    -14.208 -3.2    -14.200 -2.400
+48111.00    -14.182 -3.268  -14.400 -2.600
+48112.00    -14.459 -3.311  -14.700 -2.900
+48113.00    -14.914 -3.134  -14.700 -3.500
+48114.00    -15.264 -3.016  -14.800 -3.800
+48115.00    -15.387 -3.111  -14.400 -4.000
+48116.00    -15.368 -3.36   -13.900 -3.900
+48117.00    -15.286 -3.611  -13.400 -3.900
+48118.00    -15.186 -3.664  -12.600 -3.700
+48119.00    -15.126 -3.537  -11.500 -4.100
+48120.00    -15.245 -3.377  -11.200 -4.400
+48121.00    -15.362 -3.271  -11.800 -4.500
+48122.00    -15.271 -3.181  -12.800 -4.400
+48123.00    -14.941 -3.074  -14.100 -4.200
+48124.00    -14.468 -2.992  -15.100 -3.700
+48125.00    -14.067 -2.996  -15.300 -3.600
+48126.00    -14.02  -3.104  -15.100 -3.200
+48127.00    -14.442 -3.273  -15.100 -3.600
+48128.00    -15.057 -3.432  -14.900 -4.000
+48129.00    -15.493 -3.501  -14.700 -4.300
+48130.00    -15.571 -3.458  -15.000 -4.100
+48131.00    -15.369 -3.368  -14.900 -4.000
+48132.00    -15.088 -3.322  -14.500 -3.600
+48133.00    -14.878 -3.311  -13.100 -3.600
+48134.00    -14.829 -3.26   -12.500 -3.600
+48135.00    -14.952 -3.135  -12.400 -3.500
+48136.00    -15.171 -2.994  -12.600 -3.400
+48137.00    -15.405 -2.924  -13.000 -3.300
+48138.00    -15.643 -2.938  -13.200 -3.400
+48139.00    -15.972 -2.998  -13.700 -3.300
+48140.00    -16.51  -3.067  -14.300 -3.300
+48141.00    -17.064 -2.839  -14.500 -3.500
+48142.00    -17.382 -2.65   -14.200 -3.600
+48143.00    -17.322 -2.727  -14.500 -3.600
+48144.00    -16.91  -2.871  -14.600 -3.900
+48145.00    -16.405 -2.998  -14.900 -3.500
+48146.00    -15.884 -3.069  -15.100 -3.500
+48147.00    -15.574 -3.121  -15.200 -3.400
+48148.00    -15.571 -3.195  -15.200 -3.800
+48149.00    -15.637 -3.255  -14.800 -3.800
+48150.00    -15.505 -3.212  -14.600 -4.000
+48151.00    -15.167 -3.000  -14.700 -4.000
+48152.00    -14.817 -2.653  -14.800 -3.900
+48153.00    -14.667 -2.311  -14.800 -3.600
+48154.00    -14.846 -2.125  -14.800 -3.400
+48155.00    -15.359 -2.145  -14.800 -3.300
+48156.00    -15.866 -2.293  -14.700 -3.300
+48157.00    -16.053 -2.428  -14.500 -3.200
+48158.00    -15.806 -2.481  -14.200 -3.200
+48159.00    -15.223 -2.527  -14.300 -3.200
+48160.00    -14.637 -2.687  -14.300 -3.300
+48161.00    -14.285 -2.973  -14.300 -3.500
+48162.00    -14.164 -3.2    -14.100 -3.500
+48163.00    -14.147 -3.201  -14.000 -3.800
+48164.00    -14.274 -3.043  -13.900 -3.700
+48165.00    -14.698 -2.874  -14.100 -3.700
+48166.00    -15.259 -2.748  -14.400 -3.300
+48167.00    -15.616 -2.614  -14.500 -3.200
+48168.00    -15.537 -2.492  -14.300 -3.100
+48169.00    -15.169 -2.451  -13.900 -3.300
+48170.00    -14.752 -2.508  -14.400 -3.700
+48171.00    -14.406 -2.58   -13.700 -3.600
+48172.00    -14.125 -2.585  -13.000 -3.700
+48173.00    -13.94  -2.523  -12.600 -3.400
+48174.00    -14.111 -2.253  -12.800 -2.600
+48175.00    -14.374 -2.129  -12.800 -2.400
+48176.00    -14.419 -2.386  -13.200 -1.900
+48177.00    -14.192 -2.584  -13.100 -2.100
+48178.00    -13.791 -2.46   -13.000 -2.300
+48179.00    -13.375 -2.186  -12.900 -2.500
+48180.00    -13.114 -1.953  -12.900 -2.400
+48181.00    -13.025 -1.816  -12.700 -2.200
+48182.00    -12.995 -1.782  -12.600 -2.200
+48183.00    -12.987 -1.859  -12.100 -2.200
+48184.00    -13.034 -1.984  -11.900 -2.500
+48185.00    -13.137 -2.195  -12.000 -2.300
+48186.00    -13.082 -2.385  -12.400 -2.100
+48187.00    -12.685 -2.458  -12.000 -2.100
+48188.00    -12.047 -2.444  -10.800 -2.300
+48189.00    -11.556 -2.427  -9.700  -2.900
+48190.00    -11.444 -2.398  -9.300  -2.900
+48191.00    -11.368 -2.274  -9.400  -3.000
+48192.00    -11.158 -2.056  -9.900  -2.900
+48193.00    -11.03  -1.851  -10.600 -2.800
+48194.00    -11.317 -1.9    -10.900 -2.800
+48195.00    -11.651 -2.035  -10.800 -2.600
+48196.00    -11.755 -2.037  -10.600 -2.600
+48197.00    -11.62  -1.949  -10.100 -2.600
+48198.00    -11.27  -1.92   -9.600  -2.400
+48199.00    -10.804 -1.935  -9.500  -2.400
+48200.00    -10.492 -1.842  -10.000 -2.600
+48201.00    -10.567 -1.633  -10.900 -2.300
+48202.00    -10.943 -1.501  -11.200 -2.100
+48203.00    -11.255 -1.575  -11.100 -2.100
+48204.00    -11.248 -1.724  -10.900 -2.200
+48205.00    -10.997 -1.723  -10.300 -2.300
+48206.00    -10.717 -1.513  -9.800  -2.200
+48207.00    -10.492 -1.218  -9.400  -2.100
+48208.00    -10.299 -0.945  -9.000  -2.100
+48209.00    -10.141 -0.687  -9.100  -1.900
+48210.00    -10.061 -0.459  -9.000  -1.800
+48211.00    -10.119 -0.484  -8.900  -1.800
+48212.00    -10.25  -0.798  -8.900  -1.900
+48213.00    -10.285 -1.136  -8.900  -1.800
+48214.00    -10.021 -1.186  -9.000  -1.900
+48215.00    -9.368  -0.974  -9.100  -1.900
+48216.00    -8.648  -0.732  -9.200  -1.600
+48217.00    -8.373  -0.651  -9.300  -1.600
+48218.00    -8.595  -0.685  -9.300  -1.500
+48219.00    -8.985  -0.695  -9.400  -1.300
+48220.00    -9.224  -0.69   -9.200  -1.300
+48221.00    -9.307  -0.762  -9.000  -1.300
+48222.00    -9.369  -0.846  -8.800  -1.300
+48223.00    -9.474  -0.709  -8.300  -1.500
+48224.00    -9.602  -0.429  -7.900  -1.500
+48225.00    -9.691  -0.318  -7.500  -1.400
+48226.00    -9.439  -0.431  -7.000  -1.400
+48227.00    -8.764  -0.601  -6.600  -1.400
+48228.00    -8.039  -0.585  -6.200  -1.200
+48229.00    -7.766  -0.311  -6.000  -1.200
+48230.00    -8.074  -0.016  -6.900  -1.500
+48231.00    -8.507  -0.03   -7.000  -1.600
+48232.00    -8.601  -0.364  -7.100  -1.600
+48233.00    -8.434  -0.652  -7.100  -1.700
+48234.00    -8.327  -0.652  -7.200  -1.700
+48235.00    -8.364  -0.441  -7.200  -1.600
+48236.00    -8.415  -0.259  -7.200  -1.600
+48237.00    -8.443  -0.2    -7.200  -1.500
+48238.00    -8.454  -0.113  -7.100  -1.400
+48239.00    -8.431  0.047   -7.100  -1.300
+48240.00    -8.305  0.185   -7.100  -1.200
+48241.00    -8.147  0.135   -7.100  -1.100
+48242.00    -8.037  0.003   -7.100  -0.900
+48243.00    -7.999  -0.026  -7.100  -0.800
+48244.00    -8.092  0.036   -7.200  -0.700
+48245.00    -8.252  0.117   -7.200  -0.700
+48246.00    -8.381  0.132   -7.100  -0.800
+48247.00    -8.297  0.063   -7.100  -0.900
+48248.00    -7.96   -0.016  -7.100  -0.900
+48249.00    -7.504  -0.072  -7.000  -1.000
+48250.00    -7.092  -0.118  -7.000  -1.100
+48251.00    -6.893  -0.101  -6.900  -1.100
+48252.00    -7.061  0.023   -6.900  -1.200
+48253.00    -7.614  0.125   -6.800  -1.100
+48254.00    -8.167  0.061   -6.800  -1.100
+48255.00    -8.243  -0.09   -6.800  -1.000
+48256.00    -7.885  -0.098  -6.700  -0.900
+48257.00    -7.51   0.134   -6.700  -0.800
+48258.00    -7.378  0.394   -6.600  -0.800
+48259.00    -7.377  0.386   -6.600  -0.700
+48260.00    -7.33   0.106   -6.600  -0.900
+48261.00    -7.116  -0.012  -6.700  -0.900
+48262.00    -6.952  0.157   -6.700  -0.900
+48263.00    -7.033  0.248   -6.600  -1.000
+48264.00    -7.208  0.045   -6.600  -1.000
+48265.00    -7.248  -0.143  -6.500  -1.000
+48266.00    -7.294  -0.146  -6.500  -1.000
+48267.00    -7.46   -0.042  -6.400  -1.000
+48268.00    -7.638  0.008   -6.400  -1.000
+48269.00    -7.753  -0.007  -6.400  -1.000
+48270.00    -7.869  0.062   -6.500  -0.900
+48271.00    -7.962  0.261   -6.600  -0.900
+48272.00    -7.901  0.404   -6.700  -0.800
+48273.00    -7.606  0.232   -6.800  -0.800
+48274.00    -7.207  -0.097  -6.900  -0.700
+48275.00    -6.976  -0.338  -7.000  -0.700
+48276.00    -6.944  -0.403  -7.100  -0.700
+48277.00    -6.989  -0.314  -7.200  -0.700
+48278.00    -7.048  -0.151  -7.300  -0.700
+48279.00    -7.174  0.019   -7.300  -0.700
+48280.00    -7.469  0.128   -7.400  -0.800
+48281.00    -7.933  0.155   -7.300  -0.800
+48282.00    -8.348  0.015   -7.200  -0.900
+48283.00    -8.406  -0.3    -7.100  -0.900
+48284.00    -7.969  -0.61   -6.800  -1.000
+48285.00    -7.17   -0.738  -6.500  -1.100
+48286.00    -6.388  -0.746  -6.200  -1.200
+48287.00    -5.811  -0.753  -5.800  -1.400
+48288.00    -5.482  -0.738  -5.500  -1.500
+48289.00    -5.521  -0.698  -5.100  -1.600
+48290.00    -5.999  -0.667  -5.600  -1.800
+48291.00    -6.696  -0.669  -5.500  -1.900
+48292.00    -7.245  -0.728  -5.400  -1.900
+48293.00    -7.48   -0.807  -5.300  -2.000
+48294.00    -7.517  -0.78   -5.200  -2.000
+48295.00    -7.461  -0.625  -5.100  -2.100
+48296.00    -7.282  -0.686  -5.000  -2.100
+48297.00    -6.97   -1.042  -5.000  -2.200
+48298.00    -6.671  -1.419  -4.900  -2.200
+48299.00    -6.553  -1.57   -4.900  -2.200
+48300.00    -6.611  -1.453  -5.000  -2.200
+48301.00    -6.635  -1.368  -5.100  -2.200
+48302.00    -6.576  -1.369  -5.200  -2.200
+48303.00    -6.571  -1.365  -5.300  -2.300
+48304.00    -6.721  -1.356  -5.500  -2.300
+48305.00    -6.999  -1.374  -5.600  -2.300
+48306.00    -7.288  -1.409  -5.800  -2.400
+48307.00    -7.482  -1.429  -5.900  -2.400
+48308.00    -7.553  -1.416  -6.100  -2.400
+48309.00    -7.587  -1.468  -6.200  -2.500
+48310.00    -7.667  -1.725  -6.300  -2.500
+48311.00    -7.708  -2.149  -6.300  -2.600
+48312.00    -7.582  -2.536  -6.400  -2.600
+48313.00    -7.253  -2.63   -6.400  -2.700
+48314.00    -6.828  -2.375  -6.400  -2.700
+48315.00    -6.463  -1.961  -6.400  -2.800
+48316.00    -6.35   -1.712  -6.400  -2.800
+48317.00    -6.423  -1.71   -6.400  -2.800
+48318.00    -6.584  -1.861  -6.400  -2.900
+48319.00    -6.804  -2.056  -6.500  -3.000
+48320.00    -7.014  -2.173  -6.300  -2.400
+48321.00    -7.138  -2.17   -6.300  -2.400
+48322.00    -7.128  -2.125  -6.300  -2.500
+48323.00    -6.91   -2.205  -6.400  -2.600
+48324.00    -6.464  -2.473  -6.500  -2.600
+48325.00    -5.902  -2.802  -6.600  -2.700
+48326.00    -5.448  -3.012  -6.700  -2.800
+48327.00    -5.317  -3.024  -6.900  -2.900
+48328.00    -5.544  -2.927  -7.000  -3.000
+48329.00    -5.948  -2.852  -7.100  -3.200
+48330.00    -6.35   -2.822  -7.100  -3.200
+48331.00    -6.707  -2.766  -7.100  -3.300
+48332.00    -6.887  -2.692  -7.000  -3.400
+48333.00    -6.928  -2.682  -6.900  -3.500
+48334.00    -6.963  -2.791  -6.800  -3.600
+48335.00    -6.974  -3.001  -6.600  -3.600
+48336.00    -6.848  -3.244  -6.400  -3.700
+48337.00    -6.577  -3.461  -6.200  -3.800
+48338.00    -6.261  -3.657  -6.000  -3.800
+48339.00    -5.961  -3.888  -5.800  -3.900
+48340.00    -5.617  -4.176  -5.600  -3.900
+48341.00    -5.165  -4.393  -5.400  -4.000
+48342.00    -4.907  -4.402  -5.200  -4.000
+48343.00    -4.92   -4.183  -5.000  -4.100
+48344.00    -5.118  -3.877  -4.900  -4.200
+48345.00    -5.334  -3.696  -4.600  -4.200
+48346.00    -5.428  -3.744  -4.400  -4.300
+48347.00    -5.355  -3.941  -4.200  -4.400
+48348.00    -5.172  -4.111  -4.100  -4.400
+48349.00    -4.967  -4.15   -4.000  -4.500
+48350.00    -4.883  -4.132  -4.000  -4.600
+48351.00    -4.834  -4.203  -4.100  -4.600
+48352.00    -4.711  -4.438  -4.100  -4.700
+48353.00    -4.535  -4.731  -4.100  -4.700
+48354.00    -4.408  -4.865  -4.100  -4.800
+48355.00    -4.435  -4.746  -4.100  -4.900
+48356.00    -4.593  -4.552  -4.100  -4.900
+48357.00    -4.697  -4.512  -4.200  -5.000
+48358.00    -4.612  -4.584  -4.200  -5.000
+48359.00    -4.379  -4.544  -4.300  -5.100
+48360.00    -4.256  -4.288  -4.400  -5.200
+48361.00    -4.453  -4.023  -4.500  -5.200
+48362.00    -4.898  -4.03   -4.600  -5.300
+48363.00    -5.316  -4.368  -4.800  -5.400
+48364.00    -5.479  -4.811  -5.100  -5.500
+48365.00    -5.34   -5.119  -5.200  -5.600
+48366.00    -5.1    -5.305  -5.400  -5.800
+48367.00    -4.95   -5.45   -5.500  -5.900
+48368.00    -4.888  -5.578  -5.600  -6.100
+48369.00    -4.781  -5.646  -5.600  -6.300
+48370.00    -4.551  -5.561  -5.500  -6.600
+48371.00    -4.358  -5.267  -5.400  -6.800
+48372.00    -4.312  -4.897  -5.200  -7.000
+48373.00    -4.342  -4.727  -5.000  -7.300
+48374.00    -4.325  -4.873  -4.800  -7.400
+48375.00    -4.234  -5.223  -4.600  -7.600
+48376.00    -4.196  -5.528  -4.500  -7.700
+48377.00    -4.323  -5.593  -4.300  -7.800
+48378.00    -4.506  -5.526  -4.200  -7.800
+48379.00    -4.559  -5.577  -4.100  -7.800
+48380.00    -4.478  -5.739  -3.800  -7.600
+48381.00    -4.345  -5.881  -3.900  -7.400
+48382.00    -4.17   -5.861  -4.000  -7.300
+48383.00    -3.938  -5.643  -4.200  -7.100
+48384.00    -3.766  -5.402  -4.300  -7.000
+48385.00    -3.882  -5.315  -4.400  -6.800
+48386.00    -4.231  -5.414  -4.500  -6.600
+48387.00    -4.546  -5.495  -4.700  -6.400
+48388.00    -4.762  -5.377  -4.900  -6.300
+48389.00    -5.019  -5.165  -5.100  -6.100
+48390.00    -5.347  -5.087  -5.400  -6.000
+48391.00    -5.545  -5.2    -5.800  -5.800
+48392.00    -5.432  -5.414  -6.200  -5.600
+48393.00    -5.108  -5.555  -6.700  -5.500
+48394.00    -4.869  -5.615  -7.100  -5.400
+48395.00    -4.892  -5.662  -7.400  -5.300
+48396.00    -5.14   -5.695  -7.700  -5.200
+48397.00    -5.432  -5.668  -7.900  -5.100
+48398.00    -5.63   -5.571  -8.000  -5.000
+48399.00    -5.81   -5.435  -8.000  -5.000
+48400.00    -5.978  -5.284  -7.900  -5.000
+48401.00    -6.086  -5.144  -7.700  -5.100
+48402.00    -6.133  -5.105  -7.500  -5.200
+48403.00    -6.087  -5.301  -7.300  -5.300
+48404.00    -5.953  -5.782  -7.000  -5.400
+48405.00    -5.781  -6.379  -6.800  -5.500
+48406.00    -5.569  -6.709  -6.500  -5.600
+48407.00    -5.318  -6.566  -6.300  -5.700
+48408.00    -5.291  -6.261  -6.100  -5.900
+48409.00    -5.61   -6.039  -5.900  -6.100
+48410.00    -6.055  -5.823  -6.500  -6.000
+48411.00    -6.284  -5.518  -6.700  -5.800
+48412.00    -6.168  -5.25   -6.800  -5.700
+48413.00    -6.03   -5.246  -7.000  -5.500
+48414.00    -6.211  -5.496  -7.200  -5.400
+48415.00    -6.785  -5.717  -7.400  -5.300
+48416.00    -7.525  -5.661  -7.700  -5.200
+48417.00    -8.189  -5.415  -8.000  -5.100
+48418.00    -8.576  -5.255  -8.300  -5.100
+48419.00    -8.545  -5.269  -8.600  -5.000
+48420.00    -8.255  -5.288  -9.000  -5.000
+48421.00    -7.917  -5.209  -9.200  -5.000
+48422.00    -7.706  -5.161  -9.400  -5.100
+48423.00    -7.679  -5.232  -9.600  -5.100
+48424.00    -7.83   -5.299  -9.600  -5.200
+48425.00    -8.136  -5.176  -9.500  -5.200
+48426.00    -8.462  -4.875  -9.300  -5.300
+48427.00    -8.565  -4.645  -9.000  -5.400
+48428.00    -8.332  -4.638  -8.700  -5.500
+48429.00    -7.965  -4.8    -8.300  -5.600
+48430.00    -7.811  -4.982  -7.900  -5.700
+48431.00    -8.017  -5.152  -7.400  -5.800
+48432.00    -8.521  -5.326  -7.000  -5.900
+48433.00    -9.139  -5.398  -6.700  -6.100
+48434.00    -9.525  -5.267  -6.400  -6.200
+48435.00    -9.661  -5.17   -6.200  -6.400
+48436.00    -9.769  -5.053  -6.100  -6.600
+48437.00    -10.016 -4.882  -6.100  -6.800
+48438.00    -10.402 -4.829  -6.200  -6.900
+48439.00    -10.71  -4.824  -6.300  -7.100
+48440.00    -10.699 -4.686  -6.800  -7.000
+48441.00    -10.451 -4.601  -7.200  -6.800
+48442.00    -10.264 -4.665  -7.900  -6.600
+48443.00    -10.327 -4.746  -8.400  -6.400
+48444.00    -10.606 -4.691  -8.800  -6.200
+48445.00    -10.986 -4.555  -9.600  -6.200
+48446.00    -11.405 -4.539  -10.200 -6.100
+48447.00    -11.798 -4.726  -10.900 -5.800
+48448.00    -11.999 -4.998  -11.400 -5.700
+48449.00    -12.132 -5.069  -11.800 -5.600
+48450.00    -12.357 -4.983  -11.500 -5.500
+48451.00    -12.478 -4.854  -11.600 -5.400
+48452.00    -12.266 -4.788  -11.700 -5.300
+48453.00    -12.268 -4.726  -11.800 -5.400
+48454.00    -12.998 -4.642  -11.800 -5.500
+48455.00    -13.903 -4.66   -12.000 -5.500
+48456.00    -14.393 -4.676  -12.100 -5.600
+48457.00    -14.254 -4.778  -12.300 -5.600
+48458.00    -14.009 -4.872  -12.600 -5.600
+48459.00    -14.205 -4.856  -12.900 -5.500
+48460.00    -14.833 -4.836  -13.300 -5.500
+48461.00    -15.457 -4.746  -13.700 -5.400
+48462.00    -15.667 -4.748  -14.100 -5.400
+48463.00    -15.531 -4.763  -14.600 -5.300
+48464.00    -15.331 -4.566  -15.000 -5.300
+48465.00    -15.227 -4.295  -15.300 -5.300
+48466.00    -15.26  -4.151  -15.700 -5.300
+48467.00    -15.242 -4.454  -16.000 -5.300
+48468.00    -15.1   -4.834  -16.200 -5.300
+48469.00    -14.997 -4.921  -16.400 -5.400
+48470.00    -15.069 -4.824  -16.600 -5.500
+48471.00    -15.354 -4.773  -16.800 -5.600
+48472.00    -15.846 -4.704  -17.000 -5.600
+48473.00    -16.345 -4.719  -17.200 -5.700
+48474.00    -16.595 -4.836  -15.800 -5.400
+48475.00    -16.529 -4.86   -16.000 -5.400
+48476.00    -16.317 -4.781  -16.200 -5.300
+48477.00    -16.217 -4.613  -16.400 -5.200
+48478.00    -16.291 -4.488  -16.700 -5.000
+48479.00    -16.385 -4.495  -16.900 -4.900
+48480.00    -16.46  -4.625  -17.200 -4.700
+48481.00    -16.781 -4.687  -17.500 -4.600
+48482.00    -17.533 -4.58   -17.800 -4.400
+48483.00    -18.378 -4.443  -18.100 -4.300
+48484.00    -18.744 -4.439  -18.300 -4.300
+48485.00    -18.442 -4.516  -18.400 -4.200
+48486.00    -17.924 -4.5    -18.400 -4.300
+48487.00    -17.63  -4.334  -18.300 -4.300
+48488.00    -17.572 -4.122  -18.200 -4.400
+48489.00    -17.533 -4.009  -18.100 -4.500
+48490.00    -17.306 -4.081  -17.900 -4.600
+48491.00    -16.927 -4.043  -17.800 -4.700
+48492.00    -16.758 -3.944  -17.700 -4.800
+48493.00    -16.866 -3.992  -17.600 -4.900
+48494.00    -17.094 -4.229  -17.600 -5.000
+48495.00    -17.324 -4.543  -17.500 -5.100
+48496.00    -17.565 -4.617  -17.600 -5.200
+48497.00    -17.813 -4.468  -17.600 -5.300
+48498.00    -18.113 -4.51   -17.700 -5.300
+48499.00    -18.328 -4.642  -17.800 -5.300
+48500.00    -18.443 -4.739  -18.000 -5.300
+48501.00    -18.529 -4.849  -18.100 -5.300
+48502.00    -18.582 -4.977  -18.400 -5.300
+48503.00    -18.582 -5.07   -18.700 -5.200
+48504.00    -18.493 -5.058  -19.000 -5.100
+48505.00    -18.352 -4.901  -19.100 -5.100
+48506.00    -18.377 -4.586  -19.300 -4.900
+48507.00    -18.509 -4.302  -19.500 -4.800
+48508.00    -18.51  -4.146  -19.600 -4.700
+48509.00    -18.391 -3.983  -19.700 -4.500
+48510.00    -18.644 -3.835  -19.600 -4.500
+48511.00    -19.249 -3.777  -19.400 -4.400
+48512.00    -19.719 -3.871  -19.300 -4.400
+48513.00    -19.703 -4.107  -19.000 -4.400
+48514.00    -19.204 -4.236  -18.700 -4.400
+48515.00    -18.511 -4.178  -18.400 -4.500
+48516.00    -17.877 -4.07   -18.100 -4.500
+48517.00    -17.416 -4.011  -17.900 -4.600
+48518.00    -17.214 -3.972  -17.700 -4.700
+48519.00    -17.332 -3.912  -17.600 -4.700
+48520.00    -17.725 -3.871  -17.600 -4.700
+48521.00    -18.181 -3.907  -17.700 -4.700
+48522.00    -18.536 -4.007  -17.800 -4.700
+48523.00    -18.737 -4.092  -17.900 -4.600
+48524.00    -18.768 -4.082  -18.100 -4.600
+48525.00    -18.671 -3.937  -18.100 -4.600
+48526.00    -18.468 -3.834  -18.100 -4.600
+48527.00    -18.199 -3.786  -18.100 -4.600
+48528.00    -17.883 -3.782  -18.000 -4.700
+48529.00    -17.537 -3.835  -17.800 -4.700
+48530.00    -17.176 -3.925  -17.700 -4.800
+48531.00    -16.831 -4.028  -17.600 -4.800
+48532.00    -16.627 -4.184  -17.500 -4.900
+48533.00    -16.658 -4.398  -17.400 -5.000
+48534.00    -16.845 -4.365  -17.400 -5.000
+48535.00    -17.038 -4.03   -17.400 -4.400
+48536.00    -17.147 -3.632  -17.400 -4.300
+48537.00    -17.156 -3.38   -17.400 -4.300
+48538.00    -17.118 -3.353  -17.300 -4.200
+48539.00    -17.198 -3.475  -17.200 -4.200
+48540.00    -17.302 -3.597  -17.100 -4.200
+48541.00    -17.215 -3.614  -17.000 -4.200
+48542.00    -16.857 -3.533  -16.800 -4.200
+48543.00    -16.315 -3.44   -16.600 -4.100
+48544.00    -15.775 -3.412  -16.300 -4.100
+48545.00    -15.401 -3.44   -16.100 -4.100
+48546.00    -15.23  -3.454  -15.900 -4.100
+48547.00    -15.191 -3.447  -15.600 -4.000
+48548.00    -15.376 -3.513  -15.400 -4.000
+48549.00    -15.685 -3.635  -15.300 -3.900
+48550.00    -15.882 -3.698  -15.200 -3.800
+48551.00    -15.9   -3.618  -15.000 -3.800
+48552.00    -15.848 -3.452  -14.900 -3.700
+48553.00    -15.783 -3.372  -14.800 -3.600
+48554.00    -15.673 -3.291  -14.800 -3.500
+48555.00    -15.454 -3.183  -14.700 -3.500
+48556.00    -15.125 -3.064  -14.700 -3.400
+48557.00    -14.759 -2.967  -14.700 -3.400
+48558.00    -14.422 -2.955  -14.700 -3.400
+48559.00    -14.129 -3.04   -14.700 -3.400
+48560.00    -13.868 -3.116  -14.800 -3.400
+48561.00    -13.691 -3.089  -14.800 -3.400
+48562.00    -13.684 -2.916  -14.700 -3.300
+48563.00    -13.719 -2.618  -14.600 -3.300
+48564.00    -13.698 -2.313  -14.400 -3.300
+48565.00    -13.595 -2.146  -14.400 -3.300
+48566.00    -13.471 -2.165  -14.400 -3.200
+48567.00    -13.386 -2.313  -14.400 -3.200
+48568.00    -13.287 -2.488  -14.100 -3.100
+48569.00    -13.136 -2.61   -13.800 -3.100
+48570.00    -13.035 -2.539  -13.500 -3.000
+48571.00    -12.898 -2.346  -13.200 -3.000
+48572.00    -12.593 -2.227  -13.000 -2.900
+48573.00    -12.21  -2.225  -12.800 -2.900
+48574.00    -12.014 -2.201  -12.600 -2.800
+48575.00    -11.987 -2.108  -12.500 -2.800
+48576.00    -12.041 -2.059  -12.400 -2.900
+48577.00    -12.194 -2.232  -12.400 -2.900
+48578.00    -12.421 -2.529  -12.400 -2.900
+48579.00    -12.615 -2.634  -12.400 -2.900
+48580.00    -12.702 -2.403  -12.400 -2.800
+48581.00    -12.665 -2.051  -12.400 -2.700
+48582.00    -12.373 -1.836  -12.400 -2.600
+48583.00    -11.997 -1.823  -12.400 -2.500
+48584.00    -11.728 -1.85   -12.400 -2.400
+48585.00    -11.627 -1.807  -12.400 -2.300
+48586.00    -11.648 -1.716  -12.400 -2.300
+48587.00    -11.67  -1.59   -12.500 -2.200
+48588.00    -11.741 -1.381  -12.500 -2.200
+48589.00    -11.722 -1.306  -12.500 -2.100
+48590.00    -11.67  -1.345  -12.400 -2.100
+48591.00    -11.714 -1.423  -12.400 -2.100
+48592.00    -11.882 -1.498  -12.400 -2.100
+48593.00    -12.099 -1.604  -12.300 -2.100
+48594.00    -12.168 -1.767  -12.200 -2.100
+48595.00    -11.861 -1.645  -12.000 -2.000
+48596.00    -11.349 -1.441  -11.800 -1.900
+48597.00    -10.898 -1.435  -11.700 -1.800
+48598.00    -10.537 -1.527  -11.600 -1.800
+48599.00    -10.209 -1.561  -11.500 -1.800
+48600.00    -9.989  -1.435  -11.400 -1.700
+48601.00    -10.029 -1.154  -11.300 -1.700
+48602.00    -10.288 -0.99   -11.300 -1.700
+48603.00    -10.438 -0.795  -11.300 -1.700
+48604.00    -10.313 -0.721  -11.200 -1.700
+48605.00    -10.178 -0.909  -11.200 -1.700
+48606.00    -10.387 -1.177  -11.100 -1.700
+48607.00    -10.792 -1.313  -11.100 -1.700
+48608.00    -11.055 -1.229  -11.100 -1.600
+48609.00    -11.019 -0.986  -11.100 -1.600
+48610.00    -10.627 -0.79   -11.000 -1.600
+48611.00    -10.018 -0.874  -11.000 -1.600
+48612.00    -9.412  -1.084  -11.000 -1.600
+48613.00    -9.1    -1.19   -11.000 -1.600
+48614.00    -9.251  -1.222  -10.900 -1.600
+48615.00    -9.653  -1.291  -10.800 -1.600
+48616.00    -9.981  -1.355  -10.600 -1.600
+48617.00    -10.162 -1.266  -10.500 -1.600
+48618.00    -10.284 -1.032  -10.300 -1.700
+48619.00    -10.401 -0.823  -10.200 -1.700
+48620.00    -10.471 -0.767  -10.100 -1.700
+48621.00    -10.473 -0.831  -10.000 -1.700
+48622.00    -10.437 -0.917  -9.900  -1.700
+48623.00    -10.354 -0.996  -9.900  -1.700
+48624.00    -10.201 -1.068  -9.900  -1.700
+48625.00    -10.003 -1.066  -10.100 -1.500
+48626.00    -9.781  -0.909  -10.100 -1.400
+48627.00    -9.535  -0.646  -10.000 -1.400
+48628.00    -9.315  -0.461  -9.900  -1.400
+48629.00    -9.222  -0.468  -9.900  -1.400
+48630.00    -9.265  -0.513  -9.800  -1.400
+48631.00    -9.283  -0.499  -9.800  -1.400
+48632.00    -9.144  -0.527  -9.800  -1.400
+48633.00    -8.96   -0.691  -9.800  -1.400
+48634.00    -8.956  -0.927  -9.800  -1.400
+48635.00    -9.257  -0.997  -9.900  -1.300
+48636.00    -9.832  -0.773  -10.000 -1.300
+48637.00    -10.496 -0.556  -10.200 -1.300
+48638.00    -10.968 -0.626  -10.400 -1.300
+48639.00    -10.999 -0.965  -10.500 -1.300
+48640.00    -10.616 -1.297  -10.500 -1.400
+48641.00    -10.135 -1.374  -10.500 -1.400
+48642.00    -9.818  -1.239  -10.500 -1.500
+48643.00    -9.6    -1.12   -10.400 -1.600
+48644.00    -9.442  -1.125  -10.300 -1.700
+48645.00    -9.437  -1.097  -10.200 -1.800
+48646.00    -9.644  -0.96   -10.100 -1.800
+48647.00    -9.925  -0.876  -9.900  -1.900
+48648.00    -10.025 -0.983  -9.800  -2.000
+48649.00    -9.89   -1.19   -9.700  -2.000
+48650.00    -9.674  -1.436  -9.600  -2.100
+48651.00    -9.421  -1.643  -9.500  -2.100
+48652.00    -9.104  -1.771  -9.500  -2.200
+48653.00    -8.786  -1.815  -9.500  -2.200
+48654.00    -8.534  -1.695  -9.700  -2.300
+48655.00    -8.416  -1.427  -9.600  -2.200
+48656.00    -8.473  -1.213  -9.400  -2.200
+48657.00    -8.697  -1.266  -9.200  -2.300
+48658.00    -9.004  -1.552  -9.000  -2.300
+48659.00    -9.303  -1.864  -9.100  -2.300
+48660.00    -9.505  -2.042  -9.200  -2.400
+48661.00    -9.55   -2.086  -9.400  -2.400
+48662.00    -9.572  -2.036  -9.500  -2.400
+48663.00    -9.777  -1.844  -9.700  -2.400
+48664.00    -10.21  -1.526  -9.800  -2.400
+48665.00    -10.677 -1.413  -10.000 -2.300
+48666.00    -11.01  -1.693  -10.200 -2.300
+48667.00    -11.097 -2.234  -10.300 -2.400
+48668.00    -10.912 -2.651  -10.500 -2.400
+48669.00    -10.611 -2.67   -10.600 -2.500
+48670.00    -10.353 -2.396  -10.700 -2.500
+48671.00    -10.123 -2.147  -10.700 -2.600
+48672.00    -9.889  -2.105  -10.800 -2.600
+48673.00    -9.71   -2.142  -10.800 -2.700
+48674.00    -9.651  -2.107  -10.800 -2.700
+48675.00    -9.67   -2.212  -10.800 -2.800
+48676.00    -9.614  -2.581  -10.700 -2.800
+48677.00    -9.548  -3.032  -10.700 -2.900
+48678.00    -9.711  -3.3    -10.600 -3.000
+48679.00    -10.007 -3.272  -10.500 -3.000
+48680.00    -10.167 -3.161  -10.300 -3.100
+48681.00    -10.006 -3.175  -10.100 -3.200
+48682.00    -9.601  -3.219  -9.900  -3.200
+48683.00    -9.196  -3.154  -9.700  -3.300
+48684.00    -8.927  -3.034  -9.500  -3.400
+48685.00    -8.78   -3.013  -8.800  -3.500
+48686.00    -8.712  -3.165  -8.700  -3.600
+48687.00    -8.712  -3.375  -8.600  -3.700
+48688.00    -8.72   -3.487  -8.500  -3.800
+48689.00    -8.57   -3.404  -8.500  -3.900
+48690.00    -8.316  -3.238  -8.500  -4.000
+48691.00    -8.202  -3.195  -8.600  -4.100
+48692.00    -8.423  -3.444  -8.700  -4.200
+48693.00    -8.89   -3.756  -8.700  -4.300
+48694.00    -9.379  -4.126  -8.800  -4.400
+48695.00    -9.542  -4.57   -8.900  -4.500
+48696.00    -9.272  -4.835  -9.000  -4.600
+48697.00    -8.884  -4.74   -9.000  -4.600
+48698.00    -8.774  -4.405  -9.000  -4.700
+48699.00    -9.03   -4.136  -9.000  -4.800
+48700.00    -9.299  -4.072  -8.900  -4.800
+48701.00    -9.392  -4.157  -8.900  -4.900
+48702.00    -9.326  -4.25   -8.800  -5.000
+48703.00    -9.135  -4.393  -8.600  -5.000
+48704.00    -8.781  -4.595  -8.500  -5.100
+48705.00    -8.367  -4.743  -8.400  -5.100
+48706.00    -8.153  -4.766  -8.400  -5.100
+48707.00    -8.233  -4.741  -8.300  -5.100
+48708.00    -8.38   -4.791  -8.300  -5.100
+48709.00    -8.381  -4.931  -8.400  -5.100
+48710.00    -8.272  -5.027  -8.400  -5.100
+48711.00    -8.252  -4.98   -8.500  -5.200
+48712.00    -8.359  -4.865  -8.600  -5.200
+48713.00    -8.384  -4.838  -8.700  -5.300
+48714.00    -8.108  -4.966  -8.800  -5.400
+48715.00    -7.774  -5.11   -8.600  -5.600
+48716.00    -7.78   -5.096  -8.500  -5.700
+48717.00    -8.052  -4.95   -8.300  -5.800
+48718.00    -8.319  -4.813  -8.200  -5.900
+48719.00    -8.369  -4.828  -8.200  -6.000
+48720.00    -8.188  -5.034  -8.200  -6.000
+48721.00    -7.961  -5.431  -8.300  -6.100
+48722.00    -7.72   -5.849  -8.400  -6.100
+48723.00    -7.475  -6.328  -8.500  -6.100
+48724.00    -7.264  -6.729  -8.600  -6.000
+48725.00    -7.173  -6.812  -8.600  -6.000
+48726.00    -7.289  -6.448  -8.700  -5.900
+48727.00    -7.598  -5.794  -8.700  -5.800
+48728.00    -7.914  -5.348  -8.700  -5.800
+48729.00    -8.16   -5.304  -8.700  -5.700
+48730.00    -8.288  -5.535  -8.600  -5.700
+48731.00    -8.269  -5.795  -8.500  -5.800
+48732.00    -8.171  -5.904  -8.400  -5.800
+48733.00    -8.15   -5.835  -8.300  -5.900
+48734.00    -8.251  -5.76   -8.200  -6.000
+48735.00    -8.374  -5.847  -8.100  -6.100
+48736.00    -8.323  -6.084  -7.900  -6.300
+48737.00    -7.965  -6.341  -7.800  -6.400
+48738.00    -7.453  -6.459  -7.700  -6.500
+48739.00    -7.106  -6.406  -7.600  -6.600
+48740.00    -7.126  -6.319  -7.500  -6.700
+48741.00    -7.404  -6.331  -7.500  -6.700
+48742.00    -7.558  -6.36   -7.500  -6.800
+48743.00    -7.533  -6.293  -7.500  -6.800
+48744.00    -7.501  -6.12   -7.500  -6.900
+48745.00    -7.542  -5.969  -7.700  -7.000
+48746.00    -7.62   -5.988  -7.800  -7.000
+48747.00    -7.679  -6.229  -7.800  -7.100
+48748.00    -7.682  -6.579  -7.900  -7.100
+48749.00    -7.567  -6.751  -7.900  -7.000
+48750.00    -7.42   -6.728  -7.900  -7.000
+48751.00    -7.278  -6.665  -7.900  -6.900
+48752.00    -7.084  -6.613  -7.900  -6.900
+48753.00    -6.797  -6.52   -7.900  -6.800
+48754.00    -6.485  -6.319  -7.800  -6.700
+48755.00    -6.393  -6.038  -7.700  -6.700
+48756.00    -6.689  -5.78   -7.700  -6.700
+48757.00    -7.14   -5.779  -7.600  -6.600
+48758.00    -7.495  -6.172  -7.600  -6.600
+48759.00    -7.641  -6.65   -7.700  -6.600
+48760.00    -7.555  -6.759  -7.700  -6.600
+48761.00    -7.372  -6.486  -7.900  -6.700
+48762.00    -7.283  -6.167  -8.100  -6.700
+48763.00    -7.418  -6.02   -8.400  -6.700
+48764.00    -7.812  -6.119  -8.700  -6.700
+48765.00    -8.062  -6.315  -8.900  -6.700
+48766.00    -8.052  -6.411  -9.100  -6.700
+48767.00    -7.984  -6.373  -9.400  -6.700
+48768.00    -8.16   -6.321  -9.500  -6.700
+48769.00    -8.719  -6.393  -9.700  -6.700
+48770.00    -9.404  -6.533  -9.800  -6.700
+48771.00    -9.853  -6.541  -9.900  -6.700
+48772.00    -10.001 -6.26   -9.900  -6.600
+48773.00    -10.019 -5.954  -9.900  -6.600
+48774.00    -10.041 -5.989  -10.300 -6.900
+48775.00    -9.928  -6.266  -9.600  -6.800
+48776.00    -9.536  -6.524  -9.200  -6.700
+48777.00    -9.196  -6.637  -8.900  -6.500
+48778.00    -9.147  -6.518  -8.700  -6.400
+48779.00    -9.249  -6.32   -8.700  -6.200
+48780.00    -9.325  -6.156  -8.900  -6.000
+48781.00    -9.268  -6.017  -9.300  -6.000
+48782.00    -9.13   -5.843  -9.800  -6.000
+48783.00    -9.122  -5.605  -10.200 -6.100
+48784.00    -9.404  -5.387  -10.700 -6.300
+48785.00    -9.962  -5.328  -11.000 -6.600
+48786.00    -10.577 -5.546  -11.100 -6.900
+48787.00    -11.015 -6.052  -10.900 -7.100
+48788.00    -11.238 -6.525  -10.600 -7.300
+48789.00    -11.461 -6.625  -10.300 -7.300
+48790.00    -11.671 -6.476  -10.100 -7.200
+48791.00    -11.576 -6.302  -10.000 -7.000
+48792.00    -11.402 -6.297  -10.200 -6.800
+48793.00    -11.581 -6.449  -10.500 -6.500
+48794.00    -11.896 -6.23   -11.100 -6.300
+48795.00    -11.841 -5.916  -11.800 -6.100
+48796.00    -11.617 -5.875  -12.600 -6.000
+48797.00    -11.86  -6.016  -13.400 -6.000
+48798.00    -12.582 -6.266  -14.200 -6.100
+48799.00    -13.435 -6.367  -14.700 -6.300
+48800.00    -14.003 -6.152  -14.900 -6.400
+48801.00    -14.186 -5.812  -14.700 -6.600
+48802.00    -14.124 -5.677  -14.500 -6.700
+48803.00    -13.968 -5.833  -14.300 -6.800
+48804.00    -13.824 -6.085  -13.900 -6.900
+48805.00    -13.758 -6.227  -13.600 -7.000
+48806.00    -13.855 -6.156  -13.900 -7.000
+48807.00    -14.145 -5.945  -14.300 -6.800
+48808.00    -14.556 -5.731  -14.800 -6.500
+48809.00    -14.958 -5.56   -15.400 -6.400
+48810.00    -15.276 -5.493  -16.000 -6.300
+48811.00    -15.475 -5.591  -16.400 -6.300
+48812.00    -15.508 -5.743  -16.600 -6.200
+48813.00    -15.635 -5.839  -16.800 -6.200
+48814.00    -15.918 -5.844  -16.700 -6.200
+48815.00    -16.2   -5.827  -16.400 -6.200
+48816.00    -16.348 -5.829  -16.200 -6.200
+48817.00    -16.372 -5.812  -16.000 -6.200
+48818.00    -16.368 -5.72   -16.200 -6.200
+48819.00    -16.389 -5.603  -16.500 -6.300
+48820.00    -16.483 -5.6    -17.000 -6.300
+48821.00    -16.639 -5.65   -17.500 -6.200
+48822.00    -16.815 -5.698  -18.200 -6.200
+48823.00    -16.864 -5.707  -19.000 -6.200
+48824.00    -16.785 -5.748  -19.600 -6.200
+48825.00    -16.887 -5.896  -20.100 -6.200
+48826.00    -17.38  -6.042  -20.500 -6.200
+48827.00    -18.06  -6.1    -20.600 -6.300
+48828.00    -18.518 -6.026  -20.400 -6.300
+48829.00    -18.481 -5.905  -20.000 -6.400
+48830.00    -18.074 -5.913  -19.600 -6.400
+48831.00    -17.673 -6.096  -19.100 -6.400
+48832.00    -17.47  -6.281  -18.600 -6.400
+48833.00    -17.567 -6.235  -18.400 -6.200
+48834.00    -17.998 -5.994  -18.300 -6.100
+48835.00    -18.641 -5.745  -18.400 -5.900
+48836.00    -19.285 -5.597  -18.700 -5.700
+48837.00    -19.786 -5.452  -19.100 -5.600
+48838.00    -20.107 -5.315  -19.400 -5.500
+48839.00    -20.223 -5.378  -19.900 -5.500
+48840.00    -20.052 -5.604  -20.200 -5.700
+48841.00    -19.775 -5.851  -20.500 -5.800
+48842.00    -19.707 -6.000  -20.400 -5.800
+48843.00    -19.894 -5.974  -20.300 -5.900
+48844.00    -20.048 -5.886  -19.800 -6.000
+48845.00    -19.997 -5.892  -19.700 -5.900
+48846.00    -19.901 -5.885  -19.800 -5.700
+48847.00    -19.828 -5.694  -20.100 -5.700
+48848.00    -19.995 -5.393  -20.500 -5.700
+48849.00    -20.418 -5.267  -21.100 -5.600
+48850.00    -20.925 -5.393  -21.700 -5.700
+48851.00    -21.248 -5.604  -22.200 -5.900
+48852.00    -21.189 -5.773  -22.600 -6.100
+48853.00    -20.899 -5.909  -22.700 -6.200
+48854.00    -20.838 -5.998  -22.400 -6.400
+48855.00    -21.209 -6.045  -21.900 -6.600
+48856.00    -21.78  -6.043  -21.300 -6.700
+48857.00    -21.812 -6.065  -20.800 -6.800
+48858.00    -21.32  -6.229  -20.300 -6.800
+48859.00    -20.771 -6.454  -20.000 -6.700
+48860.00    -20.499 -6.459  -20.000 -6.600
+48861.00    -20.712 -6.126  -20.300 -6.500
+48862.00    -21.237 -5.714  -20.700 -6.200
+48863.00    -21.607 -5.375  -21.400 -6.100
+48864.00    -21.624 -5.364  -22.100 -6.000
+48865.00    -21.714 -5.457  -22.700 -6.000
+48866.00    -22.079 -5.363  -23.200 -6.100
+48867.00    -22.354 -5.245  -23.300 -6.200
+48868.00    -22.168 -5.472  -23.200 -6.400
+48869.00    -21.532 -5.923  -23.000 -6.400
+48870.00    -20.903 -6.154  -22.700 -6.500
+48871.00    -20.689 -6.054  -22.000 -6.300
+48872.00    -20.853 -5.84   -21.400 -6.100
+48873.00    -21.168 -5.726  -20.900 -5.800
+48874.00    -21.529 -5.696  -20.800 -5.600
+48875.00    -21.797 -5.542  -20.900 -5.600
+48876.00    -21.955 -5.319  -21.200 -5.500
+48877.00    -22.048 -5.271  -21.600 -5.600
+48878.00    -22.091 -5.423  -22.200 -5.700
+48879.00    -22.054 -5.592  -22.500 -5.800
+48880.00    -21.857 -5.597  -22.900 -6.000
+48881.00    -21.544 -5.438  -22.800 -6.300
+48882.00    -21.401 -5.292  -22.500 -6.300
+48883.00    -21.524 -5.297  -22.200 -6.400
+48884.00    -21.76  -5.428  -21.800 -6.500
+48885.00    -21.891 -5.629  -21.300 -6.500
+48886.00    -21.759 -5.859  -21.000 -6.500
+48887.00    -21.433 -6.023  -20.800 -6.300
+48888.00    -21.182 -5.954  -20.700 -6.200
+48889.00    -21.242 -5.55   -20.800 -6.000
+48890.00    -21.562 -5.104  -21.000 -5.800
+48891.00    -21.819 -4.999  -21.300 -5.700
+48892.00    -21.78  -5.21   -21.600 -5.600
+48893.00    -21.641 -5.436  -21.800 -5.700
+48894.00    -21.721 -5.411  -21.900 -5.700
+48895.00    -21.956 -5.178  -21.800 -5.700
+48896.00    -21.949 -5.002  -21.500 -5.800
+48897.00    -21.509 -4.989  -21.100 -5.800
+48898.00    -20.922 -5.033  -20.600 -5.700
+48899.00    -20.563 -5.014  -20.100 -5.700
+48900.00    -20.472 -4.978  -20.000 -5.600
+48901.00    -20.475 -5.009  -19.900 -5.500
+48902.00    -20.52  -5.09   -20.200 -5.300
+48903.00    -20.652 -5.16   -20.600 -5.200
+48904.00    -20.838 -5.226  -21.200 -5.100
+48905.00    -20.948 -5.288  -21.700 -5.100
+48906.00    -20.956 -5.317  -21.900 -5.100
+48907.00    -20.915 -5.241  -22.000 -5.200
+48908.00    -20.796 -5.015  -21.900 -5.200
+48909.00    -20.515 -4.702  -21.400 -5.400
+48910.00    -20.151 -4.438  -20.700 -5.500
+48911.00    -19.851 -4.337  -19.800 -5.500
+48912.00    -19.728 -4.431  -19.200 -5.500
+48913.00    -19.704 -4.645  -18.600 -5.500
+48914.00    -19.601 -4.865  -18.200 -5.400
+48915.00    -19.281 -4.958  -18.000 -5.100
+48916.00    -18.761 -4.843  -18.000 -4.900
+48917.00    -18.351 -4.507  -18.200 -4.600
+48918.00    -18.228 -4.019  -18.600 -4.400
+48919.00    -18.293 -3.578  -18.900 -4.300
+48920.00    -18.35  -3.468  -19.100 -4.200
+48921.00    -18.391 -3.642  -19.200 -4.300
+48922.00    -18.517 -3.834  -19.100 -4.400
+48923.00    -18.692 -3.901  -18.700 -4.500
+48924.00    -18.711 -3.915  -18.200 -4.600
+48925.00    -18.381 -3.992  -17.700 -4.700
+48926.00    -17.788 -4.127  -17.100 -4.700
+48927.00    -17.256 -4.159  -16.600 -4.800
+48928.00    -16.939 -4.125  -16.300 -4.600
+48929.00    -16.823 -4.195  -16.300 -4.600
+48930.00    -16.88  -4.389  -15.800 -4.600
+48931.00    -17.026 -4.474  -16.200 -4.600
+48932.00    -17.23  -4.389  -16.800 -4.700
+48933.00    -17.402 -4.3    -17.400 -4.700
+48934.00    -17.483 -4.223  -18.000 -4.800
+48935.00    -17.5   -4.032  -18.500 -4.800
+48936.00    -17.451 -3.687  -18.400 -4.700
+48937.00    -17.249 -3.316  -18.000 -4.600
+48938.00    -16.86  -3.215  -17.300 -4.400
+48939.00    -16.307 -3.488  -16.700 -4.100
+48940.00    -15.731 -4.053  -16.100 -3.900
+48941.00    -15.464 -4.279  -15.800 -3.700
+48942.00    -15.578 -4.006  -15.600 -3.500
+48943.00    -15.855 -3.657  -15.600 -3.300
+48944.00    -16.111 -3.492  -16.000 -3.300
+48945.00    -16.326 -3.368  -16.600 -3.300
+48946.00    -16.531 -3.183  -17.200 -3.400
+48947.00    -16.739 -2.949  -17.300 -3.500
+48948.00    -16.915 -2.788  -17.300 -3.700
+48949.00    -16.98  -2.771  -17.100 -3.800
+48950.00    -16.881 -2.821  -16.600 -4.100
+48951.00    -16.62  -2.799  -15.900 -4.100
+48952.00    -16.254 -2.636  -15.200 -4.100
+48953.00    -15.821 -2.416  -14.400 -4.000
+48954.00    -15.352 -2.292  -13.600 -3.900
+48955.00    -14.899 -2.352  -13.000 -3.600
+48956.00    -14.56  -2.573  -12.700 -3.300
+48957.00    -14.452 -2.842  -12.700 -3.100
+48958.00    -14.536 -3.012  -13.100 -3.000
+48959.00    -14.543 -2.958  -13.600 -2.800
+48960.00    -14.584 -2.749  -14.400 -2.800
+48961.00    -14.752 -2.609  -15.100 -2.800
+48962.00    -14.959 -2.53   -15.500 -3.000
+48963.00    -15.06  -2.371  -15.700 -3.200
+48964.00    -14.963 -2.137  -15.700 -3.200
+48965.00    -14.659 -2.023  -15.600 -3.300
+48966.00    -14.29  -2.251  -15.300 -3.300
+48967.00    -13.928 -2.668  -14.900 -3.200
+48968.00    -13.673 -2.93   -14.500 -3.100
+48969.00    -13.636 -2.892  -14.200 -3.100
+48970.00    -13.827 -2.614  -13.900 -3.000
+48971.00    -14.091 -2.203  -13.900 -3.000
+48972.00    -14.26  -1.834  -13.900 -2.700
+48973.00    -14.219 -1.402  -14.200 -2.700
+48974.00    -14.027 -1.186  -14.400 -2.600
+48975.00    -13.866 -1.286  -14.700 -2.600
+48976.00    -13.858 -1.557  -14.800 -2.600
+48977.00    -13.984 -1.858  -14.800 -2.500
+48978.00    -14.04  -2.11   -14.700 -2.600
+48979.00    -13.887 -2.222  -14.500 -2.600
+48980.00    -13.621 -2.154  -14.200 -2.500
+48981.00    -13.39  -1.948  -13.800 -2.400
+48982.00    -13.226 -1.735  -13.500 -2.200
+48983.00    -13.07  -1.652  -13.200 -2.100
+48984.00    -12.926 -1.731  -13.100 -1.900
+48985.00    -12.865 -1.879  -13.100 -1.800
+48986.00    -12.859 -1.962  -13.000 -1.800
+48987.00    -12.761 -1.923  -13.100 -1.800
+48988.00    -12.718 -1.862  -13.300 -1.900
+48989.00    -12.881 -1.893  -13.400 -2.000
+48990.00    -13.238 -1.969  -13.400 -2.200
+48991.00    -13.66  -1.947  -13.500 -2.500
+48992.00    -13.951 -1.822  -13.400 -2.600
+48993.00    -14.002 -1.78   -13.400 -2.700
+48994.00    -13.838 -1.928  -13.400 -2.700
+48995.00    -13.503 -2.188  -13.400 -2.700
+48996.00    -13.108 -2.304  -13.400 -2.500
+48997.00    -12.856 -2.14   -13.500 -2.300
+48998.00    -12.921 -1.841  -13.700 -2.100
+48999.00    -13.266 -1.665  -14.000 -2.000
+49000.00    -13.68  -1.722  -14.200 -2.000
+49001.00    -13.987 -1.89   -14.400 -2.100
+49002.00    -14.172 -2.023  -14.600 -2.200
+49003.00    -14.29  -2.05   -14.500 -2.400
+49004.00    -14.398 -2.028  -14.300 -2.600
+49005.00    -14.485 -2.037  -14.000 -2.700
+49006.00    -14.469 -2.128  -13.700 -2.800
+49007.00    -14.282 -2.283  -13.600 -2.800
+49008.00    -13.979 -2.328  -13.500 -2.700
+49009.00    -13.722 -2.199  -13.500 -2.500
+49010.00    -13.625 -1.974  -13.600 -2.300
+49011.00    -13.642 -1.772  -13.700 -2.200
+49012.00    -13.705 -1.7    -13.900 -2.000
+49013.00    -13.793 -1.778  -14.200 -2.000
+49014.00    -13.835 -1.98   -14.500 -2.100
+49015.00    -13.777 -2.246  -14.600 -2.200
+49016.00    -13.629 -2.35   -14.800 -2.400
+49017.00    -13.471 -2.481  -15.000 -2.700
+49018.00    -13.492 -2.715  -14.900 -2.900
+49019.00    -13.725 -2.84   -14.900 -3.200
+49020.00    -14.044 -2.728  0.000   0.000
+49021.00    -14.312 -2.545  -14.700 -3.500
+49022.00    -14.286 -2.595  -14.400 -3.600
+49023.00    -13.832 -2.859  -14.100 -3.500
+49024.00    -13.309 -3.09   -13.800 -3.400
+49025.00    -12.956 -2.999  -13.600 -3.100
+49026.00    -12.944 -2.688  -13.600 -3.000
+49027.00    -13.242 -2.45   -13.500 -2.900
+49028.00    -13.628 -2.43   -13.700 -3.000
+49029.00    -13.898 -2.563  -14.000 -3.100
+49030.00    -14.001 -2.714  -14.200 -3.300
+49031.00    -14.073 -2.963  -14.500 -3.500
+49032.00    -14.148 -3.302  -14.600 -3.800
+49033.00    -14.258 -3.616  -14.600 -3.900
+49034.00    -14.457 -3.825  -14.600 -4.100
+49035.00    -14.627 -3.899  -14.400 -4.100
+49036.00    -14.554 -3.815  -14.400 -4.000
+49037.00    -14.28  -3.669  -14.300 -3.900
+49038.00    -14.013 -3.503  -14.200 -3.700
+49039.00    -13.856 -3.342  -14.100 -3.700
+49040.00    -13.793 -3.277  -14.100 -3.700
+49041.00    -13.752 -3.382  -14.200 -3.700
+49042.00    -13.63  -3.583  -14.000 -3.900
+49043.00    -13.369 -3.741  -13.900 -4.000
+49044.00    -13.021 -3.814  -13.600 -4.300
+49045.00    -12.853 -3.892  -13.600 -4.500
+49046.00    -13.068 -4.038  -13.500 -4.600
+49047.00    -13.574 -4.168  -13.500 -4.800
+49048.00    -14.056 -4.186  -13.500 -4.900
+49049.00    -14.283 -4.184  -13.600 -4.900
+49050.00    -14.29  -4.308  -13.300 -5.100
+49051.00    -14.149 -4.555  -13.500 -5.000
+49052.00    -13.856 -4.781  -13.700 -5.000
+49053.00    -13.524 -4.761  -14.000 -4.800
+49054.00    -13.331 -4.526  -13.900 -4.800
+49055.00    -13.303 -4.325  -14.000 -4.800
+49056.00    -13.36  -4.288  -14.100 -4.800
+49057.00    -13.491 -4.377  -14.200 -4.900
+49058.00    -13.631 -4.483  -14.200 -5.000
+49059.00    -13.616 -4.644  -14.100 -5.100
+49060.00    -13.364 -4.923  -13.900 -5.400
+49061.00    -13.045 -5.234  -13.500 -5.600
+49062.00    -12.943 -5.445  -13.300 -5.600
+49063.00    -13.092 -5.523  -13.000 -5.700
+49064.00    -13.231 -5.469  -12.900 -5.700
+49065.00    -13.129 -5.414  -12.800 -5.700
+49066.00    -12.81  -5.324  -12.700 -5.500
+49067.00    -12.526 -5.138  -12.700 -5.500
+49068.00    -12.435 -4.961  -12.600 -5.500
+49069.00    -12.483 -4.949  -12.700 -5.600
+49070.00    -12.558 -5.167  -13.000 -5.700
+49071.00    -12.61  -5.614  -13.000 -5.900
+49072.00    -12.565 -5.919  -13.100 -6.100
+49073.00    -12.393 -6.054  -13.100 -6.400
+49074.00    -12.261 -6.159  -12.900 -6.600
+49075.00    -12.291 -6.262  -12.700 -6.800
+49076.00    -12.384 -6.312  -12.300 -6.800
+49077.00    -12.374 -6.328  -12.000 -6.900
+49078.00    -12.193 -6.406  -11.700 -6.800
+49079.00    -11.913 -6.562  -11.600 -6.600
+49080.00    -11.669 -6.63   -11.000 -6.500
+49081.00    -11.588 -6.45   -11.400 -6.400
+49082.00    -11.705 -6.115  -12.000 -6.300
+49083.00    -11.894 -5.905  -12.300 -6.300
+49084.00    -12.000 -5.965  -12.600 -6.300
+49085.00    -12.022 -6.176  -12.700 -6.500
+49086.00    -12.033 -6.353  -12.700 -6.700
+49087.00    -11.973 -6.465  -12.700 -6.800
+49088.00    -11.743 -6.582  -12.500 -6.900
+49089.00    -11.481 -6.689  -12.300 -7.100
+49090.00    -11.477 -6.677  -12.000 -7.200
+49091.00    -11.738 -6.562  -11.900 -7.200
+49092.00    -11.886 -6.561  -11.800 -7.200
+49093.00    -11.677 -6.775  -11.800 -7.200
+49094.00    -11.179 -6.919  -11.700 -7.100
+49095.00    -10.809 -6.854  -11.600 -7.100
+49096.00    -10.838 -6.73   -11.600 -7.100
+49097.00    -11.19  -6.775  -11.700 -7.200
+49098.00    -11.576 -7.003  -11.700 -7.400
+49099.00    -11.622 -7.146  -11.700 -7.600
+49100.00    -11.47  -7.299  -11.500 -7.700
+49101.00    -11.39  -7.341  -11.300 -8.000
+49102.00    -11.502 -7.297  -11.000 -8.200
+49103.00    -11.837 -7.303  -10.800 -8.200
+49104.00    -12.288 -7.42   -10.500 -8.300
+49105.00    -12.52  -7.61   -10.400 -8.200
+49106.00    -12.123 -7.69   -10.500 -8.200
+49107.00    -11.325 -7.647  -10.700 -8.000
+49108.00    -10.625 -7.446  -11.100 -7.900
+49109.00    -10.323 -7.069  -11.600 -7.700
+49110.00    -10.46  -6.657  -12.200 -7.700
+49111.00    -10.874 -6.478  -12.800 -7.600
+49112.00    -11.347 -6.692  -13.300 -7.600
+49113.00    -11.792 -7.115  -13.500 -7.700
+49114.00    -12.174 -7.366  -13.500 -7.800
+49115.00    -12.284 -7.404  -13.200 -7.800
+49116.00    -12.05  -7.37   -12.800 -7.900
+49117.00    -11.693 -7.354  -12.300 -7.800
+49118.00    -11.533 -7.374  -11.800 -7.800
+49119.00    -11.656 -7.402  -11.400 -7.700
+49120.00    -11.782 -7.402  -11.100 -7.500
+49121.00    -11.599 -7.368  -10.900 -7.500
+49122.00    -11.239 -7.276  -11.000 -7.400
+49123.00    -11.088 -7.121  -11.300 -7.400
+49124.00    -11.308 -7.01   -11.700 -7.500
+49125.00    -11.718 -7.106  -12.300 -7.600
+49126.00    -12.046 -7.431  -12.900 -7.800
+49127.00    -12.255 -7.694  -13.300 -7.900
+49128.00    -12.37  -7.751  -13.500 -8.100
+49129.00    -12.385 -7.664  -13.500 -8.300
+49130.00    -12.34  -7.541  -13.300 -8.300
+49131.00    -12.299 -7.459  -13.000 -8.300
+49132.00    -12.297 -7.467  -12.700 -8.200
+49133.00    -12.264 -7.597  -12.500 -8.000
+49134.00    -12.208 -7.764  -12.300 -7.900
+49135.00    -12.087 -7.86   -12.300 -7.600
+49136.00    -11.91  -7.834  -12.500 -7.400
+49137.00    -11.812 -7.665  -12.900 -7.300
+49138.00    -11.935 -7.392  -13.300 -7.200
+49139.00    -12.301 -7.129  -13.600 -7.300
+49140.00    -12.803 -6.996  -13.800 -7.300
+49141.00    -13.288 -6.985  -13.900 -7.300
+49142.00    -13.599 -6.988  -14.000 -7.500
+49143.00    -13.654 -6.902  -13.800 -7.600
+49144.00    -13.514 -6.721  -13.600 -7.500
+49145.00    -13.344 -6.582  -13.500 -7.500
+49146.00    -13.296 -6.641  -13.300 -7.500
+49147.00    -13.369 -6.942  -13.300 -7.400
+49148.00    -13.533 -7.344  -13.500 -7.300
+49149.00    -13.633 -7.653  -13.800 -7.300
+49150.00    -13.643 -7.716  -14.300 -7.300
+49151.00    -13.73  -7.56   -14.700 -7.500
+49152.00    -14.024 -7.349  -15.200 -7.600
+49153.00    -14.497 -7.256  -15.700 -7.800
+49154.00    -15.026 -7.312  -16.000 -8.000
+49155.00    -15.473 -7.313  -16.200 -8.200
+49156.00    -15.752 -7.207  -16.200 -8.300
+49157.00    -15.816 -7.109  -16.200 -8.400
+49158.00    -15.676 -7.109  -16.000 -8.400
+49159.00    -15.454 -7.179  -15.900 -8.400
+49160.00    -15.366 -7.253  -15.800 -8.200
+49161.00    -15.564 -7.291  -15.900 -7.900
+49162.00    -15.91  -7.107  -16.000 -7.700
+49163.00    -16.328 -6.821  -16.400 -7.400
+49164.00    -16.764 -6.642  -16.800 -7.200
+49165.00    -17.057 -6.586  -17.200 -7.100
+49166.00    -17.229 -6.567  -17.700 -7.000
+49167.00    -17.427 -6.535  -18.100 -7.100
+49168.00    -17.718 -6.527  -18.300 -7.100
+49169.00    -18.047 -6.655  -18.400 -7.200
+49170.00    -18.203 -6.887  -18.400 -7.300
+49171.00    -18.031 -7.056  -18.200 -7.300
+49172.00    -17.62  -7.038  -17.900 -7.300
+49173.00    -17.22  -6.855  -17.800 -7.300
+49174.00    -17.022 -6.637  -17.700 -7.300
+49175.00    -17.051 -6.473  -17.700 -7.200
+49176.00    -17.247 -6.35   -17.900 -7.100
+49177.00    -17.535 -6.4    -18.400 -6.900
+49178.00    -17.884 -6.558  -18.800 -6.900
+49179.00    -18.225 -6.7    -19.300 -6.900
+49180.00    -18.552 -6.842  -19.800 -6.900
+49181.00    -18.97  -7.001  -20.100 -7.000
+49182.00    -19.529 -7.099  -20.300 -7.100
+49183.00    -20.135 -7.114  -20.400 -7.300
+49184.00    -20.478 -7.131  -20.300 -7.400
+49185.00    -20.439 -7.089  -20.200 -7.500
+49186.00    -20.201 -7.122  -20.100 -7.500
+49187.00    -19.96  -7.267  -20.100 -7.500
+49188.00    -19.857 -7.238  -20.100 -7.400
+49189.00    -20.031 -6.9    -20.300 -7.300
+49190.00    -20.523 -6.462  -20.700 -7.100
+49191.00    -21.227 -6.173  -21.100 -7.000
+49192.00    -21.856 -6.12   -21.500 -7.000
+49193.00    -22.149 -6.24   -22.000 -6.900
+49194.00    -22.081 -6.417  -22.400 -7.000
+49195.00    -21.87  -6.574  -22.500 -7.000
+49196.00    -21.791 -6.7    -22.600 -7.200
+49197.00    -21.953 -6.824  -22.500 -7.200
+49198.00    -22.231 -7.024  -22.400 -7.300
+49199.00    -22.339 -7.165  -22.100 -7.300
+49200.00    -22.196 -7.121  -22.000 -7.300
+49201.00    -21.996 -6.932  -21.900 -7.200
+49202.00    -21.952 -6.722  -22.000 -7.000
+49203.00    -22.146 -6.65   -22.300 -6.900
+49204.00    -22.525 -6.75   -22.700 -6.900
+49205.00    -22.986 -6.888  -22.600 -6.700
+49206.00    -23.322 -6.985  -23.000 -6.800
+49207.00    -23.344 -7.016  -23.500 -6.900
+49208.00    -23.125 -7.016  -23.800 -7.200
+49209.00    -23.045 -7.069  -24.100 -7.400
+49210.00    -23.423 -7.159  -24.200 -7.700
+49211.00    -24.027 -7.143  -24.200 -8.000
+49212.00    -24.426 -7.005  -24.100 -8.100
+49213.00    -24.397 -6.89   -23.900 -8.200
+49214.00    -24.072 -6.957  -23.800 -8.200
+49215.00    -23.742 -7.175  -23.700 -8.100
+49216.00    -23.598 -7.312  -23.700 -8.100
+49217.00    -23.687 -7.198  -23.900 -7.900
+49218.00    -23.953 -6.829  -24.200 -7.700
+49219.00    -24.412 -6.574  -24.600 -7.600
+49220.00    -24.882 -6.507  -25.000 -7.500
+49221.00    -25.156 -6.484  -25.300 -7.400
+49222.00    -25.153 -6.494  -25.500 -7.400
+49223.00    -24.816 -6.634  -25.500 -7.300
+49224.00    -24.203 -6.953  -25.400 -7.400
+49225.00    -23.69  -7.229  -25.100 -7.400
+49226.00    -23.59  -7.299  -24.700 -7.300
+49227.00    -23.844 -7.191  -24.400 -7.200
+49228.00    -24.192 -7.003  -24.100 -7.100
+49229.00    -24.464 -6.777  -24.000 -6.900
+49230.00    -24.611 -6.508  -24.000 -6.700
+49231.00    -24.61  -6.203  -24.200 -6.600
+49232.00    -24.508 -6.013  -24.500 -6.600
+49233.00    -24.446 -6.06   -24.800 -6.700
+49234.00    -24.52  -6.269  -25.200 -6.800
+49235.00    -24.583 -6.497  -25.600 -6.800
+49236.00    -24.514 -6.687  -25.600 -7.200
+49237.00    -24.51  -6.907  -25.600 -7.500
+49238.00    -24.824 -7.199  -25.400 -7.700
+49239.00    -25.359 -7.424  -25.100 -7.900
+49240.00    -25.685 -7.44   -24.800 -7.900
+49241.00    -25.513 -7.296  -24.600 -8.000
+49242.00    -25.009 -7.185  -24.300 -7.900
+49243.00    -24.59  -7.19   -24.300 -7.700
+49244.00    -24.535 -7.185  -24.400 -7.600
+49245.00    -24.83  -7.05   -24.800 -7.500
+49246.00    -25.253 -6.86   -25.200 -7.300
+49247.00    -25.517 -6.685  -25.700 -7.100
+49248.00    -25.554 -6.637  -26.200 -7.000
+49249.00    -25.586 -6.634  -26.500 -7.100
+49250.00    -25.778 -6.554  -26.700 -7.000
+49251.00    -25.92  -6.489  -26.700 -7.000
+49252.00    -25.653 -6.49   -26.500 -7.100
+49253.00    -24.982 -6.457  -26.200 -7.000
+49254.00    -24.493 -6.516  -25.800 -7.000
+49255.00    -24.45  -6.519  -25.400 -6.900
+49256.00    -24.583 -6.379  -25.000 -6.800
+49257.00    -24.665 -6.258  -24.800 -6.700
+49258.00    -24.652 -6.169  -24.800 -6.500
+49259.00    -24.637 -6.102  -24.900 -6.500
+49260.00    -24.633 -6.15   -25.100 -6.500
+49261.00    -24.496 -6.232  -25.300 -6.600
+49262.00    -24.49  -6.368  -25.400 -6.700
+49263.00    -24.506 -6.599  -25.400 -6.900
+49264.00    -24.422 -6.768  -25.300 -7.100
+49265.00    -24.311 -6.86   -25.100 -7.300
+49266.00    -24.354 -6.912  -24.600 -7.400
+49267.00    -24.537 -6.871  -24.200 -7.400
+49268.00    -24.531 -6.708  -23.900 -7.400
+49269.00    -24.249 -6.498  -23.500 -7.300
+49270.00    -23.848 -6.358  -23.400 -7.200
+49271.00    -23.561 -6.329  -23.400 -6.900
+49272.00    -23.573 -6.317  -23.600 -6.700
+49273.00    -23.811 -6.234  -23.900 -6.600
+49274.00    -24.012 -6.229  -24.200 -6.400
+49275.00    -23.934 -6.287  -24.600 -6.300
+49276.00    -23.489 -6.331  -24.800 -6.300
+49277.00    -23.037 -6.208  -24.900 -6.300
+49278.00    -23.032 -5.863  -24.800 -6.300
+49279.00    -23.383 -5.557  -24.600 -6.300
+49280.00    -23.567 -5.575  -24.200 -6.300
+49281.00    -23.227 -5.774  -23.600 -6.300
+49282.00    -22.639 -5.927  -23.000 -6.300
+49283.00    -22.252 -5.911  -22.500 -6.300
+49284.00    -22.117 -5.793  -22.100 -6.200
+49285.00    -21.998 -5.717  -21.900 -6.200
+49286.00    -21.814 -5.684  -21.900 -6.100
+49287.00    -21.706 -5.613  -22.000 -6.100
+49288.00    -21.801 -5.524  -22.300 -6.000
+49289.00    -22.01  -5.508  -22.500 -5.900
+49290.00    -22.205 -5.578  -22.700 -6.000
+49291.00    -22.328 -5.637  -22.700 -6.000
+49292.00    -22.31  -5.61   -22.600 -6.000
+49293.00    -22.086 -5.541  -22.400 -6.100
+49294.00    -21.692 -5.534  -22.000 -6.000
+49295.00    -21.259 -5.651  -21.800 -6.200
+49296.00    -20.892 -5.748  -21.500 -6.000
+49297.00    -20.567 -5.708  -21.200 -5.800
+49298.00    -20.264 -5.554  -21.100 -5.600
+49299.00    -20.108 -5.336  -21.200 -5.400
+49300.00    -20.288 -5.072  -21.400 -5.300
+49301.00    -20.836 -4.786  -21.600 -5.300
+49302.00    -21.361 -4.585  -21.800 -5.200
+49303.00    -21.49  -4.602  -22.000 -5.100
+49304.00    -21.142 -4.799  -22.000 -4.900
+49305.00    -20.615 -4.935  -21.800 -4.900
+49306.00    -20.322 -4.825  -21.500 -4.900
+49307.00    -20.309 -4.579  -21.000 -4.900
+49308.00    -20.213 -4.482  -20.400 -4.800
+49309.00    -19.782 -4.655  -19.900 -4.800
+49310.00    -19.221 -4.918  -19.400 -4.800
+49311.00    -18.897 -5.055  -19.000 -4.800
+49312.00    -18.869 -5.032  -18.800 -4.700
+49313.00    -18.924 -4.93   -18.800 -4.800
+49314.00    -18.947 -4.794  -19.000 -4.800
+49315.00    -19.013 -4.619  -19.200 -4.900
+49316.00    -19.151 -4.431  -19.500 -4.900
+49317.00    -19.261 -4.283  -19.800 -4.900
+49318.00    -19.29  -4.178  -19.800 -4.900
+49319.00    -19.308 -4.071  -19.800 -4.800
+49320.00    -19.336 -3.958  -19.500 -4.700
+49321.00    -19.259 -3.909  -19.200 -4.600
+49322.00    -18.993 -3.986  -18.800 -4.500
+49323.00    -18.689 -4.162  -18.400 -4.400
+49324.00    -18.501 -4.304  -18.300 -4.300
+49325.00    -18.472 -4.324  -18.100 -4.000
+49326.00    -18.535 -4.221  -18.200 -4.000
+49327.00    -18.592 -4.02   -18.400 -4.000
+49328.00    -18.624 -3.748  -18.700 -3.900
+49329.00    -18.67  -3.454  -19.000 -4.000
+49330.00    -18.735 -3.262  -19.300 -4.000
+49331.00    -18.736 -3.232  -19.400 -4.200
+49332.00    -18.59  -3.287  -19.300 -4.300
+49333.00    -18.334 -3.351  -19.100 -4.200
+49334.00    -18.112 -3.402  -18.700 -4.200
+49335.00    -17.959 -3.356  -18.100 -4.100
+49336.00    -17.747 -3.247  -17.600 -3.900
+49337.00    -17.388 -3.138  -17.000 -3.700
+49338.00    -17.021 -3.137  -16.800 -3.600
+49339.00    -16.866 -3.278  -16.700 -3.600
+49340.00    -16.964 -3.465  -16.800 -3.500
+49341.00    -17.184 -3.572  -17.100 -3.500
+49342.00    -17.423 -3.527  -17.500 -3.500
+49343.00    -17.655 -3.359  -17.900 -3.600
+49344.00    -17.813 -3.224  -18.300 -3.700
+49345.00    -17.835 -3.182  -18.600 -3.800
+49346.00    -17.752 -3.188  -18.700 -3.900
+49347.00    -17.692 -3.178  -18.700 -4.000
+49348.00    -17.717 -3.171  -18.400 -4.000
+49349.00    -17.717 -3.245  -18.100 -3.900
+49350.00    -17.537 -3.412  -17.900 -3.800
+49351.00    -17.187 -3.556  -17.600 -3.700
+49352.00    -16.805 -3.58   -17.300 -3.600
+49353.00    -16.588 -3.467  -17.200 -3.400
+49354.00    -16.618 -3.28   -17.300 -3.300
+49355.00    -16.799 -3.093  -17.500 -3.100
+49356.00    -17.011 -2.927  -17.800 -3.100
+49357.00    -17.249 -2.762  -18.100 -3.100
+49358.00    -17.614 -2.611  -18.500 -3.100
+49359.00    -18.139 -2.669  -18.700 -3.200
+49360.00    -18.653 -2.888  -18.900 -3.200
+49361.00    -18.969 -3.116  -18.900 -3.200
+49362.00    -19.013 -3.245  -18.800 -3.200
+49363.00    -18.808 -3.165  -18.600 -3.200
+49364.00    -18.485 -2.917  -18.400 -3.200
+49365.00    -18.199 -2.67   -18.300 -3.100
+49366.00    -18.008 -2.589  -18.300 -3.000
+49367.00    -17.898 -2.705  -18.400 -3.000
+49368.00    -17.9   -2.905  -18.500 -3.000
+49369.00    -18.03  -3.045  -18.700 -3.000
+49370.00    -18.224 -3.039  -18.900 -3.100
+49371.00    -18.379 -2.996  -19.100 -3.300
+49372.00    -18.417 -3.058  -19.300 -3.500
+49373.00    -18.335 -3.289  -19.400 -3.700
+49374.00    -18.256 -3.491  -19.300 -3.800
+49375.00    -18.261 -3.495  -19.200 -4.100
+49376.00    -18.317 -3.434  -18.800 -4.100
+49377.00    -18.314 -3.467  -18.600 -4.200
+49378.00    -18.145 -3.654  -18.300 -4.100
+49379.00    -17.786 -3.898  -18.100 -4.000
+49380.00    -17.406 -3.954  -18.100 -3.900
+49381.00    -17.259 -3.737  -18.200 -3.700
+49382.00    -17.486 -3.416  -18.500 -3.600
+49383.00    -18.006 -3.203  -18.800 -3.600
+49384.00    -18.573 -3.17   -19.200 -3.500
+49385.00    -19.000 -3.232  -19.800 -3.400
+49386.00    -19.285 -3.282  -20.000 -3.600
+49387.00    -19.509 -3.312  -20.100 -3.900
+49388.00    -19.753 -3.357  -19.900 -4.100
+49389.00    -19.927 -3.485  -19.800 -4.200
+49390.00    -19.846 -3.683  -19.400 -4.300
+49391.00    -19.415 -3.875  -19.100 -4.400
+49392.00    -18.747 -3.988  -18.800 -4.400
+49393.00    -18.069 -3.912  -18.500 -4.400
+49394.00    -17.606 -3.787  -18.400 -4.300
+49395.00    -17.486 -3.812  -18.500 -4.400
+49396.00    -17.668 -3.999  -18.700 -4.500
+49397.00    -18.062 -4.224  -19.100 -4.600
+49398.00    -18.546 -4.383  -19.400 -4.800
+49399.00    -18.9   -4.473  -19.700 -5.000
+49400.00    -18.964 -4.576  -19.900 -5.300
+49401.00    -18.792 -4.715  -20.100 -5.500
+49402.00    -18.583 -4.813  -20.200 -5.700
+49403.00    -18.411 -4.749  -20.000 -5.900
+49404.00    -18.227 -4.549  -19.900 -5.900
+49405.00    -18.057 -4.46   -19.700 -5.900
+49406.00    -17.986 -4.706  -19.700 -5.900
+49407.00    -17.926 -5.112  -19.500 -5.700
+49408.00    -17.79  -5.34   -19.400 -5.600
+49409.00    -17.651 -5.222  -19.300 -5.500
+49410.00    -17.683 -4.921  -19.400 -5.300
+49411.00    -17.934 -4.737  -19.500 -5.300
+49412.00    -18.226 -4.796  -19.600 -5.400
+49413.00    -18.342 -4.976  -19.500 -5.500
+49414.00    -18.225 -5.096  -19.600 -5.600
+49415.00    -18.003 -5.108  -19.400 -5.800
+49416.00    -17.834 -5.075  -19.300 -6.000
+49417.00    -17.782 -5.066  -19.100 -6.000
+49418.00    -17.814 -5.126  -18.900 -6.100
+49419.00    -17.885 -5.293  -18.700 -6.100
+49420.00    -18.033 -5.567  -18.600 -6.100
+49421.00    -18.286 -5.728  -18.400 -6.100
+49422.00    -18.576 -5.73   -18.200 -6.000
+49423.00    -18.702 -5.692  -18.100 -6.000
+49424.00    -18.58  -5.719  -18.100 -6.200
+49425.00    -18.319 -5.848  -18.100 -6.300
+49426.00    -18.031 -6.038  -18.100 -6.500
+49427.00    -17.744 -6.239  -18.000 -6.700
+49428.00    -17.558 -6.43   -17.900 -7.000
+49429.00    -17.573 -6.625  -17.700 -7.100
+49430.00    -17.734 -6.821  -17.600 -7.300
+49431.00    -17.862 -6.888  -17.200 -7.300
+49432.00    -17.766 -6.727  -16.900 -7.300
+49433.00    -17.46  -6.496  -16.800 -7.300
+49434.00    -17.222 -6.469  -16.600 -7.200
+49435.00    -17.252 -6.681  -16.600 -7.000
+49436.00    -17.354 -6.848  -16.800 -6.900
+49437.00    -17.361 -6.747  -17.100 -6.800
+49438.00    -17.347 -6.479  -17.500 -6.900
+49439.00    -17.417 -6.336  -17.800 -6.900
+49440.00    -17.544 -6.472  -18.100 -7.100
+49441.00    -17.627 -6.763  -18.200 -7.400
+49442.00    -17.603 -7.03   -18.300 -7.600
+49443.00    -17.464 -7.234  -18.200 -7.800
+49444.00    -17.254 -7.413  -17.900 -7.900
+49445.00    -17.09  -7.541  -17.700 -8.000
+49446.00    -17.076 -7.561  -17.500 -8.100
+49447.00    -17.153 -7.499  -17.500 -8.000
+49448.00    -17.148 -7.436  -17.500 -7.900
+49449.00    -17.013 -7.383  -17.500 -7.900
+49450.00    -16.894 -7.28   -17.400 -7.800
+49451.00    -16.937 -7.124  -17.400 -7.800
+49452.00    -17.124 -7.045  -17.500 -7.800
+49453.00    -17.334 -7.171  -17.500 -7.900
+49454.00    -17.448 -7.473  -17.400 -8.000
+49455.00    -17.371 -7.792  -17.200 -8.200
+49456.00    -17.103 -8.018  -17.000 -8.400
+49457.00    -16.833 -8.179  -16.800 -8.500
+49458.00    -16.769 -8.318  -16.500 -8.400
+49459.00    -16.844 -8.365  -16.300 -8.400
+49460.00    -16.757 -8.215  -16.000 -8.300
+49461.00    -16.367 -7.933  -15.900 -8.200
+49462.00    -15.908 -7.744  -16.000 -8.100
+49463.00    -15.709 -7.768  -16.100 -7.900
+49464.00    -15.837 -7.849  -16.400 -7.700
+49465.00    -16.13  -7.766  -16.600 -7.700
+49466.00    -16.435 -7.537  -17.000 -7.700
+49467.00    -16.68  -7.404  -17.300 -7.800
+49468.00    -16.834 -7.499  -17.500 -7.900
+49469.00    -16.894 -7.699  -17.600 -8.200
+49470.00    -16.887 -7.817  -17.500 -8.300
+49471.00    -16.831 -7.94   -17.400 -8.500
+49472.00    -16.631 -8.134  -17.200 -8.600
+49473.00    -16.392 -8.311  -16.900 -8.600
+49474.00    -16.413 -8.351  -16.900 -8.600
+49475.00    -16.728 -8.242  -17.000 -8.700
+49476.00    -16.996 -8.111  -17.200 -8.600
+49477.00    -16.932 -8.031  -17.400 -8.500
+49478.00    -16.682 -7.929  -17.600 -8.400
+49479.00    -16.611 -7.751  -17.900 -8.400
+49480.00    -16.842 -7.619  -18.000 -8.400
+49481.00    -17.177 -7.719  -18.200 -8.600
+49482.00    -17.383 -8.067  -18.200 -8.800
+49483.00    -17.392 -8.476  -18.100 -8.900
+49484.00    -17.311 -8.763  -17.800 -9.100
+49485.00    -17.209 -8.917  -17.400 -9.200
+49486.00    -17.242 -8.959  -17.100 -9.300
+49487.00    -17.469 -8.904  -16.700 -9.300
+49488.00    -17.675 -8.75   -16.600 -9.200
+49489.00    -17.613 -8.515  -16.600 -9.100
+49490.00    -17.309 -8.325  -16.800 -9.000
+49491.00    -17.047 -8.289  -17.000 -8.800
+49492.00    -17.028 -8.248  -17.300 -8.600
+49493.00    -17.269 -8.051  -17.800 -8.500
+49494.00    -17.634 -7.775  -18.100 -8.500
+49495.00    -17.93  -7.622  -18.300 -8.400
+49496.00    -18.058 -7.683  -18.500 -8.400
+49497.00    -18.066 -7.809  -18.500 -8.500
+49498.00    -17.983 -7.803  -18.400 -8.600
+49499.00    -17.762 -7.691  -18.100 -8.600
+49500.00    -17.346 -7.651  -17.900 -8.700
+49501.00    -16.919 -7.749  -17.800 -8.600
+49502.00    -16.872 -7.874  -17.700 -8.600
+49503.00    -17.343 -7.936  -17.900 -8.500
+49504.00    -17.975 -7.981  -18.200 -8.400
+49505.00    -18.333 -8.073  -18.700 -8.500
+49506.00    -18.405 -8.13   -19.200 -8.500
+49507.00    -18.54  -8.049  -19.600 -8.500
+49508.00    -18.938 -7.915  -20.000 -8.600
+49509.00    -19.405 -7.902  -20.300 -8.600
+49510.00    -19.659 -8.062  -20.400 -8.800
+49511.00    -19.626 -8.274  -20.300 -8.900
+49512.00    -19.394 -8.404  -20.200 -9.000
+49513.00    -19.114 -8.469  -20.000 -9.100
+49514.00    -18.937 -8.546  -19.800 -9.100
+49515.00    -18.989 -8.653  -19.600 -9.100
+49516.00    -19.243 -8.717  -19.600 -9.000
+49517.00    -19.475 -8.624  -19.800 -8.800
+49518.00    -19.454 -8.279  -20.100 -8.700
+49519.00    -19.19  -7.649  -20.500 -8.400
+49520.00    -19.016 -7.061  -21.000 -8.300
+49521.00    -19.208 -6.696  -21.400 -8.100
+49522.00    -19.769 -6.573  -21.800 -8.000
+49523.00    -20.493 -6.755  -22.000 -8.000
+49524.00    -21.146 -7.19   -22.100 -8.000
+49525.00    -21.641 -7.629  -22.100 -8.000
+49526.00    -22.029 -7.815  -21.900 -8.100
+49527.00    -22.261 -7.712  -21.800 -8.100
+49528.00    -22.21  -7.516  -21.600 -8.100
+49529.00    -21.905 -7.442  -21.700 -8.000
+49530.00    -21.637 -7.526  -21.800 -8.000
+49531.00    -21.735 -7.65   -22.100 -8.100
+49532.00    -22.113 -7.727  -22.600 -8.000
+49533.00    -22.429 -7.778  -23.100 -8.100
+49534.00    -22.586 -7.896  -23.700 -8.200
+49535.00    -22.711 -7.977  -24.300 -7.700
+49536.00    -22.984 -7.891  -24.300 -7.800
+49537.00    -23.345 -7.78   -24.200 -7.800
+49538.00    -23.627 -7.733  -23.900 -7.900
+49539.00    -23.785 -7.754  -23.700 -7.900
+49540.00    -23.846 -7.837  -23.400 -7.900
+49541.00    -23.815 -7.887  -23.100 -7.800
+49542.00    -23.717 -7.84   -22.900 -7.700
+49543.00    -23.683 -7.763  -22.900 -7.600
+49544.00    -23.895 -7.649  -23.100 -7.600
+49545.00    -24.337 -7.524  -23.400 -7.400
+49546.00    -24.771 -7.427  -23.900 -7.400
+49547.00    -24.962 -7.384  -24.500 -7.400
+49548.00    -24.879 -7.363  -25.000 -7.400
+49549.00    -24.79  -7.261  -25.500 -7.400
+49550.00    -24.951 -7.108  -25.900 -7.500
+49551.00    -25.392 -7.07   -26.100 -7.700
+49552.00    -25.979 -7.267  -26.000 -7.800
+49553.00    -26.503 -7.666  -25.900 -7.900
+49554.00    -26.72  -8.016  -25.700 -7.900
+49555.00    -26.485 -8.144  -25.500 -8.000
+49556.00    -26.031 -8.003  -25.300 -8.000
+49557.00    -25.675 -7.741  -25.300 -7.900
+49558.00    -25.608 -7.572  -25.400 -7.800
+49559.00    -25.894 -7.555  -25.700 -7.700
+49560.00    -26.385 -7.649  -26.200 -7.700
+49561.00    -26.828 -7.806  -26.700 -7.600
+49562.00    -27.103 -7.879  -27.200 -7.600
+49563.00    -27.271 -7.739  -27.600 -7.600
+49564.00    -27.44  -7.519  -27.800 -7.700
+49565.00    -27.676 -7.396  -28.000 -7.700
+49566.00    -27.985 -7.481  -27.800 -7.700
+49567.00    -28.297 -7.815  -27.700 -7.700
+49568.00    -28.465 -8.208  -27.500 -7.700
+49569.00    -28.347 -8.552  -27.100 -7.700
+49570.00    -28.089 -8.744  -27.600 -7.400
+49571.00    -27.916 -8.671  -27.700 -7.400
+49572.00    -27.955 -8.318  -27.800 -7.400
+49573.00    -28.228 -7.808  -28.000 -7.200
+49574.00    -28.56  -7.362  -28.200 -7.300
+49575.00    -28.757 -7.088  -28.500 -7.400
+49576.00    -28.588 -6.841  -28.800 -7.500
+49577.00    -28.281 -6.72   -29.100 -7.600
+49578.00    -28.145 -6.823  -29.300 -7.700
+49579.00    -28.281 -7.082  -29.300 -7.900
+49580.00    -28.667 -7.455  -29.200 -7.900
+49581.00    -29.099 -7.862  -29.100 -7.900
+49582.00    -29.33  -8.157  -28.800 -7.900
+49583.00    -29.25  -8.214  -28.500 -7.800
+49584.00    -28.961 -8.018  -28.400 -7.700
+49585.00    -28.685 -7.697  -28.400 -7.600
+49586.00    -28.6   -7.439  -28.600 -7.400
+49587.00    -28.752 -7.346  -28.900 -7.300
+49588.00    -29.122 -7.395  -29.400 -7.300
+49589.00    -29.669 -7.508  -29.800 -7.300
+49590.00    -30.183 -7.619  -30.200 -7.400
+49591.00    -30.349 -7.719  -30.500 -7.500
+49592.00    -30.126 -7.837  -30.600 -7.700
+49593.00    -29.812 -7.971  -30.500 -7.800
+49594.00    -29.713 -8.053  -30.200 -7.900
+49595.00    -29.858 -8.001  -30.000 -7.900
+49596.00    -29.913 -7.856  -29.600 -7.900
+49597.00    -29.7   -7.829  -29.200 -7.800
+49598.00    -29.379 -7.949  -29.100 -7.700
+49599.00    -29.182 -8.049  -29.000 -7.500
+49600.00    -29.213 -7.953  -29.400 -7.400
+49601.00    -29.478 -7.625  -29.700 -7.300
+49602.00    -29.918 -7.24   -30.100 -7.200
+49603.00    -30.414 -7.01   -30.400 -7.200
+49604.00    -30.813 -7.039  -30.700 -7.200
+49605.00    -30.956 -7.18   -30.800 -7.400
+49606.00    -30.831 -7.279  -30.900 -7.400
+49607.00    -30.566 -7.349  -30.600 -7.500
+49608.00    -30.308 -7.449  -30.400 -7.600
+49609.00    -30.158 -7.589  -30.100 -7.500
+49610.00    -30.105 -7.71   -29.800 -7.500
+49611.00    -30.049 -7.73   -29.600 -7.300
+49612.00    -29.92  -7.609  -29.400 -7.200
+49613.00    -29.808 -7.388  -29.400 -7.100
+49614.00    -29.836 -7.172  -29.500 -6.900
+49615.00    -30.017 -7.061  -29.700 -7.000
+49616.00    -30.328 -7.099  -30.100 -7.000
+49617.00    -30.69  -7.186  -30.300 -7.100
+49618.00    -30.923 -7.29   -30.600 -7.200
+49619.00    -30.778 -7.429  -30.600 -7.300
+49620.00    -30.261 -7.585  -30.500 -7.600
+49621.00    -29.706 -7.744  -30.200 -7.700
+49622.00    -29.502 -7.86   -29.900 -7.700
+49623.00    -29.675 -7.841  -29.500 -7.700
+49624.00    -29.819 -7.68   -29.100 -7.600
+49625.00    -29.697 -7.504  -28.800 -7.500
+49626.00    -29.482 -7.481  -28.700 -7.300
+49627.00    -29.431 -7.604  -28.700 -7.100
+49628.00    -29.544 -7.67   -28.800 -7.000
+49629.00    -29.597 -7.515  -29.100 -6.900
+49630.00    -29.43  -7.233  -29.300 -6.700
+49631.00    -29.179 -7.115  -29.600 -6.900
+49632.00    -29.178 -7.176  -29.800 -6.900
+49633.00    -29.386 -7.226  -29.800 -7.100
+49634.00    -29.605 -7.178  -29.600 -7.200
+49635.00    -29.663 -7.125  -29.300 -7.200
+49636.00    -29.374 -7.157  -29.000 -7.200
+49637.00    -28.789 -7.217  -28.500 -7.100
+49638.00    -28.195 -7.171  -28.100 -7.000
+49639.00    -27.833 -6.981  -27.800 -6.700
+49640.00    -27.732 -6.73   -27.500 -6.600
+49641.00    -27.799 -6.522  -27.400 -6.400
+49642.00    -27.949 -6.388  -27.400 -6.300
+49643.00    -28.097 -6.342  -27.600 -6.200
+49644.00    -28.159 -6.428  -27.600 -6.200
+49645.00    -28.151 -6.598  -27.800 -6.300
+49646.00    -28.099 -6.777  -27.900 -6.600
+49647.00    -27.906 -6.895  -27.900 -6.700
+49648.00    -27.529 -6.919  -27.700 -6.900
+49649.00    -27.136 -6.9    -27.400 -7.000
+49650.00    -26.957 -6.902  -27.100 -7.100
+49651.00    -26.972 -6.898  -26.800 -7.100
+49652.00    -26.961 -6.781  -26.600 -6.900
+49653.00    -26.804 -6.581  -26.400 -6.700
+49654.00    -26.673 -6.388  -26.500 -6.600
+49655.00    -26.803 -6.27   -26.600 -6.300
+49656.00    -27.115 -6.19   -26.900 -6.300
+49657.00    -27.224 -6.064  -27.100 -6.200
+49658.00    -26.818 -5.963  -27.300 -6.200
+49659.00    -26.109 -5.946  -27.500 -6.200
+49660.00    -25.467 -5.987  -28.000 -6.100
+49661.00    -25.234 -5.951  -27.700 -6.200
+49662.00    -25.52  -5.795  -27.200 -6.200
+49663.00    -26.008 -5.692  -26.700 -6.100
+49664.00    -26.181 -5.819  -26.100 -6.100
+49665.00    -25.847 -6.093  -25.600 -5.900
+49666.00    -25.301 -6.27   -25.300 -5.800
+49667.00    -24.982 -6.215  -25.100 -5.500
+49668.00    -24.995 -6.033  -24.900 -5.400
+49669.00    -25.125 -5.89   -25.000 -5.300
+49670.00    -25.22  -5.802  -25.200 -5.300
+49671.00    -25.299 -5.682  -25.300 -5.400
+49672.00    -25.366 -5.524  -25.400 -5.500
+49673.00    -25.355 -5.41   -25.500 -5.500
+49674.00    -25.239 -5.379  -25.600 -5.700
+49675.00    -25.045 -5.368  -25.400 -5.800
+49676.00    -24.808 -5.328  -25.200 -5.900
+49677.00    -24.601 -5.319  -24.900 -5.800
+49678.00    -24.547 -5.435  -24.500 -5.800
+49679.00    -24.659 -5.642  -24.200 -5.600
+49680.00    -24.704 -5.716  -24.000 -5.400
+49681.00    -24.517 -5.571  -23.700 -5.200
+49682.00    -24.21  -5.329  -23.600 -5.000
+49683.00    -24.031 -5.127  -23.700 -4.800
+49684.00    -24.087 -4.977  -23.800 -4.800
+49685.00    -24.25  -4.831  -23.900 -4.700
+49686.00    -24.308 -4.744  -23.900 -4.700
+49687.00    -24.154 -4.797  -24.000 -4.900
+49688.00    -23.86  -4.966  -24.000 -5.000
+49689.00    -23.675 -5.06   -23.900 -5.100
+49690.00    -23.792 -4.944  -24.000 -5.300
+49691.00    -24.054 -4.767  -23.500 -5.300
+49692.00    -24.048 -4.791  -23.300 -5.200
+49693.00    -23.616 -5.034  -23.300 -5.000
+49694.00    -23.189 -5.183  -23.000 -4.800
+49695.00    -23.153 -5.046  -22.900 -4.700
+49696.00    -23.433 -4.75   -22.800 -4.400
+49697.00    -23.665 -4.531  -22.900 -4.400
+49698.00    -23.655 -4.47   -22.900 -4.300
+49699.00    -23.518 -4.502  -22.900 -4.400
+49700.00    -23.379 -4.584  -23.000 -4.400
+49701.00    -23.276 -4.656  -23.000 -4.500
+49702.00    -23.179 -4.71   -23.000 -4.800
+49703.00    -23.123 -4.723  -22.800 -4.900
+49704.00    -23.12  -4.675  -22.700 -4.900
+49705.00    -23.084 -4.632  -22.500 -5.000
+49706.00    -22.946 -4.67   -22.400 -4.900
+49707.00    -22.74  -4.765  -22.300 -4.700
+49708.00    -22.605 -4.798  -22.300 -4.400
+49709.00    -22.55  -4.68   -22.200 -4.100
+49710.00    -22.525 -4.434  -22.300 -3.800
+49711.00    -22.553 -4.146  -22.500 -3.500
+49712.00    -22.682 -3.874  -22.600 -3.300
+49713.00    -22.908 -3.651  -22.700 -3.200
+49714.00    -23.15  -3.573  -22.700 -3.100
+49715.00    -23.281 -3.761  -22.600 -3.200
+49716.00    -23.24  -4.218  -22.300 -3.300
+49717.00    -23.114 -4.629  -21.900 -3.300
+49718.00    -23.041 -4.69   -21.600 -3.400
+49719.00    -23.011 -4.436  -21.200 -3.400
+49720.00    -22.859 -4.143  -22.600 -3.900
+49721.00    -22.54  -4.023  -22.700 -3.800
+49722.00    -22.305 -4.043  -22.800 -3.900
+49723.00    -22.431 -4.051  -22.900 -3.900
+49724.00    -22.839 -4.004  -23.000 -3.900
+49725.00    -23.19  -3.985  -23.300 -4.000
+49726.00    -23.31  -4.048  -23.500 -4.100
+49727.00    -23.314 -4.168  -23.500 -4.300
+49728.00    -23.318 -4.303  -23.500 -4.600
+49729.00    -23.243 -4.386  -23.300 -4.800
+49730.00    -23.043 -4.399  -23.100 -5.000
+49731.00    -22.842 -4.343  -22.800 -5.100
+49732.00    -22.76  -4.265  -22.400 -5.200
+49733.00    -22.734 -4.27   -22.100 -5.200
+49734.00    -22.655 -4.429  -21.900 -5.000
+49735.00    -22.589 -4.717  -21.800 -4.800
+49736.00    -22.721 -5.033  -21.800 -4.600
+49737.00    -22.958 -5.129  -21.900 -4.300
+49738.00    -23.146 -4.947  -22.200 -4.100
+49739.00    -23.225 -4.613  -22.400 -4.000
+49740.00    -23.209 -4.237  -22.800 -3.900
+49741.00    -23.207 -3.924  -22.900 -3.900
+49742.00    -23.344 -3.81   -22.900 -3.900
+49743.00    -23.656 -3.985  -22.900 -4.100
+49744.00    -24.026 -4.436  -22.800 -4.200
+49745.00    -24.304 -4.978  -22.700 -4.200
+49746.00    -24.434 -5.29   -22.600 -4.300
+49747.00    -24.403 -5.194  -22.500 -4.200
+49748.00    -24.191 -4.772  -22.500 -4.200
+49749.00    -23.847 -4.282  -22.700 -4.100
+49750.00    -23.596 -4.132  -23.200 -4.200
+49751.00    -23.576 -4.355  -23.400 -4.200
+49752.00    -23.713 -4.654  -23.800 -4.300
+49753.00    -23.852 -4.843  -24.100 -4.300
+49754.00    -23.933 -4.939  -24.200 -4.500
+49755.00    -24.006 -5.004  -24.300 -4.700
+49756.00    -24.099 -5.09   -24.200 -5.000
+49757.00    -24.164 -5.204  -24.100 -5.200
+49758.00    -24.165 -5.293  -23.900 -5.500
+49759.00    -24.181 -5.306  -23.600 -5.600
+49760.00    -24.282 -5.286  -23.400 -5.800
+49761.00    -24.354 -5.329  -23.200 -5.800
+49762.00    -24.172 -5.453  -23.200 -5.700
+49763.00    -23.653 -5.564  -23.200 -5.700
+49764.00    -23.077 -5.637  -23.300 -5.600
+49765.00    -22.779 -5.567  -23.500 -5.400
+49766.00    -22.832 -5.402  -23.700 -5.400
+49767.00    -23.087 -5.282  -23.900 -5.300
+49768.00    -23.374 -5.248  -23.900 -5.300
+49769.00    -23.63  -5.279  -23.800 -5.400
+49770.00    -23.905 -5.384  -23.500 -5.400
+49771.00    -24.254 -5.613  -23.200 -5.500
+49772.00    -24.606 -5.941  -22.800 -5.600
+49773.00    -24.792 -6.236  -22.400 -5.600
+49774.00    -24.734 -6.357  -22.100 -5.600
+49775.00    -24.473 -6.212  -21.900 -5.600
+49776.00    -24.144 -5.883  -21.800 -5.500
+49777.00    -23.881 -5.624  -23.600 -5.400
+49778.00    -23.719 -5.663  -23.700 -5.400
+49779.00    -23.603 -5.974  -24.000 -5.500
+49780.00    -23.497 -6.334  -24.100 -5.600
+49781.00    -23.45  -6.566  -24.300 -5.800
+49782.00    -23.513 -6.647  -24.300 -6.100
+49783.00    -23.639 -6.679  -24.100 -6.300
+49784.00    -23.701 -6.77   -23.700 -6.600
+49785.00    -23.581 -6.931  -23.300 -6.900
+49786.00    -23.314 -7.06   -23.000 -7.000
+49787.00    -23.03  -7.06   -22.600 -7.200
+49788.00    -22.835 -6.971  -22.300 -7.200
+49789.00    -22.769 -6.939  -22.100 -7.300
+49790.00    -22.794 -7.025  -22.100 -7.200
+49791.00    -22.814 -7.093  -22.200 -7.200
+49792.00    -22.722 -7.002  -22.300 -7.100
+49793.00    -22.567 -6.745  -22.500 -7.100
+49794.00    -22.488 -6.507  -22.700 -7.000
+49795.00    -22.534 -6.498  -22.800 -7.100
+49796.00    -22.617 -6.743  -22.800 -7.100
+49797.00    -22.639 -7.087  -22.700 -7.300
+49798.00    -22.633 -7.372  -22.300 -7.300
+49799.00    -22.722 -7.56   -22.100 -7.400
+49800.00    -22.899 -7.7    -21.800 -7.400
+49801.00    -23.001 -7.829  -21.700 -7.500
+49802.00    -22.894 -7.922  -21.600 -7.400
+49803.00    -22.605 -7.91   -21.600 -7.300
+49804.00    -22.317 -7.772  -21.800 -7.300
+49805.00    -22.216 -7.598  -22.100 -7.300
+49806.00    -22.259 -7.539  -22.500 -7.300
+49807.00    -22.27  -7.66   -22.700 -7.400
+49808.00    -22.159 -7.887  -23.000 -7.500
+49809.00    -22.027 -8.095  -23.000 -7.700
+49810.00    -22.004 -8.223  -22.900 -8.000
+49811.00    -22.061 -8.307  -22.600 -8.200
+49812.00    -22.084 -8.415  -22.200 -8.400
+49813.00    -22.077 -8.566  -21.800 -8.600
+49814.00    -22.107 -8.676  -21.400 -8.700
+49815.00    -22.142 -8.634  -21.000 -8.700
+49816.00    -22.082 -8.449  -20.800 -8.600
+49817.00    -21.956 -8.302  -20.600 -8.600
+49818.00    -21.911 -8.361  -20.700 -8.500
+49819.00    -21.966 -8.55   -21.000 -8.400
+49820.00    -21.985 -8.591  -21.400 -8.400
+49821.00    -21.738 -8.385  -21.700 -8.400
+49822.00    -21.434 -8.108  -22.100 -8.400
+49823.00    -21.37  -8.04   -22.400 -8.500
+49824.00    -21.526 -8.275  -22.400 -8.500
+49825.00    -21.732 -8.624  -22.400 -8.700
+49826.00    -21.871 -8.839  -22.100 -8.800
+49827.00    -21.966 -8.843  -21.800 -8.800
+49828.00    -22.131 -8.791  -21.400 -8.800
+49829.00    -22.304 -8.765  -21.100 -8.800
+49830.00    -22.35  -8.753  -20.900 -8.700
+49831.00    -22.22  -8.741  -20.900 -8.600
+49832.00    -21.969 -8.709  -21.100 -8.600
+49833.00    -21.778 -8.637  -21.300 -8.500
+49834.00    -21.811 -8.532  -21.700 -8.600
+49835.00    -22.006 -8.444  -22.100 -8.600
+49836.00    -22.183 -8.443  -22.300 -8.700
+49837.00    -22.26  -8.56   -22.500 -8.900
+49838.00    -22.26  -8.763  -22.500 -9.100
+49839.00    -22.173 -8.993  -22.300 -9.200
+49840.00    -21.978 -9.223  -21.800 -9.200
+49841.00    -21.787 -9.398  -21.400 -9.300
+49842.00    -21.736 -9.496  -21.000 -9.300
+49843.00    -21.732 -9.46   -20.600 -9.200
+49844.00    -21.524 -9.247  -20.500 -9.100
+49845.00    -21.105 -8.972  -20.400 -9.000
+49846.00    -20.845 -8.852  -20.600 -8.900
+49847.00    -21.061 -8.949  -21.000 -8.900
+49848.00    -21.632 -9.068  -21.400 -8.800
+49849.00    -22.134 -8.967  -22.000 -8.700
+49850.00    -22.377 -8.702  -22.300 -8.700
+49851.00    -22.49  -8.566  -22.600 -8.900
+49852.00    -22.604 -8.71   -22.700 -8.900
+49853.00    -22.693 -8.98   -22.700 -8.900
+49854.00    -22.662 -9.132  -22.500 -8.900
+49855.00    -22.48  -9.105  -22.100 -8.900
+49856.00    -22.234 -9.000  -21.700 -8.800
+49857.00    -22.089 -8.885  -21.500 -8.800
+49858.00    -22.162 -8.757  -21.300 -8.700
+49859.00    -22.379 -8.644  -21.300 -8.600
+49860.00    -22.542 -8.621  -21.500 -8.500
+49861.00    -22.61  -8.696  -21.800 -8.600
+49862.00    -22.787 -8.781  -22.300 -8.600
+49863.00    -23.171 -8.783  -22.700 -8.700
+49864.00    -23.641 -8.767  -23.100 -8.700
+49865.00    -23.974 -8.865  -23.300 -8.800
+49866.00    -24.035 -9.068  -23.400 -9.000
+49867.00    -23.855 -9.227  -23.300 -9.100
+49868.00    -23.581 -9.231  -23.100 -9.100
+49869.00    -23.435 -9.142  -22.800 -9.100
+49870.00    -23.587 -9.132  -22.600 -9.100
+49871.00    -23.919 -9.219  -22.400 -9.100
+49872.00    -24.056 -9.259  -22.400 -8.900
+49873.00    -23.793 -9.158  -22.700 -8.800
+49874.00    -23.391 -8.974  -22.900 -8.800
+49875.00    -23.28  -8.779  -23.400 -8.800
+49876.00    -23.56  -8.498  -23.900 -8.700
+49877.00    -23.983 -8.092  -24.300 -8.700
+49878.00    -24.31  -7.727  -24.700 -8.700
+49879.00    -24.504 -7.645  -24.900 -8.800
+49880.00    -24.67  -7.906  -24.900 -8.800
+49881.00    -24.913 -8.312  -24.900 -8.800
+49882.00    -25.237 -8.609  -24.700 -8.700
+49883.00    -25.532 -8.757  -24.500 -8.600
+49884.00    -25.586 -8.817  -24.300 -8.500
+49885.00    -25.507 -8.823  -24.300 -8.300
+49886.00    -25.63  -8.728  -24.300 -8.200
+49887.00    -26.013 -8.539  -24.600 -8.100
+49888.00    -26.32  -8.406  -25.100 -8.000
+49889.00    -26.224 -8.444  -25.500 -8.000
+49890.00    -25.768 -8.55   -26.100 -8.000
+49891.00    -25.413 -8.583  -26.600 -8.200
+49892.00    -25.425 -8.56   -26.900 -8.300
+49893.00    -25.639 -8.617  -27.100 -8.400
+49894.00    -25.85  -8.795  -27.200 -8.500
+49895.00    -26.137 -8.961  -27.100 -8.600
+49896.00    -26.7   -8.958  -26.900 -8.600
+49897.00    -27.309 -8.713  -26.700 -8.400
+49898.00    -27.865 -8.474  -26.500 -8.300
+49899.00    -28.378 -8.417  -26.400 -8.200
+49900.00    -28.702 -8.45   -26.400 -8.000
+49901.00    -28.656 -8.429  -26.600 -7.900
+49902.00    -28.335 -8.308  -27.000 -7.900
+49903.00    -28.129 -8.148  -27.500 -7.900
+49904.00    -28.393 -8.005  -27.900 -8.000
+49905.00    -29.156 -7.91   -28.500 -8.000
+49906.00    -30.083 -7.923  -28.900 -8.100
+49907.00    -30.805 -8.127  -29.300 -8.300
+49908.00    -31.152 -8.474  -29.500 -8.400
+49909.00    -31.126 -8.724  -29.600 -8.400
+49910.00    -30.798 -8.676  -29.800 -8.400
+49911.00    -30.419 -8.516  -29.700 -8.400
+49912.00    -30.024 -8.405  -29.500 -8.300
+49913.00    -29.694 -8.404  -29.500 -8.200
+49914.00    -29.729 -8.44   -29.700 -8.200
+49915.00    -30.26  -8.406  -30.000 -8.200
+49916.00    -30.944 -8.365  -30.300 -8.300
+49917.00    -31.292 -8.442  -30.700 -8.400
+49918.00    -31.247 -8.575  -31.400 -8.500
+49919.00    -31.216 -8.638  -31.900 -8.600
+49920.00    -31.487 -8.598  -32.400 -8.800
+49921.00    -31.891 -8.54   -32.700 -8.900
+49922.00    -32.115 -8.534  -32.800 -8.900
+49923.00    -32.1   -8.554  -32.800 -8.900
+49924.00    -31.971 -8.512  -32.800 -8.900
+49925.00    -31.774 -8.272  -32.500 -8.700
+49926.00    -31.577 -7.928  -32.200 -8.500
+49927.00    -31.515 -7.639  -31.900 -8.400
+49928.00    -31.664 -7.469  -31.900 -8.300
+49929.00    -31.932 -7.431  -32.000 -8.200
+49930.00    -32.183 -7.568  -32.000 -8.200
+49931.00    -32.433 -7.912  -32.300 -8.200
+49932.00    -32.662 -8.138  -32.700 -8.400
+49933.00    -32.963 -8.181  -33.200 -8.500
+49934.00    -33.362 -8.205  -33.500 -8.600
+49935.00    -33.726 -8.336  -33.800 -8.800
+49936.00    -33.948 -8.565  -34.000 -8.800
+49937.00    -34.077 -8.742  -34.000 -8.800
+49938.00    -34.252 -8.709  -34.200 -8.700
+49939.00    -34.508 -8.427  -34.100 -8.600
+49940.00    -34.609 -8.133  -34.000 -8.500
+49941.00    -34.488 -8.056  -34.000 -8.300
+49942.00    -34.401 -8.171  -34.200 -8.200
+49943.00    -34.593 -8.298  -34.400 -8.200
+49944.00    -34.989 -8.335  -34.700 -8.200
+49945.00    -35.29  -8.333  -34.900 -8.300
+49946.00    -35.361 -8.37   -35.200 -8.400
+49947.00    -35.305 -8.443  -35.400 -8.500
+49948.00    -35.293 -8.503  -35.500 -8.700
+49949.00    -35.336 -8.53   -35.400 -8.700
+49950.00    -35.346 -8.527  -35.200 -8.700
+49951.00    -35.347 -8.499  -35.000 -8.700
+49952.00    -35.427 -8.466  -34.900 -8.500
+49953.00    -35.563 -8.46   -34.700 -8.400
+49954.00    -35.521 -8.475  -34.700 -8.200
+49955.00    -35.362 -8.394  -34.800 -8.100
+49956.00    -35.373 -8.223  -35.100 -8.000
+49957.00    -35.688 -8.026  -35.300 -8.000
+49958.00    -36.091 -7.956  -35.700 -8.100
+49959.00    -36.37  -8.076  -36.000 -8.200
+49960.00    -36.548 -8.135  -36.200 -8.400
+49961.00    -36.726 -8.08   -36.500 -8.600
+49962.00    -36.847 -8.078  -36.600 -8.800
+49963.00    -36.861 -8.229  -36.500 -9.000
+49964.00    -36.779 -8.488  -36.400 -9.100
+49965.00    -36.615 -8.714  -36.300 -9.100
+49966.00    -36.445 -8.75   -36.200 -9.100
+49967.00    -36.352 -8.556  -36.000 -8.800
+49968.00    -36.269 -8.263  -35.900 -8.700
+49969.00    -36.151 -8.079  -36.000 -8.500
+49970.00    -36.077 -8.092  -36.000 -8.300
+49971.00    -36.148 -8.197  -36.100 -8.200
+49972.00    -36.373 -8.241  -36.200 -8.100
+49973.00    -36.631 -8.195  -36.200 -8.200
+49974.00    -36.762 -8.15   -36.200 -8.300
+49975.00    -36.676 -8.19   -36.100 -8.400
+49976.00    -36.397 -8.304  -35.900 -8.600
+49977.00    -36.035 -8.419  -35.600 -8.600
+49978.00    -35.742 -8.462  -35.300 -8.600
+49979.00    -35.624 -8.408  -35.000 -8.500
+49980.00    -35.667 -8.328  -34.800 -8.400
+49981.00    -35.733 -8.43   -34.700 -8.300
+49982.00    -35.721 -8.631  -34.700 -8.000
+49983.00    -35.649 -8.651  -34.900 -7.800
+49984.00    -35.618 -8.403  -35.100 -7.700
+49985.00    -35.683 -8.016  -35.500 -7.600
+49986.00    -35.797 -7.726  -35.700 -7.600
+49987.00    -35.857 -7.672  -35.900 -7.600
+49988.00    -35.792 -7.761  -36.000 -7.700
+49989.00    -35.636 -7.849  -36.100 -7.900
+49990.00    -35.486 -7.879  -35.900 -8.000
+49991.00    -35.414 -7.885  -35.700 -8.000
+49992.00    -35.417 -7.91   -35.500 -8.100
+49993.00    -35.442 -7.94   -35.300 -8.000
+49994.00    -35.442 -7.919  -35.200 -7.900
+49995.00    -35.406 -7.857  -35.000 -7.700
+49996.00    -35.359 -7.743  -35.000 -7.600
+49997.00    -35.325 -7.601  -35.000 -7.400
+49998.00    -35.303 -7.521  -35.100 -7.400
+49999.00    -35.274 -7.504  -35.200 -7.400
+50000.00    -35.261 -7.468  -35.300 -7.400
+50001.00    -35.331 -7.377  -35.200 -7.600
+50002.00    -35.412 -7.317  -35.100 -7.700
+50003.00    -35.282 -7.447  -34.900 -7.800
+50004.00    -34.828 -7.641  -34.700 -7.900
+50005.00    -34.21  -7.787  -34.300 -7.900
+50006.00    -33.717 -7.838  -34.000 -7.900
+50007.00    -33.484 -7.776  -33.700 -7.800
+50008.00    -33.416 -7.655  -33.600 -7.600
+50009.00    -33.396 -7.58   -33.400 -7.400
+50010.00    -33.437 -7.586  -33.400 -7.200
+50011.00    -33.575 -7.568  -33.400 -6.900
+50012.00    -33.726 -7.383  -33.500 -6.800
+50013.00    -33.747 -7.048  -33.500 -6.600
+50014.00    -33.596 -6.774  -33.400 -6.700
+50015.00    -33.367 -6.75   -33.200 -6.700
+50016.00    -33.227 -6.921  -33.100 -6.700
+50017.00    -33.224 -7.077  -33.000 -6.900
+50018.00    -33.307 -7.08   -32.800 -6.900
+50019.00    -33.384 -6.962  -32.500 -6.900
+50020.00    -33.363 -6.831  -32.300 -6.800
+50021.00    -33.213 -6.74   -32.100 -6.700
+50022.00    -32.986 -6.667  -32.200 -6.600
+50023.00    -32.769 -6.592  -32.100 -6.400
+50024.00    -32.641 -6.528  -32.100 -6.200
+50025.00    -32.633 -6.5    -32.100 -6.100
+50026.00    -32.694 -6.508  -32.200 -6.000
+50027.00    -32.713 -6.507  -32.200 -6.100
+50028.00    -32.643 -6.442  -32.000 -6.100
+50029.00    -32.577 -6.293  -31.700 -6.100
+50030.00    -32.616 -6.082  -31.500 -6.400
+50031.00    -32.588 -5.914  -31.200 -6.500
+50032.00    -32.224 -5.906  -30.700 -6.600
+50033.00    -31.607 -6.055  -30.400 -6.700
+50034.00    -31.082 -6.26   -30.100 -6.600
+50035.00    -30.819 -6.394  -29.900 -6.600
+50036.00    -30.711 -6.366  -29.900 -6.400
+50037.00    -30.607 -6.214  -30.000 -6.200
+50038.00    -30.601 -6.085  -30.100 -5.900
+50039.00    -30.807 -6.032  -30.300 -5.800
+50040.00    -31.079 -5.93   -30.500 -5.600
+50041.00    -31.117 -5.695  -30.700 -5.500
+50042.00    -30.82  -5.463  -30.600 -5.600
+50043.00    -30.385 -5.474  -30.500 -5.600
+50044.00    -30.102 -5.804  -30.400 -5.600
+50045.00    -30.101 -6.219  -30.200 -5.800
+50046.00    -30.323 -6.466  -29.900 -5.900
+50047.00    -30.582 -6.517  -29.800 -5.900
+50048.00    -30.681 -6.465  -29.600 -5.900
+50049.00    -30.591 -6.31   -29.600 -5.800
+50050.00    -30.483 -5.984  -29.800 -5.700
+50051.00    -30.525 -5.636  -30.000 -5.600
+50052.00    -30.702 -5.408  -30.200 -5.400
+50053.00    -30.883 -5.347  -30.400 -5.200
+50054.00    -30.973 -5.378  -30.600 -5.100
+50055.00    -30.935 -5.38   -30.600 -5.200
+50056.00    -30.736 -5.315  -30.600 -5.200
+50057.00    -30.376 -5.244  -30.300 -5.200
+50058.00    -29.921 -5.22   -30.100 -5.400
+50059.00    -29.527 -5.23   -29.600 -5.400
+50060.00    -29.226 -5.249  -29.300 -5.500
+50061.00    -29.022 -5.293  -29.000 -5.500
+50062.00    -28.989 -5.385  -28.600 -5.500
+50063.00    -29.081 -5.472  -28.600 -5.400
+50064.00    -29.082 -5.462  -28.600 -5.300
+50065.00    -28.888 -5.347  -28.800 -5.100
+50066.00    -28.737 -5.185  -28.900 -5.000
+50067.00    -28.889 -5.061  -29.100 -4.800
+50068.00    -29.254 -4.953  -29.200 -4.800
+50069.00    -29.504 -4.784  -29.200 -4.800
+50070.00    -29.474 -4.651  -29.100 -4.800
+50071.00    -29.3   -4.766  -28.900 -4.800
+50072.00    -29.2   -5.091  -28.700 -4.900
+50073.00    -29.275 -5.38   -28.400 -5.000
+50074.00    -29.48  -5.421  -28.300 -5.100
+50075.00    -29.656 -5.252  -28.200 -5.100
+50076.00    -29.628 -5.083  -28.200 -5.100
+50077.00    -29.412 -4.994  -28.400 -4.900
+50078.00    -29.256 -4.89   -28.700 -4.900
+50079.00    -29.357 -4.719  -29.000 -4.800
+50080.00    -29.591 -4.596  -29.100 -4.700
+50081.00    -29.68  -4.643  -29.400 -4.600
+50082.00    -29.557 -4.797  -29.500 -4.500
+50083.00    -29.394 -4.888  -29.400 -4.600
+50084.00    -29.306 -4.849  -29.300 -4.600
+50085.00    -29.226 -4.768  -28.800 -4.700
+50086.00    -29.079 -4.739  -28.400 -4.800
+50087.00    -28.892 -4.756  -28.000 -5.000
+50088.00    -28.71  -4.783  -27.600 -5.200
+50089.00    -28.546 -4.849  -27.400 -5.300
+50090.00    -28.421 -5.007  -27.400 -5.200
+50091.00    -28.349 -5.208  -27.600 -5.300
+50092.00    -28.276 -5.31   -27.800 -5.300
+50093.00    -28.168 -5.232  -28.100 -5.200
+50094.00    -28.132 -5.062  -28.600 -5.100
+50095.00    -28.313 -4.945  -28.900 -5.000
+50096.00    -28.673 -4.904  -29.100 -5.000
+50097.00    -29.01  -4.864  -29.300 -4.900
+50098.00    -29.212 -4.833  -29.200 -4.900
+50099.00    -29.356 -4.937  -29.100 -5.000
+50100.00    -29.552 -5.217  -28.800 -5.000
+50101.00    -29.802 -5.482  -28.700 -5.000
+50102.00    -30.012 -5.505  -28.500 -5.000
+50103.00    -30.053 -5.306  -28.300 -5.000
+50104.00    -29.834 -5.112  -28.400 -5.000
+50105.00    -29.454 -5.049  -28.600 -4.900
+50106.00    -29.222 -5.015  -29.000 -4.900
+50107.00    -29.365 -4.949  -29.300 -4.900
+50108.00    -29.717 -4.913  -29.700 -5.000
+50109.00    -29.911 -5.02   -29.900 -5.100
+50110.00    -29.841 -5.262  -30.000 -5.200
+50111.00    -29.729 -5.495  -29.900 -5.400
+50112.00    -29.714 -5.618  -29.600 -5.600
+50113.00    -29.645 -5.663  -29.200 -5.700
+50114.00    -29.423 -5.681  -28.700 -5.800
+50115.00    -29.133 -5.67   -28.500 -5.800
+50116.00    -28.932 -5.62   -28.200 -5.800
+50117.00    -28.852 -5.589  -28.100 -5.800
+50118.00    -28.845 -5.645  -28.000 -5.800
+50119.00    -28.935 -5.767  -28.200 -5.800
+50120.00    -29.209 -5.857  -28.300 -5.800
+50121.00    -29.711 -5.902  -28.200 -5.900
+50122.00    -30.118 -5.896  -28.200 -6.000
+50123.00    -30.281 -5.882  -28.200 -6.100
+50124.00    -30.265 -5.893  -28.300 -6.200
+50125.00    -30.117 -5.894  -28.600 -6.100
+50126.00    -29.92  -5.875  -29.100 -6.000
+50127.00    -29.779 -5.885  -29.600 -5.900
+50128.00    -29.609 -5.96   -29.800 -5.700
+50129.00    -29.461 -6.013  -29.800 -5.600
+50130.00    -29.437 -5.924  -29.700 -5.600
+50131.00    -29.438 -5.71   -29.300 -5.600
+50132.00    -29.353 -5.582  -29.000 -5.700
+50133.00    -29.218 -5.715  -28.800 -5.900
+50134.00    -29.233 -6.025  -28.800 -6.000
+50135.00    -29.54  -6.278  -29.100 -6.100
+50136.00    -30.009 -6.389  -29.500 -6.300
+50137.00    -30.356 -6.464  -30.000 -6.400
+50138.00    -30.495 -6.594  -30.300 -6.500
+50139.00    -30.591 -6.764  -30.500 -6.600
+50140.00    -30.729 -6.92   -30.500 -6.900
+50141.00    -30.727 -7.034  -30.100 -7.000
+50142.00    -30.42  -7.097  -29.700 -7.100
+50143.00    -29.944 -7.096  -29.200 -7.100
+50144.00    -29.568 -7.053  -28.700 -7.200
+50145.00    -29.366 -7.034  -28.400 -7.200
+50146.00    -29.21  -7.087  -28.200 -7.100
+50147.00    -29.035 -7.179  -28.200 -7.100
+50148.00    -28.924 -7.249  -28.400 -7.200
+50149.00    -28.931 -7.285  -28.700 -7.200
+50150.00    -29.022 -7.314  -29.100 -7.300
+50151.00    -29.113 -7.363  -29.400 -7.300
+50152.00    -29.17  -7.426  -29.500 -7.400
+50153.00    -29.216 -7.48   -29.500 -7.500
+50154.00    -29.273 -7.534  -29.400 -7.600
+50155.00    -29.332 -7.631  -29.100 -7.600
+50156.00    -29.352 -7.78   -28.700 -7.800
+50157.00    -29.321 -7.891  -28.400 -7.800
+50158.00    -29.256 -7.841  -28.100 -7.900
+50159.00    -29.18  -7.622  -28.000 -7.900
+50160.00    -29.102 -7.415  -28.100 -7.900
+50161.00    -29.037 -7.436  -28.200 -7.900
+50162.00    -29.044 -7.72   -28.400 -8.000
+50163.00    -29.179 -8.078  -28.500 -7.900
+50164.00    -29.403 -8.294  -28.700 -7.900
+50165.00    -29.629 -8.32   -28.800 -8.000
+50166.00    -29.829 -8.268  -28.800 -8.000
+50167.00    -30.011 -8.254  -28.700 -8.100
+50168.00    -30.084 -8.305  -28.600 -8.200
+50169.00    -29.876 -8.364  -28.300 -8.300
+50170.00    -29.464 -8.392  -27.900 -8.500
+50171.00    -28.989 -8.361  -27.700 -8.500
+50172.00    -28.666 -8.305  -27.400 -8.500
+50173.00    -28.606 -8.301  -27.400 -8.500
+50174.00    -28.693 -8.367  -27.500 -8.400
+50175.00    -28.784 -8.423  -28.000 -8.300
+50176.00    -28.867 -8.396  -28.400 -8.300
+50177.00    -28.994 -8.338  -28.700 -8.400
+50178.00    -29.092 -8.369  -29.100 -8.400
+50179.00    -29.093 -8.541  -29.400 -8.500
+50180.00    -29.012 -8.775  -29.500 -8.700
+50181.00    -28.909 -8.941  -29.400 -8.800
+50182.00    -28.84  -8.991  -29.200 -8.800
+50183.00    -28.802 -8.973  -28.900 -8.900
+50184.00    -28.733 -8.959  -28.400 -8.900
+50185.00    -28.558 -8.964  -28.000 -8.900
+50186.00    -28.286 -8.932  -27.700 -8.900
+50187.00    -28.04  -8.816  -27.500 -8.800
+50188.00    -27.977 -8.672  -27.500 -8.800
+50189.00    -28.144 -8.65   -27.600 -8.800
+50190.00    -28.426 -8.844  -27.800 -8.900
+50191.00    -28.662 -9.175  -28.100 -9.000
+50192.00    -28.763 -9.444  -28.400 -9.100
+50193.00    -28.796 -9.531  -28.500 -9.300
+50194.00    -28.874 -9.49   -28.500 -9.300
+50195.00    -28.979 -9.454  -28.500 -9.400
+50196.00    -28.959 -9.48   -28.200 -9.400
+50197.00    -28.674 -9.499  -27.800 -9.400
+50198.00    -28.166 -9.45   -27.500 -9.300
+50199.00    -27.711 -9.384  -27.200 -9.200
+50200.00    -27.474 -9.296  -27.000 -9.100
+50201.00    -27.509 -9.247  -27.000 -9.100
+50202.00    -27.81  -9.282  -27.100 -9.000
+50203.00    -28.257 -9.318  -27.500 -9.100
+50204.00    -28.644 -9.243  -27.900 -9.200
+50205.00    -28.806 -9.089  -28.400 -9.300
+50206.00    -28.598 -8.975  -28.900 -9.500
+50207.00    -28.151 -9.038  -29.300 -9.600
+50208.00    -27.721 -9.255  -29.400 -9.700
+50209.00    -27.502 -9.442  -29.400 -9.800
+50210.00    -27.703 -9.49   -29.300 -9.700
+50211.00    -28.404 -9.46   -29.000 -9.700
+50212.00    -29.094 -9.383  -28.700 -9.500
+50213.00    -29.457 -9.335  -28.400 -9.300
+50214.00    -29.424 -9.336  -28.300 -9.200
+50215.00    -29.11  -9.319  -28.100 -9.100
+50216.00    -28.799 -9.232  -28.100 -9.000
+50217.00    -28.748 -9.102  -28.300 -8.900
+50218.00    -28.967 -9.008  -28.500 -9.000
+50219.00    -29.226 -8.988  -28.600 -9.000
+50220.00    -29.296 -9.005  -28.800 -9.000
+50221.00    -29.186 -9.005  -28.800 -9.200
+50222.00    -29.065 -8.998  -28.700 -9.300
+50223.00    -29.007 -9.042  -28.500 -9.300
+50224.00    -28.956 -9.186  -28.300 -9.300
+50225.00    -28.895 -9.42   -28.000 -9.300
+50226.00    -28.9   -9.618  -27.900 -9.200
+50227.00    -28.934 -9.69   -27.900 -9.200
+50228.00    -28.871 -9.625  -28.000 -9.000
+50229.00    -28.756 -9.503  -28.300 -9.000
+50230.00    -28.864 -9.426  -28.600 -9.000
+50231.00    -29.358 -9.384  -29.000 -9.000
+50232.00    -30.023 -9.256  -29.400 -9.100
+50233.00    -30.487 -9.008  -29.700 -9.100
+50234.00    -30.61  -8.791  -30.000 -9.200
+50235.00    -30.561 -8.81   -30.100 -9.200
+50236.00    -30.532 -9.069  -30.200 -9.200
+50237.00    -30.547 -9.326  -30.100 -9.100
+50238.00    -30.581 -9.359  -29.900 -9.100
+50239.00    -30.692 -9.192  -30.000 -9.000
+50240.00    -30.93  -8.975  -29.900 -8.900
+50241.00    -31.233 -8.864  -30.000 -8.800
+50242.00    -31.444 -8.892  -30.200 -8.700
+50243.00    -31.444 -8.991  -30.500 -8.700
+50244.00    -31.287 -9.077  -30.900 -8.800
+50245.00    -31.193 -9.087  -31.200 -8.800
+50246.00    -31.343 -8.964  -31.500 -9.000
+50247.00    -31.651 -8.626  -31.700 -9.200
+50248.00    -31.912 -8.354  -31.900 -9.300
+50249.00    -31.982 -8.356  -32.000 -9.400
+50250.00    -31.881 -8.552  -31.800 -9.500
+50251.00    -31.732 -8.801  -31.800 -9.400
+50252.00    -31.645 -8.996  -31.600 -9.400
+50253.00    -31.733 -9.125  -31.500 -9.200
+50254.00    -32.068 -9.204  -31.500 -9.000
+50255.00    -32.526 -9.185  -31.600 -8.900
+50256.00    -32.804 -9.013  -31.800 -8.900
+50257.00    -32.842 -8.803  -32.100 -8.800
+50258.00    -32.954 -8.676  -32.500 -8.800
+50259.00    -33.423 -8.732  -32.800 -8.900
+50260.00    -34.065 -8.894  -33.200 -8.900
+50261.00    -34.561 -8.855  -33.700 -8.900
+50262.00    -34.691 -8.649  -34.100 -8.900
+50263.00    -34.607 -8.556  -34.500 -8.900
+50264.00    -34.604 -8.675  -34.800 -8.700
+50265.00    -34.769 -8.814  -34.900 -8.600
+50266.00    -34.999 -8.744  -35.000 -8.500
+50267.00    -35.206 -8.482  -35.000 -8.400
+50268.00    -35.411 -8.248  -35.000 -8.400
+50269.00    -35.707 -8.181  -35.000 -8.400
+50270.00    -36.123 -8.244  -35.200 -8.300
+50271.00    -36.514 -8.36   -35.200 -8.500
+50272.00    -36.655 -8.526  -35.400 -8.600
+50273.00    -36.524 -8.726  -35.500 -8.800
+50274.00    -36.416 -8.858  -35.700 -8.800
+50275.00    -36.639 -8.827  -35.900 -9.000
+50276.00    -37.114 -8.713  -36.000 -9.000
+50277.00    -37.464 -8.688  -36.000 -8.900
+50278.00    -37.448 -8.781  -36.100 -8.800
+50279.00    -37.134 -8.855  -36.100 -8.700
+50280.00    -36.745 -8.79   -36.100 -8.600
+50281.00    -36.504 -8.636  -36.200 -8.600
+50282.00    -36.58  -8.534  -36.200 -8.400
+50283.00    -36.866 -8.572  -36.300 -8.400
+50284.00    -37.048 -8.664  -36.500 -8.400
+50285.00    -36.97  -8.684  -36.700 -8.500
+50286.00    -36.881 -8.648  -36.900 -8.500
+50287.00    -37.183 -8.681  -37.200 -8.700
+50288.00    -37.914 -8.81   -37.500 -8.900
+50289.00    -38.712 -8.841  -37.800 -9.000
+50290.00    -39.162 -8.761  -38.100 -9.200
+50291.00    -39.23  -8.752  -38.200 -9.300
+50292.00    -39.206 -8.875  -38.500 -9.300
+50293.00    -39.316 -8.994  -38.700 -9.200
+50294.00    -39.543 -8.94   -38.900 -9.000
+50295.00    -39.717 -8.754  -39.200 -8.800
+50296.00    -39.727 -8.625  -39.500 -8.700
+50297.00    -39.698 -8.628  -39.800 -8.400
+50298.00    -39.895 -8.631  -40.100 -8.400
+50299.00    -40.375 -8.529  -40.300 -8.300
+50300.00    -40.82  -8.427  -40.300 -8.300
+50301.00    -40.895 -8.496  -40.300 -8.400
+50302.00    -40.729 -8.727  -40.300 -8.400
+50303.00    -40.798 -8.954  -40.400 -8.600
+50304.00    -41.176 -9.03   -40.600 -8.800
+50305.00    -41.526 -9.004  -40.700 -8.800
+50306.00    -41.524 -8.971  -40.800 -8.900
+50307.00    -41.175 -8.898  -40.800 -8.800
+50308.00    -40.735 -8.723  -40.600 -8.800
+50309.00    -40.421 -8.51   -40.100 -8.700
+50310.00    -40.32  -8.397  -39.600 -8.500
+50311.00    -40.398 -8.468  -39.400 -8.400
+50312.00    -40.518 -8.647  -39.400 -8.400
+50313.00    -40.537 -8.782  -39.400 -8.400
+50314.00    -40.479 -8.808  -39.500 -8.400
+50315.00    -40.559 -8.782  -39.800 -8.500
+50316.00    -40.933 -8.773  -40.100 -8.700
+50317.00    -41.481 -8.794  -40.200 -8.800
+50318.00    -41.919 -8.842  -40.300 -9.000
+50319.00    -42.099 -8.937  -40.500 -9.100
+50320.00    -42.109 -9.062  -40.700 -9.200
+50321.00    -42.127 -9.102  -41.000 -9.100
+50322.00    -42.204 -8.971  -41.300 -9.100
+50323.00    -42.215 -8.755  -41.600 -8.900
+50324.00    -42.082 -8.621  -41.900 -8.700
+50325.00    -41.825 -8.648  -42.100 -8.500
+50326.00    -41.71  -8.67   -42.200 -8.300
+50327.00    -41.977 -8.489  -42.200 -8.100
+50328.00    -42.43  -8.184  -42.200 -8.000
+50329.00    -42.608 -8.023  -42.100 -8.100
+50330.00    -42.366 -8.154  -42.000 -8.100
+50331.00    -42.104 -8.47   -41.700 -8.300
+50332.00    -42.107 -8.807  -41.700 -8.500
+50333.00    -42.159 -8.926  -41.700 -8.600
+50334.00    -42.023 -8.902  -41.600 -8.800
+50335.00    -41.746 -8.853  -41.600 -8.700
+50336.00    -41.537 -8.756  -41.600 -8.700
+50337.00    -41.497 -8.62   -41.700 -8.600
+50338.00    -41.534 -8.506  -41.700 -8.400
+50339.00    -41.571 -8.43   -41.800 -8.300
+50340.00    -41.639 -8.378  -41.900 -8.200
+50341.00    -41.718 -8.343  -41.900 -8.200
+50342.00    -41.709 -8.328  -41.800 -8.200
+50343.00    -41.606 -8.354  -41.800 -8.200
+50344.00    -41.559 -8.432  -41.600 -8.400
+50345.00    -41.688 -8.488  -41.200 -8.500
+50346.00    -41.923 -8.491  -41.000 -8.500
+50347.00    -42.12  -8.456  -40.700 -8.600
+50348.00    -42.21  -8.452  -40.700 -8.500
+50349.00    -42.221 -8.439  -40.700 -8.500
+50350.00    -42.204 -8.344  -41.000 -8.400
+50351.00    -42.146 -8.206  -41.300 -8.200
+50352.00    -42.005 -8.075  -41.700 -8.100
+50353.00    -41.738 -8.036  -42.100 -7.900
+50354.00    -41.488 -8.011  -42.300 -7.700
+50355.00    -41.48  -7.819  -42.300 -7.600
+50356.00    -41.709 -7.466  -42.200 -7.400
+50357.00    -41.89  -7.213  -41.900 -7.400
+50358.00    -41.789 -7.323  -41.500 -7.500
+50359.00    -41.471 -7.677  -41.000 -7.600
+50360.00    -41.054 -8.029  -40.700 -7.800
+50361.00    -40.668 -8.307  -40.300 -8.100
+50362.00    -40.416 -8.47   -40.000 -8.300
+50363.00    -40.347 -8.503  -39.900 -8.400
+50364.00    -40.475 -8.431  -39.900 -8.300
+50365.00    -40.692 -8.256  -40.100 -8.200
+50366.00    -40.814 -7.997  -40.300 -8.000
+50367.00    -40.798 -7.678  -40.500 -7.800
+50368.00    -40.751 -7.368  -40.500 -7.500
+50369.00    -40.738 -7.164  -40.500 -7.300
+50370.00    -40.669 -7.141  -40.400 -7.200
+50371.00    -40.444 -7.256  -40.200 -7.100
+50372.00    -40.135 -7.379  -39.800 -7.100
+50373.00    -39.988 -7.476  -39.400 -7.200
+50374.00    -40.099 -7.516  -39.100 -7.300
+50375.00    -40.282 -7.501  -38.900 -7.400
+50376.00    -40.347 -7.413  -38.800 -7.300
+50377.00    -40.237 -7.237  -38.700 -7.300
+50378.00    -40.009 -7.016  -38.800 -7.200
+50379.00    -39.77  -6.84   -39.000 -6.900
+50380.00    -39.617 -6.724  -39.100 -6.700
+50381.00    -39.515 -6.738  -39.300 -6.500
+50382.00    -39.402 -6.863  -39.400 -6.400
+50383.00    -39.287 -6.935  -39.500 -6.300
+50384.00    -39.198 -6.828  -39.300 -6.300
+50385.00    -39.11  -6.614  -39.000 -6.400
+50386.00    -38.94  -6.509  -38.600 -6.500
+50387.00    -38.613 -6.647  -38.200 -6.600
+50388.00    -38.142 -6.945  -37.700 -6.700
+50389.00    -37.631 -7.213  -37.300 -6.800
+50390.00    -37.232 -7.315  -37.000 -7.000
+50391.00    -37.058 -7.226  -36.800 -7.100
+50392.00    -37.116 -7.019  -36.700 -7.000
+50393.00    -37.305 -6.899  -36.800 -7.000
+50394.00    -37.469 -6.823  -36.900 -7.000
+50395.00    -37.495 -6.638  -37.000 -6.900
+50396.00    -37.514 -6.265  -37.100 -6.800
+50397.00    -37.607 -5.87   -37.200 -6.700
+50398.00    -37.67  -5.722  -37.100 -6.700
+50399.00    -37.586 -5.928  -37.000 -6.700
+50400.00    -37.337 -6.343  -36.800 -6.600
+50401.00    -37.116 -6.538  -36.600 -6.600
+50402.00    -37.000 -6.398  -36.300 -6.500
+50403.00    -37.006 -6.1    -36.200 -6.400
+50404.00    -37.069 -5.847  -36.200 -6.100
+50405.00    -37.076 -5.711  -36.300 -6.000
+50406.00    -37.013 -5.659  -36.500 -5.800
+50407.00    -36.968 -5.653  -36.700 -5.600
+50408.00    -37.042 -5.707  -36.900 -5.400
+50409.00    -37.352 -5.838  -37.000 -5.300
+50410.00    -37.89  -6.207  -37.000 -5.200
+50411.00    -38.389 -6.721  -36.800 -5.300
+50412.00    -38.547 -7.006  -36.400 -5.300
+50413.00    -38.213 -6.785  -35.900 -5.300
+50414.00    -37.349 -6.024  -35.400 -5.400
+50415.00    -36.506 -5.425  -34.800 -5.500
+50416.00    -35.843 -5.25   -34.300 -5.700
+50417.00    -35.312 -5.33   -34.000 -5.800
+50418.00    -35.002 -5.499  -33.700 -5.900
+50419.00    -34.933 -5.663  -33.700 -6.000
+50420.00    -34.965 -5.79   -33.800 -6.000
+50421.00    -34.992 -5.849  -34.000 -6.000
+50422.00    -35.211 -5.693  -34.400 -6.000
+50423.00    -35.635 -5.341  -34.700 -5.900
+50424.00    -35.977 -4.941  -35.100 -5.800
+50425.00    -36.008 -4.632  -35.300 -5.700
+50426.00    -35.762 -4.574  -35.300 -5.700
+50427.00    -35.447 -4.849  -35.200 -5.600
+50428.00    -35.251 -5.289  -35.000 -5.500
+50429.00    -35.188 -5.548  -34.700 -5.500
+50430.00    -35.216 -5.447  -34.500 -5.400
+50431.00    -35.316 -5.104  -34.300 -5.300
+50432.00    -35.447 -4.768  -34.300 -5.100
+50433.00    -35.548 -4.59   -34.400 -5.000
+50434.00    -35.597 -4.559  -34.700 -4.900
+50435.00    -35.631 -4.607  -35.100 -4.800
+50436.00    -35.708 -4.704  -35.500 -4.700
+50437.00    -35.843 -4.837  -35.900 -4.700
+50438.00    -35.975 -4.973  -36.200 -4.600
+50439.00    -35.988 -5.054  -36.300 -4.700
+50440.00    -35.829 -5.042  -36.100 -4.700
+50441.00    -35.594 -4.967  -35.800 -4.800
+50442.00    -35.436 -4.904  -35.400 -4.800
+50443.00    -35.367 -4.907  -34.900 -4.900
+50444.00    -35.263 -4.967  -34.400 -4.900
+50445.00    -35.073 -5.038  -34.100 -4.800
+50446.00    -34.891 -5.087  -33.900 -4.900
+50447.00    -34.767 -5.091  -33.900 -5.000
+50448.00    -34.607 -5.044  -34.000 -5.000
+50449.00    -34.381 -4.984  -34.400 -5.000
+50450.00    -34.279 -4.977  -34.600 -4.900
+50451.00    -34.45  -5.015  -34.900 -4.900
+50452.00    -34.718 -4.984  -35.100 -5.000
+50453.00    -34.77  -4.808  -35.100 -5.000
+50454.00    -34.58  -4.61   -35.000 -5.000
+50455.00    -34.425 -4.619  -34.800 -5.000
+50456.00    -34.505 -4.87   -34.500 -4.900
+50457.00    -34.731 -5.121  -34.300 -4.900
+50458.00    -34.874 -5.094  -34.100 -4.700
+50459.00    -34.878 -4.806  -33.900 -4.600
+50460.00    -34.848 -4.504  -34.000 -4.600
+50461.00    -34.887 -4.366  -34.200 -4.400
+50462.00    -35.03  -4.371  -34.700 -4.500
+50463.00    -35.228 -4.443  -35.100 -4.500
+50464.00    -35.36  -4.572  -35.500 -4.500
+50465.00    -35.345 -4.767  -35.900 -4.600
+50466.00    -35.228 -4.96   -36.000 -4.600
+50467.00    -35.108 -5.052  -36.000 -4.800
+50468.00    -35.019 -5.031  -35.700 -4.900
+50469.00    -34.944 -4.987  -35.400 -4.900
+50470.00    -34.909 -5.005  -34.800 -5.000
+50471.00    -34.952 -5.08   -34.300 -5.000
+50472.00    -34.969 -5.153  -33.800 -5.100
+50473.00    -34.899 -5.216  -33.400 -5.100
+50474.00    -34.808 -5.307  -33.300 -5.200
+50475.00    -34.755 -5.425  -33.400 -5.300
+50476.00    -34.704 -5.513  -33.700 -5.400
+50477.00    -34.655 -5.554  -34.100 -5.500
+50478.00    -34.763 -5.622  -34.700 -5.600
+50479.00    -35.132 -5.764  -35.300 -5.600
+50480.00    -35.556 -5.875  -35.800 -5.700
+50481.00    -35.706 -5.791  -36.100 -5.700
+50482.00    -35.581 -5.537  -36.200 -5.700
+50483.00    -35.525 -5.36   -36.200 -5.600
+50484.00    -35.763 -5.423  -36.000 -5.500
+50485.00    -36.095 -5.534  -35.700 -5.400
+50486.00    -36.191 -5.494  -35.400 -5.200
+50487.00    -35.962 -5.348  -35.100 -5.200
+50488.00    -35.581 -5.255  -35.000 -5.100
+50489.00    -35.311 -5.312  -35.000 -5.100
+50490.00    -35.302 -5.428  -35.200 -5.200
+50491.00    -35.471 -5.471  -35.600 -5.300
+50492.00    -35.584 -5.462  -35.900 -5.400
+50493.00    -35.487 -5.565  -36.100 -5.600
+50494.00    -35.305 -5.819  -36.300 -5.700
+50495.00    -35.287 -6.058  -36.400 -5.800
+50496.00    -35.505 -6.179  -36.300 -6.000
+50497.00    -35.739 -6.232  -36.000 -6.100
+50498.00    -35.75  -6.277  -35.600 -6.200
+50499.00    -35.525 -6.279  -35.200 -6.200
+50500.00    -35.228 -6.218  -34.800 -6.300
+50501.00    -34.977 -6.173  -34.500 -6.400
+50502.00    -34.788 -6.245  -34.300 -6.400
+50503.00    -34.681 -6.45   -34.300 -6.500
+50504.00    -34.661 -6.689  -34.400 -6.700
+50505.00    -34.711 -6.868  -34.600 -6.800
+50506.00    -34.862 -7.007  -34.900 -6.900
+50507.00    -35.126 -7.176  -35.000 -7.000
+50508.00    -35.357 -7.34   -35.200 -7.200
+50509.00    -35.337 -7.364  -35.100 -7.300
+50510.00    -35.08  -7.214  -35.100 -7.200
+50511.00    -34.9   -7.053  -34.800 -7.200
+50512.00    -35.052 -7.057  -34.600 -7.100
+50513.00    -35.424 -7.189  -34.400 -7.000
+50514.00    -35.676 -7.254  -34.300 -6.800
+50515.00    -35.608 -7.179  -34.200 -6.700
+50516.00    -35.322 -7.099  -34.300 -6.700
+50517.00    -35.098 -7.134  -34.600 -6.800
+50518.00    -35.175 -7.215  -34.800 -6.900
+50519.00    -35.526 -7.215  -35.100 -7.100
+50520.00    -35.821 -7.181  -35.400 -7.300
+50521.00    -35.74  -7.281  -35.700 -7.600
+50522.00    -35.356 -7.561  -35.800 -7.800
+50523.00    -35.063 -7.881  -35.800 -8.000
+50524.00    -35.074 -8.085  -35.600 -8.100
+50525.00    -35.173 -8.15   -35.400 -8.100
+50526.00    -35.067 -8.134  -35.000 -8.000
+50527.00    -34.768 -8.117  -34.600 -7.800
+50528.00    -34.492 -8.026  -34.200 -7.800
+50529.00    -34.366 -7.875  -34.000 -7.700
+50530.00    -34.331 -7.79   -33.800 -7.700
+50531.00    -34.332 -7.831  -33.800 -7.700
+50532.00    -34.402 -7.949  -34.000 -7.800
+50533.00    -34.559 -8.07   -34.200 -8.000
+50534.00    -34.749 -8.162  -34.400 -8.200
+50535.00    -34.921 -8.255  -34.500 -8.300
+50536.00    -35.031 -8.35   -34.700 -8.500
+50537.00    -34.999 -8.398  -34.700 -8.600
+50538.00    -34.783 -8.379  -34.600 -8.600
+50539.00    -34.468 -8.361  -34.400 -8.500
+50540.00    -34.207 -8.419  -34.200 -8.400
+50541.00    -34.058 -8.522  -34.100 -8.300
+50542.00    -33.981 -8.529  -34.000 -8.100
+50543.00    -33.916 -8.416  -34.000 -8.100
+50544.00    -33.866 -8.336  -34.200 -8.200
+50545.00    -33.907 -8.419  -34.300 -8.200
+50546.00    -34.134 -8.601  -34.600 -8.400
+50547.00    -34.522 -8.7    -34.800 -8.500
+50548.00    -34.817 -8.675  -35.000 -8.700
+50549.00    -34.799 -8.67   -35.200 -8.900
+50550.00    -34.553 -8.825  -35.200 -9.100
+50551.00    -34.4   -9.111  -35.200 -9.200
+50552.00    -34.496 -9.379  -35.100 -9.300
+50553.00    -34.605 -9.516  -34.900 -9.300
+50554.00    -34.418 -9.494  -34.700 -9.300
+50555.00    -33.981 -9.32   -34.500 -9.100
+50556.00    -33.66  -9.081  -34.400 -9.000
+50557.00    -33.642 -8.863  -34.100 -8.900
+50558.00    -33.799 -8.727  -34.000 -8.800
+50559.00    -33.964 -8.693  -34.000 -8.700
+50560.00    -34.105 -8.741  -33.800 -8.700
+50561.00    -34.233 -8.856  -33.800 -8.700
+50562.00    -34.323 -9.017  -33.800 -8.900
+50563.00    -34.355 -9.186  -33.800 -9.000
+50564.00    -34.397 -9.3    -33.800 -9.100
+50565.00    -34.519 -9.323  -33.800 -9.200
+50566.00    -34.669 -9.28   -33.900 -9.300
+50567.00    -34.708 -9.228  -34.000 -9.300
+50568.00    -34.556 -9.186  -34.100 -9.200
+50569.00    -34.273 -9.11   -34.200 -9.100
+50570.00    -33.968 -8.955  -34.400 -9.000
+50571.00    -33.815 -8.747  -34.600 -8.900
+50572.00    -33.919 -8.616  -34.600 -8.900
+50573.00    -34.226 -8.691  -34.700 -8.900
+50574.00    -34.595 -8.937  -34.600 -9.000
+50575.00    -34.882 -9.159  -34.600 -9.200
+50576.00    -34.94  -9.207  -34.500 -9.300
+50577.00    -34.779 -9.127  -34.500 -9.500
+50578.00    -34.582 -9.09   -34.600 -9.700
+50579.00    -34.566 -9.201  -34.600 -9.800
+50580.00    -34.773 -9.406  -34.700 -9.800
+50581.00    -35.004 -9.58   -34.800 -9.800
+50582.00    -35.037 -9.646  -34.900 -9.700
+50583.00    -34.869 -9.605  -35.000 -9.500
+50584.00    -34.723 -9.498  -35.000 -9.300
+50585.00    -34.766 -9.369  -35.200 -9.100
+50586.00    -34.977 -9.233  -35.200 -8.900
+50587.00    -35.249 -9.077  -35.400 -8.900
+50588.00    -35.502 -8.914  -35.600 -8.800
+50589.00    -35.68  -8.828  -35.700 -8.800
+50590.00    -35.739 -8.904  -35.900 -9.000
+50591.00    -35.696 -9.106  -36.000 -9.100
+50592.00    -35.675 -9.283  -36.200 -9.100
+50593.00    -35.82  -9.309  -36.300 -9.100
+50594.00    -36.147 -9.202  -36.300 -9.100
+50595.00    -36.494 -9.088  -36.400 -9.000
+50596.00    -36.635 -9.06   -36.400 -8.800
+50597.00    -36.461 -9.109  -36.500 -8.700
+50598.00    -36.098 -9.146  -36.400 -8.500
+50599.00    -35.84  -9.106  -36.500 -8.500
+50600.00    -35.945 -9.018  -36.700 -8.400
+50601.00    -36.426 -8.965  -36.800 -8.400
+50602.00    -37.021 -8.971  -36.900 -8.400
+50603.00    -37.381 -8.954  -37.000 -8.600
+50604.00    -37.331 -8.885  -36.900 -8.600
+50605.00    -37.001 -8.751  -36.800 -8.700
+50606.00    -36.68  -8.626  -36.600 -8.800
+50607.00    -36.563 -8.615  -36.600 -8.900
+50608.00    -36.649 -8.724  -36.500 -8.900
+50609.00    -36.832 -8.869  -36.600 -8.900
+50610.00    -37.022 -8.965  -36.800 -8.800
+50611.00    -37.171 -8.983  -37.100 -8.800
+50612.00    -37.269 -8.943  -37.600 -8.600
+50613.00    -37.401 -8.877  -37.900 -8.500
+50614.00    -37.713 -8.789  -38.300 -8.300
+50615.00    -38.254 -8.66   -38.600 -8.200
+50616.00    -38.847 -8.493  -38.800 -8.200
+50617.00    -39.225 -8.376  -38.900 -8.200
+50618.00    -39.279 -8.393  -38.900 -8.200
+50619.00    -39.131 -8.572  -38.800 -8.300
+50620.00    -38.983 -8.777  -38.700 -8.300
+50621.00    -38.971 -8.793  -38.700 -8.200
+50622.00    -39.142 -8.558  -38.800 -8.200
+50623.00    -39.47  -8.23   -39.000 -8.100
+50624.00    -39.836 -8.028  -39.400 -7.900
+50625.00    -40.063 -8.04   -39.800 -7.800
+50626.00    -40.048 -8.189  -40.300 -7.800
+50627.00    -39.896 -8.344  -40.700 -7.800
+50628.00    -39.879 -8.442  -41.100 -8.000
+50629.00    -40.213 -8.514  -41.200 -8.100
+50630.00    -40.843 -8.615  -41.200 -8.200
+50631.00    -41.454 -8.756  -41.200 -8.500
+50632.00    -41.739 -8.881  -41.100 -8.600
+50633.00    -41.681 -8.937  -41.000 -8.700
+50634.00    -41.507 -8.914  -40.900 -8.800
+50635.00    -41.429 -8.843  -40.900 -8.400
+50636.00    -41.502 -8.758  -41.000 -8.400
+50637.00    -41.723 -8.697  -41.300 -8.400
+50638.00    -42.093 -8.706  -41.800 -8.500
+50639.00    -42.5   -8.795  -42.300 -8.700
+50640.00    -42.623 -8.87   -42.900 -8.900
+50641.00    -42.452 -8.876  -43.400 -9.000
+50642.00    -42.384 -8.829  -43.700 -9.100
+50643.00    -42.759 -8.755  -44.000 -9.100
+50644.00    -43.473 -8.658  -44.100 -9.000
+50645.00    -44.093 -8.558  -44.000 -8.900
+50646.00    -44.273 -8.484  -43.900 -8.800
+50647.00    -44.177 -8.552  -43.700 -8.700
+50648.00    -44.12  -8.742  -43.600 -8.600
+50649.00    -44.182 -8.836  -43.500 -8.400
+50650.00    -44.278 -8.661  -43.600 -8.100
+50651.00    -44.372 -8.299  -43.800 -8.000
+50652.00    -44.489 -7.986  -44.100 -7.900
+50653.00    -44.602 -7.865  -44.700 -7.900
+50654.00    -44.75  -7.94   -45.100 -8.000
+50655.00    -44.868 -8.105  -45.600 -8.100
+50656.00    -44.921 -8.291  -45.900 -8.400
+50657.00    -45.04  -8.493  -46.000 -8.600
+50658.00    -45.376 -8.698  -45.900 -8.800
+50659.00    -45.887 -8.873  -45.700 -8.900
+50660.00    -46.307 -9.000  -45.400 -9.000
+50661.00    -46.412 -9.089  -45.000 -9.000
+50662.00    -46.22  -9.118  -44.700 -8.800
+50663.00    -45.914 -9.024  -44.600 -8.700
+50664.00    -45.657 -8.792  -44.700 -8.600
+50665.00    -45.547 -8.534  -45.000 -8.300
+50666.00    -45.628 -8.427  -45.300 -8.300
+50667.00    -45.837 -8.524  -45.800 -8.400
+50668.00    -45.947 -8.72   -46.300 -8.500
+50669.00    -45.881 -8.87   -46.600 -8.600
+50670.00    -45.936 -8.931  -46.900 -8.700
+50671.00    -46.45  -8.946  -47.100 -8.600
+50672.00    -47.283 -8.912  -47.200 -8.600
+50673.00    -47.883 -8.784  -47.200 -8.500
+50674.00    -47.935 -8.623  -47.100 -8.400
+50675.00    -47.688 -8.592  -47.200 -8.300
+50676.00    -47.577 -8.76   -47.200 -8.300
+50677.00    -47.732 -8.968  -47.200 -8.300
+50678.00    -47.978 -8.989  -47.400 -8.300
+50679.00    -48.167 -8.786  -47.700 -8.400
+50680.00    -48.355 -8.502  -48.000 -8.500
+50681.00    -48.686 -8.226  -48.300 -8.500
+50682.00    -49.146 -8.005  -48.600 -8.500
+50683.00    -49.556 -7.831  -48.700 -8.500
+50684.00    -49.654 -7.781  -48.600 -8.400
+50685.00    -49.313 -7.978  -48.400 -8.500
+50686.00    -48.751 -8.393  -47.900 -8.500
+50687.00    -48.336 -8.85   -47.400 -8.600
+50688.00    -48.213 -9.148  -46.700 -8.600
+50689.00    -48.164 -9.285  -46.200 -8.700
+50690.00    -47.964 -9.314  -45.700 -8.700
+50691.00    -47.662 -9.193  -45.500 -8.500
+50692.00    -47.462 -8.877  -45.500 -8.500
+50693.00    -47.492 -8.473  -45.800 -8.400
+50694.00    -47.751 -8.201  -46.500 -8.300
+50695.00    -48.12  -8.192  -47.100 -8.300
+50696.00    -48.315 -8.349  -47.900 -8.200
+50697.00    -48.217 -8.481  -48.500 -8.300
+50698.00    -48.043 -8.514  -49.000 -8.200
+50699.00    -48.124 -8.512  -49.200 -8.200
+50700.00    -48.493 -8.521  -49.200 -8.400
+50701.00    -48.809 -8.492  -48.900 -8.400
+50702.00    -48.779 -8.397  -48.500 -8.400
+50703.00    -48.508 -8.319  -48.000 -8.400
+50704.00    -48.333 -8.347  -47.600 -8.300
+50705.00    -48.407 -8.418  -47.300 -8.300
+50706.00    -48.587 -8.382  -47.200 -8.100
+50707.00    -48.653 -8.215  -47.300 -8.000
+50708.00    -48.544 -8.038  -47.600 -8.000
+50709.00    -48.435 -7.928  -48.000 -7.900
+50710.00    -48.57  -7.763  -48.300 -7.900
+50711.00    -48.985 -7.455  -48.500 -7.900
+50712.00    -49.361 -7.175  -48.600 -7.900
+50713.00    -49.293 -7.201  -48.500 -8.100
+50714.00    -48.763 -7.58   -48.200 -8.100
+50715.00    -48.192 -8.065  -47.700 -8.100
+50716.00    -47.921 -8.404  -47.200 -8.200
+50717.00    -47.835 -8.55   -46.700 -8.100
+50718.00    -47.628 -8.589  -46.300 -8.000
+50719.00    -47.248 -8.553  -46.100 -7.900
+50720.00    -46.903 -8.401  -46.100 -7.800
+50721.00    -46.737 -8.154  -46.300 -7.700
+50722.00    -46.719 -7.924  -46.500 -7.700
+50723.00    -46.774 -7.794  -47.000 -7.600
+50724.00    -46.842 -7.74   -47.400 -7.600
+50725.00    -46.861 -7.668  -47.600 -7.600
+50726.00    -46.822 -7.544  -47.700 -7.700
+50727.00    -46.825 -7.43   -47.600 -7.600
+50728.00    -46.942 -7.398  -47.400 -7.600
+50729.00    -47.072 -7.443  -47.000 -7.500
+50730.00    -47.075 -7.459  -46.700 -7.400
+50731.00    -46.915 -7.42   -46.300 -7.200
+50732.00    -46.705 -7.356  -46.100 -6.900
+50733.00    -46.585 -7.242  -45.900 -6.800
+50734.00    -46.587 -7.041  -46.100 -6.700
+50735.00    -46.63  -6.818  -46.400 -6.600
+50736.00    -46.608 -6.732  -46.700 -6.700
+50737.00    -46.513 -6.824  -47.200 -6.700
+50738.00    -46.494 -6.907  -47.400 -6.900
+50739.00    -46.687 -6.789  -47.600 -7.000
+50740.00    -46.951 -6.552  -47.500 -7.000
+50741.00    -46.924 -6.497  -47.200 -7.200
+50742.00    -46.449 -6.781  -46.700 -7.200
+50743.00    -45.796 -7.228  -46.000 -7.100
+50744.00    -45.361 -7.559  -45.300 -7.000
+50745.00    -45.163 -7.637  -44.600 -6.900
+50746.00    -44.955 -7.529  -44.100 -6.800
+50747.00    -44.661 -7.347  -43.800 -6.600
+50748.00    -44.45  -7.124  -43.900 -6.500
+50749.00    -44.442 -6.847  -44.000 -6.400
+50750.00    -44.579 -6.528  -44.400 -6.400
+50751.00    -44.793 -6.227  -44.900 -6.400
+50752.00    -45.044 -6.085  -45.300 -6.500
+50753.00    -45.234 -6.067  -45.500 -6.500
+50754.00    -45.248 -6.117  -45.700 -6.700
+50755.00    -45.061 -6.203  -45.500 -6.700
+50756.00    -44.809 -6.281  -45.200 -6.600
+50757.00    -44.657 -6.329  -44.800 -6.500
+50758.00    -44.621 -6.355  -44.400 -6.300
+50759.00    -44.564 -6.363  -43.900 -6.100
+50760.00    -44.381 -6.318  -43.600 -5.900
+50761.00    -44.109 -6.162  -43.400 -5.700
+50762.00    -43.886 -5.878  -43.400 -5.500
+50763.00    -43.815 -5.559  -43.400 -5.500
+50764.00    -43.858 -5.363  -43.600 -5.400
+50765.00    -43.885 -5.357  -43.900 -5.400
+50766.00    -43.872 -5.503  -44.000 -5.500
+50767.00    -43.864 -5.592  -44.100 -5.600
+50768.00    -43.844 -5.507  -44.000 -5.700
+50769.00    -43.683 -5.404  -43.800 -5.700
+50770.00    -43.276 -5.471  -43.300 -5.700
+50771.00    -42.698 -5.7    -42.800 -5.700
+50772.00    -42.119 -5.99   -42.300 -5.600
+50773.00    -41.701 -6.141  -41.800 -5.400
+50774.00    -41.511 -6.071  -41.400 -5.300
+50775.00    -41.492 -5.886  -41.400 -5.200
+50776.00    -41.639 -5.687  -41.500 -5.200
+50777.00    -41.9   -5.487  -41.800 -5.200
+50778.00    -42.131 -5.255  -42.200 -5.200
+50779.00    -42.271 -5.001  -42.600 -5.400
+50780.00    -42.382 -4.787  -43.000 -5.400
+50781.00    -42.49  -4.714  -43.300 -5.400
+50782.00    -42.496 -4.83   -43.300 -5.500
+50783.00    -42.322 -5.038  -43.100 -5.400
+50784.00    -42.08  -5.155  -42.700 -5.300
+50785.00    -42.006 -5.068  -42.200 -5.100
+50786.00    -42.23  -4.811  -41.700 -4.900
+50787.00    -42.618 -4.511  -41.300 -4.700
+50788.00    -42.925 -4.247  -41.000 -4.400
+50789.00    -43.016 -4.024  -41.000 -4.200
+50790.00    -42.932 -3.85   -41.000 -4.100
+50791.00    -42.783 -3.813  -41.300 -4.000
+50792.00    -42.626 -4.029  -41.500 -4.000
+50793.00    -42.6   -4.398  -41.900 -4.100
+50794.00    -42.606 -4.778  -42.100 -4.100
+50795.00    -42.494 -4.99   -42.200 -4.300
+50796.00    -42.261 -4.916  -42.200 -4.400
+50797.00    -41.983 -4.655  -42.000 -4.400
+50798.00    -41.722 -4.447  -41.800 -4.400
+50799.00    -41.476 -4.454  -41.500 -4.400
+50800.00    -41.221 -4.656  -41.200 -4.400
+50801.00    -40.967 -4.871  -41.000 -4.200
+50802.00    -40.779 -4.977  -40.900 -4.200
+50803.00    -40.73  -4.984  -40.900 -4.100
+50804.00    -40.851 -4.928  -41.000 -4.100
+50805.00    -41.124 -4.778  -41.300 -4.100
+50806.00    -41.502 -4.467  -41.600 -4.200
+50807.00    -41.843 -4.114  -41.800 -4.400
+50808.00    -42.089 -3.801  -42.100 -4.500
+50809.00    -42.204 -3.644  -42.200 -4.500
+50810.00    -42.139 -3.756  -42.200 -4.600
+50811.00    -41.895 -4.09   -42.000 -4.500
+50812.00    -41.541 -4.423  -41.800 -4.500
+50813.00    -41.195 -4.529  -41.500 -4.400
+50814.00    -40.962 -4.383  -40.900 -4.300
+50815.00    -40.873 -4.154  -40.700 -4.200
+50816.00    -40.872 -4.018  -40.500 -4.200
+50817.00    -40.876 -4.01   -40.400 -4.100
+50818.00    -40.869 -4.068  -40.500 -4.100
+50819.00    -40.929 -4.136  -40.600 -4.100
+50820.00    -41.141 -4.226  -40.800 -4.300
+50821.00    -41.482 -4.375  -41.200 -4.300
+50822.00    -41.8   -4.566  -41.500 -4.300
+50823.00    -41.925 -4.7    -41.700 -4.400
+50824.00    -41.828 -4.677  -41.700 -4.300
+50825.00    -41.652 -4.508  -41.700 -4.300
+50826.00    -41.555 -4.315  -41.600 -4.200
+50827.00    -41.53  -4.216  -41.300 -4.100
+50828.00    -41.436 -4.261  -41.100 -4.000
+50829.00    -41.243 -4.363  -41.000 -3.900
+50830.00    -41.092 -4.439  -41.000 -3.900
+50831.00    -41.102 -4.498  -41.000 -4.100
+50832.00    -41.23  -4.579  -41.100 -4.300
+50833.00    -41.383 -4.688  -41.200 -4.500
+50834.00    -41.575 -4.776  -41.400 -4.700
+50835.00    -41.846 -4.761  -41.500 -4.900
+50836.00    -42.097 -4.6    -41.600 -5.000
+50837.00    -42.179 -4.367  -41.600 -5.100
+50838.00    -42.109 -4.251  -41.500 -5.100
+50839.00    -42.024 -4.396  -41.600 -5.100
+50840.00    -41.932 -4.717  -41.600 -5.000
+50841.00    -41.669 -4.952  -41.700 -4.900
+50842.00    -41.232 -4.896  -41.700 -4.600
+50843.00    -40.858 -4.609  -41.800 -4.500
+50844.00    -40.815 -4.312  -41.900 -4.300
+50845.00    -41.1   -4.186  -41.800 -4.300
+50846.00    -41.504 -4.23   -41.800 -4.200
+50847.00    -41.792 -4.374  -41.800 -4.300
+50848.00    -41.848 -4.585  -41.700 -4.500
+50849.00    -41.771 -4.78   -41.700 -4.700
+50850.00    -41.668 -4.94   -41.600 -4.800
+50851.00    -41.528 -5.048  -41.500 -5.000
+50852.00    -41.311 -5.089  -41.400 -5.100
+50853.00    -41.075 -5.1    -41.300 -5.200
+50854.00    -40.931 -5.144  -41.200 -5.300
+50855.00    -40.897 -5.254  -41.100 -5.200
+50856.00    -40.867 -5.403  -41.100 -5.300
+50857.00    -40.806 -5.533  -41.100 -5.300
+50858.00    -40.836 -5.62   -41.100 -5.200
+50859.00    -41.044 -5.694  -41.200 -5.300
+50860.00    -41.337 -5.766  -41.300 -5.300
+50861.00    -41.576 -5.835  -41.400 -5.600
+50862.00    -41.767 -5.9    -41.600 -5.700
+50863.00    -41.95  -5.932  -41.800 -5.900
+50864.00    -41.988 -5.839  -41.900 -6.200
+50865.00    -41.714 -5.577  -41.800 -6.400
+50866.00    -41.28  -5.296  -41.800 -6.500
+50867.00    -41.081 -5.276  -41.700 -6.400
+50868.00    -41.243 -5.624  -41.400 -6.300
+50869.00    -41.415 -6.106  -41.300 -6.200
+50870.00    -41.196 -6.323  -41.200 -6.000
+50871.00    -40.664 -6.183  -41.300 -5.800
+50872.00    -40.261 -5.936  -41.200 -5.800
+50873.00    -40.292 -5.822  -41.300 -5.700
+50874.00    -40.673 -5.862  -41.300 -5.800
+50875.00    -41.088 -5.956  -41.300 -5.900
+50876.00    -41.276 -6.067  -41.200 -6.100
+50877.00    -41.195 -6.227  -41.200 -6.300
+50878.00    -41.001 -6.417  -41.000 -6.500
+50879.00    -40.864 -6.56   -40.700 -6.700
+50880.00    -40.799 -6.628  -40.500 -6.800
+50881.00    -40.701 -6.676  -40.300 -6.800
+50882.00    -40.53  -6.748  -40.100 -6.800
+50883.00    -40.36  -6.807  -40.100 -6.700
+50884.00    -40.252 -6.791  -40.200 -6.600
+50885.00    -40.181 -6.707  -40.400 -6.500
+50886.00    -40.158 -6.655  -40.500 -6.500
+50887.00    -40.221 -6.703  -40.600 -6.500
+50888.00    -40.319 -6.811  -40.700 -6.600
+50889.00    -40.378 -6.915  -40.600 -6.800
+50890.00    -40.443 -7.026  -40.400 -7.000
+50891.00    -40.573 -7.176  -40.200 -7.100
+50892.00    -40.611 -7.293  -39.900 -7.300
+50893.00    -40.309 -7.236  -39.700 -7.400
+50894.00    -39.756 -7.022  -39.500 -7.400
+50895.00    -39.397 -6.895  -39.500 -7.400
+50896.00    -39.491 -7.066  -39.600 -7.300
+50897.00    -39.743 -7.426  -39.800 -7.300
+50898.00    -39.699 -7.644  -39.900 -7.200
+50899.00    -39.35  -7.571  -40.100 -7.100
+50900.00    -39.095 -7.379  -40.300 -7.100
+50901.00    -39.277 -7.307  -40.400 -7.100
+50902.00    -39.84  -7.389  -40.400 -7.300
+50903.00    -40.383 -7.53   -40.300 -7.500
+50904.00    -40.478 -7.721  -40.100 -7.700
+50905.00    -40.005 -8.04   -39.900 -8.000
+50906.00    -39.385 -8.425  -39.700 -8.200
+50907.00    -39.175 -8.682  -39.500 -8.300
+50908.00    -39.426 -8.722  -39.300 -8.300
+50909.00    -39.763 -8.616  -39.300 -8.300
+50910.00    -39.82  -8.467  -39.400 -8.300
+50911.00    -39.588 -8.277  -39.500 -8.100
+50912.00    -39.282 -8.007  -39.600 -8.000
+50913.00    -39.061 -7.717  -39.700 -7.900
+50914.00    -38.94  -7.557  -39.900 -7.800
+50915.00    -38.906 -7.612  -39.900 -7.800
+50916.00    -38.984 -7.808  -39.900 -7.800
+50917.00    -39.226 -8.019  -39.800 -8.000
+50918.00    -39.68  -8.204  -39.600 -8.100
+50919.00    -40.211 -8.376  -39.200 -8.300
+50920.00    -40.64  -8.529  -38.900 -8.400
+50921.00    -40.732 -8.569  -38.600 -8.500
+50922.00    -40.401 -8.438  -38.500 -8.500
+50923.00    -39.886 -8.255  -38.400 -8.500
+50924.00    -39.482 -8.204  -38.500 -8.400
+50925.00    -39.217 -8.3    -38.800 -8.300
+50926.00    -39.031 -8.347  -39.200 -8.100
+50927.00    -38.874 -8.235  -39.600 -8.100
+50928.00    -38.863 -8.093  -39.900 -8.000
+50929.00    -39.145 -8.093  -40.200 -8.000
+50930.00    -39.657 -8.207  -40.200 -8.100
+50931.00    -40.104 -8.288  -40.200 -8.200
+50932.00    -40.145 -8.321  -40.000 -8.400
+50933.00    -39.678 -8.452  -39.900 -8.500
+50934.00    -39.036 -8.741  -39.600 -8.700
+50935.00    -38.752 -9.045  -39.400 -8.800
+50936.00    -39.008 -9.187  -39.400 -8.900
+50937.00    -39.441 -9.146  -39.400 -8.800
+50938.00    -39.601 -9.007  -39.500 -8.700
+50939.00    -39.484 -8.819  -39.600 -8.600
+50940.00    -39.383 -8.633  -39.800 -8.500
+50941.00    -39.509 -8.437  -40.100 -8.400
+50942.00    -39.774 -8.301  -40.200 -8.400
+50943.00    -39.995 -8.307  -40.300 -8.400
+50944.00    -40.117 -8.424  -40.200 -8.400
+50945.00    -40.162 -8.554  -40.000 -8.600
+50946.00    -40.147 -8.644  -39.800 -8.700
+50947.00    -40.133 -8.716  -39.400 -8.700
+50948.00    -40.186 -8.797  -39.100 -8.700
+50949.00    -40.257 -8.86   -38.700 -8.700
+50950.00    -40.187 -8.854  -38.600 -8.700
+50951.00    -39.9   -8.767  -38.700 -8.600
+50952.00    -39.516 -8.63   -38.900 -8.500
+50953.00    -39.247 -8.461  -39.300 -8.300
+50954.00    -39.244 -8.261  -39.800 -8.200
+50955.00    -39.54  -8.064  -40.300 -8.100
+50956.00    -40.078 -8.007  -40.800 -8.100
+50957.00    -40.715 -8.186  -41.100 -8.100
+50958.00    -41.26  -8.483  -41.200 -8.300
+50959.00    -41.535 -8.665  -41.200 -8.400
+50960.00    -41.425 -8.644  -41.100 -8.500
+50961.00    -40.965 -8.568  -40.900 -8.600
+50962.00    -40.441 -8.616  -40.600 -8.700
+50963.00    -40.264 -8.772  -40.500 -8.800
+50964.00    -40.588 -8.883  -40.400 -8.900
+50965.00    -41.107 -8.865  -40.400 -8.800
+50966.00    -41.375 -8.773  -40.700 -8.800
+50967.00    -41.311 -8.683  -41.000 -8.700
+50968.00    -41.222 -8.594  -41.500 -8.700
+50969.00    -41.36  -8.47   -41.800 -8.500
+50970.00    -41.667 -8.319  -42.200 -8.400
+50971.00    -41.952 -8.19   -42.300 -8.400
+50972.00    -42.133 -8.127  -42.400 -8.300
+50973.00    -42.198 -8.147  -42.200 -8.200
+50974.00    -42.112 -8.23   -41.900 -8.200
+50975.00    -41.898 -8.318  -41.600 -8.100
+50976.00    -41.737 -8.358  -41.200 -8.100
+50977.00    -41.806 -8.341  -41.100 -8.000
+50978.00    -42.057 -8.306  -41.100 -7.900
+50979.00    -42.265 -8.274  -41.300 -7.900
+50980.00    -42.306 -8.214  -41.700 -7.900
+50981.00    -42.294 -8.064  -42.200 -7.800
+50982.00    -42.385 -7.755  -42.900 -7.800
+50983.00    -42.737 -7.381  -43.500 -7.900
+50984.00    -43.376 -7.149  -44.000 -8.000
+50985.00    -44.109 -7.2    -44.500 -8.000
+50986.00    -44.651 -7.494  -44.700 -8.200
+50987.00    -44.835 -7.869  -44.800 -8.300
+50988.00    -44.696 -8.192  -44.600 -8.400
+50989.00    -44.427 -8.36   -44.400 -8.500
+50990.00    -44.265 -8.489  -44.100 -8.600
+50991.00    -44.404 -8.676  -44.000 -8.700
+50992.00    -44.877 -8.839  -44.000 -8.800
+50993.00    -45.473 -8.861  -44.100 -8.800
+50994.00    -45.877 -8.727  -44.400 -8.700
+50995.00    -45.942 -8.503  -44.800 -8.700
+50996.00    -45.929 -8.285  -45.200 -8.400
+50997.00    -45.994 -8.101  -45.700 -8.200
+50998.00    -46.149 -7.903  -46.000 -8.000
+50999.00    -46.368 -7.676  -46.300 -7.800
+51000.00    -46.595 -7.491  -46.900 -7.800
+51001.00    -46.748 -7.448  -46.900 -7.700
+51002.00    -46.743 -7.578  -46.600 -7.600
+51003.00    -46.598 -7.777  -46.400 -7.600
+51004.00    -46.477 -7.881  -46.200 -7.500
+51005.00    -46.574 -7.811  -46.100 -7.600
+51006.00    -46.925 -7.646  -46.100 -7.500
+51007.00    -47.361 -7.531  -46.300 -7.600
+51008.00    -47.653 -7.53   -46.600 -7.600
+51009.00    -47.72  -7.593  -47.100 -7.700
+51010.00    -47.69  -7.644  -47.600 -7.700
+51011.00    -47.745 -7.711  -48.200 -7.800
+51012.00    -48.045 -7.865  -48.700 -8.000
+51013.00    -48.57  -8.132  -49.200 -8.100
+51014.00    -49.098 -8.442  -49.500 -8.200
+51015.00    -49.392 -8.62   -49.500 -8.300
+51016.00    -49.39  -8.515  -49.500 -8.300
+51017.00    -49.144 -8.246  -49.200 -8.400
+51018.00    -48.871 -7.991  -48.900 -8.400
+51019.00    -48.771 -7.853  -48.700 -8.400
+51020.00    -48.896 -7.836  -48.700 -8.400
+51021.00    -49.207 -7.885  -48.900 -8.400
+51022.00    -49.631 -7.988  -49.400 -8.300
+51023.00    -50.038 -8.169  -50.100 -8.200
+51024.00    -50.28  -8.393  -51.000 -8.200
+51025.00    -50.344 -8.509  -51.800 -8.200
+51026.00    -50.405 -8.419  -52.400 -8.100
+51027.00    -50.653 -8.153  -52.600 -8.100
+51028.00    -51.055 -7.825  -52.500 -7.900
+51029.00    -51.373 -7.595  -52.000 -7.700
+51030.00    -51.435 -7.588  -51.300 -7.600
+51031.00    -51.304 -7.798  -50.900 -7.500
+51032.00    -51.165 -8.045  -50.600 -7.400
+51033.00    -51.134 -8.123  -50.500 -7.400
+51034.00    -51.238 -7.997  -50.400 -7.400
+51035.00    -51.474 -7.824  -50.700 -7.500
+51036.00    -51.813 -7.773  -51.100 -7.600
+51037.00    -52.172 -7.849  -51.700 -7.800
+51038.00    -52.47  -7.924  -52.400 -7.900
+51039.00    -52.696 -7.916  -53.000 -8.000
+51040.00    -52.929 -7.861  -53.400 -8.200
+51041.00    -53.235 -7.851  -53.600 -8.200
+51042.00    -53.541 -7.944  -53.600 -8.300
+51043.00    -53.635 -8.126  -53.300 -8.300
+51044.00    -53.354 -8.33   -52.900 -8.400
+51045.00    -52.848 -8.426  -52.400 -8.400
+51046.00    -52.357 -8.392  -52.100 -8.500
+51047.00    -52.053 -8.266  -51.800 -8.500
+51048.00    -51.975 -8.09   -51.700 -8.500
+51049.00    -52.093 -7.93   -51.800 -8.500
+51050.00    -52.36  -7.882  -52.200 -8.400
+51051.00    -52.646 -7.984  -52.500 -8.200
+51052.00    -52.766 -8.121  -52.900 -8.000
+51053.00    -52.6   -8.189  -53.200 -7.900
+51054.00    -52.391 -8.14   -53.500 -7.800
+51055.00    -52.5   -8.006  -53.600 -7.700
+51056.00    -52.913 -7.856  -53.500 -7.600
+51057.00    -53.253 -7.741  -53.300 -8.100
+51058.00    -53.27  -7.722  -53.100 -7.800
+51059.00    -53.117 -7.848  -52.900 -7.400
+51060.00    -53.06  -8.05   -52.800 -7.200
+51061.00    -53.119 -8.139  -52.700 -7.200
+51062.00    -53.159 -7.991  -52.700 -7.100
+51063.00    -53.169 -7.718  -52.900 -7.300
+51064.00    -53.291 -7.561  -53.200 -7.400
+51065.00    -53.597 -7.628  -53.500 -7.700
+51066.00    -53.976 -7.806  -53.900 -7.800
+51067.00    -54.241 -7.942  -54.200 -8.000
+51068.00    -54.286 -8.017  -54.300 -8.200
+51069.00    -54.155 -8.103  -54.400 -8.300
+51070.00    -53.982 -8.212  -54.200 -8.300
+51071.00    -53.857 -8.264  -53.900 -8.300
+51072.00    -53.728 -8.182  -53.600 -8.200
+51073.00    -53.494 -7.96   -53.400 -8.000
+51074.00    -53.178 -7.703  -53.200 -7.800
+51075.00    -52.92  -7.466  -53.000 -7.500
+51076.00    -52.815 -7.21   -52.900 -7.300
+51077.00    -52.853 -6.993  -52.900 -7.200
+51078.00    -52.965 -6.951  -52.800 -7.100
+51079.00    -53.02  -7.135  -52.900 -7.100
+51080.00    -52.833 -7.414  -53.000 -7.200
+51081.00    -52.371 -7.604  -53.100 -7.300
+51082.00    -51.923 -7.638  -53.100 -7.400
+51083.00    -51.872 -7.595  -53.100 -7.500
+51084.00    -52.222 -7.548  -53.100 -7.500
+51085.00    -52.567 -7.473  -52.800 -7.400
+51086.00    -52.603 -7.352  -52.500 -7.300
+51087.00    -52.453 -7.258  -52.100 -7.200
+51088.00    -52.389 -7.256  -51.600 -6.900
+51089.00    -52.397 -7.265  -51.300 -6.800
+51090.00    -52.287 -7.141  -51.000 -6.600
+51091.00    -52.014 -6.918  -51.000 -6.600
+51092.00    -51.778 -6.808  -51.100 -6.600
+51093.00    -51.803 -6.917  -51.300 -6.800
+51094.00    -52.125 -7.06   -51.700 -7.000
+51095.00    -52.567 -7.073  -52.000 -7.200
+51096.00    -52.863 -7.019  -52.100 -7.400
+51097.00    -52.836 -7.074  -52.200 -7.600
+51098.00    -52.544 -7.283  -52.200 -7.700
+51099.00    -52.205 -7.5    -51.900 -7.800
+51100.00    -51.932 -7.589  -51.700 -7.500
+51101.00    -51.698 -7.537  -51.300 -7.400
+51102.00    -51.366 -7.426  -51.100 -7.100
+51103.00    -50.973 -7.266  -50.800 -6.700
+51104.00    -50.694 -7.001  -50.700 -6.500
+51105.00    -50.59  -6.664  -50.600 -6.300
+51106.00    -50.562 -6.414  -50.500 -6.300
+51107.00    -50.471 -6.367  -50.500 -6.200
+51108.00    -50.226 -6.463  -50.500 -6.300
+51109.00    -49.858 -6.543  -50.500 -6.400
+51110.00    -49.542 -6.54   -50.600 -6.500
+51111.00    -49.513 -6.517  -50.600 -6.500
+51112.00    -49.786 -6.526  -50.500 -6.500
+51113.00    -50.066 -6.493  -50.400 -6.400
+51114.00    -50.074 -6.323  -50.100 -6.300
+51115.00    -49.866 -6.052  -49.700 -6.100
+51116.00    -49.718 -5.815  -49.200 -5.700
+51117.00    -49.732 -5.65   -48.800 -5.400
+51118.00    -49.763 -5.481  -48.600 -5.200
+51119.00    -49.695 -5.314  -48.500 -5.100
+51120.00    -49.557 -5.299  -48.800 -5.200
+51121.00    -49.432 -5.497  -48.900 -5.300
+51122.00    -49.428 -5.68   -49.100 -5.600
+51123.00    -49.549 -5.581  -49.200 -5.900
+51124.00    -49.636 -5.36   -49.200 -6.100
+51125.00    -49.512 -5.337  -49.200 -6.200
+51126.00    -49.208 -5.588  -49.100 -6.200
+51127.00    -48.999 -5.897  -49.000 -6.100
+51128.00    -49.097 -5.996  -48.900 -6.000
+51129.00    -49.362 -5.854  -48.800 -5.700
+51130.00    -49.45  -5.638  -48.700 -5.500
+51131.00    -49.255 -5.453  -48.600 -5.200
+51132.00    -48.998 -5.261  -48.500 -5.000
+51133.00    -48.866 -5.02   -48.400 -4.800
+51134.00    -48.796 -4.794  -48.300 -4.700
+51135.00    -48.669 -4.68   -48.200 -4.800
+51136.00    -48.483 -4.688  -48.200 -4.800
+51137.00    -48.271 -4.743  -48.000 -4.900
+51138.00    -48.057 -4.794  -47.900 -5.100
+51139.00    -47.909 -4.855  -47.900 -5.100
+51140.00    -47.9   -4.94   -47.800 -5.200
+51141.00    -47.984 -4.99   -47.800 -5.000
+51142.00    -48.015 -4.929  -47.800 -4.900
+51143.00    -47.909 -4.754  -47.900 -4.600
+51144.00    -47.717 -4.534  -48.000 -4.300
+51145.00    -47.529 -4.314  -48.200 -4.200
+51146.00    -47.408 -4.096  -48.300 -4.100
+51147.00    -47.416 -3.926  -48.300 -4.100
+51148.00    -47.585 -3.925  -48.200 -4.100
+51149.00    -47.851 -4.124  -48.000 -4.100
+51150.00    -48.101 -4.343  -47.600 -4.300
+51151.00    -48.253 -4.343  -47.100 -4.400
+51152.00    -48.247 -4.125  -46.600 -4.400
+51153.00    -48.011 -3.953  -46.200 -4.500
+51154.00    -47.577 -4.035  -46.100 -4.500
+51155.00    -47.158 -4.267  -46.200 -4.500
+51156.00    -46.97  -4.371  -46.600 -4.400
+51157.00    -47.019 -4.194  -47.000 -4.200
+51158.00    -47.07  -3.875  -47.500 -3.900
+51159.00    -47.029 -3.617  -48.000 -3.700
+51160.00    -47.057 -3.473  -47.800 -3.600
+51161.00    -47.25  -3.394  -47.800 -3.500
+51162.00    -47.47  -3.369  -47.700 -3.400
+51163.00    -47.551 -3.44   -47.500 -3.500
+51164.00    -47.54  -3.572  -47.200 -3.600
+51165.00    -47.491 -3.726  -46.900 -3.800
+51166.00    -47.356 -3.882  -46.700 -3.900
+51167.00    -47.095 -3.999  -46.500 -4.000
+51168.00    -46.816 -4.034  -46.400 -4.000
+51169.00    -46.683 -3.973  -46.500 -3.800
+51170.00    -46.726 -3.851  -46.700 -3.700
+51171.00    -46.816 -3.722  -47.000 -3.600
+51172.00    -46.819 -3.604  -47.300 -3.400
+51173.00    -46.732 -3.485  -47.700 -3.400
+51174.00    -46.676 -3.368  -47.900 -3.400
+51175.00    -46.797 -3.313  -48.200 -3.400
+51176.00    -47.126 -3.412  -48.200 -3.600
+51177.00    -47.528 -3.676  -48.000 -3.800
+51178.00    -47.82  -3.956  -47.600 -3.900
+51179.00    -47.878 -4.035  -47.500 -4.100
+51180.00    -47.682 -3.856  -47.100 -4.300
+51181.00    -47.278 -3.62   -46.700 -4.400
+51182.00    -46.762 -3.573  -46.300 -4.300
+51183.00    -46.302 -3.734  -46.100 -4.200
+51184.00    -46.058 -3.893  -46.000 -4.000
+51185.00    -46.047 -3.871  -45.900 -3.600
+51186.00    -46.166 -3.703  -46.000 -3.400
+51187.00    -46.356 -3.545  -46.200 -3.200
+51188.00    -46.64  -3.475  -46.400 -3.100
+51189.00    -46.985 -3.444  -46.700 -3.100
+51190.00    -47.259 -3.366  -46.900 -3.100
+51191.00    -47.387 -3.229  -47.000 -3.300
+51192.00    -47.455 -3.108  -47.000 -3.400
+51193.00    -47.512 -3.137  -47.000 -3.500
+51194.00    -47.503 -3.349  -46.900 -3.600
+51195.00    -47.34  -3.626  -46.700 -3.600
+51196.00    -47.048 -3.8    -46.600 -3.600
+51197.00    -46.777 -3.794  -46.500 -3.600
+51198.00    -46.64  -3.676  -46.500 -3.600
+51199.00    -46.604 -3.568  -46.600 -3.600
+51200.00    -46.568 -3.522  -46.700 -3.600
+51201.00    -46.497 -3.504  -46.800 -3.600
+51202.00    -46.465 -3.479  -47.000 -3.600
+51203.00    -46.584 -3.478  -47.100 -3.600
+51204.00    -46.893 -3.577  -47.100 -3.700
+51205.00    -47.3   -3.82   -47.000 -3.800
+51206.00    -47.63  -4.136  -46.800 -3.900
+51207.00    -47.705 -4.271  -46.600 -4.000
+51208.00    -47.6   -4.157  -46.300 -4.100
+51209.00    -47.418 -3.95   -46.100 -4.200
+51210.00    -47.214 -3.884  -46.900 -4.200
+51211.00    -46.983 -4.08   -46.700 -4.300
+51212.00    -46.725 -4.43   -46.500 -4.500
+51213.00    -46.559 -4.657  -46.600 -4.700
+51214.00    -46.571 -4.685  -47.200 -4.400
+51215.00    -46.749 -4.628  -47.200 -4.500
+51216.00    -47.008 -4.601  -46.900 -5.000
+51217.00    -47.202 -4.608  -47.200 -4.900
+51218.00    -47.252 -4.589  -47.300 -4.600
+51219.00    -47.2   -4.537  -47.300 -4.400
+51220.00    -47.053 -4.638  -47.200 -4.300
+51221.00    -46.899 -4.883  -46.700 -4.200
+51222.00    -46.812 -5.137  -46.300 -4.400
+51223.00    -46.76  -5.353  -45.900 -4.400
+51224.00    -46.648 -5.413  -45.600 -4.500
+51225.00    -46.401 -5.227  -45.600 -4.700
+51226.00    -46.049 -4.889  -45.700 -4.700
+51227.00    -45.728 -4.641  -46.100 -4.700
+51228.00    -45.613 -4.616  -46.500 -4.700
+51229.00    -45.768 -4.75   -46.900 -4.700
+51230.00    -46.092 -4.918  -47.400 -4.700
+51231.00    -46.465 -5.026  -47.500 -4.700
+51232.00    -46.815 -5.072  -47.400 -4.900
+51233.00    -47.075 -5.107  -47.100 -5.000
+51234.00    -47.155 -5.161  -46.700 -5.200
+51235.00    -47.000 -5.216  -46.200 -5.400
+51236.00    -46.668 -5.242  -45.800 -5.500
+51237.00    -46.327 -5.26   -45.500 -5.700
+51238.00    -46.124 -5.336  -45.400 -5.700
+51239.00    -46.061 -5.504  -45.400 -5.700
+51240.00    -46.029 -5.696  -45.700 -5.700
+51241.00    -46.000 -5.803  -46.000 -5.700
+51242.00    -46.084 -5.799  -46.300 -5.600
+51243.00    -46.347 -5.754  -46.500 -5.600
+51244.00    -46.648 -5.748  -46.600 -5.600
+51245.00    -46.764 -5.789  -46.600 -5.700
+51246.00    -46.623 -5.839  -46.400 -5.700
+51247.00    -46.311 -5.857  -46.200 -5.800
+51248.00    -45.903 -5.815  -46.000 -5.800
+51249.00    -45.456 -5.726  -45.800 -5.900
+51250.00    -45.108 -5.693  -45.700 -6.000
+51251.00    -45.028 -5.818  -45.500 -6.000
+51252.00    -45.165 -6.058  -45.200 -6.100
+51253.00    -45.22  -6.234  -45.000 -6.200
+51254.00    -44.996 -6.233  -44.700 -6.200
+51255.00    -44.655 -6.111  -44.600 -6.200
+51256.00    -44.57  -6.095  -44.700 -6.200
+51257.00    -44.878 -6.311  -44.900 -6.300
+51258.00    -45.346 -6.634  -45.100 -6.400
+51259.00    -45.66  -6.856  -45.300 -6.400
+51260.00    -45.699 -6.887  -45.400 -6.500
+51261.00    -45.537 -6.777  -45.400 -6.700
+51262.00    -45.278 -6.621  -45.100 -6.800
+51263.00    -44.959 -6.551  -44.700 -7.000
+51264.00    -44.58  -6.601  -44.200 -7.000
+51265.00    -44.207 -6.741  -43.800 -7.100
+51266.00    -43.975 -6.93   -43.600 -7.200
+51267.00    -43.952 -7.096  -43.600 -7.100
+51268.00    -44.055 -7.163  -43.900 -7.100
+51269.00    -44.177 -7.111  -44.100 -7.100
+51270.00    -44.333 -7.012  -44.600 -7.100
+51271.00    -44.574 -6.956  -45.000 -7.100
+51272.00    -44.827 -6.963  -45.200 -7.100
+51273.00    -44.962 -7.003  -45.300 -7.200
+51274.00    -44.989 -7.069  -45.100 -7.200
+51275.00    -45.007 -7.166  -44.900 -7.100
+51276.00    -44.959 -7.24   -44.500 -7.100
+51277.00    -44.678 -7.199  -44.200 -7.100
+51278.00    -44.248 -7.066  -43.900 -7.100
+51279.00    -44.036 -7.015  -43.700 -7.000
+51280.00    -44.206 -7.154  -43.700 -7.000
+51281.00    -44.423 -7.346  -43.800 -7.100
+51282.00    -44.271 -7.351  -44.000 -7.200
+51283.00    -43.819 -7.158  -44.100 -7.300
+51284.00    -43.559 -7.024  -44.100 -7.500
+51285.00    -43.772 -7.166  -44.100 -7.600
+51286.00    -44.219 -7.503  -44.100 -7.800
+51287.00    -44.483 -7.783  -43.900 -7.900
+51288.00    -44.426 -7.869  -43.800 -7.800
+51289.00    -44.255 -7.827  -43.800 -7.700
+51290.00    -44.189 -7.787  -43.600 -7.600
+51291.00    -44.27  -7.72   -43.500 -7.500
+51292.00    -44.363 -7.615  -43.300 -7.300
+51293.00    -44.286 -7.538  -43.200 -7.300
+51294.00    -44.026 -7.532  -43.200 -7.400
+51295.00    -43.778 -7.563  -43.200 -7.400
+51296.00    -43.721 -7.57   -43.400 -7.500
+51297.00    -43.841 -7.479  -43.500 -7.500
+51298.00    -44.012 -7.403  -43.600 -7.400
+51299.00    -44.149 -7.461  -43.700 -7.500
+51300.00    -44.211 -7.61   -44.600 -7.600
+51301.00    -44.192 -7.742  -43.800 -7.600
+51302.00    -44.182 -7.836  -44.000 -7.800
+51303.00    -44.287 -7.953  -44.100 -7.900
+51304.00    -44.407 -8.06   -44.200 -7.900
+51305.00    -44.268 -8.067  -44.200 -7.900
+51306.00    -43.824 -7.917  -44.100 -8.000
+51307.00    -43.452 -7.735  -44.000 -8.000
+51308.00    -43.527 -7.72   -43.900 -7.900
+51309.00    -43.943 -7.868  -44.000 -7.900
+51310.00    -44.298 -7.963  -44.100 -7.900
+51311.00    -44.466 -7.888  -44.500 -7.900
+51312.00    -44.718 -7.796  -44.800 -7.900
+51313.00    -45.251 -7.884  -45.100 -7.900
+51314.00    -45.84  -8.099  -45.300 -8.000
+51315.00    -46.06  -8.216  -45.300 -8.000
+51316.00    -45.71  -8.136  -45.200 -8.000
+51317.00    -44.993 -7.971  -44.800 -8.000
+51318.00    -44.367 -7.836  -44.400 -7.900
+51319.00    -44.264 -7.766  -44.000 -7.800
+51320.00    -44.634 -7.706  -43.700 -7.600
+51321.00    -45.026 -7.668  -43.700 -7.600
+51322.00    -45.105 -7.703  -43.800 -7.500
+51323.00    -44.999 -7.756  -44.300 -7.600
+51324.00    -45.073 -7.702  -44.900 -7.600
+51325.00    -45.45  -7.524  -45.500 -7.700
+51326.00    -45.914 -7.374  -46.100 -7.800
+51327.00    -46.216 -7.389  -46.500 -7.900
+51328.00    -46.294 -7.528  -46.600 -8.000
+51329.00    -46.23  -7.652  -46.600 -8.000
+51330.00    -46.156 -7.711  -46.300 -8.000
+51331.00    -46.188 -7.788  -45.900 -8.000
+51332.00    -46.313 -7.945  -45.400 -7.900
+51333.00    -46.331 -8.086  -45.100 -7.700
+51334.00    -46.074 -8.07   -44.800 -7.600
+51335.00    -45.676 -7.905  -45.000 -7.500
+51336.00    -45.471 -7.737  -45.300 -7.400
+51337.00    -45.625 -7.657  -45.500 -7.500
+51338.00    -46.017 -7.604  -45.900 -7.500
+51339.00    -46.5   -7.512  -46.200 -7.500
+51340.00    -47.061 -7.455  -46.600 -7.600
+51341.00    -47.695 -7.529  -46.900 -7.600
+51342.00    -48.241 -7.651  -47.100 -7.500
+51343.00    -48.468 -7.639  -47.300 -7.500
+51344.00    -48.269 -7.472  -47.300 -7.400
+51345.00    -47.774 -7.348  -47.400 -7.200
+51346.00    -47.313 -7.41   -47.400 -7.200
+51347.00    -47.275 -7.561  -47.500 -7.100
+51348.00    -47.735 -7.611  -47.600 -7.000
+51349.00    -48.309 -7.538  -47.700 -7.000
+51350.00    -48.556 -7.477  -47.900 -7.100
+51351.00    -48.49  -7.492  -48.100 -7.200
+51352.00    -48.534 -7.487  -48.400 -7.300
+51353.00    -48.969 -7.358  -48.800 -7.400
+51354.00    -49.61  -7.161  -49.100 -7.500
+51355.00    -50.118 -7.027  -49.400 -7.600
+51356.00    -50.367 -7.009  -49.700 -7.700
+51357.00    -50.404 -7.053  -49.900 -7.600
+51358.00    -50.26  -7.108  -49.900 -7.500
+51359.00    -49.982 -7.181  -49.700 -7.300
+51360.00    -49.792 -7.248  -49.400 -7.100
+51361.00    -49.812 -7.308  -49.100 -6.800
+51362.00    -49.908 -7.323  -48.900 -6.600
+51363.00    -49.912 -7.252  -48.700 -6.500
+51364.00    -49.865 -7.109  -48.900 -6.500
+51365.00    -49.964 -6.948  -49.600 -6.500
+51366.00    -50.356 -6.819  -50.100 -6.700
+51367.00    -51.019 -6.775  -50.800 -6.800
+51368.00    -51.79  -6.877  -51.400 -7.000
+51369.00    -52.452 -7.115  -51.800 -7.100
+51370.00    -52.823 -7.344  -52.100 -7.100
+51371.00    -52.85  -7.379  -52.100 -7.100
+51372.00    -52.595 -7.216  -52.000 -7.000
+51373.00    -52.187 -7.077  -51.800 -6.900
+51374.00    -51.829 -7.158  -51.700 -6.800
+51375.00    -51.75  -7.34   -51.500 -6.800
+51376.00    -52.082 -7.389  -51.600 -6.800
+51377.00    -52.651 -7.243  -51.900 -6.800
+51378.00    -53.103 -7.063  -52.300 -6.900
+51379.00    -53.303 -7.029  -52.900 -6.900
+51380.00    -53.444 -7.135  -53.500 -7.000
+51381.00    -53.672 -7.196  -54.000 -7.100
+51382.00    -53.947 -7.123  -54.400 -7.200
+51383.00    -54.161 -6.993  -54.700 -7.300
+51384.00    -54.31  -6.929  -54.800 -7.400
+51385.00    -54.453 -6.98   -54.700 -7.400
+51386.00    -54.561 -7.092  -54.700 -7.300
+51387.00    -54.587 -7.161  -54.700 -7.300
+51388.00    -54.624 -7.13   -54.800 -7.200
+51389.00    -54.828 -7.049  -55.000 -7.000
+51390.00    -55.189 -7.009  -55.000 -6.900
+51391.00    -55.507 -7.042  -55.200 -6.900
+51392.00    -55.621 -7.098  -55.300 -6.800
+51393.00    -55.601 -7.107  -55.500 -6.900
+51394.00    -55.652 -7.071  -55.700 -7.000
+51395.00    -55.892 -7.068  -55.600 -7.100
+51396.00    -56.243 -7.181  -55.700 -7.300
+51397.00    -56.493 -7.401  -55.600 -7.400
+51398.00    -56.471 -7.598  -55.600 -7.400
+51399.00    -56.196 -7.622  -55.500 -7.500
+51400.00    -55.853 -7.45   -55.500 -7.400
+51401.00    -55.639 -7.233  -55.500 -7.300
+51402.00    -55.608 -7.139  -55.500 -7.000
+51403.00    -55.764 -7.231  -55.700 -6.900
+51404.00    -56.134 -7.367  -55.800 -6.700
+51405.00    -56.653 -7.39   -56.000 -6.700
+51406.00    -57.117 -7.32   -56.300 -6.700
+51407.00    -57.303 -7.253  -56.400 -6.800
+51408.00    -57.153 -7.195  -56.700 -7.000
+51409.00    -56.878 -7.109  -57.000 -7.200
+51410.00    -56.66  -6.936  -57.100 -7.400
+51411.00    -56.613 -6.727  -57.300 -7.600
+51412.00    -56.776 -6.641  -57.300 -7.700
+51413.00    -57.052 -6.79   -57.300 -7.800
+51414.00    -57.239 -7.145  -57.200 -7.800
+51415.00    -57.195 -7.533  -57.200 -7.600
+51416.00    -57.012 -7.7    -57.000 -7.500
+51417.00    -56.883 -7.596  -56.900 -7.400
+51418.00    -56.917 -7.396  -57.000 -7.300
+51419.00    -57.065 -7.297  -56.900 -7.200
+51420.00    -57.212 -7.341  -57.000 -7.100
+51421.00    -57.308 -7.416  -57.100 -7.200
+51422.00    -57.404 -7.409  -57.200 -7.300
+51423.00    -57.57  -7.321  -57.300 -7.300
+51424.00    -57.793 -7.237  -57.400 -7.400
+51425.00    -57.956 -7.211  -56.800 -9.400
+51426.00    -57.921 -7.216  -56.200 -9.400
+51427.00    -57.637 -7.174  -55.800 -9.000
+51428.00    -57.197 -7.042  -55.700 -8.200
+51429.00    -56.771 -6.869  -55.900 -7.100
+51430.00    -56.497 -6.756  -56.300 -5.900
+51431.00    -56.414 -6.745  -56.900 -5.000
+51432.00    -56.488 -6.782  -57.700 -4.500
+51433.00    -56.684 -6.805  -58.400 -4.500
+51434.00    -56.957 -6.839  -58.700 -4.900
+51435.00    -57.187 -6.95   -58.600 -5.800
+51436.00    -57.197 -7.113  -58.100 -6.800
+51437.00    -56.947 -7.205  -57.400 -8.000
+51438.00    -56.642 -7.142  -56.500 -9.000
+51439.00    -56.571 -6.984  -55.600 -9.500
+51440.00    -56.794 -6.865  -54.900 -9.600
+51441.00    -57.069 -6.869  -54.500 -9.100
+51442.00    -57.122 -6.971  -54.700 -8.300
+51443.00    -56.919 -7.059  -55.400 -7.200
+51444.00    -56.693 -7.003  -56.400 -6.000
+51445.00    -56.571 -6.753  -57.500 -5.100
+51446.00    -56.552 -6.423  -58.500 -4.500
+51447.00    -56.643 -6.241  -59.300 -4.400
+51448.00    -56.864 -6.341  -59.600 -4.800
+51449.00    -57.166 -6.617  -59.300 -5.600
+51450.00    -57.432 -6.823  -58.400 -6.600
+51451.00    -57.567 -6.8    -57.300 -7.600
+51452.00    -57.566 -6.6    -56.000 -8.500
+51453.00    -57.458 -6.38   -54.800 -8.900
+51454.00    -57.245 -6.243  -54.000 -8.900
+51455.00    -56.917 -6.196  -52.300 -6.000
+51456.00    -56.508 -6.211  -53.600 -6.000
+51457.00    -56.129 -6.271  -55.400 -6.200
+51458.00    -55.896 -6.304  -56.800 -6.300
+51459.00    -55.847 -6.27   -57.600 -6.200
+51460.00    -55.898 -6.163  -57.600 -6.200
+51461.00    -55.943 -6.021  -57.200 -6.000
+51462.00    -55.939 -5.932  -56.500 -6.000
+51463.00    -55.842 -5.953  -55.800 -5.900
+51464.00    -55.544 -6.029  -55.300 -5.900
+51465.00    -55.045 -6.071  -54.300 -5.900
+51466.00    -54.573 -6.029  -52.700 -5.800
+51467.00    -54.432 -5.96   -51.100 -5.600
+51468.00    -54.628 -5.945  -50.300 -5.600
+51469.00    -54.817 -5.976  -50.700 -5.600
+51470.00    -54.729 -5.994  -52.000 -5.800
+51471.00    -54.466 -5.968  -53.800 -5.800
+51472.00    -54.269 -5.88   -55.300 -5.900
+51473.00    -54.163 -5.685  -56.100 -5.900
+51474.00    -54.007 -5.385  -55.800 -5.700
+51475.00    -53.796 -5.13   -54.900 -5.500
+51476.00    -53.705 -5.112  -54.000 -5.300
+51477.00    -53.831 -5.329  -53.500 -5.300
+51478.00    -54.074 -5.541  -54.000 -5.500
+51479.00    -54.225 -5.543  -54.500 -5.600
+51480.00    -54.232 -5.353  -54.800 -5.700
+51481.00    -54.157 -5.162  -54.800 -5.800
+51482.00    -54.049 -5.102  -54.600 -5.700
+51483.00    -53.92  -5.144  -54.100 -5.600
+51484.00    -53.758 -5.195  -53.700 -5.300
+51485.00    -53.56  -5.22   -53.500 -5.200
+51486.00    -53.385 -5.213  -53.100 -5.000
+51487.00    -53.322 -5.134  -52.900 -4.800
+51488.00    -53.379 -4.942  -52.900 -4.600
+51489.00    -53.452 -4.689  -52.900 -4.600
+51490.00    -53.43  -4.523  -52.900 -4.500
+51491.00    -53.264 -4.539  -52.900 -4.600
+51492.00    -52.931 -4.668  -52.800 -4.600
+51493.00    -52.458 -4.749  -52.500 -4.700
+51494.00    -52.027 -4.713  -52.100 -4.700
+51495.00    -51.874 -4.64   -51.800 -4.800
+51496.00    -51.991 -4.607  -51.500 -4.800
+51497.00    -52.073 -4.572  -51.300 -4.600
+51498.00    -51.914 -4.469  -51.300 -4.500
+51499.00    -51.686 -4.342  -51.500 -4.400
+51500.00    -51.638 -4.256  -51.800 -4.200
+51501.00    -51.743 -4.188  -52.100 -4.000
+51502.00    -51.774 -4.034  -52.400 -3.800
+51503.00    -51.673 -3.805  -52.500 -3.900
+51504.00    -51.62  -3.685  -52.400 -3.800
+51505.00    -51.707 -3.783  -52.100 -3.800
+51506.00    -51.795 -3.944  -51.700 -3.900
+51507.00    -51.724 -3.926  -51.300 -4.000
+51508.00    -51.496 -3.714  -50.800 -4.000
+51509.00    -51.223 -3.529  -50.500 -4.000
+51510.00    -51.008 -3.52   -50.300 -4.000
+51511.00    -50.914 -3.599  -50.300 -3.900
+51512.00    -50.926 -3.611  -50.400 -3.700
+51513.00    -50.925 -3.552  -50.700 -3.500
+51514.00    -50.824 -3.522  -51.000 -3.400
+51515.00    -50.71  -3.534  -51.300 -3.200
+51516.00    -50.74  -3.497  -51.500 -3.100
+51517.00    -50.909 -3.374  -51.500 -3.000
+51518.00    -51.049 -3.267  -51.400 -3.000
+51519.00    -51.03  -3.288  -51.200 -3.200
+51520.00    -50.877 -3.408  -50.800 -3.300
+51521.00    -50.69  -3.522  -50.300 -3.500
+51522.00    -50.579 -3.565  -50.000 -3.600
+51523.00    -50.647 -3.582  -49.800 -3.600
+51524.00    -50.882 -3.625  -49.700 -3.600
+51525.00    -51.095 -3.633  -49.900 -3.500
+51526.00    -51.109 -3.518  -50.300 -3.400
+51527.00    -50.97  -3.325  -50.700 -3.200
+51528.00    -50.851 -3.22   -51.100 -3.100
+51529.00    -50.764 -3.231  -51.500 -3.000
+51530.00    -50.606 -3.214  -51.800 -3.000
+51531.00    -50.434 -3.085  -51.800 -3.000
+51532.00    -50.456 -2.967  -51.700 -3.000
+51533.00    -50.71  -3.008  -51.400 -3.000
+51534.00    -50.948 -3.136  -50.900 -3.100
+51535.00    -50.913 -3.137  -50.400 -3.100
+51536.00    -50.581 -2.97   -49.900 -3.100
+51537.00    -50.118 -2.834  -49.500 -3.100
+51538.00    -49.742 -2.876  -49.400 -2.900
+51539.00    -49.636 -2.972  -49.400 -2.800
+51540.00    -49.841 -2.907  -49.800 -2.700
+51541.00    -50.176 -2.678  -50.100 -2.600
+51542.00    -50.392 -2.493  -50.500 -2.500
+51543.00    -50.473 -2.486  -50.800 -2.400
+51544.00    -50.607 -2.585  -50.900 -2.500
+51545.00    -50.218 -2.679  -50.800 -2.500
+51546.00    -50.459 -2.699  -50.600 -2.500
+51547.00    -50.437 -2.766  -50.300 -2.800
+51548.00    -50.188 -2.893  -49.900 -2.900
+51549.00    -49.678 -3.066  -49.400 -2.900
+51550.00    -49.409 -3.103  -49.000 -2.900
+51551.00    -49.211 -3.09   -48.500 -2.800
+51552.00    -49.134 -3.078  -48.400 -2.600
+51553.00    -49.197 -3.071  -48.300 -2.400
+51554.00    -49.336 -3.037  -48.600 -2.200
+51555.00    -49.474 -2.995  -48.900 -2.100
+51556.00    -49.629 -2.979  -49.400 -2.100
+51557.00    -49.677 -3.035  -49.900 -2.100
+51558.00    -49.689 -3.048  -50.400 -2.200
+51559.00    -49.8   -2.966  -50.700 -2.300
+51560.00    -50.181 -2.879  -50.900 -2.500
+51561.00    -50.789 -2.914  -50.800 -2.600
+51562.00    -51.314 -3.044  -50.500 -2.600
+51563.00    -51.604 -3.008  -50.200 -2.600
+51564.00    -51.228 -2.945  -49.700 -2.500
+51565.00    -50.536 -2.903  -49.300 -2.500
+51566.00    -49.812 -3.019  -49.100 -2.300
+51567.00    -49.344 -3.19   -49.200 -2.100
+51568.00    -49.289 -3.182  -49.500 -2.000
+51569.00    -49.551 -2.941  -49.800 -2.000
+51570.00    -49.778 -2.721  -50.400 -1.900
+51571.00    -50.052 -2.653  -50.800 -2.100
+51572.00    -50.347 -2.785  -51.100 -2.300
+51573.00    -50.674 -2.964  -51.200 -2.500
+51574.00    -50.834 -3.087  -51.000 -2.700
+51575.00    -50.661 -3.175  -50.700 -3.000
+51576.00    -50.262 -3.274  -50.300 -3.100
+51577.00    -49.874 -3.397  -49.800 -3.100
+51578.00    -49.607 -3.461  -49.400 -3.000
+51579.00    -49.395 -3.453  -49.000 -2.900
+51580.00    -49.234 -3.387  -48.600 -3.100
+51581.00    -49.211 -3.314  -48.400 -3.300
+51582.00    -49.352 -3.296  -48.300 -3.300
+51583.00    -49.554 -3.361  -48.700 -3.300
+51584.00    -49.669 -3.503  -49.200 -3.300
+51585.00    -49.735 -3.605  -49.800 -3.500
+51586.00    -49.789 -3.637  -50.400 -3.600
+51587.00    -49.927 -3.614  -50.800 -3.700
+51588.00    -50.204 -3.618  -51.000 -3.900
+51589.00    -50.548 -3.721  -50.800 -3.900
+51590.00    -50.779 -3.891  -50.600 -3.900
+51591.00    -50.742 -4.014  -50.200 -3.900
+51592.00    -50.43  -4.036  -49.700 -3.900
+51593.00    -49.958 -4.056  -49.400 -4.000
+51594.00    -49.483 -4.198  -49.100 -4.000
+51595.00    -49.155 -4.423  -49.000 -4.000
+51596.00    -49.085 -4.532  -49.100 -4.200
+51597.00    -49.273 -4.415  -49.300 -4.300
+51598.00    -49.615 -4.191  -49.600 -4.500
+51599.00    -50.009 -4.08   -49.900 -4.600
+51600.00    -50.396 -4.16   -50.100 -4.700
+51601.00    -50.665 -4.331  -50.200 -4.700
+51602.00    -50.64  -4.465  -50.100 -4.700
+51603.00    -50.248 -4.535  -49.800 -4.600
+51604.00    -49.671 -4.593  -49.500 -4.600
+51605.00    -49.399 -4.629  -49.200 -4.500
+51606.00    -49.141 -4.709  -48.900 -4.500
+51607.00    -49.024 -4.718  -48.700 -4.400
+51608.00    -48.94  -4.618  -48.600 -4.400
+51609.00    -48.886 -4.461  -48.700 -4.400
+51610.00    -48.9   -4.379  -48.900 -4.500
+51611.00    -48.978 -4.47   -49.200 -4.600
+51612.00    -49.184 -4.698  -49.500 -4.700
+51613.00    -49.341 -4.918  -49.700 -4.900
+51614.00    -49.548 -5.03   -49.900 -5.000
+51615.00    -49.769 -5.045  -49.900 -5.000
+51616.00    -49.912 -5.047  -49.800 -5.100
+51617.00    -49.873 -5.102  -49.500 -5.100
+51618.00    -49.604 -5.206  -49.200 -5.100
+51619.00    -48.898 -5.234  -48.800 -5.100
+51620.00    -48.468 -5.282  -48.400 -5.000
+51621.00    -48.19  -5.32   -48.100 -5.100
+51622.00    -48.112 -5.425  -47.900 -5.200
+51623.00    -48.156 -5.601  -47.800 -5.300
+51624.00    -48.231 -5.732  -47.900 -5.500
+51625.00    -48.329 -5.708  -48.000 -5.600
+51626.00    -48.514 -5.621  -48.100 -5.900
+51627.00    -48.847 -5.51   -48.400 -6.000
+51628.00    -49.222 -5.532  -48.500 -6.000
+51629.00    -49.44  -5.651  -48.600 -6.100
+51630.00    -49.344 -5.769  -48.500 -6.000
+51631.00    -48.936 -5.841  -48.500 -5.900
+51632.00    -48.369 -5.887  -48.300 -5.800
+51633.00    -47.929 -5.952  -47.900 -5.600
+51634.00    -47.625 -5.998  -47.600 -5.500
+51635.00    -47.582 -6.012  -47.200 -5.400
+51636.00    -47.702 -5.949  -47.000 -5.300
+51637.00    -47.809 -5.803  -46.900 -5.400
+51638.00    -47.813 -5.668  -47.000 -5.500
+51639.00    -47.797 -5.69   -47.200 -5.600
+51640.00    -47.915 -5.922  -47.500 -5.800
+51641.00    -48.219 -6.267  -47.800 -6.000
+51642.00    -48.592 -6.499  -48.100 -6.200
+51643.00    -48.875 -6.543  -48.200 -6.300
+51644.00    -48.961 -6.454  -48.200 -6.300
+51645.00    -48.819 -6.348  -48.100 -6.400
+51646.00    -48.458 -6.306  -47.900 -6.400
+51647.00    -48.173 -6.329  -47.600 -6.300
+51648.00    -47.67  -6.383  -47.400 -6.200
+51649.00    -47.392 -6.431  -47.400 -6.100
+51650.00    -47.442 -6.469  -47.500 -6.100
+51651.00    -47.718 -6.494  -47.600 -6.100
+51652.00    -47.987 -6.477  -48.000 -6.100
+51653.00    -48.118 -6.4    -48.300 -6.200
+51654.00    -48.421 -6.275  -48.600 -6.400
+51655.00    -48.584 -6.241  -48.800 -6.600
+51656.00    -48.813 -6.308  -48.800 -6.700
+51657.00    -48.944 -6.435  -48.800 -6.900
+51658.00    -48.882 -6.565  -48.500 -6.900
+51659.00    -48.658 -6.675  -48.200 -6.900
+51660.00    -48.308 -6.752  -47.900 -6.700
+51661.00    -47.776 -6.773  -47.600 -6.400
+51662.00    -47.357 -6.727  -47.400 -6.200
+51663.00    -47.247 -6.683  -47.300 -6.100
+51664.00    -47.527 -6.672  -47.200 -5.900
+51665.00    -47.919 -6.638  -47.300 -5.900
+51666.00    -48.105 -6.532  -47.500 -5.900
+51667.00    -48.118 -6.439  -47.800 -6.200
+51668.00    -48.26  -6.541  -48.100 -6.300
+51669.00    -48.636 -6.82   -48.500 -6.500
+51670.00    -49.026 -7.107  -48.600 -6.800
+51671.00    -49.157 -7.191  -48.500 -6.900
+51672.00    -49.011 -7.051  -48.600 -7.000
+51673.00    -48.77  -6.842  -48.500 -6.900
+51674.00    -48.563 -6.721  -48.400 -6.800
+51675.00    -48.366 -6.722  -48.400 -6.700
+51676.00    -48.124 -6.789  -48.400 -6.400
+51677.00    -47.896 -6.855  -48.500 -6.300
+51678.00    -47.849 -6.865  -48.600 -6.200
+51679.00    -48.073 -6.784  -48.800 -6.100
+51680.00    -48.453 -6.617  -49.000 -6.200
+51681.00    -48.775 -6.439  -49.200 -6.300
+51682.00    -49.026 -6.4    -49.300 -6.600
+51683.00    -49.101 -6.484  -49.400 -6.800
+51684.00    -49.147 -6.658  -49.300 -7.000
+51685.00    -49.147 -6.808  -49.000 -7.100
+51686.00    -49.124 -6.895  -48.800 -7.200
+51687.00    -49.145 -6.969  -48.400 -7.200
+51688.00    -49.144 -7.041  -48.000 -7.100
+51689.00    -48.814 -6.995  -47.800 -6.800
+51690.00    -48.451 -6.855  -47.800 -6.600
+51691.00    -48.306 -6.697  -47.900 -6.500
+51692.00    -48.673 -6.666  -48.200 -6.400
+51693.00    -49.336 -6.731  -48.500 -6.300
+51694.00    -49.82  -6.713  -48.900 -6.400
+51695.00    -50.005 -6.561  -49.200 -6.600
+51696.00    -49.884 -6.457  -49.600 -6.700
+51697.00    -50.305 -6.564  -49.700 -6.800
+51698.00    -50.689 -6.793  -49.800 -6.800
+51699.00    -50.7   -6.902  -49.700 -6.800
+51700.00    -50.344 -6.805  -49.600 -6.800
+51701.00    -49.961 -6.645  -49.600 -6.600
+51702.00    -49.858 -6.578  -49.600 -6.400
+51703.00    -50.05  -6.599  -49.800 -6.300
+51704.00    -50.304 -6.626  -49.900 -6.200
+51705.00    -50.397 -6.629  -50.200 -6.000
+51706.00    -50.353 -6.624  -50.600 -6.000
+51707.00    -50.414 -6.581  -50.900 -6.100
+51708.00    -50.757 -6.452  -51.300 -6.200
+51709.00    -51.267 -6.293  -51.600 -6.300
+51710.00    -51.963 -6.236  -51.800 -6.500
+51711.00    -52.091 -6.379  -51.900 -6.700
+51712.00    -52.031 -6.599  -51.900 -6.700
+51713.00    -51.918 -6.712  -52.000 -6.800
+51714.00    -51.892 -6.675  -51.900 -6.700
+51715.00    -52.05  -6.612  -52.000 -6.600
+51716.00    -52.318 -6.615  -52.100 -6.400
+51717.00    -52.368 -6.578  -52.300 -6.200
+51718.00    -52.267 -6.453  -52.600 -6.000
+51719.00    -52.198 -6.262  -52.900 -5.900
+51720.00    -52.525 -6.186  -53.300 -5.800
+51721.00    -53.213 -6.273  -53.600 -5.800
+51722.00    -53.86  -6.351  -53.900 -5.900
+51723.00    -54.227 -6.282  -54.000 -6.000
+51724.00    -54.412 -6.22   -54.000 -6.200
+51725.00    -54.72  -6.243  -54.000 -6.400
+51726.00    -54.966 -6.397  -53.800 -6.500
+51727.00    -54.896 -6.493  -53.600 -6.600
+51728.00    -54.496 -6.45   -53.700 -6.700
+51729.00    -54.053 -6.399  -53.700 -6.700
+51730.00    -53.906 -6.453  -53.800 -6.600
+51731.00    -54.247 -6.583  -54.200 -6.500
+51732.00    -54.786 -6.527  -54.500 -6.400
+51733.00    -55.211 -6.382  -55.000 -6.400
+51734.00    -55.289 -6.317  -55.300 -6.300
+51735.00    -55.187 -6.389  -55.600 -6.300
+51736.00    -55.276 -6.48   -55.700 -6.400
+51737.00    -55.675 -6.494  -55.700 -6.500
+51738.00    -56.1   -6.514  -55.700 -6.600
+51739.00    -56.296 -6.606  -55.500 -6.700
+51740.00    -56.234 -6.749  -55.400 -6.700
+51741.00    -56.104 -6.79   -55.300 -6.800
+51742.00    -56.067 -6.666  -55.500 -6.700
+51743.00    -56.188 -6.49   -55.700 -6.500
+51744.00    -56.443 -6.405  -56.000 -6.400
+51745.00    -56.616 -6.395  -56.500 -6.300
+51746.00    -56.737 -6.364  -56.900 -6.100
+51747.00    -56.768 -6.262  -57.500 -6.000
+51748.00    -56.942 -6.187  -57.900 -6.000
+51749.00    -57.381 -6.224  -58.200 -6.000
+51750.00    -57.939 -6.319  -58.500 -6.100
+51751.00    -58.399 -6.373  -58.500 -6.300
+51752.00    -58.696 -6.403  -58.500 -6.500
+51753.00    -58.859 -6.486  -58.200 -6.600
+51754.00    -58.87  -6.593  -58.100 -6.700
+51755.00    -58.697 -6.594  -57.800 -6.700
+51756.00    -58.397 -6.476  -57.700 -6.800
+51757.00    -58.112 -6.405  -57.800 -6.800
+51758.00    -58.002 -6.492  -58.000 -6.600
+51759.00    -58.228 -6.61   -58.300 -6.400
+51760.00    -58.724 -6.528  -58.600 -6.300
+51761.00    -59.261 -6.281  -59.000 -6.200
+51762.00    -59.498 -6.134  -59.400 -6.200
+51763.00    -59.391 -6.259  -59.600 -6.200
+51764.00    -59.255 -6.536  -59.600 -6.400
+51765.00    -59.347 -6.728  -59.500 -6.600
+51766.00    -59.413 -6.725  -59.300 -6.800
+51767.00    -59.538 -6.702  -59.000 -6.900
+51768.00    -59.497 -6.712  -58.600 -7.000
+51769.00    -59.43  -6.715  -58.400 -6.900
+51770.00    -59.411 -6.628  -58.200 -6.800
+51771.00    -59.41  -6.458  -58.200 -6.600
+51772.00    -59.437 -6.297  -58.400 -6.400
+51773.00    -59.385 -6.235  -58.700 -6.100
+51774.00    -59.542 -6.225  -59.200 -6.000
+51775.00    -59.648 -6.231  -59.600 -5.900
+51776.00    -59.722 -6.224  -60.100 -5.900
+51777.00    -59.896 -6.218  -60.400 -6.000
+51778.00    -60.247 -6.239  -60.700 -6.100
+51779.00    -60.681 -6.304  -60.700 -6.200
+51780.00    -61.006 -6.416  -60.600 -6.300
+51781.00    -61.072 -6.543  -60.500 -6.400
+51782.00    -60.87  -6.584  -60.300 -6.500
+51783.00    -60.556 -6.441  -60.300 -6.400
+51784.00    -60.326 -6.159  -60.400 -6.200
+51785.00    -60.255 -5.94   -60.600 -6.000
+51786.00    -60.295 -5.939  -60.900 -5.800
+51787.00    -60.525 -5.991  -61.300 -5.700
+51788.00    -60.78  -5.998  -61.600 -5.600
+51789.00    -61.135 -5.832  -62.300 -5.500
+51790.00    -61.383 -5.698  -62.500 -5.700
+51791.00    -61.369 -5.808  -61.700 -5.900
+51792.00    -61.176 -6.107  -61.400 -6.200
+51793.00    -60.996 -6.344  -61.100 -6.500
+51794.00    -60.682 -6.379  -60.600 -6.600
+51795.00    -60.586 -6.27   -60.100 -6.700
+51796.00    -60.499 -6.197  -59.800 -6.700
+51797.00    -60.471 -6.213  -59.600 -6.600
+51798.00    -60.459 -6.227  -59.700 -6.400
+51799.00    -60.358 -6.125  -59.900 -6.100
+51800.00    -60.185 -5.898  -60.300 -5.900
+51801.00    -60.105 -5.689  -60.600 -5.700
+51802.00    -60.16  -5.586  -61.000 -5.600
+51803.00    -60.265 -5.648  -61.300 -5.600
+51804.00    -60.308 -5.775  -61.400 -5.600
+51805.00    -60.331 -5.843  -61.300 -5.700
+51806.00    -60.453 -5.826  -61.000 -5.700
+51807.00    -60.681 -5.794  -60.700 -5.800
+51808.00    -60.78  -5.845  -60.100 -5.800
+51809.00    -60.69  -5.89   -59.600 -5.800
+51810.00    -60.319 -5.852  -59.300 -5.700
+51811.00    -59.864 -5.649  -59.000 -5.700
+51812.00    -59.581 -5.324  -58.900 -5.500
+51813.00    -59.566 -5.044  -59.000 -5.300
+51814.00    -59.696 -4.961  -59.200 -5.100
+51815.00    -59.804 -5.055  -59.400 -5.000
+51816.00    -59.878 -5.13   -59.600 -4.900
+51817.00    -59.92  -5.13   -59.800 -4.900
+51818.00    -59.969 -5.101  -59.800 -5.000
+51819.00    -59.939 -5.189  -59.700 -5.100
+51820.00    -59.745 -5.387  -59.400 -5.200
+51821.00    -59.402 -5.525  -58.900 -5.400
+51822.00    -59.02  -5.434  -58.600 -5.500
+51823.00    -58.714 -5.28   -58.100 -5.500
+51824.00    -58.558 -5.181  -57.800 -5.400
+51825.00    -58.518 -5.207  -57.600 -5.300
+51826.00    -58.483 -5.261  -57.700 -5.200
+51827.00    -58.38  -5.183  -57.800 -5.000
+51828.00    -58.247 -4.908  -58.100 -4.800
+51829.00    -58.26  -4.55   -58.500 -4.600
+51830.00    -58.296 -4.314  -58.800 -4.500
+51831.00    -58.363 -4.345  -59.000 -4.400
+51832.00    -58.38  -4.573  -59.100 -4.400
+51833.00    -58.349 -4.784  -59.000 -4.400
+51834.00    -58.332 -4.817  -58.700 -4.500
+51835.00    -58.35  -4.69   -58.100 -4.500
+51836.00    -58.43  -4.52   -57.600 -4.600
+51837.00    -58.265 -4.41   -57.100 -4.500
+51838.00    -57.924 -4.329  -56.800 -4.500
+51839.00    -57.52  -4.219  -56.600 -4.400
+51840.00    -57.248 -4.066  -56.600 -4.200
+51841.00    -57.23  -3.925  -56.900 -4.100
+51842.00    -57.41  -3.869  -57.300 -4.000
+51843.00    -57.603 -3.911  -57.600 -3.900
+51844.00    -57.65  -3.985  -57.800 -3.900
+51845.00    -57.545 -4.029  -58.000 -3.900
+51846.00    -57.393 -4.061  -57.900 -4.000
+51847.00    -57.247 -4.138  -57.600 -4.100
+51848.00    -57.032 -4.24   -57.200 -4.200
+51849.00    -56.665 -4.258  -56.600 -4.500
+51850.00    -56.224 -4.134  -55.800 -4.300
+51851.00    -55.902 -3.954  -55.300 -4.200
+51852.00    -55.779 -3.855  -55.000 -4.100
+51853.00    -55.737 -3.867  -54.900 -4.000
+51854.00    -55.656 -3.893  -55.000 -4.000
+51855.00    -55.577 -3.811  -55.300 -4.000
+51856.00    -55.61  -3.571  -55.700 -4.000
+51857.00    -55.736 -3.226  -56.100 -3.900
+51858.00    -55.822 -2.921  -56.600 -3.800
+51859.00    -55.801 -2.825  -56.800 -3.700
+51860.00    -55.718 -2.987  -56.900 -3.500
+51861.00    -55.618 -3.254  -56.600 -3.400
+51862.00    -55.481 -3.38   -56.200 -3.300
+51863.00    -55.297 -3.254  -55.700 -3.200
+51864.00    -55.106 -2.984  -55.000 -3.200
+51865.00    -54.94  -2.766  -54.500 -3.100
+51866.00    -54.776 -2.695  -54.100 -3.100
+51867.00    -54.594 -2.727  -54.000 -3.200
+51868.00    -54.447 -2.78   -54.000 -3.100
+51869.00    -54.435 -2.817  -54.200 -3.100
+51870.00    -54.603 -2.842  -54.600 -3.000
+51871.00    -54.868 -2.85   -54.900 -2.900
+51872.00    -55.054 -2.83   -55.200 -2.800
+51873.00    -55.037 -2.798  -55.300 -2.700
+51874.00    -54.853 -2.81   -55.200 -2.700
+51875.00    -54.621 -2.9    -54.900 -2.700
+51876.00    -54.377 -3.003  -54.300 -2.700
+51877.00    -54.081 -3.001  -53.600 -2.700
+51878.00    -53.785 -2.868  -53.000 -2.700
+51879.00    -53.64  -2.711  -52.500 -2.700
+51880.00    -53.606 -2.57   -52.500 -2.800
+51881.00    -53.633 -2.597  -52.500 -2.700
+51882.00    -53.534 -2.617  -52.700 -2.700
+51883.00    -53.453 -2.579  -53.100 -2.600
+51884.00    -53.58  -2.488  -53.400 -2.500
+51885.00    -53.798 -2.36   -53.700 -2.400
+51886.00    -53.94  -2.098  -54.000 -2.200
+51887.00    -53.926 -1.843  -54.100 -2.200
+51888.00    -53.922 -1.782  -54.100 -2.100
+51889.00    -53.971 -1.964  -53.900 -2.000
+51890.00    -53.885 -2.184  -53.600 -2.000
+51891.00    -53.532 -2.197  -53.100 -2.000
+51892.00    -52.962 -1.961  -52.500 -1.900
+51893.00    -52.615 -1.742  -52.100 -1.900
+51894.00    -52.487 -1.678  -51.700 -1.800
+51895.00    -52.494 -1.737  -51.700 -1.800
+51896.00    -52.538 -1.801  -51.800 -1.800
+51897.00    -52.608 -1.834  -52.200 -1.900
+51898.00    -52.751 -1.87   -52.600 -2.000
+51899.00    -52.968 -1.954  -53.000 -2.100
+51900.00    -53.238 -1.956  -53.400 -2.300
+51901.00    -53.38  -1.922  -53.600 -2.300
+51902.00    -53.296 -1.938  -53.500 -2.300
+51903.00    -53.041 -2.062  -53.300 -2.300
+51904.00    -52.739 -2.219  -53.100 -2.300
+51905.00    -52.473 -2.267  -52.600 -2.300
+51906.00    -52.307 -2.175  -52.300 -2.100
+51907.00    -52.316 -2.062  -51.900 -2.000
+51908.00    -52.467 -2.049  -51.700 -2.000
+51909.00    -52.572 -2.112  -51.600 -1.900
+51910.00    -52.513 -2.159  -51.600 -2.000
+51911.00    -52.431 -2.184  -51.800 -2.100
+51912.00    -52.522 -2.242  -52.100 -2.300
+51913.00    -52.722 -2.278  -52.600 -2.400
+51914.00    -52.837 -2.14   -53.100 -1.900
+51915.00    -52.917 -1.821  -53.500 -1.800
+51916.00    -53.215 -1.575  -53.700 -1.800
+51917.00    -53.713 -1.647  -53.800 -1.800
+51918.00    -53.979 -1.955  -53.500 -2.000
+51919.00    -53.649 -2.18   -53.200 -2.200
+51920.00    -52.624 -2.182  -52.700 -2.400
+51921.00    -51.878 -2.036  -52.300 -2.600
+51922.00    -51.498 -1.953  -52.000 -2.400
+51923.00    -51.499 -1.918  -51.900 -2.300
+51924.00    -51.709 -1.818  -51.900 -2.100
+51925.00    -51.949 -1.677  -52.000 -1.900
+51926.00    -52.141 -1.643  -52.200 -1.900
+51927.00    -52.315 -1.77   -52.400 -1.900
+51928.00    -52.581 -1.948  -52.600 -2.100
+51929.00    -52.834 -2.065  -52.600 -2.200
+51930.00    -52.871 -2.149  -52.500 -2.300
+51931.00    -52.61  -2.279  -52.400 -2.400
+51932.00    -52.196 -2.422  -52.100 -2.400
+51933.00    -51.846 -2.457  -51.700 -2.300
+51934.00    -51.605 -2.312  -51.400 -2.100
+51935.00    -51.624 -2.188  -51.000 -2.100
+51936.00    -51.77  -2.174  -50.900 -2.100
+51937.00    -51.917 -2.262  -50.800 -2.100
+51938.00    -51.961 -2.358  -50.900 -2.300
+51939.00    -51.946 -2.44   -51.100 -2.400
+51940.00    -51.98  -2.569  -51.600 -2.700
+51941.00    -51.985 -2.765  -52.100 -3.000
+51942.00    -51.998 -2.769  -52.600 -3.200
+51943.00    -52.08  -2.567  -52.900 -3.400
+51944.00    -52.499 -2.361  -53.300 -3.500
+51945.00    -53.224 -2.435  -53.400 -3.500
+51946.00    -53.761 -2.795  -53.500 -3.500
+51947.00    -53.62  -3.153  -53.400 -3.300
+51948.00    -52.834 -3.243  -53.200 -3.100
+51949.00    -51.91  -3.188  -52.900 -3.000
+51950.00    -51.319 -3.125  -52.600 -2.600
+51951.00    -51.218 -3.057  -52.300 -2.500
+51952.00    -51.475 -2.877  -52.100 -2.400
+51953.00    -51.83  -2.633  -51.900 -2.500
+51954.00    -52.076 -2.547  -51.900 -2.600
+51955.00    -52.241 -2.717  -51.700 -2.700
+51956.00    -52.437 -3.066  -51.700 -3.000
+51957.00    -52.687 -3.34   -51.500 -3.300
+51958.00    -52.746 -3.47   -51.400 -3.400
+51959.00    -52.415 -3.529  -51.200 -3.500
+51960.00    -51.832 -3.558  -51.000 -3.500
+51961.00    -51.326 -3.5    -50.800 -3.500
+51962.00    -50.976 -3.335  -50.700 -3.400
+51963.00    -50.956 -3.147  -50.500 -3.200
+51964.00    -51.055 -3.074  -50.500 -3.200
+51965.00    -51.2   -3.15   -50.600 -3.200
+51966.00    -51.325 -3.303  -50.700 -3.300
+51967.00    -51.384 -3.467  -50.900 -3.500
+51968.00    -51.395 -3.63   -51.300 -3.800
+51969.00    -51.668 -3.826  -51.600 -4.100
+51970.00    -51.632 -3.9    -51.800 -4.400
+51971.00    -51.638 -3.87   -52.000 -4.700
+51972.00    -51.81  -3.842  -52.200 -4.800
+51973.00    -52.135 -3.975  -52.200 -4.900
+51974.00    -52.357 -4.273  -52.100 -4.800
+51975.00    -52.202 -4.545  -52.000 -4.500
+51976.00    -51.688 -4.63   -51.800 -4.300
+51977.00    -51.107 -4.587  -51.600 -4.100
+51978.00    -50.747 -4.572  -51.400 -3.900
+51979.00    -50.712 -4.59   -51.300 -3.800
+51980.00    -50.933 -4.513  -51.100 -3.800
+51981.00    -51.229 -4.33   -51.000 -3.900
+51982.00    -51.433 -4.233  -50.900 -4.200
+51983.00    -51.535 -4.391  -50.700 -4.500
+51984.00    -51.665 -4.724  -50.600 -4.800
+51985.00    -51.841 -4.996  -50.400 -5.100
+51986.00    -51.824 -5.08   -50.300 -5.200
+51987.00    -51.399 -5.031  -50.200 -5.300
+51988.00    -50.698 -4.944  -50.200 -5.100
+51989.00    -50.111 -4.828  -50.100 -5.000
+51990.00    -49.86  -4.696  -50.100 -4.800
+51991.00    -49.913 -4.489  -50.100 -4.600
+51992.00    -50.077 -4.351  -50.200 -4.500
+51993.00    -50.258 -4.368  -50.200 -4.500
+51994.00    -50.411 -4.541  -50.200 -4.600
+51995.00    -50.482 -4.793  -50.300 -4.800
+51996.00    -50.483 -5.02   -50.200 -5.000
+51997.00    -50.42  -5.139  -50.100 -5.300
+51998.00    -50.514 -5.19   -49.900 -5.600
+51999.00    -50.623 -5.212  -49.800 -5.700
+52000.00    -50.626 -5.274  -49.700 -5.800
+52001.00    -50.444 -5.404  -49.600 -5.800
+52002.00    -50.089 -5.549  -49.500 -5.800
+52003.00    -49.68  -5.609  -49.600 -5.600
+52004.00    -49.398 -5.542  -49.600 -5.400
+52005.00    -49.37  -5.44   -50.000 -5.500
+52006.00    -49.565 -5.436  -50.200 -5.500
+52007.00    -49.839 -5.535  -50.300 -5.500
+52008.00    -50.069 -5.6    -50.400 -5.500
+52009.00    -50.216 -5.543  -50.400 -5.500
+52010.00    -50.299 -5.457  -50.300 -5.600
+52011.00    -50.502 -5.557  -50.000 -5.600
+52012.00    -50.635 -5.74   -49.700 -5.600
+52013.00    -50.769 -5.911  -49.500 -5.600
+52014.00    -50.707 -5.95   -49.100 -5.700
+52015.00    -50.303 -5.886  -48.800 -5.800
+52016.00    -49.685 -5.814  -48.600 -5.800
+52017.00    -49.187 -5.762  -48.500 -5.800
+52018.00    -49.053 -5.683  -48.600 -5.900
+52019.00    -49.257 -5.545  -48.800 -5.900
+52020.00    -49.603 -5.39   -49.100 -5.900
+52021.00    -49.917 -5.317  -49.300 -5.900
+52022.00    -50.103 -5.408  -49.600 -5.900
+52023.00    -50.147 -5.648  -49.800 -6.000
+52024.00    -50.13  -5.922  -49.800 -6.000
+52025.00    -50.319 -6.143  -49.800 -6.000
+52026.00    -50.514 -6.178  -49.700 -6.100
+52027.00    -50.74  -6.152  -49.500 -6.100
+52028.00    -50.776 -6.154  -49.300 -6.200
+52029.00    -50.478 -6.198  -49.100 -6.100
+52030.00    -49.916 -6.223  -49.000 -6.200
+52031.00    -49.361 -6.169  -49.000 -6.200
+52032.00    -49.158 -6.06   -49.100 -6.100
+52033.00    -49.369 -5.928  -49.400 -6.200
+52034.00    -49.905 -5.879  -49.600 -6.200
+52035.00    -50.461 -5.93   -49.800 -5.900
+52036.00    -50.78  -5.998  -50.200 -5.900
+52037.00    -50.827 -6.001  -50.400 -5.900
+52038.00    -50.758 -5.956  -50.500 -6.100
+52039.00    -50.8   -5.985  -50.400 -6.200
+52040.00    -50.907 -6.067  -50.300 -6.300
+52041.00    -51.016 -6.164  -50.000 -6.400
+52042.00    -50.989 -6.207  -49.800 -6.400
+52043.00    -50.779 -6.214  -49.600 -6.400
+52044.00    -50.458 -6.243  -49.500 -6.300
+52045.00    -50.181 -6.288  -49.500 -6.300
+52046.00    -50.143 -6.271  -49.800 -6.100
+52047.00    -50.403 -6.182  -50.200 -6.000
+52048.00    -50.912 -6.028  -50.500 -5.900
+52049.00    -51.429 -5.874  -50.900 -5.900
+52050.00    -51.73  -5.801  -51.200 -5.900
+52051.00    -51.794 -5.87   -51.400 -6.000
+52052.00    -51.787 -6.069  -51.400 -6.100
+52053.00    -51.841 -6.275  -51.300 -6.300
+52054.00    -51.985 -6.385  -51.200 -6.400
+52055.00    -52.084 -6.357  -50.900 -6.500
+52056.00    -52.048 -6.267  -50.600 -6.500
+52057.00    -51.86  -6.203  -50.500 -6.400
+52058.00    -51.561 -6.177  -50.600 -6.300
+52059.00    -51.251 -6.15   -50.900 -6.200
+52060.00    -51.097 -6.125  -51.400 -6.000
+52061.00    -51.244 -6.036  -52.000 -5.900
+52062.00    -51.72  -5.948  -52.700 -5.800
+52063.00    -52.338 -5.884  -53.100 -5.700
+52064.00    -52.808 -5.848  -52.600 -5.600
+52065.00    -52.956 -5.839  -52.500 -5.700
+52066.00    -52.868 -5.872  -52.400 -5.800
+52067.00    -52.701 -5.941  -52.200 -6.100
+52068.00    -52.706 -6.044  -51.900 -6.400
+52069.00    -52.778 -6.101  -51.800 -6.600
+52070.00    -52.859 -6.102  -51.800 -6.700
+52071.00    -52.955 -6.113  -51.900 -6.800
+52072.00    -53.041 -6.179  -52.300 -6.700
+52073.00    -53.044 -6.245  -52.700 -6.400
+52074.00    -53.123 -6.189  -53.300 -6.200
+52075.00    -53.318 -6.073  -53.700 -5.900
+52076.00    -53.895 -5.936  -54.300 -5.700
+52077.00    -54.637 -5.811  -54.600 -5.500
+52078.00    -55.15  -5.682  -54.800 -5.400
+52079.00    -55.314 -5.593  -54.900 -5.500
+52080.00    -55.352 -5.648  -54.900 -5.600
+52081.00    -55.457 -5.813  -54.800 -5.700
+52082.00    -55.519 -6.047  -54.500 -5.800
+52083.00    -55.387 -6.118  -54.400 -6.000
+52084.00    -55.131 -6.019  -54.300 -6.100
+52085.00    -54.975 -5.893  -54.300 -6.100
+52086.00    -55.024 -5.851  -54.600 -6.100
+52087.00    -55.177 -5.87   -54.900 -6.000
+52088.00    -55.395 -5.88   -55.500 -6.000
+52089.00    -55.492 -5.84   -56.000 -5.900
+52090.00    -55.7   -5.779  -56.400 -5.800
+52091.00    -56.098 -5.717  -56.600 -5.700
+52092.00    -56.574 -5.664  -56.600 -5.700
+52093.00    -56.892 -5.662  -56.300 -5.700
+52094.00    -56.929 -5.763  -56.000 -5.800
+52095.00    -56.882 -5.943  -56.900 -6.000
+52096.00    -56.746 -6.098  -57.200 -6.100
+52097.00    -56.724 -6.097  -57.300 -6.100
+52098.00    -56.847 -5.961  -57.300 -6.000
+52099.00    -57.119 -5.844  -57.300 -6.000
+52100.00    -57.433 -5.847  -57.300 -6.000
+52101.00    -57.574 -5.891  -57.300 -5.900
+52102.00    -57.562 -5.843  -57.600 -5.900
+52103.00    -57.597 -5.707  -58.100 -5.800
+52104.00    -58.082 -5.628  -58.500 -5.800
+52105.00    -58.901 -5.654  -59.000 -5.900
+52106.00    -59.563 -5.671  -59.300 -5.800
+52107.00    -59.795 -5.608  -59.400 -5.700
+52108.00    -59.785 -5.582  -59.300 -5.600
+52109.00    -59.727 -5.746  -58.700 -5.500
+52110.00    -59.684 -5.995  -58.100 -5.400
+52111.00    -59.436 -6.113  -57.700 -5.400
+52112.00    -59.081 -6.02   -57.500 -5.500
+52113.00    -58.929 -5.875  -57.800 -5.500
+52114.00    -59.145 -5.833  -58.400 -5.700
+52115.00    -59.594 -5.858  -59.500 -5.900
+52116.00    -60.059 -5.815  -60.200 -6.000
+52117.00    -60.239 -5.745  -60.800 -6.100
+52118.00    -60.241 -5.735  -61.100 -6.100
+52119.00    -60.276 -5.819  -61.200 -6.000
+52120.00    -60.493 -5.916  -61.000 -6.100
+52121.00    -60.798 -5.972  -60.700 -6.100
+52122.00    -60.947 -6.043  -60.300 -6.000
+52123.00    -60.854 -6.157  -60.000 -6.100
+52124.00    -60.604 -6.249  -59.900 -6.000
+52125.00    -60.455 -6.162  -59.700 -5.900
+52126.00    -60.486 -5.89   -59.700 -5.700
+52127.00    -60.672 -5.623  -59.900 -5.700
+52128.00    -60.888 -5.527  -60.000 -5.600
+52129.00    -60.949 -5.555  -60.300 -5.600
+52130.00    -60.873 -5.546  -60.600 -5.600
+52131.00    -60.766 -5.456  -60.900 -5.700
+52132.00    -61.056 -5.438  -61.300 -5.700
+52133.00    -61.739 -5.583  -61.600 -5.800
+52134.00    -62.391 -5.769  -61.900 -5.800
+52135.00    -62.647 -5.835  -62.000 -5.900
+52136.00    -62.552 -5.807  -62.000 -5.900
+52137.00    -62.292 -5.825  -62.000 -5.900
+52138.00    -62.068 -5.896  -61.800 -5.800
+52139.00    -61.794 -5.859  -61.700 -5.700
+52140.00    -61.555 -5.665  -61.600 -5.700
+52141.00    -61.531 -5.49   -61.700 -5.600
+52142.00    -61.781 -5.49   -62.000 -5.500
+52143.00    -62.198 -5.571  -62.300 -5.500
+52144.00    -62.59  -5.547  -62.800 -5.500
+52145.00    -62.832 -5.426  -63.200 -5.500
+52146.00    -62.813 -5.43   -63.600 -5.600
+52147.00    -62.64  -5.661  -63.700 -5.700
+52148.00    -62.562 -5.953  -63.600 -5.800
+52149.00    -62.687 -6.089  -63.300 -5.900
+52150.00    -62.825 -6.058  -62.800 -6.000
+52151.00    -62.747 -5.994  -62.300 -5.900
+52152.00    -62.479 -5.946  -61.900 -5.800
+52153.00    -62.233 -5.817  -61.500 -5.800
+52154.00    -62.123 -5.551  -61.300 -5.500
+52155.00    -62.097 -5.258  -61.700 -4.700
+52156.00    -62.065 -5.105  -61.800 -4.900
+52157.00    -61.974 -5.114  -61.800 -5.100
+52158.00    -61.811 -5.156  -61.700 -5.100
+52159.00    -61.701 -5.158  -61.500 -5.000
+52160.00    -61.821 -5.181  -61.400 -4.900
+52161.00    -62.223 -5.312  -61.500 -5.000
+52162.00    -62.691 -5.504  -61.600 -5.200
+52163.00    -62.921 -5.625  -61.800 -5.400
+52164.00    -62.802 -5.617  -61.900 -5.600
+52165.00    -62.508 -5.557  -61.800 -5.700
+52166.00    -62.083 -5.391  -61.700 -5.700
+52167.00    -61.758 -5.1    -61.600 -5.500
+52168.00    -61.672 -4.738  -61.700 -5.400
+52169.00    -61.835 -4.519  -61.700 -5.200
+52170.00    -62.089 -4.59   -62.000 -5.100
+52171.00    -62.278 -4.809  -62.300 -5.000
+52172.00    -62.399 -4.899  -62.500 -4.900
+52173.00    -62.485 -4.809  -62.700 -4.900
+52174.00    -62.467 -4.784  -62.800 -5.000
+52175.00    -62.293 -5.012  -62.700 -5.000
+52176.00    -62.084 -5.354  -62.500 -5.200
+52177.00    -61.995 -5.511  -62.100 -5.400
+52178.00    -61.97  -5.388  -61.800 -5.500
+52179.00    -61.826 -5.158  -61.300 -5.600
+52180.00    -61.54  -5.002  -60.900 -5.400
+52181.00    -61.327 -4.868  -60.500 -5.300
+52182.00    -61.159 -4.73   -60.200 -5.100
+52183.00    -61.02  -4.515  -60.200 -4.800
+52184.00    -60.852 -4.319  -60.200 -4.600
+52185.00    -60.708 -4.243  -60.400 -4.400
+52186.00    -60.638 -4.286  -60.300 -4.300
+52187.00    -60.609 -4.376  -60.200 -4.300
+52188.00    -60.594 -4.416  -60.100 -4.300
+52189.00    -60.665 -4.487  -60.100 -4.400
+52190.00    -60.806 -4.557  -60.200 -4.500
+52191.00    -60.881 -4.608  -60.300 -4.500
+52192.00    -60.725 -4.602  -60.500 -4.400
+52193.00    -60.301 -4.494  -60.700 -4.100
+52194.00    -59.763 -4.243  -60.700 -3.700
+52195.00    -59.434 -3.774  -60.800 -3.200
+52196.00    -59.428 -3.358  -60.700 -2.900
+52197.00    -59.739 -3.137  -60.700 -2.900
+52198.00    -60.061 -3.245  -60.500 -3.100
+52199.00    -60.138 -3.553  -60.300 -3.600
+52200.00    -59.996 -3.771  -60.100 -4.100
+52201.00    -59.832 -3.767  -59.800 -4.500
+52202.00    -59.724 -3.718  -59.700 -4.900
+52203.00    -59.583 -3.803  -59.400 -5.000
+52204.00    -59.362 -3.998  -59.200 -4.700
+52205.00    -59.119 -4.072  -58.900 -4.400
+52206.00    -58.891 -3.907  -58.500 -4.000
+52207.00    -58.646 -3.644  -57.900 -3.700
+52208.00    -58.399 -3.492  -57.300 -3.400
+52209.00    -58.233 -3.479  -56.900 -3.300
+52210.00    -58.165 -3.457  -56.600 -3.200
+52211.00    -58.113 -3.292  -56.600 -3.200
+52212.00    -58.035 -3.013  -56.900 -3.100
+52213.00    -57.997 -2.778  -57.500 -3.000
+52214.00    -58.039 -2.727  -58.000 -2.800
+52215.00    -58.071 -2.858  -58.300 -2.900
+52216.00    -58.075 -2.983  -58.300 -2.900
+52217.00    -57.894 -3.079  -58.000 -3.000
+52218.00    -57.726 -3.062  -57.500 -3.100
+52219.00    -57.586 -3.002  -57.100 -3.100
+52220.00    -57.366 -2.957  -56.700 -3.000
+52221.00    -56.978 -2.896  -56.700 -2.700
+52222.00    -56.506 -2.745  -56.600 -2.300
+52223.00    -56.183 -2.422  -56.400 -1.800
+52224.00    -56.234 -2.145  -56.400 -1.500
+52225.00    -56.621 -1.998  -56.400 -1.400
+52226.00    -57.063 -2.076  -56.600 -1.700
+52227.00    -57.25  -2.311  -56.800 -2.400
+52228.00    -57.138 -2.507  -57.000 -2.600
+52229.00    -56.888 -2.54   -56.900 -2.600
+52230.00    -56.701 -2.458  -56.700 -2.700
+52231.00    -56.544 -2.428  -56.500 -2.500
+52232.00    -56.355 -2.463  -56.200 -2.500
+52233.00    -56.088 -2.443  -55.900 -2.400
+52234.00    -55.798 -2.295  -55.700 -2.300
+52235.00    -55.576 -2.119  -55.400 -2.200
+52236.00    -55.477 -2.063  -55.200 -1.800
+52237.00    -55.48  -2.121  -55.100 -1.600
+52238.00    -55.538 -2.153  -55.200 -1.500
+52239.00    -55.601 -1.994  -55.300 -1.300
+52240.00    -55.682 -1.653  -55.500 -1.300
+52241.00    -55.807 -1.298  -55.600 -1.300
+52242.00    -55.944 -1.132  -55.700 -1.400
+52243.00    -56.001 -1.236  -55.600 -1.600
+52244.00    -55.854 -1.497  -55.400 -1.800
+52245.00    -55.603 -1.723  -55.000 -1.800
+52246.00    -55.272 -1.766  -54.600 -1.900
+52247.00    -54.934 -1.659  -54.200 -1.800
+52248.00    -54.617 -1.531  -53.800 -1.600
+52249.00    -54.321 -1.461  -53.600 -1.300
+52250.00    -54.076 -1.43   -53.700 -1.100
+52251.00    -53.894 -1.389  -54.000 -0.900
+52252.00    -54.018 -1.326  -54.400 -0.700
+52253.00    -54.377 -1.286  -55.000 -0.500
+52254.00    -54.824 -1.304  -55.500 -0.500
+52255.00    -55.22  -1.361  -55.900 -0.600
+52256.00    -55.247 -1.421  -56.100 -0.800
+52257.00    -55.031 -1.435  -55.900 -1.000
+52258.00    -54.743 -1.424  -55.500 -1.200
+52259.00    -54.524 -1.446  -54.800 -1.400
+52260.00    -54.37  -1.487  -54.200 -1.600
+52261.00    -54.21  -1.48   -53.700 -1.600
+52262.00    -54.05  -1.401  -53.400 -1.400
+52263.00    -53.984 -1.336  -53.200 -1.200
+52264.00    -54.043 -1.379  -53.500 -0.900
+52265.00    -53.924 -1.588  -53.900 -0.600
+52266.00    -53.942 -1.631  -54.200 -0.500
+52267.00    -53.955 -1.498  -54.800 -0.400
+52268.00    -54.085 -1.216  -55.100 -0.600
+52269.00    -54.327 -0.902  -55.400 -0.700
+52270.00    -54.556 -0.691  -55.500 -0.800
+52271.00    -54.667 -0.692  -55.500 -1.000
+52272.00    -54.728 -0.941  -55.200 -1.000
+52273.00    -54.662 -1.294  -54.800 -1.000
+52274.00    -54.357 -1.518  -54.300 -0.900
+52275.00    -53.821 -1.481  -52.800 -1.100
+52276.00    -53.265 -1.268  -52.600 -1.200
+52277.00    -52.938 -1.076  -52.600 -1.100
+52278.00    -52.906 -1.021  -52.800 -1.100
+52279.00    -53.091 -1.064  -53.100 -1.000
+52280.00    -53.33  -1.116  -53.500 -0.900
+52281.00    -53.622 -1.132  -53.800 -0.900
+52282.00    -53.953 -1.12   -54.100 -0.800
+52283.00    -54.21  -1.105  -54.100 -0.800
+52284.00    -54.304 -1.081  -54.000 -0.900
+52285.00    -54.136 -1.087  -53.700 -1.000
+52286.00    -53.756 -1.161  -53.500 -1.200
+52287.00    -53.448 -1.31   -53.300 -1.400
+52288.00    -53.288 -1.459  -53.200 -1.500
+52289.00    -53.25  -1.511  -53.200 -1.600
+52290.00    -53.278 -1.462  -53.200 -1.600
+52291.00    -53.374 -1.419  -53.300 -1.600
+52292.00    -53.504 -1.476  -53.400 -1.500
+52293.00    -53.538 -1.62   -53.300 -1.400
+52294.00    -53.402 -1.665  -53.200 -1.300
+52295.00    -53.27  -1.611  -53.000 -1.200
+52296.00    -53.356 -1.52   -53.000 -1.200
+52297.00    -53.632 -1.427  -53.000 -1.200
+52298.00    -53.901 -1.315  -53.400 -1.200
+52299.00    -54.125 -1.241  -53.800 -1.200
+52300.00    -54.387 -1.352  -54.100 -1.400
+52301.00    -54.671 -1.735  -54.200 -1.700
+52302.00    -54.583 -2.157  -54.100 -1.900
+52303.00    -53.935 -2.303  -54.000 -2.200
+52304.00    -53.054 -2.1    -53.400 -2.100
+52305.00    -52.497 -1.785  -52.900 -1.900
+52306.00    -52.497 -1.619  -52.400 -1.600
+52307.00    -52.845 -1.638  -52.300 -1.500
+52308.00    -53.214 -1.696  -52.500 -1.400
+52309.00    -53.473 -1.725  -52.800 -1.400
+52310.00    -53.665 -1.751  -54.000 -1.400
+52311.00    -53.843 -1.804  -54.100 -1.500
+52312.00    -53.959 -1.858  -53.900 -1.600
+52313.00    -53.893 -1.909  -53.400 -1.800
+52314.00    -53.498 -2.001  -53.000 -1.900
+52315.00    -53.099 -2.173  -52.600 -2.000
+52316.00    -52.804 -2.328  -52.500 -2.100
+52317.00    -52.715 -2.341  -52.500 -2.100
+52318.00    -52.787 -2.211  -52.600 -2.100
+52319.00    -52.928 -2.084  -52.700 -2.000
+52320.00    -53.037 -2.09   -52.800 -2.000
+52321.00    -53.009 -2.215  -52.700 -2.000
+52322.00    -52.796 -2.298  -52.500 -2.100
+52323.00    -52.597 -2.35   -52.300 -2.100
+52324.00    -52.626 -2.458  -52.100 -2.100
+52325.00    -52.833 -2.622  -52.100 -2.200
+52326.00    -52.99  -2.701  -52.200 -2.400
+52327.00    -53.081 -2.644  -52.500 -2.700
+52328.00    -53.26  -2.679  -52.800 -3.000
+52329.00    -53.66  -2.97   -53.100 -3.300
+52330.00    -53.763 -3.449  -53.200 -3.600
+52331.00    -53.205 -3.74   -53.100 -3.700
+52332.00    -52.247 -3.628  -52.700 -3.700
+52333.00    -51.558 -3.297  -52.100 -3.400
+52334.00    -51.514 -3.071  -51.400 -3.000
+52335.00    -51.996 -3.026  -51.300 -2.700
+52336.00    -52.427 -3.06   -51.200 -2.400
+52337.00    -52.637 -3.081  -51.400 -2.400
+52338.00    -52.661 -3.165  -51.700 -2.500
+52339.00    -52.662 -3.359  -51.900 -2.800
+52340.00    -52.744 -3.56   -52.100 -3.100
+52341.00    -52.818 -3.656  -52.100 -3.500
+52342.00    -52.614 -3.662  -51.900 -3.700
+52343.00    -52.203 -3.678  -51.600 -3.800
+52344.00    -51.725 -3.677  -51.400 -3.700
+52345.00    -51.455 -3.552  -51.300 -3.500
+52346.00    -51.475 -3.291  -51.200 -3.300
+52347.00    -51.626 -3.058  -51.300 -3.200
+52348.00    -51.748 -3.018  -51.300 -3.100
+52349.00    -51.739 -3.159  -51.300 -3.000
+52350.00    -51.598 -3.339  -51.200 -3.100
+52351.00    -51.451 -3.494  -51.000 -3.200
+52352.00    -51.449 -3.689  -50.900 -3.300
+52353.00    -51.564 -3.948  -50.800 -3.500
+52354.00    -51.599 -4.144  -50.800 -3.700
+52355.00    -51.492 -4.169  -50.900 -4.000
+52356.00    -51.432 -4.139  -51.000 -4.400
+52357.00    -51.53  -4.282  -51.100 -4.700
+52358.00    -51.554 -4.608  -51.000 -4.900
+52359.00    -51.213 -4.844  -50.800 -4.900
+52360.00    -50.631 -4.779  -50.500 -4.800
+52361.00    -50.267 -4.51   -50.200 -4.500
+52362.00    -50.401 -4.327  -49.900 -4.300
+52363.00    -50.867 -4.318  -49.700 -4.100
+52364.00    -51.291 -4.347  -49.600 -4.100
+52365.00    -51.432 -4.34   -49.700 -4.200
+52366.00    -51.299 -4.416  -49.900 -4.400
+52367.00    -51.097 -4.663  -50.100 -4.700
+52368.00    -51.094 -4.944  -50.500 -4.900
+52369.00    -51.221 -5.06   -50.700 -5.000
+52370.00    -51.255 -4.972  -50.900 -5.000
+52371.00    -50.958 -4.815  -50.800 -4.900
+52372.00    -50.455 -4.67   -50.700 -4.700
+52373.00    -50.118 -4.481  -50.600 -4.400
+52374.00    -50.146 -4.205  -50.500 -4.100
+52375.00    -50.402 -3.956  -50.500 -4.000
+52376.00    -50.645 -3.903  -50.500 -3.900
+52377.00    -50.849 -4.084  -50.400 -4.000
+52378.00    -50.826 -4.365  -50.200 -4.200
+52379.00    -50.741 -4.611  -50.100 -4.400
+52380.00    -50.701 -4.802  -50.100 -4.600
+52381.00    -50.764 -4.957  -50.200 -4.800
+52382.00    -50.844 -5.11   -50.300 -5.000
+52383.00    -50.793 -5.191  -50.400 -5.100
+52384.00    -50.58  -5.218  -50.300 -5.200
+52385.00    -50.295 -5.273  -50.200 -5.300
+52386.00    -50.01  -5.37   -50.000 -5.300
+52387.00    -49.772 -5.391  -49.800 -5.300
+52388.00    -49.7   -5.246  -49.700 -5.200
+52389.00    -49.933 -5.033  -49.800 -5.100
+52390.00    -50.438 -4.937  -50.000 -4.900
+52391.00    -51.044 -4.99   -50.200 -4.800
+52392.00    -51.38  -5.04   -50.400 -4.800
+52393.00    -51.411 -5.008  -50.600 -4.900
+52394.00    -51.188 -5.017  -50.700 -5.100
+52395.00    -50.882 -5.204  -50.900 -5.400
+52396.00    -50.717 -5.482  -51.000 -5.600
+52397.00    -50.781 -5.625  -50.800 -5.600
+52398.00    -50.9   -5.519  -50.500 -5.500
+52399.00    -50.784 -5.34   -50.100 -5.300
+52400.00    -50.47  -5.202  -49.900 -4.900
+52401.00    -50.271 -5.088  -49.900 -4.500
+52402.00    -50.404 -4.919  -50.200 -4.400
+52403.00    -50.79  -4.708  -50.600 -4.400
+52404.00    -51.167 -4.598  -51.000 -4.600
+52405.00    -51.344 -4.696  -51.100 -4.800
+52406.00    -51.418 -4.959  -51.000 -5.000
+52407.00    -51.369 -5.248  -50.900 -5.200
+52408.00    -51.284 -5.441  -50.800 -5.300
+52409.00    -51.291 -5.527  -50.900 -5.400
+52410.00    -51.445 -5.558  -51.000 -5.500
+52411.00    -51.589 -5.604  -51.100 -5.500
+52412.00    -51.504 -5.67   -50.900 -5.500
+52413.00    -51.131 -5.711  -50.700 -5.500
+52414.00    -50.66  -5.665  -50.500 -5.400
+52415.00    -50.405 -5.503  -50.500 -5.300
+52416.00    -50.596 -5.264  -50.900 -5.300
+52417.00    -51.214 -5.064  -51.400 -5.200
+52418.00    -51.985 -5.008  -51.900 -5.100
+52419.00    -52.57  -5.081  -52.100 -4.900
+52420.00    -52.794 -5.152  -52.100 -4.800
+52421.00    -52.706 -5.138  -52.000 -4.800
+52422.00    -52.458 -5.122  -51.800 -4.900
+52423.00    -52.198 -5.234  -51.700 -5.000
+52424.00    -52.057 -5.455  -51.700 -5.300
+52425.00    -52.101 -5.618  -51.900 -5.600
+52426.00    -52.252 -5.62   -51.800 -5.700
+52427.00    -52.354 -5.534  -51.700 -5.600
+52428.00    -52.36  -5.478  -51.700 -5.500
+52429.00    -52.404 -5.446  -51.800 -5.300
+52430.00    -52.639 -5.335  -52.300 -5.100
+52431.00    -53.061 -5.113  -52.900 -5.000
+52432.00    -53.538 -4.888  -53.500 -5.000
+52433.00    -53.804 -4.835  -53.800 -5.100
+52434.00    -54.05  -4.977  -53.800 -5.200
+52435.00    -54.114 -5.253  -53.800 -5.300
+52436.00    -54.054 -5.506  -53.800 -5.400
+52437.00    -54.008 -5.62   -53.800 -5.500
+52438.00    -54.077 -5.607  -53.900 -5.500
+52439.00    -54.204 -5.568  -53.900 -5.500
+52440.00    -54.182 -5.589  -53.700 -5.500
+52441.00    -53.994 -5.603  -53.400 -5.500
+52442.00    -53.706 -5.541  -53.300 -5.500
+52443.00    -53.574 -5.371  -53.400 -5.400
+52444.00    -53.81  -5.149  -53.900 -5.200
+52445.00    -54.417 -4.97   -54.500 -5.000
+52446.00    -55.163 -4.896  -55.100 -4.800
+52447.00    -55.677 -4.937  -55.500 -4.700
+52448.00    -55.889 -4.997  -55.500 -4.700
+52449.00    -55.778 -5.051  -55.300 -4.800
+52450.00    -55.532 -5.117  -55.000 -5.000
+52451.00    -55.34  -5.242  -54.800 -5.200
+52452.00    -55.293 -5.406  -54.700 -5.500
+52453.00    -55.398 -5.518  -54.900 -5.600
+52454.00    -55.673 -5.563  -55.200 -5.700
+52455.00    -55.957 -5.524  -55.700 -5.600
+52456.00    -56.223 -5.51   -56.100 -5.400
+52457.00    -56.422 -5.49   -56.300 -5.300
+52458.00    -56.604 -5.365  -56.400 -5.300
+52459.00    -56.916 -5.12   -56.500 -5.300
+52460.00    -57.44  -4.873  -57.000 -5.300
+52461.00    -58.055 -4.771  -57.400 -5.300
+52462.00    -58.514 -4.874  -57.800 -5.300
+52463.00    -58.673 -5.132  -58.200 -5.300
+52464.00    -58.599 -5.431  -58.400 -5.300
+52465.00    -58.451 -5.639  -58.300 -5.300
+52466.00    -58.317 -5.675  -58.000 -5.400
+52467.00    -58.212 -5.573  -57.800 -5.400
+52468.00    -58.224 -5.447  -57.600 -5.500
+52469.00    -58.244 -5.392  -57.700 -5.500
+52470.00    -58.353 -5.388  -57.900 -5.400
+52471.00    -58.531 -5.362  -58.200 -5.300
+52472.00    -58.784 -5.277  -58.500 -5.300
+52473.00    -59.135 -5.159  -58.800 -5.200
+52474.00    -59.57  -5.056  -59.100 -5.200
+52475.00    -59.978 -5.05   -59.400 -5.100
+52476.00    -60.203 -5.063  -59.700 -5.100
+52477.00    -60.157 -5.15   -59.900 -5.100
+52478.00    -59.923 -5.304  -59.800 -5.100
+52479.00    -59.694 -5.477  -59.600 -5.200
+52480.00    -59.614 -5.58   -59.200 -5.300
+52481.00    -59.699 -5.544  -58.900 -5.400
+52482.00    -59.932 -5.396  -58.700 -5.400
+52483.00    -60.218 -5.262  -58.700 -5.300
+52484.00    -60.495 -5.219  -59.000 -5.200
+52485.00    -60.621 -5.202  -59.500 -5.100
+52486.00    -60.603 -5.096  -60.200 -5.100
+52487.00    -60.708 -4.915  -60.800 -5.000
+52488.00    -61.195 -4.807  -61.400 -5.000
+52489.00    -61.936 -4.876  -61.600 -5.100
+52490.00    -62.484 -5.071  -61.700 -5.200
+52491.00    -62.551 -5.284  -61.500 -5.300
+52492.00    -62.268 -5.471  -61.200 -5.400
+52493.00    -61.992 -5.63   -60.900 -5.400
+52494.00    -61.705 -5.649  -60.700 -5.300
+52495.00    -61.472 -5.498  -60.600 -5.300
+52496.00    -61.376 -5.272  -60.900 -5.200
+52497.00    -61.547 -5.161  -61.300 -5.200
+52498.00    -61.955 -5.238  -61.800 -5.200
+52499.00    -62.386 -5.385  -62.300 -5.200
+52500.00    -62.664 -5.44   -62.600 -5.200
+52501.00    -62.794 -5.369  -62.800 -5.200
+52502.00    -62.898 -5.259  -62.700 -5.300
+52503.00    -63.109 -5.181  -62.600 -5.300
+52504.00    -63.271 -5.171  -62.600 -5.300
+52505.00    -63.295 -5.225  -62.500 -5.300
+52506.00    -63.114 -5.344  -62.500 -5.300
+52507.00    -62.8   -5.503  -62.500 -5.400
+52508.00    -62.594 -5.53   -62.500 -5.300
+52509.00    -62.554 -5.346  -62.600 -5.300
+52510.00    -62.624 -5.006  -62.500 -5.100
+52511.00    -62.76  -4.726  -62.400 -5.000
+52512.00    -62.855 -4.64   -62.400 -4.800
+52513.00    -62.799 -4.68   -62.300 -4.700
+52514.00    -62.61  -4.689  -62.400 -4.600
+52515.00    -62.614 -4.648  -62.500 -4.600
+52516.00    -63.009 -4.718  -62.700 -4.700
+52517.00    -63.71  -4.964  -62.800 -4.800
+52518.00    -64.185 -5.236  -62.900 -4.900
+52519.00    -64.067 -5.341  -62.800 -5.100
+52520.00    -63.531 -5.274  -62.700 -5.100
+52521.00    -63.001 -5.163  -62.600 -5.100
+52522.00    -62.677 -5.043  -62.500 -5.000
+52523.00    -62.523 -4.839  -62.600 -4.900
+52524.00    -62.544 -4.586  -62.800 -4.900
+52525.00    -62.801 -4.485  -62.900 -4.900
+52526.00    -63.21  -4.652  -63.000 -4.900
+52527.00    -63.549 -4.924  -63.100 -4.900
+52528.00    -63.692 -5.056  -63.300 -4.900
+52529.00    -63.689 -4.974  -63.400 -4.900
+52530.00    -63.661 -4.873  -63.400 -4.900
+52531.00    -63.678 -4.891  -63.300 -4.900
+52532.00    -63.738 -4.972  -63.300 -4.900
+52533.00    -63.764 -5.008  -63.100 -4.900
+52534.00    -63.641 -4.999  -62.900 -4.800
+52535.00    -63.353 -4.995  -62.800 -4.800
+52536.00    -63.037 -4.949  -62.600 -4.700
+52537.00    -62.845 -4.74   -62.500 -4.600
+52538.00    -62.688 -4.357  -62.400 -4.400
+52539.00    -62.654 -4.03   -62.200 -4.300
+52540.00    -62.56  -3.932  -62.100 -4.100
+52541.00    -62.376 -4.04   -61.900 -4.100
+52542.00    -62.154 -4.177  -61.700 -4.100
+52543.00    -62.067 -4.266  -61.600 -4.200
+52544.00    -62.297 -4.404  -61.600 -4.400
+52545.00    -62.746 -4.656  -61.700 -4.500
+52546.00    -63.007 -4.88   -61.800 -4.600
+52547.00    -62.773 -4.869  -61.800 -4.600
+52548.00    -62.175 -4.617  -61.800 -4.500
+52549.00    -61.543 -4.279  -61.500 -4.200
+52550.00    -61.224 -4.028  -61.200 -3.800
+52551.00    -61.158 -3.786  -61.000 -3.600
+52552.00    -61.357 -3.547  -60.900 -3.600
+52553.00    -61.641 -3.467  -61.000 -3.800
+52554.00    -61.884 -3.665  -61.200 -4.000
+52555.00    -61.896 -3.967  -61.500 -4.100
+52556.00    -61.714 -4.071  -61.600 -4.000
+52557.00    -61.543 -3.931  -61.700 -3.800
+52558.00    -61.483 -3.811  -61.600 -3.700
+52559.00    -61.469 -3.917  -61.400 -3.700
+52560.00    -61.444 -4.13   -61.200 -3.700
+52561.00    -61.408 -4.193  -61.100 -3.800
+52562.00    -61.316 -4.051  -60.900 -3.900
+52563.00    -61.189 -3.878  -60.900 -3.900
+52564.00    -60.879 -3.75   -60.800 -3.700
+52565.00    -60.641 -3.602  -60.700 -3.500
+52566.00    -60.525 -3.349  -60.600 -3.300
+52567.00    -60.432 -3.074  -60.500 -3.100
+52568.00    -60.281 -2.956  -60.300 -3.100
+52569.00    -60.108 -3.046  -60.100 -3.100
+52570.00    -59.977 -3.223  -60.000 -3.100
+52571.00    -59.916 -3.365  -59.900 -3.200
+52572.00    -59.933 -3.478  -59.900 -3.400
+52573.00    -60.121 -3.625  -59.800 -3.500
+52574.00    -60.069 -3.722  -59.600 -3.500
+52575.00    -59.781 -3.67   -59.400 -3.500
+52576.00    -59.302 -3.449  -59.000 -3.300
+52577.00    -58.829 -3.171  -58.600 -3.100
+52578.00    -58.526 -2.923  -58.200 -2.800
+52579.00    -58.468 -2.682  -58.100 -2.600
+52580.00    -58.713 -2.44   -58.200 -2.500
+52581.00    -59.078 -2.33   -58.500 -2.400
+52582.00    -59.338 -2.461  -58.700 -2.500
+52583.00    -59.264 -2.7    -58.900 -2.500
+52584.00    -58.934 -2.773  -58.800 -2.400
+52585.00    -58.632 -2.613  -58.500 -2.400
+52586.00    -58.494 -2.47   -58.100 -2.400
+52587.00    -58.406 -2.575  -57.700 -2.400
+52588.00    -58.265 -2.822  -57.500 -2.400
+52589.00    -58.127 -2.898  -57.400 -2.500
+52590.00    -58.043 -2.689  -57.500 -2.500
+52591.00    -58.046 -2.389  -57.600 -2.500
+52592.00    -57.926 -2.198  -57.900 -2.400
+52593.00    -57.843 -2.109  -58.000 -2.200
+52594.00    -57.837 -1.975  -58.000 -2.000
+52595.00    -57.825 -1.757  -57.800 -1.700
+52596.00    -57.751 -1.586  -57.500 -1.600
+52597.00    -57.685 -1.59   -57.200 -1.600
+52598.00    -57.693 -1.754  -57.000 -1.700
+52599.00    -57.695 -1.957  -56.800 -1.900
+52600.00    -57.564 -2.096  -56.700 -2.100
+52601.00    -57.27  -2.145  -56.600 -2.200
+52602.00    -56.936 -2.143  -56.600 -2.200
+52603.00    -56.599 -2.102  -56.500 -2.100
+52604.00    -56.262 -2.032  -56.400 -2.000
+52605.00    -55.941 -1.938  -56.300 -2.000
+52606.00    -55.707 -1.807  -56.300 -1.800
+52607.00    -55.671 -1.616  -56.300 -1.600
+52608.00    -56.053 -1.385  -56.300 -1.300
+52609.00    -56.523 -1.234  -56.400 -1.100
+52610.00    -56.957 -1.261  -56.700 -1.500
+52611.00    -57.095 -1.407  -56.800 -1.400
+52612.00    -56.926 -1.485  -56.600 -1.300
+52613.00    -56.663 -1.411  -56.300 -1.300
+52614.00    -56.452 -1.326  -55.900 -1.300
+52615.00    -56.242 -1.406  -55.600 -1.300
+52616.00    -55.972 -1.596  -55.500 -1.400
+52617.00    -55.727 -1.66   -55.500 -1.400
+52618.00    -55.631 -1.48   -55.600 -1.400
+52619.00    -55.665 -1.203  -55.700 -1.300
+52620.00    -55.794 -1.033  -55.700 -1.200
+52621.00    -55.943 -0.985  -55.700 -1.000
+52622.00    -56.075 -0.905  -55.800 -0.800
+52623.00    -56.135 -0.706  -55.800 -0.600
+52624.00    -56.122 -0.487  -55.900 -0.400
+52625.00    -56.13  -0.424  -56.000 -0.500
+52626.00    -56.238 -0.58   -56.000 -0.600
+52627.00    -56.288 -0.884  -56.000 -0.800
+52628.00    -56.129 -1.142  -55.900 -1.100
+52629.00    -55.769 -1.188  -55.600 -1.300
+52630.00    -55.283 -1.132  -55.000 -1.400
+52631.00    -54.871 -1.044  -54.400 -1.500
+52632.00    -54.583 -1.015  -53.900 -1.400
+52633.00    -54.399 -1.032  -53.500 -1.300
+52634.00    -54.322 -1.015  -53.300 -1.100
+52635.00    -54.406 -0.91   -53.500 -0.900
+52636.00    -54.548 -0.74   -54.000 -0.700
+52637.00    -54.991 -0.587  -54.600 -0.500
+52638.00    -55.413 -0.527  -55.100 -0.400
+52639.00    -55.626 -0.568  -55.500 -0.400
+52640.00    -55.58  -0.644  -55.500 -0.500
+52641.00    -55.381 -0.698  -55.300 -0.600
+52642.00    -55.151 -0.756  -54.900 -0.700
+52643.00    -54.916 -0.876  -54.500 -0.800
+52644.00    -54.663 -1.025  -54.300 -0.900
+52645.00    -54.443 -1.079  -54.100 -1.000
+52646.00    -54.366 -0.977  -54.100 -1.000
+52647.00    -54.485 -0.817  -54.300 -1.000
+52648.00    -54.737 -0.733  -54.500 -0.900
+52649.00    -54.991 -0.724  -54.700 -0.800
+52650.00    -55.122 -0.632  -54.800 -0.600
+52651.00    -55.163 -0.462  -54.900 -0.400
+52652.00    -55.158 -0.272  -54.900 -0.300
+52653.00    -55.19  -0.227  -55.000 -0.300
+52654.00    -55.273 -0.412  -55.100 -0.600
+52655.00    -55.33  -0.762  -55.200 -0.900
+52656.00    -55.258 -1.113  -55.100 -1.100
+52657.00    -54.974 -1.297  -54.900 -1.300
+52658.00    -54.527 -1.257  -54.500 -1.300
+52659.00    -54.053 -1.086  -54.100 -1.100
+52660.00    -53.724 -0.943  -53.700 -1.000
+52661.00    -53.649 -0.913  -53.400 -0.900
+52662.00    -53.817 -0.956  -53.400 -0.900
+52663.00    -54.132 -0.979  -53.600 -0.900
+52664.00    -54.457 -0.916  -53.900 -0.900
+52665.00    -54.774 -0.812  -54.400 -0.800
+52666.00    -54.991 -0.705  -54.700 -0.700
+52667.00    -55.045 -0.652  -54.900 -0.700
+52668.00    -54.91  -0.689  -54.800 -0.800
+52669.00    -54.642 -0.837  -54.500 -0.900
+52670.00    -54.354 -1.031  -54.200 -1.100
+52671.00    -54.147 -1.238  -53.900 -1.200
+52672.00    -54.035 -1.388  -53.800 -1.200
+52673.00    -53.981 -1.417  -53.800 -1.200
+52674.00    -53.98  -1.337  -53.800 -1.200
+52675.00    -54.077 -1.247  -53.900 -1.200
+52676.00    -54.265 -1.235  -54.000 -1.200
+52677.00    -54.433 -1.276  -54.000 -1.200
+52678.00    -54.482 -1.273  -53.900 -1.200
+52679.00    -54.451 -1.207  -53.900 -1.100
+52680.00    -54.446 -1.168  -53.900 -1.100
+52681.00    -54.478 -1.246  -54.000 -1.300
+52682.00    -54.442 -1.434  -54.200 -1.500
+52683.00    -54.381 -1.706  -54.300 -1.900
+52684.00    -54.325 -2.01   -54.300 -2.100
+52685.00    -54.237 -2.272  -54.100 -2.200
+52686.00    -53.957 -2.366  -53.700 -2.100
+52687.00    -53.456 -2.23   -53.300 -1.900
+52688.00    -52.998 -1.976  -53.000 -1.800
+52689.00    -52.877 -1.828  -52.900 -1.700
+52690.00    -53.22  -1.863  -53.100 -1.900
+52691.00    -53.721 -2.012  -53.400 -2.000
+52692.00    -54.093 -2.117  -53.800 -2.100
+52693.00    -54.254 -2.103  -54.100 -2.000
+52694.00    -54.273 -2.014  -54.200 -2.000
+52695.00    -54.202 -1.938  -54.000 -1.900
+52696.00    -54.016 -1.948  -53.700 -1.900
+52697.00    -53.693 -2.073  -53.200 -2.000
+52698.00    -53.31  -2.286  -52.800 -2.200
+52699.00    -53.008 -2.471  -52.500 -2.200
+52700.00    -52.919 -2.57   -52.600 -2.300
+52701.00    -52.973 -2.491  -52.800 -2.300
+52702.00    -53.052 -2.302  -53.000 -2.200
+52703.00    -53.122 -2.166  -53.200 -2.200
+52704.00    -53.174 -2.176  -53.300 -2.200
+52705.00    -53.177 -2.289  -53.300 -2.200
+52706.00    -53.092 -2.393  -53.100 -2.300
+52707.00    -53.001 -2.479  -53.000 -2.400
+52708.00    -53.008 -2.63   -52.800 -2.600
+52709.00    -53.033 -2.864  -52.800 -2.700
+52710.00    -52.883 -3.071  -52.700 -2.900
+52711.00    -52.58  -3.187  -52.700 -3.100
+52712.00    -52.385 -3.316  -52.500 -3.300
+52713.00    -52.39  -3.571  -52.100 -3.400
+52714.00    -52.324 -3.839  -51.700 -3.500
+52715.00    -51.935 -3.868  -51.300 -3.600
+52716.00    -51.45  -3.601  -51.200 -3.600
+52717.00    -51.354 -3.289  -51.300 -3.600
+52718.00    -51.788 -3.21   -51.700 -3.500
+52719.00    -52.385 -3.369  -52.100 -3.500
+52720.00    -52.733 -3.562  -52.500 -3.500
+52721.00    -52.701 -3.638  -52.600 -3.500
+52722.00    -52.52  -3.643  -52.500 -3.500
+52723.00    -52.377 -3.669  -52.200 -3.600
+52724.00    -52.275 -3.735  -51.900 -3.800
+52725.00    -52.098 -3.813  -51.700 -3.900
+52726.00    -51.784 -3.895  -51.500 -3.900
+52727.00    -51.437 -3.957  -51.500 -3.800
+52728.00    -51.244 -3.908  -51.500 -3.700
+52729.00    -51.28  -3.679  -51.500 -3.500
+52730.00    -51.438 -3.347  -51.400 -3.400
+52731.00    -51.553 -3.109  -51.200 -3.300
+52732.00    -51.586 -3.153  -51.000 -3.400
+52733.00    -51.514 -3.39   -50.800 -3.500
+52734.00    -51.368 -3.641  -50.800 -3.700
+52735.00    -51.258 -3.842  -50.900 -3.900
+52736.00    -51.285 -4.074  -51.000 -4.100
+52737.00    -51.342 -4.359  -51.100 -4.200
+52738.00    -51.174 -4.558  -50.900 -4.300
+52739.00    -50.751 -4.567  -50.700 -4.400
+52740.00    -50.391 -4.532  -50.300 -4.600
+52741.00    -50.343 -4.688  -49.900 -4.700
+52742.00    -50.418 -5.004  -49.600 -4.900
+52743.00    -50.297 -5.153  -49.600 -4.900
+52744.00    -50.073 -4.923  -49.800 -4.800
+52745.00    -50.363 -4.461  -50.200 -4.600
+52746.00    -50.934 -4.223  -50.700 -4.300
+52747.00    -51.604 -4.276  -51.000 -4.200
+52748.00    -51.877 -4.406  -51.100 -4.200
+52749.00    -51.679 -4.532  -50.900 -4.400
+52750.00    -51.252 -4.668  -50.700 -4.700
+52751.00    -50.908 -4.882  -50.500 -4.900
+52752.00    -50.782 -5.082  -50.400 -5.100
+52753.00    -50.792 -5.122  -50.400 -5.100
+52754.00    -50.741 -5.002  -50.500 -4.900
+52755.00    -50.54  -4.824  -50.400 -4.700
+52756.00    -50.334 -4.628  -50.300 -4.500
+52757.00    -50.344 -4.349  -50.300 -4.200
+52758.00    -50.59  -4.013  -50.400 -4.000
+52759.00    -50.875 -3.814  -50.800 -3.900
+52760.00    -51.014 -3.925  -51.100 -3.900
+52761.00    -50.976 -4.288  -51.200 -4.100
+52762.00    -50.818 -4.673  -51.100 -4.400
+52763.00    -50.705 -4.909  -50.900 -4.800
+52764.00    -50.721 -5.059  -50.700 -5.100
+52765.00    -50.831 -5.218  -50.600 -5.200
+52766.00    -50.83  -5.344  -50.400 -5.300
+52767.00    -50.584 -5.339  -50.300 -5.300
+52768.00    -50.24  -5.263  -50.300 -5.300
+52769.00    -49.972 -5.277  -50.100 -5.400
+52770.00    -49.993 -5.449  -49.900 -5.400
+52771.00    -50.086 -5.525  -49.900 -5.400
+52772.00    -50.269 -5.298  -50.000 -5.300
+52773.00    -50.726 -4.887  -50.600 -5.100
+52774.00    -51.457 -4.605  -51.200 -4.800
+52775.00    -52.127 -4.587  -51.700 -4.600
+52776.00    -52.379 -4.675  -51.900 -4.500
+52777.00    -52.128 -4.799  -51.600 -4.700
+52778.00    -51.589 -4.999  -51.200 -4.900
+52779.00    -51.061 -5.335  -50.800 -5.200
+52780.00    -50.794 -5.642  -50.600 -5.400
+52781.00    -50.863 -5.672  -50.600 -5.500
+52782.00    -51.09  -5.399  -50.900 -5.400
+52783.00    -51.212 -5.042  -51.200 -5.100
+52784.00    -51.203 -4.775  -51.400 -4.800
+52785.00    -51.287 -4.572  -51.700 -4.500
+52786.00    -51.609 -4.366  -51.800 -4.300
+52787.00    -51.982 -4.234  -52.000 -4.300
+52788.00    -52.26  -4.353  -52.100 -4.500
+52789.00    -52.338 -4.716  -52.200 -4.700
+52790.00    -52.3   -5.116  -52.100 -5.000
+52791.00    -52.244 -5.342  -52.000 -5.100
+52792.00    -52.247 -5.371  -51.900 -5.200
+52793.00    -52.359 -5.329  -51.900 -5.200
+52794.00    -52.524 -5.312  -52.000 -5.300
+52795.00    -52.585 -5.308  -52.100 -5.400
+52796.00    -52.455 -5.286  -52.300 -5.400
+52797.00    -52.218 -5.218  -52.300 -5.300
+52798.00    -52.115 -5.183  -52.400 -5.200
+52799.00    -52.278 -5.064  -52.600 -4.900
+52800.00    -52.767 -4.808  -52.800 -4.700
+52801.00    -53.549 -4.534  -53.100 -4.500
+52802.00    -54.346 -4.383  -53.400 -4.500
+52803.00    -54.883 -4.43   -53.700 -4.500
+52804.00    -55.004 -4.554  -54.000 -4.700
+52805.00    -54.781 -4.661  -54.100 -4.900
+52806.00    -54.378 -4.826  -54.100 -5.100
+52807.00    -53.954 -5.129  -54.100 -5.300
+52808.00    -53.629 -5.435  -53.900 -5.400
+52809.00    -53.717 -5.479  -53.800 -5.300
+52810.00    -54.102 -5.203  -53.800 -5.200
+52811.00    -54.527 -4.827  -53.800 -5.000
+52812.00    -54.812 -4.589  -54.100 -4.800
+52813.00    -55.043 -4.499  -54.400 -4.600
+52814.00    -55.376 -4.425  -54.900 -4.400
+52815.00    -55.789 -4.346  -55.400 -4.400
+52816.00    -56.129 -4.388  -55.900 -4.400
+52817.00    -56.334 -4.638  -56.200 -4.500
+52818.00    -56.407 -4.976  -56.400 -4.700
+52819.00    -56.445 -5.234  -56.300 -4.900
+52820.00    -56.421 -5.271  -56.200 -5.100
+52821.00    -56.414 -5.141  -56.200 -5.200
+52822.00    -56.477 -5.03   -56.200 -5.100
+52823.00    -56.63  -4.988  -56.400 -5.000
+52824.00    -56.681 -5.024  -56.500 -4.800
+52825.00    -56.584 -5.033  -56.500 -4.700
+52826.00    -56.504 -4.928  -56.600 -4.600
+52827.00    -56.69  -4.711  -56.800 -4.500
+52828.00    -57.246 -4.463  -57.000 -4.500
+52829.00    -58.023 -4.301  -57.400 -4.400
+52830.00    -58.701 -4.3    -57.800 -4.400
+52831.00    -59.026 -4.431  -58.100 -4.400
+52832.00    -58.947 -4.642  -58.200 -4.400
+52833.00    -58.73  -4.737  -58.100 -4.400
+52834.00    -58.502 -4.826  -58.000 -4.500
+52835.00    -58.316 -4.986  -58.000 -4.800
+52836.00    -58.214 -5.159  -58.200 -5.100
+52837.00    -58.31  -5.182  -58.500 -5.200
+52838.00    -58.665 -4.996  -59.000 -5.000
+52839.00    -59.164 -4.774  -59.500 -4.900
+52840.00    -59.61  -4.637  -59.900 -4.700
+52841.00    -59.92  -4.622  -60.300 -4.600
+52842.00    -60.157 -4.602  -60.400 -4.500
+52843.00    -60.399 -4.523  -60.400 -4.500
+52844.00    -60.655 -4.497  -60.300 -4.500
+52845.00    -60.884 -4.654  -60.300 -4.500
+52846.00    -60.932 -4.999  -60.400 -4.600
+52847.00    -60.93  -5.298  -60.600 -4.800
+52848.00    -60.779 -5.41   -60.700 -5.000
+52849.00    -60.583 -5.305  -60.800 -5.200
+52850.00    -60.43  -5.113  -60.700 -5.200
+52851.00    -60.469 -4.992  -60.500 -5.200
+52852.00    -60.57  -5.017  -60.300 -5.100
+52853.00    -60.663 -5.101  -60.300 -5.000
+52854.00    -60.785 -5.106  -60.500 -4.900
+52855.00    -61.041 -4.981  -60.900 -5.100
+52856.00    -61.473 -4.8    -61.300 -4.700
+52857.00    -61.973 -4.676  -61.700 -4.600
+52858.00    -62.345 -4.658  -62.000 -4.600
+52859.00    -62.45  -4.723  -62.200 -4.700
+52860.00    -62.304 -4.828  -62.200 -4.700
+52861.00    -62.063 -4.892  -62.000 -4.800
+52862.00    -61.866 -4.93   -61.800 -4.900
+52863.00    -61.759 -4.952  -61.500 -4.900
+52864.00    -61.729 -4.936  -61.300 -5.000
+52865.00    -61.792 -4.837  -61.300 -4.900
+52866.00    -62.004 -4.668  -61.500 -4.700
+52867.00    -62.371 -4.537  -61.800 -4.500
+52868.00    -62.774 -4.52   -62.200 -4.400
+52869.00    -63.052 -4.575  -62.600 -4.400
+52870.00    -63.148 -4.583  -63.000 -4.400
+52871.00    -63.177 -4.521  -63.200 -4.500
+52872.00    -63.28  -4.508  -63.300 -4.700
+52873.00    -63.427 -4.657  -63.400 -4.800
+52874.00    -63.524 -4.911  -63.300 -4.900
+52875.00    -63.294 -5.146  -63.300 -5.000
+52876.00    -62.925 -5.216  -63.100 -5.000
+52877.00    -62.62  -5.104  -62.900 -5.000
+52878.00    -62.496 -4.889  -62.700 -4.900
+52879.00    -62.525 -4.691  -62.500 -4.800
+52880.00    -62.673 -4.655  -62.400 -4.700
+52881.00    -62.908 -4.78   -62.400 -4.700
+52882.00    -63.199 -4.951  -62.700 -4.600
+52883.00    -63.49  -5.018  -63.000 -4.600
+52884.00    -63.733 -4.937  -63.300 -4.500
+52885.00    -63.905 -4.779  -63.500 -4.500
+52886.00    -63.983 -4.648  -63.600 -4.500
+52887.00    -63.941 -4.591  -63.500 -4.600
+52888.00    -63.67  -4.587  -63.300 -4.600
+52889.00    -63.406 -4.632  -63.100 -4.700
+52890.00    -63.134 -4.67   -62.900 -4.700
+52891.00    -62.942 -4.645  -62.800 -4.600
+52892.00    -62.871 -4.506  -62.800 -4.500
+52893.00    -62.895 -4.26   -62.900 -4.300
+52894.00    -62.988 -4.007  -63.100 -4.100
+52895.00    -63.229 -3.929  -63.300 -3.900
+52896.00    -63.451 -4.011  -63.400 -3.800
+52897.00    -63.6   -4.181  -63.600 -3.900
+52898.00    -63.576 -4.279  -63.600 -4.100
+52899.00    -63.473 -4.285  -63.600 -4.300
+52900.00    -63.463 -4.331  -63.400 -4.500
+52901.00    -63.51  -4.5    -63.100 -4.600
+52902.00    -63.385 -4.688  -62.700 -4.700
+52903.00    -62.909 -4.743  -62.300 -4.700
+52904.00    -62.352 -4.629  -61.900 -4.600
+52905.00    -62.056 -4.439  -61.700 -4.500
+52906.00    -62.092 -4.242  -61.700 -4.400
+52907.00    -62.279 -4.059  -61.800 -4.200
+52908.00    -62.478 -3.95   -62.100 -4.100
+52909.00    -62.681 -4.013  -62.400 -4.100
+52910.00    -62.868 -4.232  -62.700 -4.100
+52911.00    -62.96  -4.424  -62.900 -4.200
+52912.00    -62.943 -4.416  -63.000 -4.300
+52913.00    -62.9   -4.236  -63.100 -4.300
+52914.00    -62.886 -4.063  -63.000 -4.200
+52915.00    -62.846 -4.019  -62.800 -4.200
+52916.00    -62.688 -4.072  -62.400 -4.100
+52917.00    -62.392 -4.127  -62.000 -4.000
+52918.00    -62.034 -4.134  -61.600 -4.000
+52919.00    -61.739 -4.07   -61.400 -3.800
+52920.00    -61.621 -3.933  -61.500 -3.700
+52921.00    -61.614 -3.63   -61.500 -3.600
+52922.00    -61.646 -3.308  -61.300 -3.400
+52923.00    -61.667 -3.14   -61.100 -3.300
+52924.00    -61.667 -3.262  -61.100 -3.300
+52925.00    -61.634 -3.533  -61.200 -3.400
+52926.00    -61.524 -3.742  -61.300 -3.600
+52927.00    -61.38  -3.818  -61.300 -3.800
+52928.00    -61.312 -3.88   -61.200 -4.000
+52929.00    -61.273 -4.01   -60.900 -4.100
+52930.00    -61.048 -4.108  -60.500 -4.000
+52931.00    -60.491 -3.997  -60.000 -3.900
+52932.00    -59.908 -3.728  -59.600 -3.700
+52933.00    -59.673 -3.487  -59.400 -3.400
+52934.00    -59.826 -3.349  -59.500 -3.200
+52935.00    -60.112 -3.211  -59.700 -3.000
+52936.00    -60.338 -3.02   -60.100 -2.900
+52937.00    -60.532 -2.919  -60.300 -2.900
+52938.00    -60.561 -3.018  -60.300 -2.900
+52939.00    -60.39  -3.198  -60.200 -3.000
+52940.00    -60.09  -3.224  -60.000 -3.100
+52941.00    -59.883 -3.071  -59.900 -3.200
+52942.00    -59.873 -2.958  -59.700 -3.300
+52943.00    -59.915 -3.04   -59.600 -3.400
+52944.00    -59.866 -3.211  -59.400 -3.400
+52945.00    -59.622 -3.24   -59.400 -3.200
+52946.00    -59.334 -3.088  -59.200 -3.100
+52947.00    -59.11  -2.873  -59.000 -2.900
+52948.00    -59.009 -2.665  -58.900 -2.800
+52949.00    -59.02  -2.429  -58.900 -2.700
+52950.00    -59.05  -2.17   -58.900 -2.300
+52951.00    -59.077 -2.023  -58.900 -2.000
+52952.00    -58.943 -2.138  -58.900 -2.100
+52953.00    -58.8   -2.438  -58.900 -2.300
+52954.00    -58.676 -2.706  -58.800 -2.600
+52955.00    -58.557 -2.815  -58.600 -2.800
+52956.00    -58.441 -2.843  -58.300 -2.900
+52957.00    -58.287 -2.892  -57.900 -2.800
+52958.00    -57.999 -2.888  -57.600 -2.800
+52959.00    -57.52  -2.754  -57.300 -2.600
+52960.00    -57.072 -2.507  -57.000 -2.500
+52961.00    -56.911 -2.325  -56.800 -2.300
+52962.00    -57.003 -2.27   -56.800 -2.200
+52963.00    -57.258 -2.177  -56.900 -2.000
+52964.00    -57.539 -1.93   -57.100 -1.900
+52965.00    -57.855 -1.673  -57.300 -1.900
+52966.00    -58.088 -1.631  -57.500 -1.900
+52967.00    -58.025 -1.781  -57.600 -1.900
+52968.00    -57.674 -1.877  -57.400 -1.900
+52969.00    -57.318 -1.819  -57.100 -1.800
+52970.00    -57.158 -1.792  -56.700 -1.800
+52971.00    -57.1   -1.954  -56.300 -1.700
+52972.00    -57.013 -2.151  -56.200 -1.700
+52973.00    -56.869 -2.095  -56.300 -1.600
+52974.00    -56.817 -1.743  -56.500 -1.400
+52975.00    -56.871 -1.344  -56.800 -1.300
+52976.00    -56.964 -1.114  -57.000 -1.100
+52977.00    -57.058 -1.023  -57.000 -1.000
+52978.00    -57.11  -0.946  -57.000 -1.000
+52979.00    -57.055 -0.894  -57.000 -1.000
+52980.00    -56.885 -1.002  -56.900 -1.200
+52981.00    -56.717 -1.276  -56.800 -1.300
+52982.00    -56.625 -1.554  -56.700 -1.500
+52983.00    -56.545 -1.686  -56.400 -1.600
+52984.00    -56.362 -1.683  -56.000 -1.700
+52985.00    -56.048 -1.653  -55.500 -1.700
+52986.00    -55.658 -1.633  -55.000 -1.700
+52987.00    -55.274 -1.574  -54.700 -1.600
+52988.00    -54.999 -1.473  -54.500 -1.500
+52989.00    -54.906 -1.405  -54.600 -1.400
+52990.00    -54.912 -1.396  -54.800 -1.500
+52991.00    -55.073 -1.304  -55.000 -1.300
+52992.00    -55.383 -1.057  -55.200 -1.100
+52993.00    -55.907 -0.787  -55.500 -0.900
+52994.00    -56.487 -0.727  -55.800 -0.800
+52995.00    -56.792 -0.907  -56.000 -0.900
+52996.00    -56.671 -1.113  -56.200 -1.000
+52997.00    -56.269 -1.155  -56.100 -1.200
+52998.00    -55.891 -1.176  -55.900 -1.400
+52999.00    -55.553 -1.292  -55.800 -1.500
+53000.00    -55.263 -1.407  -55.600 -1.400
+53001.00    -55.121 -1.284  -55.600 -1.100
+53002.00    -55.265 -0.881  -55.600 -0.800
+53003.00    -55.612 -0.464  -55.800 -0.500
+53004.00    -55.957 -0.296  -55.900 -0.200
+53005.00    -56.182 -0.356  -56.100 -0.100
+53006.00    -56.267 -0.447  -56.100 -0.200
+53007.00    -56.23  -0.51   -56.000 -0.400
+53008.00    -56.014 -0.595  -55.900 -0.600
+53009.00    -55.791 -0.81   -55.700 -0.900
+53010.00    -55.682 -1.079  -55.500 -1.000
+53011.00    -55.62  -1.244  -55.200 -1.100
+53012.00    -55.433 -1.241  -54.900 -1.100
+53013.00    -55.072 -1.14   -54.600 -1.100
+53014.00    -54.671 -1.05   -54.400 -1.200
+53015.00    -54.387 -1.023  -54.200 -1.300
+53016.00    -54.273 -1.041  -54.100 -1.300
+53017.00    -54.289 -1.066  -54.100 -1.100
+53018.00    -54.306 -1.052  -54.100 -0.700
+53019.00    -54.461 -0.939  -54.400 -0.600
+53020.00    -54.74  -0.738  -54.900 -0.600
+53021.00    -55.192 -0.564  -55.300 -0.700
+53022.00    -55.71  -0.569  -55.700 -0.700
+53023.00    -56.056 -0.777  -55.900 -0.800
+53024.00    -56.077 -1.037  -55.900 -0.900
+53025.00    -55.842 -1.234  -55.600 -1.100
+53026.00    -55.472 -1.277  -55.300 -1.200
+53027.00    -55.057 -1.314  -54.900 -1.300
+53028.00    -54.694 -1.358  -54.800 -1.300
+53029.00    -54.517 -1.256  -54.800 -1.100
+53030.00    -54.69  -1.005  -55.000 -0.900
+53031.00    -55.141 -0.78   -55.300 -0.700
+53032.00    -55.636 -0.764  -55.500 -0.700
+53033.00    -55.982 -0.922  -55.700 -0.800
+53034.00    -56.103 -1.066  -55.700 -1.000
+53035.00    -55.988 -1.133  -55.600 -1.200
+53036.00    -55.661 -1.171  -55.300 -1.300
+53037.00    -55.286 -1.332  -55.000 -1.500
+53038.00    -55.04  -1.596  -54.800 -1.600
+53039.00    -54.939 -1.815  -54.600 -1.700
+53040.00    -54.847 -1.866  -54.500 -1.700
+53041.00    -54.656 -1.756  -54.400 -1.800
+53042.00    -54.412 -1.598  -54.300 -1.800
+53043.00    -54.251 -1.522  -54.200 -1.700
+53044.00    -54.236 -1.559  -54.300 -1.600
+53045.00    -54.363 -1.64   -54.300 -1.500
+53046.00    -54.587 -1.669  -54.500 -1.400
+53047.00    -54.851 -1.607  -54.700 -1.300
+53048.00    -55.095 -1.498  -54.900 -1.300
+53049.00    -55.325 -1.423  -55.100 -1.300
+53050.00    -55.385 -1.463  -55.100 -1.400
+53051.00    -55.305 -1.621  -55.100 -1.500
+53052.00    -55.105 -1.83   -54.900 -1.800
+53053.00    -54.856 -1.995  -54.600 -2.000
+53054.00    -54.616 -2.072  -54.400 -2.100
+53055.00    -54.378 -2.117  -54.300 -2.100
+53056.00    -54.168 -2.091  -54.300 -2.100
+53057.00    -54.053 -2.024  -54.300 -2.000
+53058.00    -54.143 -1.939  -54.400 -1.900
+53059.00    -54.46  -1.922  -54.500 -1.900
+53060.00    -54.885 -2.035  -54.600 -2.000
+53061.00    -55.23  -2.216  -54.700 -2.200
+53062.00    -55.343 -2.33   -54.600 -2.400
+53063.00    -55.261 -2.309  -54.500 -2.500
+53064.00    -54.831 -2.338  -54.200 -2.600
+53065.00    -54.292 -2.495  -53.900 -2.600
+53066.00    -53.828 -2.763  -53.600 -2.700
+53067.00    -53.572 -3.017  -53.400 -2.900
+53068.00    -53.53  -3.146  -53.300 -3.100
+53069.00    -53.585 -3.125  -53.100 -3.200
+53070.00    -53.658 -2.977  -53.000 -3.200
+53071.00    -53.59  -2.832  -52.900 -3.000
+53072.00    -53.561 -2.758  -53.000 -2.800
+53073.00    -53.713 -2.786  -53.300 -2.700
+53074.00    -54.06  -2.873  -54.000 -2.800
+53075.00    -54.444 -2.951  -54.400 -2.900
+53076.00    -54.663 -2.992  -54.600 -3.000
+53077.00    -54.689 -2.989  -54.500 -3.100
+53078.00    -54.399 -3.02   -54.100 -3.100
+53079.00    -53.973 -3.087  -53.500 -3.100
+53080.00    -53.526 -3.199  -52.900 -3.100
+53081.00    -53.153 -3.328  -52.600 -3.200
+53082.00    -52.919 -3.416  -52.600 -3.300
+53083.00    -52.835 -3.414  -52.700 -3.400
+53084.00    -52.84  -3.307  -52.800 -3.400
+53085.00    -52.883 -3.163  -53.000 -3.300
+53086.00    -52.936 -3.065  -53.100 -3.200
+53087.00    -53.051 -3.096  -53.100 -3.200
+53088.00    -53.258 -3.257  -53.100 -3.200
+53089.00    -53.471 -3.447  -53.000 -3.400
+53090.00    -53.538 -3.556  -53.000 -3.600
+53091.00    -53.405 -3.587  -52.800 -3.700
+53092.00    -53.051 -3.674  -52.600 -3.900
+53093.00    -52.56  -3.881  -52.400 -4.000
+53094.00    -52.01  -4.14   -52.000 -4.100
+53095.00    -51.575 -4.347  -51.700 -4.300
+53096.00    -51.461 -4.481  -51.400 -4.500
+53097.00    -51.665 -4.562  -51.300 -4.600
+53098.00    -51.948 -4.493  -51.400 -4.600
+53099.00    -52.016 -4.318  -51.600 -4.400
+53100.00    -52.007 -4.039  -52.100 -4.100
+53101.00    -52.215 -3.846  -52.500 -4.000
+53102.00    -52.703 -3.878  -52.700 -4.100
+53103.00    -53.187 -4.088  -53.000 -4.100
+53104.00    -53.342 -4.317  -53.300 -4.200
+53105.00    -53.112 -4.46   -53.200 -4.200
+53106.00    -52.691 -4.524  -52.800 -4.300
+53107.00    -52.262 -4.562  -52.300 -4.400
+53108.00    -51.886 -4.603  -51.800 -4.500
+53109.00    -51.56  -4.641  -51.500 -4.600
+53110.00    -51.317 -4.643  -51.300 -4.500
+53111.00    -51.236 -4.559  -51.200 -4.400
+53112.00    -51.344 -4.359  -51.200 -4.200
+53113.00    -51.543 -4.089  -51.300 -3.900
+53114.00    -51.689 -3.888  -51.300 -3.800
+53115.00    -51.74  -3.894  -51.300 -3.700
+53116.00    -51.66  -4.075  -51.300 -3.900
+53117.00    -51.707 -4.367  -51.200 -4.100
+53118.00    -51.718 -4.562  -51.200 -4.400
+53119.00    -51.588 -4.654  -51.200 -4.700
+53120.00    -51.481 -4.778  -51.200 -4.900
+53121.00    -51.281 -4.997  -51.100 -5.100
+53122.00    -50.896 -5.203  -51.000 -5.200
+53123.00    -50.413 -5.284  -50.700 -5.200
+53124.00    -50.16  -5.302  -50.400 -5.300
+53125.00    -50.344 -5.381  -50.300 -5.200
+53126.00    -50.751 -5.461  -50.300 -5.100
+53127.00    -51.038 -5.319  -50.500 -4.800
+53128.00    -51.22  -4.895  -51.000 -4.600
+53129.00    -51.608 -4.458  -51.600 -4.500
+53130.00    -52.325 -4.36   -52.200 -4.500
+53131.00    -52.882 -4.611  -52.600 -4.700
+53132.00    -52.928 -4.982  -52.800 -5.000
+53133.00    -52.484 -5.252  -52.700 -5.200
+53134.00    -51.911 -5.4    -52.300 -5.400
+53135.00    -51.517 -5.483  -51.900 -5.500
+53136.00    -51.348 -5.489  -51.400 -5.500
+53137.00    -51.294 -5.393  -51.100 -5.400
+53138.00    -51.244 -5.179  -51.000 -5.200
+53139.00    -51.228 -4.938  -51.100 -4.900
+53140.00    -51.342 -4.688  -51.400 -4.500
+53141.00    -51.607 -4.428  -51.700 -4.300
+53142.00    -51.895 -4.242  -52.000 -4.200
+53143.00    -52.053 -4.287  -52.100 -4.300
+53144.00    -52.067 -4.613  -52.100 -4.600
+53145.00    -52.023 -5.047  -52.100 -5.000
+53146.00    -51.996 -5.335  -52.200 -5.300
+53147.00    -51.986 -5.396  -52.400 -5.400
+53148.00    -52.101 -5.402  -52.600 -5.400
+53149.00    -52.215 -5.476  -52.500 -5.400
+53150.00    -52.133 -5.552  -52.100 -5.400
+53151.00    -51.802 -5.497  -51.500 -5.600
+53152.00    -51.502 -5.362  -51.100 -5.600
+53153.00    -51.572 -5.327  -51.200 -5.500
+53154.00    -51.996 -5.346  -51.600 -5.200
+53155.00    -52.507 -5.277  -52.200 -4.900
+53156.00    -52.991 -4.908  -53.000 -4.600
+53157.00    -53.601 -4.453  -53.800 -4.300
+53158.00    -54.338 -4.292  -54.300 -4.200
+53159.00    -54.846 -4.528  -54.600 -4.400
+53160.00    -54.789 -4.911  -54.500 -4.700
+53161.00    -54.246 -5.194  -54.400 -5.000
+53162.00    -53.616 -5.367  -54.200 -5.100
+53163.00    -53.236 -5.497  -54.000 -5.200
+53164.00    -53.205 -5.507  -53.700 -5.300
+53165.00    -53.438 -5.272  -53.300 -5.400
+53166.00    -53.752 -4.856  -53.400 -5.100
+53167.00    -53.995 -4.488  -53.700 -4.600
+53168.00    -54.173 -4.302  -53.900 -4.200
+53169.00    -54.418 -4.242  -54.000 -4.000
+53170.00    -54.761 -4.239  -54.100 -4.100
+53171.00    -55.061 -4.37   -54.400 -4.300
+53172.00    -55.187 -4.723  -55.000 -4.500
+53173.00    -55.181 -5.181  -55.400 -4.900
+53174.00    -55.174 -5.476  -55.300 -5.300
+53175.00    -55.25  -5.462  -55.300 -5.400
+53176.00    -55.425 -5.272  -55.300 -5.400
+53177.00    -55.643 -5.124  -55.300 -5.300
+53178.00    -55.762 -5.064  -55.200 -5.100
+53179.00    -55.669 -4.978  -55.200 -5.000
+53180.00    -55.478 -4.827  -55.200 -5.000
+53181.00    -55.476 -4.719  -55.500 -4.900
+53182.00    -55.825 -4.72   -55.900 -4.800
+53183.00    -56.434 -4.706  -56.500 -4.500
+53184.00    -57.147 -4.546  -57.100 -4.300
+53185.00    -57.873 -4.337  -57.700 -4.200
+53186.00    -58.474 -4.317  -58.000 -4.300
+53187.00    -58.723 -4.542  -58.100 -4.500
+53188.00    -58.525 -4.803  -58.000 -4.800
+53189.00    -58.071 -4.925  -57.900 -5.100
+53190.00    -57.656 -4.981  -57.700 -5.200
+53191.00    -57.444 -5.093  -57.700 -5.200
+53192.00    -57.499 -5.165  -57.700 -5.100
+53193.00    -57.852 -4.989  -57.900 -4.800
+53194.00    -58.406 -4.582  -58.100 -4.500
+53195.00    -58.912 -4.237  -58.300 -4.200
+53196.00    -59.201 -4.182  -58.600 -4.000
+53197.00    -59.368 -4.343  -59.000 -4.000
+53198.00    -59.584 -4.515  -59.300 -4.200
+53199.00    -59.834 -4.655  -59.600 -4.500
+53200.00    -59.973 -4.874  -59.800 -4.900
+53201.00    -59.978 -5.185  -59.800 -5.200
+53202.00    -59.958 -5.409  -59.800 -5.400
+53203.00    -59.985 -5.367  -59.800 -5.400
+53204.00    -60.037 -5.103  -59.900 -5.200
+53205.00    -60.095 -4.833  -59.900 -4.900
+53206.00    -60.153 -4.704  -59.900 -4.700
+53207.00    -60.166 -4.686  -59.900 -4.600
+53208.00    -60.113 -4.669  -59.900 -4.600
+53209.00    -60.105 -4.615  -60.200 -4.600
+53210.00    -60.32  -4.562  -60.600 -4.600
+53211.00    -60.829 -4.53   -61.200 -4.500
+53212.00    -61.514 -4.513  -61.700 -4.400
+53213.00    -62.137 -4.549  -62.100 -4.300
+53214.00    -62.446 -4.685  -62.000 -4.500
+53215.00    -62.337 -4.863  -61.800 -4.700
+53216.00    -61.963 -4.924  -61.400 -4.900
+53217.00    -61.633 -4.8    -61.200 -5.100
+53218.00    -61.521 -4.645  -61.200 -5.100
+53219.00    -61.553 -4.644  -61.300 -5.000
+53220.00    -61.649 -4.753  0.000   0.000
+53221.00    -61.898 -4.747  0.000   0.000
+53222.00    -62.389 -4.551  0.000   0.000
+53223.00    -62.967 -4.364  0.000   0.000
+53224.00    -63.362 -4.403  0.000   0.000
+53225.00    -63.499 -4.619  0.000   0.000
+53226.00    -63.512 -4.789  0.000   0.000
+53227.00    -63.499 -4.82   0.000   0.000
+53228.00    -63.429 -4.835  0.000   0.000
+53229.00    -63.295 -4.959  0.000   0.000
+53230.00    -63.171 -5.123  0.000   0.000
+53231.00    -63.092 -5.149  0.000   0.000
+53232.00    -63.011 -4.97   0.000   0.000
+53233.00    -62.912 -4.71   0.000   0.000
+53234.00    -62.857 -4.55   0.000   0.000
+53235.00    -62.883 -4.566  0.000   0.000
+53236.00    -62.94  -4.674  0.000   0.000
+53237.00    -63.005 -4.739  0.000   0.000
+53238.00    -63.161 -4.703  0.000   0.000
+53239.00    -63.495 -4.622  0.000   0.000
+53240.00    -63.939 -4.597  0.000   0.000
+53241.00    -64.263 -4.676  0.000   0.000
+53242.00    -64.246 -4.815  0.000   0.000
+53243.00    -63.877 -4.893  0.000   0.000
+53244.00    -63.406 -4.799  0.000   0.000
+53245.00    -63.172 -4.511  0.000   0.000
+53246.00    -63.216 -4.226  0.000   0.000
+53247.00    -63.377 -4.094  0.000   0.000
+53248.00    -63.473 -4.134  0.000   0.000
+53249.00    -63.565 -4.206  0.000   0.000
+53250.00    -63.844 -4.21   0.000   0.000
+53251.00    -64.326 -4.205  0.000   0.000
+53252.00    -64.786 -4.298  0.000   0.000
+53253.00    -64.991 -4.446  0.000   0.000
+53254.00    -64.896 -4.501  0.000   0.000
+53255.00    -64.606 -4.416  0.000   0.000
+53256.00    -64.24  -4.329  0.000   0.000
+53257.00    -63.885 -4.385  0.000   0.000
+53258.00    -63.605 -4.55   0.000   0.000
+53259.00    -63.419 -4.649  0.000   0.000
+53260.00    -63.312 -4.56   0.000   0.000
+53261.00    -63.272 -4.327  0.000   0.000
+53262.00    -63.307 -4.111  0.000   0.000
+53263.00    -63.406 -4.047  0.000   0.000
+53264.00    -63.522 -4.143  0.000   0.000
+53265.00    -63.631 -4.283  0.000   0.000
+53266.00    -63.761 -4.34   0.000   0.000
+53267.00    -63.935 -4.296  0.000   0.000
+53268.00    -64.084 -4.237  0.000   0.000
+53269.00    -64.063 -4.241  0.000   0.000
+53270.00    -63.767 -4.287  0.000   0.000
+53271.00    -63.254 -4.291  0.000   0.000
+53272.00    -62.74  -4.187  0.000   0.000
+53273.00    -62.445 -3.986  0.000   0.000
+53274.00    -62.421 -3.759  0.000   0.000
+53275.00    -62.529 -3.584  0.000   0.000
+53276.00    -62.603 -3.495  0.000   0.000
+53277.00    -62.624 -3.476  0.000   0.000
+53278.00    -62.72  -3.511  0.000   0.000
+53279.00    -62.992 -3.612  0.000   0.000
+53280.00    -63.35  -3.771  0.000   0.000
+53281.00    -63.56  -3.904  0.000   0.000
+53282.00    -63.441 -3.908  0.000   0.000
+53283.00    -63.02  -3.802  0.000   0.000
+53284.00    -62.477 -3.737  0.000   0.000
+53285.00    -61.967 -3.823  0.000   0.000
+53286.00    -61.539 -3.988  0.000   0.000
+53287.00    -61.222 -4.054  0.000   0.000
+53288.00    -61.099 -3.928  0.000   0.000
+53289.00    -61.22  -3.664  0.000   0.000
+53290.00    -61.49  -3.385  0.000   0.000
+53291.00    -61.727 -3.195  0.000   0.000
+53292.00    -61.835 -3.154  0.000   0.000
+53293.00    -61.854 -3.251  0.000   0.000
+53294.00    -61.852 -3.399  0.000   0.000
+53295.00    -61.826 -3.484  0.000   0.000
+53296.00    -61.727 -3.468  0.000   0.000
+53297.00    -61.512 -3.407  0.000   0.000
+53298.00    -61.163 -3.369  0.000   0.000
+53299.00    -60.705 -3.358  0.000   0.000
+53300.00    -60.231 -3.329  0.000   0.000
+53301.00    -59.867 -3.247  0.000   0.000
+53302.00    -59.696 -3.112  0.000   0.000
+53303.00    -59.701 -2.94   0.000   0.000
+53304.00    -59.782 -2.749  0.000   0.000
+53305.00    -59.837 -2.585  0.000   0.000
+53306.00    -59.839 -2.523  0.000   0.000
+53307.00    -59.858 -2.623  0.000   0.000
+53308.00    -59.949 -2.851  0.000   0.000
+53309.00    -60.031 -3.063  0.000   0.000
+53310.00    -59.933 -3.127  0.000   0.000
+53311.00    -59.593 -3.064  0.000   0.000
+53312.00    -59.12  -3.029  0.000   0.000
+53313.00    -58.635 -3.108  0.000   0.000
+53314.00    -58.155 -3.196  0.000   0.000
+53315.00    -57.729 -3.129  0.000   0.000
+53316.00    -57.552 -2.892  0.000   0.000
+53317.00    -57.772 -2.612  0.000   0.000
+53318.00    -58.248 -2.372  0.000   0.000
+53319.00    -58.656 -2.159  0.000   0.000
+53320.00    -58.83  -1.987  0.000   0.000
+53321.00    -58.84  -1.96   0.000   0.000
+53322.00    -58.763 -2.124  0.000   0.000
+53323.00    -58.573 -2.343  0.000   0.000
+53324.00    -58.275 -2.425  0.000   0.000
+53325.00    -57.988 -2.343  0.000   0.000
+53326.00    -57.796 -2.241  0.000   0.000
+53327.00    -57.631 -2.22   0.000   0.000
+53328.00    -57.402 -2.228  0.000   0.000
+53329.00    -57.147 -2.156  0.000   0.000
+53330.00    -56.995 -1.986  0.000   0.000
+53331.00    -57.018 -1.781  0.000   0.000
+53332.00    -57.155 -1.586  0.000   0.000
+53333.00    -57.259 -1.417  0.000   0.000
+53334.00    -57.213 -1.326  0.000   0.000
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/readme.eopc01
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/readme.eopc01	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/readme.eopc01	(revision 22158)
@@ -0,0 +1,82 @@
+This table comes from:
+
+ http://hpiers.obspm.fr/eoppc/eop/eopc01/eopc01.1900-2004
+ 
+As referenced in the Pan-STARRS ADD
+
+
+
+                              EOP(IERS) C 01
+                         ----------------------------
+ 
+ EOP(IERS) C 01 is a series of the earth Orientation Parameters given 
+ in the 1997 IERS system at 0.1 year interval (1846 - 1889) and 0.05 year 
+ interval (1890 - now). It is regularly recomputed to take advantage on one 
+ hand of the improvement of the various individual contributions and in the 
+ other hand of the refinement of the analyses procedures. This series is the
+ basis of the IERS system.
+ 
+ 
+ EOP(IERS) C 01 is based on the following data:
+ 
+ 
+ 1993 - now  : IERS solution of x, y, UT1-UTC, LOD, dPsi, dEpsilon (normal points),
+               based on VLBI, LLR, GPS  and SLR.
+               
+ 1980 - 1992 : IERS solution of x, y, UT1-UTC, dPsi, dEpsilon (normal points),
+               based on VLBI, LLR, GPS (from 1992), and SLR.
+
+ 1962 - 1979 : IERS and BIH solutions, giving x, y, UT1-UTC (normal points). 
+               Space techniques are introduced starting with 1969 (LLR: UT)
+               and 1972 (Doppler: polar motion).
+
+ 1900 - 1961 : Vondrak(1995), Solution derived from optical astrometry 
+               analyses the series give polar motion, celestial pole offsets 
+               and Universal Time (since 1956).
+     
+		
+ 
+ 1846 - 1899 :
+
+               The solution derived by L.V. Rikhlova (Fedorov et al., 1976) 
+               from three series of absolute declination programs (Pulkovo, 
+               Greenwhich, Washington). The frequency band of the variations 
+               kept encompasses only the annual and Chandler terms. The y
+               coordinate of the pole is missing from 1858.9 through 1860.9.
+ 
+ 
+ PRECISION AND ACCURACY
+
+ The individual values are accompanied by uncertainties which attempt to 
+ reflect their quality. For the IERS/BIH solutions, they are  derived from the
+ scattering of the independant measurements contributing to each normal point,
+ with added variance taking into account possible systematic errors. For the 
+ earlier period, they are based on the estimations given by Fedorov et al. 
+ (1976), scaled to match the agreement woth the IERS/BIH solution over
+ 1962-1968. In addition some isolated outliers are deweighted (uncertainty
+ multiplied by 3). 
+
+ The following remarks can be made concerning the drift and the annual term
+ before 1962:
+
+ Trend: as a result of the Fedorov et al. treatment, any drift in polar
+        motion existing before 1900 is ignored in the series. For the period
+        starting with 1900, although no external evidence is available for 
+        the pre-1972 polar motion, it should be mentionned that the low 
+        frequency spectrum of polar motion both before and after the advent 
+        of space techniques (giving the possibility of cross-checks) is that
+        pf random walk at a similar level.
+ 
+ Annual term: it is influenced by errors in nutation and local seasonal errors.
+        Comparisons of the Fedorov et al. solution with the IERS/BIH one over 
+        1962 - 1968 suggest that the amplitude of the annual term is accurate
+        to +/- 0.03" over 1900 - 1962.
+ 
+ REFERENCES
+ 
+ - Fedorov,E.P., Korsun,A.A, Mayor,S.P., Pantschenko,N.I., Tarady,V.K., and
+    Yatskiv,Y.S., 1972: Dvizhenie polyusa Zemli s 1890.0 po 1969.0. Naukova 
+    Dumka, Kiev. [English translation of the text available].
+ - Vondrak J., Ron C., Pesek I., Cepek A., 1995, Astron. and Astrophys. 
+    297,899-906.
+ - IERS Annual reports
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/readme.ser7
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/readme.ser7	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/readme.ser7	(revision 22158)
@@ -0,0 +1,7 @@
+This file comes from the site:
+
+http://maia.usno.navy.mil (Click on General Information about Earth Orientation)
+
+This file may also be directly downloaded from:
+
+ftp://maia.usno.navy.mil/ser7/ser7.dat
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/readme.tai_utc
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/readme.tai_utc	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/readme.tai_utc	(revision 22158)
@@ -0,0 +1,7 @@
+This file comes from the site:
+
+http://maia.usno.navy.mil (Click on table of leap seconds since 1961)
+
+This file may also be directly downloaded from:
+
+ftp://maia.usno.navy.mil/ser7/tai-utc.dat
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/ser7.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/ser7.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/ser7.dat	(revision 22158)
@@ -0,0 +1,380 @@
+#  ser7.dat
+#
+#  This file comes from http://maia.usno.navy.mil (Click on General Information about Earth Orientation). This
+#  file may also be directly downloaded from ftp://maia.usno.navy.mil/ser7/ser7.dat. See readme.ser7 (located
+#  in the psLib/data directory) for details.
+#
+#  @author Ross Harman, MHPCC
+#
+#  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+#  @date $Date: 2006-09-23 02:20:18 $
+#
+#
+#        MJD         PM-x        PM-y       UT1-UTC
+#      (days)      (arcsec)    (arcsec)      (sec)
+#        psF64        psF64       psF64       psF64
+        53244       0.1377      0.5027     -0.45210
+        53245       0.1394      0.5015     -0.45190
+        53246       0.1411      0.5002     -0.45197
+        53247       0.1429      0.4989     -0.45234
+        53248       0.1447      0.4976     -0.45293
+        53249       0.1465      0.4962     -0.45361
+        53250       0.1484      0.4948     -0.45424
+        53251       0.1503      0.4934     -0.45476
+        53252       0.1521      0.4920     -0.45512
+        53253       0.1540      0.4905     -0.45530
+        53254       0.1558      0.4890     -0.45531
+        53255       0.1577      0.4874     -0.45519
+        53256       0.1595      0.4859     -0.45497
+        53257       0.1613      0.4843     -0.45474
+        53258       0.1631      0.4827     -0.45458
+        53259       0.1649      0.4810     -0.45456
+        53260       0.1667      0.4794     -0.45474
+        53261       0.1684      0.4777     -0.45514
+        53262       0.1701      0.4760     -0.45578
+        53263       0.1717      0.4742     -0.45660
+        53264       0.1734      0.4725     -0.45754
+        53265       0.1750      0.4707     -0.45849
+        53266       0.1765      0.4689     -0.45932
+        53267       0.1780      0.4671     -0.45996
+        53268       0.1795      0.4652     -0.46036
+        53269       0.1810      0.4634     -0.46055
+        53270       0.1824      0.4615     -0.46061
+        53271       0.1838      0.4596     -0.46068
+        53272       0.1852      0.4576     -0.46086
+        53273       0.1865      0.4557     -0.46126
+        53274       0.1878      0.4537     -0.46192
+        53275       0.1890      0.4517     -0.46280
+        53276       0.1902      0.4497     -0.46382
+        53277       0.1914      0.4477     -0.46486
+        53278       0.1925      0.4457     -0.46581
+        53279       0.1936      0.4436     -0.46658
+        53280       0.1946      0.4415     -0.46715
+        53281       0.1956      0.4394     -0.46750
+        53282       0.1966      0.4373     -0.46766
+        53283       0.1976      0.4352     -0.46772
+        53284       0.1985      0.4331     -0.46773
+        53285       0.1993      0.4309     -0.46778
+        53286       0.2001      0.4288     -0.46795
+        53287       0.2009      0.4266     -0.46830
+        53288       0.2017      0.4244     -0.46887
+        53289       0.2024      0.4222     -0.46968
+        53290       0.2031      0.4200     -0.47071
+        53291       0.2037      0.4178     -0.47191
+        53292       0.2043      0.4155     -0.47317
+        53293       0.2049      0.4133     -0.47435
+        53294       0.2054      0.4111     -0.47536
+        53295       0.2059      0.4088     -0.47610
+        53296       0.2063      0.4065     -0.47659
+        53297       0.2067      0.4042     -0.47691
+        53298       0.2071      0.4020     -0.47718
+        53299       0.2075      0.3997     -0.47755
+        53300       0.2078      0.3974     -0.47811
+        53301       0.2080      0.3951     -0.47893
+        53302       0.2083      0.3928     -0.47998
+        53303       0.2085      0.3905     -0.48119
+        53304       0.2086      0.3881     -0.48247
+        53305       0.2088      0.3858     -0.48369
+        53306       0.2089      0.3835     -0.48477
+        53307       0.2089      0.3812     -0.48565
+        53308       0.2090      0.3789     -0.48630
+        53309       0.2089      0.3765     -0.48674
+        53310       0.2089      0.3742     -0.48701
+        53311       0.2088      0.3719     -0.48718
+        53312       0.2088      0.3696     -0.48732
+        53313       0.2086      0.3672     -0.48753
+        53314       0.2085      0.3649     -0.48785
+        53315       0.2082      0.3626     -0.48835
+        53316       0.2080      0.3603     -0.48906
+        53317       0.2077      0.3579     -0.48997
+        53318       0.2074      0.3556     -0.49106
+        53319       0.2071      0.3533     -0.49226
+        53320       0.2067      0.3510     -0.49344
+        53321       0.2063      0.3487     -0.49449
+        53322       0.2059      0.3464     -0.49531
+        53323       0.2054      0.3441     -0.49585
+        53324       0.2049      0.3418     -0.49618
+        53325       0.2044      0.3396     -0.49639
+        53326       0.2038      0.3373     -0.49664
+        53327       0.2032      0.3350     -0.49705
+        53328       0.2026      0.3328     -0.49769
+        53329       0.2020      0.3305     -0.49854
+        53330       0.2013      0.3283     -0.49953
+        53331       0.2006      0.3261     -0.50058
+        53332       0.1999      0.3239     -0.50158
+        53333       0.1991      0.3217     -0.50243
+        53334       0.1983      0.3195     -0.50308
+        53335       0.1975      0.3173     -0.50350
+        53336       0.1967      0.3151     -0.50369
+        53337       0.1958      0.3130     -0.50370
+        53338       0.1949      0.3108     -0.50358
+        53339       0.1940      0.3087     -0.50342
+        53340       0.1931      0.3066     -0.50329
+        53341       0.1921      0.3045     -0.50327
+        53342       0.1911      0.3024     -0.50340
+        53343       0.1901      0.3004     -0.50372
+        53344       0.1890      0.2983     -0.50423
+        53345       0.1880      0.2963     -0.50493
+        53346       0.1869      0.2943     -0.50574
+        53347       0.1858      0.2923     -0.50660
+        53348       0.1846      0.2903     -0.50739
+        53349       0.1835      0.2883     -0.50808
+        53350       0.1823      0.2864     -0.50851
+        53351       0.1811      0.2844     -0.50870
+        53352       0.1799      0.2825     -0.50874
+        53353       0.1786      0.2807     -0.50875
+        53354       0.1773      0.2788     -0.50890
+        53355       0.1760      0.2769     -0.50927
+        53356       0.1747      0.2751     -0.50987
+        53357       0.1734      0.2733     -0.51064
+        53358       0.1720      0.2715     -0.51148
+        53359       0.1707      0.2698     -0.51228
+        53360       0.1693      0.2680     -0.51295
+        53361       0.1679      0.2663     -0.51342
+        53362       0.1664      0.2646     -0.51367
+        53363       0.1650      0.2629     -0.51371
+        53364       0.1635      0.2613     -0.51357
+        53365       0.1620      0.2596     -0.51330
+        53366       0.1605      0.2580     -0.51298
+        53367       0.1590      0.2565     -0.51268
+        53368       0.1575      0.2549     -0.51247
+        53369       0.1559      0.2534     -0.51241
+        53370       0.1543      0.2519     -0.51253
+        53371       0.1528      0.2504     -0.51283
+        53372       0.1511      0.2489     -0.51331
+        53373       0.1495      0.2475     -0.51391
+        53374       0.1479      0.2461     -0.51458
+        53375       0.1463      0.2447     -0.51522
+        53376       0.1446      0.2434     -0.51574
+        53377       0.1429      0.2420     -0.51605
+        53378       0.1412      0.2407     -0.51614
+        53379       0.1395      0.2395     -0.51605
+        53380       0.1378      0.2382     -0.51590
+        53381       0.1361      0.2370     -0.51585
+        53382       0.1344      0.2358     -0.51603
+        53383       0.1326      0.2347     -0.51648
+        53384       0.1308      0.2335     -0.51717
+        53385       0.1291      0.2324     -0.51800
+        53386       0.1273      0.2313     -0.51881
+        53387       0.1255      0.2303     -0.51951
+        53388       0.1237      0.2293     -0.52000
+        53389       0.1219      0.2283     -0.52027
+        53390       0.1200      0.2273     -0.52032
+        53391       0.1182      0.2264     -0.52018
+        53392       0.1164      0.2255     -0.51992
+        53393       0.1145      0.2246     -0.51959
+        53394       0.1126      0.2237     -0.51928
+        53395       0.1108      0.2229     -0.51905
+        53396       0.1089      0.2221     -0.51897
+        53397       0.1070      0.2213     -0.51908
+        53398       0.1051      0.2206     -0.51939
+        53399       0.1032      0.2199     -0.51987
+        53400       0.1013      0.2192     -0.52050
+        53401       0.0994      0.2186     -0.52119
+        53402       0.0975      0.2180     -0.52187
+        53403       0.0956      0.2174     -0.52246
+        53404       0.0936      0.2168     -0.52288
+        53405       0.0917      0.2163     -0.52309
+        53406       0.0898      0.2158     -0.52311
+        53407       0.0878      0.2153     -0.52305
+        53408       0.0859      0.2149     -0.52303
+        53409       0.0840      0.2144     -0.52321
+        53410       0.0820      0.2141     -0.52368
+        53411       0.0801      0.2137     -0.52444
+        53412       0.0781      0.2134     -0.52542
+        53413       0.0761      0.2131     -0.52646
+        53414       0.0742      0.2128     -0.52744
+        53415       0.0722      0.2126     -0.52822
+        53416       0.0703      0.2124     -0.52877
+        53417       0.0683      0.2122     -0.52907
+        53418       0.0663      0.2120     -0.52916
+        53419       0.0644      0.2119     -0.52910
+        53420       0.0624      0.2118     -0.52897
+        53421       0.0605      0.2117     -0.52883
+        53422       0.0585      0.2117     -0.52876
+        53423       0.0566      0.2117     -0.52882
+        53424       0.0546      0.2117     -0.52907
+        53425       0.0526      0.2118     -0.52951
+        53426       0.0507      0.2118     -0.53014
+        53427       0.0487      0.2119     -0.53091
+        53428       0.0468      0.2121     -0.53174
+        53429       0.0449      0.2122     -0.53254
+        53430       0.0429      0.2124     -0.53321
+        53431       0.0410      0.2126     -0.53368
+        53432       0.0391      0.2129     -0.53392
+        53433       0.0372      0.2131     -0.53393
+        53434       0.0352      0.2134     -0.53380
+        53435       0.0333      0.2138     -0.53366
+        53436       0.0314      0.2141     -0.53365
+        53437       0.0296      0.2145     -0.53389
+        53438       0.0277      0.2149     -0.53443
+        53439       0.0258      0.2154     -0.53526
+        53440       0.0239      0.2159     -0.53627
+        53441       0.0221      0.2164     -0.53733
+        53442       0.0202      0.2169     -0.53830
+        53443       0.0184      0.2174     -0.53908
+        53444       0.0166      0.2180     -0.53964
+        53445       0.0147      0.2186     -0.53998
+        53446       0.0129      0.2192     -0.54014
+        53447       0.0111      0.2198     -0.54018
+        53448       0.0093      0.2205     -0.54018
+        53449       0.0076      0.2212     -0.54022
+        53450       0.0058      0.2219     -0.54037
+        53451       0.0040      0.2227     -0.54069
+        53452       0.0023      0.2234     -0.54118
+        53453       0.0005      0.2242     -0.54185
+        53454      -0.0012      0.2250     -0.54266
+        53455      -0.0029      0.2258     -0.54356
+        53456      -0.0046      0.2267     -0.54447
+        53457      -0.0063      0.2276     -0.54530
+        53458      -0.0079      0.2285     -0.54598
+        53459      -0.0096      0.2294     -0.54647
+        53460      -0.0112      0.2303     -0.54675
+        53461      -0.0128      0.2313     -0.54688
+        53462      -0.0144      0.2323     -0.54699
+        53463      -0.0160      0.2333     -0.54724
+        53464      -0.0176      0.2343     -0.54775
+        53465      -0.0191      0.2353     -0.54858
+        53466      -0.0207      0.2364     -0.54970
+        53467      -0.0222      0.2375     -0.55097
+        53468      -0.0237      0.2386     -0.55228
+        53469      -0.0252      0.2397     -0.55354
+        53470      -0.0267      0.2408     -0.55465
+        53471      -0.0281      0.2420     -0.55556
+        53472      -0.0295      0.2431     -0.55626
+        53473      -0.0310      0.2443     -0.55677
+        53474      -0.0323      0.2455     -0.55715
+        53475      -0.0337      0.2468     -0.55748
+        53476      -0.0351      0.2480     -0.55785
+        53477      -0.0364      0.2493     -0.55833
+        53478      -0.0377      0.2505     -0.55899
+        53479      -0.0390      0.2518     -0.55988
+        53480      -0.0403      0.2531     -0.56095
+        53481      -0.0415      0.2545     -0.56216
+        53482      -0.0427      0.2558     -0.56347
+        53483      -0.0439      0.2572     -0.56478
+        53484      -0.0451      0.2585     -0.56599
+        53485      -0.0463      0.2599     -0.56699
+        53486      -0.0474      0.2613     -0.56769
+        53487      -0.0485      0.2627     -0.56808
+        53488      -0.0496      0.2641     -0.56824
+        53489      -0.0507      0.2656     -0.56830
+        53490      -0.0517      0.2670     -0.56839
+        53491      -0.0527      0.2685     -0.56860
+        53492      -0.0537      0.2700     -0.56897
+        53493      -0.0547      0.2714     -0.56955
+        53494      -0.0556      0.2729     -0.57032
+        53495      -0.0565      0.2744     -0.57119
+        53496      -0.0574      0.2760     -0.57204
+        53497      -0.0583      0.2775     -0.57277
+        53498      -0.0591      0.2790     -0.57329
+        53499      -0.0600      0.2806     -0.57354
+        53500      -0.0607      0.2821     -0.57350
+        53501      -0.0615      0.2837     -0.57328
+        53502      -0.0622      0.2853     -0.57298
+        53503      -0.0630      0.2869     -0.57261
+        53504      -0.0636      0.2885     -0.57218
+        53505      -0.0643      0.2901     -0.57175
+        53506      -0.0649      0.2917     -0.57143
+        53507      -0.0655      0.2933     -0.57124
+        53508      -0.0661      0.2949     -0.57117
+        53509      -0.0667      0.2966     -0.57124
+        53510      -0.0672      0.2982     -0.57139
+        53511      -0.0677      0.2999     -0.57158
+        53512      -0.0682      0.3015     -0.57166
+        53513      -0.0686      0.3032     -0.57155
+        53514      -0.0690      0.3048     -0.57116
+        53515      -0.0694      0.3065     -0.57057
+        53516      -0.0698      0.3082     -0.56989
+        53517      -0.0701      0.3098     -0.56921
+        53518      -0.0704      0.3115     -0.56860
+        53519      -0.0707      0.3132     -0.56818
+        53520      -0.0710      0.3149     -0.56799
+        53521      -0.0712      0.3166     -0.56800
+        53522      -0.0714      0.3183     -0.56809
+        53523      -0.0716      0.3200     -0.56815
+        53524      -0.0717      0.3217     -0.56808
+        53525      -0.0718      0.3234     -0.56781
+        53526      -0.0719      0.3251     -0.56728
+        53527      -0.0720      0.3268     -0.56651
+        53528      -0.0720      0.3285     -0.56557
+        53529      -0.0720      0.3302     -0.56454
+        53530      -0.0720      0.3319     -0.56347
+        53531      -0.0720      0.3336     -0.56244
+        53532      -0.0719      0.3353     -0.56148
+        53533      -0.0718      0.3370     -0.56060
+        53534      -0.0717      0.3387     -0.55990
+        53535      -0.0715      0.3404     -0.55943
+        53536      -0.0713      0.3421     -0.55916
+        53537      -0.0711      0.3438     -0.55897
+        53538      -0.0709      0.3455     -0.55881
+        53539      -0.0707      0.3472     -0.55859
+        53540      -0.0704      0.3489     -0.55820
+        53541      -0.0701      0.3506     -0.55751
+        53542      -0.0697      0.3523     -0.55650
+        53543      -0.0694      0.3540     -0.55529
+        53544      -0.0690      0.3557     -0.55402
+        53545      -0.0686      0.3573     -0.55279
+        53546      -0.0682      0.3590     -0.55173
+        53547      -0.0677      0.3607     -0.55093
+        53548      -0.0673      0.3623     -0.55037
+        53549      -0.0668      0.3640     -0.54994
+        53550      -0.0662      0.3656     -0.54947
+        53551      -0.0657      0.3673     -0.54884
+        53552      -0.0651      0.3689     -0.54798
+        53553      -0.0645      0.3705     -0.54689
+        53554      -0.0639      0.3721     -0.54560
+        53555      -0.0633      0.3738     -0.54414
+        53556      -0.0626      0.3754     -0.54257
+        53557      -0.0620      0.3770     -0.54101
+        53558      -0.0613      0.3786     -0.53952
+        53559      -0.0605      0.3801     -0.53819
+        53560      -0.0598      0.3817     -0.53705
+        53561      -0.0590      0.3833     -0.53611
+        53562      -0.0583      0.3848     -0.53535
+        53563      -0.0575      0.3864     -0.53475
+        53564      -0.0566      0.3879     -0.53425
+        53565      -0.0558      0.3895     -0.53374
+        53566      -0.0549      0.3910     -0.53315
+        53567      -0.0541      0.3925     -0.53243
+        53568      -0.0532      0.3940     -0.53152
+        53569      -0.0523      0.3955     -0.53042
+        53570      -0.0513      0.3969     -0.52913
+        53571      -0.0504      0.3984     -0.52776
+        53572      -0.0494      0.3998     -0.52644
+        53573      -0.0485      0.4013     -0.52532
+        53574      -0.0475      0.4027     -0.52451
+        53575      -0.0464      0.4041     -0.52400
+        53576      -0.0454      0.4055     -0.52377
+        53577      -0.0444      0.4069     -0.52366
+        53578      -0.0433      0.4083     -0.52344
+        53579      -0.0423      0.4096     -0.52299
+        53580      -0.0412      0.4110     -0.52228
+        53581      -0.0401      0.4123     -0.52130
+        53582      -0.0390      0.4136     -0.52010
+        53583      -0.0378      0.4149     -0.51872
+        53584      -0.0367      0.4162     -0.51725
+        53585      -0.0356      0.4175     -0.51578
+        53586      -0.0344      0.4188     -0.51436
+        53587      -0.0332      0.4200     -0.51310
+        53588      -0.0320      0.4212     -0.51204
+        53589      -0.0309      0.4224     -0.51120
+        53590      -0.0297      0.4236     -0.51055
+        53591      -0.0284      0.4248     -0.51006
+        53592      -0.0272      0.4260     -0.50966
+        53593      -0.0260      0.4271     -0.50922
+        53594      -0.0247      0.4283     -0.50872
+        53595      -0.0235      0.4294     -0.50809
+        53596      -0.0222      0.4305     -0.50729
+        53597      -0.0210      0.4315     -0.50638
+        53598      -0.0197      0.4326     -0.50535
+        53599      -0.0184      0.4336     -0.50431
+        53600      -0.0171      0.4347     -0.50339
+        53601      -0.0158      0.4357     -0.50273
+        53602      -0.0145      0.4367     -0.50244
+        53603      -0.0132      0.4376     -0.50247
+        53604      -0.0119      0.4386     -0.50267
+        53605      -0.0106      0.4395     -0.50286
+        53606      -0.0093      0.4404     -0.50287
+        53607      -0.0079      0.4413     -0.50263
+        53608      -0.0066      0.4422     -0.50217
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/ser7.raw
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/ser7.raw	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/ser7.raw	(revision 22158)
@@ -0,0 +1,475 @@
+                                                                                
+      **********************************************************************    
+      *                                                                    *    
+      *                   I E R S   B U L L E T I N - A                    *    
+      *                                                                    *    
+      *           Rapid Service/Prediction of Earth Orientation            *    
+      **********************************************************************    
+      26 August 2004                                       Vol. XVII No. 034    
+      ______________________________________________________________________    
+      GENERAL INFORMATION:                                                      
+         To receive this information electronically, contact:                   
+            ser7@maia.usno.navy.mil or use http://maia.usno.navy.mil/           
+         MJD = Julian Date - 2 400 000.5 days                                   
+         UT2-UT1 = 0.022 sin(2*pi*T) - 0.012 cos(2*pi*T)                        
+                                     - 0.006 sin(4*pi*T) + 0.007 cos(4*pi*T)    
+            where pi = 3.14159265... and T is the date in Besselian years.      
+         TT = TAI + 32.184 seconds                                              
+         DUT1= (UT1-UTC) transmitted with time signals                          
+             =  -0.5 seconds beginning 29 April    2004 at 0000 UTC             
+         Beginning 1 January 1999:                                              
+            TAI-UTC(BIPM) = 32.000 000 seconds                                  
+      **********************************************************************    
+      *                 No leap second will be introduced                  *    
+      *                    in UTC on 31 December 2004.                     *    
+      *       Bulletin A is now compliant with IAU 2000 resolutions        *    
+      *                See notice at the end of this Bulletin A            *    
+      **********************************************************************    
+     ________________________________________________________________________   
+       The contributed observations used in the preparation of this Bulletin    
+       are available at ftp://maia.usno.navy.mil/bulla-data.html.  The          
+       contributed analysis results are based on data from Very Long Baseline   
+       Interferometry (VLBI), Satellite Laser Ranging (SLR), the Global         
+       Positioning System (GPS) satellites, Lunar Laser Ranging (LLR), and      
+       meteorological predictions of variations in Atmospheric Angular          
+       Momentum (AAM).                                                          
+     ________________________________________________________________________   
+                                                                                
+      COMBINED EARTH ORIENTATION PARAMETERS:                                    
+                                                                                
+                              IERS Rapid Service                                
+              MJD      x    error     y    error   UT1-UTC   error              
+                       "      "       "      "        s        s                
+    4  8 20  53237  .12423 .00003  .51109 .00006  -.451871  .000012          
+    4  8 21  53238  .12644 .00003  .51031 .00005  -.452406  .000014          
+    4  8 22  53239  .12829 .00003  .50925 .00005  -.452813  .000014          
+    4  8 23  53240  .13014 .00002  .50785 .00004  -.453011  .000012          
+    4  8 24  53241  .13227 .00002  .50627 .00004  -.452994  .000013          
+    4  8 25  53242  .13439 .00002  .50488 .00003  -.452786  .000012          
+    4  8 26  53243  .13604 .00002  .50376 .00003  -.452446  .000011          
+                                                                                
+      _______________________________________________________________________   
+                                                                                
+      PREDICTIONS:                                                              
+      The following formulas will not reproduce the predictions given below,    
+      but may be used to extend the predictions beyond the end of this table.   
+                                                                                
+      x =   .0530 +  .0660 cos A -  .0075 sin A +  .0182 cos C +  .1564 sin C   
+      y =   .3501 -  .0070 cos A -  .0542 sin A +  .1564 cos C -  .0182 sin C   
+         UT1-UTC =  -.4952 -  .00023 (MJD - 53248) - (UT2-UT1)                  
+                                                                                
+      where A = 2*pi*(MJD-53243)/365.25 and C = 2*pi*(MJD-53243)/435.           
+                                                                                
+         TAI-UTC(MJD 53244) = 32.0                                              
+      The accuracy may be estimated from the expressions:                       
+      S x,y = 0.0042 (MJD-53243)**0.28    S t = 0.0003 (MJD-53248)**0.75        
+      Estimated accuracies are:  Predictions     10 d   20 d   30 d   40 d      
+                                 Polar coord's  0.004  0.006  0.009  0.011      
+                                 UT1-UTC        0.0017 0.0028 0.0039 0.0048     
+                                                                                
+                    MJD      x(arcsec)   y(arcsec)   UT1-UTC(sec)               
+       2004  8 27  53244       0.1377      0.5027     -0.45210              
+       2004  8 28  53245       0.1394      0.5015     -0.45190              
+       2004  8 29  53246       0.1411      0.5002     -0.45197              
+       2004  8 30  53247       0.1429      0.4989     -0.45234              
+       2004  8 31  53248       0.1447      0.4976     -0.45293              
+       2004  9  1  53249       0.1465      0.4962     -0.45361              
+       2004  9  2  53250       0.1484      0.4948     -0.45424              
+       2004  9  3  53251       0.1503      0.4934     -0.45476              
+       2004  9  4  53252       0.1521      0.4920     -0.45512              
+       2004  9  5  53253       0.1540      0.4905     -0.45530              
+       2004  9  6  53254       0.1558      0.4890     -0.45531              
+       2004  9  7  53255       0.1577      0.4874     -0.45519              
+       2004  9  8  53256       0.1595      0.4859     -0.45497              
+       2004  9  9  53257       0.1613      0.4843     -0.45474              
+       2004  9 10  53258       0.1631      0.4827     -0.45458              
+       2004  9 11  53259       0.1649      0.4810     -0.45456              
+       2004  9 12  53260       0.1667      0.4794     -0.45474              
+       2004  9 13  53261       0.1684      0.4777     -0.45514              
+       2004  9 14  53262       0.1701      0.4760     -0.45578              
+       2004  9 15  53263       0.1717      0.4742     -0.45660              
+       2004  9 16  53264       0.1734      0.4725     -0.45754              
+       2004  9 17  53265       0.1750      0.4707     -0.45849              
+       2004  9 18  53266       0.1765      0.4689     -0.45932              
+       2004  9 19  53267       0.1780      0.4671     -0.45996              
+       2004  9 20  53268       0.1795      0.4652     -0.46036              
+       2004  9 21  53269       0.1810      0.4634     -0.46055              
+       2004  9 22  53270       0.1824      0.4615     -0.46061              
+       2004  9 23  53271       0.1838      0.4596     -0.46068              
+       2004  9 24  53272       0.1852      0.4576     -0.46086              
+       2004  9 25  53273       0.1865      0.4557     -0.46126              
+       2004  9 26  53274       0.1878      0.4537     -0.46192              
+       2004  9 27  53275       0.1890      0.4517     -0.46280              
+       2004  9 28  53276       0.1902      0.4497     -0.46382              
+       2004  9 29  53277       0.1914      0.4477     -0.46486              
+       2004  9 30  53278       0.1925      0.4457     -0.46581              
+       2004 10  1  53279       0.1936      0.4436     -0.46658              
+       2004 10  2  53280       0.1946      0.4415     -0.46715              
+       2004 10  3  53281       0.1956      0.4394     -0.46750              
+       2004 10  4  53282       0.1966      0.4373     -0.46766              
+       2004 10  5  53283       0.1976      0.4352     -0.46772              
+       2004 10  6  53284       0.1985      0.4331     -0.46773              
+       2004 10  7  53285       0.1993      0.4309     -0.46778              
+       2004 10  8  53286       0.2001      0.4288     -0.46795              
+       2004 10  9  53287       0.2009      0.4266     -0.46830              
+       2004 10 10  53288       0.2017      0.4244     -0.46887              
+       2004 10 11  53289       0.2024      0.4222     -0.46968              
+       2004 10 12  53290       0.2031      0.4200     -0.47071              
+       2004 10 13  53291       0.2037      0.4178     -0.47191              
+       2004 10 14  53292       0.2043      0.4155     -0.47317              
+       2004 10 15  53293       0.2049      0.4133     -0.47435              
+       2004 10 16  53294       0.2054      0.4111     -0.47536              
+       2004 10 17  53295       0.2059      0.4088     -0.47610              
+       2004 10 18  53296       0.2063      0.4065     -0.47659              
+       2004 10 19  53297       0.2067      0.4042     -0.47691              
+       2004 10 20  53298       0.2071      0.4020     -0.47718              
+       2004 10 21  53299       0.2075      0.3997     -0.47755              
+       2004 10 22  53300       0.2078      0.3974     -0.47811              
+       2004 10 23  53301       0.2080      0.3951     -0.47893              
+       2004 10 24  53302       0.2083      0.3928     -0.47998              
+       2004 10 25  53303       0.2085      0.3905     -0.48119              
+       2004 10 26  53304       0.2086      0.3881     -0.48247              
+       2004 10 27  53305       0.2088      0.3858     -0.48369              
+       2004 10 28  53306       0.2089      0.3835     -0.48477              
+       2004 10 29  53307       0.2089      0.3812     -0.48565              
+       2004 10 30  53308       0.2090      0.3789     -0.48630              
+       2004 10 31  53309       0.2089      0.3765     -0.48674              
+       2004 11  1  53310       0.2089      0.3742     -0.48701              
+       2004 11  2  53311       0.2088      0.3719     -0.48718              
+       2004 11  3  53312       0.2088      0.3696     -0.48732              
+       2004 11  4  53313       0.2086      0.3672     -0.48753              
+       2004 11  5  53314       0.2085      0.3649     -0.48785              
+       2004 11  6  53315       0.2082      0.3626     -0.48835              
+       2004 11  7  53316       0.2080      0.3603     -0.48906              
+       2004 11  8  53317       0.2077      0.3579     -0.48997              
+       2004 11  9  53318       0.2074      0.3556     -0.49106              
+       2004 11 10  53319       0.2071      0.3533     -0.49226              
+       2004 11 11  53320       0.2067      0.3510     -0.49344              
+       2004 11 12  53321       0.2063      0.3487     -0.49449              
+       2004 11 13  53322       0.2059      0.3464     -0.49531              
+       2004 11 14  53323       0.2054      0.3441     -0.49585              
+       2004 11 15  53324       0.2049      0.3418     -0.49618              
+       2004 11 16  53325       0.2044      0.3396     -0.49639              
+       2004 11 17  53326       0.2038      0.3373     -0.49664              
+       2004 11 18  53327       0.2032      0.3350     -0.49705              
+       2004 11 19  53328       0.2026      0.3328     -0.49769              
+       2004 11 20  53329       0.2020      0.3305     -0.49854              
+       2004 11 21  53330       0.2013      0.3283     -0.49953              
+       2004 11 22  53331       0.2006      0.3261     -0.50058              
+       2004 11 23  53332       0.1999      0.3239     -0.50158              
+       2004 11 24  53333       0.1991      0.3217     -0.50243              
+       2004 11 25  53334       0.1983      0.3195     -0.50308              
+       2004 11 26  53335       0.1975      0.3173     -0.50350              
+       2004 11 27  53336       0.1967      0.3151     -0.50369              
+       2004 11 28  53337       0.1958      0.3130     -0.50370              
+       2004 11 29  53338       0.1949      0.3108     -0.50358              
+       2004 11 30  53339       0.1940      0.3087     -0.50342              
+       2004 12  1  53340       0.1931      0.3066     -0.50329              
+       2004 12  2  53341       0.1921      0.3045     -0.50327              
+       2004 12  3  53342       0.1911      0.3024     -0.50340              
+       2004 12  4  53343       0.1901      0.3004     -0.50372              
+       2004 12  5  53344       0.1890      0.2983     -0.50423              
+       2004 12  6  53345       0.1880      0.2963     -0.50493              
+       2004 12  7  53346       0.1869      0.2943     -0.50574              
+       2004 12  8  53347       0.1858      0.2923     -0.50660              
+       2004 12  9  53348       0.1846      0.2903     -0.50739              
+       2004 12 10  53349       0.1835      0.2883     -0.50808              
+       2004 12 11  53350       0.1823      0.2864     -0.50851              
+       2004 12 12  53351       0.1811      0.2844     -0.50870              
+       2004 12 13  53352       0.1799      0.2825     -0.50874              
+       2004 12 14  53353       0.1786      0.2807     -0.50875              
+       2004 12 15  53354       0.1773      0.2788     -0.50890              
+       2004 12 16  53355       0.1760      0.2769     -0.50927              
+       2004 12 17  53356       0.1747      0.2751     -0.50987              
+       2004 12 18  53357       0.1734      0.2733     -0.51064              
+       2004 12 19  53358       0.1720      0.2715     -0.51148              
+       2004 12 20  53359       0.1707      0.2698     -0.51228              
+       2004 12 21  53360       0.1693      0.2680     -0.51295              
+       2004 12 22  53361       0.1679      0.2663     -0.51342              
+       2004 12 23  53362       0.1664      0.2646     -0.51367              
+       2004 12 24  53363       0.1650      0.2629     -0.51371              
+       2004 12 25  53364       0.1635      0.2613     -0.51357              
+       2004 12 26  53365       0.1620      0.2596     -0.51330              
+       2004 12 27  53366       0.1605      0.2580     -0.51298              
+       2004 12 28  53367       0.1590      0.2565     -0.51268              
+       2004 12 29  53368       0.1575      0.2549     -0.51247              
+       2004 12 30  53369       0.1559      0.2534     -0.51241              
+       2004 12 31  53370       0.1543      0.2519     -0.51253              
+       2005  1  1  53371       0.1528      0.2504     -0.51283              
+       2005  1  2  53372       0.1511      0.2489     -0.51331              
+       2005  1  3  53373       0.1495      0.2475     -0.51391              
+       2005  1  4  53374       0.1479      0.2461     -0.51458              
+       2005  1  5  53375       0.1463      0.2447     -0.51522              
+       2005  1  6  53376       0.1446      0.2434     -0.51574              
+       2005  1  7  53377       0.1429      0.2420     -0.51605              
+       2005  1  8  53378       0.1412      0.2407     -0.51614              
+       2005  1  9  53379       0.1395      0.2395     -0.51605              
+       2005  1 10  53380       0.1378      0.2382     -0.51590              
+       2005  1 11  53381       0.1361      0.2370     -0.51585              
+       2005  1 12  53382       0.1344      0.2358     -0.51603              
+       2005  1 13  53383       0.1326      0.2347     -0.51648              
+       2005  1 14  53384       0.1308      0.2335     -0.51717              
+       2005  1 15  53385       0.1291      0.2324     -0.51800              
+       2005  1 16  53386       0.1273      0.2313     -0.51881              
+       2005  1 17  53387       0.1255      0.2303     -0.51951              
+       2005  1 18  53388       0.1237      0.2293     -0.52000              
+       2005  1 19  53389       0.1219      0.2283     -0.52027              
+       2005  1 20  53390       0.1200      0.2273     -0.52032              
+       2005  1 21  53391       0.1182      0.2264     -0.52018              
+       2005  1 22  53392       0.1164      0.2255     -0.51992              
+       2005  1 23  53393       0.1145      0.2246     -0.51959              
+       2005  1 24  53394       0.1126      0.2237     -0.51928              
+       2005  1 25  53395       0.1108      0.2229     -0.51905              
+       2005  1 26  53396       0.1089      0.2221     -0.51897              
+       2005  1 27  53397       0.1070      0.2213     -0.51908              
+       2005  1 28  53398       0.1051      0.2206     -0.51939              
+       2005  1 29  53399       0.1032      0.2199     -0.51987              
+       2005  1 30  53400       0.1013      0.2192     -0.52050              
+       2005  1 31  53401       0.0994      0.2186     -0.52119              
+       2005  2  1  53402       0.0975      0.2180     -0.52187              
+       2005  2  2  53403       0.0956      0.2174     -0.52246              
+       2005  2  3  53404       0.0936      0.2168     -0.52288              
+       2005  2  4  53405       0.0917      0.2163     -0.52309              
+       2005  2  5  53406       0.0898      0.2158     -0.52311              
+       2005  2  6  53407       0.0878      0.2153     -0.52305              
+       2005  2  7  53408       0.0859      0.2149     -0.52303              
+       2005  2  8  53409       0.0840      0.2144     -0.52321              
+       2005  2  9  53410       0.0820      0.2141     -0.52368              
+       2005  2 10  53411       0.0801      0.2137     -0.52444              
+       2005  2 11  53412       0.0781      0.2134     -0.52542              
+       2005  2 12  53413       0.0761      0.2131     -0.52646              
+       2005  2 13  53414       0.0742      0.2128     -0.52744              
+       2005  2 14  53415       0.0722      0.2126     -0.52822              
+       2005  2 15  53416       0.0703      0.2124     -0.52877              
+       2005  2 16  53417       0.0683      0.2122     -0.52907              
+       2005  2 17  53418       0.0663      0.2120     -0.52916              
+       2005  2 18  53419       0.0644      0.2119     -0.52910              
+       2005  2 19  53420       0.0624      0.2118     -0.52897              
+       2005  2 20  53421       0.0605      0.2117     -0.52883              
+       2005  2 21  53422       0.0585      0.2117     -0.52876              
+       2005  2 22  53423       0.0566      0.2117     -0.52882              
+       2005  2 23  53424       0.0546      0.2117     -0.52907              
+       2005  2 24  53425       0.0526      0.2118     -0.52951              
+       2005  2 25  53426       0.0507      0.2118     -0.53014              
+       2005  2 26  53427       0.0487      0.2119     -0.53091              
+       2005  2 27  53428       0.0468      0.2121     -0.53174              
+       2005  2 28  53429       0.0449      0.2122     -0.53254              
+       2005  3  1  53430       0.0429      0.2124     -0.53321              
+       2005  3  2  53431       0.0410      0.2126     -0.53368              
+       2005  3  3  53432       0.0391      0.2129     -0.53392              
+       2005  3  4  53433       0.0372      0.2131     -0.53393              
+       2005  3  5  53434       0.0352      0.2134     -0.53380              
+       2005  3  6  53435       0.0333      0.2138     -0.53366              
+       2005  3  7  53436       0.0314      0.2141     -0.53365              
+       2005  3  8  53437       0.0296      0.2145     -0.53389              
+       2005  3  9  53438       0.0277      0.2149     -0.53443              
+       2005  3 10  53439       0.0258      0.2154     -0.53526              
+       2005  3 11  53440       0.0239      0.2159     -0.53627              
+       2005  3 12  53441       0.0221      0.2164     -0.53733              
+       2005  3 13  53442       0.0202      0.2169     -0.53830              
+       2005  3 14  53443       0.0184      0.2174     -0.53908              
+       2005  3 15  53444       0.0166      0.2180     -0.53964              
+       2005  3 16  53445       0.0147      0.2186     -0.53998              
+       2005  3 17  53446       0.0129      0.2192     -0.54014              
+       2005  3 18  53447       0.0111      0.2198     -0.54018              
+       2005  3 19  53448       0.0093      0.2205     -0.54018              
+       2005  3 20  53449       0.0076      0.2212     -0.54022              
+       2005  3 21  53450       0.0058      0.2219     -0.54037              
+       2005  3 22  53451       0.0040      0.2227     -0.54069              
+       2005  3 23  53452       0.0023      0.2234     -0.54118              
+       2005  3 24  53453       0.0005      0.2242     -0.54185              
+       2005  3 25  53454      -0.0012      0.2250     -0.54266              
+       2005  3 26  53455      -0.0029      0.2258     -0.54356              
+       2005  3 27  53456      -0.0046      0.2267     -0.54447              
+       2005  3 28  53457      -0.0063      0.2276     -0.54530              
+       2005  3 29  53458      -0.0079      0.2285     -0.54598              
+       2005  3 30  53459      -0.0096      0.2294     -0.54647              
+       2005  3 31  53460      -0.0112      0.2303     -0.54675              
+       2005  4  1  53461      -0.0128      0.2313     -0.54688              
+       2005  4  2  53462      -0.0144      0.2323     -0.54699              
+       2005  4  3  53463      -0.0160      0.2333     -0.54724              
+       2005  4  4  53464      -0.0176      0.2343     -0.54775              
+       2005  4  5  53465      -0.0191      0.2353     -0.54858              
+       2005  4  6  53466      -0.0207      0.2364     -0.54970              
+       2005  4  7  53467      -0.0222      0.2375     -0.55097              
+       2005  4  8  53468      -0.0237      0.2386     -0.55228              
+       2005  4  9  53469      -0.0252      0.2397     -0.55354              
+       2005  4 10  53470      -0.0267      0.2408     -0.55465              
+       2005  4 11  53471      -0.0281      0.2420     -0.55556              
+       2005  4 12  53472      -0.0295      0.2431     -0.55626              
+       2005  4 13  53473      -0.0310      0.2443     -0.55677              
+       2005  4 14  53474      -0.0323      0.2455     -0.55715              
+       2005  4 15  53475      -0.0337      0.2468     -0.55748              
+       2005  4 16  53476      -0.0351      0.2480     -0.55785              
+       2005  4 17  53477      -0.0364      0.2493     -0.55833              
+       2005  4 18  53478      -0.0377      0.2505     -0.55899              
+       2005  4 19  53479      -0.0390      0.2518     -0.55988              
+       2005  4 20  53480      -0.0403      0.2531     -0.56095              
+       2005  4 21  53481      -0.0415      0.2545     -0.56216              
+       2005  4 22  53482      -0.0427      0.2558     -0.56347              
+       2005  4 23  53483      -0.0439      0.2572     -0.56478              
+       2005  4 24  53484      -0.0451      0.2585     -0.56599              
+       2005  4 25  53485      -0.0463      0.2599     -0.56699              
+       2005  4 26  53486      -0.0474      0.2613     -0.56769              
+       2005  4 27  53487      -0.0485      0.2627     -0.56808              
+       2005  4 28  53488      -0.0496      0.2641     -0.56824              
+       2005  4 29  53489      -0.0507      0.2656     -0.56830              
+       2005  4 30  53490      -0.0517      0.2670     -0.56839              
+       2005  5  1  53491      -0.0527      0.2685     -0.56860              
+       2005  5  2  53492      -0.0537      0.2700     -0.56897              
+       2005  5  3  53493      -0.0547      0.2714     -0.56955              
+       2005  5  4  53494      -0.0556      0.2729     -0.57032              
+       2005  5  5  53495      -0.0565      0.2744     -0.57119              
+       2005  5  6  53496      -0.0574      0.2760     -0.57204              
+       2005  5  7  53497      -0.0583      0.2775     -0.57277              
+       2005  5  8  53498      -0.0591      0.2790     -0.57329              
+       2005  5  9  53499      -0.0600      0.2806     -0.57354              
+       2005  5 10  53500      -0.0607      0.2821     -0.57350              
+       2005  5 11  53501      -0.0615      0.2837     -0.57328              
+       2005  5 12  53502      -0.0622      0.2853     -0.57298              
+       2005  5 13  53503      -0.0630      0.2869     -0.57261              
+       2005  5 14  53504      -0.0636      0.2885     -0.57218              
+       2005  5 15  53505      -0.0643      0.2901     -0.57175              
+       2005  5 16  53506      -0.0649      0.2917     -0.57143              
+       2005  5 17  53507      -0.0655      0.2933     -0.57124              
+       2005  5 18  53508      -0.0661      0.2949     -0.57117              
+       2005  5 19  53509      -0.0667      0.2966     -0.57124              
+       2005  5 20  53510      -0.0672      0.2982     -0.57139              
+       2005  5 21  53511      -0.0677      0.2999     -0.57158              
+       2005  5 22  53512      -0.0682      0.3015     -0.57166              
+       2005  5 23  53513      -0.0686      0.3032     -0.57155              
+       2005  5 24  53514      -0.0690      0.3048     -0.57116              
+       2005  5 25  53515      -0.0694      0.3065     -0.57057              
+       2005  5 26  53516      -0.0698      0.3082     -0.56989              
+       2005  5 27  53517      -0.0701      0.3098     -0.56921              
+       2005  5 28  53518      -0.0704      0.3115     -0.56860              
+       2005  5 29  53519      -0.0707      0.3132     -0.56818              
+       2005  5 30  53520      -0.0710      0.3149     -0.56799              
+       2005  5 31  53521      -0.0712      0.3166     -0.56800              
+       2005  6  1  53522      -0.0714      0.3183     -0.56809              
+       2005  6  2  53523      -0.0716      0.3200     -0.56815              
+       2005  6  3  53524      -0.0717      0.3217     -0.56808              
+       2005  6  4  53525      -0.0718      0.3234     -0.56781              
+       2005  6  5  53526      -0.0719      0.3251     -0.56728              
+       2005  6  6  53527      -0.0720      0.3268     -0.56651              
+       2005  6  7  53528      -0.0720      0.3285     -0.56557              
+       2005  6  8  53529      -0.0720      0.3302     -0.56454              
+       2005  6  9  53530      -0.0720      0.3319     -0.56347              
+       2005  6 10  53531      -0.0720      0.3336     -0.56244              
+       2005  6 11  53532      -0.0719      0.3353     -0.56148              
+       2005  6 12  53533      -0.0718      0.3370     -0.56060              
+       2005  6 13  53534      -0.0717      0.3387     -0.55990              
+       2005  6 14  53535      -0.0715      0.3404     -0.55943              
+       2005  6 15  53536      -0.0713      0.3421     -0.55916              
+       2005  6 16  53537      -0.0711      0.3438     -0.55897              
+       2005  6 17  53538      -0.0709      0.3455     -0.55881              
+       2005  6 18  53539      -0.0707      0.3472     -0.55859              
+       2005  6 19  53540      -0.0704      0.3489     -0.55820              
+       2005  6 20  53541      -0.0701      0.3506     -0.55751              
+       2005  6 21  53542      -0.0697      0.3523     -0.55650              
+       2005  6 22  53543      -0.0694      0.3540     -0.55529              
+       2005  6 23  53544      -0.0690      0.3557     -0.55402              
+       2005  6 24  53545      -0.0686      0.3573     -0.55279              
+       2005  6 25  53546      -0.0682      0.3590     -0.55173              
+       2005  6 26  53547      -0.0677      0.3607     -0.55093              
+       2005  6 27  53548      -0.0673      0.3623     -0.55037              
+       2005  6 28  53549      -0.0668      0.3640     -0.54994              
+       2005  6 29  53550      -0.0662      0.3656     -0.54947              
+       2005  6 30  53551      -0.0657      0.3673     -0.54884              
+       2005  7  1  53552      -0.0651      0.3689     -0.54798              
+       2005  7  2  53553      -0.0645      0.3705     -0.54689              
+       2005  7  3  53554      -0.0639      0.3721     -0.54560              
+       2005  7  4  53555      -0.0633      0.3738     -0.54414              
+       2005  7  5  53556      -0.0626      0.3754     -0.54257              
+       2005  7  6  53557      -0.0620      0.3770     -0.54101              
+       2005  7  7  53558      -0.0613      0.3786     -0.53952              
+       2005  7  8  53559      -0.0605      0.3801     -0.53819              
+       2005  7  9  53560      -0.0598      0.3817     -0.53705              
+       2005  7 10  53561      -0.0590      0.3833     -0.53611              
+       2005  7 11  53562      -0.0583      0.3848     -0.53535              
+       2005  7 12  53563      -0.0575      0.3864     -0.53475              
+       2005  7 13  53564      -0.0566      0.3879     -0.53425              
+       2005  7 14  53565      -0.0558      0.3895     -0.53374              
+       2005  7 15  53566      -0.0549      0.3910     -0.53315              
+       2005  7 16  53567      -0.0541      0.3925     -0.53243              
+       2005  7 17  53568      -0.0532      0.3940     -0.53152              
+       2005  7 18  53569      -0.0523      0.3955     -0.53042              
+       2005  7 19  53570      -0.0513      0.3969     -0.52913              
+       2005  7 20  53571      -0.0504      0.3984     -0.52776              
+       2005  7 21  53572      -0.0494      0.3998     -0.52644              
+       2005  7 22  53573      -0.0485      0.4013     -0.52532              
+       2005  7 23  53574      -0.0475      0.4027     -0.52451              
+       2005  7 24  53575      -0.0464      0.4041     -0.52400              
+       2005  7 25  53576      -0.0454      0.4055     -0.52377              
+       2005  7 26  53577      -0.0444      0.4069     -0.52366              
+       2005  7 27  53578      -0.0433      0.4083     -0.52344              
+       2005  7 28  53579      -0.0423      0.4096     -0.52299              
+       2005  7 29  53580      -0.0412      0.4110     -0.52228              
+       2005  7 30  53581      -0.0401      0.4123     -0.52130              
+       2005  7 31  53582      -0.0390      0.4136     -0.52010              
+       2005  8  1  53583      -0.0378      0.4149     -0.51872              
+       2005  8  2  53584      -0.0367      0.4162     -0.51725              
+       2005  8  3  53585      -0.0356      0.4175     -0.51578              
+       2005  8  4  53586      -0.0344      0.4188     -0.51436              
+       2005  8  5  53587      -0.0332      0.4200     -0.51310              
+       2005  8  6  53588      -0.0320      0.4212     -0.51204              
+       2005  8  7  53589      -0.0309      0.4224     -0.51120              
+       2005  8  8  53590      -0.0297      0.4236     -0.51055              
+       2005  8  9  53591      -0.0284      0.4248     -0.51006              
+       2005  8 10  53592      -0.0272      0.4260     -0.50966              
+       2005  8 11  53593      -0.0260      0.4271     -0.50922              
+       2005  8 12  53594      -0.0247      0.4283     -0.50872              
+       2005  8 13  53595      -0.0235      0.4294     -0.50809              
+       2005  8 14  53596      -0.0222      0.4305     -0.50729              
+       2005  8 15  53597      -0.0210      0.4315     -0.50638              
+       2005  8 16  53598      -0.0197      0.4326     -0.50535              
+       2005  8 17  53599      -0.0184      0.4336     -0.50431              
+       2005  8 18  53600      -0.0171      0.4347     -0.50339              
+       2005  8 19  53601      -0.0158      0.4357     -0.50273              
+       2005  8 20  53602      -0.0145      0.4367     -0.50244              
+       2005  8 21  53603      -0.0132      0.4376     -0.50247              
+       2005  8 22  53604      -0.0119      0.4386     -0.50267              
+       2005  8 23  53605      -0.0106      0.4395     -0.50286              
+       2005  8 24  53606      -0.0093      0.4404     -0.50287              
+       2005  8 25  53607      -0.0079      0.4413     -0.50263              
+       2005  8 26  53608      -0.0066      0.4422     -0.50217              
+      These predictions are based on all announced leap seconds.                
+                                                                                
+    The IERS Conventions recommended software to predict celestial pole         
+    offsets is available at ftp://maia.usno.navy.mil/conventions/chapter5/      
+    ceppred.f and software for the calculation of the dX and dY with            
+    respect to IAU2000A Nutation/Precession Theory can be found at the          
+    http://maia.usno.navy.mil/conv2000.html web site in section chapter 5.      
+                                                                                
+  **************************************************************************    
+       Important Notice - IAU 2000 Resolution Compliancy Information            
+  **************************************************************************    
+                                                                                
+  Resolutions passed at the 24th General Assembly of the International          
+  Astronomical Union (IAU) recommend the implementation of a number of new      
+  procedures concerning the transformation between the celestial and            
+  terrestrial reference systems.  Information regarding these procedures        
+  is available in Chapter 5 of the IERS Conventions 2000 available at           
+  http://maia.usno.navy.mil/conv2000.html.                                      
+                                                                                
+  With these resolutions, beginning on 1 January 2003, IERS Bulletins A and     
+  B will publish new products in addition to those already published.  These    
+  products will include the celestial pole offsets X_obs-X_IAU2000A             
+  and Y_obs-Y_IAU2000A where                                                    
+                                                                                
+  X_obs and Y_obs are the observed X, Y coordinates of the Celestial            
+  Intermediate Pole in the Geocentric Celestial Reference System, and           
+                                                                                
+  X_IAU2000A and Y_IAU2000A are the celestial pole coordinates provided by      
+  using the IAU2000A Precession-Nutation theory.                                
+                                                                                
+  It is expected that Celestial Pole offsets related to the IAU1980 Nutation    
+  Theory will continue to be published through 31 December 2004.  The new       
+  celestial pole offsets related to the new IAU2000A Precession-Nutation        
+  theory will be produced in a separate data file as well as appended to        
+  to this file.                                                                 
+                                                                                
+  **************************************************************************    
+       Important Notice - IAU 2000 Resolution Compliancy Information            
+  **************************************************************************    
+                                                                                
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2a.coeff
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2a.coeff	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2a.coeff	(revision 22158)
@@ -0,0 +1,11 @@
+# Expression for the X coordinate of the CIP in the GCRS based on the IAU2000A 
+# precession-nutation model 
+# 
+# 
+# --------------------------------------------------------------------------------------------------------------
+# 
+# X = polynomial part + non-polynomial part
+# 
+# --------------------------------------------------------------------------------------------------------------
+# Polynomial part (unit microarcsecond)
+-16616.99 +2004191742.88 -427219.05 -198620.54 -46.05 +5.98
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2a.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2a.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2a.dat	(revision 22158)
@@ -0,0 +1,1630 @@
+# Expression for the X coordinate of the CIP in the GCRS based on the IAU2000A 
+# precession-nutation model 
+# 
+# 
+# --------------------------------------------------------------------------------------------------------------
+# 
+# X = polynomial part + non-polynomial part
+# 
+# --------------------------------------------------------------------------------------------------------------
+# 
+# --------------------------------------------------------------------------------------------------------------
+# 
+# Non-polynomial part (unit microarcsecond)
+# (ARG being for various combination of the fundamental arguments of the nutation theory)
+# 
+#   Sum_i[a_{s,0})_i * sin(ARG) + a_{c,0})_i * cos(ARG)] 
+# 
+# + Sum_i)j=1,4 [a_{s,j})_i * t^j * sin(ARG) + a_{c,j})_i * cos(ARG)] * t^j]
+# 
+# The Table below provides the values for a_{s,j})_i and a_{c,j})_i
+# 
+# The expressions for the fundamental arguments appearing in columns 4 to 8 (luni-solar part) 
+# and in columns 6 to 17 (planetary part) are those of the IERS Conventions 2000
+# 
+# --------------------------------------------------------------------------------------------------------------
+# 
+#     i    a_{s,j})_i      a_{c,j})_i    l    l'   F    D   Om L_Me L_Ve  L_E L_Ma  L_J L_Sa  L_U L_Ne  p_A
+# 
+# --------------------------------------------------------------------------------------------------------------
+# 
+0    -6844318.44        1328.67    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+0     -523908.04        -544.76    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+0      -90552.22         111.23    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+0       82168.76         -27.64    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+0       58707.02         470.05    0    1    0    0    0    0    0    0    0    0    0    0    0    0
+0       28288.28         -34.69    1    0    0    0    0    0    0    0    0    0    0    0    0    0
+0      -20557.78         -20.84    0    1    2   -2    2    0    0    0    0    0    0    0    0    0
+0      -15406.85          15.12    0    0    2    0    1    0    0    0    0    0    0    0    0    0
+0      -11991.74          32.46    1    0    2    0    2    0    0    0    0    0    0    0    0    0
+0       -8584.95           4.42    0    1   -2    2   -2    0    0    0    0    0    0    0    0    0
+0       -6245.02          -6.68    1    0    0   -2    0    0    0    0    0    0    0    0    0    0
+0        5095.50           7.19    0    0    2   -2    1    0    0    0    0    0    0    0    0    0
+0       -4910.93           0.76    1    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+0        2521.07          -5.97    0    0    0    2    0    0    0    0    0    0    0    0    0    0
+0        2511.85           1.07    1    0    0    0    1    0    0    0    0    0    0    0    0    0
+0        2372.58           5.93    1    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0        2307.58          -7.52    1    0    0    0   -1    0    0    0    0    0    0    0    0    0
+0       -2053.16           5.13    1    0    2    0    1    0    0    0    0    0    0    0    0    0
+0        1898.27          -0.72    2    0    0   -2    0    0    0    0    0    0    0    0    0    0
+0       -1825.49           1.23    2    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+0       -1534.09           6.29    0    0    2    2    2    0    0    0    0    0    0    0    0    0
+0       -1292.02           0.00    0    2   -2    2   -2    0    0    0    0    0    0    0    0    0
+0       -1234.96           5.21    2    0    2    0    2    0    0    0    0    0    0    0    0    0
+0        1163.22          -2.94    2    0    0    0    0    0    0    0    0    0    0    0    0    0
+0        1137.48          -0.04    1    0    2   -2    2    0    0    0    0    0    0    0    0    0
+0        1029.70          -2.63    0    0    2    0    0    0    0    0    0    0    0    0    0    0
+0        -866.48           0.52    0    0    2   -2    0    0    0    0    0    0    0    0    0    0
+0        -813.13           0.40    1    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+0         664.57          -0.40    0    2    0    0    0    0    0    0    0    0    0    0    0    0
+0        -628.24          -0.64    0    2    2   -2    2    0    0    0    0    0    0    0    0    0
+0        -603.52           0.44    1    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+0        -556.26           3.16    0    1    0    0    1    0    0    0    0    0    0    0    0    0
+0        -512.37          -1.47    1    0    0   -2    1    0    0    0    0    0    0    0    0    0
+0         506.65           2.54    0    1    0    0   -1    0    0    0    0    0    0    0    0    0
+0         438.51          -0.56    2    0   -2    0    0    0    0    0    0    0    0    0    0    0
+0         405.91           0.99    1    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0        -122.67         203.78    0    0    1   -1    1    0    0   -1    0   -2    5    0    0    0
+0        -305.78           1.75    1    0    2    2    2    0    0    0    0    0    0    0    0    0
+0         300.99          -0.44    0    1    2    0    2    0    0    0    0    0    0    0    0    0
+0        -292.37          -0.32    1    1    0   -2    0    0    0    0    0    0    0    0    0    0
+0         284.09           0.32    0    1   -2    0   -2    0    0    0    0    0    0    0    0    0
+0        -264.02           0.99    0    0    2    2    1    0    0    0    0    0    0    0    0    0
+0         261.54          -0.95    1    0    0    2    0    0    0    0    0    0    0    0    0    0
+0         256.30          -0.28    2    0    2   -2    2    0    0    0    0    0    0    0    0    0
+0        -250.54           0.08    0    0    0    2    1    0    0    0    0    0    0    0    0    0
+0         230.72           0.08    1    0    2   -2    1    0    0    0    0    0    0    0    0    0
+0         229.78          -0.60    2    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+0        -212.82           0.84    2    0    2    0    1    0    0    0    0    0    0    0    0    0
+0         196.64          -0.84    0    0    0    2   -1    0    0    0    0    0    0    0    0    0
+0         188.95          -0.12    0    1   -2    2   -1    0    0    0    0    0    0    0    0    0
+0         187.95          -0.24    1   -1    0    0    0    0    0    0    0    0    0    0    0    0
+0        -160.15         -14.04    1    0    0   -1    0    0    0    0    0    0    0    0    0    0
+0        -172.95          -0.40    0    1    0   -2    0    0    0    0    0    0    0    0    0    0
+0        -168.26           0.20    0    0    0    1    0    0    0    0    0    0    0    0    0    0
+0         161.79           0.24    2    0    0   -2    1    0    0    0    0    0    0    0    0    0
+0         161.34           0.20    1    0   -2    0    0    0    0    0    0    0    0    0    0    0
+0          57.44          95.82    0    0    0    0    0    0    0    0    0    2   -5    0    0   -1
+0         142.16           0.20    0    1    2   -2    1    0    0    0    0    0    0    0    0    0
+0        -134.81           0.20    1    1    0    0    0    0    0    0    0    0    0    0    0    0
+0         132.81          -0.52    1    0    2    0    0    0    0    0    0    0    0    0    0    0
+0        -130.31           0.04    1   -1    0   -1    0    0    0    0    0    0    0    0    0    0
+0         121.98          -0.08    2    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+0        -115.40           0.60    3    0    2    0    2    0    0    0    0    0    0    0    0    0
+0        -114.49           0.32    1   -1    2    0    2    0    0    0    0    0    0    0    0    0
+0         112.14           0.28    1    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0         105.29           0.44    0    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0          98.69          -0.28    1    1    2    0    2    0    0    0    0    0    0    0    0    0
+0          91.31          -0.40    2    0    0    0   -1    0    0    0    0    0    0    0    0    0
+0          86.74          -0.08    2    0    0    0    1    0    0    0    0    0    0    0    0    0
+0         -18.38          63.80    0    0    0    0    0    0    0    4   -8    3    0    0    0    0
+0          82.14           0.00    0    0    0    0    0    0    3   -5    0    0    0    0    0   -2
+0          79.03          -0.24    1    0   -2    2   -1    0    0    0    0    0    0    0    0    0
+0           0.00         -79.08    0    1   -1    1   -1    0    0    0    0    0    0    0    0    0
+0         -78.56           0.00    1    0    0    0    2    0    0    0    0    0    0    0    0    0
+0          47.73          23.79    0    0    1   -1    1    0   -8   12    0    0    0    0    0    0
+0          66.03          -0.20    0    0    2    1    2    0    0    0    0    0    0    0    0    0
+0          62.65          -0.24    3    0    0    0    0    0    0    0    0    0    0    0    0    0
+0          60.50           0.36    1    0   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0          59.07           0.00    0    0    0    0    0    0    1   -1    0    0    0    0    0    0
+0          57.28           0.00    0    0    0    0    0    0    0    8  -16    4    5    0    0    0
+0         -55.66           0.16    1    0    0    0   -2    0    0    0    0    0    0    0    0    0
+0         -54.81          -0.08    2    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0         -53.22          -0.20    1    0    0   -4    0    0    0    0    0    0    0    0    0    0
+0         -52.95           0.32    1    0    2    2    1    0    0    0    0    0    0    0    0    0
+0         -52.27           0.00    1   -1    0   -1   -1    0    0    0    0    0    0    0    0    0
+0          51.32           0.00    1    1    2   -2    2    0    0    0    0    0    0    0    0    0
+0         -51.00          -0.12    2    0    0   -4    0    0    0    0    0    0    0    0    0    0
+0          51.02           0.00    0    2   -2    2   -1    0    0    0    0    0    0    0    0    0
+0         -48.65          -1.15    0    0    0    0    0    0    0    1    0   -1    0    0    0    0
+0          48.29           0.20    2    0   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0         -46.38           0.00    0    0    0    0    0    0    0    0    0    2    0    0    0    2
+0         -45.59          -0.12    1    0   -4    0   -2    0    0    0    0    0    0    0    0    0
+0         -43.76           0.36    2    0    2    2    2    0    0    0    0    0    0    0    0    0
+0         -40.58          -1.00    1    0    0   -1   -1    0    0    0    0    0    0    0    0    0
+0           0.00         -41.53    1    0   -1    0   -1    0    0    0    0    0    0    0    0    0
+0          40.54          -0.04    2    0    2   -2    1    0    0    0    0    0    0    0    0    0
+0          40.33          -0.04    2    1    0   -2    0    0    0    0    0    0    0    0    0    0
+0         -38.57           0.08    1    0    0    2    1    0    0    0    0    0    0    0    0    0
+0          37.75           0.04    1   -1    0   -2    0    0    0    0    0    0    0    0    0    0
+0          37.15          -0.12    3    0    2   -2    2    0    0    0    0    0    0    0    0    0
+0          36.68          -0.04    0    0    4   -2    2    0    0    0    0    0    0    0    0    0
+0         -18.30         -17.30    0    0    0    0    1    0    0   -1    2    0    0    0    0    0
+0         -17.86          17.10    0    0    0    0    0    0    0    1   -2    0    0    0    0    0
+0         -34.81           0.04    0    1   -2    2    0    0    0    0    0    0    0    0    0    0
+0         -33.22           0.08    0    0    2   -2   -1    0    0    0    0    0    0    0    0    0
+0          32.43          -0.04    0    1    2    0    1    0    0    0    0    0    0    0    0    0
+0         -30.47           0.04    1    0    2   -2    0    0    0    0    0    0    0    0    0    0
+0         -29.53           0.04    1    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+0          28.50          -0.08    2    0   -2    0    1    0    0    0    0    0    0    0    0    0
+0          28.35          -0.16    0    1    0    0    2    0    0    0    0    0    0    0    0    0
+0         -28.00           0.00    0    0    2   -1    2    0    0    0    0    0    0    0    0    0
+0         -27.61           0.20    0    0    2    4    2    0    0    0    0    0    0    0    0    0
+0         -26.77           0.08    0    1    0    2    0    0    0    0    0    0    0    0    0    0
+0          26.54          -0.12    0    0    2    0   -1    0    0    0    0    0    0    0    0    0
+0          26.54           0.04    0    1   -2    0   -1    0    0    0    0    0    0    0    0    0
+0         -26.17           0.00    0    1    2   -2    0    0    0    0    0    0    0    0    0    0
+0         -25.42          -0.08    1    0   -2   -2    0    0    0    0    0    0    0    0    0    0
+0         -16.91           8.43    0    0    0    0    0    0    8  -13    0    0    0    0    0   -1
+0           0.32          24.42    0    0    0    0    0    0    2   -3    0    0    0    0    0    0
+0         -19.53           5.09    0    0    0    0    0    0    0    0    0    2   -5    0    0    0
+0         -23.79           0.00    0    0    0    0    0    0    2   -2    0    0    0    0    0    0
+0          23.66           0.00    1   -1    0   -1   -2    0    0    0    0    0    0    0    0    0
+0         -23.47           0.16    1   -1    2    2    2    0    0    0    0    0    0    0    0    0
+0          23.39          -0.12    2    0    0    2    0    0    0    0    0    0    0    0    0    0
+0         -23.49           0.00    0    1    0    0   -2    0    0    0    0    0    0    0    0    0
+0         -23.28          -0.08    1    1    0   -2    1    0    0    0    0    0    0    0    0    0
+0         -22.99           0.04    1    0   -2    2    0    0    0    0    0    0    0    0    0    0
+0         -22.67          -0.08    1   -1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0           9.35          13.29    0    0    0    0    0    0    8  -13    0    0    0    0    0    0
+0          22.47          -0.04    0    1    0    1    0    0    0    0    0    0    0    0    0    0
+0           4.89         -16.55    0    0    0    0    0    0    0    2   -8    3    0    0    0   -2
+0           4.89         -16.51    0    0    0    0    0    0    0    6   -8    3    0    0    0    2
+0          21.28          -0.08    0    1    2    2    2    0    0    0    0    0    0    0    0    0
+0          20.57           0.64    0    0    0    0    0    0    0    3    0   -1    0    0    0    2
+0          21.01           0.00    1   -1    0    0    1    0    0    0    0    0    0    0    0    0
+0           1.23         -19.13    0    0    1   -1    1    0    0   -1    0    2   -5    0    0    0
+0         -19.97           0.12    3    0    2    0    1    0    0    0    0    0    0    0    0    0
+0          19.65          -0.08    0    0    0    4    0    0    0    0    0    0    0    0    0    0
+0          19.58          -0.12    1    0    0    2   -1    0    0    0    0    0    0    0    0    0
+0          19.61          -0.08    1   -1    0    2    0    0    0    0    0    0    0    0    0    0
+0         -19.41           0.08    2   -1    2    0    2    0    0    0    0    0    0    0    0    0
+0         -19.49           0.00    0    0    0    0    0    0    4   -6    0    0    0    0    0   -2
+0         -18.64           0.00    0    0    0    2    2    0    0    0    0    0    0    0    0    0
+0          18.58           0.04    1    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0         -18.42           0.00    1   -1   -2    0   -2    0    0    0    0    0    0    0    0    0
+0          18.22           0.00    0    0    0    0    0    0    2   -4    0    0    0    0    0   -2
+0          -0.72         -17.34    0    0    2   -2    1    0   -5    6    0    0    0    0    0    0
+0         -18.02          -0.04    1    0    2   -4    1    0    0    0    0    0    0    0    0    0
+0          17.74           0.08    0    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0          17.46           0.00    2    0    0   -2    0    0    0   -2    0    2    0    0    0    0
+0         -17.42           0.00    0    3    2   -2    2    0    0    0    0    0    0    0    0    0
+0          -6.60          10.70    0    0    0    0    0    0    0    1    0   -2    0    0    0    0
+0          16.43           0.52    0    0    0    0    0    0    0    2    0   -2    0    0    0    0
+0         -16.75           0.04    1   -1    2    0    1    0    0    0    0    0    0    0    0    0
+0          16.55          -0.08    0    0    2    2    0    0    0    0    0    0    0    0    0    0
+0          16.39          -0.08    2    1    2    0    2    0    0    0    0    0    0    0    0    0
+0          13.88          -2.47    2    0    0   -2    0    0    0   -2    0    3    0    0    0    0
+0          15.69           0.00    1    0    0   -2   -2    0    0    0    0    0    0    0    0    0
+0         -15.52           0.00    0    0    0    1    1    0    0    0    0    0    0    0    0    0
+0           3.34          11.86    0    0    0    0    1    0    0   -4    8   -3    0    0    0    0
+0          14.72          -0.32    0    0    0    0    0    0    2    0    0    0    0    0    0    2
+0          14.92          -0.04    2   -1    0    0    0    0    0    0    0    0    0    0    0    0
+0          -3.26          11.62    0    0    0    0    1    0    0    4   -8    3    0    0    0    0
+0         -14.64           0.00    0    0    0    0    0    0    0    2   -2    0    0    0    0    0
+0           0.00          14.47    1    0   -1    0   -2    0    0    0    0    0    0    0    0    0
+0         -14.37           0.00    1    1    0    0    1    0    0    0    0    0    0    0    0    0
+0          14.32          -0.04    1    1    2    0    1    0    0    0    0    0    0    0    0    0
+0         -14.10           0.04    1    0   -2    2   -2    0    0    0    0    0    0    0    0    0
+0          10.86           3.18    0    0    1   -1    1    0    0    0   -2    0    0    0    0    0
+0         -10.58          -3.10    0    0    1   -1    0    0    0    0   -2    0    0    0    0    0
+0          -3.62           9.86    0    0    0    0    0    0    0    0    0    1    0    0    0    0
+0         -13.48           0.00    0    0    0    0    0    0    1    1    0    0    0    0    0    2
+0          13.41          -0.04    1    0    2    1    2    0    0    0    0    0    0    0    0    0
+0          13.32          -0.08    2    0    2    0    0    0    0    0    0    0    0    0    0    0
+0         -13.33          -0.04    0    1    0   -2    1    0    0    0    0    0    0    0    0    0
+0         -13.29           0.00    1    0    2   -1    2    0    0    0    0    0    0    0    0    0
+0          -0.20          13.05    0    0    0    0    0    0    3   -4    0    0    0    0    0    0
+0           0.00          13.13    1    0   -1    0    0    0    0    0    0    0    0    0    0    0
+0          -8.99           4.02    1    0    0    0    0    0  -18   16    0    0    0    0    0    0
+0         -12.93           0.04    1    0    0    1    0    0    0    0    0    0    0    0    0    0
+0           2.03          10.82    0    0    0    0    0    0    0    0    0    2    0    0    0    1
+0         -12.78           0.04    0    0    0    1   -1    0    0    0    0    0    0    0    0    0
+0          12.24           0.04    1    0    0   -2    2    0    0    0    0    0    0    0    0    0
+0           8.71           3.54    1    0    0    0    0    0  -10    3    0    0    0    0    0    0
+0          11.98          -0.04    1   -1    0    0   -1    0    0    0    0    0    0    0    0    0
+0         -11.38           0.04    2    1    0    0    0    0    0    0    0    0    0    0    0    0
+0         -11.30           0.00    2    0    0   -2   -1    0    0   -2    0    2    0    0    0    0
+0          11.14          -0.04    0    0    2    1    1    0    0    0    0    0    0    0    0    0
+0          10.98           0.00    0    3    0    0    0    0    0    0    0    0    0    0    0    0
+0         -10.98           0.00    1    2    0   -2    0    0    0    0    0    0    0    0    0    0
+0           0.44         -10.38    0    0    0    0    0    0    5   -8    0    0    0    0    0   -2
+0          10.46           0.08    1    0   -2   -4   -1    0    0    0    0    0    0    0    0    0
+0         -10.42           0.00    0    0    0    0    0    0    0    1    0    1    0    0    0    2
+0         -10.30           0.08    4    0    2    0    2    0    0    0    0    0    0    0    0    0
+0           6.92           3.34    0    0    1   -1    1    0    0   -1    0    0   -1    0    0    0
+0          10.07           0.04    1    0   -2    0    1    0    0    0    0    0    0    0    0    0
+0          10.02           0.00    2    1    2   -2    2    0    0    0    0    0    0    0    0    0
+0          -9.75           0.04    0    1    2    1    2    0    0    0    0    0    0    0    0    0
+0           9.75           0.00    1    1    2   -2    1    0    0    0    0    0    0    0    0    0
+0           9.67          -0.04    1    0    4   -2    2    0    0    0    0    0    0    0    0    0
+0          -1.99           7.72    0    0    1   -1    1    0    0   -1    0   -1    0    0    0    0
+0           0.40           9.27    0    0    2   -2    0    0   -5    6    0    0    0    0    0    0
+0          -3.42           6.09    0    0    0    0    0    0    0    2   -4    0    0    0    0    0
+0           0.56          -8.67    0    0    0    0    0    0    0    0    0    2   -5    0    0    1
+0          -9.19           0.00    2    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0           9.11           0.00    1    0   -2    1   -1    0    0    0    0    0    0    0    0    0
+0           9.07           0.00    2   -2    0   -2    0    0    0    0    0    0    0    0    0    0
+0           1.63           6.96    0    0    0    0    0    0    8  -13    0    0    0    0    0   -2
+0          -8.47           0.00    0    2    0   -2    0    0    0    0    0    0    0    0    0    0
+0          -8.28           0.04    1    1    0    0   -1    0    0    0    0    0    0    0    0    0
+0           8.27           0.04    2    0   -2   -4   -1    0    0    0    0    0    0    0    0    0
+0          -8.04           0.00    0    0    0    0    0    0    5   -7    0    0    0    0    0   -2
+0           7.91           0.00    0    1    0    2    1    0    0    0    0    0    0    0    0    0
+0          -7.84          -0.04    1    0   -4    0   -1    0    0    0    0    0    0    0    0    0
+0          -7.64           0.08    2    0    2    2    1    0    0    0    0    0    0    0    0    0
+0           5.21          -2.51    1    0    2    0    2    0    0    1    0    0    0    0    0    0
+0          -5.77           1.87    0    0    0    0    0    0    3   -5    0    0    0    0    0    0
+0           5.01          -2.51    1    0   -2    0   -2    0    0    4   -8    3    0    0    0    0
+0          -7.48           0.00    0    0    2   -3    2    0    0    0    0    0    0    0    0    0
+0          -7.32          -0.12    0    0    0    0    0    0    0    4    0   -2    0    0    0    2
+0           7.40          -0.04    0    0    4    0    2    0    0    0    0    0    0    0    0    0
+0           7.44           0.00    1    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+0           6.32          -1.11    1    0    0   -1    1    0    0    0    0    0    0    0    0    0
+0          -6.13          -1.19    0    0    0    0    0    0    0    2    0   -1    0    0    0    2
+0           0.20          -6.88    0    0    0    0    0    0    2   -1    0    0    0    0    0    2
+0           6.92           0.04    1    1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0           6.48          -0.48    0    0    0    0    0    0    0    2    0    1    0    0    0    2
+0          -6.94           0.00    2    0    0   -2   -2    0    0    0    0    0    0    0    0    0
+0           2.47          -4.46    0    0    0    0    0    0    8  -11    0    0    0    0    0   -2
+0          -2.23          -4.65    0    0    0    0    0    0    0    8  -16    4    5    0    0   -2
+0          -1.07          -5.69    0    0    1   -1    1    0    0   -1    0    2    0    0    0    0
+0           4.97          -1.71    0    0    0    0    0    0    0    8  -16    4    5    0    0    2
+0           5.57           1.07    0    0    1   -1    1    0   -5    7    0    0    0    0    0    0
+0          -6.48           0.08    1    0    2    4    2    0    0    0    0    0    0    0    0    0
+0           2.03           4.53    0    0    0    0    0    0    0    0    0    0    2    0    0    1
+0           4.10          -2.39    1    0    0   -2    0    0   19  -21    3    0    0    0    0    0
+0           0.00          -6.44    0    0    1    0    1    0    0    0    0    0    0    0    0    0
+0          -6.40           0.00    3    0    0   -4    0    0    0    0    0    0    0    0    0    0
+0           6.32           0.00    1    1   -2    0   -2    0    0    0    0    0    0    0    0    0
+0           2.67          -3.62    0    0    0    0    0    0    0    3    0   -2    0    0    0    2
+0          -1.91          -4.38    0    0    1   -1    1    0    0   -1    0    0    2    0    0    0
+0          -2.43          -3.82    0    0    0    0    0    0    8  -15    0    0    0    0    0   -2
+0           6.20           0.00    0    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+0          -3.38          -2.78    0    0    0    0    0    0    0    1    2    0    0    0    0    2
+0          -6.12           0.04    0    0    0    4    1    0    0    0    0    0    0    0    0    0
+0          -6.09          -0.04    0    0    2   -4    1    0    0    0    0    0    0    0    0    0
+0          -6.01          -0.04    1    1    0   -4    0    0    0    0    0    0    0    0    0    0
+0           3.18          -2.82    0    0    0    0    0    0    0    3   -2    0    0    0    0    2
+0          -5.05           0.84    0    0    0    0    0    0    0    0    0    3    0    0    0    2
+0           5.85           0.00    3    0    2   -2    1    0    0    0    0    0    0    0    0    0
+0           5.69          -0.12    0    0    0    0    0    0    0    4   -2    0    0    0    0    2
+0           5.73          -0.04    1    1    2    2    2    0    0    0    0    0    0    0    0    0
+0           5.61           0.00    0    0    4   -2    1    0    0    0    0    0    0    0    0    0
+0           5.49           0.00    2    0    0   -2    0    0   -3    3    0    0    0    0    0    0
+0          -5.33           0.04    3    0    2    2    2    0    0    0    0    0    0    0    0    0
+0          -5.29           0.00    0    0    0    0    0    0    0    0    0    0    2    0    0    2
+0           5.25           0.00    2    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.99           4.22    0    0    0    0    0    0    4   -6    0    0    0    0    0   -1
+0          -0.99           4.22    0    0    0    0    0    0    1   -1    0    0    0    0    0   -1
+0           0.00           5.21    1    0    0   -1    0    0   -3    4    0    0    0    0    0    0
+0           5.13           0.04    0    2   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0          -4.90           0.00    2    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+0          -3.10           1.79    0    0    0    0    0    0    0    3   -4    0    0    0    0    0
+0          -4.81           0.04    0    0    2    4    1    0    0    0    0    0    0    0    0    0
+0          -4.75           0.00    0    0    0    2   -2    0    0    0    0    0    0    0    0    0
+0           4.70          -0.04    3    0    0    0   -1    0    0    0    0    0    0    0    0    0
+0          -4.69           0.00    0    0    0    0    0    0    0    1    0   -3    0    0    0   -2
+0          -4.65           0.00    0    0    0    0    0    0    6   -8    0    0    0    0    0   -2
+0           4.65           0.00    0    0    2   -2    1    0   -3    3    0    0    0    0    0    0
+0          -4.57           0.00    2    1    0   -4    0    0    0    0    0    0    0    0    0    0
+0           4.49          -0.04    4    0    2   -2    2    0    0    0    0    0    0    0    0    0
+0          -4.53           0.00    0    0    1   -1    1    0    0    3   -8    3    0    0    0    0
+0           0.00          -4.53    0    0    0    0    0    0    3   -2    0    0    0    0    0    2
+0           0.00          -4.53    0    0    0    0    0    0    2   -5    0    0    0    0    0   -2
+0          -4.53           0.00    2    0    0    2    1    0    0    0    0    0    0    0    0    0
+0           4.50           0.00    1   -1    0   -2   -1    0    0    0    0    0    0    0    0    0
+0          -4.49           0.00    0    0    0    0    0    0    1   -3    0    0    0    0    0   -2
+0           1.83           2.63    0    0    0    0    1    0    8  -13    0    0    0    0    0    0
+0           4.38           0.00    2    1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0           0.88          -3.46    0    0    0    0    0    0    1   -2    0    0    0    0    0    0
+0          -2.70           1.55    0    0    0    0    0    0    0    2   -3    0    0    0    0    0
+0          -4.22           0.00    0    0    2   -1    1    0    0    0    0    0    0    0    0    0
+0          -4.10          -0.12    1    1    0    2    0    0    0    0    0    0    0    0    0    0
+0           3.54          -0.64    2    0    0   -2    1    0    0   -2    0    3    0    0    0    0
+0          -3.50           0.68    0    0    0    0    0    0    5   -8    0    0    0    0    0   -1
+0           4.18           0.00    1   -1   -2    2   -1    0    0    0    0    0    0    0    0    0
+0           4.14           0.00    1    2   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0           4.10           0.00    1    0    0   -3    0    0    0    0    0    0    0    0    0    0
+0          -4.06           0.00    2    0    0   -4    1    0    0    0    0    0    0    0    0    0
+0           2.70          -1.35    1    0    0    0   -1    0  -18   16    0    0    0    0    0    0
+0          -4.04           0.00    2    0    0   -2    2    0    0    0    0    0    0    0    0    0
+0          -3.98          -0.04    1    0    0   -4    1    0    0    0    0    0    0    0    0    0
+0          -3.98           0.04    1   -1    2    2    1    0    0    0    0    0    0    0    0    0
+0           4.02           0.00    2    0    2   -4    1    0    0    0    0    0    0    0    0    0
+0           3.94           0.00    0    0    1   -1    1    0    0   -5    8   -3    0    0    0    0
+0           0.84          -3.10    0    0    1   -1    0    0    0   -1    0   -1    0    0    0    0
+0           3.30           0.60    0    0    0    0    0    0    0    2    0   -3    0    0    0    0
+0          -1.59           2.27    0    0    0    0    1    0   -8   13    0    0    0    0    0    0
+0          -3.66          -0.20    2   -1    0   -2    0    0    0    0    0    0    0    0    0    0
+0          -3.10          -0.72    2    0    0   -2    0    0   -6    8    0    0    0    0    0    0
+0          -3.82           0.00    1   -1   -2    0   -1    0    0    0    0    0    0    0    0    0
+0          -3.62          -0.16    2    1   -2    0   -1    0    0    0    0    0    0    0    0    0
+0          -3.74           0.00    0    1   -2    1   -2    0    0    0    0    0    0    0    0    0
+0           3.74           0.00    4    0    0    0    0    0    0    0    0    0    0    0    0    0
+0          -3.74           0.00    0    2   -2    2    0    0    0    0    0    0    0    0    0    0
+0          -3.71           0.00    0    2    0    0    1    0    0    0    0    0    0    0    0    0
+0           3.02           0.68    0    0    0    0    1    0    0    0    0   -2    5    0    0    0
+0           3.70           0.00    1    0   -4    2   -2    0    0    0    0    0    0    0    0    0
+0           3.30           0.40    0    2   -2    0   -2    0    0    0    0    0    0    0    0    0
+0          -3.66           0.04    2   -1    2    2    2    0    0    0    0    0    0    0    0    0
+0           3.66           0.04    0    1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0          -3.62           0.00    1    0   -2   -3   -2    0    0    0    0    0    0    0    0    0
+0          -3.61           0.00    2    0    0    0    2    0    0    0    0    0    0    0    0    0
+0          -2.90           0.68    0    0    0    0    1    0    0    0    0    2   -5    0    0    0
+0           0.80          -2.78    0    0    0    0    1    0    0    0    0    1    0    0    0    0
+0           3.54           0.00    0    0    0    0    0    0    3   -3    0    0    0    0    0    0
+0          -3.54           0.00    0    0    0    0    0    0    0    2    0    0    0    0    0    2
+0          -3.50           0.00    2    0    2   -2    0    0    0    0    0    0    0    0    0    0
+0           3.45           0.00    0    2    2   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00          -3.42    0    0    0    0    0    0    0    6  -16    4    5    0    0   -2
+0           3.38           0.00    1   -2    0    0    0    0    0    0    0    0    0    0    0    0
+0           2.27          -1.11    1    0    0    0    1    0  -18   16    0    0    0    0    0    0
+0          -3.34           0.00    1   -1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0           3.34           0.00    0    1    2    2    1    0    0    0    0    0    0    0    0    0
+0          -3.30           0.01    0    0    2    0    3    0    0    0    0    0    0    0    0    0
+0           3.31           0.00    1    0    2    0   -1    0    0    0    0    0    0    0    0    0
+0           3.30           0.00    3    0    0    0    1    0    0    0    0    0    0    0    0    0
+0          -3.30           0.00    1    0   -2   -1   -2    0    0    0    0    0    0    0    0    0
+0          -1.39          -1.91    0    0    0    0    0    0    0    1    0    2    0    0    0    2
+0           3.30           0.00    0    0    0    0    0    0    4   -4    0    0    0    0    0    0
+0           3.26           0.00    2    1    0   -2    1    0    0    0    0    0    0    0    0    0
+0           3.26           0.00    1    0    0    4    0    0    0    0    0    0    0    0    0    0
+0           3.22          -0.04    1    0    2    2    0    0    0    0    0    0    0    0    0    0
+0          -3.26           0.00    2   -1   -2    0   -1    0    0    0    0    0    0    0    0    0
+0           2.51          -0.64    0    0    0    0    0    0    3   -7    0    0    0    0    0   -2
+0           3.14           0.00    2    0   -4    0   -2    0    0    0    0    0    0    0    0    0
+0          -2.63          -0.48    0    0    1   -1    1    0    0   -1    0    0    1    0    0    0
+0           3.10           0.00    3    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+0          -3.06           0.00    2   -1    2    0    1    0    0    0    0    0    0    0    0    0
+0           2.94          -0.12    1   -2    0   -2    0    0    0    0    0    0    0    0    0    0
+0           3.06           0.00    2    0   -2    2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           2.98    0    0    1    0    0    0    0    0    0    0    0    0    0    0
+0           2.98           0.00    1    0    2   -4    0    0    0    0    0    0    0    0    0    0
+0           2.07           0.91    0    0    0    0    0    0    0    0    0    1    0    0    0    2
+0          -2.98           0.00    0    0    0    0    0    0    0    1    0    0   -1    0    0    0
+0           2.94           0.00    0    2    2    0    2    0    0    0    0    0    0    0    0    0
+0          -2.94           0.00    0    0    0    0    0    0    7   -9    0    0    0    0    0   -2
+0          -2.94           0.00    0    0    0    0    0    0    0    0    2    0    0    0    0    2
+0          -2.90           0.00    1   -1    2   -2    2    0    0    0    0    0    0    0    0    0
+0          -0.56          -2.35    0    0    0    0    0    0    2   -4    0    0    0    0    0   -1
+0          -1.47           1.39    0    0    0    0    1    0    0    1   -2    0    0    0    0    0
+0           2.80           0.00    1    0    2   -4    2    0    0    0    0    0    0    0    0    0
+0          -2.74           0.00    2    0    2   -1    2    0    0    0    0    0    0    0    0    0
+0          -0.12           2.63    0    0    0    0    0    0    4   -7    0    0    0    0    0   -2
+0           2.15          -0.60    0    0    0    0    0    0    3   -3    0    0    0    0    0    2
+0          -2.70           0.00    1    1   -2    1   -1    0    0    0    0    0    0    0    0    0
+0           1.79          -0.88    0    0    0    0    0    0    0    8  -15    0    0    0    0    0
+0          -0.48           2.19    0    0    0    0    0    0    2   -2    0    0    0    0    0   -1
+0           0.44           2.23    0    0    0    0    0    0    0    0    0    0    1    0    0    0
+0           0.52           2.07    0    0    0    0    0    0    0    0    0    1    0    0    0   -1
+0          -2.59           0.00    0    1    0   -4    0    0    0    0    0    0    0    0    0    0
+0           2.55           0.00    2    1    2    0    1    0    0    0    0    0    0    0    0    0
+0          -1.11           1.43    0    0    0    0    0    0    0    1    0   -3    0    0    0    0
+0          -2.51           0.00    3   -1    2    0    2    0    0    0    0    0    0    0    0    0
+0          -2.51           0.00    2    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0           2.51           0.00    1    1   -2    0   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -2.50    1    0   -1    0   -3    0    0    0    0    0    0    0    0    0
+0           2.47           0.00    1   -1    0   -2    1    0    0    0    0    0    0    0    0    0
+0           2.11          -0.36    2    0    0   -2   -1    0    0   -2    0    3    0    0    0    0
+0           1.67           0.80    0    0    1   -1    0    0    0   -1    0    0   -1    0    0    0
+0           2.46           0.00    0    2    0    0   -1    0    0    0    0    0    0    0    0    0
+0          -2.43           0.00    1    0   -2    1    0    0    0    0    0    0    0    0    0    0
+0          -2.39           0.00    1    0    2   -3    2    0    0    0    0    0    0    0    0    0
+0          -1.83           0.56    0    0    0    0    0    0    4   -6    0    0    0    0    0    0
+0          -0.44          -1.95    0    0    0    0    0    0    3   -5    0    0    0    0    0   -1
+0           0.24           2.15    0    0    0    0    0    0    0    0    0    1    0    0    0    1
+0           2.39           0.00    2    0   -2   -2    0    0    0    0    0    0    0    0    0    0
+0           2.35           0.00    0    0    0    0    0    0    5   -5    0    0    0    0    0    0
+0           2.27           0.00    1    0    2    1    1    0    0    0    0    0    0    0    0    0
+0          -2.22           0.00    2    0    0    0   -2    0    0    0    0    0    0    0    0    0
+0          -1.03          -1.15    1    0    0   -1    1    0    0   -1    0    2    0    0    0    0
+0           1.87           0.32    0    0    0    0    0    0    0    0    0    0    1    0    0    1
+0          -0.32          -1.87    0    0    1   -1    1    0    0   -2    2    0    0    0    0    0
+0           2.15           0.00    2    0    0   -2    1    0    0   -2    0    2    0    0    0    0
+0          -0.80           1.35    0    0    0    0    0    0    0    3   -5    0    0    0    0    0
+0           2.11           0.00    3    1    2    0    2    0    0    0    0    0    0    0    0    0
+0          -2.11           0.00    1    1    2    1    2    0    0    0    0    0    0    0    0    0
+0          -0.56          -1.55    0    0    0    0    0    0    5   -8    0    0    0    0    0    0
+0           2.11           0.00    1    0    0   -1    0    0    0   -1    0    1    0    0    0    0
+0          -0.84          -1.27    0    0    0    0    0    0    0    0    4    0    0    0    0    2
+0          -1.99           0.12    0    0    0    0    0    0    8  -10    0    0    0    0    0   -2
+0          -0.24           1.87    0    0    0    0    0    0    0    1   -2    0    0    0    0   -1
+0          -0.24          -1.87    0    0    1   -1    1    0    0   -1    0    1    0    0    0    0
+0          -2.03           0.00    1   -2    2    0    2    0    0    0    0    0    0    0    0    0
+0           2.03           0.00    2   -1    2   -2    2    0    0    0    0    0    0    0    0    0
+0           2.03           0.00    2    0    0   -3    0    0    0    0    0    0    0    0    0    0
+0           2.03           0.00    0    0    0    0    0    0    0    2   -4    0    0    0    0   -2
+0          -0.40           1.59    0    0    1   -1    1    0   -3    4    0    0    0    0    0    0
+0           1.99           0.00    0    0    2   -2    1    0    0   -2    0    2    0    0    0    0
+0           1.95           0.00    0    1    0    1    1    0    0    0    0    0    0    0    0    0
+0           1.95           0.00    3    0    0    2    0    0    0    0    0    0    0    0    0    0
+0           1.91           0.00    0    1    0    1   -1    0    0    0    0    0    0    0    0    0
+0           1.19          -0.72    0    0    0    0    0    0    0    5   -4    0    0    0    0    2
+0           1.87           0.00    2    0    2    1    2    0    0    0    0    0    0    0    0    0
+0           1.87           0.00    1    1    0    1    0    0    0    0    0    0    0    0    0    0
+0          -1.27           0.60    0    0    0    0    0    0    0    0    0    0    1    0    0   -1
+0           0.72          -1.15    0    0    0    0    0    0    0    4   -4    0    0    0    0    2
+0          -0.99           0.88    0    0    0    0    0    0    0    0    0    2    0    0    0    0
+0           1.87           0.00    2   -1    0    2    0    0    0    0    0    0    0    0    0    0
+0          -1.87           0.00    1    1   -2    2   -1    0    0    0    0    0    0    0    0    0
+0          -1.83           0.00    2    0   -4   -2   -2    0    0    0    0    0    0    0    0    0
+0          -1.79           0.00    0    1    0    2   -1    0    0    0    0    0    0    0    0    0
+0          -1.79           0.00    4    0    2    0    1    0    0    0    0    0    0    0    0    0
+0           1.79           0.00    1    2    2   -2    2    0    0    0    0    0    0    0    0    0
+0           0.00          -1.79    0    0    0    0    0    0    6   -9    0    0    0    0    0   -2
+0          -1.79           0.00    1    1    2   -4    1    0    0    0    0    0    0    0    0    0
+0          -1.75           0.00    0    0    4   -4    2    0    0    0    0    0    0    0    0    0
+0          -1.75           0.00    3    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0           1.75           0.00    2    1   -2    0    0    0    0    0    0    0    0    0    0    0
+0          -1.47          -0.28    0    0    0    0    0    0    0    4    0   -3    0    0    0    2
+0          -1.71           0.00    1    0    2   -3    1    0    0    0    0    0    0    0    0    0
+0           1.71           0.00    2    0   -2   -6   -2    0    0    0    0    0    0    0    0    0
+0           0.32           1.39    0    0    0    0    0    0    5   -7    0    0    0    0    0   -1
+0           0.28          -1.43    0    0    0    0    0    0    0    2    0    0    0    0    0    1
+0          -0.52          -1.19    0    0    0    0    0    0    0    1    0    2   -5    0    0    0
+0           1.67           0.00    2    0    0    2   -1    0    0    0    0    0    0    0    0    0
+0          -1.67           0.00    0    1    2    1    1    0    0    0    0    0    0    0    0    0
+0           0.76          -0.91    0    0    0    0    0    0    2    1    0    0    0    0    0    2
+0          -0.32           1.35    0    0    0    0    0    0    3   -3    0    0    0    0    0   -1
+0          -1.39          -0.28    0    0    1   -1    0    0   -5    7    0    0    0    0    0    0
+0           1.63           0.00    2    1    2   -2    1    0    0    0    0    0    0    0    0    0
+0          -1.59           0.00    1    0    2   -1    1    0    0    0    0    0    0    0    0    0
+0           1.03          -0.56    0    0    0    0    0    0    0    4   -3    0    0    0    0    2
+0           1.59           0.00    0    0    0    0    0    0    6   -6    0    0    0    0    0    0
+0           1.55           0.00    1    0    4   -2    1    0    0    0    0    0    0    0    0    0
+0          -0.28          -1.27    0    0    0    0    0    0    1   -1    0    0    0    0    0    1
+0          -0.64           0.91    0    0    0    0    0    0    0    4   -6    0    0    0    0    0
+0          -0.32          -1.23    0    0    0    0    0    0    1   -3    0    0    0    0    0   -1
+0          -1.55           0.00    1   -1    2   -2    1    0    0    0    0    0    0    0    0    0
+0          -1.51           0.00    1    0    2   -2   -1    0    0    0    0    0    0    0    0    0
+0           1.51           0.00    2   -2    0   -2   -1    0    0    0    0    0    0    0    0    0
+0          -1.51           0.00    2   -1    0   -2    1    0    0    0    0    0    0    0    0    0
+0           1.51           0.00    2    0    0   -1    0    0    0    0    0    0    0    0    0    0
+0           1.47           0.00    2    0    4   -2    2    0    0    0    0    0    0    0    0    0
+0           1.47           0.00    0    0    2    3    2    0    0    0    0    0    0    0    0    0
+0           0.95          -0.52    0    0    0    0    0    0    0    3   -6    0    0    0    0   -2
+0           1.23          -0.24    0    0    0    0    0    0    3   -1    0    0    0    0    0    2
+0           0.60           0.88    2    0    0   -2    0    0    0   -6    8    0    0    0    0    0
+0          -1.47           0.00    1   -1    0    2    1    0    0    0    0    0    0    0    0    0
+0          -1.43           0.00    1    0   -2    2    1    0    0    0    0    0    0    0    0    0
+0           1.43           0.00    1   -1    0    2   -1    0    0    0    0    0    0    0    0    0
+0           1.43           0.00    0    1    4   -2    2    0    0    0    0    0    0    0    0    0
+0          -0.68          -0.76    0    0    1   -1    1    0    0   -1    0    0    0    0    2    0
+0           0.95          -0.48    2    0    2    0    2    0    0    2    0   -3    0    0    0    0
+0          -0.95          -0.48    0    0    2    0    2    0    0    1    0    0    0    0    0    0
+0          -1.19          -0.24    0    0    0    0    0    0    0    1    0   -4    0    0    0   -2
+0           0.36          -1.07    0    0    1   -1    1    0    0   -1    0   -4   10    0    0    0
+0           0.95           0.48    2    0    0   -2    0    0    0   -5    6    0    0    0    0    0
+0           1.43           0.00    1    1    0   -1    0    0    0    0    0    0    0    0    0    0
+0           1.39           0.00    0    0    0    4   -1    0    0    0    0    0    0    0    0    0
+0           1.39           0.00    2   -1    0    0    1    0    0    0    0    0    0    0    0    0
+0          -1.39           0.00    1   -2   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0          -1.39           0.00    1    2    0    0    0    0    0    0    0    0    0    0    0    0
+0           0.00           1.39    0    0    0    0    0    0    0    2    0   -1    0    0    0    0
+0          -0.12          -1.27    0    0    0    0    0    0    0    4    0   -1    0    0    0    2
+0           0.56           0.84    0    0    0    0    0    0    0    2   -4    0    0    0    0   -1
+0          -0.44          -0.95    0    0    0    0    0    0    0    0    0    2   -5    0    0   -2
+0           0.32          -1.07    0    0    0    0    0    0    0    1    0    0    0    0    0    0
+0           1.03          -0.36    2    0   -1   -1    0    0    0    3   -7    0    0    0    0    0
+0          -0.28           1.11    0    0    1   -1    1    0   -4    5    0    0    0    0    0    0
+0           0.44           0.95    0    0    1   -1    2    0    0   -1    0    0    2    0    0    0
+0          -1.35           0.00    1   -1   -2    2    0    0    0    0    0    0    0    0    0    0
+0           0.88           0.48    0    0    0    0    0    0    0    1   -8    3    0    0    0   -2
+0          -1.35           0.00    0    0    0    0    0    0    9  -11    0    0    0    0    0   -2
+0           1.35           0.00    1    0    0   -2    0    0    0   -2    0    2    0    0    0    0
+0           1.35           0.00    1    0    0   -1   -2    0    0    0    0    0    0    0    0    0
+0          -1.31           0.00    0    1   -2    2    1    0    0    0    0    0    0    0    0    0
+0           1.31           0.00    1    0   -2    1   -2    0    0    0    0    0    0    0    0    0
+0          -1.19          -0.12    0    0    0    0    0    0    2   -3    0    0    0    0    0   -1
+0           1.27           0.00    0    0    4    0    1    0    0    0    0    0    0    0    0    0
+0           0.40          -0.88    0    0    2   -2    1    0    0   -9   13    0    0    0    0    0
+0           1.27           0.00    1    0   -2   -6   -2    0    0    0    0    0    0    0    0    0
+0           1.27           0.00    3    1    2   -2    2    0    0    0    0    0    0    0    0    0
+0          -0.16          -1.11    0    0    0    0    0    0    1    0    0    0    0    0    0    0
+0          -0.84           0.44    2    0    0    0    0    0    0   -2    0    3    0    0    0    0
+0           0.84          -0.44    1    0    2    0    1    0    0   -2    0    3    0    0    0    0
+0           0.84          -0.44    1    0   -2    0   -1    0    0   -1    0    0    0    0    0    0
+0          -1.27           0.00    1    0   -4   -2   -2    0    0    0    0    0    0    0    0    0
+0          -1.27           0.00    1    0    0    4    1    0    0    0    0    0    0    0    0    0
+0           1.27           0.00    1    1    0    2    1    0    0    0    0    0    0    0    0    0
+0          -0.44          -0.84    0    0    0    0    1    0    0   -2    4    0    0    0    0    0
+0           0.00          -1.27    0    0    0    0    1    0    2   -3    0    0    0    0    0    0
+0          -1.27           0.00    2    0    2   -4    2    0    0    0    0    0    0    0    0    0
+0          -1.23           0.00    1   -1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0          -1.23           0.00    1   -2    2    2    2    0    0    0    0    0    0    0    0    0
+0           1.23           0.00    0    0    2   -1    0    0    0    0    0    0    0    0    0    0
+0           0.00           1.23    0    0    0    0    0    0    0    3   -6    0    0    0    0    0
+0          -0.12           1.11    0    0    1    1    1    0    0    1    0    0    0    0    0    0
+0           1.22           0.00    0    0    2   -4    2    0    0    0    0    0    0    0    0    0
+0           1.19           0.00    1    1   -2   -4   -1    0    0    0    0    0    0    0    0    0
+0          -0.24           0.95    0    0    0    0    0    0    4   -4    0    0    0    0    0   -1
+0          -0.76          -0.44    0    0    0    0    0    0    0    3   -8    3    0    0    0    0
+0           0.91           0.28    0    0    0    0    0    0    0    1   -2    0    0    0    0    1
+0           1.19           0.00    1    1   -2    1    0    0    0    0    0    0    0    0    0    0
+0           1.19           0.00    3    0    2    0    0    0    0    0    0    0    0    0    0    0
+0           0.00           1.19    0    0    1    0    2    0    0    0    0    0    0    0    0    0
+0           1.15           0.00    2   -1    0    0   -1    0    0    0    0    0    0    0    0    0
+0           0.00           1.15    1    0    0   -1    1    0   -3    4    0    0    0    0    0    0
+0          -1.15           0.00    1    0    2    4    1    0    0    0    0    0    0    0    0    0
+0           1.15           0.00    2   -1   -2    0    0    0    0    0    0    0    0    0    0    0
+0          -1.15           0.00    2    0   -2    2    0    0    0    0    0    0    0    0    0    0
+0           1.15           0.00    3   -1    0    0    0    0    0    0    0    0    0    0    0    0
+0           1.15           0.00    0    0    0    0    0    0    0    3    0    0   -1    0    0    2
+0          -0.95           0.20    0    0    0    0    0    0    6  -10    0    0    0    0    0   -2
+0           0.24           0.91    0    0    0    0    0    0    0    0    0    3    0    0    0    1
+0          -1.15           0.00    1    1    2   -2    0    0    0    0    0    0    0    0    0    0
+0          -1.12           0.00    0    1    2   -2   -1    0    0    0    0    0    0    0    0    0
+0          -1.11           0.00    1    0    0    1   -1    0    0    0    0    0    0    0    0    0
+0          -1.11           0.00    1    2    0   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.16           0.95    0    0    0    0    1    0    0    0    0    0    1    0    0    0
+0          -1.11           0.00    2    0    2   -4    0    0    0    0    0    0    0    0    0    0
+0           1.11           0.00    0    0    0    0    0    0    7   -7    0    0    0    0    0    0
+0           0.20          -0.91    0    0    0    0    0    0    1    1    0    0    0    0    0    1
+0          -0.72          -0.40    0    0    0    0    0    0    0    0    3    0    0    0    0    2
+0          -1.11           0.00    1    1   -2   -2    0    0    0    0    0    0    0    0    0    0
+0          -1.11           0.00    0    0    0    0    1    0    1   -1    0    0    0    0    0    0
+0           1.07           0.00    2   -1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0          -1.07           0.00    2    0    2    4    2    0    0    0    0    0    0    0    0    0
+0           0.76          -0.32    0    0    0    0    0    0    0    1   -4    0    0    0    0   -2
+0           0.00          -1.07    0    0    0    0    0    0    3   -6    0    0    0    0    0   -2
+0           1.07           0.00    0    0    0    0    0    0    0    3   -3    0    0    0    0    0
+0           1.07           0.00    0    0    2   -2    1    0   -4    4    0    0    0    0    0    0
+0          -1.07           0.00    0    1   -2   -2    0    0    0    0    0    0    0    0    0    0
+0           1.07           0.00    0    0    2   -3    1    0    0    0    0    0    0    0    0    0
+0          -0.84          -0.24    0    0    0    0    1    0   -3    5    0    0    0    0    0    0
+0           0.00          -1.03    0    0    3    0    3    0    0    0    0    0    0    0    0    0
+0           1.03           0.00    2    1    2    2    2    0    0    0    0    0    0    0    0    0
+0          -1.03           0.00    3    0    2   -4    2    0    0    0    0    0    0    0    0    0
+0          -0.24           0.80    0    0    0    0    0    0    0    1    0    0   -2    0    0    0
+0           0.20           0.84    0    0    1   -1    1    0   -1    0    0    0    0    0    0    0
+0          -1.03           0.00    3    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0          -1.03           0.00    0    0    0    0    3    0    0    0    0    0    0    0    0    0
+0          -0.99           0.00    2    0    0    1    0    0    0    0    0    0    0    0    0    0
+0           0.24           0.76    0    0    0    0    0    0    2   -1    0    0    0    0    0    0
+0          -0.99           0.00    0    0    0    0    0    0    0    7   -8    3    0    0    0    2
+0          -0.16           0.84    0    0    0    0    0    0    0    2    0   -2    0    0    0    1
+0          -0.99           0.00    0    0    0    0    0    0    0    1   -1    0    0    0    0    0
+0          -0.64           0.36    0    0    0    0    0    0    0    4   -7    0    0    0    0   -2
+0           0.99           0.00    1   -2    0    2    0    0    0    0    0    0    0    0    0    0
+0           0.36          -0.64    0    0    1   -1    0    0    0   -1    0   -2    5    0    0    0
+0          -0.95           0.00    3    0    2    2    1    0    0    0    0    0    0    0    0    0
+0          -0.95           0.00    1   -1    2    4    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.95    0    0    1   -1    0    0    0   -1    0   -1    1    0    0    0
+0           0.64           0.32    1    0    0   -1    0    0    0   -3    4    0    0    0    0    0
+0           0.00          -0.95    0    0    0    0    0    0    7  -10    0    0    0    0    0   -2
+0           0.84           0.12    0    0    0    0    0    0    0    5   -8    3    0    0    0    0
+0           0.20           0.76    0    0    0    0    0    0    6   -8    0    0    0    0    0   -1
+0          -0.95           0.00    3    0   -2    0    0    0    0    0    0    0    0    0    0    0
+0           0.95           0.00    1    0    4    0    2    0    0    0    0    0    0    0    0    0
+0          -0.95           0.00    1   -1   -2    2   -2    0    0    0    0    0    0    0    0    0
+0           0.00           0.92    1    0    0   -1   -1    0   -3    4    0    0    0    0    0    0
+0           0.91           0.00    1    1    2    2    1    0    0    0    0    0    0    0    0    0
+0           0.91           0.00    3    0   -2   -6   -2    0    0    0    0    0    0    0    0    0
+0           0.40           0.52    1   -2    2   -2    1    0    0    0    0    0    0    0    0    0
+0          -0.91           0.00    5    0    2    0    2    0    0    0    0    0    0    0    0    0
+0          -0.56           0.36    0    0    0    0    0    0    3   -9    4    0    0    0    0   -2
+0           0.44          -0.48    0    0    1   -1    1    0    8  -14    0    0    0    0    0    0
+0          -0.91           0.00    2    0    0   -6    0    0    0    0    0    0    0    0    0    0
+0          -0.91           0.00    3    1    0    0    0    0    0    0    0    0    0    0    0    0
+0          -0.36          -0.56    0    0    1   -1    1    0    3   -6    0    0    0    0    0    0
+0           0.91           0.00    1    0    0    2    2    0    0    0    0    0    0    0    0    0
+0          -0.88           0.00    1    2    0   -2    1    0    0    0    0    0    0    0    0    0
+0          -0.88           0.00    2    1    0    0   -1    0    0    0    0    0    0    0    0    0
+0           0.60          -0.28    0    0    0    0    1    0    0    8  -15    0    0    0    0    0
+0           0.88           0.00    0    2   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.36          -0.52    0    0    1   -1    1    0    0   -3    4    0    0    0    0    0
+0          -0.52           0.36    0    0    0    0    0    0    3   -5    4    0    0    0    0    2
+0           0.52           0.36    0    0    0    0    0    0    0    6    0    0    0    0    0    2
+0           0.00           0.88    0    0    0    0    0    0    0    4   -7    0    0    0    0    0
+0           0.56           0.32    0    0    0    0    0    0    0    8  -15    0    0    0    0   -2
+0           0.64          -0.24    0    0    0    0    0    0    0    4   -5    0    0    0    0    0
+0           0.88           0.00    1   -1    0   -4    0    0    0    0    0    0    0    0    0    0
+0           0.88           0.00    1   -1    2    0    0    0    0    0    0    0    0    0    0    0
+0           0.88           0.00    1   -1    2   -1    2    0    0    0    0    0    0    0    0    0
+0           0.84           0.00    0    1    0   -2   -2    0    0    0    0    0    0    0    0    0
+0          -0.68          -0.16    2    0    0   -2    1    0   -6    8    0    0    0    0    0    0
+0           0.84           0.00    1    2    2    0    2    0    0    0    0    0    0    0    0    0
+0           0.56           0.28    0    0    1   -1    0    0   -8   12    0    0    0    0    0    0
+0          -0.16           0.68    0    0    0    0    0    0    5   -5    0    0    0    0    0   -1
+0           0.64          -0.20    0    0    0    0    0    0    5   -7    0    0    0    0    0    0
+0           0.16           0.68    0    0    0    0    0    0    1    2    0    0    0    0    0    2
+0           0.72          -0.12    0    0    0    0    0    0    0    3    0   -3    0    0    0    0
+0          -0.83           0.00    2    0   -2    0    2    0    0    0    0    0    0    0    0    0
+0          -0.80           0.00    2    1    0    0    1    0    0    0    0    0    0    0    0    0
+0           0.80           0.00    2    2    0   -2    0    0    0    0    0    0    0    0    0    0
+0          -0.80           0.00    4    0    0   -2    0    0    0    0    0    0    0    0    0    0
+0           0.28           0.52    0    0    0    0    0    0    0    5   -9    0    0    0    0    0
+0           0.68          -0.12    0    0    0    0    0    0    3    0    0    0    0    0    0    2
+0           0.00          -0.80    0    0    0    0    0    0    0    2    0    0   -1    0    0    2
+0          -0.32           0.48    0    0    0    0    0    0    0    5   -9    0    0    0    0   -2
+0           0.36          -0.44    0    0    0    0    0    0    0    3    0   -3    0    0    0    2
+0          -0.36          -0.44    0    0    0    0    0    0    0    0    0    0    0    0    2    1
+0          -0.80           0.00    0    1    2    0    0    0    0    0    0    0    0    0    0    0
+0           0.79           0.00    1    1    0   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.74          -0.04    0    0    2   -2    3    0    0    0    0    0    0    0    0    0
+0          -0.76           0.00    0    0    0    0    1    0   -1    1    0    0    0    0    0    0
+0           0.00           0.76    0    0    0    0    1    0   -2    3    0    0    0    0    0    0
+0           0.16           0.60    0    0    0    0    1    0    0    0    0   -1    0    0    0    0
+0          -0.76           0.00    1    0    0    1    1    0    0    0    0    0    0    0    0    0
+0          -0.76           0.00    3    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+0           0.76           0.00    2    1   -2   -4   -1    0    0    0    0    0    0    0    0    0
+0          -0.76           0.00    2   -1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0           0.76           0.00    1    0   -4    2   -1    0    0    0    0    0    0    0    0    0
+0           0.12           0.64    0    0    1   -1    0    0    0   -1    0    2    0    0    0    0
+0           0.76           0.00    1    0    0   -2    0    0   -3    3    0    0    0    0    0    0
+0           0.00           0.76    0    0    1   -1    1    0    0   -9   15    0    0    0    0    0
+0           0.76           0.00    0    0    0    0    0    0    8   -8    0    0    0    0    0    0
+0           0.64          -0.12    0    0    0    0    0    0    7  -11    0    0    0    0    0   -2
+0           0.16          -0.60    0    0    0    0    0    0    2    0    0    0    0    0    0    1
+0           0.76           0.00    0    0    0    0    0    0    0    3   -1    0    0    0    0    2
+0           0.00          -0.76    0    0    0    0    0    0    0    2    0    0    1    0    0    2
+0           0.28          -0.48    0    0    0    0    0    0    0    5   -5    0    0    0    0    2
+0           0.32           0.44    0    0    0    0    0    0    0    1    0    1    0    0    0    0
+0          -0.76           0.00    1    1    2    0    0    0    0    0    0    0    0    0    0    0
+0           0.72           0.00    4    0    2   -2    1    0    0    0    0    0    0    0    0    0
+0           0.72           0.00    1   -1   -2    0    0    0    0    0    0    0    0    0    0    0
+0           0.48          -0.24    0    0    0    0    0    0    0    2    0   -2    5    0    0    2
+0          -0.72           0.00    0    1    2   -4    1    0    0    0    0    0    0    0    0    0
+0           0.72           0.00    0    0    1   -1    1    0   -2    2    0    0    0    0    0    0
+0          -0.72           0.00    0    0    2    1    0    0    0    0    0    0    0    0    0    0
+0          -0.72           0.00    3    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+0          -0.71           0.00    1   -1    0    0    2    0    0    0    0    0    0    0    0    0
+0          -0.68           0.00    1    0   -2   -2    1    0    0    0    0    0    0    0    0    0
+0          -0.68           0.00    0    2    0   -2    1    0    0    0    0    0    0    0    0    0
+0           0.68           0.00    0    1   -4    2   -2    0    0    0    0    0    0    0    0    0
+0           0.68           0.00    0    1    2    4    2    0    0    0    0    0    0    0    0    0
+0           0.68           0.00    1    0   -2    4   -1    0    0    0    0    0    0    0    0    0
+0          -0.68           0.00    0    2    2   -2    0    0    0    0    0    0    0    0    0    0
+0           0.56          -0.12    0    0    0    0    0    0    5   -3    0    0    0    0    0    2
+0          -0.68           0.00    0    0    0    0    0    0    0    3   -5    0    0    0    0   -2
+0          -0.68           0.00    0    0    0    0    0    0    0    2    0   -4    0    0    0   -2
+0           0.20           0.48    0    0    0    0    0    0    0    3    0    2   -5    0    0    2
+0          -0.44          -0.24    0    0    0    0    0    0    0    2    0    2   -5    0    0    2
+0          -0.68           0.00    1    1   -2    0    0    0    0    0    0    0    0    0    0    0
+0           0.64           0.00    2    0    0   -2    1    0   -3    3    0    0    0    0    0    0
+0           0.64           0.00    3    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+0          -0.64           0.00    2   -1    2    2    1    0    0    0    0    0    0    0    0    0
+0           0.64           0.00    0    1   -2   -4   -1    0    0    0    0    0    0    0    0    0
+0          -0.64           0.00    1    0   -2   -3   -1    0    0    0    0    0    0    0    0    0
+0          -0.12           0.52    0    0    0    0    0    0    6   -6    0    0    0    0    0   -1
+0          -0.12          -0.52    0    0    0    0    0    0    2   -2    0    0    0    0    0    1
+0          -0.16          -0.48    0    0    0    0    0    0    0    3    0   -2    0    0    0    0
+0          -0.20          -0.44    0    0    0    0    0    0    2   -3    0    0    0    0    0   -2
+0          -0.44           0.20    0    0    0    0    0    0    0   11    0    0    0    0    0    2
+0          -0.44           0.20    0    0    0    0    0    0    0    6  -15    0    0    0    0   -2
+0           0.24          -0.40    0    0    0    0    0    0    0    4   -8    0    0    0    0   -2
+0          -0.20          -0.44    0    0    0    0    0    0    0    3    0    1    0    0    0    2
+0          -0.64           0.00    1    0    0   -6    0    0    0    0    0    0    0    0    0    0
+0           0.40          -0.24    0    0    0    0    1    0    3   -7    4    0    0    0    0    0
+0          -0.64           0.00    1    0   -2   -4    0    0    0    0    0    0    0    0    0    0
+0           0.64           0.00    0    1    0   -4   -1    0    0    0    0    0    0    0    0    0
+0          -0.63           0.00    2    0   -2    2   -2    0    0    0    0    0    0    0    0    0
+0          -0.60           0.00    0    1   -2    1   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.60    0    0    2   -2    2    0   -8   11    0    0    0    0    0    0
+0          -0.60           0.00    2    0   -2   -3   -2    0    0    0    0    0    0    0    0    0
+0          -0.60           0.00    4    0    2    2    2    0    0    0    0    0    0    0    0    0
+0           0.60           0.00    0    0    0    0    0    0    0    2    0    0   -2    0    0    0
+0           0.00           0.60    0    0    0    0    0    0    0    0    0    0    3    0    0    2
+0           0.24          -0.36    2    0    0   -2    0    0    0   -2    0    4   -3    0    0    0
+0           0.12           0.48    0    0    0    0    0    0    7   -9    0    0    0    0    0   -1
+0           0.48          -0.12    0    0    0    0    0    0    4   -7    0    0    0    0    0   -1
+0           0.12           0.48    0    0    0    0    0    0    3   -3    0    0    0    0    0    1
+0           0.24          -0.36    0    0    0    0    0    0    0    6   -6    0    0    0    0    2
+0           0.36           0.24    0    0    0    0    0    0    0    6  -11    0    0    0    0    0
+0           0.12           0.48    0    0    0    0    0    0    0    5    0   -2    0    0    0    2
+0           0.44           0.16    0    0    0    0    0    0    0    2    0   -4    0    0    0    0
+0          -0.60           0.00    0    0    0    3    0    0    0    0    0    0    0    0    0    0
+0          -0.60           0.00    2    0    0   -2    0    0    0   -2    0    3   -1    0    0    0
+0           0.60           0.00    2   -1    0   -4    0    0    0    0    0    0    0    0    0    0
+0           0.00           0.60    0    0    1   -1    2    0    0   -2    2    0    0    0    0    0
+0           0.59           0.00    0    0    0    0    1    0    0    1    0   -1    0    0    0    0
+0          -0.56           0.00    3    0    0   -4    1    0    0    0    0    0    0    0    0    0
+0          -0.44          -0.12    2    0    0   -2   -1    0   -6    8    0    0    0    0    0    0
+0           0.56           0.00    1    2   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.56    0    0    1   -1    1    0    0   -1    0   -1    1    0    0    0
+0          -0.56           0.00    3    1    0   -4    0    0    0    0    0    0    0    0    0    0
+0          -0.56           0.00    3    0    0   -6    0    0    0    0    0    0    0    0    0    0
+0           0.56           0.00    0    0    0    0    0    0    0    6    0    0    0    0    0    0
+0          -0.56           0.00    0    0    0    0    0    0    0    1    0    0    1    0    0    2
+0           0.16           0.40    0    0    0    0    0    1    0   -4    0    0    0    0    0   -2
+0           0.44          -0.12    0    0    0    0    0    0    4   -4    0    0    0    0    0    2
+0           0.20          -0.36    0    0    0    0    0    0    0    1   -5    0    0    0    0   -2
+0          -0.36          -0.20    0    0    0    0    1    0   -3    7   -4    0    0    0    0    0
+0          -0.56           0.00    0    0    4   -4    1    0    0    0    0    0    0    0    0    0
+0           0.55           0.00    1    1    0   -2    2    0    0    0    0    0    0    0    0    0
+0           0.52           0.00    1    0    0   -4   -2    0    0    0    0    0    0    0    0    0
+0          -0.52           0.00    1    1    0   -4    1    0    0    0    0    0    0    0    0    0
+0           0.52           0.00    0    0    0    0    1    0    3   -5    0    2    0    0    0    0
+0           0.52           0.00    0    1    0   -1    0    0    0    0    0    0    0    0    0    0
+0           0.16           0.36    0    0    1   -1    0    0    0   -1    0    0    2    0    0    0
+0          -0.52           0.00    0    0    2   -2    0    0   -3    3    0    0    0    0    0    0
+0          -0.52           0.00    1    0    0   -2    0    0    0   -2    0    3    0    0    0    0
+0          -0.52           0.00    1    0   -2   -2   -2    0    0   -2    0    2    0    0    0    0
+0          -0.52           0.00    0    0    2    6    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.52    0    0    1   -1    1    0    2   -4    0   -3    0    0    0    0
+0           0.52           0.00    0    0    0    0    0    0    9   -9    0    0    0    0    0    0
+0          -0.52           0.00    0    0    0    0    0    0    0    1    1    0    0    0    0    2
+0           0.12           0.40    0    0    0    0    0    0    5   -6    0    0    0    0    0    2
+0           0.52           0.00    1    0   -4    0    0    0    0    0    0    0    0    0    0    0
+0          -0.52           0.00    2    0   -2   -4    0    0    0    0    0    0    0    0    0    0
+0           0.00          -0.52    1    0    1    0    1    0    0    0    0    0    0    0    0    0
+0           0.52           0.00    1    1    0    0    2    0    0    0    0    0    0    0    0    0
+0           0.52           0.00    0    0    0    1    2    0    0    0    0    0    0    0    0    0
+0          -0.51           0.00    1    0    0    2   -2    0    0    0    0    0    0    0    0    0
+0          -0.51           0.00    1    0    2    0    3    0    0    0    0    0    0    0    0    0
+0           0.48           0.00    0    1    0    2    2    0    0    0    0    0    0    0    0    0
+0           0.48           0.00    0    0    2    2   -1    0    0    0    0    0    0    0    0    0
+0          -0.16           0.32    0    0    0    0    1    0    0    2   -4    0    0    0    0    0
+0          -0.48           0.00    1   -2    2   -2    2    0    0    0    0    0    0    0    0    0
+0          -0.48           0.00    0    1   -2   -1   -2    0    0    0    0    0    0    0    0    0
+0           0.48           0.00    3   -1    2   -2    2    0    0    0    0    0    0    0    0    0
+0           0.48           0.00    4    0    0   -4    0    0    0    0    0    0    0    0    0    0
+0          -0.48           0.00    3   -1    2    2    2    0    0    0    0    0    0    0    0    0
+0          -0.12          -0.36    0    0    1   -1    1    0    0   -1    0    3    0    0    0    0
+0          -0.32           0.16    0    0    1   -1    1    0    0   -1    0    0    3    0    0    0
+0           0.32          -0.16    0    0    0    0    0    0    4   -2    0    0    0    0    0    2
+0          -0.12          -0.36    0    0    0    0    0    0    3   -5    0    0    0    0    0    1
+0           0.16           0.32    0    0    0    0    0    0    0    7  -13    0    0    0    0   -2
+0           0.20          -0.28    0    0    0    0    0    0    0    5   -7    0    0    0    0    0
+0          -0.20          -0.28    0    0    0    0    0    0    0    1    0    3    0    0    0    2
+0          -0.36           0.12    0    0    0    0    0    0    0    0    0    4    0    0    0    2
+0          -0.48           0.00    0    0    0    0    0    0    0    0    0    2   -5    0    0    2
+0           0.32          -0.16    0    0    0    0    0    0    0    0    0    0    3    0    0    1
+0           0.48           0.00    1   -1    0    4    0    0    0    0    0    0    0    0    0    0
+0          -0.48           0.00    2    1    0    2    0    0    0    0    0    0    0    0    0    0
+0          -0.48           0.00    2    0    0   -2   -1    0    0   -2    0    0    5    0    0    0
+0          -0.48           0.00    3    0    0    2    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.48    1    0    1   -2    1    0    0    0    0    0    0    0    0    0
+0           0.48           0.00    1    1    0   -4   -1    0    0    0    0    0    0    0    0    0
+0          -0.48           0.00    0    0    2   -2    2    0   -3    3    0    0    0    0    0    0
+0          -0.48           0.00    1    0    0   -1    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.48    0    0    2   -2    2    0   -5    6    0    0    0    0    0    0
+0           0.44           0.00    0    0    0    0    1    0    0   -1    0    1    0    0    0    0
+0          -0.32          -0.12    0    0    1   -1   -1    0    0    0   -2    0    0    0    0    0
+0          -0.44           0.00    0    1   -2    0    0    0    0    0    0    0    0    0    0    0
+0           0.20          -0.24    0    0    0    0    0    0    0    9  -17    0    0    0    0    0
+0           0.44           0.00    3   -1   -2   -1   -2    0    0    0    0    0    0    0    0    0
+0          -0.44           0.00    1   -1    0   -3    0    0    0    0    0    0    0    0    0    0
+0           0.44           0.00    0    0    2   -2    1    0   -2    2    0    0    0    0    0    0
+0           0.20          -0.24    0    0    0    0    0    0    8  -13    0    0    0    0    0    1
+0           0.12           0.32    0    0    0    0    0    0    5  -10    0    0    0    0    0   -2
+0          -0.20           0.24    0    0    0    0    0    0    1    0    0    0    0    0    0    2
+0           0.32          -0.12    0    0    0    0    0    0    1   -3    0    0    0    0    0    0
+0           0.00           0.44    0    0    0    0    0    0    0    6  -11    0    0    0    0   -2
+0           0.00           0.44    0    0    0    0    0    0    0    5   -8    0    0    0    0    0
+0           0.44           0.00    0    0    0    0    0    0    0    1   -3    0    0    0    0   -2
+0          -0.44           0.00    1    2    0   -4    0    0    0    0    0    0    0    0    0    0
+0          -0.44           0.00    0    1    0    4    0    0    0    0    0    0    0    0    0    0
+0          -0.44           0.00    3    0    2   -2    0    0    0    0    0    0    0    0    0    0
+0           0.44           0.00    1   -1    2   -4    1    0    0    0    0    0    0    0    0    0
+0           0.44           0.00    2    0    2    2    0    0    0    0    0    0    0    0    0    0
+0           0.40           0.00    2    0    2    0   -1    0    0    0    0    0    0    0    0    0
+0          -0.40           0.00    2    1    0   -4   -1    0    0    0    0    0    0    0    0    0
+0          -0.40           0.00    2    1    0   -4    1    0    0    0    0    0    0    0    0    0
+0          -0.40           0.00    1    0    4   -4    2    0    0    0    0    0    0    0    0    0
+0           0.40           0.00    2    0   -4    0   -1    0    0    0    0    0    0    0    0    0
+0           0.24           0.16    2    0    0   -2   -1    0    0   -5    6    0    0    0    0    0
+0           0.00          -0.40    0    0    3    0    2    0    0    0    0    0    0    0    0    0
+0           0.12           0.28    2    0   -1   -1   -1    0    0   -1    0    3    0    0    0    0
+0           0.40           0.00    1    2   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0          -0.40           0.00    0    0    4   -1    2    0    0    0    0    0    0    0    0    0
+0           0.40           0.00    0    0    0    0    0    0    0    7  -13    0    0    0    0    0
+0           0.40           0.00    5    0    2   -2    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.40    0    0    0    0    0    0    9  -12    0    0    0    0    0   -2
+0          -0.40           0.00    0    0    0    0    0    0    5   -9    0    0    0    0    0   -2
+0           0.00          -0.40    0    0    0    0    0    0    4   -4    0    0    0    0    0    1
+0           0.00          -0.40    0    0    0    0    0    0    3   -1    0    0    0    0    0    1
+0           0.20          -0.20    0    0    0    0    0    0    2   -4    0    0    0    0    0    0
+0          -0.40           0.00    0    0    0    0    0    0    1   -2    0    0    0    0    0    1
+0          -0.40           0.00    0    0    0    0    0    0    0    5   -3    0    0    0    0    2
+0          -0.12          -0.28    0    0    0    0    0    0    0    4   -8    1    5    0    0   -2
+0           0.40           0.00    0    0    0    0    0    0    3   -5    0    2    0    0    0    0
+0           0.40           0.00    1    1   -2    2    0    0    0    0    0    0    0    0    0    0
+0           0.40           0.00    2    0    0    4    0    0    0    0    0    0    0    0    0    0
+0           0.40           0.00    0    0    0    3    1    0    0    0    0    0    0    0    0    0
+0           0.40           0.00    4    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.40    0    0    1   -1    2    0    0   -1    0    2    0    0    0    0
+0          -0.20          -0.16    0    0    0    0    2    0    0   -1    2    0    0    0    0    0
+0           0.36           0.00    1    0    0   -3    1    0    0    0    0    0    0    0    0    0
+0           0.36           0.00    1   -2    0    0    1    0    0    0    0    0    0    0    0    0
+0           0.24          -0.12    0    2   -2    0   -1    0    0    0    0    0    0    0    0    0
+0           0.20          -0.16    2    0   -1   -1   -1    0    0    3   -7    0    0    0    0    0
+0           0.00           0.36    0    0    2    0    2    0    0   -4    8   -3    0    0    0    0
+0           0.00           0.36    0    0    2    0    2    0    0    4   -8    3    0    0    0    0
+0          -0.36           0.00    2    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.12           0.24    1    0    1    0    0    0    0    0    0    0    0    0    0    0
+0          -0.36           0.00    2   -2    2    0    2    0    0    0    0    0    0    0    0    0
+0          -0.36           0.00    0    3    0   -2    0    0    0    0    0    0    0    0    0    0
+0          -0.36           0.00    2   -1    0   -1    0    0    0    0    0    0    0    0    0    0
+0          -0.36           0.00    1    3    0   -2    0    0    0    0    0    0    0    0    0    0
+0           0.36           0.00    1   -1   -2   -3   -2    0    0    0    0    0    0    0    0    0
+0           0.00           0.36    0    0    1   -1    1    0   -2    3    0    0    0    0    0    0
+0           0.00           0.36    0    0    0    0    0    0    7   -7    0    0    0    0    0   -1
+0           0.00           0.36    0    0    0    0    0    0    6   -7    0    0    0    0    0    0
+0          -0.36           0.00    0    0    0    0    0    0    6   -9    0    0    0    0    0   -1
+0           0.00           0.36    0    0    0    0    0    0    4   -3    0    0    0    0    0    2
+0           0.12          -0.24    0    0    0    0    0    0    1   -2    0    0    0    0    0   -2
+0          -0.24           0.12    0    0    0    0    0    0    0    6   -5    0    0    0    0    2
+0          -0.36           0.00    0    0    0    0    0    0    0    5    0   -3    0    0    0    2
+0           0.00           0.36    0    0    0    0    0    0    0    3   -2    0    0    0    0    0
+0           0.36           0.00    0    0    0    0    0    0    0    3   -6    0    0    0    0   -1
+0           0.24          -0.12    0    0    0    0    0    0    0    2   -5    0    0    0    0   -2
+0           0.00          -0.36    0    0    1   -1    1    0    0    1    0    0    0    0    0    0
+0          -0.36           0.00    1   -2   -2    0   -2    0    0    0    0    0    0    0    0    0
+0           0.36           0.00    2    0    0    2    2    0    0    0    0    0    0    0    0    0
+0           0.36           0.00    0    1    0   -2    2    0    0    0    0    0    0    0    0    0
+0          -0.36           0.00    0    0    2    0   -2    0    0    0    0    0    0    0    0    0
+0           0.36           0.00    0    0    2   -2   -2    0    0    0    0    0    0    0    0    0
+0          -0.13           0.22    0    0    1   -1    2    0    0   -1    0   -2    5    0    0    0
+0          -0.32           0.00    0    0    0    0    1    0    3   -5    0    0    0    0    0    0
+0          -0.32           0.00    1    1    0    2   -1    0    0    0    0    0    0    0    0    0
+0           0.32           0.00    4    0    0    0   -1    0    0    0    0    0    0    0    0    0
+0          -0.20          -0.12    0    0    0    0    1    0    0   -8   15    0    0    0    0    0
+0           0.32           0.00    0    2    2    0    1    0    0    0    0    0    0    0    0    0
+0           0.12           0.20    2    0    0   -2    1    0    0   -6    8    0    0    0    0    0
+0          -0.32           0.00    3   -1    2    0    1    0    0    0    0    0    0    0    0    0
+0           0.32           0.00    0    0    2    0    2    0    1   -1    0    0    0    0    0    0
+0          -0.32           0.00    0    0    2    0    2    0   -1    1    0    0    0    0    0    0
+0          -0.32           0.00    2    0    2   -1    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.32    2    0   -1   -1   -2    0    0   -1    0    2    0    0    0    0
+0           0.32           0.00    1    2    2   -2    1    0    0    0    0    0    0    0    0    0
+0           0.32           0.00    2    2    2   -2    2    0    0    0    0    0    0    0    0    0
+0           0.12          -0.20    0    0    2   -2    0    0    0   -9   13    0    0    0    0    0
+0          -0.32           0.00    3    0    2   -1    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.32    1    0    0   -2    0    0   20  -21    0    0    0    0    0    0
+0           0.32           0.00    0    0    2   -2    1    0    0   -2    0    0    2    0    0    0
+0           0.00           0.32    0    0    2   -2    1    0    0   -8   11    0    0    0    0    0
+0           0.00          -0.32    0    0    1   -1    1    0    0   -1    0    0    0    2    0    0
+0           0.00          -0.32    0    0    1   -1    1    0    0   -1    0   -1    2    0    0    0
+0           0.32           0.00    0    0    0    0    0    0    8  -12    0    0    0    0    0    0
+0          -0.32           0.00    0    0    0    0    0    0    5   -5    0    0    0    0    0    2
+0           0.00           0.32    0    0    0    0    0    0    5   -6    0    0    0    0    0    0
+0           0.32           0.00    0    0    0    0    0    0    2   -6    0    0    0    0    0   -2
+0           0.00           0.32    0    0    0    0    0    0    0    8  -15    0    0    0    0   -1
+0           0.00          -0.32    0    0    0    0    0    0    0    5   -2    0    0    0    0    2
+0           0.32           0.00    0    0    0    0    0    0    0    4   -4    0    0    0    0    0
+0          -0.16           0.16    0    0    0    0    0    0    0    2    2    0    0    0    0    2
+0          -0.16           0.16    0    0    0    0    0    0    0    1    0   -4    0    0    0    0
+0           0.00           0.32    0    0    0    0    0    0    0    0    0    0    1    0    0    2
+0           0.20           0.12    0    0    1   -1    1    0    0   -1    0   -2    4    0    0    0
+0           0.20           0.12    0    0    0    0    0    1    0   -4    0    0    0    0    0    0
+0          -0.20           0.12    0    0    0    0    0    0    0    5   -8    0    0    0    0   -2
+0           0.12           0.20    0    0    0    0    0    0    0    4   -8    0    0    0    0    0
+0           0.12          -0.20    0    0    0    0    0    0    0    2   -6    0    0    0    0   -2
+0           0.00           0.32    0    0    2   -2    1   -1    0    2    0    0    0    0    0    0
+0          -0.32           0.00    0    0    4   -2    0    0    0    0    0    0    0    0    0    0
+0           0.32           0.00    0    0    0    1   -2    0    0    0    0    0    0    0    0    0
+0           0.28           0.00    2    0   -4    2   -2    0    0    0    0    0    0    0    0    0
+0          -0.28           0.00    0    0    0    4    2    0    0    0    0    0    0    0    0    0
+0           0.28           0.00    1    0    0    4   -1    0    0    0    0    0    0    0    0    0
+0           0.28           0.00    1   -2    0   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.28           0.00    1    1    0   -1    1    0    0    0    0    0    0    0    0    0
+0           0.16           0.12    1    0    0   -1    1    0    0   -3    4    0    0    0    0    0
+0           0.28           0.00    3    1    2    0    1    0    0    0    0    0    0    0    0    0
+0          -0.28           0.00    1    1    2    1    1    0    0    0    0    0    0    0    0    0
+0          -0.12          -0.16    0    0    0    0    1    0    0   -9   17    0    0    0    0    0
+0           0.28           0.00    1    1    4   -2    2    0    0    0    0    0    0    0    0    0
+0          -0.28           0.00    4    0    2   -4    2    0    0    0    0    0    0    0    0    0
+0          -0.28           0.00    0    2    0    2    0    0    0    0    0    0    0    0    0    0
+0           0.28           0.00    1    0    2   -3    0    0    0    0    0    0    0    0    0    0
+0           0.28           0.00    3    0   -2   -2    0    0    0    0    0    0    0    0    0    0
+0           0.28           0.00    2   -2    0    0    0    0    0    0    0    0    0    0    0    0
+0           0.28           0.00    1    1    0   -3    0    0    0    0    0    0    0    0    0    0
+0           0.28           0.00    1    0    2    3    2    0    0    0    0    0    0    0    0    0
+0           0.28           0.00    1    0    0   -2    0    0    0    1    0   -1    0    0    0    0
+0          -0.28           0.00    1    0   -2   -2   -2    0   -3    3    0    0    0    0    0    0
+0           0.28           0.00    0    0    2   -2    1    0    0   -2    0    3    0    0    0    0
+0           0.00           0.28    0    0    0    0    0    0    8   -8    0    0    0    0    0   -1
+0           0.00           0.28    0    0    0    0    0    0    8  -10    0    0    0    0    0   -1
+0           0.00          -0.28    0    0    0    0    0    0    4   -2    0    0    0    0    0    1
+0          -0.28           0.00    0    0    0    0    0    0    3   -4    0    0    0    0    0   -1
+0           0.28           0.00    0    0    0    0    0    0    3   -6    0    0    0    0    0   -1
+0          -0.12          -0.16    0    0    0    0    0    0    1   -4    0    0    0    0    0   -2
+0           0.00           0.28    0    0    0    0    0    0    0    6    0    0    0    0    0    1
+0           0.00          -0.28    0    0    0    0    0    0    0    6   -7    0    0    0    0    2
+0           0.12          -0.16    0    0    0    0    0    0    0    4    0    0    0    0    0    0
+0          -0.28           0.00    0    0    0    0    0    0    0    4    0    0   -2    0    0    2
+0           0.00          -0.28    0    0    0    0    0    0    0    3    0    0   -2    0    0    2
+0           0.00           0.28    0    0    0    0    0    0    0    1    0   -1    0    0    0    1
+0           0.00          -0.28    0    0    0    0    0    0    0    1   -6    0    0    0    0   -2
+0           0.28           0.00    0    0    0    0    0    0    0    0    0    4   -5    0    0    2
+0          -0.28           0.00    0    0    0    0    0    0    0    0    0    0    0    2    0    2
+0          -0.28           0.00    0    0    0    0    0    0    3   -7    4    0    0    0    0    0
+0           0.28           0.00    1   -1    2   -2    0    0    0    0    0    0    0    0    0    0
+0           0.28           0.00    1    1    2   -4    0    0    0    0    0    0    0    0    0    0
+0           0.12          -0.16    0    0    1   -1    1    0    0   -1    0    0   -2    0    0    0
+0           0.28           0.00    0    0    2    4    0    0    0    0    0    0    0    0    0    0
+0           0.28           0.00    2   -1   -2    0   -2    0    0    0    0    0    0    0    0    0
+0          -0.28           0.00    0    0    1   -1    2    0    0    0   -2    0    0    0    0    0
+0           0.00          -0.28    0    0    0    0    2    0    0    4   -8    3    0    0    0    0
+0           0.00          -0.28    0    0    0    0    2    0    0   -4    8   -3    0    0    0    0
+0           0.28           0.00    1    1    2   -4    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.24    0    0    2   -2   -1    0   -5    6    0    0    0    0    0    0
+0           0.24           0.00    1   -2    0   -2    1    0    0    0    0    0    0    0    0    0
+0          -0.24           0.00    0    1    0   -4    1    0    0    0    0    0    0    0    0    0
+0          -0.24           0.00    1   -2    2    0    1    0    0    0    0    0    0    0    0    0
+0           0.24           0.00    0    0    2    0    2    0    0   -1    0    1    0    0    0    0
+0          -0.24           0.00    0    0    2    0    2    0    0    1    0   -1    0    0    0    0
+0          -0.24           0.00    2    0   -4   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.24           0.00    2    0    2    1    1    0    0    0    0    0    0    0    0    0
+0           0.24           0.00    2    0   -2   -6   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.24    2    0   -1   -1   -1    0    0   -1    0    2    0    0    0    0
+0          -0.24           0.00    4   -1    2    0    2    0    0    0    0    0    0    0    0    0
+0           0.24           0.00    5    0    0    0    0    0    0    0    0    0    0    0    0    0
+0          -0.24           0.00    3    0    0   -3    0    0    0    0    0    0    0    0    0    0
+0          -0.24           0.00    2    2    0   -4    0    0    0    0    0    0    0    0    0    0
+0           0.24           0.00    2    2   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0          -0.24           0.00    2    1    2    1    2    0    0    0    0    0    0    0    0    0
+0          -0.24           0.00    1    0    2   -2    2    0    0   -2    0    2    0    0    0    0
+0          -0.24           0.00    1    0    0    0    0    0    0   -2    0    2    0    0    0    0
+0           0.24           0.00    1    0    0   -2    0    0    2   -2    0    0    0    0    0    0
+0           0.00          -0.24    1    0   -1    1   -1    0  -18   17    0    0    0    0    0    0
+0           0.24           0.00    0    2   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0          -0.24           0.00    0    1    2    3    2    0    0    0    0    0    0    0    0    0
+0           0.24           0.00    0    0    0    0    0    0    8  -12    0    0    0    0    0   -2
+0           0.24           0.00    0    0    0    0    0    0    8  -16    0    0    0    0    0   -2
+0           0.00           0.24    0    0    0    0    0    0    7   -8    0    0    0    0    0    0
+0           0.12          -0.12    0    0    0    0    0    0    2   -3    0    0    0    0    0    1
+0           0.00          -0.24    0    0    0    0    0    0    0    5   -6    0    0    0    0    2
+0          -0.24           0.00    0    0    0    0    0    0    0    4   -6    0    0    0    0   -2
+0           0.00           0.24    0    0    0    0    0    0    0    4   -8    1    5    0    0    2
+0          -0.24           0.00    0    0    0    0    0    0    0    2    0   -2    0    0    0    2
+0           0.00          -0.24    0    0    0    0    0    0    0    2   -7    0    0    0    0   -2
+0           0.24           0.00    0    0    0    0    0    0    0    0    2    0    0    0    0    0
+0          -0.24           0.00    0    0    0    0    0    0    0    0    0    0    5    0    0    2
+0          -0.24           0.00    0    0    0    0    0    0    0    0    0    0    0    0    2    2
+0           0.24           0.00    0    1    0    3    0    0    0    0    0    0    0    0    0    0
+0           0.24           0.00    0    2    2    2    2    0    0    0    0    0    0    0    0    0
+0           0.24           0.00    2   -1    2   -1    2    0    0    0    0    0    0    0    0    0
+0           0.24           0.00    1   -1    2    2    0    0    0    0    0    0    0    0    0    0
+0           0.24           0.00    2    1    2   -4    1    0    0    0    0    0    0    0    0    0
+0          -0.24           0.00    2    0    0   -2   -2    0   -3    3    0    0    0    0    0    0
+0          -0.24           0.00    1   -1    0   -4   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.24    0    0    1   -1    2    0    0   -1    0    1    0    0    0    0
+0           0.00          -0.24    0    0    1   -1    2    0    0   -1    0   -1    0    0    0    0
+0           0.24           0.00    0    0    0    0    1    0    2   -2    0    0    0    0    0    0
+0           0.00           0.20    1    0   -1    0    1    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    2   -2    0   -2    1    0    0    0    0    0    0    0    0    0
+0          -0.20           0.00    0    0    1   -1    2    0    0   -1    0    0    1    0    0    0
+0           0.20           0.00    2    0    0   -2   -1    0   -3    3    0    0    0    0    0    0
+0           0.20           0.00    1   -2    0    0   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    0    0    0    0    1    0    0    0    0    0   -1    0    0    0
+0          -0.20           0.00    1    0   -2    1    1    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    2    0    0   -3   -1    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    2    1   -2    0    1    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    2    0    0   -1    1    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    2   -1    2   -2    1    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    1   -1   -4    2   -2    0    0    0    0    0    0    0    0    0
+0          -0.20           0.00    1   -2   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    2    0    4   -2    1    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    0    0    2    3    1    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    0    1    4   -2    1    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    1    0   -2    0   -2    0  -10    3    0    0    0    0    0    0
+0           0.00           0.20    1    0    1   -2    0    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    1   -1    2    1    2    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    4    1    2    0    2    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    0    0    2   -2    1    0    0   -1    0    1    0    0    0    0
+0           0.20           0.00    1    0    0   -1    0    0    0   -2    2    0    0    0    0    0
+0          -0.20           0.00    0    0    2   -2    0    0    0   -2    0    2    0    0    0    0
+0           0.00          -0.20    1    0    0    0    0    0    0    4   -8    3    0    0    0    0
+0          -0.20           0.00    4   -1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    2    1   -2   -6   -2    0    0    0    0    0    0    0    0    0
+0          -0.20           0.00    2    0    0   -2    0    0    0   -4    8   -3    0    0    0    0
+0           0.20           0.00    2    0    0   -2    0    0   -2    2    0    0    0    0    0    0
+0           0.20           0.00    2    0    0   -2   -1    0    0   -2    0    4   -5    0    0    0
+0           0.00          -0.20    2    0   -1   -1   -1    0    0   -1    0    0    0    0    0    0
+0          -0.20           0.00    1    1   -2   -3   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    1    0    3    0    3    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    1    0    1   -1    1    0    0   -1    0    0    0    0    0    0
+0           0.00          -0.20    1    0    0    0    0    0    0   -4    8   -3    0    0    0    0
+0           0.20           0.00    1    0    0    0    0    0   -1    1    0    0    0    0    0    0
+0           0.00           0.20    1    0    0   -2    0    0   17  -16    0   -2    0    0    0    0
+0          -0.20           0.00    1    0   -1   -1   -1    0   20  -20    0    0    0    0    0    0
+0           0.20           0.00    1    0   -2   -2   -2    0    0   -2    0    3    0    0    0    0
+0           0.20           0.00    0    3   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    0    0    1   -1    1    0    1   -2    0    0    0    0    0    0
+0           0.00           0.20    0    0    1   -1    1    0   -2    1    0    0    0    0    0    0
+0          -0.20           0.00    0    0    1   -1    0    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    0    0    0    0    0    0    9   -9    0    0    0    0    0   -1
+0           0.00           0.20    0    0    0    0    0    0    9  -11    0    0    0    0    0   -1
+0           0.00           0.20    0    0    0    0    0    0    6  -10    0    0    0    0    0   -1
+0           0.00          -0.20    0    0    0    0    0    0    5   -3    0    0    0    0    0    1
+0          -0.20           0.00    0    0    0    0    0    0    4   -5    0    0    0    0    0   -1
+0           0.00          -0.20    0    0    0    0    0    0    3   -4    0    0    0    0    0   -2
+0           0.00          -0.20    0    0    0    0    0    0    0    6   -9    0    0    0    0    0
+0           0.00          -0.20    0    0    0    0    0    0    0    5  -10    0    0    0    0   -2
+0          -0.20           0.00    0    0    0    0    0    0    0    4    0   -4    0    0    0    2
+0           0.20           0.00    0    0    0    0    0    0    0    3    0   -4    0    0    0    0
+0          -0.20           0.00    0    0    0    0    0    0    0    2    0    0    0    0    0    0
+0          -0.20           0.00    0    0    0    0    0    0    0    2    0   -5    0    0    0   -2
+0           0.00           0.20    0    0    0    0    0    0    0    1    0   -2    5    0    0    2
+0           0.20           0.00    0    0    0    0    0    0    0    1    0   -2    0    0    0   -2
+0           0.00          -0.20    0    0    0    0    0    0    0    1    0   -3    0    0    0   -1
+0          -0.20           0.00    0    0    0    0    0    0    0    1    0   -5    0    0    0   -2
+0           0.00          -0.20    0    0    0    0    0    0    0    0    0    0    0    2    0    1
+0           0.00           0.20    0    0    0    0    0    0    0    0    0    0    0    1   -2   -2
+0          -0.20           0.00    0    2    0   -4    0    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    0    0    0    6    0    0    0    0    0    0    0    0    0    0
+0          -0.20           0.00    3    0    0   -2    0    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    2   -1   -2    2   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    1    0   -1    1   -1    0    0    1    0    0    0    0    0    0
+0          -0.20           0.00    0    0    2   -4    0    0    0    0    0    0    0    0    0    0
+0          -0.20           0.00    1    0    0   -1   -1    0    0   -2    2    0    0    0    0    0
+0           0.20           0.00    0    1    0    4    1    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    1    0    0   -6   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    0    0    0    0    1    0    5   -8    0    0    0    0    0    0
+0           0.20           0.00    0    0    4    2    2    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    3    0    0   -2    1    0    0    0    0    0    0    0    0    0
+0          -0.20           0.00    0    0    2   -2    2    0    0   -2    0    2    0    0    0    0
+0          -0.20           0.00    1   -1    0   -2   -2    0    0    0    0    0    0    0    0    0
+0          -0.20           0.00    0    0    1   -1    2    0   -5    7    0    0    0    0    0    0
+0          -0.20           0.00    2    1    0   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    0    0    0    0    1    0    0    2   -2    0    0    0    0    0
+0          -0.20           0.00    1    0   -2    0    2    0    0    0    0    0    0    0    0    0
+0          -0.20           0.00    1   -1    0    0   -2    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    1    1   -2    2   -2    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    0    0    0    0    1    0   -2    2    0    0    0    0    0    0
+0           0.16           0.00    1    0    0   -3   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.16    0    0    1   -1   -1    0    0   -1    0   -1    0    0    0    0
+0           0.16           0.00    2    0   -2   -2    1    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    1    0    0   -1    1    0    0   -1    0    1    0    0    0    0
+0           0.16           0.00    2    0    0   -3    1    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    3    0    0    2   -1    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    1    1    0    1    1    0    0    0    0    0    0    0    0    0
+0          -0.16           0.00    0    2    0    0   -2    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    2   -1    0    2   -1    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    1    1    0    1   -1    0    0    0    0    0    0    0    0    0
+0          -0.16           0.00    1    0   -4   -2   -1    0    0    0    0    0    0    0    0    0
+0          -0.16           0.00    1   -1   -2   -4   -1    0    0    0    0    0    0    0    0    0
+0          -0.16           0.00    1   -2    2    2    1    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    3    1    2   -2    1    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    1    0   -2   -6   -1    0    0    0    0    0    0    0    0    0
+0          -0.16           0.00    2    0    4   -4    2    0    0    0    0    0    0    0    0    0
+0          -0.04           0.12    2   -2    2   -2    2    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    3    0    4   -2    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.16    0    0    1   -1    0    0    3   -6    0    0    0    0    0    0
+0           0.16           0.00    1    1    2    4    2    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    0    0    2   -3    0    0    0    0    0    0    0    0    0    0
+0           0.00          -0.16    0    0    1    1    0    0    0    1    0    0    0    0    0    0
+0           0.00          -0.16    0    0    1   -1    0    0   -4    5    0    0    0    0    0    0
+0           0.00           0.16    0    0    1   -1    0    0    0   -2    2    0    0    0    0    0
+0           0.16           0.00    0    0    1   -1    0    0    0   -1    0    0    1    0    0    0
+0           0.00           0.16    0    0    1   -1    0    0    0   -1    0    1    0    0    0    0
+0          -0.16           0.00    0    1   -2    4   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.16    1    0    0   -2    0    0    0    4   -8    3    0    0    0    0
+0           0.16           0.00    3    0    2    1    2    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    3    0    0   -1    0    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    2    1    0    1    0    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    2    0    2    0    1    0    0    1    0    0    0    0    0    0
+0          -0.16           0.00    2    0    0   -2    0    0    0   -2    0    2    2    0    0    0
+0           0.16           0.00    2    0    0   -2    0    0    0   -4    4    0    0    0    0    0
+0          -0.16           0.00    2   -2    2    2    2    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    1    1   -2   -6   -2    0    0    0    0    0    0    0    0    0
+0          -0.16           0.00    1    0    0    0    0    0    1   -1    0    0    0    0    0    0
+0          -0.16           0.00    1    0    0    0    0    0    0   -1    0    1    0    0    0    0
+0          -0.16           0.00    1    0    0    0    0    0   -3    3    0    0    0    0    0    0
+0          -0.16           0.00    1    0    0   -2    0    0    1   -1    0    0    0    0    0    0
+0           0.00          -0.16    1    0    0   -2    0    0    0   -4    8   -3    0    0    0    0
+0          -0.16           0.00    1    0    0   -2    0    0   -2    2    0    0    0    0    0    0
+0          -0.16           0.00    0    0    2   -2    1    0    0    1    0   -1    0    0    0    0
+0           0.16           0.00    0    0    2   -2    1    0    0   -3    0    3    0    0    0    0
+0           0.16           0.00    0    0    2   -2    1    0   -5    5    0    0    0    0    0    0
+0          -0.16           0.00    0    0    1   -1    1    0    1   -3    0    0    0    0    0    0
+0           0.00           0.16    0    0    1   -1    1    0    0   -1    0    0    0   -1    0    0
+0           0.16           0.00    0    0    1   -1    1    0    0   -4    6    0    0    0    0    0
+0           0.00           0.16    0    0    1   -1    1    0   -5    6    0    0    0    0    0    0
+0          -0.16           0.00    0    0    0    2    0    0    0   -1    0    1    0    0    0    0
+0           0.00           0.16    0    0    0    0    0    0    8   -9    0    0    0    0    0    0
+0          -0.16           0.00    0    0    0    0    0    0    7  -10    0    0    0    0    0   -1
+0           0.00          -0.16    0    0    0    0    0    0    5   -5    0    0    0    0    0    1
+0           0.00          -0.16    0    0    0    0    0    0    4   -5    0    0    0    0    0   -2
+0           0.00          -0.16    0    0    0    0    0    0    3   -6    0    0    0    0    0    0
+0           0.00           0.16    0    0    0    0    0    0    3   -8    0    0    0    0    0   -2
+0           0.16           0.00    0    0    0    0    0    0    2   -5    0    0    0    0    0   -1
+0          -0.16           0.00    0    0    0    0    0    0    1    1    0    0    0    0    0    0
+0           0.16           0.00    0    0    0    0    0    0    1   -2    0    0    0    0    0   -1
+0           0.00          -0.16    0    0    0    0    0    0    0    7   -8    0    0    0    0    2
+0           0.00          -0.16    0    0    0    0    0    0    0    7   -9    0    0    0    0    2
+0           0.00           0.16    0    0    0    0    0    0    0    6  -10    0    0    0    0   -2
+0           0.00           0.16    0    0    0    0    0    0    0    3    0    0    0    0    0    2
+0           0.16           0.00    0    0    0    0    0    0    0    3   -8    3    0    0    0   -2
+0           0.00           0.16    0    0    0    0    0    0    0    2    0    0   -2    0    0    1
+0           0.16           0.00    0    0    0    0    0    0    0    2   -4    0    0    0    0    1
+0           0.16           0.00    0    0    0    0    0    0    0    1    0    0    0    0    0   -1
+0           0.00          -0.16    0    0    0    0    0    0    0    1    0   -1    0    0    0   -1
+0           0.00          -0.16    0    0    0    0    0    0    0    0    0    3   -5    0    0    0
+0          -0.16           0.00    0    0    0    0    0    0    0    0    0    2   -2    0    0    0
+0          -0.16           0.00    2    1    0   -6    0    0    0    0    0    0    0    0    0    0
+0          -0.16           0.00    1   -1    0    1    0    0    0    0    0    0    0    0    0    0
+0           0.00          -0.16    0    0    1   -1    0    0   -3    4    0    0    0    0    0    0
+0           0.16           0.00    3   -1    0    2    0    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    4    0    0    2    0    0    0    0    0    0    0    0    0    0
+0          -0.16           0.00    0    0    2   -2    0    0   -4    4    0    0    0    0    0    0
+0           0.16           0.00    1    0    2   -1    0    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    1   -2   -2    2   -1    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    1   -1   -2   -2    0    0    0    0    0    0    0    0    0    0
+0          -0.16           0.00    2    0    2   -3    2    0    0    0    0    0    0    0    0    0
+0          -0.16           0.00    0    1    2    2    0    0    0    0    0    0    0    0    0    0
+0           0.00           0.16    0    0    2   -2    1    0    0   -4    8   -3    0    0    0    0
+0           0.00           0.16    0    0    2   -2    1    0    0    4   -8    3    0    0    0    0
+0           0.16           0.00    3    0   -2    2   -1    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    2   -1    2    0    0    0    0    0    0    0    0    0    0    0
+0          -0.16           0.00    2    0    0    4    1    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    2    0   -4    2   -1    0    0    0    0    0    0    0    0    0
+0          -0.16           0.00    2   -1    0    2    1    0    0    0    0    0    0    0    0    0
+0          -0.16           0.00    2   -2    0   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.16    0    0    0    0    1    0    0    1    0   -2    0    0    0    0
+0          -0.16           0.00    3    0    0    0    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.16    0    0    0    0    1    0    3   -4    0    0    0    0    0    0
+0           0.16           0.00    0    2    0    0    2    0    0    0    0    0    0    0    0    0
+0           0.16           0.00    0    1    2   -4    2    0    0    0    0    0    0    0    0    0
+0          -0.15           0.00    0    0    1   -1    2    0   -8   12    0    0    0    0    0    0
+0           0.00           0.12    0    0    0    0    1    0    0   -1    0    2    0    0    0    0
+0           0.12           0.00    0    0    0    0    1    0    0   -2    2    0    0    0    0    0
+0           0.00           0.12    0    0    0    0    1    0   -3    4    0    0    0    0    0    0
+0           0.12           0.00    1    0    0    0   -1    0  -10    3    0    0    0    0    0    0
+0           0.12           0.00    1    0    0    0    1    0  -10    3    0    0    0    0    0    0
+0           0.00          -0.12    0    0    0    0    2    0    0    0    0    1    0    0    0    0
+0          -0.12           0.00    0    1    4   -4    2    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    2    0    2   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    1    0    2   -4   -1    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    1    2    0    0    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.12    2    0    0   -2   -1    0    0   -6    8    0    0    0    0    0
+0           0.12           0.00    2   -1   -2    0    1    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    2    0    0   -2    1    0    0   -5    6    0    0    0    0    0
+0           0.12           0.00    1    0    0   -2   -1    0    0   -2    0    2    0    0    0    0
+0           0.12           0.00    2    0   -1   -1    1    0    0    3   -7    0    0    0    0    0
+0           0.12           0.00    1    0    0   -2    1    0    0   -2    0    2    0    0    0    0
+0           0.12           0.00    1    0    0   -1   -1    0    0   -3    4    0    0    0    0    0
+0           0.12           0.00    0    0    0    3    2    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    2    2    0   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    1   -1    2   -3    1    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    1    0    4    0    1    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    2    0    0   -2   -1    0    0   -2    0    3   -1    0    0    0
+0           0.12           0.00    2   -1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    2    1    2    2    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.12    0    0    2    0    2    0    2   -3    0    0    0    0    0    0
+0           0.00           0.12    0    0    2    0    2    0   -2    3    0    0    0    0    0    0
+0          -0.12           0.00    0    0    2    0    2    0    2   -2    0    0    0    0    0    0
+0           0.12           0.00    0    0    2    0    2    0   -2    2    0    0    0    0    0    0
+0          -0.12           0.00    5    0    2    0    1    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    3    0   -2   -6   -1    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    1    2    2    0    1    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    1   -1    2    4    1    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    2    0   -2   -2   -2    0    0   -2    0    2    0    0    0    0
+0          -0.12           0.00    2    0    2    4    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.12    0    0    2   -2    1    0   -8   11    0    0    0    0    0    0
+0           0.00           0.12    1    0    2    0    2    0    0   -4    8   -3    0    0    0    0
+0           0.00           0.12    1    0    2    0    2    0    0    4   -8    3    0    0    0    0
+0          -0.12           0.00    1   -2    0   -1    0    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    2    0    2   -2    2    0    0   -2    0    3    0    0    0    0
+0           0.12           0.00    1    0    2    0    2    0    1   -1    0    0    0    0    0    0
+0          -0.12           0.00    1    0    2    0    2    0   -1    1    0    0    0    0    0    0
+0           0.00          -0.12    0    0    2   -2    0   -1    0    2    0    0    0    0    0    0
+0          -0.12           0.00    4    0   -2   -2    0    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    1    0    2   -6    1    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    0    1   -4    2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.12    0    0    1   -1    0    0    0   -1    0    0   -2    0    0    0
+0           0.12           0.00    1   -1   -2    1   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.12    0    0    1   -1    0    0    0    1    0    0    0    0    0    0
+0           0.00           0.12    2    0   -1   -1    0    0    0   -1    0    3    0    0    0    0
+0           0.00          -0.12    0    0    1   -1    0    0   -1    0    0    0    0    0    0    0
+0           0.08           0.04    0    0    0    0    0    0    0    0    1    0    0    0    0    0
+0           0.12           0.00    4    1    2   -2    2    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    3    1    2    2    2    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    3    1    0   -2    0    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    3    1   -2   -6   -2    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    3   -1    0   -2    0    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    3   -1    0   -3    0    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    2    1    0   -3    0    0    0    0    0    0    0    0    0    0
+0           0.00           0.12    2    0    1   -3    1    0   -6    7    0    0    0    0    0    0
+0           0.00          -0.12    2    0    0   -2    0    0    2   -5    0    0    0    0    0    0
+0           0.00           0.12    2    0    0   -2    0    0    0   -2    0    5   -5    0    0    0
+0           0.12           0.00    2    0    0   -2    0    0    0   -2    0    1    5    0    0    0
+0           0.12           0.00    2    0    0   -2    0    0    0   -2    0    0    2    0    0    0
+0           0.12           0.00    2    0    0   -2    0    0   -4    4    0    0    0    0    0    0
+0           0.00           0.12    2    0   -2    0   -2    0    0    5   -9    0    0    0    0    0
+0          -0.12           0.00    2    0   -2   -5   -2    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    2   -1    2    4    2    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    1    3   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    1    1   -2   -1   -2    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    1    0    2   -2    2    0   -3    3    0    0    0    0    0    0
+0           0.00           0.12    1    0    1    1    1    0    0    1    0    0    0    0    0    0
+0           0.12           0.00    1    0    0    0    0    0    0    1    0   -1    0    0    0    0
+0           0.12           0.00    1    0    0    0    0    0    0   -2    0    3    0    0    0    0
+0          -0.12           0.00    1    0    0   -2    0    0    0    2    0   -2    0    0    0    0
+0           0.12           0.00    1    0   -1    0   -1    0   -3    5    0    0    0    0    0    0
+0          -0.12           0.00    1    0   -1   -1    0    0    0    8  -15    0    0    0    0    0
+0           0.00          -0.12    1    0   -1   -2   -1    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    1    0   -2   -2   -2    0    0    1    0   -1    0    0    0    0
+0           0.12           0.00    0    0    2    2    2    0    0    2    0   -2    0    0    0    0
+0          -0.12           0.00    0    0    2   -2    1    0    0   -2    0    1    0    0    0    0
+0          -0.12           0.00    0    0    2   -2    1    0    0   -2    0    0    0    0    0    0
+0           0.12           0.00    0    0    2   -2    1    0    0   -4    4    0    0    0    0    0
+0           0.00           0.12    0    0    2   -2    1    0    0   -7    9    0    0    0    0    0
+0          -0.12           0.00    0    0    2   -2    1    0    0  -10   15    0    0    0    0    0
+0           0.12           0.00    0    0    1   -1    1    0    0    1   -4    0    0    0    0    0
+0           0.00           0.12    0    0    1   -1    1    0    0   -1    0    1   -3    0    0    0
+0           0.00           0.12    0    0    1   -1    1    0   -1    2    0    0    0    0    0    0
+0           0.12           0.00    0    0    1   -1    1    0   -4    6    0    0    0    0    0    0
+0          -0.12           0.00    0    0    0    2    0    0    0    2    0   -2    0    0    0    0
+0          -0.12           0.00    0    0    0    2    0    0   -2    2    0    0    0    0    0    0
+0           0.12           0.00    0    0    0    0    0    0    9  -13    0    0    0    0    0   -2
+0          -0.12           0.00    0    0    0    0    0    0    8  -11    0    0    0    0    0   -1
+0           0.12           0.00    0    0    0    0    0    0    8  -14    0    0    0    0    0   -2
+0           0.00          -0.12    0    0    0    0    0    0    7  -11    0    0    0    0    0   -1
+0           0.00          -0.12    0    0    0    0    0    0    6   -4    0    0    0    0    0    1
+0           0.00          -0.12    0    0    0    0    0    0    6   -6    0    0    0    0    0    1
+0          -0.12           0.00    0    0    0    0    0    0    6   -7    0    0    0    0    0   -1
+0          -0.12           0.00    0    0    0    0    0    0    6   -8    0    0    0    0    0    0
+0           0.00          -0.12    0    0    0    0    0    0    6   -9    0    0    0    0    0    0
+0           0.00           0.12    0    0    0    0    0    0    5   -4    0    0    0    0    0    2
+0          -0.12           0.00    0    0    0    0    0    0    5   -6    0    0    0    0    0   -1
+0           0.00          -0.12    0    0    0    0    0    0    5   -6    0    0    0    0    0   -2
+0          -0.12           0.00    0    0    0    0    0    0    5   -6   -4    0    0    0    0   -2
+0           0.00           0.12    0    0    0    0    0    0    4   -2    0    0    0    0    0    0
+0           0.00          -0.12    0    0    0    0    0    0    4   -5    0    0    0    0    0    0
+0           0.12           0.00    0    0    0    0    0    0    4   -8    0    0    0    0    0   -2
+0          -0.12           0.00    0    0    0    0    0    0    3   -1    0    0    0    0    0    0
+0          -0.12           0.00    0    0    0    0    0    0    3   -3    0    2    0    0    0    2
+0           0.12           0.00    0    0    0    0    0    0    3   -4    0    0    0    0    0    1
+0           0.00           0.12    0    0    0    0    0    0    2    1    0    0    0    0    0    1
+0          -0.12           0.00    0    0    0    0    0    0    2    0    0    0    0    0    0    0
+0           0.12           0.00    0    0    0    0    0    0    1   -1    0    0    0    0    0   -2
+0           0.12           0.00    0    0    0    0    0    0    1   -4    0    0    0    0    0   -1
+0          -0.12           0.00    0    0    0    0    0    0    0    9  -17    0    0    0    0   -2
+0           0.00           0.12    0    0    0    0    0    0    0    7   -7    0    0    0    0    2
+0           0.00           0.12    0    0    0    0    0    0    0    7  -12    0    0    0    0   -2
+0          -0.12           0.00    0    0    0    0    0    0    0    6   -4    0    0    0    0    2
+0           0.00          -0.12    0    0    0    0    0    0    0    6   -8    1    5    0    0    2
+0          -0.12           0.00    0    0    0    0    0    0    0    6   -9    0    0    0    0   -2
+0           0.00           0.12    0    0    0    0    0    0    0    6  -10    0    0    0    0    0
+0          -0.12           0.00    0    0    0    0    0    0    0    5    0   -4    0    0    0    2
+0           0.12           0.00    0    0    0    0    0    0    0    5   -6    0    0    0    0    0
+0          -0.12           0.00    0    0    0    0    0    0    0    5   -7    0    0    0    0   -2
+0          -0.12           0.00    0    0    0    0    0    0    0    5   -8    3    0    0    0    2
+0          -0.12           0.00    0    0    0    0    0    0    0    5   -9    0    0    0    0   -1
+0          -0.12           0.00    0    0    0    0    0    0    0    5  -13    0    0    0    0   -2
+0           0.12           0.00    0    0    0    0    0    0    0    5  -16    4    5    0    0   -2
+0          -0.12           0.00    0    0    0    0    0    0    0    4   -7    0    0    0    0   -1
+0           0.12           0.00    0    0    0    0    0    0    0    4   -8    3    0    0    0    1
+0           0.12           0.00    0    0    0    0    0    0    0    4   -8    3    0    0    0   -1
+0          -0.12           0.00    0    0    0    0    0    0    0    3    0   -5    0    0    0   -2
+0           0.00          -0.12    0    0    0    0    0    0    0    3   -5    0    0    0    0   -1
+0           0.00          -0.12    0    0    0    0    0    0    0    3   -7    0    0    0    0   -2
+0           0.00          -0.12    0    0    0    0    0    0    0    3   -9    0    0    0    0   -2
+0           0.12           0.00    0    0    0    0    0    0    0    2    1    0    0    0    0    2
+0           0.12           0.00    0    0    0    0    0    0    0    2    0    2    0    0    0    2
+0           0.00           0.12    0    0    0    0    0    0    0    2    0    0   -3    0    0    0
+0           0.00          -0.12    0    0    0    0    0    0    0    2   -8    1    5    0    0   -2
+0           0.00           0.12    0    0    0    0    0    0    0    1    0    1    0    0    0    1
+0          -0.12           0.00    0    0    0    0    0    0    0    1    0    1   -5    0    0    0
+0           0.00          -0.12    0    0    0    0    0    0    0    1    0    0    2    0    0    2
+0          -0.12           0.00    0    0    0    0    0    0    0    1    0    0   -3    0    0    0
+0           0.12           0.00    0    0    0    0    0    0    0    1    0   -3    5    0    0    0
+0           0.00           0.12    0    0    0    0    0    0    0    1   -3    0    0    0    0    0
+0           0.12           0.00    0    0    0    0    0    0    0    0    0    2   -6    3    0   -2
+0           0.00           0.12    0    0    0    0    0    0    0    0    0    1   -2    0    0    0
+0           0.00           0.12    0    0    0    0    0    0    0    0    0    0    0    1    0    0
+0           0.12           0.00    0    0    0    0    0    0    0    0    0    0    0    0    0    2
+0          -0.12           0.00    1    1    0   -6    0    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    1    0    0    3    0    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    2    0    0   -2    0    0    0   -2    0    0    5    0    0    0
+0          -0.12           0.00    3    0   -2   -1   -1    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    1    2    2   -4    1    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    0    0    1   -1    0    0   -2    2    0    0    0    0    0    0
+0           0.00           0.12    1    0   -1    1    0    0    0    1    0    0    0    0    0    0
+0           0.12           0.00    0    0    2   -2    1    0    1   -1    0    0    0    0    0    0
+0          -0.12           0.00    2    0    2   -6    1    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    2    1    2   -2    0    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    2    1    2    0    0    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    1    0    2    1    0    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    4    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    0    0    0    0    1    0    0    7  -13    0    0    0    0    0
+0           0.12           0.00    2    1    0    2    1    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    1   -1    0    4    1    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    3    0   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    2    0    0   -6   -1    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    0    0    1   -1   -1    0   -5    7    0    0    0    0    0    0
+0           0.12           0.00    0    0    0    0    2    0   -3    5    0    0    0    0    0    0
+0           0.00          -0.12    0    0    1    1    2    0    0    1    0    0    0    0    0    0
+0           0.00          -0.12    0    0    1   -1    2    0   -3    4    0    0    0    0    0    0
+0           0.00           0.12    0    0    0    0    1    0   -1    2    0    0    0    0    0    0
+0           0.12           0.00    2   -1    0   -2    2    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    1    1   -2    1   -2    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    2    1   -2    0   -2    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    0    0    1   -1    2    0    0   -1    0    0   -1    0    0    0
+0          -0.12           0.00    2    1    2   -4    2    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    2    0    0   -4    2    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    3    0    0    0   -2    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    1    0    0   -4    2    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    2    0    0   -4   -2    0    0    0    0    0    0    0    0    0
+0           0.12           0.00    1    1    0    0   -2    0    0    0    0    0    0    0    0    0
+0          -0.12           0.00    0    0    0    0    1    0    0    2    0   -2    0    0    0    0
+0          -0.12           0.00    1    0   -2    4   -2    0    0    0    0    0    0    0    0    0
+0           0.11           0.00    0    0    4   -4    4    0    0    0    0    0    0    0    0    0
+1       -3328.48      205833.15    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+1         197.53       12814.01    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+1          41.19        2187.91    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+1         -35.85       -2004.36    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+1          59.15         501.82    0    1    2   -2    2    0    0    0    0    0    0    0    0    0
+1          -5.82         448.76    0    0    2    0    1    0    0    0    0    0    0    0    0    0
+1        -179.56         164.33    0    1    0    0    0    0    0    0    0    0    0    0    0    0
+1           5.67         288.49    1    0    2    0    2    0    0    0    0    0    0    0    0    0
+1          23.85        -214.50    0    1   -2    2   -2    0    0    0    0    0    0    0    0    0
+1           2.87        -154.91    0    0    2   -2    1    0    0    0    0    0    0    0    0    0
+1           2.14        -119.21    1    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+1           1.17         -74.33    1    0    0    0    1    0    0    0    0    0    0    0    0    0
+1           1.47          70.31    1    0    0    0   -1    0    0    0    0    0    0    0    0    0
+1          -0.42          58.94    1    0    2    0    1    0    0    0    0    0    0    0    0    0
+1          -0.95          57.12    1    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+1          -1.08         -54.19    2    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+1           0.92          36.78    0    0    2    2    2    0    0    0    0    0    0    0    0    0
+1           0.68         -31.01    0    2   -2    2   -2    0    0    0    0    0    0    0    0    0
+1           0.74          29.60    2    0    2    0    2    0    0    0    0    0    0    0    0    0
+1          -0.60         -27.59    1    0    2   -2    2    0    0    0    0    0    0    0    0    0
+1         -11.11         -15.07    1    0    0    0    0    0    0    0    0    0    0    0    0    0
+1          -0.40         -24.05    1    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+1          -0.81          19.06    0    1    0    0    1    0    0    0    0    0    0    0    0    0
+1           3.18          15.32    0    2    2   -2    2    0    0    0    0    0    0    0    0    0
+1          -0.08         -17.90    1    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+1          -0.16          15.55    1    0    0   -2    1    0    0    0    0    0    0    0    0    0
+1          -0.77          14.40    0    1    0    0   -1    0    0    0    0    0    0    0    0    0
+1          -0.25          11.67    1    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+1           6.18           3.58    0    0    1   -1    1    0    0   -1    0   -2    5    0    0    0
+1          -1.00          -7.27    0    1    2    0    2    0    0    0    0    0    0    0    0    0
+1          -0.99           6.87    0    1   -2    0   -2    0    0    0    0    0    0    0    0    0
+1          -0.27           7.49    0    0    2    2    1    0    0    0    0    0    0    0    0    0
+1          -0.30           7.31    0    0    0    2    1    0    0    0    0    0    0    0    0    0
+1           0.20           7.30    1    0    2    2    2    0    0    0    0    0    0    0    0    0
+1           0.33           6.80    2    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+1           0.27          -6.81    1    0    2   -2    1    0    0    0    0    0    0    0    0    0
+1           0.35           6.08    0    0    0    2   -1    0    0    0    0    0    0    0    0    0
+1           0.35           6.09    0    1   -2    2   -1    0    0    0    0    0    0    0    0    0
+1          -0.14          -6.19    2    0    2   -2    2    0    0    0    0    0    0    0    0    0
+1           0.14           6.02    2    0    2    0    1    0    0    0    0    0    0    0    0    0
+1           2.69          -2.76    1    0    0   -2    0    0    0    0    0    0    0    0    0    0
+1          -0.08          -4.93    2    0    0   -2    1    0    0    0    0    0    0    0    0    0
+1           2.85          -1.77    0    0    0    0    0    0    0    0    0    2   -5    0    0   -1
+1          -0.07          -4.27    0    1    2   -2    1    0    0    0    0    0    0    0    0    0
+1          -3.71           0.38    0    2    0    0    0    0    0    0    0    0    0    0    0    0
+1           3.75           0.04    0    1   -1    1   -1    0    0    0    0    0    0    0    0    0
+1          -0.82          -2.73    0    0    0    2    0    0    0    0    0    0    0    0    0    0
+1          -0.06           2.93    2    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+1          -0.04           2.83    2    0    0    0   -1    0    0    0    0    0    0    0    0    0
+1           0.08           2.75    3    0    2    0    2    0    0    0    0    0    0    0    0    0
+1           0.07           2.75    1   -1    2    0    2    0    0    0    0    0    0    0    0    0
+1          -0.07           2.70    1    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+1          -0.07           2.52    0    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+1          -0.05          -2.53    2    0    0    0    1    0    0    0    0    0    0    0    0    0
+1          -0.04           2.40    1    0   -2    2   -1    0    0    0    0    0    0    0    0    0
+1          -0.06          -2.37    1    1    2    0    2    0    0    0    0    0    0    0    0    0
+1           0.69          -1.45    0    0    1   -1    1    0   -8   12    0    0    0    0    0    0
+1          -0.04           2.00    0    0    0    0    0    0    3   -5    0    0    0    0    0   -2
+1           1.99           0.02    1    0   -1    0   -1    0    0    0    0    0    0    0    0    0
+1          -0.94           1.07    2    0    0   -2    0    0    0    0    0    0    0    0    0    0
+1           0.04           1.91    1    0    0    0    2    0    0    0    0    0    0    0    0    0
+1          -0.58          -1.36    2    0    0    0    0    0    0    0    0    0    0    0    0    0
+1          -0.51          -1.25    0    0    2    0    0    0    0    0    0    0    0    0    0    0
+1          -0.04          -1.59    0    0    2    1    2    0    0    0    0    0    0    0    0    0
+1           0.39          -1.23    1    0    0   -1    0    0    0    0    0    0    0    0    0    0
+1           0.03          -1.57    1   -1    0   -1   -1    0    0    0    0    0    0    0    0    0
+1          -0.03           1.50    0    2   -2    2   -1    0    0    0    0    0    0    0    0    0
+1           0.04           1.48    1    0    2    2    1    0    0    0    0    0    0    0    0    0
+1          -0.04           1.45    1    0   -2   -4   -2    0    0    0    0    0    0    0    0    0
+1           0.02          -1.36    1    0    0    0   -2    0    0    0    0    0    0    0    0    0
+1           0.03          -1.32    2    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+1          -0.03          -1.24    1    1    2   -2    2    0    0    0    0    0    0    0    0    0
+1          -0.02          -1.18    2    0    2   -2    1    0    0    0    0    0    0    0    0    0
+1          -0.03           1.16    2    0   -2   -4   -2    0    0    0    0    0    0    0    0    0
+1           0.02           1.13    0    0    0    0    0    0    0    0    0    2    0    0    0    2
+1           0.04          -1.11    1    0    0   -1   -1    0    0    0    0    0    0    0    0    0
+1           0.02           1.11    1    0    0    2    1    0    0    0    0    0    0    0    0    0
+1           0.03          -1.10    1    0   -4    0   -2    0    0    0    0    0    0    0    0    0
+1           0.03           1.04    2    0    2    2    2    0    0    0    0    0    0    0    0    0
+1          -0.51           0.56    0    0    0    0    1    0    0   -1    2    0    0    0    0    0
+1           0.02          -0.98    0    0    2   -2   -1    0    0    0    0    0    0    0    0    0
+1          -0.02          -0.94    0    1    2    0    1    0    0    0    0    0    0    0    0    0
+1          -0.02          -0.89    3    0    2   -2    2    0    0    0    0    0    0    0    0    0
+1          -0.02          -0.88    0    0    4   -2    2    0    0    0    0    0    0    0    0    0
+1           0.31           0.60    0    0    0    0    0    0    8  -13    0    0    0    0    0   -1
+1           0.02          -0.87    1    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+1          -0.02          -0.87    2    0   -2    0    1    0    0    0    0    0    0    0    0    0
+1          -0.01           0.83    0    0    2    0   -1    0    0    0    0    0    0    0    0    0
+1          -0.02           0.77    0    1   -2    0   -1    0    0    0    0    0    0    0    0    0
+1           0.42          -0.36    0    0    2   -2    0    0    0    0    0    0    0    0    0    0
+1          -0.01          -0.73    0    1    0    0    2    0    0    0    0    0    0    0    0    0
+1           0.01           0.71    1    1    0   -2    1    0    0    0    0    0    0    0    0    0
+1           0.01           0.68    0    0    2   -1    2    0    0    0    0    0    0    0    0    0
+1           0.02           0.66    0    0    2    4    2    0    0    0    0    0    0    0    0    0
+1          -0.01          -0.62    1   -1    0    0    1    0    0    0    0    0    0    0    0    0
+1          -0.01           0.62    1    0    0    2   -1    0    0    0    0    0    0    0    0    0
+1          -0.58          -0.03    0    0    1   -1    1    0    0   -1    0    2   -5    0    0    0
+1          -0.01           0.58    1   -1    0   -1   -2    0    0    0    0    0    0    0    0    0
+1           0.44           0.14    0    0    0    0    0    0    0    2   -8    3    0    0    0   -2
+1           0.02           0.56    1   -1    2    2    2    0    0    0    0    0    0    0    0    0
+1           0.01          -0.57    0    1    0    0   -2    0    0    0    0    0    0    0    0    0
+1          -0.13          -0.45    1    0    0    2    0    0    0    0    0    0    0    0    0    0
+1           0.01           0.56    3    0    2    0    1    0    0    0    0    0    0    0    0    0
+1           0.01          -0.55    1   -1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+1           0.01           0.55    1    0    2   -4    1    0    0    0    0    0    0    0    0    0
+1          -0.52           0.03    0    0    2   -2    1    0   -5    6    0    0    0    0    0    0
+1          -0.01           0.54    1    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+1          -0.01          -0.51    0    1    2    2    2    0    0    0    0    0    0    0    0    0
+1          -0.41          -0.11    0    0    0    0    0    0    0    6   -8    3    0    0    0    2
+1          -0.01           0.50    0    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+1           0.01           0.48    1   -1    2    0    1    0    0    0    0    0    0    0    0    0
+1           0.45          -0.04    1    0   -2   -2    0    0    0    0    0    0    0    0    0    0
+1           0.01          -0.48    0    0    0    0    0    0    4   -6    0    0    0    0    0   -2
+1           0.01           0.46    2   -1    2    0    2    0    0    0    0    0    0    0    0    0
+1          -0.23           0.24    2    0   -2    0    0    0    0    0    0    0    0    0    0    0
+1           0.01           0.46    0    0    0    1    1    0    0    0    0    0    0    0    0    0
+1           0.35          -0.11    0    0    0    0    1    0    0   -4    8   -3    0    0    0    0
+1           0.01           0.45    0    0    0    2    2    0    0    0    0    0    0    0    0    0
+1           0.01          -0.45    1   -1   -2    0   -2    0    0    0    0    0    0    0    0    0
+1           0.00          -0.45    0    0    0    0    0    0    0    3    0   -1    0    0    0    2
+1          -0.01           0.44    0    0    0    0    0    0    2   -4    0    0    0    0    0   -2
+1           0.35           0.09    0    0    0    0    1    0    0    4   -8    3    0    0    0    0
+1           0.01           0.42    1    1    0    0    1    0    0    0    0    0    0    0    0    0
+1          -0.01          -0.41    1    1    2    0    1    0    0    0    0    0    0    0    0    0
+1           0.09          -0.33    0    0    1   -1    1    0    0    0   -2    0    0    0    0    0
+1           0.00           0.41    0    1    0   -2    1    0    0    0    0    0    0    0    0    0
+1           0.01           0.40    0    3    2   -2    2    0    0    0    0    0    0    0    0    0
+1          -0.01          -0.39    2    1    2    0    2    0    0    0    0    0    0    0    0    0
+1          -0.39          -0.01    1    0   -1    0   -2    0    0    0    0    0    0    0    0    0
+1           0.01          -0.39    0    0    0    1   -1    0    0    0    0    0    0    0    0    0
+1          -0.01           0.38    1    0    0   -2   -2    0    0    0    0    0    0    0    0    0
+1           0.32          -0.07    0    0    0    0    0    0    0    0    0    2    0    0    0    1
+1          -0.01           0.36    1   -1    0    0   -1    0    0    0    0    0    0    0    0    0
+1          -0.01          -0.36    0    0    0    0    0    0    2    0    0    0    0    0    0    2
+1           0.01          -0.34    1    0   -2    2   -2    0    0    0    0    0    0    0    0    0
+1           0.01          -0.34    2    0    0   -2   -1    0    0   -2    0    2    0    0    0    0
+1           0.01           0.33    0    0    0    0    0    0    1    1    0    0    0    0    0    2
+1          -0.01          -0.32    1    0    2    1    2    0    0    0    0    0    0    0    0    0
+1           0.01           0.32    1    0    2   -1    2    0    0    0    0    0    0    0    0    0
+1          -0.01          -0.32    0    0    2    1    1    0    0    0    0    0    0    0    0    0
+1          -0.01          -0.31    1    0   -2    0    1    0    0    0    0    0    0    0    0    0
+1          -0.31           0.00    0    0    1    0    1    0    0    0    0    0    0    0    0    0
+1          -0.07          -0.24    1    0    2    0    0    0    0    0    0    0    0    0    0    0
+1           0.10          -0.21    0    0    1   -1    1    0    0   -1    0    0   -1    0    0    0
+1          -0.01          -0.30    1    0    0   -2    2    0    0    0    0    0    0    0    0    0
+1          -0.01           0.29    1    0   -2   -4   -1    0    0    0    0    0    0    0    0    0
+1          -0.01          -0.29    1    1    2   -2    1    0    0    0    0    0    0    0    0    0
+1           0.00           0.29    1    0   -2    1   -1    0    0    0    0    0    0    0    0    0
+1           0.23           0.06    0    0    1   -1    1    0    0   -1    0   -1    0    0    0    0
+1           0.26           0.02    0    0    0    0    0    0    0    0    0    2   -5    0    0    1
+1           0.00          -0.27    2    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+1           0.25           0.02    0    0    0    0    0    0    5   -8    0    0    0    0    0   -2
+1           0.09          -0.18    0    1    0   -2    0    0    0    0    0    0    0    0    0    0
+1           0.01           0.25    0    0    0    0    0    0    0    1    0    1    0    0    0    2
+1           0.14          -0.11    1    1    0   -2    0    0    0    0    0    0    0    0    0    0
+1           0.00          -0.25    1    1    0    0   -1    0    0    0    0    0    0    0    0    0
+1           0.01           0.24    4    0    2    0    2    0    0    0    0    0    0    0    0    0
+1          -0.01          -0.24    2    1    2   -2    2    0    0    0    0    0    0    0    0    0
+1           0.00           0.23    2    0   -2   -4   -1    0    0    0    0    0    0    0    0    0
+1           0.01           0.23    0    1    2    1    2    0    0    0    0    0    0    0    0    0
+1          -0.01          -0.23    1    0    4   -2    2    0    0    0    0    0    0    0    0    0
+1           0.00          -0.23    0    1    0    2    1    0    0    0    0    0    0    0    0    0
+1           0.00          -0.22    1    0   -4    0   -1    0    0    0    0    0    0    0    0    0
+1           0.00           0.21    1    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+1           0.01           0.21    2    0    2    2    1    0    0    0    0    0    0    0    0    0
+1          -0.17           0.03    0    0    1   -1    1    0    0   -1    0    2    0    0    0    0
+1          -0.17           0.03    0    0    0    0    0    0    8  -13    0    0    0    0    0   -2
+1           0.00          -0.19    0    0    0    0    0    0    5   -7    0    0    0    0    0   -2
+1           0.14          -0.06    0    0    0    0    0    0    0    0    0    0    2    0    0    1
+1           0.03          -0.17    0    0    1   -1    1    0   -5    7    0    0    0    0    0    0
+1          -0.13           0.06    0    0    1   -1    1    0    0   -1    0    0    2    0    0    0
+1           0.00           0.19    0    0    2   -4    1    0    0    0    0    0    0    0    0    0
+1           0.00           0.19    0    0    2   -3    2    0    0    0    0    0    0    0    0    0
+1          -0.06          -0.13    1    0    2    0    2    0    0    1    0    0    0    0    0    0
+1           0.00           0.18    0    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+1          -0.09          -0.09    1   -1    0    0    0    0    0    0    0    0    0    0    0    0
+1           0.10          -0.09    0    0    0    0    0    0    0    8  -16    4    5    0    0   -2
+1           0.06           0.12    1    0   -2    0   -2    0    0    4   -8    3    0    0    0    0
+1           0.00           0.18    0    0    0    0    0    0    0    4    0   -2    0    0    0    2
+1           0.00          -0.18    0    0    4    0    2    0    0    0    0    0    0    0    0    0
+1           0.00           0.17    0    0    0    4    1    0    0    0    0    0    0    0    0    0
+1          -0.03           0.15    0    0    0    0    0    0    0    2    0   -1    0    0    0    2
+1          -0.01          -0.16    0    0    0    0    0    0    0    2    0    1    0    0    0    2
+1           0.00           0.17    1    1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+1           0.00          -0.17    2    0    0   -2   -2    0    0    0    0    0    0    0    0    0
+1           0.11           0.06    0    0    0    0    0    0    8  -11    0    0    0    0    0   -2
+1           0.00          -0.17    3    0    2   -2    1    0    0    0    0    0    0    0    0    0
+1          -0.08           0.09    1    0   -2    0    0    0    0    0    0    0    0    0    0    0
+1          -0.17           0.00    0    0    0    0    0    0    2   -1    0    0    0    0    0    2
+1           0.00          -0.16    0    0    4   -2    1    0    0    0    0    0    0    0    0    0
+1           0.01           0.15    1    0    2    4    2    0    0    0    0    0    0    0    0    0
+1          -0.13          -0.03    0    0    0    0    0    0    1   -1    0    0    0    0    0   -1
+1           0.00           0.15    1    1   -2    0   -2    0    0    0    0    0    0    0    0    0
+1           0.00           0.15    2    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+1          -0.13           0.03    0    0    0    0    0    0    4   -6    0    0    0    0    0   -1
+1           0.10          -0.06    0    0    0    0    0    0    8  -15    0    0    0    0    0   -2
+1          -0.07           0.08    0    0    0    0    0    0    0    1    2    0    0    0    0    2
+1          -0.09          -0.06    0    0    0    0    0    0    0    3    0   -2    0    0    0    2
+1           0.00           0.15    3    0    0    0   -1    0    0    0    0    0    0    0    0    0
+1          -0.07          -0.08    0    0    0    0    0    0    0    3   -2    0    0    0    0    2
+1           0.00          -0.14    2    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+1           0.02           0.12    0    0    0    0    0    0    0    0    0    3    0    0    0    2
+1           0.07           0.08    1    1    0    0    0    0    0    0    0    0    0    0    0    0
+1          -0.03          -0.11    3    0    0    0    0    0    0    0    0    0    0    0    0    0
+1          -0.01          -0.14    0    0    0    0    0    0    0    4   -2    0    0    0    0    2
+1           0.00          -0.14    0    0    2   -2    1    0   -3    3    0    0    0    0    0    0
+1           0.02          -0.12    1    0    0   -1    1    0    0    0    0    0    0    0    0    0
+1           0.00          -0.14    1    1    2    2    2    0    0    0    0    0    0    0    0    0
+1           0.00           0.14    0    0    1   -1    1    0    0    3   -8    3    0    0    0    0
+1           0.00           0.14    0    0    2   -1    1    0    0    0    0    0    0    0    0    0
+1           0.00           0.13    0    0    2    4    1    0    0    0    0    0    0    0    0    0
+1           0.08          -0.06    0    0    0    0    1    0    8  -13    0    0    0    0    0    0
+1           0.00           0.13    1   -1    0   -2   -1    0    0    0    0    0    0    0    0    0
+1           0.00           0.13    0    0    0    0    0    0    0    0    0    0    2    0    0    2
+1           0.01           0.13    3    0    2    2    2    0    0    0    0    0    0    0    0    0
+1           0.00           0.13    2    0    0    2    1    0    0    0    0    0    0    0    0    0
+1           0.00           0.13    1   -1   -2    2   -1    0    0    0    0    0    0    0    0    0
+1          -0.02          -0.11    2    0    0   -2    1    0    0   -2    0    3    0    0    0    0
+1           0.08          -0.04    0    0    0    1    0    0    0    0    0    0    0    0    0    0
+1           0.00           0.13    2    0    0   -4    1    0    0    0    0    0    0    0    0    0
+1           0.00           0.13    1    0    0   -4    1    0    0    0    0    0    0    0    0    0
+1           0.01          -0.12    2    1   -2    0   -1    0    0    0    0    0    0    0    0    0
+1           0.00           0.12    0    2   -2   -2   -2    0    0    0    0    0    0    0    0    0
+1          -0.02          -0.11    0    0    0    0    0    0    5   -8    0    0    0    0    0   -1
+1           0.00          -0.12    2    0    2   -4    1    0    0    0    0    0    0    0    0    0
+1           0.00          -0.12    0    0    0    0    0    0    0    8  -16    4    5    0    0    2
+1           0.00          -0.12    0    0    1   -1    1    0    0   -5    8   -3    0    0    0    0
+1           0.04           0.08    1    0    0    0   -1    0  -18   16    0    0    0    0    0    0
+1           0.00          -0.12    0    0    0    0    0    0    0    1    0   -3    0    0    0   -2
+1           0.00           0.12    1   -1    0   -2   -2    0    0    0    0    0    0    0    0    0
+1           0.00          -0.12    0    0    0    2   -2    0    0    0    0    0    0    0    0    0
+1           0.00          -0.11    0    0    0    0    0    0    6   -8    0    0    0    0    0   -2
+1           0.03          -0.09    1    0    0   -4    0    0    0    0    0    0    0    0    0    0
+1           0.00           0.11    0    2    0    0    1    0    0    0    0    0    0    0    0    0
+1          -0.11           0.00    0    0    0    0    0    0    3   -2    0    0    0    0    0    2
+1           0.00           0.11    1   -1    2    2    1    0    0    0    0    0    0    0    0    0
+1           0.00          -0.11    1   -1   -2    0   -1    0    0    0    0    0    0    0    0    0
+1           0.07           0.05    0    0    0    0    1    0   -8   13    0    0    0    0    0    0
+1           0.11           0.00    0    0    0    0    0    0    2   -5    0    0    0    0    0   -2
+1           0.00          -0.11    0    0    0    0    0    0    1   -3    0    0    0    0    0   -2
+1           0.00          -0.11    4    0    2   -2    2    0    0    0    0    0    0    0    0    0
+1           0.02          -0.09    0    0    0    0    1    0    0    0    0   -2    5    0    0    0
+1           0.00           0.11    2    1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+1           0.02           0.09    0    0    0    0    1    0    0    0    0    2   -5    0    0    0
+1           0.00          -0.11    0    2    2   -2    1    0    0    0    0    0    0    0    0    0
+1           0.00           0.11    1    0    2    0   -1    0    0    0    0    0    0    0    0    0
+1          -0.08          -0.02    0    0    0    0    1    0    0    0    0    1    0    0    0    0
+1           0.00          -0.10    2    1    0   -2    1    0    0    0    0    0    0    0    0    0
+1           0.00          -0.10    2   -1   -2    0   -1    0    0    0    0    0    0    0    0    0
+1          -0.03          -0.07    1    0    0    0    1    0  -18   16    0    0    0    0    0    0
+1           0.00           0.10    1    2   -2   -2   -2    0    0    0    0    0    0    0    0    0
+1           0.00           0.10    2    0    0   -2    2    0    0    0    0    0    0    0    0    0
+1           0.00          -0.10    1   -1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+2        2038.00          82.26    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+2         155.75          -2.70    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+2          26.92          -0.45    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+2         -24.43           0.46    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+2         -17.36          -0.50    0    1    0    0    0    0    0    0    0    0    0    0    0    0
+2          -8.41           0.01    1    0    0    0    0    0    0    0    0    0    0    0    0    0
+2           6.08          -1.36    0    1    2   -2    2    0    0    0    0    0    0    0    0    0
+2           4.59           0.17    0    0    2    0    1    0    0    0    0    0    0    0    0    0
+2           3.57          -0.06    1    0    2    0    2    0    0    0    0    0    0    0    0    0
+2           2.54           0.60    0    1   -2    2   -2    0    0    0    0    0    0    0    0    0
+2           1.86           0.00    1    0    0   -2    0    0    0    0    0    0    0    0    0    0
+2          -1.52          -0.07    0    0    2   -2    1    0    0    0    0    0    0    0    0    0
+2           1.46           0.04    1    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+2          -0.75          -0.02    1    0    0    0    1    0    0    0    0    0    0    0    0    0
+2          -0.75           0.00    0    0    0    2    0    0    0    0    0    0    0    0    0    0
+2          -0.71          -0.01    1    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+2          -0.69           0.02    1    0    0    0   -1    0    0    0    0    0    0    0    0    0
+2           0.61           0.02    1    0    2    0    1    0    0    0    0    0    0    0    0    0
+2           0.54          -0.04    2    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+2          -0.56           0.00    2    0    0   -2    0    0    0    0    0    0    0    0    0    0
+2           0.46          -0.02    0    0    2    2    2    0    0    0    0    0    0    0    0    0
+2           0.38          -0.01    0    2   -2    2   -2    0    0    0    0    0    0    0    0    0
+2           0.37          -0.02    2    0    2    0    2    0    0    0    0    0    0    0    0    0
+2          -0.34           0.01    1    0    2   -2    2    0    0    0    0    0    0    0    0    0
+2          -0.35           0.00    2    0    0    0    0    0    0    0    0    0    0    0    0    0
+2          -0.31           0.00    0    0    2    0    0    0    0    0    0    0    0    0    0    0
+2           0.19          -0.09    0    2    2   -2    2    0    0    0    0    0    0    0    0    0
+2           0.26           0.00    0    0    2   -2    0    0    0    0    0    0    0    0    0    0
+2           0.24          -0.01    1    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+2          -0.20           0.00    0    2    0    0    0    0    0    0    0    0    0    0    0    0
+2           0.18          -0.01    1    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+2           0.17           0.00    0    1    0    0    1    0    0    0    0    0    0    0    0    0
+2           0.15           0.01    1    0    0   -2    1    0    0    0    0    0    0    0    0    0
+2          -0.15           0.00    0    1    0    0   -1    0    0    0    0    0    0    0    0    0
+2          -0.13           0.00    2    0   -2    0    0    0    0    0    0    0    0    0    0    0
+2          -0.12           0.00    1    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+3           1.76         -20.39    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+3           0.00          -1.27    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+3           0.00          -0.22    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+3           0.00           0.20    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+4          -0.10          -0.02    0    0    0    0    1    0    0    0    0    0    0    0    0    0
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2a.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2a.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2a.txt	(revision 22158)
@@ -0,0 +1,1651 @@
+Expression for the X coordinate of the CIP in the GCRS based on the IAU2000A 
+precession-nutation model 
+
+
+--------------------------------------------------------------------------------------------------------------
+
+X = polynomial part + non-polynomial part
+
+--------------------------------------------------------------------------------------------------------------
+
+Polynomial part (unit microarcsecond)
+
+  -16616.99 + 2004191742.88 t - 427219.05 t^2 - 198620.54 t^3 - 46.05 t^4 + 5.98 t^5
+
+--------------------------------------------------------------------------------------------------------------
+
+Non-polynomial part (unit microarcsecond)
+(ARG being for various combination of the fundamental arguments of the nutation theory)
+
+  Sum_i[a_{s,0})_i * sin(ARG) + a_{c,0})_i * cos(ARG)] 
+
++ Sum_i)j=1,4 [a_{s,j})_i * t^j * sin(ARG) + a_{c,j})_i * cos(ARG)] * t^j]
+
+The Table below provides the values for a_{s,j})_i and a_{c,j})_i
+
+The expressions for the fundamental arguments appearing in columns 4 to 8 (luni-solar part) 
+and in columns 6 to 17 (planetary part) are those of the IERS Conventions 2000
+
+--------------------------------------------------------------------------------------------------------------
+
+    i    a_{s,j})_i      a_{c,j})_i    l    l'   F    D   Om L_Me L_Ve  L_E L_Ma  L_J L_Sa  L_U L_Ne  p_A
+
+--------------------------------------------------------------------------------------------------------------
+
+j = 0  Nb of terms = 1306        
+
+    1    -6844318.44        1328.67    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+    2     -523908.04        -544.76    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+    3      -90552.22         111.23    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+    4       82168.76         -27.64    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+    5       58707.02         470.05    0    1    0    0    0    0    0    0    0    0    0    0    0    0
+    6       28288.28         -34.69    1    0    0    0    0    0    0    0    0    0    0    0    0    0
+    7      -20557.78         -20.84    0    1    2   -2    2    0    0    0    0    0    0    0    0    0
+    8      -15406.85          15.12    0    0    2    0    1    0    0    0    0    0    0    0    0    0
+    9      -11991.74          32.46    1    0    2    0    2    0    0    0    0    0    0    0    0    0
+   10       -8584.95           4.42    0    1   -2    2   -2    0    0    0    0    0    0    0    0    0
+   11       -6245.02          -6.68    1    0    0   -2    0    0    0    0    0    0    0    0    0    0
+   12        5095.50           7.19    0    0    2   -2    1    0    0    0    0    0    0    0    0    0
+   13       -4910.93           0.76    1    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+   14        2521.07          -5.97    0    0    0    2    0    0    0    0    0    0    0    0    0    0
+   15        2511.85           1.07    1    0    0    0    1    0    0    0    0    0    0    0    0    0
+   16        2372.58           5.93    1    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+   17        2307.58          -7.52    1    0    0    0   -1    0    0    0    0    0    0    0    0    0
+   18       -2053.16           5.13    1    0    2    0    1    0    0    0    0    0    0    0    0    0
+   19        1898.27          -0.72    2    0    0   -2    0    0    0    0    0    0    0    0    0    0
+   20       -1825.49           1.23    2    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+   21       -1534.09           6.29    0    0    2    2    2    0    0    0    0    0    0    0    0    0
+   22       -1292.02           0.00    0    2   -2    2   -2    0    0    0    0    0    0    0    0    0
+   23       -1234.96           5.21    2    0    2    0    2    0    0    0    0    0    0    0    0    0
+   24        1163.22          -2.94    2    0    0    0    0    0    0    0    0    0    0    0    0    0
+   25        1137.48          -0.04    1    0    2   -2    2    0    0    0    0    0    0    0    0    0
+   26        1029.70          -2.63    0    0    2    0    0    0    0    0    0    0    0    0    0    0
+   27        -866.48           0.52    0    0    2   -2    0    0    0    0    0    0    0    0    0    0
+   28        -813.13           0.40    1    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+   29         664.57          -0.40    0    2    0    0    0    0    0    0    0    0    0    0    0    0
+   30        -628.24          -0.64    0    2    2   -2    2    0    0    0    0    0    0    0    0    0
+   31        -603.52           0.44    1    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+   32        -556.26           3.16    0    1    0    0    1    0    0    0    0    0    0    0    0    0
+   33        -512.37          -1.47    1    0    0   -2    1    0    0    0    0    0    0    0    0    0
+   34         506.65           2.54    0    1    0    0   -1    0    0    0    0    0    0    0    0    0
+   35         438.51          -0.56    2    0   -2    0    0    0    0    0    0    0    0    0    0    0
+   36         405.91           0.99    1    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+   37        -122.67         203.78    0    0    1   -1    1    0    0   -1    0   -2    5    0    0    0
+   38        -305.78           1.75    1    0    2    2    2    0    0    0    0    0    0    0    0    0
+   39         300.99          -0.44    0    1    2    0    2    0    0    0    0    0    0    0    0    0
+   40        -292.37          -0.32    1    1    0   -2    0    0    0    0    0    0    0    0    0    0
+   41         284.09           0.32    0    1   -2    0   -2    0    0    0    0    0    0    0    0    0
+   42        -264.02           0.99    0    0    2    2    1    0    0    0    0    0    0    0    0    0
+   43         261.54          -0.95    1    0    0    2    0    0    0    0    0    0    0    0    0    0
+   44         256.30          -0.28    2    0    2   -2    2    0    0    0    0    0    0    0    0    0
+   45        -250.54           0.08    0    0    0    2    1    0    0    0    0    0    0    0    0    0
+   46         230.72           0.08    1    0    2   -2    1    0    0    0    0    0    0    0    0    0
+   47         229.78          -0.60    2    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+   48        -212.82           0.84    2    0    2    0    1    0    0    0    0    0    0    0    0    0
+   49         196.64          -0.84    0    0    0    2   -1    0    0    0    0    0    0    0    0    0
+   50         188.95          -0.12    0    1   -2    2   -1    0    0    0    0    0    0    0    0    0
+   51         187.95          -0.24    1   -1    0    0    0    0    0    0    0    0    0    0    0    0
+   52        -160.15         -14.04    1    0    0   -1    0    0    0    0    0    0    0    0    0    0
+   53        -172.95          -0.40    0    1    0   -2    0    0    0    0    0    0    0    0    0    0
+   54        -168.26           0.20    0    0    0    1    0    0    0    0    0    0    0    0    0    0
+   55         161.79           0.24    2    0    0   -2    1    0    0    0    0    0    0    0    0    0
+   56         161.34           0.20    1    0   -2    0    0    0    0    0    0    0    0    0    0    0
+   57          57.44          95.82    0    0    0    0    0    0    0    0    0    2   -5    0    0   -1
+   58         142.16           0.20    0    1    2   -2    1    0    0    0    0    0    0    0    0    0
+   59        -134.81           0.20    1    1    0    0    0    0    0    0    0    0    0    0    0    0
+   60         132.81          -0.52    1    0    2    0    0    0    0    0    0    0    0    0    0    0
+   61        -130.31           0.04    1   -1    0   -1    0    0    0    0    0    0    0    0    0    0
+   62         121.98          -0.08    2    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+   63        -115.40           0.60    3    0    2    0    2    0    0    0    0    0    0    0    0    0
+   64        -114.49           0.32    1   -1    2    0    2    0    0    0    0    0    0    0    0    0
+   65         112.14           0.28    1    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+   66         105.29           0.44    0    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+   67          98.69          -0.28    1    1    2    0    2    0    0    0    0    0    0    0    0    0
+   68          91.31          -0.40    2    0    0    0   -1    0    0    0    0    0    0    0    0    0
+   69          86.74          -0.08    2    0    0    0    1    0    0    0    0    0    0    0    0    0
+   70         -18.38          63.80    0    0    0    0    0    0    0    4   -8    3    0    0    0    0
+   71          82.14           0.00    0    0    0    0    0    0    3   -5    0    0    0    0    0   -2
+   72          79.03          -0.24    1    0   -2    2   -1    0    0    0    0    0    0    0    0    0
+   73           0.00         -79.08    0    1   -1    1   -1    0    0    0    0    0    0    0    0    0
+   74         -78.56           0.00    1    0    0    0    2    0    0    0    0    0    0    0    0    0
+   75          47.73          23.79    0    0    1   -1    1    0   -8   12    0    0    0    0    0    0
+   76          66.03          -0.20    0    0    2    1    2    0    0    0    0    0    0    0    0    0
+   77          62.65          -0.24    3    0    0    0    0    0    0    0    0    0    0    0    0    0
+   78          60.50           0.36    1    0   -2   -4   -2    0    0    0    0    0    0    0    0    0
+   79          59.07           0.00    0    0    0    0    0    0    1   -1    0    0    0    0    0    0
+   80          57.28           0.00    0    0    0    0    0    0    0    8  -16    4    5    0    0    0
+   81         -55.66           0.16    1    0    0    0   -2    0    0    0    0    0    0    0    0    0
+   82         -54.81          -0.08    2    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+   83         -53.22          -0.20    1    0    0   -4    0    0    0    0    0    0    0    0    0    0
+   84         -52.95           0.32    1    0    2    2    1    0    0    0    0    0    0    0    0    0
+   85         -52.27           0.00    1   -1    0   -1   -1    0    0    0    0    0    0    0    0    0
+   86          51.32           0.00    1    1    2   -2    2    0    0    0    0    0    0    0    0    0
+   87         -51.00          -0.12    2    0    0   -4    0    0    0    0    0    0    0    0    0    0
+   88          51.02           0.00    0    2   -2    2   -1    0    0    0    0    0    0    0    0    0
+   89         -48.65          -1.15    0    0    0    0    0    0    0    1    0   -1    0    0    0    0
+   90          48.29           0.20    2    0   -2   -4   -2    0    0    0    0    0    0    0    0    0
+   91         -46.38           0.00    0    0    0    0    0    0    0    0    0    2    0    0    0    2
+   92         -45.59          -0.12    1    0   -4    0   -2    0    0    0    0    0    0    0    0    0
+   93         -43.76           0.36    2    0    2    2    2    0    0    0    0    0    0    0    0    0
+   94         -40.58          -1.00    1    0    0   -1   -1    0    0    0    0    0    0    0    0    0
+   95           0.00         -41.53    1    0   -1    0   -1    0    0    0    0    0    0    0    0    0
+   96          40.54          -0.04    2    0    2   -2    1    0    0    0    0    0    0    0    0    0
+   97          40.33          -0.04    2    1    0   -2    0    0    0    0    0    0    0    0    0    0
+   98         -38.57           0.08    1    0    0    2    1    0    0    0    0    0    0    0    0    0
+   99          37.75           0.04    1   -1    0   -2    0    0    0    0    0    0    0    0    0    0
+  100          37.15          -0.12    3    0    2   -2    2    0    0    0    0    0    0    0    0    0
+  101          36.68          -0.04    0    0    4   -2    2    0    0    0    0    0    0    0    0    0
+  102         -18.30         -17.30    0    0    0    0    1    0    0   -1    2    0    0    0    0    0
+  103         -17.86          17.10    0    0    0    0    0    0    0    1   -2    0    0    0    0    0
+  104         -34.81           0.04    0    1   -2    2    0    0    0    0    0    0    0    0    0    0
+  105         -33.22           0.08    0    0    2   -2   -1    0    0    0    0    0    0    0    0    0
+  106          32.43          -0.04    0    1    2    0    1    0    0    0    0    0    0    0    0    0
+  107         -30.47           0.04    1    0    2   -2    0    0    0    0    0    0    0    0    0    0
+  108         -29.53           0.04    1    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+  109          28.50          -0.08    2    0   -2    0    1    0    0    0    0    0    0    0    0    0
+  110          28.35          -0.16    0    1    0    0    2    0    0    0    0    0    0    0    0    0
+  111         -28.00           0.00    0    0    2   -1    2    0    0    0    0    0    0    0    0    0
+  112         -27.61           0.20    0    0    2    4    2    0    0    0    0    0    0    0    0    0
+  113         -26.77           0.08    0    1    0    2    0    0    0    0    0    0    0    0    0    0
+  114          26.54          -0.12    0    0    2    0   -1    0    0    0    0    0    0    0    0    0
+  115          26.54           0.04    0    1   -2    0   -1    0    0    0    0    0    0    0    0    0
+  116         -26.17           0.00    0    1    2   -2    0    0    0    0    0    0    0    0    0    0
+  117         -25.42          -0.08    1    0   -2   -2    0    0    0    0    0    0    0    0    0    0
+  118         -16.91           8.43    0    0    0    0    0    0    8  -13    0    0    0    0    0   -1
+  119           0.32          24.42    0    0    0    0    0    0    2   -3    0    0    0    0    0    0
+  120         -19.53           5.09    0    0    0    0    0    0    0    0    0    2   -5    0    0    0
+  121         -23.79           0.00    0    0    0    0    0    0    2   -2    0    0    0    0    0    0
+  122          23.66           0.00    1   -1    0   -1   -2    0    0    0    0    0    0    0    0    0
+  123         -23.47           0.16    1   -1    2    2    2    0    0    0    0    0    0    0    0    0
+  124          23.39          -0.12    2    0    0    2    0    0    0    0    0    0    0    0    0    0
+  125         -23.49           0.00    0    1    0    0   -2    0    0    0    0    0    0    0    0    0
+  126         -23.28          -0.08    1    1    0   -2    1    0    0    0    0    0    0    0    0    0
+  127         -22.99           0.04    1    0   -2    2    0    0    0    0    0    0    0    0    0    0
+  128         -22.67          -0.08    1   -1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+  129           9.35          13.29    0    0    0    0    0    0    8  -13    0    0    0    0    0    0
+  130          22.47          -0.04    0    1    0    1    0    0    0    0    0    0    0    0    0    0
+  131           4.89         -16.55    0    0    0    0    0    0    0    2   -8    3    0    0    0   -2
+  132           4.89         -16.51    0    0    0    0    0    0    0    6   -8    3    0    0    0    2
+  133          21.28          -0.08    0    1    2    2    2    0    0    0    0    0    0    0    0    0
+  134          20.57           0.64    0    0    0    0    0    0    0    3    0   -1    0    0    0    2
+  135          21.01           0.00    1   -1    0    0    1    0    0    0    0    0    0    0    0    0
+  136           1.23         -19.13    0    0    1   -1    1    0    0   -1    0    2   -5    0    0    0
+  137         -19.97           0.12    3    0    2    0    1    0    0    0    0    0    0    0    0    0
+  138          19.65          -0.08    0    0    0    4    0    0    0    0    0    0    0    0    0    0
+  139          19.58          -0.12    1    0    0    2   -1    0    0    0    0    0    0    0    0    0
+  140          19.61          -0.08    1   -1    0    2    0    0    0    0    0    0    0    0    0    0
+  141         -19.41           0.08    2   -1    2    0    2    0    0    0    0    0    0    0    0    0
+  142         -19.49           0.00    0    0    0    0    0    0    4   -6    0    0    0    0    0   -2
+  143         -18.64           0.00    0    0    0    2    2    0    0    0    0    0    0    0    0    0
+  144          18.58           0.04    1    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  145         -18.42           0.00    1   -1   -2    0   -2    0    0    0    0    0    0    0    0    0
+  146          18.22           0.00    0    0    0    0    0    0    2   -4    0    0    0    0    0   -2
+  147          -0.72         -17.34    0    0    2   -2    1    0   -5    6    0    0    0    0    0    0
+  148         -18.02          -0.04    1    0    2   -4    1    0    0    0    0    0    0    0    0    0
+  149          17.74           0.08    0    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  150          17.46           0.00    2    0    0   -2    0    0    0   -2    0    2    0    0    0    0
+  151         -17.42           0.00    0    3    2   -2    2    0    0    0    0    0    0    0    0    0
+  152          -6.60          10.70    0    0    0    0    0    0    0    1    0   -2    0    0    0    0
+  153          16.43           0.52    0    0    0    0    0    0    0    2    0   -2    0    0    0    0
+  154         -16.75           0.04    1   -1    2    0    1    0    0    0    0    0    0    0    0    0
+  155          16.55          -0.08    0    0    2    2    0    0    0    0    0    0    0    0    0    0
+  156          16.39          -0.08    2    1    2    0    2    0    0    0    0    0    0    0    0    0
+  157          13.88          -2.47    2    0    0   -2    0    0    0   -2    0    3    0    0    0    0
+  158          15.69           0.00    1    0    0   -2   -2    0    0    0    0    0    0    0    0    0
+  159         -15.52           0.00    0    0    0    1    1    0    0    0    0    0    0    0    0    0
+  160           3.34          11.86    0    0    0    0    1    0    0   -4    8   -3    0    0    0    0
+  161          14.72          -0.32    0    0    0    0    0    0    2    0    0    0    0    0    0    2
+  162          14.92          -0.04    2   -1    0    0    0    0    0    0    0    0    0    0    0    0
+  163          -3.26          11.62    0    0    0    0    1    0    0    4   -8    3    0    0    0    0
+  164         -14.64           0.00    0    0    0    0    0    0    0    2   -2    0    0    0    0    0
+  165           0.00          14.47    1    0   -1    0   -2    0    0    0    0    0    0    0    0    0
+  166         -14.37           0.00    1    1    0    0    1    0    0    0    0    0    0    0    0    0
+  167          14.32          -0.04    1    1    2    0    1    0    0    0    0    0    0    0    0    0
+  168         -14.10           0.04    1    0   -2    2   -2    0    0    0    0    0    0    0    0    0
+  169          10.86           3.18    0    0    1   -1    1    0    0    0   -2    0    0    0    0    0
+  170         -10.58          -3.10    0    0    1   -1    0    0    0    0   -2    0    0    0    0    0
+  171          -3.62           9.86    0    0    0    0    0    0    0    0    0    1    0    0    0    0
+  172         -13.48           0.00    0    0    0    0    0    0    1    1    0    0    0    0    0    2
+  173          13.41          -0.04    1    0    2    1    2    0    0    0    0    0    0    0    0    0
+  174          13.32          -0.08    2    0    2    0    0    0    0    0    0    0    0    0    0    0
+  175         -13.33          -0.04    0    1    0   -2    1    0    0    0    0    0    0    0    0    0
+  176         -13.29           0.00    1    0    2   -1    2    0    0    0    0    0    0    0    0    0
+  177          -0.20          13.05    0    0    0    0    0    0    3   -4    0    0    0    0    0    0
+  178           0.00          13.13    1    0   -1    0    0    0    0    0    0    0    0    0    0    0
+  179          -8.99           4.02    1    0    0    0    0    0  -18   16    0    0    0    0    0    0
+  180         -12.93           0.04    1    0    0    1    0    0    0    0    0    0    0    0    0    0
+  181           2.03          10.82    0    0    0    0    0    0    0    0    0    2    0    0    0    1
+  182         -12.78           0.04    0    0    0    1   -1    0    0    0    0    0    0    0    0    0
+  183          12.24           0.04    1    0    0   -2    2    0    0    0    0    0    0    0    0    0
+  184           8.71           3.54    1    0    0    0    0    0  -10    3    0    0    0    0    0    0
+  185          11.98          -0.04    1   -1    0    0   -1    0    0    0    0    0    0    0    0    0
+  186         -11.38           0.04    2    1    0    0    0    0    0    0    0    0    0    0    0    0
+  187         -11.30           0.00    2    0    0   -2   -1    0    0   -2    0    2    0    0    0    0
+  188          11.14          -0.04    0    0    2    1    1    0    0    0    0    0    0    0    0    0
+  189          10.98           0.00    0    3    0    0    0    0    0    0    0    0    0    0    0    0
+  190         -10.98           0.00    1    2    0   -2    0    0    0    0    0    0    0    0    0    0
+  191           0.44         -10.38    0    0    0    0    0    0    5   -8    0    0    0    0    0   -2
+  192          10.46           0.08    1    0   -2   -4   -1    0    0    0    0    0    0    0    0    0
+  193         -10.42           0.00    0    0    0    0    0    0    0    1    0    1    0    0    0    2
+  194         -10.30           0.08    4    0    2    0    2    0    0    0    0    0    0    0    0    0
+  195           6.92           3.34    0    0    1   -1    1    0    0   -1    0    0   -1    0    0    0
+  196          10.07           0.04    1    0   -2    0    1    0    0    0    0    0    0    0    0    0
+  197          10.02           0.00    2    1    2   -2    2    0    0    0    0    0    0    0    0    0
+  198          -9.75           0.04    0    1    2    1    2    0    0    0    0    0    0    0    0    0
+  199           9.75           0.00    1    1    2   -2    1    0    0    0    0    0    0    0    0    0
+  200           9.67          -0.04    1    0    4   -2    2    0    0    0    0    0    0    0    0    0
+  201          -1.99           7.72    0    0    1   -1    1    0    0   -1    0   -1    0    0    0    0
+  202           0.40           9.27    0    0    2   -2    0    0   -5    6    0    0    0    0    0    0
+  203          -3.42           6.09    0    0    0    0    0    0    0    2   -4    0    0    0    0    0
+  204           0.56          -8.67    0    0    0    0    0    0    0    0    0    2   -5    0    0    1
+  205          -9.19           0.00    2    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  206           9.11           0.00    1    0   -2    1   -1    0    0    0    0    0    0    0    0    0
+  207           9.07           0.00    2   -2    0   -2    0    0    0    0    0    0    0    0    0    0
+  208           1.63           6.96    0    0    0    0    0    0    8  -13    0    0    0    0    0   -2
+  209          -8.47           0.00    0    2    0   -2    0    0    0    0    0    0    0    0    0    0
+  210          -8.28           0.04    1    1    0    0   -1    0    0    0    0    0    0    0    0    0
+  211           8.27           0.04    2    0   -2   -4   -1    0    0    0    0    0    0    0    0    0
+  212          -8.04           0.00    0    0    0    0    0    0    5   -7    0    0    0    0    0   -2
+  213           7.91           0.00    0    1    0    2    1    0    0    0    0    0    0    0    0    0
+  214          -7.84          -0.04    1    0   -4    0   -1    0    0    0    0    0    0    0    0    0
+  215          -7.64           0.08    2    0    2    2    1    0    0    0    0    0    0    0    0    0
+  216           5.21          -2.51    1    0    2    0    2    0    0    1    0    0    0    0    0    0
+  217          -5.77           1.87    0    0    0    0    0    0    3   -5    0    0    0    0    0    0
+  218           5.01          -2.51    1    0   -2    0   -2    0    0    4   -8    3    0    0    0    0
+  219          -7.48           0.00    0    0    2   -3    2    0    0    0    0    0    0    0    0    0
+  220          -7.32          -0.12    0    0    0    0    0    0    0    4    0   -2    0    0    0    2
+  221           7.40          -0.04    0    0    4    0    2    0    0    0    0    0    0    0    0    0
+  222           7.44           0.00    1    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+  223           6.32          -1.11    1    0    0   -1    1    0    0    0    0    0    0    0    0    0
+  224          -6.13          -1.19    0    0    0    0    0    0    0    2    0   -1    0    0    0    2
+  225           0.20          -6.88    0    0    0    0    0    0    2   -1    0    0    0    0    0    2
+  226           6.92           0.04    1    1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+  227           6.48          -0.48    0    0    0    0    0    0    0    2    0    1    0    0    0    2
+  228          -6.94           0.00    2    0    0   -2   -2    0    0    0    0    0    0    0    0    0
+  229           2.47          -4.46    0    0    0    0    0    0    8  -11    0    0    0    0    0   -2
+  230          -2.23          -4.65    0    0    0    0    0    0    0    8  -16    4    5    0    0   -2
+  231          -1.07          -5.69    0    0    1   -1    1    0    0   -1    0    2    0    0    0    0
+  232           4.97          -1.71    0    0    0    0    0    0    0    8  -16    4    5    0    0    2
+  233           5.57           1.07    0    0    1   -1    1    0   -5    7    0    0    0    0    0    0
+  234          -6.48           0.08    1    0    2    4    2    0    0    0    0    0    0    0    0    0
+  235           2.03           4.53    0    0    0    0    0    0    0    0    0    0    2    0    0    1
+  236           4.10          -2.39    1    0    0   -2    0    0   19  -21    3    0    0    0    0    0
+  237           0.00          -6.44    0    0    1    0    1    0    0    0    0    0    0    0    0    0
+  238          -6.40           0.00    3    0    0   -4    0    0    0    0    0    0    0    0    0    0
+  239           6.32           0.00    1    1   -2    0   -2    0    0    0    0    0    0    0    0    0
+  240           2.67          -3.62    0    0    0    0    0    0    0    3    0   -2    0    0    0    2
+  241          -1.91          -4.38    0    0    1   -1    1    0    0   -1    0    0    2    0    0    0
+  242          -2.43          -3.82    0    0    0    0    0    0    8  -15    0    0    0    0    0   -2
+  243           6.20           0.00    0    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+  244          -3.38          -2.78    0    0    0    0    0    0    0    1    2    0    0    0    0    2
+  245          -6.12           0.04    0    0    0    4    1    0    0    0    0    0    0    0    0    0
+  246          -6.09          -0.04    0    0    2   -4    1    0    0    0    0    0    0    0    0    0
+  247          -6.01          -0.04    1    1    0   -4    0    0    0    0    0    0    0    0    0    0
+  248           3.18          -2.82    0    0    0    0    0    0    0    3   -2    0    0    0    0    2
+  249          -5.05           0.84    0    0    0    0    0    0    0    0    0    3    0    0    0    2
+  250           5.85           0.00    3    0    2   -2    1    0    0    0    0    0    0    0    0    0
+  251           5.69          -0.12    0    0    0    0    0    0    0    4   -2    0    0    0    0    2
+  252           5.73          -0.04    1    1    2    2    2    0    0    0    0    0    0    0    0    0
+  253           5.61           0.00    0    0    4   -2    1    0    0    0    0    0    0    0    0    0
+  254           5.49           0.00    2    0    0   -2    0    0   -3    3    0    0    0    0    0    0
+  255          -5.33           0.04    3    0    2    2    2    0    0    0    0    0    0    0    0    0
+  256          -5.29           0.00    0    0    0    0    0    0    0    0    0    0    2    0    0    2
+  257           5.25           0.00    2    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+  258           0.99           4.22    0    0    0    0    0    0    4   -6    0    0    0    0    0   -1
+  259          -0.99           4.22    0    0    0    0    0    0    1   -1    0    0    0    0    0   -1
+  260           0.00           5.21    1    0    0   -1    0    0   -3    4    0    0    0    0    0    0
+  261           5.13           0.04    0    2   -2   -2   -2    0    0    0    0    0    0    0    0    0
+  262          -4.90           0.00    2    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+  263          -3.10           1.79    0    0    0    0    0    0    0    3   -4    0    0    0    0    0
+  264          -4.81           0.04    0    0    2    4    1    0    0    0    0    0    0    0    0    0
+  265          -4.75           0.00    0    0    0    2   -2    0    0    0    0    0    0    0    0    0
+  266           4.70          -0.04    3    0    0    0   -1    0    0    0    0    0    0    0    0    0
+  267          -4.69           0.00    0    0    0    0    0    0    0    1    0   -3    0    0    0   -2
+  268          -4.65           0.00    0    0    0    0    0    0    6   -8    0    0    0    0    0   -2
+  269           4.65           0.00    0    0    2   -2    1    0   -3    3    0    0    0    0    0    0
+  270          -4.57           0.00    2    1    0   -4    0    0    0    0    0    0    0    0    0    0
+  271           4.49          -0.04    4    0    2   -2    2    0    0    0    0    0    0    0    0    0
+  272          -4.53           0.00    0    0    1   -1    1    0    0    3   -8    3    0    0    0    0
+  273           0.00          -4.53    0    0    0    0    0    0    3   -2    0    0    0    0    0    2
+  274           0.00          -4.53    0    0    0    0    0    0    2   -5    0    0    0    0    0   -2
+  275          -4.53           0.00    2    0    0    2    1    0    0    0    0    0    0    0    0    0
+  276           4.50           0.00    1   -1    0   -2   -1    0    0    0    0    0    0    0    0    0
+  277          -4.49           0.00    0    0    0    0    0    0    1   -3    0    0    0    0    0   -2
+  278           1.83           2.63    0    0    0    0    1    0    8  -13    0    0    0    0    0    0
+  279           4.38           0.00    2    1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+  280           0.88          -3.46    0    0    0    0    0    0    1   -2    0    0    0    0    0    0
+  281          -2.70           1.55    0    0    0    0    0    0    0    2   -3    0    0    0    0    0
+  282          -4.22           0.00    0    0    2   -1    1    0    0    0    0    0    0    0    0    0
+  283          -4.10          -0.12    1    1    0    2    0    0    0    0    0    0    0    0    0    0
+  284           3.54          -0.64    2    0    0   -2    1    0    0   -2    0    3    0    0    0    0
+  285          -3.50           0.68    0    0    0    0    0    0    5   -8    0    0    0    0    0   -1
+  286           4.18           0.00    1   -1   -2    2   -1    0    0    0    0    0    0    0    0    0
+  287           4.14           0.00    1    2   -2   -2   -2    0    0    0    0    0    0    0    0    0
+  288           4.10           0.00    1    0    0   -3    0    0    0    0    0    0    0    0    0    0
+  289          -4.06           0.00    2    0    0   -4    1    0    0    0    0    0    0    0    0    0
+  290           2.70          -1.35    1    0    0    0   -1    0  -18   16    0    0    0    0    0    0
+  291          -4.04           0.00    2    0    0   -2    2    0    0    0    0    0    0    0    0    0
+  292          -3.98          -0.04    1    0    0   -4    1    0    0    0    0    0    0    0    0    0
+  293          -3.98           0.04    1   -1    2    2    1    0    0    0    0    0    0    0    0    0
+  294           4.02           0.00    2    0    2   -4    1    0    0    0    0    0    0    0    0    0
+  295           3.94           0.00    0    0    1   -1    1    0    0   -5    8   -3    0    0    0    0
+  296           0.84          -3.10    0    0    1   -1    0    0    0   -1    0   -1    0    0    0    0
+  297           3.30           0.60    0    0    0    0    0    0    0    2    0   -3    0    0    0    0
+  298          -1.59           2.27    0    0    0    0    1    0   -8   13    0    0    0    0    0    0
+  299          -3.66          -0.20    2   -1    0   -2    0    0    0    0    0    0    0    0    0    0
+  300          -3.10          -0.72    2    0    0   -2    0    0   -6    8    0    0    0    0    0    0
+  301          -3.82           0.00    1   -1   -2    0   -1    0    0    0    0    0    0    0    0    0
+  302          -3.62          -0.16    2    1   -2    0   -1    0    0    0    0    0    0    0    0    0
+  303          -3.74           0.00    0    1   -2    1   -2    0    0    0    0    0    0    0    0    0
+  304           3.74           0.00    4    0    0    0    0    0    0    0    0    0    0    0    0    0
+  305          -3.74           0.00    0    2   -2    2    0    0    0    0    0    0    0    0    0    0
+  306          -3.71           0.00    0    2    0    0    1    0    0    0    0    0    0    0    0    0
+  307           3.02           0.68    0    0    0    0    1    0    0    0    0   -2    5    0    0    0
+  308           3.70           0.00    1    0   -4    2   -2    0    0    0    0    0    0    0    0    0
+  309           3.30           0.40    0    2   -2    0   -2    0    0    0    0    0    0    0    0    0
+  310          -3.66           0.04    2   -1    2    2    2    0    0    0    0    0    0    0    0    0
+  311           3.66           0.04    0    1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+  312          -3.62           0.00    1    0   -2   -3   -2    0    0    0    0    0    0    0    0    0
+  313          -3.61           0.00    2    0    0    0    2    0    0    0    0    0    0    0    0    0
+  314          -2.90           0.68    0    0    0    0    1    0    0    0    0    2   -5    0    0    0
+  315           0.80          -2.78    0    0    0    0    1    0    0    0    0    1    0    0    0    0
+  316           3.54           0.00    0    0    0    0    0    0    3   -3    0    0    0    0    0    0
+  317          -3.54           0.00    0    0    0    0    0    0    0    2    0    0    0    0    0    2
+  318          -3.50           0.00    2    0    2   -2    0    0    0    0    0    0    0    0    0    0
+  319           3.45           0.00    0    2    2   -2    1    0    0    0    0    0    0    0    0    0
+  320           0.00          -3.42    0    0    0    0    0    0    0    6  -16    4    5    0    0   -2
+  321           3.38           0.00    1   -2    0    0    0    0    0    0    0    0    0    0    0    0
+  322           2.27          -1.11    1    0    0    0    1    0  -18   16    0    0    0    0    0    0
+  323          -3.34           0.00    1   -1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  324           3.34           0.00    0    1    2    2    1    0    0    0    0    0    0    0    0    0
+  325          -3.30           0.01    0    0    2    0    3    0    0    0    0    0    0    0    0    0
+  326           3.31           0.00    1    0    2    0   -1    0    0    0    0    0    0    0    0    0
+  327           3.30           0.00    3    0    0    0    1    0    0    0    0    0    0    0    0    0
+  328          -3.30           0.00    1    0   -2   -1   -2    0    0    0    0    0    0    0    0    0
+  329          -1.39          -1.91    0    0    0    0    0    0    0    1    0    2    0    0    0    2
+  330           3.30           0.00    0    0    0    0    0    0    4   -4    0    0    0    0    0    0
+  331           3.26           0.00    2    1    0   -2    1    0    0    0    0    0    0    0    0    0
+  332           3.26           0.00    1    0    0    4    0    0    0    0    0    0    0    0    0    0
+  333           3.22          -0.04    1    0    2    2    0    0    0    0    0    0    0    0    0    0
+  334          -3.26           0.00    2   -1   -2    0   -1    0    0    0    0    0    0    0    0    0
+  335           2.51          -0.64    0    0    0    0    0    0    3   -7    0    0    0    0    0   -2
+  336           3.14           0.00    2    0   -4    0   -2    0    0    0    0    0    0    0    0    0
+  337          -2.63          -0.48    0    0    1   -1    1    0    0   -1    0    0    1    0    0    0
+  338           3.10           0.00    3    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+  339          -3.06           0.00    2   -1    2    0    1    0    0    0    0    0    0    0    0    0
+  340           2.94          -0.12    1   -2    0   -2    0    0    0    0    0    0    0    0    0    0
+  341           3.06           0.00    2    0   -2    2   -1    0    0    0    0    0    0    0    0    0
+  342           0.00           2.98    0    0    1    0    0    0    0    0    0    0    0    0    0    0
+  343           2.98           0.00    1    0    2   -4    0    0    0    0    0    0    0    0    0    0
+  344           2.07           0.91    0    0    0    0    0    0    0    0    0    1    0    0    0    2
+  345          -2.98           0.00    0    0    0    0    0    0    0    1    0    0   -1    0    0    0
+  346           2.94           0.00    0    2    2    0    2    0    0    0    0    0    0    0    0    0
+  347          -2.94           0.00    0    0    0    0    0    0    7   -9    0    0    0    0    0   -2
+  348          -2.94           0.00    0    0    0    0    0    0    0    0    2    0    0    0    0    2
+  349          -2.90           0.00    1   -1    2   -2    2    0    0    0    0    0    0    0    0    0
+  350          -0.56          -2.35    0    0    0    0    0    0    2   -4    0    0    0    0    0   -1
+  351          -1.47           1.39    0    0    0    0    1    0    0    1   -2    0    0    0    0    0
+  352           2.80           0.00    1    0    2   -4    2    0    0    0    0    0    0    0    0    0
+  353          -2.74           0.00    2    0    2   -1    2    0    0    0    0    0    0    0    0    0
+  354          -0.12           2.63    0    0    0    0    0    0    4   -7    0    0    0    0    0   -2
+  355           2.15          -0.60    0    0    0    0    0    0    3   -3    0    0    0    0    0    2
+  356          -2.70           0.00    1    1   -2    1   -1    0    0    0    0    0    0    0    0    0
+  357           1.79          -0.88    0    0    0    0    0    0    0    8  -15    0    0    0    0    0
+  358          -0.48           2.19    0    0    0    0    0    0    2   -2    0    0    0    0    0   -1
+  359           0.44           2.23    0    0    0    0    0    0    0    0    0    0    1    0    0    0
+  360           0.52           2.07    0    0    0    0    0    0    0    0    0    1    0    0    0   -1
+  361          -2.59           0.00    0    1    0   -4    0    0    0    0    0    0    0    0    0    0
+  362           2.55           0.00    2    1    2    0    1    0    0    0    0    0    0    0    0    0
+  363          -1.11           1.43    0    0    0    0    0    0    0    1    0   -3    0    0    0    0
+  364          -2.51           0.00    3   -1    2    0    2    0    0    0    0    0    0    0    0    0
+  365          -2.51           0.00    2    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+  366           2.51           0.00    1    1   -2    0   -1    0    0    0    0    0    0    0    0    0
+  367           0.00          -2.50    1    0   -1    0   -3    0    0    0    0    0    0    0    0    0
+  368           2.47           0.00    1   -1    0   -2    1    0    0    0    0    0    0    0    0    0
+  369           2.11          -0.36    2    0    0   -2   -1    0    0   -2    0    3    0    0    0    0
+  370           1.67           0.80    0    0    1   -1    0    0    0   -1    0    0   -1    0    0    0
+  371           2.46           0.00    0    2    0    0   -1    0    0    0    0    0    0    0    0    0
+  372          -2.43           0.00    1    0   -2    1    0    0    0    0    0    0    0    0    0    0
+  373          -2.39           0.00    1    0    2   -3    2    0    0    0    0    0    0    0    0    0
+  374          -1.83           0.56    0    0    0    0    0    0    4   -6    0    0    0    0    0    0
+  375          -0.44          -1.95    0    0    0    0    0    0    3   -5    0    0    0    0    0   -1
+  376           0.24           2.15    0    0    0    0    0    0    0    0    0    1    0    0    0    1
+  377           2.39           0.00    2    0   -2   -2    0    0    0    0    0    0    0    0    0    0
+  378           2.35           0.00    0    0    0    0    0    0    5   -5    0    0    0    0    0    0
+  379           2.27           0.00    1    0    2    1    1    0    0    0    0    0    0    0    0    0
+  380          -2.22           0.00    2    0    0    0   -2    0    0    0    0    0    0    0    0    0
+  381          -1.03          -1.15    1    0    0   -1    1    0    0   -1    0    2    0    0    0    0
+  382           1.87           0.32    0    0    0    0    0    0    0    0    0    0    1    0    0    1
+  383          -0.32          -1.87    0    0    1   -1    1    0    0   -2    2    0    0    0    0    0
+  384           2.15           0.00    2    0    0   -2    1    0    0   -2    0    2    0    0    0    0
+  385          -0.80           1.35    0    0    0    0    0    0    0    3   -5    0    0    0    0    0
+  386           2.11           0.00    3    1    2    0    2    0    0    0    0    0    0    0    0    0
+  387          -2.11           0.00    1    1    2    1    2    0    0    0    0    0    0    0    0    0
+  388          -0.56          -1.55    0    0    0    0    0    0    5   -8    0    0    0    0    0    0
+  389           2.11           0.00    1    0    0   -1    0    0    0   -1    0    1    0    0    0    0
+  390          -0.84          -1.27    0    0    0    0    0    0    0    0    4    0    0    0    0    2
+  391          -1.99           0.12    0    0    0    0    0    0    8  -10    0    0    0    0    0   -2
+  392          -0.24           1.87    0    0    0    0    0    0    0    1   -2    0    0    0    0   -1
+  393          -0.24          -1.87    0    0    1   -1    1    0    0   -1    0    1    0    0    0    0
+  394          -2.03           0.00    1   -2    2    0    2    0    0    0    0    0    0    0    0    0
+  395           2.03           0.00    2   -1    2   -2    2    0    0    0    0    0    0    0    0    0
+  396           2.03           0.00    2    0    0   -3    0    0    0    0    0    0    0    0    0    0
+  397           2.03           0.00    0    0    0    0    0    0    0    2   -4    0    0    0    0   -2
+  398          -0.40           1.59    0    0    1   -1    1    0   -3    4    0    0    0    0    0    0
+  399           1.99           0.00    0    0    2   -2    1    0    0   -2    0    2    0    0    0    0
+  400           1.95           0.00    0    1    0    1    1    0    0    0    0    0    0    0    0    0
+  401           1.95           0.00    3    0    0    2    0    0    0    0    0    0    0    0    0    0
+  402           1.91           0.00    0    1    0    1   -1    0    0    0    0    0    0    0    0    0
+  403           1.19          -0.72    0    0    0    0    0    0    0    5   -4    0    0    0    0    2
+  404           1.87           0.00    2    0    2    1    2    0    0    0    0    0    0    0    0    0
+  405           1.87           0.00    1    1    0    1    0    0    0    0    0    0    0    0    0    0
+  406          -1.27           0.60    0    0    0    0    0    0    0    0    0    0    1    0    0   -1
+  407           0.72          -1.15    0    0    0    0    0    0    0    4   -4    0    0    0    0    2
+  408          -0.99           0.88    0    0    0    0    0    0    0    0    0    2    0    0    0    0
+  409           1.87           0.00    2   -1    0    2    0    0    0    0    0    0    0    0    0    0
+  410          -1.87           0.00    1    1   -2    2   -1    0    0    0    0    0    0    0    0    0
+  411          -1.83           0.00    2    0   -4   -2   -2    0    0    0    0    0    0    0    0    0
+  412          -1.79           0.00    0    1    0    2   -1    0    0    0    0    0    0    0    0    0
+  413          -1.79           0.00    4    0    2    0    1    0    0    0    0    0    0    0    0    0
+  414           1.79           0.00    1    2    2   -2    2    0    0    0    0    0    0    0    0    0
+  415           0.00          -1.79    0    0    0    0    0    0    6   -9    0    0    0    0    0   -2
+  416          -1.79           0.00    1    1    2   -4    1    0    0    0    0    0    0    0    0    0
+  417          -1.75           0.00    0    0    4   -4    2    0    0    0    0    0    0    0    0    0
+  418          -1.75           0.00    3    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+  419           1.75           0.00    2    1   -2    0    0    0    0    0    0    0    0    0    0    0
+  420          -1.47          -0.28    0    0    0    0    0    0    0    4    0   -3    0    0    0    2
+  421          -1.71           0.00    1    0    2   -3    1    0    0    0    0    0    0    0    0    0
+  422           1.71           0.00    2    0   -2   -6   -2    0    0    0    0    0    0    0    0    0
+  423           0.32           1.39    0    0    0    0    0    0    5   -7    0    0    0    0    0   -1
+  424           0.28          -1.43    0    0    0    0    0    0    0    2    0    0    0    0    0    1
+  425          -0.52          -1.19    0    0    0    0    0    0    0    1    0    2   -5    0    0    0
+  426           1.67           0.00    2    0    0    2   -1    0    0    0    0    0    0    0    0    0
+  427          -1.67           0.00    0    1    2    1    1    0    0    0    0    0    0    0    0    0
+  428           0.76          -0.91    0    0    0    0    0    0    2    1    0    0    0    0    0    2
+  429          -0.32           1.35    0    0    0    0    0    0    3   -3    0    0    0    0    0   -1
+  430          -1.39          -0.28    0    0    1   -1    0    0   -5    7    0    0    0    0    0    0
+  431           1.63           0.00    2    1    2   -2    1    0    0    0    0    0    0    0    0    0
+  432          -1.59           0.00    1    0    2   -1    1    0    0    0    0    0    0    0    0    0
+  433           1.03          -0.56    0    0    0    0    0    0    0    4   -3    0    0    0    0    2
+  434           1.59           0.00    0    0    0    0    0    0    6   -6    0    0    0    0    0    0
+  435           1.55           0.00    1    0    4   -2    1    0    0    0    0    0    0    0    0    0
+  436          -0.28          -1.27    0    0    0    0    0    0    1   -1    0    0    0    0    0    1
+  437          -0.64           0.91    0    0    0    0    0    0    0    4   -6    0    0    0    0    0
+  438          -0.32          -1.23    0    0    0    0    0    0    1   -3    0    0    0    0    0   -1
+  439          -1.55           0.00    1   -1    2   -2    1    0    0    0    0    0    0    0    0    0
+  440          -1.51           0.00    1    0    2   -2   -1    0    0    0    0    0    0    0    0    0
+  441           1.51           0.00    2   -2    0   -2   -1    0    0    0    0    0    0    0    0    0
+  442          -1.51           0.00    2   -1    0   -2    1    0    0    0    0    0    0    0    0    0
+  443           1.51           0.00    2    0    0   -1    0    0    0    0    0    0    0    0    0    0
+  444           1.47           0.00    2    0    4   -2    2    0    0    0    0    0    0    0    0    0
+  445           1.47           0.00    0    0    2    3    2    0    0    0    0    0    0    0    0    0
+  446           0.95          -0.52    0    0    0    0    0    0    0    3   -6    0    0    0    0   -2
+  447           1.23          -0.24    0    0    0    0    0    0    3   -1    0    0    0    0    0    2
+  448           0.60           0.88    2    0    0   -2    0    0    0   -6    8    0    0    0    0    0
+  449          -1.47           0.00    1   -1    0    2    1    0    0    0    0    0    0    0    0    0
+  450          -1.43           0.00    1    0   -2    2    1    0    0    0    0    0    0    0    0    0
+  451           1.43           0.00    1   -1    0    2   -1    0    0    0    0    0    0    0    0    0
+  452           1.43           0.00    0    1    4   -2    2    0    0    0    0    0    0    0    0    0
+  453          -0.68          -0.76    0    0    1   -1    1    0    0   -1    0    0    0    0    2    0
+  454           0.95          -0.48    2    0    2    0    2    0    0    2    0   -3    0    0    0    0
+  455          -0.95          -0.48    0    0    2    0    2    0    0    1    0    0    0    0    0    0
+  456          -1.19          -0.24    0    0    0    0    0    0    0    1    0   -4    0    0    0   -2
+  457           0.36          -1.07    0    0    1   -1    1    0    0   -1    0   -4   10    0    0    0
+  458           0.95           0.48    2    0    0   -2    0    0    0   -5    6    0    0    0    0    0
+  459           1.43           0.00    1    1    0   -1    0    0    0    0    0    0    0    0    0    0
+  460           1.39           0.00    0    0    0    4   -1    0    0    0    0    0    0    0    0    0
+  461           1.39           0.00    2   -1    0    0    1    0    0    0    0    0    0    0    0    0
+  462          -1.39           0.00    1   -2   -2   -2   -2    0    0    0    0    0    0    0    0    0
+  463          -1.39           0.00    1    2    0    0    0    0    0    0    0    0    0    0    0    0
+  464           0.00           1.39    0    0    0    0    0    0    0    2    0   -1    0    0    0    0
+  465          -0.12          -1.27    0    0    0    0    0    0    0    4    0   -1    0    0    0    2
+  466           0.56           0.84    0    0    0    0    0    0    0    2   -4    0    0    0    0   -1
+  467          -0.44          -0.95    0    0    0    0    0    0    0    0    0    2   -5    0    0   -2
+  468           0.32          -1.07    0    0    0    0    0    0    0    1    0    0    0    0    0    0
+  469           1.03          -0.36    2    0   -1   -1    0    0    0    3   -7    0    0    0    0    0
+  470          -0.28           1.11    0    0    1   -1    1    0   -4    5    0    0    0    0    0    0
+  471           0.44           0.95    0    0    1   -1    2    0    0   -1    0    0    2    0    0    0
+  472          -1.35           0.00    1   -1   -2    2    0    0    0    0    0    0    0    0    0    0
+  473           0.88           0.48    0    0    0    0    0    0    0    1   -8    3    0    0    0   -2
+  474          -1.35           0.00    0    0    0    0    0    0    9  -11    0    0    0    0    0   -2
+  475           1.35           0.00    1    0    0   -2    0    0    0   -2    0    2    0    0    0    0
+  476           1.35           0.00    1    0    0   -1   -2    0    0    0    0    0    0    0    0    0
+  477          -1.31           0.00    0    1   -2    2    1    0    0    0    0    0    0    0    0    0
+  478           1.31           0.00    1    0   -2    1   -2    0    0    0    0    0    0    0    0    0
+  479          -1.19          -0.12    0    0    0    0    0    0    2   -3    0    0    0    0    0   -1
+  480           1.27           0.00    0    0    4    0    1    0    0    0    0    0    0    0    0    0
+  481           0.40          -0.88    0    0    2   -2    1    0    0   -9   13    0    0    0    0    0
+  482           1.27           0.00    1    0   -2   -6   -2    0    0    0    0    0    0    0    0    0
+  483           1.27           0.00    3    1    2   -2    2    0    0    0    0    0    0    0    0    0
+  484          -0.16          -1.11    0    0    0    0    0    0    1    0    0    0    0    0    0    0
+  485          -0.84           0.44    2    0    0    0    0    0    0   -2    0    3    0    0    0    0
+  486           0.84          -0.44    1    0    2    0    1    0    0   -2    0    3    0    0    0    0
+  487           0.84          -0.44    1    0   -2    0   -1    0    0   -1    0    0    0    0    0    0
+  488          -1.27           0.00    1    0   -4   -2   -2    0    0    0    0    0    0    0    0    0
+  489          -1.27           0.00    1    0    0    4    1    0    0    0    0    0    0    0    0    0
+  490           1.27           0.00    1    1    0    2    1    0    0    0    0    0    0    0    0    0
+  491          -0.44          -0.84    0    0    0    0    1    0    0   -2    4    0    0    0    0    0
+  492           0.00          -1.27    0    0    0    0    1    0    2   -3    0    0    0    0    0    0
+  493          -1.27           0.00    2    0    2   -4    2    0    0    0    0    0    0    0    0    0
+  494          -1.23           0.00    1   -1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+  495          -1.23           0.00    1   -2    2    2    2    0    0    0    0    0    0    0    0    0
+  496           1.23           0.00    0    0    2   -1    0    0    0    0    0    0    0    0    0    0
+  497           0.00           1.23    0    0    0    0    0    0    0    3   -6    0    0    0    0    0
+  498          -0.12           1.11    0    0    1    1    1    0    0    1    0    0    0    0    0    0
+  499           1.22           0.00    0    0    2   -4    2    0    0    0    0    0    0    0    0    0
+  500           1.19           0.00    1    1   -2   -4   -1    0    0    0    0    0    0    0    0    0
+  501          -0.24           0.95    0    0    0    0    0    0    4   -4    0    0    0    0    0   -1
+  502          -0.76          -0.44    0    0    0    0    0    0    0    3   -8    3    0    0    0    0
+  503           0.91           0.28    0    0    0    0    0    0    0    1   -2    0    0    0    0    1
+  504           1.19           0.00    1    1   -2    1    0    0    0    0    0    0    0    0    0    0
+  505           1.19           0.00    3    0    2    0    0    0    0    0    0    0    0    0    0    0
+  506           0.00           1.19    0    0    1    0    2    0    0    0    0    0    0    0    0    0
+  507           1.15           0.00    2   -1    0    0   -1    0    0    0    0    0    0    0    0    0
+  508           0.00           1.15    1    0    0   -1    1    0   -3    4    0    0    0    0    0    0
+  509          -1.15           0.00    1    0    2    4    1    0    0    0    0    0    0    0    0    0
+  510           1.15           0.00    2   -1   -2    0    0    0    0    0    0    0    0    0    0    0
+  511          -1.15           0.00    2    0   -2    2    0    0    0    0    0    0    0    0    0    0
+  512           1.15           0.00    3   -1    0    0    0    0    0    0    0    0    0    0    0    0
+  513           1.15           0.00    0    0    0    0    0    0    0    3    0    0   -1    0    0    2
+  514          -0.95           0.20    0    0    0    0    0    0    6  -10    0    0    0    0    0   -2
+  515           0.24           0.91    0    0    0    0    0    0    0    0    0    3    0    0    0    1
+  516          -1.15           0.00    1    1    2   -2    0    0    0    0    0    0    0    0    0    0
+  517          -1.12           0.00    0    1    2   -2   -1    0    0    0    0    0    0    0    0    0
+  518          -1.11           0.00    1    0    0    1   -1    0    0    0    0    0    0    0    0    0
+  519          -1.11           0.00    1    2    0   -2   -1    0    0    0    0    0    0    0    0    0
+  520           0.16           0.95    0    0    0    0    1    0    0    0    0    0    1    0    0    0
+  521          -1.11           0.00    2    0    2   -4    0    0    0    0    0    0    0    0    0    0
+  522           1.11           0.00    0    0    0    0    0    0    7   -7    0    0    0    0    0    0
+  523           0.20          -0.91    0    0    0    0    0    0    1    1    0    0    0    0    0    1
+  524          -0.72          -0.40    0    0    0    0    0    0    0    0    3    0    0    0    0    2
+  525          -1.11           0.00    1    1   -2   -2    0    0    0    0    0    0    0    0    0    0
+  526          -1.11           0.00    0    0    0    0    1    0    1   -1    0    0    0    0    0    0
+  527           1.07           0.00    2   -1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+  528          -1.07           0.00    2    0    2    4    2    0    0    0    0    0    0    0    0    0
+  529           0.76          -0.32    0    0    0    0    0    0    0    1   -4    0    0    0    0   -2
+  530           0.00          -1.07    0    0    0    0    0    0    3   -6    0    0    0    0    0   -2
+  531           1.07           0.00    0    0    0    0    0    0    0    3   -3    0    0    0    0    0
+  532           1.07           0.00    0    0    2   -2    1    0   -4    4    0    0    0    0    0    0
+  533          -1.07           0.00    0    1   -2   -2    0    0    0    0    0    0    0    0    0    0
+  534           1.07           0.00    0    0    2   -3    1    0    0    0    0    0    0    0    0    0
+  535          -0.84          -0.24    0    0    0    0    1    0   -3    5    0    0    0    0    0    0
+  536           0.00          -1.03    0    0    3    0    3    0    0    0    0    0    0    0    0    0
+  537           1.03           0.00    2    1    2    2    2    0    0    0    0    0    0    0    0    0
+  538          -1.03           0.00    3    0    2   -4    2    0    0    0    0    0    0    0    0    0
+  539          -0.24           0.80    0    0    0    0    0    0    0    1    0    0   -2    0    0    0
+  540           0.20           0.84    0    0    1   -1    1    0   -1    0    0    0    0    0    0    0
+  541          -1.03           0.00    3    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  542          -1.03           0.00    0    0    0    0    3    0    0    0    0    0    0    0    0    0
+  543          -0.99           0.00    2    0    0    1    0    0    0    0    0    0    0    0    0    0
+  544           0.24           0.76    0    0    0    0    0    0    2   -1    0    0    0    0    0    0
+  545          -0.99           0.00    0    0    0    0    0    0    0    7   -8    3    0    0    0    2
+  546          -0.16           0.84    0    0    0    0    0    0    0    2    0   -2    0    0    0    1
+  547          -0.99           0.00    0    0    0    0    0    0    0    1   -1    0    0    0    0    0
+  548          -0.64           0.36    0    0    0    0    0    0    0    4   -7    0    0    0    0   -2
+  549           0.99           0.00    1   -2    0    2    0    0    0    0    0    0    0    0    0    0
+  550           0.36          -0.64    0    0    1   -1    0    0    0   -1    0   -2    5    0    0    0
+  551          -0.95           0.00    3    0    2    2    1    0    0    0    0    0    0    0    0    0
+  552          -0.95           0.00    1   -1    2    4    2    0    0    0    0    0    0    0    0    0
+  553           0.00           0.95    0    0    1   -1    0    0    0   -1    0   -1    1    0    0    0
+  554           0.64           0.32    1    0    0   -1    0    0    0   -3    4    0    0    0    0    0
+  555           0.00          -0.95    0    0    0    0    0    0    7  -10    0    0    0    0    0   -2
+  556           0.84           0.12    0    0    0    0    0    0    0    5   -8    3    0    0    0    0
+  557           0.20           0.76    0    0    0    0    0    0    6   -8    0    0    0    0    0   -1
+  558          -0.95           0.00    3    0   -2    0    0    0    0    0    0    0    0    0    0    0
+  559           0.95           0.00    1    0    4    0    2    0    0    0    0    0    0    0    0    0
+  560          -0.95           0.00    1   -1   -2    2   -2    0    0    0    0    0    0    0    0    0
+  561           0.00           0.92    1    0    0   -1   -1    0   -3    4    0    0    0    0    0    0
+  562           0.91           0.00    1    1    2    2    1    0    0    0    0    0    0    0    0    0
+  563           0.91           0.00    3    0   -2   -6   -2    0    0    0    0    0    0    0    0    0
+  564           0.40           0.52    1   -2    2   -2    1    0    0    0    0    0    0    0    0    0
+  565          -0.91           0.00    5    0    2    0    2    0    0    0    0    0    0    0    0    0
+  566          -0.56           0.36    0    0    0    0    0    0    3   -9    4    0    0    0    0   -2
+  567           0.44          -0.48    0    0    1   -1    1    0    8  -14    0    0    0    0    0    0
+  568          -0.91           0.00    2    0    0   -6    0    0    0    0    0    0    0    0    0    0
+  569          -0.91           0.00    3    1    0    0    0    0    0    0    0    0    0    0    0    0
+  570          -0.36          -0.56    0    0    1   -1    1    0    3   -6    0    0    0    0    0    0
+  571           0.91           0.00    1    0    0    2    2    0    0    0    0    0    0    0    0    0
+  572          -0.88           0.00    1    2    0   -2    1    0    0    0    0    0    0    0    0    0
+  573          -0.88           0.00    2    1    0    0   -1    0    0    0    0    0    0    0    0    0
+  574           0.60          -0.28    0    0    0    0    1    0    0    8  -15    0    0    0    0    0
+  575           0.88           0.00    0    2   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  576           0.36          -0.52    0    0    1   -1    1    0    0   -3    4    0    0    0    0    0
+  577          -0.52           0.36    0    0    0    0    0    0    3   -5    4    0    0    0    0    2
+  578           0.52           0.36    0    0    0    0    0    0    0    6    0    0    0    0    0    2
+  579           0.00           0.88    0    0    0    0    0    0    0    4   -7    0    0    0    0    0
+  580           0.56           0.32    0    0    0    0    0    0    0    8  -15    0    0    0    0   -2
+  581           0.64          -0.24    0    0    0    0    0    0    0    4   -5    0    0    0    0    0
+  582           0.88           0.00    1   -1    0   -4    0    0    0    0    0    0    0    0    0    0
+  583           0.88           0.00    1   -1    2    0    0    0    0    0    0    0    0    0    0    0
+  584           0.88           0.00    1   -1    2   -1    2    0    0    0    0    0    0    0    0    0
+  585           0.84           0.00    0    1    0   -2   -2    0    0    0    0    0    0    0    0    0
+  586          -0.68          -0.16    2    0    0   -2    1    0   -6    8    0    0    0    0    0    0
+  587           0.84           0.00    1    2    2    0    2    0    0    0    0    0    0    0    0    0
+  588           0.56           0.28    0    0    1   -1    0    0   -8   12    0    0    0    0    0    0
+  589          -0.16           0.68    0    0    0    0    0    0    5   -5    0    0    0    0    0   -1
+  590           0.64          -0.20    0    0    0    0    0    0    5   -7    0    0    0    0    0    0
+  591           0.16           0.68    0    0    0    0    0    0    1    2    0    0    0    0    0    2
+  592           0.72          -0.12    0    0    0    0    0    0    0    3    0   -3    0    0    0    0
+  593          -0.83           0.00    2    0   -2    0    2    0    0    0    0    0    0    0    0    0
+  594          -0.80           0.00    2    1    0    0    1    0    0    0    0    0    0    0    0    0
+  595           0.80           0.00    2    2    0   -2    0    0    0    0    0    0    0    0    0    0
+  596          -0.80           0.00    4    0    0   -2    0    0    0    0    0    0    0    0    0    0
+  597           0.28           0.52    0    0    0    0    0    0    0    5   -9    0    0    0    0    0
+  598           0.68          -0.12    0    0    0    0    0    0    3    0    0    0    0    0    0    2
+  599           0.00          -0.80    0    0    0    0    0    0    0    2    0    0   -1    0    0    2
+  600          -0.32           0.48    0    0    0    0    0    0    0    5   -9    0    0    0    0   -2
+  601           0.36          -0.44    0    0    0    0    0    0    0    3    0   -3    0    0    0    2
+  602          -0.36          -0.44    0    0    0    0    0    0    0    0    0    0    0    0    2    1
+  603          -0.80           0.00    0    1    2    0    0    0    0    0    0    0    0    0    0    0
+  604           0.79           0.00    1    1    0   -2   -2    0    0    0    0    0    0    0    0    0
+  605           0.74          -0.04    0    0    2   -2    3    0    0    0    0    0    0    0    0    0
+  606          -0.76           0.00    0    0    0    0    1    0   -1    1    0    0    0    0    0    0
+  607           0.00           0.76    0    0    0    0    1    0   -2    3    0    0    0    0    0    0
+  608           0.16           0.60    0    0    0    0    1    0    0    0    0   -1    0    0    0    0
+  609          -0.76           0.00    1    0    0    1    1    0    0    0    0    0    0    0    0    0
+  610          -0.76           0.00    3    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+  611           0.76           0.00    2    1   -2   -4   -1    0    0    0    0    0    0    0    0    0
+  612          -0.76           0.00    2   -1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+  613           0.76           0.00    1    0   -4    2   -1    0    0    0    0    0    0    0    0    0
+  614           0.12           0.64    0    0    1   -1    0    0    0   -1    0    2    0    0    0    0
+  615           0.76           0.00    1    0    0   -2    0    0   -3    3    0    0    0    0    0    0
+  616           0.00           0.76    0    0    1   -1    1    0    0   -9   15    0    0    0    0    0
+  617           0.76           0.00    0    0    0    0    0    0    8   -8    0    0    0    0    0    0
+  618           0.64          -0.12    0    0    0    0    0    0    7  -11    0    0    0    0    0   -2
+  619           0.16          -0.60    0    0    0    0    0    0    2    0    0    0    0    0    0    1
+  620           0.76           0.00    0    0    0    0    0    0    0    3   -1    0    0    0    0    2
+  621           0.00          -0.76    0    0    0    0    0    0    0    2    0    0    1    0    0    2
+  622           0.28          -0.48    0    0    0    0    0    0    0    5   -5    0    0    0    0    2
+  623           0.32           0.44    0    0    0    0    0    0    0    1    0    1    0    0    0    0
+  624          -0.76           0.00    1    1    2    0    0    0    0    0    0    0    0    0    0    0
+  625           0.72           0.00    4    0    2   -2    1    0    0    0    0    0    0    0    0    0
+  626           0.72           0.00    1   -1   -2    0    0    0    0    0    0    0    0    0    0    0
+  627           0.48          -0.24    0    0    0    0    0    0    0    2    0   -2    5    0    0    2
+  628          -0.72           0.00    0    1    2   -4    1    0    0    0    0    0    0    0    0    0
+  629           0.72           0.00    0    0    1   -1    1    0   -2    2    0    0    0    0    0    0
+  630          -0.72           0.00    0    0    2    1    0    0    0    0    0    0    0    0    0    0
+  631          -0.72           0.00    3    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+  632          -0.71           0.00    1   -1    0    0    2    0    0    0    0    0    0    0    0    0
+  633          -0.68           0.00    1    0   -2   -2    1    0    0    0    0    0    0    0    0    0
+  634          -0.68           0.00    0    2    0   -2    1    0    0    0    0    0    0    0    0    0
+  635           0.68           0.00    0    1   -4    2   -2    0    0    0    0    0    0    0    0    0
+  636           0.68           0.00    0    1    2    4    2    0    0    0    0    0    0    0    0    0
+  637           0.68           0.00    1    0   -2    4   -1    0    0    0    0    0    0    0    0    0
+  638          -0.68           0.00    0    2    2   -2    0    0    0    0    0    0    0    0    0    0
+  639           0.56          -0.12    0    0    0    0    0    0    5   -3    0    0    0    0    0    2
+  640          -0.68           0.00    0    0    0    0    0    0    0    3   -5    0    0    0    0   -2
+  641          -0.68           0.00    0    0    0    0    0    0    0    2    0   -4    0    0    0   -2
+  642           0.20           0.48    0    0    0    0    0    0    0    3    0    2   -5    0    0    2
+  643          -0.44          -0.24    0    0    0    0    0    0    0    2    0    2   -5    0    0    2
+  644          -0.68           0.00    1    1   -2    0    0    0    0    0    0    0    0    0    0    0
+  645           0.64           0.00    2    0    0   -2    1    0   -3    3    0    0    0    0    0    0
+  646           0.64           0.00    3    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+  647          -0.64           0.00    2   -1    2    2    1    0    0    0    0    0    0    0    0    0
+  648           0.64           0.00    0    1   -2   -4   -1    0    0    0    0    0    0    0    0    0
+  649          -0.64           0.00    1    0   -2   -3   -1    0    0    0    0    0    0    0    0    0
+  650          -0.12           0.52    0    0    0    0    0    0    6   -6    0    0    0    0    0   -1
+  651          -0.12          -0.52    0    0    0    0    0    0    2   -2    0    0    0    0    0    1
+  652          -0.16          -0.48    0    0    0    0    0    0    0    3    0   -2    0    0    0    0
+  653          -0.20          -0.44    0    0    0    0    0    0    2   -3    0    0    0    0    0   -2
+  654          -0.44           0.20    0    0    0    0    0    0    0   11    0    0    0    0    0    2
+  655          -0.44           0.20    0    0    0    0    0    0    0    6  -15    0    0    0    0   -2
+  656           0.24          -0.40    0    0    0    0    0    0    0    4   -8    0    0    0    0   -2
+  657          -0.20          -0.44    0    0    0    0    0    0    0    3    0    1    0    0    0    2
+  658          -0.64           0.00    1    0    0   -6    0    0    0    0    0    0    0    0    0    0
+  659           0.40          -0.24    0    0    0    0    1    0    3   -7    4    0    0    0    0    0
+  660          -0.64           0.00    1    0   -2   -4    0    0    0    0    0    0    0    0    0    0
+  661           0.64           0.00    0    1    0   -4   -1    0    0    0    0    0    0    0    0    0
+  662          -0.63           0.00    2    0   -2    2   -2    0    0    0    0    0    0    0    0    0
+  663          -0.60           0.00    0    1   -2    1   -1    0    0    0    0    0    0    0    0    0
+  664           0.00           0.60    0    0    2   -2    2    0   -8   11    0    0    0    0    0    0
+  665          -0.60           0.00    2    0   -2   -3   -2    0    0    0    0    0    0    0    0    0
+  666          -0.60           0.00    4    0    2    2    2    0    0    0    0    0    0    0    0    0
+  667           0.60           0.00    0    0    0    0    0    0    0    2    0    0   -2    0    0    0
+  668           0.00           0.60    0    0    0    0    0    0    0    0    0    0    3    0    0    2
+  669           0.24          -0.36    2    0    0   -2    0    0    0   -2    0    4   -3    0    0    0
+  670           0.12           0.48    0    0    0    0    0    0    7   -9    0    0    0    0    0   -1
+  671           0.48          -0.12    0    0    0    0    0    0    4   -7    0    0    0    0    0   -1
+  672           0.12           0.48    0    0    0    0    0    0    3   -3    0    0    0    0    0    1
+  673           0.24          -0.36    0    0    0    0    0    0    0    6   -6    0    0    0    0    2
+  674           0.36           0.24    0    0    0    0    0    0    0    6  -11    0    0    0    0    0
+  675           0.12           0.48    0    0    0    0    0    0    0    5    0   -2    0    0    0    2
+  676           0.44           0.16    0    0    0    0    0    0    0    2    0   -4    0    0    0    0
+  677          -0.60           0.00    0    0    0    3    0    0    0    0    0    0    0    0    0    0
+  678          -0.60           0.00    2    0    0   -2    0    0    0   -2    0    3   -1    0    0    0
+  679           0.60           0.00    2   -1    0   -4    0    0    0    0    0    0    0    0    0    0
+  680           0.00           0.60    0    0    1   -1    2    0    0   -2    2    0    0    0    0    0
+  681           0.59           0.00    0    0    0    0    1    0    0    1    0   -1    0    0    0    0
+  682          -0.56           0.00    3    0    0   -4    1    0    0    0    0    0    0    0    0    0
+  683          -0.44          -0.12    2    0    0   -2   -1    0   -6    8    0    0    0    0    0    0
+  684           0.56           0.00    1    2   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  685           0.00           0.56    0    0    1   -1    1    0    0   -1    0   -1    1    0    0    0
+  686          -0.56           0.00    3    1    0   -4    0    0    0    0    0    0    0    0    0    0
+  687          -0.56           0.00    3    0    0   -6    0    0    0    0    0    0    0    0    0    0
+  688           0.56           0.00    0    0    0    0    0    0    0    6    0    0    0    0    0    0
+  689          -0.56           0.00    0    0    0    0    0    0    0    1    0    0    1    0    0    2
+  690           0.16           0.40    0    0    0    0    0    1    0   -4    0    0    0    0    0   -2
+  691           0.44          -0.12    0    0    0    0    0    0    4   -4    0    0    0    0    0    2
+  692           0.20          -0.36    0    0    0    0    0    0    0    1   -5    0    0    0    0   -2
+  693          -0.36          -0.20    0    0    0    0    1    0   -3    7   -4    0    0    0    0    0
+  694          -0.56           0.00    0    0    4   -4    1    0    0    0    0    0    0    0    0    0
+  695           0.55           0.00    1    1    0   -2    2    0    0    0    0    0    0    0    0    0
+  696           0.52           0.00    1    0    0   -4   -2    0    0    0    0    0    0    0    0    0
+  697          -0.52           0.00    1    1    0   -4    1    0    0    0    0    0    0    0    0    0
+  698           0.52           0.00    0    0    0    0    1    0    3   -5    0    2    0    0    0    0
+  699           0.52           0.00    0    1    0   -1    0    0    0    0    0    0    0    0    0    0
+  700           0.16           0.36    0    0    1   -1    0    0    0   -1    0    0    2    0    0    0
+  701          -0.52           0.00    0    0    2   -2    0    0   -3    3    0    0    0    0    0    0
+  702          -0.52           0.00    1    0    0   -2    0    0    0   -2    0    3    0    0    0    0
+  703          -0.52           0.00    1    0   -2   -2   -2    0    0   -2    0    2    0    0    0    0
+  704          -0.52           0.00    0    0    2    6    2    0    0    0    0    0    0    0    0    0
+  705           0.00          -0.52    0    0    1   -1    1    0    2   -4    0   -3    0    0    0    0
+  706           0.52           0.00    0    0    0    0    0    0    9   -9    0    0    0    0    0    0
+  707          -0.52           0.00    0    0    0    0    0    0    0    1    1    0    0    0    0    2
+  708           0.12           0.40    0    0    0    0    0    0    5   -6    0    0    0    0    0    2
+  709           0.52           0.00    1    0   -4    0    0    0    0    0    0    0    0    0    0    0
+  710          -0.52           0.00    2    0   -2   -4    0    0    0    0    0    0    0    0    0    0
+  711           0.00          -0.52    1    0    1    0    1    0    0    0    0    0    0    0    0    0
+  712           0.52           0.00    1    1    0    0    2    0    0    0    0    0    0    0    0    0
+  713           0.52           0.00    0    0    0    1    2    0    0    0    0    0    0    0    0    0
+  714          -0.51           0.00    1    0    0    2   -2    0    0    0    0    0    0    0    0    0
+  715          -0.51           0.00    1    0    2    0    3    0    0    0    0    0    0    0    0    0
+  716           0.48           0.00    0    1    0    2    2    0    0    0    0    0    0    0    0    0
+  717           0.48           0.00    0    0    2    2   -1    0    0    0    0    0    0    0    0    0
+  718          -0.16           0.32    0    0    0    0    1    0    0    2   -4    0    0    0    0    0
+  719          -0.48           0.00    1   -2    2   -2    2    0    0    0    0    0    0    0    0    0
+  720          -0.48           0.00    0    1   -2   -1   -2    0    0    0    0    0    0    0    0    0
+  721           0.48           0.00    3   -1    2   -2    2    0    0    0    0    0    0    0    0    0
+  722           0.48           0.00    4    0    0   -4    0    0    0    0    0    0    0    0    0    0
+  723          -0.48           0.00    3   -1    2    2    2    0    0    0    0    0    0    0    0    0
+  724          -0.12          -0.36    0    0    1   -1    1    0    0   -1    0    3    0    0    0    0
+  725          -0.32           0.16    0    0    1   -1    1    0    0   -1    0    0    3    0    0    0
+  726           0.32          -0.16    0    0    0    0    0    0    4   -2    0    0    0    0    0    2
+  727          -0.12          -0.36    0    0    0    0    0    0    3   -5    0    0    0    0    0    1
+  728           0.16           0.32    0    0    0    0    0    0    0    7  -13    0    0    0    0   -2
+  729           0.20          -0.28    0    0    0    0    0    0    0    5   -7    0    0    0    0    0
+  730          -0.20          -0.28    0    0    0    0    0    0    0    1    0    3    0    0    0    2
+  731          -0.36           0.12    0    0    0    0    0    0    0    0    0    4    0    0    0    2
+  732          -0.48           0.00    0    0    0    0    0    0    0    0    0    2   -5    0    0    2
+  733           0.32          -0.16    0    0    0    0    0    0    0    0    0    0    3    0    0    1
+  734           0.48           0.00    1   -1    0    4    0    0    0    0    0    0    0    0    0    0
+  735          -0.48           0.00    2    1    0    2    0    0    0    0    0    0    0    0    0    0
+  736          -0.48           0.00    2    0    0   -2   -1    0    0   -2    0    0    5    0    0    0
+  737          -0.48           0.00    3    0    0    2    1    0    0    0    0    0    0    0    0    0
+  738           0.00          -0.48    1    0    1   -2    1    0    0    0    0    0    0    0    0    0
+  739           0.48           0.00    1    1    0   -4   -1    0    0    0    0    0    0    0    0    0
+  740          -0.48           0.00    0    0    2   -2    2    0   -3    3    0    0    0    0    0    0
+  741          -0.48           0.00    1    0    0   -1    2    0    0    0    0    0    0    0    0    0
+  742           0.00           0.48    0    0    2   -2    2    0   -5    6    0    0    0    0    0    0
+  743           0.44           0.00    0    0    0    0    1    0    0   -1    0    1    0    0    0    0
+  744          -0.32          -0.12    0    0    1   -1   -1    0    0    0   -2    0    0    0    0    0
+  745          -0.44           0.00    0    1   -2    0    0    0    0    0    0    0    0    0    0    0
+  746           0.20          -0.24    0    0    0    0    0    0    0    9  -17    0    0    0    0    0
+  747           0.44           0.00    3   -1   -2   -1   -2    0    0    0    0    0    0    0    0    0
+  748          -0.44           0.00    1   -1    0   -3    0    0    0    0    0    0    0    0    0    0
+  749           0.44           0.00    0    0    2   -2    1    0   -2    2    0    0    0    0    0    0
+  750           0.20          -0.24    0    0    0    0    0    0    8  -13    0    0    0    0    0    1
+  751           0.12           0.32    0    0    0    0    0    0    5  -10    0    0    0    0    0   -2
+  752          -0.20           0.24    0    0    0    0    0    0    1    0    0    0    0    0    0    2
+  753           0.32          -0.12    0    0    0    0    0    0    1   -3    0    0    0    0    0    0
+  754           0.00           0.44    0    0    0    0    0    0    0    6  -11    0    0    0    0   -2
+  755           0.00           0.44    0    0    0    0    0    0    0    5   -8    0    0    0    0    0
+  756           0.44           0.00    0    0    0    0    0    0    0    1   -3    0    0    0    0   -2
+  757          -0.44           0.00    1    2    0   -4    0    0    0    0    0    0    0    0    0    0
+  758          -0.44           0.00    0    1    0    4    0    0    0    0    0    0    0    0    0    0
+  759          -0.44           0.00    3    0    2   -2    0    0    0    0    0    0    0    0    0    0
+  760           0.44           0.00    1   -1    2   -4    1    0    0    0    0    0    0    0    0    0
+  761           0.44           0.00    2    0    2    2    0    0    0    0    0    0    0    0    0    0
+  762           0.40           0.00    2    0    2    0   -1    0    0    0    0    0    0    0    0    0
+  763          -0.40           0.00    2    1    0   -4   -1    0    0    0    0    0    0    0    0    0
+  764          -0.40           0.00    2    1    0   -4    1    0    0    0    0    0    0    0    0    0
+  765          -0.40           0.00    1    0    4   -4    2    0    0    0    0    0    0    0    0    0
+  766           0.40           0.00    2    0   -4    0   -1    0    0    0    0    0    0    0    0    0
+  767           0.24           0.16    2    0    0   -2   -1    0    0   -5    6    0    0    0    0    0
+  768           0.00          -0.40    0    0    3    0    2    0    0    0    0    0    0    0    0    0
+  769           0.12           0.28    2    0   -1   -1   -1    0    0   -1    0    3    0    0    0    0
+  770           0.40           0.00    1    2   -2   -4   -2    0    0    0    0    0    0    0    0    0
+  771          -0.40           0.00    0    0    4   -1    2    0    0    0    0    0    0    0    0    0
+  772           0.40           0.00    0    0    0    0    0    0    0    7  -13    0    0    0    0    0
+  773           0.40           0.00    5    0    2   -2    2    0    0    0    0    0    0    0    0    0
+  774           0.00          -0.40    0    0    0    0    0    0    9  -12    0    0    0    0    0   -2
+  775          -0.40           0.00    0    0    0    0    0    0    5   -9    0    0    0    0    0   -2
+  776           0.00          -0.40    0    0    0    0    0    0    4   -4    0    0    0    0    0    1
+  777           0.00          -0.40    0    0    0    0    0    0    3   -1    0    0    0    0    0    1
+  778           0.20          -0.20    0    0    0    0    0    0    2   -4    0    0    0    0    0    0
+  779          -0.40           0.00    0    0    0    0    0    0    1   -2    0    0    0    0    0    1
+  780          -0.40           0.00    0    0    0    0    0    0    0    5   -3    0    0    0    0    2
+  781          -0.12          -0.28    0    0    0    0    0    0    0    4   -8    1    5    0    0   -2
+  782           0.40           0.00    0    0    0    0    0    0    3   -5    0    2    0    0    0    0
+  783           0.40           0.00    1    1   -2    2    0    0    0    0    0    0    0    0    0    0
+  784           0.40           0.00    2    0    0    4    0    0    0    0    0    0    0    0    0    0
+  785           0.40           0.00    0    0    0    3    1    0    0    0    0    0    0    0    0    0
+  786           0.40           0.00    4    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  787           0.00           0.40    0    0    1   -1    2    0    0   -1    0    2    0    0    0    0
+  788          -0.20          -0.16    0    0    0    0    2    0    0   -1    2    0    0    0    0    0
+  789           0.36           0.00    1    0    0   -3    1    0    0    0    0    0    0    0    0    0
+  790           0.36           0.00    1   -2    0    0    1    0    0    0    0    0    0    0    0    0
+  791           0.24          -0.12    0    2   -2    0   -1    0    0    0    0    0    0    0    0    0
+  792           0.20          -0.16    2    0   -1   -1   -1    0    0    3   -7    0    0    0    0    0
+  793           0.00           0.36    0    0    2    0    2    0    0   -4    8   -3    0    0    0    0
+  794           0.00           0.36    0    0    2    0    2    0    0    4   -8    3    0    0    0    0
+  795          -0.36           0.00    2    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  796           0.12           0.24    1    0    1    0    0    0    0    0    0    0    0    0    0    0
+  797          -0.36           0.00    2   -2    2    0    2    0    0    0    0    0    0    0    0    0
+  798          -0.36           0.00    0    3    0   -2    0    0    0    0    0    0    0    0    0    0
+  799          -0.36           0.00    2   -1    0   -1    0    0    0    0    0    0    0    0    0    0
+  800          -0.36           0.00    1    3    0   -2    0    0    0    0    0    0    0    0    0    0
+  801           0.36           0.00    1   -1   -2   -3   -2    0    0    0    0    0    0    0    0    0
+  802           0.00           0.36    0    0    1   -1    1    0   -2    3    0    0    0    0    0    0
+  803           0.00           0.36    0    0    0    0    0    0    7   -7    0    0    0    0    0   -1
+  804           0.00           0.36    0    0    0    0    0    0    6   -7    0    0    0    0    0    0
+  805          -0.36           0.00    0    0    0    0    0    0    6   -9    0    0    0    0    0   -1
+  806           0.00           0.36    0    0    0    0    0    0    4   -3    0    0    0    0    0    2
+  807           0.12          -0.24    0    0    0    0    0    0    1   -2    0    0    0    0    0   -2
+  808          -0.24           0.12    0    0    0    0    0    0    0    6   -5    0    0    0    0    2
+  809          -0.36           0.00    0    0    0    0    0    0    0    5    0   -3    0    0    0    2
+  810           0.00           0.36    0    0    0    0    0    0    0    3   -2    0    0    0    0    0
+  811           0.36           0.00    0    0    0    0    0    0    0    3   -6    0    0    0    0   -1
+  812           0.24          -0.12    0    0    0    0    0    0    0    2   -5    0    0    0    0   -2
+  813           0.00          -0.36    0    0    1   -1    1    0    0    1    0    0    0    0    0    0
+  814          -0.36           0.00    1   -2   -2    0   -2    0    0    0    0    0    0    0    0    0
+  815           0.36           0.00    2    0    0    2    2    0    0    0    0    0    0    0    0    0
+  816           0.36           0.00    0    1    0   -2    2    0    0    0    0    0    0    0    0    0
+  817          -0.36           0.00    0    0    2    0   -2    0    0    0    0    0    0    0    0    0
+  818           0.36           0.00    0    0    2   -2   -2    0    0    0    0    0    0    0    0    0
+  819          -0.13           0.22    0    0    1   -1    2    0    0   -1    0   -2    5    0    0    0
+  820          -0.32           0.00    0    0    0    0    1    0    3   -5    0    0    0    0    0    0
+  821          -0.32           0.00    1    1    0    2   -1    0    0    0    0    0    0    0    0    0
+  822           0.32           0.00    4    0    0    0   -1    0    0    0    0    0    0    0    0    0
+  823          -0.20          -0.12    0    0    0    0    1    0    0   -8   15    0    0    0    0    0
+  824           0.32           0.00    0    2    2    0    1    0    0    0    0    0    0    0    0    0
+  825           0.12           0.20    2    0    0   -2    1    0    0   -6    8    0    0    0    0    0
+  826          -0.32           0.00    3   -1    2    0    1    0    0    0    0    0    0    0    0    0
+  827           0.32           0.00    0    0    2    0    2    0    1   -1    0    0    0    0    0    0
+  828          -0.32           0.00    0    0    2    0    2    0   -1    1    0    0    0    0    0    0
+  829          -0.32           0.00    2    0    2   -1    1    0    0    0    0    0    0    0    0    0
+  830           0.00          -0.32    2    0   -1   -1   -2    0    0   -1    0    2    0    0    0    0
+  831           0.32           0.00    1    2    2   -2    1    0    0    0    0    0    0    0    0    0
+  832           0.32           0.00    2    2    2   -2    2    0    0    0    0    0    0    0    0    0
+  833           0.12          -0.20    0    0    2   -2    0    0    0   -9   13    0    0    0    0    0
+  834          -0.32           0.00    3    0    2   -1    2    0    0    0    0    0    0    0    0    0
+  835           0.00          -0.32    1    0    0   -2    0    0   20  -21    0    0    0    0    0    0
+  836           0.32           0.00    0    0    2   -2    1    0    0   -2    0    0    2    0    0    0
+  837           0.00           0.32    0    0    2   -2    1    0    0   -8   11    0    0    0    0    0
+  838           0.00          -0.32    0    0    1   -1    1    0    0   -1    0    0    0    2    0    0
+  839           0.00          -0.32    0    0    1   -1    1    0    0   -1    0   -1    2    0    0    0
+  840           0.32           0.00    0    0    0    0    0    0    8  -12    0    0    0    0    0    0
+  841          -0.32           0.00    0    0    0    0    0    0    5   -5    0    0    0    0    0    2
+  842           0.00           0.32    0    0    0    0    0    0    5   -6    0    0    0    0    0    0
+  843           0.32           0.00    0    0    0    0    0    0    2   -6    0    0    0    0    0   -2
+  844           0.00           0.32    0    0    0    0    0    0    0    8  -15    0    0    0    0   -1
+  845           0.00          -0.32    0    0    0    0    0    0    0    5   -2    0    0    0    0    2
+  846           0.32           0.00    0    0    0    0    0    0    0    4   -4    0    0    0    0    0
+  847          -0.16           0.16    0    0    0    0    0    0    0    2    2    0    0    0    0    2
+  848          -0.16           0.16    0    0    0    0    0    0    0    1    0   -4    0    0    0    0
+  849           0.00           0.32    0    0    0    0    0    0    0    0    0    0    1    0    0    2
+  850           0.20           0.12    0    0    1   -1    1    0    0   -1    0   -2    4    0    0    0
+  851           0.20           0.12    0    0    0    0    0    1    0   -4    0    0    0    0    0    0
+  852          -0.20           0.12    0    0    0    0    0    0    0    5   -8    0    0    0    0   -2
+  853           0.12           0.20    0    0    0    0    0    0    0    4   -8    0    0    0    0    0
+  854           0.12          -0.20    0    0    0    0    0    0    0    2   -6    0    0    0    0   -2
+  855           0.00           0.32    0    0    2   -2    1   -1    0    2    0    0    0    0    0    0
+  856          -0.32           0.00    0    0    4   -2    0    0    0    0    0    0    0    0    0    0
+  857           0.32           0.00    0    0    0    1   -2    0    0    0    0    0    0    0    0    0
+  858           0.28           0.00    2    0   -4    2   -2    0    0    0    0    0    0    0    0    0
+  859          -0.28           0.00    0    0    0    4    2    0    0    0    0    0    0    0    0    0
+  860           0.28           0.00    1    0    0    4   -1    0    0    0    0    0    0    0    0    0
+  861           0.28           0.00    1   -2    0   -2   -1    0    0    0    0    0    0    0    0    0
+  862           0.28           0.00    1    1    0   -1    1    0    0    0    0    0    0    0    0    0
+  863           0.16           0.12    1    0    0   -1    1    0    0   -3    4    0    0    0    0    0
+  864           0.28           0.00    3    1    2    0    1    0    0    0    0    0    0    0    0    0
+  865          -0.28           0.00    1    1    2    1    1    0    0    0    0    0    0    0    0    0
+  866          -0.12          -0.16    0    0    0    0    1    0    0   -9   17    0    0    0    0    0
+  867           0.28           0.00    1    1    4   -2    2    0    0    0    0    0    0    0    0    0
+  868          -0.28           0.00    4    0    2   -4    2    0    0    0    0    0    0    0    0    0
+  869          -0.28           0.00    0    2    0    2    0    0    0    0    0    0    0    0    0    0
+  870           0.28           0.00    1    0    2   -3    0    0    0    0    0    0    0    0    0    0
+  871           0.28           0.00    3    0   -2   -2    0    0    0    0    0    0    0    0    0    0
+  872           0.28           0.00    2   -2    0    0    0    0    0    0    0    0    0    0    0    0
+  873           0.28           0.00    1    1    0   -3    0    0    0    0    0    0    0    0    0    0
+  874           0.28           0.00    1    0    2    3    2    0    0    0    0    0    0    0    0    0
+  875           0.28           0.00    1    0    0   -2    0    0    0    1    0   -1    0    0    0    0
+  876          -0.28           0.00    1    0   -2   -2   -2    0   -3    3    0    0    0    0    0    0
+  877           0.28           0.00    0    0    2   -2    1    0    0   -2    0    3    0    0    0    0
+  878           0.00           0.28    0    0    0    0    0    0    8   -8    0    0    0    0    0   -1
+  879           0.00           0.28    0    0    0    0    0    0    8  -10    0    0    0    0    0   -1
+  880           0.00          -0.28    0    0    0    0    0    0    4   -2    0    0    0    0    0    1
+  881          -0.28           0.00    0    0    0    0    0    0    3   -4    0    0    0    0    0   -1
+  882           0.28           0.00    0    0    0    0    0    0    3   -6    0    0    0    0    0   -1
+  883          -0.12          -0.16    0    0    0    0    0    0    1   -4    0    0    0    0    0   -2
+  884           0.00           0.28    0    0    0    0    0    0    0    6    0    0    0    0    0    1
+  885           0.00          -0.28    0    0    0    0    0    0    0    6   -7    0    0    0    0    2
+  886           0.12          -0.16    0    0    0    0    0    0    0    4    0    0    0    0    0    0
+  887          -0.28           0.00    0    0    0    0    0    0    0    4    0    0   -2    0    0    2
+  888           0.00          -0.28    0    0    0    0    0    0    0    3    0    0   -2    0    0    2
+  889           0.00           0.28    0    0    0    0    0    0    0    1    0   -1    0    0    0    1
+  890           0.00          -0.28    0    0    0    0    0    0    0    1   -6    0    0    0    0   -2
+  891           0.28           0.00    0    0    0    0    0    0    0    0    0    4   -5    0    0    2
+  892          -0.28           0.00    0    0    0    0    0    0    0    0    0    0    0    2    0    2
+  893          -0.28           0.00    0    0    0    0    0    0    3   -7    4    0    0    0    0    0
+  894           0.28           0.00    1   -1    2   -2    0    0    0    0    0    0    0    0    0    0
+  895           0.28           0.00    1    1    2   -4    0    0    0    0    0    0    0    0    0    0
+  896           0.12          -0.16    0    0    1   -1    1    0    0   -1    0    0   -2    0    0    0
+  897           0.28           0.00    0    0    2    4    0    0    0    0    0    0    0    0    0    0
+  898           0.28           0.00    2   -1   -2    0   -2    0    0    0    0    0    0    0    0    0
+  899          -0.28           0.00    0    0    1   -1    2    0    0    0   -2    0    0    0    0    0
+  900           0.00          -0.28    0    0    0    0    2    0    0    4   -8    3    0    0    0    0
+  901           0.00          -0.28    0    0    0    0    2    0    0   -4    8   -3    0    0    0    0
+  902           0.28           0.00    1    1    2   -4    2    0    0    0    0    0    0    0    0    0
+  903           0.00           0.24    0    0    2   -2   -1    0   -5    6    0    0    0    0    0    0
+  904           0.24           0.00    1   -2    0   -2    1    0    0    0    0    0    0    0    0    0
+  905          -0.24           0.00    0    1    0   -4    1    0    0    0    0    0    0    0    0    0
+  906          -0.24           0.00    1   -2    2    0    1    0    0    0    0    0    0    0    0    0
+  907           0.24           0.00    0    0    2    0    2    0    0   -1    0    1    0    0    0    0
+  908          -0.24           0.00    0    0    2    0    2    0    0    1    0   -1    0    0    0    0
+  909          -0.24           0.00    2    0   -4   -2   -1    0    0    0    0    0    0    0    0    0
+  910           0.24           0.00    2    0    2    1    1    0    0    0    0    0    0    0    0    0
+  911           0.24           0.00    2    0   -2   -6   -1    0    0    0    0    0    0    0    0    0
+  912           0.00          -0.24    2    0   -1   -1   -1    0    0   -1    0    2    0    0    0    0
+  913          -0.24           0.00    4   -1    2    0    2    0    0    0    0    0    0    0    0    0
+  914           0.24           0.00    5    0    0    0    0    0    0    0    0    0    0    0    0    0
+  915          -0.24           0.00    3    0    0   -3    0    0    0    0    0    0    0    0    0    0
+  916          -0.24           0.00    2    2    0   -4    0    0    0    0    0    0    0    0    0    0
+  917           0.24           0.00    2    2   -2   -4   -2    0    0    0    0    0    0    0    0    0
+  918          -0.24           0.00    2    1    2    1    2    0    0    0    0    0    0    0    0    0
+  919          -0.24           0.00    1    0    2   -2    2    0    0   -2    0    2    0    0    0    0
+  920          -0.24           0.00    1    0    0    0    0    0    0   -2    0    2    0    0    0    0
+  921           0.24           0.00    1    0    0   -2    0    0    2   -2    0    0    0    0    0    0
+  922           0.00          -0.24    1    0   -1    1   -1    0  -18   17    0    0    0    0    0    0
+  923           0.24           0.00    0    2   -2   -4   -2    0    0    0    0    0    0    0    0    0
+  924          -0.24           0.00    0    1    2    3    2    0    0    0    0    0    0    0    0    0
+  925           0.24           0.00    0    0    0    0    0    0    8  -12    0    0    0    0    0   -2
+  926           0.24           0.00    0    0    0    0    0    0    8  -16    0    0    0    0    0   -2
+  927           0.00           0.24    0    0    0    0    0    0    7   -8    0    0    0    0    0    0
+  928           0.12          -0.12    0    0    0    0    0    0    2   -3    0    0    0    0    0    1
+  929           0.00          -0.24    0    0    0    0    0    0    0    5   -6    0    0    0    0    2
+  930          -0.24           0.00    0    0    0    0    0    0    0    4   -6    0    0    0    0   -2
+  931           0.00           0.24    0    0    0    0    0    0    0    4   -8    1    5    0    0    2
+  932          -0.24           0.00    0    0    0    0    0    0    0    2    0   -2    0    0    0    2
+  933           0.00          -0.24    0    0    0    0    0    0    0    2   -7    0    0    0    0   -2
+  934           0.24           0.00    0    0    0    0    0    0    0    0    2    0    0    0    0    0
+  935          -0.24           0.00    0    0    0    0    0    0    0    0    0    0    5    0    0    2
+  936          -0.24           0.00    0    0    0    0    0    0    0    0    0    0    0    0    2    2
+  937           0.24           0.00    0    1    0    3    0    0    0    0    0    0    0    0    0    0
+  938           0.24           0.00    0    2    2    2    2    0    0    0    0    0    0    0    0    0
+  939           0.24           0.00    2   -1    2   -1    2    0    0    0    0    0    0    0    0    0
+  940           0.24           0.00    1   -1    2    2    0    0    0    0    0    0    0    0    0    0
+  941           0.24           0.00    2    1    2   -4    1    0    0    0    0    0    0    0    0    0
+  942          -0.24           0.00    2    0    0   -2   -2    0   -3    3    0    0    0    0    0    0
+  943          -0.24           0.00    1   -1    0   -4   -1    0    0    0    0    0    0    0    0    0
+  944           0.00           0.24    0    0    1   -1    2    0    0   -1    0    1    0    0    0    0
+  945           0.00          -0.24    0    0    1   -1    2    0    0   -1    0   -1    0    0    0    0
+  946           0.24           0.00    0    0    0    0    1    0    2   -2    0    0    0    0    0    0
+  947           0.00           0.20    1    0   -1    0    1    0    0    0    0    0    0    0    0    0
+  948           0.20           0.00    2   -2    0   -2    1    0    0    0    0    0    0    0    0    0
+  949          -0.20           0.00    0    0    1   -1    2    0    0   -1    0    0    1    0    0    0
+  950           0.20           0.00    2    0    0   -2   -1    0   -3    3    0    0    0    0    0    0
+  951           0.20           0.00    1   -2    0    0   -1    0    0    0    0    0    0    0    0    0
+  952           0.00           0.20    0    0    0    0    1    0    0    0    0    0   -1    0    0    0
+  953          -0.20           0.00    1    0   -2    1    1    0    0    0    0    0    0    0    0    0
+  954           0.20           0.00    2    0    0   -3   -1    0    0    0    0    0    0    0    0    0
+  955           0.20           0.00    2    1   -2    0    1    0    0    0    0    0    0    0    0    0
+  956           0.20           0.00    2    0    0   -1    1    0    0    0    0    0    0    0    0    0
+  957           0.20           0.00    2   -1    2   -2    1    0    0    0    0    0    0    0    0    0
+  958           0.20           0.00    1   -1   -4    2   -2    0    0    0    0    0    0    0    0    0
+  959          -0.20           0.00    1   -2   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  960           0.20           0.00    2    0    4   -2    1    0    0    0    0    0    0    0    0    0
+  961           0.20           0.00    0    0    2    3    1    0    0    0    0    0    0    0    0    0
+  962           0.20           0.00    0    1    4   -2    1    0    0    0    0    0    0    0    0    0
+  963           0.20           0.00    1    0   -2    0   -2    0  -10    3    0    0    0    0    0    0
+  964           0.00           0.20    1    0    1   -2    0    0    0    0    0    0    0    0    0    0
+  965           0.20           0.00    1   -1    2    1    2    0    0    0    0    0    0    0    0    0
+  966           0.20           0.00    4    1    2    0    2    0    0    0    0    0    0    0    0    0
+  967           0.20           0.00    0    0    2   -2    1    0    0   -1    0    1    0    0    0    0
+  968           0.20           0.00    1    0    0   -1    0    0    0   -2    2    0    0    0    0    0
+  969          -0.20           0.00    0    0    2   -2    0    0    0   -2    0    2    0    0    0    0
+  970           0.00          -0.20    1    0    0    0    0    0    0    4   -8    3    0    0    0    0
+  971          -0.20           0.00    4   -1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+  972           0.20           0.00    2    1   -2   -6   -2    0    0    0    0    0    0    0    0    0
+  973          -0.20           0.00    2    0    0   -2    0    0    0   -4    8   -3    0    0    0    0
+  974           0.20           0.00    2    0    0   -2    0    0   -2    2    0    0    0    0    0    0
+  975           0.20           0.00    2    0    0   -2   -1    0    0   -2    0    4   -5    0    0    0
+  976           0.00          -0.20    2    0   -1   -1   -1    0    0   -1    0    0    0    0    0    0
+  977          -0.20           0.00    1    1   -2   -3   -2    0    0    0    0    0    0    0    0    0
+  978           0.00          -0.20    1    0    3    0    3    0    0    0    0    0    0    0    0    0
+  979           0.00           0.20    1    0    1   -1    1    0    0   -1    0    0    0    0    0    0
+  980           0.00          -0.20    1    0    0    0    0    0    0   -4    8   -3    0    0    0    0
+  981           0.20           0.00    1    0    0    0    0    0   -1    1    0    0    0    0    0    0
+  982           0.00           0.20    1    0    0   -2    0    0   17  -16    0   -2    0    0    0    0
+  983          -0.20           0.00    1    0   -1   -1   -1    0   20  -20    0    0    0    0    0    0
+  984           0.20           0.00    1    0   -2   -2   -2    0    0   -2    0    3    0    0    0    0
+  985           0.20           0.00    0    3   -2   -2   -2    0    0    0    0    0    0    0    0    0
+  986           0.00           0.20    0    0    1   -1    1    0    1   -2    0    0    0    0    0    0
+  987           0.00           0.20    0    0    1   -1    1    0   -2    1    0    0    0    0    0    0
+  988          -0.20           0.00    0    0    1   -1    0    0    0    0    0    0    0    0    0    0
+  989           0.00           0.20    0    0    0    0    0    0    9   -9    0    0    0    0    0   -1
+  990           0.00           0.20    0    0    0    0    0    0    9  -11    0    0    0    0    0   -1
+  991           0.00           0.20    0    0    0    0    0    0    6  -10    0    0    0    0    0   -1
+  992           0.00          -0.20    0    0    0    0    0    0    5   -3    0    0    0    0    0    1
+  993          -0.20           0.00    0    0    0    0    0    0    4   -5    0    0    0    0    0   -1
+  994           0.00          -0.20    0    0    0    0    0    0    3   -4    0    0    0    0    0   -2
+  995           0.00          -0.20    0    0    0    0    0    0    0    6   -9    0    0    0    0    0
+  996           0.00          -0.20    0    0    0    0    0    0    0    5  -10    0    0    0    0   -2
+  997          -0.20           0.00    0    0    0    0    0    0    0    4    0   -4    0    0    0    2
+  998           0.20           0.00    0    0    0    0    0    0    0    3    0   -4    0    0    0    0
+  999          -0.20           0.00    0    0    0    0    0    0    0    2    0    0    0    0    0    0
+ 1000          -0.20           0.00    0    0    0    0    0    0    0    2    0   -5    0    0    0   -2
+ 1001           0.00           0.20    0    0    0    0    0    0    0    1    0   -2    5    0    0    2
+ 1002           0.20           0.00    0    0    0    0    0    0    0    1    0   -2    0    0    0   -2
+ 1003           0.00          -0.20    0    0    0    0    0    0    0    1    0   -3    0    0    0   -1
+ 1004          -0.20           0.00    0    0    0    0    0    0    0    1    0   -5    0    0    0   -2
+ 1005           0.00          -0.20    0    0    0    0    0    0    0    0    0    0    0    2    0    1
+ 1006           0.00           0.20    0    0    0    0    0    0    0    0    0    0    0    1   -2   -2
+ 1007          -0.20           0.00    0    2    0   -4    0    0    0    0    0    0    0    0    0    0
+ 1008           0.20           0.00    0    0    0    6    0    0    0    0    0    0    0    0    0    0
+ 1009          -0.20           0.00    3    0    0   -2    0    0    0    0    0    0    0    0    0    0
+ 1010           0.20           0.00    2   -1   -2    2   -1    0    0    0    0    0    0    0    0    0
+ 1011           0.00          -0.20    1    0   -1    1   -1    0    0    1    0    0    0    0    0    0
+ 1012          -0.20           0.00    0    0    2   -4    0    0    0    0    0    0    0    0    0    0
+ 1013          -0.20           0.00    1    0    0   -1   -1    0    0   -2    2    0    0    0    0    0
+ 1014           0.20           0.00    0    1    0    4    1    0    0    0    0    0    0    0    0    0
+ 1015           0.20           0.00    1    0    0   -6   -1    0    0    0    0    0    0    0    0    0
+ 1016           0.00           0.20    0    0    0    0    1    0    5   -8    0    0    0    0    0    0
+ 1017           0.20           0.00    0    0    4    2    2    0    0    0    0    0    0    0    0    0
+ 1018           0.20           0.00    3    0    0   -2    1    0    0    0    0    0    0    0    0    0
+ 1019          -0.20           0.00    0    0    2   -2    2    0    0   -2    0    2    0    0    0    0
+ 1020          -0.20           0.00    1   -1    0   -2   -2    0    0    0    0    0    0    0    0    0
+ 1021          -0.20           0.00    0    0    1   -1    2    0   -5    7    0    0    0    0    0    0
+ 1022          -0.20           0.00    2    1    0   -2   -2    0    0    0    0    0    0    0    0    0
+ 1023           0.20           0.00    0    0    0    0    1    0    0    2   -2    0    0    0    0    0
+ 1024          -0.20           0.00    1    0   -2    0    2    0    0    0    0    0    0    0    0    0
+ 1025          -0.20           0.00    1   -1    0    0   -2    0    0    0    0    0    0    0    0    0
+ 1026           0.20           0.00    1    1   -2    2   -2    0    0    0    0    0    0    0    0    0
+ 1027           0.16           0.00    0    0    0    0    1    0   -2    2    0    0    0    0    0    0
+ 1028           0.16           0.00    1    0    0   -3   -1    0    0    0    0    0    0    0    0    0
+ 1029           0.00          -0.16    0    0    1   -1   -1    0    0   -1    0   -1    0    0    0    0
+ 1030           0.16           0.00    2    0   -2   -2    1    0    0    0    0    0    0    0    0    0
+ 1031           0.16           0.00    1    0    0   -1    1    0    0   -1    0    1    0    0    0    0
+ 1032           0.16           0.00    2    0    0   -3    1    0    0    0    0    0    0    0    0    0
+ 1033           0.16           0.00    3    0    0    2   -1    0    0    0    0    0    0    0    0    0
+ 1034           0.16           0.00    1    1    0    1    1    0    0    0    0    0    0    0    0    0
+ 1035          -0.16           0.00    0    2    0    0   -2    0    0    0    0    0    0    0    0    0
+ 1036           0.16           0.00    2   -1    0    2   -1    0    0    0    0    0    0    0    0    0
+ 1037           0.16           0.00    1    1    0    1   -1    0    0    0    0    0    0    0    0    0
+ 1038          -0.16           0.00    1    0   -4   -2   -1    0    0    0    0    0    0    0    0    0
+ 1039          -0.16           0.00    1   -1   -2   -4   -1    0    0    0    0    0    0    0    0    0
+ 1040          -0.16           0.00    1   -2    2    2    1    0    0    0    0    0    0    0    0    0
+ 1041           0.16           0.00    3    1    2   -2    1    0    0    0    0    0    0    0    0    0
+ 1042           0.16           0.00    1    0   -2   -6   -1    0    0    0    0    0    0    0    0    0
+ 1043          -0.16           0.00    2    0    4   -4    2    0    0    0    0    0    0    0    0    0
+ 1044          -0.04           0.12    2   -2    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1045           0.16           0.00    3    0    4   -2    2    0    0    0    0    0    0    0    0    0
+ 1046           0.00           0.16    0    0    1   -1    0    0    3   -6    0    0    0    0    0    0
+ 1047           0.16           0.00    1    1    2    4    2    0    0    0    0    0    0    0    0    0
+ 1048           0.16           0.00    0    0    2   -3    0    0    0    0    0    0    0    0    0    0
+ 1049           0.00          -0.16    0    0    1    1    0    0    0    1    0    0    0    0    0    0
+ 1050           0.00          -0.16    0    0    1   -1    0    0   -4    5    0    0    0    0    0    0
+ 1051           0.00           0.16    0    0    1   -1    0    0    0   -2    2    0    0    0    0    0
+ 1052           0.16           0.00    0    0    1   -1    0    0    0   -1    0    0    1    0    0    0
+ 1053           0.00           0.16    0    0    1   -1    0    0    0   -1    0    1    0    0    0    0
+ 1054          -0.16           0.00    0    1   -2    4   -1    0    0    0    0    0    0    0    0    0
+ 1055           0.00          -0.16    1    0    0   -2    0    0    0    4   -8    3    0    0    0    0
+ 1056           0.16           0.00    3    0    2    1    2    0    0    0    0    0    0    0    0    0
+ 1057           0.16           0.00    3    0    0   -1    0    0    0    0    0    0    0    0    0    0
+ 1058           0.16           0.00    2    1    0    1    0    0    0    0    0    0    0    0    0    0
+ 1059           0.16           0.00    2    0    2    0    1    0    0    1    0    0    0    0    0    0
+ 1060          -0.16           0.00    2    0    0   -2    0    0    0   -2    0    2    2    0    0    0
+ 1061           0.16           0.00    2    0    0   -2    0    0    0   -4    4    0    0    0    0    0
+ 1062          -0.16           0.00    2   -2    2    2    2    0    0    0    0    0    0    0    0    0
+ 1063           0.16           0.00    1    1   -2   -6   -2    0    0    0    0    0    0    0    0    0
+ 1064          -0.16           0.00    1    0    0    0    0    0    1   -1    0    0    0    0    0    0
+ 1065          -0.16           0.00    1    0    0    0    0    0    0   -1    0    1    0    0    0    0
+ 1066          -0.16           0.00    1    0    0    0    0    0   -3    3    0    0    0    0    0    0
+ 1067          -0.16           0.00    1    0    0   -2    0    0    1   -1    0    0    0    0    0    0
+ 1068           0.00          -0.16    1    0    0   -2    0    0    0   -4    8   -3    0    0    0    0
+ 1069          -0.16           0.00    1    0    0   -2    0    0   -2    2    0    0    0    0    0    0
+ 1070          -0.16           0.00    0    0    2   -2    1    0    0    1    0   -1    0    0    0    0
+ 1071           0.16           0.00    0    0    2   -2    1    0    0   -3    0    3    0    0    0    0
+ 1072           0.16           0.00    0    0    2   -2    1    0   -5    5    0    0    0    0    0    0
+ 1073          -0.16           0.00    0    0    1   -1    1    0    1   -3    0    0    0    0    0    0
+ 1074           0.00           0.16    0    0    1   -1    1    0    0   -1    0    0    0   -1    0    0
+ 1075           0.16           0.00    0    0    1   -1    1    0    0   -4    6    0    0    0    0    0
+ 1076           0.00           0.16    0    0    1   -1    1    0   -5    6    0    0    0    0    0    0
+ 1077          -0.16           0.00    0    0    0    2    0    0    0   -1    0    1    0    0    0    0
+ 1078           0.00           0.16    0    0    0    0    0    0    8   -9    0    0    0    0    0    0
+ 1079          -0.16           0.00    0    0    0    0    0    0    7  -10    0    0    0    0    0   -1
+ 1080           0.00          -0.16    0    0    0    0    0    0    5   -5    0    0    0    0    0    1
+ 1081           0.00          -0.16    0    0    0    0    0    0    4   -5    0    0    0    0    0   -2
+ 1082           0.00          -0.16    0    0    0    0    0    0    3   -6    0    0    0    0    0    0
+ 1083           0.00           0.16    0    0    0    0    0    0    3   -8    0    0    0    0    0   -2
+ 1084           0.16           0.00    0    0    0    0    0    0    2   -5    0    0    0    0    0   -1
+ 1085          -0.16           0.00    0    0    0    0    0    0    1    1    0    0    0    0    0    0
+ 1086           0.16           0.00    0    0    0    0    0    0    1   -2    0    0    0    0    0   -1
+ 1087           0.00          -0.16    0    0    0    0    0    0    0    7   -8    0    0    0    0    2
+ 1088           0.00          -0.16    0    0    0    0    0    0    0    7   -9    0    0    0    0    2
+ 1089           0.00           0.16    0    0    0    0    0    0    0    6  -10    0    0    0    0   -2
+ 1090           0.00           0.16    0    0    0    0    0    0    0    3    0    0    0    0    0    2
+ 1091           0.16           0.00    0    0    0    0    0    0    0    3   -8    3    0    0    0   -2
+ 1092           0.00           0.16    0    0    0    0    0    0    0    2    0    0   -2    0    0    1
+ 1093           0.16           0.00    0    0    0    0    0    0    0    2   -4    0    0    0    0    1
+ 1094           0.16           0.00    0    0    0    0    0    0    0    1    0    0    0    0    0   -1
+ 1095           0.00          -0.16    0    0    0    0    0    0    0    1    0   -1    0    0    0   -1
+ 1096           0.00          -0.16    0    0    0    0    0    0    0    0    0    3   -5    0    0    0
+ 1097          -0.16           0.00    0    0    0    0    0    0    0    0    0    2   -2    0    0    0
+ 1098          -0.16           0.00    2    1    0   -6    0    0    0    0    0    0    0    0    0    0
+ 1099          -0.16           0.00    1   -1    0    1    0    0    0    0    0    0    0    0    0    0
+ 1100           0.00          -0.16    0    0    1   -1    0    0   -3    4    0    0    0    0    0    0
+ 1101           0.16           0.00    3   -1    0    2    0    0    0    0    0    0    0    0    0    0
+ 1102           0.16           0.00    4    0    0    2    0    0    0    0    0    0    0    0    0    0
+ 1103          -0.16           0.00    0    0    2   -2    0    0   -4    4    0    0    0    0    0    0
+ 1104           0.16           0.00    1    0    2   -1    0    0    0    0    0    0    0    0    0    0
+ 1105           0.16           0.00    1   -2   -2    2   -1    0    0    0    0    0    0    0    0    0
+ 1106           0.16           0.00    1   -1   -2   -2    0    0    0    0    0    0    0    0    0    0
+ 1107          -0.16           0.00    2    0    2   -3    2    0    0    0    0    0    0    0    0    0
+ 1108          -0.16           0.00    0    1    2    2    0    0    0    0    0    0    0    0    0    0
+ 1109           0.00           0.16    0    0    2   -2    1    0    0   -4    8   -3    0    0    0    0
+ 1110           0.00           0.16    0    0    2   -2    1    0    0    4   -8    3    0    0    0    0
+ 1111           0.16           0.00    3    0   -2    2   -1    0    0    0    0    0    0    0    0    0
+ 1112           0.16           0.00    2   -1    2    0    0    0    0    0    0    0    0    0    0    0
+ 1113          -0.16           0.00    2    0    0    4    1    0    0    0    0    0    0    0    0    0
+ 1114           0.16           0.00    2    0   -4    2   -1    0    0    0    0    0    0    0    0    0
+ 1115          -0.16           0.00    2   -1    0    2    1    0    0    0    0    0    0    0    0    0
+ 1116          -0.16           0.00    2   -2    0   -2   -2    0    0    0    0    0    0    0    0    0
+ 1117           0.00          -0.16    0    0    0    0    1    0    0    1    0   -2    0    0    0    0
+ 1118          -0.16           0.00    3    0    0    0    2    0    0    0    0    0    0    0    0    0
+ 1119           0.00          -0.16    0    0    0    0    1    0    3   -4    0    0    0    0    0    0
+ 1120           0.16           0.00    0    2    0    0    2    0    0    0    0    0    0    0    0    0
+ 1121           0.16           0.00    0    1    2   -4    2    0    0    0    0    0    0    0    0    0
+ 1122          -0.15           0.00    0    0    1   -1    2    0   -8   12    0    0    0    0    0    0
+ 1123           0.00           0.12    0    0    0    0    1    0    0   -1    0    2    0    0    0    0
+ 1124           0.12           0.00    0    0    0    0    1    0    0   -2    2    0    0    0    0    0
+ 1125           0.00           0.12    0    0    0    0    1    0   -3    4    0    0    0    0    0    0
+ 1126           0.12           0.00    1    0    0    0   -1    0  -10    3    0    0    0    0    0    0
+ 1127           0.12           0.00    1    0    0    0    1    0  -10    3    0    0    0    0    0    0
+ 1128           0.00          -0.12    0    0    0    0    2    0    0    0    0    1    0    0    0    0
+ 1129          -0.12           0.00    0    1    4   -4    2    0    0    0    0    0    0    0    0    0
+ 1130          -0.12           0.00    2    0    2   -2   -1    0    0    0    0    0    0    0    0    0
+ 1131           0.12           0.00    1    0    2   -4   -1    0    0    0    0    0    0    0    0    0
+ 1132          -0.12           0.00    1    2    0    0    1    0    0    0    0    0    0    0    0    0
+ 1133           0.00           0.12    2    0    0   -2   -1    0    0   -6    8    0    0    0    0    0
+ 1134           0.12           0.00    2   -1   -2    0    1    0    0    0    0    0    0    0    0    0
+ 1135           0.12           0.00    2    0    0   -2    1    0    0   -5    6    0    0    0    0    0
+ 1136           0.12           0.00    1    0    0   -2   -1    0    0   -2    0    2    0    0    0    0
+ 1137           0.12           0.00    2    0   -1   -1    1    0    0    3   -7    0    0    0    0    0
+ 1138           0.12           0.00    1    0    0   -2    1    0    0   -2    0    2    0    0    0    0
+ 1139           0.12           0.00    1    0    0   -1   -1    0    0   -3    4    0    0    0    0    0
+ 1140           0.12           0.00    0    0    0    3    2    0    0    0    0    0    0    0    0    0
+ 1141           0.12           0.00    2    2    0   -2   -1    0    0    0    0    0    0    0    0    0
+ 1142           0.12           0.00    1   -1    2   -3    1    0    0    0    0    0    0    0    0    0
+ 1143           0.12           0.00    1    0    4    0    1    0    0    0    0    0    0    0    0    0
+ 1144          -0.12           0.00    2    0    0   -2   -1    0    0   -2    0    3   -1    0    0    0
+ 1145           0.12           0.00    2   -1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+ 1146           0.12           0.00    2    1    2    2    1    0    0    0    0    0    0    0    0    0
+ 1147           0.00           0.12    0    0    2    0    2    0    2   -3    0    0    0    0    0    0
+ 1148           0.00           0.12    0    0    2    0    2    0   -2    3    0    0    0    0    0    0
+ 1149          -0.12           0.00    0    0    2    0    2    0    2   -2    0    0    0    0    0    0
+ 1150           0.12           0.00    0    0    2    0    2    0   -2    2    0    0    0    0    0    0
+ 1151          -0.12           0.00    5    0    2    0    1    0    0    0    0    0    0    0    0    0
+ 1152           0.12           0.00    3    0   -2   -6   -1    0    0    0    0    0    0    0    0    0
+ 1153           0.12           0.00    1    2    2    0    1    0    0    0    0    0    0    0    0    0
+ 1154          -0.12           0.00    1   -1    2    4    1    0    0    0    0    0    0    0    0    0
+ 1155           0.12           0.00    2    0   -2   -2   -2    0    0   -2    0    2    0    0    0    0
+ 1156          -0.12           0.00    2    0    2    4    1    0    0    0    0    0    0    0    0    0
+ 1157           0.00           0.12    0    0    2   -2    1    0   -8   11    0    0    0    0    0    0
+ 1158           0.00           0.12    1    0    2    0    2    0    0   -4    8   -3    0    0    0    0
+ 1159           0.00           0.12    1    0    2    0    2    0    0    4   -8    3    0    0    0    0
+ 1160          -0.12           0.00    1   -2    0   -1    0    0    0    0    0    0    0    0    0    0
+ 1161           0.12           0.00    2    0    2   -2    2    0    0   -2    0    3    0    0    0    0
+ 1162           0.12           0.00    1    0    2    0    2    0    1   -1    0    0    0    0    0    0
+ 1163          -0.12           0.00    1    0    2    0    2    0   -1    1    0    0    0    0    0    0
+ 1164           0.00          -0.12    0    0    2   -2    0   -1    0    2    0    0    0    0    0    0
+ 1165          -0.12           0.00    4    0   -2   -2    0    0    0    0    0    0    0    0    0    0
+ 1166          -0.12           0.00    1    0    2   -6    1    0    0    0    0    0    0    0    0    0
+ 1167           0.12           0.00    0    1   -4    2   -1    0    0    0    0    0    0    0    0    0
+ 1168           0.00           0.12    0    0    1   -1    0    0    0   -1    0    0   -2    0    0    0
+ 1169           0.12           0.00    1   -1   -2    1   -1    0    0    0    0    0    0    0    0    0
+ 1170           0.00           0.12    0    0    1   -1    0    0    0    1    0    0    0    0    0    0
+ 1171           0.00           0.12    2    0   -1   -1    0    0    0   -1    0    3    0    0    0    0
+ 1172           0.00          -0.12    0    0    1   -1    0    0   -1    0    0    0    0    0    0    0
+ 1173           0.08           0.04    0    0    0    0    0    0    0    0    1    0    0    0    0    0
+ 1174           0.12           0.00    4    1    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1175           0.12           0.00    3    1    2    2    2    0    0    0    0    0    0    0    0    0
+ 1176          -0.12           0.00    3    1    0   -2    0    0    0    0    0    0    0    0    0    0
+ 1177           0.12           0.00    3    1   -2   -6   -2    0    0    0    0    0    0    0    0    0
+ 1178          -0.12           0.00    3   -1    0   -2    0    0    0    0    0    0    0    0    0    0
+ 1179          -0.12           0.00    3   -1    0   -3    0    0    0    0    0    0    0    0    0    0
+ 1180           0.12           0.00    2    1    0   -3    0    0    0    0    0    0    0    0    0    0
+ 1181           0.00           0.12    2    0    1   -3    1    0   -6    7    0    0    0    0    0    0
+ 1182           0.00          -0.12    2    0    0   -2    0    0    2   -5    0    0    0    0    0    0
+ 1183           0.00           0.12    2    0    0   -2    0    0    0   -2    0    5   -5    0    0    0
+ 1184           0.12           0.00    2    0    0   -2    0    0    0   -2    0    1    5    0    0    0
+ 1185           0.12           0.00    2    0    0   -2    0    0    0   -2    0    0    2    0    0    0
+ 1186           0.12           0.00    2    0    0   -2    0    0   -4    4    0    0    0    0    0    0
+ 1187           0.00           0.12    2    0   -2    0   -2    0    0    5   -9    0    0    0    0    0
+ 1188          -0.12           0.00    2    0   -2   -5   -2    0    0    0    0    0    0    0    0    0
+ 1189          -0.12           0.00    2   -1    2    4    2    0    0    0    0    0    0    0    0    0
+ 1190           0.12           0.00    1    3   -2   -2   -2    0    0    0    0    0    0    0    0    0
+ 1191          -0.12           0.00    1    1   -2   -1   -2    0    0    0    0    0    0    0    0    0
+ 1192          -0.12           0.00    1    0    2   -2    2    0   -3    3    0    0    0    0    0    0
+ 1193           0.00           0.12    1    0    1    1    1    0    0    1    0    0    0    0    0    0
+ 1194           0.12           0.00    1    0    0    0    0    0    0    1    0   -1    0    0    0    0
+ 1195           0.12           0.00    1    0    0    0    0    0    0   -2    0    3    0    0    0    0
+ 1196          -0.12           0.00    1    0    0   -2    0    0    0    2    0   -2    0    0    0    0
+ 1197           0.12           0.00    1    0   -1    0   -1    0   -3    5    0    0    0    0    0    0
+ 1198          -0.12           0.00    1    0   -1   -1    0    0    0    8  -15    0    0    0    0    0
+ 1199           0.00          -0.12    1    0   -1   -2   -1    0    0    0    0    0    0    0    0    0
+ 1200          -0.12           0.00    1    0   -2   -2   -2    0    0    1    0   -1    0    0    0    0
+ 1201           0.12           0.00    0    0    2    2    2    0    0    2    0   -2    0    0    0    0
+ 1202          -0.12           0.00    0    0    2   -2    1    0    0   -2    0    1    0    0    0    0
+ 1203          -0.12           0.00    0    0    2   -2    1    0    0   -2    0    0    0    0    0    0
+ 1204           0.12           0.00    0    0    2   -2    1    0    0   -4    4    0    0    0    0    0
+ 1205           0.00           0.12    0    0    2   -2    1    0    0   -7    9    0    0    0    0    0
+ 1206          -0.12           0.00    0    0    2   -2    1    0    0  -10   15    0    0    0    0    0
+ 1207           0.12           0.00    0    0    1   -1    1    0    0    1   -4    0    0    0    0    0
+ 1208           0.00           0.12    0    0    1   -1    1    0    0   -1    0    1   -3    0    0    0
+ 1209           0.00           0.12    0    0    1   -1    1    0   -1    2    0    0    0    0    0    0
+ 1210           0.12           0.00    0    0    1   -1    1    0   -4    6    0    0    0    0    0    0
+ 1211          -0.12           0.00    0    0    0    2    0    0    0    2    0   -2    0    0    0    0
+ 1212          -0.12           0.00    0    0    0    2    0    0   -2    2    0    0    0    0    0    0
+ 1213           0.12           0.00    0    0    0    0    0    0    9  -13    0    0    0    0    0   -2
+ 1214          -0.12           0.00    0    0    0    0    0    0    8  -11    0    0    0    0    0   -1
+ 1215           0.12           0.00    0    0    0    0    0    0    8  -14    0    0    0    0    0   -2
+ 1216           0.00          -0.12    0    0    0    0    0    0    7  -11    0    0    0    0    0   -1
+ 1217           0.00          -0.12    0    0    0    0    0    0    6   -4    0    0    0    0    0    1
+ 1218           0.00          -0.12    0    0    0    0    0    0    6   -6    0    0    0    0    0    1
+ 1219          -0.12           0.00    0    0    0    0    0    0    6   -7    0    0    0    0    0   -1
+ 1220          -0.12           0.00    0    0    0    0    0    0    6   -8    0    0    0    0    0    0
+ 1221           0.00          -0.12    0    0    0    0    0    0    6   -9    0    0    0    0    0    0
+ 1222           0.00           0.12    0    0    0    0    0    0    5   -4    0    0    0    0    0    2
+ 1223          -0.12           0.00    0    0    0    0    0    0    5   -6    0    0    0    0    0   -1
+ 1224           0.00          -0.12    0    0    0    0    0    0    5   -6    0    0    0    0    0   -2
+ 1225          -0.12           0.00    0    0    0    0    0    0    5   -6   -4    0    0    0    0   -2
+ 1226           0.00           0.12    0    0    0    0    0    0    4   -2    0    0    0    0    0    0
+ 1227           0.00          -0.12    0    0    0    0    0    0    4   -5    0    0    0    0    0    0
+ 1228           0.12           0.00    0    0    0    0    0    0    4   -8    0    0    0    0    0   -2
+ 1229          -0.12           0.00    0    0    0    0    0    0    3   -1    0    0    0    0    0    0
+ 1230          -0.12           0.00    0    0    0    0    0    0    3   -3    0    2    0    0    0    2
+ 1231           0.12           0.00    0    0    0    0    0    0    3   -4    0    0    0    0    0    1
+ 1232           0.00           0.12    0    0    0    0    0    0    2    1    0    0    0    0    0    1
+ 1233          -0.12           0.00    0    0    0    0    0    0    2    0    0    0    0    0    0    0
+ 1234           0.12           0.00    0    0    0    0    0    0    1   -1    0    0    0    0    0   -2
+ 1235           0.12           0.00    0    0    0    0    0    0    1   -4    0    0    0    0    0   -1
+ 1236          -0.12           0.00    0    0    0    0    0    0    0    9  -17    0    0    0    0   -2
+ 1237           0.00           0.12    0    0    0    0    0    0    0    7   -7    0    0    0    0    2
+ 1238           0.00           0.12    0    0    0    0    0    0    0    7  -12    0    0    0    0   -2
+ 1239          -0.12           0.00    0    0    0    0    0    0    0    6   -4    0    0    0    0    2
+ 1240           0.00          -0.12    0    0    0    0    0    0    0    6   -8    1    5    0    0    2
+ 1241          -0.12           0.00    0    0    0    0    0    0    0    6   -9    0    0    0    0   -2
+ 1242           0.00           0.12    0    0    0    0    0    0    0    6  -10    0    0    0    0    0
+ 1243          -0.12           0.00    0    0    0    0    0    0    0    5    0   -4    0    0    0    2
+ 1244           0.12           0.00    0    0    0    0    0    0    0    5   -6    0    0    0    0    0
+ 1245          -0.12           0.00    0    0    0    0    0    0    0    5   -7    0    0    0    0   -2
+ 1246          -0.12           0.00    0    0    0    0    0    0    0    5   -8    3    0    0    0    2
+ 1247          -0.12           0.00    0    0    0    0    0    0    0    5   -9    0    0    0    0   -1
+ 1248          -0.12           0.00    0    0    0    0    0    0    0    5  -13    0    0    0    0   -2
+ 1249           0.12           0.00    0    0    0    0    0    0    0    5  -16    4    5    0    0   -2
+ 1250          -0.12           0.00    0    0    0    0    0    0    0    4   -7    0    0    0    0   -1
+ 1251           0.12           0.00    0    0    0    0    0    0    0    4   -8    3    0    0    0    1
+ 1252           0.12           0.00    0    0    0    0    0    0    0    4   -8    3    0    0    0   -1
+ 1253          -0.12           0.00    0    0    0    0    0    0    0    3    0   -5    0    0    0   -2
+ 1254           0.00          -0.12    0    0    0    0    0    0    0    3   -5    0    0    0    0   -1
+ 1255           0.00          -0.12    0    0    0    0    0    0    0    3   -7    0    0    0    0   -2
+ 1256           0.00          -0.12    0    0    0    0    0    0    0    3   -9    0    0    0    0   -2
+ 1257           0.12           0.00    0    0    0    0    0    0    0    2    1    0    0    0    0    2
+ 1258           0.12           0.00    0    0    0    0    0    0    0    2    0    2    0    0    0    2
+ 1259           0.00           0.12    0    0    0    0    0    0    0    2    0    0   -3    0    0    0
+ 1260           0.00          -0.12    0    0    0    0    0    0    0    2   -8    1    5    0    0   -2
+ 1261           0.00           0.12    0    0    0    0    0    0    0    1    0    1    0    0    0    1
+ 1262          -0.12           0.00    0    0    0    0    0    0    0    1    0    1   -5    0    0    0
+ 1263           0.00          -0.12    0    0    0    0    0    0    0    1    0    0    2    0    0    2
+ 1264          -0.12           0.00    0    0    0    0    0    0    0    1    0    0   -3    0    0    0
+ 1265           0.12           0.00    0    0    0    0    0    0    0    1    0   -3    5    0    0    0
+ 1266           0.00           0.12    0    0    0    0    0    0    0    1   -3    0    0    0    0    0
+ 1267           0.12           0.00    0    0    0    0    0    0    0    0    0    2   -6    3    0   -2
+ 1268           0.00           0.12    0    0    0    0    0    0    0    0    0    1   -2    0    0    0
+ 1269           0.00           0.12    0    0    0    0    0    0    0    0    0    0    0    1    0    0
+ 1270           0.12           0.00    0    0    0    0    0    0    0    0    0    0    0    0    0    2
+ 1271          -0.12           0.00    1    1    0   -6    0    0    0    0    0    0    0    0    0    0
+ 1272          -0.12           0.00    1    0    0    3    0    0    0    0    0    0    0    0    0    0
+ 1273           0.12           0.00    2    0    0   -2    0    0    0   -2    0    0    5    0    0    0
+ 1274          -0.12           0.00    3    0   -2   -1   -1    0    0    0    0    0    0    0    0    0
+ 1275          -0.12           0.00    1    2    2   -4    1    0    0    0    0    0    0    0    0    0
+ 1276          -0.12           0.00    0    0    1   -1    0    0   -2    2    0    0    0    0    0    0
+ 1277           0.00           0.12    1    0   -1    1    0    0    0    1    0    0    0    0    0    0
+ 1278           0.12           0.00    0    0    2   -2    1    0    1   -1    0    0    0    0    0    0
+ 1279          -0.12           0.00    2    0    2   -6    1    0    0    0    0    0    0    0    0    0
+ 1280          -0.12           0.00    2    1    2   -2    0    0    0    0    0    0    0    0    0    0
+ 1281          -0.12           0.00    2    1    2    0    0    0    0    0    0    0    0    0    0    0
+ 1282          -0.12           0.00    1    0    2    1    0    0    0    0    0    0    0    0    0    0
+ 1283           0.12           0.00    4    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+ 1284          -0.12           0.00    0    0    0    0    1    0    0    7  -13    0    0    0    0    0
+ 1285           0.12           0.00    2    1    0    2    1    0    0    0    0    0    0    0    0    0
+ 1286          -0.12           0.00    1   -1    0    4    1    0    0    0    0    0    0    0    0    0
+ 1287          -0.12           0.00    3    0   -2   -4   -2    0    0    0    0    0    0    0    0    0
+ 1288           0.12           0.00    2    0    0   -6   -1    0    0    0    0    0    0    0    0    0
+ 1289           0.12           0.00    0    0    1   -1   -1    0   -5    7    0    0    0    0    0    0
+ 1290           0.12           0.00    0    0    0    0    2    0   -3    5    0    0    0    0    0    0
+ 1291           0.00          -0.12    0    0    1    1    2    0    0    1    0    0    0    0    0    0
+ 1292           0.00          -0.12    0    0    1   -1    2    0   -3    4    0    0    0    0    0    0
+ 1293           0.00           0.12    0    0    0    0    1    0   -1    2    0    0    0    0    0    0
+ 1294           0.12           0.00    2   -1    0   -2    2    0    0    0    0    0    0    0    0    0
+ 1295           0.12           0.00    1    1   -2    1   -2    0    0    0    0    0    0    0    0    0
+ 1296           0.12           0.00    2    1   -2    0   -2    0    0    0    0    0    0    0    0    0
+ 1297          -0.12           0.00    0    0    1   -1    2    0    0   -1    0    0   -1    0    0    0
+ 1298          -0.12           0.00    2    1    2   -4    2    0    0    0    0    0    0    0    0    0
+ 1299           0.12           0.00    2    0    0   -4    2    0    0    0    0    0    0    0    0    0
+ 1300          -0.12           0.00    3    0    0    0   -2    0    0    0    0    0    0    0    0    0
+ 1301           0.12           0.00    1    0    0   -4    2    0    0    0    0    0    0    0    0    0
+ 1302           0.12           0.00    2    0    0   -4   -2    0    0    0    0    0    0    0    0    0
+ 1303           0.12           0.00    1    1    0    0   -2    0    0    0    0    0    0    0    0    0
+ 1304          -0.12           0.00    0    0    0    0    1    0    0    2    0   -2    0    0    0    0
+ 1305          -0.12           0.00    1    0   -2    4   -2    0    0    0    0    0    0    0    0    0
+ 1306           0.11           0.00    0    0    4   -4    4    0    0    0    0    0    0    0    0    0
+ 
+j = 1  Nb of terms = 253
+
+ 1307       -3328.48      205833.15    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+ 1308         197.53       12814.01    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1309          41.19        2187.91    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+ 1310         -35.85       -2004.36    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+ 1311          59.15         501.82    0    1    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1312          -5.82         448.76    0    0    2    0    1    0    0    0    0    0    0    0    0    0
+ 1313        -179.56         164.33    0    1    0    0    0    0    0    0    0    0    0    0    0    0
+ 1314           5.67         288.49    1    0    2    0    2    0    0    0    0    0    0    0    0    0
+ 1315          23.85        -214.50    0    1   -2    2   -2    0    0    0    0    0    0    0    0    0
+ 1316           2.87        -154.91    0    0    2   -2    1    0    0    0    0    0    0    0    0    0
+ 1317           2.14        -119.21    1    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+ 1318           1.17         -74.33    1    0    0    0    1    0    0    0    0    0    0    0    0    0
+ 1319           1.47          70.31    1    0    0    0   -1    0    0    0    0    0    0    0    0    0
+ 1320          -0.42          58.94    1    0    2    0    1    0    0    0    0    0    0    0    0    0
+ 1321          -0.95          57.12    1    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+ 1322          -1.08         -54.19    2    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+ 1323           0.92          36.78    0    0    2    2    2    0    0    0    0    0    0    0    0    0
+ 1324           0.68         -31.01    0    2   -2    2   -2    0    0    0    0    0    0    0    0    0
+ 1325           0.74          29.60    2    0    2    0    2    0    0    0    0    0    0    0    0    0
+ 1326          -0.60         -27.59    1    0    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1327         -11.11         -15.07    1    0    0    0    0    0    0    0    0    0    0    0    0    0
+ 1328          -0.40         -24.05    1    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+ 1329          -0.81          19.06    0    1    0    0    1    0    0    0    0    0    0    0    0    0
+ 1330           3.18          15.32    0    2    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1331          -0.08         -17.90    1    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+ 1332          -0.16          15.55    1    0    0   -2    1    0    0    0    0    0    0    0    0    0
+ 1333          -0.77          14.40    0    1    0    0   -1    0    0    0    0    0    0    0    0    0
+ 1334          -0.25          11.67    1    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+ 1335           6.18           3.58    0    0    1   -1    1    0    0   -1    0   -2    5    0    0    0
+ 1336          -1.00          -7.27    0    1    2    0    2    0    0    0    0    0    0    0    0    0
+ 1337          -0.99           6.87    0    1   -2    0   -2    0    0    0    0    0    0    0    0    0
+ 1338          -0.27           7.49    0    0    2    2    1    0    0    0    0    0    0    0    0    0
+ 1339          -0.30           7.31    0    0    0    2    1    0    0    0    0    0    0    0    0    0
+ 1340           0.20           7.30    1    0    2    2    2    0    0    0    0    0    0    0    0    0
+ 1341           0.33           6.80    2    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+ 1342           0.27          -6.81    1    0    2   -2    1    0    0    0    0    0    0    0    0    0
+ 1343           0.35           6.08    0    0    0    2   -1    0    0    0    0    0    0    0    0    0
+ 1344           0.35           6.09    0    1   -2    2   -1    0    0    0    0    0    0    0    0    0
+ 1345          -0.14          -6.19    2    0    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1346           0.14           6.02    2    0    2    0    1    0    0    0    0    0    0    0    0    0
+ 1347           2.69          -2.76    1    0    0   -2    0    0    0    0    0    0    0    0    0    0
+ 1348          -0.08          -4.93    2    0    0   -2    1    0    0    0    0    0    0    0    0    0
+ 1349           2.85          -1.77    0    0    0    0    0    0    0    0    0    2   -5    0    0   -1
+ 1350          -0.07          -4.27    0    1    2   -2    1    0    0    0    0    0    0    0    0    0
+ 1351          -3.71           0.38    0    2    0    0    0    0    0    0    0    0    0    0    0    0
+ 1352           3.75           0.04    0    1   -1    1   -1    0    0    0    0    0    0    0    0    0
+ 1353          -0.82          -2.73    0    0    0    2    0    0    0    0    0    0    0    0    0    0
+ 1354          -0.06           2.93    2    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+ 1355          -0.04           2.83    2    0    0    0   -1    0    0    0    0    0    0    0    0    0
+ 1356           0.08           2.75    3    0    2    0    2    0    0    0    0    0    0    0    0    0
+ 1357           0.07           2.75    1   -1    2    0    2    0    0    0    0    0    0    0    0    0
+ 1358          -0.07           2.70    1    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+ 1359          -0.07           2.52    0    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+ 1360          -0.05          -2.53    2    0    0    0    1    0    0    0    0    0    0    0    0    0
+ 1361          -0.04           2.40    1    0   -2    2   -1    0    0    0    0    0    0    0    0    0
+ 1362          -0.06          -2.37    1    1    2    0    2    0    0    0    0    0    0    0    0    0
+ 1363           0.69          -1.45    0    0    1   -1    1    0   -8   12    0    0    0    0    0    0
+ 1364          -0.04           2.00    0    0    0    0    0    0    3   -5    0    0    0    0    0   -2
+ 1365           1.99           0.02    1    0   -1    0   -1    0    0    0    0    0    0    0    0    0
+ 1366          -0.94           1.07    2    0    0   -2    0    0    0    0    0    0    0    0    0    0
+ 1367           0.04           1.91    1    0    0    0    2    0    0    0    0    0    0    0    0    0
+ 1368          -0.58          -1.36    2    0    0    0    0    0    0    0    0    0    0    0    0    0
+ 1369          -0.51          -1.25    0    0    2    0    0    0    0    0    0    0    0    0    0    0
+ 1370          -0.04          -1.59    0    0    2    1    2    0    0    0    0    0    0    0    0    0
+ 1371           0.39          -1.23    1    0    0   -1    0    0    0    0    0    0    0    0    0    0
+ 1372           0.03          -1.57    1   -1    0   -1   -1    0    0    0    0    0    0    0    0    0
+ 1373          -0.03           1.50    0    2   -2    2   -1    0    0    0    0    0    0    0    0    0
+ 1374           0.04           1.48    1    0    2    2    1    0    0    0    0    0    0    0    0    0
+ 1375          -0.04           1.45    1    0   -2   -4   -2    0    0    0    0    0    0    0    0    0
+ 1376           0.02          -1.36    1    0    0    0   -2    0    0    0    0    0    0    0    0    0
+ 1377           0.03          -1.32    2    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+ 1378          -0.03          -1.24    1    1    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1379          -0.02          -1.18    2    0    2   -2    1    0    0    0    0    0    0    0    0    0
+ 1380          -0.03           1.16    2    0   -2   -4   -2    0    0    0    0    0    0    0    0    0
+ 1381           0.02           1.13    0    0    0    0    0    0    0    0    0    2    0    0    0    2
+ 1382           0.04          -1.11    1    0    0   -1   -1    0    0    0    0    0    0    0    0    0
+ 1383           0.02           1.11    1    0    0    2    1    0    0    0    0    0    0    0    0    0
+ 1384           0.03          -1.10    1    0   -4    0   -2    0    0    0    0    0    0    0    0    0
+ 1385           0.03           1.04    2    0    2    2    2    0    0    0    0    0    0    0    0    0
+ 1386          -0.51           0.56    0    0    0    0    1    0    0   -1    2    0    0    0    0    0
+ 1387           0.02          -0.98    0    0    2   -2   -1    0    0    0    0    0    0    0    0    0
+ 1388          -0.02          -0.94    0    1    2    0    1    0    0    0    0    0    0    0    0    0
+ 1389          -0.02          -0.89    3    0    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1390          -0.02          -0.88    0    0    4   -2    2    0    0    0    0    0    0    0    0    0
+ 1391           0.31           0.60    0    0    0    0    0    0    8  -13    0    0    0    0    0   -1
+ 1392           0.02          -0.87    1    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+ 1393          -0.02          -0.87    2    0   -2    0    1    0    0    0    0    0    0    0    0    0
+ 1394          -0.01           0.83    0    0    2    0   -1    0    0    0    0    0    0    0    0    0
+ 1395          -0.02           0.77    0    1   -2    0   -1    0    0    0    0    0    0    0    0    0
+ 1396           0.42          -0.36    0    0    2   -2    0    0    0    0    0    0    0    0    0    0
+ 1397          -0.01          -0.73    0    1    0    0    2    0    0    0    0    0    0    0    0    0
+ 1398           0.01           0.71    1    1    0   -2    1    0    0    0    0    0    0    0    0    0
+ 1399           0.01           0.68    0    0    2   -1    2    0    0    0    0    0    0    0    0    0
+ 1400           0.02           0.66    0    0    2    4    2    0    0    0    0    0    0    0    0    0
+ 1401          -0.01          -0.62    1   -1    0    0    1    0    0    0    0    0    0    0    0    0
+ 1402          -0.01           0.62    1    0    0    2   -1    0    0    0    0    0    0    0    0    0
+ 1403          -0.58          -0.03    0    0    1   -1    1    0    0   -1    0    2   -5    0    0    0
+ 1404          -0.01           0.58    1   -1    0   -1   -2    0    0    0    0    0    0    0    0    0
+ 1405           0.44           0.14    0    0    0    0    0    0    0    2   -8    3    0    0    0   -2
+ 1406           0.02           0.56    1   -1    2    2    2    0    0    0    0    0    0    0    0    0
+ 1407           0.01          -0.57    0    1    0    0   -2    0    0    0    0    0    0    0    0    0
+ 1408          -0.13          -0.45    1    0    0    2    0    0    0    0    0    0    0    0    0    0
+ 1409           0.01           0.56    3    0    2    0    1    0    0    0    0    0    0    0    0    0
+ 1410           0.01          -0.55    1   -1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+ 1411           0.01           0.55    1    0    2   -4    1    0    0    0    0    0    0    0    0    0
+ 1412          -0.52           0.03    0    0    2   -2    1    0   -5    6    0    0    0    0    0    0
+ 1413          -0.01           0.54    1    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+ 1414          -0.01          -0.51    0    1    2    2    2    0    0    0    0    0    0    0    0    0
+ 1415          -0.41          -0.11    0    0    0    0    0    0    0    6   -8    3    0    0    0    2
+ 1416          -0.01           0.50    0    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+ 1417           0.01           0.48    1   -1    2    0    1    0    0    0    0    0    0    0    0    0
+ 1418           0.45          -0.04    1    0   -2   -2    0    0    0    0    0    0    0    0    0    0
+ 1419           0.01          -0.48    0    0    0    0    0    0    4   -6    0    0    0    0    0   -2
+ 1420           0.01           0.46    2   -1    2    0    2    0    0    0    0    0    0    0    0    0
+ 1421          -0.23           0.24    2    0   -2    0    0    0    0    0    0    0    0    0    0    0
+ 1422           0.01           0.46    0    0    0    1    1    0    0    0    0    0    0    0    0    0
+ 1423           0.35          -0.11    0    0    0    0    1    0    0   -4    8   -3    0    0    0    0
+ 1424           0.01           0.45    0    0    0    2    2    0    0    0    0    0    0    0    0    0
+ 1425           0.01          -0.45    1   -1   -2    0   -2    0    0    0    0    0    0    0    0    0
+ 1426           0.00          -0.45    0    0    0    0    0    0    0    3    0   -1    0    0    0    2
+ 1427          -0.01           0.44    0    0    0    0    0    0    2   -4    0    0    0    0    0   -2
+ 1428           0.35           0.09    0    0    0    0    1    0    0    4   -8    3    0    0    0    0
+ 1429           0.01           0.42    1    1    0    0    1    0    0    0    0    0    0    0    0    0
+ 1430          -0.01          -0.41    1    1    2    0    1    0    0    0    0    0    0    0    0    0
+ 1431           0.09          -0.33    0    0    1   -1    1    0    0    0   -2    0    0    0    0    0
+ 1432           0.00           0.41    0    1    0   -2    1    0    0    0    0    0    0    0    0    0
+ 1433           0.01           0.40    0    3    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1434          -0.01          -0.39    2    1    2    0    2    0    0    0    0    0    0    0    0    0
+ 1435          -0.39          -0.01    1    0   -1    0   -2    0    0    0    0    0    0    0    0    0
+ 1436           0.01          -0.39    0    0    0    1   -1    0    0    0    0    0    0    0    0    0
+ 1437          -0.01           0.38    1    0    0   -2   -2    0    0    0    0    0    0    0    0    0
+ 1438           0.32          -0.07    0    0    0    0    0    0    0    0    0    2    0    0    0    1
+ 1439          -0.01           0.36    1   -1    0    0   -1    0    0    0    0    0    0    0    0    0
+ 1440          -0.01          -0.36    0    0    0    0    0    0    2    0    0    0    0    0    0    2
+ 1441           0.01          -0.34    1    0   -2    2   -2    0    0    0    0    0    0    0    0    0
+ 1442           0.01          -0.34    2    0    0   -2   -1    0    0   -2    0    2    0    0    0    0
+ 1443           0.01           0.33    0    0    0    0    0    0    1    1    0    0    0    0    0    2
+ 1444          -0.01          -0.32    1    0    2    1    2    0    0    0    0    0    0    0    0    0
+ 1445           0.01           0.32    1    0    2   -1    2    0    0    0    0    0    0    0    0    0
+ 1446          -0.01          -0.32    0    0    2    1    1    0    0    0    0    0    0    0    0    0
+ 1447          -0.01          -0.31    1    0   -2    0    1    0    0    0    0    0    0    0    0    0
+ 1448          -0.31           0.00    0    0    1    0    1    0    0    0    0    0    0    0    0    0
+ 1449          -0.07          -0.24    1    0    2    0    0    0    0    0    0    0    0    0    0    0
+ 1450           0.10          -0.21    0    0    1   -1    1    0    0   -1    0    0   -1    0    0    0
+ 1451          -0.01          -0.30    1    0    0   -2    2    0    0    0    0    0    0    0    0    0
+ 1452          -0.01           0.29    1    0   -2   -4   -1    0    0    0    0    0    0    0    0    0
+ 1453          -0.01          -0.29    1    1    2   -2    1    0    0    0    0    0    0    0    0    0
+ 1454           0.00           0.29    1    0   -2    1   -1    0    0    0    0    0    0    0    0    0
+ 1455           0.23           0.06    0    0    1   -1    1    0    0   -1    0   -1    0    0    0    0
+ 1456           0.26           0.02    0    0    0    0    0    0    0    0    0    2   -5    0    0    1
+ 1457           0.00          -0.27    2    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+ 1458           0.25           0.02    0    0    0    0    0    0    5   -8    0    0    0    0    0   -2
+ 1459           0.09          -0.18    0    1    0   -2    0    0    0    0    0    0    0    0    0    0
+ 1460           0.01           0.25    0    0    0    0    0    0    0    1    0    1    0    0    0    2
+ 1461           0.14          -0.11    1    1    0   -2    0    0    0    0    0    0    0    0    0    0
+ 1462           0.00          -0.25    1    1    0    0   -1    0    0    0    0    0    0    0    0    0
+ 1463           0.01           0.24    4    0    2    0    2    0    0    0    0    0    0    0    0    0
+ 1464          -0.01          -0.24    2    1    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1465           0.00           0.23    2    0   -2   -4   -1    0    0    0    0    0    0    0    0    0
+ 1466           0.01           0.23    0    1    2    1    2    0    0    0    0    0    0    0    0    0
+ 1467          -0.01          -0.23    1    0    4   -2    2    0    0    0    0    0    0    0    0    0
+ 1468           0.00          -0.23    0    1    0    2    1    0    0    0    0    0    0    0    0    0
+ 1469           0.00          -0.22    1    0   -4    0   -1    0    0    0    0    0    0    0    0    0
+ 1470           0.00           0.21    1    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+ 1471           0.01           0.21    2    0    2    2    1    0    0    0    0    0    0    0    0    0
+ 1472          -0.17           0.03    0    0    1   -1    1    0    0   -1    0    2    0    0    0    0
+ 1473          -0.17           0.03    0    0    0    0    0    0    8  -13    0    0    0    0    0   -2
+ 1474           0.00          -0.19    0    0    0    0    0    0    5   -7    0    0    0    0    0   -2
+ 1475           0.14          -0.06    0    0    0    0    0    0    0    0    0    0    2    0    0    1
+ 1476           0.03          -0.17    0    0    1   -1    1    0   -5    7    0    0    0    0    0    0
+ 1477          -0.13           0.06    0    0    1   -1    1    0    0   -1    0    0    2    0    0    0
+ 1478           0.00           0.19    0    0    2   -4    1    0    0    0    0    0    0    0    0    0
+ 1479           0.00           0.19    0    0    2   -3    2    0    0    0    0    0    0    0    0    0
+ 1480          -0.06          -0.13    1    0    2    0    2    0    0    1    0    0    0    0    0    0
+ 1481           0.00           0.18    0    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+ 1482          -0.09          -0.09    1   -1    0    0    0    0    0    0    0    0    0    0    0    0
+ 1483           0.10          -0.09    0    0    0    0    0    0    0    8  -16    4    5    0    0   -2
+ 1484           0.06           0.12    1    0   -2    0   -2    0    0    4   -8    3    0    0    0    0
+ 1485           0.00           0.18    0    0    0    0    0    0    0    4    0   -2    0    0    0    2
+ 1486           0.00          -0.18    0    0    4    0    2    0    0    0    0    0    0    0    0    0
+ 1487           0.00           0.17    0    0    0    4    1    0    0    0    0    0    0    0    0    0
+ 1488          -0.03           0.15    0    0    0    0    0    0    0    2    0   -1    0    0    0    2
+ 1489          -0.01          -0.16    0    0    0    0    0    0    0    2    0    1    0    0    0    2
+ 1490           0.00           0.17    1    1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+ 1491           0.00          -0.17    2    0    0   -2   -2    0    0    0    0    0    0    0    0    0
+ 1492           0.11           0.06    0    0    0    0    0    0    8  -11    0    0    0    0    0   -2
+ 1493           0.00          -0.17    3    0    2   -2    1    0    0    0    0    0    0    0    0    0
+ 1494          -0.08           0.09    1    0   -2    0    0    0    0    0    0    0    0    0    0    0
+ 1495          -0.17           0.00    0    0    0    0    0    0    2   -1    0    0    0    0    0    2
+ 1496           0.00          -0.16    0    0    4   -2    1    0    0    0    0    0    0    0    0    0
+ 1497           0.01           0.15    1    0    2    4    2    0    0    0    0    0    0    0    0    0
+ 1498          -0.13          -0.03    0    0    0    0    0    0    1   -1    0    0    0    0    0   -1
+ 1499           0.00           0.15    1    1   -2    0   -2    0    0    0    0    0    0    0    0    0
+ 1500           0.00           0.15    2    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+ 1501          -0.13           0.03    0    0    0    0    0    0    4   -6    0    0    0    0    0   -1
+ 1502           0.10          -0.06    0    0    0    0    0    0    8  -15    0    0    0    0    0   -2
+ 1503          -0.07           0.08    0    0    0    0    0    0    0    1    2    0    0    0    0    2
+ 1504          -0.09          -0.06    0    0    0    0    0    0    0    3    0   -2    0    0    0    2
+ 1505           0.00           0.15    3    0    0    0   -1    0    0    0    0    0    0    0    0    0
+ 1506          -0.07          -0.08    0    0    0    0    0    0    0    3   -2    0    0    0    0    2
+ 1507           0.00          -0.14    2    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+ 1508           0.02           0.12    0    0    0    0    0    0    0    0    0    3    0    0    0    2
+ 1509           0.07           0.08    1    1    0    0    0    0    0    0    0    0    0    0    0    0
+ 1510          -0.03          -0.11    3    0    0    0    0    0    0    0    0    0    0    0    0    0
+ 1511          -0.01          -0.14    0    0    0    0    0    0    0    4   -2    0    0    0    0    2
+ 1512           0.00          -0.14    0    0    2   -2    1    0   -3    3    0    0    0    0    0    0
+ 1513           0.02          -0.12    1    0    0   -1    1    0    0    0    0    0    0    0    0    0
+ 1514           0.00          -0.14    1    1    2    2    2    0    0    0    0    0    0    0    0    0
+ 1515           0.00           0.14    0    0    1   -1    1    0    0    3   -8    3    0    0    0    0
+ 1516           0.00           0.14    0    0    2   -1    1    0    0    0    0    0    0    0    0    0
+ 1517           0.00           0.13    0    0    2    4    1    0    0    0    0    0    0    0    0    0
+ 1518           0.08          -0.06    0    0    0    0    1    0    8  -13    0    0    0    0    0    0
+ 1519           0.00           0.13    1   -1    0   -2   -1    0    0    0    0    0    0    0    0    0
+ 1520           0.00           0.13    0    0    0    0    0    0    0    0    0    0    2    0    0    2
+ 1521           0.01           0.13    3    0    2    2    2    0    0    0    0    0    0    0    0    0
+ 1522           0.00           0.13    2    0    0    2    1    0    0    0    0    0    0    0    0    0
+ 1523           0.00           0.13    1   -1   -2    2   -1    0    0    0    0    0    0    0    0    0
+ 1524          -0.02          -0.11    2    0    0   -2    1    0    0   -2    0    3    0    0    0    0
+ 1525           0.08          -0.04    0    0    0    1    0    0    0    0    0    0    0    0    0    0
+ 1526           0.00           0.13    2    0    0   -4    1    0    0    0    0    0    0    0    0    0
+ 1527           0.00           0.13    1    0    0   -4    1    0    0    0    0    0    0    0    0    0
+ 1528           0.01          -0.12    2    1   -2    0   -1    0    0    0    0    0    0    0    0    0
+ 1529           0.00           0.12    0    2   -2   -2   -2    0    0    0    0    0    0    0    0    0
+ 1530          -0.02          -0.11    0    0    0    0    0    0    5   -8    0    0    0    0    0   -1
+ 1531           0.00          -0.12    2    0    2   -4    1    0    0    0    0    0    0    0    0    0
+ 1532           0.00          -0.12    0    0    0    0    0    0    0    8  -16    4    5    0    0    2
+ 1533           0.00          -0.12    0    0    1   -1    1    0    0   -5    8   -3    0    0    0    0
+ 1534           0.04           0.08    1    0    0    0   -1    0  -18   16    0    0    0    0    0    0
+ 1535           0.00          -0.12    0    0    0    0    0    0    0    1    0   -3    0    0    0   -2
+ 1536           0.00           0.12    1   -1    0   -2   -2    0    0    0    0    0    0    0    0    0
+ 1537           0.00          -0.12    0    0    0    2   -2    0    0    0    0    0    0    0    0    0
+ 1538           0.00          -0.11    0    0    0    0    0    0    6   -8    0    0    0    0    0   -2
+ 1539           0.03          -0.09    1    0    0   -4    0    0    0    0    0    0    0    0    0    0
+ 1540           0.00           0.11    0    2    0    0    1    0    0    0    0    0    0    0    0    0
+ 1541          -0.11           0.00    0    0    0    0    0    0    3   -2    0    0    0    0    0    2
+ 1542           0.00           0.11    1   -1    2    2    1    0    0    0    0    0    0    0    0    0
+ 1543           0.00          -0.11    1   -1   -2    0   -1    0    0    0    0    0    0    0    0    0
+ 1544           0.07           0.05    0    0    0    0    1    0   -8   13    0    0    0    0    0    0
+ 1545           0.11           0.00    0    0    0    0    0    0    2   -5    0    0    0    0    0   -2
+ 1546           0.00          -0.11    0    0    0    0    0    0    1   -3    0    0    0    0    0   -2
+ 1547           0.00          -0.11    4    0    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1548           0.02          -0.09    0    0    0    0    1    0    0    0    0   -2    5    0    0    0
+ 1549           0.00           0.11    2    1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+ 1550           0.02           0.09    0    0    0    0    1    0    0    0    0    2   -5    0    0    0
+ 1551           0.00          -0.11    0    2    2   -2    1    0    0    0    0    0    0    0    0    0
+ 1552           0.00           0.11    1    0    2    0   -1    0    0    0    0    0    0    0    0    0
+ 1553          -0.08          -0.02    0    0    0    0    1    0    0    0    0    1    0    0    0    0
+ 1554           0.00          -0.10    2    1    0   -2    1    0    0    0    0    0    0    0    0    0
+ 1555           0.00          -0.10    2   -1   -2    0   -1    0    0    0    0    0    0    0    0    0
+ 1556          -0.03          -0.07    1    0    0    0    1    0  -18   16    0    0    0    0    0    0
+ 1557           0.00           0.10    1    2   -2   -2   -2    0    0    0    0    0    0    0    0    0
+ 1558           0.00           0.10    2    0    0   -2    2    0    0    0    0    0    0    0    0    0
+ 1559           0.00          -0.10    1   -1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+
+j = 2  Nb of terms = 36
+
+ 1560        2038.00          82.26    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+ 1561         155.75          -2.70    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1562          26.92          -0.45    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+ 1563         -24.43           0.46    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+ 1564         -17.36          -0.50    0    1    0    0    0    0    0    0    0    0    0    0    0    0
+ 1565          -8.41           0.01    1    0    0    0    0    0    0    0    0    0    0    0    0    0
+ 1566           6.08          -1.36    0    1    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1567           4.59           0.17    0    0    2    0    1    0    0    0    0    0    0    0    0    0
+ 1568           3.57          -0.06    1    0    2    0    2    0    0    0    0    0    0    0    0    0
+ 1569           2.54           0.60    0    1   -2    2   -2    0    0    0    0    0    0    0    0    0
+ 1570           1.86           0.00    1    0    0   -2    0    0    0    0    0    0    0    0    0    0
+ 1571          -1.52          -0.07    0    0    2   -2    1    0    0    0    0    0    0    0    0    0
+ 1572           1.46           0.04    1    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+ 1573          -0.75          -0.02    1    0    0    0    1    0    0    0    0    0    0    0    0    0
+ 1574          -0.75           0.00    0    0    0    2    0    0    0    0    0    0    0    0    0    0
+ 1575          -0.71          -0.01    1    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+ 1576          -0.69           0.02    1    0    0    0   -1    0    0    0    0    0    0    0    0    0
+ 1577           0.61           0.02    1    0    2    0    1    0    0    0    0    0    0    0    0    0
+ 1578           0.54          -0.04    2    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+ 1579          -0.56           0.00    2    0    0   -2    0    0    0    0    0    0    0    0    0    0
+ 1580           0.46          -0.02    0    0    2    2    2    0    0    0    0    0    0    0    0    0
+ 1581           0.38          -0.01    0    2   -2    2   -2    0    0    0    0    0    0    0    0    0
+ 1582           0.37          -0.02    2    0    2    0    2    0    0    0    0    0    0    0    0    0
+ 1583          -0.34           0.01    1    0    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1584          -0.35           0.00    2    0    0    0    0    0    0    0    0    0    0    0    0    0
+ 1585          -0.31           0.00    0    0    2    0    0    0    0    0    0    0    0    0    0    0
+ 1586           0.19          -0.09    0    2    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1587           0.26           0.00    0    0    2   -2    0    0    0    0    0    0    0    0    0    0
+ 1588           0.24          -0.01    1    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+ 1589          -0.20           0.00    0    2    0    0    0    0    0    0    0    0    0    0    0    0
+ 1590           0.18          -0.01    1    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+ 1591           0.17           0.00    0    1    0    0    1    0    0    0    0    0    0    0    0    0
+ 1592           0.15           0.01    1    0    0   -2    1    0    0    0    0    0    0    0    0    0
+ 1593          -0.15           0.00    0    1    0    0   -1    0    0    0    0    0    0    0    0    0
+ 1594          -0.13           0.00    2    0   -2    0    0    0    0    0    0    0    0    0    0    0
+ 1595          -0.12           0.00    1    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+ 
+j = 3  Nb of terms = 4
+
+ 1596           1.76         -20.39    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+ 1597           0.00          -1.27    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1598           0.00          -0.22    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+ 1599           0.00           0.20    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+
+j = 4  Nb of terms = 1
+      
+ 1600          -0.10          -0.02    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2b.coeff
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2b.coeff	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2b.coeff	(revision 22158)
@@ -0,0 +1,10 @@
+# Expression for the Y coordinate of the CIP in the GCRS based on the IAU2000A 
+# precession-nutation model 
+# 
+# --------------------------------------------------------------------------------------------------------------
+# 
+# Y = polynomial part + non-polynomial part
+# 
+# --------------------------------------------------------------------------------------------------------------
+# Polynomial part (unit microarcsecond)
+-6950.78 -25381.99 -22407250.99 +1842.28 +1113.06 +0.99
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2b.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2b.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2b.dat	(revision 22158)
@@ -0,0 +1,1304 @@
+# Expression for the Y coordinate of the CIP in the GCRS based on the IAU2000A 
+# precession-nutation model 
+# 
+# --------------------------------------------------------------------------------------------------------------
+# 
+# Y = polynomial part + non-polynomial part
+# 
+# --------------------------------------------------------------------------------------------------------------
+# 
+# --------------------------------------------------------------------------------------------------------------
+# 
+# Non-polynomial part (unit microarcsecond)
+# (ARG being for various combination of the fundamental arguments of the nutation theory)
+# 
+#   Sum_i[b_{c,0})_i * cos(ARG) + b_{s,0})_i * sin(ARG)] 
+# 
+# + Sum_i)j=1,4 [b_{c,j})_i * t^j * cos(ARG) + b_{s,j})_i * sin(ARG)] * t^j]
+# 
+# The Table below provides the values for b_{s,j})_i and b_{c,j})_i
+# 
+# The expressions for the fundamental arguments appearing in columns 4 to 8 (luni-solar part) 
+# and in columns 6 to 17 (planetary part) are those of the IERS Conventions 2000
+# 
+# --------------------------------------------------------------------------------------------------------------
+# 
+#     i    b_{s,j})_i      b_{c,j})_i    l    l'   F    D   Om L_Me L_Ve  L_E L_Ma  L_J L_Sa  L_U L_Ne  p_A
+# 
+# --------------------------------------------------------------------------------------------------------------
+# 
+0        1538.18     9205236.26    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+0        -458.66      573033.42    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+0         137.41       97846.69    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+0         -29.05      -89618.24    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+0         -17.40       22438.42    0    1    2   -2    2    0    0    0    0    0    0    0    0    0
+0          31.80       20069.50    0    0    2    0    1    0    0    0    0    0    0    0    0    0
+0          36.70       12902.66    1    0    2    0    2    0    0    0    0    0    0    0    0    0
+0         -13.20       -9592.72    0    1   -2    2   -2    0    0    0    0    0    0    0    0    0
+0        -192.40        7387.02    0    1    0    0    0    0    0    0    0    0    0    0    0    0
+0           3.92       -6918.22    0    0    2   -2    1    0    0    0    0    0    0    0    0    0
+0           0.40       -5331.13    1    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+0          -0.90       -3323.89    1    0    0    0    1    0    0    0    0    0    0    0    0    0
+0           7.50        3143.98    1    0    0    0   -1    0    0    0    0    0    0    0    0    0
+0           7.80        2636.13    1    0    2    0    1    0    0    0    0    0    0    0    0    0
+0          -6.60        2554.51    1    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0          -2.00       -2423.59    2    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+0           6.80        1645.01    0    0    2    2    2    0    0    0    0    0    0    0    0    0
+0           0.00       -1387.00    0    2   -2    2   -2    0    0    0    0    0    0    0    0    0
+0           5.90        1323.81    2    0    2    0    2    0    0    0    0    0    0    0    0    0
+0          -0.30       -1233.89    1    0    2   -2    2    0    0    0    0    0    0    0    0    0
+0           0.30       -1075.60    1    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+0          -4.48         852.85    0    1    0    0    1    0    0    0    0    0    0    0    0    0
+0           0.10        -800.34    1    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+0          35.80        -674.99    1    0    0    0    0    0    0    0    0    0    0    0    0    0
+0          -1.40         695.54    1    0    0   -2    1    0    0    0    0    0    0    0    0    0
+0          -0.50         684.99    0    2    2   -2    2    0    0    0    0    0    0    0    0    0
+0          -2.62         643.75    0    1    0    0   -1    0    0    0    0    0    0    0    0    0
+0          -1.50         522.11    1    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0         273.50         164.70    0    0    1   -1    1    0    0   -1    0   -2    5    0    0    0
+0           1.40         335.24    0    0    2    2    1    0    0    0    0    0    0    0    0    0
+0           1.90         326.60    1    0    2    2    2    0    0    0    0    0    0    0    0    0
+0           0.40         327.11    0    0    0    2    1    0    0    0    0    0    0    0    0    0
+0          -0.50        -325.03    0    1    2    0    2    0    0    0    0    0    0    0    0    0
+0          -0.40         307.03    0    1   -2    0   -2    0    0    0    0    0    0    0    0    0
+0           0.50         304.17    2    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+0          -0.10        -304.46    1    0    2   -2    1    0    0    0    0    0    0    0    0    0
+0          -0.40        -276.81    2    0    2   -2    2    0    0    0    0    0    0    0    0    0
+0           0.90         272.05    0    0    0    2   -1    0    0    0    0    0    0    0    0    0
+0           0.30         272.22    0    1   -2    2   -1    0    0    0    0    0    0    0    0    0
+0           1.20         269.45    2    0    2    0    1    0    0    0    0    0    0    0    0    0
+0           0.10        -220.67    2    0    0   -2    1    0    0    0    0    0    0    0    0    0
+0         128.60         -77.10    0    0    0    0    0    0    0    0    0    2   -5    0    0   -1
+0           0.10        -190.79    0    1    2   -2    1    0    0    0    0    0    0    0    0    0
+0         167.90           0.00    0    1   -1    1   -1    0    0    0    0    0    0    0    0    0
+0          -8.20        -123.48    1    0    0   -2    0    0    0    0    0    0    0    0    0    0
+0           0.10         131.04    2    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+0           0.40         126.64    2    0    0    0   -1    0    0    0    0    0    0    0    0    0
+0           2.90        -122.28    0    0    0    2    0    0    0    0    0    0    0    0    0    0
+0           0.70         123.20    3    0    2    0    2    0    0    0    0    0    0    0    0    0
+0           0.40         123.20    1   -1    2    0    2    0    0    0    0    0    0    0    0    0
+0          -0.30         120.70    1    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0          -0.50         112.90    0    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0          -0.20        -112.94    2    0    0    0    1    0    0    0    0    0    0    0    0    0
+0           0.20         107.31    1    0   -2    2   -1    0    0    0    0    0    0    0    0    0
+0          -0.30        -106.20    1    1    2    0    2    0    0    0    0    0    0    0    0    0
+0          31.90         -64.10    0    0    1   -1    1    0   -8   12    0    0    0    0    0    0
+0           0.00          89.50    0    0    0    0    0    0    3   -5    0    0    0    0    0   -2
+0          89.10           0.00    1    0   -1    0   -1    0    0    0    0    0    0    0    0    0
+0           0.00          85.32    1    0    0    0    2    0    0    0    0    0    0    0    0    0
+0          -0.20         -71.00    0    0    2    1    2    0    0    0    0    0    0    0    0    0
+0           0.00         -70.01    1   -1    0   -1   -1    0    0    0    0    0    0    0    0    0
+0          13.90         -55.30    1    0    0   -1    0    0    0    0    0    0    0    0    0    0
+0           0.00          67.25    0    2   -2    2   -1    0    0    0    0    0    0    0    0    0
+0           0.40          66.29    1    0    2    2    1    0    0    0    0    0    0    0    0    0
+0          -0.40          64.70    1    0   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0           1.30         -60.90    2    0    0    0    0    0    0    0    0    0    0    0    0    0
+0          -0.20         -60.92    1    0    0    0   -2    0    0    0    0    0    0    0    0    0
+0           0.20         -59.20    2    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0           1.10         -55.55    0    0    2    0    0    0    0    0    0    0    0    0    0    0
+0           0.00         -55.60    1    1    2   -2    2    0    0    0    0    0    0    0    0    0
+0          -0.10         -52.69    2    0    2   -2    1    0    0    0    0    0    0    0    0    0
+0          -0.20          51.80    2    0   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0           1.00         -49.51    1    0    0   -1   -1    0    0    0    0    0    0    0    0    0
+0           0.00          50.50    0    0    0    0    0    0    0    0    0    2    0    0    0    2
+0           2.50          47.70    2    0    0   -2    0    0    0    0    0    0    0    0    0    0
+0           0.10          49.59    1    0    0    2    1    0    0    0    0    0    0    0    0    0
+0           0.10         -49.00    1    0   -4    0   -2    0    0    0    0    0    0    0    0    0
+0         -23.20          24.60    0    0    0    0    1    0    0   -1    2    0    0    0    0    0
+0           0.40          46.50    2    0    2    2    2    0    0    0    0    0    0    0    0    0
+0          -0.10         -44.04    0    0    2   -2   -1    0    0    0    0    0    0    0    0    0
+0          -0.10         -42.19    0    1    2    0    1    0    0    0    0    0    0    0    0    0
+0          13.30          26.90    0    0    0    0    0    0    8  -13    0    0    0    0    0   -1
+0          -0.10         -39.90    3    0    2   -2    2    0    0    0    0    0    0    0    0    0
+0          -0.10         -39.50    0    0    4   -2    2    0    0    0    0    0    0    0    0    0
+0           0.00         -39.11    1    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+0          -0.10         -38.92    2    0   -2    0    1    0    0    0    0    0    0    0    0    0
+0           0.10          36.95    0    0    2    0   -1    0    0    0    0    0    0    0    0    0
+0          -0.10          34.59    0    1   -2    0   -1    0    0    0    0    0    0    0    0    0
+0           0.20         -32.55    0    1    0    0    2    0    0    0    0    0    0    0    0    0
+0          -0.10          31.61    1    1    0   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00          30.40    0    0    2   -1    2    0    0    0    0    0    0    0    0    0
+0           0.20          29.40    0    0    2    4    2    0    0    0    0    0    0    0    0    0
+0           0.00         -27.91    1   -1    0    0    1    0    0    0    0    0    0    0    0    0
+0           0.10          27.50    1    0    0    2   -1    0    0    0    0    0    0    0    0    0
+0         -25.70          -1.70    0    0    1   -1    1    0    0   -1    0    2   -5    0    0    0
+0          19.90           5.90    0    0    0    0    0    0    0    2   -8    3    0    0    0   -2
+0           0.00          25.80    1   -1    0   -1   -2    0    0    0    0    0    0    0    0    0
+0           0.20          25.20    1   -1    2    2    2    0    0    0    0    0    0    0    0    0
+0           0.00         -25.31    0    1    0    0   -2    0    0    0    0    0    0    0    0    0
+0           0.20          25.00    3    0    2    0    1    0    0    0    0    0    0    0    0    0
+0          -0.10          24.40    1    0    2   -4    1    0    0    0    0    0    0    0    0    0
+0           0.10         -24.40    1   -1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0         -23.30           0.90    0    0    2   -2    1    0   -5    6    0    0    0    0    0    0
+0          -0.10          24.00    1    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0         -18.00          -5.30    0    0    0    0    0    0    0    6   -8    3    0    0    0    2
+0          -0.10         -22.80    0    1    2    2    2    0    0    0    0    0    0    0    0    0
+0          -0.10          22.50    0    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.10          21.60    1   -1    2    0    1    0    0    0    0    0    0    0    0    0
+0           0.00         -21.30    0    0    0    0    0    0    4   -6    0    0    0    0    0   -2
+0           0.10          20.70    2   -1    2    0    2    0    0    0    0    0    0    0    0    0
+0           0.70         -20.10    0    0    0    0    0    0    0    3    0   -1    0    0    0    2
+0           0.00          20.51    0    0    0    1    1    0    0    0    0    0    0    0    0    0
+0          15.90          -4.50    0    0    0    0    1    0    0   -4    8   -3    0    0    0    0
+0           0.20         -19.94    1    0    0    2    0    0    0    0    0    0    0    0    0    0
+0           0.00          20.11    0    0    0    2    2    0    0    0    0    0    0    0    0    0
+0          15.60           4.40    0    0    0    0    1    0    0    4   -8    3    0    0    0    0
+0           0.00         -20.00    1   -1   -2    0   -2    0    0    0    0    0    0    0    0    0
+0           0.00          19.80    0    0    0    0    0    0    2   -4    0    0    0    0    0   -2
+0           0.00          18.91    1    1    0    0    1    0    0    0    0    0    0    0    0    0
+0           4.30         -14.60    0    0    1   -1    1    0    0    0   -2    0    0    0    0    0
+0          -0.10         -18.50    1    1    2    0    1    0    0    0    0    0    0    0    0    0
+0          -0.10          18.40    0    1    0   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00          18.10    0    3    2   -2    2    0    0    0    0    0    0    0    0    0
+0           1.00          16.81    0    2    0    0    0    0    0    0    0    0    0    0    0    0
+0          -0.10         -17.60    2    1    2    0    2    0    0    0    0    0    0    0    0    0
+0         -17.60           0.00    1    0   -1    0   -2    0    0    0    0    0    0    0    0    0
+0          -1.30         -16.26    0    0    2   -2    0    0    0    0    0    0    0    0    0    0
+0           0.00         -17.41    0    0    0    1   -1    0    0    0    0    0    0    0    0    0
+0          14.50          -2.70    0    0    0    0    0    0    0    0    0    2    0    0    0    1
+0           0.00          17.08    1    0    0   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.00          16.21    1   -1    0    0   -1    0    0    0    0    0    0    0    0    0
+0           0.00         -16.00    0    0    0    0    0    0    2    0    0    0    0    0    0    2
+0           0.00         -15.31    1    0   -2    2   -2    0    0    0    0    0    0    0    0    0
+0           0.00         -15.10    2    0    0   -2   -1    0    0   -2    0    2    0    0    0    0
+0           0.00          14.70    0    0    0    0    0    0    1    1    0    0    0    0    0    2
+0           0.00          14.40    1    0    2   -1    2    0    0    0    0    0    0    0    0    0
+0          -0.10         -14.30    1    0    2    1    2    0    0    0    0    0    0    0    0    0
+0           0.00         -14.40    0    0    2    1    1    0    0    0    0    0    0    0    0    0
+0           0.00         -13.81    1    0   -2    0    1    0    0    0    0    0    0    0    0    0
+0           4.50          -9.30    0    0    1   -1    1    0    0   -1    0    0   -1    0    0    0
+0         -13.80           0.00    0    0    1    0    1    0    0    0    0    0    0    0    0    0
+0           0.00         -13.38    1    0    0   -2    2    0    0    0    0    0    0    0    0    0
+0          -0.10          13.10    1    0   -2   -4   -1    0    0    0    0    0    0    0    0    0
+0          10.30           2.70    0    0    1   -1    1    0    0   -1    0   -1    0    0    0    0
+0           0.00          12.80    1    0   -2    1   -1    0    0    0    0    0    0    0    0    0
+0           0.00         -12.80    1    1    2   -2    1    0    0    0    0    0    0    0    0    0
+0          11.70           0.80    0    0    0    0    0    0    0    0    0    2   -5    0    0    1
+0           0.00         -12.00    2    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0          11.30           0.50    0    0    0    0    0    0    5   -8    0    0    0    0    0   -2
+0           0.00          11.40    0    0    0    0    0    0    0    1    0    1    0    0    0    2
+0           0.00         -11.20    1    1    0    0   -1    0    0    0    0    0    0    0    0    0
+0           0.10          10.90    4    0    2    0    2    0    0    0    0    0    0    0    0    0
+0           0.10         -10.77    1    0    2    0    0    0    0    0    0    0    0    0    0    0
+0           0.00         -10.80    2    1    2   -2    2    0    0    0    0    0    0    0    0    0
+0          -0.20          10.47    2    0   -2    0    0    0    0    0    0    0    0    0    0    0
+0           0.00          10.50    2    0   -2   -4   -1    0    0    0    0    0    0    0    0    0
+0           0.00         -10.40    1    0    4   -2    2    0    0    0    0    0    0    0    0    0
+0           0.00          10.40    0    1    2    1    2    0    0    0    0    0    0    0    0    0
+0           0.00         -10.20    0    1    0    2    1    0    0    0    0    0    0    0    0    0
+0           0.00         -10.00    1    0   -4    0   -1    0    0    0    0    0    0    0    0    0
+0           0.00           9.60    1    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+0           0.10           9.40    2    0    2    2    1    0    0    0    0    0    0    0    0    0
+0          -7.60           1.70    0    0    0    0    0    0    8  -13    0    0    0    0    0   -2
+0          -7.70           1.40    0    0    1   -1    1    0    0   -1    0    2    0    0    0    0
+0           1.40          -7.50    0    0    1   -1    1    0   -5    7    0    0    0    0    0    0
+0           6.10          -2.70    0    0    0    0    0    0    0    0    0    0    2    0    0    1
+0           0.00          -8.70    0    0    0    0    0    0    5   -7    0    0    0    0    0   -2
+0          -5.90           2.60    0    0    1   -1    1    0    0   -1    0    0    2    0    0    0
+0           0.00           8.40    0    0    2   -4    1    0    0    0    0    0    0    0    0    0
+0          -0.20          -8.11    0    1    0   -2    0    0    0    0    0    0    0    0    0    0
+0          -2.60          -5.70    1    0    2    0    2    0    0    1    0    0    0    0    0    0
+0           0.00           8.30    0    0    2   -3    2    0    0    0    0    0    0    0    0    0
+0           2.70           5.50    1    0   -2    0   -2    0    0    4   -8    3    0    0    0    0
+0           4.20          -4.00    0    0    0    0    0    0    0    8  -16    4    5    0    0   -2
+0          -0.10           8.00    0    0    0    0    0    0    0    4    0   -2    0    0    0    2
+0           0.00           8.09    0    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+0          -1.30           6.70    0    0    0    0    0    0    0    2    0   -1    0    0    0    2
+0           0.00          -7.90    0    0    4    0    2    0    0    0    0    0    0    0    0    0
+0           0.00           7.80    0    0    0    4    1    0    0    0    0    0    0    0    0    0
+0          -7.50          -0.20    0    0    0    0    0    0    2   -1    0    0    0    0    0    2
+0          -0.50          -7.20    0    0    0    0    0    0    0    2    0    1    0    0    0    2
+0           4.90           2.70    0    0    0    0    0    0    8  -11    0    0    0    0    0   -2
+0           0.00           7.50    1    1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -7.50    3    0    2   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00          -7.49    2    0    0   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -7.20    0    0    4   -2    1    0    0    0    0    0    0    0    0    0
+0           0.10           6.90    1    0    2    4    2    0    0    0    0    0    0    0    0    0
+0          -5.60           1.40    0    0    0    0    0    0    4   -6    0    0    0    0    0   -1
+0          -5.70          -1.30    0    0    0    0    0    0    1   -1    0    0    0    0    0   -1
+0           0.00           6.90    2    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+0           4.20          -2.70    0    0    0    0    0    0    8  -15    0    0    0    0    0   -2
+0           0.00           6.90    1    1   -2    0   -2    0    0    0    0    0    0    0    0    0
+0          -3.10           3.70    0    0    0    0    0    0    0    1    2    0    0    0    0    2
+0          -3.90          -2.90    0    0    0    0    0    0    0    3    0   -2    0    0    0    2
+0           0.00           6.60    3    0    0    0   -1    0    0    0    0    0    0    0    0    0
+0          -3.10          -3.50    0    0    0    0    0    0    0    3   -2    0    0    0    0    2
+0           1.10          -5.39    1    0    0   -1    1    0    0    0    0    0    0    0    0    0
+0           0.00          -6.40    2    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+0           0.90           5.50    0    0    0    0    0    0    0    0    0    3    0    0    0    2
+0           0.00          -6.30    0    0    2   -2    1    0   -3    3    0    0    0    0    0    0
+0          -0.10          -6.20    0    0    0    0    0    0    0    4   -2    0    0    0    0    2
+0           0.00          -6.10    1    1    2    2    2    0    0    0    0    0    0    0    0    0
+0           0.00           6.10    0    0    1   -1    1    0    0    3   -8    3    0    0    0    0
+0           0.00           6.10    0    0    2   -1    1    0    0    0    0    0    0    0    0    0
+0           3.50          -2.50    0    0    0    0    1    0    8  -13    0    0    0    0    0    0
+0           0.00           6.00    0    0    2    4    1    0    0    0    0    0    0    0    0    0
+0           0.00           5.90    1   -1    0   -2   -1    0    0    0    0    0    0    0    0    0
+0          -0.90          -4.80    2    0    0   -2    1    0    0   -2    0    3    0    0    0    0
+0           0.00           5.70    1   -1   -2    2   -1    0    0    0    0    0    0    0    0    0
+0           0.10           5.60    3    0    2    2    2    0    0    0    0    0    0    0    0    0
+0           0.00           5.70    0    0    0    0    0    0    0    0    0    0    2    0    0    2
+0           0.00           5.70    2    0    0    2    1    0    0    0    0    0    0    0    0    0
+0           0.00           5.60    2    0    0   -4    1    0    0    0    0    0    0    0    0    0
+0           0.00           5.60    1    0    0   -4    1    0    0    0    0    0    0    0    0    0
+0           0.20          -5.40    2    1   -2    0   -1    0    0    0    0    0    0    0    0    0
+0          -0.90          -4.70    0    0    0    0    0    0    5   -8    0    0    0    0    0   -1
+0          -0.40          -5.10    1    1    0   -2    0    0    0    0    0    0    0    0    0    0
+0           0.00           5.50    0    2   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -5.40    2    0    2   -4    1    0    0    0    0    0    0    0    0    0
+0           0.00          -5.40    0    0    0    0    0    0    0    8  -16    4    5    0    0    2
+0           1.80           3.60    1    0    0    0   -1    0  -18   16    0    0    0    0    0    0
+0           0.00           5.30    1   -1    0   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -5.30    0    0    1   -1    1    0    0   -5    8   -3    0    0    0    0
+0           0.00          -5.20    0    0    0    0    0    0    0    1    0   -3    0    0    0   -2
+0           0.00          -5.19    0    0    0    2   -2    0    0    0    0    0    0    0    0    0
+0           3.00           2.10    0    0    0    0    1    0   -8   13    0    0    0    0    0    0
+0           0.00          -5.10    0    0    0    0    0    0    6   -8    0    0    0    0    0   -2
+0           0.00           5.07    0    2    0    0    1    0    0    0    0    0    0    0    0    0
+0           0.90          -4.10    0    0    0    0    1    0    0    0    0   -2    5    0    0    0
+0          -5.00           0.00    0    0    0    0    0    0    3   -2    0    0    0    0    0    2
+0           0.00          -5.00    3    0    0    0    0    0    0    0    0    0    0    0    0    0
+0           0.00           5.00    1   -1    2    2    1    0    0    0    0    0    0    0    0    0
+0           0.00          -5.00    1   -1   -2    0   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -4.90    4    0    2   -2    2    0    0    0    0    0    0    0    0    0
+0           4.90           0.00    0    0    0    0    0    0    2   -5    0    0    0    0    0   -2
+0           0.00          -4.90    0    0    0    0    0    0    1   -3    0    0    0    0    0   -2
+0           0.90           3.90    0    0    0    0    1    0    0    0    0    2   -5    0    0    0
+0           0.00           4.80    2    1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0          -3.70          -1.10    0    0    0    0    1    0    0    0    0    1    0    0    0    0
+0           0.00          -4.72    0    2    2   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00           4.71    1    0    2    0   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -4.50    2    1    0   -2    1    0    0    0    0    0    0    0    0    0
+0          -1.50          -3.00    1    0    0    0    1    0  -18   16    0    0    0    0    0    0
+0           0.00          -4.50    2   -1   -2    0   -1    0    0    0    0    0    0    0    0    0
+0           0.30          -4.11    1   -1    0    0    0    0    0    0    0    0    0    0    0    0
+0           0.00           4.40    1    2   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -4.40    1   -1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           4.39    2    0    0   -2    2    0    0    0    0    0    0    0    0    0
+0           0.00          -4.30    3    0    0    0    1    0    0    0    0    0    0    0    0    0
+0           0.00           4.30    2    0   -2    2   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -4.30    0    1    2    2    1    0    0    0    0    0    0    0    0    0
+0           0.20           4.03    1    0   -2    0    0    0    0    0    0    0    0    0    0    0
+0           0.20           4.00    0    2   -2    0   -2    0    0    0    0    0    0    0    0    0
+0          -0.60           3.50    0    0    1   -1    1    0    0   -1    0    0    1    0    0    0
+0           0.00           4.10    3    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+0           0.00           4.00    1    0   -4    2   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -4.00    0    1   -2    1   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -3.91    1    0    0   -4    0    0    0    0    0    0    0    0    0    0
+0           1.90           2.00    0    0    0    0    1    0    0    1   -2    0    0    0    0    0
+0           0.00           3.90    2   -1    2    2    2    0    0    0    0    0    0    0    0    0
+0           0.00           3.90    0    1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -3.90    1    0   -2   -3   -2    0    0    0    0    0    0    0    0    0
+0           3.10          -0.80    0    0    0    0    0    0    2   -4    0    0    0    0    0   -1
+0           0.00           3.90    2   -1    2    0    1    0    0    0    0    0    0    0    0    0
+0           0.00           3.90    2    0    0    0    2    0    0    0    0    0    0    0    0    0
+0           0.00           3.80    0    0    0    0    0    0    0    2    0    0    0    0    0    2
+0          -0.20           3.51    1    1    0    0    0    0    0    0    0    0    0    0    0    0
+0           0.00          -3.60    1    0   -2   -1   -2    0    0    0    0    0    0    0    0    0
+0          -2.10           1.50    0    0    0    0    0    0    0    1    0    2    0    0    0    2
+0           0.00          -3.60    1    1   -2    1   -1    0    0    0    0    0    0    0    0    0
+0           0.70           2.80    0    0    0    0    0    0    3   -7    0    0    0    0    0   -2
+0          -2.80           0.70    0    0    0    0    0    0    0    0    0    1    0    0    0   -1
+0           0.00          -3.50    0    0    0    0    0    0    0    2    0    0    0    0    0    0
+0          -2.90          -0.60    0    0    0    0    0    0    2   -2    0    0    0    0    0   -1
+0           0.00          -3.40    1   -1    0   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00           3.40    2    0   -4    0   -2    0    0    0    0    0    0    0    0    0
+0           0.00           3.36    0    0    2    0    3    0    0    0    0    0    0    0    0    0
+0           0.50           2.80    2    0    0   -2   -1    0    0   -2    0    3    0    0    0    0
+0           2.60          -0.70    0    0    0    0    0    0    3   -5    0    0    0    0    0   -1
+0           1.00          -2.30    0    0    0    0    0    0    0    0    0    1    0    0    0    2
+0           0.00          -3.30    2    1    2    0    1    0    0    0    0    0    0    0    0    0
+0           0.00           3.30    1    1   -2    0   -1    0    0    0    0    0    0    0    0    0
+0           0.00           3.23    0    2    0    0   -1    0    0    0    0    0    0    0    0    0
+0           0.00           3.20    1   -1    2   -2    2    0    0    0    0    0    0    0    0    0
+0           0.00          -3.20    0    2    2    0    2    0    0    0    0    0    0    0    0    0
+0           0.00          -3.20    0    0    0    0    0    0    7   -9    0    0    0    0    0   -2
+0           0.00           3.20    0    0    0    0    0    0    0    0    2    0    0    0    0    2
+0           2.90          -0.30    0    0    0    0    0    0    0    0    0    1    0    0    0    1
+0           0.08           3.05    0    0    2   -2    3    0    0    0    0    0    0    0    0    0
+0          -0.70          -2.40    0    0    0    0    0    0    3   -3    0    0    0    0    0    2
+0           0.00          -3.08    1    0    2   -4    2    0    0    0    0    0    0    0    0    0
+0           0.00           3.00    2    0    2   -1    2    0    0    0    0    0    0    0    0    0
+0          -1.60           1.40    1    0    0   -1    1    0    0   -1    0    2    0    0    0    0
+0          -2.90          -0.10    0    0    0    0    0    0    4   -7    0    0    0    0    0   -2
+0           0.00          -2.90    2    0    0   -2    1    0    0   -2    0    2    0    0    0    0
+0          -2.50           0.40    0    0    1   -1    1    0    0   -2    2    0    0    0    0    0
+0           0.40          -2.50    0    0    0    0    0    0    0    0    0    0    1    0    0    1
+0           0.00          -2.90    1    0    2    1    1    0    0    0    0    0    0    0    0    0
+0           0.00           2.89    0    1   -2    2    0    0    0    0    0    0    0    0    0    0
+0           0.00          -2.80    2    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0          -2.50           0.30    0    0    1   -1    1    0    0   -1    0    1    0    0    0    0
+0          -2.50          -0.30    0    0    0    0    0    0    0    1   -2    0    0    0    0   -1
+0           0.00          -2.70    0    0    2   -2    1    0    0   -2    0    2    0    0    0    0
+0           2.70           0.00    1    0   -1    0   -3    0    0    0    0    0    0    0    0    0
+0           0.00          -2.60    0    1    0    1    1    0    0    0    0    0    0    0    0    0
+0           0.00          -2.60    0    1    0    2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           2.60    3   -1    2    0    2    0    0    0    0    0    0    0    0    0
+0           2.10           0.50    0    0    1   -1    1    0   -3    4    0    0    0    0    0    0
+0           0.00           2.50    0    1    0    1   -1    0    0    0    0    0    0    0    0    0
+0           0.80           1.70    0    0    0    0    0    0    0    0    0    0    1    0    0   -1
+0           1.90          -0.60    0    0    0    0    0    0    0    6  -16    4    5    0    0   -2
+0           0.00          -2.50    2    0    0    0   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -2.40    2    0    0    2    0    0    0    0    0    0    0    0    0    0
+0           0.00           2.40    2    0    0    2   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -2.40    1    1   -2    2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           2.40    1    0    2   -3    1    0    0    0    0    0    0    0    0    0
+0          -1.90           0.50    0    0    0    0    0    0    5   -7    0    0    0    0    0   -1
+0          -0.10          -2.30    2    0    0   -4    0    0    0    0    0    0    0    0    0    0
+0           0.00           2.30    1    1    2   -4    1    0    0    0    0    0    0    0    0    0
+0           0.00          -2.30    3    1    2    0    2    0    0    0    0    0    0    0    0    0
+0          -1.40           0.90    0    0    0    0    0    0    0    0    4    0    0    0    0    2
+0          -0.10          -2.20    0    0    0    0    0    0    8  -10    0    0    0    0    0   -2
+0          -0.20          -2.00    0    0    0    1    0    0    0    0    0    0    0    0    0    0
+0           0.00           2.20    1   -2    2    0    2    0    0    0    0    0    0    0    0    0
+0           0.00          -2.20    2   -1    2   -2    2    0    0    0    0    0    0    0    0    0
+0           0.00           2.20    1    1    2    1    2    0    0    0    0    0    0    0    0    0
+0           0.00           2.20    0    0    0    0    0    0    0    2   -4    0    0    0    0   -2
+0          -1.80          -0.40    0    0    0    0    0    0    3   -3    0    0    0    0    0   -1
+0           0.00           2.20    0    1    2    1    1    0    0    0    0    0    0    0    0    0
+0           0.00           2.20    4    0    2    0    1    0    0    0    0    0    0    0    0    0
+0          -1.70           0.40    0    0    0    0    0    0    1   -1    0    0    0    0    0    1
+0          -0.80          -1.30    0    0    0    0    0    0    0    5   -4    0    0    0    0    2
+0          -1.30          -0.80    0    0    0    0    0    0    0    4   -4    0    0    0    0    2
+0           0.00           2.10    1    0   -2    1   -2    0    0    0    0    0    0    0    0    0
+0           0.00           2.10    1   -1    2   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00          -2.10    1    0    4   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00          -2.10    2    1    2   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00           2.10    1    0    2   -1    1    0    0    0    0    0    0    0    0    0
+0           0.00          -2.00    1    0    2   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           2.00    1    0   -2    2    1    0    0    0    0    0    0    0    0    0
+0           0.00           2.00    1   -1    0    2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           2.00    2   -2    0   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -2.00    1    2    2   -2    2    0    0    0    0    0    0    0    0    0
+0           2.00           0.00    0    0    0    0    0    0    6   -9    0    0    0    0    0   -2
+0           1.10          -0.90    0    0    0    0    0    0    0    0    0    2   -5    0    0   -2
+0           1.60          -0.40    0    0    0    0    0    0    1   -3    0    0    0    0    0   -1
+0           0.00          -1.91    1    0   -2   -2    0    0    0    0    0    0    0    0    0    0
+0           0.00          -1.90    0    0    0    4    0    0    0    0    0    0    0    0    0    0
+0           0.00           1.90    0    0    4   -4    2    0    0    0    0    0    0    0    0    0
+0           0.00          -1.90    3    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.00           1.90    2   -1    0   -2    1    0    0    0    0    0    0    0    0    0
+0           1.50           0.40    0    0    1   -1    1    0   -4    5    0    0    0    0    0    0
+0          -1.50          -0.40    0    0    0    0    0    0    0    2    0    0    0    0    0    1
+0          -1.40          -0.50    0    0    1   -1    1    0    0   -1    0   -4   10    0    0    0
+0          -1.00           0.90    0    0    1   -1    1    0    0   -1    0    0    0    0    2    0
+0           0.00          -1.90    2    0    2    1    2    0    0    0    0    0    0    0    0    0
+0          -0.30           1.60    0    0    0    0    0    0    0    4    0   -3    0    0    0    2
+0           0.00           1.90    0    0    0    4   -1    0    0    0    0    0    0    0    0    0
+0           0.00           1.90    1   -1    0    2    1    0    0    0    0    0    0    0    0    0
+0           0.00          -1.80    2   -1    0    0    1    0    0    0    0    0    0    0    0    0
+0           0.00          -1.80    2    0   -4   -2   -2    0    0    0    0    0    0    0    0    0
+0          -1.10           0.70    0    0    0    0    0    0    0    2   -4    0    0    0    0   -1
+0           0.20          -1.60    0    0    0    0    0    0    2   -3    0    0    0    0    0   -1
+0           0.00           1.80    2    0   -2   -6   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -1.71    0    0    2    2    0    0    0    0    0    0    0    0    0    0
+0          -1.20          -0.50    0    0    2   -2    1    0    0   -9   13    0    0    0    0    0
+0           1.50           0.20    0    0    1    1    1    0    0    1    0    0    0    0    0    0
+0          -0.60          -1.10    1    0    2    0    1    0    0   -2    0    3    0    0    0    0
+0           0.60           1.10    1    0   -2    0   -1    0    0   -1    0    0    0    0    0    0
+0          -0.60          -1.10    0    0    0    0    0    0    0    4   -3    0    0    0    0    2
+0          -1.10           0.60    0    0    0    0    1    0    0   -2    4    0    0    0    0    0
+0          -1.70           0.00    0    0    0    0    1    0    2   -3    0    0    0    0    0    0
+0           0.00           1.60    0    1   -2    2    1    0    0    0    0    0    0    0    0    0
+0           0.00          -1.60    2    0    4   -2    2    0    0    0    0    0    0    0    0    0
+0           0.00          -1.60    0    0    2    3    2    0    0    0    0    0    0    0    0    0
+0           1.20          -0.40    0    0    0    0    0    0    0    0    0    3    0    0    0    1
+0          -0.50          -1.10    2    0    2    0    2    0    0    2    0   -3    0    0    0    0
+0           0.60           1.00    0    0    0    0    0    0    0    3   -6    0    0    0    0   -2
+0          -1.30          -0.30    0    0    0    0    0    0    4   -4    0    0    0    0    0   -1
+0           0.30          -1.30    0    0    0    0    0    0    0    1   -2    0    0    0    0    1
+0           0.00           1.60    1    0    0    4    1    0    0    0    0    0    0    0    0    0
+0           0.00          -1.60    1    1    0    2    1    0    0    0    0    0    0    0    0    0
+0           0.00          -1.60    0    0    4    0    1    0    0    0    0    0    0    0    0    0
+0           1.10          -0.50    0    0    1   -1    2    0    0   -1    0    0    2    0    0    0
+0           0.00          -1.50    1   -1    0    2    0    0    0    0    0    0    0    0    0    0
+0           0.00          -1.50    0    1    2   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           1.50    2   -1    0    0   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -1.50    1    0    0    1   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -1.50    1    2    0   -2   -1    0    0    0    0    0    0    0    0    0
+0           1.50           0.00    1    0    0   -1    1    0   -3    4    0    0    0    0    0    0
+0           0.00          -1.50    0    1    4   -2    2    0    0    0    0    0    0    0    0    0
+0           1.30          -0.20    0    0    0    0    1    0    0    0    0    0    1    0    0    0
+0           0.00          -1.50    0    0    0    0    0    0    9  -11    0    0    0    0    0   -2
+0          -1.20          -0.30    0    0    0    0    0    0    1    1    0    0    0    0    0    1
+0          -1.40           0.10    0    0    0    0    0    0    0    4    0   -1    0    0    0    2
+0          -0.50           1.00    0    0    2    0    2    0    0    1    0    0    0    0    0    0
+0          -0.50           1.00    0    0    0    0    0    0    0    1   -8    3    0    0    0   -2
+0           0.20          -1.30    0    0    0    0    0    0    0    1    0   -4    0    0    0   -2
+0           0.00           1.50    1    1   -2   -4   -1    0    0    0    0    0    0    0    0    0
+0           0.00           1.50    1    0    0   -1   -2    0    0    0    0    0    0    0    0    0
+0           0.00           1.50    0    0    0    0    1    0    1   -1    0    0    0    0    0    0
+0           0.00           1.49    2    0    2   -4    2    0    0    0    0    0    0    0    0    0
+0           0.00          -1.41    2    0    2    0    0    0    0    0    0    0    0    0    0    0
+0           0.00           1.41    0    1    0    2    0    0    0    0    0    0    0    0    0    0
+0           0.00          -1.40    0    0    2   -3    1    0    0    0    0    0    0    0    0    0
+0           0.00          -1.40    1   -2   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.00           1.40    1    0   -2   -6   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -1.40    0    0    2   -2    1    0   -4    4    0    0    0    0    0    0
+0           1.10          -0.30    0    0    1   -1    1    0   -1    0    0    0    0    0    0    0
+0           0.00          -1.40    3    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           1.40    1    0    2    4    1    0    0    0    0    0    0    0    0    0
+0           1.40           0.00    0    0    1    0    2    0    0    0    0    0    0    0    0    0
+0          -0.30           1.10    0    0    0    0    1    0   -3    5    0    0    0    0    0    0
+0           0.20           1.20    2   -1    0   -2    0    0    0    0    0    0    0    0    0    0
+0          -1.30           0.00    1    0    0   -1   -1    0   -3    4    0    0    0    0    0    0
+0           0.00          -1.30    1   -1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0           0.00           1.30    1   -2    2    2    2    0    0    0    0    0    0    0    0    0
+0          -0.70          -0.60    0    0    1   -1    1    0    8  -14    0    0    0    0    0    0
+0          -0.80           0.50    0    0    1   -1    1    0    3   -6    0    0    0    0    0    0
+0          -0.20          -1.10    0    0    0    0    0    0    6  -10    0    0    0    0    0   -2
+0           1.10           0.20    0    0    0    0    0    0    0    2    0   -2    0    0    0    1
+0           0.00          -1.30    3    1    2   -2    2    0    0    0    0    0    0    0    0    0
+0           0.00          -1.30    1    0   -4   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -1.30    0    0    0    0    0    0    3   -1    0    0    0    0    0    2
+0           0.00          -1.30    0    0    0    0    0    0    0    3    0    0   -1    0    0    2
+0           0.00          -1.29    0    0    2   -4    2    0    0    0    0    0    0    0    0    0
+0           0.00           1.20    1    2    0   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00          -1.20    2    1    0    0   -1    0    0    0    0    0    0    0    0    0
+0          -0.40          -0.80    0    0    0    0    1    0    0    8  -15    0    0    0    0    0
+0           0.00           1.20    2    0    2    4    2    0    0    0    0    0    0    0    0    0
+0           1.20           0.00    0    0    0    0    0    0    3   -6    0    0    0    0    0   -2
+0          -0.70          -0.50    0    0    1   -1    1    0    0   -3    4    0    0    0    0    0
+0          -1.00           0.20    0    0    0    0    0    0    6   -8    0    0    0    0    0   -1
+0          -1.00           0.20    0    0    0    0    0    0    2    1    0    0    0    0    0    2
+0           0.20          -1.00    0    0    0    0    0    0    2    1    0    0    0    0    0    1
+0           0.40           0.80    0    0    0    0    0    0    0    1   -4    0    0    0    0   -2
+0          -0.40           0.80    0    0    0    0    0    0    0    0    3    0    0    0    0    2
+0           0.00          -1.20    1    1    2    2    1    0    0    0    0    0    0    0    0    0
+0           0.00           1.15    0    0    0    0    3    0    0    0    0    0    0    0    0    0
+0           0.00           1.10    2    1    0    0    1    0    0    0    0    0    0    0    0    0
+0          -0.20           0.90    2    0    0   -2    1    0   -6    8    0    0    0    0    0    0
+0          -1.10           0.00    0    0    3    0    3    0    0    0    0    0    0    0    0    0
+0           0.00          -1.10    2    1    2    2    2    0    0    0    0    0    0    0    0    0
+0          -1.10           0.00    1    0    1    0    1    0    0    0    0    0    0    0    0    0
+0           0.00           1.10    2   -1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.00           1.10    3    0    2   -4    2    0    0    0    0    0    0    0    0    0
+0           0.00           1.10    0    0    0    0    0    0    0    7   -8    3    0    0    0    2
+0           0.60          -0.50    0    0    0    0    0    0    0    0    0    0    0    0    2    1
+0          -0.90          -0.20    0    0    0    0    0    0    5   -5    0    0    0    0    0   -1
+0          -0.40          -0.70    0    0    0    0    0    0    0    4   -7    0    0    0    0   -2
+0          -0.50           0.60    1   -2    2   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00           1.10    3    0    2    2    1    0    0    0    0    0    0    0    0    0
+0           0.00          -1.10    1   -1   -2    2   -2    0    0    0    0    0    0    0    0    0
+0           0.00           1.00    0    0    0    0    1    0   -1    1    0    0    0    0    0    0
+0           1.00           0.00    0    0    0    0    1    0   -2    3    0    0    0    0    0    0
+0           0.80          -0.20    0    0    0    0    1    0    0    0    0   -1    0    0    0    0
+0           0.00           1.00    1    0    0    1    1    0    0    0    0    0    0    0    0    0
+0           0.00           1.00    0    2    0   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00          -1.00    3    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+0          -1.00           0.00    1    0    1   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00           1.00    1   -1    2    4    2    0    0    0    0    0    0    0    0    0
+0           1.00           0.00    0    0    1   -1    1    0    0   -9   15    0    0    0    0    0
+0           1.00           0.00    0    0    0    0    0    0    7  -10    0    0    0    0    0   -2
+0          -0.80          -0.20    0    0    0    0    0    0    2    0    0    0    0    0    0    1
+0           0.40           0.60    0    0    0    0    0    0    3   -5    4    0    0    0    0    2
+0          -0.40          -0.60    0    0    0    0    0    0    3   -9    4    0    0    0    0   -2
+0           0.00          -1.00    1    0    4    0    2    0    0    0    0    0    0    0    0    0
+0           0.00           1.00    0    1    2   -4    1    0    0    0    0    0    0    0    0    0
+0           0.00           1.00    1    0   -4    2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           1.00    0    2   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           1.00    2    0   -2    0    2    0    0    0    0    0    0    0    0    0
+0           0.00          -1.00    1    0    0    2    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.91    1    0    2   -2    0    0    0    0    0    0    0    0    0    0
+0           0.10           0.80    1   -1    0   -2    0    0    0    0    0    0    0    0    0    0
+0           0.00           0.90    1    0   -2   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.90    0    1    0   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.90    2    0    0   -2    1    0   -3    3    0    0    0    0    0    0
+0           0.00          -0.90    1    2    2    0    2    0    0    0    0    0    0    0    0    0
+0          -0.70          -0.20    0    0    0    0    0    0    6   -6    0    0    0    0    0   -1
+0           0.70          -0.20    0    0    0    0    0    0    1    2    0    0    0    0    0    2
+0          -0.30           0.60    0    0    0    0    0    0    0    8  -15    0    0    0    0   -2
+0           0.00           0.90    5    0    2    0    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.90    3    0   -2   -6   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.90    0    0    1   -1    1    0   -2    2    0    0    0    0    0    0
+0          -0.50          -0.40    0    0    0    0    0    0    0    3    0   -3    0    0    0    2
+0          -0.90           0.00    0    0    0    0    0    0    0    2    0    0   -1    0    0    2
+0           0.00          -0.90    1   -1    2   -1    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.90    1    0   -2    4   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.90    2    1   -2   -4   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.90    4    0    2   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.90    1   -1    0   -1    0    0    0    0    0    0    0    0    0    0
+0           0.00          -0.80    2   -1    0    0    0    0    0    0    0    0    0    0    0    0
+0           0.00           0.80    3    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.80    2   -1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0           0.10           0.70    0    0    0    0    0    0    7  -11    0    0    0    0    0   -2
+0          -0.70           0.10    0    0    0    0    0    0    2   -2    0    0    0    0    0    1
+0          -0.60           0.20    0    0    0    0    0    0    7   -9    0    0    0    0    0   -1
+0           0.20           0.60    0    0    0    0    0    0    4   -7    0    0    0    0    0   -1
+0           0.00           0.80    0    0    4   -4    1    0    0    0    0    0    0    0    0    0
+0          -0.50           0.30    0    0    0    0    0    0    3   -5    0    0    0    0    0    1
+0          -0.50          -0.30    0    0    0    0    0    0    0    5   -5    0    0    0    0    2
+0          -0.50          -0.30    0    0    0    0    0    0    0    5   -9    0    0    0    0   -2
+0           0.00          -0.80    0    0    0    0    0    0    0    3   -1    0    0    0    0    2
+0          -0.30           0.50    0    0    0    0    0    0    0    2    0    2   -5    0    0    2
+0          -0.80           0.00    0    0    0    0    0    0    0    2    0    0    1    0    0    2
+0          -0.30          -0.50    0    0    0    0    0    0    0    2    0   -2    5    0    0    2
+0          -0.30           0.50    0    0    0    0    1    0   -3    7   -4    0    0    0    0    0
+0          -0.30          -0.50    0    0    0    0    1    0    3   -7    4    0    0    0    0    0
+0           0.00           0.80    0    1    0   -4   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.80    3    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.80    1    0   -2   -3   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.80    0    1   -2    1   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.80    1    2   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.80    1    1    0   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.80    0    0    0    0    1    0    0    1    0   -1    0    0    0    0
+0           0.00           0.76    1    0    2    0    3    0    0    0    0    0    0    0    0    0
+0           0.00           0.70    3    0    0   -4    1    0    0    0    0    0    0    0    0    0
+0           0.10          -0.60    2    0    0   -2   -1    0   -6    8    0    0    0    0    0    0
+0           0.00           0.70    0    1   -4    2   -2    0    0    0    0    0    0    0    0    0
+0           0.70           0.00    0    0    1   -1    1    0    0   -1    0   -1    1    0    0    0
+0           0.00          -0.70    0    0    0    0    1    0    3   -5    0    2    0    0    0    0
+0           0.00          -0.70    0    1    2    4    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.70    4    0    2    2    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.70    2    0   -2   -3   -2    0    0    0    0    0    0    0    0    0
+0          -0.70           0.00    0    0    1   -1    1    0    2   -4    0   -3    0    0    0    0
+0          -0.50           0.20    0    0    1   -1    1    0    0   -1    0    3    0    0    0    0
+0          -0.20          -0.50    0    0    0    0    0    0    9   -9    0    0    0    0    0   -1
+0           0.50          -0.20    0    0    0    0    0    0    2   -3    0    0    0    0    0   -2
+0           0.20           0.50    0    0    0    0    0    0    0   11    0    0    0    0    0    2
+0          -0.20          -0.50    0    0    0    0    0    0    0    6  -15    0    0    0    0   -2
+0           0.50          -0.20    0    0    0    0    0    0    0    3    0    2   -5    0    0    2
+0          -0.50           0.20    0    0    0    0    0    0    0    3    0    1    0    0    0    2
+0           0.00          -0.70    0    0    0    0    0    0    0    3   -5    0    0    0    0   -2
+0           0.00          -0.70    0    0    0    0    0    0    0    2    0   -4    0    0    0   -2
+0           0.70           0.00    0    0    0    0    0    0    0    0    0    0    3    0    0    2
+0          -0.60          -0.10    0    0    0    0    0    0    3   -1    0    0    0    0    0    1
+0           0.60          -0.10    0    0    0    0    0    0    3   -3    0    0    0    0    0    1
+0           0.40           0.30    0    0    0    0    0    0    0    4   -8    0    0    0    0   -2
+0           0.00           0.70    1    0    0    1    0    0    0    0    0    0    0    0    0    0
+0           0.70           0.00    0    0    1   -1    2    0    0   -2    2    0    0    0    0    0
+0           0.00           0.70    2   -1    2    2    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.70    0    1   -2   -4   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.70    1   -1    0    0    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.60    0    0    0    0    1    0    0   -1    0    1    0    0    0    0
+0           0.00           0.60    0    0    2    2   -1    0    0    0    0    0    0    0    0    0
+0           0.10          -0.50    0    0    1   -1   -1    0    0    0   -2    0    0    0    0    0
+0           0.00           0.60    2    1    0    0    0    0    0    0    0    0    0    0    0    0
+0           0.40           0.20    0    0    0    0    1    0    0    2   -4    0    0    0    0    0
+0           0.00           0.60    1    0    0   -4   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.60    2    1    0   -4   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.60    1    1    0   -4    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.60    0    1    0    1    0    0    0    0    0    0    0    0    0    0
+0           0.00          -0.60    1   -1    2   -4    1    0    0    0    0    0    0    0    0    0
+0           0.50           0.10    0    0    1   -1    1    0   -2    3    0    0    0    0    0    0
+0          -0.50          -0.10    0    0    0    0    0    0    7   -7    0    0    0    0    0   -1
+0          -0.10          -0.50    0    0    0    0    0    0    4   -4    0    0    0    0    0    2
+0           0.10           0.50    0    0    0    0    0    0    1   -2    0    0    0    0    0    1
+0           0.50          -0.10    0    0    0    0    0    0    0    5    0   -2    0    0    0    2
+0          -0.10           0.50    0    0    0    0    0    0    0    3   -6    0    0    0    0   -1
+0           0.00          -0.60    2    0    0   -2   -1    0    0   -2    0    0    5    0    0    0
+0          -0.40           0.20    2    0   -1   -1   -1    0    0   -1    0    3    0    0    0    0
+0           0.00          -0.60    1    0   -2   -2   -2    0    0   -2    0    2    0    0    0    0
+0           0.60           0.00    0    0    2   -2    2    0   -8   11    0    0    0    0    0    0
+0           0.00          -0.60    0    0    2   -2    1    0   -2    2    0    0    0    0    0    0
+0           0.20           0.40    0    0    1   -1    1    0    0   -1    0    0    3    0    0    0
+0          -0.40           0.20    0    0    0    0    0    1    0   -4    0    0    0    0    0   -2
+0           0.30           0.30    0    0    0    0    0    0    8  -13    0    0    0    0    0    1
+0           0.40          -0.20    0    0    0    0    0    0    0    6    0    0    0    0    0    2
+0          -0.40          -0.20    0    0    0    0    0    0    0    6   -6    0    0    0    0    2
+0           0.00           0.60    0    0    0    0    0    0    0    1    1    0    0    0    0    2
+0           0.00           0.60    0    0    0    0    0    0    0    1    0    0    1    0    0    2
+0           0.40           0.20    0    0    0    0    0    0    0    1   -5    0    0    0    0   -2
+0          -0.20          -0.40    0    0    0    0    0    0    0    0    0    0    3    0    0    1
+0           0.00           0.60    4    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.60    0    0    0    3    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.60    3    0    0    2    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.60    1    1    0   -4   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.60    0    0    0    1    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.60    1    1    0   -2    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.60    2    0   -2    2   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.50    1    1    0   -4    0    0    0    0    0    0    0    0    0    0
+0           0.00           0.50    2    0    2    0   -1    0    0    0    0    0    0    0    0    0
+0           0.10           0.40    2    1    0   -2    0    0    0    0    0    0    0    0    0    0
+0           0.00          -0.50    0    1    0    2    2    0    0    0    0    0    0    0    0    0
+0           0.10           0.40    0    0    0    0    1    0    3   -5    0    0    0    0    0    0
+0           0.00           0.50    1   -2    2   -2    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.50    2    1    0   -4    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.50    1   -2    0    0    1    0    0    0    0    0    0    0    0    0
+0           0.30          -0.20    2    0    0   -2    1    0    0   -6    8    0    0    0    0    0
+0          -0.20           0.30    2    0    0   -2   -1    0    0   -5    6    0    0    0    0    0
+0           0.20           0.30    2    0   -1   -1   -1    0    0    3   -7    0    0    0    0    0
+0           0.40          -0.10    0    0    2    0    2    0    0   -4    8   -3    0    0    0    0
+0           0.40           0.10    0    0    2    0    2    0    0    4   -8    3    0    0    0    0
+0           0.00          -0.50    0    1   -2   -1   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.50    3   -1    2   -2    2    0    0    0    0    0    0    0    0    0
+0           0.30           0.20    0    0    0    0    0    0    1    0    0    0    0    0    0    2
+0          -0.30           0.20    0    0    0    0    0    0    0    7  -13    0    0    0    0   -2
+0           0.20           0.30    0    0    0    0    0    0    0    2   -5    0    0    0    0   -2
+0          -0.30           0.20    0    0    0    0    0    0    0    1    0    3    0    0    0    2
+0           0.00           0.50    3   -1    2    2    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.50    3   -1   -2   -1   -2    0    0    0    0    0    0    0    0    0
+0           0.00           0.50    0    0    2    6    2    0    0    0    0    0    0    0    0    0
+0          -0.50           0.00    0    0    1   -1    1    0    0    1    0    0    0    0    0    0
+0           0.50           0.00    0    0    0    0    0    0    9  -12    0    0    0    0    0   -2
+0           0.00          -0.50    0    0    0    0    0    0    6   -9    0    0    0    0    0   -1
+0          -0.50           0.00    0    0    0    0    0    0    4   -4    0    0    0    0    0    1
+0          -0.50           0.00    0    0    0    0    0    0    0    6  -11    0    0    0    0   -2
+0           0.00           0.50    0    0    0    0    0    0    0    1   -3    0    0    0    0   -2
+0           0.40           0.10    0    0    2   -2    1   -1    0    2    0    0    0    0    0    0
+0          -0.40          -0.10    0    0    1   -1    1    0    0   -1    0    0    0    2    0    0
+0           0.40          -0.10    0    0    0    0    0    0    5   -6    0    0    0    0    0    2
+0          -0.40           0.10    0    0    0    0    0    0    5  -10    0    0    0    0    0   -2
+0           0.10           0.40    0    0    0    0    0    0    0    5    0   -3    0    0    0    2
+0           0.10           0.40    0    0    0    0    0    0    0    0    0    4    0    0    0    2
+0          -0.50           0.00    0    0    3    0    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.50    2    0   -4    0   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.50    2    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.50    0    0    2   -2    2    0   -3    3    0    0    0    0    0    0
+0           0.00           0.50    1    0    0   -1    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.50    1    1    0    0    2    0    0    0    0    0    0    0    0    0
+0           0.50           0.00    0    0    2   -2    2    0   -5    6    0    0    0    0    0    0
+0           0.00          -0.50    1    0    0    2   -2    0    0    0    0    0    0    0    0    0
+0           0.00           0.50    1    0   -2    2    0    0    0    0    0    0    0    0    0    0
+0           0.00          -0.40    1    0    2    2    0    0    0    0    0    0    0    0    0    0
+0          -0.20           0.20    0    0    0    0    2    0    0   -1    2    0    0    0    0    0
+0          -0.10           0.30    1    1    0    2    0    0    0    0    0    0    0    0    0    0
+0           0.00          -0.40    1    0    0    4    0    0    0    0    0    0    0    0    0    0
+0           0.40           0.00    1    0   -1    0    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.40    0    2    0   -2    0    0    0    0    0    0    0    0    0    0
+0           0.00          -0.40    1    0    0   -3    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.40    4    0    0    0   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.40    1   -2    0   -2   -1    0    0    0    0    0    0    0    0    0
+0          -0.10           0.30    0    0    0    0    1    0    0   -8   15    0    0    0    0    0
+0           0.00           0.40    1    0    4   -4    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.40    1    1    0   -1    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.40    0    0    2    0    2    0    1   -1    0    0    0    0    0    0
+0           0.00          -0.40    1    1    0    2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.40    2   -2    2    0    2    0    0    0    0    0    0    0    0    0
+0          -0.20          -0.20    0    0    1   -1    1    0    0   -1    0    0   -2    0    0    0
+0           0.20          -0.20    0    0    1   -1    1    0    0   -1    0   -2    4    0    0    0
+0           0.20           0.20    0    0    0    0    0    0    0    2    2    0    0    0    0    2
+0          -0.10           0.30    2   -2    2   -2    2    0    0    0    0    0    0    0    0    0
+0          -0.30           0.10    0    0    0    0    0    0    6  -10    0    0    0    0    0   -1
+0           0.10           0.30    0    0    0    0    0    0    0    6   -5    0    0    0    0    2
+0          -0.10           0.30    0    0    0    0    0    0    0    2    0   -2    0    0    0    2
+0           0.00          -0.40    5    0    2   -2    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.40    3    0    2   -1    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.40    1    2   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0           0.00           0.40    1   -1   -2   -3   -2    0    0    0    0    0    0    0    0    0
+0           0.00           0.40    0    0    4   -1    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.40    0    0    2   -2    1    0    0   -2    0    3    0    0    0    0
+0           0.00          -0.40    0    0    2   -2    1    0    0   -2    0    0    2    0    0    0
+0           0.40           0.00    0    0    2   -2    1    0    0   -8   11    0    0    0    0    0
+0          -0.40           0.00    0    0    1   -1    1    0    0   -1    0   -1    2    0    0    0
+0          -0.40           0.00    0    0    0    0    0    0    8   -8    0    0    0    0    0   -1
+0          -0.40           0.00    0    0    0    0    0    0    8  -10    0    0    0    0    0   -1
+0           0.00           0.40    0    0    0    0    0    0    5   -5    0    0    0    0    0    2
+0           0.00          -0.40    0    0    0    0    0    0    5   -9    0    0    0    0    0   -2
+0           0.00          -0.40    0    0    0    0    0    0    4   -2    0    0    0    0    0    2
+0          -0.40           0.00    0    0    0    0    0    0    4   -2    0    0    0    0    0    1
+0           0.40           0.00    0    0    0    0    0    0    4   -3    0    0    0    0    0    2
+0           0.00          -0.40    0    0    0    0    0    0    3   -4    0    0    0    0    0   -1
+0           0.00           0.40    0    0    0    0    0    0    3   -6    0    0    0    0    0   -1
+0           0.00           0.40    0    0    0    0    0    0    2   -6    0    0    0    0    0   -2
+0           0.40           0.00    0    0    0    0    0    0    0    8  -15    0    0    0    0   -1
+0           0.00          -0.40    0    0    0    0    0    0    0    6    0    0    0    0    0    0
+0          -0.40           0.00    0    0    0    0    0    0    0    5   -2    0    0    0    0    2
+0           0.00           0.40    0    0    0    0    0    0    0    5   -3    0    0    0    0    2
+0           0.40           0.00    0    0    0    0    0    0    0    0    0    0    1    0    0    2
+0           0.00          -0.40    4    0    0    0    0    0    0    0    0    0    0    0    0    0
+0           0.00          -0.40    1   -2   -2    0   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.40    1    2    2   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.40    0    2    2    0    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.40    3    1    2    0    1    0    0    0    0    0    0    0    0    0
+0          -0.10           0.30    0    2   -2    0   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.40    1    1    2    1    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.40    3   -1    2    0    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.40    2    0    2   -1    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.40    2    0    0    2    2    0    0    0    0    0    0    0    0    0
+0           0.40           0.00    0    0    1   -1    2    0    0   -1    0    2    0    0    0    0
+0           0.00           0.40    0    0    2   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.21           0.10    0    0    1   -1    2    0    0   -1    0   -2    5    0    0    0
+0           0.00           0.30    2    0   -4    2   -2    0    0    0    0    0    0    0    0    0
+0          -0.30           0.00    0    0    2   -2   -1    0   -5    6    0    0    0    0    0    0
+0           0.00          -0.30    2   -2    0   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.30    0    0    0    4    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.30    2    0    0   -2   -1    0   -3    3    0    0    0    0    0    0
+0           0.20           0.10    0    0    1   -1   -1    0    0   -1    0   -1    0    0    0    0
+0           0.00          -0.30    1   -2    0   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.30    1   -2    0    0   -1    0    0    0    0    0    0    0    0    0
+0           0.30           0.00    0    0    0    0    1    0    0    0    0    0   -1    0    0    0
+0           0.00           0.30    2    0    0   -3   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.30    2    1   -2    0    1    0    0    0    0    0    0    0    0    0
+0          -0.20           0.10    2    0    0   -2   -1    0    0   -6    8    0    0    0    0    0
+0          -0.10          -0.20    2    0   -1   -1    1    0    0    3   -7    0    0    0    0    0
+0           0.00          -0.30    2    1    2   -4    1    0    0    0    0    0    0    0    0    0
+0           0.10          -0.20    1    0    0   -1    1    0    0   -3    4    0    0    0    0    0
+0           0.00           0.30    2   -1   -2    0   -2    0    0    0    0    0    0    0    0    0
+0           0.00           0.30    0    0    2    0    2    0   -1    1    0    0    0    0    0    0
+0           0.00          -0.30    0    0    2    0    2    0    0   -1    0    1    0    0    0    0
+0           0.00           0.30    0    0    2    0    2    0    0    1    0   -1    0    0    0    0
+0           0.00           0.30    0    1    0   -4    1    0    0    0    0    0    0    0    0    0
+0          -0.20           0.10    0    0    0    0    1    0    0   -9   17    0    0    0    0    0
+0           0.00          -0.30    1    1    4   -2    2    0    0    0    0    0    0    0    0    0
+0          -0.10          -0.20    2    0    2    0    1    0    0    1    0    0    0    0    0    0
+0          -0.10           0.20    1    0   -2    0   -2    0  -10    3    0    0    0    0    0    0
+0           0.20          -0.10    0    0    2   -2    1    0    0   -7    9    0    0    0    0    0
+0          -0.10          -0.20    0    0    0    0    0    0    2   -3    0    0    0    0    0    1
+0           0.20           0.10    0    0    0    0    0    0    1   -2    0    0    0    0    0   -2
+0           0.20          -0.10    0    0    0    0    0    0    1   -4    0    0    0    0    0   -2
+0          -0.20          -0.10    0    0    0    0    0    0    0    6  -10    0    0    0    0   -2
+0          -0.10          -0.20    0    0    0    0    0    0    0    5   -8    0    0    0    0   -2
+0           0.20          -0.10    0    0    0    0    0    0    0    3   -5    0    0    0    0   -1
+0           0.20           0.10    0    0    0    0    0    0    0    2   -6    0    0    0    0   -2
+0           0.00           0.30    4    0    2   -4    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.30    2    2    2   -2    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.30    2    1    2    1    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.30    2    0    0   -2   -1    0    0   -2    0    4   -5    0    0    0
+0           0.00          -0.30    2    0    0   -2   -2    0   -3    3    0    0    0    0    0    0
+0           0.30           0.00    2    0   -1   -1   -1    0    0   -1    0    0    0    0    0    0
+0           0.00          -0.30    1    0    2    3    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.30    1    0    2   -2    2    0    0   -2    0    2    0    0    0    0
+0           0.30           0.00    1    0    1   -1    1    0    0   -1    0    0    0    0    0    0
+0           0.30           0.00    1    0   -1    1   -1    0  -18   17    0    0    0    0    0    0
+0           0.00          -0.30    1    0   -1   -1   -1    0   20  -20    0    0    0    0    0    0
+0           0.00          -0.30    1    0   -2   -2   -2    0   -3    3    0    0    0    0    0    0
+0           0.00          -0.30    0    2    2    2    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.30    0    2   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0           0.00           0.30    0    1    2    3    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.30    0    0    2   -2    1    0    0   -1    0    1    0    0    0    0
+0           0.30           0.00    0    0    1   -1    1    0    1   -2    0    0    0    0    0    0
+0           0.30           0.00    0    0    1   -1    1    0   -2    1    0    0    0    0    0    0
+0          -0.30           0.00    0    0    0    0    0    0    9  -11    0    0    0    0    0   -1
+0           0.00           0.30    0    0    0    0    0    0    8  -16    0    0    0    0    0   -2
+0          -0.30           0.00    0    0    0    0    0    0    5   -3    0    0    0    0    0    1
+0           0.30           0.00    0    0    0    0    0    0    0    6    0    0    0    0    0    1
+0          -0.30           0.00    0    0    0    0    0    0    0    6   -7    0    0    0    0    2
+0           0.00           0.30    0    0    0    0    0    0    0    4    0    0   -2    0    0    2
+0           0.30           0.00    0    0    0    0    0    0    0    4   -8    1    5    0    0   -2
+0          -0.30           0.00    0    0    0    0    0    0    0    3    0    0   -2    0    0    2
+0           0.30           0.00    0    0    0    0    0    0    0    1    0   -1    0    0    0    1
+0           0.30           0.00    0    0    0    0    0    0    0    1    0   -3    0    0    0   -1
+0           0.30           0.00    0    0    0    0    0    0    0    1   -6    0    0    0    0   -2
+0           0.00          -0.30    0    0    0    0    0    0    0    0    0    4   -5    0    0    2
+0           0.00           0.30    0    0    0    0    0    0    0    0    0    0    5    0    0    2
+0           0.00           0.30    0    0    0    0    0    0    0    0    0    0    0    2    0    2
+0           0.30           0.00    0    0    0    0    0    0    0    0    0    0    0    2    0    1
+0           0.00           0.30    0    0    0    0    0    0    0    0    0    0    0    0    2    2
+0           0.00          -0.30    1    0    0   -1   -1    0    0   -2    2    0    0    0    0    0
+0           0.00          -0.30    2   -1    2   -1    2    0    0    0    0    0    0    0    0    0
+0           0.30           0.00    2    0   -1   -1   -1    0    0   -1    0    2    0    0    0    0
+0           0.00           0.30    1    0    0   -6   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.30    1   -1    0   -4   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.30    1    0    0    4   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.30    3    0    0   -2    1    0    0    0    0    0    0    0    0    0
+0           0.30           0.00    0    0    0    0    1    0    5   -8    0    0    0    0    0    0
+0           0.00          -0.30    1   -2   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.30    0    1    4   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.30    2    0    4   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.30    0    0    2    3    1    0    0    0    0    0    0    0    0    0
+0           0.30           0.00    0    0    1   -1    2    0    0   -1    0    1    0    0    0    0
+0           0.00           0.30    1   -2    2    0    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.30    2   -1    2   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.30    2    0   -2   -6   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.30    2    0   -4   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.30    2    0    2    1    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.30    0    0    1   -1    2    0    0    0   -2    0    0    0    0    0
+0          -0.30           0.00    0    0    0    0    2    0    0    4   -8    3    0    0    0    0
+0          -0.30           0.00    0    0    0    0    2    0    0   -4    8   -3    0    0    0    0
+0           0.00           0.30    0    0    0    1   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.30    0    0    2    0   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.30    0    1    0   -2    2    0    0    0    0    0    0    0    0    0
+0          -0.20          -0.10    0    0    0    0    1    0    0    1    0   -2    0    0    0    0
+0           0.00          -0.30    0    0    0    0    1    0    2   -2    0    0    0    0    0    0
+0           0.00          -0.30    1    1    2   -4    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.21    0    1    2   -2    3    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    2    0    2   -2    0    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    0    0    0    0    1    0   -2    2    0    0    0    0    0    0
+0           0.00          -0.20    3    0    2    0    0    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    0    0    0    0    1    0    0   -2    2    0    0    0    0    0
+0           0.00          -0.20    0    1    0   -4    0    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    0    0    0    0    1    0   -3    4    0    0    0    0    0    0
+0           0.00          -0.20    3    0    0    2    0    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    0    3    0    0    0    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    2    0   -2   -2    0    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    2    0    2   -4    0    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    1    0    0   -3   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    2    0    2   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    1    0    2   -4   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    0    0    1   -1    2    0    0   -1    0    0    1    0    0    0
+0           0.00           0.20    1    0   -2    1    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    1    2    0   -2    0    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    2    0   -2   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    1    0    0   -1    1    0    0   -1    0    1    0    0    0    0
+0           0.00          -0.20    2    0    0   -3    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    1    1    0    1    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    1    1    0    1   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    2    0    0   -1    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    1    2    0    0    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    2    0    0   -2    1    0    0   -5    6    0    0    0    0    0
+0           0.00           0.20    1    0    0   -2   -1    0    0   -2    0    2    0    0    0    0
+0           0.00          -0.20    1    0    0   -2    1    0    0   -2    0    2    0    0    0    0
+0           0.00           0.20    2    0   -4    2   -1    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    0    0    2   -2    1    0    0    4   -8    3    0    0    0    0
+0           0.20           0.00    0    0    2   -2    1    0    0   -4    8   -3    0    0    0    0
+0           0.00           0.20    2   -1    0    2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    1    0    0   -1   -1    0    0   -3    4    0    0    0    0    0
+0           0.10          -0.10    1   -2    0   -2    0    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    2    0    0   -2   -1    0    0   -2    0    3   -1    0    0    0
+0           0.00           0.20    1   -1   -4    2   -2    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    3    0    0    2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    1    0    0   -3    0    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    2    0    2   -6    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    2   -1   -2    2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    1   -2   -2    2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    2    0    4   -4    2    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    2    0   -1   -1   -2    0    0   -1    0    2    0    0    0    0
+0           0.00          -0.20    4    1    2    0    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    4   -1    2    0    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    4   -1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    3    0    4   -2    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    3    0    2    1    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    3    0   -2    2   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    3    0   -2   -1   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    2    2   -2   -4   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    2    1    0   -4    0    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    2    1   -2   -6   -2    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    2    0    2   -3    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    2   -2    2    2    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    1    1    2    4    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    1    1   -2   -3   -2    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    1    1   -2   -6   -2    0    0    0    0    0    0    0    0    0
+0          -0.20           0.00    1    0    3    0    3    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    1    0    1    1    1    0    0    1    0    0    0    0    0    0
+0           0.20           0.00    1    0   -1    1   -1    0    0    1    0    0    0    0    0    0
+0           0.00           0.20    1    0   -1    0   -1    0   -3    5    0    0    0    0    0    0
+0           0.20           0.00    1    0   -1   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    1    0   -2   -2   -2    0    0   -2    0    3    0    0    0    0
+0           0.00          -0.20    1   -1    2    1    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    1   -1   -2    1   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    0    3   -2   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    0    0    4    2    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    0    0    2   -2    1    0    0    1    0   -1    0    0    0    0
+0           0.00           0.20    0    0    2   -2    1    0    0   -2    0    0    0    0    0    0
+0           0.00          -0.20    0    0    2   -2    1    0    0   -3    0    3    0    0    0    0
+0           0.00          -0.20    0    0    2   -2    1    0    0   -4    4    0    0    0    0    0
+0           0.00          -0.20    0    0    2   -2    1    0   -5    5    0    0    0    0    0    0
+0           0.00           0.20    0    0    1   -1    1    0    1   -3    0    0    0    0    0    0
+0           0.00          -0.20    0    0    1   -1    1    0    0    1   -4    0    0    0    0    0
+0           0.20           0.00    0    0    1   -1    1    0    0   -1    0    1   -3    0    0    0
+0           0.20           0.00    0    0    1   -1    1    0    0   -1    0    0    0   -1    0    0
+0           0.00          -0.20    0    0    1   -1    1    0    0   -4    6    0    0    0    0    0
+0           0.20           0.00    0    0    1   -1    1    0   -5    6    0    0    0    0    0    0
+0           0.00           0.20    0    0    0    0    0    0    8  -12    0    0    0    0    0   -2
+0           0.00          -0.20    0    0    0    0    0    0    7  -10    0    0    0    0    0   -1
+0           0.20           0.00    0    0    0    0    0    0    7  -11    0    0    0    0    0   -1
+0          -0.20           0.00    0    0    0    0    0    0    6   -4    0    0    0    0    0    1
+0          -0.20           0.00    0    0    0    0    0    0    6   -6    0    0    0    0    0    1
+0          -0.20           0.00    0    0    0    0    0    0    5   -5    0    0    0    0    0    1
+0           0.00          -0.20    0    0    0    0    0    0    5   -6    0    0    0    0    0   -1
+0          -0.20           0.00    0    0    0    0    0    0    4   -2    0    0    0    0    0    0
+0           0.00          -0.20    0    0    0    0    0    0    4   -5    0    0    0    0    0   -1
+0           0.20           0.00    0    0    0    0    0    0    4   -5    0    0    0    0    0   -2
+0           0.00          -0.20    0    0    0    0    0    0    3   -4    0    0    0    0    0    1
+0           0.20           0.00    0    0    0    0    0    0    3   -4    0    0    0    0    0   -2
+0          -0.20           0.00    0    0    0    0    0    0    3   -8    0    0    0    0    0   -2
+0           0.00           0.20    0    0    0    0    0    0    2   -5    0    0    0    0    0   -1
+0           0.00           0.20    0    0    0    0    0    0    1   -2    0    0    0    0    0   -1
+0           0.00           0.20    0    0    0    0    0    0    1   -4    0    0    0    0    0   -1
+0           0.00          -0.20    0    0    0    0    0    0    0    9  -17    0    0    0    0   -2
+0          -0.20           0.00    0    0    0    0    0    0    0    7   -7    0    0    0    0    2
+0          -0.20           0.00    0    0    0    0    0    0    0    7   -8    0    0    0    0    2
+0          -0.20           0.00    0    0    0    0    0    0    0    7   -9    0    0    0    0    2
+0          -0.20           0.00    0    0    0    0    0    0    0    5   -6    0    0    0    0    2
+0           0.20           0.00    0    0    0    0    0    0    0    5  -10    0    0    0    0   -2
+0           0.00           0.20    0    0    0    0    0    0    0    4    0   -4    0    0    0    2
+0           0.00          -0.20    0    0    0    0    0    0    0    4   -6    0    0    0    0   -2
+0           0.00          -0.20    0    0    0    0    0    0    0    4   -7    0    0    0    0   -1
+0           0.00          -0.20    0    0    0    0    0    0    0    4   -8    3    0    0    0    1
+0           0.00           0.20    0    0    0    0    0    0    0    4   -8    3    0    0    0   -1
+0           0.20           0.00    0    0    0    0    0    0    0    4   -8    1    5    0    0    2
+0           0.20           0.00    0    0    0    0    0    0    0    3    0    0    0    0    0    2
+0           0.00           0.20    0    0    0    0    0    0    0    3   -8    3    0    0    0   -2
+0           0.20           0.00    0    0    0    0    0    0    0    2    0    0   -2    0    0    1
+0           0.00          -0.20    0    0    0    0    0    0    0    2    0   -5    0    0    0   -2
+0           0.00          -0.20    0    0    0    0    0    0    0    2   -4    0    0    0    0    1
+0           0.20           0.00    0    0    0    0    0    0    0    2   -7    0    0    0    0   -2
+0           0.20           0.00    0    0    0    0    0    0    0    1    0    1    0    0    0    1
+0           0.00           0.20    0    0    0    0    0    0    0    1    0    0    0    0    0   -1
+0           0.20           0.00    0    0    0    0    0    0    0    1    0   -1    0    0    0   -1
+0           0.20           0.00    0    0    0    0    0    0    0    1    0   -2    5    0    0    2
+0           0.00           0.20    0    0    0    0    0    0    0    1    0   -2    0    0    0   -2
+0           0.00          -0.20    0    0    0    0    0    0    0    1    0   -5    0    0    0   -2
+0           0.10          -0.10    0    0    0    0    0    0    0    2    1    0    0    0    0    2
+0           0.00          -0.20    1    0    4    0    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    4    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    0    1    0    4    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    2    0    0    4    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    0    0    0    0    1    0    0    7  -13    0    0    0    0    0
+0           0.00          -0.20    2    1    0    2    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    1   -1    0    4    1    0    0    0    0    0    0    0    0    0
+0           0.20           0.00    0    0    2   -2    1    0   -8   11    0    0    0    0    0    0
+0           0.00           0.20    1    0    2   -6    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    0    0    2   -2    2    0    0   -2    0    2    0    0    0    0
+0           0.00          -0.20    1    2    2    0    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    3    0   -2   -6   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    2    0    0   -6   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    1   -1    2    4    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    2    1    2    2    1    0    0    0    0    0    0    0    0    0
+0          -0.20           0.00    0    0    1    1    2    0    0    1    0    0    0    0    0    0
+0           0.00           0.20    2   -1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    0    1   -2    4   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    2    0    2    4    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    1   -1   -2   -4   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    1    0   -4   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    1   -2    2    2    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    1    0   -2   -6   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    3    1    2   -2    1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    2   -2    0   -2   -2    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    2   -1    0    2    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    3    0    0    0    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    1   -1    2   -3    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    0    0    1   -1    2    0   -5    7    0    0    0    0    0    0
+0           0.00          -0.20    2    1    0   -2   -2    0    0    0    0    0    0    0    0    0
+0          -0.20           0.00    0    0    1   -1    2    0    0   -1    0   -1    0    0    0    0
+0           0.00          -0.20    2    1   -2    0    0    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    1    0   -2    0    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    1   -1    0    0   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.20    0    2    0    0    2    0    0    0    0    0    0    0    0    0
+0          -0.20           0.00    0    0    0    0    1    0    3   -4    0    0    0    0    0    0
+0           0.00          -0.20    0    0    0    0    1    0    0    2   -2    0    0    0    0    0
+0           0.00           0.20    0    0    0    0    1    0    0    2    0   -2    0    0    0    0
+0           0.00          -0.20    0    1    2   -4    2    0    0    0    0    0    0    0    0    0
+0           0.00           0.20    0    0    1   -1    2    0   -8   12    0    0    0    0    0    0
+0           0.00           0.20    1    1   -2    2   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.19    0    1    2   -2    0    0    0    0    0    0    0    0    0    0
+0           0.00           0.17    0    1   -2    2   -3    0    0    0    0    0    0    0    0    0
+0           0.00           0.11    1    0   -2    0   -3    0    0    0    0    0    0    0    0    0
+0           0.00          -0.10    1    1   -2   -2    0    0    0    0    0    0    0    0    0    0
+0           0.10           0.00    0    0    0    0    1    0    0   -1    0    2    0    0    0    0
+0           0.00          -0.10    0    1   -2   -2    0    0    0    0    0    0    0    0    0    0
+0           0.00           0.10    1    0    0    0   -1    0  -10    3    0    0    0    0    0    0
+0           0.00          -0.10    1    0    0    0    1    0  -10    3    0    0    0    0    0    0
+0           0.00          -0.10    1    0   -2   -4    0    0    0    0    0    0    0    0    0    0
+0           0.00          -0.10    2   -1    0    2    0    0    0    0    0    0    0    0    0    0
+0           0.00          -0.10    0    2    0    0   -2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.10    1    0    0   -6    0    0    0    0    0    0    0    0    0    0
+0           0.00           0.10    0    1    4   -4    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.10    2    0    0   -6    0    0    0    0    0    0    0    0    0    0
+0          -0.10           0.00    0    0    0    0    2    0    0    0    0    1    0    0    0    0
+0           0.00          -0.10    3    0    0   -4    0    0    0    0    0    0    0    0    0    0
+0           0.00          -0.10    2   -1   -2    0    1    0    0    0    0    0    0    0    0    0
+0           0.00           0.10    2    2    0   -2   -1    0    0    0    0    0    0    0    0    0
+0           0.00          -0.10    0    0    0    3    2    0    0    0    0    0    0    0    0    0
+0           0.00          -0.10    3   -1    0    0    0    0    0    0    0    0    0    0    0    0
+0           0.10           0.00    0    0    2    0    2    0    2   -3    0    0    0    0    0    0
+0           0.10           0.00    0    0    2    0    2    0   -2    3    0    0    0    0    0    0
+0           0.00           0.10    0    0    2    0    2    0    2   -2    0    0    0    0    0    0
+0           0.00          -0.10    0    0    2    0    2    0   -2    2    0    0    0    0    0    0
+0           0.00          -0.10    2   -1   -2    0    0    0    0    0    0    0    0    0    0    0
+0           0.00           0.10    2    0   -2   -2   -2    0    0   -2    0    2    0    0    0    0
+0           0.00           0.10    1    2    2   -4    1    0    0    0    0    0    0    0    0    0
+1      153041.82         878.89    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+1       11714.49        -289.32    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+1        2024.68         -50.99    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+1       -1837.33          47.75    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+1       -1312.21         -28.91    0    1    0    0    0    0    0    0    0    0    0    0    0    0
+1        -632.54           0.78    1    0    0    0    0    0    0    0    0    0    0    0    0    0
+1         459.68         -67.23    0    1    2   -2    2    0    0    0    0    0    0    0    0    0
+1         344.50           1.46    0    0    2    0    1    0    0    0    0    0    0    0    0    0
+1         268.14          -7.03    1    0    2    0    2    0    0    0    0    0    0    0    0    0
+1         192.06          29.80    0    1   -2    2   -2    0    0    0    0    0    0    0    0    0
+1         139.64           0.15    1    0    0   -2    0    0    0    0    0    0    0    0    0    0
+1        -113.94          -1.06    0    0    2   -2    1    0    0    0    0    0    0    0    0    0
+1         109.81           3.18    1    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+1         -56.37           0.13    0    0    0    2    0    0    0    0    0    0    0    0    0    0
+1         -56.17          -0.02    1    0    0    0    1    0    0    0    0    0    0    0    0    0
+1         -53.05          -1.23    1    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+1         -51.60           0.17    1    0    0    0   -1    0    0    0    0    0    0    0    0    0
+1          45.91          -0.11    1    0    2    0    1    0    0    0    0    0    0    0    0    0
+1         -42.45           0.02    2    0    0   -2    0    0    0    0    0    0    0    0    0    0
+1          40.82          -1.03    2    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+1          34.30          -1.24    0    0    2    2    2    0    0    0    0    0    0    0    0    0
+1          28.89           0.00    0    2   -2    2   -2    0    0    0    0    0    0    0    0    0
+1          27.61          -1.22    2    0    2    0    2    0    0    0    0    0    0    0    0    0
+1         -25.43           1.00    1    0    2   -2    2    0    0    0    0    0    0    0    0    0
+1         -26.01           0.07    2    0    0    0    0    0    0    0    0    0    0    0    0    0
+1         -23.02           0.06    0    0    2    0    0    0    0    0    0    0    0    0    0    0
+1          19.37          -0.01    0    0    2   -2    0    0    0    0    0    0    0    0    0    0
+1          14.05          -4.19    0    2    2   -2    2    0    0    0    0    0    0    0    0    0
+1          18.18          -0.01    1    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+1         -14.86          -0.09    0    2    0    0    0    0    0    0    0    0    0    0    0    0
+1          13.49          -0.01    1    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+1          12.44          -0.27    0    1    0    0    1    0    0    0    0    0    0    0    0    0
+1          11.46           0.03    1    0    0   -2    1    0    0    0    0    0    0    0    0    0
+1         -11.33          -0.06    0    1    0    0   -1    0    0    0    0    0    0    0    0    0
+1          -9.81           0.01    2    0   -2    0    0    0    0    0    0    0    0    0    0    0
+1          -9.08          -0.02    1    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+1           2.74          -4.56    0    0    1   -1    1    0    0   -1    0   -2    5    0    0    0
+1           6.84          -0.04    1    0    2    2    2    0    0    0    0    0    0    0    0    0
+1          -6.73           0.01    0    1    2    0    2    0    0    0    0    0    0    0    0    0
+1           6.54           0.01    1    1    0   -2    0    0    0    0    0    0    0    0    0    0
+1          -6.35          -0.01    0    1   -2    0   -2    0    0    0    0    0    0    0    0    0
+1           5.90          -0.02    0    0    2    2    1    0    0    0    0    0    0    0    0    0
+1          -5.85           0.02    1    0    0    2    0    0    0    0    0    0    0    0    0    0
+1          -5.73           0.01    2    0    2   -2    2    0    0    0    0    0    0    0    0    0
+1           5.60           0.00    0    0    0    2    1    0    0    0    0    0    0    0    0    0
+1          -5.16           0.00    1    0    2   -2    1    0    0    0    0    0    0    0    0    0
+1          -5.14           0.01    2    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+1           4.76          -0.02    2    0    2    0    1    0    0    0    0    0    0    0    0    0
+1          -4.40           0.02    0    0    0    2   -1    0    0    0    0    0    0    0    0    0
+1          -4.22           0.00    0    1   -2    2   -1    0    0    0    0    0    0    0    0    0
+1          -4.20           0.01    1   -1    0    0    0    0    0    0    0    0    0    0    0    0
+1           3.58           0.31    1    0    0   -1    0    0    0    0    0    0    0    0    0    0
+1           3.87           0.01    0    1    0   -2    0    0    0    0    0    0    0    0    0    0
+1           3.76           0.00    0    0    0    1    0    0    0    0    0    0    0    0    0    0
+1          -3.62          -0.01    2    0    0   -2    1    0    0    0    0    0    0    0    0    0
+1          -3.61           0.00    1    0   -2    0    0    0    0    0    0    0    0    0    0    0
+1          -1.28          -2.14    0    0    0    0    0    0    0    0    0    2   -5    0    0   -1
+1          -3.18           0.00    0    1    2   -2    1    0    0    0    0    0    0    0    0    0
+1           3.01           0.00    1    1    0    0    0    0    0    0    0    0    0    0    0    0
+1          -2.97           0.01    1    0    2    0    0    0    0    0    0    0    0    0    0    0
+1           2.91           0.00    1   -1    0   -1    0    0    0    0    0    0    0    0    0    0
+1          -2.73           0.00    2    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+1           2.58          -0.01    3    0    2    0    2    0    0    0    0    0    0    0    0    0
+1           2.56          -0.01    1   -1    2    0    2    0    0    0    0    0    0    0    0    0
+1          -2.51          -0.01    1    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+1          -2.35          -0.01    0    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+1          -2.21           0.01    1    1    2    0    2    0    0    0    0    0    0    0    0    0
+1          -2.04           0.01    2    0    0    0   -1    0    0    0    0    0    0    0    0    0
+1          -1.94           0.00    2    0    0    0    1    0    0    0    0    0    0    0    0    0
+1           0.41          -1.43    0    0    0    0    0    0    0    4   -8    3    0    0    0    0
+1          -1.84           0.00    0    0    0    0    0    0    3   -5    0    0    0    0    0   -2
+1          -1.77           0.01    1    0   -2    2   -1    0    0    0    0    0    0    0    0    0
+1           0.00           1.77    0    1   -1    1   -1    0    0    0    0    0    0    0    0    0
+1           1.76           0.00    1    0    0    0    2    0    0    0    0    0    0    0    0    0
+1          -1.07          -0.53    0    0    1   -1    1    0   -8   12    0    0    0    0    0    0
+1          -1.48           0.00    0    0    2    1    2    0    0    0    0    0    0    0    0    0
+1          -1.40           0.01    3    0    0    0    0    0    0    0    0    0    0    0    0    0
+1          -1.35          -0.01    1    0   -2   -4   -2    0    0    0    0    0    0    0    0    0
+1          -1.32           0.00    0    0    0    0    0    0    1   -1    0    0    0    0    0    0
+1          -1.28           0.00    0    0    0    0    0    0    0    8  -16    4    5    0    0    0
+1           1.24           0.00    1    0    0    0   -2    0    0    0    0    0    0    0    0    0
+1           1.23           0.00    2    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+1           1.19           0.00    1    0    0   -4    0    0    0    0    0    0    0    0    0    0
+1           1.18          -0.01    1    0    2    2    1    0    0    0    0    0    0    0    0    0
+1           1.17           0.00    1   -1    0   -1   -1    0    0    0    0    0    0    0    0    0
+1          -1.15           0.00    1    1    2   -2    2    0    0    0    0    0    0    0    0    0
+1           1.14           0.00    2    0    0   -4    0    0    0    0    0    0    0    0    0    0
+1          -1.14           0.00    0    2   -2    2   -1    0    0    0    0    0    0    0    0    0
+1           1.09           0.03    0    0    0    0    0    0    0    1    0   -1    0    0    0    0
+1          -1.08           0.00    2    0   -2   -4   -2    0    0    0    0    0    0    0    0    0
+1           1.04           0.00    0    0    0    0    0    0    0    0    0    2    0    0    0    2
+1           1.02           0.00    1    0   -4    0   -2    0    0    0    0    0    0    0    0    0
+1           0.98          -0.01    2    0    2    2    2    0    0    0    0    0    0    0    0    0
+1           0.91           0.02    1    0    0   -1   -1    0    0    0    0    0    0    0    0    0
+1           0.00           0.93    1    0   -1    0   -1    0    0    0    0    0    0    0    0    0
+1          -0.91           0.00    2    0    2   -2    1    0    0    0    0    0    0    0    0    0
+1          -0.90           0.00    2    1    0   -2    0    0    0    0    0    0    0    0    0    0
+1           0.86           0.00    1    0    0    2    1    0    0    0    0    0    0    0    0    0
+1          -0.84           0.00    1   -1    0   -2    0    0    0    0    0    0    0    0    0    0
+1          -0.83           0.00    3    0    2   -2    2    0    0    0    0    0    0    0    0    0
+1          -0.82           0.00    0    0    4   -2    2    0    0    0    0    0    0    0    0    0
+1           0.41           0.39    0    0    0    0    1    0    0   -1    2    0    0    0    0    0
+1           0.40          -0.38    0    0    0    0    0    0    0    1   -2    0    0    0    0    0
+1           0.78           0.00    0    1   -2    2    0    0    0    0    0    0    0    0    0    0
+1           0.74           0.00    0    0    2   -2   -1    0    0    0    0    0    0    0    0    0
+1          -0.73           0.00    0    1    2    0    1    0    0    0    0    0    0    0    0    0
+1           0.68           0.00    1    0    2   -2    0    0    0    0    0    0    0    0    0    0
+1           0.66           0.00    1    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+1          -0.64           0.00    2    0   -2    0    1    0    0    0    0    0    0    0    0    0
+1          -0.63           0.00    0    1    0    0    2    0    0    0    0    0    0    0    0    0
+1           0.63           0.00    0    0    2   -1    2    0    0    0    0    0    0    0    0    0
+1           0.62           0.00    0    0    2    4    2    0    0    0    0    0    0    0    0    0
+1           0.60           0.00    0    1    0    2    0    0    0    0    0    0    0    0    0    0
+1          -0.59           0.00    0    0    2    0   -1    0    0    0    0    0    0    0    0    0
+1          -0.59           0.00    0    1   -2    0   -1    0    0    0    0    0    0    0    0    0
+1           0.59           0.00    0    1    2   -2    0    0    0    0    0    0    0    0    0    0
+1           0.57           0.00    1    0   -2   -2    0    0    0    0    0    0    0    0    0    0
+1           0.38          -0.19    0    0    0    0    0    0    8  -13    0    0    0    0    0   -1
+1          -0.01          -0.55    0    0    0    0    0    0    2   -3    0    0    0    0    0    0
+1           0.44          -0.11    0    0    0    0    0    0    0    0    0    2   -5    0    0    0
+1           0.53           0.00    0    0    0    0    0    0    2   -2    0    0    0    0    0    0
+1          -0.53           0.00    1   -1    0   -1   -2    0    0    0    0    0    0    0    0    0
+1           0.52           0.00    1   -1    2    2    2    0    0    0    0    0    0    0    0    0
+1          -0.52           0.00    2    0    0    2    0    0    0    0    0    0    0    0    0    0
+1           0.53           0.00    0    1    0    0   -2    0    0    0    0    0    0    0    0    0
+1           0.52           0.00    1    1    0   -2    1    0    0    0    0    0    0    0    0    0
+1           0.51           0.00    1    0   -2    2    0    0    0    0    0    0    0    0    0    0
+1           0.51           0.00    1   -1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+1          -0.21          -0.30    0    0    0    0    0    0    8  -13    0    0    0    0    0    0
+1          -0.50           0.00    0    1    0    1    0    0    0    0    0    0    0    0    0    0
+1          -0.11           0.37    0    0    0    0    0    0    0    2   -8    3    0    0    0   -2
+1          -0.11           0.37    0    0    0    0    0    0    0    6   -8    3    0    0    0    2
+1          -0.48           0.00    0    1    2    2    2    0    0    0    0    0    0    0    0    0
+1          -0.46          -0.01    0    0    0    0    0    0    0    3    0   -1    0    0    0    2
+1          -0.47           0.00    1   -1    0    0    1    0    0    0    0    0    0    0    0    0
+1          -0.03           0.43    0    0    1   -1    1    0    0   -1    0    2   -5    0    0    0
+1           0.45           0.00    3    0    2    0    1    0    0    0    0    0    0    0    0    0
+1          -0.44           0.00    0    0    0    4    0    0    0    0    0    0    0    0    0    0
+1          -0.44           0.00    1    0    0    2   -1    0    0    0    0    0    0    0    0    0
+1          -0.44           0.00    1   -1    0    2    0    0    0    0    0    0    0    0    0    0
+1           0.43           0.00    2   -1    2    0    2    0    0    0    0    0    0    0    0    0
+1           0.44           0.00    0    0    0    0    0    0    4   -6    0    0    0    0    0   -2
+1           0.42           0.00    0    0    0    2    2    0    0    0    0    0    0    0    0    0
+1          -0.42           0.00    1    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+1           0.41           0.00    1   -1   -2    0   -2    0    0    0    0    0    0    0    0    0
+1          -0.41           0.00    0    0    0    0    0    0    2   -4    0    0    0    0    0   -2
+1           0.02           0.39    0    0    2   -2    1    0   -5    6    0    0    0    0    0    0
+1           0.40           0.00    1    0    2   -4    1    0    0    0    0    0    0    0    0    0
+1          -0.40           0.00    0    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+1          -0.39           0.00    2    0    0   -2    0    0    0   -2    0    2    0    0    0    0
+1           0.39           0.00    0    3    2   -2    2    0    0    0    0    0    0    0    0    0
+1           0.15          -0.24    0    0    0    0    0    0    0    1    0   -2    0    0    0    0
+1          -0.37          -0.01    0    0    0    0    0    0    0    2    0   -2    0    0    0    0
+1           0.37           0.00    1   -1    2    0    1    0    0    0    0    0    0    0    0    0
+1          -0.37           0.00    0    0    2    2    0    0    0    0    0    0    0    0    0    0
+1          -0.37           0.00    2    1    2    0    2    0    0    0    0    0    0    0    0    0
+1          -0.31           0.06    2    0    0   -2    0    0    0   -2    0    3    0    0    0    0
+1          -0.35           0.00    1    0    0   -2   -2    0    0    0    0    0    0    0    0    0
+1           0.35           0.00    0    0    0    1    1    0    0    0    0    0    0    0    0    0
+1          -0.07          -0.27    0    0    0    0    1    0    0   -4    8   -3    0    0    0    0
+1          -0.33           0.01    0    0    0    0    0    0    2    0    0    0    0    0    0    2
+1          -0.33           0.00    2   -1    0    0    0    0    0    0    0    0    0    0    0    0
+1           0.07          -0.26    0    0    0    0    1    0    0    4   -8    3    0    0    0    0
+1           0.33           0.00    0    0    0    0    0    0    0    2   -2    0    0    0    0    0
+1           0.00          -0.32    1    0   -1    0   -2    0    0    0    0    0    0    0    0    0
+1           0.32           0.00    1    1    0    0    1    0    0    0    0    0    0    0    0    0
+1          -0.32           0.00    1    1    2    0    1    0    0    0    0    0    0    0    0    0
+1           0.32           0.00    1    0   -2    2   -2    0    0    0    0    0    0    0    0    0
+1          -0.24          -0.07    0    0    1   -1    1    0    0    0   -2    0    0    0    0    0
+1           0.24           0.07    0    0    1   -1    0    0    0    0   -2    0    0    0    0    0
+1           0.30           0.00    0    0    0    0    0    0    1    1    0    0    0    0    0    2
+1           0.08          -0.22    0    0    0    0    0    0    0    0    0    1    0    0    0    0
+1          -0.30           0.00    1    0    2    1    2    0    0    0    0    0    0    0    0    0
+1          -0.30           0.00    2    0    2    0    0    0    0    0    0    0    0    0    0    0
+1           0.30           0.00    0    1    0   -2    1    0    0    0    0    0    0    0    0    0
+1           0.30           0.00    1    0    2   -1    2    0    0    0    0    0    0    0    0    0
+1           0.00          -0.29    0    0    0    0    0    0    3   -4    0    0    0    0    0    0
+1           0.00          -0.29    1    0   -1    0    0    0    0    0    0    0    0    0    0    0
+1           0.20          -0.09    1    0    0    0    0    0  -18   16    0    0    0    0    0    0
+1           0.29           0.00    1    0    0    1    0    0    0    0    0    0    0    0    0    0
+1          -0.05          -0.24    0    0    0    0    0    0    0    0    0    2    0    0    0    1
+1           0.29           0.00    0    0    0    1   -1    0    0    0    0    0    0    0    0    0
+1          -0.27           0.00    1    0    0   -2    2    0    0    0    0    0    0    0    0    0
+1          -0.19          -0.08    1    0    0    0    0    0  -10    3    0    0    0    0    0    0
+1          -0.27           0.00    1   -1    0    0   -1    0    0    0    0    0    0    0    0    0
+1           0.25           0.00    2    1    0    0    0    0    0    0    0    0    0    0    0    0
+1           0.25           0.00    2    0    0   -2   -1    0    0   -2    0    2    0    0    0    0
+1          -0.25           0.00    0    0    2    1    1    0    0    0    0    0    0    0    0    0
+1           0.25           0.00    1    2    0   -2    0    0    0    0    0    0    0    0    0    0
+1          -0.25           0.00    0    3    0    0    0    0    0    0    0    0    0    0    0    0
+1          -0.01           0.23    0    0    0    0    0    0    5   -8    0    0    0    0    0   -2
+1          -0.23           0.00    1    0   -2   -4   -1    0    0    0    0    0    0    0    0    0
+1           0.23           0.00    0    0    0    0    0    0    0    1    0    1    0    0    0    2
+1           0.23           0.00    4    0    2    0    2    0    0    0    0    0    0    0    0    0
+1          -0.15          -0.07    0    0    1   -1    1    0    0   -1    0    0   -1    0    0    0
+1          -0.23           0.00    1    0   -2    0    1    0    0    0    0    0    0    0    0    0
+1          -0.22           0.00    2    1    2   -2    2    0    0    0    0    0    0    0    0    0
+1           0.22           0.00    0    1    2    1    2    0    0    0    0    0    0    0    0    0
+1          -0.22           0.00    1    1    2   -2    1    0    0    0    0    0    0    0    0    0
+1          -0.22           0.00    1    0    4   -2    2    0    0    0    0    0    0    0    0    0
+1           0.04          -0.17    0    0    1   -1    1    0    0   -1    0   -1    0    0    0    0
+1          -0.01          -0.21    0    0    2   -2    0    0   -5    6    0    0    0    0    0    0
+1           0.08          -0.14    0    0    0    0    0    0    0    2   -4    0    0    0    0    0
+1          -0.01           0.19    0    0    0    0    0    0    0    0    0    2   -5    0    0    1
+1           0.21           0.00    2    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+1          -0.20           0.00    1    0   -2    1   -1    0    0    0    0    0    0    0    0    0
+1          -0.20           0.00    2   -2    0   -2    0    0    0    0    0    0    0    0    0    0
+1          -0.04          -0.16    0    0    0    0    0    0    8  -13    0    0    0    0    0   -2
+1           0.19           0.00    0    2    0   -2    0    0    0    0    0    0    0    0    0    0
+1           0.19           0.00    1    1    0    0   -1    0    0    0    0    0    0    0    0    0
+1          -0.19           0.00    2    0   -2   -4   -1    0    0    0    0    0    0    0    0    0
+1           0.18           0.00    0    0    0    0    0    0    5   -7    0    0    0    0    0   -2
+1          -0.18           0.00    0    1    0    2    1    0    0    0    0    0    0    0    0    0
+1           0.18           0.00    1    0   -4    0   -1    0    0    0    0    0    0    0    0    0
+1           0.17           0.00    2    0    2    2    1    0    0    0    0    0    0    0    0    0
+1          -0.12           0.06    1    0    2    0    2    0    0    1    0    0    0    0    0    0
+1           0.13          -0.04    0    0    0    0    0    0    3   -5    0    0    0    0    0    0
+1          -0.11           0.06    1    0   -2    0   -2    0    0    4   -8    3    0    0    0    0
+1           0.17           0.00    0    0    2   -3    2    0    0    0    0    0    0    0    0    0
+1           0.16           0.00    0    0    0    0    0    0    0    4    0   -2    0    0    0    2
+1          -0.17           0.00    0    0    4    0    2    0    0    0    0    0    0    0    0    0
+1          -0.17           0.00    1    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+1          -0.14           0.02    1    0    0   -1    1    0    0    0    0    0    0    0    0    0
+1           0.14           0.03    0    0    0    0    0    0    0    2    0   -1    0    0    0    2
+1           0.00           0.15    0    0    0    0    0    0    2   -1    0    0    0    0    0    2
+1          -0.15           0.00    1    1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+1          -0.14           0.01    0    0    0    0    0    0    0    2    0    1    0    0    0    2
+1           0.16           0.00    2    0    0   -2   -2    0    0    0    0    0    0    0    0    0
+1          -0.06           0.10    0    0    0    0    0    0    8  -11    0    0    0    0    0   -2
+1           0.05           0.10    0    0    0    0    0    0    0    8  -16    4    5    0    0   -2
+1           0.02           0.13    0    0    1   -1    1    0    0   -1    0    2    0    0    0    0
+1          -0.11           0.04    0    0    0    0    0    0    0    8  -16    4    5    0    0    2
+1          -0.12          -0.02    0    0    1   -1    1    0   -5    7    0    0    0    0    0    0
+1          -0.05          -0.10    0    0    0    0    0    0    0    0    0    0    2    0    0    1
+1           0.14           0.00    1    0    2    4    2    0    0    0    0    0    0    0    0    0
+1          -0.09           0.05    1    0    0   -2    0    0   19  -21    3    0    0    0    0    0
+1           0.00           0.14    0    0    1    0    1    0    0    0    0    0    0    0    0    0
+1           0.14           0.00    3    0    0   -4    0    0    0    0    0    0    0    0    0    0
+1          -0.14           0.00    1    1   -2    0   -2    0    0    0    0    0    0    0    0    0
+1           0.04           0.10    0    0    1   -1    1    0    0   -1    0    0    2    0    0    0
+1          -0.06           0.08    0    0    0    0    0    0    0    3    0   -2    0    0    0    2
+1           0.05           0.09    0    0    0    0    0    0    8  -15    0    0    0    0    0   -2
+1          -0.14           0.00    0    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+1           0.08           0.06    0    0    0    0    0    0    0    1    2    0    0    0    0    2
+1           0.14           0.00    0    0    0    4    1    0    0    0    0    0    0    0    0    0
+1           0.14           0.00    0    0    2   -4    1    0    0    0    0    0    0    0    0    0
+1           0.13           0.00    1    1    0   -4    0    0    0    0    0    0    0    0    0    0
+1          -0.07           0.06    0    0    0    0    0    0    0    3   -2    0    0    0    0    2
+1           0.11          -0.02    0    0    0    0    0    0    0    0    0    3    0    0    0    2
+1          -0.13           0.00    3    0    2   -2    1    0    0    0    0    0    0    0    0    0
+1          -0.13           0.00    0    0    0    0    0    0    0    4   -2    0    0    0    0    2
+1          -0.13           0.00    1    1    2    2    2    0    0    0    0    0    0    0    0    0
+1          -0.13           0.00    0    0    4   -2    1    0    0    0    0    0    0    0    0    0
+1          -0.12           0.00    2    0    0   -2    0    0   -3    3    0    0    0    0    0    0
+1           0.12           0.00    3    0    2    2    2    0    0    0    0    0    0    0    0    0
+1           0.12           0.00    0    0    0    0    0    0    0    0    0    0    2    0    0    2
+1          -0.12           0.00    2    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+1           0.00          -0.12    1    0    0   -1    0    0   -3    4    0    0    0    0    0    0
+1          -0.02          -0.09    0    0    0    0    0    0    4   -6    0    0    0    0    0   -1
+1           0.02          -0.09    0    0    0    0    0    0    1   -1    0    0    0    0    0   -1
+1          -0.11           0.00    0    2   -2   -2   -2    0    0    0    0    0    0    0    0    0
+1           0.11           0.00    2    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+1           0.07          -0.04    0    0    0    0    0    0    0    3   -4    0    0    0    0    0
+1           0.11           0.00    0    0    2    4    1    0    0    0    0    0    0    0    0    0
+1           0.11           0.00    0    0    0    2   -2    0    0    0    0    0    0    0    0    0
+1          -0.11           0.00    3    0    0    0   -1    0    0    0    0    0    0    0    0    0
+1           0.10           0.00    0    0    0    0    0    0    0    1    0   -3    0    0    0   -2
+1          -0.10           0.00    0    0    2   -2    1    0   -3    3    0    0    0    0    0    0
+1           0.10           0.00    0    0    0    0    0    0    6   -8    0    0    0    0    0   -2
+1           0.10           0.00    2    1    0   -4    0    0    0    0    0    0    0    0    0    0
+1           0.10           0.00    0    0    1   -1    1    0    0    3   -8    3    0    0    0    0
+1           0.00           0.10    0    0    0    0    0    0    3   -2    0    0    0    0    0    2
+1           0.00           0.10    0    0    0    0    0    0    2   -5    0    0    0    0    0   -2
+1          -0.10           0.00    4    0    2   -2    2    0    0    0    0    0    0    0    0    0
+1           0.10           0.00    2    0    0    2    1    0    0    0    0    0    0    0    0    0
+1          -0.10           0.00    1   -1    0   -2   -1    0    0    0    0    0    0    0    0    0
+1           0.10           0.00    0    0    0    0    0    0    1   -3    0    0    0    0    0   -2
+2         121.15       -2301.27    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+2          -0.98        -143.27    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+2          -0.27         -24.46    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+2           0.24          22.41    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+2          -1.19          -5.61    0    1    2   -2    2    0    0    0    0    0    0    0    0    0
+2           3.57          -1.83    0    1    0    0    0    0    0    0    0    0    0    0    0    0
+2           0.24          -5.02    0    0    2    0    1    0    0    0    0    0    0    0    0    0
+2          -0.04          -3.23    1    0    2    0    2    0    0    0    0    0    0    0    0    0
+2          -0.48           2.40    0    1   -2    2   -2    0    0    0    0    0    0    0    0    0
+2          -0.10           1.73    0    0    2   -2    1    0    0    0    0    0    0    0    0    0
+2          -0.01           1.33    1    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+2          -0.04           0.83    1    0    0    0    1    0    0    0    0    0    0    0    0    0
+2          -0.05          -0.79    1    0    0    0   -1    0    0    0    0    0    0    0    0    0
+2           0.03          -0.66    1    0    2    0    1    0    0    0    0    0    0    0    0    0
+2           0.00          -0.64    1    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+2           0.04           0.61    2    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+2          -0.01          -0.41    0    0    2    2    2    0    0    0    0    0    0    0    0    0
+2          -0.01           0.35    0    2   -2    2   -2    0    0    0    0    0    0    0    0    0
+2          -0.01          -0.33    2    0    2    0    2    0    0    0    0    0    0    0    0    0
+2           0.01           0.31    1    0    2   -2    2    0    0    0    0    0    0    0    0    0
+2           0.01           0.27    1    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+2          -0.07          -0.17    0    2    2   -2    2    0    0    0    0    0    0    0    0    0
+2           0.07           0.17    1    0    0    0    0    0    0    0    0    0    0    0    0    0
+2           0.02          -0.21    0    1    0    0    1    0    0    0    0    0    0    0    0    0
+2           0.01           0.20    1    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+2           0.01          -0.17    1    0    0   -2    1    0    0    0    0    0    0    0    0    0
+2           0.01          -0.16    0    1    0    0   -1    0    0    0    0    0    0    0    0    0
+2           0.00          -0.13    1    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+2          -0.07          -0.04    0    0    1   -1    1    0    0   -1    0   -2    5    0    0    0
+2           0.02           0.08    0    1    2    0    2    0    0    0    0    0    0    0    0    0
+3         -15.23          -1.62    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+3          -1.16          -0.01    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+3          -0.20           0.00    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+3           0.18           0.00    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+3           0.13           0.00    0    1    0    0    0    0    0    0    0    0    0    0    0    0
+4          -0.01           0.11    0    0    0    0    1    0    0    0    0    0    0    0    0    0
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2b.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2b.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2b.txt	(revision 22158)
@@ -0,0 +1,1325 @@
+Expression for the Y coordinate of the CIP in the GCRS based on the IAU2000A 
+precession-nutation model 
+
+--------------------------------------------------------------------------------------------------------------
+
+Y = polynomial part + non-polynomial part
+
+--------------------------------------------------------------------------------------------------------------
+
+Polynomial part (unit microarcsecond)
+
+  -6950.78 - 25381.99 t - 22407250.99 t^2 + 1842.28 t^3 + 1113.06 t^4 + 0.99 t^5
+
+--------------------------------------------------------------------------------------------------------------
+
+Non-polynomial part (unit microarcsecond)
+(ARG being for various combination of the fundamental arguments of the nutation theory)
+
+  Sum_i[b_{c,0})_i * cos(ARG) + b_{s,0})_i * sin(ARG)] 
+
++ Sum_i)j=1,4 [b_{c,j})_i * t^j * cos(ARG) + b_{s,j})_i * sin(ARG)] * t^j]
+
+The Table below provides the values for b_{s,j})_i and b_{c,j})_i
+
+The expressions for the fundamental arguments appearing in columns 4 to 8 (luni-solar part) 
+and in columns 6 to 17 (planetary part) are those of the IERS Conventions 2000
+
+--------------------------------------------------------------------------------------------------------------
+
+    i    b_{s,j})_i      b_{c,j})_i    l    l'   F    D   Om L_Me L_Ve  L_E L_Ma  L_J L_Sa  L_U L_Ne  p_A
+
+--------------------------------------------------------------------------------------------------------------
+
+j = 0  Nb of terms = 962
+
+    1        1538.18     9205236.26    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+    2        -458.66      573033.42    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+    3         137.41       97846.69    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+    4         -29.05      -89618.24    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+    5         -17.40       22438.42    0    1    2   -2    2    0    0    0    0    0    0    0    0    0
+    6          31.80       20069.50    0    0    2    0    1    0    0    0    0    0    0    0    0    0
+    7          36.70       12902.66    1    0    2    0    2    0    0    0    0    0    0    0    0    0
+    8         -13.20       -9592.72    0    1   -2    2   -2    0    0    0    0    0    0    0    0    0
+    9        -192.40        7387.02    0    1    0    0    0    0    0    0    0    0    0    0    0    0
+   10           3.92       -6918.22    0    0    2   -2    1    0    0    0    0    0    0    0    0    0
+   11           0.40       -5331.13    1    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+   12          -0.90       -3323.89    1    0    0    0    1    0    0    0    0    0    0    0    0    0
+   13           7.50        3143.98    1    0    0    0   -1    0    0    0    0    0    0    0    0    0
+   14           7.80        2636.13    1    0    2    0    1    0    0    0    0    0    0    0    0    0
+   15          -6.60        2554.51    1    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+   16          -2.00       -2423.59    2    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+   17           6.80        1645.01    0    0    2    2    2    0    0    0    0    0    0    0    0    0
+   18           0.00       -1387.00    0    2   -2    2   -2    0    0    0    0    0    0    0    0    0
+   19           5.90        1323.81    2    0    2    0    2    0    0    0    0    0    0    0    0    0
+   20          -0.30       -1233.89    1    0    2   -2    2    0    0    0    0    0    0    0    0    0
+   21           0.30       -1075.60    1    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+   22          -4.48         852.85    0    1    0    0    1    0    0    0    0    0    0    0    0    0
+   23           0.10        -800.34    1    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+   24          35.80        -674.99    1    0    0    0    0    0    0    0    0    0    0    0    0    0
+   25          -1.40         695.54    1    0    0   -2    1    0    0    0    0    0    0    0    0    0
+   26          -0.50         684.99    0    2    2   -2    2    0    0    0    0    0    0    0    0    0
+   27          -2.62         643.75    0    1    0    0   -1    0    0    0    0    0    0    0    0    0
+   28          -1.50         522.11    1    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+   29         273.50         164.70    0    0    1   -1    1    0    0   -1    0   -2    5    0    0    0
+   30           1.40         335.24    0    0    2    2    1    0    0    0    0    0    0    0    0    0
+   31           1.90         326.60    1    0    2    2    2    0    0    0    0    0    0    0    0    0
+   32           0.40         327.11    0    0    0    2    1    0    0    0    0    0    0    0    0    0
+   33          -0.50        -325.03    0    1    2    0    2    0    0    0    0    0    0    0    0    0
+   34          -0.40         307.03    0    1   -2    0   -2    0    0    0    0    0    0    0    0    0
+   35           0.50         304.17    2    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+   36          -0.10        -304.46    1    0    2   -2    1    0    0    0    0    0    0    0    0    0
+   37          -0.40        -276.81    2    0    2   -2    2    0    0    0    0    0    0    0    0    0
+   38           0.90         272.05    0    0    0    2   -1    0    0    0    0    0    0    0    0    0
+   39           0.30         272.22    0    1   -2    2   -1    0    0    0    0    0    0    0    0    0
+   40           1.20         269.45    2    0    2    0    1    0    0    0    0    0    0    0    0    0
+   41           0.10        -220.67    2    0    0   -2    1    0    0    0    0    0    0    0    0    0
+   42         128.60         -77.10    0    0    0    0    0    0    0    0    0    2   -5    0    0   -1
+   43           0.10        -190.79    0    1    2   -2    1    0    0    0    0    0    0    0    0    0
+   44         167.90           0.00    0    1   -1    1   -1    0    0    0    0    0    0    0    0    0
+   45          -8.20        -123.48    1    0    0   -2    0    0    0    0    0    0    0    0    0    0
+   46           0.10         131.04    2    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+   47           0.40         126.64    2    0    0    0   -1    0    0    0    0    0    0    0    0    0
+   48           2.90        -122.28    0    0    0    2    0    0    0    0    0    0    0    0    0    0
+   49           0.70         123.20    3    0    2    0    2    0    0    0    0    0    0    0    0    0
+   50           0.40         123.20    1   -1    2    0    2    0    0    0    0    0    0    0    0    0
+   51          -0.30         120.70    1    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+   52          -0.50         112.90    0    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+   53          -0.20        -112.94    2    0    0    0    1    0    0    0    0    0    0    0    0    0
+   54           0.20         107.31    1    0   -2    2   -1    0    0    0    0    0    0    0    0    0
+   55          -0.30        -106.20    1    1    2    0    2    0    0    0    0    0    0    0    0    0
+   56          31.90         -64.10    0    0    1   -1    1    0   -8   12    0    0    0    0    0    0
+   57           0.00          89.50    0    0    0    0    0    0    3   -5    0    0    0    0    0   -2
+   58          89.10           0.00    1    0   -1    0   -1    0    0    0    0    0    0    0    0    0
+   59           0.00          85.32    1    0    0    0    2    0    0    0    0    0    0    0    0    0
+   60          -0.20         -71.00    0    0    2    1    2    0    0    0    0    0    0    0    0    0
+   61           0.00         -70.01    1   -1    0   -1   -1    0    0    0    0    0    0    0    0    0
+   62          13.90         -55.30    1    0    0   -1    0    0    0    0    0    0    0    0    0    0
+   63           0.00          67.25    0    2   -2    2   -1    0    0    0    0    0    0    0    0    0
+   64           0.40          66.29    1    0    2    2    1    0    0    0    0    0    0    0    0    0
+   65          -0.40          64.70    1    0   -2   -4   -2    0    0    0    0    0    0    0    0    0
+   66           1.30         -60.90    2    0    0    0    0    0    0    0    0    0    0    0    0    0
+   67          -0.20         -60.92    1    0    0    0   -2    0    0    0    0    0    0    0    0    0
+   68           0.20         -59.20    2    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+   69           1.10         -55.55    0    0    2    0    0    0    0    0    0    0    0    0    0    0
+   70           0.00         -55.60    1    1    2   -2    2    0    0    0    0    0    0    0    0    0
+   71          -0.10         -52.69    2    0    2   -2    1    0    0    0    0    0    0    0    0    0
+   72          -0.20          51.80    2    0   -2   -4   -2    0    0    0    0    0    0    0    0    0
+   73           1.00         -49.51    1    0    0   -1   -1    0    0    0    0    0    0    0    0    0
+   74           0.00          50.50    0    0    0    0    0    0    0    0    0    2    0    0    0    2
+   75           2.50          47.70    2    0    0   -2    0    0    0    0    0    0    0    0    0    0
+   76           0.10          49.59    1    0    0    2    1    0    0    0    0    0    0    0    0    0
+   77           0.10         -49.00    1    0   -4    0   -2    0    0    0    0    0    0    0    0    0
+   78         -23.20          24.60    0    0    0    0    1    0    0   -1    2    0    0    0    0    0
+   79           0.40          46.50    2    0    2    2    2    0    0    0    0    0    0    0    0    0
+   80          -0.10         -44.04    0    0    2   -2   -1    0    0    0    0    0    0    0    0    0
+   81          -0.10         -42.19    0    1    2    0    1    0    0    0    0    0    0    0    0    0
+   82          13.30          26.90    0    0    0    0    0    0    8  -13    0    0    0    0    0   -1
+   83          -0.10         -39.90    3    0    2   -2    2    0    0    0    0    0    0    0    0    0
+   84          -0.10         -39.50    0    0    4   -2    2    0    0    0    0    0    0    0    0    0
+   85           0.00         -39.11    1    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+   86          -0.10         -38.92    2    0   -2    0    1    0    0    0    0    0    0    0    0    0
+   87           0.10          36.95    0    0    2    0   -1    0    0    0    0    0    0    0    0    0
+   88          -0.10          34.59    0    1   -2    0   -1    0    0    0    0    0    0    0    0    0
+   89           0.20         -32.55    0    1    0    0    2    0    0    0    0    0    0    0    0    0
+   90          -0.10          31.61    1    1    0   -2    1    0    0    0    0    0    0    0    0    0
+   91           0.00          30.40    0    0    2   -1    2    0    0    0    0    0    0    0    0    0
+   92           0.20          29.40    0    0    2    4    2    0    0    0    0    0    0    0    0    0
+   93           0.00         -27.91    1   -1    0    0    1    0    0    0    0    0    0    0    0    0
+   94           0.10          27.50    1    0    0    2   -1    0    0    0    0    0    0    0    0    0
+   95         -25.70          -1.70    0    0    1   -1    1    0    0   -1    0    2   -5    0    0    0
+   96          19.90           5.90    0    0    0    0    0    0    0    2   -8    3    0    0    0   -2
+   97           0.00          25.80    1   -1    0   -1   -2    0    0    0    0    0    0    0    0    0
+   98           0.20          25.20    1   -1    2    2    2    0    0    0    0    0    0    0    0    0
+   99           0.00         -25.31    0    1    0    0   -2    0    0    0    0    0    0    0    0    0
+  100           0.20          25.00    3    0    2    0    1    0    0    0    0    0    0    0    0    0
+  101          -0.10          24.40    1    0    2   -4    1    0    0    0    0    0    0    0    0    0
+  102           0.10         -24.40    1   -1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+  103         -23.30           0.90    0    0    2   -2    1    0   -5    6    0    0    0    0    0    0
+  104          -0.10          24.00    1    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  105         -18.00          -5.30    0    0    0    0    0    0    0    6   -8    3    0    0    0    2
+  106          -0.10         -22.80    0    1    2    2    2    0    0    0    0    0    0    0    0    0
+  107          -0.10          22.50    0    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  108           0.10          21.60    1   -1    2    0    1    0    0    0    0    0    0    0    0    0
+  109           0.00         -21.30    0    0    0    0    0    0    4   -6    0    0    0    0    0   -2
+  110           0.10          20.70    2   -1    2    0    2    0    0    0    0    0    0    0    0    0
+  111           0.70         -20.10    0    0    0    0    0    0    0    3    0   -1    0    0    0    2
+  112           0.00          20.51    0    0    0    1    1    0    0    0    0    0    0    0    0    0
+  113          15.90          -4.50    0    0    0    0    1    0    0   -4    8   -3    0    0    0    0
+  114           0.20         -19.94    1    0    0    2    0    0    0    0    0    0    0    0    0    0
+  115           0.00          20.11    0    0    0    2    2    0    0    0    0    0    0    0    0    0
+  116          15.60           4.40    0    0    0    0    1    0    0    4   -8    3    0    0    0    0
+  117           0.00         -20.00    1   -1   -2    0   -2    0    0    0    0    0    0    0    0    0
+  118           0.00          19.80    0    0    0    0    0    0    2   -4    0    0    0    0    0   -2
+  119           0.00          18.91    1    1    0    0    1    0    0    0    0    0    0    0    0    0
+  120           4.30         -14.60    0    0    1   -1    1    0    0    0   -2    0    0    0    0    0
+  121          -0.10         -18.50    1    1    2    0    1    0    0    0    0    0    0    0    0    0
+  122          -0.10          18.40    0    1    0   -2    1    0    0    0    0    0    0    0    0    0
+  123           0.00          18.10    0    3    2   -2    2    0    0    0    0    0    0    0    0    0
+  124           1.00          16.81    0    2    0    0    0    0    0    0    0    0    0    0    0    0
+  125          -0.10         -17.60    2    1    2    0    2    0    0    0    0    0    0    0    0    0
+  126         -17.60           0.00    1    0   -1    0   -2    0    0    0    0    0    0    0    0    0
+  127          -1.30         -16.26    0    0    2   -2    0    0    0    0    0    0    0    0    0    0
+  128           0.00         -17.41    0    0    0    1   -1    0    0    0    0    0    0    0    0    0
+  129          14.50          -2.70    0    0    0    0    0    0    0    0    0    2    0    0    0    1
+  130           0.00          17.08    1    0    0   -2   -2    0    0    0    0    0    0    0    0    0
+  131           0.00          16.21    1   -1    0    0   -1    0    0    0    0    0    0    0    0    0
+  132           0.00         -16.00    0    0    0    0    0    0    2    0    0    0    0    0    0    2
+  133           0.00         -15.31    1    0   -2    2   -2    0    0    0    0    0    0    0    0    0
+  134           0.00         -15.10    2    0    0   -2   -1    0    0   -2    0    2    0    0    0    0
+  135           0.00          14.70    0    0    0    0    0    0    1    1    0    0    0    0    0    2
+  136           0.00          14.40    1    0    2   -1    2    0    0    0    0    0    0    0    0    0
+  137          -0.10         -14.30    1    0    2    1    2    0    0    0    0    0    0    0    0    0
+  138           0.00         -14.40    0    0    2    1    1    0    0    0    0    0    0    0    0    0
+  139           0.00         -13.81    1    0   -2    0    1    0    0    0    0    0    0    0    0    0
+  140           4.50          -9.30    0    0    1   -1    1    0    0   -1    0    0   -1    0    0    0
+  141         -13.80           0.00    0    0    1    0    1    0    0    0    0    0    0    0    0    0
+  142           0.00         -13.38    1    0    0   -2    2    0    0    0    0    0    0    0    0    0
+  143          -0.10          13.10    1    0   -2   -4   -1    0    0    0    0    0    0    0    0    0
+  144          10.30           2.70    0    0    1   -1    1    0    0   -1    0   -1    0    0    0    0
+  145           0.00          12.80    1    0   -2    1   -1    0    0    0    0    0    0    0    0    0
+  146           0.00         -12.80    1    1    2   -2    1    0    0    0    0    0    0    0    0    0
+  147          11.70           0.80    0    0    0    0    0    0    0    0    0    2   -5    0    0    1
+  148           0.00         -12.00    2    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  149          11.30           0.50    0    0    0    0    0    0    5   -8    0    0    0    0    0   -2
+  150           0.00          11.40    0    0    0    0    0    0    0    1    0    1    0    0    0    2
+  151           0.00         -11.20    1    1    0    0   -1    0    0    0    0    0    0    0    0    0
+  152           0.10          10.90    4    0    2    0    2    0    0    0    0    0    0    0    0    0
+  153           0.10         -10.77    1    0    2    0    0    0    0    0    0    0    0    0    0    0
+  154           0.00         -10.80    2    1    2   -2    2    0    0    0    0    0    0    0    0    0
+  155          -0.20          10.47    2    0   -2    0    0    0    0    0    0    0    0    0    0    0
+  156           0.00          10.50    2    0   -2   -4   -1    0    0    0    0    0    0    0    0    0
+  157           0.00         -10.40    1    0    4   -2    2    0    0    0    0    0    0    0    0    0
+  158           0.00          10.40    0    1    2    1    2    0    0    0    0    0    0    0    0    0
+  159           0.00         -10.20    0    1    0    2    1    0    0    0    0    0    0    0    0    0
+  160           0.00         -10.00    1    0   -4    0   -1    0    0    0    0    0    0    0    0    0
+  161           0.00           9.60    1    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+  162           0.10           9.40    2    0    2    2    1    0    0    0    0    0    0    0    0    0
+  163          -7.60           1.70    0    0    0    0    0    0    8  -13    0    0    0    0    0   -2
+  164          -7.70           1.40    0    0    1   -1    1    0    0   -1    0    2    0    0    0    0
+  165           1.40          -7.50    0    0    1   -1    1    0   -5    7    0    0    0    0    0    0
+  166           6.10          -2.70    0    0    0    0    0    0    0    0    0    0    2    0    0    1
+  167           0.00          -8.70    0    0    0    0    0    0    5   -7    0    0    0    0    0   -2
+  168          -5.90           2.60    0    0    1   -1    1    0    0   -1    0    0    2    0    0    0
+  169           0.00           8.40    0    0    2   -4    1    0    0    0    0    0    0    0    0    0
+  170          -0.20          -8.11    0    1    0   -2    0    0    0    0    0    0    0    0    0    0
+  171          -2.60          -5.70    1    0    2    0    2    0    0    1    0    0    0    0    0    0
+  172           0.00           8.30    0    0    2   -3    2    0    0    0    0    0    0    0    0    0
+  173           2.70           5.50    1    0   -2    0   -2    0    0    4   -8    3    0    0    0    0
+  174           4.20          -4.00    0    0    0    0    0    0    0    8  -16    4    5    0    0   -2
+  175          -0.10           8.00    0    0    0    0    0    0    0    4    0   -2    0    0    0    2
+  176           0.00           8.09    0    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+  177          -1.30           6.70    0    0    0    0    0    0    0    2    0   -1    0    0    0    2
+  178           0.00          -7.90    0    0    4    0    2    0    0    0    0    0    0    0    0    0
+  179           0.00           7.80    0    0    0    4    1    0    0    0    0    0    0    0    0    0
+  180          -7.50          -0.20    0    0    0    0    0    0    2   -1    0    0    0    0    0    2
+  181          -0.50          -7.20    0    0    0    0    0    0    0    2    0    1    0    0    0    2
+  182           4.90           2.70    0    0    0    0    0    0    8  -11    0    0    0    0    0   -2
+  183           0.00           7.50    1    1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+  184           0.00          -7.50    3    0    2   -2    1    0    0    0    0    0    0    0    0    0
+  185           0.00          -7.49    2    0    0   -2   -2    0    0    0    0    0    0    0    0    0
+  186           0.00          -7.20    0    0    4   -2    1    0    0    0    0    0    0    0    0    0
+  187           0.10           6.90    1    0    2    4    2    0    0    0    0    0    0    0    0    0
+  188          -5.60           1.40    0    0    0    0    0    0    4   -6    0    0    0    0    0   -1
+  189          -5.70          -1.30    0    0    0    0    0    0    1   -1    0    0    0    0    0   -1
+  190           0.00           6.90    2    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+  191           4.20          -2.70    0    0    0    0    0    0    8  -15    0    0    0    0    0   -2
+  192           0.00           6.90    1    1   -2    0   -2    0    0    0    0    0    0    0    0    0
+  193          -3.10           3.70    0    0    0    0    0    0    0    1    2    0    0    0    0    2
+  194          -3.90          -2.90    0    0    0    0    0    0    0    3    0   -2    0    0    0    2
+  195           0.00           6.60    3    0    0    0   -1    0    0    0    0    0    0    0    0    0
+  196          -3.10          -3.50    0    0    0    0    0    0    0    3   -2    0    0    0    0    2
+  197           1.10          -5.39    1    0    0   -1    1    0    0    0    0    0    0    0    0    0
+  198           0.00          -6.40    2    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+  199           0.90           5.50    0    0    0    0    0    0    0    0    0    3    0    0    0    2
+  200           0.00          -6.30    0    0    2   -2    1    0   -3    3    0    0    0    0    0    0
+  201          -0.10          -6.20    0    0    0    0    0    0    0    4   -2    0    0    0    0    2
+  202           0.00          -6.10    1    1    2    2    2    0    0    0    0    0    0    0    0    0
+  203           0.00           6.10    0    0    1   -1    1    0    0    3   -8    3    0    0    0    0
+  204           0.00           6.10    0    0    2   -1    1    0    0    0    0    0    0    0    0    0
+  205           3.50          -2.50    0    0    0    0    1    0    8  -13    0    0    0    0    0    0
+  206           0.00           6.00    0    0    2    4    1    0    0    0    0    0    0    0    0    0
+  207           0.00           5.90    1   -1    0   -2   -1    0    0    0    0    0    0    0    0    0
+  208          -0.90          -4.80    2    0    0   -2    1    0    0   -2    0    3    0    0    0    0
+  209           0.00           5.70    1   -1   -2    2   -1    0    0    0    0    0    0    0    0    0
+  210           0.10           5.60    3    0    2    2    2    0    0    0    0    0    0    0    0    0
+  211           0.00           5.70    0    0    0    0    0    0    0    0    0    0    2    0    0    2
+  212           0.00           5.70    2    0    0    2    1    0    0    0    0    0    0    0    0    0
+  213           0.00           5.60    2    0    0   -4    1    0    0    0    0    0    0    0    0    0
+  214           0.00           5.60    1    0    0   -4    1    0    0    0    0    0    0    0    0    0
+  215           0.20          -5.40    2    1   -2    0   -1    0    0    0    0    0    0    0    0    0
+  216          -0.90          -4.70    0    0    0    0    0    0    5   -8    0    0    0    0    0   -1
+  217          -0.40          -5.10    1    1    0   -2    0    0    0    0    0    0    0    0    0    0
+  218           0.00           5.50    0    2   -2   -2   -2    0    0    0    0    0    0    0    0    0
+  219           0.00          -5.40    2    0    2   -4    1    0    0    0    0    0    0    0    0    0
+  220           0.00          -5.40    0    0    0    0    0    0    0    8  -16    4    5    0    0    2
+  221           1.80           3.60    1    0    0    0   -1    0  -18   16    0    0    0    0    0    0
+  222           0.00           5.30    1   -1    0   -2   -2    0    0    0    0    0    0    0    0    0
+  223           0.00          -5.30    0    0    1   -1    1    0    0   -5    8   -3    0    0    0    0
+  224           0.00          -5.20    0    0    0    0    0    0    0    1    0   -3    0    0    0   -2
+  225           0.00          -5.19    0    0    0    2   -2    0    0    0    0    0    0    0    0    0
+  226           3.00           2.10    0    0    0    0    1    0   -8   13    0    0    0    0    0    0
+  227           0.00          -5.10    0    0    0    0    0    0    6   -8    0    0    0    0    0   -2
+  228           0.00           5.07    0    2    0    0    1    0    0    0    0    0    0    0    0    0
+  229           0.90          -4.10    0    0    0    0    1    0    0    0    0   -2    5    0    0    0
+  230          -5.00           0.00    0    0    0    0    0    0    3   -2    0    0    0    0    0    2
+  231           0.00          -5.00    3    0    0    0    0    0    0    0    0    0    0    0    0    0
+  232           0.00           5.00    1   -1    2    2    1    0    0    0    0    0    0    0    0    0
+  233           0.00          -5.00    1   -1   -2    0   -1    0    0    0    0    0    0    0    0    0
+  234           0.00          -4.90    4    0    2   -2    2    0    0    0    0    0    0    0    0    0
+  235           4.90           0.00    0    0    0    0    0    0    2   -5    0    0    0    0    0   -2
+  236           0.00          -4.90    0    0    0    0    0    0    1   -3    0    0    0    0    0   -2
+  237           0.90           3.90    0    0    0    0    1    0    0    0    0    2   -5    0    0    0
+  238           0.00           4.80    2    1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+  239          -3.70          -1.10    0    0    0    0    1    0    0    0    0    1    0    0    0    0
+  240           0.00          -4.72    0    2    2   -2    1    0    0    0    0    0    0    0    0    0
+  241           0.00           4.71    1    0    2    0   -1    0    0    0    0    0    0    0    0    0
+  242           0.00          -4.50    2    1    0   -2    1    0    0    0    0    0    0    0    0    0
+  243          -1.50          -3.00    1    0    0    0    1    0  -18   16    0    0    0    0    0    0
+  244           0.00          -4.50    2   -1   -2    0   -1    0    0    0    0    0    0    0    0    0
+  245           0.30          -4.11    1   -1    0    0    0    0    0    0    0    0    0    0    0    0
+  246           0.00           4.40    1    2   -2   -2   -2    0    0    0    0    0    0    0    0    0
+  247           0.00          -4.40    1   -1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  248           0.00           4.39    2    0    0   -2    2    0    0    0    0    0    0    0    0    0
+  249           0.00          -4.30    3    0    0    0    1    0    0    0    0    0    0    0    0    0
+  250           0.00           4.30    2    0   -2    2   -1    0    0    0    0    0    0    0    0    0
+  251           0.00          -4.30    0    1    2    2    1    0    0    0    0    0    0    0    0    0
+  252           0.20           4.03    1    0   -2    0    0    0    0    0    0    0    0    0    0    0
+  253           0.20           4.00    0    2   -2    0   -2    0    0    0    0    0    0    0    0    0
+  254          -0.60           3.50    0    0    1   -1    1    0    0   -1    0    0    1    0    0    0
+  255           0.00           4.10    3    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+  256           0.00           4.00    1    0   -4    2   -2    0    0    0    0    0    0    0    0    0
+  257           0.00          -4.00    0    1   -2    1   -2    0    0    0    0    0    0    0    0    0
+  258           0.00          -3.91    1    0    0   -4    0    0    0    0    0    0    0    0    0    0
+  259           1.90           2.00    0    0    0    0    1    0    0    1   -2    0    0    0    0    0
+  260           0.00           3.90    2   -1    2    2    2    0    0    0    0    0    0    0    0    0
+  261           0.00           3.90    0    1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+  262           0.00          -3.90    1    0   -2   -3   -2    0    0    0    0    0    0    0    0    0
+  263           3.10          -0.80    0    0    0    0    0    0    2   -4    0    0    0    0    0   -1
+  264           0.00           3.90    2   -1    2    0    1    0    0    0    0    0    0    0    0    0
+  265           0.00           3.90    2    0    0    0    2    0    0    0    0    0    0    0    0    0
+  266           0.00           3.80    0    0    0    0    0    0    0    2    0    0    0    0    0    2
+  267          -0.20           3.51    1    1    0    0    0    0    0    0    0    0    0    0    0    0
+  268           0.00          -3.60    1    0   -2   -1   -2    0    0    0    0    0    0    0    0    0
+  269          -2.10           1.50    0    0    0    0    0    0    0    1    0    2    0    0    0    2
+  270           0.00          -3.60    1    1   -2    1   -1    0    0    0    0    0    0    0    0    0
+  271           0.70           2.80    0    0    0    0    0    0    3   -7    0    0    0    0    0   -2
+  272          -2.80           0.70    0    0    0    0    0    0    0    0    0    1    0    0    0   -1
+  273           0.00          -3.50    0    0    0    0    0    0    0    2    0    0    0    0    0    0
+  274          -2.90          -0.60    0    0    0    0    0    0    2   -2    0    0    0    0    0   -1
+  275           0.00          -3.40    1   -1    0   -2    1    0    0    0    0    0    0    0    0    0
+  276           0.00           3.40    2    0   -4    0   -2    0    0    0    0    0    0    0    0    0
+  277           0.00           3.36    0    0    2    0    3    0    0    0    0    0    0    0    0    0
+  278           0.50           2.80    2    0    0   -2   -1    0    0   -2    0    3    0    0    0    0
+  279           2.60          -0.70    0    0    0    0    0    0    3   -5    0    0    0    0    0   -1
+  280           1.00          -2.30    0    0    0    0    0    0    0    0    0    1    0    0    0    2
+  281           0.00          -3.30    2    1    2    0    1    0    0    0    0    0    0    0    0    0
+  282           0.00           3.30    1    1   -2    0   -1    0    0    0    0    0    0    0    0    0
+  283           0.00           3.23    0    2    0    0   -1    0    0    0    0    0    0    0    0    0
+  284           0.00           3.20    1   -1    2   -2    2    0    0    0    0    0    0    0    0    0
+  285           0.00          -3.20    0    2    2    0    2    0    0    0    0    0    0    0    0    0
+  286           0.00          -3.20    0    0    0    0    0    0    7   -9    0    0    0    0    0   -2
+  287           0.00           3.20    0    0    0    0    0    0    0    0    2    0    0    0    0    2
+  288           2.90          -0.30    0    0    0    0    0    0    0    0    0    1    0    0    0    1
+  289           0.08           3.05    0    0    2   -2    3    0    0    0    0    0    0    0    0    0
+  290          -0.70          -2.40    0    0    0    0    0    0    3   -3    0    0    0    0    0    2
+  291           0.00          -3.08    1    0    2   -4    2    0    0    0    0    0    0    0    0    0
+  292           0.00           3.00    2    0    2   -1    2    0    0    0    0    0    0    0    0    0
+  293          -1.60           1.40    1    0    0   -1    1    0    0   -1    0    2    0    0    0    0
+  294          -2.90          -0.10    0    0    0    0    0    0    4   -7    0    0    0    0    0   -2
+  295           0.00          -2.90    2    0    0   -2    1    0    0   -2    0    2    0    0    0    0
+  296          -2.50           0.40    0    0    1   -1    1    0    0   -2    2    0    0    0    0    0
+  297           0.40          -2.50    0    0    0    0    0    0    0    0    0    0    1    0    0    1
+  298           0.00          -2.90    1    0    2    1    1    0    0    0    0    0    0    0    0    0
+  299           0.00           2.89    0    1   -2    2    0    0    0    0    0    0    0    0    0    0
+  300           0.00          -2.80    2    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+  301          -2.50           0.30    0    0    1   -1    1    0    0   -1    0    1    0    0    0    0
+  302          -2.50          -0.30    0    0    0    0    0    0    0    1   -2    0    0    0    0   -1
+  303           0.00          -2.70    0    0    2   -2    1    0    0   -2    0    2    0    0    0    0
+  304           2.70           0.00    1    0   -1    0   -3    0    0    0    0    0    0    0    0    0
+  305           0.00          -2.60    0    1    0    1    1    0    0    0    0    0    0    0    0    0
+  306           0.00          -2.60    0    1    0    2   -1    0    0    0    0    0    0    0    0    0
+  307           0.00           2.60    3   -1    2    0    2    0    0    0    0    0    0    0    0    0
+  308           2.10           0.50    0    0    1   -1    1    0   -3    4    0    0    0    0    0    0
+  309           0.00           2.50    0    1    0    1   -1    0    0    0    0    0    0    0    0    0
+  310           0.80           1.70    0    0    0    0    0    0    0    0    0    0    1    0    0   -1
+  311           1.90          -0.60    0    0    0    0    0    0    0    6  -16    4    5    0    0   -2
+  312           0.00          -2.50    2    0    0    0   -2    0    0    0    0    0    0    0    0    0
+  313           0.00          -2.40    2    0    0    2    0    0    0    0    0    0    0    0    0    0
+  314           0.00           2.40    2    0    0    2   -1    0    0    0    0    0    0    0    0    0
+  315           0.00          -2.40    1    1   -2    2   -1    0    0    0    0    0    0    0    0    0
+  316           0.00           2.40    1    0    2   -3    1    0    0    0    0    0    0    0    0    0
+  317          -1.90           0.50    0    0    0    0    0    0    5   -7    0    0    0    0    0   -1
+  318          -0.10          -2.30    2    0    0   -4    0    0    0    0    0    0    0    0    0    0
+  319           0.00           2.30    1    1    2   -4    1    0    0    0    0    0    0    0    0    0
+  320           0.00          -2.30    3    1    2    0    2    0    0    0    0    0    0    0    0    0
+  321          -1.40           0.90    0    0    0    0    0    0    0    0    4    0    0    0    0    2
+  322          -0.10          -2.20    0    0    0    0    0    0    8  -10    0    0    0    0    0   -2
+  323          -0.20          -2.00    0    0    0    1    0    0    0    0    0    0    0    0    0    0
+  324           0.00           2.20    1   -2    2    0    2    0    0    0    0    0    0    0    0    0
+  325           0.00          -2.20    2   -1    2   -2    2    0    0    0    0    0    0    0    0    0
+  326           0.00           2.20    1    1    2    1    2    0    0    0    0    0    0    0    0    0
+  327           0.00           2.20    0    0    0    0    0    0    0    2   -4    0    0    0    0   -2
+  328          -1.80          -0.40    0    0    0    0    0    0    3   -3    0    0    0    0    0   -1
+  329           0.00           2.20    0    1    2    1    1    0    0    0    0    0    0    0    0    0
+  330           0.00           2.20    4    0    2    0    1    0    0    0    0    0    0    0    0    0
+  331          -1.70           0.40    0    0    0    0    0    0    1   -1    0    0    0    0    0    1
+  332          -0.80          -1.30    0    0    0    0    0    0    0    5   -4    0    0    0    0    2
+  333          -1.30          -0.80    0    0    0    0    0    0    0    4   -4    0    0    0    0    2
+  334           0.00           2.10    1    0   -2    1   -2    0    0    0    0    0    0    0    0    0
+  335           0.00           2.10    1   -1    2   -2    1    0    0    0    0    0    0    0    0    0
+  336           0.00          -2.10    1    0    4   -2    1    0    0    0    0    0    0    0    0    0
+  337           0.00          -2.10    2    1    2   -2    1    0    0    0    0    0    0    0    0    0
+  338           0.00           2.10    1    0    2   -1    1    0    0    0    0    0    0    0    0    0
+  339           0.00          -2.00    1    0    2   -2   -1    0    0    0    0    0    0    0    0    0
+  340           0.00           2.00    1    0   -2    2    1    0    0    0    0    0    0    0    0    0
+  341           0.00           2.00    1   -1    0    2   -1    0    0    0    0    0    0    0    0    0
+  342           0.00           2.00    2   -2    0   -2   -1    0    0    0    0    0    0    0    0    0
+  343           0.00          -2.00    1    2    2   -2    2    0    0    0    0    0    0    0    0    0
+  344           2.00           0.00    0    0    0    0    0    0    6   -9    0    0    0    0    0   -2
+  345           1.10          -0.90    0    0    0    0    0    0    0    0    0    2   -5    0    0   -2
+  346           1.60          -0.40    0    0    0    0    0    0    1   -3    0    0    0    0    0   -1
+  347           0.00          -1.91    1    0   -2   -2    0    0    0    0    0    0    0    0    0    0
+  348           0.00          -1.90    0    0    0    4    0    0    0    0    0    0    0    0    0    0
+  349           0.00           1.90    0    0    4   -4    2    0    0    0    0    0    0    0    0    0
+  350           0.00          -1.90    3    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+  351           0.00           1.90    2   -1    0   -2    1    0    0    0    0    0    0    0    0    0
+  352           1.50           0.40    0    0    1   -1    1    0   -4    5    0    0    0    0    0    0
+  353          -1.50          -0.40    0    0    0    0    0    0    0    2    0    0    0    0    0    1
+  354          -1.40          -0.50    0    0    1   -1    1    0    0   -1    0   -4   10    0    0    0
+  355          -1.00           0.90    0    0    1   -1    1    0    0   -1    0    0    0    0    2    0
+  356           0.00          -1.90    2    0    2    1    2    0    0    0    0    0    0    0    0    0
+  357          -0.30           1.60    0    0    0    0    0    0    0    4    0   -3    0    0    0    2
+  358           0.00           1.90    0    0    0    4   -1    0    0    0    0    0    0    0    0    0
+  359           0.00           1.90    1   -1    0    2    1    0    0    0    0    0    0    0    0    0
+  360           0.00          -1.80    2   -1    0    0    1    0    0    0    0    0    0    0    0    0
+  361           0.00          -1.80    2    0   -4   -2   -2    0    0    0    0    0    0    0    0    0
+  362          -1.10           0.70    0    0    0    0    0    0    0    2   -4    0    0    0    0   -1
+  363           0.20          -1.60    0    0    0    0    0    0    2   -3    0    0    0    0    0   -1
+  364           0.00           1.80    2    0   -2   -6   -2    0    0    0    0    0    0    0    0    0
+  365           0.00          -1.71    0    0    2    2    0    0    0    0    0    0    0    0    0    0
+  366          -1.20          -0.50    0    0    2   -2    1    0    0   -9   13    0    0    0    0    0
+  367           1.50           0.20    0    0    1    1    1    0    0    1    0    0    0    0    0    0
+  368          -0.60          -1.10    1    0    2    0    1    0    0   -2    0    3    0    0    0    0
+  369           0.60           1.10    1    0   -2    0   -1    0    0   -1    0    0    0    0    0    0
+  370          -0.60          -1.10    0    0    0    0    0    0    0    4   -3    0    0    0    0    2
+  371          -1.10           0.60    0    0    0    0    1    0    0   -2    4    0    0    0    0    0
+  372          -1.70           0.00    0    0    0    0    1    0    2   -3    0    0    0    0    0    0
+  373           0.00           1.60    0    1   -2    2    1    0    0    0    0    0    0    0    0    0
+  374           0.00          -1.60    2    0    4   -2    2    0    0    0    0    0    0    0    0    0
+  375           0.00          -1.60    0    0    2    3    2    0    0    0    0    0    0    0    0    0
+  376           1.20          -0.40    0    0    0    0    0    0    0    0    0    3    0    0    0    1
+  377          -0.50          -1.10    2    0    2    0    2    0    0    2    0   -3    0    0    0    0
+  378           0.60           1.00    0    0    0    0    0    0    0    3   -6    0    0    0    0   -2
+  379          -1.30          -0.30    0    0    0    0    0    0    4   -4    0    0    0    0    0   -1
+  380           0.30          -1.30    0    0    0    0    0    0    0    1   -2    0    0    0    0    1
+  381           0.00           1.60    1    0    0    4    1    0    0    0    0    0    0    0    0    0
+  382           0.00          -1.60    1    1    0    2    1    0    0    0    0    0    0    0    0    0
+  383           0.00          -1.60    0    0    4    0    1    0    0    0    0    0    0    0    0    0
+  384           1.10          -0.50    0    0    1   -1    2    0    0   -1    0    0    2    0    0    0
+  385           0.00          -1.50    1   -1    0    2    0    0    0    0    0    0    0    0    0    0
+  386           0.00          -1.50    0    1    2   -2   -1    0    0    0    0    0    0    0    0    0
+  387           0.00           1.50    2   -1    0    0   -1    0    0    0    0    0    0    0    0    0
+  388           0.00          -1.50    1    0    0    1   -1    0    0    0    0    0    0    0    0    0
+  389           0.00          -1.50    1    2    0   -2   -1    0    0    0    0    0    0    0    0    0
+  390           1.50           0.00    1    0    0   -1    1    0   -3    4    0    0    0    0    0    0
+  391           0.00          -1.50    0    1    4   -2    2    0    0    0    0    0    0    0    0    0
+  392           1.30          -0.20    0    0    0    0    1    0    0    0    0    0    1    0    0    0
+  393           0.00          -1.50    0    0    0    0    0    0    9  -11    0    0    0    0    0   -2
+  394          -1.20          -0.30    0    0    0    0    0    0    1    1    0    0    0    0    0    1
+  395          -1.40           0.10    0    0    0    0    0    0    0    4    0   -1    0    0    0    2
+  396          -0.50           1.00    0    0    2    0    2    0    0    1    0    0    0    0    0    0
+  397          -0.50           1.00    0    0    0    0    0    0    0    1   -8    3    0    0    0   -2
+  398           0.20          -1.30    0    0    0    0    0    0    0    1    0   -4    0    0    0   -2
+  399           0.00           1.50    1    1   -2   -4   -1    0    0    0    0    0    0    0    0    0
+  400           0.00           1.50    1    0    0   -1   -2    0    0    0    0    0    0    0    0    0
+  401           0.00           1.50    0    0    0    0    1    0    1   -1    0    0    0    0    0    0
+  402           0.00           1.49    2    0    2   -4    2    0    0    0    0    0    0    0    0    0
+  403           0.00          -1.41    2    0    2    0    0    0    0    0    0    0    0    0    0    0
+  404           0.00           1.41    0    1    0    2    0    0    0    0    0    0    0    0    0    0
+  405           0.00          -1.40    0    0    2   -3    1    0    0    0    0    0    0    0    0    0
+  406           0.00          -1.40    1   -2   -2   -2   -2    0    0    0    0    0    0    0    0    0
+  407           0.00           1.40    1    0   -2   -6   -2    0    0    0    0    0    0    0    0    0
+  408           0.00          -1.40    0    0    2   -2    1    0   -4    4    0    0    0    0    0    0
+  409           1.10          -0.30    0    0    1   -1    1    0   -1    0    0    0    0    0    0    0
+  410           0.00          -1.40    3    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  411           0.00           1.40    1    0    2    4    1    0    0    0    0    0    0    0    0    0
+  412           1.40           0.00    0    0    1    0    2    0    0    0    0    0    0    0    0    0
+  413          -0.30           1.10    0    0    0    0    1    0   -3    5    0    0    0    0    0    0
+  414           0.20           1.20    2   -1    0   -2    0    0    0    0    0    0    0    0    0    0
+  415          -1.30           0.00    1    0    0   -1   -1    0   -3    4    0    0    0    0    0    0
+  416           0.00          -1.30    1   -1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+  417           0.00           1.30    1   -2    2    2    2    0    0    0    0    0    0    0    0    0
+  418          -0.70          -0.60    0    0    1   -1    1    0    8  -14    0    0    0    0    0    0
+  419          -0.80           0.50    0    0    1   -1    1    0    3   -6    0    0    0    0    0    0
+  420          -0.20          -1.10    0    0    0    0    0    0    6  -10    0    0    0    0    0   -2
+  421           1.10           0.20    0    0    0    0    0    0    0    2    0   -2    0    0    0    1
+  422           0.00          -1.30    3    1    2   -2    2    0    0    0    0    0    0    0    0    0
+  423           0.00          -1.30    1    0   -4   -2   -2    0    0    0    0    0    0    0    0    0
+  424           0.00          -1.30    0    0    0    0    0    0    3   -1    0    0    0    0    0    2
+  425           0.00          -1.30    0    0    0    0    0    0    0    3    0    0   -1    0    0    2
+  426           0.00          -1.29    0    0    2   -4    2    0    0    0    0    0    0    0    0    0
+  427           0.00           1.20    1    2    0   -2    1    0    0    0    0    0    0    0    0    0
+  428           0.00          -1.20    2    1    0    0   -1    0    0    0    0    0    0    0    0    0
+  429          -0.40          -0.80    0    0    0    0    1    0    0    8  -15    0    0    0    0    0
+  430           0.00           1.20    2    0    2    4    2    0    0    0    0    0    0    0    0    0
+  431           1.20           0.00    0    0    0    0    0    0    3   -6    0    0    0    0    0   -2
+  432          -0.70          -0.50    0    0    1   -1    1    0    0   -3    4    0    0    0    0    0
+  433          -1.00           0.20    0    0    0    0    0    0    6   -8    0    0    0    0    0   -1
+  434          -1.00           0.20    0    0    0    0    0    0    2    1    0    0    0    0    0    2
+  435           0.20          -1.00    0    0    0    0    0    0    2    1    0    0    0    0    0    1
+  436           0.40           0.80    0    0    0    0    0    0    0    1   -4    0    0    0    0   -2
+  437          -0.40           0.80    0    0    0    0    0    0    0    0    3    0    0    0    0    2
+  438           0.00          -1.20    1    1    2    2    1    0    0    0    0    0    0    0    0    0
+  439           0.00           1.15    0    0    0    0    3    0    0    0    0    0    0    0    0    0
+  440           0.00           1.10    2    1    0    0    1    0    0    0    0    0    0    0    0    0
+  441          -0.20           0.90    2    0    0   -2    1    0   -6    8    0    0    0    0    0    0
+  442          -1.10           0.00    0    0    3    0    3    0    0    0    0    0    0    0    0    0
+  443           0.00          -1.10    2    1    2    2    2    0    0    0    0    0    0    0    0    0
+  444          -1.10           0.00    1    0    1    0    1    0    0    0    0    0    0    0    0    0
+  445           0.00           1.10    2   -1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+  446           0.00           1.10    3    0    2   -4    2    0    0    0    0    0    0    0    0    0
+  447           0.00           1.10    0    0    0    0    0    0    0    7   -8    3    0    0    0    2
+  448           0.60          -0.50    0    0    0    0    0    0    0    0    0    0    0    0    2    1
+  449          -0.90          -0.20    0    0    0    0    0    0    5   -5    0    0    0    0    0   -1
+  450          -0.40          -0.70    0    0    0    0    0    0    0    4   -7    0    0    0    0   -2
+  451          -0.50           0.60    1   -2    2   -2    1    0    0    0    0    0    0    0    0    0
+  452           0.00           1.10    3    0    2    2    1    0    0    0    0    0    0    0    0    0
+  453           0.00          -1.10    1   -1   -2    2   -2    0    0    0    0    0    0    0    0    0
+  454           0.00           1.00    0    0    0    0    1    0   -1    1    0    0    0    0    0    0
+  455           1.00           0.00    0    0    0    0    1    0   -2    3    0    0    0    0    0    0
+  456           0.80          -0.20    0    0    0    0    1    0    0    0    0   -1    0    0    0    0
+  457           0.00           1.00    1    0    0    1    1    0    0    0    0    0    0    0    0    0
+  458           0.00           1.00    0    2    0   -2    1    0    0    0    0    0    0    0    0    0
+  459           0.00          -1.00    3    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+  460          -1.00           0.00    1    0    1   -2    1    0    0    0    0    0    0    0    0    0
+  461           0.00           1.00    1   -1    2    4    2    0    0    0    0    0    0    0    0    0
+  462           1.00           0.00    0    0    1   -1    1    0    0   -9   15    0    0    0    0    0
+  463           1.00           0.00    0    0    0    0    0    0    7  -10    0    0    0    0    0   -2
+  464          -0.80          -0.20    0    0    0    0    0    0    2    0    0    0    0    0    0    1
+  465           0.40           0.60    0    0    0    0    0    0    3   -5    4    0    0    0    0    2
+  466          -0.40          -0.60    0    0    0    0    0    0    3   -9    4    0    0    0    0   -2
+  467           0.00          -1.00    1    0    4    0    2    0    0    0    0    0    0    0    0    0
+  468           0.00           1.00    0    1    2   -4    1    0    0    0    0    0    0    0    0    0
+  469           0.00           1.00    1    0   -4    2   -1    0    0    0    0    0    0    0    0    0
+  470           0.00           1.00    0    2   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  471           0.00           1.00    2    0   -2    0    2    0    0    0    0    0    0    0    0    0
+  472           0.00          -1.00    1    0    0    2    2    0    0    0    0    0    0    0    0    0
+  473           0.00           0.91    1    0    2   -2    0    0    0    0    0    0    0    0    0    0
+  474           0.10           0.80    1   -1    0   -2    0    0    0    0    0    0    0    0    0    0
+  475           0.00           0.90    1    0   -2   -2    1    0    0    0    0    0    0    0    0    0
+  476           0.00           0.90    0    1    0   -2   -2    0    0    0    0    0    0    0    0    0
+  477           0.00          -0.90    2    0    0   -2    1    0   -3    3    0    0    0    0    0    0
+  478           0.00          -0.90    1    2    2    0    2    0    0    0    0    0    0    0    0    0
+  479          -0.70          -0.20    0    0    0    0    0    0    6   -6    0    0    0    0    0   -1
+  480           0.70          -0.20    0    0    0    0    0    0    1    2    0    0    0    0    0    2
+  481          -0.30           0.60    0    0    0    0    0    0    0    8  -15    0    0    0    0   -2
+  482           0.00           0.90    5    0    2    0    2    0    0    0    0    0    0    0    0    0
+  483           0.00           0.90    3    0   -2   -6   -2    0    0    0    0    0    0    0    0    0
+  484           0.00          -0.90    0    0    1   -1    1    0   -2    2    0    0    0    0    0    0
+  485          -0.50          -0.40    0    0    0    0    0    0    0    3    0   -3    0    0    0    2
+  486          -0.90           0.00    0    0    0    0    0    0    0    2    0    0   -1    0    0    2
+  487           0.00          -0.90    1   -1    2   -1    2    0    0    0    0    0    0    0    0    0
+  488           0.00           0.90    1    0   -2    4   -1    0    0    0    0    0    0    0    0    0
+  489           0.00           0.90    2    1   -2   -4   -1    0    0    0    0    0    0    0    0    0
+  490           0.00          -0.90    4    0    2   -2    1    0    0    0    0    0    0    0    0    0
+  491           0.00          -0.90    1   -1    0   -1    0    0    0    0    0    0    0    0    0    0
+  492           0.00          -0.80    2   -1    0    0    0    0    0    0    0    0    0    0    0    0
+  493           0.00           0.80    3    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+  494           0.00          -0.80    2   -1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+  495           0.10           0.70    0    0    0    0    0    0    7  -11    0    0    0    0    0   -2
+  496          -0.70           0.10    0    0    0    0    0    0    2   -2    0    0    0    0    0    1
+  497          -0.60           0.20    0    0    0    0    0    0    7   -9    0    0    0    0    0   -1
+  498           0.20           0.60    0    0    0    0    0    0    4   -7    0    0    0    0    0   -1
+  499           0.00           0.80    0    0    4   -4    1    0    0    0    0    0    0    0    0    0
+  500          -0.50           0.30    0    0    0    0    0    0    3   -5    0    0    0    0    0    1
+  501          -0.50          -0.30    0    0    0    0    0    0    0    5   -5    0    0    0    0    2
+  502          -0.50          -0.30    0    0    0    0    0    0    0    5   -9    0    0    0    0   -2
+  503           0.00          -0.80    0    0    0    0    0    0    0    3   -1    0    0    0    0    2
+  504          -0.30           0.50    0    0    0    0    0    0    0    2    0    2   -5    0    0    2
+  505          -0.80           0.00    0    0    0    0    0    0    0    2    0    0    1    0    0    2
+  506          -0.30          -0.50    0    0    0    0    0    0    0    2    0   -2    5    0    0    2
+  507          -0.30           0.50    0    0    0    0    1    0   -3    7   -4    0    0    0    0    0
+  508          -0.30          -0.50    0    0    0    0    1    0    3   -7    4    0    0    0    0    0
+  509           0.00           0.80    0    1    0   -4   -1    0    0    0    0    0    0    0    0    0
+  510           0.00          -0.80    3    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+  511           0.00          -0.80    1    0   -2   -3   -1    0    0    0    0    0    0    0    0    0
+  512           0.00          -0.80    0    1   -2    1   -1    0    0    0    0    0    0    0    0    0
+  513           0.00           0.80    1    2   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  514           0.00           0.80    1    1    0   -2   -2    0    0    0    0    0    0    0    0    0
+  515           0.00          -0.80    0    0    0    0    1    0    0    1    0   -1    0    0    0    0
+  516           0.00           0.76    1    0    2    0    3    0    0    0    0    0    0    0    0    0
+  517           0.00           0.70    3    0    0   -4    1    0    0    0    0    0    0    0    0    0
+  518           0.10          -0.60    2    0    0   -2   -1    0   -6    8    0    0    0    0    0    0
+  519           0.00           0.70    0    1   -4    2   -2    0    0    0    0    0    0    0    0    0
+  520           0.70           0.00    0    0    1   -1    1    0    0   -1    0   -1    1    0    0    0
+  521           0.00          -0.70    0    0    0    0    1    0    3   -5    0    2    0    0    0    0
+  522           0.00          -0.70    0    1    2    4    2    0    0    0    0    0    0    0    0    0
+  523           0.00           0.70    4    0    2    2    2    0    0    0    0    0    0    0    0    0
+  524           0.00          -0.70    2    0   -2   -3   -2    0    0    0    0    0    0    0    0    0
+  525          -0.70           0.00    0    0    1   -1    1    0    2   -4    0   -3    0    0    0    0
+  526          -0.50           0.20    0    0    1   -1    1    0    0   -1    0    3    0    0    0    0
+  527          -0.20          -0.50    0    0    0    0    0    0    9   -9    0    0    0    0    0   -1
+  528           0.50          -0.20    0    0    0    0    0    0    2   -3    0    0    0    0    0   -2
+  529           0.20           0.50    0    0    0    0    0    0    0   11    0    0    0    0    0    2
+  530          -0.20          -0.50    0    0    0    0    0    0    0    6  -15    0    0    0    0   -2
+  531           0.50          -0.20    0    0    0    0    0    0    0    3    0    2   -5    0    0    2
+  532          -0.50           0.20    0    0    0    0    0    0    0    3    0    1    0    0    0    2
+  533           0.00          -0.70    0    0    0    0    0    0    0    3   -5    0    0    0    0   -2
+  534           0.00          -0.70    0    0    0    0    0    0    0    2    0   -4    0    0    0   -2
+  535           0.70           0.00    0    0    0    0    0    0    0    0    0    0    3    0    0    2
+  536          -0.60          -0.10    0    0    0    0    0    0    3   -1    0    0    0    0    0    1
+  537           0.60          -0.10    0    0    0    0    0    0    3   -3    0    0    0    0    0    1
+  538           0.40           0.30    0    0    0    0    0    0    0    4   -8    0    0    0    0   -2
+  539           0.00           0.70    1    0    0    1    0    0    0    0    0    0    0    0    0    0
+  540           0.70           0.00    0    0    1   -1    2    0    0   -2    2    0    0    0    0    0
+  541           0.00           0.70    2   -1    2    2    1    0    0    0    0    0    0    0    0    0
+  542           0.00           0.70    0    1   -2   -4   -1    0    0    0    0    0    0    0    0    0
+  543           0.00           0.70    1   -1    0    0    2    0    0    0    0    0    0    0    0    0
+  544           0.00          -0.60    0    0    0    0    1    0    0   -1    0    1    0    0    0    0
+  545           0.00           0.60    0    0    2    2   -1    0    0    0    0    0    0    0    0    0
+  546           0.10          -0.50    0    0    1   -1   -1    0    0    0   -2    0    0    0    0    0
+  547           0.00           0.60    2    1    0    0    0    0    0    0    0    0    0    0    0    0
+  548           0.40           0.20    0    0    0    0    1    0    0    2   -4    0    0    0    0    0
+  549           0.00           0.60    1    0    0   -4   -2    0    0    0    0    0    0    0    0    0
+  550           0.00          -0.60    2    1    0   -4   -1    0    0    0    0    0    0    0    0    0
+  551           0.00           0.60    1    1    0   -4    1    0    0    0    0    0    0    0    0    0
+  552           0.00          -0.60    0    1    0    1    0    0    0    0    0    0    0    0    0    0
+  553           0.00          -0.60    1   -1    2   -4    1    0    0    0    0    0    0    0    0    0
+  554           0.50           0.10    0    0    1   -1    1    0   -2    3    0    0    0    0    0    0
+  555          -0.50          -0.10    0    0    0    0    0    0    7   -7    0    0    0    0    0   -1
+  556          -0.10          -0.50    0    0    0    0    0    0    4   -4    0    0    0    0    0    2
+  557           0.10           0.50    0    0    0    0    0    0    1   -2    0    0    0    0    0    1
+  558           0.50          -0.10    0    0    0    0    0    0    0    5    0   -2    0    0    0    2
+  559          -0.10           0.50    0    0    0    0    0    0    0    3   -6    0    0    0    0   -1
+  560           0.00          -0.60    2    0    0   -2   -1    0    0   -2    0    0    5    0    0    0
+  561          -0.40           0.20    2    0   -1   -1   -1    0    0   -1    0    3    0    0    0    0
+  562           0.00          -0.60    1    0   -2   -2   -2    0    0   -2    0    2    0    0    0    0
+  563           0.60           0.00    0    0    2   -2    2    0   -8   11    0    0    0    0    0    0
+  564           0.00          -0.60    0    0    2   -2    1    0   -2    2    0    0    0    0    0    0
+  565           0.20           0.40    0    0    1   -1    1    0    0   -1    0    0    3    0    0    0
+  566          -0.40           0.20    0    0    0    0    0    1    0   -4    0    0    0    0    0   -2
+  567           0.30           0.30    0    0    0    0    0    0    8  -13    0    0    0    0    0    1
+  568           0.40          -0.20    0    0    0    0    0    0    0    6    0    0    0    0    0    2
+  569          -0.40          -0.20    0    0    0    0    0    0    0    6   -6    0    0    0    0    2
+  570           0.00           0.60    0    0    0    0    0    0    0    1    1    0    0    0    0    2
+  571           0.00           0.60    0    0    0    0    0    0    0    1    0    0    1    0    0    2
+  572           0.40           0.20    0    0    0    0    0    0    0    1   -5    0    0    0    0   -2
+  573          -0.20          -0.40    0    0    0    0    0    0    0    0    0    0    3    0    0    1
+  574           0.00           0.60    4    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  575           0.00          -0.60    0    0    0    3    1    0    0    0    0    0    0    0    0    0
+  576           0.00           0.60    3    0    0    2    1    0    0    0    0    0    0    0    0    0
+  577           0.00           0.60    1    1    0   -4   -1    0    0    0    0    0    0    0    0    0
+  578           0.00          -0.60    0    0    0    1    2    0    0    0    0    0    0    0    0    0
+  579           0.00          -0.60    1    1    0   -2    2    0    0    0    0    0    0    0    0    0
+  580           0.00          -0.60    2    0   -2    2   -2    0    0    0    0    0    0    0    0    0
+  581           0.00          -0.50    1    1    0   -4    0    0    0    0    0    0    0    0    0    0
+  582           0.00           0.50    2    0    2    0   -1    0    0    0    0    0    0    0    0    0
+  583           0.10           0.40    2    1    0   -2    0    0    0    0    0    0    0    0    0    0
+  584           0.00          -0.50    0    1    0    2    2    0    0    0    0    0    0    0    0    0
+  585           0.10           0.40    0    0    0    0    1    0    3   -5    0    0    0    0    0    0
+  586           0.00           0.50    1   -2    2   -2    2    0    0    0    0    0    0    0    0    0
+  587           0.00           0.50    2    1    0   -4    1    0    0    0    0    0    0    0    0    0
+  588           0.00          -0.50    1   -2    0    0    1    0    0    0    0    0    0    0    0    0
+  589           0.30          -0.20    2    0    0   -2    1    0    0   -6    8    0    0    0    0    0
+  590          -0.20           0.30    2    0    0   -2   -1    0    0   -5    6    0    0    0    0    0
+  591           0.20           0.30    2    0   -1   -1   -1    0    0    3   -7    0    0    0    0    0
+  592           0.40          -0.10    0    0    2    0    2    0    0   -4    8   -3    0    0    0    0
+  593           0.40           0.10    0    0    2    0    2    0    0    4   -8    3    0    0    0    0
+  594           0.00          -0.50    0    1   -2   -1   -2    0    0    0    0    0    0    0    0    0
+  595           0.00          -0.50    3   -1    2   -2    2    0    0    0    0    0    0    0    0    0
+  596           0.30           0.20    0    0    0    0    0    0    1    0    0    0    0    0    0    2
+  597          -0.30           0.20    0    0    0    0    0    0    0    7  -13    0    0    0    0   -2
+  598           0.20           0.30    0    0    0    0    0    0    0    2   -5    0    0    0    0   -2
+  599          -0.30           0.20    0    0    0    0    0    0    0    1    0    3    0    0    0    2
+  600           0.00           0.50    3   -1    2    2    2    0    0    0    0    0    0    0    0    0
+  601           0.00           0.50    3   -1   -2   -1   -2    0    0    0    0    0    0    0    0    0
+  602           0.00           0.50    0    0    2    6    2    0    0    0    0    0    0    0    0    0
+  603          -0.50           0.00    0    0    1   -1    1    0    0    1    0    0    0    0    0    0
+  604           0.50           0.00    0    0    0    0    0    0    9  -12    0    0    0    0    0   -2
+  605           0.00          -0.50    0    0    0    0    0    0    6   -9    0    0    0    0    0   -1
+  606          -0.50           0.00    0    0    0    0    0    0    4   -4    0    0    0    0    0    1
+  607          -0.50           0.00    0    0    0    0    0    0    0    6  -11    0    0    0    0   -2
+  608           0.00           0.50    0    0    0    0    0    0    0    1   -3    0    0    0    0   -2
+  609           0.40           0.10    0    0    2   -2    1   -1    0    2    0    0    0    0    0    0
+  610          -0.40          -0.10    0    0    1   -1    1    0    0   -1    0    0    0    2    0    0
+  611           0.40          -0.10    0    0    0    0    0    0    5   -6    0    0    0    0    0    2
+  612          -0.40           0.10    0    0    0    0    0    0    5  -10    0    0    0    0    0   -2
+  613           0.10           0.40    0    0    0    0    0    0    0    5    0   -3    0    0    0    2
+  614           0.10           0.40    0    0    0    0    0    0    0    0    0    4    0    0    0    2
+  615          -0.50           0.00    0    0    3    0    2    0    0    0    0    0    0    0    0    0
+  616           0.00           0.50    2    0   -4    0   -1    0    0    0    0    0    0    0    0    0
+  617           0.00          -0.50    2    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  618           0.00           0.50    0    0    2   -2    2    0   -3    3    0    0    0    0    0    0
+  619           0.00           0.50    1    0    0   -1    2    0    0    0    0    0    0    0    0    0
+  620           0.00          -0.50    1    1    0    0    2    0    0    0    0    0    0    0    0    0
+  621           0.50           0.00    0    0    2   -2    2    0   -5    6    0    0    0    0    0    0
+  622           0.00          -0.50    1    0    0    2   -2    0    0    0    0    0    0    0    0    0
+  623           0.00           0.50    1    0   -2    2    0    0    0    0    0    0    0    0    0    0
+  624           0.00          -0.40    1    0    2    2    0    0    0    0    0    0    0    0    0    0
+  625          -0.20           0.20    0    0    0    0    2    0    0   -1    2    0    0    0    0    0
+  626          -0.10           0.30    1    1    0    2    0    0    0    0    0    0    0    0    0    0
+  627           0.00          -0.40    1    0    0    4    0    0    0    0    0    0    0    0    0    0
+  628           0.40           0.00    1    0   -1    0    1    0    0    0    0    0    0    0    0    0
+  629           0.00          -0.40    0    2    0   -2    0    0    0    0    0    0    0    0    0    0
+  630           0.00          -0.40    1    0    0   -3    1    0    0    0    0    0    0    0    0    0
+  631           0.00           0.40    4    0    0    0   -1    0    0    0    0    0    0    0    0    0
+  632           0.00           0.40    1   -2    0   -2   -1    0    0    0    0    0    0    0    0    0
+  633          -0.10           0.30    0    0    0    0    1    0    0   -8   15    0    0    0    0    0
+  634           0.00           0.40    1    0    4   -4    2    0    0    0    0    0    0    0    0    0
+  635           0.00          -0.40    1    1    0   -1    1    0    0    0    0    0    0    0    0    0
+  636           0.00          -0.40    0    0    2    0    2    0    1   -1    0    0    0    0    0    0
+  637           0.00          -0.40    1    1    0    2   -1    0    0    0    0    0    0    0    0    0
+  638           0.00           0.40    2   -2    2    0    2    0    0    0    0    0    0    0    0    0
+  639          -0.20          -0.20    0    0    1   -1    1    0    0   -1    0    0   -2    0    0    0
+  640           0.20          -0.20    0    0    1   -1    1    0    0   -1    0   -2    4    0    0    0
+  641           0.20           0.20    0    0    0    0    0    0    0    2    2    0    0    0    0    2
+  642          -0.10           0.30    2   -2    2   -2    2    0    0    0    0    0    0    0    0    0
+  643          -0.30           0.10    0    0    0    0    0    0    6  -10    0    0    0    0    0   -1
+  644           0.10           0.30    0    0    0    0    0    0    0    6   -5    0    0    0    0    2
+  645          -0.10           0.30    0    0    0    0    0    0    0    2    0   -2    0    0    0    2
+  646           0.00          -0.40    5    0    2   -2    2    0    0    0    0    0    0    0    0    0
+  647           0.00           0.40    3    0    2   -1    2    0    0    0    0    0    0    0    0    0
+  648           0.00           0.40    1    2   -2   -4   -2    0    0    0    0    0    0    0    0    0
+  649           0.00           0.40    1   -1   -2   -3   -2    0    0    0    0    0    0    0    0    0
+  650           0.00           0.40    0    0    4   -1    2    0    0    0    0    0    0    0    0    0
+  651           0.00          -0.40    0    0    2   -2    1    0    0   -2    0    3    0    0    0    0
+  652           0.00          -0.40    0    0    2   -2    1    0    0   -2    0    0    2    0    0    0
+  653           0.40           0.00    0    0    2   -2    1    0    0   -8   11    0    0    0    0    0
+  654          -0.40           0.00    0    0    1   -1    1    0    0   -1    0   -1    2    0    0    0
+  655          -0.40           0.00    0    0    0    0    0    0    8   -8    0    0    0    0    0   -1
+  656          -0.40           0.00    0    0    0    0    0    0    8  -10    0    0    0    0    0   -1
+  657           0.00           0.40    0    0    0    0    0    0    5   -5    0    0    0    0    0    2
+  658           0.00          -0.40    0    0    0    0    0    0    5   -9    0    0    0    0    0   -2
+  659           0.00          -0.40    0    0    0    0    0    0    4   -2    0    0    0    0    0    2
+  660          -0.40           0.00    0    0    0    0    0    0    4   -2    0    0    0    0    0    1
+  661           0.40           0.00    0    0    0    0    0    0    4   -3    0    0    0    0    0    2
+  662           0.00          -0.40    0    0    0    0    0    0    3   -4    0    0    0    0    0   -1
+  663           0.00           0.40    0    0    0    0    0    0    3   -6    0    0    0    0    0   -1
+  664           0.00           0.40    0    0    0    0    0    0    2   -6    0    0    0    0    0   -2
+  665           0.40           0.00    0    0    0    0    0    0    0    8  -15    0    0    0    0   -1
+  666           0.00          -0.40    0    0    0    0    0    0    0    6    0    0    0    0    0    0
+  667          -0.40           0.00    0    0    0    0    0    0    0    5   -2    0    0    0    0    2
+  668           0.00           0.40    0    0    0    0    0    0    0    5   -3    0    0    0    0    2
+  669           0.40           0.00    0    0    0    0    0    0    0    0    0    0    1    0    0    2
+  670           0.00          -0.40    4    0    0    0    0    0    0    0    0    0    0    0    0    0
+  671           0.00          -0.40    1   -2   -2    0   -2    0    0    0    0    0    0    0    0    0
+  672           0.00          -0.40    1    2    2   -2    1    0    0    0    0    0    0    0    0    0
+  673           0.00          -0.40    0    2    2    0    1    0    0    0    0    0    0    0    0    0
+  674           0.00          -0.40    3    1    2    0    1    0    0    0    0    0    0    0    0    0
+  675          -0.10           0.30    0    2   -2    0   -1    0    0    0    0    0    0    0    0    0
+  676           0.00           0.40    1    1    2    1    1    0    0    0    0    0    0    0    0    0
+  677           0.00           0.40    3   -1    2    0    1    0    0    0    0    0    0    0    0    0
+  678           0.00           0.40    2    0    2   -1    1    0    0    0    0    0    0    0    0    0
+  679           0.00          -0.40    2    0    0    2    2    0    0    0    0    0    0    0    0    0
+  680           0.40           0.00    0    0    1   -1    2    0    0   -1    0    2    0    0    0    0
+  681           0.00           0.40    0    0    2   -2   -2    0    0    0    0    0    0    0    0    0
+  682           0.21           0.10    0    0    1   -1    2    0    0   -1    0   -2    5    0    0    0
+  683           0.00           0.30    2    0   -4    2   -2    0    0    0    0    0    0    0    0    0
+  684          -0.30           0.00    0    0    2   -2   -1    0   -5    6    0    0    0    0    0    0
+  685           0.00          -0.30    2   -2    0   -2    1    0    0    0    0    0    0    0    0    0
+  686           0.00           0.30    0    0    0    4    2    0    0    0    0    0    0    0    0    0
+  687           0.00           0.30    2    0    0   -2   -1    0   -3    3    0    0    0    0    0    0
+  688           0.20           0.10    0    0    1   -1   -1    0    0   -1    0   -1    0    0    0    0
+  689           0.00          -0.30    1   -2    0   -2    1    0    0    0    0    0    0    0    0    0
+  690           0.00           0.30    1   -2    0    0   -1    0    0    0    0    0    0    0    0    0
+  691           0.30           0.00    0    0    0    0    1    0    0    0    0    0   -1    0    0    0
+  692           0.00           0.30    2    0    0   -3   -1    0    0    0    0    0    0    0    0    0
+  693           0.00          -0.30    2    1   -2    0    1    0    0    0    0    0    0    0    0    0
+  694          -0.20           0.10    2    0    0   -2   -1    0    0   -6    8    0    0    0    0    0
+  695          -0.10          -0.20    2    0   -1   -1    1    0    0    3   -7    0    0    0    0    0
+  696           0.00          -0.30    2    1    2   -4    1    0    0    0    0    0    0    0    0    0
+  697           0.10          -0.20    1    0    0   -1    1    0    0   -3    4    0    0    0    0    0
+  698           0.00           0.30    2   -1   -2    0   -2    0    0    0    0    0    0    0    0    0
+  699           0.00           0.30    0    0    2    0    2    0   -1    1    0    0    0    0    0    0
+  700           0.00          -0.30    0    0    2    0    2    0    0   -1    0    1    0    0    0    0
+  701           0.00           0.30    0    0    2    0    2    0    0    1    0   -1    0    0    0    0
+  702           0.00           0.30    0    1    0   -4    1    0    0    0    0    0    0    0    0    0
+  703          -0.20           0.10    0    0    0    0    1    0    0   -9   17    0    0    0    0    0
+  704           0.00          -0.30    1    1    4   -2    2    0    0    0    0    0    0    0    0    0
+  705          -0.10          -0.20    2    0    2    0    1    0    0    1    0    0    0    0    0    0
+  706          -0.10           0.20    1    0   -2    0   -2    0  -10    3    0    0    0    0    0    0
+  707           0.20          -0.10    0    0    2   -2    1    0    0   -7    9    0    0    0    0    0
+  708          -0.10          -0.20    0    0    0    0    0    0    2   -3    0    0    0    0    0    1
+  709           0.20           0.10    0    0    0    0    0    0    1   -2    0    0    0    0    0   -2
+  710           0.20          -0.10    0    0    0    0    0    0    1   -4    0    0    0    0    0   -2
+  711          -0.20          -0.10    0    0    0    0    0    0    0    6  -10    0    0    0    0   -2
+  712          -0.10          -0.20    0    0    0    0    0    0    0    5   -8    0    0    0    0   -2
+  713           0.20          -0.10    0    0    0    0    0    0    0    3   -5    0    0    0    0   -1
+  714           0.20           0.10    0    0    0    0    0    0    0    2   -6    0    0    0    0   -2
+  715           0.00           0.30    4    0    2   -4    2    0    0    0    0    0    0    0    0    0
+  716           0.00          -0.30    2    2    2   -2    2    0    0    0    0    0    0    0    0    0
+  717           0.00           0.30    2    1    2    1    2    0    0    0    0    0    0    0    0    0
+  718           0.00           0.30    2    0    0   -2   -1    0    0   -2    0    4   -5    0    0    0
+  719           0.00          -0.30    2    0    0   -2   -2    0   -3    3    0    0    0    0    0    0
+  720           0.30           0.00    2    0   -1   -1   -1    0    0   -1    0    0    0    0    0    0
+  721           0.00          -0.30    1    0    2    3    2    0    0    0    0    0    0    0    0    0
+  722           0.00           0.30    1    0    2   -2    2    0    0   -2    0    2    0    0    0    0
+  723           0.30           0.00    1    0    1   -1    1    0    0   -1    0    0    0    0    0    0
+  724           0.30           0.00    1    0   -1    1   -1    0  -18   17    0    0    0    0    0    0
+  725           0.00          -0.30    1    0   -1   -1   -1    0   20  -20    0    0    0    0    0    0
+  726           0.00          -0.30    1    0   -2   -2   -2    0   -3    3    0    0    0    0    0    0
+  727           0.00          -0.30    0    2    2    2    2    0    0    0    0    0    0    0    0    0
+  728           0.00           0.30    0    2   -2   -4   -2    0    0    0    0    0    0    0    0    0
+  729           0.00           0.30    0    1    2    3    2    0    0    0    0    0    0    0    0    0
+  730           0.00          -0.30    0    0    2   -2    1    0    0   -1    0    1    0    0    0    0
+  731           0.30           0.00    0    0    1   -1    1    0    1   -2    0    0    0    0    0    0
+  732           0.30           0.00    0    0    1   -1    1    0   -2    1    0    0    0    0    0    0
+  733          -0.30           0.00    0    0    0    0    0    0    9  -11    0    0    0    0    0   -1
+  734           0.00           0.30    0    0    0    0    0    0    8  -16    0    0    0    0    0   -2
+  735          -0.30           0.00    0    0    0    0    0    0    5   -3    0    0    0    0    0    1
+  736           0.30           0.00    0    0    0    0    0    0    0    6    0    0    0    0    0    1
+  737          -0.30           0.00    0    0    0    0    0    0    0    6   -7    0    0    0    0    2
+  738           0.00           0.30    0    0    0    0    0    0    0    4    0    0   -2    0    0    2
+  739           0.30           0.00    0    0    0    0    0    0    0    4   -8    1    5    0    0   -2
+  740          -0.30           0.00    0    0    0    0    0    0    0    3    0    0   -2    0    0    2
+  741           0.30           0.00    0    0    0    0    0    0    0    1    0   -1    0    0    0    1
+  742           0.30           0.00    0    0    0    0    0    0    0    1    0   -3    0    0    0   -1
+  743           0.30           0.00    0    0    0    0    0    0    0    1   -6    0    0    0    0   -2
+  744           0.00          -0.30    0    0    0    0    0    0    0    0    0    4   -5    0    0    2
+  745           0.00           0.30    0    0    0    0    0    0    0    0    0    0    5    0    0    2
+  746           0.00           0.30    0    0    0    0    0    0    0    0    0    0    0    2    0    2
+  747           0.30           0.00    0    0    0    0    0    0    0    0    0    0    0    2    0    1
+  748           0.00           0.30    0    0    0    0    0    0    0    0    0    0    0    0    2    2
+  749           0.00          -0.30    1    0    0   -1   -1    0    0   -2    2    0    0    0    0    0
+  750           0.00          -0.30    2   -1    2   -1    2    0    0    0    0    0    0    0    0    0
+  751           0.30           0.00    2    0   -1   -1   -1    0    0   -1    0    2    0    0    0    0
+  752           0.00           0.30    1    0    0   -6   -1    0    0    0    0    0    0    0    0    0
+  753           0.00          -0.30    1   -1    0   -4   -1    0    0    0    0    0    0    0    0    0
+  754           0.00           0.30    1    0    0    4   -1    0    0    0    0    0    0    0    0    0
+  755           0.00          -0.30    3    0    0   -2    1    0    0    0    0    0    0    0    0    0
+  756           0.30           0.00    0    0    0    0    1    0    5   -8    0    0    0    0    0    0
+  757           0.00          -0.30    1   -2   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  758           0.00          -0.30    0    1    4   -2    1    0    0    0    0    0    0    0    0    0
+  759           0.00          -0.30    2    0    4   -2    1    0    0    0    0    0    0    0    0    0
+  760           0.00          -0.30    0    0    2    3    1    0    0    0    0    0    0    0    0    0
+  761           0.30           0.00    0    0    1   -1    2    0    0   -1    0    1    0    0    0    0
+  762           0.00           0.30    1   -2    2    0    1    0    0    0    0    0    0    0    0    0
+  763           0.00          -0.30    2   -1    2   -2    1    0    0    0    0    0    0    0    0    0
+  764           0.00           0.30    2    0   -2   -6   -1    0    0    0    0    0    0    0    0    0
+  765           0.00          -0.30    2    0   -4   -2   -1    0    0    0    0    0    0    0    0    0
+  766           0.00          -0.30    2    0    2    1    1    0    0    0    0    0    0    0    0    0
+  767           0.00           0.30    0    0    1   -1    2    0    0    0   -2    0    0    0    0    0
+  768          -0.30           0.00    0    0    0    0    2    0    0    4   -8    3    0    0    0    0
+  769          -0.30           0.00    0    0    0    0    2    0    0   -4    8   -3    0    0    0    0
+  770           0.00           0.30    0    0    0    1   -2    0    0    0    0    0    0    0    0    0
+  771           0.00          -0.30    0    0    2    0   -2    0    0    0    0    0    0    0    0    0
+  772           0.00          -0.30    0    1    0   -2    2    0    0    0    0    0    0    0    0    0
+  773          -0.20          -0.10    0    0    0    0    1    0    0    1    0   -2    0    0    0    0
+  774           0.00          -0.30    0    0    0    0    1    0    2   -2    0    0    0    0    0    0
+  775           0.00          -0.30    1    1    2   -4    2    0    0    0    0    0    0    0    0    0
+  776           0.00          -0.21    0    1    2   -2    3    0    0    0    0    0    0    0    0    0
+  777           0.00           0.20    2    0    2   -2    0    0    0    0    0    0    0    0    0    0
+  778           0.00          -0.20    0    0    0    0    1    0   -2    2    0    0    0    0    0    0
+  779           0.00          -0.20    3    0    2    0    0    0    0    0    0    0    0    0    0    0
+  780           0.00          -0.20    0    0    0    0    1    0    0   -2    2    0    0    0    0    0
+  781           0.00          -0.20    0    1    0   -4    0    0    0    0    0    0    0    0    0    0
+  782           0.20           0.00    0    0    0    0    1    0   -3    4    0    0    0    0    0    0
+  783           0.00          -0.20    3    0    0    2    0    0    0    0    0    0    0    0    0    0
+  784           0.00           0.20    0    3    0    0    0    0    0    0    0    0    0    0    0    0
+  785           0.00           0.20    2    0   -2   -2    0    0    0    0    0    0    0    0    0    0
+  786           0.20           0.00    2    0    2   -4    0    0    0    0    0    0    0    0    0    0
+  787           0.00           0.20    1    0    0   -3   -1    0    0    0    0    0    0    0    0    0
+  788           0.00          -0.20    2    0    2   -2   -1    0    0    0    0    0    0    0    0    0
+  789           0.00           0.20    1    0    2   -4   -1    0    0    0    0    0    0    0    0    0
+  790           0.00           0.20    0    0    1   -1    2    0    0   -1    0    0    1    0    0    0
+  791           0.00           0.20    1    0   -2    1    1    0    0    0    0    0    0    0    0    0
+  792           0.00          -0.20    1    2    0   -2    0    0    0    0    0    0    0    0    0    0
+  793           0.00          -0.20    2    0   -2   -2    1    0    0    0    0    0    0    0    0    0
+  794           0.00          -0.20    1    0    0   -1    1    0    0   -1    0    1    0    0    0    0
+  795           0.00          -0.20    2    0    0   -3    1    0    0    0    0    0    0    0    0    0
+  796           0.00          -0.20    1    1    0    1    1    0    0    0    0    0    0    0    0    0
+  797           0.00           0.20    1    1    0    1   -1    0    0    0    0    0    0    0    0    0
+  798           0.00          -0.20    2    0    0   -1    1    0    0    0    0    0    0    0    0    0
+  799           0.00           0.20    1    2    0    0    1    0    0    0    0    0    0    0    0    0
+  800           0.00          -0.20    2    0    0   -2    1    0    0   -5    6    0    0    0    0    0
+  801           0.00           0.20    1    0    0   -2   -1    0    0   -2    0    2    0    0    0    0
+  802           0.00          -0.20    1    0    0   -2    1    0    0   -2    0    2    0    0    0    0
+  803           0.00           0.20    2    0   -4    2   -1    0    0    0    0    0    0    0    0    0
+  804           0.20           0.00    0    0    2   -2    1    0    0    4   -8    3    0    0    0    0
+  805           0.20           0.00    0    0    2   -2    1    0    0   -4    8   -3    0    0    0    0
+  806           0.00           0.20    2   -1    0    2   -1    0    0    0    0    0    0    0    0    0
+  807           0.00           0.20    1    0    0   -1   -1    0    0   -3    4    0    0    0    0    0
+  808           0.10          -0.10    1   -2    0   -2    0    0    0    0    0    0    0    0    0    0
+  809           0.00          -0.20    2    0    0   -2   -1    0    0   -2    0    3   -1    0    0    0
+  810           0.00           0.20    1   -1   -4    2   -2    0    0    0    0    0    0    0    0    0
+  811           0.00           0.20    3    0    0    2   -1    0    0    0    0    0    0    0    0    0
+  812           0.00           0.20    1    0    0   -3    0    0    0    0    0    0    0    0    0    0
+  813           0.00           0.20    2    0    2   -6    1    0    0    0    0    0    0    0    0    0
+  814           0.00           0.20    2   -1   -2    2   -1    0    0    0    0    0    0    0    0    0
+  815           0.00           0.20    1   -2   -2    2   -1    0    0    0    0    0    0    0    0    0
+  816           0.00           0.20    2    0    4   -4    2    0    0    0    0    0    0    0    0    0
+  817           0.20           0.00    2    0   -1   -1   -2    0    0   -1    0    2    0    0    0    0
+  818           0.00          -0.20    4    1    2    0    2    0    0    0    0    0    0    0    0    0
+  819           0.00           0.20    4   -1    2    0    2    0    0    0    0    0    0    0    0    0
+  820           0.00          -0.20    4   -1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+  821           0.00          -0.20    3    0    4   -2    2    0    0    0    0    0    0    0    0    0
+  822           0.00          -0.20    3    0    2    1    2    0    0    0    0    0    0    0    0    0
+  823           0.00           0.20    3    0   -2    2   -1    0    0    0    0    0    0    0    0    0
+  824           0.00          -0.20    3    0   -2   -1   -1    0    0    0    0    0    0    0    0    0
+  825           0.00           0.20    2    2   -2   -4   -2    0    0    0    0    0    0    0    0    0
+  826           0.00          -0.20    2    1    0   -4    0    0    0    0    0    0    0    0    0    0
+  827           0.00           0.20    2    1   -2   -6   -2    0    0    0    0    0    0    0    0    0
+  828           0.00           0.20    2    0    2   -3    2    0    0    0    0    0    0    0    0    0
+  829           0.00           0.20    2   -2    2    2    2    0    0    0    0    0    0    0    0    0
+  830           0.00          -0.20    1    1    2    4    2    0    0    0    0    0    0    0    0    0
+  831           0.00          -0.20    1    1   -2   -3   -2    0    0    0    0    0    0    0    0    0
+  832           0.00           0.20    1    1   -2   -6   -2    0    0    0    0    0    0    0    0    0
+  833          -0.20           0.00    1    0    3    0    3    0    0    0    0    0    0    0    0    0
+  834           0.20           0.00    1    0    1    1    1    0    0    1    0    0    0    0    0    0
+  835           0.20           0.00    1    0   -1    1   -1    0    0    1    0    0    0    0    0    0
+  836           0.00           0.20    1    0   -1    0   -1    0   -3    5    0    0    0    0    0    0
+  837           0.20           0.00    1    0   -1   -2   -1    0    0    0    0    0    0    0    0    0
+  838           0.00           0.20    1    0   -2   -2   -2    0    0   -2    0    3    0    0    0    0
+  839           0.00          -0.20    1   -1    2    1    2    0    0    0    0    0    0    0    0    0
+  840           0.00           0.20    1   -1   -2    1   -1    0    0    0    0    0    0    0    0    0
+  841           0.00           0.20    0    3   -2   -2   -2    0    0    0    0    0    0    0    0    0
+  842           0.00          -0.20    0    0    4    2    2    0    0    0    0    0    0    0    0    0
+  843           0.00           0.20    0    0    2   -2    1    0    0    1    0   -1    0    0    0    0
+  844           0.00           0.20    0    0    2   -2    1    0    0   -2    0    0    0    0    0    0
+  845           0.00          -0.20    0    0    2   -2    1    0    0   -3    0    3    0    0    0    0
+  846           0.00          -0.20    0    0    2   -2    1    0    0   -4    4    0    0    0    0    0
+  847           0.00          -0.20    0    0    2   -2    1    0   -5    5    0    0    0    0    0    0
+  848           0.00           0.20    0    0    1   -1    1    0    1   -3    0    0    0    0    0    0
+  849           0.00          -0.20    0    0    1   -1    1    0    0    1   -4    0    0    0    0    0
+  850           0.20           0.00    0    0    1   -1    1    0    0   -1    0    1   -3    0    0    0
+  851           0.20           0.00    0    0    1   -1    1    0    0   -1    0    0    0   -1    0    0
+  852           0.00          -0.20    0    0    1   -1    1    0    0   -4    6    0    0    0    0    0
+  853           0.20           0.00    0    0    1   -1    1    0   -5    6    0    0    0    0    0    0
+  854           0.00           0.20    0    0    0    0    0    0    8  -12    0    0    0    0    0   -2
+  855           0.00          -0.20    0    0    0    0    0    0    7  -10    0    0    0    0    0   -1
+  856           0.20           0.00    0    0    0    0    0    0    7  -11    0    0    0    0    0   -1
+  857          -0.20           0.00    0    0    0    0    0    0    6   -4    0    0    0    0    0    1
+  858          -0.20           0.00    0    0    0    0    0    0    6   -6    0    0    0    0    0    1
+  859          -0.20           0.00    0    0    0    0    0    0    5   -5    0    0    0    0    0    1
+  860           0.00          -0.20    0    0    0    0    0    0    5   -6    0    0    0    0    0   -1
+  861          -0.20           0.00    0    0    0    0    0    0    4   -2    0    0    0    0    0    0
+  862           0.00          -0.20    0    0    0    0    0    0    4   -5    0    0    0    0    0   -1
+  863           0.20           0.00    0    0    0    0    0    0    4   -5    0    0    0    0    0   -2
+  864           0.00          -0.20    0    0    0    0    0    0    3   -4    0    0    0    0    0    1
+  865           0.20           0.00    0    0    0    0    0    0    3   -4    0    0    0    0    0   -2
+  866          -0.20           0.00    0    0    0    0    0    0    3   -8    0    0    0    0    0   -2
+  867           0.00           0.20    0    0    0    0    0    0    2   -5    0    0    0    0    0   -1
+  868           0.00           0.20    0    0    0    0    0    0    1   -2    0    0    0    0    0   -1
+  869           0.00           0.20    0    0    0    0    0    0    1   -4    0    0    0    0    0   -1
+  870           0.00          -0.20    0    0    0    0    0    0    0    9  -17    0    0    0    0   -2
+  871          -0.20           0.00    0    0    0    0    0    0    0    7   -7    0    0    0    0    2
+  872          -0.20           0.00    0    0    0    0    0    0    0    7   -8    0    0    0    0    2
+  873          -0.20           0.00    0    0    0    0    0    0    0    7   -9    0    0    0    0    2
+  874          -0.20           0.00    0    0    0    0    0    0    0    5   -6    0    0    0    0    2
+  875           0.20           0.00    0    0    0    0    0    0    0    5  -10    0    0    0    0   -2
+  876           0.00           0.20    0    0    0    0    0    0    0    4    0   -4    0    0    0    2
+  877           0.00          -0.20    0    0    0    0    0    0    0    4   -6    0    0    0    0   -2
+  878           0.00          -0.20    0    0    0    0    0    0    0    4   -7    0    0    0    0   -1
+  879           0.00          -0.20    0    0    0    0    0    0    0    4   -8    3    0    0    0    1
+  880           0.00           0.20    0    0    0    0    0    0    0    4   -8    3    0    0    0   -1
+  881           0.20           0.00    0    0    0    0    0    0    0    4   -8    1    5    0    0    2
+  882           0.20           0.00    0    0    0    0    0    0    0    3    0    0    0    0    0    2
+  883           0.00           0.20    0    0    0    0    0    0    0    3   -8    3    0    0    0   -2
+  884           0.20           0.00    0    0    0    0    0    0    0    2    0    0   -2    0    0    1
+  885           0.00          -0.20    0    0    0    0    0    0    0    2    0   -5    0    0    0   -2
+  886           0.00          -0.20    0    0    0    0    0    0    0    2   -4    0    0    0    0    1
+  887           0.20           0.00    0    0    0    0    0    0    0    2   -7    0    0    0    0   -2
+  888           0.20           0.00    0    0    0    0    0    0    0    1    0    1    0    0    0    1
+  889           0.00           0.20    0    0    0    0    0    0    0    1    0    0    0    0    0   -1
+  890           0.20           0.00    0    0    0    0    0    0    0    1    0   -1    0    0    0   -1
+  891           0.20           0.00    0    0    0    0    0    0    0    1    0   -2    5    0    0    2
+  892           0.00           0.20    0    0    0    0    0    0    0    1    0   -2    0    0    0   -2
+  893           0.00          -0.20    0    0    0    0    0    0    0    1    0   -5    0    0    0   -2
+  894           0.10          -0.10    0    0    0    0    0    0    0    2    1    0    0    0    0    2
+  895           0.00          -0.20    1    0    4    0    1    0    0    0    0    0    0    0    0    0
+  896           0.00           0.20    4    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+  897           0.00          -0.20    0    1    0    4    1    0    0    0    0    0    0    0    0    0
+  898           0.00           0.20    2    0    0    4    1    0    0    0    0    0    0    0    0    0
+  899           0.00           0.20    0    0    0    0    1    0    0    7  -13    0    0    0    0    0
+  900           0.00          -0.20    2    1    0    2    1    0    0    0    0    0    0    0    0    0
+  901           0.00           0.20    1   -1    0    4    1    0    0    0    0    0    0    0    0    0
+  902           0.20           0.00    0    0    2   -2    1    0   -8   11    0    0    0    0    0    0
+  903           0.00           0.20    1    0    2   -6    1    0    0    0    0    0    0    0    0    0
+  904           0.00           0.20    0    0    2   -2    2    0    0   -2    0    2    0    0    0    0
+  905           0.00          -0.20    1    2    2    0    1    0    0    0    0    0    0    0    0    0
+  906           0.00           0.20    3    0   -2   -6   -1    0    0    0    0    0    0    0    0    0
+  907           0.00           0.20    2    0    0   -6   -1    0    0    0    0    0    0    0    0    0
+  908           0.00           0.20    1   -1    2    4    1    0    0    0    0    0    0    0    0    0
+  909           0.00          -0.20    2    1    2    2    1    0    0    0    0    0    0    0    0    0
+  910          -0.20           0.00    0    0    1    1    2    0    0    1    0    0    0    0    0    0
+  911           0.00           0.20    2   -1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  912           0.00          -0.20    0    1   -2    4   -1    0    0    0    0    0    0    0    0    0
+  913           0.00           0.20    2    0    2    4    1    0    0    0    0    0    0    0    0    0
+  914           0.00          -0.20    1   -1   -2   -4   -1    0    0    0    0    0    0    0    0    0
+  915           0.00          -0.20    1    0   -4   -2   -1    0    0    0    0    0    0    0    0    0
+  916           0.00           0.20    1   -2    2    2    1    0    0    0    0    0    0    0    0    0
+  917           0.00           0.20    1    0   -2   -6   -1    0    0    0    0    0    0    0    0    0
+  918           0.00          -0.20    3    1    2   -2    1    0    0    0    0    0    0    0    0    0
+  919           0.00          -0.20    2   -2    0   -2   -2    0    0    0    0    0    0    0    0    0
+  920           0.00           0.20    2   -1    0    2    1    0    0    0    0    0    0    0    0    0
+  921           0.00           0.20    3    0    0    0    2    0    0    0    0    0    0    0    0    0
+  922           0.00          -0.20    1   -1    2   -3    1    0    0    0    0    0    0    0    0    0
+  923           0.00           0.20    0    0    1   -1    2    0   -5    7    0    0    0    0    0    0
+  924           0.00          -0.20    2    1    0   -2   -2    0    0    0    0    0    0    0    0    0
+  925          -0.20           0.00    0    0    1   -1    2    0    0   -1    0   -1    0    0    0    0
+  926           0.00          -0.20    2    1   -2    0    0    0    0    0    0    0    0    0    0    0
+  927           0.00           0.20    1    0   -2    0    2    0    0    0    0    0    0    0    0    0
+  928           0.00          -0.20    1   -1    0    0   -2    0    0    0    0    0    0    0    0    0
+  929           0.00          -0.20    0    2    0    0    2    0    0    0    0    0    0    0    0    0
+  930          -0.20           0.00    0    0    0    0    1    0    3   -4    0    0    0    0    0    0
+  931           0.00          -0.20    0    0    0    0    1    0    0    2   -2    0    0    0    0    0
+  932           0.00           0.20    0    0    0    0    1    0    0    2    0   -2    0    0    0    0
+  933           0.00          -0.20    0    1    2   -4    2    0    0    0    0    0    0    0    0    0
+  934           0.00           0.20    0    0    1   -1    2    0   -8   12    0    0    0    0    0    0
+  935           0.00           0.20    1    1   -2    2   -2    0    0    0    0    0    0    0    0    0
+  936           0.00          -0.19    0    1    2   -2    0    0    0    0    0    0    0    0    0    0
+  937           0.00           0.17    0    1   -2    2   -3    0    0    0    0    0    0    0    0    0
+  938           0.00           0.11    1    0   -2    0   -3    0    0    0    0    0    0    0    0    0
+  939           0.00          -0.10    1    1   -2   -2    0    0    0    0    0    0    0    0    0    0
+  940           0.10           0.00    0    0    0    0    1    0    0   -1    0    2    0    0    0    0
+  941           0.00          -0.10    0    1   -2   -2    0    0    0    0    0    0    0    0    0    0
+  942           0.00           0.10    1    0    0    0   -1    0  -10    3    0    0    0    0    0    0
+  943           0.00          -0.10    1    0    0    0    1    0  -10    3    0    0    0    0    0    0
+  944           0.00          -0.10    1    0   -2   -4    0    0    0    0    0    0    0    0    0    0
+  945           0.00          -0.10    2   -1    0    2    0    0    0    0    0    0    0    0    0    0
+  946           0.00          -0.10    0    2    0    0   -2    0    0    0    0    0    0    0    0    0
+  947           0.00          -0.10    1    0    0   -6    0    0    0    0    0    0    0    0    0    0
+  948           0.00           0.10    0    1    4   -4    2    0    0    0    0    0    0    0    0    0
+  949           0.00          -0.10    2    0    0   -6    0    0    0    0    0    0    0    0    0    0
+  950          -0.10           0.00    0    0    0    0    2    0    0    0    0    1    0    0    0    0
+  951           0.00          -0.10    3    0    0   -4    0    0    0    0    0    0    0    0    0    0
+  952           0.00          -0.10    2   -1   -2    0    1    0    0    0    0    0    0    0    0    0
+  953           0.00           0.10    2    2    0   -2   -1    0    0    0    0    0    0    0    0    0
+  954           0.00          -0.10    0    0    0    3    2    0    0    0    0    0    0    0    0    0
+  955           0.00          -0.10    3   -1    0    0    0    0    0    0    0    0    0    0    0    0
+  956           0.10           0.00    0    0    2    0    2    0    2   -3    0    0    0    0    0    0
+  957           0.10           0.00    0    0    2    0    2    0   -2    3    0    0    0    0    0    0
+  958           0.00           0.10    0    0    2    0    2    0    2   -2    0    0    0    0    0    0
+  959           0.00          -0.10    0    0    2    0    2    0   -2    2    0    0    0    0    0    0
+  960           0.00          -0.10    2   -1   -2    0    0    0    0    0    0    0    0    0    0    0
+  961           0.00           0.10    2    0   -2   -2   -2    0    0   -2    0    2    0    0    0    0
+  962           0.00           0.10    1    2    2   -4    1    0    0    0    0    0    0    0    0    0
+
+j = 1  Nb of terms = 277
+
+  963      153041.82         878.89    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+  964       11714.49        -289.32    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+  965        2024.68         -50.99    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+  966       -1837.33          47.75    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+  967       -1312.21         -28.91    0    1    0    0    0    0    0    0    0    0    0    0    0    0
+  968        -632.54           0.78    1    0    0    0    0    0    0    0    0    0    0    0    0    0
+  969         459.68         -67.23    0    1    2   -2    2    0    0    0    0    0    0    0    0    0
+  970         344.50           1.46    0    0    2    0    1    0    0    0    0    0    0    0    0    0
+  971         268.14          -7.03    1    0    2    0    2    0    0    0    0    0    0    0    0    0
+  972         192.06          29.80    0    1   -2    2   -2    0    0    0    0    0    0    0    0    0
+  973         139.64           0.15    1    0    0   -2    0    0    0    0    0    0    0    0    0    0
+  974        -113.94          -1.06    0    0    2   -2    1    0    0    0    0    0    0    0    0    0
+  975         109.81           3.18    1    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+  976         -56.37           0.13    0    0    0    2    0    0    0    0    0    0    0    0    0    0
+  977         -56.17          -0.02    1    0    0    0    1    0    0    0    0    0    0    0    0    0
+  978         -53.05          -1.23    1    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+  979         -51.60           0.17    1    0    0    0   -1    0    0    0    0    0    0    0    0    0
+  980          45.91          -0.11    1    0    2    0    1    0    0    0    0    0    0    0    0    0
+  981         -42.45           0.02    2    0    0   -2    0    0    0    0    0    0    0    0    0    0
+  982          40.82          -1.03    2    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+  983          34.30          -1.24    0    0    2    2    2    0    0    0    0    0    0    0    0    0
+  984          28.89           0.00    0    2   -2    2   -2    0    0    0    0    0    0    0    0    0
+  985          27.61          -1.22    2    0    2    0    2    0    0    0    0    0    0    0    0    0
+  986         -25.43           1.00    1    0    2   -2    2    0    0    0    0    0    0    0    0    0
+  987         -26.01           0.07    2    0    0    0    0    0    0    0    0    0    0    0    0    0
+  988         -23.02           0.06    0    0    2    0    0    0    0    0    0    0    0    0    0    0
+  989          19.37          -0.01    0    0    2   -2    0    0    0    0    0    0    0    0    0    0
+  990          14.05          -4.19    0    2    2   -2    2    0    0    0    0    0    0    0    0    0
+  991          18.18          -0.01    1    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+  992         -14.86          -0.09    0    2    0    0    0    0    0    0    0    0    0    0    0    0
+  993          13.49          -0.01    1    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+  994          12.44          -0.27    0    1    0    0    1    0    0    0    0    0    0    0    0    0
+  995          11.46           0.03    1    0    0   -2    1    0    0    0    0    0    0    0    0    0
+  996         -11.33          -0.06    0    1    0    0   -1    0    0    0    0    0    0    0    0    0
+  997          -9.81           0.01    2    0   -2    0    0    0    0    0    0    0    0    0    0    0
+  998          -9.08          -0.02    1    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+  999           2.74          -4.56    0    0    1   -1    1    0    0   -1    0   -2    5    0    0    0
+ 1000           6.84          -0.04    1    0    2    2    2    0    0    0    0    0    0    0    0    0
+ 1001          -6.73           0.01    0    1    2    0    2    0    0    0    0    0    0    0    0    0
+ 1002           6.54           0.01    1    1    0   -2    0    0    0    0    0    0    0    0    0    0
+ 1003          -6.35          -0.01    0    1   -2    0   -2    0    0    0    0    0    0    0    0    0
+ 1004           5.90          -0.02    0    0    2    2    1    0    0    0    0    0    0    0    0    0
+ 1005          -5.85           0.02    1    0    0    2    0    0    0    0    0    0    0    0    0    0
+ 1006          -5.73           0.01    2    0    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1007           5.60           0.00    0    0    0    2    1    0    0    0    0    0    0    0    0    0
+ 1008          -5.16           0.00    1    0    2   -2    1    0    0    0    0    0    0    0    0    0
+ 1009          -5.14           0.01    2    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+ 1010           4.76          -0.02    2    0    2    0    1    0    0    0    0    0    0    0    0    0
+ 1011          -4.40           0.02    0    0    0    2   -1    0    0    0    0    0    0    0    0    0
+ 1012          -4.22           0.00    0    1   -2    2   -1    0    0    0    0    0    0    0    0    0
+ 1013          -4.20           0.01    1   -1    0    0    0    0    0    0    0    0    0    0    0    0
+ 1014           3.58           0.31    1    0    0   -1    0    0    0    0    0    0    0    0    0    0
+ 1015           3.87           0.01    0    1    0   -2    0    0    0    0    0    0    0    0    0    0
+ 1016           3.76           0.00    0    0    0    1    0    0    0    0    0    0    0    0    0    0
+ 1017          -3.62          -0.01    2    0    0   -2    1    0    0    0    0    0    0    0    0    0
+ 1018          -3.61           0.00    1    0   -2    0    0    0    0    0    0    0    0    0    0    0
+ 1019          -1.28          -2.14    0    0    0    0    0    0    0    0    0    2   -5    0    0   -1
+ 1020          -3.18           0.00    0    1    2   -2    1    0    0    0    0    0    0    0    0    0
+ 1021           3.01           0.00    1    1    0    0    0    0    0    0    0    0    0    0    0    0
+ 1022          -2.97           0.01    1    0    2    0    0    0    0    0    0    0    0    0    0    0
+ 1023           2.91           0.00    1   -1    0   -1    0    0    0    0    0    0    0    0    0    0
+ 1024          -2.73           0.00    2    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+ 1025           2.58          -0.01    3    0    2    0    2    0    0    0    0    0    0    0    0    0
+ 1026           2.56          -0.01    1   -1    2    0    2    0    0    0    0    0    0    0    0    0
+ 1027          -2.51          -0.01    1    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+ 1028          -2.35          -0.01    0    1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+ 1029          -2.21           0.01    1    1    2    0    2    0    0    0    0    0    0    0    0    0
+ 1030          -2.04           0.01    2    0    0    0   -1    0    0    0    0    0    0    0    0    0
+ 1031          -1.94           0.00    2    0    0    0    1    0    0    0    0    0    0    0    0    0
+ 1032           0.41          -1.43    0    0    0    0    0    0    0    4   -8    3    0    0    0    0
+ 1033          -1.84           0.00    0    0    0    0    0    0    3   -5    0    0    0    0    0   -2
+ 1034          -1.77           0.01    1    0   -2    2   -1    0    0    0    0    0    0    0    0    0
+ 1035           0.00           1.77    0    1   -1    1   -1    0    0    0    0    0    0    0    0    0
+ 1036           1.76           0.00    1    0    0    0    2    0    0    0    0    0    0    0    0    0
+ 1037          -1.07          -0.53    0    0    1   -1    1    0   -8   12    0    0    0    0    0    0
+ 1038          -1.48           0.00    0    0    2    1    2    0    0    0    0    0    0    0    0    0
+ 1039          -1.40           0.01    3    0    0    0    0    0    0    0    0    0    0    0    0    0
+ 1040          -1.35          -0.01    1    0   -2   -4   -2    0    0    0    0    0    0    0    0    0
+ 1041          -1.32           0.00    0    0    0    0    0    0    1   -1    0    0    0    0    0    0
+ 1042          -1.28           0.00    0    0    0    0    0    0    0    8  -16    4    5    0    0    0
+ 1043           1.24           0.00    1    0    0    0   -2    0    0    0    0    0    0    0    0    0
+ 1044           1.23           0.00    2    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+ 1045           1.19           0.00    1    0    0   -4    0    0    0    0    0    0    0    0    0    0
+ 1046           1.18          -0.01    1    0    2    2    1    0    0    0    0    0    0    0    0    0
+ 1047           1.17           0.00    1   -1    0   -1   -1    0    0    0    0    0    0    0    0    0
+ 1048          -1.15           0.00    1    1    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1049           1.14           0.00    2    0    0   -4    0    0    0    0    0    0    0    0    0    0
+ 1050          -1.14           0.00    0    2   -2    2   -1    0    0    0    0    0    0    0    0    0
+ 1051           1.09           0.03    0    0    0    0    0    0    0    1    0   -1    0    0    0    0
+ 1052          -1.08           0.00    2    0   -2   -4   -2    0    0    0    0    0    0    0    0    0
+ 1053           1.04           0.00    0    0    0    0    0    0    0    0    0    2    0    0    0    2
+ 1054           1.02           0.00    1    0   -4    0   -2    0    0    0    0    0    0    0    0    0
+ 1055           0.98          -0.01    2    0    2    2    2    0    0    0    0    0    0    0    0    0
+ 1056           0.91           0.02    1    0    0   -1   -1    0    0    0    0    0    0    0    0    0
+ 1057           0.00           0.93    1    0   -1    0   -1    0    0    0    0    0    0    0    0    0
+ 1058          -0.91           0.00    2    0    2   -2    1    0    0    0    0    0    0    0    0    0
+ 1059          -0.90           0.00    2    1    0   -2    0    0    0    0    0    0    0    0    0    0
+ 1060           0.86           0.00    1    0    0    2    1    0    0    0    0    0    0    0    0    0
+ 1061          -0.84           0.00    1   -1    0   -2    0    0    0    0    0    0    0    0    0    0
+ 1062          -0.83           0.00    3    0    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1063          -0.82           0.00    0    0    4   -2    2    0    0    0    0    0    0    0    0    0
+ 1064           0.41           0.39    0    0    0    0    1    0    0   -1    2    0    0    0    0    0
+ 1065           0.40          -0.38    0    0    0    0    0    0    0    1   -2    0    0    0    0    0
+ 1066           0.78           0.00    0    1   -2    2    0    0    0    0    0    0    0    0    0    0
+ 1067           0.74           0.00    0    0    2   -2   -1    0    0    0    0    0    0    0    0    0
+ 1068          -0.73           0.00    0    1    2    0    1    0    0    0    0    0    0    0    0    0
+ 1069           0.68           0.00    1    0    2   -2    0    0    0    0    0    0    0    0    0    0
+ 1070           0.66           0.00    1    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+ 1071          -0.64           0.00    2    0   -2    0    1    0    0    0    0    0    0    0    0    0
+ 1072          -0.63           0.00    0    1    0    0    2    0    0    0    0    0    0    0    0    0
+ 1073           0.63           0.00    0    0    2   -1    2    0    0    0    0    0    0    0    0    0
+ 1074           0.62           0.00    0    0    2    4    2    0    0    0    0    0    0    0    0    0
+ 1075           0.60           0.00    0    1    0    2    0    0    0    0    0    0    0    0    0    0
+ 1076          -0.59           0.00    0    0    2    0   -1    0    0    0    0    0    0    0    0    0
+ 1077          -0.59           0.00    0    1   -2    0   -1    0    0    0    0    0    0    0    0    0
+ 1078           0.59           0.00    0    1    2   -2    0    0    0    0    0    0    0    0    0    0
+ 1079           0.57           0.00    1    0   -2   -2    0    0    0    0    0    0    0    0    0    0
+ 1080           0.38          -0.19    0    0    0    0    0    0    8  -13    0    0    0    0    0   -1
+ 1081          -0.01          -0.55    0    0    0    0    0    0    2   -3    0    0    0    0    0    0
+ 1082           0.44          -0.11    0    0    0    0    0    0    0    0    0    2   -5    0    0    0
+ 1083           0.53           0.00    0    0    0    0    0    0    2   -2    0    0    0    0    0    0
+ 1084          -0.53           0.00    1   -1    0   -1   -2    0    0    0    0    0    0    0    0    0
+ 1085           0.52           0.00    1   -1    2    2    2    0    0    0    0    0    0    0    0    0
+ 1086          -0.52           0.00    2    0    0    2    0    0    0    0    0    0    0    0    0    0
+ 1087           0.53           0.00    0    1    0    0   -2    0    0    0    0    0    0    0    0    0
+ 1088           0.52           0.00    1    1    0   -2    1    0    0    0    0    0    0    0    0    0
+ 1089           0.51           0.00    1    0   -2    2    0    0    0    0    0    0    0    0    0    0
+ 1090           0.51           0.00    1   -1   -2   -2   -2    0    0    0    0    0    0    0    0    0
+ 1091          -0.21          -0.30    0    0    0    0    0    0    8  -13    0    0    0    0    0    0
+ 1092          -0.50           0.00    0    1    0    1    0    0    0    0    0    0    0    0    0    0
+ 1093          -0.11           0.37    0    0    0    0    0    0    0    2   -8    3    0    0    0   -2
+ 1094          -0.11           0.37    0    0    0    0    0    0    0    6   -8    3    0    0    0    2
+ 1095          -0.48           0.00    0    1    2    2    2    0    0    0    0    0    0    0    0    0
+ 1096          -0.46          -0.01    0    0    0    0    0    0    0    3    0   -1    0    0    0    2
+ 1097          -0.47           0.00    1   -1    0    0    1    0    0    0    0    0    0    0    0    0
+ 1098          -0.03           0.43    0    0    1   -1    1    0    0   -1    0    2   -5    0    0    0
+ 1099           0.45           0.00    3    0    2    0    1    0    0    0    0    0    0    0    0    0
+ 1100          -0.44           0.00    0    0    0    4    0    0    0    0    0    0    0    0    0    0
+ 1101          -0.44           0.00    1    0    0    2   -1    0    0    0    0    0    0    0    0    0
+ 1102          -0.44           0.00    1   -1    0    2    0    0    0    0    0    0    0    0    0    0
+ 1103           0.43           0.00    2   -1    2    0    2    0    0    0    0    0    0    0    0    0
+ 1104           0.44           0.00    0    0    0    0    0    0    4   -6    0    0    0    0    0   -2
+ 1105           0.42           0.00    0    0    0    2    2    0    0    0    0    0    0    0    0    0
+ 1106          -0.42           0.00    1    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+ 1107           0.41           0.00    1   -1   -2    0   -2    0    0    0    0    0    0    0    0    0
+ 1108          -0.41           0.00    0    0    0    0    0    0    2   -4    0    0    0    0    0   -2
+ 1109           0.02           0.39    0    0    2   -2    1    0   -5    6    0    0    0    0    0    0
+ 1110           0.40           0.00    1    0    2   -4    1    0    0    0    0    0    0    0    0    0
+ 1111          -0.40           0.00    0    1   -2   -2   -1    0    0    0    0    0    0    0    0    0
+ 1112          -0.39           0.00    2    0    0   -2    0    0    0   -2    0    2    0    0    0    0
+ 1113           0.39           0.00    0    3    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1114           0.15          -0.24    0    0    0    0    0    0    0    1    0   -2    0    0    0    0
+ 1115          -0.37          -0.01    0    0    0    0    0    0    0    2    0   -2    0    0    0    0
+ 1116           0.37           0.00    1   -1    2    0    1    0    0    0    0    0    0    0    0    0
+ 1117          -0.37           0.00    0    0    2    2    0    0    0    0    0    0    0    0    0    0
+ 1118          -0.37           0.00    2    1    2    0    2    0    0    0    0    0    0    0    0    0
+ 1119          -0.31           0.06    2    0    0   -2    0    0    0   -2    0    3    0    0    0    0
+ 1120          -0.35           0.00    1    0    0   -2   -2    0    0    0    0    0    0    0    0    0
+ 1121           0.35           0.00    0    0    0    1    1    0    0    0    0    0    0    0    0    0
+ 1122          -0.07          -0.27    0    0    0    0    1    0    0   -4    8   -3    0    0    0    0
+ 1123          -0.33           0.01    0    0    0    0    0    0    2    0    0    0    0    0    0    2
+ 1124          -0.33           0.00    2   -1    0    0    0    0    0    0    0    0    0    0    0    0
+ 1125           0.07          -0.26    0    0    0    0    1    0    0    4   -8    3    0    0    0    0
+ 1126           0.33           0.00    0    0    0    0    0    0    0    2   -2    0    0    0    0    0
+ 1127           0.00          -0.32    1    0   -1    0   -2    0    0    0    0    0    0    0    0    0
+ 1128           0.32           0.00    1    1    0    0    1    0    0    0    0    0    0    0    0    0
+ 1129          -0.32           0.00    1    1    2    0    1    0    0    0    0    0    0    0    0    0
+ 1130           0.32           0.00    1    0   -2    2   -2    0    0    0    0    0    0    0    0    0
+ 1131          -0.24          -0.07    0    0    1   -1    1    0    0    0   -2    0    0    0    0    0
+ 1132           0.24           0.07    0    0    1   -1    0    0    0    0   -2    0    0    0    0    0
+ 1133           0.30           0.00    0    0    0    0    0    0    1    1    0    0    0    0    0    2
+ 1134           0.08          -0.22    0    0    0    0    0    0    0    0    0    1    0    0    0    0
+ 1135          -0.30           0.00    1    0    2    1    2    0    0    0    0    0    0    0    0    0
+ 1136          -0.30           0.00    2    0    2    0    0    0    0    0    0    0    0    0    0    0
+ 1137           0.30           0.00    0    1    0   -2    1    0    0    0    0    0    0    0    0    0
+ 1138           0.30           0.00    1    0    2   -1    2    0    0    0    0    0    0    0    0    0
+ 1139           0.00          -0.29    0    0    0    0    0    0    3   -4    0    0    0    0    0    0
+ 1140           0.00          -0.29    1    0   -1    0    0    0    0    0    0    0    0    0    0    0
+ 1141           0.20          -0.09    1    0    0    0    0    0  -18   16    0    0    0    0    0    0
+ 1142           0.29           0.00    1    0    0    1    0    0    0    0    0    0    0    0    0    0
+ 1143          -0.05          -0.24    0    0    0    0    0    0    0    0    0    2    0    0    0    1
+ 1144           0.29           0.00    0    0    0    1   -1    0    0    0    0    0    0    0    0    0
+ 1145          -0.27           0.00    1    0    0   -2    2    0    0    0    0    0    0    0    0    0
+ 1146          -0.19          -0.08    1    0    0    0    0    0  -10    3    0    0    0    0    0    0
+ 1147          -0.27           0.00    1   -1    0    0   -1    0    0    0    0    0    0    0    0    0
+ 1148           0.25           0.00    2    1    0    0    0    0    0    0    0    0    0    0    0    0
+ 1149           0.25           0.00    2    0    0   -2   -1    0    0   -2    0    2    0    0    0    0
+ 1150          -0.25           0.00    0    0    2    1    1    0    0    0    0    0    0    0    0    0
+ 1151           0.25           0.00    1    2    0   -2    0    0    0    0    0    0    0    0    0    0
+ 1152          -0.25           0.00    0    3    0    0    0    0    0    0    0    0    0    0    0    0
+ 1153          -0.01           0.23    0    0    0    0    0    0    5   -8    0    0    0    0    0   -2
+ 1154          -0.23           0.00    1    0   -2   -4   -1    0    0    0    0    0    0    0    0    0
+ 1155           0.23           0.00    0    0    0    0    0    0    0    1    0    1    0    0    0    2
+ 1156           0.23           0.00    4    0    2    0    2    0    0    0    0    0    0    0    0    0
+ 1157          -0.15          -0.07    0    0    1   -1    1    0    0   -1    0    0   -1    0    0    0
+ 1158          -0.23           0.00    1    0   -2    0    1    0    0    0    0    0    0    0    0    0
+ 1159          -0.22           0.00    2    1    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1160           0.22           0.00    0    1    2    1    2    0    0    0    0    0    0    0    0    0
+ 1161          -0.22           0.00    1    1    2   -2    1    0    0    0    0    0    0    0    0    0
+ 1162          -0.22           0.00    1    0    4   -2    2    0    0    0    0    0    0    0    0    0
+ 1163           0.04          -0.17    0    0    1   -1    1    0    0   -1    0   -1    0    0    0    0
+ 1164          -0.01          -0.21    0    0    2   -2    0    0   -5    6    0    0    0    0    0    0
+ 1165           0.08          -0.14    0    0    0    0    0    0    0    2   -4    0    0    0    0    0
+ 1166          -0.01           0.19    0    0    0    0    0    0    0    0    0    2   -5    0    0    1
+ 1167           0.21           0.00    2    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+ 1168          -0.20           0.00    1    0   -2    1   -1    0    0    0    0    0    0    0    0    0
+ 1169          -0.20           0.00    2   -2    0   -2    0    0    0    0    0    0    0    0    0    0
+ 1170          -0.04          -0.16    0    0    0    0    0    0    8  -13    0    0    0    0    0   -2
+ 1171           0.19           0.00    0    2    0   -2    0    0    0    0    0    0    0    0    0    0
+ 1172           0.19           0.00    1    1    0    0   -1    0    0    0    0    0    0    0    0    0
+ 1173          -0.19           0.00    2    0   -2   -4   -1    0    0    0    0    0    0    0    0    0
+ 1174           0.18           0.00    0    0    0    0    0    0    5   -7    0    0    0    0    0   -2
+ 1175          -0.18           0.00    0    1    0    2    1    0    0    0    0    0    0    0    0    0
+ 1176           0.18           0.00    1    0   -4    0   -1    0    0    0    0    0    0    0    0    0
+ 1177           0.17           0.00    2    0    2    2    1    0    0    0    0    0    0    0    0    0
+ 1178          -0.12           0.06    1    0    2    0    2    0    0    1    0    0    0    0    0    0
+ 1179           0.13          -0.04    0    0    0    0    0    0    3   -5    0    0    0    0    0    0
+ 1180          -0.11           0.06    1    0   -2    0   -2    0    0    4   -8    3    0    0    0    0
+ 1181           0.17           0.00    0    0    2   -3    2    0    0    0    0    0    0    0    0    0
+ 1182           0.16           0.00    0    0    0    0    0    0    0    4    0   -2    0    0    0    2
+ 1183          -0.17           0.00    0    0    4    0    2    0    0    0    0    0    0    0    0    0
+ 1184          -0.17           0.00    1    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+ 1185          -0.14           0.02    1    0    0   -1    1    0    0    0    0    0    0    0    0    0
+ 1186           0.14           0.03    0    0    0    0    0    0    0    2    0   -1    0    0    0    2
+ 1187           0.00           0.15    0    0    0    0    0    0    2   -1    0    0    0    0    0    2
+ 1188          -0.15           0.00    1    1   -2   -4   -2    0    0    0    0    0    0    0    0    0
+ 1189          -0.14           0.01    0    0    0    0    0    0    0    2    0    1    0    0    0    2
+ 1190           0.16           0.00    2    0    0   -2   -2    0    0    0    0    0    0    0    0    0
+ 1191          -0.06           0.10    0    0    0    0    0    0    8  -11    0    0    0    0    0   -2
+ 1192           0.05           0.10    0    0    0    0    0    0    0    8  -16    4    5    0    0   -2
+ 1193           0.02           0.13    0    0    1   -1    1    0    0   -1    0    2    0    0    0    0
+ 1194          -0.11           0.04    0    0    0    0    0    0    0    8  -16    4    5    0    0    2
+ 1195          -0.12          -0.02    0    0    1   -1    1    0   -5    7    0    0    0    0    0    0
+ 1196          -0.05          -0.10    0    0    0    0    0    0    0    0    0    0    2    0    0    1
+ 1197           0.14           0.00    1    0    2    4    2    0    0    0    0    0    0    0    0    0
+ 1198          -0.09           0.05    1    0    0   -2    0    0   19  -21    3    0    0    0    0    0
+ 1199           0.00           0.14    0    0    1    0    1    0    0    0    0    0    0    0    0    0
+ 1200           0.14           0.00    3    0    0   -4    0    0    0    0    0    0    0    0    0    0
+ 1201          -0.14           0.00    1    1   -2    0   -2    0    0    0    0    0    0    0    0    0
+ 1202           0.04           0.10    0    0    1   -1    1    0    0   -1    0    0    2    0    0    0
+ 1203          -0.06           0.08    0    0    0    0    0    0    0    3    0   -2    0    0    0    2
+ 1204           0.05           0.09    0    0    0    0    0    0    8  -15    0    0    0    0    0   -2
+ 1205          -0.14           0.00    0    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+ 1206           0.08           0.06    0    0    0    0    0    0    0    1    2    0    0    0    0    2
+ 1207           0.14           0.00    0    0    0    4    1    0    0    0    0    0    0    0    0    0
+ 1208           0.14           0.00    0    0    2   -4    1    0    0    0    0    0    0    0    0    0
+ 1209           0.13           0.00    1    1    0   -4    0    0    0    0    0    0    0    0    0    0
+ 1210          -0.07           0.06    0    0    0    0    0    0    0    3   -2    0    0    0    0    2
+ 1211           0.11          -0.02    0    0    0    0    0    0    0    0    0    3    0    0    0    2
+ 1212          -0.13           0.00    3    0    2   -2    1    0    0    0    0    0    0    0    0    0
+ 1213          -0.13           0.00    0    0    0    0    0    0    0    4   -2    0    0    0    0    2
+ 1214          -0.13           0.00    1    1    2    2    2    0    0    0    0    0    0    0    0    0
+ 1215          -0.13           0.00    0    0    4   -2    1    0    0    0    0    0    0    0    0    0
+ 1216          -0.12           0.00    2    0    0   -2    0    0   -3    3    0    0    0    0    0    0
+ 1217           0.12           0.00    3    0    2    2    2    0    0    0    0    0    0    0    0    0
+ 1218           0.12           0.00    0    0    0    0    0    0    0    0    0    0    2    0    0    2
+ 1219          -0.12           0.00    2    1    0   -2   -1    0    0    0    0    0    0    0    0    0
+ 1220           0.00          -0.12    1    0    0   -1    0    0   -3    4    0    0    0    0    0    0
+ 1221          -0.02          -0.09    0    0    0    0    0    0    4   -6    0    0    0    0    0   -1
+ 1222           0.02          -0.09    0    0    0    0    0    0    1   -1    0    0    0    0    0   -1
+ 1223          -0.11           0.00    0    2   -2   -2   -2    0    0    0    0    0    0    0    0    0
+ 1224           0.11           0.00    2    0    0   -4   -1    0    0    0    0    0    0    0    0    0
+ 1225           0.07          -0.04    0    0    0    0    0    0    0    3   -4    0    0    0    0    0
+ 1226           0.11           0.00    0    0    2    4    1    0    0    0    0    0    0    0    0    0
+ 1227           0.11           0.00    0    0    0    2   -2    0    0    0    0    0    0    0    0    0
+ 1228          -0.11           0.00    3    0    0    0   -1    0    0    0    0    0    0    0    0    0
+ 1229           0.10           0.00    0    0    0    0    0    0    0    1    0   -3    0    0    0   -2
+ 1230          -0.10           0.00    0    0    2   -2    1    0   -3    3    0    0    0    0    0    0
+ 1231           0.10           0.00    0    0    0    0    0    0    6   -8    0    0    0    0    0   -2
+ 1232           0.10           0.00    2    1    0   -4    0    0    0    0    0    0    0    0    0    0
+ 1233           0.10           0.00    0    0    1   -1    1    0    0    3   -8    3    0    0    0    0
+ 1234           0.00           0.10    0    0    0    0    0    0    3   -2    0    0    0    0    0    2
+ 1235           0.00           0.10    0    0    0    0    0    0    2   -5    0    0    0    0    0   -2
+ 1236          -0.10           0.00    4    0    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1237           0.10           0.00    2    0    0    2    1    0    0    0    0    0    0    0    0    0
+ 1238          -0.10           0.00    1   -1    0   -2   -1    0    0    0    0    0    0    0    0    0
+ 1239           0.10           0.00    0    0    0    0    0    0    1   -3    0    0    0    0    0   -2
+
+j = 2  Nb of terms = 30
+
+ 1240         121.15       -2301.27    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+ 1241          -0.98        -143.27    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1242          -0.27         -24.46    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+ 1243           0.24          22.41    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+ 1244          -1.19          -5.61    0    1    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1245           3.57          -1.83    0    1    0    0    0    0    0    0    0    0    0    0    0    0
+ 1246           0.24          -5.02    0    0    2    0    1    0    0    0    0    0    0    0    0    0
+ 1247          -0.04          -3.23    1    0    2    0    2    0    0    0    0    0    0    0    0    0
+ 1248          -0.48           2.40    0    1   -2    2   -2    0    0    0    0    0    0    0    0    0
+ 1249          -0.10           1.73    0    0    2   -2    1    0    0    0    0    0    0    0    0    0
+ 1250          -0.01           1.33    1    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+ 1251          -0.04           0.83    1    0    0    0    1    0    0    0    0    0    0    0    0    0
+ 1252          -0.05          -0.79    1    0    0    0   -1    0    0    0    0    0    0    0    0    0
+ 1253           0.03          -0.66    1    0    2    0    1    0    0    0    0    0    0    0    0    0
+ 1254           0.00          -0.64    1    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+ 1255           0.04           0.61    2    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+ 1256          -0.01          -0.41    0    0    2    2    2    0    0    0    0    0    0    0    0    0
+ 1257          -0.01           0.35    0    2   -2    2   -2    0    0    0    0    0    0    0    0    0
+ 1258          -0.01          -0.33    2    0    2    0    2    0    0    0    0    0    0    0    0    0
+ 1259           0.01           0.31    1    0    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1260           0.01           0.27    1    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+ 1261          -0.07          -0.17    0    2    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1262           0.07           0.17    1    0    0    0    0    0    0    0    0    0    0    0    0    0
+ 1263           0.02          -0.21    0    1    0    0    1    0    0    0    0    0    0    0    0    0
+ 1264           0.01           0.20    1    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+ 1265           0.01          -0.17    1    0    0   -2    1    0    0    0    0    0    0    0    0    0
+ 1266           0.01          -0.16    0    1    0    0   -1    0    0    0    0    0    0    0    0    0
+ 1267           0.00          -0.13    1    0   -2   -2   -1    0    0    0    0    0    0    0    0    0
+ 1268          -0.07          -0.04    0    0    1   -1    1    0    0   -1    0   -2    5    0    0    0
+ 1269           0.02           0.08    0    1    2    0    2    0    0    0    0    0    0    0    0    0
+ 
+j = 3  Nb of terms = 5
+
+ 1270         -15.23          -1.62    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+ 1271          -1.16          -0.01    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+ 1272          -0.20           0.00    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+ 1273           0.18           0.00    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+ 1274           0.13           0.00    0    1    0    0    0    0    0    0    0    0    0    0    0    0
+ 
+j = 4  Nb of terms = 1
+
+ 1275          -0.01           0.11    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2c.coeff
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2c.coeff	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2c.coeff	(revision 22158)
@@ -0,0 +1,13 @@
+# Expression for the quantity s(t)+XY/2 based on the IAU2000A precession-nutation 
+# model 
+# 
+# 
+# Updated Table (12/11/2003) for ensuring continuity of UT1 on 1st January 2003
+# 
+# --------------------------------------------------------------------------------------------------------------
+# 
+# s + XY/2 = polynomial part + non-polynomial part
+# 
+# --------------------------------------------------------------------------------------------------------------
+# Polynomial part (unit microarcsecond)
+94.0 +3808.35 -119.94 -72574.09 +27.70 +15.61
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2c.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2c.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2c.dat	(revision 22158)
@@ -0,0 +1,100 @@
+# Expression for the quantity s(t)+XY/2 based on the IAU2000A precession-nutation 
+# model 
+# 
+# 
+# Updated Table (12/11/2003) for ensuring continuity of UT1 on 1st January 2003
+# 
+# --------------------------------------------------------------------------------------------------------------
+# 
+# s + XY/2 = polynomial part + non-polynomial part
+# 
+# --------------------------------------------------------------------------------------------------------------
+# 
+# --------------------------------------------------------------------------------------------------------------
+# 
+# Non-polynomial part (unit microarcsecond)
+# (ARG being for various combination of the fundamental arguments of the nutation theory)
+# 
+#   Sum_i[C_{s,0})_i * sin(ARG) + C_{c,0})_i * cos(ARG)] 
+# 
+# + Sum_i)j=1,4 [C_{s,j})_i * t^j * sin(ARG) + C_{c,j})_i * cos(ARG)] * t^j]
+# 
+# The Table below provides the values for C_{s,j})_i and C_{c,j})_i
+# 
+# Cutoff (0.1 microarcsecond and periods less than 500 years)
+# 
+# The expressions for the fundamental arguments appearing in columns 4 to 8 (luni-solar part)
+# and in columns 6 to 17 (planetary part) are those of the IERS Conventions 2000
+# 
+# --------------------------------------------------------------------------------------------------------------
+# 
+#     i    C_{s,j})_i      C_{c,j})_i    l    l'   F    D   Om L_Me L_Ve  L_E L_Ma  L_J L_Sa  L_U L_Ne  p_A
+# 
+# --------------------------------------------------------------------------------------------------------------
+#  
+0       -2640.73           0.39    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+0         -63.53           0.02    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+0         -11.75          -0.01    0    0    2   -2    3    0    0    0    0    0    0    0    0    0
+0         -11.21          -0.01    0    0    2   -2    1    0    0    0    0    0    0    0    0    0
+0           4.57           0.00    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+0          -2.02           0.00    0    0    2    0    3    0    0    0    0    0    0    0    0    0
+0          -1.98           0.00    0    0    2    0    1    0    0    0    0    0    0    0    0    0
+0           1.72           0.00    0    0    0    0    3    0    0    0    0    0    0    0    0    0
+0           1.41           0.01    0    1    0    0    1    0    0    0    0    0    0    0    0    0
+0           1.26           0.01    0    1    0    0   -1    0    0    0    0    0    0    0    0    0
+0           0.63           0.00    1    0    0    0   -1    0    0    0    0    0    0    0    0    0
+0           0.63           0.00    1    0    0    0    1    0    0    0    0    0    0    0    0    0
+0          -0.46           0.00    0    1    2   -2    3    0    0    0    0    0    0    0    0    0
+0          -0.45           0.00    0    1    2   -2    1    0    0    0    0    0    0    0    0    0
+0          -0.36           0.00    0    0    4   -4    4    0    0    0    0    0    0    0    0    0
+0           0.24           0.12    0    0    1   -1    1    0   -8   12    0    0    0    0    0    0
+0          -0.32           0.00    0    0    2    0    0    0    0    0    0    0    0    0    0    0
+0          -0.28           0.00    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+0          -0.27           0.00    1    0    2    0    3    0    0    0    0    0    0    0    0    0
+0          -0.26           0.00    1    0    2    0    1    0    0    0    0    0    0    0    0    0
+0           0.21           0.00    0    0    2   -2    0    0    0    0    0    0    0    0    0    0
+0          -0.19           0.00    0    1   -2    2   -3    0    0    0    0    0    0    0    0    0
+0          -0.18           0.00    0    1   -2    2   -1    0    0    0    0    0    0    0    0    0
+0           0.10          -0.05    0    0    0    0    0    0    8  -13    0    0    0    0    0   -1
+0          -0.15           0.00    0    0    0    2    0    0    0    0    0    0    0    0    0    0
+0           0.14           0.00    2    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+0           0.14           0.00    0    1    2   -2    2    0    0    0    0    0    0    0    0    0
+0          -0.14           0.00    1    0    0   -2    1    0    0    0    0    0    0    0    0    0
+0          -0.14           0.00    1    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+0          -0.13           0.00    0    0    4   -2    4    0    0    0    0    0    0    0    0    0
+0           0.11           0.00    0    0    2   -2    4    0    0    0    0    0    0    0    0    0
+0          -0.11           0.00    1    0   -2    0   -3    0    0    0    0    0    0    0    0    0
+0          -0.11           0.00    1    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+1          -0.07           3.57    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+1           1.71          -0.03    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+1           0.00           0.48    0    0    2   -2    3    0    0    0    0    0    0    0    0    0
+2         743.53          -0.17    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+2          56.91           0.06    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+2           9.84          -0.01    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+2          -8.85           0.01    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+2          -6.38          -0.05    0    1    0    0    0    0    0    0    0    0    0    0    0    0
+2          -3.07           0.00    1    0    0    0    0    0    0    0    0    0    0    0    0    0
+2           2.23           0.00    0    1    2   -2    2    0    0    0    0    0    0    0    0    0
+2           1.67           0.00    0    0    2    0    1    0    0    0    0    0    0    0    0    0
+2           1.30           0.00    1    0    2    0    2    0    0    0    0    0    0    0    0    0
+2           0.93           0.00    0    1   -2    2   -2    0    0    0    0    0    0    0    0    0
+2           0.68           0.00    1    0    0   -2    0    0    0    0    0    0    0    0    0    0
+2          -0.55           0.00    0    0    2   -2    1    0    0    0    0    0    0    0    0    0
+2           0.53           0.00    1    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+2          -0.27           0.00    0    0    0    2    0    0    0    0    0    0    0    0    0    0
+2          -0.27           0.00    1    0    0    0    1    0    0    0    0    0    0    0    0    0
+2          -0.26           0.00    1    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+2          -0.25           0.00    1    0    0    0   -1    0    0    0    0    0    0    0    0    0
+2           0.22           0.00    1    0    2    0    1    0    0    0    0    0    0    0    0    0
+2          -0.21           0.00    2    0    0   -2    0    0    0    0    0    0    0    0    0    0
+2           0.20           0.00    2    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+2           0.17           0.00    0    0    2    2    2    0    0    0    0    0    0    0    0    0
+2           0.13           0.00    2    0    2    0    2    0    0    0    0    0    0    0    0    0
+2          -0.13           0.00    2    0    0    0    0    0    0    0    0    0    0    0    0    0
+2          -0.12           0.00    1    0    2   -2    2    0    0    0    0    0    0    0    0    0
+2          -0.11           0.00    0    0    2    0    0    0    0    0    0    0    0    0    0    0
+3           0.30         -23.51    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+3          -0.03          -1.39    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+3          -0.01          -0.24    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+3           0.00           0.22    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+4          -0.26          -0.01    0    0    0    0    1    0    0    0    0    0    0    0    0    0
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2c.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2c.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/tab5.2c.txt	(revision 22158)
@@ -0,0 +1,121 @@
+Expression for the quantity s(t)+XY/2 based on the IAU2000A precession-nutation 
+model 
+
+
+Updated Table (12/11/2003) for ensuring continuity of UT1 on 1st January 2003
+
+--------------------------------------------------------------------------------------------------------------
+
+s + XY/2 = polynomial part + non-polynomial part
+
+--------------------------------------------------------------------------------------------------------------
+
+Polynomial part (unit microarcsecond)
+
+  94.0 + 3808.35 t - 119.94 t^2 - 72574.09 t^3 + 27.70 t^4 + 15.61 t^5
+
+--------------------------------------------------------------------------------------------------------------
+
+Non-polynomial part (unit microarcsecond)
+(ARG being for various combination of the fundamental arguments of the nutation theory)
+
+  Sum_i[C_{s,0})_i * sin(ARG) + C_{c,0})_i * cos(ARG)] 
+
++ Sum_i)j=1,4 [C_{s,j})_i * t^j * sin(ARG) + C_{c,j})_i * cos(ARG)] * t^j]
+
+The Table below provides the values for C_{s,j})_i and C_{c,j})_i
+
+Cutoff (0.1 microarcsecond and periods less than 500 years)
+
+The expressions for the fundamental arguments appearing in columns 4 to 8 (luni-solar part)
+and in columns 6 to 17 (planetary part) are those of the IERS Conventions 2000
+
+--------------------------------------------------------------------------------------------------------------
+
+    i    C_{s,j})_i      C_{c,j})_i    l    l'   F    D   Om L_Me L_Ve  L_E L_Ma  L_J L_Sa  L_U L_Ne  p_A
+
+--------------------------------------------------------------------------------------------------------------
+ 
+j = 0  Nb of terms = 33
+
+    1       -2640.73           0.39    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+    2         -63.53           0.02    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+    3         -11.75          -0.01    0    0    2   -2    3    0    0    0    0    0    0    0    0    0
+    4         -11.21          -0.01    0    0    2   -2    1    0    0    0    0    0    0    0    0    0
+    5           4.57           0.00    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+    6          -2.02           0.00    0    0    2    0    3    0    0    0    0    0    0    0    0    0
+    7          -1.98           0.00    0    0    2    0    1    0    0    0    0    0    0    0    0    0
+    8           1.72           0.00    0    0    0    0    3    0    0    0    0    0    0    0    0    0
+    9           1.41           0.01    0    1    0    0    1    0    0    0    0    0    0    0    0    0
+   10           1.26           0.01    0    1    0    0   -1    0    0    0    0    0    0    0    0    0
+   11           0.63           0.00    1    0    0    0   -1    0    0    0    0    0    0    0    0    0
+   12           0.63           0.00    1    0    0    0    1    0    0    0    0    0    0    0    0    0
+   13          -0.46           0.00    0    1    2   -2    3    0    0    0    0    0    0    0    0    0
+   14          -0.45           0.00    0    1    2   -2    1    0    0    0    0    0    0    0    0    0
+   15          -0.36           0.00    0    0    4   -4    4    0    0    0    0    0    0    0    0    0
+   16           0.24           0.12    0    0    1   -1    1    0   -8   12    0    0    0    0    0    0
+   17          -0.32           0.00    0    0    2    0    0    0    0    0    0    0    0    0    0    0
+   18          -0.28           0.00    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+   19          -0.27           0.00    1    0    2    0    3    0    0    0    0    0    0    0    0    0
+   20          -0.26           0.00    1    0    2    0    1    0    0    0    0    0    0    0    0    0
+   21           0.21           0.00    0    0    2   -2    0    0    0    0    0    0    0    0    0    0
+   22          -0.19           0.00    0    1   -2    2   -3    0    0    0    0    0    0    0    0    0
+   23          -0.18           0.00    0    1   -2    2   -1    0    0    0    0    0    0    0    0    0
+   24           0.10          -0.05    0    0    0    0    0    0    8  -13    0    0    0    0    0   -1
+   25          -0.15           0.00    0    0    0    2    0    0    0    0    0    0    0    0    0    0
+   26           0.14           0.00    2    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+   27           0.14           0.00    0    1    2   -2    2    0    0    0    0    0    0    0    0    0
+   28          -0.14           0.00    1    0    0   -2    1    0    0    0    0    0    0    0    0    0
+   29          -0.14           0.00    1    0    0   -2   -1    0    0    0    0    0    0    0    0    0
+   30          -0.13           0.00    0    0    4   -2    4    0    0    0    0    0    0    0    0    0
+   31           0.11           0.00    0    0    2   -2    4    0    0    0    0    0    0    0    0    0
+   32          -0.11           0.00    1    0   -2    0   -3    0    0    0    0    0    0    0    0    0
+   33          -0.11           0.00    1    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+ 
+j = 1  Nb of terms = 3
+
+   34          -0.07           3.57    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+   35           1.71          -0.03    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+   36           0.00           0.48    0    0    2   -2    3    0    0    0    0    0    0    0    0    0
+
+j = 2  Nb of terms = 25
+      
+   37         743.53          -0.17    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+   38          56.91           0.06    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+   39           9.84          -0.01    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+   40          -8.85           0.01    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+   41          -6.38          -0.05    0    1    0    0    0    0    0    0    0    0    0    0    0    0
+   42          -3.07           0.00    1    0    0    0    0    0    0    0    0    0    0    0    0    0
+   43           2.23           0.00    0    1    2   -2    2    0    0    0    0    0    0    0    0    0
+   44           1.67           0.00    0    0    2    0    1    0    0    0    0    0    0    0    0    0
+   45           1.30           0.00    1    0    2    0    2    0    0    0    0    0    0    0    0    0
+   46           0.93           0.00    0    1   -2    2   -2    0    0    0    0    0    0    0    0    0
+   47           0.68           0.00    1    0    0   -2    0    0    0    0    0    0    0    0    0    0
+   48          -0.55           0.00    0    0    2   -2    1    0    0    0    0    0    0    0    0    0
+   49           0.53           0.00    1    0   -2    0   -2    0    0    0    0    0    0    0    0    0
+   50          -0.27           0.00    0    0    0    2    0    0    0    0    0    0    0    0    0    0
+   51          -0.27           0.00    1    0    0    0    1    0    0    0    0    0    0    0    0    0
+   52          -0.26           0.00    1    0   -2   -2   -2    0    0    0    0    0    0    0    0    0
+   53          -0.25           0.00    1    0    0    0   -1    0    0    0    0    0    0    0    0    0
+   54           0.22           0.00    1    0    2    0    1    0    0    0    0    0    0    0    0    0
+   55          -0.21           0.00    2    0    0   -2    0    0    0    0    0    0    0    0    0    0
+   56           0.20           0.00    2    0   -2    0   -1    0    0    0    0    0    0    0    0    0
+   57           0.17           0.00    0    0    2    2    2    0    0    0    0    0    0    0    0    0
+   58           0.13           0.00    2    0    2    0    2    0    0    0    0    0    0    0    0    0
+   59          -0.13           0.00    2    0    0    0    0    0    0    0    0    0    0    0    0    0
+   60          -0.12           0.00    1    0    2   -2    2    0    0    0    0    0    0    0    0    0
+   61          -0.11           0.00    0    0    2    0    0    0    0    0    0    0    0    0    0    0
+ 
+j = 3  Nb of terms = 4
+
+   62           0.30         -23.51    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+   63          -0.03          -1.39    0    0    2   -2    2    0    0    0    0    0    0    0    0    0
+   64          -0.01          -0.24    0    0    2    0    2    0    0    0    0    0    0    0    0    0
+   65           0.00           0.22    0    0    0    0    2    0    0    0    0    0    0    0    0    0
+
+j = 4  Nb of terms = 1
+  
+   66          -0.26          -0.01    0    0    0    0    1    0    0    0    0    0    0    0    0    0
+
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/tai_utc.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/tai_utc.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/tai_utc.dat	(revision 22158)
@@ -0,0 +1,50 @@
+#  tai-utc.dat
+#
+#  This file comes from http://maia.usno.navy.mil (Click on table of leap seconds since 1961). This file may
+#  also be directly downloaded from ftp://maia.usno.navy.mil/ser7/tai-utc.dat. See readme.tai-utc (located in
+#  the psLib/data directory) for details.
+#
+#  @author Ross Harman, MHPCC
+#
+#  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+#  @date $Date: 2006-09-23 02:20:18 $
+#
+#          JD           TAI-UTC    Const 1       Const 2
+#        (days)          (sec)      (none)       (none)
+#          psF64	         psF64      psF64         psF64
+        2437300.5      1.4228180    37300.0     0.0012960
+        2437512.5      1.3728180    37300.0     0.0012960
+        2437665.5      1.8458580    37665.0     0.0011232
+        2438334.5      1.9458580    37665.0     0.0011232
+        2438395.5      3.2401300    38761.0     0.0012960
+        2438486.5      3.3401300    38761.0     0.0012960
+        2438639.5      3.4401300    38761.0     0.0012960
+        2438761.5      3.5401300    38761.0     0.0012960
+        2438820.5      3.6401300    38761.0     0.0012960
+        2438942.5      3.7401300    38761.0     0.0012960
+        2439004.5      3.8401300    38761.0     0.0012960
+        2439126.5      4.3131700    39126.0     0.0025920
+        2439887.5      4.2131700    39126.0     0.0025920
+        2441317.5     10.0000000    41317.0     0.0000000
+        2441499.5     11.0000000    41317.0     0.0000000
+        2441683.5     12.0000000    41317.0     0.0000000
+        2442048.5     13.0000000    41317.0     0.0000000
+        2442413.5     14.0000000    41317.0     0.0000000
+        2442778.5     15.0000000    41317.0     0.0000000
+        2443144.5     16.0000000    41317.0     0.0000000
+        2443509.5     17.0000000    41317.0     0.0000000
+        2443874.5     18.0000000    41317.0     0.0000000
+        2444239.5     19.0000000    41317.0     0.0000000
+        2444786.5     20.0000000    41317.0     0.0000000
+        2445151.5     21.0000000    41317.0     0.0000000
+        2445516.5     22.0000000    41317.0     0.0000000
+        2446247.5     23.0000000    41317.0     0.0000000
+        2447161.5     24.0000000    41317.0     0.0000000
+        2447892.5     25.0000000    41317.0     0.0000000
+        2448257.5     26.0000000    41317.0     0.0000000
+        2448804.5     27.0000000    41317.0     0.0000000
+        2449169.5     28.0000000    41317.0     0.0000000
+        2449534.5     29.0000000    41317.0     0.0000000
+        2450083.5     30.0000000    41317.0     0.0000000
+        2450630.5     31.0000000    41317.0     0.0000000
+        2451179.5     32.0000000    41317.0     0.0000000
Index: /branches/eam_branches/eam_branch_20080719/psLib/share/tai_utc.raw
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/share/tai_utc.raw	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/share/tai_utc.raw	(revision 22158)
@@ -0,0 +1,36 @@
+ 1961 JAN  1 =JD 2437300.5  TAI-UTC=   1.4228180 S + (MJD - 37300.) X 0.001296 S
+ 1961 AUG  1 =JD 2437512.5  TAI-UTC=   1.3728180 S + (MJD - 37300.) X 0.001296 S
+ 1962 JAN  1 =JD 2437665.5  TAI-UTC=   1.8458580 S + (MJD - 37665.) X 0.0011232S
+ 1963 NOV  1 =JD 2438334.5  TAI-UTC=   1.9458580 S + (MJD - 37665.) X 0.0011232S
+ 1964 JAN  1 =JD 2438395.5  TAI-UTC=   3.2401300 S + (MJD - 38761.) X 0.001296 S
+ 1964 APR  1 =JD 2438486.5  TAI-UTC=   3.3401300 S + (MJD - 38761.) X 0.001296 S
+ 1964 SEP  1 =JD 2438639.5  TAI-UTC=   3.4401300 S + (MJD - 38761.) X 0.001296 S
+ 1965 JAN  1 =JD 2438761.5  TAI-UTC=   3.5401300 S + (MJD - 38761.) X 0.001296 S
+ 1965 MAR  1 =JD 2438820.5  TAI-UTC=   3.6401300 S + (MJD - 38761.) X 0.001296 S
+ 1965 JUL  1 =JD 2438942.5  TAI-UTC=   3.7401300 S + (MJD - 38761.) X 0.001296 S
+ 1965 SEP  1 =JD 2439004.5  TAI-UTC=   3.8401300 S + (MJD - 38761.) X 0.001296 S
+ 1966 JAN  1 =JD 2439126.5  TAI-UTC=   4.3131700 S + (MJD - 39126.) X 0.002592 S
+ 1968 FEB  1 =JD 2439887.5  TAI-UTC=   4.2131700 S + (MJD - 39126.) X 0.002592 S
+ 1972 JAN  1 =JD 2441317.5  TAI-UTC=  10.0       S + (MJD - 41317.) X 0.0      S
+ 1972 JUL  1 =JD 2441499.5  TAI-UTC=  11.0       S + (MJD - 41317.) X 0.0      S
+ 1973 JAN  1 =JD 2441683.5  TAI-UTC=  12.0       S + (MJD - 41317.) X 0.0      S
+ 1974 JAN  1 =JD 2442048.5  TAI-UTC=  13.0       S + (MJD - 41317.) X 0.0      S
+ 1975 JAN  1 =JD 2442413.5  TAI-UTC=  14.0       S + (MJD - 41317.) X 0.0      S
+ 1976 JAN  1 =JD 2442778.5  TAI-UTC=  15.0       S + (MJD - 41317.) X 0.0      S
+ 1977 JAN  1 =JD 2443144.5  TAI-UTC=  16.0       S + (MJD - 41317.) X 0.0      S
+ 1978 JAN  1 =JD 2443509.5  TAI-UTC=  17.0       S + (MJD - 41317.) X 0.0      S
+ 1979 JAN  1 =JD 2443874.5  TAI-UTC=  18.0       S + (MJD - 41317.) X 0.0      S
+ 1980 JAN  1 =JD 2444239.5  TAI-UTC=  19.0       S + (MJD - 41317.) X 0.0      S
+ 1981 JUL  1 =JD 2444786.5  TAI-UTC=  20.0       S + (MJD - 41317.) X 0.0      S
+ 1982 JUL  1 =JD 2445151.5  TAI-UTC=  21.0       S + (MJD - 41317.) X 0.0      S
+ 1983 JUL  1 =JD 2445516.5  TAI-UTC=  22.0       S + (MJD - 41317.) X 0.0      S
+ 1985 JUL  1 =JD 2446247.5  TAI-UTC=  23.0       S + (MJD - 41317.) X 0.0      S
+ 1988 JAN  1 =JD 2447161.5  TAI-UTC=  24.0       S + (MJD - 41317.) X 0.0      S
+ 1990 JAN  1 =JD 2447892.5  TAI-UTC=  25.0       S + (MJD - 41317.) X 0.0      S
+ 1991 JAN  1 =JD 2448257.5  TAI-UTC=  26.0       S + (MJD - 41317.) X 0.0      S
+ 1992 JUL  1 =JD 2448804.5  TAI-UTC=  27.0       S + (MJD - 41317.) X 0.0      S
+ 1993 JUL  1 =JD 2449169.5  TAI-UTC=  28.0       S + (MJD - 41317.) X 0.0      S
+ 1994 JUL  1 =JD 2449534.5  TAI-UTC=  29.0       S + (MJD - 41317.) X 0.0      S
+ 1996 JAN  1 =JD 2450083.5  TAI-UTC=  30.0       S + (MJD - 41317.) X 0.0      S
+ 1997 JUL  1 =JD 2450630.5  TAI-UTC=  31.0       S + (MJD - 41317.) X 0.0      S
+ 1999 JAN  1 =JD 2451179.5  TAI-UTC=  32.0       S + (MJD - 41317.) X 0.0      S
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/.cvsignore	(revision 22158)
@@ -0,0 +1,14 @@
+DoxygenLog
+Makefile.in
+.deps
+.libs
+Makefile
+config.h
+*.la
+*.lo
+stamp-h1
+libpslib.la.temp
+config.h.in
+*.bb
+*.bbg
+*.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/Makefile.am	(revision 22158)
@@ -0,0 +1,23 @@
+SUBDIRS = $(SRCDIRS)
+
+lib_LTLIBRARIES = libpslib.la
+
+libpslib_la_CPPFLAGS = $(SRCINC) $(PSLIB_CFLAGS) 
+libpslib_la_LIBADD = $(SRCSUBLIBS) $(PSLIB_LIBS)
+libpslib_la_DEPENDENCIES = $(SRCSUBLIBS)
+libpslib_la_SOURCES =
+libpslib_la_LDFLAGS = -version-info $(PSLIB_LT_VERSION)
+
+
+EXTRA_DIST = mainpage.dox psErrorCodes_en.dat
+
+pkginclude_HEADERS = \
+	pslib.h \
+	pslib_strict.h
+
+install-exec-local: libpslib.la
+	$(PERL) -pe "s|(^dependency_libs=.*)|dependency_libs=\'$(PSLIB_LIBS)\'|" libpslib.la > libpslib.la.temp
+	cp libpslib.la.temp libpslib.la
+	rm -f libpslib.la.temp
+
+CLEANFILES = *~ *.bb *.bbg *.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/TestCoverage
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/TestCoverage	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/TestCoverage	(revision 22158)
@@ -0,0 +1,236 @@
+#!/usr/bin/perl
+#
+#  This is a perl script
+#
+#  SYNOPSIS:  SlocCount options topLevelDirectory
+#
+#       where  options =
+#             --verbose     Display extra information to user
+#             --noverbose   Don't display extra information to user
+#             --recursiv e  Recursively run tests in directory tree
+#             --norecursive Test only the specified or current directory
+#             --silent      Don't display any information to user
+#             --nosilent    Display progress of script to user
+#
+#              arguements = directory(ies) to perform software line count
+#
+#  RETURN : zero upon successful parsing of directories
+#
+#  $Revision: 1.4 $  $Name: not supported by cvs2svn $
+#  $Date: 2005-09-23 19:03:12 $
+#
+#  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+#
+##############################################################################
+
+# Provide functions for determining the pathname of current working directory
+use Cwd;
+
+# Provides functions for handling long command line options
+use Getopt::Long;
+
+# Assign variables based on the presence of command line options to the script
+# The ! option allows for --nooption to be set to zero
+# (e.g. --noverbose --recursive causes $verbose=0 and $recursive=1)
+GetOptions("verbose!"=>\$verbose,
+           "recursive!"=>\$recursive,
+           "silent!"=>\$silent);
+
+# Check if both silent and verbose options are set and if so stop the script
+die "Can't specify both verbose and silent options." if ($verbose && $silent);
+
+# Initialize variables for counting the total lines of code, files
+$cFileCount = 0;
+
+# Initialize variable indicating how many arguements were passed
+$args = 0;
+
+open(COVFILE, "> coverageFileResult.txt");
+
+# Loop through all the arguements passed to the script
+foreach (@ARGV) {
+    # Remove newline if there is one
+    chomp;
+    # Increment number of arguements found
+    $args++;
+    # Set variable to current working directory
+    $cwd = cwd;
+    # Change directory to the directory of the arguement
+    chdir($_);
+    # Check for the recursive option
+    if ($recursive) {
+        # Invoke subroutine to go to the lowest directory in tree
+        # starting at the specified directory
+#        &worm($_);
+    }
+    # Change directory back to the directory where FullUnitTest was invoked
+    chdir($cwd);
+}
+
+# Check if there were no arguements specified
+if ($args == 0){
+    # Display message to user that all directories under the current will be
+    # tested
+    print("Recursively testing current directory tree.\n");
+    # Invoke subroutine to go to recursively test each directory in tree
+    &worm($ENV{"PWD"});
+}
+
+# Display summary of line counts
+print("\nSUMMARY STATISTICS\n");
+print("Files");
+print("$cFileCount");
+$totalFiles = $cFileCount;
+print("\nTotal\t$totalFiles\n\n");
+
+close(COVFILE);
+
+# Exit
+exit(0);
+
+
+################################################################################
+#
+# SUBROUTINE: worm
+#
+#     Description:  This subroutine will perform the necessary unit tests be
+#                   calling makeTestDrivers and executeTestDrivers  subroutines
+#                   and then check each subdirectory below the base directory
+#                   recursively.
+#
+#     Parameter(s):  base directory to counting slocs
+#
+################################################################################
+
+sub worm {
+    # Assign local variable to input parameter
+    local($base_dir) = @_;
+    local(@files, $i);
+
+    # Create array of entries found in directory
+    @files = <*>;
+
+    # Loop through the file list looking for another directory that is not
+    # labelled CVS and recursively invoke subroutine worm
+    $i = 0;
+    while ($files[$i]) {
+        # Check for directory and directory not labelled CVS
+        if (-d $files[$i] && ($files[$i] ne "CVS") && ($files[$i] ne "temp")
+                          && ($files[$i] ne "verified") && ($files[$i] ne ".libs")) {
+            # Change current directory to directory found
+            chdir($files[$i]);
+            # Invoke subroutine worm again
+            &worm("$base_dir/$files[$i]");
+            # Change current directory back to parent
+            chdir("..");
+        }
+        # Increment file list index
+        $i++;
+    }
+
+    # Count the number of files and test coverage in this directory
+    &getTestCoverage($base_dir);
+}
+
+################################################################################
+#
+#  SUBROUTINE: getSlocNumber
+#
+#      Description:  This subroutine will parse the output file for the sloc
+#                    count.
+#
+#      Parameter(s):  base directory where make and test drivers are located
+#
+################################################################################
+
+sub getFileCoverage{
+    local($base_dir) = @_;
+    local($retVal) = 0;
+
+    $fname = 0;
+
+    # Open the output file for reading if it exists
+    if ( -e "$base_dir/coverage" ) {
+        open(OUTFILE, "< $base_dir/coverage");
+        while($retVal = <OUTFILE>) {
+            @result = split(/ /,$retVal);
+
+            if( $result[6] !~ /file/) {
+               if( $result[0] !~ /Creat/) {
+                  print COVFILE ("$result[0]\t$result[2]\t$result[6]\t$result[7]");
+               }
+            }
+            else {
+               print COVFILE ("$result[0]\t$result[2]\t$result[6]\t$result[7]");
+            }
+       }
+
+        $retVal = s/\D//;
+        close(OUTFILE);
+    }
+
+    return($result[0]);
+}
+
+################################################################################
+#
+#  SUBROUTINE: getTestCoverage
+#
+#      Description:  This subroutine will
+#
+#      Parameter(s):  base directory where make and test drivers are located
+#
+################################################################################
+
+sub getTestCoverage{
+    local($base_dir) = @_;
+    local($pwd);
+
+    my($cfiles);
+
+    $cfiles = 0;
+
+    # Set variable to pwd to current test directory
+    # Display total for this directory
+    print("\n$base_dir\n");
+
+    $pwd = cwd;
+
+    # Create a list of all elements in base directory
+    @files = <*>;
+
+    # Loop through all the items in the files array
+    $initialTest = 0;
+    $j = 0;
+    while ( $files[$j]) {
+        # Check that the item is not a directory
+        if ( ! (-d $files[$j]) ) {
+
+            if ( ( $files[$j] =~ m@\.c$@ ) ) {
+
+                $objfile = $files[$j];
+                $objfile =~ s/\.c$/\.o/;
+                $objfile = `find $base_dir/.libs -name "*$objfile"`;
+                chop $objfile;
+
+                if (length($objfile) > 0) {
+                    # Increment total number of c files
+                    $cfiles++;
+
+                    # Call C source sloc count
+                    system("gcov -f -o $objfile $base_dir/$files[$j] > $base_dir/coverage");
+                    if ( $? == 0 ) {
+                        getFileCoverage($base_dir);
+                    }
+                    if ( -e "$base_dir/coverage" ) {
+                        system("rm $base_dir/coverage");
+                    }
+                }
+            }
+        }
+        $j++;
+    }
+    $cFileCount += $cfiles;
+}
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/astro/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/astro/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/astro/.cvsignore	(revision 22158)
@@ -0,0 +1,10 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
+*.loT
+*.bb
+*.bbg
+*.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/astro/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/astro/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/astro/Makefile.am	(revision 22158)
@@ -0,0 +1,22 @@
+#Makefile for astronomy functions of psLib
+#
+AM_CFLAGS=$(CFLAGS) -DPS_CONFIG_FILE_DEFAULT=\"$(sysconfdir)/pslib/pslib.config\"
+
+noinst_LTLIBRARIES = libpslibastro.la
+
+libpslibastro_la_CPPFLAGS = $(SRCINC) $(PSLIB_CFLAGS) 
+libpslibastro_la_SOURCES = \
+	psTime.c \
+	psCoord.c \
+	psSphereOps.c \
+        psEarthOrientation.c
+
+EXTRA_DIST = astro.i
+
+pkginclude_HEADERS = \
+	psTime.h \
+	psCoord.h \
+	psSphereOps.h \
+	psEarthOrientation.h
+
+CLEANFILES = *~ *.bb *.bbg *.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/astro/astro.i
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/astro/astro.i	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/astro/astro.i	(revision 22158)
@@ -0,0 +1,3 @@
+/* astro headers */
+%include "psCoord.h"
+%include "psTime.h"
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/astro/parse_gcov-out.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/astro/parse_gcov-out.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/astro/parse_gcov-out.c	(revision 22158)
@@ -0,0 +1,114 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAXSTR 10000
+
+static char outStr[MAXSTR];
+static float average;
+static int sum;
+
+void parseFile(FILE *in, const char *filename);
+
+int main(void)
+{
+
+    FILE *output = NULL;
+    FILE *input = NULL;
+    average = 0.0;
+    sum = 0;
+    int N = 0;
+
+    input = fopen("sph_gcov.out", "r");
+    parseFile(input, "psSphereOps.c");
+    fclose(input);
+    N++;
+
+    input = fopen("eoc_gcov.out", "r");
+    parseFile(input, "psEarthOrientation.c");
+    fclose(input);
+    N++;
+
+    input = fopen("time_gcov.out", "r");
+    parseFile(input, "psTime.c");
+    fclose(input);
+    N++;
+
+    input = fopen("crd_gcov.out", "r");
+    parseFile(input, "psCoord.c");
+    fclose(input);
+    N++;
+
+    average = average / sum;
+
+    output = fopen("Coverage-Report.txt", "w");
+    fprintf(output, "\nTOTAL COVERAGE IN THE ../src/astro/ DIRECTORY\n");
+    fprintf(output, "\n%s", outStr);
+    fprintf(output, "  -------------------------------"
+            "-------------------------------------\n");
+    fprintf(output, "  ---> Total                        = Lines executed:");
+    fprintf(output, "%3.2f%%  of %d\n\n", average, sum);
+    fclose(output);
+    return 0;
+}
+
+void parseINT(const char *nums, float percent)
+{
+    sum += atoi(nums);
+    average += (float)((int)(percent * atoi(nums)));
+}
+
+float parseDBL(const char *nums)
+{
+    char temp[7];
+    int i = 0;
+    int j = 9;
+    float out = 0.0;
+    while (nums[j] != '%') {
+        temp[i] = nums[j];
+        i++;
+        j++;
+    }
+    //    average += (float)atof(temp);
+    out = (float)atof(temp);
+    return out;
+}
+
+void parseFile(FILE *in, const char *filename)
+{
+    char currentStr[100];
+    char searchStr[100];
+    char out[250];
+    sprintf(out, "  >><< %-25s    =", filename);
+    sprintf(searchStr, "'%s'", filename);
+    //    printf("\n searchStr = %s\n", searchStr);
+    strcat(outStr, out);
+    int i;
+    float numLines = 0.0;
+    while ( fscanf(in, "%s", currentStr) != EOF) {
+        if ( strncmp(currentStr, searchStr, 99) == 0 ) {
+            for (i = 0; i < 4; i++) {
+                if (i == 1) {
+                    fscanf(in, "%s", out);
+                    numLines = parseDBL(out);
+                    sprintf(currentStr, "%-16s", out);
+                } else if ( i == 3) {
+                    fscanf(in, "%s", out);
+                    parseINT(out, numLines);
+                    sprintf(currentStr, "%s", out);
+                } else {
+                    fscanf(in, "%s", currentStr);
+                }
+                strcat(outStr, " ");
+                strcat(outStr, currentStr);
+            }
+            continue;
+        }
+    }
+    strcat(outStr, "\n\n");
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/astro/profile_tap
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/astro/profile_tap	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/astro/profile_tap	(revision 22158)
@@ -0,0 +1,9 @@
+
+gcov -f --object-file ./.libs/libpslibastro_la-psSphereOps.o psSphereOps.c > sph_gcov.out
+gcov -f --object-file ./.libs/libpslibastro_la-psEarthOrientation.o psEarthOrientation.c > eoc_gcov.out
+gcov -f --object-file ./.libs/libpslibastro_la-psTime.o psTime.c > time_gcov.out
+gcov -f --object-file ./.libs/libpslibastro_la-psCoord.o psCoord.c > crd_gcov.out
+gcc parse_gcov-out.c -o parse_gcov
+./parse_gcov
+rm *.out
+more Coverage-Report.txt
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psCoord.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psCoord.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psCoord.c	(revision 22158)
@@ -0,0 +1,1275 @@
+/** @file  psCoord.c
+ *
+ *  @brief Contains basic coordinate transformation definitions and operations
+ *
+ *  This file defines the basic types for astronomical coordinate
+ *  transformation
+ *
+ *  @ingroup CoordinateTransform
+ *
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.141 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-10-09 19:25:44 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+/******************************************************************************/
+/*  INCLUDE FILES                                                             */
+/******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <math.h>
+#include <float.h>
+#include <string.h>
+
+#include "psType.h"
+#include "psCoord.h"
+#include "psMemory.h"
+#include "psTime.h"
+#include "psAssert.h"
+#include "psError.h"
+#include "psLogMsg.h"
+#include "psTrace.h"
+#include "psAbort.h"
+
+#include "psMatrix.h"
+#include "psMinimizePolyFit.h"
+
+# define ELIXIR_CODE 1
+
+static void planeFree(psPlane *p)
+{
+    // There are non dynamic allocated items
+}
+
+static void sphereFree(psSphere* s)
+{
+    // There are non dynamic allocated items
+}
+
+static void cubeFree(psCube* c)
+{
+    // There are non dynamic allocated items
+}
+
+static void planeTransformFree(psPlaneTransform *pt)
+{
+    psFree(pt->x);
+    psFree(pt->y);
+}
+
+/*****************************************************************************
+p_psPlaneTransformLinearInvert(transform): : this is a private function which
+simply inverts the supplied psPlaneTransform transform.  It assumes that
+"transform" is linear.
+
+XXX: This code no longer makes sense.  The merge must be reviewed.
+
+XXX: below is the code using the standard matrix representation.  note that
+this inversion requires x->nX == 1, y->nY == 1 and x->nY <= 1, y->nX <= 1
+*****************************************************************************/
+psPlaneTransform *p_psPlaneTransformLinearInvert(psPlaneTransform *transform)
+{
+    PS_ASSERT_PTR_NON_NULL(transform, NULL);
+    PS_ASSERT_PTR_NON_NULL(transform->x, NULL);
+    PS_ASSERT_PTR_NON_NULL(transform->y, NULL);
+    if ((transform->x->nX < 1) ||
+	(transform->x->nY < 1) ||
+	(transform->y->nX < 1) ||
+	(transform->y->nY < 1)) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: input transform is not invertible.");
+        return(NULL);
+    }
+
+    psPlaneTransform *out = psPlaneTransformAlloc(1, 1);
+
+    if (0) {
+        // XXX: Get rid of this code.
+        psF64 A = transform->x->coeff[1][0];
+        psF64 B = transform->x->coeff[0][1];
+        psF64 C = transform->y->coeff[1][0];
+        psF64 D = transform->y->coeff[0][1];
+        psF64 E = transform->x->coeff[0][0];
+        psF64 F = transform->y->coeff[0][0];
+        psF64 invDet = 1.0 / (A * D - B * C);
+
+        out->x->coeff[1][0] = invDet *  D;
+        out->x->coeff[0][1] = invDet * -B;
+        out->y->coeff[1][0] = invDet * -C;
+        out->y->coeff[0][1] = invDet *  A;
+
+        //
+        // This comes from substituting the (x_2 = x_1 - e) and (y_2 = y_1 - f) equations:
+        //
+        out->x->coeff[0][0] = invDet * (B * F - D * E);
+        out->y->coeff[0][0] = invDet * (E * C - A * F);
+
+    }
+
+    psF64 r12 = 0.0;
+    if (transform->x->nY == 1) {
+        r12 = transform->x->coeff[0][1];
+    }
+    psF64 r21 = 0.0;
+    if (transform->y->nX == 1) {
+        r21 = transform->y->coeff[1][0];
+    }
+    psF64 r11 = transform->x->coeff[1][0];
+    psF64 r22 = transform->y->coeff[0][1];
+    psF64 xo  = transform->x->coeff[0][0];
+    psF64 yo  = transform->y->coeff[0][0];
+
+    psF64 invDet = 1.0 / (r11 * r22 - r12 * r21);
+
+    // apply the results back to the polynomials
+    out->x->coeff[0][0] = -invDet * (r22 * xo - r12 * yo);
+    out->y->coeff[0][0] = -invDet * (r11 * yo - r21 * xo);
+    out->x->coeff[1][0] = +invDet * r22;
+    out->y->coeff[0][1] = +invDet * r11;
+    if (transform->x->nY == 1) {
+        out->x->coeff[0][1] = -invDet * r12;
+    }
+    if (transform->y->nX == 1) {
+        out->y->coeff[1][0] = -invDet * r21;
+    }
+    return(out);
+}
+
+/*****************************************************************************
+p_psIsProjectionLinear(): this is a private function which simply determines
+if the supplied psPlaneTransform transform is linear: if any of the
+cooefficients of order 2 are higher are non-zero, then it is not linear.
+
+Returns:
+    true: if linear
+    false: otherwise
+
+Why isn't this called p_psIsPlaneTransformLinear()?
+*****************************************************************************/
+bool p_psIsProjectionLinear(psPlaneTransform *transform)
+{
+    PS_ASSERT_PTR_NON_NULL(transform, false);
+    PS_ASSERT_PTR_NON_NULL(transform->x, false);
+    PS_ASSERT_PTR_NON_NULL(transform->y, false);
+
+    for (psS32 i=0;i<(1 + transform->x->nX);i++) {
+        for (psS32 j=0;j<(1 + transform->x->nY);j++) {
+            if (transform->x->coeff[i][j] != 0.0) {
+                if (!(((i == 0) && (j == 0)) ||
+		      ((i == 0) && (j == 1)) ||
+		      ((i == 1) && (j == 0)))) {
+                    return(false);
+                }
+            }
+        }
+    }
+
+    for (psS32 i=0;i<(1 + transform->y->nX);i++) {
+        for (psS32 j=0;j<(1 + transform->y->nY);j++) {
+            if (transform->y->coeff[i][j] != 0.0) {
+                if (!(((i == 0) && (j == 0)) ||
+		      ((i == 0) && (j == 1)) ||
+		      ((i == 1) && (j == 0)))) {
+                    return(false);
+                }
+            }
+        }
+    }
+
+    return(true);
+}
+
+psPlane* psPlaneAlloc(void)
+{
+    psPlane *p = psAlloc(sizeof(psPlane));
+    psMemSetDeallocator(p, (psFreeFunc) planeFree);
+
+    p->x = NAN;
+    p->y = NAN;
+    p->xErr = NAN;
+    p->yErr = NAN;
+
+    return(p);
+}
+
+
+psSphere* psSphereAlloc(void)
+{
+    psSphere *s = psAlloc(sizeof(psSphere));
+    psMemSetDeallocator(s, (psFreeFunc) sphereFree);
+
+    return(s);
+}
+
+psCube* psCubeAlloc(void)
+{
+    psCube *c = psAlloc(sizeof(psCube));
+
+    psMemSetDeallocator(c, (psFreeFunc) cubeFree);
+    return(c);
+}
+
+psPlaneTransform* psPlaneTransformAlloc(int order1, int order2)
+{
+    PS_ASSERT_INT_NONNEGATIVE(order1, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(order2, NULL);
+
+    psPlaneTransform *pt = psAlloc(sizeof(psPlaneTransform));
+    pt->x = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, order1, order2);
+    pt->y = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, order1, order2);
+
+    psMemSetDeallocator(pt, (psFreeFunc) planeTransformFree);
+    return(pt);
+}
+
+
+bool psMemCheckPlane(psPtr ptr)
+{
+    PS_ASSERT_PTR_NON_NULL(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)planeFree );
+}
+
+bool psMemCheckSphere(psPtr ptr)
+{
+    PS_ASSERT_PTR_NON_NULL(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)sphereFree );
+}
+
+bool psMemCheckCube(psPtr ptr)
+{
+    PS_ASSERT_PTR_NON_NULL(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)cubeFree );
+}
+
+bool psMemCheckPlaneTransform(psPtr ptr)
+{
+    PS_ASSERT_PTR_NON_NULL(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)planeTransformFree );
+}
+
+psPlane* psPlaneTransformApply(
+    psPlane* out,
+    const psPlaneTransform* transform,
+    const psPlane* coords)
+{
+    PS_ASSERT_PTR_NON_NULL(transform, NULL);
+    PS_ASSERT_PTR_NON_NULL(transform->x, NULL);
+    PS_ASSERT_PTR_NON_NULL(transform->y, NULL);
+    PS_ASSERT_PTR_NON_NULL(coords, NULL);
+
+    if (out == NULL) {
+        out = psPlaneAlloc();
+    }
+
+    out->x = psPolynomial2DEval(transform->x, coords->x, coords->y);
+    out->y = psPolynomial2DEval(transform->y, coords->x, coords->y);
+
+    return (out);
+}
+
+static void planeDistortFree(psPlaneDistort *pt)
+{
+    psFree(pt->x);
+    psFree(pt->y);
+}
+
+psPlaneDistort* psPlaneDistortAlloc(int order1, int order2, int order3, int order4)
+{
+    PS_ASSERT_INT_NONNEGATIVE(order1, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(order2, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(order3, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(order4, NULL);
+
+    psPlaneDistort *pt = psAlloc(sizeof(psPlaneDistort));
+    pt->x = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, order1, order2, order3, order4);
+    pt->y = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, order1, order2, order3, order4);
+
+    psMemSetDeallocator(pt, (psFreeFunc) planeDistortFree);
+    return(pt);
+}
+
+bool psMemCheckPlaneDistort(psPtr ptr)
+{
+    PS_ASSERT_PTR_NON_NULL(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)planeDistortFree );
+}
+
+
+
+/******************************************************************************
+This transformation takes into account parameters beyond an objects spatial
+coordinates: term3 and term4 (magnitude and color).
+*****************************************************************************/
+psPlane* psPlaneDistortApply(
+    psPlane* out,
+    const psPlaneDistort* distort,
+    const psPlane* coords,
+    float mag,
+    float color)
+{
+    PS_ASSERT_PTR_NON_NULL(distort, NULL);
+    PS_ASSERT_PTR_NON_NULL(distort->x, NULL);
+    PS_ASSERT_PTR_NON_NULL(distort->y, NULL);
+    PS_ASSERT_PTR_NON_NULL(coords, NULL);
+
+    if (out == NULL) {
+        out = psPlaneAlloc();
+    }
+    out->x = psPolynomial4DEval(distort->x, coords->x, coords->y, mag, color);
+    out->y = psPolynomial4DEval(distort->y, coords->x, coords->y, mag, color);
+    return (out);
+}
+
+
+void projectionFree(psProjection *p)
+{
+    // There are no dynamically allocated items
+}
+
+psProjection* psProjectionAlloc(
+    double R,
+    double D,
+    double Xs,
+    double Ys,
+    psProjectionType type)
+{
+    psProjection *p = psAlloc(sizeof(psProjection));
+    p->D = D;
+    p->R = R;
+    p->Xs = Xs;
+    p->Ys = Ys;
+    p->type = type;
+
+    psMemSetDeallocator(p, (psFreeFunc) projectionFree);
+    return(p);
+}
+
+bool psMemCheckProjection(psPtr ptr)
+{
+    PS_ASSERT_PTR_NON_NULL(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)projectionFree );
+}
+
+typedef enum {
+    PS_PROJECTION_CLASS_NONE,
+    PS_PROJECTION_CLASS_CARTESIAN,
+    PS_PROJECTION_CLASS_ZENITHAL,
+    PS_PROJECTION_CLASS_PSEUDOCYL,
+}psProjectionClass;
+
+psPlane* psProject(
+    psPlane *outPlane,
+    const psSphere* coord,
+    const psProjection* projection)
+{
+    PS_ASSERT_PTR_NON_NULL(coord, NULL);
+    PS_ASSERT_PTR_NON_NULL(projection, NULL);
+
+    psF64 phi = 0;
+    psF64 theta = 0;
+    psF64 sinTheta = 0;
+    psF64 cosPhiCT = 0;
+    psF64 sinPhiCT = 0;
+    psF64 sinDp, cosDp, sinAlpha, cosAlpha, sinDelta, cosDelta, zeta;
+
+    psProjectionClass class = PS_PROJECTION_CLASS_NONE;
+    switch (projection->type) {
+      case PS_PROJ_LIN:
+      case PS_PROJ_PLY:
+      case PS_PROJ_WRP:
+        class = PS_PROJECTION_CLASS_CARTESIAN;
+        break;
+      case PS_PROJ_TAN:
+      case PS_PROJ_TNX:
+      case PS_PROJ_DIS:
+      case PS_PROJ_SIN:
+      case PS_PROJ_STG:
+      case PS_PROJ_ZEA:
+      case PS_PROJ_ZPL:
+        class = PS_PROJECTION_CLASS_ZENITHAL;
+        break;
+      case PS_PROJ_AIT:
+      case PS_PROJ_PAR:
+      case PS_PROJ_GLS:
+      case PS_PROJ_MER:
+      case PS_PROJ_CAR:
+        class = PS_PROJECTION_CLASS_PSEUDOCYL;
+        break;
+
+      default:
+        psAbort("invalid projection");
+        break;
+    }
+
+    // Allocate return value
+    psPlane* out = NULL;
+    if (outPlane == NULL) {
+        out = psPlaneAlloc();
+    } else {
+        out = outPlane;
+    }
+
+    switch (class) {
+      case PS_PROJECTION_CLASS_CARTESIAN:
+        out->x = (coord->r - projection->R);
+        out->y = (coord->d - projection->D);
+        break;
+
+      case PS_PROJECTION_CLASS_ZENITHAL:
+        sinDp = sin(projection->D);
+        cosDp = cos(projection->D);
+        sinAlpha = sin(coord->r-projection->R);
+        cosAlpha = cos(coord->r-projection->R);
+        sinDelta = sin(coord->d);
+        cosDelta = cos(coord->d);
+
+# if ELIXIR_CODE
+
+        sinTheta =  cosDelta*cosAlpha*cosDp + sinDelta*sinDp;
+	sinPhiCT =  cosDelta*sinAlpha;
+	cosPhiCT =  cosDelta*cosAlpha*sinDp - sinDelta*cosDp;
+# else
+
+        sinTheta =  cosDelta*cosAlpha*cosDp + sinDelta*sinDp;
+	sinPhiCT = -cosDelta*sinAlpha;
+	cosPhiCT = -cosDelta*cosAlpha*sinDp + sinDelta*cosDp;
+# endif
+	// Perform the specified projection
+	switch (projection->type) {
+	  case PS_PROJ_TAN:
+	  case PS_PROJ_TNX: // XXX this is not quite right
+	  case PS_PROJ_DIS:
+	    // Gnomonic projection
+	    out->x = +sinPhiCT / sinTheta;
+	    out->y = -cosPhiCT / sinTheta;
+	    break;
+	  case PS_PROJ_SIN:
+	    // Othrographic projection
+	    out->x = +sinPhiCT;
+	    out->y = -cosPhiCT;
+	    break;
+	  case PS_PROJ_STG:
+	    // Othrographic projection
+	    out->x = +2*sinPhiCT / (1 + sinTheta);
+	    out->y = -2*cosPhiCT / (1 + sinTheta);
+	    break;
+	  case PS_PROJ_ZEA:
+	  case PS_PROJ_ZPL:
+	    // Zenithal Equal-Area
+	    zeta = M_SQRT2 / sqrt (1 + sinTheta);
+	    out->x = +zeta * sinPhiCT;
+	    out->y = -zeta * cosPhiCT;
+	    break;
+	  default:
+	    psAbort("invalid projection");
+	    break;
+	}
+	break;
+
+      case PS_PROJECTION_CLASS_PSEUDOCYL:
+        phi = coord->r - projection->R;
+        theta = coord->d - projection->D;
+        switch (projection->type)
+        {
+	  case PS_PROJ_AIT:
+            // Hammer-Aitoff projection
+            zeta = 1.0/sqrt(0.5*(1.0+cos(theta)*cos(phi/2.0)));
+            out->x = 2.0*zeta*cos(theta)*sin(phi/2.0);
+            out->y = zeta*sin(theta);
+            break;
+	  case PS_PROJ_GLS:
+            // projection name?
+            out->x = phi * cos(theta);
+            out->x = theta;
+            break;
+	  case PS_PROJ_PAR:
+            // Parabolic projection
+            out->x = phi*(2.0*cos(2.0*theta/3.0) - 1.0);
+            out->y = M_PI*sin(theta/3.0);
+            break;
+	  case PS_PROJ_CAR:
+	  case PS_PROJ_MER:
+            psAbort("projection not yet implemented");
+            break;
+	  default:
+            psAbort("invalid projection");
+            break;
+        }
+        break;
+
+      default:
+        psAbort("invalid projection");
+        break;
+    }
+
+    // Apply plate scales
+    out->x /= projection->Xs;
+    out->y /= projection->Ys;
+
+    // Return output
+    return out;
+}
+
+psSphere* psDeproject(
+    psSphere *outSphere,
+    const psPlane* coord,
+    const psProjection* projection)
+{
+    PS_ASSERT_PTR_NON_NULL(coord, NULL);
+    PS_ASSERT_PTR_NON_NULL(projection, NULL);
+
+    psF64 rho      = 0.0;
+    psF64 rho2      = 0.0;
+    psF64 sinTheta = 0.0;
+    psF64 cosTheta = 0.0;
+    psF64 sinPhi   = 0.0;
+    psF64 cosPhi   = 0.0;
+
+    psF64  theta = 0.0;
+    psF64  phi   = 0.0;
+    psF64  x = 0, y = 0, R = 0;
+
+    psProjectionClass class = PS_PROJECTION_CLASS_NONE;
+    switch (projection->type) {
+      case PS_PROJ_LIN:
+      case PS_PROJ_PLY:
+      case PS_PROJ_WRP:
+        class = PS_PROJECTION_CLASS_CARTESIAN;
+        break;
+      case PS_PROJ_TAN:
+      case PS_PROJ_TNX:
+      case PS_PROJ_DIS:
+      case PS_PROJ_SIN:
+      case PS_PROJ_STG:
+      case PS_PROJ_ZEA:
+      case PS_PROJ_ZPL:
+        class = PS_PROJECTION_CLASS_ZENITHAL;
+        break;
+      case PS_PROJ_AIT:
+      case PS_PROJ_PAR:
+      case PS_PROJ_GLS:
+      case PS_PROJ_CAR:
+      case PS_PROJ_MER:
+        class = PS_PROJECTION_CLASS_PSEUDOCYL;
+        break;
+
+      default:
+        psAbort("invalid projection");
+        break;
+    }
+
+    // Allocate return sphere structure
+    psSphere *out = NULL;
+    if (outSphere == NULL) {
+        out = psSphereAlloc();
+    } else {
+        out = outSphere;
+    }
+
+    // Perform inverse projection
+    switch (class) {
+      case PS_PROJECTION_CLASS_CARTESIAN:
+        out->r = coord->x*projection->Xs + projection->R;
+        out->d = coord->y*projection->Ys + projection->D;
+        break;
+
+      case PS_PROJECTION_CLASS_ZENITHAL:
+        // Remove plate scales
+        x = coord->x*projection->Xs;
+        y = coord->y*projection->Ys;
+        R = sqrt(x*x + y*y);
+        sinPhi   = (R == 0) ? 0.0 : +x / R;
+        cosPhi   = (R == 0) ? 1.0 : -y / R;
+
+        switch (projection->type) {
+	  case PS_PROJ_TAN:
+	  case PS_PROJ_TNX:// XXX this is not quite right
+	  case PS_PROJ_DIS:
+            // Gnonomic deprojection
+            rho      = sqrt (1 + R*R);
+            sinTheta = 1 / rho;
+            cosTheta = R / rho;
+            break;
+	  case PS_PROJ_SIN:
+            // Orhtographic deprojection
+            sinTheta = sqrt (1 - R*R);
+            cosTheta = R;
+            break;
+	  case PS_PROJ_STG:
+            psAbort("STG not defined");
+            break;
+	  case PS_PROJ_ZEA:
+	  case PS_PROJ_ZPL:
+            if (R > 2)
+                return NULL;
+            sinTheta = 1 - 0.5*PS_SQR(R);
+            cosTheta = sqrt (1 - PS_SQR(sinTheta));
+            break;
+	  default:
+            psAbort("invalid projection");
+            break;
+        }
+
+        psF64 sinDp = sin(projection->D);
+        psF64 cosDp = cos(projection->D);
+
+        // Convert from projection spherical coordinates
+        // psLib versions:
+# if ELIXIR_CODE
+        // XXX the elixir version : does the ADD have a sign error?
+        psF64 delta    = asin(sinTheta*sinDp - cosTheta*cosPhi*cosDp);
+        psF64 sinAlpha = +cosTheta*sinPhi;
+        psF64 cosAlpha = +cosTheta*cosPhi*sinDp + sinTheta*cosDp;
+# else
+
+	psF64 delta    = asin(sinTheta*sinDp + cosTheta*cosPhi*cosDp);
+        psF64 sinAlpha = -cosTheta*sinPhi;
+        psF64 cosAlpha = -cosTheta*cosPhi*sinDp + sinTheta*cosDp;
+# endif
+
+        out->d = delta;
+        out->r = atan2(sinAlpha, cosAlpha) + projection->R;
+        break;
+
+      case PS_PROJECTION_CLASS_PSEUDOCYL:
+        switch (projection->type)
+        {
+	  case PS_PROJ_AIT:
+            // Hammer-Aitoff deprojection
+            // XXX EAM : need range check on z^2 : must be > 0
+            // XXX EAM : old code, ADD, and elixir code are discrepant re x/4, y/2
+            rho2 = 1.0 - PS_SQR(0.25*x) - PS_SQR(0.5*y);
+            if (rho2 < 0)
+                return (NULL);
+            rho = sqrt(rho2);
+            phi = 2.0*atan2(0.5*x*rho, 2.0*rho2 - 1.0);
+            theta = asin(y*rho);
+            break;
+	  case PS_PROJ_PAR:
+            // Parabolic deprojection
+            rho = y/M_PI;
+            phi = x/(1.0 - 4.0*rho*rho);
+            theta = 3.0*asin(rho);
+            break;
+	  case PS_PROJ_GLS:
+            phi = x/cos(y);
+            theta = y;
+            break;
+	  default:
+            psAbort("invalid projection");
+            break;
+        }
+        out->r = phi   + projection->R;
+        out->d = theta + projection->D;
+        break;
+      default:
+        psAbort("invalid projection");
+        break;
+    }
+
+    // Return sphere coordinate
+    return out;
+}
+
+/*****************************************************************************
+multiplyDPoly2D(trans1, trans2): Takes two 2-D polynomials as input and
+multiplies them.  Basically, for each non-zero coeff in the trans1 coeff[][]
+array, you must multiply by all non-zero coeffs in trans2.
+*****************************************************************************/
+static psPolynomial2D *multiplyDPoly2D(
+    psPolynomial2D *trans1,
+    psPolynomial2D *trans2)
+{
+    psTrace("psLib.astro", 4, "---- %s() begin ----\n", __func__);
+    psTrace("psLib.astro", 5, "multiplyDPoly2D(%d %d: %d %d)\n", trans1->nX, trans1->nY, trans2->nX, trans2->nY);
+    psS32 orderX = trans1->nX + trans2->nX;
+    psS32 orderY = trans1->nY + trans2->nY;
+    psTrace("psLib.astro", 5, "out poly (nX, nY) is (%d, %d)\n", orderX, orderY);
+
+    psPolynomial2D *out = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, orderX, orderY);
+    psTrace("psLib.astro", 5, "Creating poly (%d, %d)\n", orderX, orderY);
+
+    for (psS32 t1x = 0 ; t1x < (1 + trans1->nX) ; t1x++) {
+        for (psS32 t1y = 0 ; t1y < (1 + trans1->nY) ; t1y++) {
+            if (0.0 != trans1->coeff[t1x][t1y]) {
+                for (psS32 t2x = 0 ; t2x < (1 + trans2->nX) ; t2x++) {
+                    for (psS32 t2y = 0 ; t2y < (1 + trans2->nY) ; t2y++) {
+                        out->coeff[t1x+t2x][t1y+t2y]+= (trans1->coeff[t1x][t1y] * trans2->coeff[t2x][t2y]);
+                    }
+                }
+            }
+        }
+    }
+    psTrace("psLib.astro", 4, "---- %s() end ----\n", __func__);
+    return(out);
+}
+
+/*****************************************************************************
+psPlaneTransformCombine(out, trans1, trans2)
+*****************************************************************************/
+psPlaneTransform *psPlaneTransformCombine(
+    psPlaneTransform *out,
+    const psPlaneTransform *trans1,
+    const psPlaneTransform *trans2,
+    psRegion region,
+    int nSamples)
+{
+    psTrace("psLib.astro", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psLib.astro", 3, "tracelevel(%s) is %d\n", __func__, psTraceGetLevel("psLib.astro"));
+
+    PS_ASSERT_PTR_NON_NULL(trans1, NULL);
+    PS_ASSERT_PTR_NON_NULL(trans2, NULL);
+    psTrace("psLib.astro", 5, "trans1->x is (%d, %d) order.\n", trans1->x->nX, trans1->x->nY);
+    psTrace("psLib.astro", 5, "trans1->y is (%d, %d) order.\n", trans1->y->nX, trans1->y->nY);
+    psTrace("psLib.astro", 5, "trans2->x is (%d, %d) order.\n", trans2->x->nX, trans2->x->nY);
+    psTrace("psLib.astro", 5, "trans2->y is (%d, %d) order.\n", trans2->y->nX, trans2->y->nY);
+    if (psTraceGetLevel("psLib.astro") >= 6) {
+        PS_POLY_PRINT_2D(trans1->x);
+        PS_POLY_PRINT_2D(trans1->y);
+        PS_POLY_PRINT_2D(trans2->x);
+        PS_POLY_PRINT_2D(trans2->y);
+    }
+
+    //
+    // Determine the size of the new psPlaneTransform.
+    //
+    psS32 orderXnX = (trans2->x->nX * trans1->x->nX) + (trans2->x->nY * trans1->y->nX);
+    psS32 orderXnY = (trans2->x->nX * trans1->x->nY) + (trans2->x->nY * trans1->y->nY);
+    psS32 orderYnX = (trans2->y->nX * trans1->x->nX) + (trans2->y->nY * trans1->y->nX);
+    psS32 orderYnY = (trans2->y->nX * trans1->x->nY) + (trans2->y->nY * trans1->y->nY);
+    psS32 orderX = PS_MAX(orderXnX, orderYnX);
+    psS32 orderY = PS_MAX(orderXnY, orderYnY);
+    psTrace("psLib.astro", 5, "The new (orderX, orderY) is (%d, %d)\n", orderX, orderY);
+
+    //
+    // Allocate the new psPlaneTransform, if necessary.
+    //
+
+    psPlaneTransform *myPT = NULL;
+    if (out == NULL) {
+        myPT = psPlaneTransformAlloc(orderX, orderY);
+    } else {
+        if ((out->x->nX == orderX) &&
+	    (out->x->nY == orderY) &&
+	    (out->y->nX == orderX) &&
+	    (out->y->nY == orderY)) {
+            myPT = out;
+            //
+            // Initialize the new psPlaneTransform, if necessary.
+            //
+            for (psS32 i = 0 ; i < orderX+1 ; i++) {
+                for (psS32 j = 0 ; j < orderY+1 ; j++) {
+                    myPT->x->coeff[i][j] = 0.0;
+                    myPT->y->coeff[i][j] = 0.0;
+                    myPT->x->coeffMask[i][j] = PS_POLY_MASK_NONE;
+                    myPT->y->coeffMask[i][j] = PS_POLY_MASK_NONE;
+                }
+            }
+        } else {
+            psFree(out);
+            myPT = psPlaneTransformAlloc(orderX, orderY);
+        }
+    }
+    psTrace("psLib.astro", 5, "New polynomial ranks are (%d %d %d %d)\n", myPT->x->nX, myPT->x->nY, myPT->y->nX, myPT->y->nY);
+
+    //
+    // For each term (a * x^i * y^j) in trans2, we substitute the appropriate
+    // equation from trans1, and raise it to the appropriate power.  This is
+    // done via the multiplyDPoly2D().  The result is a polynomial (currPoly)
+    // and its coefficients are added into the myPT coeff matrix.
+    //
+    // trans1XPolys[i]: contains a polynomial corresponding to trans1->x raised to the i-th power.
+    //
+
+    psS32 order = PS_MAX(PS_MAX(PS_MAX(trans2->x->nX, trans2->x->nY), trans2->y->nX), trans2->y->nY);
+    psPolynomial2D **trans1XPolys = (psPolynomial2D **) psAlloc((order + 1) * sizeof(psPolynomial2D *));
+    psPolynomial2D **trans1YPolys = (psPolynomial2D **) psAlloc((order + 1) * sizeof(psPolynomial2D *));
+
+    //
+    // Raise the trans1 polynomials to whatever power is need in the trans2 polynomials.
+    //
+    trans1XPolys[0] = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 0, 0);
+    trans1XPolys[0]->coeff[0][0] = 1.0;
+    trans1YPolys[0] = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 0, 0);
+    trans1YPolys[0]->coeff[0][0] = 1.0;
+
+    for (psS32 c = 1 ; c < (order + 1) ; c++) {
+        trans1XPolys[c] = multiplyDPoly2D(trans1XPolys[c-1], trans1->x);
+        trans1YPolys[c] = multiplyDPoly2D(trans1YPolys[c-1], trans1->y);
+    }
+
+    psTrace("psLib.astro", 5, "Determine the new x-polynomial\n");
+    for (psS32 t2x = 0 ; t2x < (trans2->x->nX + 1) ; t2x++) {
+        for (psS32 t2y = 0 ; t2y < (trans2->x->nY + 1) ; t2y++) {
+            psTrace("psLib.astro", 6, "X: -------------------- (t2x, t2y) (%d, %d) --------------------\n", t2x, t2y);
+            if (trans2->x->coeffMask[t2x][t2y] & PS_POLY_MASK_SET) {
+		continue;
+	    }
+
+	    psTrace("psLib.astro", 6, "In this iteration, we raise trans1->x to the %d power and trans1->y to the %d-power.\n", t2x, t2y);
+	    psPolynomial2D *newPoly = multiplyDPoly2D(trans1XPolys[t2x], trans1YPolys[t2y]);
+
+	    if (psTraceGetLevel("psLib.astro") >= 6) {
+		PS_POLY_PRINT_2D(newPoly);
+	    }
+
+	    // Set the appropriate coeffs in myPT->x
+	    for (psS32 i = 0 ; i < (1 + newPoly->nX) ; i++) {
+		for (psS32 j = 0 ; j < (1 + newPoly->nY) ; j++) {
+		    myPT->x->coeff[i][j]+= newPoly->coeff[i][j] * trans2->x->coeff[t2x][t2y];
+		}
+	    }
+
+	    if (psTraceGetLevel("psLib.astro") >= 6) {
+		PS_POLY_PRINT_2D(myPT->x);
+	    }
+	    psFree(newPoly);
+        }
+    }
+    if (psTraceGetLevel("psLib.astro") >= 6) {
+        psTrace("psLib.astro", 6, "The final x-polynomial\n");
+        PS_POLY_PRINT_2D(myPT->x);
+    }
+
+    //
+    // Determine the new y-polynomial
+    //
+    psTrace("psLib.astro", 5, "Determine the new y-polynomial\n");
+    for (psS32 t2x = 0 ; t2x < (trans2->y->nX + 1) ; t2x++) {
+        for (psS32 t2y = 0 ; t2y < (trans2->y->nY + 1) ; t2y++) {
+            psTrace("psLib.astro", 5, "Y: -------------------- (t2x, t2y) (%d, %d) --------------------\n", t2x, t2y);
+            if (trans2->y->coeffMask[t2x][t2y] & PS_POLY_MASK_SET) {
+		continue;
+	    }
+	    psTrace("psLib.astro", 5, "In this iteration, we raise trans1->x to the %d power and trans1->y to the %d-power.\n", t2x, t2y);
+	    psPolynomial2D *newPoly = multiplyDPoly2D(trans1XPolys[t2x], trans1YPolys[t2y]);
+
+	    if (psTraceGetLevel("psLib.astro") >= 6) {
+		PS_POLY_PRINT_2D(newPoly);
+	    }
+
+	    // Set the appropriate coeffs in myPT->x
+	    for (psS32 i = 0 ; i < (1 + newPoly->nX) ; i++) {
+		for (psS32 j = 0 ; j < (1 + newPoly->nY) ; j++) {
+		    myPT->y->coeff[i][j]+= newPoly->coeff[i][j] * trans2->y->coeff[t2x][t2y];
+		}
+	    }
+	    if (psTraceGetLevel("psLib.astro") >= 6) {
+		PS_POLY_PRINT_2D(myPT->x);
+	    }
+	    psFree(newPoly);
+        }
+    }
+    if (psTraceGetLevel("psLib.astro") >= 6) {
+        psTrace("psLib.astro", 6, "The final y-polynomial\n");
+        PS_POLY_PRINT_2D(myPT->y);
+    }
+
+    for (psS32 c = 0 ; c < (order + 1) ; c++) {
+        psFree(trans1XPolys[c]);
+        psFree(trans1YPolys[c]);
+    }
+    psFree(trans1XPolys);
+    psFree(trans1YPolys);
+
+    psTrace("psLib.astro", 3, "---- %s() end ----\n", __func__);
+    return(myPT);
+}
+
+/*****************************************************************************
+psPlaneTransformFit(trans, source, dest, nRejIter, sigmaClip)
+
+XXX: This code ignores nRejIter and sigmaClip.  We must call the ClipFit
+routines instead.
+*****************************************************************************/
+bool psPlaneTransformFit(
+    psPlaneTransform *trans,
+    const psArray *source,
+    const psArray *dest,
+    int nRejIter,
+    float sigmaClip)
+{
+    PS_ASSERT_PTR_NON_NULL(trans, NULL);
+    PS_ASSERT_PTR_NON_NULL(source, NULL);
+    PS_ASSERT_PTR_NON_NULL(dest, NULL);
+
+    //
+    // Create the x and y vectors for the psVectorFitPolynomial2D() function.
+    //
+    psS32 numCoords = PS_MIN(source->n, dest->n);
+    psVector *xIn = psVectorAlloc(numCoords, PS_TYPE_F64);
+    psVector *yIn = psVectorAlloc(numCoords, PS_TYPE_F64);
+    psVector *xOut = psVectorAlloc(numCoords, PS_TYPE_F64);
+    psVector *yOut = psVectorAlloc(numCoords, PS_TYPE_F64);
+    for (int g = 0; g < numCoords; g++) {
+        xIn->data.F64[g] = ((psPlane *) source->data[g])->x;
+        yIn->data.F64[g] = ((psPlane *) source->data[g])->y;
+        xOut->data.F64[g] = ((psPlane *) dest->data[g])->x;
+        yOut->data.F64[g] = ((psPlane *) dest->data[g])->y;
+    }
+
+    bool result = true;
+    result &= psVectorFitPolynomial2D(trans->x, NULL, 0, xOut, NULL, xIn, yIn);
+    result &= psVectorFitPolynomial2D(trans->y, NULL, 0, yOut, NULL, xIn, yIn);
+    psFree(xIn);
+    psFree(yIn);
+    psFree(xOut);
+    psFree(yOut);
+
+    if (!result) {
+        psError( PS_ERR_UNKNOWN, true, "psVectorFitPolynomial2D() returned NULL: could not fit a 2-D polynomial to the data.\n");
+        return(false);
+    }
+
+    return(true);
+}
+
+
+/*****************************************************************************
+psPlaneTransformInvert(out, in, region, nSamples)
+
+*****************************************************************************/
+psPlaneTransform *psPlaneTransformInvert(
+    psPlaneTransform *out,
+    const psPlaneTransform *in,
+    psRegion region,
+    int nSamples)
+{
+    PS_ASSERT_PTR_NON_NULL(in, NULL);
+    PS_ASSERT_PTR_NON_NULL(in->x, NULL);
+    PS_ASSERT_PTR_NON_NULL(in->y, NULL);
+    PS_ASSERT_INT_LARGER_THAN(nSamples, 0, NULL);
+
+    // Reject a trivially non-invertible case.
+    if ((in->x->nX < 1) || (in->x->nY < 1) || (in->y->nX < 1) || (in->y->nY < 1)) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: input transform is not invertible.");
+        return(NULL);
+    }
+
+    // Ensure that the input transformation is symmetrical.
+    if ((in->x->nX != in->x->nY) || (in->y->nX != in->y->nY) || (in->x->nX != in->y->nX)) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Input transformation must have same nX==nY.");
+    }
+
+    //
+    // If the transform is linear, then invert it exactly and return.
+    //
+    if (p_psIsProjectionLinear((psPlaneTransform *) in)) {
+        return(p_psPlaneTransformLinearInvert((psPlaneTransform *) in));
+    }
+    PS_ASSERT_INT_LARGER_THAN_OR_EQUAL(nSamples, 1, NULL);
+
+    //
+    // Allocate a new psPlaneTransform if "out" is NULL, or has the wrong size.
+    //
+    psS32 order = in->x->nX;
+    psPlaneTransform *myPT = NULL;
+    if (out == NULL) {
+        myPT = psPlaneTransformAlloc(order, order);
+    } else {
+        if ((out->x->nX == order) && (out->x->nY == order) &&
+	    (out->y->nX == order) && (out->y->nX == order)) {
+            myPT = out;
+        } else {
+            psFree(out);
+            myPT = psPlaneTransformAlloc(order, order);
+        }
+    }
+
+    //
+    // Initialize the grid.  Since we want the inverse of the transformation, the
+    // inCoords are written to the outData vector, and the outCoords are written
+    // to the inData vector.
+    //
+    psVector *xIn = psVectorAlloc(nSamples*nSamples, PS_TYPE_F64);
+    psVector *yIn = psVectorAlloc(nSamples*nSamples, PS_TYPE_F64);
+    psVector *xOut = psVectorAlloc(nSamples*nSamples, PS_TYPE_F64);
+    psVector *yOut = psVectorAlloc(nSamples*nSamples, PS_TYPE_F64);
+    psPlane *inCoord = psPlaneAlloc();
+    psPlane *outCoord = psPlaneAlloc();
+    psS32 cnt = 0;
+    for (int yint = 0; yint < nSamples; yint++) {
+        inCoord->y = region.y0 + ((psF32) yint) * ((region.y1 - region.y0) / ((psF32) nSamples));
+        for (int xint = 0; xint < nSamples; xint++) {
+            inCoord->x = region.x0 + ((psF32) xint) * ((region.x1 - region.x0) / ((psF32) nSamples));
+            (void)psPlaneTransformApply(outCoord, in, inCoord);
+            xOut->data.F64[cnt] = inCoord->x;
+            yOut->data.F64[cnt] = inCoord->y;
+            xIn->data.F64[cnt] = outCoord->x;
+            yIn->data.F64[cnt] = outCoord->y;
+            cnt++;
+        }
+    }
+
+    bool result = true;
+    result &= psVectorFitPolynomial2D(myPT->x, NULL, 0, xOut, NULL, xIn, yIn);
+    result &= psVectorFitPolynomial2D(myPT->y, NULL, 0, yOut, NULL, xIn, yIn);
+
+    psFree(inCoord);
+    psFree(outCoord);
+    psFree(xIn);
+    psFree(yIn);
+    psFree(xOut);
+    psFree(yOut);
+
+    if (!result) {
+        psError( PS_ERR_UNKNOWN, true, "psVectorFitPolynomial2D() returned NULL: could not fit a 2-D polynomial to the data.\n");
+        psFree(myPT);
+        return(NULL);
+    }
+
+    return(myPT);
+}
+
+
+psPlane *psPlaneTransformDeriv(
+    psPlane *out,
+    const psPlaneTransform *transformation,
+    const psPlane *coord
+    )
+{
+    PS_ASSERT_PTR_NON_NULL(transformation, NULL);
+    PS_ASSERT_POLY_NON_NULL(transformation->x, NULL);
+    PS_ASSERT_POLY_NON_NULL(transformation->y, NULL);
+    PS_ASSERT_PTR_NON_NULL(coord, NULL);
+
+    if (out == NULL) {
+        out = psPlaneAlloc();
+    }
+
+    out->x = 0.0;
+    out->y = 0.0;
+    out->xErr = 0.0;
+    out->yErr = 0.0;
+
+    psPolynomial2D *xPoly = transformation->x;
+    psPolynomial2D *yPoly = transformation->y;
+
+    //
+    // Calculate the derivative with respect to x.
+    //
+    psF32 xSum = 1.0;
+    psF32 ySum = 1.0;
+
+    // This loop starts at loop_x=1 since the derivative of the loop_x=0 terms are all 0.0
+    for (psS32 loop_x = 1; loop_x < (1 + xPoly->nX); loop_x++) {
+        ySum = 1.0;
+        for (psS32 loop_y = 0; loop_y < (1 + xPoly->nY); loop_y++) {
+            //
+            // For each iteration of the loop, we multiply the (x, y) coefficient
+            // by (x^(loop_x-1) * y^loop_y) * loop_x
+            //
+
+            out->x+= xPoly->coeff[loop_x][loop_y] * xSum * ySum * ((psF32) loop_x);
+            psTrace("psLib.astro", 6, "out->x+= (%.2f * %.2f * %.2f * %.2f)\n", xPoly->coeff[loop_x][loop_y], xSum, ySum, ((psF32) loop_x));
+            ySum*= coord->y;
+        }
+        xSum*= coord->x;
+    }
+
+    //
+    // Calculate the derivative with respect to x.
+    //
+    xSum = 1.0;
+
+    // This loop starts at loop_y=1 since the derivative of the loop_y=0 terms are all 0.0
+    for (psS32 loop_x = 0; loop_x < (1 + yPoly->nX); loop_x++) {
+        ySum = 1.0;
+        for (psS32 loop_y = 1; loop_y < (1 + yPoly->nY); loop_y++) {
+            //
+            // For each iteration of the loop, we multiply the (x, y) coefficient
+            // by (x^(loop_x-1) * y^loop_y) * loop_y
+            // by (x^(loop_x) * y^(loop_y-1))
+            //
+
+            out->y+= yPoly->coeff[loop_x][loop_y] * xSum * ySum * ((psF32) loop_y);
+            psTrace("psLib.astro", 6, "out->y+= (%.2f * %.2f * %.2f * %.2f)\n", yPoly->coeff[loop_x][loop_y], xSum, ySum, ((psF32) loop_y));
+            ySum*= coord->y;
+        }
+        xSum*= coord->x;
+    }
+
+    return(out);
+}
+
+psPixels *psPixelsTransform(
+    psPixels *out,
+    const psPixels *input,
+    const psPlaneTransform *inToOut)
+{
+    PS_ASSERT_PTR_NON_NULL(input, NULL);
+    PS_ASSERT_PTR_NON_NULL(inToOut, NULL);
+    if (out == NULL) {
+        //XXX: Should the length (nalloc) be 1 and append be used everytime a pixel is added?
+        //        out = psPixelsAlloc(input->nalloc);
+        out = psPixelsAlloc(0);
+    }
+    psPlane *coord = psPlaneAlloc();
+    psPlane *deriv = psPlaneAlloc();
+    psPlane *fxnVal = psPlaneAlloc();
+
+    int i = 0;
+    //    int m = 0;
+    //    while (input->data.x[i] != 0.0 && input->data.y[i] != 0.0) {
+    for ( i = 0; i < input->n; i++) {
+        coord->x = input->data[i].x;
+        coord->y = input->data[i].y;
+        deriv = psPlaneTransformDeriv(deriv, inToOut, coord);
+        fxnVal = psPlaneTransformApply(fxnVal, inToOut, coord);
+        if (fabs(fxnVal->x - coord->x) <= fabs(deriv->x) &&
+	    fabs(fxnVal->y - coord->y) <= fabs(deriv->y)) {
+            int x = (int)(ceil(fabs(deriv->x)));
+            int y = (int)(ceil(fabs(deriv->y)));
+            for (int j = -x; j <= x; j++) {
+                for (int k = -y; k <= y; k++) {
+                    //                    out->data[m].x = fxnVal->x + x;
+                    //                    out->data[m].y = fxnVal->y + y;
+                    //                    m++;
+                    out = psPixelsAdd(out, 1, (float)(fxnVal->x+j),
+                                      (float)(fxnVal->y+k) );
+                }
+            }
+        }
+    }
+
+    psFree(coord);
+    psFree(deriv);
+    psFree(fxnVal);
+    return out;
+}
+
+psCube *psSphereToCube(const psSphere *sphere)
+{
+    if(sphere == NULL) {
+        psError( PS_ERR_UNKNOWN, true, "psSphere argument is NULL.  Returning NULL.\n");
+        return NULL;
+    }
+
+    psCube *cube = NULL;
+
+    cube = psCubeAlloc();
+    cube->x = cos(sphere->d) * cos(sphere->r);
+    cube->y = cos(sphere->d) * sin(sphere->r);
+    cube->z = sin(sphere->d);
+    cube->xErr = cos(sphere->dErr) * cos(sphere->rErr);
+    cube->yErr = cos(sphere->dErr) * sin(sphere->rErr);
+    cube->zErr = sin(sphere->dErr);
+
+    return(cube);
+}
+
+psSphere *psCubeToSphere(const psCube *cube)
+{
+    if(cube == NULL) {
+        psError( PS_ERR_UNKNOWN, true, "psCube argument is NULL.  Returning NULL.\n");
+        return NULL;
+    }
+
+    psSphere *sphere = NULL;
+    sphere = psSphereAlloc();
+    //    sphere->r = arctan(cube->x/cube->y);
+    //    sphere->d = arctan(sqrt(cube->x*cube->x + cube->y*cube->y)/cube->z);
+    //    sphere->rErr = arctan(cube->xErr/cube->yErr);
+    //    sphere->dErr = arctan(sqrt(cube->xErr*cube->xErr + cube->yErr*cube->yErr)/cube->zErr);
+    //    sphere->r = 1 / (atan(cube->x/cube->y));
+    //    sphere->d = 1 / (atan(sqrt(cube->x*cube->x + cube->y*cube->y)/cube->z));
+    //    sphere->rErr = 1 / (atan(cube->xErr/cube->yErr));
+    //    sphere->dErr = 1 / (atan(sqrt(cube->xErr*cube->xErr + cube->yErr*cube->yErr)/cube->zErr));
+    psCube *cube2 = psCubeAlloc();
+    *cube2 = *cube;
+    double mag = sqrt(cube->x*cube->x + cube->y*cube->y + cube->z*cube->z);
+    if (mag > 1.0) {
+        cube2->x = cube2->x/mag;
+        cube2->y = cube2->y/mag;
+        cube2->z = cube2->z/mag;
+    }
+
+    sphere->r = atan2(cube2->y, cube2->x);
+    sphere->d = asin(cube2->z);
+    //    sphere->d = atan2((cube->x*cube->x + cube->y*cube->y), cube->z);
+    sphere->rErr = atan2(cube2->yErr, cube2->xErr);
+    sphere->dErr = asin(cube2->zErr);
+    psFree(cube2);
+
+    return(sphere);
+}
+
+psString psProjectTypeToString(psProjectionType type, const char *prefix)
+{
+    PS_ASSERT_STRING_NON_EMPTY(prefix, NULL);
+
+    char *name = NULL;
+
+    switch (type) {
+      case PS_PROJ_LIN:
+        psStringAppend (&name, "%s-LIN", prefix);
+        return name;
+      case PS_PROJ_PLY:
+        psStringAppend (&name, "%s-PLY", prefix);
+        return name;
+      case PS_PROJ_WRP:
+        psStringAppend (&name, "%s-WRP", prefix);
+        return name;
+      case PS_PROJ_TAN:
+        psStringAppend (&name, "%s-TAN", prefix);
+        return name;
+      case PS_PROJ_TNX:
+        psStringAppend (&name, "%s-TNX", prefix);
+        return name;
+      case PS_PROJ_DIS:
+        psStringAppend (&name, "%s-DIS", prefix);
+        return name;
+      case PS_PROJ_SIN:
+        psStringAppend (&name, "%s-SIN", prefix);
+        return name;
+      case PS_PROJ_STG:
+        psStringAppend (&name, "%s-STG", prefix);
+        return name;
+      case PS_PROJ_AIT:
+        psStringAppend (&name, "%s-AIT", prefix);
+        return name;
+      case PS_PROJ_PAR:
+        psStringAppend (&name, "%s-PAR", prefix);
+        return name;
+      case PS_PROJ_GLS:
+        psStringAppend (&name, "%s-GLS", prefix);
+        return name;
+      case PS_PROJ_CAR:
+        psStringAppend (&name, "%s-CAR", prefix);
+        return name;
+      case PS_PROJ_MER:
+        psStringAppend (&name, "%s-MER", prefix);
+        return name;
+
+      default:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unknown projection type: %d\n", type);
+        return NULL;
+    }
+    return NULL;
+}
+
+psProjectionType psProjectTypeFromString(const char *name)
+{
+    PS_ASSERT_STRING_NON_EMPTY(name, PS_PROJ_NONE);
+
+    if (!strcmp (&name[4], "-LIN")) return PS_PROJ_LIN;
+    if (!strcmp (&name[4], "-PLY")) return PS_PROJ_PLY;
+    if (!strcmp (&name[4], "-WRP")) return PS_PROJ_WRP;
+    if (!strcmp (&name[4], "-TAN")) return PS_PROJ_TAN;
+    if (!strcmp (&name[4], "-TNX")) return PS_PROJ_TNX;
+    if (!strcmp (&name[4], "-DIS")) return PS_PROJ_DIS;
+    if (!strcmp (&name[4], "-SIN")) return PS_PROJ_SIN;
+    if (!strcmp (&name[4], "-STG")) return PS_PROJ_STG;
+    if (!strcmp (&name[4], "-AIT")) return PS_PROJ_AIT;
+    if (!strcmp (&name[4], "-PAR")) return PS_PROJ_PAR;
+    if (!strcmp (&name[4], "-GLS")) return PS_PROJ_GLS;
+    if (!strcmp (&name[4], "-CAR")) return PS_PROJ_CAR;
+    if (!strcmp (&name[4], "-MER")) return PS_PROJ_MER;
+
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unrecognised projection type: %s", name);
+    return PS_PROJ_NONE;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psCoord.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psCoord.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psCoord.h	(revision 22158)
@@ -0,0 +1,460 @@
+/** @file  psCoord.h
+ *
+ *  @brief Basic coordinate transformations
+ *
+ *  This file defines the basic types for astronomical coordinate
+ *  transformation
+ *
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.61 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-08-09 01:40:07 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_COORD_H
+#define PS_COORD_H
+
+/// @addtogroup Astro Astronomy
+/// @{
+
+#include "psType.h"
+#include "psImage.h"
+#include "psArray.h"
+#include "psList.h"
+#include "psPolynomial.h"
+#include "psPixels.h"
+#include "psRegion.h"
+//#include "psTime.h"
+
+/** Euclidiean Coordinate System.
+ *
+ *  Both detector and sky positions will be used extensively in the IPP. One
+ *  coordinate system to be used is linear coordinates which conform to
+ *  Euclidean geometry.
+ *
+ */
+typedef struct
+{
+    double x;                          ///< x position
+    double y;                          ///< y position
+    double xErr;                       ///< Error in x position
+    double yErr;                       ///< Error in y position
+}
+psPlane;
+
+/** Angular Coordinate System
+ *
+ *  Both detector and sky positions will be used extensively in the IPP. One
+ *  coordinate system to be used is angular coordinates for which additional
+ *  care must often be taken in comparison to a euclidiean coordinate system.
+ *
+ */
+typedef struct
+{
+    double r;                          ///< RA
+    double d;                          ///< Dec
+    double rErr;                       ///< Error in RA
+    double dErr;                       ///< Error in Dec
+}
+psSphere;
+
+/** 3-Dimensional Euclidean Coordinate System
+ *
+ *  Both detector and sky positions will be used extensively in the IPP. One
+ *  coordinate system to be used is cubic coordinates for which additional
+ *  care must often be taken in comparison to an angular coordinate system.
+ *
+ */
+typedef struct
+{
+    double x;                          ///< cos (DEC) cos (RA)
+    double y;                          ///< cos (DEC) sin (RA)
+    double z;                          ///< sin (DEC)
+    double xErr;                       ///< Error in x
+    double yErr;                       ///< Error in y
+    double zErr;                       ///< Error in z
+}
+psCube;
+
+/** 2D Polynomial Transform
+ *
+ *  A transform between coordinate systems that consists simply of two 2D
+ *  polynomials to transform both components - the output coordinates depend
+ *  only on the input coordinates and no other quantities of objects at those
+ *  coordinates.
+ *
+ */
+typedef struct
+{
+    psPolynomial2D* x;                 ///< 2D polynomial transform of X coordinates
+    psPolynomial2D* y;                 ///< 2D polynomial transform of Y coordinates
+}
+psPlaneTransform;
+
+/** 4D Polynomial Transform
+ *
+ *  A transform between coordinate systems that consists of two 4D polynomials
+ *  in which the output coordinates are also specified to be a function of the
+ *  magnitude and color of the object with the given coordinates. This type of
+ *  coordinate transformation is necessary to represent the (color-dependent)
+ *  optical distortions caused by the atmosphere and camera optics, and the
+ *  possibly effects of charge transfer inefficiency.
+ *
+ *  The lowest two terms are the x and y axis of the target system.  The higher
+ *  two terms may represent magnitude and color terms.
+ */
+typedef struct
+{
+    psPolynomial4D* x;                 ///< 4D polynomial transform of X coordinates
+    psPolynomial4D* y;                 ///< 4D polynomial transform of Y coordinates
+}
+psPlaneDistort;
+
+/** Projection type for projection/deprojection
+ *
+ *  @see psProject, psDeproject
+ *
+ */
+typedef enum {
+    PS_PROJ_NONE,                       ///< No projection
+    PS_PROJ_LIN,                        ///< Linear projection
+    PS_PROJ_PLY,                        ///< Linear polynomial projection
+    PS_PROJ_WRP,                        ///< Linear polynomial projection
+    PS_PROJ_TAN,                        ///< Tangent projection
+    PS_PROJ_DIS,                        ///< Sine projection
+    PS_PROJ_SIN,                        ///< Sine projection
+    PS_PROJ_STG,                        ///< Sine projection
+    PS_PROJ_TNX,                        ///< Sine projection
+    PS_PROJ_ZEA,                        ///< Sine projection
+    PS_PROJ_ZPL,                        ///< Sine projection
+    PS_PROJ_AIT,                        ///< Aitoff projection
+    PS_PROJ_PAR,                        ///< Par projection
+    PS_PROJ_GLS,                        ///< GLS projection
+    PS_PROJ_CAR,                        ///< CAR projection
+    PS_PROJ_MER,                        ///< MER projection
+    PS_PROJ_NTYPE                       ///< Number of types; must be last.
+} psProjectionType;
+
+/** Parameter set for projection/deprojection
+ *
+ *  @see psProject, psDeproject
+ *
+ */
+typedef struct
+{
+    double R;                          ///< Coordinates of projection center
+    double D;                          ///< Coordinates of projection center
+    double Xs;                         ///< plate-scale in X direction
+    double Ys;                         ///< plate-scale in Y direction
+    psProjectionType type;             ///< Projection type
+}
+psProjection;
+
+/** Allocates a psPlane
+ *
+ *  @return psPlane*     resulting plane structure.
+ */
+psPlane* psPlaneAlloc(void) PS_ATTR_MALLOC;
+
+/** Allocates a psSphere
+ *
+ *  @return psSphere*     resulting sphere structure.
+ */
+psSphere* psSphereAlloc(void) PS_ATTR_MALLOC;
+
+/** Allocates a psCube
+ *
+ *  @return psCube*     resulting cubic structure.
+ */
+psCube* psCubeAlloc(void) PS_ATTR_MALLOC;
+
+/** Allocates a psPlaneTransform transform.
+ *
+ *  @return psPlaneTransform*     resulting plane transform
+ */
+
+psPlaneTransform* psPlaneTransformAlloc(
+    int order1,                        ///< The order of the x term in the transform.
+    int order2                         ///< The order of the y term in the transform.
+) PS_ATTR_MALLOC;
+
+/** Applies the psPlaneTransform transform to a specified coordinate
+ *
+ *  @return psPlane*     resulting coordinate based on transform
+ */
+psPlane* psPlaneTransformApply(
+    psPlane* out,                      ///< a psPlane to recycle.  If NULL, a new one is generated.
+    const psPlaneTransform* transform, ///< the transform to apply
+    const psPlane* coords              ///< the coordinate to apply the transform above.
+);
+
+/** Allocates a psPlaneDistort transform.
+ *
+ *  @return psPlaneDistort*     resulting plane distort transform
+ */
+
+psPlaneDistort* psPlaneDistortAlloc(
+    int order1,                        ///< The order of the w term in the transform.
+    int order2,                        ///< The order of the x term in the transform.
+    int order3,                        ///< The order of the y term in the transform.
+    int order4                         ///< The order of the z term in the transform.
+) PS_ATTR_MALLOC;
+
+
+/** Applies the psPlaneDistort transform to a specified coordinate
+ *
+ *  @return psPlane*     resulting coordinate based on transform
+ */
+psPlane* psPlaneDistortApply(
+    psPlane* out,                      ///< a psPlane to recycle.  If NULL, a new one is generated.
+    const psPlaneDistort* distort,     ///< the transform to apply
+    const psPlane* coords,             ///< the coordinate to apply the transform above.
+    float mag,                         ///< third term -- maybe magnitude
+    float color                        ///< forth term -- maybe color
+);
+
+/** Allocates memory for a psProjection structure
+ *
+ *  @return psProjection*    psProjection structure
+ */
+psProjection* psProjectionAlloc(
+    double R,                          ///< Right-ascension of projection center.
+    double D,                          ///< Declination of projection center.
+    double Xs,                         ///< Scale in x-dimension
+    double Ys,                         ///< Scale in y-dimension
+    psProjectionType type
+) PS_ATTR_MALLOC;
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psPlane structure, false otherwise.
+ */
+bool psMemCheckPlane(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psSphere structure, false otherwise.
+ */
+bool psMemCheckSphere(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psCube structure, false otherwise.
+ */
+bool psMemCheckCube(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psPlaneTransform structure, false otherwise.
+ */
+bool psMemCheckPlaneTransform(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psPlaneDistort structure, false otherwise.
+ */
+bool psMemCheckPlaneDistort(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psProjection structure, false otherwise.
+ */
+bool psMemCheckProjection(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+
+/** Projects a spherical coordinate to a linear coordinate system
+ *
+ *  @return psPlane*    projected coordinate
+ */
+psPlane* psProject(
+    psPlane *out,
+    const psSphere* coord,             ///< coordinate to project
+    const psProjection* projection     ///< parameters of the projection
+);
+
+/** Reverse projection of a linear coordinate to a spherical coordinate system
+ *
+ *  @return psPlane*    projected coordinate
+ */
+psSphere* psDeproject(
+    psSphere *outSphere,
+    const psPlane* coord,              ///< coordinate to project
+    const psProjection* projection     ///< parameters of the projection
+);
+
+/** Takes a given transform and inverts it linearly if possible.
+ *
+ *  @return psPlaneTransform
+ *  the linearly inverted transform
+*/
+psPlaneTransform *p_psPlaneTransformLinearInvert(
+    psPlaneTransform *transform        ///< transform to invert
+);
+
+/** Takes a transform and tests whether or not it is a linear projection.
+ *
+ *  @return psS32
+ *  the order of the projection
+*/
+bool p_psIsProjectionLinear(
+    psPlaneTransform *transform        ///< transform to test for linearity
+);
+
+
+/** inverts a given transformation.
+ *
+ *  It may assume that the input transformation is one-to-one, and that the
+ *  inverse transformation may be specified through using polynomials of the
+ *  same type and order as the forward transformation. In the event that the
+ *  input transformation is linear, an exact solution may be calculated;
+ *  otherwise nSamples samples in each axis, covering the region specified by
+ *  region shall be used as a grid to fit the best inverse transformation. The
+ *  function shall return NULL if it was unable to generate the inverse
+ *  transformation; otherwise it shall return the inverse transformation. In
+ *  the event that out is NULL, a new psPlaneTransform shall be allocated and
+ *  returned.
+ *
+ *  @return psPlaneTransform*  the resulting inverted transform
+ */
+psPlaneTransform* psPlaneTransformInvert(
+    psPlaneTransform *out,             ///< a transform to recycle, or NULL if one is to be created.
+    const psPlaneTransform *in,        ///< transform to invert
+    psRegion region,                   ///< region to fit for non-linear transform inversion
+    int nSamples                       ///< number of samples in each axis for fit
+);
+
+/** Creates a single transformation that has the effect of performing trans1
+ *  followed by trans2.
+ *
+ *  psPlaneTransformCombine takes two transformations (trans1 and trans2) and
+ *  returns a single transformation that has the effect of performing trans1
+ *  followed by trans2. In the event that the input transformation is linear,
+ *  an exact solution may be calculated; otherwise nSamples samples in each
+ *  axis, covering the region specified by region shall be used as a grid to
+ *  fit the best inverse transformation. The function shall return NULL if it
+ *  was unable to generate the transformation; otherwise it shall return the
+ *  transformation.
+ *
+ *  @return psPlaneTransform*    resulting transformation
+ */
+psPlaneTransform* psPlaneTransformCombine(
+    psPlaneTransform *out,             ///< a transform to recycle, or NULL if one is to be created.
+    const psPlaneTransform *trans1,    ///< first transform to combine
+    const psPlaneTransform *trans2,    ///< first transform to combine
+    psRegion region,                   ///< region to cover (for non-linear transforms)
+    int nSamples                       ///< number of samples on each axis (for non-linear transforms)
+);
+
+
+/** takes two arrays containing matched coordinates and returns the
+ *  best-fitting transformation.
+ *
+ *  psPlaneTransformFit takes two arrays containing matched coordinates (i.e.,
+ *  coordinates in the source array correspond to the coordinates in the dest
+ *  array) and returns the best-fitting transformation. The source and dest
+ *  will contain psCoords. In the event that the number of coordinates in each
+ *  is not identical, the function shall generate a warning, and extra
+ *  coordinates in the longer of the two shall be ignored. The trans transform
+ *  may not be NULL, since it specifies the desired order, polynomial type and
+ *  any polynomial terms to mask. nRejIter rejection iterations shall be
+ *  performed, wherein coordinates lying more than sigmaClip standard
+ *  deviations from the fit shall be rejected.
+ *
+ *  @return bool        TRUE if successful, otherwise FALSE.
+ */
+bool psPlaneTransformFit(
+    psPlaneTransform *trans,           ///< desired order, polynomial type, & polynomial mask terms
+    const psArray *source,             ///< coordinates matching those in dest
+    const psArray *dest,               ///< coordinates matching those in source
+    int nRejIter,                      ///< number of rejection iterations to be performed
+    float sigmaClip                    ///< coordinates above this number of standard deviations will be rejected
+);
+//XXX: need to add doxygen comments on the parameters above. -rdd
+
+/** Converts from a 3-dimensional coordinate system to an angular coordinate system.
+ *
+ *  @return psSphere*       The former psCube in terms of a psSphere.
+ */
+psSphere *psCubeToSphere(
+    const psCube *cube                 ///< psCube to convert
+);
+
+/** Converts from an angular coordinate system to a 3-dimensional coordinate system.
+ *
+ *  @return psCube*         The former psSphere in terms of a psCube.
+ */
+psCube *psSphereToCube(
+    const psSphere *sphere             ///< psSphere to convert
+);
+
+
+/** Calculates the derivative of the specified psPlaneTransform with respect to x and y.
+ *
+ *  @return psPlane*         The derivative.
+ */
+psPlane *psPlaneTransformDeriv(
+    psPlane *out,
+    const psPlaneTransform *transformation,
+    const psPlane *coord
+);
+
+/** Generates a list of pixels in the output coordinate frame that overlap the input
+ *  pixels in the input coordinate frame through the specified transformation, inToOut.
+ *
+ *  psPixelsTransform is more complicated than simply transforming the input pixels,
+ *  but requires the evaluation of the derivatives of the transformation in order to
+ *  obtain the list of all pixels in the output coordinate frame that possibly overlap
+ *  the pixel in the input coordinate frame.  In the event that input or inToOut are
+ *  NULL, the function shall generate an error and return NULL.  If out is non-NULL it
+ *  shall be modified and returned;  otherwise a new psPixels shall be allocated and
+ *  returned.
+ *
+ *  @return psPixels*:      the list of overlapping pixels.
+ */
+psPixels *psPixelsTransform(
+    psPixels *out,                     ///< output list of overlapping pixels
+    const psPixels *input,             ///< input list of pixels
+    const psPlaneTransform *inToOut    ///< specified transformation
+);
+
+psString psProjectTypeToString(psProjectionType type, const char *prefix);
+psProjectionType psProjectTypeFromString(const char *name);
+
+
+#define PS_PRINT_PLANE_TRANSFORM(NAME) \
+{ \
+    printf("---------------------- Plane Transform ----------------------\n"); \
+    printf("x:\n"); \
+    PS_POLY_PRINT_2D(NAME->x); \
+    printf("y:\n"); \
+    PS_POLY_PRINT_2D(NAME->y); \
+} \
+
+/// @}
+#endif // #ifndef PS_COORD_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psEarthOrientation.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psEarthOrientation.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psEarthOrientation.c	(revision 22158)
@@ -0,0 +1,1390 @@
+/** @file  psEarthOrientation.c
+ *
+ *  @brief Function implementations for earth orientation calculations
+ *
+ *  @ingroup EarthOrientation
+ *
+ *  @author Dave Robbins, MHPCC
+ *  @author Robert Daniel DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.46 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-06-22 02:28:48 $
+ *
+ *  Copyright 2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <math.h>
+#include <string.h>
+
+#include "psEarthOrientation.h"
+#include "psArray.h"
+#include "psPolynomial.h"
+#include "psVector.h"
+#include "psMetadata.h"
+#include "psMetadataConfig.h"
+#include "psError.h"
+
+#include "psMemory.h"
+#include "psCoord.h"
+#include "psAssert.h"
+
+// Sun's Mass (src: Google's Calculator Service)
+#define PS_M   1.98892e30 /* kilograms */
+// Newton's Gravitational Constant (src:NIST)
+#define PS_G   6.6742e-11 /* m^3/kg/s^2 */
+// Speed of light in vacuum (src:NIST)
+#define PS_C0  299792458.0 /* m/s */
+// Average distance from earth to sun
+#define PS_AU 149597890000.0 /* meters */
+// Modified Julian Day 1/1/2000 00:00:00
+#define MJD_2000  51544.5
+// Days in Julian century
+#define JULIAN_CENTURY 36525.0
+
+//The arrays used for storage of x,y,&s-values extracted from the precession data tables.
+// Created in p_psEOCInit from finalsTable and used in psPrecessionModel.
+static psArray* xTable = NULL;
+static psArray* yTable = NULL;
+static psArray* sTable = NULL;
+
+//used for storage of the IERS precession table.  Should contain MJD date followed by the
+// corresponding dX & dY values from the finals2000A table.  (Used in psPrecessionCorr.)
+static psArray* iersTable = NULL;
+//used for precession data.  Should contain MJD date followed by the corresponding X, Y, &
+// UT1-UTC values from the finals2000A table.  (Used in psPrecessionModel, psGetPolarMotion).
+static psArray* finalsTable = NULL;
+
+//1D Polynomials created from the coefficients given by the tab5.2?.txt files.  Used
+// by psPrecessionModel to determine psEarthPole components.
+static psPolynomial1D* xPoly = NULL;
+static psPolynomial1D* yPoly = NULL;
+static psPolynomial1D* sPoly = NULL;
+
+//Boolean variable to tell whether the above EOC data has been initialized.
+static bool eocInitialized = false;
+
+//Internal function used for conversion from a 3x3 rotation matrix to a quaternion (psSphereRot).
+static psSphereRot *rotMatrix_To_Quat(double A[3][3]);
+
+static void earthPoleFree(psEarthPole *pole)
+{
+    // There are non dynamic allocated items
+}
+
+psEarthPole *psEarthPoleAlloc(void)
+{
+    psEarthPole* pole = psAlloc(sizeof(psEarthPole));
+    psMemSetDeallocator(pole, (psFreeFunc) earthPoleFree);
+    pole->x = 0.0;
+    pole->y = 0.0;
+    pole->s = 0.0;
+    return pole;
+}
+
+bool p_psEOCInit()
+{
+    unsigned int nFail = 0;
+
+    // Read config file
+    psMetadata* eocMetadata = psMetadataConfigRead(NULL,
+                              &nFail,
+                              p_psTimeConfigFilename(NULL),
+                              true);
+    //Make sure reading of config file worked correctly
+    if(eocMetadata == NULL) {
+        return false;
+    } else if(nFail != 0) {
+        return false;
+    }
+
+    bool success = false;
+    // Get table formats & error if lookups fail.
+    char* tableFormat = psMetadataLookupStr(&success, eocMetadata,
+                                            "psLib.eoc.precession.table.format");
+    if(! success || tableFormat == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                "psLib.eoc.precession.table.format");
+        return false;
+    }
+
+    char* xTableName = psMetadataLookupStr(&success, eocMetadata,
+                                           "psLib.eoc.precession.table.file.x");
+    if(! success || xTableName == NULL) {
+        psFree(tableFormat);
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                "psLib.eoc.precession.x.file");
+        return false;
+    }
+
+    char* yTableName = psMetadataLookupStr(&success, eocMetadata,
+                                           "psLib.eoc.precession.table.file.y");
+    if(! success || yTableName == NULL) {
+        psFree(tableFormat);
+        psFree(xTableName);
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                "psLib.eoc.precession.y.file");
+        return false;
+    }
+
+    char* sTableName = psMetadataLookupStr(&success, eocMetadata,
+                                           "psLib.eoc.precession.table.file.s");
+    if(! success || sTableName == NULL) {
+        psFree(tableFormat);
+        psFree(xTableName);
+        psFree(yTableName);
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                "psLib.eoc.precession.s.file");
+        return false;
+    }
+
+    char* iersTableName = psMetadataLookupStr(&success, eocMetadata,
+                          "psLib.eoc.precession.table.file.iers");
+    if(! success || sTableName == NULL) {
+        psFree(tableFormat);
+        psFree(xTableName);
+        psFree(yTableName);
+        psFree(sTableName);
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                "psLib.eoc.precession.iers.file");
+        return false;
+    }
+
+    char* finalsTableName = psMetadataLookupStr(&success, eocMetadata,
+                            "psLib.eoc.precession.table.file.final");
+    if(! success || sTableName == NULL) {
+        psFree(tableFormat);
+        psFree(xTableName);
+        psFree(yTableName);
+        psFree(sTableName);
+        psFree(iersTableName);
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                "psLib.eoc.precession.finals.file");
+        return false;
+    }
+
+    char* iersTableFormat = psMetadataLookupStr(&success, eocMetadata,
+                            "psLib.eoc.precession.iers.table.format");
+    if(! success || iersTableFormat == NULL) {
+        psFree(tableFormat);
+        psFree(xTableName);
+        psFree(yTableName);
+        psFree(sTableName);
+        psFree(iersTableName);
+        psFree(finalsTableName);
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                "psLib.eoc.precession.iers.table.format");
+        return false;
+    }
+
+    char* finalsTableFormat = psMetadataLookupStr(&success, eocMetadata,
+                              "psLib.eoc.precession.finals.table.format");
+    if(! success || iersTableFormat == NULL) {
+        psFree(tableFormat);
+        psFree(xTableName);
+        psFree(yTableName);
+        psFree(sTableName);
+        psFree(iersTableName);
+        psFree(finalsTableName);
+        psFree(iersTableFormat);
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                "psLib.eoc.precession.iers.table.format");
+        return false;
+    }
+
+    //Extract the necessary data to setup the tables
+    xTable = psVectorsReadFromFile(xTableName, tableFormat);
+    yTable = psVectorsReadFromFile(yTableName, tableFormat);
+    sTable = psVectorsReadFromFile(sTableName, tableFormat);
+    iersTable = psVectorsReadFromFile(iersTableName, iersTableFormat);
+    finalsTable = psVectorsReadFromFile(finalsTableName, finalsTableFormat);
+
+    //Check that the data extraction was performed successfully.
+    if(xTable == NULL || yTable == NULL || sTable == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Failed to read the precession-nutation model tables.");
+        return false;
+    }
+    if(iersTable == NULL || finalsTable == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Failed to read the IERS/finals tables.");
+        return false;
+    }
+
+    //Load the coefficient data to setup the polynomials.
+    psVector* xCoeff = psMetadataLookupPtr(&success, eocMetadata, "psLib.eoc.precession.poly.x");
+    if(! success || xCoeff == NULL || xCoeff->type.type != PS_TYPE_F64) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                "psLib.eoc.precession.poly.x");
+        return false;
+    }
+    psVector* yCoeff = psMetadataLookupPtr(&success, eocMetadata, "psLib.eoc.precession.poly.y");
+    if(! success || yCoeff == NULL || yCoeff->type.type != PS_TYPE_F64) {
+        psFree(xCoeff);
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                "psLib.eoc.precession.poly.y");
+        return false;
+    }
+    psVector* sCoeff = psMetadataLookupPtr(&success, eocMetadata, "psLib.eoc.precession.poly.s");
+    if(! success || sCoeff == NULL || sCoeff->type.type != PS_TYPE_F64) {
+        psFree(xCoeff);
+        psFree(yCoeff);
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                "psLib.eoc.precession.poly.s");
+        return false;
+    }
+    //Allocate the X,Y,&S polynomials to be used for earthpole calculations
+    xPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, xCoeff->n);
+    memcpy(xPoly->coeff, xCoeff->data.F64,PSELEMTYPE_SIZEOF(PS_TYPE_F64)*xCoeff->n);
+    yPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, yCoeff->n);
+    memcpy(yPoly->coeff, yCoeff->data.F64,PSELEMTYPE_SIZEOF(PS_TYPE_F64)*yCoeff->n);
+    sPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, sCoeff->n);
+    memcpy(sPoly->coeff, sCoeff->data.F64,PSELEMTYPE_SIZEOF(PS_TYPE_F64)*sCoeff->n);
+
+    psFree(eocMetadata);
+
+    return true;
+}
+
+bool p_psEOCFinalize(void)
+{
+    psFree(xTable);
+    psFree(yTable);
+    psFree(sTable);    // There are non dynamic allocated items
+    psFree(iersTable);
+    psFree(finalsTable);
+
+    xTable = NULL;
+    yTable = NULL;
+    sTable = NULL;
+    iersTable = NULL;
+    finalsTable = NULL;
+
+    psFree(xPoly);
+    psFree(yPoly);
+    psFree(sPoly);
+
+    xPoly = NULL;
+    yPoly = NULL;
+    sPoly = NULL;
+
+    eocInitialized = false;
+
+    return true;
+}
+
+psSphere *psAberration(psSphere *apparent,
+                       const psSphere *actual,
+                       const psSphere *direction,
+                       double speed)
+{
+    //Check for valid inputs
+    PS_ASSERT_PTR_NON_NULL(actual, NULL);
+    PS_ASSERT_PTR_NON_NULL(direction, NULL);
+    if (fabs(speed) < DBL_EPSILON) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Aberration speed should not be equal to 0.\n");
+        return NULL;
+    }
+    if (fabs(speed) > 1.0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Aberration speed should not greater than the speed of light!.\n");
+        return NULL;
+    }
+
+    psCube *rp = psCubeAlloc();
+    psCube *r_p = psCubeAlloc();
+    double mu = 0.0;
+    double mu_p = 0.0;
+    double a = 0.0;
+
+    //Convert the spherical input coords direction and actual to cubic coords for computations.
+    psCube* directionVector = NULL;
+    directionVector = psSphereToCube(direction);
+    if (directionVector == NULL) {
+        PS_ASSERT_PTR_NON_NULL(directionVector, NULL);
+    }
+    psCube* actualVector = NULL;
+    actualVector = psSphereToCube(actual);
+    if (actualVector == NULL) {
+        PS_ASSERT_PTR_NON_NULL(actualVector, NULL);
+    }
+
+    //Calculate mu as the dot-product of direction and actual (from ADD)
+    mu = (directionVector->x*actualVector->x +
+          directionVector->y*actualVector->y +
+          directionVector->z*actualVector->z);
+    //Calculate r-perpendicular (as in sec 3.5.3.2 of ADD). actual = r-hat, direction = beta-hat.
+    rp->x = actualVector->x - mu * directionVector->x;
+    rp->y = actualVector->y - mu * directionVector->y;
+    rp->z = actualVector->z - mu * directionVector->z;
+    //Calculate mu-prime.  (Eqn. 129 of ADD).
+    mu_p = mu - speed * ((mu * mu - 1.0) / (1.0 - speed * mu));
+    //Calculate a-value.  (a = sqrt[ (1 - mu-prime^2) / modulus(r-perpendicular) ] )
+    a = (1.0 - mu_p * mu_p) / (rp->x * rp->x + rp->y * rp->y + rp->z * rp->z);
+    if (a < 0.0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Invalid parameter.  a-value cannot be negative.\n");
+        psFree(rp);
+        psFree(r_p);
+        psFree(directionVector);
+        psFree(actualVector);
+        psFree(apparent);
+        return NULL;
+    } else {
+        a = sqrt(a);
+    }
+    //Calculate r-prime values.  r-prime = mu-prime * beta-hat  +  a * r-perpendicular
+    r_p->x = mu_p * directionVector->x + a * rp->x;
+    r_p->y = mu_p * directionVector->y + a * rp->y;
+    r_p->z = mu_p * directionVector->z + a * rp->z;
+    //If apparent is non-NULL, deallocate it for use with psCubeToSphere
+    if (apparent != NULL) {
+        psFree(apparent);
+    }
+    //Convert r-prime to spherical coordinates for output.
+    apparent = psCubeToSphere(r_p);
+    if (apparent == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "psCubeToSphere returned a NULL sphere in psAberration.\n");
+        return NULL;
+    }
+    psFree(rp);
+    psFree(r_p);
+    psFree(directionVector);
+    psFree(actualVector);
+
+    return apparent;
+}
+
+psSphere *psGravityDeflection(psSphere *apparent,
+                              psSphere *actual,
+                              psSphere *sun)
+{
+    //Check for valid inputs
+    PS_ASSERT_PTR_NON_NULL(actual, NULL);
+    PS_ASSERT_PTR_NON_NULL(sun, NULL);
+
+    psSphere *temp = psSphereAlloc();
+    psCube* sunVector = psSphereToCube(sun);
+    psCube* actualVector = psSphereToCube(actual);
+
+    // use dot product to calculate the angle of separation
+    double dotProd = (sunVector->x*actualVector->x +
+                      sunVector->y*actualVector->y + sunVector->z*actualVector->z);
+    double theta, sunMag, actMag;
+    sunMag = sqrt(sunVector->x*sunVector->x + sunVector->y*sunVector->y +
+                  sunVector->z*sunVector->z);
+    actMag = sqrt(actualVector->x*actualVector->x + actualVector->y*actualVector->y +
+                  actualVector->z*actualVector->z);
+    dotProd = dotProd / (sunMag * actMag);
+    theta = acos(dotProd);
+
+    printf(" Theta = %.13g\n", theta);
+    double r0 = PS_AU * tan(theta);
+    printf(" r0 = %.19e\n", r0);
+    double deflection = 4.0*PS_G*PS_M/(PS_C0*PS_C0*r0);
+
+    // make sure the deflection is not greater than 1.75 arcsec
+    double limit = SEC_TO_RAD(1.75);
+    if (deflection > limit) {
+        //if deflection is greater than limit, the light rays will hit the sun
+        psWarning("Invalid positions.  Light ray will not be seen on earth.\n");
+        psFree(actualVector);
+        psFree(sunVector);
+        return apparent;
+    }
+
+
+    if (apparent != NULL) {
+        psFree(apparent);
+    }
+    // bend the actual vector away from the sun vector by deflection angle.
+    theta = 0.0;
+    double phi = 0.0;
+    //    deflection = SEC_TO_RAD(deflection) * 1e6;
+    //    deflection *= M_PI * 1e-2;
+    theta = atan(r0/PS_AU) * tan(deflection);
+    //    phi = sqrt( deflection*deflection - theta*theta );
+    //    phi = deflection * cos(asin(theta/deflection));
+
+    //    phi = sqrt(theta*theta - deflection*deflection);
+    //    phi = deflection * cos(asin(theta/deflection)) * 3e-2;
+    //    phi = cos(asin(theta/deflection));
+    //    phi = asin(theta/deflection);
+
+    //    apparent->r = theta;
+    //    apparent->d = phi;
+    /*
+        actualVector->x += actualVector->x*deflection;
+        actualVector->y += actualVector->y*deflection;
+        actualVector->z += actualVector->z*deflection;
+        apparent = psCubeToSphere(actualVector);
+    */
+    theta = tan(sun->r - actual->r) * deflection;
+    phi = tan(sun->d - actual->d) * deflection;
+
+    printf(" Theta = %.13g\n", theta);
+    printf(" phi = %.13g\n", phi);
+
+    temp->r = theta;
+    temp->d = phi;
+    apparent = psSphereSetOffset(actual, temp, PS_SPHERICAL, PS_RADIAN);
+
+    psFree(actualVector);
+    psFree(sunVector);
+    psFree(temp);
+
+    return apparent;
+}
+
+psEarthPole *psEOC_PrecessionModel(const psTime *time)
+{
+    // Check for null parameter
+    PS_ASSERT_PTR_NON_NULL(time, NULL);
+    if (time->type == PS_TIME_UT1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Invalid time input.  Time cannot be of type UT1.\n");
+        return NULL;
+    }
+
+    // Convert psTime to MJD
+    double MJD = psTimeToMJD(time);
+    if (isnan(MJD)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "Time conversion to MJD failed.  Invalid input time.\n");
+        return NULL;
+    }
+
+    // Calculate number of Julian centuries since 2000
+    double t = ( MJD - MJD_2000 ) / JULIAN_CENTURY;
+    double t2 = t*t;
+    double t3 = t*t*t;
+    double t4 = t*t*t*t;
+
+    // The following formulae are from the ADD (& s5.8 of IERS Technical Note 32):
+    double F[14];
+    // Mean Anomaly of the Moon (l)
+    F[0] = DEG_TO_RAD(134.96340251) +
+           SEC_TO_RAD(1717915923.2178)*t +
+           SEC_TO_RAD(31.8792)*t2 +
+           SEC_TO_RAD(0.051635)*t3 -
+           SEC_TO_RAD(0.00024470)*t4;
+    // Mean Anomaly of the Sun (l')
+    F[1] = DEG_TO_RAD(357.52910918) +
+           SEC_TO_RAD(129596581.0481)*t -
+           SEC_TO_RAD(0.5532)*t2 +
+           SEC_TO_RAD(0.000136)*t3 -
+           SEC_TO_RAD(0.00001149)*t4;
+    // L - Omega    (L = Mean Longitude of the Moon, Omega = F4)
+    F[2] = DEG_TO_RAD(93.27209062) +
+           SEC_TO_RAD(1739527262.8478)*t -
+           SEC_TO_RAD(12.7512)*t2 -
+           SEC_TO_RAD(0.001037)*t3 +
+           SEC_TO_RAD(0.00000417)*t4;
+    // Mean Elongation of the Moon from the Sun (D)
+    F[3] = DEG_TO_RAD(297.85019547) +
+           SEC_TO_RAD(1602961601.2090)*t -
+           SEC_TO_RAD(6.3706)*t2 +
+           SEC_TO_RAD(0.006593)*t3 -
+           SEC_TO_RAD(0.00003169)*t4;
+    // Mean Longitude of the Ascending Node of the Moon (Omega)
+    F[4] = DEG_TO_RAD(125.04455501) -
+           SEC_TO_RAD(6962890.5431)*t +
+           SEC_TO_RAD(7.4722)*t2 +
+           SEC_TO_RAD(0.007702)*t3 -
+           SEC_TO_RAD(0.0000593)*t4;
+    //F5-F13 are the mean longitudes of the planets
+    F[5] = 4.402608842 + 2608.7903141574*t;
+    F[6] = 3.176146697 + 1021.3285546211*t;
+    F[7] = 1.753470314 + 628.3075849991*t;
+    F[8] = 6.203480913 + 334.0612426700*t;
+    F[9] = 0.599546497 + 52.9690962641*t;
+    F[10] = 0.874016757 + 21.3299104960*t;
+    F[11] = 5.481293872 + 7.4781598567*t;
+    F[12] = 5.311886287 + 3.8133035638*t;
+    F[13] = 0.024381750*t + 0.00000538691*t2;
+
+    // Check if EOC data loaded
+    if(! eocInitialized) {
+        eocInitialized = p_psEOCInit();
+        if(!eocInitialized) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Could not initialize EOC tables -- check data files.");
+            return NULL;
+        }
+    }
+    // calculate the polynomial portion first
+    double X = psPolynomial1DEval(xPoly,t);
+    double Y = psPolynomial1DEval(yPoly,t);
+    double S = psPolynomial1DEval(sPoly,t);
+    //Units from the table & coefficients are in micro-arcseconds so convert to radians.
+    X = SEC_TO_RAD(X * 1e-6);
+    Y = SEC_TO_RAD(Y * 1e-6);
+    S = SEC_TO_RAD(S * 1e-6);
+
+    // now calculate the non-poly portion from the tables
+    psF64* cols[17];  //Used to store all of the table information from tab5.2?.dat
+    for (int lcv = 0; lcv < 17; lcv++) {
+        cols[lcv] = ((psVector*)(xTable->data[lcv]))->data.F64;
+    }
+    //Get the number of rows in the table and loop through the non-poly contributions.
+    int numRows = ((psVector*)(xTable->data[0]))->n;
+    for (int lcv = 0; lcv < numRows; lcv++) {
+        double arg = 0.0;
+        //Get the argument- from the table and corresponding F-value.  Convert to radians.
+        for (int k = 0; k < 14; k++) {
+            arg += cols[k+3][lcv]*F[k];
+        }
+        //The order of t for each part is specified by a column in the tab.dat files.
+        double tj = pow(t,cols[0][lcv]);
+        double as = cols[1][lcv];
+        double ac = cols[2][lcv];
+        as = SEC_TO_RAD(as) * 1e-6;
+        ac = SEC_TO_RAD(ac) * 1e-6;
+        X += (as*tj*sin(arg) + ac*cos(arg)) * tj;
+    }
+    //Do the same procedure from the previous 15 lines for Y.
+    for (int lcv = 0; lcv < 17; lcv++) {
+        cols[lcv] = ((psVector*)(yTable->data[lcv]))->data.F64;
+    }
+    numRows = ((psVector*)(yTable->data[0]))->n;
+    for (int lcv = 0; lcv < numRows; lcv++) {
+        double arg = 0.0;
+        for (int k = 0; k < 14; k++) {
+            arg += cols[k+3][lcv]*F[k];
+        }
+        double tj = pow(t,cols[0][lcv]);
+        double as = cols[1][lcv];
+        double ac = cols[2][lcv];
+        as = SEC_TO_RAD(as) * 1e-6;
+        ac = SEC_TO_RAD(ac) * 1e-6;
+        Y += (as*tj*sin(arg) + ac*cos(arg)) * tj;
+    }
+    //Again for S.
+    for (int lcv = 0; lcv < 17; lcv++) {
+        cols[lcv] = ((psVector*)(sTable->data[lcv]))->data.F64;
+    }
+    numRows = ((psVector*)(sTable->data[0]))->n;
+    for (int lcv = 0; lcv < numRows; lcv++) {
+        double arg = 0.0;
+        for (int k = 0; k < 14; k++) {
+            arg += cols[k+3][lcv]*F[k];
+        }
+        double tj = pow(t,cols[0][lcv]);
+        double as = cols[1][lcv];
+        double ac = cols[2][lcv];
+        as = SEC_TO_RAD(as) * 1e-6;
+        ac = SEC_TO_RAD(ac) * 1e-6;
+        S += (as*tj*sin(arg) + ac*cos(arg)) * tj;
+    }
+
+    //the tables for S actually gives S + XY/2, so let's get the real S now. (from ADD)
+    S -= X*Y/2.0;
+
+    //Create the output psEarthPole and set the corresponding component values.
+    psEarthPole* pole = psEarthPoleAlloc();
+    pole->x = X;
+    pole->y = Y;
+    pole->s = S;
+
+    return pole;
+}
+
+psEarthPole *psEOC_PrecessionCorr(const psTime *time,
+                                  psTimeBulletin bulletin)
+{
+    // Check for null parameter or invalid bulletin
+    PS_ASSERT_PTR_NON_NULL(time,NULL);
+    PS_ASSERT_INT_WITHIN_RANGE(bulletin, PS_IERS_A, PS_IERS_B, NULL);
+    //Convert the input time to MJD.  If NAN is returned, return NULL for the function.
+    double MJD = psTimeToMJD(time);
+    if (isnan(MJD)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "Time conversion to MJD failed.  Invalid input time.\n");
+        return NULL;
+    }
+    //Allocate space for the psEarthPole output.
+    psEarthPole *out = psEarthPoleAlloc();
+
+    // Check if EOC data loaded
+    if(!eocInitialized) {
+        eocInitialized = p_psEOCInit();
+        if(!eocInitialized) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Could not initialize EOC tables -- check data files.");
+            return NULL;
+        }
+    }
+
+    //Load the data table and store in the corresponding, newly-allocated vectors.
+    psF64* cols[5];
+    for (int colNum = 0; colNum < 5; colNum++) {
+        cols[colNum] = ((psVector*)(iersTable->data[colNum]))->data.F64;
+    }
+    int numRows = ((psVector*)(iersTable->data[0]))->n;
+    psVector *X = psVectorAlloc(numRows, PS_TYPE_F64);
+    psVector *Y = psVectorAlloc(numRows, PS_TYPE_F64);
+    psVector *T = psVectorAlloc(numRows, PS_TYPE_F64);
+    if (bulletin == PS_IERS_A) {
+        for (int rowNum = 0; rowNum < numRows; rowNum++) {
+            T->data.F64[rowNum] = cols[0][rowNum];
+            X->data.F64[rowNum] = cols[1][rowNum];
+            Y->data.F64[rowNum] = cols[2][rowNum];
+        }
+    } else {
+        for (int rowNum = 0; rowNum < numRows; rowNum++) {
+            T->data.F64[rowNum] = cols[0][rowNum];
+            X->data.F64[rowNum] = cols[3][rowNum];
+            Y->data.F64[rowNum] = cols[4][rowNum];
+        }
+    }
+
+    //The following uses lagrange interpolation to calculate the corrections to X & Y.
+    double xOut = 0.0;
+    double yOut = 0.0;
+    double xTerm = 0.0;
+    double yTerm = 0.0;
+    int k = 0;
+    for (int i = 0; i < (numRows-1); i++) {
+        if (MJD >= T->data.F64[i] && MJD < T->data.F64[i+1]) {
+            k = i;
+            if (k < 2) {
+                k = 2;
+            }
+            if (k > (numRows-2)) {
+                k = numRows-2;
+            }
+            for (int m = k-1; m <= k+2; m++) {
+                xTerm = X->data.F64[m];
+                yTerm = Y->data.F64[m];
+                for (int j = k-1; j <= k+2; j++) {
+                    if ( m != j) {
+                        double term = (MJD - T->data.F64[j])/(T->data.F64[m] - T->data.F64[j]);
+                        xTerm *= term;
+                        yTerm *= term;
+                    }
+                }
+                xOut += xTerm;
+                yOut += yTerm;
+            }
+            i = numRows-1;
+        }
+    }
+    //Convert the values from milli-arcsecond to radian.
+    out->x = SEC_TO_RAD(xOut) * 1e-3;
+    out->y = SEC_TO_RAD(yOut) * 1e-3;
+    psFree(X);
+    psFree(Y);
+    psFree(T);
+
+    return out;
+}
+
+static psSphereRot *rotMatrix_To_Quat(double A[3][3])
+{
+    int i;
+    psSphereRot *new = psSphereRotAlloc(0.0, 0.0, 0.0);
+    new->q3 = 0.0;
+
+    //Convert rotation matrix to quaternions.  Formula directly from ADD.
+    double diag_sum[3];
+    int maxi;
+    double recip;
+    diag_sum[0] = 1.0 + A[0][0] - A[1][1] - A[2][2];
+    diag_sum[1] = 1.0 - A[0][0] + A[1][1] - A[2][2];
+    diag_sum[2] = 1.0 - A[0][0] - A[1][1] + A[2][2];
+    diag_sum[3] = 1.0 + A[0][0] + A[1][1] + A[2][2];
+
+    maxi = 0;
+    for (i = 1; i < 4; ++i) {
+        if (diag_sum[i] > diag_sum[maxi]) {
+            maxi = i;
+        }
+    }
+
+    double p = 0.5 * sqrt(diag_sum[maxi]);
+    recip = 1.0 / (4.0 * p);
+
+    if (maxi == 0) {
+        new->q0 = p;
+        new->q1 = recip * (A[0][1] + A[1][0]);
+        new->q2 = recip * (A[2][0] + A[0][2]);
+        new->q3 = recip * (A[1][2] - A[2][1]);
+    } else if (maxi == 1) {
+        new->q0 = recip * (A[0][1] + A[1][0]);
+        new->q1 = p;
+        new->q2 = recip * (A[1][2] + A[2][1]);
+        new->q3 = recip * (A[2][0] - A[0][2]);
+    } else if (maxi == 2) {
+        new->q0 = recip * (A[2][0] + A[0][2]);
+        new->q1 = recip * (A[1][2] + A[2][1]);
+        new->q2 = p;
+        new->q3 = recip * (A[0][1] - A[1][0]);
+    } else if (maxi == 3) {
+        new->q0 = recip * (A[1][2] - A[2][1]);
+        new->q1 = recip * (A[2][0] - A[0][2]);
+        new->q2 = recip * (A[0][1] - A[1][0]);
+        new->q3 = p;
+    }
+    return new;
+}
+
+psSphereRot* psSphereRot_CEOtoGCRS(const psEarthPole *pole)
+{
+    // Check for null parameter
+    PS_ASSERT_PTR_NON_NULL(pole,NULL);
+    double A[3][3];
+    psSphereRot *out = NULL;
+
+    //Setup the rotation matrix and scalar value, a, as outlined by the ADD
+    double a =  1.0 / (1.0 + sqrt(1.0 - (pole->x*pole->x + pole->y*pole->y) ) );
+    A[0][0] = (1.0 - a*pole->x*pole->x)*cos(pole->s) - a*pole->x*pole->y*sin(pole->s);
+    A[1][0] = -a*pole->x*pole->y*cos(pole->s) + (1.0 - a*pole->y*pole->y)*sin(pole->s);
+    A[2][0] = pole->x*cos(pole->s) + pole->y*sin(pole->s);
+    A[0][1] = -(1.0 - a*pole->x*pole->x)*sin(pole->s) - a*pole->x*pole->y*cos(pole->s);
+    A[1][1] = a*pole->x*pole->y*sin(pole->s) + (1.0 - a*pole->y*pole->y)*cos(pole->s);
+    A[2][1] = -pole->x*sin(pole->s) + pole->y*cos(pole->s);
+    A[0][2] = -pole->x;
+    A[1][2] = -pole->y;
+    A[2][2] = 1.0 - a*(pole->x*pole->x + pole->y*pole->y);
+
+    //Convert the rotation matrix to a psSphereRot (quaternions)
+    out = rotMatrix_To_Quat(A);
+
+    return out;
+}
+
+psSphereRot* psSphereRot_TEOtoCEO(const psTime *time,
+                                  psEarthPole *tidalCorr)
+{
+    // Check for null parameter
+    PS_ASSERT_PTR_NON_NULL(time,NULL);
+    //Create a copy of the input time that can be manipulated/changed (input time is const).
+    psTime *in = psTimeCopy(time);
+    if (in->type != PS_TIME_UT1) {
+        in = psTimeConvert(in, PS_TIME_UT1);
+    }
+    //Check if tidal corrections should be included.
+    //If so, make sure values are positive and in the correct range.
+    if (tidalCorr != NULL && fabs(tidalCorr->s) > FLT_EPSILON) {
+        int nsec = in->nsec + (int)(tidalCorr->s * 1e9);
+        if (nsec > 1e9) {
+            nsec += -1e9;
+            in->sec += 1;
+        }
+        if (nsec < 0) {
+            in->sec += -1;
+            in->nsec = (int)(1e9) + nsec;
+        } else {
+            in->nsec = nsec;
+        }
+    }
+    //Calculate the Julian Date from the input time in UT1 format.
+    double T = psTimeToJD(in);
+    if (isnan(T)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "Time conversion to JD failed.  Invalid input time.\n");
+        return NULL;
+    }
+    T += -2451545.0;
+    //Formula for theta comes directly from the ADD.  Create output psSphereRot from theta.
+    double theta = 2.0 * M_PI * (0.7790572732640 + 1.00273781191135448 * T);
+    psSphereRot *out = psSphereRotAlloc(theta, 0.0, 0.0);
+
+    psFree(in);
+    return out;
+}
+
+psEarthPole* psEOC_GetPolarMotion(const psTime *time,
+                                  psTimeBulletin bulletin)
+{
+    PS_ASSERT_PTR_NON_NULL(time, NULL);
+    PS_ASSERT_INT_WITHIN_RANGE(bulletin, PS_IERS_A, PS_IERS_B, NULL);
+
+    psEarthPole *out = psEarthPoleAlloc();
+    out->x = 0.0;
+    out->y = 0.0;
+    out->s = 0.0;
+
+    double MJD = psTimeToMJD(time);
+    if ( isnan(MJD) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "Time conversion to MJD failed.  Invalid input time.\n");
+        return NULL;
+    }
+
+    // Check if EOC data loaded
+    if(! eocInitialized) {
+        eocInitialized = p_psEOCInit();
+        if(!eocInitialized) {
+            // XXX: Move error message.
+            psError(PS_ERR_UNKNOWN, false,
+                    "Could not initialize EOC tables -- check data files.");
+            return NULL;
+        }
+    }
+
+    psF64* cols[7];
+    for (int colNum = 0; colNum < 7; colNum++) {
+        cols[colNum] = ((psVector*)(finalsTable->data[colNum]))->data.F64;
+    }
+    int numRows = ((psVector*)(finalsTable->data[0]))->n;
+    psVector *X = psVectorAlloc(numRows, PS_TYPE_F64);
+    psVector *Y = psVectorAlloc(numRows, PS_TYPE_F64);
+    //    psVector *S = psVectorAlloc(numRows, PS_TYPE_F64);
+    psVector *T = psVectorAlloc(numRows, PS_TYPE_F64);
+    if (bulletin == PS_IERS_A) {
+        for (int rowNum = 0; rowNum < numRows; rowNum++) {
+            T->data.F64[rowNum] = cols[0][rowNum];
+            X->data.F64[rowNum] = cols[1][rowNum];
+            Y->data.F64[rowNum] = cols[2][rowNum];
+            //            S->data.F64[rowNum] = cols[3][rowNum];
+        }
+    } else {
+        for (int rowNum = 0; rowNum < numRows; rowNum++) {
+            T->data.F64[rowNum] = cols[0][rowNum];
+            X->data.F64[rowNum] = cols[4][rowNum];
+            Y->data.F64[rowNum] = cols[5][rowNum];
+            //            S->data.F64[rowNum] = cols[6][rowNum];
+        }
+    }
+
+    double xOut = 0.0;
+    double yOut = 0.0;
+    //    double sOut = 0.0;
+    double xTerm = 0.0;
+    double yTerm = 0.0;
+    //    double sTerm = 0.0;
+    int k = 0;
+    for (int i = 0; i < (numRows-1); i++) {
+        if (MJD >= T->data.F64[i] && MJD < T->data.F64[i+1]) {
+            k = i;
+            if (k < 2) {
+                k = 2;
+            }
+            //            if (k > (numRows-2)) {
+            //                k = numRows-2;
+            //            }
+            for (int m = k-1; m <= k+2; m++) {
+                xTerm = X->data.F64[m];
+                yTerm = Y->data.F64[m];
+                //                sTerm = S->data.F64[m];
+                for (int j = k-1; j <= k+2; j++) {
+                    if ( m != j) {
+                        double term = (MJD - T->data.F64[j])/(T->data.F64[m] - T->data.F64[j]);
+                        xTerm *= term;
+                        yTerm *= term;
+                        //                        sTerm *= term;
+                    }
+                }
+                xOut += xTerm;
+                yOut += yTerm;
+                //                sOut += sTerm;
+            }
+            i = numRows-1;
+        }
+    }
+    out->x = SEC_TO_RAD(xOut);
+    out->y = SEC_TO_RAD(yOut);
+    //    psEarthPole *polarTideCorr = psEOC_PolarTideCorr(time);
+    //    out->x += polarTideCorr->x;
+    //    out->y += polarTideCorr->y;
+    //    psFree(polarTideCorr);
+
+    //    out->s = SEC_TO_RAD(sOut);
+
+
+    /*
+        for (int rowNum = 0; rowNum < numRows; rowNum++) {
+            if ( (MJD - cols[0][rowNum]) < 1.0 ) {
+                if (bulletin == PS_IERS_A) {
+                    out->x = cols[1][rowNum];
+                    out->y = cols[2][rowNum];
+                    out->s = cols[3][rowNum];
+                    out->x = SEC_TO_RAD(out->x);
+                    out->y = SEC_TO_RAD(out->y);
+                    out->s = SEC_TO_RAD(out->s);
+                    rowNum = numRows;
+                } else {
+                    out->x = cols[4][rowNum];
+                    out->y = cols[5][rowNum];
+                    out->s = cols[6][rowNum];
+                    out->x = SEC_TO_RAD(out->x);
+                    out->y = SEC_TO_RAD(out->y);
+                    out->s = SEC_TO_RAD(out->s);
+                    rowNum = numRows;
+                }
+            }
+        }
+    */
+    psFree(X);
+    psFree(Y);
+    //    psFree(S);
+    psFree(T);
+    return out;
+}
+
+static double DMOD(double x, double y)
+{
+    //Internal function for calculating the remainder of a double quotient.
+    //used often in the algorithm for psEOC_PolarTideCorr which is the Ray model of
+    //Simon et. al. from its fortran implementation.
+    double value = x - y * trunc(x/y);
+    return value;
+}
+
+psEarthPole* psEOC_PolarTideCorr(const psTime *time)
+{
+    // Check for null parameter
+    PS_ASSERT_PTR_NON_NULL(time, NULL);
+    // Convert psTime to MJD
+    double MJD = psTimeToMJD(time);
+    if (isnan(MJD)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "Time conversion to MJD failed.  Invalid input time.\n");
+        return NULL;
+    }
+    psEarthPole *out = psEarthPoleAlloc();
+
+    //Formula comes from fortran reference of the Ray model of Simon et. al.
+    double T, L, LPRIME, CAPF, CAPD, OMEGA, THETA, CORX, CORY, CORZ;
+    double ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8;
+    double T2, T3, T4;
+    // Calculate number of Julian centuries since 2000
+    T = (MJD - 51544.5) / 36525.0;
+    T2 = T*T;
+    T3 = T*T*T;
+    T4 = T*T*T*T;
+    L = -0.0002447 * T4 + 0.051635 * T3 + 31.8792 * T2 + 1717915923.2178 * T + 485868.249036;
+    L = DMOD(L, 1296000.0);
+    LPRIME = -0.00001149 * T4 - 0.000136 * T3 - 0.5532 * T2 + 129596581.0481 * T + 1287104.79305;
+    LPRIME = DMOD(LPRIME, 1296000.0);
+    CAPF = 0.00000417 * T4 - 0.001037 * T3 - 12.7512 * T2 + 1739527262.8478 * T + 335779.526232;
+    CAPF = DMOD(CAPF, 1296000.0);
+    CAPD = -0.00003169 * T4 + 0.006593 * T3 - 6.3706 * T2 + 1602961601.209 * T + 1072260.70369;
+    CAPD = DMOD(CAPD, 1296000.0);
+    OMEGA = -0.00005939 * T4 + 0.007702 * T3 + 7.4722 * T2 - 6962890.2665 * T + 450160.398036;
+    OMEGA = DMOD(OMEGA, 1296000.0);
+    THETA = (67310.54841 + (876600.0 * 3600.0 + 8640184.812866) * T + 0.093104 * T2 -
+             6.2e-6 * T3) * 15.0 + 648000.0;
+    ARG7 = DMOD((-L - 2.0 * CAPF - 2.0 * OMEGA + THETA) * M_PI / 648000.0, 2.0 * M_PI)
+           - M_PI / 2.0;
+    ARG1 = DMOD((-2.0 * CAPF - 2.0 * OMEGA + THETA) * M_PI / 648000.0, 2.0 * M_PI) - M_PI / 2.0;
+    ARG2 = DMOD((-2.0 * CAPF + 2.0 * CAPD - 2.0 * OMEGA + THETA) * M_PI / 648000.0, 2.0 * M_PI)
+           - M_PI / 2.0;
+    ARG3 = DMOD(THETA * M_PI / 648000.0, 2.0 * M_PI) - M_PI / 2.0;
+    ARG4 = DMOD((-L - 2.0 * CAPF - 2.0 * OMEGA + 2.0 * THETA) * M_PI / 648000.0, 2.0 * M_PI);
+    ARG5 = DMOD((-2.0 * CAPF - 2.0 * OMEGA + 2.0 * THETA) * M_PI / 648000.0, 2.0 * M_PI);
+    ARG6 = DMOD((-2.0 * CAPF + 2.0 * CAPD - 2.0 * OMEGA + 2.0 * THETA) * M_PI / 648000.0,
+                2.0 * M_PI);
+    ARG8 = DMOD((2.0 * THETA) * M_PI / 648000.0, 2.0 * M_PI);
+    CORX = -0.026 * sin(ARG7) + 0.006 * cos(ARG7)
+           -0.133 * sin(ARG1) + 0.049 * cos(ARG1)
+           -0.050 * sin(ARG2) + 0.025 * cos(ARG2)
+           -0.152 * sin(ARG3) + 0.078 * cos(ARG3)
+           -0.057 * sin(ARG4) - 0.013 * cos(ARG4)
+           -0.330 * sin(ARG5) - 0.028 * cos(ARG5)
+           -0.145 * sin(ARG6) + 0.064 * cos(ARG6)
+           -0.036 * sin(ARG8) + 0.017 * cos(ARG8);
+    CORY = -0.006 * sin(ARG7) - 0.026 * cos(ARG7)
+           -0.049 * sin(ARG1) - 0.133 * cos(ARG1)
+           -0.025 * sin(ARG2) - 0.050 * cos(ARG2)
+           -0.078 * sin(ARG3) - 0.152 * cos(ARG3)
+           +0.011 * sin(ARG4) + 0.033 * cos(ARG4)
+           +0.037 * sin(ARG5) + 0.196 * cos(ARG5)
+           +0.059 * sin(ARG6) + 0.087 * cos(ARG6)
+           +0.018 * sin(ARG8) + 0.022 * cos(ARG8);
+    CORZ =  0.0245 * sin(ARG7) + 0.0503 * cos(ARG7)
+            +0.1210 * sin(ARG1) + 0.1605 * cos(ARG1)
+            +0.0286 * sin(ARG2) + 0.0516 * cos(ARG2)
+            +0.0864 * sin(ARG3) + 0.1771 * cos(ARG3)
+            -0.0380 * sin(ARG4) - 0.0154 * cos(ARG4)
+            -0.1617 * sin(ARG5) - 0.0720 * cos(ARG5)
+            -0.0759 * sin(ARG6) - 0.0004 * cos(ARG6)
+            -0.0196 * sin(ARG8) - 0.0038 * cos(ARG8);
+    CORX = CORX * 1.0e-3;
+    CORY = CORY * 1.0e-3;
+    CORZ = CORZ * 0.1e-3;
+
+    CORX = SEC_TO_RAD(CORX);
+    CORY = SEC_TO_RAD(CORY);
+
+    out->x = CORX;
+    out->y = CORY;
+    out->s = CORZ;
+
+    return out;
+}
+
+psEarthPole* psEOC_NutationCorr(psTime *time)
+{
+    // Check for null parameter
+    PS_ASSERT_PTR_NON_NULL(time, NULL);
+    // Convert psTime to MJD
+    double MJD = psTimeToMJD(time);
+    //    printf("\nMJD check = %.13g\n", MJD);
+    if (isnan(MJD)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "Time conversion to MJD failed.  Invalid input time.\n");
+        return NULL;
+    }
+
+    // Calculate number of Julian centuries since 2000
+    double t = ( MJD - MJD_2000 ) / JULIAN_CENTURY;
+    double t2 = t*t;
+    double t3 = t*t*t;
+    double t4 = t*t*t*t;
+
+    // The following formulae are from the ADD (& s5.8 of IERS Technical Note 32):
+    double F[5];
+    // Mean Anomaly of the Moon
+    F[0] = DEG_TO_RAD(134.96340251) +
+           SEC_TO_RAD(1717915923.2178)*t +
+           SEC_TO_RAD(31.8792)*t2 +
+           SEC_TO_RAD(0.051635)*t3 -
+           SEC_TO_RAD(0.00024470)*t4;
+
+    // Mean Anomaly of the Sun
+    F[1] = DEG_TO_RAD(357.52910918) +
+           SEC_TO_RAD(129596581.0481)*t -
+           SEC_TO_RAD(0.5532)*t2 +
+           SEC_TO_RAD(0.000136)*t3 -
+           SEC_TO_RAD(0.00001149)*t4;
+
+    // L â Omega    (L = Mean Longitude of the Moon, Omega = F4)
+    F[2] = DEG_TO_RAD(93.27209062) +
+           SEC_TO_RAD(1739527262.8478)*t -
+           SEC_TO_RAD(12.7512)*t2 -
+           SEC_TO_RAD(0.001037)*t3 +
+           SEC_TO_RAD(0.00000417)*t4;
+
+    // Mean Elongation of the Moon from the Sun
+    F[3] = DEG_TO_RAD(297.85019547) +
+           SEC_TO_RAD(1602961601.2090)*t -
+           SEC_TO_RAD(6.3706)*t2 +
+           SEC_TO_RAD(0.006593)*t3 -
+           SEC_TO_RAD(0.00003169)*t4;
+
+    // Mean Longitude of the Ascending Node of the Moon
+    F[4] = DEG_TO_RAD(125.04455501) -
+           SEC_TO_RAD(6962890.5431)*t +
+           SEC_TO_RAD(7.4722)*t2 +
+           SEC_TO_RAD(0.007702)*t3 -
+           SEC_TO_RAD(0.00005939)*t4;
+
+    //argument values taken from table 5.1 in IERS techical note No.32
+    //http://maia.usno.navy.mil/conv2000/chapter5/tn32_c5.pdf, p38
+    //Units are in micro-arcseconds here and must be converted to radians before using
+    double w_l[10] = {SEC_TO_RAD(-1.0),
+                      SEC_TO_RAD(-1.0),
+                      SEC_TO_RAD(1.0),
+                      0.0,
+                      0.0,
+                      SEC_TO_RAD(-1.0),
+                      0.0,
+                      0.0,
+                      0.0,
+                      SEC_TO_RAD(1.0)};
+    double w_l_p[10] = {0.0,
+                        0.0,
+                        0.0,
+                        0.0,
+                        0.0,
+                        0.0,
+                        0.0,
+                        0.0,
+                        0.0,
+                        0.0};
+    double w_F[10] = {SEC_TO_RAD(-2.0),
+                      SEC_TO_RAD(-2.0),
+                      SEC_TO_RAD(-2.0),
+                      SEC_TO_RAD(-2.0),
+                      SEC_TO_RAD(-2.0),
+                      0.0,
+                      SEC_TO_RAD(-2.0),
+                      0.0,
+                      0.0,
+                      0.0};
+    double w_D[10] = {0.0,
+                      0.0,
+                      SEC_TO_RAD(-2.0),
+                      0.0,
+                      0.0,
+                      0.0,
+                      SEC_TO_RAD(2.0),
+                      0.0,
+                      0.0,
+                      0.0};
+    double w_Omega[10] = {SEC_TO_RAD(-1.0),
+                          SEC_TO_RAD(-2.0),
+                          SEC_TO_RAD(-2.0),
+                          SEC_TO_RAD(-1.0),
+                          SEC_TO_RAD(-2.0),
+                          0.0,
+                          SEC_TO_RAD(-2.0),
+                          0.0,
+                          SEC_TO_RAD(-1.0),
+                          0.0};
+    double xp_sin[10] = {SEC_TO_RAD(-0.44),
+                         SEC_TO_RAD(-2.31),
+                         SEC_TO_RAD(-0.44),
+                         SEC_TO_RAD(-2.14),
+                         SEC_TO_RAD(-11.36),
+                         SEC_TO_RAD(0.84),
+                         SEC_TO_RAD(-4.76),
+                         SEC_TO_RAD(14.27),
+                         SEC_TO_RAD(1.93),
+                         SEC_TO_RAD(0.76)};
+    double xp_cos[10] = {SEC_TO_RAD(0.25),
+                         SEC_TO_RAD(1.32),
+                         SEC_TO_RAD(0.25),
+                         SEC_TO_RAD(1.23),
+                         SEC_TO_RAD(6.52),
+                         SEC_TO_RAD(-0.48),
+                         SEC_TO_RAD(2.73),
+                         SEC_TO_RAD(-8.19),
+                         SEC_TO_RAD(-1.11),
+                         SEC_TO_RAD(-0.43)};
+    double yp_sin[10] = {SEC_TO_RAD(-0.25),
+                         SEC_TO_RAD(-1.32),
+                         SEC_TO_RAD(-0.25),
+                         SEC_TO_RAD(-1.23),
+                         SEC_TO_RAD(-6.52),
+                         SEC_TO_RAD(0.48),
+                         SEC_TO_RAD(-2.73),
+                         SEC_TO_RAD(8.19),
+                         SEC_TO_RAD(1.11),
+                         SEC_TO_RAD(0.43)};
+    double yp_cos[10] = {SEC_TO_RAD(-0.44),
+                         SEC_TO_RAD(-2.31),
+                         SEC_TO_RAD(-0.44),
+                         SEC_TO_RAD(-2.14),
+                         SEC_TO_RAD(-11.36),
+                         SEC_TO_RAD(0.84),
+                         SEC_TO_RAD(-4.76),
+                         SEC_TO_RAD(14.27),
+                         SEC_TO_RAD(1.93),
+                         SEC_TO_RAD(0.76)};
+
+    double X = 0.0;
+    double Y = 0.0;
+
+    //Implementation adapted from PM_GRAVI in interp.f from hpiers.obspm.fr/eop-pc/models/interp.f
+    double arg[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
+    arg[0] = (67310.54841 +
+              (876600.0*3600.0 + 8640184.812866)*t
+              + 0.093104*t2 - 6.2e-6*t3) * 15.0 + 648000.0;
+    arg[0] = DMOD(arg[1], 1296000.0);
+    arg[0] = SEC_TO_RAD(arg[0]);
+    arg[1] = RAD_TO_SEC(F[0]);
+    arg[1] = DMOD(arg[1], 1296000.0);
+    arg[1] = SEC_TO_RAD(arg[1]);
+    arg[2] = RAD_TO_SEC(F[1]);
+    arg[2] = DMOD(arg[2], 1296000.0);
+    arg[2] = SEC_TO_RAD(arg[2]);
+    arg[3] = RAD_TO_SEC(F[2]);
+    arg[3] = DMOD(arg[3], 1296000.0);
+    arg[3] = SEC_TO_RAD(arg[3]);
+    arg[4] = RAD_TO_SEC(F[3]);
+    arg[4] = DMOD(arg[4], 1296000.0);
+    arg[4] = SEC_TO_RAD(arg[4]);
+    arg[5] = RAD_TO_SEC(F[4]);
+    arg[5] = DMOD(arg[5], 1296000.0);
+    arg[5] = SEC_TO_RAD(arg[5]);
+
+    for (int j = 0; j < 10; j++) {
+        double ag = 0.0;
+        ag = SEC_TO_RAD(1.0)*arg[0] + w_l[j]*arg[1] + w_l_p[j]*arg[2] + w_F[j]*arg[3]
+             + w_D[j]*arg[4] + w_Omega[j]*arg[5];
+        ag = RAD_TO_SEC(ag);
+        ag = DMOD(ag, 2.0*M_PI);
+        X += xp_sin[j] * SEC_TO_RAD(sin(ag)) + xp_cos[j] * SEC_TO_RAD(cos(ag));
+        Y += yp_sin[j] * SEC_TO_RAD(sin(ag)) + yp_cos[j] * SEC_TO_RAD(cos(ag));
+    }
+
+    psEarthPole *pole = psEarthPoleAlloc();
+    pole->x = X;
+    pole->y = Y;
+    //The value of s is simply: s = -4.7e-5 * t as specified by the ADD and IERS 32.
+    pole->s = -SEC_TO_RAD(4.7e-5) * t;
+
+    return pole;
+}
+
+psSphereRot* psSphereRot_ITRStoTEO(const psEarthPole* motion)
+{
+    // Check for null parameter
+    PS_ASSERT_PTR_NON_NULL(motion,NULL);
+    double A[3][3];
+    psSphereRot *out = NULL;
+
+    double x,y,s;
+    x = motion->x;
+    y = motion->y;
+    s = motion->s;
+    s = -s;
+
+    //Setup Rotation matrix.  Rotation is constructed by rotation about the X-axis by y,
+    // about the Y-axis by x, and about the Z-axis by s' (where s' = -s).
+    A[0][0] = cos(x)*cos(s);
+    A[1][0] = cos(x)*sin(s);
+    A[2][0] = -sin(x);
+    A[0][1] = sin(x)*sin(y)*cos(s) - cos(y)*sin(s);
+    A[1][1] = sin(x)*sin(y)*sin(s) + cos(y)*cos(s);
+    A[2][1] = cos(x)*sin(y);
+    A[0][2] = sin(x)*cos(y)*cos(s) + sin(y)*sin(s);
+    A[1][2] = sin(x)*cos(y)*sin(s) - sin(y)*cos(s);
+    A[2][2] = cos(x)*cos(y);
+
+    //Convert rotation matrix to quaternions
+    out = rotMatrix_To_Quat(A);
+
+    return out;
+}
+
+psSphereRot *psSpherePrecess(const psTime *fromTime,
+                             const psTime *toTime,
+                             psPrecessMethod mode)
+{
+    // Check input for NULL pointers
+    if (fromTime == NULL && toTime == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "Invalid time inputs.  fromTime & toTime cannot both be NULL.\n");
+        return NULL;
+    }
+    PS_ASSERT_INT_WITHIN_RANGE(mode, PS_PRECESS_ROUGH, PS_PRECESS_IAU2000A, NULL);
+    psF64 fromMJD, toMJD;
+    // Calculate Julian centuries
+    //If either input time is NULL, assume it to be J2000 -> from SDRS as of rev 18
+    psTime *from = NULL;
+    psTime *to = NULL;
+    if (fromTime == NULL) {
+        fromMJD = MJD_2000;
+        from = psTimeFromMJD(fromMJD);
+    } else {
+        fromMJD = psTimeToMJD(fromTime);
+        from = psTimeCopy(fromTime);
+    }
+    if (toTime == NULL) {
+        toMJD = MJD_2000;
+        to = psTimeFromMJD(toMJD);
+    } else {
+        toMJD = psTimeToMJD(toTime);
+        to = psTimeCopy(toTime);
+    }
+    if (fromMJD > toMJD) {
+        psWarning("From time is later than to time in psSpherePrecess.\n");
+    }
+
+    if (mode == PS_PRECESS_ROUGH) {
+        //For PS_PRECESS_ROUGH, no time/earthpole corrections are used.  This is the
+        //lowest level of detail mode.
+        psF64 T = (toMJD - fromMJD) / JULIAN_CENTURY;
+
+        // Calculate conversion constants
+        //    psF64 alphaP = DEG_TO_RAD(90.0) - ((DEG_TO_RAD(0.6406161) * T) +
+        psF64 alphaP = DEG_TO_RAD(180.0) + ((DEG_TO_RAD(0.6406161) * T) +
+                                            (DEG_TO_RAD(0.0000839) * T * T) +
+                                            (DEG_TO_RAD(0.000005) * T * T * T));
+
+        psF64 deltaP = (DEG_TO_RAD(0.5567530) * T) -
+                       (DEG_TO_RAD(0.0001185) * T * T) -
+                       (DEG_TO_RAD(0.0000116) * T * T * T);
+
+        //    psF64 phiP = DEG_TO_RAD(90.0) + ((DEG_TO_RAD(0.6406161) * T) +
+        psF64 phiP = DEG_TO_RAD(180.0) + ((DEG_TO_RAD(0.6406161) * T) +
+                                          (DEG_TO_RAD(0.0003041) * T * T) +
+                                          (DEG_TO_RAD(0.0000051) * T * T * T));
+
+        // Create transform with proper constants
+        psSphereRot* tmpST = psSphereRotAlloc(alphaP, deltaP, phiP);
+        psFree(from);
+        psFree(to);
+        return tmpST;
+    } else if (mode == PS_PRECESS_IAU2000A) {
+        //For IAU2000A mode, run psEOC_PrecessionModel and then psSphereRot_CEOtoGCRS for
+        //each time.  Then difference the resulting rotations by adding the inverse
+        //rotation corresponding to fromTime to the toTime rotation.
+
+        //Calculate the earthpoles and quaternions corresponding to each time (from, to).
+        //Combine the quaternions to produce the output psSphereRot.
+        psEarthPole *fromEP = psEOC_PrecessionModel(from);
+        psSphereRot *fromRot = psSphereRot_CEOtoGCRS(fromEP);
+        psEarthPole *toEP = psEOC_PrecessionModel(to);
+        psSphereRot *toRot = psSphereRot_CEOtoGCRS(toEP);
+        psSphereRot *fromConj = psSphereRotConjugate(NULL, fromRot);
+        psSphereRot *out = psSphereRotCombine(NULL, toRot, fromConj);
+        psFree(from);
+        psFree(to);
+        psFree(fromEP);
+        psFree(fromRot);
+        psFree(toEP);
+        psFree(toRot);
+        psFree(fromConj);
+        return out;
+    } else if (mode == PS_PRECESS_COMPLETE_A) {
+        //For PS_PRECESS_COMPLETE_A the same procedure as IAU2000A is used but with
+        //additional earthpole corrections from psEOC_PrecessionCorr.  The corrections
+        //for COMPLETE_A come from the IERS Bulletin A.
+
+        //Calculate the earthpoles and quaternions corresponding to each time (from, to).
+        //Add in the precession corrections from IERS bulletin A.
+        //Combine the quaternions to produce the output psSphereRot.
+        psEarthPole *fromEP = psEOC_PrecessionModel(from);
+        psEarthPole *fromCorr = psEOC_PrecessionCorr(from, PS_IERS_A);
+        fromEP->x += fromCorr->x;
+        fromEP->y += fromCorr->y;
+        psSphereRot *fromRot = psSphereRot_CEOtoGCRS(fromEP);
+        psEarthPole *toEP = psEOC_PrecessionModel(to);
+        psEarthPole *toCorr = psEOC_PrecessionCorr(to, PS_IERS_A);
+        toEP->x += toCorr->x;
+        toEP->y += toCorr->y;
+        psSphereRot *toRot = psSphereRot_CEOtoGCRS(toEP);
+        psSphereRot *fromConj = psSphereRotConjugate(NULL, fromRot);
+        psSphereRot *out = psSphereRotCombine(NULL, toRot, fromConj);
+        psFree(from);
+        psFree(to);
+        psFree(fromEP);
+        psFree(fromCorr);
+        psFree(fromRot);
+        psFree(toEP);
+        psFree(toCorr);
+        psFree(toRot);
+        psFree(fromConj);
+        return out;
+    } else {  //mode == PS_PRECESS_COMPLETE_B
+        //For PS_PRECESS_COMPLETE_B the same procedure as IAU2000A is used but with
+        //additional earthpole corrections from psEOC_PrecessionCorr.  The corrections
+        //for COMPLETE_B come from the IERS Bulletin B.
+
+        //Calculate the earthpoles and quaternions corresponding to each time (from, to).
+        //Add in the precession corrections from IERS bulletin B.
+        //Combine the quaternions to produce the output psSphereRot.
+        psEarthPole *fromEP = psEOC_PrecessionModel(from);
+        psEarthPole *fromCorr = psEOC_PrecessionCorr(from, PS_IERS_B);
+        fromEP->x += fromCorr->x;
+        fromEP->y += fromCorr->y;
+        psSphereRot *fromRot = psSphereRot_CEOtoGCRS(fromEP);
+        psEarthPole *toEP = psEOC_PrecessionModel(to);
+        psEarthPole *toCorr = psEOC_PrecessionCorr(to, PS_IERS_B);
+        toEP->x += toCorr->x;
+        toEP->y += toCorr->y;
+        psSphereRot *toRot = psSphereRot_CEOtoGCRS(toEP);
+        psSphereRot *fromConj = psSphereRotConjugate(NULL, fromRot);
+        psSphereRot *out = psSphereRotCombine(NULL, toRot, fromConj);
+        psFree(from);
+        psFree(to);
+        psFree(fromEP);
+        psFree(fromCorr);
+        psFree(fromRot);
+        psFree(toEP);
+        psFree(toCorr);
+        psFree(toRot);
+        psFree(fromConj);
+        return out;
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psEarthOrientation.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psEarthOrientation.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psEarthOrientation.h	(revision 22158)
@@ -0,0 +1,201 @@
+/** @file  psEarthOrientation.h
+*
+*  @brief earth orientation calculations and transformation
+*
+*  @author Josh Hoblitt, IfA
+*  @author Ed Pier, IfA
+*  @author Eugene Magnier, IfA
+*  @author Robert Daniel DeSonia, MHPCC
+*
+*  @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-08-09 01:40:07 $
+*
+*  Copyright 2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifndef PS_EARTH_ORIENTATION
+#define PS_EARTH_ORIENTATION
+
+/// @addtogroup Astro Astronomy
+/// @{
+
+#include "psCoord.h"
+#include "psTime.h"
+#include "psSphereOps.h"
+
+/** Structure for respresenting the Earth's pole at any moment or determine velocity
+ *  at the pole.  This structure carries the polar coordinate information.       */
+typedef struct
+{
+    double x;                          ///< X component of the earth's pole
+    double y;                          ///< Y component of the earth's pole
+    double s;                          ///< s component of the earth's pole
+}
+psEarthPole;
+
+/** Method for spherical precession used to specify the level of detail used in
+ *  calculation.
+ *
+ *  @see psSpherePrecess
+ *
+ */
+typedef enum {
+    PS_PRECESS_ROUGH,                  ///< roughest, lowest level of detail
+    PS_PRECESS_COMPLETE_A,             ///< complete level of detail using IERS A
+    PS_PRECESS_COMPLETE_B,             ///< complete level of detail using IERS B
+    PS_PRECESS_IAU2000A                ///< highest level of detail
+}
+psPrecessMethod;
+
+/** Initialize EOC.
+ *
+ *  Parses IERS table data and creates the polynomials used by certain EOC functions.
+ *
+ *  @return bool:       True if successful, otherwise false.
+ */
+bool p_psEOCInit(void);
+
+/** Finalize EOC after using functions that make calls to eocInit for time table data
+ *
+ *  @return bool:       True if successful, otherwise false.
+ */
+bool p_psEOCFinalize(void);
+
+/** Allocates a new psEarthPole structure.  */
+psEarthPole *psEarthPoleAlloc(void) PS_ATTR_MALLOC;
+
+/** Calculates the apparent position of a star, given its actual position and the
+ *  velocity vector of the observer.
+ *
+ *  The actual and apparent positions are represented as psSphere entries, as is the
+ *  direction of motion.  The speed in that direction is given in units of the speed
+ *  of light.  If the value of apparent is NULL, a new psSphere is allocated, otherwise
+ *  the point to apparent is used for the result.
+ *
+ *  @return psSphere*:      the actual position of a star.
+ */
+psSphere *psAberration(
+    psSphere *apparent,                ///< apparent position of star
+    const psSphere *actual,            ///< actual position of star
+    const psSphere *direction,         ///< direction of motion of observer
+    double speed                       ///< speed of motion of observer
+);
+
+/** Calculates the apparent position of a star, given its actual position and the
+ *  position of the sun.
+ *
+ *  The actual and apparent positions are represented as psSphere entries, as is
+ *  position of the sun.  If the value of apparent is NULL, a new psSphere is allocated,
+ *  otherwise the point to apparent is used for the result.
+ *
+ *  @return psSphere*:      the apparent position of a star.
+ */
+psSphere *psGravityDeflection(
+    psSphere *apparent,                ///< apparent position of star
+    psSphere *actual,                  ///< actual position of star
+    psSphere *sunPos                      ///< position of the sun
+);
+
+/** Calculates the components of the rotation between the CEO and GCRS frames, X, Y,
+ *  and s, using the IAU2000A precession & nutation model.
+ *
+ *  The input time may be represented in any format other than UT1.  This routine must
+ *  give results identical to the IERS XYS2000A subroutine.
+ *
+ *  @return psEarthPole*:       the calculated components of the rotation.
+ */
+psEarthPole *psEOC_PrecessionModel(
+    const psTime *time                 ///< specified time
+);
+
+/** Provides interpolated corrections to the X and Y components of the polar
+ *  coordinates from the tables provided by the IERS, just as it does for UT1 and
+ *  polar motion.
+ *
+ *  @return psEarthPole*:       interpolated corrections to the precession components.
+ */
+psEarthPole *psEOC_PrecessionCorr(
+    const psTime *time,                ///< specified time
+    psTimeBulletin bulletin            ///< IERS tables for polar coordinate components.
+);
+
+/** Constructs the spherical rotation for transforming from CEO to GCRS coordinates.
+ *
+ *  The resulting psSphereRot may be used to determine the rotation from CIP/CEO to
+ *  GCRS.  This function must give results identical to the IERS BPN2000.
+ *
+ *  @return psSphereRot*:       spherical rotation for CEO to GCRS transformation.
+ */
+psSphereRot *psSphereRot_CEOtoGCRS(
+    const psEarthPole *pole            ///< input coordinates to transform
+);
+
+/** Calculates the rotation of the Earth about the CIP.
+ *
+ *  If tidalCorr is non-NULL, use the S-component to provide tidal corrections to the
+ *  UT1 time.  If tidalCorr is NULL, no corrections are made & this step is skipped.
+ *
+ *  @return psSphereRot*:       spherical rotation of the Earth about the CIP.
+ */
+psSphereRot *psSphereRot_TEOtoCEO(
+    const psTime *time,                ///< specified time
+    psEarthPole *tidalCorr             ///< UT1 polar tide correction or NULL
+);
+
+/** Provides interpolated values of the polar motion components extracted from the
+ *  IERS tables.
+ *
+ *  @return psEarthPole*:       interpolated polar motion components.
+ */
+psEarthPole *psEOC_GetPolarMotion(
+    const psTime *time,                ///< specified time
+    psTimeBulletin bulletin            ///< IERS tables for polar coordinate components.
+);
+
+/** Provides tidal corrections to the polar motion components using the Ray model
+ *  of Simon et al.
+ *
+ *  @return psEarthPole*:       corrected polar motion components.
+ */
+psEarthPole *psEOC_PolarTideCorr(
+    const psTime *time                 ///< specified time
+);
+
+/** Provides the additional corrections due to nutation terms with periods less than
+ *  or equal to two days, as well as the correction to the s-prime component of polar
+ *  motion.
+ *
+ *  @return psEarthPole*:       corrected polar motion components.
+ */
+psEarthPole *psEOC_NutationCorr(
+    psTime *time                       ///< specified time
+);
+
+/** Converts the polar motion corrections to a spherical rotation.
+ *
+ *  This function should give identical results to the IERS POM2000 subroutine.
+ *
+ *  @return psSphereRot*:       ITRS to TEO sphere rotation.
+ */
+psSphereRot *psSphereRot_ITRStoTEO(
+    const psEarthPole *motion          ///< corrected polar motion components
+);
+
+/** Generates the complete spherical rotation to account for precession
+ *  between two times.  The equinoxes shall be Julian equinoxes.
+ *
+ *  If NULL is provided for either time, it is assumed to have the reference
+ *  equinox value of J2000.  The mode argument is used to specify the level of
+ *  detail used in the calculation.
+ *
+ *  @return psSphere*:       the resulting spherical rotation
+ */
+psSphereRot* psSpherePrecess(
+    const psTime *fromTime,            ///< equinox of coords input
+    const psTime *toTime,              ///< equinox of coords output
+    psPrecessMethod mode               ///< level of detail to use
+);
+
+
+/// @}
+#endif // #ifndef PS_EARTH_ORIENTATION
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psSphereOps.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psSphereOps.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psSphereOps.c	(revision 22158)
@@ -0,0 +1,473 @@
+/** @file  psSphereOps.c
+ *
+ *  @brief Contains spherical rotation and offset operations
+ *
+ *  @ingroup CoordinateTransform
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Dave Robbins, MHPCC
+ *
+ *  @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-01-09 22:38:52 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <math.h>
+#include <float.h>
+
+#include "psSphereOps.h"
+#include "psType.h"
+#include "psCoord.h"
+#include "psMemory.h"
+#include "psTime.h"
+#include "psAssert.h"
+#include "psError.h"
+#include "psLogMsg.h"
+
+
+
+// Modified Julian Day 01/01/1900 00:00:00
+#define MJD_1900 15021.0
+
+// Days in Julian century
+#define JULIAN_CENTURY 36525.0
+
+static void sphereRotFree(psSphereRot *result)
+{
+    // There are non dynamic allocated items
+}
+
+static psSphereRot* sphereRotAlloc(void)
+{
+    psSphereRot *sphereRot = (psSphereRot* ) psAlloc(sizeof(psSphereRot));
+    psMemSetDeallocator(sphereRot, (psFreeFunc)sphereRotFree);
+    return (sphereRot);
+}
+
+psSphereRot* psSphereRotAlloc(double alphaP,
+                              double deltaP,
+                              double phiP)
+{
+    if (isnan(alphaP) || isnan(deltaP) || isnan(phiP) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Input angles cannot be NaN in psSphereRotAlloc.");
+        return NULL;
+    }
+    psSphereRot *r = sphereRotAlloc();
+    psSphereRot *s = sphereRotAlloc();
+    psSphereRot *t = sphereRotAlloc();
+
+    //The following represents: r =a rotation about the z-axis by alphaP, s =a rotation about
+    // the y-axis by deltaP, and t =a rotation about the z-axis by phiP.
+    r->q0=0;
+    r->q1=0;
+    r->q2=sin(alphaP/2.0);
+    r->q3=cos(alphaP/2.0);
+
+    s->q0=0;
+    s->q1=sin(deltaP/2.0);
+    s->q2=0;
+    s->q3=cos(deltaP/2.0);
+
+    t->q0=0;
+    t->q1=0;
+    t->q2=sin(phiP/2.0);
+    t->q3=cos(phiP/2.0);
+
+    // calculate t*s*r.
+    psSphereRot* temp = psSphereRotCombine(NULL,t,s);
+    psSphereRot* result = psSphereRotCombine(NULL, temp, r);
+    psFree(temp);
+    psFree(r);
+    psFree(s);
+    psFree(t);
+    return result;
+}
+
+bool psMemCheckSphereRot(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    //See if the ptr corresponds to a psSphereRot*
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)sphereRotFree );
+}
+
+//This function is really a second allocate function for psSphereRot's that uses quaternion
+// component inputs instead of angle inputs as in psSphereRotAlloc.
+psSphereRot* psSphereRotQuat(double q0,
+                             double q1,
+                             double q2,
+                             double q3)
+{
+    if (isnan(q0) || isnan(q1) || isnan(q2) || isnan(q3) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Input quaternions cannot be NaN in psSphereRotQuat.");
+        return NULL;
+    }
+    //allocate space for a new sphere rotation and set deallocator
+    psSphereRot* rot = sphereRotAlloc();
+
+    //The magnitude of a rotation quaternion should = 1 so we normalize here in case the
+    // inputs have not been.
+    double len = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);
+    rot->q0 = q0 / len;
+    rot->q1 = q1 / len;
+    rot->q2 = q2 / len;
+    rot->q3 = q3 / len;
+
+    return rot;
+}
+
+psSphereRot* psSphereRotConjugate(psSphereRot *out,
+                                  const psSphereRot *in)
+{
+    //if input sphere rotation is NULL, return NULL
+    if (in == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "psSphereRot input cannot be NULL.\n");
+        return NULL;
+    }
+    //if output sphere rotation is NULL, allocate a new sphere rotation to return
+    if (out == NULL) {
+        out = sphereRotAlloc();
+    }
+    //Since q3 is the magnitude and q0,q1,q2 are direction, the conjugate rotation
+    // is formed by -q0,-q1,-q2,+q3.  Note that this is the same as q0,q1,q2,-q3.
+    out->q0 = -in->q0;
+    out->q1 = -in->q1;
+    out->q2 = -in->q2;
+    out->q3 = in->q3;
+
+    return out;
+}
+
+psSphere* psSphereRotApply(psSphere* out,
+                           const psSphereRot* transform,
+                           const psSphere* coord)
+{
+    //Make sure that input coordinates and rotation are not NULL
+    PS_ASSERT_PTR_NON_NULL(transform, NULL);
+    PS_ASSERT_PTR_NON_NULL(coord, NULL);
+    //If output coordinates is NULL allocate a new psSphere
+    if (out == NULL) {
+        out = psSphereAlloc();
+    }
+    //apply the transform by creating a new psSphereRot from the input coord
+    // and combining it with the input transform (see ADD)
+    double cosD = cos(coord->d);
+    psSphereRot* coordQuat = psSphereRotQuat(
+                                 cosD*cos(coord->r),
+                                 cosD*sin(coord->r),
+                                 sin(coord->d),
+                                 0.0);
+    //Get the conjugate of the input rotation.  Need to calculate r*p*R to apply rotation
+    // where R = r-conjugate.
+    psSphereRot *conjugate = psSphereRotConjugate(NULL, transform);
+    psSphereRot *temp = psSphereRotCombine(NULL, transform, coordQuat);
+    psSphereRot *result = psSphereRotCombine(NULL, temp, conjugate);
+    //From ADD we can find the new sphere coordinates,
+    // r is calculated as tan^-1 (q1/q0), d is sin^-1 (q2)
+    out->r = atan2(result->q1, result->q0);
+    out->d = asin(result->q2);
+    out->rErr = 0.0;
+    out->dErr = 0.0;
+    //Simply for convention, we make sure all output r-parameters are positive in the range
+    // of 0 to 2pi
+    if (out->r < -0.000001) {
+        out->r += 2.0 * M_PI;
+    }
+
+    psFree(conjugate);
+    psFree(temp);
+    psFree(result);
+    psFree(coordQuat);
+    return out;
+}
+
+psSphereRot* psSphereRotCombine(psSphereRot* out,
+                                const psSphereRot* rot1,
+                                const psSphereRot* rot2)
+{
+    //Make sure that input rotations are not NULL
+    PS_ASSERT_PTR_NON_NULL(rot1, NULL);
+    PS_ASSERT_PTR_NON_NULL(rot2, NULL);
+    //If output rotation is NULL, allocate a new psSphereRot to return
+    if (out == NULL) {
+        out = sphereRotAlloc();
+    }
+
+    double a0 = rot1->q0;
+    double a1 = rot1->q1;
+    double a2 = rot1->q2;
+    double a3 = rot1->q3;
+    double b0 = rot2->q0;
+    double b1 = rot2->q1;
+    double b2 = rot2->q2;
+    double b3 = rot2->q3;
+
+    //Combine rot1 & rot2.  Formulas here came from ADD.
+    out->q0 = a3*b0 + a0*b3 + a1*b2 - a2*b1;
+    out->q1 = a3*b1 - a0*b2 + a1*b3 + a2*b0;
+    out->q2 = a3*b2 + a0*b1 - a1*b0 + a2*b3;
+    out->q3 = b3*a3 - b2*a2 - b1*a1 - b0*a0;
+
+    return out;
+}
+
+psSphereRot *psSphereRotInvert(double alphaP,
+                               double deltaP,
+                               double phiP)
+{
+    //This function should produce identical results to psSphereRotConjugate in most
+    // or possibly all situations.  Creates the inverse rotation from the input angles.
+    return (psSphereRotAlloc(-phiP, -deltaP, -alphaP));
+}
+
+psSphereRot* psSphereRotEclipticToICRS(const psTime *time)
+{
+    psF64 T;
+    // Check for null parameter
+    PS_ASSERT_PTR_NON_NULL(time, NULL);
+    // Convert psTime to MJD
+    psF64 MJD = psTimeToMJD(time);
+    // Check the specified MJD is greater than 1900
+    if ( MJD < MJD_1900 ) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE,true,_("Specified time is less than 1900."));
+        return NULL;
+    }
+    // Calculate number of Julian centuries since 1900
+    T = ( MJD - MJD_1900 ) / JULIAN_CENTURY;
+    //Formulas for phiP, deltaP, alphaP came from ADD.
+    psF64 phiP = - DEG_TO_RAD(270.0);
+    psF64 deltaP = - (DEG_TO_RAD(23.0) +
+                      MIN_TO_RAD(27.0) +
+                      SEC_TO_RAD(8.26) -
+                      (SEC_TO_RAD(46.845) * T) -
+                      (SEC_TO_RAD(0.0059) * T * T) +
+                      (SEC_TO_RAD(0.00181) * T * T * T));
+    psF64 alphaP = - DEG_TO_RAD(90.0);
+
+    return (psSphereRotAlloc(alphaP, deltaP, phiP));
+}
+
+psSphereRot* psSphereRotICRSToEcliptic(const psTime *time)
+{
+    psF64 T;
+    // Check for null parameter
+    PS_ASSERT_PTR_NON_NULL(time, NULL);
+    // Convert psTime to MJD
+    psF64 MJD = psTimeToMJD(time);
+    // Check the specified MJD is greater than 1900
+    if ( MJD < MJD_1900 ) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE,true,_("Specified time is less than 1900."));
+        return NULL;
+    }
+    // Calculate number of Julian centuries since 1900
+    T = ( MJD - MJD_1900 ) / JULIAN_CENTURY;
+
+    //Formulas for phiP, deltaP, alphaP came from ADD.  Notice that the formulas are the
+    // same as for EclipticToICRS except that alpha=-phiP, deltaP=-deltaP, phiP=-alphaP to
+    // produce the inverse rotation as in psSphereRotInverse.
+    psF64 alphaP = DEG_TO_RAD(270.0);
+    psF64 deltaP = DEG_TO_RAD(23.0) +
+                   MIN_TO_RAD(27.0) +
+                   SEC_TO_RAD(8.26) -
+                   (SEC_TO_RAD(46.845) * T) -
+                   (SEC_TO_RAD(0.0059) * T * T) +
+                   (SEC_TO_RAD(0.00181) * T * T * T);
+    psF64 phiP = DEG_TO_RAD(90.0);
+
+    return (psSphereRotAlloc(alphaP, deltaP, phiP));
+}
+
+psSphereRot* psSphereRotGalacticToICRS(void)
+{
+    //Formulas for alphaP, deltaP, phiP came from the ADD for ICRSToGalactic.  Notice that
+    // this is the reason the inverse gets allocated and returned here.
+    psF64 alphaP = DEG_TO_RAD(180.0-192.85948);
+    psF64 deltaP = DEG_TO_RAD(90.0 - 27.12825);
+    psF64 phiP = DEG_TO_RAD(90.0+32.93192);
+    return (psSphereRotAlloc(-phiP,-deltaP,-alphaP));
+}
+
+psSphereRot* psSphereRotICRSToGalactic(void)
+{
+    //Formulas for alphaP, deltaP, phiP came from ADD.
+    psF64 alphaP = DEG_TO_RAD(180.0-192.85948);
+    psF64 deltaP = DEG_TO_RAD(90.0 - 27.12825);
+    psF64 phiP = DEG_TO_RAD(90.0+32.93192);
+
+    return (psSphereRotAlloc(alphaP, deltaP, phiP));
+}
+
+//Calculates the difference between coordinates in position1 & 2 and returns this offset.
+psSphere* psSphereGetOffset(const psSphere* position1,
+                            const psSphere* position2,
+                            psSphereOffsetMode mode,
+                            psSphereOffsetUnit unit)
+{
+    //Make sure that input coordinates are not NULL & that mode & unit are valid
+    PS_ASSERT_PTR_NON_NULL(position1, NULL);
+    PS_ASSERT_PTR_NON_NULL(position2, NULL);
+    // Check positions near 90 degree and issue warnings if necessary
+    if (position1->d >= DEG_TO_RAD(90.0)) {
+        psLogMsg(__func__, PS_LOG_WARN,
+                 "WARNING: psDeproject(): position1->d is larger than 90 degrees.  Returning NULL.");
+        return NULL;
+    }
+    if (position2->d >= DEG_TO_RAD(90.0)) {
+        psLogMsg(__func__, PS_LOG_WARN,
+                 "WARNING: psDeproject(): position2->d is larger than 90 degrees.  Returning NULL.");
+        return NULL;
+    }
+    // Allocate return structure
+    psSphere* tmp = psSphereAlloc();
+
+    // Mode is LINEAR - Use first position as projection center and project second point
+    // onto tangent plane, set point projected into psSphere structure x->r y->d
+    if (mode == PS_LINEAR) {
+        //The basic idea is to project both positions onto the linear plane, with position1
+        // at the center, then calculate the linear offset between those projections.
+        psProjection* proj = psProjectionAlloc(position1->r,
+                                               position1->d,
+                                               1.0,
+                                               1.0,
+                                               PS_PROJ_TAN);
+        // Perform projection onto tangent plane
+        psPlane* lin = psProject(NULL, position2, proj);
+        // Set return values
+        tmp->r = lin->x;
+        tmp->d = lin->y;
+        // Free data structures allocated
+        psFree(proj);
+        psFree(lin);
+
+        // Mode is SPHERICAL - Get difference between positiion 1 and position 2 and convert
+        // offset value from radians to desired units and return
+    } else if (mode == PS_SPHERICAL) {
+        tmp->r = position2->r - position1->r;
+        tmp->d = position2->d - position1->d;
+
+        // Wrap these to an acceptable range.  This assumes that all
+        // angles are in radians.
+        tmp->r = fmod(tmp->r, 2*M_PI);
+        tmp->d = fmod(tmp->d, 2*M_PI);
+        tmp->rErr = 0.0;
+        tmp->dErr = 0.0;
+
+        // Convert output to desired units
+        if (unit == PS_ARCSEC) {
+            tmp->r = RAD_TO_SEC(tmp->r);
+            tmp->d = RAD_TO_SEC(tmp->d);
+        } else if (unit == PS_ARCMIN) {
+            tmp->r = RAD_TO_MIN(tmp->r);
+            tmp->d = RAD_TO_MIN(tmp->d);
+        } else if (unit == PS_DEGREE) {
+            tmp->r = RAD_TO_DEG(tmp->r);
+            tmp->d = RAD_TO_DEG(tmp->d);
+        } else if (unit == PS_RADIAN) {}
+        else {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    _("Specified units, 0x%x, is not supported."),
+                    unit);
+            psFree(tmp);
+            return NULL;
+        }
+
+        // Invalid mode
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified offset mode, 0x%x, is not supported."),
+                mode);
+        psFree(tmp);
+        return NULL;
+    }
+
+    // Return value
+    return tmp;
+}
+
+//Applies the specified offset to the input position coordinates and returns the new position.
+psSphere* psSphereSetOffset(const psSphere* position,
+                            const psSphere* offset,
+                            psSphereOffsetMode mode,
+                            psSphereOffsetUnit unit)
+{
+    //Make sure that input coordinates are not NULL & that mode & unit are valid
+    PS_ASSERT_PTR_NON_NULL(position, NULL);
+    PS_ASSERT_PTR_NON_NULL(offset, NULL);
+
+    psSphere* tmp;
+    psF64 tmpR = 0.0;
+    psF64 tmpD = 0.0;
+
+    // If mode is linear then set position to projection center
+    // and offset to linear coordinate then deproject to obtain
+    // new sphere coordinate
+    if (mode == PS_LINEAR) {
+        // Allocate plane coordinate and set coordinate
+        psPlane*  lin = psPlaneAlloc();
+        lin->x = offset->r;
+        lin->y = offset->d;
+        // Allocate and set projection structure
+        psProjection* proj = psProjectionAlloc(position->r,
+                                               position->d,
+                                               1.0,
+                                               1.0,
+                                               PS_PROJ_TAN);
+        // Project tangent plane coord to spherical coord
+        tmp = psDeproject(NULL, lin, proj);
+        // Free data structures used
+        psFree(proj);
+        psFree(lin);
+
+        // If mode is spherical then convert offset to radians, add the offset
+        // to the position and wrap to 0 to 2pi
+    } else if (mode == PS_SPHERICAL) {
+        // Convert offset unit to radians
+        if (unit == PS_ARCSEC) {
+            tmpR = SEC_TO_RAD(offset->r);
+            tmpD = SEC_TO_RAD(offset->d);
+        } else if (unit == PS_ARCMIN) {
+            tmpR = MIN_TO_RAD(offset->r);
+            tmpD = MIN_TO_RAD(offset->d);
+        } else if (unit == PS_DEGREE) {
+            tmpR = DEG_TO_RAD(offset->r);
+            tmpD = DEG_TO_RAD(offset->d);
+        } else if (unit == PS_RADIAN) {
+            tmpR = offset->r;
+            tmpD = offset->d;
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    _("Specified units, 0x%x, is not supported."),
+                    unit);
+            return NULL;
+        }
+
+        // Allocate sphere structure to return
+        tmp = psSphereAlloc();
+
+        // Add offset and wrap to 0 to 2PI if necessary
+        tmp->r = position->r + tmpR;
+        tmp->r = fmod(tmp->r, 2.0*M_PI);
+        tmp->d = position->d + tmpD;
+        tmp->d = fmod(tmp->d, 2.0*M_PI);
+        tmp->rErr = 0.0;
+        tmp->dErr = 0.0;
+
+        // Invalid mode report error
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified offset mode, 0x%x, is not supported."),
+                mode);
+        return NULL;
+    }
+
+    return tmp;
+}
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psSphereOps.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psSphereOps.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psSphereOps.h	(revision 22158)
@@ -0,0 +1,217 @@
+/** @file  psSphereOps.h
+ *
+ *  @brief Contains spherical rotation and offset operations
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author David Robbins, MHPCC
+ *
+ *  @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-08-09 01:40:07 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_SPHERE_H
+#define PS_SPHERE_H
+
+/// @addtogroup Astro Astronomy
+/// @{
+
+# include "psTime.h"
+
+/** Spherical Rotation Definition
+ *
+ *  We need to be able to convert between ICRS, Galactic and Ecliptic
+ *  coordinates, and potentially between arbitrary spherical coordinate
+ *  systems. All of these basic spherical transformations represent rotations
+ *  of the spherical coordinate reference.
+ *
+ */
+typedef struct
+{
+    double q0;
+    double q1;
+    double q2;
+    double q3;
+}
+psSphereRot;
+
+/** Mode for Offset calculation between two sky positions
+ *
+ *  @see  psSphereGetOffset, psSphereSetOffset
+ *
+ */
+typedef enum {
+    PS_SPHERICAL,                      ///< offset corresponds to an angular offset
+    PS_LINEAR                          ///< offset corresponds to a linear offset
+} psSphereOffsetMode;
+
+/** The units of the offset
+ *
+ *  @see  psSphereGetOffset, psSphereSetOffset
+ *
+ */
+typedef enum {
+    PS_ARCSEC,                         ///< Arcseconds
+    PS_ARCMIN,                         ///< Arcminutes
+    PS_DEGREE,                         ///< Degrees
+    PS_RADIAN                          ///< Radians
+} psSphereOffsetUnit;
+
+
+/** Allocator for psSphereRot
+ *
+ *  @return psSphereRot*         newly allocated psSphereRot
+ */
+
+psSphereRot* psSphereRotAlloc(
+    double alphaP,                     ///< north pole latitude
+    double deltaP,                     ///< north pole longitude
+    double phiP                        ///< defines the longitude in the input system of the equatorial intersection between the two systems (e.g, the first point of Ares).
+) PS_ATTR_MALLOC;
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psSphereRot structure, false otherwise.
+ */
+bool psMemCheckSphereRot(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+
+/** Allocator for psSphereRot given quaternions.
+ *
+ *  Normalizes a given quaternion and returns the cooresponding newly allocated
+ *  psSphereRot object.
+ *
+ *  @return psSphereRot*         newly allocated psSphereRot
+ */
+psSphereRot* psSphereRotQuat(
+    double q0,                          ///< q0
+    double q1,                          ///< q1
+    double q2,                          ///< q2
+    double q3                           ///< q3
+);
+
+/** Applies the psSphereTransform transform for a specified coordinate
+ *
+ *  @return psSphere*      resulting coordinate based on transform
+ */
+psSphere* psSphereRotApply(
+    psSphere* out,                     ///< a psSphere to recycle.  If NULL, a new one is generated.
+    const psSphereRot* transform,      ///< the transform to apply
+    const psSphere* coord              ///< the coordinate to apply the transform above.x
+);
+
+/** Combines two rotations.
+ *
+ *  Combines two rotations to produce a single rotation which is the
+ *  equivalent of applying the ï¬rst rotation and then the second. The output
+ *  rotation may be supplied, or will be allocated if NULL.
+ *
+ *  @return psSphereRot*    New psSphereRot that is the combination of the input psSphereRots
+ */
+psSphereRot* psSphereRotCombine(
+    psSphereRot* out,                  ///< a psSphereRot to recycle or NULL
+    const psSphereRot* rot1,           ///< first rotation to combine
+    const psSphereRot* rot2            ///< second rotation to combine
+);
+
+/** Returns the conjugate of a specified rotation.
+ *
+ *  Stores the conjugate of a specified rotation in an existing psSphereRot* or creates a
+ *  new psSphereRot* if NULL.  The conjugate of a rotation given in quaternions is -q0,
+ *  -q1, -q2, q3.
+ *
+ *  @return psSphereRot*    the Conjugate of the specified psSphereRot, in.
+ */
+psSphereRot* psSphereRotConjugate(
+    psSphereRot *out,                  ///< a psSphereRot to recycle or NULL
+    const psSphereRot *in              ///< the psSphereRot from which to obtain the conjugate
+);
+
+/** Inverts the rotation.
+ *
+ *  A given rotation is inverted by creating a psSphereRot using -phiP, -deltaP, -alphaP.
+ *
+ *  @return psSphereRot*    Inverted input psSphereRot
+ */
+psSphereRot* psSphereRotInvert(
+    double alphaP,                      ///< north pole latitude
+    double deltaP,                      ///< north pole longitude
+    double phiP                         ///< defines the longitude in the input system of the equatorial intersection between the two systems (e.g, the first point of Ares).
+);
+
+/** Determines the offset (RA,Dec) on the sky between two positions.
+ *
+ *  Both an offset mode and an offset unit may be defined. The mode may be
+ *  either PS_SPHERICAL, in which case the specified offset corresponds to an
+ *  offset in angles, or it may be PS_LINEAR, in which case the offset
+ *  corresponds to a linear offset in a local projection. The offset unit may
+ *  be in one of PS_ARCSEC, PS_ARCMIN, PS_DEGREE, and PS_RADIAN, which
+ *  specifies the units of the offset only.
+ *
+ *  @return psSphere*        the offset between position1 and position2
+ */
+psSphere* psSphereGetOffset(
+    const psSphere* position1,         ///< first position for calculating offset
+    const psSphere* position2,         ///< second position for calculating offset
+    psSphereOffsetMode mode,           ///< type of offset can be PS_SPHERICAL or PS_LINEAR
+    psSphereOffsetUnit unit            ///< specifies the units of offset only
+);
+
+/** Applies the given offset to a coordinate.
+ *
+ *  Both an offset mode and an offset unit may be defined. The mode may be
+ *  either PS_SPHERICAL, in which case the specified offset corresponds to an
+ *  offset in angles, or it may be PS_LINEAR, in which case the offset
+ *  corresponds to a linear offset in a local projection. The offset unit may
+ *  be in one of PS_ARCSEC, PS_ARCMIN, PS_DEGREE, and PS_RADIAN, which
+ *  specifies the units of the offset only.
+ *
+ *  @return psSphere*              the original position with the given offset applied.
+ */
+psSphere* psSphereSetOffset(
+    const psSphere* position,          ///< coordinate of origin
+    const psSphere* offset,            ///< coordinate of offset to apply
+    psSphereOffsetMode mode,           ///< corresponds to an offset in angles or local projection
+    psSphereOffsetUnit unit            ///< specifies the units of offset only
+);
+
+/** Creates the appropriate transform for converting from ICRS to Ecliptic
+ *  coordinate systems.
+ *
+ *  @return psSphereRot*     transform for ICRS->Ecliptic coordinate systems
+ */
+psSphereRot* psSphereRotICRSToEcliptic(
+    const psTime *time                 ///< the time for which the resulting transform will be valid
+);
+
+/** Creates the appropriate transform for converting from Ecliptic to ICRS
+ *  coordinate systems.
+ *
+ *  @return psSphereRot*     transform for Ecliptic->ICRS coordinate systems
+ */
+psSphereRot* psSphereRotEclipticToICRS(
+    const psTime *time                 ///< the time for which the resulting transform will be valid
+);
+
+/** Creates the appropriate transform for converting from ICRS to Galactic
+ *  coordinate systems.
+ *
+ *  @return psSphereRot*        new sphere rotation for ICRS to Galactic transformations.
+ */
+psSphereRot* psSphereRotICRSToGalactic(void);
+
+/** Creates the appropriate transform for converting from Galactic to ICRS
+ *  coordinate systems.
+ *
+ *  @return psSphereRot*        new sphere rotation for Galactic to ICRS transformations.
+ */
+psSphereRot* psSphereRotGalacticToICRS(void);
+
+/// @}
+
+#endif // #ifndef PS_SPHERE_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psTime.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psTime.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psTime.c	(revision 22158)
@@ -0,0 +1,1984 @@
+/** @file  psTime.c
+ *
+ *  @brief Definitions for time, time utilities, and conversion functions for use with psLib astronomy
+ *  functions.
+ *
+ *  A collection of functions are required by psLib to manipulate time data. These functions primarily consist
+ *  of conversions between specific time formats.  They use the UNIX timeval time system as the
+ *  base upon which International Atomic Time (TAI) and Universal Time Coordinated (UTC) are calculated.
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.115 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-03-17 23:53:43 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <ctype.h>
+
+#include "psTime.h"
+#include "psError.h"
+#include "psLogMsg.h"
+#include "psTrace.h"
+#include "psMemory.h"
+#include "psAbort.h"
+#include "psImage.h"
+#include "psString.h"
+#include "psMetadata.h"
+#include "psMetadataConfig.h"
+#include "psLookupTable.h"
+#include "psAssert.h"
+
+#define MAX_STRING_LENGTH 256
+
+/** Sidereal angular conversion from seconds to radians for GMST in seconds (i.e. pi/(180*240)) */
+#define S2R (7.272205216643039903848711535369e-5)
+
+/** Two times pi with double precision accuracy */
+#define TWOPI (2.0*M_PI)
+
+/** Conversion from radians to degrees */
+#define R2DEG = (180.0/M_PI)
+
+/** Maximum length of time string */
+#define MAX_TIME_STRING_LENGTH 256
+
+/** Seconds per minute */
+#define  SEC_PER_MINUTE 60.0
+
+/** Seconds per hour */
+#define  SEC_PER_HOUR (60.0*SEC_PER_MINUTE)
+
+/** Seconds per day */
+#define  SEC_PER_DAY (24.0*SEC_PER_HOUR)
+
+/** Seconds per year */
+#define  SEC_PER_YEAR (365.0*SEC_PER_DAY)
+
+/** Microseconds per day */
+#define NSEC_PER_DAY 86400000000000.0
+
+// Time config file path
+static char *timeConfig = NULL;
+
+/** Time metadata read from config file */
+static psMetadata *timeMetadata = NULL;
+
+// Offset to convert terrestrial time(TT) to international atomic time(TAI)
+#define  TAI_TT_OFFSET_SECONDS        32
+#define  TAI_TT_OFFSET_NANOSECONDS    184000000
+
+// Offset from converting to MJD
+#define  MJD_EPOCH_OFFSET             40587.0
+
+// Offset for converting to JD
+#define  JD_EPOCH_OFFSET              2440587.5
+
+// Offset of year 0000 from epoch
+#define YEAR_0000_SEC                 -62125920000
+
+// Offset of year 9999 from epoch
+#define YEAR_9999_SEC                 253202544000
+
+/** Static function prototypes */
+static char *cleanString(char *inString, int sLen);
+static char* getToken(char **inString, char *delimiter, psParseErrorType *status);
+static psTime* convertTimeTAIUTC(psTime* time);
+static psTime* convertTimeUTCTAI(psTime* time);
+static psTime* convertTimeTAITT(psTime* time);
+static psTime* convertTimeTTTAI(psTime* time);
+static psTime* convertTimeUTCUT1(psTime* time);
+
+static bool p_psTimeInit(const char *fileName);
+
+/** Removes leading and trailing whitespace and # characters from a string. The cleaned string is a new null
+ *  terminated copy of the original input string. */
+static char *cleanString(char *inString,
+                         int sLen)
+{
+    char *ptrB = NULL;
+    char *ptrE = NULL;
+    char *cleaned = NULL;
+
+    ptrB = inString;
+
+    // Skip over leading # or whitespace
+    while (isspace(*ptrB) || *ptrB=='#') {
+        ptrB++;
+    }
+
+    // Skip over trailing whitespace, null terminators, and # characters
+    ptrE = inString + sLen - 1;
+    while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') {
+        ptrE--;
+    }
+
+    // Length, sLen, does not include '\0'
+    sLen = ptrE - ptrB + 1;
+
+    // Adds '\0' to end of string and +1 to sLen
+    cleaned = psStringNCopy(ptrB, sLen);
+
+    return cleaned;
+}
+
+/** Returns cleaned token based on delimiter, but not including delimiter. Also changes the pointer location
+ * the beginning of the string. Tokens are newly allocated null terminated strings. */
+static char* getToken(char **inString,
+                      char *delimiter,
+                      psParseErrorType *status)
+{
+    char *cleanToken = NULL;
+    int sLen = 0;
+
+    // Skip over leading whitespace
+    while(isspace(**inString)) {
+        (*inString)++;
+    }
+
+    // Length of token, not including delimiter
+    sLen = strcspn(*inString, delimiter);
+
+    if(sLen) {
+
+        // Create new, cleaned, and null terminated token
+        cleanToken = cleanString(*inString, sLen);
+
+        // Move to end of token
+        //        (*inString) += (sLen+1);
+        (*inString) += sLen;
+        if (**inString != '\0' ) {
+            (*inString)++;
+        }
+
+    } else if(**inString!='\0' && sLen==0) {
+        *status = PS_PARSE_ERROR_GENERAL;
+    }
+
+    return cleanToken;
+}
+
+// get the pslib.config filename by checking environment variable first, then
+// the possiblity set config file name, then the original installation area.
+const char *p_psTimeConfigFilename(const char *filename)
+{
+    // if filename is provided, set timeConfig to this value
+    if (filename) {
+        psFree(timeConfig);
+        timeConfig = psStringCopy(filename);
+        psMemSetPersistent(timeConfig, true);
+        return timeConfig;
+    }
+
+    // check the env var first
+    const char *PS_CONFIG_FILE = getenv("PS_CONFIG_FILE");
+    if (PS_CONFIG_FILE) {
+        return PS_CONFIG_FILE;
+    }
+
+    // check timeConfig var 2nd
+    if (timeConfig) {
+        return timeConfig;
+    }
+
+    // fall back to the default, this should come from configure.ac
+    return PS_CONFIG_FILE_DEFAULT;
+}
+
+
+// Searches time tables in priority order and performs interpolation if input index value is within a table.
+// If the index value is out of range, the status is set accordingly.
+psF64 p_psTimeSearchTables(psF64 index,
+                           psU64 column,
+                           char *metadataTableNames[],
+                           psU32 nTables,
+                           psLookupStatusType* status)
+{
+    char*            tableName          = NULL;
+    psF64            result             = NAN;
+    psLookupTable*   table              = NULL;
+    psMetadataItem*  tableMetadataItem  = NULL;
+
+    // Check if psTime tables are already loaded
+    if(!p_psTimeInit(p_psTimeConfigFilename(NULL))) {
+        *status = PS_LOOKUP_ERROR;
+        return NAN;
+    }
+
+    // Search each table in priority order: daily, eopc,finals
+    for(psS32 i = 0; i < nTables; i++) {
+
+        // Get table name from list of tables to search
+        tableName = metadataTableNames[i];
+
+        // Lookup table name in time metadata
+        tableMetadataItem = psMetadataLookup(timeMetadata, tableName);
+
+        // Check if table not a metadata item
+        if(tableMetadataItem == NULL) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                    tableName);
+            *status = PS_LOOKUP_ERROR;
+            return NAN;
+        }
+
+        // Get table from metadata
+        table = (psLookupTable*)tableMetadataItem->data.V;
+
+        // Check that table is not NULL
+        PS_ASSERT_PTR_NON_NULL(table,NAN);
+
+        // Check if index within to/from range
+        if(index >= table->validFrom ) {
+            if(index <= table->validTo) {
+                // Attempt to interpolate table
+                result = psLookupTableInterpolate(table, index, column);
+                *status = PS_LOOKUP_SUCCESS;
+                if(!isnan(result)) {
+                    break;
+                }
+            } else {
+                *status = PS_LOOKUP_PAST_BOTTOM;
+            }
+        } else {
+            *status = PS_LOOKUP_PAST_TOP;
+        }
+    }
+
+    return result;
+}
+
+bool p_psTimeInit(const char *fileName)
+{
+    psS32 numLines = 0;
+    bool foundTable = false;
+    char *tableDir = NULL;
+    char *tableNames = NULL;
+    char *tableFormats = NULL;
+    char *namesPtr = NULL;
+    char *formatPtr = NULL;
+    char *metadataNamesPtr = NULL;
+    char *tableName = NULL;
+    char *tableFormat = NULL;
+    char *fullTableName = NULL;
+    psS32 i = 0;
+    psS32 j = 0;
+    psS32 numTables = 0;
+    psU32 nFail = 0;
+    psVector *tablesFrom = NULL;
+    psVector *tablesTo = NULL;
+    psVector *tablesIndex = NULL;
+    psMetadataItem *metadataItem = NULL;
+    psLookupTable *table = NULL;
+    psParseErrorType status = PS_PARSE_SUCCESS;
+    char metadataTableNames[4][MAX_STRING_LENGTH] = {"daily", "eopc",  "finals", "tai"};
+
+    // Check if the p_psTimeInit has already been ran
+    if (timeMetadata != NULL) {
+        return true;
+    }
+
+    // XXX this is not thread safe as the persistence setting is global
+    const bool initialPersistence =
+        p_psMemAllocatePersistent(true); // All memory allocated below is "persistent"
+
+    // Read config file
+    timeMetadata = psMetadataConfigRead(timeMetadata, &nFail, fileName, true);
+    if(timeMetadata == NULL) {
+        return false;
+    } else if(nFail != 0) {
+        return false;
+    }
+
+    // Get number of tables
+    metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.n");
+    if(metadataItem == NULL) {
+        p_psMemAllocatePersistent(initialPersistence);
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                "psLib.time.tables.n");
+        return false;
+    }
+    numTables = (psS32)metadataItem->data.S32;
+
+    // Get lower range of tables
+    metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.from");
+    if(metadataItem == NULL) {
+        p_psMemAllocatePersistent(initialPersistence);
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                "psLib.time.tables.from");
+        return false;
+    }
+    tablesFrom = psVectorCopy(tablesFrom, metadataItem->data.V, PS_TYPE_F64);
+    if(tablesFrom->n != numTables) {
+        p_psMemAllocatePersistent(initialPersistence);
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Incorrect vector size. Size: %ld, Expected %d."), tablesFrom->n, numTables);
+        psFree(tablesFrom);
+        return false;
+    }
+
+    // Get upper range of tables
+    metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.to");
+    if(metadataItem == NULL) {
+        p_psMemAllocatePersistent(initialPersistence);
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                "psLib.time.tables.to");
+        psFree(tablesFrom);
+        return false;
+    }
+    tablesTo = psVectorCopy(tablesTo, metadataItem->data.V, PS_TYPE_F64);
+    if(tablesTo->n != numTables) {
+        p_psMemAllocatePersistent(initialPersistence);
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Incorrect vector size. Size: %ld, Expected %d."), tablesTo->n, numTables);
+        psFree(tablesFrom);
+        psFree(tablesTo);
+        return false;
+    }
+
+    // Get index columns for the tables
+    metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.index");
+    if(metadataItem == NULL) {
+        p_psMemAllocatePersistent(initialPersistence);
+        psError(PS_ERR_BAD_PARAMETER_VALUE,true,_("Failed find '%s' in time metadata."),
+                "psLib.time.tables.index");
+        psFree(tablesFrom);
+        psFree(tablesTo);
+        return false;
+    }
+    tablesIndex = psVectorCopy(tablesIndex, metadataItem->data.V, PS_TYPE_S32);
+    if(tablesIndex->n != numTables) {
+        p_psMemAllocatePersistent(initialPersistence);
+        psError(PS_ERR_BAD_PARAMETER_VALUE,true,_("Incorrect vector size. Size: %ld, Expected %d."),tablesIndex->n,numTables);
+        psFree(tablesFrom);
+        psFree(tablesTo);
+        psFree(tablesIndex);
+        return false;
+    }
+
+    // Get path to time data files
+    metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.dir");
+    if(metadataItem == NULL) {
+        p_psMemAllocatePersistent(initialPersistence);
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                "psLib.time.tables.dir");
+        psFree(tablesFrom);
+        psFree(tablesTo);
+        psFree(tablesIndex);
+        return false;
+    }
+    tableDir = psStringCopy(metadataItem->data.V);
+
+    // Table file names
+    metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.files");
+    if(metadataItem == NULL) {
+        p_psMemAllocatePersistent(initialPersistence);
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                "psLib.time.tables.files");
+
+        psFree(tablesFrom);
+        psFree(tablesTo);
+        psFree(tablesIndex);
+        psFree(tableDir);
+        return false;
+    }
+    tableNames = psStringCopy(metadataItem->data.V);
+
+    // Get table format strings
+    metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.format");
+    if(metadataItem == NULL) {
+        p_psMemAllocatePersistent(initialPersistence);
+        psError(PS_ERR_BAD_PARAMETER_VALUE,true, _("Failed find '%s' in time metadata."),
+                "psLib.time.tables.format");
+        psFree(tablesFrom);
+        psFree(tablesTo);
+        psFree(tablesIndex);
+        psFree(tableDir);
+        psFree(tableNames);
+        return false;
+    }
+    tableFormats = psStringCopy(metadataItem->data.V);
+    formatPtr = tableFormats;
+
+    // Read time tables
+    bool no_problem = true;  // True if we've detected no errors
+    namesPtr = tableNames;
+    while((tableName=getToken(&namesPtr, " ", &status)) != NULL) {
+
+        // Form path with table name, adding one to length for last '/' that may not occur
+        // in string in cong file
+        fullTableName = (char*)psAlloc(strlen(tableDir)+strlen(tableName)+1+1);
+
+        // Old strings may come back from psAlloc(), so set initial position to EOL
+        fullTableName[0]='\0';
+        strcat(fullTableName, tableDir);
+        strcat(fullTableName, "/");
+        strcat(fullTableName, tableName);
+
+        // Get table format
+        tableFormat = getToken(&formatPtr,",",&status);
+        if(tableFormat == NULL) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE,no_problem,_("Failed find '%s' in time metadata."),
+                    "psLib.time.tables.format");
+            no_problem = false;
+        }
+
+        // Create and read table
+        if(i < numTables) {
+            table = psLookupTableAlloc(fullTableName, (const char*)tableFormat, tablesIndex->data.S32[i]);
+            numLines = psLookupTableRead(table);
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, no_problem,
+                    _("Incorrect number of table files entered. Found: %d. Expected: %d."), i+1, numTables);
+            no_problem = false;
+        }
+
+        // Place tables into metadata slightly altered names as keys to create consistent naming conventions
+        foundTable = false;
+        for(j=0; j<numTables; j++) {
+            metadataNamesPtr = strstr(tableName, metadataTableNames[j]);
+            if(metadataNamesPtr != NULL) {
+                psMetadataAdd(timeMetadata, PS_LIST_TAIL, strcat(metadataTableNames[j], "Table"),
+                              PS_DATA_LOOKUPTABLE, NULL, table);
+                foundTable = true;
+            } else if(foundTable==false && j==numTables-1) {
+                psError(PS_ERR_BAD_PARAMETER_VALUE, no_problem,
+                        _("Incorrect number of table files entered. Found: %d. Expected: %d."), j, numTables);
+                no_problem = false;
+            }
+        }
+
+        psFree(fullTableName);
+        psFree(tableName);
+        psFree(tableFormat);
+        psFree(table);
+        i++;
+    }
+
+    p_psMemAllocatePersistent(initialPersistence);
+
+    if(numTables != i) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, no_problem, _("Incorrect number of table files entered. Found: %d. Expected: %d."), i, numTables);
+    }
+
+    psFree(tableDir);
+    psFree(tableNames);
+    psFree(tablesFrom);
+    psFree(tablesTo);
+    psFree(tablesIndex);
+    psFree(tableFormats);
+
+    return no_problem;
+}
+
+bool p_psTimeFinalize(void)
+{
+    if(timeMetadata != NULL) {
+        psFree(timeMetadata);
+        timeMetadata = NULL;
+    }
+
+    return true;
+}
+
+static void timeFree(psTime *outTime)
+{
+    // There are non dynamic allocated items
+}
+
+psTime* psTimeAlloc(psTimeType type)
+{
+    psTime *outTime = NULL;
+
+    // Error checks
+    if(type!=PS_TIME_TAI && type!=PS_TIME_UTC && type!=PS_TIME_UT1 &&
+            type!=PS_TIME_TT) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified type, %d, is not supported."),
+                type);
+        return NULL;
+    }
+
+    // Allocate memory for structure
+    outTime = (psTime*)psAlloc(sizeof(psTime));
+    psMemSetDeallocator(outTime, (psFreeFunc)timeFree);
+    // Initialize members
+    outTime->sec = 0;
+    outTime->nsec = 0;
+    outTime->type = type;
+    outTime->leapsecond = false;
+
+    return outTime;
+}
+
+
+bool psMemCheckTime(psPtr ptr)
+{
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)timeFree );
+}
+
+
+psTime* psTimeGetNow(psTimeType type)
+{
+    struct timeval now;
+    psTime *time = NULL;
+
+    // Allocate psTime struct
+    time = psTimeAlloc(type);
+
+    // Verify time structure allocated
+    if(time == NULL) {
+        return NULL;
+    }
+
+    // Get the system time
+    //    if (gettimeofday(&now, (struct timezone *)0) == -1) {
+    if (gettimeofday(&now, 0) == -1) {
+        psError(PS_ERR_OS_CALL_FAILED, true,
+                _("Failed to determine the current time from gettimeofday function."));
+        return NULL;
+    }
+
+    // Convert timeval time to psTime
+    time->sec = now.tv_sec;
+    time->nsec = now.tv_usec*1000;
+
+    // Add most leapseconds to UTC time to get TAI time if necessary
+    if(type == PS_TIME_TAI) {
+        time->sec += p_psTimeGetTAIDelta(time);
+    }
+
+    return time;
+}
+
+static psTime* convertTimeTAIUTC(psTime* time)
+{
+    psF64  deltaTAI     = 0.0;
+    psS64  deltaSec     = 0;
+    psU32  deltaNsec    = 0;
+    psF64  deltaUTC     = 0.0;
+
+    // Determine delta to convert between UTC and TAI
+    deltaTAI = p_psTimeGetTAIDelta(time);
+    deltaSec = (psS64)(deltaTAI);
+    deltaNsec = (psU32)((deltaTAI - (psF64)deltaSec) * 1e9);
+
+    // Determine seconds
+    time->sec -= deltaSec;
+
+    // Check for underflow in nsec
+    if(deltaNsec > time->nsec) {
+        // Borrow second
+        time->nsec += 1e9;
+        time->sec--;
+    }
+
+    // Determine nsec
+    time->nsec -= deltaNsec;
+
+    // Check for overflow in nsec
+    if(time->nsec >= 1e9) {
+        time->nsec -= 1e9;
+        time->sec++;
+    }
+
+    // Set new type
+    time->type = PS_TIME_UTC;
+
+    // Check if leapsecond present in delta
+    deltaUTC = p_psTimeGetTAIDelta(time);
+    if(fabs(deltaTAI-deltaUTC) >= 1.0) {
+        time->sec++;
+    }
+
+    return time;
+}
+
+static psTime* convertTimeUTCTAI(psTime* time)
+{
+    psF64  delta     = 0.0;
+    psS64  deltaSec  = 0;
+    psU32  deltaNsec = 0;
+
+    // Determine delta to convert between UTC and TAI
+    delta = p_psTimeGetTAIDelta(time);
+
+    deltaSec = (psS64)(delta);
+    deltaNsec = (psU32)((delta - (psF64)deltaSec) * 1e9);
+
+    // Determine seconds
+    time->sec += deltaSec;
+
+    // Determine nsec
+    time->nsec += deltaNsec;
+
+    // Check for overflow in nsec
+    if(time->nsec >= 1e9) {
+        time->nsec -= 1e9;
+        time->sec++;
+    }
+
+    // Set new type
+    time->type = PS_TIME_TAI;
+
+    //XXX: Set leapseconds to TRUE
+    //    time->leapsecond = true;
+    return time;
+}
+
+static psTime* convertTimeTAITT(psTime* time)
+{
+    // Add TT offset
+    time->sec += TAI_TT_OFFSET_SECONDS;
+    time->nsec += TAI_TT_OFFSET_NANOSECONDS;
+
+    // Check for overflow in nsec
+    if(time->nsec >= 1e9) {
+        time->nsec -= 1e9;
+        time->sec++;
+    }
+
+    // Set new type
+    time->type = PS_TIME_TT;
+
+    return time;
+}
+
+static psTime* convertTimeTTTAI(psTime* time)
+{
+    // Subtract TT offset
+    time->sec -= TAI_TT_OFFSET_SECONDS;
+
+    // Check for nsec underflow
+    if(TAI_TT_OFFSET_NANOSECONDS > time->nsec) {
+        // Borrow second
+        time->sec--;
+        time->nsec += 1e9;
+    }
+    time->nsec -= TAI_TT_OFFSET_NANOSECONDS;
+
+    // Check for overflow in nsec
+    if(time->nsec >= 1e9) {
+        time->nsec -= 1e9;
+        time->sec++;
+    }
+
+    // Set new type
+    time->type = PS_TIME_TAI;
+
+    return time;
+}
+
+static psTime* convertTimeUTCUT1(psTime* time)
+{
+    psS64   ut1utc  = 0;
+
+    // Get UT1-UTC value
+    ut1utc = (psS64)(psTimeGetUT1Delta(time,PS_IERS_A) * 1e9);
+
+    // Since UTC is within 0.9 sec of UT1 then nsec member is the member affected
+    if((ut1utc < 0) && (abs(ut1utc) > time->nsec)) {
+        // Borrow from sec
+        time->sec--;
+        if(time->leapsecond) {
+            time->leapsecond = false;
+        } else {
+            time->leapsecond = psTimeIsLeapSecond(time);
+        }
+        // Add to nsec
+        time->nsec += 1e9;
+    }
+    time->nsec += ut1utc;
+
+    // Check for overflow in nsec
+    if(time->nsec >= 1e9) {
+        time->nsec -= 1e9;
+        time->sec++;
+        if(time->leapsecond) {
+            time->leapsecond = false;
+            time->sec--;
+        } else {
+            time->leapsecond = psTimeIsLeapSecond(time);
+        }
+    }
+
+    // Set new type
+    time->type = PS_TIME_UT1;
+
+    return time;
+}
+
+psTime* psTimeConvert(psTime *time,
+                      psTimeType type)
+{
+    // Error checks
+    PS_ASSERT_PTR_NON_NULL(time,NULL);
+    PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1), NULL);
+
+    // If the input type is UT1 then return time and generate error message
+    if(time->type == PS_TIME_UT1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE,true,"Cannot convert from UT1 time type");
+        return NULL;
+    }
+
+    // If the time to convert to is the same as psTime the return time
+    if (time->type == type) {
+        return time;
+    }
+
+    // Convert from TAI to UTC, TT, UT1
+    if(time->type == PS_TIME_TAI) {
+        // Convert from TAI to UTC
+        if(type == PS_TIME_UTC) {
+            time = convertTimeTAIUTC(time);
+            // Convert from TAI to TT
+        } else if(type == PS_TIME_TT) {
+            time = convertTimeTAITT(time);
+            // Convert from TAI to UT1
+        } else if(type == PS_TIME_UT1) {
+            // Convert to UTC first
+            time = convertTimeTAIUTC(time);
+            // Convert UTC to UT1
+            time = convertTimeUTCUT1(time);
+            // Convert from TAI to unknown time type
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Specified type, %d, is not supported."), type);
+            return NULL;
+        }
+        // Convert from TT to TAI, UTC, UT1
+    } else if(time->type == PS_TIME_TT) {
+        // Convert from TT to UTC
+        if(type == PS_TIME_UTC) {
+            // Convert to TAI time first
+            time = convertTimeTTTAI(time);
+            // Convert from TAI to UTC
+            time = convertTimeTAIUTC(time);
+            // Convert from TT to TAI
+        } else if(type == PS_TIME_TAI) {
+            time = convertTimeTTTAI(time);
+            // Convert from TT to UT1
+        } else if(type == PS_TIME_UT1) {
+            // Convert to UTC first
+            // Convert to TAI time first
+            time = convertTimeTTTAI(time);
+            // Convert from TAI to UTC
+            time = convertTimeTAIUTC(time);
+            // Convert from UTC to UT1
+            time = convertTimeUTCUT1(time);
+            // Convert from TT to unknown time type
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Specified type, %d, is not supported."), type);
+            return NULL;
+        }
+        // Convert from UTC to TAI, TT, UT1
+    } else if(time->type == PS_TIME_UTC) {
+        // Convert UTC to TAI
+        if(type == PS_TIME_TAI) {
+            time = convertTimeUTCTAI(time);
+            // Convert UTC to TT
+        } else if(type == PS_TIME_TT) {
+            // Convert to TAI time first
+            time = convertTimeUTCTAI(time);
+            // Convert TAI to TT
+            time = convertTimeTAITT(time);
+            // Convert UTC to UT1
+        } else if(type == PS_TIME_UT1) {
+            time = convertTimeUTCUT1(time);
+            // Convert UTC to unknown time type
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Specified type, %d, is not supported."), type);
+            return NULL;
+        }
+        // Convert unknown time type
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Specified type, %d, is not supported."), time->type);
+        return NULL;
+    }
+
+    return time;
+}
+
+double psTimeToLMST(psTime *time,
+                    double longitude)
+{
+    psF64  jdTdtDays    =  0.0;
+    psF64  jdUt1Days    =  0.0;
+    psF64  mjdUt1Days   =  0.0;
+    psF64  lmstRad      =  0.0;
+    psF64  fracDays     =  0.0;
+    psF64  gmstRad      =  0.0;
+    psF64  t            =  0.0;
+    psF64  tu           =  0.0;
+    psF64  const1       =  24110.5493771;
+    psF64  const2       =  8639877.3173760;
+    psF64  const3       =  307.4771600;
+    psF64  const4       =  0.0931118;
+    psF64  const5       = -0.0000062;
+    psF64  const6       =  0.0000013;
+    psTime *tdtTime     = NULL;
+    psTime *ut1Time     = NULL;
+
+    // Error checks
+    PS_ASSERT_PTR_NON_NULL(time,NAN);
+    PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NAN);
+
+    // Verify input time is not in UT1 seconds
+    if(time->type == PS_TIME_UT1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE,true,_("Specified type, %d, is incorrect."),time->type);
+        return NAN;
+    }
+
+    // Determine time reference to TT
+    tdtTime = psTimeAlloc(time->type);
+    tdtTime->sec = time->sec;
+    tdtTime->nsec = time->nsec;
+    tdtTime->leapsecond = time->leapsecond;
+    tdtTime = psTimeConvert(tdtTime,PS_TIME_TT);
+
+    // Determine time reference to UT1
+    ut1Time = psTimeAlloc(time->type);
+    ut1Time->sec = time->sec;
+    ut1Time->nsec = time->nsec;
+    ut1Time->leapsecond = time->leapsecond;
+    ut1Time = psTimeConvert(ut1Time,PS_TIME_UT1);
+
+    // Calculate UT1 as Julian Centuries since J2000.0
+    jdUt1Days = psTimeToJD(ut1Time);
+    mjdUt1Days = psTimeToMJD(ut1Time);
+    t = (jdUt1Days - 2451545.0)/36525.0;
+
+    // Calculate TDT as Julian centuries since J2000.0
+    jdTdtDays = psTimeToJD(tdtTime);
+    tu = (jdTdtDays - 2451545.0)/36525.0;
+
+    // Calculate fractional part of MJD
+    fracDays = fmod(mjdUt1Days, 1.0);
+
+    // Calculate Greenwich Mean Sidereal Time (GMST) in radians.
+    // Equation set up to minimize multiplications.
+    gmstRad = fracDays*TWOPI
+              + (const1+const2*tu+t*(const3+t*(const4+t*(const5+const6*t))))*S2R;
+
+    // Place GMST between 0 and 2*pi
+    gmstRad = fmod(gmstRad, TWOPI);
+
+    // Calculate Local Mean Sidereal Time (LMST) in radians
+    lmstRad = gmstRad + longitude;
+
+    // Free temporary structs
+    psFree(ut1Time);
+    psFree(tdtTime);
+
+    return lmstRad;
+}
+
+double psTimeGetUT1Delta(const psTime *time,
+                         psTimeBulletin bulletin)
+{
+    psU32              nTables               = 2;
+    psF64              mjd                   = 0.0;
+    psF64              result                = 0.0;
+    psU64              tableColumn           = 0;
+    psF64              dut2ut1               = 0.0;
+    psF64              t                     = 0.0;
+    psVector*          dut                   = NULL;
+    psMetadataItem*    tableMetadataItem     = NULL;
+    psLookupStatusType status                = PS_LOOKUP_SUCCESS;
+    char*              metadataTableNames[2] = {"dailyTable",  "finalsTable"};
+
+    // Error checks
+    PS_ASSERT_PTR_NON_NULL(time,NAN);
+    PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NAN);
+
+    // Check for invalid bulletin specified
+    if((bulletin != PS_IERS_A) && (bulletin != PS_IERS_B)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE,true,"Invalid bulletin specified %d",bulletin);
+        return NAN;
+    }
+
+    // Check if psTime tables are already loaded
+    if(!p_psTimeInit(p_psTimeConfigFilename(NULL))) {
+        psError(PS_ERR_UNKNOWN, true, "failed to init time tables.");
+        return NAN;
+    }
+
+    // Set lookup table column based on Bullentin
+    if(bulletin == PS_IERS_A) {
+        tableColumn = 3;
+    } else {
+        tableColumn = 6;
+    }
+
+    // Attempt to find value through table lookup and interpolation
+    mjd = psTimeToMJD(time);
+    result = p_psTimeSearchTables(mjd,tableColumn,metadataTableNames,nTables,&status);
+
+    // Value could not be found through table lookup and interpolation
+    if(status == PS_LOOKUP_PAST_TOP) {
+
+        // Date too early for tables. Get default time delta value from metadata, and issue warning.
+        psLogMsg("psLib.astro", PS_LOG_WARN,_("Specified psTime predates (%g) all tables of %s information."),mjd,"UT1-UTC");
+
+        // Lookup value from time metadata loaded from pslib.config
+        tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.before.dut");
+        if(tableMetadataItem == NULL) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                    "psLib.time.before.dut");
+            return NAN;
+        }
+        result = tableMetadataItem->data.F64;
+
+    } else if(status == PS_LOOKUP_PAST_BOTTOM) {
+        /* Date too late for tables. Issue warning and use following formulae for predicting
+           ahead of the most recent available table entry.
+             ut1-utc = [0] + [1]*(MJD - [2]) - (ut2-ut1)
+             [0, 1, 2] = @psLib.time.predict.dut
+             ut2-ut1 = 0.022 sin(2*pi*t) - 0.012 cos(2*pi*t) - 0.006 sin(4*pi*t) + 0.007 cos(4*pi*t)
+             t = 2000.0 + (MJD - 51544.03)/365.2422
+        */
+        // Generate warning of postdate information
+        psLogMsg("psLib.astro", PS_LOG_WARN,_("Specified psTime postdates (%g) all tables of %s information."), mjd, "UT1-UTC");
+
+        // Lookup values to calculate prediction
+        tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.predict.dut");
+        if(tableMetadataItem == NULL) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                    "psLib.time.predict.dut");
+            return NAN;
+        }
+        dut = (psVector*)tableMetadataItem->data.V;
+        PS_ASSERT_PTR_NON_NULL(dut,NAN);
+
+        // Calculate predication of future UT1-UTC
+        t = 2000.0 + (mjd - 51544.03)/365.2422;
+        dut2ut1 = 0.022*sin(TWOPI*t) - 0.012*cos(TWOPI*t) - 0.006*sin(4.0*M_PI*t) + 0.007*cos(4.0*M_PI*t);
+        result = dut->data.F64[0] + dut->data.F64[1]*(mjd - dut->data.F64[2]) - dut2ut1;
+
+    } else if(status != PS_LOOKUP_SUCCESS) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed time table interpolation."));
+        return NAN;
+    }
+
+    return result;
+}
+
+static double DMOD(double x, double y)
+{
+    double value = x - y * trunc(x/y);
+    return value;
+}
+
+psTime *psTime_TideUT1Corr(const psTime *time)
+{
+    PS_ASSERT_PTR_NON_NULL(time, NULL);
+    psTime *out = NULL;
+    //Also see psEOC_PolarTideCorr for more info.
+
+    // Convert psTime to MJD
+    double MJD = psTimeToMJD(time);
+    if (isnan(MJD)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "Time conversion to MJD failed.  Invalid input time.\n");
+        return NULL;
+    }
+
+    // Calculate number of Julian centuries since 2000
+    double RJD = MJD;
+
+    //Formula comes from fortran reference
+    //DMOD in fortran ref. = double remainder -> x - y * trunc(x/y)
+    double T, L, LPRIME, CAPF, CAPD, OMEGA, THETA, CORZ;
+    double ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8;
+    double T2, T3, T4;
+    T = (RJD - 51544.5) / 36525.0;
+    T2 = T*T;
+    T3 = T*T*T;
+    T4 = T*T*T*T;
+    L = -0.0002447 * T4 + 0.051635 * T3 + 31.8792 * T2 + 1717915923.2178 * T + 485868.249036;
+    L = DMOD(L, 1296000.0);
+    LPRIME = -0.00001149 * T4 - 0.000136 * T3 - 0.5532 * T2 + 129596581.0481 * T + 1287104.79305;
+    LPRIME = DMOD(LPRIME, 1296000.0);
+    CAPF = 0.00000417 * T4 - 0.001037 * T3 - 12.7512 * T2 + 1739527262.8478 * T + 335779.526232;
+    CAPF = DMOD(CAPF, 1296000.0);
+    CAPD = -0.00003169 * T4 + 0.006593 * T3 - 6.3706 * T2 + 1602961601.209 * T + 1072260.70369;
+    CAPD = DMOD(CAPD, 1296000.0);
+    OMEGA = -0.00005939 * T4 + 0.007702 * T3 + 7.4722 * T2 - 6962890.2665 * T + 450160.398036;
+    OMEGA = DMOD(OMEGA, 1296000.0);
+    THETA = (67310.54841 + (876600.0 * 3600.0 + 8640184.812866) * T + 0.093104 * T2 -
+             6.2e-6 * T3) * 15.0 + 648000.0;
+    ARG7 = DMOD((-L - 2.0 * CAPF - 2.0 * OMEGA + THETA) * M_PI / 648000.0, 2.0 * M_PI)
+           - M_PI / 2.0;
+    ARG1 = DMOD((-2.0 * CAPF - 2.0 * OMEGA + THETA) * M_PI / 648000.0, 2.0 * M_PI) - M_PI / 2.0;
+    ARG2 = DMOD((-2.0 * CAPF + 2.0 * CAPD - 2.0 * OMEGA + THETA) * M_PI / 648000.0, 2.0 * M_PI)
+           - M_PI / 2.0;
+    ARG3 = DMOD(THETA * M_PI / 648000.0, 2.0 * M_PI) - M_PI / 2.0;
+    ARG4 = DMOD((-L - 2.0 * CAPF - 2.0 * OMEGA + 2.0 * THETA) * M_PI / 648000.0, 2.0 * M_PI);
+    ARG5 = DMOD((-2.0 * CAPF - 2.0 * OMEGA + 2.0 * THETA) * M_PI / 648000.0, 2.0 * M_PI);
+    ARG6 = DMOD((-2.0 * CAPF + 2.0 * CAPD - 2.0 * OMEGA + 2.0 * THETA) * M_PI / 648000.0,
+                2.0 * M_PI);
+    ARG8 = DMOD((2.0 * THETA) * M_PI / 648000.0, 2.0 * M_PI);
+    CORZ =  0.0245 * sin(ARG7) + 0.0503 * cos(ARG7)
+            +0.1210 * sin(ARG1) + 0.1605 * cos(ARG1)
+            +0.0286 * sin(ARG2) + 0.0516 * cos(ARG2)
+            +0.0864 * sin(ARG3) + 0.1771 * cos(ARG3)
+            -0.0380 * sin(ARG4) - 0.0154 * cos(ARG4)
+            -0.1617 * sin(ARG5) - 0.0720 * cos(ARG5)
+            -0.0759 * sin(ARG6) - 0.0004 * cos(ARG6)
+            -0.0196 * sin(ARG8) - 0.0038 * cos(ARG8);
+    CORZ = CORZ * 0.1e-3;
+
+    double timeCheck = (double)(time->sec) + (double)(1e-9*time->nsec);
+    if ( (timeCheck + CORZ) < 0.0 ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Invalid time for Tide Correction.\n");
+        return NULL;
+    }
+    out = psTimeAlloc(time->type);
+    *out = *time;
+    if (out->type != PS_TIME_UT1) {
+        out = psTimeConvert(out, PS_TIME_UT1);
+    }
+    //see if corrections include seconds or just nano-seconds
+    //nano-seconds must be converted (scaled) to integer values & total cannot be negative
+    if (fabs(CORZ) > 1.0) {
+        int sec = (int)CORZ;
+        out->sec += sec;
+        int nsec = (int)((CORZ - sec)*1e9);
+        out->nsec += nsec;
+    } else {
+        int nsec = out->nsec + (int)(CORZ * 1e9);
+        if (nsec < 0) {
+            out->sec += -1;
+            out->nsec = (int)(1e9) + nsec;
+        } else {
+            out->nsec = nsec;
+        }
+    }
+    return out;
+}
+
+psSphere* p_psTimeGetPoleCoords(const psTime* time)
+{
+    psU32 nTables = 3;
+    psF64 x = 0.0;
+    psF64 y = 0.0;
+    psF64 mjd = 0.0;
+    psF64 a = 0.0;
+    psF64 c = 0.0;
+    psF64 mjdPred = 0.0;
+    psSphere* output = NULL;
+    psLookupStatusType xStatus = PS_LOOKUP_SUCCESS;
+    psLookupStatusType yStatus = PS_LOOKUP_SUCCESS;
+    psMetadataItem *tableMetadataItem = NULL;
+    char *metadataTableNames[3] = {"dailyTable", "eopcTable",  "finalsTable"};
+    psVector *xp = NULL;
+    psVector *yp = NULL;
+
+    // Error checks
+    PS_ASSERT_PTR_NON_NULL(time,NULL);
+    PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NULL);
+
+    if(time->type != PS_TIME_TAI) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Specified type, %d, is incorrect."), time->type);
+        return NULL;
+    }
+
+    // Check if psTime tables are already loaded
+    if(!p_psTimeInit(p_psTimeConfigFilename(NULL))) {
+        psError(PS_ERR_UNKNOWN, true, "failed to init time tables.");
+        return NULL;
+    }
+
+    // Attempt to find value through table lookup and interpolation
+    mjd = psTimeToMJD(time);
+    //    x = p_psTimeSearchTables(mjd, 0, &xStatus, metadataTableNames, nTables);
+    x = p_psTimeSearchTables(mjd, 0, metadataTableNames, nTables,&xStatus);
+    //    y = p_psTimeSearchTables(mjd, 0, &yStatus, metadataTableNames, nTables);
+    y = p_psTimeSearchTables(mjd, 0, metadataTableNames, nTables,&yStatus);
+
+    // Value could not be found through table lookup and interpolation
+    if(xStatus==PS_LOOKUP_PAST_TOP && yStatus==PS_LOOKUP_PAST_TOP) {
+
+        // Date too earlier for tables. Get default polar coodinate values from metadata, and issue warning.
+        #if 0
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Specified psTime predates (%g) all tables of %s information."), mjd, "polar motion");
+        return NULL;
+        #else
+
+        psLogMsg("psLib.astro", PS_LOG_ERROR, _("Specified psTime predates (%g) all tables of %s information."), mjd, "polar motion");
+        #endif
+
+        tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.before.xp");
+        if(tableMetadataItem == NULL) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    _("Failed find '%s' in time metadata."), "psLib.time.before.xp");
+            return NULL;
+        }
+        x = tableMetadataItem->data.F64;
+
+        tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.before.yp");
+        if(tableMetadataItem == NULL) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."), "psLib.time.before.yp");
+            return NULL;
+        }
+        y = tableMetadataItem->data.F64;
+
+    } else if(xStatus==PS_LOOKUP_PAST_BOTTOM && yStatus==PS_LOOKUP_PAST_BOTTOM) {
+
+        /* Date too late for tables. Issue warning and use following formulae for predicting
+           ahead of the most recent available table entry.
+              x = [0] + [1]*cos a + [2]*sin a + [3]*cos c + [4]*sin c
+              [0], [1], [2], [3] = @psLib.time.predict.xp
+              y = [0] + [1]*cos a + [2]*sin a + [3]*cos c + [4]*sin c
+              [0], [1], [2], [3] = @psLib.time.predict.yp
+              a = 2*pi*(mjd - pslib.time.predict.mjd)/365.25
+              c = 2*pi*(mjd - pslib.time.predict.mjd)/435.0
+        */
+        #if 0
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified psTime postdates (%g) all tables of %s information."), mjd, "polar motion");
+        return NULL;
+        #else
+
+        psLogMsg("psLib.astro", PS_LOG_ERROR,
+                 _("Specified psTime postdates (%g) all tables of %s information."), mjd, "polar motion");
+        #endif
+
+        // Get predicted MJD
+        tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.predict.mjd");
+        if(tableMetadataItem == NULL) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."),
+                    "psLib.time.predict.mjd");
+            return NULL;
+        }
+        mjdPred = tableMetadataItem->data.F64;
+
+        // Get xp
+        tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.predict.xp");
+        if(tableMetadataItem == NULL) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."), "psLib.time.predict.xp");
+            return NULL;
+        }
+        xp = (psVector*)tableMetadataItem->data.V;
+        PS_ASSERT_PTR_NON_NULL(xp,NULL);
+
+        // Get yp
+        tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.predict.yp");
+        if(tableMetadataItem == NULL) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."), "psLib.time.predict.yp");
+            return NULL;
+        }
+        yp = (psVector*)tableMetadataItem->data.V;
+        PS_ASSERT_PTR_NON_NULL(yp,NULL);
+
+        // Calculate "a" and "c" constants
+        a = TWOPI*(mjd - mjdPred)/365.25;
+        c = TWOPI*(mjd - mjdPred)/435.0;
+
+        // Calculate x and y polar coordinates
+        x = xp->data.F64[0] +
+            xp->data.F64[1]*cos(a) +
+            xp->data.F64[2]*sin(a) +
+            xp->data.F64[3]*cos(c) +
+            xp->data.F64[4]*sin(c);
+
+        y = yp->data.F64[0] +
+            yp->data.F64[1]*cos(a) +
+            yp->data.F64[2]*sin(a) +
+            yp->data.F64[3]*cos(c) +
+            yp->data.F64[4]*sin(c);
+
+    } else if(xStatus!=PS_LOOKUP_SUCCESS || yStatus!=PS_LOOKUP_SUCCESS) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed time table interpolation."));
+        return NULL;
+    }
+
+    // Create output sphere and convert arcsec to radians (i.e. x/60/60*PS_PI/180)
+    output = psAlloc(sizeof(psSphere));
+    output->r = x * M_PI / 648000.0;
+    output->d = y * M_PI / 648000.0;
+
+    return output;
+}
+
+psF64 p_psTimeGetTAIDelta(const psTime *time)
+{
+    psF64 jd = 0.0;
+    psF64 mjd = 0.0;
+    psF64 out = 0.0;
+    psF64 const1 = 0.0;
+    psF64 const2 = 0.0;
+    psF64 const3 = 0.0;
+    psLookupTable* table = NULL;
+    psMetadataItem *tableMetadataItem = NULL;
+    psVector *results = NULL;
+
+    // Error checks
+    PS_ASSERT_PTR_NON_NULL(time,NAN);
+    PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NAN);
+
+    // Check if psTime tables are loaded/loadable
+    if (!p_psTimeInit(p_psTimeConfigFilename(NULL))) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed to open file %s."),
+                p_psTimeConfigFilename(NULL));
+        return NAN;
+    }
+
+    // Get table from metadata
+    tableMetadataItem = psMetadataLookup(timeMetadata, "taiTable");
+    if(tableMetadataItem == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed find '%s' in time metadata."), "taiTable");
+        return NAN;
+    }
+    table = (psLookupTable*)tableMetadataItem->data.V;
+    PS_ASSERT_PTR_NON_NULL(table,0);
+
+    // Determine Julian and modified Julian dates used in table lookup and time delta calculation
+    if(time->sec < 0) {
+        // psTime earlier than epoch
+        jd = time->sec / SEC_PER_DAY - time->nsec / NSEC_PER_DAY + JD_EPOCH_OFFSET;
+        mjd = time->sec / SEC_PER_DAY - time->nsec / NSEC_PER_DAY + MJD_EPOCH_OFFSET;
+    } else {
+        // psTime greater than epoch
+        jd = time->sec / SEC_PER_DAY + time->nsec / NSEC_PER_DAY + JD_EPOCH_OFFSET;
+        mjd = time->sec / SEC_PER_DAY + time->nsec / NSEC_PER_DAY + MJD_EPOCH_OFFSET;
+    }
+
+    // Set ceiling of the julian date to the last entry in the lookup table
+    if(table->validTo < jd) {
+        jd = table->validTo;
+    }
+
+    // Interpolation of look up table
+    results = psLookupTableInterpolateAll(table, jd);
+
+    // Check for successful interpolation
+    if(results == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed time table interpolation."));
+        return NAN;
+    }
+
+    // Set constants from table
+    const1 = results->data.F64[1];
+    const2 = results->data.F64[2];
+    const3 = results->data.F64[3];
+
+    // If const3 not equal to zero solve for difference else floor of const1
+    if(fabs(const3-0.0) > FLT_EPSILON) {
+        out = const1 + (mjd - const2) * const3;
+    } else {
+        out = floor(const1);
+    }
+
+    psFree(results);
+
+    return out;
+}
+
+long psTimeLeapSecondDelta(const psTime *time1,
+                           const psTime *time2)
+{
+    psS64 diff = 0;
+
+    // Error checks
+    PS_ASSERT_PTR_NON_NULL(time1,0);
+    PS_ASSERT_PTR_NON_NULL(time2,0);
+    PS_ASSERT_INT_WITHIN_RANGE(time1->nsec,0,(psU32)((1e9)-1),0);
+    PS_ASSERT_INT_WITHIN_RANGE(time2->nsec,0,(psU32)((1e9)-1),0);
+    diff = abs((psS64)p_psTimeGetTAIDelta((psTime*)time1)-(psS64)p_psTimeGetTAIDelta((psTime*)time2));
+    return diff;
+}
+
+bool psTimeIsLeapSecond(const psTime* utc)
+{
+    psTime*    prevUtc     = NULL;
+    bool     returnValue = false;
+
+    // Check for valid time
+    PS_ASSERT_PTR_NON_NULL(utc,false);
+
+    // Verify time is UTC type
+    if(utc->type != PS_TIME_UTC) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE,true,_("Specified type, %d, is incorrect."),utc->type);
+        return false;
+    }
+
+    // Allocate time to hold utc - 1 second
+    prevUtc = psTimeAlloc(PS_TIME_UTC);
+    prevUtc->sec = utc->sec - 1;
+
+    // Check the absolute difference between the two times for leapsecond
+    if(psTimeLeapSecondDelta(utc,prevUtc) >= 1.0) {
+        returnValue = true;
+    } else {
+        returnValue = false;
+    }
+
+    // Free prevUtc
+    psFree(prevUtc);
+
+    return returnValue;
+}
+
+double psTimeToJD(const psTime *time)
+{
+    psF64 jd = NAN;
+
+    // Error checks
+    PS_ASSERT_PTR_NON_NULL(time,NAN);
+    PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NAN);
+
+    psTime *time2 = psTimeCopy(time);
+    //XXX: ADD says that this formula works only for PS_TIME_TAI, so adding the following:
+    if (time->type == PS_TIME_UTC || time->type == PS_TIME_TT) {
+        time2 = psTimeConvert(time2, PS_TIME_TAI);
+    }
+
+    // Julian date conversion
+    if(time2->sec < 0) {
+        // psTime earlier than epoch
+        jd = time2->sec / SEC_PER_DAY - time2->nsec / NSEC_PER_DAY + JD_EPOCH_OFFSET;
+    } else {
+        // psTime greater than epoch
+        jd = time2->sec / SEC_PER_DAY + time2->nsec / NSEC_PER_DAY + JD_EPOCH_OFFSET;
+    }
+
+    psFree(time2);
+    return jd;
+}
+
+double psTimeToMJD(const psTime *time)
+{
+    psF64 mjd = NAN;
+
+    // Error checks
+    PS_ASSERT_PTR_NON_NULL(time,NAN);
+    PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NAN);
+    psTime *time2 = psTimeCopy(time);
+    //XXX: ADD says that this formula works only for PS_TIME_TAI, so adding the following:
+    if (time->type == PS_TIME_UTC || time->type == PS_TIME_TT) {
+        time2 = psTimeConvert(time2, PS_TIME_TAI);
+    }
+
+    // Modified Julian date conversion
+    if(time2->sec < 0) {
+        // psTime earlier than epoch
+        mjd = time2->sec / SEC_PER_DAY - time2->nsec / NSEC_PER_DAY + MJD_EPOCH_OFFSET;
+    } else {
+        // psTime greater than epoch
+        mjd = time2->sec / SEC_PER_DAY + time2->nsec / NSEC_PER_DAY + MJD_EPOCH_OFFSET;
+    }
+    psFree(time2);
+    return mjd;
+}
+
+psString psTimeToISO(const psTime *time)
+{
+    psS32 ds = 0;
+    char *timeString = NULL;
+    char *tempString = NULL;
+
+    // Error checks
+    PS_ASSERT_PTR_NON_NULL(time,NULL);
+    PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NULL);
+
+    // Check valid year range
+    PS_ASSERT_S64_WITHIN_RANGE(time->sec, (psS64)YEAR_0000_SEC, (psS64)YEAR_9999_SEC, NULL);
+
+    // Allocate temp strings
+    tempString = psAlloc(MAX_TIME_STRING_LENGTH);
+    timeString = psAlloc(MAX_TIME_STRING_LENGTH);
+
+    // Convert nanoseconds to decaseconds
+    ds = time->nsec / 100000000;
+
+    // tmTime variable is statically allocated, no need to free
+    struct tm *tmTime = psTimeToTM(time);
+
+    // Converts psTime to YYYY-MM-DDThh:mm:ss.sss in string form
+    if (!strftime(tempString, MAX_TIME_STRING_LENGTH, "%Y-%m-%dT%H:%M:%S", tmTime)) {
+        psError(PS_ERR_OS_CALL_FAILED, true, _("Failed to convert a time via strftime function."));
+        return NULL;
+    }
+    psFree(tmTime);
+
+    // Check if time is UTC and leapsecond
+    if(((time->type==PS_TIME_UTC)||(time->type==PS_TIME_UT1)) && (time->leapsecond)) {
+        // Modify second to be 60
+        tempString[17] = '6';
+        tempString[18] = '0';
+    }
+
+    // Create string with milliseconds
+    if (snprintf(timeString, MAX_TIME_STRING_LENGTH, "%s.%1d", tempString, ds) < 0) {
+        psError(PS_ERR_OS_CALL_FAILED, true, _("Failed to append millisecond to time string with snprintf function."));
+        return NULL;
+    }
+    psFree(tempString);
+
+    return timeString;
+}
+
+struct tm *psTimeToTM(const psTime *time)
+{
+    PS_ASSERT_PTR_NON_NULL(time,NULL);
+
+    // XXX is it safe to assume that time_t is always an integer value?
+    time_t sec = time->sec;
+
+    // if this is NOT a UTC time then we want to make sure tm.tm_sec does not
+    // end up being set to 60
+    if (!time->type == PS_TIME_UTC)
+    {
+        // If leapsecond use previous day
+        if (time->leapsecond) {
+            sec--;
+        }
+    }
+
+    // struct tm can handle leapseconds
+    struct tm *tmTime = psAlloc(sizeof(struct tm));
+    gmtime_r(&sec, tmTime);
+
+    return tmTime;
+}
+
+struct timeval* psTimeToTimeval(const psTime *time)
+{
+    struct timeval  *timevalTime = NULL;
+
+    // Error checks
+    PS_ASSERT_PTR_NON_NULL(time,NULL);
+    PS_ASSERT_INT_WITHIN_RANGE(time->sec,0,INT32_MAX,NULL);
+    PS_ASSERT_INT_WITHIN_RANGE(time->nsec,0,(psU32)((1e9)-1),NULL);
+
+    // Allocate structure timeval
+    timevalTime = (struct timeval*)psAlloc(sizeof(struct timeval));
+
+    // Set structure members
+    timevalTime->tv_sec = time->sec;
+    timevalTime->tv_usec = time->nsec / 1000;
+
+    return timevalTime;
+}
+
+psTime* psTimeFromJD(double jd)
+{
+    psF64 days = 0.0;
+    psF64 seconds = 0.0;
+    psTime *outTime = NULL;
+
+    // Allocate psTime struct
+    outTime = psTimeAlloc(PS_TIME_TAI);
+
+    // Julian date conversion courtesy of Eugene Magnier
+    days = jd - 2440587.5;
+    seconds = days * SEC_PER_DAY;
+    if(seconds < 0.0) {
+        outTime->nsec = (seconds - (psS64)seconds) * -1000000000.0;  // psTime earlier than epoch
+    } else {
+        outTime->nsec = (seconds - (psS64)seconds) * 1000000000.0;   // psTime greater than epoch
+    }
+    outTime->sec = seconds;
+
+    // Error check
+    PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0,(psU32)((1e9)-1),outTime);
+
+    return outTime;
+}
+
+psTime* psTimeFromMJD(double mjd)
+{
+    psF64 days = 0.0;
+    psF64 seconds = 0.0;
+    psTime *outTime = NULL;
+
+    // Allocate psTime struct
+    outTime = psTimeAlloc(PS_TIME_TAI);
+
+    // Modified Julian date conversion courtesy of Eugene Magnier
+    days = mjd - 40587.0;
+    seconds = days * SEC_PER_DAY;
+
+    if(seconds < 0.0) {
+        outTime->nsec = (seconds - (psS64)seconds) * -1000000000.0;  // psTime earlier than epoch
+    } else {
+        outTime->nsec = (seconds - (psS64)seconds) * 1000000000.0;   // psTime greater than epoch
+    }
+    outTime->sec = seconds;
+
+    // Error check
+    PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0,(psU32)((1e9)-1),NULL);
+
+    return outTime;
+}
+
+psTime* psTimeFromISO(const char *input,
+                      psTimeType type)
+{
+
+    // Check for NULL string
+    PS_ASSERT_PTR_NON_NULL(input,NULL);
+    PS_ASSERT_INT_WITHIN_RANGE(type, PS_TIME_TAI, PS_TIME_TT, NULL);
+
+    // Convert YYYY-MM-DDThh:mm:ss.sss[Z] in string form to tm time
+    psTime *outTime = psTimeStrptime(input, "%Y-%m-%dT%H:%M:%S");
+    if (!outTime) {
+        // try for date with assumed 00:00:00 time
+        outTime = psTimeStrptime(input, "%Y-%m-%d");
+        if (!outTime) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Specified ISO Time string, '%s', is malformed.  Must be in 'YYYY-MM-DDThh:mm:ss.sss' format."), input);
+            return NULL;
+        }
+    }
+
+    outTime->type = type;
+
+    return outTime;
+}
+
+// accepts a range of human readable times:
+// ISO (YYYY-MM-MMTHH:MM:SS[.sss][Z])
+// YYYY/MM/DD,HH:MM:DD
+psTime* psTimeFromString(const char *input,
+                      psTimeType type)
+{
+
+    // Check for NULL string
+    PS_ASSERT_PTR_NON_NULL(input,NULL);
+    PS_ASSERT_INT_WITHIN_RANGE(type, PS_TIME_TAI, PS_TIME_TT, NULL);
+
+    psTime *outTime = NULL;
+
+    // Convert YYYY-MM-DDThh:mm:ss.sss[Z] in string form to tm time
+    outTime = psTimeStrptime(input, "%Y-%m-%dT%H:%M:%S");
+    if (outTime) {
+      outTime->type = type;
+      return outTime;
+    }
+    psErrorClear ();
+
+    // Convert YYYY/MM/DD,hh:mm:ss.sss[Z] in string form to tm time
+    outTime = psTimeStrptime(input, "%Y/%m/%d,%H:%M:%S");
+    if (outTime) {
+      outTime->type = type;
+      return outTime;
+    }
+    psErrorClear ();
+
+    // Convert YYYY/MM/DD@hh:mm:ss.sss[Z] in string form to tm time
+    outTime = psTimeStrptime(input, "%Y/%m/%d@%H:%M:%S");
+    if (outTime) {
+      outTime->type = type;
+      return outTime;
+    }
+    psErrorClear ();
+
+    // try for date with assumed 00:00:00 time
+    outTime = psTimeStrptime(input, "%Y-%m-%d");
+    if (outTime) {
+      outTime->type = type;
+      return outTime;
+    }
+    psErrorClear ();
+
+    // try for date with assumed 00:00:00 time
+    outTime = psTimeStrptime(input, "%Y/%m/%d");
+    if (outTime) {
+      outTime->type = type;
+      return outTime;
+    }
+    psErrorClear ();
+
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Specified Time string, '%s', is malformed.  Must be in 'YYYY-MM-DDThh:mm:ss.sss' format."), input);
+    return NULL;
+}
+
+psTime* psTimeFromTT(psS64 sec,
+                     psU32 nsec)
+{
+    psTime*      outTime  = NULL;
+
+    // Verify nsec within range
+    PS_ASSERT_INT_WITHIN_RANGE(nsec,0,(psU32)((1e9)-1),NULL);
+
+    // Allocate psTime data
+    outTime = psTimeAlloc(PS_TIME_TT);
+
+    // Set data members
+    outTime->sec = sec;
+    outTime->nsec = nsec;
+
+    // Return data structure
+    return outTime;
+}
+
+psTime* psTimeFromUTC(psS64 sec,
+                      psU32 nsec,
+                      bool leapsecond)
+{
+    psTime*   outTime   = NULL;
+
+    // Verify nsec within range
+    PS_ASSERT_INT_WITHIN_RANGE(nsec,0,(psU32)((1e9)-1),NULL);
+
+    // Allocate psTime data
+    outTime = psTimeAlloc(PS_TIME_UTC);
+
+    // Set data members
+    outTime->sec = sec;
+    outTime->nsec = nsec;
+
+    // Set leapsecond flag if necessary
+    outTime->leapsecond = psTimeIsLeapSecond(outTime);
+
+    return outTime;
+}
+
+psTime* psTimeFromTimeval(const struct timeval *input)
+{
+    psTime *outTime = NULL;
+
+
+    // Error check
+    PS_ASSERT_PTR_NON_NULL(input,NULL);
+
+    // Allocate psTime struct
+    outTime = psTimeAlloc(PS_TIME_TAI);
+
+    // Convert to psTime
+    outTime->sec = input->tv_sec;
+    outTime->nsec = input->tv_usec * 1000;
+
+    // Error check
+    PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0,(psU32)((1e9)-1),outTime);
+
+    return outTime;
+}
+
+psTime* psTimeFromTM(const struct tm* time)
+{
+    psS64 year;
+    psS64 month;
+    psS64 day;
+    psS64 hour;
+    psS64 minute;
+    psS64 seconds;
+    psS64 temp;
+    psTime *outTime = NULL;
+
+    // Error check
+    PS_ASSERT_PTR_NON_NULL(time,NULL);
+
+    // Allocate psTime struct
+    outTime = psTimeAlloc(PS_TIME_TAI);
+
+    // Extract data from TM struct
+    year = time->tm_year + 1900;
+    month = time->tm_mon + 1;
+    day = time->tm_mday;
+    hour = time->tm_hour;
+    minute = time->tm_min;
+    seconds = time->tm_sec;
+
+    // Make month in range 3..14 (treat Jan & Feb as months 13..14 of prev year)
+    if( month <= 2 )
+    {
+        temp = (14 - month) / 12;
+        //        year -= (temp = (14 - month) / 12);
+        year -= temp;
+        month += 12 * temp;
+    } else if(month > 14)
+    {
+        temp = (month - 3) / 12;
+        //        year += (temp = (month - 3) / 12);
+        year += temp;
+        month -= 12 * temp;
+    }
+
+    // Make year positive
+    if (year < 0 )
+    {
+        day -= 146097 * (temp = (399 - year) / 400);
+        year += 400 * temp;
+    }
+
+    // Add day of month, days of previous 0-11 month period that began w/March, days of previous 0-399 year
+    // period that began w/March of a 400-multiple year), days of any 400-year periods before that, and 306
+    // days to adjust from Mar 1, year 0-relative to Jan 1, year 1-relative. Add hours, minutes, and seconds.
+    day += (month * 367 - 1094) / 12 + year % 100 * 1461 / 4 + (year/100 * 36524 + year/400) - 306;
+
+    outTime->sec = ((day - 1) * SEC_PER_DAY - 62135596800)
+                   + (hour * SEC_PER_HOUR)
+                   + (minute * SEC_PER_MINUTE)
+                   + seconds;
+
+    // C's TM does not define a microsecond field. Microseconds must be manipulated by calling function.
+    outTime->nsec = 0;
+
+    // Error check
+    PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0,(psU32)((1e9)-1),outTime);
+
+    return outTime;
+}
+
+psTime* psTimeStrptime(const char *s, const char *format)
+{
+    PS_ASSERT_PTR_NON_NULL(s, NULL);
+    PS_ASSERT_PTR_NON_NULL(format, NULL);
+
+    double fractionalSeconds = 0.0;
+
+    struct tm tmTime;
+    tmTime.tm_year = tmTime.tm_mon = tmTime.tm_mday = 0;
+    tmTime.tm_hour = tmTime.tm_min = tmTime.tm_sec = 0;
+    char *lastChar = strptime(s, format, &tmTime);
+    if (!lastChar) {
+        psError(PS_ERR_UNKNOWN, true, "error parsing time string");
+        return NULL;
+    }
+
+    if (*lastChar != '\0') {
+        psTrace("psLib.astro", 3, "handling fractional second in time string\n");
+        // XXXXXXXXXXXXXXX
+        // XXX this is a really stupid error:
+        // we are dropping the fractional seconds with this conversion
+        // I've put in a proposed fix, but PLEASE test!!!
+        if (*lastChar == '.') {
+            char *reallyLast;
+            fractionalSeconds = strtod (lastChar, &reallyLast);
+            if (!reallyLast) {
+                psWarning("time string was not completely consumed\n");
+            }
+        }
+    }
+
+    psTime *time = psTimeFromTM(&tmTime);
+    if (!time) {
+        psError(PS_ERR_UNKNOWN, false, "failed to generate a psTime");
+        return NULL;
+    }
+
+    time->nsec += fractionalSeconds * 1e9;
+    return time;
+}
+
+psString psTimeStrftime(const psTime *time, const char *format)
+{
+    PS_ASSERT_PTR_NON_NULL(time, NULL);
+    PS_ASSERT_PTR_NON_NULL(format, NULL);
+
+    struct tm *tmTime = psTimeToTM(time);
+
+    psString s = psAlloc(MAX_TIME_STRING_LENGTH);
+    size_t size = strftime(s, MAX_TIME_STRING_LENGTH, format, tmTime);
+    psFree(tmTime);
+    // it's worth nothing that strftime() can zero without an error having
+    // occured don't believe it's worth supporting that edge case.  See
+    // strftime(3) for further details.
+    if (size == 0) {
+        psError(PS_ERR_UNKNOWN, true, "failed to stringify a psTime");
+        return NULL;
+    }
+
+    return s;
+}
+
+psTime* psTimeMath(const psTime *time,
+                   double delta)
+{
+    psF64 sec = 0.0;
+    psTime *outTime = NULL;
+    psTime *tempTime = NULL;
+
+    // Error checks
+    PS_ASSERT_PTR_NON_NULL(time,NULL);
+    PS_ASSERT_INT_WITHIN_RANGE(time->nsec, (psU32)0, (psU32)((1e9)-1), NULL);
+
+    // Convert time to TAI if necessary, but without changing input arguments
+    if(time->type == PS_TIME_UTC) {
+        tempTime = psTimeAlloc(PS_TIME_UTC);
+        tempTime->sec = time->sec;
+        tempTime->nsec = time->nsec;
+        tempTime = psTimeConvert(tempTime, PS_TIME_TAI);
+        outTime = psTimeAlloc(PS_TIME_TAI);
+    } else {
+        tempTime = psMemIncrRefCounter((psTime*)time);
+        outTime = psTimeAlloc(time->type);
+    }
+
+    // Create output time
+    sec = delta + (psF64)tempTime->sec + (psF64)tempTime->nsec/1e9;
+    PS_ASSERT_S64_WITHIN_RANGE((psS64)sec, (psS64)0, PS_MAX_S64, NULL);
+    outTime->sec = (psS64)sec;
+    outTime->nsec = (psU32)((sec - (psF64)outTime->sec)*1e9);
+
+    // Error check
+    PS_ASSERT_INT_WITHIN_RANGE(outTime->nsec,0,(psU32)((1e9)-1), NULL);
+
+    // Convert result to same time type as input
+    if(time->type == PS_TIME_UTC) {
+        outTime = psTimeConvert(outTime, PS_TIME_UTC);
+    }
+
+    psFree(tempTime);
+
+    return outTime;
+}
+
+double psTimeDelta(const psTime *time1,
+                   const psTime *time2)
+{
+    psF64 uSec1 = 0.0;
+    psF64 uSec2 = 0.0;
+    psTime *tempTime1 = NULL;
+    psTime *tempTime2 = NULL;
+
+    // Error checks
+    // XXX nsec is U32, use an integer for comparison
+    PS_ASSERT_PTR_NON_NULL(time1,0.0);
+    PS_ASSERT_INT_WITHIN_RANGE(time1->nsec,0,(psU32)(999999999),0.0);
+    PS_ASSERT_PTR_NON_NULL(time2,0.0);
+    PS_ASSERT_INT_WITHIN_RANGE(time2->nsec,0,(psU32)(999999999),0.0);
+
+    // Verify both times of the same type
+    if(time1->type != time2->type) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE,true,_("Specified type, %d, is incorrect."),time1->type);
+        return NAN;
+    }
+
+    // Convert time to TAI if necessary, but without changing input arguments
+    if(time1->type == PS_TIME_UTC) {
+        tempTime1 = psTimeAlloc(PS_TIME_UTC);
+        tempTime1->sec = time1->sec;
+        tempTime1->nsec = time1->nsec;
+        tempTime1 = psTimeConvert(tempTime1, PS_TIME_TAI);
+    } else {
+        tempTime1 = psMemIncrRefCounter((psTime*)time1);
+    }
+    if(time2->type == PS_TIME_UTC) {
+        tempTime2 = psTimeAlloc(PS_TIME_UTC);
+        tempTime2->sec = time2->sec;
+        tempTime2->nsec = time2->nsec;
+        tempTime2 = psTimeConvert(tempTime2, PS_TIME_TAI);
+    } else {
+        tempTime2 = psMemIncrRefCounter((psTime*)time2);
+    }
+
+    uSec1 = tempTime1->sec >= 0 ? 1.0 : -1.0;
+    uSec1 = uSec1*tempTime1->nsec/1e9;
+    uSec2 = tempTime2->sec >= 0 ? 1.0 : -1.0;
+    uSec2 = uSec2*tempTime2->nsec/1e9;
+    psF64 out = (tempTime1->sec-tempTime2->sec) + (uSec1-uSec2);
+
+    psFree(tempTime1);
+    psFree(tempTime2);
+
+    return out;
+}
+
+// delay actual init until a timefunction is used
+bool psTimeInit(const char *filename)
+{
+    // at present, this function can not fail
+    p_psTimeConfigFilename(filename);
+
+    return true;
+}
+
+void psTimeFinalize(void)
+{
+    p_psTimeFinalize();
+}
+
+psTime *psTimeCopy(const psTime *inTime)
+{
+    // Pass through NULL values!
+    if (!inTime) {
+        psTrace("psLib.astro", 6, "passing through NULL value");
+        return NULL;
+    }
+
+    psTime *outTime = psTimeAlloc(inTime->type);
+    if (outTime == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                "Invalid type specified in psTimeCopy.  %x", inTime->type);
+        return NULL;
+    }
+    //    *outTime = *inTime;
+    outTime->sec = inTime->sec;
+    outTime->nsec = inTime->nsec;
+    outTime->leapsecond = inTime->leapsecond;
+    return outTime;
+}
+
+// XXX EAM : I've changed the timers to report TAI
+// this makes more sense because it has monotonically increasing seconds
+// would be even better if we could get a TAI value without doing a big lookup...
+
+static psHash *timers = NULL;
+
+// free all timers
+static void psTimerFree ()
+{
+    p_psTimeFinalize();
+    psFree(timers);
+    timers = NULL;
+    return;
+}
+
+// start/restart a named timer
+bool psTimerStart (char *name)
+{
+    if (name == NULL)
+        return false;
+    if (timers == NULL) {
+        timers = psHashAlloc (16);
+    }
+    psTime *start = psTimeGetNow (PS_TIME_TAI);
+    psHashAdd (timers, name, start);
+    psFree (start);
+    return true;
+}
+
+// clear the timer, return elapsed time to date, or NAN if not previously defined
+psF64 psTimerClear (char *name)
+{
+    if (name == NULL)
+        return NAN;
+    psF64 delta = psTimerMark(name);
+
+    psTime *start = psTimeGetNow (PS_TIME_TAI);
+    psHashAdd (timers, name, start);
+    psFree (start);
+    return delta;
+}
+
+// get current elapsed time on named timer (NAN if not defined)
+psF64 psTimerMark (char *name)
+{
+    if (timers == NULL)
+        return (NAN);
+    psTime *start = psHashLookup (timers, name);
+    if (start == NULL)
+        return (NAN);
+
+    psTime *mark = psTimeGetNow (PS_TIME_TAI);
+    psF64  delta = psTimeDelta (mark, start);
+    psFree (mark);
+    return delta;
+}
+
+bool psTimerStop(void)
+{
+    psTimerFree();
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psTime.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psTime.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/astro/psTime.h	(revision 22158)
@@ -0,0 +1,481 @@
+/** @file  psTime.h
+ *
+ *  @brief Definitions for time, time utilities, and conversion functions for use
+ *  with psLib astronomy functions.
+ *
+ *  A collection of functions are required by psLib to manipulate time data. These
+ *  functions primarily consist of conversions between specific time formats.  They
+ *  use the UNIX timeval time system as the base upon which International Atomic
+ *  Time (TAI) and Universal Time Coordinated (UTC) are calculated.
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.58 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-03-17 23:53:59 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PSTIME_H
+#define PSTIME_H
+
+/// @addtogroup Astro Astronomy
+/// @{
+
+#include <time.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include "psType.h"
+#include "psImage.h"
+#include "psLookupTable.h"
+#include "psCoord.h"
+
+#if defined(__APPLE__)   // incorrectly missing in time.h
+struct tm *gmtime_r(const time_t *, struct tm *);
+#endif
+
+struct psSphere;
+
+/** Time type.
+ *
+ * Enumeration for psTime types, TAI or UTC time.
+ */
+typedef enum {
+    PS_TIME_TAI,                       ///< Temps Atomique International (TAI) time (time with leapseconds)
+    PS_TIME_UTC,                       ///< Universal Time Coordinated (UTC) time (time without leapseconds)
+    PS_TIME_UT1,                       ///< Universal Time corrected for polar motion
+    PS_TIME_TT,                        ///< Terrestrial Time
+} psTimeType;
+
+/** Time Bulletin type
+ *
+ * Enumeration for psTimeBulletin type, A or B.
+ */
+typedef enum {
+    PS_IERS_A,                         ///< IERS Bulletin A
+    PS_IERS_B,                         ///< IERS Bulletin B
+} psTimeBulletin;
+
+/** Definition of psTime.
+ *
+ *  The psTime struct is used by psLib to represent time values critical to
+ *  astronomical calculations.  This structure represents a time which is
+ *  equivalent to TAI (International Atomic Time) and is measured in both
+ *  seconds and microseconds.
+ */
+typedef struct
+{
+    psS64 sec;                         ///< Seconds since epoch, Jan 1, 1970.
+    psU32 nsec;                        ///< Nanoseconds since last second.
+    bool leapsecond;                   ///< if time falls on UTC leapsecond
+    psTimeType type;                   ///< Type of time.
+}
+psTime;
+
+
+/** Initialize time data.
+ *
+ *  Sets the configuration file and sets up the appropriate psTimeTables and predictions.
+ */
+bool psTimeInit(
+    const char *filename                ///< psTime configuration file
+);
+
+
+/** Frees memory that was allocated by psTime functions.
+ *
+ *  Allows a subsequent search for leaked memory.
+ *
+ * @return true on sucess.
+*/
+bool p_psTimeFinalize(void);
+
+/** Frees memory that was allocated by psTime functions.
+ *
+ *  Allows a subsequent search for leaked memory.
+ */
+void psTimeFinalize(void);
+
+/** Allocate time struct.
+ *
+ * Allocates an empty time struct. User must specify the psTimeType
+ * (PS_TIME_TAI or PS_TIME_UTC) in the argument. The seconds and microseconds members
+ * of the struct are set to zero.
+ *
+ * @return psTime*:     Struct with empty time.
+ */
+psTime* psTimeAlloc(
+    psTimeType type                    ///< Type of time to create (UTC or TAI).
+) PS_ATTR_MALLOC;
+
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psTime structure, false otherwise.
+ */
+bool psMemCheckTime(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+
+/** Get current time.
+ *
+ * Gets current time from the system clock. User must specify the psTimeType
+ * (PS_TIME_TAI or PS_TIME_UTC) in the argument.
+ *
+ *  @return psTime*:    Struct with current time.
+ */
+psTime* psTimeGetNow(
+    psTimeType type                    ///< Type of time to get (UTC or TAI).
+);
+
+/** Convert psTime to UTC, TAI, UT1, or TT time.
+ *
+ *  Converts psTime to UTC, TAI, UT1, or TT time based on the psTimeType argument.
+ *
+ *  @return psTime*:    Pointer to psTime.
+ */
+psTime* psTimeConvert(
+    psTime *time,                      ///< Time to be converted.
+    psTimeType type                    ///< Type to be converted to.
+);
+
+/** Convert psTime to Local Mean Sidereal Time (LMST).
+ *
+ *  Converts psTime at the given longitude to LMST time. If the input time is not
+ *  in UTC format, then it is converted.
+ *
+ *  @return double:     LST Time.
+ */
+double psTimeToLMST(
+    psTime *time,                      ///< psTime to be converted.
+    double longitude                   ///< Longitude.
+);
+
+/** Determine UT1 - UTC from table lookup.
+ *
+ *  This function is necessary to for various SLALIB functions.
+ *
+ *  @return double:     Time difference.
+ */
+double psTimeGetUT1Delta(
+    const psTime *time,                ///< psTime to be looked up.
+    psTimeBulletin bulletin            ///< IERS bulletin to use
+);
+
+/** Provides tidal corrections to UT1-UTC.
+ *
+ *  Uses the Ray model of Simon et al.
+ *
+ *  @return psTime*:    The corrected time in UT1.
+ */
+psTime *psTime_TideUT1Corr(
+    const psTime *time                 ///< psTime to be corrected.
+);
+
+/** Determine TAI - UTC from table lookup.
+ *
+ *  This function is necessary to for various psTime functions.
+ *
+ *  @return psF64:      Time difference.
+ */
+psF64 p_psTimeGetTAIDelta(
+    const psTime *time                 ///< psTime to be looked up.
+);
+
+/** Determine polar coordinates at a given time.
+ *
+ *  Determines the orientation of the polar axis at the given time.
+ *
+ *  @return psSphere*:      Spherical coordinates of Earth's polar axias.
+ */
+psSphere* p_psTimeGetPoleCoords(
+    const psTime *time      ///< psTime determine polar orientation.
+);
+
+/** Calculate the number of leapseconds between two times.
+ *
+ *  Calculates the number of leapseconds between two times.
+ *
+ *  @return long:   leapseconds added between given times
+ */
+long psTimeLeapSecondDelta(
+    const psTime* time1,               ///< First input time.
+    const psTime* time2                ///< Second input time.
+);
+
+/** Determine if UTC time is a leapsecond.
+ *
+ *  Determines if the specified UTC time is a valid leapsecond.
+ *
+ *  @return bool:   valid leap second
+ */
+bool psTimeIsLeapSecond(
+    const psTime* utc                  ///< UTC to verify if leap second
+);
+
+/** Convert psTime to Julian date time.
+ *
+ *  Converts psTime to Julian date (JD) time. This function does not add or
+ *  subtract leapseconds.
+ *
+ *  @return double:     Julian Date (JD) time.
+ */
+double psTimeToJD(
+    const psTime* time                 ///< Input time to be converted.
+);
+/** Convert psTime to modified Julian date time.
+ *
+ *  Converts psTime to modified Julian date (MJD) time. This function does not
+ *  add or subtract leapseconds.
+ *
+ *  @return double:     Modified Julian Days (MJD) time.
+ */
+double psTimeToMJD(
+    const psTime* time                  ///< Input time to be converted.
+);
+
+/** Convert psTime to ISO8601 formatted string.
+ *
+ *  Converts psTime to a null terminated string in the form of YYYY-MM-DDThh:mm:ss.sss.
+ *  This function does not add or subtract leapseconds.
+ *
+ *  @return psString:     Pointer null terminated array of chars in ISO time.
+ */
+psString psTimeToISO(
+    const psTime* time                  ///< Input time to be converted.
+);
+
+/** Convert psTime to struct tm time.
+ *
+ *  Converts psTime to struct tm time.  This function should handle
+ *  UTC leapseconds correctly.
+ *
+ *  @return tm*:   tm struct.
+ */
+struct tm *psTimeToTM(
+                const psTime* time     ///< Input time to be converted.
+            );
+
+/** Convert psTime to timeval time.
+ *
+ *  Converts psTime to timeval time. This function does not add or subtract leapseconds.
+ *
+ *  @return timeval*:   timeval struct time.
+ */
+struct timeval* psTimeToTimeval(
+                const psTime* time     ///< Input time to be converted.
+            );
+
+/*
+ * Convert psTime to tm time.
+ *
+ * Converts psTime to tm time. This function is based on a Perl algorithm availble
+ * in the Pan-STARRS Image processing Algorithm Design Description (ADD). This function
+ * does not add or subtract leapseconds.
+ *
+ *  @return  tm: tm struct time.
+ *
+struct tm* p_psTimeToTM(
+                const psTime *time     ///< Input time to be converted.
+            );
+*/
+/** Convert JD to psTime.
+ *
+ *  Converts JD time to psTime. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime: time.
+ */
+psTime* psTimeFromJD(
+    double jd                          ///< Input time to be converted.
+);
+
+/** Convert MJD to psTime.
+ *
+ *  Converts MJD time to psTime. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime: time.
+ */
+psTime* psTimeFromMJD(
+    double mjd                         ///< Input time to be converted.
+);
+
+/** Convert ISO to psTime.
+ *
+ *  Converts ISO time to psTime. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime*: time
+ */
+psTime* psTimeFromISO(
+    const char* input,                 ///< Input time to be converted.
+    psTimeType type                    ///< Time type.
+);
+
+/** Convert various human-readable formats to psTime.
+ *
+ *  Converts human readable time formats to psTime. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime*: time
+ */
+psTime* psTimeFromString(
+    const char* input,                 ///< Input time to be converted.
+    psTimeType type                    ///< Time type.
+);
+
+/** Convert timeval to psTime.
+ *
+ *  Converts timeval time to psTime. This function does not add or subtract leapseconds.
+ *
+ *  @return  psTime*: time.
+ */
+psTime* psTimeFromTimeval(
+    const struct timeval *input        ///< Input time to be converted.
+);
+
+/** Convert Terrestrial Time to psTime
+ *
+ *  Converts Terrestial Time to psTime.  This function assumes resultant time is of type TT.
+ *
+ *  @return psTime*: time (TT)
+ */
+psTime* psTimeFromTT(
+    psS64 sec,                         ///< Input terrestrial time in seconds
+    psU32 nsec                         ///< Input terrestrial time fraction of seconds (nanoseconds)
+);
+
+/** Convert UTC time to psTime
+ *
+ *  Converts UTC time to psTime.  It will verify if time specified is a leapsecond.
+ *
+ *  @return psTime*: time (UTC)time
+ */
+psTime* psTimeFromUTC(
+    psS64  sec,                        ///< Input time in seconds
+    psU32  nsec,                       ///< Input time fraction of seconds (nanoseconds)
+    bool leapsecond                    ///< Input time is a leapsecond
+);
+
+/** Convert tm time to psTime.
+ *
+ *  Converts tm time to psTime. This function is based on a Perl algorithm availble
+ *  in the Pan-STARRS Image processing Algorithm Design Description (ADD). This function
+ *  does not add or subtract leapseconds.
+ *
+ *  @return  psTime*: time.
+ */
+psTime* psTimeFromTM(
+    const struct tm *time              ///< Input time to be converted.
+);
+
+/** Convert an arbitrary string into a psTime.
+ *
+ *  Converts a string, using a strptime(3) format, into a psTime.  See
+ *  strptime(3) for documentation on this format.
+ *
+ *  @return  psTime*: time.
+ */
+
+psTime* psTimeStrptime(
+    const char *s,                      ///< string to be converted
+    const char *format                  ///< strptime(3) format
+);
+
+/** Convert a psTime into a formated string.
+ *
+ *  Converts a psTime, using a strftime(3) format, into a formatted string.
+ *  See strftime(3) for documentation on this format.
+ *
+ *  @return  psString: string.
+ */
+
+psString psTimeStrftime(
+    const psTime *time,                 ///< Time to be formatted.
+    const char *format                  ///< strftime(3) format
+);
+
+/** Adds delta to time. Result is in TAI time.
+ *
+ *  Adds delta to time. Input time is converted to TAI format if necessary.
+ *
+ *  @return  psTime*: time.
+ */
+psTime* psTimeMath(
+    const psTime *time,                ///< Time.
+    double delta                       ///< Time delta.
+);
+
+/** Determine difference between two times. Result is in TAI time.
+ *
+ *  Determine difference between two times. Input times are converted to TAI format if necessary.
+ *
+ *  @return double: Time difference.
+ */
+double psTimeDelta(
+    const psTime *time1,               ///< First time.
+    const psTime *time2                ///< Second time.
+);
+
+/** Searches the IERS time tables for a specified entry location.
+ *
+ *  Returns the interpolated double precision (arcsec) value at the specified entry
+ *  location.  Inputs to specify are the time index in mjd, the column number
+ *  corresponding to Xp, Yp, or Sp (UT1-UTC) in IERS A or B, the time table names,
+ *  and the number of time tables.
+ *
+ *  @return psF64:          Resulting table entry for specified parameters.
+ */
+psF64 p_psTimeSearchTables(
+    psF64 index,                       ///< time index for which to search
+    psU64 column,                      ///< column number of specified index
+    char *metadataTableNames[],        ///< names of IERS tables to search
+    psU32 nTables,                     ///< number of IERS tables to search
+    psLookupStatusType* status         ///< status of table search
+);
+
+/** Stores the current time in a psHash of timers, under the supplied name.
+ *
+ *  @return bool:       True if successful, otherwise false.
+ */
+bool psTimerStart(
+    char *name                         ///< timer name to start
+);
+
+/** Resets the named timer.
+ *
+ *  @return psF64:      The time elapsed since start.
+ */
+psF64 psTimerClear(
+    char *name                         ///< timer name to clear
+);
+
+/** Returns the elapsed time, in seconds, for the timer specified by name.
+ *
+ *  @return psF64:      The elapsed time in seconds since timer start.
+ */
+psF64 psTimerMark(
+    char *name                        ///< timer name to mark
+);
+
+/** Frees all memory associated with all timers and returns the expended time.
+ *
+ *  @return psF64:      The maximum time expended.
+ */
+bool psTimerStop(void);
+
+/** Copy a psTime.
+ *
+ *  @return psTime*:        New copy of existing psTime.
+ */
+psTime *psTimeCopy(
+    const psTime *inTime               ///< input time to copy.
+);
+
+// used by p_psEOCInit()
+const char *p_psTimeConfigFilename(const char *filename);
+
+/// @}
+
+#endif // #ifndef PSTIME_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/db/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/db/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/db/.cvsignore	(revision 22158)
@@ -0,0 +1,10 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
+*.loT
+*.bb
+*.bbg
+*.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/db/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/db/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/db/Makefile.am	(revision 22158)
@@ -0,0 +1,14 @@
+#Makefile for db functions of psLib
+#
+noinst_LTLIBRARIES = libpslibdb.la
+
+libpslibdb_la_CPPFLAGS = $(SRCINC) $(PSLIB_CFLAGS) $(MYSQL_CFLAGS)
+libpslibdb_la_SOURCES = \
+	psDB.c
+
+EXTRA_DIST = db.i
+
+pkginclude_HEADERS = \
+	psDB.h
+
+CLEANFILES = *~ *.bb *.bbg *.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/db/db.i
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/db/db.i	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/db/db.i	(revision 22158)
@@ -0,0 +1,2 @@
+/* db headers */
+%include "psDB.h"
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/db/psDB.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/db/psDB.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/db/psDB.c	(revision 22158)
@@ -0,0 +1,2769 @@
+/** @file psDB.c
+ *
+ * Copyright (C) 2005-2007  Joshua Hoblitt, University of Hawaii
+ * Copyright (C) 2005  Aaron Culliney
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * @brief database functions
+ *
+ * This file contains functions that perform basic database operations.  MySQL
+ * 4.1.2 or newer is required.
+ *
+ * $Id: psDB.c,v 1.168 2008-07-18 22:09:19 price Exp $
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_PSDB
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+#undef __STRICT_ANSI__
+#include <stdlib.h>
+#define __STRICT_ANSI__
+#include <math.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <regex.h>
+#include <mysql.h>
+#include <mysql_com.h> // enum_field_types
+
+#include "psDB.h"
+#include "psMemory.h"
+#include "psAssert.h"
+#include "psAbort.h"
+#include "psError.h"
+#include "psString.h"
+#include "psTrace.h"
+#include "psMetadataConfig.h"
+
+
+// set the pointer to NULL if we are actually freeing the memory
+#define PSDB_NULL_FREE(ptr) \
+if (psMemGetRefCounter(ptr) == 1) { \
+    psFree(ptr); \
+    ptr = NULL; \
+} else { \
+    psFree(ptr); \
+}
+
+typedef struct
+{
+    enum enum_field_types type;
+    bool            isUnsigned;
+}
+mysqlType;
+
+typedef struct
+{
+    MYSQL_BIND      *bind;
+    psU32           n;
+}
+psDBMysqlRow;
+
+// cache of prepared query statements
+static pthread_mutex_t preparedQueryMutex = PTHREAD_MUTEX_INITIALIZER;
+static psHash *preparedQuery = NULL;
+
+static pthread_mutex_t lookupTableMutex = PTHREAD_MUTEX_INITIALIZER;
+static psHash   *pTypeToSQLlookupTable = NULL;
+static psHash   *sqlToPTypeLookupTable = NULL;
+static psHash   *mysqlToSqlLookupTable = NULL;
+static psHash   *pTypeToMysqlLookupTable = NULL;
+
+// free func
+static void psDBFree(psDB *dbh);
+
+// database utility functions
+static inline bool psDBPackMySQLRow(psDBMysqlRow *mysqlRow, const psMetadata *values);
+static psDBMysqlRow *psDBMysqlRowAlloc(psU32 paramCount);
+static void psDBMysqlRowFree(psDBMysqlRow *row);
+static void psDBMysqlRowRecycle(psDBMysqlRow *mysqlRow);
+
+// SQL generation functions
+static psString psDBGenerateCreateTableSQL(const char *tableName, const psMetadata *where);
+static psString psDBGenerateSelectRowSQL(const char *tableName, const char *col,
+        const psMetadata *where, psU64 limit);
+static psString psDBGenerateInsertRowSQL(const char *tableName, const psMetadata *row);
+static psString psDBGenerateUpdateRowSQL(const char *tableName, const psMetadata *where,
+        const psMetadata *values);
+static psString psDBGenerateDeleteRowSQL(const char *tableName, const psMetadata *where,
+        unsigned long long limit);
+static psString psDBGenerateSetSQL(const psMetadata *set
+                                  );
+static char *psDBGenerateConditionalSQL(const psMetadataItem *item, const char *tableName);
+
+// lookup table functions
+static psElemType psDBMySQLToPType(enum enum_field_types type, unsigned int flags);
+static psString psDBPTypeToSQL(psElemType pType);
+static mysqlType *psDBPTypeToMySQL(psElemType pType);
+
+static psHash  *psDBPTypeToSQLTableSetup(void);
+static psHash  *psDBPTypeToSQLTableGet(void);
+static void     psDBPTypeToSQLTableCleanup(void);
+
+static psHash  *psDBSQLToPTypeTableSetup(void);
+static psHash  *psDBSQLToPTypeTableGet(void);
+static void     psDBSQLToPTypeTableCleanup(void);
+
+static psHash  *psDBMySQLToSQLTableSetup(void);
+static psHash  *psDBMySQLToSQLTableGet(void);
+static void     psDBMySQLToSQLTableCleanup(void);
+
+static psHash  *psDBPTypeToMySQLTableSetup(void);
+static psHash  *psDBPTypeToMySQLTableGet(void);
+static void     psDBPTypeToMySQLTableCleanup(void);
+
+static psPtr    psDBMySQLTypeAlloc(enum enum_field_types type, bool isUnsigned);
+static void     psDBAddToLookupTable(psHash *lookupTable, psU32 type, const char *string);
+static void     psDBAddVoidToLookupTable(psHash *lookupTable, psU32 type, psPtr value);
+static psErrorCode mysqlTopsErr(MYSQL *mysql);
+
+// pType utility functions
+static psPtr    psDBGetPTypeNaN(psElemType pType);
+static bool     psDBIsPTypeNaN(psElemType pType, psPtr data);
+
+// public functions
+/*****************************************************************************/
+
+psDB *psDBAlloc(const char *host,
+                const char *user,
+                const char *passwd,
+                const char *dbname,
+                unsigned int port)
+{
+    MYSQL           *mysql;
+    psDB            *dbh;
+
+    mysql = mysql_init(NULL);
+    if (!mysql) {
+        psAbort("mysql_init(), out of memory.");
+    }
+
+    // without this call we won't pick up anything from my.cnf
+    mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "client");
+
+    // Connect to host and mySql server with specified database
+    if (!mysql_real_connect(mysql, host, user, passwd, dbname, port, NULL, 0)) {
+        psError(mysqlTopsErr(mysql), true,
+                _("Failed to connect to database.  Error: %s"),mysql_error(mysql));
+
+        mysql_close(mysql);
+
+        return NULL;
+    }
+
+    dbh = psAlloc(sizeof(psDB));
+
+    dbh->mysql = mysql;
+
+    // explicit transactions default to false
+    if (!psDBExplicitTrans(dbh, false)) {
+        psError(mysqlTopsErr(dbh->mysql), true,
+                "failed to set transaction type. Error: %s", mysql_error(mysql));
+
+        mysql_close(mysql);
+        psFree(dbh);
+
+        return NULL;
+    }
+
+    if (psMemGetThreadSafety()) {
+        pthread_mutex_lock(&lookupTableMutex);
+
+        // psDBPTypeToSQLTableSetu must be run first
+        psDBPTypeToSQLTableSetup();
+        psDBSQLToPTypeTableSetup();
+        psDBMySQLToSQLTableSetup();
+        psDBPTypeToMySQLTableSetup();
+
+        pthread_mutex_unlock(&lookupTableMutex);
+    } else {
+        // psDBPTypeToSQLTableSetu must be run first
+        psDBPTypeToSQLTableSetup();
+        psDBSQLToPTypeTableSetup();
+        psDBMySQLToSQLTableSetup();
+        psDBPTypeToMySQLTableSetup();
+    }
+
+    // don't set the deallocator func until after we've setup the lookup tables
+    // so an alloc error doesn't try to free potentionally uncreated tables
+    psMemSetDeallocator(dbh, (psFreeFunc) psDBFree);
+
+    psTrace("psLib.db", PS_LOG_INFO, "connected to database %s", dbname);
+
+    return dbh;
+}
+
+static void psDBFree(psDB *dbh)
+{
+    // quietly handle NULLs
+    if (!dbh) {
+        return;
+    }
+
+    // Attempt to close specified database connection
+    mysql_close(dbh->mysql);
+
+    // ASC WARNING NOTE: the psDBSQLToPTypeTableCleanup cleanup routine
+    // needs to be called first because it refers to
+    // psDBPTypeToSQLTableGet ...
+    //
+    // The *cleanup functions should be thread safe as they just call psFree()
+    // but we don't want to be cleaning up & setting up at the same time
+    if (psMemGetThreadSafety()) {
+        pthread_mutex_lock(&lookupTableMutex);
+
+        psDBSQLToPTypeTableCleanup();
+        psDBMySQLToSQLTableCleanup();
+        psDBPTypeToSQLTableCleanup();
+        psDBPTypeToMySQLTableCleanup();
+
+        pthread_mutex_unlock(&lookupTableMutex);
+    } else {
+        psDBSQLToPTypeTableCleanup();
+        psDBMySQLToSQLTableCleanup();
+        psDBPTypeToSQLTableCleanup();
+        psDBPTypeToMySQLTableCleanup();
+    }
+
+    psTrace("psLib.db", PS_LOG_INFO, "disconnected");
+}
+
+bool psDBCreate(psDB *dbh,
+                const char *dbname)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, false);
+    PS_ASSERT_PTR_NON_NULL(dbname, false);
+
+    psString query = NULL;
+    psStringAppend(&query, "CREATE DATABASE %s", dbname);
+
+    // the MySQL C API notes that mysql_create_db() is deprecated
+    bool status = p_psDBRunQuery(dbh, query);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "Failed to create new database.");
+    }
+
+    psFree(query);
+
+    psTrace("psLib.db", PS_LOG_INFO, "created a database named %s", dbname);
+
+    return status;
+}
+
+bool psDBChange(psDB *dbh,
+                const char *dbname)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, false);
+    PS_ASSERT_PTR_NON_NULL(dbname, false);
+
+    // Attempt to select new database
+    if (mysql_select_db(dbh->mysql, dbname) != 0) {
+        psError(mysqlTopsErr(dbh->mysql), true, _("Failed to change database.  Error: %s"),
+                mysql_error(dbh->mysql));
+
+        return false;
+    }
+
+    psTrace("psLib.db", PS_LOG_INFO, "changed to using database %s", dbname);
+
+    return true;
+}
+
+bool psDBDrop(psDB *dbh,
+              const char *dbname)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, false);
+    PS_ASSERT_PTR_NON_NULL(dbname, false);
+
+    char            *query = NULL;
+    psStringAppend(&query, "DROP DATABASE %s", dbname);
+
+    // the MySQL C API notes that mysql_drop_db() is deprecated
+    bool status = p_psDBRunQuery(dbh, query);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "Failed to drop database.");
+    }
+
+    psFree(query);
+
+    psTrace("psLib.db", PS_LOG_INFO, "dropped database %s", dbname);
+
+    return status;
+}
+
+bool psDBCreateTable(psDB *dbh,
+                     const char *tableName,
+                     const psMetadata *md)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, false);
+    PS_ASSERT_PTR_NON_NULL(tableName, false);
+    PS_ASSERT_PTR_NON_NULL(md, false);
+
+    // Generate SQL query string
+    psString query = psDBGenerateCreateTableSQL(tableName, md);
+    if (!query) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, _("Query generation failed."));
+        return false;
+    }
+
+    // Run SQL query to create table
+    bool status = p_psDBRunQuery(dbh, query);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, _("Failed to create table."));
+    }
+
+    psFree(query);
+
+    psTrace("psLib.db", PS_LOG_INFO, "created table %s", tableName);
+
+    return status;
+}
+
+bool psDBDropTable(psDB *dbh,
+                   const char *tableName)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, false);
+    PS_ASSERT_PTR_NON_NULL(tableName, false);
+
+    // Create SQL command string to drop table
+    psString query = NULL;
+    psStringAppend(&query, "DROP TABLE %s", tableName);
+
+    // Execute query
+    bool status = p_psDBRunQuery(dbh, query);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, _("Failed to drop table."));
+    }
+
+    psFree(query);
+
+    psTrace("psLib.db", PS_LOG_INFO, "dropped table %s", tableName);
+
+    return status;
+}
+
+psArray *psDBSelectColumn(psDB *dbh,
+                          const char *tableName,
+                          const char *col,
+                          unsigned long long limit)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, NULL);
+    PS_ASSERT_PTR_NON_NULL(tableName, NULL);
+    PS_ASSERT_PTR_NON_NULL(col, NULL);
+
+    MYSQL_RES       *result;            // complete db result set
+    MYSQL_ROW       row;                // single row of db result set
+    my_ulonglong    rowCount;           // number of rows in db result set
+    unsigned long   dataSize;           // size of field
+    unsigned int    fieldCount;         // number of fields in db result set
+    psArray         *column = NULL;     // return array
+    psPtr           data;               // copy of result field
+
+    // Generate SQL query string
+    psString query = psDBGenerateSelectRowSQL(tableName, col, NULL, limit);
+    if (!query) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, _("Query generation failed."));
+        return NULL;
+    }
+
+    // Execut SQL query string
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, _("Failed to select column."));
+        psFree(query);
+        return NULL;
+    }
+    psFree(query);
+
+    // Obtain query result and check for no data condition
+    result = mysql_store_result(dbh->mysql);
+
+    if (!result) {
+        // no result set
+        fieldCount = mysql_field_count(dbh->mysql);
+
+        // if field count is zero the query returned no data.  If it's non-zero
+        // then something bad has happened.
+        if (fieldCount != 0) {
+            psError(mysqlTopsErr(dbh->mysql), true, _("Query returned no data.  Error: %s"),
+                    mysql_error(dbh->mysql));
+            return NULL;
+        }
+    }
+
+    // Get number of rows returned in result
+    rowCount = mysql_num_rows(result);
+    // XXX has mysql's semantics changed?  If this is zero then why was a
+    // result set returned?
+    if (!rowCount) {
+        mysql_free_result(result);
+        return NULL;
+    }
+
+    // pre-allocate enough elements to hold the complete result set
+    // then reset n to 0 so elements are added from the beginning of
+    // the array
+    column = psArrayAllocEmpty(rowCount);
+
+    // Fetch each result
+    while ((row = mysql_fetch_row(result))) {
+        // get the first element of lengths array that is part of the
+        // result set
+        dataSize = *(mysql_fetch_lengths(result));
+
+        // represent NULL as a NULL string
+        if (row[0] == NULL) {
+            psArrayAdd(column, 0, NULL);
+            continue;
+        }
+
+        // make a copy of the data
+        data = psAlloc(dataSize+1);
+        memcpy(data, row[0], dataSize);
+        ((char*)data)[dataSize] = '\0';
+
+        // add field to return array
+        psArrayAdd(column, 0, data);
+        psFree(data);
+    }
+
+    // Clean up mysql memory
+    mysql_free_result(result);
+
+    return column;
+}
+
+// dest = assign to, source = source string psArray, conv = conversion function,
+// type = type to cast to, pType = psElemType
+#define PS_STR_ARRAY_TO_PTYPE(dest, source, conv, type, pType) \
+{ \
+    psPtr           myNaN; \
+    \
+    for (long i = 0; i < source->n; i++) { \
+        if (source->data[i]) { \
+            dest[i] = (type)conv(source->data[i]); \
+        } else { \
+            myNaN = psDBGetPTypeNaN(pType); \
+            dest[i] = *(type *)myNaN; \
+            psFree(myNaN); \
+        } \
+    } \
+}
+
+psVector *psDBSelectColumnNum(psDB *dbh,
+                              const char *tableName,
+                              const char *col,
+                              psElemType type,
+                              unsigned long long limit)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, NULL);
+    PS_ASSERT_PTR_NON_NULL(tableName, NULL);
+    PS_ASSERT_PTR_NON_NULL(col, NULL);
+
+    psArray *stringColumn = psDBSelectColumn(dbh, tableName, col, limit);
+    if (!stringColumn) {
+        // could be an error or the result set was just empty
+        return NULL;
+    }
+
+    psVector *column = psVectorAlloc(stringColumn->n, type);
+
+    // conversion functions are a portability issue
+    switch (type) {
+    case PS_DATA_S8:
+        PS_STR_ARRAY_TO_PTYPE(column->data.S8, stringColumn, atoi, psS8, PS_DATA_S8);
+        break;
+    case PS_DATA_S16:
+        PS_STR_ARRAY_TO_PTYPE(column->data.S16, stringColumn, atoi, psS16, PS_DATA_S16);
+        break;
+    case PS_DATA_S32:
+        PS_STR_ARRAY_TO_PTYPE(column->data.S32, stringColumn, atoi, psS32, PS_DATA_S32);
+        break;
+    case PS_DATA_S64:
+        PS_STR_ARRAY_TO_PTYPE(column->data.S64, stringColumn, atoll, psS64, PS_DATA_S64);
+        break;
+    case PS_DATA_U8:
+        PS_STR_ARRAY_TO_PTYPE(column->data.U8, stringColumn, atoi, psU8, PS_DATA_U8);
+        break;
+    case PS_DATA_U16:
+        PS_STR_ARRAY_TO_PTYPE(column->data.U16, stringColumn, atoi, psU16, PS_DATA_U16);
+        break;
+    case PS_DATA_U32:
+        PS_STR_ARRAY_TO_PTYPE(column->data.U32, stringColumn, atoi, psU32, PS_DATA_U32);
+        break;
+    case PS_DATA_U64:
+        PS_STR_ARRAY_TO_PTYPE(column->data.U64, stringColumn, atoll, psU64, PS_DATA_U64);
+        break;
+    case PS_DATA_F32:
+        PS_STR_ARRAY_TO_PTYPE(column->data.F32, stringColumn, atof, psF32, PS_DATA_F32);
+        break;
+    case PS_DATA_F64:
+        PS_STR_ARRAY_TO_PTYPE(column->data.F64, stringColumn, atof, psF64, PS_DATA_F64);
+        break;
+    case PS_DATA_BOOL:
+        // valid for psVector?
+        PS_STR_ARRAY_TO_PTYPE(column->data.U8, stringColumn, atoi, psU8, PS_DATA_U8);
+        break;
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                "Invalid type specified in psDBSelectColumnNum.\n");
+        psFree(stringColumn);
+        psFree(column);
+        return NULL;
+        break;
+    }
+
+    psFree(stringColumn);
+
+    return column;
+}
+
+psArray *psDBSelectRows(psDB *dbh,
+                        const char *tableName,
+                        const psMetadata *where,
+                        unsigned long long limit)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, NULL);
+    PS_ASSERT_PTR_NON_NULL(tableName, NULL);
+
+    // Create select row query
+    psString query = psDBGenerateSelectRowSQL(tableName, NULL, where, limit);
+    if (!query) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Query generation failed.");
+        return NULL;
+    }
+
+    // Run SQL query
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "Query execution failed.");
+        psFree(query);
+        return NULL;
+    }
+    psFree(query);
+
+    // return the result
+    return p_psDBFetchResult(dbh);
+}
+
+bool psDBInsertOneRow(psDB *dbh,
+                      const char *tableName,
+                      const psMetadata *row)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, false);
+    PS_ASSERT_PTR_NON_NULL(tableName, false);
+    PS_ASSERT_PTR_NON_NULL(row, false);
+
+    // Create array to store single row
+    psArray *rowSet = psArrayAllocEmpty(1);
+    psArrayAdd(rowSet, 0, (psPtr)row);
+
+    // Execute function to insert rows
+    if (!psDBInsertRows(dbh, tableName, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, _("Failed to insert row."));
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool psDBInsertRows(psDB *dbh,
+                    const char *tableName,
+                    const psArray *rowSet)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, false);
+    PS_ASSERT_PTR_NON_NULL(tableName, false);
+    PS_ASSERT_PTR_NON_NULL(rowSet, false);
+
+    // we are assuming that all rows in the set have an identical with reguard
+    // to field count and type
+    psMetadata *row = rowSet->data[0];
+
+    // Generate SQL query string
+    psString query = psDBGenerateInsertRowSQL(tableName, row);
+    if (!query) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, _("Query generation failed."));
+        return false;
+    }
+
+    if (p_psDBRunQueryPrepared(dbh, rowSet, query) < 0) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "insert failed");
+        psFree(query);
+        return false;
+    }
+
+    psFree(query);
+
+    return true;
+}
+
+psArray *psDBDumpRows(psDB *dbh,
+                      const char *tableName)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, false);
+    PS_ASSERT_PTR_NON_NULL(tableName, false);
+
+    return psDBSelectRows(dbh, tableName, NULL, 0);
+}
+
+psMetadata *psDBDumpCols(psDB *dbh,
+                         const char *tableName)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, false);
+    PS_ASSERT_PTR_NON_NULL(tableName, false);
+
+    MYSQL_RES       *result;
+    MYSQL_FIELD     *field;
+    unsigned int    fieldCount;
+    psU32           pType;
+    unsigned int    i;
+    psPtr           column;
+
+    // find column types
+    result = mysql_list_fields(dbh->mysql, tableName, NULL);
+    if (!result) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Failed to retrieve column types.");
+    }
+
+    field = mysql_fetch_fields(result);
+    fieldCount = mysql_num_fields(result);
+
+    // this metadata is returned
+    psMetadata *table = psMetadataAlloc();
+
+    // fetch each column and load into psMetadata
+    for (i =0; i < fieldCount; i++) {
+        // find ptype of column
+        pType = psDBMySQLToPType(field[i].type, field[i].flags);
+        if (!pType) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to lookup type.");
+            psFree(table);
+            mysql_free_result(result);
+            return NULL;
+        }
+        //psLogMsg( __func__, PS_LOG_INFO, "pType=[%ld]\n", pType );
+
+        // if the ptype is PS_DATA_PTR assume that it's a string and fetch the
+        // column as an psArray of strings; otherwise fetch the column as a
+        // psVector.
+        if (pType == PS_DATA_STRING) {
+            // PS_DATA_UNKNOWN -> PS_DATA_ARRAY ?
+            column = psDBSelectColumn(dbh, tableName, field[i].name, 0);
+            psMetadataAddArray(table, PS_LIST_TAIL, field[i].name, 0, "", column);
+            //            psMetadataAddStr(table, PS_LIST_TAIL, field[i].name, "", column);
+            psFree(column);
+        } else {
+            column = psDBSelectColumnNum(dbh, tableName, field[i].name, pType, 0);
+            psMetadataAddVector(table, PS_LIST_TAIL, field[i].name, 0, "", column);
+            psFree(column);
+        }
+    }
+
+    // Clean up mysql memory
+    mysql_free_result(result);
+
+    return table;
+}
+
+long psDBUpdateRows(psDB *dbh,
+                    const char *tableName,
+                    const psMetadata *where,
+                    psMetadata *values)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, -1);
+    PS_ASSERT_PTR_NON_NULL(tableName, -1);
+    PS_ASSERT_PTR_NON_NULL(values, -1);
+
+    // Generate SQL query to update row
+    psString query = psDBGenerateUpdateRowSQL(tableName, where, values);
+    if (!query) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, _("Query generation failed."));
+        return -1;
+    }
+
+    psArray *rowData = psArrayAllocEmpty(1);
+    psArrayAdd(rowData, 0, values);
+    long rowsAffected = p_psDBRunQueryPrepared(dbh, rowData, query);
+    psFree(rowData);
+    psFree(query);
+    if (rowsAffected < 0) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "update failed");
+        return -1;
+    }
+
+    return rowsAffected;
+}
+
+long psDBDeleteRows(psDB *dbh,
+                    const char *tableName,
+                    const psMetadata *where,
+                    unsigned long long limit)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, -1);
+    PS_ASSERT_PTR_NON_NULL(tableName, -1);
+
+    // Create SQL statement string
+    psString query = psDBGenerateDeleteRowSQL(tableName, where,limit);
+    if (!query) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Query generation failed.");
+        return -1;
+    }
+
+    // Run SQL query
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "Delete failed.");
+        mysql_rollback(dbh->mysql);
+        psFree(query);
+        return -1;
+    }
+    psFree(query);
+
+    // Get the number of affected row for the delete command
+    psS64 rows = (psS64)mysql_affected_rows(dbh->mysql);
+
+    return rows;
+}
+
+long long psDBLastInsertID(psDB *dbh)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, -1);
+
+    psTrace("psLib.db", PS_LOG_INFO, "calling myql_insert_id()");
+
+    // XXX return type is actually my_ulonglong - should the return be psU64?
+    long long id = (long long)mysql_insert_id(dbh->mysql);
+
+    psTrace("psLib.db", PS_LOG_INFO, "LAST_INSERT_ID == %lld", id);
+
+    return id;
+}
+
+bool psDBExplicitTrans(psDB *dbh, bool mode)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, -1);
+
+    psTrace("psLib.db", PS_LOG_INFO, "calling mysql_autocommit(): %u", !mode);
+
+    // mode needs to be inverted as autocommits are the opposide of explicit
+    // transactions.
+    // the return value also needs to be inverted for the same reason.
+    // is it safe to assume my_bool always safely casts to bool?
+    return !(bool)mysql_autocommit(dbh->mysql, !mode);
+}
+
+bool psDBTransaction(psDB *dbh)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, -1);
+
+    bool status = p_psDBRunQuery(dbh, "START TRANSACTION");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "Failed to start a new transaction.");
+    }
+
+    return status;
+}
+
+bool psDBCommit(psDB *dbh)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, -1);
+
+    psTrace("psLib.db", PS_LOG_INFO, "calling myql_commit()");
+
+    // is it safe to assume my_bool always safely casts to bool?
+    // mysql_commit - Zero if successful. Non-zero if an error occurred.
+    return !(bool)mysql_commit(dbh->mysql);
+}
+
+bool psDBRollback(psDB *dbh)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, -1);
+
+    psTrace("psLib.db", PS_LOG_INFO, "calling myql_rollback()");
+
+    // is it safe to assume my_bool always safely casts to bool?
+    // mysql_rollback - Zero if successful. Non-zero if an error occurred.
+    return !(bool)mysql_rollback(dbh->mysql);
+}
+
+psU64 psDBAffectedRows(psDB *dbh)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, (psU64)-1);
+
+    // mysql_affected_rows() returns (my_ulonglong)-1 on error
+    return (psU64)mysql_affected_rows(dbh->mysql);
+}
+
+// database utility functions
+/*****************************************************************************/
+
+bool p_psDBRunQuery(psDB *dbh,
+                    const char *format,
+                    ...)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, false);
+    PS_ASSERT_PTR_NON_NULL(format, false);
+
+    psString query = NULL;
+
+    // Run query
+    va_list ap;
+    va_start(ap, format);
+    psStringAppendV(&query, format, ap);
+    va_end(ap);
+
+    psTrace("psLib.db", PS_LOG_INFO, "Executing SQL:\n%s", query);
+
+    if (mysql_real_query(dbh->mysql, query, (unsigned long)strlen(query)) !=0) {
+        psError(mysqlTopsErr(dbh->mysql), true, _("Failed to execute SQL query.  Error: %s"), mysql_error(dbh->mysql));
+        psFree(query);
+        return false;
+    }
+
+    psFree(query);
+
+    return true;
+}
+
+long p_psDBRunQueryPrepared(psDB *dbh,
+                            const psArray *rowSet,
+                            const char *format,
+                            ...)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, -1);
+    PS_ASSERT_PTR_NON_NULL(rowSet, -1);
+    PS_ASSERT_PTR_NON_NULL(format, -1);
+
+    psString query = NULL;
+
+    // start lock on query cache
+    if (psMemGetThreadSafety()) {
+        pthread_mutex_lock(&preparedQueryMutex);
+    }
+
+    // initalize the prepared query cache
+    if (!preparedQuery) {
+        preparedQuery = psHashAlloc(10);
+        psMemSetPersistent(preparedQuery, true);
+    }
+
+    // generate query string
+    va_list ap;
+    va_start(ap, format);
+    psStringAppendV(&query, format, ap);
+    va_end(ap);
+
+    psTrace("psLib.db", PS_LOG_INFO, "Preparing SQL:\n%s", query);
+
+    // check the query cache
+    MYSQL_STMT **stmt = psHashLookup(preparedQuery, query);
+    if (!stmt) {
+        psTrace("psLib.db", PS_LOG_INFO, "statment is not in query cache");
+
+        // Prepare SQL statement
+        stmt = psAlloc(sizeof(MYSQL_STMT *));
+        *stmt = mysql_stmt_init(dbh->mysql);
+        if (!stmt) {
+            psAbort("mysql_stmt_init(), out of memory.");
+        }
+        if (mysql_stmt_prepare(*stmt, query, (unsigned long)strlen(query))) {
+            psError(PS_ERR_UNKNOWN, true, "Failed to prepare query.  Error: %s", mysql_stmt_error(*stmt));
+            mysql_stmt_close(*stmt);
+            psFree(query);
+
+            // end lock on query cache
+            if (psMemGetThreadSafety()) {
+                pthread_mutex_unlock(&preparedQueryMutex);
+            }
+
+            return -1;
+        }
+
+        // add this statement to the cache
+        psHashAdd(preparedQuery, query, stmt);
+    } else {
+        psTrace("psLib.db", PS_LOG_INFO, "found statment in query cache");
+    }
+
+    // end lock on query cache
+    if (psMemGetThreadSafety()) {
+        pthread_mutex_unlock(&preparedQueryMutex);
+    }
+
+    psFree(query);
+
+    // how many place holders are in our query
+    psS32 paramCount = mysql_stmt_param_count(*stmt);
+
+    // structure large enough to hold one field of data per place holder
+    psDBMysqlRow *mysqlRow = psDBMysqlRowAlloc(paramCount);
+
+    // loop over rows
+    for (long j = 0; j < rowSet->n; j++) {
+        psMetadata *rowData = rowSet->data[j];
+
+        if (!psDBPackMySQLRow(mysqlRow, rowData)) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to pack params into bind structure.");
+
+            psFree(mysqlRow);
+//            mysql_stmt_close(stmt);
+
+            return -1;
+        }
+
+        if (psTraceGetLevel("psLib.db") >= PS_LOG_INFO) {
+            psString binding = psMetadataConfigFormat(rowData);
+            psTrace("psLib.db", PS_LOG_INFO, "Binding:\n%s", binding);
+            psFree(binding);
+        }
+
+        if (mysql_stmt_bind_param(*stmt, mysqlRow->bind)) {
+            psError(PS_ERR_UNKNOWN, true, "Failed to bind params.  Error: %s", mysql_stmt_error(*stmt));
+
+            psFree(mysqlRow);
+//           mysql_stmt_close(stmt);
+
+            return -1;
+        }
+
+        if (mysql_stmt_execute(*stmt)) {
+            psError(PS_ERR_UNKNOWN, true, "Failed to execute prepared statement.  Error: %s", mysql_stmt_error(*stmt));
+
+            psFree(mysqlRow);
+//            mysql_stmt_close(stmt);
+
+            return -1;
+        }
+
+        // free temporary buffers
+        psDBMysqlRowRecycle(mysqlRow);
+
+    } // end loop over rows
+
+    psFree(mysqlRow);
+
+    // FYI mysql_stmt_affected_rows() must be called before a commit
+    long rowsAffected = mysql_stmt_affected_rows(*stmt);
+
+//    mysql_stmt_close(stmt);
+
+    return rowsAffected;
+}
+
+psArray *p_psDBFetchResult(psDB *dbh)
+{
+    PS_ASSERT_PTR_NON_NULL(dbh, NULL);
+
+    MYSQL_RES       *result;            // complete db result set
+    MYSQL_ROW       row;                // single row of db result set
+    MYSQL_FIELD     *field;             // field type info
+    my_ulonglong    rowCount;           // number of rows in db result set
+    unsigned int    fieldCount;         // number of fields in db result set
+    unsigned long   *fieldLength;       // field sizes
+    long            len;                // field length
+    psArray         *resultSet;         // return array
+    int             i;                  // field index
+    psMetadata      *md;                // a row
+    psU32           pType;              // psElemType of a field
+    psPtr           data;               // copy of result field
+
+    result = mysql_store_result(dbh->mysql);
+    if (!result) {
+        // no result set
+        fieldCount = mysql_field_count(dbh->mysql);
+
+        // we're going to exit no matter what after this point
+        mysql_free_result(result);
+
+        // if field count is zero the query should have returned no data.  If
+        // it's non-zero then something bad has happened.
+        if (fieldCount != 0) {
+            psError(mysqlTopsErr(dbh->mysql), true, "Query returned no data.  Error: %s", mysql_error(dbh->mysql));
+
+            return NULL;
+        }
+
+        return psArrayAlloc(0);
+    }
+
+    rowCount = mysql_num_rows(result);
+    // XXX has mysql's semantics changed?  If this is zero then why was a
+    // result set returned?
+    if (rowCount == 0) {
+        mysql_free_result(result);
+        // occording to popular opinion a query that succeeds but returns no
+        // data should return an empty array -- this is somewhat inefficent -JH
+        return psArrayAlloc(0);
+    }
+
+    // pre-allocate enough elements to hold the complete result set
+    // then reset n to 0 so elements are added from the beginning of
+    // the array
+    resultSet = psArrayAllocEmpty(rowCount);
+
+    field = mysql_fetch_fields(result);
+    fieldCount = mysql_num_fields(result);
+
+    psTrace("psLib.db", PS_LOG_INFO, "query returned %lld rows with %d fields",             rowCount, fieldCount);
+
+    while ((row = mysql_fetch_row(result))) {
+        // allocate new psMetadata to represent a row
+        md = psMetadataAlloc();
+
+        fieldLength = mysql_fetch_lengths(result);
+
+        for (i = 0; i < fieldCount; i++) {
+            // lookup MySQL column type
+            pType = psDBMySQLToPType(field[i].type, field[i].flags);
+            if (!pType) {
+                psError(PS_ERR_UNKNOWN, false, "Failed to lookup type.");
+                psFree(md);
+                mysql_free_result(result);
+                psFree(resultSet);
+                return NULL;
+            }
+
+            len = fieldLength[i];
+            if (len) {
+                // copy the data out of the result set struct
+                data = psAlloc(len + 1);
+                memcpy(data, row[i], len);
+                ((char*)data)[len] = '\0';
+            } else {
+                // if len is zero then the value is NULL
+                psTrace("psLib.db", PS_LOG_INFO, "database field name %s contains a NULL", field[i].name);
+                data = psDBGetPTypeNaN(pType);
+                if (!psMetadataAdd(md, PS_LIST_TAIL, field[i].name, pType, "", data)) {
+                    psError(PS_ERR_UNKNOWN, false, "Failed to add item %s", field[i].name);
+                    psFree(data);
+                    psFree(md);
+                    mysql_free_result(result);
+                    psFree(resultSet);
+                    return NULL;
+                }
+                psFree(data);
+                continue;
+            }
+
+            switch (pType) {
+            case PS_DATA_STRING:
+                if (!psMetadataAddStr(md, PS_LIST_TAIL, field[i].name, 0, "", data)) {
+                    psError(PS_ERR_UNKNOWN, false, "Failed to add item %s", field[i].name);
+                    psFree(data);
+                    psFree(md);
+                    mysql_free_result(result);
+                    psFree(resultSet);
+                    return NULL;
+                }
+                break;
+            case PS_DATA_U8:
+                if (!psMetadataAddU8(md, PS_LIST_TAIL, field[i].name, 0, "",(psU8)atoll(data))) {
+                    psError(PS_ERR_UNKNOWN, false, "Failed to add item %s", field[i].name);
+                    psFree(data);
+                    psFree(md);
+                    mysql_free_result(result);
+                    psFree(resultSet);
+                    return NULL;
+                }
+                break;
+            case PS_DATA_U16:
+                if (!psMetadataAddU16(md, PS_LIST_TAIL, field[i].name, 0, "",(psU16)atoll(data))) {
+                    psError(PS_ERR_UNKNOWN, false, "Failed to add item %s", field[i].name);
+                    psFree(data);
+                    psFree(md);
+                    mysql_free_result(result);
+                    psFree(resultSet);
+                    return NULL;
+                }
+                break;
+            case PS_DATA_U32:
+                if (!psMetadataAddU32(md, PS_LIST_TAIL, field[i].name, 0, "",(psU32)atoll(data))) {
+                    psError(PS_ERR_UNKNOWN, false, "Failed to add item %s", field[i].name);
+                    psFree(data);
+                    psFree(md);
+                    mysql_free_result(result);
+                    psFree(resultSet);
+                    return NULL;
+                }
+                break;
+            case PS_DATA_U64:
+                if (!psMetadataAddU64(md, PS_LIST_TAIL, field[i].name, 0, "",(psU64)atoll(data))) {
+                    psError(PS_ERR_UNKNOWN, false, "Failed to add item %s", field[i].name);
+                    psFree(data);
+                    psFree(md);
+                    mysql_free_result(result);
+                    psFree(resultSet);
+                    return NULL;
+                }
+                break;
+            case PS_DATA_S8:
+                if (!psMetadataAddS8(md, PS_LIST_TAIL, field[i].name, 0, "", (psS8)atoll(data))) {
+                    psError(PS_ERR_UNKNOWN, false, "Failed to add item %s", field[i].name);
+                    psFree(data);
+                    psFree(md);
+                    mysql_free_result(result);
+                    psFree(resultSet);
+                    return NULL;
+                }
+                break;
+            case PS_DATA_S16:
+                if (!psMetadataAddS16(md, PS_LIST_TAIL, field[i].name, 0, "", (psS16)atoll(data))) {
+                    psError(PS_ERR_UNKNOWN, false, "Failed to add item %s", field[i].name);
+                    psFree(data);
+                    psFree(md);
+                    mysql_free_result(result);
+                    psFree(resultSet);
+                    return NULL;
+                }
+                break;
+            case PS_DATA_S32:
+                if (!psMetadataAddS32(md, PS_LIST_TAIL, field[i].name, 0, "", (psS32)atoll(data))) {
+                    psError(PS_ERR_UNKNOWN, false, "Failed to add item %s", field[i].name);
+                    psFree(data);
+                    psFree(md);
+                    mysql_free_result(result);
+                    psFree(resultSet);
+                    return NULL;
+                }
+                break;
+            case PS_DATA_S64:
+                if (!psMetadataAddS64(md, PS_LIST_TAIL, field[i].name, 0, "", (psS64)atoll(data))) {
+                    psError(PS_ERR_UNKNOWN, false, "Failed to add item %s", field[i].name);
+                    psFree(data);
+                    psFree(md);
+                    mysql_free_result(result);
+                    psFree(resultSet);
+                    return NULL;
+                }
+                break;
+            case PS_DATA_F32:
+                if (!psMetadataAddF32(md, PS_LIST_TAIL, field[i].name, 0, "", atof(data))) {
+                    psError(PS_ERR_UNKNOWN, false, "Failed to add item %s", field[i].name);
+                    psFree(data);
+                    psFree(md);
+                    mysql_free_result(result);
+                    psFree(resultSet);
+                    return NULL;
+                }
+                break;
+            case PS_DATA_F64:
+                if (!psMetadataAddF64(md, PS_LIST_TAIL, field[i].name, 0, "", atof(data))) {
+                    psError(PS_ERR_UNKNOWN, false, "Failed to add item %s", field[i].name);
+                    psFree(data);
+                    psFree(md);
+                    mysql_free_result(result);
+                    psFree(resultSet);
+                    return NULL;
+                }
+                break;
+            case PS_DATA_BOOL:
+                if (!psMetadataAddBool(md, PS_LIST_TAIL, field[i].name, 0, "", (bool)atoi(data))) {
+                    psError(PS_ERR_UNKNOWN, false, "Failed to add item %s", field[i].name);
+                    psFree(data);
+                    psFree(md);
+                    mysql_free_result(result);
+                    psFree(resultSet);
+                    return NULL;
+                }
+                break;
+            case PS_DATA_TIME:
+                // just pass NULL values through as there is currently no
+                // concept of a psTime with a NULL value
+                if (!(char *)data) {
+                    if (!psMetadataAddTime(md, PS_LIST_TAIL, field[i].name, 0, "", NULL)) {
+                        psError(PS_ERR_UNKNOWN, false, "Failed to add item %s", field[i].name);
+                        psFree(data);
+                        psFree(md);
+                        mysql_free_result(result);
+                        psFree(resultSet);
+                        return NULL;
+                    }
+                } else if (psStrcasestr(data, "0000-00-00 00:00:00")) {
+                    // look for 0000-00-00 00:00:00, which can't be parsed by
+                    // psTimeStrptime as the month/day are bogus
+                    if (!psMetadataAddTime(md, PS_LIST_TAIL, field[i].name, 0, "", NULL)) {
+                        psError(PS_ERR_UNKNOWN, false, "Failed to add item %s", field[i].name);
+                        psFree(data);
+                        psFree(md);
+                        mysql_free_result(result);
+                        psFree(resultSet);
+                        return NULL;
+                    }
+                } else {
+                    psTime *time = psTimeStrptime((char *)data, "%EY-%m-%d%t%T");
+                    if (!time) {
+                        psError(PS_ERR_UNKNOWN, true, "error parsing MySQL DateTime string");
+                        psFree(md);
+                        mysql_free_result(result);
+                        psFree(resultSet);
+                        return NULL;
+                    }
+                    if (!psMetadataAddTime(md, PS_LIST_TAIL, field[i].name, 0, "", time)) {
+                        psError(PS_ERR_UNKNOWN, false, "Failed to add item %s", field[i].name);
+                        psFree(data);
+                        psFree(md);
+                        mysql_free_result(result);
+                        psFree(resultSet);
+                        return NULL;
+                    }
+                    psFree(time);
+                }
+                break;
+                #if 0
+                // this is the procedure needed for stmt
+                MYSQL_TIME *myTime = (MYSQL_TIME *)&data;
+                // convert MYSQL_TIME to struct tm
+                struct tm tmTime;
+                tmTime.tm_year  = (int)myTime->year - 1900;
+                tmTime.tm_mon   = (int)myTime->month - 1;
+                tmTime.tm_mday  = (int)myTime->day;
+                tmTime.tm_hour  = (int)myTime->hour;
+                tmTime.tm_min   = (int)myTime->minute;
+                tmTime.tm_sec   = (int)myTime->second;
+                // assume for the time being that we don't have negative time
+                //(bool)myTime->neg
+                // currently unused by mysql nor does struct tm support it
+                // (unsigned long)myTime->second_part;
+                psTime *time = psTimeFromTM(&tmTime);
+                psMetadataAddTime(md, PS_LIST_TAIL, field[i].name, 0, "",
+                                  time);
+                psFree(time);
+                #endif
+
+            default:
+                psError(PS_ERR_BAD_PARAMETER_TYPE , true,
+                        "field name: %s FIXME: Only type of "
+                        "PS_DATA_U8 (PS_DATA_U8), "
+                        "PS_DATA_U16 (PS_DATA_U16), "
+                        "PS_DATA_U32 (PS_DATA_U32), "
+                        "PS_DATA_U64 (PS_DATA_U64), "
+                        "PS_DATA_S8 (PS_DATA_S8), "
+                        "PS_DATA_S16 (PS_DATA_S16), "
+                        "PS_DATA_S32 (PS_DATA_S32), "
+                        "PS_DATA_S64 (PS_DATA_S64), "
+                        "PS_DATA_F32 (PS_DATA_F32), "
+                        "PS_DATA_F64 (PS_DATA_F64), "
+                        "PS_DATA_BOOL (PS_DATA_BOOL), "
+                        "PS_DATA_STRING "
+                        "and PS_DATA_TIME are supported.", field[i].name);
+                psFree(data);
+                psFree(md);
+                mysql_free_result(result);
+                psFree(resultSet);
+                return NULL;
+            }
+
+            psFree(data);
+        }
+
+        if (psTraceGetLevel("psLib.db") >= PS_LOG_INFO) {
+            psString rowString = psMetadataConfigFormat(md);
+            psTrace("psLib.db", PS_LOG_INFO, "adding row to result set:\n %s", rowString);
+            psFree(rowString);
+        }
+
+        // add row to result set
+        psArrayAdd(resultSet, 0, md);
+        psFree(md);
+    }
+
+    mysql_free_result(result);
+
+
+    return resultSet;
+}
+
+static inline bool psDBPackMySQLRow(psDBMysqlRow *mysqlRow,
+                                    const psMetadata *values)
+{
+    PS_ASSERT_PTR_NON_NULL(mysqlRow, false);
+    PS_ASSERT_PTR_NON_NULL(values, false);
+
+    mysqlType       *mType;             // type tmp variable
+    static bool     isNull = true;      // used in a MYSQL_BIND to indicate NULL
+
+    MYSQL_BIND *bind = mysqlRow->bind;
+
+    // row iterator
+    // check size of values == paramCount ?
+    psListIterator *cursor = psListIteratorAlloc(values->list, 0, false);
+
+    // loop over fields
+    psMetadataItem *item = NULL;              // field in row
+    for (psU32 i = 0; (item = psListGetAndIncrement(cursor)); i++) {
+        // lookup pType -> mysql type
+        mType = psDBPTypeToMySQL(item->type);
+
+        bind[i].buffer_type = mType->type;
+        bind[i].is_unsigned = mType->isUnsigned;
+
+        psFree(mType);
+
+        // input data length is determined by the MYSQL_TYPE_* unless it's a
+        // string
+        switch (item->type) {
+        case PS_DATA_U8: {
+                bind[i].length  = 0;
+                bind[i].buffer  = &item->data.U8;
+                bind[i].is_null = psDBIsPTypeNaN(item->type, &item->data.U8)
+                                  ? (my_bool *)&isNull
+                                  : NULL;
+                break;
+            }
+        case PS_DATA_U16: {
+                bind[i].length  = 0;
+                bind[i].buffer  = &item->data.U16;
+                bind[i].is_null = psDBIsPTypeNaN(item->type, &item->data.U16)
+                                  ? (my_bool *)&isNull
+                                  : NULL;
+                break;
+            }
+        case PS_DATA_U32: {
+                bind[i].length  = 0;
+                bind[i].buffer  = &item->data.U32;
+                bind[i].is_null = psDBIsPTypeNaN(item->type, &item->data.U32)
+                                  ? (my_bool *)&isNull
+                                  : NULL;
+                break;
+            }
+        case PS_DATA_U64: {
+                bind[i].length  = 0;
+                bind[i].buffer  = &item->data.U64;
+                bind[i].is_null = psDBIsPTypeNaN(item->type, &item->data.U64)
+                                  ? (my_bool *)&isNull
+                                  : NULL;
+                break;
+            }
+        case PS_DATA_S8: {
+                bind[i].length  = 0;
+                bind[i].buffer  = &item->data.S8;
+                bind[i].is_null = psDBIsPTypeNaN(item->type, &item->data.S8)
+                                  ? (my_bool *)&isNull
+                                  : NULL;
+                break;
+            }
+        case PS_DATA_S16: {
+                bind[i].length  = 0;
+                bind[i].buffer  = &item->data.S16;
+                bind[i].is_null = psDBIsPTypeNaN(item->type, &item->data.S16)
+                                  ? (my_bool *)&isNull
+                                  : NULL;
+                break;
+            }
+        case PS_DATA_S32: {
+                bind[i].length  = 0;
+                bind[i].buffer  = &item->data.S32;
+                bind[i].is_null = psDBIsPTypeNaN(item->type, &item->data.S32)
+                                  ? (my_bool *)&isNull
+                                  : NULL;
+                break;
+            }
+        case PS_DATA_S64: {
+                bind[i].length  = 0;
+                bind[i].buffer  = &item->data.S64;
+                bind[i].is_null = psDBIsPTypeNaN(item->type, &item->data.S64)
+                                  ? (my_bool *)&isNull
+                                  : NULL;
+                break;
+            }
+        case PS_DATA_F32: {
+                bind[i].length  = 0;
+                bind[i].buffer  = &item->data.F32;
+                bind[i].is_null = psDBIsPTypeNaN(item->type, &item->data.F32)
+                                  ? (my_bool *)&isNull
+                                  : NULL;
+                break;
+            }
+        case PS_DATA_F64: {
+                bind[i].length  = 0;
+                bind[i].buffer  = &item->data.F64;
+                bind[i].is_null = psDBIsPTypeNaN(item->type, &item->data.F64)
+                                  ? (my_bool *)&isNull
+                                  : NULL;
+                break;
+            }
+        case PS_DATA_BOOL: {
+                // XXX: ASC HACK NOTE (2005/06/03): set extreme bytes to the
+                // boolean character value.  sizeof(bool)==4 which triggers
+                // an endianess issue in the MySQL conversion (reading only 1
+                // byte), on Macintosh hardware (and maybe others?)
+                unsigned int c  = (unsigned int)item->data.B;
+                item->data.S32  = (unsigned int)((c<<24) | c);
+                bind[i].length  = 0;
+                bind[i].buffer  = &item->data.B;
+                bind[i].is_null = psDBIsPTypeNaN(item->type, &item->data.B)
+                                  ? (my_bool *)&isNull
+                                  : NULL;
+                break;
+            }
+        case PS_DATA_STRING: {
+                // convert NaNs to NULL and set the buffer_length for strings
+
+                if (item->data.str) {
+                    // will handle the case of "" as a NULL database value
+                    bind[i].buffer_length = (unsigned long)strlen(item->data.str);
+                    bind[i].length  = &bind[i].buffer_length;
+                    bind[i].buffer  = psStringCopy(item->data.V);
+                    bind[i].is_null = *item->data.str == '\0'
+                                      ? (my_bool *)&isNull
+                                      : NULL;
+                } else {
+                    // handles the case of NULL as a NULL database value
+                    bind[i].buffer_length = 0;
+                    bind[i].length  = &bind[i].buffer_length;
+                    bind[i].buffer  = NULL;
+                    bind[i].is_null = (my_bool *)&isNull;
+                }
+                break;
+            }
+        case PS_DATA_TIME: {
+                // XXX we're abusing the comment field of the metadata item
+                // here as we need to have a buffer that exists outside this
+                // functions scope without leaking memory make a copy of the
+                // psTime so we don't modify user data when we try to do the
+                // conversion
+                if (item->data.V) {
+                    psTime *time = (psTime *)item->data.V;
+                    struct tm *tmTime = psTimeToTM(time);
+                    if (!tmTime) {
+                        psError(PS_ERR_UNKNOWN, false, _("failed to convert psTime to struct tm"));
+                        psFree(cursor);
+
+                        return false;
+                    }
+
+                    // XXX it wouldn't hurt to make this conversion it's own
+                    // function myTime is used as the 'buffer' so it doesn't
+                    // have to be free'd
+                    MYSQL_TIME *myTime = psAlloc(sizeof(MYSQL_TIME));
+                    myTime->year    = (unsigned int)tmTime->tm_year + 1900;
+                    myTime->month   = (unsigned int)tmTime->tm_mon + 1;
+                    myTime->day     = (unsigned int)tmTime->tm_mday;
+                    myTime->hour    = (unsigned int)tmTime->tm_hour;
+                    myTime->minute  = (unsigned int)tmTime->tm_min;
+                    myTime->second  = (unsigned int)tmTime->tm_sec;
+                    // assume for the time being that we don't have negative
+                    // time as ISO8601 doesn't support dates prior to 0
+                    myTime->neg     = (my_bool)false;
+                    // currently unused by mysql
+                    myTime->second_part  = (unsigned long)time->nsec;
+                    psFree(tmTime);
+
+                    bind[i].buffer  = myTime;
+                    bind[i].buffer_length = sizeof(MYSQL_TIME);
+                    bind[i].length  = &bind[i].buffer_length;
+                    bind[i].is_null = NULL;
+                } else {
+                    // handles the case of NULL as a NULL database value
+                    bind[i].buffer_length = 0;
+                    bind[i].length  = &bind[i].buffer_length;
+                    bind[i].buffer  = NULL;
+                    bind[i].is_null = (my_bool *)&isNull;
+                }
+                break;
+            }
+        default: {
+                psError(PS_ERR_BAD_PARAMETER_TYPE , true,
+                        "FIXME: Unsupported data type");
+                psFree(cursor);
+
+                return false;
+                break;                  // unreachable
+            }
+        }
+    }
+
+    psFree(cursor);
+
+    return true;
+}
+
+static psDBMysqlRow *psDBMysqlRowAlloc(psU32 paramCount)
+{
+    psDBMysqlRow *row = psAlloc(sizeof(psDBMysqlRow));
+    psMemSetDeallocator(row, (psFreeFunc)psDBMysqlRowFree);
+
+    row->bind = psAlloc(sizeof(MYSQL_BIND) * paramCount);
+    memset(row->bind, 0, sizeof(MYSQL_BIND) * paramCount);
+    row->n = paramCount;
+
+    return row;
+}
+
+static void psDBMysqlRowFree(psDBMysqlRow *mysqlRow)
+{
+    PS_ASSERT_PTR_NON_NULL(mysqlRow, );
+
+    MYSQL_BIND *bind = mysqlRow->bind;
+
+    psDBMysqlRowRecycle(mysqlRow);
+
+    psFree(bind);
+}
+
+static void psDBMysqlRowRecycle(psDBMysqlRow *mysqlRow)
+{
+    PS_ASSERT_PTR_NON_NULL(mysqlRow, );
+
+    MYSQL_BIND *bind = mysqlRow->bind;
+
+    for (psU32 i = 0; i < mysqlRow->n; i++) {
+        // buffer_length is only defined for pointers to character buffers
+        // primitive types will have this value set to zero.
+        if (bind[i].buffer_length) {
+            psFree(bind[i].buffer);
+        }
+    }
+
+    memset(bind, '\0', sizeof(MYSQL_BIND) * mysqlRow->n);
+}
+
+
+// SQL generation functions
+/*****************************************************************************/
+
+static psString psDBGenerateCreateTableSQL(const char *tableName,
+        const psMetadata *table)
+{
+    PS_ASSERT_PTR_NON_NULL(tableName, NULL);
+    PS_ASSERT_PTR_NON_NULL(table, NULL);
+
+    char            *query = NULL;      // complete query
+    psMetadataItem  *item;              // column description
+    psListIterator  *cursor;            // column iterator
+    char            *colType;           // type lookup table
+
+    // Begin to create SQL string to create table
+    psStringAppend(&query, "CREATE TABLE %s (", tableName);
+
+    // Set list iterator at head of list
+    cursor = psListIteratorAlloc(table->list, 0, false);
+
+    // find column name and type
+    while ((item = psListGetAndIncrement(cursor))) {
+        switch (item->type) {
+        case PS_DATA_U8:
+        case PS_DATA_U16:
+        case PS_DATA_U32:
+        case PS_DATA_U64:
+        case PS_DATA_S8:
+        case PS_DATA_S16:
+        case PS_DATA_S32:
+        case PS_DATA_S64:
+        case PS_DATA_F32:
+        case PS_DATA_F64:
+        case PS_DATA_BOOL:
+        case PS_DATA_TIME: {
+                // + column name + _ + column type
+                colType = psDBPTypeToSQL(item->type);
+                psStringAppend(&query, "%s %s", item->name, colType);
+                psFree(colType);
+                break;
+            }
+        case PS_DATA_STRING: {
+                // + column name + _ + varchar( + length + )
+                psStringAppend(&query, "%s VARCHAR(%s)", item->name, item->data.str);
+                break;
+            }
+        default: {
+                psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                        "FIXME: Unsupported data type %d", item->type);
+
+                psFree(query);
+                psFree(cursor);
+
+                return NULL;
+                break;                  // unreachable
+            }
+        }
+
+        if (psStrcasestr(item->comment, "AUTO_INCREMENT")) {
+            psStringAppend(&query, " %s", "AUTO_INCREMENT");
+        }
+        if (psStrcasestr(item->comment, "Unique")) {
+            psStringAppend(&query, " %s", "UNIQUE");
+        }
+        if (psStrcasestr(item->comment, "NOT NULL")) {
+            psStringAppend(&query, " %s", "NOT NULL");
+        }
+
+        // add a , after every column declaration except the last one
+        if (!cursor->offEnd) {
+            psStringAppend(&query, ", ");
+        }
+    }
+
+
+    // find database indexes
+    // check for Primary Keys first as they have to be part of the same Primary
+    // Key stmt
+    // Reset iterator to head of list
+    psListIteratorSet(cursor, 0);
+    psArray *pKeys = psArrayAllocEmpty(1);
+    while ((item = psListGetAndIncrement(cursor))) {
+        if (psStrcasestr(item->comment, "Primary Key")) {
+            psArrayAdd(pKeys, 0, item->name);
+        }
+    }
+    if (psArrayLength(pKeys)) {
+        psStringAppend(&query, ", PRIMARY KEY(");
+        for (int i = 0; i < psArrayLength(pKeys); i++) {
+            if (i < 1) {
+                psStringAppend(&query, "%s", (char *)pKeys->data[i]);
+            } else {
+                psStringAppend(&query, ", %s", (char *)pKeys->data[i]);
+            }
+        }
+        psStringAppend(&query, ")");
+    }
+    psFree(pKeys);
+
+    // Reset iterator to head of list
+    psListIteratorSet(cursor, 0);
+    // look for regular keys
+    while ((item = psListGetAndIncrement(cursor))) {
+        // it's just a regular key if it matchs "Key" but not "Primary Key"
+        if (psStrcasestr(item->comment, "Key")
+                && (psStrcasestr(item->comment, "Primary Key") == NULL)) {
+            psStringAppend(&query, ", KEY(%s)", item->name);
+        } else if (psStrcasestr(item->comment, "AUTO_INCREMENT")) {
+            // this needs to be recognized as a key if it wasn't already
+            psStringAppend(&query, ", KEY(%s)", item->name);
+        }
+    }
+
+
+    // Reset iterator to head of list
+    psListIteratorSet(cursor, 0);
+    // look for indexes
+    while ((item = psListGetAndIncrement(cursor))) {
+        // don't compile a regex unless we have too
+
+        if (psStrcasestr(item->comment, "UINDEX")) {
+            // look for UINDEXs before INDEXs
+            regex_t         myregex;
+            regmatch_t      mymatch[2];     // match + 1 sub strings
+            int             errbuf_size = 1024;
+            char            errbuf[errbuf_size];
+            char            *pattern = "UINDEX[:space:]*[(]([^)]*)";
+
+            int status = regcomp(&myregex, pattern, REG_EXTENDED|REG_ICASE);
+            if (status != 0) {
+                regerror(status, &myregex, errbuf, errbuf_size);
+                psError(PS_ERR_UNKNOWN, true, "regcomp() failed: %s", errbuf);
+                psFree(query);
+                psFree(cursor);
+                return NULL;
+            }
+
+            psTrace("psLib.db", 10, "trying regex pattern: %s against string: %s", pattern, item->comment);
+            status = regexec(&myregex, item->comment, 2, mymatch, 0);
+            if (status != 0) {
+                regerror(status, &myregex, errbuf, errbuf_size);
+                psError(PS_ERR_UNKNOWN, true, "regexec() failed: %s", errbuf);
+                psFree(query);
+                psFree(cursor);
+                return NULL;
+            }
+
+            regfree(&myregex);
+
+            // sub string 1: uindex(.*)
+            size_t matchStart = (size_t)mymatch[1].rm_so;
+            size_t matchEnd   = (size_t)mymatch[1].rm_eo;
+            size_t matchLength = matchEnd - matchStart;
+
+            if (matchStart == -1) {
+                psError(PS_ERR_UNKNOWN, true, "substring 1 failed to match");
+                psFree(query);
+                psFree(cursor);
+                return NULL;
+            }
+
+            psString index = psStringNCopy(item->comment + matchStart, matchLength);
+            psTrace("psLib.db", 10, "regex $1 matched: %s", index);
+            psStringAppend(&query, ", UNIQUE KEY(%s)", index);
+            psFree(index);
+        } else if (psStrcasestr(item->comment, "INDEX")) {
+            regex_t         myregex;
+            regmatch_t      mymatch[2];     // match + 1 sub strings
+            int             errbuf_size = 1024;
+            char            errbuf[errbuf_size];
+            // don't accidentally match uindex
+            char            *pattern = "[:space:]*INDEX[:space:]*[(]([^)]*)";
+
+            int status = regcomp(&myregex, pattern, REG_EXTENDED|REG_ICASE);
+            if (status != 0) {
+                regerror(status, &myregex, errbuf, errbuf_size);
+                psError(PS_ERR_UNKNOWN, true, "regcomp() failed: %s", errbuf);
+                psFree(query);
+                psFree(cursor);
+                return NULL;
+            }
+
+            psTrace("psLib.db", 10, "trying regex pattern: %s against string: %s", pattern, item->comment);
+            status = regexec(&myregex, item->comment, 2, mymatch, 0);
+            if (status != 0) {
+                regerror(status, &myregex, errbuf, errbuf_size);
+                psError(PS_ERR_UNKNOWN, true, "regexec() failed: %s", errbuf);
+                psFree(query);
+                psFree(cursor);
+                return NULL;
+            }
+
+            regfree(&myregex);
+
+            // sub string 1: index(.*)
+            size_t matchStart = (size_t)mymatch[1].rm_so;
+            size_t matchEnd   = (size_t)mymatch[1].rm_eo;
+            size_t matchLength = matchEnd - matchStart;
+
+            if (matchStart == -1) {
+                psError(PS_ERR_UNKNOWN, true, "substring 1 failed to match");
+                psFree(query);
+                psFree(cursor);
+                return NULL;
+            }
+
+            psString index = psStringNCopy(item->comment + matchStart, matchLength);
+            psTrace("psLib.db", 10, "regex $1 matched: %s", index);
+            psStringAppend(&query, ", INDEX(%s)", index);
+            psFree(index);
+        }
+    }
+
+    // Reset iterator to head of list
+    psListIteratorSet(cursor, 0);
+    // look for foreign keys after all other key types
+    while ((item = psListGetAndIncrement(cursor))) {
+        // don't compile a regex unless we have too
+        if (psStrcasestr(item->comment, "FKEY") == NULL) {
+            continue;
+        }
+        // find foreign key and references
+        regex_t         myregex;
+        regmatch_t      mymatch[3];     // match + 2 sub strings
+        int             errbuf_size = 1024;
+        char            errbuf[errbuf_size];
+        char            *pattern = "FKEY(.*)[:space:]*REF(.*)";
+
+        int status = regcomp(&myregex, pattern, REG_EXTENDED|REG_ICASE);
+        if (status != 0) {
+            regerror(status, &myregex, errbuf, errbuf_size);
+            psError(PS_ERR_UNKNOWN, true, "regcomp() failed: %s", errbuf);
+            psFree(query);
+            psFree(cursor);
+            return NULL;
+        }
+
+        psTrace("psLib.db", 10, "trying regex pattern: %s against string: %s", pattern, item->comment);
+        status = regexec(&myregex, item->comment, 3, mymatch, 0);
+        if (status != 0) {
+            regerror(status, &myregex, errbuf, errbuf_size);
+            psError(PS_ERR_UNKNOWN, true, "regexec() failed: %s", errbuf);
+            psFree(query);
+            psFree(cursor);
+            return NULL;
+        }
+
+        regfree(&myregex);
+
+        // sub string 1: foreign(.*)
+        size_t matchStart = (size_t)mymatch[1].rm_so;
+        size_t matchEnd   = (size_t)mymatch[1].rm_eo;
+        size_t matchLength = matchEnd - matchStart;
+
+        if (matchStart == -1) {
+            psError(PS_ERR_UNKNOWN, true, "substring 1 failed to match");
+            psFree(query);
+            psFree(cursor);
+            return NULL;
+        }
+
+        psString fkey = psStringNCopy(item->comment + matchStart, matchLength);
+        psTrace("psLib.db", 10, "regex $1 matched: %s", fkey);
+        psStringAppend(&query, ", FOREIGN KEY %s", fkey);
+        psFree(fkey);
+
+        // sub string 2: references(.*)
+        matchStart = (size_t)mymatch[2].rm_so;
+        matchEnd   = (size_t)mymatch[2].rm_eo;
+        matchLength = matchEnd - matchStart;
+
+        if (matchStart == -1) {
+            psError(PS_ERR_UNKNOWN, true, "substring 2 failed to match");
+            psFree(query);
+            psFree(cursor);
+            return NULL;
+        }
+
+        psString refs = psStringNCopy(item->comment + matchStart, matchLength);
+        psTrace("psLib.db", 10, "regex $2 matched: %s", refs);
+        psStringAppend(&query, " REFERENCES %s", refs);
+        psFree(refs);
+    }
+
+    psFree(cursor);
+
+    // end column types + table type
+    psStringAppend(&query, ") ENGINE=innodb");
+
+    return query;
+}
+
+static psString psDBGenerateSelectRowSQL(const char *tableName,
+        const char *col,
+        const psMetadata *where,
+        psU64 limit)
+{
+    PS_ASSERT_PTR_NON_NULL(tableName, NULL);
+
+    char            *query = NULL;
+    char            *whereSQL;
+    char            *limitString;
+
+    // select all columns if col is NULL
+    if (col) {
+        psStringAppend(&query, "SELECT %s FROM %s", col, tableName);
+    } else {
+        psStringAppend(&query, "SELECT * FROM %s", tableName);
+    }
+
+    // select all rows if where is NULL
+    if (where) {
+        whereSQL = psDBGenerateWhereSQL(where, tableName);
+        if (!whereSQL) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "SQL substring generation failed.");
+
+            psFree(query);
+
+            return NULL;
+        }
+        psStringAppend(&query, " %s", whereSQL);
+        psFree(whereSQL);
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    return query;
+}
+
+psString psDBGenerateLimitSQL(psU64 limit)
+{
+    psString query = NULL;
+
+    psString limitString = psDBIntToString(limit);
+    psStringAppend(&query, " LIMIT %s", limitString);
+    psFree(limitString);
+
+    return query;
+}
+
+static psString psDBGenerateInsertRowSQL(const char *tableName,
+        const psMetadata *row)
+{
+    PS_ASSERT_PTR_NON_NULL(tableName, NULL);
+    PS_ASSERT_PTR_NON_NULL(row, NULL);
+
+    char            *query = NULL;
+    psListIterator  *cursor;
+    psMetadataItem  *item;
+
+    // Start building query string
+    psStringAppend(&query, "INSERT INTO %s (", tableName);
+
+    cursor = psListIteratorAlloc(row->list, 0, false);
+
+    // get field names
+    while ((item = psListGetAndIncrement(cursor))) {
+        psStringAppend(&query, item->name);
+
+        // + , + _ between every field name
+        if (!cursor->offEnd) {
+            psStringAppend(&query, ", ");
+        }
+    }
+
+    // end of field names
+    psStringAppend(&query, ") VALUES (");
+
+    psListIteratorSet(cursor, 0);
+
+    // create value place holders
+    while ((item = psListGetAndIncrement(cursor))) {
+        psStringAppend(&query, "?");
+
+        // + ", " between every place holder
+        if (!cursor->offEnd) {
+            psStringAppend(&query, ", ");
+        }
+    }
+
+    psFree(cursor);
+
+    // end of values
+    psStringAppend(&query, ")");
+
+    return query;
+}
+
+static psString psDBGenerateUpdateRowSQL(const char *tableName,
+        const psMetadata *where,
+        const psMetadata *values)
+{
+    PS_ASSERT_PTR_NON_NULL(tableName, NULL);
+    PS_ASSERT_PTR_NON_NULL(values, NULL);
+
+    char            *query = NULL;
+    char            *setSQL;
+    char            *whereSQL;
+
+    // Create set SQL substring
+    setSQL = psDBGenerateSetSQL(values);
+    if (!setSQL) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, _("SQL substring generation failed."));
+        return NULL;
+    }
+
+    // Create where SQL substring
+    whereSQL = psDBGenerateWhereSQL(where, tableName);
+    if (!whereSQL) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, _("SQL substring generation failed."));
+        return NULL;
+    }
+
+    // Append substring to SQL update string
+    psStringAppend(&query, "UPDATE %s %s %s", tableName, setSQL, whereSQL);
+    psFree(setSQL);
+    psFree(whereSQL);
+
+    return query;
+}
+
+static psString psDBGenerateDeleteRowSQL(const char *tableName,
+        const psMetadata *where,
+        unsigned long long limit)
+{
+    PS_ASSERT_PTR_NON_NULL(tableName, NULL);
+
+    char            *query = NULL;
+    char            *whereSQL;
+    char            *limitString;
+
+    // delete all rows if where is NULL
+    if (!where) {
+        psStringAppend(&query, "TRUNCATE TABLE %s", tableName);
+        return query;
+    }
+
+    // Generate where SQL substring
+    whereSQL = psDBGenerateWhereSQL(where, tableName);
+    if (!whereSQL) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, _("SQL substring generation failed."));
+        return NULL;
+    }
+
+    psStringAppend(&query, "DELETE FROM %s %s", tableName, whereSQL);
+
+    // Complete delete SQL command string
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        limitString = psDBIntToString(limit);
+        psStringAppend(&query, " LIMIT %s", limitString);
+        psFree(limitString);
+    }
+    psFree(whereSQL);
+
+    return query;
+}
+
+psString psDBGenerateWhereSQL(const psMetadata *where, const char *tableName)
+{
+    PS_ASSERT_PTR_NON_NULL(where, NULL);
+
+    psString search = psDBGenerateWhereConditionSQL(where, tableName);
+    if (search) {
+        psStringPrepend(&search, "WHERE ");
+    }
+
+    return search;
+}
+
+psString psDBGenerateWhereConditionSQL(const psMetadata *where, const char *tableName)
+{
+    PS_ASSERT_PTR_NON_NULL(where, NULL);
+
+    psString query = NULL;
+
+    // we need to know if an item is 'MULTI' so we have to march through the
+    // list by key name and not by items
+    psList *keys = psHashKeyList(where->hash);
+    psListIterator *cursor = psListIteratorAlloc(keys, 0, false);
+
+    // find column name and match pattern
+    psString itemName = NULL;
+    while ((itemName = psListGetAndIncrement(cursor))) {
+        psMetadataItem *item = psMetadataLookup(where, itemName);
+
+        if (item->type == PS_DATA_METADATA_MULTI) {
+            char *logicalOp = "AND";
+
+            // scan through the list and change the logicalOp joining
+            // conditionals together to "OR" if a comment of "==" is found
+            psListIterator *mCursor = psListIteratorAlloc(item->data.list, 0,
+                                      false);
+            psMetadataItem *mItem = NULL;
+            while ((mItem = psListGetAndIncrement(mCursor))) {
+                if (mItem->comment && psStrcasestr(mItem->comment, "==")) {
+                    logicalOp = "OR";
+                    break;
+                }
+            }
+
+            // "(" + conditional [ + " AND/OR " + conditional ] + ")"
+            // reset the iterator
+            psListIteratorSet(mCursor, 0);
+            psStringAppend(&query, "(");
+            while ((mItem = psListGetAndIncrement(mCursor))) {
+                psString conditional = psDBGenerateConditionalSQL(mItem, tableName);
+                if (!conditional) {
+                    psError(PS_ERR_UNKNOWN, false,
+                            "SQL conditional generation failed.");
+                    psFree(mCursor);
+                    psFree(cursor);
+                    psFree(keys);
+                    psFree(query);
+                    return NULL;
+                }
+
+                psStringAppend(&query, "%s", conditional);
+                psFree(conditional);
+
+                // + " AND/OR "
+                if (!mCursor->offEnd) {
+                    psStringAppend(&query, " %s ", logicalOp);
+                }
+
+            }
+            psFree(mCursor);
+
+            psStringAppend(&query, ")");
+        } else {
+            psString conditional = psDBGenerateConditionalSQL(item, tableName);
+            if (!conditional) {
+                psError(PS_ERR_UNKNOWN, false,
+                        "SQL conditional generation failed.");
+                psFree(cursor);
+                psFree(keys);
+                psFree(query);
+                return NULL;
+            }
+
+            psStringAppend(&query, "%s", conditional);
+            psFree(conditional);
+        }
+
+        // + " and " after every column declaration except the last one
+        if (!cursor->offEnd) {
+            psStringAppend(&query, " AND ");
+        }
+    }
+
+    //    psFree(cursor);
+    psFree(keys);
+
+    return query;
+}
+
+static psString psDBGenerateSetSQL(const psMetadata *set
+                                  )
+{
+    PS_ASSERT_PTR_NON_NULL(set
+                           , NULL);
+
+    psString query = psStringCopy("SET ");
+
+    psListIterator *cursor = psListIteratorAlloc(set
+                             ->list, 0, false);
+
+    // find column name
+    psMetadataItem *item = NULL;
+    while ((item = psListGetAndIncrement(cursor))) {
+        // + column name + _ + = + _ + ?
+        psStringAppend(&query, "%s = ?", item->name);
+
+        // + ", " after every column declaration except the last one
+        if (!cursor->offEnd) {
+            psStringAppend(&query, ",  ");
+        }
+    }
+
+    psFree(cursor);
+
+    return query;
+}
+
+typedef enum {
+    PS_DB_OP_EQ,
+    PS_DB_OP_LT,
+    PS_DB_OP_GT,
+    PS_DB_OP_LE,
+    PS_DB_OP_GE,
+} psDBOpValue;
+
+# define PS_DB_FLT_PAD (FLT_EPSILON * 10)
+# define PS_DB_DBL_PAD (DBL_EPSILON * 10)
+
+static psString psDBGenerateConditionalSQL(const psMetadataItem *item, const char *tableName)
+{
+    PS_ASSERT_PTR_NON_NULL(item, NULL);
+
+    psString query = NULL;
+
+    // stringify the psMetadataItem into a SQL search specification
+    // XXX we're making a big assumption here that the MySQL server handles
+    // floating point in the exact same way as the client.  This is a bit scary
+    // as MySQL uses native types on the server end.  In theory all IEEE754
+    // math is the same but know that isn't always the case.  At least forcing
+    // the comparison to be done on the server provides some consistency
+    // between clients on different archs.
+
+    // if tableName is specified prepend it to the item name
+    psString itemName = NULL;
+    if (tableName) {
+        psStringAppend(&itemName, "%s.%s", tableName, item->name);
+    } else {
+        psStringAppend(&itemName, "%s", item->name);
+    }
+
+    // select the by of comparasion to use.  currently the comparision
+    // op value is only used by PS_DATA_S32 & PS_DATA_TIME
+
+    // default to exact match ('=')
+    char *opStr = "=";
+    psDBOpValue op = PS_DB_OP_EQ;
+    if (item->comment) {
+        // arbitrary semantic, precedence is: >=, <=, >, <, = (default)
+        if (strstr(item->comment, ">=")) {
+            opStr = ">=";
+            op = PS_DB_OP_GE;
+        } else if (strstr(item->comment, "<=")) {
+            opStr = "<=";
+            op = PS_DB_OP_LE;
+        } else if (strstr(item->comment, ">")) {
+            opStr = ">";
+            op = PS_DB_OP_GT;
+        } else if (strstr(item->comment, "<")) {
+            opStr = "<";
+            op = PS_DB_OP_LT;
+        }
+    }
+
+    // XXX why are >, < searches not supported here????
+    // fix this immediately!!
+    // for datetime comparisons, we need to use single-quotes around the string value:
+    // where dateobs < '2002-09-06' and dateobs > '2002-09-05,15:40:22'
+
+    switch (item->type) {
+    case PS_DATA_S8:
+    case PS_DATA_S16:
+    case PS_DATA_S32:
+        // the raw opStr is good enough in the query
+        psStringAppend(&query, "%s %s %d", itemName, opStr, (int)(item->data.S32));
+        break;
+    case PS_DATA_S64:
+        // the raw opStr is good enough in the query
+        psStringAppend(&query, "%s %s %" PRId64, itemName, opStr, item->data.S64);
+        break;
+    case PS_DATA_U8:
+    case PS_DATA_U16:
+    case PS_DATA_U32:
+        psStringAppend(&query, "%s %s %u", itemName, opStr, (unsigned int)(item->data.U32));
+        break;
+    case PS_DATA_U64:
+        // the raw opStr is good enough in the query
+        psStringAppend(&query, "%s %s %" PRIu64, itemName, opStr, item->data.U64);
+        break;
+    case PS_DATA_F32:
+        // need to handle floating-point round-off issues (use a padding of 10*FLT_EPSILON)
+        switch (op) {
+        case PS_DB_OP_EQ:
+            psStringAppend(&query, "(ABS(%s - %.8f) < %.8f)", itemName, (float)(item->data.F32), PS_DB_FLT_PAD);
+            break;
+        case PS_DB_OP_LE:
+        case PS_DB_OP_LT:
+            // A < B becomes A < B + epsilon
+            psStringAppend(&query, "(%s < %.8f + %.8f)", itemName, (float)(item->data.F32), PS_DB_FLT_PAD);
+            break;
+        case PS_DB_OP_GE:
+        case PS_DB_OP_GT:
+            // A > B becomes A > B - epsilon
+            psStringAppend(&query, "(%s > %.8f - %.8f)", itemName, (float)(item->data.F32), PS_DB_FLT_PAD);
+            break;
+        }
+        break;
+    case PS_DATA_F64:
+        // need to handle floating-point round-off issues (use a padding of 10*FLT_EPSILON)
+        switch (op) {
+        case PS_DB_OP_EQ:
+            psStringAppend(&query, "(ABS(%s - %.17f) < %.17f)", itemName, (float)(item->data.F64), PS_DB_DBL_PAD);
+            break;
+        case PS_DB_OP_LE:
+        case PS_DB_OP_LT:
+            // A < B becomes A < B + epsilon
+            psStringAppend(&query, "(%s < %.17f + %.17f)", itemName, (float)(item->data.F64), PS_DB_DBL_PAD);
+            break;
+        case PS_DB_OP_GE:
+        case PS_DB_OP_GT:
+            // A > B becomes A > B - epsilon
+            psStringAppend(&query, "(%s > %.17f - %.17f)", itemName, (float)(item->data.F64), PS_DB_DBL_PAD);
+            break;
+        }
+        break;
+    case PS_DATA_BOOL:
+        switch (op) {
+        case PS_DB_OP_EQ:
+            psStringAppend(&query, "%s = %d", itemName, (int)(item->data.B));
+            break;
+        default:
+            psError(PS_ERR_UNKNOWN, true, "NULL bool can't be compared with any operator other than '=='");
+            psFree(itemName);
+            return NULL;
+        }
+        break;
+    case PS_DATA_STRING:
+        // XXX EAM : probably need to add some regex-like operations here
+        // + column name + _ + like + _ + ' + value + '
+        // check for NULL and empty ("") strings
+        if (item->data.V == NULL || *item->data.str == '\0') {
+            psStringAppend(&query, "%s IS NULL", itemName);
+        } else {
+            if (item->comment && psStrcasestr(item->comment, "LIKE")) {
+                // XXX ASC NOTE: we should have a better match for
+                // char & varchar columns than this.  LIKE is OK for
+                // very large TEXT columns that really shouldn't be
+                // used in a where clause...
+                psStringAppend(&query, "%s LIKE '%s'", itemName, item->data.str);
+            } else {
+                psStringAppend(&query, "%s = '%s'", itemName, item->data.str);
+            }
+        }
+        break;
+    case PS_DATA_TIME: {
+            if (item->data.V) {
+                psString timeStr = psTimeToISO(item->data.V);
+                psStringAppend(&query, "%s %s '%s'", itemName, opStr, timeStr);
+                psFree(timeStr);
+            } else if (strstr(opStr, "=")) {
+                psStringAppend(&query, "%s IS NULL", itemName);
+            } else {
+                psError(PS_ERR_UNKNOWN, true, "psTime comparison value is NULL: A NULL psTime value can't be compared with any operator other than '=='");
+                psFree(itemName);
+                return NULL;
+            }
+
+            break;
+        }
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                "Fixme: Unsupported data type");
+        psFree(itemName);
+
+        return NULL;
+    }
+
+    psFree(itemName);
+
+    return query;
+}
+
+
+// lookup table functions
+/*****************************************************************************/
+
+static psElemType psDBMySQLToPType(enum enum_field_types type,
+                                   unsigned int flags)
+{
+    psHash          *mysqlToSQLTable;   // type lookup table
+    psHash          *sqlToPSTable;      // type lookup table
+    char            *key;               // hash tmp value
+    char            *value;             // hash tmp value
+    psString        sqlType;            // copy of lookup table result
+    psU32           pType;              // psElemType of a field
+
+    mysqlToSQLTable = psDBMySQLToSQLTableGet();
+
+    // lookup MySQL column type
+    key     = psDBIntToString((psU64)type);
+    sqlType = psMemIncrRefCounter(psHashLookup(mysqlToSQLTable, key));
+    psFree(key);
+
+    if (!sqlType) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "type lookup failed.");
+        return 0;
+    }
+
+    // MySQL column types can not be directly translated to PS
+    // types as the the mysql types do not tell you if the value is
+    // signed or unsigned.  The result is this ugly conversion from
+    // mysql -> ascii -> ptype
+    // XXX it appears that TIMESTAMP fields get marked as being unsigned...
+    if ((flags & UNSIGNED_FLAG) && strncmp(sqlType, "DATETIME", 9)) {
+        psString new = NULL;
+        psStringAppend(&new, "%s UNSIGNED", sqlType);
+        psFree(sqlType);
+        sqlType = new;
+    }
+
+    //psTrace("psLib.db", 9, "sqlType=[%s]\n", sqlType );
+
+    // convert MySQL type to PS type
+    sqlToPSTable = psDBSQLToPTypeTableGet();
+    value = psHashLookup(sqlToPSTable, sqlType);
+
+    if (!value) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "type lookup of %s failed.", sqlType);
+        psFree(sqlType);
+        return 0;
+    }
+    psFree(sqlType);
+
+    pType = (psU32)atol(value);
+
+    return pType;
+}
+
+static psString psDBPTypeToSQL(psElemType pType)
+{
+    psHash          *pTypeToSQLTable;   // type lookup table
+    char            *key;               // hash tmp value
+    char            *sqlType;             // hash tmp value
+
+    pTypeToSQLTable = psDBPTypeToSQLTableGet();
+
+    key = psDBIntToString((psU64)pType);
+    sqlType = psHashLookup(pTypeToSQLTable, key);
+    psFree(key);
+
+    if (!sqlType) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "type lookup failed.");
+
+        return NULL;
+    }
+
+    psMemIncrRefCounter(sqlType);
+
+    return sqlType;
+}
+
+static mysqlType *psDBPTypeToMySQL(psElemType pType)
+{
+    psHash          *pTypeToMySQLTable; // type lookup table
+    char            *key;               // hash tmp value
+    mysqlType       *mType;             // mysqlType struct to return
+
+    pTypeToMySQLTable = psDBPTypeToMySQLTableGet();
+
+    key = psDBIntToString((psU64)pType);
+    mType = psHashLookup(pTypeToMySQLTable, key);
+    psFree(key);
+
+    if (!mType) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "type lookup failed.");
+
+        return NULL;
+    }
+
+    psMemIncrRefCounter(mType);
+
+    return mType;
+}
+
+// PTypeToSQLTable
+
+static psHash *psDBPTypeToSQLTableSetup(void)
+{
+    if (!pTypeToSQLlookupTable) {
+        pTypeToSQLlookupTable = psHashAlloc(14);
+
+        // no support for CHAR, TEXT or GLOB
+        psDBAddToLookupTable(pTypeToSQLlookupTable, PS_DATA_S8,  "TINYINT");
+        psDBAddToLookupTable(pTypeToSQLlookupTable, PS_DATA_S16, "SMALLINT");
+        psDBAddToLookupTable(pTypeToSQLlookupTable, PS_DATA_S32, "INT");
+        psDBAddToLookupTable(pTypeToSQLlookupTable, PS_DATA_S64, "BIGINT");
+        psDBAddToLookupTable(pTypeToSQLlookupTable, PS_DATA_U8,  "TINYINT UNSIGNED");
+        psDBAddToLookupTable(pTypeToSQLlookupTable, PS_DATA_U16, "SMALLINT UNSIGNED");
+        psDBAddToLookupTable(pTypeToSQLlookupTable, PS_DATA_U32, "INT UNSIGNED" );
+        psDBAddToLookupTable(pTypeToSQLlookupTable, PS_DATA_U64, "BIGINT UNSIGNED");
+        psDBAddToLookupTable(pTypeToSQLlookupTable, PS_DATA_F32, "FLOAT");
+        psDBAddToLookupTable(pTypeToSQLlookupTable, PS_DATA_F64, "DOUBLE");
+        // XXX Since BOOL is added after S8 all "TINYINT" data will appear in
+        // the database as boolean data.  There does not seem to be any way to
+        // work around this with MySQL < 5.0.3.
+        psDBAddToLookupTable(pTypeToSQLlookupTable, PS_DATA_BOOL,"TINYINT");
+        psDBAddToLookupTable(pTypeToSQLlookupTable, PS_DATA_STRING, "VARCHAR");
+        psDBAddToLookupTable(pTypeToSQLlookupTable, PS_DATA_TIME, "DATETIME");
+        psDBAddToLookupTable(pTypeToSQLlookupTable, PS_DATA_UNKNOWN, "NULL");
+    } else {
+        // increment the ref count by one for every psDB
+        psMemIncrRefCounter(pTypeToSQLlookupTable);
+    }
+
+    return pTypeToSQLlookupTable;
+}
+
+static psHash *psDBPTypeToSQLTableGet(void)
+{
+    return pTypeToSQLlookupTable;
+}
+
+static void psDBPTypeToSQLTableCleanup(void)
+{
+    PSDB_NULL_FREE(pTypeToSQLlookupTable);
+}
+
+
+// SQLToPTypeTable
+
+static psHash *psDBSQLToPTypeTableSetup(void)
+{
+    psHash          *psToSQLTable;
+    psList          *list;
+    psListIterator  *cursor;
+    char            *key;
+    char            *value;
+
+    if (!sqlToPTypeLookupTable) {
+        // invert the PSToSQL table
+        psToSQLTable = psDBPTypeToSQLTableGet();
+        sqlToPTypeLookupTable = psHashAlloc(psToSQLTable->n);
+
+        list = psHashKeyList(psToSQLTable);
+        cursor = psListIteratorAlloc(list, 0, false);
+
+        while ((key = psListGetAndIncrement(cursor))) {
+            value = psHashLookup(psToSQLTable, key);
+            // switch key and value
+            psHashAdd(sqlToPTypeLookupTable, value, key);
+        }
+
+        // Add BLOB & TEXT reverse mappings
+        value = psDBIntToString((psU64)PS_DATA_STRING);
+        psHashAdd(sqlToPTypeLookupTable, "BLOB",    value);
+        psHashAdd(sqlToPTypeLookupTable, "TEXT",    value);
+        psFree(value);
+
+        // DECIMAL does not exist in the pType to SQL table
+        value = psDBIntToString(0);
+        psHashAdd(sqlToPTypeLookupTable, "DECIMAL", value);
+        psFree(value);
+
+        psFree(cursor);
+        psFree(list);
+    } else {
+        // increment the ref count by one for every psDB
+        psMemIncrRefCounter(sqlToPTypeLookupTable);
+    }
+
+    return sqlToPTypeLookupTable;
+}
+
+static psHash *psDBSQLToPTypeTableGet(void)
+{
+    return sqlToPTypeLookupTable;
+}
+
+static void psDBSQLToPTypeTableCleanup(void)
+{
+    PSDB_NULL_FREE(sqlToPTypeLookupTable);
+}
+
+
+// MySQLToSQLTable
+
+static psHash *psDBMySQLToSQLTableSetup(void)
+{
+    if (!mysqlToSqlLookupTable) {
+        mysqlToSqlLookupTable = psHashAlloc(20);
+
+        psDBAddToLookupTable(mysqlToSqlLookupTable, MYSQL_TYPE_TINY,      "TINYINT");
+        psDBAddToLookupTable(mysqlToSqlLookupTable, MYSQL_TYPE_SHORT,     "SMALLINT");
+        psDBAddToLookupTable(mysqlToSqlLookupTable, MYSQL_TYPE_LONG,      "INT");
+        psDBAddToLookupTable(mysqlToSqlLookupTable, MYSQL_TYPE_INT24,     "MEDIUMINT");
+        psDBAddToLookupTable(mysqlToSqlLookupTable, MYSQL_TYPE_LONGLONG,  "BIGINT");
+        psDBAddToLookupTable(mysqlToSqlLookupTable, MYSQL_TYPE_DECIMAL,   "DECIMAL");
+        psDBAddToLookupTable(mysqlToSqlLookupTable, MYSQL_TYPE_FLOAT,     "FLOAT");
+        psDBAddToLookupTable(mysqlToSqlLookupTable, MYSQL_TYPE_DOUBLE,    "DOUBLE");
+        psDBAddToLookupTable(mysqlToSqlLookupTable, MYSQL_TYPE_TIMESTAMP, "DATETIME");
+        psDBAddToLookupTable(mysqlToSqlLookupTable, MYSQL_TYPE_DATE,      "DATE");
+        psDBAddToLookupTable(mysqlToSqlLookupTable, MYSQL_TYPE_TIME,      "TIME");
+        psDBAddToLookupTable(mysqlToSqlLookupTable, MYSQL_TYPE_DATETIME,  "DATETIME");
+        psDBAddToLookupTable(mysqlToSqlLookupTable, MYSQL_TYPE_YEAR,      "YEAR");
+        // strictly speaking this should CHAR but there is no equivilent ps type
+        // for char as psString is already mapped to varchar
+        psDBAddToLookupTable(mysqlToSqlLookupTable, MYSQL_TYPE_STRING,    "VARCHAR");
+        psDBAddToLookupTable(mysqlToSqlLookupTable, MYSQL_TYPE_VAR_STRING,"VARCHAR");
+        psDBAddToLookupTable(mysqlToSqlLookupTable, MYSQL_TYPE_BLOB,      "BLOB");
+        psDBAddToLookupTable(mysqlToSqlLookupTable, MYSQL_TYPE_SET,       "SET");
+        psDBAddToLookupTable(mysqlToSqlLookupTable, MYSQL_TYPE_ENUM,      "ENUM");
+        psDBAddToLookupTable(mysqlToSqlLookupTable, MYSQL_TYPE_NULL,      "NULL");
+    } else {
+        // increment the ref count by one for every psDB
+        psMemIncrRefCounter(mysqlToSqlLookupTable);
+    }
+
+    return mysqlToSqlLookupTable;
+}
+
+static psHash *psDBMySQLToSQLTableGet(void)
+{
+    return mysqlToSqlLookupTable;
+}
+
+static void psDBMySQLToSQLTableCleanup(void)
+{
+    PSDB_NULL_FREE(mysqlToSqlLookupTable);
+}
+
+
+// PTypeToMySQLTable
+
+static psHash *psDBPTypeToMySQLTableSetup(void)
+{
+    if (!pTypeToMysqlLookupTable) {
+        pTypeToMysqlLookupTable = psHashAlloc(14);
+
+        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_S8,     psDBMySQLTypeAlloc(MYSQL_TYPE_TINY,       false));
+        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_S16,    psDBMySQLTypeAlloc(MYSQL_TYPE_SHORT,      false));
+        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_S32,    psDBMySQLTypeAlloc(MYSQL_TYPE_LONG,       false));
+        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_S64,    psDBMySQLTypeAlloc(MYSQL_TYPE_LONGLONG,   false));
+        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_U8,     psDBMySQLTypeAlloc(MYSQL_TYPE_TINY,       true));
+        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_U16,    psDBMySQLTypeAlloc(MYSQL_TYPE_SHORT,      true));
+        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_U32,    psDBMySQLTypeAlloc(MYSQL_TYPE_LONG,       true));
+        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_U64,    psDBMySQLTypeAlloc(MYSQL_TYPE_LONGLONG,   true));
+        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_F32,    psDBMySQLTypeAlloc(MYSQL_TYPE_FLOAT,      false));
+        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_F64,    psDBMySQLTypeAlloc(MYSQL_TYPE_DOUBLE,     false));
+        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_BOOL,   psDBMySQLTypeAlloc(MYSQL_TYPE_TINY,       true));
+        // XXX: removed PS_DATA_PTR, can this be removed too?
+        // psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_PTR,    psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
+
+        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_STRING,    psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
+        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_TIME,      psDBMySQLTypeAlloc(MYSQL_TYPE_DATETIME, false));
+        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_VECTOR,    psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
+        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_IMAGE,    psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
+        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_HASH,   psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
+        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_LOOKUPTABLE,
+                                 psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
+        //        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_JPEG,   psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
+        //        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_PNG,    psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
+        //        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_ASTROM, psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
+        psDBAddVoidToLookupTable(pTypeToMysqlLookupTable, PS_DATA_UNKNOWN,psDBMySQLTypeAlloc(MYSQL_TYPE_NULL, false));
+    } else {
+        // increment the ref count by one for every psDB
+        psMemIncrRefCounter(pTypeToMysqlLookupTable);
+    }
+
+    return pTypeToMysqlLookupTable;
+}
+
+static psHash *psDBPTypeToMySQLTableGet(void)
+{
+    return pTypeToMysqlLookupTable;
+}
+
+static void psDBPTypeToMySQLTableCleanup(void)
+{
+    PSDB_NULL_FREE(pTypeToMysqlLookupTable);
+}
+
+static psPtr psDBMySQLTypeAlloc(enum enum_field_types type,
+                                bool isUnsigned)
+{
+    mysqlType *mType = psAlloc(sizeof(mysqlType));
+    mType->type       = type;
+    mType->isUnsigned = isUnsigned;
+
+    return mType;
+}
+
+static void psDBAddToLookupTable(psHash *lookupTable,
+                                 psU32 type,
+                                 const char *string)
+{
+    PS_ASSERT_PTR_NON_NULL(lookupTable, );
+
+    psString key = psDBIntToString((psU64)type);
+    psString value = psStringCopy(string);
+
+    psHashAdd(lookupTable, key, value);
+
+    psFree(key);
+    psFree(value);
+}
+
+static void psDBAddVoidToLookupTable(psHash *lookupTable,
+                                     psU32 type,
+                                     psPtr value)
+{
+    PS_ASSERT_PTR_NON_NULL(lookupTable, );
+
+    psString key = psDBIntToString((psU64)type);
+
+    psHashAdd(lookupTable, key, value);
+
+    // destructive of value parameter
+    psFree(value);
+    psFree(key);
+}
+
+static psErrorCode mysqlTopsErr(MYSQL *mysql)
+{
+    unsigned int myerrno = mysql_errno(mysql);
+    if ((myerrno >= 1000) && (myerrno < 2000)) {
+        return PS_ERR_DB_SERVER;
+    } else if ((myerrno >= 2000) && (myerrno < 3000)) {
+        return PS_ERR_DB_CLIENT;
+    }
+
+    return PS_ERR_UNKNOWN;
+}
+
+
+// pType utility functions
+/*****************************************************************************/
+
+#define PS_NAN_ALLOC(dest, type, nan) \
+dest = psAlloc(sizeof(type)); \
+*(type *)dest = nan;
+
+static psPtr psDBGetPTypeNaN(psElemType pType)
+{
+    psPtr           myNaN = NULL;
+
+    switch (pType) {
+    case PS_DATA_S8:
+        PS_NAN_ALLOC(myNaN, psS8, PS_MAX_S8);
+        break;
+    case PS_DATA_S16:
+        PS_NAN_ALLOC(myNaN, psS16, PS_MAX_S16);
+        break;
+    case PS_DATA_S32:
+        PS_NAN_ALLOC(myNaN, psS32, PS_MAX_S32);
+        break;
+    case PS_DATA_S64:
+        PS_NAN_ALLOC(myNaN, psS64, PS_MAX_S64);
+        break;
+    case PS_DATA_U8:
+        PS_NAN_ALLOC(myNaN, psU8, PS_MAX_U8);
+        break;
+    case PS_DATA_U16:
+        PS_NAN_ALLOC(myNaN, psU16, PS_MAX_U16);
+        break;
+    case PS_DATA_U32:
+        PS_NAN_ALLOC(myNaN, psU32, PS_MAX_U32);
+        break;
+    case PS_DATA_U64:
+        PS_NAN_ALLOC(myNaN, psU64, PS_MAX_U64);
+        break;
+    case PS_DATA_F32:
+        PS_NAN_ALLOC(myNaN, psF32, NAN);
+        break;
+    case PS_DATA_F64:
+        PS_NAN_ALLOC(myNaN, psF64, NAN);
+        break;
+    case PS_DATA_BOOL:
+        // XXX: what is NaN for a bool?
+        PS_NAN_ALLOC(myNaN, psU8, PS_MAX_U8);
+        break;
+    }
+
+    return myNaN;
+}
+
+#define PS_IS_NAN(type, data, nan) *(type *)data == nan
+
+static bool psDBIsPTypeNaN(psElemType pType,
+                           psPtr data)
+{
+    bool    isNaN = NULL;
+
+    switch (pType) {
+    case PS_DATA_S8:
+        isNaN = PS_IS_NAN(psS8, data, PS_MAX_S8);
+        break;
+    case PS_DATA_S16:
+        isNaN = PS_IS_NAN(psS16, data, PS_MAX_S16);
+        break;
+    case PS_DATA_S32:
+        isNaN = PS_IS_NAN(psS32, data, PS_MAX_S32);
+        break;
+    case PS_DATA_S64:
+        isNaN = PS_IS_NAN(psS64, data, PS_MAX_S64);
+        break;
+    case PS_DATA_U8:
+        isNaN = PS_IS_NAN(psU8, data, PS_MAX_U8);
+        break;
+    case PS_DATA_U16:
+        isNaN = PS_IS_NAN(psU16, data, PS_MAX_U16);
+        break;
+    case PS_DATA_U32:
+        isNaN = PS_IS_NAN(psU32, data, PS_MAX_U32);
+        break;
+    case PS_DATA_U64:
+        isNaN = PS_IS_NAN(psU64, data, PS_MAX_U64);
+        break;
+    case PS_DATA_F32:
+        isNaN = PS_IS_NAN(psF32, data, NAN);
+        break;
+    case PS_DATA_F64:
+        isNaN = PS_IS_NAN(psF64, data, NAN);
+        break;
+    case PS_DATA_BOOL:
+        // XXX: what is NaN for a bool?
+        isNaN = PS_IS_NAN(psU8, data, PS_MAX_U8);
+        break;
+    }
+
+    return isNaN;
+}
+
+// string utility functions
+/*****************************************************************************/
+
+psString psDBIntToString(psU64 value)
+{
+    // length of string (log10 + 1) + \0
+    // if value is 0, length is 1 char + \0
+    size_t length = value ? (size_t)log10((double)value) + 1 + 1
+                    : 2;
+    psString string = psStringAlloc(length);
+    snprintf(string, length, "%li", (long int)value);
+
+    return string;
+}
+
+#endif // HAVE_PSDB
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/db/psDB.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/db/psDB.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/db/psDB.h	(revision 22158)
@@ -0,0 +1,453 @@
+/** @file psDB.h
+ *
+ * Copyright (C) 2007  Joshua Hoblitt, University of Hawaii
+ *
+ * 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
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * @brief database types and functions
+ *
+ * This file defines the abstract database type and functions that
+ * perform basic database operations.
+ *
+ * $Id: psDB.h,v 1.37 2007-09-05 23:20:04 jhoblitt Exp $
+ */
+
+#ifndef PS_DB_H
+#define PS_DB_H 1
+#ifdef HAVE_PSDB
+
+/// @addtogroup FileIO Input/Output
+/// @{
+
+#include "psType.h"
+#include "psMetadata.h"
+
+/** Database handle
+ *
+ *  An opaque object representing a database connection.
+ *
+ */
+typedef struct
+{
+    void* mysql;                       ///< MySQL database handle
+}
+psDB;
+
+/** Opens a new database connection
+ *
+ *  @return psDB*:      A new psDB object if the database connection is
+ *  successful or NULL on failure.
+ */
+psDB *psDBAlloc(
+    const char *host,                  ///< Database server hostname
+    const char *user,                  ///< Database username
+    const char *passwd,                ///< Database password
+    const char *dbname,                ///< Database namespace
+    unsigned int port                  ///< Database port number
+) PS_ATTR_MALLOC;
+
+/** Opens a new database connection
+ *
+ *  This function is deprecated favor of psDBAlloc()
+ *
+ *  @return psDB*:      A new psDB object if the database connection is
+ *  successful or NULL on failure.
+ */
+#ifdef DOXYGEN
+psDB *psDBInit(
+    const char *host,                  ///< Database server hostname
+    const char *user,                  ///< Database username
+    const char *passwd,                ///< Database password
+    const char *dbname,                ///< Database namespace
+    unsigned int port                  ///< Database port number
+);
+#else // DOXYGEN
+#define psDBInit(host, user, passwd, dbname, port) \
+psDBAlloc(host, user, passwd, dbname, port)
+#endif
+
+#ifdef DOXYGEN
+/** Closes a database connection
+ *
+ *  This function is deprecated favor of psFree()
+ */
+void psDBCleanup(
+    psDB *dbh                          ///< Database handle
+);
+#else // DOXYGEN
+#define psDBCleanup(dbh) \
+psFree(dbh)
+#endif
+
+/** Creates a new database namespace
+ *
+ * @return bool:    true on success
+ */
+bool psDBCreate(
+    psDB *dbh,                         ///< Database handle
+    const char *dbname                 ///< New database namespace
+);
+
+/** Changes the current database namespace
+ *
+ * @return bool:    true on success
+ */
+bool psDBChange(
+    psDB *dbh,                         ///< Database handle
+    const char *dbname                 ///< Database namespace
+);
+
+/** Drops a database namespace
+ *
+ * @return bool:    true on success
+ */
+bool psDBDrop(
+    psDB *dbh,                         ///< Database handle
+    const char *dbname                 ///< Database namespace
+);
+
+/** Executes a SQL query
+ *
+ * This function will execute a string as a raw SQL query.  No additional
+ * processing of the string or abstraction of the underlying database's SQL
+ * dialect is provided.  Caveat emptor.
+ *
+ * @return bool:    true on success
+ */
+bool p_psDBRunQuery(
+    psDB *dbh,                         ///< Database handle
+    const char *format,                ///< SQL string to execute
+    ...                                ///< Arguments for name formatting and metadata item data.
+) PS_ATTR_FORMAT(printf, 2, 3);
+
+/** Executes a SQL query as a prepared statement
+ *
+ * This function will execute a string as a raw SQL query.  No additional
+ * processing of the string or abstraction of the underlying database's SQL
+ * dialect is provided.  Caveat emptor.
+ *
+ * @return long:    the number of database rows affected
+ */
+long p_psDBRunQueryPrepared(
+    psDB *dbh,                          ///< Database handle
+    const psArray *rowSet,              ///< row data as psArray of psMetadata
+    const char *format,                 ///< SQL string to execute
+    ...
+) PS_ATTR_FORMAT(printf, 3, 4);
+
+/** Fetches the result of a SQL query
+ *
+ * This function returns the result of the most recent SQL query as a psArray
+ * of psMetadata.  Caveat emptor.
+ *
+ * @return psArray*:    A psArray of psMetadata or NULL on failure
+ */
+psArray *p_psDBFetchResult(
+    psDB *dbh                          ///< Database handle
+);
+
+/** Creates a new database table
+ *
+ * This function generates and executes the SQL needed to create a table named
+ * "tableName", with the column names and data types as described in "md".  Each
+ * data item in the psMetadata collection represents a single table field.  The
+ * name of the field is given by the name of the psMetadataItem and the data
+ * type is give by the psMetadataItem.type and psMetadataItem.ptype entries.  A
+ * lookup table should be used to convert from PSLib types into MySQL
+ * compatible SQL data types.  For example, a PS_DATA_STRING would map to an SQL99
+ * varchar.  If the value of type is PS_DATA_STRING then the psMetadataItem.data
+ * element is set to a string with the length for the field written as a text
+ * string.  The value of the psMetadataItem.data element is unused for the
+ * PS_META_PRIMITIVE types.  Other psMetadata types beyond PS_DATA_STRING and
+ * PS_META_PRIMITIVE are not allowed in a table definition.
+ *
+ * Database indexes can be specified setting the "comment" field to "Primary
+ * Key" or "Key".  Comments are otherwise ignored.
+ *
+ * @return bool:    true on success
+ */
+bool psDBCreateTable(
+    psDB *dbh,                         ///< Database handle
+    const char *tableName,             ///< Table name
+    const psMetadata *md               ///< Column names, types, and indexes
+);
+
+/** Deletes a database table
+ *
+ * @return bool:    true on success
+*/
+bool psDBDropTable(
+    psDB *dbh,                          ///< Database handle
+    const char *tableName               ///< Table name
+);
+
+/** Selects a column from a table
+ *
+ * This function generates and executes the SQL needed to select an entire
+ * column from a table or up to "limit" rows from it.  If "limit" is 0, the
+ * entire range is returned.
+ *
+ * @return psArray*:    A psArray of strings or NULL on failure
+ */
+psArray *psDBSelectColumn(
+    psDB *dbh,                         ///< Database handle
+    const char *tableName,             ///< Table name
+    const char *col,                   ///< Column name
+    unsigned long long limit           ///< Maximum number of elements to return
+);
+
+/** Selects a column from a table and casts it to a given type
+ *
+ * This function generates and executes the SQL needed to select an entire
+ * column from a table or up to "limit" rows from it.  If "limit" is 0, the
+ * entire range is returned.  The data in the column is cast to to "pType".
+ *
+ * @return psVector*:   A psVector or NULL on failure
+ */
+psVector *psDBSelectColumnNum(
+    psDB *dbh,                         ///< Database handle
+    const char *tableName,             ///< Table name
+    const char *col,                   ///< Column name
+    psElemType type,                   ///< Resulting psVector type
+    unsigned long long limit           ///< Maximum number of elements to return
+);
+
+/** Selects a set of rows from a table
+ *
+ * This function returns rows from the specified table which match the
+ * restrictions given by "where".  The restrictions are specified as field /
+ * value pairs.  The psMetadata collection "where" must consist of valid
+ * database fields.  The selected rows are returned as a psArray of psMetadata
+ * values, one per row.
+ *
+ * Currently, the "where" specification only supports the PS_DATA_STRING type.
+ * The string value can be a SQL match pattern, e.g. "%foo%", or an empty
+ * string, e.g. "", to match NULL field values.
+ *
+ * @return psArray*:    A psArray of psMetadata or NULL on failure
+ */
+psArray *psDBSelectRows(
+    psDB *dbh,                         ///< Database handle
+    const char *tableName,             ///< Table name
+    const psMetadata *where,           ///< Row match criteria
+    unsigned long long limit           ///< Maximum number of elements to return
+);
+
+/** Insert a single row into a table
+ *
+ * This function inserts the data from "row" into "tableName".
+ *
+ * The "row" specification uses the psMetadataItem name as the column name.
+ * The field values may be specified in any order.  psMetadata types beyond
+ * PS_DATA_STRING and PS_META_PRIMITIVE are not supported.  If fields are
+ * specified in "row" that do not exist in "tableName", the insert will fail.
+ *
+ * @return bool:    true on success
+ */
+bool psDBInsertOneRow(
+    psDB *dbh,                         ///< Database handle
+    const char *tableName,             ///< Table name
+    const psMetadata *row              ///< Row description
+);
+
+/** Insert a set of rows into a table
+ *
+ * This function inserts the data from "rowSet" into "tableName".
+ *
+ * "rowSet" is a psArray of psMetadata containing row specifications identical to
+ * those used in psDBInsertOneRow().
+ *
+ * @return bool:    true on success
+ */
+bool psDBInsertRows(
+    psDB *dbh,                         ///< Database handle
+    const char *tableName,             ///< Table name
+    const psArray *rowSet              ///< Set of rows to insert
+);
+
+/** Retrieves all rows from a table
+ *
+ * This function fetches all rows as an psArray of psMetadata.  The rows are in
+ * the same psMetadata format as used in psDBInsertOneRow() & psDBInsertRows().
+ *
+ * @return psArray*:    A psArray of psMetadata or NULL on failure
+ */
+psArray *psDBDumpRows(
+    psDB *dbh,                         ///< Database handle
+    const char *tableName              ///< Table name
+);
+
+/** Retrieves all columns from a table
+ *
+ * This function fetches all columns, as either a psVector or a psArray
+ * depending on whether or not the column is numeric, and return them in a
+ * psMetadata structure where psMetadataItem.name contains the column's name.
+ *
+ * @return psMetadata*:     A psMetadata containing either a psArrays or psVector per column
+ */
+psMetadata *psDBDumpCols(
+    psDB *dbh,                         ///< Database handle
+    const char *tableName              ///< Table name
+);
+
+/** Updates the field values, as specified, in a table
+ *
+ * This function updates the fields contained in "values" in the row(s) that
+ * have a field with the value indicated by "where".  Where "where" is in the
+ * same format as used in psDBSelectRows().
+ *
+ * The "values" specification uses the same format as the row specification
+ * used in psDBInsertOneRow(), etc.
+ *
+ * @return long:    The number of rows modified or a negative value on error
+ */
+long psDBUpdateRows(
+    psDB *dbh,                         ///< Database handle
+    const char *tableName,             ///< Table name
+    const psMetadata *where,           ///< Row match criteria
+    psMetadata *values                 ///< new field values
+);
+
+/** Deletes rows, as specified, in a table
+ *
+ * Delete the rows that are matched by "where" using the same semantics for
+ * "where" as in psDBUpdateRow().
+ *
+ * If "where" is NULL, all rows in the table will be removed and regardless of
+ * the number of rows that were dropped, only 1 will be returned on success.
+ *
+ * @return long:    The number of rows removed or a negative value on error
+ */
+long psDBDeleteRows(
+    psDB *dbh,                         ///< Database handle
+    const char *tableName,             ///< Table name
+    const psMetadata *where,           ///< Row match criteria
+    unsigned long long limit           ///< Maximum number of rows to delete
+);
+
+/** Get the last insert ID
+ *
+ * Returns the value of MySQLs 'LAST_INSERT_ID()' function
+ *
+ * @return long:    The last insert ID
+ */
+long long psDBLastInsertID(
+    psDB *dbh                          ///< Database handle
+);
+
+/** Enable/Disable explicit database transactions
+ *
+ * This function is used to enable explicit transaction support.  It is off by
+ * default.
+ *
+ * @return bool:    true if transactions are enabled
+ */
+bool psDBExplicitTrans(
+    psDB *dbh,                          ///< Database handle
+    bool mode                           ///< transactions enable/disable
+);
+
+/** Start a new transaction set.
+ *
+ * This is only a meaningful action if explict transactions are disabled.
+ *
+ * @return bool:    true on success
+ */
+bool psDBTransaction(
+    psDB *dbh                           ///< Database handle
+);
+
+/** Commits the current transaction
+ *
+ * This function will commit the current transaction set (a rollback is not
+ * possible after this function is successfully executed).  A commit also
+ * effectively starts a new transaction if explict transactions are enabled.
+ *
+ * @return bool:    true on success
+ */
+bool psDBCommit(
+    psDB *dbh                           ///< Database handle
+);
+
+/** Rollback the current transaction
+ *
+ * This function will rollback the current transaction set.
+ *
+ * @return bool:    true on success
+ */
+bool psDBRollback(
+    psDB *dbh                           ///< Database handle
+);
+
+/** Generates an SQL "Where" fragment
+ *
+ * This function generates an SQL fragment (not a whole usable query) based on
+ * the standard "where" metadata format.
+ *
+ * @return psString:   A psString or NULL on failure
+ */
+psString psDBGenerateWhereSQL(
+    const psMetadata *where,           ///< Row match criteria
+    const char *tableName              ///< Table name
+);
+
+/** Generates an SQL "where conditon" statement
+ *
+ * This function generates a "Where" fragment but omits the "Where" keyword.
+ * This function generates an SQL fragment (not a whole usable query) based on
+ * the standard "where" metadata format.
+ *
+ * @return psString:   A psString or NULL on failure
+ */
+psString psDBGenerateWhereConditionSQL(
+    const psMetadata *where,           ///< Row match criteria
+    const char *tableName              ///< Table name
+);
+
+/** Generates an SQL "limit" statement
+ *
+ * This function generates an SQL fragment (not a whole usable query).
+ *
+ * @return psString:   A psString or NULL on failure
+ */
+psString psDBGenerateLimitSQL(
+    psU64 limit                         ///< result set row limit
+);
+
+/** converts an integer into a psString
+ *
+ * Note that this function takes an unsigned value.
+ *
+ * @return psString:   A psString or NULL on failure
+ */
+psString psDBIntToString(
+    psU64 value                         // integer value to convert
+);
+
+/** The number of rows modified or inserted by the last query
+ *
+ *  This function returns ((psU64) - 1) on error
+ *
+ * @return psU64
+ */
+psU64 psDBAffectedRows(
+    psDB *dbh                           ///< Database handle
+);
+
+/// @}
+#else
+typedef void psDB;
+#endif // HAVE_PSDB
+#endif // PS_DB_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fft/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fft/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fft/.cvsignore	(revision 22158)
@@ -0,0 +1,10 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
+*.loT
+*.bb
+*.bbg
+*.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fft/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fft/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fft/Makefile.am	(revision 22158)
@@ -0,0 +1,16 @@
+#Makefile for fft functions of psLib
+#
+noinst_LTLIBRARIES = libpslibfft.la
+
+libpslibfft_la_CPPFLAGS = $(SRCINC) $(PSLIB_CFLAGS) $(FFTW3_CFLAGS)
+libpslibfft_la_SOURCES = \
+	psImageFFT.c \
+	psVectorFFT.c
+
+EXTRA_DIST = fft.i
+
+pkginclude_HEADERS = \
+	psVectorFFT.h \
+	psImageFFT.h
+
+CLEANFILES = *~ *.bb *.bbg *.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fft/fft.i
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fft/fft.i	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fft/fft.i	(revision 22158)
@@ -0,0 +1,3 @@
+/* db headers */
+%include "psImageFFT.h"
+%include "psVectorFFT.h"
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fft/psImageFFT.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fft/psImageFFT.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fft/psImageFFT.c	(revision 22158)
@@ -0,0 +1,451 @@
+/// @file  psImageFFT.c
+///
+/// @brief Contains FFT transform related functions for psImage.
+///
+/// @author Paul Price, IfA
+/// @author Robert DeSonia, MHPCC
+///
+/// @version $Revision: 1.26 $ $Name: not supported by cvs2svn $
+/// @date $Date: 2008-04-08 01:25:42 $
+///
+/// Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+///
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <unistd.h>
+#include <string.h>
+#include <complex.h>
+#include <fftw3.h>
+
+#include "psAssert.h"
+#include "psError.h"
+#include "psMemory.h"
+#include "psLogMsg.h"
+#include "psConstants.h"
+#include "psImageStructManip.h"
+#include "psImageConvolve.h"
+#include "psImageFFT.h"
+
+
+#define FFTW_PLAN_RIGOR FFTW_ESTIMATE   // How rigorous the FFTW planning is
+
+static psBool fftwWisdomImported = false; // Has the FFTW wisdom been imported yet?
+
+bool psImageForwardFFT(psImage **real, psImage **imag, const psImage *in)
+{
+    PS_ASSERT_IMAGE_NON_NULL(in, false);
+    PS_ASSERT_IMAGE_TYPE(in, PS_TYPE_F32, false);
+    PS_ASSERT_PTR_NON_NULL(real, false);
+    PS_ASSERT_PTR_NON_NULL(imag, false);
+
+    // Make sure the system-level wisdom information is imported.
+    if (!fftwWisdomImported) {
+        fftwf_import_system_wisdom();
+        fftwWisdomImported = true;
+    }
+
+    int numCols = in->numCols;          // Number of columns
+    int numRows = in->numRows;          // Number of rows
+
+    psF32 *input;                       // Input data, for FFTW
+    if (!in->parent) {
+        // No parent --- can just use the data buffer
+        input = psMemIncrRefCounter(in->p_rawDataBuffer);
+    } else {
+        // Need to copy the data
+        input = psAlloc(numCols * numRows);
+        for (int y = 0; y < numRows; y++) {
+            memcpy(&input[y * numRows], in->data.F32[y], numCols);
+        }
+    }
+
+    // Do the FFT
+    fftwf_complex *out = fftwf_malloc((numCols/2 + 1) * numRows * sizeof(fftwf_complex)); // Output data
+    fftwf_plan plan = fftwf_plan_dft_r2c_2d(numRows, numCols, input, out, FFTW_PLAN_RIGOR);
+    fftwf_execute(plan);
+    fftwf_destroy_plan(plan);
+    psFree(input);
+
+    // Pull the real and imaginary parts out
+    numCols = numCols/2 + 1;            // x dimension is halved by FFTW
+    *real = psImageRecycle(*real, numCols, numRows, PS_TYPE_F32);
+    *imag = psImageRecycle(*imag, numCols, numRows, PS_TYPE_F32);
+    for (int y = 0, index = 0; y < numRows; y++) {
+        for (int x = 0; x < numCols; index++, x++) {
+#if !defined(FFTW_NO_Complex) && defined(_Complex_I) && defined(complex) && defined(I)
+            // C99 complex support
+            (*real)->data.F32[y][x] = creal(out[index]);
+            (*imag)->data.F32[y][x] = cimag(out[index]);
+#else
+            // FFTW's backup complex support
+            (*real)->data.F32[y][x] = out[index][0];
+            (*imag)->data.F32[y][x] = out[index][1];
+#endif
+        }
+    }
+    fftwf_free(out);
+
+    return true;
+}
+
+bool psImageBackwardFFT(psImage **out, const psImage *real, const psImage *imag, int origCols)
+{
+    PS_ASSERT_IMAGE_NON_NULL(real, false);
+    PS_ASSERT_IMAGE_TYPE(real, PS_TYPE_F32, false);
+    PS_ASSERT_IMAGE_NON_NULL(imag, false);
+    PS_ASSERT_IMAGE_TYPE(imag, PS_TYPE_F32, false);
+    PS_ASSERT_IMAGES_SIZE_EQUAL(real, imag, false);
+    PS_ASSERT_PTR_NON_NULL(out, false);
+
+    int numCols = real->numCols;        // Number of columns
+    int numRows = real->numRows;        // Number of rows
+
+    // Because of the way FFT r2c and c2r work, need the number of columns in the target to be:
+    // 2 * numCols = 2*(numCols/2 + 1) = origCols % 2 ? origCols + 1 : origCols + 2
+    if (2 * numCols != ((origCols % 2) ? origCols + 1 : origCols + 2)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "Number of columns in FFT-ed images (%d) should be origCols (%d) / 2 + 1 = %d",
+                numCols, origCols, origCols/2 + 1);
+        return false;
+    }
+
+    if (*out && (*out)->parent) {
+        // It has a parent, so we can't write directly into the buffer.
+        // It had better be the correct size and type, because we don't want to resize a child image
+        PS_ASSERT_IMAGE_SIZE(*out, origCols, numRows, false);
+        PS_ASSERT_IMAGE_TYPE(*out, PS_TYPE_F32, false);
+    }
+
+
+    // Make sure the system-level wisdom information is imported.
+    if (!fftwWisdomImported) {
+        fftwf_import_system_wisdom();
+        fftwWisdomImported = true;
+    }
+
+    // Stuff the real and imaginary parts in
+    psF32 *target = psAlloc(2 * numCols * numRows * PSELEMTYPE_SIZEOF(PS_TYPE_F32)); // Target for FFTW
+    fftwf_complex *in = fftwf_malloc(numCols * numRows * sizeof(fftwf_complex)); // Input data
+
+    for (int y = 0, index = 0; y < numRows; y++) {
+        for (int x = 0; x < numCols; index++, x++) {
+#if !defined(FFTW_NO_Complex) && defined(_Complex_I) && defined(complex) && defined(I)
+            // C99 complex support
+            in[index] = real->data.F32[y][x] + imag->data.F32[y][x] * I;
+#else
+            // FFTW's backup complex support
+            in[index][0] = real->data.F32[y][x];
+            in[index][1] = imag->data.F32[y][x];
+#endif
+        }
+    }
+
+    // Do the FFT
+    fftwf_plan plan = fftwf_plan_dft_c2r_2d(numRows, origCols, in, target, FFTW_PLAN_RIGOR);
+    fftwf_execute(plan);
+    fftwf_destroy_plan(plan);
+    fftwf_free(in);
+
+    // Copy the target pixels into the output
+    if (!(*out) || !(*out)->parent) {
+        *out = psImageRecycle(*out, origCols, numRows, PS_TYPE_F32);
+        memcpy((*out)->p_rawDataBuffer, target, numRows * origCols * PSELEMTYPE_SIZEOF(PS_TYPE_F32));
+    } else {
+        for (int y = 0, index = 0; y < numRows; y++, index += origCols) {
+            memcpy(&(*out)->data.F32[y][0], &target[index], origCols * PSELEMTYPE_SIZEOF(PS_TYPE_F32));
+        }
+    }
+
+    psFree(target);
+
+    return true;
+}
+
+psImage* psImagePowerSpectrum(psImage *out, const psImage *in)
+{
+    PS_ASSERT_IMAGE_NON_NULL(in, NULL);
+    PS_ASSERT_IMAGE_TYPE(in, PS_TYPE_F32, NULL);
+
+    psImage *real = NULL;              // Real component of FFT
+    psImage *imag = NULL;              // Imaginary component of FFT
+
+    if (!psImageForwardFFT(&real, &imag, in)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to perform forward FFT.");
+        return NULL;
+    }
+
+    int numCols = real->numCols;        // Number of columns
+    int numRows = real->numRows;        // Number of rows
+
+    float norm = 1.0 / PS_SQR(in->numCols) / PS_SQR(in->numRows);
+    for (int y = 0; y < numRows; y++) {
+        for (int x = 0; x < numCols; x++) {
+            // Power spectrum is the square of the complex modulus
+            real->data.F32[y][x] = norm * (PS_SQR(real->data.F32[y][x]) + PS_SQR(imag->data.F32[y][x]));
+        }
+    }
+    psFree(imag);
+
+    return real;
+}
+
+
+bool psImageComplexMultiply(psImage **outReal, psImage **outImag,
+                            const psImage *in1Real, const psImage *in1Imag,
+                            const psImage *in2Real, const psImage *in2Imag)
+{
+    PS_ASSERT_IMAGE_NON_NULL(in1Real, false);
+    PS_ASSERT_IMAGE_NON_NULL(in1Imag, false);
+    PS_ASSERT_IMAGE_NON_NULL(in2Real, false);
+    PS_ASSERT_IMAGE_NON_NULL(in2Imag, false);
+    PS_ASSERT_IMAGE_TYPE(in1Real, PS_TYPE_F32, false);
+    PS_ASSERT_IMAGE_TYPE(in1Imag, PS_TYPE_F32, false);
+    PS_ASSERT_IMAGE_TYPE(in2Real, PS_TYPE_F32, false);
+    PS_ASSERT_IMAGE_TYPE(in2Imag, PS_TYPE_F32, false);
+    PS_ASSERT_IMAGES_SIZE_EQUAL(in1Imag, in1Real, false);
+    PS_ASSERT_IMAGES_SIZE_EQUAL(in2Real, in1Real, false);
+    PS_ASSERT_IMAGES_SIZE_EQUAL(in2Imag, in1Real, false);
+    PS_ASSERT_PTR_NON_NULL(outReal, false);
+    PS_ASSERT_PTR_NON_NULL(outImag, false);
+    if (*outReal) {
+        PS_ASSERT_IMAGE_NON_NULL(*outReal, false);
+        PS_ASSERT_IMAGE_NON_NULL(*outImag, false);
+    } else if (*outImag) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "If the output real part is provided, the output imaginary part must also be provided.");
+        return false;
+    }
+
+    int numRows = in1Real->numRows;     // Number of rows
+    int numCols = in1Real->numCols;     // Number of columns
+
+    // Need to worry if the outputs are children
+    psImage *targetReal, *targetImag;   // Target real and imaginary parts
+
+    if ((*outReal)->parent) {
+        // It had better be the correct size and type, because we don't want to resize a child image
+        PS_ASSERT_IMAGE_TYPE(*outReal, PS_TYPE_F32, false);
+        PS_ASSERT_IMAGE_SIZE(*outReal, numCols, numRows, false);
+        targetReal = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    } else {
+        *outReal = psImageRecycle(*outReal, numCols, numRows, PS_TYPE_F32);
+        targetReal = psMemIncrRefCounter(*outReal);
+    }
+    if ((*outImag)->parent) {
+        // It had better be the correct size and type, because we don't want to resize a child image
+        if ((*outReal)->numCols != numCols || (*outReal)->numRows != numRows ||
+            (*outImag)->type.type != PS_TYPE_F32) {
+            // Plug potential memory leak --- need to free targetReal if there's a problem
+            psFree(targetReal);
+        }
+        PS_ASSERT_IMAGE_TYPE(*outReal, PS_TYPE_F32, false);
+        PS_ASSERT_IMAGE_SIZE(*outReal, numCols, numRows, false);
+        targetImag = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    } else {
+        *outImag = psImageRecycle(*outImag, numCols, numRows, PS_TYPE_F32);
+        targetImag = psMemIncrRefCounter(*outImag);
+    }
+
+    for (int y = 0; y < numRows; y++) {
+        for (int x = 0; x < numCols; x++) {
+            // (a + bi) * (c + di) = (ac - bd) + (bc + ad)i
+            float real = in1Real->data.F32[y][x] * in2Real->data.F32[y][x] -
+                in1Imag->data.F32[y][x] * in2Imag->data.F32[y][x];
+            float imag = in1Imag->data.F32[y][x] * in2Real->data.F32[y][x] +
+                in1Real->data.F32[y][x] * in2Imag->data.F32[y][x];
+            targetReal->data.F32[y][x] = real;
+            targetImag->data.F32[y][x] = imag;
+        }
+    }
+
+    if ((*outReal)->parent) {
+        *outReal = psImageCopy(*outReal, targetReal, PS_TYPE_F32);
+    }
+    if ((*outImag)->parent) {
+        *outImag = psImageCopy(*outImag, targetImag, PS_TYPE_F32);
+    }
+
+    psFree(targetReal);
+    psFree(targetImag);
+
+    return true;
+}
+
+
+psImage *psImageConvolveFFT(psImage *out, const psImage *in, const psImage *mask, psMaskType maskVal,
+                            const psKernel *kernel)
+{
+    PS_ASSERT_IMAGE_NON_NULL(in, NULL);
+    PS_ASSERT_IMAGE_TYPE(in, PS_TYPE_F32, NULL);
+    PS_ASSERT_KERNEL_NON_NULL(kernel, NULL);
+    if (mask) {
+        PS_ASSERT_IMAGE_NON_NULL(mask, NULL);
+        PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, NULL);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(mask, in, NULL);
+    }
+
+    int numCols = in->numCols, numRows = in->numRows; // Size of image
+    int xMin = kernel->xMin, xMax = kernel->xMax, yMin = kernel->yMin, yMax = kernel->yMax; // Kernel sizes
+
+    // Need to pad the input image to protect from wrap-around effects
+    if (xMax - xMin > numCols || yMax - yMin > numRows) {
+        // Cannot pad the image if the kernel is larger.
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                _("Kernel cannot extend further than input image size (%dx%d vs %dx%d)."),
+                xMax, yMax, numCols, numRows);
+        return NULL;
+    }
+    int paddedCols = numCols + PS_MAX(-xMin, xMax); // Number of columns in padded image
+    int paddedRows = numRows + PS_MAX(-yMin, yMax); // Number of rows in padded image
+    int numPadded = paddedCols * paddedRows; // Number of pixels in padded image
+
+    // Create data array containing the padded image and padded kernel
+    psF32 *data = fftwf_malloc(2 * numPadded * PSELEMTYPE_SIZEOF(PS_TYPE_F32)); // Data for FFTW
+    psF32 *dataPtr = data;              // Pointer into FFTW data
+    psF32 **imageData = in->data.F32;   // Pointer into image data
+
+    // Image part of data array
+    size_t goodBytes = numCols * PSELEMTYPE_SIZEOF(PS_TYPE_F32); // Number of bytes per image row
+    size_t padBytes = (paddedCols - numCols) * PSELEMTYPE_SIZEOF(PS_TYPE_F32); // Number of bytes to pad
+    for (int y = 0; y < numRows; y++, dataPtr += paddedCols, imageData++) {
+        memcpy(dataPtr, *imageData, goodBytes);
+        memset(dataPtr + numCols, 0, padBytes);
+    }
+    memset(dataPtr, 0, (paddedRows - numRows) * paddedCols * PSELEMTYPE_SIZEOF(PS_TYPE_F32));
+
+#if 1
+    {
+        // Use this for inspecting the result of copying the image
+        psImage *test = psImageAlloc(paddedCols, paddedRows, PS_TYPE_F32);
+        psFree(test->p_rawDataBuffer);
+        test->p_rawDataBuffer = data;
+        test->data.V[0] = test->p_rawDataBuffer;
+        for (int y = 1; y < paddedRows; y++) {
+            test->data.V[y] = (psPtr)((int8_t *)test->data.V[y - 1] +
+                                      paddedCols * PSELEMTYPE_SIZEOF(PS_TYPE_F32));
+        }
+        // View image here
+        test->p_rawDataBuffer = NULL;
+        psFree(test);
+    }
+#endif
+
+    // Kernel part of data array
+    dataPtr = data + numPadded;         // Reset to kernel image location
+    float norm = 1.0 / (float)(paddedRows * paddedCols); // Normalisation to correct for FFT
+    // We could generate the padded kernel image using memcpy, but by going pixel by pixel we can apply the
+    // normalisation that corrects for the FFT renormalisation.  By applying it to the kernel here, we save
+    // applying it to the entire output image.
+    int xNegMin = PS_MIN(-1, xMin), xNegMax = PS_MIN(-1, xMax); // Min and max for x when negative
+    int xPosMin = PS_MAX(0, xMin), xPosMax = PS_MAX(0, xMax); // Min and max for x when positive
+    int yNegMin = PS_MIN(-1, yMin), yNegMax = PS_MIN(-1, yMax); // Min and max for x when negative
+    int yPosMin = PS_MAX(0, yMin), yPosMax = PS_MAX(0, yMax); // Min and max for x when positive
+    int blankCols = xNegMin + paddedCols - xPosMax - 1; // Number of columns between kernel extrema
+    int blankRows = (yNegMin + paddedRows - yPosMax - 1) * paddedCols; // Rows between kernel extrema
+    size_t blankColBytes = blankCols * PSELEMTYPE_SIZEOF(PS_TYPE_F32); // Number of bytes in blankCols
+    for (int y = yPosMin; y <= yPosMax; y++) {
+        // y is positive
+        for (int x = xPosMin; x <= xPosMax; x++, dataPtr++) {
+            // x is positive
+            *dataPtr = kernel->kernel[y][x] * norm;
+        }
+        // Columns between kernel extrema
+        memset(dataPtr, 0, blankColBytes);
+        dataPtr += blankCols;
+        for (int x = xNegMin; x <= xNegMax; x++, dataPtr++) {
+            // x is negative
+            *dataPtr = kernel->kernel[y][x] * norm;
+        }
+    }
+    // Rows between kernel extrema
+    memset(dataPtr, 0, blankRows * PSELEMTYPE_SIZEOF(PS_TYPE_F32));
+    dataPtr += blankRows;
+    for (int y = yNegMin; y <= yNegMax; y++) {
+        // y is negative
+        for (int x = xPosMin; x <= xPosMax; x++, dataPtr++) {
+            // x is positive
+            *dataPtr = kernel->kernel[y][x] * norm;
+        }
+        // Columns between kernel extrema
+        memset(dataPtr, 0, blankColBytes);
+        dataPtr += blankCols;
+        for (int x = xNegMin; x <= xNegMax; x++, dataPtr++) {
+            // x is negative
+            *dataPtr = kernel->kernel[y][x] * norm;
+        }
+    }
+
+#if 1
+    {
+        // Use this for inspecting the result of copying the kernel
+        psImage *test = psImageAlloc(paddedCols, paddedRows, PS_TYPE_F32);
+        psFree(test->p_rawDataBuffer);
+        test->p_rawDataBuffer = &data[numPadded];
+        test->data.V[0] = test->p_rawDataBuffer;
+        for (int y = 1; y < paddedRows; y++) {
+            test->data.V[y] = (psPtr)((int8_t *)test->data.V[y - 1] +
+                                      paddedCols * PSELEMTYPE_SIZEOF(PS_TYPE_F32));
+        }
+        // View image here
+        test->p_rawDataBuffer = NULL;
+        psFree(test);
+    }
+#endif
+
+    // Mask bad pixels (which may be NANs), lest they infect everything
+    if (mask && maskVal) {
+        for (int y = 0; y < numRows; y++) {
+            for (int x = 0; x < numCols; x++) {
+                if (mask->data.PS_TYPE_MASK_DATA[y][x] & maskVal) {
+                    data[x + paddedCols * y] = 0;
+                }
+            }
+        }
+    }
+
+    // Do the forward FFT
+    // Note that the FFT images have different size from the input
+    fftwf_complex *fft = fftwf_malloc(2 * (paddedCols/2 + 1) * paddedRows * sizeof(fftwf_complex)); // FFT
+    int size[] = { paddedRows, paddedCols }; // Size of transforms
+    int fftCols = paddedCols/2 + 1, fftRows = paddedRows; // Size of FFT images
+    int fftPixels = fftCols * fftRows;  // Number of pixels in FFT image
+    fftwf_plan forward = fftwf_plan_many_dft_r2c(2, size, 2, data, NULL, 1, paddedCols * paddedRows,
+                                                 fft, NULL, 1, fftPixels, FFTW_PLAN_RIGOR);
+    fftwf_execute(forward);
+    fftwf_destroy_plan(forward);
+
+    // Multiply the two transforms
+    for (int i = 0, j = fftPixels; i < fftPixels; i++, j++) {
+        // (a + bi) * (c + di) = (ac - bd) + (bc + ad)i
+#if !defined(FFTW_NO_Complex) && defined(_Complex_I) && defined(complex) && defined(I)
+        // C99 complex support
+        fft[i] *= fft[j];
+#else
+        // FFTW's backup complex support
+        float imageReal = fft[i][0], imageImag = fft[i][1];
+        float kernelReal = fft[j][0], kernelImag = fft[j][1];
+        fft[i][0] = imageReal * kernelReal - imageImag * kernelImag;
+        fft[i][1] = imageImag * kernelReal + imageReal * kernelImag;
+#endif
+    }
+
+    // Do the backward FFT
+    fftwf_plan backward = fftwf_plan_dft_c2r_2d(paddedRows, paddedCols, fft, data, FFTW_PLAN_RIGOR);
+    fftwf_execute(backward);
+    fftwf_destroy_plan(backward);
+    fftwf_free(fft);
+
+    // Copy into the target, without the padding
+    out = psImageRecycle(out, numCols, numRows, PS_TYPE_F32);
+    psF32 **outData = out->data.F32;    // Pointer into output
+    dataPtr = data;                     // Reset to start
+    for (int y = 0; y < numRows; y++, outData++, dataPtr += paddedCols) {
+        memcpy(*outData, dataPtr, goodBytes);
+    }
+    fftwf_free(data);
+
+    return out;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fft/psImageFFT.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fft/psImageFFT.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fft/psImageFFT.h	(revision 22158)
@@ -0,0 +1,77 @@
+/// @file  psImageFFT.h
+/// @brief Contains FFT transform related functions for psImage
+///
+/// @author Paul Price, IfA
+/// @author Robert DeSonia, MHPCC
+///
+/// @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+/// @date $Date: 2008-04-04 22:44:56 $
+/// Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+///
+
+#ifndef PS_IMAGE_FFT_H
+#define PS_IMAGE_FFT_H
+
+#include "psImage.h"
+#include "psImageConvolve.h"
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+/// Forward FFT of an image
+///
+/// Applies a forward FFT (exponent -1), with the result returned in both real and imaginary parts.  The FFT
+/// is not normalised (a forward followed by a reverse is the original scaled by the total number of pixels).
+/// The FFT takes advantage of the fact that the input is purely real; hence the output number of columns is
+/// numCols/2 + 1 (with division rounding down).  Only implemented for F32 input.
+bool psImageForwardFFT(psImage **real,  ///< Real part of FFT
+                       psImage **imag,  ///< Imaginary part of FFT
+                       const psImage *in///< Input image (F32)
+    );
+
+/// Backward FFT of an image
+///
+/// Applies a backward FFT (exponent +1) from the real and imaginary parts with the (purely) real result
+/// returned.  The FFT is not normalised (a forward followed by a reverse is the original scaled by the total
+/// number of pixels).  The FFT takes advantage of the fact that the output will be purely real; hence the
+/// input number of columns is numCols/2 + 1 (with division rounding down); to manage the redundancy (is the
+/// original number of columns even or odd?), we need the original number of columns (the number of columns of
+/// the image that was input to psImageForwardFFT) to be provided.  Only implemented for F32 input.
+bool psImageBackwardFFT(psImage **out,///< Output image
+                        const psImage *real, ///< Real input (F32)
+                        const psImage *imag, ///< Imaginary input (F32)
+                        int origCols    ///< Original number of columns
+    );
+
+
+/// Power spectrum of an image
+///
+/// Generates the power spectrum of an image.  Only implemented for F32 input.
+psImage* psImagePowerSpectrum(psImage *out, const psImage *in);
+
+/// Multiply complex images
+///
+/// The input images are the real and imaginary parts of each of two images.  The real and imaginary parts
+/// of the output image are returned.  Only implemented for F32 input.
+bool psImageComplexMultiply(psImage **outReal, ///< Real part of output
+                            psImage **outImag, ///< Imaginary part of output
+                            const psImage *in1Real, ///< Real part of input 1
+                            const psImage *in1Imag, ///< Imaginary part of input 1
+                            const psImage *in2Real, ///< Real part of input 2
+                            const psImage *in2Imag ///< Imaginary part of input 2
+    );
+
+/// Convolve an image with a kernel, using the FFT
+///
+/// This is appropriate for larger kernels, where the direct convolution is slow.  The input image and kernel
+/// are suitably padded to avoid wrap-around effects.
+psImage *psImageConvolveFFT(
+    psImage *out,                       ///< Output image, or NULL
+    const psImage *in,                  ///< Image to convolve
+    const psImage *mask,                ///< Corresponding mask
+    psMaskType maskVal,                 ///< Value to mask
+    const psKernel *kernel              ///< kernel to colvolve with
+);
+
+/// @}
+#endif // #ifndef PS_IMAGE_FFT_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fft/psVectorFFT.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fft/psVectorFFT.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fft/psVectorFFT.c	(revision 22158)
@@ -0,0 +1,186 @@
+/** @file  psVectorFFT.c
+ *
+ *  @brief Contains FFT transform related functions for psVector
+ *
+ *  @author Paul Price, IfA
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.39 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-02-09 00:45:51 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+#include <stdbool.h>
+#include <string.h>
+#include <complex.h>
+#include <fftw3.h>
+
+#include "psAssert.h"
+#include "psError.h"
+#include "psMemory.h"
+#include "psLogMsg.h"
+#include "psConstants.h"
+#include "psVectorFFT.h"
+
+#define FFTW_PLAN_RIGOR FFTW_ESTIMATE   // How rigorous the FFTW planning is
+
+static psBool fftwWisdomImported = false; // Has the system wisdom been imported?
+
+bool psVectorForwardFFT(psVector **real, psVector **imag, const psVector *in)
+{
+    PS_ASSERT_VECTOR_NON_NULL(in, false);
+    PS_ASSERT_VECTOR_TYPE(in, PS_TYPE_F32, false);
+    PS_ASSERT_PTR_NON_NULL(real, false);
+    PS_ASSERT_PTR_NON_NULL(imag, false);
+
+    // Make sure the system-level wisdom information is imported.
+    if (!fftwWisdomImported) {
+        fftwf_import_system_wisdom();
+        fftwWisdomImported = true;
+    }
+
+    long num = in->n;                   // Number of elements
+
+    // Do the FFT
+    fftwf_complex *out = fftwf_malloc((num/2 + 1) * sizeof(fftwf_complex)); // Output data
+    fftwf_plan plan = fftwf_plan_dft_r2c_1d(num, in->data.F32, out, FFTW_PLAN_RIGOR);
+    fftwf_execute(plan);
+    fftwf_destroy_plan(plan);
+
+    // Pull the real and imaginary parts out
+    num = num/2 + 1;
+    *real = psVectorRecycle(*real, num, PS_TYPE_F32);
+    *imag = psVectorRecycle(*imag, num, PS_TYPE_F32);
+    for (int i = 0; i < num; i++) {
+#if !defined(FFTW_NO_Complex) && defined(_Complex_I) && defined(complex) && defined(I)
+        // C99 complex support
+        (*real)->data.F32[i] = creal(out[i]);
+        (*imag)->data.F32[i] = cimag(out[i]);
+#else
+        // FFTW's backup complex support
+        (*real)->data.F32[i] = out[i][0];
+        (*imag)->data.F32[i] = out[i][1];
+#endif
+    }
+    fftwf_free(out);
+
+    return true;
+}
+
+bool psVectorBackwardFFT(psVector **out, const psVector *real, const psVector *imag, long origNum)
+{
+    PS_ASSERT_VECTOR_NON_NULL(real, false);
+    PS_ASSERT_VECTOR_TYPE(real, PS_TYPE_F32, false);
+    PS_ASSERT_VECTOR_NON_NULL(imag, false);
+    PS_ASSERT_VECTOR_TYPE(imag, PS_TYPE_F32, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(real, imag, false);
+    PS_ASSERT_PTR_NON_NULL(out, false);
+
+    // Make sure the system-level wisdom information is imported.
+    if (!fftwWisdomImported) {
+        fftwf_import_system_wisdom();
+        fftwWisdomImported = true;
+    }
+
+    long num = real->n;                 // Number of elements
+
+    // Stuff the real and imaginary parts in
+    fftwf_complex *in = fftwf_malloc(num * sizeof(fftwf_complex)); // Input data
+    for (int i = 0; i < num; i++) {
+#if !defined(FFTW_NO_Complex) && defined(_Complex_I) && defined(complex) && defined(I)
+        // C99 complex support
+        in[i] = real->data.F32[i] + imag->data.F32[i] * I;
+#else
+        // FFTW's backup complex support
+        in[i][0] = real->data.F32[i];
+        in[i][1] = imag->data.F32[i];
+#endif
+    }
+
+
+    // Do the FFT
+    *out = psVectorRecycle(*out, origNum, PS_TYPE_F32);
+    fftwf_plan plan = fftwf_plan_dft_c2r_1d(origNum, in, (*out)->data.F32, FFTW_PLAN_RIGOR);
+    fftwf_execute(plan);
+    fftwf_destroy_plan(plan);
+
+    fftwf_free(in);
+
+    return true;
+}
+
+psVector *psVectorPowerSpectrum(psVector* out, const psVector* in)
+{
+    PS_ASSERT_VECTOR_NON_NULL(in, NULL);
+    PS_ASSERT_VECTOR_TYPE(in, PS_TYPE_F32, NULL);
+
+    psVector *real = NULL;              // Real component of FFT
+    psVector *imag = NULL;              // Imaginary component of FFT
+
+    if (!psVectorForwardFFT(&real, &imag, in)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to perform forward FFT.");
+        return NULL;
+    }
+
+    int num = real->n;                  // Number of elements
+
+    float norm = 1.0 / PS_SQR(in->n);
+    for (int i = 0; i < num; i++) {
+        // Power spectrum is the square of the complex modulus
+        real->data.F32[i] = norm * (PS_SQR(real->data.F32[i]) + PS_SQR(imag->data.F32[i]));
+    }
+    psFree(imag);
+
+    return real;
+}
+
+bool psVectorComplexMultiply(psVector **outReal, psVector **outImag,
+                             const psVector *in1Real, const psVector *in1Imag,
+                             const psVector *in2Real, const psVector *in2Imag)
+{
+    PS_ASSERT_VECTOR_NON_NULL(in1Real, false);
+    PS_ASSERT_VECTOR_NON_NULL(in1Imag, false);
+    PS_ASSERT_VECTOR_NON_NULL(in2Real, false);
+    PS_ASSERT_VECTOR_NON_NULL(in2Imag, false);
+    PS_ASSERT_VECTOR_TYPE(in1Real, PS_TYPE_F32, false);
+    PS_ASSERT_VECTOR_TYPE(in1Imag, PS_TYPE_F32, false);
+    PS_ASSERT_VECTOR_TYPE(in2Real, PS_TYPE_F32, false);
+    PS_ASSERT_VECTOR_TYPE(in2Imag, PS_TYPE_F32, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(in1Imag, in1Real, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(in2Real, in1Real, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(in2Imag, in1Real, false);
+    PS_ASSERT_PTR_NON_NULL(outReal, false);
+    PS_ASSERT_PTR_NON_NULL(outImag, false);
+    if (*outReal) {
+        PS_ASSERT_VECTOR_NON_NULL(*outReal, false);
+        PS_ASSERT_VECTOR_NON_NULL(*outImag, false);
+    } else if (*outImag) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "If the output real part is provided, the output imaginary part must also be provided.");
+        return false;
+    }
+
+    int num = in1Real->n;               // Number of elements
+
+    *outReal = psVectorRecycle(*outReal, num, PS_TYPE_F32);
+    *outImag = psVectorRecycle(*outImag, num, PS_TYPE_F32);
+
+    for (int i = 0; i < num; i++) {
+        // (a + bi) * (c + di) = (ac - bd) + (bc + ad)i
+        float real = in1Real->data.F32[i] * in2Real->data.F32[i] -
+            in1Imag->data.F32[i] * in2Imag->data.F32[i];
+        float imag = in1Imag->data.F32[i] * in2Real->data.F32[i] +
+            in1Real->data.F32[i] * in2Imag->data.F32[i];
+
+        (*outReal)->data.F32[i] = real;
+        (*outImag)->data.F32[i] = imag;
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fft/psVectorFFT.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fft/psVectorFFT.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fft/psVectorFFT.h	(revision 22158)
@@ -0,0 +1,65 @@
+/// @file  psVectorFFT.h
+/// @brief Contains FFT transform related functions for psVector
+///
+/// @author Paul Price, IfA
+/// @author Robert DeSonia, MHPCC
+///
+/// @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
+/// @date $Date: 2007-02-08 04:23:57 $
+/// Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+///
+
+#ifndef PS_VECTOR_FFT_H
+#define PS_VECTOR_FFT_H
+
+#include "psVector.h"
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+/// Forward FFT of a vector
+///
+/// Applies a forward FFT (exponent -1), with the result returned in both real and imaginary parts.  The FFT
+/// is not normalised (a forward followed by a reverse is the original scaled by the number of elements).  The
+/// FFT takes advantage of the fact that the input is purely real; hence the output size is N/2 + 1 (with
+/// division rounding down).  Only implemented for F32 input.
+bool psVectorForwardFFT(psVector **real,///< Real part of FFT
+                        psVector **imag,///< Imaginary part of FFT
+                        const psVector *in ///< Input vector (F32)
+    );
+
+/// Backward FFT of a vector
+///
+/// Applies a backward FFT (exponent +1) from the real and imaginary parts with the (purely) real result
+/// returned.  The FFT is not normalised (a forward followed by a reverse is the original scaled by the number
+/// of elements).  The FFT takes advantage of the fact that the output will be purely real; hence the input
+/// size is N/2 + 1 (with division rounding down); to manage the redundancy (is the original size even or
+/// odd?), we need the original size (the size of the array that was input to psVectorForwardFFT) to be
+/// provided.  Only implemented for F32 input.
+bool psVectorBackwardFFT(psVector **out,///< Output vector
+                         const psVector *real, ///< Real input (F32)
+                         const psVector *imag, ///< Imaginary input (F32)
+                         long origNum    ///< Original number of elements
+    );
+
+/// Power spectrum of a vector
+///
+/// Generates the power spectrum of a vector.  Only implemented for F32 input.
+psVector *psVectorPowerSpectrum(psVector *out, ///< Output power spectrum, or NULL
+                                const psVector* in ///< Input vector (F32)
+    );
+
+/// Multiply complex vectors
+///
+/// The input vectors are the real and imaginary parts of each of two vectors.  The real and imaginary parts
+/// of the output vector are returned.  Only implemented for F32 input.
+bool psVectorComplexMultiply(psVector **outReal, ///< Real part of output
+                             psVector **outImag, ///< Imaginary part of output
+                             const psVector *in1Real, ///< Real part of input 1
+                             const psVector *in1Imag, ///< Imaginary part of input 1
+                             const psVector *in2Real, ///< Real part of input 2
+                             const psVector *in2Imag ///< Imaginary part of input 2
+    );
+
+/// @}
+#endif // #ifndef PS_VECTOR_FFT_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fits/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fits/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fits/.cvsignore	(revision 22158)
@@ -0,0 +1,10 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
+*.loT
+*.bb
+*.bbg
+*.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fits/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fits/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fits/Makefile.am	(revision 22158)
@@ -0,0 +1,26 @@
+#Makefile for fits functions of psLib
+#
+noinst_LTLIBRARIES = libpslibfits.la
+
+libpslibfits_la_CFLAGS = $(SRCINC) $(PSLIB_CFLAGS) $(CFITSIO_CFLAGS) $(AM_CFLAGS)
+libpslibfits_la_SOURCES = \
+	psFits.c \
+	psFitsHeader.c \
+	psFitsImage.c \
+	psFitsTable.c \
+	psFitsFloat.c \
+	psFitsFloatFile.c \
+	psFitsScale.c
+
+EXTRA_DIST = fits.i
+
+pkginclude_HEADERS = \
+	psFits.h \
+	psFitsHeader.h \
+	psFitsImage.h \
+	psFitsTable.h \
+	psFitsFloat.h \
+	psFitsFloatFile.h \
+	psFitsScale.h
+
+CLEANFILES = *~ *.bb *.bbg *.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fits/fits.i
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fits/fits.i	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fits/fits.i	(revision 22158)
@@ -0,0 +1,5 @@
+/* fits headers */
+%include "psFits.h"
+%include "psFitsHeader.h"
+%include "psFitsImage.h"
+%include "psFitsTable.h"
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFits.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFits.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFits.c	(revision 22158)
@@ -0,0 +1,915 @@
+/** @file  psFits.c
+ *
+ *  @brief Contains Fits I/O routines
+ *
+ *  @ingroup FileIO
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.80 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-05-13 22:03:21 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <unistd.h>
+#include <string.h>
+
+#include "psFits.h"
+#include "psFitsHeader.h"
+#include "psError.h"
+#include "psAssert.h"
+#include "psImageStructManip.h"
+#include "psMemory.h"
+#include "psString.h"
+#include "psLogMsg.h"
+#include "psTrace.h"
+#include "psVector.h"
+#include "psAbort.h"
+#include "psFitsFloat.h"
+
+#define MAX_STRING_LENGTH 256  // maximum length string for FITS routines
+static char *defaultExtword = "EXTNAME";
+
+static bool isHDUEmpty(const psFits* fits)
+{
+    /* check for keys - no keys means this is really an empty HDU */
+    int keysexist = -1;
+    int morekeys;
+    int status = 0;
+
+    fits_get_hdrspace(fits->fd, &keysexist, &morekeys, &status);
+
+    // if no keys exist and not primary HDU, this really is an empty HDU
+    if (keysexist == 0) {
+        return true;
+    }
+
+    return false;
+
+}
+
+static bool fitsClose(psFits* fits)
+{
+    int status = 0;
+
+    if (fits != NULL) {
+        if (fits_close_file(fits->fd, &status)) {
+            char fitsErr[MAX_STRING_LENGTH];
+            fits_get_errstatus(status, fitsErr);
+            psError(PS_ERR_BAD_FITS, true,
+                    "Error while closing psFits object. CFITSIO error: %s",
+                    fitsErr);
+            return false;
+        }
+        fits->fd = NULL;
+    }
+    return true;
+}
+
+static void fitsFree(psFits* fits)
+{
+    if (!fits) return;
+    if (fits->fd) {
+        fitsClose(fits);
+    }
+    psFree(fits->options);
+}
+
+bool psFitsClose(psFits* fits)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    bool status = fitsClose(fits);
+    psFree(fits);
+
+    return status;
+}
+
+psFits* psFitsOpen(const char* name, const char* mode)
+{
+    PS_ASSERT_STRING_NON_EMPTY(name, NULL);
+
+    int status = 0;
+    fitsfile *fptr = NULL;      /* Pointer to the FITS file */
+
+    /* check the mode to determine how to open/create file */
+    int iomode;
+    bool newFile;
+    if (strcmp(mode,"r") == 0) {
+        iomode = READONLY;
+        newFile = false;
+    } else if (strcmp(mode,"rw") == 0 || strcmp(mode,"r+") == 0) {
+        iomode = READWRITE;
+        newFile = false;
+    } else if (strcmp(mode,"w") == 0 || strcmp(mode,"w+") == 0) {
+        iomode = READWRITE;
+        newFile = true;
+    } else if (strcmp(mode,"a") == 0|| strcmp(mode,"a+") == 0) {
+        iomode = READWRITE;
+        newFile = (access(name, F_OK) != 0);
+    } else {
+        // mode is not valid
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Specified mode, '%s', is invalid.  Supported modes are r, r+, rw, w, w+, a, or a+.",
+                mode);
+        return NULL;
+    }
+
+    if (newFile) {
+        /* Check if an existing file is in the way before creating file*/
+        if (access(name, F_OK) == 0) {
+            // file exists, delete old one first
+            remove(name);
+        }
+
+        #if ( CFITSIO_DISKFILE == 1 )
+        (void)fits_create_diskfile
+        #else
+        (void)fits_create_file
+        #endif
+        (&fptr, name, &status);
+        if (fptr == NULL || status != 0) {
+            char fitsErr[MAX_STRING_LENGTH];
+            fits_get_errstatus(status, fitsErr);
+            psError(PS_ERR_IO, true,
+                    _("Could not create file,'%s'. CFITSIO Error: %s"),
+                    name, fitsErr);
+            return NULL;
+        }
+    } else {
+        #if ( CFITSIO_DISKFILE == 1 )
+        (void)fits_open_diskfile
+        #else
+        (void)fits_open_file
+        #endif
+        (&fptr, name, iomode, &status);
+        if (fptr == NULL || status != 0) {
+            char fitsErr[MAX_STRING_LENGTH];
+            fits_get_errstatus(status, fitsErr);
+            psError(PS_ERR_IO, true,
+                    _("Could not open file,'%s'. CFITSIO Error: %s"),
+                    name, fitsErr);
+            return NULL;
+        }
+    }
+
+    psFits* fits = psAlloc(sizeof(psFits));
+    psMemSetDeallocator(fits, (psFreeFunc)fitsFree);
+
+    fits->fd = fptr;
+    fits->writable = (iomode == READWRITE);
+
+    fits->options = NULL;
+
+    return fits;
+}
+
+
+static void fitsOptionsFree(psFitsOptions *options)
+{
+    psFree(options->extword);
+}
+
+
+psFitsOptions *psFitsOptionsAlloc(void)
+{
+    psFitsOptions *options = psAlloc(sizeof(psFitsOptions)); // Options, to return
+    psMemSetDeallocator(options, (psFreeFunc)fitsOptionsFree);
+
+    options->extword = NULL;
+
+    options->conventions.compression = true;
+    options->conventions.psBitpix = true;
+
+    options->floatType = PS_FITS_FLOAT_NONE;
+
+    options->bitpix = 0;
+
+    options->scaling = PS_FITS_SCALE_NONE;
+    options->fuzz = true;
+    options->bscale = 1.0;
+    options->bzero = 0.0;
+    options->mean = NAN;
+    options->stdev = NAN;
+    options->stdevBits = 4;
+    options->stdevNum = 5.0;
+
+    return options;
+}
+
+psErrorCode p_psFitsError(const char* filename, unsigned int lineno, const char* func, int status,
+                          bool new, const char *errorMsg, ...)
+{
+    if (status == 0) {
+        return PS_ERR_NONE;
+    }
+
+    va_list ap;                         // Variable arguments
+    va_start(ap, errorMsg);
+    psString msg = NULL;                // Message to pass to psError
+    psStringAppendV(&msg, errorMsg, ap);
+    va_end(ap);
+
+    char cfitsioMsg[MAX_STRING_LENGTH];   // Error message from cfitsio
+    (void)fits_get_errstatus(status, cfitsioMsg);
+
+    psStringAppend(&msg, "[CFITSIO error: %s]", cfitsioMsg);
+
+    psErrorCode code = p_psError(filename, lineno, func, PS_ERR_IO, new, msg); // Error code
+    psFree(msg);
+    return code;
+}
+
+static void psFitsCompressionFree(psFitsCompression *comp)
+{
+    PS_ASSERT_PTR_NON_NULL(comp,);
+    psFree(comp->tilesize);
+}
+
+psFitsCompression* psFitsCompressionAlloc(
+    psFitsCompressionType type,         ///< type of compression
+    psVector *tilesize,                 ///< vector defining compression tile size
+    int noisebits,                      ///< noise bits
+    int scale,                          ///< hcompress scale
+    int smooth                          ///< hcompress smothing
+)
+{
+    psFitsCompression *comp = psAlloc(sizeof(psFitsCompression));
+    psMemSetDeallocator(comp, (psFreeFunc) psFitsCompressionFree);
+
+    comp->type = type;
+    comp->tilesize = psVectorCopy(NULL, tilesize, PS_DATA_S64);
+    comp->noisebits = noisebits;
+    comp->scale = scale;
+    comp->smooth = smooth;
+
+    return comp;
+}
+
+bool psMemCheckFits(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)fitsFree );
+}
+
+bool psFitsSetExtnameWord(psFits *fits, const char *extword)
+{
+    PS_ASSERT_PTR_NON_NULL(fits,    false);
+    PS_ASSERT_PTR_NON_NULL(extword, false);
+
+    if (!fits->options) {
+        fits->options = psFitsOptionsAlloc();
+    }
+
+    psFree(fits->options->extword);
+    fits->options->extword = psStringCopy(extword);
+    return true;
+}
+
+// Files compressed with cfitsio's "imcopy" program may have multiple EXTNAME keywords, with the first set to
+// COMPRESSED_IMAGE.  However, fits_movnam_hdu won't find the second (proper) value of EXTNAME, and so can
+// fail to find a perfectly legitimate extension, simply because imcopy does something silly.  However, we
+// really want to be able to read these files (MegaCam data are shipped as imcopy-compressed images).
+// Therefore, we implement our own version of moving to an extension specified by name.  The pure cfitsio
+// version is used if "conventions.compression" handling is turned off in the psFits structure.
+bool psFitsMoveExtName(const psFits* fits,
+                       const char* extname)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_STRING_NON_EMPTY(extname, false);
+
+    int status = 0;
+
+    psFitsOptions *options = fits->options; // FITS options
+    if (options && !options->conventions.compression && !options->extword) {
+        // User wants to use cfitsio.  Good luck to them!
+        if (fits_movnam_hdu(fits->fd, ANY_HDU, (char*)extname, 0, &status) != 0) {
+            psFitsError(status, true, _("Could not find HDU '%s'"), extname);
+            return false;
+        }
+        return true;
+    }
+
+    // Ignore EXTNAME with value COMPRESSED_IMAGE?
+    bool ignoreCI = (!options || (options->conventions.compression && (strcmp(extname, "COMPRESSED_IMAGE") != 0)));
+
+    char *extword = (options && options->extword) ? options->extword : "EXTNAME"; // Word for extension name
+
+#if 0
+    // XXX Future optimisation: loop through from the current HDU to the end, then from the start to the
+    // current position.  This will save seeking through the file multiple times.
+    int currentExt = psFitsGetExtNum(fits); // Current extension number
+    int numExt = psFitsGetSize(fits);   // Total number of extensions
+#endif
+
+    for (int i = 1; true; i++) {
+        int hdutype = 0;
+        if (fits_movabs_hdu(fits->fd, i, &hdutype, &status)) {
+            // We've run off the end
+            psFitsError(status, true, _("Could not find HDU with %s = '%s'"), extword, extname);
+            return false;
+        }
+        // Is there a keyword called 'extword'? (read as string regardless of type)
+        char name[MAX_STRING_LENGTH];  // Name of extension
+        if (fits_read_keyword(fits->fd, extword, name, NULL, &status)) {
+            // It doesn't exist in the header.
+            // This isn't the extension you're looking for.  Move along.
+            status = 0;
+            continue;
+        }
+        char *fixed = p_psFitsHeaderParseString(name); // Parsed version (removing quotes and spaces)
+
+        if (ignoreCI && strcmp(fixed, "COMPRESSED_IMAGE") == 0) {
+            // Read it again, Sam
+            if (fits_read_keyword(fits->fd, extword, name, NULL, &status)) {
+                status = 0;
+                continue;
+            }
+            fixed = p_psFitsHeaderParseString(name);
+        }
+
+        if (strcmp(fixed, extname) == 0) {
+            // We've arrived
+            return true;
+        }
+    }
+    psAbort("Should never reach here.");
+}
+
+bool psFitsMoveExtNum(const psFits* fits,
+                      int extnum,
+                      bool relative)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    int status = 0;
+    int hdutype = 0;
+
+    if (relative) {
+        fits_movrel_hdu(fits->fd, extnum, &hdutype, &status);
+        if (status != 0) {
+            char fitsErr[MAX_STRING_LENGTH];
+            fits_get_errstatus(status, fitsErr);
+            psError(PS_ERR_LOCATION_INVALID, true,
+                    _("Could not move %d HDUs from current position. CFITSIO Error: %s"),
+                    extnum, fitsErr);
+            return false;
+        }
+    } else {
+        fits_movabs_hdu(fits->fd, extnum+1, &hdutype, &status);
+        if (status != 0) {
+            char fitsErr[MAX_STRING_LENGTH];
+            fits_get_errstatus(status, fitsErr);
+            psError(PS_ERR_LOCATION_INVALID, true,
+                    _("Could not move to specified HDU #%d. CFITSIO Error: %s"),
+                    extnum, fitsErr);
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool psFitsMoveLast(psFits* fits)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    int size = psFitsGetSize(fits);
+    if (size == 0) { // empty file -- no action needed
+        return true;
+    } else {
+        return psFitsMoveExtNum(fits,size-1,false);
+    }
+}
+
+int psFitsGetExtNum(const psFits* fits)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    int hdunum;
+    return fits_get_hdu_num(fits->fd,&hdunum) - 1;
+}
+
+psString psFitsGetExtName(const psFits* fits)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+
+    int status = 0;
+    char name[MAX_STRING_LENGTH];
+
+    psFitsOptions *options = fits->options; // FITS options
+    char *extword = (!options || !options->extword) ? defaultExtword : options->extword;
+
+    if (fits_read_key_str(fits->fd, extword, name, NULL, &status) != 0) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true, _("Header keyword %s is not found"), extword);
+        return NULL;
+    }
+    return psStringCopy(name);
+}
+
+bool psFitsSetExtName(psFits* fits, const char* name)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_STRING_NON_EMPTY(name, false);
+
+    int status = 0;
+
+    psFitsOptions *options = fits->options; // FITS options
+    char *extword = (!options || !options->extword) ? defaultExtword : options->extword;
+
+    if (fits_update_key_str(fits->fd, extword, (char*)name, NULL, &status) != 0) {
+        char fitsErr[MAX_STRING_LENGTH];
+        (void)fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_IO, true, _("Could not write data to file. CFITSIO Error: %s"), fitsErr);
+        return false;
+    }
+
+    return true;
+}
+
+bool psFitsDeleteExtNum(psFits* fits,
+                        int extnum,
+                        bool relative)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_FITS_WRITABLE(fits, false);
+
+    // move to the specified HDU
+    if (!psFitsMoveExtNum(fits, extnum, relative) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Failed to delete HDU #%d", extnum);
+        return false;
+    }
+
+    int status = 0;
+
+    // OK, now let's delete the HDU
+    if (fits_delete_hdu(fits->fd, NULL, &status) != 0) {
+        char fitsErr[MAX_STRING_LENGTH];
+        (void)fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_IO, true, _("Could not write data to file. CFITSIO Error: %s"), fitsErr);
+        return false;
+    }
+
+    return true;
+}
+
+bool psFitsDeleteExtName(psFits* fits,
+                         const char* extname)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_FITS_WRITABLE(fits, false);
+    PS_ASSERT_STRING_NON_EMPTY(extname, false);
+
+    // move to the specified HDU
+    if (! psFitsMoveExtName(fits,extname) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "Failed to delete HDU with the name '%s'",
+                extname);
+        return false;
+    }
+
+
+    int status = 0;
+
+    // OK, now let's delete the HDU
+    if (fits_delete_hdu(fits->fd, NULL, &status) != 0) {
+        char fitsErr[MAX_STRING_LENGTH];
+        (void)fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_IO, true,
+                _("Could not write data to file. CFITSIO Error: %s"),
+                fitsErr);
+        return false;
+    }
+
+    return true;
+}
+
+int psFitsGetSize(const psFits* fits)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, 0);
+
+    int num = 0;
+    int status = 0;
+
+    if (fits_get_num_hdus(fits->fd, &num, &status) != 0) {
+        char fitsErr[MAX_STRING_LENGTH];
+        fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_LOCATION_INVALID, true,
+                _("Failed to determine the number of HDUs. CFITSIO Error: %s"),
+                fitsErr);
+        return 0;
+    }
+
+    return num;
+}
+
+psFitsType psFitsGetExtType(const psFits* fits)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, PS_FITS_TYPE_NONE);
+
+    int status = 0;
+    int hdutype = PS_FITS_TYPE_NONE;
+
+    if (fits_get_hdu_type(fits->fd, &hdutype, &status) != 0) {
+        char fitsErr[MAX_STRING_LENGTH];
+        fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_LOCATION_INVALID, true,
+                _("Failed to determine an HDU type. CFITSIO Error: %s"),
+                fitsErr);
+        return PS_FITS_TYPE_NONE;
+    }
+
+    if (hdutype == PS_FITS_TYPE_IMAGE &&
+            psFitsGetExtNum(fits) > 0 &&
+            isHDUEmpty(fits)) {
+        return PS_FITS_TYPE_ANY;
+    }
+
+    return hdutype;
+}
+
+bool psFitsTruncate(psFits* fits)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_FITS_WRITABLE(fits, false);
+
+    int newEnd = psFitsGetExtNum(fits);
+
+    psFitsMoveLast(fits);
+    int end = psFitsGetExtNum(fits);
+
+    // delete HDUs from end to beginning position + 1;
+    for (int lcv=end;lcv > newEnd; lcv--) {
+        if (! psFitsDeleteExtNum(fits,lcv,false)) {
+            // failed to delete an HDU!?
+            psError(PS_ERR_UNKNOWN, false,
+                    "Failed to truncate file.  HDU #%d out of %d could not be deleted.",
+                    lcv,end);
+            return false;
+        }
+    }
+
+    return true;
+}
+
+
+bool psFitsSetCompression(
+    psFits* fits,                       ///< psFits object to close
+    psFitsCompressionType type,         ///< type of compression
+    psVector *tilesize,
+    int noisebits,                      ///< noise bits
+    int scale,                          ///< hcompress scale
+    int smooth                          ///< hcompress smothing
+)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_FITS_WRITABLE(fits, false);
+
+    // convert psFitsCompressionType to cfitsio compression types
+    int comptype;
+    switch (type) {
+        case PS_FITS_COMPRESS_NONE:
+            comptype = 0x0;
+            break;
+        case PS_FITS_COMPRESS_GZIP:
+            comptype = GZIP_1;
+            break;
+        case PS_FITS_COMPRESS_RICE:
+            comptype = RICE_1;
+            break;
+        case PS_FITS_COMPRESS_HCOMPRESS:
+            comptype = HCOMPRESS_1;
+            break;
+        case PS_FITS_COMPRESS_PLIO:
+            comptype = PLIO_1;
+            break;
+        default:
+            psError(PS_ERR_UNKNOWN, true, "invalid psFitsCompressionType");
+            return false;
+    }
+
+    int status = 0;
+    if (fits_set_compression_type(fits->fd, comptype, &status)) {
+        char fitsErr[MAX_STRING_LENGTH];
+        fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_BAD_FITS, true,
+            "Error while configuring compression. CFITSIO error: %s", fitsErr);
+        return false;
+    }
+
+    // if we are setting a trivial compression (NONE), don't bother with the other parameters
+    if (type == PS_FITS_COMPRESS_NONE) {
+        return true;
+    }
+
+    PS_ASSERT_VECTOR_NON_NULL(tilesize, false);
+
+    // convert a psVector into the (long *) array that cfitsio requires
+    psVector *dim = NULL;
+    if (sizeof(long) == sizeof(psS64)) {
+        dim = psVectorCopy(NULL, tilesize, PS_DATA_S64);
+        fits_set_tile_dim(fits->fd, psVectorLength(dim), (long *)dim->data.S64, &status);
+    } else if (sizeof(long) == sizeof(psS32)) {
+        dim = psVectorCopy(NULL, tilesize, PS_DATA_S32);
+        fits_set_tile_dim(fits->fd, psVectorLength(dim), (long *)dim->data.S32, &status);
+    } else {
+        psAbort("can't map (long) type to a psLib type");
+    }
+    psFree(dim);
+    // status check belongs to fits_set_tile_dim() call
+    if (status) {
+        fits_set_compression_type(fits->fd, 0x0, &status);
+        char fitsErr[MAX_STRING_LENGTH];
+        fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_BAD_FITS, true,
+            "Error while configuring compression. CFITSIO error: %s", fitsErr);
+        return false;
+    }
+
+    // noise bits are irrelevant (not allowed) for PLIO.  XXX actually, it is the data type
+    // that is the restriction; data must be 32 or 64 bit for noise bits to be valid.
+    if (type != PS_FITS_COMPRESS_PLIO) {
+        if (fits_set_noise_bits(fits->fd, noisebits, &status)) {
+            fits_set_compression_type(fits->fd, 0x0, &status);
+            char fitsErr[MAX_STRING_LENGTH];
+            fits_get_errstatus(status, fitsErr);
+            psError(PS_ERR_BAD_FITS, true,
+                    "Error while configuring compression. CFITSIO error: %s", fitsErr);
+            return false;
+        }
+    }
+
+#if FITS_HCOMP
+    if (fits_set_hcomp_scale(fits->fd, scale, &status)) {
+        fits_set_compression_type(fits->fd, 0x0, &status);
+        char fitsErr[MAX_STRING_LENGTH];
+        fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_BAD_FITS, true,
+            "Error while configuring compression. CFITSIO error: %s", fitsErr);
+        return false;
+    }
+    if (fits_set_hcomp_smooth(fits->fd, smooth, &status)) {
+        fits_set_compression_type(fits->fd, 0x0, &status);
+        char fitsErr[MAX_STRING_LENGTH];
+        fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_BAD_FITS, true,
+            "Error while configuring compression. CFITSIO error: %s", fitsErr);
+        return false;
+    }
+#endif // FITS_HCOMP
+
+    return true;
+}
+
+psFitsCompression *psFitsCompressionGet(psFits* fits)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+
+    int status = 0;                     // cfitsio status
+
+    psFitsCompressionType type = psFitsCompressionGetType(fits);
+    if (type < 0) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to get compression type.");
+        return NULL;
+    }
+
+    psElemType tileType;                // Type corresponding to "long"
+    if (sizeof(long) == sizeof(psS64)) {
+        tileType = PS_TYPE_S64;
+    } else if (sizeof(long) == sizeof(psS32)) {
+        tileType = PS_TYPE_S32;
+    } else {
+        psAbort("can't map (long) type to a psLib type");
+    }
+
+    psVector *tiles = psVectorAlloc(3, tileType); // Tile sizes
+    if (fits_get_tile_dim(fits->fd, 3, (long*)tiles->data.U8, &status)) {
+        psFitsError(status, true, "Unable to get compression tile sizes.");
+        psFree(tiles);
+        return NULL;
+    }
+
+    int noisebits;                      // Noise bits for compression
+    if (fits_get_noise_bits(fits->fd, &noisebits, &status)) {
+        psFitsError(status, true, "Unable to get compression noise bits.");
+        psFree(tiles);
+        return NULL;
+    }
+
+    int hscale = 0, hsmooth = 0;        // Scaling and smoothing for HCOMPRESS
+
+#if FITS_HCOMP
+    if (fits_get_hcomp_scale(fits->fd, &hscale, &status)) {
+        psFitsError(status, true, "Unable to get HCOMPRESS scaling.");
+        psFree(tiles);
+        return NULL;
+    }
+    if (fits_get_hcomp_smooth(fits->fd, &hsmooth, &status)) {
+        psFitsError(status, true, "Unable to get HCOMPRESS smoothing.");
+        psFree(tiles);
+        return NULL;
+    }
+#endif // FITS_HCOMP
+
+    psFitsCompression *compress = psFitsCompressionAlloc(type, tiles, noisebits, hscale, hsmooth);
+    psFree(tiles);                      // Drop reference
+
+    return compress;
+}
+
+psFitsCompressionType psFitsCompressionGetType(psFits* fits)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, -1);
+
+    int status = 0;                     // cfitsio status
+    int comptype = 0;                   // cfitsio compression type
+    if (fits_get_compression_type(fits->fd, &comptype, &status)) {
+        psFitsError(status, true, "Unable to get compression type.");
+        return -1;
+    }
+
+    psFitsCompressionType type;
+    switch (comptype) {
+      case 0:
+        type = PS_FITS_COMPRESS_NONE;
+        break;
+      case GZIP_1:
+        type = PS_FITS_COMPRESS_GZIP;
+        break;
+      case RICE_1:
+        type = PS_FITS_COMPRESS_RICE;
+        break;
+      case HCOMPRESS_1:
+        type = PS_FITS_COMPRESS_HCOMPRESS;
+        break;
+      case PLIO_1:
+        type = PS_FITS_COMPRESS_PLIO;
+        break;
+      default:
+        psError(PS_ERR_UNKNOWN, true, "cfitsio reports unknown compression type.");
+        return -1;
+    }
+
+    return type;
+}
+
+
+bool psFitsCompressionApply(
+    psFits* fits,                       ///< psFits object to close
+    psFitsCompression *comp             ///< options object
+)
+{
+    return psFitsSetCompression(fits, comp->type, comp->tilesize, comp->noisebits, comp->scale, comp->smooth);
+}
+
+
+psDataType p_psFitsTypeFromCfitsio(int datatype)
+{
+    switch (datatype) {
+    case TBYTE:
+        return PS_TYPE_U8;
+    case TSBYTE:
+        return PS_TYPE_S8;
+    case TSHORT:
+        return PS_TYPE_S16;
+    case TUSHORT:
+        return PS_TYPE_U16;
+    case TLONG:
+        if (sizeof(long) == 8) {
+            return PS_TYPE_S64;
+        }
+        // no break
+    case TINT:
+        return PS_TYPE_S32;
+    case TULONG:
+        if (sizeof(unsigned long) == 8) {
+            return PS_TYPE_U64;
+        }
+        // no break
+    case TUINT:
+        return PS_TYPE_U32;
+    case TLONGLONG:
+        return PS_TYPE_S64;
+    case TFLOAT:
+        return PS_TYPE_F32;
+    case TDOUBLE:
+        return PS_TYPE_F64;
+    case TLOGICAL:
+        return PS_TYPE_BOOL;
+    default:
+        psError(PS_ERR_IO, true,
+                "Unknown FITS datatype, %d.",
+                datatype);
+        return 0;
+    }
+}
+
+bool p_psFitsTypeToCfitsio(psDataType type, int* bitPix, double* bZero, int* dataType)
+{
+    int bitpix;
+    int datatype;
+    double bzero = 0.0;
+
+    switch (type) {
+
+    case PS_TYPE_U8:
+        bitpix = BYTE_IMG;
+        // bzero = -1.0 * INT8_MIN;
+        datatype = TBYTE;
+        break;
+
+    case PS_TYPE_S8:
+        bitpix = BYTE_IMG;
+        bzero = +1.0 * INT8_MIN;
+        datatype = TSBYTE;
+        break;
+
+    case PS_TYPE_U16:
+        bitpix = SHORT_IMG;
+        bzero = -1.0 * INT16_MIN;
+        datatype = TUSHORT;
+        break;
+
+    case PS_TYPE_S16:
+        bitpix = SHORT_IMG;
+        datatype = TSHORT;
+        break;
+
+    case PS_TYPE_U32:
+        bitpix = LONG_IMG;
+        bzero = -1.0 * INT32_MIN;
+        datatype = TUINT;
+        break;
+
+    case PS_TYPE_S32:
+        bitpix = LONG_IMG;
+        datatype = TINT;
+        break;
+
+    case PS_TYPE_F32:
+        bitpix = FLOAT_IMG;
+        datatype = TFLOAT;
+        break;
+
+    case PS_TYPE_F64:
+        bitpix = DOUBLE_IMG;
+        datatype = TDOUBLE;
+        break;
+
+    case PS_DATA_STRING:
+        bitpix = BYTE_IMG;
+        datatype = TSTRING;
+        break;
+
+    case PS_DATA_BOOL:
+        bitpix = BYTE_IMG;
+        datatype = TLOGICAL;
+        break;
+
+    default: {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    _("Specified type, %s, is not supported."),
+                    typeStr);
+            return false;
+        }
+    }
+
+    // pass back the requested parameters  (NULL parameters are not set, of course).
+    if (bitPix != NULL) {
+        *bitPix = bitpix;
+    }
+
+    if (dataType != NULL) {
+        *dataType = datatype;
+    }
+
+    if (bZero != NULL) {
+        *bZero = bzero;
+    }
+
+    return true;
+}
+
+
+psFitsCompressionType psFitsCompressionTypeFromString(const char *string)
+{
+    if (!string || strlen(string) == 0) {
+        psWarning("Unable to identify compression type --- none set.");
+        return PS_FITS_COMPRESS_NONE;
+    }
+
+    if (strcmp(string, "NONE") == 0) return PS_FITS_COMPRESS_NONE;
+    if (strcmp(string, "GZIP") == 0) return PS_FITS_COMPRESS_GZIP;
+    if (strcmp(string, "RICE") == 0) return PS_FITS_COMPRESS_RICE;
+    if (strcmp(string, "HCOMPRESS") == 0) return PS_FITS_COMPRESS_HCOMPRESS;
+    if (strcmp(string, "PLIO") == 0) return PS_FITS_COMPRESS_PLIO;
+
+    psWarning("Unable to identify compression type (%s) --- none set.", string);
+    return PS_FITS_COMPRESS_NONE;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFits.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFits.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFits.h	(revision 22158)
@@ -0,0 +1,341 @@
+/* @file  psFits.h
+ * @brief Contains Fits I/O routines
+ *
+ * @author Robert DeSonia, MHPCC
+ *
+ * @version $Revision: 1.36 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-01-23 03:08:03 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_FITS_H
+#define PS_FITS_H
+
+/// @addtogroup FileIO Input/Output
+/// @{
+
+#include <fitsio.h>
+#include "psType.h"
+#include "psArray.h"
+#include "psVector.h"
+#include "psMetadata.h"
+#include "psImage.h"
+#include "psFitsFloat.h"
+
+#include "psErrorCodes.h"
+
+/// FITS HDU type.
+typedef enum {
+    PS_FITS_TYPE_NONE = -1,            ///< Unknown HDU type
+    PS_FITS_TYPE_IMAGE = IMAGE_HDU,    ///< Image HDU type
+    PS_FITS_TYPE_BINARY_TABLE = BINARY_TBL, ///< Binary table HDU type
+    PS_FITS_TYPE_ASCII_TABLE = ASCII_TBL,   ///< ASCII table HDU type
+    PS_FITS_TYPE_ANY = ANY_HDU         ///< Any HDU type
+} psFitsType;
+
+/// FITS compression type
+typedef enum {
+    PS_FITS_COMPRESS_NONE = 0,          ///< No compression
+    PS_FITS_COMPRESS_GZIP,              ///< GZIP compression (of the pixels only)
+    PS_FITS_COMPRESS_RICE,              ///< RICE compression (of the pixels only)
+    PS_FITS_COMPRESS_HCOMPRESS,         ///< HCOMPRESS compression (of the pixels only)
+    PS_FITS_COMPRESS_PLIO               ///< PLIO compression (of the pixels only; appropriate for masks)
+} psFitsCompressionType;
+
+/// FITS scaling method: how to set BSCALE and BZERO
+typedef enum {
+    PS_FITS_SCALE_NONE,                 ///< No auto-scaling to be applied (BSCALE = 1, BZERO = 0)
+    PS_FITS_SCALE_RANGE,                ///< Auto-scale to preserve dynamic range
+    PS_FITS_SCALE_STDEV_POSITIVE,       ///< Auto-scale to sample stdev, place mean at lower limit
+    PS_FITS_SCALE_STDEV_NEGATIVE,       ///< Auto-scale to sample stdev, place mean at upper limit
+    PS_FITS_SCALE_STDEV_BOTH,           ///< Auto-scale to sample stdev, place mean at middle
+    PS_FITS_SCALE_MANUAL                ///< Manual scaling (use specified BSCALE and BZERO)
+} psFitsScaling;
+
+/// Options for FITS I/O
+typedef struct {
+    char *extword;                      ///< user-specified word to name extensions (NULL implies EXTNAME)
+    struct {
+        bool compression;               ///< Compression convention: handling of compressed images
+        bool psBitpix;                  ///< Custom floating-point image
+    } conventions;                      ///< Conventions to honour
+    // The following options are particular to writing images; they needn't be set for anything else.
+    psFitsFloat floatType;              ///< Desired custom floating-point for output images
+    int bitpix;                         ///< Desired BITPIX for output images; 0 to use as provided
+    psFitsScaling scaling;              ///< Scaling scheme to use when quantising floating-point values
+    bool fuzz;                          ///< Fuzz the values when quantising floating-point values?
+    double bscale, bzero;               ///< Manually specified BSCALE and BZERO (for SCALE_MANUAL)
+    double mean, stdev;                 ///< Mean and standard deviation of image
+    int stdevBits;                      ///< Number of bits to sample a standard deviation (for SCALE_STDEV_*)
+    float stdevNum;                     ///< Number of standard deviations to pad off the edge
+} psFitsOptions;
+
+
+/// FITS file
+typedef struct {
+    fitsfile* fd;                       ///< the CFITSIO fits files handle.
+    bool writable;                      ///< Is the file writable?
+    psFitsOptions *options;             ///< Options for FITS I/O, or NULL
+} psFits;
+
+
+/** FITS compression settings. */
+typedef struct {
+    psFitsCompressionType type;         ///< type of compression
+    psVector *tilesize;                 ///< vector defining compression tile size
+    int noisebits;                      ///< noise bits
+    int scale;                          ///< hcompress scale
+    int smooth;                         ///< hcompress smothing
+} psFitsCompression;
+
+/** Opens a FITS file and allocates the associated psFits object.
+ *
+ *  @return psFits*    new psFits object for the FITS files specified or
+ *                     NULL if the open of the FITS file failed
+ */
+psFits* psFitsOpen(
+    const char* filename,              ///< the FITS file name
+    const char* mode
+    /**< File open mode. Could be one of the following:
+     *       'r' (read only),
+     *       'r+' (read & write),
+     *       'rw' (same as 'r+'), or
+     *       'w' (create new file for writing)
+     */
+);
+
+
+/// Generate an error including the cfitsio error string
+#ifdef DOXYGEN
+psErrorCode psFitsError(
+    int status,                         ///< cfitsio status value
+    bool new,                           ///< new error?
+    const char *errorMsg,               ///< printf-style format of header line
+    ...                                 ///< any parameters required in format
+    );
+#else // ifdef DOXYGEN
+psErrorCode p_psFitsError(
+    const char* filename,               ///< file name
+    unsigned int lineno,                ///< line number in file
+    const char* func,                   ///< function name
+    int status,                         ///< cfitsio status value
+    bool new,                           ///< new error?
+    const char *errorMsg,               ///< printf-style format of header line
+    ...                                 ///< any parameters required in format
+    ) PS_ATTR_FORMAT(printf, 6, 7);
+#ifndef SWIG
+#define psFitsError(status,new,...) \
+      p_psFitsError(__FILE__,__LINE__,__func__,status,new,__VA_ARGS__)
+#endif // ifndef SWIG
+#endif // ifdef DOXYGEN
+
+
+/** Creates a new FITS options struct
+ *
+ *  @return psFitsOptions or NULL on failure
+ */
+psFitsCompression* psFitsCompressionAlloc(
+    psFitsCompressionType type,         ///< type of compression
+    psVector *tilesize,                 ///< vector defining compression tile size
+    int noisebits,                      ///< noise bits
+    int scale,                          ///< hcompress scale
+    int smooth                          ///< hcompress smothing
+);
+
+/// Return the FITS compression type specified by a string
+psFitsCompressionType psFitsCompressionTypeFromString(
+    const char *string                  ///< String with compression type
+    );
+
+/** Closes a FITS file.
+ *
+ *  @return bool      TRUE if FITS file was successfully closed, otherwise FALSE
+ */
+bool psFitsClose(
+    psFits* fits                       ///< psFits object to close
+);
+
+/// Allocator for options
+psFitsOptions *psFitsOptionsAlloc(void);
+
+/** Enables/configures FITS compression.
+ *
+ * Note that HCOMPRESS compression is not presently supported.
+ *
+ *  @return bool      TRUE if successfully configured, otherwise FALSE
+ */
+bool psFitsSetCompression(
+    psFits* fits,                       ///< psFits object for which to set compression
+    psFitsCompressionType type,         ///< type of compression
+    psVector *tilesize,                 ///< vector defining compression tile size
+    int noisebits,                      ///< noise bits
+    int scale,                          ///< hcompress scale
+    int smooth                          ///< hcompress smothing
+);
+
+/// Get the compression options for a file handle
+psFitsCompression *psFitsCompressionGet(
+    psFits* fits                        ///< psFits object for which to get compression
+);
+
+/// Get the compression type for a file handle
+psFitsCompressionType psFitsCompressionGetType(
+    psFits* fits                        ///< psFits object for which to get compression type
+    );
+
+/** Sets FITS write options
+ *
+ *  @return bool      TRUE if successfully configured, otherwise FALSE
+ */
+bool psFitsCompressionApply(
+    psFits* fits,                       ///< psFits object for which to set compression
+    psFitsCompression *compress         ///< options object
+);
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr
+ *  datatype.
+ *
+ *  @return bool:       True if the pointer matches a psFits structure, false
+ *                      otherwise.
+ */
+bool psMemCheckFits(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+// set the user-defined extension name;
+bool psFitsSetExtnameWord (psFits *fits, const char *extword);
+
+// move to the first HDU where extword == extname.  this is equivalent to fits_movnam_hdu() for
+// a user-defined word in place of EXTNAME
+bool p_psFitsMoveExtName_UserKey(const psFits *fits,
+                                 const char *extname,
+                                 const char *extword);
+
+/** Moves the FITS HDU to the specified extension name.
+ *
+ *  @return bool        TRUE if the extension name was found and move was
+ *                      successful, otherwise FALSE
+ */
+bool psFitsMoveExtName(
+    const psFits* fits,                ///< the psFits object to move
+    const char* extname                ///< the extension name
+);
+
+/** Moves the FITS HDU to the specified extension number
+ *
+ *  @return bool        TRUE if the extension number was found and move was
+ *                      successful, otherwise FALSE
+ */
+bool psFitsMoveExtNum(
+    const psFits* fits,                ///< the psFits object to move
+    int extnum,                        ///< the extension number to move to (zero is primary HDU)
+    bool relative                      ///< if true, extnum is a relative number to the current position
+);
+
+/** Moves the FITS HDU to the end of the file
+ *
+ *  @return bool        TRUE if the move was successful, otherwise FALSE
+*/
+bool psFitsMoveLast(
+    psFits* fits                       ///< the psFits object to move
+);
+
+/** Get the current extension number, where 0 is the primary HDU.
+ *
+ *  @return int        Current HDU number of the psFits file or < 0 if an error
+ *                     occurred.
+ */
+int psFitsGetExtNum(
+    const psFits* fits                 ///< the psFits object
+);
+
+/** Get the current extension name.
+ *
+ *  @return int        Current HDU name of the psFits file or NULL if an
+ *                     error occurred.
+ */
+psString psFitsGetExtName(
+    const psFits* fits                 ///< the psFits object
+);
+
+/** Set the current extension's name
+ *
+ *  @return bool       TRUE if the extension was successfully set, otherwise FALSE.
+ */
+bool psFitsSetExtName(
+    psFits* fits,                      ///< the psFits object
+    const char* name                   ///< the extension name
+);
+
+/** Get the total number of HDUs in the FITS file.
+ *
+ *  @return int        The total number of HDUs in the FITS file or < 0 if an
+ *                     error occurred.
+ */
+int psFitsGetSize(
+    const psFits* fits                 ///< the psFits object
+);
+
+/** Remove the an HDU as specified by number
+ *
+ *  @return bool        TRUE if the specified HDU was removed, otherwise FALSE
+ */
+bool psFitsDeleteExtNum(
+    psFits* fits,                      ///< the psFits object
+    int extnum,                        ///< the extension number to delete (zero is primary HDU)
+    bool relative                      ///< if true, extnum is a relative number to the current position
+);
+
+/** Remove the an HDU as specified by extension name
+ *
+ *  @return bool        TRUE if the specified HDU was removed, otherwise FALSE
+ */
+bool psFitsDeleteExtName(
+    psFits* fits,                      ///< the psFits object
+    const char* extname                ///< the extension name to delete
+);
+
+/** Get the extension type of the current HDU.
+ *
+ *  @return psFitsType The type of the current HDU.  If PS_FITS_TYPE_UNKNOWN,
+ *                     the type could not be determined.
+ */
+psFitsType psFitsGetExtType(
+    const psFits* fits                 ///< the psFits object
+);
+
+/** Delete all extensions after the current position
+ *
+ *  @return bool        TRUE if the operation was successful, otherwise FALSE
+ */
+bool psFitsTruncate(
+    psFits* fits                       ///< the psFits object
+);
+
+// Return the psLib type, given a cfitsio data type
+psDataType p_psFitsTypeFromCfitsio(int datatype // cfitsio data type
+                                  );
+
+// Return the cfitsio data type, given a psLib type
+bool p_psFitsTypeToCfitsio(psDataType type, // psLib data type
+                           int* bitPix, // The corresponding BITPIX (returned)
+                           double* bZero, // The corresponding BZERO (returned)
+                           int* dataType// The corresponding cfitsio data type (returned)
+                          );
+
+#define PS_ASSERT_FITS_NON_NULL(NAME, RVAL) \
+if (!(NAME) || !(NAME)->fd) { \
+    psError(PS_ERR_UNEXPECTED_NULL, true, "Error: FITS file pointer %s is NULL", #NAME); \
+    return RVAL; \
+}
+
+#define PS_ASSERT_FITS_WRITABLE(NAME, RVAL) \
+if (!(NAME)->writable) { \
+    psError(PS_ERR_UNEXPECTED_NULL, true, "Error: FITS file %s not open for writing.", #NAME); \
+    return RVAL; \
+}
+
+/// @}
+#endif // #ifndef PS_FITS_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsFloat.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsFloat.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsFloat.c	(revision 22158)
@@ -0,0 +1,192 @@
+/*
+** Copyright (C) 2008 Institute for Astronomy, University of Hawaii
+**
+** This is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+**
+** The GNU C Library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with the GNU C Library; if not, write to the Free
+** Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+** 02111-1307 USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <assert.h>
+
+#include "psAbort.h"
+#include "psType.h"
+#include "psError.h"
+#include "psImage.h"
+#include "psFits.h"
+#include "psTrace.h"
+#include "psMemory.h"
+
+#include "psFitsFloat.h"
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Private functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// This definition of IEEE754 floating-point, with some modifications, is from the GNU C Library, ieee754.h
+// Copyright (C) 1992, 1995, 1996, 1999 Free Software Foundation, Inc.
+union float_ieee754 {
+    float f;                            // Floating point
+    struct {                            // IEEE 754 single-precision format
+#ifdef WORDS_BIGENDIAN
+        unsigned int negative:1;
+        unsigned int exponent:8;
+        unsigned int mantissa:23;
+#else
+        unsigned int mantissa:23;
+        unsigned int exponent:8;
+        unsigned int negative:1;
+#endif
+    } ieee;
+};
+#define BIAS_FLOAT_IEEE754         0x7f // Exponent bias for IEEE754
+// End definition from ieee754.h
+
+
+// 16-bit floating point
+union float_16_0 {
+    psS16 s16;                          // 16-bit integer version
+        struct {                        // Floating-point version
+        unsigned int negative:1;        // Sign bit
+        unsigned int exponent:5;        // Exponent bits
+        unsigned int mantissa:10;       // Mantissa bits
+    } f16;
+};
+#define BIAS_FLOAT_16_0              10 // Exponent bias for FLOAT_16_0
+
+
+static inline psS16 convertF32toFloat16_0(psF32 value)
+{
+    union float_ieee754 in;             // Input value
+    union float_16_0 out;               // Output value
+
+    // XXX What happens to NAN and INF?
+    in.f = value;
+    out.f16.negative = in.ieee.negative;
+    out.f16.exponent = in.ieee.exponent - BIAS_FLOAT_IEEE754 + BIAS_FLOAT_16_0;
+    out.f16.mantissa = in.ieee.mantissa >> 13;
+
+    return out.s16;
+}
+
+static inline psF32 convertF32fromFloat16_0(psS16 value)
+{
+    union float_16_0 in;                // Input value
+    union float_ieee754 out;            // Output value
+
+    in.s16 = value;
+    out.ieee.negative = in.f16.negative;
+    out.ieee.exponent = in.f16.exponent + BIAS_FLOAT_IEEE754 - BIAS_FLOAT_16_0;
+    out.ieee.mantissa = in.f16.mantissa << 13;
+
+    return out.f;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+psImage *psFitsFloatImageToDisk(const psImage *image, psFitsFloat type)
+{
+    PS_ASSERT_IMAGE_NON_NULL(image, NULL);
+    PS_ASSERT_IMAGE_TYPE(image, PS_TYPE_F32, NULL);
+
+    psImage *output = NULL;             // Output image, to return
+
+    switch (type) {
+      case PS_FITS_FLOAT_NONE:
+        // No conversion to be performed
+        return psMemIncrRefCounter((psImage*)image); // Casting away "const"
+      case PS_FITS_FLOAT_16_0:
+        output = psImageAlloc(image->numCols, image->numRows, PS_TYPE_S16); // Output image
+        for (int y = 0; y < image->numRows; y++) {
+            for (int x = 0; x < image->numCols; x++) {
+                output->data.S16[y][x] = convertF32toFloat16_0(image->data.F32[y][x]);
+            }
+        }
+        break;
+      default:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unrecognised custom floating-point type: %x", type);
+        return NULL;
+    }
+
+    return output;
+}
+
+
+psImage *psFitsFloatImageFromDisk(psImage *out, const psImage *in, psFitsFloat type)
+{
+    PS_ASSERT_IMAGE_NON_NULL(in, NULL);
+
+    psElemType elem = psFitsFloatImageType(type); // Type for elements
+    if (elem == 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to recognise convention: %x", type);
+        return NULL;
+    }
+
+    int numCols = in->numCols, numRows = in->numRows; // Size of image
+
+    out = psImageRecycle(out, numCols, numRows, elem);
+
+    switch (type) {
+      case PS_FITS_FLOAT_16_0:
+        if (in->type.type != PS_TYPE_S16) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Convention claims to be FLOAT_16_0, but image type is not S16.");
+            return NULL;
+        }
+        psAssert(out->type.type == PS_TYPE_F32, "impossible");
+        for (int y = 0; y < numRows; y++) {
+            for (int x = 0; x < numCols; x++) {
+                out->data.F32[y][x] = convertF32fromFloat16_0(in->data.S16[y][x]);
+            }
+        }
+        return out;
+      case PS_FITS_FLOAT_NONE:
+      default:
+        psAbort("Should be unreachable");
+    }
+    return NULL;
+}
+
+psElemType psFitsFloatImageType(psFitsFloat type)
+{
+    switch (type) {
+      case PS_FITS_FLOAT_16_0:
+        return PS_TYPE_F32;
+      case PS_FITS_FLOAT_NONE:
+      default:
+        return 0;                       // Doesn't correspond to ANY type --- should flag a real error
+    }
+}
+
+
+psFitsFloat psFitsFloatTypeFromString(const char *string)
+{
+    PS_ASSERT_STRING_NON_EMPTY(string, PS_FITS_FLOAT_NONE);
+
+    if (strcmp(string, "FLOAT_16_0") == 0) {
+        return PS_FITS_FLOAT_16_0;
+    }
+
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+            "Unable to recognise custom floating-point convention name: %s", string);
+    return PS_FITS_FLOAT_NONE;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsFloat.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsFloat.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsFloat.h	(revision 22158)
@@ -0,0 +1,33 @@
+#ifndef PS_FITS_FLOAT_H
+#define PS_FITS_FLOAT_H
+
+#include <psFits.h>
+#include <psType.h>
+#include <psImage.h>
+
+/// Type of custom floating point
+typedef enum {
+    PS_FITS_FLOAT_NONE,                 ///< No conversion to be performed
+    PS_FITS_FLOAT_16_0,                 ///< Original F16 proposal: 1S 5E 10M
+} psFitsFloat;
+
+/// Convert an image to custom floating-point (the disk representation) in preparation for writing as FITS
+psImage *psFitsFloatImageToDisk(const psImage *image, ///< Image to convert
+                               psFitsFloat type ///< Custom floating point type
+    );
+
+/// Convert the custom floating-point image (the disk representation) to a normal floating-point image
+psImage *psFitsFloatImageFromDisk(psImage *out, ///< Output image, or NULL
+                                  const psImage *in, ///< Image to convert
+                                  psFitsFloat type ///< Custom floating point type
+    );
+
+/// Return the appropriate element type for a custom floating-point
+psElemType psFitsFloatImageType(psFitsFloat type ///< Custom floating-point type
+    );
+
+/// Return the custom floating-point type from a string description
+psFitsFloat psFitsFloatTypeFromString(const char *string ///< String with name of type
+    );
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsFloatFile.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsFloatFile.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsFloatFile.c	(revision 22158)
@@ -0,0 +1,65 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "psError.h"
+#include "psFits.h"
+#include "psFitsFloat.h"
+#include "psMemory.h"
+
+#include "psFitsFloatFile.h"
+
+bool psFitsFloatImageSet(const psFits *fits, psFitsFloat type)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_FITS_WRITABLE(fits, false);
+
+    char *convName;                     // Convention name
+
+    switch (type) {
+      case PS_FITS_FLOAT_NONE:
+        return true;
+      case PS_FITS_FLOAT_16_0:
+        convName = "FLOAT_16_0";
+        break;
+      default:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to recognise convention: %x", type);
+        return false;
+    }
+
+    int status = 0;                     // Status from cfitsio
+    fits_write_key_str(fits->fd, "PSBITPIX", convName, "Custom floating point convention name", &status);
+    if (psFitsError(status, true, "Could not write PSBITPIX header to file.")) {
+        return false;
+    }
+    return true;
+}
+
+
+psFitsFloat psFitsFloatImageCheck(const psFits *fits)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, PS_FITS_FLOAT_NONE);
+
+    psFitsOptions *options = fits->options; // FITS I/O options
+
+    if (!options || !options->conventions.psBitpix) {
+        return PS_FITS_FLOAT_NONE;
+    }
+
+    int status = 0;                     // Status of CFITSIO calls
+    char convName[FLEN_CARD];           // Convention name for custom floating-point
+    if (fits_read_key_str(fits->fd, "PSBITPIX", convName, NULL, &status) && status != KEY_NO_EXIST) {
+        psFitsError(status, true, "Unable to read header.");
+        return PS_FITS_FLOAT_NONE;
+    }
+
+    // XXX convName is static if (!convName || status == KEY_NO_EXIST) {
+    if (status == KEY_NO_EXIST) {
+        return PS_FITS_FLOAT_NONE;
+    }
+
+    return psFitsFloatTypeFromString(convName);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsFloatFile.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsFloatFile.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsFloatFile.h	(revision 22158)
@@ -0,0 +1,20 @@
+// This file exists to resolve the co-dependency problem of placing these function definitions in
+// psFitsFloat.h --- because they refer to psFits, and psFits refers to psFitsFloat, we would end up with a
+// co-dependency problem if these function declarations were to be placed in psFitsFloat.h.
+#ifndef PS_FITS_FLOAT_FILE_H
+#define PS_FITS_FLOAT_FILE_H
+
+#include <psFits.h>
+#include <psFitsFloat.h>
+
+/// Set a flag in the FITS header of the current extension that the image is a custom floating-point
+bool psFitsFloatImageSet(const psFits *fits,  ///< FITS file
+                         psFitsFloat type ///< Custom floating-point type
+    );
+
+/// Check if the current extension contains a custom floating-point, returning the appropriate type
+psFitsFloat psFitsFloatImageCheck(const psFits *fits ///< FITS file
+    );
+
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsHeader.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsHeader.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsHeader.c	(revision 22158)
@@ -0,0 +1,754 @@
+/** @file  psFitsHeader.c
+ *
+ *  @brief Contains Fits header I/O routines
+ *
+ *  @ingroup FileIO
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.46 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-04 03:18:06 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <unistd.h>
+#include <string.h>
+#include <strings.h>
+
+#include "psAbort.h"
+#include "psAssert.h"
+#include "psFits.h"
+#include "psError.h"
+
+#include "psImageStructManip.h"
+#include "psMemory.h"
+#include "psString.h"
+#include "psLogMsg.h"
+#include "psTrace.h"
+#include "psVector.h"
+
+#define MAX_STRING_LENGTH 256           // maximum length string for FITS routines
+#define NUM_EMPTY_KEYS 8                // Number of keywords before header is considered practically empty
+
+// list of FITS header keys to ignore; NULL-terminated
+static const char* ignoreFitsKeys[] = { "", NULL };
+
+// List of FITS header keys that may be duplicated; NULL-terminated
+static const char *duplicateFitsKeys[] = { "COMMENT", "HIERARCH", "HISTORY", NULL };
+
+// List of FITS header keys that are put in the comment by cfitsio; but we want them in the value.
+static const char *commentFitsKeys[] = { "COMMENT", "HISTORY", NULL };
+
+// List of FITS header keys not to write (handled by cfitsio); NULL-terminated
+static const char *noWriteFitsKeys[] = { "SIMPLE", "XTENSION", "BITPIX", "NAXIS", "EXTNAME", "BSCALE",
+                                         "BZERO", "TFIELDS", "PCOUNT", "GCOUNT", "PSBITPIX", NULL };
+
+// List of the start of FITS header keys not to write (handled by cfitsio); NULL-terminated
+static const char *noWriteFitsKeyStarts[] = { "NAXIS", "TTYPE", "TFORM", NULL };
+
+// List of compressed FITS header keys not to write (handled by cfitsio); NULL-terminated
+static const char *noWriteCompressedKeys[] = { "ZBITPIX", "ZIMAGE", "ZBITPIX", "ZCMPTYPE", NULL };
+
+// List of the start of FITS header keys not to write (handled by cfitsio); NULL-terminated
+static const char *noWriteCompressedKeyStarts[] = { "ZNAXIS", "ZTILE", "ZNAME", "ZVAL", NULL };
+
+// List of FITS header keys that may be present if the header is considered "empty"; NULL-terminated
+static const char *emptyKeys[] = { "SIMPLE", "BITPIX", "NAXIS", "EXTEND", "COMMENT", "CHECKSUM", "DATASUM",
+                                   NULL  };
+
+// How to translate between keywords
+typedef struct {
+    const char *from;                   // Translate from this keyword
+    const char *to;                     // Translate to this keyword
+} keywordTranslation;
+
+// Translation for compressed image headers           FROM        TO
+// The "From" and "To" are appropriate for reading.
+static keywordTranslation compressTranslation[] = { { "ZSIMPLE",  "SIMPLE" },
+                                                    { "ZTENSION", "XTENSION" },
+                                                    { "ZBITPIX",  "BITPIX" },
+                                                    { "ZNAXIS",   "NAXIS"  },
+                                                    { "ZNAXIS1",  "NAXIS1" },
+                                                    { "ZNAXIS2",  "NAXIS2" },
+                                                    { "ZNAXIS3",  "NAXIS3" },
+                                                    { "ZEXTEND",  "EXTEND" },
+                                                    { "ZBLOCKED", "BLOCKED"},
+                                                    //                                                    { "ZPCOUNT",  "PCOUNT" },
+                                                    //                                                    { "ZGCOUNT",  "GCOUNT" },
+                                                    { "ZHECKSUM", "CHECKSUM"},
+                                                    { "ZDATASUM", "DATASUM" },
+                                                    { NULL,       NULL } };
+
+
+// Compare a keyword with a list of keywords; return true if it's in the list
+static bool keywordInList(const char *keyword, // Keyword to check
+                          const char *list[] // List of keywords
+    )
+{
+    for (const char **check = list; *check; ++check) {
+        if (strcmp(keyword, *check) == 0) {
+            return true;
+        }
+    }
+    return false;
+}
+
+// Compare a keyword with a list of keyword beginnings; return true if the keyword starts with one of these
+static bool keywordStartsWith(const char *keyword, // Keyword to check
+                              const char *list[] // List of keyword beginnings
+                              )
+{
+    bool writeKey = true;   // Write this keyword?
+    for (int i = 0; list[i] && writeKey; i++) {
+        if (strncmp(keyword, list[i], strlen(list[i])) == 0) {
+            return true;
+        }
+    }
+    return false;
+}
+
+
+// Translate one keyword to another.
+// This is appropriate for reading
+static const char *keywordTranslate(const char *keyword, // Keyword to check
+                                    keywordTranslation translation[] // Translation list
+                                    )
+{
+    for (keywordTranslation *trans = translation; (*trans).from; ++trans) {
+        if (strcmp(keyword, (*trans).from) == 0) {
+            // Translate it
+            return (*trans).to;
+        } else if (strcmp(keyword, (*trans).to) == 0) {
+            // Ignore it completely --- something else will translate to it
+            return NULL;
+        }
+    }
+    // It translates to itself
+    return keyword;
+}
+
+// Translate back the other way.
+// This is appropriate for writing.
+static const char *keywordUntranslate(const char *keyword, // Keyword to check
+                                      keywordTranslation translation[] // Translation list
+    )
+{
+    for (keywordTranslation *trans = translation; (*trans).to; ++trans) {
+        if (strcmp(keyword, (*trans).to) == 0) {
+            // Translate it
+            return (*trans).from;
+        }
+    }
+    // It translates to itself
+    return keyword;
+}
+
+
+bool psFitsCheckSingleCompressedImagePHU(const psFits *fits, psMetadata *header)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    if (fits->options && !fits->options->conventions.compression) {
+        // User has turned off compression conventions; doesn't want any nasty surprises
+        return false;
+    }
+
+    if (psFitsGetExtNum(fits) != 0) {
+        // It's not the PHU, so it can't be the PHU for a single compressed image!
+        return false;
+    }
+
+    if (psFitsGetSize(fits) != 2) {
+        // No second extension, or multiple extensions
+        return false;
+    }
+
+    int numKeys;                        // Number of keywords in the header
+    int status = 0;                     // CFITSIO status
+    fits_get_hdrspace(fits->fd, &numKeys, 0, &status);
+    if (numKeys > NUM_EMPTY_KEYS) {
+        return false;
+    }
+
+    int bitpix, naxis;                  // Bits per pixel and number of axes
+    long naxes[MAX_COMPRESS_DIM];       // Dimensions
+    fits_get_img_param(fits->fd, MAX_COMPRESS_DIM, &bitpix, &naxis, naxes, &status);
+    if (naxis != 0) {
+        return false;
+    }
+
+    if (!header) {
+        for (int i = 1; i <= numKeys; i++) {
+            // Just want to read the keyword names, without parsing the values and stuffing into a metadata
+            char keyName[MAX_STRING_LENGTH];// Keyword name
+            char keyValue[MAX_STRING_LENGTH]; // Corresponding value
+            char keyComment[MAX_STRING_LENGTH]; // Corresponding comment
+            fits_read_keyn(fits->fd, i, keyName, keyValue, keyComment, &status);
+            if (!keywordInList(keyName, emptyKeys)) {
+                return false;
+            }
+        }
+    } else {
+        psMetadataIterator *iter = psMetadataIteratorAlloc(header, PS_LIST_HEAD, NULL); // Iterator
+        psMetadataItem *item;           // Item from iteration
+        while ((item = psMetadataGetAndIncrement(iter))) {
+            if (!keywordInList(item->name, emptyKeys)) {
+                psFree(iter);
+                return false;
+            }
+        }
+        psFree(iter);
+    }
+
+    if (!psFitsMoveExtNum(fits, 1, false)) {
+        psWarning("Unable to examine first extension as suspect compressed image.");
+        return false;
+    }
+
+    if (fits_is_compressed_image(fits->fd, &status)) {
+        return true;
+    }
+
+    // It's not a single compressed image PHU --- move back to the PHU for the user
+    if (!psFitsMoveExtNum(fits, 0, false)) {
+        psWarning("Unable to examine first extension as suspect compressed image.");
+        return false;
+    }
+
+    return false;
+}
+
+char *p_psFitsHeaderParseString(char *string)
+{
+    if (!string || strlen(string) == 0) {
+        return string;
+    }
+
+    char *fixed = string;       // Fixed version of the string
+    // remove the single-quotes at front/end
+    if (fixed[0] == '\'' && fixed[strlen(string)-1] == '\'') {
+        string[strlen(string)-1] = '\0'; // Remove the trailing quote
+        fixed += 1; // Advance past the leading quote
+    }
+    // Remove trailing spaces, which are not significant, according to the FITS standard
+    // http://archive.stsci.edu/fits/fits_standard/node31.html
+    char *lastSpace = NULL; // The last space in the string
+    while (strlen(fixed) > 0 && (lastSpace = strrchr(fixed, ' ')) && lastSpace[1] == '\0') {
+        // This is a trailing space, not a leading space.
+        lastSpace[0] = '\0'; // Truncate the string here
+    }
+
+    return fixed;
+}
+
+// Read the header
+static psMetadata *readHeader(const psFits *fits // FITS file from which to read header
+                              )
+{
+    psAssert(fits, "impossible");
+
+    psMetadata *header = psMetadataAlloc(); // Header, to return
+
+    // Get number of key names
+    int numKeys = 0;                    // Number of keywords
+    int keyNum = 0;                     // Current key number
+    int status = 0;                     // Status of cfitsio calls
+    fits_get_hdrpos(fits->fd, &numKeys, &keyNum, &status);
+
+    bool compressed = false;            // Is this a compressed image?
+    if ((!fits->options || fits->options->conventions.compression) &&
+        fits_is_compressed_image(fits->fd, &status)) {
+        compressed = true;
+    }
+
+    // Get each key name. Keywords start at one.
+    for (int i = 1; i <= numKeys; i++) {
+        char keyName[MAX_STRING_LENGTH];// Keyword name
+        char keyValue[MAX_STRING_LENGTH]; // Corresponding value
+        char keyComment[MAX_STRING_LENGTH]; // Corresponding comment
+        fits_read_keyn(fits->fd, i, keyName, keyValue, keyComment, &status);
+
+        // Check to see if the keyword should be ignored
+        if (keywordInList(keyName, ignoreFitsKeys)) {
+            // We're done here; skip to the next key
+            continue;
+        }
+
+        const char *keyNameTrans = keyName;   // Translated name of keyword
+        if (compressed) {
+            keyNameTrans = keywordTranslate(keyName, compressTranslation);
+            if (!keyNameTrans) {
+                // It's to be ignored (it will be replaced by something else)
+                continue;
+            }
+        }
+
+        // Check to see if the keyword should be duplicated
+        int dupFlag = 0;                // Duplicate flag
+        if (keywordInList(keyName, duplicateFitsKeys)) {
+            dupFlag = PS_META_DUPLICATE_OK;
+        }
+
+        bool success;                   // Was the add to the metadata successful?
+
+        // Certain keywords (COMMENT and HISTORY) are put in the comment rather than value by cfitsio.
+        if (keywordInList(keyName, commentFitsKeys)) {
+            success = psMetadataAddStr(header, PS_LIST_TAIL, keyNameTrans, dupFlag, NULL, keyComment);
+        } else {
+            char keyType;                   // Type of key; from cfitsio
+            if (keyValue[0] != 0) { // blank values are not handled by fits_get_keytype
+                fits_get_keytype(keyValue, &keyType, &status);
+            } else {
+                keyType = 'C';
+            }
+            if (status != 0) {
+                break;
+            }
+
+            switch (keyType) {
+              case 'X': // bit
+              case 'B': // byte
+                success = psMetadataAddS8(header, PS_LIST_TAIL, keyNameTrans, dupFlag, keyComment,
+                                          atoi(keyValue));
+                break;
+              case 'I': // short int.
+                // This is the default type that cfitsio reports whenever it doesn't know what it is.
+                // Trap NAN, INF and -INF, which cfitsio doesn't handle.
+                if (strncasecmp(keyValue, "NAN", 3) == 0) {
+                    success = psMetadataAddF32(header, PS_LIST_TAIL, keyNameTrans, dupFlag, keyComment, NAN);
+                } else if (strncasecmp(keyValue, "INF", 3) == 0) {
+                    success = psMetadataAddF32(header, PS_LIST_TAIL, keyNameTrans, dupFlag, keyComment,
+                                               INFINITY);
+                } else if (strncasecmp(keyValue, "-INF", 4) == 0) {
+                    success = psMetadataAddF32(header, PS_LIST_TAIL, keyNameTrans, dupFlag, keyComment,
+                                               -INFINITY);
+                } else {
+                    success = psMetadataAddS32(header, PS_LIST_TAIL, keyNameTrans, dupFlag, keyComment,
+                                               atoi(keyValue));
+                }
+                break;
+              case 'J': // int.
+                success = psMetadataAddS32(header, PS_LIST_TAIL, keyNameTrans, dupFlag, keyComment,
+                                           atoi(keyValue));
+                break;
+              case 'U': // unsigned int.
+                success = psMetadataAddU32(header, PS_LIST_TAIL, keyNameTrans, dupFlag, keyComment,
+                                           atol(keyValue));
+                break;
+
+              case 'K': // long int. can't all fit in a psS32, put in psF64
+              case 'F':
+                success = psMetadataAddF64(header, PS_LIST_TAIL, keyNameTrans, dupFlag, keyComment,
+                                           atof(keyValue));
+                break;
+              case 'C': {
+                  char *keyValueFixed = p_psFitsHeaderParseString(keyValue); // Fixed version of the string
+
+                  // Need to trap NAN, INF and -INF written by psFitsWriteHeader: cfitsio won't write these,
+                  // so we write them as strings, and then have to trap them on read.
+                  if (strcasecmp(keyValueFixed, "NAN") == 0) {
+                      success = psMetadataAddF32(header, PS_LIST_TAIL, keyNameTrans, dupFlag, keyComment,
+                                                 NAN);
+                  } else if (strcasecmp(keyValueFixed, "INF") == 0) {
+                      success = psMetadataAddF32(header, PS_LIST_TAIL, keyNameTrans, dupFlag, keyComment,
+                                                 INFINITY);
+                  } else if (strcasecmp(keyValueFixed, "-INF") == 0) {
+                      success = psMetadataAddF32(header, PS_LIST_TAIL, keyNameTrans, dupFlag, keyComment,
+                                                 -INFINITY);
+                  } else if (compressed && strcmp(keyName, "EXTNAME") == 0 &&
+                             strcmp(keyValueFixed, "COMPRESSED_IMAGE") == 0) {
+                      // Ignore EXTNAME=COMPRESSED_IMAGE if compression convention is to be respected
+                      success = true;
+                  } else {
+                      success = psMetadataAddStr(header, PS_LIST_TAIL, keyNameTrans, dupFlag, keyComment,
+                                                 keyValueFixed);
+                  }
+                  break;
+              }
+              case 'L': {
+                  bool temp = (keyValue[0] == 'T') ? 1 : 0;
+                  success = psMetadataAddBool(header, PS_LIST_TAIL, keyNameTrans, dupFlag, keyComment, temp);
+                  break;
+              }
+              default:
+                psError(PS_ERR_IO, true, _("Specified FITS metadata type, %c, is not supported."), keyType);
+                psFree(header);
+                return NULL;
+            }
+        }
+
+        if (!success) {
+            psError(PS_ERR_UNKNOWN, false, _("Failed to add metadata item, %s --> %s."),
+                    keyName, keyNameTrans);
+            psFree(header);
+            return NULL;
+        }
+
+    }
+
+    if (status != 0) {
+        psFitsError(status, true, _("Failed to add metadata item."));
+        psFree(header);
+        return false;
+    }
+
+    return header;
+}
+
+
+psMetadata* psFitsReadHeader(psMetadata* out,
+                             const psFits* fits)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+
+    psMetadata *header = readHeader(fits); // Header
+    if (!header) {
+        return NULL;
+    }
+
+    // Explore the potential case that this is an empty PHU, and the first extension contains the sole image,
+    // which is compressed.
+    if (psFitsCheckSingleCompressedImagePHU(fits, header)) {
+        // This is really what we want, not the empty PHU
+        psTrace("psLib.fits", 1,
+                "This PHU should really be a compressed image --- getting that header instead.");
+        psFree(header);
+        header = readHeader(fits);
+        if (!header) {
+            return NULL;
+        }
+    }
+
+    if (!out) {
+        return header;
+    }
+
+    // Need to move header onto the nominated metadata
+    psMetadataIterator *iter = psMetadataIteratorAlloc(header, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *item;           // Item from iteration
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        // Need to look for MULTI, which won't be picked up using the iterator.
+        psMetadataItem *multiCheckItem = psMetadataLookup(header, item->name);
+        psAssert(multiCheckItem, "impossible");
+        unsigned int flag = 0;      // Flag to indicate MULTI; otherwise default action
+        if (multiCheckItem->type == PS_DATA_METADATA_MULTI) {
+            flag = PS_META_DUPLICATE_OK;
+        }
+        if (!psMetadataAddItem(out, item, PS_LIST_TAIL, flag)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to add header item %s to extant metadata.",
+                    item->name);
+            psFree(iter);
+            psFree(header);
+            return NULL;
+        }
+    }
+    psFree(iter);
+    psFree(header);
+    return out;
+}
+
+psMetadata* psFitsReadHeaderSet(psMetadata* out, const psFits* fits)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+
+    if (!out) {
+        out = psMetadataAlloc();
+    }
+
+    int size = psFitsGetSize(fits);
+
+    int origPosition = psFitsGetExtNum(fits);
+
+    for (int lcv=0; lcv < size; lcv++) {
+        psFitsMoveExtNum(fits, lcv, false);
+
+        char* name = NULL;
+        if (lcv == 0) {
+            name = psStringCopy("PHU");
+        } else {
+            name = psFitsGetExtName(fits);
+        }
+
+        psMetadata* header = psFitsReadHeader(NULL, fits);
+        if (name != NULL && header != NULL) {
+            psMetadataAddMetadata(out, PS_LIST_TAIL, name, 0, "FITS Header", header);
+        } else {
+            psWarning("Failed to read HDU#%d header data.",
+                      lcv);
+        }
+
+        psFree(name);
+        psFree(header);
+    }
+
+    // reposition to the original position
+    psFitsMoveExtNum(fits, origPosition, false);
+
+    return out;
+}
+
+static bool fitsWriteHeader(psFits *fits, // The FITS file handle
+                            const psMetadata *output, // Metadata that is to be output into the FITS file
+                            bool keyStarts // Write out the key starts?
+                           )
+{
+    int status = 0;                     // Status of cfitsio calls
+    bool simple = true;                 // If SIMPLE is T, then the file should conform to the FITS standard
+    psFitsCompressionType compress = psFitsCompressionGetType(fits); // Compression type
+    if (psFitsGetExtNum(fits) == 0) {
+        // We allow the user to write SIMPLE, but it must be boolean
+        psMetadataItem *simpleItem = psMetadataLookup(output, "SIMPLE"); // SIMPLE in the header
+        if (simpleItem) {
+            if (simpleItem->type != PS_DATA_BOOL) {
+                psError(PS_ERR_BAD_PARAMETER_TYPE, true, "SIMPLE in a FITS header must be of boolean type: "
+                        "not %x --- assuming FALSE.\n", simpleItem->type);
+                int value = false;          // Temporary holder for boolean
+                fits_update_key(fits->fd, TLOGICAL, "SIMPLE", &value,
+                                "File does not conform to FITS standard", &status);
+                simple = false;
+            } else if (!simpleItem->data.B) {
+                simple = false;
+                int value = false;      // Temporary holder for boolean
+                fits_update_key(fits->fd, TLOGICAL, "SIMPLE", &value,
+                                "File does not conform to FITS standard", &status);
+            }
+            // Uncompressed SIMPLE = T is taken care of by cfitsio.
+        }
+    }
+    if ((!fits->options || fits->options->conventions.compression) && compress != PS_FITS_COMPRESS_NONE) {
+        psMetadataItem *simpleItem = psMetadataLookup(output, "SIMPLE"); // SIMPLE in the header
+        if (simpleItem) {
+            if (simpleItem->type != PS_DATA_BOOL) {
+                psError(PS_ERR_BAD_PARAMETER_TYPE, true, "SIMPLE in a FITS header must be of boolean type: "
+                        "not %x --- assuming FALSE.\n", simpleItem->type);
+                simple = false;
+            } else {
+                simple = simpleItem->data.B;
+            }
+        }
+        //        int value = simple;             // Temporary holder for boolean
+        //        fits_update_key(fits->fd, TLOGICAL, "ZSIMPLE", &value,
+        //                        "Uncompressed file's conformance to FITS standard", &status);
+    }
+
+    // Traverse the metadata list and add each key.
+    psListIterator* iter = psListIteratorAlloc(output->list, PS_LIST_HEAD, true); // Iterator
+    psMetadataItem* item;               // Item from iteration
+    while ((item = psListGetAndIncrement(iter))) {
+        char *name = item->name;        // Keyword name to use when writing out
+        // Check to see if the item should be ignored
+        if (simple) {
+            // We ignore particular (required) keywords, because these are written by CFITSIO
+            // Furthermore, users tend to supply FITS headers that are wrong (e.g., after binning down the
+            // image, the NAXISn haven't been changed; or after converting to F32, the BITPIX hasn't been
+            // changed) so we'll take care of that for them.
+
+            // Also block out TTYPEn, NAXISn, etc --- keywords that start with a certain sequence.
+            // We want to do this when writing an image or table, since it guarantees that the NAXISn etc
+            // that go in are correct.  However, when we're writing a "blank" HDU (header only), we want
+            // to preserve NAXISn etc for reference, so we don't do this.
+
+            // Options for compression
+            if (compress != PS_FITS_COMPRESS_NONE &&
+                (!fits->options || fits->options->conventions.compression)) {
+                // Check to see if the keyword should be translated
+                name = (char*)keywordUntranslate(name, compressTranslation); // Casting away const for cfitsio
+
+                if (keywordInList(name, noWriteCompressedKeys) ||
+                    (keyStarts && keywordStartsWith(name, noWriteCompressedKeyStarts))) {
+                    continue;
+                }
+            }
+
+            if (keywordInList(name, noWriteFitsKeys) ||
+                (keyStarts && keywordStartsWith(name, noWriteFitsKeyStarts))) {
+                continue;
+            }
+        }
+
+        if (strcmp(name, "COMMENT") == 0) {
+            if (item->type != PS_DATA_STRING) {
+                psWarning("COMMENT header is not of type STRING (%x) --- ignored.", item->type);
+            } else {
+                fits_write_comment(fits->fd, item->data.str, &status);
+            }
+        } else if (strcmp(name,  "HISTORY") == 0) {
+            if (item->type != PS_DATA_STRING) {
+                psWarning("COMMENT header is not of type STRING (%x) --- ignored.", item->type);
+            } else {
+                fits_write_history(fits->fd, item->data.str, &status);
+            }
+        } else {
+            // A regular FITS header
+            switch (item->type) {
+            case PS_DATA_BOOL: {
+                    int value = item->data.B;
+                    fits_update_key(fits->fd, TLOGICAL, name, &value, item->comment, &status);
+                    break;
+                }
+            case PS_DATA_S8:
+                fits_update_key(fits->fd, TBYTE, name, &item->data.S8, item->comment, &status);
+                break;
+            case PS_DATA_S16:
+                fits_update_key(fits->fd, TSHORT, name, &item->data.S16, item->comment, &status);
+                break;
+            case PS_DATA_S32:
+                fits_update_key(fits->fd, TINT, name, &item->data.S32, item->comment, &status);
+                break;
+            case PS_DATA_U8: {
+                    unsigned short int temp = item->data.U8;
+                    fits_update_key(fits->fd, TUSHORT, name, &temp, item->comment, &status);
+                }
+                break;
+            case PS_DATA_U16:
+                fits_update_key(fits->fd, TUSHORT, name, &item->data.U16, item->comment, &status);
+                break;
+            case PS_DATA_U32:
+                fits_update_key(fits->fd, TUINT, name, &item->data.U32, item->comment, &status);
+                break;
+            case PS_DATA_F32: {
+                    int infCheck = 0;         // Result of isinf()
+                    if (isnan(item->data.F32)) {
+                        fits_update_key(fits->fd, TSTRING, name, "NaN", item->comment, &status);
+                    } else if ((infCheck = isinf(item->data.F32)) != 0) {
+                        if (infCheck == 1) {
+                            fits_update_key(fits->fd, TSTRING, name, "Inf", item->comment, &status);
+                        } else {
+                            fits_update_key(fits->fd, TSTRING, name, "-Inf", item->comment, &status);
+                        }
+                    } else {
+                        fits_update_key(fits->fd, TFLOAT, name, &item->data.F32, item->comment,
+                                        &status);
+                    }
+                    break;
+                }
+            case PS_DATA_F64: {
+                    int infCheck = 0;         // Result of isinf()
+                    if (isnan(item->data.F64)) {
+                        fits_update_key(fits->fd, TSTRING, name, "NaN", item->comment, &status);
+                    } else if ((infCheck = isinf(item->data.F64)) != 0) {
+                        if (infCheck == 1) {
+                            fits_update_key(fits->fd, TSTRING, name, "Inf", item->comment, &status);
+                        } else {
+                            fits_update_key(fits->fd, TSTRING, name, "-Inf", item->comment, &status);
+                        }
+                    } else {
+                        fits_update_key(fits->fd, TDOUBLE, name, &item->data.F64, item->comment,
+                                        &status);
+                    }
+                    break;
+                }
+            case PS_DATA_STRING:
+                fits_update_key(fits->fd, TSTRING, name, item->data.V, item->comment, &status);
+                break;
+            default:  // all other META types are ignored
+                psLogMsg(__func__, PS_LOG_WARN, "Attempt to write metadata type %x to FITS header ignored.\n",
+                         item->type);
+                break;
+            }
+        }
+
+        if (status != 0) {
+            char fitsErr[MAX_STRING_LENGTH];
+            (void)fits_get_errstatus(status, fitsErr);
+            psError(PS_ERR_IO, true, _("Could not write data to file. CFITSIO Error: %s"), fitsErr);
+            return false;
+        }
+    }
+
+    psFree(iter);
+
+    return true;
+}
+
+bool psFitsWriteHeader(psFits *fits,
+                       const psMetadata *output
+                      )
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_FITS_WRITABLE(fits, false);
+    PS_ASSERT_METADATA_NON_NULL(output, false);
+
+    return fitsWriteHeader(fits, output, true);
+}
+
+bool psFitsWriteBlank(psFits* fits,
+                      const psMetadata* output,
+                      const char *extname
+                     )
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_FITS_WRITABLE(fits, false);
+
+    // We allow output == NULL in order to write a minimal header.
+
+    // Create a dummy image HDU for the primary HDU
+    int status = 0;                 // Status of cfitsio
+
+    psFitsMoveLast(fits);
+
+    int hdus = psFitsGetSize(fits);     // Number of HDUs in file
+    if (hdus == 0) {
+        // We're creating the first image
+        fits_create_img(fits->fd, 16, 0, NULL, &status);
+    } else {
+        // Insert after the current position
+        fits_insert_img(fits->fd, 16, 0, NULL, &status);
+    }
+
+    if (status) {
+        char fitsErr[MAX_STRING_LENGTH];
+        (void)fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_IO, true, "Unable to create blank header.\n%s\n", fitsErr);
+        return false;
+    }
+
+    if (output && !fitsWriteHeader(fits, output, false)) {
+        psError(PS_ERR_IO, false, "Unable to write FITS header.\n");
+        return false;
+    }
+
+    if (extname && strlen(extname)) {
+        psFitsSetExtName(fits, extname);
+    }
+
+    char buffer[10];
+    fits_write_img(fits->fd, TSHORT, 1, 0, buffer, &status);
+
+    return true;
+}
+
+bool psFitsHeaderValidate(psMetadata *header)
+{
+    PS_ASSERT_METADATA_NON_NULL(header, false);
+
+    // Traverse the metadata list and inspect at each key
+    psListIterator* iter = psListIteratorAlloc(header->list, PS_LIST_HEAD, true); // Iterator
+    psMetadataItem* item;               // Item from iteration
+    bool valid = true;                  // Are all items valid?
+    while ((item = psListGetAndIncrement(iter))) {
+        if (item->type > PS_DATA_STRING) { // i.e., a non-primitive type
+            valid = false;
+        }
+
+        if (strlen(item->name) > 8) {
+            item->name[8] = '\0'; // truncate to 8 characters
+        }
+
+        fits_uppercase(item->name); // make uppercase
+
+        // now, let's see if CFITSIO thinks this is a good keyword...
+        int status = 0;                 // Status from cfitsio calls
+        if (fits_test_keyword(item->name,&status) != 0) {
+            valid = false;
+        }
+    }
+    psFree(iter);
+
+    return valid;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsHeader.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsHeader.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsHeader.h	(revision 22158)
@@ -0,0 +1,87 @@
+/* @file  psFitsHeader.h
+ * @brief Contains Fits header I/O routines
+ *
+ * @author Robert DeSonia, MHPCC
+ *
+ * @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-10-03 21:27:21 $
+ *
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_FITSHEADER_H
+#define PS_FITSHEADER_H
+
+/// @addtogroup FileIO Input/Output
+/// @{
+
+#include "psFits.h"
+#include "psMetadata.h"
+
+
+/// Determine whether the current HDU is an empty PHU with a single compressed image following.
+///
+/// In that case, what should be treated as an image PHU is technically an empty PHU with a binary table
+/// extension.  We test the current position, number of extensions, the FITS headers and presence of a
+/// following compressed image to determine if this is the case.  If so, the FITS file pointer is left
+/// pointing at the compressed image.
+bool psFitsCheckSingleCompressedImagePHU(const psFits *fits, ///< FITS file pointer
+                                         const psMetadata *header ///< Header, or NULL
+    );
+
+/// Parse a string read from the FITS header.
+
+/// Removes the quotes, and any trailing spaces.  NOTE: the returned string is NOT on the psLib memory system
+/// --- it's simply a hacked version of the input string.  Note also that the input string is MODIFIED.
+char *p_psFitsHeaderParseString(char *string ///< String to parse
+    );
+
+/** Reads the header of the current HDU.
+ *
+ *  @return psMetadata*   the header data
+ */
+psMetadata* psFitsReadHeader(
+    psMetadata* out,
+    ///< The psMetadata to add the header data.  If null, a new psMetadata is created.
+    const psFits* fits                 ///< the psFits object
+);
+
+/** Reads the header of all HDUs.  The current HDU is not changed.
+ *
+ *  @return psMetadata*      the header data set as a number of metadata entries
+ */
+psMetadata* psFitsReadHeaderSet(
+    psMetadata* out,                         ///< output metadata or NULL if new psMetadata is to be created.
+    const psFits* fits                       ///< the psFits object
+);
+
+/** Writes the values of the metadata to the current HDU header.
+ *  Doesn't check if the header has to be created.
+ *
+ * @return bool         if TRUE, the write was successful, otherwise FALSE.
+ */
+bool psFitsWriteHeader(
+    psFits* fits,                       ///< the psFits object
+    const psMetadata* output            ///< the psMetadata data in which to write
+);
+
+/** Writes a "blank" --- a header only, with no image or table.
+ *
+ *  @return bool        if TRUE, the write was successful, otherwise FALSE.
+ */
+bool psFitsWriteBlank(
+    psFits* fits,                       ///< the psFits object
+    const psMetadata* output,           ///< the psMetadata data in which to write
+    const char *extname
+);
+
+/** psFitsHeaderValidate validates the supplied header so that it is in
+ *  compliance to the FITS standard for header keyword names and types.
+ *
+ *  @return bool        TRUE if the resulting header conforms to the FITS
+ *                      standard, otherwise FALSE
+ */
+bool psFitsHeaderValidate(psMetadata *header);
+
+/// @}
+#endif // #ifndef PS_FITS_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsImage.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsImage.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsImage.c	(revision 22158)
@@ -0,0 +1,947 @@
+/** @file  psFitsImage.c
+ *
+ *  @brief Contains Fits I/O routines
+ *
+ *  @ingroup FileIO
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.36 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-17 03:34:22 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+#include <assert.h>
+#include <string.h>
+
+#include "psAbort.h"
+#include "psType.h"
+#include "psAssert.h"
+#include "psError.h"
+#include "psString.h"
+#include "psLogMsg.h"
+#include "psTrace.h"
+#include "psVector.h"
+#include "psRandom.h"
+#include "psImageStructManip.h"
+
+#include "psFits.h"
+#include "psFitsFloat.h"
+#include "psFitsFloatFile.h"
+#include "psFitsHeader.h"
+#include "psFitsScale.h"
+
+#include "psMemory.h"
+
+#include "psFitsImage.h"
+
+#define MAX_STRING_LENGTH 256           // maximum length string for FITS routines
+
+// Information required to read a FITS file
+typedef struct {
+    int nAxis;                          // Number of axes
+    int bitPix;                         // Bits per pixel
+    long nAxes[3];                      // Length of each axis
+    long firstPixel[3];                 // lower-left corner of image subset
+    long lastPixel[3];                  // upper-right corner of image subset
+    long increment[3];                  // increment for image subset
+    int fitsDatatype;                   // cfitsio data type
+    int psDatatype;                     // psLib data type
+} p_psFitsReadInfo;
+
+// Read the vital statistics of this FITS image, in preparation for reading the image
+static p_psFitsReadInfo *p_psFitsReadInfoAlloc(
+    const psFits *fits, // The FITS file handle
+    psRegion region, // Region to read
+    int z // z-plane to read in cube
+    )
+{
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(z, NULL);
+
+    p_psFitsReadInfo *info = psAlloc(sizeof(p_psFitsReadInfo));
+    memset(info, 0, sizeof(p_psFitsReadInfo));
+
+    int status = 0;                     // CFITSIO status
+
+    // check to see if we even are positioned on an image HDU
+    int hduType;                        // Type of HDU
+    if (fits_get_hdu_type(fits->fd, &hduType, &status) != 0) {
+        psFitsError(status, true, "Could not determine the HDU type.");
+        goto bad;
+    }
+    if (hduType != IMAGE_HDU) {
+        psError(PS_ERR_IO, true, _("Current FITS HDU type must be an image."));
+        goto bad;
+    }
+
+    // Get the data type 'bitPix' from the FITS image
+    if (fits_get_img_equivtype(fits->fd, &info->bitPix, &status) != 0) {
+        psFitsError(status, true, "Could not determine image data type.");
+        goto bad;
+    }
+
+    /* Get the dimensions 'nAxis' from the FITS image */
+    if (fits_get_img_dim(fits->fd, &info->nAxis, &status) != 0) {
+        psFitsError(status, true, "Could not determine image dimensions.");
+        goto bad;
+    }
+
+    /* Validate the number of axis */
+    if ((info->nAxis < 2) || (info->nAxis > 3)) {
+        psError(PS_ERR_IO, true,
+                _("Image number of dimensions, %d, is not supported."), info->nAxis);
+        goto bad;
+    }
+
+    /* Get the Image size from the FITS file */
+    if (fits_get_img_size(fits->fd, info->nAxis, info->nAxes, &status) != 0) {
+        psFitsError(status, true, "Could not determine image size.");
+        goto bad;
+    }
+
+    info->firstPixel[0] = region.x0 + 1;
+    info->firstPixel[1] = region.y0 + 1;
+    info->firstPixel[2] = z + 1;
+
+    if (region.x1 > 0) {
+        info->lastPixel[0] = region.x1;
+    } else {
+        info->lastPixel[0] = info->nAxes[0] + region.x1; // n.b., region.x1 < 0
+    }
+    if (region.y1 > 0) {
+        info->lastPixel[1] = region.y1;
+    } else {
+        info->lastPixel[1] = info->nAxes[1] + region.y1; // n.b., region.y1 < 0
+    }
+    info->lastPixel[2] = z + 1;
+
+    info->increment[0] = 1;
+    info->increment[1] = 1;
+    info->increment[2] = 1;
+
+    // Check scale and zero
+    double bscale = 0.0, bzero = 0.0;    // Scale and zero point
+    if (fits_read_key_dbl(fits->fd, "BSCALE", &bscale, NULL, &status) && status != KEY_NO_EXIST) {
+        psFitsError(status, true, "Unable to read header.");
+        goto bad;
+    }
+    status = 0;
+    if (fits_read_key_dbl(fits->fd, "BZERO", &bzero, NULL, &status) && status != KEY_NO_EXIST) {
+        psFitsError(status, true, "Unable to read header.");
+        goto bad;
+    }
+    status = 0;
+
+    if ((bscale != 0.0 && bscale != 1.0) || bzero != (int)bzero) {
+        // It's a floating-point image that's been quantised
+        // cfitsio will apply the scale and zero point for us if we choose the correct data type
+        switch (info->bitPix) {
+          case BYTE_IMG:
+          case SBYTE_IMG:
+          case USHORT_IMG:
+          case SHORT_IMG:
+          case ULONG_IMG:
+          case LONG_IMG:
+          case FLOAT_IMG:
+            info->psDatatype = PS_TYPE_F32;
+            info->fitsDatatype = TFLOAT;
+            break;
+          case LONGLONG_IMG:
+          case DOUBLE_IMG:
+            info->psDatatype = PS_TYPE_F64;
+            info->fitsDatatype = TDOUBLE;
+            break;
+          default:
+            psError(PS_ERR_IO, true, _("FITS image type, BITPIX=%d, is not supported."), info->bitPix);
+            goto bad;
+        }
+    } else {
+        switch (info->bitPix) {
+          case BYTE_IMG:
+            info->psDatatype = PS_TYPE_U8;
+            info->fitsDatatype = TBYTE;
+            break;
+          case SBYTE_IMG:
+            info->psDatatype = PS_TYPE_S8;
+            info->fitsDatatype = TSBYTE;
+            break;
+          case USHORT_IMG:
+            info->psDatatype = PS_TYPE_U16;
+            info->fitsDatatype = TUSHORT;
+            break;
+          case SHORT_IMG:
+            info->psDatatype = PS_TYPE_S16;
+            info->fitsDatatype = TSHORT;
+            break;
+          case ULONG_IMG:
+            info->psDatatype = PS_TYPE_U32;
+            info->fitsDatatype = TUINT;
+            break;
+          case LONG_IMG:
+            info->psDatatype = PS_TYPE_S32;
+            info->fitsDatatype = TINT;
+            break;
+          case LONGLONG_IMG:
+            info->psDatatype = PS_TYPE_S64;
+            info->fitsDatatype = TLONGLONG;
+            break;
+          case FLOAT_IMG:
+            info->psDatatype = PS_TYPE_F32;
+            info->fitsDatatype = TFLOAT;
+            break;
+          case DOUBLE_IMG:
+            info->psDatatype = PS_TYPE_F64;
+            info->fitsDatatype = TDOUBLE;
+            break;
+          default:
+            psError(PS_ERR_IO, true, _("FITS image type, BITPIX=%d, is not supported."), info->bitPix);
+            goto bad;
+        }
+    }
+    return info;
+
+    // Common error cleanup
+bad:
+    psFree(info);
+    return NULL;
+}
+
+
+bool psFitsImageSize(int *numCols, int *numRows, psElemType *type, const psFits *fits, psRegion region)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+
+    if (psFitsCheckSingleCompressedImagePHU(fits, NULL)) {
+        // This is really what we want, not the empty PHU
+        psTrace("psLib.fits", 1,
+                "This PHU should really be a compressed image --- reading that image instead.");
+    }
+
+    p_psFitsReadInfo *info = p_psFitsReadInfoAlloc(fits, region, 0); // How big the region to read is
+
+    if (numCols) {
+        *numCols = info->lastPixel[0] - info->firstPixel[0] + 1;
+    }
+    if (numRows) {
+        *numRows = info->lastPixel[1] - info->firstPixel[1] + 1;
+    }
+    if (type) {
+        *type = info->psDatatype;
+    }
+
+    psFree(info);
+
+    return true;
+}
+
+
+// Convert an image to the desired BITPIX, i.e., the desired disk representation
+static psImage *imageToDiskRepresentation(double *bscale, // Scaling applied
+                                          double *bzero, // Zero point applied
+                                          long *blank, // Blank value (integer data)
+                                          psFitsFloat *floatType, // Type of custom floating-point
+                                          psFits *fits, // FITS file pointer
+                                          const psImage *image, // Current type
+                                          psRandom *rng, // Random number generator
+                                          bool newScaleZero // Determine a new BSCALE and BZERO?
+                                          )
+{
+    psAssert(bscale, "impossible");
+    psAssert(bzero, "impossible");
+    psAssert(floatType, "impossible");
+    psAssert(fits, "impossible");
+    psAssert(image, "impossible");
+
+    *bscale = 1.0;
+    *bzero = 0.0;
+    *floatType = PS_FITS_FLOAT_NONE;
+
+    psFitsOptions *options = fits->options;
+    if (!options) {
+        return psMemIncrRefCounter((psImage*)image); // Casting away const
+    }
+
+    // Custom floating-point
+    if (PS_IS_PSELEMTYPE_REAL(image->type.type) && options->conventions.psBitpix &&
+        options->floatType != PS_FITS_FLOAT_NONE) {
+        *floatType = options->floatType;
+        return psFitsFloatImageToDisk(image, options->floatType);
+    }
+
+    // Automatically select what we're given
+    if (options->bitpix == 0) {
+        return psMemIncrRefCounter((psImage*)image); // Casting away const
+    }
+
+    // Quantise floating-point images
+    if (PS_IS_PSELEMTYPE_REAL(image->type.type) && options->bitpix > 0) {
+        if (newScaleZero) {
+            // Choose an appropriate BSCALE and BZERO
+            if (!psFitsScaleDetermine(bscale, bzero, blank, image, fits)) {
+                // We can't have the write dying for this reason --- try to save it somehow!
+                psWarning("Unable to determine BSCALE and BZERO for image --- refusing to quantise.");
+                psErrorClear();
+                return psMemIncrRefCounter((psImage*)image);
+            }
+        } else {
+            // Don't want to muck with the current BSCALE and BZERO.  Get the current values and use those.
+            int status = 0;                 // Status of cfitsio
+            if (fits_read_key_dbl(fits->fd, "BSCALE", bscale, NULL, &status) && status != KEY_NO_EXIST) {
+                psFitsError(status, true, "Unable to read header.");
+                return NULL;
+            }
+            status = 0;
+            if (fits_read_key_dbl(fits->fd, "BZERO", bzero, NULL, &status) && status != KEY_NO_EXIST) {
+                psFitsError(status, true, "Unable to read header.");
+                return NULL;
+            }
+            status = 0;
+            if (*bscale == 0.0) {
+                psError(PS_ERR_IO, true,
+                        "Supposed to use old values of BSCALE and BZERO, but they don't exist.");
+                return NULL;
+            }
+        }
+
+        return psFitsScaleForDisk(image, fits, *bscale, *bzero, rng);
+    }
+
+    // Choose the appropriate output type, given the input type and desired bits per pixel
+#define CONVERT_TYPE_INT_CASE(OUTTYPE, INTYPE, BITPIX) \
+  case BITPIX: \
+    OUTTYPE = PS_IS_PSELEMTYPE_UNSIGNED(INTYPE) ? PS_TYPE_U##BITPIX : PS_TYPE_S##BITPIX; \
+    break;
+#define CONVERT_TYPE_FLOAT_CASE(OUTTYPE, BITPIX) \
+  case -BITPIX: /* Note the use of the negative sign */ \
+    OUTTYPE = PS_TYPE_F##BITPIX; \
+    break;
+
+    *bscale = 1.0;
+    *bzero = 0.0;
+    psElemType inType = image->type.type; // Type for input image
+    psElemType outType;                 // Type for output image
+    switch (options->bitpix) {
+        CONVERT_TYPE_INT_CASE(outType, inType, 8);
+        CONVERT_TYPE_INT_CASE(outType, inType, 16);
+        CONVERT_TYPE_INT_CASE(outType, inType, 32);
+        CONVERT_TYPE_INT_CASE(outType, inType, 64);
+        CONVERT_TYPE_FLOAT_CASE(outType, 32);
+        CONVERT_TYPE_FLOAT_CASE(outType, 64);
+      default:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Target bitpix (%d) is not one of 8,16,32,64",
+                options->bitpix);
+        return NULL;
+    }
+
+    if (outType == inType) {
+        return psMemIncrRefCounter((psImage*)image);
+    }
+
+    if (PSELEMTYPE_SIZEOF(inType) > PSELEMTYPE_SIZEOF(outType)) {
+        psWarning("Truncating image pixels to write to disk.");
+    }
+
+    return psImageCopy(NULL, image, outType);
+}
+
+
+// Read into an extant image of just the right size
+static bool fitsReadImage(psImage *output,   // Output image
+                          const psFits *fits, // FITS file handle
+                          p_psFitsReadInfo *info // Info on how to read
+                         )
+{
+    // n.b., this assumes contiguous image buffer
+    psAssert(output, "impossible");
+    psAssert(fits, "impossible");
+    psAssert(info, "impossible");
+    psAssert(output->numCols == info->lastPixel[0] - info->firstPixel[0] + 1, "impossible");
+    psAssert(output->numRows == info->lastPixel[1] - info->firstPixel[1] + 1, "impossible"); // Right size
+    psAssert(!output->parent, "impossible");            // No parents means the buffer is contiguous
+
+    void *nullValue = NULL;             // Null value for data
+    float nullFloat = NAN;              // Null value for floating point
+    double nullDouble = NAN;            // Null value for double
+    switch (info->psDatatype) {
+      case PS_TYPE_F32:
+        nullValue = &nullFloat;
+        break;
+      case PS_TYPE_F64:
+        nullValue = &nullDouble;
+        break;
+      case PS_TYPE_U8:
+      case PS_TYPE_U16:
+      case PS_TYPE_U32:
+      case PS_TYPE_U64:
+      case PS_TYPE_S8:
+      case PS_TYPE_S16:
+      case PS_TYPE_S32:
+      case PS_TYPE_S64:
+        // Can't mark bad pixels any further than what is in the FITS image
+        break;
+      default:
+        psAbort("Unknown type: %x", info->psDatatype);
+    }
+
+    int anynull = 0;                    // Are there any NULLs in the data?
+    int status = 0;                     // cfitsio status
+    if (fits_read_subset(fits->fd, info->fitsDatatype, info->firstPixel, info->lastPixel,
+                         info->increment, nullValue, output->data.V[0], &anynull, &status) != 0) {
+        psFitsError(status, true, "Reading FITS file failed.");
+        return false;
+    }
+
+    // No need to apply the BSCALE, BZERO because cfitsio does this for us
+
+    return true;
+}
+
+psImage* psFitsReadImage(const psFits *fits, // the psFits object
+                         psRegion region, // the region in the FITS image to read
+                         int z          // the z-plane in the FITS image cube to read
+                        )
+{
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(z, NULL);
+
+    if (psFitsCheckSingleCompressedImagePHU(fits, NULL)) {
+        // This is really what we want, not the empty PHU
+        psTrace("psLib.fits", 1,
+                "This PHU should really be a compressed image --- reading that image instead.");
+    }
+
+    p_psFitsReadInfo *info = p_psFitsReadInfoAlloc(fits, region, z);
+
+    // Size of image
+    int numCols = info->lastPixel[0] - info->firstPixel[0] + 1;
+    int numRows = info->lastPixel[1] - info->firstPixel[1] + 1;
+
+    psImage *inImage = psImageAlloc(numCols, numRows, info->psDatatype); // Image to read in
+
+    psFitsFloat floatType = psFitsFloatImageCheck(fits); // Type of custom floating-point
+    psImage *outImage = (floatType == PS_FITS_FLOAT_NONE ? psMemIncrRefCounter(inImage) :
+                         psImageAlloc(numCols, numRows, psFitsFloatImageType(floatType))); // Output image
+
+    if (!fitsReadImage(inImage, fits, info)) {
+        psFree(info);
+        psFree(inImage);
+        return NULL;
+    }
+    psFree(info);
+
+    if (floatType != PS_FITS_FLOAT_NONE) {
+        outImage = psFitsFloatImageFromDisk(outImage, inImage, floatType);
+    }
+    psFree(inImage);
+
+    return outImage;
+}
+
+psImage* psFitsReadImageBuffer(psImage *outImage, // Output image buffer
+                               const psFits *fits, // the psFits object
+                               psRegion region, // the region in the FITS image to read
+                               int z           // the z-plane in the FITS image cube to read
+                              )
+{
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(z, NULL);
+
+    if (outImage && outImage->parent) {
+        psError(PS_ERR_IO, true, "Unable to read into a buffer for a child image.\n");
+        return NULL;
+    }
+
+    if (psFitsCheckSingleCompressedImagePHU(fits, NULL)) {
+        // This is really what we want, not the empty PHU
+        psTrace("psLib.fits", 1,
+                "This PHU should really be a compressed image --- reading that image instead.");
+    }
+
+    p_psFitsReadInfo *info = p_psFitsReadInfoAlloc(fits, region, z);
+
+    // Size of image
+    int numCols = info->lastPixel[0] - info->firstPixel[0] + 1;
+    int numRows = info->lastPixel[1] - info->firstPixel[1] + 1;
+
+    psFitsFloat floatType = psFitsFloatImageCheck(fits); // Type of custom floating-point
+    psImage *inImage;                   // Image to read in
+    if (floatType == PS_FITS_FLOAT_NONE) {
+        inImage = psImageRecycle(outImage, numCols, numRows, info->psDatatype);
+        outImage = psMemIncrRefCounter(inImage);
+    } else {
+        inImage = psImageAlloc(numCols, numRows, info->psDatatype);
+        outImage = psImageRecycle(outImage, numCols, numRows, psFitsFloatImageType(floatType));
+    }
+
+    if (!fitsReadImage(inImage, fits, info)) {
+        psFree(info);
+        psFree(inImage);
+        psFree(outImage);
+        return NULL;
+    }
+    psFree(info);
+
+    if (floatType != PS_FITS_FLOAT_NONE) {
+        outImage = psFitsFloatImageFromDisk(outImage, inImage, floatType);
+    }
+    psFree(inImage);
+
+    return outImage;
+}
+
+bool psFitsWriteImage(psFits* fits,
+                      psMetadata* header,
+                      const psImage* input,
+                      int numZPlanes,
+                      const char* extname)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_FITS_WRITABLE(fits, false);
+    PS_ASSERT_IMAGE_NON_NULL(input, false);
+    // this is equivalent to insert after the last HDU
+
+    psFitsMoveLast(fits);
+    return psFitsInsertImage(fits,header,input,numZPlanes,extname,true);
+}
+
+bool psFitsInsertImage(psFits* fits, psMetadata* header, const psImage* image, int numZPlanes,
+                       const char* extname, bool after)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_FITS_WRITABLE(fits, false);
+    PS_ASSERT_IMAGE_NON_NULL(image, false);
+
+    int numCols = image->numCols;       // Number of columns for image
+    int numRows = image->numRows;       // Number of rows for image
+    int status = 0;                     // Status from cfitsio
+    bool success = true;
+    psFitsCompression *compress = NULL; // FITS compression parameters; to save state
+
+    double bscale = NAN, bzero = NAN;   // Scale and zero point to put in header
+    long blank = 0;                     // Blank (undefined) value for image
+    psFitsFloat floatType;              // Custom floating-point convention type
+    psImage *diskImage = imageToDiskRepresentation(&bscale, &bzero, &blank, &floatType, fits, image,
+                                                   NULL, true); // Image to write out
+    if (!diskImage) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to convert image to desired disk format.");
+        success = false;
+        goto INSERT_DONE;
+    }
+
+    bool useRequestedScale = true;
+    if (!isfinite(bscale) || !isfinite(bzero)) {
+        // Couldn't scale, so don't compress.  Save compression parameters for later
+        useRequestedScale = false;
+        compress = psFitsCompressionGet(fits);
+        if (!psFitsSetCompression(fits, PS_FITS_COMPRESS_NONE, NULL, 0, 0, 0)) {
+            psError(PS_ERR_IO, false, "Unable to unset compression.");
+            success = false;
+            goto INSERT_DONE;
+        }
+    }
+
+    // determine the FITS-equivalent parameters
+    int bitPix;                         // Bits per pixel
+    double cfitsioBzero = 0.0;          // Zero point for cfitsio to apply
+    int dataType;                       // cfitsio data type
+    if (!p_psFitsTypeToCfitsio(diskImage->type.type, &bitPix, &cfitsioBzero, &dataType)) {
+        success = false;
+        goto INSERT_DONE;
+    }
+    if (cfitsioBzero != 0.0) {
+        // p_psFitsTypeToCfitsio and imageToDiskRepresentation must not clash!
+        psAssert(bzero == 0.0 && bscale == 1.0, "impossible");
+        bscale = 1.0;
+        bzero = cfitsioBzero;
+    }
+
+    psFitsOptions *options = fits->options; // FITS I/O options
+    psAssert(!useRequestedScale || !options || bitPix == options->bitpix || options->bitpix == 0, "impossible");
+
+    int naxis = 3;                      // Number of axes
+    long naxes[3];                      // Length of each axis
+    naxes[0] = numCols;
+    naxes[1] = numRows;
+    naxes[2] = numZPlanes;
+
+    if (numZPlanes < 2) {
+        naxis = 2;
+    }
+
+    // Create the image HDU
+    int hdus = psFitsGetSize(fits);     // Number of HDUs in file
+    if (hdus == 0) {
+        // We're creating the first image
+        fits_create_img(fits->fd, bitPix, naxis, naxes, &status);
+    } else {
+        if (!after) {
+            if (psFitsGetExtNum(fits) == 0) {
+                // We're creating a replacement primary HDU.
+                // Set status to signal fits_insert_img to insert a new primary HDU
+                status = PREPEND_PRIMARY;
+            } else {
+                // Move back one to perform an insert after the previous HDU
+                psFitsMoveExtNum(fits, -1, true);
+            }
+        }
+        // Insert after the current position
+        fits_insert_img(fits->fd, bitPix, naxis, naxes, &status);
+    }
+    if (psFitsError(status, true, "Could not create image HDU.")) {
+        success = false;
+        goto INSERT_DONE;
+    }
+
+    // write the header, if any.
+    if (header && !psFitsWriteHeader(fits, header)) {
+        psError(PS_ERR_IO, false, "Unable to write FITS header.\n");
+        success = false;
+        goto INSERT_DONE;
+    }
+
+    // We only want cfitsio to do the scale and zero if the type conversion requires it (e.g., input type is
+    // an unsigned integer type).  In all other cases, we have already converted the image to use the
+    // appropriate scale and zero (because we want to apply a randomiser to the quantisation).
+    fits_set_bscale(fits->fd, 1.0, cfitsioBzero, &status);
+
+    if (isfinite(bzero) && isfinite(bscale) && (bscale != 0.0)) {
+        fits_write_key_dbl(fits->fd, "BZERO", bzero, 12,
+                           "Scaling: TRUE = BZERO + BSCALE * DISK", &status);
+        fits_write_key_dbl(fits->fd, "BSCALE", bscale, 12,
+                           "Scaling: TRUE = BZERO + BSCALE * DISK", &status);
+        if (psFitsError(status, true, "Could not write BSCALE/BZERO headers to file.")) {
+            success = false;
+            goto INSERT_DONE;
+        }
+    }
+
+    if (blank != 0) {
+        // Some quantisation has taken place --- record the blank ("magic") pixel value
+        char *keyword = (psFitsCompressionGetType(fits) != PS_FITS_COMPRESS_NONE &&
+                         (!fits->options || fits->options->conventions.compression)) ?
+            "ZBLANK" : "BLANK";         // Keyword for recording blank pixel value
+        fits_write_key_lng(fits->fd, keyword, blank, "Value for undefined pixels", &status);
+        fits_set_imgnull(fits->fd, blank, &status);
+        if (psFitsError(status, true, "Could not write BLANK header to file.")) {
+            success = false;
+            goto INSERT_DONE;
+        }
+    }
+
+    if (floatType != PS_FITS_FLOAT_NONE) {
+        psFitsFloatImageSet(fits, floatType);
+    }
+
+    if (extname && strlen(extname) > 0) {
+        psFitsSetExtName(fits, extname);
+    }
+
+    if (image->parent == NULL) {
+        // if no parent, assume that the image data is contiguous
+        fits_write_img(fits->fd, dataType, 1, numCols*numRows, diskImage->data.V[0], &status);
+    } else {
+        // image data may not be contiguous; write one row at a time
+        int firstPixel = 1;
+        for (int row = 0; row < numRows; row++) {
+            fits_write_img(fits->fd, dataType, firstPixel, numCols, diskImage->data.V[row], &status);
+            firstPixel += numCols;
+        }
+    }
+    if (psFitsError(status, true, "Could not write image to file.")) {
+        success = false;
+        goto INSERT_DONE;
+    }
+
+    // This forces a re-scan of the header to ensure everything's kosher.
+    // Without this, compressed HDUs have been written out with PCOUNT=0 and TFORM1 not correctly set.
+    ffrdef(fits->fd, &status);
+    if (psFitsError(status, true, "Could not re-scan HDU.")) {
+        success = false;
+        goto INSERT_DONE;
+    }
+
+
+ INSERT_DONE:
+    psFree(diskImage);
+    if (compress) {
+        // Restore compression state
+        psFitsCompressionApply(fits, compress);
+        psFree(compress);
+    }
+
+    return success;
+}
+
+bool psFitsUpdateImage(psFits* fits, const psImage* input, int x0, int y0, int z)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_FITS_WRITABLE(fits, false);
+    PS_ASSERT_IMAGE_NON_NULL(input, false);
+
+    int status = 0;
+
+    // check to see if we are positioned on an image HDU
+    int hduType;
+    if (fits_get_hdu_type(fits->fd, &hduType, &status) != 0) {
+        psFitsError(status, true, "Could not determine the HDU type.");
+        return NULL;
+    }
+    if (hduType != IMAGE_HDU) {
+        psError(PS_ERR_IO, true, _("Current FITS HDU type must be an image."));
+        return NULL;
+    }
+
+    int numCols = input->numCols;
+    int numRows = input->numRows;
+    psFitsCompression *compress = NULL; // FITS compression parameters; to save state
+
+    bool success = true;                // Successful update?
+    double bscale = NAN, bzero = NAN;   // Scale and zero point to put in header
+    long blank = 0;                     // Blank (undefined) value for image
+    psFitsFloat floatType;              // Custom floating-point convention type
+    psImage *diskImage = imageToDiskRepresentation(&bscale, &bzero, &blank, &floatType, fits, input,
+                                                   NULL, false); // Image to write out
+    if (!diskImage) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to convert image to desired disk format.");
+        success = false;
+        goto UPDATE_DONE;
+    }
+
+    bool useRequestedScale = true;
+    if (!isfinite(bscale) || !isfinite(bzero)) {
+        // Couldn't scale, so don't compress.  Save compression parameters for later
+        useRequestedScale = false;
+        compress = psFitsCompressionGet(fits);
+        if (!psFitsSetCompression(fits, PS_FITS_COMPRESS_NONE, NULL, 0, 0, 0)) {
+            psError(PS_ERR_IO, false, "Unable to unset compression.");
+            success = false;
+            goto UPDATE_DONE;
+        }
+    }
+
+    // determine the FITS-equivalent parameters
+    int bitPix;                         // Bits per pixel
+    double cfitsioBzero = 0.0;          // Zero point for cfitsio to apply
+    int dataType;                       // cfitsio data type
+    if (!p_psFitsTypeToCfitsio(diskImage->type.type, &bitPix, &cfitsioBzero, &dataType)) {
+        success = false;
+        goto UPDATE_DONE;
+    }
+    if (cfitsioBzero != 0.0) {
+        // p_psFitsTypeToCfitsio and imageToDiskRepresentation must not clash!
+        psAssert(bzero == 0.0 && bscale == 1.0, "impossible");
+        bscale = 1.0;
+        bzero = cfitsioBzero;
+    }
+    psFitsOptions *options = fits->options; // FITS I/O options
+    psAssert(!useRequestedScale || !options || bitPix == options->bitpix || options->bitpix == 0, "impossible");
+
+    // Check to see if the HDU has the same datatype
+    int fileBitpix;
+    int naxis;
+    long nAxes[3];
+    nAxes[2] = 1;
+    fits_get_img_param(fits->fd, 3, &fileBitpix, &naxis, nAxes, &status);
+
+    //check if the HDU has the z-plane requested
+    if (z >= nAxes[2]) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                _("Current FITS HDU has %ld z-planes, but z-plane %d was specified."), nAxes[2], z);
+        success = false;
+        goto UPDATE_DONE;
+    }
+
+    // determine the region in the FITS file domain
+    long firstPixel[3];
+    long lastPixel[3];
+
+    firstPixel[0] = x0 + 1;
+    firstPixel[1] = y0 + 1;
+    firstPixel[2] = z + 1;
+
+    lastPixel[0] = x0 + numCols;
+    lastPixel[1] = y0 + numRows;
+    lastPixel[2] = z + 1;
+
+    if (firstPixel[0] < 1 || firstPixel[0] > nAxes[0] ||
+        firstPixel[1] < 1 || firstPixel[1] > nAxes[1] ||
+        lastPixel[0] < 1 || lastPixel[0] > nAxes[0] ||
+        lastPixel[1] < 1 || lastPixel[1] > nAxes[1]) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Input image [size of %ix%i] at position (%i,%i) does not all lay in the %lix%li FITS image.",
+                numCols, numRows, x0, y0, nAxes[0], nAxes[1]);
+        success = false;
+        goto UPDATE_DONE;
+    }
+
+    // We only want cfitsio to do the scale and zero if the type conversion requires it (e.g., input type is
+    // an unsigned integer type).  In all other cases, we have already converted the image to use the
+    // appropriate scale and zero (because we want to apply a randomiser to the quantisation).
+    fits_set_bscale(fits->fd, 1.0, cfitsioBzero, &status);
+    fits_write_subset(fits->fd, dataType, firstPixel, lastPixel, diskImage->data.V[0], &status);
+    if (psFitsError(status, true, "Could not write data to file.")) {
+        success = false;
+        goto UPDATE_DONE;
+    }
+
+    // This forces a re-scan of the header to ensure everything's kosher.  We found this occassionally
+    // necessary for compressed images, which are tables, so perhaps it helps here too.  I guess it can't
+    // hurt.
+    ffrdef(fits->fd, &status);
+    if (psFitsError(status, true, "Could not re-scan HDU.")) {
+        success = false;
+        goto UPDATE_DONE;
+    }
+
+UPDATE_DONE:
+    psFree(diskImage);
+    if (compress) {
+        // Restore compression state
+        psFitsCompressionApply(fits, compress);
+        psFree(compress);
+    }
+
+    return success;
+}
+
+psArray *psFitsReadImageCube(const psFits *fits, psRegion region)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+
+    int nAxis = 0;                      // Number of axes
+    long nAxes[3];                      // Number of pixels on each axis
+    int status = 0;                     // cfitsio status value
+
+    // Some of this replicates what is in psFitsReadImage, so it's a little inefficient.  But it saves
+    // code replication, and should be sufficient for our needs.
+
+    if (psFitsCheckSingleCompressedImagePHU(fits, NULL)) {
+        // This is really what we want, not the empty PHU
+        psTrace("psLib.fits", 1,
+                "This PHU should really be a compressed image --- reading that image instead.");
+    }
+
+    if (fits_get_img_dim(fits->fd, &nAxis, &status) != 0) {
+        psFitsError(status, true, "Could not determine image dimensions.");
+        return NULL;
+    }
+
+    if (nAxis == 2) {
+        psArray *images = psArrayAlloc(1); // Single image plane
+        images->data[0] = psFitsReadImage(fits, region, 0);
+        return images;
+    }
+    if (nAxis == 3) {
+        if (fits_get_img_size(fits->fd, nAxis, nAxes, &status) != 0) {
+            psFitsError(status, true, "Could not determine image size.");
+            return NULL;
+        }
+
+        psArray *images = psArrayAlloc(nAxes[2]); // Array of image planes
+        for (int i = 0; i < nAxes[2]; i++) {
+            images->data[i] = psFitsReadImage(fits, region, i);
+        }
+
+        return images;
+    }
+
+    // Bad dimensionality
+    psError(PS_ERR_IO, true, _("Image number of dimensions, %d, is not supported."), nAxis);
+    return NULL;
+}
+
+bool psFitsWriteImageCube(psFits *fits, psMetadata *header, const psArray *input, const char *extname)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_FITS_WRITABLE(fits, false);
+    PS_ASSERT_ARRAY_NON_NULL(input, false);
+
+    if (input->n == 0) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, _("The input array was empty."));
+        return false;
+    }
+
+    if (input->n == 1) {
+        // The problem reduces to one already solved
+        return psFitsWriteImage(fits, header, input->data[0], 1, extname);
+    }
+
+    // Check that all images are of the same size
+    psImage *testImage = input->data[0];// First image off the array
+    int numCols = testImage->numCols;   // Number of columns
+    int numRows = testImage->numRows;   // Number of rows
+    for (int i = 1; i < input->n; i++) {
+        testImage = input->data[i];
+        if (testImage->numCols != numCols || testImage->numRows != numRows) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true, _("The sizes of images in the array differ."));
+            return false;
+        }
+    }
+
+    // Need to check the header to make sure NAXIS and NAXIS[1-3] are correct
+    psMetadata *headerCopy = NULL;      // Copy of header
+    if (header) {
+        headerCopy = psMemIncrRefCounter(header);
+    } else {
+        headerCopy = psMetadataAlloc();
+    }
+    bool update = psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS", PS_META_REPLACE, "Dimensionality", 3) &&
+        psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS1", PS_META_REPLACE, "Number of columns", numCols) &&
+        psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS2", PS_META_REPLACE, "Number of rows", numRows) &&
+        psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS3", PS_META_REPLACE, "Number of image planes",
+                         input->n);
+    if (! update) {
+        psError(PS_ERR_UNKNOWN, false, _("Failed to add metadata item, %s."),
+                "NAXIS, NAXIS1, NAXIS2, NAXIS3");
+        psFree(headerCopy);
+        return false;
+    }
+
+    // Now we can safely write the images out.
+    // The first is an psFitsImageWrite to create the extension.
+    // The next are psFitsImageUpdate to write into the extension.
+    if (! psFitsWriteImage(fits, headerCopy, input->data[0], input->n, extname)) {
+        psError(PS_ERR_UNKNOWN, false, _("Could not write image plane %d."), 0);
+        psFree(headerCopy);
+        return false;
+    }
+    psFree(headerCopy);                 // Free, or drop reference
+
+    for (int i = 1; i < input->n; i++) {
+        if (! psFitsUpdateImage(fits, input->data[i], 0, 0, i)) {
+            psError(PS_ERR_UNKNOWN, false, _("Could not write image plane %d."), i);
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool psFitsUpdateImageCube(psFits *fits, const psArray *input, int x0, int y0)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_FITS_WRITABLE(fits, false);
+    PS_ASSERT_ARRAY_NON_NULL(input, false);
+
+    if (input->n == 0) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, _("The input array was empty."));
+        return false;
+    }
+
+    for (int i = 0; i < input->n; i++) {
+        if (! psFitsUpdateImage(fits, input->data[i], x0, y0, i)) {
+            psError(PS_ERR_UNKNOWN, false, _("Could not update image plane %d."), i);
+            return false;
+        }
+    }
+
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsImage.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsImage.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsImage.h	(revision 22158)
@@ -0,0 +1,93 @@
+/* @file  psFitsImage.h
+ * @brief Contains Fits I/O routines
+ *
+ * @author Robert DeSonia, MHPCC
+ *
+ * @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-16 01:04:56 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_FITSIMAGE_H
+#define PS_FITSIMAGE_H
+
+/// @addtogroup FileIO Input/Output
+/// @{
+
+#include "psFits.h"
+#include "psType.h"
+#include "psArray.h"
+#include "psVector.h"
+#include "psMetadata.h"
+#include "psImage.h"
+
+/// Return the dimensions and type of the FITS image
+bool psFitsImageSize(int *numCols, int *numRows, ///< Size of image
+                     psElemType *type,  ///< Type of image
+                     const psFits *fits, ///< FITS file pointer
+                     psRegion region    ///< Region in the FITS image to read
+    );
+
+/** Reads an image, given the desired region and z-plane.
+ *
+ *  @return psImage*     the read image or NULL if there was an error.
+ */
+psImage* psFitsReadImage(
+    const psFits* fits,                ///< the psFits object
+    psRegion region,                   ///< the region in the FITS image to read
+    int z                              ///< the z-plane in the FITS image cube to read
+);
+
+// Read an image into an extant buffer
+psImage* psFitsReadImageBuffer(psImage *output, // Output image buffer
+                               const psFits *fits,    // the psFits object
+                               psRegion region, // the region in the FITS image to read
+                               int z           // the z-plane in the FITS image cube to read
+                              );
+
+/** Writes an image, given the desired region and z-plane.
+ *
+ *  @return bool        TRUE is the write was successful, otherwise FALSE.
+ */
+bool psFitsWriteImage(
+    psFits* fits,                      ///< the psFits object
+    psMetadata* header,                 ///< header items for the new HDU.  Can be NULL.
+    const psImage* input,              ///< the image to output
+    int depth,                         ///< the number of z-planes of the FITS image data cube
+    const char* extname                ///< FITS extension name
+);
+
+/** Writes an image, given the desired region and z-plane.  A new IMAGE HDU is
+ *  appended to the end of the FITS file.
+ *
+ *  @return bool        TRUE is the write was successful, otherwise FALSE.
+ */
+bool psFitsInsertImage(
+    psFits* fits,                      ///< the psFits object
+    psMetadata* header,                 ///< header items for the new HDU.  Can be NULL.
+    const psImage* input,              ///< the image to output
+    int depth,                         ///< the number of z-planes of the FITS image data cube
+    const char* extname,               ///< FITS extension name
+    bool after                         ///< if TRUE, inserts HDU after current HDU, otherwise before
+);
+
+/** Updates the FITS file image, given the desired region and z-plane. a new
+ *  IMAGE HDU is inserted before or after, depending on the AFTER parameter,
+ *  the current HDU.
+ *
+ *  @return bool        TRUE is the write was successful, otherwise FALSE.
+ */
+bool psFitsUpdateImage(
+    psFits* fits,                      ///< the psFits object
+    const psImage* input,              ///< the image to output
+    int x0,                            ///< psImage's x-axis origin in FITS image coordinates
+    int y0,                            ///< psImage's y-axis origin in FITS image coordinates
+    int z                              ///< the z-planes of the FITS image data cube to write
+);
+
+psArray *psFitsReadImageCube(const psFits *fits, psRegion region);
+bool psFitsWriteImageCube(psFits *fits, psMetadata *header, const psArray *input, const char *extname);
+bool psFitsUpdateImageCube(psFits *fits, const psArray *input, int x0, int y0);
+
+/// @}
+#endif // #ifndef PS_FITS_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsScale.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsScale.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsScale.c	(revision 22158)
@@ -0,0 +1,448 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <strings.h>
+
+#include "psAbort.h"
+#include "psAssert.h"
+#include "psError.h"
+#include "psTrace.h"
+
+#include "psFits.h"
+#include "psImageBackground.h"
+#include "psStats.h"
+#include "psImageStructManip.h"
+
+#include "psMemory.h"
+
+#include "psFitsScale.h"
+
+// Remember:
+// TRUE(i.e., value in memory) = BZERO + BSCALE * FITS(i.e., value on disk)
+
+
+#define MEAN_STAT PS_STAT_ROBUST_MEDIAN // Statistic to use for mean
+#define STDEV_STAT PS_STAT_ROBUST_STDEV // Statistic to use for stdev
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Private (file-static) functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Determine appropriate BSCALE and BZERO for an image, preserving dynamic range
+static bool scaleRange(double *bscale, // Scaling, to return
+                       double *bzero, // Zero point, to return
+                       const psImage *image, // Image to scale
+                       const psFitsOptions *options // FITS options
+    )
+{
+    psAssert(bscale, "impossible");
+    psAssert(bzero, "impossible");
+    psAssert(image, "impossible");
+    psAssert(options, "impossible");
+
+    double range = pow(2.0, options->bitpix) - 1.0; // Range of values for target BITPIX, reduced by the BLANK
+    double min = INFINITY, max = -INFINITY; // Minimum and maximum values
+    int numCols = image->numCols, numRows = image->numRows; // Size of image
+
+    // Determine the minimum and maximum values
+#define SCALE_DETERMINE_CASE(IN, INTYPE) \
+    case PS_TYPE_##INTYPE: { \
+        for (int y = 0; y < numRows; y++) { \
+            for (int x = 0; x < numCols; x++) { \
+                ps##INTYPE value = (IN)->data.INTYPE[y][x]; /* Value of interest */ \
+                if (isfinite(value)) { \
+                    if (value < min) { \
+                        min = value; \
+                    } \
+                    if (value > max) { \
+                        max = value; \
+                    } \
+                } \
+            } \
+        } \
+        break; \
+    }
+
+    switch (image->type.type) {
+        SCALE_DETERMINE_CASE(image, F32);
+        SCALE_DETERMINE_CASE(image, F64);
+      default:
+        psAbort("Should be unreachable.");
+    }
+
+    if (!isfinite(min) || !isfinite(max)) {
+        psWarning("No valid values in image to derive BSCALE,BZERO");
+        *bscale = 1.0;
+        *bzero = 0.0;
+        return false;
+    }
+    if (min == max) {
+        *bscale = 1.0;
+        *bzero = min;
+    } else {
+        *bscale = (max - min) / range ;
+        *bzero = min + 0.5 * range * (*bscale);
+    }
+
+    return true;
+}
+
+// Determine appropriate BSCALE and BZERO for an image, mapping the standard deviation to the nominated number
+// of bits
+static bool scaleStdev(double *bscale, // Scaling, to return
+                       double *bzero, // Zero point, to return
+                       const psImage *image, // Image to scale
+                       const psFitsOptions *options // FITS options
+    )
+{
+    psAssert(bscale, "impossible");
+    psAssert(bzero, "impossible");
+    psAssert(image, "impossible");
+    psAssert(options, "impossible");
+
+    // Measure the mean and stdev
+    // psImageBackground automatically excludes pixels that are non-finite, so we don't need to bother about a
+    // mask.
+    psU64 seed = p_psRandomGetSystemSeed(false);
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, seed);
+    psStats *stats = psStatsAlloc(MEAN_STAT | STDEV_STAT); // Statistics object
+    if (!psImageBackground(stats, NULL, image, NULL, 0, rng)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to perform statistics on image");
+        psFree(rng);
+        psFree(stats);
+        return false;
+    }
+    psFree(rng);
+
+    double mean = psStatsGetValue(stats, MEAN_STAT); // Mean
+    double stdev = psStatsGetValue(stats, STDEV_STAT); // Standard deviation
+    psFree(stats);
+    if (!isfinite(mean) || !isfinite(stdev)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Mean (%f) or stdev (%f) is non-finite.", mean, stdev);
+        return false;
+    }
+
+    long range = 1 << options->stdevBits;  // Range of values to carry standard deviation
+    *bscale = stdev / (double) range;
+
+    double imageVal;                    // Value on image
+    long diskVal;                       // Corresponding value on disk
+    switch (options->scaling) {
+      case PS_FITS_SCALE_STDEV_POSITIVE:
+        // Put (mean - N sigma) at the lowest possible value: predominantly positive images
+        imageVal = mean - options->stdevNum * stdev;
+        diskVal = - (1 << (options->bitpix - 1));
+        break;
+      case PS_FITS_SCALE_STDEV_NEGATIVE:
+        // Put (mean + N sigma) at the highest possible value: predominantly negative images
+        imageVal = mean + options->stdevNum * stdev;
+        diskVal = (1 << (options->bitpix - 1)) - 1;
+        break;
+      case PS_FITS_SCALE_STDEV_BOTH:
+        // Put mean right in the middle: images with an equal abundance of positive and negative values
+        imageVal = mean;
+        diskVal = 0;
+        break;
+      default:
+        psAbort("Should never get here.");
+    }
+
+    *bzero = imageVal - *bscale * diskVal;
+
+    return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool psFitsScaleDetermine(double *bscale, // Scaling, to return
+                          double *bzero, // Zero point, to return
+                          long *blank,  // Blank value, to return
+                          const psImage *image, // Image to scale
+                          const psFits *fits // FITS options
+    )
+{
+    PS_ASSERT_PTR_NON_NULL(bscale, false);
+    PS_ASSERT_PTR_NON_NULL(bzero, false);
+    PS_ASSERT_PTR_NON_NULL(blank, false);
+    PS_ASSERT_IMAGE_NON_NULL(image, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    *bscale = NAN;
+    *bzero = NAN;
+    *blank = 0;
+
+    psFitsOptions *options = fits->options; // FITS options
+    if (!PS_IS_PSELEMTYPE_REAL(image->type.type) || !options) {
+        return true;
+    }
+
+    switch (options->bitpix) {
+      case 0:
+        // No scaling applied
+        return true;
+      case 8:
+      case 16:
+      case 32:
+      case 64:
+        // Nothing to do; just allowing these values to pass through
+        break;
+      default:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Target bitpix (%d) is not one of 0,8,16,32,64",
+                options->bitpix);
+        return false;
+    }
+
+    *blank = (1 << (options->bitpix - 1)) - 1;
+
+    switch (options->scaling) {
+      case PS_FITS_SCALE_NONE:
+        // No scaling applied
+        break;
+      case PS_FITS_SCALE_RANGE:
+        if (!scaleRange(bscale, bzero, image, options)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to set BSCALE and BZERO from range");
+            return false;
+        }
+        break;
+      case PS_FITS_SCALE_STDEV_POSITIVE:
+      case PS_FITS_SCALE_STDEV_NEGATIVE:
+      case PS_FITS_SCALE_STDEV_BOTH:
+        if (!scaleStdev(bscale, bzero, image, options)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to set BSCALE and BZERO from stdev");
+            return false;
+        }
+        break;
+      case PS_FITS_SCALE_MANUAL:
+        *bscale = options->bscale;
+        *bzero = options->bzero;
+        break;
+      default:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unrecognised FITS scaling method: %x",
+                options->scaling);
+        return false;
+    }
+
+    if (options->bitpix == 8) {
+        // FITS standard wants unsigned for BITPIX=8, two's-complement for BITPIX=16,32,64.
+        *bzero -= *bscale * 128;
+        *blank = 255;
+    }
+
+
+    psTrace("psLib.fits", 3, "BSCALE = %.10lf, BZERO = %.10lf, BLANK = %ld\n", *bscale, *bzero, *blank);
+    return true;
+}
+
+
+psImage *psFitsScaleForDisk(const psImage *image, const psFits *fits, double bscale, double bzero,
+                            psRandom *rng)
+{
+    PS_ASSERT_IMAGE_NON_NULL(image, NULL);
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+
+    psFitsOptions *options = fits->options; // FITS options
+    if (!PS_IS_PSELEMTYPE_REAL(image->type.type) || !options || options->bitpix == 0) {
+        // No scaling desired
+        return psMemIncrRefCounter((psImage*)image); // Casting away "const"
+    }
+
+    int bitpix = options->bitpix;       // Bits per pixel
+    psElemType outType;                 // Type for output image
+    // Choosing to use signed types because those don't require BSCALE,BZERO to represent them in the FITS
+    // file
+    switch (bitpix) {
+      case 8:
+        // Note: Use unsigned integer for BITPIX=8
+        outType = PS_TYPE_U8;
+        break;
+      case 16:
+        outType = PS_TYPE_S16;
+        break;
+      case 32:
+        outType = PS_TYPE_S32;
+        break;
+      case 64:
+        outType = PS_TYPE_S64;
+        break;
+      default:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Target bitpix (%d) is not one of 8,16,32,64", bitpix);
+        return NULL;
+    }
+
+    if (bscale == 1.0 && bzero == 0.0 && !options->fuzz) {
+        return psImageCopy(NULL, image, outType);
+    }
+
+    int numCols = image->numCols, numRows = image->numRows; // Size of image
+    psImage *out = psImageAlloc(numCols, numRows, outType); // Output image
+
+    if (!psMemIncrRefCounter(rng) && options->fuzz) {
+        // Don't blab about which seed we're going to get --- it's not necessary for this purpose
+        psU64 seed = p_psRandomGetSystemSeed(false);
+        rng = psRandomAlloc(PS_RANDOM_TAUS, seed);
+    }
+
+#define SCALE_WRITE_OUT_CASE(IN, INTYPE, OUT, OUTTYPE) \
+    case PS_TYPE_##OUTTYPE: { \
+        double scale = 1.0 / bscale; \
+        double zero = bzero; \
+        /* Note: BITPIX=8 treated differently, since it uses unsigned values; the rest use signed */ \
+        double min = bitpix == 8 ? 0 : -pow(2.0, options->bitpix - 1); \
+        double max = bitpix == 8 ? 255 : (pow(2.0, options->bitpix - 1) - 1.0); \
+        for (int y = 0; y < numRows; y++) { \
+            for (int x = 0; x < numCols; x++) { \
+                ps##INTYPE value = (IN)->data.INTYPE[y][x]; \
+                if (!isfinite(value)) { \
+                    /* This choice of "max" for non-finite pixels is mainly cosmetic --- it has to be */ \
+                    /* something, and "min" would produce holes in the cores of bright stars. */ \
+                    (OUT)->data.OUTTYPE[y][x] = max; \
+                } else { \
+                    value = (value - zero) * scale; \
+                    if (options->fuzz) { \
+                       /* Add random factor [0,1): adds a variance of 1/12, */ \
+                       /* but preserves the expectation value */ \
+                        value += psRandomUniform(rng); \
+                    } \
+                    /* Check for underflow and overflow; set either to max */ \
+                    (OUT)->data.OUTTYPE[y][x] = (value < min || value > max ? max : value); \
+                } \
+            } \
+        } \
+        break; \
+    }
+
+#define SCALE_WRITE_IN_CASE(IN, INTYPE, OUT) \
+    case PS_TYPE_##INTYPE: { \
+        switch (outType) { \
+            SCALE_WRITE_OUT_CASE(IN, INTYPE, OUT, U8); \
+            SCALE_WRITE_OUT_CASE(IN, INTYPE, OUT, S16); \
+            SCALE_WRITE_OUT_CASE(IN, INTYPE, OUT, S32); \
+            SCALE_WRITE_OUT_CASE(IN, INTYPE, OUT, S64); \
+          default: \
+            psAbort("Should be unreachable."); \
+        } \
+        break; \
+    }
+
+    switch (image->type.type) {
+        SCALE_WRITE_IN_CASE(image, F32, out);
+        SCALE_WRITE_IN_CASE(image, F64, out);
+      default:
+        psAbort("Should be unreachable.");
+    }
+
+    psFree(rng);
+
+    return out;
+}
+
+
+#if 0
+// This function to apply BSCALE and BZERO to an image read immediately from disk should not be necessary at
+// the present time, since cfitsio should apply the scaling itself in the process of reading.  However, we may
+// later desire it (e.g., if we ever make our own FITS implementation).
+psImage *psFitsScaleFromDisk(psFits *fits, psImage *image)
+{
+    PS_ASSERT_IMAGE_NON_NULL(image, NULL);
+
+    if (bscale == 0.0) {
+        // BSCALE = 0 means don't apply anything
+        return psMemIncrRefCounter(image);
+    }
+
+    psElemType inType = image->type.type; // Type for input image
+    psElemType outType;                 // Type for output image
+    switch (inType) {
+      case PS_TYPE_S8:
+      case PS_TYPE_S16:
+      case PS_TYPE_S32:
+      case PS_TYPE_U8:
+      case PS_TYPE_U16:
+        outType = PS_TYPE_F32;
+        break;
+      case PS_TYPE_S64:
+      case PS_TYPE_U32:
+      case PS_TYPE_U64:
+        outType = PS_TYPE_F64;
+        break;
+        // Including floating-point types just in case someone wants to apply a BSCALE and BZERO to them.
+      case PS_TYPE_F32:
+        outType = PS_TYPE_F32;
+        break;
+      case PS_TYPE_F64:
+        outType = PS_TYPE_F64;
+        break;
+      default:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unsupported image type: %x", inType);
+        return NULL;
+    }
+
+    int numCols = image->numCols, numRows = image->numRows;
+    psImage *out = psImageAlloc(numCols, numRows, outType); // Output scaled image
+
+
+#define SCALE_READ_OUT_CASE(INTYPE, OUTTYPE) \
+  case PS_TYPE_##OUTTYPE: { \
+      for (int y = 0; y < numRows; y++) { \
+          for (int x = 0; x < numCols; x++) { \
+              out->data.OUTTYPE[y][x] = image->data.INTYPE[y][x] * bscale + bzero; \
+          } \
+      } \
+      break; \
+  }
+
+#define SCALE_READ_IN_CASE(INTYPE) \
+  case PS_TYPE_##INTYPE: { \
+      switch (outType) { \
+          SCALE_READ_OUT_CASE(INTYPE, F32); \
+          SCALE_READ_OUT_CASE(INTYPE, F64); \
+        default: \
+          psAbort("Should never get here: type %x should be F32 or F64", outType); \
+      } \
+      break; \
+  }
+
+    switch (inType) {
+        SCALE_READ_IN_CASE(S8);
+        SCALE_READ_IN_CASE(S16);
+        SCALE_READ_IN_CASE(S32);
+        SCALE_READ_IN_CASE(S64);
+        SCALE_READ_IN_CASE(U8);
+        SCALE_READ_IN_CASE(U16);
+        SCALE_READ_IN_CASE(U32);
+        SCALE_READ_IN_CASE(U64);
+        SCALE_READ_IN_CASE(F32);
+        SCALE_READ_IN_CASE(F64);
+      default:
+          psAbort("Should never get here: type %x should be integer", inType);
+    }
+
+    return out;
+}
+#endif
+
+
+
+psFitsScaling psFitsScalingFromString(const char *string)
+{
+    PS_ASSERT_STRING_NON_EMPTY(string, PS_FITS_SCALE_NONE);
+
+    if (strcasecmp(string, "RANGE") == 0)          return PS_FITS_SCALE_RANGE;
+    if (strcasecmp(string, "STDEV_POSITIVE") == 0) return PS_FITS_SCALE_STDEV_POSITIVE;
+    if (strcasecmp(string, "STDEV_NEGATIVE") == 0) return PS_FITS_SCALE_STDEV_NEGATIVE;
+    if (strcasecmp(string, "STDEV_BOTH") == 0)     return PS_FITS_SCALE_STDEV_BOTH;
+    if (strcasecmp(string, "MANUAL") == 0)         return PS_FITS_SCALE_MANUAL;
+
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to interpret FITS scaling: %s", string);
+    return PS_FITS_SCALE_NONE;
+}
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsScale.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsScale.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsScale.h	(revision 22158)
@@ -0,0 +1,34 @@
+#ifndef PS_FITS_SCALE_H
+#define PS_FITS_SCALE_H
+
+#include <psFits.h>
+#include <psImage.h>
+#include <psType.h>
+#include <psRandom.h>
+
+/// Determine BSCALE and BZERO for an image
+bool psFitsScaleDetermine(double *bscale, ///< Scaling, to return
+                          double *bzero, ///< Zero point, to return
+                          long *blank,  ///< Blank value, to return
+                          const psImage *image, ///< Image to scale
+                          const psFits *fits ///< FITS options
+    );
+
+/// Apply the BSCALE and BZERO for an image, so that we get the image as it should be written to disk.
+///
+/// "Fuzz" may be optionally added.  The idea is that the "fuzz" (adding a random number between 0 and 1)
+/// preserves the expectation value of the image (e.g., a value of 0.1 will get translated to zero 90% of the
+/// time, and unity 10% of the time), though at the cost of adding an additional variance of 1/12 (a standard
+/// deviation of ~0.29).
+psImage *psFitsScaleForDisk(const psImage *image, ///< Image to which to apply BSCALE and BZERO
+                            const psFits *fits, ///< FITS file
+                            double bscale, ///< Scaling
+                            double bzero, ///< Zero point
+                            psRandom *rng ///< Random number generator (for the "fuzz"), or NULL
+    );
+
+/// Interpret a string as a scaling method
+psFitsScaling psFitsScalingFromString(const char *string ///< String to interpret
+    );
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsTable.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsTable.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsTable.c	(revision 22158)
@@ -0,0 +1,704 @@
+/** @file  psFitsTable.c
+ *
+ *  @brief Contains Fits I/O routines
+ *
+ *  @ingroup FileIO
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.33 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-04 03:18:06 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "psFits.h"
+#include "string.h"
+#include "psError.h"
+
+#include "psImageStructManip.h"
+#include "psMemory.h"
+#include "psString.h"
+#include "psLogMsg.h"
+#include "psTrace.h"
+#include "psVector.h"
+#include "psFitsTable.h"
+#include "psFitsHeader.h"
+#include "psAbort.h"
+#include "psAssert.h"
+
+#define MAX_STRING_LENGTH 256  // maximum length string for FITS routines
+
+long psFitsTableSize(const psFits *fits)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, 0);
+
+    int status = 0;                     // CFITSIO status
+    long numRows;                       // Number of rows
+    if (fits_get_num_rows(fits->fd, &numRows, &status)) {
+        psFitsError(status, true, "Unable to determine number of rows in table.");
+        return -1;
+    }
+
+    return numRows;
+}
+
+// Check the FITS file in preparation for reading a table
+static bool readTableCheck(const psFits *fits // FITS file
+                           )
+{
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+
+    if (psFitsGetExtNum(fits) == 0 && !psFitsMoveExtNum(fits, 1, false)) {
+        psError(PS_ERR_IO, false, "Unable to move to first extension to read table.");
+        return false;
+    }
+
+
+    // check that we are positioned on a table HDU
+    int status = 0;                     // CFITSIO status
+    int hdutype;                        // Type of HDU
+    fits_get_hdu_type(fits->fd, &hdutype, &status);
+    if (psFitsError(status, true, "Could not determine the HDU type.")) {
+        return false;
+    }
+    if (hdutype != ASCII_TBL && hdutype != BINARY_TBL) {
+        psError(PS_ERR_IO, true, _("Current FITS HDU is not a table."));
+        return false;
+    }
+    return true;
+}
+
+
+psMetadata* psFitsReadTableRow(const psFits* fits,
+                               int row)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(row, NULL);
+
+    if (!readTableCheck(fits)) {
+        return NULL;
+    }
+
+    // get the size of the FITS table
+    long numRows;
+    int numCols;
+    int status = 0;
+    fits_get_num_rows(fits->fd, &numRows, &status);
+    fits_get_num_cols(fits->fd, &numCols, &status);
+    if (status != 0) {
+        psFitsError(status, true, "Failed to determine the size of the current HDU table.");
+        return NULL;
+    }
+
+    psTrace("psLib.fits",5,"Table size is %ix%li\n",numCols, numRows);
+    // the row parameter in the proper range?
+    if (row < 0 || row >= numRows) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified row, %d, is not valid for current table of %ld rows."),
+                row, numRows);
+        return NULL;
+    }
+
+    psMetadata* data = psMetadataAlloc();
+
+    int hdutype;                        // Type of HDU: need to distinguish ASCII and binary tables
+    fits_get_hdu_type(fits->fd, &hdutype, &status);
+    if (psFitsError(status, true, "Could not determine the HDU type.")) {
+        return false;
+    }
+
+    int typecode;
+    long repeat;
+    long width;
+    char name[60];
+    for (int col = 1; col <= numCols; col++) {
+        // get the column name
+        if (hdutype == BINARY_TBL) {
+            fits_get_bcolparms(fits->fd, col, name,
+                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, &status);
+        } else {
+            fits_get_acolparms(fits->fd, col, name,
+                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, &status);
+        }
+        // get the column type
+        fits_get_coltype(fits->fd, col, &typecode, &repeat, &width, &status);
+        if (psFitsError(status, true, "Unable to get column type for column %d", col)) {
+            psFree(data);
+            return NULL;
+        }
+
+#define READ_TABLE_ROW_CASE(FITSTYPE, NATIVETYPE, TYPE, VECTYPE) \
+        case FITSTYPE: { \
+                if (repeat == 1) { \
+                    NATIVETYPE value; \
+                    int anynul = 0; \
+                    fits_read_col(fits->fd, FITSTYPE, col,row+1, \
+                                  1, 1, NULL, &value, &anynul, &status); \
+                    psTrace("psLib.fits",5,"Column #%i, '%s', is type %i, repeat %li, Value = %g\n", \
+                            col, name, typecode, repeat, (double)value); \
+                    psMetadataAdd(data,PS_LIST_TAIL, name, \
+                                  PS_DATA_##TYPE, \
+                                  "", (ps##TYPE)value); \
+                } else { \
+                    NATIVETYPE* value = psAlloc(sizeof(NATIVETYPE)*repeat); \
+                    psVector* vec = psVectorAlloc(repeat,PS_TYPE_##VECTYPE); \
+                    int anynul = 0; \
+                    fits_read_col(fits->fd, FITSTYPE, col,row+1, \
+                                  1, repeat, NULL, value, &anynul, &status); \
+                    for (int lcv = 0; lcv < repeat; lcv++) { \
+                        vec->data.VECTYPE[lcv] = value[lcv]; \
+                    } \
+                    psMetadataAdd(data,PS_LIST_TAIL, name, PS_DATA_VECTOR, "", vec); \
+                    psFree(value); \
+                    psFree(vec); \
+                } \
+                break; \
+            }
+
+        switch (typecode) {
+          case TBYTE:
+          case TSHORT:
+          case TLONGLONG:
+            READ_TABLE_ROW_CASE(TLONG, long, S32, S32);
+            READ_TABLE_ROW_CASE(TFLOAT, float, F32, F32);
+            READ_TABLE_ROW_CASE(TDOUBLE, double, F64, F64);
+            READ_TABLE_ROW_CASE(TLOGICAL, bool, BOOL, S8);
+          case TSTRING: {
+              psString value = psStringAlloc(repeat);
+              int anynul = 0;
+              fits_read_col(fits->fd, TSTRING, col,row+1, 1, 1, NULL, &value, &anynul, &status);
+              psTrace("psLib.fits", 5, "Column #%i, '%s', is type %i, repeat %li, value = %s\n",
+                      col, name, typecode, repeat, value);
+              if (anynul == 0) {
+                  psMetadataAdd(data,PS_LIST_TAIL, name, PS_DATA_STRING, NULL, value);
+              }
+              psFree(value);
+              break;
+          }
+          default:
+            psWarning("Data type (%d) not supportted for column %d", typecode, col);
+            psTrace("psLib.fits", 2, "Column %d or row %d was of a non primitive type, %d",
+                    col, row, typecode);
+        }
+
+        if (psFitsError(status, true, "Failed to retrieve table element (%d,%d)", col, row)) {
+            psFree(data);
+            return NULL;
+        }
+    }
+
+    return data;
+}
+
+psArray* psFitsReadTableColumn(const psFits* fits,
+                               const char* colname)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(colname, NULL);
+
+    if (!readTableCheck(fits)) {
+        return NULL;
+    }
+
+    int colnum = 0;
+    int status = 0;
+
+    // find the column by name
+    if (fits_get_colnum(fits->fd, CASESEN, (char*)colname, &colnum, &status) != 0) {
+        psFitsError(status, true, "Specified column, %s, was not found.", colname);
+        return NULL;
+    }
+
+    // get the number of rows
+    long numRows = psFitsTableSize(fits);
+    if (numRows == -1) {
+        return NULL;
+    }
+
+    // get the column length.
+    int width;
+    if (fits_get_col_display_width(fits->fd, colnum, &width, &status) != 0) {
+        psFitsError(status, true, "Could not determine the datatype of the table column.");
+        return NULL;
+    }
+
+    // allocate the buffers
+    psArray* result = psArrayAlloc(numRows);
+    for (int row = 0; row < numRows; row++) {
+        result->data[row] = psStringAlloc(width);
+    }
+
+    fits_read_col_str(fits->fd, colnum, 1, 1, numRows, "", (char**)result->data, NULL, &status);
+    if (psFitsError(status, true, "Failed to read table column.")) {
+        psFree(result);
+        return NULL;
+    }
+
+    return result;
+}
+
+psVector* psFitsReadTableColumnNum(const psFits* fits,
+                                   const char* colname)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(colname, NULL);
+
+    if (!readTableCheck(fits)) {
+        return NULL;
+    }
+
+    int status = 0;
+    int colnum = 0;
+
+    // find the column by name
+    if (fits_get_colnum(fits->fd, CASESEN, (char*)colname, &colnum, &status) != 0) {
+        psFitsError(status, true, "Specified column, %s, was not found.", colname);
+        return NULL;
+    }
+
+    // get the number of rows
+    long numRows = psFitsTableSize(fits);
+    if (numRows == -1) {
+        return NULL;
+    }
+
+    // get the column datatype.
+    int typecode;
+    long repeat;
+    long width;
+    if (fits_get_eqcoltype(fits->fd, colnum, &typecode, &repeat, &width, &status) != 0) {
+        psFitsError(status, true, "Could not determine the datatype of the table column.");
+        return NULL;
+    }
+
+    psVector* result = psVectorAlloc(numRows, p_psFitsTypeFromCfitsio(typecode));
+
+    fits_read_col(fits->fd, typecode, colnum, 1, 1, numRows, NULL, (psPtr)(result->data.U8), NULL, &status);
+    if (psFitsError(status, true, "Failed to read table column.")) {
+        psFree(result);
+        return NULL;
+    }
+
+    return result;
+}
+
+
+psArray* psFitsReadTable(const psFits* fits)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+
+    if (!readTableCheck(fits)) {
+        return NULL;
+    }
+
+    // get the number of rows
+    long numRows = psFitsTableSize(fits);
+    if (numRows == -1) {
+        return NULL;
+    }
+
+    psArray* table = psArrayAlloc(numRows);
+
+    for (int row = 0; row < numRows; row++) {
+        psTrace("psLib.fits",5,"Reading row %i of %li\n", row, numRows);
+        table->data[row] = psFitsReadTableRow(fits,row);
+    }
+
+    return table;
+}
+
+bool psFitsWriteTable(psFits* fits,
+                      const psMetadata* header,
+                      const psArray* table,
+                      const char *extname)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_FITS_WRITABLE(fits, false);
+    if (!psFitsMoveLast(fits)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to move to last extension to write table");
+        return false;
+    }
+    return psFitsInsertTable(fits, header, table, extname, true);
+}
+
+
+// Return the size of the column
+static inline size_t columnSize(const psMetadataItem *item // Item for which to get the size
+                               )
+{
+    if (PS_DATA_IS_PRIMITIVE(item->type)) {
+        return 1;
+    }
+    switch (item->type) {
+    case PS_DATA_STRING:
+        return strlen(item->data.V);
+    case PS_DATA_VECTOR: {
+            psVector *vector = item->data.V;
+            return vector ? vector->n : 0;
+        }
+    default:
+        psAbort("Shouldn't ever get here.");
+    }
+    return 0;
+}
+
+// Get the TFORM character, given a PS type
+static inline char getTForm(psDataType type)
+{
+    switch (type) {
+    case PS_TYPE_U8:
+    case PS_TYPE_S8:
+        return 'B';
+    case PS_TYPE_S16:
+        return 'I';
+    case PS_TYPE_S32:
+        return 'J';
+    case PS_TYPE_U64:
+    case PS_TYPE_S64:
+        return 'K';
+    case PS_TYPE_U16:
+        return 'U';
+    case PS_TYPE_U32:
+        return 'V';
+    case PS_TYPE_F32:
+        return 'E';
+    case PS_TYPE_F64:
+        return 'D';
+    case PS_TYPE_BOOL:
+        return 'L';
+    case PS_DATA_STRING:
+        return 'A';
+    default:
+        psError(PS_ERR_UNKNOWN, true, "Unknown type: %x\n", type);
+        return '?';
+    }
+}
+
+
+// Column specification
+// Included here, because there's no need for the user to have access to it
+typedef struct {
+    psDataType type;                    // psLib type (e.g., PS_DATA_STRING or PS_TYPE_F32)
+    size_t size;                        // Size (number of repeats)
+    psElemType vectorType;              // psLib type of vectors
+} colSpec;
+
+
+bool psFitsInsertTable(psFits* fits,
+                       const psMetadata* header,
+                       const psArray* table,
+                       const char *extname,
+                       bool after)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_FITS_WRITABLE(fits, false);
+    PS_ASSERT_ARRAY_NON_NULL(table, false);
+
+    int status = 0;
+
+    long numRows = table->n;
+    if (numRows < 1) {
+        // no table data, what can I do?
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                _("Can't create a table without any rows."));
+        return false;
+    }
+
+    // Find the unique items in the array of metadata 'rows', and their sizes
+    psMetadata *colSpecs = psMetadataAlloc(); // Column specifications
+    size_t rowSize = 0;                 // Size (in bytes) of each row
+    for (long i = 0; i < numRows; i++) {
+        psMetadata* row = table->data[i];
+        if (!row) {
+            continue;
+        }
+        psMetadataIterator *rowIter = psMetadataIteratorAlloc(row, PS_LIST_HEAD, NULL); // Iterator
+        psMetadataItem *colItem;        // Column item, from iteration
+        while ((colItem = psMetadataGetAndIncrement(rowIter))) {
+            if (!(PS_DATA_IS_PRIMITIVE(colItem->type) || colItem->type == PS_DATA_STRING ||
+                    colItem->type == PS_DATA_VECTOR)) {
+                // unsupported type -- treating as an error
+                psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                        "Unsupported data type (%d) for Metadata Item '%s' in row %ld.",
+                        colItem->type, colItem->name, i);
+                psFree(rowIter);
+                psFree(colSpecs);
+                return false;
+            }
+
+            size_t size = columnSize(colItem); // Size for this column
+
+            // Check to see if we know about this one; or update the size if required
+            psMetadataItem *colSpecItem = psMetadataLookup(colSpecs, colItem->name);
+            if (!colSpecItem) {
+                // A new one!
+                colSpec *spec = psAlloc(sizeof(colSpec)); // Specification for this column
+                // BOOL type is not a valid vector type, so we translate it to U8
+                spec->type = colItem->type == PS_TYPE_BOOL ? PS_TYPE_U8 : colItem->type;
+                spec->size = size;
+                if (colItem->type == PS_DATA_VECTOR) {
+                    psVector *vector = colItem->data.V; // The vector
+                    spec->vectorType = vector->type.type;
+                }
+                psMetadataAddPtr(colSpecs, PS_LIST_TAIL, colItem->name, PS_DATA_UNKNOWN, "", spec);
+                psFree(spec);           // Drop reference
+                rowSize += PSELEMTYPE_SIZEOF(spec->type);
+            } else {
+                colSpec *spec = colSpecItem->data.V; // The specification
+                if (size > spec->size) {
+                    spec->size = size;
+                }
+                if (colItem->type != spec->type &&
+                    colItem->type != PS_TYPE_BOOL && spec->type != PS_TYPE_U8) {
+                    psWarning("Differing type found for column %s: %x vs %x --- using the first found.\n",
+                              colSpecItem->name, colItem->type, spec->type);
+                }
+                if (colItem->type == PS_DATA_VECTOR) {
+                    psVector *vector = colItem->data.V; // The vector
+                    if (vector->type.type != spec->vectorType) {
+                        psWarning("Differing vector type found for column %s: %x vs %x "
+                                 "--- using the first found.\n", colSpecItem->name, vector->type.type,
+                                 spec->vectorType);
+                    }
+                }
+            }
+        }
+        psFree(rowIter);
+    }
+
+    long numColumns = colSpecs->list->n;// Number of columns
+    if (numColumns == 0) {
+        // No table columns found
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                "Did not find any column data to write to a table.");
+        psFree(colSpecs);
+        return false;
+    }
+
+    // Create array of column names and types.
+    psArray *columnNames = psArrayAlloc(numColumns); // Array of column names, for cfitsio
+    psArray *columnTypes = psArrayAlloc(numColumns); // Array of column types, for cfitsio
+    psMetadataIterator *colSpecsIter = psMetadataIteratorAlloc(colSpecs, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *colSpecItem;        // Column specification item, from iteration
+    for (long i = 0; (colSpecItem = psMetadataGetAndIncrement(colSpecsIter)); i++) {
+        colSpec *spec = colSpecItem->data.V; // The specification
+        columnNames->data[i] = psMemIncrRefCounter(colSpecItem->name);
+        psString colType = NULL;        // The column type
+        if (spec->type == PS_DATA_VECTOR) {
+            psStringAppend(&colType, "%zd%c", spec->size, getTForm(spec->vectorType));
+        } else {
+            psStringAppend(&colType, "%zd%c", spec->size, getTForm(spec->type));
+        }
+        columnTypes->data[i] = colType;
+    }
+
+    // Create the table HDU
+    int numHDUs = psFitsGetSize(fits);  // Number of HDUs in file
+    if (numHDUs == 0) {
+        // We're creating the first extension
+        fits_create_tbl(fits->fd,
+                        BINARY_TBL,
+                        table->n, // number of rows in table
+                        numColumns, // number of columns in table
+                        (char**)columnNames->data, // names of the columns
+                        (char**)columnTypes->data, // format of the columns
+                        NULL, // physical unit of columns
+                        NULL, // skip extension name: we set the by hand below
+                        &status);
+    } else {
+        if (!after) {
+            if (psFitsGetExtNum(fits) == 0) {
+                // We're creating a replacement primary HDU.
+                // Set status to signal fits_insert_img to insert a new primary HDU
+                status = PREPEND_PRIMARY;
+            } else {
+                // Move back one to perform an insert after the previous HDU
+                psFitsMoveExtNum(fits, -1, true);
+            }
+        }
+        // Insert the table
+        fits_insert_btbl(fits->fd,
+                         table->n, // number of rows in table
+                         numColumns, // number of columns in table
+                         (char**)columnNames->data, // names of the columns
+                         (char**)columnTypes->data, // format of the columns
+                         NULL, // physical unit of columns
+                         NULL, // skip extension name: we set this by hand below
+                         0, &status);
+    }
+    psFree(columnNames);
+    psFree(columnTypes);
+
+    if (status != 0) {
+        psFitsError(status, true, "Unable to create FITS table with %ld columns and %ld rows",
+                    numColumns, table->n);
+        psFree(colSpecsIter);
+        psFree(colSpecs);
+        return false;
+    }
+
+    // Write header
+    if (header && !psFitsWriteHeader(fits, header)) {
+        psError(PS_ERR_IO, false, "Unable to write FITS header.\n");
+        psFree(colSpecsIter);
+        psFree(colSpecs);
+        return false;
+    }
+
+    // write the header, if any.
+    if (extname && strlen(extname) > 0) {
+        if (!psFitsSetExtName(fits, extname)) {
+            psError(PS_ERR_IO, false, "Unable to write FITS header extension name.\n");
+            psFree(colSpecsIter);
+            psFree(colSpecs);
+            return false;
+        }
+    }
+
+    // cfitsio requires that we write the data by columns --- urgh!
+    psMetadataIteratorSet(colSpecsIter, PS_LIST_HEAD);
+    for (long colNum = 1; (colSpecItem = psMetadataGetAndIncrement(colSpecsIter)); colNum++) {
+        // Note: colNum is unit-indexed, because it's for cfitsio
+        colSpec *spec = colSpecItem->data.V; // The specification
+        if (PS_DATA_IS_PRIMITIVE(spec->type)) {
+            size_t dataSize = PSELEMTYPE_SIZEOF(spec->type); // Size (in bytes) of this type
+            psVector *columnData = psVectorAlloc(table->n, spec->type); // The raw row data, to be written
+            psVectorInit(columnData, 0);
+            for (long i = 0; i < table->n; i++) {
+                psMetadata *row = table->data[i]; // The row of interest
+                psMetadataItem *dataItem = psMetadataLookup(row, colSpecItem->name); // The value of interest
+                memcpy(&columnData->data.U8[i * dataSize], &dataItem->data, dataSize);
+            }
+
+            int fitsDataType;           // Data type for cfitsio
+            p_psFitsTypeToCfitsio(spec->type, NULL, NULL, &fitsDataType);
+            fits_write_col(fits->fd,
+                           fitsDataType,
+                           colNum, // column number
+                           1, // first row
+                           1, // first element
+                           table->n, // number of rows
+                           columnData->data.U8, // the data
+                           &status);
+            psFree(columnData);
+        } else {
+            switch (spec->type) {
+            case PS_DATA_STRING: {
+                    psArray *strings = psArrayAlloc(table->n); // Array of strings
+                    for (long i = 0; i < table->n; i++) {
+                        psMetadata *row = table->data[i]; // The row of interest
+                        strings->data[i] = psMemIncrRefCounter(psMetadataLookupStr(NULL, row,
+                                                               colSpecItem->name));
+                    }
+                    fits_write_col_str(fits->fd, colNum, 1, 1, table->n, (char**)strings->data, &status);
+                    psFree(strings);
+                    break;
+                }
+            case PS_DATA_VECTOR: {
+                    size_t dataSize = PSELEMTYPE_SIZEOF(spec->vectorType); // Size of data, in bytes
+                    psVector *columnData = psVectorAlloc(spec->size * table->n * dataSize, PS_TYPE_U8);
+                    psVectorInit(columnData, 0);
+                    for (long i = 0; i < table->n; i++) {
+                        psMetadata *row = table->data[i]; // The row of interest
+                        psMetadataItem* dataItem = psMetadataLookup(row, colSpecItem->name);
+                        if (dataItem->type != PS_DATA_VECTOR) {
+                            // Just in case --- get a zero instead of some weird result
+                            continue;
+                        }
+                        psVector *vector = dataItem->data.V;
+                        memcpy(&columnData->data.U8[i * dataSize * spec->size], vector->data.U8,
+                               vector->n * dataSize);
+                    }
+
+                    int fitsDataType;           // Data type for cfitsio
+                    p_psFitsTypeToCfitsio(spec->vectorType, NULL, NULL, &fitsDataType);
+                    fits_write_col(fits->fd, fitsDataType, colNum, 1, 1, table->n * spec->size,
+                                   columnData->data.U8, &status);
+                    psFree(columnData);
+                    break;
+                }
+            default:
+                psAbort("Should never get here.\n");
+            }
+        }
+
+        // Check error status from writing column
+        if (status != 0) {
+            psFitsError(status, true, "Unable to write column %ld of FITS table", colNum);
+            psFree(colSpecsIter);
+            psFree(colSpecs);
+            return false;
+        }
+    }
+
+    psFree(colSpecsIter);
+    psFree(colSpecs);
+
+    // This forces a re-scan of the header to ensure everything's kosher.  We found this occassionally
+    // necessary for compressed images, which are tables, so perhaps it helps here too.  I guess it can't
+    // hurt.
+    ffrdef(fits->fd, &status);
+    if (psFitsError(status, true, "Could not re-scan HDU.")) {
+        return false;
+    }
+
+    return true;
+}
+
+bool psFitsUpdateTable(psFits* fits,
+                       const psMetadata* data,
+                       int row)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_FITS_WRITABLE(fits, false);
+    PS_ASSERT_METADATA_NON_NULL(data, false);
+    PS_ASSERT_INT_NONNEGATIVE(row, false);
+
+    if (!readTableCheck(fits)) {
+        return NULL;
+    }
+
+    int status = 0;
+    psMetadataIterator* iter = psMetadataIteratorAlloc((psPtr)data, PS_LIST_HEAD, NULL);
+    psMetadataItem* item;
+    while ( (item=psMetadataGetAndIncrement(iter)) != NULL) {
+        if (PS_DATA_IS_PRIMITIVE(item->type) ||
+                item->type == PS_DATA_BOOL ||
+                item->type == PS_DATA_STRING) {
+            // operating on primitive data type or string, i.e., not a complex object
+            int colnum = 0;
+
+            if (fits_get_colnum(fits->fd, CASESEN, item->name, &colnum, &status) == 0) {
+                // cooresponding column found in table
+                int dataType;
+                p_psFitsTypeToCfitsio(item->type, NULL, NULL, &dataType);
+
+                if (fits_write_col(fits->fd, dataType, colnum, row+1, 1, 1, &item->data, &status) != 0) {
+                    psFitsError(status, true, "Could not write data to file.");
+                    psFree(iter);
+                    return false;
+                }
+            } else {
+                // the column was not found.
+                psWarning("No column with the name '%s' exists in the table.", item->name);
+            }
+        }
+    }
+
+    psFree(iter);
+
+    // This forces a re-scan of the header to ensure everything's kosher.  We found this occassionally
+    // necessary for compressed images, which are tables, so perhaps it helps here too.  I guess it can't
+    // hurt.
+    ffrdef(fits->fd, &status);
+    if (psFitsError(status, true, "Could not re-scan HDU.")) {
+        return false;
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsTable.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsTable.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/fits/psFitsTable.h	(revision 22158)
@@ -0,0 +1,122 @@
+/* @file  psFitsTable.h
+ * @brief Contains Fits I/O routines
+ *
+ * @author EAM, PAP, JH
+ * @author Robert DeSonia, MHPCC
+ *
+ * @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-10-09 02:56:23 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_FITSTABLE_H
+#define PS_FITSTABLE_H
+
+/// @addtogroup FileIO Input/Output
+/// @{
+
+#include "psFits.h"
+
+#include "psType.h"
+#include "psArray.h"
+#include "psVector.h"
+#include "psMetadata.h"
+#include "psImage.h"
+
+/// Return the number of rows in the current table
+///
+/// The current HDU type must be either PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.
+long psFitsTableSize(const psFits *fits ///< FITS file
+                     );
+
+/** Reads a table row.  The current HDU type must be either
+ *  PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.
+ *
+ *  @return psMetadata*    The table row's data.  The keys are the column names.
+ */
+psMetadata* psFitsReadTableRow(
+    const psFits* fits,                ///< the psFits object
+    int row                            ///< row number to read
+);
+
+/** Reads a table column.  The current HDU type must be either
+ *  PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.
+ *
+ *  @return psArray*    Array of data items for the specified column or NULL
+ *                      if an error occurred.
+ */
+psArray* psFitsReadTableColumn(
+    const psFits* fits,                ///< the psFits object
+    const char* colname                ///< the column name
+);
+
+/** Reads a table column of numbers.  The current HDU type must be either
+ *  PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.
+ *
+ *  @return psVector*    Vector of data for the specified column or NULL
+ *                       if an error occurred.
+ */
+psVector* psFitsReadTableColumnNum(
+    const psFits* fits,                ///< the psFits object
+    const char* colname                ///< the column name
+);
+
+
+/** Reads a whole FITS table.  The current HDU type must be either
+ *  PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.
+ *
+ *  @return psArray*     Array of psMetadata items, which contains the output
+ *                       data items of each row.
+ *
+ *  @see psFitsReadTableRow
+ */
+psArray* psFitsReadTable(
+    const psFits* fits                  ///< the psFits object
+);
+
+/** Writes a whole FITS table. A new HDU of the type BINTABLE is appended
+ *  to the file.
+ *
+ *  @return bool        TRUE if the write was successful, otherwise FALSE
+ *
+ *  @see psFitsReadTable
+ *  @see psFitsInsertTable
+ */
+bool psFitsWriteTable(
+    psFits* fits,                      ///< the psFits object
+    const psMetadata* header,          ///< header items for the new HDU.  Can be NULL.
+    const psArray* table, ///< Array of psMetadata items, which contains the output data items of each row.
+    const char *extname                 ///< Extension name
+);
+
+/** Inserts a whole FITS table. A new HDU of the type BINTABLE is inserted either
+ *  before or after, depending on the AFTER parameter, the current HDU.
+ *
+ *  @return bool        TRUE if the insert/write was successful, otherwise FALSE
+ *
+ *  @see psFitsWriteTable
+ */
+bool psFitsInsertTable(
+    psFits* fits,                  ///< the psFits object
+    const psMetadata* header,      ///< header items for the new HDU.  Can be NULL.
+    const psArray* table, ///< Array of psMetadata items, which contains the output data items of each row.
+    const char *extname,                ///< Extension name
+    bool after    ///< TRUE if insert is done after CHDU, otherwise table is inserted before CHDU
+);
+
+/** Updates a FITS table.  The current HDU type must be either
+ *  PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.
+ *
+ *  @return bool        TRUE if the write was successful, otherwise FALSE
+ *
+ *  @see psFitsWriteTable
+ */
+bool psFitsUpdateTable(
+    psFits* fits,                      ///< the psFits object
+    const psMetadata* data,
+    ///< Array of psMetadata items, which contains the output data items of each row.
+    int row                            ///< the row number to update.
+);
+
+/// @}
+#endif // #ifndef PS_FITS_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/.cvsignore	(revision 22158)
@@ -0,0 +1,10 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
+*.loT
+*.bb
+*.bbg
+*.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/Makefile.am	(revision 22158)
@@ -0,0 +1,40 @@
+#Makefile for image operation functions of psLib
+#
+noinst_LTLIBRARIES = libpslibimageops.la
+
+libpslibimageops_la_CPPFLAGS = $(SRCINC) $(PSLIB_CFLAGS) $(GSL_CFLAGS)
+libpslibimageops_la_SOURCES = \
+	psImageBackground.c \
+	psImageConvolve.c \
+	psImageGeomManip.c \
+	psImageInterpolate.c \
+	psImagePixelExtract.c \
+	psImagePixelManip.c \
+	psImageStats.c \
+	psImageStructManip.c \
+	psImageMaskOps.c \
+	psImageBinning.c \
+	psImageMap.c \
+	psImageMapFit.c \
+	psImagePixelInterpolate.c \
+	psImageUnbin.c
+
+EXTRA_DIST = imageops.i
+
+pkginclude_HEADERS = \
+	psImageBackground.h \
+	psImageConvolve.h \
+	psImageGeomManip.h \
+	psImageInterpolate.h \
+	psImagePixelExtract.h \
+	psImagePixelManip.h \
+	psImageStats.h \
+	psImageStructManip.h \
+	psImageMaskOps.h \
+	psImageBinning.h \
+	psImageMap.h \
+	psImageMapFit.h \
+	psImagePixelInterpolate.h \
+	psImageUnbin.h
+
+CLEANFILES = *~ *.bb *.bbg *.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/imageops.i
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/imageops.i	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/imageops.i	(revision 22158)
@@ -0,0 +1,8 @@
+/* imageops headers */
+%include "psImageConvolve.h"
+%include "psImageGeomManip.h"
+%include "psImagePixelExtract.h"
+%include "psImagePixelManip.h"
+%include "psImageStats.h"
+%include "psImageStructManip.h"
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageBackground.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageBackground.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageBackground.c	(revision 22158)
@@ -0,0 +1,134 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "psMemory.h"
+#include "psTrace.h"
+#include "psImage.h"
+#include "psVector.h"
+#include "psStats.h"
+#include "psType.h"
+#include "psAssert.h"
+#include "psRandom.h"
+#include "psError.h"
+
+// XXX allow the user to choose the stats method?
+// (SAMPLE_MEAN, CLIPPED_MEAN, ROBUST_MEDIAN, FITTED_MEAN)
+bool psImageBackground(psStats *stats, psVector **sample, const psImage *image, const psImage *mask, psMaskType maskValue, psRandom *rng)
+{
+    PS_ASSERT_IMAGE_NON_NULL(image, NULL);
+    if (mask) {
+        PS_ASSERT_IMAGE_NON_NULL(mask, NULL);
+        PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_U8, NULL);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(mask, image, NULL);
+    }
+    if (stats->options & PS_STAT_ROBUST_QUARTILE) {
+        PS_ASSERT_FLOAT_LARGER_THAN_OR_EQUAL(stats->min, 0.0, NULL);
+        PS_ASSERT_FLOAT_LARGER_THAN_OR_EQUAL(stats->max, 0.0, NULL);
+        PS_ASSERT_FLOAT_LESS_THAN_OR_EQUAL(stats->min, 1.0, NULL);
+        PS_ASSERT_FLOAT_LESS_THAN_OR_EQUAL(stats->max, 1.0, NULL);
+    }
+    PS_ASSERT_INT_NONNEGATIVE(stats->nSubsample, NULL);
+    PS_ASSERT_PTR_NON_NULL(rng, NULL);
+
+    // Size of image
+    long nx = image->numCols;
+    long ny = image->numRows;
+
+    const int Npixels = nx*ny;                // Total number of pixels
+    const int Nsubset = (stats->nSubsample == 0) ? Npixels : PS_MIN(stats->nSubsample, Npixels); // Number of pixels in subset
+
+    psVector *values;                   // Vector containing subsample
+    if (sample) {
+        *sample = psVectorRecycle(*sample, Nsubset, PS_TYPE_F32);
+        values = psMemIncrRefCounter(*sample);
+        values->n = 0;
+    } else {
+        values = psVectorAllocEmpty(Nsubset, PS_TYPE_F32);
+    }
+
+    // Minimum and maximum values
+    float min = values->data.F32[0];
+    float max = values->data.F32[0];
+
+    // select a subset of the image pixels to measure the stats
+    long n = 0;                         // Number of actual pixels in subset
+    for (long i = 0; i < Nsubset; i++) {
+        double frnd = psRandomUniform(rng);
+        int pixel = Npixels * frnd;
+        int ix = pixel % nx;
+        int iy = pixel / nx;
+
+        if (!isfinite(image->data.F32[iy][ix]) || (mask && mask->data.U8[iy][ix] & maskValue)) {
+            continue;
+        }
+
+        float value = image->data.F32[iy][ix];
+        min = PS_MIN(value, min);
+        max = PS_MIN(value, max);
+        values->data.F32[n] = value;
+        n++;
+    }
+    if (n < 0.01*Nsubset) {
+        psLogMsg("psLib.psImageBackground", PS_LOG_INFO,
+                 "Unable to measure image background: too few data points (%ld)", n);
+        psFree(values);
+        return false;
+    }
+
+    values->n = n;
+
+    if (stats->options & PS_STAT_ROBUST_QUARTILE) {
+        // use simple stats code (old verions)
+        // XXX this hack is just for testing, drop when I am happy with the psStats version of the values
+
+        int imin = stats->min * n;
+        int imax = stats->max * n;
+        int npts = imax - imin + 1;
+
+        if (!psVectorSort(values, values)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to sort values.\n");
+            psFree(values);
+            return false;
+        }
+
+        // Subtract the median when we add the numbers, so we don't get numerical problems
+        float median = npts % 2 ? 0.5 * (values->data.F32[npts/2 - 1] + values->data.F32[npts/2]) :
+                       values->data.F32[npts/2];
+        double value = 0;
+        for (long i = imin; (i <= imax) && (i < n); i++) {
+            value += values->data.F32[i] - median;
+        }
+        value = value / npts + median;
+        stats->robustMedian = value;
+        stats->robustUQ = values->data.F32[imax];
+        stats->robustLQ = values->data.F32[imin];
+    } else {
+        if (!psVectorStats (stats, values, NULL, NULL, 0)) {
+            if (psTraceGetLevel("psLib.imageops") >= 5) {
+                FILE *f = fopen ("vector.dat", "w");
+                int fd = fileno(f);
+                p_psVectorPrint (fd, values, "values");
+                fclose (f);
+            }
+            psError(PS_ERR_UNKNOWN, false, "Unable to measure statistics for image background "
+                    "(%dx%d, (row0,col0) = (%d,%d)",
+                    image->numRows, image->numCols, image->row0, image->col0);
+            psFree(values);
+            return false;
+        }
+        if (psTraceGetLevel("psLib.imageops") >= 6) {
+            FILE *f = fopen ("vector.dat", "w");
+            int fd = fileno(f);
+            p_psVectorPrint (fd, values, "values");
+            fclose (f);
+        }
+    }
+
+    psFree(values);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageBackground.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageBackground.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageBackground.h	(revision 22158)
@@ -0,0 +1,37 @@
+/** @file  psImageUnbin.h
+ *
+ *  @brief Functions to determine the image background
+ *
+ *  @author EAM, IfA
+ *
+ *  $Revision: 1.6 $ $Name: not supported by cvs2svn $
+ *  $Date: 2008-01-17 22:07:33 $
+ *  Copyright 2004-2005 IfA, University of Hawaii
+ */
+
+#ifndef PS_IMAGE_BACKGROUND_H
+#define PS_IMAGE_BACKGROUND_H
+
+/// @addtogroup ImageOps Image Operations
+/// @{
+
+#include <psStats.h>
+#include <psImage.h>
+#include <psVector.h>
+#include <psType.h>
+#include <psRandom.h>
+
+// Get the background for an image
+bool psImageBackground(psStats *stats, // desired measurement and options
+                       psVector **sample, // Vector of data used for analysis (buffer), or NULL
+                       const psImage *image, // Image for which to get the background
+                       const psImage *mask, // Mask image
+                       psMaskType maskValue, // Mask pixels which this mask value
+                       psRandom *rng // Random number generator (for pixel selection)
+                      );
+
+/// @}
+#endif // #ifndef PS_IMAGE_BACKGROUND_H
+
+/* the user may supply a psVector ** or NULL to sample.  if a vector is supplied,
+   the user must free the resulting vector */
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageBinning.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageBinning.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageBinning.c	(revision 22158)
@@ -0,0 +1,206 @@
+/** @file  psImageBinning.c
+ *
+ *  @brief Functions to define the binning strategy and to perform image binning / unbinning
+ *  (resampling).
+ *
+ *  @ingroup Image
+ *
+ *  @author Eugene Magnier, IfA
+ *
+ *  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-08 03:10:30 $
+ *
+ *  Copyright 2007 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include "psMemory.h"
+#include "psError.h"
+#include "psAbort.h"
+#include "psAssert.h"
+#include "psRegion.h"
+#include "psImage.h"
+#include "psImageBinning.h"
+
+static void psImageBinningFree(psImageBinning *binning) {
+    return;
+}
+
+psImageBinning *psImageBinningAlloc() {
+    psImageBinning *binning = (psImageBinning*)psAlloc(sizeof(psImageBinning));
+    psMemSetDeallocator(binning, (psFreeFunc)psImageBinningFree);
+
+    return binning;
+}
+
+bool psMemCheckBinning(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) psImageBinningFree);
+}
+
+void psImageBinningSetRuffSize(psImageBinning *binning, psImageBinningAlign align) {
+
+    assert (binning->nXfine > 0);
+    assert (binning->nYfine > 0);
+    assert (binning->nXbin > 0);
+    assert (binning->nYbin > 0);
+
+    // force nXruff*nXbin > nXfine
+    binning->nXruff = binning->nXfine / binning->nXbin;
+    if (binning->nXfine % binning->nXbin) binning->nXruff ++;
+
+    // force nYruff*nYbin > nYfine
+    binning->nYruff = binning->nYfine / binning->nYbin;
+    if (binning->nYfine % binning->nYbin) binning->nYruff ++;
+
+    switch (align) {
+      case PS_IMAGE_BINNING_LEFT:
+        binning->nXoff = 0;
+        binning->nYoff = 0;
+        break;
+      case PS_IMAGE_BINNING_CENTER:
+        binning->nXoff = (binning->nXruff * binning->nXbin - binning->nXfine) / 2;
+        binning->nYoff = (binning->nYruff * binning->nYbin - binning->nYfine) / 2;
+        break;
+      case PS_IMAGE_BINNING_RIGHT:
+        binning->nXoff = (binning->nXruff * binning->nXbin - binning->nXfine);
+        binning->nYoff = (binning->nYruff * binning->nYbin - binning->nYfine);
+        break;
+      default:
+        psAbort ("programming error in %s: impossible case\n", __func__);
+    }
+    return;
+}
+
+void psImageBinningSetFineSize(psImageBinning *binning, psImageBinningAlign align) {
+
+    binning->nXfine = binning->nXruff * binning->nXbin;
+    binning->nYfine = binning->nYruff * binning->nYbin;
+    return;
+}
+
+void psImageBinningSetSkip(psImageBinning *binning, psImage *image)
+{
+    int col0, row0;                     // Offset for image
+    if (image) {
+        col0 = image->col0;
+        row0 = image->row0;
+    } else {
+        col0 = row0 = 0;
+    }
+    psImageBinningSetSkipByOffset(binning, col0, row0);
+    return;
+}
+
+void psImageBinningSetSkipByOffset(psImageBinning *binning, int col0, int row0) {
+
+    binning->nXskip = col0 - binning->nXoff;
+    binning->nYskip = row0 - binning->nYoff;
+    return;
+}
+
+void psImageBinningSetScale(psImageBinning *binning, psImageBinningAlign align) {
+
+    assert (binning->nXfine > 0);
+    assert (binning->nYfine > 0);
+    assert (binning->nXruff > 0);
+    assert (binning->nYruff > 0);
+
+    // force nXruff*nXbin > nXfine
+    binning->nXbin = binning->nXfine / binning->nXruff;
+    if (binning->nXfine % binning->nXruff) binning->nXbin ++;
+
+    // force nYruff*nYbin > nYfine
+    binning->nYbin = binning->nYfine / binning->nYruff;
+    if (binning->nYfine % binning->nYruff) binning->nYbin ++;
+
+    switch (align) {
+      case PS_IMAGE_BINNING_LEFT:
+        binning->nXoff = 0;
+        binning->nYoff = 0;
+        break;
+      case PS_IMAGE_BINNING_CENTER:
+        binning->nXoff = (binning->nXruff * binning->nXbin - binning->nXfine) / 2;
+        binning->nYoff = (binning->nYruff * binning->nYbin - binning->nYfine) / 2;
+        break;
+      case PS_IMAGE_BINNING_RIGHT:
+        binning->nXoff = (binning->nXruff * binning->nXbin - binning->nXfine);
+        binning->nYoff = (binning->nYruff * binning->nYbin - binning->nYfine);
+        break;
+      default:
+        psAbort ("programming error in %s: impossible case\n", __func__);
+    }
+    return;
+}
+
+psRegion psImageBinningSetFineRegion (psImageBinning *binning, psRegion ruffRegion) {
+
+    psRegion fineRegion;
+
+    fineRegion.x0 = ruffRegion.x0 * binning->nXbin;
+    fineRegion.x1 = ruffRegion.x1 * binning->nXbin;
+    fineRegion.y0 = ruffRegion.y0 * binning->nYbin;
+    fineRegion.y1 = ruffRegion.y1 * binning->nYbin;
+    return fineRegion;
+}
+
+psRegion psImageBinningSetRuffRegion (psImageBinning *binning, psRegion fineRegion) {
+
+    psRegion ruffRegion;
+
+    ruffRegion.x0 = fineRegion.x0 / binning->nXbin;
+    ruffRegion.x1 = fineRegion.x1 / binning->nXbin;
+    ruffRegion.y0 = fineRegion.y0 / binning->nYbin;
+    ruffRegion.y1 = fineRegion.y1 / binning->nYbin;
+    return ruffRegion;
+}
+
+
+// convert the fine coordinate to the ruff coordinate
+double psImageBinningGetRuffX (const psImageBinning *binning, const double xFine) {
+
+    PS_ASSERT_INT_POSITIVE(binning->nXbin, NAN);
+    PS_ASSERT_INT_POSITIVE(binning->nYbin, NAN);
+    PS_ASSERT_INT_LESS_THAN_OR_EQUAL(binning->nXskip, binning->nXbin, NAN);
+    PS_ASSERT_INT_LESS_THAN_OR_EQUAL(binning->nYskip, binning->nYbin, NAN);
+
+    double xRuff = (xFine - binning->nXskip)/binning->nXbin;
+    return xRuff;
+}
+double psImageBinningGetRuffY (const psImageBinning *binning, const double yFine) {
+
+    PS_ASSERT_INT_POSITIVE(binning->nXbin, NAN);
+    PS_ASSERT_INT_POSITIVE(binning->nYbin, NAN);
+    PS_ASSERT_INT_LESS_THAN_OR_EQUAL(binning->nXskip, binning->nXbin, NAN);
+    PS_ASSERT_INT_LESS_THAN_OR_EQUAL(binning->nYskip, binning->nYbin, NAN);
+
+    double yRuff = (yFine - binning->nYskip)/binning->nYbin;
+    return yRuff;
+}
+
+// convert the ruff coordinate to the fine coordinate
+double psImageBinningGetFineX (const psImageBinning *binning, const double xRuff) {
+
+    PS_ASSERT_INT_POSITIVE(binning->nXbin, NAN);
+    PS_ASSERT_INT_POSITIVE(binning->nYbin, NAN);
+    PS_ASSERT_INT_LESS_THAN_OR_EQUAL(binning->nXskip, binning->nXbin, NAN);
+    PS_ASSERT_INT_LESS_THAN_OR_EQUAL(binning->nYskip, binning->nYbin, NAN);
+
+    double xFine = xRuff * binning->nXbin + binning->nXskip;
+    return xFine;
+}
+double psImageBinningGetFineY (const psImageBinning *binning, const double yRuff) {
+
+    PS_ASSERT_INT_POSITIVE(binning->nXbin, NAN);
+    PS_ASSERT_INT_POSITIVE(binning->nYbin, NAN);
+    PS_ASSERT_INT_LESS_THAN_OR_EQUAL(binning->nXskip, binning->nXbin, NAN);
+    PS_ASSERT_INT_LESS_THAN_OR_EQUAL(binning->nYskip, binning->nYbin, NAN);
+
+    double yFine = yRuff * binning->nYbin + binning->nYskip;
+    return yFine;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageBinning.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageBinning.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageBinning.h	(revision 22158)
@@ -0,0 +1,62 @@
+/** @file  psImageBinning.c
+ *
+ *  @brief Functions to define the binning strategy and to perform image binning / unbinning
+ *  (resampling).
+ *
+ *  @ingroup Image
+ *
+ *  @author Eugene Magnier, IfA
+ *
+ *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-10-25 20:35:50 $
+ *
+ *  Copyright 2007 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PS_IMAGE_BINNING_H
+#define PS_IMAGE_BINNING_H
+
+/// @addtogroup ImageOps Image Operations
+/// @{
+
+// description of the image binning relationship between a binned and an unbinned
+// image. binning is defined for a specific input size and output image size.
+typedef struct {
+    int nXfine; 			// width of the hi-res image
+    int nYfine;				// height of the hi-res image
+    int nXruff; 			// width of the lo-res image 
+    int nYruff;				// height of the lo-res image
+    int nXbin;				// X binning factor (~ nXfine/nXruff)
+    int nYbin;				// Y binning factor (~ nYfine/nYruff)
+    int nXoff;				// offset in fine pixels to start of ruff 0 pixel (x_fine - nXoff) / nXbin = x_ruff
+    int nYoff;				// offset in fine pixels to start of ruff 0 pixel (x_fine - nXoff) / nXbin = x_ruff
+    int nXskip;				// offset in fine pixels from start of fine parent 0 pixel to ruff 0 pixel (nXskip = col0 - nXoff)
+    int nYskip;				// offset in fine pixels from start of fine parent 0 pixel to ruff 0 pixel (nYskip = row0 - nYoff)
+} psImageBinning;
+
+typedef enum {
+    PS_IMAGE_BINNING_LEFT,
+    PS_IMAGE_BINNING_CENTER,
+    PS_IMAGE_BINNING_RIGHT,
+} psImageBinningAlign;
+
+
+psImageBinning *psImageBinningAlloc() PS_ATTR_MALLOC;
+bool psMemCheckBinning(psPtr ptr);
+
+void psImageBinningSetRuffSize(psImageBinning *binning, psImageBinningAlign align);
+void psImageBinningSetFineSize(psImageBinning *binning, psImageBinningAlign align);
+void psImageBinningSetScale(psImageBinning *binning, psImageBinningAlign align);
+void psImageBinningSetSkip(psImageBinning *binning, psImage *image);
+void psImageBinningSetSkipByOffset(psImageBinning *binning, int col0, int row0);
+
+psRegion psImageBinningSetFineRegion (psImageBinning *binning, psRegion ruffRegion);
+psRegion psImageBinningSetRuffRegion (psImageBinning *binning, psRegion fineRegion);
+
+double psImageBinningGetRuffX (const psImageBinning *binning, const double xFine);
+double psImageBinningGetRuffY (const psImageBinning *binning, const double yFine);
+double psImageBinningGetFineX (const psImageBinning *binning, const double xRuff);
+double psImageBinningGetFineY (const psImageBinning *binning, const double yRuff);
+
+/// @}
+#endif // #ifndef PS_IMAGE_GEOM_MANIP_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageConvolve.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageConvolve.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageConvolve.c	(revision 22158)
@@ -0,0 +1,872 @@
+/// @file  psImageConvolve.c
+///
+/// @brief Contains FFT transform related functions for psImage.
+///
+/// @author Robert DeSonia, MHPCC
+/// @author Paul Price, IfA
+/// @author Eugene Magnier, IfA
+///
+/// @version $Revision: 1.71 $ $Name: not supported by cvs2svn $
+/// @date $Date: 2008-05-24 23:01:42 $
+///
+/// Copyright 2004-2007 Institute for Astronomy, University of Hawaii
+///
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <math.h>
+#include "psAbort.h"
+#include "psMemory.h"
+#include "psLogMsg.h"
+#include "psError.h"
+#include "psAssert.h"
+#include "psScalar.h"
+#include "psBinaryOp.h"
+#include "psImageFFT.h"
+#include "psImageStructManip.h"
+#include "psImagePixelManip.h"
+#include "psTrace.h"
+
+#include "psImageConvolve.h"
+
+static void kernelFree(psKernel *kernel)
+{
+    if (kernel) {
+        psFree(kernel->image);
+        psFree(kernel->p_kernelRows);
+    }
+    return;
+}
+
+// Set up indirections, so we can refer to kernel->kernel[-1][-3] for the (-1,-1) element, instead of
+// kernel->image[kernel->yMax - kernel->yMin + 1][kernel->yMax - kernel->yMin + 3] (yuk!).
+static void kernelRedirects(psKernel *kernel, // Kernel for which to set up the redirects
+                            int numRows // Number of rows
+    )
+{
+    int xMin = kernel->xMin, yMin = kernel->yMin; // Minimum values
+
+    kernel->p_kernelRows = psAlloc(sizeof(float*)*numRows);
+    for (int i = 0; i < numRows; i++) {
+        kernel->p_kernelRows[i] = kernel->image->data.PS_TYPE_KERNEL_DATA[i] - xMin;
+    }
+    kernel->kernel = kernel->p_kernelRows - yMin;
+    return;
+}
+
+psKernel *psKernelAlloc(int xMin, int xMax, int yMin, int yMax)
+{
+    // Check the inputs to make sure max > min; if not, switch.
+    // following is explicitly spelled out in the SDRS as a requirement
+    if (yMin > yMax) {
+        psWarning("Specified yMin, %d, was greater than yMax, %d.  Values swapped.",
+                 yMin, yMax);
+
+        int temp = yMin;
+        yMin = yMax;
+        yMax = temp;
+    }
+    if (xMin > xMax) {
+        psWarning("Specified xMin, %d, was greater than xMax, %d.  Values swapped.",
+                 xMin, xMax);
+
+        int temp = xMin;
+        xMin = xMax;
+        xMax = temp;
+    }
+
+    int numRows = yMax - yMin + 1;      // Number of rows for kernel image
+    int numCols = xMax - xMin + 1;      // Number of columns for kernel image
+
+    psKernel *kernel = psAlloc(sizeof(psKernel)); // The kernel, to be returned
+    psMemSetDeallocator(kernel,(psFreeFunc)kernelFree);
+
+    kernel->xMin = xMin;
+    kernel->xMax = xMax;
+    kernel->yMin = yMin;
+    kernel->yMax = yMax;
+    kernel->image = psImageAlloc(numCols, numRows, PS_TYPE_KERNEL);
+    psImageInit(kernel->image, 0.0);
+
+    kernelRedirects(kernel, numRows);
+
+    return kernel;
+}
+
+psKernel *psKernelAllocFromImage(psImage *image, int x0, int y0)
+{
+    psKernel *kernel = psAlloc(sizeof(psKernel)); // The kernel, to be returned
+    psMemSetDeallocator(kernel,(psFreeFunc)kernelFree);
+
+    int numCols = image->numCols, numRows = image->numRows; // Size of image
+
+    kernel->xMin = - x0;
+    kernel->xMax = numCols - 1 - x0;
+    kernel->yMin = - y0;
+    kernel->yMax = numRows - 1 - y0;
+    kernel->image = psMemIncrRefCounter(image);
+
+    kernelRedirects(kernel, numRows);
+
+    return kernel;
+}
+
+bool psMemCheckKernel(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)kernelFree );
+}
+
+
+psKernel *psKernelGenerate(const psVector *tShifts,
+                           const psVector *xShifts,
+                           const psVector *yShifts,
+                           float totalTime,
+                           bool xyRelative)
+{
+    PS_ASSERT_VECTOR_NON_NULL(tShifts, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(xShifts, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(yShifts, NULL);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(tShifts, xShifts, NULL);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(tShifts, yShifts, NULL);
+    PS_ASSERT_VECTOR_TYPE(tShifts, PS_TYPE_F32, NULL);
+    PS_ASSERT_VECTOR_TYPE(xShifts, PS_TYPE_S32, NULL);
+    PS_ASSERT_VECTOR_TYPE(yShifts, PS_TYPE_S32, NULL);
+
+    if (isnan(totalTime)) {
+        // It's more expensive to check for NAN than 0.0
+        totalTime = 0.0;
+    }
+
+    // If there are no shifts, the kernel is just a 1 at 0,0
+    long num = tShifts->n;              // Number of shifts
+    if (num == 0) {
+        psKernel *kernel = psKernelAlloc(0,0,0,0);
+        kernel->kernel[0][0] = 1;
+        return kernel;
+    }
+
+    // Get dimensions and scaling
+    int xMin, xMax, yMin, yMax;         // Range of values for kernel
+    int xLast, yLast;                   // Last location, for relative shifts
+    float tSum = tShifts->data.F32[0];   // Sum of the times
+    xLast = xMin = xMax = xShifts->data.S32[0];
+    yLast = yMin = yMax = yShifts->data.S32[0];
+    int x0, y0;                         // Final location; everything is relative to this
+    x0 = xShifts->data.S32[num - 1];
+    y0 = yShifts->data.S32[num - 1];
+    for (long i = 1; i < num; i++) {
+        int x = xShifts->data.S32[i] - x0; // x position in kernel
+        int y = yShifts->data.S32[i] - y0; // y position in kernel
+        if (xyRelative) {
+            x += xLast;
+            y += yLast;
+            xLast = x;
+            yLast = y;
+        }
+        if (x < xMin) {
+            xMin = x;
+        }
+        if (x > xMax) {
+            xMax = x;
+        }
+        if (y < yMin) {
+            yMin = y;
+        }
+        if (y > yMax) {
+            yMax = y;
+        }
+
+        if (totalTime <= 0) {
+            tSum += tShifts->data.F32[i];
+        }
+    }
+
+    psTrace("psLib.imageops", 5, "Kernel range: %d:%d,%d:%d\n", xMin, xMax, yMin, yMax);
+
+    if (totalTime > 0) {
+        // Then the total time is simply the final value
+        // NB: We assume the counter starts at zero!
+        tSum = totalTime;
+    }
+
+    // One more pass through to set the kernel
+    psKernel *kernel = psKernelAlloc(xMin, xMax, yMin, yMax); // The kernel
+    xLast = xShifts->data.S32[0];
+    yLast = yShifts->data.S32[0];
+    float tLast = 0.0;                  // Last value for t
+    for (int i = 0; i < num; i++) {
+        int x = xShifts->data.S32[i] - x0; // x position in kernel
+        int y = yShifts->data.S32[i] - y0; // y position in kernel
+        if (xyRelative) {
+            x += xLast;
+            y += yLast;
+            xLast = x;
+            yLast = y;
+        }
+        float t = tShifts->data.F32[i];
+        if (totalTime > 0) {
+            t -= tLast;
+            tLast = tShifts->data.F32[i];
+        }
+
+        kernel->kernel[y][x] += t;
+    }
+
+    // Normalise the kernel by the total time (kernel sum should be unity)
+    psBinaryOp(kernel->image, kernel->image, "*", psScalarAlloc(1.0 / tSum, PS_TYPE_F32));
+
+    return kernel;
+}
+
+psImage *psImageConvolveDirect(psImage *out,
+                               const psImage *in,
+                               const psKernel *kernel)
+{
+    PS_ASSERT_IMAGE_NON_NULL(in, NULL);
+    if (in->type.type != PS_TYPE_S32 && in->type.type != PS_TYPE_F32 && in->type.type != PS_TYPE_F64) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                "Unallowable operation: psImage %s is not of type S32 or F{32,64}.", "in");
+        return(NULL);
+    }
+    PS_ASSERT_PTR_NON_NULL(kernel, NULL);
+    PS_ASSERT_PTR_NON_NULL(kernel->kernel, NULL);
+
+    // Pull out kernel parameters, for convenience
+    int xMin = kernel->xMin;
+    int xMax = kernel->xMax;
+    int yMin = kernel->yMin;
+    int yMax = kernel->yMax;
+    float **kernelData = kernel->kernel;
+
+    int numRows = in->numRows;          // Number of rows
+    int numCols = in->numCols;          // Number of columns
+
+#if 1
+
+    // This is the usual way of doing the convolution, but it wastes time if there's a large number of zero
+    // pixels in the kernel.
+#define SPATIAL_CONVOLVE_CASE(TYPE) \
+    case PS_TYPE_##TYPE: { \
+        ps##TYPE **inData = in->data.TYPE; /* Dereference input data */ \
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_##TYPE); \
+        for (int row = 0; row < numRows; row++) { \
+            ps##TYPE *outRow = out->data.TYPE[row]; \
+            int kRowMin = PS_MAX(yMin, row + 1 - numRows); \
+            int kRowMax = PS_MIN(yMax, row); \
+            for (int col = 0; col < numCols; col++) { \
+                int kColMin = PS_MAX(xMin, col + 1 - numCols); \
+                int kColMax = PS_MIN(xMax, col); \
+                ps##TYPE pixel = 0.0; \
+                for (int kRow = kRowMin; kRow <= kRowMax; kRow++) { \
+                    for (int kCol = kColMin; kCol <= kColMax; kCol++) { \
+                        pixel += kernelData[kRow][kCol] * inData[row - kRow][col - kCol]; \
+                    } \
+                } \
+                outRow[col] = pixel; \
+            } \
+        } \
+    } \
+    break;
+
+#else
+
+    // This turns the convolution inside-out, allowing us to skip kernel pixels that have no contribution.
+#define SPATIAL_CONVOLVE_CASE(TYPE) \
+    case PS_TYPE_##TYPE: { \
+        ps##TYPE **inData = in->data.TYPE; /* Dereference input data */ \
+        out = psImageRecycle(out, numCols, numRows, PS_TYPE_##TYPE); \
+        psImageInit(out, 0.0); \
+        for (int ky = yMin; ky <= yMax; ky++) { \
+            for (int kx = xMin; kx <= xMax; kx++) { \
+                float kValue = kernelData[ky][kx]; /* Kernel value */ \
+                if (kValue == 0.0) { \
+                    continue; \
+                } \
+                for (int y = PS_MAX(ky, 0); y < PS_MIN(numRows, numRows + ky); y++) { \
+                    for (int x = PS_MAX(kx, 0); x < PS_MIN(numCols, numCols + kx); x++) { \
+                        out->data.TYPE[y][x] += kValue * inData[y - ky][x - kx]; \
+                    } \
+                } \
+            } \
+        } \
+    } \
+    break;
+
+#endif
+
+    switch (in->type.type) {
+        SPATIAL_CONVOLVE_CASE(S32);
+        SPATIAL_CONVOLVE_CASE(F32);
+        SPATIAL_CONVOLVE_CASE(F64);
+      default:
+        psAbort("Should never get here: bad type that was asserted on previously.");
+    }
+
+    return out;
+}
+
+psImage *psImageConvolveMaskDirect(psImage *out, const psImage *mask, psMaskType maskVal,
+                                   psMaskType setVal, int xMin, int xMax, int yMin, int yMax)
+{
+    PS_ASSERT_IMAGE_NON_NULL(mask, NULL);
+    PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, NULL);
+    if (out == mask && ((maskVal & setVal) || !setVal)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Can't convolve mask in-place if values to set contains values to convolve.");
+        return NULL;
+    }
+
+    if (yMin > yMax) {
+        psWarning("Specified yMin, %d, was greater than yMax, %d.  Values swapped.",
+                 yMin, yMax);
+
+        int temp = yMin;
+        yMin = yMax;
+        yMax = temp;
+    }
+    if (xMin > xMax) {
+        psWarning("Specified xMin, %d, was greater than xMax, %d.  Values swapped.",
+                 xMin, xMax);
+
+        int temp = xMin;
+        xMin = xMax;
+        xMax = temp;
+    }
+
+    int numRows = mask->numRows;        // Number of rows
+    int numCols = mask->numCols;        // Number of columns
+
+    if (!out) {
+        // Propagate the non-masked values
+        out = (psImage*)psBinaryOp(NULL, (const psPtr)mask, "&", psScalarAlloc(~maskVal, PS_TYPE_MASK));
+    }
+
+    // Dereference mask images
+    psMaskType **maskData = mask->data.PS_TYPE_MASK_DATA;
+    psMaskType **outData = out->data.PS_TYPE_MASK_DATA;
+
+    if (setVal) {
+        // Grow any pixels matching maskVal, setting setVal
+        for (int row = 0; row < numRows; row++) {
+            for (int col = 0; col < numCols; col++) {
+                if (maskData[row][col] & maskVal) {
+                    for (int kRow = PS_MAX(yMin, -row); kRow <= PS_MIN(yMax, numRows - row - 1); kRow++) {
+                        for (int kCol = PS_MAX(xMin, -col); kCol <= PS_MIN(xMax, numCols - col - 1); kCol++) {
+                            outData[row + kRow][col + kCol] |= setVal;
+                        }
+                    }
+                }
+            }
+        }
+    } else {
+        // Each pixel receives any maskVal bits set within the convolution window
+        for (int row = 0; row < numRows; row++) {
+            for (int col = 0; col < numCols; col++) {
+                psMaskType pixel = outData[row][col]; // Pixel value to set
+                if (pixel & maskVal) {
+                    // Already done this one
+                    continue;
+                }
+                for (int kRow = PS_MAX(yMin, -row); kRow <= PS_MIN(yMax, numRows - row - 1); kRow++) {
+                    for (int kCol = PS_MAX(xMin, -col); kCol <= PS_MIN(xMax, numCols - col - 1); kCol++) {
+                        pixel |= maskData[row][col] & maskVal;
+                    }
+                }
+                outData[row][col] = pixel;
+            }
+        }
+    }
+
+    return out;
+}
+
+
+psImage *psImageConvolveMaskFFT(psImage *out, const psImage *mask, psMaskType maskVal,
+                                psMaskType setVal, int xMin, int xMax, int yMin, int yMax, float thresh)
+{
+    PS_ASSERT_IMAGE_NON_NULL(mask, NULL);
+    PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, NULL);
+    PS_ASSERT_FLOAT_LARGER_THAN(thresh, 0.0, NULL);
+    PS_ASSERT_FLOAT_LESS_THAN(thresh, 1.0, NULL);
+    if (out == mask && (maskVal & setVal)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Can't convolve mask in-place if values to set contains values to convolve.");
+        return NULL;
+    }
+
+    if (yMin > yMax) {
+        psWarning("Specified yMin, %d, was greater than yMax, %d.  Values swapped.",
+                 yMin, yMax);
+
+        int temp = yMin;
+        yMin = yMax;
+        yMax = temp;
+    }
+    if (xMin > xMax) {
+        psWarning("Specified xMin, %d, was greater than xMax, %d.  Values swapped.",
+                 xMin, xMax);
+
+        int temp = xMin;
+        xMin = xMax;
+        xMax = temp;
+    }
+
+    int numRows = mask->numRows, numCols = mask->numCols; // Size of image
+
+    psImage *onoff = psImageAlloc(numCols, numRows, PS_TYPE_F32); // Pixels on or off
+    psImageInit(onoff, 0);
+    for (int y = 0; y < numRows; y++) {
+        for (int x = 0; x < numCols; x++) {
+            if (mask->data.PS_TYPE_MASK_DATA[y][x] & maskVal) {
+                onoff->data.F32[y][x] = 1.0;
+            }
+        }
+    }
+
+    psKernel *kernel = psKernelAlloc(xMin, xMax, yMin, yMax);
+    psImageInit(kernel->image, 1.0);
+    psImage *convolved = psImageConvolveFFT(NULL, onoff, NULL, 0, kernel);
+    psFree(onoff);
+    psFree(kernel);
+    if (!convolved) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to convolve mask.");
+        return NULL;
+    }
+
+    if (!setVal) {
+        setVal = maskVal;
+    }
+
+    if (!out) {
+        out = psImageAlloc(numCols, numRows, PS_TYPE_MASK);
+    }
+    for (int y = 0; y < numRows; y++) {
+        for (int x = 0; x < numCols; x++) {
+            out->data.PS_TYPE_MASK_DATA[y][x] = (convolved->data.F32[y][x] >= thresh) ?
+                (mask->data.PS_TYPE_MASK_DATA[y][x] | setVal) : mask->data.PS_TYPE_MASK_DATA[y][x];
+        }
+    }
+
+    psFree(convolved);
+
+    return out;
+}
+
+bool psImageSmooth (psImage *image,
+                    double  sigma,
+                    double  Nsigma)
+{
+    PS_ASSERT_IMAGE_NON_NULL(image, NULL);
+
+    // relevant terms
+    int Nrange = sigma*Nsigma + 0.5;    // Number of pixels either side for convolution kernel
+    int Npixel = 2*Nrange + 1;          // Total number of pixels in convolution kernel
+    int Nx = image->numCols;            // Number of columns
+    int Ny = image->numRows;            // Number of rows
+
+    #define IMAGESMOOTH_CASE(TYPE) \
+case PS_TYPE_##TYPE: { \
+        /* generate normalized gaussian */ \
+        psVector *gaussnorm = psVectorAlloc(Npixel, PS_TYPE_##TYPE); \
+        { \
+            double sum = 0.0; \
+            double factor = -0.5/(sigma*sigma); \
+            for (int i = -Nrange; i < Nrange + 1; i++) { \
+                gaussnorm->data.TYPE[i+Nrange] = exp(factor*i*i); \
+                sum += gaussnorm->data.TYPE[i+Nrange]; \
+            } \
+            for (int i = -Nrange; i < Nrange + 1; i++) { \
+                gaussnorm->data.TYPE[i+Nrange] /= sum; \
+            } \
+        } \
+        ps##TYPE *gauss = &gaussnorm->data.TYPE[Nrange]; \
+        \
+        /* Smooth in X direction */ \
+        { \
+            psVector *calculation = psVectorAlloc(Nx, PS_TYPE_##TYPE); \
+            for (int j = 0; j < Ny; j++) { \
+                ps##TYPE *vi = image->data.TYPE[j]; \
+                ps##TYPE *vo = calculation->data.TYPE; \
+                int xMax = PS_MIN(Nrange, Nx); \
+                int convRange = PS_MIN(Nrange + 1, Nx); \
+                /* Smooth first Nrange pixels, with renorm */ \
+                for (int i = 0; i < xMax; i++, vi++, vo++) { \
+                    ps##TYPE *vr = vi - i; \
+                    ps##TYPE *vg = gauss - i; \
+                    double g = 0.0; \
+                    double s = 0.0; \
+                    for (int n = -i; n < convRange; n++, vr++, vg++) { \
+                        s += *vg * *vr; \
+                        g += *vg; \
+                    } \
+                    *vo = s / g; \
+                } \
+                /* If that's all the pixels we have, then we're done already */ \
+                if (Nx > Nrange) { \
+                    /* Smooth middle pixels */ \
+                    for (int i = Nrange; i < Nx - Nrange; i++, vi++, vo++) { \
+                        ps##TYPE *vr = vi - Nrange; \
+                        ps##TYPE *vg = gauss - Nrange; \
+                        double s = 0; \
+                        for (int n = -Nrange; n < Nrange + 1; n++, vr++, vg++) { \
+                            s += *vg * *vr; \
+                        } \
+                        *vo = s; \
+                    } \
+                    /* Smooth last Nrange pixels, with renorm */ \
+                    /* XXX does this miss the last column? */ \
+                    for (int i = Nx - Nrange; i < Nx; i++, vi++, vo++) { \
+                        ps##TYPE *vr = vi - Nrange; \
+                        ps##TYPE *vg = gauss - Nrange; \
+                        double g = 0.0; \
+                        double s = 0.0; \
+                        for (int n = -Nrange; n < Nx - i; n++, vr++, vg++) { \
+                            s += *vg * *vr; \
+                            g += *vg; \
+                        } \
+                        *vo = s / g; \
+                    } \
+                } \
+                memcpy(image->data.TYPE[j], calculation->data.TYPE, Nx*sizeof(ps##TYPE)); \
+            } \
+            psFree(calculation); \
+        } \
+        \
+        /* Smooth in Y direction */ \
+        psArray *rows = psArrayAlloc(Nrange); \
+        /* Smooth the first Nrange pixels, with renorm */ \
+        int yMax = PS_MIN(Nrange, Ny); \
+        int convRange = PS_MIN(Nrange + 1, Ny); \
+        for (int j = 0; j < yMax; j++) { \
+            psVector *calculation = psVectorAlloc(Nx, PS_TYPE_##TYPE); \
+            /* Zero the output row */ \
+            memset(calculation->data.TYPE, 0, Nx*sizeof(ps##TYPE)); \
+            double sum = 0.0; \
+            for (int n = -j; n < convRange; n++) { sum += gauss[n]; } \
+            for (int n = -j; n < convRange; n++) { \
+                ps##TYPE *vi = image->data.TYPE[j+n]; \
+                ps##TYPE *vo = calculation->data.TYPE; \
+                double g = gauss[n] / sum; \
+                for (int i = 0; i < Nx; i++, vi++, vo++) { \
+                    *vo += *vi * g; \
+                } \
+            } \
+            /* Save output rows on temp array of rows */ \
+            rows->data[j] = calculation; \
+        } \
+        if (Ny < Nrange) { \
+            /* Need to save the first bit, then we're done */ \
+            for (int j = 0; j < Ny; j++) {  \
+                psVector *save = rows->data[j]; \
+                memcpy(image->data.TYPE[j], save->data.TYPE, Nx*sizeof(ps##TYPE)); \
+            } \
+        } else { \
+            /* Smooth middle pixels */ \
+            psVector *calculation = psVectorAlloc(Nx, PS_TYPE_##TYPE); \
+            for (int j = Nrange; j < Ny - Nrange; j++) { \
+                memset(calculation->data.TYPE, 0, Nx*sizeof(ps##TYPE)); \
+                for (int n = -Nrange; n < Nrange + 1; n++) { \
+                    ps##TYPE *vi = image->data.TYPE[j+n]; \
+                    ps##TYPE *vo = calculation->data.TYPE; \
+                    double g = gauss[n]; \
+                    for (int i = 0; i < Nx; i++, vi++, vo++) { \
+                        *vo += *vi * g; \
+                    } \
+                } \
+                /* Write the output row */ \
+                int Nr = j % Nrange; \
+                psVector *save = rows->data[Nr]; \
+                memcpy(image->data.TYPE[j-Nrange], save->data.TYPE, Nx*sizeof(ps##TYPE)); \
+                /* Juggle the pointers, so that next run we use the one we just wrote */ \
+                rows->data[Nr] = calculation; \
+                calculation = save; \
+            } \
+            /* Smooth last Nrange pixels, with renorm */ \
+            for (int j = Ny - Nrange; j < Ny; j++) { \
+                /* save the Nrange-offset output row, then zero */ \
+                memset(calculation->data.TYPE, 0, Nx*sizeof(ps##TYPE)); \
+                double sum = 0.0; \
+                for (int n = -Nrange; n < Ny - j; n++) { sum += gauss[n]; } \
+                for (int n = -Nrange; n < Ny - j; n++) { \
+                    ps##TYPE *vi = image->data.TYPE[j+n]; \
+                    ps##TYPE *vo = calculation->data.TYPE; \
+                    double g = gauss[n] / sum; \
+                    for (int i = 0; i < Nx; i++, vi++, vo++) { \
+                        *vo += *vi * g; \
+                    } \
+                } \
+                /* Write the output row */ \
+                int Nr = j % Nrange; \
+                psVector *save = rows->data[Nr]; \
+                memcpy(image->data.TYPE[j-Nrange], save->data.TYPE, Nx*sizeof(ps##TYPE)); \
+                /* Juggle the pointers, so that next run we use the one we just wrote */ \
+                rows->data[Nr] = calculation; \
+                calculation = save; \
+            } \
+            psFree(calculation); \
+            /* Write the remaining rows */ \
+            for (int j = Ny; j < Ny + Nrange; j++) {  \
+                int Nr = j % Nrange; \
+                psVector *save = rows->data[Nr]; \
+                memcpy(image->data.TYPE[j-Nrange], save->data.TYPE, Nx*sizeof(ps##TYPE)); \
+            } \
+        } \
+        psFree(rows); \
+        psFree(gaussnorm); \
+        break; \
+    }
+
+    switch (image->type.type) {
+        IMAGESMOOTH_CASE(F32);
+        IMAGESMOOTH_CASE(F64);
+    default: {
+            char *typeStr;
+            PS_TYPE_NAME(typeStr,image->type.type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    _("Specified psImage type, %s, is not supported."),
+                    typeStr);
+            return false;
+        }
+    }
+    return true;
+}
+
+bool psImageSmoothMaskF32 (psImage *image,
+                           psImage *mask,
+                           psMaskType maskVal,
+                           double  sigma,
+                           double  Nsigma)
+{
+    PS_ASSERT_IMAGE_NON_NULL(image, NULL);
+    PS_ASSERT_IMAGE_NON_NULL(mask, NULL);
+
+    // relevant terms
+    int Nrange = sigma*Nsigma + 0.5;    // Number of pixels either side for convolution kernel
+    int Npixel = 2*Nrange + 1;          // Total number of pixels in convolution kernel
+    int Nx = image->numCols;            // Number of columns
+    int Ny = image->numRows;            // Number of rows
+
+    /* generate normalized gaussian */
+    psVector *gaussnorm = psVectorAlloc(Npixel, PS_TYPE_F32);
+    {
+        double sum = 0.0;
+        double factor = -0.5/(sigma*sigma);
+        for (int i = -Nrange; i < Nrange + 1; i++) {
+            gaussnorm->data.F32[i+Nrange] = exp(factor*i*i);
+            sum += gaussnorm->data.F32[i+Nrange];
+        }
+        for (int i = -Nrange; i < Nrange + 1; i++) {
+            gaussnorm->data.F32[i+Nrange] /= sum;
+        }
+    }
+    psF32 *gauss = &gaussnorm->data.F32[Nrange];
+
+    /** Smooth in X direction **/
+    psVector *calculation = psVectorAlloc(Nx, PS_TYPE_F32);
+    for (int j = 0; j < Ny; j++) {
+        psU8  *vm = mask->data.U8[j];
+        psF32 *vi = image->data.F32[j];
+        psF32 *vo = calculation->data.F32;
+        // loop over all pixels in the row
+        for (int i = 0; i < Nx; i++, vi++, vo++, vm++) {
+            int offset = PS_MIN (i, Nrange);
+            psU8  *sm = vm - offset;
+            psF32 *si = vi - offset;
+            psF32 *sg = gauss - offset;
+            double g = 0.0;
+            double s = 0.0;
+            // loop over all valid pixels in the smoothing kernel
+            int xMin = PS_MAX (i - Nrange, 0);
+            int xMax = PS_MIN (i + Nrange + 1, Nx);
+            for (int n = xMin; n < xMax; n++, sm++, si++, sg++) {
+                if (*sm & maskVal)
+                    continue;
+                s += *sg * *si;
+                g += *sg;
+            }
+            *vo = (g > 0.25) ? s / g : NAN;
+        }
+        memcpy(image->data.F32[j], calculation->data.F32, Nx*sizeof(psF32));
+    }
+    psFree(calculation);
+
+    // XXX test
+    if (0) {
+        psFree(gaussnorm);
+        return true;
+    }
+
+    /** Smooth in Y direction  **/
+    // allocate and save Nrange extra row vectors for storage. these will be
+    // written over the output rows only after we are Nrange rows beyond them
+    int Nsave = Nrange + 1;
+    psArray *rows = psArrayAlloc(Nsave);
+    for (int i = 0; i < Nsave; i++) {
+        rows->data[i] = psVectorAlloc(Nx, PS_TYPE_F32);
+    }
+
+    psVector *outsum = psVectorAlloc(Nx, PS_TYPE_F32);
+    for (int j = 0; j < Ny; j++) {
+        psVector *output = rows->data[j % Nsave];
+        memset (output->data.F32, 0, Nx*sizeof(psF32));
+        memset (outsum->data.F32, 0, Nx*sizeof(psF32));
+        int yMin = PS_MAX (j - Nrange, 0);
+        int yMax = PS_MIN (j + Nrange + 1, Ny);
+        for (int n = yMin; n < yMax; n++) {
+            psU8  *vm = mask->data.U8[n];
+            psF32 *vi = image->data.F32[n];
+            psF32 *vo = output->data.F32;
+            psF32 *vs = outsum->data.F32;
+            double g = gauss[n - j];
+            for (int i = 0; i < Nx; i++, vi++, vo++, vm++, vs++) {
+                if (*vm & maskVal) continue;
+                if (!isfinite(*vi)) continue;
+                *vo += *vi * g;
+                *vs += g;
+            }
+        }
+        // renormalize the row
+        psF32 *vo = output->data.F32;
+        psF32 *vs = outsum->data.F32;
+        for (int i = 0; i < Nx; i++, vo++, vs++) {
+            *vo = (*vs > 0.25) ? *vo / *vs : NAN;
+        }
+
+        // Write the output row
+        if (j - Nrange >= 0) {
+            int Nout = (j - Nrange) % Nsave;
+            psVector *save = rows->data[Nout];
+            memcpy(image->data.F32[j-Nrange], save->data.F32, Nx*sizeof(psF32));
+        }
+    }
+
+    // Write the remaining output rows
+    for (int j = PS_MAX(0, Ny - Nrange); j < Ny; j++) {
+        psVector *save = rows->data[j % Nsave];
+        memcpy(image->data.F32[j], save->data.F32, Nx*sizeof(psF32));
+    }
+    psFree(rows);
+    psFree(outsum);
+    psFree(gaussnorm);
+    return true;
+}
+
+
+
+
+psImage *psImageConvolveMask(psImage *out, const psImage *mask, psMaskType maskVal,
+                             psMaskType setVal, int xMin, int xMax, int yMin, int yMax)
+{
+    PS_ASSERT_IMAGE_NON_NULL(mask, NULL);
+    PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, NULL);
+    if (out) {
+        PS_ASSERT_IMAGE_NON_NULL(out, NULL);
+        PS_ASSERT_IMAGE_TYPE(out, PS_TYPE_MASK, NULL);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(out, mask, NULL);
+        if (out == mask && ((maskVal & setVal) || !setVal)) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Can't convolve mask in-place if values to set contains values to convolve.");
+            return NULL;
+        }
+    }
+
+    if (yMin > yMax) {
+        psWarning("Specified yMin, %d, was greater than yMax, %d.  Values swapped.",
+                 yMin, yMax);
+
+        int temp = yMin;
+        yMin = yMax;
+        yMax = temp;
+    }
+    if (xMin > xMax) {
+        psWarning("Specified xMin, %d, was greater than xMax, %d.  Values swapped.",
+                 xMin, xMax);
+
+        int temp = xMin;
+        xMin = xMax;
+        xMax = temp;
+    }
+
+    int numRows = mask->numRows;        // Number of rows
+    int numCols = mask->numCols;        // Number of columns
+
+    // Propagate the non-masked values
+    out = (psImage*)psBinaryOp(out, (const psPtr)mask, "&", psScalarAlloc(~setVal, PS_TYPE_MASK));
+
+    if (!setVal) {
+        setVal = maskVal;
+    }
+
+    psImage *conv = psImageAlloc(numCols, numRows, PS_TYPE_MASK); // Temporary convolved image
+    psImageInit(conv, 0);
+
+    // Dereference mask images
+    psMaskType **maskData = mask->data.PS_TYPE_MASK_DATA;
+    psMaskType **convData = conv->data.PS_TYPE_MASK_DATA;
+    psMaskType **outData = out->data.PS_TYPE_MASK_DATA;
+
+    // Since we're just masking everything inside a square, it's separable
+    for (int y = 0; y < numRows; y++) {
+        int min = 0, max = 0;           // Minimum and maximum points to mask
+        bool masking = false;           // Currently masking?
+        for (int x = 0; x < numCols; x++) {
+            if (maskData[y][x] & maskVal) {
+                if (!masking) {
+                    masking = true;
+                    min = x + xMin;
+                    max = x + xMax;
+                } else {
+                    max++;
+                }
+            } else if (masking) {
+                // Do the masking
+                masking = false;
+                min = PS_MAX(0, min);
+                max = PS_MIN(numCols - 1, max);
+                memset(&convData[y][min], 0xff, (max - min + 1) * PSELEMTYPE_SIZEOF(PS_TYPE_MASK));
+            }
+        }
+        if (masking) {
+            // Mask from the minimum to the end of the row
+            min = PS_MAX(0, min);
+            memset(&convData[y][min], 0xff, (numCols - min) * PSELEMTYPE_SIZEOF(PS_TYPE_MASK));
+        }
+    }
+    for (int x = 0; x < numCols; x++) {
+        int min = 0, max = 0;           // Minimum and maximum points to mask
+        bool masking = false;           // Currently masking?
+        for (int y = 0; y < numRows; y++) {
+            if (convData[y][x]) {
+                if (!masking) {
+                    masking = true;
+                    min = y + yMin;
+                    max = y + yMax;
+                } else {
+                    max++;
+                }
+            } else if (masking) {
+                // Do the masking
+                masking = false;
+                min = PS_MAX(0, min);
+                max = PS_MIN(numRows - 1, max);
+                for (int i = min; i <= max; i++) {
+                    outData[i][x] |= setVal;
+                }
+            }
+        }
+        if (masking) {
+            // Mask from the minimum to the end of the column
+            for (int i = PS_MAX(0, min); i < numRows; i++) {
+                outData[i][x] |= setVal;
+            }
+        }
+    }
+
+    psFree(conv);
+
+    return out;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageConvolve.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageConvolve.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageConvolve.h	(revision 22158)
@@ -0,0 +1,204 @@
+/* @file  psImageConvolve.h
+ *
+ * @brief image convolution functionality
+ *
+ * @author Robert DeSonia, MHPCC
+ *
+ * @version $Revision: 1.33 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-05-17 01:38:20 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_IMAGE_CONVOLVE_H
+#define PS_IMAGE_CONVOLVE_H
+
+/// @addtogroup ImageOps Image Operations
+/// @{
+
+#include "psImage.h"
+#include "psVector.h"
+#include "psType.h"
+
+#define PS_TYPE_KERNEL PS_TYPE_F32     ///< the data member to use for kernel image */
+#define PS_TYPE_KERNEL_DATA F32        ///< the data member to use for kernel image */
+#define PS_TYPE_KERNEL_NAME "psF32"    ///< the data type for kernel as a string */
+
+/// A convolution kernel
+typedef struct {
+    psImage *image;                    ///< Kernel data, in the form of an image
+    int xMin;                          ///< Most negative x index
+    int yMin;                          ///< Most negative y index
+    int xMax;                          ///< Most positive x index
+    int yMax;                          ///< Most positive y index
+    float **kernel;                    ///< Pointer to the kernel data
+    float **p_kernelRows;              ///< Pointer to the rows of the kernel data; not intended for user use.
+} psKernel;
+
+#define PS_ASSERT_KERNEL_NON_NULL(KERNEL, RETURNVALUE) \
+    if ((KERNEL) == NULL || (KERNEL)->kernel == NULL) { \
+        psError(PS_ERR_BAD_PARAMETER_NULL, true, \
+                "Unallowable operation: psKernel %s or its data is NULL.", \
+                #KERNEL); \
+        return RETURNVALUE; \
+    } \
+    PS_ASSERT_IMAGE_NON_NULL((KERNEL)->image, RETURNVALUE);
+
+#define PS_ASSERT_KERNELS_SIZE_EQUAL(KERNEL1, KERNEL2, RETURNVALUE) \
+    if ((KERNEL1)->xMin != (KERNEL2)->xMin || \
+        (KERNEL1)->xMax != (KERNEL2)->xMax || \
+        (KERNEL1)->yMin != (KERNEL2)->yMin || \
+        (KERNEL1)->yMax != (KERNEL2)->yMax) { \
+        psError(PS_ERR_BAD_PARAMETER_NULL, true, \
+                "Unallowable operation: Kernels %s and %s are not the same size.", \
+                #KERNEL1, #KERNEL2); \
+        return RETURNVALUE; \
+    } \
+    PS_ASSERT_IMAGES_SIZE_EQUAL((KERNEL1)->image, (KERNEL2)->image, RETURNVALUE);
+
+/// Allocates a convolution kernel of the given range
+///
+/// In order to perform a convolution, we need to define the convolution
+/// kernel. We need a more general object than a psImage so that we can
+/// incorporate the offset from the (0, 0) pixel to the (0, 0) value of the
+/// kernel. It might be convenient to allow both positive and negative
+/// indices to convey the positive and negative shifts. One might consider
+/// setting the x0 and y0 members of a psImage to the appropriate offsets,
+/// but this is not the purpose of these members, and doing so may affect the
+/// behavior of other psImage operations.
+///
+/// This construction allows the kernel member to use negative indices, while
+/// preserving the location of psMemBlocks relative to allocated memory.
+///
+/// The maximum extent of the kernel shifts shall be defined by the xMin,
+/// xMax, yMin and yMax members. Note that xMin and yMin, under normal
+/// circumstances, should be negative numbers. That is,
+/// myKernel->kernel[-3][-2] may be defined if yMin and xMin are equal to or
+/// more negative than -3 and -2, respectively.
+///
+/// In the event that one of the minimum values is greater than the
+/// corresponding maximum value, the function shall generate a warning, and
+/// the offending values shall be exchanged.
+///
+/// @return psKernel*          A new kernel object
+///
+psKernel *psKernelAlloc(
+    int xMin,                          ///< Most negative x index
+    int xMax,                          ///< Most positive x index
+    int yMin,                          ///< Most negative y index
+    int yMax                           ///< Most positive y index
+) PS_ATTR_MALLOC;
+
+/// Allocate a convolution kernel from a provided image
+psKernel *psKernelAllocFromImage(psImage *image, ///< Image from which to define kernel
+                                 int x0, int y0 ///< Coordinates of kernel centre
+    );
+
+/// Checks the type of a particular pointer.
+///
+/// Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+///
+/// @return bool:       True if the pointer matches a psKernel structure, false otherwise.
+///
+bool psMemCheckKernel(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+
+/// Generates a kernel given a list of shift values
+///
+/// Given a list of values (e.g., shifts made in the course of OT guiding),
+/// psKernelGenerate shall return the appropriate kernel.  The vectors xShifts
+/// and yShifts, which are a list of shifts relative to some starting point,
+/// will be supplied by the user. The elements of the vectors should be of an
+/// integer type; otherwise the values shall be truncated to integers. The
+/// output kernel shall be normalized such that the sum over the kernel is
+/// unity.
+///
+/// If the vectors are not of the same number of elements, then the function
+/// shall generate a warning shall be generated, following which, the longer
+/// vector trimmed to the length of the shorter, and the function shall continue.
+///
+/// @return psKernel*    new Kernel object
+///
+psKernel *psKernelGenerate(
+    const psVector *tShifts,            ///< list of time shifts (F32)
+    const psVector *xShifts,            ///< list of x-axis shifts (S32)
+    const psVector *yShifts,            ///< list of y-axis shifts (S32)
+    float totalTime,                    ///< Total time (relative times if negative or zero)
+    bool xyRelative                     ///< Are x,y positions relative (shifts) or absolute?
+);
+
+/// Convolve an image with a kernel, using a direct convolution
+///
+/// This is appropriate for small kernels, where there is no time saving to use FFT method.
+///
+/// @return psImage*  resulting image
+///
+psImage *psImageConvolveDirect(
+    psImage *out,                       ///< Output image, or NULL
+    const psImage *in,                  ///< Image to convolve
+    const psKernel *kernel              ///< kernel to colvolve with
+);
+
+/// Convolve a mask image with a kernel
+///
+/// Returns a mask, grown by the supplied convolution bounds.  Only those pixels specified by the maskVal are
+/// grown, being ORed with setVal; the rest are simply propagated.  If setVal is zero, uses maskVal; note that
+/// the mode of growing individual bits in maskVal is NOT supported because this algorithm does not enable it.
+psImage *psImageConvolveMask(psImage *out, ///< Output image, or NULL
+                             const psImage *mask, ///< Mask to convolve
+                             psMaskType maskVal, ///< Mask value to convolve
+                             psMaskType setVal, ///< Mask value to set; 0 to propagate maskVal
+                             int xMin, int xMax, int yMin, int yMax ///< Convolution bounds
+    );
+
+/// Convolve a mask image with a kernel, using direct convolution
+///
+/// Returns a mask, grown by the supplied convolution bounds.  Only those pixels specified by the maskVal are
+/// grown, being ORed with setVal; the rest are simply propagated.  If setVal is zero, then individual bits
+/// matching maskVal are grown.
+psImage *psImageConvolveMaskDirect(psImage *out, ///< Output image, or NULL
+                                   const psImage *mask, ///< Mask to convolve
+                                   psMaskType maskVal, ///< Mask value to convolve
+                                   psMaskType setVal, ///< Mask value to set; 0 to propagate maskVal
+                                   int xMin, int xMax, int yMin, int yMax ///< Convolution bounds
+    );
+
+/// Convolve a mask image with a kernel, using the FFT
+///
+/// Returns a mask, grown by the supplied convolution bounds.  Only those pixels specified by the maskVal are
+/// grown, being ORed with setVal; the rest are simply propagated.  If setVal is zero, uses maskVal; note that
+/// the mode of growing individual bits in maskVal is NOT supported because this algorithm does not enable it.
+/// Uses psImageConvolveFFT to convolve those pixels which are masked, and then thresholds at the specified
+/// level.
+psImage *psImageConvolveMaskFFT(psImage *out, ///< Output image, or NULL
+                                const psImage *mask, ///< Mask to convolve
+                                psMaskType maskVal, ///< Mask value to convolve
+                                psMaskType setVal, ///< Mask value to set; 0 to use maskVal
+                                int xMin, int xMax, int yMin, int yMax, ///< Convolution bounds
+                                float thresh ///< Threshold (0..1) for convolved floating-point image
+    );
+
+/// Smooths an image by parts using 1D Gaussian independently in x and y.
+///
+/// Applies a circularly symmetric Gaussian smoothing first in x and then in y
+/// directions with just a vector.  This process is 2N faster than 2D convolutions (in general).
+///
+/// @return bool        TRUE if successful, otherwise FALSE
+///
+bool psImageSmooth(
+    psImage *image,                    ///< the image to be smoothed
+    double  sigma,                     ///< the width of the smoothing kernel in pixels
+    double  Nsigma                     ///< the size of the smoothing box in sigmas
+);
+
+bool psImageSmoothMaskF32(
+    psImage *image,                    ///< the image to be smoothed
+    psImage *mask,                     ///< optional mask
+    psMaskType maskVal,
+    double  sigma,                     ///< the width of the smoothing kernel in pixels
+    double  Nsigma                     ///< the size of the smoothing box in sigmas
+);
+
+/// @}
+#endif // #ifndef PS_IMAGE_CONVOLVE_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageGeomManip.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageGeomManip.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageGeomManip.c	(revision 22158)
@@ -0,0 +1,998 @@
+/** @file  psImageGeomManip.c
+ *
+ *  @brief Contains basic image pixel and geometry manipulation operations, as
+ *         specified in the PSLIB SDRS sections "Image Pixel Manipulations" and
+ *         "Image Geometry Manipulations".
+ *
+ *  @ingroup Image
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.42 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-03-11 00:41:30 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <math.h>                          // for isfinite(), etc.
+#include <stdlib.h>
+#include <string.h>                        // for memcpy, etc.
+
+#include "psImageGeomManip.h"
+
+#include "psAbort.h"
+#include "psError.h"
+#include "psImage.h"
+#include "psImageStructManip.h"
+#include "psStats.h"
+#include "psMemory.h"
+#include "psAssert.h"
+#include "psImageInterpolate.h"
+#include "psCoord.h"
+
+psImage* psImageRebin(psImage* out,
+                      const psImage* in,
+                      const psImage* mask,
+                      psMaskType maskVal,
+                      int scale,
+                      const psStats* stats)
+{
+    psS32 inRows;
+    psS32 inCols;
+    psS32 outRows;
+    psS32 outCols;
+    psVector* vec;                     // vector to hold the values of a single bin.
+    psVector* maskVec = NULL;          // vector to hold the mask of a single bin.
+    psMaskType* maskData = NULL;
+    psStats* myStats;
+
+    if (in == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not operate on a NULL psImage."));
+        psFree(out);
+        return NULL;
+    }
+
+    if (scale < 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified scale value, %d, must be a positive value."),
+                scale);
+        psFree(out);
+        return NULL;
+    }
+
+    if (stats == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Specified statistic can not be NULL."));
+        psFree(out);
+        return NULL;
+    }
+
+    psStatsOptions statistic = psStatsSingleOption(stats->options); // Statistics option to use
+    if (statistic == 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified statistic option, %d, is not valid.  Must specify one and only one statistic type."),
+                stats->options);
+        psFree(out);
+        return NULL;
+    }
+
+    vec = psVectorAllocEmpty(scale * scale, in->type.type);
+
+    if (mask != NULL) {
+        if (mask->type.type != PS_TYPE_MASK) {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,mask->type.type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    _("Input psImage mask type, %s, is not the supported mask datatype of %s."),
+                    typeStr, PS_TYPE_MASK_NAME);
+            psFree(out);
+            psFree(vec);
+            return NULL;
+        }
+        maskVec = psVectorAllocEmpty(scale * scale, PS_TYPE_MASK);
+        maskData = maskVec->data.PS_TYPE_MASK_DATA;
+    }
+
+    myStats = psAlloc(sizeof(psStats));
+    *myStats = *stats;
+
+    // create output image.
+    inRows = in->numRows;
+    inCols = in->numCols;
+    outRows = (inRows + scale - 1) / scale;     // round-up for remainders
+    outCols = (inCols + scale - 1) / scale;     // round-up for remainders
+    out = psImageRecycle(out, outCols, outRows, in->type.type);
+
+    #define PS_IMAGE_REBIN_CASE(TYPE) \
+case PS_TYPE_##TYPE: { \
+        ps##TYPE *outRowData; \
+        ps##TYPE *vecData = vec->data.TYPE; \
+        psMaskType *inRowMask = NULL; \
+        for (psS32 row = 0; row < outRows; row++) { \
+            outRowData = out->data.TYPE[row]; \
+            psS32 inCurrentRow = row * scale; \
+            psS32 inNextRow = (row + 1) * scale; \
+            for (psS32 col = 0; col < outCols; col++) { \
+                psS32 inCurrentCol = col * scale; \
+                psS32 inNextCol = (col + 1) * scale; \
+                psS32 n = 0; \
+                for (psS32 inRow = inCurrentRow; inRow < inNextRow && inRow < inRows; inRow++) { \
+                    ps##TYPE* inRowData = in->data.TYPE[inRow]; \
+                    if (mask != NULL) { \
+                        inRowMask = mask->data.PS_TYPE_MASK_DATA[inRow]; \
+                    } \
+                    for (psS32 inCol = inCurrentCol; inCol < inNextCol && inCol < inCols; inCol++) { \
+                        if (maskData != NULL) { \
+                            maskData[n] = inRowMask[inCol]; \
+                        } \
+                        vecData[n++] = inRowData[inCol]; \
+                    } \
+                } \
+                vec->n = n; \
+                if (maskVec) { \
+                    maskVec->n = n; \
+                } \
+                psVectorStats(myStats, vec, NULL, maskVec, maskVal); \
+                outRowData[col] = (ps##TYPE)psStatsGetValue(myStats, statistic); \
+            } \
+        } \
+    } \
+    break;
+
+    switch (in->type.type) {
+        //        PS_IMAGE_REBIN_CASE(U8);       Not valid since psVectorStats doesn't allow
+        PS_IMAGE_REBIN_CASE(U16);
+        PS_IMAGE_REBIN_CASE(U32);      // Not a requirement
+        PS_IMAGE_REBIN_CASE(U64);      // Not a requirement
+        PS_IMAGE_REBIN_CASE(S8);
+        //        PS_IMAGE_REBIN_CASE(S16);      Not valid since psVectorStats doesn't allow
+        PS_IMAGE_REBIN_CASE(S32);      // Not a requirement
+        PS_IMAGE_REBIN_CASE(S64);      // Not a requirement
+        PS_IMAGE_REBIN_CASE(F32);
+        PS_IMAGE_REBIN_CASE(F64);
+
+    default: {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,in->type.type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    _("Specified psImage type, %s, is not supported."),
+                    typeStr);
+            psFree(out);
+            out = NULL;
+        }
+    }
+
+    psFree(vec);
+    psFree(maskVec);
+    psFree(myStats);
+
+    return out;
+}
+
+psImage* psImageResample(psImage* out,
+                         const psImage* in,
+                         int scale,
+                         psImageInterpolateMode mode)
+{
+    psS32 outRows;
+    psS32 outCols;
+    float invScale;
+
+    if (in == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not operate on a NULL psImage."));
+        psFree(out);
+        return NULL;
+    }
+
+    if (scale < 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified scale value, %d, must be a positive value."),
+                scale);
+        psFree(out);
+        return NULL;
+    }
+
+    // create an output image of the same size
+    // and type
+    outRows = in->numRows * scale;
+    outCols = in->numCols * scale;
+    invScale = 1.0f / (float)scale;
+
+    psImageInterpolateOptions *interp = psImageInterpolateOptionsAlloc(mode, in, NULL, NULL, 0,
+                                                                       NAN, NAN, 0, 0, 0);
+
+    #define PSIMAGE_RESAMPLE_CASE(TYPE) \
+case PS_TYPE_##TYPE: { \
+        out = psImageRecycle(out,outCols, outRows, PS_TYPE_##TYPE); \
+        for (psS32 row=0;row<outRows;row++) { \
+            ps##TYPE* rowData = out->data.TYPE[row]; \
+            float inRow = (float)row * invScale; \
+            for (psS32 col=0;col<outCols;col++) { \
+                double value; \
+                if (!psImageInterpolate(&value, NULL, NULL, (float)col*invScale, inRow, interp)) { \
+                    psError(PS_ERR_UNKNOWN, false, "Unable to interpolate image."); \
+                    psFree(interp); \
+                    psFree(out); \
+                    return NULL; \
+                } \
+                rowData[col] = value; \
+            } \
+        }  \
+        break; \
+    }
+
+    switch (in->type.type) {
+        PSIMAGE_RESAMPLE_CASE(U8)
+        PSIMAGE_RESAMPLE_CASE(U16)
+        PSIMAGE_RESAMPLE_CASE(U32)
+        PSIMAGE_RESAMPLE_CASE(U64)
+        PSIMAGE_RESAMPLE_CASE(S8)
+        PSIMAGE_RESAMPLE_CASE(S16)
+        PSIMAGE_RESAMPLE_CASE(S32)
+        PSIMAGE_RESAMPLE_CASE(S64)
+        PSIMAGE_RESAMPLE_CASE(F32)
+        PSIMAGE_RESAMPLE_CASE(F64)
+    default: {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,in->type.type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    _("Specified psImage type, %s, is not supported."),
+                    typeStr);
+            psFree(out);
+            out = NULL;
+        }
+    }
+
+    psFree(interp);
+
+    return out;
+}
+
+psImage* psImageRoll(psImage* out,
+                     const psImage* input,
+                     int dx,
+                     int dy)
+{
+    psS32 outRows;
+    psS32 outCols;
+    psS32 elementSize;
+
+    if (input == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not operate on a NULL psImage."));
+        psFree(out);
+        return NULL;
+    }
+    // create an output image of the same size
+    // and type
+    outRows = input->numRows;
+    outCols = input->numCols;
+    elementSize = PSELEMTYPE_SIZEOF(input->type.type);
+    out = psImageRecycle(out, outCols, outRows, input->type.type);
+
+    // make dx and dy between 0 and outCols or
+    // outRows, respectively
+    dx = dx % outCols;
+    dy = dy % outRows;
+    if (dx < 0) {
+        dx += outCols;
+    }
+    if (dy < 0) {
+        dy += outRows;
+    }
+
+    psS32 segment1Size = elementSize * (outCols - dx);
+    psS32 segment2Size = elementSize * dx;
+
+    for (psS32 row = 0; row < outRows; row++) {
+        psS32 inRowNumber = row + dy;
+
+        if (inRowNumber >= outRows) {
+            inRowNumber -= outRows;
+        }
+        psU8* inRow = input->data.U8[inRowNumber]; // use byte arithmetic for all types
+        psU8* outRow = out->data.U8[row];
+
+        memcpy(outRow, inRow + segment2Size, segment1Size);
+        memcpy(outRow + segment1Size, inRow, segment2Size);
+    }
+
+    return out;
+}
+
+psImage* psImageRotate(psImage* out,
+                       const psImage* input,
+                       float angle,
+                       double exposed,
+                       psImageInterpolateMode mode)
+{
+    if (input == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not operate on a NULL psImage."));
+        psFree(out);
+        return NULL;
+    }
+    // put the angle in the range of 0...2PI.
+    angle = (float)((double)angle - (2.0*M_PI) * floor(angle / (2.0*M_PI)));
+
+    if (fabsf(angle - M_PI_2) < FLT_EPSILON) {
+        // perform 1/4 rotate counter-clockwise
+        psS32 numRows = input->numCols;
+        psS32 numCols = input->numRows;
+        psS32 lastCol = numCols - 1;
+        psElemType type = input->type.type;
+
+        out = psImageRecycle(out, numCols, numRows, type);
+
+        #define PSIMAGE_ROTATE_LEFT_90(TYPE) \
+    case PS_TYPE_##TYPE: { \
+            ps##TYPE** inData = input->data.TYPE; \
+            for (psS32 row=0;row<numRows;row++) { \
+                ps##TYPE* outRow = out->data.TYPE[row]; \
+                for (psS32 col=0;col<numCols;col++) { \
+                    outRow[col] = inData[lastCol-col][row]; \
+                } \
+            } \
+        } \
+        break;
+
+        switch (type) {
+            PSIMAGE_ROTATE_LEFT_90(U8);
+            PSIMAGE_ROTATE_LEFT_90(U16);
+            PSIMAGE_ROTATE_LEFT_90(U32);    //  Not a requirement
+            PSIMAGE_ROTATE_LEFT_90(U64);    //  Not a requirement
+            PSIMAGE_ROTATE_LEFT_90(S8);
+            PSIMAGE_ROTATE_LEFT_90(S16);
+            PSIMAGE_ROTATE_LEFT_90(S32);    //  Not a requirement
+            PSIMAGE_ROTATE_LEFT_90(S64);    //  Not a requirement
+            PSIMAGE_ROTATE_LEFT_90(F32);
+            PSIMAGE_ROTATE_LEFT_90(F64);
+
+        default: {
+                char* typeStr;
+                PS_TYPE_NAME(typeStr,type);
+                psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                        _("Specified psImage type, %s, is not supported."),
+                        typeStr);
+                psFree(out);
+                return NULL;
+            }
+        }
+    } else if (fabsf(angle - M_PI) < FLT_EPSILON) {
+        // perform 1/2 rotate
+        psS32 numRows = input->numRows;
+        psS32 lastRow = numRows - 1;
+        psS32 numCols = input->numCols;
+        psS32 lastCol = numCols - 1;
+        psElemType type = input->type.type;
+
+        out = psImageRecycle(out, numCols, numRows, type);
+
+        #define PSIMAGE_ROTATE_180_CASE(TYPE) \
+    case PS_TYPE_##TYPE: { \
+            for (psS32 row=0;row<numRows;row++) { \
+                ps##TYPE* outRow = out->data.TYPE[row]; \
+                ps##TYPE* inRow = input->data.TYPE[lastRow-row]; \
+                for (psS32 col=0;col<numCols;col++) { \
+                    outRow[col] = inRow[lastCol - col]; \
+                } \
+            } \
+        } \
+        break;
+
+        switch (type) {
+            PSIMAGE_ROTATE_180_CASE(U8);
+            PSIMAGE_ROTATE_180_CASE(U16);
+            PSIMAGE_ROTATE_180_CASE(U32);    // Not a requirement
+            PSIMAGE_ROTATE_180_CASE(U64);    // Not a requirement
+            PSIMAGE_ROTATE_180_CASE(S8);
+            PSIMAGE_ROTATE_180_CASE(S16);
+            PSIMAGE_ROTATE_180_CASE(S32);    // Not a requirement
+            PSIMAGE_ROTATE_180_CASE(S64);    // Not a requirement
+            PSIMAGE_ROTATE_180_CASE(F32);
+            PSIMAGE_ROTATE_180_CASE(F64);
+
+        default: {
+                char* typeStr;
+                PS_TYPE_NAME(typeStr,type);
+                psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                        _("Specified psImage type, %s, is not supported."),
+                        typeStr);
+                psFree(out);
+                return NULL;
+            }
+        }
+    } else if (fabsf(angle - (M_PI+M_PI_2)) < FLT_EPSILON) {
+        // perform 1/4 rotate clockwise
+        psS32 numRows = input->numCols;
+        psS32 lastRow = numRows - 1;
+        psS32 numCols = input->numRows;
+        psElemType type = input->type.type;
+
+        out = psImageRecycle(out, numCols, numRows, type);
+
+        #define PSIMAGE_ROTATE_RIGHT_90(TYPE) \
+    case PS_TYPE_##TYPE: { \
+            ps##TYPE** inData = input->data.TYPE; \
+            for (psS32 row=0;row<numRows;row++) { \
+                ps##TYPE* outRow = out->data.TYPE[row]; \
+                for (psS32 col=0;col<numCols;col++) { \
+                    outRow[col] = inData[col][lastRow-row]; \
+                } \
+            } \
+        } \
+        break;
+
+        switch (type) {
+            PSIMAGE_ROTATE_RIGHT_90(U8);
+            PSIMAGE_ROTATE_RIGHT_90(U16);
+            PSIMAGE_ROTATE_RIGHT_90(U32);     // Not a requirement
+            PSIMAGE_ROTATE_RIGHT_90(U64);     // Not a requirement
+            PSIMAGE_ROTATE_RIGHT_90(S8);
+            PSIMAGE_ROTATE_RIGHT_90(S16);
+            PSIMAGE_ROTATE_RIGHT_90(S32);     // Not a requirement
+            PSIMAGE_ROTATE_RIGHT_90(S64);     // Not a requirement
+            PSIMAGE_ROTATE_RIGHT_90(F32);
+            PSIMAGE_ROTATE_RIGHT_90(F64);
+
+        default: {
+                char* typeStr;
+                PS_TYPE_NAME(typeStr,type);
+                psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                        _("Specified psImage type, %s, is not supported."),
+                        typeStr);
+                psFree(out);
+                return NULL;
+            }
+        }
+    } else if (fabsf(angle) < FLT_EPSILON) {
+        out = psImageCopy(out, input, input->type.type);
+    } else {
+        psElemType type = input->type.type;
+        psS32 numRows = input->numRows;
+        psS32 numCols = input->numCols;
+        float centerX = (float)(numCols) / 2.0f;
+        float centerY = (float)(numRows) / 2.0f;
+        double cosT = cosf(angle);
+        double sinT = sinf(angle);
+
+        // calculate the corners of the rotated image so we know the proper output image size.
+        // x' = x cos(t) + y sin(t); i.e, x' = (x-centerX)*cosT + (y-centerY)*sinT;
+        // y' = y cos(t) - x sin(t); i.e. y' = (y-centerY)*cosT - (x-centerX)*sinT;
+
+        psS32 outCols = ceil(abs(numCols * cosT) + abs(numRows * sinT)) + 1;
+        psS32 outRows = ceil(abs(numCols * sinT) + abs(numRows * cosT)) + 1;
+        float minX = (float)outCols / -2.0f;
+        psS32 intMinY = outRows / -2;
+
+        out = psImageRecycle(out, outCols, outRows, type);
+
+        /* optimized public domain rotation routine by Karl Lager
+         *
+         * float cosT,sinT;
+         * cosT = cos(t);
+         * sinT = sin(t);
+         * for (y = min_y; y <= max_y; y++) {
+         *     x' = min_x * cosT + y * sinT + x1';
+         *     y' = y * cosT - min_x * sinT + y1';
+         *     for (x = min_x; x <= max_x; x++) {
+         *         if (x', y') is in the bounds of the bitmap, get pixel
+         *            (x', y') and plot the pixel to (x, y) on screen.
+         *         x' += cosT;
+         *         y' -= sinT;
+         *     }
+         * }
+         */
+
+        // precalculate some figures that are used within loop
+        float minXTimesCosTPlusCenterX = minX * cosT + centerX;
+        float CenterYMinusminXTimesSinT = centerY - minX * sinT;
+
+        psImageInterpolateOptions *interp = psImageInterpolateOptionsAlloc(mode, input, NULL, NULL, 0,
+                                                                           exposed, NAN, 0, 0, 0.0);
+
+        #define PSIMAGE_ROTATE_ARBITRARY_LOOP(TYPE)  \
+          case PS_TYPE_##TYPE: { \
+            if (exposed < PS_MIN_##TYPE || \
+                    exposed > PS_MAX_##TYPE || \
+                    exposed < PS_MIN_##TYPE || \
+                    exposed > PS_MAX_##TYPE) { \
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+                        _("Specified %s value, %g%+gi, is not the the range of input psImage's valid pixel values (%s), i.e. [%g:%g]."), \
+                        "exposed", \
+                        exposed, exposed, \
+                        PS_TYPE_##TYPE##_NAME,  \
+                        (double)PS_MIN_##TYPE,(double)PS_MAX_##TYPE); \
+                psFree(out); \
+                out = NULL; \
+                break; \
+            } \
+            float inX; \
+            float inY; \
+            ps##TYPE* outRow; \
+            for (psS32 y = 0; y < outRows; y++) { \
+                inX = minXTimesCosTPlusCenterX + (y+intMinY) * sinT; \
+                inY = CenterYMinusminXTimesSinT + (y+intMinY) * cosT; \
+                outRow = out->data.TYPE[y]; \
+                for (psS32 x = 0; x < outCols; x++) { \
+                    double value; \
+                    if (!psImageInterpolate(&value, NULL, NULL, inX, inY, interp)) { \
+                        psError(PS_ERR_UNKNOWN, false, "Unable to interpolate image."); \
+                        psFree(out); \
+                        psFree(interp); \
+                        return NULL; \
+                    } \
+                    outRow[x] = value; \
+                    inX += cosT; \
+                    inY -= sinT; \
+                } \
+            } \
+            break; \
+        }
+
+        switch (type) {
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(U8);
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(U16);
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(U32);
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(U64);
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(S8);
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(S16);
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(S32);
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(S64);
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(F32);
+            PSIMAGE_ROTATE_ARBITRARY_LOOP(F64);
+          default: {
+              char* typeStr;
+              PS_TYPE_NAME(typeStr,type);
+              psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                      _("Specified psImage type, %s, is not supported."),
+                      typeStr);
+              psFree(out);
+              psFree(interp);
+              out = NULL;
+          }
+        }
+
+        psFree(interp);
+
+    }
+
+    return out;
+}
+
+psImage* psImageShift(psImage* out,
+                      const psImage* input,
+                      float dx,
+                      float dy,
+                      double exposed,
+                      psImageInterpolateMode mode)
+{
+    psS32 outRows;
+    psS32 outCols;
+    psS32 elementSize;
+    psElemType type;
+
+    if (input == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not operate on a NULL psImage."));
+        psFree(out);
+        return NULL;
+    }
+    // create an output image of the same size
+    // and type
+    outRows = input->numRows;
+    outCols = input->numCols;
+    type = input->type.type;
+    elementSize = PSELEMTYPE_SIZEOF(type);
+    out = psImageRecycle(out, outCols, outRows, type);
+
+    psImageInterpolateOptions *interp = psImageInterpolateOptionsAlloc(mode, input, NULL, NULL, 0,
+                                                                       exposed, NAN, 0, 0, 0.0);
+
+    #define PSIMAGE_SHIFT_CASE(TYPE) \
+case PS_TYPE_##TYPE: \
+    if (exposed < PS_MIN_##TYPE || \
+            exposed > PS_MAX_##TYPE || \
+            exposed < PS_MIN_##TYPE || \
+            exposed > PS_MAX_##TYPE) { \
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+                _("Specified %s value, %g%+gi, is not the the range of input psImage's valid pixel values (%s), i.e. [%g:%g]."), \
+                "exposed", \
+                exposed,exposed, \
+                PS_TYPE_##TYPE##_NAME,  \
+                (double)PS_MIN_##TYPE,(double)PS_MAX_##TYPE); \
+        psFree(out); \
+        out = NULL; \
+        break; \
+    } \
+    /* note: output(i,j) = input(i+0.5-dx,j+0.5-dy) */ \
+    /* positive dx,dy moves pixel i-dx,j-dy to i,y */ \
+    /* also: pixel center is 0.5,0.5 */ \
+    for (psS32 row=0;row<outRows;row++) { \
+        ps##TYPE* outRow = out->data.TYPE[row]; \
+        float y = row + 0.5 - dy; \
+        for (psS32 col=0;col<outCols;col++) { \
+            float x = col + 0.5 - dx; \
+            double value; \
+            if (!psImageInterpolate(&value, NULL, NULL, x, y, interp)) { \
+                psError(PS_ERR_UNKNOWN, false, "Unable to interpolate image."); \
+                psFree(interp); \
+                psFree(out); \
+                return NULL; \
+            } \
+            outRow[col] = value; \
+        } \
+    } \
+    break;
+
+    switch (input->type.type) {
+        PSIMAGE_SHIFT_CASE(U8);
+        PSIMAGE_SHIFT_CASE(U16);
+        PSIMAGE_SHIFT_CASE(U32);
+        PSIMAGE_SHIFT_CASE(U64);
+        PSIMAGE_SHIFT_CASE(S8);
+        PSIMAGE_SHIFT_CASE(S16);
+        PSIMAGE_SHIFT_CASE(S32);
+        PSIMAGE_SHIFT_CASE(S64);
+        PSIMAGE_SHIFT_CASE(F32);
+        PSIMAGE_SHIFT_CASE(F64);
+      default: {
+          char* typeStr;
+          PS_TYPE_NAME(typeStr,type);
+          psError(PS_ERR_BAD_PARAMETER_TYPE, true, _("Specified psImage type, %s, is not supported."),
+                  typeStr);
+          psFree(out);
+          psFree(interp);
+          return NULL;
+        }
+    }
+
+    psFree(interp);
+    return out;
+}
+
+bool psImageShiftMask(psImage **out, psImage **outMask, const psImage* in, const psImage *inMask,
+                      psMaskType maskVal, float dx, float dy, double exposed, psMaskType blank,
+                      psImageInterpolateMode mode)
+{
+    PS_ASSERT(out, false);
+    PS_ASSERT_IMAGE_NON_NULL(in, false);
+    if (inMask) {
+        PS_ASSERT_IMAGE_NON_NULL(inMask, false);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(in, inMask, false);
+        PS_ASSERT_IMAGE_TYPE(inMask, PS_TYPE_MASK, false);
+    }
+
+    int numRows = in->numRows, numCols = in->numCols; // Size of image
+    psElemType type = in->type.type;    // Type of image
+
+    *out = psImageRecycle(*out, numCols, numRows, type);
+    if (outMask) {
+        *outMask = psImageRecycle(*outMask, numCols, numRows, PS_TYPE_MASK);
+    }
+
+    psImageInterpolateOptions *interp = psImageInterpolateOptionsAlloc(PS_INTERPOLATE_BICUBE, in, NULL,
+                                                                       inMask, maskVal, exposed, NAN, blank,
+                                                                       blank, 0.0);
+
+    #define PSIMAGE_SHIFT_MASK_CASE(TYPE) \
+case PS_TYPE_##TYPE: \
+    if (exposed < PS_MIN_##TYPE || \
+            exposed > PS_MAX_##TYPE || \
+            exposed < PS_MIN_##TYPE || \
+            exposed > PS_MAX_##TYPE) { \
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+                _("Specified exposed value, %g%+gi, is not the the range of input image's " \
+                  "valid pixel values (%s), i.e. [%g:%g]."), \
+                exposed, exposed, \
+                PS_TYPE_##TYPE##_NAME,  \
+                (double)PS_MIN_##TYPE,(double)PS_MAX_##TYPE); \
+        psFree(out); \
+        out = NULL; \
+        break; \
+    } \
+    /* note: output(i,j) = input(i+0.5-dx,j+0.5-dy) */ \
+    /* positive dx,dy moves pixel i-dx,j-dy to i,y */ \
+    /* also: pixel center is 0.5,0.5 */ \
+    for (int row = 0; row < numRows; row++) { \
+        ps##TYPE* outRow = (*out)->data.TYPE[row]; \
+        psMaskType *outMaskRow = (outMask ? (*outMask)->data.PS_TYPE_MASK_DATA[row] : NULL); \
+        float y = row + 0.5 - dy; \
+        for (int col = 0; col < numCols; col++) { \
+            float x = col + 0.5 - dx; \
+            double value; \
+            psMaskType valueMask; \
+            if (!psImageInterpolate(&value, NULL, &valueMask, x, y, interp)) { \
+                psError(PS_ERR_UNKNOWN, false, "Unable to interpolate image."); \
+                psFree(interp); \
+                return false; \
+            } \
+            outRow[col] = value; \
+            if (outMask) { \
+                outMaskRow[col] = valueMask; \
+            } \
+        } \
+    } \
+    break;
+
+    switch (type) {
+        PSIMAGE_SHIFT_MASK_CASE(U8);
+        PSIMAGE_SHIFT_MASK_CASE(U16);
+        PSIMAGE_SHIFT_MASK_CASE(U32);
+        PSIMAGE_SHIFT_MASK_CASE(U64);
+        PSIMAGE_SHIFT_MASK_CASE(S8);
+        PSIMAGE_SHIFT_MASK_CASE(S16);
+        PSIMAGE_SHIFT_MASK_CASE(S32);
+        PSIMAGE_SHIFT_MASK_CASE(S64);
+        PSIMAGE_SHIFT_MASK_CASE(F32);
+        PSIMAGE_SHIFT_MASK_CASE(F64);
+      default: {
+          char* typeStr;
+          PS_TYPE_NAME(typeStr,type);
+          psError(PS_ERR_BAD_PARAMETER_TYPE, true, _("Specified psImage type, %s, is not supported."),
+                  typeStr);
+          psFree(interp);
+          return false;
+        }
+    }
+
+    psFree(interp);
+    return true;
+}
+
+psImage* psImageTransform(psImage *output,
+                          psPixels** blankPixels,
+                          const psImage *input,
+                          const psImage *inputMask,
+                          psMaskType inputMaskVal,
+                          const psPlaneTransform *outToIn,
+                          psRegion region,
+                          const psPixels* pixels,
+                          psImageInterpolateMode mode,
+                          double exposedValue)
+{
+    if (input == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not operate on a NULL psImage."));
+        psFree(output);
+        return NULL;
+    }
+    psElemType type = input->type.type;
+
+    if (blankPixels != NULL && *blankPixels == NULL) {
+        *blankPixels = psPixelsAlloc(0);
+    }
+
+    if (inputMask != NULL) {
+        if (input->numRows != inputMask->numRows || input->numCols != inputMask->numCols) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    _("Input psImage mask size, %dx%d, does not match psImage input size, %dx%d."),
+                    input->numCols, input->numRows,
+                    inputMask->numCols, inputMask->numRows );
+            psFree(output);
+            return NULL;
+        }
+        if (inputMask->type.type != PS_TYPE_MASK) {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,inputMask->type.type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    _("Input psImage mask type, %s, is not the supported mask datatype of %s."),
+                    typeStr, PS_TYPE_MASK_NAME);
+            psFree(output);
+            return NULL;
+        }
+    }
+
+    if (outToIn == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Specified input transform can not be NULL."));
+        return NULL;
+    }
+
+    int row0;
+    int row1;
+    int col0;
+    int col1;
+    int numRows;
+    int numCols;
+    if (output == NULL) { // output image size is determined by psRegion
+        row0 = region.y0;
+        row1 = region.y1;
+        col0 = region.x0;
+        col1 = region.x1;
+        //If [0,0,0,0] specified, the whole image is to be included
+        if (row0 == 0 && col0 == 0 && row1 == 0 && col1 == 0) {
+            row0 = input->row0;
+            col0 = input->col0;
+            row1 = input->row0 + input->numRows - 1;
+            col1 = input->col0 + input->numCols - 1;
+        }
+        if (col1 < 1) {
+            col1 += input->col0 + input->numCols;
+        }
+
+        if (row1 < 1) {
+            row1 += input->row0 + input->numRows;
+        }
+
+        numRows = row1 - row0;
+        numCols = col1 - col0;
+
+        if (numRows < 1 || numCols < 1) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    "The specified region is invalid.");
+            psFree(output);
+            return NULL;
+        }
+        // create the output image.
+        output = psImageRecycle(output, numCols, numRows, input->type.type);
+        P_PSIMAGE_SET_COL0(output, region.x0);
+        P_PSIMAGE_SET_ROW0(output, region.y0);
+    } else { // size of output is determined by output parameter
+        numRows = output->numRows;
+        numCols = output->numCols;
+        row0 = output->row0;
+        col0 = output->col0;
+        row1 = row0+numRows -1;
+        col1 = col0+numCols -1;
+    }
+
+    // loop through the output image using the domain above and transform
+    // each output pixel to input coordinates and use psImageInterpolate
+    // to determine the pixel value.
+    psPlane outPosition;
+    psPlane* inPosition = NULL;
+
+    psImageInterpolateOptions *interp = psImageInterpolateOptionsAlloc(mode, input, NULL, inputMask,
+                                                                       inputMaskVal, NAN, NAN, 0, 0, 0.0);
+
+
+    #define PSIMAGE_TRANSFORM_DOTRANSFORM(TYPE) \
+    /* apply the transform to get the position in the input image */ \
+    inPosition = psPlaneTransformApply(inPosition, outToIn, &outPosition); \
+    \
+    if (inPosition == NULL) { \
+        psError(PS_ERR_UNKNOWN, false, \
+                "Failed to apply the transform"); \
+        psFree(output); \
+        return NULL; \
+    } \
+    /* interpolate the cooresponding input pixel to get the output pixel value. */ \
+    double value; \
+    if (!psImageInterpolate(&value, NULL, NULL, inPosition->x, inPosition->y, interp)) { \
+        psError(PS_ERR_UNKNOWN, false, "Unable to interpolate image."); \
+        psFree(output); \
+        psFree(interp); \
+        return NULL; \
+    } \
+    /*    psFree(inPosition); */\
+    if (isnan(value)) { \
+        if (blankPixels != NULL) { \
+            psPixelsAdd(*blankPixels, (*blankPixels)->nalloc, outPosition.x, outPosition.y); \
+        } \
+        value = exposedValue; \
+    } \
+
+    #define PSIMAGE_TRANSFORM_CASE(TYPE) \
+      case PS_TYPE_##TYPE: { \
+        for (int row = 0; row < numRows; row++) { \
+            outPosition.y = row+row0; \
+            ps##TYPE* outputData=output->data.TYPE[row]; \
+            for (int col = 0; col < numCols; col++) { \
+                outPosition.x = col+col0; \
+                PSIMAGE_TRANSFORM_DOTRANSFORM(TYPE) \
+                outputData[col] = value; \
+            } \
+        } \
+        break; \
+    }
+
+    switch (type) {
+        PSIMAGE_TRANSFORM_CASE(F32);
+        PSIMAGE_TRANSFORM_CASE(F64);
+      default: {
+          char* typeStr;
+          PS_TYPE_NAME(typeStr,type);
+          psError(PS_ERR_BAD_PARAMETER_TYPE, true, _("Specified psImage type, %s, is not supported."),
+                  typeStr);
+          psFree(output);
+          psFree(inPosition);
+          return NULL;
+      }
+    }
+
+    psFree(inPosition);
+
+    return output;
+}
+
+
+#define FLIP_X_CASE(TYPENAME,TYPE) \
+case TYPENAME: { \
+    long numRows = input->numRows; \
+    long numCols = input->numCols; \
+    for (long i = 0; i < numRows; i++) { \
+        for (long j = 0; j < numCols; j++) { \
+            output->data.TYPE[i][j] = input->data.TYPE[i][numCols - j - 1]; \
+        } \
+    } \
+    break; \
+}
+
+#define FLIP_Y_CASE(TYPENAME,TYPE) \
+case TYPENAME: { \
+    long numRows = input->numRows; \
+    long numCols = input->numCols; \
+    for (long i = 0; i < numRows; i++) { \
+        for (long j = 0; j < numCols; j++) { \
+            output->data.TYPE[i][j] = input->data.TYPE[numRows - i - 1][j]; \
+        } \
+    } \
+    break; \
+}
+
+psImage *psImageFlip(psImage *output, const psImage *input, bool xFlip, bool yFlip)
+{
+    PS_ASSERT_IMAGE_NON_NULL(input, NULL);
+
+    if (xFlip && yFlip) {
+        // This is equivalent to a 180 degree rotation;
+        return psImageRotate(output, input, M_PI, NAN, PS_INTERPOLATE_BILINEAR);
+    }
+
+    if (!xFlip && !yFlip) {
+        // They want something, so let's give it to them
+        return psImageCopy(output, input, input->type.type);
+    }
+
+    output = psImageRecycle(output, input->numCols, input->numRows, input->type.type);
+
+    if (xFlip) {
+        switch (input->type.type) {
+            FLIP_X_CASE(PS_TYPE_U8,  U8);
+            FLIP_X_CASE(PS_TYPE_U16, U16);
+            FLIP_X_CASE(PS_TYPE_U32, U32);
+            FLIP_X_CASE(PS_TYPE_U64, U64);
+            FLIP_X_CASE(PS_TYPE_S8,  S8);
+            FLIP_X_CASE(PS_TYPE_S16, S16);
+            FLIP_X_CASE(PS_TYPE_S32, S32);
+            FLIP_X_CASE(PS_TYPE_S64, S64);
+            FLIP_X_CASE(PS_TYPE_F32, F32);
+            FLIP_X_CASE(PS_TYPE_F64, F64);
+        default:
+            psFree(output);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Unknown type for input image: %x\n", input->type.type);
+            return NULL;
+        }
+        return output;
+    }
+    if (yFlip) {
+        switch (input->type.type) {
+            FLIP_Y_CASE(PS_TYPE_U8,  U8);
+            FLIP_Y_CASE(PS_TYPE_U16, U16);
+            FLIP_Y_CASE(PS_TYPE_U32, U32);
+            FLIP_Y_CASE(PS_TYPE_U64, U64);
+            FLIP_Y_CASE(PS_TYPE_S8,  S8);
+            FLIP_Y_CASE(PS_TYPE_S16, S16);
+            FLIP_Y_CASE(PS_TYPE_S32, S32);
+            FLIP_Y_CASE(PS_TYPE_S64, S64);
+            FLIP_Y_CASE(PS_TYPE_F32, F32);
+            FLIP_Y_CASE(PS_TYPE_F64, F64);
+        default:
+            psFree(output);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Unknown type for input image: %x\n", input->type.type);
+            return NULL;
+        }
+        return output;
+    }
+
+    psAbort("Should never get here.\n");
+    return NULL;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageGeomManip.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageGeomManip.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageGeomManip.h	(revision 22158)
@@ -0,0 +1,179 @@
+/* @file  psImageGeomManip.h
+ *
+ * @brief Contains basic image geometry manipulation operations, as
+ *        specified in the PSLIB SDRS sections "Image Geometry Manipulations".
+ *
+ * @author Robert DeSonia, MHPCC
+ *
+ * @version $Revision: 1.22 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-03-11 00:41:30 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+#ifndef PS_IMAGE_GEOM_MANIP_H
+#define PS_IMAGE_GEOM_MANIP_H
+
+/// @addtogroup ImageOps Image Operations
+/// @{
+
+#include "psImage.h"
+#include "psImageInterpolate.h"
+#include "psCoord.h"
+#include "psStats.h"
+#include "psPixels.h"
+
+/** Rebin image to new scale.
+ *
+ *  A new image is constructed in which the dimensions are reduced by a factor of
+ *  1/scale.  The scale, always a positive number, is equal in each dimension and
+ *  specified the number of pixels used to define a new pixel in the output image.
+ *  The output image is generated from all input image pixels. This function is
+ *  defined for psU8, psS8, psS16, psF32, psF64.
+ *
+ *  @return psImage    new image formed by rebinning input image.
+ */
+psImage* psImageRebin(
+    psImage* out,                      ///< an psImage to recycle.  If NULL, a new image is created
+    const psImage* in,                 ///< input image
+    const psImage* mask,               ///< mask for input image.  If NULL, no masking is done.
+    psMaskType maskVal,                ///< the bits to check in mask.
+    int scale,                         ///< the scale to rebin for each dimension
+    const psStats* stats
+    ///< the statistic to perform when rebinning.  Only one method should be set.
+);
+
+/** Resample image to new scale.
+ *
+ *  A new image is constructed in which the dimensions are increased by a
+ *  factor of scale. The scale, always a positive number, is equal in each
+ *  dimension. The output image is generated from all input image pixels.
+ *  Each pixel in the output image is derived by interpolating between
+ *  neighboring pixels using the specified interpolation method (mode).
+ *
+ *  @return psImage*    resampled image result
+ */
+psImage* psImageResample(
+    psImage* out,                      ///< an psImage to recycle.  If NULL, a new image is created
+    const psImage* in,                 ///< input image
+    int scale,                       ///< resample scaling factor
+    psImageInterpolateMode mode        ///< the interpolation mode used in resampling
+);
+
+/** Rotate the input image by given angle, specified in degrees.
+ *
+ *  The output image must contain all of the pixels from the input image in
+ *  their new frame. Pixels in the output image which do not map to input
+ *  pixels should be set to exposed. The center of rotation is always the
+ *  center pixel of the image. The rotation is specified in the sense that a
+ *  positive angle is an anti-clockwise rotation. This function must be
+ *  defined for the following types: psU8, psU16, psS8, psS16, psF32, psF64.
+ *
+ *  @return psImage*     the rotated image result.
+ */
+psImage* psImageRotate(
+    psImage* out,                      ///< an psImage to recycle.  If NULL, a new image is created
+    const psImage* input,              ///< input image
+    float angle,                       ///< the rotation angle in radians.
+    double exposed,                    ///< the output image pixel values for non-imagery areas
+    psImageInterpolateMode mode        ///< the interpolation mode used
+);
+
+/** Shift image by an arbitrary number of pixels (dx,dy) in either direction.
+ *
+ *  If the shift values are fractional, the output pixel values should
+ *  interpolate between the input pixel values. The output image has the same
+ *  dimensions as the input image. Pixels which fall off the edge of the
+ *  output image are lost. Newly exposed pixels are set to the value given by
+ *  exposed. This function must be defined for the following types: psU8,
+ *  psU16, psS8, psS16, psF32, psF64.
+ *
+ *  @return psImage*     the shifted image result.
+ */
+psImage* psImageShift(
+    psImage* out,                      ///< an psImage to recycle.  If NULL, a new image is created
+    const psImage* input,              ///< input image
+    float dx,                          ///< the shift in x direction.
+    float dy,                          ///< the shift in y direction.
+    double exposed,                    ///< the output image pixel values for non-imagery areas
+    psImageInterpolateMode mode        ///< the interpolation mode to use
+);
+
+/// Apply a translation to an image
+///
+/// This function is very much like psImageShift, except that it applies the same shifts to the mask
+bool psImageShiftMask(
+    psImage **out,                      ///< Output shifted image
+    psImage **outMask,                  ///< Output shifted mask, or NULL
+    const psImage* in,                  ///< Input image
+    const psImage *inMask,              ///< Input mask, or NULL
+    psMaskType maskVal,                 ///< Value to mask
+    float dx, float dy,                 ///< Shift to apply
+    double exposed,                     ///< Value to give exposed pixels
+    psMaskType blank,                   ///< Mask value for exposed pixels
+    psImageInterpolateMode mode         ///< Interpolation mode
+    );
+
+/** Roll image by an integer number of pixels in either direction.
+ *
+ *  The output image is the same dimensions as the input image.  Edge pixels
+ *  wrap to the other side (no values are lost).  This function is
+ *  defined for psU8, psS8, psS16, psF32, psF64.
+ *
+ *  @return psImage* the rolled version of the input image.
+ */
+psImage* psImageRoll(
+    psImage* out,                      ///< an psImage to recycle.  If NULL, a new image is created
+    const psImage* input,              ///< input image
+    int dx,                            ///< number of pixels to roll in the x-dimension
+    int dy                             ///< number of pixels to roll in the y-dimension
+);
+
+/** Transform the input image according the supplied transformation.
+ *
+ *  Transform the input image according the supplied transformation. The size
+ *  of the transformed image is defined by the supplied output image, if
+ *  non-NULL, or the region otherwise (size region.x1 - region.x0 by region.y1
+ *  region.y0, with out->x0 = region.x0 and out->y0 = region.y0). If the
+ *  inputMask is non-NULL, those pixels in the inputMask matching inputMaskVal
+ *  are to be ignored in the transformation. The inputMask must be of type
+ *  psU8, and of the same size as the input, otherwise the function shall
+ *  generate an error and return NULL. The transformation outToIn speciï¬es the
+ *  coordinates in the input image of a pixel in the output image â note that
+ *  this is the reverse of what might be naively expected, but it is what is
+ *  required in order to use psImageInterpolate. If the pixels array is
+ *  non-NULL, it shall consist of psPixelCoords, and only those pixels in the
+ *  output image shall be transformed; otherwise, the entire image is
+ *  generated. The interpolation is performed using the speciï¬ed interpolation
+ *  mode. Where a pixel in the output image does not correspond to a pixel in
+ *  the input image (or all appropriate pixels in the input image are
+ *  masked), the value shall be set to exposed, and the pixel added to the
+ *  appropriate list of pixels (psPixels) in the array of blankPixels for
+ *  return to the user. This function must be capable of handling the following
+ *  types for the input (with corresponding types for the output): psF32, psF64.
+
+ *
+ *  @return psImage*    The transformed image.
+ */
+psImage* psImageTransform(
+    psImage *output,                   ///< psImage to recycle, or NULL
+    psPixels** blankPixels,            ///< list of pixels in output image not set, or NULL if no list is desired.
+    const psImage *input,              ///< psImage to apply transform to
+    const psImage *inputMask,          ///< if not NULL, mask of input psImage
+    psMaskType inputMaskVal,           ///< masking value for inputMask
+    const psPlaneTransform *outToIn,   ///< the transform to apply
+    psRegion region,                   ///< the size of the transformed image
+    const psPixels* pixels,            /**< if not NULL, consists of psPixelCoords and specifies
+                                                        * which pixels in output image shall be transformed;
+                                                        * otherwise, entire image generated*/
+    psImageInterpolateMode mode,       ///< the interpolation scheme to be used
+    double exposedValue                ///< Exposed value to which non-corresponding pixels are set
+);
+
+// Flip the input image
+psImage *psImageFlip(psImage *output,   // Output image, or NULL
+                     const psImage *input, // Input image
+                     bool xFlip,        // Flip x axis?
+                     bool yFlip         // Flip y axis?
+                    );
+
+/// @}
+#endif // #ifndef PS_IMAGE_GEOM_MANIP_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageInterpolate.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageInterpolate.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageInterpolate.c	(revision 22158)
@@ -0,0 +1,770 @@
+/** @file  psImageInterpolate.c
+ *
+ *  @brief Contains functions for interpolating an image
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Ross Harman, MHPCC
+ *  @author Paul Price, IfA
+ *
+ *  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-06-24 02:04:55 $
+ *
+ *  Copyright 2004-2007 Institute for Astronomy, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <string.h>
+
+#include "psAbort.h"
+#include "psMemory.h"
+#include "psError.h"
+#include "psAssert.h"
+#include "psString.h"
+#include "psImage.h"
+#include "psImageInterpolate.h"
+
+static void imageInterpolateOptionsFree(psImageInterpolateOptions *options)
+{
+    // Casting away const
+    psFree((psImage*)options->image);
+    psFree((psImage*)options->mask);
+    psFree((psImage*)options->variance);
+}
+
+psImageInterpolateOptions *psImageInterpolateOptionsAlloc(psImageInterpolateMode mode,
+                                                          const psImage *image, const psImage *variance,
+                                                          const psImage *mask, psMaskType maskVal,
+                                                          double badImage, double badVariance,
+                                                          psMaskType badMask, psMaskType poorMask,
+                                                          float poorFrac)
+{
+    psImageInterpolateOptions *options = psAlloc(sizeof(psImageInterpolateOptions)); // Options, to return
+    psMemSetDeallocator(options, (psFreeFunc)imageInterpolateOptionsFree);
+
+    options->mode = mode;
+    // Casting away const to add to options
+    options->image = psMemIncrRefCounter((psImage*)image);
+    options->variance = psMemIncrRefCounter((psImage*)variance);
+    options->mask = psMemIncrRefCounter((psImage*)mask);
+    options->maskVal = maskVal;
+    options->badImage = badImage;
+    options->badVariance = badVariance;
+    options->badMask = badMask;
+    options->poorMask = poorMask;
+    options->poorFrac = poorFrac;
+
+    return options;
+}
+
+// Interpolation engine for flat mode (nearest pixel)
+static inline psImageInterpolateStatus interpolateFlat(double *imageValue, double *varianceValue,
+                                                       psMaskType *maskValue, float x, float y,
+                                                       const psImageInterpolateOptions *options)
+{
+    // Parameters have been checked by psImageInterpolate()
+
+    const psImage *image = options->image; // Image of interest
+    int xInt = round(x - 0.5 + FLT_EPSILON); // Pixel closest to point of interest in x
+    int yInt = round(y - 0.5 + FLT_EPSILON); // Pixel closest to point of interest in y
+    int xLast = image->numCols - 1;     // Last pixel in x
+    int yLast = image->numRows - 1;     // Last pixel in y
+
+    if (xInt < 0 || xInt > xLast || yInt < 0 || yInt > yLast) {
+        // At least one pixel of the interpolation kernel is off the image
+        if (imageValue) {
+            *imageValue = options->badImage;
+        }
+        if (varianceValue) {
+            *varianceValue = options->badVariance;
+        }
+        if (maskValue) {
+            *maskValue = options->badMask;
+        }
+
+        return PS_INTERPOLATE_STATUS_OFF;
+    } else {
+
+        // Image and variance 'interpolation' according to image type
+        #define FLAT_CASE(TYPE) \
+          case PS_TYPE_##TYPE: { \
+            if (imageValue) { \
+                *imageValue = options->image->data.TYPE[yInt][xInt]; \
+            } \
+            if (varianceValue && options->variance) { \
+                *varianceValue = options->variance->data.TYPE[yInt][xInt]; \
+            } \
+            break; \
+        }
+
+        switch (options->image->type.type) {
+            FLAT_CASE(U8);
+            FLAT_CASE(U16);
+            FLAT_CASE(U32);
+            FLAT_CASE(U64);
+            FLAT_CASE(S8);
+            FLAT_CASE(S16);
+            FLAT_CASE(S32);
+            FLAT_CASE(S64);
+            FLAT_CASE(F32);
+            FLAT_CASE(F64);
+          default:
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Unrecognised type for image: %x",
+                    options->image->type.type);
+            return PS_INTERPOLATE_STATUS_ERROR;
+        }
+
+        if (maskValue) {
+            if (options->mask) {
+                *maskValue = options->mask->data.PS_TYPE_MASK_DATA[yInt][xInt];
+            } else {
+                *maskValue = 0;
+            }
+        }
+    }
+    return PS_INTERPOLATE_STATUS_GOOD;
+}
+
+// Setup for interpolation by kernel
+static inline void interpolateKernelSetup(int *xNum, int *yNum, // Size of interpolation kernel, returned
+                                          int *xCentral, int *yCentral, // Central pixel of convolution
+                                          float x, float y, // Coordinates of interest
+                                          psImageInterpolateMode mode // Mode for interpolation
+                                          )
+{
+    switch (mode) {
+      case PS_INTERPOLATE_BILINEAR:
+        *xNum = *yNum = 2;
+        // Central pixel is the pixel below the point of interest
+        *xCentral = floor(x - 0.5 + FLT_EPSILON);
+        *yCentral = floor(y - 0.5 + FLT_EPSILON);
+        break;
+      case PS_INTERPOLATE_BICUBE:
+      case PS_INTERPOLATE_GAUSS:
+        *xNum = *yNum = 3;
+        // Central pixel is the closest pixel to the point of interest
+        *xCentral = x;
+        *yCentral = y;
+        break;
+      case PS_INTERPOLATE_FLAT:
+      case PS_INTERPOLATE_LANCZOS2:
+      case PS_INTERPOLATE_LANCZOS3:
+      case PS_INTERPOLATE_LANCZOS4:
+      default:
+        psAbort("Invalid interpolation mode.");
+    }
+}
+
+// Generate the interpolation kernel; it should be normalised to unity
+static inline void interpolateKernelGenerate(int xNum, int yNum, // Size of interpolation kernel
+                                             double kernel[xNum][yNum], // Kernel, to be set
+                                             int xCentral, int yCentral, // Central pixel of convolution
+                                             float x, float y, // Coordinates of interest
+                                             psImageInterpolateMode mode // Mode for interpolation
+                                             )
+{
+    switch (mode) {
+      case PS_INTERPOLATE_BILINEAR: {
+          double xFrac = x - 0.5 - xCentral; // Fraction of pixel in x
+          double yFrac = y - 0.5 - yCentral; // Fraction of pixel in y
+          kernel[0][0] = (1.0 - xFrac) * (1.0 - yFrac);
+          kernel[0][1] = xFrac * (1.0 - yFrac);
+          kernel[1][0] = yFrac * (1.0 - xFrac);
+          kernel[1][1] = xFrac * yFrac;
+          break;
+      }
+      case PS_INTERPOLATE_BICUBE: {
+          double xFrac = x - 0.5 - xCentral; // Fraction of pixel in x
+          double yFrac = y - 0.5 - yCentral; // Fraction of pixel in y
+          // Calculation variables
+          double xxFrac = xFrac * xFrac / 6.0;
+          double yyFrac = yFrac * yFrac / 6.0;
+          double xyFrac = 0.25 * xFrac * yFrac;
+          xFrac /= 6.0;
+          yFrac /= 6.0;
+          kernel[0][0] = - 1.0/9.0 - xFrac - yFrac + xxFrac + yyFrac + xyFrac;
+          kernel[0][1] = 2.0/9.0 - yFrac - 2.0 * xxFrac + yyFrac;
+          kernel[0][2] = - 1.0/9.0 + xFrac - yFrac + xxFrac + yyFrac - xyFrac;
+          kernel[1][0] = 2.0/9.0 - xFrac + xxFrac - 2.0 * yyFrac;
+          kernel[1][1] = 5.0/9.0 - 2.0 * xxFrac - 2.0 * yyFrac;
+          kernel[1][2] = 2.0/9.0 + xFrac + xxFrac - 2.0 * yyFrac;
+          kernel[2][0] = - 1.0/9.0 - xFrac + yFrac + xxFrac + yyFrac - xyFrac;
+          kernel[2][1] = 2.0/9.0 + yFrac - 2.0 * xxFrac + yyFrac;
+          kernel[2][2] = - 1.0/9.0 + xFrac + yFrac + xxFrac + yyFrac + xyFrac;
+          break;
+      }
+      case PS_INTERPOLATE_GAUSS: {
+          double xFrac = x - xCentral - 0.5; // Fraction of pixel in x
+          double yFrac = y - yCentral - 0.5; // Fraction of pixel in y
+          double sigma = 0.5;           // Gaussian sigma
+          double norm = 0.0;            // Normalisation
+          for (int j = 0, yPos = - (yNum - 1) / 2; j < yNum; j++, yPos++) {
+              for (int i = 0, xPos = - (xNum - 1) / 2; i < xNum; i++, xPos++) {
+                  norm += kernel[j][i] = exp(-0.5 / PS_SQR(sigma) * (PS_SQR(xPos - xFrac) +
+                                                                     PS_SQR(yPos - yFrac)));
+              }
+          }
+          norm = 1.0 / norm;
+          for (int j = 0; j < yNum; j++) {
+              for (int i = 0; i < xNum; i++) {
+                  kernel[j][i] *= norm;
+              }
+          }
+          break;
+      }
+      case PS_INTERPOLATE_FLAT:
+      case PS_INTERPOLATE_LANCZOS2:
+      case PS_INTERPOLATE_LANCZOS3:
+      case PS_INTERPOLATE_LANCZOS4:
+      default:
+        psAbort("Invalid interpolation mode.");
+    }
+}
+
+// Interpolation engine using interpolation kernel
+static psImageInterpolateStatus interpolateKernel(double *imageValue, double *varianceValue,
+                                                  psMaskType *maskValue, float x, float y,
+                                                  const psImageInterpolateOptions *options)
+{
+    // Parameters have been checked by psImageInterpolate()
+
+    int xNum, yNum;                     // Number of interpolation kernel pixels
+    int xCentral, yCentral;             // Central pixel of the convolution
+    interpolateKernelSetup(&xNum, &yNum, &xCentral, &yCentral, x, y, options->mode);
+
+    const psImage *image = options->image; // Image of interest
+    int xLast = image->numCols - 1;     // Last pixel in x
+    int yLast = image->numRows - 1;     // Last pixel in y
+
+    if (xCentral - (xNum - 1) / 2 < 0 || xCentral + xNum / 2 > xLast ||
+        yCentral - (yNum - 1) / 2 < 0 || yCentral + yNum / 2 > yLast) {
+        // At least one pixel of the interpolation kernel is off the image
+        if (imageValue) {
+            *imageValue = options->badImage;
+        }
+        if (varianceValue) {
+            *varianceValue = options->badVariance;
+        }
+        if (maskValue) {
+            *maskValue = options->badMask;
+        }
+        return PS_INTERPOLATE_STATUS_OFF;
+    }
+
+    double kernel[yNum][xNum];          // Interpolation kernel for straight interpolation
+    interpolateKernelGenerate(xNum, yNum, kernel, xCentral, yCentral, x, y, options->mode);
+
+    // Image interpolation, according to image type
+    #define KERNEL_IMAGE_CASE(TYPE) \
+        case PS_TYPE_##TYPE: { \
+            for (int j = 0, yPix = yCentral - (yNum - 1) / 2; j < yNum; j++, yPix++) { \
+                for (int i = 0, xPix = xCentral - (xNum - 1) / 2; i < xNum; i++, xPix++) { \
+                    *imageValue += kernel[j][i] * image->data.TYPE[yPix][xPix]; \
+                } \
+            } \
+            break; \
+        }
+
+    // Calculate the value for the image
+    if (imageValue) {
+        *imageValue = 0.0;
+        switch (image->type.type) {
+            KERNEL_IMAGE_CASE(U8);
+            KERNEL_IMAGE_CASE(U16);
+            KERNEL_IMAGE_CASE(U32);
+            KERNEL_IMAGE_CASE(U64);
+            KERNEL_IMAGE_CASE(S8);
+            KERNEL_IMAGE_CASE(S16);
+            KERNEL_IMAGE_CASE(S32);
+            KERNEL_IMAGE_CASE(S64);
+            KERNEL_IMAGE_CASE(F32);
+            KERNEL_IMAGE_CASE(F64);
+          default:
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Unrecognised type for image: %x",
+                    image->type.type);
+            return PS_INTERPOLATE_STATUS_ERROR;
+        }
+    }
+
+    // Check the mask value
+    const psImage *mask = options->mask; // Image mask
+    psImageInterpolateStatus status = PS_INTERPOLATE_STATUS_GOOD; // Status of interpolation
+    if (maskValue) {
+        *maskValue = 0;
+        if (mask) {
+            psMaskType maskVal = options->maskVal; // Mask value
+            double badContrib = 0.0;        // Amount of kernel on bad pixels
+            double totContrib = 0.0;        // Total amount of kernel
+            bool badPix = false;            // Is there a bad pixel?
+            for (int j = 0, yPix = yCentral - (yNum - 1) / 2; j < yNum; j++, yPix++) {
+                for (int i = 0, xPix = xCentral - (xNum - 1) / 2; i < xNum; i++, xPix++) {
+                    if (mask->data.PS_TYPE_MASK_DATA[yPix][xPix] & maskVal) {
+                        badContrib += fabs(kernel[j][i]);
+                        badPix = true;
+                    }
+                    *maskValue |= mask->data.PS_TYPE_MASK_DATA[yPix][xPix];
+                    totContrib += fabs(kernel[j][i]);
+                }
+            }
+
+            if (badPix) {
+                if (badContrib / totContrib >= options->poorFrac) {
+                    *maskValue |= options->badMask;
+                    status = PS_INTERPOLATE_STATUS_BAD;
+                } else {
+                    *maskValue |= options->poorMask;
+                    status = PS_INTERPOLATE_STATUS_POOR;
+                }
+            }
+        }
+    }
+
+    // Finally, the variance
+    const psImage *variance = options->variance; // Image variance
+    if (varianceValue && variance) {
+        *varianceValue = 0.0;
+
+        // Variance interpolation, according to image type
+        #define KERNEL_VARIANCE_CASE(TYPE) \
+            case PS_TYPE_##TYPE: { \
+                double sumKernel2 = 0.0; /* Sum of kernel squares */ \
+                for (int j = 0, yPix = yCentral - (yNum - 1) / 2; j < yNum; j++, yPix++) { \
+                    for (int i = 0, xPix = xCentral - (xNum - 1) / 2; i < xNum; i++, xPix++) { \
+                        double kernel2 = PS_SQR(kernel[j][i]); /* Kernel squared */ \
+                        sumKernel2 += kernel2; \
+                        *varianceValue += kernel2 * variance->data.TYPE[yPix][xPix]; \
+                    } \
+                } \
+                *varianceValue /= sumKernel2; /* Normalise so that sum of kernel squares is unity */ \
+                break; \
+            }
+
+        switch (variance->type.type) {
+            KERNEL_VARIANCE_CASE(U8);
+            KERNEL_VARIANCE_CASE(U16);
+            KERNEL_VARIANCE_CASE(U32);
+            KERNEL_VARIANCE_CASE(U64);
+            KERNEL_VARIANCE_CASE(S8);
+            KERNEL_VARIANCE_CASE(S16);
+            KERNEL_VARIANCE_CASE(S32);
+            KERNEL_VARIANCE_CASE(S64);
+            KERNEL_VARIANCE_CASE(F32);
+            KERNEL_VARIANCE_CASE(F64);
+          default:
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Unrecognised type for image: %x",
+                    image->type.type);
+            return PS_INTERPOLATE_STATUS_ERROR;
+        }
+    }
+
+    return status;
+}
+
+
+// Generate Lanczos interpolation kernels
+static void lanczos(double values[],    // Interpolation kernel to generate
+                    int num,            // Number of values in the kernel
+                    float frac          // Sub-pixel position
+    )
+{
+    // XXX: Instead of generating a convolution kernel that does no shifting, need to set a boolean that says
+    // we can do an exact shift.
+    if (fabs(frac) < DBL_EPSILON) {
+        // No real shift
+        for (int i = 0; i < (num - 1) / 2; i++) {
+            values[i] = 0.0;
+        }
+        values[(num - 1) / 2] = 1.0;
+        for (int i = (num - 1) / 2 + 1; i < num; i++) {
+            values[i] = 0.0;
+        }
+    } else {
+        double norm4 = 0.0;             // Normalisation
+        double norm1 = 2.0 / PS_SQR(M_PI); // Normalisation for laczos
+        double norm2 = M_PI * 4.0 / (float)num; // Normalisation for sinc function 1
+        double norm3 =M_PI_2 * 4.0 / (float)num; // Normalisation for sinc function 2
+        double pos = - (num - 1)/2 - frac;  // Position of interest
+        for (int i = 0; i < num; i++, pos += 1.0) {
+            norm4 += values[i] = norm1 * sin(pos * norm2) * sin(pos * norm3) / PS_SQR(pos);
+        }
+        norm4 = 1.0 / norm4;
+        for (int i = 0; i < num; i++) {
+            values[i] *= norm4;
+        }
+    }
+
+    return;
+}
+
+// Setup for interpolation by separable kernels
+static inline void interpolateSeparateSetup(int *xNum, int *yNum, // Size of interpolation kernel, returned
+                                            int *xCentral, int *yCentral, // Central pixel of convolution
+                                            float x, float y, // Coordinates of interest
+                                            psImageInterpolateMode mode // Mode for interpolation
+                                            )
+{
+    // Central pixel is the pixel below the point of interest
+    *xCentral = floor(x - 0.5);
+    *yCentral = floor(y - 0.5);
+    switch (mode) {
+      case PS_INTERPOLATE_LANCZOS2:
+        *xNum = *yNum = 4;
+        break;
+      case PS_INTERPOLATE_LANCZOS3:
+        *xNum = *yNum = 6;
+        break;
+      case PS_INTERPOLATE_LANCZOS4:
+        *xNum = *yNum = 8;
+        break;
+      case PS_INTERPOLATE_FLAT:
+      case PS_INTERPOLATE_BILINEAR:
+      case PS_INTERPOLATE_BICUBE:
+      case PS_INTERPOLATE_GAUSS:
+      default:
+        psAbort("Invalid interpolation mode.");
+    }
+}
+
+// Generate the interpolation kernels for separable case; they should be normalised to unity
+static inline void interpolateSeparateGenerate(int xNum, int yNum, // Size of interpolation kernel
+                                               double xKernel[xNum], double yKernel[yNum], // Kernels
+                                               int xCentral, int yCentral, // Central pixel of convolution
+                                               float x, float y, // Coordinates of interest
+                                               psImageInterpolateMode mode // Mode for interpolation
+                                               )
+{
+    // XXX Could put in an "exact shift" (i.e., xFrac = 0.0) version
+    switch (mode) {
+      case PS_INTERPOLATE_LANCZOS2:
+      case PS_INTERPOLATE_LANCZOS3:
+      case PS_INTERPOLATE_LANCZOS4: {
+          double xFrac = x - xCentral - 0.5; // Fraction of pixel in x
+          lanczos(xKernel, xNum, xFrac);
+          double yFrac = y - yCentral - 0.5; // Fraction of pixel in y
+          lanczos(yKernel, yNum, yFrac);
+          break;
+      }
+      case PS_INTERPOLATE_FLAT:
+      case PS_INTERPOLATE_BILINEAR:
+      case PS_INTERPOLATE_BICUBE:
+      case PS_INTERPOLATE_GAUSS:
+      default:
+        psAbort("Invalid interpolation mode.");
+    }
+}
+
+// Interpolation engine for separable interpolation kernels (either for good reasons or for practical reasons)
+static psImageInterpolateStatus interpolateSeparate(double *imageValue, double *varianceValue,
+                                                    psMaskType *maskValue, float x, float y,
+                                                    const psImageInterpolateOptions *options)
+{
+    // Parameters have been checked by psImageInterpolate()
+
+    int xNum, yNum;                     // Number of interpolation kernel pixels
+    int xCentral, yCentral; // Central pixel of the convolution
+    interpolateSeparateSetup(&xNum, &yNum, &xCentral, &yCentral, x, y, options->mode);
+
+    const psImage *image = options->image; // Image of interest
+    int xLast = image->numCols - 1;     // Last pixel in x
+    int yLast = image->numRows - 1;     // Last pixel in y
+
+    if (xCentral - (xNum - 1) / 2 < 0 || xCentral + xNum / 2 > xLast ||
+        yCentral - (yNum - 1) / 2 < 0 || yCentral + yNum / 2 > yLast) {
+        // At least one pixel of the interpolation kernel is off the image
+        if (imageValue) {
+            *imageValue = options->badImage;
+        }
+        if (varianceValue) {
+            *varianceValue = options->badVariance;
+        }
+        if (maskValue) {
+            *maskValue = options->badMask;
+        }
+        return PS_INTERPOLATE_STATUS_OFF;
+    }
+
+    double xKernel[xNum], yKernel[yNum]; // Interpolation kernels
+    interpolateSeparateGenerate(xNum, yNum, xKernel, yKernel, xCentral, yCentral, x, y, options->mode);
+
+    // Image interpolation, according to image type
+    #define SEPARATE_IMAGE_CASE(TYPE) \
+      case PS_TYPE_##TYPE: { \
+        for (int j = 0, yPix = yCentral - (yNum - 1) / 2; j < yNum; j++, yPix++) { \
+            double xInterpValue = 0.0; /* Interpolation in x */ \
+            for (int i = 0, xPix = xCentral - (xNum - 1) / 2; i < xNum; i++, xPix++) { \
+                xInterpValue += xKernel[i] * image->data.TYPE[yPix][xPix]; \
+            } \
+            *imageValue += yKernel[j] * xInterpValue; /* Interpolating in y */ \
+        } \
+        break; \
+      }
+
+    // Calculate the value for the image
+    if (imageValue) {
+        *imageValue = 0.0;
+        switch (image->type.type) {
+            SEPARATE_IMAGE_CASE(U8);
+            SEPARATE_IMAGE_CASE(U16);
+            SEPARATE_IMAGE_CASE(U32);
+            SEPARATE_IMAGE_CASE(U64);
+            SEPARATE_IMAGE_CASE(S8);
+            SEPARATE_IMAGE_CASE(S16);
+            SEPARATE_IMAGE_CASE(S32);
+            SEPARATE_IMAGE_CASE(S64);
+            SEPARATE_IMAGE_CASE(F32);
+            SEPARATE_IMAGE_CASE(F64);
+          default:
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Unrecognised type for image: %x",
+                    image->type.type);
+            return PS_INTERPOLATE_STATUS_ERROR;
+        }
+    }
+
+    // Check the mask value
+    const psImage *mask = options->mask; // Image mask
+    psImageInterpolateStatus status = PS_INTERPOLATE_STATUS_GOOD; // Status of interpolation
+    if (maskValue) {
+        *maskValue = 0;
+        if (mask) {
+            psMaskType maskVal = options->maskVal; // Mask value
+            double badContrib = 0.0;        // Amount of kernel on bad pixels
+            double totContrib = 0.0;        // Total amount of kernel
+            bool badPix = false;            // Number of bad pixels
+            for (int j = 0, yPix = yCentral - (yNum - 1) / 2; j < yNum; j++, yPix++) {
+                // Interpolation in x
+                double xBadContrib = 0.0;   // Amount of x kernel on bad pixels
+                double xTotContrib = 0.0;   // Total amount of x kernel
+                for (int i = 0, xPix = xCentral - (xNum - 1) / 2; i < xNum; i++, xPix++) {
+                    if (mask->data.PS_TYPE_MASK_DATA[yPix][xPix] & maskVal) {
+                        xBadContrib += fabs(xKernel[i]);
+                        badPix = true;
+                    }
+                    *maskValue |= mask->data.PS_TYPE_MASK_DATA[yPix][xPix];
+                    xTotContrib += fabs(xKernel[i]);
+                }
+                // Interpolating in y
+                badContrib += fabs(yKernel[j]) * xBadContrib;
+                totContrib += fabs(yKernel[j]) * xTotContrib;
+            }
+
+            if (badPix) {
+                if (badContrib / totContrib >= options->poorFrac) {
+                    *maskValue |= options->badMask;
+                    status = PS_INTERPOLATE_STATUS_BAD;
+                } else {
+                    *maskValue |= options->poorMask;
+                    status = PS_INTERPOLATE_STATUS_POOR;
+                }
+            }
+        }
+    }
+
+    // Finally, the variance
+    const psImage *variance = options->variance; // Image variance
+    if (varianceValue && variance) {
+        *varianceValue = 0.0;
+
+        // Variance interpolation, according to image type
+        #define SEPARATE_VARIANCE_CASE(TYPE) \
+          case PS_TYPE_##TYPE: { \
+            double ySumKernel2 = 0.0; /* Sum of kernel squared in y */ \
+            for (int j = 0, yPix = yCentral - (yNum - 1) / 2; j < yNum; j++, yPix++) { \
+                double xSumKernel2 = 0.0; /* Sum of kernel squared in x */ \
+                double xInterpValue = 0.0; /* Interpolation in x */ \
+                for (int i = 0, xPix = xCentral - (xNum - 1) / 2; i < xNum; i++, xPix++) { \
+                    double kernel2 = PS_SQR(xKernel[i]); /* Kernel squared */ \
+                    xSumKernel2 += kernel2; \
+                    xInterpValue += kernel2 * variance->data.TYPE[yPix][xPix]; \
+                } \
+                double kernel2 = PS_SQR(yKernel[j]); /* Kernel squared */ \
+                ySumKernel2 += xSumKernel2 * kernel2; \
+                *varianceValue += xInterpValue * kernel2; /* Interpolating in y */ \
+            } \
+            *varianceValue /= ySumKernel2; \
+            break; \
+          }
+
+        switch (variance->type.type) {
+            SEPARATE_VARIANCE_CASE(U8);
+            SEPARATE_VARIANCE_CASE(U16);
+            SEPARATE_VARIANCE_CASE(U32);
+            SEPARATE_VARIANCE_CASE(U64);
+            SEPARATE_VARIANCE_CASE(S8);
+            SEPARATE_VARIANCE_CASE(S16);
+            SEPARATE_VARIANCE_CASE(S32);
+            SEPARATE_VARIANCE_CASE(S64);
+            SEPARATE_VARIANCE_CASE(F32);
+            SEPARATE_VARIANCE_CASE(F64);
+          default:
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Unrecognised type for image: %x",
+                    variance->type.type);
+            return PS_INTERPOLATE_STATUS_ERROR;
+        }
+    }
+
+    return status;
+}
+
+
+
+psImageInterpolateStatus psImageInterpolate(double *imageValue, double *varianceValue, psMaskType *maskValue,
+                                            float x, float y, const psImageInterpolateOptions *options)
+{
+    PS_ASSERT_PTR_NON_NULL(options, PS_INTERPOLATE_STATUS_ERROR);
+
+    const psImage *image = options->image; // Image to interpolate
+    const psImage *mask = options->mask; // Mask to interpolate
+    const psImage *variance = options->variance; // Variance to interpolate
+
+    PS_ASSERT_IMAGE_NON_NULL(image, PS_INTERPOLATE_STATUS_ERROR);
+    if (varianceValue && variance) {
+        PS_ASSERT_IMAGE_NON_NULL(variance, PS_INTERPOLATE_STATUS_ERROR);
+        PS_ASSERT_IMAGE_TYPE(variance, image->type.type, PS_INTERPOLATE_STATUS_ERROR);
+        psAssert(image->numCols == variance->numCols && image->numRows == variance->numRows,
+                 "Image and variance sizes");
+    }
+    if (maskValue && mask) {
+        PS_ASSERT_IMAGE_NON_NULL(mask, PS_INTERPOLATE_STATUS_ERROR);
+        PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, PS_INTERPOLATE_STATUS_ERROR);
+        psAssert(image->numCols == mask->numCols && image->numRows == mask->numRows, "Image and mask sizes");
+    }
+
+    PS_ASSERT_FLOAT_LARGER_THAN_OR_EQUAL(options->poorFrac, 0.0, PS_INTERPOLATE_STATUS_ERROR);
+
+    switch (options->mode) {
+      case PS_INTERPOLATE_FLAT:
+        return interpolateFlat(imageValue, varianceValue, maskValue, x, y, options);
+      case PS_INTERPOLATE_BILINEAR:
+      case PS_INTERPOLATE_BICUBE:
+      case PS_INTERPOLATE_GAUSS:
+        return interpolateKernel(imageValue, varianceValue, maskValue, x, y, options);
+      case PS_INTERPOLATE_LANCZOS2:
+      case PS_INTERPOLATE_LANCZOS3:
+      case PS_INTERPOLATE_LANCZOS4:
+        return interpolateSeparate(imageValue, varianceValue, maskValue, x, y, options);
+      default:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified interpolation method (%d) is not supported."),
+                options->mode);
+        return PS_INTERPOLATE_STATUS_ERROR;
+    }
+
+    psAbort("Should never reach here.");
+    return PS_INTERPOLATE_STATUS_ERROR;
+}
+
+
+static float varianceFactorFlat(float x, float y, const psImageInterpolateOptions *options)
+{
+    // There's no smearing
+    return 1.0;
+}
+
+static float varianceFactorKernel(float x, float y, const psImageInterpolateOptions *options)
+{
+    int xNum, yNum;                     // Number of interpolation kernel pixels
+    int xCentral, yCentral;             // Central pixel of the convolution
+    interpolateKernelSetup(&xNum, &yNum, &xCentral, &yCentral, x, y, options->mode);
+
+    const psImage *image = options->image; // Image of interest
+    int xLast = image->numCols - 1;     // Last pixel in x
+    int yLast = image->numRows - 1;     // Last pixel in y
+
+    if (xCentral - (xNum - 1) / 2 < 0 || xCentral + xNum / 2 > xLast ||
+        yCentral - (yNum - 1) / 2 < 0 || yCentral + yNum / 2 > yLast) {
+        // At least one pixel of the interpolation kernel is off the image
+        return NAN;
+    }
+
+    double kernel[yNum][xNum];          // Interpolation kernel for straight interpolation
+    interpolateKernelGenerate(xNum, yNum, kernel, xCentral, yCentral, x, y, options->mode);
+
+    double sumKernel2 = 0.0;            // Sum of kernel squares
+    for (int j = 0; j < yNum; j++) {
+        for (int i = 0; i < xNum; i++) {
+            sumKernel2 += PS_SQR(kernel[j][i]);
+        }
+    }
+
+    return sumKernel2;
+}
+
+static float varianceFactorSeparate(float x, float y, const psImageInterpolateOptions *options)
+{
+    int xNum, yNum;                     // Number of interpolation kernel pixels
+    int xCentral, yCentral;             // Central pixel of the convolution
+    interpolateSeparateSetup(&xNum, &yNum, &xCentral, &yCentral, x, y, options->mode);
+
+    const psImage *image = options->image; // Image of interest
+    int xLast = image->numCols - 1;     // Last pixel in x
+    int yLast = image->numRows - 1;     // Last pixel in y
+
+    if (xCentral - (xNum - 1) / 2 < 0 || xCentral + xNum / 2 > xLast ||
+        yCentral - (yNum - 1) / 2 < 0 || yCentral + yNum / 2 > yLast) {
+        // At least one pixel of the interpolation kernel is off the image
+        return NAN;
+    }
+
+    double xKernel[xNum], yKernel[yNum]; // Interpolation kernels for separable interpolation
+    interpolateSeparateGenerate(xNum, yNum, xKernel, yKernel, xCentral, yCentral, x, y, options->mode);
+
+    double ySumKernel2 = 0.0;           // Sum of kernel squared in y
+    for (int j = 0; j < yNum; j++) {
+        double xSumKernel2 = 0.0;       // Sum of kernel squared in x
+        for (int i = 0; i < xNum; i++) {
+            xSumKernel2 += PS_SQR(xKernel[i]);
+        }
+        ySumKernel2 += xSumKernel2 * PS_SQR(yKernel[j]);
+    }
+
+    return ySumKernel2;
+}
+
+float psImageInterpolateVarianceFactor(float x, float y, const psImageInterpolateOptions *options)
+{
+    PS_ASSERT_PTR_NON_NULL(options, PS_INTERPOLATE_STATUS_ERROR);
+
+    switch (options->mode) {
+      case PS_INTERPOLATE_FLAT:
+        return varianceFactorFlat(x, y, options);
+      case PS_INTERPOLATE_BILINEAR:
+      case PS_INTERPOLATE_BICUBE:
+      case PS_INTERPOLATE_GAUSS:
+        return varianceFactorKernel(x, y, options);
+      case PS_INTERPOLATE_LANCZOS2:
+      case PS_INTERPOLATE_LANCZOS3:
+      case PS_INTERPOLATE_LANCZOS4:
+        return varianceFactorSeparate(x, y, options);
+      default:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified interpolation method (%d) is not supported."),
+                options->mode);
+        return NAN;
+    }
+
+    psAbort("Should never reach here.");
+    return NAN;
+}
+
+
+psImageInterpolateMode psImageInterpolateModeFromString(const char *name)
+{
+    PS_ASSERT_STRING_NON_EMPTY(name, PS_INTERPOLATE_NONE);
+
+    if (!strcasecmp(name, "FLAT"))     return PS_INTERPOLATE_FLAT;
+    if (!strcasecmp(name, "BILINEAR")) return PS_INTERPOLATE_BILINEAR;
+    if (!strcasecmp(name, "BICUBE"))   return PS_INTERPOLATE_BICUBE;
+    if (!strcasecmp(name, "GAUSS"))    return PS_INTERPOLATE_GAUSS;
+    if (!strcasecmp(name, "LANCZOS2")) return PS_INTERPOLATE_LANCZOS2;
+    if (!strcasecmp(name, "LANCZOS3")) return PS_INTERPOLATE_LANCZOS3;
+    if (!strcasecmp(name, "LANCZOS4")) return PS_INTERPOLATE_LANCZOS4;
+
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Unknown interpolation type %s"), name);
+    return PS_INTERPOLATE_NONE;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageInterpolate.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageInterpolate.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageInterpolate.h	(revision 22158)
@@ -0,0 +1,95 @@
+/* @file  psImageInterpolate.h
+ * @brief Functions for interpolating an image
+ *
+ * @author Robert DeSonia, MHPCC
+ * @author Ross Harman, MHPCC
+ * @author Joshua Hoblitt, University of Hawaii
+ * @author Paul Price, Institute for Astronomy
+ *
+ * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-06-17 21:24:58 $
+ * Copyright 2004-2007 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PS_IMAGE_INTERPOLATE_H
+#define PS_IMAGE_INTERPOLATE_H
+
+
+/// Enumeration of options in interpolation
+typedef enum {
+    PS_INTERPOLATE_NONE,               ///< no interpolate defined (error state)
+    PS_INTERPOLATE_FLAT,               ///< Flat interpolation (nearest pixel)
+    PS_INTERPOLATE_BILINEAR,           ///< Bilinear interpolation
+    PS_INTERPOLATE_BICUBE,             ///< Bicubic interpolation with 3x3 region
+    PS_INTERPOLATE_GAUSS,              ///< Gaussian inteprolation with 3x3 region
+    PS_INTERPOLATE_LANCZOS2,           ///< Sinc interpolation with 4x4 pixel kernel
+    PS_INTERPOLATE_LANCZOS3,           ///< Sinc interpolation with 6x6 pixel kernel
+    PS_INTERPOLATE_LANCZOS4,           ///< Sinc interpolation with 8x8 pixel kernel
+} psImageInterpolateMode;
+
+/// Status of interpolation
+typedef enum {
+    PS_INTERPOLATE_STATUS_ERROR = 0,    ///< There was an error
+    PS_INTERPOLATE_STATUS_OFF,          ///< The pixel fell completely off the image or in the border
+    PS_INTERPOLATE_STATUS_BAD,          ///< The pixel is bad
+    PS_INTERPOLATE_STATUS_POOR,         ///< The pixel is poor
+    PS_INTERPOLATE_STATUS_GOOD,         ///< The pixel is good
+} psImageInterpolateStatus;
+
+/// Options for general interpolation.
+///
+/// We stuff in here all the constant values when doing interpolation, so that not all of it has to be pushed
+/// onto the stack in the middle of a tight loop.  For this reason, even the image, mask and variance map are
+/// included.
+typedef struct {
+    psImageInterpolateMode mode;        ///< Interpolation mode
+    const psImage *image;               ///< Input image for interpolation
+    const psImage *variance;            ///< Variance image for interpolation
+    const psImage *mask;                ///< Mask image for interpolation
+    psMaskType maskVal;                 ///< Value to mask
+    double badImage;                    ///< Image value if x,y location is not good
+    double badVariance;                 ///< Variance value if x,y location is not good
+    psMaskType badMask;                 ///< Mask value to give bad pixels
+    psMaskType poorMask;                ///< Mask value to give poor pixels
+    float poorFrac;                     ///< Fraction of flux in bad pixels before output is marked bad
+} psImageInterpolateOptions;
+
+
+/// Allocator
+psImageInterpolateOptions *psImageInterpolateOptionsAlloc(psImageInterpolateMode mode, // Interpolation mode
+                                                          const psImage *image, // Input image
+                                                          const psImage *variance,  // Variance image
+                                                          const psImage *mask, // Mask image
+                                                          psMaskType maskVal, // Value to mask
+                                                          double badImage, // Value for image if bad
+                                                          double badVariance, // Value for variance if bad
+                                                          psMaskType badMask, // Mask value for bad pixels
+                                                          psMaskType poorMask, // Mask value for poor pixels
+                                                          float poorFrac // Fraction of flux for question
+    ) PS_ATTR_MALLOC;
+
+
+
+/// Interpolate image pixel value given floating point coordinates.
+psImageInterpolateStatus psImageInterpolate(double *imageValue, ///< Return value for image
+                                            double *varianceValue, ///< Return value for variance
+                                            psMaskType *maskValue, ///< Return value for mask
+                                            float x, float y, ///< Location to which to interpolate
+                                            const psImageInterpolateOptions *options ///< Options
+    );
+
+
+// Return the appropriate interpolation mode given a char string name for that mode
+psImageInterpolateMode psImageInterpolateModeFromString(const char *name // Mode name
+    );
+
+/// Return the variance factor for the appropriate position
+///
+/// psImageInterpolate sets the variance appropriate for extended regions (on the scale of the interpolation
+/// kernel), but this is not appropriate for pixel-to-pixel statistics.  This function returns the conversion
+/// factor.
+float psImageInterpolateVarianceFactor(float x, float y, ///< Position of interest
+                                       const psImageInterpolateOptions *options ///< Interpolation options
+    );
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageMap.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageMap.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageMap.c	(revision 22158)
@@ -0,0 +1,329 @@
+/** @file  psImageMap.c
+ *
+ *  @brief Functions define a 2d coarse representation of a finer 2D field
+ *
+ *  @ingroup Image
+ *
+ *  @author Eugene Magnier, IfA
+ *
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-12-15 01:20:03 $
+ *
+ *  Copyright 2007 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "psError.h"
+#include "psAbort.h"
+
+#include "psFits.h"
+#include "psAssert.h"
+#include "psRegion.h"
+#include "psFitsImage.h"
+
+#include "psMemory.h"
+#include "psVector.h"
+#include "psImage.h"
+#include "psStats.h"
+#include "psImageBinning.h"
+#include "psImagePixelInterpolate.h"
+#include "psImageUnbin.h"
+
+#include "psImageMap.h"
+
+static void psImageMapFree(psImageMap *map) {
+
+    if (!map) return;
+
+    psFree(map->map);
+    psFree(map->error);
+    psFree(map->stats);
+    psFree(map->binning);
+
+    return;
+}
+
+psImageMap *psImageMapAlloc(const psImage *field, psImageBinning *binning, psStats *stats) {
+    PS_ASSERT_IMAGE_NON_NULL(field, NULL);
+    assert (binning);
+    assert (stats);
+
+    psImageMap *map = (psImageMap*)psAlloc(sizeof(psImageMap));
+    psMemSetDeallocator(map, (psFreeFunc)psImageMapFree);
+
+    map->binning = psMemIncrRefCounter (binning);
+    map->stats   = psMemIncrRefCounter (stats);
+
+    map->col0 = field->col0;
+    map->row0 = field->row0;
+    map->numCols = field->numCols;
+    map->numRows = field->numRows;
+
+    map->map     = psImageAlloc (binning->nXruff, binning->nYruff, PS_TYPE_F32);
+    psImageInit (map->map, 0.0);
+
+    map->error   = psImageAlloc (binning->nXruff, binning->nYruff, PS_TYPE_F32);
+    psImageInit (map->error, 0.0);
+
+    psImageBinningSetScale (map->binning, PS_IMAGE_BINNING_CENTER);
+    psImageBinningSetSkipByOffset (map->binning, map->col0, map->row0);
+
+    return map;
+}
+
+bool psMemCheckImageMap(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) psImageMapFree);
+}
+
+// allocate the image map using the psImageBinning supplied
+psImageMap *psImageMapNoImageAlloc(psImageBinning *binning, psStats *stats) {
+
+    assert (binning);
+    assert (stats);
+
+    psImageMap *map = (psImageMap*)psAlloc(sizeof(psImageMap));
+    psMemSetDeallocator(map, (psFreeFunc)psImageMapFree);
+
+    map->stats   = psMemIncrRefCounter (stats);
+    map->binning = psMemIncrRefCounter (binning);
+
+    map->map     = psImageAlloc (binning->nXruff, binning->nYruff, PS_TYPE_F32);
+    psImageInit (map->map, 0.0);
+
+    map->error   = psImageAlloc (binning->nXruff, binning->nYruff, PS_TYPE_F32);
+    psImageInit (map->error, 0.0);
+
+    return map;
+}
+
+bool psImageMapModifyScale(psImageMap *map, int nXruff, int nYruff)
+{
+    assert (map);
+
+    map->binning->nXruff = nXruff;
+    map->binning->nYruff = nYruff;
+
+    psImageRecycle (map->map, nXruff, nYruff, PS_TYPE_F32);
+    psImageRecycle (map->error, nXruff, nYruff, PS_TYPE_F32);
+
+    psImageBinningSetScale (map->binning, PS_IMAGE_BINNING_CENTER);
+    psImageBinningSetSkipByOffset (map->binning, map->col0, map->row0);
+
+    return true;
+}
+
+// generate a psImageMap (or NULL) with the given number of superpixels in X and Y
+// this function returns an error if the output map has impossible holes
+bool psImageMapGenerate(psImageMap *map, const psVector *x, const psVector *y,
+                        const psVector *f, const psVector *df, float badFrac)
+{
+    // XXX asserts
+
+    psImage *mask = psImageAlloc (map->map->numCols, map->map->numRows, PS_TYPE_MASK);
+    psImage *xCoord = psImageAlloc (map->map->numCols, map->map->numRows, PS_TYPE_F32);
+    psImage *yCoord = psImageAlloc (map->map->numCols, map->map->numRows, PS_TYPE_F32);
+
+    // accumulate the values for each map pixel
+
+    // we can do this by accumulating a vector of pixel indexes for each cell
+    psArray *pixelSets = psArrayAlloc (map->map->numCols*map->map->numRows);
+    for (int i = 0; i < pixelSets->n; i++) {
+        pixelSets->data[i] = psVectorAllocEmpty (4, PS_TYPE_S32);
+    }
+    // associate each value with a cell
+    for (int i = 0; i < x->n; i++) {
+        int xRuff = psImageBinningGetRuffX (map->binning, x->data.F32[i]);
+        int yRuff = psImageBinningGetRuffY (map->binning, y->data.F32[i]);
+
+        int bin = xRuff + yRuff*map->map->numCols;
+        assert (bin >= 0);
+        assert (bin < pixelSets->n);
+
+        psVector *pixels = pixelSets->data[bin];
+        pixels->data.S32[pixels->n] = i;
+        psVectorExtend (pixels, 4, 1);
+    }
+
+    // stats structure for getting the position centers
+    psStats *meanStat = psStatsAlloc (PS_STAT_SAMPLE_MEAN);
+
+    // accumulate the x,y coords for each point to calculate the mean position.
+    int Nx = map->map->numCols;
+    int Ny = map->map->numRows;
+    for (int iy = 0; iy < Ny; iy++) {
+        for (int ix = 0; ix < Nx; ix++) {
+
+            // pixel index for this cell
+            psVector *pixels = pixelSets->data[ix + iy*Nx];
+
+            // storage vectors
+            psVector *xCell = psVectorAlloc (pixels->n, PS_TYPE_F32);
+            psVector *yCell = psVectorAlloc (pixels->n, PS_TYPE_F32);
+            psVector *fCell = psVectorAlloc (pixels->n, PS_TYPE_F32);
+
+            // error vector, if needed
+            psVector *dfCell = NULL;
+            if (df) {
+                dfCell = psVectorAlloc (pixels->n, PS_TYPE_F32);
+            }
+
+            // collect data for this cell
+            for (int i = 0; i < pixels->n; i++) {
+                int bin = pixels->data.S32[i];
+                // convert x,y in the fine image to the ruff image
+                xCell->data.F32[i]  = psImageBinningGetRuffX (map->binning, x->data.F32[bin]);
+                yCell->data.F32[i]  = psImageBinningGetRuffY (map->binning, y->data.F32[bin]);
+                fCell->data.F32[i]  = f->data.F32[bin];
+                if (df) {
+                    dfCell->data.F32[i] = df->data.F32[bin];
+                }
+            }
+
+            // reset the stats to avoid contamination from the previous loop
+            psStatsInit (map->stats);
+
+            // get the value
+            // XXX need to supply a mask and skip the masked pixels when calculating the centroid
+            // this will not in general be properly weighted...
+            if (psVectorStats (map->stats, fCell, dfCell, NULL, 0)) {
+                mask->data.U8[iy][ix] = 0;
+                // XXX ensure only one option is selected, or save both position and width
+                map->map->data.F32[iy][ix] = psStatsGetValue (map->stats, map->stats->options);
+
+                // calculate the mean position and save:
+                psStatsInit (meanStat);
+                psVectorStats (meanStat, xCell, NULL, NULL, 0);
+                xCoord->data.F32[iy][ix] = psStatsGetValue (meanStat, meanStat->options);
+                psStatsInit (meanStat);
+                psVectorStats (meanStat, yCell, NULL, NULL, 0);
+                yCoord->data.F32[iy][ix] = psStatsGetValue (meanStat, meanStat->options);
+            } else {
+                mask->data.U8[iy][ix] = 1;
+            }
+
+            psFree (xCell);
+            psFree (yCell);
+            psFree (fCell);
+            psFree (dfCell);
+        }
+    }
+    psFree (pixelSets);
+    psFree (meanStat);
+   // at this point, for each map pixel, we have (f,x,y), or the pixel is masked.
+
+    psFits *fits = NULL;
+
+    fits = psFitsOpen ("imageMap.raw.fits", "w");
+    psFitsWriteImage (fits, NULL, map->map, 0, NULL);
+    psFitsClose (fits);
+
+    // did this analysis succeed?  (enough good or OK pixels?)
+    psImage *state = psImagePixelInterpolateState (&map->nBad, &map->nPoor, mask, 0xff);
+    map->nGood = mask->numCols * mask->numRows - map->nBad - map->nPoor;
+    if (map->nBad > badFrac * mask->numCols * mask->numRows) {
+        psFree (xCoord);
+        psFree (yCoord);
+        psFree (mask);
+        return false;
+    }
+
+    // fit the valid pixels to (0,1,2) order polynomials, interpolate values to the pixel center
+    // XXX I need to be careful about the pixel coordinates: center is 0,0 or 0.5, 0.5?
+    psImagePixelInterpolateCenter (map->map, xCoord, yCoord, state, mask, 0xff);
+    psFree (xCoord);
+    psFree (yCoord);
+
+    fits = psFitsOpen ("imageMap.ref.fits", "w");
+    psFitsWriteImage (fits, NULL, map->map, 0, NULL);
+    psFitsClose (fits);
+
+    psImagePixelInterpolatePoor (map->map, state, mask, 0xff);
+
+    fits = psFitsOpen ("imageMap.fix.fits", "w");
+    psFitsWriteImage (fits, NULL, map->map, 0, NULL);
+    psFitsClose (fits);
+
+    psFree (state);
+    psFree (mask);
+    return true;
+}
+
+// using the points given, generate a map with maximum resolution that yields only good and ok pixels
+bool psImageMapGenerateScale(psImageMap *map, const psVector *x, const psVector *y,
+                             const psVector *f, const psVector *df, float badFrac)
+{
+    // XXX Asserts
+
+    int nXruff, nYruff;
+
+    while (!psImageMapGenerate (map, x, y, f, df, badFrac)) {
+        // if we failed to build an acceptable map, decrease nXruff, nYruff as appropriate, and
+        // try again...  try to keep the aspect ratio.
+
+        // if both axes are at 1, give up
+        if ((map->binning->nXruff == 1) && (map->binning->nYruff == 1)) {
+            return false;
+        }
+
+        // if one axis is at 1, decrement the other
+        if (map->binning->nXruff == 1) {
+            nXruff = map->binning->nXruff;
+            nYruff = map->binning->nYruff - 1;
+            psImageMapModifyScale (map, nXruff, nYruff);
+            continue;
+        }
+        if (map->binning->nYruff == 1) {
+            nYruff = map->binning->nYruff;
+            nXruff = map->binning->nXruff - 1;
+            psImageMapModifyScale (map, nXruff, nYruff);
+            continue;
+        }
+
+        // otherwise, decrement the larger axis, and set the smaller based
+        // on the aspect ratio
+        float aRatio = map->binning->nXruff / map->binning->nYruff;
+        if (map->binning->nXruff > map->binning->nYruff) {
+            nXruff = map->binning->nXruff - 1;
+            nYruff = (int)(0.5 + (nXruff / aRatio));
+        } else {
+            nYruff = map->binning->nYruff - 1;
+            nXruff = (int)(0.5 + (nYruff * aRatio));
+        }
+
+        psImageMapModifyScale (map, nXruff, nYruff);
+    }
+    return true;
+}
+
+// x,y are in fractional pixel coords of the fine image (pixel center: 0.5)
+double psImageMapEval(const psImageMap *map, float x, float y) {
+
+    double result;
+
+    result = psImageUnbinPixel_V2(x, y, map->map, map->binning);
+
+    return result;
+}
+
+psVector *psImageMapEvalVector(const psImageMap *map, const psVector *x, const psVector *y) {
+
+    assert (x);
+    assert (y);
+    assert (x->n == y->n);
+    assert (map);
+
+    psVector *result = psVectorAlloc (x->n, PS_TYPE_F32);
+
+    for (int i = 0; i < x->n; i++) {
+        result->data.F32[i] = psImageUnbinPixel_V2(x->data.F32[i], y->data.F32[i], map->map, map->binning);
+    }
+
+    return result;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageMap.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageMap.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageMap.h	(revision 22158)
@@ -0,0 +1,62 @@
+/** @file  psImageMap.c
+ *
+ *  @brief Functions define a 2d coarse representation of a finer 2D field
+ *
+ *  @ingroup Image
+ *
+ *  @author Eugene Magnier, IfA
+ *
+ *  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-12-15 01:20:03 $
+ *
+ *  Copyright 2007 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PS_IMAGE_MAP_H
+#define PS_IMAGE_MAP_H
+
+/// @addtogroup ImageOps Image Operations
+/// @{
+
+#include <psStats.h>
+#include <psImage.h>
+#include <psImageBinning.h>
+#include <psVector.h>
+
+// a structure to describe the 2D variations of some quantity as a function of position the
+// variation is represented as a psImage which covers the field also represented as a psImage.
+// the map image pixels are superpixels of the field image.  values in the field are determined
+// by interpolating the map image.
+typedef struct {
+    psStats *stats;
+    psImage *map;
+    psImage *error;
+    int col0, row0;                     // Column and row offsets from the original image
+    int numCols, numRows;               // Size of original image
+    psImageBinning *binning;
+    int nBad;
+    int nPoor;
+    int nGood;
+    psStatsOptions singleMean, singleStdev;  // Statistics for mean and stdev when there's a single pixel
+} psImageMap;
+
+psImageMap *psImageMapAlloc(const psImage *field, psImageBinning *binning, psStats *stats) PS_ATTR_MALLOC;
+bool psMemCheckImageMap(psPtr ptr);
+
+psImageMap *psImageMapNoImageAlloc(psImageBinning *binning, psStats *stats) PS_ATTR_MALLOC;
+
+bool psImageMapModifyScale(psImageMap *map, int nXruff, int nYruff);
+
+// generate a psImageMap (or NULL) with the given number of superpixels in X and Y
+bool psImageMapGenerate (psImageMap *map, const psVector *x, const psVector *y, const psVector *f, const psVector *df, float badFrac);
+
+bool psImageMapGenerateScale (psImageMap *map, const psVector *x, const psVector *y, const psVector *f, const psVector *df, float badFrac);
+
+// apply the psImageMap to the given coordinate (fine image pixels)
+double psImageMapEval (const psImageMap *map, float x, float y);
+
+// apply the psImageMap to the given coordinate vectors (fine image pixels)
+psVector *psImageMapEvalVector (const psImageMap *map, const psVector *x, const psVector *y);
+
+/// @}
+#endif // #ifndef PS_IMAGE_MAP_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageMapFit.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageMapFit.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageMapFit.c	(revision 22158)
@@ -0,0 +1,746 @@
+/** @file  psImageMapFit.c
+ *
+ *  @brief Functions define a 2d coarse representation of a finer 2D field
+ *
+ *  @ingroup Image
+ *
+ *  @author Eugene Magnier, IfA
+ *
+ *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-05-10 01:33:26 $
+ *
+ *  Copyright 2007 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include "psError.h"
+#include "psAbort.h"
+#include "psTrace.h"
+
+// #include "psFits.h"
+#include "psAssert.h"
+#include "psRegion.h"
+// #include "psFitsImage.h"
+
+#include "psMemory.h"
+#include "psVector.h"
+#include "psImage.h"
+#include "psMatrix.h"
+#include "psStats.h"
+#include "psImageBinning.h"
+#include "psImageMap.h"
+// #include "psImagePixelInterpolate.h"
+// #include "psImageUnbin.h"
+
+#include "psImageMapFit.h"
+
+
+// given a randomly-sampled field of values & weights at points: (f, df) @ (x, y), find the
+// best fit image from which Bilinear interpolation yields the input field.  The fitted image
+// consists of a grid of values g(n,m) at coordinates (n,m).
+
+// relationship between x,y and n,m coordinates:
+
+// map defines the output image dimensions and scaling.
+bool psImageMapFit(psImageMap *map, const psVector *mask, psMaskType maskValue,
+                   const psVector *x, const psVector *y, const psVector *f, const psVector *df)
+{
+    // XXX Add Asserts
+
+    // dimensions of the output map image
+    int Nx = map->binning->nXruff;
+    int Ny = map->binning->nYruff;
+
+    // no spatial information, just calculate mean & stdev
+    if ((Nx == 1) && (Ny == 1)) {
+        psStatsInit(map->stats);
+
+        // the user has supplied one of various stats option pairs,
+        psStatsOptions mean = psStatsMeanOption(map->stats->options);
+        psStatsOptions stdev = psStatsStdevOption(map->stats->options);
+        if (!psStatsSingleOption(mean)) {
+            psError(PS_ERR_UNKNOWN, true, "no valid mean stats option selected");
+            return false;
+        }
+        if (!psStatsSingleOption(stdev)) {
+            psError(PS_ERR_UNKNOWN, true, "no valid stdev stats option selected");
+            return false;
+        }
+
+        // XXX does ROBUST_MEDIAN work with weight?
+        psVectorStats(map->stats, f, NULL, mask, maskValue);
+
+        map->map->data.F32[0][0]   = psStatsGetValue(map->stats, mean);
+        map->error->data.F32[0][0] = psStatsGetValue(map->stats, stdev);
+        return true;
+    }
+
+    if (Nx == 1) {
+        bool status;
+        status = psImageMapFit1DinY (map, mask, maskValue, x, y, f, df);
+        return status;
+    }
+    if (Ny == 1) {
+        bool status;
+        status = psImageMapFit1DinX (map, mask, maskValue, x, y, f, df);
+        return status;
+    }
+
+    // set up the redirection table so we can use sA[-1][-1], etc
+    // XXX psKernel does this for you --- PAP.
+    float SAm[3][3], *SAv[3], **sA;
+    // float TAm[3][3], *TAv[3], **tA;
+
+    for (int i = 0; i < 3; i++) {
+        SAv[i] = SAm[i] + 1;
+        // TAv[i] = TAm[i] + 1;
+    }
+    sA = SAv + 1;
+    // tA = TAv + 1;
+
+    // elements of the matrix equation Ax = B; we are solving for the vector x
+    psImage *A = psImageAlloc (Nx*Ny, Nx*Ny, PS_TYPE_F32);
+    psVector *B = psVectorAlloc (Nx*Ny, PS_TYPE_F32);
+
+    psImageInit (A, 0.0);
+    psVectorInit (B, 0.0);
+
+    // we are looping over the Nx,Ny image map elements;
+    // the matrix equation contains Nx*Ny rows and columns
+    // for (int n = 1; n < Nx - 1; n++) {
+    // for (int m = 1; m < Ny - 1; m++) {
+
+    // float Total = 0.0;
+    for (int n = 0; n < Nx; n++) {
+        for (int m = 0; m < Ny; m++) {
+            // define & init summing variables
+            float rx_rx_ry_ry = 0;
+            float rx_rx_dy_ry = 0;
+            float dx_rx_ry_ry = 0;
+            float dx_rx_dy_ry = 0;
+            float fi_rx_ry    = 0;
+            float rx_rx_py_py = 0;
+            float rx_rx_qy_py = 0;
+            float dx_rx_py_py = 0;
+            float dx_rx_qy_py = 0;
+            float fi_rx_py    = 0;
+            float px_px_ry_ry = 0;
+            float px_px_dy_ry = 0;
+            float qx_px_ry_ry = 0;
+            float qx_px_dy_ry = 0;
+            float fi_px_ry    = 0;
+            float px_px_py_py = 0;
+            float px_px_qy_py = 0;
+            float qx_px_py_py = 0;
+            float qx_px_qy_py = 0;
+            float fi_px_py    = 0;
+
+            // generate the sums for the fitting matrix element I,J
+            // I = n + nX*m
+            // J = (n + jn) + nX*(m + jm)
+            for (int i = 0; i < x->n; i++) {
+
+                if (mask && (mask->data.U8[i] & maskValue)) continue;
+
+                // base coordinate offset for this point (x,y) relative to this map element (n,m)
+                // float dx = x->data.F32[i] - psImageBinningGetFineX (map->binning, n + 0.5);
+                // float dy = y->data.F32[i] - psImageBinningGetFineY (map->binning, m + 0.5);
+
+                float dx = psImageBinningGetRuffX (map->binning, x->data.F32[i]) - (n + 0.5);
+                float dy = psImageBinningGetRuffY (map->binning, y->data.F32[i]) - (m + 0.5);
+
+                // edge cases to include:
+                bool edgeX = false;
+                edgeX |= ((n == 1) && (dx < -1.0));
+                edgeX |= ((n == Nx - 2) && (dx > +1.0));
+
+                bool edgeY = false;
+                edgeY |= ((m == 1) && (dy < -1.0));
+                edgeY |= ((m == Ny - 2) && (dy > +1.0));
+
+                // skip points outside of 2x2 grid centered on n,m:
+                if (!edgeX && (fabs(dx) > 1.0)) continue;
+                if (!edgeY && (fabs(dy) > 1.0)) continue;
+
+                // related offset values
+                float rx = 1.0 - dx;
+                float ry = 1.0 - dy;
+                float px = 1.0 + dx;
+                float py = 1.0 + dy;
+                float qx = -dx;
+                float qy = -dy;
+
+                // data value & weight for this point
+                float fi = f->data.F32[i];
+                float wt = 1.0;
+                if (df != NULL) {
+                    if (df->data.F32[i] == 0.0) {
+                        wt = 0.0;
+                    } else {
+                        wt = 1.0 / PS_SQR(df->data.F32[i]); // XXX test for dz == NULL or dz_i = 0
+                    }
+                }
+
+                // sum the appropriate elements for the different quadrants
+
+                int Qx = (dx >= 0) ? 1 : 0;
+                if (n ==      0) Qx = 1;
+                if (n == Nx - 1) Qx = 0;
+
+                int Qy = (dy >= 0) ? 1 : 0;
+                if (m ==      0) Qy = 1;
+                if (m == Ny - 1) Qy = 0;
+
+                assert (isfinite(fi));
+                assert (isfinite(wt));
+                assert (isfinite(rx));
+                assert (isfinite(ry));
+
+                // points at offset 1,1
+                if ((Qx == 1) && (Qy == 1)) {
+                    rx_rx_ry_ry += rx*rx*ry*ry*wt;
+                    rx_rx_dy_ry += rx*rx*dy*ry*wt;
+                    dx_rx_ry_ry += dx*rx*ry*ry*wt;
+                    dx_rx_dy_ry += dx*rx*dy*ry*wt;
+                    fi_rx_ry    += fi*rx*ry*wt;
+                }
+                // points at offset 1,0
+                if ((Qx == 1) && (Qy == 0)) {
+                    rx_rx_py_py += rx*rx*py*py*wt;
+                    rx_rx_qy_py += rx*rx*qy*py*wt;
+                    dx_rx_py_py += dx*rx*py*py*wt;
+                    dx_rx_qy_py += dx*rx*qy*py*wt;
+                    fi_rx_py    += fi*rx*py*wt;
+                }
+                // points at offset 0,1
+                if ((Qx == 0) && (Qy == 1)) {
+                    px_px_ry_ry += px*px*ry*ry*wt;
+                    px_px_dy_ry += px*px*dy*ry*wt;
+                    qx_px_ry_ry += qx*px*ry*ry*wt;
+                    qx_px_dy_ry += qx*px*dy*ry*wt;
+                    fi_px_ry    += fi*px*ry*wt;
+                }
+                // points at offset 0,0
+                if ((Qx == 0) && (Qy == 0)) {
+                    px_px_py_py += px*px*py*py*wt;
+                    px_px_qy_py += px*px*qy*py*wt;
+                    qx_px_py_py += qx*px*py*py*wt;
+                    qx_px_qy_py += qx*px*qy*py*wt;
+                    fi_px_py    += fi*px*py*wt;
+                }
+            }
+
+            // the chi-square derivatives have elements of the form g(n+jn,m+jm)*A(jn,jm),
+            // jn,jm = -1 to +1. Convert the sums above into the correct coefficients
+            sA[-1][-1] = qx_px_qy_py;
+            sA[-1][ 0] = qx_px_ry_ry + qx_px_py_py;
+            sA[-1][+1] = qx_px_dy_ry;
+            sA[ 0][-1] = rx_rx_qy_py + px_px_qy_py;
+            sA[ 0][ 0] = rx_rx_ry_ry + px_px_ry_ry + rx_rx_py_py + px_px_py_py;
+            sA[ 0][+1] = rx_rx_dy_ry + px_px_dy_ry;
+            sA[+1][-1] = dx_rx_qy_py;
+            sA[+1][ 0] = dx_rx_ry_ry + dx_rx_py_py;
+            sA[+1][+1] = dx_rx_dy_ry;
+
+            // I[ 0][ 0] = index for this n,m element:
+            int I = n + Nx * m;
+            B->data.F32[I] = fi_rx_ry + fi_rx_py + fi_px_ry + fi_px_py;
+
+            // insert these values into their corresponding locations in A, B
+            // float Sum = 0.0;
+            for (int jn = -1; jn <= +1; jn++) {
+                if (n + jn <   0) continue;
+                if (n + jn >= Nx) continue;
+                for (int jm = -1; jm <= +1; jm++) {
+                    if (m + jm <   0) continue;
+                    if (m + jm >= Ny) continue;
+                    int J = (n + jn) + Nx * (m + jm);
+                    A->data.F32[J][I] = sA[jn][jm];
+                    // fprintf (stderr, "A %d %d (%d %d : %d %d): %f\n", I, J, n, m, n + jn, m + jm, sA[jn][jm]);
+                    // Sum += sA[jn][jm];
+                }
+            }
+            // fprintf (stderr, "B %d (%d %d) : %f  :  %f\n", I, n, m, B->data.F32[I], Sum);
+            // Total += Sum;
+        }
+    }
+    // fprintf (stderr, "Total: %f\n", Total);
+
+    // test for empty diagonal elements (unconstained cells), mark, and set pivots to 1.0
+    psVector *Empty = psVectorAlloc (Nx*Ny, PS_TYPE_S8);
+    psVectorInit (Empty, 0);
+    for (int i = 0; i < Nx*Ny; i++) {
+        if (A->data.F32[i][i] == 0.0) {
+            Empty->data.S8[i] = 1;
+            for (int j = 0; j < Nx*Ny; j++) {
+                A->data.F32[i][j] = 0.0;
+                A->data.F32[j][i] = 0.0;
+            }
+            A->data.F32[i][i] = 1.0;
+            B->data.F32[i] = 0.0;
+        }
+    }
+
+# if (0)
+    psFits *fits = psFitsOpen ("Agj.fits", "w");
+    psFitsWriteImage (fits, NULL, A, 0, NULL);
+    psFitsClose (fits);
+
+    psImage *vector = psImageAlloc (1, B->n, PS_TYPE_F32);
+    for (int n = 0; n < B->n; n++) {
+        vector->data.F32[0][n] = B->data.F32[n];
+    }
+
+    fits = psFitsOpen ("Bgj.fits", "w");
+    psFitsWriteImage (fits, NULL, vector, 0, NULL);
+    psFitsClose (fits);
+    psFree (vector);
+# endif
+
+    if (!psMatrixGJSolveF32(A, B)) {
+        psAbort ("failed on linear equations");
+        psError(PS_ERR_UNKNOWN, false, "Could not solve linear equations.  Returning NULL.\n");
+        psFree (A);
+        psFree (B);
+        return false;
+    }
+
+    // set bad values to NaN
+    for (int i = 0; i < Nx*Ny; i++) {
+        if (Empty->data.S8[i]) {
+            B->data.F32[i] = NAN;
+        }
+    }
+
+
+    for (int n = 0; n < Nx; n++) {
+        for (int m = 0; m < Ny; m++) {
+            int I = n + Nx * m;
+            map->map->data.F32[m][n] = B->data.F32[I];
+            map->error->data.F32[m][n] = sqrt(A->data.F32[I][I]);
+        }
+    }
+
+    psFree (A);
+    psFree (B);
+    psFree (Empty);
+
+    return true;
+}
+
+// measure residuals on each pass and clip outliers based on stats
+bool psImageMapClipFit(psImageMap *map, psStats *stats, psVector *inMask, psMaskType maskValue,
+                       const psVector *x, const psVector *y, const psVector *f, const psVector *df)
+{
+    // XXX add in full PS_ASSERTS
+    psAssert(map, "impossible");
+    psAssert(stats, "impossible");
+    psAssert(x, "impossible");
+    psAssert(y, "impossible");
+    psAssert(f, "impossible");
+
+    // the user supplies one of various stats option pairs,
+    // determine the desired mean and stdev STATS options:
+    psStatsOptions meanOption = psStatsMeanOption(stats->options);
+    psStatsOptions stdevOption = psStatsStdevOption(stats->options);
+    if (!psStatsSingleOption(meanOption)) {
+        psError(PS_ERR_UNKNOWN, true, "no valid mean stats option selected");
+        return false;
+    }
+    if (!psStatsSingleOption(stdevOption)) {
+        psError(PS_ERR_UNKNOWN, true, "no valid stdev stats option selected");
+        return false;
+    }
+
+    // clipping range defined by min and max and/or clipSigma
+    psF32 minClipSigma;
+    psF32 maxClipSigma;
+    if (isfinite(stats->max)) {
+        maxClipSigma = fabs(stats->max);
+    } else {
+        maxClipSigma = fabs(stats->clipSigma);
+    }
+    if (isfinite(stats->min)) {
+        minClipSigma = fabs(stats->min);
+    } else {
+        minClipSigma = fabs(stats->clipSigma);
+    }
+
+    psVector *mask = inMask;
+    if (!inMask) {
+        mask = psVectorAlloc (x->n, PS_TYPE_U8);
+        psVectorInit (mask, 0);
+    }
+
+    // vector to store residuals
+    psVector *resid = psVectorAlloc(f->n, PS_TYPE_F32);
+
+    psTrace("psLib.imageops", 4, "stats->clipIter is %d\n", stats->clipIter);
+    psTrace("psLib.imageops", 4, "(minClipSigma, maxClipSigma) is (%.2f, %.2f)\n", minClipSigma, maxClipSigma);
+
+    for (psS32 N = 0; N < stats->clipIter; N++) {
+        psTrace("psLib.imageops", 6, "Loop iteration %d.  Calling psImageMapFit()\n", N);
+        psS32 Nkeep = 0;
+        if (!psImageMapFit(map, mask, maskValue, x, y, f, df)) {
+            psError(PS_ERR_UNKNOWN, false, "Could not fit image map.\n");
+            psFree(resid);
+            if (!inMask) psFree (mask);
+            return false;
+        }
+
+        psVector *fit = psImageMapEvalVector(map, x, y);
+        if (fit == NULL) {
+            psError(PS_ERR_UNKNOWN, false, "Failure in psImageMapEvalVector().\n");
+            psFree(resid);
+            if (!inMask) psFree (mask);
+            return false;
+        }
+        for (int i = 0 ; i < f->n ; i++) {
+            resid->data.F32[i] = (f->data.F32[i] - fit->data.F32[i]);
+        }
+
+        if (!psVectorStats(stats, resid, NULL, mask, maskValue)) {
+            psError(PS_ERR_UNKNOWN, false, "Failure to compute statistics on the resid vector.\n");
+            psFree(resid);
+            psFree(fit);
+            if (!inMask) psFree (mask);
+            return false;
+        }
+
+        double meanValue = psStatsGetValue (stats, meanOption);
+        double stdevValue = psStatsGetValue (stats, stdevOption);
+
+        psTrace("psLib.imageops", 5, "Mean is %f\n", meanValue);
+        psTrace("psLib.imageops", 5, "Stdev is %f\n", stdevValue);
+        psF32 minClipValue = -minClipSigma*stdevValue;
+        psF32 maxClipValue = +maxClipSigma*stdevValue;
+
+        // set mask if pts are not valid
+        // we are masking out any point which is out of range
+        // recovery is not allowed with this scheme
+        for (psS32 i = 0; i < resid->n; i++) {
+            // XXX this prevents recovery of previously masked values
+            if (mask->data.U8[i] & maskValue) {
+                continue;
+            }
+
+            if ((resid->data.F32[i] - meanValue > maxClipValue) || (resid->data.F32[i] - meanValue < minClipValue)) {
+                psTrace("psLib.imageops", 6, "Masking element %d  : %f vs %f : resid is %f\n", i, f->data.F32[i], fit->data.F32[i], resid->data.F32[i]);
+                mask->data.U8[i] |= 0x01;
+                continue;
+            }
+            Nkeep++;
+        }
+
+        // We should probably exit this loop if no new elements were masked since the fit won't
+        // change.
+        psTrace("psLib.imageops", 6, "keeping %d of %ld pts for fit\n", Nkeep, x->n);
+        stats->clippedNvalues = Nkeep;
+        psFree(fit);
+    }
+
+    // Free local temporary variables
+    psFree(resid);
+    if (!inMask) psFree (mask);
+    return true;
+}
+
+// map defines the output image dimensions and scaling.
+bool psImageMapFit1DinY(psImageMap *map, const psVector *mask, psMaskType maskValue,
+                        const psVector *x, const psVector *y, const psVector *f, const psVector *df)
+{
+    // XXX Add Asserts
+    assert (map->binning->nXruff == 1);
+
+    // dimensions of the output map image
+    int Ny = map->binning->nYruff;
+
+    // set up the redirection table so we can use sA[-1][-1], etc
+    float SAv[3], *sA;
+
+    sA = SAv + 1;
+
+    // elements of the matrix equation Ax = B; we are solving for the vector x
+    psImage *A = psImageAlloc (Ny, Ny, PS_TYPE_F32);
+    psVector *B = psVectorAlloc (Ny, PS_TYPE_F32);
+
+    psImageInit (A, 0.0);
+    psVectorInit (B, 0.0);
+
+    for (int m = 0; m < Ny; m++) {
+        // define & init summing variables
+        float ry_ry = 0;
+        float dy_ry = 0;
+        float fi_ry = 0;
+        float py_py = 0;
+        float qy_py = 0;
+        float fi_py = 0;
+
+        // generate the sums for the fitting matrix element I,J
+        // I = m
+        // J = m + jm
+        for (int i = 0; i < y->n; i++) {
+
+            if (mask && (mask->data.U8[i] & maskValue)) continue;
+
+            float dy = psImageBinningGetRuffY (map->binning, y->data.F32[i]) - (m + 0.5);
+
+            bool edgeY = false;
+            edgeY |= ((m == 1) && (dy < -1.0));
+            edgeY |= ((m == Ny - 2) && (dy > +1.0));
+
+            // skip points outside of 2x2 grid centered on n,m:
+            if (!edgeY && (fabs(dy) > 1.0)) continue;
+
+            // related offset values
+            float ry = 1.0 - dy;
+            float py = 1.0 + dy;
+            float qy = -dy;
+
+            // data value & weight for this point
+            float fi = f->data.F32[i];
+            float wt = 1.0;
+            if (df != NULL) {
+                if (df->data.F32[i] == 0.0) {
+                    wt = 0.0;
+                } else {
+                    wt = 1.0 / PS_SQR(df->data.F32[i]); // XXX test for dz == NULL or dz_i = 0
+                }
+            }
+
+            // sum the appropriate elements for the different quadrants
+            int Qy = (dy >= 0) ? 1 : 0;
+            if (m ==      0) Qy = 1;
+            if (m == Ny - 1) Qy = 0;
+
+            assert (isfinite(fi));
+            assert (isfinite(wt));
+            assert (isfinite(ry));
+
+            // points at offset 1,1
+            if (Qy == 1) {
+                ry_ry += ry*ry*wt;
+                dy_ry += dy*ry*wt;
+                fi_ry += fi*ry*wt;
+            }
+            // points at offset 1,0
+            if (Qy == 0) {
+                py_py += py*py*wt;
+                qy_py += qy*py*wt;
+                fi_py += fi*py*wt;
+            }
+        }
+
+        // the chi-square derivatives have elements of the form g(n+jn,m+jm)*A(jn,jm),
+        // jn,jm = -1 to +1. Convert the sums above into the correct coefficients
+        sA[-1] = qy_py;
+        sA[ 0] = ry_ry + py_py;
+        sA[+1] = dy_ry;
+
+        // I[ 0][ 0] = index for this n,m element:
+        int I = m;
+        B->data.F32[I] = fi_ry + fi_py;
+
+        // insert these values into their corresponding locations in A, B
+        for (int jm = -1; jm <= +1; jm++) {
+            if (m + jm <   0) continue;
+            if (m + jm >= Ny) continue;
+            int J = (m + jm);
+            A->data.F32[J][I] = sA[jm];
+        }
+    }
+
+    // test for empty diagonal elements (unconstained cells), mark, and set pivots to 1.0
+    psVector *Empty = psVectorAlloc (Ny, PS_TYPE_S8);
+    psVectorInit (Empty, 0);
+    for (int i = 0; i < Ny; i++) {
+        if (A->data.F32[i][i] == 0.0) {
+            Empty->data.S8[i] = 1;
+            for (int j = 0; j < Ny; j++) {
+                A->data.F32[i][j] = 0.0;
+                A->data.F32[j][i] = 0.0;
+            }
+            A->data.F32[i][i] = 1.0;
+            B->data.F32[i] = 0.0;
+        }
+    }
+
+    if (!psMatrixGJSolveF32(A, B)) {
+        psAbort ("failed on linear equations");
+        psError(PS_ERR_UNKNOWN, false, "Could not solve linear equations.  Returning NULL.\n");
+        psFree (A);
+        psFree (B);
+        return false;
+    }
+
+    // set bad values to NaN
+    for (int i = 0; i < Ny; i++) {
+        if (Empty->data.S8[i]) {
+            B->data.F32[i] = NAN;
+        }
+    }
+
+    for (int m = 0; m < Ny; m++) {
+        map->map->data.F32[m][0] = B->data.F32[m];
+        map->error->data.F32[m][0] = sqrt(A->data.F32[m][m]);
+    }
+
+    psFree (A);
+    psFree (B);
+    psFree (Empty);
+
+    return true;
+}
+
+// map defines the output image dimensions and scaling.
+bool psImageMapFit1DinX(psImageMap *map, const psVector *mask, psMaskType maskValue,
+                        const psVector *x, const psVector *y, const psVector *f, const psVector *df)
+{
+    // XXX Add Asserts
+    assert (map->binning->nYruff == 1);
+
+    // dimensions of the output map image
+    int Nx = map->binning->nXruff;
+
+    // set up the redirection table so we can use sA[-1][-1], etc
+    float SAv[3], *sA;
+
+    sA = SAv + 1;
+
+    // elements of the matrix equation Ax = B; we are solving for the vector x
+    psImage *A = psImageAlloc (Nx, Nx, PS_TYPE_F32);
+    psVector *B = psVectorAlloc (Nx, PS_TYPE_F32);
+
+    psImageInit (A, 0.0);
+    psVectorInit (B, 0.0);
+
+    for (int m = 0; m < Nx; m++) {
+        // define & init summing variables
+        float rx_rx = 0;
+        float dx_rx = 0;
+        float fi_rx = 0;
+        float px_px = 0;
+        float qx_px = 0;
+        float fi_px = 0;
+
+        // generate the sums for the fitting matrix element I,J
+        // I = m
+        // J = m + jm
+        for (int i = 0; i < x->n; i++) {
+
+            if (mask && (mask->data.U8[i] & maskValue)) continue;
+
+            float dx = psImageBinningGetRuffX (map->binning, x->data.F32[i]) - (m + 0.5);
+
+            bool edgeX = false;
+            edgeX |= ((m == 1) && (dx < -1.0));
+            edgeX |= ((m == Nx - 2) && (dx > +1.0));
+
+            // skip points outside of 2x2 grid centered on n,m:
+            if (!edgeX && (fabs(dx) > 1.0)) continue;
+
+            // related offset values
+            float rx = 1.0 - dx;
+            float px = 1.0 + dx;
+            float qx = -dx;
+
+            // data value & weight for this point
+            float fi = f->data.F32[i];
+            float wt = 1.0;
+            if (df != NULL) {
+                if (df->data.F32[i] == 0.0) {
+                    wt = 0.0;
+                } else {
+                    wt = 1.0 / PS_SQR(df->data.F32[i]); // XXX test for dz == NULL or dz_i = 0
+                }
+            }
+
+            // sum the appropriate elements for the different quadrants
+            int Qx = (dx >= 0) ? 1 : 0;
+            if (m ==      0) Qx = 1;
+            if (m == Nx - 1) Qx = 0;
+
+            assert (isfinite(fi));
+            assert (isfinite(wt));
+            assert (isfinite(rx));
+
+            // points at offset 1,1
+            if (Qx == 1) {
+                rx_rx += rx*rx*wt;
+                dx_rx += dx*rx*wt;
+                fi_rx += fi*rx*wt;
+            }
+            // points at offset 1,0
+            if (Qx == 0) {
+                px_px += px*px*wt;
+                qx_px += qx*px*wt;
+                fi_px += fi*px*wt;
+            }
+        }
+
+        // the chi-square derivatives have elements of the form g(n+jn,m+jm)*A(jn,jm),
+        // jn,jm = -1 to +1. Convert the sums above into the correct coefficients
+        sA[-1] = qx_px;
+        sA[ 0] = rx_rx + px_px;
+        sA[+1] = dx_rx;
+
+        // I[ 0][ 0] = index for this n,m element:
+        int I = m;
+        B->data.F32[I] = fi_rx + fi_px;
+
+        // insert these values into their corresponding locations in A, B
+        for (int jm = -1; jm <= +1; jm++) {
+            if (m + jm <   0) continue;
+            if (m + jm >= Nx) continue;
+            int J = (m + jm);
+            A->data.F32[J][I] = sA[jm];
+        }
+    }
+
+    // test for empty diagonal elements (unconstained cells), mark, and set pivots to 1.0
+    psVector *Empty = psVectorAlloc (Nx, PS_TYPE_S8);
+    psVectorInit (Empty, 0);
+    for (int i = 0; i < Nx; i++) {
+        if (A->data.F32[i][i] == 0.0) {
+            Empty->data.S8[i] = 1;
+            for (int j = 0; j < Nx; j++) {
+                A->data.F32[i][j] = 0.0;
+                A->data.F32[j][i] = 0.0;
+            }
+            A->data.F32[i][i] = 1.0;
+            B->data.F32[i] = 0.0;
+        }
+    }
+
+    if (!psMatrixGJSolveF32(A, B)) {
+        psAbort ("failed on linear equations");
+        psError(PS_ERR_UNKNOWN, false, "Could not solve linear equations.  Returning NULL.\n");
+        psFree (A);
+        psFree (B);
+        return false;
+    }
+
+    // set bad values to NaN
+    for (int i = 0; i < Nx; i++) {
+        if (Empty->data.S8[i]) {
+            B->data.F32[i] = NAN;
+        }
+    }
+
+    for (int m = 0; m < Nx; m++) {
+        int I = m; // XXX I'm not entirely sure about this; it wasn't set for this scope --- PAP.
+        map->map->data.F32[0][m] = B->data.F32[I];
+        map->error->data.F32[0][m] = sqrt(A->data.F32[I][I]);
+    }
+
+    psFree (A);
+    psFree (B);
+    psFree (Empty);
+
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageMapFit.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageMapFit.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageMapFit.h	(revision 22158)
@@ -0,0 +1,48 @@
+#ifndef PS_IMAGE_MAP_FIT_H
+#define PS_IMAGE_MAP_FIT_H
+
+#include <psType.h>
+#include <psVector.h>
+#include <psImageMap.h>
+
+
+// fit the image map to a set of points
+bool psImageMapFit(psImageMap *map,
+                   const psVector *mask,
+                   psMaskType maskValue,
+                   const psVector *x,
+                   const psVector *y,
+                   const psVector *f,
+                   const psVector *df
+    );
+
+// fit the image map to a set of points
+bool psImageMapClipFit(psImageMap *map,
+                       psStats *stats,
+                       psVector *mask,  // WARNING: Mask is modified!
+                       psMaskType maskValue,
+                       const psVector *x,
+                       const psVector *y,
+                       const psVector *f,
+                       const psVector *df
+    );
+
+bool psImageMapFit1DinY(psImageMap *map,
+                        const psVector *mask,
+                        psMaskType maskValue,
+                        const psVector *x,
+                        const psVector *y,
+                        const psVector *f,
+                        const psVector *df
+    );
+
+bool psImageMapFit1DinX(psImageMap *map,
+                        const psVector *mask,
+                        psMaskType maskValue,
+                        const psVector *x,
+                        const psVector *y,
+                        const psVector *f,
+                        const psVector *df
+    );
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageMaskOps.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageMaskOps.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageMaskOps.c	(revision 22158)
@@ -0,0 +1,296 @@
+/** @file  psImageMaskOps.c
+ *
+ *  @brief Contains basic image pixel and geometry manipulation operations, as
+ *         specified in the PSLIB SDRS sections "Mask Operations"
+ *
+ *  @ingroup Image
+ *
+ *  @author David Robbins, MHPCC
+ *
+ *  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-12 21:08:33 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <math.h>                          // for isfinite(), etc.
+#include <stdlib.h>
+#include <string.h>                        // for memcpy, etc.
+
+#include "psImageMaskOps.h"
+
+#include "psError.h"
+#include "psImage.h"
+#include "psStats.h"
+#include "psMemory.h"
+#include "psAssert.h"
+
+#include "psCoord.h"
+
+// mask the area contained by the region
+// the region is defined wrt the parent image
+void psImageMaskRegion(psImage *image,
+                       psRegion region,
+                       const char *op,
+                       psMaskType maskValue)
+{
+    if (image == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "Invalid image input.  Image is NULL.\n");
+        return;
+    }
+
+
+# define MASK_IT(OP) \
+      for (int j = 0; j < image->numRows; j++) { \
+	if ((j + image->row0) < region.y0) continue; \
+	if ((j + image->row0) > region.y1) continue; /* is this correct (not >= ?) */ \
+	for (int i = 0; i < image->numCols; i++) { \
+	  if ((i + image->col0) < region.x0) continue; \
+	  if ((i + image->col0) > region.x1) continue; /* is this correct (not >= ?) */ \
+	  image->data.PS_TYPE_MASK_DATA[j][i] OP maskValue; \
+	} \
+      }
+
+    if ( !strncmp(op, "&", 2) || !strncmp(op, "AND", 5) ) {
+      MASK_IT (&=);
+      return;
+    }
+    if ( !strncmp(op, "|", 2) || !strncmp(op, "OR", 5) ) {
+      MASK_IT (|=);
+      return;
+    }
+    if ( !strncmp(op, "=", 2) || !strncmp(op, "EQUAL", 5) ) {
+      MASK_IT (=);
+      return;
+    }
+    if ( !strncmp(op, "^", 2) || !strncmp(op, "XOR", 5) ) {
+      MASK_IT (^=);
+      return;
+    }
+
+    psError(PS_ERR_BAD_PARAMETER_VALUE,true,
+	    "The logical operation specified is incorrect\n");
+    return;
+}
+
+// mask the area not contained by the region
+// the region is defined wrt the parent image
+void psImageKeepRegion(psImage *image,
+                       psRegion region,
+                       const char *op,
+                       psMaskType maskValue)
+{
+    if (image == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "Invalid image input.  Image is NULL.\n");
+        return;
+    }
+
+
+# define KEEP_IT(OP) \
+    for (int j = 0; j < image->numRows; j++) { \
+      for (int i = 0; i < image->numCols; i++) { \
+	if ((j + image->row0) < region.y0 || \
+	    (j + image->row0) > region.y1 || \
+	    (i + image->col0) < region.x0 || \
+	    (i + image->col0) > region.x1 ) { \
+	  image->data.PS_TYPE_MASK_DATA[j][i] OP maskValue; \
+	} } }
+
+    if ( !strncmp(op, "&", 2) || !strncmp(op, "AND", 5) ) {
+      KEEP_IT(&=);
+      return;
+    }
+    if ( !strncmp(op, "|", 2) || !strncmp(op, "OR", 5) ) {
+      KEEP_IT(|=);
+      return;
+    }
+    if ( !strncmp(op, "=", 2) || !strncmp(op, "EQUAL", 5) ) {
+      KEEP_IT(=);
+      return;
+    }
+    if ( !strncmp(op, "^", 2) || !strncmp(op, "XOR", 5) ) {
+      KEEP_IT(^=);
+      return;
+    }
+    psError(PS_ERR_BAD_PARAMETER_VALUE,true,
+	    "The logical operation specified is incorrect\n");
+    return;
+}
+
+// mask the area contained by the region
+// the region is defined wrt the parent image
+void psImageMaskCircle(psImage *image,
+                       double x,
+                       double y,
+                       double radius,
+                       const char *op,
+                       psMaskType maskValue)
+{
+    if (image == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "Invalid image input.  Image is NULL.\n");
+        return;
+    }
+
+    double dx, dy, r2, R2;
+
+    R2 = PS_SQR(radius);
+
+# define MASK_IT_CIRCLE(OP) \
+    for (int iy = 0; iy < image->numRows; iy++) { \
+        for (int ix = 0; ix < image->numCols; ix++) { \
+            dx = ix + image->col0 - x; \
+            dy = iy + image->row0 - y; \
+            r2 = PS_SQR(dx) + PS_SQR(dy); \
+            if (r2 <= R2) { \
+	      image->data.PS_TYPE_MASK_DATA[iy][ix] OP maskValue; \
+            } } }
+
+    if ( !strncmp(op, "&", 2) || !strncmp(op, "AND", 5) ) {
+      MASK_IT_CIRCLE (&=);
+      return;
+    } 
+    if ( !strncmp(op, "|", 2) || !strncmp(op, "OR", 5) ) {
+      MASK_IT_CIRCLE (|=);
+      return;
+    } 
+    if ( !strncmp(op, "=", 2) || !strncmp(op, "EQUAL", 5) ) {
+      MASK_IT_CIRCLE (=);
+      return;
+    } 
+    if ( !strncmp(op, "^", 2) || !strncmp(op, "XOR", 5) ) {
+      MASK_IT_CIRCLE (^=);
+      return;
+    } 
+
+    psError(PS_ERR_BAD_PARAMETER_VALUE,true,
+	    "The logical operation specified is incorrect\n");
+    return;
+}
+
+// mask the area contained by the region
+// the region is defined wrt the parent image
+void psImageKeepCircle(psImage *image,
+                       double x,
+                       double y,
+                       double radius,
+                       const char *op,
+                       psMaskType maskValue)
+{
+
+    if (image == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "Invalid image input.  Image is NULL.\n");
+        return;
+    }
+    double dx, dy, r2, R2;
+
+    R2 = PS_SQR(radius);
+
+# define KEEP_IT_CIRCLE(OP) \
+    for (int iy = 0; iy < image->numRows; iy++) { \
+        for (int ix = 0; ix < image->numCols; ix++) { \
+            dx = ix + image->col0 - x; \
+            dy = iy + image->row0 - y; \
+            r2 = PS_SQR(dx) + PS_SQR(dy); \
+            if (r2 > R2) { \
+	      image->data.PS_TYPE_MASK_DATA[iy][ix] OP maskValue; \
+            } } }
+
+    if ( !strncmp(op, "&", 2) || !strncmp(op, "AND", 5) ) {
+      KEEP_IT_CIRCLE (&=);
+      return;
+    } 
+    if ( !strncmp(op, "|", 2) || !strncmp(op, "OR", 5) ) {
+      KEEP_IT_CIRCLE (|=);
+      return;
+    } 
+    if ( !strncmp(op, "=", 2) || !strncmp(op, "EQUAL", 5) ) {
+      KEEP_IT_CIRCLE (=);
+      return;
+    } 
+    if ( !strncmp(op, "^", 2) || !strncmp(op, "XOR", 5) ) {
+      KEEP_IT_CIRCLE (^=);
+      return;
+    } 
+
+    psError(PS_ERR_BAD_PARAMETER_VALUE,true,
+	    "The logical operation specified is incorrect\n");
+    return;
+}
+
+psImage *psImageGrowMask(psImage *out,
+                         const psImage *in,
+                         psMaskType maskVal,
+                         unsigned int growSize,
+                         psMaskType growVal)
+{
+    if (in == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "Invalid input image.  Input image cannot be NULL.\n");
+        return NULL;
+    }
+    if (in->type.type != PS_TYPE_MASK) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                "Invalid input image.  Input image type must match psMaskType.\n");
+        return NULL;
+    }
+    if (out != NULL) {
+        if (out->numCols != in->numCols || out->numRows != in->numRows) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Invalid out image.  Size of out does not match size of in.\n");
+            return NULL;
+        }
+        if (out->type.type != in->type.type) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Invalid out image.  Type of out does not match type of in.\n");
+            return NULL;
+        }
+    }
+    if (out == NULL) {
+        out = psImageAlloc(in->numCols, in->numRows, in->type.type);
+    }
+    psImage *changed = psImageAlloc(in->numCols, in->numRows, in->type.type);
+    int k,l,m,n;
+    for (k = 0; k < in->numRows; k++) {
+        for (l = 0; l < in->numCols; l++) {
+            out->data.PS_TYPE_MASK_DATA[k][l] = in->data.PS_TYPE_MASK_DATA[k][l];
+            changed->data.PS_TYPE_MASK_DATA[k][l] = 0;
+        }
+    }
+
+    for (int i = 0; i < in->numRows; i++) {
+        for (int j = 0; j < in->numCols; j++) {
+            if ( (in->data.PS_TYPE_MASK_DATA[i][j] & maskVal) != 0 &&
+                    changed->data.PS_TYPE_MASK_DATA[i][j] == 0) {
+                m = i - growSize;
+                if (m < 0) {
+                    m = 0;
+                }
+                for (k = m; k <= (i + growSize) && k < in->numRows; k++) {
+                    n = j - growSize;
+                    if (n < 0) {
+                        n = 0;
+                    }
+                    for (l = n; l <= (j + growSize) && l < in->numCols; l++) {
+                        if (((k-i)*(k-i) + (l-j)*(l-j)) <= (growSize*growSize)) {
+                            out->data.PS_TYPE_MASK_DATA[k][l] |= growVal;
+                            if ( (in->data.PS_TYPE_MASK_DATA[i][j] & maskVal) == 0 ) {
+                                changed->data.PS_TYPE_MASK_DATA[k][l] = 1;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    psFree(changed);
+    return out;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageMaskOps.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageMaskOps.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageMaskOps.h	(revision 22158)
@@ -0,0 +1,97 @@
+/* @file  psImageMaskOps.h
+ *
+ * @brief Contains basic image pixel manipulation operations, as
+ *        specified in the PSLIB SDRS sections "Mask Operations"
+ *
+ * @author David Robbins, MHPCC
+ *
+ * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-01-23 22:47:23 $
+ *
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_IMAGE_MASK_OPS_H
+#define PS_IMAGE_MASK_OPS_H
+
+/// @addtogroup ImageOps Image Operations
+/// @{
+
+#include "psImage.h"
+#include "psCoord.h"
+#include "psStats.h"
+#include "psPixels.h"
+
+/** Sets the bits inside the region, ignoring pixels outside.
+ *
+ *  The pixels are set by combining the existing pixel value and the given maskValue
+ *  with a logical operation.  The allowed operations are =, AND, OR, and XOR.
+ */
+void psImageMaskRegion(
+    psImage *image,                    ///< the image to set
+    psRegion region,                   ///< the specified region
+    const char *op,                    ///< the logical operation
+    psMaskType maskValue               ///< the specified bits
+);
+
+/** Sets the bits outside the region, ignoring pixels inside.
+ *
+ *  The pixels are set by combining the existing pixel value and the given maskValue
+ *  with a logical operation.  The allowed operations are =, AND, OR, and XOR.
+ */
+void psImageKeepRegion(
+    psImage *image,                    ///< the image to set
+    psRegion region,                   ///< the specified region
+    const char *op,                    ///< the logical operation
+    psMaskType maskValue               ///< the specified bits
+);
+
+/** Sets the bits inside the circle, ignoring the pixels outside.
+ *
+ *  The pixel values are set by combining the existing pixel value and the given maskValue
+ *  with a logical operation.  The allowed operations are =, AND, OR, and XOR.
+ */
+void psImageMaskCircle(
+    psImage *image,                    ///< the image to set
+    double x,                          ///< the x coordinate of the circle's center
+    double y,                          ///< the y coordinate of the circle's center
+    double radius,                     ///< the radius of the specified circle
+    const char *op,                    ///< the logical operation
+    psMaskType maskValue               ///< the specified bits
+);
+
+/** Sets the bits outside the circle, ignoring the pixels inside.
+ *
+ *  The pixel values are set by combining the existing pixel value and the given maskValue
+ *  with a logical operation.  The allowed operations are =, AND, OR, and XOR.
+ */
+void psImageKeepCircle(
+    psImage *image,                    ///< the image to set
+    double x,                          ///< the x coordinate of the circle's center
+    double y,                          ///< the y coordinate of the circle's center
+    double radius,                     ///< the radius of the specified circle
+    const char *op,                    ///< the logical operation
+    psMaskType maskValue               ///< the specified bits
+);
+
+/** Grows the specified values on the imput mask image, in, returning the result.
+ *
+ *  If out is NULL, then a new image of the same type and dimension as in shall
+ *  be allocated and returned; otherwise out shall be modified.  If out is non-
+ *  NULL and does not have the same size and type as in, the function shall
+ *  generate an error and return NULL.  Pixels in the in image within growSize
+ *  pixels (either horizontal or vertical) of a pixel which matches the maskVal
+ *  shall have the corresponding pixel in the out image set to the growVal.
+ *
+ *  @return psImage*:
+ */
+psImage *psImageGrowMask(
+    psImage *out,                      ///< the image to set and return
+    const psImage *in,                 ///< the input to image
+    psMaskType maskVal,                ///< the specified mask value
+    unsigned int growSize,             ///< the range of values from maskVal
+    psMaskType growVal                 ///< the output value to set
+);
+
+/// @}
+#endif // #ifndef PS_MASK_OPS_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImagePixelExtract.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImagePixelExtract.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImagePixelExtract.c	(revision 22158)
@@ -0,0 +1,929 @@
+/** @file  psImagePixelExtract.c
+ *
+ *  @brief Contains basic image extraction operations, as specified in the
+ *         PSLIB SDRS sections "Image Pixel Extractions".
+ *
+ *  @ingroup Image
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.32 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-04-04 22:42:02 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+
+#include "psMemory.h"
+#include "psVector.h"
+#include "psError.h"
+#include "psImage.h"
+#include "psImageInterpolate.h"
+#include "psImagePixelExtract.h"
+
+#define VECTOR_STORE_ROW_CASE(TYPE) \
+case PS_TYPE_##TYPE: \
+memcpy(out->data.TYPE, input->data.TYPE[row], input->numCols*sizeof(ps##TYPE)); \
+break;
+
+psVector *psImageRow(psVector *out,
+                     const psImage *input,
+                     int row)
+{
+    if (input == NULL || input->data.V == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not operate on a NULL psImage."));
+        psFree(out);
+        return NULL;
+    }
+    if (input->col0 < 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImage input is invalid.  col0 cannot be negative.\n");
+        psFree(out);
+        return NULL;
+    }
+    if (input->row0 < 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImage input is invalid.  row0 cannot be negative.\n");
+        psFree(out);
+        return NULL;
+    }
+    if (input->numCols < 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImage input is invalid.  numCols must be greater than 0.\n");
+        psFree(out);
+        return NULL;
+    }
+    if (input->numRows < 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImage input is invalid.  numRows must be greater than 0.\n");
+        psFree(out);
+        return NULL;
+    }
+    if (row >= (input->numRows + input->row0) ) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "Specified row number is out of range for specified image.\n");
+        psFree(out);
+        return NULL;
+    } else if ( row < input->row0 && row >= 0 ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Specified row number is out of range for specified image.\n");
+        psFree(out);
+        return NULL;
+    } else if ( row < 0 ) {
+        row += input->numRows;
+        if ( row < 0 ) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Specified row number is out of range for specified image.\n");
+            psFree(out);
+            return NULL;
+        }
+    } else {
+        row -= input->row0;
+    }
+
+    out = psVectorRecycle(out, input->numCols, input->type.type);
+    out->n = input->numCols;
+
+    switch (input->type.type) {
+        VECTOR_STORE_ROW_CASE(S8);
+        VECTOR_STORE_ROW_CASE(S16);
+        VECTOR_STORE_ROW_CASE(S32);
+        VECTOR_STORE_ROW_CASE(S64);
+        VECTOR_STORE_ROW_CASE(U8);
+        VECTOR_STORE_ROW_CASE(U16);
+        VECTOR_STORE_ROW_CASE(U32);
+        VECTOR_STORE_ROW_CASE(U64);
+        VECTOR_STORE_ROW_CASE(F32);
+        VECTOR_STORE_ROW_CASE(F64);
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                "Specified psImage has invalid type for this function.\n");
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+}
+
+
+#define VECTOR_STORE_COL_CASE(TYPE) \
+case PS_TYPE_##TYPE: \
+for (int i = 0; i < input->numRows; i++) { \
+    out->data.TYPE[i] = input->data.TYPE[i][column]; \
+} \
+break;
+
+psVector *psImageCol(psVector *out,
+                     const psImage *input,
+                     int column)
+{
+    if (input == NULL || input->data.V == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not operate on a NULL psImage."));
+        psFree(out);
+        return NULL;
+    }
+    if (input->col0 < 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImage input is invalid.  col0 cannot be negative.\n");
+        psFree(out);
+        return NULL;
+    }
+    if (input->row0 < 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImage input is invalid.  row0 cannot be negative.\n");
+        psFree(out);
+        return NULL;
+    }
+    if (input->numCols < 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImage input is invalid.  numCols must be greater than 0.\n");
+        psFree(out);
+        return NULL;
+    }
+    if (input->numRows < 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImage input is invalid.  numRows must be greater than 0.\n");
+        psFree(out);
+        return NULL;
+    }
+    if (column >= (input->numCols + input->col0) ) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "Specified column number is out of range for specified image.\n");
+        psFree(out);
+        return NULL;
+    } else if ( column < input->col0 && column >= 0 ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Specified column number is out of range for specified image.\n");
+        psFree(out);
+        return NULL;
+    } else if ( column < 0 ) {
+        column += input->numCols;
+        if ( column < 0 ) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Specified column number is out of range for specified image.\n");
+            psFree(out);
+            return NULL;
+        }
+    } else {
+        column -= input->col0;
+    }
+
+    out = psVectorRecycle(out, input->numRows, input->type.type);
+    out->n = input->numRows;
+
+    switch (input->type.type) {
+        VECTOR_STORE_COL_CASE(S8);
+        VECTOR_STORE_COL_CASE(S16);
+        VECTOR_STORE_COL_CASE(S32);
+        VECTOR_STORE_COL_CASE(S64);
+        VECTOR_STORE_COL_CASE(U8);
+        VECTOR_STORE_COL_CASE(U16);
+        VECTOR_STORE_COL_CASE(U32);
+        VECTOR_STORE_COL_CASE(U64);
+        VECTOR_STORE_COL_CASE(F32);
+        VECTOR_STORE_COL_CASE(F64);
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                "Specified psImage has invalid type for this function.\n");
+        psFree(out);
+        return NULL;
+    }
+
+    return out;
+
+}
+
+psVector* psImageSlice(psVector* out,
+                       psPixels* coords,
+                       const psImage* input,
+                       const psImage* mask,
+                       psMaskType maskVal,
+                       psRegion region,
+                       psImageCutDirection direction,
+                       const psStats* stats)
+{
+    psStats* myStats;
+    psElemType type;
+    psS32 inRows;
+    psS32 inCols;
+    psS32 delta = 1;
+    psF64* outData;
+    psS32 row0 = region.y0;
+    psS32 row1 = region.y1;
+    psS32 col0 = region.x0;
+    psS32 col1 = region.x1;
+
+    if (input == NULL || input->data.V == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not operate on a NULL psImage."));
+        psFree(out);
+        return NULL;
+    }
+    if (input->col0 < 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImage input is invalid.  col0 cannot be negative.\n");
+        psFree(out);
+        return NULL;
+    }
+    if (input->row0 < 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImage input is invalid.  row0 cannot be negative.\n");
+        psFree(out);
+        return NULL;
+    }
+    if (input->numCols < 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImage input is invalid.  numCols must be greater than 0.\n");
+        psFree(out);
+        return NULL;
+    }
+    if (input->numRows < 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImage input is invalid.  numRows must be greater than 0.\n");
+        psFree(out);
+        return NULL;
+    }
+
+    //If [0,0,0,0] specified, the whole image is to be included
+    if (row0 == 0 && col0 == 0 && row1 == 0 && col1 == 0) {
+        row0 = input->row0;
+        col0 = input->col0;
+        row1 = input->row0 + input->numRows - 1;
+        col1 = input->col0 + input->numCols - 1;
+    }
+
+    //Make sure x0 of region is inside image.  If so, set col0 to corresponding index number.
+    if (col0 >= input->col0 && col0 < (input->col0 + input->numCols) ) {
+        col0 -= input->col0;
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Specified psRegion parameter, x0=%f, is out of range [%d,%d].\n",
+                region.x0, input->col0, input->col0+input->numCols-1);
+        psFree(out);
+        return NULL;
+    }
+    //Make sure y0 of region is inside image.  If so, set row0 to corresponding index number.
+    if (row0 >= input->row0 && row0 < (input->row0 + input->numRows) ) {
+        row0 -= input->row0;
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Specified psRegion parameter, y0=%f, is out of range [%d,%d].\n",
+                region.y0, input->row0, input->row0+input->numRows-1);
+        psFree(out);
+        return NULL;
+    }
+
+    //Make sure x1 of region is valid.  If negative, index from tail (if valid).
+    if (col1 < 0) {
+        col1 += input->numCols;
+        if (col1 < 0) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Specified psRegion parameter, x1=%f=%d, is out of range [%d,%d].\n",
+                    region.x1, col1+input->col0, input->col0, input->col0+input->numCols-1);
+            psFree(out);
+            return NULL;
+        }
+    } else if (col1 >= input->col0 && col1 < (input->col0 + input->numCols) ) {
+        col1 -= input->col0;
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Specified psRegion parameter, x1=%f=%d, is out of range [%d,%d].\n",
+                region.x1, col1, input->col0, input->col0+input->numCols-1);
+        psFree(out);
+        return NULL;
+    }
+    //Make sure y1 of region is valid.  If negative, index from tail (if valid).
+    if (row1 < 0) {
+        row1 += input->numRows;
+        if (row1 < 0) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Specified psRegion parameter, y1=%f=%d, is out of range [%d,%d].\n",
+                    region.y1, row1+input->row0, input->row0, input->row0+input->numRows-1);
+            psFree(out);
+            return NULL;
+        }
+    } else if (row1 >= input->row0 && row1 < (input->row0 + input->numRows) ) {
+        row1 -= input->row0;
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Specified psRegion parameter, y1=%f=%d, is out of range [%d,%d].\n",
+                region.y1, row1, input->row0, input->row0+input->numRows-1);
+        psFree(out);
+        return NULL;
+    }
+    //Now make sure that the region makes sense.
+    if (col0 > col1 || row0 > row1) {
+        if (col0 > col1) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Invalid psRegion specified.  x0=%f=%d is greater than x1=%f=%d.\n",
+                    region.x0, col0, region.x1, col1);
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Invalid psRegion specified.  y0=%f=%d is greater than y1=%f=%d.\n",
+                    region.y0, row0, region.y1, row1);
+        }
+        psFree(out);
+        return NULL;
+    } else if (col0 == col1 && row0 == row1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Invalid psRegion specified.  Region contains only 1 pixel.\n");
+        psFree(out);
+        return NULL;
+    }
+
+    type = input->type.type;
+    inRows = input->numRows;
+    inCols = input->numCols;
+
+    if (direction == PS_CUT_X_NEG || direction == PS_CUT_Y_NEG) {
+        delta = -1;
+    }
+
+    if (mask != NULL) {
+        if (inRows != mask->numRows || inCols != mask->numCols) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    _("Input psImage mask size, %dx%d, does not match psImage input size, %dx%d."),
+                    mask->numCols,mask->numRows,
+                    inCols, inRows);
+            psFree(out);
+            return NULL;
+        }
+        if (mask->type.type != PS_TYPE_MASK) {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,mask->type.type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    _("Input psImage mask type, %s, is not the supported mask datatype of %s."),
+                    typeStr, PS_TYPE_MASK_NAME);
+            psFree(out);
+            return NULL;
+        }
+    }
+
+    if (stats == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Specified statistic can not be NULL."));
+        psFree(out);
+        return NULL;
+    }
+
+    // verify that the stats struct specifies a single stats operation
+    psStatsOptions statistic = psStatsSingleOption(stats->options);
+    if (statistic == 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                _("Specified statistic option, %d, is not valid.  Must specify one and only one statistic type."),stats->options);
+        psFree(out);
+        return NULL;
+    }
+    // since stats input is const, I need to
+    // create a 'scratch' stats struct
+    myStats = psAlloc(sizeof(psStats));
+    *myStats = *stats;
+
+    psS32 numCols = col1-col0;
+    psS32 numRows = row1-row0;
+
+    if (direction == PS_CUT_X_POS || direction == PS_CUT_X_NEG) {
+        psVector* imgVec = psVectorAlloc(numRows, type);
+        psVector* maskVec = NULL;
+        psMaskType* maskData = NULL;
+        psPixelCoord* outPosition = NULL;
+
+        // recycle output to make a proper sized/type output structure
+        // n.b. type is double as that is the type given for all stats is
+        // psStats.
+        out = psVectorRecycle(out, numCols, PS_TYPE_F64);
+        out->n = numCols;
+        if (coords != NULL) {
+            coords = psPixelsRealloc(coords, numCols);
+            coords->n = numCols;
+            outPosition = coords->data;
+        }
+        outData = out->data.F64;
+        if (delta < 0) {
+            outData += numCols - 1;
+            if (outPosition != NULL) {
+                outPosition += numCols - 1;
+            }
+        }
+
+        if (mask != NULL) {
+            maskVec = psVectorAlloc(numRows, mask->type.type);
+        }
+        #define PSIMAGE_CUT_VERTICAL(TYPE) \
+    case PS_TYPE_##TYPE: { \
+            psMaskType* maskVecData = NULL; \
+            for (psS32 c=col0;c<col1;c++) { \
+                ps##TYPE *imgData = input->data.TYPE[row0] + c; \
+                ps##TYPE *imgVecData = imgVec->data.TYPE; \
+                if (maskVec != NULL) { \
+                    maskVecData = maskVec->data.U8; \
+                    maskData = (psMaskType* )(mask->data.U8[row0]) + c; \
+                } \
+                for (psS32 r=row0;r<row1;r++) { \
+                    *(imgVecData++) = *imgData; \
+                    imgData += inCols; \
+                    if (maskVecData != NULL) { \
+                        *(maskVecData++) = *maskData; \
+                        maskData += inCols; \
+                    } \
+                } \
+                psVectorStats(myStats,imgVec,NULL,maskVec,maskVal); \
+                *outData = psStatsGetValue(myStats, statistic); \
+                if (outPosition != NULL) { \
+                    outPosition->x = c; \
+                    outPosition->y = row0; \
+                    outPosition += delta; \
+                } \
+                outData += delta; \
+            } \
+            break; \
+        }
+
+        switch (type) {
+            PSIMAGE_CUT_VERTICAL(U8);  // Not a requirement
+            PSIMAGE_CUT_VERTICAL(U16);
+            PSIMAGE_CUT_VERTICAL(U32); // Not a requirement
+            PSIMAGE_CUT_VERTICAL(U64); // Not a requirement
+            PSIMAGE_CUT_VERTICAL(S8);
+            PSIMAGE_CUT_VERTICAL(S16); // Not a requirement
+            PSIMAGE_CUT_VERTICAL(S32); // Not a requirement
+            PSIMAGE_CUT_VERTICAL(S64); // Not a requirement
+            PSIMAGE_CUT_VERTICAL(F32);
+            PSIMAGE_CUT_VERTICAL(F64);
+        default: {
+                char* typeStr;
+                PS_TYPE_NAME(typeStr,type);
+                psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                        _("Specified psImage type, %s, is not supported."),
+                        typeStr);
+                psFree(out);
+                out = NULL;
+            }
+        }
+        psFree(imgVec);
+        psFree(maskVec);
+    } else if (direction == PS_CUT_Y_POS || direction == PS_CUT_Y_NEG) {
+        // Cut in Y direction
+        psVector* imgVec = NULL;
+        psVector* maskVec = NULL;
+        psS32 elementSize = PSELEMTYPE_SIZEOF(type);
+        psPixelCoord* outPosition = NULL;
+
+        // fill in psVector to fake out the statistics functions.
+        imgVec = psAlloc(sizeof(psVector));
+        imgVec->type = input->type;
+        P_PSVECTOR_SET_NALLOC(imgVec,numCols);
+        if (mask != NULL) {
+            maskVec = psAlloc(sizeof(psVector));
+            maskVec->type = mask->type;
+            P_PSVECTOR_SET_NALLOC(maskVec,numCols);
+        }
+        // recycle output to make a proper sized/type output structure
+        // n.b. type is double as that is the type given for all stats in
+        // psStats.
+        out = psVectorRecycle(out, numRows, PS_TYPE_F64);
+        out->n = numRows;
+        imgVec->n = imgVec->nalloc;
+        maskVec->n = maskVec->nalloc;
+        if (coords != NULL) {
+            coords = psPixelsRealloc(coords, numRows);
+            coords->n = numRows;
+            outPosition = coords->data;
+        }
+        outData = out->data.F64;
+        if (delta < 0) {
+            outData += numRows-1;
+            if (outPosition != NULL) {
+                outPosition += numRows-1;
+            }
+        }
+
+        for (psS32 r = row0; r < row1; r++) {
+            // point the vector struct to the
+            // data to calculate the stats
+            imgVec->data.U8 = (psPtr )(input->data.U8[r] + col0 * elementSize);
+            if (maskVec != NULL) {
+                maskVec->data.U8 = (psPtr )(mask->data.U8[r] + col0 * sizeof(psMaskType));
+            }
+            psVectorStats(myStats, imgVec, NULL, maskVec, maskVal);
+            *outData = psStatsGetValue(myStats, statistic);
+            if (outPosition != NULL) {
+                outPosition->y = r;
+                outPosition->x = col0;
+                outPosition += delta;
+
+            }
+            outData += delta;
+        }
+        psFree(imgVec);
+        psFree(maskVec);
+    } else { // don't know what the direction flag is
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified slice direction, %d, is invalid."),
+                direction);
+        psFree(out);
+        out = NULL;
+    }
+
+    psFree(myStats);
+
+    return out;
+}
+
+psVector* psImageCut(psVector* out,
+                     psVector* cutCols,
+                     psVector* cutRows,
+                     const psImage* input,
+                     const psImage* mask,
+                     psMaskType maskVal,
+                     psRegion region,
+                     unsigned int nSamples,
+                     psImageInterpolateMode mode)
+{
+
+    if (input == NULL || input->data.V == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not operate on a NULL psImage."));
+        psFree(out);
+        return NULL;
+    }
+    if (input->col0 < 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImage input is invalid.  col0 cannot be negative.\n");
+        psFree(out);
+        return NULL;
+    }
+    if (input->row0 < 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImage input is invalid.  row0 cannot be negative.\n");
+        psFree(out);
+        return NULL;
+    }
+    if (input->numCols < 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImage input is invalid.  numCols must be greater than 0.\n");
+        psFree(out);
+        return NULL;
+    }
+    if (input->numRows < 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImage input is invalid.  numRows must be greater than 0.\n");
+        psFree(out);
+        return NULL;
+    }
+    psS32 numCols = input->numCols;
+    psS32 numRows = input->numRows;
+
+    if (nSamples < 2) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified number of samples, %d, must be greater than 1 to make a line."),
+                nSamples);
+        psFree(out);
+        return NULL;
+    }
+
+    float col0 = region.x0;
+    float row0 = region.y0;
+    float col1 = region.x1;
+    float row1 = region.y1;
+
+    //If [0,0,0,0] specified, the whole image is to be included
+    if (row0 == 0 && col0 == 0 && row1 == 0 && col1 == 0) {
+        row0 = input->row0;
+        col0 = input->col0;
+        row1 = input->row0 + input->numRows - 1;
+        col1 = input->col0 + input->numCols - 1;
+    }
+
+    //Make sure x0 of region is inside image.  If so, set col0 to corresponding index number.
+    if (col0 >= input->col0 && col0 < (input->col0 + input->numCols) ) {
+        col0 -= input->col0;
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Specified psRegion parameter, x0=%f, is out of range [%d,%d].\n",
+                region.x0, input->col0, input->col0+input->numCols);
+        psFree(out);
+        return NULL;
+    }
+    //Make sure y0 of region is inside image.  If so, set row0 to corresponding index number.
+    if (row0 >= input->row0 && row0 < (input->row0 + input->numRows) ) {
+        row0 -= input->row0;
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Specified psRegion parameter, y0=%f, is out of range [%d,%d].\n",
+                region.y0, input->row0, input->row0+input->numRows);
+        psFree(out);
+        return NULL;
+    }
+    if (col1 < 0 || row1 < 0 || col0 < 0 || row0 < 0 || col0 >= numCols || col1 >= numCols ||
+            row0 >= numRows || row1 >= numRows) {
+        psFree(out);
+        return NULL;
+    }
+    float startCol = col0;
+    float startRow = row0;
+    float endCol = col1;
+    float endRow = row1;
+
+    if (mode < PS_INTERPOLATE_FLAT ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified interpolation mode, %d, is unsupported."),
+                mode);
+        psFree(out);
+        return NULL;
+    }
+
+    if (mask != NULL) {
+        if (numRows != mask->numRows || numCols != mask->numCols) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    _("Input psImage mask size, %dx%d, does not match psImage input size, %dx%d."),
+                    mask->numCols,mask->numRows,
+                    numCols-1, numRows);
+            psFree(out);
+            return NULL;
+        }
+        if (mask->type.type != PS_TYPE_MASK) {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,mask->type.type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    _("Input psImage mask type, %s, is not the supported mask datatype of %s."),
+                    typeStr, PS_TYPE_MASK_NAME);
+            psFree(out);
+            return NULL;
+        }
+    }
+
+    //resize the vectors for the coordinate output
+    psF32* cutColsData = NULL;
+    psF32* cutRowsData = NULL;
+    if (cutCols != NULL) {
+        cutCols = psVectorRecycle(cutCols, nSamples, PS_TYPE_F32);
+        cutColsData = cutCols->data.F32;
+    }
+    if (cutRows != NULL) {
+        cutRows = psVectorRecycle(cutRows, nSamples, PS_TYPE_F32);
+        cutRowsData = cutRows->data.F32;
+    }
+
+    out = psVectorRecycle(out, nSamples, input->type.type);
+
+    float dX = (endCol - startCol) / (float)(nSamples-1);
+    float dY = (endRow - startRow) / (float)(nSamples-1);
+
+    psImageInterpolateOptions *interp = psImageInterpolateOptionsAlloc(mode, input, NULL, mask, maskVal,
+                                                                       0, 0, 0, 0, 0);
+
+    #define LINEAR_CUT_CASE(TYPE) \
+case PS_TYPE_##TYPE: { \
+        ps##TYPE* outData = out->data.TYPE; \
+        for (psS32 i = 0; i < nSamples; i++) { \
+            float x = startCol + (float)i*dX; \
+            float y = startRow + (float)i*dY; \
+            /* store off the location of the sample. */ \
+            if (cutColsData != NULL) { \
+                cutColsData[i] = x; \
+            } \
+            if (cutRowsData != NULL) { \
+                cutRowsData[i] = y; \
+            } \
+            double value; \
+            if (!psImageInterpolate(&value, NULL, NULL, x, y, interp)) { \
+                psError(PS_ERR_UNKNOWN, false, "Unable to interpolate image."); \
+                psFree(interp); \
+                psFree(out); \
+                return NULL; \
+            } \
+            outData[i] = value; \
+        } \
+    } \
+    break;
+
+
+    switch (input->type.type) {
+        LINEAR_CUT_CASE(U8);
+        LINEAR_CUT_CASE(U16);
+        LINEAR_CUT_CASE(U32);
+        LINEAR_CUT_CASE(U64);
+        LINEAR_CUT_CASE(S8);
+        LINEAR_CUT_CASE(S16);
+        LINEAR_CUT_CASE(S32);
+        LINEAR_CUT_CASE(S64);
+        LINEAR_CUT_CASE(F32);
+        LINEAR_CUT_CASE(F64);
+      default: {
+          char* typeStr;
+          PS_TYPE_NAME(typeStr,input->type.type);
+          psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                  _("Specified psImage type, %s, is not supported."),
+                  typeStr);
+          psFree(interp);
+          psFree(out);
+          out = NULL;
+      }
+    }
+
+    psFree(interp);
+
+    return out;
+}
+
+psVector* psImageRadialCut(psVector* out,
+                           const psImage* input,
+                           const psImage* mask,
+                           psMaskType maskVal,
+                           float x,
+                           float y,
+                           const psVector* radii,
+                           const psStats* stats)
+{
+    /* check the parameters */
+
+    if (input == NULL || input->data.V == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not operate on a NULL psImage."));
+        psFree(out);
+        return NULL;
+    }
+    psS32 numCols = input->numCols;
+    psS32 numRows = input->numRows;
+
+    if (mask != NULL) {
+        if (numRows != mask->numRows || numCols != mask->numCols) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    _("Input psImage mask size, %dx%d, does not match psImage input size, %dx%d."),
+                    mask->numCols,mask->numRows,
+                    numCols, numRows);
+            psFree(out);
+            return NULL;
+        }
+        if (mask->type.type != PS_TYPE_MASK) {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,mask->type.type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    _("Input psImage mask type, %s, is not the supported mask datatype of %s."),
+                    typeStr, PS_TYPE_MASK_NAME);
+            psFree(out);
+            return NULL;
+        }
+    }
+
+    //    if (x < 0 || x >= numCols ||
+    //            y < 0 || y >= numRows) {
+    if (x < input->col0 || x >= (input->col0 + numCols) ||
+            y < input->row0 || y >= (input->row0 + numRows) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified center, (%g,%g), is outside of the psImage boundaries, [0:%d,0:%d]."),
+                x, y,
+                numCols-1, numRows-1);
+        psFree(out);
+        return NULL;
+    }
+
+    if (radii == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Specified radii vector can not be NULL."));
+        psFree(out);
+        return NULL;
+    }
+
+    if (radii->n < 2) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                _("Input radii vector size, %ld, can not be less than 2."),
+                radii->n);
+        psFree(out);
+        return NULL;
+    }
+
+    if (stats == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Specified statistic can not be NULL."));
+        psFree(out);
+        return NULL;
+    }
+
+    // verify that the stats struct specifies a single stats operation
+    psStatsOptions statistic = psStatsSingleOption(stats->options);
+    if (statistic == 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                _("Specified statistic option, %d, is not valid.  Must specify one and only one statistic type."),
+                stats->options);
+        psFree(out);
+        return NULL;
+    }
+
+    /* completed checking the parameters */
+
+    // size the output vector to proper size.
+    psS32 numOut = radii->n - 1;
+    out = psVectorRecycle(out, numOut, PS_TYPE_F64);
+    psF64* outData = out->data.F64;
+
+    psVector* rSqVec = psVectorCopy(NULL, radii, PS_TYPE_F32);
+    psF32* rSq = rSqVec->data.F32;
+
+    psS32 startRow = y - rSq[numOut];
+    psS32 endRow = y + rSq[numOut];
+    psS32 startCol = x - rSq[numOut];
+    psS32 endCol = x + rSq[numOut];
+
+    if (startRow < 0) {
+        startRow = 0;
+    }
+
+    if (startCol < 0) {
+        startCol = 0;
+    }
+
+    if (endRow >= numRows) {
+        endRow = numRows - 1;
+    }
+
+    if (endCol >= numCols) {
+        endCol = numCols - 1;
+    }
+
+    // Square the radii data
+    for (psS32 d = 0; d <= numOut; d++) {
+        rSq[d] *= rSq[d];
+    }
+
+    // create temporary vectors for the data binning step
+    psVector** buffer = psAlloc(sizeof(psVector*)*numOut);
+    psVector** bufferMask = psAlloc(sizeof(psVector*)*numOut);
+    for (psS32 lcv = 0; lcv < numOut; lcv++) {
+        // n.b. alloc enough for the data by making the vectors slightly larger
+        // than the area of the region of interest.
+        buffer[lcv] = psVectorAllocEmpty(1+4*(rSq[lcv+1]-rSq[lcv]),
+                                         input->type.type);
+
+        bufferMask[lcv] = NULL;
+        if (mask != NULL) {
+            bufferMask[lcv] = psVectorAllocEmpty(1+4*(rSq[lcv+1]-rSq[lcv]),
+                                                 PS_TYPE_MASK);
+        }
+    }
+
+    float dX;
+    float dY;
+    float dist;
+    for (psS32 row=startRow; row <= endRow; row++) {
+        psF32* inRow = input->data.F32[row];
+        psMaskType* maskRow = NULL;
+        if (mask != NULL) {
+            maskRow = mask->data.PS_TYPE_MASK_DATA[row];
+        }
+        for (psS32 col=startCol; col <= endCol; col++) {
+            dX = x - (float)col - 0.5f;
+            dY = y - (float)row - 0.5f;
+            dist = dX*dX+dY*dY;
+            for (psS32 r = 0; r < numOut; r++) {
+                if (rSq[r] < dist && dist < rSq[r+1]) {
+                    psS32 n = buffer[r]->n;
+                    if (n == buffer[r]->nalloc) { // in case buffers already full, expand
+                        buffer[r] = psVectorRealloc(buffer[r], n*2);
+                        if (bufferMask[r] != NULL) {
+                            bufferMask[r] = psVectorRealloc(bufferMask[r], n*2);
+                        }
+                    }
+
+                    buffer[r]->data.F32[n] = inRow[col];
+                    buffer[r]->n = n+1;
+
+                    if (maskRow != NULL) {
+                        bufferMask[r]->data.PS_TYPE_MASK_DATA[n] = maskRow[col];
+                        bufferMask[r]->n = n+1;
+                    }
+
+                    break;
+                }
+            }
+        }
+    }
+
+    psStats* myStats = psAlloc(sizeof(psStats));
+    *myStats = *stats;
+
+    for (psS32 r = 0; r < numOut; r++) {
+        psVectorStats(myStats,buffer[r], NULL, bufferMask[r],maskVal);
+        outData[r] = psStatsGetValue(myStats, statistic);
+    }
+
+    psFree(myStats);
+
+    for (psS32 lcv = 0; lcv < numOut; lcv++) {
+        psFree(buffer[lcv]);
+        psFree(bufferMask[lcv]);
+    }
+    psFree(buffer);
+    psFree(bufferMask);
+    psFree(rSqVec);
+    return out;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImagePixelExtract.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImagePixelExtract.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImagePixelExtract.h	(revision 22158)
@@ -0,0 +1,145 @@
+/* @file  psImagePixelExtract.h
+ *
+ * @brief Basic image extraction operations
+ *
+ * @author Robert DeSonia, MHPCC
+ *
+ * @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-01-23 22:47:23 $
+ *
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PSIMAGE_PIXEL_EXTRACT_H
+#define PSIMAGE_PIXEL_EXTRACT_H
+
+/// @addtogroup ImageOps Image Operations
+/// @{
+
+#include "psImage.h"
+#include "psVector.h"
+#include "psStats.h"
+#include "psPixels.h"
+
+/* Cut direction flag.  Used with psImageCut function.
+ */
+typedef enum {
+    PS_CUT_X_POS,                      ///< Cut in the x dimension from left to right
+    PS_CUT_X_NEG,                      ///< Cut in the x dimension from rigth to left
+    PS_CUT_Y_POS,                      ///< Cut in the y dimension from bottom up
+    PS_CUT_Y_NEG                       ///< Cut in the y dimension from top down.
+} psImageCutDirection;
+
+/** Extracts a single complete row from the image and returns it to the
+ *  provided vector, allocating it if it is NULL.
+ *
+ *  @return psVector*:      The row data extracted from psImage input
+ */
+psVector *psImageRow(
+    psVector *out,                     ///< specified vector to return
+    const psImage *input,              ///< input image
+    int row                            ///< row number to extract
+);
+
+/** Extracts a single complete column from the image and returns it to the
+ *  provided vector, allocating it if it is NULL.
+ *
+ *  @return psVector*:      The column data extracted from psImage input
+ */
+psVector *psImageCol(
+    psVector *out,                     ///< specified vector to return
+    const psImage *input,              ///< input image
+    int column                         ///< column number to extract
+);
+
+/** Extract pixels from rectlinear region to a vector (array of floats).
+ *
+ *  The output vector contains either col1-col0 or row1-row0 elements, based
+ *  on the value of the direction: e.g., if direction is PS_CUT_X_POS, there
+ *  are col1-col0 elements. The region to be  sliced  is defined by the
+ *  lower-left corner, (col0,row0), and the upper-right corner, (col1,row1).
+ *  Note that the row and column of the  upper right-hand corner  are NOT
+ *  included in the region. In the event that col1 or row1 are negative, they
+ *  shall be interpreted as being relative to the size of the parent image in
+ *  that dimension. The input region is collapsed in the direction perpendicular
+ *  to that specified by direction, and each element of the output vectors is
+ *  derived from the statistics of the pixels at that direction coordinate. The
+ *  statistic used to derive the output vector value is specified by stats.
+ *  If mask is non-NULL, pixels for which the corresponding mask pixel
+ *  matches maskVal are excluded from operations. If coords is not NULL, the
+ *  calculated coordinates along the slice are returned in this vector. Only
+ *  one of the statistics choices may be specified, otherwise the function
+ *  must return an error.
+ *
+ *  This function is defined for the following types: psS8, psU16, psF32, psF64.
+ *
+ * @return psVector    the resulting vector
+ */
+psVector* psImageSlice(
+    psVector* out,                     ///< psVector to recycle, or NULL.
+    psPixels* coords,
+    ///< If not NULL, it is populated with the coordinate in the slice dimension
+    ///< coorsponding to the output vector's value of the same position in the
+    ///< vector.  This vector maybe resized and retyped as appropriate.
+    const psImage* input,              ///< the input image in which to perform the slice
+    const psImage* mask,               ///< the mask for the input image.
+    psMaskType maskVal,                ///< the mask value to apply to the mask
+    psRegion region,                   ///< the slice region
+    psImageCutDirection direction,     ///< the slice dimension and direction
+    const psStats* stats               ///< the statistic to perform in slice operation
+);
+
+/** Extract pixels from an image along a line to a vector (array of floats).
+ *
+ *  The vector (xs,ys) - (xe,ye) forms the basis of the output vector. Pixels
+ *  are considered in a rectangular region of width dw about this vector. The
+ *  input region is collapsed in the perpendicular direction, and each element
+ *  of the output vector represents pixel-sized boxes, where the value is
+ *  derived from the statistics of the pixels interpolated along the
+ *  perpendicular direction. The specific algorithm which must be used is
+ *  described in the PSLib ADD (PSDC-430-006). The statistic used to derive
+ *  the output vector value is specified by stats. Only one of the statistics
+ *  choices may be specified, otherwise the function must return an error.
+ *  This function must be defined for the following types: psS8, psU16, psF32,
+ *  psF64.
+ *
+ *  @return psVector*    resulting vector
+ */
+psVector* psImageCut(
+    psVector* out,                     ///< psVector to recycle, or NULL.
+    psVector* cutCols,                 ///< if not NULL, the calculated column values along the slice (output)
+    psVector* cutRows,                 ///< if not NULL, the calculated row values along the slice (output)
+    const psImage* input,              ///< the input image in which to perform the cut
+    const psImage* mask,               ///< the mask for the input image.
+    psMaskType maskVal,                ///< the mask value to apply to the mask
+    psRegion region,                   ///< the start and end points to cut along
+    unsigned int nSamples,             ///< the number of samples along the cut
+    psImageInterpolateMode mode        ///< the interpolation method to use
+);
+
+/** Extract radial region data to a vector. A vector is constructed where each
+ *  vector elements is derived from the statistics of the pixels which land
+ *  within one of a sequence of radii. The radii are centered on the image
+ *  pixel coordinate x,y, and are defined by the sequence of values in the
+ *  vector radii. The specific algorithm which must be used is described in
+ *  the PSLib ADD (PSDC-430-006). The statistic used to derive the output
+ *  vector value is specified by stats. Only one of the statistics choices
+ *  may be specified, otherwise the function must return an error. This
+ *  function must be defined for the following types: psS8, psU16, psF32,
+ *  psF64.
+ *
+ *  @return psVector    resulting vector
+ */
+psVector* psImageRadialCut(
+    psVector* out,                     ///< psVector to recycle, or NULL.
+    const psImage* input,              ///< the input image in which to perform the cut
+    const psImage* mask,               ///< the mask for the input image.
+    psMaskType maskVal,                ///< the mask value to apply to the mask
+    float x,                           ///< the column of the center of the cut circle
+    float y,                           ///< the row of the center of the cut circle
+    const psVector* radii,             ///< the radii of the cut circle
+    const psStats* stats               ///< the statistic to perform in operation
+);
+
+/// @}
+#endif // #ifndef PSIMAGE_PIXEL_EXTRACT_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImagePixelInterpolate.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImagePixelInterpolate.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImagePixelInterpolate.c	(revision 22158)
@@ -0,0 +1,379 @@
+/** @file  psImagePixelInterpolate.c
+ *
+ *  @brief Functions for interpolating bad pixels in images
+ *
+ *  these functions test and set masked pixels in an image.  These functions are complementary
+ *  to the psImageInterpolate functions, which perform sub-pixel interpolation.  Those
+ *  functions require all pixels surrounding the sub-pixel interpolation to have values which
+ *  are valid.  These functions enable interpolation of complete missing pixels, potentially
+ *  across large spans.
+ *
+ *  @author Eugene Magnier, IfA
+ *
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-10-09 19:25:44 $
+ *
+ *  Copyright 2007 Institute for Astronomy, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <string.h>
+
+#include "psAbort.h"
+#include "psMemory.h"
+#include "psError.h"
+#include "psAssert.h"
+#include "psString.h"
+#include "psPolynomial.h"
+#include "psPolynomialUtils.h"
+#include "psMinimizePolyFit.h"
+#include "psImage.h"
+#include "psImageInterpolate.h"
+#include "psImagePixelInterpolate.h"
+
+#include "psFits.h"
+#include "psFitsImage.h"
+
+# define PS_IMAGE_ITER_STATE(XS,XE,YS,YE,N_MIN,TYPE) \
+	    nGood = 0; \
+	    for (int jy = YS; jy <= YE; jy++) { \
+		/* stick to pixels in image grid */ \
+		if (jy + iy < 0) { continue; } \
+		if (jy + iy >= mask->numRows) { continue; } \
+		for (int jx = XS; jx <= XE; jx++) { \
+		    /* stick to pixels in image grid */ \
+		    if (jx + ix < 0) { continue; } \
+		    if (jx + ix >= mask->numCols) { continue; } \
+		    /* do not test self */ \
+		    if (!jx && !jy) { continue; } \
+		    if (mask->data.PS_TYPE_MASK_DATA[iy+jy][ix+jx] & maskVal) { continue; } \
+		    nGood ++; \
+		} \
+	    } \
+	    if (nGood >= N_MIN) {  \
+		nPoor ++; \
+		result->data.S32[iy][ix] = TYPE; \
+		continue; \
+	    }
+
+// count and mark pixels based on their potential for being interpolated.  the input image is
+// just the mask, the output image contains enum values which define the type of interpolation which
+// can be performed
+psImage *psImagePixelInterpolateState (int *nBad, int *nPoor, psImage *mask, psMaskType maskVal) {
+
+    psImage *result = psImageAlloc (mask->numCols, mask->numRows, PS_TYPE_S32);
+    psImageInit (result, 0);
+    
+    *nPoor = 0;
+    *nBad = 0;
+
+    for (int iy = 0; iy < mask->numRows; iy++) {
+	for (int ix = 0; ix < mask->numCols; ix++) {
+
+	    // state of the good pixels (unmasked)
+	    if (!(mask->data.PS_TYPE_MASK_DATA[iy][ix] & maskVal)) { 
+		// count good neighbor pixels (+ self)
+		int nGood = 0;
+		int minX = +1;
+		int maxX = -1;
+		int minY = +1;
+		int maxY = -1;
+		for (int jy = -1; jy <= +1; jy++) {
+		    /* stick to pixels in image grid */
+		    if (jy + iy < 0) { continue; }
+		    if (jy + iy >= mask->numRows) { continue; }
+		    for (int jx = -1; jx <= +1; jx++) {
+			/* stick to pixels in image grid */
+			if (jx + ix < 0) { continue; }
+			if (jx + ix >= mask->numCols) { continue; }
+			if (mask->data.PS_TYPE_MASK_DATA[iy+jy][ix+jx] & maskVal) { continue; }
+			nGood ++;
+			minX = PS_MIN (minX, jx);
+			maxX = PS_MAX (maxX, jx);
+			minY = PS_MIN (minY, jy);
+			maxY = PS_MAX (maxY, jy);
+		    }
+		}
+		int dX = maxX - minX;
+		int dY = maxY - minY;
+		// what type of local interpolation can we use?
+		if ((nGood >= 6) && (dX == 2) && (dY == 2)) {
+		    result->data.S32[iy][ix] = PS_IMAGE_INTERPOLATE_GOOD2;
+		    continue; 
+		}
+		if (nGood >= 3) {
+		    result->data.S32[iy][ix] = PS_IMAGE_INTERPOLATE_GOOD1;
+		    continue; 
+		}
+		result->data.S32[iy][ix] = PS_IMAGE_INTERPOLATE_GOOD0;
+		continue; 
+	    }
+
+	    // examine the neighbors.  If at least 6 of the 8 surrounding, or 3 of the 4 corner
+	    // neighbors are valid, this is a pixel which can be interpolated.
+
+	    int nGood;
+
+	    // check for poor pixels
+	    PS_IMAGE_ITER_STATE (-1,+1,-1,+1,6, PS_IMAGE_INTERPOLATE_CENTER);
+	    PS_IMAGE_ITER_STATE (-1,+0,-1,+0,3, PS_IMAGE_INTERPOLATE_UR);
+	    PS_IMAGE_ITER_STATE (-1,+0,+0,+1,3, PS_IMAGE_INTERPOLATE_LR);
+	    PS_IMAGE_ITER_STATE (+0,+1,-1,+0,3, PS_IMAGE_INTERPOLATE_UL);
+	    PS_IMAGE_ITER_STATE (+0,+1,+0,+1,3, PS_IMAGE_INTERPOLATE_LL);
+
+	    nBad ++;
+	    result->data.S32[iy][ix] = PS_IMAGE_INTERPOLATE_BAD;
+	}	    
+    }
+    return result;
+}
+
+// interpolate the poor pixels using the available options
+bool psImagePixelInterpolatePoor (psImage *image, psImage *state, psImage *mask, psMaskType maskVal) {
+
+    assert (image->numCols == state->numCols);
+    assert (image->numRows == state->numRows);
+    assert (image->numCols == mask->numCols);
+    assert (image->numRows == mask->numRows);
+
+    // allocate the vectors for the 2nd order fit below
+    psVector *f  = psVectorAlloc (9, PS_TYPE_F32);
+    // XXX if we add the weight above, include df
+    // psVector *df = psVectorAlloc (9, PS_TYPE_F32); 
+    psVector *x  = psVectorAlloc (9, PS_TYPE_F32);
+    psVector *y  = psVectorAlloc (9, PS_TYPE_F32);
+
+    // allocate a 2D polynomial to fit a quadratic to the valid neighbor pixels.
+    psPolynomial2D *poly = psPolynomial2DAlloc (PS_POLYNOMIAL_ORD, 2, 2);
+    poly->coeffMask[2][2] = PS_POLY_MASK_SET;
+    poly->coeffMask[2][1] = PS_POLY_MASK_SET;
+    poly->coeffMask[1][2] = PS_POLY_MASK_SET;
+
+    for (int iy = 0; iy < state->numRows; iy++) {
+	for (int ix = 0; ix < state->numCols; ix++) {
+
+	    switch (state->data.S32[iy][ix]) {
+	      case PS_IMAGE_INTERPOLATE_GOOD0: 
+	      case PS_IMAGE_INTERPOLATE_GOOD1: 
+	      case PS_IMAGE_INTERPOLATE_GOOD2: 
+		// skip the good pixels
+		break; 
+
+	      case PS_IMAGE_INTERPOLATE_BAD:
+		// skip the bad pixels
+		break; 
+
+	      case PS_IMAGE_INTERPOLATE_CENTER: {
+		  // XXX is there a fit-image-region function?
+		  int n = 0;
+		  for (int jy = -1; jy <= +1; jy++) {
+		      // skip invalid pixels 
+		      if (jy + iy < 0) { continue; }
+		      if (jy + iy >= image->numRows) { continue; }
+		      for (int jx = -1; jx <= +1; jx++) {
+			  // skip invalid pixels 
+			  if (jx + ix < 0) { continue; } 
+			  if (jx + ix >= image->numCols) { continue; } 
+			  // skip self 
+			  if (!jx && !jy) { continue; } 
+			  // skip masked pixels
+			  if (mask->data.PS_TYPE_MASK_DATA[iy+jy][ix+jx] & maskVal) { continue; }
+			  x->data.F32[n] = jx;
+			  y->data.F32[n] = jy;
+			  f->data.F32[n] = image->data.F32[iy+jy][ix+jx];
+			  // df->data.F32[n] = weight->data.F32[iy+jy][ix+jx];
+			  n++;
+		      }
+		  }
+		  // set vector lengths here
+		  x->n = n;
+		  y->n = n;
+		  f->n = n;
+		  // df->n = n;
+		  // psVectorFitPolynomial2D (poly, NULL, 0xff, f, df, x, y);
+		  psVectorFitPolynomial2D (poly, NULL, 0xff, f, NULL, x, y);
+		  // apply the fitted quadratic to get the poor pixel value
+		  image->data.F32[iy][ix] = poly->coeff[0][0];
+		  break; }
+
+		// XXX should I use 1 1D polynomial fitting all unmasked pixels in the 3x3 grid?
+		// XXX that would automatically extend to regions where only 2 pixels are valid...
+	      case PS_IMAGE_INTERPOLATE_LL: {
+		  // fit a plane to the 3 pixels at (0,1),(1,0),(1,1), extend to pixel at (0,0)
+		  image->data.F32[iy][ix] = image->data.F32[iy+1][ix+1] - image->data.F32[iy+0][ix+1] - image->data.F32[iy+1][ix+0];
+		  break; }
+
+	      case PS_IMAGE_INTERPOLATE_LR: {
+		  // fit a plane to the 3 pixels at (0,1),(-1,0),(-1,1), extend to pixel at (0,0)
+		  image->data.F32[iy][ix] = image->data.F32[iy+1][ix-1] - image->data.F32[iy+0][ix-1] - image->data.F32[iy+1][ix+0];
+		  break; }
+
+	      case PS_IMAGE_INTERPOLATE_UL: {
+		  // fit a plane to the 3 pixels at (0,-1),(1,0),(1,-1), extend to pixel at (0,0)
+		  image->data.F32[iy][ix] = image->data.F32[iy-1][ix+1] - image->data.F32[iy+0][ix+1] - image->data.F32[iy-1][ix+0];
+		  break; }
+
+	      case PS_IMAGE_INTERPOLATE_UR: {
+		  // fit a plane to the 3 pixels at (0,-1),(-1,0),(-1,-1), extend to pixel at (0,0)
+		  image->data.F32[iy][ix] = image->data.F32[iy-1][ix-1] - image->data.F32[iy+0][ix-1] - image->data.F32[iy-1][ix+0];
+		  break; }
+
+	      default:
+		psAbort("impossible case in __func__");
+	    }
+	}	    
+    }
+
+    psFree (x);
+    psFree (y);
+    psFree (f);
+
+    psFree (poly);
+    return true;
+}
+    
+// interpolate the good pixels to their true centers
+bool psImagePixelInterpolateCenter (psImage *value, psImage *xCoord, psImage *yCoord, psImage *state, psImage *mask, psMaskType maskVal) {
+
+    assert (value->numCols == state->numCols);
+    assert (value->numRows == state->numRows);
+    assert (value->numCols == mask->numCols);
+    assert (value->numRows == mask->numRows);
+
+# if (0)
+    psFits *fits = NULL;
+
+    fits = psFitsOpen ("xcoords.fits", "w");
+    psFitsWriteImage (fits, NULL, xCoord, 0, NULL);
+    psFitsClose (fits);
+
+    fits = psFitsOpen ("ycoords.fits", "w");
+    psFitsWriteImage (fits, NULL, yCoord, 0, NULL);
+    psFitsClose (fits);
+
+    fits = psFitsOpen ("value.fits", "w");
+    psFitsWriteImage (fits, NULL, value, 0, NULL);
+    psFitsClose (fits);
+# endif
+
+    psImage *output = psImageAlloc (value->numCols, value->numRows, PS_TYPE_F32);
+
+    // allocate the vectors for the 2nd order fit below
+    psVector *f  = psVectorAlloc (9, PS_TYPE_F32);
+    // XXX if we add the weight above, include df
+    // psVector *df = psVectorAlloc (9, PS_TYPE_F32); 
+    psVector *x  = psVectorAlloc (9, PS_TYPE_F32);
+    psVector *y  = psVectorAlloc (9, PS_TYPE_F32);
+
+    // allocate a 2D polynomial to fit a quadratic to the valid neighbor pixels.
+    psPolynomial2D *poly2o = psPolynomial2DAlloc (PS_POLYNOMIAL_ORD, 2, 2);
+    poly2o->coeffMask[2][2] = PS_POLY_MASK_SET;
+    poly2o->coeffMask[2][1] = PS_POLY_MASK_SET;
+    poly2o->coeffMask[1][2] = PS_POLY_MASK_SET;
+
+    // allocate a 2D polynomial to fit a plane to the valid neighbor pixels.
+    psPolynomial2D *poly1o = psPolynomial2DAlloc (PS_POLYNOMIAL_ORD, 1, 1);
+    poly2o->coeffMask[1][1] = PS_POLY_MASK_SET;
+
+    for (int iy = 0; iy < state->numRows; iy++) {
+	for (int ix = 0; ix < state->numCols; ix++) {
+
+	    switch (state->data.S32[iy][ix]) {
+	      case PS_IMAGE_INTERPOLATE_GOOD2: {
+		  // XXX is there a fit-image-region function?
+		  int n = 0;
+		  for (int jy = -1; jy <= +1; jy++) {
+		      // skip invalid pixels 
+		      if (jy + iy < 0) { continue; }
+		      if (jy + iy >= value->numRows) { continue; }
+		      for (int jx = -1; jx <= +1; jx++) {
+			  // skip invalid pixels 
+			  if (jx + ix < 0) { continue; } 
+			  if (jx + ix >= value->numCols) { continue; } 
+			  // skip masked pixels
+			  if (mask->data.PS_TYPE_MASK_DATA[iy+jy][ix+jx] & maskVal) { continue; }
+			  x->data.F32[n] = xCoord->data.F32[iy+jy][ix+jx];
+			  y->data.F32[n] = yCoord->data.F32[iy+jy][ix+jx];
+			  f->data.F32[n] = value->data.F32[iy+jy][ix+jx];
+			  // df->data.F32[n] = weight->data.F32[iy+jy][ix+jx];
+			  n++;
+		      }
+		  }
+		  // set vector lengths here
+		  x->n = n;
+		  y->n = n;
+		  f->n = n;
+		  // df->n = n;
+		  // psVectorFitPolynomial2D (poly, NULL, 0xff, f, df, x, y);
+		  psVectorFitPolynomial2D (poly2o, NULL, 0xff, f, NULL, x, y);
+		  // apply the fitted quadratic to get the poor pixel value
+		  // center of pixel is 0.5,0.5
+		  output->data.F32[iy][ix] = psPolynomial2DEval (poly2o, ix + 0.5, iy + 0.5);
+		  break; }
+
+	      case PS_IMAGE_INTERPOLATE_GOOD1: {
+		  // XXX is there a fit-image-region function?
+		  int n = 0;
+		  for (int jy = -1; jy <= +1; jy++) {
+		      // skip invalid pixels 
+		      if (jy + iy < 0) { continue; }
+		      if (jy + iy >= value->numRows) { continue; }
+		      for (int jx = -1; jx <= +1; jx++) {
+			  // skip invalid pixels 
+			  if (jx + ix < 0) { continue; } 
+			  if (jx + ix >= value->numCols) { continue; } 
+			  // skip masked pixels
+			  if (mask->data.PS_TYPE_MASK_DATA[iy+jy][ix+jx] & maskVal) { continue; }
+			  x->data.F32[n] = xCoord->data.F32[iy+jy][ix+jx];
+			  y->data.F32[n] = yCoord->data.F32[iy+jy][ix+jx];
+			  f->data.F32[n] = value->data.F32[iy+jy][ix+jx];
+			  // df->data.F32[n] = weight->data.F32[iy+jy][ix+jx];
+			  n++;
+		      }
+		  }
+		  // set vector lengths here
+		  x->n = n;
+		  y->n = n;
+		  f->n = n;
+		  // df->n = n;
+		  // psVectorFitPolynomial2D (poly1o, NULL, 0xff, f, df, x, y);
+		  psVectorFitPolynomial2D (poly1o, NULL, 0xff, f, NULL, x, y);
+		  // apply the fitted quadratic to get the poor pixel value
+		  output->data.F32[iy][ix] = psPolynomial2DEval (poly1o, ix + 0.5, iy + 0.5);
+		  break; }
+
+	      case PS_IMAGE_INTERPOLATE_GOOD0: {
+		  output->data.F32[iy][ix] = value->data.F32[iy][ix];
+		  break; }
+
+	      default:
+		// skip poor or bad pixels (interpolate later)
+		break;
+	    }
+	}	    
+    }
+
+    for (int iy = 0; iy < value->numRows; iy++) {
+	for (int ix = 0; ix < value->numCols; ix++) {
+	  if (mask->data.PS_TYPE_MASK_DATA[iy][ix] & maskVal) { continue; }
+	  value->data.F32[iy][ix] = output->data.F32[iy][ix];
+	}
+    }
+
+    psFree (x);
+    psFree (y);
+    psFree (f);
+
+    psFree (poly2o);
+    psFree (poly1o);
+
+    psFree (output);
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImagePixelInterpolate.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImagePixelInterpolate.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImagePixelInterpolate.h	(revision 22158)
@@ -0,0 +1,41 @@
+/** @file  psImagePixelInterpolate.c
+ *
+ *  @brief Functions for interpolating bad pixels in images
+ *
+ *  @ingroup Image
+ *
+ *  @author Eugene Magnier, IfA
+ *
+ *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-09-20 23:54:25 $
+ *
+ *  Copyright 2007 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PS_IMAGE_PIXEL_INTERPOLATE_H
+#define PS_IMAGE_PIXEL_INTERPOLATE_H
+
+/// @addtogroup ImageOps Image Operations
+/// @{
+
+// XXX make these all bit values?
+typedef enum {
+    PS_IMAGE_INTERPOLATE_GOOD   = 0x10,
+    PS_IMAGE_INTERPOLATE_GOOD0  = 0x11,
+    PS_IMAGE_INTERPOLATE_GOOD1  = 0x12,
+    PS_IMAGE_INTERPOLATE_GOOD2  = 0x13,
+    PS_IMAGE_INTERPOLATE_BAD    = 0x01,
+    PS_IMAGE_INTERPOLATE_CENTER = 0x02,
+    PS_IMAGE_INTERPOLATE_CORNER = 0x04,
+    PS_IMAGE_INTERPOLATE_UR     = 0x04,
+    PS_IMAGE_INTERPOLATE_UL     = 0x05,
+    PS_IMAGE_INTERPOLATE_LR     = 0x06,
+    PS_IMAGE_INTERPOLATE_LL     = 0x07,
+} psImagePixelInterpolateType;
+
+psImage *psImagePixelInterpolateState (int *nBad, int *nPoor, psImage *mask, psMaskType maskVal);
+bool psImagePixelInterpolatePoor (psImage *image, psImage *state, psImage *mask, psMaskType maskVal);
+bool psImagePixelInterpolateCenter (psImage *value, psImage *xCoord, psImage *yCoord, psImage *state, psImage *mask, psMaskType maskVal);
+
+/// @}
+#endif // #ifndef PS_IMAGE_MAP_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImagePixelManip.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImagePixelManip.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImagePixelManip.c	(revision 22158)
@@ -0,0 +1,313 @@
+/** @file  psImagePixelManip.c
+ *
+ *  @brief Contains basic image pixel and geometry manipulation operations, as
+ *         specified in the PSLIB SDRS sections "Image Pixel Manipulations" and
+ *         "Image Geometry Manipulations".
+ *
+ *  @ingroup Image
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.24 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-04-22 22:22:09 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <math.h>                          // for isfinite(), etc.
+#include <stdlib.h>
+#include <string.h>                        // for memcpy, etc.
+
+#include "psImagePixelManip.h"
+
+#include "psError.h"
+#include "psImage.h"
+#include "psStats.h"
+#include "psMemory.h"
+#include "psAssert.h"
+
+#include "psCoord.h"
+
+int psImageClip(psImage* input,
+                double min,
+                double vmin,
+                double max,
+                double vmax)
+{
+    psS32 numClipped = 0;
+    psU32 numRows;
+    psU32 numCols;
+
+    if (input == NULL) {
+        return 0;
+    }
+
+    if (max < min) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified min value, %g, can not be greater than the specified max value, %g."),
+                (double)min,(double)max);
+        return 0;
+    }
+
+    numRows = input->numRows;
+    numCols = input->numCols;
+
+    switch (input->type.type) {
+
+        #define psImageClipCase(type) \
+    case PS_TYPE_##type: { \
+            if (vmin < PS_MIN_##type || vmin > PS_MAX_##type) { \
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+                        _("Specified %s value, %g, is outside of psImage type's range (%s: %g to %g)."), \
+                        "vmin",vmin, PS_TYPE_##type##_NAME, \
+                        (psF64)PS_MIN_##type,(psF64)PS_MAX_##type); \
+            } \
+            if (vmax > PS_MAX_##type || vmax < PS_MIN_##type) { \
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+                        _("Specified %s value, %g, is outside of psImage type's range (%s: %g to %g)."), \
+                        "vmax",vmax, PS_TYPE_##type##_NAME, \
+                        (psF64)PS_MIN_##type,(psF64)PS_MAX_##type); \
+            } \
+            for (psU32 row = 0;row<numRows;row++) { \
+                ps##type* inputRow = input->data.type[row]; \
+                for (psU32 col = 0; col < numCols; col++) { \
+                    if ((psF64)inputRow[col] < min) { \
+                        inputRow[col] = (ps##type)vmin; \
+                        numClipped++; \
+                    } else if ((psF64)inputRow[col] > max) { \
+                        inputRow[col] = (ps##type)vmax; \
+                        numClipped++; \
+                    } \
+                } \
+            } \
+        } \
+        break;
+
+        psImageClipCase(S8)
+        psImageClipCase(S16)
+        psImageClipCase(S32)            // Not a requirement
+        psImageClipCase(S64)            // Not a requirement
+        psImageClipCase(U8)
+        psImageClipCase(U16)
+        psImageClipCase(U32)            // Not a requirement
+        psImageClipCase(U64)            // Not a requirement
+        psImageClipCase(F32)
+        psImageClipCase(F64)
+
+    default: {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,input->type.type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    _("Specified psImage type, %s, is not supported."),
+                    typeStr);
+        }
+    }
+
+    return numClipped;
+}
+
+int psImageClipNaN(psImage* input,
+                   float value)
+{
+    psS32 numClipped = 0;
+    psU32 numRows;
+    psU32 numCols;
+
+    if (input == NULL) {
+        return 0;
+    }
+    numRows = input->numRows;
+    numCols = input->numCols;
+
+    switch (input->type.type) {
+
+        #define psImageClipNaNCase(type) \
+    case PS_TYPE_##type: \
+        for (psU32 row = 0;row<numRows;row++) { \
+            ps##type* inputRow = input->data.type[row]; \
+            for (psU32 col = 0; col < numCols; col++) { \
+                if (! isfinite(inputRow[col])) { \
+                    inputRow[col] = (ps##type)value; \
+                    numClipped++; \
+                } \
+            } \
+        } \
+        break;
+
+        psImageClipNaNCase(F32)
+        psImageClipNaNCase(F64)
+
+    default: {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,input->type.type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    _("Specified psImage type, %s, is not supported."),
+                    typeStr);
+        }
+    }
+
+    return numClipped;
+}
+
+// XXX why does this have an x0,y0?  does it respect col0,row0 (in either image?)
+int psImageOverlaySection(psImage* image,
+                          const psImage* overlay,
+                          int x0,
+                          int y0,
+                          const char *op)
+{
+    psU32 imageNumRows;
+    psU32 imageNumCols;
+    psU32 overlayNumRows;
+    psU32 overlayNumCols;
+    psU32 imageRowLimit;
+    psU32 imageColLimit;
+    psElemType type;
+    psU32 pixelsOverlaid = 0;
+
+    if (image == NULL || overlay == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not operate on a NULL psImage."));
+        return pixelsOverlaid;
+    }
+
+    if (op == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Operation can not be NULL."));
+        return pixelsOverlaid;
+    }
+
+    type = image->type.type;
+
+    if (type != overlay->type.type) {
+        char* typeStr;
+        char* typeStrOverlay;
+        PS_TYPE_NAME(typeStr,type);
+        PS_TYPE_NAME(typeStrOverlay,overlay->type.type);
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("Input overlay psImage type, %s, must match input psImage type, %s."),
+                typeStrOverlay, typeStr);
+        return pixelsOverlaid;
+    }
+
+    imageNumRows = image->numRows;
+    imageNumCols = image->numCols;
+    overlayNumRows = overlay->numRows;
+    overlayNumCols = overlay->numCols;
+    imageRowLimit = y0 + overlayNumRows;
+    imageColLimit = x0 + overlayNumCols;
+
+    /* check to see if overlay is within the input image */
+    if ( y0 < 0 ||
+            x0 < 0 ||
+            imageRowLimit > imageNumRows ||
+            imageColLimit > imageNumCols) {
+
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified subset range, [%d:%d,%d:%d], is invalid or outside input psImage's boundaries, [0:%d,0:%d]."),
+                x0, imageColLimit, y0, imageRowLimit,
+                imageNumCols, imageNumRows);
+        return pixelsOverlaid;
+    }
+
+
+    #define psImageOverlayLoop(DATATYPE,OP) { \
+        for (int row=y0;row<imageRowLimit;row++) { \
+            ps##DATATYPE* imageRow = image->data.DATATYPE[row]; \
+            ps##DATATYPE* overlayRow = overlay->data.DATATYPE[row-y0]; \
+            for (int col=x0;col<imageColLimit;col++) { \
+                imageRow[col] OP overlayRow[col-x0]; \
+            } \
+        } \
+        pixelsOverlaid += (imageRowLimit - y0) * (imageColLimit - x0); \
+    }
+
+    #define psImageOverlayLoopDivide(DATATYPE,BADVALUE) { \
+        for (int row=y0;row<imageRowLimit;row++) { \
+            ps##DATATYPE* imageRow = image->data.DATATYPE[row]; \
+            ps##DATATYPE* overlayRow = overlay->data.DATATYPE[row-y0]; \
+            for (int col=x0;col<imageColLimit;col++) { \
+                if (overlayRow[col-x0] == 0) { \
+                    imageRow[col] = BADVALUE; \
+                    continue; \
+                } \
+                imageRow[col] /= overlayRow[col-x0]; \
+            } \
+        } \
+        pixelsOverlaid += (imageRowLimit - y0) * (imageColLimit - x0); \
+    }
+
+    // Use memcpy to perform the '=' operation.  Depending on the particular application, it can be about 20%
+    // faster than using a 'for' loop.  Josh Hoblitt says it has an additional advantage that it doesn't blow
+    // away the L2 cache.  Of course, if you want to use the result immediately afterwards, perhaps this is
+    // a drawback?  We fall back on the loop if we have to change types.
+    #define psImageOverlaySetLoop(DATATYPE) { \
+        if (image->type.type == overlay->type.type) { \
+            int numBytes = (imageColLimit - x0) * sizeof(ps##DATATYPE); \
+            for (int row = y0; row < imageRowLimit; row++) { \
+                ps##DATATYPE *imageRow = image->data.DATATYPE[row]; \
+                ps##DATATYPE *overlayRow = overlay->data.DATATYPE[row - y0]; \
+                memcpy(&imageRow[x0], overlayRow, numBytes); \
+            } \
+            pixelsOverlaid += (imageRowLimit - y0) * (imageColLimit - x0); \
+        } else { \
+            psImageOverlayLoop(DATATYPE,=); \
+        } \
+    }
+
+    #define psImageOverlayCase(DATATYPE,BADVALUE) \
+case PS_TYPE_##DATATYPE: \
+    switch (*op) { \
+    case '+': \
+        psImageOverlayLoop(DATATYPE,+=); \
+        break; \
+    case '-': \
+        psImageOverlayLoop(DATATYPE,-=); \
+        break; \
+    case '*': \
+        psImageOverlayLoop(DATATYPE,*=); \
+        break; \
+    case '/': \
+        psImageOverlayLoopDivide(DATATYPE,BADVALUE); \
+        break; \
+    case '=': \
+        psImageOverlaySetLoop(DATATYPE); \
+        break; \
+    default: \
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+                _("Specified operation, '%s', is not supported."), \
+                op); \
+        return pixelsOverlaid; \
+    } \
+    break;
+
+    switch (type) {
+        psImageOverlayCase(U8, 0);
+        psImageOverlayCase(U16,0);
+        psImageOverlayCase(U32,0);       // Not a requirement
+        psImageOverlayCase(U64,0);       // Not a requirement
+        psImageOverlayCase(S8, 0);
+        psImageOverlayCase(S16,0);
+        psImageOverlayCase(S32,0);       // Not a requirement
+        psImageOverlayCase(S64,0);       // Not a requirement
+        psImageOverlayCase(F32,NAN);
+        psImageOverlayCase(F64,NAN);
+
+    default: {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    _("Specified psImage type, %s, is not supported."),
+                    typeStr);
+            return pixelsOverlaid;
+        }
+    }
+
+    return pixelsOverlaid;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImagePixelManip.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImagePixelManip.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImagePixelManip.h	(revision 22158)
@@ -0,0 +1,72 @@
+/* @file  psImagePixelManip.h
+ *
+ * @brief Basic image pixel manipulation operations
+ *
+ * @author Robert DeSonia, MHPCC
+ *
+ * @version $Revision: 1.17 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-03-14 00:39:50 $
+ *
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_IMAGE_PIXEL_MANIP_H
+#define PS_IMAGE_PIXEL_MANIP_H
+
+/// @addtogroup ImageOps Image Operations
+/// @{
+
+#include "psImage.h"
+#include "psCoord.h"
+#include "psStats.h"
+#include "psPixels.h"
+
+/** Clip image values outside of range to given values
+ *
+ *  All pixels with values less than min are set to the value vmin.  all pixels
+ *  with values greater than max are set to the value vmax. This function is
+ *  defined for psU8, psU16, psS8, psS16, psF32, psF64.
+ *
+ *  @return int     The number of clipped pixels
+ */
+int psImageClip(
+    psImage* input,                    ///< the image to clip
+    double min,                        ///< the minimum image value allowed
+    double vmin,                       ///< the value pixels < min are set to
+    double max,                        ///< the maximum image value allowed
+    double vmax                        ///< the value pixels > max are set to
+);
+
+/** Clip NaN image pixels to given value.
+ *
+ *  Pixels with NaN, +Inf, or -Inf values are set to the specified value. This
+ *  function is defined for psF32, psF64.
+ *
+ *  @return int     The number of clipped pixels
+ */
+int psImageClipNaN(
+    psImage* input,                    ///< the image to clip
+    float value                        ///< the value to set all NaN/Inf values to
+);
+
+/** Overlay subregion of image with another image
+ *
+ *  Replace the pixels in the image which correspond to the pixels in OVERLAY
+ *  with values derived from the IMAGE and OVERLAY based on the given operator
+ *  OP.  Valid operators are "=" (set image value to OVERLAY value), "+" (add
+ *  OVERLAY value to image value), "-" (subtract OVERLAY from image), "*"
+ *  (multiply OVERLAY times image), "/" (divide image by OVERLAY).  This
+ *  function is defined for psU8, psS8, psS16, psF32, psF64.
+ *
+ *  @return int         0 if success, non-zero if failed.
+ */
+int psImageOverlaySection(
+    psImage* image,                    ///< target image
+    const psImage* overlay,            ///< the overlay image
+    int x0,                            ///< the column to start overlay
+    int y0,                            ///< the row to start overlay
+    const char *op                     ///< the operation to perform for overlay
+);
+
+/// @}
+#endif // #ifndef PS_IMAGE_PIXEL_MANIP_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageStats.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageStats.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageStats.c	(revision 22158)
@@ -0,0 +1,647 @@
+/** @file psImageStats.c
+ *  \brief Routines for calculating statistics on images.
+ *  @ingroup ImageStats
+ *
+ *  This file will hold the prototypes for procedures which calculate
+ *  statistic on images, histograms on images, and fit/evaluate Chebyshev
+ *  polynomials to images.
+ *
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.106 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-03-14 00:39:50 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <float.h>
+#include <math.h>
+#include "psMemory.h"
+#include "psVector.h"
+#include "psTrace.h"
+#include "psError.h"
+#include "psStats.h"
+#include "psImage.h"
+#include "psPolynomial.h"
+#include "psImageStats.h"
+#include "psAssert.h"
+
+#include "psRegion.h"
+#include "psRegionForImage.h"
+
+/// This routine must determine the various statistics for the image.
+/*****************************************************************************
+psImageStats(stats, in, mask, maskVal): this routine simply calls the
+psVectorStats() routine, which does the actual statistical calculation.  In
+order to do so, we create dummy psVectors and set their "data" pointer to that
+of the input psImages.
+
+XXX: use static psVectors
+
+XXX: optimize this.  2k vs 4k, sample mean, takes8 seconds on Gene's machine.
+Should take .2.
+ *****************************************************************************/
+bool psImageStats(psStats* stats,
+                      const psImage* in,
+                      const psImage* mask,
+                      psMaskType maskVal)
+{
+    psVector *junkData = NULL;
+    psVector *junkMask = NULL;
+
+    PS_ASSERT_PTR_NON_NULL(stats, false);
+    PS_ASSERT_INT_NONZERO(stats->options, false);
+    PS_ASSERT_IMAGE_NON_NULL(in, false)
+    if (mask != NULL) {
+        PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_U8, false);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(in, mask, false);
+    }
+
+    if (in->parent == NULL) {
+        // stuff the image data into a psVector struct.
+        junkData = (psVector *) psAlloc(sizeof(psVector));
+        junkData->type = in->type;
+        P_PSVECTOR_SET_NALLOC(junkData,in->numRows * in->numCols);
+        junkData->n = junkData->nalloc;
+        junkData->data.U8 = in->data.V[0];      // since psImage data is contiguous...
+    } else {
+        // image not necessarily contiguous
+        int numRows = in->numRows;
+        int numCols = in->numCols;
+        int rowSize = numCols * (PSELEMTYPE_SIZEOF(in->type.type));
+
+        junkData = psVectorAlloc(numRows*numCols, in->type.type);
+
+        psU8* data = junkData->data.U8;
+        for (int row = 0; row < numRows; row++) {
+            memcpy(data, in->data.V[row], rowSize);
+            data += rowSize;
+        }
+    }
+
+    if (mask != NULL) {
+        if (mask->parent == NULL) {
+            // stuff the mask data into a psVector struct.
+            junkMask = psAlloc(sizeof(psVector));
+            junkMask->type = mask->type;
+            P_PSVECTOR_SET_NALLOC(junkMask,mask->numRows * mask->numCols);
+            junkMask->n = junkMask->nalloc;
+            junkMask->data.U8 = mask->data.V[0];
+        } else {
+            // image not necessarily contiguous
+            int numRows = mask->numRows;
+            int numCols = mask->numCols;
+            int rowSize = numCols * (PSELEMTYPE_SIZEOF(mask->type.type));
+
+            junkMask = psVectorAlloc(numRows*numCols, mask->type.type);
+
+            psU8* data = junkMask->data.U8;
+            for (int row = 0; row < numRows; row++) {
+                memcpy(data, mask->data.V[row], rowSize);
+                data += rowSize;
+            }
+        }
+    }
+
+    psVectorStats(stats, junkData, NULL, junkMask, maskVal);
+
+    psFree(junkMask);
+    psFree(junkData);
+    return true;
+}
+
+/*****************************************************************************
+NOTE: We assume that the psHistogram structure out has already been allocated
+and initialized.
+ *****************************************************************************/
+bool psImageHistogram(psHistogram* out,
+                              const psImage* in,
+                              const psImage* mask,
+                              psMaskType maskVal)
+{
+    PS_ASSERT_PTR_NON_NULL(out, false);
+    PS_ASSERT_PTR_NON_NULL(in, false);
+    if (mask != NULL) {
+        PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_U8, false);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(in, mask, false);
+    }
+    psVector* junkData = NULL;
+    psVector* junkMask = NULL;
+
+    if (in->parent == NULL) {
+        // stuff the image data into a psVector struct.
+        junkData = (psVector *) psAlloc(sizeof(psVector));
+        junkData->type = in->type;
+        P_PSVECTOR_SET_NALLOC(junkData,in->numRows * in->numCols);
+        junkData->n = junkData->nalloc;
+        junkData->data.U8 = in->data.V[0];      // since psImage data is contiguous...
+    } else {
+        // image not necessarily contiguous
+        int numRows = in->numRows;
+        int numCols = in->numCols;
+        int rowSize = numCols * (PSELEMTYPE_SIZEOF(in->type.type));
+
+        junkData = psVectorAlloc(numRows*numCols, in->type.type);
+
+        psU8* data = junkData->data.U8;
+        for (int row = 0; row < numRows; row++) {
+            memcpy(data, in->data.V[row], rowSize);
+            data += rowSize;
+        }
+    }
+
+    if (mask != NULL) {
+        if (mask->parent == NULL) {
+            // stuff the mask data into a psVector struct.
+            junkMask = psAlloc(sizeof(psVector));
+            junkMask->type = mask->type;
+            P_PSVECTOR_SET_NALLOC(junkMask,mask->numRows * mask->numCols);
+            junkMask->n = junkMask->nalloc;
+            junkMask->data.U8 = mask->data.V[0];
+        } else {
+            // image not necessarily contiguous
+            int numRows = mask->numRows;
+            int numCols = mask->numCols;
+            int rowSize = numCols * (PSELEMTYPE_SIZEOF(mask->type.type));
+
+            junkMask = psVectorAlloc(numRows*numCols, mask->type.type);
+
+            psU8* data = junkMask->data.U8;
+            for (int row = 0; row < numRows; row++) {
+                memcpy(data, mask->data.V[row], rowSize);
+                data += rowSize;
+            }
+        }
+    }
+
+    if (!psVectorHistogram(out, junkData, NULL, junkMask, maskVal)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to generate image histogram.\n");
+        psFree(junkMask);
+        psFree(junkData);
+        return false;
+    }
+
+    psFree(junkMask);
+    psFree(junkData);
+
+    return true;
+}
+
+/*****************************************************************************
+calcScaleFactorsEval(n): The Chebyshev polynomials are defined over the
+interval [-1.0 : 1.0].  Images typically have sizes of 512x512 or more.  In
+order to use Chebyshev polynomials, we must scale the coordinates from
+0:512 to -1:1.  This routine takes as input an integer N and produces as
+output a vector of evenly spaced floating point values between -1.0:1.0.
+
+XXX: Use the p_psNormalizeVector here?
+ *****************************************************************************/
+static double* calcScaleFactors(psS32 n)
+{
+    PS_ASSERT_INT_NONNEGATIVE(n, NULL);
+    psS32 i = 0;
+    double tmp = 0.0;
+    double *scalingFactors = (double *)psAlloc(n * sizeof(double));
+
+    for (i = 0; i < n; i++) {
+        tmp = (double)(n - i);
+        tmp = (M_PI * (tmp - 0.5)) / ((double)n);
+        scalingFactors[i] = cos(tmp);
+    }
+
+    return (scalingFactors);
+}
+
+/*****************************************************************************
+psImageFitPolynomial(): This routine takes as input a 2-D image and produces
+as output the coefficients of the Chebyshev polynomials which match that
+input image.
+  Input:
+  Output:
+  Internal Data Structures:
+    chebPolys[i][j]
+    sums[i][j]: This will contain the sum of
+                input->data.F32[y][x] *
+                psPolynomial1DEval(
+chebPolys[i],
+(float) x) *
+                psPolynomial1DEval(
+chebPolys[j],
+(float) y,
+);
+        over all pixels (x,y) in the image.
+  *****************************************************************************/
+bool psImageFitPolynomial(psPolynomial2D* coeffs,
+                                     const psImage* input)
+{
+    PS_ASSERT_IMAGE_NON_NULL(input, false);
+    PS_ASSERT_IMAGE_NON_EMPTY(input, false);
+    if ((input->type.type != PS_TYPE_S8) &&
+            (input->type.type != PS_TYPE_U16) &&
+            (input->type.type != PS_TYPE_F32) &&
+            (input->type.type != PS_TYPE_F64)) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Unallowable image type.\n");
+        return false;
+    }
+    PS_ASSERT_POLY_NON_NULL(coeffs, false);
+    PS_ASSERT_POLY_TYPE(coeffs, PS_POLYNOMIAL_CHEB, false);
+    psS32 x = 0;
+    psS32 y = 0;
+    psS32 i = 0;
+    psS32 j = 0;
+    double **sums = NULL;
+    psPolynomial1D* *chebPolys = NULL;
+    psS32 maxChebyPoly = 0;
+    double *cScalingFactors = NULL;
+    double *rScalingFactors = NULL;
+
+    // Create the sums[][] data structure.  This
+    // will hold the LHS of
+    // equation
+    // 29 in the ADD: sums[k][l] = SUM {
+    // image(x,y) * Tk(x) * Tl(y) }
+    sums = (double **)psAlloc((1 + coeffs->nX) * sizeof(double *));
+    for (i = 0; i < (1 + coeffs->nX); i++) {
+        sums[i] = (double *)psAlloc((1 + coeffs->nY) * sizeof(double));
+    }
+    // We scale the pixel positions to values
+    // between -1.0 and 1.0
+    //    rScalingFactors = calcScaleFactors(input->numRows);
+    //    cScalingFactors = calcScaleFactors(input->numCols);
+    rScalingFactors = calcScaleFactors(input->row0 + input->numRows);
+    cScalingFactors = calcScaleFactors(input->col0 + input->numCols);
+
+    // Determine how many Chebyshev polynomials
+    // are needed, then create them.
+    // XXX: record or verify the poly order/nterm change
+    maxChebyPoly = coeffs->nX;
+    if (coeffs->nY > coeffs->nX) {
+        maxChebyPoly = coeffs->nY;
+    }
+    chebPolys = p_psCreateChebyshevPolys(maxChebyPoly + 1);
+
+    // Compute the sums[][] data structure.
+    for (i = 0; i < (1 + coeffs->nX); i++) {
+        for (j = 0; j < (1 + coeffs->nY); j++) {
+            sums[i][j] = 0.0;
+            //            for (x = 0; x < input->numRows; x++) {
+            //                for (y = 0; y < input->numCols; y++) {
+            for (y = input->row0; y < (input->row0 + input->numRows); y++) {
+                for (x = input->col0; x < (input->col0 + input->numCols); x++) {
+                    double pixel = 0.0;
+                    if (input->type.type == PS_TYPE_S8) {
+                        pixel = (double) input->data.S8[y][x];
+                    } else if (input->type.type == PS_TYPE_U16) {
+                        pixel = (double) input->data.U16[y][x];
+                    } else if (input->type.type == PS_TYPE_F32) {
+                        pixel = (double) input->data.F32[y][x];
+                    } else if (input->type.type == PS_TYPE_F64) {
+                        pixel = input->data.F64[y][x];
+                    }
+                    sums[i][j] += pixel * psPolynomial1DEval(chebPolys[i],rScalingFactors[y]) *
+                                  psPolynomial1DEval(chebPolys[j], cScalingFactors[x]);
+                }
+            }
+        }
+    }
+
+    for (i = 0; i < (1 + coeffs->nX); i++) {
+        for (j = 0; j < (1 + coeffs->nY); j++) {
+            coeffs->coeff[i][j] = sums[i][j];
+            coeffs->coeff[i][j] /= (double)(input->numRows * input->numCols);
+
+            if ((i != 0) && (j != 0)) {
+                coeffs->coeff[i][j] *= 4.0;
+            } else if ((i == 0) && (j == 0)) {
+                coeffs->coeff[i][j] *= 1.0;
+            } else {
+                coeffs->coeff[i][j] *= 2.0;
+            }
+        }
+    }
+
+    // Free the Chebyshev polynomials that were
+    // created in this routine.
+    for (i = 0; i < maxChebyPoly + 1; i++) {
+        psFree(chebPolys[i]);
+    }
+    psFree(chebPolys);
+
+    // Free some data
+    for (i = 0; i < (1 + coeffs->nX); i++) {
+        psFree(sums[i]);
+    }
+    psFree(sums);
+    psFree(cScalingFactors);
+    psFree(rScalingFactors);
+
+    return true;
+}
+
+/*****************************************************************************
+XXX: Use static variables for Chebyshev polynomials and scaling factors.
+ *****************************************************************************/
+psImage* p_psImageEvalPolynomialCheb(psImage* input,
+                                     const psPolynomial2D* coeffs)
+{
+    PS_ASSERT_POLY_TYPE(coeffs, PS_POLYNOMIAL_CHEB, NULL);
+
+    psPolynomial1D* *chebPolys = NULL;
+    long maxChebyPoly = 0;
+    double *cScalingFactors = NULL;
+    double *rScalingFactors = NULL;
+
+    // We scale the pixel positions to values between -1.0 and 1.0
+    // Use static data structures here.
+    //    rScalingFactors = calcScaleFactors(input->numRows);
+    //    cScalingFactors = calcScaleFactors(input->numCols);
+    rScalingFactors = calcScaleFactors(input->numRows+input->row0);
+    cScalingFactors = calcScaleFactors(input->numCols+input->col0);
+
+    // Determine how many Chebyshev polynomials
+    // are needed, then create them.
+    maxChebyPoly = coeffs->nX;
+    if (coeffs->nY > coeffs->nX) {
+        maxChebyPoly = coeffs->nY;
+    }
+
+    chebPolys = p_psCreateChebyshevPolys(maxChebyPoly + 1);
+
+    for (long y = input->row0; y < (input->row0 + input->numRows); y++) {
+        for (long x = input->col0; x < (input->col0 + input->numCols); x++) {
+            double polySum = 0.0;
+            for (long i = 0; i < (1 + coeffs->nX); i++) {
+                for (long j = 0; j < (1 + coeffs->nY); j++) {
+                    polySum +=
+                        psPolynomial1DEval(chebPolys[i], rScalingFactors[y]) *
+                        psPolynomial1DEval(chebPolys[j], cScalingFactors[x]) *
+                        coeffs->coeff[i][j];
+                }
+            }
+
+            if (input->type.type == PS_TYPE_S8) {
+                input->data.S8[y][x] = (char) polySum;
+            } else if (input->type.type == PS_TYPE_U16) {
+                input->data.U16[y][x] = (short int) polySum;
+            } else if (input->type.type == PS_TYPE_F32) {
+                input->data.F32[y][x] = (float) polySum;
+            } else if (input->type.type == PS_TYPE_F64) {
+                input->data.F64[y][x] = polySum;
+            }
+        }
+    }
+
+    // Free the Chebyshev polynomials that were
+    // created in this routine.
+    // XXX: Use static data structures here.
+    for (long i = 0; i < maxChebyPoly + 1; i++) {
+        psFree(chebPolys[i]);
+    }
+    psFree(chebPolys);
+
+    psFree(cScalingFactors);
+    psFree(rScalingFactors);
+
+    return input;
+}
+
+psImage* p_psImageEvalPolynomialOrd(psImage* input,
+                                    const psPolynomial2D* coeffs)
+{
+    PS_ASSERT_POLY_TYPE(coeffs, PS_POLYNOMIAL_ORD, NULL);
+
+    for (int row = 0; row < input->numRows ; row++) {
+        for (int col = 0; col < input->numCols ; col++) {
+            if (input->type.type == PS_TYPE_S8) {
+                input->data.S8[row][col] = (psS8) psPolynomial2DEval(coeffs,
+                                           (psF32) (row + input->row0), (psF32) (col + input->col0));
+            } else if (input->type.type == PS_TYPE_U16) {
+                input->data.U16[row][col] = (psS16) psPolynomial2DEval(coeffs,
+                                            (psF32) (row + input->row0), (psF32) (col + input->col0));
+            } else if (input->type.type == PS_TYPE_F32) {
+                input->data.F32[row][col] = psPolynomial2DEval(coeffs,
+                                            (psF32) (row + input->row0), (psF32) (col + input->col0));
+            } else if (input->type.type == PS_TYPE_F64) {
+                input->data.F64[row][col] = (psF64) psPolynomial2DEval(coeffs,
+                                            (psF32) (row + input->row0), (psF32) (col + input->col0));
+            }
+        }
+    }
+
+    return(input);
+}
+
+
+/*****************************************************************************
+XXX: I added normal polynomials to this routine.  Let IfA know, put it in the
+psLib SDR.
+ *****************************************************************************/
+psImage* psImageEvalPolynomial(psImage* input,
+                               const psPolynomial2D* coeffs)
+{
+    PS_ASSERT_IMAGE_NON_NULL(input, NULL);
+    PS_ASSERT_IMAGE_NON_EMPTY(input, NULL);
+    if ((input->type.type != PS_TYPE_S8) &&
+            (input->type.type != PS_TYPE_U16) &&
+            (input->type.type != PS_TYPE_F32) &&
+            (input->type.type != PS_TYPE_F64)) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                "Unallowable image type.\n");
+    }
+    PS_ASSERT_POLY_NON_NULL(coeffs, NULL);
+
+    if (coeffs->type == PS_POLYNOMIAL_ORD) {
+        return(p_psImageEvalPolynomialOrd(input, coeffs));
+    } else if (coeffs->type == PS_POLYNOMIAL_CHEB) {
+        return(p_psImageEvalPolynomialCheb(input, coeffs));
+    } else {
+        psError(PS_ERR_UNKNOWN, false, "Incorrect Polynomial Type.\n");
+    }
+    return(NULL);
+}
+
+// count number of pixels with given mask value
+long psImageCountPixelMask (psImage *mask,
+                            psRegion region,
+                            psMaskType value)
+{
+    long Npixels = 0;
+    int x0 = 0;
+    int y0 = 0;
+    int x1 = 0;
+    int y1 = 0;
+    psElemType type;
+
+    // this is not a valid error: a psRegion with ranges outside the valid pixels
+    // should saturate on the valid pixels, not result in an error (per SDRS)
+    //    if (region.x1 > mask->numCols || region.y1 > mask->numRows) {
+    //        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+    //                "psRegion input is outside of image boundary\n");
+    //        return -1;
+    //    }
+    //    if (region.x0 <= 0 || region.x1 <= 0 || region.y0 <= 0 || region.y1 <= 0) {
+    //        region = psRegionForImage(mask, region);
+    //    }
+    // not a valid error: if region coordinates are out of order, they should be flipped
+    //    if (region.x0 > region.x1 || region.y0 > region.y1) {
+    //        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+    //               "Invalid region.  Lower boundary greater than upper boundary.\n");
+    //        return -1;
+    //    }
+
+    // rationalize the region
+
+    /*
+        if (mask == NULL) {
+            psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                    _("Can not operate on a NULL psImage."));
+            return -1;
+        }
+        region = psRegionForImage(mask, region);
+
+        if (region.x0 == region.x1 || region.y0 == region.y1) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    "psRegion input contains 0 pixels\n");
+            return -1;
+        }
+    */
+    PS_ASSERT_IMAGE_NON_NULL(mask, -1);
+    PS_ASSERT_INT_NONNEGATIVE(mask->col0, -1);
+    PS_ASSERT_INT_NONNEGATIVE(mask->row0, -1);
+    PS_ASSERT_INT_POSITIVE(mask->numCols, -1);
+    PS_ASSERT_INT_POSITIVE(mask->numRows, -1);
+
+    int col0 = (int)(roundf(region.x0));
+    int col1 = (int)(roundf(region.x1));
+    int row0 = (int)(roundf(region.y0));
+    int row1 = (int)(roundf(region.y1));
+    //If (0,0,0,0) specified, the whole image is to be used.
+    if (col0 == 0 && col1 == 0 && row0 == 0 && row1 == 0) {
+        col0 = mask->col0;
+        col1 = mask->col0 + mask->numCols;
+        row0 = mask->row0;
+        row1 = mask->row0 + mask->numRows;
+    }
+
+    //Make sure x0 of region is inside image.  If so, set col0 to corresponding index number.
+    if (col0 >= mask->col0 && col0 <= (mask->col0 + mask->numCols) ) {
+        col0 -= mask->col0;
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Specified psRegion parameter, x0=%f, is out of range [%d,%d].\n",
+                region.x0, mask->col0, mask->col0+mask->numCols);
+        return -1;
+    }
+    //Make sure y0 of region is inside image.  If so, set row0 to corresponding index number.
+    if (row0 >= mask->row0 && row0 <= (mask->row0 + mask->numRows) ) {
+        row0 -= mask->row0;
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Specified psRegion parameter, y0=%f, is out of range [%d,%d].\n",
+                region.y0, mask->row0, mask->row0+mask->numRows);
+        return -1;
+    }
+
+    //Make sure x1 of region is valid.  If negative, index from tail (if valid).
+    if (col1 < 0) {
+        col1 += mask->numCols;
+        if (col1 < 0) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Specified psRegion parameter, x1=%f=%d, is out of range [%d,%d].\n",
+                    region.x1, col1+mask->col0, mask->col0, mask->col0+mask->numCols);
+            return -1;
+        }
+    } else if (col1 >= mask->col0 && col1 <= (mask->col0 + mask->numCols) ) {
+        col1 -= mask->col0;
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Specified psRegion parameter, x1=%f=%d, is out of range [%d,%d].\n",
+                region.x1, col1, mask->col0, mask->col0+mask->numCols);
+        return -1;
+    }
+    //Make sure y1 of region is valid.  If negative, index from tail (if valid).
+    if (row1 < 0) {
+        row1 += mask->numRows;
+        if (row1 < 0) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Specified psRegion parameter, y1=%f=%d, is out of range [%d,%d].\n",
+                    region.y1, row1+mask->row0, mask->row0, mask->row0+mask->numRows);
+            return -1;
+        }
+    } else if (row1 >= mask->row0 && row1 <= (mask->row0 + mask->numRows) ) {
+        row1 -= mask->row0;
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Specified psRegion parameter, y1=%f=%d, is out of range [%d,%d].\n",
+                region.y1, row1, mask->row0, mask->row0+mask->numRows);
+        return -1;
+    }
+    //Now make sure that the region makes sense.
+    if (col0 > col1 || row0 > row1) {
+        if (col0 > col1) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Invalid psRegion specified.  x0=%f=%d is greater than x1=%f=%d.\n",
+                    region.x0, col0, region.x1, col1);
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Invalid psRegion specified.  y0=%f=%d is greater than y1=%f=%d.\n",
+                    region.y0, row0, region.y1, row1);
+        }
+        return -1;
+    }/* else if (col0 == col1 && row0 == row1) {
+                                                            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                                                                    "Invalid psRegion specified.  Region contains only 1 pixel.\n");
+                                                            return -1;
+                                                        }
+                                                    */
+    x0 = col0;
+    x1 = col1;
+    y0 = row0;
+    y1 = row1;
+
+    type = mask->type.type;
+    if (type != PS_TYPE_MASK) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                "psImage type does not match the specified psMaskType!\n");
+        return -1;
+    }
+
+    switch (type) {
+    case PS_TYPE_U8:
+    case PS_TYPE_U16:
+        for (long j = y0; j < y1; j++) {
+            for (long i = x0; i < x1; i++) {
+                if (mask->data.PS_TYPE_MASK_DATA[j][i] & value) {
+                    Npixels ++;
+                }
+            }
+        }
+        break;
+    case PS_TYPE_S8:
+    case PS_TYPE_S16:
+    case PS_TYPE_S32:
+    case PS_TYPE_S64:
+    case PS_TYPE_U32:
+    case PS_TYPE_U64:
+    case PS_TYPE_F32:
+    case PS_TYPE_F64:
+    default:
+        // XXX this should include the mask type (as a string)
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("Input psImage mask type is not a supported mask datatype"));
+
+        return -1;
+    }
+    return (Npixels);
+
+
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageStats.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageStats.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageStats.h	(revision 22158)
@@ -0,0 +1,103 @@
+/* @file psImageStats.h
+ *
+ * @brief Routines for calculating statistics on images.
+ *
+ * This file will hold the prototypes for procedures which calculate
+ * statistic on images, histograms on images, and fit/evaluate Chebyshev
+ * polynomials to images.
+ *
+ * @author GLG, MHPCC
+ *
+ * @version $Revision: 1.31 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-02-13 03:01:23 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_IMAGE_STATS_H
+#define PS_IMAGE_STATS_H
+
+/// @addtogroup ImageOps Image Operations
+/// @{
+
+#include "psType.h"
+#include "psVector.h"
+#include "psImage.h"
+#include "psStats.h"
+#include "psHistogram.h"
+#include "psPolynomial.h"
+#include "psRegion.h"
+
+/** This routine must determine the various statistics for the image.
+ *
+ *  Determine statistics for image (or subimage). The statistics to be
+ *  determined are specified by stats. The mask allows pixels to be excluded
+ *  if their corresponding mask pixel value matches the value of maskVal.
+ *  This function must be defined for the following types: psS8, psU16, psF32,
+ *  psF64.
+ *
+ *  @return bool   Successful operation?
+ */
+bool psImageStats(
+    psStats* stats,                    ///< defines statistics to be calculated
+    const psImage* in,                 ///< image (or subimage) to calculate stats
+    const psImage* mask,               ///< mask data for image (NULL ok)
+    psMaskType maskVal                 ///< mask value for mask
+);
+
+/** Construct a histogram from an image (or subimage).
+ *
+ *  The histogram to generate is specified by psHistogram hist (see section
+ *  4.3.2 in SDRS). This function must be defined for the following types:
+ *  psS8, psU16, psF32, psF64.
+ *
+ *  @return bool   Successful operation?
+ */
+bool psImageHistogram(
+    psHistogram* out,                  ///< input histogram description & target
+    const psImage* in,                 ///< Image data to be histogramed.
+    const psImage* mask,               ///< mask data for image (NULL ok)
+    psMaskType maskVal                 ///< mask Mask for mask
+);
+
+/** Fit a 2-D polynomial surface to an image.
+ *
+ *  The input structure coeffs contains the desired order and terms of
+ *  interest. This function must be defined for the following types: psS8,
+ *  psU16, psF32, psF64.
+ *
+ *  @return bool   Successful operation?
+ *
+ */
+bool psImageFitPolynomial(
+    psPolynomial2D* coeffs,            ///< coefficient structure carries in desired terms & target
+    const psImage* input               ///< input image
+);
+
+/** Evaluate a 2-D polynomial surface for the image pixels.
+ *
+ *  Given the input polynomial coefficients, set the image pixel values on the
+ *  basis of the polynomial function. This function must be defined for the
+ *  following types: psS8, psU16, psF32, psF64.
+ *
+ *  @return psImage*    the resulting image
+ */
+psImage* psImageEvalPolynomial(
+    psImage* input,                    ///< input image
+    const psPolynomial2D* coeffs       ///< coefficient structure carries in desired terms
+);
+
+/** Returns the number of pixels in the image region which satisfy any of the mask bits.
+ *
+ *  An error (eg, invalid image, invalid region) results in a return value of -1.
+ *  The vector must be U8.
+ *
+ *  @return long:       the number of pixels counted
+ */
+long psImageCountPixelMask(
+    psImage *mask,                     ///< input image to count
+    psRegion region,                   ///< input region of image
+    psMaskType value                   ///< the mask value to satisfy
+);
+
+/// @}
+#endif // #ifndef PS_IMAGE_STATS_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageStructManip.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageStructManip.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageStructManip.c	(revision 22158)
@@ -0,0 +1,382 @@
+/** @file  psImageStructManip.c
+ *
+ *  @brief Contains basic image structure manipulations, as specified in the
+ *         PSLIB SDRS sections "Image Structure Manipulation".
+ *
+ *  @ingroup Image
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-08 01:09:48 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <assert.h>
+
+#include "psMemory.h"
+#include "psError.h"
+#include "psAbort.h"
+
+#include "psImageStructManip.h"
+
+// col0,row0 are the starting pixel in the input image coordinate frame
+// col1,row1 are the ending pixel in the input image coordinate frame
+// note that these are relative to the input col0,row0
+// also note that col0,row0 may not be less than input->col0,row0
+static psImage* imageSubset(const char *file, // File name of caller
+                            unsigned int lineno, // Line number of caller
+                            const char *func, // Function name of caller
+                            psImage* out,
+                            psImage* image,
+                            psS32 col0,
+                            psS32 row0,
+                            psS32 col1,
+                            psS32 row1)
+{
+    psU32 elementSize;          // size of image element in bytes
+    psS32 inputColOffset;       // offset in **bytes** to first subset pixel in input row
+    psS32 inputRowOffset;       // offset in **rows*** to first input row
+
+    if (image == NULL || image->data.V == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not operate on a NULL psImage."));
+        return NULL;
+    }
+
+    if ( col0 < image->col0 || row0 < image->row0 ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified subset range, [%d:%d,%d:%d], is invalid or outside input psImage's boundaries, [%d:%d,%d:%d]."),
+                col0, col1-1, row0, row1-1, image->col0, image->col0 + image->numCols-1, image->row0,
+                image->row0 + image->numRows-1);
+        return NULL;
+    }
+
+    if (image->type.dimen != PS_DIMEN_IMAGE) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("The input psImage must have a PS_DIMEN_IMAGE dimension type."));
+        return NULL;
+    }
+
+    if (col1 < 1) {
+        col1 = image->col0 + image->numCols + col1;
+    }
+    if (row1 < 1) {
+        row1 = image->row0 + image->numRows + row1;
+    }
+
+    if (col1 <= col0 ||
+        row1 <= row0 ||
+        col0 >= image->col0 + image->numCols ||
+        row0 >= image->row0 + image->numRows ||
+        col1 > image->col0 + image->numCols ||
+        row1 > image->row0 + image->numRows ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified subset range, [%d:%d,%d:%d], is invalid or outside input psImage's boundaries, [%d:%d,%d:%d]."),
+                col0, col1-1, row0, row1-1,
+                image->col0, image->col0 + image->numCols-1, image->row0, image->row0 + image->numRows-1);
+        return NULL;
+    }
+
+    psS32 numRows = row1-row0;
+    psS32 numCols = col1-col0;
+
+    elementSize = PSELEMTYPE_SIZEOF(image->type.type);
+
+    // if this is a child, we need to start working with parent pixels
+    // the subset region (col0,row0 - col1,row1) is in the parent frame
+    if (image->parent != NULL) {
+        image = (psImage*)image->parent;
+    }
+
+    // increment the raw data buffer before freeing anything in the 'out'
+    psPtr rawData = psMemIncrRefCounter(image->p_rawDataBuffer);
+
+    if (out != NULL) {
+        // if a child, need to orphan (disassociate from parent) first
+        psImage *parent = (psImage *) out->parent;
+        if (parent != NULL) {
+            // break the back-pointer first so we don't loop
+            out->parent = NULL;
+
+            // drop my entry on my parent's array of children
+            psArrayRemoveDataNoFree (out->parent->children, out);
+
+            // drop my reference to my old parent
+            psFree (parent);
+        }
+
+        // we recycle out->data.V
+        psFree(out->p_rawDataBuffer); // free the previous data reference
+    } else {
+        out = p_psAlloc(file, lineno, func, sizeof(psImage));
+        out->data.V = NULL;
+    }
+
+    out->data.V = p_psRealloc(file, lineno, func, out->data.V,
+                              sizeof(psPtr)*numRows); // resize row pointer array
+    P_PSIMAGE_SET_TYPE(out, image->type);
+    P_PSIMAGE_SET_NUMCOLS(out, numCols);
+    P_PSIMAGE_SET_NUMROWS(out, numRows);
+    P_PSIMAGE_SET_COL0(out, col0);
+    P_PSIMAGE_SET_ROW0(out, row0);
+
+    out->parent = psMemIncrRefCounter(image); // track references to parents
+    out->children = NULL;
+    out->p_rawDataBuffer = rawData;
+
+    // set the new psImage's deallocator to the same as the input image
+    psMemSetDeallocator(out,psMemGetDeallocator(image));
+
+    inputRowOffset = (row0 - image->row0);
+    inputColOffset = (col0 - image->col0)*elementSize;
+    assert (inputRowOffset >= 0);
+    assert (inputColOffset >= 0);
+    for (psS32 row = 0; row < numRows; row++) {
+        out->data.V[row] = image->data.U8[row + inputRowOffset] + inputColOffset;
+    }
+
+    // add output image as a child of the input image.
+    image->children = p_psArrayAdd(file, lineno, func, image->children, 16, out);
+    psFree (out); // the image->children array is an array of views only
+
+    return (out);
+}
+
+psImage* p_psImageSubset(const char *file, unsigned int lineno, const char *func,
+                       psImage* image, psRegion region)
+{
+    return imageSubset(file, lineno, func, NULL, image, region.x0, region.y0, region.x1, region.y1);
+}
+
+psImage* psImageCopyView(psImage *output, psImage *input)
+{
+    psRegion region = {0, 0, 0, 0};
+    region = psRegionForImage (input, region);
+    psImage *result = imageSubset(__FILE__, __LINE__, __func__, output, input,
+                                  region.x0, region.y0, region.x1, region.y1);
+    return result;
+}
+
+psImage* p_psImageCopy(const char *file, unsigned int lineno, const char *func,
+                       psImage* output, const psImage* input, psElemType type)
+{
+    psElemType inDatatype;
+    psS32 elementSize;
+    psS32 elements;
+    psS32 numRows;
+    psS32 numCols;
+
+    if (input == NULL || input->data.V == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not operate on a NULL psImage."));
+        psFree(output);
+        return NULL;
+    }
+
+    if (input == output) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Specified input and output psImage can not reference the same psImage."));
+        psFree(output);
+        return NULL;
+    }
+
+    if (input->type.dimen != PS_DIMEN_IMAGE) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("The input psImage must have a PS_DIMEN_IMAGE dimension type."));
+        psFree(output);
+        return NULL;
+    }
+
+    inDatatype = input->type.type;
+    numRows = input->numRows;
+    numCols = input->numCols;
+    elements = numRows * numCols;
+    elementSize = PSELEMTYPE_SIZEOF(inDatatype);
+
+    output = p_psImageRecycle(file, lineno, func, output, numCols, numRows, type);
+    P_PSIMAGE_SET_COL0(output, input->col0);
+    P_PSIMAGE_SET_ROW0(output, input->row0);
+
+    // cover the trival case of copy of the same
+    // datatype.
+    if (type == inDatatype) {
+        for (psS32 row=0;row<numRows;row++) {
+            memcpy(output->data.V[row], input->data.V[row], elementSize * numCols);
+        }
+        return output;
+    }
+
+    #define PSIMAGE_ELEMENT_COPY(IN,INTYPE,OUT,OUTTYPE,ELEMENTS) { \
+        ps##INTYPE *in; \
+        ps##OUTTYPE *out; \
+        for(psS32 row=0;row<numRows;row++) { \
+            in = IN->data.INTYPE[row]; \
+            out = OUT->data.OUTTYPE[row]; \
+            for (psS32 col=0;col<numCols;col++) { \
+                *(out++) = *(in++); \
+            } \
+        } \
+    }
+
+    #define PSIMAGE_COPY_CASE(OUT,OUTTYPE) { \
+        switch (inDatatype) { \
+        case PS_TYPE_S8: \
+            PSIMAGE_ELEMENT_COPY(input,S8,OUT,OUTTYPE,elements); \
+            break; \
+        case PS_TYPE_S16: \
+            PSIMAGE_ELEMENT_COPY(input,S16,OUT,OUTTYPE,elements); \
+            break; \
+        case PS_TYPE_S32: \
+            PSIMAGE_ELEMENT_COPY(input,S32,OUT,OUTTYPE,elements); \
+            break; \
+        case PS_TYPE_S64: \
+            PSIMAGE_ELEMENT_COPY(input,S64,OUT,OUTTYPE,elements); \
+            break; \
+        case PS_TYPE_U8: \
+            PSIMAGE_ELEMENT_COPY(input,U8,OUT,OUTTYPE,elements); \
+            break; \
+        case PS_TYPE_U16: \
+            PSIMAGE_ELEMENT_COPY(input,U16,OUT,OUTTYPE,elements); \
+            break; \
+        case PS_TYPE_U32: \
+            PSIMAGE_ELEMENT_COPY(input,U32,OUT,OUTTYPE,elements); \
+            break; \
+        case PS_TYPE_U64: \
+            PSIMAGE_ELEMENT_COPY(input,U64,OUT,OUTTYPE,elements); \
+            break; \
+        case PS_TYPE_F32: \
+            PSIMAGE_ELEMENT_COPY(input,F32,OUT,OUTTYPE,elements); \
+            break; \
+        case PS_TYPE_F64: \
+            PSIMAGE_ELEMENT_COPY(input,F64,OUT,OUTTYPE,elements); \
+            break; \
+        default: \
+            break; \
+        } \
+    }
+
+    switch (type) {
+    case PS_TYPE_S8:
+        PSIMAGE_COPY_CASE(output, S8);
+        break;
+    case PS_TYPE_S16:
+        PSIMAGE_COPY_CASE(output, S16);
+        break;
+    case PS_TYPE_S32:
+        PSIMAGE_COPY_CASE(output, S32);
+        break;
+    case PS_TYPE_S64:
+        PSIMAGE_COPY_CASE(output, S64);
+        break;
+    case PS_TYPE_U8:
+        PSIMAGE_COPY_CASE(output, U8);
+        break;
+    case PS_TYPE_U16:
+        PSIMAGE_COPY_CASE(output, U16);
+        break;
+    case PS_TYPE_U32:
+        PSIMAGE_COPY_CASE(output, U32);
+        break;
+    case PS_TYPE_U64:
+        PSIMAGE_COPY_CASE(output, U64);
+        break;
+    case PS_TYPE_F32:
+        PSIMAGE_COPY_CASE(output, F32);
+        break;
+    case PS_TYPE_F64:
+        PSIMAGE_COPY_CASE(output, F64);
+        break;
+    default: {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    _("Specified psImage type, %s, is not supported."),
+                    typeStr);
+            psFree(output);
+
+            break;
+        }
+    }
+    return output;
+}
+
+psImage* psImageTrim(psImage* image,
+                     psRegion region)
+{
+    if (image == NULL || image->data.V == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not operate on a NULL psImage."));
+        return NULL;
+    }
+
+    if ((image->children != NULL) && (image->children->n > 0)) {
+        psAbort ("cannot trim an image with outstanding children");
+    }
+
+    if (image->parent != NULL) {
+        return imageSubset(__FILE__, __LINE__, __func__, image, (psImage*)image->parent,
+                           region.x0+image->col0, region.y0+image->row0,
+                           region.x1+image->col0, region.y1+image->row0);
+    }
+
+    int col0 = region.x0;
+    int row0 = region.y0;
+    int col1 = region.x1;
+    int row1 = region.y1;
+
+    if (col1 < 1) {
+        col1 += image->numCols;
+    }
+
+    if (row1 < 1) {
+        row1 += image->numRows;
+    }
+
+    if (    col0 < 0 ||
+            row0 < 0 ||
+            col1 > image->numCols ||
+            row1 > image->numRows ||
+            col0 >= col1 ||
+            row0 >= row1 ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified subset range, [%d:%d,%d:%d], is invalid or outside input psImage's boundaries, [0:%d,0:%d]."),
+                col0, col1-1, row0, row1-1,
+                image->numCols-1, image->numRows-1);
+        psFree(image);
+        return NULL;
+    }
+
+    psU32 elementSize = PSELEMTYPE_SIZEOF(image->type.type);
+    psU32 numCols = col1-col0;
+    psU32 numRows = row1-row0;
+    psU32 rowSize = elementSize*numCols;
+    psU32 colOffset = elementSize * col0;
+    psU8* imageData = image->p_rawDataBuffer;
+    for (psS32 row = row0; row < row1; row++) {
+        memmove(imageData,image->data.U8[row] + colOffset,rowSize);
+        imageData += rowSize;
+    }
+
+    P_PSIMAGE_SET_NUMCOLS(image, numCols);
+    P_PSIMAGE_SET_NUMROWS(image, numRows);
+
+    // XXX: should I really resize the buffers?
+    image->data.V = psRealloc(image->data.V,sizeof(psPtr)*numRows);
+    image->p_rawDataBuffer = psRealloc(image->p_rawDataBuffer,rowSize*numRows);
+
+    image->data.V[0] = image->p_rawDataBuffer;
+    for (psS32 r = 1; r < numRows; r++) {
+        image->data.U8[r] = image->data.U8[r-1] + rowSize;
+    }
+
+    return (image);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageStructManip.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageStructManip.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageStructManip.h	(revision 22158)
@@ -0,0 +1,108 @@
+/** @file  psImageStructManip.h
+*
+*  @brief basic image structure manipulation operations
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-11-08 01:10:15 $
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifndef PSIMAGE_STRUCT_MANIP_H
+#define PSIMAGE_STRUCT_MANIP_H
+
+/// @addtogroup ImageOps Image Operations
+/// @{
+
+#include "psImage.h"
+#include "psRegion.h"
+#include "psRegionForImage.h"
+
+/** Create a subimage of the specified area.
+ *
+ *  Define a subimage of the specified area of the given image. This function must raise an
+ *  error if the requested subset area lies outside of the parent image and return NULL. The
+ *  argument image is the parent image, region.x0, region.y0 specify the starting pixel of the
+ *  subraster, and region.x1,region.y1 specify the extent of the desired subraster. Note that
+ *  the row and column of this upper right-hand corner NOT included in the region. In the event
+ *  that x1 or y1 are negative, they shall be interpreted as being relative to the size of the
+ *  parent image in that dimension. The entire subraster must be contained within the raster of
+ *  the parent image. Note that the refCounter for the parent should be incremented.  This
+ *  function must be defined for the following types: psU8, psU16, psS8, psS16, psF32, psF64.
+ *
+ *  @return psImage* : Pointer to psImage.
+ *
+ */
+#ifdef DOXYGEN
+psImage* psImageSubset(
+    psImage* image,                    ///< Parent image.
+    psRegion region                    ///< region of subimage
+);
+#else // ifdef DOXYGEN
+psImage* p_psImageSubset(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psImage* image,                    ///< Parent image.
+    psRegion region                    ///< region of subimage
+) PS_ATTR_MALLOC;
+#define psImageSubset(image, region) \
+      p_psImageSubset(__FILE__, __LINE__, __func__, image, region)
+#endif // ifdef DOXYGEN
+
+/** Makes a copy of the image view on the parent:
+ *  if this is a child, returns a child pointing at the same pixels
+ *  if this is a parent, returns a child pointing at the full array
+ */
+psImage* psImageCopyView(psImage *output, psImage *input);
+
+/** Makes a copy of a psImage
+ *
+ * @return psImage* Copy of the input psImage.  This may not be equal to the
+ * output parameter
+ *
+ */
+#ifdef DOXYGEN
+psImage* psImageCopy(
+    psImage* output,                   ///< if not NULL, a psImage that could be recycled.
+    const psImage* input,              ///< the psImage to copy
+    psElemType type                    ///< the desired datatype of the returned copy
+);
+#else // ifdef DOXYGEN
+psImage* p_psImageCopy(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psImage* output,                   ///< if not NULL, a psImage that could be recycled.
+    const psImage* input,              ///< the psImage to copy
+    psElemType type                    ///< the desired datatype of the returned copy
+) PS_ATTR_MALLOC;
+#define psImageCopy(output, input, type) \
+      p_psImageCopy(__FILE__, __LINE__, __func__, output, input, type)
+#endif // ifdef DOXYGEN
+
+/** Trim an image
+ *
+ *  Trim the specified image in-place, which involves shuffling the pixels around in memory.
+ *  The pixels in the region [col0:col1,row0:row1] shall consist the output image.  The column
+ *  col1 and row row1 are NOT included in the range.  In the event that x1 or y1 are
+ *  non-positive, they shall be interpreted as being relative to the size of the parent image
+ *  in that dimension.
+ *
+ *  If the entire specified subimage is not contained within the parent image, an error results
+ *  and the return value will be NULL.
+ *
+ *  N.B. If the input psImage is a child of another psImage, no pixel data will be trimmed,
+ *  rather it equivalent to calling psImageSubset.  If the input psImage is, however, a parent
+ *  psImage, any children will be obliterated, i.e., freed from memory.
+ *
+ *  @return psImage*  trimmed image result
+ */
+psImage* psImageTrim(
+    psImage* image,                    ///< image to trim
+    psRegion region                    ///< trim region
+);
+
+/// @}
+#endif // #ifndef PSIMAGE_STRUCT_MANIP_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageUnbin.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageUnbin.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageUnbin.c	(revision 22158)
@@ -0,0 +1,343 @@
+/** @file  psImageUnbin.c
+ *
+ *  @brief Functions to perform unbinning (resampling) of images.
+ *
+ *  @ingroup Image
+ *
+ *  @author Eugene Magnier, IfA
+ *
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-09-20 23:55:50 $
+ *
+ *  Copyright 2007 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include "psError.h"
+#include "psAssert.h"
+#include "psRegion.h"
+#include "psImage.h"
+#include "psImageBinning.h"
+#include "psImageUnbin.h"
+
+// interpolate from model to background (~bresenham linear interpolation)
+// DX, DY are the binning factor
+// dx, dy is the distance is high-res pixels to the 0,0 corner of the first
+// binned pixel. 
+// XXX check that this is still consistent with psphotImageMedian...
+psImage *psImageUnbin(psImage *out, const psImage *in, const psImageBinning *binning)
+{
+    PS_ASSERT_IMAGE_NON_NULL(in, NULL);
+    PS_ASSERT_IMAGE_NON_NULL(out, NULL);
+
+    int DX = binning->nXbin;
+    int DY = binning->nYbin;
+    int dx = binning->nXskip;
+    int dy = binning->nYskip;
+
+    PS_ASSERT_INT_POSITIVE(DX, NULL);
+    PS_ASSERT_INT_POSITIVE(DY, NULL);
+    PS_ASSERT_INT_LESS_THAN_OR_EQUAL(dx, DX, NULL);
+    PS_ASSERT_INT_LESS_THAN_OR_EQUAL(dy, DY, NULL);
+
+    long nx = in->numCols;
+    long ny = in->numRows;
+    long Nx = out->numCols;
+    long Ny = out->numRows;
+
+    // XXX validate the binning structure vs the input and output images?
+
+    psF32 **vIn = in->data.F32;
+    psF32 **vOut = out->data.F32;
+
+    // loop over all input pixels excluding the last
+    for (int Iy = 0; Iy < ny-1; Iy ++) {
+        for (int Ix = 0; Ix < nx-1; Ix ++) {
+
+            float V00 = vIn[Iy+0][Ix+0];
+            float V01 = vIn[Iy+0][Ix+1];
+            float V10 = vIn[Iy+1][Ix+0];
+            float V11 = vIn[Iy+1][Ix+1];
+
+            // a single binned pixel quad
+            // (Xs,Ys) : (Xe,Ye) : binned pixel centers in unbinned coords
+            // corresponding to (Ix,Iy), (Ix+1,Iy+1)
+            int Xs = PS_MAX (0, PS_MIN (Nx, (Ix + 0.5)*DX - dx));
+            int Ys = PS_MAX (0, PS_MIN (Ny, (Iy + 0.5)*DY - dy));
+            int Xe = PS_MAX (0, PS_MIN (Nx, Xs + DX));
+            int Ye = PS_MAX (0, PS_MIN (Ny, Ys + DY));
+
+            for (int iy = Ys; (iy < Ye) && (iy < Ny); iy++) {
+                float Vxs = (V10 - V00)*(iy - Ys) / DY + V00;
+                float Vxe = (V11 - V01)*(iy - Ys) / DY + V01;
+                float dV = (Vxe - Vxs) / DX;
+                float V  = Vxs;
+                for (int ix = Xs; (ix < Xe) && (ix < Nx); ix++) {
+                    vOut[iy][ix] = V;
+                    //assert (fabs(V - psImageUnbinPixel(ix, iy, in, DX, DY, dx, dy)) < 1e-5*fabs(V));
+                    V += dV;
+                }
+            }
+        }
+    }
+
+    // side pixels
+    int Xs = PS_MAX (0, PS_MIN (Nx, ( 0 + 0.5)*DX - dx));
+    int Xe = PS_MAX (0, PS_MIN (Nx, (nx - 0.5)*DX - dx));
+    for (int Iy = 0; Iy < ny - 1; Iy++) {
+
+        int Ys = PS_MAX (0, PS_MIN (Ny, (Iy + 0.5)*DY - dy));
+        int Ye = PS_MAX (0, PS_MIN (Ny, Ys + DY));
+
+        // leading edge
+        float V0 = vIn[Iy+0][0];
+        float V1 = vIn[Iy+1][0];
+        float dV = (V1 - V0) / DY;
+        float V = V0;
+        for (int iy = Ys; (iy < Ye) && (iy < Ny); iy++) {
+            for (int ix = 0; ix < Xs; ix++) {
+                vOut[iy][ix] = V;
+            }
+            V += dV;
+        }
+
+        // trailing edge
+        V0 = vIn[Iy+0][nx-1];
+        V1 = vIn[Iy+1][nx-1];
+        dV = (V1 - V0) / DY;
+        V = V0;
+        for (int iy = Ys; (iy < Ye) && (iy < Ny); iy++) {
+            for (int ix = Xe; ix < Nx; ix++) {
+                vOut[iy][ix] = V;
+            }
+            V += dV;
+        }
+    }
+
+    // top and bottom pixels
+    int Ys = PS_MAX (0, PS_MIN (Ny, ( 0 + 0.5)*DY - dy));
+    int Ye = PS_MAX (0, PS_MIN (Ny, (ny - 0.5)*DY - dy));
+    for (int Ix = 0; Ix < nx - 1; Ix++) {
+
+        int Xs = PS_MAX (0, PS_MIN (Nx, (Ix + 0.5)*DX - dx));
+        int Xe = PS_MAX (0, PS_MIN (Nx, Xs + DX));
+
+        // top edge
+        float V0 = vIn[0][Ix+0];
+        float V1 = vIn[0][Ix+1];
+        float dV = (V1 - V0) / DX;
+        for (int iy = 0; iy < Ys; iy++) {
+            float V = V0;
+            for (int ix = Xs; (ix < Xe) && (ix < Nx); ix++) {
+                vOut[iy][ix] = V;
+                V += dV;
+            }
+        }
+
+        // bottom edge
+        V0 = vIn[ny-1][Ix+0];
+        V1 = vIn[ny-1][Ix+1];
+        dV = (V1 - V0) / DX;
+        for (int iy = Ye; iy < Ny; iy++) {
+            float V = V0;
+            for (int ix = Xs; (ix < Xe) && (ix < Nx); ix++) {
+                vOut[iy][ix] = V;
+                V += dV;
+            }
+        }
+    }
+    // return out;
+
+    // the four corners
+    {
+        float V;
+	// center of last pixel 
+	int Xs = PS_MAX (0, PS_MIN (Nx, ( 0 + 0.5)*DX - dx));
+	int Xe = PS_MAX (0, PS_MIN (Nx, (nx - 0.5)*DX - dx));
+	int Ys = PS_MAX (0, PS_MIN (Ny, ( 0 + 0.5)*DY - dy));
+	int Ye = PS_MAX (0, PS_MIN (Ny, (ny - 0.5)*DY - dy));
+
+        // 0,0
+        V = vIn[0][0];
+        for (int iy = 0; iy < Ys; iy++)
+        {
+            for (int ix = 0; ix < Xs; ix++) {
+                vOut[iy][ix] = V;
+            }
+        }
+        // Nx,0
+        V = vIn[0][nx-1];
+        for (int iy = 0; iy < Ys; iy++)
+        {
+            for (int ix = Xe; ix < Nx; ix++) {
+                vOut[iy][ix] = V;
+            }
+        }
+        // 0,Ny
+        V = vIn[ny-1][0];
+        for (int iy = Ye; iy < Ny; iy++)
+        {
+            for (int ix = 0; ix < Xs; ix++) {
+                vOut[iy][ix] = V;
+            }
+        }
+        // Nx,Ny
+        V = vIn[ny-1][nx-1];
+        for (int iy = Ye; iy < Ny; iy++)
+        {
+            for (int ix = Xe; ix < Nx; ix++) {
+                vOut[iy][ix] = V;
+            }
+        }
+    }
+
+    return out;
+}
+
+/************************************************************************************************************/
+/*
+ * Get the value of a single unbinned pixel from the binned representation
+ *
+ * N.b. This code only works for the central part of the image; the edge
+ * cases should be added
+
+ * XXXX this is bilinear interpolation, but written sub-optimally
+ * XXXX this function should be taking float input coordinates!!!
+ */
+double psImageUnbinPixel(const int ix, const int iy, // desired Unbinned point (parent coords)
+                         const psImage *in, // binned image
+                         const psImageBinning *binning)   //!< Overhang
+{
+
+    int DX = binning->nXbin;
+    int DY = binning->nYbin;
+    int dx = binning->nXskip;
+    int dy = binning->nYskip;
+
+    PS_ASSERT_IMAGE_NON_NULL(in, NAN);
+    assert (in->type.type == PS_TYPE_F32);
+
+    PS_ASSERT_INT_POSITIVE(DX, NAN);
+    PS_ASSERT_INT_POSITIVE(DY, NAN);
+    PS_ASSERT_INT_LESS_THAN_OR_EQUAL(dx, DX, NAN);
+    PS_ASSERT_INT_LESS_THAN_OR_EQUAL(dy, DY, NAN);
+    /*
+     * Find which binned pixel we're in
+     */
+
+    const int Xs = (ix - dx)/DX; // index of binned pixel
+    const int Ys = (iy - dy)/DY;
+    if (Xs < 0 || Xs >= in->numCols || Ys < 0 || Ys >= in->numRows) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Point (%d,%d) lies outside binned image", ix, iy);
+        return NAN;
+    }
+    const int Xe = PS_MIN (Xs + 1, in->numCols - 1);
+    const int Ye = PS_MIN (Ys + 1, in->numRows - 1);
+
+    double V00 = in->data.F32[Ys][Xs];
+    double V01 = in->data.F32[Ys][Xe];
+    double V10 = in->data.F32[Ye][Xs];
+    double V11 = in->data.F32[Ye][Xe];
+
+    const int xs = Xs*DX - dx; // centre of bottom left corner of binned pixel
+    const int ys = Ys*DY - dy; // (i.e. [Xs][Ys]) in unbinned coordinates
+
+    const double Vxs = (V10 - V00)*(iy - ys)/DY + V00;
+    const double Vxe = (V11 - V01)*(iy - ys)/DY + V01;
+
+    return Vxs + (Vxe - Vxs)*(ix - xs)/DX; // value at [iy][ix]
+}
+
+double psImageUnbinPixel_V2(const double xFine, const double yFine, // desired Unbinned point (parent coords)
+			    const psImage *in, // binned image
+			    const psImageBinning *binning)   //!< Overhang
+{
+    PS_ASSERT_IMAGE_NON_NULL(in, NAN);
+    assert (in->type.type == PS_TYPE_F32);
+
+    const float xRuff = psImageBinningGetRuffX (binning, xFine);
+    const float yRuff = psImageBinningGetRuffY (binning, yFine);
+
+    const double value = psImageInterpolatePixelBilinear (xRuff, yRuff, in);
+
+    return value;
+}
+
+// fast & simple API to interpolate to a subpixel position using bilinear interpolation
+// x,y in parent image coordinates (pixel centers at 0.5, 0.5)
+double psImageInterpolatePixelBilinear (const double xIn, const double yIn, const psImage *in) {
+
+    PS_ASSERT_PTR_NON_NULL(in, PS_ERR_BAD_PARAMETER_VALUE);
+    assert (in->type.type == PS_TYPE_F32);
+
+    const double x = xIn - in->col0;
+    const double y = yIn - in->row0;
+
+    // allow extrapolation to edge of valid pixels, but not beyond
+    if ((x < 0) || (x >= in->numCols) || (y < 0) || (y >= in->numRows)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Point (%f,%f) lies outside binned image", x, y);
+        return NAN;
+    }
+
+    // limiting cases: Nx == 1 and/or Ny == 1
+
+    // if we have a single pixel, there is no spatial information
+    if ((in->numCols == 1) && (in->numRows == 1)) {
+	const double value = in->data.F32[0][0];
+	return value;
+    }
+
+    // handle edge cases with extrapolation
+
+    const int ix = x - 0.5; // index of reference pixel
+    const int iy = y - 0.5; // index of reference pixel
+
+    // do numCols,Rows first so we are never < 0
+    const int Xs = PS_MAX (PS_MIN (ix, in->numCols - 2), 0);
+    const int Ys = PS_MAX (PS_MIN (iy, in->numRows - 2), 0);
+
+    const int Xe = Xs + 1;
+    const int Ye = Ys + 1;
+
+    // dx,dy range from 0.0 to 1.0 for interpolated pixels, and -0.5 to 1.5 for extrapolation
+    const double dx = x - 0.5 - Xs;
+    const double dy = y - 0.5 - Ys;
+
+    const double rx = 1.0 - dx;
+    const double ry = 1.0 - dy;
+
+    // if Nx == 1, we have no x-dir spatial information
+    if (in->numCols == 1) {
+	double V0 = in->data.F32[Ys][Xs];
+	double V1 = in->data.F32[Ye][Xs];
+
+	const double value = V0*ry + V1*dy;
+	return value;
+    }	
+
+    // if Ny == 1, we have no y-dir spatial information
+    if (in->numRows == 1) {
+	double V0 = in->data.F32[Ys][Xs];
+	double V1 = in->data.F32[Ys][Xe];
+
+	const double value = V0*rx + V1*dx;
+	return value;
+    }	
+
+    // Vxy 
+    double V00 = in->data.F32[Ys][Xs];
+    double V10 = in->data.F32[Ys][Xe];
+    double V01 = in->data.F32[Ye][Xs];
+    double V11 = in->data.F32[Ye][Xe];
+
+    // bilinear interpolation
+    const double value = V00*rx*ry + V10*dx*ry + V01*rx*dy + V11*dx*dy;
+
+    return value;
+}
+
+    
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageUnbin.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageUnbin.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/imageops/psImageUnbin.h	(revision 22158)
@@ -0,0 +1,38 @@
+/** @file  psImageUnbin.h
+ *
+ *  @brief Functions to unbin images
+ *
+ *  @author EAM, IfA
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  $Date: 2007-09-20 23:55:52 $
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_IMAGE_UNBIN_H
+#define PS_IMAGE_UNBIN_H
+
+/// @addtogroup ImageOps Image Operations
+/// @{
+
+// This needs to be considered more carefully
+psImage *psImageUnbin (psImage *out,    //!< Output image
+                       const psImage *in, //!< Input image
+                       const psImageBinning *binning ///< binning definition
+    );
+
+double psImageUnbinPixel(const int ix, const int iy, //!< desired Unbinned point
+                         const psImage *in, //!< binned image
+			 const psImageBinning *binning ///< binning definition
+                        );
+
+double psImageUnbinPixel_V2(const double xFine, const double yFine, // desired Unbinned point (parent coords)
+			    const psImage *in, // binned image
+			    const psImageBinning *binning   //!< Overhang
+    );
+
+double psImageInterpolatePixelBilinear (const double xIn, const double yIn, const psImage *in);
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/jpeg/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/jpeg/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/jpeg/.cvsignore	(revision 22158)
@@ -0,0 +1,10 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
+*.loT
+*.bb
+*.bbg
+*.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/jpeg/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/jpeg/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/jpeg/Makefile.am	(revision 22158)
@@ -0,0 +1,12 @@
+#Makefile for image jpeg functions of psLib
+#
+noinst_LTLIBRARIES = libpslibjpeg.la
+
+libpslibjpeg_la_CPPFLAGS = $(SRCINC) $(PSLIB_CFLAGS) $(JPEG_CFLAGS)
+libpslibjpeg_la_SOURCES = \
+	psImageJpeg.c
+
+pkginclude_HEADERS = \
+	psImageJpeg.h
+
+CLEANFILES = *~ *.bb *.bbg *.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/jpeg/psImageJpeg.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/jpeg/psImageJpeg.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/jpeg/psImageJpeg.c	(revision 22158)
@@ -0,0 +1,220 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <strings.h>  // for strcasecmp
+#include <string.h>
+
+#include "psMemory.h"
+#include "psImage.h"
+#include "psVector.h"
+#include "psError.h"
+#include "psAssert.h"
+#include "psImageJpeg.h"
+
+#ifdef HAVE_STDLIB_H
+// jpeglib.h includes jconfig.h which is full of autoconf generated HAVE_*
+// defines. This is a hack to work around CPP redefinition errors.  Arrrrrgh!!!
+// -JH
+# undef HAVE_STDLIB_H
+# include <jpeglib.h>
+#endif // ifdef HAVE_STDLIB_H
+
+static void imageJpegColormapFree(psImageJpegColormap *map)
+{
+
+    if (!map) {
+        return;
+    }
+
+    psFree(map->red);
+    psFree(map->green);
+    psFree(map->blue);
+    return;
+}
+
+psImageJpegColormap *psImageJpegColormapAlloc ()
+{
+    psImageJpegColormap *map = psAlloc(sizeof(psImageJpegColormap));
+    psMemSetDeallocator(map, (psFreeFunc)imageJpegColormapFree);
+
+    map->red   = psVectorAlloc(256, PS_TYPE_U8);
+    map->blue  = psVectorAlloc(256, PS_TYPE_U8);
+    map->green = psVectorAlloc(256, PS_TYPE_U8);
+
+    return map;
+}
+
+psImageJpegColormap *psImageJpegColormapSet(psImageJpegColormap *map, const char *name)
+{
+
+    if (!map) {
+        map = psImageJpegColormapAlloc ();
+    }
+
+    /* grayscale */
+    if ((!strcasecmp (name, "grayscale")) || (!strcasecmp (name, "greyscale"))) {
+        for (int i = 0; i < map->red->n; i++) {
+            map->red->data.U8[i]   = PS_JPEG_RANGELIM(i);
+            map->green->data.U8[i] = PS_JPEG_RANGELIM(i);
+            map->blue->data.U8[i]  = PS_JPEG_RANGELIM(i);
+        }
+        return map;
+    }
+
+    /* -grayscale */
+    if ((!strcasecmp (name, "-grayscale")) || (!strcasecmp (name, "-greyscale"))) {
+        for (int i = 0; i < map->red->n; i++) {
+            map->red->data.U8[i]   = PS_JPEG_RANGELIM(256 - i);
+            map->green->data.U8[i] = PS_JPEG_RANGELIM(256 - i);
+            map->blue->data.U8[i]  = PS_JPEG_RANGELIM(256 - i);
+        }
+        return map;
+    }
+
+    /* rainbow */
+    if (!strcasecmp (name, "rainbow")) {
+        int I1 = 0.25*map->red->n;
+        int I2 = 0.50*map->red->n;
+        int I3 = 0.75*map->red->n;
+        for (int i = 0; i < I1; i++) {
+            map->red->data.U8[i]   = 0;
+            map->green->data.U8[i] = 0;
+            map->blue->data.U8[i]  = PS_JPEG_RANGELIM(4*i);
+        }
+        for (int i = I1; i < I2; i++) {
+            map->red->data.U8[i]   = PS_JPEG_RANGELIM(4*(i - I1));
+            map->green->data.U8[i] = 0;
+            map->blue->data.U8[i]  = PS_JPEG_RANGELIM(4*(I2 - i));
+        }
+        for (int i = I2; i < I3; i++) {
+            map->red->data.U8[i]   = 255;
+            map->green->data.U8[i] = 4*(i - I2);
+            map->blue->data.U8[i]  = 0;
+        }
+        for (int i = I3; i < map->red->n; i++) {
+            map->red->data.U8[i]   = 255;
+            map->green->data.U8[i] = 255;
+            map->blue->data.U8[i]  = PS_JPEG_RANGELIM(4*(i - I3));
+        }
+        return map;
+    }
+
+    /* heat */
+    if (!strcasecmp (name, "heat")) {
+        int I1 = 0.25*map->red->n;
+        int I2 = 0.50*map->red->n;
+        int I3 = 0.75*map->red->n;
+        for (int i = 0; i < I1; i++) {
+            map->red->data.U8[i]   = PS_JPEG_RANGELIM(2*i);
+            map->green->data.U8[i] = 0;
+            map->blue->data.U8[i]  = 0;
+        }
+        for (int i = I1; i < I2; i++) {
+            map->red->data.U8[i]   = PS_JPEG_RANGELIM(2*i);
+            map->green->data.U8[i] = PS_JPEG_RANGELIM(2*(i - I1));
+            map->blue->data.U8[i]  = 0;
+        }
+        for (int i = I2; i < I3; i++) {
+            map->red->data.U8[i]   = 255;
+            map->green->data.U8[i] = PS_JPEG_RANGELIM(2*(i - I1));
+            map->blue->data.U8[i]  = PS_JPEG_RANGELIM(2*(i - I2));
+        }
+        for (int i = I3; i < map->red->n; i++) {
+            map->red->data.U8[i]   = 255;
+            map->green->data.U8[i] = 255;
+            map->blue->data.U8[i]  = PS_JPEG_RANGELIM(2*(i - I2));
+        }
+        return map;
+    }
+
+    // invalid colormap: warn user
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Invalid colormap name: %s --- using greyscale\n", name);
+    return psImageJpegColormapSet (map, "greyscale");
+}
+
+bool psImageJpeg(const psImageJpegColormap *map, const psImage *image, const char *filename,
+                 float min, float max)
+{
+    PS_ASSERT_PTR_NON_NULL(map, false);
+    PS_ASSERT_IMAGE_NON_NULL(image, false);
+    PS_ASSERT_VECTOR_NON_NULL(map->red, false);
+    PS_ASSERT_VECTOR_NON_NULL(map->green, false);
+    PS_ASSERT_VECTOR_NON_NULL(map->blue, false);
+    PS_ASSERT_PTR_NON_NULL(filename, false);
+    PS_ASSERT_INT_POSITIVE(strlen(filename), false);
+    PS_ASSERT_FLOAT_REAL(min, false);
+    PS_ASSERT_FLOAT_REAL(max, false);
+
+    float zero, scale;
+    struct jpeg_compress_struct cinfo;
+    struct jpeg_error_mgr jerr;
+
+    long pixel;
+    JSAMPLE *jpegLine;   // Points to data for current line
+    JSAMPROW jpegLineList[1];  // pointer to JSAMPLE row[s]
+    JSAMPLE *outPix;
+
+    /* JPEG init calls */
+    cinfo.err = jpeg_std_error (&jerr);
+    jpeg_create_compress (&cinfo);
+
+    /* open file, prep for jpeg */
+    FILE *f = fopen(filename, "w");
+    if (!f) {
+        psError(PS_ERR_IO, true, "failed to open %s for output\n", filename);
+        return false;
+    }
+    jpeg_stdio_dest(&cinfo, f);
+
+    /* set up color jpeg buffers */
+    int quality = 75;
+    cinfo.image_width = image->numCols; // image width and height, in pixels
+    cinfo.image_height = image->numRows;
+    cinfo.input_components = 3;
+    cinfo.in_color_space = JCS_RGB;
+    jpeg_set_defaults (&cinfo);
+    jpeg_set_quality (&cinfo, quality, true); // limit to baseline-JPEG values
+    jpeg_start_compress (&cinfo, true);
+
+    jpegLine = psAlloc (3*image->numCols*sizeof(JSAMPLE));
+    jpegLineList[0] = jpegLine;
+
+    psU8 *Rpix = map->red->data.U8;
+    psU8 *Gpix = map->green->data.U8;
+    psU8 *Bpix = map->blue->data.U8;
+
+    if (max == min) {
+        zero = min - 0.1;
+        scale = 256.0/0.2;
+    } else {
+        zero = min;
+        scale = 256.0/(max - min);
+    }
+
+    for (int j = 0; j < image->numRows; j++) {
+        psF32 *row = image->data.F32[j];
+
+        outPix = jpegLine;
+        for (int i = 0; i < image->numCols; i++, outPix += 3) {
+            if (isfinite(row[i])) {
+                pixel = PS_JPEG_SCALEVALUE(row[i],zero,scale);
+            } else {
+                pixel = 0;
+            }
+            outPix[0] = Rpix[pixel];
+            outPix[1] = Gpix[pixel];
+            outPix[2] = Bpix[pixel];
+        }
+        jpeg_write_scanlines(&cinfo, jpegLineList, 1);
+    }
+
+    jpeg_finish_compress(&cinfo);
+    fclose(f);
+    jpeg_destroy_compress(&cinfo);
+
+    psFree(jpegLine);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/jpeg/psImageJpeg.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/jpeg/psImageJpeg.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/jpeg/psImageJpeg.h	(revision 22158)
@@ -0,0 +1,46 @@
+/* @file  psImageJpeg.h
+ * @brief functions to generate JPEG images from psImage
+ * 
+ * @author EAM
+ * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-08-09 01:40:07 $
+ */
+
+#ifndef PS_IMAGE_JPEG_H
+#define PS_IMAGE_JPEG_H
+
+/// @addtogroup FileIO Input/Output
+/// @{
+
+#include "psImage.h"
+
+typedef struct
+{
+    psVector *red;                      // Red colormap
+    psVector *green;                    // Green colormap
+    psVector *blue;                     // Blue colormap
+}
+psImageJpegColormap;
+
+#define PS_JPEG_RANGELIM(A)(PS_MAX(0,PS_MIN(255,(A))))
+
+#define PS_JPEG_SCALEVALUE(VALUE,ZERO,SCALE)(PS_MAX(0,PS_MIN(255,(SCALE*(VALUE-ZERO)))))
+
+// allocate a colormap (does not define the map values)
+psImageJpegColormap *psImageJpegColormapAlloc() PS_ATTR_MALLOC;
+
+// set the colormap values using the supplied name
+psImageJpegColormap *psImageJpegColormapSet(psImageJpegColormap *map, // Colormap to set
+        const char *name // Name of colormap
+                                           );
+
+// write out a JPEG file using the supplied image and colormap
+// output goes to the specified filename
+bool psImageJpeg(const psImageJpegColormap *map, // Color map
+                 const psImage *image,  // Image to write
+                 const char *filename,  // Filename of JPEG
+                 float min, float max   // Minimum and maximum values
+                );
+
+/// @}
+#endif /* PS_IMAGE_JPEG_H */
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/mainpage.dox
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/mainpage.dox	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/mainpage.dox	(revision 22158)
@@ -0,0 +1,197 @@
+/** @file mainpage.dox
+ *  @brief Main page for the Doxygen documentation
+ *
+ *  @author Robert Daniel DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-12-06 18:46:08 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/** @mainpage psLib Image Processing Library
+
+@section intro Introduction
+
+This library contains the Pan-STARRS Image Processing Pipeline (IPP) common library,
+psLib. The intended use is to provide a set of basic software functions in which
+can be used throughout the Pan-STARRS project to simplify programming tasks. Among
+the benefits are:
+ - Reuse of code
+ - Simplification of testing
+ - Streamlining of code
+ - Isolation of functionality that may be subject to change
+
+The capabilities provided by psLib are grouped into the following areas which are
+also reflected in the file system directory structure:
+ - System Utilities
+ - Data Collections
+ - Image Operations
+ - Data Manipulation
+ - Astronomy
+
+The capabilities provided by psModuke are grouped into the following areas which are
+also reflected in the file system directory structure:
+ - Configuration
+ - Astrometry, Focal Plane
+ - Photometry
+ - Basic Image Detrending
+ - Object Detection and Classification
+ - Image Combination
+ - Image Subtraction
+
+This list is sorted in hierarchical order: The later entries depend on the functions and
+data types of the earlier entries.
+
+The installed code for psLib consists of header files and binary libraries in
+the form of static and/or shared library, depending on the configuration options.
+To assist in using the library, a script "pslib-config" is supplied that
+provides the compiler and linker options.
+
+
+@section extinstall 3rd Party Libraries
+
+Before building psLib from source, several 3rd party software libraries must
+be installed.  These include:
+ - GNU Scientific Library (GSL)
+     - Available at http://www.gnu.org/software/gsl
+     - Compatibility tested with version 1.4
+ - Fastest Fourier Transform in the West (FFTW), version 3, with single-precison float support
+     - Available at http://www.fftw.org
+     - Compatibility tested with version is 3.0.1
+     - The '--enable-float' option is required in the configure step to enable single-precision float support.  Use 'configure --help' for more information of the configuration options for this library.
+ - C Flexible Image Transport System Input output (CFITSIO), version 2.480 or later
+     - Available at http://heasarc.gsfc.nasa.gov/docs/software/fitsio
+     - Compatibility tested with version 2.490, requires at least 2.480
+ - Gnome XML C parser and toolkit (libxml2)
+     - Available at http://www.xmlsoft.org
+     - Compatibility tested with version 2.6.12 and 2.6.16
+
+Though not required to build the base library, several 3rd party software
+libraries are needed for particular functionality.
+ - Doxygen Documentation System
+     - Required for creation of documentation
+     - Available at http://www.doxygen.org
+     - Compatibility tested with version 1.3.2 and 1.3.8
+     - The optional companion package, GraphViz (a.k.a., the 'dot' command), is recommended to enable header-file dependency diagrams
+ - MySQL
+     - Required for database functionality.  If not desired, the '--disable-mysql' configure option should be used.
+     - Available at http://dev.mysql.com
+     - Compatibility tested with version 4.1.10a, requires at least 4.1.2
+     - A server running locally is required for tests.
+ - Autoconf/Automake
+     - Required only if making from CVS
+     - Available at http://www.gnu.org/software/autoconf and http://www.gnu.org/software/automake
+     - Compatibility tested with version 2.5.9 (autoconf) and 1.9.2 (automake)
+
+We recommend using the particular versions listed as compatibility tested, as
+that is the only versions tested to work well with psLib. Though it is quite 
+possible that later versions of the libraries listed will also work as well, 
+care must be taken when upgrading these libraries to verify that its
+functionality is compatible with the tested version.
+
+
+@section obtain How to Obtain the Source
+
+Tested versions of psLib are put into a tar file and can be downloaded from:
+
+https://mhpcc.pan-starrs.org/code/releases
+
+If one has a login account on mhpcc.pan-starrs.org, direct CVS access is also
+possible.  Example of the commands required for direct CVS retrieval are
+as follows:
+<pre>
+$ cvs -d:ext:USERNAME@mhpcc.pan-starrs.org:/data/panstarrs/cvsroot co -r RELEASEBRANCH psLib
+</pre>
+where:
+  - USERNAME is your login name on the server
+  - RELEASEBRANCH is the desired release branch, e.g. rel7.
+
+
+@section build How to Build and Test
+
+The source uses autoconf/automake to build control the build process.  If, 
+and only if, the source came from CVS, the configuration script will have
+to be made first via:
+<pre>
+$ cd psLib
+$ ./autogen.sh
+</pre>
+<i>This creates the required configure script and Makefile templates.</i>
+
+The recommended steps to build the library are:
+<pre>
+$ cd psLib
+$ ./configure
+$ make
+$ make check
+$ make install
+</pre>
+<i>This builds, tests, and installs the library.</i>
+
+The configure step allows users to specify specific locations for the third
+party libraries (see "3rd Party Libraries" for a list), disabling of select
+functionality (e.g., database and perl module), installation location, etc.
+An enumeration of the options for configure, and the default values, can be
+obtained via "./configure --help".
+
+Though 'make check' compiles and runs the test suite, one can also use custom
+scripts to run all the tests and just a particular test.  To run the unit test
+suite, do the following:
+<pre>
+$ cd psLib/test
+$ ./FullUnitTest
+</pre>
+
+This has the advantage over 'make check' in that it does not stop when a test
+fails and it collects some very basic statistics on the results.  To run a
+particular test, do the following:
+<pre>
+$ runTest testfilename
+</pre>
+
+@section install How to Install
+
+To install the library using the prefix given in the configure step, execute in
+the top build directory:
+<pre>
+$ make install
+</pre>
+
+
+@section usage Building and Linking your code to the psLib library
+
+To assist the use of the library with your own code, a configuration tool is part
+of the psLib library package.  This tool, pslib-config, is installed in the BIN
+directory, according to the options given to the configure script.
+
+The required CFLAG options for the compiler stage of code that uses psLib can be
+obtained via 'pslib-config --cflags'.  This outputs the cc options that supplies
+include path(s) required to find the psLib headers.
+
+The required linking options, can be obtained via 'pslib-config --libs'.  This
+outputs the ld options that supplies the library paths and files required to
+link to the pslib library.
+
+Note: pslib-config usage above refers to the install locations of the library.  
+To link to the library directly in the build area, you need to use
+'pslib-config --build-cflags' and 'pslib-config --build-libs' instead.  These
+options will modify the output to point to the non-installed (build) locations
+of the include files and libraries. (this feature is experimental)
+
+@section doc How to Create Code Documentation
+
+Both HTML and man page documentation may be generated from the inline
+documentation embedded in the code using the following commands:
+<pre>
+$ cd psLib
+$ make docs
+</pre>
+<i>This places documentation in PREFIX/docs/psLib, where PREFIX is set using
+the configure script.</i>
+
+Also, a prebuilt set of code documentation for releases and can be found at:
+
+https://mhpcc.pan-starrs.org/docs/
+
+*/
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/.cvsignore	(revision 22158)
@@ -0,0 +1,10 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
+*.loT
+*.bb
+*.bbg
+*.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/Makefile.am	(revision 22158)
@@ -0,0 +1,64 @@
+#Makefile for math functions of psLib
+#
+noinst_LTLIBRARIES = libpslibmath.la
+
+libpslibmath_la_CPPFLAGS = $(SRCINC) $(PSLIB_CFLAGS) $(GSL_CFLAGS)
+libpslibmath_la_SOURCES = \
+	psUnaryOp.c \
+	psBinaryOp.c \
+	psClip.c \
+	psCompare.c \
+	psEllipse.c \
+	psMathUtils.c \
+	psMatrix.c \
+	psMD5.c \
+	psMinimizeLMM.c \
+	psMinimizePowell.c \
+	psMinimizePolyFit.c \
+	psPolynomial.c \
+	psPolynomialMetadata.c \
+	psPolynomialUtils.c \
+	psPolynomialMD.c \
+	psRandom.c \
+	psRegion.c \
+	psRegionForImage.c \
+	psSparse.c \
+	psSpline.c \
+	psStats.c \
+	psHistogram.c \
+	psVectorSmooth.c \
+	md5.c
+
+EXTRA_DIST = math.i
+
+pkginclude_HEADERS = \
+	psUnaryOp.h \
+	psBinaryOp.h \
+	psClip.h \
+	psCompare.h \
+	psConstants.h \
+	psEllipse.h \
+	psMathUtils.h \
+	psMatrix.h \
+	psMD5.h \
+	psMinimizeLMM.h \
+	psMinimizePowell.h \
+	psMinimizePolyFit.h \
+	psPolynomial.h \
+	psPolynomialMetadata.h \
+	psPolynomialUtils.h \
+	psPolynomialMD.h \
+	psRandom.h \
+	psRegion.h \
+	psRegionForImage.h \
+	psSort.h \
+	psSparse.h \
+	psSpline.h \
+	psStats.h \
+	psHistogram.h \
+	psVectorSmooth.h
+
+noinst_HEADERS = \
+	md5.h
+
+CLEANFILES = *~ *.bb *.bbg *.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/math.i
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/math.i	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/math.i	(revision 22158)
@@ -0,0 +1,12 @@
+/* math headers */
+
+%include "psBinaryOp.h"
+%include "psCompare.h"
+%include "psConstants.h"
+%include "psMatrix.h"
+%include "psMinimize.h"
+%include "psPolynomial.h"
+%include "psSpline.h"
+%include "psRandom.h"
+%include "psStats.h"
+%include "psUnaryOp.h"
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/md5.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/md5.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/md5.c	(revision 22158)
@@ -0,0 +1,386 @@
+/*
+  Copyright (C) 1999, 2000, 2002 Aladdin Enterprises.  All rights reserved.
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  L. Peter Deutsch
+  ghost@aladdin.com
+
+ */
+/* $Id: md5.c,v 1.1 2007-03-20 01:13:54 price Exp $ */
+/*
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321, whose
+  text is available at
+        http://www.ietf.org/rfc/rfc1321.txt
+  The code is derived from the text of the RFC, including the test suite
+  (section A.5) but excluding the rest of Appendix A.  It does not include
+  any code or documentation that is identified in the RFC as being
+  copyrighted.
+
+  The original and principal author of md5.c is L. Peter Deutsch
+  <ghost@aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+
+  2007-03-19 pap Added support for autoconf; incorporating into psLib.
+  2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
+        either statically or dynamically; added missing #include <string.h>
+        in library.
+  2002-03-11 lpd Corrected argument list for main(), and added int return
+        type, in test program and T value program.
+  2002-02-21 lpd Added missing #include <stdio.h> in test program.
+  2000-07-03 lpd Patched to eliminate warnings about "constant is
+        unsigned in ANSI C, signed in traditional"; made test program
+        self-checking.
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+  1999-05-03 lpd Original version.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "md5.h"
+#include <string.h>
+
+#undef BYTE_ORDER       /* 1 = big-endian, -1 = little-endian, 0 = unknown */
+#ifdef WORDS_BIGENDIAN                  // Comes from autoconf
+#  define BYTE_ORDER (WORDS_BIGENDIAN ? 1 : -1)
+#else
+#  define BYTE_ORDER 0
+#endif
+
+#define T_MASK ((md5_word_t)~0)
+#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
+#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
+#define T3    0x242070db
+#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
+#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
+#define T6    0x4787c62a
+#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
+#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
+#define T9    0x698098d8
+#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
+#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
+#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
+#define T13    0x6b901122
+#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
+#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
+#define T16    0x49b40821
+#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
+#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
+#define T19    0x265e5a51
+#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
+#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
+#define T22    0x02441453
+#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
+#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
+#define T25    0x21e1cde6
+#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
+#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
+#define T28    0x455a14ed
+#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
+#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
+#define T31    0x676f02d9
+#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
+#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
+#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
+#define T35    0x6d9d6122
+#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
+#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
+#define T38    0x4bdecfa9
+#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
+#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
+#define T41    0x289b7ec6
+#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
+#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
+#define T44    0x04881d05
+#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
+#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
+#define T47    0x1fa27cf8
+#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
+#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
+#define T50    0x432aff97
+#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
+#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
+#define T53    0x655b59c3
+#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
+#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
+#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
+#define T57    0x6fa87e4f
+#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
+#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
+#define T60    0x4e0811a1
+#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
+#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
+#define T63    0x2ad7d2bb
+#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
+
+
+static void
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+    md5_word_t
+        a = pms->abcd[0], b = pms->abcd[1],
+        c = pms->abcd[2], d = pms->abcd[3];
+    md5_word_t t;
+#if BYTE_ORDER > 0
+    /* Define storage only for big-endian CPUs. */
+    md5_word_t X[16];
+#else
+    /* Define storage for little-endian or both types of CPUs. */
+    md5_word_t xbuf[16];
+    const md5_word_t *X;
+#endif
+
+    {
+#if BYTE_ORDER == 0
+        /*
+         * Determine dynamically whether this is a big-endian or
+         * little-endian machine, since we can use a more efficient
+         * algorithm on the latter.
+         */
+        static const int w = 1;
+
+        if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+#endif
+#if BYTE_ORDER <= 0             /* little-endian */
+        {
+            /*
+             * On little-endian machines, we can process properly aligned
+             * data without copying it.
+             */
+            if (!((data - (const md5_byte_t *)0) & 3)) {
+                /* data are properly aligned */
+                X = (const md5_word_t *)data;
+            } else {
+                /* not aligned */
+                memcpy(xbuf, data, 64);
+                X = xbuf;
+            }
+        }
+#endif
+#if BYTE_ORDER == 0
+        else                    /* dynamic big-endian */
+#endif
+#if BYTE_ORDER >= 0             /* big-endian */
+        {
+            /*
+             * On big-endian machines, we must arrange the bytes in the
+             * right order.
+             */
+            const md5_byte_t *xp = data;
+            int i;
+
+#  if BYTE_ORDER == 0
+            X = xbuf;           /* (dynamic only) */
+#  else
+#    define xbuf X              /* (static only) */
+#  endif
+            for (i = 0; i < 16; ++i, xp += 4)
+                xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+        }
+#endif
+    }
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+    /* Round 1. */
+    /* Let [abcd k s i] denote the operation
+       a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + F(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+    /* Do the following 16 operations. */
+    SET(a, b, c, d,  0,  7,  T1);
+    SET(d, a, b, c,  1, 12,  T2);
+    SET(c, d, a, b,  2, 17,  T3);
+    SET(b, c, d, a,  3, 22,  T4);
+    SET(a, b, c, d,  4,  7,  T5);
+    SET(d, a, b, c,  5, 12,  T6);
+    SET(c, d, a, b,  6, 17,  T7);
+    SET(b, c, d, a,  7, 22,  T8);
+    SET(a, b, c, d,  8,  7,  T9);
+    SET(d, a, b, c,  9, 12, T10);
+    SET(c, d, a, b, 10, 17, T11);
+    SET(b, c, d, a, 11, 22, T12);
+    SET(a, b, c, d, 12,  7, T13);
+    SET(d, a, b, c, 13, 12, T14);
+    SET(c, d, a, b, 14, 17, T15);
+    SET(b, c, d, a, 15, 22, T16);
+#undef SET
+
+     /* Round 2. */
+     /* Let [abcd k s i] denote the operation
+          a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + G(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  1,  5, T17);
+    SET(d, a, b, c,  6,  9, T18);
+    SET(c, d, a, b, 11, 14, T19);
+    SET(b, c, d, a,  0, 20, T20);
+    SET(a, b, c, d,  5,  5, T21);
+    SET(d, a, b, c, 10,  9, T22);
+    SET(c, d, a, b, 15, 14, T23);
+    SET(b, c, d, a,  4, 20, T24);
+    SET(a, b, c, d,  9,  5, T25);
+    SET(d, a, b, c, 14,  9, T26);
+    SET(c, d, a, b,  3, 14, T27);
+    SET(b, c, d, a,  8, 20, T28);
+    SET(a, b, c, d, 13,  5, T29);
+    SET(d, a, b, c,  2,  9, T30);
+    SET(c, d, a, b,  7, 14, T31);
+    SET(b, c, d, a, 12, 20, T32);
+#undef SET
+
+     /* Round 3. */
+     /* Let [abcd k s t] denote the operation
+          a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + H(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  5,  4, T33);
+    SET(d, a, b, c,  8, 11, T34);
+    SET(c, d, a, b, 11, 16, T35);
+    SET(b, c, d, a, 14, 23, T36);
+    SET(a, b, c, d,  1,  4, T37);
+    SET(d, a, b, c,  4, 11, T38);
+    SET(c, d, a, b,  7, 16, T39);
+    SET(b, c, d, a, 10, 23, T40);
+    SET(a, b, c, d, 13,  4, T41);
+    SET(d, a, b, c,  0, 11, T42);
+    SET(c, d, a, b,  3, 16, T43);
+    SET(b, c, d, a,  6, 23, T44);
+    SET(a, b, c, d,  9,  4, T45);
+    SET(d, a, b, c, 12, 11, T46);
+    SET(c, d, a, b, 15, 16, T47);
+    SET(b, c, d, a,  2, 23, T48);
+#undef SET
+
+     /* Round 4. */
+     /* Let [abcd k s t] denote the operation
+          a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + I(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  0,  6, T49);
+    SET(d, a, b, c,  7, 10, T50);
+    SET(c, d, a, b, 14, 15, T51);
+    SET(b, c, d, a,  5, 21, T52);
+    SET(a, b, c, d, 12,  6, T53);
+    SET(d, a, b, c,  3, 10, T54);
+    SET(c, d, a, b, 10, 15, T55);
+    SET(b, c, d, a,  1, 21, T56);
+    SET(a, b, c, d,  8,  6, T57);
+    SET(d, a, b, c, 15, 10, T58);
+    SET(c, d, a, b,  6, 15, T59);
+    SET(b, c, d, a, 13, 21, T60);
+    SET(a, b, c, d,  4,  6, T61);
+    SET(d, a, b, c, 11, 10, T62);
+    SET(c, d, a, b,  2, 15, T63);
+    SET(b, c, d, a,  9, 21, T64);
+#undef SET
+
+     /* Then perform the following additions. (That is increment each
+        of the four registers by the value it had before this block
+        was started.) */
+    pms->abcd[0] += a;
+    pms->abcd[1] += b;
+    pms->abcd[2] += c;
+    pms->abcd[3] += d;
+}
+
+void
+md5_init(md5_state_t *pms)
+{
+    pms->count[0] = pms->count[1] = 0;
+    pms->abcd[0] = 0x67452301;
+    pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+    pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+    pms->abcd[3] = 0x10325476;
+}
+
+void
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+    const md5_byte_t *p = data;
+    int left = nbytes;
+    int offset = (pms->count[0] >> 3) & 63;
+    md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+    if (nbytes <= 0)
+        return;
+
+    /* Update the message length. */
+    pms->count[1] += nbytes >> 29;
+    pms->count[0] += nbits;
+    if (pms->count[0] < nbits)
+        pms->count[1]++;
+
+    /* Process an initial partial block. */
+    if (offset) {
+        int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+        memcpy(pms->buf + offset, p, copy);
+        if (offset + copy < 64)
+            return;
+        p += copy;
+        left -= copy;
+        md5_process(pms, pms->buf);
+    }
+
+    /* Process full blocks. */
+    for (; left >= 64; p += 64, left -= 64)
+        md5_process(pms, p);
+
+    /* Process a final partial block. */
+    if (left)
+        memcpy(pms->buf, p, left);
+}
+
+void
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+    static const md5_byte_t pad[64] = {
+        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+    };
+    md5_byte_t data[8];
+    int i;
+
+    /* Save the length before padding. */
+    for (i = 0; i < 8; ++i)
+        data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+    /* Pad to 56 bytes mod 64. */
+    md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+    /* Append the length. */
+    md5_append(pms, data, 8);
+    for (i = 0; i < 16; ++i)
+        digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/md5.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/md5.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/md5.h	(revision 22158)
@@ -0,0 +1,94 @@
+/*
+  Copyright (C) 1999, 2002 Aladdin Enterprises.  All rights reserved.
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  L. Peter Deutsch
+  ghost@aladdin.com
+
+ */
+/* $Id: md5.h,v 1.1 2007-03-20 01:13:54 price Exp $ */
+/*
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321, whose
+  text is available at
+        http://www.ietf.org/rfc/rfc1321.txt
+  The code is derived from the text of the RFC, including the test suite
+  (section A.5) but excluding the rest of Appendix A.  It does not include
+  any code or documentation that is identified in the RFC as being
+  copyrighted.
+
+  The original and principal author of md5.h is L. Peter Deutsch
+  <ghost@aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+
+  2007-03-19 pap Fixing types for wider acceptance; incorporating into psLib.
+  2002-04-13 lpd Removed support for non-ANSI compilers; removed
+        references to Ghostscript; clarified derivation from RFC 1321;
+        now handles byte order either statically or dynamically.
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+        added conditionalization for C++ compilation from Martin
+        Purschke <purschke@bnl.gov>.
+  1999-05-03 lpd Original version.
+ */
+
+#ifndef md5_INCLUDED
+#  define md5_INCLUDED
+
+/*
+ * This package supports both compile-time and run-time determination of CPU
+ * byte order.  If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
+ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
+ * defined as non-zero, the code will be compiled to run only on big-endian
+ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
+ * run on either big- or little-endian CPUs, but will run slightly less
+ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
+ */
+
+#include <inttypes.h>
+
+typedef uint8_t md5_byte_t; /* 8-bit byte */
+typedef uint32_t md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+    md5_word_t count[2];        /* message length in bits, lsw first */
+    md5_word_t abcd[4];         /* digest buffer */
+    md5_byte_t buf[64];         /* accumulate block */
+} md5_state_t;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Initialize the algorithm. */
+void md5_init(md5_state_t *pms);
+
+/* Append a string to the message. */
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+
+/* Finish the message and return the digest. */
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+
+#ifdef __cplusplus
+}  /* end extern "C" */
+#endif
+
+#endif /* md5_INCLUDED */
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psBinaryOp.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psBinaryOp.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psBinaryOp.c	(revision 22158)
@@ -0,0 +1,538 @@
+/** @file  psBinaryOp.c
+ *
+ *  @brief Provides binary functions for simple matrix and vector element operations. Functions
+ *  include:
+ *
+ *      Addition (+)
+ *      Subtraction (-)
+ *      Multiplication (*)
+ *      Division (/)
+ *      Power (^)
+ *      Minimum (min)
+ *      Maximum (max)
+ *      Absolute value (abs)
+ *      Exponent (exp)
+ *      Natural Log (ln)
+ *      Power of 10 (ten)
+ *      Log (log)
+ *      Sine (sin or dsin)
+ *      Cosine (cos or dcos)
+ *      Tangent (tan or dtan)
+ *      Arcsine (asin or dasin)
+ *      Arccosine (acos or dacos)
+ *      Arctan (atan or datan)
+ *
+ *  Currently only vector-vector and image-image binary operations are supported.
+ *
+ *  @ingroup MatrixArithmetic
+ *
+ *  @author Ross Harman, MHPCC
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-03-19 00:52:35 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/******************************************************************************
+ *  INCLUDE FILES                                                             *
+ ******************************************************************************/
+#include <string.h>
+#include <strings.h>
+#include <math.h>
+#include <stdint.h>
+
+#include "psMemory.h"
+#include "psError.h"
+#include "psImage.h"
+#include "psVector.h"
+#include "psScalar.h"
+#include "psLogMsg.h"
+#include "psAssert.h"
+
+
+/*****************************************************************************
+ *  FUNCTION IMPLEMENTATION - LOCAL                                          *
+ *****************************************************************************/
+
+// Binary SCALAR_XXXX operations
+#define SCALAR_SCALAR(OUT,IN1,OP,IN2,TYPE) \
+{ \
+    ps##TYPE *o  = &((psScalar*)OUT)->data.TYPE; \
+    ps##TYPE *i1 = &((psScalar*)IN1)->data.TYPE; \
+    ps##TYPE *i2 = &((psScalar*)IN2)->data.TYPE; \
+    *o = OP; \
+}
+
+#define SCALAR_VECTOR(OUT,IN1,OP,IN2,TYPE) \
+{ \
+    long npt = ((psVector*)IN2)->n; \
+    ps##TYPE *o  = ((psVector*)OUT)->data.TYPE; \
+    ps##TYPE *i1 = &((psScalar*)IN1)->data.TYPE; \
+    ps##TYPE *i2 = ((psVector*)IN2)->data.TYPE; \
+    for (long i = 0; i < npt; i++, o++, i2++) { \
+        *o = OP; \
+    } \
+}
+
+#define SCALAR_IMAGE(OUT,IN1,OP,IN2,TYPE) \
+{ \
+    long numRows = ((psImage*)IN2)->numRows; \
+    long numCols = ((psImage*)IN2)->numCols; \
+    for (long j = 0; j < numCols; j++) { \
+        ps##TYPE *o  = ((psImage*)OUT)->data.TYPE[j]; \
+        ps##TYPE *i1 = &((psScalar*)IN1)->data.TYPE; \
+        ps##TYPE *i2 = ((psImage*)IN2)->data.TYPE[j]; \
+        for (long i = 0; i < numRows; i++, o++, i2++) { \
+            *o = OP; \
+        } \
+    } \
+}
+
+// Binary VECTOR_XXXX operations
+#define VECTOR_SCALAR(OUT,IN1,OP,IN2,TYPE) \
+{ \
+    long n1  = ((psVector*)IN1)->n; \
+    ps##TYPE *o  = ((psVector*)OUT)->data.TYPE; \
+    ps##TYPE *i1 = ((psVector*)IN1)->data.TYPE; \
+    ps##TYPE *i2 = &((psScalar*)IN2)->data.TYPE; \
+    for (long i = 0; i < n1; i++, o++, i1++) { \
+        *o = OP; \
+    } \
+}
+
+#define VECTOR_VECTOR(OUT,IN1,OP,IN2,TYPE) \
+{ \
+    long n1 = ((psVector*)IN1)->n; \
+    long n2 = ((psVector*)IN2)->n; \
+    if (n1 != n2) { \
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, _("Number of elements inconsistent, %ld vs %ld.  Number of elements must match."), n1, n2); \
+        if (OUT != IN1 && OUT != IN2) { \
+            psFree(OUT); \
+        } \
+        return NULL; \
+    } \
+    ps##TYPE *o  = ((psVector*)OUT)->data.TYPE; \
+    ps##TYPE *i1 = ((psVector*)IN1)->data.TYPE; \
+    ps##TYPE *i2 = ((psVector*)IN2)->data.TYPE; \
+    for (long i = 0; i < n1; i++, o++, i1++, i2++) { \
+        *o = OP; \
+    } \
+}
+
+#define VECTOR_IMAGE(OUT,IN1,OP,IN2,TYPE) \
+{ \
+    long n1 = ((psVector*)IN1)->n; \
+    long numRows2 = ((psImage*)IN2)->numRows; \
+    long numCols2 = ((psImage*)IN2)->numCols; \
+    \
+    if (((psVector*)IN1)->type.dimen == PS_DIMEN_VECTOR) { /* Regular vectors */ \
+        if (n1 != numRows2) { \
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true, _("Number of elements inconsistent, %ld vs %ld.  Number of elements must match."), n1, numRows2); \
+            if (OUT != IN1 && OUT != IN2) { \
+                psFree(OUT); \
+            } \
+            return NULL; \
+        } \
+        \
+        ps##TYPE *i1 = ((psVector*)IN1)->data.TYPE; \
+        for (long j = 0; j < numRows2; j++, i1++) { \
+            ps##TYPE *o  = ((psImage*)OUT)->data.TYPE[j]; \
+            ps##TYPE *i2 = ((psImage*)IN2)->data.TYPE[j]; \
+            for (long i = 0; i < numCols2; i++, o++, i2++) { \
+                *o = OP; \
+            } \
+        } \
+    } else {  /* Transposed vectors */ \
+        if (n1 != numCols2) { \
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true, _("Number of elements inconsistent, %ld vs %ld.  Number of elements must match."), n1, numCols2); \
+            if (OUT != IN1 && OUT != IN2) { \
+                psFree(OUT); \
+            } \
+            return NULL; \
+        } \
+        \
+        for (long j = 0; j < numRows2; j++) { \
+            ps##TYPE *o  = ((psImage*)OUT)->data.TYPE[j]; \
+            ps##TYPE *i1 = ((psVector*)IN1)->data.TYPE; \
+            ps##TYPE *i2 = ((psImage*)IN2)->data.TYPE[j]; \
+            for (long i = 0; i < numCols2; i++, o++, i1++, i2++) { \
+                *o = OP; \
+            } \
+        } \
+    } \
+}
+
+// Binary IMAGE_XXXX operations
+#define IMAGE_SCALAR(OUT,IN1,OP,IN2,TYPE) \
+{ \
+    long numRows = ((psImage*)IN1)->numRows; \
+    long numCols = ((psImage*)IN1)->numCols; \
+    for (long j = 0; j < numRows; j++) { \
+        ps##TYPE *o  = ((psImage*)OUT)->data.TYPE[j]; \
+        ps##TYPE *i1 = ((psImage*)IN1)->data.TYPE[j]; \
+        ps##TYPE *i2 = &((psScalar*)IN2)->data.TYPE; \
+        for (long i = 0; i < numCols; i++, o++, i1++) { \
+            *o = OP; \
+        } \
+    } \
+}
+
+#define IMAGE_VECTOR(OUT,IN1,OP,IN2,TYPE) \
+{ \
+    long n2 = ((psVector*)IN2)->n; \
+    long numRows1 = ((psImage*)IN1)->numRows; \
+    long numCols1 = ((psImage*)IN1)->numCols; \
+    \
+    if (((psVector*)IN2)->type.dimen == PS_DIMEN_VECTOR) { /* Regular vectors */ \
+        if (n2 != numRows1) { \
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true, _("Number of elements inconsistent, %ld vs %ld.  Number of elements must match."), n2, numRows1); \
+            if (OUT != IN1 && OUT != IN2) { \
+                psFree(OUT); \
+            } \
+            return NULL; \
+        } \
+        \
+        ps##TYPE *i2 = ((psVector* )IN2)->data.TYPE; \
+        for (long j = 0; j < numRows1; j++, i2++) { \
+            ps##TYPE *o  = ((psImage*)OUT)->data.TYPE[j]; \
+            ps##TYPE *i1 = ((psImage*)IN1)->data.TYPE[j]; \
+            for (long i = 0; i < numCols1; i++, o++, i1++) { \
+                *o = OP; \
+            } \
+        } \
+    } else {  /* Transposed vectors */ \
+        if (n2 != numCols1) { \
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true, _("Number of elements inconsistent, %ld vs %ld.  Number of elements must match."), n2, numCols1); \
+            if (OUT != IN1) { \
+                psFree(OUT); \
+            } \
+            return NULL; \
+        } \
+        \
+        for (long j = 0; j < numRows1; j++) { \
+            ps##TYPE *o  = ((psImage*)OUT)->data.TYPE[j]; \
+            ps##TYPE *i1 = ((psVector*)IN2)->data.TYPE; \
+            ps##TYPE *i2 = ((psImage*)IN1)->data.TYPE[j]; \
+            for (long i = 0; i < numCols1; i++, o++, i2++, i1++) { \
+                *o = OP; \
+            } \
+        } \
+    } \
+}
+
+#define IMAGE_IMAGE(OUT,IN1,OP,IN2,TYPE) \
+{ \
+    long numRows1 = ((psImage*)IN1)->numRows; \
+    long numCols1 = ((psImage*)IN1)->numCols; \
+    long numRows2 = ((psImage*)IN2)->numRows; \
+    long numCols2 = ((psImage*)IN2)->numCols; \
+    if (numRows1 != numRows2 || numCols1 != numCols2) { \
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, _("Specified psImage dimensions differed, %ldx%ld vs %ldx%ld."), \
+                numCols1, numRows1, numCols2, numRows2); \
+        if (OUT != IN1 && OUT != IN2) { \
+            psFree(OUT); \
+        } \
+        return NULL; \
+    } \
+    for (long j = 0; j < numRows1; j++) { \
+        ps##TYPE *o  = ((psImage*)OUT)->data.TYPE[j]; \
+        ps##TYPE *i1 = ((psImage*)IN1)->data.TYPE[j]; \
+        ps##TYPE *i2 = ((psImage*)IN2)->data.TYPE[j]; \
+        for (long i = 0; i < numCols1; i++, o++, i1++, i2++) { \
+            *o = OP; \
+        } \
+    } \
+}
+
+
+// Preprocessor macro function to create arithmetic function based on input type --- for integers only
+#define BINARY_TYPE_INTEGER(DIM1,DIM2,OUT,IN1,OP,IN2)                                                        \
+switch (IN1->type) {                                                                                         \
+case PS_TYPE_U8:                                                                                             \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,U8);                                                                        \
+    break;                                                                                                   \
+case PS_TYPE_U16:                                                                                            \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,U16);                                                                       \
+    break;                                                                                                   \
+case PS_TYPE_U32:                                                                                            \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,U32);                                                                       \
+    break;                                                                                                   \
+case PS_TYPE_U64:                                                                                            \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,U64);                                                                       \
+    break;                                                                                                   \
+case PS_TYPE_S8:                                                                                             \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,S8);                                                                        \
+    break;                                                                                                   \
+case PS_TYPE_S16:                                                                                            \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,S16);                                                                       \
+    break;                                                                                                   \
+case PS_TYPE_S32:                                                                                            \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,S32);                                                                       \
+    break;                                                                                                   \
+case PS_TYPE_S64:                                                                                            \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,S64);                                                                       \
+    break;                                                                                                   \
+default:                                                                                                     \
+    /* char* strType;                                                                                        \
+    PS_TYPE_NAME(strType,IN1->type);                                                                         \
+    psError(PS_ERR_BAD_PARAMETER_TYPE, true,                                                                 \
+            _("Specified data type, %s, is not supported."),                                                             \
+            strType);  */                                                                                    \
+    if (OUT != IN1 && OUT != IN2) {                                                                          \
+        psFree(OUT);                                                                                         \
+    }                                                                                                        \
+    return NULL;                                                                                             \
+}
+
+// Preprocessor macro function to create arithmetic function based on input type
+#define BINARY_TYPE(DIM1,DIM2,OUT,IN1,OP,IN2)                                                                \
+switch (IN1->type) {                                                                                         \
+case PS_TYPE_U8:                                                                                             \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,U8);                                                                        \
+    break;                                                                                                   \
+case PS_TYPE_U16:                                                                                            \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,U16);                                                                       \
+    break;                                                                                                   \
+case PS_TYPE_U32:                                                                                            \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,U32);                                                                       \
+    break;                                                                                                   \
+case PS_TYPE_U64:                                                                                            \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,U64);                                                                       \
+    break;                                                                                                   \
+case PS_TYPE_S8:                                                                                             \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,S8);                                                                        \
+    break;                                                                                                   \
+case PS_TYPE_S16:                                                                                            \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,S16);                                                                       \
+    break;                                                                                                   \
+case PS_TYPE_S32:                                                                                            \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,S32);                                                                       \
+    break;                                                                                                   \
+case PS_TYPE_S64:                                                                                            \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,S64);                                                                       \
+    break;                                                                                                   \
+case PS_TYPE_F32:                                                                                            \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,F32);                                                                       \
+    break;                                                                                                   \
+case PS_TYPE_F64:                                                                                            \
+    DIM1##_##DIM2(OUT,IN1,OP,IN2,F64);                                                                       \
+    break;                                                                                                   \
+default: {                                                                                                   \
+        char* strType;                                                                                       \
+        PS_TYPE_NAME(strType,IN1->type);                                                                     \
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,                                                             \
+                _("Specified data type, %s, is not supported."),                                             \
+                strType);                                                                                    \
+        if (OUT != IN1 && OUT != IN2) {                                                                      \
+            psFree(OUT);                                                                                     \
+        }                                                                                                    \
+        return NULL;                                                                                         \
+    }                                                                                                        \
+}
+
+// Preprocessor macro function to create arithmetic function operation name
+#define BINARY_OP(DIM1,DIM2,OUT,IN1,OP,IN2)                                                                  \
+if (!strncmp(OP, "+", 1)) {                                                                                  \
+    BINARY_TYPE(DIM1,DIM2,OUT,IN1,*i1 + *i2,IN2);                                                            \
+} else if (!strncmp(OP, "-", 1)) {                                                                           \
+    BINARY_TYPE(DIM1,DIM2,OUT,IN1,*i1 - *i2,IN2);                                                            \
+} else if (!strncmp(OP, "*", 1)) {                                                                           \
+    BINARY_TYPE(DIM1,DIM2,OUT,IN1,*i1 * *i2,IN2);                                                            \
+} else if (!strncmp(OP, "/", 1)) {                                                                           \
+    BINARY_TYPE(DIM1,DIM2,OUT,IN1,*i1 / *i2,IN2);                                                            \
+} else if (!strncmp(OP, "&", 1)) {                                                                           \
+    if (PS_IS_PSELEMTYPE_INT(IN1->type) && PS_IS_PSELEMTYPE_INT(IN2->type)) {                                \
+        BINARY_TYPE_INTEGER(DIM1,DIM2,OUT,IN1,(*i1) & (*i2),IN2);                                            \
+    } else {                                                                                                 \
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,                                                            \
+                "Types (%x,%x) are not appropriate for logical AND.\n", IN1->type, IN2->type);               \
+        return NULL;                                                                                         \
+    }                                                                                                        \
+} else if (!strncmp(OP, "|", 1)) {                                                                           \
+    if (PS_IS_PSELEMTYPE_INT(IN1->type) && PS_IS_PSELEMTYPE_INT(IN2->type)) {                                \
+        BINARY_TYPE_INTEGER(DIM1,DIM2,OUT,IN1,(*i1) | (*i2),IN2);                                            \
+    } else {                                                                                                 \
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,                                                            \
+                "Types (%x,%x) are not appropriate for logical OR.\n", IN1->type, IN2->type);                \
+        return NULL;                                                                                         \
+    }                                                                                                        \
+} else if (!strncmp(OP, "^", 1)) {                                                                           \
+    BINARY_TYPE(DIM1,DIM2,OUT,IN1,pow(*i1,*i2),IN2);                                                         \
+} else if (!strncasecmp(OP, "min", 3)) {                                                                     \
+    BINARY_TYPE(DIM1,DIM2,OUT,IN1,fmin(*i1,*i2),IN2);                                                        \
+} else if (!strncasecmp(OP, "max", 3)) {                                                                     \
+    BINARY_TYPE(DIM1,DIM2,OUT,IN1,fmax(*i1,*i2),IN2);                                                        \
+} else {                                                                                                     \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true,                                                                \
+            _("Specified operation, %s, is not supported."),                                                 \
+            OP);                                                                                             \
+    if (OUT != IN1 && OUT != IN2) {                                                                          \
+        psFree(OUT);                                                                                         \
+    }                                                                                                        \
+    return NULL;                                                                                             \
+}
+
+psMathType* psBinaryOp(psPtr out, const psPtr in1, const char *op, const psPtr in2)
+{
+
+    psVector* input1 = (psVector* ) in1;
+    psVector* input2 = (psVector* ) in2;
+
+    #define psBinaryOp_EXIT { \
+                              if (out != in1 && out != in2) { \
+                              psFree(out); \
+                              } \
+                              return NULL; \
+                            }
+
+    PS_ASSERT_GENERAL_PTR_NON_NULL(input1, psBinaryOp_EXIT);
+    PS_ASSERT_GENERAL_PTR_NON_NULL(input2, psBinaryOp_EXIT);
+    PS_ASSERT_GENERAL_PTR_NON_NULL(op, psBinaryOp_EXIT);
+
+    PS_ASSERT_GENERAL_PTR_TYPE_EQUAL(input1,input2, psBinaryOp_EXIT);
+
+    PS_ASSERT_PTR_DIMEN_GENERAL_NOT(input1, PS_DIMEN_OTHER, psBinaryOp_EXIT);
+    PS_ASSERT_PTR_DIMEN_GENERAL_NOT(input2, PS_DIMEN_OTHER, psBinaryOp_EXIT);
+
+    psMathType* psType1 = (psMathType*)in1;
+    psMathType* psType2 = (psMathType*)in2;
+    psDimen dim1 = psType1->dimen;
+    psDimen dim2 = psType2->dimen;
+    psElemType elType1 = psType1->type;
+    psElemType elType2 = psType2->type;
+
+    if (dim1 == PS_DIMEN_VECTOR || dim1 == PS_DIMEN_TRANSV) {
+        if (((psVector* ) in1)->n == 0) {
+            psLogMsg(__func__, PS_LOG_WARN, "Vector contains zero elements");
+        }
+    } else if (dim1 == PS_DIMEN_IMAGE) {
+        if (((psImage* ) in1)->numCols == 0 || ((psImage* ) in1)->numRows == 0) {
+            psLogMsg(__func__, PS_LOG_WARN, "Image contains zero length row or cols");
+        }
+    }
+
+    if (dim2 == PS_DIMEN_VECTOR || dim2 == PS_DIMEN_TRANSV) {
+        if (((psVector* ) in2)->n == 0) {
+            psLogMsg(__func__, PS_LOG_WARN, "Vector contains zero elements");
+        }
+    } else if (dim2 == PS_DIMEN_IMAGE) {
+        if (((psImage* ) in2)->numCols == 0 || ((psImage* ) in2)->numRows == 0) {
+            psLogMsg(__func__, PS_LOG_WARN, "Image contains zero length row or cols");
+        }
+    }
+
+    if (dim1 == PS_DIMEN_SCALAR) {
+        if ( out != NULL && ((psMathType*)out)->dimen != dim2) {
+            if (out != in1 && out != in2) {
+                psFree(out);
+            }
+            out = NULL;
+        }
+        if (dim2 == PS_DIMEN_SCALAR) {
+            if (out == NULL || ((psScalar*)out)->type.type != elType1) {
+                if (out != in1 && out != in2) {
+                    psFree(out);
+                }
+                out = psScalarAlloc(0.0,elType1);
+            }
+            BINARY_OP(SCALAR, SCALAR, out, psType1, op, psType2);       // scalar op scalar
+        } else if (dim2 == PS_DIMEN_VECTOR || dim2 == PS_DIMEN_TRANSV) {
+            out = psVectorRecycle(out,((psVector*)in2)->n,elType1);
+            if (out == NULL) {
+                psError(PS_ERR_UNKNOWN, false,
+                        _("Couldn't create a proper output psVector."));
+                return NULL;
+            }
+            ((psVector*)out)->n = ((psVector*)in2)->n;
+            BINARY_OP(SCALAR, VECTOR, out, psType1, op, psType2);       // scalar op vector
+        } else if (dim2 == PS_DIMEN_IMAGE) {
+            out = psImageRecycle(out, ((psImage* ) in2)->numCols, ((psImage* ) in2)->numRows,elType1);
+            if (out == NULL) {
+                psError(PS_ERR_UNKNOWN, false,
+                        _("Couldn't create a proper output psImage."));
+                return NULL;
+            }
+            BINARY_OP(SCALAR, IMAGE, out, psType1, op, psType2);        // scalar op image
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    _("Specified parameter, %s, has invalid dimensionality, %d."),
+                    "in2",dim2);
+            psBinaryOp_EXIT;
+        }
+    } else if (dim1 == PS_DIMEN_VECTOR || dim1 == PS_DIMEN_TRANSV) {
+        if (dim2 == PS_DIMEN_SCALAR) {
+            out = psVectorRecycle(out,((psVector*)in1)->n,elType1);
+            if (out == NULL) {
+                psError(PS_ERR_UNKNOWN, false,
+                        _("Couldn't create a proper output psVector."));
+                return NULL;
+            }
+            ((psVector*)out)->n = ((psVector*)in1)->n;
+            BINARY_OP(VECTOR, SCALAR, out, psType1, op, psType2);       // vector op scalar
+        } else if (dim2 == PS_DIMEN_VECTOR || dim2 == PS_DIMEN_TRANSV) {
+            out = psVectorRecycle(out,((psVector*)in2)->n,elType2);
+            if (out == NULL) {
+                psError(PS_ERR_UNKNOWN, false,
+                        _("Couldn't create a proper output psVector."));
+                return NULL;
+            }
+            ((psVector*)out)->n = ((psVector*)in2)->n;
+            BINARY_OP(VECTOR, VECTOR, out, psType1, op, psType2);       // vector op vector
+        } else if (dim2 == PS_DIMEN_IMAGE) {
+            out = psImageRecycle(out, ((psImage* ) in2)->numCols, ((psImage* ) in2)->numRows, elType2);
+            if (out == NULL) {
+                psError(PS_ERR_UNKNOWN, false,
+                        _("Couldn't create a proper output psImage."));
+                return NULL;
+            }
+            BINARY_OP(VECTOR, IMAGE, out, psType1, op, psType2);        // vector op image
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    _("Specified parameter, %s, has invalid dimensionality, %d."),
+                    "in2",dim2);
+            psBinaryOp_EXIT;
+        }
+    } else if (dim1 == PS_DIMEN_IMAGE) {
+        out = psImageRecycle(out, ((psImage*)in1)->numCols, ((psImage*)in1)->numRows, elType1);
+        if (out == NULL) {
+            psError(PS_ERR_UNKNOWN, false,
+                    _("Couldn't create a proper output psImage."));
+            return NULL;
+        }
+        if (dim2 == PS_DIMEN_SCALAR) {
+            BINARY_OP(IMAGE, SCALAR, out, psType1, op, psType2);        // image op scalar
+        } else if (dim2 == PS_DIMEN_VECTOR || dim2 == PS_DIMEN_TRANSV) {
+            BINARY_OP(IMAGE, VECTOR, out, psType1, op, psType2);        // image op vector
+        } else if (dim2 == PS_DIMEN_IMAGE) {
+            BINARY_OP(IMAGE, IMAGE, out, psType1, op, psType2); // image op image
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    _("Specified parameter, %s, has invalid dimensionality, %d."),
+                    "in2",dim2);
+            psBinaryOp_EXIT;
+        }
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("Specified parameter, %s, has invalid dimensionality, %d."),
+                "in1",dim1);
+        psBinaryOp_EXIT;
+    }
+
+    // Automtically free psScalar types, since they are usually allocated in the argument list when this
+    // function is called, provided that the input is not the output.
+    if (psType1->dimen==PS_DIMEN_SCALAR && in1!=out) {
+        psFree(in1);
+    }
+
+    if (psType2->dimen==PS_DIMEN_SCALAR && in2!=out) {
+        psFree(in2);
+    }
+
+    return out;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psBinaryOp.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psBinaryOp.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psBinaryOp.h	(revision 22158)
@@ -0,0 +1,63 @@
+/* @file  psBinaryOp.h
+ *
+ * @brief Provides binary functions for simple matrix and vector element operations. 
+ * 
+ * Functions include:
+ *     Addition (+)
+ *     Subtraction (-)
+ *     Multiplication (*)
+ *     Division (/)
+ *     Power (^)
+ *     Minimum (min)
+ *     Maximum (max)
+ *     Absolute value (abs)
+ *     Exponent (exp)
+ *     Natural Log (ln)
+ *     Power of 10 (ten)
+ *     Log (log)
+ *     Sine (sin or dsin)
+ *     Cosine (cos or dcos)
+ *     Tangent (tan or dtan)
+ *     Arcsine (asin or dasin)
+ *     Arccosine (acos or dacos)
+ *     Arctan (atan or datan)
+ *
+ * Currently only vector-vector and image-image binary operations are supported.
+ *
+ * @author Ross Harman, MHPCC
+ * @author Robert DeSonia, MHPCC
+ *
+ * @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-01-23 22:47:23 $
+ *
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PSBINARY_OP_H
+#define PSBINARY_OP_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+/** Perform simple binary arithmetic with images or vectors
+ *
+ *  Performs addition, subtraction, multiplication, division, power, minumum, and maximum arithmetic
+ *  operations with images and vectors. Uses the form:
+ *
+ *      out = in1 op in2,
+ *
+ *      Where op is: "=", "+", "-", "*", "/", "^", "min", or "max"
+ *
+ *  This function only supports vector-vector or image-image operations.
+ *
+ *  @return  psType* : Pointer to either psImage or psVector.
+ */
+psMathType* psBinaryOp(
+    psPtr out,                         ///< Output type, either psImage or psVector.
+    const psPtr in1,                   ///< First input, either psImage or psVector.
+    const char *op,                    ///< Operator.
+    const psPtr in2                    ///< Second input, either psImage or psVector.
+);
+
+/// @}
+#endif // #ifndef PSBINARY_OP_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psClip.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psClip.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psClip.c	(revision 22158)
@@ -0,0 +1,197 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <math.h>
+
+#include "psMemory.h"
+#include "psError.h"
+#include "psErrorCodes.h"
+#include "psAssert.h"
+#include "psTrace.h"
+#include "psVector.h"
+#include "psStats.h"
+#include "psClip.h"
+
+// No-op; purpose of function is merely to identify the type
+static void clipParamsFree(psClipParams *params)
+{
+    return;
+}
+
+psClipParams *psClipParamsAlloc(psStatsOptions meanStat, psStatsOptions stdevStat,
+                                psMaskType masked, psMaskType clipped)
+{
+    psClipParams *params = psAlloc(sizeof(psClipParams)); // Clip parameters
+    psMemSetDeallocator(params, (psFreeFunc)clipParamsFree);
+
+    params->meanStat = meanStat;
+    params->stdevStat = stdevStat;
+    params->fracHigh = 0.0;
+    params->fracLow = 0.0;
+    params->numKeep = 0;
+    params->iter = 1;
+    params->rej = 0.0;
+    params->masked = masked;
+    params->clipped = clipped;
+
+    params->mean = NAN;
+    params->stdev = NAN;
+
+    return params;
+}
+
+
+long psClipMinMax(const psClipParams *params, const psVector *values, psVector *mask)
+{
+    PS_ASSERT_VECTOR_NON_NULL(values, -1);
+    PS_ASSERT_VECTOR_NON_NULL(mask, -1);
+    PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_MASK, -1);
+    PS_ASSERT_PTR(params, -1);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(values, mask, -1);
+    PS_ASSERT_FLOAT_LARGER_THAN_OR_EQUAL(params->fracLow, 0.0, -1);
+    PS_ASSERT_FLOAT_LESS_THAN(params->fracLow, 1.0, -1);
+    PS_ASSERT_FLOAT_LARGER_THAN_OR_EQUAL(params->fracHigh, 0.0, -1);
+    PS_ASSERT_FLOAT_LESS_THAN(params->fracHigh, 1.0, -1);
+    PS_ASSERT_INT_NONZERO(params->clipped, -1);
+
+    if (params->fracLow == 0.0 && params->fracHigh == 0.0) {
+        // No min-max rejection desired
+        return 0;
+    }
+
+    psMaskType masked = params->masked; // Indicates masked values
+    psMaskType clipped = params->clipped; // Indicates clipped values
+    masked |= clipped;                  // Make sure we're also masking clipped values
+    psMaskType *maskData = mask->data.PS_TYPE_MASK_DATA; // Dereference mask
+    long totalMasked = 0;               // Total number of pixels masked
+
+    // Apply fracLow,fracHigh if there are enough values
+
+    // Run through to get number of operational values
+    long numValid = 0;                  // Number of valid values
+    for (long i = 0; i < mask->n; i++) {
+        if (!(maskData[i] & masked)) {
+            numValid++;
+        }
+    }
+    psTrace("psLib.math", 2, "%ld valid values.\n", numValid);
+
+    // XXX: Not sure if sorting provides the fastest implementation.  It might be quicker to do a linear pass
+    // through the data, pulling out the highest M and lowest N values,
+
+    float keepFrac = 1.0 - params->fracLow - params->fracHigh; // Fraction of values to keep
+    if (numValid * keepFrac >= params->numKeep) {
+        psTrace("psLib.math", 1, "Applying min/max clipping.\n");
+        psVector *index = psVectorSortIndex(NULL, values);
+        int numLow = numValid * params->fracLow; // Number of low values to clip
+        int numHigh = numValid * params->fracHigh; // Number of high values to clip
+        // Low values
+        psS32 *indexData = index->data.S32; // Dereference index
+        long numMasked = 0;             // Number masked
+        for (long i = 0; i < index->n && numMasked < numLow; i++) {
+            // Don't count the ones that are already masked
+            if (! (maskData[indexData[i]] & masked)) {
+                maskData[indexData[i]] |= clipped;
+                numMasked++;
+            }
+        }
+        totalMasked += numMasked;
+        numMasked = 0;
+        // High values
+        for (long i = values->n - 1;  i >= 0 && numMasked < numHigh; i--) {
+            // Don't count the ones that are already masked
+            if (! (maskData[indexData[i]] & masked)) {
+                maskData[indexData[i]] |= clipped;
+                numMasked++;
+            }
+        }
+        totalMasked += numMasked;
+        psFree(index);
+    }
+
+    return totalMasked;
+}
+
+
+long psClipReject(psClipParams *params, const psVector *values, psVector *mask, const psVector *errors)
+{
+    PS_ASSERT_VECTOR_NON_NULL(values, -1);
+    PS_ASSERT_VECTOR_NON_NULL(mask, -1);
+    PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_MASK, -1);
+    PS_ASSERT_PTR(params, -1);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(values, mask, -1);
+    if (errors) {
+        PS_ASSERT_VECTOR_NON_NULL(errors, -1);
+        PS_ASSERT_VECTORS_SIZE_EQUAL(values, errors, -1);
+        PS_ASSERT_VECTOR_TYPE_F32_OR_F64(values, -1);
+        PS_ASSERT_VECTOR_TYPE_EQUAL(values, errors, -1);
+    }
+    PS_ASSERT_INT_NONZERO(params->meanStat, -1);
+    PS_ASSERT_INT_NONZERO(params->stdevStat, -1);
+    if (!isfinite(params->rej) || params->rej < 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Rejection limit (%f) is not valid.\n", params->rej);
+        return -1;
+    }
+
+    if (params->rej == 0.0) {
+        // No clipping desired
+        return 0;
+    }
+
+    psMaskType masked = params->masked; // Indicates masked values
+    psMaskType clipped = params->clipped; // Indicates clipped values
+    masked |= clipped;                  // Make sure we're also masking clipped values
+
+    // Get statistics
+    psStats *stats = psStatsAlloc(params->meanStat | params->stdevStat);
+    if (!psVectorStats(stats, values, errors, mask, masked)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to perform statistics on values.\n");
+        psFree(stats);
+        return -1;
+    }
+    params->mean = psStatsGetValue(stats, params->meanStat);
+    params->stdev = psStatsGetValue(stats, params->stdevStat);
+
+    #define REJECT_CASE(TYPE) \
+case PS_TYPE_##TYPE: { \
+        ps##TYPE *valuesData = values->data.TYPE; /* Dereference for speed */ \
+        psMaskType *maskData = mask->data.PS_TYPE_MASK_DATA; /* Dereference mask for speed */ \
+        if (errors) { \
+            ps##TYPE *errorsData = errors->data.TYPE; \
+            for (int j = 0; j < values->n; j++) { \
+                if (!(maskData[j] & masked) && \
+                        fabs(valuesData[j] - params->mean) > params->rej * errorsData[j]) { \
+                    maskData[j] |= clipped; \
+                    totalMasked++; \
+                } \
+            } \
+        } else { \
+            ps##TYPE limit = params->rej * params->stdev; /* Limit on deviation */ \
+            for (int j = 0; j < values->n; j++) { \
+                if (!(maskData[j] & masked) && fabs(valuesData[j] - params->mean) > limit) { \
+                    maskData[j] |= clipped; \
+                    totalMasked++; \
+                } \
+            } \
+        } \
+    }
+
+    long totalMasked = 0;               // Total number of pixels masked
+    switch (values->type.type) {
+        REJECT_CASE(S8);
+        REJECT_CASE(S16);
+        REJECT_CASE(S32);
+        REJECT_CASE(S64);
+        REJECT_CASE(F32);
+        REJECT_CASE(F64);
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Unsupported vector type: %x\n", values->type.type);
+        psFree(stats);
+        return -1;
+    }
+
+    psFree(stats);
+    return totalMasked;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psClip.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psClip.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psClip.h	(revision 22158)
@@ -0,0 +1,64 @@
+/* @file  psClip.h
+ * @brief vector clipping functions
+ *
+ * @author Paul Price, IfA.
+ *
+ * $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ * $Date: 2007-08-09 01:40:07 $
+ * Copyright 2007 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PS_CLIP_H
+#define PS_CLIP_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+/// Parameters for clipping
+typedef struct
+{
+    psStatsOptions meanStat;            ///< Stats option to use for mean
+    psStatsOptions stdevStat;           ///< Stats option to use for standard deviation
+    float fracHigh;                     ///< Fraction of high values to clip
+    float fracLow;                      ///< Fraction of low values to clip
+    int numKeep;                        ///< Minimum number of values to keep from clipping
+    int iter;                           ///< Number of rejection iterations; unused by psClip functions
+    float rej;                          ///< Rejection limit (standard deviations)
+    psMaskType masked;                  ///< Mask value for entries already masked
+    psMaskType clipped;                 ///< Mask value to give to clipped entries
+    double mean;                        ///< Resultant mean
+    double stdev;                       ///< Resultant stdev
+}
+psClipParams;
+
+/// Allocator
+psClipParams *psClipParamsAlloc(psStatsOptions meanStat, ///< Stats option to use for mean
+                                psStatsOptions stdevStat, ///< Stats option to use for standard deviation
+                                psMaskType masked, ///< Mask value for entries already masked
+                                psMaskType clipped ///< Mask value to give to clipped entries
+    ) PS_ATTR_MALLOC;
+
+
+/// Apply min-max clipping to a list of values
+///
+/// The specified fraction of high and low values are identified as clipped in the mask.  Errors are not used
+/// in this step.
+long psClipMinMax(const psClipParams *params, ///< Clip parameters
+                  const psVector *values, ///< Values to inspect and clip
+                  psVector *mask        ///< Mask for values
+    );
+
+
+
+/// Apply a rejection iteration to a list of values
+///
+/// The specified rejection limit is applied to the values and errors; discrepant values are identified as
+/// clipped in the mask.  This function only applies a single rejection iteration.
+long psClipReject(psClipParams *params, ///< Clip parameters
+                  const psVector *values, ///< Values to inspect and clip
+                  psVector *mask,       ///< Mask for values
+                  const psVector *errors ///< Errors for values, or NULL
+    );
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psCompare.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psCompare.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psCompare.c	(revision 22158)
@@ -0,0 +1,123 @@
+
+/** @file psCompare.c
+ *  @brief Comparison functions for sorting routines
+ *  @ingroup Compare
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author Robert Daniel DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-01-09 22:38:52 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "psCompare.h"
+
+#define COMPARE_NUMERIC_PTR(TYPE) \
+int psCompare##TYPE##Ptr(const void** a, const void** b) { \
+    return **((ps##TYPE**)a) - **((ps##TYPE**)b); \
+}
+
+#define COMPARE_NUMERIC_PTR_DESCENDING(TYPE) \
+int psCompareDescending##TYPE##Ptr(const void** a, const void** b) { \
+    return **((ps##TYPE**)b) - **((ps##TYPE**)a); \
+}
+
+#define COMPARE_NUMERIC(TYPE) \
+int psCompare##TYPE(const void* a, const void* b) { \
+    return *((ps##TYPE*)a) - *((ps##TYPE*)b); \
+}
+
+#define COMPARE_NUMERIC_DESCENDING(TYPE) \
+int psCompareDescending##TYPE(const void* a, const void* b) { \
+    return *((ps##TYPE*)b) - *((ps##TYPE*)a); \
+}
+
+COMPARE_NUMERIC_PTR(S8)
+COMPARE_NUMERIC_PTR(S16)
+COMPARE_NUMERIC_PTR(S32)
+COMPARE_NUMERIC_PTR(S64)
+COMPARE_NUMERIC_PTR(U8)
+COMPARE_NUMERIC_PTR(U16)
+COMPARE_NUMERIC_PTR(U32)
+COMPARE_NUMERIC_PTR(U64)
+
+int psCompareF32Ptr(const void** a, const void** b)
+{
+    psF32 diff = **((psF32**)a) - **((psF32**)b);
+    return (diff>FLT_EPSILON) ? 1 : ((diff<FLT_EPSILON) ? -1 :0);
+}
+
+int psCompareF64Ptr(const void** a, const void** b)
+{
+    psF64 diff = **((psF64**)a) - **((psF64**)b);
+    return (diff>DBL_EPSILON) ? 1 : ((diff<DBL_EPSILON) ? -1 :0);
+}
+
+COMPARE_NUMERIC_PTR_DESCENDING(S8)
+COMPARE_NUMERIC_PTR_DESCENDING(S16)
+COMPARE_NUMERIC_PTR_DESCENDING(S32)
+COMPARE_NUMERIC_PTR_DESCENDING(S64)
+COMPARE_NUMERIC_PTR_DESCENDING(U8)
+COMPARE_NUMERIC_PTR_DESCENDING(U16)
+COMPARE_NUMERIC_PTR_DESCENDING(U32)
+COMPARE_NUMERIC_PTR_DESCENDING(U64)
+
+int psCompareDescendingF32Ptr(const void** a, const void** b)
+{
+    psF32 diff = **((psF32**)b) - **((psF32**)a);
+    return (diff>FLT_EPSILON) ? 1 : ((diff<FLT_EPSILON) ? -1 :0);
+}
+
+int psCompareDescendingF64Ptr(const void** a, const void** b)
+{
+    psF64 diff = **((psF64**)b) - **((psF64**)a);
+    return (diff>DBL_EPSILON) ? 1 : ((diff<DBL_EPSILON) ? -1 :0);
+}
+
+COMPARE_NUMERIC(S8)
+COMPARE_NUMERIC(S16)
+COMPARE_NUMERIC(S32)
+COMPARE_NUMERIC(S64)
+COMPARE_NUMERIC(U8)
+COMPARE_NUMERIC(U16)
+COMPARE_NUMERIC(U32)
+COMPARE_NUMERIC(U64)
+
+int psCompareF32(const void* a, const void* b)
+{
+    psF32 diff = *((psF32*)a) - *((psF32*)b);
+    return (diff>FLT_EPSILON) ? 1 : ((diff<FLT_EPSILON) ? -1 :0);
+}
+
+int psCompareF64(const void* a, const void* b)
+{
+    psF64 diff = *((psF64*)a) - *((psF64*)b);
+    return (diff>DBL_EPSILON) ? 1 : ((diff<DBL_EPSILON) ? -1 :0);
+}
+
+COMPARE_NUMERIC_DESCENDING(S8)
+COMPARE_NUMERIC_DESCENDING(S16)
+COMPARE_NUMERIC_DESCENDING(S32)
+COMPARE_NUMERIC_DESCENDING(S64)
+COMPARE_NUMERIC_DESCENDING(U8)
+COMPARE_NUMERIC_DESCENDING(U16)
+COMPARE_NUMERIC_DESCENDING(U32)
+COMPARE_NUMERIC_DESCENDING(U64)
+
+int psCompareDescendingF32(const void* a, const void* b)
+{
+    psF32 diff = *((psF32*)b) - *((psF32*)a);
+    return (diff>FLT_EPSILON) ? 1 : ((diff<FLT_EPSILON) ? -1 :0);
+}
+
+int psCompareDescendingF64(const void* a, const void* b)
+{
+    psF64 diff = *((psF64*)b) - *((psF64*)a);
+    return (diff>DBL_EPSILON) ? 1 : ((diff<DBL_EPSILON) ? -1 :0);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psCompare.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psCompare.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psCompare.h	(revision 22158)
@@ -0,0 +1,502 @@
+/* @file psCompare.h
+ * @brief Comparison functions for sorting routines
+ *
+ * @author Robert Daniel DeSonia, MHPCC
+ *
+ * @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-09-28 21:02:23 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_COMPARE_H
+#define PS_COMPARE_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+#include "psType.h"
+
+/** A comparison function for sorting elements that are pointers to data,
+ *  e.g., for psList of pointers to numeric values.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+typedef int (*psComparePtrFunc) (
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** A comparison function for sorting.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+typedef int (*psCompareFunc) (
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+/** Compare function of psS8 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareS8Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS16 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareS16Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS32 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareS32Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS64 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareS64Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU8 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareU8Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU16 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareU16Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU32 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareU32Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU64 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareU64Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psF32 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareF32Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psF64 data.  For use with psListSort.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareF64Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS8 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or less than the second.
+ */
+int psCompareDescendingS8Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS16 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or less than the second.
+ */
+int psCompareDescendingS16Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS32 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or less than the second.
+ */
+int psCompareDescendingS32Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS64 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or less than the second.
+ */
+int psCompareDescendingS64Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU8 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or less than the second.
+ */
+int psCompareDescendingU8Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU16 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or less than the second.
+ */
+int psCompareDescendingU16Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU32 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or lessg than the second.
+ */
+int psCompareDescendingU32Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psU64 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or lessg than the second.
+ */
+int psCompareDescendingU64Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psF32 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or lessg than the second.
+ */
+int psCompareDescendingF32Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psF64 data.  For use with psListSort for descending ordering.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or lessg than the second.
+ */
+int psCompareDescendingF64Ptr(
+    const void **a,                    ///< first comparison target
+    const void **b                     ///< second comparison target
+);
+
+/** Compare function of psS8 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareS8(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS16 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareS16(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS32 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareS32(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS64 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareS64(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU8 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareU8(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU16 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareU16(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU32 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareU32(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU64 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareU64(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psF32 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareF32(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psF64 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively less
+ *                   than, equal to, or greater than the second.
+ */
+int psCompareF64(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS8 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or less than the second.
+ */
+int psCompareDescendingS8(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS16 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or less than the second.
+ */
+int psCompareDescendingS16(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS32 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or less than the second.
+ */
+int psCompareDescendingS32(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psS64 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or less than the second.
+ */
+int psCompareDescendingS64(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU8 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or less than the second.
+ */
+int psCompareDescendingU8(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU16 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or less than the second.
+ */
+int psCompareDescendingU16(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU32 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or less than the second.
+ */
+int psCompareDescendingU32(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psU64 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or less than the second.
+ */
+int psCompareDescendingU64(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psF32 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or less than the second.
+ */
+int psCompareDescendingF32(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+
+/** Compare function of psF64 data.
+ *
+ *  @return int      an integer less than, equal to, or greater than zero if
+ *                   the first argument is considered to be respectively greater
+ *                   than, equal to, or less than the second.
+ */
+int psCompareDescendingF64(
+    const void *a,                     ///< first comparison target
+    const void *b                      ///< second comparison target
+);
+
+/// @}
+#endif  // #ifndef PS_COMPARE_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psConstants.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psConstants.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psConstants.h	(revision 22158)
@@ -0,0 +1,73 @@
+/* @file  psConstants.h
+ *
+ * @brief Definitions of various constants and common macros
+ *
+ * @author GLG, MHPCC
+ *
+ * @version $Revision: 1.96 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-03-18 18:25:00 $
+ *
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ * XXX: Add parenthesis around all arguments so that these macros can be
+ *      called with complex expressions.
+ *
+ * XXX: All functions which use the PS_ASSERT macros must be scrutinized so
+ * that we ensure that an argument which is expected to be output is
+ * psFree'ed before reurning NULL.
+ *
+ * XXX: The macros have a name similar to PS_CHECK_CONDITION() and generally
+ * throw a psError if the CONDITION is true.  However, some throw the error
+ * if the CONDITION is false.  This should be consistant.
+ *
+ */
+
+#ifndef PS_CONSTANTS_H
+#define PS_CONSTANTS_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+#include <math.h> // for M_PI
+
+/*****************************************************************************
+These are common mathimatical constants used by various functions in the psLib.
+ *****************************************************************************/
+#ifndef M_PI
+#define M_PI   3.1415926535897932384626433832795029  /* pi */
+#define M_PI_2 1.5707963267948966192313216916397514  /* pi/2 */
+#define M_PI_4 0.7853981633974483096156608458198757  /* pi/4 */
+#define M_1_PI 0.3183098861837906715377675267450287  /* 1/pi */
+#define M_2_PI 0.6366197723675813430755350534900574  /* 2/pi */
+#endif // #ifndef M_PI
+
+#define DEG_TO_RAD(DEGREES) ((DEGREES) * M_PI / 180.0)
+#define MIN_TO_RAD(MINUTES) ((MINUTES) * M_PI / (180.0 * 60.0))
+#define SEC_TO_RAD(SECONDS) ((SECONDS) * M_PI / (180.0 * 60.0 * 60.0))
+#define RAD_TO_DEG(RADIANS) ((RADIANS) * 180.0 / M_PI)
+#define RAD_TO_MIN(RADIANS) ((RADIANS) * 180.0 * 60.0 / M_PI)
+#define RAD_TO_SEC(RADIANS) ((RADIANS) * 180.0 * 60.0 * 60.0 / M_PI)
+
+# define PS_DEG_RAD 57.295779513082322
+# define PS_RAD_DEG  0.017453292519943
+
+/*****************************************************************************
+    Misc. macros:
+*****************************************************************************/
+#define PS_MAX(A, B) \
+(((A) > (B)) ? (A) : (B))
+
+#define PS_MIN(A, B) \
+(((A) < (B)) ? (A) : (B))
+
+#define PS_SQR(A) \
+((A) * (A))
+
+#define PS_SWAP(X,Y) {double tmp=(X); (X) = (Y); (Y) = tmp;}
+
+// These defines for bitwise opertaions are necessary to yield results of the proper size (use instead of ~)
+#define PS_NOT_U8(A)(UCHAR_MAX-(A)) // Perform bitwise NOT on A which is of type U8
+#define PS_NOT_U16(A)(USHORT_MAX-(A)) // Perform bitwaise NOT on A which is of type U16
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psEllipse.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psEllipse.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psEllipse.c	(revision 22158)
@@ -0,0 +1,212 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include "psConstants.h"
+#include "psEllipse.h"
+
+// ellipse rotation (major, minor, theta) -> (x2, y2, xy)
+psEllipsePol psEllipseAxesToPol(psEllipseAxes axes)
+{
+    psEllipsePol pol;
+
+    pol.e0 = PS_SQR(axes.major) + PS_SQR(axes.minor);
+    double ds = PS_SQR(axes.major) - PS_SQR(axes.minor);
+
+    pol.e1 = ds*cos(2*axes.theta);
+    pol.e2 = ds*sin(2*axes.theta);
+
+    assert (isfinite(pol.e0));
+    assert (isfinite(pol.e1));
+    assert (isfinite(pol.e2));
+
+    return pol;
+}
+
+// ellipse rotation (major, minor, theta) -> (x2, y2, xy)
+psEllipsePol psEllipseShapeToPol(psEllipseShape shape)
+{
+    psEllipsePol pol;
+
+    double r = 1.0 / (1.0 - PS_SQR(shape.sx)*PS_SQR(shape.sy)*PS_SQR(shape.sxy));
+
+    pol.e0 = r*(PS_SQR(shape.sx) + PS_SQR(shape.sy));
+    pol.e1 = r*(PS_SQR(shape.sx) - PS_SQR(shape.sy));
+    // XXX I do not understand this negative sign
+    pol.e2 = -r*(2.0*PS_SQR(shape.sx)*PS_SQR(shape.sy)*shape.sxy);
+
+    assert (isfinite(pol.e0));
+    assert (isfinite(pol.e1));
+    assert (isfinite(pol.e2));
+
+    return pol;
+}
+
+// ellipse rotation (major, minor, theta) -> (x2, y2, xy)
+// XXXX handle case where e0 < LIMIT
+psErrorCode psEllipsePolToAxes(const psEllipsePol pol,
+			       const float minMinorAxis,
+			       psEllipseAxes *axes)
+{
+    axes->theta = +0.5 * atan2 (pol.e2, pol.e1); // theta in radians
+
+    double cs = cos(2*axes->theta);
+    double sn = sin(2*axes->theta);
+    double ds = 0;
+
+    if ((cs > 0.707) || (cs < -0.707)) {
+	ds = pol.e1 / cs;
+    } else {
+	ds = pol.e2 / sn;
+    }
+
+    float LIMIT = PS_SQR(minMinorAxis);
+    if (pol.e0 < LIMIT) {
+	// if e0 is too small, we are really out of luck
+	axes->major = minMinorAxis;
+	axes->minor = minMinorAxis;
+    } else {
+	if (2.0*(pol.e0 - ds) < LIMIT) {
+	    // if e0 - ds is too small, saturate the minor axis at minMinorAxis
+	    axes->major = sqrt(pol.e0 - LIMIT);
+	    axes->minor = sqrt(LIMIT);
+	} else {
+	    // normal values for e0 & ds
+	    axes->major = sqrt(0.5*(pol.e0 + ds));
+	    axes->minor = sqrt(0.5*(pol.e0 - ds));
+	}
+    }
+
+    if (!isfinite(axes->major) || !isfinite(axes->minor) || !isfinite(axes->theta)) {
+	return psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Shape of object is NaN");
+    }
+
+    return PS_ERR_NONE;
+}
+
+// ellipse rotation (major, minor, theta) -> (x2, y2, xy)
+psEllipseMoments psEllipseAxesToMoments(psEllipseAxes axes)
+{
+    psEllipseMoments moments;
+
+    double f1 = PS_SQR(axes.major) + PS_SQR(axes.minor);
+    double f2 = PS_SQR(axes.major) - PS_SQR(axes.minor);
+
+    moments.x2 = +0.5*f1 + 0.5*f2*cos(2*axes.theta);
+    moments.y2 = +0.5*f1 - 0.5*f2*cos(2*axes.theta);
+    moments.xy = +0.5*f2*sin(2*axes.theta);
+
+    assert (isfinite(moments.x2));
+    assert (isfinite(moments.y2));
+    assert (isfinite(moments.xy));
+
+    return moments;
+}
+
+// ellipse rotation (x2, y2, xy) -> (major, minor, theta)
+psEllipseAxes psEllipseMomentsToAxes(psEllipseMoments moments, double maxAR)
+{
+    psEllipseAxes axes;
+    psEllipseAxes badValue = {NAN, NAN, NAN};
+
+    if (!isfinite(moments.x2)) return badValue;
+    if (!isfinite(moments.y2)) return badValue;
+    if (!isfinite(moments.xy)) return badValue;
+
+    if (moments.x2 < 0) return badValue;
+    if (moments.y2 < 0) return badValue;
+
+    double g1 = moments.x2 + moments.y2;
+    double g2 = moments.x2 - moments.y2;
+    double g3 = sqrt(PS_SQR(g2) + 4*PS_SQR(moments.xy));
+
+    axes.major = sqrt (0.5*(g1 + g3));
+    axes.theta = +0.5 * atan2 (+2.0*moments.xy, g2); // theta in radians
+
+    // long, thin objects are likely to have a poorly measured minor axis
+    // the angle and major axis are likely to be ok.
+    // restrict the axis ratio
+    double rAR2 = (g1 - g3) / (g1 + g3);
+    if (rAR2 < 1.0/PS_SQR(maxAR)) {
+        axes.minor = axes.major / maxAR;
+    } else {
+        axes.minor = sqrt (0.5*(g1 - g3));
+    }
+
+    assert (isfinite(axes.major));
+    assert (isfinite(axes.minor));
+    assert (isfinite(axes.theta));
+
+    return axes;
+}
+
+// ellipse rotation (major, minor, theta) -> (sx, sy, sxy)
+psEllipseShape psEllipseAxesToShape(psEllipseAxes axes)
+{
+    psEllipseShape shape;
+    psEllipseShape badValue = {NAN, NAN, NAN};
+
+    if (!isfinite(axes.minor)) return badValue;
+    if (!isfinite(axes.major)) return badValue;
+    if (!isfinite(axes.theta)) return badValue;
+
+    if (axes.minor <= 0) return badValue;
+    if (axes.major <= 0) return badValue;
+
+    double f1 = 1.0 / PS_SQR(axes.minor) + 1.0 / PS_SQR(axes.major);
+    double f2 = 1.0 / PS_SQR(axes.minor) - 1.0 / PS_SQR(axes.major);
+
+    double sxr = 0.5*f1 - 0.5*f2*cos(2*axes.theta);
+    double syr = 0.5*f1 + 0.5*f2*cos(2*axes.theta);
+
+    // sxr, syr cannot be < 0 (f1 >= f2)
+
+    shape.sx  = +1.0 / sqrt(sxr);
+    shape.sy  = +1.0 / sqrt(syr);
+    shape.sxy = -0.5*f2*sin(2*axes.theta);
+
+    assert (isfinite(shape.sx));
+    assert (isfinite(shape.sy));
+    assert (isfinite(shape.sxy));
+
+    return shape;
+}
+
+// ellipse derotation (sx, sy, sxy) -> (major, minor, theta)
+psEllipseAxes psEllipseShapeToAxes(psEllipseShape shape, double maxAR)
+{
+    psEllipseAxes axes;
+
+    double f1 = 1.0 / PS_SQR(shape.sy) + 1.0 / PS_SQR(shape.sx);
+    double f2 = 1.0 / PS_SQR(shape.sy) - 1.0 / PS_SQR(shape.sx);
+    double f3 = sqrt(PS_SQR(f2) + 4*PS_SQR(shape.sxy));
+
+    axes.minor = sqrt (2.0 / (f1 + f3));
+    axes.theta = -0.5 * atan2 (+2.0*shape.sxy, f2);
+
+    // long, thin objects are likely to have a poorly measured major axis
+    // the angle and minor axis are likely to be ok.
+    // restrict the axis ratio
+    double rAR2 = (f1 - f3) / (f1 + f3);
+    if (rAR2 < 1.0/PS_SQR(maxAR)) {
+        axes.major = axes.minor * maxAR;
+    } else {
+        axes.major = sqrt (2.0 / (f1 - f3));
+    }
+
+    assert (isfinite(axes.theta));
+    assert (isfinite(axes.major));
+    assert (isfinite(axes.minor));
+
+    return axes;
+}
+
+// XXX keep this construction?
+// force the axis ratio to be less than 10
+// double r1 = 0.5*0.95*sqrt (PS_SQR(f1) - PS_SQR(f2));
+
+//    double f = sqrt (0.25*PS_SQR(moments.x2 - moments.y2) + PS_SQR(moments.xy));
+//    if (f > (moments.x2 + moments.y2) / 2.0) {
+//        f = 0.98*(moments.x2 + moments.y2) / 2.0;
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psEllipse.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psEllipse.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psEllipse.h	(revision 22158)
@@ -0,0 +1,84 @@
+/* @file  psEllipse.h
+ * @brief functions to manipulate sparse matrices equations
+ *
+ * $Revision: 1.6 $ $Name: not supported by cvs2svn $
+ * $Date: 2007-12-12 21:01:32 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_ELLIPSE_H
+#define PS_ELLIPSE_H
+
+#include "psError.h"
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+// Different representations of an ellipse
+
+/// Ellipse defined in terms of axes
+typedef struct {
+    double major;                       ///< Major axis
+    double minor;                       ///< Minor axis
+    double theta;                       ///< Position angle
+} psEllipseAxes;
+
+/// Ellipse defined in terms of moments
+typedef struct {
+    double x2;                          ///< Moment of xx (Mxx)
+    double y2;                          ///< Moment of yy (Myy)
+    double xy;                          ///< Moment of xy (Mxy)
+} psEllipseMoments;
+
+/// Ellipse defined in terms of Gaussian shape parameters
+typedef struct {
+    double sx;                          ///< Shape parameter in x
+    double sy;                          ///< Shape parameter in y
+    double sxy;                         ///< Shape parameter in xy
+} psEllipseShape;
+
+/// Ellipse defined in terms of polarisations
+typedef struct {
+    double e0;                          ///< Scale (Mxx + Myy)
+    double e1;                          ///< Polarization 1 (Mxx - Myy)
+    double e2;                          ///< Polarization 1 (2Mxy)
+} psEllipsePol;
+
+// Conversions between elliptical shape representations
+
+/// Convert axes to moments representation
+psEllipseMoments psEllipseAxesToMoments(psEllipseAxes axes ///< Axes of ellipse
+                                        );
+
+/// Convert moments to axes representation
+psEllipseAxes psEllipseMomentsToAxes(psEllipseMoments moments, ///< Moments of ellipse
+                                     double maxAR ///< Maximum allowed axis ratio
+                                     );
+
+/// Convert axes to shape representation
+psEllipseShape psEllipseAxesToShape(psEllipseAxes axes ///< Axes of ellipse
+                                    );
+
+/// Convert shape to axes representation
+psEllipseAxes psEllipseShapeToAxes(psEllipseShape shape, ///< Shape of ellipse
+                                   double maxAR ///< Maximum allowed axis ratio
+                                   );
+
+/// Convert axes to polarisation representation
+psEllipsePol psEllipseAxesToPol(psEllipseAxes axes ///< Axes of ellipse
+                                );
+
+/// Convert shape to polarisation representation
+psEllipsePol psEllipseShapeToPol(psEllipseShape shape ///< Shape of ellipse
+                                 );
+
+/// Convert polarisation to axes representation
+///
+/// XXX This API goes against the PS convention of outputs being first.
+psErrorCode psEllipsePolToAxes(const psEllipsePol pol, ///< Polarisation of ellipse
+                               const float minMinorAxis, ///< Minimum allowed minor axis
+                               psEllipseAxes *axes ///< Output ellipse axes
+                               );
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psHistogram.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psHistogram.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psHistogram.c	(revision 22158)
@@ -0,0 +1,352 @@
+/** @file  psHistogram.h
+ *  \brief basic histogram functions
+ *  @ingroup Math
+ *
+ *  @author GLG (MHPCC), EAM (IfA)
+ *
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-05-07 23:11:30 $
+ *
+ *  Copyright 2006 IfA, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <float.h>
+#include <math.h>
+#include <limits.h>
+#include <strings.h>
+
+/*****************************************************************************/
+/* INCLUDE FILES                                                             */
+/*****************************************************************************/
+#include "psMemory.h"
+#include "psAbort.h"
+//#include "psImage.h"
+#include "psVector.h"
+#include "psTrace.h"
+#include "psLogMsg.h"
+#include "psError.h"
+#include "psStats.h"
+#include "psHistogram.h"
+#include "psAssert.h"
+#include "psMathUtils.h"
+//#include "psList.h"
+//#include "psString.h"
+
+static void histogramFree(psHistogram* myHist);
+
+/******************************************************************************
+psHistogramAlloc(lower, upper, n): allocate a uniform histogram structure
+with the specifed upper and lower limits, and the specifed number of bins.
+This routine will also set the bounds for each of the bins.
+
+Input:
+    lower
+    upper
+    n
+Returns:
+    The histogram structure
+ *****************************************************************************/
+psHistogram* psHistogramAlloc(float lower, float upper, int n)
+{
+    psTrace("psLib.math", 3, "---- %s() begin  ----\n", __func__);
+    psTrace("psLib.math", 5, "(lower, upper, n) is (%f, %f, %d)\n", lower, upper, n);
+    PS_ASSERT_INT_POSITIVE(n, NULL);
+    PS_ASSERT_FLOAT_LARGER_THAN_OR_EQUAL(upper, lower, NULL);
+
+    // Allocate memory for the new histogram structure.  If there are N bins, then there are N+1 bounds to
+    // those bins.
+    psHistogram *newHist = (psHistogram* ) psAlloc(sizeof(psHistogram)); // The new histogram structure
+    psMemSetDeallocator(newHist, (psFreeFunc) histogramFree);
+    psVector* newBounds = psVectorAlloc(n + 1, PS_TYPE_F32);
+    newHist->bounds = newBounds;
+
+    // Calculate the bounds for each bin.
+    psF32 binSize = (upper - lower) / (psF32)n; // The histogram bin size
+    // XXX: Is the following necessary? It prevents the max data point from being in a non-existant bin.
+    binSize += FLT_EPSILON;
+    for (long i = 0; i < n + 1; i++) {
+        newBounds->data.F32[i] = lower + (binSize * (psF32)i);
+    }
+
+    // Allocate the bins, and initialize them to zero.
+    newHist->nums = psVectorAlloc(n, PS_TYPE_F32);
+    psVectorInit(newHist->nums, 0.0);
+
+    // Initialize the other members.
+    newHist->minNum = 0;
+    newHist->maxNum = 0;
+    newHist->uniform = true;
+
+    psTrace("psLib.math", 3, "---- %s() end  ----\n", __func__);
+    return newHist;
+}
+
+/******************************************************************************
+psHistogramAllocGeneric(bounds): allocate a non-uniform histogram structure
+with the specifed bounds.
+
+Input:
+    bounds
+Returns:
+    The histogram structure
+ *****************************************************************************/
+psHistogram* psHistogramAllocGeneric(const psVector* bounds)
+{
+    psTrace("psLib.math", 3, "---- %s() begin  ----\n", __func__);
+    PS_ASSERT_VECTOR_NON_NULL(bounds, NULL);
+    PS_ASSERT_VECTOR_TYPE(bounds, PS_TYPE_F32, NULL);
+    PS_ASSERT_LONG_LARGER_THAN_OR_EQUAL(bounds->n, (long)2, NULL);
+
+    // Allocate memory for the new histogram structure.
+    psHistogram *newHist = (psHistogram* ) psAlloc(sizeof(psHistogram)); // The new histogram structure
+    psMemSetDeallocator(newHist, (psFreeFunc) histogramFree);
+    psVector* newBounds = psVectorCopy(NULL, bounds, PS_TYPE_F32);
+    newHist->bounds = newBounds;
+
+    // Allocate the bins, and initialize them to zero.  If there are N bounds,
+    // then there are N-1 bins.
+    newHist->nums = psVectorAlloc((bounds->n) - 1, PS_TYPE_F32);
+    psVectorInit(newHist->nums, 0.0);
+
+    // Initialize the other members.
+    newHist->minNum = 0;
+    newHist->maxNum = 0;
+    newHist->uniform = false;
+
+    psTrace("psLib.math", 3, "---- %s() end  ----\n", __func__);
+    return (newHist);
+}
+
+static void histogramFree(psHistogram* myHist)
+{
+    psFree((void *)myHist->bounds);
+    psFree(myHist->nums);
+}
+
+
+bool psMemCheckHistogram(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)histogramFree );
+}
+
+/*****************************************************************************
+UpdateHistogramBins(binNum, out, data, error): This routine is to be used when
+updating the histogram in the presence of errors in the input data.  We treat
+the data point as a boxcar PDF and update a range of points surrounding the
+histogram bin which contains the point.  The width of that boxcar is defined
+as 2.35 * error.
+
+XXX: Must test this.
+ *****************************************************************************/
+static bool UpdateHistogramBins(long binNum, // Bin number of the data point
+                                psHistogram* out, // The histogram to be updated
+                                psF32 data, // The data point value
+                                psF32 error // The error in the data point
+                               )
+{
+    psTrace("psLib.math", 3, "---- %s() begin  ----\n", __func__);
+    PS_ASSERT_PTR_NON_NULL(out, false);
+    PS_ASSERT_PTR_NON_NULL(out->bounds, false);
+    PS_ASSERT_PTR_NON_NULL(out->nums, false);
+    PS_ASSERT_LONG_WITHIN_RANGE(binNum, (long)0, (long)((out->nums->n)-1), false);
+    PS_ASSERT_FLOAT_LARGER_THAN_OR_EQUAL(error, 0.0, false);
+    PS_ASSERT_FLOAT_WITHIN_RANGE(data, out->bounds->data.F32[0],
+                                 out->bounds->data.F32[(out->bounds->n)-1], false);
+
+    psF32 boxcarWidth = 2.35 * error;   // Width of the boxcar
+    psF32 boxcarCenter = (out->bounds->data.F32[binNum] +
+                          out->bounds->data.F32[binNum+1]) / 2.0; // Centre of the boxcar
+    psF32 boxcarLeft = boxcarCenter - (boxcarWidth / 2.0); // Left endpoint of the boxcar for the PDF
+    psF32 boxcarRight = boxcarCenter + (boxcarWidth / 2.0); // Right endpoint of the boxcar for the PDF
+    psS32 boxcarLeftBinNum = 0;         // Bin number for left endpoint
+    psS32 boxcarRightBinNum = 0;        // Bin number for right endpoint
+
+    // Determine the left endpoint of the boxcar for the PDF.
+    for (long bin = binNum; bin >= 0; bin--) {
+        if (out->nums->data.F32[bin] <= boxcarLeft) {
+            boxcarLeftBinNum = bin;
+            break;
+        }
+    }
+
+    // Determine the right endpoint of the boxcar for the PDF.
+    for (long bin = binNum; bin < out->nums->n; bin++) {
+        if (out->nums->data.F32[bin] >= boxcarRight) {
+            boxcarRightBinNum = bin;
+            break;
+        }
+    }
+
+    // If the boxcar fits entirely inside this bin, then simply add 1.0 to the
+    // bin and return.
+    if (boxcarLeftBinNum == boxcarRightBinNum) {
+        out->nums->data.F32[binNum] += 1.0;
+        psTrace("psLib.math", 3, "---- %s(true) end  ----\n", __func__);
+        return true;
+    }
+
+    // If we get here, multiple bins must be updated.  We handle the left-most endpoint, and right-most
+    // endpoints differently.
+    out->nums->data.F32[boxcarLeftBinNum] +=
+        (out->bounds->data.F32[boxcarLeftBinNum+1] - boxcarLeft) / boxcarWidth;
+
+    // Loop through the center bins, if any.
+    for (long bin = boxcarLeftBinNum + 1; bin < (boxcarRightBinNum - 1); bin++) {
+        out->nums->data.F32[bin] +=
+            (out->bounds->data.F32[bin+1] - out->bounds->data.F32[bin]) / boxcarWidth;
+    }
+
+    // Handle the right endpoint differently.
+    out->nums->data.F32[boxcarRightBinNum]+=
+        (boxcarRight - out->bounds->data.F32[boxcarRightBinNum]) / boxcarWidth;
+
+    psTrace("psLib.math", 3, "---- %s(true) end  ----\n", __func__);
+    return true;
+}
+
+/*****************************************************************************
+psVectorHistogram(out, in, errors, mask, maskVal): this procedure takes as
+input a preallocated and initialized histogram structure.  It fills the bins
+in that histogram structure in accordance with the input data "in" and the,
+possibly NULL, mask vector.
+
+Inputs:
+    out
+    in
+    mask
+    maskVal
+Returns:
+    The histogram structure "out".
+ *****************************************************************************/
+bool psVectorHistogram(psHistogram* out,
+                               const psVector* values,
+                               const psVector* errors,
+                               const psVector* mask,
+                               psMaskType maskVal)
+{
+    psTrace("psLib.math", 3, "---- %s() begin  ----\n", __func__);
+    PS_ASSERT_PTR_NON_NULL(out, false);
+    PS_ASSERT_VECTOR_NON_NULL(out->bounds, false);
+    PS_ASSERT_VECTOR_TYPE(out->bounds, PS_TYPE_F32, false);
+    PS_ASSERT_INT_NONNEGATIVE(out->bounds->n, false);
+    PS_ASSERT_VECTOR_NON_NULL(out->nums, false);
+    PS_ASSERT_VECTOR_TYPE(out->nums, PS_TYPE_F32, false);
+    PS_ASSERT_INT_NONNEGATIVE(out->nums->n, false);
+    PS_ASSERT_VECTOR_NON_NULL(values, out);
+    if (mask) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(values, mask, false);
+        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
+    }
+    if (errors) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(values, errors, false);
+        PS_ASSERT_VECTOR_TYPE(errors, values->type.type, false);
+    }
+
+    long binNum = 0;                    // A temporary bin number
+    long numBins = out->nums->n;        // The total number of bins
+    psScalar tmpScalar;
+    tmpScalar.type.type = PS_TYPE_F32;
+
+    // Convert input and errors vectors to F32 if necessary.
+    psVector* inF32 = NULL;             // F32 version of input vector
+    if (values->type.type == PS_TYPE_F32) {
+        inF32 = psMemIncrRefCounter((psPtr)values);
+    } else {
+        inF32 = psVectorCopy(NULL, values, PS_TYPE_F32);
+    }
+    psVector* errorsF32 = NULL;         // F32 version of errors vector
+    if (errors) {
+        if (errors->type.type == PS_TYPE_F32) {
+            errorsF32 = psMemIncrRefCounter((psPtr)errors);
+        } else {
+            errorsF32 = psVectorCopy(NULL, errors, PS_TYPE_F32);
+        }
+    }
+
+    for (long i = 0; i < inF32->n; i++) {
+        // Check if this pixel is masked, and if so, skip it.
+        if (!mask || (mask && (!(mask->data.U8[i] & maskVal)))) {
+            if (inF32->data.F32[i] < out->bounds->data.F32[0]) {
+                // If this pixel is below minimum value, count it, then skip.
+                out->minNum++;
+            } else if (inF32->data.F32[i] > out->bounds->data.F32[numBins]) {
+                // If this pixel is above maximum value, count it, then skip.
+                out->maxNum++;
+            } else {
+                // If this is a uniform histogram, determining the correct bin
+                // number is almost trivial.  start with a guess from the uniform scale.
+                if (out->uniform == true) {
+                    double binSize = (out->bounds->data.F32[out->nums->n] - out->bounds->data.F32[0]) / (float) out->nums->n; // Histogram bin size
+                    binNum = (inF32->data.F32[i] - out->bounds->data.F32[0]) / binSize;
+		    binNum = PS_MAX (binNum, 0);
+		    binNum = PS_MIN (binNum, numBins - 1);
+
+		    // value is in bin 'i' if bound[i] <= value < bound[i]
+
+		    // we may slightly overshoot or undershoot.  creep up or down on the true bin
+		    if (inF32->data.F32[i] < out->bounds->data.F32[binNum]) {
+			psTrace("psLib.math", 6, "missed target bin, adjusting: %f vs %f to %f\n", inF32->data.F32[i], out->bounds->data.F32[binNum], out->bounds->data.F32[binNum+1]);
+			while ((inF32->data.F32[i] < out->bounds->data.F32[binNum]) && (binNum > 0)) {
+			    binNum --;
+			}
+			
+		    }
+		    if (inF32->data.F32[i] >= out->bounds->data.F32[binNum+1]) {
+			psTrace("psLib.math", 6, "missed target bin, adjusting: %f vs %f to %f\n", inF32->data.F32[i], out->bounds->data.F32[binNum], out->bounds->data.F32[binNum+1]);
+			while ((inF32->data.F32[i] >= out->bounds->data.F32[binNum+1]) && (binNum < numBins - 1)) {
+			    binNum ++;
+			}
+		    }
+
+                    if (errorsF32) {
+                        if (!UpdateHistogramBins(binNum, out, inF32->data.F32[i], errorsF32->data.F32[i])) {
+                            psLogMsg(__func__, PS_LOG_WARN, "WARNING: Failed to update the histogram "
+                                     "bins with the errors vector.\n");
+                        }
+                    } else {
+                        // This if-statement really shouldn't be necessary.
+                        // However, due to numerical lack of precision, we
+                        // occasionally produce a binNum outside the range.
+                        if (binNum >= out->nums->n) {
+                            binNum = out->nums->n - 1;
+                        }
+                        (out->nums->data.F32[binNum])+= 1.0;
+                    }
+
+                } else {
+                    // If this is a non-uniform histogram, determining the
+                    // correct bin number requires a bit more work.
+                    tmpScalar.data.F32 = inF32->data.F32[i];
+		    psVectorBinaryDisectResult result;
+                    binNum = psVectorBinaryDisect(&result, out->bounds, &tmpScalar);
+		    if (result != PS_BINARY_DISECT_PASS) {
+			continue;
+		    }
+		    if (errorsF32 != NULL) {
+			if (!UpdateHistogramBins(binNum, out, inF32->data.F32[i], errors->data.F32[i])) {
+			    psLogMsg(__func__, PS_LOG_WARN, "WARNING: Failed to update the histogram "
+				     "bins with the errors vector.\n");
+			}
+		    } else {
+			out->nums->data.F32[binNum] += 1.0;
+		    }
+                }
+            }
+        }
+    }
+
+    psFree(inF32);
+    psFree(errorsF32);
+
+    psTrace("psLib.math", 3, "---- %s() end  ----\n", __func__);
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psHistogram.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psHistogram.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psHistogram.h	(revision 22158)
@@ -0,0 +1,94 @@
+/* @file  psHistogram.h
+ * @brief basic histogram functions
+ *
+ * This file holds the definition of the histogram data structures.  It also contains
+ * prototypes for procedures which operate on those data structures.
+ *
+ * @author GLG, MHPCC
+ *
+ * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-08-09 01:40:07 $
+ *
+ * Copyright 2004-2005 IfA, University of Hawaii
+ */
+
+#ifndef PS_HISTOGRAM_H
+#define PS_HISTOGRAM_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+/******************************************************************************
+    Histogram functions and data structures.
+ *****************************************************************************/
+
+/** The basic histogram structure which contains bounds and bins.
+ *
+ *  In this structure, the vector bounds specifies the boundaries of the
+ *  histogram bins, and must of type psF32, while nums specifies the number
+ *  of entries in the bin, and must of type psU32. The value of bounds.n must
+ *  therefore be 1 greater than than nums.n. The two values minNum and maxNum
+ *  are the number of data values which fell below the lower limit bound or
+ *  above the upper limit bound, respectively.
+ */
+typedef struct
+{
+    const psVector* bounds;            ///< Bounds for the bins (type F32)
+    psVector* nums;                    ///< Number in each of the bins (INT)
+    int minNum;                        ///< Number below the minimum
+    int maxNum;                        ///< Number above the maximum
+    bool uniform;                      ///< Is it a uniform distribution?
+}
+psHistogram;
+
+/** Allocator for psHistogram where the bounds of the bins are implicitly
+ *  specified through simply specifying an upper and lower limit along with
+ *  the size of the bins.
+ *
+ *  @return psHistogram*    Newly allocated psHistogram
+ */
+psHistogram* psHistogramAlloc(
+    float lower,                       ///< Lower limit for the bins
+    float upper,                       ///< Upper limit for the bins
+    int n                              ///< Number of bins
+) PS_ATTR_MALLOC;
+
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psHistogram structure, false otherwise.
+ */
+bool psMemCheckHistogram(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+
+/** Allocator for psHistogram where the bounds of the bins are explicitly
+ *  specified.
+ *
+ *  @return psHistogram*    Newly allocated psHistogram
+ */
+psHistogram* psHistogramAllocGeneric(
+    const psVector* bounds             ///< Bounds for the bins
+);
+
+/** Calculate a histogram
+ *
+ *  The following function populates the histogram bins from the specified
+ *  vector (in). It alters and returns the histogram out structure. The input
+ *  vector may be of types psU8, psU16, psF32, psF64.
+ *
+ *  @return bool   Successful operation?
+ */
+bool psVectorHistogram(
+    psHistogram* out,                  ///< Histogram data
+    const psVector* values,            ///< Vector to analyse
+    const psVector* errors,            ///< Errors
+    const psVector* mask,              ///< Mask dat for input vector
+    psMaskType maskVal                 ///< Mask value
+);
+
+/// @}
+#endif // #ifndef PS_HISTOGRAM_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMD5.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMD5.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMD5.c	(revision 22158)
@@ -0,0 +1,78 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "md5.h"
+
+#include "psAssert.h"
+#include "psMemory.h"
+#include "psString.h"
+#include "psVector.h"
+#include "psImage.h"
+#include "psError.h"
+#include "psMD5.h"
+
+
+#define MD5_DIGEST_LENGTH 16            // Length of an MD5 digest, in bytes
+
+psVector *psStringMD5(const char *string)
+{
+    psVector *hash = psVectorAlloc(MD5_DIGEST_LENGTH, PS_TYPE_U8); // The resultant MD5 hash
+    md5_state_t buffer;                 // Calculation buffer
+    md5_init(&buffer);
+    md5_append(&buffer, (psU8*)string, strlen(string));
+    md5_finish(&buffer, &hash->data.U8[0]);
+    return hash;
+}
+
+psVector *psVectorMD5(const psVector *vector)
+{
+    PS_ASSERT_VECTOR_NON_NULL(vector, NULL);
+
+    psVector *hash = psVectorAlloc(MD5_DIGEST_LENGTH, PS_TYPE_U8); // The resultant MD5 hash
+    md5_state_t buffer;                 // Calculation buffer
+    md5_init(&buffer);
+    md5_append(&buffer, vector->data.U8, vector->n * PSELEMTYPE_SIZEOF(vector->type.type));
+    md5_finish(&buffer, &hash->data.U8[0]);
+    return hash;
+}
+
+
+psVector *psImageMD5(const psImage *image)
+{
+    PS_ASSERT_IMAGE_NON_NULL(image, NULL);
+
+    psVector *hash = psVectorAlloc(MD5_DIGEST_LENGTH, PS_TYPE_U8); // The resultant MD5 hash
+    md5_state_t buffer;                 // Calculation buffer
+    md5_init(&buffer);
+    if (!image->parent) {
+        // No parent means image is contiguous
+        md5_append(&buffer, image->data.U8[0],
+                   image->numCols * image->numRows * PSELEMTYPE_SIZEOF(image->type.type));
+    } else {
+        for (int row = 0; row < image->numRows; row++) {
+            md5_append(&buffer, image->data.U8[row],
+                       image->numCols * PSELEMTYPE_SIZEOF(image->type.type));
+        }
+    }
+    md5_finish(&buffer, &hash->data.U8[0]);
+
+    return hash;
+}
+
+
+psString psMD5toString(const psVector *hash)
+{
+    PS_ASSERT_VECTOR_NON_NULL(hash, NULL);
+    PS_ASSERT_VECTOR_SIZE(hash, (long int)MD5_DIGEST_LENGTH, NULL);
+    PS_ASSERT_VECTOR_TYPE(hash, PS_TYPE_U8, NULL);
+
+    psString string = psStringAlloc(MD5_DIGEST_LENGTH * 2 + 1); // String to return
+    for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {
+        sprintf(string + i * 2, "%02x", hash->data.U8[i]);
+    }
+    return string;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMD5.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMD5.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMD5.h	(revision 22158)
@@ -0,0 +1,42 @@
+/* @file  psMD5.h
+ * @brief support for MD5 hashes
+ *
+ * $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ * $Date: 2007-01-23 22:47:23 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_MD5_H
+#define PS_MD5_h
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+#include "psVector.h"
+#include "psString.h"
+#include "psImage.h"
+
+/// Return an MD5 hash of the supplied string.
+///
+/// The MD5 hash is returned in a U8 vector of size 16.
+psVector *psStringMD5(const char *string   ///< String to hash
+                     );
+
+/// Return an MD5 hash of the supplied vector.
+///
+/// The MD5 hash is returned in a U8 vector of size 16.
+psVector *psVectorMD5(const psVector *vector ///< Vector to hash
+                     );
+
+/// Return an MD5 hash of the supplied image.
+///
+/// The MD5 hash is returned in a U8 vector of size 16.
+psVector *psImageMD5(const psImage *image ///< Image to hash
+                    );
+
+/// Convert an MD5 hash into a string, for printing.
+psString psMD5toString(const psVector *hash ///< Hash to stringify
+                      );
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMathUtils.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMathUtils.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMathUtils.c	(revision 22158)
@@ -0,0 +1,316 @@
+/** @file psMathUtils.c
+ *
+ *  This file contains standard math routines.
+ *
+ *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-05-07 23:11:58 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/*****************************************************************************/
+/*  INCLUDE FILES                                                            */
+/*****************************************************************************/
+#include <stdio.h>
+#include <stdbool.h>
+#include <float.h>
+#include <math.h>
+#include "psMemory.h"
+#include "psVector.h"
+#include "psScalar.h"
+#include "psTrace.h"
+#include "psError.h"
+#include "psLogMsg.h"
+#include "psPolynomial.h"
+#include "psMathUtils.h"
+#include "psAssert.h"
+#include "psConstants.h"
+#include "psAbort.h"
+
+/*****************************************************************************/
+/* DEFINE STATEMENTS                                                         */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* TYPE DEFINITIONS                                                          */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* GLOBAL VARIABLES                                                          */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* FILE STATIC VARIABLES                                                     */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* FUNCTION IMPLEMENTATION - LOCAL                                           */
+/*****************************************************************************/
+
+/*****************************************************************************
+This is a macro covering the various types for the below function.
+ *****************************************************************************/
+#define VECTOR_BINARY_DISECT_CASE(TYPE) \
+case PS_TYPE_##TYPE: { \
+    ps##TYPE *bounds = bins->data.TYPE; \
+    ps##TYPE value = x->data.TYPE; \
+    long min; \
+    long max; \
+    long mid; \
+    psTrace("psLib.math", 5, "---- () begin ----\n"); \
+    psTrace("psLib.math", 4, "Determining the bin for: %f\n", (float) value); \
+    if (value < bounds[0]) { \
+        psTrace("psLib.math", 3, \
+                 "psVectorBinaryDisect : ordinate %f is outside vector range (%f - %f).", \
+                 (double)value, (double)bounds[0], (double)bounds[numBins-1]); \
+        *status = PS_BINARY_DISECT_OUTSIDE_RANGE; \
+        return (0); \
+    } \
+    if (value > bounds[numBins-1]) { \
+        psTrace("psLib.math", 3, \
+                 "psVectorBinaryDisect : ordinate %f is outside vector range (%f - %f).", \
+                 (double)value, (double)bounds[0], (double)bounds[numBins-1]); \
+        *status = PS_BINARY_DISECT_OUTSIDE_RANGE; \
+        return (numBins-1); \
+    } \
+    \
+    min = 0; \
+    max = numBins-2; \
+    mid = ((max+1)-min)/2; \
+    while (min != max) { \
+        \
+        if (value == bounds[mid]) { \
+            psTrace("psLib.math", 4, "found %ld\n", mid); \
+            psTrace("psLib.math", 5, "---- %s(%ld) end (1) ----\n", __func__, mid); \
+            return(mid); \
+        } else if (value < bounds[mid]) { \
+            max = mid-1; \
+        } else { \
+            min = mid; \
+        } \
+        mid = ((max+1)+min)/2; \
+    } \
+    psTrace("psLib.math", 5, "---- %s(%ld) end (2) ----\n", __func__, min); \
+    return(min); \
+}
+
+/*****************************************************************************
+psVectorBinDisect(): This function takes as input an array of data as well as a single value for that data.
+The input vector values are assumed to be non-decreasing (v[i-1] <= v[i] for all i).  This routine does a
+binary disection of the vector and returns "i" such that (v[i] <= x < v[i+1).  If x lies outside the range of
+v[], then this routine prints a warning message and returns (-2 or -1).
+  *****************************************************************************/
+psS32 psVectorBinaryDisect(
+    psVectorBinaryDisectResult *status,
+    const psVector *bins,
+    const psScalar *x)
+{
+    assert (status);
+    PS_ASSERT_GENERAL_VECTOR_NON_NULL (bins, *status = PS_BINARY_DISECT_INVALID_INPUT; return 0);
+    PS_ASSERT_GENERAL_VECTOR_NON_EMPTY(bins, *status = PS_BINARY_DISECT_INVALID_INPUT; return 0);
+    PS_ASSERT_GENERAL_PTR_NON_NULL(x, *status = PS_BINARY_DISECT_INVALID_INPUT; return 0);
+    PS_ASSERT_GENERAL_PTR_TYPE_EQUAL(x, bins, *status = PS_BINARY_DISECT_INVALID_INPUT; return 0);
+    long numBins = bins->n;             // Number of bins
+
+    *status = PS_BINARY_DISECT_PASS;
+
+    switch (x->type.type) {
+        VECTOR_BINARY_DISECT_CASE(S8);
+        VECTOR_BINARY_DISECT_CASE(S16);
+        VECTOR_BINARY_DISECT_CASE(S32);
+        VECTOR_BINARY_DISECT_CASE(S64);
+        VECTOR_BINARY_DISECT_CASE(U8);
+        VECTOR_BINARY_DISECT_CASE(U16);
+        VECTOR_BINARY_DISECT_CASE(U32);
+        VECTOR_BINARY_DISECT_CASE(U64);
+	VECTOR_BINARY_DISECT_CASE(F32);
+        VECTOR_BINARY_DISECT_CASE(F64);
+    default: {
+            char* strType;
+            PS_TYPE_NAME(strType, x->type.type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, "psLib type %s is not supported.", strType);
+	    *status = PS_BINARY_DISECT_INVALID_TYPE;
+            return 0;
+        }
+    }
+    psAbort ("programming error");
+    return (0);
+}
+
+
+/*************************************************************************************************************
+Helper macro for p_psVectorInterpolate: handles each of the types
+*************************************************************************************************************/
+#define VECTOR_INTERPOLATE_CASE(TYPE) \
+case PS_TYPE_##TYPE: { \
+    psTrace("psLib.math", 4, "---- %s() begin %u-order.) (%d data points) ----\n", __func__, order, order+1); \
+    if (x->data.TYPE < domain->data.TYPE[0]) { \
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: x is outside the domain of input data.\n"); \
+        out->data.TYPE = range->data.TYPE[0]; \
+        return(out); \
+    } \
+    if (x->data.TYPE > domain->data.TYPE[domain->n-1]) { \
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: x is outside the domain of input data.\n"); \
+        out->data.TYPE = range->data.TYPE[domain->n-1]; \
+        return(out); \
+    } \
+    psVector *p = psVectorCopy(NULL, range, PS_TYPE_##TYPE); \
+    psVectorBinaryDisectResult result; \
+    psS32 binNum = psVectorBinaryDisect(&result, domain, x); \
+    \
+    psS32 numIntPoints = order+1; \
+    psS32 origin; \
+    if (0 == numIntPoints%2) { \
+        origin = binNum - ((numIntPoints/2) - 1); \
+    } else { \
+        origin = binNum - (numIntPoints/2); \
+        if ((x->data.TYPE-domain->data.TYPE[binNum]) > (domain->data.TYPE[binNum+1]-x->data.TYPE)) { \
+            /* x is closer to binNum+1. */\
+            origin = 1 + (binNum - (numIntPoints/2)); \
+        } \
+    } \
+    origin = PS_MAX(origin, 0); \
+    origin = PS_MIN(origin, (domain->n - numIntPoints)); \
+    \
+    /* From NR, during each iteration of the m loop, we are computing the p_{i ... i+m} terms. */ \
+    for (psU32 m = 1 ; m < numIntPoints ; m++) { \
+        for (psU32 i = origin ; i < (numIntPoints+origin-m) ; i++) { \
+            p->data.TYPE[i] = (((x->data.TYPE - domain->data.TYPE[i+m]) * p->data.TYPE[i]) + \
+                               ((domain->data.TYPE[i] - x->data.TYPE) * p->data.TYPE[i+1])) / \
+                              (domain->data.TYPE[i] - domain->data.TYPE[i+m]); \
+        } \
+    } \
+    out->data.TYPE = p->data.TYPE[origin]; \
+    psFree(p); \
+    psTrace("psLib.math", 4, "---- %s(....) end ----\n", __func__); \
+    return(out); \
+}
+
+/*****************************************************************************
+p_psVectorInterpolate(): This routine will take as input psVectors domain and
+range, and the x value, assumed to lie with the domain vector.  It produces
+as output the LaGrange interpolated value of a polynomial of the specified
+order around the point x.
+ 
+XXX: This stuff does not currently work with a mask.
+ *****************************************************************************/
+psScalar *p_psVectorInterpolate(
+    psScalar *out,
+    const psVector *domain,
+    const psVector *range,
+    psS32 order,
+    const psScalar *x)
+{
+    psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_VECTOR_NON_NULL(domain, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(range, NULL);
+    PS_ASSERT_PTR_NON_NULL(x, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(order, NULL);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(domain, range, NULL);
+    PS_ASSERT_PTR_TYPE_EQUAL(domain, range, NULL);
+    PS_ASSERT_PTR_TYPE_EQUAL(domain, x, NULL);
+    if (!out) {
+        out = psScalarAlloc(0, x->type.type);
+    } else {
+        PS_ASSERT_PTR_TYPE_EQUAL(domain, out, NULL);
+    }
+
+    switch (x->type.type) {
+        VECTOR_INTERPOLATE_CASE(U8);
+        VECTOR_INTERPOLATE_CASE(U16);
+        VECTOR_INTERPOLATE_CASE(U32);
+        VECTOR_INTERPOLATE_CASE(U64);
+        VECTOR_INTERPOLATE_CASE(S8);
+        VECTOR_INTERPOLATE_CASE(S16);
+        VECTOR_INTERPOLATE_CASE(S32);
+        VECTOR_INTERPOLATE_CASE(S64);
+        VECTOR_INTERPOLATE_CASE(F32);
+        VECTOR_INTERPOLATE_CASE(F64);
+    default: {
+            char* strType;
+            PS_TYPE_NAME(strType, x->type.type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, "psLib type %s is not supported.", strType);
+            return NULL;
+        }
+    }
+
+    return NULL;
+}
+
+/*****************************************************************************
+Helper macro for p_psNormalizeVectorRange: handles each of the types
+ *****************************************************************************/
+#define NORMALIZE_VECTOR_RANGE_CASE(TYPE) \
+case PS_TYPE_##TYPE: { \
+    ps##TYPE low = outLow; \
+    ps##TYPE high = outHigh; \
+    ps##TYPE min = (ps##TYPE)PS_MAX_##TYPE; \
+    ps##TYPE max = (ps##TYPE)-PS_MAX_##TYPE; \
+    \
+    for (long i = 0; i < myData->n; i++) { \
+        if (myData->data.TYPE[i] < min) { \
+            min = myData->data.TYPE[i]; \
+        } \
+        if (myData->data.TYPE[i] > max) { \
+            max = myData->data.TYPE[i]; \
+        } \
+    } \
+    \
+    /* Ensure that max!=min before we divide by (max-min) */ \
+    if (max != min) { \
+        for (long i = 0; i < myData->n; i++) { \
+            myData->data.TYPE[i] = (low + (myData->data.TYPE[i] - min) * \
+                                    (high - low) / (max - min)); \
+        } \
+    } else { \
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: (max==min).  Setting all elements to min.\n"); \
+        for (long i = 0; i < myData->n; i++) \
+        { \
+            \
+            myData->data.TYPE[i] = low; \
+            \
+        } \
+    } \
+    break; \
+} \
+
+/*************************************************************************************************************
+p_psNormalizeVectorRange(myData, low, high): this function normalises the vector (myData) to the range
+low:
+high.
+*************************************************************************************************************/
+bool p_psNormalizeVectorRange(psVector* myData,
+                              psF64 outLow,
+                              psF64 outHigh)
+{
+    PS_ASSERT_VECTOR_NON_NULL(myData, false);
+    psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__);
+
+    switch (myData->type.type) {
+        NORMALIZE_VECTOR_RANGE_CASE(U8);
+        NORMALIZE_VECTOR_RANGE_CASE(U16);
+        NORMALIZE_VECTOR_RANGE_CASE(U32);
+        NORMALIZE_VECTOR_RANGE_CASE(U64);
+        NORMALIZE_VECTOR_RANGE_CASE(S8);
+        NORMALIZE_VECTOR_RANGE_CASE(S16);
+        NORMALIZE_VECTOR_RANGE_CASE(S32);
+        NORMALIZE_VECTOR_RANGE_CASE(S64);
+        NORMALIZE_VECTOR_RANGE_CASE(F32);
+        NORMALIZE_VECTOR_RANGE_CASE(F64);
+    default: {
+            char* strType;
+            PS_TYPE_NAME(strType, myData->type.type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, "psLib type %s is not supported.", strType);
+            break;
+        }
+    }
+    psTrace("psLib.math", 4, "---- %s() end ----\n", __func__);
+    return true;
+}
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMathUtils.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMathUtils.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMathUtils.h	(revision 22158)
@@ -0,0 +1,63 @@
+/* @file psMathUtils.h
+ * @brief Standard Mathematical Functions.
+ *
+ * This file contains standard math rotines.
+ *
+ * @author GLG, MHPCC
+ *
+ * @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-03-14 02:36:28 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_MATHUTILS_H
+#define PS_MATHUTILS_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <float.h>
+#include <math.h>
+#include "psVector.h"
+#include "psScalar.h"
+#include "psPolynomial.h"
+
+typedef enum {
+    PS_BINARY_DISECT_PASS,
+    PS_BINARY_DISECT_OUTSIDE_RANGE,
+    PS_BINARY_DISECT_INVALID_INPUT,
+    PS_BINARY_DISECT_INVALID_TYPE,
+} psVectorBinaryDisectResult;
+
+/** Performs a binary disection on a monotonically non-decreasing vector.
+ *  Searches through an array of data for a specified value.
+ *
+ *  @return psS32    corresponding index number of specified value
+ */
+psS32 psVectorBinaryDisect(
+    psVectorBinaryDisectResult *status,
+    const psVector *bins,               ///< Array of non-decreasing values
+    const psScalar *x                   ///< Target value to find
+);
+
+/** Interpolates a series of data points for evaluation at a specific coordinate.  Uses a
+ *  Lagrange interpolation method.
+ *
+ *  @return psScalar*    Lagrange interpolation value at given location
+ */
+psScalar *p_psVectorInterpolate(
+    psScalar *out,                      ///< Output scalar, or NULL
+    const psVector *domain,             ///< Domain (x coords) for interpolation
+    const psVector *range,              ///< Range (y coords) for interpolation
+    psS32 order,                        ///< Order of interpolation function
+    const psScalar *x                   ///< Location at which to evaluate
+);
+
+bool p_psNormalizeVectorRange(psVector* myData,
+                              psF64 outLow,
+                              psF64 outHigh);
+
+/// @}
+#endif // #ifndef PS_MATHUTILS_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMatrix.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMatrix.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMatrix.c	(revision 22158)
@@ -0,0 +1,785 @@
+/** @file  psMatrix.c
+ *
+ *  @brief Provides functions for linear algebra operations on psImages and psVectors.
+ *
+ *  Functions are provided to:
+ *      Transpose a psImage
+ *      Compute LUD
+ *      Solve LUD
+ *      Matrix inversion
+ *      Calculate determinant
+ *      Matrix addition
+ *      Matrix subtraction
+ *      Matrix multiplication
+ *      Calculate Eigenvectors
+ *      Convert matrix to vector
+ *      Convert vector to matrix
+ *
+ *  These functions treat psImages as if they were matrices, therefore there is no psMatrix.
+ *
+ *  @author Ross Harman, MHPCC
+ *  @author Robert DeSonia, MHPCC
+ *  @author Andy Becker, University of Washington (SVD).
+ *
+ *  @version $Revision: 1.57 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-05-07 23:10:46 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+// XXX Future optimisation: use GSL type appropriate to the psLib type, and use memcpy instead of copying each
+// value individually.
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/******************************************************************************/
+/*  INCLUDE FILES                                                             */
+/******************************************************************************/
+#include <string.h>
+#include <gsl/gsl_matrix.h>
+#include <gsl/gsl_linalg.h>
+#include <gsl/gsl_blas.h>
+#include <gsl/gsl_permutation.h>
+#include <gsl/gsl_eigen.h>
+
+#include "psAbort.h"
+#include "psMemory.h"
+#include "psError.h"
+#include "psImage.h"
+#include "psVector.h"
+#include "psMatrix.h"
+#include "psAssert.h"
+
+#include "psTrace.h"
+
+/*****************************************************************************/
+/* DEFINE STATEMENTS                                                         */
+/*****************************************************************************/
+
+/** Preprocessor macro to generate error for image dimensionality not set to PS_DIMEN_IMAGE */
+#define PS_CHECK_DIMEN_AND_TYPE(NAME, PS_DIMEN, CLEANUP)                                             \
+if (NAME->type.dimen != PS_DIMEN) {                                                                 \
+    psError(PS_ERR_BAD_PARAMETER_TYPE, true,                                                        \
+            "Invalid operation. %s has incorrect dimensionality %d.", #NAME, PS_DIMEN);             \
+    CLEANUP;                                                                                  \
+} else if(NAME->type.type!=PS_TYPE_F64 && NAME->type.type!=PS_TYPE_F32) {                           \
+    psError(PS_ERR_BAD_PARAMETER_TYPE, true,                                                        \
+            "Invalid operation. %s not PS_TYPE_F64.", #NAME);                                       \
+    CLEANUP;                                                                                  \
+}
+
+/** Preprocessor macro to check that input is not equal to output */
+#define PS_CHECK_POINTERS(NAME1, NAME2, CLEANUP)                                                     \
+if (NAME1 == NAME2) {                                                                               \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true,                                                       \
+            "Invalid operation: Pointer to %s is same as %s.", #NAME1, #NAME2);                     \
+    CLEANUP;                                                                                  \
+}
+
+/** Preprocessor macro to check that an image is square */
+#define PS_CHECK_SQUARE(NAME, CLEANUP)                                                               \
+if (NAME->numCols != NAME->numRows) {                                                               \
+    psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Invalid operation: %s not square array.", #NAME);     \
+    CLEANUP;                                                                                  \
+}
+
+/** Preprocessor macro to initalize a GSL matrix. */
+#define PS_GSL_MATRIX_INITIALIZE(LHS_NAME, RHS_NAME)                                                \
+LHS_NAME.size1 = numRows;                                                                           \
+LHS_NAME.size2 = numCols;                                                                           \
+LHS_NAME.tda   = numCols;                                                                           \
+LHS_NAME.data  = RHS_NAME;
+
+
+/*****************************************************************************/
+/* FILE STATIC FUNCTIONS                                                     */
+/*****************************************************************************/
+
+static void  psVectorToGslVector(gsl_vector *outGslVector, const psVector *inVector);
+static void gslVectorToPsVector(psVector *outVector, gsl_vector *inGslVector);
+static void  psImageToGslMatrix(gsl_matrix *outGslMatrix, const psImage *inImage);
+static void gslMatrixToPsImage(psImage *outImage, gsl_matrix *inGslMatrix);
+
+/** Static function to copy psF32 or psF64 vector data to a GSL vector */
+static void  psVectorToGslVector(gsl_vector *outGslVector,
+                                 const psVector *inVector)
+{
+    psU32 i = 0;
+    psU32 n = 0;
+
+
+    n = inVector->n;
+    for(i=0; i<n; i++) {
+        if(inVector->type.type == PS_TYPE_F32) {
+            outGslVector->data[i] = (psF64)inVector->data.F32[i];
+        } else {
+            outGslVector->data[i] = inVector->data.F64[i];
+        }
+    }
+}
+
+/** Static function to copy GSL vector data to a psF32 or psF64 vector */
+static void gslVectorToPsVector(psVector *outVector,
+                                gsl_vector *inGslVector)
+{
+    psU32 i = 0;
+    psU32 n = 0;
+
+
+    n = outVector->n;
+    for(i=0; i<n; i++) {
+        if(outVector->type.type == PS_TYPE_F32) {
+            outVector->data.F32[i] = (psF32)inGslVector->data[i];
+        } else {
+            outVector->data.F64[i] = inGslVector->data[i];
+        }
+    }
+}
+
+/** Static function to copy psF32 or psF64 image data to a GSL matrix */
+static void  psImageToGslMatrix(gsl_matrix *outGslMatrix,
+                                const psImage *inImage)
+{
+    psU32 i = 0;
+    psU32 j = 0;
+    psU32 numRows = 0;
+    psU32 numCols = 0;
+
+
+    numRows = inImage->numRows;
+    numCols = inImage->numCols;
+    if(inImage->type.type == PS_TYPE_F32) {
+        for(i=0; i<numRows; i++) {
+            for(j=0; j<numCols; j++) {
+                outGslMatrix->data[i*numCols+j] = inImage->data.F32[i][j];
+            }
+        }
+    } else {
+        for(i=0; i<numRows; i++) {
+            for(j=0; j<numCols; j++) {
+                outGslMatrix->data[i*numCols+j] = inImage->data.F64[i][j];
+            }
+        }
+    }
+}
+
+/** Static function to copy GSL matrix data to a psF32 or psF64 image */
+static void gslMatrixToPsImage(psImage *outImage,
+                               gsl_matrix *inGslMatrix)
+{
+    psU32 i = 0;
+    psU32 j = 0;
+    psU32 numRows = 0;
+    psU32 numCols = 0;
+
+
+    numRows = outImage->numRows;
+    numCols = outImage->numCols;
+    if(outImage->type.type == PS_TYPE_F32) {
+        for(i=0; i<numRows; i++) {
+            for(j=0; j<numCols; j++) {
+                outImage->data.F32[i][j] = inGslMatrix->data[i*numCols+j];
+            }
+        }
+    } else {
+        for(i=0; i<numRows; i++) {
+            for(j=0; j<numCols; j++) {
+                outImage->data.F64[i][j] = inGslMatrix->data[i*numCols+j];
+            }
+        }
+    }
+}
+
+
+/*****************************************************************************/
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+/*****************************************************************************/
+
+psImage* psMatrixLUD(psImage* out,
+                     psVector** perm,
+                     const psImage* in)
+{
+    psS32 signum = 0;
+    psS32 numRows = 0;
+    psS32 numCols = 0;
+    gsl_matrix *lu = NULL;
+    gsl_permutation permGSL;
+
+
+    #define psMatrixLUD_EXIT {psFree(out); return NULL;}
+
+    // Error checks
+    PS_ASSERT_GENERAL_IMAGE_NON_NULL(in, psMatrixLUD_EXIT);
+    PS_CHECK_POINTERS(in, out, psMatrixLUD_EXIT);
+    PS_CHECK_DIMEN_AND_TYPE(in, PS_DIMEN_IMAGE, psMatrixLUD_EXIT);
+    PS_ASSERT_GENERAL_PTR_NON_NULL(perm, psMatrixLUD_EXIT);
+
+    out = psImageRecycle(out, in->numCols, in->numRows, in->type.type);
+
+    PS_CHECK_SQUARE(in, psMatrixLUD_EXIT); // gsl_linalg_LU_decomp would fail on non-square input.
+    PS_CHECK_SQUARE(out, psMatrixLUD_EXIT);
+
+    // Initialize data
+    numRows = in->numRows;
+    numCols = in->numCols;
+
+    // Initialize GSL data
+    permGSL.size = numCols;
+    if (sizeof(size_t) == 4) {
+        *perm = psVectorRecycle(*perm, numCols, PS_TYPE_S32);
+    } else if (sizeof(size_t) == 8) {
+        *perm = psVectorRecycle(*perm, numCols, PS_TYPE_S64);
+    } else {
+        psError(PS_ERR_UNKNOWN, true,
+                "Failed to allocate the permutation vector; "
+                "could not determine the cooresponding data type.");
+        psMatrixLUD_EXIT;
+    }
+
+    (*perm)->n = numCols;
+    permGSL.data = (psPtr)((*perm)->data.U8);
+    lu = gsl_matrix_alloc(numRows, numCols);
+
+    // Copy psImage data into GSL matrix data
+    psImageToGslMatrix(lu, in);
+
+    // Calculate LU decomposition
+    gsl_linalg_LU_decomp(lu, &permGSL, &signum); // N.B., uses Gaussian Elimination with partial pivoting.
+
+    // Copy GSL matrix data to psImage data
+    gslMatrixToPsImage(out, lu);
+
+    // Free GSL data
+    gsl_matrix_free(lu);
+
+    return out;
+}
+
+psVector* psMatrixLUSolve(psVector* out,
+                          const psImage* LU,
+                          const psVector* RHS,
+                          const psVector* perm)
+{
+    psS32 numRows = 0;
+    psS32 numCols = 0;
+    gsl_matrix *lu;
+    gsl_permutation permGSL;
+    gsl_vector *b = NULL;
+    gsl_vector *x = NULL;
+
+    #define LUSOLVE_CLEANUP {psFree(out); return NULL;}
+
+    // Error checks
+    PS_ASSERT_GENERAL_IMAGE_NON_NULL(LU, LUSOLVE_CLEANUP);
+    PS_CHECK_DIMEN_AND_TYPE(LU, PS_DIMEN_IMAGE, LUSOLVE_CLEANUP);
+    PS_ASSERT_GENERAL_IMAGE_NON_EMPTY(LU, LUSOLVE_CLEANUP);
+    PS_ASSERT_GENERAL_VECTOR_NON_NULL(RHS, LUSOLVE_CLEANUP);
+    PS_CHECK_DIMEN_AND_TYPE(RHS, PS_DIMEN_VECTOR, LUSOLVE_CLEANUP);
+    PS_ASSERT_GENERAL_VECTOR_NON_NULL(perm, LUSOLVE_CLEANUP);
+
+    out = psVectorRecycle(out, LU->numRows, LU->type.type);
+
+    PS_CHECK_POINTERS(out, RHS, LUSOLVE_CLEANUP);
+    PS_CHECK_POINTERS(RHS, perm, LUSOLVE_CLEANUP);
+    PS_CHECK_POINTERS(out, perm, LUSOLVE_CLEANUP);
+
+    // Initialize data
+    numRows = LU->numRows;
+    numCols = LU->numCols;
+
+    // Initialize GSL data
+    lu = gsl_matrix_alloc(numRows, numCols);
+    psImageToGslMatrix(lu, LU);
+    b = gsl_vector_alloc(RHS->n);
+    psVectorToGslVector(b, RHS);
+    x = gsl_vector_alloc(RHS->n);
+
+    out->n = numCols;
+    permGSL.size = perm->n;
+    permGSL.data = (psPtr)(perm->data.U8);
+
+    // Solve for {x} in equation: {b} = [A]{x}
+    gsl_linalg_LU_solve(lu, &permGSL, b, x);
+
+    // Copy GSL vector data to psVector data
+    gslVectorToPsVector(out, x);
+
+    // Free GSL data
+    gsl_vector_free(b);
+    gsl_vector_free(x);
+    gsl_matrix_free(lu);
+
+    return out;
+}
+
+// This used to be "a temporary gauss-jordan solver based on gene's version based on the Numerical Recipes
+// version".  However, it's been removed due to copyright, and replaced with LU Decomposition solving.
+bool psMatrixGJSolve(psImage *a,
+                     psVector *b
+                    )
+{
+    PS_ASSERT_IMAGE_NON_NULL(a, false);
+    PS_ASSERT_VECTOR_NON_NULL(b, false);
+    PS_ASSERT_IMAGE_TYPE_F32_OR_F64(a, false);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(b, false);
+    PS_ASSERT_INT_EQUAL(a->numCols, a->numRows, false);
+    PS_ASSERT_VECTOR_SIZE(b, (long int)a->numCols, false);
+
+    // Check for non-finite entries
+#define MATRIX_CHECK_NONFINITE_CASE(TYPE,MATRIX) \
+  case PS_TYPE_##TYPE: { \
+      ps##TYPE **values = MATRIX->data.TYPE; /* Dereference */ \
+      int numCols = (MATRIX)->numCols, numRows = (MATRIX)->numRows; /* Size of matrix */ \
+      for (int i = 0; i < numRows; i++) { \
+          for (int j = 0; j < numCols; j++) { \
+              if (!isfinite(values[i][j])) { \
+                  psError(PS_ERR_BAD_PARAMETER_VALUE, 3, \
+                          "Input matrix contains non-finite elements: matrix[%d][%d] is %.2f\n", \
+                          i, j, values[i][j]); \
+                  return false; \
+              } \
+          } \
+      } \
+      break; \
+  }
+
+    // Check for non-finite entries in matrix
+    switch (a->type.type) {
+        MATRIX_CHECK_NONFINITE_CASE(F32, a);
+        MATRIX_CHECK_NONFINITE_CASE(F64, a);
+      default:
+        psAbort("Should never get here.");
+    }
+
+    // Decompose the matrix and solve
+    psVector *perm = NULL;              // Permutation vector
+    psImage *lu = psMatrixLUD(NULL, &perm, a); // LU decomposed matrix
+    if (!lu) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to generate LU decomposed matrix");
+        psFree(perm);
+        return false;
+    }
+    psVector *ans = psMatrixLUSolve(NULL, lu, b, perm); // Answer
+    psFree(lu);
+    psFree(perm);
+    if (!ans) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to solve matrix equation.");
+        return false;
+    }
+
+    memcpy(b->data.U8, ans->data.U8, b->n * PSELEMTYPE_SIZEOF(ans->type.type));
+    psFree(ans);
+
+    return true;
+}
+
+
+psImage* psMatrixInvert(psImage* out,
+                        const psImage* in,
+                        float *determinant)
+{
+    psS32 signum = 0;
+    psS32 numRows = 0;
+    psS32 numCols = 0;
+    gsl_matrix *inv = NULL;
+    gsl_matrix *lu = NULL;
+    gsl_permutation *perm = NULL;
+
+    #define INVERT_CLEANUP { psFree(out); return NULL; }
+    // Error checks
+    PS_ASSERT_GENERAL_IMAGE_NON_NULL(in, INVERT_CLEANUP);
+    PS_CHECK_POINTERS(in, out, INVERT_CLEANUP);
+    PS_CHECK_DIMEN_AND_TYPE(in, PS_DIMEN_IMAGE, INVERT_CLEANUP);
+    PS_ASSERT_GENERAL_IMAGE_NON_EMPTY(in, INVERT_CLEANUP);
+
+    out = psImageRecycle(out, in->numCols, in->numRows, in->type.type);
+
+    PS_CHECK_SQUARE(in, INVERT_CLEANUP);
+    PS_CHECK_SQUARE(out, INVERT_CLEANUP);
+
+    // Initialize data
+    numRows = in->numRows;
+    numCols = in->numCols;
+
+    // Initialize GSL data
+    perm = gsl_permutation_alloc(numRows);
+    lu = gsl_matrix_alloc(numRows, numCols);
+    inv = gsl_matrix_alloc(numRows, numCols);
+    psImageToGslMatrix(lu, in);
+
+    // Invert data and calculate determinant
+    gsl_linalg_LU_decomp(lu, perm, &signum);
+    gsl_linalg_LU_invert(lu, perm, inv);
+    if (determinant) {
+      // XXX this is getting the wrong value: is it the wrong calculation?
+      // it disagrees with the results of 
+      // det = (psF32)gsl_linalg_LU_det(lu, signum);
+      // used in psMatrixDeterminatn
+      // *determinant = (float)gsl_linalg_LU_lndet(lu);
+      *determinant = (psF32)gsl_linalg_LU_det(lu, signum);
+    }
+
+    // Copy GSL matrix data to psImage data
+    gslMatrixToPsImage(out, inv);
+
+    // Free GSL structs
+    gsl_permutation_free(perm);
+    gsl_matrix_free(lu);
+    gsl_matrix_free(inv);
+
+    return out;
+}
+
+float psMatrixDeterminant(const psImage* in)
+{
+    psS32 signum = 0;
+    psS32 numRows = 0;
+    psS32 numCols = 0;
+    psF32 det = 0;
+    gsl_matrix *lu = NULL;
+    gsl_permutation *perm = NULL;
+
+    #define DETERMINANT_EXIT { return 0; }
+    // Error checks
+    PS_ASSERT_GENERAL_IMAGE_NON_NULL(in, DETERMINANT_EXIT);
+    PS_CHECK_DIMEN_AND_TYPE(in, PS_DIMEN_IMAGE, DETERMINANT_EXIT);
+    PS_ASSERT_GENERAL_IMAGE_NON_EMPTY(in, DETERMINANT_EXIT);
+    PS_CHECK_SQUARE(in, DETERMINANT_EXIT);
+
+    // Initialize data
+    numRows = in->numRows;
+    numCols = in->numCols;
+
+    // Allocate GSL structs
+    perm = gsl_permutation_alloc(numRows);
+    lu = gsl_matrix_alloc(numRows, numCols);
+    psImageToGslMatrix(lu, in);
+
+    // Calculate determinant
+    gsl_linalg_LU_decomp(lu, perm, &signum);
+    det = (psF32)gsl_linalg_LU_det(lu, signum);
+
+    // Free GSL structs
+    gsl_permutation_free(perm);
+    gsl_matrix_free(lu);
+
+    return det;
+}
+
+psImage* psMatrixMultiply(psImage* out,
+                          const psImage* in1,
+                          const psImage* in2)
+{
+    #define MULTIPLY_CLEANUP { psFree(out); return NULL; }
+
+    // Error checks
+    PS_ASSERT_GENERAL_IMAGE_NON_NULL(in1, MULTIPLY_CLEANUP);
+    PS_ASSERT_GENERAL_IMAGE_NON_NULL(in2, MULTIPLY_CLEANUP);
+    PS_ASSERT_GENERAL_IMAGE_NON_EMPTY(in1, MULTIPLY_CLEANUP);
+    PS_ASSERT_GENERAL_IMAGE_NON_EMPTY(in2, MULTIPLY_CLEANUP);
+    PS_CHECK_DIMEN_AND_TYPE(in1, PS_DIMEN_IMAGE, MULTIPLY_CLEANUP);
+    PS_CHECK_DIMEN_AND_TYPE(in2, PS_DIMEN_IMAGE, MULTIPLY_CLEANUP);
+    PS_CHECK_POINTERS(in1, out, MULTIPLY_CLEANUP);
+    PS_CHECK_POINTERS(in1, in2, MULTIPLY_CLEANUP);
+
+    int rows1 = in1->numRows, cols1 = in1->numCols; // Size of input 1
+    int rows2 = in2->numRows, cols2 = in2->numCols; // Size of input 2
+    if (cols1 != rows2) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                "Incompatible dimensions for matrix multiplication: %dx%d * %dx%d (row x col)",
+                rows1, cols1, rows2, cols2);
+        MULTIPLY_CLEANUP;
+    }
+    int common = cols1;                 // Common dimension
+
+    if (in1->type.type != in2->type.type) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Invalid operation: data types of in1 and in2 must match.");
+        MULTIPLY_CLEANUP;
+    }
+
+    psElemType type = in1->type.type;   // Data type
+    int outRows = rows1, outCols = cols2; // Size of output
+    out = psImageRecycle(out, outCols, outRows, type);
+
+#define MATRIX_MULTIPLY_CASE(TYPE) \
+  case PS_TYPE_##TYPE: \
+    for (int i = 0; i < outRows; i++) { \
+        for (int j = 0; j < outCols; j++) { \
+            ps##TYPE value = 0.0; \
+            for (int k = 0; k < common; k++) { \
+                value += in1->data.TYPE[i][k] * in2->data.TYPE[k][j]; \
+            } \
+            out->data.TYPE[i][j] = value; \
+        } \
+    } \
+    break;
+
+    switch (type) {
+        MATRIX_MULTIPLY_CASE(F32);
+        MATRIX_MULTIPLY_CASE(F64);
+      default:
+        psAbort("Should never get here.  Unsupported type: %x", type);
+    }
+
+    return out;
+}
+
+psImage* psMatrixTranspose(psImage* out, const psImage* in)
+{
+    // Error checks
+    PS_ASSERT_IMAGE_NON_NULL(in, NULL);
+    PS_ASSERT_IMAGE_NON_EMPTY(in, NULL);
+    PS_CHECK_DIMEN_AND_TYPE(in, PS_DIMEN_IMAGE, return NULL);
+    PS_ASSERT(in != out, NULL);
+
+    int numCols = in->numRows, numRows = in->numCols; // Size of transposed image
+    psElemType type = in->type.type;    // Data type
+
+    out = psImageRecycle(out, numCols, numRows, type);
+
+#define TRANSPOSE_CASE(TYPE) \
+  case PS_TYPE_##TYPE: { \
+      for (int i = 0; i < numRows; i++) { \
+          for (int j = 0; j < numCols; j++) { \
+              out->data.TYPE[i][j] = in->data.TYPE[j][i]; \
+          } \
+      } \
+      break; \
+  }
+
+    switch (type) {
+        TRANSPOSE_CASE(F32);
+        TRANSPOSE_CASE(F64);
+      default:
+        psAbort("Unsupported type: %x", type);
+    }
+
+    return out;
+}
+
+psImage* psMatrixEigenvectors(psImage* out,
+                              const psImage* in)
+{
+    psS32 numRows = 0;
+    psS32 numCols = 0;
+    gsl_vector *eVals = NULL;
+    gsl_eigen_symmv_workspace *w = NULL;
+    gsl_matrix *outGSL = NULL;
+    gsl_matrix *inGSL = NULL;
+
+    #define EIGENVECTORS_CLEANUP { psFree(out); return NULL; }
+    // Error checks
+    PS_ASSERT_GENERAL_IMAGE_NON_NULL(in, EIGENVECTORS_CLEANUP);
+    PS_CHECK_DIMEN_AND_TYPE(in, PS_DIMEN_IMAGE, EIGENVECTORS_CLEANUP);
+    PS_ASSERT_GENERAL_IMAGE_NON_EMPTY(in, EIGENVECTORS_CLEANUP);
+    PS_CHECK_POINTERS(in, out, EIGENVECTORS_CLEANUP);
+
+    out = psImageRecycle(out, in->numCols, in->numRows, in->type.type);
+
+    // Initialize data
+    numRows = in->numRows;
+    numCols = in->numCols;
+
+    inGSL = gsl_matrix_alloc(numRows, numCols);
+    psImageToGslMatrix(inGSL, in);
+    outGSL = gsl_matrix_alloc(numRows, numCols);
+
+    // Allocate GSL structs
+    eVals = gsl_vector_alloc(numRows);
+    w = gsl_eigen_symmv_alloc(numRows);
+
+    // Non-square matrices not allowed
+    PS_CHECK_SQUARE(in, EIGENVECTORS_CLEANUP);
+    PS_CHECK_SQUARE(out, EIGENVECTORS_CLEANUP);
+
+    // Calculate Eigenvalues and Eigenvectors...Eigenvalues not currently used
+    gsl_eigen_symmv(inGSL, eVals, outGSL, w);
+
+    // Copy GSL matrix data to psImage data
+    gslMatrixToPsImage(out, outGSL);
+
+    // Free GSL structs
+    gsl_matrix_free(inGSL);
+    gsl_matrix_free(outGSL);
+    gsl_eigen_symmv_free(w);
+    gsl_vector_free(eVals);
+
+    return out;
+}
+
+psVector* psMatrixToVector(psVector* outVector,
+                           const psImage* inImage)
+{
+    psS32 size = 0;
+
+    #define psMatrixToVector_EXIT {psFree(outVector); return NULL;}
+
+    // Error checks
+    PS_ASSERT_GENERAL_IMAGE_NON_NULL(inImage, psMatrixToVector_EXIT);
+    PS_CHECK_DIMEN_AND_TYPE(inImage, PS_DIMEN_IMAGE, psMatrixToVector_EXIT);
+    PS_ASSERT_GENERAL_IMAGE_NON_EMPTY(inImage, psMatrixToVector_EXIT);
+
+    if (inImage->numRows == 1) {
+        // Create transposed row vector
+        outVector = psVectorRecycle(outVector, inImage->numCols, inImage->type.type);
+        outVector->type.dimen = PS_DIMEN_TRANSV;
+    } else if (inImage->numCols == 1) {
+        // Create non-transposed column vector
+        outVector = psVectorRecycle(outVector, inImage->numRows, inImage->type.type);
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                "Image does not have dim with 1 col or 1 row: (%d x %d).",
+                inImage->numRows, inImage->numCols);
+        psMatrixToVector_EXIT;
+    }
+
+    // More checks
+    if (outVector->type.dimen == PS_DIMEN_VECTOR) {
+        PS_CHECK_DIMEN_AND_TYPE(outVector, PS_DIMEN_VECTOR, psMatrixToVector_EXIT);
+
+        if (outVector->n == 0) {
+            outVector->n = inImage->numRows;
+        }
+
+        if (outVector->n != inImage->numRows) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    "Image and vector sizes differ: (%d vs %ld).",
+                    inImage->numRows, outVector->n);
+            psMatrixToVector_EXIT;
+        }
+
+        size = PSELEMTYPE_SIZEOF(inImage->type.type) * inImage->numRows;
+
+    } else if (outVector->type.dimen == PS_DIMEN_TRANSV) {
+        PS_CHECK_DIMEN_AND_TYPE(outVector, PS_DIMEN_TRANSV, psMatrixToVector_EXIT);
+
+        if (outVector->n == 0) {
+            outVector->n = inImage->numCols;
+        }
+
+        if (outVector->n != inImage->numCols) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    "Image and vector sizes differ: (%d vs %ld).",
+                    inImage->numCols, outVector->n);
+            psMatrixToVector_EXIT;
+        }
+
+        size = PSELEMTYPE_SIZEOF(inImage->type.type) * inImage->numCols;
+    }
+
+    memcpy(outVector->data.U8, inImage->data.U8[0], size);
+
+    return outVector;
+}
+
+psImage* psVectorToMatrix(psImage* outImage,
+                          const psVector* inVector)
+{
+    psS32 size = 0;
+
+    #define VECTORTOMATRIX_CLEANUP {psFree(outImage); return NULL; }
+    // Error checks
+    PS_ASSERT_GENERAL_VECTOR_NON_NULL(inVector, VECTORTOMATRIX_CLEANUP);
+
+    if (inVector->type.dimen == PS_DIMEN_VECTOR) {
+        PS_CHECK_DIMEN_AND_TYPE(inVector, PS_DIMEN_VECTOR, VECTORTOMATRIX_CLEANUP);
+        PS_ASSERT_GENERAL_VECTOR_NON_EMPTY(inVector, VECTORTOMATRIX_CLEANUP);
+
+        outImage = psImageRecycle(outImage, 1, inVector->n, inVector->type.type);
+
+        // More checks for PS_DIMEN_VECTOR
+        if (outImage->numCols > 1) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    "Image has more than 1 column: numCols = %d.",
+                    outImage->numCols);
+            VECTORTOMATRIX_CLEANUP;
+        } else if (outImage->numRows != inVector->n) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    "Image and vector sizes differ: (%d vs %ld).",
+                    outImage->numRows, inVector->n);
+            VECTORTOMATRIX_CLEANUP;
+        }
+
+        size = PSELEMTYPE_SIZEOF(outImage->type.type) * outImage->numRows;
+
+    } else if (inVector->type.dimen == PS_DIMEN_TRANSV) {
+        PS_CHECK_DIMEN_AND_TYPE(inVector, PS_DIMEN_TRANSV, VECTORTOMATRIX_CLEANUP);
+        PS_ASSERT_GENERAL_VECTOR_NON_EMPTY(inVector, VECTORTOMATRIX_CLEANUP);
+        outImage = psImageRecycle(outImage, inVector->n, 1, inVector->type.type);
+        // More checks for PS_DIMEN_TRANSV
+        if (outImage->numRows > 1) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    "Image has more than 1 row: numRows = %d.",
+                    outImage->numRows);
+            VECTORTOMATRIX_CLEANUP;
+        } else if (outImage->numCols != inVector->n) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    "Image and vector sizes differ: (%d vs %ld).",
+                    outImage->numCols, inVector->n);
+            VECTORTOMATRIX_CLEANUP;
+        }
+
+        size = PSELEMTYPE_SIZEOF(outImage->type.type) * outImage->numCols;
+    }
+
+    PS_ASSERT_GENERAL_IMAGE_NON_NULL(outImage, VECTORTOMATRIX_CLEANUP);
+    PS_CHECK_DIMEN_AND_TYPE(outImage, PS_DIMEN_IMAGE, VECTORTOMATRIX_CLEANUP);
+
+    memcpy(outImage->data.U8[0], inVector->data.U8, size);
+
+    return outImage;
+}
+
+// This code supplied by Andy Becker (becker@astro.washington.edu)
+psImage *psMatrixSVD(psImage* evec, psVector* eval, const psImage* in)
+{
+    #define psMatrixSVD_EXIT {psFree(evec); psFree(eval); return NULL;}
+
+    // Error checks  Missing one for eval
+    PS_ASSERT_GENERAL_IMAGE_NON_NULL(in, psMatrixSVD_EXIT);
+    PS_CHECK_POINTERS(in, evec, psMatrixSVD_EXIT);
+    PS_CHECK_DIMEN_AND_TYPE(in, PS_DIMEN_IMAGE, psMatrixSVD_EXIT);
+
+    // evec ends up : numCols x numCols
+    evec = psImageRecycle(evec,  in->numCols, in->numCols, in->type.type);
+    eval = psVectorRecycle(eval, in->numCols, in->type.type);
+
+    // Initialize data
+    int numRows = in->numRows;
+    int numCols = in->numCols;
+
+    gsl_matrix *A = gsl_matrix_alloc(numRows, numCols);
+    gsl_matrix *V = gsl_matrix_alloc(numCols, numCols);
+    gsl_vector *S = gsl_vector_alloc(numCols);
+    gsl_vector *work = gsl_vector_alloc(numCols);
+
+    // Copy psImage data into GSL matrix data
+    psImageToGslMatrix(A, in);
+
+    // Calculate SVD decomposition
+    gsl_linalg_SV_decomp(A, V, S, work);
+
+    // Copy GSL matrix data to psImage data
+    gslMatrixToPsImage(evec, V);
+    gslVectorToPsVector(eval, S);
+
+    // Take the square root of eval
+    for (int i = 0; i < eval->n; i++) {
+        eval->data.F64[i] = sqrt(eval->data.F64[i]);
+        /* make sure that these things are sorted! */
+        if (i > 0) {
+            psAssert(eval->data.F64[i] <= eval->data.F64[i-1], "impossible");
+        }
+    }
+
+    // Free GSL data
+    gsl_matrix_free(A);
+    gsl_matrix_free(V);
+    gsl_vector_free(S);
+    gsl_vector_free(work);
+
+    return evec;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMatrix.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMatrix.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMatrix.h	(revision 22158)
@@ -0,0 +1,177 @@
+/* @file  psMatrix.h
+ *
+ * @brief Provides functions for linear algebra operations on psImages and psVectors.
+ *
+ * Functions are provided to:
+ *     Transpose a psImage
+ *     Compute LUD
+ *     Solve LUD
+ *     Matrix inversion
+ *     Calculate determinant
+ *     Matrix multiplication
+ *     Calculate Eigenvectors
+ *     Convert matrix to vector
+ *     Convert vector to matrix
+ *
+ * These functions treat psImages as if they were matrices, therefore there is no psMatrix. These functions
+ * operate only with the psF64 data type.
+ *
+ * @author Ross Harman, MHPCC
+ *
+ * @version $Revision: 1.28 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-12-14 00:41:17 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PSMATRIX_H
+#define PSMATRIX_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+/** LU Decomposition of psImage matrix.
+ *
+ *  Performs a LU decomposition on a psImage matrix and returns the LU matrix. If the user specifies NULL for
+ *  the outImage or outPerm arguments, then they will be automatically created. The input image must
+ *  be square. This function operates only with the psF64 data type. Input and output arguments should not be
+ *  the same. GSL indexes the top row as the zero row, not the bottom.
+ *
+ *  @return  psImage* : Pointer to LU decomposed psImage.
+ */
+psImage* psMatrixLUD(
+    psImage* out,                      ///< Image to return, or NULL.
+    psVector** perm,                   ///< Output permutation vector used by psMatrixLUSolve.
+    const psImage* in                  ///< Image to decompose.
+);
+
+/** LU Solution of psImage matrix.
+ *
+ *  Solves for and returns the psVector, {x} in the equation [A]{x} = {b}. If the user specifies NULL as the
+ *  outVector argument, then it will automatically be created. The input image must be square. This function
+ *  operates only with the psF64 data type. Input and output arguments should not be the same. GSL indexes
+ *  the top row as the zero row, not the bottom.
+ *
+ *  @return  psVector* : Pointer to psVector solution of matrix equation.
+ */
+psVector* psMatrixLUSolve(
+    psVector* out,                     ///< Vector to return, or NULL.
+    const psImage* LU,                 ///< LU-decomposed matrix.
+    const psVector* RHS,               ///< Vector right-hand-side of equation.
+    const psVector* perm               ///< Permutation vector resulting from psMatrixLUD function.
+);
+
+/** Used to be a Gauss-Jordan numerical solver, but now uses LU decomposition.
+ *
+ *  @return bool:   True if successful.
+ */
+bool psMatrixGJSolve(
+    psImage *A,                   ///< Matrix to be solved
+    psVector *b                   ///< Vector of values
+);
+
+/** Gauss-Jordan numerical solver for F32 input data */
+#define psMatrixGJSolveF32(A,B) psMatrixGJSolve(A,B)
+
+
+/** Invert psImage matrix.
+ *
+ *  Inverts a psImage matrix and returns the determinant as an option through the argument list. If the user
+ *  specifies NULL as the outImage argument, then it will automatically be created. The input image must be
+ *  square. This function operates only with the psF64 data type. Input and output arguments should not be
+ *  the same. GSL indexes the top row as the zero row, not the bottom.
+ *
+ *  @return  psImage* : Pointer to inverted psImage.
+ */
+psImage* psMatrixInvert(
+    psImage* out,                      ///< Image to return, or NULL for in-place substitution.
+    const psImage* in,                 ///< Image to be inverted
+    float *determinant                 ///< Determinant to return, or NULL
+);
+
+/** Calculate psImage matrix determinant.
+ *
+ *  Calculates the determinant of a psImage matrix and returns the single precision floating point result. The
+ *  input image must be square. This function operates only with the psF64 data type. GSL indexes the top row
+ *  as the zero row, not the bottom.
+ *
+ *  @return  float: Determinant from psImage.
+ */
+float psMatrixDeterminant(
+    const psImage* in                  ///< Image used to calculate determinant.
+);
+
+/** Performs psImage matrix multiplication.
+ *
+ *  Performs a classical matrix multiplication involving row and column operations. Input images must be square
+ *  and the same size. If the user specifies NULL as the outImage argument, then it will automatically be
+ *  created. This function operates only with the psF64 data type. GSL indexes the top row as the
+ *  zero row, not the bottom.
+ *
+ *  @return  psImage* : Pointer to resulting psImage.
+ */
+psImage* psMatrixMultiply(
+    psImage* out,                      ///< Matrix to return, or NULL.
+    const psImage* in1,                ///< First input image.
+    const psImage* in2                 ///< Second input image.
+);
+
+/** Transpose matrix.
+ *
+ *  Performs psImage matrix transpose by substituting existing rows for columns. The input image must be
+ *  square. If the user specifies NULL as the outImage argument, then it will automaticallty be created.
+ *  This function operates only with the psF64 data type. GSL indexes the top row as the zero
+ *  row, not the bottom.
+ *
+ *  @return  psImage* : Pointer to transposed psImage.
+ */
+psImage* psMatrixTranspose(
+    psImage* out,                      ///< Image to return, or NULL
+    const psImage* in                  ///< Image to transpose
+);
+
+/** Calculate matrix eigenvectors.
+ *
+ *  Calculates the eigenvectors for a matrix. The input image must be symmetric and square. If the user
+ *  specifies NULL as the outImage argument, then it will automatically be created. This function operates
+ *  only with the psF64 data type. GSL indexes the top row as the zero row, not the bottom.
+ *
+ *  @return  psImage* : Pointer to matrix of Eigenvectors.
+ */
+psImage* psMatrixEigenvectors(
+    psImage* out,                      ///< Eigenvectors to return, or NULL.
+    const psImage* in                  ///< Input image.
+);
+
+/** Convert matrix to vector.
+ *
+ *  Converts a 1-d psImage matrix into a vector. If the user specifies NULL as the outVector argument, then it
+ *  will automatically be created based on the input image (PS_DIMEN_VECTOR for an input image with 1 col or
+ *  PS_DIMENT_TRANSV for an input image with 1 row). Either the number of rows or the number of colums of the
+ *  input matrix must be 1. This function operates only  with the psF64 data type.
+ *
+ *  @return  psVector* : Pointer to psVector.
+ */
+psVector* psMatrixToVector(
+    psVector* outVector,               ///< Vector to return, or NULL.
+    const psImage* inImage             ///< Image to convert.
+);
+
+/** Convert vector to matrix.
+ *
+ *  Converts a vector into a psImage matrix. If the dimensionality of the vector is PS_DIMEN_VECTOR, then the
+ *  resulting psImage is a 1d column. If the dimensionality of the vector is PS_DIMEN_TRANSV, then the
+ *  resulting psImage is a 1d row. If the user specifies NULL as the outImage argument,  then it will
+ *  automatically be created. This function operates only with the psF64 data type.
+ *
+ *  @return  psVector* : Pointer to psIamge.
+ */
+psImage* psVectorToMatrix(
+    psImage* outImage,                 ///< Matrix to return, or NULL.
+    const psVector* inVector           ///< Vector to convert.
+);
+
+/// Single value decomposition, provided by Andy Becker
+psImage *psMatrixSVD(psImage* evec, psVector* eval, const psImage* in);
+
+/// @}
+#endif // #ifndef PSMATRIX_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizeLMM.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizeLMM.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizeLMM.c	(revision 22158)
@@ -0,0 +1,589 @@
+/** @file  psMinimize.c
+ *  \brief basic minimization functions
+ *  @ingroup Math
+ *
+ *  This file will contain functions to minimize an arbitrary function at
+ *  a data point, fit an arbitrary function to a set of data points, and
+ *  fit a 1-D polynomial to a set of data points.
+ *
+ *  @author GLG, MHPCC
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.34 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-04-07 00:45:21 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/*****************************************************************************/
+/* INCLUDE FILES                                                             */
+/*****************************************************************************/
+#include <stdio.h>
+#include <float.h>
+#include <math.h>
+
+#include "psAbort.h"
+#include "psAssert.h"
+#include "psMinimizeLMM.h"
+#include "psImage.h"
+#include "psImageStructManip.h"
+#include "psLogMsg.h"
+/*****************************************************************************/
+/* DEFINE STATEMENTS                                                         */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* TYPE DEFINITIONS                                                          */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* GLOBAL VARIABLES                                                          */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* FILE STATIC VARIABLES                                                     */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* FUNCTION IMPLEMENTATION - LOCAL                                           */
+/*****************************************************************************/
+
+// Alpha & Beta only represent unmasked values
+bool psMinLM_GuessABP(
+    psImage  *Alpha,
+    psVector *Beta,
+    psVector *Params,
+    const psImage  *alpha,
+    const psVector *beta,
+    const psVector *params,
+    const psVector *paramMask,
+    psMinimizeLMLimitFunc checkLimits,
+    psF32 lambda,
+    psF32 *dLinear)
+{
+    PS_ASSERT_VECTOR_TYPE(Alpha,     PS_TYPE_F32,  false);
+    PS_ASSERT_VECTOR_TYPE(Beta,      PS_TYPE_F32,  false);
+    PS_ASSERT_VECTOR_TYPE(Params,    PS_TYPE_F32,  false);
+    PS_ASSERT_VECTOR_TYPE(alpha,     PS_TYPE_F32,  false);
+    PS_ASSERT_VECTOR_TYPE(beta,      PS_TYPE_F32,  false);
+    PS_ASSERT_VECTOR_TYPE(params,    PS_TYPE_F32,  false);
+    if (paramMask) {
+        PS_ASSERT_VECTOR_TYPE(paramMask, PS_TYPE_MASK, false);
+    }
+
+    assert (alpha->numCols == beta->n);
+    assert (alpha->numCols == alpha->numRows);
+
+    // set new guess values, applying (1+lambda) scaling to pivots
+    Beta = psVectorCopy(Beta, beta, PS_TYPE_F32);
+    Alpha = psImageCopy(Alpha, alpha, PS_TYPE_F32);
+    for (int j = 0; j < Alpha->numCols; j++) {
+        Alpha->data.F32[j][j] = alpha->data.F32[j][j] * (1.0 + lambda);
+    }
+
+    // error and clear above if kept?
+    if (false == psMatrixGJSolveF32(Alpha, Beta)) {
+        psTrace ("psLib.math", 4, "singular matrix in Guess ABP\n");
+        return(false);
+    }
+
+    // measure linear model prediction
+    // (we must do this before truncating Beta below)
+    if (dLinear) {
+	*dLinear = psMinLM_dLinear(Beta, beta, lambda);
+    }
+
+    // full-length Beta for checkLimits functions 
+    psVector *tmpBeta = psVectorAlloc(params->n, PS_TYPE_F32);
+    psVectorInit (tmpBeta, 0.0);
+
+    // set tmpBeta values which are not masked
+    for (int j = 0, n = 0; j < params->n; j++) {
+	if (paramMask && (paramMask->data.U8[j])) continue;
+	tmpBeta->data.F32[j] = Beta->data.F32[n];
+	n++;
+    }
+
+    // apply Beta to get new Params values
+    for (int j = 0; j < params->n; j++) {
+        if (paramMask && (paramMask->data.U8[j])) {
+            Params->data.F32[j] = params->data.F32[j];
+            continue;
+        }
+        // apply beta limits
+        if (checkLimits) {
+            checkLimits (PS_MINIMIZE_BETA_LIMIT, j, Params->data.F32, tmpBeta->data.F32);
+	}
+
+        Params->data.F32[j] = params->data.F32[j] - tmpBeta->data.F32[j];
+
+        // compare new params to param limits
+        if (checkLimits) {
+            checkLimits (PS_MINIMIZE_PARAM_MIN,  j, Params->data.F32, tmpBeta->data.F32);
+            checkLimits (PS_MINIMIZE_PARAM_MAX,  j, Params->data.F32, tmpBeta->data.F32);
+	}
+    }
+
+    // apply tmpBeta after limits have been checked
+    for (int j = 0, n = 0; j < params->n; j++) {
+	if (paramMask && (paramMask->data.U8[j])) continue;
+	Beta->data.F32[n] = tmpBeta->data.F32[j];
+	n++;
+    }
+
+    psFree (tmpBeta);
+    return(true);
+}
+
+bool psMinimizeGaussNewtonDelta(
+    psVector *delta,
+    const psVector *params,
+    const psVector *paramMask,
+    const psArray  *x,
+    const psVector *y,
+    const psVector *yWt,
+    psMinimizeLMChi2Func func)
+{
+    psTrace("psLib.math", 3, "---- begin ----\n");
+
+    // allocate internal arrays (current vs Guess)
+    psImage *Alpha = NULL;
+    psVector *Beta = NULL;
+
+    psVectorInit (delta, 0.0);
+
+    // Alpha & Beta only contain elements to represent the unmasked parameters
+    // if none are available, return false
+    if (!psMinLM_AllocAB (&Alpha, &Beta, params, paramMask)) {
+	return false;
+    }
+
+    psImage *alpha   = psImageAlloc(Alpha->numCols, Alpha->numRows, PS_TYPE_F32);
+    psVector *Params = psVectorAlloc(params->n, PS_TYPE_F32);
+
+    psVector *dy     = NULL;
+    bool retValue = true;
+
+    // the user provides the error or NULL.  we need to convert
+    // to appropriate weights
+    if (yWt != NULL) {
+        dy = (psVector *) yWt;
+    } else {
+        dy = psVectorAlloc(y->n, PS_TYPE_F32);
+        psVectorInit(dy, 1.0);
+    }
+
+    // XXX should we give up if chisq is nan?
+    psF32 chisq = psMinLM_SetABX(alpha, Beta, params, paramMask, x, y, dy, func);
+    if (isnan(chisq)) {
+        psTrace ("psLib.math", 5, "psMinLM_SetABX() returned a NAN chisq.\n");
+        retValue = false;
+    }
+
+    psTrace("psLib.math", 5, "psMinLM_SetABX() was succesful\n");
+    // dump some useful info if trace is defined
+    if (psTraceGetLevel("psLib.math") >= 6) {
+        p_psImagePrint(psTraceGetDestination(), alpha, "alpha guess (0)");
+        p_psVectorPrint(psTraceGetDestination(), Beta, "beta guess (0)");
+        p_psVectorPrint(psTraceGetDestination(), params, "params guess (0)");
+    }
+
+    bool status = psMinLM_GuessABP(Alpha, delta, Params, alpha, Beta, params, paramMask, NULL, 0.0, NULL);
+    if (!status) {
+        psTrace ("psLib.math", 5, "psMinLM_GuessABP() returned FALSE.\n");
+        retValue = false;
+    }
+    psTrace("psLib.math", 5, "psMinLM_GuessABP() was succesful\n");
+    if (psTraceGetLevel("psLib.math") >= 6) {
+        p_psImagePrint(psTraceGetDestination(), Alpha, "alpha guess (1)");
+        p_psVectorPrint(psTraceGetDestination(), delta, "delta guess (1)");
+        p_psVectorPrint(psTraceGetDestination(), Params, "params guess (1)");
+    }
+
+    psFree(alpha);
+    psFree(Alpha);
+    psFree(Beta);
+    psFree(Params);
+    if (yWt == NULL) {
+        psFree(dy);
+    }
+    psTrace("psLib.math", 3, "---- end ----\n");
+    return(retValue);
+}
+
+// measure linear model prediction
+psF32 psMinLM_dLinear(
+    const psVector *Beta,
+    const psVector *beta,
+    psF32 lambda)
+{
+
+    /* get linear model prediction */
+    psF32 dLinear = 0;
+    psF32 *B = Beta->data.F32;
+    psF32 *b = beta->data.F32;
+
+    float dh = 0.0, sh = 0.0, Sh = 0.0;
+
+    // beta only counts unmasked parameters
+    for (int i = 0; i < beta->n; i++) {
+	dh = lambda*B[i] + b[i];
+	sh = 0.5*B[i]*dh;
+	Sh += sh;
+        dLinear += lambda*PS_SQR(B[i]) + B[i]*b[i];
+    }
+    return(0.5*dLinear);
+}
+
+// alpha, beta, params are already allocated
+psF32 psMinLM_SetABX(
+    psImage  *alpha,
+    psVector *beta,
+    const psVector *params,
+    const psVector *paramMask,
+    const psArray  *x,
+    const psVector *y,
+    const psVector *dy,
+    psMinimizeLMChi2Func func)
+{
+    PS_ASSERT_IMAGE_NON_NULL(alpha, NAN);
+    PS_ASSERT_VECTOR_NON_NULL(beta, NAN);
+    PS_ASSERT_VECTOR_NON_NULL(params, NAN);
+    PS_ASSERT_PTR_NON_NULL(x, NAN);
+    PS_ASSERT_VECTOR_NON_NULL(y, NAN);
+    PS_ASSERT_VECTOR_NON_NULL(dy, NAN);
+
+    PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32, false);
+    if (paramMask) {
+        PS_ASSERT_VECTOR_TYPE(paramMask, PS_TYPE_MASK, false);
+    }
+
+    psF32 chisq;
+    psF32 delta;
+    psF32 weight;
+    psF32 ymodel;
+    psVector *deriv = psVectorAlloc(params->n, PS_TYPE_F32);
+
+    // zero alpha, beta, and chisq for summing below
+    psImageInit (alpha, 0.0);
+    psVectorInit (beta, 0.0);
+    chisq = 0.0;
+
+    // calculate chisq, alpha, beta. alpha & beta only represent unmasked parameters; skip
+    // masked ones
+    for (psS32 i = 0; i < y->n; i++) {
+        ymodel = func(deriv, params, (psVector *) x->data[i]);
+
+        delta = ymodel - y->data.F32[i];
+        chisq += PS_SQR(delta) * dy->data.F32[i];
+
+        assert (!isnan(dy->data.F32[i]));
+        assert (!isnan(delta));
+        assert (!isnan(chisq));
+
+	// we track alpha,beta and params,deriv separately
+        for (int j = 0, J = 0; j < params->n; j++) {
+            if (paramMask && (paramMask->data.U8[j])) continue;
+
+            weight = deriv->data.F32[j] * dy->data.F32[i];
+
+            for (int k = 0, K = 0; k <= j; k++) {
+                if (paramMask && (paramMask->data.U8[k])) continue;
+                alpha->data.F32[J][K] += weight * deriv->data.F32[k];
+		K++;
+            }
+            beta->data.F32[J] += weight * delta;
+	    J++;
+        }
+    }
+
+    // calculate lower-left half of alpha
+    for (int j = 1; j < alpha->numCols; j++) {
+        for (int k = 0; k < j; k++) {
+            alpha->data.F32[k][j] = alpha->data.F32[j][k];
+        }
+    }
+
+    psFree(deriv);
+    return(chisq);
+}
+
+
+/******************************************************************************
+psMinimizeLMChi2():  This routine will take an procedure which calculates an
+arbitrary function and it's derivative and minimize the chi-squared match
+between that function at the specified coords and the specified value at those
+coords.
+ 
+This requires F32 input data; all internal calls use F32.
+XXX Make an F64 version?
+  *****************************************************************************/
+bool psMinimizeLMChi2(
+    psMinimization *min,
+    psImage *covar,
+    psVector *params,
+    psMinConstraint *constraint,
+    const psArray *x,
+    const psVector *y,
+    const psVector *yWt,
+    psMinimizeLMChi2Func func)
+{
+    psTrace("psLib.math", 3, "---- begin ----\n");
+    PS_ASSERT_PTR_NON_NULL(min, false);
+    PS_ASSERT_VECTOR_NON_NULL(params, false);
+    PS_ASSERT_VECTOR_NON_EMPTY(params, false);
+    PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32, false);
+    psVector *paramMask = NULL;
+    if (constraint != NULL) {
+        paramMask = constraint->paramMask;
+        if (paramMask != NULL) {
+            PS_ASSERT_VECTOR_TYPE(paramMask, PS_TYPE_U8, false);
+            PS_ASSERT_VECTORS_SIZE_EQUAL(params, paramMask, false);
+        }
+    }
+    PS_ASSERT_PTR_NON_NULL(x, false);
+    for (psS32 i = 0 ; i < x->n ; i++) {
+        psVector *coord = (psVector *) (x->data[i]);
+        PS_ASSERT_VECTOR_NON_NULL(coord, false);
+        PS_ASSERT_VECTOR_TYPE(coord, PS_TYPE_F32, false);
+    }
+    PS_ASSERT_VECTOR_NON_NULL(y, false);
+    PS_ASSERT_VECTOR_NON_EMPTY(y, false);
+    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(x, y, false);
+    if (yWt != NULL) {
+        PS_ASSERT_VECTOR_TYPE(yWt, PS_TYPE_F32, false);
+        PS_ASSERT_VECTORS_SIZE_EQUAL(y, yWt, false);
+    }
+    PS_ASSERT_PTR_NON_NULL(func, false);
+
+    psMinimizeLMLimitFunc checkLimits = NULL;
+    if (constraint) {
+        checkLimits = constraint->checkLimits;
+    }
+
+    // this function has test and current values for several things
+    // the current best value is in lower case
+    // the next guess value is in upper case
+
+    // allocate internal arrays (current vs Guess)
+    psImage *Alpha = NULL;
+    psVector *Beta = NULL;
+
+    // Alpha & Beta only contain elements to represent the unmasked parameters
+    if (!psMinLM_AllocAB (&Alpha, &Beta, params, paramMask)) {
+	psAbort ("programming error: no unmasked parameters to be fit\n");
+    }
+    
+    psImage *alpha   = psImageAlloc(Alpha->numCols, Alpha->numRows, PS_TYPE_F32);
+    psVector *beta   = psVectorAlloc(Beta->n, PS_TYPE_F32);
+    psVector *Params = psVectorAlloc(params->n, PS_TYPE_F32);
+
+    psVector *dy     = NULL;
+    psF32 Chisq = 0.0;
+    psF32 lambda = 0.001;
+    psF32 dLinear = 0.0;
+
+    // the user provides the error or NULL.  we need to convert
+    // to appropriate weights
+    if (yWt != NULL) {
+        dy = (psVector *) yWt;
+    } else {
+        dy = psVectorAlloc(y->n, PS_TYPE_F32);
+        psVectorInit(dy, 1.0);
+    }
+
+    // calculate initial alpha and beta, set chisq (min->value)
+    min->value = psMinLM_SetABX(alpha, beta, params, paramMask, x, y, dy, func);
+    if (isnan(min->value)) {
+        min->iter = min->maxIter;
+        return(false);
+    }
+    // dump some useful info if trace is defined
+    if (psTraceGetLevel("psLib.math") >= 6) {
+        p_psImagePrint(psTraceGetDestination(), alpha, "alpha guess (0)");
+        p_psVectorPrint(psTraceGetDestination(), beta, "beta guess (0)");
+    }
+    if (psTraceGetLevel("psLib.math") >= 5) {
+        p_psVectorPrint(psTraceGetDestination(), params, "params guess (0)");
+    }
+
+    // iterate until the tolerance is reached, or give up
+    while ((min->iter < min->maxIter) && ((min->lastDelta > min->tol) || !isfinite(min->lastDelta))) {
+        psTrace("psLib.math", 5, "Iteration number %d.  (max iterations is %d).\n", min->iter, min->maxIter);
+        psTrace("psLib.math", 5, "Last delta is %f.  Min->tol is %f.\n", min->lastDelta, min->tol);
+
+        // set a new guess for Alpha, Beta, Params
+        if (!psMinLM_GuessABP(Alpha, Beta, Params, alpha, beta, params, paramMask, checkLimits, lambda, &dLinear)) {
+            min->iter ++;
+            lambda *= 10.0;
+            continue;
+        }
+
+        // dump some useful info if trace is defined
+        if (psTraceGetLevel("psLib.math") >= 6) {
+            p_psImagePrint(psTraceGetDestination(), Alpha, "Alpha guess (1)");
+            p_psVectorPrint(psTraceGetDestination(), Beta, "Beta guess (1)");
+            p_psVectorPrint(psTraceGetDestination(), beta, "beta current (1)");
+        }
+        if (psTraceGetLevel("psLib.math") >= 5) {
+            p_psVectorPrint(psTraceGetDestination(), Params, "params guess (1)");
+        }
+
+        // calculate Chisq for new guess, update Alpha & Beta
+        Chisq = psMinLM_SetABX(Alpha, Beta, Params, paramMask, x, y, dy, func);
+        if (isnan(Chisq)) {
+            min->iter ++;
+            lambda *= 10.0;
+            continue;
+        }
+
+        // convergence criterion:
+        // compare the delta (min->value - Chisq) with the
+        // expected delta from the linear model (dLinear)
+        // accept new guess if it is an improvement (rho > 0), or else increase lambda
+        psF32 rho = (min->value - Chisq) / dLinear;
+
+        psTrace("psLib.math", 5, "last chisq: %f, new chisq %f, delta: %f, dLinear: %f, rho: %f, lambda: %f\n", min->value,
+                Chisq, min->lastDelta, dLinear, rho, lambda);
+
+        // dump some useful info if trace is defined
+        if (psTraceGetLevel("psLib.math") >= 6) {
+            p_psImagePrint(psTraceGetDestination(), Alpha, "alpha guess (2)");
+            p_psVectorPrint(psTraceGetDestination(), Beta, "beta guess (2)");
+        }
+
+        /* if (Chisq < min->value) {  */
+        if (rho > 0.0) {
+            min->lastDelta = (min->value - Chisq) / (dy->n - params->n);
+            min->value = Chisq;
+            alpha  = psImageCopy(alpha, Alpha, PS_TYPE_F32);
+            beta   = psVectorCopy(beta, Beta, PS_TYPE_F32);
+            params = psVectorCopy(params, Params, PS_TYPE_F32);
+            lambda *= 0.25;
+        } else {
+            lambda *= 10.0;
+        }
+        min->iter++;
+    }
+    psTrace("psLib.math", 5, "chisq: %f, last delta: %f, Niter: %d\n", min->value, min->lastDelta, min->iter);
+
+    // construct & return the covariance matrix (if requested)
+    if (covar != NULL) {
+        if (!psMinLM_GuessABP(Alpha, Beta, Params, alpha, beta, params, paramMask, NULL, 0.0, NULL)) {
+            psTrace ("psLib.math", 5, "failure to calculate covariance matrix\n");
+        }
+	// set covar values which are not masked
+	psImageInit (covar, 0.0);
+	for (int j = 0, J = 0; j < params->n; j++) {
+	    if (paramMask && (paramMask->data.U8[j])) {
+		covar->data.F32[j][j] = 1.0;
+		continue;
+	    }
+	    for (int k = 0, K = 0; k < params->n; k++) {
+		if (paramMask && (paramMask->data.U8[k])) continue;
+		covar->data.F32[j][k] = Alpha->data.F32[J][K];
+		K++;
+	    }
+	    J++;
+	}
+    }
+
+    // free the internal temporary data
+    psFree(alpha);
+    psFree(Alpha);
+    psFree(beta);
+    psFree(Beta);
+    psFree(Params);
+    if (yWt == NULL) {
+        psFree(dy);
+    }
+    if (min->iter == min->maxIter) {
+        psTrace("psLib.math", 3, "---- end (false) ----\n");
+        return(false);
+    }
+    psTrace("psLib.math", 3, "---- end (true) ----\n");
+    return(true);
+}
+
+bool psMinLM_AllocAB (psImage **Alpha, psVector **Beta, const psVector *params, const psVector *paramMask) {
+
+    assert (Alpha);
+    assert (Beta);
+    assert (params);
+
+    int nParams = params->n;
+
+    // count unmasked parameters
+    if (paramMask) {
+	nParams = 0;
+	for (int i = 0; i < paramMask->n; i++) {
+	    if (paramMask->data.U8[i]) continue;
+	    nParams ++;
+	}
+    }
+
+    if (nParams == 0) { 
+	return false;
+    }
+
+    *Alpha = psImageAlloc(nParams, nParams, PS_TYPE_F32);
+    *Beta  = psVectorAlloc(nParams, PS_TYPE_F32);
+    return true;
+}
+
+static void minimizationFree(psMinimization *min)
+{
+    // There are no dynamically allocated items
+}
+
+psMinimization *psMinimizationAlloc(int maxIter,
+                                    float tol)
+{
+    PS_ASSERT_INT_NONNEGATIVE(maxIter, NULL);
+
+    psMinimization *min = psAlloc(sizeof(psMinimization));
+    psMemSetDeallocator(min, (psFreeFunc)minimizationFree);
+    P_PSMINIMIZATION_SET_MAXITER(min,maxIter);
+    P_PSMINIMIZATION_SET_TOL(min,tol);
+    min->value = 0.0;
+    min->iter = 0;
+    min->lastDelta = NAN;
+
+    return(min);
+}
+
+bool psMemCheckMinimization(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return( psMemGetDeallocator(ptr) == (psFreeFunc)minimizationFree );
+}
+
+
+static void constraintFree(psMinConstraint *tmp)
+{
+    if (tmp == NULL)
+        return;
+
+    psFree (tmp->paramMask);
+}
+
+psMinConstraint* psMinConstraintAlloc()
+{
+    psMinConstraint *tmp = psAlloc(sizeof(psMinConstraint));
+    psMemSetDeallocator(tmp, (psFreeFunc)constraintFree);
+    tmp->paramMask = NULL;
+    tmp->checkLimits = NULL;
+
+    return(tmp);
+}
+
+bool psMemCheckConstraint(psPtr tmp)
+{
+    return(psMemGetDeallocator(tmp) == (psFreeFunc) constraintFree);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizeLMM.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizeLMM.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizeLMM.h	(revision 22158)
@@ -0,0 +1,180 @@
+/* @file  psMinimizeLMM.c
+ * @brief basic minimization functions
+ *
+ * This file will contain function prototypes for various Levenberg-Marquadt
+ * minimization routines.
+ *
+ * @author GLG, MHPCC
+ *
+ * @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-09-28 00:35:20 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_MINIMIZE_LMM_H
+#define PS_MINIMIZE_LMM_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+#include "psVector.h"
+#include "psMemory.h"
+#include "psArray.h"
+#include "psImage.h"
+#include "psMatrix.h"
+#include "psPolynomial.h"
+#include "psSpline.h"
+#include "psStats.h"
+#include "psTrace.h"
+#include "psError.h"
+#include "psConstants.h"
+
+#define PS_DETERMINE_BRACKET_STEP_SIZE 0.10
+#define PS_MAX_LMM_ITERATIONS 100
+#define PS_MAX_MINIMIZE_ITERATIONS 100
+#define P_PSMINIMIZATION_SET_MAXITER(m,val) *(int*)&m->maxIter = val
+        #define P_PSMINIMIZATION_SET_TOL(m,val) *(float*)&m->tol = val
+
+                typedef enum {
+                    PS_MINIMIZE_BETA_LIMIT,
+                    PS_MINIMIZE_PARAM_MIN,
+                    PS_MINIMIZE_PARAM_MAX
+                } psMinConstraintMode;
+
+/** Specifies the format of a user-defined function that the general Levenberg-
+ *  Marquardt minimizer routine will accept.
+ *
+ *  @return float:   the single float value of the function given the parameters,
+ *       positions, and derivatives.
+ */
+typedef
+float (*psMinimizeLMChi2Func)(
+    psVector *deriv,                   ///< derivatives of the function
+    const psVector *params,            ///< the parameters used to evaluate the function
+    const psVector *x                  ///< positions for evaluation
+);
+
+/** Specifies the format of a user-defined function which check the parameters
+ *  against the allowed limits.  used by the general Levenberg-Marquardt minimizer.
+ *
+ *  @return float:   the single float value of the function given the parameters,
+ *       positions, and derivatives.
+ */
+typedef
+bool (*psMinimizeLMLimitFunc)(
+    psMinConstraintMode mode,   ///< which limit to check
+    int nParam,    ///< which param to check
+    float *params,   ///< current param value set
+    float *beta       ///< current beta value, if needed
+);
+
+/** A data structure for minimization routines.
+ *
+ *  Contains numerical analysis parameters/values
+ */
+typedef struct
+{
+    const int maxIter;                 ///< Convergence limit
+    const float tol;                   ///< Error Tolerance
+    float value;                       ///< Value of function at minimum
+    int iter;                          ///< Number of iterations to date
+    float lastDelta;                   ///< The last difference for the fit
+}
+psMinimization;
+
+/** A data structure for minimization routines.
+ *
+ *
+ */
+typedef struct
+{
+    psVector *paramMask;                ///< valid / invalid parameters
+    psMinimizeLMLimitFunc checkLimits; ///< user-supplied function to test the parameter limits
+}
+psMinConstraint;
+
+psMinConstraint *psMinConstraintAlloc() PS_ATTR_MALLOC;
+
+/** Allocates a psMinimization structure.
+ *
+ *  @return psMinimization* :   a new psMinimization struct
+ */
+psMinimization *psMinimizationAlloc(
+    int maxIter,                       ///< Number of minimization iterations to perform.
+    float tol                          ///< Requested error tolerance
+) PS_ATTR_MALLOC;
+
+/*  Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psMinimization structure, false otherwise.
+ */
+bool psMemCheckMinimization(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+/** Minimizes a specified function based on the Levenberg-Marquardt method.
+ *
+ *  @return bool:   True if successful.
+ */
+bool psMinimizeLMChi2(
+    psMinimization *min,               ///< Minimization specification
+    psImage *covar,                    ///< Covariance matrix
+    psVector *params,                  ///< "Best Guess" for the parameters that minimize func
+    psMinConstraint *constraint, ///< Constraints on the parameters
+    const psArray *x,                  ///< Measurement ordinates of multiple vectors
+    const psVector *y,                 ///< Measurement coordinates
+    const psVector *yWt,               ///< Errors in the measurement coordinates
+    psMinimizeLMChi2Func func          ///< Specified function
+);
+
+bool psMinimizeGaussNewtonDelta (
+    psVector *delta,
+    const psVector *params,
+    const psVector *paramMask,
+    const psArray  *x,
+    const psVector *y,
+    const psVector *yErr,
+    psMinimizeLMChi2Func func
+);
+
+/** Function used to set parameters for generating "best guess" in minimizing Chi-Squared value.
+ *
+ *  @return psF32:    Chi-squared value for new guess
+ */
+psF32 psMinLM_SetABX (
+    psImage  *alpha,                   ///< alpha guess
+    psVector *beta,                    ///< beta guess
+    const psVector *params,            ///< params guess
+    const psVector *paramMask,         ///< param mask
+    const psArray  *x,                 ///< Measurement ordinates
+    const psVector *y,                 ///< Measurement coordinates
+    const psVector *dy,                ///< Weights calculated from y-errors
+    psMinimizeLMChi2Func func          ///< Specified function
+);
+
+
+bool psMinLM_GuessABP(
+    psImage  *Alpha,
+    psVector *Beta,
+    psVector *Params,
+    const psImage  *alpha,
+    const psVector *beta,
+    const psVector *params,
+    const psVector *paramMask,
+    psMinimizeLMLimitFunc checkLimits,
+    psF32 lambda,
+    psF32 *dLinear
+);
+
+psF32 psMinLM_dLinear(
+    const psVector *Beta,
+    const psVector *beta,
+    psF32 lambda);
+
+// allocate alpha and beta for unmasked parameters only 
+bool psMinLM_AllocAB (psImage **Alpha, psVector **Beta, const psVector *params, const psVector *paramMask);
+
+/// @}
+#endif // #ifndef PS_MINIMIZE_LMM_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizeLMM_ND.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizeLMM_ND.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizeLMM_ND.c	(revision 22158)
@@ -0,0 +1,577 @@
+/** @file  psMinimizeLMM_ND.c
+ *  \brief Levenberg-Marqardt minimization of N-D functions of N-D variables.  
+ *  @ingroup Math
+ *
+ *  Levenberg-Marqardt minimization of an N-dimensional function of N-diminsional independent
+ *  variables.  This code is based on the 1-D function version of N-D variables in psMinimizeLMM.c 
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-04-11 08:01:29 $
+ *
+ *  Copyright 2007 Institute for Astronomy, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <float.h>
+#include <math.h>
+#include "psAbort.h"
+#include "psAssert.h"
+#include "psVector.h"
+#include "psMemory.h"
+#include "psArray.h"
+#include "psImage.h"
+#include "psMatrix.h"
+#include "psTrace.h"
+#include "psError.h"
+#include "psConstants.h"
+#include "psImage.h"
+#include "psLogMsg.h"
+
+// the main user API: minimize the chisq of the N-D function
+bool psMinimizeLMChi2(
+    psMinimization *min,
+    psImage *covar,
+    psVector *params,
+    psMinConstraint *constraint,
+    const psArray *x,
+    const psArray *y,
+    const psArray *yWt,
+    psMinimizeLMNDChi2Func func)
+{
+    psTrace("psLib.math", 3, "---- begin ----\n");
+    PS_ASSERT_PTR_NON_NULL(min, false);
+    PS_ASSERT_VECTOR_NON_NULL(params, false);
+    PS_ASSERT_VECTOR_NON_EMPTY(params, false);
+    PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32, false);
+    psVector *paramMask = NULL;
+    if (constraint != NULL) {
+        paramMask = constraint->paramMask;
+        if (paramMask != NULL) {
+            PS_ASSERT_VECTOR_TYPE(paramMask, PS_TYPE_U8, false);
+            PS_ASSERT_VECTORS_SIZE_EQUAL(params, paramMask, false);
+        }
+    }
+    PS_ASSERT_PTR_NON_NULL(x, false);
+    for (psS32 i = 0 ; i < x->n ; i++) {
+        psVector *coord = (psVector *) (x->data[i]);
+        PS_ASSERT_VECTOR_NON_NULL(coord, false);
+        PS_ASSERT_VECTOR_TYPE(coord, PS_TYPE_F32, false);
+    }
+    PS_ASSERT_PTR_NON_NULL(y, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(x, y, false);
+    for (psS32 i = 0 ; i < y->n ; i++) {
+        psVector *value = (psVector *) (y->data[i]);
+        PS_ASSERT_VECTOR_NON_NULL(value, false);
+        PS_ASSERT_VECTOR_TYPE(value, PS_TYPE_F32, false);
+    }
+    if (yWt != NULL) {
+	PS_ASSERT_VECTORS_SIZE_EQUAL(x, yWt, false);
+	for (psS32 i = 0 ; i < yWt->n ; i++) {
+	    psVector *value = (psVector *) (yWt->data[i]);
+	    PS_ASSERT_VECTOR_NON_NULL(value, false);
+	    PS_ASSERT_VECTOR_TYPE(value, PS_TYPE_F32, false);
+	}
+    }
+    PS_ASSERT_PTR_NON_NULL(func, false);
+
+    psMinimizeLMLimitFunc checkLimits = NULL;
+    if (constraint) {
+        checkLimits = constraint->checkLimits;
+    }
+
+    // This function has 'test' and 'current' values for several things (alpha, beta,
+    // etc).  The current best value is in lower case; the next guess value is in upper
+    // case
+
+    // allocate internal arrays (current vs Guess)
+    psImage *Alpha = NULL;
+    psVector *Beta = NULL;
+
+    // Alpha & Beta only contain elements to represent the unmasked parameters
+    if (!psMinLM_AllocAB (&Alpha, &Beta, params, paramMask)) {
+	psAbort ("programming error: no unmasked parameters to be fit\n");
+    }
+    
+    psImage *alpha   = psImageAlloc(Alpha->numCols, Alpha->numRows, PS_TYPE_F32);
+    psVector *beta   = psVectorAlloc(Beta->n, PS_TYPE_F32);
+    psVector *Params = psVectorAlloc(params->n, PS_TYPE_F32);
+
+    psVector *dy     = NULL;
+    psF32 Chisq = 0.0;
+    psF32 lambda = 0.001;
+    psF32 dLinear = 0.0;
+
+    // the user provides the error or NULL.  we need to convert
+    // to appropriate weights
+    if (yWt != NULL) {
+        dy = (psVector *) yWt;
+    } else {
+        dy = psVectorAlloc(y->n, PS_TYPE_F32);
+        psVectorInit(dy, 1.0);
+    }
+
+    // calculate initial alpha and beta, set chisq (min->value)
+    min->value = psMinLM_SetABX(alpha, beta, params, paramMask, x, y, dy, func);
+    if (isnan(min->value)) {
+        min->iter = min->maxIter;
+        return(false);
+    }
+    // dump some useful info if trace is defined
+    if (psTraceGetLevel("psLib.math") >= 6) {
+        p_psImagePrint(psTraceGetDestination(), alpha, "alpha guess (0)");
+        p_psVectorPrint(psTraceGetDestination(), beta, "beta guess (0)");
+    }
+    if (psTraceGetLevel("psLib.math") >= 5) {
+        p_psVectorPrint(psTraceGetDestination(), params, "params guess (0)");
+    }
+
+    // iterate until the tolerance is reached, or give up
+    while ((min->iter < min->maxIter) && ((min->lastDelta > min->tol) || !isfinite(min->lastDelta))) {
+        psTrace("psLib.math", 5, "Iteration number %d.  (max iterations is %d).\n", min->iter, min->maxIter);
+        psTrace("psLib.math", 5, "Last delta is %f.  Min->tol is %f.\n", min->lastDelta, min->tol);
+
+        // set a new guess for Alpha, Beta, Params
+        if (!psMinLM_GuessABP(Alpha, Beta, Params, alpha, beta, params, paramMask, checkLimits, lambda, &dLinear)) {
+            min->iter ++;
+            lambda *= 10.0;
+            continue;
+        }
+
+        // dump some useful info if trace is defined
+        if (psTraceGetLevel("psLib.math") >= 6) {
+            p_psImagePrint(psTraceGetDestination(), Alpha, "Alpha guess (1)");
+            p_psVectorPrint(psTraceGetDestination(), Beta, "Beta guess (1)");
+            p_psVectorPrint(psTraceGetDestination(), beta, "beta current (1)");
+        }
+        if (psTraceGetLevel("psLib.math") >= 5) {
+            p_psVectorPrint(psTraceGetDestination(), Params, "params guess (1)");
+        }
+
+        // calculate Chisq for new guess, update Alpha & Beta
+        Chisq = psMinLM_SetABX(Alpha, Beta, Params, paramMask, x, y, dy, func);
+        if (isnan(Chisq)) {
+            min->iter ++;
+            lambda *= 10.0;
+            continue;
+        }
+
+        // convergence criterion:
+        // compare the delta (min->value - Chisq) with the
+        // expected delta from the linear model (dLinear)
+        // accept new guess if it is an improvement (rho > 0), or else increase lambda
+        psF32 rho = (min->value - Chisq) / dLinear;
+
+        psTrace("psLib.math", 5, "last chisq: %f, new chisq %f, delta: %f, dLinear: %f, rho: %f, lambda: %f\n", min->value,
+                Chisq, min->lastDelta, dLinear, rho, lambda);
+
+        // dump some useful info if trace is defined
+        if (psTraceGetLevel("psLib.math") >= 6) {
+            p_psImagePrint(psTraceGetDestination(), Alpha, "alpha guess (2)");
+            p_psVectorPrint(psTraceGetDestination(), Beta, "beta guess (2)");
+        }
+
+        /* if (Chisq < min->value) {  */
+        if (rho > 0.0) {
+            min->lastDelta = (min->value - Chisq) / (dy->n - params->n);
+            min->value = Chisq;
+            alpha  = psImageCopy(alpha, Alpha, PS_TYPE_F32);
+            beta   = psVectorCopy(beta, Beta, PS_TYPE_F32);
+            params = psVectorCopy(params, Params, PS_TYPE_F32);
+            lambda *= 0.25;
+        } else {
+            lambda *= 10.0;
+        }
+        min->iter++;
+    }
+    psTrace("psLib.math", 5, "chisq: %f, last delta: %f, Niter: %d\n", min->value, min->lastDelta, min->iter);
+
+    // construct & return the covariance matrix (if requested)
+    if (covar != NULL) {
+        if (!psMinLM_GuessABP(Alpha, Beta, Params, alpha, beta, params, paramMask, NULL, 0.0, NULL)) {
+            psTrace ("psLib.math", 5, "failure to calculate covariance matrix\n");
+        }
+	// set covar values which are not masked
+	psImageInit (covar, 0.0);
+	for (int j = 0, J = 0; j < params->n; j++) {
+	    if (paramMask && (paramMask->data.U8[j])) {
+		covar->data.F32[j][j] = 1.0;
+		continue;
+	    }
+	    for (int k = 0, K = 0; k < params->n; k++) {
+		if (paramMask && (paramMask->data.U8[k])) continue;
+		covar->data.F32[j][k] = Alpha->data.F32[J][K];
+		K++;
+	    }
+	    J++;
+	}
+    }
+
+    // free the internal temporary data
+    psFree(alpha);
+    psFree(Alpha);
+    psFree(beta);
+    psFree(Beta);
+    psFree(Params);
+    if (yWt == NULL) {
+        psFree(dy);
+    }
+    if (min->iter == min->maxIter) {
+        psTrace("psLib.math", 3, "---- end (false) ----\n");
+        return(false);
+    }
+    psTrace("psLib.math", 3, "---- end (true) ----\n");
+    return(true);
+}
+
+// Alpha & Beta only represent unmasked values
+bool psMinLM_GuessABP(
+    psImage  *Alpha,
+    psVector *Beta,
+    psVector *Params,
+    const psImage  *alpha,
+    const psVector *beta,
+    const psVector *params,
+    const psVector *paramMask,
+    psMinimizeLMLimitFunc checkLimits,
+    psF32 lambda,
+    psF32 *dLinear)
+{
+    PS_ASSERT_VECTOR_TYPE(Alpha,     PS_TYPE_F32,  false);
+    PS_ASSERT_VECTOR_TYPE(Beta,      PS_TYPE_F32,  false);
+    PS_ASSERT_VECTOR_TYPE(Params,    PS_TYPE_F32,  false);
+    PS_ASSERT_VECTOR_TYPE(alpha,     PS_TYPE_F32,  false);
+    PS_ASSERT_VECTOR_TYPE(beta,      PS_TYPE_F32,  false);
+    PS_ASSERT_VECTOR_TYPE(params,    PS_TYPE_F32,  false);
+    if (paramMask) {
+        PS_ASSERT_VECTOR_TYPE(paramMask, PS_TYPE_MASK, false);
+    }
+
+    assert (alpha->numCols == beta->n);
+    assert (alpha->numCols == alpha->numRows);
+
+    // set new guess values, applying (1+lambda) scaling to pivots
+    Beta = psVectorCopy(Beta, beta, PS_TYPE_F32);
+    Alpha = psImageCopy(Alpha, alpha, PS_TYPE_F32);
+    for (int j = 0; j < Alpha->numCols; j++) {
+        Alpha->data.F32[j][j] = alpha->data.F32[j][j] * (1.0 + lambda);
+    }
+
+    // error and clear above if kept?
+    if (false == psMatrixGJSolveF32(Alpha, Beta)) {
+        psTrace ("psLib.math", 4, "singular matrix in Guess ABP\n");
+        return(false);
+    }
+
+    // measure linear model prediction
+    // (we must do this before truncating Beta below)
+    if (dLinear) {
+	*dLinear = psMinLM_dLinear(Beta, beta, lambda);
+    }
+
+    // full-length Beta for checkLimits functions 
+    psVector *tmpBeta = psVectorAlloc(params->n, PS_TYPE_F32);
+    psVectorInit (tmpBeta, 0.0);
+
+    // set tmpBeta values which are not masked
+    for (int j = 0, n = 0; j < params->n; j++) {
+	if (paramMask && (paramMask->data.U8[j])) continue;
+	tmpBeta->data.F32[j] = Beta->data.F32[n];
+	n++;
+    }
+
+    // apply Beta to get new Params values
+    for (int j = 0; j < params->n; j++) {
+        if (paramMask && (paramMask->data.U8[j])) {
+            Params->data.F32[j] = params->data.F32[j];
+            continue;
+        }
+        // apply beta limits
+        if (checkLimits) {
+            checkLimits (PS_MINIMIZE_BETA_LIMIT, j, Params->data.F32, tmpBeta->data.F32);
+	}
+
+        Params->data.F32[j] = params->data.F32[j] - tmpBeta->data.F32[j];
+
+        // compare new params to param limits
+        if (checkLimits) {
+            checkLimits (PS_MINIMIZE_PARAM_MIN,  j, Params->data.F32, tmpBeta->data.F32);
+            checkLimits (PS_MINIMIZE_PARAM_MAX,  j, Params->data.F32, tmpBeta->data.F32);
+	}
+    }
+
+    // apply tmpBeta after limits have been checked
+    for (int j = 0, n = 0; j < params->n; j++) {
+	if (paramMask && (paramMask->data.U8[j])) continue;
+	Beta->data.F32[n] = tmpBeta->data.F32[j];
+	n++;
+    }
+
+    psFree (tmpBeta);
+    return(true);
+}
+
+bool psMinimizeGaussNewtonDelta(
+    psVector *delta,
+    const psVector *params,
+    const psVector *paramMask,
+    const psArray  *x,
+    const psVector *y,
+    const psVector *yWt,
+    psMinimizeLMChi2Func func)
+{
+    psTrace("psLib.math", 3, "---- begin ----\n");
+
+    // allocate internal arrays (current vs Guess)
+    psImage *Alpha = NULL;
+    psVector *Beta = NULL;
+
+    psVectorInit (delta, 0.0);
+
+    // Alpha & Beta only contain elements to represent the unmasked parameters
+    // if none are available, return false
+    if (!psMinLM_AllocAB (&Alpha, &Beta, params, paramMask)) {
+	return false;
+    }
+
+    psImage *alpha   = psImageAlloc(Alpha->numCols, Alpha->numRows, PS_TYPE_F32);
+    psVector *Params = psVectorAlloc(params->n, PS_TYPE_F32);
+
+    psVector *dy     = NULL;
+    bool retValue = true;
+
+    // the user provides the error or NULL.  we need to convert
+    // to appropriate weights
+    if (yWt != NULL) {
+        dy = (psVector *) yWt;
+    } else {
+        dy = psVectorAlloc(y->n, PS_TYPE_F32);
+        psVectorInit(dy, 1.0);
+    }
+
+    // XXX should we give up if chisq is nan?
+    psF32 chisq = psMinLM_SetABX(alpha, Beta, params, paramMask, x, y, dy, func);
+    if (isnan(chisq)) {
+        psTrace ("psLib.math", 5, "psMinLM_SetABX() returned a NAN chisq.\n");
+        retValue = false;
+    }
+
+    psTrace("psLib.math", 5, "psMinLM_SetABX() was succesful\n");
+    // dump some useful info if trace is defined
+    if (psTraceGetLevel("psLib.math") >= 6) {
+        p_psImagePrint(psTraceGetDestination(), alpha, "alpha guess (0)");
+        p_psVectorPrint(psTraceGetDestination(), Beta, "beta guess (0)");
+        p_psVectorPrint(psTraceGetDestination(), params, "params guess (0)");
+    }
+
+    bool status = psMinLM_GuessABP(Alpha, delta, Params, alpha, Beta, params, paramMask, NULL, 0.0, NULL);
+    if (!status) {
+        psTrace ("psLib.math", 5, "psMinLM_GuessABP() returned FALSE.\n");
+        retValue = false;
+    }
+    psTrace("psLib.math", 5, "psMinLM_GuessABP() was succesful\n");
+    if (psTraceGetLevel("psLib.math") >= 6) {
+        p_psImagePrint(psTraceGetDestination(), Alpha, "alpha guess (1)");
+        p_psVectorPrint(psTraceGetDestination(), delta, "delta guess (1)");
+        p_psVectorPrint(psTraceGetDestination(), Params, "params guess (1)");
+    }
+
+    psFree(alpha);
+    psFree(Alpha);
+    psFree(Beta);
+    psFree(Params);
+    if (yWt == NULL) {
+        psFree(dy);
+    }
+    psTrace("psLib.math", 3, "---- end ----\n");
+    return(retValue);
+}
+
+// measure linear model prediction
+psF32 psMinLM_dLinear(
+    const psVector *Beta,
+    const psVector *beta,
+    psF32 lambda)
+{
+
+    /* get linear model prediction */
+    psF32 dLinear = 0;
+    psF32 *B = Beta->data.F32;
+    psF32 *b = beta->data.F32;
+
+    float dh = 0.0, sh = 0.0, Sh = 0.0;
+
+    // beta only counts unmasked parameters
+    for (int i = 0; i < beta->n; i++) {
+	dh = lambda*B[i] + b[i];
+	sh = 0.5*B[i]*dh;
+	Sh += sh;
+        dLinear += lambda*PS_SQR(B[i]) + B[i]*b[i];
+    }
+    return(0.5*dLinear);
+}
+
+// alpha, beta, params are already allocated
+psF32 psMinLM_SetABX(
+    psImage  *alpha,
+    psVector *beta,
+    const psVector *params,
+    const psVector *paramMask,
+    const psArray  *x,
+    const psArray  *y,
+    const psArray *dy,
+    psMinimizeLMNDChi2Func func)
+{
+    PS_ASSERT_IMAGE_NON_NULL(alpha, NAN);
+    PS_ASSERT_VECTOR_NON_NULL(beta, NAN);
+    PS_ASSERT_VECTOR_NON_NULL(params, NAN);
+    PS_ASSERT_PTR_NON_NULL(x, NAN);
+    PS_ASSERT_PTR_NON_NULL(y, NAN);
+    PS_ASSERT_PTR_NON_NULL(dy, NAN);
+
+    PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32, false);
+    if (paramMask) {
+        PS_ASSERT_VECTOR_TYPE(paramMask, PS_TYPE_MASK, false);
+    }
+
+    psF32 chisq;
+    psF32 delta;
+    psF32 weight;
+
+    int nValue = ((psVector *)(y->data[0]))->n;
+
+    psVector *deriv = psVectorAlloc(params->n, PS_TYPE_F32);
+    psVector *ymodel = psVectorAlloc(nValue, PS_TYPE_F32);
+
+    // zero alpha, beta, and chisq for summing below
+    psImageInit (alpha, 0.0);
+    psVectorInit (beta, 0.0);
+    chisq = 0.0;
+
+    // calculate chisq, alpha, beta. alpha & beta only represent unmasked parameters; skip
+    // masked ones
+    for (psS32 i = 0; i < y->n; i++) {
+        func (ymodel, deriv, params, (psVector *) x->data[i]);
+
+	psVector *yvalue = y->data[i];
+	psVector *dyvalue = dy->data[i];
+
+	for (int k = 0; k < nValue; k++) {
+	    delta = ymodel->data.F32[k] - yvalue->data.F32[k];
+	    chisq += PS_SQR(delta) * dyvalue->data.F32[k];
+
+	    assert (!isnan(dyvalue->data.F32[k]));
+	    assert (!isnan(delta));
+	    assert (!isnan(chisq));
+	}
+
+	// we track alpha,beta and params,deriv separately
+        for (int j = 0, J = 0; j < params->n; j++) {
+            if (paramMask && (paramMask->data.U8[j])) continue;
+
+            weight = deriv->data.F32[j] * dy->data.F32[i];
+
+            for (int k = 0, K = 0; k <= j; k++) {
+                if (paramMask && (paramMask->data.U8[k])) continue;
+                alpha->data.F32[J][K] += weight * deriv->data.F32[k];
+		K++;
+            }
+            beta->data.F32[J] += weight * delta;
+	    J++;
+        }
+    }
+
+    // calculate lower-left half of alpha
+    for (int j = 1; j < alpha->numCols; j++) {
+        for (int k = 0; k < j; k++) {
+            alpha->data.F32[k][j] = alpha->data.F32[j][k];
+        }
+    }
+
+    psFree(deriv);
+    return(chisq);
+}
+
+
+bool psMinLM_AllocAB (psImage **Alpha, psVector **Beta, const psVector *params, const psVector *paramMask) {
+
+    assert (Alpha);
+    assert (Beta);
+    assert (params);
+
+    int nParams = params->n;
+
+    // count unmasked parameters
+    if (paramMask) {
+	nParams = 0;
+	for (int i = 0; i < paramMask->n; i++) {
+	    if (paramMask->data.U8[i]) continue;
+	    nParams ++;
+	}
+    }
+
+    if (nParams == 0) { 
+	return false;
+    }
+
+    *Alpha = psImageAlloc(nParams, nParams, PS_TYPE_F32);
+    *Beta  = psVectorAlloc(nParams, PS_TYPE_F32);
+    return true;
+}
+
+static void minimizationFree(psMinimization *min)
+{
+    // There are no dynamically allocated items
+}
+
+psMinimization *psMinimizationAlloc(int maxIter,
+                                    float tol)
+{
+    PS_ASSERT_INT_NONNEGATIVE(maxIter, NULL);
+
+    psMinimization *min = psAlloc(sizeof(psMinimization));
+    psMemSetDeallocator(min, (psFreeFunc)minimizationFree);
+    P_PSMINIMIZATION_SET_MAXITER(min,maxIter);
+    P_PSMINIMIZATION_SET_TOL(min,tol);
+    min->value = 0.0;
+    min->iter = 0;
+    min->lastDelta = NAN;
+
+    return(min);
+}
+
+bool psMemCheckMinimization(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return( psMemGetDeallocator(ptr) == (psFreeFunc)minimizationFree );
+}
+
+
+static void constraintFree(psMinConstraint *tmp)
+{
+    if (tmp == NULL)
+        return;
+
+    psFree (tmp->paramMask);
+}
+
+psMinConstraint* psMinConstraintAlloc()
+{
+    psMinConstraint *tmp = psAlloc(sizeof(psMinConstraint));
+    psMemSetDeallocator(tmp, (psFreeFunc)constraintFree);
+    tmp->paramMask = NULL;
+    tmp->checkLimits = NULL;
+
+    return(tmp);
+}
+
+bool psMemCheckConstraint(psPtr tmp)
+{
+    return(psMemGetDeallocator(tmp) == (psFreeFunc) constraintFree);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizeLMM_ND.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizeLMM_ND.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizeLMM_ND.h	(revision 22158)
@@ -0,0 +1,106 @@
+/* @file  psMinimizeLMM.h
+ * @brief Levenberg-Marqardt minimization of N-D functions of N-D variables.  
+ * @ingroup Math
+ *
+ *  Levenberg-Marqardt minimization of an N-dimensional function of N-diminsional independent
+ *  variables.  This code is based on the 1-D function version of N-D variables in psMinimizeLMM.c 
+ *
+ *  @author EAM, IfA
+ *  Copyright 2007 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PS_MINIMIZE_LMM_ND_H
+#define PS_MINIMIZE_LMM_ND_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+/* Format of a user-defined function that the general Levenberg-Marquardt minimizer
+ * routine will accept.
+ *
+ * @return bool: success / failure status.  the N-D function value is returned to the
+ * pre-allocated vector 'value' and the derivatives of the parameters are returned to the
+ * pre-allocated vector 'deriv', iff defined
+ * 
+ */
+typedef bool (*psMinimizeLMNDChi2Func)(
+    psVector *value,                   ///< values of the function
+    psVector *deriv,                   ///< derivatives of the function
+    const psVector *params,            ///< the parameters used to evaluate the function
+    const psVector *x                  ///< positions for evaluation
+    );
+
+/*  Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psMinimization structure, false otherwise.
+ */
+bool psMemCheckMinimization(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+/** Minimizes a specified function based on the Levenberg-Marquardt method.
+ *
+ *  @return bool:   True if successful.
+ */
+bool psMinimizeLMChi2(
+    psMinimization *min,               ///< Minimization specification
+    psImage *covar,                    ///< Covariance matrix
+    psVector *params,                  ///< "Best Guess" for the parameters that minimize func
+    psMinConstraint *constraint, ///< Constraints on the parameters
+    const psArray *x,                  ///< Measurement ordinates of multiple vectors
+    const psVector *y,                 ///< Measurement coordinates
+    const psVector *yWt,               ///< Errors in the measurement coordinates
+    psMinimizeLMChi2Func func          ///< Specified function
+);
+
+bool psMinimizeGaussNewtonDelta (
+    psVector *delta,
+    const psVector *params,
+    const psVector *paramMask,
+    const psArray  *x,
+    const psVector *y,
+    const psVector *yErr,
+    psMinimizeLMChi2Func func
+);
+
+/** Function used to set parameters for generating "best guess" in minimizing Chi-Squared value.
+ *
+ *  @return psF32:    Chi-squared value for new guess
+ */
+psF32 psMinLM_SetABX (
+    psImage  *alpha,                   ///< alpha guess
+    psVector *beta,                    ///< beta guess
+    const psVector *params,            ///< params guess
+    const psVector *paramMask,         ///< param mask
+    const psArray  *x,                 ///< Measurement ordinates
+    const psVector *y,                 ///< Measurement coordinates
+    const psVector *dy,                ///< Weights calculated from y-errors
+    psMinimizeLMChi2Func func          ///< Specified function
+);
+
+
+bool psMinLM_GuessABP(
+    psImage  *Alpha,
+    psVector *Beta,
+    psVector *Params,
+    const psImage  *alpha,
+    const psVector *beta,
+    const psVector *params,
+    const psVector *paramMask,
+    psMinimizeLMLimitFunc checkLimits,
+    psF32 lambda,
+    psF32 *dLinear
+);
+
+psF32 psMinLM_dLinear(
+    const psVector *Beta,
+    const psVector *beta,
+    psF32 lambda);
+
+// allocate alpha and beta for unmasked parameters only 
+bool psMinLM_AllocAB (psImage **Alpha, psVector **Beta, const psVector *params, const psVector *paramMask);
+
+/// @}
+#endif // #ifndef PS_MINIMIZE_LMM_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizePolyFit.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizePolyFit.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizePolyFit.c	(revision 22158)
@@ -0,0 +1,2313 @@
+/** @file  psMinimize.c
+ *  \brief basic minimization functions
+ *  @ingroup Math
+ *
+ *  This file will contain functions to minimize an arbitrary function at
+ *  a data point, fit an arbitrary function to a set of data points, and
+ *  fit a 1-D polynomial to a set of data points.
+ *
+ *  @author GLG, MHPCC
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.32 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-10-09 19:25:45 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ *  XXX: psMatrixLUSolve() does not return error codes when the results are NANs.
+ *
+ *  XXX: For clip-fit functions, what should we do if the mask is NULL?
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/*****************************************************************************/
+/* INCLUDE FILES                                                             */
+/*****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <float.h>
+#include <math.h>
+
+#include "psMinimizePolyFit.h"
+#include "psAssert.h"
+#include "psMinimizeLMM.h"  // For Gauss-Jordan routines
+#include "psStats.h"
+#include "psImage.h"
+#include "psImageStructManip.h"
+#include "psBinaryOp.h"
+#include "psLogMsg.h"
+#include "psMathUtils.h"
+/*****************************************************************************/
+/* DEFINE STATEMENTS                                                         */
+/*****************************************************************************/
+
+# define USE_GAUSS_JORDAN 1
+# define USE_ROBUST_STATS_FOR_CLIPPING 1
+
+#define PS_VECTOR_GEN_CHEBY_INDEX(VEC, SIZE, TYPE) \
+VEC = psVectorAlloc(SIZE, TYPE); \
+if (TYPE == PS_TYPE_F64) { \
+    for (psS32 i = 0 ; i < SIZE ; i++) { \
+        VEC->data.F64[i] = ((2.0 / ((psF64) (SIZE - 1))) * ((psF64) i)) - 1.0; \
+    }\
+} else if (TYPE == PS_TYPE_F32){ \
+    for (psS32 i = 0 ; i < SIZE ; i++) { \
+        VEC->data.F32[i] = ((2.0 / ((psF32) (SIZE - 1))) * ((psF32) i)) - 1.0; \
+    }\
+}\
+
+// free a local temporary F64 vector (TEMP) which is a copy of a non-F64 vector (ORIG)
+# define PS_FREE_TEMP_F64_VECTOR(ORIG, TEMP) \
+if ((ORIG != NULL) && (ORIG->type.type != PS_TYPE_F64)) { psFree(TEMP); }
+
+/*****************************************************************************/
+/* TYPE DEFINITIONS                                                          */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* GLOBAL VARIABLES                                                          */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* FILE STATIC VARIABLES                                                     */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* FUNCTION IMPLEMENTATION - LOCAL                                           */
+/*****************************************************************************/
+
+/******************************************************************************
+BuildSums1D(sums, x, polyOrder, sums): this routine calculates the powers of
+input parameter "x" between 0 and input parameter nTerms*2.  The result is
+returned as a psVector sums.
+*****************************************************************************/
+static psVector *BuildSums1D(
+    psVector* sums,
+    psF64 x,
+    psS32 nTerm)
+{
+    psS32 nSum = 0;
+    psF64 xSum = 0.0;
+
+    //
+    // XXX: Why do we multiply by 2 here?  It's better to do it outside and
+    // have the definition of this function remain sensible.
+    //
+    nSum = 2*nTerm;
+    if (sums == NULL) {
+        sums = psVectorAlloc(nSum, PS_TYPE_F64);
+    } else if (nSum > sums->n) {
+        sums = psVectorRealloc(sums, nSum);
+        sums->n = nSum;
+    }
+
+    xSum = 1.0;
+    for (psS32 i = 0; i < nSum; i++) {
+        sums->data.F64[i] = xSum;
+        xSum *= x;
+    }
+    return (sums);
+}
+
+/******************************************************************************
+BuildSums2D(sums, x, y, nXterm, nYterm): this routine calculates the powers of
+input parameter "x" and "y" between 0 and input parameter nXterms*2 and
+nYterm*2.  The result is returned as a psImage sums.
+ *****************************************************************************/
+static psImage *BuildSums2D(
+    psImage *sums,
+    psF64 x,
+    psF64 y,
+    psS32 nXterm,
+    psS32 nYterm)
+{
+    psS32 nXsum = 0;
+    psS32 nYsum = 0;
+    psF64 xSum = 1.0;
+    psF64 ySum = 1.0;
+
+    // note that we are using the X and Y elements of the image reversed to be
+    // consistent with the other BuildSumsND functions in terms of the definition
+    // of the sums array
+    nXsum = 2*nXterm;
+    nYsum = 2*nYterm;
+    if (sums == NULL) {
+        sums = psImageAlloc(nYsum, nXsum, PS_TYPE_F64);
+    }
+    if ((nYsum != sums->numCols) || (nXsum != sums->numRows)) {
+        psFree (sums);
+        sums = psImageAlloc(nYsum, nXsum, PS_TYPE_F64);
+    }
+
+    xSum = 1.0;
+    for (psS32 i = 0; i < nXsum; i++) {
+        ySum = xSum;
+        for (psS32 j = 0; j < nYsum; j++) {
+            sums->data.F64[i][j] = ySum;
+            ySum *= y;
+        }
+        xSum *= x;
+    }
+
+    return (sums);
+}
+
+/******************************************************************************
+BuildSums3D(sums, x, y, z, nXterm, nYterm, nZterm): this routine calculates
+the powers of input parameter "x", "y", and "z" between 0 and input parameter
+nXterms*2, nYterm*2, and nZterm*2.  The result is returned as a 3-D array sums.
+ *****************************************************************************/
+static psF64 ***BuildSums3D(
+    psF64 ***sums,
+    psF64 x,
+    psF64 y,
+    psF64 z,
+    psS32 nXterm,
+    psS32 nYterm,
+    psS32 nZterm)
+{
+    psS32 nXsum = 0;
+    psS32 nYsum = 0;
+    psS32 nZsum = 0;
+    psF64 xSum = 1.0;
+    psF64 ySum = 1.0;
+    psF64 zSum = 1.0;
+
+    nXsum = 2*nXterm;
+    nYsum = 2*nYterm;
+    nZsum = 2*nZterm;
+    if (sums == NULL) {
+        sums = (psF64 ***) psAlloc (nXsum*sizeof(psF64));
+        for (psS32 i = 0; i < nXsum; i++) {
+            sums[i] = (psF64 **) psAlloc (nYsum*sizeof(psF64));
+            for (psS32 j = 0; j < nYsum; j++) {
+                sums[i][j] = (psF64 *) psAlloc (nZsum*sizeof(psF64));
+            }
+        }
+    }
+    // careful with this function: there is no size checking and realloc for reuse
+
+    if (1) {
+        zSum = 1.0;
+        for (psS32 k = 0; k < nZsum; k++) {
+            ySum = zSum;
+            for (psS32 j = 0; j < nYsum; j++) {
+                xSum = ySum;
+                for (psS32 i = 0; i < nXsum; i++) {
+                    sums[i][j][k] = xSum;
+                    xSum *= x;
+                }
+                ySum *= y;
+            }
+            zSum *= z;
+        }
+    } else {
+        xSum = 1.0;
+        for (psS32 i = 0; i < nXsum; i++) {
+            ySum = xSum;
+            for (psS32 j = 0; j < nYsum; j++) {
+                zSum = ySum;
+                for (psS32 k = 0; k < nZsum; k++) {
+                    sums[i][j][k] = zSum;
+                    zSum *= z;
+                }
+                ySum *= y;
+            }
+            xSum *= x;
+        }
+    }
+
+    return (sums);
+}
+
+/******************************************************************************
+    BuildSums4D(sums, x, y, z, t, nXterm, nYterm, nZterm, nTterm). equiv to
+    BuildSums2D(). The result is returned as a psF64 ****
+*****************************************************************************/
+static psF64 ****BuildSums4D(
+    psF64 ****sums,
+    psF64 x,
+    psF64 y,
+    psF64 z,
+    psF64 t,
+    psS32 nXterm,
+    psS32 nYterm,
+    psS32 nZterm,
+    psS32 nTterm)
+{
+    psS32 nXsum = 0;
+    psS32 nYsum = 0;
+    psS32 nZsum = 0;
+    psS32 nTsum = 0;
+    psF64 xSum = 1.0;
+    psF64 ySum = 1.0;
+    psF64 zSum = 1.0;
+    psF64 tSum = 1.0;
+
+    nXsum = 2*nXterm;
+    nYsum = 2*nYterm;
+    nZsum = 2*nZterm;
+    nTsum = 2*nTterm;
+    if (sums == NULL) {
+        sums = (psF64 ****) psAlloc (nXsum*sizeof(psF64));
+        for (psS32 i = 0; i < nXsum; i++) {
+            sums[i] = (psF64 ***) psAlloc (nYsum*sizeof(psF64));
+            for (psS32 j = 0; j < nYsum; j++) {
+                sums[i][j] = (psF64 **) psAlloc (nZsum*sizeof(psF64));
+                for (psS32 k = 0; k < nZsum; k++) {
+                    sums[i][j][k] = (psF64 *) psAlloc (nTsum*sizeof(psF64));
+                }
+            }
+        }
+    }
+    // careful with this function: there is no size checking and realloc for reuse
+
+    tSum = 1.0;
+    for (psS32 m = 0; m < nTsum; m++) {
+        zSum = tSum;
+        for (psS32 k = 0; k < nZsum; k++) {
+            ySum = zSum;
+            for (psS32 j = 0; j < nYsum; j++) {
+                xSum = ySum;
+                for (psS32 i = 0; i < nXsum; i++) {
+                    sums[i][j][k][m] = xSum;
+                    xSum *= x;
+                }
+                ySum *= y;
+            }
+            zSum *= z;
+        }
+        tSum *= t;
+    }
+    return (sums);
+}
+
+/******************************************************************************
+ ******************************************************************************
+ Analytical 1-D fitting routines.
+ ******************************************************************************
+ *****************************************************************************/
+
+/******************************************************************************
+ ******************************************************************************
+ 1-D Vector Poly Fitting Code.
+ ******************************************************************************
+ *****************************************************************************/
+
+/******************************************************************************
+vectorFitPolynomial1DCheb():  This routine will fit a Chebyshev
+polynomial of degree myPoly->nX to the data points (x, y) and return the
+coefficients of that polynomial.
+*****************************************************************************/
+static bool vectorFitPolynomial1DCheb(
+    psPolynomial1D* myPoly,
+    const psVector *mask,
+    psMaskType maskValue,
+    const psVector* y,
+    const psVector* yErr,
+    const psVector* x)
+{
+    PS_ASSERT_POLY_NON_NULL(myPoly, NULL);
+    PS_ASSERT_INT_LARGER_THAN_OR_EQUAL(myPoly->nX, 0, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
+    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL);
+    if (yErr != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(y, yErr, NULL);
+        PS_ASSERT_VECTOR_TYPE(yErr, PS_TYPE_F64, NULL);
+    }
+    if (x != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(y, x, NULL);
+        PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL);
+    }
+    if (mask != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(y, mask, NULL);
+        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
+    }
+
+    int numTerms = myPoly->nX + 1;      // Number of polynomial terms
+    int numData = x->n;                 // Number of data elements
+
+    psImage *A = psImageAlloc(numTerms, numTerms, PS_TYPE_F64); // Least-squares matrix
+    psVector *B = psVectorAlloc(numTerms, PS_TYPE_F64); // Least-squares vector
+    psImageInit(A, 0.0);
+    psVectorInit(B, 0.0);
+
+    psPolynomial1D **chebPolys = p_psCreateChebyshevPolys(numTerms); // The chebyshev polynomials
+    psImage *sums = psImageAlloc(numData, numTerms, PS_TYPE_F64);
+    for (int i = 0; i < numTerms; i++) {
+        if (myPoly->coeffMask[i] & PS_POLY_MASK_BOTH) {
+            continue;
+        }
+        psPolynomial1D *cheb = chebPolys[i];
+        psVector *sum = psPolynomial1DEvalVector(cheb, x);
+        memcpy(sums->data.F64[i], sum->data.F64, numData*sizeof(psF64));
+        psFree(sum);
+        psFree(cheb);
+    }
+    psFree(chebPolys);
+
+    // Dereference pointers, for speed in the loop
+    psF64 **matrix = A->data.F64;       // Least-squares matrix
+    psF64 *vector = B->data.F64;        // Least-squares vector
+    psU8 *dataMask = NULL;              // Mask for data
+    if (mask) {
+        dataMask = mask->data.U8;
+    }
+    psU8 *coeffMask = myPoly->coeffMask;      // Mask for polynomial terms
+    psF64 *yData = y->data.F64;         // Coordinate data
+    psF64 *yErrData = NULL;             // Errors in the coordinate
+    if (yErr) {
+        yErrData = yErr->data.F64;
+    }
+    psF64 **sumsData = sums->data.F64;  // Sums
+
+    for (int k = 0; k < numData; k++) {
+        if (dataMask && dataMask[k]) {
+            continue;
+        }
+
+        double wt;
+        if (!yErr) {
+            wt = 1.0;
+        } else {
+            // this filters fErr == 0 values
+            wt = (yErrData[k] == 0) ? 0.0 : 1.0 / PS_SQR(yErrData[k]);
+        }
+
+        for (int i = 0; i < numTerms; i++) {
+            if (coeffMask[i] & PS_POLY_MASK_BOTH) {
+                matrix[i][i] = 1.0;
+                continue;
+            }
+            vector[i] += yData[k] * sumsData[i][k] * wt;
+            matrix[i][i] += sumsData[i][k] * sumsData[i][k] * wt; // The diagonal entry
+            for (int j = i + 1; j < numTerms; j++) { // The upper diagonal only: we will use symmetry
+                if (coeffMask[j] & PS_POLY_MASK_BOTH) {
+                    continue;
+                }
+                double value = sumsData[i][k] * sumsData[j][k] * wt; // The value to add to the matrix
+                matrix[i][j] += value;
+                matrix[j][i] += value;  // Taking advantage of the symmetry
+            }
+        }
+    }
+    psFree(sums);
+
+    if (psTraceGetLevel("psLib.math") >= 6) {
+        PS_IMAGE_PRINT_F64(A);
+        PS_VECTOR_PRINT_F64(B);
+    }
+
+    if (USE_GAUSS_JORDAN) {
+        // GaussJordan version
+        if (!psMatrixGJSolve(A, B)) {
+            psError(PS_ERR_UNKNOWN, false, "Could not solve linear equations.  Returning NULL.\n");
+            goto escape_GJ;
+        } else {
+            // the first nTerm entries in B correspond directly to the desired
+            // polynomial coefficients.  this is only true for the 1D case
+            for (psS32 k = 0; k < numTerms; k++) {
+                myPoly->coeff[k] = B->data.F64[k];
+                myPoly->coeffErr[k] = sqrt(A->data.F64[k][k]);
+            }
+            // The constant needs to be multiplied by 2, because it's half the a_0.
+            myPoly->coeff[0] *= 2.0;
+            myPoly->coeffErr[0] *= 2.0;
+        }
+    } else {
+        // LUD version of the fit
+        psImage *ALUD = NULL;
+        psVector* outPerm = NULL;
+        psVector* coeffs = NULL;
+
+        ALUD = psImageAlloc(numTerms, numTerms, PS_TYPE_F64);
+        ALUD = psMatrixLUD(ALUD, &outPerm, A);
+        if (ALUD == NULL) {
+            psError(PS_ERR_UNKNOWN, false, "Could not do LUD decomposition on matrix.  Returning NULL.\n");
+            goto escape_LUD;
+        } else {
+            coeffs = psMatrixLUSolve(coeffs, ALUD, B, outPerm);
+            if (coeffs == NULL) {
+                psError(PS_ERR_UNKNOWN, false, "Could not solve LUD matrix.  Returning NULL.\n");
+                goto escape_LUD;
+            } else {
+                for (psS32 k = 0; k < numTerms; k++) {
+                    myPoly->coeff[k] = coeffs->data.F64[k];
+                }
+            }
+        }
+        psFree(ALUD);
+        psFree(coeffs);
+        psFree(outPerm);
+    }
+    psFree(A);
+    psFree(B);
+    return true;
+
+escape_LUD:
+    // XXX drop the LUD version!
+    psFree(A);
+    psFree(B);
+    return false;
+
+escape_GJ:
+    psFree(A);
+    psFree(B);
+    return false;
+}
+
+/******************************************************************************
+VectorFitPolynomial1DOrd(myPoly, *mask, maskValue, *y, *yErr, *x): This is a
+private routine which will fit a 1-D polynomial to a set of (x, f) pairs.  The
+x and fErr vectors may be NULL.  All non-NULL vectors must be of type
+PS_TYPE_F64.
+ 
+XXX EAM : since this is a private function, can we drop the ASSERTS?
+XXX EAM : can we drop the LUD version? it does not calculate coeffErr values!!
+*****************************************************************************/
+static bool VectorFitPolynomial1DOrd(
+    psPolynomial1D* myPoly,
+    const psVector *mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x)
+{
+    psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_POLY_NON_NULL(myPoly, false);
+    PS_ASSERT_VECTOR_NON_NULL(f, false);
+    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, false);
+    if (mask) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false);
+        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
+    }
+    if (x) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
+        PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, false);
+    }
+    if (fErr) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false);
+        PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, false);
+    }
+
+    if (psTraceGetLevel("psLib.math") >= 6) {
+        psTrace("psLib.math", 6, "VectorFitPolynomial1D()\n");
+        for (psS32 i = 0; i < f->n; i++) {
+            psTrace("psLib.math", 6, "(x, f, fErr) is (");
+            if (x != NULL) {
+                psTrace("psLib.math", 6, "%f, %f, ", x->data.F64[i], f->data.F64[i]);
+            } else {
+                psTrace("psLib.math", 6, "%f, %f, ", (psF64) i, f->data.F64[i]);
+            }
+            if (fErr != NULL) {
+                psTrace("psLib.math", 6, "%f)\n", fErr->data.F64[i]);
+            } else {
+                psTrace("psLib.math", 6, "NULL)\n");
+            }
+        }
+    }
+
+    int nTerm = myPoly->nX + 1;         // Number of terms in the equation
+    int nData = f->n;                   // Number of data points
+    psImage *A = psImageAlloc(nTerm, nTerm, PS_TYPE_F64); // Least-squares matrix
+    psVector *B = psVectorAlloc(nTerm, PS_TYPE_F64); // Least-squares vector
+
+    // Initialize data structures.
+    if (!psImageInit(A, 0.0) || !psVectorInit(B, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "Could initialize data structures A, B.  Returning NULL.\n");
+        psFree(A);
+        psFree(B);
+        psTrace("psLib.math", 4, "---- %s() End ----\n", __func__);
+        return false;
+    }
+
+    // Build the least squares matrix and vector
+
+    // Dereference some pointers for speed in the loop
+    psU8 *dataMask = NULL;              // Dereferenced version of mask for data points
+    if (mask) {
+        dataMask = mask->data.U8;
+    }
+    psU8 *coeffMask = myPoly->coeffMask;      // Dereferenced version of mask for polynomial terms
+    psF64 *ordinates = NULL;            // Dereferenced version of ordinate data
+    if (x) {
+        ordinates = x->data.F64;
+    }
+    psF64 *coordinates = f->data.F64;   // Dereferenced version of coordinate data
+    psF64 *coordErr = NULL;             // Dereferenced version of coordinate errors
+    if (fErr) {
+        coordErr = fErr->data.F64;
+    }
+    psF64 *vector = B->data.F64;        // Dereferenced version of least-squares vector
+    psF64 **matrix = A->data.F64;       // Dereferenced version of least-squares matrix
+
+    psVector* xSums = NULL;             // Contains 1, x, x^2, x^3, etc, for ease of calculation
+    for (int k = 0; k < nData; k++) {
+        if (dataMask && dataMask[k] & maskValue) {
+            continue;
+        }
+        if (ordinates) {
+            xSums = BuildSums1D(xSums, ordinates[k], nTerm);
+        } else {
+            xSums = BuildSums1D(xSums, (psF64)k, nTerm);
+        }
+        psF64 *sums = xSums->data.F64;  // Dereferenced version of sums
+
+        double wt;
+        if (!fErr) {
+            wt = 1.0;
+        } else {
+            // this filters fErr == 0 values
+            wt = (coordErr[k] == 0) ? 0.0 : 1.0 / PS_SQR(coordErr[k]);
+        }
+
+        for (int i = 0; i < nTerm; i++) {
+            if (coeffMask[i] & PS_POLY_MASK_SET) {
+                matrix[i][i] = 1.0;
+                continue;
+            }
+            vector[i] += coordinates[k] * sums[i] * wt;
+            matrix[i][i] += sums[2 * i] * wt; // The diagonal entry
+            for (int j = i + 1; j < nTerm; j++) { // The upper diagonal only: we will use symmetry
+                if (coeffMask[j] & PS_POLY_MASK_SET) {
+                    continue;
+                }
+                double value = sums[i + j] * wt; // The value to add to the matrix
+                matrix[i][j] += value;
+                matrix[j][i] += value;  // Taking advantage of the symmetry
+            }
+        }
+    }
+    psFree(xSums);
+
+    // elements which are masked for fitting need to be subtracted from the vector
+    for (int i = 0; i < nTerm; i++) {
+	if (coeffMask[i] & PS_POLY_MASK_BOTH) {
+	    continue;
+	}
+	for (int j = 0; j < nTerm; j++) { // The upper diagonal only: we will use symmetry
+	    if (coeffMask[j] & PS_POLY_MASK_SET) {
+		continue;
+	    }
+	    if (!(coeffMask[j] & PS_POLY_MASK_FIT)) {
+		continue;
+	    }
+	    vector[i] -= matrix[i][j]*myPoly->coeff[j];
+	}
+    }
+    
+    // set the un-fitted and un-set elements to 0 or 1 for pivots
+    for (int i = 0; i < nTerm; i++) {
+	if (coeffMask[i] & PS_POLY_MASK_BOTH) {
+	    for (int j = 0; j < nTerm; j++) { // The upper diagonal only: we will use symmetry
+		matrix[i][j] = 0.0;
+		matrix[j][i] = 0.0;
+	    }
+	    matrix[i][i] = 1.0;
+	    continue;
+	}
+    }
+
+    if (psTraceGetLevel("psLib.math") >= 4) {
+        printf("Least-squares vector:\n");
+        for (int i = 0; i < nTerm; i++) {
+            printf("%f ", B->data.F64[i]);
+        }
+        printf("\n");
+        printf("Least-squares matrix:\n");
+        for (int i = 0; i < nTerm; i++) {
+            for (int j = 0; j < nTerm; j++) {
+                printf("%f ", A->data.F64[i][j]);
+            }
+            printf("\n");
+        }
+    }
+
+    // XXX: rel10_ifa used psMatrixGJSolve().  However, this failed tests.  So, I'm using psMatrixLUD().
+    if (USE_GAUSS_JORDAN) {
+        // GaussJordan version
+        if (!psMatrixGJSolve(A, B)) {
+            psError(PS_ERR_UNKNOWN, false, "Could not solve linear equations.  Returning NULL.\n");
+            goto escape_GJ;
+        } else {
+            // the first nTerm entries in B correspond directly to the desired
+            // polynomial coefficients.  this is only true for the 1D case
+            for (psS32 k = 0; k < nTerm; k++) {
+		if (coeffMask[k] & PS_POLY_MASK_FIT) continue;
+		myPoly->coeff[k] = B->data.F64[k];
+		myPoly->coeffErr[k] = sqrt(A->data.F64[k][k]);
+            }
+        }
+    } else {
+        // LUD version of the fit
+        psImage *ALUD = NULL;
+        psVector* outPerm = NULL;
+        psVector* coeffs = NULL;
+
+        ALUD = psImageAlloc(nTerm, nTerm, PS_TYPE_F64);
+        ALUD = psMatrixLUD(ALUD, &outPerm, A);
+        if (ALUD == NULL) {
+            psError(PS_ERR_UNKNOWN, false, "Could not do LUD decomposition on matrix.  Returning NULL.\n");
+            goto escape_LUD;
+        } else {
+            coeffs = psMatrixLUSolve(coeffs, ALUD, B, outPerm);
+            if (coeffs == NULL) {
+                psError(PS_ERR_UNKNOWN, false, "Could not solve LUD matrix.  Returning NULL.\n");
+                goto escape_LUD;
+            } else {
+                for (psS32 k = 0; k < nTerm; k++) {
+		    if (coeffMask[k] & PS_POLY_MASK_FIT) continue;
+                    myPoly->coeff[k] = coeffs->data.F64[k];
+                    // XXX LUD does not give inverse of A
+                }
+            }
+        }
+        psFree(ALUD);
+        psFree(coeffs);
+        psFree(outPerm);
+    }
+    psFree(A);
+    psFree(B);
+
+    psTrace("psLib.math", 4, "---- %s() End ----\n", __func__);
+    return true;
+
+escape_LUD:
+    psFree(A);
+    psFree(B);
+    return false;
+
+escape_GJ:
+    psFree(A);
+    psFree(B);
+    return false;
+}
+
+
+/******************************************************************************
+psVectorFitPolynomial1D():  This routine fits a polynomial of arbitrary degree
+(specified in poly) to the data points (x, y) and return that polynomial.
+Types F32 and F64 are supported, however, type F32 is done via vector
+conversion only.
+ *****************************************************************************/
+bool psVectorFitPolynomial1D(
+    psPolynomial1D *poly,
+    const psVector *mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x)
+{
+    PS_ASSERT_POLY_NON_NULL(poly, false);
+    PS_ASSERT_INT_NONNEGATIVE(poly->nX, false);
+
+    PS_ASSERT_VECTOR_NON_NULL(f, false);
+    PS_ASSERT_VECTOR_NON_EMPTY(f, false);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false);
+    if (mask != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false);
+        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
+    }
+    if (fErr != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false);
+        PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, false);
+    }
+    if (x != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
+        PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, false);
+    }
+
+    // Convert input vectors to F64 if necessary.
+    psVector *f64 = (f->type.type == PS_TYPE_F64) ? (psVector *) f : psVectorCopy (NULL, f, PS_TYPE_F64);
+    psVector *x64 = NULL;
+    if (x != NULL) {
+        x64 = (x->type.type == PS_TYPE_F64) ? (psVector *) x : psVectorCopy (NULL, x, PS_TYPE_F64);
+    }
+    psVector *fErr64 = NULL;
+    if (fErr != NULL) {
+        fErr64 = (fErr->type.type == PS_TYPE_F64) ? (psVector *) fErr : psVectorCopy (NULL, fErr, PS_TYPE_F64);
+    }
+
+    bool result = true;
+
+    switch (poly->type) {
+    case PS_POLYNOMIAL_ORD:
+        result = VectorFitPolynomial1DOrd(poly, mask, maskValue, f64, fErr64, x64);
+        if (!result) {
+            psError(PS_ERR_UNKNOWN, false, "Could not fit polynomial.  Returning NULL.\n");
+        }
+        break;
+    case PS_POLYNOMIAL_CHEB:
+        if (mask != NULL) {
+            psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n");
+        }
+        if (fErr != NULL) {
+            psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring error vector with Chebyshev polynomials.\n");
+        }
+        if (x == NULL) {
+            // If x==NULL, create an x64 vector with x values set to (-1:1).
+            PS_VECTOR_GEN_CHEBY_INDEX(x64, f64->n, PS_TYPE_F64);
+        }
+
+        result = vectorFitPolynomial1DCheb(poly, mask, maskValue, f64, fErr64, x64);
+        if (!result) {
+            psError(PS_ERR_UNKNOWN, false, "Could not fit polynomial.  Returning NULL.\n");
+        }
+
+        if (x == NULL) {
+            psFree(x64);
+        }
+        break;
+    default:
+        psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type (%d).  Returning NULL.\n", poly->type);
+        result = false;
+        break;
+    }
+
+    // Free psVectors that were created for NULL arguments.
+    PS_FREE_TEMP_F64_VECTOR (f, f64);
+    PS_FREE_TEMP_F64_VECTOR (x, x64);
+    PS_FREE_TEMP_F64_VECTOR (fErr, fErr64);
+
+    return result;
+}
+
+// This function accepts F32 and F64 input vectors.
+bool psVectorClipFitPolynomial1D(
+    psPolynomial1D *poly,
+    psStats *stats,
+    const psVector *mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *xIn)
+{
+    psTrace("psLib.math", 3, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_POLY_NON_NULL(poly, false);
+    PS_ASSERT_PTR_NON_NULL(stats, false);
+    PS_ASSERT_VECTOR_NON_NULL(f, false);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false);
+    PS_ASSERT_VECTOR_NON_NULL(mask, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(mask, f, false);
+    PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
+
+    if (fErr != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(fErr, f, false);
+        PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, false);
+    }
+
+    // Internal pointers for possibly NULL vectors.
+    psVector *x = NULL;
+    if (xIn != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(xIn, f, false);
+        PS_ASSERT_VECTOR_TYPE(xIn, f->type.type, false);
+        x = (psVector *) xIn;
+    } else {
+        if (poly->type == PS_POLYNOMIAL_ORD) {
+            x = psVectorCreate(NULL, 0, f->n, 1, f->type.type);
+        } else if (poly->type == PS_POLYNOMIAL_CHEB) {
+            if (f->type.type == PS_TYPE_F32) {
+                PS_VECTOR_GEN_CHEBY_INDEX(x, f->n, PS_TYPE_F32);
+            } else if (f->type.type == PS_TYPE_F64) {
+                PS_VECTOR_GEN_CHEBY_INDEX(x, f->n, PS_TYPE_F64);
+            }
+        } else {
+            psError(PS_ERR_UNKNOWN, true, "Error, bad poly type.\n");
+            return false;
+        }
+    }
+
+    // the user supplies one of various stats option pairs,
+    // determine the desired mean and stdev STATS options:
+    // XXX enforce consistency?
+    // XXX psStatsGetValue() probably has inverted precedence
+    psStatsOptions meanOption = stats->options & (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN | PS_STAT_ROBUST_MEDIAN | PS_STAT_CLIPPED_MEAN | PS_STAT_FITTED_MEAN | PS_STAT_FITTED_MEAN_V2);
+    psStatsOptions stdevOption = stats->options & (PS_STAT_SAMPLE_STDEV | PS_STAT_ROBUST_STDEV | PS_STAT_CLIPPED_STDEV | PS_STAT_FITTED_STDEV | PS_STAT_FITTED_STDEV_V2);
+    if (!meanOption) {
+        psError(PS_ERR_UNKNOWN, true, "no valid mean stats option selected");
+        return false;
+    }
+    if (!stdevOption) {
+        psError(PS_ERR_UNKNOWN, true, "no valid stdev stats option selected");
+        return false;
+    }
+
+    // clipping range defined by min and max and/or clipSigma
+    psF32 minClipSigma;
+    psF32 maxClipSigma;
+    if (isfinite(stats->max)) {
+        maxClipSigma = fabs(stats->max);
+    } else {
+        maxClipSigma = fabs(stats->clipSigma);
+    }
+    if (isfinite(stats->min)) {
+        minClipSigma = fabs(stats->min);
+    } else {
+        minClipSigma = fabs(stats->clipSigma);
+    }
+    psVector *resid = psVectorAlloc(f->n, PS_TYPE_F64);
+
+    psTrace("psLib.math", 4, "stats->clipIter is %d\n", stats->clipIter);
+    psTrace("psLib.math", 4, "(minClipSigma, maxClipSigma) is (%.2f, %.2f)\n", minClipSigma, maxClipSigma);
+
+    //
+    for (psS32 N = 0; N < stats->clipIter; N++) {
+        psTrace("psLib.math", 6, "Loop iteration %d.  Calling psVectorFitPolynomial1D()\n", N);
+        psS32 Nkeep = 0;
+        if (psTraceGetLevel("psLib.math") >= 6) {
+            if (mask != NULL) {
+                for (psS32 i = 0 ; i < mask->n ; i++) {
+                    psTrace("psLib.math", 6,  "mask[%d] is %d\n", i, mask->data.U8[i]);
+                }
+            }
+        }
+        if (!psVectorFitPolynomial1D(poly, mask, maskValue, f, fErr, x)) {
+            psError(PS_ERR_UNKNOWN, false, "Could not fit polynomial.  Returning false.\n");
+            if (xIn == NULL) {
+                psFree(x);
+            }
+	    psFree(resid);
+	    
+            return false;
+        }
+
+        psVector *fit = psPolynomial1DEvalVector(poly, x);
+        if (fit == NULL) {
+            psError(PS_ERR_UNKNOWN, false, "Could not call psPolynomial3DEvalVector().  Returning false.\n");
+            if (xIn == NULL) {
+                psFree(x);
+            }
+            psFree(resid);
+            return false;
+        }
+        for (psS32 i = 0 ; i < f->n ; i++) {
+            if (f->type.type == PS_TYPE_F64) {
+                resid->data.F64[i] = f->data.F64[i] - fit->data.F64[i];
+            } else {
+                resid->data.F64[i] = (psF64) (f->data.F32[i] - fit->data.F32[i]);
+            }
+        }
+        if (psTraceGetLevel("psLib.math") >= 6) {
+            if (mask != NULL) {
+                for (psS32 i = 0 ; i < mask->n ; i++) {
+                    if (!((mask != NULL) && (mask->data.U8[i] & maskValue))) {
+                        psTrace("psLib.math", 6,  "(f, fit)[%d] is (%f, %f).  resid is (%f)\n",
+                                i, f->data.F32[i], fit->data.F32[i], resid->data.F64[i]);
+                    }
+                }
+            }
+        }
+
+        if (!psVectorStats(stats, resid, NULL, mask, maskValue)) {
+            psError(PS_ERR_UNKNOWN, false, "Could not compute statistics on the resid vector.  Returning false.\n");
+            psFree(resid);
+            psFree(fit);
+            return false;
+        }
+
+        double meanValue = psStatsGetValue (stats, meanOption);
+        double stdevValue = psStatsGetValue (stats, stdevOption);
+
+        psTrace("psLib.math", 5, "Mean is %f\n", meanValue);
+        psTrace("psLib.math", 5, "Stdev is %f\n", stdevValue);
+        psF32 minClipValue = -minClipSigma*stdevValue;
+        psF32 maxClipValue = +maxClipSigma*stdevValue;
+
+        // set mask if pts are not valid
+        // we are masking out any point which is out of range
+        // recovery is not allowed with this scheme
+        for (psS32 i = 0; i < resid->n; i++) {
+            if ((mask != NULL) && (mask->data.U8[i] & maskValue)) {
+                continue;
+            }
+
+            if ((resid->data.F64[i] - meanValue > maxClipValue) || (resid->data.F64[i] - meanValue < minClipValue)) {
+                if (f->type.type == PS_TYPE_F64) {
+                    psTrace("psLib.math", 6, "Masking element %d (%f).  resid->data.F64[%d] is %f\n",
+                            i, fit->data.F64[i], i, resid->data.F64[i]);
+                } else {
+                    psTrace("psLib.math", 6, "Masking element %d (%f).  resid->data.F64[%d] is %f\n",
+                            i, fit->data.F32[i], i, resid->data.F64[i]);
+                }
+
+                if (mask != NULL) {
+                    mask->data.U8[i] |= 0x01;
+                }
+                continue;
+            }
+            Nkeep++;
+        }
+
+        //
+        // We should probably exit this loop if no new elements were masked
+        // since the polynomial fit won't change.
+        //
+        psTrace("psLib.math", 6, "keeping %d of %ld pts for fit\n", Nkeep, x->n);
+        stats->clippedNvalues = Nkeep;
+        psFree(fit);
+    }
+
+    // Free psVectors that were created for NULL arguments.
+    if (xIn == NULL) {
+        psFree(x);
+    }
+    // Free other local temporary variables
+    psFree(resid);
+
+    psTrace("psLib.math", 3, "---- %s() end ----\n", __func__);
+    return true;
+}
+
+
+/******************************************************************************
+ ******************************************************************************
+ 2-D Vector Code.
+ ******************************************************************************
+ *****************************************************************************/
+
+/******************************************************************************
+VectorFitPolynomial2DOrd(myPoly, *mask, maskValue, *f, *fErr, *x, *y): This is
+a private routine which will fit a 2-D polynomial to a set of (x, y)-(f)
+pairs.  All non-NULL vectors must be of type PS_TYPE_F64.
+ 
+ *****************************************************************************/
+static bool VectorFitPolynomial2DOrd(
+    psPolynomial2D* myPoly,
+    const psVector* mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x,
+    const psVector *y)
+{
+    psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_POLY_NON_NULL(myPoly, false);
+    PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, false);
+    PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, false);
+    PS_ASSERT_VECTOR_NON_NULL(f, false);
+    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, false);
+    if (fErr != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, false);
+        PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, false);
+    }
+    PS_ASSERT_VECTOR_NON_NULL(x, false);
+    PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
+    PS_ASSERT_VECTOR_NON_NULL(y, false);
+    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false);
+    if (mask != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(y, mask, false);
+        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
+    }
+
+    // Number of polynomial terms
+    int nXterm = 1 + myPoly->nX;      // Number of terms in x
+    int nYterm = 1 + myPoly->nY;      // Number of terms in y
+    int nTerm = nXterm * nYterm;            // Total number of terms
+
+    psImage *A = psImageAlloc(nTerm, nTerm, PS_TYPE_F64); // Least-squares matrix
+    psVector *B = psVectorAlloc(nTerm, PS_TYPE_F64); // Least-squares vector
+
+    // Initialize data structures.
+    if (!psImageInit(A, 0.0) || !psVectorInit(B, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "Could initialize data structures A, B.  Returning NULL.\n");
+        psFree(A);
+        psFree(B);
+        psTrace("psLib.math", 6, "---- %s() End ----\n", __func__);
+        return false;
+    }
+
+    // Dereference stuff, to make the loop go faster
+    psF64 **matrix = A->data.F64;       // Dereference the least-squares matrix
+    psF64 *vector = B->data.F64;        // Dereference the least-squares vector
+    psU8 **coeffMask = myPoly->coeffMask;     // Dereference mask for polynomial terms
+    psU8 *dataMask = NULL;              // Dereference mask for data
+    if (mask) {
+        dataMask = mask->data.U8;
+    }
+    psF64 *xData = x->data.F64;         // Dereference x
+    psF64 *yData = y->data.F64;         // Dereference y
+    psF64 *fData = f->data.F64;         // Dereference f
+    psF64 *fErrData = NULL;             // Dereference fErr
+    if (fErr) {
+        fErrData = fErr->data.F64;
+    }
+
+    // Build the least-squares matrix and vector
+    psImage *xySums = NULL;               // The sums: 1, x, x^2, ... x^(2n+1), y, xy, x^2y, ... x^(2n+1)
+    for (int k = 0; k < x->n; k++) {
+        if (dataMask && dataMask[k] & maskValue) {
+            continue;
+        }
+        xySums = BuildSums2D(xySums, xData[k], yData[k], nXterm, nYterm);
+        psF64 **sums = xySums->data.F64;// Dereference sums
+
+        double wt;                      // Weight
+        if (!fErrData) {
+            wt = 1.0;
+        } else {
+            // this filters fErr == 0 values
+            wt = (fErrData[k] == 0.0) ? 0.0 : 1.0 / PS_SQR(fErrData[k]);
+        }
+
+        // Iterating over the matrix
+        for (int i = 0; i < nTerm; i++) {
+            int l = i / nYterm;         // x index
+            int m = i % nYterm;         // y index
+            if (coeffMask[l][m] & PS_POLY_MASK_SET) {
+                matrix[i][i] = 1.0;
+                continue;
+            }
+            vector[i] += fData[k] * sums[l][m] * wt;
+            matrix[i][i] += sums[2*l][2*m] * wt; // The diagonal entry
+            for (int j = i + 1; j < nTerm; j++) { // Doing the upper diagonal only: we will use symmetry
+                int p = j / nYterm;     // x index
+                int q = j % nYterm;     // y index
+                if (coeffMask[p][q] & PS_POLY_MASK_SET) {
+                    continue;
+                }
+                double value = sums[l+p][m+q] * wt; // Value to add in
+                matrix[i][j] += value;
+                matrix[j][i] += value;  // Taking advantage of the symmetry
+            }
+        }
+    }
+    psFree(xySums);
+
+    // elements which are masked for fitting need to be subtracted from the vector
+    for (int i = 0; i < nTerm; i++) {
+	int ix = i / nYterm;         // x index
+	int iy = i % nYterm;         // y index
+	if (coeffMask[ix][iy] & PS_POLY_MASK_BOTH) {
+	    continue;
+	}
+	for (int j = 0; j < nTerm; j++) { // The upper diagonal only: we will use symmetry
+	    int jx = j / nYterm;         // x index
+	    int jy = j % nYterm;         // y index
+	    if (coeffMask[jx][jy] & PS_POLY_MASK_SET) {
+		continue;
+	    }
+	    if (!(coeffMask[jx][jy] & PS_POLY_MASK_FIT)) {
+		continue;
+	    }
+	    vector[i] -= matrix[i][j]*myPoly->coeff[jx][jy];
+	}
+    }
+    
+    // set the un-fitted and un-set elements to 0 or 1 for pivots
+    for (int i = 0; i < nTerm; i++) {
+	int ix = i / nYterm;         // x index
+	int iy = i % nYterm;         // y index
+	if (coeffMask[ix][iy] & PS_POLY_MASK_BOTH) {
+	    for (int j = 0; j < nTerm; j++) { // The upper diagonal only: we will use symmetry
+		matrix[i][j] = 0.0;
+		matrix[j][i] = 0.0;
+	    }
+	    matrix[i][i] = 1.0;
+	    continue;
+	}
+    }
+
+    if (psTraceGetLevel("psLib.math") >= 4) {
+        printf("Least-squares vector:\n");
+        for (int i = 0; i < nTerm; i++) {
+            printf("%f ", B->data.F64[i]);
+        }
+        printf("\n");
+        printf("Least-squares matrix:\n");
+        for (int i = 0; i < nTerm; i++) {
+            for (int j = 0; j < nTerm; j++) {
+                printf("%f ", A->data.F64[i][j]);
+            }
+            printf("\n");
+        }
+    }
+
+    if (!psMatrixGJSolve(A, B)) {
+        psError(PS_ERR_UNKNOWN, false, "Could not solve linear equations.  Returning NULL.\n");
+        psFree(A);
+        psFree(B);
+        return false;
+    }
+
+    // select the appropriate solution entries
+    for (int i = 0; i < nTerm; i++) {
+        int l = i / nYterm;         // x index
+        int m = i % nYterm;         // y index
+
+	// retain the incoming values if masked on the fit
+	if (coeffMask[l][m] & PS_POLY_MASK_FIT) continue;
+	myPoly->coeff[l][m] = B->data.F64[i];
+	myPoly->coeffErr[l][m] = sqrt(A->data.F64[i][i]);
+    }
+    psFree(A);
+    psFree(B);
+
+    psTrace("psLib.math", 6, "---- %s() end ----\n", __func__);
+    return true;
+}
+
+/******************************************************************************
+psVectorFitPolynomial2D():  This routine fits a 2D polynomial of arbitrary
+degree (specified in poly) to the data points (x, y)-(f) and returns that
+polynomial.  Types F32 and F64 are supported, however, type F32 is done via
+vector conversion only.
+ *****************************************************************************/
+bool psVectorFitPolynomial2D(
+    psPolynomial2D *poly,
+    const psVector *mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x,
+    const psVector *y)
+{
+    PS_ASSERT_POLY_NON_NULL(poly, false);
+    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false);
+
+    PS_ASSERT_VECTOR_NON_NULL(f, false);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false);
+    PS_ASSERT_VECTOR_NON_NULL(x, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
+    PS_ASSERT_VECTOR_NON_NULL(y, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false);
+    if (mask != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false);
+        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
+    }
+    if (fErr != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false);
+        PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, false);
+    }
+
+    // Convert input vectors to F64 if necessary.
+    psVector *f64 = (f->type.type == PS_TYPE_F64) ? (psVector *) f : psVectorCopy(NULL, f, PS_TYPE_F64);
+    psVector *x64 = (x->type.type == PS_TYPE_F64) ? (psVector *) x : psVectorCopy(NULL, x, PS_TYPE_F64);
+    psVector *y64 = (y->type.type == PS_TYPE_F64) ? (psVector *) y : psVectorCopy(NULL, y, PS_TYPE_F64);
+
+    psVector *fErr64 = NULL;
+    if (fErr != NULL) {
+        fErr64 = (fErr->type.type == PS_TYPE_F64) ? (psVector *) fErr : psVectorCopy(NULL, fErr, PS_TYPE_F64);
+    }
+
+    bool result = true;
+
+    switch (poly->type) {
+    case PS_POLYNOMIAL_ORD:
+        result = VectorFitPolynomial2DOrd(poly, mask, maskValue, f64, fErr64, x64, y64);
+        if (!result) {
+            psError(PS_ERR_UNKNOWN, true, "Could not fit polynomial.  Returning NULL.\n");
+        }
+        break;
+    case PS_POLYNOMIAL_CHEB:
+        if (mask != NULL) {
+            psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n");
+        }
+        psError(PS_ERR_UNKNOWN, true, "2-D Chebyshev polynomial vector fitting has not been implemented.  Returning NULL.\n");
+        result = false;
+        break;
+    default:
+        psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type.  Returning NULL.\n");
+        result = false;
+        break;
+    }
+
+    // Free psVectors that were created for NULL arguments.
+    PS_FREE_TEMP_F64_VECTOR (f, f64);
+    PS_FREE_TEMP_F64_VECTOR (x, x64);
+    PS_FREE_TEMP_F64_VECTOR (y, y64);
+    PS_FREE_TEMP_F64_VECTOR (fErr, fErr64);
+
+    return result;
+}
+
+bool psVectorClipFitPolynomial2D(
+    psPolynomial2D *poly,
+    psStats *stats,
+    const psVector *mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x,
+    const psVector *y)
+{
+    psTrace("psLib.math", 3, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_POLY_NON_NULL(poly, false);
+    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false);
+    PS_ASSERT_PTR_NON_NULL(stats, false);
+    PS_ASSERT_VECTOR_NON_NULL(mask, false);
+    PS_ASSERT_VECTOR_NON_NULL(f, false);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false);
+
+    PS_ASSERT_VECTOR_NON_NULL(x, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
+    PS_ASSERT_VECTOR_TYPE(x, f->type.type, false);
+
+    PS_ASSERT_VECTOR_NON_NULL(y, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false);
+    PS_ASSERT_VECTOR_TYPE(y, f->type.type, false);
+
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false);
+    PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
+
+    if (fErr != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false);
+        PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, false);
+    }
+
+    // the user supplies one of various stats option pairs,
+    // determine the desired mean and stdev STATS options:
+    // XXX enforce consistency?
+    // XXX psStatsGetValue() probably has inverted precedence
+    psStatsOptions meanOption = stats->options & (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN | PS_STAT_ROBUST_MEDIAN | PS_STAT_CLIPPED_MEAN | PS_STAT_FITTED_MEAN | PS_STAT_FITTED_MEAN_V2);
+    psStatsOptions stdevOption = stats->options & (PS_STAT_SAMPLE_STDEV | PS_STAT_ROBUST_STDEV | PS_STAT_CLIPPED_STDEV | PS_STAT_FITTED_STDEV | PS_STAT_FITTED_STDEV_V2);
+    if (!meanOption) {
+        psError(PS_ERR_UNKNOWN, true, "no valid mean stats option selected");
+        return false;
+    }
+    if (!stdevOption) {
+        psError(PS_ERR_UNKNOWN, true, "no valid stdev stats option selected");
+        return false;
+    }
+
+    // clipping range defined by min and max and/or clipSigma
+    psF32 minClipSigma;
+    psF32 maxClipSigma;
+    if (isfinite(stats->max)) {
+        maxClipSigma = fabs(stats->max);
+    } else {
+        maxClipSigma = fabs(stats->clipSigma);
+    }
+    if (isfinite(stats->min)) {
+        minClipSigma = fabs(stats->min);
+    } else {
+        minClipSigma = fabs(stats->clipSigma);
+    }
+    psVector *resid = psVectorAlloc(f->n, PS_TYPE_F64);
+
+    psTrace("psLib.math", 4, "stats->clipIter is %d\n", stats->clipIter);
+    psTrace("psLib.math", 4, "(minClipSigma, maxClipSigma) is (%.2f, %.2f)\n", minClipSigma, maxClipSigma);
+
+    for (psS32 N = 0; N < stats->clipIter; N++) {
+        psTrace("psLib.math", 6, "Loop iteration %d.  Calling psVectorFitPolynomial1D()\n", N);
+        psS32 Nkeep = 0;
+        if (psTraceGetLevel("psLib.math") >= 7) {
+            if (mask != NULL) {
+                for (psS32 i = 0 ; i < mask->n ; i++) {
+                    psTrace("psLib.math", 7,  "mask[%d] is %d\n", i, mask->data.U8[i]);
+                }
+            }
+        }
+
+        if (!psVectorFitPolynomial2D(poly, mask, maskValue, f, fErr, x, y)) {
+            psError(PS_ERR_UNKNOWN, false, "Could not fit a polynomial to the data.  Returning false.\n");
+            psFree(resid);
+            return false;
+        }
+
+        psVector *fit = psPolynomial2DEvalVector(poly, x, y);
+        if (fit == NULL) {
+            psError(PS_ERR_UNKNOWN, false, "Could not call psPolynomial3DEvalVector().  Returning NULL.\n");
+            psFree(resid);
+            return false;
+        }
+
+        for (psS32 i = 0 ; i < f->n ; i++) {
+            if (f->type.type == PS_TYPE_F64) {
+                resid->data.F64[i] = f->data.F64[i] - fit->data.F64[i];
+            } else {
+                resid->data.F64[i] = (psF64) (f->data.F32[i] - fit->data.F32[i]);
+            }
+        }
+
+        if (psTraceGetLevel("psLib.math") >= 7) {
+            if (mask != NULL) {
+                for (psS32 i = 0 ; i < mask->n ; i++) {
+                    if (!((mask != NULL) && (mask->data.U8[i] & maskValue))) {
+                        psTrace("psLib.math", 7,  "(f, fit)[%d] is (%f, %f).  resid is (%f)\n",
+                                i, f->data.F32[i], fit->data.F32[i], resid->data.F64[i]);
+                    }
+                }
+            }
+        }
+
+        if (!psVectorStats(stats, resid, NULL, mask, maskValue)) {
+            psError(PS_ERR_UNKNOWN, false, "Could not compute statistics on the resid vector.  Returning NULL.\n");
+            psFree(resid);
+            psFree(fit);
+            return false;
+        }
+
+        double meanValue = psStatsGetValue (stats, meanOption);
+        double stdevValue = psStatsGetValue (stats, stdevOption);
+
+        psTrace("psLib.math", 5, "Mean is %f\n", meanValue);
+        psTrace("psLib.math", 5, "Stdev is %f\n", stdevValue);
+        psF32 minClipValue = -minClipSigma*stdevValue;
+        psF32 maxClipValue = +maxClipSigma*stdevValue;
+
+        // set mask if pts are not valid
+        // we are masking out any point which is out of range
+        // recovery is not allowed with this scheme
+        for (psS32 i = 0; i < resid->n; i++) {
+            if ((mask != NULL) && (mask->data.U8[i] & maskValue)) {
+                continue;
+            }
+
+            if ((resid->data.F64[i] - meanValue > maxClipValue) || (resid->data.F64[i] - meanValue < minClipValue)) {
+                if (fit->type.type == PS_TYPE_F64) {
+                    psTrace("psLib.math", 6, "Masking element %d (%f).  resid->data.F64[%d] is %f\n",
+                            i, fit->data.F64[i], i, resid->data.F64[i]);
+                } else {
+                    psTrace("psLib.math", 6, "Masking element %d (%f).  resid->data.F64[%d] is %f\n",
+                            i, fit->data.F32[i], i, resid->data.F64[i]);
+                }
+
+                if (mask != NULL) {
+                    mask->data.U8[i] |= 0x01;
+                }
+                continue;
+            }
+            Nkeep++;
+        }
+        psTrace("psLib.math", 4, "keeping %d of %ld pts for fit\n", Nkeep, x->n);
+        stats->clippedNvalues = Nkeep;
+        psFree(fit);
+    }
+    // Free local temporary variables
+    psFree(resid);
+
+    psTrace("psLib.math", 3, "---- %s() end ----\n", __func__);
+    return true;
+}
+
+
+/******************************************************************************
+ ******************************************************************************
+ 3-D Vector Code.
+ ******************************************************************************
+ *****************************************************************************/
+
+/******************************************************************************
+VectorFitPolynomial3DOrd(myPoly, *mask, maskValue, *f, *fErr, *x, *y, *z):
+This is a private routine which will fit a 3-D polynomial to a set of (x,
+y, z)-(f) pairs.  All non-NULL vectors must be of type PS_TYPE_F64.
+ 
+ *****************************************************************************/
+static bool VectorFitPolynomial3DOrd(
+    psPolynomial3D* myPoly,
+    const psVector* mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x,
+    const psVector *y,
+    const psVector *z)
+{
+    psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_POLY_NON_NULL(myPoly, false);
+    PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, false);
+    PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, false);
+    PS_ASSERT_INT_NONNEGATIVE(myPoly->nZ, false);
+
+    PS_ASSERT_VECTOR_NON_NULL(f, false);
+    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, false);
+    if (fErr != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, false);
+        PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, false);
+    }
+    PS_ASSERT_VECTOR_NON_NULL(x, false);
+    PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
+    PS_ASSERT_VECTOR_NON_NULL(y, false);
+    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false);
+    PS_ASSERT_VECTOR_NON_NULL(z, false);
+    PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F64, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, false);
+    if (mask != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false);
+        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
+    }
+
+    int nXterm = 1 + myPoly->nX;        // Number of x terms
+    int nYterm = 1 + myPoly->nY;        // Number of y terms
+    int nZterm = 1 + myPoly->nZ;        // Number of z terms
+    int nTerm = nXterm * nYterm * nZterm; // Total number of terms
+    int nData = x->n;                   // Number of data points
+    psImage    *A = psImageAlloc(nTerm, nTerm, PS_TYPE_F64); // Least-squares matrix
+    psVector   *B = psVectorAlloc(nTerm, PS_TYPE_F64); // Least-squares vector
+
+    // Initialize data structures.
+    if (!psImageInit(A, 0.0) || !psVectorInit(B, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "Could initialize data structures A, B.  Returning NULL.\n");
+        psFree(A);
+        psFree(B);
+        psTrace("psLib.math", 4, "---- %s() End ----\n", __func__);
+        return false;
+    }
+
+    // Dereference points for speed in the loop
+    psF64 **matrix = A->data.F64;       // Least-squares matrix
+    psF64 *vector = B->data.F64;        // Least-squares vector
+    psF64 *xData = x->data.F64;         // x
+    psF64 *yData = y->data.F64;         // y
+    psF64 *zData = z->data.F64;         // z
+    psF64 *fData = f->data.F64;         // f
+    psF64 *fErrData = NULL;             // Error in f
+    if (fErr) {
+        fErrData = fErr->data.F64;
+    }
+    psU8 *dataMask = NULL;              // Mask for data
+    if (mask) {
+        dataMask = mask->data.U8;
+    }
+    psU8 ***coeffMask = myPoly->coeffMask;    // Mask for polynomial terms
+    int nYZterm = nYterm * nZterm;      // Multiplication of the numbers, to calculate the index
+
+    // Build the B and A data structs.
+    psF64 ***Sums = NULL;         // Sums look like: 1, x, x^2, ... x^(2n+1), y, xy, x^2y, ... x^(2n+1)*y, ...
+    for (int k = 0; k < nData; k++) {
+        if (dataMask && dataMask[k] & maskValue) {
+            continue;
+        }
+
+        Sums = BuildSums3D(Sums, xData[k], yData[k], zData[k], nXterm, nYterm, nZterm);
+
+        double wt;
+        if (fErr == NULL) {
+            wt = 1.0;
+        } else {
+            // this filters fErr == 0 values
+            wt = (fErr->data.F64[k] == 0.0) ? 0.0 : 1.0 / PS_SQR(fErrData[k]);
+        }
+
+        for (int i = 0; i < nTerm; i++) {
+            int ix = i / nYZterm; // x index
+            int iy = (i % nYZterm) / nZterm; // y index
+            int iz = (i % nYZterm) % nZterm; // z index
+            if (coeffMask[ix][iy][iz] & PS_POLY_MASK_BOTH) {
+                matrix[i][i] = 1.0;
+                continue;
+            }
+
+            vector[i] += fData[k] * Sums[ix][iy][iz] * wt;
+            matrix[i][i] += Sums[2*ix][2*iy][2*iz] * wt;
+            for (int j = i + 1; j < nTerm; j++) {
+                int jx = j / (nYZterm); // x index
+                int jy = (j % nYZterm) / nZterm; // y index
+                int jz = (j % nYZterm) % nZterm; // z index
+                if (coeffMask[jx][jy][jz] & PS_POLY_MASK_BOTH) {
+                    continue;
+                }
+                double value = Sums[ix+jx][iy+jy][iz+jz] * wt;
+                matrix[i][j] += value;
+                matrix[j][i] += value;
+            }
+        }
+    }
+
+    // Free the sums
+    for (psS32 ix = 0; ix < 2*nXterm; ix++) {
+        for (psS32 iy = 0; iy < 2*nYterm; iy++) {
+            psFree(Sums[ix][iy]);
+        }
+        psFree(Sums[ix]);
+    }
+    psFree(Sums);
+
+
+    // XXX: rel10_ifa used psMatrixGJSolve().  However, this failed tests.  So, I'm using psMatrixLUD().
+    if (USE_GAUSS_JORDAN) {
+        // does the solution in place
+        // The matrices were overflowing, so I switched to LUD.
+        if (!psMatrixGJSolve(A, B)) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to perform GaussJordan elimination.\n");
+            goto escape_GJ;
+        }
+        // select the appropriate solution entries
+        for (int i = 0; i < nTerm; i++) {
+            int ix = i / nYZterm; // x index
+            int iy = (i % nYZterm) / nZterm; // y index
+            int iz = (i % nYZterm) % nZterm; // z index
+	    if (coeffMask[ix][iy][iz] & PS_POLY_MASK_FIT) continue;
+            myPoly->coeff[ix][iy][iz] = B->data.F64[i];
+            myPoly->coeffErr[ix][iy][iz] = sqrt(A->data.F64[i][i]);
+        }
+    } else {
+        // LUD version of the fit
+        psImage *ALUD = NULL;
+        psVector* outPerm = NULL;
+        psVector* coeffs = NULL;
+
+        ALUD = psImageAlloc(nTerm, nTerm, PS_TYPE_F64);
+        ALUD = psMatrixLUD(ALUD, &outPerm, A);
+        if (ALUD == NULL) {
+            psError(PS_ERR_UNKNOWN, false, "Could not do LUD decomposition on matrix.  Returning NULL.\n");
+            goto escape_LUD;
+        } else {
+            coeffs = psMatrixLUSolve(coeffs, ALUD, B, outPerm);
+            if (coeffs == NULL) {
+                psError(PS_ERR_UNKNOWN, false, "Could not solve LUD matrix.  Returning NULL.\n");
+                goto escape_LUD;
+            } else {
+                // select the appropriate solution entries
+                for (psS32 ix = 0; ix < nXterm; ix++) {
+                    for (psS32 iy = 0; iy < nYterm; iy++) {
+                        for (psS32 iz = 0; iz < nZterm; iz++) {
+                            psS32 nx = ix+iy*nXterm+iz*nXterm*nYterm;
+			    if (coeffMask[ix][iy][iz] & PS_POLY_MASK_FIT) continue;
+                            myPoly->coeff[ix][iy][iz] = coeffs->data.F64[nx];
+                            // XXX myPoly->coeffErr[ix][iy][iz] = sqrt(A->data.F64[nx][nx]);
+                            // XXX this is wrong: A is not replaced with inverse(A), as for GaussJordan
+                        }
+                    }
+                }
+            }
+        }
+
+        psFree(ALUD);
+        psFree(coeffs);
+        psFree(outPerm);
+    }
+    psFree(A);
+    psFree(B);
+
+    psTrace("psLib.math", 4, "---- %s() end ----\n", __func__);
+    return true;
+
+escape_LUD:
+    psFree(A);
+    psFree(B);
+    return false;
+
+escape_GJ:
+
+    psFree(A);
+    psFree(B);
+    return false;
+}
+
+/******************************************************************************
+psVectorFitPolynomial3D():  This routine fits a 3D polynomial of arbitrary
+degree (specified in poly) to the data points (x, y, z)-(f) and returns that
+polynomial.  Types F32 and F64 are supported, however, type F32 is done via
+vector conversion only.
+ *****************************************************************************/
+bool psVectorFitPolynomial3D(
+    psPolynomial3D *poly,
+    const psVector *mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x,
+    const psVector *y,
+    const psVector *z)
+{
+    PS_ASSERT_POLY_NON_NULL(poly, false);
+    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false);
+
+    PS_ASSERT_VECTOR_NON_NULL(f, false);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false);
+    PS_ASSERT_VECTOR_NON_NULL(x, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
+    PS_ASSERT_VECTOR_NON_NULL(y, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false);
+    PS_ASSERT_VECTOR_NON_NULL(z, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, false);
+    if (mask != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false);
+        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
+    }
+    if (fErr != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false);
+        PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, false);
+    }
+
+    // Convert input vectors to F64 if necessary.
+    psVector *f64 = (f->type.type == PS_TYPE_F64) ? (psVector *) f : psVectorCopy(NULL, f, PS_TYPE_F64);
+    psVector *x64 = (x->type.type == PS_TYPE_F64) ? (psVector *) x : psVectorCopy(NULL, x, PS_TYPE_F64);
+    psVector *y64 = (y->type.type == PS_TYPE_F64) ? (psVector *) y : psVectorCopy(NULL, y, PS_TYPE_F64);
+    psVector *z64 = (z->type.type == PS_TYPE_F64) ? (psVector *) z : psVectorCopy(NULL, z, PS_TYPE_F64);
+
+    psVector *fErr64 = NULL;
+    if (fErr != NULL) {
+        fErr64 = (fErr->type.type == PS_TYPE_F64) ? (psVector *) fErr : psVectorCopy(NULL, fErr, PS_TYPE_F64);
+    }
+
+    bool result = true;
+
+    switch (poly->type) {
+    case PS_POLYNOMIAL_ORD:
+        result = VectorFitPolynomial3DOrd(poly, mask, maskValue, f64, fErr64, x64, y64, z64);
+        if (!result) {
+            psError(PS_ERR_UNKNOWN, true, "Could not fit polynomial.  Returning NULL.\n");
+        }
+        break;
+    case PS_POLYNOMIAL_CHEB:
+        if (mask != NULL) {
+            psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n");
+        }
+        psError(PS_ERR_UNKNOWN, true, "3-D Chebyshev polynomial vector fitting has not been implemented.  Returning NULL.\n");
+        result = false;
+        break;
+    default:
+        psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type.  Returning NULL.\n");
+        result = false;
+        break;
+    }
+
+    // Free psVectors that were created for NULL arguments.
+    PS_FREE_TEMP_F64_VECTOR (f, f64);
+    PS_FREE_TEMP_F64_VECTOR (x, x64);
+    PS_FREE_TEMP_F64_VECTOR (y, y64);
+    PS_FREE_TEMP_F64_VECTOR (z, z64);
+    PS_FREE_TEMP_F64_VECTOR (fErr, fErr64);
+
+    return result;
+}
+
+bool psVectorClipFitPolynomial3D(
+    psPolynomial3D *poly,
+    psStats *stats,
+    const psVector *mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x,
+    const psVector *y,
+    const psVector *z)
+{
+    psTrace("psLib.math", 3, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_POLY_NON_NULL(poly, false);
+    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false);
+    PS_ASSERT_PTR_NON_NULL(stats, false);
+    PS_ASSERT_VECTOR_NON_NULL(mask, false);
+    PS_ASSERT_VECTOR_NON_NULL(f, false);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false);
+
+    PS_ASSERT_VECTOR_NON_NULL(x, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
+    PS_ASSERT_VECTOR_TYPE(x, f->type.type, false);
+
+    PS_ASSERT_VECTOR_NON_NULL(y, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false);
+    PS_ASSERT_VECTOR_TYPE(y, f->type.type, false);
+
+    PS_ASSERT_VECTOR_NON_NULL(z, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, false);
+    PS_ASSERT_VECTOR_TYPE(z, f->type.type, false);
+
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false);
+    PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
+
+    if (fErr != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false);
+        PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, false);
+    }
+
+    // the user supplies one of various stats option pairs,
+    // determine the desired mean and stdev STATS options:
+    // XXX enforce consistency?
+    // XXX psStatsGetValue() probably has inverted precedence
+    psStatsOptions meanOption = stats->options & (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN | PS_STAT_ROBUST_MEDIAN | PS_STAT_CLIPPED_MEAN | PS_STAT_FITTED_MEAN | PS_STAT_FITTED_MEAN_V2);
+    psStatsOptions stdevOption = stats->options & (PS_STAT_SAMPLE_STDEV | PS_STAT_ROBUST_STDEV | PS_STAT_CLIPPED_STDEV | PS_STAT_FITTED_STDEV | PS_STAT_FITTED_STDEV_V2);
+    if (!meanOption) {
+        psError(PS_ERR_UNKNOWN, true, "no valid mean stats option selected");
+        return false;
+    }
+    if (!stdevOption) {
+        psError(PS_ERR_UNKNOWN, true, "no valid stdev stats option selected");
+        return false;
+    }
+
+    // clipping range defined by min and max and/or clipSigma
+    psF32 minClipSigma;
+    psF32 maxClipSigma;
+    if (isfinite(stats->max)) {
+        maxClipSigma = fabs(stats->max);
+    } else {
+        maxClipSigma = fabs(stats->clipSigma);
+    }
+    if (isfinite(stats->min)) {
+        minClipSigma = fabs(stats->min);
+    } else {
+        minClipSigma = fabs(stats->clipSigma);
+    }
+    psVector *resid = psVectorAlloc(f->n, PS_TYPE_F64);
+
+    psTrace("psLib.math", 4, "stats->clipIter is %d\n", stats->clipIter);
+    psTrace("psLib.math", 4, "(minClipSigma, maxClipSigma) is (%.2f, %.2f)\n", minClipSigma, maxClipSigma);
+
+    for (psS32 N = 0; N < stats->clipIter; N++) {
+        psTrace("psLib.math", 6, "Loop iteration %d.  Calling psVectorFitPolynomial1D()\n", N);
+        psS32 Nkeep = 0;
+        if (psTraceGetLevel("psLib.math") >= 6) {
+            if (mask != NULL) {
+                for (psS32 i = 0 ; i < mask->n ; i++) {
+                    psTrace("psLib.math", 6,  "mask[%d] is %d\n", i, mask->data.U8[i]);
+                }
+            }
+        }
+
+        if (!psVectorFitPolynomial3D(poly, mask, maskValue, f, fErr, x, y, z)) {
+            psError(PS_ERR_UNKNOWN, false, "Could not fit a polynomial to the data.  Returning NULL.\n");
+            psFree(resid);
+            return false;
+        }
+        psVector *fit = psPolynomial3DEvalVector(poly, x, y, z);
+        if (fit == NULL) {
+            psError(PS_ERR_UNKNOWN, false, "Could not call psPolynomial3DEvalVector().  Returning NULL.\n");
+            psFree(resid);
+            return false;
+        }
+        for (psS32 i = 0 ; i < f->n ; i++) {
+            if (f->type.type == PS_TYPE_F64) {
+                resid->data.F64[i] = f->data.F64[i] - fit->data.F64[i];
+            } else {
+                resid->data.F64[i] = ((psF64) f->data.F32[i]) - fit->data.F64[i];
+            }
+        }
+
+        if (psTraceGetLevel("psLib.math") >= 6) {
+            if (mask != NULL) {
+                for (psS32 i = 0 ; i < mask->n ; i++) {
+                    if (!((mask != NULL) && (mask->data.U8[i] & maskValue))) {
+                        psTrace("psLib.math", 6,  "(f, fit)[%d] is (%f, %f).  resid is (%f)\n",
+                                i, f->data.F32[i], fit->data.F32[i], resid->data.F64[i]);
+                    }
+                }
+            }
+        }
+
+        if (!psVectorStats(stats, resid, NULL, mask, maskValue)) {
+            psError(PS_ERR_UNKNOWN, false, "Could not compute statistics on the resid vector.  Returning NULL.\n");
+            psFree(resid);
+            psFree(fit);
+            return false;
+        }
+
+        double meanValue = psStatsGetValue (stats, meanOption);
+        double stdevValue = psStatsGetValue (stats, stdevOption);
+
+        psTrace("psLib.math", 5, "Mean is %f\n", meanValue);
+        psTrace("psLib.math", 5, "Stdev is %f\n", stdevValue);
+        psF32 minClipValue = -minClipSigma*stdevValue;
+        psF32 maxClipValue = +maxClipSigma*stdevValue;
+
+        // set mask if pts are not valid
+        // we are masking out any point which is out of range
+        // recovery is not allowed with this scheme
+        for (psS32 i = 0; i < resid->n; i++) {
+            if ((mask != NULL) && (mask->data.U8[i] & maskValue)) {
+                continue;
+            }
+
+            if ((resid->data.F64[i] - meanValue > maxClipValue) || (resid->data.F64[i] - meanValue < minClipValue))  {
+                if (f->type.type == PS_TYPE_F64) {
+                    psTrace("psLib.math", 6, "Masking element %d (%f).  resid->data.F64[%d] is %f\n",
+                            i, fit->data.F64[i], i, resid->data.F64[i]);
+                } else {
+                    psTrace("psLib.math", 6, "Masking element %d (%f).  resid->data.F64[%d] is %f\n",
+                            i, fit->data.F32[i], i, resid->data.F64[i]);
+                }
+
+                if (mask != NULL) {
+                    mask->data.U8[i] |= 0x01;
+                }
+                continue;
+            }
+            Nkeep++;
+        }
+        psTrace("psLib.math", 6, "keeping %d of %ld pts for fit\n", Nkeep, x->n);
+        stats->clippedNvalues = Nkeep;
+        psFree(fit);
+    }
+    // Free local temporary variables
+    psFree(resid);
+
+    psTrace("psLib.math", 3, "---- %s() end ----\n", __func__);
+    return true;
+}
+
+/******************************************************************************
+ ******************************************************************************
+ 4-D Vector Code.
+ ******************************************************************************
+ *****************************************************************************/
+/******************************************************************************
+VectorFitPolynomial4DOrd(myPoly, *mask, maskValue, *f, *fErr, *x, *y, *z, *t):
+This is a private routine which will fit a 4-D polynomial to a set of (x,
+y, z, t)-(f) pairs.  All non-NULL vectors must be of type PS_TYPE_F64.
+ 
+ *****************************************************************************/
+static bool VectorFitPolynomial4DOrd(
+    psPolynomial4D* myPoly,
+    const psVector* mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x,
+    const psVector *y,
+    const psVector *z,
+    const psVector *t)
+{
+    psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_POLY_NON_NULL(myPoly, false);
+    PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, false);
+    PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, false);
+    PS_ASSERT_INT_NONNEGATIVE(myPoly->nZ, false);
+    PS_ASSERT_INT_NONNEGATIVE(myPoly->nT, false);
+    PS_ASSERT_VECTOR_NON_NULL(f, false);
+    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, false);
+    if (fErr != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, false);
+        PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, false);
+    }
+    PS_ASSERT_VECTOR_NON_NULL(x, false);
+    PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
+    PS_ASSERT_VECTOR_NON_NULL(y, false);
+    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false);
+    PS_ASSERT_VECTOR_NON_NULL(z, false);
+    PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F64, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, false);
+    PS_ASSERT_VECTOR_NON_NULL(t, false);
+    PS_ASSERT_VECTOR_TYPE(t, PS_TYPE_F64, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, false);
+    if (mask) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(y, mask, false);
+        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
+    }
+
+
+    int nXterm = 1 + myPoly->nX;        // Number of x terms
+    int nYterm = 1 + myPoly->nY;        // Number of y terms
+    int nZterm = 1 + myPoly->nZ;        // Number of z terms
+    int nTterm = 1 + myPoly->nT;        // Number of t terms
+    int nTerm = nXterm * nYterm * nZterm * nTterm; // Total number of terms
+    int nData = x->n;                   // Number of data points
+    psImage    *A = psImageAlloc(nTerm, nTerm, PS_TYPE_F64); // Least-squares matrix
+    psVector   *B = psVectorAlloc(nTerm, PS_TYPE_F64); // Least-squares vector
+
+    // Initialize data structures.
+    if (!psImageInit(A, 0.0) || !psVectorInit(B, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "Could initialize data structures A, B.  Returning NULL.\n");
+        psFree(A);
+        psFree(B);
+        psTrace("psLib.math", 4, "---- %s() End ----\n", __func__);
+        return false;
+    }
+
+    // Dereference points for speed in the loop
+    psF64 **matrix = A->data.F64;       // Least-squares matrix
+    psF64 *vector = B->data.F64;        // Least-squares vector
+    psF64 *xData = x->data.F64;         // x
+    psF64 *yData = y->data.F64;         // y
+    psF64 *zData = z->data.F64;         // z
+    psF64 *tData = t->data.F64;         // t
+    psF64 *fData = f->data.F64;         // f
+    psF64 *fErrData = NULL;             // Error in f
+    if (fErr) {
+        fErrData = fErr->data.F64;
+    }
+    psU8 *dataMask = NULL;              // Mask for data
+    if (mask) {
+        dataMask = mask->data.U8;
+    }
+    psU8 ****coeffMask = myPoly->coeffMask;    // Mask for polynomial terms
+    int nYZTterm = nYterm * nZterm * nTterm; // Multiplication of the numbers, for calculating the index
+    int nZTterm = nZterm * nTterm;      // Multiplication of the numbers, for calculating the index
+
+    // Build the B and A data structs.
+    psF64 ****Sums = NULL;        // Sums look like: 1, x, x^2, ... x^(2n+1), y, xy, x^2y, ... x^(2n+1)*y, ...
+    for (int k = 0; k < nData; k++) {
+        if (dataMask && dataMask[k] & maskValue) {
+            continue;
+        }
+
+        Sums = BuildSums4D(Sums, xData[k], yData[k], zData[k], tData[k], nXterm, nYterm, nZterm, nTterm);
+
+        double wt;
+        if (fErr == NULL) {
+            wt = 1.0;
+        } else {
+            // this filters fErr == 0 values
+            wt = (fErr->data.F64[k] == 0.0) ? 0.0 : 1.0 / PS_SQR(fErrData[k]);
+        }
+
+        for (int i = 0; i < nTerm; i++) {
+            int ix = i / (nYZTterm); // x index
+            int iy = (i % (nYZTterm)) / (nZTterm); // y index
+            int iz = ((i % (nYZTterm)) % (nZTterm)) / nTterm; // z index
+            int it = ((i % (nYZTterm)) % (nZTterm)) % nTterm; // t index
+            if (coeffMask[ix][iy][iz][it] & PS_POLY_MASK_BOTH) {
+                matrix[i][i] = 1.0;
+                continue;
+            }
+
+            vector[i] += fData[k] * Sums[ix][iy][iz][it] * wt;
+            matrix[i][i] += Sums[2*ix][2*iy][2*iz][2*it] * wt;
+            for (int j = i + 1; j < nTerm; j++) {
+                int jx = j / nYZTterm; // x index
+                int jy = (j % nYZTterm) / nZTterm; // y index
+                int jz = ((j % nYZTterm) % nZTterm) / nTterm; // z index
+                int jt = ((j % nYZTterm) % nZTterm) % nTterm; // t index
+                if (coeffMask[jx][jy][jz][jt] & PS_POLY_MASK_BOTH) {
+                    continue;
+                }
+                double value = Sums[ix+jx][iy+jy][iz+jz][it+jt] * wt;
+                matrix[i][j] += value;
+                matrix[j][i] += value;
+            }
+        }
+    }
+
+    // Free the sums
+    if (Sums == NULL) {
+        assert (nData == 0);
+    } else {
+        for (int ix = 0; ix < 2*nXterm; ix++) {
+            for (int iy = 0; iy < 2*nYterm; iy++) {
+                for (int iz = 0; iz < 2*nZterm; iz++) {
+                    psFree(Sums[ix][iy][iz]);
+                }
+                psFree(Sums[ix][iy]);
+            }
+            psFree(Sums[ix]);
+        }
+        psFree(Sums);
+    }
+
+    // XXX: rel10_ifa used psMatrixGJSolve().  However, this failed tests.  So, I'm using psMatrixLUD().
+    if (USE_GAUSS_JORDAN) {
+        // does the solution in place
+        // The GaussJordan version was overflowing, so I'm using LUD.
+        if (!psMatrixGJSolve(A, B)) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to perform GaussJordan elimination.\n");
+            goto escape_GJ;
+        }
+
+        // select the appropriate solution entries
+        for (int i = 0; i < nTerm; i++) {
+            int ix = i / nYZTterm; // x index
+            int iy = (i % nYZTterm) / nZTterm; // y index
+            int iz = ((i % nYZTterm) % nZTterm) / nTterm; // z index
+            int it = ((i % nYZTterm) % nZTterm) % nTterm; // t index
+	    if (coeffMask[ix][iy][iz][it] & PS_POLY_MASK_FIT) continue;
+            myPoly->coeff[ix][iy][iz][it] = B->data.F64[i];
+            myPoly->coeffErr[ix][iy][iz][it] = sqrt(A->data.F64[i][i]);
+        }
+    } else {
+        // LUD version of the fit
+        psImage *ALUD = NULL;
+        psVector* outPerm = NULL;
+        psVector* coeffs = NULL;
+
+        ALUD = psImageAlloc(nTerm, nTerm, PS_TYPE_F64);
+        ALUD = psMatrixLUD(ALUD, &outPerm, A);
+        if (ALUD == NULL) {
+            psError(PS_ERR_UNKNOWN, false, "Could not do LUD decomposition on matrix.  Returning NULL.\n");
+            goto escape_LUD;
+        } else {
+            coeffs = psMatrixLUSolve(coeffs, ALUD, B, outPerm);
+            if (coeffs == NULL) {
+                psError(PS_ERR_UNKNOWN, false, "Could not solve LUD matrix.  Returning NULL.\n");
+                goto escape_LUD;
+            } else {
+                // select the appropriate solution entries
+                for (psS32 ix = 0; ix < nXterm; ix++) {
+                    for (psS32 iy = 0; iy < nYterm; iy++) {
+                        for (psS32 iz = 0; iz < nZterm; iz++) {
+                            for (psS32 it = 0; it < nTterm; it++) {
+                                psS32 nx = ix+iy*nXterm+iz*nXterm*nYterm+it*nXterm*nYterm*nZterm;
+				if (coeffMask[ix][iy][iz][it] & PS_POLY_MASK_FIT) continue;
+                                myPoly->coeff[ix][iy][iz][it] = coeffs->data.F64[nx];
+                                // myPoly->coeffErr[ix][iy][iz][it] = sqrt(A->data.F64[nx][nx]);
+                                // XXX this is wrong: LUD does not supply inverse(A)
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        psFree(ALUD);
+        psFree(coeffs);
+        psFree(outPerm);
+    }
+    psFree(A);
+    psFree(B);
+
+    psTrace("psLib.math", 4, "---- %s() end ----\n", __func__);
+    return true;
+
+escape_LUD:
+    psFree(A);
+    psFree(B);
+    return false;
+
+escape_GJ:
+    psFree(A);
+    psFree(B);
+    return false;
+}
+
+/******************************************************************************
+psVectorFitPolynomial4D():  This routine fits a 4D polynomial of arbitrary
+degree (specified in poly) to the data points (x, y, z, t)-(f) and returns
+that polynomial.  Types F32 and F64 are supported, however, type F32 is done
+via vector conversion only.
+ *****************************************************************************/
+bool psVectorFitPolynomial4D(
+    psPolynomial4D *poly,
+    const psVector *mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x,
+    const psVector *y,
+    const psVector *z,
+    const psVector *t)
+{
+    PS_ASSERT_POLY_NON_NULL(poly, false);
+    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false);
+
+    PS_ASSERT_VECTOR_NON_NULL(f, false);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false);
+    PS_ASSERT_VECTOR_NON_NULL(x, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
+    PS_ASSERT_VECTOR_NON_NULL(y, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false);
+    PS_ASSERT_VECTOR_NON_NULL(z, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, false);
+    PS_ASSERT_VECTOR_NON_NULL(t, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, false);
+    if (mask) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false);
+        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
+    }
+    if (fErr != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false);
+        PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, false);
+    }
+
+    // Convert input vectors to F64 if necessary.
+    psVector *f64 = (f->type.type == PS_TYPE_F64) ? (psVector *) f : psVectorCopy(NULL, f, PS_TYPE_F64);
+    psVector *x64 = (x->type.type == PS_TYPE_F64) ? (psVector *) x : psVectorCopy(NULL, x, PS_TYPE_F64);
+    psVector *y64 = (y->type.type == PS_TYPE_F64) ? (psVector *) y : psVectorCopy(NULL, y, PS_TYPE_F64);
+    psVector *z64 = (z->type.type == PS_TYPE_F64) ? (psVector *) z : psVectorCopy(NULL, z, PS_TYPE_F64);
+    psVector *t64 = (t->type.type == PS_TYPE_F64) ? (psVector *) t : psVectorCopy(NULL, t, PS_TYPE_F64);
+
+    psVector *fErr64 = NULL;
+    if (fErr != NULL) {
+        fErr64 = (fErr->type.type == PS_TYPE_F64) ? (psVector *) fErr : psVectorCopy(NULL, fErr, PS_TYPE_F64);
+    }
+
+    bool result = true;
+
+    switch (poly->type) {
+    case PS_POLYNOMIAL_ORD:
+        result = VectorFitPolynomial4DOrd(poly, mask, maskValue, f64, fErr64, x64, y64, z64, t64);
+        if (!result) {
+            psError(PS_ERR_UNKNOWN, true, "Could not fit polynomial.  Returning NULL.\n");
+        }
+        break;
+    case PS_POLYNOMIAL_CHEB:
+        if (mask != NULL) {
+            psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n");
+        }
+        psError(PS_ERR_UNKNOWN, true, "4-D Chebyshev polynomial vector fitting has not been implemented.  Returning NULL.\n");
+        result = false;
+        break;
+    default:
+        psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type.  Returning NULL.\n");
+        result = false;
+        break;
+    }
+
+    // Free psVectors that were created for NULL arguments.
+    PS_FREE_TEMP_F64_VECTOR (f, f64);
+    PS_FREE_TEMP_F64_VECTOR (x, x64);
+    PS_FREE_TEMP_F64_VECTOR (y, y64);
+    PS_FREE_TEMP_F64_VECTOR (z, z64);
+    PS_FREE_TEMP_F64_VECTOR (t, t64);
+    PS_FREE_TEMP_F64_VECTOR (fErr, fErr64);
+
+    return result;
+}
+
+
+bool psVectorClipFitPolynomial4D(
+    psPolynomial4D *poly,
+    psStats *stats,
+    const psVector *mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x,
+    const psVector *y,
+    const psVector *z,
+    const psVector *t)
+{
+    psTrace("psLib.math", 3, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_POLY_NON_NULL(poly, false);
+    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false);
+    PS_ASSERT_PTR_NON_NULL(stats, false);
+    PS_ASSERT_VECTOR_NON_NULL(mask, false);
+    PS_ASSERT_VECTOR_NON_NULL(f, false);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false);
+
+    PS_ASSERT_VECTOR_NON_NULL(x, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
+    PS_ASSERT_VECTOR_TYPE(x, f->type.type, false);
+
+    PS_ASSERT_VECTOR_NON_NULL(y, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false);
+    PS_ASSERT_VECTOR_TYPE(y, f->type.type, false);
+
+    PS_ASSERT_VECTOR_NON_NULL(z, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, false);
+    PS_ASSERT_VECTOR_TYPE(z, f->type.type, false);
+
+    PS_ASSERT_VECTOR_NON_NULL(t, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, false);
+    PS_ASSERT_VECTOR_TYPE(t, f->type.type, false);
+
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false);
+    PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
+
+    if (fErr != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false);
+        PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, false);
+    }
+
+    // the user supplies one of various stats option pairs,
+    // determine the desired mean and stdev STATS options:
+    // XXX enforce consistency?
+    // XXX psStatsGetValue() probably has inverted precedence
+    psStatsOptions meanOption = stats->options & (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN | PS_STAT_ROBUST_MEDIAN | PS_STAT_CLIPPED_MEAN | PS_STAT_FITTED_MEAN | PS_STAT_FITTED_MEAN_V2);
+    psStatsOptions stdevOption = stats->options & (PS_STAT_SAMPLE_STDEV | PS_STAT_ROBUST_STDEV | PS_STAT_CLIPPED_STDEV | PS_STAT_FITTED_STDEV | PS_STAT_FITTED_STDEV_V2);
+    if (!meanOption) {
+        psError(PS_ERR_UNKNOWN, true, "no valid mean stats option selected");
+        return false;
+    }
+    if (!stdevOption) {
+        psError(PS_ERR_UNKNOWN, true, "no valid stdev stats option selected");
+        return false;
+    }
+
+    // clipping range defined by min and max and/or clipSigma
+    psF32 minClipSigma;
+    psF32 maxClipSigma;
+    if (isfinite(stats->max)) {
+        maxClipSigma = fabs(stats->max);
+    } else {
+        maxClipSigma = fabs(stats->clipSigma);
+    }
+    if (isfinite(stats->min)) {
+        minClipSigma = fabs(stats->min);
+    } else {
+        minClipSigma = fabs(stats->clipSigma);
+    }
+    psVector *resid = psVectorAlloc(f->n, PS_TYPE_F64);
+
+    psTrace("psLib.math", 4, "stats->clipIter is %d\n", stats->clipIter);
+    psTrace("psLib.math", 4, "(minClipSigma, maxClipSigma) is (%.2f, %.2f)\n", minClipSigma, maxClipSigma);
+
+    for (psS32 N = 0; N < stats->clipIter; N++) {
+        psTrace("psLib.math", 6, "Loop iteration %d.  Calling psVectorFitPolynomial4D()\n", N);
+        psS32 Nkeep = 0;
+        if (psTraceGetLevel("psLib.math") >= 6) {
+            if (mask != NULL) {
+                for (psS32 i = 0 ; i < mask->n ; i++) {
+                    psTrace("psLib.math", 6,  "mask[%d] is %d\n", i, mask->data.U8[i]);
+                }
+            }
+        }
+
+        if (!psVectorFitPolynomial4D (poly, mask, maskValue, f, fErr, x, y, z, t)) {
+            psError(PS_ERR_UNKNOWN, false, "Could not fit a polynomial to the data.  Returning NULL.\n");
+            psFree(resid);
+            return false;
+        }
+
+        psVector *fit = psPolynomial4DEvalVector (poly, x, y, z, t);
+        if (fit == NULL) {
+            psError(PS_ERR_UNKNOWN, false, "Could not call psPolynomial4DEvalVector().  Returning NULL.\n");
+            psFree(resid);
+            return false;
+        }
+        for (psS32 i = 0 ; i < f->n ; i++) {
+            if (f->type.type == PS_TYPE_F64) {
+                resid->data.F64[i] = f->data.F64[i] - fit->data.F64[i];
+            } else {
+                resid->data.F64[i] = ((psF64) f->data.F32[i]) - fit->data.F64[i];
+            }
+        }
+
+        if (psTraceGetLevel("psLib.math") >= 6) {
+            if (mask != NULL) {
+                for (psS32 i = 0 ; i < mask->n ; i++) {
+                    if (!((mask != NULL) && (mask->data.U8[i] & maskValue))) {
+                        psTrace("psLib.math", 6,  "(f, fit)[%d] is (%f, %f).  resid is (%f)\n",
+                                i, f->data.F32[i], fit->data.F32[i], resid->data.F64[i]);
+                    }
+                }
+            }
+        }
+
+        if (!psVectorStats (stats, resid, NULL, mask, maskValue)) {
+            psError(PS_ERR_UNKNOWN, false, "Could not compute statistics on the resid vector.  Returning NULL.\n");
+            psFree(resid);
+            psFree(fit);
+            return false;
+        }
+
+        double meanValue = psStatsGetValue (stats, meanOption);
+        double stdevValue = psStatsGetValue (stats, stdevOption);
+
+        psTrace("psLib.math", 5, "Mean is %f\n", meanValue);
+        psTrace("psLib.math", 5, "Stdev is %f\n", stdevValue);
+        psF32 minClipValue = -minClipSigma*stdevValue;
+        psF32 maxClipValue = +maxClipSigma*stdevValue;
+
+        // set mask if pts are not valid
+        // we are masking out any point which is out of range
+        // recovery is not allowed with this scheme
+        for (psS32 i = 0; i < resid->n; i++) {
+            if ((mask != NULL) && (mask->data.U8[i] & maskValue)) {
+                continue;
+            }
+
+            if ((resid->data.F64[i] - meanValue > maxClipValue) || (resid->data.F64[i] - meanValue < minClipValue)) {
+                if (f->type.type == PS_TYPE_F64) {
+                    psTrace("psLib.math", 6, "Masking element %d (%f).  resid->data.F64[%d] is %f\n",
+                            i, fit->data.F64[i], i, resid->data.F64[i]);
+                } else {
+                    psTrace("psLib.math", 6, "Masking element %d (%f).  resid->data.F64[%d] is %f\n",
+                            i, fit->data.F32[i], i, resid->data.F64[i]);
+                }
+
+                if (mask != NULL) {
+                    mask->data.U8[i] |= 0x01;
+                }
+                continue;
+            }
+            Nkeep++;
+        }
+        psTrace("psLib.math", 6, "keeping %d of %ld pts for fit\n", Nkeep, x->n);
+        stats->clippedNvalues = Nkeep;
+        psFree (fit);
+    }
+    // Free local temporary variables
+    psFree (resid);
+
+    psTrace("psLib.math", 3, "---- %s() end ----\n", __func__);
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizePolyFit.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizePolyFit.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizePolyFit.h	(revision 22158)
@@ -0,0 +1,137 @@
+/* @file  psMinimizePolyFit.c
+ * @brief basic minimization functions
+ *
+ * This file will contain function prototypes for various
+ * 1-D polynomial fitting routines.
+ *
+ * @author GLG, MHPCC
+ *
+ * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-01-23 22:47:23 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifndef PS_MINIMIZE_POLYFIT_H
+#define PS_MINIMIZE_POLYFIT_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+#include "psVector.h"
+#include "psMemory.h"
+#include "psArray.h"
+#include "psImage.h"
+#include "psMatrix.h"
+#include "psPolynomial.h"
+#include "psSpline.h"
+#include "psStats.h"
+#include "psTrace.h"
+#include "psError.h"
+#include "psConstants.h"
+
+/** Derive a polynomial fit.
+ *
+ *  psVectorFitPolynomial1d returns the polynomial that best fits the
+ *  observations. The input parameters are a polynomial that specifies the
+ *  fit order, myPoly, which will be altered and returned with the best-fit
+ *  coefficients; and the observations, x, y and yErr. The independent
+ *  variable list, x may be NULL, in which case the vector index is used.
+ *  The dependent variable error, yErr may be null, in which case the solution
+ *  is determined in the assumption that all data errors are equal. This
+ *  function must be valid only for types psF32, psF64.
+ *
+ *  @return psPolynomial1D*    polynomial fit
+ */
+
+bool psVectorFitPolynomial1D(
+    psPolynomial1D *poly,
+    const psVector *mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x
+);
+
+bool psVectorFitPolynomial2D(
+    psPolynomial2D *poly,
+    const psVector *mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x,
+    const psVector *y
+);
+
+bool psVectorFitPolynomial3D(
+    psPolynomial3D *poly,
+    const psVector *mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x,
+    const psVector *y,
+    const psVector *z
+);
+
+bool psVectorFitPolynomial4D(
+    psPolynomial4D *poly,
+    const psVector *mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x,
+    const psVector *y,
+    const psVector *z,
+    const psVector *t
+);
+
+
+bool psVectorClipFitPolynomial1D(
+    psPolynomial1D *poly,
+    psStats *stats,
+    const psVector *mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x
+);
+
+bool psVectorClipFitPolynomial2D(
+    psPolynomial2D *poly,
+    psStats *stats,
+    const psVector *mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x,
+    const psVector *y
+);
+
+bool psVectorClipFitPolynomial3D(
+    psPolynomial3D *poly,
+    psStats *stats,
+    const psVector *mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x,
+    const psVector *y,
+    const psVector *z
+);
+
+bool psVectorClipFitPolynomial4D(
+    psPolynomial4D *poly,
+    psStats *stats,
+    const psVector *mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x,
+    const psVector *y,
+    const psVector *z,
+    const psVector *t
+);
+
+/// @}
+#endif // #ifndef PS_MINIMIZE_POLYFIT_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizePowell.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizePowell.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizePowell.c	(revision 22158)
@@ -0,0 +1,797 @@
+/** @file  psMinimize.c
+ *  \brief basic minimization functions
+ *  @ingroup Math
+ *
+ *  This file will contain functions to minimize an arbitrary function at
+ *  a data point, fit an arbitrary function to a set of data points, and
+ *  fit a 1-D polynomial to a set of data points.
+ *
+ *  @author GLG, MHPCC
+ *
+ *  NOTE: XXX: The SDR is silent about data types.  F32 is implemented here.
+ *
+ *  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-02-06 21:36:09 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/*****************************************************************************/
+/* INCLUDE FILES                                                             */
+/*****************************************************************************/
+#include <stdio.h>
+#include <float.h>
+#include <math.h>
+
+#include "psMinimizePowell.h"
+#include "psAssert.h"
+#include "psStats.h"
+#include "psImage.h"
+#include "psImageStructManip.h"
+#include "psLogMsg.h"
+/*****************************************************************************/
+/* DEFINE STATEMENTS                                                         */
+/*****************************************************************************/
+
+// This macro takes as input the vector BASE and adds a multiple of the vector
+// LINE to it.  We assume BASEMASK is non-null.
+#define PS_VECTOR_ADD_MULTIPLE(BASE, BASEMASK, LINE, OUT, MUL) \
+for (psS32 i=0;i<BASE->n;i++) { \
+    if (BASEMASK->data.U8[i] == 0) { \
+        OUT->data.F32[i] = BASE->data.F32[i] + (MUL * LINE->data.F32[i]); \
+    } else { \
+        OUT->data.F32[i] = BASE->data.F32[i]; \
+    } \
+} \
+
+#define PS_VECTOR_F32_CHECK_ZERO_VECTOR(IN, BOOL_VAR) \
+BOOL_VAR = true; \
+for (psS32 i=0;i<IN->n;i++) { \
+    if (fabs(IN->data.F32[i]) >= FLT_EPSILON) { \
+        BOOL_VAR = false; \
+        break; \
+    } \
+} \
+
+#define PS_VECTOR_WITH_MASK_F32_CHECK_ZERO_VECTOR(IN, INMASK, BOOL_VAR) \
+BOOL_VAR = true; \
+for (psS32 i=0;i<IN->n;i++) { \
+    if ((INMASK->data.U8[i] == 0) && (fabs(IN->data.F32[i]) >= FLT_EPSILON)) { \
+        BOOL_VAR = false; \
+        break; \
+    } \
+} \
+
+/*****************************************************************************/
+/* TYPE DEFINITIONS                                                          */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* FUNCTION IMPLEMENTATION - LOCAL                                           */
+/*****************************************************************************/
+
+/******************************************************************************
+p_psDetermineBracket():  This routine takes as input an arbitrary function,
+and the parameter to vary, and the line along which it must vary.  This
+function produces as output a bracket [a, b, c] such that
+f(param + b * line) < f(param + a * line)
+f(param + b * line) < f(param + c * line)
+a < b < c
+ 
+Algorithm:
+ 
+XXX completely ad hoc:
+start with the user-supplied starting parameter and
+call that b.  Calculate a/c as a fractional amount smaller/larger than b.
+Repeat this process until a local minimum is found.
+ 
+XXX: new algorithm:
+start at x=0, expand in one direction until the function
+decreases.  Then you have two points in the bracket.  Keep going until it
+increases, or x is too large.  If thst does not work, expand in the other
+direction.
+ 
+XXX: output bracket vector should be an input as well.
+*****************************************************************************/
+psVector *p_psDetermineBracket(
+    psVector *params,
+    psVector *line,
+    const psVector *paramMask,
+    const psArray *coords,
+    psMinimizePowellFunc func)
+{
+    psF32 a = 0.0;
+    psF32 b = 0.0;
+    psF32 c = 0.0;
+    psF32 fa = 0.0;
+    psF32 fb = 0.0;
+    psF32 fc = 0.0;
+    psS32 iter = 100;
+    psF32 aDir = 0.0;
+    psF32 cDir = 0.0;
+    psF32 new_aDir = 0.0;
+    psF32 new_cDir = 0.0;
+    psVector *bracket = psVectorAlloc(3, PS_TYPE_F32);
+    psF32 stepSize = PS_DETERMINE_BRACKET_STEP_SIZE;
+    psVector *tmp = NULL;
+    bool boolLineIsNull = true;
+
+    psTrace("psLib.math", 4, "---- p_psDetermineBracket() begin ----\n");
+
+    // If the line vector is zero, then return NULL.
+    PS_VECTOR_WITH_MASK_F32_CHECK_ZERO_VECTOR(params, paramMask, boolLineIsNull);
+    if (boolLineIsNull == true) {
+        psTrace("psLib.math", 2, "p_psDetermineBracket() called with zero line vector.\n");
+        psTrace("psLib.math", 4, "---- p_psDetermineBracket() end (NULL) ----\n");
+        psFree(bracket);
+        return(NULL);
+    }
+
+    tmp = psVectorAlloc(params->n, PS_TYPE_F32);
+
+    b = 0;
+    a = -stepSize;
+    c = stepSize;
+
+    PS_VECTOR_ADD_MULTIPLE(params, paramMask, line, tmp, a);
+    fa = func(tmp, coords);
+
+    PS_VECTOR_ADD_MULTIPLE(params, paramMask, line, tmp, b);
+    fb = func(tmp, coords);
+
+    PS_VECTOR_ADD_MULTIPLE(params, paramMask, line, tmp, c);
+    fc = func(tmp, coords);
+
+    if (fa < fb) {
+        aDir = -1;
+    } else {
+        aDir = 1;
+    }
+
+    if (fc < fb) {
+        cDir = -1;
+    } else {
+        cDir = 1;
+    }
+
+    psTrace("psLib.math", 6, "(a, b, c) is (%f %f %f) (fa, fb, fc) is (%f %f %f)\n", a, b, c, fa, fb, fc);
+
+    while (iter > 0) {
+        psTrace("psLib.math", 6, "psDetermineBracket(): iteration %d\n", iter);
+        if ((fb < fa) && (fb < fc)) {
+            bracket->data.F32[0] = a;
+            bracket->data.F32[1] = b;
+            bracket->data.F32[2] = c;
+            psFree(tmp);
+            psTrace("psLib.math", 6, "---- p_psDetermineBracket() end ----\n");
+            return(bracket);
+        }
+        stepSize*= (1.0 + stepSize);
+        a =- stepSize;
+        c =+ stepSize;
+
+        PS_VECTOR_ADD_MULTIPLE(params, paramMask, line, tmp, a);
+        fa = func(tmp, coords);
+
+        PS_VECTOR_ADD_MULTIPLE(params, paramMask, line, tmp, c);
+        fc = func(tmp, coords);
+
+        psTrace("psLib.math", 6, "Iter(%d): (a, b, c) is (%f %f %f) (fa, fb, fc) is (%f %f %f)\n", iter, a, b, c, fa, fb, fc);
+
+        if (fa < fb) {
+            new_aDir = -1;
+        } else {
+            new_aDir = 1;
+        }
+
+        if (fc < fb) {
+            new_cDir = -1;
+        } else {
+            new_cDir = 1;
+        }
+        if ((new_aDir == 1) && (aDir == -1)) {
+            bracket->data.F32[0] = a;
+            bracket->data.F32[1] = b;
+            bracket->data.F32[2] = c;
+            psFree(tmp);
+            psTrace("psLib.math", 4, "---- p_psDetermineBracket() end ----\n");
+            return(bracket);
+        }
+
+        if ((new_cDir == 1) && (cDir == -1)) {
+            bracket->data.F32[0] = a;
+            bracket->data.F32[1] = b;
+            bracket->data.F32[2] = c;
+            psFree(tmp);
+            psTrace("psLib.math", 4, "---- p_psDetermineBracket() end ----\n");
+            return(bracket);
+        }
+        aDir = new_aDir;
+        cDir = new_cDir;
+        iter--;
+    }
+    psFree(tmp);
+    psFree(bracket);
+    psTrace("psLib.math", 4, "---- p_psDetermineBracket() end (NULL) ----\n");
+    return(NULL);
+}
+
+
+#define RETURN_FINAL_BRACKET(d) \
+if (a < c) { \
+    bracket->data.F32[0] = a; \
+    bracket->data.F32[1] = b; \
+    bracket->data.F32[2] = c; \
+} else { \
+    bracket->data.F32[0] = c; \
+    bracket->data.F32[1] = b; \
+    bracket->data.F32[2] = a; \
+} \
+psTrace("psLib.math", 4, "Final bracket (a, b, c) is (%f %f %f) (fa, fb, fc) is (%f %f %f)\n", a, b, c, fa, fb, fc); \
+psTrace("psLib.math", 4, "---- p_psDetermineBracket() end ----\n"); \
+psFree(tmp); \
+return(bracket); \
+
+#define PS_DETERMINE_BRACKET_MAX_ITERATIONS 100
+psVector *p_psDetermineBracket2(
+    psVector *params,
+    psVector *line,
+    const psVector *paramMask,
+    const psArray *coords,
+    psMinimizePowellFunc func)
+{
+    psF32 a = 0.0;
+    psF32 b = 0.0;
+    psF32 c = 0.0;
+    psF32 fa = 0.0;
+    psF32 fb = 0.0;
+    psF32 fc = 0.0;
+    psS32 iter = 0;
+    psVector *tmp = psVectorAlloc(params->n, PS_TYPE_F32);
+    bool boolLineIsNull = true;
+    psF32 prevMin = 0.0;
+    psS32 countMin = 0;
+
+    psTrace("psLib.math", 4, "---- p_psDetermineBracket() begin ----\n");
+
+    // If the line vector is zero, then return NULL.
+    PS_VECTOR_WITH_MASK_F32_CHECK_ZERO_VECTOR(params, paramMask, boolLineIsNull);
+    if (boolLineIsNull == true) {
+        psTrace("psLib.math", 2, "p_psDetermineBracket() called with zero line vector.\n");
+        psTrace("psLib.math", 4, "---- p_psDetermineBracket() end (NULL) ----\n");
+        psFree(tmp);
+        return(NULL);
+    }
+
+    // We determine in what x-direction does the function decrease.
+    a = 0.0;
+    fa = func(params, coords);
+    b = 0.5;
+    iter = 0;
+    do {
+        b*= (1.0 + PS_DETERMINE_BRACKET_STEP_SIZE);
+        PS_VECTOR_ADD_MULTIPLE(params, paramMask, line, tmp, b);
+        fb = func(tmp, coords);
+    } while ((fabs(fb - fa) < FLT_EPSILON) && (iter++ < 100));
+
+    if (fb > fa) {
+        a = b;
+        fa = fb;
+        b = 0.0;
+        fb = func(params, coords);
+    }
+    c = b;
+
+    // At this point we have (a, b) and we know that (fa >= fb).  Initially, c=b;
+    // We keep stretching b out further from "a" until (fc > previous fc).  If
+    // that happens, then we have our bracket.
+    psVector *bracket = psVectorAlloc(3, PS_TYPE_F32);
+    iter = 0;
+    while (iter < PS_DETERMINE_BRACKET_MAX_ITERATIONS) {
+        psTrace("psLib.math", 6, "psDetermineBracket(): iterationA %d\n", iter);
+        c+= (1.0 + PS_DETERMINE_BRACKET_STEP_SIZE) * (c - a);
+
+        PS_VECTOR_ADD_MULTIPLE(params, paramMask, line, tmp, c);
+        fc = func(tmp, coords);
+
+        psTrace("psLib.math", 6, "Iteration(%d) (bracket): (a, b, c) is (%f %f %f) (fa, fb, fc) is (%f %f %f)\n", iter, a, b, c, fa, fb, fc);
+
+        if ((fb < fa) && (fb < fc)) {
+            RETURN_FINAL_BRACKET();
+        } else {
+            b = c;
+            fb = fc;
+        }
+
+        // This code maintains a count of how many times the minimum fc has
+        // stayed the same.  If it gets too high, we exit this loop.
+        if (fc == prevMin) {
+            countMin++;
+        } else {
+            countMin = 0;
+        }
+        prevMin = fc;
+        if (countMin == 10) {
+            RETURN_FINAL_BRACKET();
+        }
+
+        iter++;
+    }
+
+    psFree(bracket);
+    psTrace("psLib.math", 4, "---- p_psDetermineBracket() end (NULL) (BAD) ----\n");
+    return(NULL);
+}
+
+/******************************************************************************
+This routine takes as input a possibly multi-dimensional function, along
+with an initial guess at the parameters of that function and vector "line"
+of the same size as the parameter vector.  It will minimize the function
+along that vector and returns the offset along that vector at which the
+minimum is determined.
+ 
+XXX: This routine is not very efficient in terms of total evaluations of the
+function.
+XXX: Since this is an internal function, many of the parameter checks are
+     redundant.
+ *****************************************************************************/
+#define PS_LINEMIN_MAX_ITERATIONS 30
+static psF32 LineMin(
+    psMinimization *min,
+    psVector *params,
+    psVector *line,
+    const psVector *paramMask,
+    const psArray *coords,
+    psMinimizePowellFunc func)
+{
+    PS_ASSERT_PTR_NON_NULL(min, NAN);
+    PS_ASSERT_VECTOR_NON_NULL(params, NAN);
+    PS_ASSERT_VECTOR_NON_EMPTY(params, NAN);
+    PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32, NAN);
+    PS_ASSERT_VECTOR_NON_NULL(line, NAN);
+    PS_ASSERT_VECTOR_NON_EMPTY(line, NAN);
+    PS_ASSERT_VECTOR_TYPE(line, PS_TYPE_F32, NAN);
+    PS_ASSERT_VECTOR_NON_NULL(paramMask, NAN);
+    PS_ASSERT_VECTOR_NON_EMPTY(paramMask, NAN);
+    PS_ASSERT_VECTOR_TYPE(paramMask, PS_TYPE_U8, NAN);
+    PS_ASSERT_PTR_NON_NULL(coords, NAN);
+    PS_ASSERT_PTR_NON_NULL(func, NAN);
+    psVector *bracket;
+    psF32 a = 0.0;
+    psF32 b = 0.0;
+    psF32 c = 0.0;
+    psF32 n = 0.0;
+    psF32 fa = 0.0;
+    psF32 fb = 0.0;
+    psF32 fc = 0.0;
+    psF32 fn = 0.0;
+    psF32 mul = 0.0;
+    psS32 i = 0;
+    psS32 boolLineIsNull = true;
+    psS32 numIterations = 0;
+
+    psTrace("psLib.math", 4, "---- LineMin() begin ----\n");
+    PS_VECTOR_F32_CHECK_ZERO_VECTOR(line, boolLineIsNull);
+
+    if (boolLineIsNull == true) {
+        min->value = func(params, coords);
+        psTrace("psLib.math", 2, "LineMin() called with zero line vector.  Return 0.0.  Function value is %f\n", min->value);
+        return(0.0);
+    }
+
+    if (6 <= psTraceGetLevel("psLib.math")) {
+        for (i=0;i<params->n;i++) {
+            psTrace("psLib.math", 6, "(params, paramMask, line)[%d] is (%f %d %f)\n", i,
+                    params->data.F32[i], paramMask->data.U8[i], line->data.F32[i]);
+        }
+    }
+
+    bracket = p_psDetermineBracket2(params, line, paramMask, coords, func);
+    if (bracket == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "Could not bracket minimum.  Returning NAN.\n");
+        return(NAN);
+    }
+    numIterations = 0;
+
+    psVector *tmpa = psVectorAlloc(params->n, PS_TYPE_F32);
+    psVector *tmpb = psVectorAlloc(params->n, PS_TYPE_F32);
+    psVector *tmpc = psVectorAlloc(params->n, PS_TYPE_F32);
+    psVector *tmpn = psVectorAlloc(params->n, PS_TYPE_F32);
+
+    while (numIterations < PS_LINEMIN_MAX_ITERATIONS) {
+        numIterations++;
+        psTrace("psLib.math", 6, "LineMin(): iteration %d\n", numIterations);
+
+        a = bracket->data.F32[0];
+        b = bracket->data.F32[1];
+        c = bracket->data.F32[2];
+        PS_VECTOR_ADD_MULTIPLE(params, paramMask, line, tmpa, a);
+        PS_VECTOR_ADD_MULTIPLE(params, paramMask, line, tmpb, b);
+        PS_VECTOR_ADD_MULTIPLE(params, paramMask, line, tmpc, c);
+        fa = func(tmpa, coords);
+        fb = func(tmpb, coords);
+        fc = func(tmpc, coords);
+        psTrace("psLib.math", 6, "LineMin: f(%f %f %f) is (%f %f %f)\n", a, b, c, fa, fb, fc);
+
+        // We determine which is the biggest segment in [a,b,c] then split
+        // that with the point n.
+        if ((b-a) > (c-b)) {
+            // This is the golden section formula
+            n = a + (0.69 * (b-a));
+            for (i=0;i<params->n;i++) {
+                tmpn->data.F32[i] = params->data.F32[i] + (n * line->data.F32[i]);
+            }
+            fn = func(tmpn, coords);
+
+            if (fn > fb) {
+                // a = n, b = b, c = c
+                bracket->data.F32[0] = n;
+            } else {
+                // a = a, b = n, c = b
+                bracket->data.F32[1] = n;
+                bracket->data.F32[2] = b;
+            }
+        } else {
+            n = b + (0.69 * (c-b));
+            for (i=0;i<params->n;i++) {
+                tmpn->data.F32[i] = params->data.F32[i] + (n * line->data.F32[i]);
+            }
+            fn = func(tmpn, coords);
+
+            if (fn > fb) {
+                // a = a, b = b, c = n
+                bracket->data.F32[2] = n;
+            } else {
+                // a = b, b = n, c = c
+                bracket->data.F32[0] = b;
+                bracket->data.F32[1] = n;
+            }
+        }
+        psTrace("psLib.math", 6, "LineMin: new bracket is (%f %f %f)\n", bracket->data.F32[0], bracket->data.F32[1], bracket->data.F32[2]);
+
+        mul = bracket->data.F32[1];
+        if ((fabs(a-b) < min->tol) && (fabs(b-c) < min->tol)) {
+            PS_VECTOR_ADD_MULTIPLE(params, paramMask, line, params, mul);
+            min->value = func(params, coords);
+            psFree(bracket);
+            psTrace("psLib.math", 4, "---- LineMin() end.a (%f) (%f) ----\n", mul, min->value);
+            psFree(tmpa);
+            psFree(tmpb);
+            psFree(tmpc);
+            psFree(tmpn);
+            return(mul);
+        }
+    }
+
+    mul = bracket->data.F32[1];
+    PS_VECTOR_ADD_MULTIPLE(params, paramMask, line, params, mul);
+    min->value = func(params, coords);
+    psTrace("psLib.math", 4, "---- LineMin() end.b (%f) %f ----\n", mul, min->value);
+
+    psFree(bracket);
+    psFree(tmpa);
+    psFree(tmpb);
+    psFree(tmpc);
+    psFree(tmpn);
+    return(mul);
+}
+
+
+/******************************************************************************
+This routine must minimize a possibly multi-dimensional function.  The
+function to be minimized "func" is:
+    psF32 func(psVector *params, psArray *coords)
+The "params" are the parameters of the function which are varied.  The data
+points at which the function is varied are in the argument "coords" which is
+a psArray of psVectors: each vector represents a different coordinate.
+ 
+XXX: We do not use Brent's method.
+ *****************************************************************************/
+#define PS_MINIMIZE_POWELL_LINEMIN_MAX_ITERATIONS 20
+#define PS_MINIMIZE_POWELL_LINEMIN_ERROR_TOLERANCE 0.01
+
+bool psMinimizePowell(
+    psMinimization *min,
+    psVector *params,
+    const psVector *paramMask,
+    const psArray *coords,
+    psMinimizePowellFunc func)
+{
+    PS_ASSERT_PTR_NON_NULL(min, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(params, NULL);
+    PS_ASSERT_VECTOR_NON_EMPTY(params, NULL);
+    PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32, NULL);
+    PS_ASSERT_PTR_NON_NULL(coords, NULL);
+    PS_ASSERT_PTR_NON_NULL(func, NULL);
+    psS32 numDims = params->n;
+    psS32 i = 0;
+    psS32 j = 0;
+    psVector *myParamMask = NULL;
+    psMinimization dummyMin;
+    psF32 mul = 0.0;
+    psF32 baseFuncVal = 0.0;
+    psF32 currFuncVal = 0.0;
+    psS32 biggestIter = 0;
+    psF32 biggestDiff = 0.0;
+    psS32 iterationNumber = 0;
+
+    psTrace("psLib.math", 4, "---- psMinimizePowell() begin ----\n");
+    psTrace("psLib.math", 6, "min->maxIter is %d\n", min->maxIter);
+    psTrace("psLib.math", 6, "min->tol is %f\n", min->tol);
+
+    if (paramMask == NULL) {
+        myParamMask = psVectorAlloc(params->n, PS_TYPE_U8);
+        psVectorInit(myParamMask, 0);
+    } else {
+        myParamMask = (psVector *) paramMask;
+    }
+    PS_ASSERT_VECTORS_SIZE_EQUAL(params, myParamMask, NULL);
+
+
+    psVector *pQP = psVectorAlloc(numDims, PS_TYPE_F32);
+    psVector *u   = psVectorAlloc(numDims, PS_TYPE_F32);
+    psVector *Q   = psVectorAlloc(numDims, PS_TYPE_F32);
+
+    // 1: Set v[i] to be the unit vectors for each dimension in params
+    psArray *v = psArrayAlloc(numDims);
+    for (i=0;i<numDims;i++) {
+        (v->data[i]) = (psVector *) psVectorAlloc(numDims, PS_TYPE_F32);
+        for (j=0;j<numDims;j++) {
+            if (i == j) {
+                ((psVector *) (v->data[i]))->data.F32[j] = 1.0;
+            } else {
+                ((psVector *) (v->data[i]))->data.F32[j] = 0.0;
+            }
+        }
+    }
+
+    // 2: Set Q to be the initial params (P in the ADD)
+    for (i=0;i<numDims;i++) {
+        Q->data.F32[i] = params->data.F32[i];
+        Q->n++;
+    }
+
+    while (iterationNumber < min->maxIter) {
+        iterationNumber++;
+        psTrace("psLib.math", 6, "psMinimizePowell() iteration %d\n", iterationNumber);
+
+        // 3: For each dimension in params, move Q only in the vector v[i] to
+        //    minimize the function.
+
+        baseFuncVal = func(Q, coords);
+        currFuncVal = baseFuncVal;
+        psTrace("psLib.math", 6, "Current function value is %f\n", currFuncVal);
+
+        biggestDiff = 0;
+        biggestIter = 0;
+        for (i=0;i<numDims;i++) {
+            if (myParamMask->data.U8[i] == 0) {
+                P_PSMINIMIZATION_SET_MAXITER((&dummyMin),PS_MINIMIZE_POWELL_LINEMIN_MAX_ITERATIONS);
+                *(float*)&dummyMin.tol = PS_MINIMIZE_POWELL_LINEMIN_ERROR_TOLERANCE;
+                mul = LineMin(&dummyMin, Q, ((psVector *) v->data[i]),
+                              myParamMask, coords, func);
+                if (isnan(mul)) {
+                    psError(PS_ERR_UNKNOWN, false,
+                            "Could not perform line minimization.  Returning FALSE.\n");
+                    psFree(v);
+                    psFree(pQP);
+                    psFree(u);
+                    psFree(Q);
+                    psFree(myParamMask);
+                    return(false);
+                }
+                psTrace("psLib.math", 6, "LineMin along dimension %d has multiple %f\n", i, mul);
+
+                if (fabs(dummyMin.value - currFuncVal) > biggestDiff) {
+                    biggestDiff = fabs(dummyMin.value - currFuncVal);
+                    biggestIter = i;
+                }
+                currFuncVal = dummyMin.value;
+            }
+            // XXX: how can it be that we are not saving mul anywhere?
+        }
+        psTrace("psLib.math", 6, "New function value is %f\n", currFuncVal);
+        // XXX: There must be a bug here.  How can currFuncVal be the current function value?
+        // It is simply the minimum along one of the parameter dimensions.
+
+        // 4: Set the vector u = Q - P
+        for (i=0;i<numDims;i++) {
+            if (myParamMask->data.U8[i] == 0) {
+                u->data.F32[i] = Q->data.F32[i] - params->data.F32[i];
+                u->n++;
+
+                psTrace("psLib.math", 6, "u[i]=Q[i]-P[i] (%f = %f - %f)\n", u->data.F32[i],
+                        Q->data.F32[i],
+                        params->data.F32[i]);
+
+            } else {
+                u->data.F32[i] = 0.0;
+                u->n++;
+            }
+        }
+
+        // 5: Move Q only in the direction u, and minimize the function.
+        for (i=0;i<numDims;i++) {
+            psTrace("psLib.math", 6, "u[i] is %f\n", u->data.F32[i]);
+        }
+
+        mul = LineMin(&dummyMin, params, u, myParamMask, coords, func);
+        if (isnan(mul)) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Could not perform line minimization.  Returning FALSE.\n");
+            psFree(v);
+            psFree(pQP);
+            psFree(u);
+            psFree(Q);
+            psFree(myParamMask);
+            return(false);
+        }
+
+        // 6:
+        if (dummyMin.value > currFuncVal) {
+            psFree(v);
+            psFree(pQP);
+            psFree(u);
+            psFree(Q);
+            min->iter = iterationNumber;
+            min->value = currFuncVal;
+            min->lastDelta = 0.0;
+            psTrace("psLib.math", 4, "---- psMinimizePowell() end (1)(true) ----\n");
+            psFree(myParamMask);
+            return(true);
+        }
+
+        for (i=0;i<numDims;i++) {
+            if (myParamMask->data.U8[i] == 0) {
+                pQP->data.F32[i] = (2 * Q->data.F32[i]) - params->data.F32[i];
+            } else {
+                pQP->data.F32[i] = params->data.F32[i];
+            }
+        }
+        psF32 fqp = func(pQP, coords);
+        psF32 term1 = (baseFuncVal - currFuncVal) - biggestDiff;
+        term1*= term1;
+        term1*= 2.0 * (baseFuncVal - (2.0 * currFuncVal) + fqp);
+        psF32 term2 = baseFuncVal - fqp;
+        term2*= term2 * biggestDiff;
+        if (term1 < term2) {
+            for (i=0;i<numDims;i++) {
+                if (myParamMask->data.U8[i] == 0) {
+                    ((psVector *) v->data[biggestIter])->data.F32[i] = u->data.F32[i];
+                }
+            }
+        }
+
+        // 7: Set P to Q
+        for (i=0;i<numDims;i++) {
+            if (myParamMask->data.U8[i] == 0) {
+                params->data.F32[i] = Q->data.F32[i];
+            }
+        }
+
+        // 8: Go to step 3 until the change is less than some tolerance.
+        if (fabs(baseFuncVal - currFuncVal) <= min->tol) {
+            psFree(v);
+            psFree(pQP);
+            psFree(u);
+            psFree(Q);
+            // XXX: Ensure that currFuncVal is the correct value to use here.
+            min->value = currFuncVal;
+            min->iter = iterationNumber;
+            min->lastDelta = currFuncVal - baseFuncVal;
+            psTrace("psLib.math", 4, "---- psMinimizePowell() end (2) (true) ----\n");
+            psFree(myParamMask);
+            return(true);
+        }
+    }
+
+    psFree(v);
+    psFree(pQP);
+    psFree(u);
+    psFree(Q);
+    min->iter = iterationNumber;
+    psTrace("psLib.math", 4, "---- psMinimizePowell() end (0) (false) ----\n");
+
+    psFree(myParamMask);
+    return(false);
+}
+
+
+/******************************************************************************
+This routine is to be used with the psMinimizeChi2Powell() function below.
+and the psMinimizePowell() function above.
+ 
+The basic idea is calculate chi-squared for a set of params/coords/errors.
+This functions uses global variables to receive the function pointer, the
+data values, and the data errors.
+ *****************************************************************************/
+static psF32 myPowellChi2Func(
+    const psVector *params,
+    const psArray *coords)
+{
+    psTrace("psLib.math", 4, "---- myPowellChi2Func() begin ----\n");
+    PS_ASSERT_VECTOR_NON_NULL(params, NAN);
+    PS_ASSERT_VECTOR_NON_EMPTY(params, NAN);
+    PS_ASSERT_PTR_NON_NULL(coords, NAN);
+
+    psF32 chi2 = 0.0;
+    psF32 d;
+    psS32 i;
+    psVector *tmp;
+
+    psVector *values = coords->data[coords->n];
+    psVector *errors = coords->data[coords->n + 1];
+    psMinimizeChi2PowellFunc *func = coords->data[coords->n + 2];
+
+    PS_ASSERT_VECTOR_NON_NULL(values, NAN);
+    PS_ASSERT_VECTOR_NON_EMPTY(values, NAN);
+    PS_ASSERT_VECTOR_TYPE(values, PS_TYPE_F32, NAN);
+    if (errors) {
+        PS_ASSERT_VECTOR_NON_NULL(errors, NAN);
+        PS_ASSERT_VECTOR_NON_EMPTY(errors, NAN);
+        PS_ASSERT_VECTOR_TYPE(errors, PS_TYPE_F32, NAN);
+        PS_ASSERT_VECTORS_SIZE_EQUAL(values, errors, NAN);
+    }
+
+    tmp = (*func)(params, coords);
+
+    if (errors == NULL) {
+        for (i=0;i<coords->n;i++) {
+            d = (tmp->data.F32[i] - values->data.F32[i]);
+            chi2+= d * d;
+        }
+    } else {
+        for (i=0;i<coords->n;i++) {
+            d = (tmp->data.F32[i] - values->data.F32[i]) / errors->data.F32[i];
+            chi2+= d * d;
+        }
+    }
+    psFree(tmp);
+    psTrace("psLib.math", 4, "---- myPowellChi2Func() end (chi2 is %f) ----\n", chi2);
+    return(chi2);
+}
+
+
+/******************************************************************************
+This routine must minimize the chi-squared match of a set of data points and
+values for a possibly multi-dimensional function.
+ 
+The basic idea is to use the psMinimizePowell() function defined above.  In
+order to do so, we defined above a function myPowellChi2Func() which takes
+the "func" function and returns chi-squared over the params/coords/values.
+We then use that function myPowellChi2Func() in the call to
+psMinimizePowell().
+ *****************************************************************************/
+bool psMinimizeChi2Powell(
+    psMinimization *min,
+    psVector *params,
+    psMinConstraint *constraint,
+    const psArray *coords,
+    const psVector *value,
+    const psVector *error,
+    psMinimizeChi2PowellFunc model)
+{
+    // Generate extended version of coords array, so we can pass in extra data to the chi^2 function
+    psArray *newCoords = psArrayAlloc(coords->n + 3);
+    for (long i = 0; i < coords->n; i++) {
+        newCoords->data[i] = psMemIncrRefCounter(coords->data[i]);
+    }
+    newCoords->n = coords->n;           // We deceive everyone else as to the length
+    // Casting away const: I'm not going to hurt you, just want to increment your reference counter is all
+    newCoords->data[coords->n] = psMemIncrRefCounter((psVector*)value);
+    newCoords->data[coords->n + 1] = psMemIncrRefCounter((psVector*)error);
+    newCoords->data[coords->n + 2] = &model;
+
+    bool success = psMinimizePowell(min, params, constraint->paramMask, newCoords, myPowellChi2Func);
+
+    newCoords->data[coords->n - 1] = NULL; // We can't free the array with a function pointer on it
+    psFree(newCoords);
+    return success;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizePowell.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizePowell.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psMinimizePowell.h	(revision 22158)
@@ -0,0 +1,85 @@
+/* @file  psMinimizePowell.c
+ * @brief basic minimization functions
+ *
+ * This file will contain function prototypes for various Powell
+ * chi-squared minimization routines.
+ *
+ * @author GLG, MHPCC
+ *
+ * @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-01-23 22:47:23 $
+ *
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifndef PS_MINIMIZE_POWELL_H
+#define PS_MINIMIZE_POWELL_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+#include "psMinimizeLMM.h"
+#include "psVector.h"
+#include "psMemory.h"
+#include "psArray.h"
+#include "psImage.h"
+#include "psMatrix.h"
+#include "psPolynomial.h"
+#include "psSpline.h"
+#include "psStats.h"
+#include "psTrace.h"
+#include "psError.h"
+#include "psConstants.h"
+
+/** Specifies the format of a user-defined function that the general Powell
+ *  minimizer routine will accept.
+ *
+ *  @return float:   the single float value of the function given the parameters
+ *      and coordinate vectors.
+*/
+typedef
+float (*psMinimizePowellFunc)(
+    const psVector *params,            ///< Parameters used to evaluate the function
+    const psArray *coords              ///< Coordinates at which to evaluate
+);
+
+/** Minimizes a specified function based on the Powell method.
+ *
+ *  @return bool:   True if successful.
+ */
+bool psMinimizePowell(
+    psMinimization *min,               ///< Minimization specification
+    psVector *params,                  ///< "Best guess" for parameters that minimize func
+    const psVector *paramMask,         ///< Parameters to be held fixed by minimizer
+    const psArray *coords,             ///< Measurement coordinates
+    psMinimizePowellFunc func          ///< Specified function
+);
+
+/** Specifies the format of a user-defined function that the general Powell chi-
+ *  squared minimizer routine will accept.
+ *
+ *  @return psVector*:    Calculated values given the parameters and coordinates.
+*/
+typedef
+psVector *(*psMinimizeChi2PowellFunc)(
+    const psVector *params,            ///< Parameters used to evaluate the function
+    const psArray *coords              ///< Coordinates at which to evaluate
+);
+
+/** Minimizes a specified function based on the Powell chi-squared method.
+ *
+ *  @return bool:   True is successful.
+ */
+bool psMinimizeChi2Powell(
+    psMinimization *min,               ///< Minimization specification
+    psVector *params,                  ///< "Best guess" for parameters that minimize func
+    psMinConstraint *constraint,
+    const psArray *coords,             ///< Measurement coordinates
+    const psVector *value,             ///< Measured values at the coordinates
+    const psVector *error,             ///< Errors in the measure values (or NULL)
+    psMinimizeChi2PowellFunc model     ///< Specified function
+);
+
+/// @}
+#endif // #ifndef PS_MINIMIZE_POWELL_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomial.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomial.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomial.c	(revision 22158)
@@ -0,0 +1,1223 @@
+/** @file  psPolynomial.c
+*
+*  @brief Contains basic function allocation, deallocation, and evaluation
+*         routines.
+*
+*  This file will hold the routiness for allocating, freeing, and evaluating
+*  polynomials.  It also contains a Gaussian functions.
+*
+*  @version $Revision: 1.158 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-10-09 19:24:46 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*
+*  XXX: Should the "coeffErr[]" be used as well?  Bug ???.  Ignore coeffErr
+*
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/*****************************************************************************/
+/*  INCLUDE FILES                                                            */
+/*****************************************************************************/
+#include <stdio.h>
+#include <stdbool.h>
+#include <float.h>
+#include <math.h>
+
+#include "psRandom.h"
+#include "psMemory.h"
+#include "psVector.h"
+#include "psScalar.h"
+#include "psTrace.h"
+#include "psError.h"
+#include "psLogMsg.h"
+#include "psPolynomial.h"
+#include "psAssert.h"
+
+
+/*****************************************************************************/
+/* DEFINE STATEMENTS                                                         */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* TYPE DEFINITIONS                                                          */
+/*****************************************************************************/
+static void polynomial1DFree(psPolynomial1D* poly);
+static void polynomial2DFree(psPolynomial2D* poly);
+static void polynomial3DFree(psPolynomial3D* poly);
+static void polynomial4DFree(psPolynomial4D* poly);
+
+/*****************************************************************************/
+/* GLOBAL VARIABLES                                                          */
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/* FILE STATIC VARIABLES                                                     */
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/* FUNCTION IMPLEMENTATION - LOCAL                                           */
+/*****************************************************************************/
+
+bool psMemCheckPolynomial1D(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)polynomial1DFree );
+}
+
+bool psMemCheckPolynomial2D(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)polynomial2DFree );
+}
+
+bool psMemCheckPolynomial3D(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)polynomial3DFree );
+}
+
+bool psMemCheckPolynomial4D(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)polynomial4DFree );
+}
+
+static void polynomial1DFree(psPolynomial1D* poly)
+{
+    psFree(poly->coeff);
+    psFree(poly->coeffErr);
+    psFree(poly->coeffMask);
+}
+
+static void polynomial2DFree(psPolynomial2D* poly)
+{
+    unsigned int x = 0;
+
+    for (x = 0; x < (1 + poly->nX); x++) {
+        psFree(poly->coeff[x]);
+        psFree(poly->coeffErr[x]);
+        psFree(poly->coeffMask[x]);
+    }
+    psFree(poly->coeff);
+    psFree(poly->coeffErr);
+    psFree(poly->coeffMask);
+}
+
+static void polynomial3DFree(psPolynomial3D* poly)
+{
+    unsigned int x = 0;
+    unsigned int y = 0;
+
+    for (x = 0; x < (1 + poly->nX); x++) {
+        for (y = 0; y < (1 + poly->nY); y++) {
+            psFree(poly->coeff[x][y]);
+            psFree(poly->coeffErr[x][y]);
+            psFree(poly->coeffMask[x][y]);
+        }
+        psFree(poly->coeff[x]);
+        psFree(poly->coeffErr[x]);
+        psFree(poly->coeffMask[x]);
+    }
+
+    psFree(poly->coeff);
+    psFree(poly->coeffErr);
+    psFree(poly->coeffMask);
+}
+
+static void polynomial4DFree(psPolynomial4D* poly)
+{
+    unsigned int x = 0;
+    unsigned int y = 0;
+    unsigned int z = 0;
+
+    for (x = 0; x < (1 + poly->nX); x++) {
+        for (y = 0; y < (1 + poly->nY); y++) {
+            for (z = 0; z < (1 + poly->nZ); z++) {
+                psFree(poly->coeff[x][y][z]);
+                psFree(poly->coeffErr[x][y][z]);
+                psFree(poly->coeffMask[x][y][z]);
+            }
+            psFree(poly->coeff[x][y]);
+            psFree(poly->coeffErr[x][y]);
+            psFree(poly->coeffMask[x][y]);
+        }
+        psFree(poly->coeff[x]);
+        psFree(poly->coeffErr[x]);
+        psFree(poly->coeffMask[x]);
+    }
+
+    psFree(poly->coeff);
+    psFree(poly->coeffErr);
+    psFree(poly->coeffMask);
+}
+
+/*****************************************************************************
+p_psCreateChebyshevPolys(n): this routine takes as input the required order n,
+and returns as output as a pointer to an array of n psPolynomial1D
+structures, corresponding to the first n Chebyshev polynomials.
+ 
+XXX: The output should be static since the Chebyshev polynomials might be
+used frequently and the data structure created here does not contain the
+outer coefficients of the Chebyshev polynomials.
+ *****************************************************************************/
+psPolynomial1D **p_psCreateChebyshevPolys(psS32 numPolys)
+{
+    PS_ASSERT_INT_LARGER_THAN_OR_EQUAL(numPolys, 1, NULL);
+
+    psPolynomial1D **chebPolys = (psPolynomial1D **) psAlloc(numPolys * sizeof(psPolynomial1D *));
+    for (psS32 i = 0; i < numPolys; i++) {
+        chebPolys[i] = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, i);
+    }
+
+    // Create the Chebyshev polynomials.
+    // Polynomial i has i-th order.
+    chebPolys[0]->coeff[0] = 1.0;
+    if (numPolys >= 2) {
+        chebPolys[1]->coeff[1] = 1.0;
+
+        for (psS32 i = 2; i < numPolys; i++) {
+            for (psS32 j = 0; j < chebPolys[i - 1]->nX+1; j++) {
+                chebPolys[i]->coeff[j + 1] = 2.0 * chebPolys[i - 1]->coeff[j];
+            }
+            for (psS32 j = 0; j < chebPolys[i - 2]->nX+1; j++) {
+                chebPolys[i]->coeff[j] -= chebPolys[i - 2]->coeff[j];
+            }
+        }
+    }
+
+    if (psTraceGetLevel("psLib.math") >= 6) {
+        for (psS32 j = 0; j < numPolys; j++) {
+            PS_POLY_PRINT_1D(chebPolys[j]);
+        }
+    }
+    return (chebPolys);
+}
+
+
+/*****************************************************************************
+    Polynomial coefficients will be accessed in [w][x][y][z] fashion.
+ *****************************************************************************/
+static psF64 ordPolynomial1DEval(
+    psF64 x,
+    const psPolynomial1D* poly)
+{
+    unsigned int loop_x = 0;
+    psF64 polySum = 0.0;
+    psF64 xSum = 1.0;
+
+    psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__);
+    psTrace("psLib.math", 4, "Polynomial order is %u\n", poly->nX);
+    for (loop_x = 0; loop_x < poly->nX+1; loop_x++) {
+        psTrace("psLib.math", 4, "Polynomial coeff[%u] is %lf\n", loop_x, poly->coeff[loop_x]);
+    }
+
+    for (loop_x = 0; loop_x < poly->nX+1; loop_x++) {
+        if (!(poly->coeffMask[loop_x] & PS_POLY_MASK_SET)) {
+            psTrace("psLib.math", 8,
+                    "polysum+= sum*coeff [%lf+= (%lf * %lf)\n", polySum, xSum, poly->coeff[loop_x]);
+            polySum += xSum * poly->coeff[loop_x];
+        }
+        xSum *= x;
+    }
+
+    psTrace("psLib.math", 4, "---- %s() end ----\n", __func__);
+    return(polySum);
+}
+
+// XXX: You can do this without having to psAlloc() vector d.
+// XXX: How does the mask vector effect Crenshaw's formula?
+// NOTE: We assume that x is scaled between -1.0 and 1.0;
+// XXX: Create a faster version for low-order Chebyshevs.
+static psF64 chebPolynomial1DEval(
+    psF64 x,
+    const psPolynomial1D* poly)
+{
+    PS_ASSERT_DOUBLE_WITHIN_RANGE(x, -1.0, 1.0, NAN);
+    PS_ASSERT_INT_LARGER_THAN_OR_EQUAL(poly->nX, 0, NAN);
+    psVector *d;
+
+    unsigned int nTerms = 1 + poly->nX;
+    unsigned int i;
+    psF64 tmp = 0.0;
+
+    // Special case where the Chebyshev poly is constant.
+    if (nTerms == 1) {
+        if (!(poly->coeffMask[0] & PS_POLY_MASK_SET)) {
+            tmp += poly->coeff[0];
+        }
+        return(tmp);
+    }
+
+    // Special case where the Chebyshev poly is linear.
+    if (nTerms == 2) {
+        if (!(poly->coeffMask[0] & PS_POLY_MASK_SET)) {
+            tmp+= poly->coeff[0];
+        }
+        if (!(poly->coeffMask[1] & PS_POLY_MASK_SET)) {
+            tmp+= poly->coeff[1] * x;
+        }
+        return(tmp);
+    }
+
+    if (1) {
+        // General case where the Chebyshev poly has 2 or more terms.
+        d = psVectorAlloc(nTerms, PS_TYPE_F64);
+        if (!(poly->coeffMask[nTerms-1] & PS_POLY_MASK_SET)) {
+            d->data.F64[nTerms-1] = poly->coeff[nTerms-1];
+        } else {
+            d->data.F64[nTerms-1] = 0.0;
+        }
+
+        d->data.F64[nTerms-2] = (2.0 * x * d->data.F64[nTerms-1]);
+        if (!(poly->coeffMask[nTerms-2] & PS_POLY_MASK_SET)) {
+            d->data.F64[nTerms-2] += poly->coeff[nTerms-2];
+        }
+
+        for (i=nTerms-3;i>=1;i--) {
+            d->data.F64[i] = (2.0 * x * d->data.F64[i+1]) - (d->data.F64[i+2]);
+            if (!(poly->coeffMask[i] & PS_POLY_MASK_SET)) {
+                d->data.F64[i] += poly->coeff[i];
+            }
+        }
+
+        tmp = (x * d->data.F64[1]) - (d->data.F64[2]);
+        if (!(poly->coeffMask[0] & PS_POLY_MASK_SET)) {
+            tmp += (0.5 * poly->coeff[0]);
+        }
+        psFree(d);
+    } else {
+        // XXX: This is old code that does not use Clenshaw's formula.  Get rid of it.
+        psPolynomial1D **chebPolys = p_psCreateChebyshevPolys(1 + poly->nX);
+
+        tmp = 0.0;
+        for (psS32 i=0;i<(1 + poly->nX);i++) {
+            tmp+= (poly->coeff[i] * psPolynomial1DEval(chebPolys[i], x));
+        }
+        tmp-= (poly->coeff[0]/2.0);
+
+        for (psS32 i=0;i<(1 + poly->nX);i++) {
+            psFree(chebPolys[i]);
+        }
+        psFree(chebPolys);
+    }
+
+    return(tmp);
+}
+
+static psF64 ordPolynomial2DEval(psF64 x,
+                                 psF64 y,
+                                 const psPolynomial2D* poly)
+{
+    PS_ASSERT_POLY_NON_NULL(poly, NAN);
+
+    unsigned int loop_x = 0;
+    unsigned int loop_y = 0;
+    psF64 polySum = 0.0;
+    psF64 xSum = 1.0;
+    psF64 ySum = 1.0;
+
+    for (loop_x = 0; loop_x < (1 + poly->nX); loop_x++) {
+        ySum = xSum;
+        for (loop_y = 0; loop_y < (1 + poly->nY); loop_y++) {
+            if (!(poly->coeffMask[loop_x][loop_y] & PS_POLY_MASK_SET)) {
+                polySum += ySum * poly->coeff[loop_x][loop_y];
+            }
+            ySum *= y;
+        }
+        xSum *= x;
+    }
+
+    return(polySum);
+}
+
+static psF64 chebPolynomial2DEval(psF64 x,
+                                  psF64 y,
+                                  const psPolynomial2D* poly)
+{
+    PS_ASSERT_DOUBLE_WITHIN_RANGE(x, -1.0, 1.0, 0.0);
+    PS_ASSERT_DOUBLE_WITHIN_RANGE(y, -1.0, 1.0, 0.0);
+    PS_ASSERT_POLY_NON_NULL(poly, NAN);
+
+    unsigned int loop_x = 0;
+    unsigned int loop_y = 0;
+    unsigned int i = 0;
+    psF64 polySum = 0.0;
+    psPolynomial1D* *chebPolys = NULL;
+    unsigned int maxChebyPoly = 0;
+
+    // Determine how many Chebyshev polynomials
+    // are needed, then create them.
+    maxChebyPoly = poly->nX;
+    if (poly->nY > maxChebyPoly) {
+        maxChebyPoly = poly->nY;
+    }
+    chebPolys = p_psCreateChebyshevPolys(maxChebyPoly + 1);
+
+    for (loop_x = 0; loop_x < (1 + poly->nX); loop_x++) {
+        for (loop_y = 0; loop_y < (1 + poly->nY); loop_y++) {
+            if (!(poly->coeffMask[loop_x][loop_y] & PS_POLY_MASK_SET)) {
+                polySum += poly->coeff[loop_x][loop_y] *
+                           psPolynomial1DEval(chebPolys[loop_x], x) *
+                           psPolynomial1DEval(chebPolys[loop_y], y);
+            }
+        }
+    }
+    for (i=0;i<maxChebyPoly+1;i++) {
+        psFree(chebPolys[i]);
+    }
+    psFree(chebPolys);
+    return(polySum);
+}
+
+static psF64 ordPolynomial3DEval(psF64 x,
+                                 psF64 y,
+                                 psF64 z,
+                                 const psPolynomial3D* poly)
+{
+    unsigned int loop_x = 0;
+    unsigned int loop_y = 0;
+    unsigned int loop_z = 0;
+    psF64 polySum = 0.0;
+    psF64 xSum = 1.0;
+    psF64 ySum = 1.0;
+    psF64 zSum = 1.0;
+
+    for (loop_x = 0; loop_x < (1 + poly->nX); loop_x++) {
+        ySum = xSum;
+        for (loop_y = 0; loop_y < (1 + poly->nY); loop_y++) {
+            zSum = ySum;
+            for (loop_z = 0; loop_z < (1 + poly->nZ); loop_z++) {
+                if (!(poly->coeffMask[loop_x][loop_y][loop_z] & PS_POLY_MASK_SET)) {
+                    polySum += zSum * poly->coeff[loop_x][loop_y][loop_z];
+                }
+                zSum *= z;
+            }
+            ySum *= y;
+        }
+        xSum *= x;
+    }
+
+    return(polySum);
+}
+
+static psF64 chebPolynomial3DEval(psF64 x,
+                                  psF64 y,
+                                  psF64 z,
+                                  const psPolynomial3D* poly)
+{
+    PS_ASSERT_DOUBLE_WITHIN_RANGE(x, -1.0, 1.0, 0.0);
+    PS_ASSERT_DOUBLE_WITHIN_RANGE(y, -1.0, 1.0, 0.0);
+    PS_ASSERT_DOUBLE_WITHIN_RANGE(z, -1.0, 1.0, 0.0);
+    unsigned int loop_x = 0;
+    unsigned int loop_y = 0;
+    unsigned int loop_z = 0;
+    unsigned int i = 0;
+    psF64 polySum = 0.0;
+    psPolynomial1D* *chebPolys = NULL;
+    unsigned int maxChebyPoly = 0;
+
+    // Determine how many Chebyshev polynomials
+    // are needed, then create them.
+    maxChebyPoly = poly->nX;
+    if (poly->nY > maxChebyPoly) {
+        maxChebyPoly = poly->nY;
+    }
+    if (poly->nZ > maxChebyPoly) {
+        maxChebyPoly = poly->nZ;
+    }
+    chebPolys = p_psCreateChebyshevPolys(maxChebyPoly + 1);
+
+    for (loop_x = 0; loop_x < (1 + poly->nX); loop_x++) {
+        for (loop_y = 0; loop_y < (1 + poly->nY); loop_y++) {
+            for (loop_z = 0; loop_z < (1 + poly->nZ); loop_z++) {
+                if (!(poly->coeffMask[loop_x][loop_y][loop_z] & PS_POLY_MASK_SET)) {
+                    polySum += poly->coeff[loop_x][loop_y][loop_z] *
+                               psPolynomial1DEval(chebPolys[loop_x], x) *
+                               psPolynomial1DEval(chebPolys[loop_y], y) *
+                               psPolynomial1DEval(chebPolys[loop_z], z);
+                }
+            }
+        }
+    }
+
+    for (i=0;i<maxChebyPoly+1;i++) {
+        psFree(chebPolys[i]);
+    }
+    psFree(chebPolys);
+    return(polySum);
+}
+
+static psF64 ordPolynomial4DEval(psF64 x,
+                                 psF64 y,
+                                 psF64 z,
+                                 psF64 t,
+                                 const psPolynomial4D* poly)
+{
+    unsigned int loop_x = 0;
+    unsigned int loop_y = 0;
+    unsigned int loop_z = 0;
+    unsigned int loop_t = 0;
+    psF64 polySum = 0.0;
+    psF64 xSum = 1.0;
+    psF64 ySum = 1.0;
+    psF64 zSum = 1.0;
+    psF64 tSum = 1.0;
+
+    for (loop_x = 0; loop_x < (1 + poly->nX); loop_x++) {
+        ySum = xSum;
+        for (loop_y = 0; loop_y < (1 + poly->nY); loop_y++) {
+            zSum = ySum;
+            for (loop_z = 0; loop_z < (1 + poly->nZ); loop_z++) {
+                tSum = zSum;
+                for (loop_t = 0; loop_t < (1 + poly->nT); loop_t++) {
+                    if (!(poly->coeffMask[loop_x][loop_y][loop_z][loop_t] & PS_POLY_MASK_SET)) {
+                        polySum += tSum * poly->coeff[loop_x][loop_y][loop_z][loop_t];
+                    }
+                    tSum *= t;
+                }
+                zSum *= z;
+            }
+            ySum *= y;
+        }
+        xSum *= x;
+    }
+
+    return(polySum);
+}
+
+static psF64 chebPolynomial4DEval(psF64 x,
+                                  psF64 y,
+                                  psF64 z,
+                                  psF64 t,
+                                  const psPolynomial4D* poly)
+{
+    PS_ASSERT_DOUBLE_WITHIN_RANGE(x, -1.0, 1.0, 0.0);
+    PS_ASSERT_DOUBLE_WITHIN_RANGE(y, -1.0, 1.0, 0.0);
+    PS_ASSERT_DOUBLE_WITHIN_RANGE(z, -1.0, 1.0, 0.0);
+    PS_ASSERT_DOUBLE_WITHIN_RANGE(t, -1.0, 1.0, 0.0);
+    unsigned int loop_x = 0;
+    unsigned int loop_y = 0;
+    unsigned int loop_z = 0;
+    unsigned int loop_t = 0;
+    unsigned int i = 0;
+    psF64 polySum = 0.0;
+    psPolynomial1D* *chebPolys = NULL;
+    unsigned int maxChebyPoly = 0;
+
+    // Determine how many Chebyshev polynomials
+    // are needed, then create them.
+    maxChebyPoly = poly->nX;
+    if (poly->nY > maxChebyPoly) {
+        maxChebyPoly = poly->nY;
+    }
+    if (poly->nZ > maxChebyPoly) {
+        maxChebyPoly = poly->nZ;
+    }
+    if (poly->nT > maxChebyPoly) {
+        maxChebyPoly = poly->nT;
+    }
+    // Add 1 since p_psCreateChebyshevPolys() takes nTerms, not nOrder.
+    chebPolys = p_psCreateChebyshevPolys(maxChebyPoly + 1);
+
+    for (loop_x = 0; loop_x < (1 + poly->nX); loop_x++) {
+        for (loop_y = 0; loop_y < (1 + poly->nY); loop_y++) {
+            for (loop_z = 0; loop_z < (1 + poly->nZ); loop_z++) {
+                for (loop_t = 0; loop_t < (1 + poly->nT); loop_t++) {
+                    if (!(poly->coeffMask[loop_x][loop_y][loop_z][loop_t] & PS_POLY_MASK_SET)) {
+                        polySum += poly->coeff[loop_x][loop_y][loop_z][loop_t] *
+                                   psPolynomial1DEval(chebPolys[loop_x], x) *
+                                   psPolynomial1DEval(chebPolys[loop_y], y) *
+                                   psPolynomial1DEval(chebPolys[loop_z], z) *
+                                   psPolynomial1DEval(chebPolys[loop_t], t);
+                    }
+                }
+            }
+        }
+    }
+
+    for (i=0;i<maxChebyPoly+1;i++) {
+        psFree(chebPolys[i]);
+    }
+    psFree(chebPolys);
+    return(polySum);
+}
+
+/*****************************************************************************/
+/*  FUNCTION IMPLEMENTATION - PUBLIC                                         */
+/*****************************************************************************/
+
+/*****************************************************************************
+    Evaluate a non-normalized Gaussian with the given mean and sigma at the
+    given coordianate.  Note that this is not a Gaussian deviate.  The
+    evaluated Gaussian is: \f[ exp(-\frac{(x-mean)^2}{2\sigma^2}) \f]
+ *****************************************************************************/
+float psGaussian(float x,
+                 float mean,
+                 float sigma,
+                 bool normal)
+{
+    psF32 tmp = 1.0;
+
+    psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__);
+
+    if (normal == true) {
+        tmp = 1.0 / sqrtf(2.0 * M_PI * (sigma * sigma));
+    }
+
+    psTrace("psLib.math", 4, "---- %s() end ----\n", __func__);
+    return(tmp * exp(-((x - mean) * (x - mean)) / (2.0 * sigma * sigma)));
+}
+
+/*****************************************************************************
+    This routine must allocate memory for the polynomial structures.
+ 
+    XXX: How do we check for an appropriate value for n?
+ *****************************************************************************/
+psPolynomial1D* psPolynomial1DAlloc(
+    psPolynomialType type,
+    unsigned int nX)
+{
+    PS_ASSERT_POLY_VALID_TYPE(type, NULL);
+
+    psU32 nOrder = nX;
+    psPolynomial1D *newPoly = (psPolynomial1D* ) psAlloc(sizeof(psPolynomial1D));
+    psMemSetDeallocator(newPoly, (psFreeFunc) polynomial1DFree);
+
+    newPoly->type = type;
+    newPoly->nX = nOrder;
+    newPoly->coeff = psAlloc((nOrder + 1) * sizeof(psF64));
+    newPoly->coeffErr = psAlloc((nOrder + 1) * sizeof(psF64));
+    newPoly->coeffMask = (psMaskType *)psAlloc((nOrder + 1) * sizeof(psMaskType));
+    for (psU32 i = 0; i < (nOrder + 1); i++) {
+        newPoly->coeff[i] = 0.0;
+        newPoly->coeffErr[i] = 0.0;
+        newPoly->coeffMask[i] = PS_POLY_MASK_NONE;
+    }
+
+    return(newPoly);
+}
+
+psPolynomial2D* psPolynomial2DAlloc(
+    psPolynomialType type,
+    unsigned int nX,
+    unsigned int nY)
+{
+    PS_ASSERT_POLY_VALID_TYPE(type, NULL);
+
+    unsigned int x = 0;
+    unsigned int y = 0;
+    psPolynomial2D* newPoly = NULL;
+
+    newPoly = (psPolynomial2D* ) psAlloc(sizeof(psPolynomial2D));
+    psMemSetDeallocator(newPoly, (psFreeFunc) polynomial2DFree);
+
+    newPoly->type = type;
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+
+    newPoly->coeff = psAlloc((1 + nX) * sizeof(psF64 *));
+    newPoly->coeffErr = psAlloc((1 + nX) * sizeof(psF64 *));
+    newPoly->coeffMask = (psMaskType **)psAlloc((1 + nX) * sizeof(psMaskType *));
+    for (x = 0; x < (1 + nX); x++) {
+        newPoly->coeff[x] = psAlloc((1 + nY) * sizeof(psF64));
+        newPoly->coeffErr[x] = psAlloc((1 + nY) * sizeof(psF64));
+        newPoly->coeffMask[x] = (psMaskType *)psAlloc((1 + nY) * sizeof(psMaskType));
+    }
+    for (x = 0; x < (1 + nX); x++) {
+        for (y = 0; y < (1 + nY); y++) {
+            newPoly->coeff[x][y] = 0.0;
+            newPoly->coeffErr[x][y] = 0.0;
+            newPoly->coeffMask[x][y] = PS_POLY_MASK_NONE;
+        }
+    }
+
+    return(newPoly);
+}
+
+// XXX add 1D, 3D, 4D versions
+bool psPolynomial2DRecycle(psPolynomial2D *poly,
+                           psPolynomialType type,
+                           unsigned int nX,
+                           unsigned int nY)
+{
+    PS_ASSERT_INT_NONNEGATIVE(nX, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(nY, NULL);
+
+    bool match = true;
+    match &= (poly->type == type);
+    match &= (poly->nX == type);
+    match &= (poly->nY == type);
+
+    if (!match) {
+        for (int i = 0; i < poly->nX + 1; i++) {
+            psFree (poly->coeff[i]);
+            psFree (poly->coeffErr[i]);
+            psFree (poly->coeffMask[i]);
+        }
+        psFree (poly->coeff);
+        psFree (poly->coeffErr);
+        psFree (poly->coeffMask);
+
+        poly->type = type;
+        poly->nX = nX;
+        poly->nY = nY;
+
+        poly->coeff = psAlloc((1 + nX) * sizeof(psF64 *));
+        poly->coeffErr = psAlloc((1 + nX) * sizeof(psF64 *));
+        poly->coeffMask = (psMaskType **)psAlloc((1 + nX) * sizeof(psMaskType *));
+        for (int i = 0; i < (1 + nX); i++) {
+            poly->coeff[i] = psAlloc((1 + nY) * sizeof(psF64));
+            poly->coeffErr[i] = psAlloc((1 + nY) * sizeof(psF64));
+            poly->coeffMask[i] = (psMaskType *)psAlloc((1 + nY) * sizeof(psMaskType));
+        }
+    }
+    for (int i = 0; i < (1 + nX); i++) {
+        for (int j = 0; j < (1 + nY); j++) {
+            poly->coeff[i][j] = 0.0;
+            poly->coeffErr[i][j] = 0.0;
+            poly->coeffMask[i][j] = PS_POLY_MASK_NONE;
+        }
+    }
+    return(true);
+}
+
+// XXX add 1D, 3D, 4D versions
+psPolynomial2D *psPolynomial2DCopy(psPolynomial2D *out,
+                                   psPolynomial2D *poly)
+{
+    if (out == NULL) {
+        out = psPolynomial2DAlloc (poly->type, poly->nX, poly->nY);
+    } else {
+        psPolynomial2DRecycle (out, poly->type, poly->nX, poly->nY);
+    }
+
+    for (int i = 0; i < (1 + poly->nX); i++) {
+        for (int j = 0; j < (1 + poly->nY); j++) {
+            out->coeff[i][j] = poly->coeff[i][j];
+            out->coeffErr[i][j] = poly->coeffErr[i][j];
+            out->coeffMask[i][j] = poly->coeffMask[i][j];
+        }
+    }
+    return(out);
+}
+
+psPolynomial3D* psPolynomial3DAlloc(
+    psPolynomialType type,
+    unsigned int nX,
+    unsigned int nY,
+    unsigned int nZ)
+{
+    PS_ASSERT_POLY_VALID_TYPE(type, NULL);
+
+    //PS_ASSERT_INT_NONNEGATIVE(nX, NULL);
+    //PS_ASSERT_INT_NONNEGATIVE(nY, NULL);
+    //PS_ASSERT_INT_NONNEGATIVE(nZ, NULL);
+
+    unsigned int x = 0;
+    unsigned int y = 0;
+    unsigned int z = 0;
+    psPolynomial3D* newPoly = NULL;
+
+    newPoly = (psPolynomial3D* ) psAlloc(sizeof(psPolynomial3D));
+    psMemSetDeallocator(newPoly, (psFreeFunc) polynomial3DFree);
+
+    newPoly->type = type;
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+    newPoly->nZ = nZ;
+
+    newPoly->coeff = psAlloc((nX + 1) * sizeof(psF64 **));
+    newPoly->coeffErr = psAlloc((nX + 1) * sizeof(psF64 **));
+    newPoly->coeffMask = (psMaskType ***)psAlloc((nX + 1) * sizeof(psMaskType **));
+    for (x = 0; x < (1 + nX); x++) {
+        newPoly->coeff[x] = psAlloc((nY + 1) * sizeof(psF64 *));
+        newPoly->coeffErr[x] = psAlloc((nY + 1) * sizeof(psF64 *));
+        newPoly->coeffMask[x] = (psMaskType **)psAlloc((nY + 1) * sizeof(psMaskType *));
+        for (y = 0; y < (nY + 1); y++) {
+            newPoly->coeff[x][y] = psAlloc((nZ + 1) * sizeof(psF64));
+            newPoly->coeffErr[x][y] = psAlloc((nZ + 1) * sizeof(psF64));
+            newPoly->coeffMask[x][y] = (psMaskType *)psAlloc((nZ + 1) * sizeof(psMaskType));
+        }
+    }
+    for (x = 0; x < (nX + 1); x++) {
+        for (y = 0; y < (nY + 1); y++) {
+            for (z = 0; z < (nZ + 1); z++) {
+                newPoly->coeff[x][y][z] = 0.0;
+                newPoly->coeffErr[x][y][z] = 0.0;
+                newPoly->coeffMask[x][y][z] = PS_POLY_MASK_NONE;
+            }
+        }
+    }
+
+    return(newPoly);
+}
+
+psPolynomial4D* psPolynomial4DAlloc(
+    psPolynomialType type,
+    unsigned int nX,
+    unsigned int nY,
+    unsigned int nZ,
+    unsigned int nT)
+{
+    PS_ASSERT_POLY_VALID_TYPE(type, NULL);
+
+    //PS_ASSERT_INT_NONNEGATIVE(nX, NULL);
+    //PS_ASSERT_INT_NONNEGATIVE(nY, NULL);
+    //PS_ASSERT_INT_NONNEGATIVE(nZ, NULL);
+    //PS_ASSERT_INT_NONNEGATIVE(nT, NULL);
+
+    unsigned int x = 0;
+    unsigned int y = 0;
+    unsigned int z = 0;
+    unsigned int t = 0;
+    psPolynomial4D* newPoly = NULL;
+
+    newPoly = (psPolynomial4D* ) psAlloc(sizeof(psPolynomial4D));
+    psMemSetDeallocator(newPoly, (psFreeFunc) polynomial4DFree);
+
+    newPoly->type = type;
+    newPoly->nX = nX;
+    newPoly->nY = nY;
+    newPoly->nZ = nZ;
+    newPoly->nT = nT;
+
+    newPoly->coeff = psAlloc((nX + 1) * sizeof(psF64 ***));
+    newPoly->coeffErr = psAlloc((nX + 1) * sizeof(psF64 ***));
+    newPoly->coeffMask = (psMaskType ****)psAlloc((nX + 1) * sizeof(psMaskType ***));
+    for (x = 0; x < (nX + 1); x++) {
+        newPoly->coeff[x] = psAlloc((nY + 1) * sizeof(psF64 **));
+        newPoly->coeffErr[x] = psAlloc((nY + 1) * sizeof(psF64 **));
+        newPoly->coeffMask[x] = (psMaskType ***)psAlloc((nY + 1) * sizeof(psMaskType **));
+        for (y = 0; y < (nY + 1); y++) {
+            newPoly->coeff[x][y] = psAlloc((nZ + 1) * sizeof(psF64 *));
+            newPoly->coeffErr[x][y] = psAlloc((nZ + 1) * sizeof(psF64 *));
+            newPoly->coeffMask[x][y] = (psMaskType **)psAlloc((nZ + 1) * sizeof(psMaskType *));
+            for (z = 0; z < (nZ + 1); z++) {
+                newPoly->coeff[x][y][z] = psAlloc((nT + 1) * sizeof(psF64));
+                newPoly->coeffErr[x][y][z] = psAlloc((nT + 1) * sizeof(psF64));
+                newPoly->coeffMask[x][y][z] = (psMaskType *)psAlloc((nT + 1) * sizeof(psMaskType));
+            }
+        }
+    }
+    for (x = 0; x < (nX + 1); x++) {
+        for (y = 0; y < (nY + 1); y++) {
+            for (z = 0; z < (nZ + 1); z++) {
+                for (t = 0; t < (nT + 1); t++) {
+                    newPoly->coeff[x][y][z][t] = 0.0;
+                    newPoly->coeffErr[x][y][z][t] = 0.0;
+                    newPoly->coeffMask[x][y][z][t] = PS_POLY_MASK_NONE;
+                }
+            }
+        }
+    }
+
+    return(newPoly);
+}
+
+psF64 psPolynomial1DEval(const psPolynomial1D* poly,
+                         psF64 x)
+{
+    PS_ASSERT_POLY_NON_NULL(poly, NAN);
+
+    if (poly->type == PS_POLYNOMIAL_ORD) {
+        return(ordPolynomial1DEval(x, poly));
+    } else if (poly->type == PS_POLYNOMIAL_CHEB) {
+        return(chebPolynomial1DEval(x, poly));
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("Unknown polynomial type 0x%x found.  Evaluation failed."),
+                poly->type);
+    }
+    return(NAN);
+}
+
+// this function must accept F32 and F64 input x vectors
+psVector *psPolynomial1DEvalVector(const psPolynomial1D *poly,
+                                   const psVector *x)
+{
+    PS_ASSERT_POLY_NON_NULL(poly, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(x, NULL);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, NULL);
+
+    psVector *tmp;
+
+    switch (x->type.type) {
+    case PS_TYPE_F64:
+        tmp = psVectorAlloc(x->n, PS_TYPE_F64);
+        for (unsigned int i=0;i<x->n;i++) {
+            tmp->data.F64[i] = psPolynomial1DEval(poly, x->data.F64[i]);
+        }
+        break;
+    case PS_TYPE_F32:
+        tmp = psVectorAlloc(x->n, PS_TYPE_F32);
+        for (unsigned int i=0;i<x->n;i++) {
+            tmp->data.F32[i] = psPolynomial1DEval(poly, x->data.F32[i]);
+        }
+        break;
+    default:
+        psError(PS_ERR_UNKNOWN, false, "invalid input data type.\n");
+        return (NULL);
+    }
+    return(tmp);
+}
+
+psF64 psPolynomial2DEval(const psPolynomial2D* poly,
+                         psF64 x,
+                         psF64 y)
+{
+    PS_ASSERT_POLY_NON_NULL(poly, NAN);
+
+    if (poly->type == PS_POLYNOMIAL_ORD) {
+        return(ordPolynomial2DEval(x, y, poly));
+    } else if (poly->type == PS_POLYNOMIAL_CHEB) {
+        return(chebPolynomial2DEval(x, y, poly));
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("Unknown polynomial type 0x%x found.  Evaluation failed."),
+                poly->type);
+    }
+    return(NAN);
+}
+
+// this function must support input data types of F32 and F64
+// all input vectors data types must match (all F32 or all F64)
+psVector *psPolynomial2DEvalVector(const psPolynomial2D *poly,
+                                   const psVector *x,
+                                   const psVector *y)
+
+{
+    PS_ASSERT_POLY_NON_NULL(poly, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(x, NULL);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL);
+
+    psVector *tmp;
+    unsigned int vecLen=x->n;
+
+    // Determine the length of the output vector to by the minimum of the x,y vectors
+    if (y->n < vecLen) {
+        vecLen = y->n;
+    }
+
+    switch (x->type.type) {
+    case PS_TYPE_F32:
+        if (y->type.type != x->type.type) {
+            psError(PS_ERR_UNKNOWN, true, "type mismatch in data vectors");
+            return (NULL);
+        }
+
+        // Create output vector to return
+        tmp = psVectorAlloc(vecLen, PS_TYPE_F32);
+
+        // Evaluate the polynomial at the specified points
+        for (unsigned int i=0; i<vecLen; i++) {
+            tmp->data.F32[i] = psPolynomial2DEval(poly,x->data.F32[i],y->data.F32[i]);
+        }
+        break;
+    case PS_TYPE_F64:
+        if (y->type.type != x->type.type) {
+            psError(PS_ERR_UNKNOWN, true, "type mismatch in data vectors");
+            return (NULL);
+        }
+
+        // Create output vector to return
+        tmp = psVectorAlloc(vecLen, PS_TYPE_F64);
+
+        // Evaluate the polynomial at the specified points
+        for (unsigned int i=0; i<vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial2DEval(poly,x->data.F64[i],y->data.F64[i]);
+        }
+        break;
+    default:
+        psError(PS_ERR_UNKNOWN, false, "invalid input data type.\n");
+        return (NULL);
+    }
+    // Return output vector
+    return(tmp);
+}
+
+psF64 psPolynomial3DEval(const psPolynomial3D* poly,
+                         psF64 x,
+                         psF64 y,
+                         psF64 z)
+{
+    PS_ASSERT_POLY_NON_NULL(poly, NAN);
+
+    if (poly->type == PS_POLYNOMIAL_ORD) {
+        return(ordPolynomial3DEval(x, y, z, poly));
+    } else if (poly->type == PS_POLYNOMIAL_CHEB) {
+        return(chebPolynomial3DEval(x, y, z, poly));
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("Unknown polynomial type 0x%x found.  Evaluation failed."),
+                poly->type);
+    }
+    return(NAN);
+}
+
+// XXX: The output of this routine is always psF64 while 1D and 2D are
+// dependent on the input vectors.
+psVector *psPolynomial3DEvalVector(
+    const psPolynomial3D *poly,
+    const psVector *x,
+    const psVector *y,
+    const psVector *z)
+{
+    PS_ASSERT_POLY_NON_NULL(poly, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(x, NULL);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(z, NULL);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(z, NULL);
+
+    psVector *tmp;
+    unsigned int vecLen=x->n;
+
+    // Determine the length of output vector from min of the input vectors
+    if (y->n < vecLen) {
+        vecLen = y->n;
+    }
+    if (z->n < vecLen) {
+        vecLen = z->n;
+    }
+
+    // Allocate output vector
+    tmp = psVectorAlloc(vecLen, PS_TYPE_F64);
+
+    // Evaluate polynomial
+    // XXX: Consult with IfA: is this how they want to handle multiple data types?
+    if ((x->type.type == PS_TYPE_F32) && (y->type.type == PS_TYPE_F32)
+            && (z->type.type == PS_TYPE_F32)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial3DEval(poly, x->data.F32[i],
+                                                  y->data.F32[i], z->data.F32[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F32) && (y->type.type == PS_TYPE_F32)
+               && (z->type.type == PS_TYPE_F64)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial3DEval(poly, x->data.F32[i],
+                                                  y->data.F32[i], z->data.F64[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F32) && (y->type.type == PS_TYPE_F64)
+               && (z->type.type == PS_TYPE_F32)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial3DEval(poly, x->data.F32[i],
+                                                  y->data.F64[i], z->data.F32[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F32) && (y->type.type == PS_TYPE_F64)
+               && (z->type.type == PS_TYPE_F64)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial3DEval(poly, x->data.F32[i],
+                                                  y->data.F64[i], z->data.F64[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F64) && (y->type.type == PS_TYPE_F32)
+               && (z->type.type == PS_TYPE_F32)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial3DEval(poly, x->data.F64[i],
+                                                  y->data.F32[i], z->data.F32[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F64) && (y->type.type == PS_TYPE_F32)
+               && (z->type.type == PS_TYPE_F64)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial3DEval(poly, x->data.F64[i],
+                                                  y->data.F32[i], z->data.F64[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F64) && (y->type.type == PS_TYPE_F64)
+               && (z->type.type == PS_TYPE_F32)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial3DEval(poly, x->data.F64[i],
+                                                  y->data.F64[i], z->data.F32[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F64) && (y->type.type == PS_TYPE_F64)
+               && (z->type.type == PS_TYPE_F64)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial3DEval(poly, x->data.F64[i],
+                                                  y->data.F64[i], z->data.F64[i]);
+        }
+    }
+
+
+    // Return output vector
+    return(tmp);
+}
+
+psF64 psPolynomial4DEval(
+    const psPolynomial4D* poly,
+    psF64 x,
+    psF64 y,
+    psF64 z,
+    psF64 t)
+{
+    PS_ASSERT_POLY_NON_NULL(poly, NAN);
+
+    if (poly->type == PS_POLYNOMIAL_ORD) {
+        return(ordPolynomial4DEval(x,y,z,t, poly));
+    } else if (poly->type == PS_POLYNOMIAL_CHEB) {
+        return(chebPolynomial4DEval(x,y,z,t, poly));
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("Unknown polynomial type 0x%x found.  Evaluation failed."),
+                poly->type);
+    }
+    return(NAN);
+}
+
+psVector *psPolynomial4DEvalVector(
+    const psPolynomial4D *poly,
+    const psVector *x,
+    const psVector *y,
+    const psVector *z,
+    const psVector *t)
+{
+    PS_ASSERT_POLY_NON_NULL(poly, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(x, NULL);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(z, NULL);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(z, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(t, NULL);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(t, NULL);
+
+    psVector *tmp;
+    unsigned int vecLen=x->n;
+
+    // Determine output vector size from min of input vectors
+    if (z->n < vecLen) {
+        vecLen = z->n;
+    }
+    if (y->n < vecLen) {
+        vecLen = y->n;
+    }
+    if (t->n < vecLen) {
+        vecLen = t->n;
+    }
+
+    // Allocoutput vector
+    tmp = psVectorAlloc(vecLen, PS_TYPE_F64);
+
+    // Evaluate polynomial
+    // XXX: Consult with IfA: is this how they want to handle multiple data types?
+    if ((x->type.type == PS_TYPE_F32) && (y->type.type == PS_TYPE_F32)
+            && (z->type.type == PS_TYPE_F32) && (t->type.type == PS_TYPE_F32)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial4DEval(poly, x->data.F32[i],
+                                                  y->data.F32[i], z->data.F32[i], t->data.F32[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F32) && (y->type.type == PS_TYPE_F32)
+               && (z->type.type == PS_TYPE_F32) && (t->type.type == PS_TYPE_F64)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial4DEval(poly, x->data.F32[i],
+                                                  y->data.F32[i], z->data.F32[i], t->data.F64[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F32) && (y->type.type == PS_TYPE_F32)
+               && (z->type.type == PS_TYPE_F64) && (t->type.type == PS_TYPE_F32)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial4DEval(poly, x->data.F32[i],
+                                                  y->data.F32[i], z->data.F64[i], t->data.F32[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F32) && (y->type.type == PS_TYPE_F32)
+               && (z->type.type == PS_TYPE_F64) && (t->type.type == PS_TYPE_F64)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial4DEval(poly, x->data.F32[i],
+                                                  y->data.F32[i], z->data.F64[i], t->data.F64[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F32) && (y->type.type == PS_TYPE_F64)
+               && (z->type.type == PS_TYPE_F32) && (t->type.type == PS_TYPE_F32)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial4DEval(poly, x->data.F32[i],
+                                                  y->data.F64[i], z->data.F32[i], t->data.F32[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F32) && (y->type.type == PS_TYPE_F64)
+               && (z->type.type == PS_TYPE_F32) && (t->type.type == PS_TYPE_F64)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial4DEval(poly, x->data.F32[i],
+                                                  y->data.F64[i], z->data.F32[i], t->data.F64[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F32) && (y->type.type == PS_TYPE_F64)
+               && (z->type.type == PS_TYPE_F64) && (t->type.type == PS_TYPE_F32)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial4DEval(poly, x->data.F32[i],
+                                                  y->data.F64[i], z->data.F64[i], t->data.F32[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F32) && (y->type.type == PS_TYPE_F64)
+               && (z->type.type == PS_TYPE_F64) && (t->type.type == PS_TYPE_F64)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial4DEval(poly, x->data.F32[i],
+                                                  y->data.F64[i], z->data.F64[i], t->data.F64[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F64) && (y->type.type == PS_TYPE_F32)
+               && (z->type.type == PS_TYPE_F32) && (t->type.type == PS_TYPE_F32)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial4DEval(poly, x->data.F64[i],
+                                                  y->data.F32[i], z->data.F32[i], t->data.F32[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F64) && (y->type.type == PS_TYPE_F32)
+               && (z->type.type == PS_TYPE_F32) && (t->type.type == PS_TYPE_F64)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial4DEval(poly, x->data.F64[i],
+                                                  y->data.F32[i], z->data.F32[i], t->data.F64[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F64) && (y->type.type == PS_TYPE_F32)
+               && (z->type.type == PS_TYPE_F64) && (t->type.type == PS_TYPE_F32)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial4DEval(poly, x->data.F64[i],
+                                                  y->data.F32[i], z->data.F64[i], t->data.F32[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F64) && (y->type.type == PS_TYPE_F32)
+               && (z->type.type == PS_TYPE_F64) && (t->type.type == PS_TYPE_F64)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial4DEval(poly, x->data.F64[i],
+                                                  y->data.F32[i], z->data.F64[i], t->data.F64[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F64) && (y->type.type == PS_TYPE_F64)
+               && (z->type.type == PS_TYPE_F32) && (t->type.type == PS_TYPE_F32)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial4DEval(poly, x->data.F64[i],
+                                                  y->data.F64[i], z->data.F32[i], t->data.F32[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F64) && (y->type.type == PS_TYPE_F64)
+               && (z->type.type == PS_TYPE_F32) && (t->type.type == PS_TYPE_F64)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial4DEval(poly, x->data.F64[i],
+                                                  y->data.F64[i], z->data.F32[i], t->data.F64[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F64) && (y->type.type == PS_TYPE_F64)
+               && (z->type.type == PS_TYPE_F64) && (t->type.type == PS_TYPE_F32)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial4DEval(poly, x->data.F64[i],
+                                                  y->data.F64[i], z->data.F64[i], t->data.F32[i]);
+        }
+    } else if ((x->type.type == PS_TYPE_F64) && (y->type.type == PS_TYPE_F64)
+               && (z->type.type == PS_TYPE_F64) && (t->type.type == PS_TYPE_F64)) {
+        for (unsigned int i = 0; i < vecLen; i++) {
+            tmp->data.F64[i] = psPolynomial4DEval(poly, x->data.F64[i],
+                                                  y->data.F64[i], z->data.F64[i],
+                                                  t->data.F64[i]);
+        }
+    }
+
+
+    // Evaluate polynomial
+    for (unsigned int i = 0; i < vecLen; i++) {
+        tmp->data.F64[i] = psPolynomial4DEval(poly,
+                                              x->data.F64[i],
+                                              y->data.F64[i],
+                                              z->data.F64[i],
+                                              t->data.F64[i]);
+    }
+
+    // Return output vector
+    return(tmp);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomial.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomial.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomial.h	(revision 22158)
@@ -0,0 +1,357 @@
+/* @file  psPolynomial.h
+ * @brief Standard Mathematical Functions.
+ *
+ * This file will hold the prototypes for procedures which allocate, free,
+ * and evaluate various polynomials.  Those polynomial structures are also
+ * defined here.
+ *
+ * @author GLG, MHPCC
+ *
+ * @version $Revision: 1.69 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-10-09 19:24:46 $
+ *
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_POLYNOMIAL_H
+#define PS_POLYNOMIAL_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <float.h>
+#include <math.h>
+
+#include "psVector.h"
+#include "psScalar.h"
+
+typedef enum {
+    PS_POLY_MASK_NONE = 0,
+    PS_POLY_MASK_SET  = 1, // the coefficient should not be used (implies MASK_FIT)
+    PS_POLY_MASK_FIT  = 2, // the coefficient should not be fitted 
+    PS_POLY_MASK_BOTH = 3, // the coefficient should not be fitted 
+} psPolynomialMaskValues;
+
+/** Evaluate a non-normalized Gaussian with the given mean and sigma at the
+ *  given coordianate.
+ *
+ *  Note that this is not a Gaussian deviate.  The evaluated Gaussian is:
+ *        \f[ exp(-\frac{(x-mean)^2}{2\sigma^2}) \f]
+ *
+ *  @return float      value on the gaussian curve given the input parameters
+ */
+float psGaussian(
+    float x,                           ///< Value at which to evaluate
+    float mean,                        ///< Mean for the Gaussian
+    float sigma,                       ///< Standard deviation for the Gaussian
+    bool normal                        ///< Indicates whether result should be normalized
+);
+
+/** Polynomial Type.
+ *
+ *  Enumeration for Polynomial types.
+ */
+typedef enum {
+    PS_POLYNOMIAL_ORD,                  ///< Ordinary Polynomial
+    PS_POLYNOMIAL_CHEB                  ///< Chebyshev Polynomial
+}
+psPolynomialType;
+
+/** One-dimensional polynomial */
+typedef struct
+{
+    psPolynomialType type;              ///< Polynomial type
+    unsigned int nX;                    ///< Polynomial order
+    psF64 *coeff;                       ///< Coefficients
+    psF64 *coeffErr;                    ///< Error in coefficients
+    psMaskType *coeffMask;		///< Coefficient mask
+}
+psPolynomial1D;
+
+/** Two-dimensional polynomial */
+typedef struct
+{
+    psPolynomialType type;              ///< Polynomial type
+    unsigned int nX;            ///< Polynomial order in x
+    unsigned int nY;            ///< Polynomial order in y
+    psF64 **coeff;                      ///< Coefficients
+    psF64 **coeffErr;                   ///< Error in coefficients
+    psMaskType **coeffMask;                  ///< Coefficients mask
+}
+psPolynomial2D;
+
+/** Three-dimensional polynomial */
+typedef struct
+{
+    psPolynomialType type;              ///< Polynomial type
+    unsigned int nX;            ///< Polynomial order in x
+    unsigned int nY;            ///< Polynomial order in y
+    unsigned int nZ;            ///< Polynomial order in z
+    psF64 ***coeff;                     ///< Coefficients
+    psF64 ***coeffErr;                  ///< Error in coefficients
+    psMaskType ***coeffMask;                 ///< Coefficients mask
+}
+psPolynomial3D;
+
+/** Four-dimensional polynomial */
+typedef struct
+{
+    psPolynomialType type;              ///< Polynomial type
+    unsigned int nX;			///< Polynomial order in x
+    unsigned int nY;			///< Polynomial order in y
+    unsigned int nZ;			///< Polynomial order in z
+    unsigned int nT;			///< Polynomial order in t
+    psF64 ****coeff;                    ///< Coefficients
+    psF64 ****coeffErr;                 ///< Error in coefficients
+    psMaskType ****coeffMask;		///< Coefficients mask
+}
+psPolynomial4D;
+
+
+/** Allocates a psPolynomial1D structure with n terms
+ *
+ *  @return  psPolynomial1D*    new 1-D polynomial struct
+ */
+psPolynomial1D* psPolynomial1DAlloc(
+    psPolynomialType type,             ///< Polynomial Type
+    unsigned int nX                    ///< Number of terms
+) PS_ATTR_MALLOC;
+
+/** Allocates a 2-D polynomial structure
+ *
+ *  @return  psPolynomial2D*    new 2-D polynomial struct
+ */
+psPolynomial2D* psPolynomial2DAlloc(
+    psPolynomialType type,             ///< Polynomial Type
+    unsigned int nX,                   ///< Number of terms in x
+    unsigned int nY                    ///< Number of terms in y
+) PS_ATTR_MALLOC;
+
+/** Allocates a 3-D polynomial structure
+ *
+ *  @return  psPolynomial3D*    new 3-D polynomial struct
+ */
+psPolynomial3D* psPolynomial3DAlloc(
+    psPolynomialType type,             ///< Polynomial Type
+    unsigned int nX,                   ///< Number of terms in x
+    unsigned int nY,                   ///< Number of terms in y
+    unsigned int nZ                    ///< Number of terms in z
+) PS_ATTR_MALLOC;
+
+/** Allocates a 4-D polynomial structure
+ *
+ *  @return  psPolynomial4D*    new 4-D polynomial struct
+ */
+psPolynomial4D* psPolynomial4DAlloc(
+    psPolynomialType type,             ///< Polynomial Type
+    unsigned int nX,                   ///< Number of terms in x
+    unsigned int nY,                   ///< Number of terms in y
+    unsigned int nZ,                   ///< Number of terms in z
+    unsigned int nT                    ///< Number of terms in t
+) PS_ATTR_MALLOC;
+
+bool psPolynomial2DRecycle(psPolynomial2D *poly,
+                           psPolynomialType type,
+                           unsigned int nX,
+                           unsigned int nY);
+
+psPolynomial2D *psPolynomial2DCopy(psPolynomial2D *out,
+                                   psPolynomial2D *poly);
+
+/** Evaluates a 1-D polynomial at specific coordinates.
+ *
+ *  @return psF64    result of polynomial at given location
+ */
+psF64 psPolynomial1DEval(
+    const psPolynomial1D* poly,        ///< Coefficients for the polynomial
+    psF64 x                            ///< location at which to evaluate
+);
+
+/** Evaluates a 2-D polynomial at specific coordinates.
+ *
+ *  @return psF64    result of polynomial at given location
+ */
+psF64 psPolynomial2DEval(
+    const psPolynomial2D* poly,        ///< Coefficients for the polynomial
+    psF64 x,                           ///< x location at which to evaluate
+    psF64 y                            ///< y location at which to evaluate
+);
+
+/** Evaluates a 3-D polynomial at specific coordinates.
+ *
+ *  @return psF64    result of polynomial at given location
+ */
+psF64 psPolynomial3DEval(
+    const psPolynomial3D* poly,        ///< Coefficients for the polynomial
+    psF64 x,                           ///< x location at which to evaluate
+    psF64 y,                           ///< y location at which to evaluate
+    psF64 z                            ///< z location at which to evaluate
+);
+
+/** Evaluates a 4-D polynomial at specific coordinates.
+ *
+ *  @return psF64    result of polynomial at given location
+ */
+psF64 psPolynomial4DEval(
+    const psPolynomial4D* poly,        ///< Coefficients for the polynomial
+    psF64 x,                           ///< x location at which to evaluate
+    psF64 y,                           ///< y location at which to evaluate
+    psF64 z,                           ///< z location at which to evaluate
+    psF64 t                            ///< t location at which to evaluate
+);
+
+/** Evaluates a 1-D polynomial at specific sets of coordinates
+ *
+ *  @return psVector*    results of polynomials at given locations
+ */
+psVector *psPolynomial1DEvalVector(
+    const psPolynomial1D *poly,        ///< Coefficients for the polynomial
+    const psVector *x                  ///< x locations at which to evaluate
+);
+
+/** Evaluates a 2-D polynomial at specific sets of coordinates
+ *
+ *  @return psVector*    results of polynomial at given locations
+ */
+psVector *psPolynomial2DEvalVector(
+    const psPolynomial2D *poly,        ///< Coefficients for the polynomial
+    const psVector *x,                 ///< x locations at which to evaluate
+    const psVector *y                  ///< y locations at which to evaluate
+);
+
+/** Evaluates a 3-D polynomial at specific sets of coordinates
+ *
+ *  @return psVector*    results of polynomial at given locations
+ */
+psVector *psPolynomial3DEvalVector(
+    const psPolynomial3D *poly,        ///< Coefficients for the polynomial
+    const psVector *x,                 ///< x locations at which to evaluate
+    const psVector *y,                 ///< y locations at which to evaluate
+    const psVector *z                  ///< z locations at which to evaluate
+);
+
+/** Evaluates a 4-D polynomial at specific sets of coordinates
+ *
+ *  @return psVector*    results of polynomial at given locations
+ */
+psVector *psPolynomial4DEvalVector(
+    const psPolynomial4D *poly,        ///< Coefficients for the polynomial
+    const psVector *x,                 ///< x locations at which to evaluate
+    const psVector *y,                 ///< y locations at which to evaluate
+    const psVector *z,                 ///< z locations at which to evaluate
+    const psVector *t                  ///< t locations at which to evaluate
+);
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psPolynomial1D structure, false otherwise.
+ */
+bool psMemCheckPolynomial1D(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psPolynomial2D structure, false otherwise.
+ */
+bool psMemCheckPolynomial2D(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psPolynomial3D structure, false otherwise.
+ */
+bool psMemCheckPolynomial3D(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psPolynomial4D structure, false otherwise.
+ */
+bool psMemCheckPolynomial4D(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+
+
+
+/** Creates the specified number of chebyshev polys.
+ *
+ *  @return psPolynomial1D** The chebyshev polys.
+ *
+ */
+psPolynomial1D **p_psCreateChebyshevPolys(
+    psS32 numPolys
+);
+
+typedef struct
+{
+    int n;                              ///< The number of Chebyshev polys.
+    psPolynomial1D **chebyPolys;        ///< THe chebyshev polys
+
+}
+p_chebyPolys;
+
+
+/*****************************************************************************
+    PS_POLY macros:
+*****************************************************************************/
+#define PS_ASSERT_POLY1D(NAME, RVAL) \
+if (false == psMemCheckPolynomial1D(NAME)) { \
+    psError(PS_ERR_BAD_PARAMETER_NULL, true, \
+            "Unallowable operation: argument %s is not a psPolynomial1D struct.\n",\
+            #NAME); \
+    return(RVAL); \
+} \
+
+#define PS_ASSERT_POLY_NON_NULL(NAME, RVAL) \
+if ((NAME) == NULL || (NAME)->coeff == NULL) { \
+    psError(PS_ERR_BAD_PARAMETER_NULL, true, \
+            "Unallowable operation: polynomial %s or its coeffs is NULL.", \
+            #NAME); \
+    return(RVAL); \
+} \
+
+#define PS_ASSERT_POLY_TYPE(NAME, TYPE, RVAL) \
+if ((NAME)->type != TYPE) { \
+    psError(PS_ERR_BAD_PARAMETER_TYPE, true, \
+            "Unallowable operation: polynomial %s has wrong type.", #NAME); \
+    return(RVAL); \
+} \
+
+#define PS_ASSERT_POLY_VALID_TYPE(TYPE, RVAL) \
+if ((TYPE != PS_POLYNOMIAL_ORD) && \
+        (TYPE != PS_POLYNOMIAL_CHEB)) { \
+    psError(PS_ERR_BAD_PARAMETER_TYPE, true, \
+            "Unallowable operation: invalid type %d for polynomial", TYPE); \
+    return(RVAL); \
+} \
+
+#define PS_POLY_PRINT_1D(NAME) \
+printf("Poly %s: (nX) is (%d)\n", #NAME, NAME->nX);\
+for (psS32 i = 0 ; i < NAME->nX+1 ; i++) {\
+    printf("%s->coeff[%d] is %f\n", #NAME, i, NAME->coeff[i]); \
+}\
+
+#define PS_POLY_PRINT_2D(NAME) \
+printf("Poly %s: (nX, nY) is (%d, %d)\n", #NAME, NAME->nX, NAME->nY);\
+for (psS32 i = 0 ; i < NAME->nX+1 ; i++) {\
+    for (psS32 j = 0 ; j < NAME->nY+1 ; j++) {\
+        printf("%s->coeff[%d][%d] is %f\n", #NAME, i, j, NAME->coeff[i][j]); \
+    }\
+}\
+
+/// @}
+#endif // #ifndef PS_POLYNOMIAL_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomialMD.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomialMD.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomialMD.c	(revision 22158)
@@ -0,0 +1,473 @@
+#include <stdio.h>
+#include <assert.h>
+#include <limits.h>
+
+#include "psMemory.h"
+#include "psVector.h"
+#include "psImage.h"
+#include "psPolynomial.h"
+#include "psArray.h"
+#include "psMatrix.h"
+#include "psError.h"
+#include "psAbort.h"
+#include "psAssert.h"
+#include "psTrace.h"
+
+#include "psPolynomialMD.h"
+
+
+//#define DEBUG
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Private (file-static) functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Destructor
+static void polynomialMDFree(psPolynomialMD *poly // Polynomial
+    )
+{
+    psFree(poly->orders);
+    psFree(poly->coeff);
+    return;
+}
+
+// Generate a least-squares matrix and vector
+// Note: only generates the diagonal and lower triangle of the matrix
+static void polynomialMDLeastSquares(const psPolynomialMD *poly, // Polynomial
+                                     psImage *matrix, // Least-squares matrix to fill out
+                                     psVector *vector, // Least-squares vector to fill out
+                                     const psVector *coords, // Coordinates
+                                     float value, // Value
+                                     float error, // Error
+                                     psVector *buffer // Buffer for evaluations
+    )
+{
+    int numTerms = vector->n;           // Number of terms
+    psAssert(matrix->numCols == numTerms && matrix->numRows == numTerms, "impossible");
+    psAssert(buffer && buffer->n == numTerms && buffer->type.type == PS_TYPE_F64, "impossible");
+
+#ifdef DEBUG
+    psImageInit(matrix, NAN);
+    psVectorInit(vector, NAN);
+#endif
+
+    buffer->data.F64[0] = 1.0;
+    for (int i = 0, index = 1; i < poly->dim; i++) {
+        int order = poly->orders->data.U8[i]; // Order of polynomial
+        float coord = coords->data.F32[i]; // Coordinate of interest
+        double value = coord;           // Value of polynomial stages
+        buffer->data.F64[index++] = value;
+        for (int j = 2; j <= order; j++, index++) {
+            value *= coord;
+            buffer->data.F64[index] = value;
+        }
+    }
+
+    double invSigma2 = (error == 0.0) ? 1.0 : 1.0 / PS_SQR(error); // 1/sigma^2
+    for (int i = 0; i < numTerms; i++) {
+        for (int j = 0; j < i; j++) {
+            matrix->data.F64[i][j] = buffer->data.F64[i] * buffer->data.F64[j] * invSigma2;
+        }
+        matrix->data.F64[i][i] = PS_SQR(buffer->data.F64[i]) * invSigma2;
+        vector->data.F64[i] = value * buffer->data.F64[i] * invSigma2;
+    }
+
+    return;
+}
+
+// Accumulate the lower triangle of the matrix
+static void polynomialMDAccumulate(psImage *targetMatrix, // Final least-squares matrix
+                                   psVector *targetVector, // Final least-squares vector
+                                   const psImage *sourceMatrix, // Input least-squares matrix
+                                   const psVector *sourceVector // Input least-squares vector
+    )
+{
+    int numTerms = targetVector->n;     // Number of terms in polynomial
+
+    for (int j = 0; j < numTerms; j++) {
+        for (int k = 0; k < j; k++) {
+            targetMatrix->data.F64[j][k] += sourceMatrix->data.F64[j][k];
+        }
+        targetMatrix->data.F64[j][j] += sourceMatrix->data.F64[j][j];
+        targetVector->data.F64[j] += sourceVector->data.F64[j];
+    }
+
+    return;
+}
+
+// Fill in the upper triangle of the matrix
+static void polynomialMDFill(psImage *matrix // Final least-squares matrix
+    )
+{
+    int numTerms = matrix->numCols;     // Number of terms in polynomial
+
+    for (int j = 0; j < numTerms; j++) {
+        for (int k = j + 1; k < numTerms; k++) {
+            matrix->data.F64[j][k] = matrix->data.F64[k][j];
+        }
+    }
+
+    return;
+}
+
+// Accumulate and solve the least-squares equation
+static bool polynomialMDClipFit(psPolynomialMD *poly, // Polynomial
+                                psImage *matrix, // Least-squares matrix
+                                psVector *vector, // Least-squares vector
+                                psImage **lu, // LU-decomposed matrix
+                                psVector **perm, // Permutations vector
+                                const psArray *matrices, // Individual least-squares matrices
+                                const psArray *vectors, // Individual least-squares vectors
+                                const psVector *mask // Mask for values
+    )
+{
+    int numValues = vectors->n;         // Number of values
+
+    // Accumulate the least-squares matrix and vector
+    psImageInit(matrix, 0.0);
+    psVectorInit(vector, 0.0);
+    for (int i = 0; i < numValues; i++) {
+        if (mask->data.U8[i]) {
+            continue;
+        }
+
+        psImage *newMatrix = matrices->data[i]; // Matrix to accumulate
+        psVector *newVector = vectors->data[i]; // Vector to accumulate
+
+        polynomialMDAccumulate(matrix, vector, newMatrix, newVector);
+    }
+    polynomialMDFill(matrix);
+
+    // Solve least-squares equation
+    *lu = psMatrixLUD(*lu, perm, matrix);
+    if (!*lu) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to LU-Decompose least-squares matrix.");
+        return false;
+    }
+    poly->coeff = psMatrixLUSolve(poly->coeff, *lu, vector, *perm);
+    if (!poly->coeff) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to solve least-squares equation.");
+        return false;
+    }
+    return true;
+}
+
+// Calculate the standard deviation of the fit
+static void polynomialMDStdev(psPolynomialMD *poly, // Polynomial for which to measure stdev
+                              psVector *deviations, // Deviations, or NULL
+                              const psArray *coords, // Array of coordinates
+                              const psVector *values, // Measured values
+                              const psVector *mask // Mask for values
+                              )
+{
+    psAssert(poly, "impossible");
+    psAssert(coords, "impossible");
+    psAssert(values, "impossible");
+
+    double rms = 0.0;                   // Root mean square deviation
+    int numValues = values->n;          // Number of values
+    int numGood = numValues;            // Number of good values
+    for (int i = 0; i < numValues; i++) {
+        if (mask && mask->data.U8[i]) {
+            numGood--;
+            continue;
+        }
+        float diff = values->data.F32[i] - psPolynomialMDEval(poly, coords->data[i]);
+        if (deviations) {
+            deviations->data.F32[i] = diff;
+        }
+        rms += PS_SQR(diff);
+    }
+    poly->stdevFit = sqrt(rms / (double)numGood);
+
+    return;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+psPolynomialMD *psPolynomialMDAlloc(const psVector *orders)
+{
+    psPolynomialMD *poly = psAlloc(sizeof(psPolynomialMD));
+    psMemSetDeallocator(poly, (psFreeFunc)polynomialMDFree);
+
+    int dim = orders->n;                // Number of dimensions
+
+        #define CHECK_ORDER_CASE_SIGNED(TYPE) \
+          case PS_TYPE_##TYPE: { \
+              for (int i = 0; i < dim; i++) { \
+                  if (orders->data.TYPE[i] <= 0) { \
+                      psAbort("Order %d is non-positive.", i); \
+                  } \
+              } \
+              break; \
+          }
+
+    switch (orders->type.type) {
+        CHECK_ORDER_CASE_SIGNED(S8);
+        CHECK_ORDER_CASE_SIGNED(S16);
+        CHECK_ORDER_CASE_SIGNED(S32);
+        CHECK_ORDER_CASE_SIGNED(S64);
+      case PS_TYPE_F32:
+      case PS_TYPE_F64:
+        psAbort("Floating-point order vector is not supported.");
+      case PS_TYPE_U8:
+      case PS_TYPE_U16:
+      case PS_TYPE_U32:
+      case PS_TYPE_U64:
+        // These can pass unchecked
+        break;
+      default:
+        psAbort("Unknown type: %x", orders->type.type);
+    }
+
+    poly->dim = dim;
+    poly->orders = psVectorCopy(NULL, orders, PS_TYPE_U8);
+    poly->numFit = 0;
+    poly->stdevFit = NAN;
+
+    int numTerms = 1;                   // Number of terms in polynomial
+    for (int i = 0; i < dim; i++) {
+        numTerms += poly->orders->data.U8[i];
+    }
+    poly->coeff = psVectorAlloc(numTerms, PS_TYPE_F64);
+
+    return poly;
+}
+
+double psPolynomialMDEval(const psPolynomialMD *poly, ///< Polynomial
+                          const psVector *coords ///< Coordinates
+    )
+{
+    PS_ASSERT_POLYNOMIALMD_NON_NULL(poly, NAN);
+    PS_ASSERT_VECTOR_NON_NULL(coords, NAN);
+    PS_ASSERT_VECTOR_SIZE(coords, (long)poly->dim, NAN);
+    PS_ASSERT_VECTOR_TYPE(coords, PS_TYPE_F32, NAN);
+
+    psVector *orders = poly->orders; // Orders for each polynomial
+    psF64 *coeff = poly->coeff->data.F64; // Coefficients
+
+    double sum = coeff[0];              // Sum of all polynomials
+    for (int i = 0, index = 1; i < poly->dim; i++) {
+        int order = orders->data.U8[i]; // Order of polynomial
+        float coord = coords->data.F32[i]; // Coordinate of interest
+        float value = coord; // Value of the polynomial stage
+        sum += coeff[index++] * value;
+        for (int j = 2; j <= order; j++, index++) {
+            value *= coord;
+            sum += coeff[index] * value;
+        }
+    }
+
+    return sum;
+}
+
+bool psPolynomialMDFit(psPolynomialMD *poly, const psVector *values, const psVector *errors,
+                       const psVector *mask, psMaskType maskVal, const psArray *coordsArray)
+{
+    PS_ASSERT_POLYNOMIALMD_NON_NULL(poly, false);
+    PS_ASSERT_VECTOR_NON_NULL(values, false);
+    PS_ASSERT_VECTOR_TYPE(values, PS_TYPE_F32, false);
+    if (errors) {
+        PS_ASSERT_VECTOR_NON_NULL(errors, false);
+        PS_ASSERT_VECTOR_TYPE(errors, PS_TYPE_F32, false);
+        PS_ASSERT_VECTORS_SIZE_EQUAL(values, errors, false);
+    }
+    if (maskVal == 0) {
+        mask = NULL;
+    }
+    if (mask) {
+        PS_ASSERT_VECTOR_NON_NULL(mask, false);
+        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_MASK, false);
+        PS_ASSERT_VECTORS_SIZE_EQUAL(values, mask, false);
+    }
+    PS_ASSERT_ARRAY_NON_NULL(coordsArray, false);
+    PS_ASSERT_ARRAY_SIZE(coordsArray, values->n, false);
+
+    int numValues = values->n;          // Number of values
+    int numTerms = poly->coeff->n;      // Number of terms
+    psImage *matrix = psImageAlloc(numTerms, numTerms, PS_TYPE_F64); // Least-squares matrix
+    psImageInit(matrix, 0.0);
+    psVector *vector = psVectorAlloc(numTerms, PS_TYPE_F64); // Least-squares vector
+    psVectorInit(vector, 0.0);
+
+    psImage *newMatrix = psImageAlloc(numTerms, numTerms, PS_TYPE_F64); // Least-squares matrix for each term
+    psVector *newVector = psVectorAlloc(numTerms, PS_TYPE_F64); // Least-squares vector for each term
+    psVector *buffer = psVectorAlloc(numTerms, PS_TYPE_F64); // Buffer for evaluations of polynomial stages
+
+    for (int i = 0; i < numValues; i++) {
+        psVector *coords = coordsArray->data[i];
+        PS_ASSERT_VECTOR_NON_NULL(coords, false);
+        PS_ASSERT_VECTORS_SIZE_EQUAL(coords, poly->orders, false);
+        PS_ASSERT_VECTOR_TYPE(coords, PS_TYPE_F32, false);
+
+        if (mask && (mask->data.PS_TYPE_MASK_DATA[i] & maskVal)) {
+            continue;
+        }
+
+        polynomialMDLeastSquares(poly, newMatrix, newVector, coords, values->data.F32[i],
+                                 errors ? errors->data.F32[i] : 0.0, buffer);
+        polynomialMDAccumulate(matrix, vector, newMatrix, newVector);
+    }
+    polynomialMDFill(matrix);
+
+    psFree(newMatrix);
+    psFree(newVector);
+    psFree(buffer);
+
+    psVector *perm = NULL;              // Permutation vector
+    psImage *lu = psMatrixLUD(NULL, &perm, matrix); // LU-decomposed matrix
+    psFree(matrix);
+    if (!lu) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to LU-Decompose least-squares matrix.");
+        psFree(vector);
+        return false;
+    }
+    poly->coeff = psMatrixLUSolve(poly->coeff, lu, vector, perm);
+    psFree(vector);
+    psFree(lu);
+    psFree(perm);
+    if (!poly->coeff) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to solve least-squares equation.");
+        return false;
+    }
+
+    polynomialMDStdev(poly, NULL, coordsArray, values, NULL);
+
+    return true;
+}
+
+bool psPolynomialMDClipFit(psPolynomialMD *poly, const psVector *values, const psVector *errors,
+                           const psVector *mask, psMaskType maskVal, const psArray *coordsArray,
+                           int numIter, float rej)
+{
+    PS_ASSERT_POLYNOMIALMD_NON_NULL(poly, false);
+    PS_ASSERT_VECTOR_NON_NULL(values, false);
+    PS_ASSERT_VECTOR_TYPE(values, PS_TYPE_F32, false);
+    if (errors) {
+        PS_ASSERT_VECTOR_NON_NULL(errors, false);
+        PS_ASSERT_VECTOR_TYPE(errors, PS_TYPE_F32, false);
+        PS_ASSERT_VECTORS_SIZE_EQUAL(values, errors, false);
+    }
+    if (maskVal == 0) {
+        mask = NULL;
+    }
+    if (mask) {
+        PS_ASSERT_VECTOR_NON_NULL(mask, false);
+        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_MASK, false);
+        PS_ASSERT_VECTORS_SIZE_EQUAL(values, mask, false);
+    }
+    PS_ASSERT_ARRAY_NON_NULL(coordsArray, false);
+    PS_ASSERT_ARRAY_SIZE(coordsArray, (long)values->n, false);
+    PS_ASSERT_INT_NONNEGATIVE(numIter, false);
+    PS_ASSERT_FLOAT_LARGER_THAN(rej, 0.0, false);
+
+    int numValues = values->n;          // Number of values
+    int numTerms = poly->coeff->n;      // Number of terms
+
+    psArray *matrices = psArrayAlloc(numValues); // Least-squares matrix for each input value
+    psArray *vectors = psArrayAlloc(numValues); // Least-squares vector for each input value
+
+    // Generate least-squares matrices and vectors
+    psVector *buffer = psVectorAlloc(numTerms, PS_TYPE_F64); // Buffer for evaluations of polynomial stages
+    for (int i = 0; i < numValues; i++) {
+        psVector *coords = coordsArray->data[i];
+        PS_ASSERT_VECTOR_NON_NULL(coords, false);
+        PS_ASSERT_VECTORS_SIZE_EQUAL(coords, poly->orders, false);
+        PS_ASSERT_VECTOR_TYPE(coords, PS_TYPE_F32, false);
+
+        if (mask && (mask->data.PS_TYPE_MASK_DATA[i] & maskVal)) {
+            continue;
+        }
+
+        matrices->data[i] = psImageAlloc(numTerms, numTerms, PS_TYPE_F64);
+        vectors->data[i] = psVectorAlloc(numTerms, PS_TYPE_F64);
+
+        polynomialMDLeastSquares(poly, matrices->data[i], vectors->data[i], coords, values->data.F32[i],
+                                 errors ? errors->data.F32[i] : 0.0, buffer);
+    }
+    psFree(buffer);
+
+    // Iterate over the solution
+    int numGood = numValues;            // Number of good values
+    psImage *matrix = psImageAlloc(numTerms, numTerms, PS_TYPE_F64); // Least-squares matrix
+    psVector *vector = psVectorAlloc(numTerms, PS_TYPE_F64); // Least-squares vector
+    psVector *ownMask = psVectorAlloc(numValues, PS_TYPE_U8); // Our own mask for input values
+    psVectorInit(ownMask, 0);
+    if (mask) {
+        for (int i = 0; i < numValues; i++) {
+            if (mask->data.PS_TYPE_MASK_DATA[i] & maskVal) {
+                ownMask->data.U8[i] = 0xff;
+                numGood--;
+            }
+        }
+    }
+    psImage *lu = NULL;                 // LU-decomposed matrix
+    psVector *perm = NULL;              // Permutation vector
+    psVector *deviations = psVectorAlloc(numValues, PS_TYPE_F32); // Deviations from fit
+    int numClipped = INT_MAX;           // Number of values clipped int an interation
+    for (int iter = 0; iter < numIter && numClipped > 0 && numGood > numTerms; iter++) {
+        numClipped = 0;
+
+        if (!polynomialMDClipFit(poly, matrix, vector, &lu, &perm, matrices, vectors, ownMask)) {
+            psFree(matrix);
+            psFree(vector);
+            psFree(lu);
+            psFree(perm);
+            psFree(matrices);
+            psFree(vectors);
+            psFree(ownMask);
+            psFree(deviations);
+            return false;
+        }
+
+        polynomialMDStdev(poly, deviations, coordsArray, values, ownMask);
+        psTrace("psLib.math", 7, "RMS from %d points is %lf\n", numGood, poly->stdevFit);
+
+        // Reject
+        float limit = rej * poly->stdevFit; // Rejection limit
+        for (int i = 0; i < numValues; i++) {
+            if (ownMask->data.U8[i]) {
+                continue;
+            }
+            if (fabs(deviations->data.F32[i]) > limit) {
+                psTrace("psLib.math", 9, "Rejected point %d (%f,%f: %f > %f)\n",
+                        i, values->data.F32[i], psPolynomialMDEval(poly, coordsArray->data[i]),
+                        deviations->data.F32[i], limit);
+                ownMask->data.U8[i] = 0xff;
+                numClipped++;
+                numGood--;
+            }
+        }
+        psTrace("psLib.math", 7, "Rejected %d points (%d remaining)\n", numClipped, numGood);
+    }
+
+    if (numClipped > 0) {
+        // Need to do a final re-evaluation of the fit
+        if (!polynomialMDClipFit(poly, matrix, vector, &lu, &perm, matrices, vectors, ownMask)) {
+            psFree(matrix);
+            psFree(vector);
+            psFree(lu);
+            psFree(perm);
+            psFree(matrices);
+            psFree(vectors);
+            psFree(ownMask);
+            psFree(deviations);
+            return false;
+        }
+        polynomialMDStdev(poly, NULL, coordsArray, values, ownMask);
+    }
+
+    psFree(matrix);
+    psFree(vector);
+    psFree(lu);
+    psFree(perm);
+    psFree(matrices);
+    psFree(vectors);
+    psFree(ownMask);
+    psFree(deviations);
+
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomialMD.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomialMD.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomialMD.h	(revision 22158)
@@ -0,0 +1,54 @@
+#ifndef PS_POLYNOMIAL_MD_H
+#define PS_POLYNOMIAL_MD_H
+
+#include <psVector.h>
+#include <psPolynomial.h>
+#include <psArray.h>
+
+/// Multi-dimensional polynomial
+typedef struct {
+    int dim;                            ///< Dimensions
+    psVector *orders;                   ///< Polynomial orders for each dimension
+    psVector *coeff;                    ///< Coefficients
+    int numFit;                         ///< Number of values in fit
+    float stdevFit;                     ///< Standard deviation of fit
+} psPolynomialMD;
+
+/// Assertion for valid polynomial
+#define PS_ASSERT_POLYNOMIALMD_NON_NULL(POLY, RETURN) \
+    if (!(POLY) || (POLY)->dim < 0 || !(POLY)->orders || (POLY)->orders->n != (POLY)->dim || \
+        !(POLY)->coeff) { \
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Invalid polynomial."); \
+        return RETURN; \
+    }
+
+/// Constructor
+psPolynomialMD *psPolynomialMDAlloc(const psVector *orders ///< Orders for each dimension
+    ) PS_ATTR_MALLOC;
+
+/// Evaluate a polynomial
+double psPolynomialMDEval(const psPolynomialMD *poly, ///< Polynomial
+                          const psVector *coords ///< Coordinates
+    );
+
+/// Fit a polynomial
+bool psPolynomialMDFit(psPolynomialMD *poly, ///< Polynomial to fit
+                       const psVector *values, ///< Values
+                       const psVector *errors, ///< Errors
+                       const psVector *mask, ///< Mask
+                       psMaskType maskVal, ///< Value to mask
+                       const psArray *coordsArray ///< Array of coordinates
+    );
+
+/// Fit a polynomial, with clipping
+bool psPolynomialMDClipFit(psPolynomialMD *poly, ///< Polynomial to fit
+                           const psVector *values, ///< Values
+                           const psVector *errors, ///< Errors
+                           const psVector *mask, ///< Mask
+                           psMaskType maskVal, ///< Value to mask
+                           const psArray *coordsArray, ///< Array of coordinates
+                           int numIter,    ///< Number of rejection iterations
+                           float rej    ///< Rejection limit, standard deviations
+    );
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomialMetadata.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomialMetadata.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomialMetadata.c	(revision 22158)
@@ -0,0 +1,545 @@
+/** @file  psPolyMetadata.c
+ *
+ *
+ *  @brief Contains metadata structures, enumerations and functions prototypes.
+ *
+ *  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
+ *  prototypes necessary creating psLib metadata APIs
+ *
+ *  @ingroup Metadata
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-05-05 00:09:04 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "psType.h"
+#include "psMemory.h"
+#include "psError.h"
+#include "psMetadata.h"
+#include "psString.h"
+
+#include "psAssert.h"
+
+psPolynomial1D *psPolynomial1DfromMetadata(const psMetadata *folder)
+{
+    PS_ASSERT_PTR_NON_NULL(folder, NULL);
+    bool status;
+    char keyword[80];
+
+    // get polynomial orders
+    int nXorder = psMetadataLookupS32 (&status, folder, "NORDER_X");
+    if (!status) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psPolynomial1D in metadata is missing NORDER_X");
+        return NULL;
+    }
+    // how many polynomial coeffs are expected?
+    int nElementsExpected = psMetadataLookupS32 (&status, folder, "NELEMENTS");
+    if (!status) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psPolynomial1D in metadata is missing NELEMENTS");
+        return NULL;
+    }
+
+    psPolynomial1D *poly = psPolynomial1DAlloc (PS_POLYNOMIAL_ORD, nXorder);
+
+    int nElements = 0;
+    for (int nx = 0; nx < poly->nX + 1; nx++) {
+        sprintf (keyword, "VAL_X%02d", nx);
+        poly->coeff[nx] = psMetadataLookupF64 (&status, folder, keyword);
+        if (!status) {
+            // an undefined component implies the component was masked
+            // this is symmetrical with the 1DtoMD function
+            poly->coeff[nx] = 0;
+            poly->coeffErr[nx] = 0;
+            poly->coeffMask[nx] = PS_POLY_MASK_SET;
+        } else {
+            poly->coeffMask[nx] = PS_POLY_MASK_NONE;
+            nElements ++;
+        }
+        sprintf (keyword, "ERR_X%02d", nx);
+        poly->coeffErr[nx] = psMetadataLookupF64 (&status, folder, keyword);
+    }
+    if (nElements != nElementsExpected) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psPolynomial1D in metadata does not have the correct number of coefficients: "
+                "%d found vs %d expected", nElements, nElementsExpected);
+        psFree(poly);
+        return NULL;
+    }
+    return (poly);
+}
+
+// XXX : these may need F64, or %g format for output
+bool psPolynomial1DtoMetadata(psMetadata *md,
+                              const psPolynomial1D *poly,
+                              const char *format,
+                              ...)
+{
+    PS_ASSERT_PTR_NON_NULL(md, false);
+    PS_ASSERT_PTR_NON_NULL(poly, false);
+    PS_ASSERT_PTR_NON_NULL(format, false);
+
+    //XXX:  Current implementation only supports ordinary polynomials.
+    if (poly->type != PS_POLYNOMIAL_ORD)
+        return false;
+
+    int Nbyte;
+    char tmp;
+    char *root;
+    va_list argp;
+
+    // skip past whitespace (output name should not include whitespace)
+    char *fmt = (char *) format;
+    while (isspace(*fmt)) fmt++;
+
+    va_start (argp, format);
+    Nbyte = vsnprintf (&tmp, 0, fmt, argp);
+    va_end (argp);
+
+    if (Nbyte <= 0) return false;
+
+    va_start (argp, format);
+    root = (char *) psAlloc (Nbyte + 1);
+    memset (root, 0, Nbyte + 1);
+    vsnprintf (root, Nbyte + 1, fmt, argp);
+    va_end (argp);
+
+    psMetadata *folder = psMetadataAlloc ();
+
+    // specify the polynomial orders
+    psMetadataAdd (folder, PS_LIST_TAIL, "NORDER_X", PS_DATA_S32, "number of x orders", poly->nX);
+
+    char namespace[80];
+    char namespace_err[80];
+    int nElements = 0;   // count the number of unmasked elements
+
+    // place polynomial entries on folder
+    for (int nx = 0; nx < poly->nX + 1; nx++) {
+        if (!(poly->coeffMask[nx] & PS_POLY_MASK_SET)) {
+            sprintf(namespace, "VAL_X%02d", nx);
+            sprintf(namespace_err, "ERR_X%02d", nx);
+            psMetadataAdd (folder, PS_LIST_TAIL, namespace, PS_DATA_F64,
+                           "polynomial coefficient", poly->coeff[nx]);
+            psMetadataAdd (folder, PS_LIST_TAIL, namespace_err, PS_DATA_F64,
+                           "polynomial coefficient error", poly->coeffErr[nx]);
+            nElements ++;
+        }
+    }
+    psMetadataAdd (folder, PS_LIST_TAIL, "NELEMENTS", PS_DATA_S32, "number of unmasked coeffs", nElements);
+    psMetadataAdd (md, PS_LIST_TAIL, root, PS_DATA_METADATA, "folder for 1D polynomial", folder);
+    psFree (root);
+    psFree(folder);
+    return true;
+}
+
+psPolynomial2D *psPolynomial2DfromMetadata(const psMetadata *folder)
+{
+    PS_ASSERT_PTR_NON_NULL(folder, NULL);
+    bool status;
+    char keyword[80];
+
+    // get polynomial orders
+    int nXorder = psMetadataLookupS32 (&status, folder, "NORDER_X");
+    if (!status) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psPolynomial2D in metadata is missing NORDER_X");
+        return NULL;
+    }
+    int nYorder = psMetadataLookupS32 (&status, folder, "NORDER_Y");
+    if (!status) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psPolynomial2D in metadata is missing NORDER_Y");
+        return NULL;
+    }
+    // how many polynomial coeffs are expected?
+    int nElementsExpected = psMetadataLookupS32 (&status, folder, "NELEMENTS");
+    if (!status) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psPolynomial2D in metadata is missing NELEMENTS");
+        return NULL;
+    }
+
+    psPolynomial2D *poly = psPolynomial2DAlloc (PS_POLYNOMIAL_ORD, nXorder, nYorder);
+
+    int nElements = 0;
+    for (int nx = 0; nx < poly->nX + 1; nx++) {
+        for (int ny = 0; ny < poly->nY + 1; ny++) {
+            sprintf (keyword, "VAL_X%02d_Y%02d", nx, ny);
+            poly->coeff[nx][ny] = psMetadataLookupF64 (&status, folder, keyword);
+            if (!status) {
+                // an undefined component implies the component was masked
+                // this is symmetrical with the 2DtoMD function
+                poly->coeff[nx][ny] = 0;
+                poly->coeffErr[nx][ny] = 0;
+                poly->coeffMask[nx][ny] = PS_POLY_MASK_SET;
+            } else {
+                poly->coeffMask[nx][ny] = PS_POLY_MASK_NONE;
+                nElements ++;
+            }
+            sprintf (keyword, "ERR_X%02d_Y%02d", nx, ny);
+            poly->coeffErr[nx][ny] = psMetadataLookupF64 (&status, folder, keyword);
+        }
+    }
+    if (nElements != nElementsExpected) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psPolynomial2D in metadata does not have the correct number of coefficients: "
+                "%d found vs %d expected", nElements, nElementsExpected);
+        psFree(poly);
+        return NULL;
+    }
+    return (poly);
+}
+
+// XXX : these may need F64, or %g format for output
+bool psPolynomial2DtoMetadata (psMetadata *md,
+                               const psPolynomial2D *poly,
+                               const char *format,
+                               ...)
+{
+    PS_ASSERT_PTR_NON_NULL(md, false);
+    PS_ASSERT_PTR_NON_NULL(poly, false);
+    PS_ASSERT_PTR_NON_NULL(format, false);
+
+    // XXX Current implementation only supports ordinary polynomials.
+    if (poly->type != PS_POLYNOMIAL_ORD)
+        return false;
+
+    int Nbyte;
+    char tmp;
+    char *root;
+    va_list argp;
+
+    // skip past whitespace (output name should not include whitespace)
+    char *fmt = (char *) format;
+    while (isspace(*fmt)) fmt++;
+
+    va_start (argp, format);
+    Nbyte = vsnprintf (&tmp, 0, fmt, argp);
+    va_end (argp);
+
+    if (Nbyte <= 0)
+        return false;
+
+    va_start (argp, format);
+    root = (char *) psAlloc (Nbyte + 1);
+    memset (root, 0, Nbyte + 1);
+    vsnprintf (root, Nbyte + 1, fmt, argp);
+    va_end (argp);
+
+    psMetadata *folder = psMetadataAlloc ();
+
+    // specify the polynomial orders
+    psMetadataAdd (folder, PS_LIST_TAIL, "NORDER_X", PS_DATA_S32, "number of x orders", poly->nX);
+    psMetadataAdd (folder, PS_LIST_TAIL, "NORDER_Y", PS_DATA_S32, "number of y orders", poly->nY);
+
+    char namespace[80];
+    char namespace_err[80];
+    int nElements = 0;   // count the number of unmasked elements
+
+    // place polynomial entries on folder
+    for (int nx = 0; nx < poly->nX + 1; nx++) {
+        for (int ny = 0; ny < poly->nY + 1; ny++) {
+            if (!(poly->coeffMask[nx][ny] & PS_POLY_MASK_SET)) {
+                sprintf(namespace, "VAL_X%02d_Y%02d", nx, ny);
+                sprintf(namespace_err, "ERR_X%02d_Y%02d", nx, ny);
+                psMetadataAdd (folder, PS_LIST_TAIL, namespace, PS_DATA_F64,
+                               "polynomial coefficient", poly->coeff[nx][ny]);
+                psMetadataAdd (folder, PS_LIST_TAIL, namespace_err, PS_DATA_F64,
+                               "polynomial coefficient error", poly->coeffErr[nx][ny]);
+                nElements ++;
+            }
+        }
+    }
+    psMetadataAdd (folder, PS_LIST_TAIL, "NELEMENTS", PS_DATA_S32, "number of unmasked coeffs", nElements);
+    psMetadataAdd (md, PS_LIST_TAIL, root, PS_DATA_METADATA, "folder for 2D polynomial", folder);
+    psFree (root);
+    psFree(folder);
+    return true;
+}
+
+psPolynomial3D *psPolynomial3DfromMetadata (const psMetadata *folder)
+{
+    PS_ASSERT_PTR_NON_NULL(folder, NULL);
+
+    bool status;
+    char keyword[80];
+
+    // get polynomial orders
+    int nXorder = psMetadataLookupS32 (&status, folder, "NORDER_X");
+    if (!status) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psPolynomial3D in metadata is missing NORDER_X");
+        return NULL;
+    }
+    int nYorder = psMetadataLookupS32 (&status, folder, "NORDER_Y");
+    if (!status) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psPolynomial3D in metadata is missing NORDER_Y");
+        return NULL;
+    }
+    int nZorder = psMetadataLookupS32 (&status, folder, "NORDER_Z");
+    if (!status) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psPolynomial3D in metadata is missing NORDER_Z");
+        return NULL;
+    }
+    // how many polynomial coeffs are expected?
+    int nElementsExpected = psMetadataLookupS32 (&status, folder, "NELEMENTS");
+    if (!status) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psPolynomial3D in metadata is missing NELEMENTS");
+        return NULL;
+    }
+
+    psPolynomial3D *poly = psPolynomial3DAlloc (PS_POLYNOMIAL_ORD, nXorder, nYorder, nZorder);
+
+    int nElements = 0;
+    for (int nx = 0; nx < poly->nX + 1; nx++) {
+        for (int ny = 0; ny < poly->nY + 1; ny++) {
+            for (int nz = 0; nz < poly->nZ + 1; nz++) {
+                sprintf (keyword, "VAL_X%02d_Y%02d_Z%02d", nx, ny, nz);
+                poly->coeff[nx][ny][nz] = psMetadataLookupF64 (&status, folder, keyword);
+                if (!status) {
+                    // an undefined component implies the component was masked
+                    // this is symmetrical with the 3DtoMD function
+                    poly->coeff[nx][ny][nz] = 0;
+                    poly->coeffErr[nx][ny][nz] = 0;
+                    poly->coeffMask[nx][ny][nz] = PS_POLY_MASK_SET;
+                } else {
+                    poly->coeffMask[nx][ny][nz] = PS_POLY_MASK_NONE;
+                    nElements ++;
+                }
+                sprintf (keyword, "ERR_X%02d_Y%02d_Z%02d", nx, ny, nz);
+                poly->coeffErr[nx][ny][nz] = psMetadataLookupF64 (&status, folder, keyword);
+            }
+        }
+    }
+    if (nElements != nElementsExpected) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psPolynomial3D in metadata does not have the correct number of coefficients: "
+                "%d found vs %d expected", nElements, nElementsExpected);
+        psFree(poly);
+        return NULL;
+    }
+    return (poly);
+}
+
+bool psPolynomial3DtoMetadata (psMetadata *md,
+                               const psPolynomial3D *poly,
+                               const char *format,
+                               ...)
+{
+    PS_ASSERT_PTR_NON_NULL(md, false);
+    PS_ASSERT_PTR_NON_NULL(poly, false);
+    PS_ASSERT_PTR_NON_NULL(format, false);
+
+    //XXX:  Current implementation only supports ordinary polynomials.
+    if (poly->type != PS_POLYNOMIAL_ORD)
+        return false;
+
+    int Nbyte;
+    char tmp;
+    char *root;
+    va_list argp;
+
+    // skip past whitespace (output name should not include whitespace)
+    char *fmt = (char *) format;
+    while (isspace(*fmt)) fmt++;
+
+    va_start (argp, format);
+    Nbyte = vsnprintf (&tmp, 0, fmt, argp);
+    va_end (argp);
+
+    if (Nbyte <= 0)
+        return false;
+
+    va_start (argp, format);
+    root = (char *) psAlloc (Nbyte + 1);
+    memset (root, 0, Nbyte + 1);
+    vsnprintf (root, Nbyte + 1, fmt, argp);
+    va_end (argp);
+
+    psMetadata *folder = psMetadataAlloc ();
+
+    // specify the polynomial orders
+    psMetadataAdd (folder, PS_LIST_TAIL, "NORDER_X", PS_DATA_S32, "number of x orders", poly->nX);
+    psMetadataAdd (folder, PS_LIST_TAIL, "NORDER_Y", PS_DATA_S32, "number of y orders", poly->nY);
+    psMetadataAdd (folder, PS_LIST_TAIL, "NORDER_Z", PS_DATA_S32, "number of z orders", poly->nZ);
+
+    char namespace[80];
+    char namespace_err[80];
+    int nElements = 0;   // count the number of unmasked elements
+
+    // place polynomial entries on folder
+    for (int nx = 0; nx < poly->nX + 1; nx++) {
+        for (int ny = 0; ny < poly->nY + 1; ny++) {
+            for (int nz = 0; nz < poly->nZ + 1; nz++) {
+                if (!(poly->coeffMask[nx][ny][nz] & PS_POLY_MASK_SET)) {
+                    sprintf(namespace, "VAL_X%02d_Y%02d_Z%02d", nx, ny, nz);
+                    sprintf(namespace_err, "ERR_X%02d_Y%02d_Z%02d", nx, ny, nz);
+                    psMetadataAdd (folder, PS_LIST_TAIL, namespace,
+                                   PS_DATA_F64, "polynomial coefficient",
+                                   poly->coeff[nx][ny][nz], nx, ny, nz);
+                    psMetadataAdd (folder, PS_LIST_TAIL, namespace_err,
+                                   PS_DATA_F64, "polynomial coeffficient error",
+                                   poly->coeffErr[nx][ny][nz], nx, ny, nz);
+                    nElements ++;
+                }
+            }
+        }
+    }
+    psMetadataAdd (folder, PS_LIST_TAIL, "NELEMENTS", PS_DATA_S32, "number of unmasked coeffs", nElements);
+    psMetadataAdd (md, PS_LIST_TAIL, root, PS_DATA_METADATA, "folder for 3D polynomial", folder);
+    psFree(root);
+    psFree(folder);
+    return true;
+}
+
+psPolynomial4D *psPolynomial4DfromMetadata(const psMetadata *folder)
+{
+    PS_ASSERT_PTR_NON_NULL(folder, NULL);
+
+    bool status;
+    char keyword[80];
+
+    int nXorder = psMetadataLookupS32 (&status, folder, "NORDER_X");
+    if (!status) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psPolynomial4D in metadata is missing NORDER_X");
+        return NULL;
+    }
+    int nYorder = psMetadataLookupS32 (&status, folder, "NORDER_Y");
+    if (!status) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psPolynomial4D in metadata is missing NORDER_Y");
+        return NULL;
+    }
+    int nZorder = psMetadataLookupS32 (&status, folder, "NORDER_Z");
+    if (!status) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psPolynomial4D in metadata is missing NORDER_Z");
+        return NULL;
+    }
+    int nTorder = psMetadataLookupS32 (&status, folder, "NORDER_T");
+    if (!status) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psPolynomial4D in metadata is missing NORDER_T");
+        return NULL;
+    }
+    // how many polynomial coeffs are expected?
+    int nElementsExpected = psMetadataLookupS32 (&status, folder, "NELEMENTS");
+    if (!status) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psPolynomial4D in metadata is missing NELEMENTS");
+        return NULL;
+    }
+
+    psPolynomial4D *poly = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, nXorder, nYorder, nZorder, nTorder);
+
+    int nElements = 0;
+    for (int nx = 0; nx < poly->nX + 1; nx++) {
+        for (int ny = 0; ny < poly->nY + 1; ny++) {
+            for (int nz = 0; nz < poly->nZ + 1; nz++) {
+                for (int nt = 0; nt < poly->nT + 1; nt++) {
+                    sprintf (keyword, "VAL_X%02d_Y%02d_Z%02d_T%02d", nx, ny, nz, nt);
+                    poly->coeff[nx][ny][nz][nt] = psMetadataLookupF64 (&status, folder, keyword);
+                    if (!status) {
+                        // an undefined component implies the component was masked
+                        // this is symmetrical with the 4DtoMD function
+                        poly->coeff[nx][ny][nz][nt] = 0;
+                        poly->coeffErr[nx][ny][nz][nt] = 0;
+                        poly->coeffMask[nx][ny][nz][nt] = PS_POLY_MASK_SET;
+                    } else {
+                        poly->coeffMask[nx][ny][nz][nt] = PS_POLY_MASK_NONE;
+                        nElements ++;
+                    }
+                    sprintf (keyword, "ERR_X%02d_Y%02d_Z%02d_T%02d", nx, ny, nz, nt);
+                    poly->coeffErr[nx][ny][nz][nt] = psMetadataLookupF64 (&status, folder, keyword);
+                }
+            }
+        }
+    }
+    if (nElements != nElementsExpected) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psPolynomial4D in metadata does not have the correct number of coefficients: "
+                "%d found vs %d expected", nElements, nElementsExpected);
+        psFree(poly);
+        return NULL;
+    }
+    return (poly);
+}
+
+bool psPolynomial4DtoMetadata (psMetadata *md,
+                               const psPolynomial4D *poly,
+                               const char *format,
+                               ...)
+{
+    PS_ASSERT_PTR_NON_NULL(md, false);
+    PS_ASSERT_PTR_NON_NULL(poly, false);
+    PS_ASSERT_PTR_NON_NULL(format, false);
+
+    //XXX:  Current implementation only supports ordinary polynomials.
+    if (poly->type != PS_POLYNOMIAL_ORD)
+        return false;
+
+    int Nbyte;
+    char tmp;
+    char *root;
+    va_list argp;
+
+    // skip past whitespace (output name should not include whitespace)
+    char *fmt = (char *) format;
+    while (isspace(*fmt)) fmt++;
+
+    va_start (argp, format);
+    Nbyte = vsnprintf (&tmp, 0, fmt, argp);
+    va_end (argp);
+
+    if (Nbyte <= 0)
+        return false;
+
+    va_start (argp, format);
+    root = (char *) psAlloc (Nbyte + 1);
+    memset (root, 0, Nbyte + 1);
+    vsnprintf (root, Nbyte + 1, fmt, argp);
+    va_end (argp);
+
+    psMetadata *folder = psMetadataAlloc ();
+
+    // specify the polynomial orders
+    psMetadataAdd (folder, PS_LIST_TAIL, "NORDER_X", PS_DATA_S32, "number of x orders", poly->nX);
+    psMetadataAdd (folder, PS_LIST_TAIL, "NORDER_Y", PS_DATA_S32, "number of y orders", poly->nY);
+    psMetadataAdd (folder, PS_LIST_TAIL, "NORDER_Z", PS_DATA_S32, "number of z orders", poly->nZ);
+    psMetadataAdd (folder, PS_LIST_TAIL, "NORDER_T", PS_DATA_S32, "number of t orders", poly->nT);
+
+    char namespace[80];
+    char namespace_err[80];
+    int nElements = 0;   // count the number of unmasked elements
+
+    // place polynomial entries on folder
+    for (int nx = 0; nx < poly->nX + 1; nx++) {
+        for (int ny = 0; ny < poly->nY + 1; ny++) {
+            for (int nz = 0; nz < poly->nZ + 1; nz++) {
+                for (int nt = 0; nt < poly->nT + 1; nt++) {
+                    if (!(poly->coeffMask[nx][ny][nz][nt] & PS_POLY_MASK_SET)) {
+                        sprintf(namespace, "VAL_X%02d_Y%02d_Z%02d_T%02d", nx, ny, nz, nt);
+                        sprintf(namespace_err, "ERR_X%02d_Y%02d_Z%02d_T%02d", nx, ny, nz, nt);
+                        psMetadataAdd (folder, PS_LIST_TAIL, namespace,
+                                       PS_DATA_F64, "polynomial coefficient",
+                                       poly->coeff[nx][ny][nz][nt], nx, ny, nz, nt);
+                        psMetadataAdd (folder, PS_LIST_TAIL, namespace_err,
+                                       PS_DATA_F64, "polynomial coeffficient error",
+                                       poly->coeffErr[nx][ny][nz][nt], nx, ny, nz, nt);
+                        nElements ++;
+                    }
+                }
+            }
+        }
+    }
+    psMetadataAdd (folder, PS_LIST_TAIL, "NELEMENTS", PS_DATA_S32, "number of unmasked coeffs", nElements);
+    psMetadataAdd (md, PS_LIST_TAIL, root, PS_DATA_METADATA, "folder for 4D polynomial", folder);
+    psFree(root);
+    psFree(folder);
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomialMetadata.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomialMetadata.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomialMetadata.h	(revision 22158)
@@ -0,0 +1,157 @@
+/* @file  psPolyMetdata.h
+ * @brief Standard Mathematical Functions.
+ *
+ * This file will hold the prototypes for procedures which allocate, free,
+ * and evaluate various polynomials.  Those polynomial structures are also
+ * defined here.
+ *
+ * @author GLG, MHPCC
+ *
+ * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-08-09 01:40:07 $
+ *
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_POLYMETADATA_H
+#define PS_POLYMETADATA_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+/** Allocates a new psPolynomial1D structure with information from a psMetadata.
+ *
+ *  Parses a psMetadata container with psPolynomial1D information.  The first two
+ *  elements of the metadata folder specify the order of the x & y variables.  (ie,
+ *  NORDER_X, NORDER_Y).  The following elements are the values of the coefficients
+ *  and the coefficient errors.  (ie, VAL_X00_Y00, ERR_X00_Y00, etc.).  If the orders
+ *  or any coefficients are missing or have incorrect syntax, NULL is returned.
+ *
+ *  @return psPolynomial1D*:        Newly allocated psPolynomial1D from metadata.
+ */
+psPolynomial1D *psPolynomial1DfromMetadata(
+    const psMetadata *folder                 ///< folder containing the polynomial info.
+);
+
+/** Stores the information from a psPolynomial1D structure in a psMetadata container.
+ *
+ *  Creates a psMetadata folder with psPolynomial1D information.  The first two
+ *  elements of the metadata folder specify the order of the x & y variables.  (ie,
+ *  NORDER_X, NORDER_Y).  The following elements are the values of the coefficients
+ *  and the coefficient errors.  (ie, VAL_X00_Y00, ERR_X00_Y00, etc.).  The input
+ *  polynomial must be of ordinary type and have a valid name format.  False is also
+ *  returned if any inputs are NULL.  *If a particular mask element is non-zero, that
+ *  polynomial coefficient (and error) are skipped.
+ *
+ *  @return bool:       True if successful, otherwise false.
+ */
+bool psPolynomial1DtoMetadata(
+    psMetadata *md,                    ///< Metadata container for polynomial storage.
+    const psPolynomial1D *poly,        ///< Polynomial information to be stored.
+    const char *format,                ///< Name of polynomial folder.
+    ...                                ///< Arguments for name formatting.
+) PS_ATTR_FORMAT(printf,3,4);
+
+/** Allocates a new psPolynomial2D structure with information from a psMetadata.
+ *
+ *  Parses a psMetadata container with psPolynomial2D information.  The first two
+ *  elements of the metadata folder specify the order of the x & y variables.  (ie,
+ *  NORDER_X, NORDER_Y).  The following elements are the values of the coefficients
+ *  and the coefficient errors.  (ie, VAL_X00_Y00, ERR_X00_Y00, etc.).  If the orders
+ *  or any coefficients are missing or have incorrect syntax, NULL is returned.
+ *
+ *  @return psPolynomial2D*:        Newly allocated psPolynomial2D from metadata.
+ */
+psPolynomial2D *psPolynomial2DfromMetadata(
+    const psMetadata *folder                 ///< folder containing the polynomial info.
+);
+
+/** Stores the information from a psPolynomial2D structure in a psMetadata container.
+ *
+ *  Creates a psMetadata folder with psPolynomial2D information.  The first two
+ *  elements of the metadata folder specify the order of the x & y variables.  (ie,
+ *  NORDER_X, NORDER_Y).  The following elements are the values of the coefficients
+ *  and the coefficient errors.  (ie, VAL_X00_Y00, ERR_X00_Y00, etc.).  The input
+ *  polynomial must be of ordinary type and have a valid name format.  False is also
+ *  returned if any inputs are NULL.  *If a particular mask element is non-zero, that
+ *  polynomial coefficient (and error) are skipped.
+ *
+ *  @return bool:       True if successful, otherwise false.
+ */
+bool psPolynomial2DtoMetadata(
+    psMetadata *md,                    ///< Metadata container for polynomial storage.
+    const psPolynomial2D *poly,              ///< Polynomial information to be stored.
+    const char *format,                      ///< Name of polynomial folder.
+    ...                                ///< Arguments for name formatting.
+) PS_ATTR_FORMAT(printf,3,4);
+
+/** Allocates a new psPolynomial3D structure with information from a psMetadata.
+ *
+ *  Parses a psMetadata container with psPolynomial3D information.  The first three
+ *  elements of the metadata folder specify the order of the x, y, & z variables.  (ie,
+ *  NORDER_X, NORDER_Y, NORDER_Z).  The following elements are the values of the
+ *  coefficients and the coefficient errors.  (ie, VAL_X00_Y00_Z00, ERR_X00_Y00_Z00,
+ *  etc.).  If the orders or any coefficients are missing or have incorrect syntax,
+ *  NULL is returned.
+ *
+ *  @return psPolynomial3D*:        Newly allocated psPolynomial3D from metadata.
+ */
+psPolynomial3D *psPolynomial3DfromMetadata(
+    const psMetadata *folder                 ///< folder containing the polynomial info.
+);
+
+/** Stores the information from a psPolynomial3D structure in a psMetadata container.
+ *
+ *  Creates a psMetadata folder with psPolynomial3D information.  The first three
+ *  elements of the metadata folder specify the order of the x, y, & z variables.  (ie,
+ *  NORDER_X, NORDER_Y, NORDER_Z).  The following elements are the values of the
+ *  coefficients and the coefficient errors.  (ie, VAL_X00_Y00_Z00, ERR_X00_Y00_Z00,
+ *  etc.).  The input polynomial must be of ordinary type and have a valid name format.
+ *  False is also returned if any inputs are NULL.  *If a particular mask element is
+ *  non-zero, that polynomial coefficient (and error) are skipped.
+ *
+ *  @return bool:       True if successful, otherwise false.
+ */
+bool psPolynomial3DtoMetadata(
+    psMetadata *md,                    ///< Metadata container for polynomial storage.
+    const psPolynomial3D *poly,              ///< Polynomial information to be stored.
+    const char *format,                      ///< Name of polynomial folder.
+    ...                                ///< Arguments for name formatting.
+) PS_ATTR_FORMAT(printf, 3, 4);
+
+/** Allocates a new psPolynomial4D structure with information from a psMetadata.
+ *
+ *  Parses a psMetadata container with psPolynomial4D information.  The first four
+ *  elements of the metadata folder specify the order of the x, y, z, & t variables.
+ *  (ie, NORDER_X, NORDER_Y, NORDER_Z, NORDER_T).  The following elements are the
+ *  values of the coefficients and the coefficient errors.  (ie, VAL_X00_Y00_Z00_T00,
+ *  ERR_X00_Y00_Z00_T00, etc.).  If the orders or any coefficients are missing or
+ *  have incorrect syntax, NULL is returned.
+ *
+ *  @return psPolynomial4D*:        Newly allocated psPolynomial4D from metadata.
+ */
+psPolynomial4D *psPolynomial4DfromMetadata(
+    const psMetadata *folder                 ///< folder containing the polynomial info.
+);
+
+/** Stores the information from a psPolynomial4D structure in a psMetadata container.
+ *
+ *  Creates a psMetadata folder with psPolynomial4D information.  The first four
+ *  elements of the metadata folder specify the order of the x, y, z, & t variables.
+ *  (ie, NORDER_X, NORDER_Y, NORDER_Z, NORDER_T).  The following elements are the values
+ *  of the coefficients and the coefficient errors.  (ie, VAL_X00_Y00_Z00_T00,
+ *  ERR_X00_Y00_Z00_T00, etc.).  The input polynomial must be of ordinary type and have
+ *  a valid name format.  False is also returned if any inputs are NULL.  *If a particular
+ *  mask element is non-zero, that polynomial coefficient (and error) are skipped.
+ *
+ *  @return bool:       True if successful, otherwise false.
+ */
+bool psPolynomial4DtoMetadata(
+    psMetadata *md,                    ///< Metadata container for polynomial storage.
+    const psPolynomial4D *poly,              ///< Polynomial information to be stored.
+    const char *format,                      ///< Name of polynomial folder.
+    ...                                ///< Arguments for name formatting.
+) PS_ATTR_FORMAT(printf, 3, 4);
+
+/// @}
+#endif // #ifndef PS_POLYMETADATA_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomialUtils.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomialUtils.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomialUtils.c	(revision 22158)
@@ -0,0 +1,247 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include "psMemory.h"
+#include "psError.h"
+#include "psLogMsg.h"
+#include "psVector.h"
+#include "psImage.h"
+#include "psBinaryOp.h"
+#include "psStats.h"
+#include "psAssert.h"
+#include "psPolynomial.h"
+#include "psMinimizePolyFit.h"
+#include "psCoord.h"
+#include "psPolynomialUtils.h"
+
+bool psVectorChiClipFitPolynomial4D(
+    psPolynomial4D *poly,
+    psStats *stats,
+    const psVector *mask,
+    psMaskType maskValue,
+    const psVector *f,
+    const psVector *fErr,
+    const psVector *x,
+    const psVector *y,
+    const psVector *z,
+    const psVector *t)
+{
+    PS_ASSERT_POLY_NON_NULL(poly, NULL);
+    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);
+    PS_ASSERT_PTR_NON_NULL(stats, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(f, NULL);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);
+    if (mask != NULL) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
+        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
+    }
+    PS_ASSERT_VECTOR_NON_NULL(x, NULL);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(z, NULL);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(z, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(t, NULL);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, NULL);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(t, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(fErr, NULL);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(fErr, mask, NULL);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, NULL);
+
+    // clipping range defined by min and max and/or clipSigma
+    float minClipSigma;
+    float maxClipSigma;
+    if (isfinite(stats->max)) {
+        maxClipSigma = +fabs(stats->max);
+    } else {
+        maxClipSigma = +fabs(stats->clipSigma);
+    }
+    if (isfinite(stats->min)) {
+        minClipSigma = -fabs(stats->min);
+    } else {
+        minClipSigma = -fabs(stats->clipSigma);
+    }
+    psVector *fit   = NULL;
+    psVector *resid = psVectorAlloc (x->n, PS_TYPE_F64);
+
+    // eventual expansion: user supplies one of various stats option pairs,
+    // eg (SAMPLE_MEAN | SAMPLE_STDEV) and the correct pair is used to
+    // evaluate the clipping sigma
+    // for now, for the SAMPLE_MEDIAN and SAMPLE_STDEV to be used
+    stats->options |= (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
+
+    for (int N = 0; N < stats->clipIter; N++) {
+        int Nkeep = 0;
+
+        if (!psVectorFitPolynomial4D (poly, mask, maskValue, f, fErr, x, y, z, t)) {
+            psError(PS_ERR_UNKNOWN, true, "Could not fit a polynomial to the data.  Returning NULL.\n");
+            psFree (resid);
+            return false;
+        }
+
+        fit = psPolynomial4DEvalVector (poly, x, y, z, t);
+        if (fit == NULL) {
+            psError(PS_ERR_UNKNOWN, false, "Could not call psPolynomial4DEvalVector().  Returning NULL.\n");
+            psFree(resid);
+            return false;
+        }
+
+        resid = (psVector *) psBinaryOp (resid, (void *) f, "-", (void *) fit);
+
+        if (!psVectorStats (stats, resid, NULL, mask, maskValue)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to measure vector stats");
+            psFree (fit);
+            psFree (resid);
+            return false;
+        }
+        psTrace (__func__, 5, "resid stats: %f +/- %f\n", stats->sampleMedian, stats->sampleStdev);
+
+        // set mask if pts are not valid
+        // we are masking out any point which is out of range
+        // recovery is not allowed with this scheme
+        for (int i = 0; i < resid->n; i++) {
+            if ((mask != NULL) && (mask->data.U8[i] & maskValue)) {
+                continue;
+            }
+            float sigma = hypot (psVectorGet (fErr, i), stats->sampleStdev);
+            if (resid->data.F64[i] - stats->sampleMedian > sigma*maxClipSigma) {
+                if (mask != NULL) {
+                    mask->data.U8[i] |= 0x01;
+                }
+                continue;
+            }
+            if (resid->data.F64[i] - stats->sampleMedian < sigma*minClipSigma) {
+                if (mask != NULL) {
+                    mask->data.U8[i] |= 0x01;
+                }
+                continue;
+            }
+            Nkeep ++;
+        }
+
+        psTrace (__func__, 4, "keeping %d of %ld pts for fit\n", Nkeep, x->n);
+        stats->clippedNvalues = Nkeep;
+        psFree (fit);
+    }
+    // Free local temporary variables
+    psFree (resid);
+
+    return true;
+}
+
+// this function expects x,y in parent coords
+// XXX add a mask, fit only the valid pixels
+// XXX determine the errors, and propagate to the output of psImageBicubeMin
+psPolynomial2D *psImageBicubeFit(const psImage *image, int x, int y)
+{
+    PS_ASSERT_IMAGE_NON_NULL(image, NULL);
+
+    int ix = x - image->col0;
+    int iy = y - image->row0;
+
+    PS_ASSERT_INT_WITHIN_RANGE(ix, 1, image->numCols - 1, NULL);
+    PS_ASSERT_INT_WITHIN_RANGE(iy, 1, image->numRows - 1, NULL);
+
+    psF32 *Fm = &image->data.F32[iy - 1][ix];
+    psF32 *Fo = &image->data.F32[iy + 0][ix];
+    psF32 *Fp = &image->data.F32[iy + 1][ix];
+
+    double Fxm = Fm[-1] + Fo[-1] + Fp[-1];
+    double Fxp = Fm[+1] + Fo[+1] + Fp[+1];
+    double Fym = Fm[-1] + Fm[+0] + Fm[+1];
+    double Fyp = Fp[-1] + Fp[+0] + Fp[+1];
+    double Foo = Fym + Fyp + Fo[-1] + Fo[+0] + Fo[+1];
+
+    psPolynomial2D *poly = psPolynomial2DAlloc (PS_POLYNOMIAL_ORD, 2, 2);
+    poly->coeffMask[2][2] = PS_POLY_MASK_SET;
+    poly->coeffMask[1][2] = PS_POLY_MASK_SET;
+    poly->coeffMask[2][1] = PS_POLY_MASK_SET;
+
+    poly->coeff[0][0] = Foo*(5.0/9.0) - (Fxp + Fxm)/3.0 - (Fyp + Fym)/3.0 ;
+
+    poly->coeff[1][0] = (Fxp - Fxm)/6.0;
+    poly->coeff[0][1] = (Fyp - Fym)/6.0;
+
+    poly->coeff[2][0] = (Fxp + Fxm)/2.0 - Foo/3.0;
+    poly->coeff[0][2] = (Fyp + Fym)/2.0 - Foo/3.0;
+
+    poly->coeff[1][1] = (Fp[+1] + Fm[-1] - Fm[+1] - Fp[-1])/4.0;
+
+    return poly;
+}
+
+psPlane psImageBicubeMin(const psPolynomial2D *poly)
+{
+    psPlane min = { NAN, NAN, 0, 0 };   // Minimum value to return
+
+    PS_ASSERT_PTR_NON_NULL(poly, min);
+    PS_ASSERT_INT_EQUAL(poly->nX, 2, min);
+    PS_ASSERT_INT_EQUAL(poly->nY, 2, min);
+
+    double det = 4*poly->coeff[2][0]*poly->coeff[0][2] - PS_SQR(poly->coeff[1][1]); // Determinant
+    min.x = (poly->coeff[1][1]*poly->coeff[0][1] - 2*poly->coeff[0][2]*poly->coeff[1][0]) / det;
+    min.y = (poly->coeff[1][1]*poly->coeff[1][0] - 2*poly->coeff[2][0]*poly->coeff[0][1]) / det;
+
+    return min;
+}
+
+psPolynomial2D *psPolynomial2D_dX (psPolynomial2D *out, psPolynomial2D *poly)
+{
+    int nXout = poly->nX - 1;
+    int nYout = poly->nY;
+
+    if (out == poly) {
+        psError(PS_ERR_UNKNOWN, false, "cannot assign output to input polynomial");
+        return NULL;
+    }
+
+    if (poly->nX == 0)
+        return NULL;
+
+    if (out == NULL) {
+        out = psPolynomial2DAlloc (PS_POLYNOMIAL_ORD, nXout, nYout);
+    } else {
+        psPolynomial2DRecycle (out, poly->type, nXout, nYout);
+    }
+
+    for (int i = 0; i < nXout + 1; i++) {
+        for (int j = 0; j < nYout + 1; j++) {
+            out->coeffMask[i][j] = poly->coeffMask[i+1][j];
+            out->coeff[i][j] = poly->coeff[i+1][j] * (i+1);
+        }
+    }
+    return out;
+}
+
+psPolynomial2D *psPolynomial2D_dY (psPolynomial2D *out, psPolynomial2D *poly)
+{
+    int nXout = poly->nX;
+    int nYout = poly->nY - 1;
+
+    if (out == poly) {
+        psError(PS_ERR_UNKNOWN, false, "cannot assign output to input polynomial");
+        return NULL;
+    }
+
+    if (poly->nY == 0)
+        return NULL;
+
+    if (out == NULL) {
+        out = psPolynomial2DAlloc (PS_POLYNOMIAL_ORD, nXout, nYout);
+    } else {
+        psPolynomial2DRecycle (out, poly->type, nXout, nYout);
+    }
+
+    for (int i = 0; i < nXout + 1; i++) {
+        for (int j = 0; j < nYout + 1; j++) {
+            out->coeffMask[i][j] = poly->coeffMask[i][j+1];
+            out->coeff[i][j] = poly->coeff[i][j+1] * (j+1);
+        }
+    }
+    return out;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomialUtils.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomialUtils.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psPolynomialUtils.h	(revision 22158)
@@ -0,0 +1,47 @@
+/* @file  psPolynomialUtils.h
+ * @brief extra psPolynomial-related functions
+ *
+ * $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ * $Date: 2007-01-23 22:47:23 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_POLYNOMIAL_UTILS_H
+#define PS_POLYNOMIAL_UTILS_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+#include "psVector.h"
+#include "psImage.h"
+#include "psCoord.h"
+#include "psStats.h"
+#include "psPolynomial.h"
+
+// perform vector clip-fit based on significance of deviations
+bool psVectorChiClipFitPolynomial4D(
+    psPolynomial4D *poly,               // Polynomial to fit
+    psStats *stats,                     // Statistics to use in clipping
+    const psVector *mask,               // Mask for input values
+    psMaskType maskValue,               // Mask value
+    const psVector *f,                  // Value of the function, f(x,y,z,t)
+    const psVector *fErr,               // Error in the value
+    const psVector *x,                  // x ordinate
+    const psVector *y,                  // y ordinate
+    const psVector *z,                  // z ordinate
+    const psVector *t                   // t ordinate
+);
+
+// fit a 2D 2nd order polynomial to the 9 pixels centered on (x,y)
+psPolynomial2D *psImageBicubeFit(const psImage *image, // Image to fit
+                                 int x, int y // Pixels of centre of fit
+                                );
+
+// detemine the min(max) of the special 2D 2nd order polynomial
+psPlane psImageBicubeMin(const psPolynomial2D *poly // The polynomial
+                        );
+psPolynomial2D *psPolynomial2D_dX (psPolynomial2D *out, psPolynomial2D *poly);
+psPolynomial2D *psPolynomial2D_dY (psPolynomial2D *out, psPolynomial2D *poly);
+
+/// @}
+#endif /* PS_POLY_UTILS_H */
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psRandom.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psRandom.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psRandom.c	(revision 22158)
@@ -0,0 +1,162 @@
+/** @file psRandom.c
+*  \brief Random Number Generators
+*  \ingroup Math
+*
+*  This file will hold the functions which allocate, free,
+*  and evaluate random number Generators.
+*
+*  @ingroup Math
+*
+*  @author GLG, MHPCC
+*
+*  @version $Revision: 1.17 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-11-16 00:41:07 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <float.h>
+#include <math.h>
+#include <time.h>
+#include <gsl/gsl_rng.h>
+#include <gsl/gsl_randist.h>
+#include <inttypes.h>
+
+#include "psMemory.h"
+#include "psRandom.h"
+#include "psScalar.h"
+#include "psError.h"
+#include "psTrace.h"
+#include "psLogMsg.h"
+#include "psAssert.h"
+
+
+psU64 p_psRandomGetSystemSeed(bool log)
+{
+    FILE*  fd;
+    psU64  seedVal = 0;
+    time_t timeVal;
+
+    fd = fopen("/dev/urandom","r");
+    if(fd == NULL) {
+        // Read system clock to get seed
+        seedVal = (psU64)time(&timeVal);
+    } else {
+        // Read urandom to get seed
+        fread(&seedVal, sizeof(psU64),1,fd);
+        // Close file
+        fclose(fd);
+    }
+
+    // Send log message of the system seed value used
+    if (log) {
+        psLogMsg(__func__,PS_LOG_INFO,"System random seed value used = %" PRIx64, seedVal);
+    }
+
+    return seedVal;
+}
+
+psRandom *psRandomAlloc(psRandomType type,
+                        unsigned long seed)
+{
+    gsl_rng   *r      = NULL;
+    psRandom  *myRNG  = NULL;
+
+    switch (type) {
+    case PS_RANDOM_TAUS:
+        myRNG = (psRandom*)psAlloc(sizeof(psRandom));
+        r = gsl_rng_alloc(gsl_rng_taus);
+        myRNG->gsl = r;
+        if(seed == 0) {
+            gsl_rng_set(myRNG->gsl, p_psRandomGetSystemSeed(true));
+        } else {
+            gsl_rng_set(myRNG->gsl, seed);
+        }
+        myRNG->type = type;
+        break;
+
+    default:
+        psError(PS_ERR_UNEXPECTED_NULL, true, _("Unknown Random Number Generator Type"));
+        break;
+    }
+
+    return(myRNG);
+}
+
+void psRandomReset(psRandom *rand,
+                   unsigned long seed)
+{
+    // Check null psRandom
+    if(rand==NULL) {
+        psError(PS_ERR_UNEXPECTED_NULL,
+                true,
+                _("Random variable is NULL."));
+    } else {
+        // Check seed value to see if system seed should be used
+        if(seed == 0) {
+            gsl_rng_set(rand->gsl,p_psRandomGetSystemSeed(true));
+        } else {
+            gsl_rng_set(rand->gsl, seed);
+        }
+    }
+}
+
+double psRandomUniform(const psRandom *r)
+{
+    // Check null psRandom variable
+    if(r == NULL) {
+        psError(PS_ERR_UNEXPECTED_NULL,
+                true,
+                _("Random variable is NULL."));
+        return(0);
+    } else {
+        return(gsl_rng_uniform(r->gsl));
+    }
+}
+
+double psRandomGaussian(const psRandom *r)
+{
+    // Check null psRandom variable
+    if(r == NULL) {
+        psError(PS_ERR_UNEXPECTED_NULL,
+                true,
+                _("Random variable is NULL."));
+        return(0);
+    } else {
+        // XXX: What should sigma be?
+        return(gsl_ran_gaussian(r->gsl, 1.0));
+    }
+}
+
+double p_psRandomGaussian(const psRandom *r, double sigma)
+{
+    // Check null psRandom variable
+    if(r == NULL) {
+        psError(PS_ERR_UNEXPECTED_NULL,
+                true,
+                _("Random variable is NULL."));
+        return(0);
+    } else {
+        return(gsl_ran_gaussian(r->gsl, sigma));
+    }
+}
+
+double psRandomPoisson(const psRandom *r, double mean)
+{
+    // Check null psRandom variable
+    if(r == NULL) {
+        psError(PS_ERR_UNEXPECTED_NULL,
+                true,
+                _("Random variable is NULL."));
+        return(0);
+    } else {
+        return((psF64) gsl_ran_poisson(r->gsl, mean));
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psRandom.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psRandom.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psRandom.h	(revision 22158)
@@ -0,0 +1,116 @@
+/* @file psRandom.h
+ * @brief Random Number Generators
+ *
+ * This file will hold the prototypes for procedures which allocate, free,
+ * and evaluate random number Generators.
+ *
+ * @author GLG, MHPCC
+ *
+ * @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-16 00:41:07 $
+ *
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_RANDOM_H
+#define PS_RANDOM_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <float.h>
+#include <math.h>
+
+#include "psVector.h"
+#include "psScalar.h"
+#include <gsl/gsl_rng.h>
+#include <gsl/gsl_randist.h>
+
+/** Enumeration containing a flag for psRandom types.  */
+typedef enum {
+    PS_RANDOM_TAUS                     ///< A maximally equidistributed combined Tausworthe generator.
+} psRandomType;
+
+/** Data structure for psRandom.
+ *  Contains information on the psRandom type and GNU Scientific Library random number generator.
+ */
+typedef struct {
+    psRandomType type;                 ///< The type of RNG
+    gsl_rng *gsl;                      ///< The RNG itself
+} psRandom;
+
+/// Get a seed from the system.
+///
+/// Tries /dev/random first, and then the system clock
+psU64 p_psRandomGetSystemSeed(bool log  ///< Print a log message about the choice of seed?
+    );
+
+/** Allocates a psRandom struct.
+ *
+ *  @return psRandom*:    A new psRandom structure.
+ */
+psRandom *psRandomAlloc(
+    psRandomType type,                 ///< The type of RNG
+    unsigned long seed                 ///< Known value with which to seed the RNG
+) PS_ATTR_MALLOC;
+
+/** Resets an existing psRandom struct.
+ *
+ *  @return void
+ */
+void psRandomReset(
+    psRandom *rand,                    ///< Existing psRandom struct to reset
+    unsigned long seed                 ///< Known value with which to seed the RNG
+);
+
+/** Random number generator based on a uniform distribution on [0,1).
+ *  Uses gsl_rng_uniform.
+ *
+ *  @return double:     Random number.
+ */
+double psRandomUniform(
+    const psRandom *r                  ///< psRandom struct for RNG
+);
+
+/** Random number generator based on a Gaussian deviate, N(0,1).
+ *  Uses gsl_ran_gaussian.
+ *
+ *  @return double:     Random number.
+ */
+double psRandomGaussian(
+    const psRandom *r                  ///< psRandom struct for RNG
+);
+
+/** Random number generator based on a Gaussian deviate, N(0,1).
+ *  Uses gsl_ran_gaussian.
+ *
+ *  XXX: I created this since the above psLib spec for p_psRandomGaussian
+ *  had no argument for sigma.  Verify that with IfA.
+ *
+ *  @return double:     Random number.
+ */
+double p_psRandomGaussian(
+    const psRandom *r,                  ///< psRandom struct for RNG
+    double sigma
+);
+
+/** Random number generator based on a Poisson distribution with the given mean.
+ *  Uses gsl_ran_poisson.
+ *
+ *  @return double:     Random number.
+ */
+double psRandomPoisson(
+    const psRandom *r,                 ///< psRandom struct for RNG
+    double mean                         ///< Mean value
+);
+
+#define PS_ASSERT_RANDOM_NON_NULL(NAME, RVAL) \
+if (!(NAME) || !(NAME)->gsl) { \
+    psError(PS_ERR_UNEXPECTED_NULL, true, "Error: Random number generator %s is NULL", #NAME); \
+    return RVAL; \
+}
+
+/// @}
+#endif // #ifndef PS_RANDOM_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psRegion.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psRegion.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psRegion.c	(revision 22158)
@@ -0,0 +1,173 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include "psMemory.h"
+#include "psError.h"
+#include "psAssert.h"
+#include "psConstants.h"
+#include "psRegion.h"
+
+static void regionFree(psRegion *region)
+{
+    // There are non dynamic allocated items
+}
+
+psRegion *psRegionAlloc(float x0,
+                        float x1,
+                        float y0,
+                        float y1)
+{
+    psRegion *region = psAlloc(sizeof(psRegion)); // New region, to be returned
+    psMemSetDeallocator(region, (psFreeFunc)regionFree);
+    // No complex structures, so no special deallocator
+    *region = psRegionSet(x0, x1, y0, y1);
+    return region;
+}
+
+psRegion psRegionSet(float x0,
+                     float x1,
+                     float y0,
+                     float y1)
+{
+    psRegion out;
+
+    out.x0 = x0;
+    out.y0 = y0;
+    out.x1 = x1;
+    out.y1 = y1;
+
+    return out;
+}
+
+psRegion psRegionFromString(const char* region)
+{
+    psS32 col0;
+    psS32 col1;
+    psS32 row0;
+    psS32 row1;
+
+    // section should be of the form '[col0:col1,row0:row1]'
+    if (region == NULL) {
+        return psRegionSet(0,0,0,0);
+    }
+
+    if (sscanf(region,"[%d:%d,%d:%d]",&col0,&col1,&row0,&row1) < 4) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Specified subsection string, '%s', can not be parsed.  Must be in the form '[x1:x2,y1:y2]'."),
+                region);
+        return psRegionSet(NAN,NAN,NAN,NAN);
+    }
+
+    // [0:0,0:0] is complete image region
+    if ((col0 == 0) && (col1 == 0) && (row0 == 0) && (row1 == 0)) {
+        return psRegionSet(0,0,0,0);
+    }
+
+    if ((col1 > 0) && (col0 > col1)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified subset range, [%d:%d,%d:%d], is invalid.  Ranges must be incremental."),
+                col0,col1,row0,row1);
+        return psRegionSet(NAN,NAN,NAN,NAN);
+    }
+
+    if ((row1 > 0) && (row0 > row1)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified subset range, [%d:%d,%d:%d], is invalid.  Ranges must be incremental."),
+                col0,col1,row0,row1);
+        return psRegionSet(NAN,NAN,NAN,NAN);
+    }
+
+    return psRegionSet(col0-1,col1,row0-1,row1);
+}
+
+psRegion psRegionAndParityFromString(int *xParity, int *yParity, const char* region)
+{
+    PS_ASSERT_PTR_NON_NULL (xParity, psRegionSet(NAN,NAN,NAN,NAN));
+    PS_ASSERT_PTR_NON_NULL (yParity, psRegionSet(NAN,NAN,NAN,NAN));
+
+    psS32 col0;
+    psS32 col1;
+    psS32 row0;
+    psS32 row1;
+
+    // unless otherwise detected
+    *xParity = +1;
+    *yParity = +1;
+
+    // section should be of the form '[col0:col1,row0:row1]'
+    if (region == NULL) {
+        return psRegionSet(0,0,0,0);
+    }
+
+    // XXX this is perhaps excessive: if the string is empty, assume 0,0,0,0
+    if (*region == 0) {
+        return psRegionSet(0,0,0,0);
+    }
+
+    if (sscanf(region,"[%d:%d,%d:%d]",&col0,&col1,&row0,&row1) < 4) {
+	// psError(PS_ERR_BAD_PARAMETER_NULL, true,
+	// ("Specified subsection string, '%s', can not be parsed.  Must be in the form '[x1:x2,y1:y2]'."),
+	// region);
+        // return psRegionSet(NAN,NAN,NAN,NAN);
+        return psRegionSet(0,0,0,0);
+    }
+
+    // [0:0,0:0] is complete image region
+    if ((col0 == 0) && (col1 == 0) && (row0 == 0) && (row1 == 0)) {
+        return psRegionSet(0,0,0,0);
+    }
+
+    if ((col1 > 0) && (col0 > col1)) {
+	*xParity = -1;
+	PS_SWAP (col0, col1);
+    }
+
+    if ((row1 > 0) && (row0 > row1)) {
+	*yParity = -1;
+	PS_SWAP (row0, row1);
+    }
+
+    return psRegionSet(col0-1,col1,row0-1,row1);
+}
+
+psString psRegionToString(const psRegion region)
+{
+    char *result = NULL;
+
+    // [0:0,0:0] is complete image region
+    if ((region.x0 == 0) && (region.x1 == 0) && (region.y0 == 0) && (region.y1 == 0)) {
+        psStringAppend(&result, "[0:0,0:0]");
+    } else {
+        psStringAppend(&result, "[%g:%g,%g:%g]",
+                       region.x0+1, region.x1,
+                       region.y0+1, region.y1);
+    }
+    return result;
+}
+
+// define a square region centered on the given coordinate
+psRegion psRegionForSquare(double x,
+                           double y,
+                           double radius)
+{
+    psRegion region;
+    region = psRegionSet (x - radius, x + radius + 1,
+                          y - radius, y + radius + 1);
+    return (region);
+}
+
+bool psRegionIsNaN(psRegion region)
+{
+    return isnan(region.x0) || isnan(region.x1) || isnan(region.y0) || isnan(region.y1);
+}
+
+bool psMemCheckRegion(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)regionFree );
+}
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psRegion.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psRegion.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psRegion.h	(revision 22158)
@@ -0,0 +1,117 @@
+/* @file  psRegion.h
+ * @brief image regions and related functions
+ *
+ * $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ * $Date: 2007-06-10 17:54:05 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_REGION_H
+#define PS_REGION_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+#include "psString.h"
+
+/** Basic image region structure.
+ *
+ * Struct for specifying a rectangular area in an image.
+ *
+ */
+typedef struct
+{
+    float x0;                          ///< the first column of the region.
+    float x1;                          ///< the last column of the region.
+    float y0;                          ///< the first row of the region.
+    float y1;                          ///< the last row of the region.
+}
+psRegion;
+
+/** Create a pointer to a psRegion, with associated psMemBlock.
+ *
+ * @return psRegion* : a new psRegion.
+ */
+psRegion *psRegionAlloc(
+    float x0,                          ///< the first column of the region.
+    float x1,                          ///< the last column of the region + 1.
+    float y0,                          ///< the first row of the region.
+    float y1                           ///< the last row of the region + 1.
+);
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psRegion structure, false otherwise.
+ */
+bool psMemCheckRegion(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+/** Create a psRegion with the specified attributes.
+ *
+ *  @return psRegion :      a corresponding psRegion.
+ */
+psRegion psRegionSet(
+    float x0,                          ///< the first column of the region.
+    float x1,                          ///< the last column of the region + 1.
+    float y0,                          ///< the first row of the region.
+    float y1                           ///< the last row of the region + 1.
+);
+
+/** Create a psRegion with the attribute values given as a string.
+ *
+ *  Create a psRegion with the attribute values given as a string.  The format
+ *  shall be of the standard IRAF form '[x0:x1,y0:y1]'
+ *
+ *  @return psRegion:       A new psRegion struct, or NULL is not successful.
+ */
+psRegion psRegionFromString(
+    const char* region                 ///< image rectangular region in the form '[x0:x1,y0:y1]'
+);
+
+/** Create a psRegion from a string in IRAF form '[x0:x1,y0:y1]', returning range parities
+ *
+ *  Create a psRegion using the range defined by a string in the standard IRAF form
+ *  '[x0:x1,y0:y1]'.  Unlike psRegionFromString, the ranges may have x0 > x1 or y0 > y1, in
+ *  which case the xParity or yParity terms will be set to -1 (instead of the default +1).
+ *
+ *  @return psRegion:       A new psRegion struct, or NULL is not successful.
+ */
+psRegion psRegionAndParityFromString(
+    int *xParity,		      ///< +1 if x0 <= x1, -1 otherwise
+    int *yParity,		      ///< +1 if y0 <= y1, -1 otherwise
+    const char* region		      ///< image rectangular region in the form '[x0:x1,y0:y1]'
+);
+
+/** Create a string of the standard IRAF form '[x0:x1,y0:y1]' from a psRegion.
+ *
+ *  @return psString:  A new string representing the psRegion as text, or NULL
+ *                  is not successful.
+ */
+psString psRegionToString(
+    const psRegion region              ///< the psRegion to convert to a string
+);
+
+/** Defines a region corresponding to the square with center at coordinate x,y
+ *  and with coderadius.  The width of the square is 2radius + 1.
+ *
+ *  @return psRegion:       the newly defined psRegion.
+ */
+psRegion psRegionForSquare(
+    double x,                          ///< x coordinate at square-center
+    double y,                          ///< y coordinate at square-center
+    double radius                      ///< radius of square
+);
+
+/** Test if any element of the region is NaN
+ *
+ * @return bool:        True if an element is NaN, otherwise false.
+ */
+bool psRegionIsNaN(
+    psRegion region                    ///< Region to check
+);
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psRegionForImage.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psRegionForImage.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psRegionForImage.c	(revision 22158)
@@ -0,0 +1,65 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include "psError.h"
+#include "psRegion.h"
+#include "psImage.h"
+#include "psRegionForImage.h"
+
+// set actual region based on image parameters:
+// - compensate for negative upper limits
+// - force range to be on this image
+// - saturate on upper and lower limits of image
+// - flip x0,x1 if x0>x1
+// - flip y0,y1 if y0>y1
+// psRegion in refers to coordinates in the *parent* image
+psRegion psRegionForImage(psImage *image,
+                          psRegion in)
+{
+
+    //    if (image == NULL) {
+    //        return in;
+    //    }
+    PS_ASSERT_IMAGE_NON_NULL(image, in);
+    //if the region is [0,0,0,0], the whole image (or subimage) is to be included.
+    if (in.x0 == 0 && in.x1 == 0 && in.y0 == 0 && in.y1 == 0) {
+        in.x0 = image->col0;
+        in.x1 = image->col0 + image->numCols;
+        in.y0 = image->row0;
+        in.y1 = image->row0 + image->numRows;
+        return (in);
+    }
+
+    // convert non-positive upper-limits
+    // XXX note that the upper limit in these cases is defined relative to the subimage
+    // also note that truncation limits to the valid subimage pixels
+    in.x1 = (in.x1 <= 0) ? (image->col0 + image->numCols + in.x1) : in.x1;
+    in.y1 = (in.y1 <= 0) ? (image->row0 + image->numRows + in.y1) : in.y1;
+
+    // force the upper-limits to be on the image
+    in.x1 = PS_MIN(image->col0 + image->numCols, in.x1);
+    in.y1 = PS_MIN(image->row0 + image->numRows, in.y1);
+
+    // force the lower-limits to be on the image
+    in.x0 = PS_MAX(image->col0, in.x0);
+    in.y0 = PS_MAX(image->row0, in.y0);
+    in.x0 = PS_MIN(image->col0 + image->numCols, in.x0);
+    in.y0 = PS_MIN(image->row0 + image->numRows, in.y0);
+
+    // flip start and end if out of order
+    if (in.x0 > in.x1) {
+        psError (PS_ERR_BAD_PARAMETER_VALUE, true,
+                 "Invalid region in psRegionForImage.  x0 > x1.  Values have been swapped.\n");
+        PS_SWAP (in.x0, in.x1);
+    }
+    if (in.y0 > in.y1) {
+        psError (PS_ERR_BAD_PARAMETER_VALUE, true,
+                 "Invalid region in psRegionForImage.  y0 > y1.  Values have been swapped.\n");
+        PS_SWAP (in.y0, in.y1);
+    }
+
+    return (in);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psRegionForImage.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psRegionForImage.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psRegionForImage.h	(revision 22158)
@@ -0,0 +1,35 @@
+/* @file  psRegionForImage.h
+ * @brief regions definitions based on images
+ *
+ * $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ * $Date: 2007-01-23 22:47:23 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_REGION_FOR_IMAGE_H
+#define PS_REGION_FOR_IMAGE_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+/** Sets an actual region based on image parameters.
+ *
+ *  An image region defined with negative upper limits may be rationalized for the bounds of a
+ *  specific image with psRegionForImage.  The output of this function is a region with negative
+ *  upper limits replaced by their corrected value appropriate to the given image.  In addition,
+ *  the lower and upper limits are foced to lie within the bounds of the image.  If the lower-
+ *  limit coordinates are lewss than the lower bound of the image, they are limited to the lower
+ *  bound of the image.  Conversely, if the upper-limit coordinates are greater than the upper
+ *  bound of the image, they are truncated to define only valid pixels.  If the lower-limit
+ *  coordinates are greater than the upper bounds of the image, or the upper-limit coordinates
+ *  are less than the lower bounds of the image, the coordinates should saturate on those limits.
+ *
+ *  @return psRegion:       A region with negative upper limits replaced by the corrected
+ */
+psRegion psRegionForImage(
+    psImage *image,                    ///< the image for which the region is to be set
+    psRegion in                        ///< the image region limits
+);
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psSort.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psSort.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psSort.h	(revision 22158)
@@ -0,0 +1,137 @@
+// Heap sort of the array
+// Based on descriptions in Sedgewick "Algorithms in C"
+//
+// Copyright (C) 1999  Thomas Walter
+// Copyright (C) 2007  Paul Price, Institute for Astronomy, University of Hawaii
+//
+// 18 February 2000: Modified for GSL by Brian Gough
+// 29 November 2007: Modified for psLib by Paul Price
+//
+//
+// This 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 source 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.
+//
+
+#ifndef PS_SORT_H
+#define PS_SORT_H
+
+// XXX since the key size is fixed (same number of bits) a Radix sort could be
+// a big win here -- someone should benchmark this -JH
+
+// The following sort code is based on gsl_heapsort from GSL-1.8 (www.gnu.org/software/gsl), file
+// gsl-1.8/sort/sort.c, which is distributed under the GNU General Public License, version 2.
+
+
+// Use of the PSSORT() and PSSELECT() macros require additional macros defined:
+// COMPAREEXPR(A,B): expression to compare element A with element B; true if element A is smaller than B.
+// SWAPFUNC(TYPE,A,B): swap element A with element B; the type is provided so that a temporary variable can
+// be defined.
+
+// Sort the heap
+#define PSSORT_DOWNHEAP(COMPAREFUNC, SWAPFUNC, SWAPTYPE, K) { \
+    unsigned long k = K; /* Local version of k --- so the higher-level version isn't modified */ \
+    while (k <= N / 2) { \
+        unsigned long j = 2 * k; \
+        if (j < N && COMPAREFUNC(j, j + 1)) { \
+            j++; \
+        } \
+        if (COMPAREFUNC(k, j)) { \
+            SWAPFUNC(SWAPTYPE, j, k); \
+        } else { \
+            break; \
+        } \
+        k = j; \
+    } \
+}
+
+// Driver for heap sort
+// SIZE: Size of the array
+// COMPAREEXPR: Macro with expression for comparison
+// SWAPFUNC: Macro to swap elements
+// SWAPTYPE: Type for swapping, passed to SWAPFUNC
+#define PSSORT(SIZE, COMPAREEXPR, SWAPFUNC, SWAPTYPE) { \
+    unsigned long N = (SIZE) - 1; /* Index of last element */ \
+    unsigned long i = N / 2 + 1; /* Adding one to compensate for i-- below */ \
+    do { \
+        i--; \
+        PSSORT_DOWNHEAP(COMPAREEXPR, SWAPFUNC, SWAPTYPE, i); \
+    } while (i > 0); \
+    while (N > 0) { \
+        SWAPFUNC(SWAPTYPE, 0, N); /* Swap elements */ \
+        /* Process the heap */ \
+        N--; \
+        PSSORT_DOWNHEAP(COMPAREEXPR, SWAPFUNC, SWAPTYPE, 0); \
+    } \
+}
+// END of heap sort code from GSL
+
+
+
+// The following algorithm for selection was provided by http://en.wikipedia.org/wiki/Selection_algorithm
+// (version as of 21 May 2008, at 17:38), and implemented below as PSSELECT():
+//
+// function partition(list, left, right, pivotIndex)
+//     pivotValue := list[pivotIndex]
+//     swap list[pivotIndex] and list[right]  // Move pivot to end
+//     storeIndex := left
+//     for i from left to right-1
+//         if list[i] < pivotValue
+//             swap list[storeIndex] and list[i]
+//             storeIndex := storeIndex + 1
+//     swap list[right] and list[storeIndex]  // Move pivot to its final place
+//     return storeIndex
+//
+// function select(list, k, left, right)
+//     loop
+//         select a pivot value list[pivotIndex]
+//         pivotNewIndex := partition(list, left, right, pivotIndex)
+//         if k = pivotNewIndex
+//             return list[k]
+//         else if k < pivotNewIndex
+//             right := pivotNewIndex-1
+//         else
+//             left := pivotNewIndex+1
+
+
+// Select the RANK-th element
+// This macro reorders the array so that the RANK-th element is in the correct position
+// SIZE: Size of the array
+// RANK: RANK to move into the correct position
+// COMPAREEXPR: Macro with expression for comparison
+// SWAPFUNC: Macro to swap elements
+// SWAPTYPE: Type for swapping, passed to SWAPFUNC
+#define PSSELECT(SIZE, RANK, COMPAREEXPR, SWAPFUNC, SWAPTYPE) { \
+    bool selectContinue = true;         /* Continue swapping? */ \
+    long selectMax = SIZE - 1;           /* Maximum index */ \
+    long selectMin = 0;                  /* Minimum index */ \
+    while (selectContinue) { \
+        long selectPivot = (selectMin + selectMax) >> 1; /* Pivot index */ \
+        SWAPFUNC(SWAPTYPE, selectPivot, selectMax); /* Move pivot to end */ \
+        long selectStore = selectMin;    /* Index of interest */ \
+        for (long i = selectMin; i < selectMax; i++) { \
+            if (COMPAREEXPR(i, selectMax)) { /* Note: comparing with the original pivot */ \
+                SWAPFUNC(SWAPTYPE, selectStore, i); \
+                selectStore++; \
+            } \
+        } \
+        SWAPFUNC(SWAPTYPE, selectMax, selectStore); /* Move pivot to its final place */ \
+        if (selectStore == RANK) { \
+            selectContinue = false;     /* Done */ \
+        } else if (selectStore > RANK) { \
+            selectMax = selectStore - 1; \
+        } else { \
+            selectMin = selectStore + 1; \
+        } \
+    } \
+}
+
+
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psSparse.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psSparse.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psSparse.c	(revision 22158)
@@ -0,0 +1,470 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <unistd.h>
+
+#include "psMemory.h"
+#include "psError.h"
+#include "psLogMsg.h"
+#include "psVector.h"
+#include "psAssert.h"
+#include "psConstants.h"
+#include "psImageStructManip.h"
+#include "psImage.h"
+#include "psMatrix.h"
+#include "psSparse.h"
+#include "psAbort.h"
+
+#define BUFFER 100                      // Size to increment at each go
+
+static void sparseFree(psSparse *sparse)
+{
+    if (!sparse) {
+        return;
+    }
+    psFree(sparse->Aij);
+    psFree(sparse->Bfj);
+    psFree(sparse->Qii);
+    psFree(sparse->Si);
+    psFree(sparse->Sj);
+    return;
+}
+
+// allocate a sparse matrix container for Nrows, with Nelem slots allocated
+psSparse *psSparseAlloc(int Nrows, int Nelem)
+{
+    psSparse *sparse = (psSparse *)psAlloc(sizeof(psSparse));
+    psMemSetDeallocator(sparse, (psFreeFunc)sparseFree);
+
+    sparse->Aij = psVectorAllocEmpty(Nelem, PS_DATA_F32);
+    sparse->Si  = psVectorAllocEmpty(Nelem, PS_DATA_S32);
+    sparse->Sj  = psVectorAllocEmpty(Nelem, PS_DATA_S32);
+
+    sparse->Nelem = 0;
+
+    sparse->Bfj = psVectorAlloc(Nrows, PS_DATA_F32);
+    sparse->Qii = psVectorAlloc(Nrows, PS_DATA_F32);
+
+    sparse->Nrows = Nrows;
+
+    return sparse;
+}
+
+// user should only add elements above the diagonal, but we don't check this
+bool psSparseMatrixElement(psSparse *sparse, int i, int j, float value)
+{
+    PS_ASSERT_PTR_NON_NULL(sparse, false);
+    PS_ASSERT_INT_NONNEGATIVE(i, false);
+    PS_ASSERT_INT_NONNEGATIVE(j, false);
+
+    // EAM : this is now a fatal error
+    if (i < j) {
+        // psError(PS_ERR_UNKNOWN, true, "i=%d, j=%d refers to a sub-diagonal element. not allowed!");
+        psAbort("i=%d, j=%d refers to a sub-diagonal element. not allowed!", i, j);
+        return false;
+    }
+
+    if (i == j) {
+        // add to the diagonal
+        sparse->Qii->data.F32[i] = value;
+
+        // check vectors lengths and extend if needed
+        if (sparse->Nelem >= sparse->Aij->nalloc) {
+            psVectorRealloc(sparse->Aij, sparse->Aij->nalloc + BUFFER);
+            psVectorRealloc(sparse->Si,  sparse->Si->nalloc + BUFFER);
+            psVectorRealloc(sparse->Sj,  sparse->Sj->nalloc + BUFFER);
+        }
+
+        int k = sparse->Nelem;         // Index at which to add
+        sparse->Aij->data.F32[k] = value;
+        sparse->Si->data.S32[k]  = i;
+        sparse->Sj->data.S32[k]  = j;
+
+        sparse->Nelem ++;
+        sparse->Aij->n ++;
+        sparse->Si->n ++;
+        sparse->Sj->n ++;
+    } else {
+        // check vectors lengths and extend if needed
+        if (sparse->Nelem >= sparse->Aij->nalloc - 1) {
+            psVectorRealloc(sparse->Aij, sparse->Aij->nalloc + BUFFER);
+            psVectorRealloc(sparse->Si,  sparse->Si->nalloc + BUFFER);
+            psVectorRealloc(sparse->Sj,  sparse->Sj->nalloc + BUFFER);
+        }
+
+        int k = sparse->Nelem;         // Index at which to add
+        sparse->Aij->data.F32[k] = value;
+        sparse->Si->data.S32[k]  = i;
+        sparse->Sj->data.S32[k]  = j;
+        k++;
+
+        sparse->Aij->data.F32[k] = value;
+        sparse->Si->data.S32[k]  = j;
+        sparse->Sj->data.S32[k]  = i;
+
+        sparse->Nelem  += 2;
+        sparse->Aij->n += 2;
+        sparse->Si->n  += 2;
+        sparse->Sj->n  += 2;
+    }
+
+    return true;
+}
+
+void psSparseVectorElement(psSparse *sparse, int i, float value)
+{
+
+    sparse->Bfj->data.F32[i] = value;
+    return;
+}
+
+// multiply A * x
+psVector *psSparseMatrixTimesVector(psVector *output, const psSparse *matrix, const psVector *vector)
+{
+    PS_ASSERT_PTR_NON_NULL(matrix, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(vector, NULL);
+
+    output = psVectorRecycle(output, vector->n, PS_TYPE_F32);
+
+    int Nelem = 0;                     // Number of elements
+    for (int j = 0; j < vector->n; j++) {
+        double F = 0;                    // Running total
+        while (matrix->Sj->data.S32[Nelem] == j) {
+            int i = matrix->Si->data.S32[Nelem];
+            F += vector->data.F32[i] * matrix->Aij->data.F32[Nelem];
+            Nelem++;
+        }
+        output->data.F32[j] = F;
+    }
+    return output;
+}
+
+// solve Ax = B
+psVector *psSparseSolve(psVector *output, psSparseConstraint constraint, const psSparse *sparse, int Niter)
+{
+    PS_ASSERT_PTR_NON_NULL(sparse, NULL);
+    PS_ASSERT_INT_POSITIVE(Niter, NULL);
+    PS_ASSERT_FLOAT_LARGER_THAN(constraint.paramDelta, 0.0, NULL);
+
+    // Dereference some vectors
+    psVector *Qii = sparse->Qii;
+    psVector *Bfj = sparse->Bfj;
+
+    // initial guess is B / Qii
+    output = psVectorCopy(output, Bfj, PS_DATA_F32);
+    for (int i = 0; i < output->n; i++) {
+        output->data.F32[i] /= Qii->data.F32[i];
+    }
+
+    // temporary storage for intermediate results
+    psVector *dQ = psVectorAlloc(output->n, PS_DATA_F32);
+
+    for (int j = 0; j < Niter; j++) {
+        dQ = psSparseMatrixTimesVector(dQ, sparse, output);
+        for (int i = 0; i < dQ->n; i++) {
+            psF32 dG = (dQ->data.F32[i] - Bfj->data.F32[i]) / Qii->data.F32[i];
+            if (fabs (dG) > constraint.paramDelta) {
+                if (dG > 0) {
+                    dG = +constraint.paramDelta;
+                } else {
+                    dG = -constraint.paramDelta;
+                }
+            }
+            output->data.F32[i] -= dG;
+            output->data.F32[i] = PS_MAX(output->data.F32[i], constraint.paramMin);
+            output->data.F32[i] = PS_MIN(output->data.F32[i], constraint.paramMax);
+        }
+    }
+    psFree(dQ);
+
+    return output;
+}
+
+bool psSparseResort(psSparse *sparse)
+{
+    int Nelem = sparse->Nelem;
+
+    psVector *index = psVectorSortIndex(NULL, sparse->Sj); // Index key for sorting
+    if (!index) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to sort sparse matrix.\n");
+        return false;
+    }
+    psVector *Aij = sparse->Aij;
+    psVector *Si = sparse->Si;
+    psVector *Sj = sparse->Sj;
+
+    // allocate new temporary vectors
+    psVector *tAij = psVectorAlloc(Nelem, PS_DATA_F32);
+    psVector *tSi  = psVectorAlloc(Nelem, PS_DATA_S32);
+    psVector *tSj  = psVectorAlloc(Nelem, PS_DATA_S32);
+
+    for (int i = 0; i < Nelem; i++) {
+        int j = index->data.U32[i];
+        tAij->data.F32[i] = Aij->data.F32[j];
+        tSi->data.S32[i]  = Si->data.S32[j];
+        tSj->data.S32[i]  = Sj->data.S32[j];
+    }
+    psFree(index);
+    psFree(Aij);
+    psFree(Si);
+    psFree(Sj);
+
+    sparse->Aij = tAij;
+    sparse->Si = tSi;
+    sparse->Sj = tSj;
+
+    return true;
+}
+
+/*** psSparseBorder Functions : these are used to solve a matrix equation of the form:
+     A x = f  where A is partitioned into:
+     A = |S B| where Q is a low-rank square matrix (N<20)
+     |B Q| and B is a rectangular band (technically this is B and B^T)
+     and S is a sparse matrix.
+*/
+
+static void psSparseBorderFree(psSparseBorder *border)
+{
+    if (!border) {
+        return;
+    }
+    psFree(border->sparse);
+    psFree(border->Bij);
+    psFree(border->Tjj);
+    psFree(border->Gj);
+    return;
+}
+
+// allocate a sparse matrix border container for a system with Nrows + Nborder elements
+// the supplied psSparse has a size of Nrows
+psSparseBorder *psSparseBorderAlloc(psSparse *sparse, int Nborder)
+{
+    psSparseBorder *border = (psSparseBorder *)psAlloc(sizeof(psSparseBorder));
+    psMemSetDeallocator(border, (psFreeFunc) psSparseBorderFree);
+
+    border->sparse = psMemIncrRefCounter (sparse); // XXX increment ref counter or not?
+
+    int Nrows = sparse->Nrows;
+    border->Nrows = Nrows;
+    border->Nborder = Nborder;
+
+    border->Bij = psImageAlloc(Nrows, Nborder, PS_DATA_F32);
+    psImageInit (border->Bij, 0.0);
+
+    border->Tjj = psImageAlloc(Nborder, Nborder, PS_DATA_F32);
+    psImageInit (border->Tjj, 0.0);
+
+    border->Gj = psVectorAlloc(Nborder, PS_DATA_F32);
+    psVectorInit (border->Gj, 0.0);
+
+    return border;
+}
+
+// add elements to border->Tjj
+bool psSparseBorderElementT(psSparseBorder *border, int i, int j, float value)
+{
+    PS_ASSERT_PTR_NON_NULL(border, false);
+    PS_ASSERT_PTR_NON_NULL(border->Tjj, false);
+    PS_ASSERT_INT_NONNEGATIVE(i, false);
+    PS_ASSERT_INT_NONNEGATIVE(j, false);
+
+    // check i,j against border->Tjj->nX,nY
+    border->Tjj->data.F32[j][i] = value;
+    return true;
+}
+
+// add elements to border->Bij
+bool psSparseBorderElementB(psSparseBorder *border, int i, int j, float value)
+{
+    PS_ASSERT_PTR_NON_NULL(border, false);
+    PS_ASSERT_PTR_NON_NULL(border->Bij, false);
+    PS_ASSERT_INT_NONNEGATIVE(i, false);
+    PS_ASSERT_INT_NONNEGATIVE(j, false);
+
+    border->Bij->data.F32[j][i] = value;
+    return true;
+}
+
+// add elements to border->Gj
+bool psSparseBorderElementG(psSparseBorder *border, int i, float value)
+{
+    PS_ASSERT_PTR_NON_NULL(border, false);
+    PS_ASSERT_PTR_NON_NULL(border->Gj, false);
+    PS_ASSERT_INT_NONNEGATIVE(i, false);
+
+    border->Gj->data.F32[i] = value;
+    return true;
+}
+
+// perform the operation dG = B*x
+psVector *psSparseBorderLowerProduct (psVector *dG, psSparseBorder *border, psVector *xVec)
+{
+    // XXX assert xVec->n == border->Nrows
+
+    int Nborder = border->Nborder;
+    int Nrows = border->Nrows;
+
+    dG = psVectorRecycle (dG, Nborder, PS_TYPE_F32);
+    psVectorInit (dG, 0.0);
+
+    for (int j = 0; j < Nborder; j++) {
+        double value = 0;
+        for (int i = 0; i < Nrows; i++) {
+            value += border->Bij->data.F32[j][i] * xVec->data.F32[i];
+        }
+        dG->data.F32[j] = value;
+    }
+
+    return dG;
+}
+
+// perform the operation dF = B^T*y
+psVector *psSparseBorderUpperProduct (psVector *dF, psSparseBorder *border, psVector *yVec)
+{
+    // XXX assert yVec->n == border->Nborder
+
+    int Nborder = border->Nborder;
+    int Nrows = border->Nrows;
+
+    dF = psVectorRecycle (dF, Nrows, PS_TYPE_F32);
+    psVectorInit (dF, 0.0);
+
+    for (int i = 0; i < Nrows; i++) {
+        double value = 0;
+        for (int j = 0; j < Nborder; j++) {
+            value += border->Bij->data.F32[j][i] * yVec->data.F32[j];
+        }
+        dF->data.F32[i] = value;
+    }
+
+    return dF;
+}
+
+// perform the operation dG = T*y
+psVector *psSparseBorderSquareProduct (psVector *dG, psSparseBorder *border, psVector *yVec)
+{
+    // XXX assert yVec->n == border->Nborder
+
+    int Nborder = border->Nborder;
+
+    dG = psVectorRecycle (dG, Nborder, PS_TYPE_F32);
+    psVectorInit (dG, 0.0);
+
+    for (int i = 0; i < Nborder; i++) {
+        double value = 0;
+        for (int j = 0; j < Nborder; j++) {
+            value += border->Tjj->data.F32[i][j] * yVec->data.F32[j];
+        }
+        dG->data.F32[i] = value;
+    }
+
+    return dG;
+}
+
+// perform the operation dF = B^T*y
+bool psSparseBorderUpperDelta (psSparseBorder *border, psVector *dF)
+{
+
+    int Nrows = border->Nrows;
+
+    for (int i = 0; i < Nrows; i++) {
+        border->sparse->Bfj->data.F32[i] -= dF->data.F32[i];
+    }
+
+    return true;
+}
+
+// perform the operation dF = B^T*y
+psVector *psSparseBorderLowerDelta (psVector *Go, psSparseBorder *border, psVector *dG)
+{
+    int Nborder = border->Nborder;
+
+    Go = psVectorRecycle (Go, Nborder, PS_TYPE_F64);
+    psVectorInit (Go, 0.0);
+
+    for (int i = 0; i < Nborder; i++) {
+        Go->data.F64[i] = border->Gj->data.F32[i] - dG->data.F32[i];
+    }
+    return Go;
+}
+
+// multiply A*x = b (where x is (x,y) and b is (f,g))
+bool psSparseBorderMultiply (psVector **fIn, psVector **gIn, psSparseBorder *border, psVector *xVec, psVector *yVec)
+{
+    psVector *fVec = *fIn;
+    fVec = psSparseMatrixTimesVector (fVec, border->sparse, xVec);
+    psVector *dF = psSparseBorderUpperProduct (NULL, border, yVec);
+    for (int i = 0; i < border->Nrows; i++) {
+        fVec->data.F32[i] += dF->data.F32[i];
+    }
+    psFree (dF);
+    *fIn = fVec;
+
+    psVector *gVec = *gIn;
+    gVec = psSparseBorderSquareProduct (gVec, border, yVec);
+    psVector *dG = psSparseBorderLowerProduct (NULL, border, xVec);
+    for (int i = 0; i < border->Nborder; i++) {
+        gVec->data.F32[i] += dG->data.F32[i];
+    }
+    psFree (dG);
+    *gIn = gVec;
+
+    return true;
+}
+
+bool psSparseBorderSolve(psVector **xFit, psVector **yFit, psSparseConstraint constraint, psSparseBorder *border, int Niter)
+{
+    // PS_ASSERT_PTR_NON_NULL(sparse, NULL);
+    // PS_ASSERT_INT_POSITIVE(Niter, NULL);
+    // PS_ASSERT_FLOAT_LARGER_THAN(constraint.paramDelta, 0.0, NULL);
+
+    psVector *xVec = *xFit;
+    psVector *yVec = *yFit;
+
+    // save the original value of Bfj, alloc other temp vectors
+    // XXX be careful about TYPE requirements of support functions...
+    psVector *Fo = psVectorCopy (NULL, border->sparse->Bfj, PS_TYPE_F32);
+    psVector *dF = psVectorAlloc (border->Nrows, PS_TYPE_F32);
+    psVector *Go = psVectorAlloc (border->Nborder, PS_TYPE_F64);
+    psVector *dG = psVectorAlloc (border->Nborder, PS_TYPE_F32);
+    psImage *square = psImageAlloc (border->Nborder, border->Nborder, PS_TYPE_F64);
+
+    for (int j = 0; j < Niter; j++) {
+
+        // solve Sx = f
+        xVec = psSparseSolve(xVec, constraint, border->sparse, Niter);
+
+        dG = psSparseBorderLowerProduct (dG, border, xVec);
+
+        // XXX i have an error here: i'm not
+        // I need to reset to the original value of g before subtracting
+        // XXX this function returns an psVector:F64 so we can us it in GJ
+        Go = psSparseBorderLowerDelta (Go, border, dG);
+
+        // use gauss-jordan to solve the lower square
+        // square is modified by GJSolve, so re-copy each time
+        square = psImageCopy (square, border->Tjj, PS_TYPE_F64);
+        psMatrixGJSolve (square, Go);
+        yVec = psVectorCopy (yVec, Go, PS_TYPE_F32);
+
+        // calculate the delta relative to the original Bfj:
+        border->sparse->Bfj = psVectorCopy (border->sparse->Bfj, Fo, PS_TYPE_F32);
+        dF = psSparseBorderUpperProduct (dF, border, yVec);
+        psSparseBorderUpperDelta (border, dF);
+    }
+
+    psFree (dG);
+    psFree (Go);
+    psFree (dF);
+    psFree (Fo);
+    psFree (square);
+
+    *xFit = xVec;
+    *yFit = yVec;
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psSparse.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psSparse.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psSparse.h	(revision 22158)
@@ -0,0 +1,110 @@
+/* @file  psSparse.h
+ * @brief functions to manipulate sparse matrices equations
+ *
+ * $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ * $Date: 2007-08-09 01:40:07 $
+ * Copyright 2004-2005 IfA, University of Hawaii
+ */
+
+#ifndef PS_SPARSE_H
+#define PS_SPARSE_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+// constraints to limit the range of the matrix equation solution
+typedef struct
+{
+    double paramDelta;
+    double paramMin;
+    double paramMax;
+}
+psSparseConstraint;
+
+// A sparse matrix equation: A x = Bf
+typedef struct
+{
+    psVector *Aij;                      // Aij contains the populated elements of the matrix
+    psVector *Bfj;                      // Bfj contains the elements of the vector Bf
+    psVector *Qii;                      // Qii contains the diagonal elements of Aij
+    psVector *Si;                       // Si contains the i-index values of Aij
+    psVector *Sj;                       // Sj contains the j-index values of Aij
+    int Nelem;                         // Number of elements
+    int Nrows;                         // Number of rows
+}
+psSparse;
+
+// The border elements of a sparse matrix equation:
+// A = |S B'| where T is a low-rank square matrix (N<20)
+//     |B T | and B is a rectangular band (B' is B transpose)
+typedef struct
+{
+    psSparse *sparse;   // corresponding sparse matrix equation
+    psImage *Bij;   // Bij contains the border band (Nrow x Nborder)
+    psImage *Tjj;   // Tjj contains the square border matrix (Nborder x Nborder)
+    psVector *Gj;   // XXX lower dependent var drop??
+    int Nrows;    // Number of rows (long dimension of Bij, 0-j)
+    int Nborder;   // Number of border elements (size of Qii)
+}
+psSparseBorder;
+
+// allocate a sparse matrix structure
+psSparse *psSparseAlloc(int Nrows, int Nelem) PS_ATTR_MALLOC;
+
+// add a new matrix element
+// user should only add elements above the diagonal
+bool psSparseMatrixElement(psSparse *sparse, // Matrix to which to add
+                           int i, int j, // Matrix indices at which to add
+                           float value  // Value to add
+                          );
+
+// define a new sparse matrix equation vector element
+void psSparseVectorElement(psSparse *sparse, // Matrix to which to add
+                           int i,      // Index to add
+                           float value  // Value to add
+                          );
+
+// perform the operation matrix * vector on a sparse matrix and a vector
+psVector *psSparseMatrixTimesVector(psVector *output, // Output vector, or NULL
+                                    const psSparse *matrix, // Sparse matrix
+                                    const psVector *vector // Corresponding vector
+                                   );
+
+// re-sort a sparse matrix to have all elements in index order rather than insertion order
+// call this before solving, but after populating matrix and vector
+bool psSparseResort(psSparse *sparse    // Matrix to re-sort
+                   );
+
+// solve the equation A x = Bf for the value of x
+// a good starting guess is the vector Bf
+psVector *psSparseSolve(psVector *output,// The output vector, or NULL
+                        psSparseConstraint constraint, // Constraint to limit the range of the solution
+                        const psSparse *sparse, // Sparse matrix
+                        int Niter       // Number of iterations
+                       );
+
+// allocate a sparse matrix structure
+psSparseBorder *psSparseBorderAlloc(psSparse *sparse, int Nborder) PS_ATTR_MALLOC;
+
+bool psSparseBorderElementT(psSparseBorder *border, int i, int j, float value);
+
+bool psSparseBorderElementB(psSparseBorder *border, int i, int j, float value);
+
+bool psSparseBorderElementG(psSparseBorder *border, int i, float value);
+
+psVector *psSparseBorderLowerProduct (psVector *dG, psSparseBorder *border, psVector *xVec);
+
+psVector *psSparseBorderUpperProduct (psVector *dF, psSparseBorder *border, psVector *yVec);
+
+psVector *psSparseBorderSquareProduct (psVector *dG, psSparseBorder *border, psVector *yVec);
+
+bool psSparseBorderUpperDelta (psSparseBorder *border, psVector *dF);
+
+psVector *psSparseBorderLowerDelta (psVector *Go, psSparseBorder *border, psVector *dG);
+
+bool psSparseBorderMultiply (psVector **fIn, psVector **gIn, psSparseBorder *border, psVector *xVec, psVector *yVec);
+
+bool psSparseBorderSolve(psVector **xFit, psVector **yFit, psSparseConstraint constraint, psSparseBorder *border, int Niter);
+
+/// @}
+#endif /* PS_SPARSE_H */
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psSpline.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psSpline.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psSpline.c	(revision 22158)
@@ -0,0 +1,429 @@
+/** @file psSpline.c
+*
+*  @brief Contains basic spline allocation, deallocation, fitting,
+*         and evaluation routines.
+*
+*  This file contains the routines that allocate, free, and evaluate splines.
+*
+*  @version $Revision: 1.158 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-03-14 02:36:28 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/*****************************************************************************/
+/*  INCLUDE FILES                                                            */
+/*****************************************************************************/
+#include <stdio.h>
+#include <stdbool.h>
+#include <float.h>
+#include <math.h>
+
+#include "psMemory.h"
+#include "psVector.h"
+#include "psScalar.h"
+#include "psTrace.h"
+#include "psError.h"
+#include "psLogMsg.h"
+#include "psPolynomial.h"
+#include "psSpline.h"
+#include "psAssert.h"
+
+#include "psMathUtils.h"
+
+/*****************************************************************************/
+/* DEFINE STATEMENTS                                                         */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* TYPE DEFINITIONS                                                          */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* GLOBAL VARIABLES                                                          */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* FILE STATIC VARIABLES                                                     */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* FUNCTION IMPLEMENTATION - LOCAL                                           */
+/*****************************************************************************/
+
+static void spline1DFree(psSpline1D *tmpSpline)
+{
+    if (tmpSpline == NULL) {
+        return;
+    }
+
+    if (tmpSpline->spline != NULL) {
+        for (psS32 i=0;i<tmpSpline->n;i++) {
+            psFree((tmpSpline->spline)[i]);
+        }
+        psFree(tmpSpline->spline);
+    }
+
+    if (tmpSpline->p_psDeriv2 != NULL) {
+        psFree(tmpSpline->p_psDeriv2);
+    }
+
+    psFree(tmpSpline->knots);
+
+    return;
+}
+
+
+static void PS_POLY1D_PRINT(
+    psPolynomial1D *poly)
+{
+    printf("-------------- PS_POLY1D_PRINT() --------------\n");
+    printf("poly->nX is %d\n", poly->nX);
+    for (psS32 i = 0 ; i < (1 + poly->nX) ; i++) {
+        printf("poly->coeff[%d] is %f\n", i, poly->coeff[i]);
+    }
+}
+
+static void PS_PRINT_SPLINE2(psSpline1D *mySpline)
+{
+    printf("-------------- PS_PRINT_SPLINE2() --------------\n");
+    printf("mySpline->n is %d\n", mySpline->n);
+    for (psS32 i = 0 ; i < mySpline->n ; i++) {
+        PS_POLY1D_PRINT(mySpline->spline[i]);
+    }
+    PS_VECTOR_PRINT_F32(mySpline->knots);
+}
+
+/*****************************************************************************
+CalculateSecondDerivs(): Given a set of x/y vectors corresponding to a
+tabulated function at n points, this routine calculates the second
+derivatives of the interpolating cubic splines at those n points.
+ 
+The first and second derivatives at the endpoints were previously undefined in
+the SDR.  From bugzilla #???, they are required to be 0.0, implementing natural
+splines.
+ 
+Endpoints are defined by
+    PS_LEFT_SPLINE_DERIV
+    PS_RIGHT_SPLINE_DERIV
+ 
+This routine assumes that vectors x and y are of the appropriate types/sizes
+(F32).
+ 
+XXX: use recycled vectors for internal data.
+XXX: do an F64 version?
+ *****************************************************************************/
+#define PS_LEFT_SPLINE_DERIV 0.0
+#define PS_RIGHT_SPLINE_DERIV 0.0
+static psF32 *calculateSecondDerivs(
+    const psVector* x,                  ///< Ordinates
+    const psVector* y)                  ///< Coordinates
+{
+    psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__);
+    if (psTraceGetLevel("psLib.math") >= 6) {
+        p_psVectorPrint(1, (psVector *) x, "x");
+        p_psVectorPrint(1, (psVector *) y, "y");
+    }
+    psS32 n = y->n;
+    psF32 *u = (psF32 *) psAlloc(n * sizeof(psF32));
+    psF32 *derivs2 = (psF32 *) psAlloc(n * sizeof(psF32));
+    psF32 *X = (psF32 *) & (x->data.F32[0]);
+    psF32 *Y = (psF32 *) & (y->data.F32[0]);
+    //
+    // The second derivatives at the endpoints, undefined in the SDR,
+    // are set in psAssert.h: PS_LEFT_SPLINE_DERIV, PS_RIGHT_SPLINE_DERIV.
+    //
+    derivs2[0] = -0.5;
+    u[0]= (3.0/(X[1]-X[0])) * ((Y[1]-Y[0])/(X[1]-X[0]) - PS_LEFT_SPLINE_DERIV);
+
+    for (psS32 i=1;i<=(n-2);i++) {
+        psF32 sig = (X[i] - X[i-1]) / (X[i+1] - X[i-1]);
+        psF32 p = sig * derivs2[i-1] + 2.0;
+        derivs2[i] = (sig - 1.0) / p;
+        u[i] = ((Y[i+1] - Y[i])/(X[i+1]-X[i])) - ((Y[i]-Y[i-1])/(X[i]-X[i-1]));
+        u[i] = ((6.0 * u[i] / (X[i+1] - X[i-1])) - (sig * u[i-1])) / p;
+
+        psTrace("psLib.math", 6, "X[%d] is %f\n", i, X[i]);
+        psTrace("psLib.math", 6, "Y[%d] is %f\n", i, Y[i]);
+        psTrace("psLib.math", 6, "u[%d] is %f\n", i, u[i]);
+    }
+
+    psF32 qn = 0.5;
+    u[n-1] = (3.0/(X[n-1]-X[n-2])) * (PS_RIGHT_SPLINE_DERIV - (Y[n-1]-Y[n-2])/(X[n-1]-X[n-2]));
+    derivs2[n-1] = (u[n-1] - (qn * u[n-2])) / ((qn * derivs2[n-2]) + 1.0);
+
+    for (psS32 k=(n-2);k>=0;k--) {
+        derivs2[k] = derivs2[k] * derivs2[k+1] + u[k];
+        psTrace("psLib.math", 6, "derivs2[%d] is %f\n", k, derivs2[k]);
+    }
+    psFree(u);
+    psTrace("psLib.math", 4, "---- %s() end ----\n", __func__);
+    return(derivs2);
+}
+
+
+/*****************************************************************************/
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+/*****************************************************************************/
+
+bool psMemCheckSpline1D(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)spline1DFree );
+}
+
+psSpline1D *psSpline1DAlloc()
+{
+    psSpline1D *tmpSpline = (psSpline1D *) psAlloc(sizeof(psSpline1D));
+    tmpSpline->n = 0;
+    tmpSpline->spline = NULL;
+    tmpSpline->knots = NULL;
+    tmpSpline->p_psDeriv2 = NULL;
+    psMemSetDeallocator(tmpSpline, (psFreeFunc) spline1DFree);
+
+    return(tmpSpline);
+}
+
+/*****************************************************************************
+psVectorFitSpline1D(): given a set of x/y vectors, this routine generates the
+linear or cublic splines which satisfy those data points.
+ 
+The formula for calculating the spline polynomials is derived from Numerical
+Recipes in C.  The basic idea is that the polynomial is
+ (1)     y = (A * y[0]) +
+ (2)         (B * y[1]) +
+ (3)         ((((A*A*A)-A) * mySpline->p_psDeriv2[0]) * H^2)/6.0 +
+ (4)         ((((B*B*B)-B) * mySpline->p_psDeriv2[1]) * H^2)/6.0
+Where:
+ H = x[1]-x[0]
+ A = (x[1]-x)/H
+ B = (x-x[0])/H
+The bulk of the code in this routine is the expansion of the above equation
+into a polynomial in terms of x, and then saving the coefficients of the
+powers of x in the spline polynomials.  This gets pretty complicated.
+ 
+XXX: What types must be supported?
+ *****************************************************************************/
+psSpline1D *psVectorFitSpline1D(
+    const psVector* x,                  ///< Ordinates.
+    const psVector* y)                  ///< Coordinates.
+{
+    psTrace("psLib.math", 3, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL);
+    PS_ASSERT_LONG_LARGER_THAN_OR_EQUAL(y->n, (long)2, NULL);
+    psS32 numSplines = (y->n)-1;
+    psTrace("psLib.math", 5, "numSplines is %d\n", numSplines);
+
+    //
+    // Create the psSpline1D struct.
+    //
+    psSpline1D *spline = psSpline1DAlloc();
+    spline->n = numSplines;
+    spline->spline = (psPolynomial1D **) psAlloc(numSplines * sizeof(psPolynomial1D *));
+    for (psS32 i=0;i<numSplines;i++) {
+        spline->spline[i] = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 3);
+    }
+
+    //
+    // The following code ensures that xPtr and yPtr points to a psF32 psVector.
+    //
+    // XXX: Use the vector copy and create routines here:
+    //
+
+    spline->knots = psVectorAlloc(y->n, PS_TYPE_F32);
+    if (x != NULL) {
+        PS_ASSERT_VECTOR_NON_NULL(x, NULL);
+        PS_ASSERT_VECTORS_SIZE_EQUAL(x, y, NULL);
+        PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, NULL);
+        if (x->type.type == PS_TYPE_F32) {
+            for (psS32 i = 0 ; i < x->n ; i++) {
+                spline->knots->data.F32[i] = x->data.F32[i];
+            }
+        } else if (x->type.type == PS_TYPE_F64) {
+            for (psS32 i = 0 ; i < x->n ; i++) {
+                spline->knots->data.F32[i] = (psF32) x->data.F64[i];
+            }
+        }
+    } else {
+        for (psS32 i = 0 ; i < y->n ; i++) {
+            spline->knots->data.F32[i] = (psF32) i;
+        }
+    }
+    psVector *xPtr = spline->knots;
+
+    psVector *yPtr = NULL;
+    // Convert y to F32 if necessary.
+    if (PS_TYPE_F64 == y->type.type) {
+        yPtr = psVectorCopy(NULL, y, PS_TYPE_F32);
+    } else {
+        yPtr = (psVector *) y;
+    }
+
+    //
+    // Generate the second derivatives at each data point.
+    //
+    spline->p_psDeriv2 = calculateSecondDerivs(xPtr, yPtr);
+
+    //
+    // We generate the coefficients of the spline polynomials.  I can't
+    // concisely explain how this code works.  See above function comments
+    // and Numerical Recipes in C.
+    //
+    for (psS32 i=0 ; i < numSplines ; i++) {
+        psF32 H = xPtr->data.F32[i+1] - xPtr->data.F32[i];
+        if (fabs(H) <= FLT_EPSILON) {
+            psError(PS_ERR_UNKNOWN, false, "x data points are not distinct (%d %d) (%f %f).\n",
+                    i, i+1, xPtr->data.F32[i], xPtr->data.F32[i+1]);
+        }
+        psTrace("psLib.math", 6, "x data (%f - %f) (%f)\n", xPtr->data.F32[i], xPtr->data.F32[i+1], H);
+        //
+        // ******** Calculate 0-order term ********
+        //
+        // From (1)
+        spline->spline[i]->coeff[0] = yPtr->data.F32[i] * xPtr->data.F32[i+1]/H;
+        // From (2)
+        spline->spline[i]->coeff[0]-= (yPtr->data.F32[i+1] * xPtr->data.F32[i])/H;
+        // From (3)
+        psF32 tmp = (xPtr->data.F32[i+1] * xPtr->data.F32[i+1] * xPtr->data.F32[i+1]) / (H * H * H);
+        tmp-= xPtr->data.F32[i+1] / H;
+        tmp*= spline->p_psDeriv2[i] * H * H / 6.0;
+        spline->spline[i]->coeff[0]+= tmp;
+        // From (4)
+        tmp = -(xPtr->data.F32[i] * xPtr->data.F32[i] * xPtr->data.F32[i]) / (H * H * H);
+        tmp+= xPtr->data.F32[i] / H;
+        tmp*= spline->p_psDeriv2[i+1] * H * H / 6.0;
+        spline->spline[i]->coeff[0]+= tmp;
+
+        //
+        // ******** Calculate 1-order term ********
+        //
+        // From (1)
+        spline->spline[i]->coeff[1] = -(yPtr->data.F32[i]) / H;
+        // From (2)
+        spline->spline[i]->coeff[1]+= yPtr->data.F32[i+1] / H;
+        // From (3)
+        tmp = -3.0 * xPtr->data.F32[i+1] * xPtr->data.F32[i+1] / (H * H * H);
+        tmp+= (1.0 / H);
+        tmp*= spline->p_psDeriv2[i] * H * H / 6.0;
+        spline->spline[i]->coeff[1]+= tmp;
+        // From (4)
+        tmp = 3.0 * xPtr->data.F32[i] * xPtr->data.F32[i] / (H * H * H);
+        tmp-= 1.0 / H;
+        tmp*= spline->p_psDeriv2[i+1] * H * H / 6.0;
+        spline->spline[i]->coeff[1]+= tmp;
+
+        //
+        // ******** Calculate 2-order term ********
+        //
+        // From (3)
+        spline->spline[i]->coeff[2] = spline->p_psDeriv2[i] * 3.0 * xPtr->data.F32[i+1] / (6.0 * H);
+        // From (4)
+        spline->spline[i]->coeff[2]-= spline->p_psDeriv2[i+1] * 3.0 * xPtr->data.F32[i] / (6.0 * H);
+
+        //
+        // ******** Calculate 3-order term ********
+        //
+        // From (3)
+        spline->spline[i]->coeff[3] = -spline->p_psDeriv2[i] / (6.0 * H);
+        // From (4)
+        spline->spline[i]->coeff[3]+=  spline->p_psDeriv2[i+1] / (6.0 * H);
+
+        psTrace("psLib.math", 6, "(spline->spline[%u])->coeff[0] is %f\n", i, spline->spline[i]->coeff[0]);
+        psTrace("psLib.math", 6, "(spline->spline[%u])->coeff[1] is %f\n", i, spline->spline[i]->coeff[1]);
+        psTrace("psLib.math", 6, "(spline->spline[%u])->coeff[2] is %f\n", i, spline->spline[i]->coeff[2]);
+        psTrace("psLib.math", 6, "(spline->spline[%u])->coeff[3] is %f\n", i, spline->spline[i]->coeff[3]);
+    }
+
+    if (PS_TYPE_F64 == y->type.type) {
+        psFree(yPtr);
+    }
+    psTrace("psLib.math", 3, "---- %s() end ----\n", __func__);
+    return(spline);
+}
+
+
+/*****************************************************************************
+psSpline1DEval(): this routine takes an existing spline of arbitrary order
+and an independent x value.  It determines which spline that x corresponds
+to by doing a bracket disection on the knots of the spline data structure
+(vectorBinDisectF32()).  Then it evaluates the spline at that x location
+by a call to the 1D polynomial functions.
+ 
+XXX: The spline eval functions require input and output to be F32.  however
+     the spline fit functions require F32 and F64.
+ 
+XXX: This only works if spline->knots if psF32.  Must we add support for psU32 and
+psF64?
+ *****************************************************************************/
+float psSpline1DEval(
+    const psSpline1D *spline,
+    float x)
+{
+    psTrace("psLib.math", 3, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_PTR_NON_NULL(spline, NAN);
+    PS_ASSERT_INT_NONNEGATIVE(spline->n, NAN);
+    PS_ASSERT_VECTOR_TYPE(spline->knots, PS_TYPE_F32, NAN);
+
+    psS32 n = spline->n;
+    if ((x < spline->knots->data.F32[0]) || (x > spline->knots->data.F32[spline->knots->n-1])) {
+        // If x is outside the range of spline->knots, generate a warning
+        // message, then return the left, or right, endpoint.
+        psLogMsg(__func__, PS_LOG_WARN,
+                 "psSpline1DEval(): x ordinate (%f) is outside the spline range (%f - %f) (%d).",
+                 x, spline->knots->data.F32[0], spline->knots->data.F32[n-1], n);
+
+        psS32 binNum = (x < spline->knots->data.F32[0]) ? 0 : n-1;
+        psTrace("psLib.math", 3, "---- %s() end ----\n", __func__);
+        return(psPolynomial1DEval(spline->spline[binNum], x));
+    }
+
+    psScalar tmpScalar;
+    tmpScalar.type.type = PS_TYPE_F32;
+    tmpScalar.data.F32 = x;
+    psVectorBinaryDisectResult result;
+    psS32 binNum = psVectorBinaryDisect(&result, spline->knots, &tmpScalar);
+    if (result != PS_BINARY_DISECT_PASS) {
+        psError(PS_ERR_UNKNOWN, false, "Could not perform bin dissection on spline->knots.\n");
+        return(NAN);
+    }
+
+    psTrace("psLib.math", 3, "---- %s() end ----\n", __func__);
+    return(psPolynomial1DEval(spline->spline[binNum], x));
+}
+
+
+/*****************************************************************************
+ *****************************************************************************/
+psVector *psSpline1DEvalVector(
+    const psSpline1D *spline,
+    const psVector *x)
+{
+    psTrace("psLib.math", 3, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_PTR_NON_NULL(spline, NULL);
+    PS_ASSERT_VECTOR_TYPE(spline->knots, PS_TYPE_F32, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(x, NULL);
+    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, NULL);
+    if (psTraceGetLevel("psLib.math") >= 6) {
+        PS_VECTOR_PRINT_F32(x);
+        PS_PRINT_SPLINE2((psSpline1D *) spline);
+    }
+
+    psVector *tmpVector = psVectorAlloc(x->n, PS_TYPE_F32);
+    if (x->type.type == PS_TYPE_F32) {
+        for (psS32 i=0;i<x->n;i++) {
+            tmpVector->data.F32[i] = psSpline1DEval(spline, x->data.F32[i]);
+        }
+    } else if (x->type.type == PS_TYPE_F64) {
+        for (psS32 i=0;i<x->n;i++) {
+            tmpVector->data.F32[i] = psSpline1DEval(spline, (psF32) x->data.F64[i]);
+        }
+    }
+
+    psTrace("psLib.math", 3, "---- %s() end ----\n", __func__);
+    return(tmpVector);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psSpline.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psSpline.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psSpline.h	(revision 22158)
@@ -0,0 +1,111 @@
+/* @file psSpline.h
+ * @brief Standard Mathematical Functions.
+ *
+ * This file will hold the prototypes for procedures which allocate, free,
+ * and evaluate splines.
+ *
+ * @author GLG, MHPCC
+ *
+ * @version $Revision: 1.62 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-08-09 01:40:07 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_SPLINE_H
+#define PS_SPLINE_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <float.h>
+#include <math.h>
+
+#include "psVector.h"
+#include "psScalar.h"
+#include "psPolynomial.h"
+
+#define PS_LEFT_SPLINE_DERIV 0.0
+#define PS_RIGHT_SPLINE_DERIV 0.0
+
+/** One-Dimensional Spline */
+typedef struct
+{
+    unsigned int n;                    ///< The number of spline pieces
+    psPolynomial1D **spline;           ///< An array of n pointers to the spline polynomials
+    psVector *knots;                   ///< The boundaries between each spline piece.  Size is n+1.
+    psF32 *p_psDeriv2;                 ///< For cubic splines, the second derivative at each domain point.  Size is n+1.
+}
+psSpline1D;
+
+/** Allocates a psSpline1D structure
+ *
+ *  Allocator for psSpline1D.
+ *
+ *  @return psSpline1D*    new 1-D spline struct
+ */
+psSpline1D *psSpline1DAlloc() PS_ATTR_MALLOC;
+
+/** Evaluates 1-D spline polynomials at a specific coordinate.
+ *
+ *  @return float    result of spline polynomials evaluated at given location
+ */
+float psSpline1DEval(
+    const psSpline1D *spline,          ///< Coefficients for spline polynomials
+    float x                            ///< location at which to evaluate
+);
+
+/** Evaluates 1-D spline polynomials at a set of specific coordinates.
+ *
+ *  @return psVector*    results of spline polynomials evaluated at given locations
+ */
+psVector *psSpline1DEvalVector(
+    const psSpline1D *spline,          ///< Coefficients of spline polynomials
+    const psVector *x                  ///< locations at which to evaluate
+);
+
+/** Derive a one-dimensional spline fit.
+ *
+ *  Given a psSpline1D data structure and a set of x,y vectors, this routine
+ *  generates the linear splines which satisfy those data points.
+ *
+ *  @return psSpline1D*:  the calculated one-dimensional splines
+ */
+psSpline1D *psVectorFitSpline1D(
+    const psVector* x,                 ///< Ordinates (or NULL to just use the indices)
+    const psVector* y                  ///< Coordinates
+);
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psSpline1D structure, false otherwise.
+ */
+bool psMemCheckSpline1D(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+/*****************************************************************************
+    PS_SPLINE macros:
+*****************************************************************************/
+#define PS_ASSERT_SPLINE(NAME, RVAL) \
+if (false == psMemCheckSpline1D(NAME)) { \
+    psError(PS_ERR_BAD_PARAMETER_NULL, true, \
+            "Unallowable operation: argument %s is not a psSpline1D struct.\n",\
+            #NAME); \
+    return(RVAL); \
+} \
+
+#define PS_ASSERT_SPLINE_NON_NULL(NAME, RVAL) \
+if ((NAME) == NULL) { \
+    psError(PS_ERR_BAD_PARAMETER_NULL, true, \
+            "Unallowable operation: psSpline1D %s is NULL.", \
+            #NAME); \
+    return(RVAL); \
+} \
+
+
+/// @}
+#endif // #ifndef PS_SPLINE_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psStats.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psStats.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psStats.c	(revision 22158)
@@ -0,0 +1,2901 @@
+/** @file  psStats.c
+ *  \brief basic statistical operations
+ *  @ingroup Stat
+ *
+ *  This file will hold the definitions of the histogram and stats data
+ *  structures.  It also contains prototypes for procedures which operate
+ *  on those data structures.
+ *
+ *  @author GLG (MHPCC), EAM (IfA)
+ *
+ * XXX: Must do
+ * nSubsample points
+ * use ->min and ->max (PS_STAT_USE_RANGE)
+ *
+ *  @version $Revision: 1.227 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-12 21:08:14 $
+ *
+ *  Copyright 2006 IfA, University of Hawaii
+ */
+
+
+// Note: choice of return values in many places is quite grey.  For example, calculating the sample standard
+// deviation: here it's an error to get an array of size zero, but it's not an error to get an array of size
+// unity, even though the standard deviation is not defined in that case (NAN).
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <float.h>
+#include <math.h>
+#include <limits.h>
+#include <strings.h>
+
+/*****************************************************************************/
+/* INCLUDE FILES                                                             */
+/*****************************************************************************/
+#include "psMemory.h"
+#include "psAbort.h"
+//#include "psImage.h"
+#include "psVector.h"
+#include "psTrace.h"
+#include "psLogMsg.h"
+#include "psError.h"
+#include "psHistogram.h"
+#include "psStats.h"
+#include "psMinimizeLMM.h"
+#include "psMinimizePolyFit.h"
+#include "psPolynomial.h"
+#include "psAssert.h"
+#include "psMathUtils.h"
+#include "psList.h"
+#include "psString.h"
+
+
+
+/*****************************************************************************/
+/* DEFINE STATEMENTS                                                         */
+/*****************************************************************************/
+#define PS_GAUSS_WIDTH 3                // The width of the Gaussian smoothing.
+#define PS_CLIPPED_NUM_ITER_LB 1 // This corresponds to N in the ADD.
+#define PS_CLIPPED_NUM_ITER_UB 10
+#define PS_CLIPPED_SIGMA_LB 1.0
+#define PS_CLIPPED_SIGMA_UB 10.0
+#define PS_POLY_MEDIAN_MAX_ITERATIONS 30
+#define MASK_MARK 0x80   // bit to use internally to mark data as bad
+#define PS_ROBUST_MAX_ITERATIONS 20     // Maximum number of iterations for robust statistics
+
+#define PS_BIN_MIDPOINT(HISTOGRAM, BIN_NUM) \
+(0.5 * (HISTOGRAM->bounds->data.F32[(BIN_NUM)] + HISTOGRAM->bounds->data.F32[(BIN_NUM)+1]))
+
+// set the bin closest to the corresponding value.  if USE_END is +/- 1,
+// out-of-range saturates on lower/upper bin REGARDLESS of actual value
+#define PS_BIN_FOR_VALUE(RESULT, VECTOR, VALUE, USE_END) { \
+        psVectorBinaryDisectResult result; \
+        psScalar tmpScalar; \
+        tmpScalar.type.type = PS_TYPE_F32; \
+        tmpScalar.data.F32 = (VALUE); \
+        RESULT = psVectorBinaryDisect (&result, VECTOR, &tmpScalar); \
+        switch (result) { \
+          case PS_BINARY_DISECT_PASS: \
+            break; \
+          case PS_BINARY_DISECT_OUTSIDE_RANGE: \
+            psTrace ("psLib.math", 6, "selected bin outside range"); \
+            if (USE_END == -1) { RESULT = 0; } \
+            if (USE_END == +1) { RESULT = VECTOR->n - 1; } \
+            break; \
+          case PS_BINARY_DISECT_INVALID_INPUT: \
+          case PS_BINARY_DISECT_INVALID_TYPE: \
+            psAbort ("programming error"); \
+            break; \
+        } }
+
+# define PS_BIN_INTERPOLATE(RESULT, VECTOR, BOUNDS, BIN, VALUE) { \
+        float dX, dY, Xo, Yo, Xt; \
+        if (BIN == BOUNDS->n - 1) { \
+            dX = 0.5*(BOUNDS->data.F32[BIN+1] - BOUNDS->data.F32[BIN-1]); \
+            dY = VECTOR->data.F32[BIN] - VECTOR->data.F32[BIN-1]; \
+            Xo = 0.5*(BOUNDS->data.F32[BIN+1] + BOUNDS->data.F32[BIN]); \
+            Yo = VECTOR->data.F32[BIN]; \
+        } else { \
+            dX = 0.5*(BOUNDS->data.F32[BIN+2] - BOUNDS->data.F32[BIN]); \
+            dY = VECTOR->data.F32[BIN+1] - VECTOR->data.F32[BIN]; \
+            Xo = 0.5*(BOUNDS->data.F32[BIN+1] + BOUNDS->data.F32[BIN]); \
+            Yo = VECTOR->data.F32[BIN]; \
+        } \
+        if (dY != 0) { \
+            Xt = (VALUE - Yo)*dX/dY + Xo; \
+        } else { \
+            Xt = Xo; \
+        } \
+        Xt = PS_MIN (BOUNDS->data.F32[BIN+1], PS_MAX(BOUNDS->data.F32[BIN], Xt)); \
+        psTrace("psLib.math", 6, "(Xo, Yo, dX, dY, Xt, Yt) is (%.2f %.2f %.2f %.2f %.2f %.2f)\n", \
+                Xo, Yo, dX, dY, Xt, VALUE); \
+        RESULT = Xt; }
+
+#define TRACE "psLib.math"
+
+/*****************************************************************************/
+/* TYPE DEFINITIONS                                                          */
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/* GLOBAL VARIABLES                                                          */
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/* FILE STATIC VARIABLES                                                     */
+/*****************************************************************************/
+
+// None
+
+/******************************************************************************
+MISC PRIVATE STATISTICAL FUNCTIONS
+
+NOTE: it is assumed that any call to these statistical functions will have
+been preceded by a call to the psVectorStats() function.  Various sanity tests
+will only be performed in psVectorStats().
+
+For many of these private stats routines, it is possible that there are no acceptable elements
+in the input vector (if no elements lie within range, or there are no unmasked elements, or the
+input vector is NULL).  In such cases, we set the desired value to NAN and return an error.
+The calling function may clear the error.
+*****************************************************************************/
+
+// static prototypes:
+static psF32 minimizeLMChi2Gauss1D(psVector *deriv, const psVector *params, const psVector *coords);
+// static psF32 fitQuadraticSearchForYThenReturnX(const psVector *xVec, psVector *yVec, psS32 binNum, psF32 yVal);
+static psF32 fitQuadraticSearchForYThenReturnXusingValues(const psVector *xVec, psVector *yVec, psS32 binNum, psF32 yVal);
+
+/******************************************************************************
+vectorSampleMean(myVector, maskVector, maskVal, stats): calculates the
+mean of the input vector.  If there was a problem with the mean calculation,
+this routine sets stats->sampleMean to NAN.
+
+using the method below, with a single loop for various options costs only a small amount and is
+much easier to debug. running 10000 tests of 1000 point vectors for the two methods gives:
+
+                     separate    single          w/errors
+(mask: 0, range: 0): 0.067 sec  0.073 sec (10%)  0.072 sec
+(mask: 1, range: 0): 0.098 sec  0.102 sec ( 4%)  0.119 sec
+(mask: 0, range: 0): 0.136 sec  0.162 sec (20%)  0.170 sec
+(mask: 1, range: 0): 0.177 sec  0.181 sec ( 2%)  0.198 sec
+
+(effect of errors not tested)
+
+To optmize this, use a macro and ifdef in or out the three states (errors, mask, range)
+*****************************************************************************/
+    static bool vectorSampleMean(const psVector* myVector,
+                                 const psVector* errors,
+                                 const psVector* maskVector,
+                                 psMaskType maskVal,
+                                 psStats* stats)
+{
+    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
+
+    long count = 0;                     // Number of points contributing to this mean
+    psF32 mean = 0.0;                   // The mean
+    psF32 weight;
+
+    psF32 *data = myVector->data.F32;   // Dereference
+    int numData = myVector->n;          // Number of data points
+
+    psU8 *maskData = (maskVector == NULL) ? NULL : maskVector->data.U8;
+    bool useRange = stats->options & PS_STAT_USE_RANGE;
+
+    psF32 sumWeights = 0.0;  // The sum of the weights
+    psF32 *errorsData = (errors == NULL) ? NULL : errors->data.F32;
+
+    for (long i = 0; i < numData; i++) {
+        // Check if the data is with the specified range
+        if (useRange && (data[i] < stats->min))
+            continue;
+        if (useRange && (data[i] > stats->max))
+            continue;
+        if (maskData && (maskData[i] & maskVal))
+            continue;
+        if (errors) {
+            weight = (errorsData[i] == 0) ? 0.0 : PS_SQR(errorsData[i]);
+            mean += data[i] * weight;
+            sumWeights += weight;
+        } else {
+            mean += data[i];
+        }
+        count++;
+    }
+    if (errors) {
+        mean = (count > 0) ? mean / sumWeights : NAN;
+    } else {
+        mean = (count > 0) ? mean / count : NAN;
+    }
+    stats->sampleMean = mean;
+    if (isnan(mean)) {
+        // XXX raise an error here?
+        psTrace(TRACE, 4, "---- %s(false) end ----\n", __func__);
+        return true;
+    }
+
+    stats->results |= PS_STAT_SAMPLE_MEAN;
+    psTrace(TRACE, 4, "---- %s(true) end ----\n", __func__);
+    return true;
+}
+
+/******************************************************************************
+vectorMinMax(myVector, maskVector, maskVal, stats): calculates the minimum and maximum of the input vector.
+If there was a problem with the calculation, this routine sets stats->max and stats->min to NAN.  Return the
+number of valid values in the vector (those not masked or outside the specified range).
+XXX : using the method below, with a single loop for various options
+      costs only a small amount and is much easier to debug. running 10000 tests
+      of 1000 point vectors for the two methods gives:
+                     separate    single
+(mask: 0, range: 0):  0.101 sec  0.149 sec
+(mask: 1, range: 0):  0.125 sec  0.160 sec
+(mask: 0, range: 0):  0.179 sec  0.208 sec
+(mask: 1, range: 0):  0.200 sec  0.244 sec
+*****************************************************************************/
+    static long vectorMinMax(const psVector* myVector,
+                             const psVector* maskVector,
+                             psMaskType maskVal,
+                             psStats* stats
+        )
+{
+    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
+    psF32 max = -PS_MAX_F32;            // The calculated maximum
+    psF32 min = PS_MAX_F32;             // The calculated minimum
+    psF32 *vector = myVector->data.F32; // Dereference the vector
+
+    int num = myVector->n;              // Number of values
+    int numValid = 0;                   // Number of valid values
+
+    psU8 *maskData = (maskVector == NULL) ? NULL : maskVector->data.U8;
+    bool useRange = stats->options & PS_STAT_USE_RANGE;
+
+    for (long i = 0; i < num; i++) {
+        // Check if the data is with the specified range
+        if (maskData && (maskData[i] & maskVal)) {
+            continue;
+        }
+
+        if (useRange) {
+            if (vector[i] < stats->min || vector[i] > stats->max) {
+                continue;
+            }
+        } else if (!isfinite(vector[i])) {
+            stats->max = stats->min = NAN;
+            psError(PS_ERR_IEEE, true, "Element %ld of vector is Inf/NaN", i);
+            return 0;
+        }
+
+        numValid++;
+        max = PS_MAX (vector[i], max);
+        min = PS_MIN (vector[i], min);
+    }
+
+    // XXX save numValid in psStats?
+    if (numValid == 0) {
+        stats->max = NAN;
+        stats->min = NAN;
+    } else {
+        stats->max = max;
+        stats->min = min;
+        stats->results |= PS_STAT_MIN;
+        stats->results |= PS_STAT_MAX;
+    }
+    psTrace(TRACE, 4, "---- %s(%d) end ----\n", __func__, numValid);
+    return numValid;
+}
+
+/******************************************************************************
+vectorSampleMedian(myVector, maskVector, maskVal, stats): calculates the median
+and quartiles of the input vector.  Returns true on success (including if there
+were no valid input vector elements). Expects F32 vector for input.
+*****************************************************************************/
+static bool vectorSampleMedian(const psVector* inVector,
+                               const psVector* maskVector,
+                               psMaskType maskVal,
+                               psStats* stats)
+{
+    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
+
+    bool useRange = stats->options & PS_STAT_USE_RANGE;
+    psU8 *maskData = (maskVector == NULL) ? NULL : maskVector->data.U8; // Dereference the vector
+    psF32 *input = inVector->data.F32; // Dereference the vector
+
+    // Allocate temporary vectors for the data.
+    psVector *outVector = psVectorAllocEmpty(inVector->n, PS_TYPE_F32); // Vector containing unmasked values
+    psF32 *output = outVector->data.F32; // Dereference the vector
+
+    long count = 0;                     // Number of valid entries
+
+    // Store all non-masked data points within the min/max range
+    // into the temporary vectors.
+    for (long i = 0; i < inVector->n; i++) {
+        if (useRange && (input[i] < stats->min))
+            continue;
+        if (useRange && (input[i] > stats->max))
+            continue;
+        if (maskData && (maskData[i] & maskVal))
+            continue;
+
+        output[count] = input[i];
+        count++;
+    }
+    outVector->n = count;
+
+    if (count == 0) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "No valid data in input vector.\n");
+        psFree(outVector);
+        stats->sampleUQ = NAN;
+        stats->sampleLQ = NAN;
+        stats->sampleMedian = NAN;
+        return true;
+    }
+
+    // Sort the temporary vector.
+    if (!psVectorSort(outVector, outVector)) { // Sort in-place (since it's a copy, it's OK)
+        psError(PS_ERR_UNEXPECTED_NULL, false, _("Failed to sort input data."));
+        stats->sampleUQ = NAN;
+        stats->sampleLQ = NAN;
+        stats->sampleMedian = NAN;
+        psFree(outVector);
+        return false;
+    }
+
+    // Calculate the median.  Use the average if the number of samples if even.
+    if (count % 2 == 0) {
+        stats->sampleMedian = 0.5 * (output[(count/2) - 1] + output[count/2]);
+    } else {
+        stats->sampleMedian = output[count/2];
+    }
+
+    // Calculate the quartile points exactly.
+    stats->sampleUQ = output[(int)(0.75*count)];
+    stats->sampleLQ = output[(int)(0.25*count)];
+
+    stats->results |= PS_STAT_SAMPLE_MEDIAN;
+    stats->results |= PS_STAT_SAMPLE_QUARTILE;
+
+    // Free the temporary data structures.
+    psFree(outVector);
+
+    // Return "true" on success.
+    psTrace(TRACE, 4, "---- %s(true) end ----\n", __func__);
+    return true;
+}
+
+/******************************************************************************
+vectorSampleStdev(myVector, maskVector, maskVal, stats): calculates the
+stdev of the input vector.
+Inputs
+    myVector
+    maskVector
+    maskVal
+    stats
+Returns
+    NULL
+
+using the method below, with a single loop for various options costs only a small amount and is
+much easier to debug.
+*****************************************************************************/
+
+static bool vectorSampleStdev(const psVector* myVector,
+                              const psVector* errors,
+                              const psVector* maskVector,
+                              psMaskType maskVal,
+                              psStats* stats)
+{
+    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
+
+    // This procedure requires the mean.  If it has not been already
+    // calculated, then call vectorSampleMean()
+    if (!(stats->results & PS_STAT_SAMPLE_MEAN)) {
+        vectorSampleMean(myVector, errors, maskVector, maskVal, stats);
+    }
+
+    // If the mean is NAN, then generate a warning and set the stdev to NAN.
+    if (isnan(stats->sampleMean)) {
+        psTrace(TRACE, 5, "WARNING: vectorSampleStdev(): sample mean is NAN.  "
+                "Setting stats->sampleStdev = NAN.\n");
+        stats->sampleStdev = NAN;
+        return true;
+    }
+
+    psF32 *data = myVector->data.F32;   // Dereference
+    psU8 *maskData = (maskVector == NULL) ? NULL : maskVector->data.U8;
+    bool useRange = stats->options & PS_STAT_USE_RANGE;
+    psF32 *errorsData = (errors == NULL) ? NULL : errors->data.F32;
+
+    // Accumulate the sums
+    double mean = stats->sampleMean;    // The mean
+    double sumSquares = 0.0;            // Sum of the squares
+    double sumDiffs = 0.0;              // Sum of the differences
+    double errorDivisor = 0.0;          // Division for errors
+    long count = 0;                     // Number of data points being used
+    for (long i = 0; i < myVector->n; i++) {
+        // Check if the data is with the specified range
+        if (useRange && (data[i] < stats->min)) {
+            continue;
+        }
+        if (useRange && (data[i] > stats->max)) {
+            continue;
+        }
+        if (maskData && (maskData[i] & maskVal)) {
+            continue;
+        }
+
+        double diff = data[i] - mean;
+        sumSquares += PS_SQR(diff);
+        sumDiffs += diff;
+        count++;
+        if (errors) {
+            errorDivisor += 1.0 / PS_SQR(errorsData[i]);
+        }
+    }
+
+    if (count == 0) {
+        // This is an ambiguous case: error or not?
+        // It's not an empty array (that's been asserted on previously), but everything's been masked out.
+        // Assume that the user knows what he's doing when he masks out everything --> no error.
+        stats->sampleStdev = NAN;
+        psTrace(TRACE, 5, "WARNING: vectorSampleStdev(): no valid psVector elements (%ld).  "
+                "Setting stats->sampleStdev = NAN.\n", count);
+        return true;
+    }
+    if (count == 1) {
+        stats->sampleStdev = 0.0;
+        psTrace(TRACE, 5, "WARNING: vectorSampleStdev(): only one valid psVector elements (%ld).  "
+                "Setting stats->sampleStdev = 0.0.\n", count);
+        return true;
+    }
+
+    if (errors) {
+        stats->sampleStdev = (1.0 / sqrtf(errorDivisor));
+    } else {
+        stats->sampleStdev = sqrt((sumSquares - (sumDiffs * sumDiffs / (float)count)) / (float)(count - 1));
+    }
+    stats->results |= PS_STAT_SAMPLE_STDEV;
+
+    psTrace(TRACE, 4, "---- %s() end ----\n", __func__);
+
+    return true;
+}
+
+static bool vectorSampleMoments(const psVector* myVector,
+                                const psVector* maskVector,
+                                psMaskType maskVal,
+                                psStats* stats)
+{
+    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
+
+    // This procedure requires the mean and standard deviation
+    if (!(stats->results & PS_STAT_SAMPLE_MEAN)) {
+        vectorSampleMean(myVector, NULL, maskVector, maskVal, stats);
+    }
+    if (isnan(stats->sampleMean)) {
+        psTrace(TRACE, 5, "WARNING: vectorSampleMoments(): sample mean is NAN.\n");
+        goto SAMPLE_MOMENTS_BAD;
+    }
+    if (!(stats->results & PS_STAT_SAMPLE_STDEV)) {
+        vectorSampleStdev(myVector, NULL, maskVector, maskVal, stats);
+    }
+    if (isnan(stats->sampleStdev) || stats->sampleStdev == 0.0) {
+        psTrace(TRACE, 5, "WARNING: vectorSampleMoments(): sample stdev is NAN or 0.\n");
+        goto SAMPLE_MOMENTS_BAD;
+    }
+
+    psF32 *data = myVector->data.F32;   // Dereference
+    psU8 *maskData = (maskVector == NULL) ? NULL : maskVector->data.U8;
+    bool useRange = stats->options & PS_STAT_USE_RANGE;
+
+    // Accumulate the sums
+    double mean = stats->sampleMean;    // The mean
+    double sum3 = 0.0;                  // Sum of the cubes of the differences
+    double sum4 = 0.0;                  // Sum of the fourth powers of the differences
+    long count = 0;                     // Number of data points being used
+    for (long i = 0; i < myVector->n; i++) {
+        // Check if the data is with the specified range
+        if (useRange && (data[i] < stats->min)) {
+            continue;
+        }
+        if (useRange && (data[i] > stats->max)) {
+            continue;
+        }
+        if (maskData && (maskData[i] & maskVal)) {
+            continue;
+        }
+
+        double diff = data[i] - mean;   // Difference from the mean
+        double temp;                    // Temporary variable for accumulating
+
+        sum3 += temp = PS_SQR(diff);
+        sum4 += temp * diff;
+
+        count++;
+    }
+
+    psAssert(count > 1, "impossible");                  // It should be, because we have a mean and standard deviation
+
+    double stdev = stats->sampleStdev;  // Standard deviation
+    double variance = PS_SQR(stdev);    // Variance
+
+    // Formula for skewness and kurtosis from Numerical Recipes in C, p 613.
+    // Note that we are defining the kurtosis relative to a normal distribution (hence the -3.0).
+    stats->sampleSkewness = sum3 / (count * variance * stdev);
+    stats->sampleKurtosis = sum4 / (count * PS_SQR(variance)) - 3.0;
+    stats->results |= PS_STAT_SAMPLE_SKEWNESS | PS_STAT_SAMPLE_KURTOSIS;
+
+    psTrace(TRACE, 4, "---- %s() end ----\n", __func__);
+
+    return true;
+
+ SAMPLE_MOMENTS_BAD:
+    // stats->sampleStdev has already been set
+    stats->sampleSkewness = NAN;
+    stats->sampleKurtosis = NAN;
+    stats->results |= PS_STAT_SAMPLE_SKEWNESS | PS_STAT_SAMPLE_KURTOSIS;
+    return true;
+}
+
+/******************************************************************************
+vectorClippedStats(myVector, errors, maskInput, maskValInput, stats): calculates the
+clipped stats (mean or stdev) of the input vector.
+
+Inputs
+    myVector
+    maskInput
+    maskValInput
+    stats
+Returns
+    true for success; false otherwise
+*****************************************************************************/
+static bool vectorClippedStats(const psVector* myVector,
+                               const psVector* errors,
+                               psVector* maskInput,
+                               psMaskType maskValInput,
+                               psStats* stats
+    )
+{
+    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
+    psTrace(TRACE, 4, "Trace level is %d\n", psTraceGetLevel("psLib.math"));
+
+    // Ensure that stats->clipIter is within the proper range.
+    PS_ASSERT_INT_WITHIN_RANGE(stats->clipIter,
+                               PS_CLIPPED_NUM_ITER_LB,
+                               PS_CLIPPED_NUM_ITER_UB, -1);
+
+    // Ensure that stats->clipSigma is within the proper range.
+    PS_ASSERT_FLOAT_WITHIN_RANGE(stats->clipSigma,
+                                 PS_CLIPPED_SIGMA_LB,
+                                 PS_CLIPPED_SIGMA_UB, -1);
+
+    // unless we succeed, these will have NAN values
+    stats->clippedMean = NAN;
+    stats->clippedStdev = NAN;
+    stats->clippedNvalues = 0;
+
+    // We copy the mask vector, to preserve the original
+    psMaskType maskVal = MASK_MARK | maskValInput;
+    psVector *tmpMask = psVectorAlloc(myVector->n, PS_TYPE_U8);
+    psVectorInit(tmpMask, 0);
+    if (maskInput) {
+        for (long i = 0; i < myVector->n; i++) {
+            if (maskInput->data.U8[i] & maskValInput) {
+                tmpMask->data.U8[i] = maskVal;
+            }
+        }
+    }
+
+    // 1. Compute the sample median, which we save for output
+    vectorSampleMedian(myVector, tmpMask, maskVal, stats);
+    if (isnan(stats->sampleMedian)) {
+        psTrace(TRACE, 5, "Call to vectorSampleMedian returned NAN\n");
+        psTrace(TRACE, 4, "---- %s(false) end ----\n", __func__);
+        psFree(tmpMask);
+        return false;
+    }
+    psTrace(TRACE, 6, "The initial sample median is %f\n", stats->sampleMedian);
+
+    // 2. Compute the sample standard deviation, which we save for output
+    vectorSampleStdev(myVector, errors, tmpMask, maskVal, stats);
+    if (isnan(stats->sampleStdev)) {
+        psTrace(TRACE, 5, "Call to vectorSampleStdev returned NAN\n");
+        psTrace(TRACE, 4, "---- %s(false) end ----\n", __func__);
+        psFree(tmpMask);
+        return false;
+    }
+    psTrace(TRACE, 6, "The initial sample stdev is %f\n", stats->sampleStdev);
+
+    // 3. Use the sample median as the first estimator of the mean X.
+    psF32 clippedMean = stats->sampleMedian;
+
+    // 4. Use the sample stdev as the first estimator of the mean stdev.
+    psF32 clippedStdev = stats->sampleStdev;
+
+    // 5. Repeat N (stats->clipIter) times:
+    long numClipped = 0;                // Number of values clipped
+    bool clipped = true;                // Have we clipped anything in this iteration
+    for (int iter = 0; iter < stats->clipIter && clipped; iter++) {
+        clipped = false;
+        psTrace(TRACE, 6, "------------ Iteration %d ------------\n", iter);
+        // a) Exclude all values x_i for which |x_i - x| > K * stdev
+        if (errors) {
+            // XXXX if we convert errors to variance, this should square the other terms (A*A faster than
+            // sqrt(A))
+            for (long j = 0; j < myVector->n; j++) {
+                if (!tmpMask->data.U8[j] &&
+                    fabsf(myVector->data.F32[j] - clippedMean) > stats->clipSigma * errors->data.F32[j]) {
+                    tmpMask->data.U8[j] = 0xff;
+                    psTrace(TRACE, 10, "Clipped %ld: %f +/- %f\n", j,
+                            myVector->data.F32[j], errors->data.F32[j]);
+                    numClipped++;
+                    clipped = true;
+                }
+            }
+        } else {
+            for (long j = 0; j < myVector->n; j++) {
+                if (!tmpMask->data.U8[j] &&
+                    fabsf(myVector->data.F32[j] - clippedMean) > (stats->clipSigma * clippedStdev)) {
+                    tmpMask->data.U8[j] = 0xff;
+                    psTrace(TRACE, 10, "Clipped %ld: %f\n", j, myVector->data.F32[j]);
+                    numClipped++;
+                    clipped = true;
+                }
+            }
+        }
+
+        // b) compute new mean and stdev
+        // Allocate a psStats structure for calculating the mean and stdev.
+        psStats *statsTmp = psStatsAlloc(PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
+        vectorSampleMean(myVector, errors, tmpMask, maskVal, statsTmp);
+        vectorSampleStdev(myVector, errors, tmpMask, maskVal, statsTmp);
+        psTrace(TRACE, 6, "The new sample mean is %f\n", statsTmp->sampleMean);
+        psTrace(TRACE, 6, "The new sample stdev is %f\n", statsTmp->sampleStdev);
+
+        // If the new mean and stdev are NAN, we must exit the loop.
+        // Otherwise, use the new results and continue.
+        if (isnan(statsTmp->sampleMean) || isnan(statsTmp->sampleStdev)) {
+            // Exit loop.
+            iter = stats->clipIter;
+            psError(PS_ERR_UNKNOWN, true, "vectorSampleMean() or vectorSampleStdev() returned a NAN.\n");
+            psFree(tmpMask);
+            return false;
+        } else {
+            clippedMean = statsTmp->sampleMean;
+            clippedStdev = statsTmp->sampleStdev;
+        }
+        psFree(statsTmp);
+    }
+
+    // Number of values used in calculation is the total number of data values, minus those we clipped
+    stats->clippedNvalues = myVector->n - numClipped;
+
+    // 7. The last calcuated value of x is the clipped mean.
+    // 8. The last calcuated value of stdev is the clipped stdev.
+    // we always return both stats even if only one was requested
+    stats->clippedMean = clippedMean;
+    stats->clippedStdev = clippedStdev;
+
+    stats->results |= PS_STAT_CLIPPED_MEAN;
+    stats->results |= PS_STAT_CLIPPED_STDEV;
+
+    psTrace(TRACE, 6, "The final clipped mean is %f\n", clippedMean);
+    psTrace(TRACE, 6, "The final clipped stdev is %f\n", clippedStdev);
+
+    psFree(tmpMask);
+    psTrace(TRACE, 4, "---- %s(true) end ----\n", __func__);
+    return true;
+}
+
+/******************************************************************************
+vectorRobustStats(myVector, maskInput, maskValInput, stats): This is the new
+version of the robust stats routine.
+
+XXX: MUST DO: If the errors in the input values are known, then the same
+approach is used, except that the histograms become probability density
+functions (PDFs). In this case, the input values are spread out, so that they
+do not simply contribute a single unit to the histogram, but rather contribute
+a fraction of a value, equivalent to the weight. In the interests of speed, a
+boxcar PDF may be used to represent each input value (as opposed to a
+Gaussian), where the boxcar width is equal to 2p2 ln 2 times the error and
+each input value contributes constant area. Then the robust median and
+standard deviation are estimated in the same manner as above.
+
+XXX: Check for errors in psLib routines that we call.
+
+XXX: Review and ensure that all memory is free'ed at premature exits.
+*****************************************************************************/
+#define INITIAL_NUM_BINS 1000.0
+static bool vectorRobustStats(const psVector* myVector,
+                              const psVector* errors,
+                              psVector* maskInput,
+                              psMaskType maskValInput,
+                              psStats* stats)
+{
+    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
+    if (psTraceGetLevel("psLib.math") >= 8) {
+        PS_VECTOR_PRINT_F32(myVector);
+    }
+
+    // we need to generate an internal mask and maskVal which ensures a bit is set
+    // and tested even if there is no supplied mask (and/or the maskVal is 0)
+    // XXX this would be better if we had globally defined mask values
+    psMaskType maskVal = MASK_MARK | maskValInput;
+    psVector *mask = psVectorAlloc(myVector->n, PS_TYPE_MASK); // The actual mask we will use
+    psVectorInit(mask, 0);
+    if (maskInput) {
+        for (long i = 0; i < myVector->n; i++) {
+            if (maskInput->data.U8[i] & maskValInput) {
+                mask->data.U8[i] = maskVal;
+            }
+        }
+    }
+
+    // statsMinMax is only applied to a subset of the data points
+    psStats *statsMinMax = psStatsAlloc(PS_STAT_MIN | PS_STAT_MAX); // Statistics for min and max
+    psHistogram *histogram = NULL;      // Histogram of the data
+    psHistogram *cumulative = NULL;     // Cumulative histogram of the data
+    float min = NAN, max = NAN;         // Mimimum and maximum values
+    float sigma = NAN;                  // The robust standard deviation
+    long totalDataPoints = 0;           // Total number of (unmasked) data points
+
+    float binSize = 0.0;            // Size of bins for histogram
+    long binLo, binHi;
+    long binL2, binH2;
+    long binL4, binH4;
+    long binMedian;
+
+    // Iterate to get the best bin size; an iteration limit is enforced at the bottom of the loop.
+    for (int iterate = 1; iterate > 0; iterate++) {
+        psTrace(TRACE, 6,
+                "-------------------- Iterating on Bin size.  Iteration number %d --------------------\n",
+                iterate);
+
+        // Get the minimum and maximum values
+        int numValid = vectorMinMax(myVector, mask, maskVal, statsMinMax); // Number of valid values
+        min = statsMinMax->min;
+        max = statsMinMax->max;
+        if (numValid == 0 || isnan(min) || isnan(max)) {
+            // Data range calculation failed
+            psError(PS_ERR_UNKNOWN, false, "Failed to calculate the min/max of the input vector.\n");
+            goto escape;
+        }
+        psTrace(TRACE, 6, "Data min/max is (%.2f, %.2f)\n", min, max);
+
+        // If all data points have the same value, then we set the appropriate members of stats and return.
+        if (fabs(max - min) <= FLT_EPSILON) {
+            stats->robustMedian = min;
+            stats->robustStdev = 0.0;
+            stats->robustUQ = min;
+            stats->robustLQ = min;
+            stats->robustN50 = numValid;
+            stats->results |= PS_STAT_ROBUST_MEDIAN;
+            stats->results |= PS_STAT_ROBUST_STDEV;
+            stats->results |= PS_STAT_ROBUST_QUARTILE;
+            psTrace(TRACE, 5, "All data points have the same value: %f.\n", min);
+            psTrace(TRACE, 4, "---- %s(0) end  ----\n", __func__);
+            psFree(mask);
+            psFree(statsMinMax);
+            return true;
+        }
+
+        if ((iterate == 1) && (stats->options & PS_STAT_USE_BINSIZE)) {
+            // Set initial bin size to the specified value.
+            binSize = stats->binsize;
+            psTrace(TRACE, 6, "Setting initial robust bin size to %.2f\n", binSize);
+        } else {
+            // Determine the bin size of the robust histogram, using the pre-defined number of bins
+            binSize = (max - min) / INITIAL_NUM_BINS;
+        }
+        psTrace(TRACE, 6, "Initial robust bin size is %.2f\n", binSize);
+
+        // ADD step 0: Construct the histogram with the specified bin size.  NOTE: we can not specify the bin
+        // size precisely since the argument to psHistogramAlloc() is the number of bins, not the binSize.  If
+        // we get here, we know that binSize != 0.0.
+        long numBins = (max - min) / binSize; // Number of bins
+        psTrace(TRACE, 6, "Numbins is %ld\n", numBins);
+        psTrace(TRACE, 6, "Creating a robust histogram from data range (%.2f - %.2f)\n", min, max);
+        // Generate the histogram
+        histogram = psHistogramAlloc(min, max, numBins);
+        // XXXXX we need to consider this step if errors -> variance
+        if (!psVectorHistogram(histogram, myVector, errors, mask, maskVal)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to generate histogram for robust statistics.\n");
+            goto escape;
+        }
+        if (psTraceGetLevel("psLib.math") >= 8) {
+            PS_VECTOR_PRINT_F32(histogram->bounds);
+            PS_VECTOR_PRINT_F32(histogram->nums);
+        }
+
+        // ADD step 1: Convert the specific histogram to a cumulative histogram
+        // The cumulative histogram data points correspond to the UPPER bound value (N < Bin[i+1])
+        cumulative = psHistogramAlloc(min, max, numBins);
+        cumulative->nums->data.F32[0] = histogram->nums->data.F32[0];
+        for (long i = 1; i < histogram->nums->n; i++) {
+            cumulative->nums->data.F32[i] = cumulative->nums->data.F32[i-1] + histogram->nums->data.F32[i];
+            cumulative->bounds->data.F32[i-1] = histogram->bounds->data.F32[i];
+        }
+        if (psTraceGetLevel("psLib.math") >= 8) {
+            PS_VECTOR_PRINT_F32(cumulative->bounds);
+            PS_VECTOR_PRINT_F32(cumulative->nums);
+        }
+
+        // ADD step 2: Find the bin which contains the 50% data point.
+        totalDataPoints = cumulative->nums->data.F32[numBins - 1];
+        psTrace(TRACE, 6, "Total data points is %ld\n", totalDataPoints);
+
+        // find bin which is the lower bound of median (value[binMedian] < median < value[binMedian+1]
+        PS_BIN_FOR_VALUE(binMedian, cumulative->nums, totalDataPoints/2.0, 0);
+
+        psTrace(TRACE, 6, "The median bin is %ld (%.2f to %.2f)\n", binMedian,
+                cumulative->bounds->data.F32[binMedian], cumulative->bounds->data.F32[binMedian+1]);
+
+        // ADD step 3: Interpolate to the exact 50% position: this is the robust histogram median.
+        stats->robustMedian = fitQuadraticSearchForYThenReturnXusingValues(cumulative->bounds, cumulative->nums, binMedian, totalDataPoints/2.0);
+        if (isnan(stats->robustMedian)) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Failed to fit a quadratic and calculate the 50-percent position.\n");
+            goto escape;
+        }
+        psTrace(TRACE, 6, "Current robust median is %f\n", stats->robustMedian);
+
+        // ADD step 4: Find the bins which contains the 15.8655% (-1 sigma) and 84.1345% (+1 sigma) data
+        // points also find the 30.8538% (-0.5 sigma) and 69.1462% (+0.5 sigma) points
+        PS_BIN_FOR_VALUE(binLo, cumulative->nums, totalDataPoints * 0.158655f, 0);
+        PS_BIN_FOR_VALUE(binHi, cumulative->nums, totalDataPoints * 0.841345f, 0);
+        PS_BIN_FOR_VALUE(binL2, cumulative->nums, totalDataPoints * 0.308538f, 0);
+        PS_BIN_FOR_VALUE(binH2, cumulative->nums, totalDataPoints * 0.691462f, 0);
+        PS_BIN_FOR_VALUE(binL4, cumulative->nums, totalDataPoints * 0.022481f, 0);
+        PS_BIN_FOR_VALUE(binH4, cumulative->nums, totalDataPoints * 0.977519f, 0);
+
+        psTrace(TRACE, 6, "The 15.8655%% and 84.1345%% data point bins are (%ld, %ld).\n",
+                binLo, binHi);
+        psTrace(TRACE, 6, "binLo midpoint is %f\n", PS_BIN_MIDPOINT(cumulative, binLo));
+        psTrace(TRACE, 6, "binHi midpoint is %f\n", PS_BIN_MIDPOINT(cumulative, binHi));
+        psTrace(TRACE, 6, "binL2 midpoint is %f\n", PS_BIN_MIDPOINT(cumulative, binL2));
+        psTrace(TRACE, 6, "binH2 midpoint is %f\n", PS_BIN_MIDPOINT(cumulative, binH2));
+
+        if ((binLo < 0) || (binHi < 0)) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to calculate the 15.8655%% and 84.1345%% data points.\n");
+            goto escape;
+        }
+
+        // ADD step 4b: Interpolate Sigma (linearly) to find these two positions exactly: these are the 1sigma
+        // positions.
+        psTrace(TRACE, 6, "binLo is %ld.  Nums at that bin and the next are (%.2f, %.2f)\n",
+                binLo, cumulative->nums->data.F32[binLo], cumulative->nums->data.F32[binLo+1]);
+        psTrace(TRACE, 6, "binHi is %ld.  Nums at that bin and the next are (%.2f, %.2f)\n",
+                binHi, cumulative->nums->data.F32[binHi], cumulative->nums->data.F32[binHi+1]);
+
+        // find the +0.5 and -0.5 sigma points with linear interpolation.  binLo and binHi are the bins
+        // containing the value of interest.  constrain the answer to be within the current bin.
+        // (extrapolation should not be needed and will result in errors)
+        float binLoF32, binHiF32, binL2F32, binH2F32, binL4F32, binH4F32;
+        PS_BIN_INTERPOLATE (binLoF32, cumulative->nums, cumulative->bounds, binLo,
+                            totalDataPoints * 0.158655f);
+        PS_BIN_INTERPOLATE (binHiF32, cumulative->nums, cumulative->bounds, binHi,
+                            totalDataPoints * 0.841345f);
+        PS_BIN_INTERPOLATE (binL2F32, cumulative->nums, cumulative->bounds, binL2,
+                            totalDataPoints * 0.308538f);
+        PS_BIN_INTERPOLATE (binH2F32, cumulative->nums, cumulative->bounds, binH2,
+                            totalDataPoints * 0.691462f);
+        PS_BIN_INTERPOLATE (binL4F32, cumulative->nums, cumulative->bounds, binL4,
+                            totalDataPoints * 0.022481f);
+        PS_BIN_INTERPOLATE (binH4F32, cumulative->nums, cumulative->bounds, binH4,
+                            totalDataPoints * 0.977519f);
+
+        // report +/- 1 sigma points
+        psTrace(TRACE, 5,
+                "The exact 15.8655 and 84.1345 percent data point positions are: (%f, %f)\n",
+                binLoF32, binHiF32);
+        psTrace(TRACE, 5,
+                "The exact 30.8538 and 69.1462 percent data point positions are: (%f, %f)\n",
+                binL2F32, binH2F32);
+        psTrace(TRACE, 5,
+                "The exact 02.22481 and 97.7519 percent data point positions are: (%f, %f)\n",
+                binL4F32, binH4F32);
+
+        // ADD step 5: Determine SIGMA as the distance between binL2 and binH2 (+/- 0.5 sigma)
+        float sigma1 = (binH2F32 - binL2F32);
+        float sigma2 = (binHiF32 - binLoF32) / 2.0;
+        float sigma4 = (binH4F32 - binL4F32) / 4.0;
+
+        // take the smallest of the three: if we have a clump with wide outliers, sigma2 and
+        // sigma4 will be biased high; if we have a bi-modal distribution, sigma1 and sigma2
+        // will be biased high.
+        sigma = PS_MIN (sigma1, PS_MIN (sigma2, sigma4));
+
+        psTrace(TRACE, 6, "The 1x sigma is %f.\n", sigma1);
+        psTrace(TRACE, 6, "The 2x sigma is %f.\n", sigma2);
+        psTrace(TRACE, 6, "The 4x sigma is %f.\n", sigma4);
+
+        psTrace(TRACE, 6, "The current sigma is %f.\n", sigma);
+        stats->robustStdev = sigma;
+
+        // ADD step 6: If the measured SIGMA is less than 2 times the bin size, exclude points which are more
+        // than 25 bins from the median, recalculate the bin size, and perform the algorithm again.
+        if (sigma < (3.0 * binSize)) {
+            psTrace(TRACE, 6, "*************: Do another iteration (%f %f).\n", sigma, binSize);
+            long maskLo = PS_MAX(0, (binMedian - 25)); // Low index for masking region
+            long maskHi = PS_MIN(histogram->bounds->n - 1, (binMedian + 25)); // High index for masking
+            psF32 medianLo = histogram->bounds->data.F32[maskLo]; // Value at low index
+            psF32 medianHi = histogram->bounds->data.F32[maskHi]; // Value at high index
+            psTrace(TRACE, 6, "Masking data more than 25 bins from the median\n");
+            psTrace(TRACE, 6,
+                    "The median is at bin number %ld.  We mask bins outside the bin range (%ld:%ld)\n",
+                    binMedian, maskLo, maskHi);
+            psTrace(TRACE, 6, "Masking data outside (%f %f)\n", medianLo, medianHi);
+            for (long i = 0 ; i < myVector->n ; i++) {
+                if ((myVector->data.F32[i] < medianLo) || (myVector->data.F32[i] > medianHi)) {
+		    // XXXX is this correct?  is MASK_MARK safe?
+                    mask->data.U8[i] |= MASK_MARK;
+                    psTrace(TRACE, 6, "Masking element %ld is %f\n", i, myVector->data.F32[i]);
+                }
+            }
+
+            // Free the histograms; they will be recreated on the next iteration, with new bounds
+            psFree(histogram);
+            histogram = NULL;
+
+            psFree(cumulative);
+            cumulative = NULL;
+
+            if (iterate >= PS_ROBUST_MAX_ITERATIONS) {
+                // This occurs when a large number of the values are identical --- a bin size cannot be found
+                // that will spread out the distribution.  Therefore, set what we can, and fall over
+                // gracefully.
+                // stats->robustMedian has already been set
+                stats->robustStdev = sigma;
+                stats->robustUQ = stats->robustMedian;
+                stats->robustLQ = stats->robustMedian;
+                stats->robustN50 = numValid;
+                stats->results |= PS_STAT_ROBUST_MEDIAN;
+                stats->results |= PS_STAT_ROBUST_STDEV;
+                stats->results |= PS_STAT_ROBUST_QUARTILE;
+                psTrace(TRACE, 5, "Maximum number of iterations (%d) exceeded.", PS_ROBUST_MAX_ITERATIONS);
+                psTrace(TRACE, 4, "---- %s(0) end  ----\n", __func__);
+                psFree(mask);
+                psFree(statsMinMax);
+                return false;
+            }
+        } else {
+            // We've got the bin size correct now
+            psTrace(TRACE, 6, "*************: No more iteration.  sigma is %f\n", sigma);
+            iterate = -1;
+        }
+    }
+
+    // XXX test lines while studying algorithm errors
+    // fprintf (stderr, "robust stats test %7.1f +/- %7.1f : %4ld %4ld %4ld %4ld %4ld  : %f %f %f\n",
+    // stats->robustMedian, stats->robustStdev,
+    // binLo, binL2, binMedian, binH2, binHi, binSize, max, min);
+
+    // ADD step 7: Find the bins which contains the 25% and 75% data points.
+    long binLo25, binHi25;
+    PS_BIN_FOR_VALUE (binLo25, cumulative->nums, totalDataPoints * 0.25f, 0);
+    PS_BIN_FOR_VALUE (binHi25, cumulative->nums, totalDataPoints * 0.75f, 0);
+    psTrace(TRACE, 6, "The 25-percent and 75-precent data point bins are (%ld, %ld).\n", binLo25, binHi25);
+
+    // ADD step 8: Interpolate to find these two positions exactly: these are the upper and lower quartile
+    // positions.
+    psF32 binLo25F32 = fitQuadraticSearchForYThenReturnXusingValues(cumulative->bounds, cumulative->nums, binLo25, totalDataPoints * 0.25f);
+    psF32 binHi25F32 = fitQuadraticSearchForYThenReturnXusingValues(cumulative->bounds, cumulative->nums, binHi25, totalDataPoints * 0.75f);
+    if (isnan(binLo25F32) || isnan(binHi25F32)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "could not determine the robustUQ: fitQuadraticSearchForYThenReturnX() returned a NAN.\n");
+        goto escape;
+    }
+
+    stats->robustLQ = binLo25F32;
+    stats->robustUQ = binHi25F32;
+    psTrace(TRACE, 6, "The 25 and 75 percent data point exact positions are (%f, %f).\n",
+            binLo25F32, binHi25F32);
+    long N50 = 0;
+    for (long i = 0 ; i < myVector->n ; i++) {
+        if (!mask->data.U8[i] &&
+            (binLo25F32 <= myVector->data.F32[i]) && (binHi25F32 >= myVector->data.F32[i])) {
+            N50++;
+        }
+    }
+    stats->robustN50 = N50;
+    psTrace(TRACE, 6, "The robustN50 is %ld.\n", N50);
+
+    // Clean up
+    psFree(histogram);
+    psFree(cumulative);
+    psFree(statsMinMax);
+    psFree(mask);
+
+    stats->results |= PS_STAT_ROBUST_MEDIAN;
+    stats->results |= PS_STAT_ROBUST_STDEV;
+    stats->results |= PS_STAT_ROBUST_QUARTILE;
+
+    psTrace(TRACE, 4, "---- %s(0) end  ----\n", __func__);
+    return true;
+
+escape:
+    stats->robustMedian = NAN;
+    stats->robustStdev = NAN;
+    stats->robustUQ = NAN;
+    stats->robustLQ = NAN;
+    stats->robustN50 = 0;
+    stats->results |= PS_STAT_ROBUST_MEDIAN;
+    stats->results |= PS_STAT_ROBUST_STDEV;
+    stats->results |= PS_STAT_ROBUST_QUARTILE;
+
+    psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
+
+    psFree(histogram);
+    psFree(cumulative);
+    psFree(statsMinMax);
+    psFree(mask);
+
+    return false;
+}
+
+/*
+ * vectorFittedStats requires guess for fittedMean and fittedStdev
+ * robustN50 should also be set
+ */
+static bool vectorFittedStats (const psVector* myVector,
+                               const psVector* errors,
+                               psVector* mask,
+                               psMaskType maskVal,
+                               psStats* stats)
+{
+
+    // This procedure requires the mean.  If it has not been already
+    // calculated, then call vectorSampleMean()
+    if (!(stats->results & PS_STAT_ROBUST_MEDIAN)) {
+        vectorRobustStats(myVector, errors, mask, maskVal, stats);
+    }
+
+    // If the mean is NAN, then generate a warning and set the stdev to NAN.
+    if (isnan(stats->robustMedian)) {
+        stats->fittedStdev = NAN;
+        stats->fittedStdev = NAN;
+        psTrace(TRACE, 4, "---- %s() end ----\n", __func__);
+        return false;
+    }
+
+    float guessStdev = stats->robustStdev;  // pass the guess sigma
+    float guessMean = stats->robustMedian;  // pass the guess mean
+
+    psTrace(TRACE, 6, "The guess mean  is %f.\n", guessMean);
+    psTrace(TRACE, 6, "The guess stdev is %f.\n", guessStdev);
+
+    bool done = false;
+    for (int iteration = 0; !done && (iteration < 2); iteration ++) {
+        psStats *statsMinMax = psStatsAlloc(PS_STAT_MIN | PS_STAT_MAX); // Statistics for min and max
+
+        psF32 binSize = 1;
+        if (stats->options & PS_STAT_USE_BINSIZE) {
+            // Set initial bin size to the specified value.
+            binSize = stats->binsize;
+            psTrace(TRACE, 6, "Setting initial robust bin size to %.2f\n", binSize);
+        } else {
+            // construct a histogram with (sigma/10 < binsize < sigma)
+            // set roughly so that the lowest bins have about 2 cnts
+            // Nsmallest ~ N50 / (4*dN))
+            psF32 dN = PS_MAX (1, PS_MIN (10, stats->robustN50 / 8));
+            binSize = guessStdev / dN;
+        }
+
+        // Determine the min/max of the vector (which prior outliers masked out)
+        int numValid = vectorMinMax(myVector, mask, maskVal, statsMinMax); // Number of values
+        float min = statsMinMax->min;
+        float max = statsMinMax->max;
+        if (numValid == 0 || isnan(min) || isnan(max)) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to calculate the min/max of the input vector.\n");
+            psFree(statsMinMax);
+            psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
+            return false;
+        }
+
+        // Calculate the number of bins.
+        // XXX can we calculate the binMin, binMax **before** building this histogram?
+        long numBins = (max - min) / binSize;
+        psTrace(TRACE, 6, "The new min/max values are (%f, %f).\n", min, max);
+        psTrace(TRACE, 6, "The new bin size is %f.\n", binSize);
+        psTrace(TRACE, 6, "The numBins is %ld\n", numBins);
+
+        psHistogram *histogram = psHistogramAlloc(min, max, numBins); // A new histogram (without outliers)
+        if (!psVectorHistogram(histogram, myVector, errors, mask, maskVal)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to generate histogram for fitted statistics.\n");
+            psFree(histogram);
+            psFree(statsMinMax);
+            return false;
+        }
+        if (psTraceGetLevel("psLib.math") >= 8) {
+            PS_VECTOR_PRINT_F32(histogram->nums);
+        }
+
+        // Fit a Gaussian to the bins in the requested range about the guess mean
+        // min,max overrides clipSigma
+        psF32 maxFitSigma = 2.0;
+        if (isfinite(stats->clipSigma)) {
+            maxFitSigma = fabs(stats->clipSigma);
+        }
+        if (isfinite(stats->max)) {
+            maxFitSigma = fabs(stats->max);
+        }
+
+        psF32 minFitSigma = 2.0;
+        if (isfinite(stats->clipSigma)) {
+            minFitSigma = fabs(stats->clipSigma);
+        }
+        if (isfinite(stats->min)) {
+            minFitSigma = fabs(stats->min);
+        }
+
+        // select the min and max bins, saturating on the lower and upper end-points
+        long binMin, binMax;
+        PS_BIN_FOR_VALUE (binMin, histogram->bounds, guessMean - minFitSigma*guessStdev, 0);
+        PS_BIN_FOR_VALUE (binMax, histogram->bounds, guessMean + maxFitSigma*guessStdev, 0);
+
+        // Generate the variables that will be used in the Gaussian fitting
+        // XXX EAM : we should test / guarantee that there are at least 3 (right?) bins
+        psVector *y = psVectorAlloc((1 + (binMax - binMin)), PS_TYPE_F32); // Vector of coordinates
+        psArray *x = psArrayAlloc((1 + (binMax - binMin))); // Array of ordinates
+        for (long i = binMin, j = 0; i <= binMax ; i++, j++) {
+            y->data.F32[j] = histogram->nums->data.F32[i];
+            psVector *ordinate = psVectorAlloc(1, PS_TYPE_F32); // The ordinate value
+            ordinate->data.F32[0] = PS_BIN_MIDPOINT(histogram, i);
+            x->data[j] = ordinate;
+        }
+        if (psTraceGetLevel("psLib.math") >= 8) {
+            // XXX: Print the x array somehow.
+            PS_VECTOR_PRINT_F32(y);
+        }
+        psTrace(TRACE, 6, "The clipped numBins is %ld\n", y->n);
+        psTrace(TRACE, 6, "The clipped min is %f (%ld)\n", PS_BIN_MIDPOINT(histogram, binMin), binMin);
+        psTrace(TRACE, 6, "The clipped max is %f (%ld)\n", PS_BIN_MIDPOINT(histogram, binMax), binMax);
+
+        // Normalize y to [0.0:1.0] (since the psMinimizeLMChi2Gauss1D() functions is [0.0:1.0])
+        // XXX EAM : why not just fit the normalization as well??
+        p_psNormalizeVectorRange(y, 0.0, 1.0);
+
+        // Fit a Gaussian to the data.
+        psMinimization *minimizer = psMinimizationAlloc(100, 0.01); // The minimizer information
+        psVector *params = psVectorAlloc(2, PS_TYPE_F32); // Parameters for the Gaussian
+        // Initial guess for the mean (index 0) and var (index 1).
+        params->data.F32[0] = guessMean;
+        params->data.F32[1] = PS_SQR(guessStdev);
+        if (psTraceGetLevel("psLib.math") >= 8) {
+            PS_VECTOR_PRINT_F32(params);
+            PS_VECTOR_PRINT_F32(y);
+        }
+        if (!psMinimizeLMChi2(minimizer, NULL, params, NULL, x, y, NULL, minimizeLMChi2Gauss1D)) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to fit a gaussian to the robust histogram.\n");
+            psFree(params);
+            psFree(minimizer);
+            psFree(x);
+            psFree(y);
+            psFree(histogram);
+            psFree(statsMinMax);
+            psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
+            return false;
+        }
+        if (psTraceGetLevel("psLib.math") >= 8) {
+            PS_VECTOR_PRINT_F32(params);
+        }
+
+        guessMean = params->data.F32[0];
+        guessStdev = sqrt(params->data.F32[1]);
+        if (guessStdev > 0.75*stats->robustStdev) {
+            done = true;
+        }
+
+        // Clean up after fitting
+        psFree (params);
+        psFree (minimizer);
+        psFree (x);
+        psFree (y);
+        psFree (histogram);
+        psFree (statsMinMax);
+    }
+
+    // The fitted mean is the Gaussian mean.
+    stats->fittedMean = guessMean;
+    psTrace(TRACE, 6, "The fitted mean is %f.\n", stats->fittedMean);
+
+    // The fitted standard deviation
+    stats->fittedStdev = guessStdev;
+    psTrace(TRACE, 6, "The fitted stdev is %f.\n", stats->fittedStdev);
+
+    stats->results |= PS_STAT_FITTED_MEAN;
+    stats->results |= PS_STAT_FITTED_STDEV;
+
+    return true;
+}
+
+
+/********************
+ * vectorFittedStats_v2 requires guess for fittedMean and fittedStdev
+ * robustN50 should also be set
+ * gaussian fit is performed using 2D polynomial to ln(y)
+ ********************/
+static bool vectorFittedStats_v2 (const psVector* myVector,
+                                  const psVector* errors,
+                                  psVector* mask,
+                                  psMaskType maskVal,
+                                  psStats* stats)
+{
+
+    // This procedure requires the mean.  If it has not been already
+    // calculated, then call vectorSampleMean()
+    if (!(stats->results & PS_STAT_ROBUST_MEDIAN)) {
+        vectorRobustStats(myVector, errors, mask, maskVal, stats);
+    }
+
+    // If the mean is NAN, then generate a warning and set the stdev to NAN.
+    if (isnan(stats->robustMedian)) {
+        stats->fittedStdev = NAN;
+        stats->fittedStdev = NAN;
+        psTrace(TRACE, 4, "---- %s() end ----\n", __func__);
+        return false;
+    }
+
+    float guessStdev = stats->robustStdev;  // pass the guess sigma
+    float guessMean = stats->robustMedian;  // pass the guess mean
+
+    psTrace(TRACE, 6, "The ** starting ** guess mean  is %f.\n", guessMean);
+    psTrace(TRACE, 6, "The ** starting ** guess stdev is %f.\n", guessStdev);
+
+    bool done = false;
+    for (int iteration = 0; !done && (iteration < 2); iteration ++) {
+        psStats *statsMinMax = psStatsAlloc(PS_STAT_MIN | PS_STAT_MAX); // Statistics for min and max
+
+        psF32 binSize = 1;
+        if (stats->options & PS_STAT_USE_BINSIZE) {
+            // Set initial bin size to the specified value.
+            binSize = stats->binsize;
+            psTrace(TRACE, 6, "Setting initial robust bin size to %.2f\n", binSize);
+        } else {
+            // construct a histogram with (sigma/10 < binsize < sigma)
+            // set roughly so that the lowest bins have about 2 cnts
+            // Nsmallest ~ N50 / (4*dN))
+            psF32 dN = PS_MAX (1, PS_MIN (10, stats->robustN50 / 8));
+            binSize = guessStdev / dN;
+        }
+
+        // Determine the min/max of the vector (which prior outliers masked out)
+        int numValid = vectorMinMax(myVector, mask, maskVal, statsMinMax); // Number of values
+        float min = statsMinMax->min;
+        float max = statsMinMax->max;
+        if (numValid == 0 || isnan(min) || isnan(max)) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to calculate the min/max of the input vector.\n");
+            psFree(statsMinMax);
+            psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
+            return false;
+        }
+
+        // Calculate the number of bins.
+        // XXX can we calculate the binMin, binMax **before** building this histogram?
+        long numBins = (max - min) / binSize;
+        psTrace(TRACE, 6, "The new min/max values are (%f, %f).\n", min, max);
+        psTrace(TRACE, 6, "The new bin size is %f.\n", binSize);
+        psTrace(TRACE, 6, "The numBins is %ld\n", numBins);
+
+        psHistogram *histogram = psHistogramAlloc(min, max, numBins); // A new histogram (without outliers)
+        if (!psVectorHistogram(histogram, myVector, errors, mask, maskVal)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to generate histogram for fitted statistcs v2.\n");
+            psFree(histogram);
+            psFree(statsMinMax);
+            return false;
+        }
+        if (psTraceGetLevel("psLib.math") >= 8) {
+            PS_VECTOR_PRINT_F32(histogram->nums);
+        }
+
+        // Fit a Gaussian to the bins in the requested range about the guess mean
+        // min,max overrides clipSigma
+        psF32 maxFitSigma = 2.0;
+        if (isfinite(stats->clipSigma)) {
+            maxFitSigma = fabs(stats->clipSigma);
+        }
+        if (isfinite(stats->max)) {
+            maxFitSigma = fabs(stats->max);
+        }
+
+        psF32 minFitSigma = 2.0;
+        if (isfinite(stats->clipSigma)) {
+            minFitSigma = fabs(stats->clipSigma);
+        }
+        if (isfinite(stats->min)) {
+            minFitSigma = fabs(stats->min);
+        }
+
+        // select the min and max bins, saturating on the lower and upper end-points
+        long binMin, binMax;
+        PS_BIN_FOR_VALUE (binMin, histogram->bounds, guessMean - minFitSigma*guessStdev, 0);
+        PS_BIN_FOR_VALUE (binMax, histogram->bounds, guessMean + maxFitSigma*guessStdev, 0);
+
+        // Generate the variables that will be used in the Gaussian fitting
+        // XXX EAM : we should test / guarantee that there are at least 3 (right?) bins
+        psVector *y = psVectorAllocEmpty((1 + (binMax - binMin)), PS_TYPE_F32); // Vector of coordinates
+        psVector *x = psVectorAllocEmpty((1 + (binMax - binMin)), PS_TYPE_F32); // Vector of ordinates
+        long j = 0;
+        for (long i = binMin; i <= binMax ; i++) {
+            if (histogram->nums->data.F32[i] <= 0.0)
+                continue;
+            x->data.F32[j] = PS_BIN_MIDPOINT(histogram, i);
+            y->data.F32[j] = log(histogram->nums->data.F32[i]);
+            // XXX note this is the natural log: expected distribution is A exp(-(x-xo)^2/2sigma^2)
+            j++;
+        }
+        y->n = x->n = j;
+        if (psTraceGetLevel("psLib.math") >= 8) {
+            // XXX: Print the x array somehow.
+            PS_VECTOR_PRINT_F32(y);
+        }
+        psTrace(TRACE, 6, "The clipped numBins is %ld\n", y->n);
+        psTrace(TRACE, 6, "The clipped min is %f (%ld)\n", PS_BIN_MIDPOINT(histogram, binMin), binMin);
+        psTrace(TRACE, 6, "The clipped max is %f (%ld)\n", PS_BIN_MIDPOINT(histogram, binMax), binMax);
+
+        // fit 2nd order polynomial to ln(y) = -(x-xo)^2/2sigma^2
+        psPolynomial1D *poly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 2);
+
+        // XXX how can we protect against some extreme outliers?  the robust histogram
+        // should have already dealt with those, but we are again sensitive to them...
+        // psStats *fitStats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
+        // fitStats->clipIter = 3.0;
+        // fitStats->clipSigma = 3.0;
+        // psVector *fitMask = psVectorAlloc(y->n, PS_TYPE_U8);
+        // psVectorInit (fitMask, 0);
+
+        if (!psVectorFitPolynomial1D (poly, NULL, 0, y, NULL, x)) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to fit a gaussian to the robust histogram.\n");
+            psFree(x);
+            psFree(y);
+            psFree(poly);
+            psFree(histogram);
+            psFree(statsMinMax);
+            psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
+            return false;
+        }
+
+        if (poly->coeff[2] >= 0.0) {
+            psTrace(TRACE, 6, "Parabolic fit results: %f + %f x + %f x^2\n",
+                    poly->coeff[0], poly->coeff[1], poly->coeff[2]);
+            psError(PS_ERR_UNKNOWN, false, "fit did not converge\n");
+            psFree(x);
+            psFree(y);
+            psFree(poly);
+            psFree(histogram);
+            psFree(statsMinMax);
+            psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
+            return false;
+        }
+
+        guessStdev = sqrt(-0.5/poly->coeff[2]);
+        guessMean = poly->coeff[1]*PS_SQR(guessStdev);
+        if (guessStdev > 0.75*stats->robustStdev) {
+            done = true;
+        } else {
+            psTrace(TRACE, 6, "Parabolic fit results: %f + %f x + %f x^2\n",
+                    poly->coeff[0], poly->coeff[1], poly->coeff[2]);
+            psTrace(TRACE, 6, "The new guess mean  is %f.\n", guessMean);
+            psTrace(TRACE, 6, "The new guess stdev is %f.\n", guessStdev);
+        }
+
+        // Clean up after fitting
+        psFree (x);
+        psFree (y);
+        psFree (poly);
+        // psFree (fitStats);
+        // psFree (fitMask);
+        psFree (histogram);
+        psFree (statsMinMax);
+    }
+
+    // The fitted mean is the Gaussian mean.
+    stats->fittedMean = guessMean;
+    psTrace(TRACE, 6, "The fitted mean is %f.\n", stats->fittedMean);
+
+    // The fitted standard deviation
+    stats->fittedStdev = guessStdev;
+    psTrace(TRACE, 6, "The fitted stdev is %f.\n", stats->fittedStdev);
+
+    stats->results |= PS_STAT_FITTED_MEAN_V2;
+    stats->results |= PS_STAT_FITTED_STDEV_V2;
+
+    return true;
+}
+
+/********************
+ * perform an asymmetric fit to the population
+ * vectorFittedStats_v3 requires guess for fittedMean and fittedStdev
+ * robustN50 should also be set
+ * gaussian fit is performed using 2D polynomial to ln(y)
+ ********************/
+static bool vectorFittedStats_v3 (const psVector* myVector,
+                                  const psVector* errors,
+                                  psVector* mask,
+                                  psMaskType maskVal,
+                                  psStats* stats)
+{
+
+    // This procedure requires the mean.  If it has not been already
+    // calculated, then call vectorSampleMean()
+    if (!(stats->results & PS_STAT_ROBUST_MEDIAN)) {
+        vectorRobustStats(myVector, errors, mask, maskVal, stats);
+    }
+
+    // If the mean is NAN, then generate a warning and set the stdev to NAN.
+    if (isnan(stats->robustMedian)) {
+        stats->fittedStdev = NAN;
+        stats->fittedStdev = NAN;
+        psTrace(TRACE, 4, "---- %s() end ----\n", __func__);
+        return false;
+    }
+
+    float guessStdev = stats->robustStdev;  // pass the guess sigma
+    float guessMean = stats->robustMedian;  // pass the guess mean
+
+    psTrace(TRACE, 6, "The ** starting ** guess mean  is %f.\n", guessMean);
+    psTrace(TRACE, 6, "The ** starting ** guess stdev is %f.\n", guessStdev);
+
+    bool done = false;
+    for (int iteration = 0; !done && (iteration < 2); iteration ++) {
+        psStats *statsMinMax = psStatsAlloc(PS_STAT_MIN | PS_STAT_MAX); // Statistics for min and max
+
+        psF32 binSize = 1;
+        if (stats->options & PS_STAT_USE_BINSIZE) {
+            // Set initial bin size to the specified value.
+            binSize = stats->binsize;
+            psTrace(TRACE, 6, "Setting initial robust bin size to %.2f\n", binSize);
+        } else {
+            // construct a histogram with (sigma/2 < binsize < sigma)
+            // set roughly so that the lowest bins have about 2 cnts
+            // Nsmallest ~ N50 / (4*dN))
+            psF32 dN = PS_MAX (1, PS_MIN (4, stats->robustN50 / 8));
+            binSize = guessStdev / dN;
+        }
+
+        // Determine the min/max of the vector (which prior outliers masked out)
+        int numValid = vectorMinMax(myVector, mask, maskVal, statsMinMax); // Number of values
+        float min = statsMinMax->min;
+        float max = statsMinMax->max;
+        if (numValid == 0 || isnan(min) || isnan(max)) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to calculate the min/max of the input vector.\n");
+            psFree(statsMinMax);
+            psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
+            return false;
+        }
+
+        // Calculate the number of bins.
+        // XXX can we calculate the binMin, binMax **before** building this histogram?
+        long numBins = (max - min) / binSize;
+        psTrace(TRACE, 6, "The new min/max values are (%f, %f).\n", min, max);
+        psTrace(TRACE, 6, "The new bin size is %f.\n", binSize);
+        psTrace(TRACE, 6, "The numBins is %ld\n", numBins);
+
+        psHistogram *histogram = psHistogramAlloc(min, max, numBins); // A new histogram (without outliers)
+        if (!psVectorHistogram(histogram, myVector, errors, mask, maskVal)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to generate histogram for fitted statistics v3.\n");
+            psFree(histogram);
+            psFree(statsMinMax);
+            return false;
+        }
+        if (psTraceGetLevel("psLib.math") >= 8) {
+            PS_VECTOR_PRINT_F32(histogram->nums);
+        }
+
+        // now fit a Gaussian to the upper and lower halves about the peak independently
+
+        // set the full-range upper and lower limits
+        psF32 maxFitSigma = 2.0;
+        if (isfinite(stats->clipSigma)) {
+            maxFitSigma = fabs(stats->clipSigma);
+        }
+        if (isfinite(stats->max)) {
+            maxFitSigma = fabs(stats->max);
+        }
+
+        psF32 minFitSigma = 2.0;
+        if (isfinite(stats->clipSigma)) {
+            minFitSigma = fabs(stats->clipSigma);
+        }
+        if (isfinite(stats->min)) {
+            minFitSigma = fabs(stats->min);
+        }
+
+        // select the min and max bins, saturating on the lower and upper end-points
+        long binMin, binMax;
+        PS_BIN_FOR_VALUE (binMin, histogram->bounds, guessMean - minFitSigma*guessStdev, 0);
+        PS_BIN_FOR_VALUE (binMax, histogram->bounds, guessMean + maxFitSigma*guessStdev, 0);
+        if (binMin == binMax) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to calculate the min/max of the input vector.\n");
+            psFree(statsMinMax);
+            psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
+            return false;
+        }
+
+        // search for mode (peak of histogram within range mean-2sigma - mean+2sigma
+        long  binPeak = binMin;
+        float valPeak = histogram->nums->data.F32[binPeak];
+        for (int i = binMin; i < binMax; i++) {
+            if (histogram->nums->data.F32[i] > valPeak) {
+                binPeak = i;
+                valPeak = histogram->nums->data.F32[binPeak];
+            }
+            psTrace (TRACE, 6, "(%f = %.0f) ", histogram->bounds->data.F32[i], histogram->nums->data.F32[i]);
+        }
+        psTrace (TRACE, 6, "\n");
+
+        // assume a reasonably well-defined gaussian-like population; run from peak out until val < 0.25*peak
+
+        psTrace(TRACE, 6, "The clipped numBins is %ld\n", binMax - binMin);
+        psTrace(TRACE, 6, "The clipped min is %f (%ld)\n",
+                PS_BIN_MIDPOINT(histogram, binMin), binMin);
+        psTrace(TRACE, 6, "The clipped max is %f (%ld)\n",
+                PS_BIN_MIDPOINT(histogram, binMax - 1), binMax - 1);
+        psTrace(TRACE, 6, "The clipped peak is %f (%ld)\n",
+                PS_BIN_MIDPOINT(histogram, binPeak), binPeak);
+        psTrace(TRACE, 6, "The clipped peak value is %f\n", histogram->nums->data.F32[binPeak]);
+
+        {
+            // fit the lower half of the distribution
+            // run down until we drop below 0.25*valPeak
+            long binS = binMin;
+            long binE = PS_MIN (binPeak + 3, binMax);
+            for (int i = binPeak-3; i >= binMin; i--) {
+                if (histogram->nums->data.F32[i] < 0.25*valPeak) {
+                    binS = i;
+                    break;
+                }
+            }
+            psTrace(TRACE, 6, "Lower bound for lower half: %f (%ld)\n",
+                    PS_BIN_MIDPOINT(histogram, binS), binS);
+            psTrace(TRACE, 6, "Upper bound for lower half: %f (%ld)\n",
+                    PS_BIN_MIDPOINT(histogram, binE), binE);
+
+            psVector *y = psVectorAllocEmpty(binE - binS, PS_TYPE_F32); // Vector of coordinates
+            psVector *x = psVectorAllocEmpty(binE - binS, PS_TYPE_F32); // Vector of ordinates
+            long j = 0;
+            for (long i = binS; i < binE; i++) {
+                if (histogram->nums->data.F32[i] <= 0.0)
+                    continue;
+                x->data.F32[j] = PS_BIN_MIDPOINT(histogram, i);
+                // note this is the natural log: expected distribution is A exp(-(x-xo)^2/2sigma^2)
+                y->data.F32[j] = log(histogram->nums->data.F32[i]);
+                j++;
+            }
+            y->n = x->n = j;
+
+            // fit 2nd order polynomial to ln(y) = -(x-xo)^2/2sigma^2
+            psPolynomial1D *poly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 2);
+            bool status = psVectorFitPolynomial1D (poly, NULL, 0, y, NULL, x);
+            psFree(x);
+            psFree(y);
+
+            if (!status) {
+                psError(PS_ERR_UNKNOWN, false, "Failed to fit a gaussian to the robust histogram.\n");
+                psFree(poly);
+                psFree(histogram);
+                psFree(statsMinMax);
+                psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
+                return false;
+            }
+
+            if (poly->coeff[2] >= 0.0) {
+                psTrace(TRACE, 6, "Failed parabolic fit: %f + %f x + %f x^2\n",
+                        poly->coeff[0], poly->coeff[1], poly->coeff[2]);
+                psFree(poly);
+                psFree(histogram);
+                psFree(statsMinMax);
+
+                // sometimes, the guessStdev is much too large.  in this case, the entire real population
+                // tends to be found in a single bin.  make one attempt to recover by dropping the guessStdev
+                // down by a jump and trying again
+                if (iteration == 0) {
+                    guessStdev = 0.25*guessStdev;
+                    psTrace(TRACE, 6, "*** retry, new stdev is %f.\n", guessStdev);
+                    continue;
+                }
+
+                psError(PS_ERR_UNKNOWN, false, "fit did not converge\n");
+                psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
+                return false;
+            }
+
+            // calculate lower mean & stdev from parabolic fit -- use this as the result
+            guessStdev = sqrt(-0.5/poly->coeff[2]);
+            guessMean = poly->coeff[1]*PS_SQR(guessStdev);
+            if (guessStdev > 0.75*stats->robustStdev) {
+                done = true;
+            }
+            psTrace(TRACE, 6, "Parabolic Lower fit results: %f + %f x + %f x^2\n",
+                    poly->coeff[0], poly->coeff[1], poly->coeff[2]);
+            psTrace(TRACE, 6, "The lower mean  is %f.\n", guessMean);
+            psTrace(TRACE, 6, "The lower stdev is %f.\n", guessStdev);
+
+            psFree(poly);
+        }
+
+        // for test, measure the same result for the upper section
+        {
+            // fit the upper half of the distribution
+            // run up until we drop below 0.25*valPeak
+            long binS = PS_MAX (binPeak - 3, 0);
+            long binE = binMax;
+            for (int i = binPeak+3; i < binMax; i++) {
+                if (histogram->nums->data.F32[i] < 0.25*valPeak) {
+                    binE = i;
+                    break;
+                }
+            }
+            psTrace(TRACE, 6, "Lower bound for upper half: %f (%ld)\n",
+                    PS_BIN_MIDPOINT(histogram, binS), binS);
+            psTrace(TRACE, 6, "Upper bound for upper half: %f (%ld)\n",
+                    PS_BIN_MIDPOINT(histogram, binE), binE);
+
+            psVector *y = psVectorAllocEmpty(binE - binS, PS_TYPE_F32); // Vector of coordinates
+            psVector *x = psVectorAllocEmpty(binE - binS, PS_TYPE_F32); // Vector of ordinates
+            long j = 0;
+            for (long i = binS; i < binE; i++) {
+                if (histogram->nums->data.F32[i] <= 0.0)
+                    continue;
+                x->data.F32[j] = PS_BIN_MIDPOINT(histogram, i);
+                // note this is the natural log: expected distribution is A exp(-(x-xo)^2/2sigma^2)
+                y->data.F32[j] = log(histogram->nums->data.F32[i]);
+                j++;
+            }
+            y->n = x->n = j;
+
+            // fit 2nd order polynomial to ln(y) = -(x-xo)^2/2sigma^2
+            psPolynomial1D *poly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 2);
+            bool status = psVectorFitPolynomial1D (poly, NULL, 0, y, NULL, x);
+            psFree(x);
+            psFree(y);
+
+            if (!status) {
+                psError(PS_ERR_UNKNOWN, false, "Failed to fit a gaussian to the robust histogram.\n");
+                psFree(poly);
+                psFree(histogram);
+                psFree(statsMinMax);
+                psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
+                return false;
+            }
+
+            // calculate upper mean & stdev from parabolic fit -- ignore this value
+            float upperStdev = sqrt(-0.5/poly->coeff[2]);
+            float upperMean = poly->coeff[1]*PS_SQR(upperStdev);
+#ifndef PS_NO_TRACE
+            psTrace(TRACE, 6, "Parabolic Upper fit results: %f + %f x + %f x^2\n",
+                    poly->coeff[0], poly->coeff[1], poly->coeff[2]);
+            psTrace(TRACE, 6, "The upper mean  is %f.\n", upperMean);
+            psTrace(TRACE, 6, "The upper stdev is %f.\n", upperStdev);
+#endif
+
+            // if the resulting value is outside of the range binMin - binMax, use the upper value
+            if (done && (guessMean > PS_BIN_MIDPOINT(histogram, binMax - 1))) {
+                guessMean = upperMean;
+                guessStdev = upperStdev;
+            }
+
+            psFree (poly);
+        }
+
+        // Clean up after fitting
+        psFree (histogram);
+        psFree (statsMinMax);
+    }
+
+    // The fitted mean is the Gaussian mean.
+    stats->fittedMean = guessMean;
+    psTrace(TRACE, 6, "The fitted mean is %f.\n", stats->fittedMean);
+
+    // The fitted standard deviation
+    stats->fittedStdev = guessStdev;
+    psTrace(TRACE, 6, "The fitted stdev is %f.\n", stats->fittedStdev);
+
+    stats->results |= PS_STAT_FITTED_MEAN_V3;
+    stats->results |= PS_STAT_FITTED_STDEV_V3;
+
+    return true;
+}
+
+/********************
+ * perform an asymmetric fit to the population
+ * vectorFittedStats_v4 requires guess for fittedMean and fittedStdev
+ * robustN50 should also be set
+ * gaussian fit is performed using 2D polynomial to ln(y)
+ * this version follows the upper portion of the distribution until it passes 0.5*peak
+ ********************/
+static bool vectorFittedStats_v4 (const psVector* myVector,
+                                  const psVector* errors,
+                                  psVector* mask,
+                                  psMaskType maskVal,
+                                  psStats* stats)
+{
+
+    // This procedure requires the mean.  If it has not been already
+    // calculated, then call vectorSampleMean()
+    if (!(stats->results & PS_STAT_ROBUST_MEDIAN)) {
+        vectorRobustStats(myVector, errors, mask, maskVal, stats);
+    }
+
+    // If the mean is NAN, then generate a warning and set the stdev to NAN.
+    if (isnan(stats->robustMedian)) {
+        stats->fittedStdev = NAN;
+        stats->fittedStdev = NAN;
+        psTrace(TRACE, 4, "---- %s() end ----\n", __func__);
+        return false;
+    }
+
+    float guessStdev = stats->robustStdev;  // pass the guess sigma
+    float guessMean = stats->robustMedian;  // pass the guess mean
+
+    psTrace(TRACE, 6, "The ** starting ** guess mean  is %f.\n", guessMean);
+    psTrace(TRACE, 6, "The ** starting ** guess stdev is %f.\n", guessStdev);
+
+    bool done = false;
+    for (int iteration = 0; !done && (iteration < 2); iteration ++) {
+        psStats *statsMinMax = psStatsAlloc(PS_STAT_MIN | PS_STAT_MAX); // Statistics for min and max
+
+        psF32 binSize = 1;
+        if (stats->options & PS_STAT_USE_BINSIZE) {
+            // Set initial bin size to the specified value.
+            binSize = stats->binsize;
+            psTrace(TRACE, 6, "Setting initial robust bin size to %.2f\n", binSize);
+        } else {
+            // construct a histogram with (sigma/2 < binsize < sigma)
+            // set roughly so that the lowest bins have about 2 cnts
+            // Nsmallest ~ N50 / (4*dN))
+            psF32 dN = PS_MAX (1, PS_MIN (4, stats->robustN50 / 8));
+            binSize = guessStdev / dN;
+        }
+
+        // Determine the min/max of the vector (which prior outliers masked out)
+        int numValid = vectorMinMax(myVector, mask, maskVal, statsMinMax); // Number of values
+        float min = statsMinMax->min;
+        float max = statsMinMax->max;
+        if (numValid == 0 || isnan(min) || isnan(max)) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to calculate the min/max of the input vector.\n");
+            psFree(statsMinMax);
+            psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
+            return false;
+        }
+
+        // Calculate the number of bins.
+        // XXX can we calculate the binMin, binMax **before** building this histogram?
+        // if the range is too absurd, adjust numBins & binSize
+        long numBins = PS_MAX (50, PS_MIN (10000, (max - min) / binSize));
+        binSize = (max - min) / (float) numBins;
+        psTrace(TRACE, 6, "The new min/max values are (%f, %f).\n", min, max);
+        psTrace(TRACE, 6, "The new bin size is %f.\n", binSize);
+        psTrace(TRACE, 6, "The numBins is %ld\n", numBins);
+
+        psHistogram *histogram = psHistogramAlloc(min, max, numBins); // A new histogram (without outliers)
+        if (!psVectorHistogram(histogram, myVector, errors, mask, maskVal)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to generate histogram for fitted statistics v4.\n");
+            psFree(histogram);
+            psFree(statsMinMax);
+            return false;
+        }
+        if (psTraceGetLevel("psLib.math") >= 8) {
+            PS_VECTOR_PRINT_F32(histogram->nums);
+        }
+
+        // now fit a Gaussian to the upper and lower halves about the peak independently
+
+        // set the full-range upper and lower limits
+        psF32 maxFitSigma = 2.0;
+        if (isfinite(stats->clipSigma)) {
+            maxFitSigma = fabs(stats->clipSigma);
+        }
+        if (isfinite(stats->max)) {
+            maxFitSigma = fabs(stats->max);
+        }
+
+        psF32 minFitSigma = 2.0;
+        if (isfinite(stats->clipSigma)) {
+            minFitSigma = fabs(stats->clipSigma);
+        }
+        if (isfinite(stats->min)) {
+            minFitSigma = fabs(stats->min);
+        }
+
+        // select the min and max bins, saturating on the lower and upper end-points
+        long binMin, binMax;
+        PS_BIN_FOR_VALUE (binMin, histogram->bounds, guessMean - minFitSigma*guessStdev, 0);
+        PS_BIN_FOR_VALUE (binMax, histogram->bounds, guessMean + maxFitSigma*guessStdev, 0);
+        if (binMin == binMax) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to calculate the min/max of the input vector.\n");
+            psFree(statsMinMax);
+            psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
+            return false;
+        }
+
+        // search for mode (peak of histogram within range mean-2sigma - mean+2sigma
+        long  binPeak = binMin;
+        float valPeak = histogram->nums->data.F32[binPeak];
+        for (int i = binMin; i < binMax; i++) {
+            if (histogram->nums->data.F32[i] > valPeak) {
+                binPeak = i;
+                valPeak = histogram->nums->data.F32[binPeak];
+            }
+            psTrace (TRACE, 6, "(%f = %.0f) ", histogram->bounds->data.F32[i], histogram->nums->data.F32[i]);
+        }
+        psTrace (TRACE, 6, "\n");
+
+        // assume a reasonably well-defined gaussian-like population; run from peak out until val < 0.25*peak
+
+        psTrace(TRACE, 6, "The clipped numBins is %ld\n", binMax - binMin);
+        psTrace(TRACE, 6, "The clipped min is %f (%ld)\n", PS_BIN_MIDPOINT(histogram, binMin), binMin);
+        psTrace(TRACE, 6, "The clipped max is %f (%ld)\n",
+                PS_BIN_MIDPOINT(histogram, binMax - 1), binMax - 1);
+        psTrace(TRACE, 6, "The clipped peak is %f (%ld)\n", PS_BIN_MIDPOINT(histogram, binPeak), binPeak);
+        psTrace(TRACE, 6, "The clipped peak value is %f\n", histogram->nums->data.F32[binPeak]);
+
+        {
+            // fit the lower half of the distribution
+            // run down until we drop below 0.25*valPeak
+            // run up until we drop below 0.50*valPeak
+            long binS = binMin;
+            long binE = PS_MIN (binPeak + 3, binMax);
+            for (int i = binPeak - 3; i >= binMin; i--) {
+                if (histogram->nums->data.F32[i] < 0.25*valPeak) {
+                    binS = i;
+                    break;
+                }
+            }
+            for (int i = binPeak + 3; i < binMax; i++) {
+                if (histogram->nums->data.F32[i] < 0.50*valPeak) {
+                    binE = i;
+                    break;
+                }
+            }
+            psTrace(TRACE, 6, "Lower bound for lower half: %f (%ld)\n",
+                    PS_BIN_MIDPOINT(histogram, binS), binS);
+            psTrace(TRACE, 6, "Upper bound for lower half: %f (%ld)\n",
+                    PS_BIN_MIDPOINT(histogram, binE), binE);
+
+            psVector *y = psVectorAllocEmpty(binE - binS, PS_TYPE_F32); // Vector of coordinates
+            psVector *x = psVectorAllocEmpty(binE - binS, PS_TYPE_F32); // Vector of ordinates
+            long j = 0;
+            for (long i = binS; i < binE; i++) {
+                if (histogram->nums->data.F32[i] <= 0.0)
+                    continue;
+                x->data.F32[j] = PS_BIN_MIDPOINT(histogram, i);
+                // note this is the natural log: expected distribution is A exp(-(x-xo)^2/2sigma^2)
+                y->data.F32[j] = log(histogram->nums->data.F32[i]);
+                j++;
+            }
+            y->n = x->n = j;
+
+            // fit 2nd order polynomial to ln(y) = -(x-xo)^2/2sigma^2
+            psPolynomial1D *poly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 2);
+            bool status = psVectorFitPolynomial1D (poly, NULL, 0, y, NULL, x);
+            psFree(x);
+            psFree(y);
+
+            if (!status) {
+                psError(PS_ERR_UNKNOWN, false, "Failed to fit a gaussian to the robust histogram.\n");
+                psFree(poly);
+                psFree(histogram);
+                psFree(statsMinMax);
+                psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
+                return false;
+            }
+
+            if (poly->coeff[2] >= 0.0) {
+                psTrace(TRACE, 6, "Failed parabolic fit: %f + %f x + %f x^2\n",
+                        poly->coeff[0], poly->coeff[1], poly->coeff[2]);
+                psFree(poly);
+                psFree(histogram);
+                psFree(statsMinMax);
+
+                // sometimes, the guessStdev is much too large.  in this case, the entire real population
+                // tends to be found in a single bin.  make one attempt to recover by dropping the guessStdev
+                // down by a jump and trying again
+                if (iteration == 0) {
+                    guessStdev = 0.25*guessStdev;
+                    psTrace(TRACE, 6, "*** retry, new stdev is %f.\n", guessStdev);
+                    continue;
+                }
+
+                psError(PS_ERR_UNKNOWN, false, "fit did not converge\n");
+                psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
+                return false;
+            }
+
+            // calculate lower mean & stdev from parabolic fit -- use this as the result
+            guessStdev = sqrt(-0.5/poly->coeff[2]);
+            guessMean = poly->coeff[1]*PS_SQR(guessStdev);
+            if (guessStdev > 0.75*stats->robustStdev) {
+                done = true;
+            }
+            psTrace(TRACE, 6, "Parabolic Lower fit results: %f + %f x + %f x^2\n",
+                    poly->coeff[0], poly->coeff[1], poly->coeff[2]);
+            psTrace(TRACE, 6, "The lower mean  is %f.\n", guessMean);
+            psTrace(TRACE, 6, "The lower stdev is %f.\n", guessStdev);
+
+            psFree(poly);
+        }
+
+        // if we converge on a solution outside the range binMin - binMax, use a more conservative range
+        float minValue = PS_BIN_MIDPOINT(histogram, binMin);
+        float maxValue = PS_BIN_MIDPOINT(histogram, binMax - 1);
+
+        if (done && ((guessMean < minValue) || (guessMean > maxValue))) {
+            psTrace(TRACE, 6, "Inconsistent result, re-trying the fit\n");
+
+            // fit a symmetric distribution
+            // run up until we drop below 0.15*valPeak
+            // run up until we drop below 0.15*valPeak
+            long binS = binMin;
+            long binE = binMax;
+            for (int i = binPeak - 3; i >= binMin; i--) {
+                if (histogram->nums->data.F32[i] < 0.15*valPeak) {
+                    binS = i;
+                    break;
+                }
+            }
+            for (int i = binPeak + 3; i < binMax; i++) {
+                if (histogram->nums->data.F32[i] < 0.15*valPeak) {
+                    binE = i;
+                    break;
+                }
+            }
+            psTrace(TRACE, 6, "Lower bound for symmetric range: %f (%ld)\n",
+                    PS_BIN_MIDPOINT(histogram, binS), binS);
+            psTrace(TRACE, 6, "Upper bound for symmetric range: %f (%ld)\n",
+                    PS_BIN_MIDPOINT(histogram, binE), binE);
+
+            psVector *y = psVectorAllocEmpty(binE - binS, PS_TYPE_F32); // Vector of coordinates
+            psVector *x = psVectorAllocEmpty(binE - binS, PS_TYPE_F32); // Vector of ordinates
+            long j = 0;
+            for (long i = binS; i < binE; i++) {
+                if (histogram->nums->data.F32[i] <= 0.0)
+                    continue;
+                x->data.F32[j] = PS_BIN_MIDPOINT(histogram, i);
+                // note this is the natural log: expected distribution is A exp(-(x-xo)^2/2sigma^2)
+                y->data.F32[j] = log(histogram->nums->data.F32[i]);
+                j++;
+            }
+            y->n = x->n = j;
+
+            // fit 2nd order polynomial to ln(y) = -(x-xo)^2/2sigma^2
+            psPolynomial1D *poly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 2);
+            bool status = psVectorFitPolynomial1D (poly, NULL, 0, y, NULL, x);
+            psFree(x);
+            psFree(y);
+
+            if (!status) {
+                psError(PS_ERR_UNKNOWN, false, "Failed to fit a gaussian to the robust histogram.\n");
+                psFree(poly);
+                psFree(histogram);
+                psFree(statsMinMax);
+                psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
+                return false;
+            }
+
+            // calculate upper mean & stdev from parabolic fit -- ignore this value
+            guessStdev = sqrt(-0.5/poly->coeff[2]);
+            guessMean = poly->coeff[1]*PS_SQR(guessStdev);
+#ifndef PS_NO_TRACE
+            psTrace(TRACE, 6, "Parabolic Symmetric fit results: %f + %f x + %f x^2\n",
+                    poly->coeff[0], poly->coeff[1], poly->coeff[2]);
+            psTrace(TRACE, 6, "The symmetric mean  is %f.\n", guessMean);
+            psTrace(TRACE, 6, "The symmetric stdev is %f.\n", guessStdev);
+#endif
+
+            // if we converge on a solution outside the range binMin - binMax, use a more conservative range
+            float minValueSym = PS_BIN_MIDPOINT(histogram, binS);
+            float maxValueSym = PS_BIN_MIDPOINT(histogram, binE - 1);
+
+            // saturate on min or max value
+            if (guessMean < minValueSym) {
+                guessMean = minValueSym;
+                psTrace(TRACE, 6, "The symmetric mean is out of bounds, saturating to %f.\n", guessMean);
+            }
+
+            // saturate on min or max value
+            if (guessMean > maxValueSym) {
+                guessMean = maxValueSym;
+                psTrace(TRACE, 6, "The symmetric mean is out of bounds, saturating to %f.\n", guessMean);
+            }
+
+            psFree (poly);
+        }
+
+        // Clean up after fitting
+        psFree (histogram);
+        psFree (statsMinMax);
+    }
+
+    // The fitted mean is the Gaussian mean.
+    stats->fittedMean = guessMean;
+    psTrace(TRACE, 6, "The fitted mean is %f.\n", stats->fittedMean);
+
+    // The fitted standard deviation
+    stats->fittedStdev = guessStdev;
+    psTrace(TRACE, 6, "The fitted stdev is %f.\n", stats->fittedStdev);
+
+    stats->results |= PS_STAT_FITTED_MEAN_V4;
+    stats->results |= PS_STAT_FITTED_STDEV_V4;
+
+    return true;
+}
+
+
+/******************************************************************************
+vectorSmoothHistGaussian(): This routine smoothes the data in the input
+robustHistogram with a Gaussian of width sigma.  It returns a psVector of the
+smoothed data.
+
+XXX this function is unused
+*****************************************************************************/
+psVector *vectorSmoothHistGaussian(psHistogram *histogram,
+                                   psF32 sigma)
+{
+    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
+    psTrace(TRACE, 5, "(histogram->nums->n, sigma) is (%d, %.2f\n", (int) histogram->nums->n, sigma);
+    PS_ASSERT_PTR_NON_NULL(histogram, NULL);
+    PS_ASSERT_PTR_NON_NULL(histogram->bounds, NULL);
+    PS_ASSERT_PTR_NON_NULL(histogram->nums, NULL);
+    if (psTraceGetLevel("psLib.math") >= 8) {
+        PS_VECTOR_PRINT_F32(histogram->nums);
+    }
+
+    long numBins = histogram->nums->n;  // Number of histogram bins
+    psVector *smooth = psVectorAlloc(numBins, PS_TYPE_F32); // Smoothed version of histogram bins
+    const psVector *bounds = histogram->bounds; // The bounds for the histogram bins
+
+    if (!histogram->uniform) {
+        //
+        // We get here if the histogram is non-uniform.  This code is not tested.
+        // However, it is also not used anywhere, yet.
+        //
+        psWarning("WARNING: vectorSmoothHistGaussian() on non-uniform "
+                  "histograms has not been tested or used.\n");
+
+        for (long i = 0; i < numBins; i++) {
+            // Determine the midpoint of bin i.
+            float iMid = PS_BIN_MIDPOINT(histogram, i);
+
+            //
+            // We determine the bin numbers (jMin:jMax) corresponding to a
+            // range of data values surrounding iMid.  The range is of size:
+            // 2*PS_GAUSS_WIDTH*sigma
+            long jMin, jMax;
+            psF32 x = iMid - (PS_GAUSS_WIDTH * sigma);
+            for (jMin = i; jMin > 0 && bounds->data.F32[jMin] > x; jMin--)
+                ;
+            x = iMid + (PS_GAUSS_WIDTH * sigma);
+            for (jMax = i; jMax < bounds->n - 1 && bounds->data.F32[jMax + 1] > x; jMax++)
+                ;
+
+            //
+            // Loop from jMin to jMax, computing the gaussian of data i.
+            //
+            smooth->data.F32[i] = 0.0;
+            for (long j = jMin ; j <= jMax ; j++) {
+                float jMid = PS_BIN_MIDPOINT(histogram, j);
+                smooth->data.F32[i] +=
+                    histogram->nums->data.F32[j] * psGaussian(jMid, iMid, sigma, true);
+            }
+        }
+    } else {
+        //
+        // We get here if the histogram is uniform.
+        //
+        for (long i = 0; i < numBins; i++) {
+            psF32 binSize = bounds->data.F32[1] - bounds->data.F32[0];
+            psS32 gaussWidth = ((PS_GAUSS_WIDTH * sigma) / binSize);
+
+            //
+            // XXX: The following is wrong.  However, in practice, the sigma was too
+            // large compared to the binSize.  This meant that the smoothing was done
+            // over 500 bins in the robust stats algorithm.  This mean that the smoothing
+            // took way too long.
+            //
+#if 0
+
+            gaussWidth = 10;
+#endif
+            //
+            // We determine the bin numbers (jMin:jMax) corresponding to a
+            // range of data values surrounding iMid.  The range is of size:
+            // 2*PS_GAUSS_WIDTH*sigma
+            //
+            psS32 jMin = PS_MAX(i - gaussWidth, 0);
+            psS32 jMax = PS_MIN(i + gaussWidth, bounds->n - 1);
+
+            //
+            // Loop from jMin to jMax, computing the gaussian of data i.
+            //
+            smooth->data.F32[i] = 0.0;
+            float iMid = PS_BIN_MIDPOINT(histogram, i);
+            for (long j = jMin ; j <= jMax ; j++) {
+                float jMid = PS_BIN_MIDPOINT(histogram, j);
+                smooth->data.F32[i] +=
+                    histogram->nums->data.F32[j] * psGaussian(jMid, iMid, sigma, true);
+            }
+        }
+    }
+
+    if (psTraceGetLevel("psLib.math") >= 8) {
+        PS_VECTOR_PRINT_F32(smooth);
+    }
+    psTrace(TRACE, 4, "---- %s() end ----\n", __func__);
+    return(smooth);
+}
+
+/*****************************************************************************/
+
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+
+/*****************************************************************************/
+
+// We keep statsFree so that we can identify statistics pointers from the memblock
+static void statsFree(psStats *stats)
+{
+    // There are non dynamic allocated items
+    return;
+}
+
+/******************************************************************************
+    psStatsAlloc(): This routine must create a new psStats data structure.
+*****************************************************************************/
+psStats* p_psStatsAlloc(const char *file, unsigned int lineno, const char *func, psStatsOptions options)
+{
+    psTrace(TRACE, 3,"---- %s() begin  ----\n", __func__);
+
+    psStats *stats = p_psAlloc(file, lineno, func, sizeof(psStats));
+    psMemSetDeallocator(stats, (psFreeFunc)statsFree);
+
+    // set initial, default values
+    psStatsInit (stats);
+
+    // these values are can be set as desired by the user.  they are not affected by
+    // psStatsInit
+    stats->clipSigma = 3.0;
+    stats->clipIter = 3;
+    stats->nSubsample = 100000;
+    stats->options = options;
+
+    psTrace(TRACE, 3, "---- %s() end  ----\n", __func__);
+    return stats;
+}
+
+// reset the values which are output, and which may be used from one psStats stage to the next
+void psStatsInit(psStats *stats)
+{
+    stats->sampleMean = NAN;
+    stats->sampleMedian = NAN;
+    stats->sampleStdev = NAN;
+    stats->sampleUQ = NAN;
+    stats->sampleLQ = NAN;
+    stats->sampleSkewness = NAN;
+    stats->sampleKurtosis = NAN;
+    stats->robustMedian = NAN;
+    stats->robustStdev = NAN;
+    stats->robustUQ = NAN;
+    stats->robustLQ = NAN;
+    stats->robustN50 = -1;
+    stats->fittedMean = NAN;
+    stats->fittedStdev = NAN;
+    stats->fittedNfit = -1;
+    stats->clippedMean = NAN;
+    stats->clippedStdev = NAN;
+    stats->clippedNvalues = -1;     // XXX: This is never used
+    stats->min = NAN;
+    stats->max = NAN;
+    stats->binsize = NAN;
+    return;
+}
+
+
+bool psMemCheckStats(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)statsFree );
+}
+
+/******************************************************************************
+psVectorStats(in, mask, maskVal, stats): this is the public API
+function which calls the above private stats functions based on what bits
+were set in stats->options.
+
+Inputs
+    in
+    mask
+    maskVal
+    stats
+Returns
+    The stats structure.
+
+XXX: Should we free stats if the asserts fail? NO; we don't own it (RHL).
+*****************************************************************************/
+bool psVectorStats(psStats* stats,
+                   const psVector* in,
+                   const psVector* errors,
+                   const psVector* mask,
+                   psMaskType maskVal)
+{
+    psTrace(TRACE, 3,"---- %s() begin  ----\n", __func__);
+    PS_ASSERT_PTR_NON_NULL(stats, false);
+    PS_ASSERT_VECTOR_NON_NULL(in, false);
+    PS_ASSERT_VECTOR_NON_EMPTY(in, false);
+    if (mask) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(mask, in, false);
+        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
+    }
+    if (errors) {
+        PS_ASSERT_VECTORS_SIZE_EQUAL(errors, in, false);
+        PS_ASSERT_VECTOR_TYPE(errors, in->type.type, false);
+    }
+
+    // Convert types, as necessary
+    psVector *inF32 = NULL;             // Input vector of values, F32 version
+    if (in->type.type == PS_TYPE_F32) {
+        inF32 = psMemIncrRefCounter((psPtr)in);
+    } else {
+        inF32 = psVectorCopy(NULL, in, PS_TYPE_F32);
+    }
+    psVector *errorsF32 = NULL;         // Input vector of errors, F32 version
+    if (errors) {
+        if (errors->type.type == PS_TYPE_F32) {
+            errorsF32 = psMemIncrRefCounter((psPtr)errors);
+        } else {
+            errorsF32 = psVectorCopy(NULL, errors, PS_TYPE_F32);
+        }
+    }
+    psVector *maskU8 = NULL;            // Input mask vector, U8 version
+    if (mask) {
+        if (mask->type.type == PS_TYPE_MASK) {
+            maskU8 = psMemIncrRefCounter((psPtr)mask);
+        } else {
+            maskU8 = psVectorCopy(NULL, mask, PS_TYPE_MASK);
+        }
+    }
+
+    if ((stats->options & PS_STAT_USE_RANGE) && (stats->min >= stats->max)) {
+        PS_ASSERT_FLOAT_LARGER_THAN_OR_EQUAL(stats->max, stats->min, false);
+    }
+
+    if ((stats->options & PS_STAT_USE_BINSIZE) && (stats->min >= stats->max)) {
+        PS_ASSERT_FLOAT_LARGER_THAN_OR_EQUAL(stats->binsize, 0.0, false);
+    }
+
+    // init the value of stats->results: this is used internally to check if
+    // prior functions have been called
+    stats->results = PS_STAT_NONE;
+    bool status = true;
+
+    // ************************************************************************
+    if (stats->options & PS_STAT_SAMPLE_MEAN) {
+        if (!vectorSampleMean(inF32, errorsF32, maskU8, maskVal, stats)) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to calculate vector sample mean");
+            status &= false;
+        }
+    }
+
+    // ************************************************************************
+    if (stats->options & (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_QUARTILE)) {
+        if (!vectorSampleMedian(inF32, maskU8, maskVal, stats)) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to calculate sample median");
+            status &= false;
+        }
+    }
+
+    // ************************************************************************
+    if (stats->options & PS_STAT_SAMPLE_STDEV) {
+        if (!vectorSampleStdev(inF32, errorsF32, maskU8, maskVal, stats)) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to calculate sample stdev");
+            status &= false;
+        }
+    }
+
+    if (stats->options & (PS_STAT_SAMPLE_SKEWNESS | PS_STAT_SAMPLE_KURTOSIS)) {
+        if (!vectorSampleMoments(inF32, maskU8, maskVal, stats)) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to calculate sample moments");
+            status &= false;
+        }
+    }
+
+    // ************************************************************************
+    if (stats->options & (PS_STAT_MAX | PS_STAT_MIN)) {
+        if (vectorMinMax(inF32, maskU8, maskVal, stats) == 0) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to calculate vector minimum and maximum");
+            status &= false;
+        }
+    }
+
+    // ************************************************************************
+    if (stats->options & (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV | PS_STAT_ROBUST_QUARTILE)) {
+        if (!vectorRobustStats(inF32, errorsF32, maskU8, maskVal, stats)) {
+            psError(PS_ERR_UNKNOWN, false, _("Failed to calculate robust statistics"));
+            status &= false;
+        }
+    }
+
+    // ************************************************************************
+    if (stats->options & (PS_STAT_FITTED_MEAN | PS_STAT_FITTED_STDEV)) {
+        if (!vectorFittedStats(inF32, errorsF32, maskU8, maskVal, stats)) {
+            psError(PS_ERR_UNKNOWN, false, _("Failed to calculate fitted statistics"));
+            status &= false;
+        }
+    }
+
+    // ************************************************************************
+    if (stats->options & (PS_STAT_FITTED_MEAN_V2 | PS_STAT_FITTED_STDEV_V2)) {
+        if (stats->options & (PS_STAT_FITTED_MEAN | PS_STAT_FITTED_STDEV)) {
+            psAbort("you may not specify both FITTED_MEAN and FITTED_MEAN_V2");
+        }
+        if (!vectorFittedStats_v2(inF32, errorsF32, maskU8, maskVal, stats)) {
+            psError(PS_ERR_UNKNOWN, false, _("Failed to calculate fitted statistics"));
+            status &= false;
+        }
+    }
+
+    // ************************************************************************
+    if (stats->options & (PS_STAT_FITTED_MEAN_V3 | PS_STAT_FITTED_STDEV_V3)) {
+        if (stats->options & (PS_STAT_FITTED_MEAN | PS_STAT_FITTED_STDEV)) {
+            psAbort("you may not specify both FITTED_MEAN and FITTED_MEAN_V3");
+        }
+        if (!vectorFittedStats_v3(inF32, errorsF32, maskU8, maskVal, stats)) {
+            psError(PS_ERR_UNKNOWN, false, _("Failed to calculate fitted statistics"));
+            status &= false;
+        }
+    }
+
+    // ************************************************************************
+    if (stats->options & (PS_STAT_FITTED_MEAN_V4 | PS_STAT_FITTED_STDEV_V4)) {
+        if (stats->options & (PS_STAT_FITTED_MEAN | PS_STAT_FITTED_STDEV)) {
+            psAbort("you may not specify both FITTED_MEAN and FITTED_MEAN_V4");
+        }
+        if (!vectorFittedStats_v4(inF32, errorsF32, maskU8, maskVal, stats)) {
+            psError(PS_ERR_UNKNOWN, false, _("Failed to calculate fitted statistics"));
+            status &= false;
+        }
+    }
+
+    // ************************************************************************
+    if ((stats->options & PS_STAT_CLIPPED_MEAN) || (stats->options & PS_STAT_CLIPPED_STDEV)) {
+        if (!vectorClippedStats(inF32, errorsF32, maskU8, maskVal, stats)) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to calculate clipped statistics\n");
+            status &= false;
+        }
+    }
+
+    psFree(inF32);
+    psFree(errorsF32);
+    psFree(maskU8);
+    psTrace(TRACE, 3,"---- %s() end  ----\n", __func__);
+    return status;
+}
+
+psStatsOptions psStatsOptionFromString(const char *string)
+{
+#define READ_STAT(NAME, SYMBOL) \
+    if (strcasecmp(string, NAME) == 0) { \
+        return SYMBOL; \
+    }
+
+    READ_STAT("MEAN",       PS_STAT_SAMPLE_MEAN);
+    READ_STAT("STDEV",      PS_STAT_SAMPLE_STDEV);
+    READ_STAT("SKEWNESS",   PS_STAT_SAMPLE_SKEWNESS);
+    READ_STAT("KURTOSIS",   PS_STAT_SAMPLE_KURTOSIS);
+    READ_STAT("MEDIAN",     PS_STAT_SAMPLE_MEDIAN);
+    READ_STAT("QUARTILE",   PS_STAT_SAMPLE_QUARTILE);
+    READ_STAT("SAMPLE_MEAN",     PS_STAT_SAMPLE_MEAN);
+    READ_STAT("SAMPLE_STDEV",    PS_STAT_SAMPLE_STDEV);
+    READ_STAT("SAMPLE_MEDIAN",   PS_STAT_SAMPLE_MEDIAN);
+    READ_STAT("SAMPLE_QUARTILE", PS_STAT_SAMPLE_QUARTILE);
+    READ_STAT("SAMPLE_SKEWNESS", PS_STAT_SAMPLE_SKEWNESS);
+    READ_STAT("SAMPLE_KURTOSIS", PS_STAT_SAMPLE_KURTOSIS);
+    READ_STAT("ROBUST",          PS_STAT_ROBUST_MEDIAN);
+    READ_STAT("ROBUST_MEDIAN",   PS_STAT_ROBUST_MEDIAN);
+    READ_STAT("ROBUST_STDEV",    PS_STAT_ROBUST_STDEV);
+    READ_STAT("ROBUST_QUARTILE", PS_STAT_ROBUST_QUARTILE);
+    READ_STAT("FITTED",         PS_STAT_FITTED_MEAN);
+    READ_STAT("FITTED_MEAN",    PS_STAT_FITTED_MEAN);
+    READ_STAT("FITTED_STDEV",   PS_STAT_FITTED_STDEV);
+    READ_STAT("FITTED_V2",       PS_STAT_FITTED_MEAN_V2);
+    READ_STAT("FITTED_MEAN_V2",  PS_STAT_FITTED_MEAN_V2);
+    READ_STAT("FITTED_STDEV_V2", PS_STAT_FITTED_STDEV_V2);
+    READ_STAT("FITTED_V3",       PS_STAT_FITTED_MEAN_V3);
+    READ_STAT("FITTED_MEAN_V3",  PS_STAT_FITTED_MEAN_V3);
+    READ_STAT("FITTED_STDEV_V3", PS_STAT_FITTED_STDEV_V3);
+    READ_STAT("FITTED_V4",       PS_STAT_FITTED_MEAN_V4);
+    READ_STAT("FITTED_MEAN_V4",  PS_STAT_FITTED_MEAN_V4);
+    READ_STAT("FITTED_STDEV_V4", PS_STAT_FITTED_STDEV_V4);
+    READ_STAT("CLIPPED",         PS_STAT_CLIPPED_MEAN);
+    READ_STAT("CLIPPED_MEAN",    PS_STAT_CLIPPED_MEAN);
+    READ_STAT("CLIPPED_STDEV",   PS_STAT_CLIPPED_STDEV);
+
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to parse statistic: %s\n", string);
+    return 0;
+}
+
+psString psStatsOptionToString(psStatsOptions option)
+{
+    psString string = NULL;             // String to return
+
+#define WRITE_STAT(NAME, SYMBOL) \
+    if (option & SYMBOL) { \
+        psStringAppend(&string, "%s ", NAME); \
+    }
+
+    // Same list as above (for psStatsFromString), but with repeat symbols removed
+    WRITE_STAT("SAMPLE_MEAN",     PS_STAT_SAMPLE_MEAN);
+    WRITE_STAT("SAMPLE_STDEV",    PS_STAT_SAMPLE_STDEV);
+    WRITE_STAT("SAMPLE_MEDIAN",   PS_STAT_SAMPLE_MEDIAN);
+    WRITE_STAT("SAMPLE_QUARTILE", PS_STAT_SAMPLE_QUARTILE);
+    WRITE_STAT("SAMPLE_SKEWNESS", PS_STAT_SAMPLE_SKEWNESS);
+    WRITE_STAT("SAMPLE_KURTOSIS", PS_STAT_SAMPLE_KURTOSIS);
+    WRITE_STAT("ROBUST_MEDIAN",   PS_STAT_ROBUST_MEDIAN);
+    WRITE_STAT("ROBUST_STDEV",    PS_STAT_ROBUST_STDEV);
+    WRITE_STAT("ROBUST_QUARTILE", PS_STAT_ROBUST_QUARTILE);
+    WRITE_STAT("FITTED_MEAN",     PS_STAT_FITTED_MEAN);
+    WRITE_STAT("FITTED_STDEV",    PS_STAT_FITTED_STDEV);
+    WRITE_STAT("FITTED_MEAN_V2",  PS_STAT_FITTED_MEAN_V2);
+    WRITE_STAT("FITTED_STDEV_V2", PS_STAT_FITTED_STDEV_V2);
+    WRITE_STAT("FITTED_MEAN_V3",  PS_STAT_FITTED_MEAN_V3);
+    WRITE_STAT("FITTED_STDEV_V3", PS_STAT_FITTED_STDEV_V3);
+    WRITE_STAT("FITTED_MEAN_V4",  PS_STAT_FITTED_MEAN_V4);
+    WRITE_STAT("FITTED_STDEV_V4", PS_STAT_FITTED_STDEV_V4);
+    WRITE_STAT("CLIPPED_MEAN",    PS_STAT_CLIPPED_MEAN);
+    WRITE_STAT("CLIPPED_STDEV",   PS_STAT_CLIPPED_STDEV);
+
+    return string;
+}
+
+psStats *psStatsFromString(const char *string)
+{
+    psList *subStrings = psStringSplit(string, " ,;", false); // List of sub-strings
+    if (!subStrings || psListLength(subStrings) == 0) {
+        // Nothing here
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false, "No string to parse for statistics: %s\n", string);
+        psFree(subStrings);
+        return NULL;
+    }
+    psStats *stats = psStatsAlloc(0);   // Generate empty stats structure
+    psListIterator *iterator = psListIteratorAlloc(subStrings, PS_LIST_HEAD, false); // Iterator
+    psString statString;                // Statistic string, from iteration
+    while ((statString = psListGetAndIncrement(iterator))) {
+        psStatsOptions option = psStatsOptionFromString(statString);
+        if (option == 0) {
+            psWarning("Unable to interpret statistic option: %s --- ignored.\n", statString);
+            continue;
+        }
+        stats->options |= option;
+    }
+    psFree(iterator);
+    psFree(subStrings);
+    return stats;
+}
+
+psString psStatsToString(const psStats *stats)
+{
+    return psStatsOptionToString(stats->options);
+}
+
+psStatsOptions psStatsSingleOption(psStatsOptions option)
+{
+    switch (option & ~(PS_STAT_USE_RANGE | PS_STAT_USE_BINSIZE)) {
+      case PS_STAT_SAMPLE_MEAN:
+      case PS_STAT_SAMPLE_MEDIAN:
+      case PS_STAT_SAMPLE_STDEV:
+      case PS_STAT_SAMPLE_QUARTILE:
+      case PS_STAT_SAMPLE_SKEWNESS:
+      case PS_STAT_SAMPLE_KURTOSIS:
+      case PS_STAT_ROBUST_MEDIAN:
+      case PS_STAT_ROBUST_STDEV:
+      case PS_STAT_ROBUST_QUARTILE:
+      case PS_STAT_FITTED_MEAN:
+      case PS_STAT_FITTED_STDEV:
+      case PS_STAT_FITTED_MEAN_V2:
+      case PS_STAT_FITTED_STDEV_V2:
+      case PS_STAT_FITTED_MEAN_V3:
+      case PS_STAT_FITTED_STDEV_V3:
+      case PS_STAT_FITTED_MEAN_V4:
+      case PS_STAT_FITTED_STDEV_V4:
+      case PS_STAT_CLIPPED_MEAN:
+      case PS_STAT_CLIPPED_STDEV:
+      case PS_STAT_MAX:
+      case PS_STAT_MIN:
+        return option & ~(PS_STAT_USE_RANGE | PS_STAT_USE_BINSIZE);
+      default:
+        return 0;
+    }
+    psAbort("Should never get here.\n");
+    return 0;
+}
+
+psStatsOptions psStatsMeanOption(psStatsOptions options)
+{
+    return options & (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN | PS_STAT_ROBUST_MEDIAN |
+                      PS_STAT_CLIPPED_MEAN | PS_STAT_FITTED_MEAN | PS_STAT_FITTED_MEAN_V2 |
+                      PS_STAT_FITTED_MEAN_V3 | PS_STAT_FITTED_MEAN_V4);
+}
+
+psStatsOptions psStatsStdevOption(psStatsOptions options)
+{
+    return options & (PS_STAT_SAMPLE_STDEV | PS_STAT_ROBUST_STDEV | PS_STAT_CLIPPED_STDEV |
+                      PS_STAT_FITTED_STDEV | PS_STAT_FITTED_STDEV_V2 | PS_STAT_FITTED_STDEV_V3 |
+                      PS_STAT_FITTED_STDEV_V4);
+}
+
+
+double psStatsGetValue(const psStats *stats, psStatsOptions option)
+{
+    // We could call psStatsSingle to check, but it would be a waste since we effectively do it anyway
+    switch (option & ~(PS_STAT_USE_RANGE | PS_STAT_USE_BINSIZE)) {
+      case PS_STAT_SAMPLE_MEAN:
+        return stats->sampleMean;
+      case PS_STAT_SAMPLE_MEDIAN:
+        return stats->sampleMedian;
+      case PS_STAT_SAMPLE_STDEV:
+        return stats->sampleStdev;
+      case PS_STAT_SAMPLE_SKEWNESS:
+        return stats->sampleSkewness;
+      case PS_STAT_SAMPLE_KURTOSIS:
+        return stats->sampleKurtosis;
+      case PS_STAT_ROBUST_MEDIAN:
+        return stats->robustMedian;
+      case PS_STAT_ROBUST_STDEV:
+        return stats->robustStdev;
+      case PS_STAT_FITTED_MEAN:
+        return stats->fittedMean;
+      case PS_STAT_FITTED_STDEV:
+        return stats->fittedStdev;
+      case PS_STAT_FITTED_MEAN_V2:
+        return stats->fittedMean;
+      case PS_STAT_FITTED_STDEV_V2:
+        return stats->fittedStdev;
+      case PS_STAT_FITTED_MEAN_V3:
+        return stats->fittedMean;
+      case PS_STAT_FITTED_STDEV_V3:
+        return stats->fittedStdev;
+      case PS_STAT_FITTED_MEAN_V4:
+        return stats->fittedMean;
+      case PS_STAT_FITTED_STDEV_V4:
+        return stats->fittedStdev;
+      case PS_STAT_CLIPPED_MEAN:
+        return stats->clippedMean;
+      case PS_STAT_CLIPPED_STDEV:
+        return stats->clippedStdev;
+      case PS_STAT_MAX:
+        return stats->max;
+      case PS_STAT_MIN:
+        return stats->min;
+      case PS_STAT_SAMPLE_QUARTILE:
+      case PS_STAT_ROBUST_QUARTILE:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Cannot return a single quartile value; "
+                "get them yourself.\n");
+        return NAN;
+      default:
+        return NAN;
+    }
+    psAbort("Should never get here.\n");
+    return NAN;
+}
+
+// other private functions used above
+
+static psF32 QuadraticInverse(psF32 a,
+                              psF32 b,
+                              psF32 c,
+                              psF32 y,
+                              psF32 xLo,
+                              psF32 xHi
+    )
+{
+    psF64 tmp = sqrt((y - c)/a + (b*b)/(4.0 * a * a));
+
+    psF64 x1 = -b/(2.0*a) + tmp;
+    psF64 x2 = -b/(2.0*a) - tmp;
+
+    if (xLo <= x1 && x1 <= xHi) {
+        return x1;
+    }
+    if (xLo <= x2 && x2 <= xHi) {
+        return x2;
+    }
+    return 0.5 * (xLo + xHi);
+}
+
+# if (0)
+/******************************************************************************
+fitQuadraticSearchForYThenReturnX(*xVec, *yVec, binNum, yVal): A general
+routine which fits a quadratic to three points and returns the x-value
+corresponding to the input y-value.  This routine takes psVectors of x/y pairs
+as input, and fits a quadratic to the 3 points surrounding element binNum in
+the vectors (the midpoint between element i and i+1 is used for x[i]).  It
+then determines for what value x does that quadratic f(x) = yVal (the input
+parameter).
+
+*****************************************************************************/
+static psF32 fitQuadraticSearchForYThenReturnX(const psVector *xVec,
+                                               psVector *yVec,
+                                               psS32 binNum,
+                                               psF32 yVal
+    )
+{
+    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
+    psTrace(TRACE, 5, "binNum, yVal is (%d, %f)\n", binNum, yVal);
+    if (psTraceGetLevel("psLib.math") >= 8) {
+        PS_VECTOR_PRINT_F32(xVec);
+        PS_VECTOR_PRINT_F32(yVec);
+    }
+
+    PS_ASSERT_VECTOR_NON_NULL(xVec, NAN);
+    PS_ASSERT_VECTOR_NON_NULL(yVec, NAN);
+    PS_ASSERT_VECTOR_TYPE(xVec, PS_TYPE_F32, NAN);
+    PS_ASSERT_VECTOR_TYPE(yVec, PS_TYPE_F32, NAN);
+    //    PS_ASSERT_VECTORS_SIZE_EQUAL(xVec, yVec, NAN);
+    PS_ASSERT_INT_WITHIN_RANGE(binNum, 0, (int)(xVec->n - 1), NAN);
+    PS_ASSERT_INT_WITHIN_RANGE(binNum, 0, (int)(yVec->n - 1), NAN);
+
+    psVector *x = psVectorAlloc(3, PS_TYPE_F64);
+    psVector *y = psVectorAlloc(3, PS_TYPE_F64);
+    psF32 tmpFloat = 0.0f;
+
+    if ((binNum >= 1) && (binNum < (yVec->n - 2)) && (binNum < (xVec->n - 2))) {
+        // The general case.  We have all three points.
+        x->data.F64[0] = (psF64) (0.5 * (xVec->data.F32[binNum - 1] + xVec->data.F32[binNum]));
+        x->data.F64[1] = (psF64) (0.5 * (xVec->data.F32[binNum] + xVec->data.F32[binNum+1]));
+        x->data.F64[2] = (psF64) (0.5 * (xVec->data.F32[binNum+1] + xVec->data.F32[binNum+2]));
+        y->data.F64[0] = yVec->data.F32[binNum - 1];
+        y->data.F64[1] = yVec->data.F32[binNum];
+        y->data.F64[2] = yVec->data.F32[binNum + 1];
+        psTrace(TRACE, 6, "x vec (orig) is (%f %f %f %f)\n", xVec->data.F32[binNum - 1],
+                xVec->data.F32[binNum], xVec->data.F32[binNum+1], xVec->data.F32[binNum+2]);
+        psTrace(TRACE, 6, "x data is (%f %f %f)\n", x->data.F64[0], x->data.F64[1], x->data.F64[2]);
+        psTrace(TRACE, 6, "y data is (%f %f %f)\n", y->data.F64[0], y->data.F64[1], y->data.F64[2]);
+
+        //
+        // Ensure that the y value lies within range of the y values.
+        //
+        if (! (((y->data.F64[0] <= yVal) && (yVal <= y->data.F64[2])) ||
+               ((y->data.F64[2] <= yVal) && (yVal <= y->data.F64[0]))) ) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    _("Specified yVal, %g, is not within y-range, %g to %g."),
+                    (psF64)yVal, y->data.F64[0], y->data.F64[2]);
+        }
+
+        //
+        // Ensure that the y values are monotonic.
+        //
+        if (((y->data.F64[0] < y->data.F64[1]) && !(y->data.F64[1] <= y->data.F64[2])) ||
+            ((y->data.F64[0] > y->data.F64[1]) && !(y->data.F64[1] >= y->data.F64[2]))) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "This routine must be called with monotonically increasing or decreasing data points.\n");
+            psFree(x);
+            psFree(y);
+            psTrace(TRACE, 5, "---- %s() end ----\n", __func__);
+            return NAN;
+        }
+
+        // Determine the coefficients of the polynomial.
+        psPolynomial1D *myPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 2);
+        if (!psVectorFitPolynomial1D(myPoly, NULL, 0, y, NULL, x)) {
+            psError(PS_ERR_UNEXPECTED_NULL, false,
+                    _("Failed to fit a 1-dimensional polynomial to the three specified data points.  "
+                      "Returning NAN."));
+            psFree(x);
+            psFree(y);
+            psTrace(TRACE, 5, "---- %s(NAN) end ----\n", __func__);
+            return NAN;
+        }
+        psTrace(TRACE, 6, "myPoly->coeff[0] is %f\n", myPoly->coeff[0]);
+        psTrace(TRACE, 6, "myPoly->coeff[1] is %f\n", myPoly->coeff[1]);
+        psTrace(TRACE, 6, "myPoly->coeff[2] is %f\n", myPoly->coeff[2]);
+        psTrace(TRACE, 6, "Fitted y vec is (%f %f %f)\n",
+                (psF32) psPolynomial1DEval(myPoly, (psF64) x->data.F64[0]),
+                (psF32) psPolynomial1DEval(myPoly, (psF64) x->data.F64[1]),
+                (psF32) psPolynomial1DEval(myPoly, (psF64) x->data.F64[2]));
+
+        psTrace(TRACE, 6, "We fit the polynomial, now find x such that f(x) equals %f\n", yVal);
+        tmpFloat = QuadraticInverse(myPoly->coeff[2], myPoly->coeff[1], myPoly->coeff[0], yVal,
+                                    x->data.F64[0], x->data.F64[2]);
+        psFree(myPoly);
+
+        if (isnan(tmpFloat)) {
+            psError(PS_ERR_UNEXPECTED_NULL,
+                    false, _("Failed to determine the median of the fitted polynomial.  Returning NAN."));
+            psFree(x);
+            psFree(y);
+            psTrace(TRACE, 5, "---- %s(NAN) end ----\n", __func__);
+            return(NAN);
+        }
+    } else {
+        // These are special cases where the bin is at the beginning or end of the vector.
+        if (binNum == 0) {
+            // We have two points only at the beginning of the vectors x and y.
+            tmpFloat = 0.5 * (xVec->data.F32[binNum] +
+                              xVec->data.F32[binNum + 1]);
+        } else if (binNum == (xVec->n - 1)) {
+            // The special case where we have two points only at the end of
+            // the vectors x and y.
+            // XXX: Is this right?
+            tmpFloat = xVec->data.F32[binNum];
+        } else if (binNum == (xVec->n - 2)) {
+            // XXX: Is this right?
+            tmpFloat = 0.5 * (xVec->data.F32[binNum] + xVec->data.F32[binNum + 1]);
+        }
+    }
+
+    psTrace(TRACE, 6, "FIT: return %f\n", tmpFloat);
+    psFree(x);
+    psFree(y);
+
+    psTrace(TRACE, 5, "---- %s(%f) end ----\n", __func__, tmpFloat);
+    return tmpFloat;
+}
+# endif
+
+/******************************************************************************
+fitQuadraticSearchForYThenReturnXusingValues(*xVec, *yVec, binNum, yVal): A general routine
+which fits a quadratic to three points and returns the x-value corresponding to the input
+y-value.  This routine takes psVectors of x/y pairs as input, and fits a quadratic to the 3
+points surrounding element binNum in the vectors.  This version uses the values of x[i] for the
+x coordinates (not the midpoints).  This is appropriate for a cumulative histogram.  It then
+determines for what value x does that quadratic f(x) = yVal (the input parameter).
+
+*****************************************************************************/
+static psF32 fitQuadraticSearchForYThenReturnXusingValues(const psVector *xVec,
+                                                          psVector *yVec,
+                                                          psS32 binNum,
+                                                          psF32 yVal
+    )
+{
+    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
+    psTrace(TRACE, 5, "binNum, yVal is (%d, %f)\n", binNum, yVal);
+    if (psTraceGetLevel("psLib.math") >= 8) {
+        PS_VECTOR_PRINT_F32(xVec);
+        PS_VECTOR_PRINT_F32(yVec);
+    }
+
+    PS_ASSERT_VECTOR_NON_NULL(xVec, NAN);
+    PS_ASSERT_VECTOR_NON_NULL(yVec, NAN);
+    PS_ASSERT_VECTOR_TYPE(xVec, PS_TYPE_F32, NAN);
+    PS_ASSERT_VECTOR_TYPE(yVec, PS_TYPE_F32, NAN);
+    PS_ASSERT_INT_WITHIN_RANGE(binNum, 0, (int)(xVec->n - 1), NAN);
+    PS_ASSERT_INT_WITHIN_RANGE(binNum, 0, (int)(yVec->n - 1), NAN);
+
+    psVector *x = psVectorAlloc(3, PS_TYPE_F64);
+    psVector *y = psVectorAlloc(3, PS_TYPE_F64);
+    psF32 tmpFloat = 0.0f;
+
+    if ((binNum >= 1) && (binNum < (yVec->n - 2)) && (binNum < (xVec->n - 2))) {
+        // The general case.  We have all three points.
+        x->data.F64[0] = xVec->data.F32[binNum - 1];
+        x->data.F64[1] = xVec->data.F32[binNum];
+        x->data.F64[2] = xVec->data.F32[binNum+1];
+        y->data.F64[0] = yVec->data.F32[binNum - 1];
+        y->data.F64[1] = yVec->data.F32[binNum];
+        y->data.F64[2] = yVec->data.F32[binNum + 1];
+        psTrace(TRACE, 6, "x vec (orig) is (%f %f %f %f)\n", xVec->data.F32[binNum - 1],
+                xVec->data.F32[binNum], xVec->data.F32[binNum+1], xVec->data.F32[binNum+2]);
+        psTrace(TRACE, 6, "x data is (%f %f %f)\n", x->data.F64[0], x->data.F64[1], x->data.F64[2]);
+        psTrace(TRACE, 6, "y data is (%f %f %f)\n", y->data.F64[0], y->data.F64[1], y->data.F64[2]);
+
+        //
+        // Ensure that the y value lies within range of the y values.
+        //
+        if (! (((y->data.F64[0] <= yVal) && (yVal <= y->data.F64[2])) ||
+               ((y->data.F64[2] <= yVal) && (yVal <= y->data.F64[0]))) ) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    _("Specified yVal, %g, is not within y-range, %g to %g."),
+                    (psF64)yVal, y->data.F64[0], y->data.F64[2]);
+        }
+
+        //
+        // Ensure that the y values are monotonic.
+        //
+        if (((y->data.F64[0] < y->data.F64[1]) && !(y->data.F64[1] <= y->data.F64[2])) ||
+            ((y->data.F64[0] > y->data.F64[1]) && !(y->data.F64[1] >= y->data.F64[2]))) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "This routine must be called with monotonically increasing or decreasing data points.\n");
+            psFree(x);
+            psFree(y);
+            psTrace(TRACE, 5, "---- %s() end ----\n", __func__);
+            return NAN;
+        }
+
+        // Determine the coefficients of the polynomial.
+        psPolynomial1D *myPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 2);
+        if (!psVectorFitPolynomial1D(myPoly, NULL, 0, y, NULL, x)) {
+            psError(PS_ERR_UNEXPECTED_NULL, false,
+                    _("Failed to fit a 1-dimensional polynomial to the three specified data points.  "
+                      "Returning NAN."));
+            psFree(x);
+            psFree(y);
+            psTrace(TRACE, 5, "---- %s(NAN) end ----\n", __func__);
+            return NAN;
+        }
+        psTrace(TRACE, 6, "myPoly->coeff[0] is %f\n", myPoly->coeff[0]);
+        psTrace(TRACE, 6, "myPoly->coeff[1] is %f\n", myPoly->coeff[1]);
+        psTrace(TRACE, 6, "myPoly->coeff[2] is %f\n", myPoly->coeff[2]);
+        psTrace(TRACE, 6, "Fitted y vec is (%f %f %f)\n",
+                (psF32) psPolynomial1DEval(myPoly, (psF64) x->data.F64[0]),
+                (psF32) psPolynomial1DEval(myPoly, (psF64) x->data.F64[1]),
+                (psF32) psPolynomial1DEval(myPoly, (psF64) x->data.F64[2]));
+
+        psTrace(TRACE, 6, "We fit the polynomial, now find x such that f(x) equals %f\n", yVal);
+        tmpFloat = QuadraticInverse(myPoly->coeff[2], myPoly->coeff[1], myPoly->coeff[0], yVal,
+                                    x->data.F64[0], x->data.F64[2]);
+        psFree(myPoly);
+
+        if (isnan(tmpFloat)) {
+            psError(PS_ERR_UNEXPECTED_NULL,
+                    false, _("Failed to determine the median of the fitted polynomial.  Returning NAN."));
+            psFree(x);
+            psFree(y);
+            psTrace(TRACE, 5, "---- %s(NAN) end ----\n", __func__);
+            return(NAN);
+        }
+    } else {
+        // These are special cases where the bin is at the beginning or end of the vector.
+        if (binNum == 0) {
+            // We have two points only at the beginning of the vectors x and y.
+            // XXX this does not seem to be doing the linear interpolation / extrapolation
+            tmpFloat = 0.5 * (xVec->data.F32[binNum] +
+                              xVec->data.F32[binNum + 1]);
+        } else if (binNum == (xVec->n - 1)) {
+            // The special case where we have two points only at the end of
+            // the vectors x and y.
+            // XXX: Is this right?
+            tmpFloat = xVec->data.F32[binNum];
+        } else if (binNum == (xVec->n - 2)) {
+            // XXX: Is this right?
+            tmpFloat = 0.5 * (xVec->data.F32[binNum] + xVec->data.F32[binNum + 1]);
+        }
+    }
+
+    psTrace(TRACE, 6, "FIT: return %f\n", tmpFloat);
+    psFree(x);
+    psFree(y);
+
+    psTrace(TRACE, 5, "---- %s(%f) end ----\n", __func__, tmpFloat);
+    return tmpFloat;
+}
+
+/******************************************************************************
+NOTE: We assume unnormalized gaussians.
+*****************************************************************************/
+static psF32 minimizeLMChi2Gauss1D(psVector *deriv,
+                                   const psVector *params,
+                                   const psVector *coords
+    )
+{
+    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_VECTOR_NON_NULL(params, NAN);
+    PS_ASSERT_VECTOR_SIZE(params, (long)2, NAN);
+    PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32, NAN);
+    PS_ASSERT_VECTOR_NON_NULL(coords, NAN);
+    PS_ASSERT_VECTOR_SIZE(coords, (long)1, NAN);
+    PS_ASSERT_VECTOR_TYPE(coords, PS_TYPE_F32, NAN);
+
+    psF32 x = coords->data.F32[0];
+    psF32 mean = params->data.F32[0];
+    psF32 var = params->data.F32[1];
+    psF32 dx = (x - mean);
+
+    psF32 gauss = exp (-0.5*PS_SQR(dx)/var);
+    if (deriv) {
+        PS_ASSERT_VECTOR_SIZE(deriv, (long)2, NAN);
+        PS_ASSERT_VECTOR_TYPE(deriv, PS_TYPE_F32, NAN);
+        psF32 tmp = dx * gauss;
+        deriv->data.F32[0] = tmp / var;
+        deriv->data.F32[1] = tmp * dx / (var * var);
+    }
+
+
+    psTrace(TRACE, 4, "---- %s() end ----\n", __func__);
+    return gauss;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psStats.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psStats.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psStats.h	(revision 22158)
@@ -0,0 +1,183 @@
+/* @file  psStats.h
+ * @brief basic statistical operations
+ *
+ * This file will hold the definition of the histogram and stats data
+ * structures.  It also contains prototypes for procedures which operate
+ * on those data structures.
+ *
+ * @author GLG, MHPCC
+ *
+ * @version $Revision: 1.64 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-12-15 01:17:28 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_STATS_H
+#define PS_STATS_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+/******************************************************************************
+    Statistical functions and data structures.
+ *****************************************************************************/
+
+/** enumeration of statistical calculation options
+ *
+ *  @see psStats, psVectorStats, psImageStats
+ */
+typedef enum {
+    PS_STAT_NONE            = 0x000000, ///< Empty set
+    PS_STAT_MIN             = 0x000001, ///< Maximum
+    PS_STAT_MAX             = 0x000002, ///< Minumum
+    PS_STAT_SAMPLE_MEAN     = 0x000004, ///< Sample Mean
+    PS_STAT_SAMPLE_MEDIAN   = 0x000008, ///< Sample Median
+    PS_STAT_SAMPLE_STDEV    = 0x000010, ///< Sample Standard Deviation
+    PS_STAT_SAMPLE_QUARTILE = 0x000020, ///< Sample Quartile
+    PS_STAT_SAMPLE_SKEWNESS = 0x000040, ///< Sample Skewness (third moment)
+    PS_STAT_SAMPLE_KURTOSIS = 0x000080, ///< Sample Kurtosis (fourth moment)
+    PS_STAT_ROBUST_MEDIAN   = 0x000100, ///< Robust Median
+    PS_STAT_ROBUST_STDEV    = 0x000200, ///< Robust Standarad Deviation
+    PS_STAT_ROBUST_QUARTILE = 0x000400, ///< Robust Quartile
+    PS_STAT_ROBUST_SPARE1   = 0x000800, ///< Spare 1
+    PS_STAT_FITTED_MEAN     = 0x001000, ///< Fitted Mean
+    PS_STAT_FITTED_STDEV    = 0x002000, ///< Fitted Standard Deviation
+    PS_STAT_FITTED_MEAN_V2  = 0x004000, ///< Fitted Mean
+    PS_STAT_FITTED_STDEV_V2 = 0x008000, ///< Fitted Standard Deviation
+    PS_STAT_FITTED_MEAN_V3  = 0x010000, ///< Fitted Mean
+    PS_STAT_FITTED_STDEV_V3 = 0x020000, ///< Fitted Standard Deviation
+    PS_STAT_CLIPPED_MEAN    = 0x040000, ///< Clipped Mean
+    PS_STAT_CLIPPED_STDEV   = 0x080000, ///< Clipped Standard Deviation
+    PS_STAT_USE_RANGE       = 0x100000, ///< Range
+    PS_STAT_USE_BINSIZE     = 0x200000, ///< Binsize
+    PS_STAT_FITTED_MEAN_V4  = 0x400000, ///< Fitted Mean
+    PS_STAT_FITTED_STDEV_V4 = 0x800000, ///< Fitted Standard Deviation
+} psStatsOptions;
+
+/** This is the generic statistics structure.  It contails the data members
+    for the various statistic values.  It also contains the options member to
+    specifiy which statistics should be calculated. */
+typedef struct
+{
+    double sampleMean;                 ///< formal mean of sample
+    double sampleMedian;               ///< formal median of sample
+    double sampleStdev;                ///< standard deviation of sample
+    double sampleUQ;                   ///< upper quartile of sample
+    double sampleLQ;                   ///< lower quartile of sample
+    double sampleSkewness;             ///< skewness (third moment) of sample
+    double sampleKurtosis;             ///< kurtosis (fourth moment) of sample
+    double robustMedian;               ///< robust median of array
+    double robustStdev;                ///< robust standard deviation of array
+    double robustUQ;                   ///< robust upper quartile
+    double robustLQ;                   ///< robust lower quartile
+    long robustN50;                    ///< Number of points in Gaussian fit; XXX: This is currently unused.
+    double fittedMean;                 ///< robust mean of data
+    double fittedStdev;                ///< robust standard deviation of data
+    long fittedNfit;                   ///< Number of points in Gaussian fit; XXX: This is currently unused
+    double clippedMean;                ///< Nsigma clipped mean
+    double clippedStdev;               ///< standard deviation after clipping
+    long clippedNvalues;               ///< Number of data points used for clipped mean.
+    double clipSigma;                  ///< Nsigma used for clipping; user input
+    int clipIter;                      ///< Number of clipping iterations; user input
+    double min;                        ///< minimum data value in array
+    double max;                        ///< maximum data value in array
+    double binsize;                    ///< binsize for robust fit (input/ouput)
+    long nSubsample;                   ///< maxinum number of measurements (input)
+    psStatsOptions options;            ///< bitmask of values requested
+    psStatsOptions results;            ///< bitmask of values calculated
+}
+psStats;
+
+/** Performs statistical calculations on a vector.
+ *
+ *  @return psStats*    the statistical results as specified by stats->options
+ */
+bool psVectorStats(
+    psStats* stats,                    ///< stats structure defines stats to be calculated and how
+    const psVector* in,                ///< Vector to be analysed.
+    const psVector* errors,            ///< Errors.
+    const psVector* mask,              ///< Ignore elements where (maskVector & maskVal) != 0: must be INT or NULL
+    psMaskType maskVal                 ///< Only mask elements with one of these bits set in maskVector
+);
+
+/** Allocator of the psStats structure.
+ *
+ *  @return psStats*    A new psStats struct with the options member set to the
+ *                      value given.
+ */
+#ifdef DOXYGEN
+psStats* psStatsAlloc(
+    psStatsOptions options              ///< Statistics to calculate
+);
+#else // ifdef DOXYGEN
+psStats* p_psStatsAlloc(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psStatsOptions options              ///< Statistics to calculate
+) PS_ATTR_MALLOC;
+#define psStatsAlloc(options) \
+      p_psStatsAlloc(__FILE__, __LINE__, __func__, options)
+#endif // ifdef DOXYGEN
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psStats structure, false otherwise.
+ */
+bool psMemCheckStats(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+// reset the values which are output, and which may be used from one psStats stage to the next
+void psStatsInit(psStats *stats);
+
+// Get the statistics option from a string
+psStatsOptions psStatsOptionFromString(const char *string);
+// Write a string from the statistics options
+psString psStatsOptionToString(psStatsOptions option);
+// Generate a psStats from a string of statistics options
+psStats *psStatsFromString(const char *string);
+// Generate a string of statistics options from a psStats
+psString psStatsToString(const psStats *stats);
+// Is only a single statistics option set?
+psStatsOptions psStatsSingleOption(psStatsOptions option);
+// Return a particular stats value
+double psStatsGetValue(const psStats *stats, psStatsOptions option);
+// Return the statistics option(s) for the mean/median
+psStatsOptions psStatsMeanOption(psStatsOptions options);
+// Return the statistics option(s) for the stdev
+psStatsOptions psStatsStdevOption(psStatsOptions options);
+
+/// @}
+#endif // #ifndef PS_STATS_H
+
+/*
+ * private stats functions used in psStats.c:
+ *
+ * vectorSampleMean
+   (none)
+ * vectorMinMax
+   (none)
+ * vectorSampleMedian (also yields SAMPLE_QUARTILE)
+   (none)
+ * vectorSampleStdev
+   (vectorSampleMean)
+ * vectorClippedStats
+   (vectorSampleMedian)
+   (vectorSampleMean (*also subset))
+   (vectorSampleStdev (*also subset))
+ * vectorRobustStats
+   (vectorMinMax (*only subset))
+ * vectorFittedStats
+   (vectorRobustStats)
+
+ * private stats functions called by other private stats functions are automatically called by
+ * those functions.  since they set the stats->results flags, they are not called multiple
+ * times.
+
+ * the private stats functions do not test for their corresponding stats flags: it is not
+ * necessary to request them if they are called within this function.
+
+*/
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psUnaryOp.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psUnaryOp.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psUnaryOp.c	(revision 22158)
@@ -0,0 +1,282 @@
+/** @file  psUnary.c
+ *
+ *  @brief Provides unary functions for simple matrix and vector element operations. Functions
+ *  include:
+ *
+ *      Addition (+)
+ *      Subtraction (-)
+ *      Multiplication (*)
+ *      Division (/)
+ *      Power (^)
+ *      Minimum (min)
+ *      Maximum (max)
+ *      Absolute value (abs)
+ *      Exponent (exp)
+ *      Natural Log (ln)
+ *      Power of 10 (ten)
+ *      Log (log)
+ *      Square root (sqrt)
+ *      Sine (sin or dsin)
+ *      Cosine (cos or dcos)
+ *      Tangent (tan or dtan)
+ *      Arcsine (asin or dasin)
+ *      Arccosine (acos or dacos)
+ *      Arctan (atan or datan)
+ *
+ *  Currently only vector-vector and image-image binary operations are supported.
+ *
+ *  @ingroup MatrixArithmetic
+ *
+ *  @author Ross Harman, MHPCC
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-03-19 00:52:35 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/******************************************************************************
+ *  INCLUDE FILES                                                             *
+ ******************************************************************************/
+#include <string.h>
+#include <strings.h>
+#include <math.h>
+#include <stdint.h>
+
+#include "psMemory.h"
+#include "psError.h"
+#include "psImage.h"
+#include "psVector.h"
+#include "psScalar.h"
+#include "psLogMsg.h"
+#include "psAssert.h"
+
+
+/*****************************************************************************
+ *  FUNCTION IMPLEMENTATION - LOCAL                                          *
+ *****************************************************************************/
+
+// Conversion for degrees to radians
+#define D2R 0.01745329252111111  /* PI/180 */
+
+// Conversion for radians to degrees
+#define R2D 57.29577950924861   /* 180.0/PI */
+
+
+// Unary SCALAR operations
+#define SCALAR(OUT,IN,OP,TYPE) \
+{ \
+    ps##TYPE *o  = &((psScalar*)OUT)->data.TYPE; \
+    ps##TYPE *i1 = &((psScalar*)IN)->data.TYPE; \
+    *o = OP; \
+}
+
+// Unary IMAGE operations
+#define VECTOR(OUT,IN,OP,TYPE) \
+{ \
+    long nIn = ((psVector*)IN)->n; \
+    long nOut = ((psVector*)OUT)->n; \
+    if (nIn != nOut) { \
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, _("Number of elements inconsistent, %ld vs %ld.  Number of elements must match."), nIn, nOut); \
+        if (OUT != IN) { \
+            psFree(OUT); \
+        } \
+        return NULL; \
+    } \
+    ps##TYPE *o  = ((psVector*)OUT)->data.TYPE; \
+    ps##TYPE *i1 = ((psVector*)IN)->data.TYPE; \
+    for (long i = 0; i < nIn; i++, o++, i1++) { \
+        *o = OP; \
+    } \
+}
+
+// Unary IMAGE operations
+#define IMAGE(OUT,IN,OP,TYPE) \
+{ \
+    long numRowsIn = ((psImage*)IN)->numRows; \
+    long numColsIn = ((psImage*)IN)->numCols; \
+    long numRowsOut = ((psImage*)OUT)->numRows; \
+    long numColsOut = ((psImage*)OUT)->numCols; \
+    if(numRowsIn!=numRowsOut || numColsIn!=numColsOut) { \
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, _("Specified psImage dimensions differed, %ldx%ld vs %ldx%ld."), \
+                numColsIn, numRowsIn, numColsOut, numRowsOut); \
+        if (OUT != IN) { \
+            psFree(OUT); \
+        } \
+        return NULL; \
+    } \
+    for (long j = 0; j < numRowsIn; j++) { \
+        ps##TYPE *o  = ((psImage* )OUT)->data.TYPE[j]; \
+        ps##TYPE *i1 = ((psImage* )IN)->data.TYPE[j]; \
+        for (long i = 0; i < numColsIn; i++, o++, i1++) { \
+            *o = OP; \
+        } \
+    }\
+}
+
+// Preprocessor macro function to create arithmetic function based on input type
+#define UNARY_TYPE(DIM,OUT,IN,OP) \
+switch (IN->type) { \
+case PS_TYPE_U8: \
+    DIM(OUT,IN,OP,U8); \
+    break; \
+case PS_TYPE_U16: \
+    DIM(OUT,IN,OP,U16); \
+    break; \
+case PS_TYPE_U32: \
+    DIM(OUT,IN,OP,U32); \
+    break; \
+case PS_TYPE_U64: \
+    DIM(OUT,IN,OP,U64); \
+    break; \
+case PS_TYPE_S8: \
+    DIM(OUT,IN,OP,S8); \
+    break; \
+case PS_TYPE_S16: \
+    DIM(OUT,IN,OP,S16); \
+    break; \
+case PS_TYPE_S32: \
+    DIM(OUT,IN,OP,S32); \
+    break; \
+case PS_TYPE_S64: \
+    DIM(OUT,IN,OP,S64); \
+    break; \
+case PS_TYPE_F32: \
+    DIM(OUT,IN,OP,F32); \
+    break; \
+case PS_TYPE_F64: \
+    DIM(OUT,IN,OP,F64); \
+    break; \
+default: { \
+        char* strType; \
+        PS_TYPE_NAME(strType, IN->type); \
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, _("Specified data type, %s, is not supported."), strType); \
+        if (OUT != IN) { \
+            psFree(OUT); \
+        } \
+        return NULL; \
+    } \
+}
+
+// Preprocessor macro function to create arithmetic function operation name. Functions below that add
+// FLT_EPSILON are done so to align results with a 64 bit computing architecture
+#define UNARY_OP(DIM,OUT,IN,OP) \
+if(!strncasecmp(OP, "abs", 3)) { \
+    UNARY_TYPE(DIM,OUT,IN,fabs((double)*i1)); \
+} else if(!strncasecmp(OP, "sqrt", 4)) { \
+    UNARY_TYPE(DIM,OUT,IN,sqrt((double)*i1)); \
+} else if(!strncasecmp(OP, "exp", 3)) { \
+    UNARY_TYPE(DIM,OUT,IN,exp((double)*i1)); \
+} else if(!strncasecmp(OP, "ln", 2)) { \
+    UNARY_TYPE(DIM,OUT,IN,log((double)*i1)); \
+} else if(!strncasecmp(OP, "ten", 3)) { \
+    UNARY_TYPE(DIM,OUT,IN,pow(10.0,(double)*i1)); \
+} else if(!strncasecmp(OP, "log", 3)) { \
+    UNARY_TYPE(DIM,OUT,IN,log10((double)*i1)); \
+} else if(!strncasecmp(OP, "sin", 3)) { \
+    UNARY_TYPE(DIM,OUT,IN,sin((double)*i1)); \
+} else if(!strncasecmp(OP, "dsin", 4)) { \
+    UNARY_TYPE(DIM,OUT,IN,sin((double)*i1*D2R)); \
+} else if(!strncasecmp(OP, "cos", 3)) { \
+    UNARY_TYPE(DIM,OUT,IN,cos((double)*i1)); \
+} else if(!strncasecmp(OP, "dcos", 4)) { \
+    UNARY_TYPE(DIM,OUT,IN,cos((double)*i1*D2R)); \
+} else if(!strncasecmp(OP, "tan", 3)) { \
+    UNARY_TYPE(DIM,OUT,IN,tan((double)*i1)); \
+} else if(!strncasecmp(OP, "dtan", 4)) { \
+    UNARY_TYPE(DIM,OUT,IN,tan((double)*i1*D2R)); \
+} else if(!strncasecmp(OP, "asin", 4)) { \
+    UNARY_TYPE(DIM,OUT,IN,asin((double)*i1)); \
+} else if(!strncasecmp(OP, "dasin", 5)) { \
+    UNARY_TYPE(DIM,OUT,IN,(R2D*asin((double)*i1))); \
+} else if(!strncasecmp(OP, "acos", 4)) { \
+    UNARY_TYPE(DIM,OUT,IN,acos((double)*i1)); \
+} else if(!strncasecmp(OP, "dacos", 5)) { \
+    UNARY_TYPE(DIM,OUT,IN,R2D*acos((double)*i1)); \
+} else if(!strncasecmp(OP, "atan", 4)) { \
+    UNARY_TYPE(DIM,OUT,IN,atan((double)*i1)); \
+} else if(!strncasecmp(OP, "datan", 5)) { \
+    UNARY_TYPE(DIM,OUT,IN,R2D*atan((double)*i1)); \
+} else { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Specified operation, %s, is not supported."), OP); \
+    if (OUT != IN) { \
+        psFree(OUT); \
+    } \
+    return NULL; \
+}
+
+psMathType* psUnaryOp(psPtr out, const psPtr in, const char *op)
+{
+    #define psUnaryOp_EXIT { \
+                             if (out != in) { \
+                             psFree(out); \
+                             } \
+                             return NULL; \
+                           }
+
+    psMathType* psTypeIn = (psMathType* ) in;
+
+    PS_ASSERT_GENERAL_PTR_NON_NULL(in, psUnaryOp_EXIT);
+    PS_ASSERT_GENERAL_PTR_NON_NULL(op, psUnaryOp_EXIT);
+
+    switch (psTypeIn->dimen) {
+    case PS_DIMEN_SCALAR:
+        if (out == NULL ||
+                ((psMathType*)out)->dimen != PS_DIMEN_SCALAR ||
+                ((psScalar*)out)->type.type != psTypeIn->type) {
+            psFree(out);
+            out = psScalarAlloc(0.0, psTypeIn->type);
+        }
+        UNARY_OP(SCALAR, out, psTypeIn, op);    // scalar
+        break;
+    case PS_DIMEN_VECTOR:
+    case PS_DIMEN_TRANSV:
+        if (((psVector*)in)->n == 0) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true, _("Input psVector contains no elements.  No data to perform operation with."));
+            psUnaryOp_EXIT;
+        }
+
+        out = psVectorRecycle(out, ((psVector*)in)->n, psTypeIn->type);
+        if (out == NULL) {
+            psError(PS_ERR_UNKNOWN, false, _("Couldn't create a proper output psVector."));
+            psUnaryOp_EXIT;
+        }
+        ((psVector*)out)->n = ((psVector*)in)->n;
+
+        UNARY_OP(VECTOR, out, psTypeIn, op);    // vector
+        break;
+    case PS_DIMEN_IMAGE:
+        if (((psImage* ) in)->numCols == 0 || ((psImage* ) in)->numRows == 0) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true, _("Input psImage contains no pixels.  No data to perform operation with."));
+            psUnaryOp_EXIT;
+        }
+
+        out = psImageRecycle(out, ((psImage*)in)->numCols, ((psImage*)in)->numRows, psTypeIn->type);
+        if (out == NULL) {
+            psError(PS_ERR_UNKNOWN, false, _("Couldn't create a proper output psImage."));
+            psUnaryOp_EXIT;
+        }
+
+        UNARY_OP(IMAGE, out, psTypeIn, op);     // image
+        break;
+    default:
+        if (out != in) {
+            psFree(out);
+        }
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, _("Specified parameter, %s, has invalid dimensionality, %d."), "in", psTypeIn->dimen);
+        psUnaryOp_EXIT;
+    }
+
+    // Automtically free psScalar types, since they are usually allocated in the argument list when this
+    // function is called, provided that the input is not the output.
+    if (psTypeIn->dimen == PS_DIMEN_SCALAR && in!=out) {
+        psFree(in);
+    }
+
+    return out;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psUnaryOp.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psUnaryOp.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psUnaryOp.h	(revision 22158)
@@ -0,0 +1,66 @@
+/* @file  psUnaryOp.h
+ *
+ * @brief Provides unary functions for simple matrix and vector element operations
+ *
+ * Defined unary functions include:
+ *
+ *     Addition (+)
+ *     Subtraction (-)
+ *     Multiplication (*)
+ *     Division (/)
+ *     Power (^)
+ *     Minimum (min)
+ *     Maximum (max)
+ *     Absolute value (abs)
+ *     Exponent (exp)
+ *     Natural Log (ln)
+ *     Power of 10 (ten)
+ *     Log (log)
+ *     Sine (sin or dsin)
+ *     Cosine (cos or dcos)
+ *     Tangent (tan or dtan)
+ *     Arcsine (asin or dasin)
+ *     Arccosine (acos or dacos)
+ *     Arctan (atan or datan)
+ *
+ * Currently only vector-vector and image-image binary operations are supported.
+ *
+ * @author EAM, IfA
+ * @author Ross Harman, MHPCC
+ * @author Robert DeSonia, MHPCC
+ *
+ * @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-01-23 22:47:23 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PSUNARY_OP_H
+#define PSUNARY_OP_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+/** Perform simple unary arithmetic with images or vectors
+ *
+ *  Performs absolute value, exponent, natural log, power of 10, log, sine, cosine, tangent, arcsine,
+ *  arccosine, or arctan. operations with images and vectors. Uses the form:
+ *
+ *     out = op(in),
+ *
+ *     Where op is: "abs", "exp", "ln", "ten", "log", "sin", "cos", "tan" "asin", "acos", "atan", "dsin",
+ *                  "dcos", dtan", "dasin", "dacos", or "datan".
+ *
+ *  Trigometric Operations with "d" prefix use units of degrees. Those without are in radians.
+ *
+ *  This function only supports vector-vector or image-image opertions.
+ *
+ *  @return  psType* : Pointer to either psImage or psVector.
+ */
+psMathType* psUnaryOp(
+    psPtr out,                         ///< Output type, either psImage or psVector.
+    const psPtr in,                    ///< Input, either psImage or psVector.
+    const char *op                     ///< Operator.
+);
+
+/// @}
+#endif // #ifndef PSUNARY_OP_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psVectorSmooth.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psVectorSmooth.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psVectorSmooth.c	(revision 22158)
@@ -0,0 +1,171 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <unistd.h>
+
+#include "psMemory.h"
+#include "psError.h"
+#include "psLogMsg.h"
+#include "psVector.h"
+#include "psAssert.h"
+#include "psConstants.h"
+
+#include "psVectorSmooth.h"
+
+psVector *psVectorSmooth(psVector *output,
+                         const psVector *input,
+                         double sigma,
+                         double Nsigma
+                        )
+{
+    PS_ASSERT_VECTOR_NON_NULL(input, NULL);
+    PS_ASSERT_FLOAT_LARGER_THAN(sigma, 0.0, NULL);
+    PS_ASSERT_FLOAT_LARGER_THAN(Nsigma, 0.0, NULL);
+
+    if (output == input) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Cannot smooth vector in-place.");
+        return false;
+    }
+
+    // relevant terms
+    long Nrange = sigma*Nsigma + 0.5;   // Extent of smoothing
+    long Npixel = 2*Nrange + 1;         // Total size of smoothing kernel
+    long Nbin = input->n;               // Number of elements
+    double factor = -0.5/(sigma*sigma); // Factor for Gaussian
+
+    #define VECTOR_SMOOTH_CASE(TYPE) \
+case PS_TYPE_##TYPE: { \
+        output = psVectorRecycle(output, Nbin, PS_TYPE_##TYPE); \
+        /* generate normalized gaussian */ \
+        psVector *gaussnorm = psVectorAlloc(Npixel, PS_TYPE_##TYPE); \
+        double sum = 0.0; \
+        for (long i = -Nrange; i < Nrange + 1; i++) { \
+            gaussnorm->data.TYPE[i+Nrange] = exp(factor*i*i); \
+            sum += gaussnorm->data.TYPE[i+Nrange]; \
+        } \
+        for (long i = -Nrange; i < Nrange + 1; i++) { \
+            gaussnorm->data.TYPE[i+Nrange] /= sum; \
+        } \
+        ps##TYPE *gauss = &gaussnorm->data.TYPE[Nrange]; \
+        \
+        /* smooth vector */ \
+        psVector *temp = psVectorAlloc(Nbin, PS_TYPE_##TYPE); \
+        ps##TYPE *vi = input->data.TYPE; \
+        ps##TYPE *vo = temp->data.TYPE; \
+        /* smooth first Nrange pixels, with renorm */ \
+        /* XXX need to check that this does not run over end for narrow vectors */ \
+        for (long i = 0; i < Nrange; i++, vi++, vo++) { \
+            ps##TYPE *vr = vi - i; \
+            ps##TYPE *vg = gauss - i; \
+            double g = 0; \
+            double s = 0; \
+            for (int n = -i; n < Nrange + 1; n++, vr++, vg++) { \
+                s += *vg * *vr; \
+                g += *vg; \
+            } \
+            *vo = s / g; \
+        } \
+        /* smooth middle pixels */ \
+        for (long i = Nrange; i < Nbin - Nrange; i++, vi++, vo++) { \
+            ps##TYPE *vr = vi - Nrange; \
+            ps##TYPE *vg = gauss - Nrange; \
+            double s = 0; \
+            for (int n = -Nrange; n < Nrange + 1; n++, vr++, vg++) { \
+                s += *vg * *vr; \
+            } \
+            *vo = s; \
+        } \
+        /* smooth last Nrange pixels, with renorm */ \
+        /* XXX does this miss the last column? */ \
+        for (long i = Nbin - Nrange; i < Nbin; i++, vi++, vo++) { \
+            ps##TYPE *vr = vi - Nrange; \
+            ps##TYPE *vg = gauss - Nrange; \
+            double g = 0; \
+            double s = 0; \
+            for (int n = -Nrange; n < Nbin - i - 1; n++, vr++, vg++) { \
+                s += *vg * *vr; \
+                g += *vg; \
+            } \
+            *vo = s / g; \
+        } \
+        memcpy(output->data.TYPE, temp->data.TYPE, Nbin*sizeof(ps##TYPE)); \
+        psFree(temp); \
+        psFree(gaussnorm); \
+        break; \
+    }
+
+    switch (input->type.type) {
+        VECTOR_SMOOTH_CASE(F32);
+        VECTOR_SMOOTH_CASE(F64);
+    default: {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr, input->type.type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Type %s is not valid.", typeStr);
+            return NULL;
+        }
+    }
+    return output;
+}
+
+
+
+psVector *psVectorBoxcar(psVector *output,
+                         const psVector *input,
+                         int size
+                        )
+{
+    PS_ASSERT_VECTOR_NON_NULL(input, NULL);
+    PS_ASSERT_INT_POSITIVE(size, NULL);
+
+    if (output == input) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Cannot smooth vector in-place.");
+        return false;
+    }
+
+    long num = input->n;                // Number of elements
+    output = psVectorRecycle(output, num, input->type.type);
+    psVector *nums = psVectorAlloc(num, PS_TYPE_U32); // Number of elements in each bin
+    psU32 *numsData = nums->data.U32;   // Dereferenced version
+
+    psVectorInit(output, 0.0);
+    psVectorInit(nums, 0);
+
+
+    #define VECTOR_BOXCAR_CASE(TYPE) \
+  case PS_TYPE_##TYPE: { \
+      /* Dereference data */ \
+      ps##TYPE *outputData = output->data.TYPE; \
+      ps##TYPE *inputData = input->data.TYPE; \
+      /* Smooth the vector */ \
+      for (long i = 0; i < num; i++) { \
+          for (long j = PS_MAX(0, i - size); j < PS_MIN(num, i + size + 1); j++) { \
+              outputData[j] += inputData[i]; \
+              numsData[j]++; \
+          } \
+      } \
+      /* Normalisation */ \
+      for (long i = 0; i < num; i++) { \
+          outputData[i] /= numsData[i]; \
+      } \
+      break; \
+  }
+
+    switch (input->type.type) {
+        VECTOR_BOXCAR_CASE(F32);
+        VECTOR_BOXCAR_CASE(F64);
+    default: {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr, input->type.type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Type %s is not valid.", typeStr);
+            psFree(nums);
+            return NULL;
+        }
+    }
+    psFree(nums);
+    return output;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/math/psVectorSmooth.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/math/psVectorSmooth.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/math/psVectorSmooth.h	(revision 22158)
@@ -0,0 +1,29 @@
+/* @file psVectorSmooth.h
+ * @brief smooth the input vector
+ *
+ * $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ * $Date: 2007-06-20 20:21:30 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_VECTOR_SMOOTH_H
+#define PS_VECTOR_SMOOTH_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+/// Smooth a vector with a Gaussian
+psVector *psVectorSmooth(psVector *output, ///< Output vector, or NULL
+                         const psVector *input, ///< Input vector (F32 or F64 only)
+                         double sigma,  ///< Gausian width (standard deviations)
+                         double Nsigma  ///< Number of standard deviations for Gaussian to extend
+                        );
+
+/// Smooth a vector with a boxcar
+psVector *psVectorBoxcar(psVector *output, ///< Output vector, or NULL
+                         const psVector *input, ///< Input vector (F32 or F64 only)
+                         int size       ///< Boxcar size (one-sided size)
+    );
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/.cvsignore	(revision 22158)
@@ -0,0 +1,10 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
+*.loT
+*.bb
+*.bbg
+*.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/Makefile.am	(revision 22158)
@@ -0,0 +1,18 @@
+#Makefile for mathtypes functions of psLib
+#
+noinst_LTLIBRARIES = libpslibmathtypes.la
+
+libpslibmathtypes_la_CPPFLAGS = $(SRCINC) $(PSLIB_CFLAGS) 
+libpslibmathtypes_la_SOURCES = \
+	psImage.c \
+	psScalar.c \
+	psVector.c
+
+EXTRA_DIST = mathtypes.i
+
+pkginclude_HEADERS = \
+	psImage.h \
+	psScalar.h \
+	psVector.h
+
+CLEANFILES = *~ *.bb *.bbg *.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/mathtypes.i
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/mathtypes.i	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/mathtypes.i	(revision 22158)
@@ -0,0 +1,5 @@
+/* mathtypes headers */
+
+%include "psImage.h"
+%include "psScalar.h"
+%include "psVector.h"
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/psImage.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/psImage.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/psImage.c	(revision 22158)
@@ -0,0 +1,613 @@
+/** @file  psImage.c
+ *
+ *  @brief Contains basic image definitions and operations.
+ *
+ *  This file defines the basic type for an image struct and functions useful
+ *  in manupulating images.
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.131 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-05 23:42:46 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ *  That is the routine used to generate matrices.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <math.h>
+#include <unistd.h>
+
+#include "psMemory.h"
+#include "psError.h"
+#include "psAssert.h"
+#include "psAbort.h"
+
+#include "psImage.h"
+#include "psString.h"
+
+
+static void imageFree(psImage* image)
+{
+    if (image == NULL) {
+        return;
+    }
+
+    psImage *parent = (psImage *) image->parent;
+
+    // if I am a child, remove me from my parent's array of children
+    if (parent != NULL) {
+        // sanity check : a child cannot also be a parent
+        if ((image->children != NULL) && (image->children->n > 0)) {
+            psAbort ("psImage cannot be both child and parent!");
+        }
+
+        // break the back-pointer first so we don't loop
+        image->parent = NULL;
+
+        // drop my entry on my parent's array of children
+        psArrayRemoveDataNoFree (parent->children, image);
+
+        // drop my reference to my parent
+        psFree (parent);
+    }
+
+    // sanity check: this function should never be reached if an image still has live children;
+    // they should each be holding a pointer to the image, forcing the number of references to
+    // be > 1.
+    if (image->children && (image->children->n > 0)) {
+        psAbort ("psImage memory management programming error : imageFree called on image with live children");
+    }
+
+    psFree(image->children);
+    psFree(image->p_rawDataBuffer);
+    psFree(image->data.V);
+}
+
+psImage* p_psImageAlloc(const char *file,
+                        unsigned int lineno,
+                        const char *func,
+                        int numCols,
+                        int numRows,
+                        psElemType type)
+{
+    int elementSize = PSELEMTYPE_SIZEOF(type);  // element size in bytes
+    int rowSize = numCols * elementSize;        // row size in bytes.
+
+    if (numRows < 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified number of rows (%d) or columns (%d) is invalid."),
+                numRows, numCols);
+        return NULL;
+    }
+    if (numCols < 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified number of rows (%d) or columns (%d) is invalid."),
+                numRows, numCols);
+        return NULL;
+    }
+
+    long numBytes = numRows * numCols * elementSize;
+
+    psImage* image = (psImage* ) p_psAlloc(file, lineno, func, sizeof(psImage));
+
+    psMemSetDeallocator(image, (psFreeFunc) imageFree);
+
+    image->data.V = p_psAlloc(file, lineno, func, sizeof(psPtr ) * numRows);
+
+    image->p_rawDataBuffer = p_psAlloc(file, lineno, func, numBytes);
+
+    // set the row pointers.
+    image->data.V[0] = image->p_rawDataBuffer;
+    for (psS32 i = 1; i < numRows; i++) {
+        image->data.V[i] = (psPtr )((int8_t *) image->data.V[i - 1] + rowSize);
+    }
+
+    P_PSIMAGE_SET_COL0 (image, 0);
+    P_PSIMAGE_SET_ROW0 (image, 0);
+    P_PSIMAGE_SET_NUMCOLS (image, numCols);
+    P_PSIMAGE_SET_NUMROWS (image, numRows);
+
+    psMathType imageType;
+    imageType.dimen = PS_DIMEN_IMAGE;
+    imageType.type = type;
+    P_PSIMAGE_SET_TYPE (image, imageType);
+
+    image->parent = NULL;
+    image->children = NULL;
+
+    return image;
+}
+
+
+bool psMemCheckImage(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)imageFree );
+}
+
+
+
+// Image initialisation for integer types
+#define IMAGEINIT_INTCASE(TYPE) \
+    case PS_TYPE_##TYPE: { \
+            if (value == 0.0) { \
+                size_t numBytes = image->numCols * sizeof(ps##TYPE); \
+                for (int y = 0; y < image->numRows; y++) { \
+                    memset(image->data.TYPE[y], 0, numBytes); \
+                } \
+            } else { \
+                if (value < (double)PS_MIN_##TYPE || value > (double)PS_MAX_##TYPE) { \
+                    psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Error: Value %f out of range for type %s.\n", \
+                            value, #TYPE); \
+                    return false; \
+                } \
+                ps##TYPE castValue = (ps##TYPE)value; \
+                for (int iy = 0; iy < image->numRows; iy++) { \
+                    ps##TYPE *row = image->data.TYPE[iy]; \
+                    for (int ix = 0; ix < image->numCols; ix++) { \
+                        row[ix] = castValue; \
+                    } \
+                } \
+            } \
+            return true; \
+        }
+
+// Image initialisation for char-size integer types
+#define IMAGEINIT_CHARCASE(TYPE) \
+    case PS_TYPE_##TYPE: { \
+            if (value < (double)PS_MIN_##TYPE || value > (double)PS_MAX_##TYPE) { \
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Error: Value %f out of range for type %s.\n", \
+                        value, #TYPE); \
+                return false; \
+            } \
+            size_t numBytes = image->numCols * sizeof(ps##TYPE); \
+            ps##TYPE castValue = (ps##TYPE)value; \
+            for (int y = 0; y < image->numRows; y++) { \
+                memset(image->data.TYPE[y], castValue, numBytes); \
+            } \
+            return true; \
+        }
+// Image initialisation for floating point types
+#define IMAGEINIT_FLOATCASE(TYPE) \
+    case PS_TYPE_##TYPE: { \
+            if (value == 0.0) { \
+                size_t numBytes = image->numCols * sizeof(ps##TYPE); \
+                for (int y = 0; y < image->numRows; y++) { \
+                    memset(image->data.TYPE[y], 0, numBytes); \
+                } \
+            } else { \
+                ps##TYPE castValue = (ps##TYPE)value; \
+                for (int iy = 0; iy < image->numRows; iy++) { \
+                    ps##TYPE *row = image->data.TYPE[iy]; \
+                    for (int ix = 0; ix < image->numCols; ix++) { \
+                        row[ix] = castValue; \
+                    } \
+                } \
+            } \
+            return true; \
+        }
+
+
+bool psImageInit (psImage *image, double value)
+{
+    PS_ASSERT_PTR(image, false);
+    PS_ASSERT_IMAGE_NON_NULL(image, false);
+
+    switch (image->type.type) {
+        IMAGEINIT_CHARCASE(U8)
+        IMAGEINIT_INTCASE(U16)
+        IMAGEINIT_INTCASE(U32)
+        IMAGEINIT_CHARCASE(S8)
+        IMAGEINIT_INTCASE(S16)
+        IMAGEINIT_INTCASE(S32)
+        IMAGEINIT_INTCASE(U64)
+        IMAGEINIT_INTCASE(S64)
+        IMAGEINIT_FLOATCASE(F32)
+        IMAGEINIT_FLOATCASE(F64)
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Type %x not supported", image->type.type);
+    }
+    return (false);
+}
+
+bool psImageSet(psImage *image,
+                int x,
+                int y,
+                double value)
+{
+    PS_ASSERT_IMAGE_NON_NULL(image, false);
+    PS_ASSERT_INT_NONNEGATIVE(image->col0, false);
+    PS_ASSERT_INT_NONNEGATIVE(image->row0, false);
+    PS_ASSERT_INT_POSITIVE(image->numCols, false);
+    PS_ASSERT_INT_POSITIVE(image->numRows, false);
+    if ( x >= (image->col0 + image->numCols) ) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                "Invalid x-position %d.  Position out of range (%d-%d)\n",
+                x, image->col0, image->numCols+image->col0-1 );
+        return false;
+    } else if ( y >= (image->row0 + image->numRows) ) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                "Invalid y-position %d.  Position out of range (%d-%d)\n",
+                y, image->row0, image->numRows+image->row0-1 );
+        return false;
+    } else if (x < image->col0 && x >= 0) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                "Invalid x-position %d.  Position out of range (%d-%d)\n",
+                x, image->col0, image->numCols+image->col0-1 );
+        return false;
+    } else if (y < image->row0 && y >= 0) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                "Invalid y-position %d.  Position out of range (%d-%d)\n",
+                y, image->row0, image->numRows+image->row0-1 );
+        return false;
+    } else if (x < 0 || y < 0) {
+        if (x < 0) {
+            x += image->numCols;
+        }
+        if (x < 0) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    "Invalid x-position %d.  Position out of range (%d-%d)\n",
+                    (x+image->col0), image->col0, image->numCols+image->col0-1 );
+            return false;
+        }
+        if (y < 0) {
+            y += image->numRows;
+        }
+        if (y < 0) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    "Invalid y-position %d.  Position out of range (%d-%d)\n",
+                    (y+image->row0), image->row0, image->numRows+image->row0-1 );
+            return false;
+        }
+    } else {
+        x -= image->col0;
+        y -= image->row0;
+    }
+
+    #define IMAGE_SET_CASE(TYPE) \
+case PS_TYPE_##TYPE: \
+    image->data.TYPE[y][x] = (ps##TYPE)value; \
+    break;
+
+    switch (image->type.type) {
+        IMAGE_SET_CASE(U8);
+        IMAGE_SET_CASE(U16);
+        IMAGE_SET_CASE(U32);
+        IMAGE_SET_CASE(U64);
+        IMAGE_SET_CASE(S8);
+        IMAGE_SET_CASE(S16);
+        IMAGE_SET_CASE(S32);
+        IMAGE_SET_CASE(S64);
+        IMAGE_SET_CASE(F32);
+        IMAGE_SET_CASE(F64);
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Invalid psImage Data Type\n");
+        return false;
+    }
+
+    return true;
+}
+
+double psImageGet(const psImage *image,
+                          int x,
+                          int y)
+{
+    PS_ASSERT_IMAGE_NON_NULL(image, NAN);
+    PS_ASSERT_INT_NONNEGATIVE(image->col0, NAN);
+    PS_ASSERT_INT_NONNEGATIVE(image->row0, NAN);
+    PS_ASSERT_INT_POSITIVE(image->numCols, NAN);
+    PS_ASSERT_INT_POSITIVE(image->numRows, NAN);
+    if ( x >= (image->col0 + image->numCols) ) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                "Invalid x-position %d.  Position out of range (%d-%d)\n",
+                x, image->col0, image->numCols+image->col0-1 );
+        return NAN;
+    } else if ( y >= (image->row0 + image->numRows) ) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                "Invalid y-position %d.  Position out of range (%d-%d)\n",
+                y, image->row0, image->numRows+image->row0-1 );
+        return NAN;
+    } else if (x < image->col0 && x >= 0) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                "Invalid x-position %d.  Position out of range (%d-%d)\n",
+                x, image->col0, image->numCols+image->col0-1 );
+        return NAN;
+    } else if (y < image->row0 && y >= 0) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                "Invalid y-position %d.  Position out of range (%d-%d)\n",
+                y, image->row0, image->numRows+image->row0-1 );
+        return NAN;
+    } else if (x < 0 || y < 0) {
+        if (x < 0) {
+            x += image->numCols;
+        }
+        if (x < 0) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    "Invalid x-position %d.  Position out of range (%d-%d)\n",
+                    (x+image->col0), image->col0, image->numCols+image->col0-1 );
+            return NAN;
+        }
+        if (y < 0) {
+            y += image->numRows;
+        }
+        if (y < 0) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    "Invalid y-position %d.  Position out of range (%d-%d)\n",
+                    (y+image->row0), image->row0, image->numRows+image->row0-1 );
+            return NAN;
+        }
+    } else {
+        x -= image->col0;
+        y -= image->row0;
+    }
+
+    #define IMAGE_GET_CASE(TYPE) \
+case PS_TYPE_##TYPE: \
+    return image->data.TYPE[y][x];
+
+    switch (image->type.type) {
+        IMAGE_GET_CASE(U8);
+        IMAGE_GET_CASE(U16);
+        IMAGE_GET_CASE(U32);
+        IMAGE_GET_CASE(U64);
+        IMAGE_GET_CASE(S8);
+        IMAGE_GET_CASE(S16);
+        IMAGE_GET_CASE(S32);
+        IMAGE_GET_CASE(S64);
+        IMAGE_GET_CASE(F32);
+        IMAGE_GET_CASE(F64);
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Invalid psImage Data Type\n");
+        return NAN;
+    }
+}
+
+psImage* p_psImageRecycle(const char *file,
+                        unsigned int lineno,
+                        const char *func,
+                        psImage* old,
+                        int numCols,
+                        int numRows,
+                        const psElemType type)
+{
+    psS32 elementSize = PSELEMTYPE_SIZEOF(type);  // element size in bytes
+    psS32 rowSize = numCols * elementSize;        // row size in bytes.
+
+    if (old == NULL) {
+        old = p_psImageAlloc(file, lineno, func, numCols, numRows, type);
+        return old;
+    }
+
+    if (old->type.dimen != PS_DIMEN_IMAGE) {
+        psFree(old);
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("The input psImage must have a PS_DIMEN_IMAGE dimension type."));
+        return NULL;
+    }
+
+    /* image already the right size/type? */
+    if (numCols == old->numCols && numRows == old->numRows &&
+            type == old->type.type) {
+        return old;
+    }
+    // Resize the image buffer
+    old->p_rawDataBuffer = psRealloc(old->data.V[0],
+                                     numCols * numRows * elementSize);
+    old->data.V = (psPtr *)psRealloc(old->data.V, numRows * sizeof(psPtr ));
+
+    // recreate the row pointers
+    old->data.V[0] = old->p_rawDataBuffer;
+    for (psS32 i = 1; i < numRows; i++) {
+        old->data.V[i] = (psPtr )((int8_t *) old->data.V[i - 1] + rowSize);
+    }
+
+    *(psU32 *)&old->numCols = numCols;
+    *(psU32 *)&old->numRows = numRows;
+    *(psElemType* ) & old->type.type = type;
+
+    return old;
+}
+
+bool p_psImageCopyToRawBuffer(void* buffer,
+                              const psImage* input,
+                              psElemType type)
+{
+    psElemType inDatatype;
+    psS32 numRows;
+    psS32 numCols;
+
+    if (input == NULL || input->data.V == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not operate on a NULL psImage."));
+        return false;
+    }
+
+    if (input->type.dimen != PS_DIMEN_IMAGE) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("The input psImage must have a PS_DIMEN_IMAGE dimension type."));
+        return false;
+    }
+
+    inDatatype = input->type.type;
+    numRows = input->numRows;
+    numCols = input->numCols;
+
+    // cover the trival case of copy of the same
+    // datatype.
+    if (type == inDatatype) {
+        int rowSize = PSELEMTYPE_SIZEOF(inDatatype)*numCols;
+        for (psS32 row=0;row<numRows;row++) {
+            memcpy(&((psS8*)buffer)[row*rowSize], input->data.V[row], rowSize);
+        }
+        return true;
+    }
+
+    #define PSIMAGE_BUFFER_COPY(INTYPE,OUTTYPE) { \
+        ps##INTYPE *in; \
+        ps##OUTTYPE *out = buffer; \
+        for(psS32 row=0;row<numRows;row++) { \
+            in = input->data.INTYPE[row]; \
+            for (psS32 col=0;col<numCols;col++) { \
+                *(out++) = *(in++); \
+            } \
+        } \
+    }
+
+    #define PSIMAGE_BUFFER_COPY_CASE(OUT,OUTTYPE) { \
+        switch (inDatatype) { \
+        case PS_TYPE_S8: \
+            PSIMAGE_BUFFER_COPY(S8,OUTTYPE); \
+            break; \
+        case PS_TYPE_S16: \
+            PSIMAGE_BUFFER_COPY(S16,OUTTYPE); \
+            break; \
+        case PS_TYPE_S32: \
+            PSIMAGE_BUFFER_COPY(S32,OUTTYPE); \
+            break; \
+        case PS_TYPE_S64: \
+            PSIMAGE_BUFFER_COPY(S64,OUTTYPE); \
+            break; \
+        case PS_TYPE_U8: \
+            PSIMAGE_BUFFER_COPY(U8,OUTTYPE); \
+            break; \
+        case PS_TYPE_U16: \
+            PSIMAGE_BUFFER_COPY(U16,OUTTYPE); \
+            break; \
+        case PS_TYPE_U32: \
+            PSIMAGE_BUFFER_COPY(U32,OUTTYPE); \
+            break; \
+        case PS_TYPE_U64: \
+            PSIMAGE_BUFFER_COPY(U64,OUTTYPE); \
+            break; \
+        case PS_TYPE_F32: \
+            PSIMAGE_BUFFER_COPY(F32,OUTTYPE); \
+            break; \
+        case PS_TYPE_F64: \
+            PSIMAGE_BUFFER_COPY(F64,OUTTYPE); \
+            break; \
+        default: \
+            break; \
+        } \
+    }
+
+    switch (type) {
+    case PS_TYPE_S8:
+        PSIMAGE_BUFFER_COPY_CASE(output, S8);
+        break;
+    case PS_TYPE_S16:
+        PSIMAGE_BUFFER_COPY_CASE(output, S16);
+        break;
+    case PS_TYPE_S32:
+        PSIMAGE_BUFFER_COPY_CASE(output, S32);
+        break;
+    case PS_TYPE_S64:
+        PSIMAGE_BUFFER_COPY_CASE(output, S64);
+        break;
+    case PS_TYPE_U8:
+        PSIMAGE_BUFFER_COPY_CASE(output, U8);
+        break;
+    case PS_TYPE_U16:
+        PSIMAGE_BUFFER_COPY_CASE(output, U16);
+        break;
+    case PS_TYPE_U32:
+        PSIMAGE_BUFFER_COPY_CASE(output, U32);
+        break;
+    case PS_TYPE_U64:
+        PSIMAGE_BUFFER_COPY_CASE(output, U64);
+        break;
+    case PS_TYPE_F32:
+        PSIMAGE_BUFFER_COPY_CASE(output, F32);
+        break;
+    case PS_TYPE_F64:
+        PSIMAGE_BUFFER_COPY_CASE(output, F64);
+        break;
+    default: {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    _("Specified psImage type, %s, is not supported."),
+                    typeStr);
+            break;
+        }
+    }
+    return true;
+}
+
+bool p_psImagePrint (int fd,
+                     psImage *a,
+                     char *name)
+{
+    write(fd,"matrix: ",8);
+    write(fd,name,strlen(name));
+    write(fd,"\n",1);
+
+    char buffer[20];
+    //    for (int j = 0; j < a[0].numRows; j++) {
+    //        for (int i = 0; i < a[0].numCols; i++) {
+    for (int j = 0; j < a->numRows; j++) {
+        for (int i = 0; i < a->numCols; i++) {
+            snprintf (buffer,20, "%f  ", p_psImageGetElementF64(a, i, j));
+            write(fd,buffer,strlen(buffer));
+        }
+        write(fd,"\n",1);
+    }
+    write(fd,"\n",1);
+    return (true);
+}
+
+
+psF64 p_psImageGetElementF64(psImage* image,
+                             int col,
+                             int row)
+{
+    if (image == NULL) {
+        return NAN;
+    }
+    if (col < 0 || col >= image->numCols) {
+        return NAN;
+    }
+    if (row < 0 || row >= image->numRows) {
+        return NAN;
+    }
+
+    switch (image->type.type) {
+    case PS_TYPE_U8:
+        return image->data.U8[row][col];
+        break;
+    case PS_TYPE_U16:
+        return image->data.U16[row][col];
+        break;
+    case PS_TYPE_U32:
+        return image->data.U32[row][col];
+        break;
+    case PS_TYPE_U64:
+        return image->data.U64[row][col];
+        break;
+    case PS_TYPE_S8:
+        return image->data.S8[row][col];
+        break;
+    case PS_TYPE_S16:
+        return image->data.S16[row][col];
+        break;
+    case PS_TYPE_S32:
+        return image->data.S32[row][col];
+        break;
+    case PS_TYPE_S64:
+        return image->data.S64[row][col];
+        break;
+    case PS_TYPE_F32:
+        return image->data.F32[row][col];
+        break;
+    case PS_TYPE_F64:
+        return image->data.F64[row][col];
+    default:
+        return NAN;
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/psImage.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/psImage.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/psImage.h	(revision 22158)
@@ -0,0 +1,292 @@
+/* @file  psImage.h
+ * @brief Basic image definitions and operations
+ *
+ * This file defines the basic type for an image struct and functions useful
+ * in manupulating images.
+ *
+ * @author Robert DeSonia, MHPCC
+ * @author Ross Harman, MHPCC
+ * @author Joshua Hoblitt, University of Hawaii
+ *
+ * @version $Revision: 1.96 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-12-07 19:33:19 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_IMAGE_H
+#define PS_IMAGE_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+#include <stdio.h>
+#include "psType.h"
+#include "psArray.h"
+#include "psConstants.h"
+
+
+/** Basic image data structure.
+ *
+ * Struct for maintaining image data of varying types. It also contains
+ * information about image size, parent images and children images.
+ *
+ */
+typedef struct psImage
+{
+    const psMathType type;             ///< Image data type and dimension.
+    const int numCols;                 ///< Number of columns in image
+    const int numRows;                 ///< Number of rows in image.
+    const int col0;                     ///< Column position relative to parent.
+    const int row0;                     ///< Row position relative to parent.
+
+    union {
+        psS8**  S8;                    ///< Signed 8-bit integer data.
+        psS16** S16;                   ///< Signed 16-bit integer data.
+        psS32** S32;                   ///< Signed 32-bit integer data.
+        psS64** S64;                   ///< Signed 64-bit integer data.
+        psU8**  U8;                    ///< Unsigned 8-bit integer data.
+        psU16** U16;                   ///< Unsigned 16-bit integer data.
+        psU32** U32;                   ///< Unsigned 32-bit integer data.
+        psU64** U64;                   ///< Unsigned 64-bit integer data.
+        psF32** F32;                   ///< Single-precision float data.
+        psF64** F64;                   ///< Double-precision float data.
+        psPtr*  V;                     ///< Pointer to data.
+    } data;                            ///< Union for data types.
+    const struct psImage* parent;      ///< Parent, if a subimage.
+    psPtr p_rawDataBuffer;             ///< Raw data buffer for Allocating/Freeing Images; private
+    psArray* children;                 ///< Children of this region.
+    void *lock;                        ///< Optional lock for thread safety
+}
+psImage;
+
+
+#define P_PSIMAGE_SET_NUMCOLS(img,nc) {*(int*)&img->numCols = nc;}
+#define P_PSIMAGE_SET_NUMROWS(img,nr) {*(int*)&img->numRows = nr;}
+#define P_PSIMAGE_SET_COL0(img,c0) {*(int*)&img->col0 = c0;}
+#define P_PSIMAGE_SET_ROW0(img,r0) {*(int*)&img->row0 = r0;}
+#define P_PSIMAGE_SET_TYPE(img,t) {*(psMathType*)&img->type = t;}
+
+/** Create an image of the specified size and type.
+ *
+ * Uses psLib memory allocation functions to create an image struct of the
+ * specified size and type.
+ *
+ * @return psImage* : Pointer to psImage.
+ *
+ */
+#ifdef DOXYGEN
+psImage* psImageAlloc(
+    int numCols,                       ///< Number of columns in image.
+    int numRows,                       ///< Number of rows in image.
+    psElemType type                    ///< Type of data for image.
+);
+#else // ifdef DOXYGEN
+psImage* p_psImageAlloc(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    int numCols,                       ///< Number of columns in image.
+    int numRows,                       ///< Number of rows in image.
+    psElemType type                    ///< Type of data for image.
+) PS_ATTR_MALLOC;
+#define psImageAlloc(numCols, numRows, type) \
+      p_psImageAlloc(__FILE__, __LINE__, __func__, numCols, numRows, type)
+#endif // ifdef DOXYGEN
+
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr * datatype.
+ *  @return bool:       True if the pointer matches a psImage structure, false otherwise.
+ */
+bool psMemCheckImage(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+/** Initializes the image with the given value.
+ *
+ *  The input data is cast to match the image datatype.
+ *
+ *  @return bool:       True on success, otherwise false.
+ */
+bool psImageInit(
+    psImage *image,                    ///< the image to be initialized
+    double value                        ///< Value to which to initialise
+);
+
+
+/** Sets the value of the image at the specified x,y position to value.
+ *
+ *  A negative value for the x or y positions means index from the end.
+ *
+ *  @return bool:       True on success, otherwise false.
+ */
+bool psImageSet(
+    psImage *image,                     ///< the image to set
+    int x,                              ///< x-position
+    int y,                              ///< y-position
+    double value                        ///< specified value to set
+);
+
+/** Returns the value of the image at the specified x,y position.
+ *
+ *  A negative value for the x or y positions means index from the end.
+ *
+ *  @return double: The value at the specified x,y position.
+ */
+double psImageGet(
+    const psImage *image,              ///< the image from which to get
+    int x,                             ///< x-position
+    int y                              ///< y-position
+);
+
+/** Resize a given image to the given size/type.
+ *
+ *  @return psImage* Resized psImage.
+ */
+#ifdef DOXYGEN
+psImage* psImageRecycle(
+    psImage* old,                      ///< the psImage to recycle by resizing image buffer
+    int numCols,                       ///< the desired number of columns in image
+    int numRows,                       ///< the desired number of rows in image
+    const psElemType type              ///< the desired datatype of the image
+);
+#else // ifdef DOXYGEN
+psImage* p_psImageRecycle(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psImage* old,                      ///< the psImage to recycle by resizing image buffer
+    int numCols,                       ///< the desired number of columns in image
+    int numRows,                       ///< the desired number of rows in image
+    const psElemType type              ///< the desired datatype of the image
+);
+#define psImageRecycle(old, numCols, numRows, type) \
+      p_psImageRecycle(__FILE__, __LINE__, __func__, old, numCols, numRows, type)
+#endif // ifdef DOXYGEN
+
+
+/** Copy an image to a new buffer
+ *
+ *  @return True if image copied or false if error
+ */
+bool p_psImageCopyToRawBuffer(
+    void* buffer,                      ///< the buffer used to copy the image
+    const psImage* input,              ///< the input image to be copied
+    psElemType type                    ///< the datatype of the image to be copied
+);
+
+
+/** Frees all children of a psImage.
+ *
+ *  @return int      Number of children freed.
+ */
+int psImageFreeChildren(
+    psImage* image                     ///< psImage in which all children shall be deallocated
+);
+
+
+/** get an element of an image as a psF64.
+ *
+ *  @return psF64   pixel value at specified location
+ */
+psF64 p_psImageGetElementF64(
+    psImage* image,                    ///< input image
+    int col,                           ///< pixel column
+    int row                            ///< pixel row
+);
+
+
+/** print image pixel values.
+ *
+ *  @return bool    TRUE is successful, otherwise FALSE.
+ */
+bool p_psImagePrint(
+    int fd,                            ///< Destination file descriptor
+    psImage *a,                        ///< image to print
+    char *name                         ///< name of the image (for title)
+);
+
+
+
+
+/*****************************************************************************
+    PS_IMAGE macros:
+*****************************************************************************/
+#define PS_ASSERT_IMAGE_NON_NULL(NAME, RVAL) PS_ASSERT_GENERAL_IMAGE_NON_NULL(NAME, return RVAL)
+#define PS_ASSERT_GENERAL_IMAGE_NON_NULL(NAME, CLEANUP) \
+if ((NAME) == NULL || (NAME)->data.V == NULL) { \
+    psError(PS_ERR_BAD_PARAMETER_NULL, true, \
+            "Unallowable operation: psImage %s or its data is NULL.", \
+            #NAME); \
+    CLEANUP; \
+}
+
+#define PS_ASSERT_IMAGE_NON_EMPTY(NAME, RVAL) PS_ASSERT_GENERAL_IMAGE_NON_EMPTY(NAME, return RVAL)
+#define PS_ASSERT_GENERAL_IMAGE_NON_EMPTY(NAME, CLEANUP) \
+if ((NAME)->numCols < 1 || (NAME)->numRows < 1) { \
+    psError(PS_ERR_BAD_PARAMETER_SIZE, true, \
+            "Unallowable operation: psImage %s has zero rows or columns (%dx%d).", \
+            #NAME, (NAME)->numCols, (NAME)->numRows); \
+    CLEANUP; \
+}
+
+#define PS_ASSERT_IMAGE_TYPE(NAME, TYPE, RVAL) \
+if ((NAME)->type.type != TYPE) { \
+    char *imageType, *desiredType; \
+    PS_TYPE_NAME(imageType, (NAME)->type.type); \
+    PS_TYPE_NAME(desiredType, TYPE); \
+    psError(PS_ERR_BAD_PARAMETER_TYPE, true, \
+            "Unallowable operation: psImage %s has incorrect type: %s instead of %s.", \
+            #NAME, imageType, desiredType); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_IMAGE_TYPE_F32_OR_F64(NAME, RVAL) \
+if ((NAME)->type.type != PS_TYPE_F32 && (NAME)->type.type != PS_TYPE_F64) { \
+    char *imageType; \
+    PS_TYPE_NAME(imageType, (NAME)->type.type); \
+    psError(PS_ERR_BAD_PARAMETER_TYPE, true, \
+            "Unallowable operation: psImage %s is not of type F32 or F64: %s.", \
+            #NAME, imageType); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_IMAGES_SIZE_EQUAL(NAME1, NAME2, RVAL) \
+if (((NAME1)->numCols != (NAME2)->numCols) || \
+        ((NAME1)->numRows != (NAME2)->numRows)) { \
+    psError(PS_ERR_BAD_PARAMETER_SIZE, true, \
+            "Unallowable operation: psImages %s and %s are not the same size: %dx%d vs %dx%d.", \
+            #NAME1, #NAME2, (NAME1)->numCols, (NAME1)->numRows, (NAME2)->numCols, (NAME2)->numRows); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_IMAGE_SIZE(NAME1, NUM_COLS, NUM_ROWS, RVAL) \
+if (((NAME1)->numCols != NUM_COLS) || \
+        ((NAME1)->numRows != NUM_ROWS)) { \
+    psError(PS_ERR_BAD_PARAMETER_SIZE, true, \
+            "Unallowable operation: psImages %s is not the correct size: %dx%d instead of %dx%d.", \
+            #NAME1, (NAME1)->numCols, (NAME1)->numRows, NUM_COLS, NUM_ROWS); \
+    return(RVAL); \
+}
+
+#define PS_IMAGE_PRINT_F32(NAME) \
+printf("======== printing %s ========\n", #NAME); \
+for (int i = 0 ; i < (NAME)->numRows ; i++) { \
+    for (int j = 0 ; j < (NAME)->numCols ; j++) { \
+        printf("%.2f ", (NAME)->data.F32[i][j]); \
+    } \
+    printf("\n"); \
+}\
+
+#define PS_IMAGE_PRINT_F64(NAME) \
+printf("======== printing %s ========\n", #NAME); \
+for (int i = 0 ; i < (NAME)->numRows ; i++) { \
+    for (int j = 0 ; j < (NAME)->numCols ; j++) { \
+        printf("%.2f ", (NAME)->data.F64[i][j]); \
+    } \
+    printf("\n"); \
+}\
+
+/// @}
+#endif // PS_IMAGE_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/psScalar.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/psScalar.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/psScalar.c	(revision 22158)
@@ -0,0 +1,154 @@
+/** @file  psScalar.c
+ *
+ *  @brief Contains basic scalar definitions and operations
+ *
+ *  This file defines the basic type for a scalar struct and functions useful
+ *  in manupulating scalars.
+ * *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.28.26.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-28 04:03:48 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "psMemory.h"
+#include "psError.h"
+#include "psScalar.h"
+#include "psLogMsg.h"
+#include "psAbort.h"
+#include "psAssert.h"
+
+
+static void scalarFree(psScalar *scalar)
+{
+    // There are non dynamic allocated items
+}
+
+// XXX this function is badly designed for int types.  we should be using a var-arg syntax so
+// we can actually pass the value correctly casted.
+psScalar* p_psScalarAlloc(const char *file,
+                          unsigned int lineno,
+                          const char *func,
+                          double value,
+                          psElemType type)
+{
+    psScalar* scalar = NULL;
+
+    // Create scalar
+    scalar = (psScalar* ) p_psAlloc(file, lineno, func, sizeof(psScalar));
+    psMemSetDeallocator(scalar, (psFreeFunc)scalarFree);
+    scalar->type.dimen = PS_DIMEN_SCALAR;
+    scalar->type.type = type;
+
+    switch (type) {
+    case PS_TYPE_S8:
+        scalar->data.S8 = (psS8) value;
+        break;
+    case PS_TYPE_U8:
+        scalar->data.U8 = (psU8) value;
+        break;
+    case PS_TYPE_S16:
+        scalar->data.S16 = (psS16) value;
+        break;
+    case PS_TYPE_U16:
+        scalar->data.U16 = (psU16) value;
+        break;
+    case PS_TYPE_S32:
+        scalar->data.S32 = (psS32) value;
+        break;
+    case PS_TYPE_U32:
+        scalar->data.U32 = (psU32) value;
+        break;
+    case PS_TYPE_S64:
+        scalar->data.S64 = (psS64) value;
+        break;
+    case PS_TYPE_U64:
+        scalar->data.U64 = (psU64) value;
+        break;
+    case PS_TYPE_F32:
+        scalar->data.F32 = (psF32) value;
+        break;
+    case PS_TYPE_F64:
+        scalar->data.F64 = (psF64) value;
+        break;
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("Specified datatype (%d) is unsupported by psScalar."),
+                type);
+        psFree(scalar);
+        return NULL;
+    }
+
+    return scalar;
+}
+
+
+
+bool psMemCheckScalar(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, NULL);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)scalarFree );
+}
+
+
+psScalar* p_psScalarCopy(const char *file,
+                       unsigned int lineno,
+                       const char *func,
+                       const psScalar *value)
+{
+    psElemType dataType;
+    psScalar *newScalar = NULL;
+
+    if (value == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not copy a NULL psScalar."));
+        return NULL;
+    }
+
+    dataType = value->type.type;
+    switch (dataType) {
+    case PS_TYPE_S8:
+        newScalar =  p_psScalarAlloc(file, lineno, func, value->data.S8, dataType);
+        break;
+    case PS_TYPE_U8:
+        newScalar =  p_psScalarAlloc(file, lineno, func, value->data.U8, dataType);
+        break;
+    case PS_TYPE_S16:
+        newScalar =  p_psScalarAlloc(file, lineno, func, value->data.S16, dataType);
+        break;
+    case PS_TYPE_U16:
+        newScalar =  p_psScalarAlloc(file, lineno, func, value->data.U16, dataType);
+        break;
+    case PS_TYPE_S32:
+        newScalar =  p_psScalarAlloc(file, lineno, func, value->data.S32, dataType);
+        break;
+    case PS_TYPE_U32:
+        newScalar =  p_psScalarAlloc(file, lineno, func, value->data.U32, dataType);
+        break;
+    case PS_TYPE_S64:
+        newScalar =  p_psScalarAlloc(file, lineno, func, value->data.S64, dataType);
+        break;
+    case PS_TYPE_U64:
+        newScalar =  p_psScalarAlloc(file, lineno, func, value->data.U64, dataType);
+        break;
+    case PS_TYPE_F32:
+        newScalar =  p_psScalarAlloc(file, lineno, func, value->data.F32, dataType);
+        break;
+    case PS_TYPE_F64:
+        newScalar =  p_psScalarAlloc(file, lineno, func, value->data.F64, dataType);
+        break;
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("Specified datatype (%d) is unsupported by psScalar."),
+                dataType);
+        return NULL;
+    }
+
+    return newScalar;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/psScalar.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/psScalar.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/psScalar.h	(revision 22158)
@@ -0,0 +1,112 @@
+/* @file  psScalar.h
+ * @brief Basic scalar definitions and operations
+ *
+ * This file defines the basic type for a scalar struct and functions useful
+ * in manupulating scalars.
+ *
+ * @author Ross Harman, MHPCC
+ * @author Joshua Hoblitt, University of Hawaii
+ *
+ * @version $Revision: 1.24 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-08-09 01:40:07 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_SCALAR_H
+#define PS_SCALAR_H
+
+/// @addtogroup MathOps Mathematical Operations
+/// @{
+
+#include "psType.h"
+
+/** Basic scalar data structure.
+ *
+ * Struct for maintaining a scalar of frequently used primitive types.
+ *
+ */
+typedef struct
+{
+    psMathType type;            ///< Type of data.
+
+    union {
+        psS8 S8;                ///< Signed 8-bit integer data.
+        psS16 S16;              ///< Signed 16-bit integer data.
+        psS32 S32;              ///< Signed 32-bit integer data.
+        psS64 S64;              ///< Signed 64-bit integer data.
+        psU8 U8;                ///< Unsigned 8-bit integer data.
+        psU16 U16;              ///< Unsigned 16-bit integer data.
+        psU32 U32;              ///< Unsigned 32-bit integer data.
+        psU64 U64;              ///< Unsigned 64-bit integer data.
+        psF32 F32;              ///< Single-precision float data.
+        psF64 F64;              ///< Double-precision float data.
+    } data;                     ///< Union for data types.
+}
+psScalar;
+
+/*****************************************************************************/
+
+/* FUNCTION PROTOTYPES                                                       */
+
+/*****************************************************************************/
+
+/** Allocate a scalar.
+ *
+ * Uses psLib memory allocation functions to create scalar data as defined by the psType type.
+ * Accepts a double for input value, as max size, but resizes according to correct type.
+ *
+ * @return psScalar*   Pointer to a new psScalar.
+ */
+#ifdef DOXYGEN
+psScalar* psScalarAlloc(
+    double value,                       ///< Data to be put into psScalar
+    psElemType type                     ///< Type of data to be held by psScalar
+);
+#else // ifdef DOXYGEN
+psScalar* p_psScalarAlloc(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    double value,                       ///< Data to be put into psScalar
+    psElemType type                     ///< Type of data to be held by psScalar
+) PS_ATTR_MALLOC;
+#define psScalarAlloc(value, type) \
+      p_psScalarAlloc(__FILE__, __LINE__, __func__, value, type)
+#endif // ifdef DOXYGEN
+
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psScalar structure, false otherwise.
+ */
+bool psMemCheckScalar(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+
+/** Copy a scalar.
+ *
+ * Uses psLib memory allocation functions to copy a scalar.
+ *
+ * @return psScalar*    A copy of the input scalar
+ */
+#ifdef DOXYGEN
+psScalar* psScalarCopy(
+    const psScalar *value               ///< Scalar to copy
+);
+#else // ifdef DOXYGEN
+psScalar* p_psScalarCopy(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    const psScalar *value               ///< Scalar to copy.
+);
+#define psScalarCopy(value) \
+      p_psScalarCopy(__FILE__, __LINE__, __func__, value)
+#endif // ifdef DOXYGEN
+
+
+/// @}
+#endif // #ifndef PS_SCALAR_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/psVector.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/psVector.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/psVector.c	(revision 22158)
@@ -0,0 +1,990 @@
+/** @file  psVector.c
+*
+*  @brief Contains support for basic vector types
+*
+*  This file defines the basic type for a vector struct and functions useful
+*  in manupulating vectors.
+*
+*  @author Ross Harman, MHPCC
+*  @author Robert DeSonia, MHPCC
+*  @author Joshua Hoblitt, University of Hawaii
+*
+*  @version $Revision: 1.102 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2008-06-24 21:32:52 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>                        // for memcpy
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <unistd.h>
+
+#include "psMemory.h"
+#include "psError.h"
+#include "psVector.h"
+#include "psLogMsg.h"
+#include "psCompare.h"
+#include "psAssert.h"
+#include "psString.h"
+#include "psSort.h"
+
+static void vectorFree(psVector* psVec)
+{
+    if (psVec == NULL) {
+        return;
+    }
+
+    psFree(psVec->data.U8);
+}
+
+// FUNCTION IMPLEMENTATION - PUBLIC
+bool psMemCheckVector(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)vectorFree );
+}
+
+
+// Allocate a psVector; does not set vector->n (left to the caller)
+static psVector *vectorAlloc(const char *file,
+                             unsigned int lineno,
+                             const char *func,
+                             long nalloc, // Number of elements to allocate
+                             psElemType type) // Type of elements
+{
+    int elementSize = PSELEMTYPE_SIZEOF(type); // Size, in bytes, of element
+    if (elementSize < 1) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("Input psVector is an unsupported type (0x%x)."), type);
+        return NULL;
+    }
+
+    // Create vector struct
+    psVector *vector = (psVector*) p_psAlloc(file, lineno, func, sizeof(psVector));
+    psMemSetDeallocator(vector, (psFreeFunc) vectorFree);
+
+    vector->type.dimen = PS_DIMEN_VECTOR;
+    vector->type.type = type;
+    P_PSVECTOR_SET_NALLOC(vector, nalloc);
+
+    // Create vector data array
+    vector->data.U8 = psAlloc(nalloc * elementSize);
+
+    return vector;
+}
+
+psVector* p_psVectorAlloc(const char *file,
+                          unsigned int lineno,
+                          const char *func,
+                          long nalloc,
+                          psElemType type)
+{
+    psVector *vector = vectorAlloc(file, lineno, func, nalloc, type);
+    if (!vector) {
+        return NULL;
+    }
+    vector->n = nalloc;
+    return vector;
+}
+
+psVector* p_psVectorAllocEmpty(const char *file,
+                               unsigned int lineno,
+                               const char *func,
+                               long nalloc,
+                               psElemType type)
+{
+    psVector *vector = vectorAlloc(file, lineno, func, nalloc, type);
+    if (!vector) {
+        return NULL;
+    }
+    vector->n = 0;
+    return vector;
+}
+
+psVector* psVectorRealloc(psVector* vector,
+                          long nalloc)
+{
+    psS32 elementSize = 0;
+    psElemType elemType;
+
+    if (vector == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("psVectorRealloc must a given a non-NULL psVector to resize.  Desired datatype unknown."));
+        return NULL;
+    } else if (vector->nalloc != nalloc) {     // No need to realloc to same size
+        elemType = vector->type.type;
+        elementSize = PSELEMTYPE_SIZEOF(elemType);
+        if (nalloc < vector->n) {
+            vector->n = nalloc;
+        }
+        // Realloc after decrementation to avoid accessing freed array elements
+        vector->data.U8 = psRealloc(vector->data.U8, nalloc * elementSize);
+        P_PSVECTOR_SET_NALLOC(vector,nalloc);
+    }
+
+    return vector;
+}
+
+psVector* p_psVectorRecycle(const char *file,
+                            unsigned int lineno,
+                            const char *func,
+                            psVector* vector,
+                            long nalloc,
+                            psElemType type)
+{
+    psS32 byteSize;
+
+    if (vector == NULL) {
+        return p_psVectorAlloc(file, lineno, func, nalloc, type);
+    }
+
+    if (vector->type.dimen !=  PS_DIMEN_VECTOR &&
+            vector->type.dimen !=  PS_DIMEN_TRANSV) {
+        psFree(vector);
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("The input psVector must have a vector dimension type."));
+        return NULL;
+    }
+
+    byteSize = nalloc * PSELEMTYPE_SIZEOF(type);
+
+    // need to increase data buffer?
+    if (byteSize > vector->nalloc*PSELEMTYPE_SIZEOF(vector->type.type)) {
+        vector->data.U8 = psRealloc(vector->data.U8, byteSize);
+        P_PSVECTOR_SET_NALLOC(vector,nalloc);
+    }
+
+    vector->type.dimen = PS_DIMEN_VECTOR;
+    vector->type.type = type;
+    vector->n = nalloc;
+    return vector;
+}
+
+psVector *psVectorExtend(psVector *vector,
+                         long delta,
+                         long nExtend)
+{
+    // can't handle a NULL vector (don't know the data type to allocate)
+    if (vector == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("The input psVector can not be NULL."));
+        return NULL;
+    }
+
+    // requirement on delta; if < 1, set to 10.
+    if (delta < 1) {
+        delta = 10;
+    }
+
+    // adjust the allocated size, if needed. (if nExtend < 1, this is will never happen)
+    if (nExtend > 0) {
+        unsigned int minAlloc = vector->n + nExtend + nExtend;
+        if (vector->nalloc < minAlloc) {
+            unsigned int nAlloc = delta + vector->nalloc;
+            // make sure the delta is large enough hold twice the extended length.
+            if (nAlloc < minAlloc) {
+                nAlloc = minAlloc;
+            }
+            vector = psVectorRealloc(vector, nAlloc);
+        }
+    } else if (nExtend < -vector->n) {
+        // For the case of a negative nExtend, need to check that we are not decreasing
+        // vector beyond its own length (i.e., creating a negative length).
+        nExtend = -vector->n;
+    }
+
+    // increment the length by the value specified
+    vector->n += nExtend;
+
+    return vector;
+}
+
+psVector* p_psVectorCopy(const char *file,
+                       unsigned int lineno,
+                       const char *func,
+                       psVector* output,
+                       const psVector* input,
+                       psElemType type)
+{
+    if (input == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("The input psVector can not be NULL."));
+        psFree(output);
+        return NULL;
+    }
+
+    psS32 nElements = input->n;
+
+    output = p_psVectorRecycle(file, lineno, func, output, nElements, type);
+    if (nElements == 0) {
+        //        psWarning("Warning: psVector was copied with 0 elements!\n");
+        return output;
+    }
+    output->n = nElements;
+
+    if (input->type.type == type) {
+        // Can simply copy the bytes if the types are the same
+
+        #define PSVECTOR_COPY_SAME_CASE(NAME) \
+    case PS_TYPE_##NAME: \
+        output->data.NAME = memcpy(output->data.NAME, input->data.NAME, \
+                                   input->n * PSELEMTYPE_SIZEOF(PS_TYPE_##NAME)); \
+        break;
+
+        switch (type) {
+            PSVECTOR_COPY_SAME_CASE(U8);
+            PSVECTOR_COPY_SAME_CASE(U16);
+            PSVECTOR_COPY_SAME_CASE(U32);
+            PSVECTOR_COPY_SAME_CASE(U64);
+            PSVECTOR_COPY_SAME_CASE(S8);
+            PSVECTOR_COPY_SAME_CASE(S16);
+            PSVECTOR_COPY_SAME_CASE(S32);
+            PSVECTOR_COPY_SAME_CASE(S64);
+            PSVECTOR_COPY_SAME_CASE(F32);
+            PSVECTOR_COPY_SAME_CASE(F64);
+        default: {
+                char* typeStr;
+                PS_TYPE_NAME(typeStr,type);
+                psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                        //                        _("Input psVector is an unsupported type (0x%x)."), typeStr);
+                        "Input psVector is an unsupported type.\n");
+                psFree(output);
+                return NULL;
+            }
+        }
+        return output;
+    }
+
+    #define PSVECTOR_COPY(INTYPE,OUTTYPE) { \
+        ps##INTYPE *inVec = input->data.INTYPE; \
+        ps##OUTTYPE *outVec = output->data.OUTTYPE; \
+        for (psS32 col=0;col<nElements;col++) { \
+            *(outVec++) = *(inVec++); \
+        } \
+    }
+
+    #define PSVECTOR_COPY_CASE(OUTTYPE) \
+case PS_TYPE_##OUTTYPE: { \
+        switch (input->type.type) { \
+        case PS_TYPE_S8: \
+            PSVECTOR_COPY(S8,OUTTYPE); \
+            break; \
+        case PS_TYPE_S16: \
+            PSVECTOR_COPY(S16,OUTTYPE); \
+            break; \
+        case PS_TYPE_S32: \
+            PSVECTOR_COPY(S32,OUTTYPE); \
+            break; \
+        case PS_TYPE_S64: \
+            PSVECTOR_COPY(S64,OUTTYPE); \
+            break; \
+        case PS_TYPE_U8: \
+            PSVECTOR_COPY(U8,OUTTYPE); \
+            break; \
+        case PS_TYPE_U16: \
+            PSVECTOR_COPY(U16,OUTTYPE); \
+            break; \
+        case PS_TYPE_U32: \
+            PSVECTOR_COPY(U32,OUTTYPE); \
+            break; \
+        case PS_TYPE_U64: \
+            PSVECTOR_COPY(U64,OUTTYPE); \
+            break; \
+        case PS_TYPE_F32: \
+            PSVECTOR_COPY(F32,OUTTYPE); \
+            break; \
+        case PS_TYPE_F64: \
+            PSVECTOR_COPY(F64,OUTTYPE); \
+            break; \
+        default: { \
+                char* typeStr; \
+                PS_TYPE_NAME(typeStr,type); \
+                psError(PS_ERR_BAD_PARAMETER_TYPE, true, \
+                        _("Input psVector is an unsupported type (0x%s)."), \
+                        typeStr); \
+                psFree(output); \
+            } \
+        } \
+        break; \
+    }
+
+    switch (type) {
+        PSVECTOR_COPY_CASE(S8);
+        PSVECTOR_COPY_CASE(S16);
+        PSVECTOR_COPY_CASE(S32);
+        PSVECTOR_COPY_CASE(S64);
+        PSVECTOR_COPY_CASE(U8);
+        PSVECTOR_COPY_CASE(U16);
+        PSVECTOR_COPY_CASE(U32);
+        PSVECTOR_COPY_CASE(U64);
+        PSVECTOR_COPY_CASE(F32);
+        PSVECTOR_COPY_CASE(F64);
+    default: {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    _("Input psVector is an unsupported type (0x%s)."),
+                    typeStr);
+            psFree(output);
+            output = NULL;
+            break;
+        }
+    }
+    return output;
+
+
+}
+
+
+// Comparison and swap functions for sorting values directly
+#define PSVECTOR_SORT_COMPARE_DIRECT(A,B) (value[A] < value[B])
+#define PSVECTOR_SORT_SWAP_DIRECT(TYPE,A,B) { \
+    if (A != B) { \
+        ps##TYPE temp = value[A]; \
+        value[A] = value[B]; \
+        value[B] = temp; \
+    } \
+}
+
+// Comparison and swap functions for sorting vector indices
+#define PSVECTOR_SORT_COMPARE_INDEX(A,B) (value[index[A]] < value[index[B]])
+#define PSVECTOR_SORT_SWAP_INDEX(TYPE,A,B) { \
+    if (A != B) { \
+        ps##TYPE temp = index[A]; \
+        index[A] = index[B]; \
+        index[B] = temp; \
+    } \
+}
+
+#define PSVECTOR_SORT_CASE(ELEMTYPE, COMPAREEXPR, SWAPFUNC, SWAPTYPE) \
+case PS_TYPE_##ELEMTYPE: { \
+    ps##ELEMTYPE *value = vector->data.ELEMTYPE; \
+    PSSORT(vector->n, COMPAREEXPR, SWAPFUNC, SWAPTYPE); \
+    break; \
+}
+
+bool psVectorSortInPlace(const psVector *vector)
+{
+    PS_ASSERT_VECTOR_NON_NULL(vector, false);
+
+    if (vector->n < 2) {
+        // Already sorted!
+        return true;
+    }
+
+    switch (vector->type.type) {
+        PSVECTOR_SORT_CASE(U8 , PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, U8 );
+        PSVECTOR_SORT_CASE(U16, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, U16);
+        PSVECTOR_SORT_CASE(U32, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, U32);
+        PSVECTOR_SORT_CASE(U64, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, U64);
+        PSVECTOR_SORT_CASE(S8 , PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, S8 );
+        PSVECTOR_SORT_CASE(S16, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, S16);
+        PSVECTOR_SORT_CASE(S32, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, S32);
+        PSVECTOR_SORT_CASE(S64, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, S64);
+        PSVECTOR_SORT_CASE(F32, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, F32);
+        PSVECTOR_SORT_CASE(F64, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, F64);
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("Input psVector is an unsupported type (0x%x)."),
+                vector->type.type);
+        return false;
+    }
+    return true;
+}
+
+psVector* psVectorSort(psVector* outVector,
+                       const psVector* inVector)
+{
+    if (!inVector) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("psVectorSort can not sort a NULL psVector."));
+        psFree(outVector);
+        return NULL;
+    }
+
+    if (outVector != inVector) {
+        outVector = psVectorCopy(outVector, inVector, inVector->type.type);
+        if (!outVector) {
+            psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                    "Error in psVectorSort:  psVectorCopy returned NULL vector!\n");
+            return NULL;
+        }
+    }
+
+    if (!psVectorSortInPlace(outVector)) {
+        if (outVector != inVector) {
+            // It was allocated here.
+            psFree(outVector);
+        }
+        return NULL;
+    }
+
+    return outVector;
+}
+
+psVector* psVectorSortIndex(psVector *out,
+                            const psVector *vector)
+{
+    PS_ASSERT_VECTOR_NON_NULL(vector, NULL);
+
+    psVector *indexVector = psVectorCreate(out, 0, vector->n, 1, PS_TYPE_S32); // Array of indices
+    psS32 *index = indexVector->data.S32; // Dereference for convenience
+
+    if (vector->n < 2) {
+        // Already sorted
+        return indexVector;
+    }
+    switch (vector->type.type) {
+        PSVECTOR_SORT_CASE(U8 , PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX, S32);
+        PSVECTOR_SORT_CASE(U16, PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX, S32);
+        PSVECTOR_SORT_CASE(U32, PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX, S32);
+        PSVECTOR_SORT_CASE(U64, PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX, S32);
+        PSVECTOR_SORT_CASE(S8 , PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX, S32);
+        PSVECTOR_SORT_CASE(S16, PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX, S32);
+        PSVECTOR_SORT_CASE(S32, PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX, S32);
+        PSVECTOR_SORT_CASE(S64, PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX, S32);
+        PSVECTOR_SORT_CASE(F32, PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX, S32);
+        PSVECTOR_SORT_CASE(F64, PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX, S32);
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("Input psVector is an unsupported type (0x%x)."),
+                vector->type.type);
+        psFree(indexVector);
+        return NULL;
+    }
+
+    return indexVector;
+}
+
+// Selection for different vector types
+#define PSVECTOR_SELECT_CASE(TYPE, COMPAREFUNC, SWAPFUNC, SWAPTYPE) \
+case PS_TYPE_##TYPE: { \
+    ps##TYPE *value = vector->data.TYPE; \
+    PSSELECT(vector->n, rank, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, SWAPTYPE); \
+    break; \
+}
+
+
+bool psVectorSelectInPlace(psVector *vector, long rank)
+{
+    PS_ASSERT_VECTOR_NON_NULL(vector, false);
+    PS_ASSERT_INT_NONNEGATIVE(rank, false);
+    PS_ASSERT_INT_LESS_THAN(rank, vector->n, false);
+
+    if (vector->n < 2) {
+        // Already sorted!
+        return true;
+    }
+
+    switch (vector->type.type) {
+        PSVECTOR_SELECT_CASE(U8 , PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, U8 );
+        PSVECTOR_SELECT_CASE(U16, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, U16);
+        PSVECTOR_SELECT_CASE(U32, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, U32);
+        PSVECTOR_SELECT_CASE(U64, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, U64);
+        PSVECTOR_SELECT_CASE(S8 , PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, S8 );
+        PSVECTOR_SELECT_CASE(S16, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, S16);
+        PSVECTOR_SELECT_CASE(S32, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, S32);
+        PSVECTOR_SELECT_CASE(S64, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, S64);
+        PSVECTOR_SELECT_CASE(F32, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, F32);
+        PSVECTOR_SELECT_CASE(F64, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT, F64);
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("Input psVector is an unsupported type (0x%x)."),
+                vector->type.type);
+        return false;
+    }
+    return true;
+}
+
+psVector *psVectorSelect(psVector *out, const psVector *in, long rank)
+{
+    PS_ASSERT_VECTOR_NON_NULL(in, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(rank, false);
+    PS_ASSERT_INT_LESS_THAN(rank, in->n, false);
+
+    if (out != in) {
+        out = psVectorCopy(out, in, in->type.type);
+        if (!out) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to copy vector to select.");
+            return NULL;
+        }
+    }
+
+    if (!psVectorSelectInPlace(out, rank)) {
+        if (out != in) {
+            // It was allocated here.
+            psFree(out);
+        }
+        return NULL;
+    }
+
+    return out;
+}
+
+psString psVectorToString(const psVector* vector,
+                          int maxLength)
+{
+
+    if (maxLength < 5) {
+        return NULL;
+    }
+
+    psString str = psStringAlloc(maxLength + 1);
+
+    if (vector == NULL) {
+        snprintf(str,maxLength, "NULL");
+        return str;
+    }
+
+    int size = vector->n;
+
+    if (size == 0) {
+        snprintf(str,maxLength, "[]");
+        return str;
+    }
+
+    psString tempStr = psStringAlloc(maxLength+1);
+    *str = '\0';
+    bool full = false;
+
+    #define APPEND_ELEMENTS_CASE(TYPE, NATIVE_TYPE, FORMAT) \
+case PS_TYPE_##TYPE: \
+    for (lcv=0; lcv < size && ! full; lcv++) { \
+        snprintf(tempStr, maxLength, "%s" FORMAT, prefix, (NATIVE_TYPE) (vector->data.TYPE[lcv])); \
+        strncat(str,tempStr,maxLength); \
+        full = (strlen(str) > maxLength-2); \
+        prefix = ","; \
+    } \
+    break;
+
+    int lcv;
+    char* prefix = "[";
+    switch(vector->type.type) {
+        APPEND_ELEMENTS_CASE(S8,char,"%hd")
+        APPEND_ELEMENTS_CASE(S16,short int,"%hd")
+        APPEND_ELEMENTS_CASE(S32,int,"%d")
+        APPEND_ELEMENTS_CASE(S64,long,"%ld")
+        APPEND_ELEMENTS_CASE(U8,unsigned char,"%hu")
+        APPEND_ELEMENTS_CASE(U16,unsigned short,"%hu")
+        APPEND_ELEMENTS_CASE(U32,unsigned int, "%u")
+        APPEND_ELEMENTS_CASE(U64,unsigned long,"%lu")
+        APPEND_ELEMENTS_CASE(F32,double,"%g")
+        APPEND_ELEMENTS_CASE(F64,double,"%g")
+    default:
+        snprintf(str,maxLength,"[...]");
+        break;
+    }
+
+    if (full) {
+        // couldn't all fit in given string length
+
+        // remove elements until there is room for ",...]"
+        while (strlen(str) > maxLength - 5) {
+            char* lastComma = strrchr(str,',');
+            if (lastComma == NULL) { // no comma, must be first number
+                str[1] = '\0';
+            } else {
+                *lastComma = '\0';
+            }
+        }
+        strncat(str,",...]",maxLength);
+    } else {
+        strncat(str,"]",maxLength);
+    }
+
+    psFree(tempStr);
+
+    return str;
+}
+
+psF64 p_psVectorGetElementF64(const psVector* vector,
+                              int position)
+{
+    if (vector == NULL) {
+        return NAN;
+    }
+    if (position < 0 || position >= vector->n) {
+        return NAN;
+    }
+
+    switch (vector->type.type) {
+    case PS_TYPE_U8:
+        return vector->data.U8[position];
+        break;
+    case PS_TYPE_U16:
+        return vector->data.U16[position];
+        break;
+    case PS_TYPE_U32:
+        return vector->data.U32[position];
+        break;
+    case PS_TYPE_U64:
+        return vector->data.U64[position];
+        break;
+    case PS_TYPE_S8:
+        return vector->data.S8[position];
+        break;
+    case PS_TYPE_S16:
+        return vector->data.S16[position];
+        break;
+    case PS_TYPE_S32:
+        return vector->data.S32[position];
+        break;
+    case PS_TYPE_S64:
+        return vector->data.S64[position];
+        break;
+    case PS_TYPE_F32:
+        return vector->data.F32[position];
+        break;
+    case PS_TYPE_F64:
+        return vector->data.F64[position];
+    default:
+        return NAN;
+    }
+}
+
+
+bool p_psVectorPrint (int fd,
+                      const psVector *a,
+                      char *name)
+{
+    char line[1024];
+
+    sprintf (line, "vector: %s\n", name);
+    write (fd, line, strlen(line));
+
+    for (int i = 0; i < a[0].n; i++) {
+        sprintf (line, "%f\n", p_psVectorGetElementF64(a, i));
+        write (fd, line, strlen(line));
+    }
+    sprintf (line, "\n");
+    write (fd, line, strlen(line));
+    return (true);
+}
+
+// Image initialisation for integer types
+#define VECTORINIT_INTCASE(TYPE) \
+    case PS_TYPE_##TYPE: { \
+            if (value == 0.0) { \
+                memset(vector->data.TYPE, 0, vector->n * sizeof(ps##TYPE)); \
+            } else { \
+                if (value < (double)PS_MIN_##TYPE || value > (double)PS_MAX_##TYPE) { \
+                    psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Error: Value %f out of range for type %s.\n", \
+                            value, #TYPE); \
+                    return false; \
+                } \
+                ps##TYPE castValue = (ps##TYPE)value; \
+                ps##TYPE *vectorData = vector->data.TYPE; \
+                for (int i = 0; i < vector->n; i++) { \
+                    vectorData[i] = castValue; \
+                } \
+            } \
+            return true; \
+        }
+
+// Image initialisation for char-size integer types
+#define VECTORINIT_CHARCASE(TYPE) \
+    case PS_TYPE_##TYPE: { \
+            if (value < (double)PS_MIN_##TYPE || value > (double)PS_MAX_##TYPE) { \
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Error: Value %f out of range for type %s.\n", \
+                        value, #TYPE); \
+                return false; \
+            } \
+            memset(vector->data.TYPE, (ps##TYPE)value, vector->n * sizeof(ps##TYPE)); \
+            return true; \
+        }
+
+// Image initialisation for floating point types
+#define VECTORINIT_FLOATCASE(TYPE) \
+    case PS_TYPE_##TYPE: { \
+            if (value == 0.0) { \
+                memset(vector->data.TYPE, 0, vector->n * sizeof(ps##TYPE)); \
+            } else { \
+                ps##TYPE castValue = (ps##TYPE)value; \
+                ps##TYPE *vectorData = vector->data.TYPE; \
+                for (int i = 0; i < vector->n; i++) { \
+                    vectorData[i] = castValue; \
+                } \
+            } \
+            return true; \
+        }
+
+
+
+bool psVectorInit(psVector *vector, double value)
+{
+    PS_ASSERT_VECTOR_NON_NULL(vector, false);
+
+    switch (vector->type.type) {
+        VECTORINIT_CHARCASE(U8)
+        VECTORINIT_INTCASE(U16)
+        VECTORINIT_INTCASE(U32)
+        VECTORINIT_CHARCASE(S8)
+        VECTORINIT_INTCASE(S16)
+        VECTORINIT_INTCASE(S32)
+        VECTORINIT_INTCASE(U64)
+        VECTORINIT_INTCASE(S64)
+        VECTORINIT_FLOATCASE(F32)
+        VECTORINIT_FLOATCASE(F64)
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Type %x not supported", vector->type.type);
+    }
+    return (false);
+}
+
+#define FUNC_MACRO_VECTOR_CREATE(TYPE) \
+static psVector *vectorCreate##TYPE(const char *file, unsigned int lineno, const char *func, psVector *input, double lower, double upper, double delta) \
+{ \
+    \
+    int nBin = (upper - lower) / delta; \
+    psVector *vec = p_psVectorRecycle(file, lineno, func, input, nBin, PS_TYPE_##TYPE); \
+    vec->n = nBin; \
+    for (int i = 0; i < nBin; i++) \
+    { \
+        vec->data.TYPE[i] = lower + (i * delta); \
+    } \
+    return vec; \
+} \
+
+FUNC_MACRO_VECTOR_CREATE(S8)
+FUNC_MACRO_VECTOR_CREATE(S16)
+FUNC_MACRO_VECTOR_CREATE(S32)
+FUNC_MACRO_VECTOR_CREATE(S64)
+FUNC_MACRO_VECTOR_CREATE(U8)
+FUNC_MACRO_VECTOR_CREATE(U16)
+FUNC_MACRO_VECTOR_CREATE(U32)
+FUNC_MACRO_VECTOR_CREATE(U64)
+FUNC_MACRO_VECTOR_CREATE(F32)
+FUNC_MACRO_VECTOR_CREATE(F64)
+
+psVector *p_psVectorCreate(const char *file,
+                           unsigned int lineno,
+                           const char *func,
+                           psVector *input,
+                           double lower,
+                           double upper,
+                           double delta,
+                           psElemType type)
+{
+    psVector *out = NULL;
+    switch (type) {
+    case PS_TYPE_S8:
+        out = vectorCreateS8(file, lineno, func, input, lower,  upper, delta);
+        break;
+    case PS_TYPE_S16:
+        out = vectorCreateS16(file, lineno, func, input, lower, upper, delta);
+        break;
+    case PS_TYPE_S32:
+        out = vectorCreateS32(file, lineno, func, input, lower, upper, delta);
+        break;
+    case PS_TYPE_S64:
+        out = vectorCreateS64(file, lineno, func, input, lower, upper, delta);
+        break;
+    case PS_TYPE_U8:
+        out = vectorCreateU8(file, lineno, func, input, lower, upper, delta);
+        break;
+    case PS_TYPE_U16:
+        out = vectorCreateU16(file, lineno, func, input, lower, upper, delta);
+        break;
+    case PS_TYPE_U32:
+        out = vectorCreateU32(file, lineno, func, input, lower, upper, delta);
+        break;
+    case PS_TYPE_U64:
+        out = vectorCreateU64(file, lineno, func, input, lower, upper, delta);
+        break;
+    case PS_TYPE_F32:
+        out = vectorCreateF32(file, lineno, func, input, lower, upper, delta);
+        break;
+    case PS_TYPE_F64:
+        out = vectorCreateF64(file, lineno, func, input, lower, upper, delta);
+        break;
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Invalid psType for Vector Create\n");
+    }
+    return (out);
+}
+
+bool psVectorSet(psVector *input,
+                 long position,
+                 double value)
+{
+    if (input == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psVector can not be NULL."));
+        return false;
+    }
+    if (position > input->n) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Invalid position.  Number too large\n");
+        return false;
+    }
+    if (position < 0)
+        position += input->n;
+    if (position < 0) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Invalid position.  Negative number too large\n");
+        return false;
+    }
+
+    if (position == input->n) {
+        if (position >= input->nalloc) {
+            psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                    "Specified position, %ld, is greater than n+1 of the vector, %ld.",
+                    position, input->nalloc);
+            return false;
+        }
+        (*(psVector**)&input)->n++;
+    }
+
+    switch (input->type.type) {
+    case PS_TYPE_U8:
+        input->data.U8[position] = (psU8)value;
+        break;
+    case PS_TYPE_U16:
+        input->data.U16[position] = (psU16)value;
+        break;
+    case PS_TYPE_U32:
+        input->data.U32[position] = (psU32)value;
+        break;
+    case PS_TYPE_U64:
+        input->data.U64[position] = (psU64)value;
+        break;
+    case PS_TYPE_S8:
+        input->data.S8[position] = (psS8)value;
+        break;
+    case PS_TYPE_S16:
+        input->data.S16[position] = (psS16)value;
+        break;
+    case PS_TYPE_S32:
+        input->data.S32[position] = (psS32)value;
+        break;
+    case PS_TYPE_S64:
+        input->data.S64[position] = (psS64)value;
+        break;
+    case PS_TYPE_F32:
+        input->data.F32[position] = (psF32)value;
+        break;
+    case PS_TYPE_F64:
+        input->data.F64[position] = (psF64)value;
+        break;
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Invalid psVector Data Type\n");
+        return false;
+    }
+
+    return true;
+}
+
+double psVectorGet(const psVector *input,
+                           long position)
+{
+    if (input == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psVector can not be NULL."));
+        return NAN;
+    }
+    if (position >= input->n) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Invalid position.  Number too large\n");
+        return NAN;
+    }
+    if(position < 0)
+        position += input->n;
+    if (position < 0) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Invalid position.  Negative number too large\n");
+        return NAN;
+    }
+    switch (input->type.type) {
+    case PS_TYPE_U8:
+        return input->data.U8[position];
+        break;
+    case PS_TYPE_U16:
+        return input->data.U16[position];
+        break;
+    case PS_TYPE_U32:
+        return input->data.U32[position];
+        break;
+    case PS_TYPE_U64:
+        return input->data.U64[position];
+        break;
+    case PS_TYPE_S8:
+        return input->data.S8[position];
+        break;
+    case PS_TYPE_S16:
+        return input->data.S16[position];
+        break;
+    case PS_TYPE_S32:
+        return input->data.S32[position];
+        break;
+    case PS_TYPE_S64:
+        return input->data.S64[position];
+        break;
+    case PS_TYPE_F32:
+        return input->data.F32[position];
+        break;
+    case PS_TYPE_F64:
+        return input->data.F64[position];
+        break;
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Invalid psVector Data Type\n");
+        return NAN;
+    }
+
+}
+
+// count number of pixels with given mask value
+long psVectorCountPixelMask (psVector *mask,
+                             psMaskType value)
+{
+    long Npixels = 0;
+    if (mask == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psVector can not be NULL."));
+        Npixels = -1;
+        return Npixels;
+    }
+
+    psElemType type;
+    type = mask->type.type;
+
+    if (type != PS_TYPE_MASK) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                "psVector type does not match the specified psMaskType!\n");
+        return -1;
+    }
+
+    switch (type) {
+    case PS_TYPE_U8:
+    case PS_TYPE_U16:
+        for (long i = 0; i < mask->n; i++) {
+            if (mask->data.PS_TYPE_MASK_DATA[i] & value) {
+                Npixels ++;
+            }
+        }
+        break;
+    case PS_TYPE_S8:
+    case PS_TYPE_S16:
+    case PS_TYPE_S32:
+    case PS_TYPE_S64:
+    case PS_TYPE_U32:
+    case PS_TYPE_U64:
+    case PS_TYPE_F32:
+    case PS_TYPE_F64:
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("Input psVector is an unsupported type (0x%x)."), type);
+        return -1;
+    }
+    return (Npixels);
+}
+
+long psVectorLength(const psVector *vector)
+{
+    if ( !psMemCheckVector((psVector*)vector) ) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                "Error:  Specified vector is not a valid psVector \n");
+        return -1;
+    }
+    return (vector->n);
+}
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/psVector.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/psVector.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/mathtypes/psVector.h	(revision 22158)
@@ -0,0 +1,482 @@
+/* @file  psVector.h
+ *
+ * @brief basic vector definitions and operations
+ *
+ * This file defines the basic type for a vector struct and functions useful
+ * in manupulating vectors.
+ *
+ * @author Robert DeSonia, MHPCC
+ * @author Ross Harman, MHPCC
+ * @author Joshua Hoblitt, University of Hawaii
+ *
+ * @version $Revision: 1.71 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-06-24 21:32:52 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_VECTOR_H
+#define PS_VECTOR_H
+
+/// @addtogroup MathTypes Mathematical Structures
+/// @{
+
+#include <stdio.h>
+#include "psType.h"
+
+/** An vector to support primitive types.
+ *
+ * Struct for maintaining an vector of frequently used primitive types.
+ *
+ */
+typedef struct
+{
+    psMathType type;                   ///< Type of data.
+    long n;                            ///< Number of elements in use.
+    const long nalloc;                 ///< Total number of elements available.
+    union {
+        psS8* S8;                      ///< Signed 8-bit integer data.
+        psS16* S16;                    ///< Signed 16-bit integer data.
+        psS32* S32;                    ///< Signed 32-bit integer data.
+        psS64* S64;                    ///< Signed 64-bit integer data.
+        psU8* U8;                      ///< Unsigned 8-bit integer data.
+        psU16* U16;                    ///< Unsigned 16-bit integer data.
+        psU32* U32;                    ///< Unsigned 32-bit integer data.
+        psU64* U64;                    ///< Unsigned 64-bit integer data.
+        psF32* F32;                    ///< Single-precision float data.
+        psF64* F64;                    ///< Double-precision float data.
+    } data;
+    void *lock;                        ///< Optional lock for thread safety.
+}
+psVector;
+
+#define P_PSVECTOR_SET_NALLOC(vec,n) *(long*)&(vec->nalloc) = n
+
+/*****************************************************************************/
+
+/* FUNCTION PROTOTYPES                                                       */
+
+/*****************************************************************************/
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr
+ *  datatype.
+ *
+ *  @return bool:       True if the pointer matches a psVector structure, false
+ *  otherwise.
+ */
+bool psMemCheckVector(
+    psPtr ptr                          ///< the pointer whose type to check
+)
+;
+
+/** Allocate a vector, with length set to number allocated
+ *
+ *  Uses psLib memory allocation functions to create a vector collection of
+ *  data as defined by the psType type.
+ *
+ * @return psVector*    Pointer to psVector.
+ */
+#ifdef DOXYGEN
+psVector* psVectorAlloc(
+    long nalloc,                       ///< Total number of elements to make available.
+    psElemType type                    ///< Type of data to be held by vector.
+);
+#else // ifdef DOXYGEN
+psVector* p_psVectorAlloc(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    long nalloc,                        ///< Total number of elements to make available.
+    psElemType type                    ///< Type of data to be held by vector.
+) PS_ATTR_MALLOC;
+#define psVectorAlloc(nalloc, type) \
+      p_psVectorAlloc(__FILE__, __LINE__, __func__, nalloc, type)
+#endif // ifdef DOXYGEN
+
+
+/** Allocate a vector, with length set to zero
+ *
+ *  Uses psLib memory allocation functions to create a vector collection of
+ *  data as defined by the psType type.
+ *
+ * @return psVector*    Pointer to psVector.
+ */
+#ifdef DOXYGEN
+psVector* psVectorAllocEmpty(
+    long nalloc,                       ///< Total number of elements to make available.
+    psElemType type                    ///< Type of data to be held by vector.
+);
+#else // ifdef DOXYGEN
+psVector* p_psVectorAllocEmpty(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    long nalloc,                       ///< Total number of elements to make available.
+    psElemType type                    ///< Type of data to be held by vector.
+) PS_ATTR_MALLOC;
+#define psVectorAllocEmpty(nalloc, type) \
+      p_psVectorAllocEmpty(__FILE__, __LINE__, __func__, nalloc, type)
+#endif // ifdef DOXYGEN
+
+
+/** Reallocate a vector.
+ *
+ *  Uses psLib memory allocation functions to reallocate a vector collection
+ *  of data. The vector is reallocated according to the psType type member
+ *  contained within the vector.
+ *
+ *  @return psVector*      Pointer to psVector.
+ *
+ */
+psVector* psVectorRealloc(
+    psVector* vector,                  ///< Vector to reallocate.
+    long nalloc                        ///< Total number of elements to make available.
+);
+
+
+/** Extend a vector's length.
+ *
+ *  Increments a vector's length, n, by the specified number of elements.
+ *  If the allocated storage is less than the current vector's length plus
+ *  twice the number of elements to be added, it is reallocated larger by
+ *  a given amount.
+ *
+ *  @return psVector*      Pointer to the adjusted psVector
+ */
+psVector *psVectorExtend(
+    psVector *vector,                  ///< Vector to extend
+    long delta,                        ///< Amount to expand allocation, if necessary
+    long nExtend                       ///< Number of elements to add to vector length
+);
+
+
+/** Recycle a vector.
+ *
+ *  Uses psLib memory allocation functions to reallocate a vector collection
+ *  of data. The vector is reallocated according to the psElemType type
+ *  parameter.
+ *
+ * @return psVector*       Pointer to psVector.
+ *
+ */
+#ifdef DOXYGEN
+psVector* psVectorRecycle(
+    psVector* vector,
+    ///< Vector to recycle.  If NULL, a new vector is created.  No effort
+    ///< taken to preserve the values.
+
+    long nalloc,                        ///< Total number of elements to make available.
+    psElemType type                     ///< the datatype of the returned vector
+);
+#else // ifdef DOXYGEN
+psVector* p_psVectorRecycle(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psVector* vector,
+    ///< Vector to recycle.  If NULL, a new vector is created.  No effort
+    ///< taken to preserve the values.
+
+    long nalloc,                        ///< Total number of elements to make available.
+    psElemType type                     ///< the datatype of the returned vector
+);
+#define psVectorRecycle(vector, nalloc, type) \
+      p_psVectorRecycle(__FILE__, __LINE__, __func__, vector, nalloc, type)
+#endif // ifdef DOXYGEN
+
+
+/** Copy a vector, converting types.
+ *
+ *  Performs a deep copy of the elements of one psVector to a new psVector,
+ *  converting numeric types to a specified type.
+ *
+ * @return psVector*       Pointer to resulting psVector.
+ *
+ */
+#ifdef DOXYGEN
+psVector* psVectorCopy(
+    psVector* output,                  ///< if non-NULL, a psVector to recycle
+    const psVector* input,             ///< the vector to copy.
+    psElemType type                    ///< the data type of the resulting psVector
+);
+#else // ifdef DOXYGEN
+psVector* p_psVectorCopy(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psVector* output,                  ///< if non-NULL, a psVector to recycle
+    const psVector* input,             ///< the vector to copy.
+    psElemType type                    ///< the data type of the resulting psVector
+);
+#define psVectorCopy(output, input, type) \
+      p_psVectorCopy(__FILE__, __LINE__, __func__, output, input, type)
+#endif // ifdef DOXYGEN
+
+/** Sort a vector in-place
+ *
+ * Sorts in ascending order
+ *
+ * @return  bool           Success or failure
+ */
+bool psVectorSortInPlace(const psVector *vector ///< Vector to sort
+    );
+
+/** Sort an array of floats.
+ *
+ *  Sorts an array of floats in ascending order.
+ *
+ *  @return  psVector*     Pointer to sorted psVector.
+ */
+psVector* psVectorSort(
+    psVector* outVector,               ///< the output vector to recycle, or NULL if new vector desired.
+    const psVector* inVector           ///< the vector to sort.
+);
+
+
+/** Creates an array of indices based on sort ordered of array.
+ *
+ *  Sorts a vector and creates an integer array holding indices of
+ *  sorted float values based on pre-sort index positions.
+ *
+ *  @return  psVector*     vector of the indices of sort.
+ */
+psVector* psVectorSortIndex(
+    psVector* outVector,               ///< vector to recycle
+    const psVector* inVector           ///< vector to sort
+);
+
+
+/// Select a ranked element within a vector; operations are performed in-place
+///
+/// Selection orders the vector so that the element of the nominated rank is in the correct place.  No
+/// guarantee is made about other elements.
+bool psVectorSelectInPlace(psVector *vector, ///< Vector from which to select
+                           long rank    ///< Rank of interest
+    );
+
+/// Select a ranked element within a vector; operations are performed on a copy
+///
+/// Selection orders the vector so that the element of the nominated rank is in the correct place.  No
+/// guarantee is made about other elements.
+psVector *psVectorSelect(psVector *out, ///< Output vector, or NULL
+                         const psVector *in, ///< Vector from which to select
+                         long rank      ///< Rank of interest
+    );
+
+
+/** Creates a string from a psVector's values in the form "[x0,x1,x2]".
+ *
+ *  @return psPtr          a newly allocated string
+ */
+psString psVectorToString(
+    const psVector* vector,             ///< vector to create a string from
+    int maxLength                      ///< the maximum length of the resulting string
+);
+
+
+/** Returns an element in the vector as a psF64 value
+ *
+ *  @return psF64          the value at specified position, or NAN if position is invalid.
+ */
+psF64 p_psVectorGetElementF64(
+    const psVector* vector,                  ///< vector to retrieve element
+    int position                       ///< the vector position to get
+);
+
+
+/** Print a vector to a stream
+ *
+ *  @return bool          TRUE is successful, otherwise FALSE.
+ */
+bool p_psVectorPrint(
+    int fd,                            ///< output file descriptor
+    const psVector *a,                       ///< vector to print
+    char *name                         ///< name of vector (for title)
+);
+
+
+/** Initializes the vector with the given value.
+ *
+ *  The input data is cast to match the vector datatype, allowing for integers
+ *  to be preserved.
+ *
+ *  @return bool:       True if successful, otherwise false.
+ */
+bool psVectorInit(
+    psVector *vector,                  ///< the vector to be initialized
+    double value                        ///< Value to which to initialise
+);
+
+
+/** Creates a new vector, or reallocates the provided vector if input is not NULL.
+ *
+ *  The created vector consists of the data range starting at lower, running to
+ *  upper, in steps of delta.  The upper-end value is exclusive; the sequence
+ *  is equivalent to for (x = lower; x <= upper - 1; x += delta).
+ *
+ *  @return psVector*:       the newly created psVector
+ */
+#ifdef DOXYGEN
+psVector *psVectorCreate(
+    psVector *input,                   ///< Input vector
+    double lower,                      ///< lower bound
+    double upper,                      ///< upper bound
+    double delta,                      ///< size of increment
+    psElemType type                    ///< type of vector to create
+);
+#else // ifdef DOXYGEN
+psVector *p_psVectorCreate(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psVector *input,                   ///< Input vector
+    double lower,                      ///< lower bound
+    double upper,                      ///< upper bound
+    double delta,                      ///< size of increment
+    psElemType type                    ///< type of vector to create
+);
+#define psVectorCreate(input, lower, upper, delta, type) \
+      p_psVectorCreate(__FILE__, __LINE__, __func__, input, lower, upper, delta, type)
+#endif // ifdef DOXYGEN
+
+
+/** Sets the value of the input vector at the specified position to value.
+ *
+ *  A negative position means index from the end.
+ *
+ *  @return bool:       True if successful, otherwise false.
+ */
+bool psVectorSet(
+    psVector *input,                    ///< Input vector to set
+    long position,                      ///< vector position
+    double value                        ///< value to set
+);
+
+
+/** Returns the value of the input vector at the specified position.
+ *
+ *  A negative position means index from the end.
+ *
+ *  @return double:        Value of the input vector at the specified position.
+ */
+double psVectorGet(
+    const psVector *input,             ///< Input vector from which to get value
+    long position                      ///< vector position
+);
+
+
+/** Returns the number of pixels in the vector which satisfy any of the mask bits.
+ *
+ *  An error (eg, invalid vector) results in a return value of -1.  The vector
+ *  must be U8.
+ *
+ *  @return long:       the number of pixels counted
+ */
+long psVectorCountPixelMask(
+    psVector *mask,                    ///< input vector to count
+    psMaskType value                   ///< the mask value to satisfy
+);
+
+
+/** Get the number of elements in use from a specified psVector. (vector.n)
+ *
+ *  @return long:       The number of elements in use.
+ */
+long psVectorLength(
+    const psVector *vector             ///< input psVector
+);
+
+
+/*****************************************************************************
+    PS_VECTOR macros:
+ *****************************************************************************/
+
+#define PS_ASSERT_VECTOR_NON_NULL(NAME, RVAL) PS_ASSERT_GENERAL_VECTOR_NON_NULL(NAME, return RVAL)
+#define PS_ASSERT_GENERAL_VECTOR_NON_NULL(NAME, CLEANUP) \
+if ((NAME) == NULL || (NAME)->data.U8 == NULL) { \
+    psError(PS_ERR_BAD_PARAMETER_NULL, true, \
+            "Unallowable operation: psVector %s or its data is NULL.", \
+            #NAME); \
+    CLEANUP; \
+} \
+
+#define PS_ASSERT_VECTOR_NON_EMPTY(NAME, RVAL) PS_ASSERT_GENERAL_VECTOR_NON_EMPTY(NAME, return RVAL)
+#define PS_ASSERT_GENERAL_VECTOR_NON_EMPTY(NAME, CLEANUP) \
+if ((NAME)->n < 1) { \
+    psError(PS_ERR_BAD_PARAMETER_SIZE, true, \
+            "Unallowable operation: psVector %s has no elements.", \
+            #NAME); \
+    CLEANUP; \
+} \
+
+#define PS_ASSERT_VECTOR_TYPE_F32_OR_F64(NAME, RVAL) \
+if (((NAME)->type.type != PS_TYPE_F32) && ((NAME)->type.type != PS_TYPE_F64)) { \
+    psError(PS_ERR_BAD_PARAMETER_TYPE, true, \
+            "psVector %s: bad type(%d)", \
+            #NAME, (NAME)->type.type); \
+    return(RVAL); \
+} \
+
+#define PS_ASSERT_VECTOR_TYPE_S16_S32_F32(NAME, RVAL) \
+if (((NAME)->type.type != PS_TYPE_S16) && ((NAME)->type.type != PS_TYPE_S32) && ((NAME)->type.type != PS_TYPE_F32)) { \
+    psError(PS_ERR_BAD_PARAMETER_TYPE, true, \
+            "psVector %s: bad type(%d)", \
+            #NAME, (NAME)->type.type); \
+    return(RVAL); \
+} \
+
+#define PS_ASSERT_VECTOR_TYPE(NAME, TYPE, RVAL) \
+if ((NAME)->type.type != TYPE) { \
+    psError(PS_ERR_BAD_PARAMETER_TYPE, true, \
+            "Unallowable operation: psVector %s has incorrect type.", \
+            #NAME); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_VECTORS_SIZE_EQUAL(VEC1, VEC2, RVAL) \
+if ((VEC1)->n != (VEC2)->n) { \
+    psError(PS_ERR_BAD_PARAMETER_SIZE, true, \
+            "psVector %s has size %ld, psVector %s has size %ld.", \
+            #VEC1, (VEC1)->n, #VEC2, (VEC2)->n); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_VECTOR_SIZE(VEC, SIZE, RVAL) \
+if ((VEC)->n != (SIZE)) { \
+    psError(PS_ERR_BAD_PARAMETER_SIZE, true, \
+            "psVector %s has size %ld, should be %ld.", \
+            #VEC, (VEC)->n, (SIZE)); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_VECTOR_TYPE_EQUAL(VEC1, VEC2, RVAL) \
+if ((VEC1)->type.type != (VEC2)->type.type) { \
+    psError(PS_ERR_BAD_PARAMETER_SIZE, true, \
+            "psVector %s has size %d, psVector %s has size %d.", \
+            #VEC1, (VEC1)->type.type, #VEC2, (VEC2)->type.type); \
+    return(RVAL); \
+}
+
+#define PS_VECTOR_PRINT_F32(NAME) \
+if ((NAME) != NULL) { \
+    for (int i = 0; i < (NAME)->n; i++) { \
+        printf("%s->data.F32[%d] is %f\n", #NAME, i, (NAME)->data.F32[i]); \
+    } \
+    printf("\n"); \
+} else {\
+    printf("MACRO WARNING: vector %s is NULL.\n", #NAME); \
+}\
+
+#define PS_VECTOR_PRINT_F64(NAME) \
+if ((NAME) != NULL) { \
+    for (int i = 0; i < (NAME)->n; i++) { \
+        printf("%s->data.F64[%d] is %f\n", #NAME, i, (NAME)->data.F64[i]); \
+    } \
+    printf("\n"); \
+} else {\
+    printf("MACRO WARNING: vector %s is NULL.\n", #NAME); \
+}\
+
+/// @}
+#endif // #ifndef PS_VECTOR_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/psErrorCodes_en.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/psErrorCodes_en.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/psErrorCodes_en.dat	(revision 22158)
@@ -0,0 +1,24 @@
+#
+#  This file is used to generate psErrorCode.h content
+#
+# Format:
+#    ERROR_CLASS_NAME    ERROR_CLASS_DESCRIPTION
+#
+# Note: the ERROR_CLASS_NAME will appear in the code with a "PS_ERR_" prefix
+#
+UNKNOWN                        unknown psLib error
+IO                             I/O error
+LOCATION_INVALID               specified location is unknown
+MEMORY_CORRUPTION              memory corruption detected
+MEMORY_DEREF_USAGE             dereferenced memory still used
+BAD_PARAMETER_VALUE            parameter is out-of-range
+BAD_PARAMETER_TYPE             parameter is of unsupported type
+BAD_PARAMETER_NULL             parameter is null
+BAD_PARAMETER_SIZE             size of parameter's data is outside of acceptable range.
+UNEXPECTED_NULL                unexpected NULL found
+OS_CALL_FAILED                 unexpected result from an OS standard library call.
+BAD_FITS		       file doesn't obey FITS standard
+IEEE			       a NaN or Inf was detected
+DB_CLIENT                      Database error originated in the client library
+DB_SERVER                      Database error generated by the server
+PROGRAMMING                    Known programming error
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/pslib.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/pslib.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/pslib.h	(revision 22158)
@@ -0,0 +1,21 @@
+/** @file  pslib.h
+*
+*  @brief Contains the complete list of header files for pslib.
+*
+*  This header file includes all the necessary header files for a user to
+*  user all public functions within the pslib library.
+*
+*  @author Eric Van Alst, MHPCC
+*
+*  @version $Revision: 1.36 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-06-08 23:40:45 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifndef PS_LIB_H
+#define PS_LIB_H
+
+#include "pslib_strict.h"
+
+#endif // #ifndef PS_LIB_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/pslib_strict.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/pslib_strict.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/pslib_strict.h	(revision 22158)
@@ -0,0 +1,120 @@
+/** @file  pslib_strict.h
+*
+*  @brief Contains the complete list of header files for pslib while poisoning
+*         the use of standard memory allocation routines.
+*
+*  This header file includes all the necessary header files for a user to
+*  user all public functions within the pslib library.
+*
+*  @author Eric Van Alst, MHPCC
+*
+*  @version $Revision: 1.36.8.1 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2008-07-26 03:48:39 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifndef PS_LIB_STRICT_H
+#define PS_LIB_STRICT_H
+
+#ifdef PS_LIB_H  /* this is included from pslib.h, so don't poison anything */
+#ifndef PS_ALLOW_MALLOC
+#define PS_ALLOW_MALLOC
+#endif // #ifndef PS_ALLOW_MALLOC
+#else
+#undef PS_ALLOW_MALLOC /* don't allow code to not poison malloc, i.e., strict poisioning */
+#endif // #else
+
+#include "psTime.h"
+#include "psCoord.h"
+#include "psSphereOps.h"
+#include "psEarthOrientation.h"
+
+#include "psDB.h"
+
+#include "psVectorFFT.h"
+#include "psImageFFT.h"
+
+#include "psFits.h"
+#include "psFitsHeader.h"
+#include "psFitsImage.h"
+#include "psFitsTable.h"
+#include "psFitsFloat.h"
+#include "psFitsFloatFile.h"
+#include "psFitsScale.h"
+
+//#include "psXML.h"
+
+#include "psRegion.h"
+#include "psImageInterpolate.h"
+#include "psImageConvolve.h"
+#include "psImageGeomManip.h"
+#include "psImagePixelExtract.h"
+#include "psImagePixelManip.h"
+#include "psImagePixelInterpolate.h"
+#include "psImageStats.h"
+#include "psImageStructManip.h"
+#include "psImageMaskOps.h"
+#include "psImageBinning.h"
+#include "psImageUnbin.h"
+#include "psImageMap.h"
+#include "psImageMapFit.h"
+
+#include "psImageJpeg.h"
+
+#include "psAssert.h"
+#include "psBinaryOp.h"
+#include "psCompare.h"
+#include "psConstants.h"
+#include "psExit.h"
+#include "psMatrix.h"
+#include "psMD5.h"
+#include "psMinimizeLMM.h"
+#include "psMinimizePowell.h"
+#include "psMinimizePolyFit.h"
+#include "psRandom.h"
+#include "psRegionForImage.h"
+#include "psPolynomial.h"
+#include "psPolynomialMetadata.h"
+#include "psPolynomialUtils.h"
+#include "psPolynomialMD.h"
+#include "psSort.h"
+#include "psSpline.h"
+#include "psStats.h"
+#include "psHistogram.h"
+#include "psUnaryOp.h"
+#include "psMathUtils.h"
+#include "psImage.h"
+#include "psScalar.h"
+#include "psVector.h"
+#include "psAbort.h"
+#include "psConfigure.h"
+#include "psError.h"
+#include "psErrorCodes.h"
+#include "psLogMsg.h"
+#include "psMemory.h"
+#include "psString.h"
+#include "psLine.h"
+#include "psTrace.h"
+#include "psType.h"
+#include "psArray.h"
+#include "psBitSet.h"
+#include "psHash.h"
+#include "psList.h"
+#include "psLookupTable.h"
+#include "psMetadata.h"
+#include "psMetadataConfig.h"
+#include "psMetadataItemParse.h"
+#include "psMetadataItemCompare.h"
+#include "psPixels.h"
+#include "psArguments.h"
+#include "psVectorSmooth.h"
+#include "psImageBackground.h"
+#include "psEllipse.h"
+#include "psSparse.h"
+#include "psSlurp.h"
+#include "psTree.h"
+
+#include "psThread.h"
+
+#endif // #ifndef PS_LIB_STRICT_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/.cvsignore	(revision 22158)
@@ -0,0 +1,12 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
+psErrorCodes.c
+psErrorCodes.h
+*.loT
+*.bb
+*.bbg
+*.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/Makefile.am	(revision 22158)
@@ -0,0 +1,49 @@
+#Makefile for sys functions of psLib
+#
+noinst_LTLIBRARIES = libpslibsys.la
+
+libpslibsys_la_CPPFLAGS = $(SRCINC) $(PSLIB_CFLAGS) $(CFITSIO_CFLAGS)
+libpslibsys_la_SOURCES = \
+	psAbort.c \
+	psConfigure.c  \
+	psError.c      \
+	psErrorCodes.c \
+	psLine.c       \
+	psLogMsg.c     \
+	psMemory.c     \
+	psSlurp.c      \
+	psString.c     \
+	psThread.c     \
+	psTrace.c      \
+	psType.c       \
+	strcasestr.c
+
+EXTRA_DIST = sys.i psErrorCodes.c.in psErrorCodes.h.in
+
+BUILT_SOURCES = psErrorCodes.c
+
+psErrorCodes.c: ../psErrorCodes_$(PS_LANG).dat psErrorCodes.c.in psErrorCodes.h
+	$(top_srcdir)/utils/psParseErrorCodes --data=../psErrorCodes_$(PS_LANG).dat $@
+
+psError.h: psErrorCodes.h
+
+psErrorCodes.h: ../psErrorCodes_$(PS_LANG).dat psErrorCodes.h.in
+	$(top_srcdir)/utils/psParseErrorCodes --data=../psErrorCodes_$(PS_LANG).dat $@
+
+pkginclude_HEADERS = \
+	psAbort.h \
+	psAssert.h \
+	psConfigure.h  \
+	psError.h      \
+	psErrorCodes.h \
+	psExit.h       \
+	psLine.h       \
+	psLogMsg.h     \
+	psMemory.h     \
+	psSlurp.h      \
+	psString.h     \
+	psThread.h     \
+	psTrace.h      \
+	psType.h
+
+CLEANFILES = *~ *.bb *.bbg *.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psAbort.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psAbort.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psAbort.c	(revision 22158)
@@ -0,0 +1,74 @@
+
+/** @file  psAbort.c
+ *
+ *  @brief Contains the definition for abort function
+ *
+ *  The abort logging and handling shall be performed by psAbort function.
+ *  This will allow for consistent handling of other software units
+ *  needing to abort from program execution.
+ *
+ *  @author Eric Van Alst, MHPCC
+ *  @author Joshua Hoblitt, University of Hawaii
+ *   
+ *  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-04-13 08:18:27 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include "psAbort.h"
+#include "psError.h"
+#include "psLogMsg.h"
+
+void p_psAbort(const char *file,
+               unsigned int lineno,
+               const char *func,
+               const char *format,
+               ...)
+{
+    psErrorStackPrint(stderr, "Aborting. Error stack:");
+
+    va_list argPtr;             // variable list arguement pointer
+    // Get the variable list parameters to pass to logging function
+    va_start(argPtr, format);
+
+    // Call logging function with PS_LOG_ABORT level
+    psLogMsgV("psLib.sys", PS_LOG_ABORT, format, argPtr);
+
+    // Clean up stack after variable arguement has been used
+    va_end(argPtr);
+
+    // Call system abort function to terminate program execution
+    abort();
+}
+
+void p_psAssert(const char *file,
+		unsigned int lineno,
+		const char *func,
+		const bool value,
+		const char *format,
+		...)
+{
+    if (value) return;
+    psErrorStackPrint(stderr, "Aborting. Error stack:");
+
+    va_list argPtr;             // variable list arguement pointer
+    // Get the variable list parameters to pass to logging function
+    va_start(argPtr, format);
+
+    // Call logging function with PS_LOG_ABORT level
+    psLogMsgV("psLib.sys", PS_LOG_ABORT, format, argPtr);
+
+    // Clean up stack after variable arguement has been used
+    va_end(argPtr);
+
+    // Call system abort function to terminate program execution
+    abort();
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psAbort.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psAbort.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psAbort.h	(revision 22158)
@@ -0,0 +1,88 @@
+/** @file  psAbort.h
+ *
+ *  @brief Contains the declarations for the abort function
+ *
+ *  The abort logging and handling shall be performed by psAbort function.
+ *  This will allow for consistent handling of other software units
+ *  needing to abort from program execution.
+ *
+ *  @author Eric Van Alst, MHPCC
+ *  @author Joshua Hoblitt, University of Hawaii
+ *
+ *  $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ *  $Date: 2008-04-13 08:18:27 $
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_ABORT_H
+#define PS_ABORT_H
+
+/// @addtogroup SysUtils System Utilities
+/// @{
+
+#include <stdarg.h>
+
+#include "psType.h"
+
+/** Reports an abort message to logging facility
+ *
+ *  This function will invoke the psLogMsg function with a level of
+ *  PS_LOG_ABORT and pass the parameters name and fmt to generate a proper
+ *  log message.  After logging, this function will call system abort
+ *  function to abnormally terminate the program.
+ *
+ *  @return  void No return value
+ *
+ */
+#ifdef DOXYGEN
+void psAbort(
+    const char *format,                 ///< A printf style formatting statement
+    ...
+);
+#else // ifdef DOXYGEN
+void p_psAbort(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    const char *format,                 ///< A printf style formatting statement
+    ...
+) PS_ATTR_FORMAT(printf, 4, 5) PS_ATTR_NORETURN;
+#ifndef SWIG
+#define psAbort(...) \
+      p_psAbort(__FILE__, __LINE__, __func__, __VA_ARGS__)
+#endif // iddef SWIG
+#endif // ifdef DOXYGEN
+
+/** Reports an abort message to logging facility
+ *
+ *  This function will invoke the psLogMsg function with a level of
+ *  PS_LOG_ABORT and pass the parameters name and fmt to generate a proper
+ *  log message.  After logging, this function will call system abort
+ *  function to abnormally terminate the program.
+ *
+ *  @return  void No return value
+ *
+ */
+#ifdef DOXYGEN
+void psAssert(
+    const bool value,
+    const char *format,                 ///< A printf style formatting statement
+    ...
+);
+#else // ifdef DOXYGEN
+void p_psAssert(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    const bool value,
+    const char *format,                 ///< A printf style formatting statement
+    ...
+) PS_ATTR_FORMAT(printf, 5, 6);
+#ifndef SWIG
+#define psAssert(VALUE, ...) \
+      p_psAssert(__FILE__, __LINE__, __func__, (VALUE), __VA_ARGS__)
+#endif // iddef SWIG
+#endif // ifdef DOXYGEN
+
+/// @}
+#endif // #ifndef PS_ABORT_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psAssert.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psAssert.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psAssert.h	(revision 22158)
@@ -0,0 +1,279 @@
+#ifndef PS_ASSERT_H
+#define PS_ASSERT_H
+
+/// @addtogroup SysUtils System Utilities
+/// @{
+
+#include <assert.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include "psError.h"
+#include "psLogMsg.h"
+
+// these two asserts can be used in the middle of a function to test for programming errors
+#define PS_ASSERT(VAR, RVAL) \
+if (!(VAR)) { \
+    psError(PS_ERR_PROGRAMMING, false, "Error: %s is not true.", #VAR); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_INT_UNEQUAL(NAME1, NAME2, RVAL) \
+if ((NAME1) == (NAME2)) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: %s and %s are equal.", \
+            #NAME1, #NAME2); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_INT_UNEQUAL(NAME1, NAME2, RVAL) \
+if ((NAME1) == (NAME2)) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: %s and %s are equal.", \
+            #NAME1, #NAME2); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_INT_EQUAL(NAME1, NAME2, RVAL) \
+if ((NAME1) != (NAME2)) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: %s and %s are not equal.", \
+            #NAME1, #NAME2); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_INT_NONNEGATIVE(NAME, RVAL) \
+if ((NAME) < 0) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Error: %s is less than 0.", #NAME); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_INT_POSITIVE(NAME, RVAL) \
+if ((NAME) < 1) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: %s is 0 or less.", #NAME); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_INT_ZERO(NAME, RVAL) \
+if ((NAME) != 0) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: %s is 0.", #NAME); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_INT_NONZERO(NAME, RVAL) \
+if ((NAME) == 0) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: %s is 0.", #NAME); \
+    return(RVAL); \
+}
+
+// XXX: Where did these int casts come from?
+#define PS_ASSERT_INT_WITHIN_RANGE(NAME, LOWER, UPPER, RVAL) \
+if ((int)(NAME) < LOWER || (int)(NAME) > UPPER) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: %s, %ld, is out of range.  Must be between %ld and %ld.", \
+            #NAME,(long)(NAME),(long)(LOWER),(long)(UPPER)); \
+    return RVAL; \
+}
+
+#define PS_ASSERT_INT_LESS_THAN(VAR1, VAR2, RVAL) \
+if (!(VAR1 < VAR2)) { \
+    psError(PS_ERR_UNKNOWN, true, \
+            "Error: %s is not less than %s (%ld, %ld)", #VAR1, #VAR2, (long)(VAR1), (long)(VAR2)); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_INT_LESS_THAN_OR_EQUAL(VAR1, VAR2, RVAL) \
+if (!(VAR1 <= VAR2)) { \
+    psError(PS_ERR_UNKNOWN, true, \
+            "Error: %s is not less than %s (%ld, %ld)", #VAR1, #VAR2, (long)(VAR1), (long)(VAR2)); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_INT_LARGER_THAN(NAME1, NAME2, RVAL) \
+if (!((NAME1) > (NAME2))) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: !(%s > %s) (%ld %ld).", \
+            #NAME1, #NAME2,(long)(NAME1), (long)(NAME2)); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_INT_LARGER_THAN_OR_EQUAL(NAME1, NAME2, RVAL) \
+if (!((NAME1) >= (NAME2))) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: !(%s >= %s) (%ld %ld).", \
+            #NAME1, #NAME2, (long)(NAME1), (long)(NAME2)); \
+    return(RVAL); \
+}
+#define PS_ASSERT_FLOAT_LARGER_THAN(NAME1, NAME2, RVAL) \
+if (!((NAME1) > (NAME2))) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: !(%s > %s) (%lf %lf).", \
+            #NAME1, #NAME2, (double)(NAME1), (double)(NAME2)); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_FLOAT_LARGER_THAN_OR_EQUAL(NAME1, NAME2, RVAL) \
+if (!((NAME1) >= (NAME2))) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: !(%s >= %s) (%lf %lf).", \
+            #NAME1, #NAME2, (double)(NAME1), (double)(NAME2)); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_FLOAT_LESS_THAN(NAME1, NAME2, RVAL) \
+if (!((NAME1) < (NAME2))) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: !(%s < %s) (%lf %lf).", \
+            #NAME1, #NAME2, (double)(NAME1), (double)(NAME2)); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_FLOAT_LESS_THAN_OR_EQUAL(NAME1, NAME2, RVAL) \
+if (!((NAME1) <= (NAME2))) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: !(%s <= %s) (%lf %lf).", \
+            #NAME1, #NAME2, (double)(NAME1), (double)(NAME2)); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_FLOAT_NON_EQUAL(NAME1, NAME2, RVAL) \
+if (fabs((NAME2) - (NAME1)) < FLT_EPSILON) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: %s and %s are equal.", \
+            #NAME1, #NAME2); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_FLOAT_EQUAL(NAME1, NAME2, RVAL) \
+if (fabs((NAME2) - (NAME1)) > FLT_EPSILON) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: %s and %s are not equal.", \
+            #NAME1, #NAME2); \
+    return(RVAL); \
+}
+
+// Return an error if the arg lies outside the supplied range.
+#define PS_ASSERT_FLOAT_WITHIN_RANGE(NAME, LOWER, UPPER, RVAL) \
+if ((NAME) < (LOWER) || (NAME) > (UPPER)) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: %s, %f, is out of range.  Must be between %lf and %lf.", \
+            #NAME, NAME, (double)(LOWER), (double)(UPPER)); \
+    return RVAL; \
+}
+
+#define PS_ASSERT_FLOAT_REAL(NAME, RVAL) \
+if (!isfinite(NAME)) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: %s=%lf is not a real value.\n", \
+            #NAME, (double)(NAME)); \
+    return RVAL; \
+}
+
+#define PS_ASSERT_DOUBLE_WITHIN_RANGE(NAME, LOWER, UPPER, RVAL) \
+if ((NAME) < (LOWER) || (NAME) > (UPPER)) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: %s, %lf, is out of range.  Must be between %lf and %lf.", \
+            #NAME, NAME, LOWER, UPPER); \
+    return RVAL; \
+}
+
+#define PS_ASSERT_LONG_WITHIN_RANGE(NAME, LOWER, UPPER, RVAL) \
+if ((NAME) < (LOWER) || (NAME) > (UPPER)) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: %s, %ld, is out of range.  Must be between %ld and %ld.", \
+            #NAME, NAME, LOWER, UPPER); \
+    return RVAL; \
+}
+
+#define PS_ASSERT_LONG_LARGER_THAN_OR_EQUAL(NAME1, NAME2, RVAL) \
+if (!((NAME1) >= (NAME2))) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Error: !(%s >= %s) (%ld %ld).",\
+            #NAME1, #NAME2, NAME1, NAME2); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_S64_WITHIN_RANGE(NAME, LOWER, UPPER, RVAL) \
+if ((NAME) < (LOWER) || (NAME) > (UPPER)) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: %s, %" PRId64 ", is out of range.  Must be between %" PRId64 " and %" PRId64 ".", \
+            #NAME, NAME, LOWER, UPPER); \
+    return RVAL; \
+}
+
+/*****************************************************************************
+Macros which take a generic psLib type and determine if it is NULL, or has
+the wrong type.
+*****************************************************************************/
+#define PS_WARN_PTR_NON_NULL(NAME) \
+if ((NAME) == NULL) { \
+    psLogMsg(__func__, PS_LOG_WARN, "WARNING: %s is NULL.", #NAME); \
+} \
+
+#define PS_ASSERT_PTR(NAME, RVAL)
+
+#define PS_ASSERT_PTR_NON_NULL(NAME, RVAL) PS_ASSERT_GENERAL_PTR_NON_NULL(NAME, return RVAL)
+#define PS_ASSERT_GENERAL_PTR_NON_NULL(NAME, CLEANUP) \
+if ((NAME) == NULL) { \
+    psError(PS_ERR_BAD_PARAMETER_NULL, true, \
+            "Unallowable operation: %s is NULL.", \
+            #NAME); \
+    CLEANUP; \
+}
+
+#define PS_ASSERT_PTR_NULL(NAME, RVAL) \
+if ((NAME) != NULL) { \
+    psError(PS_ERR_BAD_PARAMETER_NULL, true, \
+            "Unallowable operation: %s is not NULL.", \
+            #NAME); \
+    return RVAL; \
+}
+
+#define PS_ASSERT_PTR_TYPE(NAME, TYPE, RVAL) \
+if ((NAME)->type.type != TYPE) { \
+    psError(PS_ERR_BAD_PARAMETER_TYPE, true, \
+            "Unallowable operation: %s has incorrect type.", \
+            #NAME); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_PTR_DIMEN(NAME, DIMEN, RVAL) PS_ASSERT_GENERAL_PTR_DIMEN(NAME, DIMEN, return RVAL)
+#define PS_ASSERT_GENERAL_PTR_DIMEN(NAME, DIMEN, CLEANUP) \
+if ((NAME)->type.dimen != DIMEN) { \
+    psError(PS_ERR_BAD_PARAMETER_TYPE, true, \
+            "Unallowable operation: %s has incorrect dimensionality.", \
+            #NAME); \
+    CLEANUP; \
+}
+
+#define PS_ASSERT_PTR_DIMEN_GENERAL_NOT(NAME, DIMEN, CLEANUP) \
+if ((NAME)->type.dimen == DIMEN) { \
+    psError(PS_ERR_BAD_PARAMETER_TYPE, true, \
+            "Unallowable operation: %s has incorrect dimensionality.", \
+            #NAME); \
+    CLEANUP; \
+}
+
+
+#define PS_ASSERT_PTRS_SIZE_EQUAL(PTR1, PTR2, RVAL) \
+if (PTR1->n != PTR2->n) { \
+    psError(PS_ERR_BAD_PARAMETER_SIZE, true, \
+            "ptr %s has size %d, ptr %s has size %d.", \
+            #PTR1, PTR1->n, #PTR2, PTR2->n); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_PTR_TYPE_EQUAL(PTR1, PTR2, RVAL) PS_ASSERT_GENERAL_PTR_TYPE_EQUAL(PTR1, PTR2, return RVAL)
+#define PS_ASSERT_GENERAL_PTR_TYPE_EQUAL(PTR1, PTR2, CLEANUP) \
+if (PTR1->type.type != PTR2->type.type) { \
+    psError(PS_ERR_BAD_PARAMETER_TYPE, true, \
+            "ptr %s has type %d, ptr %s has type %d.", \
+            #PTR1, PTR1->type.type, #PTR2, PTR2->type.type); \
+    CLEANUP; \
+}
+
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psConfigure.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psConfigure.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psConfigure.c	(revision 22158)
@@ -0,0 +1,144 @@
+/** @file  psConfigure.c
+ *
+ *  @brief Contains the declarations for initialization, memory finalization,
+ *   and configuration.
+ *
+ *  These functions initalize psLib data before the beginning of a run and
+ *  remove (finalize) the same data after the run is complete. A function is
+ *  also provided to return the current psLib version.
+ *
+ *  @ingroup Configure
+ *
+ *  @author Ross Harman, MHPCC
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.26.16.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-27 22:42:32 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "psAbort.h"
+#include "psTrace.h"
+#include "psString.h"
+#include "psTime.h"
+#include "psThread.h"
+#include "psEarthOrientation.h"
+#include "psError.h"
+#include "psConfigure.h"
+#include "psMemory.h"
+
+static char *memCheckName = NULL;       // Filename to which to write results of mem check
+static FILE *memCheckFile = NULL;       // File to which to write results of mem check
+
+static const char *cvsTag = "$Name: not supported by cvs2svn $"; // CVS tag name
+
+psString psLibVersion(void)
+{
+    psString version = NULL;            // Version, to return
+    psStringAppend(&version, "%s-%s",PACKAGE_NAME,PACKAGE_VERSION);
+    return version;
+}
+
+psString psLibVersionLong(void)
+{
+    psString version = psLibVersion();    // Version, to return
+    psString tag = psStringStripCVS(cvsTag, "Name"); // CVS tag
+
+#ifdef HAVE_PSDB
+    psStringAppend(&version, " (cvs tag %s), %s, %s with psDB", tag, __DATE__, __TIME__);
+#else
+    psStringAppend(&version, " (cvs tag %s), %s, %s without psDB", tag, __DATE__, __TIME__);
+#endif
+    psFree(tag);
+    return version;
+}
+
+// Check the memory; intended for use on exit, but might be used elsewhere
+void p_psMemoryCheck(void)
+{
+    if (!memCheckName || strlen(memCheckName) == 0) {
+        return;
+    }
+
+    memCheckFile = fopen(memCheckName, "w"); // File to write leaks to
+    if (!memCheckFile) {
+        psError(PS_ERR_IO, true, "Unable to open leaks file, %s\n", memCheckName);
+        return;
+    }
+
+    int nLeaks = psMemCheckLeaks(0, NULL, memCheckFile, false); // Number of leaks
+    if (nLeaks > 0) {
+        psWarning("%d memory leaks found; list written to %s.\n", nLeaks, memCheckName);
+    } else {
+        psLogMsg(__func__, PS_LOG_INFO, "No memory leaks found.\n");
+    }
+
+    int nCorrupted;                     // Number of corrupted memory blocks
+    nCorrupted = psMemCheckCorruption(memCheckFile, false);
+    if (nCorrupted > 0) {
+        psWarning("%d memory blocks corrupted; list written to %s.\n", nCorrupted, memCheckName);
+    } else {
+        psLogMsg(__func__, PS_LOG_INFO, "No memory corruption found.\n");
+    }
+
+    fclose(memCheckFile);
+
+    return;
+}
+
+
+bool psLibInit(const char* timeConfig)
+{
+    // XXX: Still needs error codes to be set
+
+    if (timeConfig && strlen(timeConfig) > 0) {
+        if (!psTimeInit(timeConfig)) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    _("Failed to initialize %s."), "psTime");
+            return false;
+        }
+    }
+
+    // Does the user want memory checking at exit?
+    memCheckName = getenv("PS_ALLOC_CHECK"); // The value of PS_ALLOC_CHECK
+    if (memCheckName && strlen(memCheckName) > 0) {
+        atexit(&p_psMemoryCheck);
+    }
+
+    return true;
+}
+
+void psLibFinalize(void)
+{
+    // Users of persistent memory should free them in this function
+
+    // Stop timers
+    psTimerStop();
+
+    psThreadPoolFinalize();
+
+    // Free the time tables
+    if (!p_psTimeFinalize()) {
+        psAbort(_("Failed to finalize psTime."));
+    }
+
+    // Free the precession tables
+    if (!p_psEOCFinalize()) {
+        psAbort(_("Failed to finalize psEOC."));
+    }
+
+    // Free the trace system
+    psTraceReset();
+
+    // Free the error system
+    psErrorClear();
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psConfigure.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psConfigure.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psConfigure.h	(revision 22158)
@@ -0,0 +1,74 @@
+/** @file  psConfigure.h
+ *
+ *  @brief Functions to init and cleanup psLib
+ *
+ *  These functions initalize psLib data before the beginning of a run and
+ *  remove (finalize) the same data after the run is complete.  A function is
+ *  also provided to return the current psLib version.
+ *
+ *
+ *  @author Ross Harman, MHPCC
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-06-22 02:28:48 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_CONFIGURE_H
+#define PS_CONFIGURE_H
+
+/// @addtogroup SysUtils System Utilities
+/// @{
+
+/** Get current psLib version
+ *
+ *  Returns the current psLib version name as a string.
+ *
+ *  @return psString: String with version name.
+ */
+psString psLibVersion(
+    void
+);
+
+
+/** Get current psLib version (full identification)
+ *
+ *  Returns the current psLib version name and other information identifying the compilation.
+ *
+ *  @return psString: String with identity.
+ */
+psString psLibVersionLong(void);
+
+
+/** Initializes persistent memory.
+ *
+ *  Creates persistant memory items used throughout psLib. Items created
+ *  within this method should be freed with the psLibFinalize function.
+ *  current, a non-NULL psErr is returned with code PS_ERR_NONE.
+ *
+ */
+bool psLibInit(
+    const char* timeConfig           ///< Filename of config file for psTime.
+);
+
+
+/** Removes persistant memory created with the psLibInit function.
+ *
+ *  The memory created but not freed by psLib modules should be freed
+ *  within this function at the end of a psLib execution cycle.
+ *
+ *  @return void: void.
+ */
+void psLibFinalize(
+    void
+);
+
+
+// Check the memory; intended for use on exit, but might be used elsewhere
+void p_psMemoryCheck(void);
+
+
+/// @}
+#endif // #ifndef PS_CONFIGURE_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psError.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psError.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psError.c	(revision 22158)
@@ -0,0 +1,318 @@
+/** @file  psError.c
+ *
+ *  @brief Contains the definitions for the error reporting functions
+ *
+ *  Error reporting functions shall be used to create log entries in the
+ *  event errors are detected.  The messages shall give enough information
+ *  to allow the user to know where the error has occurred and the type
+ *  of error detected.
+ *
+ *  @author Joshua Hoblitt, University of Hawaii
+ *  @author Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.47 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-08-15 20:23:34 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdarg.h>
+#include <pthread.h>
+#include <string.h>
+
+#include "psLogMsg.h"
+#include "psError.h"
+#include "psString.h"
+#include "psTrace.h"
+#include "psAbort.h"
+#include "psMemory.h"
+
+#define MAX_STRING_LENGTH 2048
+#define MAX_ERROR_STACK_SIZE 64
+
+static pthread_mutex_t lockErrorStack = PTHREAD_MUTEX_INITIALIZER;
+static bool errorStackKeyInitialized = false;
+static pthread_key_t errorStack_key;
+
+static void psFreeWrapper(void *ptr);
+static void psErrorStackPush(psErr* err);
+static psArray *psErrorStackGet(void);
+static void psErrFree(psErr* err);
+
+// needed for pthread_key_create() because p_psFree() does not match free()'s
+// prototype
+// XXX does something like this need to be global in psMmemory.h
+static void psFreeWrapper(void *ptr)
+{
+    psFree(ptr);
+}
+
+static void psErrorStackPush(psErr* err)
+{
+    psArray *errorStack = psErrorStackGet();
+
+    // push the item onto the stack and increment the error count
+    if (psArrayLength(errorStack) < MAX_ERROR_STACK_SIZE) {
+        // make the psErr persistent
+        psMemSetPersistent(err, true);
+        psMemSetPersistent(err->msg, true);
+        psMemSetPersistent(err->name, true);
+
+        psArrayAdd(errorStack, 0, err);
+    } else {
+        psAbort("attempt to exceed maximum error stack depth of %ld",
+                (long)MAX_ERROR_STACK_SIZE);
+    }
+}
+
+static psArray *psErrorStackGet(void)
+{
+    // check to see if the error stack key has been initialized
+    pthread_mutex_lock(&lockErrorStack);
+    if (errorStackKeyInitialized == false) {
+        // note that each error stack will automatically be free'd when it's
+        // thread exits
+        if (pthread_key_create(&errorStack_key, psFreeWrapper)) {
+            psAbort("pthread_key_create failed()");
+        }
+        errorStackKeyInitialized = true;
+    }
+    pthread_mutex_unlock(&lockErrorStack);
+
+    // check to see if the error stack for this thread has been allocated
+    psArray *errorStack = NULL;
+    if ((errorStack = pthread_getspecific(errorStack_key)) == NULL) {
+        // allocate the error stack
+        errorStack = psArrayAllocEmpty(MAX_ERROR_STACK_SIZE);
+        psMemSetPersistent(errorStack, true);
+        psMemSetPersistent(errorStack->data, true);
+        // store this threads error stack
+        // note that pthread_setspecifc() does not take a pointer as the first
+        // param
+        if (pthread_setspecific(errorStack_key, errorStack)) {
+            psAbort("pthread_setspecific() failed");
+        }
+    }
+
+    return errorStack;
+}
+
+// This function serves the same purpose of psErrorStackGet() accept it does
+// not alloc the error stack if it DOES NOT already exist.  Unlike
+// psErrorStackGet(), this function is NOT guarenteed to return a valid pointer
+// and it's return status must be checked.
+static psArray *psErrorStackGetNoAlloc(void)
+{
+    // check to see if the error stack key has been initialized
+    pthread_mutex_lock(&lockErrorStack);
+    if (errorStackKeyInitialized == false) {
+        pthread_mutex_unlock(&lockErrorStack);
+        return NULL;
+    }
+    pthread_mutex_unlock(&lockErrorStack);
+
+    // check to see if the error stack for this thread has been allocated
+    psArray *errorStack = NULL;
+    if ((errorStack = pthread_getspecific(errorStack_key)) == NULL) {
+        return NULL;
+    }
+
+    return errorStack;
+}
+
+static void psErrFree(psErr* err)
+{
+    if (err != NULL) {
+        psFree(err->msg);
+        psFree(err->name);
+    }
+}
+
+psErr* psErrAlloc(const char* name, psErrorCode code, const char* msg)
+{
+    psErr* err = psAlloc(sizeof(psErr));
+    err->msg = psStringCopy(msg);
+    err->name = psStringCopy(name);
+    err->code = code;
+
+    psMemSetDeallocator(err, (psFreeFunc)psErrFree);
+
+    return err;
+}
+
+psErrorCode p_psError(const char* filename,
+                      unsigned int lineno,
+                      const char* func,
+                      psErrorCode code,
+                      bool new,
+                      const char* format,
+                      ...)
+{
+    char errMsg[MAX_STRING_LENGTH];
+    char msgName[MAX_STRING_LENGTH];
+
+    // if this the origin of a new error reset the error stack
+    if (new) {
+        psErrorClear();
+    }
+
+    snprintf(msgName, MAX_STRING_LENGTH, "%s (%s:%d)", func, filename, lineno);
+
+    va_list ap;
+    va_start(ap, format);
+
+    vsnprintf(errMsg, MAX_STRING_LENGTH, format, ap);
+
+    va_end(ap);
+
+    // Remove a single trailing \n from message -- it interferes with
+    // psErrorStackPrint
+    size_t len = strlen(errMsg);
+    if (len > 0 && errMsg[len - 1] == '\n') {
+        errMsg[len - 1] = '\0';
+    }
+
+    psErr *err = psErrAlloc(msgName, code, errMsg);
+    psErrorStackPush(err);
+
+    #ifndef PS_NO_TRACE
+    // Call tracing function with PS_LOG_ERROR level
+    // p_psTrace() automatically appends the the function name to the facility
+    // for us
+    p_psTrace(__FILE__, __LINE__, func, "err", PS_LOG_ERROR, "%s : %s", err->name, err->msg);
+    #endif
+
+    psFree(err);
+
+    return code;
+}
+
+void p_psWarning(const char* file,
+                 int lineno,
+                 const char* func,
+                 const char* format,
+                 ...)
+{
+    char msgName[MAX_STRING_LENGTH];
+
+    snprintf(msgName, MAX_STRING_LENGTH, "%s (%s:%d)", func, file, lineno);
+
+    va_list ap;
+    va_start(ap, format);
+
+    psLogMsgV(msgName, PS_LOG_WARN, format, ap);
+
+    va_end(ap);
+
+    return;
+}
+
+psErr* psErrorGet(long which)
+{
+    psErr* result;
+
+    psArray *errorStack = psErrorStackGet();
+
+    // Check for negative reference and if found return PS_ERR_NONE
+    if (which < 0 ) {
+        result = psErrAlloc("", PS_ERR_NONE, "");
+    } else {
+        // the which input is from the end of errorStack
+        which = psArrayLength(errorStack) - 1 - which;
+        if (which < 0 || which >= psArrayLength(errorStack)) {
+            // no error at the given location
+            result = psErrAlloc("", PS_ERR_NONE, "");
+        } else {
+            // a new reference passed back
+            result = psMemIncrRefCounter(errorStack->data[which]);
+        }
+    }
+
+    return result;
+}
+
+long psErrorGetStackSize()
+{
+    psArray *errorStack = psErrorStackGet();
+
+    return psArrayLength(errorStack);
+}
+
+psErr* psErrorLast(void)
+{
+    return psErrorGet(0);
+}
+
+psErrorCode psErrorCodeLast(void)
+{
+    psErr *err = psErrorGet(0);
+    psErrorCode code = err->code;
+    psFree(err);
+
+    return code;
+}
+
+void psErrorClear(void)
+{
+    psArray *errorStack = psErrorStackGet();
+
+    for (long i = 0; i < psArrayLength(errorStack); i++) {
+        psErr *err = errorStack->data[i];
+
+        psMemSetPersistent(err, false);
+        psMemSetPersistent(err->msg, false);
+        psMemSetPersistent(err->name, false);
+    }
+
+    psArrayElementsFree(errorStack);
+}
+
+void psErrorStackPrint(FILE *fd, const char *format, ...)
+{
+    if (fd == NULL) {
+        fd = stdout;
+    }
+
+    va_list ap;             // variable list arguement pointer
+
+    va_start(ap, format);
+
+    psErrorStackPrintV(fd, format, ap);
+
+    va_end(ap);
+}
+
+// This function does not allocate any memory so it is safe to call from inside
+// of psMemory.c.  Do not allocate memory in function (or call any functions
+// that do) without first removing it's use from psMemory.c.
+void psErrorStackPrintV(FILE *fd, const char *format, va_list va)
+{
+    psArray *errorStack = psErrorStackGetNoAlloc();
+    // do nothing if the error stack has not been allocated
+    if (!errorStack) {
+        return;
+    }
+
+    vfprintf(fd, format, va);
+    fprintf (fd, "\n");
+
+    for (long i = 0; i < psArrayLength(errorStack); i++) {
+        psErr *err = errorStack->data[i];
+        if(err->code >= PS_ERR_BASE) {
+            fprintf(fd," -> %s: %s\n     %s\n",
+                    err->name,
+                    psErrorCodeString(err->code),
+                    err->msg);
+        } else {
+            fprintf(fd," -> %s: %s\n     %s\n",
+                    err->name,
+                    strerror(err->code),
+                    err->msg);
+        }
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psError.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psError.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psError.h	(revision 22158)
@@ -0,0 +1,197 @@
+/** @file  psError.h
+ *
+ *  @brief error reporting functions
+ *
+ *  Error reporting functions shall be used to create log entries in the
+ *  event errors are detected.  The messages shall give enough information
+ *  to allow the user to know where the error has occurred and the type
+ *  of error detected.
+ *
+ *  @author RHL, Princeton
+ *  @author Eric Van Alst, MHPCC
+ *  @author Joshua Hoblitt, University of Hawaii
+ *
+ *  @version $Revision: 1.36 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-08-09 01:40:07 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_ERROR_H
+#define PS_ERROR_H
+
+/// @addtogroup SysUtils System Utilities
+/// @{
+
+#include<stdio.h>
+#include<stdbool.h>
+#include<stdarg.h>
+
+#include "psType.h"
+#include "psErrorCodes.h"
+
+#define _(string) string
+
+/** Error message object */
+typedef struct
+{
+    char* name;                        ///< category of code that caused the error
+    psErrorCode code;                  ///< class of error
+    char* msg;                         ///< the message associated with the error
+}
+psErr;
+
+
+/** Get a error from the error stack
+ *
+ *  Previous errors on the stack are returned by psErrorGet (a value of 0
+ *  passed to psErrorGet is equivalent to a call to psErrorLast).
+ *
+ *  if no error is at the which position, a non-NULL psErr is returned with
+ *  code PS_ERR_NONE.
+ *
+ *  @return    Error message object at 'which'
+ */
+psErr* psErrorGet(
+    long which                          ///< position in the error stack. 0 is last error on stack.
+);
+
+
+/** Get last error put on the error stack
+ *
+ *  The last error reported is available from psErrorLast; if no errors are
+ *  current, a non-NULL psErr is returned with code PS_ERR_NONE.
+ *
+ *  @return psErr*     Reference to last error message on error stack
+ */
+psErr* psErrorLast(void);
+
+
+/** Get errorCode of last error put on the error stack
+ *
+ *  @return psErrorCode     last error code, or PS_ERR_NONE
+ */
+psErrorCode psErrorCodeLast(void);
+
+
+/** Clears the error stack.
+ *
+ *  The error stack may be completely cleared with psErrorClear.
+ *
+ */
+void psErrorClear(void);
+
+
+/** Get the error stack depth
+ *
+ *  @return int The number of items on the error stack
+ */
+long psErrorGetStackSize();
+
+
+/** Prints error stack to specified open file descriptor
+ *
+ *  The entire error stack may be printed to an open file descriptor by
+ *  calling psErrorStackPrint; if and only if there are current errors, the
+ *  printf-style string format is first printed to the file descriptor fd. In
+ *  this printout, error codes are replaced by their string equivalents.
+ *
+ */
+void psErrorStackPrint(
+    FILE* fd,                          ///< destination file descriptor
+    const char* format,                ///< printf-style format of header line
+    ...                                ///< any parameters required in format
+) PS_ATTR_FORMAT(printf, 2, 3);
+
+#ifndef SWIG
+/** Prints error stack to specified open file descriptor
+ *
+ *  The entire error stack may be printed to an open file descriptor by
+ *  calling psErrorStackPrintV; if and only if there are current errors, the
+ *  vprintf-style string format is first printed to the file descriptor fd. In
+ *  this printout, error codes are replaced by their string equivalents.
+ *
+ */
+void psErrorStackPrintV(
+    FILE* fd,                          ///< destination file descriptor
+    const char* format,                   ///< printf-style format of header line
+    va_list va                         ///< any parameters required in format
+);
+#endif // ifndef SWIG
+
+
+/** Reports an error message to the logging facility
+ *
+ *  This function will invoke the psLogMsg function with a level of
+ *  PS_LOG_ERROR and pass the parameters name and format to generate a proper
+ *  log message.
+ *
+ *  This function modifies the error stack.
+ *
+ *  @return psErrorCode    the given error code
+ */
+#ifdef DOXYGEN
+psErrorCode psError(
+    psErrorCode code,                  ///< Error class code
+    bool new,                        ///< true if error originates at this location
+    const char* format,                ///< printf-style format of header line
+    ...                                ///< any parameters required in format
+);
+#else // ifdef DOXYGEN
+psErrorCode p_psError(
+    const char* filename,              ///< file name
+    unsigned int lineno,               ///< line number in file
+    const char* func,                  ///< function name
+    psErrorCode code,                  ///< Error class code
+    bool new,                          ///< true if error originates at this location
+    const char* format,                ///< printf-style format of header line
+    ...                                ///< any parameters required in format
+) PS_ATTR_FORMAT(printf, 6, 7);
+#ifndef SWIG
+#define psError(code,new,...) \
+      p_psError(__FILE__,__LINE__,__func__,code,new,__VA_ARGS__)
+#endif // ifndef SWIG
+#endif // ifdef DOXYGEN
+
+
+/** Logs a warning message.
+ *
+ *  This procedure logs a message to the destination set by a prior
+ *  call to psLogSetDestination(), This is equivalent to calling
+ *  psLogMsg with a level of PS_LOG_WARN.
+ *
+ */
+#ifdef DOXYGEN
+void psWarning(
+    const char* format,                ///< printf-style format of header line
+    ...                                ///< any parameters required in format
+);
+#else // #ifdef DOXYGEN
+void p_psWarning(
+    const char* file,                  ///< file name
+    int lineno,                        ///< line number in file
+    const char* func,                  ///< function name
+    const char* format,                ///< printf-style format of header line
+    ...                                ///< any parameters required in format
+) PS_ATTR_FORMAT(printf, 4, 5);
+#ifndef SWIG
+#define psWarning(...) \
+      p_psWarning(__FILE__,__LINE__,__func__,__VA_ARGS__)
+#endif // ifndef SWIG
+#endif // ifdef DOXYGEN
+
+
+/** Create a new psErr struct
+ *
+ *  Creates a new psErr struct, making a copy of the parameters.
+ *
+ *  @return psErr*     new psErr object
+ */
+psErr* psErrAlloc(
+    const char* name,                  ///< Name of error in the form aaa.bbb.ccc
+    psErrorCode code,                  ///< Error class code
+    const char* msg                    ///< Error message
+) PS_ATTR_MALLOC;
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psErrorCodes.c.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psErrorCodes.c.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psErrorCodes.c.in	(revision 22158)
@@ -0,0 +1,165 @@
+/** @file  psErrorCodes.c
+ *
+ *  @brief Contains the error codes for the error classes
+ *
+ *  @ingroup ErrorHandling
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-02-07 01:21:54 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <string.h>
+
+#include "psError.h"
+#include "psErrorCodes.h"
+#include "psList.h"
+#include "psMemory.h"
+
+
+
+static psErrorDescription staticErrorCodes[] = {
+            {PS_ERR_NONE,"not an error"},
+            {PS_ERR_BASE,"base error"},
+            {PS_ERR_${ErrorCode},"${ErrorDescription}"},
+            {PS_ERR_N_ERR_CLASSES,"error classes end marker"}
+        };
+
+static psList* dynamicErrorCodes = NULL;
+static const psErrorDescription* getErrorDescription(psErrorCode code);
+
+
+static const psErrorDescription* getErrorDescription(psErrorCode code)
+{
+    // first, search the static error codes
+
+    psS32 n = 0;
+    while(staticErrorCodes[n].code != PS_ERR_N_ERR_CLASSES &&
+            staticErrorCodes[n].code != code) {
+        n++;
+    }
+
+    if (staticErrorCodes[n].code == code) {
+        return &staticErrorCodes[n];
+    } else {
+        psErrorDescription* desc;
+        // make sure there is a list to search
+        if (dynamicErrorCodes == NULL) {
+            return NULL;
+        }
+
+        // search dynamic list of error descriptions before giving up.
+        psListIterator* iter = psListIteratorAlloc(dynamicErrorCodes,PS_LIST_HEAD,true);
+        while ((desc = (psErrorDescription*)psListGetAndIncrement(iter)) != NULL) {
+            if (desc->code == code) {
+                psFree(iter);
+                return desc;
+            }
+        }
+        psFree(iter);
+    }
+    return NULL;
+}
+
+static void freeErrorDescription(psErrorDescription* err)
+{
+    psFree((void *)err->description);
+}
+
+psErrorDescription* psErrorDescriptionAlloc(psErrorCode code,
+        const char *description)
+{
+    psErrorDescription* err = psAlloc(sizeof(psErrorDescription));
+    err->code = code;
+    if (description == NULL) {
+        err->description = NULL;
+    } else {
+        err->description = psAlloc(sizeof(char)*strlen(description)+1);
+        strcpy((char*)err->description,description);
+    }
+
+    psMemSetDeallocator(err,(psFreeFunc)freeErrorDescription);
+    return err;
+}
+
+
+const char *psErrorCodeString(psErrorCode code)
+{
+    // Check input argument is non-negative
+    if ( code < 0 ) {
+        return NULL;
+    }
+
+    const psErrorDescription* desc = getErrorDescription(code);
+
+    if (desc == NULL) {
+        return NULL;
+    }
+
+    return desc->description;
+}
+
+void psErrorRegister(const psErrorDescription* errors,
+                     int errorCode)
+{
+    if (errorCode < 1) {
+        return;
+    }
+
+    if (errors == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Specified psErrorDescription pointer can not be NULL."));
+        return;
+    }
+
+    if (dynamicErrorCodes == NULL) {
+        dynamicErrorCodes = psListAlloc(NULL);
+        psMemSetPersistent(dynamicErrorCodes,true);
+
+        psMemSetPersistent(dynamicErrorCodes->iterators,true);
+        psMemSetPersistent(dynamicErrorCodes->iterators->data,true);
+        for (int i = 0; i < dynamicErrorCodes->iterators->n;i++) {
+            psMemSetPersistent(dynamicErrorCodes->iterators->data[i],true);
+        }
+    }
+
+    for (psS32 i = 0; i < errorCode; i++) {
+        psErrorDescription* err = psErrorDescriptionAlloc(
+                                      errors[i].code, errors[i].description);
+        psMemSetPersistent(err,true);
+        psMemSetPersistent((psPtr)err->description,true);
+        if (! psListAdd(dynamicErrorCodes,
+                        PS_LIST_HEAD,
+                        err) ) {
+
+            psError(PS_ERR_UNKNOWN, false,
+                    _("Failed to add input psErrorDescription at array index %d."),
+                    i);
+        }
+        psMemSetPersistent(dynamicErrorCodes->head,true);
+        psFree(err);
+    }
+}
+
+bool p_psErrorUnregister(psErrorCode code)
+{
+    // Check input argument is non-negative
+    if ( code < 0 ) {
+        return false;
+    }
+
+    const psErrorDescription* desc = getErrorDescription(code);
+
+    if (desc == NULL) {
+        return false;
+    }
+
+    if (dynamicErrorCodes == NULL) {
+        return false;
+    }
+
+    return psListRemoveData(dynamicErrorCodes,(psPtr)desc);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psErrorCodes.h.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psErrorCodes.h.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psErrorCodes.h.in	(revision 22158)
@@ -0,0 +1,90 @@
+/** @file  psErrorCodes.h
+ *
+ *  @brief Contains the error codes for the error classes
+ *
+ *  @author RHL, Princeton
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-02-08 01:59:28 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_ERROR_CODES_H
+#define PS_ERROR_CODES_H
+
+/// @addtogroup SysUtils System Utilities 
+/// @{
+
+#include "psType.h"
+
+/** enumeration of the static error code classes
+ */
+typedef enum {
+    PS_ERR_NONE = 0,                   ///< not an error
+    PS_ERR_BASE = 256,
+    /**< base error.  Any psErrorCode less than this should be taken to be
+     *   valid values of errno
+     */
+    PS_ERR_${ErrorCode},
+    PS_ERR_N_ERR_CLASSES               ///< end marker - should not be used as a true error
+} psErrorCode;
+
+
+/** An error code with description
+ */
+typedef struct
+{
+    psErrorCode code;                  ///< An error code
+    const char *description;           ///< the associated description
+}
+psErrorDescription;
+
+
+/** Allocates a new psErrorDescription
+ *
+ *  @return psErrorDescription*        new psErrorDescription struct.
+ */
+psErrorDescription* psErrorDescriptionAlloc(
+    psErrorCode code,                  ///< An error code
+    const char *description            ///< the associated description
+);
+
+
+/** Retrieves the description of an error code.
+ *
+ *  The routine psErrorCodeString returns the string associated with an error
+ *  code.
+ *
+ *  @return const char*     the description associated with the given code.
+ */
+const char *psErrorCodeString(
+    psErrorCode code                   ///< the associated error code
+);
+
+
+/** Register an error code
+ *
+ *  Any project needed to use psLib must define the necessary error codes and
+ *  associated message strings.  This function registers an array of error
+ *  codes with the error handling subsystem.
+ *
+ */
+void psErrorRegister(
+    const psErrorDescription* errors,  ///< Array of error codes to register
+    int errorCode                      ///< number of errors in input array
+);
+
+
+/** Clears error codes registered via psErrorRegister.
+ *
+ *  @return bool    TRUE if given errorcode was removed, otherwise FALSE.
+ */
+bool p_psErrorUnregister(
+    psErrorCode code                   ///< the error code to find and remove
+);
+
+
+/// @}
+#endif // #ifndef PS_ERROR_CODES_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psExit.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psExit.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psExit.h	(revision 22158)
@@ -0,0 +1,21 @@
+#ifndef PS_EXIT_H
+#define PS_EXIT_H
+
+/// @addtogroup SysUtils System Utilities
+/// @{
+
+/// Exit status codes
+///
+/// These provide a bit finer granularity compared to success/fail
+typedef enum {
+    PS_EXIT_SUCCESS = 0,                ///< Successful termination; matches EXIT_SUCCESS
+    PS_EXIT_UNKNOWN_ERROR = 1,          ///< Error of unknown nature; matches EXIT_FAILURE
+    PS_EXIT_SYS_ERROR,                  ///< Error with a system call
+    PS_EXIT_CONFIG_ERROR,               ///< Error with configuration
+    PS_EXIT_PROG_ERROR,                 ///< Error in programming (look also for aborts)
+    PS_EXIT_DATA_ERROR,                 ///< Error with data
+    PS_EXIT_TIMEOUT_ERROR,              ///< Error due to timeout
+} psExit;
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psLine.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psLine.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psLine.c	(revision 22158)
@@ -0,0 +1,75 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "psAssert.h"
+#include "psConstants.h"
+#include "psLine.h"
+#include "psString.h"
+#include "psMemory.h"
+
+static void lineFree(psLine *line)
+{
+
+    if (!line) {
+        return;
+    }
+
+    psFree (line->line);
+    return;
+}
+
+// allocate a psLine structrue
+psLine *psLineAlloc(long Nline)
+{
+    psLine *line = psAlloc(sizeof(psLine));
+    psMemSetDeallocator(line, (psFreeFunc)lineFree);
+    line->Nline = 0;
+    line->NLINE = Nline;
+    //    line->line = psAlloc(Nline);
+    line->line = psStringAlloc(Nline);
+
+    return line;
+}
+
+bool psLineInit(psLine *line)
+{
+    if (!line) {
+        return false;
+    }
+
+    line->Nline = 0;
+    return true;
+}
+
+bool psLineAdd(psLine *line,
+               const char *format,
+               ...)
+{
+    if (!line) {
+        return false;
+    }
+
+    long nMax = line->NLINE - line->Nline;
+
+    va_list ap;
+    va_start(ap, format);
+    long Nchar = vsnprintf(&line->line[line->Nline], nMax, format, ap);
+    line->Nline += PS_MIN(nMax - 1, Nchar);
+    va_end(ap);
+
+    if (Nchar >= nMax) {
+        return false;
+    }
+    return true;
+}
+
+bool psMemCheckLine(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)lineFree );
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psLine.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psLine.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psLine.h	(revision 22158)
@@ -0,0 +1,80 @@
+/** @file  psLine.h
+ *
+ *  @brief charater-string fixed-length line functions
+ *
+ *  The psLine functions allow manipulation of fixed-length lines.
+ *
+ *  @author EAM, IFA
+ *  @author Paul Price, IFA
+ *  @author David Robbins, MHPCC
+ *
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-08-09 01:40:07 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_LINE_H
+#define PS_LINE_H
+
+/// @addtogroup SysUtils System Utilities
+/// @{
+
+/** Structure to carry a dynamic string */
+typedef struct
+{
+    long NLINE;                        ///< allocated length
+    long Nline;                        ///< current length
+    psString line;                     ///< character string data
+}
+psLine;
+
+
+/** Allocates a line object of length Nline.
+ *
+ *  @return psLine*:        the newly allocated line object.
+*/
+psLine *psLineAlloc(
+    long Nline                         ///< length of line object to allocate
+) PS_ATTR_MALLOC;
+
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psLine structure, false otherwise.
+ */
+bool psMemCheckLine(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+
+/** Initializes or re-initializes a line.
+ *
+ *  Initializes or re-initializes a line, setting the current length to zero and setting
+ *  the string data values to 0.  If the function is passed NULL, false is returned.
+ *
+ *  @return bool:       True if successful, otherwise false.
+*/
+bool psLineInit(
+    psLine *line                       ///< line to (re-)initialize
+);
+
+
+/** Adds the line segment to the string.
+ *
+ *  Appends a line segment to the string, returning false if the new segment would
+ *  overflow the allocated string length.
+ *
+ *  @return bool:        True if successful, otherwise false.
+*/
+bool psLineAdd(
+    psLine *line,                      ///< the line segment to append
+    const char *format,                ///< printf-style format of line
+    ...                                ///< any parameters required in format
+) PS_ATTR_FORMAT(printf, 2, 3);
+
+
+/// @}
+#endif /* PS_LINE_H */
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psLogMsg.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psLogMsg.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psLogMsg.c	(revision 22158)
@@ -0,0 +1,372 @@
+/** @file  psLogMsg.c
+ *  @brief Procedures for logging messages.
+ *  \ingroup LogTrace
+ *
+ *  This file contains code for setting message log levels, message log
+ *  formats, message log destinations, and for generating the messages
+ *  themselves.
+ *  @ingroup LogTrace
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.69 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-02-06 20:33:18 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <stdarg.h>
+#include <time.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "psLogMsg.h"
+#include "psError.h"
+#include "psTrace.h"
+#include "psList.h"
+#include "psString.h"
+#include "psMemory.h"
+
+
+
+#define MIN_LOG_LEVEL 0
+#define MAX_LOG_LEVEL 9
+
+#define MAX_LOG_LINE_LENGTH 256
+
+static int logFD = STDERR_FILENO;       // Log file descriptor
+static psS32 globalLogLevel = PS_LOG_INFO; // log all messages at this or above
+static bool logTime = true;     // Flag to include time info
+static bool logHost = true;     // Flag to include host info
+static bool logLevel = true;    // Flag to include level info
+static bool logName = true;     // Flag to include name info
+static bool logMsg = true;      // Flag to include message info
+
+/*****************************************************************************
+psLogSetLevel(): Set the current log level and return old level.
+Input:
+ level (psS32): the new log level.
+Output:
+ The old log level.
+ *****************************************************************************/
+int psLogSetLevel(int level)
+{
+    // Save old global log level for changing it.
+    psS32 oldLevel = globalLogLevel;
+
+    if ((level < MIN_LOG_LEVEL) || (level > MAX_LOG_LEVEL)) {
+        psLogMsg("logmsg", PS_LOG_WARN, "Attempt to set invalid logMsg level: %d", level);
+        level = (level < MIN_LOG_LEVEL) ? MIN_LOG_LEVEL : MAX_LOG_LEVEL;
+    }
+    // Set new global log level
+    globalLogLevel = level;
+
+    // Return old global log level
+    return oldLevel;
+}
+
+int psLogGetLevel()
+{
+    return globalLogLevel;
+}
+
+/*****************************************************************************
+psLogSetDestination(): sets the log message destination.
+Input:
+ dest (psS32): the new log destination
+Return:
+ An bool: TRUE if successful.
+ *****************************************************************************/
+bool psLogSetDestination(int fd)
+{
+    if (fd < 0) {
+        return false;
+    }
+
+    // Close the current FD if it's not stdout, stderr.
+    if (logFD > STDERR_FILENO) {
+        close(logFD);
+    }
+    logFD = fd;
+
+    return true;
+}
+
+int psLogGetDestination(void)
+{
+    return logFD;
+}
+
+
+/*****************************************************************************
+psLogSetFormat(): Set the format of psLogMsg output.  More precisely,
+    provide a string consisting of the letters {H (host), L (level), M
+    (message), N (name), T (time)}.  The default is "HLMNT".  This string
+    determines whether or not they associated type of information will be
+    included in message logs.  It does not determine the order in which that
+    information will appear (that order is fixed).
+
+Input:
+    fmt: a string specifying the format.
+Return:
+    NULL.
+ *****************************************************************************/
+bool psLogSetFormat(const char *format)
+{
+    // assume none.
+    logHost = false;
+    logLevel = false;
+    logMsg = false;
+    logName = false;
+    logTime = false;
+
+    // if fmt is NULL, no logging is desired.
+    if (format == NULL) {
+        return false;
+    }
+
+    // XXX: What is the purpose of this conditional.
+    if (strlen(format) == 0) {
+        format = "THLNM";
+    }
+    // Step through each character in the format string.  For each letter
+    // in that string, set the appropriate logging.
+
+    for (const char *ptr = format; *ptr != '\0'; ptr++) {
+        switch (*ptr) {
+        case 'H':
+        case 'h':
+            logHost = true;
+            break;
+        case 'L':
+        case 'l':
+            logLevel = true;
+            break;
+        case 'M':
+        case 'm':
+            logMsg = true;
+            break;
+        case 'N':
+        case 'n':
+            logName = true;
+            break;
+        case 'T':
+        case 't':
+            logTime = true;
+            break;
+        default:
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    _("Unknown logging keyword %c."), *ptr);
+            return false;
+        }
+    }
+
+    // XXX: If one must at least log error messages, why don't we set logMsg = true here?
+    if (!logMsg) {
+        psTrace("psLib.sys", 1, "You must at least log error messages (You chose \"%s\")", format);
+
+    }
+    return true;
+}
+
+int psMessageDestination(const char *dest)
+{
+    // No destination
+    if (dest == NULL || strcasecmp(dest, "none") == 0) {
+        return 0;
+    }
+
+    // Special destinations: stdout, stderr
+    if (strcasecmp(dest, "stdout") == 0) {
+        return STDOUT_FILENO;
+    }
+    if (strcasecmp(dest, "stderr") == 0) {
+        return STDERR_FILENO;
+    }
+
+    int fileD = creat(dest, 0666);
+    if (fileD == 0) {
+        psError(PS_ERR_IO, true, _("Could not open file '%s' for output."), dest);
+        return -1;
+    }
+    return fileD;
+}
+
+#ifndef HOST_NAME_MAX                // should be in limits.h
+#define HOST_NAME_MAX 256
+#endif // #ifndef HOST_NAME_MAX
+
+/*****************************************************************************
+psLogMsgV(): This routine sends the message, which is a printf style string
+specified in the "..." argument, to the current message log destination with
+the severity specified by the "level" argument.
+ Input:
+   name
+   level
+   fmt
+   ap
+ *****************************************************************************/
+void psLogMsgV(const char *name, int level, const char *format, va_list ap)
+{
+    static psS32 first = 1;       // Flag for calling gethostname()
+    static char hostname[HOST_NAME_MAX + 1];
+
+    // Buffer for hostname.
+    char clevel = 0;            // letter-name for level
+    char head[MAX_LOG_LINE_LENGTH + 2]; // the added two are for the ending | and \0
+    char *head_ptr = head;      // where we've got to in head
+    psS32 maxLength = MAX_LOG_LINE_LENGTH;
+    time_t clock = time(NULL);  // The current time.
+    struct tm *utc = gmtime(&clock);    // The current gm time.
+
+    // If it's an abort, we always want to see the message
+    if (logFD == 0 && level == PS_LOG_ABORT) {
+        logFD = STDERR_FILENO;
+    }
+    // If logging is off, or if the level is too high, return immediately.
+    if ((level > globalLogLevel) || (logFD == 0)) {
+        return;
+    }
+    // If I have not been here yet, determine my hostname and save it.
+    if (first) {
+        first = 0;
+        gethostname(hostname, HOST_NAME_MAX);
+    }
+
+    switch (level) {
+    case PS_LOG_ABORT:
+        clevel = 'A';
+        break;
+
+    case PS_LOG_ERROR:
+        clevel = 'E';
+        break;
+
+    case PS_LOG_WARN:
+        clevel = 'W';
+        break;
+
+    case PS_LOG_INFO:
+        clevel = 'I';
+        break;
+
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+    case 9:
+        clevel = level + '0';
+        break;
+
+    default:
+        psTrace("psLib.sys", 2, "Invalid logMsg level: %d (%s)\n", level, format);
+        level = (level < 0) ? 0 : 9;
+        clevel = level + '0';
+        break;
+    }
+
+    // Create the various log fields...
+    if (logTime) {
+        maxLength -= snprintf(head_ptr, maxLength, "%4d-%02d-%02d %02d:%02d:%02dZ",
+                              utc->tm_year + 1900, utc->tm_mon + 1, utc->tm_mday,
+                              utc->tm_hour, utc->tm_min, utc->tm_sec) - 1;
+        head_ptr += strlen(head_ptr);
+    }
+    // Hostname should be 20 characters.
+    if (logHost) {
+        if (head_ptr > head) {
+            *head_ptr++ = '|';
+        }
+        maxLength -= snprintf(head_ptr, maxLength, "%-20s", hostname);
+        head_ptr += strlen(head_ptr);
+    }
+    if (logLevel) {
+        if (head_ptr > head) {
+            *head_ptr++ = '|';
+        }
+        maxLength -= snprintf(head_ptr, maxLength, "%c", clevel);
+        head_ptr += strlen(head_ptr);
+    }
+    if (logName) {
+        if (head_ptr > head) {
+            *head_ptr++ = '|';
+        }
+        maxLength -= snprintf(head_ptr, maxLength, "%s", name);
+
+        head_ptr += strlen(head_ptr);
+    }
+
+    if (head_ptr > head) {
+        *head_ptr++ = '\n';
+    } else if (!logMsg) {                  // no output desired
+        return;
+    }
+    *head_ptr = '\0';
+
+    write(logFD, head, strlen(head));
+    if (logMsg) {
+        psString msg = NULL;            // Message to print
+        psStringAppendV(&msg, format, ap);
+
+        // detect multiple lines in message and indent each line by 4 spaces.
+        char* msgPtr;
+        char *line = strtok_r(msg, "\n", &msgPtr);
+        while (line) {
+            write(logFD, "    ", 4);
+            write(logFD, line, strlen(line));
+            write(logFD, "\n", 1);
+            line = strtok_r(NULL, "\n", &msgPtr);
+        }
+        psFree(msg);
+    } else {
+        write(logFD, "\n", 1);
+    }
+
+    if (level == PS_LOG_ABORT) {
+        switch (logFD) {
+        case STDOUT_FILENO:
+            fflush(stdout);
+            break;
+        case STDERR_FILENO:
+            fflush(stderr);
+            break;
+            // For the others, write() should send it unbuffered...?
+        }
+
+    }
+}
+
+/*****************************************************************************
+psLogMsg(): This routine sends the message, which is a printf style string
+specified in the "..." argument, to the current message log destination with
+the severity specified by the "level" argument.
+
+Input:
+  name: Indicates the source of this log message.
+  level: The severity of this log message.
+  fmt: The printf-stype formatted string, followed by the arguments
+        to that string.
+  ... The arguments to the above printf-style string.
+
+Return:
+   NULL
+ *****************************************************************************/
+void psLogMsg(const char *name, int level, const char *format, ...)
+{
+    va_list ap;
+
+    va_start(ap, format);
+    psLogMsgV(name, level, format, ap);
+    va_end(ap);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psLogMsg.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psLogMsg.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psLogMsg.h	(revision 22158)
@@ -0,0 +1,140 @@
+/** @file  psLogMsg.h
+ *
+ *  @brief Procedures for logging messages.
+ *
+ *  This file will hold the prototypes for defining procedure which set
+ *  message log levels, messahe log formats, message log destinations, and
+ *  for generating the messages themselves.
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author GLG, MHPCC
+ *  @author Joshua Hoblitt, University of Hawaii
+ *
+ *  @version $Revision: 1.40 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-08-09 01:40:07 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_LOG_MSG_H
+#define PS_LOG_MSG_H
+
+/// @addtogroup SysUtils System Utilities
+/// @{
+
+#include <stdarg.h>
+#include "psType.h"
+
+
+///< Status codes for log messages
+enum {
+    PS_LOG_ABORT = 0,                  ///< log message is a critical error, perform an abort after printing
+    PS_LOG_ERROR,                      ///< log message is an error, but don't abort
+    PS_LOG_WARN,                       ///< log message is a warning
+    PS_LOG_INFO,                       ///< log message is informational only
+    PS_LOG_DETAIL,                     ///< log message provides details of minor interest
+    PS_LOG_MINUTIA,                    ///< log message provides very detailed information
+};
+
+
+///< Destinations for log messages
+enum {
+    PS_LOG_TO_NONE = 0,                ///< turn off logging
+    PS_LOG_TO_STDERR = 1,              ///< log to system's stderr
+    PS_LOG_TO_STDOUT = 2               ///< log to system's stdout
+};
+
+/** This procedure sets the destination for future log messages.
+ *
+ *  This procedure will take an integer as an argument
+ *  which can specify general log destinations.
+ *
+ *  @return bool     true if set successfully, otherwise false.
+ */
+bool psLogSetDestination(
+    int fd                             ///< Specifies where to send messages.
+);
+
+
+/** This procedure returns the current log destination file descriptor.  If the
+ * destination has not been defined by the use, the descriptor for stdout is
+ * returned.
+ *
+ *  @return int:        The current file descriptor.
+ */
+int psLogGetDestination();
+
+
+/** This procedure sets the message level for future log messages.  Subsequent
+ *  log messages, with a log level of "mylevel", will only be logged if
+ *  "mylevel" is less than the current log level set by this procedure.
+ *  Ie. higher values set by this procedure will cause more log messages to
+ *  be displayed.  The old log level will be returned.
+ *
+ *  @return int:        old logging level.
+ */
+int psLogSetLevel(
+    int level                          ///< Specifies the system log level
+);
+
+
+/** This procedures returns the current log message level.
+ *
+ *  @return int:        The current logging level.
+ */
+int psLogGetLevel();
+
+/** This procedure sets the log format for future log messages.  The argument
+ *  must be a character string consistsing of the letters H (host), L
+ *  (level), M (message), N (name), and T (time).  The default is "THLNM".
+ *  Deleting a letter from the string will cause the associated information
+ *  to not be logged.  This procedure does not alter the order in which
+ *  the messages are displayed.
+ *
+ *  @return bool:       True if successful, otherwise false.
+ */
+bool psLogSetFormat(
+    const char *format                 ///< Specifies the system log format
+);
+
+
+/** This procedures uses a string to set the destination for which to send
+ *  the corresponding log messages.
+ *
+ *  @return int:        The file descriptor location of the message.
+ */
+int psMessageDestination(
+    const char *dest                   ///< Specifies where to send the message
+);
+
+
+/** This procedure logs a message to the destination set by a prior
+ *  call to psLogSetDestination(), if myLevel is less than the level
+ *  specified by a prior call to psLogSetLevel().  The message is specified
+ *  with a printf-type string and arguments.
+ *
+ */
+void psLogMsg(
+    const char *name,                  ///< name of the log source
+    int level,                         ///< severity level of this log message
+    const char *format,                ///< printf-style format command
+    ...
+) PS_ATTR_FORMAT(printf, 3, 4);
+
+
+/** This procedure is functionally equivalent to psLogMsg(), except that
+ *  it takes a va_list as the message parameter, not a printf-style string.
+ *
+ */
+#ifndef SWIG
+void psLogMsgV(
+    const char *name,                  ///< name of the log source
+    int level,                         ///< severity level of this log message
+    const char *format,                ///< printf-style format command
+    va_list ap                         ///< varargs argument list
+);
+#endif // #ifndef SWIG
+
+
+/// @}
+#endif // #ifndef PS_LOG_MSG_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psMemory.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psMemory.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psMemory.c	(revision 22158)
@@ -0,0 +1,1072 @@
+/** @file  psMemory.c
+*
+*  @brief Contains the definitions for the memory management system
+*
+*  psMemory.h has additional information and documentation of the routines
+*  found in this file.
+*
+*  @author Robert DeSonia, MHPCC
+*  @author Robert Lupton, Princeton University
+*  @author Joshua Hoblitt, University of Hawaii
+*
+*  @version $Revision: 1.98.20.1 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2008-07-31 03:57:31 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#define PS_ALLOW_MALLOC                    // we're allowed to call malloc()
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+#if defined(PS_MEM_BACKTRACE) && defined(HAVE_BACKTRACE)
+# include <execinfo.h>
+#endif
+
+#include "psError.h"    // for psErrorStackPrint() only
+#include "psMemory.h"
+
+// Magic number in psMemBlock header
+#define P_PS_MEMMAGIC (uint32_t)0xdeadbeef
+
+#define MUTEX_LOCK(mutexPtr) \
+if (safeThreads) { \
+    pthread_mutex_lock(mutexPtr); \
+}
+
+#define MUTEX_UNLOCK(mutexPtr) \
+if (safeThreads) { \
+    pthread_mutex_unlock(mutexPtr); \
+}
+
+// psAbort() calls functions that call psAlloc() so it is *UNSAFE* to use it
+// from within the memory subsystem.  Previous implementations tried to do
+// this and would deadlock while trying to allocate memory.
+//
+// Note that psError() is also *UNSAFE* to use from within the memory
+// subsystem.
+#define PS_MEM_ABORT(name, ...) \
+P_PS_MEM_ABORT(__FILE__, __LINE__, __func__, name, __VA_ARGS__)
+
+// psErrorStackPrint() was specifically modified to be safe to call from inside
+// psMemory.c.
+#define P_PS_MEM_ABORT(filename, lineno, func, name, ...) \
+fprintf(stderr, "%s (%s:%d) ", func, filename, lineno); \
+fprintf(stderr, __VA_ARGS__);\
+psErrorStackPrint(stderr, "\nAborting.  Error stack:\n"); \
+fprintf(stderr, "\n");\
+abort();
+
+#define HANDLE_BAD_BLOCK(memBlock, file, lineo, func) \
+if (isBadMemBlock(stderr, memBlock, file, lineo, func)) { \
+    PS_MEM_ABORT(__func__, "Unsafe to Continue\n"); \
+}
+
+static bool isBadMemBlock(FILE *output, const psMemBlock *memBlock, const char *file, unsigned int lineo, const char *func);
+
+// memBlockListMutex protects access to:
+//      safeThreads -- very rarely accessed
+//      memory_is_persistent -- very rarely accessed
+//      memAllocCallback -- very rarely accessed
+//      memFreeCallback -- very rarely accessed
+//      memExhaustedCallback -- very rarely accessed
+//      p_psMemAllocID -- rarely accessed
+//      p_psMemFreeID -- rarely accessed
+//      lastMemBlockAllocated 
+//      memid -- rarely accessby 
+//      "the linked list of mem blocks"
+//
+// This is a fair ammount of stuff to protect with a single mutex but most of
+// these items are *VERY* low contention items.  The only item that should be
+// performance issue is "the linked list of mem blocks".  If this does become a
+// problem in production use of the list should be disabled as it is really a
+// debugging feature.
+//
+// XXX make the mem block list a build time option
+//
+static pthread_mutex_t memBlockListMutex = PTHREAD_MUTEX_INITIALIZER;
+
+/******** thread safety options management ********/
+
+// private boolean for enabling/disabling thread safety.  Default = enabled.
+static bool safeThreads = true;
+
+// Set the thread-safety state of the memory system: default is true
+bool psMemSetThreadSafety(bool safe)
+{
+    // this function is only called ~once per program, before threads are launched
+    MUTEX_LOCK(&memBlockListMutex);
+
+    bool oldState = safeThreads;
+    safeThreads = safe;
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    return oldState;
+}
+
+
+// Get the thread-safety state of the memory system
+bool psMemGetThreadSafety(void)
+{
+    // this function is only called ~once per program, probably before threads are launched
+    MUTEX_LOCK(&memBlockListMutex);
+
+    bool oldState = safeThreads;
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    return oldState;
+}
+
+/******** persistent memory options management ********/
+
+// private boolean for deciding if allocated memory is persistent by default
+static bool memory_is_persistent = false;
+
+/* Set whether allocated memory is persistent
+ */
+bool p_psMemAllocatePersistent(bool is_persistent)
+{
+    // this function is only called ~once per program, before threads are launched
+    MUTEX_LOCK(&memBlockListMutex);
+
+    const bool old = memory_is_persistent;
+    memory_is_persistent = is_persistent;
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    return old;
+}
+
+/*
+ * And now the I-want-to-be-informed callbacks
+ *
+ * Call the callbacks when these IDs are allocated/freed
+ */
+/******** memory allocation callback management (memAllocCallback) ********/
+
+// Default memFreeCallback function
+static psMemId memAllocCallbackDefault(const psMemBlock *memBlock)
+{
+    static psMemId incr = 0; // "p_psMemAllocID += incr"
+
+    return incr;
+}
+
+static psMemAllocCallback memAllocCallback = memAllocCallbackDefault;
+
+psMemAllocCallback psMemAllocCallbackSet(psMemAllocCallback func)
+{
+    // this function is only called rarely per program
+    MUTEX_LOCK(&memBlockListMutex);
+
+    psMemAllocCallback old = memAllocCallback;
+
+    if (func != NULL) {
+        memAllocCallback = func;
+    } else {
+        memAllocCallback = memAllocCallbackDefault;
+    }
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    return old;
+}
+
+// notify user when this block is allocated
+// XXX why was this not static, and why was it p_psMemAllocID?
+static psMemId p_psMemAllocID = 0;       
+
+// the above callback is only called if a specific psMemId is set with this function
+// this function is rarely called in a given program
+psMemId psMemAllocCallbackSetID(psMemId id)
+{
+    // this function is only called rarely per program
+    MUTEX_LOCK(&memBlockListMutex);
+
+    psMemId old = p_psMemAllocID;
+
+    p_psMemAllocID = id;
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    return old;
+}
+
+/******** memory free callback management (memFreeCallback) ********/
+
+// Default memFreeCallback function
+static psMemId memFreeCallbackDefault(const psMemBlock *memBlock)
+{
+    static psMemId incr = 0; // "p_psMemFreeID += incr"
+
+    return incr;
+}
+
+static psMemFreeCallback memFreeCallback = memFreeCallbackDefault;
+
+// this function is called only rarely in a program
+psMemFreeCallback psMemFreeCallbackSet(psMemFreeCallback func)
+{
+    // this function is only called rarely per program
+    MUTEX_LOCK(&memBlockListMutex);
+
+    psMemFreeCallback old = memFreeCallback;
+
+    if (func != NULL) {
+        memFreeCallback = func;
+    } else {
+        memFreeCallback = memFreeCallbackDefault;
+    }
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    return old;
+}
+
+// notify user when this block is freed
+// XXX why was this not static?
+static psMemId p_psMemFreeID = 0;
+
+// the above callback is only called if a specific psMemId is set with this function
+psMemId psMemFreeCallbackSetID(psMemId id)
+{
+    // this function is rarely called in a given program
+    MUTEX_LOCK(&memBlockListMutex);
+
+    psMemId old = p_psMemFreeID;
+
+    p_psMemFreeID = id;
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    return old;
+}
+
+/******** memory exhausted callback management (memExhaustedCallback) ********/
+
+// Default memExhaustedCallback function
+static void *memExhaustedCallbackDefault(size_t size)
+{
+    return NULL;
+}
+
+static psMemExhaustedCallback memExhaustedCallback = memExhaustedCallbackDefault;
+
+psMemExhaustedCallback psMemExhaustedCallbackSet(psMemExhaustedCallback func)
+{
+    // this function is rarely called in a given program
+    MUTEX_LOCK(&memBlockListMutex);
+
+    psMemExhaustedCallback old = memExhaustedCallback;
+
+    if (func != NULL) {
+        memExhaustedCallback = func;
+    } else {
+        memExhaustedCallback = memExhaustedCallbackDefault;
+    }
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    return old;
+}
+
+/* An example callback function to check the state of the memory system; may be registered
+ * with psMem{Alloc,Free}CallbackSet
+ */
+psMemId memAllocCallbackCheckCorruption(const psMemBlock *memBlock)
+{
+    static psMemId incr = 10; // "p_psMemAllocID += incr"
+
+    if (psMemCheckCorruption(stderr, false) > 0) {
+        fprintf(stderr, "Detected memory corruption\n"); // somewhere to set a breakpoint
+    }
+
+    return incr;
+}
+
+/**** Unique ID for allocated blocks and associated accessor functions
+ */
+static psMemId memid = 0;
+
+/* Return memory ID counter for next block to be allocated
+ */
+psMemId psMemGetId(void)
+{
+    // this function is only occasionally called in a given program
+    MUTEX_LOCK(&memBlockListMutex);
+
+    psMemId id = memid + 1;
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    return id;
+}
+
+/* Return memory ID counter for last block allocated
+ */
+psMemId psMemGetLastId(void)
+{
+    // this function is only occasionally called in a given program
+    MUTEX_LOCK(&memBlockListMutex);
+
+    psMemId id = memid;
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    return id;
+}
+
+// pointer to the last mem block that was allocated.  
+// This is the root of the entire memory list
+static psMemBlock *lastMemBlockAllocated = NULL;
+
+/* Actually allocate memory
+ */
+void *p_psAlloc(const char *file,
+                unsigned int lineno,
+                const char *func,
+                size_t size)
+{
+
+    psMemBlock *memBlock = malloc(sizeof(psMemBlock) + size + sizeof(void *));
+    if (memBlock == NULL) {
+	// this lock is only occasionally called in a given program (rarely fail malloc)
+        MUTEX_LOCK(&memBlockListMutex);
+        memBlock = memExhaustedCallback(size);
+        MUTEX_UNLOCK(&memBlockListMutex);
+        if (memBlock == NULL) {
+            PS_MEM_ABORT(__func__, "Failed to allocate %zd bytes at %s (%s:%d)", size, func, file, lineno);
+        }
+    }
+
+    // posts
+    *(psU32 *)&memBlock->startblock = P_PS_MEMMAGIC;
+    *(psU32 *)&memBlock->endblock   = P_PS_MEMMAGIC;
+    *(psU32 *)((char *) (memBlock + 1) + size) = P_PS_MEMMAGIC;
+
+    // size of memory allocated
+    memBlock->userMemorySize = size;
+
+    // alloc request by:
+    // thread
+    *(pthread_t *)&memBlock->tid = pthread_self();
+    // file
+    memBlock->file = file;
+    // line number
+    *(unsigned int *)&memBlock->lineno = (unsigned int)lineno;
+    // function
+    memBlock->func = func;
+
+    #if defined(PS_MEM_BACKTRACE) && defined(HAVE_BACKTRACE)
+    #define BACKTRACE_BUFFER_SIZE 32
+    // psMemBlock.func is a 'const char *', so basically we're going to abuse
+    // that and treat it as a void ** to carry around backtrace information.
+    // psMemBlock is not ifdef'd to make sure that psMemBlock is always the
+    // same size & layout reguardless of the pslib .so that's being linked
+    // against
+    void **bt = malloc(BACKTRACE_BUFFER_SIZE * sizeof(void *));
+    if (bt == NULL) {
+        PS_MEM_ABORT(__func__, "Failed to allocate memory for backtrace buffer: %zd bytes at %s (%s:%d)", 32 * sizeof(void *), func, file, lineno);
+    }
+    *(size_t *)&memBlock->backtraceSize = backtrace(bt, BACKTRACE_BUFFER_SIZE);
+    *(void ***)&memBlock->backtrace = bt;
+    #endif // ifdef HAVE_BACKTRACE
+
+    // free function
+    memBlock->freeFunc = NULL;
+
+    // persistent memory flag
+    memBlock->persistent = memory_is_persistent;
+
+    // this block will be add as the last mem block in the list
+    memBlock->previousBlock = NULL;
+
+    // ref count
+    memBlock->refCounter = 1;                   // one user so far
+
+    // need exclusive access of the memory block list now...
+    // this lock is very frequently called in a given program
+    MUTEX_LOCK(&memBlockListMutex);
+
+    // increment the memory id only after we've grabbed the memBlockListMutex
+    *(psMemId* )&memBlock->id = ++memid;
+
+    // insert the new block to the front of the memBlock linked-list
+    if (lastMemBlockAllocated != NULL) {
+	// exchange forward and backward references with the last allocated block
+	lastMemBlockAllocated->previousBlock = memBlock;
+	memBlock->nextBlock = lastMemBlockAllocated;
+    }
+    lastMemBlockAllocated = memBlock;
+
+    // Did the user ask to be informed about this allocation?
+    if (memBlock->id == p_psMemAllocID) {
+        // p_psMemAllocID can only be changed while the memBlockList mutex is
+        // held
+        p_psMemAllocID += memAllocCallback(memBlock);
+    }
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    // And return the user the memory that they allocated
+    return memBlock + 1;                        // user memory
+}
+
+/* internal routine to check the consistency of the allocated and/or free memory arena.
+ * this is used by the user functions below (psMem{Set,Get}Deallocator, 
+ * N.b. If the block wasn't allocated by psAlloc, it will appear corrupted
+ */
+static bool isBadMemBlock(FILE *output, const psMemBlock *memBlock, const char *file, unsigned int lineno, const char *func)
+{
+    // n.b. since this is called by psMemCheckCorruption while the memblock
+    // list is mutex locked, we shouldn't call such things as
+    // p_psAlloc/p_psFree here.
+
+    bool bad = false;
+    bool blockPrinted = false;
+
+    if (memBlock == NULL) {
+        fprintf(output, _("NULL memory block.\n"
+                          "Caught in %s at (%s:%d.).\n\n"), func, file, lineno);
+        // return now as we can't do anything else
+        return true;
+    }
+
+    #if 0
+    // Currently psAlloc()/psRealloc() will blindly create memBlock's with a
+    // size of 0.  This test is in here to check if this is really
+    // happening/being use as a feature in the wild.
+    if (memBlock->userMemorySize < 1) {
+        psMemBlockPrint(output, memBlock);
+        blockPrinted = true;
+        fprintf(output, _("\n\tMemory block has a size of less than 1.\n"));
+        bad = true;
+    }
+    #endif
+
+    if (memBlock->refCounter < 1) {
+        // using an unreferenced block of memory, are you?
+        psMemBlockPrint(output, memBlock);
+        blockPrinted = true;
+        fprintf(output, _("\n\tMemory block was freed but still being used.\n"));
+        bad = true;
+    }
+
+    if (memBlock->startblock != P_PS_MEMMAGIC || memBlock->endblock != P_PS_MEMMAGIC) {
+        if (!blockPrinted) {
+            psMemBlockPrint(output, memBlock);
+            blockPrinted = true;
+        }
+        fprintf(output, _("\n\tMemory block is corrupted; buffer underflow detected.\n"));
+        bad = true;
+    }
+
+    if (*(psU32 *)((char *)(memBlock + 1) + memBlock->userMemorySize) != P_PS_MEMMAGIC) {
+        if (!blockPrinted) {
+            psMemBlockPrint(output, memBlock);
+            blockPrinted = true;
+        }
+        fprintf(output, _("\n\tMemory block is corrupted; buffer overflow detected.\n"));
+        bad = true;
+    }
+
+    //  XXX ->nextBlock, & -> prevousBlock really should not be looked at by
+    //  this function as they may be changed out from underneath us by new
+    //  memory allocation.  However, the memBlock itself shouldn't go away (end
+    //  users responsiblity) so all we're really risking is a garbage value.
+
+    //  XXX EAM : is this the error I'm catching in multithreaded processing?
+    if (memBlock == memBlock->nextBlock) {
+        if (!blockPrinted) {
+            psMemBlockPrint(output, memBlock);
+            blockPrinted = true;
+        }
+        fprintf(output, _("\n\tMemory block's ->nextBlock pointer refers to itself.\n"));
+        bad = true;
+    }
+
+    if (memBlock == memBlock->previousBlock) {
+        if (!blockPrinted) {
+            psMemBlockPrint(output, memBlock);
+            blockPrinted = true;
+        }
+        fprintf(output, _("\n\tMemory block's ->previousBlock pointer refers to itself.\n"));
+        bad = true;
+    }
+
+    if (bad) {
+        fprintf(output, _("\tCaught in %s at (%s:%d).\n\n"), func, file, lineno);
+    }
+
+    return bad;
+}
+
+void *p_psRealloc(const char *file,
+                  unsigned int lineno,
+                  const char *func,
+                  void *ptr,
+                  size_t size)
+{
+    if (ptr == NULL) {
+        return p_psAlloc(file, lineno, func, size);
+    }
+
+    psMemBlock *memBlock = ((psMemBlock *)ptr) - 1;
+
+    HANDLE_BAD_BLOCK(memBlock, file, lineno, func);
+
+    if (size == memBlock->userMemorySize) {
+        // Nothing to do
+        return ptr;
+    }
+
+    // Reallocate the memory
+
+    // we need to lock this whole section because we need to be able to adjust
+    // lastMemBlockAllocated if needed (ie, this IS lastMemBlockAllocated)
+    // this lock is frequently called in a given program
+    MUTEX_LOCK(&memBlockListMutex);
+    
+    psMemBlock *nextBlock = memBlock->nextBlock;
+    psMemBlock *previousBlock = memBlock->previousBlock;
+
+    // Is this the last block we allocated?  If it is, we need to keep track of
+    // this fact and update lastMemBlockAllocated *after* the realloc or
+    // lastMemBlockAllocated will be left with a bogus value
+    bool isBlockLast = (memBlock == lastMemBlockAllocated);
+
+    memBlock = (psMemBlock *)realloc(memBlock, sizeof(psMemBlock) + size + sizeof(void *));
+    if (memBlock == NULL) {
+        memBlock = memExhaustedCallback(size);
+        if (memBlock == NULL) {
+            psMemBlockPrint(stderr,  ((psMemBlock *)ptr) - 1);
+            fprintf(stderr, "Problem reallocating block\n");
+            PS_MEM_ABORT(__func__, "Failed to reallocate to %zd bytes at %s (%s:%d)", size, func, file, lineno);
+        }
+    }
+
+    memBlock->userMemorySize = size;
+    *(psU32 *)((char *)(memBlock + 1) + size) = P_PS_MEMMAGIC;
+
+    // update the references on the list:
+
+    // is we are modifying the last mem block, we need to update lastMemBlockAllocated
+    if (isBlockLast) {
+        lastMemBlockAllocated = memBlock;
+    }
+
+    // the block location may have changed, so fix the linked list addresses.
+    if (nextBlock != NULL) {
+        nextBlock->previousBlock = memBlock;
+    }
+    if (previousBlock != NULL) {
+        previousBlock->nextBlock = memBlock;
+    }
+
+    // Did the user ask to be informed about this allocation?
+    if (memBlock->id == p_psMemAllocID) {
+        p_psMemAllocID += memAllocCallback(memBlock);
+    }
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    return memBlock + 1;                    // usr memory
+}
+
+/*
+ * Check for memory leaks.
+ */
+int p_psMemCheckLeaks(const char *file,
+                      unsigned int lineno,
+                      const char *func,
+                      psMemId id0,
+                      psMemBlock ***array,
+                      FILE * fd,
+                      bool persistence)
+{
+    psS32 nleak = 0;
+    psS32 j = 0;
+    psMemBlock *topBlock = lastMemBlockAllocated;
+
+    // make sure that the memblock list is free of corruption before we crawl
+    // the list
+    p_psMemCheckCorruption(file, lineno, func, fd, true);
+
+    // this lock is rarely called in a given program
+    MUTEX_LOCK(&memBlockListMutex);
+
+    // if topBlock is NULL there's nothing to do
+    if (!topBlock) {
+        MUTEX_UNLOCK(&memBlockListMutex);
+        return 0;
+    }
+
+    // find the very first memblock
+    psMemBlock *memBlock = NULL;
+    for (memBlock = topBlock; memBlock->nextBlock != NULL; memBlock = memBlock->nextBlock) { }
+
+    // iterate through the block list starting with the oldest block
+    for (; memBlock != NULL; memBlock = memBlock->previousBlock) {
+        if ( (memBlock->refCounter > 0) &&
+                ( (persistence) || (!persistence && !memBlock->persistent) ) &&
+                (memBlock->id >= id0)) {
+
+            nleak++;
+
+            if (fd != NULL) {
+                if (nleak == 1) {
+                    fprintf(fd, "# func at (file:line)  ID: X  Ref: X\n");
+                }
+
+                fprintf(fd, "%s at (%s:%d)  ID: %lu  Ref: %lu", memBlock->func, memBlock->file, (int)memBlock->lineno, (unsigned long)memBlock->id, memBlock->refCounter);
+                #if defined(PS_MEM_BACKTRACE) && defined(HAVE_BACKTRACE)
+
+                size_t size = memBlock->backtraceSize;
+                char **strings = backtrace_symbols((void *const *)memBlock->backtrace, size);
+
+                fprintf(fd, "  Alloc Call Depth: %zd\n", size);
+
+                for (int i = 0; i < size; i++) {
+                    // always ident
+                    int ident = 4;  // initial indent
+                    ident += 2 * i; // nesting depth
+                    fprintf(fd, "%*s", ident, "");
+
+                    // if the caller was an anon function then strchr won't
+                    // find a '(' in the string and will return NULL
+                    char *caller = caller = strchr(strings[i], '(');
+                    if (caller) {
+                        // skip over the '('
+                        caller++;
+                        // find the end of the symbol name
+                        size_t callerLength = abs(strchr(caller, '+') - caller);
+                        // print just the symbol name
+                        for (int i = 0; i < callerLength; i++) {
+                            fputc(caller[i],fd);
+                        }
+                        fprintf(fd, "\n");
+                    } else {
+                        fprintf(fd, "(unknown)\n");
+                    }
+                }
+
+                free (strings);
+                #else // ifdef HAVE_BACKTRACE
+                // \n after "Memory Block ID"
+                fprintf(fd, "\n");
+                #endif // ifdef HAVE_BACKTRACE
+
+            }
+        }
+    }
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    if (nleak == 0 || array == NULL) {
+        return nleak;
+    }
+
+    *array = psAlloc(nleak * sizeof(psMemBlock));
+
+    // this lock is rarely called in a given program
+    MUTEX_LOCK(&memBlockListMutex);
+
+    for (psMemBlock *memBlock = topBlock; memBlock != NULL; memBlock = memBlock ->nextBlock) {
+        if ( (memBlock->refCounter > 0) &&
+                ( (persistence) || (!persistence && !memBlock->persistent) ) &&
+                (memBlock->id >= id0)) {
+
+            (*array)[j++] = memBlock;
+            if (j == nleak) {              // found them all
+                break;
+            }
+        }
+    }
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    return nleak;
+}
+
+
+/*
+ * Reference counting APIs
+ */
+psReferenceCount p_psMemGetRefCounter(const char *file,
+                                      unsigned int lineno,
+                                      const char *func,
+                                      void *ptr)
+{
+    if (ptr == NULL) {
+        return 0;
+    }
+
+    psMemBlock *memBlock = ((psMemBlock *) ptr) - 1;
+
+    HANDLE_BAD_BLOCK(memBlock, file, lineno, func);
+
+    return memBlock->refCounter;
+}
+
+
+// increment and return refCounter
+void *p_psMemIncrRefCounter(const char *file,
+                            unsigned int lineno,
+                            const char *func,
+                            void *ptr)
+{
+    if (ptr == NULL) {
+        return ptr;
+    }
+
+    psMemBlock* memBlock = ((psMemBlock *) ptr) - 1;
+
+    HANDLE_BAD_BLOCK(memBlock, file, lineno, func);
+
+    memBlock->refCounter++;
+
+    // Did the user ask to be informed about this allocation?
+    // this lock is frequently called in a given program
+    // this lock is probably not needed: if someone changes the callback ID in a different thread,
+    // do we really care about really rarely getting this wrong?
+    // MUTEX_LOCK(&memBlockListMutex);
+    if (memBlock->id == p_psMemAllocID) {
+	// XXX this is seriously bogus: why are we changing this value??
+        // p_psMemAllocID += memAllocCallback(memBlock);
+        memAllocCallback(memBlock);
+    }
+    // MUTEX_UNLOCK(&memBlockListMutex);
+
+    return ptr;
+}
+
+
+#if 0
+void * p_psMemSetRefCounter(void * vptr,
+                            psReferenceCount count,
+                            const char *file,
+                            psS32 lineno)
+{
+    psMemBlock* ptr;
+
+    if (vptr == NULL) {
+        return vptr;
+    }
+
+    if (count < 0) {
+        count = 0;
+    }
+
+    ptr = ((psMemBlock* ) vptr) - 1;
+
+    if (isBadMemBlock(ptr, __func__)) {
+        (void)p_psMemDecrRefCounter(vptr, filename, lineno);
+        memProblemCallback(ptr, file, lineno);
+    }
+
+    ptr->refCounter = count;
+
+    if (count < 1) {
+        vptr = p_psMemDecrRefCounter(vptr,file,lineno);
+    }
+
+    return vptr;
+}
+#endif
+
+
+// decrement and return refCounter
+void *p_psMemDecrRefCounter(const char *file,
+                            unsigned int lineno,
+                            const char *func,
+                            void * ptr)
+{
+    if (ptr == NULL) {
+        return NULL;
+    }
+
+    psMemBlock *memBlock = ((psMemBlock *) ptr) - 1;
+
+    HANDLE_BAD_BLOCK(memBlock, file, lineno, func);
+
+    // if we have multiple references, just decrement the count and return.
+    if (memBlock->refCounter > 1) {
+        memBlock->refCounter--;
+
+        // Did the user ask to be informed about this deallocation?
+        // MUTEX_LOCK(&memBlockListMutex);
+        if (memBlock->id == p_psMemFreeID) {
+	    // XXX why modify this?  this seems bogus
+            // p_psMemFreeID += memFreeCallback(memBlock);
+            memFreeCallback(memBlock);
+        }
+        // MUTEX_UNLOCK(&memBlockListMutex);
+        return ptr;
+    }
+
+    // we can't invoke freeFunc() while we're holding memBlockListMutex as it
+    // may invoke psFree() itself
+    if (memBlock->freeFunc != NULL) {
+        memBlock->freeFunc(ptr);
+    }
+
+    // this lock is frequently set in a given program
+    MUTEX_LOCK(&memBlockListMutex);
+
+    // Did the user ask to be informed about this deallocation?
+    if (memBlock->id == p_psMemFreeID) {
+        // p_psMemFreeID += memFreeCallback(ptr);
+        memFreeCallback(ptr);
+    }
+
+    psMemBlock *nextBlock = memBlock->nextBlock;
+    psMemBlock *previousBlock = memBlock->previousBlock;
+
+    // cut the memBlock out of the memBlock list
+    if (nextBlock != NULL) {
+        nextBlock->previousBlock = previousBlock;
+    }
+    if (previousBlock != NULL) {
+        previousBlock->nextBlock = nextBlock;
+    }
+    if (lastMemBlockAllocated == memBlock) {
+        lastMemBlockAllocated = nextBlock;
+    }
+
+    // NULL out the refs so no one can get confused
+    memBlock->nextBlock = NULL;
+    memBlock->previousBlock = NULL;
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    // invoke free only after we've released the block list lock as free()
+    // could take awhile.  We can get away with this as at this point the
+    // memBlock is no longer part of the mem block list.
+    #if defined(PS_MEM_BACKTRACE) && defined(HAVE_BACKTRACE)
+
+    free(memBlock->backtrace);
+    #endif
+
+    free(memBlock);
+
+    // since we freed it, make sure we return NULL.
+    return NULL;
+}
+
+
+/**** user functions to manage memory references ****/
+void p_psMemSetDeallocator(const char *file,
+                           unsigned int lineno,
+                           const char *func,
+                           void *ptr,
+                           psFreeFunc freeFunc)
+{
+    if (ptr == NULL) {
+        return;
+    }
+
+    psMemBlock* memBlock = ((psMemBlock *)ptr) - 1;
+
+    HANDLE_BAD_BLOCK(memBlock, file, lineno, func);
+
+    memBlock->freeFunc = freeFunc;
+}
+
+
+psFreeFunc p_psMemGetDeallocator(const char *file,
+                                 unsigned int lineno,
+                                 const char *func,
+                                 void *ptr)
+{
+    if (ptr == NULL) {
+        return NULL;
+    }
+
+    psMemBlock* memBlock = ((psMemBlock *)ptr) - 1;
+
+    HANDLE_BAD_BLOCK(memBlock, file, lineno, func);
+
+    return memBlock->freeFunc;
+}
+
+
+bool p_psMemGetPersistent(const char *file,
+                          unsigned int lineno,
+                          const char *func,
+                          void *ptr)
+{
+    if (ptr == NULL) {
+        return NULL;
+    }
+
+    psMemBlock* memBlock = ((psMemBlock *) ptr) - 1;
+
+    HANDLE_BAD_BLOCK(memBlock, file, lineno, func);
+
+    return memBlock->persistent;
+}
+
+
+void p_psMemSetPersistent(const char *file,
+                          unsigned int lineno,
+                          const char *func,
+                          void *ptr,
+                          bool value)
+{
+    if (ptr == NULL) {
+        return;
+    }
+
+    psMemBlock* memBlock = ((psMemBlock *) ptr) - 1;
+
+    HANDLE_BAD_BLOCK(memBlock, file, lineno, func);
+
+    memBlock->persistent = value;
+}
+
+int p_psMemCheckCorruption(const char *file,
+                           unsigned int lineno,
+                           const char *func,
+                           FILE *output,
+                           bool abort_on_error)
+{
+    // get exclusive access to the memBlock list to avoid it changing on us while we check it.
+
+    // this lock is rarely called in a given program
+    MUTEX_LOCK(&memBlockListMutex);
+
+    psS32 nbad = 0;               // number of bad blocks
+    for (psMemBlock *memBlock = lastMemBlockAllocated; memBlock != NULL; memBlock = memBlock->nextBlock) {
+        if (isBadMemBlock(output, memBlock, __FILE__, __LINE__, __func__)) {
+            nbad++;
+
+            if (abort_on_error) {
+                // release the lock on the memblock list
+                MUTEX_UNLOCK(&memBlockListMutex);
+                PS_MEM_ABORT(__func__, "Detected memory corruption");
+            }
+        }
+    }
+
+    // release the lock on the memblock list
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    return nbad;
+}
+
+bool p_psMemIsAlloced(const char *file,
+                      unsigned int lineno,
+                      const char *func,
+                      const void *ptr)
+{
+    // if ptr is a psAlloc()'d memory, find the actual address of the memBlock
+    psMemBlock *addr = ((psMemBlock *)ptr) - 1;
+
+    // get exclusive access to the memBlock list to avoid it changing on us
+    // this lock is only occasionally called in a given program
+    MUTEX_LOCK(&memBlockListMutex);
+
+    // loop through the linked list of memBlocks looking for a matching pointer
+    for (psMemBlock *memBlock = lastMemBlockAllocated; memBlock != NULL; memBlock = memBlock->nextBlock) {
+        if (memBlock == addr) {
+            // we found the memBlock
+            HANDLE_BAD_BLOCK(memBlock, file, lineno, func);
+
+            MUTEX_UNLOCK(&memBlockListMutex);
+            return true;
+        }
+    }
+
+    // release the lock on the memblock list
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    return false;
+}
+
+
+/**** memory usage statistics functions ****/
+
+/*
+ * Return the total amount of memory owned by psLib; if non-NULL also provide a
+ * breakdown into recyclable, allocated, and allocated-and-persistent
+ *
+ * It would be simple enough to fix this code to return an array of structs to
+ * describe the insides of the allocator rather than the printf used here.
+ */
+size_t psMemStats(const bool print, // print details as they're found?
+                  size_t *allocated, // memory that's currently allocated (but not persistent)
+                  size_t *persistent) // persistent memory that's currently allocated
+{
+    const size_t overhead = sizeof(psMemBlock) + sizeof(void *); // overhead on each allocation
+
+    if (print) {
+        printf("Type       %6s  %10s %8s\n", "size", "nByte", "nBlock");
+    }
+
+    // this lock is rarely called in a given program
+    MUTEX_LOCK(&memBlockListMutex);
+    /*
+     * All memory that's currently allocated, whether persistent or not
+     */
+    size_t allocated_s, persistent_s;
+    if (allocated == NULL) {
+        allocated = &allocated_s;
+    }
+    if (persistent == NULL) {
+        persistent = &persistent_s;
+    }
+
+    size_t alloc = 0, persist = 0;
+    size_t nalloc = 0, npersist = 0;
+    for (psMemBlock* ptr = lastMemBlockAllocated; ptr != NULL; ptr = ptr->nextBlock) {
+        assert (ptr->refCounter > 0);
+
+        if (ptr->persistent) {
+            npersist++;
+            persist += ptr->userMemorySize + overhead;
+        } else {
+            nalloc++;
+            alloc += ptr->userMemorySize + overhead;
+        }
+    }
+    *allocated = alloc;
+    *persistent = persist;
+
+    if (print) {
+        printf("Allocated  %6s  %10zd %8zd\n", "", alloc, nalloc);
+        printf("Persistent %6s  %10zd %8zd\n", "", persist, npersist);
+    }
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    return *allocated + *persistent;
+}
+
+int psMemBlockPrint(FILE *output, const psMemBlock *memBlock)
+{
+    return fprintf(output,
+                   "Memory Block ID: %lu @ %p\n"
+                   "\tPrevious Block: %p Next Block: %p\n"
+                   "\tFree function: %p\n"
+                   "\tSize: %zd Reference count: %lu Persistent: %s\n"
+                   "\tPosts: %x %x %x\n"
+                   "\tAllocated in %s at (%s:%d)\n"
+                   "\t\tby Thread ID %lu\n",
+                   memBlock->id, memBlock,
+                   memBlock->previousBlock, memBlock->nextBlock,
+                   memBlock->freeFunc,
+                   memBlock->userMemorySize, memBlock->refCounter, (memBlock->persistent ? "Yes" : "No"),
+                   memBlock->startblock, memBlock->endblock,
+                   *(psU32 *)((char *) (memBlock + 1) + memBlock->userMemorySize),
+                   memBlock->func, memBlock->file, memBlock->lineno, (unsigned long)memBlock->tid);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psMemory.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psMemory.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psMemory.h	(revision 22158)
@@ -0,0 +1,668 @@
+/* @file  psMemory.h
+ * @brief Contains the definitions for the memory management system
+ *
+ *  @brief Contains the definitions for the memory management system
+ *
+ *  This is the generic memory management system put inbetween the user's high
+ *  level code and the OS-level memory allocation routines.  This system adds
+ *  such features as callback routines for memory error events, tracing
+ *  capabilities, and reference counting.
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Robert Lupton, Princeton University
+ *  @author Joshua Hoblitt, University of Hawaii
+ *
+ *  @ingroup MemoryManagement
+ *
+ *  @version $Revision: 1.73 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-09-28 00:36:08 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_MEMORY_H
+#define PS_MEMORY_H
+
+/// @addtogroup SysUtils System Utilities
+/// @{
+
+#include <stdio.h>                      // needed for FILE
+#include <pthread.h>                    // mutexes
+#include <stdint.h>                     // for uint32_t
+#include <stdbool.h>
+
+/** @addtogroup MemoryManagement
+ *  @{
+ */
+
+/// typedef for memory identification numbers.  Guaranteed to be some variety of integer.
+typedef unsigned long psMemId;
+
+/// typedef for a memory block's reference count. Guaranteed to be some variety of integer.
+typedef unsigned long psReferenceCount;
+
+/// typedef for deallocator.
+typedef void (*psFreeFunc) (void *ptr);
+
+/** Book-keeping data for storage allocator.
+ *  N.b. sizeof(psMemBlock) must be chosen such that if ptr is a pointer
+ *  returned by malloc, then ((char *)ptr + sizeof(psMemBlock)) is properly
+ *  aligned for all storage types.
+ */
+
+// The memory overhead of a psMemBlock + the trailing post can be checked in
+// gdb with the following command:
+//      p sizeof(psMemBlock) + sizeof(void*)
+typedef struct psMemBlock
+{
+    const uint32_t startblock;          ///< initialised to p_psMEMMAGIC
+    struct psMemBlock *previousBlock;   ///< previous block in allocation list
+    struct psMemBlock *nextBlock;       ///< next block allocation list
+    psFreeFunc freeFunc;                ///< deallocator.  If NULL, use generic deallocation.
+    size_t userMemorySize;              ///< the size of the user-portion of the memory block
+    const psMemId id;                   ///< a unique ID for this allocation
+    const pthread_t tid;                ///< set from pthread_self();
+    const char *file;                   ///< set from __FILE__ in e.g. p_psAlloc
+    const unsigned int lineno;          ///< set from __LINE__ in e.g. p_psAlloc
+    const char *func;                   ///< set from __func__
+
+#if defined(PS_MEM_BACKTRACE) && defined(HAVE_BACKTRACE)
+    const void **backtrace;             ///< set from backtrace()
+    const size_t backtraceSize;         ///< set from bracktrace()
+#endif // defined(PS_MEM_BACKTRACE) && defined(HAVE_BACKTRACE)
+
+    psReferenceCount refCounter;        ///< how many times pointer is referenced
+    bool persistent;                    ///< marks if this non-user persistent data like error stack, etc.
+    const uint32_t endblock;            ///< initialised to p_psMEMMAGIC
+}
+psMemBlock;
+
+/** prototype of a basic callback used by memory functions
+ *
+ *  @see psMemAllocCallbackSet
+ */
+typedef psMemId(*psMemAllocCallback) (
+    const psMemBlock *ptr              ///< the psMemBlock just allocated
+);
+
+/** prototype of memory free callback used by memory functions
+ *
+ *  @see psMemFreeCallbackSet
+ */
+typedef psMemId(*psMemFreeCallback) (
+    const psMemBlock *ptr              ///< the psMemBlock being freed
+);
+
+/** prototype of a callback used in error conditions
+ *
+ *  This callback should not try to call psAlloc or psFree.
+ *
+ *  @see psMemProblemCallbackSet
+ */
+typedef void (*psMemProblemCallback) (
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psMemBlock *ptr                     ///< the pointer to the problematic memory block.
+);
+
+/** prototype of a callback function used when memory runs out
+ *
+ *  @return void * pointer to requested buffer of the size size_t, or NULL if
+ *  memory could not be found.
+ *
+ *  @see psMemExhaustedCallbackSet
+ */
+typedef void *(*psMemExhaustedCallback) (
+    size_t size                         ///< the size of buffer required
+);
+
+/** Memory allocation.  This operates much like malloc(), but is guaranteed to
+ * return a non-NULL value.
+ *
+ *  @return void * pointer to the allocated buffer. This will not be NULL.
+ *  @see psFree
+ */
+#ifdef DOXYGEN
+void *psAlloc(
+    size_t size                        ///< Size required
+);
+#else // ifdef DOXYGEN
+void *p_psAlloc(
+    const char *file,                  ///< File of caller
+    unsigned int lineno,               ///< Line number of caller
+    const char *func,                  ///< Function name of caller
+    size_t size                        ///< Size required
+#ifdef __GNUC__
+) __attribute__((malloc));
+# else // ifdef __GNUC__
+);
+#endif // ifdef __GNUC__
+#ifndef SWIG
+#define psAlloc(size) \
+p_psAlloc(__FILE__, __LINE__, __func__, size)
+#endif // ifndef SWIG
+#endif // ifdef DOXYGEN
+
+
+/** Set the deallocator routine
+ *
+ *  A deallocator routine can optionally be assigned to a memory block to
+ *  ensure that associated memory blocks also get freed, e.g., memory buffers
+ *  referenced within a struct.
+ *
+ */
+#ifdef DOXYGEN
+void psMemSetDeallocator(
+    void *ptr,                         ///< the memory block to operate on
+    psFreeFunc freeFunc                ///< the function to be executed at deallocation
+);
+#else // ifdef DOXYGEN
+void p_psMemSetDeallocator(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    void *ptr,                          ///< the memory block to operate on
+    psFreeFunc freeFunc                 ///< the function to be executed at deallocation
+);
+#ifndef SWIG
+#define psMemSetDeallocator(ptr, freeFunc) \
+      p_psMemSetDeallocator(__FILE__, __LINE__, __func__, ptr, freeFunc)
+#endif // ifndef SWIG
+#endif // ifdef DOXYGEN
+
+
+/** Get the deallocator routine
+ *
+ *  This function returns the deallocator for a memory block.  A deallocator
+ *  routine can optionally be assigned to a memory block to ensure that
+ *  associated memory blocks also get freed, e.g., memory buffers referenced
+ *  within a struct.
+ *
+ *  @return psFreeFunc    the routine to be called at deallocation.
+ */
+#ifdef DOXYGEN
+psFreeFunc psMemGetDeallocator(
+    void *ptr                           ///< the memory block
+);
+#else // ifdef DOXYGEN
+psFreeFunc p_psMemGetDeallocator(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    void *ptr                           ///< the memory block
+);
+#ifndef SWIG
+#define psMemGetDeallocator(ptr) \
+      p_psMemGetDeallocator(__FILE__, __LINE__, __func__, ptr)
+#endif // ifndef SWIG
+#endif // ifdef DOXYGEN
+
+
+/** Activate or Deactivate thread safety and mutex locking in the memory
+ * management.
+ *
+ *  psMemThreadSafety shall turn on thread safety in the memory management
+ *  functions if safe is true, and deactivate all mutex locking in the memory
+ *  management functions if safe is false.  The function shall return the
+ *  previous value of the thread safety.  Note that the default behaviour of
+ *  the library shall be for the locking to be performed.
+ *
+ *  @return bool:       The previous value of the thread safety.
+ */
+bool psMemSetThreadSafety(
+    bool safe                          ///< boolean for turning on/off thread safety
+);
+
+
+/** Get the current state of thread safety and mutex locking in the memory
+ * management.
+ *
+ * psMemGetThreadSafety shall return the current state of thread safety in the
+ * memory management system.
+ *
+ *  @return bool:       The current state of thread safety.
+ */
+bool psMemGetThreadSafety(void);
+
+
+/** Set the memory as persistent so that it is ignored when detecting memory
+ * leaks.
+ *
+ *  Used to mark a memory block as persistent data within the library,
+ *  i.e., non user-level data used to hold psLib's state or cache data.  Such
+ *  examples of this class of memory is psTrace's trace-levels and dynamic
+ *  error codes.
+ *
+ *  Memory marked as persistent is excluded from memory leak checks.
+ *
+ */
+#ifdef DOXYGEN
+void psMemSetPersistent(
+    void *ptr,                          ///< the memory block to operate on
+    bool value,                         ///< true if memory is persistent, otherwise false
+);
+#else // ifdef DOXYGEN
+void p_psMemSetPersistent(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    void *ptr,                          ///< the memory block to operate on
+    bool value                          ///< true if memory is persistent, otherwise false
+);
+#ifndef SWIG
+#define psMemSetPersistent(ptr, value) \
+      p_psMemSetPersistent(__FILE__, __LINE__, __func__, ptr, value)
+#endif // idndef SWIG
+#endif // ifdef DOXYGEN
+
+
+/** Set whether allocated memory is persistent
+ *
+ *  Set whether allocated memory is persistent. The defeault is false.
+ *
+ *  @return bool:       The previous value of whether all allocated memory is
+ *  persistent
+ */
+bool p_psMemAllocatePersistent(bool is_persistent); ///< Should all memory allocated be persistent?
+
+
+/** Get the memory's persistent flag.
+ *
+ *  Checks if a memory block has been marked as persistent by
+ *  p_psMemSetPresistent.
+ *
+ *  Memory marked as persistent is excluded from memory leak checks.
+ *
+ *  @return bool    true if memory is marked persistent, otherwise false.
+ */
+#ifdef DOXYGEN
+bool psMemGetPersistent(
+    void *ptr,                          ///< the memory block to check.
+);
+#else // ifdef DOXYGEN
+bool p_psMemGetPersistent(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    void *ptr                           ///< the memory block to check.
+);
+#ifndef SWIG
+#define psMemGetPersistent(ptr) \
+      p_psMemGetPersistent(__FILE__, __LINE__, __func__, ptr)
+#endif // ifndef SWIG
+#endif // ifdef DOXYGEN
+
+
+/** Memory re-allocation.  This operates much like realloc(), but is guaranteed
+ * to return a non-NULL value.
+ *
+ *  @return void * pointer to resized buffer. This will not be NULL.
+ *  @see psAlloc, psFree
+ */
+#ifdef DOXYGEN
+void *psRealloc(
+    void *ptr,                          ///< Pointer to re-allocate
+    size_t size                         ///< Size required
+);
+#else // ifdef DOXYGEN
+void *p_psRealloc(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    void *ptr,                          ///< Pointer to re-allocate
+    size_t size                         ///< Size required
+#ifdef __GNUC__
+) __attribute__((malloc));
+# else // ifdef __GNUC__
+);
+#endif // ifdef __GNUC__
+#ifndef SWIG
+#define psRealloc(ptr, size) \
+      p_psRealloc(__FILE__, __LINE__, __func__, ptr, size)
+#endif // ifndef SWIG
+#endif // ifdef DOXYGEN
+
+
+/** Free memory.  This operates much like free().
+ *
+ *  @see psAlloc, psRealloc
+ */
+#ifdef DOXYGEN
+void psFree(
+    void *ptr                           ///< Pointer to free, if NULL, function returns immediately.
+);
+#else // ifdef DOXYGEN
+#ifndef SWIG
+#define psFree(ptr) \
+        psMemDecrRefCounter(ptr)
+#endif // ifndef SWIG
+#endif // ifdef DOXYGEN
+
+
+/** Check for memory leaks.  This scans for allocated memory buffers not freed
+ * with an ID not less than id0.  This is used to check for memory leaks by: -#
+ * before a block of code to be checked, store the current ID count via
+ * psGetMemId -# after the block of code to be checked, call this function
+ * using the ID stored above.  If all memory in the block that was allocated
+ * has been freed, this call should output nothing and return 0.
+ *
+ *  If memory leaks are found, the Memory Problem callback will be called as
+ *  well.
+ *
+ *  @return int  number of memory blocks found as 'leaks', i.e., the number of
+ *  currently allocated memory blocks above id0 that have not been freed.  @see
+ *  psAlloc, psFree, psgetMemId, psMemProblemCallbackSet
+ */
+#ifdef DOXYGEN
+int psMemCheckLeaks(
+    psMemId id0,                       ///< don't list blocks with id < id0
+    psMemBlock ***array,               ///< pointer to array of pointers to leaked blocks, or NULL
+    FILE * fd,                         ///< print list of leaks to fd (or NULL)
+    bool persistence                   ///< make check across all object even persistent ones
+);
+#else // ifdef DOXYGEN
+int p_psMemCheckLeaks(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psMemId id0,                        ///< don't list blocks with id < id0
+    psMemBlock ***array,                ///< pointer to array of pointers to leaked blocks, or NULL
+    FILE * fd,                          ///< print list of leaks to fd (or NULL)
+    bool persistence                    ///< make check across all object even persistent ones
+);
+#ifndef SWIG
+#define psMemCheckLeaks(id0, array, fd, persistence) \
+      p_psMemCheckLeaks(__FILE__, __LINE__, __func__, id0, array, fd, persistence)
+#endif // ifndef SWIG
+#endif // ifdef DOXYGEN
+
+
+/** Check for memory corruption.  Scans all currently allocated memory buffers
+ * and checks for corruptions, i.e., invalid markers that signify a buffer
+ * under/overflow.
+ *
+ *  @return int
+ *
+ */
+#ifdef DOXYGEN
+int psMemCheckCorruption(
+    FILE *output,                       ///< FILE to write corrupted blocks too
+    bool abort_on_error                 ///< Abort on detecting corruption?
+);
+#else // ifdef DOXYGEN
+int p_psMemCheckCorruption(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    FILE *output,                       ///< FILE to write corrupted blocks too
+    bool abort_on_error                 ///< Abort on detecting corruption?
+);
+#ifndef SWIG
+#define psMemCheckCorruption(output, abort_on_error) \
+      p_psMemCheckCorruption(__FILE__, __LINE__, __func__, output, abort_on_error)
+#endif // ifndef SWIG
+#endif // ifdef DOXYGEN
+
+/** Checks to see if a pointer is to a region of memory that was allocated by psAlloc().
+ *  @return bool
+ *
+ */
+#ifdef DOXYGEN
+bool psMemIsAlloced(
+    const void *ptr                           ///< pointer to memory
+);
+#else // ifdef DOXYGEN
+bool p_psMemIsAlloced(
+    const char *file,
+    unsigned int lineno,
+    const char *func,
+    const void *ptr
+);
+#ifndef SWIG
+#define psMemIsAlloced(ptr) \
+      p_psMemIsAlloced(__FILE__, __LINE__, __func__, ptr)
+#endif // ifndef SWIG
+#endif // ifdef DOXYGEN
+
+
+/** Return reference counter
+ *
+ *  @return psReferenceCount
+ *
+ */
+#ifdef DOXYGEN
+psReferenceCount psMemGetRefCounter(
+    void *ptr                     ///< Pointer to get refCounter for
+);
+
+#else // ifdef DOXYGEN
+psReferenceCount p_psMemGetRefCounter(
+    const char *file,                   ///< File of call
+    unsigned int lineno,                ///< Line number of call
+    const char *func,                   ///< Function name of caller
+    void *ptr                           ///< Pointer to get refCounter for
+);
+#ifndef SWIG
+#define psMemGetRefCounter(ptr) \
+      p_psMemGetRefCounter(__FILE__, __LINE__, __func__, ptr)
+#endif // !SWIG
+#endif // !DOXYGEN
+
+
+/** Increment reference counter and return the pointer
+ *
+ *  @return void *
+ *
+ */
+#ifdef DOXYGEN
+void *psMemIncrRefCounter(
+    void *ptr                           ///< Pointer to increment refCounter, and return
+);
+#else // ifdef DOXYGEN
+void *p_psMemIncrRefCounter(
+    const char *file,                   ///< File of call
+    unsigned int lineno,                ///< Line number of call
+    const char *func,                   ///< Function name of caller
+    void *ptr                           ///< Pointer to increment refCounter, and return
+);
+#ifndef SWIG
+#define psMemIncrRefCounter(ptr) \
+      p_psMemIncrRefCounter(__FILE__, __LINE__, __func__, ptr)
+#endif // ifndef SWIG
+#endif // ifdef DOXYGEN
+
+
+/** Decrement reference counter and return the pointer
+ *
+ *
+ *  @return void *    the pointer deremented in refCount, or NULL if pointer is
+ *                   fully dereferenced.
+ */
+#ifdef DOXYGEN
+void *psMemDecrRefCounter(
+    void *ptr                           ///< Pointer to decrement refCounter, and return
+);
+#else // DOXYGEN
+void *p_psMemDecrRefCounter(
+    const char *file,                   ///< File of call
+    unsigned int lineno,                ///< Line number of call
+    const char *func,                   ///< Function name of caller
+    void *ptr                           ///< Pointer to decrement refCounter, and return
+);
+#ifndef SWIG
+#define psMemDecrRefCounter(ptr) \
+      p_psMemDecrRefCounter(__FILE__, __LINE__, __func__, ptr)
+#endif // ifndef SWIG
+#endif // ifdef DOXYGEN
+
+
+#if 0 // psMemSetRefCounter
+/** Set reference counter and return the pointer
+ *
+ *  @return void *    the pointer with refCount set, or NULL if pointer is
+ *                   fully dereferenced.
+ */
+#ifdef DOXYGEN
+void * psMemSetRefCounter(
+    void * ptr,                        ///< Pointer to decrement refCounter, and return
+    psReferenceCount count            ///< New reference count
+);
+#else // DOXYGEN
+void * p_psMemSetRefCounter(
+    void * vptr,                        ///< Pointer to decrement refCounter, and return
+    psReferenceCount count,            ///< New reference count
+    const char *file,                  ///< File of call
+    psS32 lineno                       ///< Line number of call
+);
+
+#ifndef SWIG
+#define psMemSetRefCounter(vptr, count) p_psMemSetRefCounter(vptr, count, __FILE__, __LINE__)
+#endif // !SWIG
+
+#endif // !DOXYGEN
+#endif // psMemSetRefCounter
+
+/** Set callback for out-of-memory.
+ *
+ *  If not enough memory is available to satisfy a request by psAlloc or
+ *  psRealloc, these functions attempt to find an alternative solution by
+ *  calling the psMemExhaustedCallback, a function which may be set by the
+ *  programmer in appropriate circumstances, rather than immediately fail.
+ *  The typical use of such a feature may be when a program needs a large
+ *  chunk of memory to do an operation, but the exact size is not critical.
+ *  This feature gives the programmer the opportunity to make a smaller
+ *  request and try again, limiting the size of the operating buffer.
+ *
+ *  @return psMemExhaustedCallback     old psMemExhaustedCallback function
+ */
+psMemExhaustedCallback psMemExhaustedCallbackSet(
+    psMemExhaustedCallback func        ///< Function to run at memory exhaustion
+);
+
+
+/** Set call back for when a particular memory block is allocated
+ *
+ *  A private variable, p_psMemAllocID, can be used to trace the allocation
+ *  and freeing of specific memory blocks. If p_psMemAllocID is set and a
+ *  memory block with that ID is allocated, psMemAllocCallback is called
+ *  just before memory is returned to the calling function.
+ *
+ *  @return psMemAllocCallback      old psMemAllocCallback function
+ */
+psMemAllocCallback psMemAllocCallbackSet(
+    psMemAllocCallback func            ///< Function to run at memory allocation of specific mem block
+);
+
+
+/** Set call back for when a particular memory block is freed
+ *
+ *  A private variable, p_psMemFreeID, can be used to trace the freeing of
+ *  specific memory blocks. If p_psMemFreeID is set and the memory block with
+ *  the ID is about to be freed, the psMemFreeCallback callback is called just
+ *  before the memory block is freed.
+ *
+ *  @return psMemFreeCallback          old psMemFreeCallback function
+ */
+psMemFreeCallback psMemFreeCallbackSet(
+    psMemFreeCallback func             ///< Function to run at memory free of specific mem block
+);
+
+
+/** get next memory ID
+ *
+ *  @return psMemId                 the next memory ID to be used
+ */
+psMemId psMemGetId(void);
+
+
+/** get the last memory ID used
+ *
+ *  @return psMemId                 the last memory ID used
+ */
+psMemId psMemGetLastId(void);
+
+
+/** set p_psMemAllocID to specific id
+ *
+ *  A private variable, p_psMemAllocID, can be used to trace the allocation
+ *  and freeing of specific memory blocks. If p_psMemAllocID is set and a
+ *  memory block with that ID is allocated, psMemAllocCallback is called
+ *  just before memory is returned to the calling function.
+ *
+ *  @return psMemId
+ *
+ *  @see psMemAllocCallbackSet
+ */
+psMemId psMemAllocCallbackSetID(
+    psMemId id                         ///< ID to set
+);
+
+
+/** set p_psMemFreeID to id
+ *
+ *  A private variable, p_psMemFreeID, can be used to trace the freeing of
+ *  specific memory blocks. If p_psMemFreeID is set and the memory block with
+ *  the ID is about to be freed, the psMemFreeCallback callback is called just
+ *  before the memory block is freed.
+ *
+ *  @return psMemId                 the old p_psMemFreeID
+ *
+ *  @see psMemFreeCallbackSet
+ */
+psMemId psMemFreeCallbackSetID(
+    psMemId id                         ///< ID to set
+);
+
+
+/** return statistics on memory usage
+ *
+ * @return the total amount of memory owned by psLib; if non-NULL also provide
+ * a breakdown into allocated and allocated-and-persistent
+ */
+size_t psMemStats(const bool print, ///< print details as they're found?
+                  size_t *allocated, ///< memory that's currently allocated (but not persistent)
+                  size_t *persistent); ///< persistent memory that's currently allocated
+
+/** print detailed information about a psMemBlock
+ *
+ * This function prints a detailed description of a psMemBlock to output.
+ *
+ * @return the return status of fprintf()
+ */
+int psMemBlockPrint(
+    FILE *output,                       ///< FILE to write information too
+    const psMemBlock *memBlock          ///< psMemBlock to be examined
+);
+
+// Ensure this is a psLib pointer
+#define PS_ASSERT_PTR_HEAVY(PTR, RVAL) \
+{ \
+    if (PTR && (!psMemIsAlloced(PTR))) { \
+        psError(PS_ERR_MEMORY_CORRUPTION, false, \
+            "Error: Pointer %p is corrupted or not on the PS memory system.", \
+            PTR); \
+        return RVAL; \
+    } \
+}
+
+/// @} end of SysUtils
+
+#ifndef DOXYGEN
+
+/*
+ * Ensure that any program using malloc/realloc/free will fail to compile
+ */
+#ifndef PS_ALLOW_MALLOC
+#ifdef __GNUC__
+#pragma GCC poison malloc realloc calloc free
+#else // ifdef __GNUC__
+#define malloc(S)       _Pragma("error Use of malloc is not allowed.  Use psAlloc instead.")
+#define realloc(P,S)    _Pragma("error Use of realloc is not allowed.  Use psRealloc instead.")
+#define calloc(S)       _Pragma("error Use of calloc is not allowed.  Use psAlloc instead.")
+#define free(P)         _Pragma("error Use of free is not allowed.  Use psFree instead.")
+#endif // ifdef __GNUC__
+#endif // ifndef PS_ALLOW_MALLOC
+
+#endif // #ifndef DOXYGEN
+#endif // #ifndef PS_MEMORY_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psSlurp.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psSlurp.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psSlurp.c	(revision 22158)
@@ -0,0 +1,88 @@
+/** @file  psSlurp.c
+ *
+ *  @brief Contains functions for slurping files
+ *
+ *  @author Joshua Hoblitt, University of Hawaii
+ *
+ *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-02-27 03:31:56 $
+ *
+ *  Copyright 2006 University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "psType.h"
+#include "psAssert.h"
+#include "psError.h"
+#include "psSlurp.h"
+#include "psMemory.h"
+
+#define SLURP_SIZE 4096
+
+psString psSlurpFD(int fd)
+{
+    psString str = NULL;                // String to which to write
+    size_t size  = 1;                   // bytes allocated -  make sure there is room for '\0'
+    size_t used = 0;                    // bytes actually used
+    ssize_t bytes;                      // Number of bytes read
+    do {
+        // increase the allocated string size
+        size += SLURP_SIZE;
+        str = psRealloc(str, size);
+
+        // read a block from the stream
+        bytes = read(fd, str + used, SLURP_SIZE);
+        if (bytes < 0) {
+            // it's an error
+            psError(PS_ERR_IO, true, "slurp failed on read");
+            psFree(str);
+            return NULL;
+        }
+
+        // Increase the size of the known string
+        used += bytes;
+
+    } while (bytes != 0);
+
+    // append '\0' to the end of the string
+    str[used] = '\0';
+
+    return str;
+}
+
+
+psString psSlurpFile(FILE *stream)
+{
+    return psSlurpFD(fileno(stream));
+}
+
+
+psString psSlurpFilename(const char *filename)
+{
+    PS_ASSERT_PTR_NON_NULL(filename, NULL);
+
+    int fd = open(filename, O_RDONLY);
+    if (fd < 0) {
+        psError(PS_ERR_IO, true, "Failed to open specified file, %s\n", filename);
+        return NULL;
+    }
+
+    psString text = psSlurpFD(fd);
+
+    if (close(fd) != 0) {
+        psError(PS_ERR_IO, true, "Failed to close specified file, %s\n", filename);
+        psFree(text);
+        return NULL;
+    }
+
+    return text;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psSlurp.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psSlurp.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psSlurp.h	(revision 22158)
@@ -0,0 +1,34 @@
+/* @file  psSlurp.h
+ * @brief read complete files into strings
+ *
+ * @author Joshua Hoblitt, University of Hawaii
+ *
+ * @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-10-29 21:30:03 $
+ */
+
+#ifndef PS_SLURP_H
+#define PS_SLURP_H
+
+#include <psString.h>
+
+/// @addtogroup FileIO Input/Output
+/// @{
+
+// Read ("slurp") a file (specified by file descriptor)
+// and return a string containing the entire file.
+psString psSlurpFD(int fd               // File descriptor to read
+                  );
+
+// Read ("slurp") a file (specified by file stream)
+// and return a string containing the entire file.
+psString psSlurpFile(FILE *stream       // File stream to read
+                    );
+
+// Read ("slurp") a file (specified by filename)
+// and return a string containing the entire file.
+psString psSlurpFilename(const char *filename // Filename
+                    );
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psString.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psString.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psString.c	(revision 22158)
@@ -0,0 +1,464 @@
+
+/** @file  psString.c
+ *
+ * -*- mode: C; c-basic-indent: 4; tab-width: 8; indent-tabs-mode: nil -*-
+ * vim: set cindent ts=8 sw=4 expandtab:
+ *
+ *  @brief Contains the definition of string utility functions
+ *
+ *  String utility functions defined shall provide basic string copying
+ *  capabilities while using the preferred memory management utilities.
+ *
+ *  @author Eric Van Alst, MHPCC
+ *  @author David Robbins, MHPCC
+ *
+ *  @version $Revision: 1.60 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-09 00:47:41 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "psString.h"
+#include "psError.h"
+#include "psAssert.h"
+#include "psAbort.h"
+#include "psMemory.h"
+#include "psConstants.h"
+
+static void stringFree(psString string)
+{
+    // this function is only necessary so psMemCheckString has a function
+    // pointer address to test against
+}
+
+
+psString p_psStringAlloc(const char *file,
+                         unsigned int lineno,
+                         const char *func,
+                         size_t nChar)
+{
+    psString string = p_psAlloc(file, lineno, func, nChar + 1);
+    psMemSetDeallocator(string, (psFreeFunc)stringFree);
+
+    return string;
+}
+
+
+bool psMemCheckString(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return (psMemGetDeallocator(ptr) == (psFreeFunc)stringFree);
+}
+
+
+psString p_psStringCopy(const char *file,
+                        unsigned int lineno,
+                        const char *func,
+                        const char *string)
+{
+    // Pass through NULL values!
+    if (!string) {
+        return NULL;
+    }
+
+    // Output string
+    psString output = p_psStringAlloc(file, lineno, func, strlen(string));
+
+    // Copy input string to memory just allocated
+    return strcpy(output, string);
+}
+
+
+psString p_psStringNCopy(const char *file,
+                         unsigned int lineno,
+                         const char *func,
+                         const char *string,
+                         size_t nChar)
+{
+    // Pass through NULL values
+    if (!string) {
+        return NULL;
+    }
+
+    // Check the number of characters to copy is non-negative
+    if (nChar < 0) {
+        // Log error message and return NULL
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Can not copy a negative number of characters (%zd)."),
+                nChar);
+        return NULL;
+    }
+
+    // Copy input string to memory allocated up to nChar characters
+    psString output = p_psStringAlloc(file, lineno, func, nChar);
+    output = strncpy(output, string, nChar);
+
+    // Ensure the last byte is NULL character
+    output[nChar] = '\0';
+
+    // Return the string pointer
+    return output;
+}
+
+
+ssize_t p_psStringAppend(const char *file,
+                         unsigned int lineno,
+                         const char *func,
+                         psString *dest,
+                         const char *format,
+                         ...)
+{
+    PS_ASSERT_PTR_NON_NULL(dest, 0);
+    PS_ASSERT_PTR(*dest, 0);
+    PS_ASSERT_STRING_NON_EMPTY(format, 0);
+
+    va_list ap;
+    va_start(ap, format);
+    ssize_t length = p_psStringAppendV(file, lineno, func, dest, format, ap);
+    va_end(ap);
+
+    return length;
+}
+
+ssize_t p_psStringAppendV(const char *file,
+                          unsigned int lineno,
+                          const char *func,
+                          psString *dest,
+                          const char *format,
+                          va_list ap)
+{
+    PS_ASSERT_PTR_NON_NULL(dest, 0);
+    PS_ASSERT_PTR(*dest, 0);
+    PS_ASSERT_STRING_NON_EMPTY(format, 0);
+
+    size_t          length = 0;             // complete string length (sans \0)
+    size_t          oldLength = 0;          // original string length (sans \0)
+    ssize_t         tailLength = 0;         // length of string to append
+
+    if (*dest && psMemGetRefCounter(*dest) > 1) {
+        psWarning("Appending to a string with multiple reference counts may corrupt memory!");
+    }
+
+    if (*dest) {
+        oldLength = strlen(*dest);
+    } else {
+        oldLength = 0;
+    }
+
+    va_list         apCopy;
+
+    // find the size of the string to append
+    // C99 guarentees vsnprintf() to work as expected with size = 0
+    va_copy(apCopy, ap);
+    tailLength = vsnprintf(*dest, 0, format, apCopy);
+    va_end(apCopy);
+
+    // if the new tail is zero length, return the length of the old string.  if
+    // it's a format error, return the error code.
+    if (tailLength < 1) {
+        return tailLength == 0 ? oldLength : tailLength;
+    }
+
+    // realloc string to string + tail + \0
+    if (*dest) {
+        *dest = p_psRealloc(file, lineno, func, *dest, oldLength + tailLength + 1);
+    } else {
+        *dest = p_psStringAlloc(file, lineno, func, oldLength + tailLength + 1);
+    }
+
+    // append tail + \0
+    // XXX this second call to va_copy() isn't strictly nessicary as the
+    // calling function can't assume we won't modify the va_list.  However, we
+    // have decided to error on the side of caution.
+    va_copy(apCopy, ap);
+    vsnprintf(*dest + oldLength, tailLength + 1, format, apCopy);
+    va_end(apCopy);
+
+    return length;
+}
+
+
+ssize_t p_psStringPrepend(const char *file,
+                          unsigned int lineno,
+                          const char *func,
+                          psString *dest,
+                          const char *format,
+                          ...)
+{
+    PS_ASSERT_PTR_NON_NULL(dest, 0);
+    PS_ASSERT_PTR(*dest, 0);
+    PS_ASSERT_STRING_NON_EMPTY(format, 0);
+
+    va_list ap;
+    va_start(ap, format);
+    ssize_t length = p_psStringPrependV(file, lineno, func, dest, format, ap);
+    va_end(ap);
+
+    return length;
+}
+
+
+ssize_t p_psStringPrependV(const char *file,
+                           unsigned int lineno,
+                           const char *func,
+                           psString *dest,
+                           const char *format,
+                           va_list ap)
+{
+    PS_ASSERT_PTR_NON_NULL(dest, 0);
+    PS_ASSERT_PTR(*dest, 0);
+    PS_ASSERT_STRING_NON_EMPTY(format, 0);
+
+    size_t          length;             // complete string length (sans \0)
+    ssize_t         headLength;         // length of string to prepend
+    char            *oldDest;           // copy of original string
+
+    if (*dest && psMemGetRefCounter(*dest) > 1) {
+        psWarning("Appending to a string with multiple reference counts may corrupt memory!");
+    }
+
+    if (!*dest) {
+        // makes the string backup and concatination pointless
+        *dest = p_psStringCopy(file, lineno, func, "");
+        length = 0;
+    } else {
+        // size of existing string
+        length = strlen(*dest);
+    }
+
+    va_list apCopy;
+
+    // find the size of the string to prepend
+    // C99 guarentees vsnprintf() to work as expected with size = 0
+    va_copy(apCopy, ap);
+    headLength = vsnprintf(*dest, 0, format, apCopy);
+    va_end(apCopy);
+
+    // if the new head is zero length, return the length of the old string.  if
+    // it's a format error, return the error code.
+    if (headLength < 1) {
+        return headLength == 0 ? length : headLength;
+    }
+
+    // backup original string
+    oldDest = p_psStringCopy(file, lineno, func, *dest);
+
+    // new string length (sans \0)
+    length += headLength;
+
+    // realloc string to head + string + \0
+    *dest = p_psRealloc(file, lineno, func, *dest, length + 1);
+
+    // copy the new head to the beginning of string
+    // XXX this second call to va_copy() isn't strictly nessicary as the
+    // calling function can't assume we won't modify the va_list.  However, we
+    // have decided to error on the side of caution.
+    va_copy(apCopy, ap);
+    vsnprintf(*dest, length + 1, format, apCopy);
+    va_end(apCopy);
+
+    // append the original string
+    strncat(*dest, oldDest, length + 1);
+
+    psFree(oldDest);
+
+    return length;
+}
+
+
+// split the string by the given splitters
+// NULL input string returns empty (not NULL) list
+// NULL splitters is an error
+psList *p_psStringSplit(const char *file,
+                        unsigned int lineno,
+                        const char *func,
+                        const char *string,
+                        const char *splitters,
+                        bool multipleAreSignificant)
+{
+    PS_ASSERT_STRING_NON_EMPTY(splitters, NULL);
+
+    psList *values = p_psListAlloc(file, lineno, func, NULL); // The list of values to return
+    // An input NULL string should not generate an error: it is a valid case
+    if (string == NULL) {
+        return values;
+    }
+
+    char *next = NULL;
+    char *current = (char *) string;
+    while ((next = strpbrk (current, splitters)) != NULL) {
+
+        // are multiple splitters in-a-row significant?
+        if ((next == current) && !multipleAreSignificant) {
+            current ++;
+            continue;
+        }
+
+        // Copy the current word
+        psString word = p_psStringNCopy(file, lineno, func, current, next - current);
+        psListAdd(values, PS_LIST_TAIL, word);
+        psFree(word);
+
+        current = next + 1;
+    }
+
+    if (strlen(current) > 0) {
+        // Copy the last word
+        psString word = p_psStringCopy(file, lineno, func, current);
+        (void)psListAdd(values, PS_LIST_TAIL, word);
+        psFree(word);
+    }
+
+    return values;
+}
+
+
+// given the input string, search for all copies of the key, and replace with the replacement value
+// the input string may be freed if not needed
+ssize_t psStringSubstitute(psString *input,
+                           const char *replace,
+                           const char *key)
+{
+    PS_ASSERT_PTR_NON_NULL(input, 0);
+
+    // Empty input gives empty output
+    if (!*input || strlen(*input) == 0) {
+        return 0;
+    }
+    // No key gives the same as the input
+    if (!key || strlen(key) == 0) {
+        return strlen(*input);
+    }
+    if (!psMemCheckString(*input)) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "This function requires a psString as input.\n");
+        return 0;
+    }
+
+
+    // replace == NULL is valid: it just means that we strip out the key
+    // without putting anything else in its place
+    size_t replaceLength;               // Size of "replace" string
+    if (replace) {
+        replaceLength = strlen(replace);
+    } else {
+        replaceLength = 0;
+    }
+
+    char *search = *input;              // Search this string
+    while (true) {
+        char *found = strstr(search, key); // Found occurence of the key
+        if (!found) {
+            return strlen(*input);
+        }
+
+        // we have input = xxxkeyxxx
+        // we want output = xxxreplacexxx
+
+        // this is safe since we will subtract strlen(key) elements from input
+        psString output = psStringAlloc(strlen(*input) + replaceLength + 1); // Output string
+        int numChar = found - *input;    // Number of characters to copy
+
+        // copy the first segement into 'output'
+        strncpy(output, *input, numChar);
+
+        // copy the key replacement to the start of the key
+        if (replace && replaceLength > 0) {
+            strcpy(output + numChar, replace);
+            numChar += replaceLength;
+        }
+
+        // copy the remainder to the end of the replacement
+        strcpy(output + numChar, found + strlen(key));
+
+        psFree(*input);
+        *input = output;
+        search = output + numChar;
+    }
+
+    psAbort("Should never get here.\n");
+    return 0;
+}
+
+
+psArray *psStringSplitArray(const char *string, const char *splitters, bool multi)
+{
+
+    psList *list = psStringSplit(string, splitters, multi);
+    psArray *array = psListToArray(list);
+    psFree (list);
+    return array;
+}
+
+
+#ifndef whitespace
+#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
+#endif
+
+/* Strip whitespace from the start and end of STRING. */
+size_t psStringStrip(char *string)
+{
+    long i;
+
+    if (!string || strlen(string) == 0) {
+        return 0;
+    }
+
+    for (i = 0; i < strlen(string) && whitespace(string[i]); i++)
+        ; // No action
+    if (i) {
+        memmove (string, string + i, strlen(string+i)+1);
+    }
+    for (i = strlen (string) - 1; (i > 0) && whitespace(string[i]); i--)
+        ; // No action
+    string[++i] = 0;
+
+    return i;
+}
+
+
+/*
+ * Used by PS_FILE_LINE
+ */
+const char *p_psFileLine(const char *file, int line)
+{
+    static char msg[100];
+    sprintf(msg, "%s:%d", file, line);
+    return msg;
+}
+
+
+psString psStringStripCVS(const char *string, const char *tagName)
+{
+    PS_ASSERT_STRING_NON_EMPTY(string, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(tagName, NULL);
+
+    psString tagString = NULL;          // Tag string, e.g., "$Name:" from "Name"
+    psStringAppend(&tagString, "$%s:", tagName);
+    char *p = strstr(string, tagString); // The start of the real tag
+    psFree(tagString);
+    if (!p) {
+        return psStringCopy("UNKNOWN");
+    }
+
+    psString tag = psStringCopy(string + 6); // The tag, without the leading tagString
+    p = strrchr(tag, '$');              // The closing dollar sign
+    if (p) {
+        *p = 0;
+    }
+    psStringStrip(tag);
+    if (*tag == 0) {
+        psFree(tag);
+        return psStringCopy("UNKNOWN");
+    }
+
+    return tag;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psString.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psString.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psString.h	(revision 22158)
@@ -0,0 +1,319 @@
+/* @file  psString.h
+ *
+ * @brief string utility functions
+ *
+ * String utility functions defined shall provide basic string copying
+ * capabilities.
+ *
+ * @author EAM, IfA
+ * @author Eric Van Alst, MHPCC
+ * @author David Robbins, MHPCC
+ * @author Joshua Hoblitt, University of Hawaii
+ *
+ * @version $Revision: 1.44 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-09 00:47:41 $
+ *
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_STRING_H
+#define PS_STRING_H
+
+/// @addtogroup SysUtils System Utilities
+/// @{
+
+#include <sys/types.h>
+#include <stdarg.h>
+
+#include "psType.h"
+#include "psList.h"
+
+/** This macro will convert the argument to a quoted string */
+#define PS_STRING(S)  #S
+
+/** This macro returns a (static buffer containing) "file:line" */
+const char *p_psFileLine(const char *file, int line)
+#ifdef __GNUC__
+__attribute__((deprecated))
+#endif // ifdef __GNUC__
+;
+#define PS_FILE_LINE p_psFileLine(__FILE__,__LINE__)
+
+
+/** Allocates a new psString.
+ *
+ *  @return psString:       Newly allocated string of length n.
+ */
+#ifdef DOXYGEN
+psString psStringAlloc(
+    size_t nChar                        ///< Size of psString to allocate.
+);
+#else // ifdef DOXYGEN
+psString p_psStringAlloc(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    size_t nChar                        ///< Size of psString to allocate.
+) PS_ATTR_MALLOC;
+#define psStringAlloc(nChar) \
+      p_psStringAlloc(__FILE__, __LINE__, __func__, nChar)
+#endif // ifdef DOXYGEN
+
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr
+ *  datatype.
+ *
+ *  @return bool:       True if the pointer matches a psString structure, false otherwise.
+ */
+bool psMemCheckString(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+
+/** Copies the input string
+ *
+ *  This function shall allocate memory to the length of the input string plus
+ *  one and copy the input string to the newly allocated memory.  If 'string'
+ *  is 'NULL' then 'NULL' is returned.
+ *
+ *  @return psString:      Copy of input string
+ */
+#ifdef DOXYGEN
+psString psStringCopy(
+    const char *string                  ///< Input string of characters to copy
+);
+#else // ifdef DOXYGEN
+psString p_psStringCopy(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    const char *string                  ///< Input string of characters to copy
+);
+#define psStringCopy(string) \
+      p_psStringCopy(__FILE__, __LINE__, __func__, string)
+#endif // ifdef DOXYGEN
+
+
+/** Copies the input string up to the specified number of characters
+ *
+ *  This function shall allocate memory to the length specified by nChar
+ *  plus one and copy the input string to the newly allocated memory.
+ *  This function will only copy nChar bytes from the input to new string,
+ *  so if the input string is larger than nChar characters the copied
+ *  string will be a substring of the input string.  If the input string
+ *  is smaller than nChar bytes then the remaining bytes allocated will
+ *  be set to NULL.  If 'string' is 'NULL' then 'NULL' is returned.
+ *
+ *  @return  psString:   Copy of input string
+ */
+#ifdef DOXYGEN
+psString psStringNCopy(
+    const char *string,                 ///< Input string of characters to copy
+    size_t nChar                        ///< Number of bytes to allocate for string copy
+);
+#else // ifdef DOXYGEN
+psString p_psStringNCopy(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    const char *string,                 ///< Input string of characters to copy
+    size_t nChar                        ///< Number of bytes to allocate for string copy
+);
+#define psStringNCopy(string, nChar) \
+      p_psStringNCopy(__FILE__, __LINE__, __func__, string, nChar)
+#endif // ifdef DOXYGEN
+
+
+/** Appends a format onto a string
+ *
+ * This function shall allocate a new string if dest is NULL.  dest shall be
+ * automatically extended to the size of the new string.
+ *
+ * @return ssize_t:     The length of the new string (excluding '\0')
+ */
+#ifdef DOXYGEN
+ssize_t psStringAppend(
+    psString *dest,                     ///< existing string
+    const char *format,                 ///< format to append
+    ...                                 ///< format arguments
+);
+#else // ifdef DOXYGEN
+ssize_t p_psStringAppend(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psString *dest,                     ///< existing string
+    const char *format,                 ///< format to append
+    ...                                 ///< format arguments
+) PS_ATTR_FORMAT(printf, 5, 6);
+#define psStringAppend(dest, ...) \
+      p_psStringAppend(__FILE__, __LINE__, __func__, dest, __VA_ARGS__)
+#endif // ifdef DOXYGEN
+
+
+/** Appends a format onto a string
+ *
+ * This function shall allocate a new string if dest is NULL.  dest shall be
+ * automatically extended to the size of the new string.
+ *
+ * @return ssize_t:     The length of the new string (excluding '\0')
+ */
+#ifdef DOXYGEN
+ssize_t psStringAppendV(
+    psString *dest,                     ///< existing string
+    const char *format,                 ///< format to append
+    va_list ap                          ///< va_list of format arguments
+);
+#else // ifdef DOXYGEN
+ssize_t p_psStringAppendV(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psString *dest,                     ///< existing string
+    const char *format,                 ///< format to append
+    va_list ap                          ///< va_list of format arguments
+);
+#define psStringAppendV(dest, format, ap) \
+      p_psStringAppendV(__FILE__, __LINE__, __func__, dest, format, ap)
+#endif // ifdef DOXYGEN
+
+
+/** Prepends a format onto a string
+ *
+ * This function shall allocate a new string if dest is NULL.  dest shall be
+ * automatically extended to the size of the new string.
+ *
+ * @return ssize_t:     The length of the new string (excluding '\0')
+ */
+#ifdef DOXYGEN
+ssize_t psStringPrepend(
+    psString *dest,                     ///< existing string
+    const char *format,                 ///< format to append
+    ...                                 ///< format arguments
+);
+#else // ifdef DOXYGEN
+ssize_t p_psStringPrepend(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psString *dest,                     ///< existing string
+    const char *format,                 ///< format to append
+    ...                                 ///< format arguments
+) PS_ATTR_FORMAT(printf, 5, 6);
+#define psStringPrepend(dest, ...) \
+      p_psStringPrepend(__FILE__, __LINE__, __func__, dest, __VA_ARGS__)
+#endif // ifdef DOXYGEN
+
+
+/** Prepends a format onto a string
+ *
+ * This function shall allocate a new string if dest is NULL.  dest shall be
+ * automatically extended to the size of the new string.
+ *
+ * @return ssize_t:     The length of the new string (excluding '\0')
+ */
+#ifdef DOXYGEN
+ssize_t psStringPrependV(
+    psString *dest,                     ///< existing string
+    const char *format,                 ///< format to append
+    va_list ap                          ///< va_list of format arguments
+);
+#else // ifdef DOXYGEN
+ssize_t p_psStringPrependV(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psString *dest,                     ///< existing string
+    const char *format,                 ///< format to append
+    va_list ap                          ///< va_list of format arguments
+);
+#define psStringPrependV(dest, format, ap) \
+      p_psStringPrependV(__FILE__, __LINE__, __func__, dest, format, ap)
+#endif // ifdef DOXYGEN
+
+
+/** Procedure to split the input string into a psList of psStrings.
+ *
+ *  The string is split at any one of the characters in splitters.  Split
+ *  strings of zero length should not be included in the output list.
+ *
+ *  @return psList*:    The list of (split) psStrings.
+ */
+#ifdef DOXYGEN
+psList *psStringSplit(
+    const char *string,                ///< String to split
+    const char *splitters,             ///< Characters on which to split
+    bool multipleAreSignificant        ///< Are multiple occurences significant?
+);
+#else // ifdef DOXYGEN
+psList *p_psStringSplit(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    const char *string,                ///< String to split
+    const char *splitters,             ///< Characters on which to split
+    bool multipleAreSignificant        ///< Are multiple occurences significant?
+    );
+#define psStringSplit(string, splitters, multiple) \
+      p_psStringSplit(__FILE__, __LINE__, __func__, string, splitters, multiple)
+#endif // ifdef DOXYGEN
+
+/** Procedure to split the input string into a psArray of psStrings.
+ *
+ *  The string is split at any one of the characters in splitters.  Split
+ *  strings of zero length should not be included in the output list.
+ *
+ *  @return psArray*:       The array of (split) psStrings.
+ */
+psArray *psStringSplitArray(
+    const char *string,                ///< String to split
+    const char *splitters,             ///< Characters on which to split
+    bool multipleAreSignificant        ///< Are multiple occurences significant?
+);
+
+// Given the input string, search for all copies of the key, and replace with
+// the replacement value the input string may be freed if not needed
+/** Procedure to search an input string and substitute strings where desired.
+ *
+ *  The input string is searched for all instances of the key, which is then
+ *  replaced with the replacement value wherever found.  The input string may
+ *  be freed if not needed.
+ *
+ *  @return ssize_t:      the length of the new string (excluding '\0')
+ */
+ssize_t psStringSubstitute (
+    psString *input,                    ///< ptr to input string to be modified
+    const char *replace,                ///< replacement value
+    const char *key                     ///< string to be replaced in input
+);
+
+
+// strip whitespace from head and tail of string
+/** Procedure to strip the whitespace from the head and tail of a string.
+ *
+ *  @return size_t:         Number of whitespaces removed.
+ */
+size_t psStringStrip(
+    char *string                       ///< input string to be stripped.
+);
+
+
+/// Given a CVS keyword string, strip off the CVS-specific keyword to get the value
+psString psStringStripCVS(const char *string, ///< The string, something like "$CVSKEYWORD: Value$"
+                          const char *tagName ///< The name of the tag to remove, something like "CVSKEYWORD"
+                         );
+
+#define PS_ASSERT_STRING_NON_EMPTY(NAME, RVAL) \
+if (!(NAME) || strlen(NAME) == 0) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: String %s is NULL or empty.", \
+            #NAME); \
+    return RVAL; \
+}
+
+char *psStrcasestr (const char *haystack, const char *needle);
+
+/// @}
+#endif // #ifndef PS_STRING_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psThread.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psThread.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psThread.c	(revision 22158)
@@ -0,0 +1,289 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "psAssert.h"
+#include "psConstants.h"
+#include "psAbort.h"
+#include "psMemory.h"
+#include "psList.h"
+#include "psArray.h"
+#include "psString.h"
+#include "psThread.h"
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static psList *pending = NULL;		// queue of pending jobs
+static psList *done = NULL;		// queue of done jobs
+static psArray *pool = NULL;		// array of defined threads
+static psArray *tasks = NULL;		// queue of tasks
+
+/***** basic thread functions *****/
+
+void psThreadLock () {
+    pthread_mutex_lock (&mutex);
+    return;
+}
+
+void psThreadUnlock () {
+    pthread_mutex_unlock (&mutex);
+    return;
+}
+
+void psThreadFree (psThread *thread) {
+    return;
+}
+
+// allocate a psThread
+psThread *psThreadAlloc () {
+    
+    psThread *thread = (psThread *)psAlloc(sizeof(psThread));
+    psMemSetDeallocator(thread, (psFreeFunc)psThreadFree);
+
+    thread->busy  = false;
+    thread->fault = false;
+    return thread;
+}
+
+/***** thread job functions *****/
+
+void psThreadJobFree (psThreadJob *job) {
+
+    if (!job) return;
+
+    psFree (job->type);
+    psFree (job->args);
+    return;
+}
+
+// allocate a psThreadJob of the given type
+psThreadJob *psThreadJobAlloc (char *type) {
+    
+    psThreadJob *job = (psThreadJob *)psAlloc(sizeof(psThreadJob));
+    psMemSetDeallocator(job, (psFreeFunc)psThreadJobFree);
+
+    job->type = psStringCopy (type);
+    job->args = psArrayAlloc (0);
+    return job;
+}
+
+// add a job to the queue of pending jobs
+bool psThreadJobAddPending (psThreadJob *job) {
+
+    // if we failed to call psThreadPoolInit, or we called it with nThreads == 0,
+    // find the matching function and just run it.
+    if (!pool || !pool->n) {
+
+	// in non-threaded operation, the job is placed on the done list and immediately run
+	if (done == NULL) {
+	    done = psListAlloc(NULL);
+	}
+	psListAdd (done, PS_LIST_TAIL, job);
+
+	// find the corresponding task and run it
+	for (int i = 0; i < tasks->n; i++) {
+	    psThreadTask *task = tasks->data[i];
+	    if (strcmp (job->type, task->type)) continue;
+
+	    psAssert (job->args->n == task->nArgs, "invalid number of arguments to %s", task->type);
+
+	    bool status = task->function(job);
+	    return status;
+	}
+	return false;
+    }
+
+    psThreadLock ();
+    if (pending == NULL) {
+	pending = psListAlloc(NULL);
+    }
+
+    psListAdd (pending, PS_LIST_TAIL, job);
+    psThreadUnlock ();
+    return true;
+}
+
+// this function is not locked -- see thread launder for example
+psThreadJob *psThreadJobGetPending () {
+
+    if (!pending) return NULL;
+
+    psThreadJob *job = psListGetAndRemove (pending, PS_LIST_HEAD);
+
+    // jobs we pull off the pending queue get placed on the done queue
+    if (job) {
+	if (done == NULL) {
+	    done = psListAlloc(NULL);
+	}
+	psListAdd (done, PS_LIST_TAIL, job);
+    }
+    return job;
+}
+
+// this function is not locked -- see thread launder for example
+psThreadJob *psThreadJobGetDone () {
+
+    if (!done) return NULL;
+
+    psThreadJob *job = psListGetAndRemove (done, PS_LIST_HEAD);
+    return job;
+}
+
+/***** thread task functions *****/
+
+void psThreadTaskFree (psThreadTask *task) {
+
+    if (!task) return;
+
+    psFree (task->type);
+    return;
+}
+
+// allocate a psThreadTask with nArgs arguments
+psThreadTask *psThreadTaskAlloc (char *type, int nArgs) {
+    
+    psThreadTask *task = (psThreadTask *)psAlloc(sizeof(psThreadTask));
+    psMemSetDeallocator(task, (psFreeFunc)psThreadTaskFree);
+
+    task->type = psStringCopy (type);
+    task->nArgs = nArgs;
+    task->function = NULL;
+    return task;
+}
+
+// add a task to the collection of tasks
+bool psThreadTaskAdd (psThreadTask *task) {
+
+    if (tasks == NULL) {
+	tasks = psArrayAllocEmpty(8);
+    }
+
+    psArrayAdd (tasks, 1, task);
+    return true;
+}
+
+// each thread runs this function to choose the task functions
+void *psThreadLauncher (void *data) {
+
+    psThread *self = data;
+    psThreadJob *job = NULL;
+
+    while (1) {
+
+	// if we get an error, just wait until we are cleared or killed
+	while (self->fault) {
+	    usleep (10000);
+	}
+
+	// if no tasks are assigned, just wait until they are
+	while (tasks == NULL) {
+	    usleep (10000);
+	}
+
+	// request a new job, if there are none available, sleep a bit
+	// we have to lock here so the job queue cannot be empty yet no threads busy
+	psThreadLock();
+	while ((job = psThreadJobGetPending ()) == NULL) {
+	    psThreadUnlock();
+	    usleep (10000);
+	    psThreadLock(); // XXX ???
+	}
+	self->busy = true;
+
+	for (int i = 0; i < tasks->n; i++) {
+	    psThreadTask *task = tasks->data[i];
+	    if (strcmp (job->type, task->type)) continue;
+
+	    psThreadUnlock();
+	    psAssert (job->args->n == task->nArgs, "invalid number of arguments to %s", task->type);
+
+	    bool status = task->function(job);
+	    if (!status) {
+		self->fault = true;
+	    }
+	    self->busy = false;  
+	    break;
+	}
+	psThreadUnlock();
+	// XXX what do we do if the job is unknown?
+    }
+}
+
+/***** thread pool functions *****/
+
+// create a pool of Nthreads, each running the user's job-launcher function
+bool psThreadPoolInit (int nThreads) {
+
+    if (pool) psAbort ("psThreadsInit already called"); 
+	
+    pool = psArrayAlloc (nThreads);
+    for (int i = 0; i < nThreads; i++) {
+	psThread *thread = psThreadAlloc();
+	pthread_create (&thread->pt, NULL, psThreadLauncher, thread);
+	pool->data[i] = thread;
+    }
+    return true;
+}
+
+// call this function after you have added jobs to the queue and 
+bool psThreadPoolWait () {
+
+    // this function blocks (waits in usleep) until either
+    // an error is detected on one of the threads or until 
+    // all threads are idle and no jobs are left on the queue
+
+    if (!pool) return true;
+    if (!pool->n) return true;
+
+    while (1) {
+
+	// check for an error
+	for (int i = 0; i < pool->n; i++) {
+	    psThread *thread = pool->data[i];
+	    if (thread->fault) return false;
+	}
+
+	// are all threads idle?
+	psThreadLock();
+	for (int i = 0; i < pool->n; i++) {
+	    psThread *thread = pool->data[i];
+	    if (thread->busy) goto SLEEP;
+	}
+
+	if (!pending) return true;
+
+	// is the queue empty?
+	if (pending->head == NULL) {
+	    psThreadUnlock();
+	    return true;
+	}
+
+    SLEEP:
+	psThreadUnlock();
+	usleep (10000);
+    }
+    return false;
+}
+
+// create a pool of Nthreads, each running the user's job-launcher function
+bool psThreadPoolFinalize () {
+
+    psFree (pending);
+    pending = NULL;
+
+    psFree (done);
+    done = NULL;
+
+    psFree (pool);
+    pool = NULL;
+
+    psFree (tasks);
+    tasks = NULL;
+
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psThread.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psThread.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psThread.h	(revision 22158)
@@ -0,0 +1,58 @@
+/** @file  psThread.h
+ *
+ *  @brief tools to manage a pool of threads
+ *
+ *  @author EAM, IFA
+ *  @version $Revision: 1.1.2.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-31 23:24:22 $
+ *
+ *  Copyright 2004-2005 Insitute for Astronomy, University of Hawaii
+ */
+
+#ifndef PS_THREAD_H
+#define PS_THREAD_H
+
+/// @addtogroup SysUtils System Utilities
+/// @{
+
+typedef struct {
+    psString type;
+    psArray *args;
+} psThreadJob;
+
+typedef struct {
+    bool busy;
+    bool fault;
+    pthread_t pt;
+} psThread;
+
+typedef bool (*psThreadTaskFunction)(psThreadJob *job);
+
+typedef struct {
+    psString type;
+    int nArgs;
+    psThreadTaskFunction function;
+} psThreadTask;
+
+// typedef void *(*psThreadLaunchJobsFunction)(void *data);
+
+void psThreadLock ();
+void psThreadUnlock ();
+
+psThread *psThreadAlloc ();
+
+psThreadJob *psThreadJobAlloc (char *type);
+bool psThreadJobAddPending (psThreadJob *job);
+psThreadJob *psThreadJobGetPending ();
+psThreadJob *psThreadJobGetDone ();
+
+psThreadTask *psThreadTaskAlloc (char *type, int nArgs);
+bool psThreadTaskAdd (psThreadTask *task);
+void *psThreadLauncher (void *data);
+
+bool psThreadPoolInit (int nThreads);
+bool psThreadPoolWait ();
+bool psThreadPoolFinalize ();
+
+/// @}
+#endif /* PS_THREAD_H */
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psTrace.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psTrace.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psTrace.c	(revision 22158)
@@ -0,0 +1,810 @@
+/** @file psTrace.c
+ *  \brief basic run-time trace facilities
+ *  \ingroup LogTrace
+ *
+ *  This file will hold the code for procedures to insert
+ *  trace messages into the code.
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.87 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-04-17 23:43:02 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+/*****************************************************************************
+    NOTES:
+ In the SRD, higher trace levels correspond to a numerically lower trace
+ value in the code.  This is a bit confusing.  For example, a high-level
+ message might be something like "Begin Processing".  The module programmer
+ might give that a numerically low trace level, such as 1, so then any
+ non-zero trace level in that code component will display thatmessage.
+
+ We build a tree of trace components.  Every node in the tree has a
+ depth, which is it's distance from the root.  However, this is not
+ not the same thing as a node's "level", which corresponds to the
+ trace level of that node.
+
+I think the following is the correct behavior, but not sure:
+    PS_UNKNOWN_TRACE_LEVEL: We never set the level of a component to this
+    value.  This value is only used when psTraceGetLevel is called with
+    a bad component name, or if the component root is undefined, I think.
+
+    PS_DEFAULT_TRACE_LEVEL: This should only be used when adding the
+    intermediate components of a psS64 name.  Ie. the "B" in .A.B.C
+
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+// Even if psLib is being built without tracing (PS_NO_TRACE is set) we still
+// want to build the symbols for programs linked against psLib
+#undef PS_NO_TRACE
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "psAbort.h"
+#include "psAssert.h"
+#include "psTrace.h"
+#include "psString.h"
+#include "psError.h"
+#include "psLogMsg.h"
+#include "psMetadata.h"
+#include "psMemory.h"
+
+#define MAX_HOSTNAME_LENGTH 256
+#define MAX_HEADER_LENGTH 256
+#define MAX_TRACE_LENGTH 1024
+#define MAX_COMPONENT_LENGTH 1024
+
+
+static p_psComponent* cRoot = NULL; // The root of the trace component
+static bool traceTime = false;     // Flag to include time info
+static bool traceHost = false;     // Flag to include host info
+static bool traceLevel = false;    // Flag to include level info
+static bool traceName = false;     // Flag to include name info
+static bool traceMsg = true;      // Flag to include message info
+static int traceFD = STDOUT_FILENO; // default value
+
+static void componentFree(p_psComponent* comp);
+static p_psComponent* componentAlloc(const char *name, int level);
+static int getLevel(const char *facil);
+
+/*****************************************************************************
+componentAlloc(): allocate memory for a new node, and initialize members.
+ *****************************************************************************/
+static p_psComponent* componentAlloc(const char *name, int level)
+{
+    psAssert(name, "impossible");
+
+    p_psComponent* comp = psAlloc(sizeof(p_psComponent));
+
+    psMemSetPersistent(comp,true);
+    psMemSetDeallocator(comp, (psFreeFunc) componentFree);
+    comp->name = psStringCopy(name);
+    psMemSetPersistent((psPtr)comp->name,true);
+    comp->level = level;
+    comp->n = 0;
+    comp->p_psSpecified = false;
+    comp->subcomp = NULL;
+    return comp;
+}
+
+/*****************************************************************************
+componentFree(): free the current node in the root tree, and all children
+nodes as well.
+ *****************************************************************************/
+static void componentFree(p_psComponent* comp)
+{
+    if (comp == NULL) {
+        return;
+    }
+
+    if (comp->subcomp != NULL) {
+        for (psS32 i = 0; i < comp->n; i++) {
+            psMemSetPersistent(comp->subcomp[i],false);
+            psFree(comp->subcomp[i]);
+        }
+        psMemSetPersistent(comp->subcomp,false);
+        psFree(comp->subcomp);
+    }
+
+    psMemSetPersistent((psPtr)comp->name,false);
+    psFree((void *)comp->name);
+}
+
+/*****************************************************************************
+initTrace(): simply initialize the component root tree.
+*****************************************************************************/
+static void initTrace(void)
+{
+    if (cRoot == NULL) {
+        cRoot = componentAlloc(".", PS_DEFAULT_TRACE_LEVEL);
+    }
+}
+
+// Append the function name to the facility
+// NB: declares TARGET!
+#define FACILITY(TARGET, FUNC, FACIL) \
+    size_t _facilLength = strlen(FACIL); /* Length of facility name */ \
+    size_t _funcLength = strlen(FUNC);   /* Length of function name */ \
+    char TARGET[_facilLength + _funcLength + 2]; /* facility + the function name */ \
+    strcpy(&TARGET[0], FACIL); \
+    TARGET[_facilLength] = '.'; \
+    strcpy(&TARGET[_facilLength + 1], FUNC);
+
+
+/*****************************************************************************
+Set all trace levels to zero.
+
+XXX: Currently, no function calls this routine.
+ *****************************************************************************/
+void p_psTraceReset(p_psComponent* currentNode)
+{
+    psAssert(currentNode, "impossible");
+
+    psS32 i = 0;
+
+    if (NULL == currentNode) {
+        return;
+    }
+
+    currentNode->level = 0;
+    for (i = 0; i < currentNode->n; i++) {
+        if (NULL == currentNode->subcomp[i]) {
+            psLogMsg("p_psTraceReset", PS_LOG_WARN,
+                     _("Sub-component %d of node %s in trace tree is NULL."),
+                     i, currentNode->name);
+        } else {
+            p_psTraceReset(currentNode->subcomp[i]);
+        }
+    }
+    return;
+}
+
+/*****************************************************************************
+Set all trace levels to zero.
+ *****************************************************************************/
+void psTraceReset()
+{
+    psFree(cRoot);
+    cRoot = NULL;
+}
+
+/*****************************************************************************
+componentAdd(): Adds the component named "addNodeName" to the root tree.
+ *****************************************************************************/
+static bool componentAdd(const char *addNodeName, psS32 level)
+{
+    psAssert(addNodeName, "impossible");
+
+    psS32 i = 0;                        // Loop index variable.
+    char name[MAX_COMPONENT_LENGTH]; // buffer for writeable copy.
+    char *firstComponent = NULL;        // first component of name
+    p_psComponent* currentNode = cRoot;
+    psS32 nodeExists = 0;
+
+    // XXX: Verify that this is the correct behavior.
+    if (strcmp("", addNodeName) == 0) {
+        psError(PS_ERR_BAD_PARAMETER_NULL,true,
+                _("Failed to add null component to trace tree."));
+        return false;
+    }
+
+    // Is this the root node? If so, simply set level and return.
+    if (strcmp(".", addNodeName) == 0) {
+        cRoot->level = level;
+        return true;
+    }
+
+    if (addNodeName[0] != '.') {
+        psError(PS_ERR_BAD_PARAMETER_VALUE,true,
+                _("Failed to add '%s' to the root component tree; component must start with '.'."),
+                addNodeName);
+        return false;
+    }
+
+    strncpy(name, addNodeName, MAX_COMPONENT_LENGTH);
+    char *pname = name+1;               // Take off the period
+    // Iterate through the components of addNodeName.  Strip off the first
+    // component of the name, find that in the root tree, or add it if it
+    // does not exist, then move to the next component in the name.
+
+    while (pname != NULL) {
+        firstComponent = pname;
+        pname = strchr(firstComponent, '.');
+        if (pname != NULL) {
+            *pname = '\0';
+            pname++;
+        }
+        nodeExists = 0;
+        for (i = 0; i < currentNode->n; i++) {
+            if (strcmp(currentNode->subcomp[i]->name, firstComponent) == 0) {
+                currentNode = currentNode->subcomp[i];
+                nodeExists = 1;
+                if (pname == NULL) {
+                    currentNode->level = level;
+                }
+            }
+        }
+
+        if (nodeExists == 0) {
+            currentNode->subcomp = psRealloc(currentNode->subcomp,
+                                             (currentNode->n + 1) * sizeof(p_psComponent* ));
+            psMemSetPersistent(currentNode->subcomp,true);
+
+            currentNode->n = (currentNode->n) + 1;
+
+            if (pname == NULL) {
+                // This is the final component to add.
+                currentNode->subcomp[(currentNode->n) - 1] =
+                    componentAlloc(firstComponent, level);
+            } else {
+                // We are adding an intermediate component.  The trace level
+                // is not defined.  An undefined trace level inherits the
+                // trace level of it's parent.  However, we do not set that
+                // specifically here since that would inheritance to be a
+                // static, one-time, type of behavior.
+
+                currentNode->subcomp[(currentNode->n) - 1] =
+                    componentAlloc(firstComponent, PS_DEFAULT_TRACE_LEVEL);
+            }
+            currentNode = currentNode->subcomp[(currentNode->n) - 1];
+        }
+    }
+
+    return true;
+}
+
+/*****************************************************************************
+    psSetTraceLevel(): add the component named "comp" to the component tree,
+ if it is not already there, and set it's trace level to "level".
+
+    NOTE: We modified this so that the user may omit the leading "," in a
+    component name.  Since the code was already implemented assuming the "."
+    was required, rather than change all that code, in this function, I
+    simply add a leading "." to the component name if there is none.
+
+    Input:
+ comp
+ level
+    Output:
+ none
+    Returns:
+ zero
+*****************************************************************************/
+int psTraceSetLevel(const char *comp,   // component of interest
+                    int level)  // desired trace level
+{
+    PS_ASSERT_STRING_NON_EMPTY(comp, 0);
+
+    char *compName = NULL;
+    int prevLevel = -1;
+
+    // If the root component tree does not exist, then initialize it.
+    if (cRoot == NULL) {
+        initTrace();
+    }
+
+    // If the component name has no leading dot, then supply it.
+    if (comp[0] != '.') {
+        compName = (char *) psAlloc(10 + strlen(comp));
+        strcpy(compName, ".");
+        compName = strcat(compName, comp);
+    } else {
+        compName = (char *) comp;
+    }
+    prevLevel = getLevel(compName);
+    // Add the new component to the component tree.
+    if ( !componentAdd(compName, level) ) {
+        psError(PS_ERR_UNKNOWN, false,
+                _("Failed to set trace level (%d) to '%s'."),
+                level,
+                compName);
+
+        if (comp[0] != '.') {
+            psFree(compName);
+        }
+        //        return false;
+        return -1;
+    }
+
+    if (comp[0] != '.') {
+        psFree(compName);
+    }
+
+    //    return true;
+    return prevLevel;
+}
+
+/*****************************************************************************
+    doGetTraceLevel()
+ This function recursively searches the root component tree for the
+ component named "name", which is supplied by a parameter.  If it
+ finds that component, it returns the level of that component.
+ Otherwise, it returns ???.
+
+    NOTE: We modified this so that the user may omit the leading "," in a
+    component name.  Since the code was already implemented assuming the "."
+    was required, rather than change all that code, in this function, I
+    simply add a leading "." to the component name if there is none.
+
+    Inputs:
+ name:
+    Outputs:
+ none
+    Returns:
+ The trace level of the "name" component.
+ *****************************************************************************/
+static psS32 doGetTraceLevel(const char *aname)
+{
+    psAssert(aname, "impossible");
+    char name[strlen(aname) + 1];       // need a writeable copy: for strsep()
+    char *pname = name;
+    char *firstComponent = NULL;        // first component of name
+    p_psComponent* currentNode = cRoot;
+    psS32 i = 0;
+    psS32 defaultLevel = 0;
+
+    if (NULL == currentNode) {
+        return (PS_UNKNOWN_TRACE_LEVEL);
+    }
+
+    if (strcmp(".", aname) == 0) {
+        return (cRoot->level);
+    }
+
+    if (aname[0] != '.') {
+        return (PS_UNKNOWN_TRACE_LEVEL);
+    }
+
+    defaultLevel = cRoot->level;
+    strcpy(name, aname);
+    pname = name+1;
+    while (pname != NULL) {
+        firstComponent = pname;
+        pname = strchr(firstComponent, '.');
+        if (pname != NULL) {
+            *pname = '\0';
+            pname++;
+        }
+        for (i = 0; i < currentNode->n; i++) {
+            if (NULL == currentNode->subcomp[i]) {
+                psLogMsg("p_psTraceReset", PS_LOG_WARN,
+                         _("Sub-component %d of node %s in trace tree is NULL."),
+                         i, currentNode->name);
+            }
+
+            if (strcmp(currentNode->subcomp[i]->name, firstComponent) == 0) {
+                currentNode = currentNode->subcomp[i];
+                // For level inheritance purpose, we save the level of this
+                // component if it is not DEFAULT.
+                if (currentNode->level != PS_DEFAULT_TRACE_LEVEL) {
+                    defaultLevel = currentNode->level;
+                }
+                // Determine if this is the last component:
+                if (pname == NULL) {
+                    if (currentNode->level != PS_DEFAULT_TRACE_LEVEL) {
+                        return (currentNode->level);
+                    } else {
+                        return(defaultLevel);
+                    }
+                }
+            }
+        }
+    }
+    return(defaultLevel);
+}
+
+
+/*****************************************************************************
+    getLevel()
+ Return a trace level of "name" in the root component tree.  If the
+ exact string of components in "name" does not exist in the root
+ tree, we return the deepest level of the match.
+ *****************************************************************************/
+static int getLevel(const char *name)
+{
+    if (cRoot == NULL) {
+        return (PS_UNKNOWN_TRACE_LEVEL);
+    }
+
+    psS32 traceLevel;
+
+    // If the component name has no leading dot, then supply it.
+    if (name[0] != '.') {
+        char compName[strlen(name) + 2];
+        compName[0] = '.';
+        strcpy(&compName[1], name);
+
+        traceLevel = doGetTraceLevel(compName);
+    } else {
+        // Search the component root tree, determine the trace level.
+        traceLevel = doGetTraceLevel(name);
+    }
+
+    // XXX: The default trace level is currently set at -1, which is not a
+    // valid trace level.  This is convenient in determining whether or not
+    // a component should inherit the trace level from parent nodes.  However,
+    // it's not clear that -1 should ever be returned by this function.
+    // The SDR is unclear on this point and we should probably request IfA
+    // comment.
+    if (traceLevel == PS_DEFAULT_TRACE_LEVEL) {
+        traceLevel = PS_THE_OTHER_DEFAULT_TRACE_LEVEL;
+    }
+
+    return(traceLevel);
+}
+
+int p_psTraceGetLevel(const char *file,
+                      int lineno,
+                      const char *func,
+                      const char *name)
+{
+    PS_ASSERT_STRING_NON_EMPTY(name, 0);
+    PS_ASSERT_STRING_NON_EMPTY(func, 0);
+
+    FACILITY(facility, func, name);
+    return getLevel(facility);
+}
+
+/*****************************************************************************
+    doPrintTraceLevels()
+ This function recursively searches the component tree supplied by the
+ parameter "comp" and prints the name and level of each component.
+    Inputs:
+ comp: a node in the component tree.
+ level: the level of that node
+    Outputs:
+ none
+    Returns:
+ null
+ *****************************************************************************/
+static void doPrintTraceLevels(const p_psComponent* comp,
+                               psS32 depth,
+                               psS32 defLevel)
+{
+    psAssert(comp, "impossible");
+
+    char line[1024];
+    psS32 i = 0;
+
+    // XXX EAM : probably should just return if traceFD < 1
+    if (traceFD < 1)
+        return;
+
+    if (comp->name[0] == '\0') {
+        return;
+    } else {
+        if (comp->level == PS_DEFAULT_TRACE_LEVEL) {
+            sprintf(line,"%*s%-*s %d\n", depth, "", 20 - depth, comp->name, defLevel);
+            write (traceFD, line, strlen(line));
+        } else {
+            sprintf(line, "%*s%-*s %d\n", depth, "", 20 - depth, comp->name, comp->level);
+            write (traceFD, line, strlen(line));
+        }
+    }
+
+    for (i = 0; i < comp->n; i++) {
+        if (comp->level == PS_DEFAULT_TRACE_LEVEL) {
+            doPrintTraceLevels(comp->subcomp[i], depth + 1, defLevel);
+        } else {
+            doPrintTraceLevels(comp->subcomp[i], depth + 1, comp->level);
+        }
+    }
+}
+
+
+/*****************************************************************************
+psPrintTraceLevels(): Simply print all the trace levels in the trace level
+component tree.
+Inputs:
+ none
+Outputs:
+ none
+Returns:
+ null
+*****************************************************************************/
+void psTracePrintLevels(void)
+{
+    if (cRoot == NULL) {
+        return;
+    }
+
+    doPrintTraceLevels(cRoot, 0, PS_THE_OTHER_DEFAULT_TRACE_LEVEL);
+}
+
+void psTraceV(const char *comp,
+              int level,
+              const char *format,
+              va_list ap)
+{
+    PS_ASSERT_STRING_NON_EMPTY(comp, );
+    PS_ASSERT_STRING_NON_EMPTY(format, );
+
+    // XXX EAM : fd < 1 does not print messages
+    if (traceFD < 1) {
+        return;
+    }
+
+    static bool first = true;           // First time we've been called?
+    static char hostname[MAX_HOSTNAME_LENGTH + 1]; // Host name
+    if (first) {
+        first = false;
+        gethostname(hostname, MAX_HOSTNAME_LENGTH);
+    }
+
+    // Only display this message if it's trace level is less than the level
+    // of it's associatedcomponent.
+    if (level <= getLevel(comp)) {
+
+        char clevel = 0;                    // letter-name for level
+        switch (level) {
+        case PS_LOG_ABORT:
+            clevel = 'A';
+            break;
+        case PS_LOG_ERROR:
+            clevel = 'E';
+            break;
+        case PS_LOG_WARN:
+            clevel = 'W';
+            break;
+        case PS_LOG_INFO:
+            clevel = 'I';
+            break;
+        default:
+            if (level >= 4) {
+                clevel = level + '0';
+            } else {
+                psTrace("psLib.sys", 2, "Invalid logMsg level: %d (%s)\n", level, format);
+                level = (level < 0) ? 0 : 9;
+                clevel = level + '0';
+            }
+        }
+
+        int maxLength = MAX_HEADER_LENGTH; // Maximum length of header string
+        char head[maxLength + 2];       // the added two are for the ending | and \0
+        char *head_ptr = head;          // where we've got to in head
+
+        // Create the various log fields...
+        if (traceTime) {
+            time_t clock = time(NULL);  // The current time.
+            struct tm *utc = gmtime(&clock);    // The current gm time.
+            maxLength -= snprintf(head_ptr, maxLength, "%4d:%02d:%02d %02d:%02d:%02dZ",
+                                  utc->tm_year + 1900, utc->tm_mon + 1, utc->tm_mday,
+                                  utc->tm_hour, utc->tm_min, utc->tm_sec) - 1;
+            head_ptr += strlen(head_ptr);
+        }
+        // Hostname should be 20 characters.
+        if (traceHost) {
+            if (head_ptr > head) {
+                *head_ptr++ = '|';
+            }
+            maxLength -= snprintf(head_ptr, maxLength, "%-20s", hostname);
+            head_ptr += strlen(head_ptr);
+        }
+        if (traceLevel) {
+            if (head_ptr > head) {
+                *head_ptr++ = '|';
+            }
+            maxLength -= snprintf(head_ptr, maxLength, "%c", clevel);
+            head_ptr += strlen(head_ptr);
+        }
+        if (traceName) {
+            if (head_ptr > head) {
+                *head_ptr++ = '|';
+            }
+            maxLength -= snprintf(head_ptr, maxLength, "%s", comp);
+
+            head_ptr += strlen(head_ptr);
+        }
+
+        if (head_ptr > head) {
+            *head_ptr++ = '\n';
+        } else if (!traceMsg) {                  // no output desired
+            return;
+        }
+        *head_ptr = '\0';
+
+        write(traceFD, head, strlen(head));
+
+        if (traceMsg) {
+            // We indent each message one space for each level of the message.
+            for (int i = 0; i < level; i++) {
+                write (traceFD, " ", 1);
+            }
+            psString line = NULL;       // Line to print
+            psStringAppendV(&line, format, ap);
+            write (traceFD, line, strlen(line));
+            if (line[strlen(line) - 1] != '\n') {
+                write(traceFD, "\n", 1);
+            }
+            psFree(line);
+        } else {
+            write(traceFD, "\n", 1);
+        }
+
+        // XXX: what is fd-appropriate equivalent of fflush?
+    }
+}
+
+/*****************************************************************************
+p_psTrace(): we display the trace message to standard output if the trace
+level of that message, supplied by the parameter "level" is higher than the
+trace level that is currently associated with the component named by the
+parameter "comp".
+Input:
+ comp
+ level
+ ...  a printf-style output string.
+Output:
+ none
+Return:
+ null
+ *****************************************************************************/
+void p_psTrace(
+    const char* file,                  ///< file name
+    int lineno,                        ///< line number in file
+    const char* func,                  ///< function name
+    const char *facil,                 ///< facilty of interest
+    psS32 level,                       ///< desired trace level
+    const char *format,                ///< printf-style format command
+    ...                                ///< trace message arguments
+)
+{
+    PS_ASSERT_STRING_NON_EMPTY(file, );
+    PS_ASSERT_STRING_NON_EMPTY(func, );
+    PS_ASSERT_STRING_NON_EMPTY(facil, );
+    PS_ASSERT_STRING_NON_EMPTY(format, );
+
+    FACILITY(name, func, facil);
+
+    va_list ap;
+    va_start(ap, format);
+    psTraceV(name, level, format, ap);
+    va_end(ap);
+}
+
+bool psTraceSetDestination(int fd)
+{
+    if (fd < 0) {
+        return false;
+    }
+
+    if (traceFD > STDERR_FILENO) {
+        close(traceFD);
+    }
+    traceFD = fd;
+    return true;
+}
+
+int psTraceGetDestination()
+{
+    return traceFD;
+}
+
+/*****************************************************************************
+psTraceSetFormat(): Set the format of psTrace output.  More precisely,
+    provide a string consisting of the letters {H (host), L (level), M
+    (message), N (name), T (time)}.  The default is "HLMNT".  This string
+    determines whether or not they associated type of information will be
+    included in message traces.  It does not determine the order in which that
+    information will appear (that order is fixed).
+
+Input:
+    fmt: a string specifying the format.
+Return:
+    NULL.
+ *****************************************************************************/
+bool psTraceSetFormat(const char *format)
+{
+    // assume none.
+    traceHost = false;
+    traceLevel = false;
+    traceMsg = false;
+    traceName = false;
+    traceTime = false;
+
+    // if fmt is NULL, no logging is desired.
+    if (format == NULL) {
+        return false;
+    }
+
+    // XXX: What is the purpose of this conditional.
+    if (strlen(format) == 0) {
+        format = "THLNM";
+    }
+    // Step through each character in the format string.  For each letter
+    // in that string, set the appropriate logging.
+
+    for (const char *ptr = format; *ptr != '\0'; ptr++) {
+        switch (*ptr) {
+        case 'H':
+        case 'h':
+            traceHost = true;
+            break;
+        case 'L':
+        case 'l':
+            traceLevel = true;
+            break;
+        case 'M':
+        case 'm':
+            traceMsg = true;
+            break;
+        case 'N':
+        case 'n':
+            traceName = true;
+            break;
+        case 'T':
+        case 't':
+            traceTime = true;
+            break;
+        default:
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    _("Unknown logging keyword %c."), *ptr);
+            return false;
+        }
+    }
+
+    // XXX: If one must at least log error messages, why don't we set logMsg = true here?
+    if (!traceMsg) {
+        psTrace("psLib.sys", 1,
+                "You must at least trace error messages (You chose \"%s\")", format);
+
+    }
+    return true;
+}
+
+
+static void doGetTraceLevels(psMetadata *out, // Output metadata with the trace levels
+                             const p_psComponent* comp, // Component to add
+                             psString parent, // Name of parent level
+                             int defLevel // Default level
+                            )
+{
+    if (comp->name[0] == '\0') {
+        return;
+    }
+
+    psString name = psStringCopy(parent); // Name of this level
+    if (comp->name[0] == '.') {
+        psStringAppend(&name, "%s", comp->name + 1);
+    } else if (!parent) {
+        psStringAppend(&name, "%s", comp->name);
+    } else {
+        psStringAppend(&name, ".%s", comp->name);
+    }
+
+    int level = (comp->level == PS_DEFAULT_TRACE_LEVEL) ? defLevel : comp->level; // Level for component
+    if (name) {
+        psMetadataAddS32(out, PS_LIST_TAIL, name, 0, NULL, level);
+    }
+    for (int i = 0; i < comp->n; i++) {
+        doGetTraceLevels(out, comp->subcomp[i], name, level);
+    }
+
+    psFree(name);
+
+    return;
+}
+
+
+psMetadata *psTraceLevels(void)
+{
+    if (cRoot == NULL) {
+        return psMetadataAlloc();
+    }
+
+    psMetadata *out = psMetadataAlloc();// Output metadata with the levels
+    doGetTraceLevels(out, cRoot, NULL, PS_THE_OTHER_DEFAULT_TRACE_LEVEL);
+
+    return out;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psTrace.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psTrace.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psTrace.h	(revision 22158)
@@ -0,0 +1,178 @@
+/** @file psTrace.h
+ *
+ *  @brief basic run-time trace facilities
+ *
+ *  This file will hold the prototypes for defining procedures to insert
+ *  trace messages into the code.
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.59 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-08-09 01:40:07 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_TRACE_H
+#define PS_TRACE_H 1
+
+/// @addtogroup SysUtils System Utilities
+/// @{
+
+#include <stdarg.h>
+#include "psMetadata.h"
+
+#define PS_UNKNOWN_TRACE_LEVEL -9999   // we don't know this name's level
+#define PS_DEFAULT_TRACE_LEVEL -1
+#define PS_THE_OTHER_DEFAULT_TRACE_LEVEL 0
+
+enum {
+    PS_TRACE_TO_NONE = 0,             ///< turn off all traces
+    PS_TRACE_TO_STDOUT = 1,           ///< trace to system's stdout
+    PS_TRACE_TO_STDERR = 2,           ///< trace to system's stderr
+};
+
+/** Functions **************************************************************/
+
+//#define PS_NO_TRACE 1   ///< to turn off all tracing
+
+// XXX EAM : the old 'empty' values of (void) 0 are dangerous
+# if defined(PS_NO_TRACE)
+#   define psTraceSetFormat(format)     true    /* success */
+#   define psTrace(facil, level, ...)           /* do nothing */
+#   define psTraceGetLevel(facil)       0       /* trace level is always 0 */
+#   define psTraceV(facil, level, format, __VA_LIST)    /* do nothing */
+#   define psTraceSetLevel(facil,level) 0       /* previous level was 0 */
+#   define psTraceReset()                       /* do nothing */
+#   define psTracePrintLevels()                 /* do nothing */
+#   define psTraceSetDestination(fp)    true    /* success */
+#   define psTraceGetDestination()      2       /* destination is stderr */
+#   define psTraceLevels()              psMetadataAlloc() /* empty metadata */
+#   define PS_TRACE_ON                  0
+
+# else /* PS_NO_TRACE */
+#   define PS_TRACE_ON 1
+
+/** Basic structure for the component tree.  A component is a string of the
+    form aaa.bbb.ccc, and may itself contain further subcomponents.  The
+    Component structure doesn't in fact contain it's full name, but only the
+    last part. */
+typedef struct p_psComponent
+{
+    const char *name;                  ///< last part of name of component
+    psS32 level;                       ///< trace level for this component
+    bool p_psSpecified;                ///< whether the component is specified
+    psS32 n;                           ///< number of subcomponents
+    struct p_psComponent* *subcomp;    ///< next level of subcomponents
+}
+p_psComponent;
+
+
+/** This procedure sets the trace format for future trace messages.  The argument
+ *  must be a character string consistsing of the letters H (host), L
+ *  (level), M (message), N (name), and T (time).  The default is "THLNM".
+ *  Deleting a letter from the string will cause the associated information
+ *  to not be logged.  This procedure does not alter the order in which
+ *  the messages are displayed.
+ *
+ *  @return bool:       True if successful, otherwise false.
+ */
+bool psTraceSetFormat(
+    const char *format                 ///< Specifies the system trace format
+);
+
+/** Sends a trace message. */
+#ifdef DOXYGEN
+void psTrace(
+    const char *facil,                 ///< facilty of interest
+    int level,                         ///< desired trace level
+    const char *format,                ///< printf-style format command
+    ...                                ///< trace message arguments
+);
+#else // ifdef DOXYGEN
+void p_psTrace(
+    const char* file,                  ///< file name
+    int lineno,                        ///< line number in file
+    const char* func,                  ///< function name
+    const char *facil,                 ///< facilty of interest
+    psS32 level,                       ///< desired trace level
+    const char *format,                ///< printf-style format command
+    ...                                ///< trace message arguments
+) PS_ATTR_FORMAT(printf, 6, 7);
+#ifndef SWIG
+#define psTrace(facil, level, ...) \
+      p_psTrace(__FILE__,__LINE__,__func__,facil, level, __VA_ARGS__)
+#endif // ifndef SWIG
+#endif // ifdef DOXYGEN
+
+
+/** Get the trace level
+ *
+ *  @return int:    Trace Level
+ */
+#ifdef DOXYGEN
+int psTraceGetLevel(
+    const char *facil                  ///< facilty of interest
+);
+#else // ifdef DOXYGEN
+int p_psTraceGetLevel(
+    const char* file,                  ///< file name
+    int lineno,                        ///< line number in file
+    const char *func,                  ///< function name
+    const char *facil                  ///< facilty of interest
+);
+#ifndef SWIG
+#define psTraceGetLevel(facil) \
+      p_psTraceGetLevel(__FILE__,__LINE__,__func__,facil)
+#endif // ifndef SWIG
+#endif // ifdef DOXYGEN
+
+
+
+/** Sends a trace message. */
+void psTraceV(
+    const char *facil,                 ///< facilty of interest
+    int level,                         ///< desired trace level
+    const char *format,                ///< printf-style format command
+    va_list ap                         ///< varargs argument list
+);
+
+
+/** Set trace level
+ *
+ *  @return int:       The previous level.
+ */
+int psTraceSetLevel(
+    const char *facil,                 ///< facilty of interest
+    int level                          ///< desired trace level
+);
+
+/// Set all trace levels to zero (do not free nodes in the facility tree).
+void psTraceReset(void);
+
+
+/// print trace levels
+void psTracePrintLevels(void);
+
+
+/// Set the destination of future trace messages.
+bool psTraceSetDestination(
+    int fd                             ///< File descriptor
+);
+
+
+/** Get the current destination for trace messages.
+ *
+ *  @return FILE*:      File Destination
+ */
+int psTraceGetDestination(void);
+
+
+/// Return a psMetadata summarising the trace levels
+psMetadata *psTraceLevels(void);
+
+
+/// @}
+#endif /* PS_NO_TRACE */
+#endif /* PS_TRACE_H */
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psType.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psType.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psType.c	(revision 22158)
@@ -0,0 +1,208 @@
+/** @file  psType.c
+*
+*  @brief Contains psType checking functions
+*
+*  @author Robert DeSonia, MHPCC
+*  @author Robert Lupton, Princeton University
+*  @author Joshua Hoblitt, University of Hawaii
+*
+*  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-02-03 05:54:08 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdbool.h>
+
+#include "psType.h"
+#include "psBitSet.h"
+#include "psFits.h"
+#include "psPixels.h"
+#include "psSphereOps.h"
+#include "psMinimizeLMM.h"
+#include "psImageConvolve.h"
+#include "psTime.h"
+#include "psLine.h"
+#include "psRegion.h"
+#include "psHistogram.h"
+#include "psMemory.h"
+
+bool psMemCheckType(psDataType type,
+                    psPtr ptr)
+{
+    if (!ptr) {
+        return false;
+    }
+
+    switch(type) {
+    case PS_DATA_ARRAY:
+        if (psMemCheckArray(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_BITSET:
+        if (psMemCheckBitSet(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_CUBE:
+        if (psMemCheckCube(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_FITS:
+        if (psMemCheckFits(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_HASH:
+        if (psMemCheckHash(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_HISTOGRAM:
+        if (psMemCheckHistogram(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_IMAGE:
+        if (psMemCheckImage(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_KERNEL:
+        if (psMemCheckKernel(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_LINE:
+        if (psMemCheckLine(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_LIST:
+        if (psMemCheckList(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_LOOKUPTABLE:
+        if (psMemCheckLookupTable(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_METADATA:
+        if (psMemCheckMetadata(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_METADATAITEM:
+        if (psMemCheckMetadataItem(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_MINIMIZATION:
+        if (psMemCheckMinimization(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_PIXELS:
+        if (psMemCheckPixels(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_PLANE:
+        if (psMemCheckPlane(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_PLANEDISTORT:
+        if (psMemCheckPlaneDistort(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_PLANETRANSFORM:
+        if (psMemCheckPlaneTransform(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_POLYNOMIAL1D:
+        if (psMemCheckPolynomial1D(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_POLYNOMIAL2D:
+        if (psMemCheckPolynomial2D(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_POLYNOMIAL3D:
+        if (psMemCheckPolynomial3D(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_POLYNOMIAL4D:
+        if (psMemCheckPolynomial4D(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_PROJECTION:
+        if (psMemCheckProjection(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_REGION:
+        if (psMemCheckRegion(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_SCALAR:
+        if (psMemCheckScalar(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_SPHERE:
+        if (psMemCheckSphere(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_SPHEREROT:
+        if (psMemCheckSphereRot(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_SPLINE1D:
+        if (psMemCheckSpline1D(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_STATS:
+        if (psMemCheckStats(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_STRING:
+        if (psMemCheckString(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_TIME:
+        if (psMemCheckTime(ptr)) {
+            return true;
+        }
+        break;
+    case PS_DATA_VECTOR:
+        if (psMemCheckVector(ptr)) {
+            return true;
+        }
+        break;
+    default:
+        // error state -- fall through to returning false
+        break;
+    }
+
+    return false;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psType.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psType.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/psType.h	(revision 22158)
@@ -0,0 +1,317 @@
+/** @file  psType.h
+*
+*  @brief Contains support for basic types
+*
+*  This file defines common datatypes used throughout psLib.
+*
+*  @ingroup DataContainer
+*
+*  @author Robert DeSonia, MHPCC
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.62 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-08-09 03:30:47 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifndef PS_TYPE_H
+#define PS_TYPE_H
+
+/// @addtogroup DataContainer Data Containers
+/// @{
+
+#include <inttypes.h> // According to C99, this includes stdint.h
+#include <float.h>
+#include <stdbool.h>
+
+// Make sure we have INFINITY and NAN
+// Use GSL --- they solved the problem so we don't have to
+#ifndef INFINITY
+#include <gsl/gsl_nan.h>
+#define INFINITY GSL_POSINF
+#endif
+#ifndef NAN
+#include <gsl/gsl_sys.h>
+#include <gsl/gsl_nan.h>
+#define NAN GSL_NAN
+#endif
+
+/******************************************************************************/
+
+/*  TYPE DEFINITIONS                                                          */
+
+/******************************************************************************/
+
+/** Basic data types used by the containers.
+ *
+ * The basic types of the primitives used by psLib are defined within this enum. This enum is in turn used by
+ * the psType struct.
+ *
+ */
+
+typedef uint8_t psU8;                  ///< 8-bit unsigned int
+typedef uint16_t psU16;                ///< 16-bit unsigned int
+typedef uint32_t psU32;                ///< 32-bit unsigned int
+typedef uint64_t psU64;                ///< 64-bit unsigned int
+typedef int8_t psS8;                   ///< 8-bit signed int
+typedef int16_t psS16;                 ///< 16-bit signed int
+typedef int32_t psS32;                 ///< 32-bit signed int
+typedef int64_t psS64;                 ///< 64-bit signed int
+typedef float psF32;                   ///< 32-bit floating point
+typedef double psF64;                  ///< 64-bit floating point
+typedef char* psString;                ///< string value
+typedef void* psPtr;                   ///< void pointer
+
+// XXX psBool can't be removed until all macros that 'generate' this type are
+// fixed -JH
+// #ifdef __GNUC__
+// typedef bool psBool __attribute__ ((deprecated)); ///< boolean value
+//#else // ifdef __GNUC__
+typedef bool psBool;                   ///< boolean value
+// #endif // fdef __GNUC__
+typedef bool psBOOL;                 ///< allow psBOOL to be used instead of psBool (for macros)
+
+/** Enumeration of data types for function elements.
+ *  Contains replacements for native types.
+ */
+typedef enum {
+    PS_TYPE_S8   = 0x0101,             ///< Character.
+    PS_TYPE_S16  = 0x0102,             ///< Short integer.
+    PS_TYPE_S32  = 0x0104,             ///< Integer.
+    PS_TYPE_S64  = 0x0108,             ///< Long integer.
+    PS_TYPE_U8   = 0x0301,             ///< Unsigned character.
+    PS_TYPE_U16  = 0x0302,             ///< Unsigned psS16 integer.
+    PS_TYPE_U32  = 0x0304,             ///< Unsigned integer.
+    PS_TYPE_U64  = 0x0308,             ///< Unsigned psS64 integer.
+    PS_TYPE_F32  = 0x0404,             ///< Single-precision Floating point.
+    PS_TYPE_F64  = 0x0408,             ///< Double-precision floating point.
+    PS_TYPE_BOOL = 0x1301              ///< Boolean.
+} psElemType;
+
+/** Enumeration primarily used with metadata which defines a data structure
+ *  e.g., list, array, FITS file, etc.
+*/
+typedef enum {
+    PS_DATA_S8   = PS_TYPE_S8,         ///< psS8
+    PS_DATA_S16  = PS_TYPE_S16,        ///< psS16
+    PS_DATA_S32  = PS_TYPE_S32,        ///< psS32
+    PS_DATA_S64  = PS_TYPE_S64,        ///< psS64
+    PS_DATA_U8   = PS_TYPE_U8,         ///< psU8
+    PS_DATA_U16  = PS_TYPE_U16,        ///< psU16
+    PS_DATA_U32  = PS_TYPE_U32,        ///< psU32
+    PS_DATA_U64  = PS_TYPE_U64,        ///< psU64
+    PS_DATA_F32  = PS_TYPE_F32,        ///< psF32
+    PS_DATA_F64  = PS_TYPE_F64,        ///< psF64
+    PS_DATA_BOOL = PS_TYPE_BOOL,       ///< psBool
+    PS_DATA_STRING = 0x10000,          ///< psString (char *)
+    PS_DATA_ARRAY,                     ///< psArray
+    PS_DATA_BITSET,                    ///< psBitSet
+    PS_DATA_CUBE,                      ///< psCube
+    PS_DATA_FITS,                      ///< psFits
+    PS_DATA_HASH,                      ///< psHash
+    PS_DATA_HISTOGRAM,                 ///< psHistogram
+    PS_DATA_IMAGE,                     ///< psImage
+    PS_DATA_KERNEL,                    ///< psKernel
+    PS_DATA_LINE,                      ///< psLine
+    PS_DATA_LIST,                      ///< psList
+    PS_DATA_LOOKUPTABLE,               ///< psLookupTable
+    PS_DATA_METADATA,                  ///< psMetadata
+    PS_DATA_METADATAITEM,              ///< psMetadataItem
+    PS_DATA_MINIMIZATION,              ///< psMinimization
+    PS_DATA_PIXELS,                    ///< psPixels
+    PS_DATA_PLANE,                     ///< psPlane
+    PS_DATA_PLANEDISTORT,              ///< psPlaneDistort
+    PS_DATA_PLANETRANSFORM,            ///< psPlaneTransform
+    PS_DATA_POLYNOMIAL1D,              ///< psPolynomial1D
+    PS_DATA_POLYNOMIAL2D,              ///< psPolynomial2D
+    PS_DATA_POLYNOMIAL3D,              ///< psPolynomial3D
+    PS_DATA_POLYNOMIAL4D,              ///< psPolynomial4D
+    PS_DATA_PROJECTION,                ///< psProjection
+    PS_DATA_REGION,                    ///< psRegion
+    PS_DATA_SCALAR,                    ///< psScalar
+    PS_DATA_SPHERE,                    ///< psSphere
+    PS_DATA_SPHEREROT,                 ///< psSphereTransform
+    PS_DATA_SPLINE1D,                  ///< psSpline1D
+    PS_DATA_STATS,                     ///< psStats
+    PS_DATA_TIME,                      ///< psTime
+    PS_DATA_VECTOR,                    ///< psVector
+    PS_DATA_UNKNOWN,                   ///< Other data of an unknown type
+    PS_DATA_METADATA_MULTI             ///< Used internally for metadata; not a 'real' type
+} psDataType;
+
+#define PS_TYPE_MASK PS_TYPE_U8        /**< the psElemType to use for mask image */
+#define PS_TYPE_MASK_DATA U8           /**< the data member to use for mask image */
+#define PS_TYPE_MASK_NAME "psU8"       /**< the data type for mask as a string */
+
+typedef psU8 psMaskType;               ///< the C datatype for a mask image
+
+#define PS_MIN_S8        INT8_MIN      /**< minimum valid psS8 value */
+#define PS_MIN_S16       INT16_MIN     /**< minimum valid psS16 value */
+#define PS_MIN_S32       INT32_MIN     /**< minimum valid psS32 value */
+#define PS_MIN_S64       INT64_MIN     /**< minimum valid psS64 value */
+#define PS_MIN_U8        0             /**< minimum valid psU8 value */
+#define PS_MIN_U16       0             /**< minimum valid psU16 value */
+#define PS_MIN_U32       0             /**< minimum valid psU32 value */
+#define PS_MIN_U64       0             /**< minimum valid psU64 value */
+#define PS_MIN_F32       -FLT_MAX      /**< minimum valid psF32 value */
+#define PS_MIN_F64       -DBL_MAX      /**< minimum valid psF64 value */
+
+#define PS_MAX_S8        INT8_MAX      /**< maximum valid psS8 value */
+#define PS_MAX_S16       INT16_MAX     /**< maximum valid psS16 value */
+#define PS_MAX_S32       INT32_MAX     /**< maximum valid psS32 value */
+#define PS_MAX_S64       INT64_MAX     /**< maximum valid psS64 value */
+#define PS_MAX_U8        UINT8_MAX     /**< maximum valid psU8 value */
+#define PS_MAX_U16       UINT16_MAX    /**< maximum valid psU16 value */
+#define PS_MAX_U32       UINT32_MAX    /**< maximum valid psU32 value */
+#define PS_MAX_U64       UINT64_MAX    /**< maximum valid psU64 value */
+#define PS_MAX_F32       FLT_MAX       /**< maximum valid psF32 value */
+#define PS_MAX_F64       DBL_MAX       /**< maximum valid psF64 value */
+
+#define PS_TYPE_BOOL_NAME "psBool"
+#define PS_TYPE_S8_NAME   "psS8"
+#define PS_TYPE_S16_NAME  "psS16"
+#define PS_TYPE_S32_NAME  "psS32"
+#define PS_TYPE_S64_NAME  "psS64"
+#define PS_TYPE_U8_NAME   "psU8"
+#define PS_TYPE_U16_NAME  "psU16"
+#define PS_TYPE_U32_NAME  "psU32"
+#define PS_TYPE_U64_NAME  "psU64"
+#define PS_TYPE_F32_NAME  "psF32"
+#define PS_TYPE_F64_NAME  "psF64"
+
+#define PS_TYPE_NAME(value,type) \
+switch(type) { \
+case PS_TYPE_BOOL: \
+    value = PS_TYPE_BOOL_NAME; \
+    break; \
+case PS_TYPE_S8: \
+    value = PS_TYPE_S8_NAME; \
+    break; \
+case PS_TYPE_S16: \
+    value = PS_TYPE_S16_NAME; \
+    break; \
+case PS_TYPE_S32: \
+    value = PS_TYPE_S32_NAME; \
+    break; \
+case PS_TYPE_S64: \
+    value = PS_TYPE_S64_NAME; \
+    break; \
+case PS_TYPE_U8: \
+    value = PS_TYPE_U8_NAME; \
+    break; \
+case PS_TYPE_U16: \
+    value = PS_TYPE_U16_NAME; \
+    break; \
+case PS_TYPE_U32: \
+    value = PS_TYPE_U32_NAME; \
+    break; \
+case PS_TYPE_U64: \
+    value = PS_TYPE_U64_NAME; \
+    break; \
+case PS_TYPE_F32: \
+    value = PS_TYPE_F32_NAME; \
+    break; \
+case PS_TYPE_F64: \
+    value = PS_TYPE_F64_NAME; \
+    break; \
+default: \
+    value = "unknown"; \
+};
+
+/// Macro to get the bad pixel reason code (stored as part of mask value)
+#define PS_BADPIXEL_BITMASK 0x0f
+#define PS_GET_BADPIXEL(maskValue) (maskValue & PS_BADPIXEL_BITMASK)
+
+#define PS_IS_BADPIXEL(maskValue) (PS_GET_BADPIXEL(maskValue) != 0)
+
+/// Macro to apply a bad pixel reason code to mask image
+#define PS_SET_BADPIXEL(maskValue, reasonCode) \
+{ \
+    maskValue = (psMaskType)((reasonCode & PS_BADPIXEL_BITMASK) | (maskValue & ~PS_BADPIXEL_BITMASK)); \
+}
+
+/// Macro to determine if the psElemType is an integer.
+#define PS_IS_PSELEMTYPE_INT(x) ((x & 0x100) == 0x100)
+/// Macro to determine if the psElemType is unsigned.
+#define PS_IS_PSELEMTYPE_UNSIGNED(x) ((x & 0x200) == 0x200)
+/// Macro to determine if the psElemType is a real floating-point type.
+#define PS_IS_PSELEMTYPE_REAL(x) ((x & 0x400) == 0x400)
+/// Macro to determine if the psElemType is boolean type.
+#define PS_IS_PSELEMTYPE_BOOL(x) ((x & 0x1000) == 0x1000)
+/// Macro to determine the storage size, in bytes, of the psElemType.
+#define PSELEMTYPE_SIZEOF(x) (x & 0xFF)
+
+#ifdef __GNUC__
+#define PS_ATTR_MALLOC __attribute__((__malloc__))
+#else // __GNUC__
+#define PS_ATTR_MALLOC
+#endif // __GNUC__
+
+#ifdef __GNUC__
+#define PS_ATTR_NORETURN __attribute__((noreturn))
+#else // __GNUC__
+#define PS_ATTR_NORETURN
+#endif // __GNUC__
+
+#ifdef __GNUC__
+#define PS_ATTR_FORMAT(style, start, end) __attribute__((format(style, start, end)))
+#else // __GNUC__
+#define PS_ATTR_FORMAT(style, start, end)
+#endif // __GNUC__
+
+#ifdef __GNUC__
+#define PS_ATTR_PURE __attribute__((pure))
+#else // __GNUC__
+#define PS_ATTR_PURE
+#endif // __GNUC__
+
+/** Dimensions of a data type.
+ *
+ * The dimensions of containers used by psLib are defined within this enum. This enum is used by the psType
+struct. *
+ */
+typedef enum {
+    PS_DIMEN_SCALAR,            ///< Scalar.
+    PS_DIMEN_VECTOR,            ///< Vector.
+    PS_DIMEN_TRANSV,            ///< Transposed vector.
+    PS_DIMEN_IMAGE,             ///< Image.
+    PS_DIMEN_OTHER              ///< Something else that's not supported for arithmetic.
+} psDimen;
+
+/** The type of a data type.
+ *
+ * All psLib complex types consist of primitive components. This struct provides the description of those
+ * primitives.
+ *
+ */
+typedef struct
+{
+    psElemType type;                   ///< The type
+    psDimen dimen;                     ///< The dimensionality.
+}
+psMathType;
+
+/** The type of a basic data type
+ *
+ *  All psLib complex types consist of primitive components.  This structure provides the ability to cast
+ *  an unknown data structure to safely test the underlining data type.
+ *
+ */
+typedef struct
+{
+    psMathType type;              ///< Data type information
+}
+psMath;
+
+/** Checks the deallocator to see if the pointer matches the desired datatype.
+ *
+ *  @return bool:       True if type matches, otherwise false.
+ */
+bool psMemCheckType(
+    psDataType type,                   ///< The desired psDataType to match
+    psPtr ptr                          ///< The desired pointer to match
+);
+
+/// @}
+#endif // #ifndef PS_TYPE_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/strcasestr.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/strcasestr.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/strcasestr.c	(revision 22158)
@@ -0,0 +1,133 @@
+/* Return the offset of one string within another.
+   Copyright (C) 1994, 1996-2000, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+ 
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+ 
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+ 
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/*
+ * My personal strstr() implementation that beats most other algorithms.
+ * Until someone tells me otherwise, I assume that this is the
+ * fastest implementation of strstr() in C.
+ * I deliberately chose not to comment it.  You should have at least
+ * as much fun trying to understand it, as I had to write it :-).
+ *
+ * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+
+#if defined _LIBC || defined HAVE_STRING_H
+# include <string.h>
+#endif
+
+#ifdef _LIBC
+# include <locale/localeinfo.h>
+# define TOLOWER(c) __tolower_l ((unsigned char) c, loc)
+#else
+# define TOLOWER(c) _tolower (c)
+#endif
+
+typedef unsigned chartype;
+
+#undef strcasestr
+#undef __strcasestr
+
+char *
+psStrcasestr(const char *phaystack,
+	     const char *pneedle)
+{
+    register const unsigned char *haystack, *needle;
+    register chartype b, c;
+    #ifdef _LIBC
+
+    __locale_t loc = _NL_CURRENT_LOCALE;
+    #endif
+
+    haystack = (const unsigned char *) phaystack;
+    needle = (const unsigned char *) pneedle;
+
+    b = TOLOWER (*needle);
+    if (b != '\0') {
+        haystack--;    /* possible ANSI violation */
+        do {
+            c = *++haystack;
+            if (c == '\0')
+                goto ret0;
+        } while (TOLOWER (c) != (int) b);
+
+        c = TOLOWER (*++needle);
+        if (c == '\0')
+            goto foundneedle;
+        ++needle;
+        goto jin;
+
+        for (;;) {
+            register chartype a;
+            register const unsigned char *rhaystack, *rneedle;
+
+            do {
+                a = *++haystack;
+                if (a == '\0')
+                    goto ret0;
+                if (TOLOWER (a) == (int) b)
+                    break;
+                a = *++haystack;
+                if (a == '\0')
+                    goto ret0;
+shloop:
+                ;
+            } while (TOLOWER (a) != (int) b);
+
+jin:
+            a = *++haystack;
+            if (a == '\0')
+                goto ret0;
+
+            if (TOLOWER (a) != (int) c)
+                goto shloop;
+
+            rhaystack = haystack-- + 1;
+            rneedle = needle;
+            a = TOLOWER (*rneedle);
+
+            if (TOLOWER (*rhaystack) == (int) a)
+                do {
+                    if (a == '\0')
+                        goto foundneedle;
+                    ++rhaystack;
+                    a = TOLOWER (*++needle);
+                    if (TOLOWER (*rhaystack) != (int) a)
+                        break;
+                    if (a == '\0')
+                        goto foundneedle;
+                    ++rhaystack;
+                    a = TOLOWER (*++needle);
+                } while (TOLOWER (*rhaystack) == (int) a);
+
+            needle = rneedle;  /* took the register-poor approach */
+
+            if (a == '\0')
+                break;
+        }
+    }
+foundneedle:
+    return (char*) haystack;
+ret0:
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/sys/sys.i
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/sys/sys.i	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/sys/sys.i	(revision 22158)
@@ -0,0 +1,11 @@
+/* sys headers */
+
+%include "psAbort.h"
+%include "psConfigure.h"
+%include "psErrorCodes.h"
+%include "psError.h"
+%include "psLogMsg.h"
+%include "psMemory.h"
+%include "psString.h"
+%include "psTrace.h"
+%include "psType.h"
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/.cvsignore	(revision 22158)
@@ -0,0 +1,10 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
+*.loT
+*.bb
+*.bbg
+*.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/Makefile.am	(revision 22158)
@@ -0,0 +1,36 @@
+#Makefile for types functions of psLib
+#
+noinst_LTLIBRARIES = libpslibtypes.la
+
+libpslibtypes_la_CPPFLAGS = $(SRCINC) $(PSLIB_CFLAGS) $(CFITSIO_CFLAGS)
+libpslibtypes_la_SOURCES = \
+	psArray.c \
+	psBitSet.c \
+	psHash.c \
+	psList.c \
+	psLookupTable.c \
+	psMetadata.c \
+	psMetadataConfig.c \
+	psMetadataItemParse.c \
+	psMetadataItemCompare.c \
+	psPixels.c \
+	psArguments.c	\
+	psTree.c
+
+EXTRA_DIST = types.i
+
+pkginclude_HEADERS = \
+	psArray.h \
+	psBitSet.h \
+	psHash.h \
+	psList.h \
+	psLookupTable.h \
+	psMetadata.h \
+	psMetadataConfig.h \
+	psMetadataItemParse.h \
+	psMetadataItemCompare.h \
+	psPixels.h \
+	psArguments.h	\
+	psTree.h
+
+CLEANFILES = *~ *.bb *.bbg *.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/parse_gcov-out.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/parse_gcov-out.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/parse_gcov-out.c	(revision 22158)
@@ -0,0 +1,149 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAXSTR 10000
+
+static char outStr[MAXSTR];
+static float average;
+static int sum;
+
+void parseFile(FILE *in, const char *filename);
+
+int main(void)
+{
+
+    FILE *output = NULL;
+    FILE *input = NULL;
+    average = 0.0;
+    sum = 0;
+    int N = 0;
+
+    input = fopen("arg_gcov.out", "r");
+    parseFile(input, "psArguments.c");
+    fclose(input);
+    N++;
+
+    input = fopen("arr_gcov.out", "r");
+    parseFile(input, "psArray.c");
+    fclose(input);
+    N++;
+
+    input = fopen("bit_gcov.out", "r");
+    parseFile(input, "psBitSet.c");
+    fclose(input);
+    N++;
+
+    input = fopen("hash_gcov.out", "r");
+    parseFile(input, "psHash.c");
+    fclose(input);
+    N++;
+
+    input = fopen("list_gcov.out", "r");
+    parseFile(input, "psList.c");
+    fclose(input);
+    N++;
+
+    input = fopen("look_gcov.out", "r");
+    parseFile(input, "psLookupTable.c");
+    fclose(input);
+    N++;
+
+    input = fopen("md_gcov.out", "r");
+    parseFile(input, "psMetadata.c");
+    fclose(input);
+    N++;
+
+    input = fopen("mdic_gcov.out", "r");
+    parseFile(input, "psMetadataItemCompare.c");
+    fclose(input);
+    N++;
+
+    input = fopen("mdip_gcov.out", "r");
+    parseFile(input, "psMetadataItemParse.c");
+    fclose(input);
+    N++;
+
+    input = fopen("mdc_gcov.out", "r");
+    parseFile(input, "psMetadataConfig.c");
+    fclose(input);
+    N++;
+
+    input = fopen("pix_gcov.out", "r");
+    parseFile(input, "psPixels.c");
+    fclose(input);
+    N++;
+
+    average = average / sum;
+
+    output = fopen("Coverage-Report.txt", "w");
+    fprintf(output, "\nTOTAL COVERAGE IN THE ../src/types/ DIRECTORY\n");
+    fprintf(output, "\n%s", outStr);
+    fprintf(output, "  -------------------------------"
+            "-------------------------------------\n");
+    fprintf(output, "  ---> Total                        = Lines executed:");
+    fprintf(output, "%3.2f%%  of %d\n\n", average, sum);
+    fclose(output);
+    return 0;
+}
+
+void parseINT(const char *nums, float percent)
+{
+    sum += atoi(nums);
+    average += (float)((int)(percent * atoi(nums)));
+}
+
+float parseDBL(const char *nums)
+{
+    char temp[7];
+    int i = 0;
+    int j = 9;
+    float out = 0.0;
+    while (nums[j] != '%') {
+        temp[i] = nums[j];
+        i++;
+        j++;
+    }
+    //    average += (float)atof(temp);
+    out = (float)atof(temp);
+    return out;
+}
+
+void parseFile(FILE *in, const char *filename)
+{
+    char currentStr[100];
+    char searchStr[100];
+    char out[250];
+    sprintf(out, "  >><< %-25s    =", filename);
+    sprintf(searchStr, "'%s'", filename);
+    //    printf("\n searchStr = %s\n", searchStr);
+    strcat(outStr, out);
+    int i;
+    float numLines = 0.0;
+    while ( fscanf(in, "%s", currentStr) != EOF) {
+        if ( strncmp(currentStr, searchStr, 99) == 0 ) {
+            for (i = 0; i < 4; i++) {
+                if (i == 1) {
+                    fscanf(in, "%s", out);
+                    numLines = parseDBL(out);
+                    sprintf(currentStr, "%-16s", out);
+                } else if ( i == 3) {
+                    fscanf(in, "%s", out);
+                    parseINT(out, numLines);
+                    sprintf(currentStr, "%s", out);
+                } else {
+                    fscanf(in, "%s", currentStr);
+                }
+                strcat(outStr, " ");
+                strcat(outStr, currentStr);
+            }
+            continue;
+        }
+    }
+    strcat(outStr, "\n\n");
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/profile_tap
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/profile_tap	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/profile_tap	(revision 22158)
@@ -0,0 +1,16 @@
+
+gcov -f --object-file ./.libs/libpslibtypes_la-psArguments.o psArguments.c > arg_gcov.out
+gcov -f --object-file ./.libs/libpslibtypes_la-psArray.o psArray.c > arr_gcov.out
+gcov -f --object-file ./.libs/libpslibtypes_la-psBitSet.o psBitSet.c > bit_gcov.out
+gcov -f --object-file ./.libs/libpslibtypes_la-psHash.o psHash.c > hash_gcov.out
+gcov -f --object-file ./.libs/libpslibtypes_la-psList.o psList.c > list_gcov.out
+gcov -f --object-file ./.libs/libpslibtypes_la-psLookupTable.o psLookupTable.c > look_gcov.out
+gcov -f --object-file ./.libs/libpslibtypes_la-psMetadataConfig.o psMetadataConfig.c > mdc_gcov.out
+gcov -f --object-file ./.libs/libpslibtypes_la-psMetadataItemCompare.o psMetadataItemCompare.c > mdic_gcov.out
+gcov -f --object-file ./.libs/libpslibtypes_la-psMetadataItemParse.o psMetadataItemParse.c > mdip_gcov.out
+gcov -f --object-file ./.libs/libpslibtypes_la-psMetadata.o psMetadata.c > md_gcov.out
+gcov -f --object-file ./.libs/libpslibtypes_la-psPixels.o psPixels.c > pix_gcov.out
+gcc parse_gcov-out.c -o parse_gcov
+./parse_gcov
+rm *.out
+more Coverage-Report.txt
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psArguments.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psArguments.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psArguments.c	(revision 22158)
@@ -0,0 +1,564 @@
+/** @file  psArguments.h
+ *
+ *  @brief Contains operations for parsing command line input arguments.
+ *
+ *  @ingroup Arguments
+ *
+ *  @author David Robbins, MHPCC
+ *
+ *  @version $Revision: 1.35 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-05-05 00:09:04 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "psArguments.h"
+#include "fitsio.h"
+#include "psMemory.h"
+#include "psError.h"
+#include "psAbort.h"
+
+#include "psLogMsg.h"
+#include "psTrace.h"
+#include "psAssert.h"
+
+#define NUM_SPACES 2   // Number of spaces between
+
+// Set verbosity level
+int psArgumentVerbosity(int *argc,
+                        char **argv)
+{
+    int logLevel = psLogGetLevel();     // Current logging level
+    PS_ASSERT_PTR_NON_NULL(argv, 2);
+    PS_ASSERT_PTR_NON_NULL(argc, 2);
+    PS_ASSERT_INT_POSITIVE(*argc, 2);
+    int argnum = 0;   // Argument number
+
+    // set in order, so that -vvv overrides -vv overrides -v
+    if ( (argnum = psArgumentGet(*argc, argv, "-v")) ) {
+        psArgumentRemove(argnum, argc, argv);
+        logLevel = 3;
+        psLogSetLevel(logLevel);
+    }
+    if ( (argnum = psArgumentGet(*argc, argv, "-vv")) ) {
+        psArgumentRemove(argnum, argc, argv);
+        logLevel = 4;
+        psLogSetLevel(logLevel);
+    }
+    if ( (argnum = psArgumentGet(*argc, argv, "-vvv")) ) {
+        psArgumentRemove(argnum, argc, argv);
+        logLevel = 5;
+        psLogSetLevel(logLevel);
+    }
+
+    if ( (argnum = psArgumentGet(*argc, argv, "-logfmt")) ) {
+        if (*argc < argnum + 2) {
+            psError(PS_ERR_IO, true, "-logfmt switch specified without a format.");
+        } else {
+            psArgumentRemove(argnum, argc, argv);
+            psLogSetFormat(argv[argnum]); // XXX EAM : this function should return an error if the log format is invalid
+            psArgumentRemove(argnum, argc, argv);
+        }
+    }
+
+    // Now the trace stuff
+    // argument format is: -trace (facil) (level)
+    while ( (argnum = psArgumentGet(*argc, argv, "-trace")) ) {
+        if ( (*argc < argnum + 3) ) {
+            psError(PS_ERR_IO, true, "-trace switch specified without facility and level.");
+            return logLevel;
+        }
+        psArgumentRemove(argnum, argc, argv);
+        // psTraceSetLevel is cast to void to avoid a warning in the case where
+        // PS_NO_TRACE is set and psTraceSetLevel is a macro returning an
+        // untyped value
+        (void)psTraceSetLevel(argv[argnum], atoi(argv[argnum+1])); // XXX: This function should return an error if the trace level is invalid
+        psArgumentRemove(argnum, argc, argv);
+        psArgumentRemove(argnum, argc, argv);
+    }
+    if ((argnum = psArgumentGet(*argc, argv, "-trace-levels"))) {
+        psTracePrintLevels();
+        return logLevel;
+    }
+
+    return logLevel;
+}
+
+// Find the location of the specified argument
+int psArgumentGet(int argc,
+                  char **argv,
+                  const char *arg)
+{
+    PS_ASSERT_INT_POSITIVE(argc, 0);
+    PS_ASSERT_PTR_NON_NULL(argv, 0);
+    PS_ASSERT_STRING_NON_EMPTY(arg, 0);
+
+    for (int i = 1; i < argc; i++) {
+        if (!strcmp(argv[i], arg))
+            return i;
+    }
+
+    return 0;
+}
+
+// Remove the specified argument (by location)
+bool psArgumentRemove(int argnum,
+                      int *argc,
+                      char **argv)
+{
+    PS_ASSERT_INT_POSITIVE(argnum, false);
+    PS_ASSERT_PTR_NON_NULL(argc, false);
+    PS_ASSERT_INT_LESS_THAN(argnum, *argc, false);
+    PS_ASSERT_PTR_NON_NULL(argv, false);
+
+    (*argc)--;
+    for (int i = argnum; i < *argc; i++) {
+        argv[i] = argv[i+1];
+    }
+    argv[*argc] = NULL;
+
+    return true;
+}
+
+
+#define ARG_READ_CASE_INT(TYPE,FUNC) \
+case PS_TYPE_##TYPE: { \
+    char *end; \
+    item->data.TYPE = FUNC(argv[argnum], &end, 0); \
+    if (end == argv[argnum]) { \
+        psError(PS_ERR_IO, true, "Unable to read argument value for %s", item->name); \
+        return false; \
+    } \
+    return psArgumentRemove(argnum, argc, argv); \
+}
+
+#define ARG_READ_CASE_FLOAT(TYPE,FUNC) \
+case PS_TYPE_##TYPE: { \
+    char *end; \
+    item->data.TYPE = FUNC(argv[argnum], &end); \
+    if (end == argv[argnum]) { \
+        psError(PS_ERR_IO, true, "Unable to read argument value for %s", item->name); \
+        return false; \
+    } \
+    return psArgumentRemove(argnum, argc, argv); \
+}
+
+static bool argumentRead(psMetadataItem *item, // Item to read into
+                         int argnum, // Argument number
+                         int *argc, // Number of arguments in total
+                         char **argv) // The arguments
+
+{
+    switch(item->type)
+    {
+        ARG_READ_CASE_INT(U8,strtol);
+        ARG_READ_CASE_INT(U16,strtol);
+        ARG_READ_CASE_INT(U32,strtol);
+        ARG_READ_CASE_INT(U64,strtoll);
+        ARG_READ_CASE_INT(S8,strtol);
+        ARG_READ_CASE_INT(S16,strtol);
+        ARG_READ_CASE_INT(S32,strtol);
+        ARG_READ_CASE_INT(S64,strtoll);
+        ARG_READ_CASE_FLOAT(F32,strtof);
+        ARG_READ_CASE_FLOAT(F64,strtod);
+    case PS_DATA_BOOL:
+        // Turn option on; no optional argument to remove
+        item->data.B = true;
+        return true;
+    case PS_DATA_STRING:
+        psFree(item->data.V);
+        item->data.V = psStringCopy(argv[argnum]);
+        return psArgumentRemove(argnum, argc, argv);
+    case PS_DATA_TIME:
+    {
+        psTime *time = psTimeFromString(argv[argnum], PS_TIME_UTC);
+        if (!time) {
+            psError(PS_ERR_IO, true, "Unable to read argument value for %s", item->name);
+            return false;
+        }
+        item->data.V = time; 
+        return psArgumentRemove(argnum, argc, argv);
+    }
+    default:
+        psError(PS_ERR_IO, true, "Argument type (%x) is not supported --- argument %s (%s) ignored\n",
+                item->type, item->name, item->comment);
+        return false;
+    }
+
+    return true;
+}
+
+
+bool psArgumentParse(psMetadata *arguments,
+                     int *argc,
+                     char **argv)
+{
+    PS_ASSERT_METADATA_NON_NULL(arguments, false);
+    PS_ASSERT_PTR_NON_NULL(argc, false);
+    PS_ASSERT_INT_POSITIVE(*argc, false);
+    PS_ASSERT_PTR_NON_NULL(argv, false);
+
+    // We need to do a bit of mucking around in order to preserve the arguments metadata until the last
+    // minute --- if there is a bad argument, we need to return the old "arguments", since they contain
+    // the default values, which we probably want to output in a "help" message (we don't want to print
+    // the changed values and have the user think that they are default values).
+    psMetadata *oldArgs = psMetadataCopy(NULL, arguments); // Copy of old arguments, in event of an error
+    psMetadata *multiFlag = psMetadataAlloc(); // Flag for which MULTI values have been read
+
+    for (int i = 1; i < *argc; i++) {
+        psTrace("psLib.types", 7, "Looking at %s\n", argv[i]);
+        psMetadataItem *argItem = psMetadataLookup(arguments, argv[i]);
+        if (argItem) {
+	    psStringAppend (&argItem->comment, " (found)");
+            psArgumentRemove(i, argc, argv); // Remove the switch
+
+            switch (argItem->type) {
+            case PS_DATA_METADATA: {
+                    // -arg 1 2 3
+                    psMetadata *params = argItem->data.V; // The list of parameters
+                    if (*argc < i + params->list->n) {
+                        psError(PS_ERR_IO, true, "Not enough arguments for %s.\n", argItem->name);
+                        // Remove the arguments --- they will be ignored
+                        for (int j = i; j < *argc; j++) {
+                            psArgumentRemove(i, argc, argv);
+                        }
+                        goto failed;
+                    }
+
+                    psMetadataIterator *paramsIter = psMetadataIteratorAlloc(params,
+                                                     PS_LIST_HEAD, NULL);// Iter
+                    psMetadataItem *param = NULL; // Parameter from iteration
+                    while ((param = psMetadataGetAndIncrement(paramsIter))) {
+			if (!argumentRead(param, i, argc, argv)) {
+			    psFree(paramsIter);
+			    psError(PS_ERR_IO, false, "error parsing argument %s\n", argItem->name);
+			    goto failed;
+			}
+                    }
+                    psFree(paramsIter);
+                    break;
+                }
+            case PS_DATA_METADATA_MULTI: {
+                    // -arg 1 -arg 2 -arg 3 ....
+                    psList *multi = argItem->data.V; // The MULTI list
+                    psMetadataItem *template = psListGet(multi, PS_LIST_HEAD)
+                                               ; // The template item
+                    psMetadataItem *newItem = psMetadataItemCopy(template)
+                                              ; // New item to add
+                    if (!argumentRead(newItem, i, argc, argv)) {
+			psFree(newItem);
+			psError(PS_ERR_IO, false, "error parsing argument %s\n", argItem->name);
+			goto failed;
+		    }
+
+                    psMetadataAddItem(arguments, newItem, PS_LIST_TAIL, PS_META_DUPLICATE_OK);
+                    psFree(newItem);      // Drop reference
+
+                    // Remove the template
+                    bool search = false;  // Result of search
+                    if (!psMetadataLookupBool(&search, multiFlag, argItem->name) || !search) {
+                        // Chop the template off
+                        psListRemove(multi, PS_LIST_HEAD); // Remove from MULTI (hash side)
+                        psListRemoveData(arguments->list, template)
+                        ; // Remove from list side
+                        psMetadataAddBool(multiFlag, PS_LIST_HEAD, argItem->name, PS_META_REPLACE,
+                                          NULL, true);
+                    }
+                    break;
+                }
+            default:
+                // -arg 1
+                if (argItem->type != PS_DATA_BOOL && *argc < i + 1) {
+                    psError(PS_ERR_IO, true, "Required argument for %s is missing.\n", argItem->name);
+                    goto failed;
+                }
+                if (!argumentRead(argItem, i, argc, argv)) {
+		    psError(PS_ERR_IO, false, "error parsing argument %s\n", argItem->name);
+		    goto failed;
+		}
+                break;
+            }
+            i--;                        // We removed stuff
+        } else if (strncmp(argv[i], "-", 1) == 0 || strncmp(argv[i], "+", 1) == 0) {
+            // Someone's specified a bad option
+            psError(PS_ERR_IO, true, "Unknown option: %s\n", argv[i]);
+            goto failed;
+        }
+    }
+
+    psFree(multiFlag);
+    psFree(oldArgs);                    // Didn't need these
+    return true;
+
+failed:
+    // We need to copy everything back
+    while (psListLength(arguments->list) > 0) {
+        psMetadataRemoveIndex(arguments, PS_LIST_TAIL);
+    }
+    psMetadataCopy(arguments, oldArgs);
+    psFree(multiFlag);
+    psFree(oldArgs);
+    return false;
+}
+
+
+#define LENGTH_CASE(TYPE) \
+case PS_TYPE_##TYPE: \
+return arg->data.TYPE == 0 ? 1 : \
+       (arg->data.TYPE > 0 ? (int)log10f((float)arg->data.TYPE) + 1 : \
+        (int)log10f(-(float)arg->data.TYPE) + 2);
+
+static int argLength(psMetadataItem *arg)
+{
+    switch (arg->type) {
+        // Only doing a representative set of types
+        LENGTH_CASE(U8);
+        LENGTH_CASE(U16);
+        LENGTH_CASE(U32);
+        LENGTH_CASE(U64);
+        LENGTH_CASE(S8);
+        LENGTH_CASE(S16);
+        LENGTH_CASE(S32);
+        LENGTH_CASE(S64);
+    case PS_DATA_F32:
+        return isnan(arg->data.F32) ? 3 : (arg->data.F32 >= 0 ? 12 : 13); // -d.dddddde?dd
+    case PS_DATA_F64:
+        return isnan(arg->data.F64) ? 3 : (arg->data.F64 >= 0 ? 12 : 13); // -d.dddddde?dd
+    case PS_DATA_BOOL:
+        return arg->data.B ? 4 : 5;
+    case PS_DATA_STRING:
+        return arg->data.V ? strlen(arg->data.V) : 0;
+    case PS_DATA_TIME:
+    {
+        if (arg->data.V) {
+            psString str = psTimeToISO(arg->data.V);
+            int len = strlen(str);
+            psFree(str);
+            return len;
+        }
+        return 0;
+    }
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                "Argument type (%x) is not supported.\n", arg->type);
+        return 0;
+        //        psAbort("Argument type (%x) is not supported.\n", arg->type);
+    }
+
+    return 0;
+}
+
+
+#define PRINT_CASE(TYPE,FORMAT) \
+case PS_TYPE_##TYPE: \
+printf(FORMAT, item->data.TYPE); \
+break;
+
+// Print the value and comment for an argument item
+static void printValueComment(psMetadataItem *item, // Argument item for which to print
+                              const char *comment, // Comment to print
+                              unsigned int numSpaces) // Number of spaces
+
+{
+    int valueLength = 0;                // Length of the value portion
+    printf("(");
+    if (item) {
+        // Print the value
+        switch (item->type) {
+            PRINT_CASE(U8, "%u");
+            PRINT_CASE(U16, "%u");
+            PRINT_CASE(U32, "%u");
+            PRINT_CASE(U64, "%" PRIu64);
+            PRINT_CASE(S8, "%d");
+            PRINT_CASE(S16, "%d");
+            PRINT_CASE(S32, "%d");
+            PRINT_CASE(S64, "%" PRId64);
+            PRINT_CASE(F32, "%.6e");
+            PRINT_CASE(F64, "%.6e");
+        case PS_DATA_BOOL:
+            if (item->data.B) {
+                printf("TRUE");
+            } else {
+                printf("FALSE");
+            }
+            break;
+        case PS_DATA_STRING:
+            if (item->data.V) {
+                printf("%s", item->data.str);
+            }
+            break;
+        default:
+            //            psAbort("Argument type (%x) for %s is not supported.\n",
+            //                    item->type, item->name);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    "Argument type (%x) for %s is not supported.\n", item->type, item->name);
+        }
+        valueLength = argLength(item);
+    }
+    printf(")");
+
+    // Spaces for formatting
+    for (int i = valueLength; i < numSpaces; i++) {
+        printf(" ");
+    }
+
+    // Print the comment
+    if (comment) {
+        printf("%s", comment);
+    }
+    printf("\n");
+
+    return;
+}
+
+// Return the maximum length of the values
+static void maxLength(int *maxName,     // Maximum length of the name
+                      int *maxValue,    // Maximum length of the value
+                      psMetadata *md)    // Metadata for which to check the length
+
+{
+    psMetadataIterator *iter = psMetadataIteratorAlloc(md, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *item = NULL;        // Item from iteration
+    while ((item = psMetadataGetAndIncrement(iter)))
+    {
+        if (item->type == PS_DATA_METADATA) {
+            maxLength(maxName, maxValue, item->data.V);
+        } else {
+            int nameLength = strlen(item->name); // Length of the name
+            if (nameLength > *maxName) {
+                *maxName = nameLength;
+            }
+            int valueLength = argLength(item); // Length of the value
+            if (valueLength > *maxValue) {
+                *maxValue = valueLength;
+            }
+        }
+    }
+    psFree(iter);
+    return;
+}
+
+
+void psArgumentHelp(psMetadata *arguments)
+{
+    if (arguments == NULL)
+        return;
+    printf("Optional arguments, with default values:\n");
+    int maxName = 4;   // Maximum length of a name
+    int maxValue = 4;   // Maximum length of a value
+
+    // First pass to get the sizes
+    maxLength(&maxName, &maxValue, arguments);
+
+    // Second pass to print
+    psMetadataIterator *argIter = psMetadataIteratorAlloc(arguments, PS_LIST_HEAD, NULL);
+    psMetadataItem *argItem = NULL; // Item from iterator
+    while ((argItem = psMetadataGetAndIncrement(argIter))) {
+        // Initial indent
+        for (int i = 0; i < NUM_SPACES; i++) {
+            printf(" ");
+        }
+
+        // Print the name if required
+        printf("%s", argItem->name);
+        int position = strlen(argItem->name); // Number of spaces in
+        for (int i = position; i < maxName + NUM_SPACES; i++) {
+            printf(" ");
+        }
+
+        // Check to see if it's a MULTI --- there are no default values for a MULTI
+        // -arg 1 -arg 2 -arg 3 ...
+        psMetadataItem *multiCheck = psMetadataLookup(arguments, argItem->name); // Item to check for MULTI
+        if (multiCheck->type == PS_DATA_METADATA_MULTI) {
+            bool first = true;          // Is this the first one?
+            psListIterator* iter = psListIteratorAlloc(multiCheck->data.list,PS_LIST_HEAD,true);
+            psMetadataItem* listItem;
+            int count = 0;
+            //            while ((listItem=(psMetadataItem*)psListGetAndIncrement(iter)) != NULL) {
+            while ((listItem=(psMetadataItem*)psListGetAndIncrement(iter)) != NULL) {
+                //                for (int i = 0; i < NUM_SPACES; i++) {
+                //                    printf(" ");
+                //                }
+                //                printf("%s", listItem->name);
+                //                int position = strlen(listItem->name); // Number of spaces in
+                //                for (int i = position; i < maxName + NUM_SPACES; i++) {
+                //                    printf(" ");
+                //                }
+                if (!first) {
+                    for (int i = 0; i < maxName + 2*NUM_SPACES; i++) {
+                        printf(" ");
+                    }
+                }
+                printValueComment(listItem, listItem->comment, maxValue + NUM_SPACES);
+                first = false;
+                count++;
+                //                continue;
+            }
+            psFree(iter);
+            while (count > 1) {
+                argItem = psMetadataGetAndIncrement(argIter);
+                count--;
+            }
+            continue;
+        }
+
+        // -arg 1 2 3
+        if (argItem->type == PS_DATA_METADATA) {
+            psMetadata *params = argItem->data.V; // The list of parameters
+            psMetadataIterator *paramsIter = psMetadataIteratorAlloc(params, PS_LIST_HEAD, NULL); // Iterator
+            psMetadataItem *paramItem = NULL; // Parameter, from iteration
+            bool first = true;          // Is this the first one?
+            while ((paramItem = psMetadataGetAndIncrement(paramsIter))) {
+                if (!first) {
+                    for (int i = 0; i < maxName + 2*NUM_SPACES; i++) {
+                        printf(" ");
+                    }
+                }
+                printValueComment(paramItem, paramItem->comment, maxValue + NUM_SPACES);
+                first = false;
+            }
+            psFree(paramsIter);
+            continue;
+        }
+
+        // -arg 1
+        printValueComment(argItem, argItem->comment, maxValue + NUM_SPACES);
+    }
+
+    psFree(argIter);
+}
+
+void psArgumentHelpSimple(FILE *stream, psMetadata *arguments)
+{
+    PS_ASSERT_PTR_NON_NULL(arguments, );
+
+    int maxName = 4;   // Maximum length of a name
+    int maxValue = 4;   // Maximum length of a value
+
+    // First pass to get the sizes
+    maxLength(&maxName, &maxValue, arguments);
+
+    // Second pass to print
+    psMetadataIterator *iter = psMetadataIteratorAlloc(arguments, PS_LIST_HEAD, NULL);
+    psMetadataItem *item = NULL; // Item from iterator
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        // Initial indent + name + indent + comment
+        fprintf(stream, "%*s" "%-*s" "%*s" "%s\n",
+                NUM_SPACES, " ",
+                maxName, item->name,
+                NUM_SPACES, " ",
+                item->comment);
+    }
+
+    psFree(iter);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psArguments.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psArguments.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psArguments.h	(revision 22158)
@@ -0,0 +1,81 @@
+/** @file  psArguments.h
+ *
+ *  @brief Contains operations for parsing command line input arguments.
+ *
+ *  @author David Robbins, MHPCC
+ *
+ *  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-06-01 03:37:19 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_ARGUMENTS_H
+#define PS_ARGUMENTS_H
+
+/// @addtogroup SysUtils
+/// @{
+
+#include "psMetadata.h"
+
+/** Implements the various verbosity controls.
+ *
+ *  Arguments shall be removed from the argument list as they are processed.
+ *
+ *  @return int:        The resultant logging level.
+ */
+int psArgumentVerbosity(
+    int *argc,                         ///< number of arguments
+    char **argv                        ///< the argument list
+);
+
+/** Checks for an argument and returns its index position if found.
+ *
+ *  @return int:        The index of the element in the argument list, otherwise 0.
+ */
+int psArgumentGet(
+    int argc,                          ///< number of arguments
+    char **argv,                       ///< the argument list
+    const char *arg                    ///< the specified argument to match
+);
+
+/** Removes from the argument list the argument whose index is argnum.
+ *
+ *  The number of entries in the argument list shall be decremented.
+ *
+ *  @return bool:       True if the argnum is in the argument list, otherwise false.
+ */
+bool psArgumentRemove(
+    int argnum,                        ///< the argument to remove
+    int *argc,                         ///< number of arguments
+    char **argv                        ///< the argument list
+);
+
+/** Parses the command line arguments into a metadata container of arguments.
+ *
+ *  The input arguments shall contain the list of possible arguments as the keywords providing
+ *  the default values.  As matching arguments are found on the command line, the values shall
+ *  be read into the arguments metadata, with the appropriate type.  The arguments and their
+ *  values shall be removed from the list of command line arguments as they are processed.
+ *
+ *  @return bool:       False if any argument was encountered that is not present in arguments.
+ */
+bool psArgumentParse(
+    psMetadata *arguments,             ///< metadata container for arguments
+    int *argc,                         ///< number of arguments
+    char **argv                        ///< the argument list
+);
+
+/** Prints to stdout a guide to the command-line arguments.      */
+void psArgumentHelp(
+    psMetadata *arguments              ///< metadata container for arguments
+);
+
+/** Prints to stdout a simplifed guide to the command-line arguments.      */
+void psArgumentHelpSimple(
+    FILE *stream,                      ///< FILE* to write too
+    psMetadata *arguments              ///< metadata container for arguments
+);
+
+/// @}
+#endif // #ifndef PS_ARGUMENTS_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psArray.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psArray.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psArray.c	(revision 22158)
@@ -0,0 +1,342 @@
+
+/** @file  psArray.c
+ *
+ *  @brief Contains support for basic vector types
+ *
+ *  This file defines the basic type for a vector struct and functions useful
+ *  in manupulating vectors.
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.67 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-29 21:48:53 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/******************************************************************************/
+
+/*  INCLUDE FILES                                                             */
+
+/******************************************************************************/
+#include<stdlib.h>                         // for qsort, etc.
+#include<string.h>
+
+#include "psMemory.h"
+#include "psError.h"
+#include "psArray.h"
+#include "psLogMsg.h"
+#include "psAbort.h"
+#include "psAssert.h"
+#include "psSort.h"
+
+#define DEFAULT_ARRAY_ADD 10            // Default number to add to an array when not specified
+
+/*****************************************************************************
+  FUNCTION IMPLEMENTATION - LOCAL
+ *****************************************************************************/
+static void arrayFree(psArray* psArr);
+
+static void arrayFree(psArray* psArr)
+{
+    psArrayElementsFree(psArr);
+
+    psFree(psArr->data);
+}
+
+bool psMemCheckArray(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)arrayFree );
+}
+
+// Allocate an array, deliberately leave size unset.
+static psArray *arrayAlloc(const char *file,
+                           unsigned int lineno,
+                           const char *func,
+                           long nalloc)
+{
+    if (nalloc < 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Can't allocate a psArray of negative size.");
+        return NULL;
+    }
+
+    // Create vector struct
+    psArray *array = (psArray*)p_psAlloc(file, lineno, func, sizeof(psArray));
+    psMemSetDeallocator(array, (psFreeFunc)arrayFree);
+
+    P_PSARRAY_SET_NALLOC(array, nalloc);
+    // Create vector data array
+    array->data = psAlloc(nalloc * sizeof(psPtr));
+    memset(array->data, 0, sizeof(void*) * nalloc);  //set the initial values of data to NULL
+
+    return array;
+}
+
+/*****************************************************************************
+  FUNCTION IMPLEMENTATION - PUBLIC
+ *****************************************************************************/
+psArray* p_psArrayAlloc(const char *file,
+                        unsigned int lineno,
+                        const char *func,
+                        long nalloc)
+{
+    psArray *array = arrayAlloc(file, lineno, func, nalloc);
+    if (!array) {
+        return NULL;
+    }
+    array->n = nalloc;
+    return array;
+}
+
+psArray* p_psArrayAllocEmpty(const char *file,
+                             unsigned int lineno,
+                             const char *func,
+                             long nalloc)
+{
+    psArray *array = arrayAlloc(file, lineno, func, nalloc);
+    if (!array) {
+        return NULL;
+    }
+    array->n = 0;
+    return array;
+}
+
+psArray* p_psArrayRealloc(const char *file,
+                          unsigned int lineno,
+                          const char *func,
+                          psArray* in,
+                          long nalloc)
+{
+    PS_ASSERT_ARRAY_NON_NULL(in, NULL);
+    if (nalloc < 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Can't reallocate a psArray to negative size.");
+        return in;
+    }
+
+    if (in->nalloc != nalloc) {     // No need to realloc to same size
+        if (nalloc < in->n) {
+            for (long i = nalloc; i < in->n; i++) {      // For reduction in vector size
+                psFree(in->data[i]);
+            }
+            in->n = nalloc;
+        }
+        // Realloc after decrementation to avoid accessing freed array elements
+        long n = in->n;
+        in->data = p_psRealloc(file, lineno, func, in->data, nalloc * sizeof(psPtr));
+        P_PSARRAY_SET_NALLOC(in,nalloc);
+        for (long m = n; m < nalloc; m++) { //if array is grown, set grown data to NULL
+            in->data[m] = NULL;
+        }
+    }
+
+    return in;
+}
+
+psArray* p_psArrayAdd(const char *file, unsigned int lineno, const char *func,
+                      psArray* array, long delta, psPtr data)
+{
+    if (array == NULL) {
+        long d = (delta > 0) ? delta : DEFAULT_ARRAY_ADD;
+        array = p_psArrayAlloc(file, lineno, func, d);
+        array->n = 0;
+    }
+
+    int n = array->n;
+
+    if (n >= array->nalloc) {
+        // array needs to be expanded to make room for more elements
+        long d = (delta > 0) ? delta : DEFAULT_ARRAY_ADD;
+        array = p_psArrayRealloc(file, lineno, func, array, n+d);
+    }
+
+    // add the element to the end of the array.
+    array->data[n] = psMemIncrRefCounter(data);
+    array->n = n+1;
+
+    return array;
+}
+
+// drop an item from the array and free it
+bool psArrayRemoveData(psArray* array,
+                       const psPtr data)
+{
+    PS_ASSERT_ARRAY_NON_NULL(array, false);
+    PS_ASSERT_PTR_NON_NULL(data, false);
+
+    bool success = false;
+    long n = array->n;
+    psPtr *arrayData = array->data;
+    for (long i = n-1; i >= 0; i--) {
+        if (arrayData[i] == data) {
+            memmove(&arrayData[i],&arrayData[i+1],(n-i-1)*sizeof(psPtr));
+            psFree(data); // Free the removed item
+            n--;
+            success = true;
+        }
+    }
+    array->n = n; // reset the array size to indicate the removed item(s)
+
+    return success;
+}
+
+// drop an item from the array and do not free it: this
+// can be useful in the free function of a data type
+// with a reference on another structure
+bool psArrayRemoveDataNoFree(psArray* array,
+                             const psPtr data)
+{
+    PS_ASSERT_ARRAY_NON_NULL(array, false);
+    PS_ASSERT_PTR_NON_NULL(data, false);
+
+    bool success = false;
+    long n = array->n;
+    psPtr *arrayData = array->data;
+    for (long i = n-1; i >= 0; i--) {
+        if (arrayData[i] == data) {
+            memmove(&arrayData[i],&arrayData[i+1],(n-i-1)*sizeof(psPtr));
+            n--;
+            success = true;
+        }
+    }
+    array->n = n; // reset the array size to indicate the removed item(s)
+
+    return success;
+}
+
+bool psArrayRemoveIndex(psArray* array,
+                        long index)
+{
+    PS_ASSERT_ARRAY_NON_NULL(array, false);
+    if (index < 0 || index >= array->n) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Specified index outside the range of elements in the array."));
+        return false;
+    }
+
+    long i = index;
+    long n = array->n;
+    psFree(array->data[i]);
+    memmove(&array->data[i], &array->data[i + 1], (n - i - 1) * sizeof(psPtr));
+    array->n--;    // reset the array size to indicate the removed item
+
+    return true;
+}
+
+void psArrayElementsFree(psArray* array)
+{
+    if (array == NULL) {
+        return;
+    }
+
+    for (long i = 0; i < array->n; i++) {
+        psFree(array->data[i]);
+        array->data[i] = NULL;
+    }
+
+    array->n = 0;
+}
+
+// Comparison and swap functions for sorting index into array
+#define PSARRAY_SORT_COMPARE_INDEX(A,B) (func(array[index[A]], array[index[B]]) < 0)
+#define PSARRAY_SORT_SWAP_INDEX(TYPE,A,B) { \
+    if (A != B) { \
+        ps##TYPE temp = index[A]; \
+        index[A] = index[B]; \
+        index[B] = temp; \
+    } \
+}
+
+// Heap sort of the index array
+psVector *psArraySortIndex (psVector *out, psArray *in, psCompareFunc func) {
+
+    if (in == NULL) {
+        return NULL;
+    }
+
+    out = psVectorCreate(out, 0, in->n, 1, PS_TYPE_S32);
+    psS32 *index = out->data.S32;       // Dereference index vector
+    psPtr *array = in->data;            // Dereference input array
+    PSSORT(out->n, PSARRAY_SORT_COMPARE_INDEX, PSARRAY_SORT_SWAP_INDEX, S32);
+    return out;
+}
+
+psArray* psArraySort(psArray* array,
+                     psComparePtrFunc func)
+{
+    PS_ASSERT_ARRAY_NON_NULL(array, NULL);
+    qsort(array->data, array->n, sizeof(psPtr), (int (*)(const void* , const void*))func);
+    return array;
+}
+
+// Set an element in the array.
+bool psArraySet(psArray* array,                      ///< input array to set element in
+                long position,                      ///< the element position to set
+                psPtr data)                        ///< the value to set it to
+{
+    PS_ASSERT_ARRAY_NON_NULL(array, false);
+
+    if (position > array->n)
+    {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "Specified position, %ld, is greater than n+1 of the array, %ld.",
+                position, array->n);
+        return false;
+    }
+
+    if (position < 0) {
+        position += array->n;
+    }
+    if (position < 0) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Invalid position.  Negative number too large\n");
+        return false;
+    }
+
+    if (position == array->n) {
+        if (position >= array->nalloc) {
+            psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                    _("Specified position, %ld, is greater than the allocated size of the array, %ld."),
+                    position, array->nalloc);
+            return false;
+        }
+        array->n++;
+    }
+    psFree(array->data[position]);
+    array->data[position] = psMemIncrRefCounter(data);
+
+    return true;
+}
+
+// Get an element in the array.
+psPtr psArrayGet(const psArray* array,
+                 long position )
+{
+    PS_ASSERT_ARRAY_NON_NULL(array, NULL);
+
+    if (position >= array->n) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "Specified position, %ld, is greater than n+1 of the array, %ld.",
+                position, array->n);
+        return NULL;
+    }
+    if (position < 0)
+        position += array->n;
+    if (position < 0) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Invalid position.  Negative number too large\n");
+        return NULL;
+    }
+    return (array->data[position]);
+}
+
+long psArrayLength(const psArray *array)
+{
+    PS_ASSERT_ARRAY_NON_NULL(array, -1);
+    return (array->n);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psArray.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psArray.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psArray.h	(revision 22158)
@@ -0,0 +1,314 @@
+/** @file  psArray.h
+ *
+ *  @brief Contains basic array definitions and operations
+ *
+ *  This file defines the basic type for a array struct and functions useful
+ *  in manupulating arrays.
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Ross Harman, MHPCC
+ *  @author Joshua Hoblitt, University of Hawaii
+ *
+ *  @version $Revision: 1.52 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-05 23:42:46 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_ARRAY_H
+#define PS_ARRAY_H
+
+#include "psType.h"
+#include "psCompare.h"
+#include "psVector.h"
+
+/// @addtogroup DataContainer Data Containers
+/// @{
+
+/** An array to support primitive types.
+ *
+ * Struct for maintaining an array of frequently used primitive types.
+ *
+ */
+typedef struct
+{
+    long n;                            ///< Number of elements in use.
+    const long nalloc;                 ///< Total number of elements available.
+    psPtr* data;                       ///< An Array of pointer elements
+    void *lock;                        ///< Optional lock for thread safety
+}
+psArray;
+
+#define P_PSARRAY_SET_NALLOC(vec,n) *(long*)&vec->nalloc = n
+
+/*****************************************************************************/
+
+/* FUNCTION PROTOTYPES                                                       */
+
+/*****************************************************************************/
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr
+ *  datatype.
+ *
+ *  @return bool:       True if the pointer matches a psArray structure, false
+ *  otherwise.
+ */
+bool psMemCheckArray(
+    psPtr ptr                          ///< the pointer whose type to check
+)
+;
+
+
+/** Allocate an array, set the length to the number of allocated elements
+ *
+ * Uses psLib memory allocation functions to create an array collection of
+ * data
+ *
+ * @return psArray* : Pointer to psArray.
+ *
+ */
+#ifdef DOXYGEN
+psArray* psArrayAlloc(
+    long nalloc                         ///< Total number of elements to make available.
+);
+#else // ifdef DOXYGEN
+psArray* p_psArrayAlloc(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    long nalloc                         ///< Total number of elements to make available.
+) PS_ATTR_MALLOC;
+#define psArrayAlloc(nalloc) \
+      p_psArrayAlloc(__FILE__, __LINE__, __func__, nalloc)
+#endif // ifdef DOXYGEN
+
+
+/** Allocate an array, set the length to zero.
+ *
+ * Uses psLib memory allocation functions to create an array collection of
+ * data
+ *
+ * @return psArray* : Pointer to psArray.
+ *
+ */
+#ifdef DOXYGEN
+psArray* psArrayAllocEmpty(
+    long nalloc                         ///< Total number of elements to make available.
+);
+#else // ifdef DOXYGEN
+psArray* p_psArrayAllocEmpty(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    long nalloc                         ///< Total number of elements to make available.
+);
+#define psArrayAllocEmpty(nalloc) \
+      p_psArrayAllocEmpty(__FILE__, __LINE__, __func__, nalloc)
+#endif // ifdef DOXYGEN
+
+
+/** Reallocate an array.
+ *
+ * Uses psLib memory allocation functions to reallocate an array collection
+ * of data.
+ *
+ * @return psArray* : Pointer to psArray.
+ *
+ */
+#ifdef DOXYGEN
+psArray* psArrayRealloc(
+    psArray* array,                    ///< array to reallocate.
+    long nalloc                        ///< Total number of elements to make available.
+);
+#else // ifdef DOXYGEN
+psArray* p_psArrayRealloc(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psArray* array,                    ///< array to reallocate.
+    long nalloc                        ///< Total number of elements to make available.
+);
+#define psArrayRealloc(array, nalloc) \
+      p_psArrayRealloc(__FILE__, __LINE__, __func__, array, nalloc)
+#endif // ifdef DOXYGEN
+
+
+/** Add an element to the end the array, expanding the array storage if
+ *  necessary.
+ *
+ *  If delta < 1, then 10 is used.
+ *
+ *  @return psArray*        The array with the element added
+ */
+psArray* psArrayAdd(
+    psArray* array,                    ///< array to operate on
+    long delta,                        ///< the amount to expand array, if necessary.
+    psPtr data                         ///< the data pointer to add to psArray
+);
+#ifdef DOXYGEN
+psArray* psArrayAdd(
+    psArray* array,                    ///< array to operate on
+    long delta,                        ///< the amount to expand array, if necessary.
+    psPtr data                         ///< the data pointer to add to psArray
+);
+#else // ifdef DOXYGEN
+psArray* p_psArrayAdd(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psArray* array,                     ///< array to operate on
+    long delta,                         ///< the amount to expand array, if necessary.
+    psPtr data                          ///< the data pointer to add to psArray
+) PS_ATTR_MALLOC;
+#define psArrayAdd(array, delta, data) \
+      p_psArrayAdd(__FILE__, __LINE__, __func__, array, delta, data)
+#endif // ifdef DOXYGEN
+
+
+/** Remove an element from the array by it's pointer
+ *
+ *  Finds and removes the specified data pointer from the list.
+ *
+ * @return bool:  TRUE if the specified data pointer was found and removed,
+ *                otherwise FALSE.
+ *
+ */
+bool psArrayRemoveData(
+    psArray* array,                    ///< array to operate on
+    const psPtr data                   ///< the data pointer to remove from psArray
+);
+
+
+/** Remove an element from the array by it's pointer WITHOUT freeing
+ *
+ *  Finds and removes the specified data pointer from the list, but does not free it
+ *
+ * @return bool:  TRUE if the specified data pointer was found and removed,
+ *                otherwise FALSE.
+ *
+ */
+bool psArrayRemoveDataNoFree(
+    psArray* array,                    ///< array to operate on
+    const psPtr data                   ///< the data pointer to remove from psArray
+);
+
+
+/** Remove an element from the array
+ *
+ *  Finds and removes the elements as the specified position
+ *
+ * @return bool:  TRUE if the specified data pointer was found and removed,
+ *                otherwise FALSE.
+ *
+ */
+bool psArrayRemoveIndex(
+    psArray* array,                    ///< array to operate on
+    long index                      ///< the element to remove
+);
+
+
+/** Deallocate/Dereference elements of an array.
+ *
+ * Uses psLib memory allocation functions to deallocate/dereference elements
+ * of a array of void pointers.  The array psArr is not freed, and its elements
+ * will all be set to NULL.  Additionaly, the array size (n) is set to zero.
+ *
+ */
+void psArrayElementsFree(
+    psArray* array                     ///< Void pointer array to destroy.
+);
+
+
+/** Sort the array according to an external compare function.
+ *
+ *  Sorts an array via the specification of a comparison function
+ *  to specify how the objects on the array should be sorted.
+ *
+ *  The comparison function must return an integer less than, equal to, or
+ *  greater than zero if the first argument is considered to be respectively
+ *  less than, equal to, or greater than the second.
+ *
+ *  If two members compare as equal, their order in the sorted array is
+ *  undefined.
+ *
+ *  @return psArray* The sorted array.
+ */
+psArray* psArraySort(
+    psArray* array,                       ///< input array to sort.
+    psComparePtrFunc func                 ///< the compare function
+);
+
+// return the index which sorts the array
+psVector *psArraySortIndex (psVector *outIndex, psArray *in, psCompareFunc func);
+
+/** Set an element in the array.  If the current element is non-NULL, the old
+ *  element is freed.
+ *
+ *  @return bool  TRUE if the element was set successfully, otherwise FALSE
+ */
+bool psArraySet(
+    psArray* array,                    ///< input array to set element in
+    long position,                     ///< the element position to set
+    psPtr data                         ///< the value to set it to
+);
+
+
+/** Get an element from the array.
+ *
+ *  @return void*   the element at given position.
+ */
+psPtr psArrayGet(
+    const psArray* array,              ///< input array to get element from
+    long position                      ///< the element position to get
+);
+
+
+/** Get the number of elements in use from a specified psArray. (array.n)
+ *
+ *  @return long:       The number of elements in use.
+ */
+long psArrayLength(
+    const psArray *array               ///< input psArray
+);
+
+
+// Some assertions
+
+#define PS_ASSERT_ARRAY_NON_NULL(NAME, RETURNVAL) PS_ASSERT_GENERAL_ARRAY_NON_NULL(NAME, return RETURNVAL)
+#define PS_ASSERT_GENERAL_ARRAY_NON_NULL(NAME, CLEANUP) \
+if ((NAME) == NULL || (NAME)->data == NULL || (NAME)->n < 0) { \
+    psError(PS_ERR_BAD_PARAMETER_NULL, true, \
+            "Unallowable operation: psArray %s or its data is NULL.", \
+            #NAME); \
+    CLEANUP; \
+} \
+
+#define PS_ASSERT_ARRAY_NON_EMPTY(NAME, RETURNVAL) PS_ASSERT_GENERAL_ARRAY_NON_EMPTY(NAME, return RETURNVAL)
+#define PS_ASSERT_GENERAL_ARRAY_NON_EMPTY(NAME, CLEANUP) \
+if ((NAME)->n < 1) { \
+    psError(PS_ERR_BAD_PARAMETER_SIZE, true, \
+            "Unallowable operation: psArray %s has no elements.", \
+            #NAME); \
+    CLEANUP; \
+} \
+
+#define PS_ASSERT_ARRAYS_SIZE_EQUAL(ARRAY1, ARRAY2, RVAL) \
+if ((ARRAY1)->n != (ARRAY2)->n) { \
+    psError(PS_ERR_BAD_PARAMETER_SIZE, true, \
+            "psArray %s has size %ld, psArray %s has size %ld.", \
+            #ARRAY1, (ARRAY1)->n, #ARRAY2, (ARRAY2)->n); \
+    return(RVAL); \
+}
+
+#define PS_ASSERT_ARRAY_SIZE(ARRAY, SIZE, RVAL) \
+if ((ARRAY)->n != (SIZE)) { \
+    psError(PS_ERR_BAD_PARAMETER_SIZE, true, \
+            "psArray %s has size %ld instead of expected size %ld.", \
+            #ARRAY, (ARRAY)->n, SIZE); \
+    return RVAL; \
+}
+
+/// @}
+#endif // #ifndef PS_ARRAY_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psBitSet.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psBitSet.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psBitSet.c	(revision 22158)
@@ -0,0 +1,303 @@
+/** @file  psBitSet.c
+ *
+ *  @brief Creates an array of bytes of arbitrary length for storing individual bits.
+ *
+ *  Bit masks are useful tools for toggling various flags and options. This set of functions module provides
+ *  a mechanism to create an array of bits of arbitrary length and manipulate them with basic binary
+ *  operations. A print function is also provided to display the entire set of bits in binary format as a
+ *  string.
+ *
+ *  @author Ross Harman, MHPCC
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.42 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-08-09 03:30:16 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+
+#include "psBitSet.h"
+#include "psMemory.h"
+#include "psError.h"
+#include "psAbort.h"
+#include "psString.h"
+#include "psAssert.h"
+
+
+
+enum {
+    UNKNOWN_OP,
+    AND_OP,
+    OR_OP,
+    XOR_OP,
+    NOT_OP
+};
+
+static void bitSetFree(psBitSet* inBitSet);
+
+/** Private function to create a mask.
+ *
+ *  Creates an eight bit mask with the given bit set. All other bits in the byte are zero. The input bit uses
+ *  zero-based indexing, and is the cumulitive index within the array, not the localized byte's bit position.
+ *
+ *  @return  char*: Pointer to byte in which bit is contained.
+ */
+PS_ATTR_PURE static char mask(psS32 bit)
+{
+    char mask = (char)0x01;
+
+    // Ignore splint warning about negative bit shifts
+    /* @i@ */
+    mask = mask << (bit % 8);
+
+    return mask;
+}
+
+static void bitSetFree(psBitSet* inBitSet)
+{
+    psFree(inBitSet->bits);
+}
+
+bool psMemCheckBitSet(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)bitSetFree );
+}
+
+
+psBitSet* p_psBitSetAlloc(const char *file,
+                          unsigned int lineno,
+                          const char *func,
+                          long nalloc)
+{
+    if (nalloc < 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("The number of bit in a psBitSet (%ld) must be greater than zero."),
+                nalloc);
+        return NULL;
+    }
+
+    psS32 numBytes = 0;
+    psBitSet* newObj = NULL;
+
+    numBytes = ceil(nalloc / 8.0);
+    newObj = p_psAlloc(file, lineno, func, sizeof(psBitSet));
+    psMemSetDeallocator(newObj, (psFreeFunc) bitSetFree);
+    newObj->n = numBytes;
+
+    // Ignore splint warning about releasing pointer members, since they've not been allocated yet
+    /* @i@ */
+    newObj->bits = psAlloc(sizeof(char) * numBytes);
+
+    memset(newObj->bits, 0, numBytes);
+
+    return newObj;
+}
+
+
+bool psBitSetSet(psBitSet* bitSet,
+                      long bit)
+{
+    unsigned char *byte = NULL;
+
+    if (bitSet == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not operate on a NULL psBitSet."));
+        return false;
+    } else if ( (bit < 0) ||
+                (bit > bitSet->n * 8 - 1) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("The specified bit position (%ld) is invalid.  Position must be between 0 and %ld."),
+                bit, bitSet->n * 8 - 1);
+        return false;
+    }
+    // Variable byte is the byte in the array that contains the bit to be set
+    byte = bitSet->bits + bit / 8;
+    *byte |= mask(bit);
+
+    return true;
+}
+
+bool psBitSetClear(psBitSet* bitSet,
+                        long bit)
+{
+    unsigned char *byte = NULL;
+
+    if (bitSet == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not operate on a NULL psBitSet."));
+        return false;
+    } else if ( (bit < 0) ||
+                (bit > bitSet->n * 8 - 1) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("The specified bit position (%ld) is invalid.  Position must be between 0 and %ld."),
+                bit, bitSet->n * 8 - 1);
+        return false;
+    }
+    // Variable byte is the byte in the array that contains the bit to be set
+    byte = bitSet->bits + bit / 8;
+    *byte &= ! mask(bit);
+
+    return true;
+}
+
+bool psBitSetTest(const psBitSet* bitSet,
+                  long bit)
+{
+    unsigned char *byte = NULL;
+
+    if (bitSet == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Can not operate on a NULL psBitSet."));
+        return false;
+    } else if ( (bit < 0) ||
+                (bit > bitSet->n * 8 - 1) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("The specified bit position (%ld) is invalid.  Position must be between 0 and %ld."),
+                bit,bitSet->n * 8 - 1);
+        return false;
+    }
+
+    // Variable byte is the byte in the array that contains the bit to be tested
+    byte = bitSet->bits + bit / 8;
+    return ((*byte & mask(bit)) != 0);
+}
+
+psBitSet* psBitSetOp(psBitSet* outBitSet,
+                     const psBitSet* inBitSet1,
+                     const char *operator,
+                     const psBitSet* inBitSet2)
+{
+    if (inBitSet1 == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("First psBitSet operand can not be NULL."));
+        psFree(outBitSet);
+        return NULL;
+    }
+    if (operator == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Specified operator is NULL.  Must specify desired operator."));
+        psFree(outBitSet);
+        return NULL;
+    }
+    psS32 i = 0;
+    psS32 n = 0;
+    unsigned char* outBits = NULL;
+    unsigned char* inBits1 = NULL;
+    unsigned char* inBits2 = NULL;
+    psS32 op = UNKNOWN_OP;
+
+    inBits1 = inBitSet1->bits;
+
+
+    // parse the operator
+    if (strcmp(operator,"AND")==0) {
+        op = AND_OP;
+    } else if (strcmp(operator,"OR")==0) {
+        op = OR_OP;
+    } else if (strcmp(operator,"XOR")==0) {
+        op = XOR_OP;
+    } else if (strcmp(operator,"NOT")==0) {
+        op = NOT_OP;
+    } else {
+        psFree(outBitSet);
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified operator, %s, is invalid.  Valid operators are AND, OR, and XOR."),
+                operator);
+        return NULL;
+    }
+
+    if (op != NOT_OP) {
+        if (inBitSet2 == NULL) {
+            psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                    _("Second psBitSet operand can not be NULL."));
+            psFree(outBitSet);
+            return NULL;
+        }
+
+        if (inBitSet1->n != inBitSet2->n) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    _("The psBitSet operand must be the same size."));
+            psFree(outBitSet);
+            return NULL;
+        }
+        inBits2 = inBitSet2->bits;
+    }
+
+    if (outBitSet == NULL) {
+        outBitSet = psBitSetAlloc(inBitSet1->n*8);
+    } else if (outBitSet->n != inBitSet1->n) {
+        outBitSet->n = inBitSet1->n;
+        outBitSet->bits = psRealloc(outBitSet->bits, inBitSet1->n);
+    }
+
+    n = outBitSet->n;
+    outBits = outBitSet->bits;
+
+    switch (op) {
+    case AND_OP:
+        for (i = 0; i < n; i++) {
+            outBits[i] = inBits1[i] & inBits2[i];
+        }
+        break;
+    case OR_OP:
+        for (i = 0; i < n; i++) {
+            outBits[i] = inBits1[i] | inBits2[i];
+        }
+        break;
+    case XOR_OP:
+        for (i = 0; i < n; i++) {
+            outBits[i] = inBits1[i] ^ inBits2[i];
+        }
+        break;
+    case NOT_OP:
+    default:
+        for (i = 0; i < n; i++) {
+            outBits[i] = ~inBits1[i];
+        }
+        break;
+    }
+
+    return outBitSet;
+}
+
+psBitSet* psBitSetNot(psBitSet* outBitSet,
+                      const psBitSet* inBitSet)
+{
+    if (inBitSet == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Operand can not be NULL."));
+        psFree(outBitSet);
+        return NULL;
+    }
+
+    outBitSet = psBitSetOp(outBitSet,inBitSet,"NOT",NULL);
+
+    return outBitSet;
+}
+
+psString psBitSetToString(const psBitSet* bitSet)
+{
+    PS_ASSERT_PTR_NON_NULL(bitSet, NULL);
+    psS32 i = 0;
+    psS32 numBits = bitSet->n * 8;
+    //    char *outString = psAlloc((size_t) numBits + 1);
+    psString outString = psStringAlloc(numBits + 1);
+
+    for (i = 0; i < numBits; i++) {
+        outString[numBits - i - 1] = psBitSetTest(bitSet, i) ? '1' : '0';
+    }
+
+    outString[numBits] = 0;
+
+    return outString;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psBitSet.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psBitSet.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psBitSet.h	(revision 22158)
@@ -0,0 +1,174 @@
+/** @file  psBitSet.h
+ *
+ *  @brief Creates an array of bytes of arbitrary length for storing individual bits.
+ *
+ *  Bit masks are useful tools for toggling various flags and options. This set of functions module provides
+ *  a mechanism to create an array of bits of arbitrary length and manipulate them with basic binary
+ *  operations. A print function is also provided to display the entire set of bits in binary format as a
+ *  string.
+ *
+ *  @author PAP, EAM, IfA
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.31 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-08-09 01:40:08 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PSBITSET_H
+#define PSBITSET_H
+
+#include "psType.h"
+
+/// @addtogroup DataContainer Data Containers
+/// @{
+
+/******************************************************************************/
+/*  TYPE DEFINITIONS                                                          */
+/******************************************************************************/
+
+/** Struct containing array of bytes to hold bit data and corresponding array length.
+ *
+ *  The bits in the struct are assembled in as an array of bytes with eight bits per
+ *  byte. The bits are arranged with the LSB in first (right most) position of the
+ *  first array element.
+ */
+typedef struct
+{
+    long n;                            ///< Number of bytes in the array
+    psU8 *bits;                        ///< Aray of bytes holding bits
+    void *lock;                        ///< Optional lock for thread safety
+}
+psBitSet;
+
+/*****************************************************************************/
+/* FUNCTION PROTOTYPES                                                       */
+/*****************************************************************************/
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr
+ *  datatype.
+ *
+ *  @return bool:     True if the pointer matches a psBitSet structure, false otherwise.
+ */
+bool psMemCheckBitSet(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+
+/** Allocate a psBitSet.
+ *
+ *  Create a psBitSet with the number of bits specified by the user. All bits
+ *  are set to zero upon allocation.
+ *
+ *  @return  psBitSet* : Pointer to struct containing array of bits and size of array.
+ */
+#ifdef DOXYGEN
+psBitSet* psBitSetAlloc(
+    long nalloc                        ///< Number of bits in psBitSet array
+);
+#else // ifdef DOXYGEN
+psBitSet* p_psBitSetAlloc(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    long nalloc                        ///< Number of bits in psBitSet array
+) PS_ATTR_MALLOC;
+#define psBitSetAlloc(nalloc) \
+      p_psBitSetAlloc(__FILE__, __LINE__, __func__, nalloc)
+#endif // ifdef DOXYGEN
+
+
+
+
+/** Set a bit.
+ *
+ *  Sets a bit at a given bit location. The bit is set based on a zero index
+ *  with the first bit set in the zero bit slot of the zero element of the byte
+ *  array. As an example, setting bit 3 in an array with two elements would
+ *  result in an psBitSet that looks like 00000000 00001000.
+ *
+ *  @return  bool : Successful operation?
+ */
+bool psBitSetSet(
+    psBitSet* bitSet,                  ///< Pointer to psBitSet to be set.
+    long bit                           ///< Bit to be set.
+);
+
+
+/** Clear a bit.
+ *
+ *  Clear a bit at a given bit location. The bit is cleared based on a zero
+ *  index with the first bit set in the zero bit slot of the zero element of
+ *  the byte array.
+ *
+ *  @return  bool : Successful operation?
+ */
+bool psBitSetClear(
+    psBitSet* bitSet,                  ///< Pointer to psBitSet to be cleared.
+    long bit                           ///< Bit to be cleared.
+);
+
+
+/** Test the value of a bit.
+ *
+ *  Prints the value of a bit at a given bit location, either one or zero. The
+ *  resulting bit is based on a zero index format with the first bit set in the
+ *  zero bit slot of the zero element of the byte array.  As an example,
+ *  testing bit 3 in a psBitSet with two bytes that looks like 00000000
+ *  00001000 would return a value of one, since that is the value that was set.
+ *
+ *  @return  bool:      True if successful, otherwise false
+ */
+bool psBitSetTest(
+    const psBitSet* bitSet,            ///< Pointer psBitSet to be tested.
+    long bit                           ///< Bit to be tested.
+);
+
+
+/** Perform a binary operation on two psBitSets
+ *
+ *  Perform an AND, OR, or XOR on two psBitSets. If the BitMasks are not the
+ *  same size, the operation will not be performed and an error message will be
+ *  logged.
+ *
+ *  @return  psBitSet* : Pointer to struct containing result of binary operation.
+ */
+psBitSet* psBitSetOp(
+    psBitSet* outBitSet,               ///< Resulting psBitSet from binary operation
+    const psBitSet* inBitSet1,         ///< First psBitSet on which to operate
+    const char *operator,              ///< Bit operation
+    const psBitSet* inBitSet2          ///< Second psBitSet on which to operate
+);
+
+
+/** Perform a not operation on a psBitSet
+ *
+ *  Toggles bits in a psBitset. All zero bits are set to one and all one bits
+ *  are set to zero.
+ *
+ *  @return  psBitSet* : Pointer to struct containing result of operation.
+ */
+psBitSet* psBitSetNot(
+    psBitSet* outBitSet,               ///< Resulting psBitSet from operation
+    const psBitSet* inBitSet           ///< Input psBitSet
+);
+
+
+/** Convert the psBitSet to a string of ones and zeros.
+ *
+ *  Converts the contents of a psBitSet to a string representation of its
+ *  binary form of ones and zeros. The LSB is the right-most chracter. Each set
+ *  of eight characters represents one byte.
+ *
+ *  @return  psString:      Pointer to character array containing string data.
+ */
+psString psBitSetToString(
+    const psBitSet* bitSet             ///< psBitSet to convert
+);
+
+
+/// @}
+#endif // #ifndef PSBITSET_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psHash.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psHash.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psHash.c	(revision 22158)
@@ -0,0 +1,428 @@
+
+/** @file  psHash.c
+*
+*  @brief Contains support for basic hashing functions.
+*
+*  This file will hold the functions for defining a hash table with arbitrary
+*  data types, allocating/deallocating that hash table, adding and removing
+*  data from that hash table, and listing all keys defined in the hash table.
+*
+*  @author Robert Lupton, Princeton University
+*  @author Robert DeSonia, MHPCC
+*  @author GLG, MHPCC
+*
+*  @version $Revision: 1.43 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2008-04-17 23:43:03 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "psAbort.h"
+#include "psHash.h"
+#include "psMemory.h"
+#include "psString.h"
+#include "psTrace.h"
+#include "psError.h"
+#include "psAssert.h"
+
+
+
+static psHashBucket* hashBucketAlloc(const char *key, psPtr data, psHashBucket* next);
+static void hashBucketFree(psHashBucket* bucket);
+static psPtr doHashWork(psHash* table, const char *key, psPtr data, bool remove);
+static void hashFree(psHash* table);
+
+/******************************************************************************
+psHashKeyList(table): this function creates a linked list with an entry in
+that list for every key in the hash table.
+Inputs:
+    table: a hash table
+Return;
+    The linked list
+ *****************************************************************************/
+psList* psHashKeyList(const psHash* hash)
+{
+    PS_ASSERT_HASH_NON_NULL(hash, NULL);
+
+    psList* myLinkList = NULL;  // The output data structure
+    psHashBucket* ptr = NULL;   // Used to step thru linked list.
+
+    // Create the linked list
+    myLinkList = psListAlloc(NULL);
+
+    // Loop through every bucket in the hash table.  If that bucket is not
+    // NULL, then add the bucket's key to the linked list.
+    for (long i = 0; i < hash->n; i++) {
+        if (hash->buckets[i] != NULL) {
+            // Since a bucket contains a linked list of keys/data, we must
+            // step trough each key in that linked list:
+
+            ptr = hash->buckets[i];
+            while (ptr != NULL) {
+                psListAdd(myLinkList, PS_LIST_HEAD, ptr->key);
+                ptr = ptr->next;
+            }
+        }
+    }
+
+    // Return the linked list
+    return (myLinkList);
+}
+
+/******************************************************************************
+hashBucketAlloc(key, data, next): This procedure creates a new hash bucket
+with the specified key, data, and next.
+Inputs:
+    key:  the new bucket's key pointer
+    data: the new bucket's data pointer
+    next: the new bucket's key pointer
+Return:
+    the new hash bucket.
+ *****************************************************************************/
+static psHashBucket* hashBucketAlloc(const char *key,
+                                     psPtr data,
+                                     psHashBucket* next)
+{
+    psAssert(key && strlen(key) > 0, "impossible");
+
+    // Allocate memory for the new hash bucket.
+    psHashBucket* bucket = psAlloc(sizeof(psHashBucket));
+
+    psMemSetDeallocator(bucket, (psFreeFunc) hashBucketFree);
+
+    // Initialize the bucket.
+    bucket->key = psStringCopy(key);
+
+    //XXX:  Since this function is static and only called by doHashWork,
+    //data can never be NULL here.
+    //    if (data == NULL) {
+    // NOTE: Should we flag a warning message?
+    //        bucket->data = NULL;
+    //    } else {
+    bucket->data = psMemIncrRefCounter(data);
+    //    }
+
+    bucket->next = next;
+
+    return bucket;
+}
+
+/******************************************************************************
+hashBucketFree(bucket): This procedure deallocates the specified
+hash bucket.
+Inputs:
+    bucket: the hash bucket to be freed.
+Return:
+    NONE
+ *****************************************************************************/
+static void hashBucketFree(psHashBucket* bucket)
+{
+    psFree(bucket->key);
+    psFree(bucket->data);
+}
+
+/******************************************************************************
+psHashAlloc(n): this procedure creates a new hash table with the
+specified number of buckets.
+Inputs:
+    n: initial number of buckets
+Return:
+    The new hash table.
+ *****************************************************************************/
+psHash* p_psHashAlloc(const char *file,
+                      unsigned int lineno,
+                      const char *func,
+                      long nalloc)        // initial number of buckets
+{
+    if (nalloc < 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Can't allocate a psHash of negative size.");
+        return NULL;
+    }
+
+    // Create the new hash table.
+    psHash* table = p_psAlloc(file, lineno, func, sizeof(psHash));
+
+    psMemSetDeallocator(table, (psFreeFunc) hashFree);
+
+    // Allocate memory for the buckets.
+    table->buckets = psAlloc(nalloc * sizeof(psHashBucket* ));
+    table->n = nalloc;
+
+    psTrace("psLib.types", 1, "Creating %ld-element hash table\n", nalloc);
+
+    // Initialize all buckets to NULL.
+    for (long i = 0; i < nalloc; i++) {
+        table->buckets[i] = NULL;
+    }
+
+    // Return the new hash table.
+    return table;
+}
+
+
+bool psMemCheckHash(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)hashFree );
+}
+
+
+/******************************************************************************
+hashFree(table): This procedure deallocates the specified hash
+table.  It loops through each bucket, and calls hashBucketFree() on that
+bucket.
+
+Inputs:
+    table: a hash table
+Return:
+    NONE
+ *****************************************************************************/
+static void hashFree(psHash* table)
+{
+    // Loop through each bucket in the hash table.  If that bucket is not
+    // NULL, then free the bucket via a function call to hashBucketFree();
+    for (long i = 0; i < table->n; i++) {
+        // A bucket is composed of a linked list of buckets.
+        while (table->buckets[i] != NULL) {
+            psHashBucket* bucket = table->buckets[i];
+            table->buckets[i] = bucket->next;
+            psFree(bucket);
+        }
+    }
+
+    // Free the bucket structure, then the hash table.
+    psFree(table->buckets);
+}
+
+/******************************************************************************
+doHashWork(table, key, data, remove): This is an internal
+procedure which does the bulk of the work in using the hash table.  Depending
+upon the input parameters, it will either insert a new key/data into the hash
+table, retrieve the data for a specified key, or remove a key/data item.  If
+we try to insert a key that already exists in the hash table, then we deallocate
+the existing data/key item.
+Inputs:
+    table: a hash table
+    key: the key to insert, retrieve, or remove.  Must not be NULL.
+    data: the data to insert, if not NULL
+    remove: set to non-zero if the key/data should be removed from the table.
+Return:
+    NONE
+
+NOTE: consider removing this private function and simply putting the code
+into the psHashInsert(), psHashLookup(), and psHashRemove().  Why?  Because
+there is little common code between those functions.
+  *****************************************************************************/
+static psPtr doHashWork(psHash* table,
+                        const char *key,
+                        psPtr data,
+                        bool remove
+                           )
+{
+    psAssert(table, "impossible");
+    psAssert(table->n >= 0, "impossible");
+    psAssert(key && strlen(key) > 0, "impossible");
+
+    if (table->n == 0) {
+        return NULL;
+    }
+
+    // This hash algorithm is from Sedgewick.  NOTE: must reread to ensure that
+    // the size of the hash table is not required to be a prime number.
+    char *tmpchar = (char *)key;        // Used in computing the hash function.
+    long hash;                          // The hash value
+    for (hash = 0; *tmpchar != '\0'; tmpchar++) {
+        hash = (64 * hash + *tmpchar) % (table->n);
+    }
+    psAssert(hash >= 0 && hash < table->n, "impossible");
+
+    // ptr will have the correct hash bucket.
+    psHashBucket *ptr = table->buckets[hash];   // Used to retrieve the hash bucket.
+    psHashBucket* optr = NULL;          // "original pointer": used to step thru the linked list for a bucket.
+
+    // We know the correct hash bucket, now we need to know what to do.
+    // If the data parameter is NULL, then, by definition, this is a retrieve
+    // or a remove operation on the hash table.
+
+    if (!data) {
+        if (remove) {
+            // We search through the linked list for this bucket in
+            // the hash table and look for an entry for this key.
+
+            optr = ptr;
+            while (ptr != NULL) {
+                // Determine if this entry holds the correct key.
+                if (strcmp(key, ptr->key) == 0) {
+                    // The following lines of code are fairly standard ways
+                    // of removing an item from a single-linked list.
+
+                    psPtr data = ptr->data;
+
+                    optr->next = ptr->next;
+                    if (ptr == table->buckets[hash]) {
+                        table->buckets[hash] = ptr->next;
+                    }
+                    psFree(ptr);
+
+                    // By definition, the data associated with that key
+                    // must be returned, not freed.
+                    return data;
+                }
+                optr = ptr;
+                ptr = ptr->next;
+            }
+            return NULL;                   // not in hash
+        }
+        else {
+            // If we get here, then a retrieve operation is requested.  So,
+            // we step trough the linked list at this bucket, and return the
+            // data once we find it, or return NULL if we don't.
+            while (ptr != NULL) {
+                if (strcmp(key, ptr->key) == 0) {
+                    return ptr->data;
+                }
+                ptr = ptr->next;
+            }
+            return NULL;                   // not in hash
+        }
+    } else {
+        // We get here if this procedure was called with non-NULL data.
+        // Therefore, we should insert that data into the hash table.
+        // First, we search through the linked list for this bucket in
+        // the hash table and look for a duplicate entry for this key.
+
+        while (ptr != NULL) {
+            if (strcmp(key, ptr->key) == 0) {
+                // We have found this key in the hash table.
+
+                psTrace("psLib.types", 3, "Replacing data for %s\n", key);
+
+                // NOTE: I have changed this behavior from the originally
+                // supplied code.  Formerly, if itemFree was NULL, then
+                // the new data was not inserted into the hash table.
+
+                psFree(ptr->data);
+
+                ptr->data = psMemIncrRefCounter(data);
+                return data;
+            }
+            ptr = ptr->next;
+        }
+        // We did not found key in the linked list for this bucket of the hash
+        // table.  So, we insert this data at the head of that linked list.
+
+        table->buckets[hash] = hashBucketAlloc(key, data, table->buckets[hash]);
+        return data;
+    }
+}
+
+/******************************************************************************
+psHashAdd(table, key, data): this procedure, which is part of
+the public API, inserts a new key/data pair into the hash table.
+Inputs:
+    table: a hash table
+    key: the key to use
+    data: the data to insert.
+Return:
+    boolean value defining success or failure
+ *****************************************************************************/
+bool psHashAdd(psHash* hash,
+               const char *key,
+               psPtr data)
+{
+    PS_ASSERT_HASH_NON_NULL(hash, false);
+    PS_ASSERT_STRING_NON_EMPTY(key, false);
+    PS_ASSERT_PTR_NON_NULL(data, false);
+
+    return (doHashWork(hash, key, data, false) != NULL);
+}
+
+/******************************************************************************
+psHashLookup(table, key): this procedure, which is part of the public API,
+looks up the specified key in the hash table and returns the data associated
+with that key.
+
+Inputs:
+    table: a hash table
+    key: the key to use
+Return:
+    The data associated with that key.
+ *****************************************************************************/
+psPtr psHashLookup(const psHash* hash,      // hash to lookup key in
+                   const char *key)     // key to lookup
+{
+    PS_ASSERT_HASH_NON_NULL(hash, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(key, NULL);
+
+    return doHashWork((psPtr)hash, key, NULL, false);
+}
+
+/******************************************************************************
+psHashRemove(table, key): this procedure, which is part of the
+public API, removes the specified key from the hash table.
+Inputs:
+    table: a hash table
+    key: the key to remove
+Return:
+    boolean value defining success or failure
+ *****************************************************************************/
+bool psHashRemove(psHash* hash,
+                  const char *key)
+{
+    PS_ASSERT_HASH_NON_NULL(hash, false);
+    PS_ASSERT_STRING_NON_EMPTY(key, false);
+
+    psPtr data = NULL;
+    bool retVal = false;
+
+    data = doHashWork(hash, key, NULL, true);
+    if (data != NULL) {
+        retVal = true;
+    } else {
+        retVal = false;
+    }
+
+    return retVal;
+}
+
+psArray* psHashToArray(const psHash* hash)
+{
+    PS_ASSERT_HASH_NON_NULL(hash, NULL);
+
+    // first, let's just count the number of data elements to know what size psArray we need to allocate.
+    int nElements = 0;
+    int nbucket = hash->n;
+    // XXX:  If we do psArrayAlloc(0) here and use psArrayAdd(result, 1, tmpBucket->data)
+    // we can eliminate the 2nd for loop below.
+    for (int i = 0; i < nbucket; i++) {
+        psHashBucket* tmpBucket = hash->buckets[i];
+        while (tmpBucket != NULL) {
+            nElements++;
+            tmpBucket = tmpBucket->next;
+        }
+    }
+
+    psArray* result = psArrayAlloc(nElements);
+
+    // now fill in the array with the hash hash's data
+    psPtr* data = result->data;
+    for (int i = 0; i < nbucket; i++) {
+        psHashBucket* tmpBucket = hash->buckets[i];
+        while (tmpBucket != NULL) {
+            *(data++) = psMemIncrRefCounter(tmpBucket->data);
+            tmpBucket = tmpBucket->next;
+        }
+    }
+
+    return result;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psHash.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psHash.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psHash.h	(revision 22158)
@@ -0,0 +1,124 @@
+/** @file  psHash.h
+ *
+ *  @brief Contains support for basic hashing functions.
+ *
+ *  This file will hold the prototypes for defining a hash table with arbitrary
+ *  data types, allocating/deallocating that has table, adding and removing
+ *  data from that hash table, and listing all keys defined in the hash table.
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author Robert DeSonia, MHPCC
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.24 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-08-09 01:40:08 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_HASH_H
+#define PS_HASH_H
+
+/// @addtogroup DataContainer Data Containers
+/// @{
+
+#include "psList.h"
+
+/** A bucket that holds an item of data. */
+typedef struct psHashBucket
+{
+    char *key;                         ///< The key for this item of data.
+    psPtr data;                        ///< The data itself.
+    struct psHashBucket* next;         ///< The list of other possible keys.
+}
+psHashBucket;
+
+
+//typedef struct HashTable psHash; ///< Opaque type for a hash table
+
+/** The hash-table itself. */
+typedef struct
+{
+    long n;                            ///< Number of buckets in hash table.
+    psHashBucket* *buckets;            ///< The bucket data.
+    void *lock;                        ///< Optional lock for thread safety.
+}
+psHash;
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr
+ *  datatype.
+ *
+ *  @return bool:       True if the pointer matches a psHash structure, false otherwise.
+ */
+bool psMemCheckHash(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+
+/// Allocate hash buckets in table.
+#ifdef DOXYGEN
+psHash* psHashAlloc(
+    long nalloc                        ///< The number of buckets to allocate.
+);
+#else // ifdef DOXYGEN
+psHash* p_psHashAlloc(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    long nalloc                        ///< The number of buckets to allocate.
+) PS_ATTR_MALLOC;
+#define psHashAlloc(nalloc) \
+      p_psHashAlloc(__FILE__, __LINE__, __func__, nalloc)
+#endif // ifdef DOXYGEN
+
+
+
+/// Insert entry into table.
+bool psHashAdd(
+    psHash* hash,                      ///< The table to insert in.
+    const char *key,                   ///< The key to use.
+    psPtr data                         ///< The data to insert.
+);
+
+
+/// Lookup key in table.
+psPtr psHashLookup(
+    const psHash* hash,                ///< The table to lookup key in.
+    const char *key                    ///< The key to lookup.
+);
+
+
+/// Remove key from table.
+bool psHashRemove(
+    psHash* hash,                      ///< The table to lookup key in.
+    const char *key                    ///< The key to lookup.
+);
+
+
+/// List all keys in table.
+psList* psHashKeyList(
+    const psHash* hash                 ///< The table to list keys from..
+);
+
+
+/** Create a psArray from a psHash contents.
+ *
+ *  @return psArray*       A new psArray with duplicate contents of the input psHash
+ */
+psArray* psHashToArray(
+    const psHash* hash                 ///< The table to convert to psArray.
+);
+
+
+#define PS_ASSERT_HASH_NON_NULL(NAME, RVAL) \
+if (!(NAME) || !(NAME)->buckets || (NAME)->n < 0) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: Hash %s or one of its components is NULL.", \
+            #NAME); \
+    return RVAL; \
+}
+
+/// @} End of DataContainer Functions
+#endif // #ifndef PS_HASH_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psList.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psList.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psList.c	(revision 22158)
@@ -0,0 +1,588 @@
+/** @file psList.c
+ *  @brief Support for doubly linked lists
+ *  @ingroup LinkedList
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author Robert Daniel DeSonia, MHPCC
+ *  @author Joshua Hoblitt, University of Hawaii
+ *
+ *  @version $Revision: 1.69.8.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-26 03:49:12 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "psError.h"
+#include "psAbort.h"
+#include "psMemory.h"
+#include "psList.h"
+#include "psTrace.h"
+#include "psLogMsg.h"
+#include "psAssert.h"
+
+
+#define ITER_INIT_HEAD ((psPtr )1)         // next iteration should return head
+#define ITER_INIT_TAIL ((psPtr )2)         // next iteration should return tail
+
+#define INITIAL_NUM_ITERATORS 16        // Initial number of iterators to create
+
+// private functions.
+static void listFree(psList* list);
+static void listIteratorFree(psListIterator* iter);
+static bool listIteratorRemove(psListIterator* iterator);
+
+static void listFree(psList* list)
+{
+    if (list->iterators != NULL) {
+
+        // remove the associated iterators -- any references are invalid once psList is freed.
+        psArray* iterators = list->iterators;
+        // ONLY orphan the iterators if the list iterators are about to be destroyed
+        // a case where this is not the case is in psListSort.
+        if (psMemGetRefCounter(iterators)  < 2) {
+            for (int i = 0; i < iterators->n; i++) {
+                // orphan iterators first to avoid any callbacks to dying list
+                ((psListIterator*)iterators->data[i])->list = NULL;
+            }
+        }
+        psFree(iterators);
+    }
+
+    for (psListElem* ptr = list->head; ptr != NULL;) {
+        psListElem* next = ptr->next;
+
+        psFree(ptr->data);
+        psFree(ptr);
+
+        ptr = next;
+    }
+}
+
+static void listIteratorFree(psListIterator* iter)
+{
+    // remove this iterator from the parent list
+    if (iter->list != NULL) {
+        psArray* iters = iter->list->iterators;
+        for (int lcv = 0; lcv < iters->n; lcv++) {
+            if (iters->data[lcv] == iter) {
+                // following is done to match SDRS.
+                iters->data[lcv] = iters->data[iters->n-1];
+                iters->n--;
+                break;
+            }
+        }
+    }
+}
+
+static bool listIteratorRemove(psListIterator* iterator)
+{
+    psAssert(iterator, "impossible");
+    if (iterator->cursor == NULL) {
+        return false;
+    }
+
+    psListElem* elem = iterator->cursor;
+    psList* list = iterator->list;
+    int index = iterator->index;
+
+    if (elem == list->head) {        // head of list?
+        list->head = elem->next;
+    } else {
+        elem->prev->next = elem->next;
+    }
+
+    if (elem == list->tail) {        // tail of list?
+        list->tail = elem->prev;
+    } else {
+        elem->next->prev = elem->prev;
+    }
+
+    psArray* iterators = list->iterators;
+    for (int i = 0; i < iterators->n; i++) {
+        psListIterator* iter = (psListIterator*) iterators->data[i];
+        if (iter->cursor == elem) {
+            iter->cursor = NULL;
+        } else if (iter->index > index && iter->index > 0) {
+            iter->index--;
+        }
+    }
+
+    list->n--;
+
+    // OK, delete orphaned list element and its data
+    psFree(elem->data);
+    psFree(elem);
+
+    return true;
+}
+
+psList* p_psListAlloc(const char *file,
+                    unsigned int lineno,
+                    const char *func,
+                    psPtr data)
+{
+    psList* list = p_psAlloc(file, lineno, func, sizeof(psList));
+
+    psMemSetDeallocator(list, (psFreeFunc) listFree);
+
+    list->n = 0;
+    list->head = list->tail = NULL;
+    list->iterators = psArrayAllocEmpty(INITIAL_NUM_ITERATORS);
+
+    // create a default iterator
+    psListIteratorAlloc(list,PS_LIST_HEAD,true);
+
+    if (data != NULL) {
+        psListAdd(list, PS_LIST_TAIL, data);
+    }
+
+    return list;
+}
+
+bool psMemCheckList(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)listFree );
+}
+
+psListIterator* p_psListIteratorAlloc(const char *file,
+                                    unsigned int lineno,
+                                    const char *func,
+                                    psList* list,
+                                    long location,
+                                    bool mutable)
+{
+    PS_ASSERT_LIST_NON_NULL(list, NULL);
+
+    psListIterator* iter = p_psAlloc(file, lineno, func, sizeof(psListIterator));
+    psMemSetDeallocator(iter, (psFreeFunc) listIteratorFree);
+
+    // initialize the attributes
+    iter->list = list;
+    iter->cursor = NULL;
+    iter->index = 0;
+    iter->offEnd = false;
+    iter->mutable = mutable;
+
+    // associate the iterator with the list
+    list->iterators = psArrayAdd(list->iterators,0,iter);
+    // don't want the list's array of iterators to hold a true reference
+    psMemDecrRefCounter(iter);
+
+    if (!psListIteratorSet(iter,location)) {
+        psFree(iter);
+        return NULL;
+    }
+
+    return iter;
+}
+
+bool psListIteratorSet(psListIterator* iterator,
+                       long location)
+{
+    PS_ASSERT_LIST_ITERATOR_NON_NULL(iterator, false);
+
+    psList* list = iterator->list;
+
+    if (location == PS_LIST_TAIL) {
+        iterator->cursor = list->tail;
+        iterator->index = list->n - 1;
+        iterator->offEnd = false;
+        return true;
+    }
+
+    if (location == PS_LIST_HEAD) {
+        iterator->cursor = list->head;
+        iterator->index = 0;
+        iterator->offEnd = false;
+        return true;
+    }
+
+    if (location < 0) {
+        location = list->n + location;
+    }
+
+    if (location < 0 || location >= (int)list->n) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified location, %ld, is invalid."),
+                location);
+        return false;
+    }
+
+    psListElem* cursor = iterator->cursor;
+    int index = iterator->index;
+    if (cursor == NULL) {      // set the cursor to the head if it is NULL
+        //XXX: if location can't be >= n, it def. can't be greater than n/2.
+        /*        if (location > list->n/2) { // closer to tail or head?
+                    cursor = list->tail;
+                    index = list->n - 1;
+                } else {
+        */
+        cursor = list->head;
+        index = 0;
+        //        }
+    }
+
+    if (location < index) {
+        psS32 diff = index - location;
+
+        for (psS32 count = 0; count < diff; count++) {
+            cursor = cursor->prev; // shouldn't need to check for NULL
+        }
+    } else {
+        psS32 diff = location - index;
+
+        for (psS32 count = 0; count < diff; count++) {
+            cursor = cursor->next; // shouldn't need to check for NULL
+        }
+    }
+    iterator->cursor = cursor;
+    iterator->index = location;
+    iterator->offEnd = false;
+
+    return true;
+}
+
+bool psListAdd(psList* list,
+               long location,
+               psPtr data)
+{
+    PS_ASSERT_LIST_NON_NULL(list, false);
+    PS_ASSERT_PTR_NON_NULL(data, false);
+
+    if (location != PS_LIST_HEAD && location >= list->n) {
+        psLogMsg(__func__,PS_LOG_DETAIL,
+                 "Specified location, %ld, is beyond the end of the list.  "
+                 "Adding data item to tail.",
+                 location);
+        location = PS_LIST_TAIL;
+    }
+
+    // move ourselves to the given position
+    if (! psListIteratorSet(list->iterators->data[0],location)) {
+        return false;
+    }
+
+    if (location == PS_LIST_TAIL) {
+        // insert the element at the end of the list
+        return psListAddAfter(list->iterators->data[0],data);
+    } else {
+        return psListAddBefore(list->iterators->data[0],data);
+    }
+}
+
+bool psListAddAfter(psListIterator* iterator,
+                    void* data)
+{
+    PS_ASSERT_LIST_ITERATOR_NON_NULL(iterator, false);
+    PS_ASSERT_PTR_NON_NULL(data, false);
+
+    // Check if the list pointed by the iterator can be changed
+    if (!iterator->mutable) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Specified iterator indicates list is non-mutable."));
+        return false;
+    }
+
+    psListElem* cursor = iterator->cursor;
+    psList* list = iterator->list;
+
+    if (cursor == NULL && list->head != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified iterator is not valid."));
+        return false;
+    }
+
+    psListElem* elem = psAlloc(sizeof(psListElem));
+
+    // set the new list element's attributes
+    if (cursor == NULL) { // must be an empty list
+        elem->prev = NULL;
+        elem->next = NULL;
+        list->head = elem;
+        list->tail = elem;
+    } else {
+        elem->prev = cursor;
+        elem->next = cursor->next;
+        cursor->next = elem;
+        if (elem->next == NULL) {
+            list->tail = elem;
+        } else {
+            elem->next->prev = elem;
+        }
+    }
+
+    elem->data = psMemIncrRefCounter(data);
+
+    list->n++;
+
+    psArray* iterators = list->iterators;
+    int index = iterator->index;
+    for (int i = 0; i < iterators->n; i++) {
+        psListIterator* iter = (psListIterator*) iterators->data[i];
+        if (iter->index > index) {
+            iter->index++;
+        }
+    }
+
+    return true;
+}
+
+bool psListAddBefore(psListIterator* iterator,
+                     void* data)
+{
+    PS_ASSERT_LIST_ITERATOR_NON_NULL(iterator, false);
+    PS_ASSERT_PTR_NON_NULL(data, false);
+
+    // Check if the list pointed by the iterator can be changed
+    if (!iterator->mutable) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Specified iterator indicates list is non-mutable."));
+        return false;
+    }
+
+    psListElem* cursor = iterator->cursor;
+    psList* list = iterator->list;
+
+    if (cursor == NULL && list->head != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified iterator is not valid."));
+        return false;
+    }
+
+    psListElem* elem = psAlloc(sizeof(psListElem));
+
+    // set the new list element's attributes
+    if (cursor == NULL) { // empty list.
+        elem->prev = NULL;
+        elem->next = NULL;
+        list->head = elem;
+        list->tail = elem;
+    } else {
+        elem->prev = cursor->prev;
+        elem->next = cursor;
+        cursor->prev = elem;
+        if (elem->prev == NULL) {
+            list->head = elem;
+        } else {
+            elem->prev->next = elem;
+        }
+    }
+
+    elem->data = psMemIncrRefCounter(data);
+
+    list->n++;
+
+    psArray* iterators = list->iterators;
+    int index = iterator->index;
+    for (int i = 0; i < iterators->n; i++) {
+        psListIterator* iter = (psListIterator*) iterators->data[i];
+        if (iter->index >= index) {
+            iter->index++;
+        }
+    }
+
+    return true;
+}
+
+bool psListRemove(psList* list,
+                  long location)
+{
+    PS_ASSERT_LIST_NON_NULL(list, false);
+
+    // move ourselves to the given position
+    psListIterator* defaultIterator = list->iterators->data[0];
+    if (! psListIteratorSet(defaultIterator,location)) {
+        return false;
+    }
+
+    return listIteratorRemove(defaultIterator);
+}
+
+bool psListRemoveData(psList* list,
+                      psPtr data)
+{
+    PS_ASSERT_LIST_NON_NULL(list, false);
+    PS_ASSERT_PTR_NON_NULL(data, false);
+
+    psListElem* elem = list->head;
+    int index = 0;
+    while (elem != NULL && elem->data != data) {
+        elem = elem->next;
+        index++;
+    }
+    if (elem == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Specified data item is not found in the psList."));
+        return false;
+    }
+
+    psListIterator* iterator = (psListIterator*)list->iterators->data[0];
+    iterator->index = index;
+    iterator->cursor = elem;
+
+    return listIteratorRemove(iterator);
+}
+
+psPtr psListGet(psList* list,
+                long location)
+{
+    PS_ASSERT_LIST_NON_NULL(list, NULL);
+
+    // XXX this should not be an error, right?
+    if (list->head == NULL) { // list empty?
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                _("Specified psList reference is empty."));
+        return NULL;
+    }
+
+    psListIterator* iterator = list->iterators->data[0];
+
+    if (! psListIteratorSet(iterator,location)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified location, %ld, is invalid."),
+                location);
+        return NULL;
+    }
+
+    return iterator->cursor->data;
+}
+
+// simultaneous get and remove (ie, 'pop')
+psPtr psListGetAndRemove (psList *list, long location) {
+
+    PS_ASSERT_LIST_NON_NULL(list, NULL);
+
+    // empty list : 
+    // XXX handle this explicitly since psListGet raises an error in this case
+    if (list->head == NULL) return NULL;
+
+    psPtr *item = psListGet (list, location);
+
+    psListRemove (list, location);
+    return item;
+}
+
+/*
+ * and now return the previous/next element of the list
+ */
+psPtr psListGetAndIncrement(psListIterator* iterator)
+{
+    PS_ASSERT_LIST_ITERATOR_NON_NULL(iterator, NULL);
+
+    if (( iterator->cursor == NULL) && (iterator->offEnd)) {
+        return NULL;
+    }
+    if ( (iterator->cursor == NULL) && (!iterator->offEnd)) {
+        iterator->cursor = iterator->list->head;
+        iterator->index = 0;
+        return NULL;
+    }
+
+    psPtr data = iterator->cursor->data;
+
+    iterator->cursor = iterator->cursor->next;
+    iterator->index++;
+    if (iterator->cursor == NULL) {
+        iterator->offEnd = true;
+    }
+
+    return data;
+}
+
+psPtr psListGetAndDecrement(psListIterator* iterator)
+{
+    PS_ASSERT_LIST_ITERATOR_NON_NULL(iterator, NULL);
+
+    if ((iterator->cursor == NULL) && (!iterator->offEnd))  {
+        return NULL;
+    }
+    if ( (iterator->cursor == NULL) && (iterator->offEnd) ) {
+        iterator->cursor = iterator->list->tail;
+        iterator->index = iterator->list->n-1;
+        iterator->offEnd = false;
+        return NULL;
+    }
+
+    psPtr data = iterator->cursor->data;
+
+    iterator->cursor = iterator->cursor->prev;
+    iterator->index--;
+
+    return data;
+}
+
+/*
+ * Convert a psList to/from a psVoidPtrArray
+ */
+psArray* psListToArray(const psList* list)
+{
+    PS_ASSERT_LIST_NON_NULL(list, NULL);
+
+    long n = list->n;
+    psArray *arr = psArrayAlloc(n);
+
+    psListElem *ptr = list->head;
+    for (long i = 0; i < n; i++) {
+        arr->data[i] = psMemIncrRefCounter(ptr->data);
+        ptr = ptr->next;
+    }
+
+    return arr;
+}
+
+psList* psArrayToList(const psArray* array)
+{
+    PS_ASSERT_ARRAY_NON_NULL(array, NULL);
+
+    psList *list = psListAlloc(NULL);   // list of elements
+    for (long i = 0; i < array->n; i++) {
+        psListAdd(list, PS_LIST_TAIL, array->data[i]);
+    }
+    return list;
+}
+
+psList* psListSort(psList* list,
+                   psComparePtrFunc func)
+{
+    PS_ASSERT_LIST_NON_NULL(list, NULL);
+    PS_ASSERT_PTR_NON_NULL(func, NULL);
+
+    // convert to indexable vector for use by qsort.
+    psArray *arr = psListToArray(list);
+    psArray *iterators = psMemIncrRefCounter(list->iterators);
+    psFree(list);
+
+    arr = psArraySort(arr, func);
+
+    // convert back to linked list
+    list = psArrayToList(arr);
+    psFree(list->iterators);
+    list->iterators = iterators;
+    psFree(arr);
+
+    // Invalidate all iterator positions.
+    // Also need to point them to the new list.
+    for (int i = 0; i < iterators->n; i++) {
+        psListIterator *iterator = iterators->data[i]; // Iterator of interest
+        iterator->list = list;
+        iterator->cursor = NULL;
+    }
+
+    return list;
+}
+
+long psListLength(const psList *list)
+{
+    PS_ASSERT_LIST_NON_NULL(list, -1);
+    return list->n;
+}
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psList.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psList.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psList.h	(revision 22158)
@@ -0,0 +1,306 @@
+/** @file psList.h
+ *  @brief Support for doubly linked lists
+ *
+ *  @author Robert Lupton, Princeton University
+ *  @author Robert Daniel DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.46.20.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-26 03:49:12 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_LIST_H
+#define PS_LIST_H
+
+#include "psCompare.h"
+#include "psArray.h"
+
+/// @addtogroup DataContainer Data Containers
+///  @{
+
+/** Special values of index into list
+ *
+ *  This list of possible list position values should be contiguous
+ *  non-positive values ending with PS_LIST_UNKNOWN.  Any value
+ *  less-than-or-equal-to PS_LIST_UNKNOWN is considered a undefined position.
+ *
+ */
+enum {
+    PS_LIST_HEAD = 0,                  ///< at head
+    PS_LIST_TAIL = -1,                 ///< at tail
+};
+
+
+/** Doubly-linked list element */
+typedef struct psListElem {
+    struct psListElem* prev;           ///< previous link in list
+    struct psListElem* next;           ///< next link in list
+    psPtr data;                        ///< real data item
+} psListElem;
+
+
+/** The psList Linked list structure.  User should not allocate this struct
+ *  directly; rather the psListAlloc should be used.
+ *
+ *  @see psListAlloc
+ */
+typedef struct {
+    long n;                            ///< number of elements on list
+    psListElem* head;                  ///< first element on list (may be NULL)
+    psListElem* tail;                  ///< last element on list (may be NULL)
+    psArray* iterators;
+    ///< array of all iterators associated with this list.  First iterator is
+    ///< used internally to improve performance when using indexed access, all
+    ///< others are user-level iterators created by psListIteratorAlloc.
+    void *lock;                        ///< Optional lock for thread safety
+} psList;
+
+
+/** The psList iterator structure.  This should be allocated via
+ *  psListIteratorAlloc and not directly.
+ *
+ *  The life span of a psListIterator object is ended by either a psFree
+ *  of this structure OR psFree of the psList in which it operates on.
+ *
+ *  @see psListIteratorAlloc, psListIteratorSet, psListGetAndIncrement, psListGetAndDecrement
+ */
+typedef struct
+{
+    psList* list;                      ///< List iterator to works on
+    psListElem* cursor;                ///< current cursor position
+    bool offEnd;                       ///< Iterator off the end?
+    long index;                         ///< the index number in the list
+    bool mutable;                      ///< Is it permissible to modify the list?
+}
+psListIterator;
+
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr
+ *  datatype.
+ *
+ *  @return bool:       True if the pointer matches a psList structure, false otherwise.
+ */
+bool psMemCheckList(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+
+/** Creates a psList linked list object.
+ *
+ *  @return psList* A new psList object.
+ */
+#ifdef DOXYGEN
+psList* psListAlloc(
+    psPtr data          ///< initial data item; may be NULL if an empty psList is desired
+);
+#else // ifdef DOXYGEN
+psList* p_psListAlloc(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psPtr data                          ///< initial data item; may be NULL if an empty psList is desired
+) PS_ATTR_MALLOC;
+#define psListAlloc(data) \
+      p_psListAlloc(__FILE__, __LINE__, __func__, data)
+#endif // ifdef DOXYGEN
+
+
+/** Creates a psListIterator object and associates it with a psList.
+ *
+ *  @return psListIterator* A new psListIterator object.
+ */
+#ifdef DOXYGEN
+psListIterator* psListIteratorAlloc(
+    psList* list,                      ///< the psList to iterate with
+    long location,                     ///< the initial starting point.
+    ///<  This can be a numeric index, PS_LIST_HEAD, or PS_LIST_TAIL.
+    bool mutable                       ///< Is it permissible to modify list?
+);
+#else // ifdef DOXYGEN
+psListIterator* p_psListIteratorAlloc(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psList* list,                      ///< the psList to iterate with
+    long location,                     ///< the initial starting point.
+    ///<  This can be a numeric index, PS_LIST_HEAD, or PS_LIST_TAIL.
+    bool mutable                       ///< Is it permissible to modify list?
+) PS_ATTR_MALLOC;
+#define psListIteratorAlloc(list, location, mutable) \
+      p_psListIteratorAlloc(__FILE__, __LINE__, __func__, list, location, mutable)
+#endif // ifdef DOXYGEN
+
+
+/** Set the iterator of the list to a given position.  If location is invalid the
+ *  iterator position is not changed.
+ *
+ *  @return bool        TRUE if iterator successfully set, otherwise FALSE.
+ */
+bool psListIteratorSet(
+    psListIterator* iterator,          ///< list iterator
+    long location                      ///< index number, PS_LIST_HEAD, or PS_LIST_TAIL
+);
+
+
+/** Adds an element to a psList at position given.
+ *
+ *  @return bool        TRUE if item was successfully added, otherwise FALSE.
+ */
+bool psListAdd(
+    psList* list,                      ///< list to add item to
+    long location,                     ///< index, PS_LIST_HEAD, PS_LIST_TAIL, or numbered location.
+    psPtr data                         ///< data item to add.  If NULL, list is not modified.
+);
+
+
+/** Adds an data item to a psList at position just after the list position given
+ *
+ *  @return bool        TRUE if item was successfully added, otherwise FALSE.
+ */
+bool psListAddAfter(
+    psListIterator* iterator,          ///< list position to add item to
+    psPtr data                         ///< data item to add.  If NULL, list is not modified.
+);
+
+
+/** Adds a data item to a psList at position just before the list position given
+ *
+ *  @return bool        TRUE if item was successfully added, otherwise FALSE.
+ */
+bool psListAddBefore(
+    psListIterator* iterator,          ///< list position to add item to
+    psPtr data                         ///< data item to add.  If NULL, list is not modified.
+);
+
+/** Remove an item at the specified location from a list.
+ *
+ *  @return bool        TRUE if element is successfully removed, otherwise FALSE.
+ */
+bool psListRemove(
+    psList* list,                      ///< list to remove element from
+    long location                      ///< index of item
+);
+
+
+/** Remove an item from a list.
+ *
+ *  @return bool        TRUE if element is successfully removed, otherwise FALSE.
+ */
+bool psListRemoveData(
+    psList* list,                      ///< list to remove element from
+    psPtr data                         ///< data item to find and remove
+);
+
+
+/** Retrieve an item from a list.
+ *
+ *  @return psPtr       the item corresponding to the location parameter.  If
+ *                      location is invalid (e.g., a numbered index greater
+ *                      than the list size or if the list is empty), a
+ *                      NULL is returned.
+ */
+psPtr psListGet(
+    psList* list,                      ///< list to retrieve element from
+    long location                      ///< index number, PS_LIST_HEAD, or PS_LIST_TAIL
+);
+
+/** Retrieve an item from a list.
+ *
+ *  @return psPtr       the item corresponding to the location parameter.  If
+ *                      location is invalid (e.g., a numbered index greater
+ *                      than the list size or if the list is empty), a
+ *                      NULL is returned.
+ */
+psPtr psListGetAndRemove (
+    psList *list, 			///< list from which to get and remove the element
+    long location			///< index of item
+);
+
+/** Position the specified iterator to the next item in list.
+ *
+ *  @return psPtr       the data item at the original iterator position or NULL if the
+ *                      iterator went past the end of the list.
+ */
+psPtr psListGetAndIncrement(
+    psListIterator* iterator           ///< iterator to move
+);
+
+
+/** Position the specified iterator to the previous item in list.
+ *
+ *  @return psPtr       the data item at the original iterator position or NULL if the
+ *                      iterator went past the beginning of the list.
+ */
+psPtr psListGetAndDecrement(
+    psListIterator* iterator           ///< iterator to move
+);
+
+
+/** Convert a linked list to an array
+ *
+ *  @return psArray* A new psArray populated with elements from the list,
+ *                      or NULL if the given dlist parameter is NULL.
+ */
+psArray* psListToArray(
+    const psList* list                 ///< List to convert
+);
+
+
+/** Convert array to a doubly-linked list
+ *
+ *  @return psList* A new psList populated with elements formt the psArray,
+ *                      or NULL is the given arr parameter is NULL.
+ */
+psList* psArrayToList(
+    const psArray* array               ///< vector to convert
+);
+
+
+/** Sort a list via a comparison function.
+ *
+ *  The comparison function must return an integer less than, equal to, or
+ *  greater than zero if the first argument is considered to be respectively
+ *  less than, equal to, or greater than the second.
+ *
+ *  If two members compare as equal, their order in the sorted array is
+ *  undefined.
+ *
+ *  @return psList*     Sorted list.
+ */
+psList* psListSort(
+    psList* list,                      ///< the list to sort
+    psComparePtrFunc func              ///< the comparison function
+);
+
+
+/** Get the number of elements in use from a specified psList. (list.n)
+ *
+ *  @return long:       The number of elements in use.
+ */
+long psListLength(
+    const psList *list                 ///< input psList
+);
+
+
+#define PS_ASSERT_LIST_NON_NULL(NAME, RVAL) \
+if (!(NAME) || !(NAME)->iterators || (NAME)->n < 0) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: List %s or one of its components is NULL.", \
+            #NAME); \
+    return RVAL; \
+}
+
+#define PS_ASSERT_LIST_ITERATOR_NON_NULL(NAME, RVAL) \
+if (!(NAME) || !(NAME)->list || !(NAME)->list->iterators || (NAME)->list->n < 0) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: List iterator %s or one of its components is NULL.", \
+            #NAME); \
+    return RVAL; \
+}
+
+
+/// @} End of DataContainer Functions
+#endif // #ifndef PS_LIST_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psLookupTable.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psLookupTable.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psLookupTable.c	(revision 22158)
@@ -0,0 +1,737 @@
+/** @file  psLookupTable.c
+*
+*  @brief This file defines the structure and functions for table lookups.
+*
+*  @ingroup types
+*
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.51 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2008-04-17 23:43:03 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#undef __STRICT_ANSI__
+#include <stdlib.h>
+#define __STRICT_ANSI__
+#include <limits.h>
+#include <math.h>
+#include <inttypes.h>
+
+#include "psAbort.h"
+#include "psMemory.h"
+#include "psString.h"
+#include "psError.h"
+#include "psLookupTable.h"
+
+#include "psAssert.h"
+
+/******************************************************************************/
+/*  DEFINE STATEMENTS                                                         */
+/******************************************************************************/
+
+/** Maximum size of a string */
+#define MAX_STRING_LENGTH   256
+#define ARRAY_STRIDE        16
+#define INITIAL_NUM         10          // Initial number of elements
+/******************************************************************************/
+/*  TYPE DEFINITIONS                                                          */
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  GLOBAL VARIABLES                                                         */
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  FILE STATIC VARIABLES                                                    */
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+/*****************************************************************************/
+
+static bool ignoreLine(char *inString);
+static char *cleanString(char *inString, int sLen);
+static char* getToken(char **inString, char *delimiter, psParseErrorType *status);
+static void parseValue(psVector *vec, psU64 index, char* strValue, psParseErrorType *status);
+static void lookupTableFree(psLookupTable* table);
+
+/* Determines if a line is blank (whitespace only) or a commentline. It returns true if so.
+   The input string must be null terminated. */
+static bool ignoreLine(char *inString)
+{
+    while (*inString!='\0' && *inString!='#') {
+        if (!isspace(*inString)) {
+            return false;
+        }
+        inString++;
+    }
+    return true;
+}
+
+
+/* Removes leading and trailing whitespace and # characters from a string. The
+   cleaned string is a new null terminated copy of the original input string. */
+static char *cleanString(char *inString,
+                         int sLen)
+{
+    char *ptrB = NULL;
+    char *ptrE = NULL;
+    char *cleaned = NULL;
+
+    ptrB = inString;
+
+    // Skip over leading # or whitespace
+    //    while (isspace(*ptrB) || *ptrB=='#') {
+    //        ptrB++;
+    //    }
+
+    // Skip over trailing whitespace, null terminators, and # characters
+    ptrE = inString + sLen;
+    while (isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') {
+        ptrE--;
+    }
+
+    // Length, sLen, does not include '\0'
+    sLen = ptrE - ptrB + 1;
+
+    // Adds '\0' to end of string and +1 to sLen
+    cleaned = psStringNCopy(ptrB, sLen);
+
+    return cleaned;
+}
+
+
+/* Returns cleaned token based on delimiter, but not including delimiter. Also changes
+   the pointer location the beginning of the string. Tokens are newly allocated null
+    terminated strings. */
+static char* getToken(char **inString,
+                      char *delimiter,
+                      psParseErrorType *status)
+{
+    char *cleanToken = NULL;
+    int sLen = 0;
+
+    // Skip over leading whitespace
+    while (isspace(**inString)) {
+        (*inString)++;
+    }
+
+    // Length of token, not including delimiter
+    sLen = strcspn(*inString, delimiter);
+    if (sLen) {
+
+        // Create new, cleaned, and null terminated token
+        cleanToken = cleanString(*inString, sLen);
+
+        // Move to end of token
+        (*inString) += sLen;
+    }
+    /*    else if (**inString!='\0' && sLen==0) {
+            *status = PS_PARSE_ERROR_GENERAL;
+        }
+    */
+    return cleanToken;
+}
+
+#define PARSE_VALUE_INT_CASE(TYPE, FUNC) \
+    case PS_TYPE_##TYPE: { \
+        char *end = NULL; \
+        ps##TYPE value = FUNC(strValue, &end, 0); \
+        if (*end != '\0' && !isspace(*end)) { \
+            *status = PS_PARSE_ERROR_VALUE; \
+        } \
+        vec->data.TYPE[index] = value; \
+        return; \
+    }
+
+#define PARSE_VALUE_FLOAT_CASE(TYPE, FUNC) \
+    case PS_TYPE_##TYPE: { \
+        char *end = NULL; \
+        ps##TYPE value = FUNC(strValue, &end); \
+        if (*end != '\0' && !isspace(*end)) { \
+            *status = PS_PARSE_ERROR_VALUE; \
+        } \
+        vec->data.TYPE[index] = value; \
+        return; \
+    }
+
+
+/* Returns single parsed value as a double precision number. The input string must be
+   cleaned and null terminated. */
+static void parseValue(psVector *vec,
+                       psU64 index,
+                       char* strValue,
+                       psParseErrorType *status)
+{
+    switch (vec->type.type) {
+        PARSE_VALUE_INT_CASE(S32, strtol);
+        PARSE_VALUE_INT_CASE(S64, strtoll);
+        PARSE_VALUE_FLOAT_CASE(F32, strtof);
+        PARSE_VALUE_FLOAT_CASE(F64, strtod);
+      default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Bad type for vector: %x.\n", vec->type.type);
+        *status = PS_PARSE_ERROR_TYPE;
+    }
+    return;
+}
+
+static void lookupTableFree(psLookupTable* table)
+{
+    psAssert(table, "impossible");
+    psFree(table->values);
+    psFree(table->filename);
+    psFree(table->format);
+    psFree(table->index);
+}
+
+/*****************************************************************************/
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+/*****************************************************************************/
+
+bool psMemCheckLookupTable(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)lookupTableFree );
+}
+
+
+psLookupTable* p_psLookupTableAlloc(const char *file,
+                                    unsigned int lineno,
+                                    const char *func,
+                                    const char *filename,
+                                    const char *format,
+                                    long indexCol)
+{
+    PS_ASSERT_STRING_NON_EMPTY(filename,NULL);
+    PS_ASSERT_STRING_NON_EMPTY(format,NULL);
+
+    psLookupTable *outTable = p_psAlloc(file, lineno, func, sizeof(psLookupTable));
+
+    // Set deallocator
+    psMemSetDeallocator(outTable, (psFreeFunc)lookupTableFree);
+
+    // Allocate and set file name and format strings
+    outTable->filename = psStringCopy(filename);
+    outTable->format = psStringCopy(format);
+
+    // Valid ranges. Automatically set by table read if both zero.
+    *(double *)&outTable->validFrom = 0;
+    *(double *)&outTable->validTo = 0;
+    outTable->indexCol = indexCol;
+
+    // Vector of independent index values. Filled by table read.
+    outTable->index = NULL;
+
+    // Array of dependent table values corresponding to index values. Filled by table read.
+    outTable->values = NULL;
+
+    return outTable;
+}
+
+psArray *psVectorsReadFromFile(const char *filename,
+                               const char *format)
+{
+    PS_ASSERT_STRING_NON_EMPTY(filename, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(format, NULL);
+
+    psArray*          outputArray = NULL;
+    psVector*         colVector   = NULL;
+    char*             strValue    = NULL;
+    char*             strNum      = NULL;
+    char*             line        = NULL;
+    char*             linePtr     = NULL;
+    int               numCols     = 0;
+    int               numRows     = 0;
+    FILE*             fp          = NULL;
+    const char*       tempFormat  = NULL;
+    psParseErrorType  parseStatus = PS_PARSE_SUCCESS;
+
+    // Create temp pointer which can then be used several times
+    tempFormat = format;
+
+    // Create output array and set array elements to zero
+    outputArray = psArrayAllocEmpty(INITIAL_NUM);
+
+    // Parse the format string to determine how many vectors
+    // and whether the format string is valid
+    while ((strValue = getToken((char**)&tempFormat, " \t", &parseStatus))) {
+
+        // Check for %d format sub string
+        if (strcmp(strValue,"\%d") == 0 ) {
+            numCols++;
+            colVector = psVectorAlloc(1,PS_TYPE_S32);
+            outputArray = psArrayAdd(outputArray, ARRAY_STRIDE, colVector);
+            psFree(colVector);
+        } else if (strcmp(strValue,"\%ld") == 0) {
+            numCols++;
+            colVector = psVectorAlloc(1,PS_TYPE_S64);
+            outputArray = psArrayAdd(outputArray, ARRAY_STRIDE, colVector);
+            psFree(colVector);
+        } else if (strcmp(strValue,"\%f") == 0) {
+            numCols++;
+            colVector = psVectorAlloc(1,PS_TYPE_F32);
+            outputArray = psArrayAdd(outputArray, ARRAY_STRIDE, colVector);
+            psFree(colVector);
+        } else if (strcmp(strValue,"\%lf") == 0) {
+            numCols++;
+            colVector = psVectorAlloc(1,PS_TYPE_F64);
+            outputArray = psArrayAdd(outputArray, ARRAY_STRIDE, colVector);
+            psFree(colVector);
+        } else if (strstr(strValue,"\%*") != 0) {
+            // Don't increase number of columns
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Invalid format specifier");
+            psFree(strValue);
+            numCols = 0;
+            break;
+        }
+        psFree(strValue);
+    }
+
+    // If the format string was parsed successfully and return numCols the
+    // prepare to open file and read values
+    if (numCols > 0) {
+
+        // Open specified file
+        if ((fp=fopen(filename, "r")) == NULL) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed to open file %s."),
+                    filename);
+            psFree(outputArray);
+            return NULL;
+        } else {
+            // Initialize array index
+            int arrayIndex = 0;
+
+            // Create reusable line for continuous read
+            line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char));
+
+            // Loop through file to get numRows, numCols, and column data types
+            while ((fgets(line, MAX_STRING_LENGTH, fp) != NULL) &&
+                    (parseStatus == PS_PARSE_SUCCESS))   {
+
+                // Copy pointer to line for parsing
+                linePtr = line;
+
+                // If line is not a comment or blank, then extract data
+                if (!ignoreLine(linePtr)) {
+                    numRows++;
+
+                    // Copy format pointer for parsing
+                    tempFormat = format;
+                    arrayIndex = 0;
+                    parseStatus = PS_PARSE_SUCCESS;
+
+                    // Loop through format and line strings to get values in text table file
+                    while ((strValue=getToken((char**)&tempFormat," \t",&parseStatus))
+                            && (strNum=getToken((char**)&linePtr," \t",&parseStatus)) ) {
+                        // Set column vector
+                        colVector = outputArray->data[arrayIndex];
+
+                        // Set column entries based on format string defining the type
+                        if (strcmp(strValue,"\%d") == 0 ) {
+                            colVector = psVectorRecycle(colVector, numRows,
+                                                        colVector->type.type);
+                            parseValue(colVector,numRows-1,strNum,&parseStatus);
+                            arrayIndex++;
+                        } else if (strcmp(strValue,"\%ld") == 0) {
+                            colVector = psVectorRecycle(colVector, numRows,
+                                                        colVector->type.type);
+                            parseValue(colVector,numRows-1,strNum,&parseStatus);
+                            arrayIndex++;
+                        } else if (strcmp(strValue,"\%f") == 0) {
+                            colVector = psVectorRecycle(colVector, numRows,
+                                                        colVector->type.type);
+                            parseValue(colVector,numRows-1,strNum,&parseStatus);
+                            arrayIndex++;
+                        } else if (strcmp(strValue,"\%lf") == 0) {
+                            colVector = psVectorRecycle(colVector, numRows,
+                                                        colVector->type.type);
+                            parseValue(colVector,numRows-1,strNum,&parseStatus);
+                            arrayIndex++;
+                        } else if (strstr(strValue,"\%*") != 0) {
+                            // Don't increase number of columns
+                        }
+                        psFree(strValue);
+                        psFree(strNum);
+
+                        // If the file line was not parsed successful report
+                        // error and return NULL
+                        if (parseStatus != PS_PARSE_SUCCESS) {
+                            psError(PS_ERR_UNKNOWN, true,
+                                    "Parsing text file failed.");
+                            fclose(fp);
+                            psFree(outputArray);
+                            psFree(line);
+                            return NULL;
+                        }
+                    }
+                    if (strValue != NULL && strNum == NULL) {
+                        psError(PS_ERR_UNKNOWN, true,
+                                "Parsing text file failed - missing table value(s).");
+                        fclose(fp);
+                        psFree(outputArray);
+                        psFree(line);
+                        psFree(strValue);
+                        return NULL;
+                    }
+                }  // ignore line
+            }
+
+            //Return NULL for an empty table
+            if (numRows == 0) {
+                psError(PS_ERR_UNKNOWN, true,
+                        "Parsing text file failed - input table is empty.");
+                fclose(fp);
+                psFree(outputArray);
+                psFree(line);
+                return NULL;
+            }
+
+            // Read on the lines in the file - close file pointer
+            fclose(fp);
+            psFree(line);
+        }
+    } else {
+        // Format string parse error detected
+        psError(PS_ERR_UNKNOWN, true,
+                "Format string was not parsed sucessfully");
+        psFree(outputArray);
+        return NULL;
+    }
+
+    // Return populated array
+    return outputArray;
+}
+
+bool p_psLookupTableImport(const char *file,
+                           unsigned int lineno,
+                           const char *func,
+                           psLookupTable *table,
+                           psArray *vectors,
+                           long indexCol)
+{
+    PS_ASSERT_LOOKUPTABLE_NON_NULL(table, false);
+    PS_ASSERT_ARRAY_NON_NULL(vectors, false);
+    PS_ASSERT_INT_NONNEGATIVE(indexCol, false);
+    if (indexCol >= vectors->n) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Index column, %ld, is larger"
+                " than number of columns, %ld.", indexCol, vectors->n);
+        return false;
+    }
+
+    psVector *indexVector = vectors->data[indexCol]; // The vector that provides the index
+    long numRows = indexVector->n;      // Number of rows in table
+    long numCols = vectors->n;          // Number of columns in table
+
+#define CHECK_SORT_CASE(TYPE) \
+    case PS_TYPE_##TYPE: \
+        for (long i = 1; i < numRows; i++) { \
+             if (indexVector->data.TYPE[i] < indexVector->data.TYPE[i - 1]) { \
+                 sortNeeded = true; \
+                 break; \
+             } \
+         } \
+         break;
+
+    // Check if array is sorted on the index column
+    bool sortNeeded  = false;           // Do we need to sort?
+    switch (indexVector->type.type) {
+        CHECK_SORT_CASE(U8);
+        CHECK_SORT_CASE(U16);
+        CHECK_SORT_CASE(U32);
+        CHECK_SORT_CASE(U64);
+        CHECK_SORT_CASE(S8);
+        CHECK_SORT_CASE(S16);
+        CHECK_SORT_CASE(S32);
+        CHECK_SORT_CASE(S64);
+        CHECK_SORT_CASE(F32);
+        CHECK_SORT_CASE(F64);
+      default:
+        psAbort("Should never get here: bad type.");
+    }
+
+    if (sortNeeded) {
+        psVector *sortedIndex = psVectorSortIndex(NULL, indexVector); // Indices for sorting
+        psArray *newValues = psArrayAlloc(numCols);
+        for (long i = 0; i < numCols; i++) {
+            psVector *oldVector = vectors->data[i]; // Vector of interest
+            psVector *newVector = psVectorAlloc(numRows, oldVector->type.type);
+            newValues->data[i] = newVector;
+
+#define REARRANGE_CASE(TYPE) \
+    case PS_TYPE_##TYPE: \
+        for (long j = 0; j < numRows; j++) { \
+            newVector->data.TYPE[j] = oldVector->data.TYPE[sortedIndex->data.S32[j]]; \
+        } \
+        break;
+
+            switch (oldVector->type.type) {
+                REARRANGE_CASE(U8);
+                REARRANGE_CASE(U16);
+                REARRANGE_CASE(U32);
+                REARRANGE_CASE(U64);
+                REARRANGE_CASE(S8);
+                REARRANGE_CASE(S16);
+                REARRANGE_CASE(S32);
+                REARRANGE_CASE(S64);
+                REARRANGE_CASE(F32);
+                REARRANGE_CASE(F64);
+              default:
+                psAbort("Should never get here: bad type.");
+            }
+        }
+
+        psFree(sortedIndex);
+        table->values = newValues;
+    } else {
+        table->values = psMemIncrRefCounter(vectors);
+    }
+
+    table->index = psMemIncrRefCounter(table->values->data[indexCol]);
+    table->indexCol = indexCol;
+
+#define SET_VALID_CASE(TYPE) \
+    case PS_TYPE_##TYPE: \
+        *(double*)&table->validFrom = table->index->data.TYPE[0]; \
+        *(double*)&table->validTo   = table->index->data.TYPE[numRows - 1]; \
+        break;
+
+    switch (table->index->type.type) {
+        SET_VALID_CASE(U8);
+        SET_VALID_CASE(U16);
+        SET_VALID_CASE(U32);
+        SET_VALID_CASE(U64);
+        SET_VALID_CASE(S8);
+        SET_VALID_CASE(S16);
+        SET_VALID_CASE(S32);
+        SET_VALID_CASE(S64);
+        SET_VALID_CASE(F32);
+        SET_VALID_CASE(F64);
+      default:
+        psAbort("Should never get here: bad type.");
+    }
+
+    return true;
+}
+
+long psLookupTableRead(psLookupTable* table)
+{
+    PS_ASSERT_LOOKUPTABLE_NON_NULL(table, 0);
+
+    // Read vectors from file specified in table
+    psArray *vectors = psVectorsReadFromFile(table->filename, table->format); // Vectors in file
+    if (!vectors) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read vectors from %s", table->filename);
+        return 0;
+    }
+
+    // Import vector into table
+    if (!psLookupTableImport(table, vectors, table->indexCol)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to import vectors from %s into lookup table.",
+                table->filename);
+        psFree(vectors);
+        return 0;
+    }
+    psFree(vectors);                // Drop reference
+
+    return table->index->n;
+}
+
+#define CONVERT_VALUE_TO_F64(VECTOR,INDEX,RESULT)     \
+switch(VECTOR->type.type) {                           \
+case PS_TYPE_U8:                                      \
+    RESULT = (psF64)VECTOR->data.U8[INDEX];           \
+    break;                                            \
+case PS_TYPE_U16:                                     \
+    RESULT = (psF64)VECTOR->data.U16[INDEX];          \
+    break;                                            \
+case PS_TYPE_U32:                                     \
+    RESULT = (psF64)VECTOR->data.U32[INDEX];          \
+    break;                                            \
+case PS_TYPE_U64:                                     \
+    RESULT = (psF64)VECTOR->data.U64[INDEX];          \
+    break;                                            \
+case PS_TYPE_S8:                                      \
+    RESULT = (psF64)VECTOR->data.S8[INDEX];           \
+    break;                                            \
+case PS_TYPE_S16:                                     \
+    RESULT = (psF64)VECTOR->data.S16[INDEX];          \
+    break;                                            \
+case PS_TYPE_S32:                                     \
+    RESULT = (psF64)VECTOR->data.S32[INDEX];          \
+    break;                                            \
+case PS_TYPE_S64:                                     \
+    RESULT = (psF64)VECTOR->data.S64[INDEX];          \
+    break;                                            \
+case PS_TYPE_F32:                                     \
+    RESULT = (psF64)VECTOR->data.F32[INDEX];          \
+    break;                                            \
+case PS_TYPE_F64:                                     \
+    RESULT = VECTOR->data.F64[INDEX];                 \
+    break;                                            \
+default:                                              \
+    RESULT = NAN;                                     \
+    break;                                            \
+}
+
+#define CHECK_LOWER_UPPER_BOUND(TABLE,INDEX,COLUMN)                     \
+switch (TABLE->index->type.type) {                                      \
+case PS_TYPE_S32:                                                       \
+    if ( (psS32)index < TABLE->index->data.S32[0] ) {                    \
+        return NAN;                                                     \
+    }                                                                   \
+    if ( (psS32)index > TABLE->index->data.S32[numRows-1] ) {            \
+        return NAN;                                                     \
+    }                                                                   \
+    break;                                                              \
+case PS_TYPE_S64:                                                       \
+    if ( (psS64)index < TABLE->index->data.S64[0] ) {                    \
+        return NAN;                                                     \
+    }                                                                   \
+    if ( (psS64)index > TABLE->index->data.S64[numRows-1] ) {            \
+        return NAN;                                                     \
+    }                                                                   \
+    break;                                                              \
+case PS_TYPE_F32:                                                       \
+    if ( (psF32)index < TABLE->index->data.F32[0] ) {                    \
+        return NAN;                                                     \
+    }                                                                   \
+    if ( (psF32)index > TABLE->index->data.F32[numRows-1] ) {            \
+        return NAN;                                                     \
+    }                                                                   \
+    break;                                                              \
+case PS_TYPE_F64:                                                       \
+    if ( index < TABLE->index->data.F64[0] ) {                           \
+        return NAN;                                                     \
+    }                                                                   \
+    if ( index > TABLE->index->data.F64[numRows-1] ) {                   \
+        return NAN;                                                     \
+    }                                                                   \
+    break;                                                              \
+default:                                                                \
+    return NAN;                                                         \
+    break;                                                              \
+}
+
+double psLookupTableInterpolate(const psLookupTable *table,
+                                double index,
+                                long column)
+{
+    PS_ASSERT_LOOKUPTABLE_NON_NULL(table, NAN);
+    // Ensuring information exists
+    PS_ASSERT_VECTOR_NON_NULL(table->index, NAN);
+    PS_ASSERT_ARRAY_NON_NULL(table->values, NAN);
+    PS_ASSERT_INT_WITHIN_RANGE(column, 0, (int)table->values->n - 1, NAN);
+    PS_ASSERT_VECTOR_NON_NULL((psVector*)table->values->data[column], NAN);
+
+    psU64 hiIdx = 0;
+    psU64 loIdx = 0;
+    long  numRows = 0;
+    long numCols = 0;
+    psF64 out = 0.0;
+    psF64 denom = 0.0;
+    psF64 convertVal = 0.0;
+    psF64 tempVal = 0.0;
+    psVector *indexVec = NULL;
+    psVector *valuesVec = NULL;
+    psArray *values = NULL;
+
+    indexVec = table->index;
+    values = table->values;
+    numRows = table->index->n;
+    numCols = table->values->n;
+    valuesVec = (psVector*)values->data[column];
+
+    // Verify the index is within the bounds of the table
+    CHECK_LOWER_UPPER_BOUND(table,index,column);
+
+    // Find location in table where specified index is between to entries
+    CONVERT_VALUE_TO_F64(indexVec, 0, convertVal)
+    while (index > convertVal ) {
+        hiIdx++;
+        /*  XXX:  following is unreachable.
+                if (hiIdx >= numRows) {
+                    psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                            _("High index too big, %" PRIu64 "."), hiIdx);
+                    return NAN;
+                }
+        */
+        CONVERT_VALUE_TO_F64(indexVec, hiIdx, convertVal)
+    }
+
+    // Check for negative low index and generate error
+    loIdx = hiIdx--;
+    if (loIdx < 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Low index too small, %" PRIu64 "."), loIdx);
+        return NAN;
+    }
+
+    // Perform linear interpolation to calculate return value
+    CONVERT_VALUE_TO_F64(indexVec, hiIdx, denom)
+    CONVERT_VALUE_TO_F64(indexVec, loIdx, convertVal);
+    denom -= convertVal;
+    if (fabs(denom) < FLT_EPSILON) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Divide by zero error during interpolation."));
+        return NAN;
+    } else {
+        CONVERT_VALUE_TO_F64(valuesVec,hiIdx,tempVal)
+        CONVERT_VALUE_TO_F64(valuesVec,loIdx,convertVal)
+        tempVal -= convertVal;
+        CONVERT_VALUE_TO_F64(indexVec,loIdx,convertVal)
+        out = tempVal*(index-convertVal)/denom;
+        CONVERT_VALUE_TO_F64(valuesVec,loIdx,convertVal)
+        out += convertVal;
+    }
+
+    return out;
+}
+
+psVector* psLookupTableInterpolateAll(const psLookupTable *table,
+                                      double index)
+{
+    PS_ASSERT_LOOKUPTABLE_NON_NULL(table, NULL);
+    // Ensuring information exists
+    PS_ASSERT_VECTOR_NON_NULL(table->index, NULL);
+    PS_ASSERT_ARRAY_NON_NULL(table->values, NULL);
+    long numCols = table->values->n;
+    if (numCols == 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "No columns in lookup table from which to interpolate.");
+        return NULL;
+    }
+
+    psVector *outVector = psVectorAlloc(numCols, PS_TYPE_F64);
+
+    // Fill vectors with results and status of results
+    // XXX: This algorithm must be changed to something more efficient!
+    for (long i = 0; i < numCols; i++) {
+        outVector->data.F64[i] = psLookupTableInterpolate(table, index, i);
+        if (isnan(outVector->data.F64[i])) {
+            // Free allocated vector
+            psFree(outVector);
+            outVector = NULL;
+            // Break out of loop since error detected
+            break;
+        }
+    }
+
+    return outVector;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psLookupTable.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psLookupTable.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psLookupTable.h	(revision 22158)
@@ -0,0 +1,190 @@
+/** @file  psLookupTable.h
+*
+*  @brief This file defines the structure and functions for table lookups.
+*
+*  @author PAP, IfA
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-08-09 01:40:08 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifndef PS_LOOKUPTABLE_H
+#define PS_LOOKUPTABLE_H
+
+/// @addtogroup DataContainer Data Containers
+/// @{
+
+#include "psType.h"
+#include "psVector.h"
+#include "psArray.h"
+#include "psLogMsg.h"
+#include "psString.h"
+
+/** Lookup table structure
+ *
+ *  Holds table data read from external data files.
+ *
+ */
+typedef struct {
+    psString filename;                  ///< Name of file with table
+    psString format;                    ///< scanf-like format string for file
+    long indexCol;                     ///< Column of the index vector (starting at zero)
+    psVector *index;                   ///< Vector of independent index values
+    psArray *values;                   ///< Array of dependent table values corresponding to index values
+    const double validFrom;            ///< Lower bound for rable read
+    const double validTo;              ///< Upper bound for table read
+} psLookupTable;
+
+#define PS_ASSERT_LOOKUPTABLE_NON_NULL(NAME, RVAL) \
+if (!(NAME) || !(NAME)->filename || strlen((NAME)->filename) == 0 || \
+    !(NAME)->format || strlen((NAME)->format) == 0 || (NAME)->index < 0) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: Lookup table %s or one of its components is NULL.", \
+            #NAME); \
+    return RVAL; \
+}
+
+/** Lookup table lookup status and error conditions
+ *
+ *  Success, failure, and status conditions for table lookups.
+ */
+typedef enum {
+    PS_LOOKUP_SUCCESS             = 0x0000,        ///< Table lookup succeeded
+    PS_LOOKUP_PAST_TOP            = 0x0101,        ///< Lookup off top of table
+    PS_LOOKUP_PAST_BOTTOM         = 0x0102,        ///< Lookup off bottom of table
+    PS_LOOKUP_ERROR               = 0x0104         ///< Any other type of lookup error
+} psLookupStatusType;
+
+
+/** Lookup table parse status and error conditions
+ *
+ *  Success, failure, and status conditions for table parsing.
+ */
+typedef enum {
+    PS_PARSE_SUCCESS              = 0x0000,        ///< Table lookup succeeded
+    PS_PARSE_ERROR_TYPE           = 0x0101,        ///< Error parsing type
+    PS_PARSE_ERROR_VALUE          = 0x0102,        ///< Error parsing numerical value
+    PS_PARSE_ERROR_GENERAL        = 0x0104         ///< Any other type of lookup error
+}psParseErrorType;
+
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr
+ *  datatype.
+ *
+ *  @return bool:       True if the pointer matches a psLookupTable structure,
+ *  false otherwise.
+ */
+bool psMemCheckLookupTable(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+
+/** Allocator for psLookupTable struct
+ *
+ *  Allocates a new psLookupTable struct.
+ *
+ *  @return psLookupTable*     New psLookupTable struct.
+ */
+#ifdef DOXYGEN
+psLookupTable* psLookupTableAlloc(
+    const char *filename,              ///< Name of file to read
+    const char *format,                ///< scanf-like format string
+    long indexCol                      ///< Column of the index vector (starting at zero)
+);
+#else // ifdef DOXYGEN
+psLookupTable* p_psLookupTableAlloc(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    const char *filename,              ///< Name of file to read
+    const char *format,                ///< scanf-like format string
+    long indexCol                      ///< Column of the index vector (starting at zero)
+) PS_ATTR_MALLOC;
+#define psLookupTableAlloc(filename, format, indexCol) \
+      p_psLookupTableAlloc(__FILE__, __LINE__, __func__, filename, format, indexCol)
+#endif // ifdef DOXYGEN
+
+
+/** Read vectors from file
+ *
+ *  Read numeric vectors from ASCII text file
+ *
+ *  @return psArray*  New array of psVectors corresponding to the columns of the table
+ */
+psArray *psVectorsReadFromFile(
+    const char* filename,              ///< File to be read
+    const char* format                 ///< scanf-like format string
+);
+
+
+/** Import arrays of vectors into a table
+ *
+ *  Import array of vectors read from text file into a table structure
+ *
+ *  @return psLookupTable*  Lookup table structure with array vector data
+ */
+#ifdef DOXYGEN
+bool psLookupTableImport(
+    psLookupTable *table,              ///< Lookup table into which to import
+    const psArray *vectors,            ///< Array of vectors
+    long indexCol                      ///< Index of the index vector in the array of vectors
+);
+#else // ifdef DOXYGEN
+bool p_psLookupTableImport(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psLookupTable *table,               ///< Lookup table into which to import
+    psArray *vectors,                   ///< Array of vectors
+    long indexCol                       ///< Index of the index vector in the array of vectors
+);
+#define psLookupTableImport(table, vectors, indexCol) \
+      p_psLookupTableImport(__FILE__, __LINE__, __func__, table, vectors, indexCol)
+#endif // ifdef DOXYGEN
+
+
+/** Read lookup table
+ *
+ *  Reads a lookup table and fills corresponding psLookupTable struct.
+ *
+ *  @return long:     Number of valid lines read
+ */
+long psLookupTableRead(
+    psLookupTable *table               ///< Table to read
+);
+
+
+/** Lookup and interpolate value from table.
+ *
+ *  Interpolates value from table. Sets status bit for success or one of
+ *  several possible failure conditions.
+ *
+ *  @return double     Interpolation value at index
+ */
+double psLookupTableInterpolate(
+    const psLookupTable *table,        ///< Table with data
+    double index,                      ///< Value to be interpolated
+    long column                        ///< Column in table to be interpolated
+);
+
+
+/** Lookup and interpolate all values from table.
+ *
+ *  Interpolates all values from table. Sets status bit for success or one of
+ *  several possible failure conditions.
+ *
+ *  @return psVector*     Interpolation values calculated at index
+ */
+psVector* psLookupTableInterpolateAll(
+    const psLookupTable *table,         ///< Table with data
+    double index                        ///< Value to be interpolated
+);
+
+
+/// @}
+#endif // #ifndef PS_LOOKUPTABLE_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadata.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadata.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadata.c	(revision 22158)
@@ -0,0 +1,1585 @@
+/** @file  psMetadata.c
+ *
+ *
+ *  @brief Contains metadata structures, enumerations and functions prototypes.
+ *
+ *  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
+ *  prototypes necessary creating psLib metadata APIs
+ *
+ *  @ingroup Metadata
+ *
+ *  @author Robert DeSonia, MHPCC
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.171 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-24 22:42:28 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/******************************************************************************/
+/*  INCLUDE FILES                                                             */
+/******************************************************************************/
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "fitsio.h"
+#include "psType.h"
+#include "psMemory.h"
+#include "psError.h"
+#include "psAbort.h"
+#include "psList.h"
+#include "psHash.h"
+#include "psVector.h"
+#include "psMetadata.h"
+#include "psLookupTable.h"
+#include "psString.h"
+
+#include "psAssert.h"
+#include "psLogMsg.h"
+#include "psTrace.h"
+
+/******************************************************************************/
+/*  DEFINE STATEMENTS                                                         */
+/******************************************************************************/
+
+#define MAX_STRING_SIZE 1024            // Maximum string size for psMetadatItem
+
+/******************************************************************************/
+/*  TYPE DEFINITIONS                                                          */
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  GLOBAL VARIABLES                                                         */
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  FILE STATIC VARIABLES                                                    */
+/*****************************************************************************/
+
+static psS32 metadataId = 0;
+
+/*****************************************************************************/
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+/*****************************************************************************/
+
+static psMetadataItem* makeMetaMulti(psHash* table,
+                                     const char* key,
+                                     psMetadataItem* existing)
+{
+
+    if (existing != NULL && existing->type == PS_DATA_METADATA_MULTI) {
+        return existing;
+    }
+
+    // move any existing entry into a psList
+    psList* newList = psListAlloc(existing);
+
+    psMetadataItem* item = psMetadataItemAlloc(key,
+                           PS_DATA_METADATA_MULTI,
+                           "",
+                           newList);
+
+    if (existing != NULL) {
+        psHashRemove(table,key); // take out the old entry
+    }
+
+    psHashAdd(table, key, item); // put in the new entry
+    psMemDecrRefCounter(item); // get rid of extra reference
+
+    // free local references of newly allocated items.
+    psFree(newList);
+
+    return item;
+}
+
+static void metadataItemFree(psMetadataItem* metadataItem)
+{
+    psDataType type;
+
+    type = metadataItem->type;
+
+
+    psMemDecrRefCounter(metadataItem->name);
+    psMemDecrRefCounter(metadataItem->comment);
+
+    if(!PS_DATA_IS_PRIMITIVE(type)) {
+        psFree(metadataItem->data.V);
+    }
+}
+
+static void metadataIteratorFree(psMetadataIterator* iter)
+{
+    psFree(iter->iter);
+
+    if (iter->regex != NULL) {
+        regfree(iter->regex);
+        psFree(iter->regex);
+    }
+}
+
+static void metadataFree(psMetadata* metadata)
+{
+    psFree(metadata->list);
+    psFree(metadata->hash);
+}
+
+/*****************************************************************************/
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+/*****************************************************************************/
+
+psMetadataItem* p_psMetadataItemAlloc(const char *file,
+                                      unsigned int lineno,
+                                      const char *func,
+                                      const char *name,
+                                      psDataType type,
+                                      const char *comment,
+                                      ...)
+{
+    va_list argPtr;
+    psMetadataItem* metadataItem = NULL;
+
+    // Get the variable list parameters to pass to allocation function
+    va_start(argPtr, comment);
+
+    // Call metadata item allocation
+    metadataItem = p_psMetadataItemAllocV(file, lineno, func, name, type, comment, argPtr);
+
+    // Clean up stack after variable arguement has been used
+    va_end(argPtr);
+
+    return metadataItem;
+}
+
+bool psMemCheckMetadataItem(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)metadataItemFree );
+}
+
+
+#define METADATAITEM_ALLOC_TYPE(NAME,TYPE,METATYPE) \
+psMetadataItem* psMetadataItemAlloc##NAME(const char* name, \
+        const char* comment, \
+        TYPE value) \
+{ \
+    return psMetadataItemAlloc(name, METATYPE, comment, value); \
+}
+
+METADATAITEM_ALLOC_TYPE(Str,const char*,PS_DATA_STRING)
+METADATAITEM_ALLOC_TYPE(F32,psF32,PS_DATA_F32)
+METADATAITEM_ALLOC_TYPE(F64,psF64,PS_DATA_F64)
+METADATAITEM_ALLOC_TYPE(S8,psS8,PS_DATA_S8)
+METADATAITEM_ALLOC_TYPE(S16,psS16,PS_DATA_S16)
+METADATAITEM_ALLOC_TYPE(S32,psS32,PS_DATA_S32)
+METADATAITEM_ALLOC_TYPE(S64,psS64,PS_DATA_S64)
+METADATAITEM_ALLOC_TYPE(U8,psU8,PS_DATA_U8)
+METADATAITEM_ALLOC_TYPE(U16,psU16,PS_DATA_U16)
+METADATAITEM_ALLOC_TYPE(U32,psU32,PS_DATA_U32)
+METADATAITEM_ALLOC_TYPE(U64,psU64,PS_DATA_U64)
+METADATAITEM_ALLOC_TYPE(Bool,bool,PS_DATA_BOOL)
+
+psMetadataItem* psMetadataItemAllocPtr(const char *name,
+                                       psDataType type,
+                                       const char *comment,
+                                       psPtr value)
+{
+    return (psMetadataItemAlloc(name, type, comment, value));
+}
+
+
+psMetadataItem* p_psMetadataItemAllocV(const char *file,
+                                     unsigned int lineno,
+                                     const char *func,
+                                     const char *name,
+                                     psDataType type,
+                                     const char *comment,
+                                     va_list argPtr)
+{
+    PS_ASSERT_STRING_NON_EMPTY(name, NULL);
+    PS_ASSERT_INT_POSITIVE(type, NULL);
+
+    // Allocate metadata item
+    psMetadataItem *metadataItem = (psMetadataItem*) p_psAlloc(file, lineno, func, sizeof(psMetadataItem));
+    metadataItem->data.V = NULL;
+
+    // Set deallocator
+    psMemSetDeallocator(metadataItem, (psFreeFunc) metadataItemFree);
+
+    // XXX Does it make sense allocate a NULL string here?  It seems like this
+    // is just a waste of memory but something, somewhere, is probably
+    // dependant on this behavior so I'm leaving it in place for the time
+    // being. -JH
+
+    // Allocate and set metadata item comment
+    if (comment == NULL) {
+        // Per SDRS, null isn't allowed, must use "" instead
+        metadataItem->comment = p_psStringCopy(file, lineno, func, "");
+    } else {
+        metadataItem->comment = p_psStringCopy(file, lineno, func, comment);
+    }
+
+    // Set metadata item unique id
+    *(psS32 *)(&metadataItem->id) = ++metadataId;
+
+    // Set metadata item type
+    metadataItem->type = type & PS_METADATA_TYPE_MASK;
+
+    // Allocate and set metadata item name
+    metadataItem->name = p_psStringCopy(file, lineno, func, name);
+
+    // Set metadata item value
+    switch(metadataItem->type) {
+    case PS_DATA_BOOL:
+        metadataItem->data.B = (bool)va_arg(argPtr, psS32);
+        break;
+    case PS_DATA_S8:
+        metadataItem->data.S8 = (psS8)va_arg(argPtr, psS32);
+        break;
+    case PS_DATA_S16:
+        metadataItem->data.S16 = (psS16)va_arg(argPtr, psS32);
+        break;
+    case PS_DATA_S32:
+        metadataItem->data.S32 = (psS32)va_arg(argPtr, psS32);
+        break;
+    case PS_DATA_S64:
+        metadataItem->data.S64 = (psS64)va_arg(argPtr, psS64);
+        break;
+    case PS_DATA_U8:
+        metadataItem->data.U8 = (psU8)va_arg(argPtr, psU32);
+        break;
+    case PS_DATA_U16:
+        metadataItem->data.U16 = (psU16)va_arg(argPtr, psU32);
+        break;
+    case PS_DATA_U32:
+        metadataItem->data.U32 = (psU32)va_arg(argPtr, psU32);
+        break;
+    case PS_DATA_U64:
+        metadataItem->data.U64 = (psU64)va_arg(argPtr, psU64);
+        break;
+    case PS_DATA_F32:
+        metadataItem->data.F32 = (psF32)va_arg(argPtr, psF64);
+        break;
+    case PS_DATA_F64:
+        metadataItem->data.F64 = (psF64)va_arg(argPtr, psF64);
+        break;
+    case PS_DATA_STRING: {
+        // Copy input strings, so they can be messed with
+        char *string = va_arg(argPtr, char*);
+        metadataItem->data.str = (string ? p_psStringCopy(file, lineno, func, string) : NULL);
+        break;
+    }
+    case     PS_DATA_ARRAY:                     // psArray
+    case     PS_DATA_BITSET:                    // psBitSet
+    case     PS_DATA_CUBE:                      // psCube
+    case     PS_DATA_FITS:                      // psFits
+    case     PS_DATA_HASH:                      // psHash
+    case     PS_DATA_HISTOGRAM:                 // psHistogram
+    case     PS_DATA_IMAGE:                     // psImage
+    case     PS_DATA_KERNEL:                    // psKernel
+    case     PS_DATA_LIST:                      // psList
+    case     PS_DATA_LOOKUPTABLE:               // psLookupTable
+    case     PS_DATA_METADATA:                  // psMetadata
+    case     PS_DATA_METADATAITEM:              // psMetadataItem
+    case     PS_DATA_MINIMIZATION:              // psMinimization
+    case     PS_DATA_PIXELS:                    // psPixels
+    case     PS_DATA_PLANE:                     // psPlane
+    case     PS_DATA_PLANEDISTORT:              // psPlaneDistort
+    case     PS_DATA_PLANETRANSFORM:            // psPlaneTransform
+    case     PS_DATA_POLYNOMIAL1D:              // psPolynomial1D
+    case     PS_DATA_POLYNOMIAL2D:              // psPolynomial2D
+    case     PS_DATA_POLYNOMIAL3D:              // psPolynomial3D
+    case     PS_DATA_POLYNOMIAL4D:              // psPolynomial4D
+    case     PS_DATA_PROJECTION:                // psProjection
+    case     PS_DATA_REGION:                  // psRegion
+    case     PS_DATA_SCALAR:                    // psScalar
+    case     PS_DATA_SPHERE:                    // psSphere
+    case     PS_DATA_SPHEREROT:                 // psSphereTransform
+    case     PS_DATA_SPLINE1D:                  // psSpline1D
+    case     PS_DATA_STATS:                     // psStats
+    case     PS_DATA_TIME:                      // psTime
+    case     PS_DATA_VECTOR:                    // psVector
+    case     PS_DATA_UNKNOWN:                   // "other"
+    case     PS_DATA_METADATA_MULTI:
+        // Copy of input data not performed due to variability of data types
+        metadataItem->data.V = p_psMemIncrRefCounter(file, lineno, func, va_arg(argPtr, psPtr));
+        break;
+    default:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Specified psDataType, %d, is not supported."), type);
+        psFree(metadataItem);
+        metadataItem = NULL;
+        break;
+    }
+
+    return metadataItem;
+}
+
+psMetadata* p_psMetadataAlloc(const char *file,
+                              unsigned int lineno,
+                              const char *func)
+{
+    psList* list = NULL;
+    psHash* hash = NULL;
+    psMetadata* metadata = NULL;
+
+    // Allocate metadata
+    metadata = (psMetadata*) p_psAlloc(file, lineno, func, sizeof(psMetadata));
+    // Set deallocator
+    psMemSetDeallocator(metadata, (psFreeFunc) metadataFree);
+
+    // Allocate metadata's internal containers
+    list = (psList*) psListAlloc(NULL);
+    hash = (psHash*) psHashAlloc(10);
+
+    metadata->list = list;
+    metadata->hash = hash;
+
+    return metadata;
+}
+
+
+bool psMemCheckMetadata(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)metadataFree );
+}
+
+
+psMetadataItem *p_psMetadataItemCopy(const char *file,
+                                     unsigned int lineno,
+                                     const char *func,
+                                     const psMetadataItem *in)
+{
+    PS_ASSERT_METADATA_ITEM_NON_NULL(in,NULL);
+
+    psMetadataItem *newItem = NULL;     // New metadata item, to be returned
+
+    #define PS_METADATA_ITEM_COPY_CASE(NAME,TYPE) \
+case PS_DATA_##NAME: \
+    newItem = p_psMetadataItemAlloc(file, lineno, func, in->name, PS_DATA_##NAME, in->comment, in->data.TYPE); \
+    break; \
+
+    switch (in->type) {
+        // Simple types
+        PS_METADATA_ITEM_COPY_CASE(BOOL,B);
+        PS_METADATA_ITEM_COPY_CASE(S8,S8);
+        PS_METADATA_ITEM_COPY_CASE(S16,S16);
+        PS_METADATA_ITEM_COPY_CASE(S32,S32);
+        PS_METADATA_ITEM_COPY_CASE(S64,S64);
+        PS_METADATA_ITEM_COPY_CASE(U8,U8);
+        PS_METADATA_ITEM_COPY_CASE(U16,U16);
+        PS_METADATA_ITEM_COPY_CASE(U32,U32);
+        PS_METADATA_ITEM_COPY_CASE(U64,U64);
+        PS_METADATA_ITEM_COPY_CASE(F32,F32);
+        PS_METADATA_ITEM_COPY_CASE(F64,F64);
+        PS_METADATA_ITEM_COPY_CASE(STRING,V); // This will copy the string, not point at it.
+    case PS_DATA_VECTOR: {
+            PS_ASSERT_PTR_NON_NULL(in->data.V, NULL);
+            psVector *vecCopy = psVectorCopy(NULL, (psVector*)(in->data.V),
+                                             ((psVector*)(in->data.V))->type.type);
+            newItem = p_psMetadataItemAlloc(file, lineno, func, in->name, PS_DATA_VECTOR, in->comment, vecCopy);
+            psFree(vecCopy);    // Drop reference
+            break;
+        }
+    case PS_DATA_TIME: {
+            psTime *timeCopy = NULL;
+            // pass through NULL values
+            if (in->data.V) {
+                timeCopy = psTimeCopy( (psTime*)(in->data.V) );
+                if (timeCopy == NULL) {
+                    psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                            "Error copying time.  Time skipped.\n");
+                }
+            }
+            newItem = p_psMetadataItemAlloc(file, lineno, func, in->name, PS_DATA_TIME, in->comment, timeCopy);
+            if (timeCopy) {
+                psFree(timeCopy);   // Drop reference
+            }
+            break;
+        }
+    case PS_DATA_METADATA: {
+            // Metadata: copy the next level and stuff that in too
+            psMetadata *metadata = psMetadataCopy(NULL, in->data.md);
+            newItem = p_psMetadataItemAlloc(file, lineno, func, in->name, PS_DATA_METADATA, in->comment, metadata);
+            psFree(metadata);       // Drop reference
+            break;
+        }
+    case PS_DATA_REGION: {
+            psRegion *region = in->data.V; // The region
+            psRegion *new = psRegionAlloc(region->x0, region->x1, region->y0, region->y1); // Copy of the region
+            newItem = p_psMetadataItemAlloc(file, lineno, func, in->name, PS_DATA_REGION, in->comment, new);
+            psFree(new);                  // Drop reference
+            break;
+        }
+    default:
+        // Other kinds of pointers
+      // XXX EAM : why was this a warning??
+      // psWarning("Copying a pointer in the metadata item: %s (%x)\n", in->name, in->type);
+        newItem = p_psMetadataItemAlloc(file, lineno, func, in->name, in->type, in->comment, in->data.V);
+        break;
+    }
+
+    return newItem;
+}
+
+psMetadata *p_psMetadataCopy(const char *file,
+                             unsigned int lineno,
+                             const char *func,
+                             psMetadata *out,
+                             const psMetadata *in)
+{
+    PS_ASSERT_METADATA_NON_NULL(in, NULL);
+
+    bool errorOccurred = false;
+    bool outAlloced = false;
+    if (out ==  NULL) {
+        out = p_psMetadataAlloc(file, lineno, func);
+        outAlloced = true;
+    }
+    psMetadataIterator *iter = psMetadataIteratorAlloc(in, PS_LIST_HEAD, NULL);
+    psMetadataItem *inItem = NULL;
+    while ((inItem = psMetadataGetAndIncrement(iter))) {
+        // Need to look for MULTI, which won't be picked up using the iterator.
+        psMetadataItem *multiCheckItem = psMetadataLookup(in, inItem->name);
+        unsigned int flag = PS_META_REPLACE; // Flag to indicate MULTI; otherwise, replace
+        if (multiCheckItem->type == PS_DATA_METADATA_MULTI) {
+            psTrace("psLib.types", 10, "MULTI: %s (%s)\n", inItem->name, inItem->comment);
+            flag = PS_META_DUPLICATE_OK;
+        }
+        psTrace("psLib.types", 5, "Copying %s (%s)...\n", inItem->name, inItem->comment);
+
+        // Copy the item and add it on
+        psMetadataItem *newItem = psMetadataItemCopy(inItem); // Copied item
+        if (!psMetadataAddItem(out, newItem, PS_LIST_TAIL, flag)) {
+            psError(PS_ERR_UNKNOWN, false, "Error copying %s (%s) in the metadata\n",
+                    inItem->name, inItem->comment);
+            if (outAlloced) {
+                psFree(out);
+                psFree(newItem);
+                psFree(iter);
+                return NULL;
+            } else {
+                errorOccurred = true;
+            }
+        }
+        psFree(newItem);                // Drop reference
+    }
+    psFree(iter);
+
+    if (errorOccurred) {
+        return NULL;
+    }
+
+    return out;
+}
+
+// this function copies the input metadata to the output, raising an error
+// if any entries in 'in' a) do not exist in 'out' or b) have a different type
+bool p_psMetadataUpdate(const char *file,
+                        unsigned int lineno,
+                        const char *func,
+                        psMetadata *out,
+                        const psMetadata *in)
+{
+    PS_ASSERT_METADATA_NON_NULL(in, NULL);
+    PS_ASSERT_METADATA_NON_NULL(out, NULL);
+
+    bool result = true;
+
+    // we loop over the metadata container by item, not by name.  this pushes us directly into
+    // the elements of the MULTI items; we miss the containers.  We need to check the
+    // (possible) MULTI containers to see how to set the flags.  If we encounter a MULTI which
+    // is requesting REPLACE, then the first item on the input list from that MULTI should be
+    // added with the REPLACE flag turned on; the rest should have the REPLACE flag turned off.
+    // save a list of the MULTI entries which has REPLACE turned off?
+
+    psArray *multiItems = psArrayAllocEmpty (128);
+
+    psMetadataIterator *iter = psMetadataIteratorAlloc(in, PS_LIST_HEAD, NULL);
+    psMetadataItem *inItem = NULL;
+    while ((inItem = psMetadataGetAndIncrement(iter))) {
+
+        // it is not possible to have RESET && UPDATE
+        // is it possible to have !RESET && !UPDATE?
+        // are these mutually exclusive conditions?
+        // input MULTI & RESET  : replace an existing MULTI or ITEM of same name
+        // input MULTI & UPDATE : supplement an existing MULTI or ITEM of same name
+        // in both cases the name must exist in 'out'
+
+        // Need to look for MULTI, which won't be picked up using the iterator.
+        psMetadataItem *multiCheckItem = psMetadataLookup(in, inItem->name);
+
+        // default operation for the new metadata item (replace existing entry, require existence & type)
+        unsigned int flag = PS_META_REPLACE | PS_META_REQUIRE_ENTRY | PS_META_REQUIRE_TYPE;
+
+        // for MULTI items, the mode is carried on the multi container
+        if (PS_METADATA_ITEM_GET_TYPE(multiCheckItem) == PS_DATA_METADATA_MULTI) {
+            psTrace("psLib.types", 10, "MULTI: %s (%s)\n", inItem->name, inItem->comment);
+            if (multiCheckItem->type & PS_META_UPDATE_FOLDER) {
+                psTrace("psLib.types", 10, "supplement MULTI with new entries\n");
+                flag = PS_META_DUPLICATE_OK | PS_META_REQUIRE_ENTRY | PS_META_REQUIRE_TYPE;
+            } else {
+                multiCheckItem->type |= PS_META_UPDATE_FOLDER;
+                // save this multi so we can reset their flags below
+                psArrayAdd (multiItems, 128, multiCheckItem);
+            }
+        }
+        psTrace("psLib.types", 5, "Copying %s (%s)...\n", inItem->name, inItem->comment);
+
+        // for METADATA folders, do something different?
+        if (PS_METADATA_ITEM_GET_TYPE(inItem) == PS_DATA_METADATA) {
+            if (inItem->type & PS_META_UPDATE_FOLDER) {
+                flag = PS_META_UPDATE_FOLDER | PS_META_REQUIRE_ENTRY | PS_META_REQUIRE_TYPE;
+            }
+        }
+
+        // Copy the item and add it on.  report all errors so we get a listing
+        psMetadataItem *newItem = psMetadataItemCopy(inItem); // Copied item
+        if (!psMetadataAddItem(out, newItem, PS_LIST_TAIL, flag)) {
+            psError(PS_ERR_UNKNOWN, false, "Error copying %s\n", inItem->name);
+            result = false;
+        }
+        psFree(newItem);                // Drop reference
+    }
+    psFree(iter);
+
+    // remove the UPDATE_FOLDER flag from the following MULTI items
+    for (int i = 0; i < multiItems->n; i++) {
+        psMetadataItem *item = multiItems->data[i];
+        item->type &= ~PS_META_UPDATE_FOLDER;
+    }
+    psFree (multiItems);
+
+    if (!result) {
+        psError(PS_ERR_UNKNOWN, false, "failed to update metadata\n");
+    }
+
+    return result;
+}
+
+// this function copies the input metadata to the output, supplementing existing metadata
+// folders with the contents from corresponding folders in the output
+bool p_psMetadataOverlay(const char *file,
+                         unsigned int lineno,
+                         const char *func,
+                         psMetadata *out,
+                         const psMetadata *in)
+{
+    PS_ASSERT_METADATA_NON_NULL(in, NULL);
+    PS_ASSERT_METADATA_NON_NULL(out, NULL);
+
+    bool result = true;
+
+    psMetadataIterator *iter = psMetadataIteratorAlloc(in, PS_LIST_HEAD, NULL);
+    psMetadataItem *inItem = NULL;
+    while ((inItem = psMetadataGetAndIncrement(iter))) {
+        // Need to look for MULTI, which won't be picked up using the iterator.
+        psMetadataItem *multiCheckItem = psMetadataLookup(in, inItem->name);
+        unsigned int flag = PS_META_REPLACE; // Flag to indicate MULTI; otherwise, replace
+        if (multiCheckItem->type == PS_DATA_METADATA_MULTI) {
+            psTrace("psLib.types", 10, "MULTI: %s (%s)\n", inItem->name, inItem->comment);
+            flag = PS_META_DUPLICATE_OK;
+        }
+        psTrace("psLib.types", 5, "Copying %s (%s)...\n", inItem->name, inItem->comment);
+
+        // if this is a metadata, and it has a corresponding match, overlay them
+        if (inItem->type == PS_DATA_METADATA) {
+            bool status;
+            psMetadata *outFolder = psMetadataLookupMetadata (&status, out, inItem->name);
+            if (outFolder) {
+                if (!psMetadataOverlay (outFolder, inItem->data.md)) {
+                    fprintf (stderr, "Error overlaying metadata folder\n");
+                    result = false;
+                }
+                continue;
+            }
+        }
+
+        // Copy the item and add it on.  report all errors so we get a listing
+        psMetadataItem *newItem = psMetadataItemCopy(inItem); // Copied item
+        if (!psMetadataAddItem(out, newItem, PS_LIST_TAIL, flag)) {
+            fprintf (stderr, "Error copying %s\n", inItem->name);
+            result = false;
+        }
+        psFree(newItem);                // Drop reference
+    }
+    psFree(iter);
+
+    if (!result) {
+        psError(PS_ERR_UNKNOWN, false, "failed to update metadata\n");
+    }
+    return result;
+}
+
+// may need to extend this to change the keyname in the copy
+bool psMetadataItemSupplement(psMetadata *out,
+                              const psMetadata *in,
+                              const char *key)
+{
+    PS_ASSERT_METADATA_NON_NULL(in, false);
+    PS_ASSERT_METADATA_NON_NULL(out, false);
+    PS_ASSERT_STRING_NON_EMPTY(key, false);
+
+    psMetadataItem *item = psMetadataLookup(in, key);
+    if (!item) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Could not find '%s' in metadata.\n", key);
+        return false;
+    }
+    if (!psMetadataAddItem(out, item, PS_LIST_TAIL, PS_META_REPLACE) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Could not add %s to metadata.\n", key);
+        return false;
+    }
+
+    return true;
+}
+
+// XXX is it sensible that item is a 'const' here?
+bool psMetadataAddItem(psMetadata *md,
+                       const psMetadataItem *item,
+                       int location,
+                       psS32 flags)
+{
+    PS_ASSERT_METADATA_NON_NULL(md,false);
+    PS_ASSERT_METADATA_ITEM_NON_NULL(item,false);
+
+    psHash *mdTable = md->hash;
+    psList *mdList = md->list;
+    char *key = item->name;
+
+    // See if key is already in table
+    psMetadataItem *existingEntry = psHashLookup(mdTable, key);
+
+    // this block handles cases for the MULTI items
+    if (item->type == PS_DATA_METADATA_MULTI) {
+        // the incoming entry is PS_DATA_METADATA_MULTI
+
+        // Shouldn't have a second reference to the same MULTI in a single Metadata!
+        // XXX not sure I understand this case
+        if (item == existingEntry) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Cannot have 2 references to the same MULTI in a single Metadata!");
+            return false;
+        }
+
+        if (flags & PS_META_REPLACE) {
+            // drop the existing entry or entries
+            psMetadataRemoveKey(md, key);
+        } else {
+            // elevate the existing hash entry to be PS_DATA_METADATA_MULTI
+            existingEntry = makeMetaMulti(mdTable,key,existingEntry);
+        }
+
+        // add all the items in the incoming entry to metadata
+        psList* list = item->data.list;
+        if (list != NULL) {
+            psListIterator* iter = psListIteratorAlloc(list,PS_LIST_HEAD,true);
+            psMetadataItem* listItem;
+            while ((listItem=(psMetadataItem*)psListGetAndIncrement(iter)) != NULL) {
+                psMetadataAddItem(md,listItem,location,flags);
+            }
+            psFree(iter);
+        }
+
+        return true; // all done.
+    }
+
+    // special block for items which are METADATA folders
+    if (existingEntry && (item->type == PS_DATA_METADATA)) {
+        // REPLACE and UPDATE must be mutually exclusive
+        psAssert ((!((flags & PS_META_REPLACE) && (flags & PS_META_UPDATE_FOLDER))), "cannot have both REPLACE and UPDATE");
+
+        # if (0)
+        // handle the case of replace below
+        if (flags & PS_META_REPLACE) {
+            // drop the existing entry (skip if we are replacing with same pointer)
+            // XXX what if existingEntry is a MULTI?  drop all?
+            // XXX this segment does not check for matched types
+            if (item != existingEntry) {
+                psMetadataRemoveKey(md, key);
+            }
+            existingEntry = NULL;
+        }
+        # endif
+
+        if (flags & PS_META_UPDATE_FOLDER) {
+            if (existingEntry->type != PS_DATA_METADATA) {
+                psError(PS_ERR_UNKNOWN, false, "invalid to request UPDATE for metadata which matches another type");
+                return false;
+            }
+
+            // merge the existing entry : this completes the insert
+            if (!psMetadataCopy ((psMetadata *)existingEntry->data.V, (psMetadata *)item->data.V)) {
+                psError(PS_ERR_UNKNOWN, false, "failed to copy new metadata on existing");
+                return false;
+            }
+            return true;
+        }
+    }
+
+    // how the item is added to the hash depends on prior existence, flags, etc.
+    // XXX i think these cases are overloaded - are all combinations possible?
+    if (existingEntry) { // prior existence
+
+        // duplicate entries allowed - add another entry.
+        if ((existingEntry->type == PS_DATA_METADATA_MULTI) || (flags & PS_META_DUPLICATE_OK)) {
+
+            // make sure the existing entry is PS_DATA_METADATA_MULTI
+            existingEntry = makeMetaMulti(mdTable,key,existingEntry);
+
+            // add item to the existing hash's list of duplicate entries
+            if (!psListAdd(existingEntry->data.list, PS_LIST_TAIL, (psMetadataItem *) item) ) {
+                psError(PS_ERR_UNKNOWN, false, _("Failed to add metadata item, %s, to metadata collection list."), key);
+                return false;
+            }
+            // add to the metadata list of entries
+            if (!psListAdd(mdList, location, (psMetadataItem *) item)) {
+                psError(PS_ERR_UNKNOWN, false, _("Failed to add metadata item, %s, to metadata collection list."), key);
+                return false;
+            }
+            return true;
+        }
+
+        // replace entry instead of creating a duplicate entry.
+        if (flags & PS_META_REPLACE) {
+
+            if ((flags & PS_META_REQUIRE_TYPE) && (existingEntry->type != item->type)) {
+                psError (PS_ERR_UNKNOWN, true, _("Existing item %s does not match type (%x) for item requiring matching type (%x)"), key, existingEntry->type, item->type);
+                return false;
+            }
+            if (item != existingEntry) {
+                // Replacing an item with itself can lead to memory corruption
+                // when you blow away what you're trying to add
+                psMetadataRemoveKey(md, key);
+                // add to the metadata has of entries
+                if (!psHashAdd(mdTable, key, (psMetadataItem *) item)) {
+                    psError(PS_ERR_UNKNOWN, false, _("Failed to add metadata item, %s, to metadata collection list."), key);
+                    return false;
+                }
+                // add to the metadata list of entries
+                if (!psListAdd(mdList, location, (psMetadataItem *) item)) {
+                    psError(PS_ERR_UNKNOWN, false, _("Failed to add metadata item, %s, to metadata collection list."), key);
+                    return false;
+                }
+                return true;
+            } else {
+              // adding myself back to the list; this is a NOP
+              return true;
+            }
+        }
+
+        // if specified, keep the existing entry
+        if (flags & PS_META_NO_REPLACE) {
+            return true;
+        }
+
+        // default is to error on duplicate entry.
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Duplicate metadata item name: %s is not allowed.  Use a psMetadataFlags option to allow such action."), item->name);
+        return false;
+    }
+
+    // OK, this is a new item.
+    if (flags & PS_META_REQUIRE_ENTRY) {
+        psError (PS_ERR_UNKNOWN, true, _("No matching item found for item requiring existing entry (%s)"), key);
+        return false;
+    }
+
+    // Node doesn't exist - Add new metadata item to metadata collection's hash
+    psHashAdd(mdTable, key, (psMetadataItem *) item);
+
+    // Create a multi, if requested
+    if (flags & PS_META_DUPLICATE_OK) {
+        makeMetaMulti(mdTable, key, (psMetadataItem *) item); // Casting away const!
+    }
+
+    if (!psListAdd(mdList, location, (psPtr)item)) {
+        psError(PS_ERR_UNKNOWN, false, _("Failed to add metadata item, %s, to metadata collection list."), key);
+        return false;
+    }
+
+    return true;
+}
+
+bool psMetadataAdd(psMetadata *md,
+                   long location,
+                   const char *name,
+                   int format,
+                   const char *comment,...)
+{
+    PS_ASSERT_METADATA_NON_NULL(md, false);
+
+    va_list argPtr;
+    va_start(argPtr, comment);
+    bool result = psMetadataAddV(md,location,name,format,comment,argPtr);
+    va_end(argPtr);
+
+    return result;
+}
+
+bool psMetadataAddV(psMetadata *md,
+                    long location,
+                    const char *name,
+                    int format,
+                    const char *comment,
+                    va_list list)
+{
+    PS_ASSERT_METADATA_NON_NULL(md,false);
+
+    psMetadataItem* metadataItem = psMetadataItemAllocV(name, format & PS_METADATA_TYPE_MASK, comment, list);
+
+    if (!psMetadataAddItem(md, metadataItem, location, format & PS_METADATA_FLAGS_MASK)) {
+        psError(PS_ERR_UNKNOWN,false,_("Failed to add metadata item to metadata collection list."));
+        psFree(metadataItem);
+        return false;
+    }
+    // Decrement reference count, since the metadata item is now in metadata collection and no longer needed
+    psFree(metadataItem);
+
+    return true;
+}
+
+#define METADATA_ADD_TYPE(NAME,TYPE,METATYPE) \
+bool psMetadataAdd##NAME(psMetadata* md, long where, const char* name, \
+                         int format, const char* comment, TYPE value) { \
+    return psMetadataAdd(md, where, name, format | METATYPE, comment, value); \
+}
+
+METADATA_ADD_TYPE(Bool,bool,PS_DATA_BOOL)
+METADATA_ADD_TYPE(S8,psS8,PS_DATA_S8)
+METADATA_ADD_TYPE(S16,psS16,PS_DATA_S16)
+METADATA_ADD_TYPE(S32,psS32,PS_DATA_S32)
+METADATA_ADD_TYPE(S64,psS64,PS_DATA_S64)
+METADATA_ADD_TYPE(U8,psU8,PS_DATA_U8)
+METADATA_ADD_TYPE(U16,psU16,PS_DATA_U16)
+METADATA_ADD_TYPE(U32,psU32,PS_DATA_U32)
+METADATA_ADD_TYPE(U64,psU64,PS_DATA_U64)
+METADATA_ADD_TYPE(F32,psF32,PS_DATA_F32)
+METADATA_ADD_TYPE(F64,psF64,PS_DATA_F64)
+METADATA_ADD_TYPE(List,psList*,PS_DATA_LIST)
+METADATA_ADD_TYPE(Str,const char*,PS_DATA_STRING)
+METADATA_ADD_TYPE(Vector,psVector*,PS_DATA_VECTOR)
+METADATA_ADD_TYPE(Image,psImage*,PS_DATA_IMAGE)
+METADATA_ADD_TYPE(Hash,psHash*,PS_DATA_HASH)
+METADATA_ADD_TYPE(LookupTable,psLookupTable*,PS_DATA_LOOKUPTABLE)
+METADATA_ADD_TYPE(Metadata,psMetadata*,PS_DATA_METADATA)
+METADATA_ADD_TYPE(Array,psArray*,PS_DATA_ARRAY)
+METADATA_ADD_TYPE(Time,psTime*,PS_DATA_TIME)
+METADATA_ADD_TYPE(Unknown,psPtr,PS_DATA_UNKNOWN)
+
+bool psMetadataAddPtr(psMetadata* md, long where, const char* name,
+                      psDataType type, const char* comment, psPtr value)
+{
+    return psMetadataAdd(md, where, name, type, comment, value);
+}
+
+
+
+// Remove by key name
+bool psMetadataRemoveKey(psMetadata *md,
+                         const char *key)
+{
+    PS_ASSERT_METADATA_NON_NULL(md, false);
+    PS_ASSERT_STRING_NON_EMPTY(key, false);
+
+    psList* mdList = md->list;
+    psHash* mdTable = md->hash;
+
+    psMetadataItem* entry = psHashLookup(mdTable,key);
+    if (entry == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                _("Failed to remove metadata item, %s, from metadata table."), key);
+        return false;
+    }
+    if (entry->type == PS_DATA_METADATA_MULTI) {
+        psMetadataItem* listItem;
+        psListIterator* iter = psListIteratorAlloc(
+                                   entry->data.list,
+                                   PS_LIST_HEAD,true);
+        while ((listItem=psListGetAndIncrement(iter)) != NULL) {
+            psListRemoveData(mdList, listItem);
+        }
+        psFree(iter);
+        psHashRemove(mdTable,key);
+    } else {
+        psListRemoveData(mdList, entry);
+        psHashRemove(mdTable, key);
+    }
+
+    return true;
+}
+
+
+// Remove by index
+bool psMetadataRemoveIndex(psMetadata *md,
+                           long location)
+{
+    PS_ASSERT_METADATA_NON_NULL(md, false);
+
+    psList* mdList = md->list;
+    psHash* mdTable = md->hash;
+
+    psMetadataItem* entry = psListGet(mdList, location);
+    if (entry == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Could not find metadata item at index %ld."), location);
+        return false;
+    }
+    const char *key = entry->name;
+
+    if (key == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Failed to remove metadata item, at index %ld, from metadata list."),
+                location);
+        return false;
+    }
+
+    psMetadataItem* tableItem = psHashLookup(mdTable, key);
+    if (tableItem == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                _("Failed to remove metadata item, %s, from metadata table."), key);
+        return false;
+    }
+
+    if (tableItem->type == PS_DATA_METADATA_MULTI) {
+        // multiple entries with same key, remove just the specified one
+        psListRemoveData(tableItem->data.list, entry);
+    } else {
+        //Tested below.  psHashRemove can't return false here.
+        psHashRemove(mdTable, key);
+    }
+    psListRemove(mdList, location);
+
+    return true;
+}
+
+psMetadataItem* psMetadataLookup(const psMetadata *md,
+                                 const char *key)
+{
+    PS_ASSERT_METADATA_NON_NULL(md,NULL);
+    PS_ASSERT_STRING_NON_EMPTY(key,NULL);
+
+    return (psMetadataItem*)psHashLookup(md->hash, key);
+}
+
+void* psMetadataLookupPtr(bool *status,
+                          const psMetadata *md,
+                          const char *key)
+{
+    PS_ASSERT_METADATA_NON_NULL(md,NULL);
+
+    if (status) {
+        *status = true;
+    }
+
+    psMetadataItem *metadataItem = psMetadataLookup(md, key);
+    if (metadataItem == NULL) {
+        if (status) {
+            *status = false;
+        }
+        return NULL;
+    }
+    if (metadataItem->type == PS_DATA_METADATA_MULTI) {
+        // if multiple keys found, use the first.
+        //        metadataItem = (psMetadataItem*)((metadataItem->data.list)->head);
+        metadataItem = (psMetadataItem*)(metadataItem->data.list->head->data);
+        if (status) {
+            *status = true;
+        }
+    }
+
+    if(PS_DATA_IS_PRIMITIVE(metadataItem->type)) {
+        if (status) {
+            *status = false;
+        }
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified psDataType, %d, is not supported."),
+                metadataItem->type);
+        return NULL;
+    } else {
+        return metadataItem->data.V;
+    }
+}
+
+#define psMetadataLookupNumTYPE(TYPE) \
+ps##TYPE psMetadataLookup##TYPE(bool *status, const psMetadata *md, const char *key) \
+{ \
+    psMetadataItem *metadataItem = NULL; \
+    ps##TYPE value = 0; \
+    \
+    if (status) {  \
+        *status = true; \
+    } \
+    \
+    metadataItem = psMetadataLookup(md, key); \
+    if(metadataItem == NULL) { \
+        if (status) {  \
+            *status = false; \
+        } \
+        return 0; \
+    } \
+    if (metadataItem->type == PS_DATA_METADATA_MULTI) { \
+        /* if multiple keys found, use the first. */ \
+        metadataItem = (psMetadataItem*)((metadataItem->data.list)->head); \
+    } \
+    \
+    switch (metadataItem->type) { \
+    case PS_DATA_S8: \
+        value = (ps##TYPE)metadataItem->data.S8; \
+        break; \
+    case PS_DATA_S16: \
+        value = (ps##TYPE)metadataItem->data.S16; \
+        break; \
+    case PS_DATA_S32: \
+        value = (ps##TYPE)metadataItem->data.S32; \
+        break; \
+    case PS_DATA_S64: \
+        value = (ps##TYPE)metadataItem->data.S64; \
+        break; \
+    case PS_DATA_U8: \
+        value = (ps##TYPE)metadataItem->data.U8; \
+        break; \
+    case PS_DATA_U16: \
+        value = (ps##TYPE)metadataItem->data.U16; \
+        break; \
+    case PS_DATA_U32: \
+        value = (ps##TYPE)metadataItem->data.U32; \
+        break; \
+    case PS_DATA_U64: \
+        value = (ps##TYPE)metadataItem->data.U64; \
+        break; \
+    case PS_DATA_F32: \
+        value = (ps##TYPE)metadataItem->data.F32; \
+        break; \
+    case PS_DATA_F64: \
+        value = (ps##TYPE)metadataItem->data.F64; \
+        break; \
+    case PS_DATA_BOOL: \
+        if (metadataItem->data.B) { \
+            value = 1; \
+        } \
+        break; \
+    default: \
+        /* if you get to this point, the value is not a number. */ \
+        if (status) {  \
+            *status = false; \
+        }  \
+        break; \
+    } \
+    \
+    /* psFree(metadataItem); currently, the lookup doesn't increment the ref count */ \
+    return value; \
+}
+
+psMetadataLookupNumTYPE(F32)
+psMetadataLookupNumTYPE(F64)
+psMetadataLookupNumTYPE(S8)
+psMetadataLookupNumTYPE(S16)
+psMetadataLookupNumTYPE(S32)
+psMetadataLookupNumTYPE(S64)
+psMetadataLookupNumTYPE(U8)
+psMetadataLookupNumTYPE(U16)
+psMetadataLookupNumTYPE(U32)
+psMetadataLookupNumTYPE(U64)
+psMetadataLookupNumTYPE(Bool)
+
+psMetadataItem* psMetadataGet(const psMetadata *md,
+                              int location)
+{
+    psMetadataItem* entry = NULL;
+
+    PS_ASSERT_METADATA_NON_NULL(md,NULL);
+
+    entry = (psMetadataItem*) psListGet(md->list, location);
+    if (entry == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Could not find metadata item at index %d."), location);
+        return NULL;
+    }
+
+    return entry;
+}
+
+// XXX should md be const?
+psMetadataIterator* p_psMetadataIteratorAlloc(const char *file,
+                                              unsigned int lineno,
+                                              const char *func,
+                                              const psMetadata* md,
+                                              long location,
+                                              const char* regex)
+{
+    PS_ASSERT_METADATA_NON_NULL(md,NULL);
+
+    psMetadataIterator* newIter = p_psAlloc(file, lineno, func, sizeof(psMetadataIterator));
+    psMemSetDeallocator(newIter, (psFreeFunc) metadataIteratorFree);
+
+    newIter->iter = psListIteratorAlloc(md->list, location, false);
+
+    if (regex) {
+        newIter->regex = psAlloc(sizeof(regex_t));
+        int regRtn = regcomp(newIter->regex, regex, 0);
+        if (regRtn != 0) {
+            char errMsg[256];
+            regerror(regRtn, newIter->regex, errMsg, 256);
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    _("Specified regular expression is invalid.  %s."),
+                    errMsg);
+            psFree(newIter);
+            return NULL;
+        }
+        if (!psMetadataIteratorSet(newIter, location)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to set location=%ld for metadata iterator.\n", location);
+            psFree(newIter);
+            return NULL;
+        }
+    } else {
+        newIter->regex = NULL;
+    }
+
+    return newIter;
+}
+
+bool psMetadataIteratorSet(psMetadataIterator* iterator,
+                           long location)
+{
+    PS_ASSERT_METADATA_ITERATOR_NON_NULL(iterator, NULL);
+    psListIterator *listIter = iterator->iter;
+
+    regex_t *regex = iterator->regex;
+
+    // handle trivial case where no regex subsetting is required.
+    if (regex == NULL) {
+        return psListIteratorSet(listIter, location);
+    }
+
+    // If there's a regex, then we need to count into the list.
+    // We count ONLY those entries that match the regex
+
+    // Here we count in from the tail
+    if (location < 0) {
+        psListIteratorSet(listIter, PS_LIST_TAIL);
+        psMetadataItem *item;           // Item from iteration
+        int match = 0;                  // Match number
+        while (listIter->cursor && (item = listIter->cursor->data)) {
+            if (regexec(regex, item->name, 0, NULL, 0) == 0) {
+                // this key is a match
+                match--;
+                if (match == location) {
+                    break;
+                }
+            }
+            (void)psListGetAndDecrement(listIter);
+        }
+
+        // We return "true" even if we didn't find the Nth match, because the iterator is set appropriately
+        // (off the front), and subsequent calls to psMetadataGetAnd{In,De}crement will return NULL.
+        return true;
+    }
+
+    // Here we count in from the head
+    psListIteratorSet(listIter, PS_LIST_HEAD);
+    psMetadataItem *item;               // Item from iteration
+    int match = -1;                     // Match number
+    while (listIter->cursor && (item = listIter->cursor->data)) {
+        if (regexec(regex, item->name, 0, NULL, 0) == 0) {
+            // this key is a match
+            match++;
+            if (match == location) {
+                break;
+            }
+        }
+        (void)psListGetAndIncrement(listIter);
+    }
+    // We return "true" even if we didn't find the Nth match, because the iterator is set appropriately
+    // (off the end), and subsequent calls to psMetadataGetAnd{In,De}crement will return NULL.
+    return true;
+}
+
+psMetadataItem* psMetadataGetAndIncrement(psMetadataIterator* iterator)
+{
+    PS_ASSERT_METADATA_ITERATOR_NON_NULL(iterator,NULL);
+    psListIterator* listIter = iterator->iter;
+    regex_t* regex = iterator->regex;
+
+    // handle trivial case where no regex subsetting is required.
+    if (regex == NULL) {
+        return (psMetadataItem*)psListGetAndIncrement(listIter);
+    }
+
+    // Iterate until we find something matching the regex
+    psMetadataItem *newItem;            // New MD item from iteration
+    while ((newItem = psListGetAndIncrement(listIter))) {
+        if (regexec(regex, newItem->name, 0, NULL, 0) == 0) {
+            // this key is a match
+            break;
+        }
+    }
+    return newItem;
+}
+
+psMetadataItem* psMetadataGetAndDecrement(psMetadataIterator* iterator)
+{
+    PS_ASSERT_METADATA_ITERATOR_NON_NULL(iterator, NULL);
+    psListIterator* listIter = iterator->iter;
+    regex_t* regex = iterator->regex;
+
+    // handle trivial case where no regex subsetting is required.
+    if (regex == NULL) {
+        return (psMetadataItem*)psListGetAndDecrement(listIter);
+    }
+
+    // Iterate until we find something matching the regex
+    psMetadataItem *newItem;            // New MD item from iteration
+    while ((newItem = psListGetAndDecrement(listIter))) {
+        if (regexec(regex, newItem->name, 0, NULL, 0) == 0) {
+            // this key is a match
+            break;
+        }
+    }
+    return newItem;
+}
+
+psMetadata *psMetadataLookupMetadata(bool *status,
+                                     const psMetadata *md,
+                                     const char *key)
+{
+    PS_ASSERT_METADATA_NON_NULL(md,NULL);
+    psMetadataItem *item = psMetadataLookup((psMetadata*)md, key); // The metadata with instruments
+    psMetadata *value = NULL;  // The value to return
+    if (!item) {
+        // The given key isn't in the metadata
+        if (status) {
+            *status = false;
+        } else {
+            psError(PS_ERR_IO, true, "Couldn't find %s in the metadata.\n", key);
+        }
+    } else if (item->type != PS_DATA_METADATA) {
+        // The value at the key isn't metadata
+        if (status) {
+            *status = false;
+        } else {
+            psLogMsg(__func__, PS_LOG_DETAIL, "%s isn't of type PS_DATA_META, as expected.\n", key);
+        }
+        //        value = NULL;
+    } else {
+        // We have the requested metadata
+        if (status) {
+            *status = true;
+        }
+        value = item->data.md; // The requested metadata
+    }
+    return value;
+}
+
+psTime *psMetadataLookupTime(bool *status,
+                             const psMetadata *md,
+                             const char *key)
+{
+    PS_ASSERT_METADATA_NON_NULL(md,NULL);
+
+    psMetadataItem *item = psMetadataLookup((psMetadata*)md, key);
+    if (!item) {
+        // The given key isn't in the metadata
+        if (status) {
+            *status = false;
+        } else {
+            psError(PS_ERR_IO, true, "Couldn't find %s in the metadata.\n", key);
+        }
+        return NULL;
+    }
+
+    if (item->type != PS_DATA_TIME) {
+        // The value at the key isn't metadata
+        if (status) {
+            *status = false;
+        } else {
+            psLogMsg(__func__, PS_LOG_DETAIL, "%s isn't of type PS_DATA_TIME, as expected.\n", key);
+        }
+        return NULL;
+    }
+
+    // We have the requested metadata
+    if (status) {
+        *status = true;
+    }
+
+    return item->data.V;
+}
+
+
+psString psMetadataLookupStr(bool *status,
+                             const psMetadata *md,
+                             const char *key)
+{
+    PS_ASSERT_METADATA_NON_NULL(md,NULL);
+
+    psMetadataItem *item = psMetadataLookup((psMetadata*)md, key); // The metadata with instruments
+    //    char *value = NULL;   // The value to return
+    psString value = NULL;
+    if (!item) {
+        // The given key isn't in the metadata
+        if (status) {
+            *status = false;
+        } else {
+            psError(PS_ERR_IO, true, "Couldn't find %s in the metadata.\n", key);
+        }
+    } else if (item->type != PS_DATA_STRING) {
+        // The value at the key isn't of the desired type
+        if (status) {
+            *status = false;
+        } else {
+            psLogMsg(__func__, PS_LOG_DETAIL, "%s isn't of type PS_DATA_STRING, as expected.\n", key);
+        }
+        //        value = NULL;
+    } else {
+        // We have the requested metadata
+        if (status) {
+            *status = true;
+        }
+        value = item->data.V;
+    }
+    return value;
+}
+
+psList *psMetadataKeys(psMetadata *md)
+{
+    PS_ASSERT_METADATA_NON_NULL(md, NULL);
+    return psHashKeyList(md->hash);
+}
+
+
+bool psMetadataPrint(FILE *fd,
+                     const psMetadata *md,
+                     int level)
+{
+    PS_ASSERT_METADATA_NON_NULL(md,false);
+    if (fd == NULL) {
+        fd = stdout;
+    } else {
+        if ( fprintf(fd, "\n") < 0 ) {
+            psError(PS_ERR_IO, true,
+                    "Invalid file pointer in psMetadataPrint.  Could not write to fd.\n");
+            return false;
+        }
+    }
+
+    psErrorClear();   // we're going to _append_ errors to the stack
+    bool noErrors = true;  // have see seen any errors?
+
+    // Casting away const --- the addition of an iterator should not be considered an invasion of "const".
+    psMetadataIterator *iter = psMetadataIteratorAlloc(md, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *item = NULL; // Item from metadata
+    while ( (item = psMetadataGetAndIncrement(iter)) ) {
+        //So that unsupported types are not printed here, adding a switch statement
+        switch(item->type) {
+        case PS_DATA_STRING:
+        case PS_DATA_BOOL:
+        case PS_DATA_S8:
+        case PS_DATA_S16:
+        case PS_DATA_S32:
+        case PS_DATA_S64:
+        case PS_DATA_U8:
+        case PS_DATA_U16:
+        case PS_DATA_U32:
+        case PS_DATA_U64:
+        case PS_DATA_F32:
+        case PS_DATA_F64:
+        case PS_DATA_METADATA:
+        case PS_DATA_REGION:
+        case PS_DATA_LIST:
+        case PS_DATA_TIME:
+        case PS_DATA_VECTOR:
+            // Indent...
+            //                fprintf(fd, "\n");
+            for (int i = 0; i < level; i++) {
+                fprintf(fd, "  ");
+            }
+            fprintf(fd, "%s", item->name);
+            if (item->comment && strlen(item->comment) > 0) {
+                fprintf(fd, " (%s)", item->comment);
+            }
+            fprintf(fd, ": ");
+            break;
+        case PS_DATA_UNKNOWN:
+        default:
+            break;
+        }
+        switch (item->type) {
+        case PS_DATA_STRING:
+            fprintf(fd, "%s\n", item->data.str);
+            break;
+        case PS_DATA_BOOL:
+            if (item->data.B) {
+                fprintf(fd, "True\n");
+            } else {
+                fprintf(fd, "False\n");
+            }
+            break;
+        case PS_DATA_S8:
+            fprintf(fd, "%d\n", item->data.S8);
+            break;
+        case PS_DATA_S16:
+            fprintf(fd, "%d\n", item->data.S16);
+            break;
+        case PS_DATA_S32:
+            fprintf(fd, "%d\n", item->data.S32);
+            break;
+        case PS_DATA_S64:
+            fprintf(fd, "%jd\n", item->data.S64);
+            break;
+        case PS_DATA_U8:
+            fprintf(fd, "%u\n", item->data.U8);
+            break;
+        case PS_DATA_U16:
+            fprintf(fd, "%u\n", item->data.U16);
+            break;
+        case PS_DATA_U32:
+            fprintf(fd, "%u\n", item->data.U32);
+            break;
+        case PS_DATA_U64:
+            fprintf(fd, "%ju\n", item->data.U64);
+            break;
+        case PS_DATA_F32:
+            fprintf(fd, "%f\n", item->data.F32);
+            break;
+        case PS_DATA_F64:
+            fprintf(fd, "%f\n", item->data.F64);
+            break;
+        case PS_DATA_METADATA:
+            if (!item->data.V) {
+                fprintf(fd, "(null)\n");
+                break;
+            }
+            psMetadataPrint(fd, item->data.V, level + 1);
+            for (int i = 0; i < level; i++) {
+                fprintf(fd, "  ");
+            }
+            fprintf(fd, "%s  -- END\n", item->name);
+            break;
+        case PS_DATA_REGION:
+            if (!item->data.V) {
+                fprintf(fd, "(null)\n");
+                break;
+            }
+            psString region = psRegionToString(*(psRegion*)item->data.V);
+            fprintf(fd, "%s\n", region);
+            psFree(region);
+            break;
+        case PS_DATA_LIST:
+            if (!item->data.V) {
+                fprintf(fd, "(null)\n");
+                break;
+            }
+            fprintf(fd, "<a list of size %ld>\n", ((psList*)item->data.V)->n);
+            break;
+        case PS_DATA_TIME:
+            if (!item->data.V) {
+                fprintf(fd, "(null)\n");
+                break;
+            }
+            psString time = psTimeToISO(item->data.V);
+            fprintf(fd, "%s\n", time);
+            psFree(time);
+            break;
+        case PS_DATA_VECTOR:
+          if (!item->data.V) {
+              fprintf(fd, "(null)\n");
+              break;
+          }
+          psVector *vector = item->data.V;
+          switch (vector->type.type) {
+            case PS_DATA_U8:
+              fprintf(fd, "U8  ");
+              for (int i = 0; i < vector->n; i++) {
+                  fprintf(fd, "%u ", vector->data.U8[i]);
+              }
+              fprintf(fd, "\n");
+              break;
+            case PS_DATA_U16:
+              fprintf(fd, "U16  ");
+              for (int i = 0; i < vector->n; i++) {
+                  fprintf(fd, "%u ", vector->data.U16[i]);
+              }
+              fprintf(fd, "\n");
+              break;
+            case PS_DATA_U32:
+              fprintf(fd, "U32  ");
+              for (int i = 0; i < vector->n; i++) {
+                  fprintf(fd, "%u ", vector->data.U32[i]);
+              }
+              fprintf(fd, "\n");
+              break;
+            case PS_DATA_U64:
+              fprintf(fd, "U64  ");
+              for (int i = 0; i < vector->n; i++) {
+                  fprintf(fd, "%ju ", vector->data.U64[i]);
+              }
+              fprintf(fd, "\n");
+              break;
+            case PS_DATA_S8:
+              fprintf(fd, "S8  ");
+              for (int i = 0; i < vector->n; i++) {
+                  fprintf(fd, "%d ", vector->data.S8[i]);
+              }
+              fprintf(fd, "\n");
+              break;
+            case PS_DATA_S16:
+              fprintf(fd, "S16  ");
+              for (int i = 0; i < vector->n; i++) {
+                  fprintf(fd, "%d ", vector->data.S16[i]);
+              }
+              fprintf(fd, "\n");
+              break;
+            case PS_DATA_S32:
+              fprintf(fd, "S32  ");
+              for (int i = 0; i < vector->n; i++) {
+                  fprintf(fd, "%d ", vector->data.S32[i]);
+              }
+              fprintf(fd, "\n");
+              break;
+            case PS_DATA_S64:
+              fprintf(fd, "S64  ");
+              for (int i = 0; i < vector->n; i++) {
+                  fprintf(fd, "%jd ", vector->data.S64[i]);
+              }
+              fprintf(fd, "\n");
+              break;
+            case PS_DATA_F32:
+              fprintf(fd, "F32 ");
+              for (int i = 0; i < vector->n; i++) {
+                  fprintf(fd, "%f ", vector->data.F32[i]);
+              }
+              fprintf(fd, "\n");
+              break;
+            case PS_DATA_F64:
+              fprintf(fd, "F64 ");
+              for (int i = 0; i < vector->n; i++) {
+                  fprintf(fd, "%f ", vector->data.F64[i]);
+              }
+              fprintf(fd, "\n");
+              break;
+            case PS_DATA_UNKNOWN:
+            default:
+              psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                      _("Specified psDataType, %d, is not supported."), vector->type.type);
+              psFree(iter);
+              fprintf(fd, "<Unsupported type>\n");
+              return false;
+          }
+          break;
+        default:
+          psError(PS_ERR_IO, false, "Non-printable metadata type for \"%s\": %x\n",
+                  item->name, item->type);
+          noErrors = false;
+          break;
+        }
+    }
+    psFree(iter);
+
+    return noErrors;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadata.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadata.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadata.h	(revision 22158)
@@ -0,0 +1,1302 @@
+/** @file  psMetadata.h
+*
+*  @brief Contains metadata struuctures, enumerations and functions prototypes
+*
+*  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
+*  prototypes necessary creating psLib metadata APIs
+*
+*  @author Robert DeSonia, MHPCC
+*  @author Ross Harman, MHPCC
+*
+*  @version $Revision: 1.104 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2008-05-05 00:09:04 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+#ifndef PS_METADATA_H
+#define PS_METADATA_H
+
+/// @addtogroup DataContainer Data Containers
+/// @{
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <regex.h>
+
+#include "psHash.h"
+#include "psList.h"
+#include "psTime.h"
+#include "psLookupTable.h"
+
+#define PS_DATA_IS_PRIMITIVE(TYPE) \
+(TYPE == PS_DATA_S8 || \
+ TYPE == PS_DATA_S16 || \
+ TYPE == PS_DATA_S32 || \
+ TYPE == PS_DATA_S64 || \
+ TYPE == PS_DATA_U8 || \
+ TYPE == PS_DATA_U16 || \
+ TYPE == PS_DATA_U32 || \
+ TYPE == PS_DATA_U64 || \
+ TYPE == PS_DATA_F32 || \
+ TYPE == PS_DATA_F64 || \
+ TYPE == PS_DATA_BOOL)
+
+#define PS_DATA_PRIMITIVE_TYPE(DATATYPE) ( \
+        (DATATYPE==PS_DATA_S8 || DATATYPE==PS_DATA_S16 || \
+         DATATYPE==PS_DATA_S32 || DATATYPE==PS_DATA_S64 || DATATYPE==PS_DATA_U8 || \
+         DATATYPE==PS_DATA_U16 || DATATYPE==PS_DATA_U32 || DATATYPE==PS_DATA_U64 || \
+         DATATYPE==PS_DATA_F32 || DATATYPE==PS_DATA_F64 || DATATYPE==PS_DATA_BOOL) ? DATATYPE : 0)
+
+
+/** Option flags for psMetadata functions
+ *
+ *  Enumeration for the modification of the behaviour in psMetadataAddItem.
+ *
+ *  @see psMetadataAddItem
+ */
+typedef enum {
+    PS_META_DEFAULT       = 0,		///< default behaviour (duplicate entry is an error)
+    PS_META_REPLACE       = 0x01000000,	///< allow entry to be replaced
+    PS_META_NO_REPLACE    = 0x02000000,	///< duplicate entry is silently skipped
+    PS_META_DUPLICATE_OK  = 0x04000000,	///< allow duplicate entries
+    PS_META_UPDATE_FOLDER = 0x08000000,	///< for a metadata folder, merge contents with existing md
+    PS_META_NULL          = 0x10000000,	///< psMetadataItem.data is a NULL value
+    PS_META_REQUIRE_ENTRY = 0x20000000,	///< require pre-existing entry with same name
+    PS_META_REQUIRE_TYPE  = 0x40000000	///< require pre-existing entry to have same type
+} psMetadataFlags;
+
+#define PS_METADATA_FLAGS_MASK 0xFF000000
+#define PS_METADATA_TYPE_MASK 0x00FFFFFF
+
+#define PS_METADATA_ITEM_GET_TYPE(MDITEM) (MDITEM->type & PS_METADATA_TYPE_MASK)
+
+/** Metadata data structure.
+ *
+ *  Struct for holding metadata items. Metadata items are held in two
+ *  containers. The first employs a doubly-linked list to preserve the order
+ *  of the metadata. The second container employs a hash table which
+ *  allows fast lookup when given a metadata keyword.
+ */
+typedef struct
+{
+    psList*  list;                     ///< Metadata in linked-list
+    psHash*  hash;                     ///< Metadata in a hash table
+    void *lock;                        ///< Optional lock for thread safety
+}
+psMetadata;
+
+
+/** Metadata iterator
+ *
+ *  Iterator for metadata.
+ */
+typedef struct
+{
+    psListIterator* iter;              ///< iterator for the psMetadata's psList
+    regex_t* regex;                    ///< the subsetting regular expression
+}
+psMetadataIterator;
+
+
+/** Metadata item data structure.
+ *
+ * Struct for maintaining metadata items of varying types. It also contains
+ * information about the item name, flags, comments, and other items with the same name.
+ */
+typedef struct
+{
+    const psS32 id;                    ///< Unique ID for metadata item.
+    psString name;                     ///< Name of metadata item.
+    psDataType type;                   ///< Type of metadata item.
+    union {
+        bool B;                      ///< boolean data
+        psS8 S8;                       ///< Signed 8-bit integer data.
+        psS16 S16;                     ///< Signed 16-bit integer data.
+        psS32 S32;                     ///< Signed 32-bit integer data.
+        psS64 S64;                     ///< Signed 64-bit integer data.
+        psU8 U8;                       ///< Unsigned 8-bit integer data.
+        psU16 U16;                     ///< Unsigned 16-bit integer data.
+        psU32 U32;                     ///< Unsigned 32-bit integer data.
+        psU64 U64;                     ///< Unsigned 64-bit integer data.
+        psF32 F32;                     ///< Single-precision float data.
+        psF64 F64;                     ///< Double-precision float data.
+        psList *list;                  ///< List data.
+        psMetadata *md;                ///< Metadata data.
+        psString str;                  ///< string data
+        psPtr V;                       ///< Pointer to other type of data.
+    } data;                            ///< Union for data types.
+    psString comment;                  ///< Optional comment ("", not NULL).
+}
+psMetadataItem;
+
+
+/** Create a metadata item.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct. The name argument specifies the name to use for this item, and
+ *  may include sprintf formatting codes. The format entry specifies both
+ *  the metadata type and optional flags and is created by bit-wise or of the
+ *  appropriate type and flag. The comment argument is a fixed string used to
+ *  comment the metadata item. The arguments to the name formatting codes and
+ *  the metadata itself are passed as arguments following the comment string.
+ *  The data must be a pointer for any of the elements stored in data.void.
+ *  The argument list must be interpreted appropriately by the va_list
+ *  operators in the function specified size and type.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+#ifdef DOXYGEN
+psMetadataItem* psMetadataItemAlloc(
+    const char *name,                  ///< Name of metadata item.
+    psDataType type,                   ///< Type of metadata item.
+    const char *comment,               ///< Comment for metadata item.
+    ...                                ///< Arguments for name formatting and metadata item data.
+);
+#else // ifdef DOXYGEN
+psMetadataItem* p_psMetadataItemAlloc(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    const char *name,                  ///< Name of metadata item.
+    psDataType type,                   ///< Type of metadata item.
+    const char *comment,               ///< Comment for metadata item.
+    ...                                ///< Arguments for name formatting and metadata item data.
+) PS_ATTR_MALLOC;
+#define psMetadataItemAlloc(name, type, ...) \
+      p_psMetadataItemAlloc(__FILE__, __LINE__, __func__, name, type, __VA_ARGS__)
+#endif // ifdef DOXYGEN
+
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
+ *
+ *  @return bool:       True if the pointer matches a psMetadataItem structure, false otherwise.
+ */
+bool psMemCheckMetadataItem(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+// XXX Although all of the psMetadataItemAlloc[type] prototypes are allocators,
+// I've decided not to modify them all to pass in file, lineno, func.
+// Hopefully these prototypes will become macros or generated by macros some day
+// so this can be done automatically.  -JH
+
+/** Create a metadata item with specified string data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataItemAllocStr(
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    const char* value                  ///< the value of the metadata item.
+);
+
+
+/** Create a metadata item with specified psF32 data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataItemAllocF32(
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psF32 value                        ///< the value of the metadata item.
+);
+
+/** Create a metadata item with specified psF64 data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataItemAllocF64(
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psF64 value                        ///< the value of the metadata item.
+);
+
+
+/** Create a metadata item with specified psS8 data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataItemAllocS8(
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psS8 value                         ///< the value of the metadata item.
+);
+
+
+/** Create a metadata item with specified psS16 data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataItemAllocS16(
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psS16 value                        ///< the value of the metadata item.
+);
+
+
+/** Create a metadata item with specified psS32 data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataItemAllocS32(
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psS32 value                        ///< the value of the metadata item.
+);
+
+
+/** Create a metadata item with specified psS64 data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataItemAllocS64(
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psS64 value                        ///< the value of the metadata item.
+);
+
+
+/** Create a metadata item with specified psU8 data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataItemAllocU8(
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psU8 value                         ///< the value of the metadata item.
+);
+
+
+/** Create a metadata item with specified psU16 data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataItemAllocU16(
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psU16 value                        ///< the value of the metadata item.
+);
+
+
+/** Create a metadata item with specified psU32 data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataItemAllocU32(
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psU32 value                        ///< the value of the metadata item.
+);
+
+
+/** Create a metadata item with specified psU64 data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataItemAllocU64(
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psU64 value                        ///< the value of the metadata item.
+);
+
+
+/** Create a metadata item with specified bool data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataItemAllocBool(
+    const char* name,                  ///< Name of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    bool value                         ///< the value of the metadata item.
+);
+
+
+/** Create a metadata item with specified psPtr data.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataItemAllocPtr(
+    const char* name,                  ///< Name of metadata item.
+    psDataType type,                   ///< Data type of metadata item.
+    const char* comment,               ///< Comment for metadata item.
+    psPtr value                        ///< the value of the metadata item.
+);
+
+
+/** Create a metadata item with va_list.
+ *
+ *  Returns a fill psMetadataItem ready for insertion into the psMetadata
+ *  struct. The name argument specifies the name to use for this item, and
+ *  may include sprintf formatting codes. The format entry specifies both
+ *  the metadata type and optional flags and is created by bit-wise or of the
+ *  appropriate type and flag. The comment argument is a fixed string used to
+ *  comment the metadata item. The arguments to the name formatting codes and
+ *  the metadata itself are passed as arguments following the comment string.
+ *  The data must be a pointer for any of the elements stored in data.void.
+ *  The argument list must be interpreted appropriately by the va_list
+ *  operators in the function specified size and type.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+#ifndef SWIG
+#ifdef DOXYGEN
+psMetadataItem* psMetadataItemAllocV(
+    const char *name,                  ///< Name of metadata item.
+    psDataType type,                   ///< Type of metadata item.
+    const char *comment,               ///< Comment for metadata item.
+    va_list list                       ///< Arguments for name formatting and metadata item data.
+);
+#else // ifdef DOXYGEN
+psMetadataItem* p_psMetadataItemAllocV(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    const char *name,                  ///< Name of metadata item.
+    psDataType type,                   ///< Type of metadata item.
+    const char *comment,               ///< Comment for metadata item.
+    va_list list                       ///< Arguments for name formatting and metadata item data.
+);
+#define psMetadataItemAllocV(name, type, comment, list) \
+      p_psMetadataItemAllocV(__FILE__, __LINE__, __func__, name, type,comment, list)
+#endif // ifdef DOXYGEN
+#endif // #ifndef SWIG
+
+
+/** Create a metadata collection.
+ *
+ *  Returns an empty metadata container with fully allocated internal metadata
+ *  containers.
+ *
+ *  @return psMetadata* : Pointer metadata.
+ */
+#ifdef DOXYGEN
+psMetadata* psMetadataAlloc(void);
+#else // ifdef DOXYGEN
+psMetadata* p_psMetadataAlloc(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func                    ///< Function name of caller
+) PS_ATTR_MALLOC;
+#define psMetadataAlloc() \
+      p_psMetadataAlloc(__FILE__, __LINE__, __func__)
+#endif // ifdef DOXYGEN
+
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr
+ *  datatype.
+ *
+ *  @return bool:       True if the pointer matches a psMetadata structure, false otherwise.
+ */
+bool psMemCheckMetadata(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+
+/** Creates a new copy of a psMetadataItem.
+ *
+ * @return psMetadataItem*: the copy of the psMetadataItem
+ */
+#ifdef DOXYGEN
+psMetadataItem *psMetadataItemCopy(
+    const psMetadataItem *in            ///< metadata item to be copied
+);
+#else // ifdef DOXYGEN
+psMetadataItem *p_psMetadataItemCopy(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    const psMetadataItem *in            ///< metadata item to be copied
+);
+#define psMetadataItemCopy(in) \
+      p_psMetadataItemCopy(__FILE__, __LINE__, __func__, in)
+#endif // ifdef DOXYGEN
+
+
+/** Create a copy of an existing psMetadata collection.
+ *
+ *  Creates a new copy of all the psMetadataItems in the psMetadata collection,
+ *  in, and returns them in out, or creates a new container if out is NULL.  If
+ *  an error occurs, NULL is returned but out may still have been updated if it
+ *  is non-NULL.
+ *
+ *  @return psMetadata*:        the copy of the psMetadata container.
+ */
+#ifdef DOXYGEN
+psMetadata *psMetadataCopy(
+    psMetadata *out,                   ///< output Metadata container for copying.
+    const psMetadata *in               ///< Metadata collection to be copied.
+);
+#else // ifdef DOXYGEN
+psMetadata *p_psMetadataCopy(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psMetadata *out,                    ///< output Metadata container for copying.
+    const psMetadata *in                ///< Metadata collection to be copied.
+);
+#define psMetadataCopy(out, in) \
+      p_psMetadataCopy(__FILE__, __LINE__, __func__, out, in)
+#endif // ifdef DOXYGEN
+
+
+/** Updates an existing psMetadata collection with elements from a metadata collection
+ *
+ *  Creates a new copy of all the psMetadataItems in the psMetadata collection 'in' and places
+ *  them in out.  all items in 'in' must already be in 'out' and be of the same type.
+ *
+ *  @return psMetadata*:        the copy of the psMetadata container.
+ */
+#ifdef DOXYGEN
+bool psMetadataUpdate(
+    psMetadata *out,                   ///< output Metadata container for copying.
+    const psMetadata *in               ///< Metadata collection to be copied.
+    );
+#else // ifdef DOXYGEN
+bool p_psMetadataUpdate(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psMetadata *out,                    ///< output Metadata container for copying.
+    const psMetadata *in                ///< Metadata collection to be copied.
+    );
+#define psMetadataUpdate(out, in) \
+      p_psMetadataUpdate(__FILE__, __LINE__, __func__, out, in)
+#endif // ifdef DOXYGEN
+
+
+/** Overlays an existing psMetadata collection with elements from a metadata collection
+ *
+ *  Creates a new copy of all the psMetadataItems in the psMetadata collection 'in' and places
+ *  them in out.  matching metadata structures in 'out' are supplemented with corresponding
+ *  entries from 'in'
+ *
+ *  @return psMetadata*:        the copy of the psMetadata container.
+ */
+#ifdef DOXYGEN
+bool psMetadataOverlay(
+    psMetadata *out,                   ///< output Metadata container for copying.
+    const psMetadata *in               ///< Metadata collection to be copied.
+    );
+#else // ifdef DOXYGEN
+bool p_psMetadataOverlay(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psMetadata *out,                    ///< output Metadata container for copying.
+    const psMetadata *in                ///< Metadata collection to be copied.
+    );
+#define psMetadataOverlay(out, in) \
+      p_psMetadataOverlay(__FILE__, __LINE__, __func__, out, in)
+#endif // ifdef DOXYGEN
+
+
+/** Supplements a metadata with an item from another metadata.
+ *
+ *  Supplements the output metadata with the metadata item of the specified name from the input metadata.  If
+ *  out is NULL, a new container is created.
+ *
+ *  @return bool:       True if successful, otherwise false.
+ */
+bool psMetadataItemSupplement(
+    psMetadata *out,                   ///< output Metadata container for copying.
+    const psMetadata *in,              ///< Metadata collection from which to copy.
+    const char *key                    ///< key to identify the metadata item for copying.
+);
+
+
+/** Add existing metadata item to metadata collection.
+ *
+ *  Add a metadata item that has already been created to the metadata
+ *  collection.
+ *
+ * Note: that this function accepts it's "value" as a stdarg.  This means that
+ * the type of the value is not coerced by the prototype.  You need to be
+ * careful to cast 64-bit integer values as smaller types will not be promoted.
+ * This *includes* constant values as they are typically a 32-bit type.
+ *
+ *  @return bool: True for success, false for failure.
+ */
+bool psMetadataAddItem(
+    psMetadata*  md,                   ///< Metadata collection to insert metadata item.
+    const psMetadataItem* item,        ///< Metadata item to be added.
+    int location,                      ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    psS32 flags                        ///< Options flag mask, see psMetadataFlags enum
+);
+
+
+/** Create and add a metadata item to metadata collection.
+ *
+ * Creates a new metadata item add to the metadata collection.
+ *
+ * Note: that this function accepts it's "value" as a stdarg.  This means that
+ * the type of the value is not coerced by the prototype.  You need to be
+ * careful to cast 64-bit integer values as smaller types will not be promoted.
+ * This *includes* constant values as they are typically a 32-bit type.
+ *
+ * @return bool: True for success, false for failure.
+ */
+bool psMetadataAdd(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item.
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char *name,                  ///< Name of metadata item.
+    int format,                        ///< psDataType of metadata item & options (psMetadataFlags)
+    const char *comment,               ///< Comment for metadata item.
+    ...                                ///< Arguments for name formatting and metadata item data.
+);
+
+
+/** Create and add a metadata item to metadata collection.
+ *
+ * Creates a new metadata item add to the metadata collection.
+ *
+ * @return bool: True for success, false for failure.
+ */
+#ifndef SWIG
+bool psMetadataAddV(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item.
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char *name,                  ///< Name of metadata item.
+    int format,                        ///< psDataType of metadata item & options (psMetadataFlags)
+    const char *comment,               ///< Comment for metadata item.
+    va_list list                       ///< Arguments for name formatting and metadata item data.
+);
+#endif // #ifndef SWIG
+
+
+/** Add a bool value to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddBool(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    bool value                         ///< Value for metadata item data
+);
+
+
+/** Add a psS8 value to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddS8(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    psS8 value                         ///< Value for metadata item data
+);
+
+
+/** Add a psS16 value to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddS16(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    psS16 value                        ///< Value for metadata item data
+);
+
+
+/** Add a psS32 value to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddS32(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    psS32 value                        ///< Value for metadata item data
+);
+
+
+/** Add a psS64 value to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddS64(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    psS64 value                        ///< Value for metadata item data
+);
+
+
+/** Add a psU8 value to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddU8(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    psU8 value                         ///< Value for metadata item data
+);
+
+
+/** Add a psU16 value to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddU16(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    psU16 value                        ///< Value for metadata item data
+);
+
+
+/** Add a psU32 value to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddU32(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    psU32 value                        ///< Value for metadata item data
+);
+
+
+/** Add a psU64 value to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddU64(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    psU64 value                        ///< Value for metadata item data
+);
+
+
+/** Add a psF32 value to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+*/
+bool psMetadataAddF32(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    psF32 value                        ///< Value for metadata item data
+);
+
+
+/** Add a psF64 value to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+*/
+bool psMetadataAddF64(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    psF64 value                        ///< Value for metadata item data
+);
+
+
+/** Add a psList to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddList(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    psList* value                      ///< psList for metadata item data
+);
+
+
+/** Add a string to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddStr(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    const char* value                  ///< String for metadata item data
+);
+
+
+/** Add a vector to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddVector(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    psVector* value                    ///< Vector for metadata item data
+);
+
+
+/** Add a array to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddArray(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    psArray* value                     ///< Vector for metadata item data
+);
+
+
+/** Add an Image to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddImage(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    psImage* value                     ///< Image for metadata item data
+);
+
+
+/** Add a Time to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddTime(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    psTime* value                      ///< Time for metadata item data
+);
+
+
+/** Add a Hash to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddHash(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    psHash* value                      ///< Hash for metadata item data
+);
+
+
+/** Add a LookupTable to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddLookupTable(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    psLookupTable* value               ///< LookupTable for metadata item data
+);
+
+
+/** Add an Unknown (psPtr) to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddUnknown(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    psPtr value                        ///< Unknown for metadata item data
+);
+
+
+/** Add a psPtr to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddPtr(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    psDataType type,                   ///< psDataType for metadata item
+    const char* comment,               ///< Comment for metadata item
+    psPtr value                        ///< Unknown for metadata item data
+);
+
+
+/** Add Metadata to metadata collection.
+ *
+ *  @return bool:  True for success, False for failure.
+ */
+bool psMetadataAddMetadata(
+    psMetadata* md,                    ///< Metadata collection to insert metadata item
+    long location,                     ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* name,                  ///< Name of metadata item
+    int format,                        ///< psMetadataFlag options/flags
+    const char* comment,               ///< Comment for metadata item
+    psMetadata* value                  ///< Metadata for metadata item data
+);
+
+
+/** Removes an item from metadata by key name.
+ *
+ *  @return bool:  True for success, false for failure.
+ */
+bool psMetadataRemoveKey(
+    psMetadata *md,                    ///< Metadata collection to remove metadata item.
+    const char *key                    ///< Name of metadata key.
+);
+
+
+/** Removes an item from metadata by index number.
+ *
+ *  @return bool:  True for success, false for failure.
+ */
+bool psMetadataRemoveIndex(
+    psMetadata *md,                    ///< Metadata collection to remove metadata item.
+    long location                       ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+);
+
+
+/** Find an item in the metadata collection based on key name.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is
+ *  non-unique, the first item is returned. If the item is not found, null is
+ *  returned.
+ *
+ * @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataLookup(
+    const psMetadata * md,             ///< Metadata collection to lookup metadata item.
+    const char * key                   ///< Name of metadata key.
+);
+
+
+/** Find an item in the metadata collection based on key name and return its double precision value.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is
+ *  non-unique, the value of the first item is returned. If the item is not
+ *  found, zero is returned.
+ *
+ * @return psF64 : Value of metadata item.
+ */
+psF64 psMetadataLookupF64(
+    bool *status,                      ///< Status of lookup.
+    const psMetadata *md,              ///< Metadata collection to lookup metadata item.
+    const char *key                    ///< Name of metadata key.
+);
+
+
+/** Find an item in the metadata collection based on key name and return its single precision value.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is
+ *  non-unique, the value of the first item is returned. If the item is not
+ *  found, zero is returned.
+ *
+ * @return psF32 : Value of metadata item.
+ */
+psF32 psMetadataLookupF32(
+    bool *status,                      ///< Status of lookup.
+    const psMetadata *md,              ///< Metadata collection to lookup metadata item.
+    const char *key                    ///< Name of metadata key.
+);
+
+
+/** Find an item in the metadata collection based on key name and return its integer value.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is
+ *  non-unique, the value of the first item is returned. If the item is not
+ *  found, zero is returned.
+ *
+ * @return psS8 : Value of metadata item.
+ */
+psS8 psMetadataLookupS8(
+    bool *status,                      ///< Status of lookup.
+    const psMetadata *md,              ///< Metadata collection to lookup metadata item.
+    const char *key                    ///< Name of metadata key.
+);
+
+
+/** Find an item in the metadata collection based on key name and return its integer value.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is
+ *  non-unique, the value of the first item is returned. If the item is not
+ *  found, zero is returned.
+ *
+ * @return psS16 : Value of metadata item.
+ */
+psS16 psMetadataLookupS16(
+    bool *status,                      ///< Status of lookup.
+    const psMetadata *md,              ///< Metadata collection to lookup metadata item.
+    const char *key                    ///< Name of metadata key.
+);
+
+
+/** Find an item in the metadata collection based on key name and return its integer value.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is
+ *  non-unique, the value of the first item is returned. If the item is not
+ *  found, zero is returned.
+ *
+ * @return psS32 : Value of metadata item.
+ */
+psS32 psMetadataLookupS32(
+    bool *status,                      ///< Status of lookup.
+    const psMetadata *md,              ///< Metadata collection to lookup metadata item.
+    const char *key                    ///< Name of metadata key.
+);
+
+
+/** Find an item in the metadata collection based on key name and return its integer value.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is
+ *  non-unique, the value of the first item is returned. If the item is not
+ *  found, zero is returned.
+ *
+ * @return psS64 : Value of metadata item.
+ */
+psS64 psMetadataLookupS64(
+    bool *status,                      ///< Status of lookup.
+    const psMetadata *md,              ///< Metadata collection to lookup metadata item.
+    const char *key                    ///< Name of metadata key.
+);
+
+
+/** Find an item in the metadata collection based on key name and return its integer value.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is
+ *  non-unique, the value of the first item is returned. If the item is not
+ *  found, zero is returned.
+ *
+ * @return psU8 : Value of metadata item.
+ */
+psU8 psMetadataLookupU8(
+    bool *status,                      ///< Status of lookup.
+    const psMetadata *md,              ///< Metadata collection to lookup metadata item.
+    const char *key                    ///< Name of metadata key.
+);
+
+
+/** Find an item in the metadata collection based on key name and return its integer value.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is
+ *  non-unique, the value of the first item is returned. If the item is not
+ *  found, zero is returned.
+ *
+ * @return psU16 : Value of metadata item.
+ */
+psU16 psMetadataLookupU16(
+    bool *status,                      ///< Status of lookup.
+    const psMetadata *md,              ///< Metadata collection to lookup metadata item.
+    const char *key                    ///< Name of metadata key.
+);
+
+
+/** Find an item in the metadata collection based on key name and return its integer value.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is
+ *  non-unique, the value of the first item is returned. If the item is not
+ *  found, zero is returned.
+ *
+ * @return psU32 : Value of metadata item.
+ */
+psU32 psMetadataLookupU32(
+    bool *status,                      ///< Status of lookup.
+    const psMetadata *md,              ///< Metadata collection to lookup metadata item.
+    const char *key                    ///< Name of metadata key.
+);
+
+
+/** Find an item in the metadata collection based on key name and return its integer value.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is
+ *  non-unique, the value of the first item is returned. If the item is not
+ *  found, zero is returned.
+ *
+ * @return psU64 : Value of metadata item.
+ */
+psU64 psMetadataLookupU64(
+    bool *status,                      ///< Status of lookup.
+    const psMetadata *md,              ///< Metadata collection to lookup metadata item.
+    const char *key                    ///< Name of metadata key.
+);
+
+
+/** Find an item in the metadata collection based on key name and return its boolean value.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is
+ *  non-unique, the value of the first item is returned. If the item is not
+ *  found, zero is returned.
+ *
+ * @return bool : Value of metadata item.
+ */
+bool psMetadataLookupBool(
+    bool *status,                      ///< Status of lookup.
+    const psMetadata *md,              ///< Metadata collection to lookup metadata item.
+    const char *key                    ///< Name of metadata key.
+);
+
+
+/** Find an item in the metadata collection based on key name and return its integer value.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is
+ *  non-unique, the value of the first item is returned. If the item is not
+ *  found, zero is returned.
+ *
+ * @return void* : Value of metadata item.
+ */
+psPtr psMetadataLookupPtr(
+    bool *status,                      ///< Status of lookup.
+    const psMetadata* md,              ///< Metadata collection to lookup metadata item.
+    const char *key                    ///< Name of metadata key.
+);
+
+
+/** Find an item in the metadata collection based on list index.
+ *
+ *  Items may be found in the metadata by their entry position in the list
+ *  container.
+ *
+ *  @return psMetadataItem* : Pointer metadata item.
+ */
+psMetadataItem* psMetadataGet(
+    const psMetadata* md,              ///< Metadata collection to retrieve metadata item.
+    int location                       ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+);
+
+
+/** Creates a psMetadataIterator to iterate over the specified psMetadata.
+ *
+ *  Supports the subsetting of the metadata via keyword using regular
+ *  expression.  If no regular expression is specified, iteration
+ *  over the entire psMetadata is performed.
+ *
+ *  @return psMetadataIterator*        a new psMetadataIterator, of NULL if error occurred
+ */
+#ifdef DOXYGEN
+psMetadataIterator* psMetadataIteratorAlloc(
+    const psMetadata* md,               ///< the psMetadata to iterate with
+    long location,                      ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* regex
+    ///< A regular expression for subsetting the psMetadata.  If NULL, no
+    ///< subsetting is performed.
+);
+#else // ifdef DOXYGEN
+psMetadataIterator* p_psMetadataIteratorAlloc(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    const psMetadata* md,               ///< the psMetadata to iterate with
+    long location,                      ///< Index number, PS_LIST_HEAD, or PS_LIST_TAIL
+    const char* regex
+    ///< A regular expression for subsetting the psMetadata.  If NULL, no
+    ///< subsetting is performed.
+) PS_ATTR_MALLOC;
+#define psMetadataIteratorAlloc(md, location, regex) \
+      p_psMetadataIteratorAlloc(__FILE__, __LINE__, __func__, md, location, regex)
+#endif // ifdef DOXYGEN
+
+
+/** Set the iterator of the psMetadat to a given position.  If location is
+ *  invalid the iterator position is not changed.
+ *
+ *  @return bool        TRUE if iterator successfully set, otherwise FALSE.
+*/
+bool psMetadataIteratorSet(
+    psMetadataIterator* iterator,      ///< psMetadata iterator
+    long location                      ///< index number, PS_LIST_HEAD, or PS_LIST_TAIL
+);
+
+
+/** Position the specified iterator to the next matching item in psMetadata,
+ *  given the regular expression of the iterator
+ *
+ *  @return psPtr       the psMetadataItem at the original iterator position
+ *                      or NULL if the iterator went past the end of the list.
+ */
+psMetadataItem* psMetadataGetAndIncrement(
+    psMetadataIterator* iterator       ///< iterator to move
+);
+
+
+/** Position the specified iterator to the previous matching item in psMetadata,
+ *  given the regular expression of the iterator
+ *
+ *  @return psPtr       the psMetadataItem at the original iterator position
+ *                      or NULL if the iterator went past the beginning of the
+ *                      list.
+ */
+psMetadataItem* psMetadataGetAndDecrement(
+    psMetadataIterator* iterator       ///< iterator to move
+);
+
+
+/** Find an item in the metadata collection based on key name and return its metadata value.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is
+ *  non-unique, the value of the first item is returned. If the item is not
+ *  found, zero is returned.
+ *
+ *  @return psMetadata*:        Value of metadata item.
+ */
+psMetadata *psMetadataLookupMetadata(
+    bool *status,                      ///< Status of lookup.
+    const psMetadata *md,              ///< Metadata collection to lookup metadata item.
+    const char *key                    ///< Name of metadata key.
+);
+
+
+/** Find an item in the metadata collection based on key name and return its string value.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is
+ *  non-unique, the value of the first item is returned. If the item is not
+ *  found, zero is returned.
+ *
+ *  @return psString:           Value of metadata item.
+ */
+psString psMetadataLookupStr(
+    bool *status,                      ///< Status of lookup.
+    const psMetadata *md,              ///< Metadata collection to lookup metadata item.
+    const char *key                    ///< Name of metadata key.
+);
+
+
+/** Find an item in the metadata collection based on key name and return it as a psTime pointer.
+ *
+ *  Items may be found in the metadata by providing a key. If the key is
+ *  non-unique, the value of the first item is returned. If the item is not
+ *  found, zero is returned.
+ *
+ *  @return psTime:           Value of metadata item.
+ */
+
+psTime *psMetadataLookupTime(
+    bool *status,                      ///< Status of lookup.
+    const psMetadata *md,              ///< Metadata collection to lookup metadata item.
+    const char *key                    ///< Name of metadata key.
+);
+
+/// Return a list of keys for a metadata
+psList *psMetadataKeys(psMetadata *md   ///< Metadata for which to return keys
+                       );
+
+/** Prints metadata collection.
+ *
+ *  Metadata contents are printed to a valid file descriptor if one exists.  Otherwise,
+ *  fd should be NULL and the contents are printed to the screen (stdout).
+ *
+ *  @return bool:           True if successful, otherwise false.
+*/
+bool psMetadataPrint(
+    FILE *fd,                          ///< File Descriptor or NULL
+    const psMetadata *md,              ///< Metadata collection to print.
+    int level                          ///< the level of metadata items.
+);
+
+/// Assert on metadata with extant hash and list components
+#define PS_ASSERT_METADATA_NON_NULL(NAME, RVAL) \
+if (!(NAME) || !(NAME)->hash || !(NAME)->list) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: Metadata %s or one of its components is NULL.", \
+            #NAME); \
+    return RVAL; \
+}
+
+/// Assert on metadata item with extant name and type
+///
+/// The data contained within the metadata item is permitted to be NULL.
+#define PS_ASSERT_METADATA_ITEM_NON_NULL(NAME, RVAL) \
+if (!(NAME) || !(NAME)->name || !(NAME)->type) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: Metadata item %s or its name or type is NULL.", \
+            #NAME); \
+    return RVAL; \
+}
+
+#define PS_ASSERT_METADATA_ITERATOR_NON_NULL(NAME, RVAL) \
+if (!(NAME) || !(NAME)->iter) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: Metadata iterator %s or its component is NULL.", \
+            #NAME); \
+    return RVAL; \
+}
+
+/// @}
+#endif // #ifndef PS_METADATA_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadataConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadataConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadataConfig.c	(revision 22158)
@@ -0,0 +1,1706 @@
+/** @file  psMetadataConfig.c
+*
+*  @brief Contains metadata input/output functions.
+*
+*  This file defines functions to read and write metadata to/from an external file.
+*
+*  @ingroup Metadata
+*
+*  @author Ross Harman, MHPCC
+*  @author Eric Van Alst, MHPCC
+*  @author Joshua Hoblitt, University of Hawaii 2006-2007
+*
+*  @version $Revision: 1.143 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2008-05-05 00:09:04 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <fitsio.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <strings.h>
+#include "psSlurp.h"
+
+#include "psMemory.h"
+#include "psMetadataConfig.h"
+#include "psAssert.h"
+#include "psTrace.h"
+
+/******************************************************************************/
+/*  DEFINE STATEMENTS                                                         */
+/******************************************************************************/
+
+/** Maximum size of a string */
+#define MAX_STRING_LENGTH 1024
+#define INITIAL_LENGTH 10               // Initial length for arrays
+
+/******************************************************************************/
+/*  TYPE DEFINITIONS                                                          */
+/******************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  GLOBAL VARIABLES                                                         */
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  FILE STATIC VARIABLES                                                    */
+/*****************************************************************************/
+
+// None
+
+/*****************************************************************************/
+/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
+/*****************************************************************************/
+
+static psMetadata *genTypeTemplate(char *linePtr);
+static psMetadata *parseTypeValues(psMetadata *template, char *linePtr)
+;
+static bool parseLine(psArray *levelArray,
+                      char *linePtr,
+                      bool overwrite,
+                      bool *notBlank);
+static bool parseMetadataItem(char *keyName, psArray *levelArray,
+                              char *linePtr, psMetadataFlags flags);
+static psString formatMetadataItem(psMetadataItem *item);
+static psArray *p_psMetadataKeyArray(psMetadata *md);
+static bool parseGeneric(char *keyName,
+                         psArray *levelArray,
+                         char *linePtr,
+                         psMetadataFlags flags);
+static bool parseType(char *keyName,
+                      psArray *levelArray,
+                      char *linePtr,
+                      psMetadataFlags flags);
+static bool parseMetadataEnd(char *keyName,
+                             psArray *levelArray,
+                             char *linePtr,
+                             psMetadataFlags flags);
+
+
+// A metadata data structure used in parsing arrays.
+// Contains array information and the metadata storage location.
+typedef struct
+{
+    psArray *   nonUniqueKeyArray;      ///< non-unique key names
+    psHash *    typeTemplates;          ///< hash of user type templates
+    psMetadata *metadata;               ///< metadata container
+}
+p_psParseLevelInfo;
+
+static void parseLevelInfoFree(p_psParseLevelInfo *info)
+{
+    psFree(info->nonUniqueKeyArray);
+    psFree(info->typeTemplates);
+    psFree(info->metadata);
+}
+
+static p_psParseLevelInfo *p_psParseLevelInfoAlloc(void)
+{
+    // Allocate memory for parse level info
+    p_psParseLevelInfo *info = (p_psParseLevelInfo*)psAlloc(sizeof(p_psParseLevelInfo));
+    psMemSetDeallocator(info,(psFreeFunc)parseLevelInfoFree);
+
+    info->nonUniqueKeyArray = psArrayAllocEmpty(INITIAL_LENGTH);
+    info->typeTemplates = psHashAlloc(10);
+    info->metadata = NULL;
+
+    return info;
+}
+
+// Determines if a line is blank (whitespace only) or a commentline. It returns true if so. The input string
+// must be null terminated.
+static bool ignoreLine(char *inString)
+{
+    while(*inString!='\0' && *inString!='#') {
+        if(!isspace(*inString)) {
+            return false;
+        }
+        inString++;
+    }
+
+    return true;
+}
+
+
+//  Removes leading and trailing whitespace and # characters from a string. The cleaned string is a new null
+//  terminated copy of the original input string.
+static char *cleanString(char *inString,
+                         psS32 sLen,
+                         bool ignoreComment)
+{
+    char *ptrB = NULL;
+    char *ptrE = NULL;
+    char *cleaned = NULL;
+
+    // Initialize begining of string pointer
+    ptrB = inString;
+
+    // Skip over leading # or whitespace
+    if(ignoreComment) {
+        while (isspace(*ptrB) || *ptrB=='#') {
+            ptrB++;
+        }
+    } else {
+        while (isspace(*ptrB)) {
+            ptrB++;
+        }
+    }
+
+    // Skip over trailing whitespace, null terminators, and # characters
+    ptrE = inString + sLen;
+    if(ignoreComment) {
+        while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') {
+            ptrE--;
+        }
+    } else {
+        while(isspace(*ptrE) || *ptrE=='\0') {
+            ptrE--;
+        }
+    }
+
+    // Length, sLen, does not include '\0'
+    sLen = ptrE - ptrB + 1;
+
+    // Adds '\0' to end of string and +1 to sLen
+    if(sLen < 0 ) {
+        cleaned = NULL;
+    } else {
+        cleaned = psStringNCopy(ptrB, sLen);
+    }
+
+    return cleaned;
+}
+
+// Count repeat occurances of a single character within a line. The input string must be null terminated.
+static psS32 repeatedChars(char *inString,
+                           char ch)
+{
+    psS32 count = 0;
+
+    while(*inString!='\0') {
+        if(*inString == ch) {
+            count++;
+        }
+        inString++;
+    }
+
+    return count;
+}
+
+// Returns cleaned token based on delimiter, but not including delimiter. Also changes the pointer location
+// the beginning of the string. Tokens are newly allocated null terminated strings.
+// XXX EAM : not sure this API is well-thought-out:
+// *status must be set to 0 going in.
+// status is 1 if delimeter is found, but no valid token
+// returned string is NULL if no valid token is found
+static char *getToken(char **inString,
+                      char *delimiter,
+                      psS32 *status,
+                      bool ignoreComment)
+{
+    char *cleanToken = NULL;
+    char *convertChar = NULL;
+    psS32 sLen = 0;
+
+    // Convert tab characters to white space
+    while((convertChar=strchr(*inString,'\t')) != NULL ) {
+        *convertChar = ' ';
+    }
+
+    // Skip over leading whitespace
+    while(isspace(**inString)) {
+        (*inString)++;
+    }
+
+    // Length of token, not including delimiter
+    sLen = strcspn(*inString, delimiter);
+    if(sLen) {
+
+        // Create new, cleaned, and null terminated token
+        cleanToken = cleanString(*inString, sLen,ignoreComment);
+
+        // Move to end of token
+        (*inString) += sLen;
+    } else if(**inString!='\0' && sLen==0) {
+        *status = 1;
+    }
+
+    return cleanToken;
+}
+
+// Returns single parsed value as a double precision number. The input string must be cleaned and null
+// terminated.
+static double parseDouble(char *inString,
+                          psS32 *status)
+{
+    char *end = NULL;
+    double value = 0.0;
+
+    value = strtod(inString, &end);
+    if(*end != '\0') {
+        *status = 1;
+    } else if(inString==end) {
+        *status = 1;
+    }
+
+    return value;
+}
+
+// Returns single parsed value as a long signed int. The input string must be cleaned and null
+// terminated.
+static psS64 parseSignedInt(char *inString,
+                            psS32 *status)
+{
+    char *end = NULL;
+    psS64 value = 0;
+
+    value = strtol(inString, &end, 0);
+    if(*end != '\0') {
+        *status = 1;
+    } else if(inString==end) {
+        *status = 1;
+    }
+
+    return value;
+}
+
+// Returns single parsed value as a double precision number. The input string must be cleaned and null
+// terminated.
+static psU64 parseUnsignedInt(char *inString,
+                              psS32 *status)
+{
+    char *end = NULL;
+    psU64 value = 0;
+
+    value = strtoul(inString, &end, 0);
+    if(*end != '\0') {
+        *status = 1;
+    } else if(inString==end) {
+        *status = 1;
+    }
+
+    return value;
+}
+
+/** Returns true or false. 'T', 't', '1', 'F', 'f', and '0' are acceptable, parsable variations. */
+static bool parseBool(char *inString,
+                      psS32 *status)
+{
+    // if inString is NULL return flalse, status = 0
+    if (!inString) {
+        if (status) {
+            *status = 0;
+        }
+        return false;
+    }
+
+    if (!strncasecmp(inString, "T", 2) ||
+            !strncmp(inString, "1", 2) ||
+            !strncasecmp(inString, "true", 5)) {
+        if (status != NULL) {
+            *status = 0;
+        }
+        return true;
+    }
+    if ( !strncasecmp(inString, "F", 2) ||
+            !strncmp(inString, "0", 2) ||
+            !strncasecmp(inString, "false", 6)) {
+        if (status != NULL) {
+            *status = 0;
+        }
+        return false;
+    }
+
+    if (status != NULL) {
+        *status = 1;
+    }
+    return false;
+}
+
+/** Returns a psTime structure */
+static psTime *parseTime(char *inString,
+                         psTimeType tt,
+                         psS32 *status)
+{
+    PS_ASSERT_PTR_NON_NULL(status, NULL);
+    if (!inString) {
+        *status = 0;
+        return NULL;
+    }
+
+    // handle "NULL" as the time value
+    if (strncmp(inString, "NULL", 5) == 0) {
+        *status = 0;
+        return NULL;
+    }
+
+    psTime *out = psTimeFromISO(inString, tt);
+    if (!out) {
+        *status = 1;
+        return NULL;
+    }
+
+    *status = 0;
+
+    return out;
+}
+
+/** Returns parsed vector filled with with data. The input string must be null terminated. */
+static psVector *parseVector(char *inString,
+                             psElemType elemType,
+                             psS32 *status)
+{
+    PS_ASSERT_PTR_NON_NULL(inString, NULL);
+
+    // split string into multiple values on " " and ","
+    psList *tokens = psStringSplit(inString, ", ", false);
+
+    // allocate a large enough vector to hold all of the tokens
+    psVector *vec = psVectorAlloc(psListLength(tokens), elemType);
+
+    // iterate through the list of tokens and concert them to numeric values
+    // one by one
+    for (long i = 0; i < psListLength(tokens); i ++) {
+        psString tok = psListGet(tokens, i);
+        char *ptr = NULL;
+        double value = strtod(tok, &ptr);
+
+        // ptr will be set to tok if the parse failed
+        if (tok == ptr) {
+            *status = 1;
+            psError(PS_ERR_IO, true,
+                    _("failed to parse %s as a vector element."), tok);
+            psFree(vec);
+            psFree(tokens);
+            return NULL;
+        }
+
+        // XXX this switch statement and cases should be turned inside out but
+        // this optimization isn't a priority
+        switch(elemType) {
+        case PS_TYPE_U8:
+            vec->data.U8[i] = (psU8)value;
+            break;
+        case PS_TYPE_U16:
+            vec->data.U16[i] = (psU16)value;
+            break;
+        case PS_TYPE_U32:
+            vec->data.U32[i] = (psU32)value;
+            break;
+        case PS_TYPE_U64:
+            vec->data.U64[i] = (psU64)value;
+            break;
+        case PS_TYPE_S8:
+            vec->data.S8[i] = (psS8)value;
+            break;
+        case PS_TYPE_S16:
+            vec->data.S16[i] = (psS16)value;
+            break;
+        case PS_TYPE_S32:
+            vec->data.S32[i] = (psS32)value;
+            break;
+        case PS_TYPE_S64:
+            vec->data.S64[i] = (psS64)value;
+            break;
+        case PS_TYPE_F32:
+            vec->data.F32[i] = (psF32)value;
+            break;
+        case PS_TYPE_F64:
+            vec->data.F64[i] = (psF64)value;
+            break;
+        default:
+            *status = 1;
+            psError(PS_ERR_BAD_PARAMETER_VALUE,true,
+                    _("Specified type, %d, is not supported."), elemType);
+            psFree(vec);
+            psFree(tokens);
+            return NULL;
+            break;                          // unreachable
+        }
+    }
+
+    psFree(tokens);
+
+    return vec;
+}
+
+
+/*****************************************************************************/
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+/*****************************************************************************/
+
+bool psMetadataItemPrint(FILE  *fd,
+                         const char *format,
+                         const psMetadataItem* item)
+{
+    psDataType type;
+    bool success = true;
+
+    PS_ASSERT_PTR_NON_NULL(fd, false);
+    PS_ASSERT_STRING_NON_EMPTY(format, false);
+    PS_ASSERT_METADATA_ITEM_NON_NULL(item, false);
+
+    type = item->type;
+
+    // determining the format type
+    char *fType = strchr(format,'%');
+    if (fType == NULL) {
+        // well, the format contains no reference to the metadataItem's data:
+        // that is truly trival to do!
+        //        fprintf(fd,format);
+        return false;
+    }
+
+    // skip over any format modifiers
+    const char *formatEnd = format+strlen(format);
+    while ( (fType < formatEnd) &&
+        (strchr(" +-01234567890.$#, hlL",*(++fType)) != NULL) ) {}
+
+    #define METADATAITEM_NUMERIC_CAST(FORMAT_TYPE) { \
+        switch(type) { \
+        case PS_DATA_BOOL: \
+            fprintf(fd, format, (FORMAT_TYPE) item->data.B); \
+            break; \
+        case PS_DATA_S8: \
+            fprintf(fd,format,(FORMAT_TYPE)  item->data.S8); \
+            break; \
+        case PS_DATA_S16: \
+            fprintf(fd,format,(FORMAT_TYPE)  item->data.S16); \
+            break; \
+        case PS_DATA_S32: \
+            fprintf(fd,format,(FORMAT_TYPE)  item->data.S32); \
+            break; \
+        case PS_DATA_S64: \
+            fprintf(fd,format,(FORMAT_TYPE)  item->data.S64); \
+            break; \
+        case PS_DATA_U8: \
+            fprintf(fd,format,(FORMAT_TYPE)  item->data.U8); \
+            break; \
+        case PS_DATA_U16: \
+            fprintf(fd,format,(FORMAT_TYPE)  item->data.U16); \
+            break; \
+        case PS_DATA_U32: \
+            fprintf(fd,format,(FORMAT_TYPE)  item->data.U32); \
+            break; \
+        case PS_DATA_U64: \
+            fprintf(fd,format,(FORMAT_TYPE)  item->data.U64); \
+            break; \
+        case PS_DATA_F32: \
+            fprintf(fd, format,(FORMAT_TYPE)  item->data.F32); \
+            break; \
+        case PS_DATA_F64: \
+            fprintf(fd, format,(FORMAT_TYPE) item->data.F64); \
+            break; \
+        default: \
+            psError(PS_ERR_BAD_PARAMETER_TYPE,true, \
+                    _("Specified psDataType, %d, is not supported."), (int)type); \
+            success = false; \
+        } \
+    }
+
+    switch(*fType) {
+    case 'd':
+    case 'i':
+    case 'c':
+        METADATAITEM_NUMERIC_CAST(int)
+        break;
+    case 'o':
+    case 'u':
+    case 'x':
+    case 'X':
+        METADATAITEM_NUMERIC_CAST(unsigned int)
+        break;
+    case 'e':
+    case 'E':
+    case 'f':
+    case 'F':
+    case 'g':
+    case 'G':
+    case 'a':
+    case 'A':
+        METADATAITEM_NUMERIC_CAST(double)
+        break;
+    case 's':
+        if (type == PS_DATA_STRING) {
+            fprintf(fd,format, item->data.str);
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_TYPE,true,
+                    _("Specified psDataType, %d, is not supported."), (int)type);
+            success = false;
+        }
+        break;
+    case 'p':
+        fprintf(fd,format,item->data.V);
+        break;
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                _("Specified print format, %%%c, is not supported."), *fType);
+        success = false;
+        break;
+    }
+
+    return success;
+}
+
+static psMetadata *genTypeTemplate(char *linePtr)
+{
+    psMetadata*     metadataTemplate = NULL;
+    psS32           status           = 0;
+    char*           token            = NULL;
+    psMetadataItem* tempItem         = NULL;
+
+    // Loop through line and generate metadata items for each token found
+    while ((token = getToken(&linePtr, " ", &status, false)) != NULL) {
+
+        // If not allocated then allocate new metadata
+        if (metadataTemplate == NULL) {
+            metadataTemplate = psMetadataAlloc();
+        }
+
+        // Look for comment indicator #
+        if (strstr(token, "#") != 0) {
+            psFree(metadataTemplate);
+            psFree(token);
+            return NULL;
+        }
+
+        // Create metadata item to represent token read
+        tempItem = psMetadataItemAllocStr(token, "", "");
+        if (tempItem == NULL) {
+            psFree(metadataTemplate);
+            psFree(token);
+            return NULL;
+        }
+        psFree(token);
+
+        // Add item to template
+        if (!psMetadataAddItem(metadataTemplate, tempItem, PS_LIST_TAIL, PS_META_DEFAULT)) {
+            psFree(metadataTemplate);
+            psFree(tempItem);
+            return NULL;
+        }
+        psFree(tempItem);
+    }
+
+    return metadataTemplate;
+}
+
+
+static psMetadata *parseTypeValues(psMetadata *template,
+                                   char *linePtr)
+{
+    psMetadata*      md           = NULL;
+    char*            token        = NULL;
+    psS32            status       = 0;
+    psMetadataItem*  mdItem       = NULL;
+    psMetadataItem*  templateItem = NULL;
+    psListIterator*  iter         = NULL;
+
+    // Allocate metadata to return
+    md = psMetadataAlloc();
+
+    // Determine the number of items in template
+    long items = psListLength(template->list);
+
+    if (items > 0 ) {
+        // Point to first item in template
+        iter = psListIteratorAlloc(template->list, PS_LIST_HEAD, true);
+        // For each item in template parse line string for values
+        for (long i = 0; i < items; i++) {
+            // Get template item
+            templateItem = psListGetAndIncrement(iter);
+            if (templateItem == NULL) {
+                psFree(md);
+                psFree(iter);
+                md = NULL;
+                break;
+            }
+
+            // Get the next token on the line
+            token = getToken(&linePtr, " ", &status, false);
+            if (token != NULL) {
+                // Allocate metadata item
+                mdItem = psMetadataItemAllocStr(templateItem->name,
+                                                templateItem->comment, token);
+                if (mdItem == NULL) {
+                    psFree(md);
+                    md = NULL;
+                    psFree(token);
+                    psFree(iter);
+                    break;
+                }
+                psFree(token);
+
+                // Add item to metadata
+                if (!psMetadataAddItem(md, mdItem, PS_LIST_TAIL, PS_META_DEFAULT)) {
+                    psFree(md);
+                    md = NULL;
+                    psFree(mdItem);
+                    psFree(iter);
+                    break;
+                }
+                psFree(mdItem);
+            } else {
+                // Missing items
+                psFree(md);
+                psFree(iter);
+                md = NULL;
+                break;
+            }
+        }
+    }
+
+    return md;
+}
+
+bool parseMetadataItem(char *keyName,
+                       psArray *levelArray,
+                       char *linePtr,
+                       psMetadataFlags flags)
+{
+    // XXX This function is a monstrous abomination.  I have been slowly
+    // refactoring it as I fix bugs but it really needs to be split up into
+    // managable bits.
+    bool               returnValue   = true;
+    bool               addStatus     = false;
+    psDataType           mdType        = PS_DATA_UNKNOWN;
+    psElemType           vectorType    = PS_TYPE_S8;
+    char*                strValue      = NULL;
+    char*                strComment    = NULL;
+    psS32                status        = 0;
+    psMetadata*          md            = NULL;
+    psArray*             nonUniqueKeys = NULL;
+    psMetadata*          tempMeta      = NULL;
+    p_psParseLevelInfo*  nextLevelInfo = NULL;
+
+    long level = psArrayLength(levelArray) - 1;
+
+    // Get the metadata item type
+    char *strType = getToken(&linePtr, " ", &status,true);
+
+    // Check for no type
+    if (strType == NULL) {
+        psError(PS_ERR_IO, true, _("Failed to read a metadata type."));
+        return false;
+    }
+
+    // Set metadata type based on type token
+    // Check if the keyName specifies a vector and if so use strType token to
+    // find vector type
+    if (*keyName == '@') {
+        mdType = PS_DATA_VECTOR;
+        // Get the type of vector
+        if(!strncmp(strType, "U8", 2)) {
+            vectorType = PS_TYPE_U8;
+        } else if (!strncmp(strType,"U16",3)) {
+            vectorType = PS_TYPE_U16;
+        } else if (!strncmp(strType,"U32",3)) {
+            vectorType = PS_TYPE_U32;
+        } else if (!strncmp(strType,"U64",3)) {
+            vectorType = PS_TYPE_U64;
+        } else if (!strncmp(strType,"S8",2)) {
+            vectorType = PS_TYPE_S8;
+        } else if (!strncmp(strType,"S16",3)) {
+            vectorType = PS_TYPE_S16;
+        } else if (!strncmp(strType,"S32",3)) {
+            vectorType = PS_TYPE_S32;
+        } else if (!strncmp(strType,"S64",3)) {
+            vectorType = PS_TYPE_S64;
+        } else if (!strncmp(strType,"F32",3)) {
+            vectorType = PS_TYPE_F32;
+        } else if (!strncmp(strType,"F64",3)) {
+            vectorType = PS_TYPE_F64;
+        } else {
+            psError(PS_ERR_IO, true,
+                    _("Failed to parse the value '%s' of metadata item %s, type %s, "),
+                      "", keyName,  strType);
+            psFree(strType);
+            return false;
+        }
+    } else if(!strncmp(strType, "STR", 3)) {
+        mdType = PS_DATA_STRING;
+    } else if(!strncmp(strType, "BOOL", 4)) {
+        mdType = PS_DATA_BOOL;
+    } else if(!strncmp(strType, "S8", 2)) {
+        mdType = PS_DATA_S8;
+    } else if(!strncmp(strType, "S16", 3)) {
+        mdType = PS_DATA_S16;
+    } else if(!strncmp(strType, "S32", 3)) {
+        mdType = PS_DATA_S32;
+    } else if(!strncmp(strType, "S64", 3)) {
+        mdType = PS_DATA_S64;
+    } else if(!strncmp(strType, "U8", 2)) {
+        mdType = PS_DATA_U8;
+    } else if(!strncmp(strType, "U16", 3)) {
+        mdType = PS_DATA_U16;
+    } else if(!strncmp(strType, "U32", 3)) {
+        mdType = PS_DATA_U32;
+    } else if(!strncmp(strType, "U64", 3)) {
+        mdType = PS_DATA_U64;
+    } else if(!strncmp(strType, "F32", 3)) {
+        mdType = PS_DATA_F32;
+    } else if(!strncmp(strType, "F64", 3)) {
+        mdType = PS_DATA_F64;
+    } else if(!strncmp(strType, "MULTI", 5)) {
+        mdType = PS_DATA_METADATA_MULTI;
+    } else if(!strncmp(strType, "METADATA", 8)) {
+        mdType = PS_DATA_METADATA;
+    } else if( !strncmp(strType, "UTC", 3) || !strncmp(strType, "TAI", 3)
+               || !strncmp(strType, "UT1", 3) || !strncmp(strType, "TT", 3)) {
+        mdType = PS_DATA_TIME;
+    } else {
+        // Search through user types
+        // Check if type already exists in typeTempaltes
+        psHash *typeTemplates = ((p_psParseLevelInfo*)(levelArray->data[level]))->typeTemplates;
+
+        psMetadata *template = psHashLookup(typeTemplates, strType);
+        if (!template) {
+            psError(PS_ERR_IO, true,
+                    _("Metadata TYPE '%s' is invalid."), strType);
+            psFree(strType);
+            return false;
+        }
+
+        // covert the template, and the rest of the line, into a metadata
+        tempMeta = parseTypeValues(template, linePtr);
+        if (!tempMeta) {
+            // Metadata type read error
+            psError(PS_ERR_IO,true,
+                    _("Failed to read Metadata TYPE %s."), keyName);
+            psFree(strType);
+            return false;
+        }
+
+        // get the current level's metadata
+        md = ((p_psParseLevelInfo*)(levelArray->data[level]))->metadata;
+
+        // add the parsed TYPE to it
+        addStatus = psMetadataAdd(md,PS_LIST_TAIL,keyName,
+                PS_DATA_METADATA | flags,"",tempMeta);
+        psFree(tempMeta);
+
+        // Check for add failure
+        if (! addStatus) {
+            psError(PS_ERR_IO, true,
+                    _("Duplicate Metadata item, %s, found.  "
+                     "Overwrite not allowed."), keyName);
+            psFree(strType);
+            return false;
+        }
+
+        psFree(strComment);
+        psFree(strValue);
+        psFree(strType);
+
+        return true;
+    }
+
+    // If type is MULTI or META then check for the (optional) directives UPDATE or RESET;
+    // otherwise, get the value and comment.
+    // line may have the following forms:
+    // NAME METADATA
+    // NAME METADATA # Comment
+    // NAME METADATA#Comment
+    // NAME METADATA UPDATE # Comment
+    // NAME METADATA RESET # Comment
+    // NAME METADATA UPDATE
+    // NAME METADATA RESET
+    if((mdType == PS_DATA_METADATA_MULTI) || (mdType == PS_DATA_METADATA)) {
+
+        // Get the metadata directive if there is one.
+        status = 0;
+        strValue = getToken (&linePtr, "#", &status, true);
+       
+        if (!status && strValue) {
+	    // found a directive, what does it say?
+	    if (strcasecmp (strValue, "UPDATE") && strcasecmp (strValue, "RESET")) {
+		psError(PS_ERR_IO, true, _("Invalid directive %s for METADATA or MULTI."), strValue);
+		psFree(strType);
+		psFree(strValue);
+		return false;
+	    }
+
+	    // found a directive, what does it say?
+	    if (!strcasecmp (strValue, "UPDATE")) {
+		// this folder or group is merged with an existing one of the same name
+		flags |= PS_META_UPDATE_FOLDER;
+	    }
+	    if (!strcasecmp (strValue, "RESET")) {
+		// this folder or group replaces an existing one of the same name
+		flags |= PS_META_REPLACE;
+	    }
+	    psFree(strValue);
+	    strValue = NULL;
+	}
+
+        // Not all lines will have comments, so NULL is ok.
+        status = 0;
+
+        // XXX this is a very ugly way of finding from the current position to
+        // the end of the line
+        strComment = getToken(&linePtr, "", &status, true);
+
+        if (status) {
+            psError(PS_ERR_IO, true, _("Error reading metadata line"));
+            psFree(strType);
+            psFree(strComment);
+            return false;
+        }
+    } else {
+        // Get the metadata item value if there is one.
+        status = 0;
+        strValue = getToken(&linePtr, "#", &status,true);
+
+        if(status) {
+            psError(PS_ERR_IO, true, _("Failed to read a metadata value."));
+            psFree(strType);
+            psFree(strValue);
+            return false;
+        }
+
+        if(strValue==NULL) {
+            psError(PS_ERR_IO, true, _("Failed to read a metadata value."));
+            psFree(strType);
+            psFree(strValue);
+            return false;
+        }
+        // Not all lines will have comments, so NULL is ok.
+        status = 0;
+        // XXX this is a very ugly way of finding from the current position to
+        // the end of the line
+        strComment = getToken(&linePtr, "", &status, true);
+        if(status) {
+            psError(PS_ERR_IO, true, _("Failed to read a metadata comment"));
+            psFree(strType);
+            psFree(strValue);
+            psFree(strComment);
+            return false;
+        }
+    } 
+
+#define PARSE_ADD_CASE(NAME, TYPE, PARSEFUNC) \
+  case PS_DATA_##NAME: { \
+      ps##TYPE value = PARSEFUNC(strValue, &status); \
+      if (!status) { \
+          addStatus = psMetadataAdd##TYPE(md, PS_LIST_TAIL, keyName, flags, strComment, value); \
+      } else { \
+          psError(PS_ERR_IO, true, \
+                  _("Failed to parse the value '%s' of metadata item %s, type %s."), \
+                  strValue, keyName, strType); \
+          returnValue = false; \
+      } \
+      break; \
+  }
+
+    // Need to add item to metadata so get pointer to metadata
+    status = 0;
+    md = ((p_psParseLevelInfo*)(levelArray->data[level]))->metadata;
+    nonUniqueKeys = ((p_psParseLevelInfo*)(levelArray->data[level]))->nonUniqueKeyArray;
+    switch(mdType) {
+        PARSE_ADD_CASE(BOOL,   Bool,   parseBool);
+        PARSE_ADD_CASE(F32,    F32,    parseDouble);
+        PARSE_ADD_CASE(F64,    F64,    parseDouble);
+        PARSE_ADD_CASE(S8,     S8,     parseSignedInt);
+        PARSE_ADD_CASE(S16,    S16,    parseSignedInt);
+        PARSE_ADD_CASE(S32,    S32,    parseSignedInt);
+        PARSE_ADD_CASE(S64,    S64,    parseSignedInt);
+        PARSE_ADD_CASE(U8,     U8,     parseUnsignedInt);
+        PARSE_ADD_CASE(U16,    U16,    parseUnsignedInt);
+        PARSE_ADD_CASE(U32,    U32,    parseUnsignedInt);
+        PARSE_ADD_CASE(U64,    U64,    parseUnsignedInt);
+      case PS_DATA_STRING:
+        // map "NULL" strings to NULL
+        if (strcasecmp(strValue, "null") == 0) {
+            addStatus = psMetadataAddStr(md, PS_LIST_TAIL, keyName, flags, strComment, NULL);
+        } else {
+            addStatus = psMetadataAddStr(md, PS_LIST_TAIL, keyName, flags, strComment, strValue);
+        }
+        break;
+      case PS_DATA_TIME: {
+          psTimeType timeType = PS_TIME_TAI;
+          if(!strncmp(strType, "UTC", 3)) {
+              timeType = PS_TIME_UTC;
+          } else if(!strncmp(strType, "TAI", 3)) {
+              timeType = PS_TIME_TAI;
+          } else if(!strncmp(strType, "UT1", 3)) {
+              timeType = PS_TIME_UT1;
+          } else if(!strncmp(strType, "TT", 3)) {
+              timeType = PS_TIME_TT;
+          }
+
+          psTime *mTime = parseTime(strValue, timeType, &status);
+          if(!status) {
+              addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName,
+                                        mdType | flags,
+                                        strComment, mTime);
+          } else {
+              psError(PS_ERR_IO, true,
+                      _("Failed to parse the value '%s' of metadata item %s, type %s."),
+                      strValue, keyName, strType);
+              returnValue = false;
+          }
+          psFree(mTime);
+          break;
+      }
+      case PS_DATA_VECTOR: {
+          psVector *tempVec = parseVector(strValue, vectorType, &status);
+          if(!status) {
+              addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName+1,
+                                        mdType | flags,
+                                        strComment, tempVec);
+          } else {
+              psError(PS_ERR_IO, true,
+                      _("Failed to parse the value '%s' of metadata item %s, type %s."),
+                      strValue, keyName, strType);
+              returnValue = false;
+          }
+          psFree(tempVec);
+          break;
+      }
+    case PS_DATA_METADATA_MULTI:
+        // Add key to non-unique array of keys
+        // Check for duplicate MULTI lines
+
+      // XXX currently, we only place the name of the MULTI on this list.  we thus lose
+      // the associated comment (if any) and the flags (if any) we could probably fix this
+      // behavior by allowing psMetadataAddItem to be passed an empty MULTI, which would
+      // have a null data pointer until an element is added (in other words, treat MULTI
+      // as another type of folder, but without a link of its own on the metadata->list
+
+        addStatus = true;
+        for(psS32 k=0; k < nonUniqueKeys->n; k++) {
+            if(strcmp(keyName,(char*)nonUniqueKeys->data[k]) == 0) {
+                psError(PS_ERR_IO,true,_("Duplicate MULTI specifier."));
+                psFree(strType);
+                return false;
+            }
+        }
+        psString tempStr = psStringCopy(keyName);
+        nonUniqueKeys = psArrayAdd(nonUniqueKeys,0,tempStr);
+        addStatus = true;
+        psFree(tempStr);
+        break;
+    case PS_DATA_METADATA: {
+            // check to see if this keyname already exists and is allowed as a
+            // MULTI.  If we don't do this check first, it's possible that we
+            // can create a new "scope" yet fail to add the new metdata.
+            psMetadataItem *item = psMetadataLookup (md, keyName);
+            if ((item != NULL) &&
+                    ((item->type != PS_DATA_METADATA_MULTI) &&
+                    ((flags & PS_META_REPLACE) == 0))
+            ) {
+                psError(PS_ERR_IO, true, _("Duplicate Metadata declaration: %s is not allowed without 'overwrite' or MULTI specifier."), keyName);
+                break;
+            }
+
+            // create the nested metadata
+            psMetadata *newScope = psMetadataAlloc();
+
+            // Create next level info
+            nextLevelInfo = p_psParseLevelInfoAlloc();
+
+
+            // try to add the new metdata to the current one
+            addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName,
+                                      mdType | flags,
+                                      strComment, newScope);
+
+            if (addStatus) {
+                // switch to the scope to the new metadata
+                nextLevelInfo->metadata = psMemIncrRefCounter(newScope);
+
+                // Add next level to levelArray
+                levelArray = psArrayAdd(levelArray, 0, nextLevelInfo);
+            }
+
+            psFree(nextLevelInfo);
+            psFree(newScope);
+
+            break;
+        }
+    default:
+        psError(PS_ERR_IO, true,
+                _("Metadata of unknown type found."));
+        break;
+    }
+
+    // Check if the add status was successful
+    if (! addStatus) {
+        returnValue = false;
+    }
+
+    psFree(strComment);
+    psFree(strValue);
+    psFree(strType);
+
+    return returnValue;
+}
+
+static bool parseLine(psArray *levelArray,
+                      char *linePtr,
+                      bool overwrite,
+                      bool *notBlank)
+{
+    psMetadataFlags     flags  = PS_META_DEFAULT;
+
+    // Set flags if overwrite specified
+    if (overwrite) {
+        flags = PS_META_REPLACE;
+    }
+
+    // If line is a comment or blank, then extract data
+    if (ignoreLine(linePtr)) {
+        // do nothing and return
+        if (notBlank) {
+            *notBlank = false;
+        }
+        return true;
+    }
+
+    // even if it's a "bad line" we know it can't be "blank" after this point
+    *notBlank = true;
+
+    // Check for more than one '@' in a line
+    // XXX this logic is wrong -- there's no reason a @ can't appear in a
+    // comment
+    if (repeatedChars(linePtr, '@') > 1) {
+        psError(PS_ERR_IO, true,
+                _("More than one '@' character is not allowed"));
+        return false;
+    }
+
+    // Get metadata item name
+    psS32               status = 0;
+    char *keyName = getToken(&linePtr, " ", &status, true);
+    if (status) {
+        psError(PS_ERR_IO, true, _("Failed to read item key name on line"));
+        psFree(keyName);
+        return false;
+    }
+
+    // Check for special keyName values "TYPE", "END"
+    if (strcmp(keyName, "END") == 0) {
+        if (!parseMetadataEnd(keyName, levelArray, linePtr, flags)) {
+            goto FAIL;
+        }
+    } else if (strcmp(keyName,"TYPE") == 0 ) {
+        if (!parseType(keyName, levelArray, linePtr, flags)) {
+            goto FAIL;
+        }
+    } else {
+        if (!parseGeneric(keyName, levelArray, linePtr, flags)) {
+            goto FAIL;
+        }
+    }
+
+    psFree(keyName);
+
+    return true;
+
+FAIL:
+    psError(PS_ERR_UNKNOWN, false, _("Failed to parse line"));
+    psFree(keyName);
+    return false;
+}
+
+static bool parseGeneric(char *keyName,
+                         psArray *levelArray,
+                         char *linePtr,
+                         psMetadataFlags flags)
+{
+    PS_ASSERT_STRING_NON_EMPTY(keyName, false);
+    PS_ASSERT_ARRAY_NON_NULL(levelArray, false);
+    PS_ASSERT_PTR_NON_NULL(linePtr, false);
+
+    long level = psArrayLength(levelArray) - 1;
+
+    // Check if key name present in array of non-unique key names
+    psS32 limit = ((p_psParseLevelInfo*)(levelArray->data[level]))->nonUniqueKeyArray->n;
+    for (psS32 k = 0; k < limit; k++) {
+        char *name = (char*)((p_psParseLevelInfo*)
+                             (levelArray->data[level]))->nonUniqueKeyArray->data[k];
+        if (strcmp(name, keyName) == 0) {
+            flags = PS_META_DUPLICATE_OK;
+        }
+    }
+
+    // Parse metadataItem
+    if (!parseMetadataItem(keyName, levelArray, linePtr, flags)) {
+        return false;
+    }
+
+    return true;
+}
+
+static bool parseType(char *keyName,
+                      psArray *levelArray,
+                      char *linePtr,
+                      psMetadataFlags flags)
+{
+    PS_ASSERT_STRING_NON_EMPTY(keyName, false);
+    PS_ASSERT_ARRAY_NON_NULL(levelArray, false);
+    PS_ASSERT_PTR_NON_NULL(linePtr, false);
+
+    long level = psArrayLength(levelArray) - 1;
+
+    // Get the type name
+    psS32 status = 0;
+    char *strType = getToken(&linePtr, " ", &status, true);
+    if(!strType) {
+        psError(PS_ERR_IO,true, _("Failed to read item type."));
+        return false;
+    }
+    if (status) {
+        psError(PS_ERR_IO, true, _("Failed to read item type."));
+        psFree(strType);
+        return false;
+    }
+
+    // Access typeTypes for this level/scope
+    psHash *typeTemplates = ((p_psParseLevelInfo*)(levelArray->data[level]))->typeTemplates;
+
+    // Check if type already exists in typeTempaltes
+    if (psHashLookup(typeTemplates, strType)) {
+        psError(PS_ERR_IO, true,
+            _("Specified type %s is already defined."), strType);
+        psFree(strType);
+        return false;
+    }
+
+    // attempt to parse the TYPE line into a template metadata
+    psMetadata *tempTemplate = genTypeTemplate(linePtr);
+    if (!tempTemplate) {
+        psError(PS_ERR_IO, true, _("Metadata type '%s' is invalid."), strType);
+        psFree(strType);
+        return false;
+    }
+
+    // Add key name to array of type
+    // Add template to hash of templates
+    if (!psHashAdd(typeTemplates, strType, tempTemplate)) {
+        psError(PS_ERR_UNKNOWN, false, _("failed to add template for '%s' to hash"), strType);
+        psFree(tempTemplate);
+        psFree(strType);
+        return false;
+    }
+
+    psFree(tempTemplate);
+    psFree(strType);
+
+    return true;
+}
+
+static bool parseMetadataEnd(char *keyName,
+                             psArray *levelArray,
+                             char *linePtr,
+                             psMetadataFlags flags)
+{
+    PS_ASSERT_STRING_NON_EMPTY(keyName, false);
+    PS_ASSERT_ARRAY_NON_NULL(levelArray, false);
+    PS_ASSERT_PTR_NON_NULL(linePtr, false);
+
+    long level = psArrayLength(levelArray) - 1;
+
+    if ((level) < 1) {
+        psError(PS_ERR_UNKNOWN, false, "can not END the top level metadata");
+        return false;
+    }
+
+    // the END just moved us up one nesting level
+    // Remove lower info level
+    if(!psArrayRemoveIndex(levelArray, level)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to remove array item");
+        return false;
+    }
+
+    return true;
+}
+
+psMetadata *psMetadataConfigRead(psMetadata *md,
+                                 unsigned int *nFail,
+                                 const char *filename,
+                                 bool overwrite)
+{
+    // Check for NULL file name
+    PS_ASSERT_STRING_NON_EMPTY(filename, NULL);
+
+    psString file = psSlurpFilename(filename);
+
+    md = psMetadataConfigParse(md, nFail, (char *)file, overwrite);
+    if (!md) {
+        psError(PS_ERR_IO, true, _("failed to parse file '%s'"), filename);
+        psFree(md);
+	psFree(file);
+        return NULL;
+    }
+
+    psFree(file);
+    return md;
+}
+
+psMetadata* psMetadataConfigParse(psMetadata* md,
+                                  unsigned int *nFail,
+                                  const char *str,
+                                  bool overwrite)
+{
+    bool allocedMD = false;
+
+    PS_ASSERT_STRING_NON_EMPTY(str, NULL);
+
+    // Initialise nFail, if provided
+    if (nFail) {
+        *nFail = 0;
+    }
+
+    // Allocate metadata if necessary
+    if (md == NULL) {
+        allocedMD = true;
+        md = psMetadataAlloc();
+    }
+
+    // split the input string into an array of lines
+    psList *doc = psStringSplit(str, "\n", true);
+    if (!doc) {
+        psError(PS_ERR_UNKNOWN, false, "failed to split string: %s", str);
+        if (allocedMD) {
+            psFree(md);
+        }
+        return NULL;
+    }
+
+    // accept completely empty strings
+    // nFail == 0 / nPass == 0 - OK
+    if (psListLength(doc) == 0) {
+        psTrace("psLib.types", PS_LOG_INFO, "string contained no lines");
+        psFree(doc);
+        return md;
+    }
+
+    // Allocate array to store parse level information
+    psArray *parseLevelInfoArray = psArrayAllocEmpty(INITIAL_LENGTH);
+
+    // Set parse level info for the top level
+    p_psParseLevelInfo *topLevelInfo = p_psParseLevelInfoAlloc();
+    topLevelInfo->metadata = psMemIncrRefCounter(md);
+    psArrayAdd(parseLevelInfoArray, 0, topLevelInfo);
+    psFree(topLevelInfo);
+
+    // clear the error stack so we can call psError(..., false, ...) and let
+    // errors from the parse loop accumulate
+    psErrorClear();
+
+    // line type counts
+    long nLines = 0;                // all lines
+    long nGood  = 0;                // valid lines excluding blank/comment
+    long nBad   = 0;                // invalid lines
+
+    // While loop to parse the file
+    char *line = NULL;
+    psListIterator *iter = psListIteratorAlloc(doc, 0, false);
+    while ((line = psListGetAndIncrement(iter))) {
+        nLines++; // indexed from 1
+
+        bool notBlank = false;
+        if (!parseLine(parseLevelInfoArray, line, overwrite, &notBlank)) {
+            nBad++;
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Error parsing line #%lu : %s", nLines, line);
+        } else if (notBlank) {
+        // do not count blank/comment lines as "good" lines
+            nGood++;
+        }
+    }
+
+    psFree(iter);
+    psFree(doc);
+
+    // Free parse array and line buffer
+    psFree(parseLevelInfoArray);
+
+    // nFail > 0 / nPass == 0 - NULL
+    if ((nBad > 0) && (nGood == 0)) {
+        psError(PS_ERR_UNKNOWN, false, "string contained no data lines and %ld bad lines", nBad);
+        psFree(md);
+        return NULL;
+    }
+
+    // pass back the number of failed lines
+    if (nFail) {
+        *nFail = nBad;
+    }
+
+    // nFail == 0 / nPass > 0
+    // nFail > 0 / nPass > 0
+    return md;
+}
+
+psString psMetadataConfigFormat(psMetadata *md)
+{
+    PS_ASSERT_METADATA_NON_NULL(md, NULL);
+
+    psString format = psStringCopy("");
+
+    psArray *keys = p_psMetadataKeyArray(md);
+    for (long i = 0; i < psArrayLength(keys); i++) {
+        psMetadataItem *item = psMetadataLookup(md, keys->data[i]);
+        if (!item) {
+            // XXX : this is probably not the right error value
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    _("Specified psDataType, %d, is not supported."), PS_DATA_UNKNOWN);
+            psTrace("psLib.types", 5, "failed to find key %s\n", (char *) keys->data[i]);
+            psFree(keys);
+            psFree(format);
+            return NULL;
+        }
+        psString str = formatMetadataItem(item);
+        if (!str) {
+            psError(PS_ERR_UNKNOWN, false, "failed to format psMetadataItem");
+            psTrace("psLib.types", 5, "failed to format %s\n", (char *) keys->data[i]);
+            psFree(keys);
+            psFree(format);
+            psFree(str);
+            return NULL;
+        }
+        psStringAppend(&format, "%s", str);
+        psFree(str);
+    }
+
+    psFree(keys);
+
+    return format;
+}
+
+
+static psString formatMetadataItem(psMetadataItem *item)
+{
+    PS_ASSERT_METADATA_ITEM_NON_NULL(item, NULL);
+
+    psString content = NULL;
+
+    #define FORMAT_PRIMITIVE_METADATAITEM(type, dataformat) \
+    psStringAppend(&content, "%-15s  %-8s  %-15" dataformat, \
+                   item->name, #type, item->data.type); \
+    if (item->comment && strncmp(item->comment, "", 2)) { \
+        psStringAppend(&content, "  # %s", item->comment); \
+    } \
+    psStringAppend(&content, "\n");
+
+    // In this block, the single item is used to build 'content'
+    switch (item->type) {
+    case PS_DATA_METADATA_MULTI: {
+            psStringAppend(&content, "%s MULTI\n", item->name);
+
+            // a MULTI is a list of items so we need to recurse through the
+            // list
+            psListIterator *iter = psListIteratorAlloc(item->data.list, 0, false);
+            psMetadataItem *multiItem = NULL;
+            while ((multiItem = psListGetAndIncrement(iter))) {
+                psString str = formatMetadataItem(multiItem);
+                psStringAppend(&content, str);
+                psFree(str);
+            }
+            psFree(iter);
+        }
+        break;
+    case PS_DATA_BOOL:
+        psStringAppend (&content, "%-15s  %-8s  %-15s",
+                        item->name, "BOOL", item->data.B ? "T" : "F");
+        if (item->comment && strncmp(item->comment, "", 2)) {
+            psStringAppend(&content, "  # %s", item->comment);
+        }
+        psStringAppend(&content, "\n");
+        break;
+    case PS_DATA_S8:
+        FORMAT_PRIMITIVE_METADATAITEM(S8, "d");
+        break;
+    case PS_DATA_S16:
+        FORMAT_PRIMITIVE_METADATAITEM(S16, "d");
+        break;
+    case PS_DATA_S32:
+        FORMAT_PRIMITIVE_METADATAITEM(S32, "d");
+        break;
+    case PS_DATA_S64:
+        FORMAT_PRIMITIVE_METADATAITEM(S64, PRId64);
+        break;
+    case PS_DATA_U8:
+        FORMAT_PRIMITIVE_METADATAITEM(U8, "u");
+        break;
+    case PS_DATA_U16:
+        FORMAT_PRIMITIVE_METADATAITEM(U16, "u");
+        break;
+    case PS_DATA_U32:
+        FORMAT_PRIMITIVE_METADATAITEM(U32, "u");
+        break;
+    case PS_DATA_U64:
+        FORMAT_PRIMITIVE_METADATAITEM(U64, PRIu64);
+        break;
+    case PS_DATA_F32:
+        FORMAT_PRIMITIVE_METADATAITEM(F32, ".7g");
+        break;
+    case PS_DATA_F64:
+        FORMAT_PRIMITIVE_METADATAITEM(F64, ".15g");
+        break;
+      case PS_DATA_STRING: {
+          bool valid = false;
+          if (item->data.str && strlen(item->data.str) > 0) {
+              char *p = item->data.str;
+              while (*p && isblank(*p)) p++;
+              if (*p) valid = true;
+          }
+          if (valid) {
+              psStringAppend(&content, "%-15s  %-8s  %-15s",
+                             item->name, "STR", item->data.str);
+          } else {
+              psStringAppend(&content, "%-15s  %-8s  %-15s",
+                             item->name, "STR", "NULL");
+          }
+          if (item->comment && strncmp(item->comment,"",2)) {
+              psStringAppend(&content, "  # %s", item->comment);
+          }
+          psStringAppend(&content, " \n");
+          break;
+      }
+    case PS_DATA_METADATA: {
+            if (item->comment && strncmp(item->comment,"",2)) {
+                psStringAppend(&content, "\n%s  METADATA  # %s", item->name, item->comment);
+            } else {
+                psStringAppend(&content, "\n%s  METADATA  ", item->name);
+            }
+
+            psString newStr = psMetadataConfigFormat(item->data.md);
+            if (newStr) {
+                // add 3 extra spaces to each metadata folder item
+                char *buf = strtok(newStr, "\n");
+                while (buf != NULL) {
+                    psStringAppend(&content, "\n   %s", buf);
+                    buf = strtok(NULL, "\n");
+                }
+                psFree(newStr);
+            }
+
+            psStringAppend(&content, "\nEND\n");
+            break;
+        }
+    case PS_DATA_TIME:
+        psStringAppend(&content, "%-15s  ", item->name);
+        psTime *time = item->data.V;
+        if (time) {
+            switch (time->type) {
+            case PS_TIME_UTC:
+                psStringAppend(&content, "%-8s  ", "UTC");
+                break;
+            case PS_TIME_TAI:
+                psStringAppend(&content, "%-8s  ", "TAI");
+                break;
+            case PS_TIME_UT1:
+                psStringAppend(&content, "%-8s  ", "UT1");
+                break;
+            case PS_TIME_TT:
+                psStringAppend(&content, "%-8s  ", "TT");
+                break;
+            default:
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                        _("Specified psTime type, %d, is not supported."),
+                        time->type);
+                psFree(content);
+                return NULL;
+            }
+            psString timeStr = psTimeToISO(time);
+            psString timeOutput;
+            timeOutput = psStringNCopy(timeStr, 19);
+            psStringAppend(&content, "%s", timeOutput);
+            psStringAppend(&content, "Z");
+            psFree(timeStr);
+            psFree(timeOutput);
+        } else {
+            // psTime is a NULL pointer
+            psStringAppend(&content, "%-8s  %-15s", "TAI", "NULL");
+        }
+
+        if (item->comment && strncmp(item->comment,"",2)) {
+            psStringAppend(&content, "  # %s", item->comment);
+        }
+        psStringAppend(&content, "\n");
+        break;
+    case PS_DATA_VECTOR:
+        psStringAppend(&content, "@%s ", item->name);
+        psVector *vector = item->data.V;
+
+        switch (vector->type.type) {
+        case PS_DATA_U8:
+            psStringAppend(&content, "U8 ");
+            for (int i = 0; i < vector->n; i++) {
+                psStringAppend(&content, "%u ", vector->data.U8[i]);
+            }
+            break;
+        case PS_DATA_U16:
+            psStringAppend(&content, "U16 ");
+            for (int i = 0; i < vector->n; i++) {
+                psStringAppend(&content, "%u ", vector->data.U16[i]);
+            }
+            break;
+        case PS_DATA_U32:
+            psStringAppend(&content, "U32 ");
+            for (int i = 0; i < vector->n; i++) {
+                psStringAppend(&content, "%u ", vector->data.U32[i]);
+            }
+            break;
+        case PS_DATA_U64:
+            psStringAppend(&content, "U64 ");
+            for (int i = 0; i < vector->n; i++) {
+                psStringAppend(&content, "%" PRIu64 " ", vector->data.U64[i]);
+            }
+            break;
+        case PS_DATA_S8:
+            psStringAppend(&content, "S8 ");
+            for (int i = 0; i < vector->n; i++) {
+                psStringAppend(&content, "%d ", vector->data.S8[i]);
+            }
+            break;
+        case PS_DATA_S16:
+            psStringAppend(&content, "S16 ");
+            for (int i = 0; i < vector->n; i++) {
+                psStringAppend(&content, "%d ", vector->data.S16[i]);
+            }
+            break;
+        case PS_DATA_S32:
+            psStringAppend(&content, "S32 ");
+            for (int i = 0; i < vector->n; i++) {
+                psStringAppend(&content, "%d ", vector->data.S32[i]);
+            }
+            break;
+        case PS_DATA_S64:
+            psStringAppend(&content, "S64 ");
+            for (int i = 0; i < vector->n; i++) {
+                psStringAppend(&content, "%" PRId64 " ", vector->data.S64[i]);
+            }
+            break;
+        case PS_DATA_F32:
+            psStringAppend(&content, "F32 ");
+            for (int i = 0; i < vector->n; i++) {
+                psStringAppend(&content, "%.7g ", vector->data.F32[i]);
+            }
+            break;
+        case PS_DATA_F64:
+            psStringAppend(&content, "F64 ");
+            for (int i = 0; i < vector->n; i++) {
+                psStringAppend(&content, "%.15g ", vector->data.F64[i]);
+            }
+            break;
+        case PS_DATA_UNKNOWN:
+        default:
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    _("Specified psDataType, %d, is not supported."), vector->type.type);
+            psFree(content);
+            return NULL;
+        }
+        if (item->comment && strncmp(item->comment, "", 2)) {
+            psStringAppend(&content, "  # %s", item->comment);
+        }
+        psStringAppend(&content, "\n");
+        break;
+    case PS_DATA_UNKNOWN:
+    default:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified psDataType, %d, is not supported."), item->type);
+        psFree(content);
+        return NULL;
+    }
+
+    return content;
+}
+
+
+static psArray *p_psMetadataKeyArray(psMetadata *md)
+{
+    PS_ASSERT_METADATA_NON_NULL(md, NULL);
+
+    psArray *keys = psArrayAllocEmpty(psListLength(md->list));
+
+    // since we want to preserve the order of the keys in the metadata we can't
+    // get a list of key names from the metadata's hash table.  Instead we have
+    // to iterate through the metadata's list of items and reject duplicate key
+    // names.
+
+    psMetadataItem *item = NULL;
+    psMetadataIterator *iter = psMetadataIteratorAlloc(md, PS_LIST_HEAD, NULL);
+OUTSIDE:
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        for (long i = 0; i < psArrayLength(keys); i++) {
+            // does this element have a value
+            psString elem = keys->data[i];
+            if (elem) {
+                if(strcmp(elem, item->name) == 0) {
+                    goto OUTSIDE;
+                }
+            }
+        }
+        psString string = psStringCopy(item->name);
+        psArrayAdd(keys, 0, string);
+        psFree(string);
+    }
+    psFree(iter);
+    return keys;
+}
+
+
+bool psMetadataConfigWrite(psMetadata *md,
+                           const char *filename)
+{
+    PS_ASSERT_METADATA_NON_NULL(md, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(filename, NULL);
+    FILE *file;
+    if ( !(file = fopen(filename, "w")) ) {
+        psError(PS_ERR_IO, true,
+                "Failed to open specified file, %s\n", filename);
+        return false;
+    }
+    psString fileString = NULL;
+    fileString = psMetadataConfigFormat(md);
+    if (fileString == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psMetadataConfigFormat returned NULL.\n");
+        return false;
+    }
+    fprintf(file, "%s", fileString);
+    psFree(fileString);
+    if (fclose(file) == EOF) {
+        psError(PS_ERR_IO, true,
+                "Failed to close file, %s\n", filename);
+        return false;
+    }
+    return true;
+}
+
+bool psMetadataConfigPrint(FILE *stream,
+                           psMetadata *md)
+{
+    PS_ASSERT_METADATA_NON_NULL(md, false);
+    PS_ASSERT_PTR_NON_NULL(stream, false);
+    if (fprintf(stream, "\n") <= 0) {
+        psError(PS_ERR_IO, false,
+                "Unable to write to specified file.");
+        return false;
+    }
+
+    psString str = psMetadataConfigFormat(md);
+    if (!str) {
+        psError(PS_ERR_UNKNOWN, false,
+                _("failed to format metadata into a string."));
+        return false;
+    }
+
+    fprintf(stream, "%s", str);
+    psFree(str);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadataConfig.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadataConfig.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadataConfig.h	(revision 22158)
@@ -0,0 +1,101 @@
+/** @file  psMetadataConfig.h
+ *
+ *  @brief Contains metadata input/output functions.
+ *
+ *  This file defines functions to read and write metadata to/from an external file.
+ *
+ *  @author EAM, IfA
+ *  @author PAP, IfA
+ *  @author JH, IfA
+ *  @author Ross Harman, MHPCC
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.26 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-01-23 22:47:23 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+#ifndef PS_METADATACONFIG_H
+#define PS_METADATACONFIG_H
+
+#include "psMetadata.h"
+
+/// @addtogroup DataContainer Data Containers
+/// @{
+
+/** Print metadata item to file.
+ *
+ *  Metadata items may be printed to an open file descriptor based on a
+ *  provided format. The format is a sprintf format statement with exactly
+ *  one % formatting command. If the metadata item type is a numeric type,
+ *  this formatting command must also be numeric, and the type conversion
+ *  performed to the value to match the format type. If the metadata type is
+ *  a string, the formatting command must also be for a string. If the
+ *  metadata type is any other data type, printing is not allowed.
+ *
+ * @return psMetadataItem* :    Pointer metadata item.
+ */
+bool psMetadataItemPrint(
+    FILE * fd,                         ///< Pointer to file to write metadata item.
+    const char *format,                ///< Format to print metadata item.
+    const psMetadataItem* item         ///< Metadata item to print.
+);
+
+/** Read metadata configuration file.
+ *
+ *  Loads pre-defined settings by parsing a configuration file into a psMetadata structure.
+ *
+ *  @return psMetadata* : Resulting metadata from read.
+ */
+psMetadata* psMetadataConfigRead(
+    psMetadata* md,                    ///< Resulting metadata from read.
+    unsigned int *nFail,               ///< Number of failed lines.
+    const char *filename,              ///< Name of file to read.
+    bool overwrite                     ///< Allow overwrite of duplicate specifications.
+);
+
+/** Parse metadata configuration string.
+ *
+ *  Loads pre-defined settings by parsing a string into a psMetadata structure.
+ *
+ *  @return psMetadata* : Resulting metadata from parse.
+ */
+psMetadata* psMetadataConfigParse(
+    psMetadata* md,                    ///< Resulting metadata from read.
+    unsigned int *nFail,               ///< Number of failed lines.
+    const char *str,                   ///< String to process.
+    bool overwrite                     ///< Allow overwrite of duplicate specifications.
+);
+
+/** Converts a psMetadata structure (including any nested psMetadata) into a
+ *  configuration file formatted string.
+ *
+ *  A NULL shall be returned on error.
+ *  @return psString:       a Configuration File formatted string.
+ */
+psString psMetadataConfigFormat(
+    psMetadata *md                     ///< The metadata to convert
+);
+
+/** Converts a psMetadata structure (including any nested psMetadata) into a
+ *  configuration file formatted string that is written out to filename.
+ *
+ *  @return bool:       True if successful, otherwise false.
+ */
+bool psMetadataConfigWrite(
+    psMetadata *md,                    ///< The metadata to convert
+    const char *filename               ///< Name of file to write
+);
+
+/** Converts a psMetadata structure (including any nested psMetadata) into a
+ *  configuration file formatted string that is written a file stream.
+ *
+ *  @return bool:       True if successful, otherwise false.
+ */
+bool psMetadataConfigPrint(
+    FILE *stream,                       ///< file stream to write to
+    psMetadata *md                      ///< The metadata to convert
+);
+
+/// @}
+#endif // #ifndef PS_METADATAIO_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadataItemCompare.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadataItemCompare.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadataItemCompare.c	(revision 22158)
@@ -0,0 +1,119 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+
+#include "psType.h"
+#include "psError.h"
+#include "psAbort.h"
+#include "psTrace.h"
+#include "psMetadata.h"
+#include "psMetadataItemCompare.h"
+
+bool psMetadataItemCompare(const psMetadataItem *compare, // Item to compare to the template
+                           const psMetadataItem *template) // The template
+{
+
+    // First order checks
+    if (! compare || ! template) {
+        return false;
+    }
+    if (strcmp(compare->name, template->name)
+            != 0) {
+        return false;
+    }
+
+
+    #define COMPARE_CASE(TEMPLATENAME, TEMPLATETYPE, COMPARENAME, COMPARETYPENAME) \
+case PS_TYPE_##COMPARETYPENAME: { \
+        TEMPLATETYPE value = (TEMPLATETYPE)compare->data.COMPARENAME; \
+        if (value != compare->data.COMPARENAME) { \
+            return false; \
+        } \
+        return (template->data.TEMPLATENAME == value) ? true : false; \
+    }
+
+    #define TEMPLATE_CASE(TYPENAME, NAME, TYPE) \
+case PS_TYPE_##TYPENAME: \
+    switch(compare->type) { \
+        COMPARE_CASE(NAME, TYPE, B  , BOOL); \
+        COMPARE_CASE(NAME, TYPE, U8 , U8 ); \
+        COMPARE_CASE(NAME, TYPE, U16, U16); \
+        COMPARE_CASE(NAME, TYPE, U32, U32); \
+        COMPARE_CASE(NAME, TYPE, S8 , S8 ); \
+        COMPARE_CASE(NAME, TYPE, S16, S16); \
+        COMPARE_CASE(NAME, TYPE, S32, S32); \
+        COMPARE_CASE(NAME, TYPE, F32, F32); \
+        COMPARE_CASE(NAME, TYPE, F64, F64); \
+    default: \
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Don't know how to compare types %x and %x\n", \
+                compare->type, template->type); \
+        return false; \
+    }
+
+
+    switch (template->type) {
+        TEMPLATE_CASE(BOOL, B,   bool)
+        ;
+        TEMPLATE_CASE(U8,   U8,  psU8 );
+        TEMPLATE_CASE(U16,  U16, psU16);
+        TEMPLATE_CASE(U32,  U32, psU32);
+        TEMPLATE_CASE(S8,   S8,  psS8 );
+        TEMPLATE_CASE(S16,  S16, psS16);
+        TEMPLATE_CASE(S32,  S32, psS32);
+        TEMPLATE_CASE(F32,  F32, psF32);
+        TEMPLATE_CASE(F64,  F64, psF64);
+    case PS_DATA_STRING:
+
+        // for MULTI, try each one & succeed if any match (valid = true is default state)
+        if (compare->type == PS_DATA_METADATA_MULTI) {
+            for (int j = 0; j < compare->data.list->n; j++) {
+                psMetadataItem *entry = psListGet (compare->data.list, j);
+		if (!entry) continue;
+		if (entry->type != PS_DATA_STRING) {
+		  continue;
+		}
+		if (template->data.V && !entry->data.V) { // expecting valid data, found NULL
+		  continue;
+		}
+		if (!template->data.V && entry->data.V) { // expecting NULL, found valid data
+		  continue;
+		}
+		// XXX should we return true for both NULL?
+		if (!template->data.V && !entry->data.V) { // expecting NULL, found NULL
+		  return true;
+		}
+		if (!strcasecmp(entry->data.V, template->data.V)) {
+		  return true;
+		}
+		// XXX this is a hack : also compare with the comment field (for HISTORY, COMMENT)
+		if (!strcasecmp(entry->comment, template->data.V)) {
+		  return true;
+		}
+            }
+	    return false;
+        }
+
+	// any other (non-MULTI) is a mis-match
+        if (compare->type != PS_DATA_STRING) {
+            return false;
+        }
+        psTrace("psLib.types", 10, "Comparing '%s' with '%s'\n", compare->data.str, template->data.str);
+        if ((!compare->data.V && template->data.V) || (!template->data.V && compare->data.V)) {
+            return false;
+        }
+        return (strcasecmp(compare->data.V, template->data.V) == 0) ? true : false;
+
+    default:
+        // Simply don't know how to compare more complex types.
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Don't know how to compare types %x and %x\n",
+                compare->type, template->type);
+        return false;
+    }
+
+    psAbort("Should never get here.\n");
+    return false;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadataItemCompare.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadataItemCompare.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadataItemCompare.h	(revision 22158)
@@ -0,0 +1,34 @@
+/** @file  psMetadataItemCompare.h
+ *
+ *  @brief Compares Metadata Items
+ *
+ *  This file defines functions to compare psMetadataItem's.
+ *
+ *  @author IFA
+ *
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-01-23 22:47:23 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_METADATA_ITEM_COMPARE_H
+#define PS_METADATA_ITEM_COMPARE_H
+
+#include "psMetadata.h"
+
+/// @addtogroup DataContainer Data Containers
+/// @{
+
+/** Compares two psMetadataItems.
+ *
+ *  @return bool:       True if compare matches template, otherwise false.
+ */
+bool psMetadataItemCompare(
+    const psMetadataItem *compare,     ///< Item to compare to the template
+    const psMetadataItem *template     ///< The template
+)
+;
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadataItemParse.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadataItemParse.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadataItemParse.c	(revision 22158)
@@ -0,0 +1,288 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include "psMemory.h"
+#include "psAssert.h"
+#include "psError.h"
+#include "psMetadata.h"
+#include "psMetadataItemParse.h"
+
+# define PS_METADATA_ITEM_PARSE_NUMBER(INTYPE,OUTTYPE) \
+case PS_DATA_##INTYPE: \
+return (ps##OUTTYPE)(item->data.INTYPE); \
+
+
+// NOTE: This function flows through so that errors may be handled by the "default" case.
+#define PS_METADATA_ITEM_PARSE_STRING_FLOAT(OUTTYPE,FUNCTION) \
+case PS_DATA_STRING: { \
+    char *end = NULL; \
+    ps##OUTTYPE number = FUNCTION(item->data.V, &end); \
+    if (end != item->data.V) { \
+        return number; \
+    } \
+}
+
+// NOTE: This function flows through so that errors may be handled by the "default" case.
+#define PS_METADATA_ITEM_PARSE_STRING_INT(OUTTYPE,FUNCTION) \
+case PS_DATA_STRING: { \
+    char *end = NULL; \
+    ps##OUTTYPE number = FUNCTION(item->data.V, &end, 10); \
+    if (end != item->data.V) { \
+        return number; \
+    } \
+}
+
+bool psMetadataItemParseBool(const psMetadataItem *item
+                              )
+{
+    PS_ASSERT_METADATA_ITEM_NON_NULL(item, false);
+
+    switch (item->type) {
+        PS_METADATA_ITEM_PARSE_NUMBER(F32, BOOL);
+        PS_METADATA_ITEM_PARSE_NUMBER(F64, BOOL);
+        PS_METADATA_ITEM_PARSE_NUMBER(S8,  BOOL);
+        PS_METADATA_ITEM_PARSE_NUMBER(S16, BOOL);
+        PS_METADATA_ITEM_PARSE_NUMBER(S32, BOOL);
+        PS_METADATA_ITEM_PARSE_NUMBER(U8,  BOOL);
+        PS_METADATA_ITEM_PARSE_NUMBER(U16, BOOL);
+        PS_METADATA_ITEM_PARSE_NUMBER(U32, BOOL);
+    case PS_DATA_BOOL:
+        return item->data.B;
+    case PS_DATA_STRING:
+        if (strcasecmp(item->data.V, "true") == 0) {
+            return true;
+        } else if (strcasecmp(item->data.V, "false") == 0) {
+            return false;
+        }
+        // Flow through
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Item %s (%s) is not of boolean type (%x) --- "
+                "treating as false.\n", item->name, item->comment, item->type);
+        return false;
+    }
+}
+
+psF32 psMetadataItemParseF32(const psMetadataItem *item
+                            )
+{
+    PS_ASSERT_METADATA_ITEM_NON_NULL(item, NAN);
+
+    switch (item->type) {
+        PS_METADATA_ITEM_PARSE_NUMBER(F32, F32);
+        PS_METADATA_ITEM_PARSE_NUMBER(F64, F32);
+        PS_METADATA_ITEM_PARSE_NUMBER(S8,  F32);
+        PS_METADATA_ITEM_PARSE_NUMBER(S16, F32);
+        PS_METADATA_ITEM_PARSE_NUMBER(S32, F32);
+        PS_METADATA_ITEM_PARSE_NUMBER(U8,  F32);
+        PS_METADATA_ITEM_PARSE_NUMBER(U16, F32);
+        PS_METADATA_ITEM_PARSE_NUMBER(U32, F32);
+        PS_METADATA_ITEM_PARSE_STRING_FLOAT(F32, strtof);
+        // Flow through
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Item %s (%s) is not of floating point type (%x) --- "
+                "treating as NaN.\n", item->name, item->comment, item->type);
+        return NAN;
+    }
+}
+
+psF64 psMetadataItemParseF64(const psMetadataItem *item
+                            )
+{
+    PS_ASSERT_METADATA_ITEM_NON_NULL(item, NAN);
+
+    switch (item->type) {
+        PS_METADATA_ITEM_PARSE_NUMBER(F32, F64);
+        PS_METADATA_ITEM_PARSE_NUMBER(F64, F64);
+        PS_METADATA_ITEM_PARSE_NUMBER(S8,  F64);
+        PS_METADATA_ITEM_PARSE_NUMBER(S16, F64);
+        PS_METADATA_ITEM_PARSE_NUMBER(S32, F64);
+        PS_METADATA_ITEM_PARSE_NUMBER(U8,  F64);
+        PS_METADATA_ITEM_PARSE_NUMBER(U16, F64);
+        PS_METADATA_ITEM_PARSE_NUMBER(U32, F64);
+        PS_METADATA_ITEM_PARSE_STRING_FLOAT(F32, strtod);
+        // Flow through
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Item %s (%s) is not of double-precision floating "
+                "point type (%x) --- treating as NaN.\n", item->name, item->comment, item->type);
+        return NAN;
+    }
+}
+
+psU8 psMetadataItemParseU8(const psMetadataItem *item
+                          )
+{
+    PS_ASSERT_METADATA_ITEM_NON_NULL(item, 0);
+
+    switch (item->type) {
+        PS_METADATA_ITEM_PARSE_NUMBER(F32, U8);
+        PS_METADATA_ITEM_PARSE_NUMBER(F64, U8);
+        PS_METADATA_ITEM_PARSE_NUMBER(S8,  U8);
+        PS_METADATA_ITEM_PARSE_NUMBER(S16, U8);
+        PS_METADATA_ITEM_PARSE_NUMBER(S32, U8);
+        PS_METADATA_ITEM_PARSE_NUMBER(U8,  U8);
+        PS_METADATA_ITEM_PARSE_NUMBER(U16, U8);
+        PS_METADATA_ITEM_PARSE_NUMBER(U32, U8);
+        PS_METADATA_ITEM_PARSE_STRING_INT(U8,strtoul);
+        // Flow through
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Item %s (%s) is not of integer type (%x) --- "
+                "treating as zero.\n", item->name, item->comment, item->type);
+        return 0;
+    }
+}
+
+psU16 psMetadataItemParseU16(const psMetadataItem *item
+                            )
+{
+    PS_ASSERT_METADATA_ITEM_NON_NULL(item, 0);
+
+    switch (item->type) {
+        PS_METADATA_ITEM_PARSE_NUMBER(F32, U16);
+        PS_METADATA_ITEM_PARSE_NUMBER(F64, U16);
+        PS_METADATA_ITEM_PARSE_NUMBER(S8,  U16);
+        PS_METADATA_ITEM_PARSE_NUMBER(S16, U16);
+        PS_METADATA_ITEM_PARSE_NUMBER(S32, U16);
+        PS_METADATA_ITEM_PARSE_NUMBER(U8,  U16);
+        PS_METADATA_ITEM_PARSE_NUMBER(U16, U16);
+        PS_METADATA_ITEM_PARSE_NUMBER(U32, U16);
+        PS_METADATA_ITEM_PARSE_STRING_INT(U16,strtoul);
+        // Flow through
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Item %s (%s) is not of integer type (%x) --- "
+                "treating as zero.\n", item->name, item->comment, item->type);
+        return 0;
+    }
+}
+
+psU32 psMetadataItemParseU32(const psMetadataItem *item
+                            )
+{
+    PS_ASSERT_METADATA_ITEM_NON_NULL(item, 0);
+
+    switch (item->type) {
+        PS_METADATA_ITEM_PARSE_NUMBER(F32, U32);
+        PS_METADATA_ITEM_PARSE_NUMBER(F64, U32);
+        PS_METADATA_ITEM_PARSE_NUMBER(S8,  U32);
+        PS_METADATA_ITEM_PARSE_NUMBER(S16, U32);
+        PS_METADATA_ITEM_PARSE_NUMBER(S32, U32);
+        PS_METADATA_ITEM_PARSE_NUMBER(U8,  U32);
+        PS_METADATA_ITEM_PARSE_NUMBER(U16, U32);
+        PS_METADATA_ITEM_PARSE_NUMBER(U32, U32);
+        PS_METADATA_ITEM_PARSE_STRING_INT(U32,strtoul);
+        // Flow through
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Item %s (%s) is not of integer type (%x) --- "
+                "treating as zero.\n", item->name, item->comment, item->type);
+        return 0;
+    }
+}
+
+psS8 psMetadataItemParseS8(const psMetadataItem *item
+                          )
+{
+    PS_ASSERT_METADATA_ITEM_NON_NULL(item, 0);
+
+    switch (item->type) {
+        PS_METADATA_ITEM_PARSE_NUMBER(F32, S8);
+        PS_METADATA_ITEM_PARSE_NUMBER(F64, S8);
+        PS_METADATA_ITEM_PARSE_NUMBER(S8,  S8);
+        PS_METADATA_ITEM_PARSE_NUMBER(S16, S8);
+        PS_METADATA_ITEM_PARSE_NUMBER(S32, S8);
+        PS_METADATA_ITEM_PARSE_NUMBER(U8,  S8);
+        PS_METADATA_ITEM_PARSE_NUMBER(U16, S8);
+        PS_METADATA_ITEM_PARSE_NUMBER(U32, S8);
+        PS_METADATA_ITEM_PARSE_STRING_INT(S8,strtol);
+        // Flow through
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Item %s (%s) is not of integer type (%x) --- "
+                "treating as zero.\n", item->name, item->comment, item->type);
+        return 0;
+    }
+}
+
+psS16 psMetadataItemParseS16(const psMetadataItem *item
+                            )
+{
+    PS_ASSERT_METADATA_ITEM_NON_NULL(item, 0);
+
+    switch (item->type) {
+        PS_METADATA_ITEM_PARSE_NUMBER(F32, S16);
+        PS_METADATA_ITEM_PARSE_NUMBER(F64, S16);
+        PS_METADATA_ITEM_PARSE_NUMBER(S8,  S16);
+        PS_METADATA_ITEM_PARSE_NUMBER(S16, S16);
+        PS_METADATA_ITEM_PARSE_NUMBER(S32, S16);
+        PS_METADATA_ITEM_PARSE_NUMBER(U8,  S16);
+        PS_METADATA_ITEM_PARSE_NUMBER(U16, S16);
+        PS_METADATA_ITEM_PARSE_NUMBER(U32, S16);
+        PS_METADATA_ITEM_PARSE_STRING_INT(S16,strtol);
+        // Flow through
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Item %s (%s) is not of integer type (%x) --- "
+                "treating as zero.\n", item->name, item->comment, item->type);
+        return 0;
+    }
+}
+
+psS32 psMetadataItemParseS32(const psMetadataItem *item
+                            )
+{
+    PS_ASSERT_METADATA_ITEM_NON_NULL(item, 0);
+
+    switch (item->type) {
+        PS_METADATA_ITEM_PARSE_NUMBER(F32, S32);
+        PS_METADATA_ITEM_PARSE_NUMBER(F64, S32);
+        PS_METADATA_ITEM_PARSE_NUMBER(S8,  S32);
+        PS_METADATA_ITEM_PARSE_NUMBER(S16, S32);
+        PS_METADATA_ITEM_PARSE_NUMBER(S32, S32);
+        PS_METADATA_ITEM_PARSE_NUMBER(U8,  S32);
+        PS_METADATA_ITEM_PARSE_NUMBER(U16, S32);
+        PS_METADATA_ITEM_PARSE_NUMBER(U32, S32);
+        PS_METADATA_ITEM_PARSE_STRING_INT(S32,strtol);
+        // Flow through
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Item %s (%s) is not of integer type (%x) --- "
+                "treating as zero.\n", item->name, item->comment, item->type);
+        return 0;
+    }
+}
+
+# define PS_METADATA_ITEM_PARSE_STRING(TYPE,MODE) \
+case PS_DATA_##TYPE: { \
+    psString value = NULL; \
+    psStringAppend(&value, MODE, item->data.TYPE); \
+    return value; } \
+
+psString psMetadataItemParseString(const psMetadataItem *item
+                                  )
+{
+    PS_ASSERT_METADATA_ITEM_NON_NULL(item, NULL);
+
+    switch (item->type) {
+    case PS_DATA_STRING:
+        return psMemIncrRefCounter(item->data.V);
+
+        PS_METADATA_ITEM_PARSE_STRING(F32, "%f");
+        PS_METADATA_ITEM_PARSE_STRING(F64, "%f");
+        PS_METADATA_ITEM_PARSE_STRING(S8,  "%d");
+        PS_METADATA_ITEM_PARSE_STRING(S16, "%d");
+        PS_METADATA_ITEM_PARSE_STRING(S32, "%d");
+        PS_METADATA_ITEM_PARSE_STRING(U8,  "%d");
+        PS_METADATA_ITEM_PARSE_STRING(U16, "%d");
+        PS_METADATA_ITEM_PARSE_STRING(U32, "%d");
+      case PS_DATA_TIME:
+        return psTimeToISO(item->data.V);
+
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                "Item %s (%s) is not of string type (%x) --- treating as "
+                "undefined.\n", item->name, item->comment, item->type);
+        //        return psStringCopy("");
+        return NULL;
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadataItemParse.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadataItemParse.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psMetadataItemParse.h	(revision 22158)
@@ -0,0 +1,35 @@
+/** @file  psMetadataItemParse.h
+*
+*  @brief Parse metadata items
+*
+*  @author EAM, PAP, JH, RHL, 
+*
+*  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-02-06 21:36:09 $
+*
+*  Copyright 2004-2005 IfA, University of Hawaii
+*/
+
+#ifndef PS_METADATA_ITEM_PARSE_H
+#define PS_METADATA_ITEM_PARSE_H
+
+/// @addtogroup DataContainer Data Containers
+/// @{
+
+#include "psType.h"
+#include "psMetadata.h"
+
+// Parse a psMetadataItem as a particular type
+bool psMetadataItemParseBool(const psMetadataItem *item);
+psF32 psMetadataItemParseF32(const psMetadataItem *item);
+psF64 psMetadataItemParseF64(const psMetadataItem *item);
+psS8  psMetadataItemParseS8(const psMetadataItem *item);
+psS16 psMetadataItemParseS16(const psMetadataItem *item);
+psS32 psMetadataItemParseS32(const psMetadataItem *item);
+psU8  psMetadataItemParseU8(const psMetadataItem *item);
+psU16 psMetadataItemParseU16(const psMetadataItem *item);
+psU32 psMetadataItemParseU32(const psMetadataItem *item);
+psString psMetadataItemParseString(const psMetadataItem *item);
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psPixels.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psPixels.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psPixels.c	(revision 22158)
@@ -0,0 +1,361 @@
+/** @file  psPixels.c
+ *
+ *  @brief Contains psPixel related functions
+ *
+ *  @ingroup Image
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.41 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-04-17 23:43:03 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "psAbort.h"
+#include "psPixels.h"
+#include "psMemory.h"
+#include "psAssert.h"
+#include "psError.h"
+
+#define PIXELS_DEFAULT_ADD 10           // Default number to add, if not specified
+
+typedef int(*qsortCompareFunc)(const void *, const void *);
+
+static void pixelsFree(psPixels* pixels)
+{
+    psAssert(pixels, "impossible");
+    psFree(pixels->data);
+}
+
+// for use by qsort, etc.
+static int comparePixelCoord(psPixelCoord* coord1,
+                             psPixelCoord* coord2)
+{
+    // check row first
+    if (coord1->y < coord2->y) {
+        return -1;
+    }
+
+    if (coord1->y > coord2->y) {
+        return 1;
+    }
+
+    // rows are the same, so check column
+    if (coord1->x < coord2->x) {
+        return -1;
+    }
+
+    if (coord1->x > coord2->x) {
+        return 1;
+    }
+
+    return 0;
+}
+
+
+static psPixels *pixelsAlloc(const char *file,
+                          unsigned int lineno,
+                          const char *func,
+                          long nalloc)
+{
+    psPixels* out = p_psAlloc(file, lineno, func, sizeof(psPixels));
+    psMemSetDeallocator(out, (psFreeFunc)pixelsFree);
+
+    out->data = p_psAlloc(file, lineno, func, sizeof(psPixelCoord)*nalloc);
+    P_PSPIXELS_SET_NALLOC(out,nalloc);
+
+    return out;
+}
+
+psPixels* p_psPixelsAlloc(const char *file,
+                          unsigned int lineno,
+                          const char *func,
+                          long nalloc)
+{
+    psPixels *out = pixelsAlloc(file, lineno, func, nalloc);
+    out->n = nalloc;
+    return out;
+}
+
+psPixels* p_psPixelsAllocEmpty(const char *file,
+                             unsigned int lineno,
+                             const char *func,
+                             long nalloc)
+{
+    psPixels *out = pixelsAlloc(file, lineno, func, nalloc);
+    out->n = 0;
+    return out;
+}
+
+
+bool psMemCheckPixels(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)pixelsFree );
+}
+
+
+psPixels* p_psPixelsRealloc(const char *file,
+                            unsigned int lineno,
+                            const char *func,
+                            psPixels* pixels,
+                            long nalloc)
+{
+    if (!pixels) {
+        return p_psPixelsAlloc(file, lineno, func, nalloc);
+    }
+    if (nalloc < 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Can't reallocate a psPixels to negative size.");
+        return pixels;
+    }
+
+    if (pixels->n == nalloc) {
+        return pixels;
+    }
+    if (nalloc < pixels->n) {
+        pixels->n = nalloc;
+    }
+    pixels->data = p_psRealloc(file, lineno, func, pixels->data, sizeof(psPixelCoord)*nalloc);
+    P_PSPIXELS_SET_NALLOC(pixels,nalloc);
+
+    return pixels;
+}
+
+psPixels* psPixelsAdd(psPixels* pixels,
+                      long growth,
+                      float x,
+                      float y)
+{
+    if (growth <= 0) {
+        growth = PIXELS_DEFAULT_ADD;
+    }
+
+    if (!pixels) {
+        pixels = psPixelsAllocEmpty(growth);
+    } else if (pixels->n >= pixels->nalloc) {
+        pixels = psPixelsRealloc(pixels, pixels->nalloc + growth);
+    }
+
+    long n = pixels->n;
+
+    pixels->data[n].x = x;
+    pixels->data[n].y = y;
+
+    pixels->n++;
+
+    return pixels;
+}
+
+psPixels* p_psPixelsCopy(const char *file,
+                         unsigned int lineno,
+                         const char *func,
+                         psPixels* out,
+                         const psPixels* pixels)
+{
+    PS_ASSERT_PIXELS_NON_NULL(pixels, NULL);
+
+    out = p_psPixelsRealloc(file, lineno, func, out, pixels->n);
+    memcpy(out->data,pixels->data, pixels->n*sizeof(psPixelCoord));
+    out->n = pixels->n;
+
+    return out;
+}
+
+psImage *psPixelsToMask(psImage *out,
+                        const psPixels *pixels,
+                        psRegion region,
+                        psMaskType maskVal)
+{
+    PS_ASSERT_PIXELS_NON_NULL(pixels, NULL);
+
+    float x0 = region.x0;
+    float x1 = region.x1;
+    float y0 = region.y0;
+    float y1 = region.y1;
+
+    if (x0 < 0 || x1 < 0 || y0 < 0 || y1 < 0 || x1 < x0 || y1 < y0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Specified psRegion, [%d:%d,%d:%d], does not specify a valid region."),
+                (int)x0,(int)x1,(int)y0,(int)y1);
+        psFree(out);
+        return NULL;
+    }
+
+    int numRows = y1 - y0 + 1, numCols = x1 - x0 + 1; // Size of image
+
+    out = psImageRecycle(out, numCols, numRows, PS_TYPE_MASK);
+    if (!out) {
+        psError(PS_ERR_UNKNOWN, false, _("Failed to create image of size %dx%d."), numCols, numRows);
+        return NULL;
+    }
+//    P_PSIMAGE_SET_COL0(out, (int)x0);
+//    P_PSIMAGE_SET_ROW0(out, (int)y0);
+    psImageInit(out, 0);
+
+
+    // cycle through the vector of pixels and insert pixels into image
+    long length = pixels->n;            // Length of pixel array
+    psMaskType** outData = out->data.PS_TYPE_MASK_DATA;
+    for (int p = 0; p < length; p++) {
+        float x = pixels->data[p].x;
+        float y = pixels->data[p].y;
+        // pixel in region?
+        if (x >= x0 && x <= x1 && y >= y0 && y <= y1) {
+            outData[(int)(y-y0)][(int)(x-x0)] |= maskVal;
+        }
+    }
+
+    return out;
+}
+
+psPixels* psPixelsFromMask(psPixels* out,
+                           const psImage* mask,
+                           psMaskType maskVal)
+{
+    PS_ASSERT_IMAGE_NON_NULL(mask, NULL);
+    PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, NULL);
+
+    int numRows = mask->numRows, numCols = mask->numCols; // Size of image
+
+    // assumption: number of masked pixels is relatively small compared to total pixels, so it is best to just
+    // start with a guess and resize if necessary
+    long minPixels = PS_MAX(numRows * numCols / 100, 32); // initial guess: 1% of pixels masked;
+    if (!out || !out->data || out->nalloc < minPixels) {
+        out = psPixelsRealloc(out, minPixels);
+    }
+    out->n = 0;
+
+    // find the mask pixels in the image
+    for (int y = 0; y < numRows; y++) {
+        for (int x = 0; x < numCols; x++) {
+            if (mask->data.PS_TYPE_MASK_DATA[y][x] & maskVal) {
+                psPixelsAdd(out, out->nalloc, x, y);
+            }
+        }
+    }
+
+    return out;
+}
+
+psPixels* psPixelsConcatenate(psPixels *out, const psPixels *pixels)
+{
+    PS_ASSERT_PIXELS_NON_NULL(pixels, NULL);
+    if (!out) {
+        return psPixelsCopy(NULL, pixels);
+    }
+
+    // sort the OUT array to help in searching for duplicates later
+    qsort(out->data, out->n, sizeof(psPixelCoord), (qsortCompareFunc)comparePixelCoord);
+
+    // add non-duplicate values in pixels to the end of the output list (unsorted!)
+    long numInPix = pixels->n;          // Number of input pixels
+    long numOutPix = out->n;            // (Original) number of output pixels
+    for (long i = 0; i < numInPix; i++) {
+        psPixelCoord pix = pixels->data[i]; // Coordinate of interest
+        if (!bsearch(&pix, out->data, numOutPix, sizeof(psPixelCoord), (qsortCompareFunc)comparePixelCoord)) {
+            psPixelsAdd(out, 0, pix.x, pix.y);
+        }
+    }
+
+    return out;
+}
+
+bool p_psPixelsPrint(FILE *fd,
+                     psPixels* pixels,
+                     const char *name)
+{
+    PS_ASSERT_PIXELS_NON_NULL(pixels, false);
+
+    if (fd == NULL) {
+        fd = stdout;
+    } else {
+        if ( fprintf(fd, "\n") < 0 ) {
+            psError(PS_ERR_IO, true,
+                    "Invalid file pointer in p_psPixelsPrint.  Could not write to fd.\n");
+            return false;
+        }
+    }
+
+    if (name != NULL) {
+        fprintf (fd, "psPixels: %s\n", name);
+    }
+
+    long n = pixels->n;
+    psPixelCoord* data = pixels->data;
+
+    if (data == NULL || n == 0) {
+        fprintf(fd,"EMPTY\n\n");
+        return true;
+    }
+
+    for (long i = 0; i < n; i++) {
+        fprintf (fd, "(%f,%f)\n", data[i].x, data[i].y);
+    }
+    fprintf (fd, "\n");
+    return (true);
+}
+
+bool psPixelsSet(psPixels *pixels,
+                 long position,
+                 psPixelCoord value)
+{
+    PS_ASSERT_PIXELS_NON_NULL(pixels, false);
+
+    if (position < 0) {
+        position += pixels->n;
+    }
+    if (position < 0 || position >= pixels->n) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Invalid position: %ld\n", position);
+        return false;
+    }
+    pixels->data[position].x = value.x;
+    pixels->data[position].y = value.y;
+
+    return true;
+}
+
+psPixelCoord psPixelsGet(const psPixels *pixels,
+                         long position)
+{
+    psPixelCoord out;
+    if (pixels == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true, _("Input psPixels can not be NULL."));
+        out.x = NAN;
+        out.y = NAN;
+        return out;
+    }
+    if (position < 0) {
+        position += pixels->n;
+    }
+    if (position >= pixels->n) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Invalid position.  Number too large\n");
+        out.x = NAN;
+        out.y = NAN;
+        return out;
+    }
+    if (position < 0) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Invalid position.  Negative number too large\n");
+        out.x = NAN;
+        out.y = NAN;
+        return out;
+    }
+    out.x = pixels->data[position].x;
+    out.y = pixels->data[position].y;
+    return out;
+}
+
+long psPixelsLength(const psPixels *pixels)
+{
+    PS_ASSERT_PIXELS_NON_NULL(pixels, -1);
+    return pixels->n;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psPixels.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psPixels.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psPixels.h	(revision 22158)
@@ -0,0 +1,273 @@
+/** @file  psPixels.h
+ *
+ *  @brief Contains psPixel related functions
+ *
+ *  @author Paul Price, IfA
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.28 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-08-09 01:40:08 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_PIXELS_H
+#define PS_PIXELS_H
+
+#include "psImage.h"
+#include "psVector.h"
+#include "psRegion.h"
+
+/// @addtogroup DataContainer Data Containers
+/// @{
+
+/** Data structure for storing psPixel coordinates  */
+typedef struct
+{
+    float x;                             ///< x coordinate
+    float y;                             ///< y coordinate
+}
+psPixelCoord;
+
+/** list of pixel coordinates
+ *
+ *  Usually an image mask is the best way to carry information about what
+ *  pixels mean what. However, in the case where the number of pixels in which
+ *  we are interested is limited, it is more efficient to simply carry a list
+ *  of pixels. An example of this is in the image combination code, where we
+ *  want to perform an operation on a relatively small fraction of pixels, and
+ *  it is inefficient to go through an entire mask image checking each pixel.
+ *
+ */
+typedef struct
+{
+    long n;                            ///< Number in use
+    const long nalloc;                 ///< Number allocated
+    psPixelCoord* data;                ///< The pixel coordinates
+    void *lock;                        ///< Option lock for thread safety
+}
+psPixels;
+
+#define PS_ASSERT_PIXELS_NON_NULL(NAME, RVAL) \
+if (!(NAME) || !(NAME)->data || (NAME)->n < 0 || (NAME)->nalloc < 0) { \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, \
+            "Error: Pixels %s or one of its components is NULL.", \
+            #NAME); \
+    return RVAL; \
+}
+
+#define P_PSPIXELS_SET_NALLOC(pix,n) *(long*)&pix->nalloc = n
+
+
+/** Allocates a new psPixels structure
+ *
+ *  @return psPixels*   new psPixels
+ */
+#ifdef DOXYGEN
+psPixels* psPixelsAlloc(
+    long nalloc                         ///< the size of the coordinate vectors
+);
+#else // ifdef DOXYGEN
+psPixels* p_psPixelsAlloc(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    long nalloc                         ///< the size of the coordinate vectors
+) PS_ATTR_MALLOC;
+#define psPixelsAlloc(nalloc) \
+      p_psPixelsAlloc(__FILE__, __LINE__, __func__, nalloc)
+#endif // ifdef DOXYGEN
+
+/** Allocates a new empty psPixels structure
+ *
+ *  @return psPixels*   new psPixels
+ */
+#ifdef DOXYGEN
+psPixels* psPixelsAllocEmpty(
+    long nalloc                         ///< the size of the coordinate vectors
+);
+#else // ifdef DOXYGEN
+psPixels* p_psPixelsAllocEmpty(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    long nalloc                         ///< the size of the coordinate vectors
+);
+#define psPixelsAllocEmpty(nalloc) \
+      p_psPixelsAllocEmpty(__FILE__, __LINE__, __func__, nalloc)
+#endif // ifdef DOXYGEN
+
+
+/** Checks the type of a particular pointer.
+ *
+ *  Uses the appropriate deallocation function in psMemBlock to check the ptr
+ *  datatype.
+ *
+ *  @return bool:       True if the pointer matches a psPixels structure, false otherwise.
+ */
+bool psMemCheckPixels(
+    psPtr ptr                          ///< the pointer whose type to check
+);
+
+
+/** resizes a psPixels structure
+ *
+ *  @return psPixels*   resized psPixels
+ */
+#ifdef DOXYGEN
+psPixels* psPixelsRealloc(
+    psPixels* pixels,                  ///< psPixels to resize, or NULL to create new psPixels
+    long nalloc                        ///< the size of the coordinate vectors
+);
+#else // ifdef DOXYGEN
+psPixels* p_psPixelsRealloc(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psPixels* pixels,                  ///< psPixels to resize, or NULL to create new psPixels
+    long nalloc                        ///< the size of the coordinate vectors
+);
+#define psPixelsRealloc(pixels, nalloc) \
+      p_psPixelsRealloc(__FILE__, __LINE__, __func__, pixels, nalloc)
+#endif // ifdef DOXYGEN
+
+
+/** Add a pixel location to a psPixels
+ *
+ *  Grow the psPixels input by growth.  If growth is less that 1, 10 is used.  If a NULL
+ *  psPixels is given, a new one is created.
+ *
+ *  @return psPixels*       psPixels with the value appended.
+ */
+psPixels* psPixelsAdd(
+    psPixels* pixels,                  ///< psPixels to append new coordinate to.
+    long growth,                       ///< Number of elements to grow the pixels list if necessary.
+    float x,                           ///< x coordinate to append
+    float y                            ///< y coordinate to append
+);
+
+
+/** Copies a psPixels object
+ *
+ *  Makes a deep copy of the data in a psPixels object.  Any data in the OUT
+ *  parameter will be destroyed and OUT will be resized, if necessary.
+ *
+ *  @return psPixels*   a new psPixels that is a duplicate to IN
+ */
+#ifdef DOXYGEN
+psPixels* psPixelsCopy(
+    psPixels* out,                     ///< psPixels struct to recycle, or NULL
+    const psPixels* pixels             ///< psPixels struct to copy
+);
+#else // ifdef DOXYGEN
+psPixels* p_psPixelsCopy(
+    const char *file,                   ///< File of caller
+    unsigned int lineno,                ///< Line number of caller
+    const char *func,                   ///< Function name of caller
+    psPixels* out,                     ///< psPixels struct to recycle, or NULL
+    const psPixels* pixels             ///< psPixels struct to copy
+);
+#define psPixelsCopy(out, pixels) \
+      p_psPixelsCopy(__FILE__, __LINE__, __func__, out, pixels)
+#endif // ifdef DOXYGEN
+
+
+/** Generate a psImage from a psPixels
+ *
+ *  psPixelsToMask shall return an image of type U8 with the pixels lying
+ *  within the specified region set to the maskVal. The out image shall be
+ *  modified if supplied, or allocated and returned if NULL. The size of the
+ *  output image shall be region->x1 - region->x0 by region->y1 - region->y0,
+ *  with out->x0 = region->x0 and out->y0 = region->y0. In the event that
+ *  either of pixels or region are NULL, the function shall generate an
+ *  error and return NULL.
+ *
+ *  @return psImage*    generated mask image
+ */
+psImage* psPixelsToMask(
+    psImage* out,                      ///< psImage to recycle, or NULL
+    const psPixels* pixels,            ///< list of pixels to use
+    psRegion region,                   ///< region to define the output mask image
+    psMaskType maskVal                 ///< the mask bit-values to act upon
+);
+
+
+/** Generate a psPixels from a mask psImage
+ *
+ *  psMaskToPixels shall return a psPixels consisting of the coordinates in
+ *  the mask that match the maskVal. The out pixel list shall be modified if
+ *  supplied, or allocated and returned if NULL. In hte event that mask is
+ *  NULL, the function shall generate an error and return NULL.
+ *
+ *  @return psPixels*   generated psPixels pixel list
+ */
+psPixels* psPixelsFromMask(
+    psPixels *out,                     ///< psPixels to recycle, or NULL
+    const psImage *mask,               ///< the input mask psImage
+    psMaskType maskVal                 ///< the mask bit-values to act upon
+);
+
+
+/** Concatenates two psPixels
+ *
+ *  psPixelsConcatenate shall concatenate pixels onto out. In the event that
+ *  out is NULL, a new psPixels shall be allocated, and the contents of
+ *  pixels simply copied in. If pixels is NULL, the function shall generate
+ *  an error and return NULL. The function shall take care to ensure that
+ *  there are no duplicate pixels in out.
+ *
+ *  @return psPixels         Concatenated psPixel list
+ */
+psPixels* psPixelsConcatenate(
+    psPixels *out,                     ///< psPixels to recycle, or NULL
+    const psPixels *pixels             ///< psPixels to append to OUT
+);
+
+
+/** Prints a psPixels to specified destination.
+ *
+ *  @return bool:    True if successful.
+*/
+bool p_psPixelsPrint(
+    FILE *fd,                          ///< destination file descriptor
+    psPixels* pixels,                  ///< psPixels to print
+    const char *name                   ///< printf-style format of header line
+);
+
+
+/** Sets the value of the the pixels array at the specified position to value.
+ *
+ *  A negative position means index from the end.
+ *
+ *  @return bool:       True if Successful, otherwise false.
+*/
+bool psPixelsSet(
+    psPixels *pixels,                  ///< pixels to set
+    long position,                     ///< position to set
+    psPixelCoord value                 ///< pixels value to be set
+);
+
+
+/** Returns the value of the pixels array at the specified position.
+ *
+ *  A negative position means index from the end.
+ *
+ *  @return psPixelCoord:       The value of the pixels at the specified position.
+*/
+psPixelCoord psPixelsGet(
+    const psPixels *pixels,            ///< input pixels from which to get
+    long position                      ///< position to get
+);
+
+
+/** Get the number of elements in use from a specified psPixels. (pixels.n)
+ *
+ *  @return long:       The number of elements in use.
+ */
+long psPixelsLength(
+    const psPixels *pixels             ///< input psPixels
+);
+
+
+/// @}
+#endif // #ifndef PS_PIXELS_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psTree.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psTree.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psTree.c	(revision 22158)
@@ -0,0 +1,708 @@
+#include <stdio.h>
+#include <string.h>
+
+#include "psAssert.h"
+#include "psAbort.h"
+#include "psMemory.h"
+#include "psType.h"
+#include "psArray.h"
+#include "psVector.h"
+#include "psImage.h"
+#include "psList.h"
+#include "psSort.h"
+
+#include "psTree.h"
+
+
+// XXX Upgrades:
+// * Could allow different types of coordinates (saving memory)
+// * Could make tree "growable" by including a pointer to a new tree within each node.
+// * Rebalancing the tree ("pruning"?) is done by collecting all the points and re-planting a new tree.
+
+static void treeCoordArrayFree(psTreeCoordArray *array)
+{
+    psFree(array->F64);
+    psFree(array->raw);
+}
+
+static void treeNodeFree(psTreeNode *node)
+{
+    // All contents are views only
+    return;
+}
+
+static void treeFree(psTree *tree)
+{
+    for (long i = 0; i < tree->numNodes; i++) {
+        psFree(tree->nodes[i]);
+    }
+    psFree(tree->nodes);
+    psFree(tree->min);
+    psFree(tree->max);
+    psFree(tree->division);
+    // 'root' is a view only
+    psFree(tree->data);
+    psFree(tree->contents);
+}
+
+psTreeCoordArray *psTreeCoordArrayAlloc(long size, int dim)
+{
+    psAssert(size > 0, "Size (%ld) must be positive", size);
+    psAssert(dim > 0, "Dimension (%d) must be positive", dim);
+
+    psTreeCoordArray *array = psAlloc(sizeof(psTreeCoordArray)); // Array to return
+    psMemSetDeallocator(array, (psFreeFunc)treeCoordArrayFree);
+
+    array->raw = psAlloc(dim * size * sizeof(psF64));
+    array->F64 = psAlloc(size * sizeof(psF64*));
+
+    psF64 *ptr = (psF64*)array->raw;    // Pointer into raw vector
+    for (long i = 0; i < size; i++, ptr += dim) {
+        array->F64[i] = ptr;
+    }
+
+    return array;
+}
+
+psTreeNode *psTreeNodeAlloc(long index)
+{
+    psAssert(index >= 0, "Index (%ld) must be non-negative", index);
+
+    psTreeNode *node = psAlloc(sizeof(psTreeNode)); // Node to return
+    psMemSetDeallocator(node, (psFreeFunc)treeNodeFree);
+
+    node->index = index;
+    node->divideDim = -1;
+    node->num = 0;
+    node->contents = NULL;
+    node->tree = NULL;
+    node->up = NULL;
+    node->left = NULL;
+    node->right = NULL;
+
+    return node;
+}
+
+psTree *psTreeAlloc(int dim, int maxLeafContents, long numNodes)
+{
+    psAssert(dim > 0, "Dimensionality (%d) must be positive", dim);
+    psAssert(maxLeafContents > 0, "Maximum number per leaf (%d) must be positive", maxLeafContents);
+    psAssert(numNodes > 0, "Number of nodes (%ld) must be positive", numNodes);
+
+    psTree *tree = psAlloc(sizeof(psTree)); // Tree to return
+    psMemSetDeallocator(tree, (psFreeFunc)treeFree);
+
+    tree->dim = dim;
+    tree->maxLeafContents = maxLeafContents;
+
+    tree->numNodes = numNodes;
+    tree->nodes = psAlloc(numNodes * sizeof(psTreeNode*));
+    for (long i = 0; i < numNodes; i++) {
+        tree->nodes[i] = psTreeNodeAlloc(i);
+    }
+    tree->root = tree->nodes[0];
+
+    tree->min = psTreeCoordArrayAlloc(numNodes, dim);
+    tree->max = psTreeCoordArrayAlloc(numNodes, dim);
+
+    tree->division = psAlloc(numNodes * sizeof(double));
+
+    tree->numData = 0;
+    tree->data = NULL;
+
+    return tree;
+}
+
+
+psTree *psTreePlant(int dim, int maxLeafContents, ...)
+{
+    PS_ASSERT_INT_POSITIVE(dim, NULL);
+    PS_ASSERT_INT_POSITIVE(maxLeafContents, NULL);
+
+    // Parse coordinate list
+    va_list args;                       // Variable argument list
+    va_start(args, maxLeafContents);
+    psArray *coords = psArrayAlloc(dim); // Array of coordinates
+    long numData = 0;                   // Number of data points
+    for (int i = 0; i < dim; i++) {
+        psVector *data = va_arg(args, psVector*);
+        if (i == 0) {
+            numData = data->n;
+        } else if (data->n != numData) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Input vectors have differing sizes: %ld vs %ld",
+                    data->n, numData);
+            psFree(coords);
+            va_end(args);
+            return NULL;
+        }
+        coords->data[i] = psMemIncrRefCounter(data);
+    }
+    va_end(args);
+
+    long numNodes;
+    {
+        // From equation 21.2.2 in Numerical Recipes vol 3, p1102.
+        long pow2;                      // Smallest power of two >= numData
+        for (pow2 = 1; pow2 < numData; pow2 <<= 1);
+        numNodes = PS_MIN(pow2 - 1, 2 * numData - pow2 / 2 - 1);
+    }
+
+    psTree *tree = psTreeAlloc(dim, maxLeafContents, numNodes);
+    tree->data = psTreeCoordArrayAlloc(numData, dim);
+    tree->numData = numData;
+    psF64 **data = tree->data->F64;     // Dereference data
+
+    // Copy data into the tree
+#define PSTREE_COPY_DATA_CASE(TYPE) \
+    case PS_TYPE_##TYPE: { \
+        for (long j = 0; j < numData; j++) { \
+            data[j][i] = values->data.TYPE[j]; \
+        } \
+        break; \
+    }
+
+    for (int i = 0; i < dim; i++) {
+        psVector *values = coords->data[i]; // Vector of values for this dimension
+        switch (values->type.type) {
+            PSTREE_COPY_DATA_CASE(U8);
+            PSTREE_COPY_DATA_CASE(U16);
+            PSTREE_COPY_DATA_CASE(U32);
+            PSTREE_COPY_DATA_CASE(U64);
+            PSTREE_COPY_DATA_CASE(S8);
+            PSTREE_COPY_DATA_CASE(S16);
+            PSTREE_COPY_DATA_CASE(S32);
+            PSTREE_COPY_DATA_CASE(S64);
+            PSTREE_COPY_DATA_CASE(F32);
+            PSTREE_COPY_DATA_CASE(F64);
+          default:
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Unsupported vector type for dimension %d: %x",
+                    i, values->type.type);
+            psFree(tree);
+            psFree(coords);
+        }
+    }
+    psFree(coords);
+
+    long *contents = tree->contents = psAlloc(numData * sizeof(long)); // Contents of tree
+    for (long i = 0; i < numData; i++) {
+        contents[i] = i;
+    }
+
+    psTreeNode *root = tree->root;      // Root of the tree
+    root->tree = tree;
+    root->contents = contents;
+    root->num = numData;
+    root->divideDim = 0;
+    for (int i = 0; i < dim; i++) {
+        tree->min->F64[0][i] = -INFINITY;
+        tree->max->F64[0][i] = INFINITY;
+    }
+
+    psArray *work = psArrayAlloc(numNodes); // Work queue
+    work->data[0] = root;
+    long workNum = 1;
+
+// Compare points (in a single dimension) by their index
+#define PSTREE_SELECT_COMPARE(A,B) (data[contents[A]][divideDim] < data[contents[B]][divideDim])
+// Swap points by their index
+#define PSTREE_SELECT_SWAP(TYPE,A,B) { \
+    if (A != B) { \
+        TYPE temp = contents[A]; \
+        contents[A] = contents[B]; \
+        contents[B] = temp; \
+    } \
+}
+
+    for (long workIndex = 0, nextIndex = 0; workIndex < workNum; workIndex++) {
+        psTreeNode *node = work->data[workIndex]; // Node to be worked on
+        long num = node->num;           // Number of points in node
+        long *contents = node->contents;// Indices of points in node
+        psF64 **data = tree->data->F64; // Dereference the values
+        long middle = num / 2;          // Index of middle point
+        int divideDim = node->divideDim;// Dimension in which to divide
+        long nodeIndex = node->index;   // Index of node
+
+        PSSELECT(num, middle, PSTREE_SELECT_COMPARE, PSTREE_SELECT_SWAP, long);
+
+        psF64 *nodeMin = tree->min->F64[nodeIndex]; // Minimum bounds for current node
+        psF64 *nodeMax = tree->max->F64[nodeIndex]; // Maximum bounds for current node
+
+        // Divide to the left and right
+        double division = tree->division[nodeIndex] = data[contents[middle]][divideDim];
+
+        long leftIndex = ++nextIndex, rightIndex = ++nextIndex; // Indices for left and right nodes
+        psTreeNode *left = node->left = tree->nodes[leftIndex]; // Node to the left
+        psTreeNode *right = node->right = tree->nodes[rightIndex]; // Node to the right
+        long numLeft = middle, numRight = num - middle; // Number in each node
+
+        for (int i = 0; i < dim; i++) {
+            tree->min->F64[leftIndex][i] = nodeMin[i];
+            tree->min->F64[rightIndex][i] = (i == divideDim ? division : nodeMin[i]);
+            tree->max->F64[leftIndex][i] = (i == divideDim ? division : nodeMax[i]);
+            tree->max->F64[rightIndex][i] = nodeMax[i];
+        }
+
+        left->num = numLeft;
+        right->num = numRight;
+
+        left->contents = contents;
+        right->contents = contents + middle;
+
+#if 0
+        // Check contents
+        for (int i = 0; i < numLeft; i++) {
+            long index = left->contents[i]; // Index of point
+            for (int j = 0; j < dim; j++) {
+                if (data[index][j] < tree->min->F64[leftIndex][j] ||
+                    data[index][j] > tree->max->F64[leftIndex][j]) {
+                    psWarning("Bad division");
+                }
+            }
+        }
+        for (int i = 0; i < numRight; i++) {
+            long index = right->contents[i]; // Index of point
+            for (int j = 0; j < dim; j++) {
+                if (data[index][j] < tree->min->F64[rightIndex][j] ||
+                    data[index][j] > tree->max->F64[rightIndex][j]) {
+                    psWarning("Bad division");
+                }
+            }
+        }
+#endif
+
+        divideDim++;
+        if (divideDim == dim) {
+            divideDim = 0;
+        }
+        left->divideDim = right->divideDim = divideDim;
+
+        left->up = right->up = node;
+        left->tree = right->tree = tree;
+
+        if (numLeft > maxLeafContents) {
+            work->data[workNum++] = left;
+        }
+        if (numRight > maxLeafContents) {
+            work->data[workNum++] = right;
+        }
+
+        work->data[workIndex] = NULL;
+    }
+    psFree(work);
+
+    return tree;
+}
+
+// Print a representation of the node; called recursively
+static void treeNodePrint(FILE *fptr,   // File pointer to which to print
+                          const psTreeNode *node, // Node to print
+                          int level     // Level at which to print
+    )
+{
+    long index = node->index;           // Index of node
+    psTree *tree = node->tree;          // Parent tree
+    int dim = tree->dim;                // Dimensions
+
+    for (int i = 0; i < level; i++) {
+        fprintf(fptr, " ");
+    }
+    fprintf(fptr, "%ld: (", index);
+    for (int i = 0; i < dim; i++) {
+        fprintf(fptr, "%lf", tree->min->F64[index][i]);
+        if (i < dim - 1) {
+            fprintf(fptr, ",");
+        }
+    }
+    fprintf(fptr, ") --> (");
+    for (int i = 0; i < dim; i++) {
+        fprintf(fptr, "%lf", tree->max->F64[index][i]);
+        if (i < dim - 1) {
+            fprintf(fptr, ",");
+        }
+    }
+    fprintf(fptr, ")");
+    level++;
+
+    if (node->left && node->right) {
+        fprintf(fptr, " ==> %lf\n", tree->division[index]);
+        treeNodePrint(fptr, node->left, level);
+        treeNodePrint(fptr, node->right, level);
+        return;
+    }
+    fprintf(fptr, "\n");
+    for (int i = 0; i < level; i++) {
+        fprintf(fptr, " ");
+    }
+    fprintf(fptr, "(");
+    for (int i = 0; i < node->num; i++) {
+        psF64 *coords = tree->data->F64[node->contents[i]]; // Coordinates
+        for (int j = 0; j < dim; j++) {
+            fprintf(fptr, "%lf", coords[j]);
+            if (j < dim - 1) {
+                fprintf(fptr, ",");
+            }
+        }
+        fprintf(fptr, ")");
+        if (i < node->num - 1) {
+            fprintf(fptr, " (");
+        }
+    }
+    fprintf(fptr, "\n");
+
+    return;
+}
+
+
+void psTreePrint(FILE *fptr, const psTree *tree)
+{
+    PS_ASSERT_TREE_NON_NULL(tree, );
+
+    treeNodePrint(fptr, tree->root, 0);
+    return;
+}
+
+// Given an arbitrary point, find the appropriate leaf
+psTreeNode *psTreeLeaf(const psTree *tree, const psVector *coords)
+{
+#if 1 // Might be in a tight loop
+    PS_ASSERT_TREE_NON_NULL(tree, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(coords, NULL);
+    PS_ASSERT_VECTOR_SIZE(coords, (long)tree->dim, NULL);
+#endif
+
+#define TREE_LEAF_CASE(TYPE) \
+  case PS_TYPE_##TYPE: \
+      for (; node->left; node = (coords->data.TYPE[node->divideDim] < tree->division[node->index]) ? \
+               node->left : node->right); \
+      break;
+
+    psTreeNode *node = tree->root;      // Node of interest
+    switch (coords->type.type) {
+        TREE_LEAF_CASE(U8);
+        TREE_LEAF_CASE(U16);
+        TREE_LEAF_CASE(U32);
+        TREE_LEAF_CASE(U64);
+        TREE_LEAF_CASE(S8);
+        TREE_LEAF_CASE(S16);
+        TREE_LEAF_CASE(S32);
+        TREE_LEAF_CASE(S64);
+        TREE_LEAF_CASE(F32);
+        TREE_LEAF_CASE(F64);
+      default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Unsupported type: %x", coords->type.type);
+        return NULL;
+    }
+    return node;
+}
+
+// Returns the square of the distance between a point on the tree and an aribtary point
+static inline double treeContentDistance(const psTree *tree, // Tree of interest
+                                         long index, // Index of point on tree
+                                         const psVector *coords // Coordinates of interest
+    )
+{
+    int dim = tree->dim;                // Dimensionality
+    switch (dim) {
+      case 2:
+        return PS_SQR(coords->data.F64[0] - tree->data->F64[index][0]) +
+            PS_SQR(coords->data.F64[1] - tree->data->F64[index][1]);
+      case 3:
+        return PS_SQR(coords->data.F64[0] - tree->data->F64[index][0]) +
+            PS_SQR(coords->data.F64[1] - tree->data->F64[index][1]) +
+            PS_SQR(coords->data.F64[2] - tree->data->F64[index][2]);
+      default: {
+          double distance2 = 0.0;             // Distance of interest
+          for (int i = 0; i < dim; i++) {
+              distance2 += PS_SQR(coords->data.F64[i] - tree->data->F64[index][i]);
+          }
+          return distance2;
+      }
+    }
+    return NAN;
+}
+
+// Returns the square of the distance between a leaf and an arbitrary point
+static inline double treeBranchDistance(const psTree *tree, long index, const psVector *coords)
+{
+    int dim = tree->dim;                // Dimensionality
+    double distance = 0.0;              // Distance to box
+    for (int i = 0; i < dim; i++) {
+        double minDiff = tree->min->F64[index][i] - coords->data.F64[i];
+        if (minDiff > 0) {
+            distance += PS_SQR(minDiff);
+            continue;
+        }
+        double maxDiff = coords->data.F64[i] - tree->max->F64[index][i];
+        if (maxDiff > 0) {
+            distance += PS_SQR(maxDiff);
+            continue;
+        }
+    }
+    return distance;
+}
+
+// Returns whether the designated leaf contains an arbitrary point
+static inline bool treeBranchInside(const psTree *tree, // Tree of interest
+                                    long index, // Index of leaf on tree
+                                    const psVector *coords // Coordinates of interest
+    )
+{
+    int dim = tree->dim;                // Dimensionality
+    for (int i = 0; i < dim; i++) {
+        if (tree->min->F64[index][i] > coords->data.F64[i]) {
+            return false;
+        }
+        if (tree->max->F64[index][i] < coords->data.F64[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+// Search a leaf node for a closer point
+static inline void treeLeafSearchNearest(long *bestIndex, // Index of closest point
+                                         double *bestDistance, // Distance to closest point
+                                         const psTree *tree, // Tree of interest
+                                         const psTreeNode *leaf, // Leaf to search
+                                         const psVector *coords // Coordinates of interest
+    )
+{
+    for (int i = 0; i < leaf->num; i++) {
+        long index = leaf->contents[i]; // Index of point
+        double distance = treeContentDistance(tree, index, coords); // Distance to point
+        if (distance < *bestDistance) {
+            *bestIndex = index;
+            *bestDistance = distance;
+        }
+    }
+    return;
+}
+
+// Return the index of the nearest neighbour to given coordinates, within some radius
+// This is the engine for psTreeNearest() and psTreeNearestWithin()
+static inline long treeNearestWithin(const psTree *tree, // Tree
+                                     const psVector *coordinates, // Coordinates of interest
+                                     double bestDistance // Distance (radius-squared) to best point
+    )
+{
+#if 1 // Might be in a tight loop
+    PS_ASSERT_TREE_NON_NULL(tree, -1);
+    PS_ASSERT_VECTOR_NON_NULL(coordinates, -1);
+    PS_ASSERT_VECTOR_SIZE(coordinates, (long)tree->dim, -1);
+#endif
+
+    psVector *coords = (coordinates->type.type == PS_TYPE_F64 ? psMemIncrRefCounter((psVector*)coordinates) :
+                        psVectorCopy(NULL, coordinates, PS_TYPE_F64)); // F64 version of coordinates
+
+    // Find the closest point in the leaf that contains the point of interest
+    psTreeNode *leaf = psTreeLeaf(tree, coords); // Leaf containing the point of interest
+    long bestIndex = -1;                // Index of best point
+    treeLeafSearchNearest(&bestIndex, &bestDistance, tree, leaf, coords);
+
+    // Work up from the leaf containing the point of interest, and for each in turn, search down the other
+    // branch.  Every time we search down a branch, we first check to see if the current best distance rules
+    // out that branch.  By having the check within the work queue loop, we allow the best distance to evolve
+    // (smaller), which means our elimination test goes up against the smallest possible distance.
+    psArray *work = psArrayAlloc(tree->numNodes); // Work queue
+    while (leaf->up) {
+        psTreeNode *up = leaf->up;      // Parent node
+
+        long workIndex = 0;
+        work->data[workIndex] = (leaf == up->left ? up->right : up->left); // The other node
+        while (workIndex >= 0) {
+            psTreeNode *node = work->data[workIndex];
+            if (treeBranchDistance(tree, node->index, coords) > bestDistance) {
+                // No need to investigate
+                work->data[workIndex] = NULL;
+                workIndex--;
+                continue;
+            }
+            if (node->left) {
+                // Branch node
+                work->data[workIndex] = node->right;
+                work->data[++workIndex] = node->left;
+                continue;
+            }
+            // Leaf node
+            treeLeafSearchNearest(&bestIndex, &bestDistance, tree, node, coords);
+            work->data[workIndex] = NULL;
+            workIndex--;
+        }
+
+        leaf = up;
+    }
+    psFree(work);
+    psFree(coords);
+
+    return bestIndex;
+}
+
+// Given an arbitrary point, return the index of the nearest neighbour
+long psTreeNearest(const psTree *tree, const psVector *coords)
+{
+    return treeNearestWithin(tree, coords, INFINITY);
+}
+
+
+long psTreeNearestWithin(const psTree *tree, const psVector *coords, double radius)
+{
+    return treeNearestWithin(tree, coords, PS_SQR(radius));
+}
+
+
+// Search a leaf node for points within radius squared
+static inline long treeLeafSearchWithin(double radius2, // Radius squared to search
+                                        const psTree *tree, // Tree of interest
+                                        const psTreeNode *leaf, // Leaf to search
+                                        const psVector *coords // Coordinates of interest
+    )
+{
+    long num = 0;                       // Number within circle
+    for (int i = 0; i < leaf->num; i++) {
+        long index = leaf->contents[i]; // Index of point
+        double distance = treeContentDistance(tree, index, coords); // Distance to point
+        if (distance < radius2) {
+            num++;
+        }
+    }
+    return num;
+}
+
+// Given an arbitrary point and a matching radius, return the number of points within that radius
+long psTreeWithin(const psTree *tree, const psVector *coordinates, double radius)
+{
+#if 1 // Might be in a tight loop
+    PS_ASSERT_TREE_NON_NULL(tree, -1);
+    PS_ASSERT_VECTOR_NON_NULL(coordinates, -1);
+    PS_ASSERT_VECTOR_SIZE(coordinates, (long)tree->dim, -1);
+#endif
+
+    psVector *coords = (coordinates->type.type == PS_TYPE_F64 ? psMemIncrRefCounter((psVector*)coordinates) :
+                        psVectorCopy(NULL, coordinates, PS_TYPE_F64)); // F64 version of coordinates
+
+    radius *= radius;                   // We work with the radius-squared
+    long num = 0;                       // Number of points in circle
+
+    // This is essentially the same as psTreeNearest, except we're not allowed to prune
+
+    // Find the closest point in the leaf that contains the point of interest
+    psTreeNode *leaf = psTreeLeaf(tree, coords); // Leaf containing the point of interest
+    num += treeLeafSearchWithin(radius, tree, leaf, coords);
+
+    psArray *work = psArrayAlloc(tree->numNodes); // Work queue
+    while (leaf->up) {
+        psTreeNode *up = leaf->up;      // Parent node
+
+        long workIndex = 0;
+        work->data[workIndex] = (leaf == up->left ? up->right : up->left); // The other node
+        while (workIndex >= 0) {
+            psTreeNode *node = work->data[workIndex];
+            if (node->left) {
+                // Branch node
+                work->data[workIndex] = node->right;
+                work->data[++workIndex] = node->left;
+                continue;
+            }
+            // Leaf node
+            num += treeLeafSearchWithin(radius, tree, node, coords);
+            work->data[workIndex] = NULL;
+            workIndex--;
+        }
+
+        leaf = up;
+    }
+    psFree(work);
+    psFree(coords);
+
+    return num;
+}
+
+// Search a leaf node for any points within radius squared
+static inline bool treeLeafSearchWithinAny(double radius2, // Radius squared to search
+                                           const psTree *tree, // Tree of interest
+                                           const psTreeNode *leaf, // Leaf to search
+                                           const psVector *coords // Coordinates of interest
+    )
+{
+    for (int i = 0; i < leaf->num; i++) {
+        long index = leaf->contents[i]; // Index of point
+        double distance = treeContentDistance(tree, index, coords); // Distance to point
+        if (distance < radius2) {
+            return true;
+        }
+    }
+    return false;
+}
+
+// Given an arbitrary point and a matching radius, return whether there are any points within that radius
+bool psTreeWithinAny(const psTree *tree, const psVector *coordinates, double radius)
+{
+#if 1 // Might be in a tight loop
+    PS_ASSERT_TREE_NON_NULL(tree, false);
+    PS_ASSERT_VECTOR_NON_NULL(coordinates, false);
+    PS_ASSERT_VECTOR_SIZE(coordinates, (long)tree->dim, false);
+#endif
+
+    psVector *coords = (coordinates->type.type == PS_TYPE_F64 ? psMemIncrRefCounter((psVector*)coordinates) :
+                        psVectorCopy(NULL, coordinates, PS_TYPE_F64)); // F64 version of coordinates
+
+    radius *= radius;                   // We work with the radius-squared
+
+    // This is essentially the same as psTreeWithin, except we can bail as soon as we find something
+
+    // Find the closest point in the leaf that contains the point of interest
+    psTreeNode *leaf = psTreeLeaf(tree, coords); // Leaf containing the point of interest
+    if (treeLeafSearchWithinAny(radius, tree, leaf, coords)) {
+        psFree(coords);
+        return true;
+    }
+
+    psArray *work = psArrayAlloc(tree->numNodes); // Work queue
+    while (leaf->up) {
+        psTreeNode *up = leaf->up;      // Parent node
+
+        long workIndex = 0;
+        work->data[workIndex] = (leaf == up->left ? up->right : up->left); // The other node
+        while (workIndex >= 0) {
+            psTreeNode *node = work->data[workIndex];
+            if (node->left) {
+                // Branch node
+                work->data[workIndex] = node->right;
+                work->data[++workIndex] = node->left;
+                continue;
+            }
+            // Leaf node
+            if (treeLeafSearchWithinAny(radius, tree, node, coords)) {
+                // Clear out the work queue
+                memset(work->data, 0, (workIndex + 1) * sizeof(void));
+                psFree(work);
+                psFree(coords);
+                return true;
+            }
+            work->data[workIndex] = NULL;
+            workIndex--;
+        }
+
+        leaf = up;
+    }
+    psFree(work);
+    psFree(coords);
+
+    return false;
+}
+
+
+psVector *psTreeCoords(psVector *out, const psTree *tree, long index)
+{
+#if 1 // Might be in a tight loop
+    PS_ASSERT_TREE_NON_NULL(tree, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(index, NULL);
+    PS_ASSERT_INT_LESS_THAN_OR_EQUAL(index, tree->numData, NULL);
+#endif
+
+    int dim = tree->dim;                // Dimensions
+
+    out = psVectorRecycle(out, dim, PS_TYPE_F64);
+    memcpy(out->data.F64, tree->data->F64[index], dim * PSELEMTYPE_SIZEOF(PS_TYPE_F64));
+    return out;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/psTree.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/psTree.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/psTree.h	(revision 22158)
@@ -0,0 +1,120 @@
+#ifndef PS_TREE_H
+#define PS_TREE_H
+
+#include <psError.h>
+
+/// An array of coordinates for the tree
+///
+/// The coordinate for point i, dimension j is psTreeCoordArray->F64[i][j].  We have a "raw" vector which
+/// points into the operational vector, as is done for psImage.  This keeps all the memory together, reducing
+/// fragmentation.  Currently supports only F64 type, but could be expanded to support multiple types (to save
+/// memory) by changing the F64 member into a union.
+typedef struct {
+    psF64 **F64;                        ///< Coordinates
+    psU8 *raw;                          // Raw vector
+} psTreeCoordArray;
+
+/// A simple kd-tree implementation
+///
+/// This parent tree structure contains all the main information for the tree.  We choose this instead of
+/// including everything within the nodes to avoid memory fragmentation.
+typedef struct {
+    int dim;                            ///< Dimensionality
+    int maxLeafContents;                ///< Maximum number of points on a leaf
+    long numNodes;                      ///< Number of nodes
+    long numData;                       ///< Number of data points
+    struct psTreeNode **nodes;          ///< Array of nodes
+    psTreeCoordArray *min, *max;        ///< Bounding box: minimum and maximum coordinates
+    double *division;                   ///< Division for each node
+    struct psTreeNode *root;            ///< Convenience pointer to root node of tree
+    psTreeCoordArray *data;             ///< Data: coordinates
+    long *contents;                     ///< Indices into the data
+} psTree;
+
+/// A node of the kd-tree
+///
+/// Most of the information is stored in the parent tree (to reduce memory fragmentation).  All the pointers
+/// are views only; the pointers to the nodes are contained within the parent tree's "nodes" element.
+typedef struct psTreeNode {
+    long index;                         ///< Index of node
+    int divideDim;                      ///< Dimension in which to divide
+    int num;                            ///< Number of points in node
+    long *contents;                     ///< Contents of node; view only
+    psTree *tree;                       ///< Parent tree; view only
+    struct psTreeNode *up;              ///< Node higher up; view only
+    struct psTreeNode *left, *right;    ///< Nodes below, to the left and right; views only
+} psTreeNode;
+
+/// Assertion for psTree
+#define PS_ASSERT_TREE_NON_NULL(TREE, RETVAL) \
+if (!(TREE) || !(TREE)->nodes || !(TREE)->min || !(TREE)->max || !(TREE)->division || !(TREE)->root || \
+    !(TREE)->data || !(TREE)->contents) { \
+    psError(PS_ERR_UNEXPECTED_NULL, true, "Tree %s or one of its components is NULL.", #TREE); \
+    return RETVAL; \
+}
+
+/// Allocator for psTreeCoordArray
+psTreeCoordArray *psTreeCoordArrayAlloc(long size, ///< Size of array
+                                        int dim ///< Dimensionality
+                                        );
+
+/// Allocator for psTreeNode
+psTreeNode *psTreeNodeAlloc(long index  ///< Index of node
+                            );
+
+/// Allocator for psTree
+psTree *psTreeAlloc(int dim,            ///< Dimensionality
+                    int maxLeafContents,///< Maximum number of points on a leaf
+                    long numNodes       ///< Number of nodes in tree
+                    );
+
+/// Plant (create) a tree
+///
+/// This is the main startup function.
+psTree *psTreePlant(int dim,            ///< Dimensionality
+                    int maxLeafContents,///< Maximum number of points on a leaf
+                    ...                 ///< psVector for each coordinate
+                    );
+
+/// Return the leaf node containing given coordinates
+///
+/// Returns a view to the pointer.
+psTreeNode *psTreeLeaf(const psTree *tree, ///< Tree
+                       const psVector *coords ///< Coordinates of interest
+                       );
+
+/// Return the index of the nearest neighbour to given coordinates
+long psTreeNearest(const psTree *tree,  ///< Tree
+                   const psVector *coords ///< Coordinates of interest
+                   );
+
+/// Return the index of the nearest neighbour to given coordinates, but within some radius
+long psTreeNearestWithin(const psTree *tree,  ///< Tree
+                         const psVector *coords, ///< Coordinates of interest
+                         double radius  ///< Radius of interest
+                         );
+
+/// Return the number of points within some radius of given coordinates
+long psTreeWithin(const psTree *tree,   ///< Tree
+                  const psVector *coords, ///< Coordinates of interest
+                  double radius         ///< Radius of interest
+                  );
+
+/// Return whether there are any points within some radius of given coordinates
+bool psTreeWithinAny(const psTree *tree,   ///< Tree
+                     const psVector *coords, ///< Coordinates of interest
+                     double radius         ///< Radius of interest
+                     );
+
+/// Return the coordinates of a point in the tree, specified by its index
+psVector *psTreeCoords(psVector *out,   ///< Output vector, or NULL
+                       const psTree *tree, ///< Tree
+                       long index       ///< Index of point in tree
+                       );
+
+/// Print a representation of the tree
+void psTreePrint(FILE *fptr,            ///< File to which to print
+                 const psTree *tree     ///< Tree
+                 );
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/types/types.i
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/types/types.i	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/types/types.i	(revision 22158)
@@ -0,0 +1,10 @@
+/* types headers */
+
+%include "psArray.h"
+%include "psBitSet.h"
+%include "psHash.h"
+%include "psList.h"
+%include "psLookupTable.h"
+%include "psMetadataConfig.h"
+%include "psMetadata.h"
+%include "psPixels.h"
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/xml/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/xml/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/xml/.cvsignore	(revision 22158)
@@ -0,0 +1,10 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
+*.loT
+*.bb
+*.bbg
+*.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/xml/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/xml/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/xml/Makefile.am	(revision 22158)
@@ -0,0 +1,14 @@
+#Makefile for xml functions of psLib
+#
+noinst_LTLIBRARIES = libpslibxml.la
+
+libpslibxml_la_CPPFLAGS = $(SRCINC) $(PSLIB_CFLAGS) $(XML_CFLAGS)
+libpslibxml_la_SOURCES = \
+	psXML.c
+
+EXTRA_DIST = xml.i
+
+pkginclude_HEADERS = \
+	psXML.h
+
+CLEANFILES = *~ *.bb *.bbg *.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/xml/psXML.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/xml/psXML.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/xml/psXML.c	(revision 22158)
@@ -0,0 +1,634 @@
+/** @file  psXML.c
+*
+*  @brief Contains basic XML definitions and operations
+*
+*  This file defines the basic type for an XML struct and functions useful
+*  in creation and usage of XML documents/files.
+*
+*  @ingroup XML
+*
+*  @author David Robbins, MHPCC
+*
+*  @version $Revision: 1.48 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2006-10-12 23:43:58 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#include "psXML.h"
+#include "psAssert.h"
+#include <unistd.h>
+#include <fcntl.h>
+
+/******************************************************************************/
+/*  DEFINE STATEMENTS                                                         */
+/******************************************************************************/
+
+/** Maximum size of a string */
+#define MAXSTR 256
+#define MAXVEC 2048
+#define MAXBUF 10000
+
+
+static void XMLFree(psXMLDoc *XML)
+{
+    xmlFreeDoc(*XML);
+}
+
+psXMLDoc *psXMLDocAlloc(void)
+{
+    psXMLDoc *XML;
+    XML = psAlloc(sizeof(psXMLDoc));
+    psMemSetDeallocator(XML, (psFreeFunc) XMLFree);
+    return(XML);
+}
+
+psXMLDoc *psMetadataToXMLDoc(const psMetadata *md)
+{
+    PS_ASSERT_PTR_NON_NULL(md, NULL);
+
+    psXMLDoc *XML = psXMLDocAlloc();
+    xmlNode *cur_node = NULL;
+    xmlNode *root = NULL;
+    xmlAttr *prop = NULL;
+    psDataType type;
+    char content[MAXSTR];
+    char vec[MAXVEC];
+    char timeVal[MAXSTR];
+    int i;
+    psMetadataIterator *iter = psMetadataIteratorAlloc(md, PS_LIST_HEAD, NULL);
+    psMetadataItem *item;
+
+    //setup root element
+    if( root == NULL ) {
+        *XML = xmlNewDoc((const xmlChar*)"1.0");
+        root = xmlNewDocNode(*XML, NULL, (const xmlChar*)"metadata", (const xmlChar*)"\n");
+        xmlDocSetRootElement(*XML, root);
+    }
+    item = psMetadataGetAndIncrement(iter);
+    while ( item != NULL ) {
+        type = item->type;
+        switch (type) {
+        case PS_DATA_BOOL:
+            cur_node = xmlNewChild(root, NULL, (const xmlChar*)"item", (const xmlChar*)"\n");
+            prop = xmlNewProp(cur_node, (const xmlChar*)"name", (const xmlChar*)item->name);
+            prop = xmlNewProp(cur_node, (const xmlChar*)"psType", (const xmlChar*)"BOOL");
+            if ( item->data.B )
+                strncpy(content, "TRUE", MAXSTR);
+            else
+                strncpy(content, "FALSE", MAXSTR);
+            prop = xmlNewProp(cur_node, (const xmlChar*)"value", (const xmlChar*)content);
+            break;
+        case PS_DATA_S32:
+            snprintf(content, MAXSTR, "%d", item->data.S32);
+            cur_node = xmlNewChild(root, NULL, (const xmlChar*)"item", (const xmlChar*)"\n");
+            prop = xmlNewProp(cur_node, (const xmlChar*)"name", (const xmlChar*)item->name);
+            prop = xmlNewProp(cur_node, (const xmlChar*)"psType", (const xmlChar*)"S32");
+            prop = xmlNewProp(cur_node, (const xmlChar*)"value", (const xmlChar*)content);
+            break;
+        case PS_DATA_F32:
+            snprintf(content, MAXSTR, "%f", item->data.F32);
+            cur_node = xmlNewChild(root, NULL, (const xmlChar*)"item", (const xmlChar*)"\n");
+            prop = xmlNewProp(cur_node, (const xmlChar*)"name", (const xmlChar*)item->name);
+            prop = xmlNewProp(cur_node, (const xmlChar*)"psType", (const xmlChar*)"F32");
+            prop = xmlNewProp(cur_node, (const xmlChar*)"value", (const xmlChar*)content);
+            break;
+        case PS_DATA_F64:
+            snprintf(content, MAXSTR, "%lf", item->data.F64);
+            cur_node = xmlNewChild(root, NULL, (const xmlChar*)"item", (const xmlChar*)"\n");
+            prop = xmlNewProp(cur_node, (const xmlChar*)"name", (const xmlChar*)item->name);
+            prop = xmlNewProp(cur_node, (const xmlChar*)"psType", (const xmlChar*)"F64");
+            prop = xmlNewProp(cur_node, (const xmlChar*)"value", (const xmlChar*)content);
+            break;
+        case PS_DATA_STRING:
+            cur_node = xmlNewChild(root, NULL, (const xmlChar*)"item", (const xmlChar*)"\n");
+            prop = xmlNewProp(cur_node, (const xmlChar*)"name", (const xmlChar*)item->name);
+            prop = xmlNewProp(cur_node, (const xmlChar*)"psType", (const xmlChar*)"STR");
+            strncpy(content, item->data.str, MAXSTR);
+            prop = xmlNewProp(cur_node, (const xmlChar*)"value", (const xmlChar*)content);
+            break;
+        case PS_DATA_METADATA:
+            i = 0;
+            psXMLDoc *newDoc;
+            xmlNode *new_root = NULL;
+            xmlNode *new_node = NULL;
+            newDoc = psMetadataToXMLDoc(item->data.md);
+            new_root = xmlDocGetRootElement(*newDoc);
+            prop = xmlNewProp(new_root, (const xmlChar*)"name", (const xmlChar*)item->name);
+            prop = xmlNewProp(new_root, (const xmlChar*)"psType", (const xmlChar*)"METADATA");
+            new_node = xmlAddSibling(cur_node, new_root);
+            psFree(newDoc);
+            break;
+        case PS_DATA_TIME:
+            cur_node = xmlNewChild(root, NULL, (const xmlChar*)"time", (const xmlChar*)"\n");
+            prop = xmlNewProp(cur_node, (const xmlChar*)"name", (const xmlChar*)item->name);
+            if ( ((psTime*)(item->data.V))->type == PS_TIME_UTC )
+                prop = xmlNewProp(cur_node, (const xmlChar*)"psType", (const xmlChar*)"PS_TIME_UTC");
+            else if ( ((psTime*)(item->data.V))->type == PS_TIME_TAI )
+                prop = xmlNewProp(cur_node, (const xmlChar*)"psType", (const xmlChar*)"PS_TIME_TAI");
+            else if ( ((psTime*)(item->data.V))->type == PS_TIME_UT1 )
+                prop = xmlNewProp(cur_node, (const xmlChar*)"psType", (const xmlChar*)"PS_TIME_UT1");
+            else if ( ((psTime*)(item->data.V))->type == PS_TIME_TT )
+                prop = xmlNewProp(cur_node, (const xmlChar*)"psType", (const xmlChar*)"PS_TIME_TT");
+            else {
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                        _("Failed to recognize XML content.  Invalid syntax."));
+                return NULL;
+            }
+            snprintf(content, MAXSTR, "%ld, ", (long)((psTime*)(item->data.V))->sec);
+            strncpy(timeVal, content, MAXSTR);
+            snprintf(content, MAXSTR, "%u, ", ((psTime*)(item->data.V))->nsec);
+            strncat(timeVal, content, MAXSTR);
+            if ( ((psTime*)(item->data.V))->leapsecond )
+                strncat(timeVal, "T", MAXSTR);
+            else
+                strncat(timeVal, "F", MAXSTR);
+            prop = xmlNewProp(cur_node, (const xmlChar*)"value", (const xmlChar*)timeVal);
+            break;
+        case PS_DATA_VECTOR:
+            cur_node = xmlNewChild(root, NULL, (const xmlChar*)"vector", (const xmlChar*)"\n");
+            prop = xmlNewProp(cur_node, (const xmlChar*)"name", (const xmlChar*)item->name);
+            type = ((psVector*)(item->data.V))->type.type;
+            strncpy(vec, "", MAXSTR);
+            switch (type) {
+            case PS_DATA_S32:
+                prop = xmlNewProp(cur_node, (const xmlChar*)"psType", (const xmlChar*)"S32");
+                for (i = 0; ((psVector*)(item->data.V))->data.S32[i] != 0; i++) {
+                    snprintf(content, MAXSTR, "%d",
+                             ((psVector*)(item->data.V))->data.S32[i]);
+                    if ( ((psVector*)(item->data.V))->data.S32[i+1] != 0 ) {
+                        strncat(content, ", ", 2);
+                    }
+                    strncat(vec, content, MAXSTR);
+                }
+                break;
+            case PS_DATA_F32:
+                prop = xmlNewProp(cur_node, (const xmlChar*)"psType", (const xmlChar*)"F32");
+                for (i = 0; ((psVector*)(item->data.V))->data.F32[i] != 0; i++) {
+                    snprintf(content, MAXSTR, "%f",
+                             ((psVector*)(item->data.V))->data.F32[i]);
+                    if ( ((psVector*)(item->data.V))->data.F32[i+1] != 0 ) {
+                        strncat(content, ", ", 2);
+                    }
+                    strncat(vec, content, MAXSTR);
+                }
+                break;
+            case PS_DATA_F64:
+                prop = xmlNewProp(cur_node, (const xmlChar*)"psType", (const xmlChar*)"F64");
+                for (i = 0; ((psVector*)(item->data.V))->data.F64[i] != 0; i++) {
+                    snprintf(content, MAXSTR, "%lf",
+                             ((psVector*)(item->data.V))->data.F64[i]);
+                    if ( ((psVector*)(item->data.V))->data.F64[i+1] != 0 ) {
+                        strncat(content, ", ", 2);
+                    }
+                    strncat(vec, content, MAXSTR);
+                }
+                break;
+            case PS_DATA_UNKNOWN:
+            default:
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                        _("Failed to recognize datatype from/for XML file."));
+                psFree(XML);
+                psFree(iter);
+                return NULL;
+            }
+            prop = xmlNewProp(cur_node, (const xmlChar*)"value", (const xmlChar*)vec);
+            break;
+        case PS_DATA_UNKNOWN:
+        default:
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    _("Failed to recognize datatype from/for XML file."));
+            psFree(XML);
+            psFree(iter);
+            return NULL;
+        }
+        item = psMetadataGetAndIncrement(iter);
+    }
+    //    xmlSaveFormatFile("xmlfname", *XML, 1);
+    psFree(iter);
+    return XML;
+}
+
+//compares strings and returns the correct data type//
+static psDataType getType(const char *in)
+{
+    //Returns types S32, F32, F64, STRING, BOOL, or UNKNOWN on ERROR
+    if ( !strncmp(in, "S32", MAXSTR) ) {
+        return(PS_DATA_S32);
+    } else if ( !strncmp(in, "F32", MAXSTR) ) {
+        return(PS_DATA_F32);
+    } else if ( !strncmp(in, "F64", MAXSTR) ) {
+        return(PS_DATA_F64);
+    } else if ( !strncmp(in, "STR", MAXSTR) ) {
+        return(PS_DATA_STRING);
+    } else if ( !strncmp(in, "BOOL", MAXSTR) ) {
+        return(PS_DATA_BOOL);
+    }
+
+    return(PS_DATA_UNKNOWN);
+}
+
+static void storeValues(psVector *inVector, char *in, psDataType type)
+{
+    int i;
+    char *endp;
+
+    switch (type) {
+    case PS_DATA_S32:
+        i = 0;
+        int intValue = 0;
+        while (i < MAXSTR) {
+            intValue = (int)strtol(in, &endp, 10);
+            if ( intValue != 0 ) {
+                inVector->data.S32[i] = intValue;
+                i++;
+                while (!strncmp(endp, ",", 1))
+                    endp++;
+                in = endp;
+            } else
+                i = MAXSTR;
+        }
+        break;
+    case PS_DATA_F32:
+        i = 0;
+        float floatValue = 0.0;
+        while (i < MAXSTR) {
+            floatValue = strtof(in, &endp);
+            if ( floatValue != 0.0 ) {
+                inVector->data.F32[i] = floatValue;
+                i++;
+                while (!strncmp(endp, ",", 1))
+                    endp++;
+                in = endp;
+            } else
+                i = MAXSTR;
+        }
+
+        break;
+    case PS_DATA_F64:
+        i = 0;
+        double doubleValue = 0.0;
+        while (i < MAXSTR) {
+            doubleValue = strtod(in, &endp);
+            if ( doubleValue != 0.0 ) {
+                inVector->data.F64[i] = doubleValue;
+                i++;
+                while (!strncmp(endp, ",", 1))
+                    endp++;
+                in = endp;
+            } else
+                i = MAXSTR;
+        }
+        break;
+    default:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Failed to recognize datatype from/for XML file."));
+    }
+}
+
+static void storeTime(psTime *out, char *in)
+{
+    char *endp;
+    long sec = 0;
+    unsigned int nsec = 0;
+
+    sec = strtol(in, &endp, 10);
+    out->sec = sec;
+    if ( !strncmp(endp, ",", 1) )
+        endp++;
+    else
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Failed to recognize XML content.  Invalid syntax."));
+    in = endp;
+    nsec = (unsigned int)strtol(in, &endp, 10);
+    out->nsec = nsec;
+    if ( !strncmp(endp, ",", 1) )
+        endp++;
+    else
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Failed to recognize XML content.  Invalid syntax."));
+    in = endp;
+    if ( !strncmp(in, "false", 10) || !strncmp(in, "f", 10) ||
+            !strncmp(in, "FALSE", 10) || !strncmp(in, " F", 10) )
+        out->leapsecond = false;
+    else if ( !strncmp(in, "true", 10) || !strncmp(in, "t", 10) ||
+              !strncmp(in, "TRUE", 10) || !strncmp(in, "T", 10) )
+        out->leapsecond = true;
+    else {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                _("Failed to recognize XML content.  Invalid syntax."));
+    }
+}
+
+//Check the xml item for errors.  Returns the data type or PS_DATA_UNKNOWN for errors.//
+static psDataType chkType(xmlNode *node)
+{
+    //NEED TO CHECK CONTENTS OF EACH ITEM/NODE //
+    //if item then,
+    if(!strncmp((const char*)node->name, "item", MAXSTR) || !strncmp((const char*)node->name, "ITEM", MAXSTR)) {
+        if (node->properties != NULL && node->properties->name != NULL
+                && node->properties->next != NULL && node->properties->next->name != NULL
+                && node->properties->next->next != NULL
+                && node->properties->next->next->name != NULL) {
+            psDataType type = getType((const char*)node->properties->next->children->content);
+            return type;
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    _("Failed to recognize XML content.  Invalid syntax."));
+            return(PS_DATA_UNKNOWN);
+        }
+    }
+    //if vector then,
+    if(!strncmp((const char*)node->name, "vector", MAXSTR) || !strncmp((const char*)node->name, "VECTOR", MAXSTR)) {
+        if (node->properties != NULL && node->properties->name != NULL
+                && node->properties->next != NULL && node->properties->next->name != NULL
+                && node->properties->next->next != NULL
+                && node->properties->next->next->name != NULL) {
+            return(PS_DATA_VECTOR);
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    _("Failed to recognize XML content.  Invalid syntax."));
+            return(PS_DATA_UNKNOWN);
+        }
+
+    }
+    //if metadata then,
+    if(!strncmp((const char*)node->name, "metadata", MAXSTR)) {
+        if (node->properties != NULL && node->properties->name
+                && node->properties->next != NULL && node->properties->next->name != NULL) {
+            return(PS_DATA_METADATA);
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    _("Failed to recognize XML content.  Invalid syntax."));
+            return(PS_DATA_UNKNOWN);
+        }
+    }
+    if(!strncmp((const char*)node->name, "time", MAXSTR) || !strncmp((const char*)node->name, "TIME", MAXSTR) ) {
+        if (node->properties != NULL && node->properties->name
+                && node->properties->next != NULL && node->properties->next->name != NULL) {
+            return(PS_DATA_TIME);
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    _("Failed to recognize XML content.  Invalid syntax."));
+            return(PS_DATA_UNKNOWN);
+        }
+    }
+    return(PS_DATA_UNKNOWN);
+}
+
+//Sorts the xmlDocPtr data into a usable Metadata structure.  Transverses an xml tree.//
+static psMetadata *xml2metadata(xmlNode *nodePtr, int nodeNum)
+{
+    psMetadata *meta = NULL;
+    xmlNode *cur_node = NULL;
+    char name[MAXSTR];
+    char content[MAXSTR];
+    //    char *name = NULL;
+    //    char *content = NULL;
+    psDataType type = PS_DATA_UNKNOWN;
+    psDataType elemType = PS_DATA_UNKNOWN;
+
+    meta = psMetadataAlloc();
+    cur_node = nodePtr;
+
+    //    for ( cur_node = nodePtr; cur_node != NULL; cur_node = cur_node->next )
+    while (cur_node != NULL) {
+        if ( cur_node->type == XML_ELEMENT_NODE ) {
+            //if the root node isn't a metadata//
+            if ( nodeNum == 0 && strncmp((const char*)cur_node->name, "metadata", MAXSTR) ) {
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                        _("Failed to recognize XML content.  Invalid syntax."));
+                psFree(meta);
+                return NULL;
+            }
+
+            if ( nodeNum != 0 ) {
+                type = chkType(cur_node);
+                //name = NULL;
+                //content = NULL;
+                switch ( type ) {
+                case PS_DATA_S32:
+                    strncpy(name, (char*)cur_node->properties->children->content, MAXSTR);
+                    strncpy(content,
+                            (char*)cur_node->properties->next->next->children->content, MAXSTR);
+                    psMetadataAddS32(meta, PS_LIST_TAIL, name, 0, "",
+                                     (int)strtol(content, NULL, 10));
+                    break;
+                case PS_DATA_F32:
+                    strncpy(name, (const char*)cur_node->properties->children->content, MAXSTR);
+                    strncpy(content,
+                            (const char*)cur_node->properties->next->next->children->content, MAXSTR);
+                    psMetadataAddF32(meta, PS_LIST_TAIL, name, 0, "", strtof(content, NULL));
+                    break;
+                case PS_DATA_F64:
+                    strncpy(name, (const char*)cur_node->properties->children->content, MAXSTR);
+                    strncpy(content,
+                            (const char*)cur_node->properties->next->next->children->content, MAXSTR);
+                    psMetadataAddF64(meta, PS_LIST_TAIL, name, 0, "", strtod(content, NULL));
+                    break;
+                case PS_DATA_STRING:
+                    strncpy(name, (const char*)cur_node->properties->children->content, MAXSTR);
+                    psMetadataAddStr(meta, PS_LIST_TAIL, name, 0, "",
+                                     (const char*)cur_node->properties->next->next->children->content);
+                    break;
+                case PS_DATA_VECTOR:
+                    strncpy(name, (const char*)cur_node->properties->children->content, MAXSTR);
+                    strncpy(content,
+                            (const char*)cur_node->properties->next->next->children->content, MAXSTR);
+                    elemType = getType((const char*)cur_node->properties->next->children->content);
+                    if (elemType == PS_DATA_UNKNOWN || elemType == PS_DATA_STRING
+                            || elemType == PS_DATA_BOOL) {
+                        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                                _("Failed to recognize datatype from/for XML file."));
+                        psFree(meta);
+                        return NULL;
+                    }
+
+                    psVector *vec = psVectorAlloc(strlen(content), elemType);
+                    storeValues(vec, content, elemType);
+                    psMetadataAddVector(meta, PS_LIST_TAIL, name, 0, "", vec);
+                    psFree(vec);
+                    break;
+                case PS_DATA_TIME:
+                    strncpy(name, (const char*)cur_node->properties->children->content, MAXSTR);
+                    strncpy(content,
+                            (const char*)cur_node->properties->next->next->children->content, MAXSTR);
+                    psTimeType timeType;
+                    char type[MAXSTR];
+                    strncpy(type, (const char*)cur_node->properties->next->children->content, MAXSTR);
+                    if ( !strncmp(type, "PS_TIME_UTC", MAXSTR) )
+                        timeType = PS_TIME_UTC;
+                    else if ( !strncmp(type, "PS_TIME_TAI", MAXSTR) )
+                        timeType = PS_TIME_TAI;
+                    else if ( !strncmp(type, "PS_TIME_UT1", MAXSTR) )
+                        timeType = PS_TIME_UT1;
+                    else if ( !strncmp(type, "PS_TIME_TT", MAXSTR) )
+                        timeType = PS_TIME_TT;
+                    else {
+                        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                                _("Failed to recognize XML content.  Invalid syntax."));
+                        psFree(meta);
+                        return NULL;
+                    }
+
+                    psTime *time;
+                    time = psTimeAlloc(timeType);
+                    storeTime(time, content);
+                    psMetadataAddTime(meta, PS_LIST_TAIL, name, 0, "", time);
+                    psFree(time);
+                    break;
+                case PS_DATA_METADATA:
+                    strncpy(name, (const char*)cur_node->properties->children->content, MAXSTR);
+                    psMetadata *temp = NULL;
+                    temp = xml2metadata(cur_node->children, nodeNum);
+                    psMetadataAddMetadata(meta, PS_LIST_TAIL, name, 0, "", temp);
+                    psFree(temp);
+                    break;
+                case PS_DATA_BOOL:
+                    strncpy(name, (const char*)cur_node->properties->children->content, MAXSTR);
+                    strncpy(content,
+                            (const char*)cur_node->properties->next->next->children->content, MAXSTR);
+                    if ( !strncmp(content, "true", MAXSTR) ||
+                            !strncmp(content, "TRUE", MAXSTR) ||
+                            !strncmp(content, "T", MAXSTR) ||
+                            !strncmp(content, "t", MAXSTR) ) {
+                        psMetadataAddBool(meta, PS_LIST_TAIL, name, 0, "", true);
+                    } else if ( !strncmp(content, "false", MAXSTR) ||
+                                !strncmp(content, "FALSE", MAXSTR) ||
+                                !strncmp(content, "F", MAXSTR) ||
+                                !strncmp(content, "f", MAXSTR) ) {
+                        psMetadataAddBool(meta, PS_LIST_TAIL, name, 0, "", false);
+                    } else {
+                        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                                _("Failed to recognize XML content.  Invalid syntax."));
+                        psFree(meta);
+                        return NULL;
+                    }
+                    break;
+                case PS_DATA_UNKNOWN:
+                default:
+                    psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                            _("Failed to recognize datatype from/for XML file."));
+                    psFree(meta);   //XXX: Do I really need this?
+                    return NULL;
+                }
+                nodeNum++;
+            } else //if root node, then increment nodeNum and go to children//
+            {
+                nodeNum++;
+                cur_node = cur_node->children;
+            }
+        }
+        cur_node = cur_node->next;
+    }
+    psFree(cur_node);
+    return meta;
+}
+
+psMetadata *psXMLDocToMetadata(const psXMLDoc *doc)
+{
+    PS_ASSERT_PTR_NON_NULL(doc, NULL);
+    //    psMetadata *md = psMetadataAlloc();
+    psMetadata *md = NULL;
+    xmlNode *root_element = NULL;
+    //XXX: doc changed to *doc
+    root_element = xmlDocGetRootElement(*doc);
+    md = xml2metadata(root_element, 0);
+    return md;
+}
+
+psXMLDoc *psXMLParseFile(const char *filename)
+{
+
+    PS_ASSERT_PTR_NON_NULL(filename, NULL);
+    psXMLDoc *XML;
+    XML = psXMLDocAlloc();
+    *XML = xmlReadFile(filename, NULL, 0);
+
+    xmlCleanupParser();
+    xmlMemoryDump();
+    return XML;
+}
+
+bool psXMLDocToFile(const psXMLDoc *doc,
+                    const char *filename)
+{
+    PS_ASSERT_PTR_NON_NULL(doc, 0);
+    PS_ASSERT_PTR_NON_NULL(filename, 0);
+    FILE *file;
+    if( (file = fopen(filename, "w")) == NULL ) {
+        psError(PS_ERR_IO, true, _("Failed to open file '%s'. Check if it exists and it has the proper permissions."), filename);
+        return false;
+    }
+
+    xmlDocDump(file, *doc);
+    fclose(file);
+    return true;
+}
+
+psXMLDoc *psXMLParseMem(const char *buffer,
+                        int size)
+{
+    PS_ASSERT_PTR_NON_NULL(buffer, NULL);
+    PS_ASSERT_INT_NONZERO(size, NULL);
+    char *URL = "new.xml";
+    psXMLDoc *XML;
+    XML = psXMLDocAlloc();
+    *XML = xmlReadMemory(buffer, size, URL, NULL, 0);
+
+    xmlCleanupParser();
+    xmlMemoryDump();
+
+    return XML;
+}
+
+bool psXMLDocToMem(const psXMLDoc *doc,
+                   char *buffer)
+{
+    PS_ASSERT_PTR_NON_NULL(doc, 0);
+    int bufferSize;
+    xmlChar *buff;
+
+    xmlDocDumpMemory(*doc, &buff, &bufferSize);
+    if ( MAXVEC < strlen((char *)buff) ) {
+        psError(PS_ERR_LOCATION_INVALID, true, _("Buffer to small to store XML doc."));
+        //        xmlFree(buff);
+        return false;
+    }
+    strncpy(buffer, (const char*)buff, MAXVEC);
+    xmlFree(buff);
+
+    return true;
+}
+
+psXMLDoc *psXMLParseFD(int fd)
+{
+    PS_ASSERT_INT_NONNEGATIVE(fd, NULL);
+    char *URL = "new.xml";
+    psXMLDoc *XML;
+    XML = psXMLDocAlloc();
+    *XML = xmlReadFd(fd, URL, NULL, 0);
+
+    xmlCleanupParser();
+    xmlMemoryDump();
+
+    return XML;
+}
+
+bool psXMLDocToFD(const psXMLDoc *doc,
+                  int fd)
+{
+    PS_ASSERT_PTR_NON_NULL(doc, 0);
+    PS_ASSERT_INT_NONNEGATIVE(fd, 0);
+
+    char buf[MAXBUF];
+    int n;
+    if ( psXMLDocToMem(doc, buf) ) {
+        n = strlen(buf);
+        write(fd, buf, n);
+    } else {
+        psError(PS_ERR_LOCATION_INVALID, true, _("Buffer to small to store XML doc."));
+        return false;
+    }
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/xml/psXML.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/xml/psXML.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/xml/psXML.h	(revision 22158)
@@ -0,0 +1,120 @@
+/* @file  psXML.h
+ * @brief Contains basic XML definitions and operations
+ *
+ * This file defines the basic type for an XML struct and functions useful
+ * in creation and usage of XML documents/files.
+ *
+ * @author David Robbins, MHPCC
+ *
+ * @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-01-23 22:47:23 $
+ * Copyright 2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PS_XML_H
+#define PS_XML_H
+
+/// @addtogroup FileIO Input/Output
+/// @{
+
+#include <libxml/parser.h>
+//#include <libxml/tree.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+
+#include "psMetadata.h"
+#include "psMetadataConfig.h"
+#include "psMemory.h"
+#include "psError.h"
+#include "psString.h"
+#include "psConstants.h"
+#include "psTime.h"
+
+/** XML wrapper pointing to an XML document in memory */
+typedef xmlDocPtr psXMLDoc;
+
+
+/*****************************************************************************/
+
+/* FUNCTION PROTOTYPES                                                       */
+
+/*****************************************************************************/
+
+/** Allocates a new psXMLDoc
+ *
+ *  @return psXMLDoc*         a new psXMLDoc object
+*/
+psXMLDoc *psXMLDocAlloc(void);
+
+/** Converts a psMetadata data structure to a complete psXMLDoc (in memory)
+ *
+ *  @return psXMLDoc*           Pointer to XML document from read
+*/
+psXMLDoc *psMetadataToXMLDoc(
+    const psMetadata *md               ///< psMetadata structure to read
+);
+
+/** Converts a complete psXMLDoc (in memory) to a psMetadata data structure
+ *
+ *  @return psMetadata*         Pointer to psMetadata data structure from read
+*/
+psMetadata *psXMLDocToMetadata(
+    const psXMLDoc *doc                ///< psXMLDoc to read
+);
+
+/** Loads the data in a named file into a complete psXMLDoc (in memory)
+ *
+ *  @return psXMLDoc*       Pointer to resulting XML document from read
+*/
+psXMLDoc *psXMLParseFile(
+    const char *filename               ///< Filename of file to be read
+);
+
+/** Writes out a complete psXMLDoc (in memory) to a named file
+ *
+ *  @return bool:       True on success or false otherwise.
+*/
+bool psXMLDocToFile(
+    const psXMLDoc *doc,               ///< psXMLDoc to read
+    const char *filename               ///< Filename of file to be written
+);
+
+/** Accepts a block of memory and parses it into a complete psXMLDoc (also in memory)
+ *
+ *  @return psXMLDoc*       Pointer to resulting XML document from read
+*/
+psXMLDoc *psXMLParseMem(
+    const char *buffer,                ///< Buffer to read
+    int size                           ///< Size of buffer
+);
+
+/** Accepts a complete psXMLDoc (in memory) and parses it into a block of memory
+ *
+ *  @return bool:       True on success or false otherwise.
+*/
+bool psXMLDocToMem(
+    const psXMLDoc *doc,               ///< psXMLDoc to read
+    char *buffer                       ///< Buffer to write
+);
+
+/** Reads from a file descriptor and converts the incoming data to a complete
+ *  psXMLDoc (in memory)
+ *
+ *  @return psXMLDoc*      Pointer to resulting XML document from read
+*/
+psXMLDoc *psXMLParseFD(
+    int fd                             ///< File descriptor to read
+);
+
+/** Reads from a complete psXMLDoc (in memory) and writes it to a file descriptor
+ *
+ *  @return bool:       True on success or false otherwise.
+*/
+bool psXMLDocToFD(
+    const psXMLDoc *doc,               ///< psXMLDoc to read
+    int fd                             ///< File descriptor to write
+);
+
+/// @}
+#endif // #ifndef PS_XML_H
Index: /branches/eam_branches/eam_branch_20080719/psLib/src/xml/xml.i
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/src/xml/xml.i	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/src/xml/xml.i	(revision 22158)
@@ -0,0 +1,2 @@
+/* xml headers */
+%include "psXML.h"
Index: /branches/eam_branches/eam_branch_20080719/psLib/swig/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/swig/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/swig/.cvsignore	(revision 22158)
@@ -0,0 +1,6 @@
+psLibModule
+Makefile
+Makefile.in
+*.bb
+*.bbg
+*.da
Index: /branches/eam_branches/eam_branch_20080719/psLib/swig/Makefile.PL
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/swig/Makefile.PL	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/swig/Makefile.PL	(revision 22158)
@@ -0,0 +1,35 @@
+# File : Makefile.PL
+use ExtUtils::MakeMaker;
+use FileHandle;
+
+sub ReadSetup {
+  my $filename = shift;
+      #return val
+  my %opts;
+
+  my $fh = FileHandle->new($filename, 'r');
+  while(<$fh>) {
+    /([a-z]+)=(.+)/ && do {
+      $opts{$1} = $2;
+      next;
+    };
+
+    #default:
+    die "Error:  syntaxt error in setup.txt line $_";
+  }
+  return %opts;
+}
+
+###############  Main ##############
+
+my %opts = ReadSetup("setup.txt");
+
+
+WriteMakefile(
+	'NAME' => 'pslib',             # Name of package
+	'INC' => $opts{includes},
+	'LIBS' => ["$opts{ldflags}"],  # Name of custom libraries
+	'OBJECT' => 'pslib_wrap.o',    # Name of object
+	'OPTIMIZE' => "$opts{cflags} -w", # cflags with disabling of warnings (SWIG generated code generates warnings)
+	'LD' => $opts{ld}
+);
Index: /branches/eam_branches/eam_branch_20080719/psLib/swig/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/swig/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/swig/Makefile.am	(revision 22158)
@@ -0,0 +1,47 @@
+
+EXTRA_DIST = pslib.i Makefile.PL example/phase2.pl example/data/*
+
+clean-generic:
+	rm -rf psLibModule
+
+# this is going into a make file one directory deeper in the tree so the
+# realitive paths need to be adjusted
+SWIGINC=`echo "${SRCINC}" | ${PERL} -pe "s|-I|-I../|g"`
+
+####################################################
+## PsLibModule swig build section.
+
+CLEANFILES = psLibModule
+
+psLibModule:
+	if [ ! -d psLibModule ]; then mkdir psLibModule; fi
+
+
+psLibModule/Makefile.PL: psLibModule
+	cp -f $(srcdir)/Makefile.PL psLibModule/Makefile.PL
+
+psLibModule/setup.txt: psLibModule
+	echo "includes=-I../$(top_srcdir)/src $(SWIGINC) $(PSLIB_CFLAGS)" > psLibModule/setup.txt
+	echo "ldflags=-L$(top_builddir)/src $(PSLIB_LIBS)" >> psLibModule/setup.txt
+	echo "cflags=$(CFLAGS) -std=c99 -Wno-unused -Wno-strict-aliasing" >> psLibModule/setup.txt
+
+psLibModule/pslib_wrap.c: psLibModule $(srcdir)/pslib.i
+	$(SWIG) -perl $(SRCINC) -w451 -o $@ $(srcdir)/pslib.i
+
+psLibModule/Makefile: psLibModule psLibModule/Makefile.PL psLibModule/setup.txt
+	cd psLibModule && $(PERL) Makefile.PL PREFIX=$(PERL_PREFIX)
+
+all: swig
+
+swig: psLibModule/pslib_wrap.c psLibModule/setup.txt psLibModule/Makefile
+	cd psLibModule && make
+
+swig-check: swig
+	export PERLLIB=psLibModule:psLibModule/blib/arch/auto/pslib && perl -Mpslib -e 'print "pslib version = " . pslib::psLibVersion() . "\n";'
+
+swig-install: swig
+	cd psLibModule && make install
+
+install-exec-hook: swig-install
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/badpix.fits
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/badpix.fits	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/badpix.fits	(revision 22158)
@@ -0,0 +1,50 @@
+SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                  -64 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   10 / length of data axis 1                          NAXIS2  =                   10 / length of data axis 2                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             p
+
+import os, re, sys
+from math import *
+import pdb
+import rhl
+
+if 0:
+    try:
+        import psLib
+        import ps
+    except: pass
+    
+try:
+    from actUtils import *
+except:
+    print "Failed to import actUtils"
+
+try:
+    from actSim import *
+except:
+    print "Failed to import actSim"
+
+try: import objects
+except: pass
+
+def tb():
+    pdb.pm()
+
+def grep(pattern, list):
+    print filter(lambda x: re.search(pattern, x), list)
+
+try:
+    import psLib
+    mortal = rhl.memCheckLeaks; id0=psLib.psMemGetId()
+except:
+    pass
+
+try:
+    from ds9 import mtv, dot, erase, line, zoom
+except:
+    print "Failed to load ds9"
+    pass
+
+###############################################################################
+
+class foo:
+    def __init__(self, a = 1, b = 2):
+        self.__dict__['a'] = a
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
Index: /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/base.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/base.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/base.config	(revision 22158)
@@ -0,0 +1,3 @@
+#
+SITE    STR     data/site.config
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/bias.fits
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/bias.fits	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/bias.fits	(revision 22158)
@@ -0,0 +1,50 @@
+SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                  -64 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   10 / length of data axis 1                          NAXIS2  =                   10 / length of data axis 2                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             p
+
+import os, re, sys
+from math import *
+import pdb
+import rhl
+
+if 0:
+    try:
+        import psLib
+        import ps
+    except: pass
+    
+try:
+    from actUtils import *
+except:
+    print "Failed to import actUtils"
+
+try:
+    from actSim import *
+except:
+    print "Failed to import actSim"
+
+try: import objects
+except: pass
+
+def tb():
+    pdb.pm()
+
+def grep(pattern, list):
+    print filter(lambda x: re.search(pattern, x), list)
+
+try:
+    import psLib
+    mortal = rhl.memCheckLeaks; id0=psLib.psMemGetId()
+except:
+    pass
+
+try:
+    from ds9 import mtv, dot, erase, line, zoom
+except:
+    print "Failed to load ds9"
+    pass
+
+###############################################################################
+
+class foo:
+    def __init__(self, a = 1, b = 2):
+        self.__dict__['a'] = a
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
Index: /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/camera-0.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/camera-0.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/camera-0.config	(revision 22158)
@@ -0,0 +1,17 @@
+#
+# Fakes for phase2
+#
+RECIPE.PHASE2   STR  data/recipe.config
+NCHIPS          S32  2
+
+NCELLS          S32  3
+CELL_NROW       S32  20
+CELL_NCOL       S32  20
+
+NREADOUTS.0.0   S32  1
+NREADOUTS.0.1   S32  1
+NREADOUTS.0.2   S32  1
+
+NREADOUTS.1.0   S32  1
+NREADOUTS.1.1   S32  1
+NREADOUTS.1.2   S32  1
Index: /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/dark.fits
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/dark.fits	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/dark.fits	(revision 22158)
@@ -0,0 +1,50 @@
+SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                  -64 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   10 / length of data axis 1                          NAXIS2  =                   10 / length of data axis 2                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             p
+
+import os, re, sys
+from math import *
+import pdb
+import rhl
+
+if 0:
+    try:
+        import psLib
+        import ps
+    except: pass
+    
+try:
+    from actUtils import *
+except:
+    print "Failed to import actUtils"
+
+try:
+    from actSim import *
+except:
+    print "Failed to import actSim"
+
+try: import objects
+except: pass
+
+def tb():
+    pdb.pm()
+
+def grep(pattern, list):
+    print filter(lambda x: re.search(pattern, x), list)
+
+try:
+    import psLib
+    mortal = rhl.memCheckLeaks; id0=psLib.psMemGetId()
+except:
+    pass
+
+try:
+    from ds9 import mtv, dot, erase, line, zoom
+except:
+    print "Failed to load ds9"
+    pass
+
+###############################################################################
+
+class foo:
+    def __init__(self, a = 1, b = 2):
+        self.__dict__['a'] = a
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
Index: /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/data.fits
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/data.fits	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/data.fits	(revision 22158)
@@ -0,0 +1,50 @@
+SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                  -64 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   10 / length of data axis 1                          NAXIS2  =                   10 / length of data axis 2                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             p
+
+import os, re, sys
+from math import *
+import pdb
+import rhl
+
+if 0:
+    try:
+        import psLib
+        import ps
+    except: pass
+    
+try:
+    from actUtils import *
+except:
+    print "Failed to import actUtils"
+
+try:
+    from actSim import *
+except:
+    print "Failed to import actSim"
+
+try: import objects
+except: pass
+
+def tb():
+    pdb.pm()
+
+def grep(pattern, list):
+    print filter(lambda x: re.search(pattern, x), list)
+
+try:
+    import psLib
+    mortal = rhl.memCheckLeaks; id0=psLib.psMemGetId()
+except:
+    pass
+
+try:
+    from ds9 import mtv, dot, erase, line, zoom
+except:
+    print "Failed to load ds9"
+    pass
+
+###############################################################################
+
+class foo:
+    def __init__(self, a = 1, b = 2):
+        self.__dict__['a'] = a
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
Index: /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/flat.fits
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/flat.fits	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/flat.fits	(revision 22158)
@@ -0,0 +1,50 @@
+SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                  -64 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   10 / length of data axis 1                          NAXIS2  =                   10 / length of data axis 2                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             p
+
+import os, re, sys
+from math import *
+import pdb
+import rhl
+
+if 0:
+    try:
+        import psLib
+        import ps
+    except: pass
+    
+try:
+    from actUtils import *
+except:
+    print "Failed to import actUtils"
+
+try:
+    from actSim import *
+except:
+    print "Failed to import actSim"
+
+try: import objects
+except: pass
+
+def tb():
+    pdb.pm()
+
+def grep(pattern, list):
+    print filter(lambda x: re.search(pattern, x), list)
+
+try:
+    import psLib
+    mortal = rhl.memCheckLeaks; id0=psLib.psMemGetId()
+except:
+    pass
+
+try:
+    from ds9 import mtv, dot, erase, line, zoom
+except:
+    print "Failed to load ds9"
+    pass
+
+###############################################################################
+
+class foo:
+    def __init__(self, a = 1, b = 2):
+        self.__dict__['a'] = a
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
Index: /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/fringe.fits
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/fringe.fits	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/fringe.fits	(revision 22158)
@@ -0,0 +1,50 @@
+SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                  -64 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   10 / length of data axis 1                          NAXIS2  =                   10 / length of data axis 2                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             p
+
+import os, re, sys
+from math import *
+import pdb
+import rhl
+
+if 0:
+    try:
+        import psLib
+        import ps
+    except: pass
+    
+try:
+    from actUtils import *
+except:
+    print "Failed to import actUtils"
+
+try:
+    from actSim import *
+except:
+    print "Failed to import actSim"
+
+try: import objects
+except: pass
+
+def tb():
+    pdb.pm()
+
+def grep(pattern, list):
+    print filter(lambda x: re.search(pattern, x), list)
+
+try:
+    import psLib
+    mortal = rhl.memCheckLeaks; id0=psLib.psMemGetId()
+except:
+    pass
+
+try:
+    from ds9 import mtv, dot, erase, line, zoom
+except:
+    print "Failed to load ds9"
+    pass
+
+###############################################################################
+
+class foo:
+    def __init__(self, a = 1, b = 2):
+        self.__dict__['a'] = a
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
Index: /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/recipe.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/recipe.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/recipe.config	(revision 22158)
@@ -0,0 +1,35 @@
+#
+# Default filenames
+#
+BADPIX.IMAGE    STR     FILE:data/badpix.fits
+BIAS.IMAGE      STR     FILE:data/bias.fits
+DARK.IMAGE      STR     FILE:data/dark.fits
+FLAT.IMAGE      STR     FILE:data/flat.fits
+FRINGE.IMAGE    STR     FILE:data/fringe.fits
+#
+BIAS.OVERSCAN STR  HEADER:BIASSEC
+
+BIAS.OVERSCAN.STATS     STR     XXX
+
+# BIAS.OVERSCAN.FIT: NONE POLYNOMIAL SPLINE 
+BIAS.OVERSCAN.FIT       STR     NONE
+
+BIAS.OVERSCAN.FIT.NBIN  S32     10
+BIAS.OVERSCAN.FIT.NPTS  S32     10
+BIAS.OVERSCAN.FIT.ORDER S32     1
+
+# The dark scaling
+DARK.FACTOR     STR     VALUE:1
+
+# Linearity corrections
+#NONLINEAR.METHOD: LOOKUP NONE POLYNOMIAL
+NONLINEAR.METHOD   STR  NONE
+NONLINEAR.ORDER    S32  3               # Why do we need this? It's implicit in .COEFFS
+@NONLINEAR.COEFFS  F64 1 2 3
+NONLINEAR.IN_FLUX          STR  foo.in.fits
+NONLINEAR.OUT_FLUX         STR  foo.out.fits
+
+#
+# How to trim the file
+#
+TRIM.DATASEC    STR     HEADER:DATASEC
Index: /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/site.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/site.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/swig/example/data/site.config	(revision 22158)
@@ -0,0 +1,1 @@
+CAMERA.0 STR data/camera-0.config # Camera filename
Index: /branches/eam_branches/eam_branch_20080719/psLib/swig/example/phase2.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/swig/example/phase2.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/swig/example/phase2.pl	(revision 22158)
@@ -0,0 +1,484 @@
+#!/usr/bin/perl -w
+package phase2;
+
+use strict;
+use pslib;
+#
+# Prototypes
+#
+sub DefineStats($);
+sub DirectionFromOverscan($);
+sub bias_subtract_readout($$$; @);
+sub dark_subtract_readout($$$);
+sub defringe_readout($$$$);
+sub getScalingFactor($$$);
+sub load_image($$$$);
+sub make_kernel();
+sub make_mask($$);
+sub mask_readout($$$$$);
+sub nonlinearity_correct_readout($$$$);
+sub phase2($$; @);
+sub pmCameraFromHeader($);
+sub pmCameraValidateHeaders($$);
+sub pmFPAfromHeader($$);
+sub pmFlatField($$$);
+sub pmRecipeDefineSection($$$);
+sub pmSectiontoRectangle($);
+sub pmSubtractBias($$$$$$$$);
+sub psFITSReadHeaderSet($);
+sub trim_readout($$$);
+
+###############################################################################
+#
+# Do the real work
+#
+sub phase2($$; @)
+{
+   my($input, $outroot, $cameraname, $recipefile, $basefile, $verbose) = @_;
+   $basefile ||= "base.config"; $verbose ||= 0;
+   my($nFail) = 0;
+   $outroot++;
+
+   pslib::psTraceSetLevel("ps.phase2", $verbose);
+
+   my($site);
+   if ($basefile) {
+      pslib::psTrace("ps.phase2", 2, "Basefile: $basefile\n");
+      
+      my($base) = pslib::psMetadataAlloc();
+      pslib::psMetadataParseConfig($base, $basefile, 1);
+      
+      my($sitefile) = pslib::psMetadataLookup($base, "SITE")->get_STR();
+      
+      $site = pslib::psMetadataAlloc();
+      pslib::psMetadataParseConfig($site, $sitefile, 1);
+   } else {
+      $site = undef;
+   }
+   
+   # load only the headers from the given file input a list of headers
+   my($headers) = psFITSReadHeaderSet($input);
+   
+   # identify camera (may be specified on command line)
+   my($camera);
+   if (!$cameraname) {
+      $cameraname = pmCameraFromHeader(pslib::psHashLookup($headers, "PHU"));
+      my($camerafile) = pslib::psMetadataLookup($site, ("CAMERA.$cameraname"))->get_STR();
+
+      # load the camera details for the specific camera
+      $camera = pslib::psMetadataAlloc();
+      pslib::psMetadataParseConfig($camera, $camerafile, 0);
+   }
+
+   # recipefile is defined in the camera metadata, if not specified on command line
+   if (!$recipefile) {
+      if (1) {			# 
+	 $recipefile = pslib::psMetadataLookup($camera, "RECIPE.PHASE2")->get_STR();
+      } else {                           # an alternative make this a database lookup & a function of date
+	 $recipefile = DetrendDatabaseLookup ("recipe", $camera, $headers);
+      }
+   }
+   
+   pslib::psTrace("ps.phase2", 2, "Reading recipe from $recipefile\n");
+   my($recipe) = pslib::psMetadataAlloc();
+   pslib::psMetadataParseConfig($recipe, $recipefile, 0);
+
+   # END CONFIG loading code
+
+   # check the validity of the given set of headers based on expectactions for this camera
+   pslib::psTrace("ps.phase2", 3, "Validating headers\n");
+   pmCameraValidateHeaders($headers, $camera);
+
+   # construct a complete, empty (ie, no pixel data) FPA structure for this camera / header set
+   # we need to construct the output container.  is it big enough to fit in memory?  assume so?
+   my($FPA) = pmFPAfromHeader($headers, $camera);
+   
+   # I\'m pretending the extname value for each cell in part of psCell
+   # Do we need to construct a list of the extname values associated with each readout?
+   # Is EXTNAME invarient?  (probably not; does not always exist)
+   #
+   # XXX Faked psCell->{extname} to exist and be NULL in pslib.i XXX
+   
+   my($i, $j, $k);
+   for ($i = 0; $i < $FPA->{chips}->{n}; $i++) {
+      my($chip) = $FPA->{chips}->get_chip($i);
+
+      pslib::psTrace("ps.phase2", 3, "Processing chip $i\n");
+      for ($j = 0; $j < $chip->{cells}->{n}; $j++) {
+	 my($cell) = $chip->{cells}->get_cell($j);
+	 
+	 pslib::psTrace("ps.phase2", 4, "Processing cell $j\n");
+	 my($bias) = load_image("BIAS", $recipe, $cell->{metadata}, $cell->{extname});
+	 my($dark) = load_image("DARK", $recipe, $cell->{metadata}, $cell->{extname});
+	 my($flat) = load_image("FLAT", $recipe, $cell->{metadata}, $cell->{extname});
+	 my($badpix) = load_image("BADPIX", $recipe, $cell->{metadata}, $cell->{extname});
+	 my($fringe) = load_image("FRINGE", $recipe, $cell->{metadata}, $cell->{extname});
+	 pslib::psTrace("ps.phase2", 5, "Read images for cell $j\n");
+	 
+	 for ($k = 0; $k < $cell->{readouts}->{n}; $k++) {
+	    pslib::psTrace("ps.phase2", 6, "Reading readout $k\n");
+	    
+	    my($readout) = $cell->{readouts}->get_readout($k);
+	    $readout->{image} = pslib::psImageReadSection(undef, 0, 0, 0, 0, 0, $cell->{extname}, $k, $input);
+
+	    if (!defined($readout->{metadata})) {
+	       pslib::psTrace("ps.phase2", 7, "Creating metadata\n");
+	       $readout->{metadata} = pslib::psMetadataAlloc();
+
+	       my($nbias) = 2;
+	       pslib::psMetadataAddStr($readout->{metadata}, $pslib::PS_LIST_TAIL,
+				       "BIASSEC", "Define bias section",
+				       sprintf("[0:%d,0:%d]",
+					       ($readout->{image}->{numRows} - 1, $nbias - 1)));
+	       pslib::psMetadataAddStr($readout->{metadata}, $pslib::PS_LIST_TAIL,
+				       "DATASEC", "Define datasection section",
+				       sprintf("[0:%d,%d:%d]",
+					       ($readout->{image}->{numRows} - 1, $nbias,
+						$readout->{image}->{numCols} - 1)));
+	    }
+	    
+	    my($kernel) = make_kernel();
+	    my($mask) = make_mask($readout->{image}->{numRows}, $readout->{image}->{numCols});
+	    
+	    pslib::psTrace("ps.phase2", 7, "Bias subtraction\n");
+	    bias_subtract_readout($readout, $bias, $recipe);
+	    
+	    pslib::psTrace("ps.phase2", 7, "Dark subtraction\n");
+	    dark_subtract_readout($readout, $dark, $recipe);
+	    nonlinearity_correct_readout($readout, $mask, $recipe, $camera);
+	    # 
+	    pslib::psTrace("ps.phase2", 7, "Trimming\n");
+	    trim_readout($readout, $mask, $recipe);
+	    mask_readout($readout, $mask, $badpix, $kernel, $recipe);
+	    # 
+	    # where do we convolve the flat with the kernel?
+	    #
+	    pmFlatField($readout, $mask, $flat);
+	    # 
+	    pslib::psTrace("ps.phase2", 7, "Defringing\n");
+	    defringe_readout($readout, $mask, $fringe, $recipe);
+
+	 }
+      }
+   }
+}
+
+sub bias_subtract_readout($$$; @)
+{
+   #"bias subtract the given readout according to the recipe (bias image may be None)
+   #no mask needed yet"
+   
+   my($readout, $bias, $recipe, $mask) = (undef, undef, undef, undef);
+   ($readout, $bias, $recipe, $mask) = @_;
+   #determine overscan option
+   my($biassec) = pmRecipeDefineSection($recipe, $readout->{metadata}, "BIAS.OVERSCAN");
+   my($overscan) = pslib::psImageSubsection($readout->{image}, $biassec);
+
+   # the type of statistic is defined by the recipe: BIAS.OVERSCAN.STATS
+   my($statname) = pslib::psMetadataLookup ($recipe, "BIAS.OVERSCAN.STATS")->get_STR();
+   my($stats) = DefineStats($statname);
+   
+   # identify the type of fit requested and relevant parameters
+   # the type of fit is defined by the recipe: BIAS.OVERSCAN.STATS
+   my($fitname) = pslib::psMetadataLookup($recipe, "BIAS.OVERSCAN.FIT")->get_STR();  # string defining overscan stats
+   
+   my($fitType, $fitSpec, $nBin, $nPts, $order);
+   if ($fitname eq "NONE") {
+      $fitType = "PM_FIT_NONE";
+      $fitSpec = undef;
+      $nBin = 0;
+   } elsif ($fitname eq "SPLINE") {
+      my($Npix) = "XXX";
+
+      $fitType = "PM_FIT_SPLINE";
+      $nBin = pslib::psMetadataLookup($recipe, "BIAS.OVERSCAN.FIT.NBIN");
+      $nPts = pslib::psMetadataLookup($recipe, "BIAS.OVERSCAN.FIT.NPTS");
+      $order = pslib::psMetadataLookup($recipe, "BIAS.OVERSCAN.FIT.ORDER");
+      $fitSpec = psSpline1DAlloc($nPts, 3, 0, $Npix);                  # Npix is either NAXIS1 or NAXIS2 (Nx or Ny)
+   } elsif ($fitname eq "POLYNOMIAL") {
+      $fitType = "PM_FIT_POLYNOMIAL";
+      $nBin = pslib::psMetadataLookup($recipe, "BIAS.OVERSCAN.FIT.NBIN");
+      $nPts = pslib::psMetadataLookup($recipe, "BIAS.OVERSCAN.FIT.NPTS");
+      $order = pslib::psMetadataLookup($recipe, "BIAS.OVERSCAN.FIT.ORDER");
+      $fitSpec = psPolynomial1DAlloc($nPts, "PS_POLYNOMIAL_CHEB");
+   } else {
+      #raise pslib::PsUtilsError ("unknown fitname: %s" % fitname)
+   }
+   
+   my($overscanlist) = pslib::psListAlloc($overscan);
+   $readout->{image} = pmSubtractBias($readout->{image}, $fitSpec, $overscanlist,
+				      DirectionFromOverscan($biassec), $stats, $nBin, $fitType, $bias);
+
+   # add these to the readout->{metadata}? 
+   # or to the chip / cell metadata?
+}
+
+sub dark_subtract_readout($$$)
+{
+   #"subtract dark image using the appropriate scaling factor for this exposure time
+   #no mask needed yet"
+
+   my($readout, $dark, $recipe) = @_;
+
+   if (!defined($dark)) {
+      return;
+   }
+
+   # need to get a lookup table from the database, apply exptime for readout and dark
+   my($factor) = getScalingFactor($recipe, $readout, $dark);
+   
+   # $out = in - dark * factor
+   my($tmp) = pslib::psImageCopy(undef, $dark, $dark->{type}->{type});
+   pslib::psBinaryOp($tmp, $dark, "*", $factor);
+   pslib::psBinaryOp($readout->{image}, $readout->{image}, "-", $tmp);
+}
+
+sub nonlinearity_correct_readout($$$$)
+{
+   #"this corrects the non-linear response, but probably should use data determined at the cell level
+   #we need to set a mask value for pixels which have were out of range (TBD)"
+
+   my($readout, $mask, $recipe, $camera) = @_;
+   
+   my($method) = pslib::psMetadataLookup($recipe, "NONLINEAR.METHOD")->get_STR();
+   
+   # use a polynomial; get coeffs from recipe
+   if ($method eq "NONE") {
+      ;
+   } elsif ($method eq "POLYNOMIAL") {
+      my($correction);
+      $correction->{n} = pslib::psMetadataLookup($recipe, "NONLINEAR.ORDER")->{data}->{S32};
+      $correction->{coeffs} = pslib::psMetadataLookup($recipe, "NONLINEAR.COEFFS");
+      pslib::pmNonLinearityPolynomial($readout, $correction);
+   } elsif ($method eq "LOOKUP") {
+      my($time) = "XXX";
+      my($lookup_table) = DetrendDatabaseLookup($time, $camera, "etc?");
+      my($inFlux) = pslib::psFITSTableRead($lookup_table, "NONLINEAR.IN_FLUX");
+      my($outFlux) = pslib::psFITSTableRead($lookup_table, "NONLINEAR.OUT_FLUX");
+      pslib::pmNonLinearityLookup($readout, $inFlux, $outFlux);
+   } else {
+      #raise pslib::PsUtilsError ("unknown method: %s" % method);
+   }
+}
+
+sub trim_readout($$$)
+{
+   #"trim the image and mask based on the requested region"
+   my($readout, $mask, $recipe) = @_;
+   my($datasec) = pmRecipeDefineSection($recipe, $readout->{metadata}, "TRIM.DATASEC");
+   
+   my($r0, $r1, $c0, $c1) = ($datasec =~ /\[([0-9]+):([0-9]+),([0-9]+):([0-9]+)\]/);
+   
+   pslib::psImageTrim($readout->{image}, $c0, $r0, $c1, $r1);
+   $mask = pslib::psImageTrim($mask, $c0, $r0, $c1, $r1);
+}
+
+# apply the bad pixel mask to the image mask
+sub mask_readout($$$$$)
+{
+   my($readout, $mask, $badpix, $kernel, $recipe) = @_;
+}
+
+sub load_image($$$$)
+{
+   #"load in the complete corresponding image of proper type (this should be done once per cell)
+   #we are implying that the bias image is guaranteed to have the corresponding EXTNAME"
+
+   my($type, $recipe, $header, $extname) = @_;
+   my($source) = pslib::psMetadataLookup($recipe, $type . ".IMAGE")->get_STR();
+
+   my($name);
+   if (uc(substr($source, 0, 5)) eq "FILE:") {
+      $name = substr($source, 5);
+   } elsif (uc($source) eq "DB:BEST") {
+      $name = DetrendDatabaseLookup("best", $header);   # these APIs need to be seriously fleshed out!!
+   } elsif (uc($source) eq "DB:CLOSE") {
+      $name = DetrendDatabaseLookup("close", $header);   # these APIs need to be seriously fleshed out!!
+   } else {
+      #raise PsUtilsError ("Unknown source for $type: $source");
+   }
+
+   my($image);
+   if (defined($name)) {
+      $image = pslib::psImageReadSection (undef, 0, 0, 0, 0, 0, $extname, 0, $name);
+   } else {
+      $image = undef;
+   }
+
+   return $image;
+}
+
+sub pmRecipeDefineSection($$$)
+{
+   my($recipe, $header, $name) = @_;
+
+   my($source) = pslib::psMetadataLookup($recipe, $name)->get_STR();
+   
+   pslib::psTrace("ps.phase2.recipe", 10, "pmRecipeDefineSection (recipe, header, $name)\n");
+   
+   if (uc($source) eq "NONE") {
+      return psRectangleAlloc(0, 0, 0, 0); # the None section
+   } elsif (uc(substr($source, 0, 7)) eq "HEADER:") {
+      my($keyword) = substr($source,7);
+      my($section) = pslib::psMetadataLookup($header, $keyword)->get_STR();
+      return pmSectiontoRectangle($section);
+   } elsif (uc(substr($source, 0, 7)) eq "RECIPE:") {
+      my($section) = substr($source, 7);
+      return pmSectiontoRectangle($section);
+   }
+   
+   #raise pslib::PsUtilsError ("invalid section: $section");
+}
+
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+sub DirectionFromOverscan($)
+{
+   #"The direction is implied by noting the long dimension of the biassec"
+   my($secstr) = @_;
+
+   return 1;
+}
+
+sub pmSectiontoRectangle($)
+{
+   #"Parse a specification of the form [col0:col1,row0:row1]
+   #For now, simply return it"
+   my($secstr) = @_;
+
+   return $secstr;
+}
+
+sub psFITSReadHeaderSet($)
+{
+   my($input) = @_;
+   
+   pslib::psTrace("ps.phase2", 2, "Reading headers: $input\n");
+
+   my($meta) = pslib::psMetadataAlloc();
+   pslib::psMetadataAddStr($meta, $pslib::PS_LIST_TAIL, "CAMERA", "Camera ID", "0");
+
+   my($headers) = pslib::psHashAlloc(64);
+   pslib::psHashAdd($headers, "PHU", $meta);
+   
+   return $headers;
+}
+
+sub pmCameraFromHeader($)
+{
+   #"Return a camera given the metadata read from a fits header"
+   my($meta) = @_;
+
+   return "0";
+}
+
+sub pmCameraValidateHeaders($$)
+{
+   my($headers, $camera) = @_;
+
+   if (0) {
+      #raise pslib::PsUtilsError ("Failed to validate $headers:$camera");
+   }
+}
+
+sub pmFPAfromHeader($$)
+{
+   my($headers, $camera) = @_;
+   
+   my($ra) = 1; my($dec) = 2; my($hourAngle) = 3; my($zenith) = 4; my($azimuth) = 5;
+   my($rotAngle) = 8;
+   my($temperature) = 9; my($pressure) = 10; my($humidity) = 11;
+   my($exposureTime) = 12;
+
+   my($nchips) = pslib::psMetadataLookup($camera, "NCHIPS")->{data}->{S32};
+   my($ncells) = pslib::psMetadataLookup($camera, "NCELLS")->{data}->{S32};
+   
+   my($obs) = pslib::psObservatoryAlloc("Haleakala", 21, 150, 3000, 0.1);
+   my($wavelength) = 5500e-10;
+   my($localTime) = pslib::psTimeGetTime($pslib::PS_TIME_TAI);
+
+   my($exposure) = pslib::psExposureAlloc($ra, $dec, $hourAngle, $zenith, $azimuth, $localTime,
+					  $rotAngle, $temperature, $pressure, $humidity, $exposureTime,
+					  $wavelength, $obs);
+   my($FPA) = pslib::psFPAAlloc($nchips, $exposure);
+   my($chips) = pslibc::psFPA_chips_get($FPA);
+   
+   my($i, $j, $k);
+   for ($i = 0; $i <$nchips; $i++) {
+      my($chip) = pslib::psChipAlloc($ncells, $FPA);
+      pslib::psArraySet($chips, $i, $chip);
+      my($cells) = pslibc::psChip_cells_get($chip);
+      for ($j = 0; $j <$ncells; $j++) {
+	 my($nReadouts) = pslib::psMetadataLookup($camera, "NREADOUTS.$i.$j")->{data}->{S32};
+
+	 my($cell) = pslib::psCellAlloc($nReadouts, $chip);
+	 
+	 pslib::psArraySet($cells, $j, $cell);
+	 
+	 my($readouts) = pslibc::psCell_readouts_get($cell);
+	 for ($k = 0; $k < $nReadouts; $k++) {
+	     pslib::psArraySet($readouts, $k, pslib::psReadoutAlloc());
+	 }
+      }
+   }
+
+   return $FPA;
+}
+
+sub make_kernel()
+{
+   my($nrow) = 5; my($ncol) = 5;
+   return pslib::psImageAlloc($ncol, $nrow, $pslib::PS_TYPE_F64);
+}
+
+sub make_mask($$)
+{
+   my($nrow, $ncol) = @_;
+
+   return pslib::psImageAlloc($ncol, $nrow, $pslib::PS_TYPE_F64);
+}
+
+sub DefineStats($)
+{
+   my($str) = @_;
+   return $str;
+}
+
+sub pmSubtractBias($$$$$$$$)
+{
+   #"Subtract the bias. Don't do a very good job..."
+   my($rawImage, $fitSpec, $overscanlist, $direction, $stats, $nBin, $type, $bias) = @_;
+   return pslib::psImageAlloc($rawImage->{numCols}, $rawImage->{numRows}, $pslib::PS_TYPE_F64);
+}
+
+sub getScalingFactor($$$)
+{
+   my($recipe, $readout, $dark) = @_;
+   my($source) = pslib::psMetadataLookup($recipe, "DARK.FACTOR")->get_STR();
+
+   if (uc(substr($source, 0, length("VALUE:"))) eq "VALUE:") {
+      return pslib::psScalarF32Alloc(substr($source, length("VALUE:")), $pslib::PS_TYPE_F64);
+   }
+
+   #raise pslib::PsUtilsError ("Unknown recipe for dark factor: $source");
+}
+
+sub pmFlatField($$$)
+{
+   my($readout, $mask, $flat) = @_;
+}
+
+sub defringe_readout($$$$)
+{
+   my($readout, $mask, $fringe, $recipe) = @_;
+}
+
+#(input, outroot, cameraname = None, recipefile = None, basefile = "base.config", verbose=0)
+if (1) {
+   phase2('data/data.fits', undef, undef, undef, "data/base.config", 4);
+   
+   if (pslib::psMemCheckLeaksToStderr(0,undef,0)) {
+      die "You leaked memory\n";
+   }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/swig/pslib.i
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/swig/pslib.i	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/swig/pslib.i	(revision 22158)
@@ -0,0 +1,69 @@
+%module pslib
+
+%{
+#define PS_ALLOW_MALLOC
+#define SWIG
+#include "pslib.h"
+
+/* SWIG uses malloc/free - make it use the pslib memory functions instead. */
+/*
+#define malloc(S)    psAlloc(S)
+#define realloc(P,S) psRealloc(P,S)
+#define free(P)      psFree(P)
+*/
+
+%}
+
+/* XXX: this is temporary -- not portable, but should work with any current OS supported */
+typedef unsigned char  uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int   uint32_t;
+typedef unsigned long  uint64_t;
+typedef char           int8_t;
+typedef short          int16_t;
+typedef int            int32_t;
+typedef long long      int64_t;
+
+/* grab the typedefs used throughout psLib, e.g. psU8, psU16,... */
+%include "cpointer.i"
+%include "typemaps.i"
+
+/**
+ * Typemap to map FILE* input to the script's native file descriptor wrapper.
+ * Used for such functions as psErrorStackPrint and psTraceSetDestination.
+ */
+%typemap(in) FILE * {
+#if defined(SWIGPERL)
+   if (!SvOK($input)) {
+      $1 = NULL;
+   } else {
+      $1 = PerlIO_findFILE(IoIFP(sv_2io($input)));
+   }
+#elif defined(SWIGPYTHON)
+    if ($input == Py_None) {
+	$1 = NULL;
+    } else if (!PyFile_Check($input)) {
+	PyErr_SetString(PyExc_TypeError, "Need a file!");
+	goto fail;
+    } else {
+	$1 = PyFile_AsFile($input);
+    }
+#endif
+}
+
+%{
+typedef struct { float re, im; } swig_psC32;  ///< 32-bit complex floating point
+typedef struct { double re, im; } swig_psC64; ///< 64-bit complex floating point
+%}
+
+/* the actual including of headers are found in each of the directories. */
+%include "astro.i"
+%include "db.i"
+%include "fft.i"
+%include "fits.i"
+%include "imageops.i"
+%include "math.i"
+%include "mathtypes.i"
+%include "sys.i"
+%include "types.i"
+%include "xml.i"
Index: /branches/eam_branches/eam_branch_20080719/psLib/test-coverage
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test-coverage	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test-coverage	(revision 22158)
@@ -0,0 +1,93 @@
+set PWD='pwd'
+./autogen.sh CFLAGS="-lgcov -fprofile-arcs -ftest-coverage" --prefix=$PWD
+make clean
+make
+mkdir Test_Coverage
+cd test
+./FullUnitTest
+cd ../src/astro
+gcov -f --object-file ./.libs/libpslibastro_la-psCoord.o psCoord.c > coverage-astro.coord
+gcov -f --object-file ./.libs/libpslibastro_la-psEarthOrientation.o psEarthOrientation.c > coverage-astro.eoc
+gcov -f --object-file ./.libs/libpslibastro_la-psSphereOps.o psSphereOps.c > coverage-astro.sphereOps
+gcov -f --object-file ./.libs/libpslibastro_la-psTime.o psTime.c > coverage-astro.time
+mv coverage-*.* ../../Test_Coverage/
+cd ../db
+gcov -f --object-file ./.libs/libpslibdb_la-psDB.o psDB.c > coverage-db.db
+mv coverage-*.* ../../Test_Coverage/
+cd ../fft
+gcov -f --object-file ./.libs/libpslibfft_la-psImageFFT.o psImageFFT.c > coverage-fft.imageFFT
+gcov -f --object-file ./.libs/libpslibfft_la-psVectorFFT.o psVectorFFT.c > coverage-fft.vectorFFT
+mv coverage-*.* ../../Test_Coverage/
+cd ../fits
+gcov -f --object-file ./.libs/libpslibfits_la-psFits.o psFits.c > coverage-fits.fits
+gcov -f --object-file ./.libs/libpslibfits_la-psFitsHeader.o psFitsHeader.c > coverage-fits.fitsHeader
+gcov -f --object-file ./.libs/libpslibfits_la-psFitsImage.o psFitsImage.c > coverage-fits.fitsImage
+gcov -f --object-file ./.libs/libpslibfits_la-psFitsTable.o psFitsTable.c > coverage-fits.fitsTable
+mv coverage-*.* ../../Test_Coverage/
+cd ../imageops
+gcov -f --object-file ./.libs/libpslibimageops_la-psImageBackground.o psImageBackground.c > coverage-imageops.imageBackground
+gcov -f --object-file ./.libs/libpslibimageops_la-psImageConvolve.o psImageConvolve.c > coverage-imageops.imageConvolve
+gcov -f --object-file ./.libs/libpslibimageops_la-psImageGeomManip.o psImageGeomManip.c > coverage-imageops.imageGeomManip
+gcov -f --object-file ./.libs/libpslibimageops_la-psImageMaskOps.o psImageMaskOps.c > coverage-imageops.imageMaskOps
+gcov -f --object-file ./.libs/libpslibimageops_la-psImagePixelExtract.o psImagePixelExtract.c > coverage-imageops.imagePixelExtract
+gcov -f --object-file ./.libs/libpslibimageops_la-psImagePixelManip.o psImagePixelManip.c > coverage-imageops.imagePixelManip
+gcov -f --object-file ./.libs/libpslibimageops_la-psImageStats.o psImageStats.c > coverage-imageops.imageStats
+gcov -f --object-file ./.libs/libpslibimageops_la-psImageStructManip.o psImageStructManip.c > coverage-imageops.imageStructManip
+gcov -f --object-file ./.libs/libpslibimageops_la-psImageUnbin.o psImageUnbin.c > coverage-imageops.imageUnbin
+mv coverage-*.* ../../Test_Coverage/
+cd ../jpeg
+gcov -f --object-file ./.libs/libpslibjpeg_la-psImageJpeg.o psImageJpeg.c > coverage-jpeg.imageJpeg
+mv coverage-*.* ../../Test_Coverage/
+cd ../math
+gcov -f --object-file ./.libs/libpslibmath_la-psBinaryOp.o psBinaryOp.c > coverage-math.binaryOp
+gcov -f --object-file ./.libs/libpslibmath_la-psCompare.o psCompare.c > coverage-math.compare
+gcov -f --object-file ./.libs/libpslibmath_la-psEllipse.o psEllipse.c > coverage-math.ellipse
+gcov -f --object-file ./.libs/libpslibmath_la-psMathUtils.o psMathUtils.c > coverage-math.mathUtils
+gcov -f --object-file ./.libs/libpslibmath_la-psMatrix.o psMatrix.c > coverage-math.matrix
+gcov -f --object-file ./.libs/libpslibmath_la-psMinimizeLMM.o psMinimizeLMM.c > coverage-math.minimizeLMM
+gcov -f --object-file ./.libs/libpslibmath_la-psMinimizePolyFit.o psMinimizePolyFit.c > coverage-math.minimizePolyFit
+gcov -f --object-file ./.libs/libpslibmath_la-psMinimizePowell.o psMinimizePowell.c > coverage-math.minimizePowell
+gcov -f --object-file ./.libs/libpslibmath_la-psPolynomial.o psPolynomial.c > coverage-math.polynomial
+gcov -f --object-file ./.libs/libpslibmath_la-psPolynomialUtils.o psPolynomialUtils.c > coverage-math.polynomialUtils
+gcov -f --object-file ./.libs/libpslibmath_la-psRandom.o psRandom.c > coverage-math.random
+gcov -f --object-file ./.libs/libpslibmath_la-psRegion.o psRegion.c > coverage-math.region
+gcov -f --object-file ./.libs/libpslibmath_la-psRegionForImage.o psRegionForImage.c > coverage-math.regionForImage
+gcov -f --object-file ./.libs/libpslibmath_la-psSparse.o psSparse.c > coverage-math.sparse
+gcov -f --object-file ./.libs/libpslibmath_la-psSpline.o psSpline.c > coverage-math.spline
+gcov -f --object-file ./.libs/libpslibmath_la-psStats.o psStats.c > coverage-math.stats
+gcov -f --object-file ./.libs/libpslibmath_la-psUnaryOp.o psUnaryOp.c > coverage-math.unaryOp
+gcov -f --object-file ./.libs/libpslibmath_la-psVectorSmooth.o psVectorSmooth.c > coverage-math.vectorSmooth
+mv coverage-*.* ../../Test_Coverage/
+cd ../mathtypes
+gcov -f --object-file ./.libs/libpslibmathtypes_la-psImage.o psImage.c > coverage-mathtypes.image
+gcov -f --object-file ./.libs/libpslibmathtypes_la-psScalar.o psScalar.c > coverage-mathtypes.scalar
+gcov -f --object-file ./.libs/libpslibmathtypes_la-psVector.o psVector.c > coverage-mathtypes.vector
+mv coverage-*.* ../../Test_Coverage/
+cd ../sys
+gcov -f --object-file ./.libs/libpslibsys_la-psAbort.o psAbort.c > coverage-sys.abort
+gcov -f --object-file ./.libs/libpslibsys_la-psConfigure.o psConfigure.c > coverage-sys.configure
+gcov -f --object-file ./.libs/libpslibsys_la-psError.o psError.c > coverage-sys.error
+gcov -f --object-file ./.libs/libpslibsys_la-psErrorCodes.o psErrorCodes.c > coverage-sys.errorCodes
+gcov -f --object-file ./.libs/libpslibsys_la-psLine.o psLine.c > coverage-sys.line
+gcov -f --object-file ./.libs/libpslibsys_la-psLogMsg.o psLogMsg.c > coverage-sys.logMsg
+gcov -f --object-file ./.libs/libpslibsys_la-psMemory.o psMemory.c > coverage-sys.memory
+gcov -f --object-file ./.libs/libpslibsys_la-psString.o psString.c > coverage-sys.string
+gcov -f --object-file ./.libs/libpslibsys_la-psTrace.o psTrace.c > coverage-sys.trace
+mv coverage-*.* ../../Test_Coverage/
+cd ../types
+gcov -f --object-file ./.libs/libpslibtypes_la-psArguments.o psArguments.c > coverage-types.arguments
+gcov -f --object-file ./.libs/libpslibtypes_la-psArray.o psArray.c > coverage-types.array
+gcov -f --object-file ./.libs/libpslibtypes_la-psBitSet.o psBitSet.c > coverage-types.bitSet
+gcov -f --object-file ./.libs/libpslibtypes_la-psHash.o psHash.c > coverage-types.hash
+gcov -f --object-file ./.libs/libpslibtypes_la-psList.o psList.c > coverage-types.list
+gcov -f --object-file ./.libs/libpslibtypes_la-psLookupTable.o psLookupTable.c > coverage-types.lookupTable
+gcov -f --object-file ./.libs/libpslibtypes_la-psMetadata.o psMetadata.c > coverage-types.metadata
+gcov -f --object-file ./.libs/libpslibtypes_la-psMetadataConfig.o psMetadataConfig.c > coverage-types.metadataConfig
+gcov -f --object-file ./.libs/libpslibtypes_la-psMetadataItemCompare.o psMetadataItemCompare.c > coverage-types.metadataItemCompare
+gcov -f --object-file ./.libs/libpslibtypes_la-psMetadataItemParse.o psMetadataItemParse.c > coverage-types.metadataItemParse
+gcov -f --object-file ./.libs/libpslibtypes_la-psPixels.o psPixels.c > coverage-types.pixels
+mv coverage-*.* ../../Test_Coverage/
+cd ../xml
+gcov -f --object-file ./.libs/libpslibxml_la-psXML.o psXML.c > coverage-xml.xml
+mv coverage-*.* ../../Test_Coverage/
+cd ../../
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/.cvsignore	(revision 22158)
@@ -0,0 +1,7 @@
+temp
+Makefile
+Makefile.in
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/Makefile.am	(revision 22158)
@@ -0,0 +1,12 @@
+SUBDIRS = tap pstap $(SRCDIRS)
+
+TESTS = test.pl
+
+EXTRA_DIST = test.pl
+
+# XXX the *.out and *.config files should not be written into this directory in
+# the first place
+CLEANFILES = core core.* *~ *.out *.config *.fits *.md tmpImages/* tst_psTrace02_OUT
+
+test: check
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/TABLE-SDRS-CH06-DataManip
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/TABLE-SDRS-CH06-DataManip	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/TABLE-SDRS-CH06-DataManip	(revision 22158)
@@ -0,0 +1,441 @@
+-------------------------------------------------------------------------------
+			Unallowed	Types	Sizes	Level	Algorithm
+			Params				of
+							Testing
+-------------------------------------------------------------------------------
+psVectorSort()
+			10		10	10	10
+    in mathtypes/tap_psVectorSort.c
+    Many more types are tested successfully than required in the SDRS.
+psVectorSortIndex()
+			10		10	10	10
+    in mathtypes/tap_psVectorSortIndex.c
+    Many more typres are tested successfully than required in the SDRS.
+psVectorStats()		5		10	5	5
+    files: math/tap_psStats00.c - math/tap_psStats09.c
+    Must review these files more.
+    More extensie robust stats?
+    They use preset answers
+    Types should be supported (from SDRS):
+	psS8, psU16, psF32, psF64
+psStatsAlloc()
+			na		na	na	10
+psStatsOptionFromString()
+			10		na	na	10	na
+psStatsOptionToString()
+			10		na	na	10	na
+psStatsFromString()
+			NONE		NONE	NONE	NONE
+psStatsToString()
+			NONE		NONE	NONE	NONE
+psStatsSingleOption()
+			NONE		NONE	NONE	NONE
+psStatsGetValue()
+			NONE		NONE	NONE	NONE
+psVectorCountPixelMask()10		10	10	10	na
+    mathtypes/tst_psVector.c
+psHistogramAlloc()
+			10		na	10	10
+psHistogramAllocGeneric()
+			10		na	10	10
+psVectorHistogram()
+			8		na	10	8
+psPolynomial1DAlloc()
+			10		10	10	10	na
+    math/tap_psPolynomial.c
+psPolynomial2DAlloc()
+			10		10	10	10	na
+    math/tap_psPolynomial.c
+psPolynomial3DAlloc()
+			10		10	10	10	na
+    math/tap_psPolynomial.c
+psPolynomial4DAlloc()
+			10		10	10	10	na
+    math/tap_psPolynomial.c
+psPolynomial1DEval()
+			10		10	1	8
+    We only allocate polynomials with 4 terms
+    We should ensure that asking for negative number of terms fails nicely.
+    The test uses precomputed results.
+psPolynomial2DEval()
+			10		10	1	5
+    We only allocate polynomials with 4 terms
+	Must vary x,y number of terms.
+    The test uses precomputed results.
+psPolynomial3DEval()
+			10		10	1	5
+    We only allocate polynomials with 4 terms
+	Must vary x,y,z number of terms.
+    The test uses precomputed results.
+psPolynomial4DEval()
+			10		10	1	5
+    We only allocate polynomials with 4 terms
+	Must vary w,x,y,z number of terms.
+    The test uses precomputed results.
+psPolynomial1DEvalVector()
+			10		10	5	9
+psPolynomial2DEvalVector()
+			10		10	5	9
+psPolynomial3DEvalVector()
+			10		10	5	9
+psPolynomial4DEvalVector()
+			10		10	5	9
+psPolynomial1DfromMetadata()10		10	10	10	na
+    types/tap_psMetadata_polynomials.c
+psPolynomial2DfromMetadata()10		10	10	10	na
+    types/tap_psMetadata_polynomials.c
+psPolynomial3DfromMetadata()10		10	10	10	na
+    types/tap_psMetadata_polynomials.c
+psPolynomial4DfromMetadata()10		10	10	10	na
+    types/tap_psMetadata_polynomials.c
+psPolynomial1DtoMetadata()10		10	10	10	na
+    types/tap_psMetadata_polynomials.c
+psPolynomial2DtoMetadata()10		10	10	10	na
+    types/tap_psMetadata_polynomials.c
+psPolynomial3DtoMetadata()10		10	10	10	na
+    types/tap_psMetadata_polynomials.c
+psPolynomial4DtoMetadata()10		10	10	10	na
+    types/tap_psMetadata_polynomials.c
+psSpline1DAlloc()
+			na		na	na	10
+psSpline1DEval()
+			8		na	5	8
+    There should be a PS_ASSERT_PTR_NON_NULL(spline->knots) before we
+    assert type:
+        PS_ASSERT_PTR_NON_NULL(spline, NULL);
+        PS_ASSERT_VECTOR_TYPE(spline->knots, PS_TYPE_F32, NULL);
+psSpline1DEvalVector()
+			8		na	5	8
+psGaussian()		na		na	na	5	na
+    math/tap_psFunc01.c
+    This test merely compares psGaussian results agaisnt preset vectors.
+    Add tests to generate a vector of data, then run psVectorStats() on it.
+psMinimizationAlloc()
+			10		10	10	10
+    Completely tested.
+psMinConstrainAlloc()
+			10		10	10	10
+    Completely tested, however the SDRS completely disagrees with the code.
+    What happened to the following members?
+        psVector *paramMax;
+        psVector *paramMin;
+        psVector *paramDelta;
+    And a new member:
+	psMinimizeLMLimitFunc checkLimits;
+psMinimizeLMChi2()
+			5		3	1	1
+    XXX: Add tests for
+        covar arg set to non-NULL
+        constraint set to non-NULL
+	Set x->vectors to NULL, or use wrong types
+	yWt (errors) vector set to incorrect size, type.
+psMinimizeGaussNewtonDelta()0		0	0	0	0
+    NONE
+psMinimizePowell()	0		0	0	0	na
+    The bad param tests are all commented out due to seg faults
+    Basically, everthing is commented out due to seg faults
+psMinimizeChi2Powell()	0		0	0	0	0
+    NONE
+psVectorFitPolynomial1D()
+			10		10	7	9
+    Maybe vary the poly orders.
+    4D has some tests that are failing, but should not be.
+psVectorFitPolynomial2D()
+			10		10	7	9
+    DITTO
+psVectorFitPolynomial3D()
+			10		10	7	9
+    DITTO
+psVectorFitPolynomial4D()
+			10		10	7	9
+    DITTO
+psVectorClipFitPolynomial1D()
+			10		10	7	9
+    DITTO
+psVectorClipFitPolynomial2D()
+			10		10	7	9
+    DITTO
+psVectorClipFitPolynomial3D()
+			10		10	7	9
+    DITTO
+psVectorClipFitPolynomial4D()
+			10		10	7	9
+    DITTO
+psVectorFitSpline1D()	0		2	10	5	5
+psImageSubset()		10		2	1	10	na
+    in imageops/tap_psImageStructManip.c
+    A single 128x256 image of type U32 is tested.
+psImageCopy()		10		10	8	10	na
+    in imageops/tap_psImageStructManip.c
+    A single input 128x256 image of type F32 is tested, however it's
+	converted to all other allowed types.
+psImageTrim()		10		2	4	10	na
+    in imageops/tap_psImageStructManip.c
+    A single 200x300 image of type F32 is tested.
+psImageFlip()		0		0	0	0	0
+    NONE
+psImageRow()		10		10	2	10	na
+    in imageops/tap_psImageStructManip.c
+psImageCol()		10		10	2	10	na
+    in imageops/tap_psImagePixelExtract.c
+    A single 3x3 image is used
+psImageSlice()		10		10	10	10	na
+    in imageops/tap_psImagePixelExtract.c
+    Spend more time determining if all input params are tested, and all combos
+	as well.
+    SDRS seems to be out of date.
+psImageCut()		5		2	2	10	na
+    in imageops/tap_psImagePixelExtract.c
+    SDRS seems to be incomplete and lots of unallowed input param combos are
+	probably not tested.
+    A single 200x300 input image of type F32 is tested.
+psImageRadialCut()	10		2	2	10	na
+    in imageops/tap_psImagePixelExtract.c
+    A single 200x300 input image of type F32 is tested.
+psImageRebin()		10		10	2	10	na
+    In imageops/tap_psImageGeomManip.c
+    Only 16x16 images are rebinned into 4x4 images.  Try NxM.
+psImageResample()	10		2	2	10	na
+    In imageops/tap_psImageGeomManip.c
+    A single 80x60 input image of type F32 is used.
+psImageRotate()		8		5	2	10	na
+    In imageops/tap_psImageGeomManip.c
+    A single 64x64 input image is used
+    Only types F32 and S16 are tested
+    Image values are compared against a stored FITS file.  Where did the file
+	come from?
+    There is a potential autoconf directory problem with reading the FITS file.
+psImageShift()		10		5	5	10	na
+    In imageops/tap_psImageGeomManip.c
+    Only 64x128 images are used.
+    Only types F32 and S16 are tested
+psImageRoll()		10		10	2	10	na
+    In imageops/tap_psImageGeomManip.c
+    Only NxN square images are tested.
+psImageTransform()	0		2	2	5	na
+    In imageops/tap_psImageGeomManip.c
+    A single 16x32 input image of type F32 is used
+    No attempt at unallowed input params, types, or sizes.
+psImageUnbin()		0		0	0	0	0
+    NONE
+psImageStats()		10		2	2	10	na
+    In imageops/tap_psImageStats.c
+    A single 10x10 input image of type F32 is used
+    subRegion tests are skipped because of a seg-fault
+psImageHistogram()	10		2	4	10	na
+    In imageops/tap_psImageStats.c
+    A single 16x15 input image of type F32 is used
+    numBins should be varied
+psImageCountPixelMask()	10		10	2	10	na
+    In imageops/tap_psImageStats.c
+    A single 10x10 input mask images used
+psImageFitPolynomial()	10		2	4	10	5
+    In imageops/tap_psImageStats.c
+    Only 10x10 images are used.
+    Only F32 and F64 are tested.
+psImageEvalPolynomial()	10		2	4	10	5
+    In imageops/tap_psImageStats.c
+    Only 10x10 images are used.
+    Only F32 and F64 are tested.
+psImagePixelInterpolate()
+			2		2	2	8	8
+    There's old code in imageops/tap_psImageInterpolate.c
+    Extensive code in mathtypes/tap_psImageInterpolate.c
+    A single 32x32 input image of type F32 is used
+    Merge param tests from imageops/tap_psImageInterpolate.c
+psImageBackground()	0		0	0	0	0
+    NONE
+psImageClip()		8		10	2	10	na
+    imageops/tap_psImagePixelManip.c
+    Only 256-128 images are tested
+    All types are tested
+    Should block off some individual tests
+psImageClipComplexRegion()0		0	0	0	0
+    NONE in tap files, there is an old imageops/tst_psImagePixelManip.c
+    Is this still in the new SDRS?
+psImageClipNaN()	8		5	2	10	na
+    imageops/tap_psImagePixelManip.c
+    Only 256-128 images are tested
+    Only F32 and F64 are tested
+    Should block off some individual tests
+psImageOverlaySection()	10		10	2	10	na
+    imageops/tap_psImagePixelManip.c
+    Only 128-by-256 images are tested
+    All types are tested
+    Should block off some individual tests
+psImageBicubeFit()	0		0	0	0	0
+    NONE
+psImageBicubeMin()	0		0	0	0	0
+    NONE
+psImageJpegColormapAlloc()
+			0		0	0	0	0
+    NONE
+psImageJpegColormapSet()0		0	0	0	0
+    NONE
+psImageJpeg()		0		0	0	0	0
+    NONE
+psImageGrowMask()	10		10	2	10	na
+    In imageops/tap_psImageMaskOps.c
+    psImageGrowMask() is currently growing a circular mask when the SDRS specs
+	a square mask.
+    All mask images are NxN
+psPixelsToMask()	10		10	10	2	na
+    In types/tap_psPixels_all.c
+    We never test pixels in the output image mask
+psPixelsFromMask()	10		10	2	2	na
+    In types/tap_psPixels_all.c
+    We never test pixels in the output psPixels
+    Should better separate individual tests
+psPixelsConcatenate()	?		?	?	?	na
+    This is not in the SDRS
+    We never test pixels in the output psPixels
+psImageMaskRegion()	5		10	10	10	na
+    In imageops/tap_psImageMaskOps.c
+    Generate tests with NULL input, bad input type, bad psRegion
+psImageKeepRegion()
+    In imageops/tap_psImageMaskOps.c
+    Generate tests with NULL input, bad input type, bad psRegion
+psImageMaskCircle()	5		10	2	5	na
+    In imageops/tap_psImageMaskOps.c
+    Generate tests with NULL input, bad input type, bad radius, etc
+    Seg faults are skipped for Nx1 and 1xN images
+psImageKeepCircle()	5		10	2	5	na
+    In imageops/tap_psImageMaskOps.c
+    Generate tests with NULL input, bad input type, bad radius, etc
+    Seg faults are skipped for Nx1 and 1xN images
+psBinaryOp()		?		?	?	?	?
+    Extensive tests in tap_psMatrixVectorArithmetic:01-04.c
+    Must review further.
+    Some are seg-faulting and failing to compile, so I removed from Makefile.am
+psUnaryOp()		?		?	?	?	?
+    Extensive tests in tap_psMatrixVectorArithmetic:01-04.c
+    Must review further.
+    Some are seg-faulting and failing to compile, so I removed from Makefile.am
+psMatrixLUD()		0		5	2	5	3
+    math/tap_psMatrix03.c
+    The NULL image argument seg-faults
+    Only 3x3 matrices, F32 and F64, are used.
+    Fairly low-level of testing
+psMatrixLUSolve()	0		5	2	5	3
+    math/tap_psMatrix03.c
+    The NULL image argument seg-faults
+    The NULL vector argument seg-faults
+    Only 3x3 matrices, F32 and F64, are used.
+    Fairly low-level of testing
+psMatrixGJSolve()	0		0	0	0	0
+    NONE
+psMatrixInvert()	0		5	2	5	3
+    math/tap_psMatrix04.c
+    Only 3x3 matrices, F32 and F64, are used.
+    The NULL image argument seg-faults
+    The NULL vector argument seg-faults
+    Fairly low-level of testing
+psMatrixDeterminant()	10		10	2	5	na
+    math/tap_psMatrix04.c
+    Only 3x3 matrices, F32 and F64, are used.
+    Fairly low-level of testing
+psMatrixMultiply()	0		5	2	5	na
+    math/tap_psMatrix05.c
+    Only 3x3 matrices, F32 and F64, are used.
+    No tests when args have different types.
+    No tests for bad input params.
+psMatrixTranspose()	10		10	4	8	na
+    math/tap_psMatrix01.c
+    Probably should N-by-M sizes
+    in file tap_psMatrix01.c
+    in file tap_psMatrix02.c
+	A few other tests with bad input parameters
+psMatrixEigenvectors()	0		5	2	5	na
+    math/tap_psMatrix06.c
+    Only 4x4 matrices, F32 and F64, are used.
+    No tests when args have different types.
+    No tests for bad input params.
+psMatrixToVector()	0		5	2	5	na
+    math/tap_psMatrix07.c
+    Only 1x3 and 3x1 matrices are used.
+    Only F32 and F64 types are used.
+    Lots of bad param tests are commented out due to seg faults
+psVectorToMatrix()	0		5	2	5	na
+    math/tap_psMatrix07.c
+    no bad param tests
+    Only 3x1 matrices are used.
+    Only F32 and F64 types are used.
+psSparseAlloc()
+			na		na	10	10	na
+psSparseMatrixElement()	0		na	na	na	na
+    math/tap_psSparse.c
+    This is not tested individually, however it is tested implictly.
+    Must write individual tests for it.
+psSparseVectorElement()	1		1	1	1	na
+    math/tap_psSparse.c
+    This is not tested individually, however it is tested implictly.
+    Must write individual tests for it.
+psSparseVectorElement()	1		1	1	1	na
+    math/tap_psSparse.c
+    This is not in the SDRS
+    This is not tested individually, however it is tested implictly.
+    Must write individual tests for it.
+psSparseMatrixTimesVector()1		1	1	1	na
+    math/tap_psSparse.c
+    This is not tested individually, however it is tested implictly.
+    Must write individual tests for it.
+psSparseResort()	1		1	1	1	na
+    math/tap_psSparse.c
+    This is not tested individually, however it is tested implictly.
+    Must write individual tests for it.
+psSparseSolve()		0		2	2	4	na
+    math/tap_psSparse.c
+    Must add param, types, and size tests.
+psVectorForwardFFT()	10		5	10	10	na
+    fft/tap_psVectorFFT.c
+    Add F64 tests
+psVectorBackwardFFT()	0		2	2	2	na
+    fft/tap_psVectorFFT.c
+    This is only tested implictly, once, along with the forward FFT test.
+psVectorPowerSpectrum()	0		0	0	0	0
+    fft/tst_psVectorFFT.c
+        There do not appear to be any tap tests.  Must look thru old files.
+psVectorComplexMultiply()0		0	0	0	0
+    NONE
+psImageForwardFFT()	10		5	10	10	na
+    fft/tap_psImageFFT.c
+    Need both F32 and F64 tests?
+psImageBackwardFFT()	0		2	2	2	na
+    fft/tap_psImageFFT.c
+    Need both F32 and F64 tests?
+    This is only tested implictly, once, along with the forward FFT test.
+psImagePowerSpectrum()	0		0	0	0	0
+    fft/tst_psImageFFT.c
+        There do not appear to be any tap tests.  Must look thru old files.
+psImageComplexMultiply()0		0	0	0	0
+    NONE
+psImageSmooth()		0		10	10	10	na
+    No bad param tests.
+    Don't you had bad param test lying around somewhere?
+psKernelAlloc()		8		na	na	8	na
+    imageops/tap_psImageConvolve.c
+    Consolidate with tap_psImageConvolve2.c
+psKernelGenerate()	8		5	5	4	na
+    imageops/tap_psImageConvolve.c
+    Some tests are skipped because of seg faults
+psImageConvolveDirect()	0		2	2	2	na
+    imageops/tap_psImageConvolve.c
+    These are completely commented away in tap_psImageConvolve.c and only
+	lightly tested in tap_psImageConvolve2.c
+psImageConvolveFFT()	0		0	0	2
+    imageops/tap_psImageConvolve2.c
+    Only lightly tested in tap_psImageConvolve2.c
+psRandomAlloc()		10		na	na	10	na
+    math/tap_psRandom.c
+psRandomReset()		5		na	na	8	na
+    math/tap_psRandom.c
+    The bad param test is commented out
+psRandomUniform()	8		na	na	10	na
+psRandomGaussian()	8		na	na	10	na
+psRandomPoisson()	8		na	na	10	na
+psEllipseMomentsToAxes()	0	0	0	0	0
+    NONE
+psEllipseAxesToShape()	0	0	0	0	0
+    NONE
+psEllipseShapeToAxes()	0	0	0	0	0
+    NONE
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/.cvsignore	(revision 22158)
@@ -0,0 +1,33 @@
+.deps
+.libs
+Makefile
+Makefile.in
+pslib.config
+temp
+test.psTime.config1
+test.psTime.config2
+test.psTime.config3
+test.psTime.config4
+test.ser7.dat
+tst_psCoord
+tst_psCoord01
+tst_psSphereOps
+tst_psTime_01
+tst_psTime_02
+tst_psTime_03
+tst_psTime_04
+tst_psEarthOrientation
+tst_psCoord02
+*.bb
+*.bbg
+*.da
+gmon.out
+tap_psEarthOrientation_corrections
+tap_psEarthOrientation_motion
+tap_psSphereOps_all
+tap_psCoord
+tap_psCoord02
+tap_psTime_01
+tap_psTime_02
+tap_psTime_03
+tap_psTime_04
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/Makefile.am	(revision 22158)
@@ -0,0 +1,70 @@
+AM_CPPFLAGS = \
+	$(SRCINC) \
+	-I$(top_srcdir)/test/tap/src \
+	-I$(top_srcdir)/test/pstap/src \
+	$(PSLIB_CFLAGS)
+AM_LDFLAGS = \
+	$(top_builddir)/src/libpslib.la  \
+	$(top_builddir)/test/tap/src/libtap.la \
+	$(top_builddir)/test/pstap/src/libpstap.la \
+	$(PSLIB_LIBS)
+
+TEST_PROGS = \
+	tap_psSphereOps_all \
+	tap_psEarthOrientation_motion \
+	tap_psEarthOrientation_corrections \
+	tap_psCoord \
+	tap_psCoord02 \
+	tap_psTime_01 \
+	tap_psTime_02 \
+	tap_psTime_03 \
+	tap_psTime_04
+
+if BUILD_TESTS
+bin_PROGRAMS = $(TEST_PROGS)
+TESTS = $(TEST_PROGS)
+else
+check_PROGRAMS = $(TEST_PROGS)
+endif
+
+EXTRA_DIST = \
+	data/psTime.config.template \
+	data/test.psTime.config1.template \
+	data/test.psTime.config2.template \
+	data/test.psTime.config3.template \
+	data/test.psTime.config4.template \
+	data/test.ser7.dat
+
+tmp_files = \
+	pslib.config \
+	test.psTime.config1 \
+	test.psTime.config2 \
+	test.psTime.config3 \
+	test.psTime.config4 \
+	test.ser7.dat
+
+CLEANFILES = $(tmp_files) core core.* *~ *.bb *.bbg *.da gmon.out
+
+tests: $(check_PROGRAMS)
+	$(top_srcdir)/test/test.pl
+
+
+pslib.config: $(top_srcdir)/etc/pslib.config.template
+	$(PERL) -pe 's|DATADIR|$(top_srcdir)/share|' $? > $@
+
+test.psTime.config1: $(srcdir)/data/test.psTime.config1.template
+	cp $? $@
+
+test.psTime.config2: $(srcdir)/data/test.psTime.config2.template
+	$(PERL) -pe 's|PREFIX|$(top_srcdir)|' $? > $@
+
+test.psTime.config3: $(srcdir)/data/test.psTime.config3.template
+	$(PERL) -pe 's|PREFIX|$(top_srcdir)|' $? > $@
+
+test.psTime.config4: $(srcdir)/data/test.psTime.config4.template
+	cp $? $@
+
+test.ser7.dat: $(srcdir)/data/test.ser7.dat
+	cp $? $@
+
+test: check
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/data/psTime.config.template
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/data/psTime.config.template	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/data/psTime.config.template	(revision 22158)
@@ -0,0 +1,23 @@
+# This configuration file specifies values required for time calculations by psLib.
+psLib.time.tables.dir STR PREFIX/share                                                  # Directory for time tables
+psLib.time.tables.n S32 4                                                               # Number of time tables
+psLib.time.tables.files STR ser7.dat eopc01_1900_2004.dat finals_all.dat tai_utc.dat    # These are the table file names
+@psLib.time.tables.from F64 53258.0, 15020.0, 41684.0 2437300.5                         # Valid from these dates
+@psLib.time.tables.to F64 53622.0, 53258.0, 53627.0 2451179.5                           # Valid to these dates
+psLib.time.before.xp F64 0.0                                                            # Value of XP for before the earliest MJD
+psLib.time.before.yp F64 0.0                                                            # Value of YP for before the earliest MJD
+psLib.time.before.dut F64 0.0                                                           # Value of UT1-UTC for before the earliest MJD
+
+# Now follows formulae for predicting ahead of the most recent available table entry.
+# xp = [0] + [1]*cos A + [2]*sin A + [3]*cos C + [4]*sin C
+# yp = [0] + [1]*cos A + [2]*sin A + [3]*cos C + [4]*sin C
+# A = 2*pi*(MJD - pslib.time.predict.mjd)/365.25
+# C = 2*pi*(MJD - pslib.time.predict.mjd)/435.0
+# dut = ut1-utc = [0] + [1]*(MJD - [2]) - (UT2-UT1)
+# ut2-ut1 = 0.022 sin(2*pi*T) - 0.012 cos(2*pi*T) - 0.006 sin(4*pi*T) + 0.007 cos(4*pi*T)
+# T = 2000.0 + (MJD - 51544.03)/365.2422
+@psLib.time.predict.xp F64 0.0569, 0.0555, -0.0200, 0.0513, 0.1483
+@psLib.time.predict.yp F64 0.3498, -0.0176, -0.0498, 0.1483, -0.0513
+psLib.time.predict.mjd F64 53257.0
+@psLib.time.predict.dut F64 -0.4944, -0.00023, 53262.0
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/data/test.psTime.config1.template
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/data/test.psTime.config1.template	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/data/test.psTime.config1.template	(revision 22158)
@@ -0,0 +1,23 @@
+# This configuration file specifies values required for time calculations by psLib.
+psLib.time.tables.dir STR bogus                                                    # Directory for time tables
+psLib.time.tables.n S32 4                                                               # Number of time tables
+psLib.time.tables.files STR ser7.dat eopc01_1900_2004.dat finals_all.dat tai_utc.dat    # These are the table file names
+@psLib.time.tables.from F64 53258.0, 15020.0, 41684.0 2437300.5                         # Valid from these dates
+@psLib.time.tables.to F64 53622.0, 53258.0, 53627.0 2451179.5                           # Valid to these dates
+psLib.time.before.xp F64 0.0                                                            # Value of XP for before the earliest MJD
+psLib.time.before.yp F64 0.0                                                            # Value of YP for before the earliest MJD
+psLib.time.before.dut F64 0.0                                                           # Value of UT1-UTC for before the earliest MJD
+
+# Now follows formulae for predicting ahead of the most recent available table entry.
+# xp = [0] + [1]*cos A + [2]*sin A + [3]*cos C + [4]*sin C
+# yp = [0] + [1]*cos A + [2]*sin A + [3]*cos C + [4]*sin C
+# A = 2*pi*(MJD - pslib.time.predict.mjd)/365.25
+# C = 2*pi*(MJD - pslib.time.predict.mjd)/435.0
+# dut = ut1-utc = [0] + [1]*(MJD - [2]) - (UT2-UT1)
+# ut2-ut1 = 0.022 sin(2*pi*T) - 0.012 cos(2*pi*T) - 0.006 sin(4*pi*T) + 0.007 cos(4*pi*T)
+# T = 2000.0 + (MJD - 51544.03)/365.2422
+@psLib.time.predict.xp F64 0.0569, 0.0555, -0.0200, 0.0513, 0.1483
+@psLib.time.predict.yp F64 0.3498, -0.0176, -0.0498, 0.1483, -0.0513
+psLib.time.predict.mjd F64 53257.0
+@psLib.time.predict.dut F64 -0.4944, -0.00023, 53262.0
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/data/test.psTime.config2.template
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/data/test.psTime.config2.template	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/data/test.psTime.config2.template	(revision 22158)
@@ -0,0 +1,23 @@
+# This configuration file specifies values required for time calculations by psLib.
+psLib.time.tables.dir STR PREFIX/share                                                  # Directory for time tables
+psLib.time.tables.n S32 4                                                               # Number of time tables
+psLib.time.tables.files STR eopc01_1900_2004.dat finals_all.dat tai_utc.dat    # These are the table file names
+@psLib.time.tables.from F64 53258.0, 15020.0, 41684.0 2437300.5                         # Valid from these dates
+@psLib.time.tables.to F64 53622.0, 53258.0, 53627.0 2451179.5                           # Valid to these dates
+psLib.time.before.xp F64 0.0                                                            # Value of XP for before the earliest MJD
+psLib.time.before.yp F64 0.0                                                            # Value of YP for before the earliest MJD
+psLib.time.before.dut F64 0.0                                                           # Value of UT1-UTC for before the earliest MJD
+
+# Now follows formulae for predicting ahead of the most recent available table entry.
+# xp = [0] + [1]*cos A + [2]*sin A + [3]*cos C + [4]*sin C
+# yp = [0] + [1]*cos A + [2]*sin A + [3]*cos C + [4]*sin C
+# A = 2*pi*(MJD - pslib.time.predict.mjd)/365.25
+# C = 2*pi*(MJD - pslib.time.predict.mjd)/435.0
+# dut = ut1-utc = [0] + [1]*(MJD - [2]) - (UT2-UT1)
+# ut2-ut1 = 0.022 sin(2*pi*T) - 0.012 cos(2*pi*T) - 0.006 sin(4*pi*T) + 0.007 cos(4*pi*T)
+# T = 2000.0 + (MJD - 51544.03)/365.2422
+@psLib.time.predict.xp F64 0.0569, 0.0555, -0.0200, 0.0513, 0.1483
+@psLib.time.predict.yp F64 0.3498, -0.0176, -0.0498, 0.1483, -0.0513
+psLib.time.predict.mjd F64 53257.0
+@psLib.time.predict.dut F64 -0.4944, -0.00023, 53262.0
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/data/test.psTime.config3.template
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/data/test.psTime.config3.template	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/data/test.psTime.config3.template	(revision 22158)
@@ -0,0 +1,23 @@
+# This configuration file specifies values required for time calculations by psLib.
+psLib.time.tables.dir STR PREFIX/share                                                  # Directory for time tables
+psLib.time.tables.n S32 4                                                               # Number of time tables
+psLib.time.tables.files STR ser7.dat eopc01_1900_2004.dat finals_all.dat tai_utc.dat    # These are the table file names
+@psLib.time.tables.from F64 15020.0, 41684.0 2437300.5                         # Valid from these dates
+@psLib.time.tables.to F64 53622.0, 53258.0, 53627.0 2451179.5                           # Valid to these dates
+psLib.time.before.xp F64 0.0                                                            # Value of XP for before the earliest MJD
+psLib.time.before.yp F64 0.0                                                            # Value of YP for before the earliest MJD
+psLib.time.before.dut F64 0.0                                                           # Value of UT1-UTC for before the earliest MJD
+
+# Now follows formulae for predicting ahead of the most recent available table entry.
+# xp = [0] + [1]*cos A + [2]*sin A + [3]*cos C + [4]*sin C
+# yp = [0] + [1]*cos A + [2]*sin A + [3]*cos C + [4]*sin C
+# A = 2*pi*(MJD - pslib.time.predict.mjd)/365.25
+# C = 2*pi*(MJD - pslib.time.predict.mjd)/435.0
+# dut = ut1-utc = [0] + [1]*(MJD - [2]) - (UT2-UT1)
+# ut2-ut1 = 0.022 sin(2*pi*T) - 0.012 cos(2*pi*T) - 0.006 sin(4*pi*T) + 0.007 cos(4*pi*T)
+# T = 2000.0 + (MJD - 51544.03)/365.2422
+@psLib.time.predict.xp F64 0.0569, 0.0555, -0.0200, 0.0513, 0.1483
+@psLib.time.predict.yp F64 0.3498, -0.0176, -0.0498, 0.1483, -0.0513
+psLib.time.predict.mjd F64 53257.0
+@psLib.time.predict.dut F64 -0.4944, -0.00023, 53262.0
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/data/test.psTime.config4.template
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/data/test.psTime.config4.template	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/data/test.psTime.config4.template	(revision 22158)
@@ -0,0 +1,23 @@
+# This configuration file specifies values required for time calculations by psLib.
+psLib.time.tables.dir STR .                                                             # Directory for time tables
+psLib.time.tables.n S32 1                                                               # Number of time tables
+psLib.time.tables.files STR test.ser7.dat                                               # This the table file
+@psLib.time.tables.from F64 53258.0                                                     # Valid from this date
+@psLib.time.tables.to F64 53622.0                                                       # Valid to this date
+psLib.time.before.xp F64 0.0                                                            # Value of XP for before the earliest MJD
+psLib.time.before.yp F64 0.0                                                            # Value of YP for before the earliest MJD
+psLib.time.before.dut F64 0.0                                                           # Value of UT1-UTC for before the earliest MJD
+
+# Now follows formulae for predicting ahead of the most recent available table entry.
+# xp = [0] + [1]*cos A + [2]*sin A + [3]*cos C + [4]*sin C
+# yp = [0] + [1]*cos A + [2]*sin A + [3]*cos C + [4]*sin C
+# A = 2*pi*(MJD - pslib.time.predict.mjd)/365.25
+# C = 2*pi*(MJD - pslib.time.predict.mjd)/435.0
+# dut = ut1-utc = [0] + [1]*(MJD - [2]) - (UT2-UT1)
+# ut2-ut1 = 0.022 sin(2*pi*T) - 0.012 cos(2*pi*T) - 0.006 sin(4*pi*T) + 0.007 cos(4*pi*T)
+# T = 2000.0 + (MJD - 51544.03)/365.2422
+@psLib.time.predict.xp F64 0.0569
+@psLib.time.predict.yp F64 0.3498
+psLib.time.predict.mjd F64 53257.0
+@psLib.time.predict.dut F64 -0.4944
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/data/test.ser7.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/data/test.ser7.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/data/test.ser7.dat	(revision 22158)
@@ -0,0 +1,380 @@
+#  ser7.dat
+#
+#  This file comes from http://maia.usno.navy.mil (Click on General Information about Earth Orientation). This
+#  file may also be directly downloaded from ftp://maia.usno.navy.mil/ser7/ser7.dat. See readme.ser7 (located
+#  in the psLib/data directory) for details.
+#
+#  @author Ross Harman, MHPCC
+#
+#  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+#  @date $Date: 2005-07-13 02:46:58 $
+#
+#
+#        MJD         PM-x        PM-y       UT1-UTC
+#      (days)      (arcsec)    (arcsec)      (sec)
+        psF64        psF64       psF64       psF64
+        53yyy244       0.1377      0.5027     -0.45210
+        53245       0.1394      0.5015     -0.45190
+        53246       0.1411      0.5002     -0.45197
+        53247       0.1429      0.4989     -0.45234
+        53248       0.1447      0.4976     -0.45293
+        53249       0.1465      0.4962     -0.45361
+        53250       0.1484      0.4948     -0.45424
+        53251       0.1503      0.4934     -0.45476
+        53252       0.1521      0.4920     -0.45512
+        53253       0.1540      0.4905     -0.45530
+        53254       0.1558      0.4890     -0.45531
+        53255       0.1577      0.4874     -0.45519
+        53256       0.1595      0.4859     -0.45497
+        53257       0.1613      0.4843     -0.45474
+        53258       0.1631      0.4827     -0.45458
+        53259       0.1649      0.4810     -0.45456
+        53260       0.1667      0.4794     -0.45474
+        53261       0.1684      0.4777     -0.45514
+        53262       0.1701      0.4760     -0.45578
+        53263       0.1717      0.4742     -0.45660
+        53264       0.1734      0.4725     -0.45754
+        53265       0.1750      0.4707     -0.45849
+        53266       0.1765      0.4689     -0.45932
+        53267       0.1780      0.4671     -0.45996
+        53268       0.1795      0.4652     -0.46036
+        53269       0.1810      0.4634     -0.46055
+        53270       0.1824      0.4615     -0.46061
+        53271       0.1838      0.4596     -0.46068
+        53272       0.1852      0.4576     -0.46086
+        53273       0.1865      0.4557     -0.46126
+        53274       0.1878      0.4537     -0.46192
+        53275       0.1890      0.4517     -0.46280
+        53276       0.1902      0.4497     -0.46382
+        53277       0.1914      0.4477     -0.46486
+        53278       0.1925      0.4457     -0.46581
+        53279       0.1936      0.4436     -0.46658
+        53280       0.1946      0.4415     -0.46715
+        53281       0.1956      0.4394     -0.46750
+        53282       0.1966      0.4373     -0.46766
+        53283       0.1976      0.4352     -0.46772
+        53284       0.1985      0.4331     -0.46773
+        53285       0.1993      0.4309     -0.46778
+        53286       0.2001      0.4288     -0.46795
+        53287       0.2009      0.4266     -0.46830
+        53288       0.2017      0.4244     -0.46887
+        53289       0.2024      0.4222     -0.46968
+        53290       0.2031      0.4200     -0.47071
+        53291       0.2037      0.4178     -0.47191
+        53292       0.2043      0.4155     -0.47317
+        53293       0.2049      0.4133     -0.47435
+        53294       0.2054      0.4111     -0.47536
+        53295       0.2059      0.4088     -0.47610
+        53296       0.2063      0.4065     -0.47659
+        53297       0.2067      0.4042     -0.47691
+        53298       0.2071      0.4020     -0.47718
+        53299       0.2075      0.3997     -0.47755
+        53300       0.2078      0.3974     -0.47811
+        53301       0.2080      0.3951     -0.47893
+        53302       0.2083      0.3928     -0.47998
+        53303       0.2085      0.3905     -0.48119
+        53304       0.2086      0.3881     -0.48247
+        53305       0.2088      0.3858     -0.48369
+        53306       0.2089      0.3835     -0.48477
+        53307       0.2089      0.3812     -0.48565
+        53308       0.2090      0.3789     -0.48630
+        53309       0.2089      0.3765     -0.48674
+        53310       0.2089      0.3742     -0.48701
+        53311       0.2088      0.3719     -0.48718
+        53312       0.2088      0.3696     -0.48732
+        53313       0.2086      0.3672     -0.48753
+        53314       0.2085      0.3649     -0.48785
+        53315       0.2082      0.3626     -0.48835
+        53316       0.2080      0.3603     -0.48906
+        53317       0.2077      0.3579     -0.48997
+        53318       0.2074      0.3556     -0.49106
+        53319       0.2071      0.3533     -0.49226
+        53320       0.2067      0.3510     -0.49344
+        53321       0.2063      0.3487     -0.49449
+        53322       0.2059      0.3464     -0.49531
+        53323       0.2054      0.3441     -0.49585
+        53324       0.2049      0.3418     -0.49618
+        53325       0.2044      0.3396     -0.49639
+        53326       0.2038      0.3373     -0.49664
+        53327       0.2032      0.3350     -0.49705
+        53328       0.2026      0.3328     -0.49769
+        53329       0.2020      0.3305     -0.49854
+        53330       0.2013      0.3283     -0.49953
+        53331       0.2006      0.3261     -0.50058
+        53332       0.1999      0.3239     -0.50158
+        53333       0.1991      0.3217     -0.50243
+        53334       0.1983      0.3195     -0.50308
+        53335       0.1975      0.3173     -0.50350
+        53336       0.1967      0.3151     -0.50369
+        53337       0.1958      0.3130     -0.50370
+        53338       0.1949      0.3108     -0.50358
+        53339       0.1940      0.3087     -0.50342
+        53340       0.1931      0.3066     -0.50329
+        53341       0.1921      0.3045     -0.50327
+        53342       0.1911      0.3024     -0.50340
+        53343       0.1901      0.3004     -0.50372
+        53344       0.1890      0.2983     -0.50423
+        53345       0.1880      0.2963     -0.50493
+        53346       0.1869      0.2943     -0.50574
+        53347       0.1858      0.2923     -0.50660
+        53348       0.1846      0.2903     -0.50739
+        53349       0.1835      0.2883     -0.50808
+        53350       0.1823      0.2864     -0.50851
+        53351       0.1811      0.2844     -0.50870
+        53352       0.1799      0.2825     -0.50874
+        53353       0.1786      0.2807     -0.50875
+        53354       0.1773      0.2788     -0.50890
+        53355       0.1760      0.2769     -0.50927
+        53356       0.1747      0.2751     -0.50987
+        53357       0.1734      0.2733     -0.51064
+        53358       0.1720      0.2715     -0.51148
+        53359       0.1707      0.2698     -0.51228
+        53360       0.1693      0.2680     -0.51295
+        53361       0.1679      0.2663     -0.51342
+        53362       0.1664      0.2646     -0.51367
+        53363       0.1650      0.2629     -0.51371
+        53364       0.1635      0.2613     -0.51357
+        53365       0.1620      0.2596     -0.51330
+        53366       0.1605      0.2580     -0.51298
+        53367       0.1590      0.2565     -0.51268
+        53368       0.1575      0.2549     -0.51247
+        53369       0.1559      0.2534     -0.51241
+        53370       0.1543      0.2519     -0.51253
+        53371       0.1528      0.2504     -0.51283
+        53372       0.1511      0.2489     -0.51331
+        53373       0.1495      0.2475     -0.51391
+        53374       0.1479      0.2461     -0.51458
+        53375       0.1463      0.2447     -0.51522
+        53376       0.1446      0.2434     -0.51574
+        53377       0.1429      0.2420     -0.51605
+        53378       0.1412      0.2407     -0.51614
+        53379       0.1395      0.2395     -0.51605
+        53380       0.1378      0.2382     -0.51590
+        53381       0.1361      0.2370     -0.51585
+        53382       0.1344      0.2358     -0.51603
+        53383       0.1326      0.2347     -0.51648
+        53384       0.1308      0.2335     -0.51717
+        53385       0.1291      0.2324     -0.51800
+        53386       0.1273      0.2313     -0.51881
+        53387       0.1255      0.2303     -0.51951
+        53388       0.1237      0.2293     -0.52000
+        53389       0.1219      0.2283     -0.52027
+        53390       0.1200      0.2273     -0.52032
+        53391       0.1182      0.2264     -0.52018
+        53392       0.1164      0.2255     -0.51992
+        53393       0.1145      0.2246     -0.51959
+        53394       0.1126      0.2237     -0.51928
+        53395       0.1108      0.2229     -0.51905
+        53396       0.1089      0.2221     -0.51897
+        53397       0.1070      0.2213     -0.51908
+        53398       0.1051      0.2206     -0.51939
+        53399       0.1032      0.2199     -0.51987
+        53400       0.1013      0.2192     -0.52050
+        53401       0.0994      0.2186     -0.52119
+        53402       0.0975      0.2180     -0.52187
+        53403       0.0956      0.2174     -0.52246
+        53404       0.0936      0.2168     -0.52288
+        53405       0.0917      0.2163     -0.52309
+        53406       0.0898      0.2158     -0.52311
+        53407       0.0878      0.2153     -0.52305
+        53408       0.0859      0.2149     -0.52303
+        53409       0.0840      0.2144     -0.52321
+        53410       0.0820      0.2141     -0.52368
+        53411       0.0801      0.2137     -0.52444
+        53412       0.0781      0.2134     -0.52542
+        53413       0.0761      0.2131     -0.52646
+        53414       0.0742      0.2128     -0.52744
+        53415       0.0722      0.2126     -0.52822
+        53416       0.0703      0.2124     -0.52877
+        53417       0.0683      0.2122     -0.52907
+        53418       0.0663      0.2120     -0.52916
+        53419       0.0644      0.2119     -0.52910
+        53420       0.0624      0.2118     -0.52897
+        53421       0.0605      0.2117     -0.52883
+        53422       0.0585      0.2117     -0.52876
+        53423       0.0566      0.2117     -0.52882
+        53424       0.0546      0.2117     -0.52907
+        53425       0.0526      0.2118     -0.52951
+        53426       0.0507      0.2118     -0.53014
+        53427       0.0487      0.2119     -0.53091
+        53428       0.0468      0.2121     -0.53174
+        53429       0.0449      0.2122     -0.53254
+        53430       0.0429      0.2124     -0.53321
+        53431       0.0410      0.2126     -0.53368
+        53432       0.0391      0.2129     -0.53392
+        53433       0.0372      0.2131     -0.53393
+        53434       0.0352      0.2134     -0.53380
+        53435       0.0333      0.2138     -0.53366
+        53436       0.0314      0.2141     -0.53365
+        53437       0.0296      0.2145     -0.53389
+        53438       0.0277      0.2149     -0.53443
+        53439       0.0258      0.2154     -0.53526
+        53440       0.0239      0.2159     -0.53627
+        53441       0.0221      0.2164     -0.53733
+        53442       0.0202      0.2169     -0.53830
+        53443       0.0184      0.2174     -0.53908
+        53444       0.0166      0.2180     -0.53964
+        53445       0.0147      0.2186     -0.53998
+        53446       0.0129      0.2192     -0.54014
+        53447       0.0111      0.2198     -0.54018
+        53448       0.0093      0.2205     -0.54018
+        53449       0.0076      0.2212     -0.54022
+        53450       0.0058      0.2219     -0.54037
+        53451       0.0040      0.2227     -0.54069
+        53452       0.0023      0.2234     -0.54118
+        53453       0.0005      0.2242     -0.54185
+        53454      -0.0012      0.2250     -0.54266
+        53455      -0.0029      0.2258     -0.54356
+        53456      -0.0046      0.2267     -0.54447
+        53457      -0.0063      0.2276     -0.54530
+        53458      -0.0079      0.2285     -0.54598
+        53459      -0.0096      0.2294     -0.54647
+        53460      -0.0112      0.2303     -0.54675
+        53461      -0.0128      0.2313     -0.54688
+        53462      -0.0144      0.2323     -0.54699
+        53463      -0.0160      0.2333     -0.54724
+        53464      -0.0176      0.2343     -0.54775
+        53465      -0.0191      0.2353     -0.54858
+        53466      -0.0207      0.2364     -0.54970
+        53467      -0.0222      0.2375     -0.55097
+        53468      -0.0237      0.2386     -0.55228
+        53469      -0.0252      0.2397     -0.55354
+        53470      -0.0267      0.2408     -0.55465
+        53471      -0.0281      0.2420     -0.55556
+        53472      -0.0295      0.2431     -0.55626
+        53473      -0.0310      0.2443     -0.55677
+        53474      -0.0323      0.2455     -0.55715
+        53475      -0.0337      0.2468     -0.55748
+        53476      -0.0351      0.2480     -0.55785
+        53477      -0.0364      0.2493     -0.55833
+        53478      -0.0377      0.2505     -0.55899
+        53479      -0.0390      0.2518     -0.55988
+        53480      -0.0403      0.2531     -0.56095
+        53481      -0.0415      0.2545     -0.56216
+        53482      -0.0427      0.2558     -0.56347
+        53483      -0.0439      0.2572     -0.56478
+        53484      -0.0451      0.2585     -0.56599
+        53485      -0.0463      0.2599     -0.56699
+        53486      -0.0474      0.2613     -0.56769
+        53487      -0.0485      0.2627     -0.56808
+        53488      -0.0496      0.2641     -0.56824
+        53489      -0.0507      0.2656     -0.56830
+        53490      -0.0517      0.2670     -0.56839
+        53491      -0.0527      0.2685     -0.56860
+        53492      -0.0537      0.2700     -0.56897
+        53493      -0.0547      0.2714     -0.56955
+        53494      -0.0556      0.2729     -0.57032
+        53495      -0.0565      0.2744     -0.57119
+        53496      -0.0574      0.2760     -0.57204
+        53497      -0.0583      0.2775     -0.57277
+        53498      -0.0591      0.2790     -0.57329
+        53499      -0.0600      0.2806     -0.57354
+        53500      -0.0607      0.2821     -0.57350
+        53501      -0.0615      0.2837     -0.57328
+        53502      -0.0622      0.2853     -0.57298
+        53503      -0.0630      0.2869     -0.57261
+        53504      -0.0636      0.2885     -0.57218
+        53505      -0.0643      0.2901     -0.57175
+        53506      -0.0649      0.2917     -0.57143
+        53507      -0.0655      0.2933     -0.57124
+        53508      -0.0661      0.2949     -0.57117
+        53509      -0.0667      0.2966     -0.57124
+        53510      -0.0672      0.2982     -0.57139
+        53511      -0.0677      0.2999     -0.57158
+        53512      -0.0682      0.3015     -0.57166
+        53513      -0.0686      0.3032     -0.57155
+        53514      -0.0690      0.3048     -0.57116
+        53515      -0.0694      0.3065     -0.57057
+        53516      -0.0698      0.3082     -0.56989
+        53517      -0.0701      0.3098     -0.56921
+        53518      -0.0704      0.3115     -0.56860
+        53519      -0.0707      0.3132     -0.56818
+        53520      -0.0710      0.3149     -0.56799
+        53521      -0.0712      0.3166     -0.56800
+        53522      -0.0714      0.3183     -0.56809
+        53523      -0.0716      0.3200     -0.56815
+        53524      -0.0717      0.3217     -0.56808
+        53525      -0.0718      0.3234     -0.56781
+        53526      -0.0719      0.3251     -0.56728
+        53527      -0.0720      0.3268     -0.56651
+        53528      -0.0720      0.3285     -0.56557
+        53529      -0.0720      0.3302     -0.56454
+        53530      -0.0720      0.3319     -0.56347
+        53531      -0.0720      0.3336     -0.56244
+        53532      -0.0719      0.3353     -0.56148
+        53533      -0.0718      0.3370     -0.56060
+        53534      -0.0717      0.3387     -0.55990
+        53535      -0.0715      0.3404     -0.55943
+        53536      -0.0713      0.3421     -0.55916
+        53537      -0.0711      0.3438     -0.55897
+        53538      -0.0709      0.3455     -0.55881
+        53539      -0.0707      0.3472     -0.55859
+        53540      -0.0704      0.3489     -0.55820
+        53541      -0.0701      0.3506     -0.55751
+        53542      -0.0697      0.3523     -0.55650
+        53543      -0.0694      0.3540     -0.55529
+        53544      -0.0690      0.3557     -0.55402
+        53545      -0.0686      0.3573     -0.55279
+        53546      -0.0682      0.3590     -0.55173
+        53547      -0.0677      0.3607     -0.55093
+        53548      -0.0673      0.3623     -0.55037
+        53549      -0.0668      0.3640     -0.54994
+        53550      -0.0662      0.3656     -0.54947
+        53551      -0.0657      0.3673     -0.54884
+        53552      -0.0651      0.3689     -0.54798
+        53553      -0.0645      0.3705     -0.54689
+        53554      -0.0639      0.3721     -0.54560
+        53555      -0.0633      0.3738     -0.54414
+        53556      -0.0626      0.3754     -0.54257
+        53557      -0.0620      0.3770     -0.54101
+        53558      -0.0613      0.3786     -0.53952
+        53559      -0.0605      0.3801     -0.53819
+        53560      -0.0598      0.3817     -0.53705
+        53561      -0.0590      0.3833     -0.53611
+        53562      -0.0583      0.3848     -0.53535
+        53563      -0.0575      0.3864     -0.53475
+        53564      -0.0566      0.3879     -0.53425
+        53565      -0.0558      0.3895     -0.53374
+        53566      -0.0549      0.3910     -0.53315
+        53567      -0.0541      0.3925     -0.53243
+        53568      -0.0532      0.3940     -0.53152
+        53569      -0.0523      0.3955     -0.53042
+        53570      -0.0513      0.3969     -0.52913
+        53571      -0.0504      0.3984     -0.52776
+        53572      -0.0494      0.3998     -0.52644
+        53573      -0.0485      0.4013     -0.52532
+        53574      -0.0475      0.4027     -0.52451
+        53575      -0.0464      0.4041     -0.52400
+        53576      -0.0454      0.4055     -0.52377
+        53577      -0.0444      0.4069     -0.52366
+        53578      -0.0433      0.4083     -0.52344
+        53579      -0.0423      0.4096     -0.52299
+        53580      -0.0412      0.4110     -0.52228
+        53581      -0.0401      0.4123     -0.52130
+        53582      -0.0390      0.4136     -0.52010
+        53583      -0.0378      0.4149     -0.51872
+        53584      -0.0367      0.4162     -0.51725
+        53585      -0.0356      0.4175     -0.51578
+        53586      -0.0344      0.4188     -0.51436
+        53587      -0.0332      0.4200     -0.51310
+        53588      -0.0320      0.4212     -0.51204
+        53589      -0.0309      0.4224     -0.51120
+        53590      -0.0297      0.4236     -0.51055
+        53591      -0.0284      0.4248     -0.51006
+        53592      -0.0272      0.4260     -0.50966
+        53593      -0.0260      0.4271     -0.50922
+        53594      -0.0247      0.4283     -0.50872
+        53595      -0.0235      0.4294     -0.50809
+        53596      -0.0222      0.4305     -0.50729
+        53597      -0.0210      0.4315     -0.50638
+        53598      -0.0197      0.4326     -0.50535
+        53599      -0.0184      0.4336     -0.50431
+        53600      -0.0171      0.4347     -0.50339
+        53601      -0.0158      0.4357     -0.50273
+        53602      -0.0145      0.4367     -0.50244
+        53603      -0.0132      0.4376     -0.50247
+        53604      -0.0119      0.4386     -0.50267
+        53605      -0.0106      0.4395     -0.50286
+        53606      -0.0093      0.4404     -0.50287
+        53607      -0.0079      0.4413     -0.50263
+        53608      -0.0066      0.4422     -0.50217
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/execute_tap
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/execute_tap	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/execute_tap	(revision 22158)
@@ -0,0 +1,4 @@
+make test
+./tap_psSphereOps_all
+./tap_psEarthOrientation_corrections
+./tap_psEarthOrientation_motion
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psCoord.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psCoord.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psCoord.c	(revision 22158)
@@ -0,0 +1,370 @@
+/** @file  tst_psCoord.c
+*
+*  @brief The code will ...
+*
+*  @author GLG, MHPCC
+*
+*  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-06-05 01:10:22 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define ORDER_X 2
+#define ORDER_Y 3
+#define ORDER_Z 4
+#define ORDER_T 5
+#define N 10
+#define COLOR 1.0
+#define MAGNITUDE 1.0
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(57);
+
+    // Test psPlaneAlloc()
+    {
+        psMemId id = psMemGetId();
+        psPlane *myP = psPlaneAlloc();
+        ok(myP != NULL, "psPlaneAlloc() returned non-NULL");
+        skip_start(myP == NULL, 4, "Skipping tests because psPlaneAlloc() returned NULL");
+        ok(isnan(myP->x), "psPlane->x is NAN");
+        ok(isnan(myP->y), "psPlane->y is NAN");
+        ok(isnan(myP->xErr), "psPlane->xErr is NAN");
+        ok(isnan(myP->yErr), "psPlane->yErr is NAN");
+        skip_end();
+        psFree(myP);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test psPlaneTransformAlloc()
+    {
+        psMemId id = psMemGetId();
+        psPlaneTransform *myPT = psPlaneTransformAlloc(ORDER_X, ORDER_Y);
+        ok(myPT != NULL, "psPlaneTransformAlloc() returned non-NULL");
+        skip_start(myPT == NULL, 4, "Skipping tests because psPlaneTransformAlloc() returned NULL");
+        ok(myPT->x->nX == ORDER_X, "psPlaneTransform->x->nX set correctly");
+        ok(myPT->y->nX == ORDER_X, "psPlaneTransform->y->nX set correctly");
+        ok(myPT->x->nY == ORDER_Y, "psPlaneTransform->x->nY set correctly");
+        ok(myPT->y->nY == ORDER_Y, "psPlaneTransform->y->nY set correctly");
+        psFree(myPT);
+
+        // Attempt to specify negative x order and verify NULL returned and
+        // errror message generated
+        myPT = psPlaneTransformAlloc(-1, 1);
+        ok(myPT == NULL, "psPlaneTransformAlloc(-1, 1) returned NULL");
+        psFree(myPT);
+
+        myPT = psPlaneTransformAlloc(1, -1);
+        ok(myPT == NULL, "psPlaneTransformAlloc(1, -1) returned NULL");
+        psFree(myPT);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test psPlaneDistortAlloc()
+    {
+        psMemId id = psMemGetId();
+        psPlaneDistort *myPD = psPlaneDistortAlloc(ORDER_X, ORDER_Y, ORDER_Z, ORDER_T);
+        ok(myPD != NULL, "psPlaneDistortAlloc() returned non-NULL");
+        skip_start(myPD == NULL, 12, "Skipping tests because psPlaneDistortAlloc() returned NULL");
+        ok(myPD->x->nX == ORDER_X, "psPlaneDistort->x->nX set correctly");
+        ok(myPD->x->nY == ORDER_Y, "psPlaneDistort->x->nY set correctly");
+        ok(myPD->x->nZ == ORDER_Z, "psPlaneDistort->x->nZ set correctly");
+        ok(myPD->x->nT == ORDER_T, "psPlaneDistort->x->nT set correctly");
+        ok(myPD->y->nX == ORDER_X, "psPlaneDistort->y->nX set correctly");
+        ok(myPD->y->nY == ORDER_Y, "psPlaneDistort->y->nY set correctly");
+        ok(myPD->y->nZ == ORDER_Z, "psPlaneDistort->y->nZ set correctly");
+        ok(myPD->y->nT == ORDER_T, "psPlaneDistort->y->nT set correctly");
+        psFree(myPD);
+
+        myPD = psPlaneDistortAlloc(-1, 1, 1, 1);
+        ok(myPD == NULL, "psPlaneDistortAlloc(-1, 1, 1, 1) returned NULL");
+        psFree(myPD);
+        myPD = psPlaneDistortAlloc(1, -1, 1, 1);
+        ok(myPD == NULL, "psPlaneDistortAlloc(1, -1, 1, 1) returned NULL");
+        psFree(myPD);
+        myPD = psPlaneDistortAlloc(1, 1, -1, 1);
+        ok(myPD == NULL, "psPlaneDistortAlloc(1, 1, -1, 1) returned NULL");
+        psFree(myPD);
+        myPD = psPlaneDistortAlloc(1, 1, 1, -1);
+        ok(myPD == NULL, "psPlaneDistortAlloc(1, 1, 1, -1) returned NULL");
+        psFree(myPD);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // We test psPlaneTransformApply() on a simple identity transformation for few x,y pairs.
+    {
+        psMemId id = psMemGetId();
+        psPlane* in = psPlaneAlloc();
+        ok(in != NULL, "psPlaneAlloc() returned non-NULL");
+        skip_start(in == NULL, 2, "Skipping tests because psPlaneAlloc() returned NULL");
+        psPlaneTransform* pt = psPlaneTransformAlloc(2,2);
+        ok(pt != NULL, "psPlaneTransformAlloc() returned non-NULL");
+        skip_start(pt == NULL, 1, "Skipping tests because psPlaneTransformAlloc() returned NULL");
+
+        // Set transform coefficients so the x coord input will equal x coord output, same for y
+        pt->x->coeff[1][0] = 1.0;
+        pt->y->coeff[0][1] = 1.0;
+
+        // Apply transform for several points
+        bool errorFlag = false;
+        for (psS32 i = 0; i < N; i++)
+        {
+            in->x = (psF64) i;
+            in->y = (psF64) (i + 5.0);
+            in->xErr = 0.0;
+            in->yErr = 0.0;
+
+            // XXX: psPlane *out = psPlaneTransformApply(out, pt, in); causes a seg-fault.
+            // Why?
+            psPlane *out = psPlaneTransformApply(NULL, pt, in);
+            if(out == NULL) {
+                diag("ERROR: psPlaneTransformApply() returned NULL");
+                errorFlag = true;
+            } else {
+                if (FLT_EPSILON < fabs(out->x - in->x)) {
+                    diag("ERROR: out.x is %lf, should be %lf", out->x, in->x);
+                    errorFlag = true;
+                }
+
+                if (FLT_EPSILON < fabs(out->y - in->y)) {
+                    diag("ERROR: out.y is %lf, should be %lf", out->y, in->y);
+                    errorFlag = true;
+                }
+            }
+            psFree(out);
+        }
+        ok(!errorFlag, "psPlaneTransformApply() successful on several data points");
+        psFree(pt);
+        psFree(in);
+        skip_end();
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psPlaneTransformApply should generate error message for NULL psPlaneTransform
+    {
+        psMemId id = psMemGetId();
+        psPlane* in = psPlaneAlloc();
+        psPlane *tmpPL = psPlaneTransformApply(NULL, NULL, in);
+        ok(tmpPL == NULL, "psPlaneTransformApply(NULL, NULL, in) returned NULL");
+        psFree(in);
+        psFree(tmpPL);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psPlaneTransformApply should generate error message for NULL x coeff psPlaneTransform
+    {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        psPlaneTransform *pt = psPlaneTransformAlloc(2,2);
+        psFree(pt->x);
+        pt->x = NULL;
+        psPlane *tmpPL = psPlaneTransformApply(NULL, pt, in);
+        ok(tmpPL == NULL, "psPlaneTransformApply(NULL, pt, in) returned NULL with NULL x coeff psPlaneTransform");
+        psFree(in);
+        psFree(pt);
+        psFree(tmpPL);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psPlaneTransformApply Should generate error message for NULL y coeff psPlaneTransform");
+    {
+        psMemId id = psMemGetId();
+        psPlane* in = psPlaneAlloc();
+        psPlaneTransform* pt = psPlaneTransformAlloc(2,2);
+        psFree(pt->y);
+        pt->y = NULL;
+        psPlane *tmpPL = psPlaneTransformApply(NULL, pt, in);
+        ok(tmpPL == NULL, "psPlaneTransformApply(NULL, pt, in) returned NULL with NULL y coeff psPlaneTransform");
+        psFree(tmpPL);
+        psFree(pt);
+        psFree(in);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psPlaneTransformApply() should generate error message for NULL psPlane");
+    {
+        psMemId id = psMemGetId();
+        psPlaneTransform* pt = psPlaneTransformAlloc(2,2);
+        psPlane *tmpPL = psPlaneTransformApply(NULL, pt, NULL);
+        ok(tmpPL == NULL, "psPlaneTransformApply(NULL, pt, NULL) did not return NULL");
+        psFree(tmpPL);
+        psFree(pt);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // We test psPlaneDistortApply() on a simple identity transformation for few x,y pairs.
+    {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        ok(in != NULL, "psPlaneAlloc() returned non-NULL");
+        skip_start(in == NULL, 1, "Skipping tests because psPlaneAlloc() returned NULL");
+        psPlaneDistort *pt = psPlaneDistortAlloc(2, 2, 2, 2);
+        ok(pt != NULL, "psPlaneDistortAlloc() returned non-NULL");
+        skip_start(pt == NULL, 1, "Skipping tests because psPlaneTransformAlloc() returned NULL");
+
+        pt->x->coeff[1][0][0][0] = 1.0;
+        pt->x->coeff[0][0][1][0] = 1.0;
+        pt->x->coeff[0][0][0][1] = 1.0;
+        pt->y->coeff[0][1][0][0] = 1.0;
+        pt->y->coeff[0][0][1][0] = 1.0;
+        pt->y->coeff[0][0][0][1] = 1.0;
+
+        bool errorFlag = false;
+        for (psS32 i = 0; i < N; i++)
+        {
+            in->x = (psF64) i;
+            in->y = (psF64) (i + 5.0);
+            in->xErr = 0.0;
+            in->yErr = 0.0;
+
+            // XXX: psPlane *out = psPlaneDistortApply(out, pt, in, COLOR, MAGNITUDE); generates a seg-fault.  Why?
+            psPlane *out = psPlaneDistortApply(NULL, pt, in, COLOR, MAGNITUDE);
+            if(out == NULL) {
+                diag("ERROR: psPlaneDistortApply() returned NULL");
+                errorFlag = true;
+            } else {
+                if (FLT_EPSILON < fabs(out->x - COLOR - MAGNITUDE - in->x)) {
+                    diag("ERROR: out->x is %lf, should be %lf",
+                         out->x, in->x + COLOR + MAGNITUDE);
+                    errorFlag = true;
+                }
+                if (FLT_EPSILON < fabs(out->y - COLOR - MAGNITUDE - in->y)) {
+                    diag("ERROR: out->y is %lf, should be %lf",
+                         out->y, in->y + COLOR + MAGNITUDE);
+                    errorFlag = true;
+                }
+            }
+            psFree(out);
+        }
+        ok(!errorFlag, "psPlaneDistortApply() successful on several data points");
+        psFree(in);
+        psFree(pt);
+        skip_end();
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psPlaneDistortApply() should generate an error message for null psPlaneDistort
+    if (1) {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        psPlane *tmpPL = psPlaneDistortApply(NULL, NULL, in, COLOR, MAGNITUDE);
+        ok(tmpPL == NULL, "psPlaneDistortApply(NULL, NULL, in, COLOR, MAGNITUDE) returned NULL");
+        psFree(tmpPL);
+        psFree(in);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psPlaneDistortApply() should generate an error message for null x member psPlaneDistort
+    if (1) {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        psPlaneDistort *pt = psPlaneDistortAlloc(2, 2, 2, 2);
+        psFree(pt->x);
+        pt->x = NULL;
+        psPlane *tmpPL = psPlaneDistortApply(NULL, pt, in, COLOR, MAGNITUDE);
+        ok(tmpPL == NULL, "psPlaneDistortApply(NULL, pt, in, COLOR, MAGNITUDE) with NULL pt->x member");
+        psFree(tmpPL);
+        psFree(pt);
+        psFree(in);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psPlaneDistortApply() should generate an error message for null y member psPlaneDistort
+    if (1) {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        psPlaneDistort *pt = psPlaneDistortAlloc(2, 2, 2, 2);
+        psFree(pt->y);
+        pt->y = NULL;
+        psPlane *tmpPL = psPlaneDistortApply(NULL, pt, in, COLOR, MAGNITUDE);
+        ok(tmpPL == NULL, "psPlaneDistortApply(NULL, pt, in, COLOR, MAGNITUDE) with NULL pt->y member");
+        psFree(tmpPL);
+        psFree(pt);
+        psFree(in);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psPlaneDistortApply() should generate an error message for null input psPlane
+    if (1) {
+        psMemId id = psMemGetId();
+        psPlaneDistort *pt = psPlaneDistortAlloc(2, 2, 2, 2);
+        psPlane *tmpPL = psPlaneDistortApply(NULL, pt, NULL, COLOR, MAGNITUDE);
+        ok(tmpPL == NULL, "psPlaneDistortApply(NULL, pt, NULL, COLOR, MAGNITUDE) returned NULL");
+        psFree(tmpPL);
+        psFree(pt);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test psPixelsTransform()
+    // psPixelsTransform() should generate error message for NULL input pixels
+    {
+        psMemId id = psMemGetId();
+        psPlaneTransform *trans = psPlaneTransformAlloc(1, 3);
+        psPixels *output = psPixelsTransform(NULL, NULL, trans);
+        ok(output == NULL, "psPixelsTransform(NULL, NULL, trans) returned NULL");
+        psFree(trans);
+        psFree(output);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psPixelsTransform() should generate error message for NULL input PlaneTransform
+    {
+        psMemId id = psMemGetId();
+        psPixels *input = psPixelsAlloc(2);
+        psPixels *output = psPixelsTransform(NULL, input, NULL);
+        ok(output == NULL, "psPixelsTransform(NULL, input, NULL) returned NULL");
+        psFree(output);
+        psFree(input);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // We test psPixelsTransform() on several data points
+    {
+        psMemId id = psMemGetId();
+        psPixels *input = psPixelsAlloc(2);
+        input->n = 2;
+        input->data[0].x = 1.0;
+        input->data[0].y = 1.0;
+        input->data[1].x = 1.0;
+        input->data[1].y = 6.0;
+        psPlaneTransform *trans = psPlaneTransformAlloc(1, 3);
+        trans->x->coeff[0][0] = 0;
+        trans->x->coeff[1][0] = 1.0;
+        trans->y->coeff[0][0] = 0;
+        trans->y->coeff[0][0] = 0;
+        trans->y->coeff[0][2] = 0.5;
+
+        // XXX: Fix this
+        psPixels *output = psPixelsTransform(NULL, input, trans);
+        int nExpected = 9;
+        if (output->n != nExpected)
+        {
+            diag("ERROR: psPixelsTransform failed to return the expected number of pixels.\n");
+            printf("\n output returned with %ld pixels\n\n", output->n);
+            for (int i = 0; i < output->n; i++) {
+                printf("  (%6.2lf, %6.2lf) pixel %d\n", output->data[i].x, output->data[i].y, i+1);
+            }
+            return 3;
+        }
+
+        psFree(trans);
+        psFree(input);
+        psFree(output);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psCoord01.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psCoord01.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psCoord01.c	(revision 22158)
@@ -0,0 +1,1047 @@
+/**  @file  tst_psCoord01.c
+*
+*    @brief  The code will test several functions with PSLib source file
+*            psCoord.c
+*
+*    @author Eric Van Alst, MHPCC
+*
+* XXX: must do (r,d) -> (x, y) -> (r, d) test to ensure correctness.
+* XXX: The (Xs, Ys) scales are not be used properly.
+* XXX: Much work remains to be done.  The original tests defined correct
+*      input/output pairs and compared results.  It's not clear how those
+*      values were obtained, and they nearly all fail now.
+*
+*    @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+*    @date  $Date: 2007-05-01 00:08:52 $
+*    @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+*    @date  $Date: 2007-05-01 00:08:52 $
+*
+*    Copyright 2005 Maui High Performance Computing Center, Univ. of Hawaii
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#define ERROR_TOL    0.0001
+#define TESTPOINTS   4
+#define DEG_INC   30.0
+
+#define MY_TINY 0.0001
+#define PS_COMPARE_TINY_THEN_PRINT_ERROR(ACTUAL, EXPECT, TESTSTATUS) \
+if (MY_TINY < fabs(EXPECT - ACTUAL)) { \
+    diag("%s is %lg, should be %lg", #ACTUAL, ACTUAL, EXPECT, TESTSTATUS); \
+    errorFlag = true; \
+}
+
+
+//  alpha, delta, alpha-center, delta-center, scale-x, scale-y
+psF64 projectionTestPoint[TESTPOINTS][6] = {
+            {  0.785398,  0.785398,  0.000000,  0.000000,  1.000000,  1.000000 },
+            {  0.100000,  1.500000,  0.500000,  0.250000,  1.000000,  1.000000 },
+            {  0.628319,  0.448799,  0.000000,  0.000000,  0.250000,  0.750000 },
+            { -1.047196,  0.222222, -0.250000,  0.000000,  1.500000,  1.250000 }
+        };
+
+// Expected values for TAN
+psF64 projectionTanExpected[TESTPOINTS][2] = {
+            { -1.000000, -1.414214 },
+            {  0.088884, -3.066567 },
+            { -0.181636, -0.446444 },
+            {  1.535818, -0.404231 }
+        };
+
+// Expected values for SIN
+psF64 projectionSinExpected[TESTPOINTS][2] = {
+            { -0.500000, -0.707101 },
+            {  0.027546, -0.950366 },
+            { -0.132394, -0.325413 },
+            {  1.046712, -0.275497 }
+        };
+
+// Expected values for AIT
+psF64 projectionAitExpected[TESTPOINTS][2] = {
+            { -0.549175,  0.523375 },
+            {  0.027895,  0.313807 },
+            { -0.162822,  0.607646 },
+            {  1.455312,  0.955388 }
+        };
+
+// Expected values for PAR
+psF64 projectionParExpected[TESTPOINTS][2] = {
+            { -0.541244,  0.545532 },
+            {  0.027703,  0.329366 },
+            { -0.157157,  0.633550 },
+            {  1.432951,  0.971372 }
+        };
+
+// Testpoints, offset and expected values for psSphereSetOffset test
+#define TESTPOINTS_OFFSET  4
+psF64 setOffsetTestpoint[TESTPOINTS_OFFSET][2] = {
+            { 0.50,  0.50 },
+            {-0.50,  0.50 },
+            { 0.00,  0.00 },
+            { 1.50, -0.10 }
+        };
+
+psF64 setOffsetOffset[TESTPOINTS_OFFSET][2] = {
+            { 0.190761, -0.272205 },
+            {-0.553049, -0.460926 },
+            { 0.100335,-14.172222 },
+            {14.172222, -0.100335 }
+        };
+
+psF64 setOffsetResult[TESTPOINTS_OFFSET][2] = {
+            //XXX: Eugene says his values are correct, so i'm changing these values to the output.
+            //            { 0.25,  0.75 },
+            //            { 0.20,  0.80 },
+            //            {-0.10,  1.50 },
+            //            { 0.00,  0.00 }
+            { 0.68702,   0.230294},
+            { -0.966388,  0.0608434 },
+            {0.10,  -1.50 },
+            { 3.00141, -0.0140538  }
+        };
+
+psF64 getOffsetTestpoint1[TESTPOINTS_OFFSET][2] = {
+            { 0.00,  0.00 },
+            {-0.25,  0.50 },
+            { 0.50, -0.25 },
+            { 0.25, -0.10 }
+        };
+
+psF64 getOffsetTestpoint2[TESTPOINTS_OFFSET][2] = {
+            { 0.75,  0.25 },
+            { 0.40, -0.60 },
+            { 1.50,  0.50 },
+            { 0.10,  0.75 }
+        };
+
+psF64 getOffsetResult[TESTPOINTS_OFFSET][2] = {
+            //XXX: Eugene says his values are correct, so i'm changing these values to the output.
+            //            { -0.931596, -0.348976 },
+            //            { -1.632830,  2.649629 },
+            //            { -2.166795, -1.707211 },
+            //            {  0.167752, -1.151351 }
+            { 0.931596, 0.348976 },
+            { 1.632830,  -2.649629 },
+            { 2.166795, 1.707211 },
+            {  -0.167752, 1.151351 }
+        };
+
+
+psS32 main( psS32 argc, char *argv[] )
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(87);
+
+    // psProjectionAlloc()
+    {
+        psMemId id = psMemGetId();
+        psProjection *myProjection = psProjectionAlloc(1.1, 2.2, 3.3, 4.4, PS_PROJ_AIT);
+        ok(myProjection != NULL, "psProjectionAlloc() returned non-NULL");
+        ok(myProjection->R == 1.1, "psProjection->R set correctly");
+        ok(myProjection->D == 2.2, "psProjection->D set correctly");
+        ok(myProjection->Xs == 3.3, "psProjection->Xs set correctly");
+        ok(myProjection->Ys == 4.4, "psProjection->Ys set correctly");
+        ok(myProjection->type == PS_PROJ_AIT, "psProjection->type set correctly");
+        psFree(myProjection);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testProjectTan()
+    // We do a psProject() then a psDeproject() on several data points and
+    // verify that we produce the original data point.
+    // XXX: This test currently fails.
+    {
+        psMemId id = psMemGetId();
+        psSphere *in = psSphereAlloc();
+        psSphere *inTest = NULL;
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_TAN);
+
+        // Perform projecton on various test points
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            bool errorFlag = false;
+            in->r = projectionTestPoint[i][0];
+            in->d = projectionTestPoint[i][1];
+            myProjection->R = projectionTestPoint[i][2];
+            myProjection->D = projectionTestPoint[i][3];
+            myProjection->Xs = projectionTestPoint[i][4];
+            myProjection->Ys = projectionTestPoint[i][5];
+
+            psPlane *out = psProject(NULL, in, myProjection);
+            if(out == NULL) {
+                diag("psProject() returned NULL");
+                errorFlag = true;
+            } else {
+                inTest = psDeproject(NULL, out, myProjection);
+                if(fabs(out->x - projectionTanExpected[i][0]) > ERROR_TOL) {
+                    diag("TEST ERROR: Testpoint %d  psPlane->x = %lg  expected %lg",
+                         i,out->x, projectionTanExpected[i][0]);
+                    errorFlag = true;
+                }
+                if(fabs(out->y - projectionTanExpected[i][1]) > ERROR_TOL) {
+                    diag("TEST ERROR: Testpoint % d psPlane->y = %lg  expected %lg",
+                         i,out->y, projectionTanExpected[i][1]);
+                    errorFlag = true;
+                }
+
+                // Verify output is as expected
+                if(fabs(in->r - inTest->r) > ERROR_TOL) {
+                    diag("TEST ERROR: (in->r, inTest->r) (%.2f %.2f)\n", in->r, inTest->r);
+                    errorFlag = true;
+                }
+                if(fabs(in->d - inTest->d) > ERROR_TOL) {
+                    diag("TEST ERROR: (in->d, inTest->d) (%.2f %.2f)\n", in->d, inTest->d);
+                    errorFlag = true;
+                }
+            }
+            ok(!errorFlag, "psProject()/psDeproject() successful for test point %d\n", i);
+            psFree(inTest);
+            psFree(out);
+        }
+
+        psFree(in);
+        psFree(myProjection);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testDeprojectTan()
+    {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_TAN);
+
+        // Perform deprojection on various test points
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            bool errorFlag = false;
+            // Initialize input and projection members
+            in->x = projectionTanExpected[i][0];
+            in->y = projectionTanExpected[i][1];
+            myProjection->R = projectionTestPoint[i][2];
+            myProjection->D = projectionTestPoint[i][3];
+            myProjection->Xs = projectionTestPoint[i][4];
+            myProjection->Ys = projectionTestPoint[i][5];
+
+            // Perform deprojection
+            psSphere *out = psDeproject(NULL, in, myProjection);
+
+            // Verify output is not NULL
+            if(out == NULL) {
+                diag("psDeproject() returned NULL");
+                errorFlag = true;
+            } else {
+                // Verify output is as expected
+                if(fabs(out->r - projectionTestPoint[i][0]) > ERROR_TOL) {
+                    diag("Testpoint %d  psSphere->r = %lg  expected %lg",
+                         i,out->r,projectionTestPoint[i][0]);
+                    errorFlag = true;
+                }
+                if(fabs(out->d - projectionTestPoint[i][1]) > ERROR_TOL) {
+                    diag("Testpoint %d  psSphere->d = %lg expected %lg",
+                         i, out->d, projectionTestPoint[i][1]);
+                    errorFlag = true;
+                }
+            }
+            psFree(out);
+            ok(!errorFlag, "psProject()/psDeproject() successful for test point %d\n", i);
+        }
+
+        psFree(in);
+        psFree(myProjection);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testProjectSin()
+    {
+        psMemId id = psMemGetId();
+        psSphere *in = psSphereAlloc();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_SIN);
+
+        // Perform projecton on various test points
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            bool errorFlag = false;
+            // Initialize input and project members
+            in->r = projectionTestPoint[i][0];
+            in->d = projectionTestPoint[i][1];
+            myProjection->R = projectionTestPoint[i][2];
+            myProjection->D = projectionTestPoint[i][3];
+            myProjection->Xs = projectionTestPoint[i][4];
+            myProjection->Ys = projectionTestPoint[i][5];
+
+            // Perform projection
+            psPlane *out = psProject(NULL, in, myProjection);
+
+            // Verify output not NULL
+            if(out == NULL) {
+                diag("Return null not expected");
+                errorFlag = true;
+            } else {
+                // Verify output is as expected
+                if(fabs(out->x - projectionSinExpected[i][0]) > ERROR_TOL) {
+                    diag("Testpoint %d  psPlane->x = %lg  expected %lg",
+                         i,out->x, projectionSinExpected[i][0]);
+                    errorFlag = true;
+                }
+                if(fabs(out->y - projectionSinExpected[i][1]) > ERROR_TOL) {
+                    diag("Testpoint % d  psPlane->y = %lg  expected %lg",
+                         i,out->y, projectionSinExpected[i][1]);
+                    errorFlag = true;
+                }
+                psFree(out);
+            }
+            ok(!errorFlag, "psProject()/psDeproject() successful for test point %d\n", i);
+        }
+
+        psFree(in);
+        psFree(myProjection);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testDeprojectSin()
+    {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_SIN);
+
+        // Perform deprojection on various test points
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            bool errorFlag = false;
+            // Initialize input and projection members
+            in->x = projectionSinExpected[i][0];
+            in->y = projectionSinExpected[i][1];
+            myProjection->R = projectionTestPoint[i][2];
+            myProjection->D = projectionTestPoint[i][3];
+            myProjection->Xs = projectionTestPoint[i][4];
+            myProjection->Ys = projectionTestPoint[i][5];
+
+            // Perform deprojection
+            psSphere *out = psDeproject(NULL, in, myProjection);
+
+            // Verify output is not NULL
+            if(out == NULL) {
+                diag("Return null not expected");
+                errorFlag = true;
+            } else {
+                // Verify output is as expected
+                if(fabs(out->r - projectionTestPoint[i][0]) > ERROR_TOL) {
+                    diag("Testpoint %d  psSphere->r = %lg  expected %lg",
+                         i,out->r,projectionTestPoint[i][0]);
+                    errorFlag = true;
+                }
+                if(fabs(out->d - projectionTestPoint[i][1]) > ERROR_TOL) {
+                    diag("Testpoint %d  psSphere->d = %lg expected %lg",
+                         i, out->d, projectionTestPoint[i][1]);
+                    errorFlag = true;
+                }
+                psFree(out);
+            }
+            ok(!errorFlag, "psProject()/psDeproject() successful for test point %d\n", i);
+        }
+
+        psFree(in);
+        psFree(myProjection);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testProjectAit()
+    {
+        psMemId id = psMemGetId();
+        psSphere *in = psSphereAlloc();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_AIT);
+
+        // Perform projecton on various test points
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            bool errorFlag = false;
+            // Initialize input and project members
+            in->r = projectionTestPoint[i][0];
+            in->d = projectionTestPoint[i][1];
+            myProjection->R = projectionTestPoint[i][2];
+            myProjection->D = projectionTestPoint[i][3];
+            myProjection->Xs = projectionTestPoint[i][4];
+            myProjection->Ys = projectionTestPoint[i][5];
+
+            // Perform projection
+            psPlane *out = psProject(NULL, in, myProjection);
+
+            // Verify output not NULL
+            if(out == NULL) {
+                diag("Return null not expected");
+                errorFlag = true;
+            } else {
+                // Verify output is as expected
+                if(fabs(out->x - projectionAitExpected[i][0]) > ERROR_TOL) {
+                    diag("Testpoint %d  psPlane->x = %lg  expected %lg",
+                         i,out->x, projectionAitExpected[i][0]);
+                    errorFlag = true;
+                }
+                if(fabs(out->y - projectionAitExpected[i][1]) > ERROR_TOL) {
+                    diag("Testpoint % d  psPlane->y = %lg  expected %lg",
+                         i,out->y, projectionAitExpected[i][1]);
+                    errorFlag = true;
+                }
+                psFree(out);
+            }
+            ok(!errorFlag, "psProject()/psDeproject() successful for test point %d\n", i);
+        }
+
+        psFree(in);
+        psFree(myProjection);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testDeprojectAit()
+    {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_AIT);
+
+        // Perform deprojection on various test points
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            bool errorFlag = false;
+            // Initialize input and projection members
+            in->x = projectionAitExpected[i][0];
+            in->y = projectionAitExpected[i][1];
+            myProjection->R = projectionTestPoint[i][2];
+            myProjection->D = projectionTestPoint[i][3];
+            myProjection->Xs = projectionTestPoint[i][4];
+            myProjection->Ys = projectionTestPoint[i][5];
+
+            // Perform deprojection
+            psSphere *out = psDeproject(NULL, in, myProjection);
+
+            // Verify output is not NULL
+            if(out == NULL) {
+                diag("Return null not expected");
+                errorFlag = true;
+            } else {
+                // Verify output is as expected
+                if(fabs(out->r - projectionTestPoint[i][0]) > ERROR_TOL) {
+                    diag("Testpoint %d  psSphere->r = %lg  expected %lg",
+                         i,out->r,projectionTestPoint[i][0]);
+                    errorFlag = true;
+                }
+                if(fabs(out->d - projectionTestPoint[i][1]) > ERROR_TOL) {
+                    diag("Testpoint %d  psSphere->d = %lg expected %lg",
+                         i, out->d, projectionTestPoint[i][1]);
+                    errorFlag = true;
+                }
+                psFree(out);
+            }
+            ok(!errorFlag, "psProject()/psDeproject() successful for test point %d\n", i);
+        }
+
+        psFree(in);
+        psFree(myProjection);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testProjectPar()
+    {
+        psMemId id = psMemGetId();
+        psSphere *in = psSphereAlloc();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_PAR);
+
+        // Perform projecton on various test points
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            bool errorFlag = false;
+            // Initialize input and project members
+            in->r = projectionTestPoint[i][0];
+            in->d = projectionTestPoint[i][1];
+            myProjection->R = projectionTestPoint[i][2];
+            myProjection->D = projectionTestPoint[i][3];
+            myProjection->Xs = projectionTestPoint[i][4];
+            myProjection->Ys = projectionTestPoint[i][5];
+
+            // Perform projection
+            psPlane *out = psProject(NULL, in, myProjection);
+
+            // Verify output not NULL
+            if(out == NULL) {
+                diag("Return null not expected");
+                errorFlag = true;
+            } else {
+                // Verify output is as expected
+                if(fabs(out->x - projectionParExpected[i][0]) > ERROR_TOL) {
+                    diag("Testpoint %d  psPlane->x = %lg  expected %lg",
+                         i,out->x, projectionParExpected[i][0]);
+                    errorFlag = true;
+                }
+                if(fabs(out->y - projectionParExpected[i][1]) > ERROR_TOL) {
+                    diag("Testpoint % d  psPlane->y = %lg  expected %lg",
+                         i,out->y, projectionParExpected[i][1]);
+                    errorFlag = true;
+                }
+                psFree(out);
+            }
+            ok(!errorFlag, "psProject()/psDeproject() successful for test point %d\n", i);
+        }
+
+        psFree(in);
+        psFree(myProjection);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testDeprojectPar()
+    {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_PAR);
+
+        // Perform deprojection on various test points
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            bool errorFlag = false;
+            // Initialize input and projection members
+            in->x = projectionParExpected[i][0];
+            in->y = projectionParExpected[i][1];
+            myProjection->R = projectionTestPoint[i][2];
+            myProjection->D = projectionTestPoint[i][3];
+            myProjection->Xs = projectionTestPoint[i][4];
+            myProjection->Ys = projectionTestPoint[i][5];
+
+            // Perform deprojection
+            psSphere *out = psDeproject(NULL, in, myProjection);
+
+            // Verify output is not NULL
+            if(out == NULL) {
+                diag("Return null not expected");
+                errorFlag = true;
+            } else {
+                // Verify output is as expected
+                if(fabs(out->r - projectionTestPoint[i][0]) > ERROR_TOL) {
+                    diag("Testpoint %d  psSphere->r = %lg  expected %lg",
+                         i,out->r,projectionTestPoint[i][0]);
+                    errorFlag = true;
+                }
+                if(fabs(out->d - projectionTestPoint[i][1]) > ERROR_TOL) {
+                    diag("Testpoint %d  psSphere->d = %lg expected %lg",
+                         i, out->d, projectionTestPoint[i][1]);
+                    errorFlag = true;
+                }
+                psFree(out);
+            }
+            ok(!errorFlag, "psProject()/psDeproject() successful for test point %d\n", i);
+        }
+
+        psFree(in);
+        psFree(myProjection);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psProject(): Invoke function with null coordinate argument
+    // Following should generate an error message for null coord arg
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_TAN);
+        psPlane *out = psProject(NULL, NULL, myProjection);
+        ok(out == NULL, "psProject(NULL, NULL, xxx) returned NULL");
+        psFree(myProjection);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Invoke function with null projection argument
+    // Following should generate an error message for null projection arg
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *in = psSphereAlloc();
+        psPlane *out = psProject(NULL, in, NULL);
+        ok(out == NULL, "psProject(NULL, in, NULL) returned NULL");
+        psFree(in);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Invoke function with unallowed projection type
+    // Following should generate an error message for unallowed projection type
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_TAN);
+        myProjection->type = PS_PROJ_NTYPE;
+        psSphere *in = psSphereAlloc();
+        psPlane *out = psProject(NULL, in,myProjection);
+        ok(out == NULL, "psProject(NULL, in, out) returned NULL with unallowed projection type");
+        psFree(myProjection);
+        psFree(in);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testDeprojectFail()
+    psMemId id = psMemGetId();
+
+
+    // Invoke function with null coordinate argument
+    // Following should generate an error message for null coord arg
+    // XXX: We do not test the error generation
+    {
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_TAN);
+        psSphere *out = psDeproject(NULL, NULL, myProjection);
+        ok(out == NULL, "psDeproject(NULL, NULL, myProjection) returned NULL");
+        psFree(myProjection);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Invoke function with null projection argument
+    // Following should generate an error message for null projection arg
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        psSphere *out = psDeproject(NULL, in, NULL);
+        ok(out == NULL, "psDeproject(NULL, in, NULL) returned NULL");
+        psFree(in);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Invoke function with unallowed projection type
+    // Following should generate an error message for unallowed projection type
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_TAN);
+        psPlane *in = psPlaneAlloc();
+        myProjection->type = PS_PROJ_NTYPE;
+        psSphere *out = psDeproject(NULL, in,myProjection);
+        ok(out == NULL, "psDeproject(NULL, in,myProjection) returned NULL with unallowed projection type");
+        psFree(myProjection);
+        psFree(in);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // testSetOffsetSphere()
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *position2 = NULL;
+        psSphere *offset = psSphereAlloc();
+        psSphere *tmpOffset = psSphereAlloc();
+        bool errorFlag = false;
+
+        // Initialize first position
+        position1->r = DEG_TO_RAD(90.0);
+        position1->d = DEG_TO_RAD(45.0);
+        position1->rErr = 0.0;
+        position1->dErr = 0.0;
+
+        //  Using various offset verify spherical offset
+        //  Use all the valid unit types
+        for (psF64 r = 0.0; r < 180.0; r += DEG_INC)
+        {
+            for (psF64 d = 0.0; d < 90.0; d += DEG_INC) {
+
+                offset->r = DEG_TO_RAD(r);
+                offset->d = DEG_TO_RAD(d);
+                offset->rErr = 0.0;
+                offset->dErr = 0.0;
+
+                position2 = psSphereSetOffset(position1, offset, PS_SPHERICAL, PS_RADIAN);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->r, (position1->r + offset->r), 1);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->d, (position1->d + offset->d), 2);
+                psFree(position2);
+
+                tmpOffset->r = RAD_TO_DEG(offset->r);
+                tmpOffset->d = RAD_TO_DEG(offset->d);
+                tmpOffset->rErr = 0.0;
+                tmpOffset->dErr = 0.0;
+                position2 = psSphereSetOffset(position1, tmpOffset, PS_SPHERICAL, PS_DEGREE);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->r, (position1->r + offset->r), 3);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->d, (position1->d + offset->d), 4);
+                psFree(position2);
+
+                tmpOffset->r = RAD_TO_MIN(offset->r);
+                tmpOffset->d = RAD_TO_MIN(offset->d);
+                tmpOffset->rErr = 0.0;
+                tmpOffset->dErr = 0.0;
+                position2 = psSphereSetOffset(position1, tmpOffset, PS_SPHERICAL, PS_ARCMIN);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->r, (position1->r + offset->r), 5);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->d, (position1->d + offset->d), 6);
+                psFree(position2);
+
+                tmpOffset->r = RAD_TO_SEC(offset->r);
+                tmpOffset->d = RAD_TO_SEC(offset->d);
+                tmpOffset->rErr = 0.0;
+                tmpOffset->dErr = 0.0;
+                position2 = psSphereSetOffset(position1, tmpOffset, PS_SPHERICAL, PS_ARCSEC);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->r, (position1->r + offset->r), 7);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->d, (position1->d + offset->d), 8);
+                psFree(position2);
+            }
+        }
+        ok(!errorFlag, "psSphereSetOffset() successful on several dat points");
+
+        psFree(position1);
+        psFree(offset);
+        psFree(tmpOffset);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to call function with null input coordinate
+    // Following should generate error message null input coord
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *offset = psSphereAlloc();
+        psSphere *position2 = psSphereSetOffset(NULL, offset, PS_LINEAR, PS_ARCSEC);
+        ok(position2 == NULL, "psSphereSetOffset() returned NULL with NULL input coordinate");
+        psFree(position2);
+        psFree(offset);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to call function with null offset
+    // Following should generate error message null offset
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *position2 = psSphereSetOffset(position1, NULL, PS_LINEAR, PS_ARCSEC);
+        ok(position2 == NULL, "psSphereSetOffset() returned NULL with NULL offset");
+        psFree(position1);
+        psFree(position2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Attempt to call function with unallowed mode
+    // Following should generate error message unallowed mode
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *offset = psSphereAlloc();
+        psSphere *position2 = psSphereSetOffset(position1, offset, 0x54321, 0);
+        ok(position2 == NULL, "psSphereSetOffset() returned NULL with unallowed mode");
+        psFree(position1);
+        psFree(position2);
+        psFree(offset);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to call function with unallowed unit
+    // Following should generate an error message unallowed unit
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *offset = psSphereAlloc();
+        psSphere *position2 = psSphereSetOffset(position1, offset, PS_SPHERICAL, 0x54321);
+        ok(position2 == NULL, "psSphereSetOffset() returned NULL with unallowed unit");
+        psFree(position1);
+        psFree(position2);
+        psFree(offset);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testSetOffsetLinear()
+    {
+        psMemId id = psMemGetId();
+        psSphere *coord = psSphereAlloc();
+        psSphere *offset = psSphereAlloc();
+        psSphere *out = NULL;
+        bool errorFlag = false;
+
+        for(psS32 i = 0; i < TESTPOINTS_OFFSET; i++)
+        {
+            bool errorFlag = false;
+            coord->r = setOffsetTestpoint[i][0];
+            coord->d = setOffsetTestpoint[i][1];
+
+            offset->r = setOffsetOffset[i][0];
+            offset->d = setOffsetOffset[i][1];
+
+            out = psSphereSetOffset(coord, offset, PS_LINEAR, PS_RADIAN);
+
+            if(fabs(out->r - setOffsetResult[i][0]) > ERROR_TOL) {
+                diag("Testpoint %d: Result out->r = %lg not equal to expected %lg",
+                     i, out->r, setOffsetResult[i][0]);
+                errorFlag = true;
+            }
+            if(fabs(out->d - setOffsetResult[i][1]) > ERROR_TOL) {
+                diag("Testpoint %d: Result out->d = %lg not equal to expected %lg",
+                     i,out->d, setOffsetResult[i][1]);
+                errorFlag = true;
+            }
+
+            psFree(out);
+        }
+        psFree(coord);
+        psFree(offset);
+        ok(!errorFlag, "psSphereSetOffset(), linear, successful on several data points");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testGetOffsetSphere()
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *position2 = psSphereAlloc();
+        psSphere *offset = NULL;
+        bool errorFlag = false;
+        position1->r = DEG_TO_RAD(90.0);
+        position1->d = DEG_TO_RAD(45.0);
+        position1->rErr = 0.0;
+        position1->dErr = 0.0;
+
+        for (psF64 r = 0.0; r < 180.0;r += DEG_INC)
+        {
+            for (psF64 d = 0.0;d < 90.0; d += DEG_INC) {
+                position2->r = DEG_TO_RAD(r);
+                position2->d = DEG_TO_RAD(d);
+                position2->rErr = 0.0;
+                position2->dErr = 0.0;
+
+                offset = psSphereGetOffset( position1,  position2,
+                                            PS_SPHERICAL, PS_RADIAN);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->r, (position2->r - position1->r), 1);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->d, (position2->d - position1->d), 1);
+                psFree(offset);
+
+                offset = psSphereGetOffset( position1, position2,
+                                            PS_SPHERICAL, PS_DEGREE);
+                offset->r = DEG_TO_RAD(offset->r);
+                offset->d = DEG_TO_RAD(offset->d);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->r, (position2->r - position1->r), 2);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->d, (position2->d - position1->d), 3);
+                psFree(offset);
+
+                offset = psSphereGetOffset( position1,  position2,
+                                            PS_SPHERICAL, PS_ARCMIN);
+                offset->r = MIN_TO_RAD(offset->r);
+                offset->d = MIN_TO_RAD(offset->d);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->r, (position2->r - position1->r), 2);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->d, (position2->d - position1->d), 3);
+                psFree(offset);
+
+                offset = psSphereGetOffset( position1,  position2,
+                                            PS_SPHERICAL, PS_ARCSEC);
+                offset->r = SEC_TO_RAD(offset->r);
+                offset->d = SEC_TO_RAD(offset->d);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->r, (position2->r - position1->r), 2);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->d, (position2->d - position1->d), 3);
+                psFree(offset);
+            }
+        }
+        psFree(position1);
+        psFree(position2);
+        ok(!errorFlag, "psSphereSetOffset(), linear, successful on several data points");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to invoke function with null position 1 parameter
+    // Following should generate an error message for null position
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *position2 = psSphereAlloc();
+        psSphere *offset = psSphereGetOffset(NULL, position2, PS_LINEAR, 0);
+        ok(offset == NULL, "psSphereGetOffset() returned NULL with null position 1 parameter");
+        psFree(offset);
+        psFree(position2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to invoke function with null position 2 parameter
+    // Following should generate an error message for null position
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *offset = psSphereGetOffset(position1, NULL, PS_LINEAR, 0);
+        ok(offset == NULL, "psSphereGetOffset() returned NULL with null position 2 parameter");
+        psFree(offset);
+        psFree(position1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to invoke function with unallowed mode
+    // Following should generate an error message for unallowed mode
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *position2 = psSphereAlloc();
+        psSphere *offset = psSphereGetOffset(position1, position2, 0x54321, 0);
+        ok(offset == NULL, "psSphereGetOffset() returned NULL with unallowed mode");
+        psFree(offset);
+        psFree(position1);
+        psFree(position2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to invoke function with unallowed unit type
+    // Following should generate an error message for unallowed unit type
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *position2 = psSphereAlloc();
+        psSphere *offset = psSphereGetOffset(position1, position2, PS_SPHERICAL, 0x54321);
+        ok(offset == NULL, "psSphereGetOffset() returned NULL with unallowed unit type");
+        psFree(offset);
+        psFree(position1);
+        psFree(position2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to invoke function with coordinate 1 declination value 90.0 degree
+    // Following should generate warning message
+    // XXX: We do not test the warning generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *position2 = psSphereAlloc();
+        position1->d = DEG_TO_RAD(90.0);
+        psSphere *offset = psSphereGetOffset(position1, position2, PS_SPHERICAL, PS_RADIAN);
+        ok(offset == NULL, "psSphereGetOffset() returned NULL with coordinate 1 declination value 90.0 degree");
+        psFree(offset);
+        psFree(position1);
+        psFree(position2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to invoke function with coordinate 2 declination value 90.0 degree
+    // Following should generate warning message
+    // XXX: We do not test the warning generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *position2 = psSphereAlloc();
+        position1->d = DEG_TO_RAD(45.0);
+        position2->d = DEG_TO_RAD(90.0);
+        psSphere *offset = psSphereGetOffset(position1, position2, PS_SPHERICAL, PS_RADIAN);
+        ok(offset == NULL, "psSphereGetOffset() returned NULL with coordinate 2 declination value 90.0 degree");
+        psFree(offset);
+        psFree(position1);
+        psFree(position2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testGetOffsetLinear()
+    {
+        psMemId id = psMemGetId();
+        psSphere *coord1 = psSphereAlloc();
+        psSphere *coord2 = psSphereAlloc();
+        bool errorFlag = false;
+
+        for(psS32 i = 0; i < TESTPOINTS_OFFSET; i++)
+        {
+            bool errorFlag = false;
+            coord1->r = getOffsetTestpoint1[i][0];
+            coord1->d = getOffsetTestpoint1[i][1];
+            coord2->r = getOffsetTestpoint2[i][0];
+            coord2->d = getOffsetTestpoint2[i][1];
+            psSphere *out = psSphereGetOffset(coord1, coord2, PS_LINEAR, PS_RADIAN);
+            if (out == NULL) {
+                diag("TEST ERROR: psSphereGetOffset() returned NULL");
+                errorFlag = true;
+            } else {
+                if(fabs(out->r - getOffsetResult[i][0]) > ERROR_TOL) {
+                    diag("Testpoint %d: Result out->r = %lg not equal to expected %lg",
+                         i, out->r, getOffsetResult[i][0]);
+                    errorFlag = true;
+                }
+                if(fabs(out->d - getOffsetResult[i][1]) > ERROR_TOL) {
+                    diag("Testpoint %d: Result out->d = %lg not equal to expected %lg",
+                         i,out->d, getOffsetResult[i][1]);
+                    errorFlag = true;
+                }
+                psFree(out);
+            }
+        }
+        psFree(coord1);
+        psFree(coord2);
+        ok(!errorFlag, "psSphereGetOffset() worked on several data points");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    /* 
+        #define DEG_INC2 15.0
+        #define VERBOSE 0
+        // testProjectTanDeProjectTan()
+        // XXX: Get rid of this?
+        {
+            psMemId id = psMemGetId();
+            bool errorFlag = false;
+            //
+            // I'm not convinced that the p_psProject() and p_psDeproject() functions work
+            // correctly.  If we project a set of coordinates over a wide range of (R, D)
+            // values, then deproject them, the original (R, D) values are only produced
+            // when D is larger than 0.  This code demonstrates that.
+            //
+            psProjection *tmpProj = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+            psPlane planeCoord01;
+            psSphere skyCoord01;
+            psSphere skyCoord02;
+            for (psF32 R = -90.0 ; R <= 90.0 ; R+= DEG_INC2) {
+                for (psF32 D = -90.0 ; D <= 90.0 ; D+= DEG_INC2) {
+                    if ((fabs(R) != 90.0) && (fabs(D) != 90.0)) {
+                        skyCoord01.r = DEG_TO_RAD(R);
+                        skyCoord01.d = DEG_TO_RAD(D);
+                        p_psProject(&planeCoord01, &skyCoord01, tmpProj);
+                        p_psDeproject(&skyCoord02, &planeCoord01, tmpProj);
+                        if ((fabs(skyCoord01.r - skyCoord02.r) < FLT_EPSILON) &&
+                            (fabs(skyCoord01.d - skyCoord02.d) < FLT_EPSILON)) {
+                            if (VERBOSE) {
+                                printf("CORRECT: (%.2fr %.2fd) (%.2fr %.2fd) -> (%.2f %.2f) -> (%.2fr %.2fd)\n", R, D,
+                                       skyCoord01.r, skyCoord01.d,
+                                       planeCoord01.x, planeCoord01.y,
+                                       skyCoord02.r, skyCoord02.d);
+                            }
+                        } else {
+                            diag("TEST ERROR: (%.2fr %.2fd) (%.2fr %.2fd) -> (%.2f %.2f) -> (%.2fr %.2fd)\n", R, D,
+                                  skyCoord01.r, skyCoord01.d,
+                                  planeCoord01.x, planeCoord01.y,
+                                  skyCoord02.r, skyCoord02.d);
+                            errorFlag = true;
+                        }
+                    }
+                }
+            }
+            ok(!errorFlag, "p_psProject()/p_psDeproject() worked on several data points");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+    */
+}
+
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psCoord02.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psCoord02.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psCoord02.c	(revision 22158)
@@ -0,0 +1,551 @@
+/** @file  tst_psCoord02.c
+*
+*  @brief This file contains test code for:
+*
+*  @author GLG, MHPCC
+*
+*  XXX: These tests should probably be split among several files
+*
+*  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-06-05 01:10:22 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define PS_PERCENT_COMPARE(X, Y, PERCENT_FRACTION) (fabs((Y)-(X))/fabs(X) < (PERCENT_FRACTION))
+#define PS_GEN_RAN_FLOAT (-0.5 + ((psF32)rand()) / ((psF32) RAND_MAX))
+#define RANDOM_SEED 1995
+
+// These macros determine the number of x/y test points which will be x-formed.
+#define TST04_X_MIN 0.0
+#define TST04_X_MAX 10.0
+#define TST04_Y_MIN 0.0
+#define TST04_Y_MAX 10.0
+#define TST04_NUM 5.0
+// These macros define the max sizes of the various input transforms.
+#define TST04_T1_X_X 2
+#define TST04_T1_X_Y 3
+#define TST04_T1_Y_X 3
+#define TST04_T1_Y_Y 3
+#define TST04_T2_X_X 3
+#define TST04_T2_X_Y 3
+#define TST04_T2_Y_X 3
+#define TST04_T2_Y_Y 3
+
+/******************************************************************************
+tstTransforms(t1, t2, t3): this function generates a set of arbitrary x/y
+coordinates, then transforms them into output coordinates via the t3
+transform, as well as the t1 followed by the t2 transform.  It verifies the
+output coordinates are identical and returns TRUE if so.  Otherwise, it prints
+a diag message and returns FALSE.
+ *****************************************************************************/
+bool tstTransforms(psPlaneTransform *t1, psPlaneTransform *t2, psPlaneTransform *t3)
+{
+    bool testStatus = true;
+    psPlane *in = psPlaneAlloc();
+    in->xErr = 0.0;
+    in->yErr = 0.0;
+
+    for (in->x = TST04_X_MIN ; in->x <= TST04_X_MAX ; in->x+= (TST04_X_MAX-TST04_X_MIN) / TST04_NUM) {
+        for (in->y = TST04_Y_MIN ; in->y <= TST04_Y_MAX ; in->y+= (TST04_Y_MAX-TST04_Y_MIN) / TST04_NUM) {
+            // Apply the t1/t2 transforms individually to the in coords.
+            psPlane *mid = psPlaneTransformApply(NULL, t1, in);
+            if (mid == NULL) {
+                diag("TEST ERROR: intermediate psPlane coords are NULL.\n");
+                psFree(in);
+                return(false);
+            }
+
+            psPlane *outT1T2 = psPlaneTransformApply(NULL, t2, mid);
+            if (outT1T2 == NULL) {
+                diag("TEST ERROR: intermediate psPlane coords are NULL.\n");
+                psFree(mid);
+                return(false);
+            }
+
+            // Apply the t3 transforms individually to the in coords.
+            psPlane *outT3 = psPlaneTransformApply(NULL, t3, in);
+            if (outT3 == NULL) {
+                diag("TEST ERROR: intermediate psPlane coords are NULL.\n");
+                psFree(mid);
+                psFree(outT1T2);
+                return(false);
+            }
+
+            // Verify that the results are identical.
+            if (!PS_PERCENT_COMPARE(outT3->x, outT1T2->x, 0.01)) {
+                diag("TEST ERROR: x is %f, should be %f\n", outT3->x, outT1T2->x);
+                testStatus = false;
+            }
+            // Verify that the results are identical.
+            if (!PS_PERCENT_COMPARE(outT3->y, outT1T2->y, 0.01)) {
+                diag("TEST ERROR: y is %f, should be %f\n", outT3->y, outT1T2->y);
+                testStatus = false;
+            }
+            if (0) {
+                if (fabs(outT3->x - outT1T2->x) > FLT_EPSILON) {
+                    printf("TEST ERROR: x is %f, should be %f\n", outT3->x, outT1T2->x);
+                    testStatus = false;
+                    printf("(in->x, in->y) is (%f, %f)\n", in->x, in->y);
+                    printf("(mid->x, mid->y) is (%f, %f)\n", mid->x, mid->y);
+                    printf("(outT1T2->x, outT1T2->y) is (%f, %f)\n", outT1T2->x, outT1T2->y);
+                    printf("(outT3->x, outT3->y) is (%f, %f)\n", outT3->x, outT3->y);
+                    PS_POLY_PRINT_2D(t1->x);
+                    PS_POLY_PRINT_2D(t1->y);
+                    PS_POLY_PRINT_2D(t2->x);
+                    PS_POLY_PRINT_2D(t2->y);
+                    PS_POLY_PRINT_2D(t3->x);
+                    PS_POLY_PRINT_2D(t3->y);
+                }
+                if (fabs(outT3->y - outT1T2->y) > FLT_EPSILON) {
+                    printf("TEST ERROR: y is %f, should be %f\n", outT3->y, outT1T2->y);
+                    testStatus = false;
+                    printf("(in->x, in->y) is (%f, %f)\n", in->x, in->y);
+                    printf("(mid->x, mid->y) is (%f, %f)\n", mid->x, mid->y);
+                    printf("(outT1T2->x, outT1T2->y) is (%f, %f)\n", outT1T2->x, outT1T2->y);
+                    printf("(outT3->x, outT3->y) is (%f, %f)\n", outT3->x, outT3->y);
+                    PS_POLY_PRINT_2D(t1->x);
+                    PS_POLY_PRINT_2D(t1->y);
+                    PS_POLY_PRINT_2D(t2->x);
+                    PS_POLY_PRINT_2D(t2->y);
+                    PS_POLY_PRINT_2D(t3->x);
+                    PS_POLY_PRINT_2D(t3->y);
+                }
+            }
+            psFree(mid);
+            psFree(outT1T2);
+            psFree(outT3);
+        }
+    }
+
+    psFree(in);
+    return(testStatus);
+}
+
+/******************************************************************************
+setCoeffs(t1, t2): this function sets the coefficients of the t1 and t2
+transforms to somewhat arbitrary values.
+ *****************************************************************************/
+int setCoeffs(psPlaneTransform *t1, psPlaneTransform *t2)
+{
+    for (psS32 t1xx = 0 ; t1xx < t1->x->nX+1 ; t1xx++) {
+        for (psS32 t1xy = 0 ; t1xy < t1->x->nY+1 ; t1xy++) {
+            t1->x->coeff[t1xx][t1xy] = PS_GEN_RAN_FLOAT;
+        }
+    }
+
+    for (psS32 t1yx = 0 ; t1yx < t1->y->nX+1 ; t1yx++) {
+        for (psS32 t1yy = 0 ; t1yy < t1->y->nY+1 ; t1yy++) {
+            t1->y->coeff[t1yx][t1yy] = PS_GEN_RAN_FLOAT;
+        }
+    }
+    for (psS32 t2xx = 0 ; t2xx < t2->x->nX+1 ; t2xx++) {
+        for (psS32 t2xy = 0 ; t2xy < t2->x->nY+1 ; t2xy++) {
+            t2->x->coeff[t2xx][t2xy] = PS_GEN_RAN_FLOAT;
+        }
+    }
+    for (psS32 t2yx = 0 ; t2yx < t2->y->nX+1 ; t2yx++) {
+        for (psS32 t2yy = 0 ; t2yy < t2->y->nY+1 ; t2yy++) {
+            t2->y->coeff[t2yx][t2yy] = PS_GEN_RAN_FLOAT;
+        }
+    }
+    return(0);
+}
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(25);
+    srand(RANDOM_SEED);
+
+    // We test psPlaneTransformCombine() with a variety of input transforms
+    // as well as input coordinates
+    //
+    //    The strategy here is to generate a pair of transforms t1 and t2 with a wide
+    //    variety of sizes for the x/y components of the x/y transforms, then set the
+    //    coefficients of t1/t2 to arbitray values, then generate a new transform t3 via
+    //    psPlaneTransformCombine() function.  Then, for several arbitrary input plane
+    //    coordinates, we tarnsform them via the new transform t3, as well as
+    //    individually via t1 then t2, and verify that they produce identical output
+    //    coordinates.
+    //
+    {
+        psMemId id = psMemGetId();
+        bool errorFlag = false;
+        for (psS32 t1xx = 0 ; t1xx < TST04_T1_X_X ; t1xx++)
+        {
+            for (psS32 t1xy = 0 ; t1xy < TST04_T1_X_Y ; t1xy++) {
+                for (psS32 t1yx = 0 ; t1yx < TST04_T1_Y_X ; t1yx++) {
+                    for (psS32 t1yy = 0 ; t1yy < TST04_T1_Y_Y ; t1yy++) {
+                        for (psS32 t2xx = 0 ; t2xx < TST04_T2_X_X ; t2xx++) {
+                            for (psS32 t2xy = 0 ; t2xy < TST04_T2_X_Y ; t2xy++) {
+                                for (psS32 t2yx = 0 ; t2yx < TST04_T2_Y_X ; t2yx++) {
+                                    for (psS32 t2yy = 0 ; t2yy < TST04_T2_Y_Y ; t2yy++) {
+                                        //printf("(%d %d %d %d %d %d %d %d)\n", t1xx, t1xy, t1yx, t1yy, t2xx, t2xy, t2yx, t2yy);
+                                        psPlaneTransform *trans1 = psPlaneTransformAlloc(PS_MAX(t1xx, t1yx), PS_MAX(t1xy, t1yy));
+                                        psPlaneTransform *trans2 = psPlaneTransformAlloc(PS_MAX(t2xx, t2yx), PS_MAX(t2xy, t2yy));
+                                        psPlaneTransform *trans3 = NULL;
+                                        setCoeffs(trans1, trans2);
+                                        trans3 = psPlaneTransformCombine(NULL, trans1,
+                                                                         trans2, psRegionSet(NAN,NAN,NAN,NAN), 0);
+                                        //XXX: the last two parameters are bogus.  Needs to change.  -rdd
+
+                                        if (trans3 == NULL) {
+                                            diag("TEST ERROR: psPlaneTransformCombine() returned NULL");
+                                            errorFlag = true;
+                                        } else {
+                                            bool testStatus = tstTransforms(trans1, trans2, trans3);
+                                            if (!testStatus) {
+                                                diag("TEST ERROR: psPlaneTransformCombine() did not produce correct results");
+                                                errorFlag = true;
+                                            }
+                                        }
+                                        psFree(trans1);
+                                        psFree(trans2);
+                                        psFree(trans3);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        ok(!errorFlag, "psPlaneTransformCombine() successful on a variety of transforms and data points");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Calling psPlaneTransformCombine with NULL trans1
+    // Should generate error and return NULL
+    // XXX: We do not test error generation
+    {
+        psMemId id = psMemGetId();
+        psPlaneTransform *trans2 = psPlaneTransformAlloc(2, 2);
+        psPlaneTransform *trans3 = psPlaneTransformCombine(NULL, NULL, trans2, psRegionSet(0,0,0,0), 10);
+        ok(trans3 == NULL, "psPlaneTransformCombine() returned NULL with NULL trans1 input");
+        psFree(trans2);
+        psFree(trans3);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Calling psPlaneTransformCombine with NULL trans2
+    // Should generate error and return NULL.\n");
+    // XXX: We do not test error generation
+    {
+        psMemId id = psMemGetId();
+        psPlaneTransform *trans1 = psPlaneTransformAlloc(2, 2);
+        psPlaneTransform *trans3 = psPlaneTransformCombine(NULL, trans1, NULL, psRegionSet(0,0,0,0), 10);
+        ok(trans3 == NULL, "psPlaneTransformCombine() returned NULL with NULL trans2 input");
+        psFree(trans1);
+        psFree(trans3);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // XXX: Clean this, put it elsewhere
+    #define TST05_X_MIN 0.0
+    #define TST05_X_MAX 10.0
+    #define TST05_Y_MIN 0.0
+    #define TST05_Y_MAX 10.0
+    #define TST05_NUM_X 5.0
+    #define TST05_NUM_Y 5.0
+    #define TST05_X_POLY_ORDER 3
+    #define TST05_Y_POLY_ORDER 3
+    #define TST05_NUM_DATA (TST05_NUM_X * TST05_NUM_Y)
+    #define TST05_IGNORE 1
+    #define TST05_VERBOSE 0
+
+    // Calling psPlaneTransformFit with NULL trans
+    // Should generate error and return NULL
+    // XXX: We do not test error generation
+    {
+        psArray *src = psArrayAlloc((int) TST05_NUM_DATA);
+        psArray *dst = psArrayAlloc((int) TST05_NUM_DATA);
+        psMemId id = psMemGetId();
+        ok(!psPlaneTransformFit(NULL, src, dst, 100, 100.0), "psPlaneTransformFit() returned FALSE with NULL trans");
+        psFree(src);
+        psFree(dst);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Calling psPlaneTransformFit with NULL src psArray
+    // Should generate error and return NULL
+    // XXX: We do not test error generation
+    {
+        psMemId id = psMemGetId();
+        psPlaneTransform *trans = psPlaneTransformAlloc(TST05_X_POLY_ORDER, TST05_Y_POLY_ORDER);
+        psArray *dst = psArrayAlloc((int) TST05_NUM_DATA);
+        ok(!psPlaneTransformFit(trans, NULL, dst, 100, 100.0), "psPlaneTransformFit() returned FALSE with NULL src psArray");
+        psFree(trans);
+        psFree(dst);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Calling psPlaneTransformFit with NULL dst psArray
+    // Should generate error and return NULL
+    // XXX: We do not test error generation
+    {
+        psMemId id = psMemGetId();
+        psPlaneTransform *trans = psPlaneTransformAlloc(TST05_X_POLY_ORDER, TST05_Y_POLY_ORDER);
+        psArray *src = psArrayAlloc((int) TST05_NUM_DATA);
+        ok(!psPlaneTransformFit(trans, src, NULL, 100, 100.0), "psPlaneTransformFit() returned FALSE with NULL dst psArray");
+        psFree(trans);
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psPlaneTransformFit()
+    // XXX: This is only a rudimentary test of the psPlaneTransformFit() function.
+    //      It tests some simple linear transformations.
+    {
+        psMemId id = psMemGetId();
+        psPlaneTransform *trans = psPlaneTransformAlloc(TST05_X_POLY_ORDER, TST05_Y_POLY_ORDER);
+        psPlaneTransform *transInit = psPlaneTransformAlloc(TST05_X_POLY_ORDER, TST05_Y_POLY_ORDER);
+        psArray *src = psArrayAlloc((int) TST05_NUM_DATA);
+        psArray *dst = psArrayAlloc((int) TST05_NUM_DATA);
+        bool rc;
+
+        // We set an arbitrary non-linear transformation.
+        for (psS32 x = 0 ; x < TST05_X_POLY_ORDER+1 ; x++)
+        {
+            for (psS32 y = 0 ; y < TST05_Y_POLY_ORDER+1 ; y++) {
+                transInit->x->coeff[x][y] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+                transInit->y->coeff[x][y] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+            }
+        }
+        if (TST05_VERBOSE)
+        {
+            PS_POLY_PRINT_2D(transInit->x);
+            PS_POLY_PRINT_2D(transInit->y);
+        }
+
+        // We generate a grid of input data points in the x1,y1 plane, calculate the
+        // corresponding values in the transformed plane, and set these to
+        // the src and dst psVectors.
+        psS32 i = 0;
+        for (psF32 x = TST05_X_MIN ; x < TST05_X_MAX ; x+= (TST05_X_MAX-TST05_X_MIN)/TST05_NUM_X)
+        {
+            for (psF32 y = TST05_Y_MIN ; y < TST05_Y_MAX ; y+= (TST05_Y_MAX-TST05_Y_MIN)/TST05_NUM_Y) {
+                if (i == src->n) {
+                    if (src->n == src->nalloc) {
+                        src = psArrayRealloc(src, src->n+1);
+                    }
+                    src->n++;
+                }
+                if (i == dst->n) {
+                    if (dst->n == dst->nalloc) {
+                        dst = psArrayRealloc(dst, dst->n+1);
+                    }
+                    dst->n++;
+                }
+                src->data[i] = (psPtr *) psPlaneAlloc();
+                ((psPlane *) src->data[i])->x = x;
+                ((psPlane *) src->data[i])->y = y;
+
+                dst->data[i] = psPlaneTransformApply(NULL, transInit, ((psPlane *) src->data[i]));
+                i++;
+            }
+        }
+
+        // Call psPlaneTransformFit with above data arrays
+        rc = psPlaneTransformFit(trans, src, dst, 100, 100.0);
+        ok(rc, "psPlaneTransformFit() returned TRUE");
+        skip_start(!rc, 1, "Skipping tests because psPlaneTransformFit() returned FALSE");
+        if (TST05_VERBOSE)
+        {
+            PS_POLY_PRINT_2D(trans->x);
+            PS_POLY_PRINT_2D(trans->y);
+        }
+
+        // For the initial grid of input points, we transform them to output points with
+        // the derived transformation, and verify that they are within 10%.
+        bool errorFlag = false;
+        for (psS32 i = TST05_IGNORE ; i < src->n-TST05_IGNORE ; i++)
+        {
+            psPlane *inData = (psPlane *) src->data[i];
+            psPlane *outData = (psPlane *) dst->data[i];
+            psPlane *outDataDeriv = psPlaneTransformApply(NULL, trans, inData);
+            if (!PS_PERCENT_COMPARE(outDataDeriv->x, outData->x, 0.20) ||
+                    !PS_PERCENT_COMPARE(outDataDeriv->y, outData->y, 0.20)) {
+                diag("TEST ERROR: the derived output coords (%d) were (%.2f, %.2f) should have been (%.2f, %.2f).\n",
+                     i, outDataDeriv->x, outDataDeriv->y, outData->x, outData->y);
+                errorFlag = true;
+            } else if (TST05_VERBOSE) {
+                diag("GOOD: the derived output coords (%d) were (%.2f, %.2f) should have been (%.2f, %.2f).\n",
+                     i, outDataDeriv->x, outDataDeriv->y, outData->x, outData->y);
+            }
+            psFree(outDataDeriv);
+        }
+        ok(!errorFlag, "The derived transformation was correct");
+        skip_end();
+        psFree(transInit);
+        psFree(trans);
+        psFree(src);
+        psFree(dst);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psPlaneTransformInvert()
+    // Calling psPlaneTransformInvert with NULL trans
+    // Should generate error and return NULL
+    // XXX: We do not test error generation
+    {
+        psMemId id = psMemGetId();
+        psRegion myRegion = psRegionSet(1.0, 5.0, 1.0, 5.0);
+        psPlaneTransform *transInverse = psPlaneTransformInvert(NULL, NULL, myRegion, 10);
+        ok(transInverse == NULL, "psPlaneTransformInvert() returned NULL with NULL trans");
+        psFree(transInverse);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psPlaneTransformInvert()
+    // Calling psPlaneTransformInvert with zero nSamples
+    // Should generate error and return NULL
+    // XXX: We do not test error generation
+    {
+        psMemId id = psMemGetId();
+        psPlaneTransform *trans = psPlaneTransformAlloc(1, 1);
+        psRegion myRegion = psRegionSet(1.0, 5.0, 1.0, 5.0);
+        psPlaneTransform *transInverse = psPlaneTransformInvert(NULL, trans, myRegion, 0);
+        ok(transInverse == NULL, "psPlaneTransformInvert() returned NULL with zero nSamples");
+        psFree(trans);
+        psFree(transInverse);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    #define NUM_TRANSFORMS 100
+    // psPlaneTransformInvert()
+    // This is only a rudimentary test of the psPlaneTransformInvert() function.
+    // It tests: Several random linear transformations.
+    // XXX: Must extensively test non-linear transformations.
+    {
+        psMemId id = psMemGetId();
+        bool errorFlag = false;
+        psPlaneTransform *trans = psPlaneTransformAlloc(1, 1);
+        psPlaneTransform *transInverse = NULL;
+        psRegion myRegion = psRegionSet(1.0, 5.0, 1.0, 5.0);
+
+        trans->x->coeff[0][0] = 0.0;
+        trans->x->coeff[0][1] = 1.0;
+        trans->x->coeff[1][0] = 2.0;
+        trans->x->coeff[1][1] = 3.0;
+        trans->y->coeff[0][0] = 4.0;
+        trans->y->coeff[0][1] = 5.0;
+        trans->y->coeff[1][0] = 6.0;
+        trans->y->coeff[1][1] = 7.0;
+
+        // We calling psPlaneTransformInvert with acceptable linear transformations
+        for (psS32 n = 0 ; n < NUM_TRANSFORMS ; n++)
+        {
+            if (n == 0) {
+                // I ensure that we test the identity transformation since this was
+                // giving us probs before.
+                trans->x->coeff[0][0] = 0.0;
+                trans->x->coeff[0][1] = 0.0;
+                trans->x->coeff[1][0] = 1.0;
+                trans->x->coeff[1][1] = 0.0;
+                trans->y->coeff[0][0] = 0.0;
+                trans->y->coeff[0][1] = 1.0;
+                trans->y->coeff[1][0] = 0.0;
+                trans->y->coeff[1][1] = 0.0;
+            } else {
+                // We create a random linear transformation and hope it is invertible.
+                trans->x->coeff[0][0] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+                trans->x->coeff[0][1] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+                trans->x->coeff[1][0] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+                trans->x->coeff[1][1] = 0.0;
+                trans->y->coeff[0][0] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+                trans->y->coeff[0][1] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+                trans->y->coeff[1][0] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+                trans->y->coeff[1][1] = 0.0;
+            }
+
+            transInverse = psPlaneTransformInvert(NULL, trans, myRegion, 10);
+            if (transInverse == NULL) {
+                diag("TEST ERROR: psPlaneTransformInvert() returned a NULL psPlaneTransform.\n");
+                errorFlag = true;
+            } else {
+                // Transform the "in" coords to "mid" with psPlaneTransform "trans", then
+                // transform "mid" to "out" with psPlaneTransform "transInverse".
+                // XXX: Must loop on a few data points.
+                psPlane *in = psPlaneAlloc();
+                in->x = 2.0;
+                in->y = 3.0;
+                psPlane *mid = psPlaneTransformApply(NULL, trans, in);
+                psPlane *out = psPlaneTransformApply(NULL, transInverse, mid);
+
+                if (((fabs(in->x - out->x) > FLT_EPSILON)) ||
+                        ((fabs(in->y - out->y) > FLT_EPSILON)) ||
+                        isnan(out->x) ||
+                        isnan(out->y)) {
+                    diag("TEST ERROR: in coords were (%f, %f), out coords were (%f, %f).\n",
+                         in->x, in->y, out->x, out->y);
+                    errorFlag = true;
+                }
+                psFree(in);
+                psFree(mid);
+                psFree(out);
+            }
+            psFree(transInverse);
+        }
+        psFree(trans);
+        ok(!errorFlag, "psPlaneTransformInvert() successful on several transforms");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psPlaneTransformDeriv()
+    // Ensure psPlaneTransformDeriv() returns NULL for NULL input plane
+    // Following should generate error message
+    // XXX: un-NULL the first parameter since we test that above
+    // XXX: We do not test error generation
+    {
+        psMemId id = psMemGetId();
+        psPlaneTransform *trans = psPlaneTransformAlloc(1, 3);
+        psPlane *deriv = psPlaneTransformDeriv(NULL, trans, NULL);
+        ok(deriv == NULL, "psPlaneTransformDeriv(NULL, trans, NULL) returned NULL");
+        psFree(trans);
+        psFree(deriv);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psPlaneTransformDeriv()
+    // We test on a very simple transformation.
+    {
+        psMemId id = psMemGetId();
+        psPlane *coord = psPlaneAlloc();
+        psPlane *deriv = NULL;
+        psPlaneTransform *trans = NULL;
+        coord->x = 3.0;
+        coord->y = 1.0;
+        trans = psPlaneTransformAlloc(1, 3);
+        //Set Polynomials.  f(x) = x, f(y) = 0.5*y^2  -->  f'(x) = 1, f'(y) = y
+        //So for 1,1  -> f'(1) = 1, f'(1) = 1
+        trans->x->coeff[0][0] = 0.0;
+        trans->x->coeff[1][0] = 1.0;
+        trans->y->coeff[0][0] = 0.0;
+        trans->y->coeff[0][1] = 0.0;
+        trans->y->coeff[0][2] = 0.5;
+
+        deriv = psPlaneTransformDeriv(NULL, trans, coord);
+        ok(deriv->x == 1.0 && deriv->y == 1.0, "psPlaneTransformDeriv() returned the correct values");
+        psFree(trans);
+        psFree(deriv);
+        psFree(coord);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psEarthOrientation_corrections.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psEarthOrientation_corrections.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psEarthOrientation_corrections.c	(revision 22158)
@@ -0,0 +1,562 @@
+/**
+ *  C Implementation: tap_psEarthOrientation_corrections
+ *
+ * Description:  Tests for p_psEOCInit, p_psEOCFinalize, psAberration,
+ *                         psGravityDeflection, psEOC_PrecessionCorr,
+ *                         psEOC_PolarTideCorr, psEOC_NutationCorr,
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <pslib.h>
+#include <string.h>
+#include "tap.h"
+#include "pstap.h"
+
+static void testEOCInit(void);
+static void testAberration(void);
+static void testGravDef(void);
+static void testEOC_Corrs(void);
+
+#define MJD_1900  15021.0        // Modified Julian Day 1/1/1900 00:00:00
+#define MJD_2100  88069.0        // Modified Julian Day 1/1/2100 00:00:00
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(8);
+
+    // Initialize library internal structures
+    psLibInit("pslib.config");
+
+    testEOCInit();
+    testAberration();
+    testGravDef();
+    testEOC_Corrs();
+    //    testSphereOffsets();
+
+    // Cleanup library
+    psLibFinalize();
+
+    done();
+}
+
+void testEOCInit(void)
+{
+//    diag("  >>>Test 1:  p_psEOCInit ");
+    //Test for psEarthPoleAlloc
+    //Return properly allocated psEarthPole
+    /*    {
+            skip_start(  ep == NULL, 3,
+                         "Skipping 3 tests because psEarthPole is NULL!");
+            ep = psEarthPoleAlloc();
+            ok( ep != NULL,
+                "psEarthPoleAlloc:               return properly allocated psEarthPole.");
+            psFree(ep);
+            ep = NULL;
+        }
+    */
+
+
+    //Check for Memory leaks
+    {
+        checkMem();
+    }
+
+}
+
+void testAberration(void)
+{
+    // psAberration()
+    psSphere *apparent = NULL;
+    psSphere *empty = NULL;
+    psCube *actualCube = psCubeAlloc();
+    //values from After gravity deflection//
+    actualCube->x = -0.35961949760293604;
+    actualCube->y = 0.5555613950298085;
+    actualCube->z = 0.7496835020836093;
+    psSphere *actual = psCubeToSphere(actualCube);
+    psCube *cubeDir = psCubeAlloc();
+    cubeDir->x = 5148.713262821658;
+    cubeDir->y = -26945.04752348012;
+    cubeDir->z = -11682.787302030947;
+    cubeDir->x += -357.6031690489248;
+    cubeDir->y += 248.46429758174693;
+    cubeDir->z += 0.09694774143797581;
+    psSphere *direction = psCubeToSphere(cubeDir);
+    double speed = sqrt(cubeDir->x*cubeDir->x + cubeDir->y*cubeDir->y + cubeDir->z*cubeDir->z);
+    double c = 299792458.0; // Speed of light in vacuum (src:NIST) m/s
+    speed /= c;
+
+    //Tests for psAberration
+    //Return NULL for NULL actual sphere input
+    {
+        empty = psAberration(apparent, NULL, direction, speed);
+        ok( empty == NULL,
+            "psAberration:                   return NULL for NULL actual sphere input.");
+    }
+    //Return NULL for NULL direction sphere input
+    {
+        empty = psAberration(apparent, actual, NULL, speed);
+        ok( empty == NULL,
+            "psAberration:                   return NULL for NULL direction sphere input.");
+    }
+    //Return NULL for speed = 0.0
+    {
+        empty = psAberration(apparent, actual, direction, 0.0);
+        ok( empty == NULL,
+            "psAberration:                   return NULL for zero speed input.");
+    }
+    //Return NULL for speed > 1.0
+    {
+        empty = psAberration(apparent, actual, direction, 1.1);
+        ok( empty == NULL,
+            "psAberration:                   return NULL for impossible speed input (> c).");
+    }
+
+    //Return correct values for valid inputs
+    {
+        double x, y, z;
+        x = -0.35963388069046304;
+        y = 0.5555192509816625;
+        z = 0.7497078321908413;
+        apparent = psAberration(apparent, actual, direction, speed);
+        skip_start(  apparent == NULL, 3,
+                     "Skipping 3 tests because psEarthPole is NULL!");
+        psCube *outCube = psSphereToCube(apparent);
+        is_double_tol( outCube->x, x, 0.001,
+                       "psAberration:                   return correct sphere for valid inputs.");
+        is_double_tol( outCube->y, y, 0.001,
+                       "psAberration:                   return correct sphere for valid inputs.");
+        is_double_tol( outCube->z, z, 0.001,
+                       "psAberration:                   return correct sphere for valid inputs.");
+        psFree(outCube);
+        skip_end();
+    }
+
+    //Check for Memory leaks
+    {
+        psFree(actualCube);
+        psFree(cubeDir);
+        psFree(apparent);
+        psFree(actual);
+        psFree(direction);
+        checkMem();
+    }
+
+}
+
+void testGravDef(void)
+{
+    // psGravityDeflection
+    // Test for psGravityDeflection
+    // Return properly allocated psEarthPole
+    /* XXX: Fix this
+        psSphere *apparent = NULL;
+        psSphere *empty = NULL;
+        psCube *actualCube = psCubeAlloc();
+        actualCube->x = -0.3596195125758298;
+        actualCube->y = 0.5555613903455866;
+        actualCube->z = 0.7496834983724809;
+        psSphere *actual = psCubeToSphere(actualCube);
+        psCube *sunCube = psCubeAlloc();
+        sunCube->x = 1.467797790127511e11;
+        sunCube->y = 2.5880956908748722e10;
+        sunCube->z = 1.1220046291457653e10;
+        double sunLength = sqrt(sunCube->x*sunCube->x + sunCube->y*sunCube->y + sunCube->z*sunCube->z);
+        sunCube->x /= sunLength;
+        sunCube->y /= sunLength;
+        sunCube->z /= sunLength;
+        if (VERBOSE) {
+        printf("sunCube = x,y,z = %.13g, %.13g, %.13g\n",
+        sunCube->x, sunCube->y, sunCube->z);
+    }
+        psSphere *sun = psCubeToSphere(sunCube);
+        if (VERBOSE) {
+        printf("sunSphere  = r, d = %.13g, %.13g\n", sun->r, sun->d);
+    }
+        psCube *outCube = psCubeAlloc();
+     
+        empty = psGravityDeflection(apparent, empty, sun);
+        if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+        "psGravityDeflection Failed to return NULL for NULL actual input sphere.\n");
+        return 1;
+    }
+        empty = psGravityDeflection(apparent, actual, empty);
+        if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+        "psGravityDeflection Failed to return NULL for NULL sun input sphere.\n");
+        return 2;
+    }
+     
+        apparent = psGravityDeflection(NULL, actual, sun);
+        //    apparent->r *= -1.0;
+        //    apparent->d *= -1.0;
+        psSphere *result2;
+        //    psSphere *result2 = psSphereSetOffset(actual, apparent, PS_SPHERICAL, PS_RADIAN);
+        //    psSphere *result = psSphereSetOffset(actual, apparent, PS_SPHERICAL, PS_RADIAN);
+        //    psSphere *result = psSphereGetOffset(apparent, actual, PS_SPHERICAL, PS_RADIAN);
+        if (VERBOSE) {
+        printf(" -- actualCube = x,y,z = %.13g, %.13g, %.13g  -- \n",
+        actualCube->x, actualCube->y, actualCube->z);
+    }
+        //    psCube *outCube = psSphereToCube(result);
+        //    printf(" -- resultCube = x,y,z = %.13g, %.13g, %.13g  -- \n",
+        //           outCube->x, outCube->y, outCube->z);
+        psCube *outCube2 = psSphereToCube(apparent);
+        if (VERBOSE) {
+        printf(" -- resultCube2= x,y,z = %.13g, %.13g, %.13g  -- \n",
+        outCube2->x, outCube2->y, outCube2->z);
+    }
+        double x, y, z;
+        x = -0.35961949760293604;
+        y = 0.5555613950298085;
+        z = 0.7496835020836093;
+     
+        if (VERBOSE) {
+        printf(" -- expectCube = x,y,z = %.13g, %.13g, %.13g  -- \n\n", x, y, z);
+     
+            //    if ( fabs(x - outCube->x) > DBL_EPSILON || fabs(y - outCube->y) > DBL_EPSILON ||
+            //            fabs(z - outCube->z) > DBL_EPSILON ) {
+            //        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+            //                "psGravityDeflection returned incorrect values.\n");
+        printf("expect-actual=  x,y,z  = %.13g, %.13g, %.13g \n",
+        (x - actualCube->x), (y - actualCube->y), (z - actualCube->z) );
+        printf("expect-result=  x,y,z  = %.13g, %.13g, %.13g \n",
+        (x - outCube2->x), (y - outCube2->y), (z - outCube2->z) );
+        printf("result-actual=  x,y,z  = %.13g, %.13g, %.13g \n",
+        (outCube2->x - actualCube->x), (outCube2->y - actualCube->y),
+        (outCube2->z - actualCube->z) );
+    }
+        //        return 1;
+        //    }
+        //    psFree(result2);
+        outCube2->x = x;
+        outCube2->y = y;
+        outCube2->z = z;
+        result2 = psCubeToSphere(outCube2);
+        //    psFree(result);
+        psSphere *result = psSphereGetOffset(actual, result2, PS_SPHERICAL, PS_RADIAN);
+        psFree(result2);
+        result2 = psSphereGetOffset(actual, apparent, PS_SPHERICAL, PS_RADIAN);
+        if (VERBOSE) {
+        printf("The apparent output sphere = r,d = %.13g, %.13g\n", result2->r, result2->d);
+        printf("The expected output sphere = r,d = %.13g, %.13g\n\n", result->r, result->d);
+    }
+        psFree(result2);
+     
+        psFree(outCube);
+        psFree(outCube2);
+        psFree(sunCube);
+        psFree(actualCube);
+        psFree(result);
+        psFree(actual);
+        psFree(apparent);
+        psFree(sun);
+     
+     
+     
+        {
+            skip_start(  ep == NULL, 3,
+                         "Skipping 3 tests because psEarthPole is NULL!");
+            ep = psEarthPoleAlloc();
+            ok( ep != NULL,
+                "psEarthPoleAlloc:               return properly allocated psEarthPole.");
+            psFree(ep);
+            ep = NULL;
+        }
+    */
+
+
+    //Check for Memory leaks
+    {
+        checkMem();
+    }
+
+}
+
+void testEOC_Corrs(void)
+{
+    // psEOC Correction Functions");
+    //Tests for psEOC_PrecessionCorr
+    /* XXX: Fix this
+        psTime *empty = NULL;
+        psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+        time2->sec = timesec;
+        time2->nsec = 0;
+        time2->leapsecond = false;
+        //    time2 = psTimeConvert(time2, PS_TIME_TAI);
+     
+        //Tests for Precession Correction function//
+        //Return NULL for NULL time input
+        psEarthPole *pcorr = NULL;
+        // Following should generate error message
+        pcorr = psEOC_PrecessionCorr(empty, PS_IERS_A);
+        if (pcorr != NULL) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                    "psEOC_PrecessionCorr failed to return NULL for NULL time input.\n");
+            return 5;
+        }
+     
+        //Return NULL for Invalid IERS table
+        // Following should generate error message
+        pcorr = psEOC_PrecessionCorr(time2, 3);
+        if (pcorr != NULL) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                    "psEOC_PrecessionCorr failed to return NULL for incorrect IERS table.\n");
+            return 6;
+        }
+        psFree(pcorr);
+     
+        //Check values from IERS table A
+        pcorr = psEOC_PrecessionCorr(time2, PS_IERS_A);
+        if ( pcorr == NULL ) {
+            psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                    "psEOC_PrecessionCorr returned NULL for valid inputs.\n");
+            return 7;
+        } else {
+            if (VERBOSE) {
+                printf("\nPrecessionCorr output (IERSA) = x,y,s = %.13g,  %.13g, %.13g\n",
+                       pcorr->x, pcorr->y, pcorr->s);
+            }
+        }
+        psFree(pcorr);
+     
+        //Check values from IERS table B
+        pcorr = psEOC_PrecessionCorr(time2, PS_IERS_B);
+        if ( pcorr == NULL ) {
+            psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                    "psEOC_PrecessionCorr returned NULL for valid inputs.\n");
+            return 9;
+        } else {
+            double xx, yy, ss;
+            xx = 0.06295703125;
+            yy = -0.0287618408203125;
+            ss = 0.0;
+            xx = SEC_TO_RAD(xx) * 1e-3;
+            yy = SEC_TO_RAD(yy) * 1e-3;
+            //        if ( fabs(pcorr->x - xx) > DBL_EPSILON || fabs(pcorr->y - yy) > DBL_EPSILON
+            //                || fabs(pcorr->s - ss) > DBL_EPSILON) {
+            //            psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+            //                    "   psEOC_PrecessionCorr return incorrect values.\n");
+            if (VERBOSE) {
+                printf("PrecessionCorr output (IERSB) = x,y,s = %.13g, %.13g, %.13g\n",
+                       pcorr->x, pcorr->y, pcorr->s);
+                printf("Expected output               = x,y,s = %.13g, %.13g, %.13g\n", xx, yy, ss);
+                printf("          A difference of:              %.13g,  %.13g, %.13g\n\n",
+                       (pcorr->x - xx), (pcorr->y - yy), (pcorr->s - ss) );
+            }
+            //            return 10;
+            //        }
+        }
+        //precess is the *actual* output from PrecessionModel + PrecessionCorr
+        psEarthPole *precess = psEOC_PrecessionModel(time2);
+        precess->x += pcorr->x;
+        precess->y += pcorr->y;
+        double xCorr, yCorr;
+        xCorr = 3.05224300720406e-10;
+        yCorr = -1.39441339235822e-10;
+        //pcorr is the *expected* output from PrecessionModel//
+        pcorr->x = 2.857175590089105e-4;
+        pcorr->y = 2.3968739377734732e-5;
+        pcorr->s = -1.3970066457904322e-8;
+        pcorr->x += xCorr;
+        pcorr->y += yCorr;
+        psSphereRot *precessNutInv = psSphereRot_CEOtoGCRS(precess);
+        psSphereRot *precessNut = psSphereRotConjugate(NULL, precessNutInv);
+        double q0, q1, q2;
+        q0 = -1.1984522406756289e-5;
+        q1 = 1.4285893358610674e-4;
+        q2 = 1.2191193518914336e-10;
+        psSphereRot *pni = psSphereRot_CEOtoGCRS(pcorr);
+        if (fabs(pni->q0-q0) > FLT_EPSILON || fabs(pni->q1-q1) > FLT_EPSILON ||
+                fabs(pni->q2-q2) > FLT_EPSILON ) {
+            printf("\n Error at CEOtoGCRS, output psSphereRot doesn't match expected.\n");
+        }
+        //    printf("  Output from CEOtoGCRS only  = %.13g,%.13g,%.13g,%.13g\n",
+        //           pni->q0, pni->q1, pni->q2, pni->q3);
+        if (VERBOSE) {
+            printf("  Expected sphere rotation    = %.13g, %.13g, %.13g\n", q0,q1,q2);
+            printf("  Result sphere rotation      = %.13g, %.13g, %.13g\n",
+                   precessNutInv->q0, precessNutInv->q1, precessNutInv->q2);
+            printf("     Difference         =        %.13g, %.13g, %.13g\n\n",
+                   precessNutInv->q0-q0, precessNutInv->q1-q1, precessNutInv->q2-q2);
+        }
+        psCube *objC = psCubeAlloc();
+        //    objC->x = -3.5963388069046304;
+        //    objC->y = 0.5555192509816625;
+        //    objC->z = 0.7497078321908413;
+        //    objSetup();
+     
+        //This is the sphere rotation for the *expected* precession output//
+        psSphereRot *pn = psSphereRotConjugate(NULL, pni);
+     
+        //    psSphere *sphere = psSphereAlloc();
+        //    *sphere = *obj;
+        //    psFree(obj);
+     
+        //create a psSphere for (from) the start position given in eoc_testing//
+        objC->x = -0.35963388069046304;
+        objC->y = 0.5555192509816625;
+        objC->z = 0.7497078321908413;
+        psSphere *sphere = psCubeToSphere(objC);
+     
+        psSphere *expect = psSphereRotApply(NULL, pn, sphere);
+        //expected results below - stored in:  sphere  //
+        double x,y,z;
+        x = -0.3598480726985338;
+        y = 0.5555012823608123;
+        z = 0.7496183628158023;
+        if (VERBOSE) {
+            printf("\n<<Expected out       = x,y,z = %.13g, %.13g, %.13g\n", x, y, z);
+        }
+        //    psFree(objC);
+        //    objC = psSphereToCube(expect);
+        //printf("<<Expected out (CEO)  = x,y,z = %.13g, %.13g, %.13g\n", objC->x, objC->y, objC->z);
+        //printf("     Difference     =           %.13g, %.13g, %.13g\n", objC->x-x, objC->y-y, objC->z-z);
+        //    x = objC->x;
+        //    y = objC->y;
+        //    z = objC->z;
+        psSphere *result = psSphereRotApply(NULL, precessNut, sphere);
+        psFree(objC);
+        objC = psSphereToCube(result);
+        double xx = greatCircle(result, expect);
+        if (VERBOSE) {
+            printf("<<Resulting out      = x,y,z = %.13g, %.13g, %.13g\n", objC->x, objC->y, objC->z);
+            printf("     Difference         =      %.13g, %.13g, %.13g\n\n",
+                   objC->x-x, objC->y-y, objC->z-z);
+            printf("GREAT CIRCLE DIFFERENCE = %.13g \n", xx);
+        }
+     
+        psFree(precess);
+        psFree(precessNut);
+        psFree(precessNutInv);
+        psFree(expect);
+        psFree(objC);
+     
+        psFree(sphere);
+        psFree(result);
+        psFree(pn);
+        psFree(pni);
+        psFree(pcorr);
+        psFree(time2);
+        if (!p_psEOCFinalize() ) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false, "EOC failed finalization!\n");
+            return 12;
+        }
+     
+    */
+
+    //Tests for psEOC_PolarTideCorr
+    /*
+        psTime *in = psTimeAlloc(PS_TIME_UTC);
+        in->sec = timesec;
+        in->nsec = 0;
+        in->leapsecond = false;
+        psTime *empty = NULL;
+        psEarthPole *eop = NULL;
+     
+        //Return NULL for NULL input time
+        // Following should generate error message
+        eop = psEOC_PolarTideCorr(empty);
+        if (eop != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+        "psEOC_PolarTideCorr failed to return NULL for NULL input time.\n");
+        return 1;
+    }
+     
+        eop = psEOC_PolarTideCorr(in);
+        if (eop == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+        "psEOC_PolarTideCorr returned NULL for valid input time.\n");
+        return 2;
+    } else {
+        if (VERBOSE) {
+        printf("\nPolarTideCorr output = x,y,s = %.13g, %.13g, %.13g\n",
+        eop->x, eop->y, eop->s);
+    }
+    }
+     
+        psFree(in);
+        psFree(eop);
+     
+    */
+
+
+
+    //Tests for psEOC_NutationCorr
+    /*
+        psTime *in = psTimeAlloc(PS_TIME_UTC);
+        in->sec = timesec;
+        in->nsec = 0;
+        in->leapsecond = false;
+        psTime *empty = NULL;
+        psEarthPole *nute = NULL;
+     
+        //Return NULL for NULL input time.
+        // Following should generate error message
+        nute = psEOC_NutationCorr(empty);
+        if (nute != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+        "psEOC_NutationCorr failed to return NULL for NULL input time.\n");
+        return 1;
+    }
+        //Return NULL for UT1 time input
+        *//*    psTime *UT1time = psTimeAlloc(PS_TIME_UT1);
+        nute = psEOC_NutationCorr(UT1time);
+        if (nute != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+        "psEOC_NutationCorr failed to return NULL for UT1 input time.\n");
+        return 2;
+    }
+        psFree(UT1time);
+        *//*
+        //Check return values from valid nutation time input
+        nute = psEOC_NutationCorr(in);
+        if ( nute == NULL ) {
+            psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                    "psEOC_NutationCorr returned NULL for valid input.\n");
+            return 3;
+        } else {
+            if (VERBOSE) {
+                printf("Nutation Correction output = x,y,s = %.13g, %.13g, %.13g\n\n",
+                       nute->x, nute->y, nute->s);
+            }
+        }
+        psFree(nute);
+        psFree(in);
+     
+        if (!p_psEOCFinalize() ) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false, "EOC failed finalization!\n");
+            return 12;
+        }
+     
+    */
+    //Return properly allocated psEarthPole
+    /*
+     
+     
+        {
+            skip_start(  ep == NULL, 3,
+                         "Skipping 3 tests because psEarthPole is NULL!");
+            ep = psEarthPoleAlloc();
+            ok( ep != NULL,
+                "psEarthPoleAlloc:               return properly allocated psEarthPole.");
+            psFree(ep);
+            ep = NULL;
+        }
+    */
+
+
+    //Check for Memory leaks
+    {
+        checkMem();
+    }
+
+}
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psEarthOrientation_motion.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psEarthOrientation_motion.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psEarthOrientation_motion.c	(revision 22158)
@@ -0,0 +1,654 @@
+/**
+ *  C Implementation: tap_psEarthOrientation_motion
+ *
+ * Description:  Tests for psEarthPoleAlloc, psEOC_PrecessionModel, psSpherePrecess
+ *                         psSphereRot_CEOtoGCRS, psSphereRot_TEOtoCEO,
+ *                         psEOC_GetPolarMotion, psSphereRot_ITRStoTEO
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <pslib.h>
+#include <string.h>
+#include "tap.h"
+#include "pstap.h"
+
+static void testPrecessionModel(void);
+static void testPolarMotion(void);
+static void testSphereRots(void);
+static void testSpherePrecess(void);
+#define MJD_1900  15021.0        // Modified Julian Day 1/1/1900 00:00:00
+#define MJD_2100  88069.0        // Modified Julian Day 1/1/2100 00:00:00
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(78);
+
+    // Tests for psEarthOrientation Motion Functions
+    // Initialize library internal structures
+    psLibInit("pslib.config");
+
+    testPrecessionModel();
+    testPolarMotion();
+    testSphereRots();
+    testSpherePrecess();
+
+    psLibFinalize();
+    done();
+}
+
+void testPrecessionModel(void)
+{
+    // psEOC_PrecessionModel
+
+    psEarthPole *ep = NULL;
+
+
+    //Test for psEarthPoleAlloc
+    //Return properly allocated psEarthPole
+    {
+        psMemId id = psMemGetId();
+        ep = psEarthPoleAlloc();
+        ok( ep != NULL, "psEarthPoleAlloc: return properly allocated psEarthPole.");
+        psFree(ep);
+        ep = NULL;
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Tests for psEOC_PrecessionModel
+    //Return NULL for NULL time input.
+    {
+        psMemId id = psMemGetId();
+        ep = psEOC_PrecessionModel(NULL);
+        ok( ep == NULL, "psEOC_PrecessionModel: return NULL for NULL time input.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for UT1 time input.
+    {
+        psMemId id = psMemGetId();
+        psTime *testTime = psTimeAlloc(PS_TIME_UT1);
+        ep = psEOC_PrecessionModel(testTime);
+        ok( ep == NULL, "psEOC_PrecessionModel: return NULL for UT1 time input.");
+        psFree(testTime);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for invalid time input.
+    {
+        psMemId id = psMemGetId();
+        psTime *testTime = psTimeAlloc(PS_TIME_UTC);
+        testTime->nsec = 2e9;
+        ep = psEOC_PrecessionModel(testTime);
+        ok( ep == NULL,
+            "psEOC_PrecessionModel:          return NULL for invalid time input.");
+        testTime->nsec = 0;
+        psFree(testTime);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for failed eoc init - missing file
+    //printf("\n filename = '%s' \n", p_psGetConfigFileName());
+    //XXX: Use the PS_CONFIG_FILE_DEFAULT macro, or PS_CONFIG_FILE environment variable
+    //to define where the real pslib config is.
+    {
+        psMemId id = psMemGetId();
+        psTime *testTime = psTimeAlloc(PS_TIME_UTC);
+        testTime->sec = 1049160600;
+        testTime->nsec = 0;
+        testTime->leapsecond = false;
+        skip_start(rename("../../etc/pslib/pslib.config", "../../etc/pslib/pslib_config.bak"),
+                   1, "Skipping 1 tests because file rename failed!");
+        ep = psEOC_PrecessionModel(testTime);
+        ok( ep == NULL,
+            "psEOC_PrecessionModel:          return NULL for failed eoc init.");
+        rename("../../etc/pslib/pslib_config.bak", "../../etc/pslib/pslib.config");
+        skip_end();
+        psFree(testTime);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return valid EarthPole for valid time input
+    {
+        psMemId id = psMemGetId();
+        psTime *testTime = psTimeAlloc(PS_TIME_UTC);
+        double x, y, s;
+        x = 2.857175590089105e-4;
+        y = 2.3968739377734732e-5;
+        s = -1.3970066457904322e-8;
+        ep = psEOC_PrecessionModel(testTime);
+        skip_start(  ep == NULL, 3,
+                     "Skipping 3 tests because psEarthPole is NULL!");
+        is_double_tol(ep->x, x, 0.1,
+                      "psEOC_PrecessionModel:          return valid EarthPole for valid inputs (x).");
+        is_double_tol(ep->y, y, 0.1,
+                      "psEOC_PrecessionModel:          return valid EarthPole for valid inputs (y).");
+        is_double_tol(ep->s, s, 0.1,
+                      "psEOC_PrecessionModel:          return valid EarthPole for valid inputs (s).");
+        skip_end();
+        psFree(testTime);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    /*
+    //Tests for psMemCheckSphereRot
+    //Make sure psMemCheckSphereRot works correctly - return false
+    {
+    int j = 2;
+    ok( !psMemCheckSphereRot(&j),
+    "psMemCheckSphereRot:            return false for non-SphereRot input.");
+    skip_start(  s1 == NULL, 1,
+    "Skipping 1 tests because psSphereRot is NULL!");
+    skip_end();
+    }
+    */
+    //Check for Memory leaks
+    {
+        psFree(ep);
+        checkMem();
+    }
+
+}
+
+void testPolarMotion(void)
+{
+    // psEOC_GetPolarMotion()
+
+    psTime *in = psTimeAlloc(PS_TIME_UTC);
+    in->sec = 1049160600;
+    in->nsec = 0;
+    in->leapsecond = false;
+    psEarthPole *polarMotion = NULL;
+
+
+    //Tests for psEOC_GetPolarMotion
+    //Return NULL for NULL time input.
+    {
+        psMemId id = psMemGetId();
+        polarMotion = psEOC_GetPolarMotion(NULL, PS_IERS_B);
+        ok( polarMotion == NULL, "psEOC_GetPolarMotion: return NULL for NULL time input.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for invalid IERS table input
+    {
+        psMemId id = psMemGetId();
+        polarMotion = psEOC_GetPolarMotion(NULL, PS_IERS_B+1);
+        ok( polarMotion == NULL, "psEOC_GetPolarMotion: return NULL for invalid IERS table input.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for invalid time input.
+    {
+        psMemId id = psMemGetId();
+        in->nsec = 2e9;
+        polarMotion = psEOC_GetPolarMotion(in, PS_IERS_B);
+        ok( polarMotion == NULL, "psEOC_GetPolarMotion: return NULL for invalid time input.");
+        in->nsec = 0;
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for failed eoc init - missing file
+    //XXX: Use the PS_CONFIG_FILE_DEFAULT macro, or PS_CONFIG_FILE environment variable
+    //to define where the real pslib config is.
+    {
+        psMemId id = psMemGetId();
+        p_psEOCFinalize();
+        skip_start(rename("../../etc/pslib/pslib.config", "../../etc/pslib/pslib_config.bak"),
+                   1, "Skipping 1 tests because file rename failed!");
+        polarMotion = psEOC_GetPolarMotion(in, PS_IERS_B);
+        ok( polarMotion == NULL, "psEOC_GetPolarMotion: return NULL for failed eoc init.");
+        rename("../../etc/pslib/pslib_config.bak", "../../etc/pslib/pslib.config");
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return valid EarthPole for valid time input - IERS B
+    {
+        psMemId id = psMemGetId();
+        double x, y, s;
+        x = -6.454389659777e-07;
+        y = 2.112606414597e-06;
+        s = 0.0;
+        polarMotion = psEOC_GetPolarMotion(in, PS_IERS_B);
+        skip_start(  polarMotion == NULL, 3,
+                     "Skipping 3 tests because psEarthPole is NULL!");
+        is_double_tol(polarMotion->x, x, 0.1,
+                      "psEOC_GetPolarMotion: return valid EarthPole for valid inputs "
+                      "(x) - IERS B.");
+        is_double_tol(polarMotion->y, y, 0.1,
+                      "psEOC_GetPolarMotion: return valid EarthPole for valid inputs "
+                      "(y) - IERS B.");
+        is_double_tol(polarMotion->s, s, 0.1,
+                      "psEOC_GetPolarMotion: return valid EarthPole for valid inputs "
+                      "(s) - IERS B.");
+        skip_end();
+        psFree(polarMotion);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return valid EarthPole for valid time input - IERS A
+    {
+        psMemId id = psMemGetId();
+        double x, y, s;
+        x = -6.45381397904e-07;
+        y = 2.112819726698e-06;
+        s = 0.0;
+        polarMotion = psEOC_GetPolarMotion(in, PS_IERS_A);
+        skip_start(  polarMotion == NULL, 3,
+                     "Skipping 3 tests because psEarthPole is NULL!");
+        is_double_tol(polarMotion->x, x, 0.1,
+                      "psEOC_GetPolarMotion: return valid EarthPole for valid inputs "
+                      "(x) - IERS A.");
+        is_double_tol(polarMotion->y, y, 0.1,
+                      "psEOC_GetPolarMotion: return valid EarthPole for valid inputs "
+                      "(y) - IERS A.");
+        is_double_tol(polarMotion->s, s, 0.1,
+                      "psEOC_GetPolarMotion: return valid EarthPole for valid inputs "
+                      "(s) - IERS A.");
+        skip_end();
+        psFree(polarMotion);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return valid EarthPole for valid time input - IERS A
+    {
+        psMemId id = psMemGetId();
+        psTime *firstTime = psTimeFromMJD(41684.50);
+        polarMotion = psEOC_GetPolarMotion(firstTime, PS_IERS_B);
+        ok( polarMotion != NULL,
+            "psEOC_GetPolarMotion: return valid EarthPole for valid inputs.");
+        psFree(firstTime);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Check for Memory leaks
+    {
+        psFree(in);
+        psFree(polarMotion);
+        checkMem();
+    }
+
+}
+
+static psSphere *objSetup(void)
+{
+    psSphere *obj = NULL;
+    psCube *tempCube = psCubeAlloc();
+    tempCube->x = -0.3598480726985338;
+    tempCube->y = 0.5555012823608123;
+    tempCube->z = 0.7496183628158023;
+    obj = psCubeToSphere(tempCube);
+    psFree(tempCube);
+    return obj;
+}
+
+void testSphereRots(void)
+{
+    // psSphereRot Functions
+    psSphereRot *out = NULL;
+    psEarthPole *in = NULL;
+    double q0,q1,q2,q3;
+    q0 = -1.1984522406756289e-5;
+    q1 = 1.4285893358610674e-4;
+    q2 = 1.2191193518914336e-10;
+    q3 = -0.9999999897238481;
+
+    //Tests for psSphereRot_CEOtoGCRS
+    //Return NULL for NULL earthPole input
+    {
+        psMemId id = psMemGetId();
+        out = psSphereRot_CEOtoGCRS(in);
+        ok( out == NULL, "psSphereRot_CEOtoGCRS: return NULL for NULL earthPole input.");
+        in = psEarthPoleAlloc();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    in->x = 2.857175590089105e-4;
+    in->y = 2.3968739377734732e-5;
+    in->s = -1.3970066457904322e-8;
+    //Return correct psSphereRot for valid input
+    {
+        psMemId id = psMemGetId();
+        out = psSphereRot_CEOtoGCRS(in);
+        skip_start(  out == NULL, 4,
+                     "Skipping 4 tests because psSphereRot output is NULL!");
+        is_double_tol( out->q0, q0, 0.0001,
+                       "psSphereRot_CEOtoGCRS: return correct psSphereRot for valid input (q0).");
+        is_double_tol( out->q1, q1, 0.0001,
+                       "psSphereRot_CEOtoGCRS: return correct psSphereRot for valid input (q1).");
+        is_double_tol( out->q2, q2, 0.0001,
+                       "psSphereRot_CEOtoGCRS: return correct psSphereRot for valid input (q2).");
+        is_double_tol( out->q3, -q3, 0.0001,
+                       "psSphereRot_CEOtoGCRS: return correct psSphereRot for valid input (q3).");
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Tests for psSphereRot_TEOtoCEO
+    psFree(out);
+    psTime *time = psTimeAlloc(PS_TIME_UT1);
+    psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+    time->sec = 1049160600-1;
+    time->nsec = 657017200;
+    time->leapsecond = false;
+    psEarthPole *temp = psEarthPoleAlloc();
+    temp->s = -2.0;
+    //Return NULL for NULL time input
+    {
+        psMemId id = psMemGetId();
+        out = psSphereRot_TEOtoCEO(NULL, NULL);
+        ok( out == NULL, "psSphereRot_TEOtoCEO: return NULL for NULL time input.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for invalid time input - large nsec, UTC time type
+    {
+        psMemId id = psMemGetId();
+        time2->nsec = 3e9;
+        out = psSphereRot_TEOtoCEO(time2, NULL);
+        ok( out == NULL, "psSphereRot_TEOtoCEO: return NULL for invalid time input.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for invalid time input - UT1 time type, large nsec
+    {
+        psMemId id = psMemGetId();
+        psFree(time2);
+        time2 = psTimeAlloc(PS_TIME_UT1);
+        time2->nsec = 1e9;
+        temp->s = 1.0;
+        out = psSphereRot_TEOtoCEO(time2, temp);
+        ok( out == NULL, "psSphereRot_TEOtoCEO: return NULL for invalid time input.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for invalid earthPole input
+    {
+        psMemId id = psMemGetId();
+        time2->nsec = 0;
+        psEarthPole *temp = psEarthPoleAlloc();
+        temp->s = -2.0;
+        out = psSphereRot_TEOtoCEO(time2, temp);
+        ok( out == NULL, "psSphereRot_TEOtoCEO: return NULL for invalid earthPole input.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return correct psSphereRot for valid inputs
+    double x, y, z;
+    x = 0.01698625430807123;
+    y = -0.6616523084626379;
+    z = 0.7496183628158023;
+    {
+        psMemId id = psMemGetId();
+        psEarthPole *polarTideCorr = psEOC_PolarTideCorr(time);
+        out = psSphereRot_TEOtoCEO(time, polarTideCorr);
+        skip_start(  out == NULL, 3,
+                     "Skipping 3 tests because psSphereRot output is NULL!");
+        psSphere *obj = objSetup();
+        psSphereRot *earthRot = psSphereRotConjugate(NULL, out);
+        psSphere *result = psSphereRotApply(NULL, earthRot, obj);
+        psCube *cube = psSphereToCube(result);
+        is_double_tol( cube->x, x, 0.0001,
+                       "psSphereRot_TEOtoCEO: return NULL for NULL time input. (x)");
+        is_double_tol( cube->y, y, 0.0001,
+                       "psSphereRot_TEOtoCEO: return NULL for NULL time input. (y)");
+        is_double_tol( cube->z, z, 0.0001, "psSphereRot_TEOtoCEO: return NULL for NULL time input. (z)");
+        psFree(earthRot);
+        psFree(result);
+        psFree(cube);
+        psFree(obj);
+        skip_end();
+        psFree(polarTideCorr);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Tests for psSphereRot_ITRStoTEO
+    //Return NULL for NULL earthPole input
+    {
+        psMemId id = psMemGetId();
+        psFree(out);
+        out = psSphereRot_ITRStoTEO(NULL);
+        ok( out == NULL,
+            "psSphereRot_ITRStoTEO:         return NULL for NULL earthPole input.");
+        in = psEarthPoleAlloc();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return correct psSphereRot for valid input
+    {
+        psMemId id = psMemGetId();
+        q0 = -1.0567571848664005e-6;
+        q1 = 3.218036562931509e-7;
+        q2 = -3.3580195807204483e-12;
+        q3 = -0.9999999999993899;
+        in->x = SEC_TO_RAD(-0.13275353774074533);
+        in->y = SEC_TO_RAD(0.4359436319739848);
+        in->s = SEC_TO_RAD(-4.2376965863576153e-10);
+        out = psSphereRot_ITRStoTEO(in);
+        skip_start(  out == NULL, 4,
+                     "Skipping 4 tests because psSphereRot output is NULL!");
+        is_double_tol( out->q0, q0, 0.0001,
+                       "psSphereRot_ITRStoTEO: return correct psSphereRot for valid input (q0).");
+        is_double_tol( out->q1, q1, 0.0001,
+                       "psSphereRot_ITRStoTEO: return correct psSphereRot for valid input (q1).");
+        is_double_tol( out->q2, q2, 0.0001,
+                       "psSphereRot_ITRStoTEO: return correct psSphereRot for valid input (q2).");
+        is_double_tol( out->q3, q3, 0.0001,
+                       "psSphereRot_ITRStoTEO: return correct psSphereRot for valid input (q3).");
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    //Check for Memory leaks
+    {
+        psFree(temp);
+        psFree(time2);
+        psFree(time);
+        psFree(out);
+        psFree(in);
+        checkMem();
+    }
+}
+
+#define SPHERE_PRECESS_TP1_R            0.0               //    0.0       degrees
+#define SPHERE_PRECESS_TP1_D            0.0               //    0.0       degrees
+#define SPHERE_PRECESS_TP1_EXPECT_R     6.238453          //  357.437     degrees
+#define SPHERE_PRECESS_TP1_EXPECT_D    -0.019426          //   -1.113     degrees
+#define SPHERE_PRECESS_TP2_R            0.0               //    0.0       degrees
+#define SPHERE_PRECESS_TP2_D            1.570796          //   90.0       degrees
+#define SPHERE_PRECESS_TP2_EXPECT_R     6.260828          //  358.719     degrees
+#define SPHERE_PRECESS_TP2_EXPECT_D     1.551353          //   88.886     degrees
+#define SPHERE_PRECESS_TP3_R            3.141593          //  180.0       degrees
+#define SPHERE_PRECESS_TP3_D            0.523599          //   30.0       degrees
+#define SPHERE_PRECESS_TP3_EXPECT_R     3.096616          //  177.423     degrees
+#define SPHERE_PRECESS_TP3_EXPECT_D     0.543024          //   31.113     degrees
+#define ERROR_TOL   0.0001
+
+void testSpherePrecess(void)
+{
+    // psSpherePrecess
+    psSphereRot *rot = NULL;
+    psTime *fromTime = NULL;
+    psTime *toTime = NULL;
+    psSphere* inputCoord  = psSphereAlloc();
+    psSphere* outputCoord = NULL;
+
+
+    //Return NULL for NULL time inputs
+    {
+        psMemId id = psMemGetId();
+        rot = psSpherePrecess(fromTime, toTime, PS_PRECESS_ROUGH);
+        ok( rot == NULL, "psSpherePrecess: return NULL for NULL time inputs.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for invalid mode input
+    {
+        psMemId id = psMemGetId();
+        fromTime    = psTimeFromMJD(MJD_2100);
+        toTime      = psTimeFromMJD(MJD_1900);
+        rot = psSpherePrecess(fromTime, toTime, -1);
+        ok( rot == NULL, "psSpherePrecess: return NULL for invalid mode input.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return correct psSphereRot for valid inputs, mode = ROUGH
+    {
+        psMemId id = psMemGetId();
+        inputCoord->r = SPHERE_PRECESS_TP1_R;
+        inputCoord->d = SPHERE_PRECESS_TP1_D;
+        inputCoord->rErr = 0.0;
+        inputCoord->dErr = 0.0;
+
+        rot = psSpherePrecess(fromTime, toTime, PS_PRECESS_ROUGH);
+        outputCoord = psSphereRotApply(NULL, rot, inputCoord);
+        if (outputCoord->r < -0.0001)
+            outputCoord->r += 2.0 * M_PI;
+        skip_start( rot == NULL || outputCoord == NULL, 2,
+                    "Skipping 2 tests because psSphereRot output is NULL!");
+        is_double_tol( outputCoord->r, SPHERE_PRECESS_TP1_EXPECT_R, ERROR_TOL,
+                       "psSpherePrecess: return correct psSphereRot for valid"
+                       " inputs and PS_PRECESS_ROUGH mode. (r)");
+        is_double_tol( outputCoord->d, SPHERE_PRECESS_TP1_EXPECT_D, ERROR_TOL,
+                       "psSpherePrecess: return correct psSphereRot for valid"
+                       " inputs and PS_PRECESS_ROUGH mode. (d)");
+        skip_end();
+        psFree(outputCoord);
+        psFree(rot);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return correct psSphereRot for valid inputs, mode = ROUGH
+    {
+        psMemId id = psMemGetId();
+        inputCoord->r = SPHERE_PRECESS_TP2_R;
+        inputCoord->d = SPHERE_PRECESS_TP2_D;
+        inputCoord->rErr = 0.0;
+        inputCoord->dErr = 0.0;
+
+        rot = psSpherePrecess(fromTime, toTime, PS_PRECESS_ROUGH);
+        outputCoord = psSphereRotApply(NULL, rot, inputCoord);
+        if (outputCoord->r < -0.0001)
+            outputCoord->r += 2.0 * M_PI;
+        skip_start( rot == NULL || outputCoord == NULL, 2,
+                    "Skipping 2 tests because psSphereRot output is NULL!");
+        is_double_tol( outputCoord->r, SPHERE_PRECESS_TP2_EXPECT_R, ERROR_TOL,
+                       "psSpherePrecess: return correct psSphereRot for valid"
+                       " inputs and PS_PRECESS_ROUGH mode. (r)");
+        is_double_tol( outputCoord->d, SPHERE_PRECESS_TP2_EXPECT_D, ERROR_TOL,
+                       "psSpherePrecess: return correct psSphereRot for valid"
+                       " inputs and PS_PRECESS_ROUGH mode. (d)");
+        skip_end();
+        psFree(outputCoord);
+        psFree(rot);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return correct psSphereRot for valid inputs, mode = ROUGH
+    {
+        psMemId id = psMemGetId();
+        inputCoord->r = SPHERE_PRECESS_TP3_R;
+        inputCoord->d = SPHERE_PRECESS_TP3_D;
+        inputCoord->rErr = 0.0;
+        inputCoord->dErr = 0.0;
+
+        rot = psSpherePrecess(fromTime, toTime, PS_PRECESS_ROUGH);
+        outputCoord = psSphereRotApply(NULL, rot, inputCoord);
+        if (outputCoord->r < -0.0001)
+            outputCoord->r += 2.0 * M_PI;
+        skip_start( rot == NULL || outputCoord == NULL, 2,
+                    "Skipping 2 tests because psSphereRot output is NULL!");
+        is_double_tol( outputCoord->r, SPHERE_PRECESS_TP3_EXPECT_R, ERROR_TOL,
+                       "psSpherePrecess: return correct psSphereRot for valid"
+                       " inputs and PS_PRECESS_ROUGH mode. (r)");
+        is_double_tol( outputCoord->d, SPHERE_PRECESS_TP3_EXPECT_D, ERROR_TOL,
+                       "psSpherePrecess: return correct psSphereRot for valid"
+                       " inputs and PS_PRECESS_ROUGH mode. (d)");
+        skip_end();
+        psFree(outputCoord);
+        psFree(rot);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return correct psSphereRot for valid inputs, mode = COMPLETE_A
+    {
+        psMemId id = psMemGetId();
+        rot = psSpherePrecess(NULL, toTime, PS_PRECESS_COMPLETE_A);
+        outputCoord = psSphereRotApply(NULL, rot, inputCoord);
+        ok( outputCoord != NULL && rot != NULL,
+            "psSpherePrecess: return correct psSphereRot for valid"
+            " inputs and PS_PRECESS_COMPLETE_A mode.");
+        psFree(outputCoord);
+        psFree(rot);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return correct psSphereRot for valid inputs, mode = COMPLETE_B
+    {
+        psMemId id = psMemGetId();
+        rot = psSpherePrecess(NULL, toTime, PS_PRECESS_COMPLETE_B);
+        outputCoord = psSphereRotApply(NULL, rot, inputCoord);
+        ok( outputCoord != NULL && rot != NULL,
+            "psSpherePrecess: return correct psSphereRot for valid"
+            " inputs and PS_PRECESS_COMPLETE_B mode.");
+        psFree(outputCoord);
+        psFree(rot);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return correct psSphereRot for valid inputs, mode = IAU2000A
+    {
+        psMemId id = psMemGetId();
+        rot = psSpherePrecess(NULL, toTime, PS_PRECESS_IAU2000A);
+        outputCoord = psSphereRotApply(NULL, rot, inputCoord);
+        ok( outputCoord != NULL && rot != NULL,
+            "psSpherePrecess: return correct psSphereRot for valid"
+            " inputs and PS_PRECESS_IAU2000A mode.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    //Check for Memory leaks
+    {
+        psFree(fromTime);
+        psFree(toTime);
+        psFree(outputCoord);
+        psFree(rot);
+        checkMem();
+    }
+
+}
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psSphereOps_all.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psSphereOps_all.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psSphereOps_all.c	(revision 22158)
@@ -0,0 +1,567 @@
+/**
+ *  C Implementation: tap_psSphereOps_all
+ *
+ * Description:  Tests for psSphereRotAlloc, psMemCheckSphereRot, psSphereRotQuat,
+ *                         psSphereRotApply, psSphereRotCombine, psSphereRotConjugate,
+ *                         psSphereRotInvert, psSphereGetOffset, psSphereSetOffset,
+ *                         psSphereRotICRSToEcliptic, psSphereRotEclipticToICRS,
+ *                         psSphereRotICRSToGalactic, psSphereRotGalacticToICRS
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <pslib.h>
+#include <string.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define DEG_INC   30.0
+#define MJD_1900  15021.0        // Modified Julian Day 1/1/1900 00:00:00
+#define MJD_2000  51544.0        // Modified Julian Day 1/1/2000 00:00:00
+#define MJD_2100  88069.0        // Modified Julian Day 1/1/2100 00:00:00
+#define ERROR_TOL   0.0001
+#define ALPHA_P 4*M_PI/3
+#define DELTA_P M_PI/4
+#define PHI_P M_PI/3
+
+static void testSphereRotCreate(void);
+static void testSphereRotConvert(void);
+static void testSphereOffsets(void);
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    plan_tests(86);
+    testSphereRotCreate();
+    testSphereRotConvert();
+    testSphereOffsets();
+}
+
+void testSphereRotCreate(void)
+{
+    // ----------------------------------------------------------------
+    //Tests for psSphereRotAlloc
+    //Return NULL for NAN input alpha
+    {
+        psMemId id = psMemGetId();
+        psSphereRot *s1 = psSphereRotAlloc(NAN, DELTA_P, PHI_P);
+        ok( s1 == NULL, "psSphereRotAlloc(): return NULL for NAN input alpha");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for NAN input delta
+    {
+        psMemId id = psMemGetId();
+        psSphereRot *s1 = psSphereRotAlloc(ALPHA_P, NAN, PHI_P);
+        ok( s1 == NULL, "psSphereRotAlloc(): return NULL for NAN input delta");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for NAN input phi
+    {
+        psMemId id = psMemGetId();
+        psSphereRot *s1 = psSphereRotAlloc(ALPHA_P, DELTA_P, NAN);
+        ok( s1 == NULL, "psSphereRotAlloc(): return NULL for NAN input phi");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    double a0 = (ALPHA_P - PHI_P)/2.0;
+    double a1 = (ALPHA_P - PHI_P)/2.0;
+    double a2 = (ALPHA_P + PHI_P)/2.0;
+    double a3 = (ALPHA_P + PHI_P)/2.0;
+    //From Mathworld, this is another way to calculate the quaternions of a rotation
+    double q0 = sin(a0)*sin(DELTA_P/2);
+    double q1 = cos(a1)*sin(DELTA_P/2);
+    double q2 = sin(a2)*cos(DELTA_P/2);
+    double q3 = cos(a3)*cos(DELTA_P/2);
+    // Test psSphereRot() for valid inputs
+    {
+        psMemId id = psMemGetId();
+        psSphereRot* myST = NULL;
+        myST = psSphereRotAlloc(ALPHA_P, DELTA_P, PHI_P);
+        ok(myST != NULL && psMemCheckSphereRot(myST),
+            "psSphereRotAlloc:  return allocated SphereRot for valid inputs.");
+        is_double(q0, myST->q0, "psSphereRotAlloc: return correct q0 value.");
+        is_double(q1, myST->q1, "psSphereRotAlloc: return correct q1 value.");
+        is_double(q2, myST->q2, "psSphereRotAlloc: return correct q2 value.");
+        is_double(q3, myST->q3, "psSphereRotAlloc: return correct q3 value.");
+        psFree(myST);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------
+    //Tests for psMemCheckSphereRot
+    //Make sure psMemCheckSphereRot works correctly - return false
+    //for non-psSphereRot input
+    {
+        psMemId id = psMemGetId();
+        int j = 2;
+        ok( !psMemCheckSphereRot(&j), "psMemCheckSphereRot: return false for non-SphereRot input.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------
+    //Tests for psSphereRotQuat
+    //Return NULL for NAN input q0
+    {
+        psMemId id = psMemGetId();
+        psSphereRot *s1 = psSphereRotQuat(NAN, q1, q2, q3);
+        ok( s1 == NULL, "psSphereRotQuat: return NULL for NAN input q0");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for NAN input q1
+    {
+        psMemId id = psMemGetId();
+        psSphereRot *s1 = psSphereRotQuat(q0, NAN, q2, q3);
+        ok( s1 == NULL, "psSphereRotQuat: return NULL for NAN input q1");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for NAN input q2
+    {
+        psMemId id = psMemGetId();
+        psSphereRot *s1 = psSphereRotQuat(q0, q1, NAN, q3);
+        ok( s1 == NULL, "psSphereRotQuat: return NULL for NAN input q2");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for NAN input q3
+    {
+        psMemId id = psMemGetId();
+        psSphereRot *s1 = psSphereRotQuat(q0, q1, q2, NAN);
+        ok( s1 == NULL, "psSphereRotQuat: return NULL for NAN input q3");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return valid psSphereRot (allocated) for valid inputs
+    psSphereRot* myST = psSphereRotQuat(q0*2.0, q1*2.0, q2*2.0, q3*2.0);
+    {
+        psMemId id = psMemGetId();
+        ok( myST != NULL && psMemCheckSphereRot(myST),
+            "psSphereRotQuat: return allocated SphereRot for valid inputs.");
+        is_double(q0, myST->q0, "psSphereRotQuat: return correct q0 value.");
+        is_double(q1, myST->q1, "psSphereRotQuat: return correct q1 value.");
+        is_double(q2, myST->q2, "psSphereRotQuat: return correct q2 value.");
+        is_double(q3, myST->q3, "psSphereRotQuat: return correct q3 value.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
+
+void testSphereRotConvert(void)
+{
+    // Allocate data structure
+    psSphereRot* myST = NULL;
+    psSphereRot* s1 = NULL;
+    psSphereRot *s2 = NULL;
+    myST = psSphereRotAlloc(ALPHA_P, DELTA_P, PHI_P);
+    psSphere *sphere = psSphereAlloc();
+    sphere->r = 0.0;
+    sphere->d = 0.0;
+    psSphere *out = NULL;
+    psSphere *out2 = NULL;
+    psTime *pre1900 = psTimeFromMJD(MJD_1900 - 100.0);
+    psTime *mjd2k = psTimeFromMJD(MJD_2000);
+    psSphere* icrs = psSphereAlloc();
+    psSphere* galactic = NULL;
+    icrs->r = DEG_TO_RAD(0.0);
+    icrs->d = DEG_TO_RAD(90.0);
+
+
+    // ---------------------------------------------------------
+    //Tests for psSphereRotCombine
+    //Return NULL for NULL sphere input
+    {
+        psMemId id = psMemGetId();
+        s1 = psSphereRotCombine(s1, myST, NULL);
+        ok( s1 == NULL, "psSphereRotCombine: return NULL for NULL input.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for NULL transform input
+    {
+        psMemId id = psMemGetId();
+        s1 = psSphereRotCombine(s1, NULL, myST);
+        ok( s1 == NULL, "psSphereRotCombine: return NULL for NULL input.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    // XXX: Must test with legitimate input data.
+
+
+    // ---------------------------------------------------------
+    //Tests for psSphereRotApply
+    //Return NULL for NULL sphere input
+    {
+        psMemId id = psMemGetId();
+        out = psSphereRotApply(out, myST, NULL);
+        ok( out == NULL, "psSphereRotApply: return NULL for NULL sphere input.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for NULL transform input
+    {
+        psMemId id = psMemGetId();
+        out = psSphereRotApply(out, NULL, sphere);
+        ok( out == NULL, "psSphereRotApply: return NULL for NULL transform input.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ---------------------------------------------------------
+    //Tests for psSphereRotConjugate
+    //Return NULL for NULL inputs
+    {
+        psMemId id = psMemGetId();
+        s1 = psSphereRotConjugate(s1, NULL);
+        ok(s1 == NULL, "psSphereRotConjugate: return NULL SphereRot for NULL inputs");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    //Return correct conjugate for valid inputs
+    {
+        psMemId id = psMemGetId();
+        s1 = psSphereRotConjugate(s1, myST);
+        skip_start(s1 == NULL, 1, "Skipping 1 tests because psSphereRot is NULL!");
+        out = psSphereRotApply(out, myST, sphere);
+        skip_start(out == NULL || out->r == 0, 2,
+                  "Skipping 1 tests because psSphereRotApply failed!");
+        out2 = psSphereRotApply(out2, s1, out);
+        is_double( out2->r, 0.0, "psSphereRotConjugate: return correct SphereRot values.");
+        is_double( out2->d, 0.0, "psSphereRotConjugate: return correct SphereRot values.");
+        skip_end();
+        psFree(s1);
+        psFree(out);
+        psFree(out2);
+        s1 = NULL;
+        out = NULL;
+        out2 = NULL;
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ---------------------------------------------------------
+    //Tests for psSphereRotInvert
+    //Return correct inversion for valid inputs
+    {
+        psMemId id = psMemGetId();
+        s1 = psSphereRotInvert(-PHI_P, -DELTA_P, -ALPHA_P);
+        is_double(s1->q0, myST->q0, "psSphereRotInvert: return correct q0 value.");
+        is_double(s1->q1, myST->q1, "psSphereRotInvert: return correct q1 value.");
+        is_double(s1->q2, myST->q2, "psSphereRotInvert: return correct q2 value.");
+        is_double(s1->q3, myST->q3, "psSphereRotInvert: return correct q3 value.");
+        psFree(s1);
+        s1 = NULL;
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ---------------------------------------------------------
+    //Tests for psSphereRotICRSToEcliptic
+    //Return NULL for NULL input
+    {
+        psMemId id = psMemGetId();
+        s1 = psSphereRotICRSToEcliptic(NULL);
+        ok( s1 == NULL, "psSphereRotICRSToEcliptic: return NULL SphereRot for NULL inputs.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for Pre-MJD_1900 Date
+    {
+        psMemId id = psMemGetId();
+        s1 = psSphereRotICRSToEcliptic(pre1900);
+        ok( s1 == NULL, "psSphereRotICRSToEcliptic: return NULL SphereRot for pre-1900 MJD date.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return correct SphereRot for MJD_2000
+    {
+        psMemId id = psMemGetId();
+        s1 = psSphereRotICRSToEcliptic(mjd2k);
+        skip_start(  s1 == NULL, 2, "Skipping 2 tests because psSphereRot is NULL!");
+        icrs->r = DEG_TO_RAD(0.0);
+        icrs->d = DEG_TO_RAD(90.0);
+        psSphere* ecliptic = psSphereRotApply(NULL, s1, icrs);
+        is_double_tol(DEG_TO_RAD(90.0), ecliptic->r, 0.00001,
+                      "psSphereRotICRSToEcliptic: return correct SphereRot for MJD_2000 date.");
+        is_double_tol(DEG_TO_RAD(66.560719), ecliptic->d, 0.00001,
+                      "psSphereRotICRSToEcliptic: return correct SphereRot for MJD_2000 date.");
+        psFree(ecliptic);
+        skip_end();
+        psFree(s1);
+        s1 = NULL;
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // --------------------------------------------------------------
+    //Tests for psSphereRotEclipticToICRS
+    //Return NULL for NULL input
+    {
+        psMemId id = psMemGetId();
+        s1 = psSphereRotEclipticToICRS(NULL);
+        ok( s1 == NULL, "psSphereRotEclipticToICRS: return NULL SphereRot for NULL inputs.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for Pre-MJD_1900 Date
+    {
+        psMemId id = psMemGetId();
+        s1 = psSphereRotEclipticToICRS(pre1900);
+        ok( s1 == NULL, "psSphereRotEclipticToICRS: return NULL SphereRot for pre-1900 MJD date.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return correct SphereRot for MJD_2000
+    {
+        psMemId id = psMemGetId();
+        s1 = psSphereRotEclipticToICRS(mjd2k);
+        skip_start(  s1 == NULL, 2, "Skipping 2 tests because psSphereRot is NULL!");
+        psSphere* ecliptic = psSphereRotApply(NULL, s1, icrs);
+        s2 = psSphereRotICRSToEcliptic(mjd2k);
+        psSphere* fromEcliptic = psSphereRotApply(NULL, s2, ecliptic);
+        //XXX:  Pretty sure the following can be 180 degrees OR 0 degrees. (= the poles)
+        is_double_tol(DEG_TO_RAD(180.0), fromEcliptic->r, 0.00001,
+                      "psSphereRotEclipticToICRS: return correct SphereRot for MJD_2000 date.");
+        is_double_tol(DEG_TO_RAD(90.0), fromEcliptic->d, 0.00001,
+                      "psSphereRotEclipticToICRS: return correct SphereRot for MJD_2000 date.");
+        psFree(ecliptic);
+        psFree(fromEcliptic);
+        skip_end();
+        psFree(s1);
+        s1 = NULL;
+        psFree(s2);
+        s2 = NULL;
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // --------------------------------------------------------------
+    //Tests for psSphereRotICRSToGalactic
+    //Return correct transformation
+    {
+        psMemId id = psMemGetId();
+        s2 = psSphereRotICRSToGalactic();
+        galactic = psSphereRotApply(NULL, s2, icrs);
+        is_double_tol(DEG_TO_RAD(122.93192), galactic->r, 0.00001,
+                      "psSphereRotICRSToGalactic: return correct SphereRot.");
+        is_double_tol(DEG_TO_RAD(27.12825), galactic->d, 0.00001,
+                      "psSphereRotICRSToGalactic: return correct SphereRot.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // --------------------------------------------------------------
+    //Tests for psSphereRotGalacticToICRS
+    //Return correct transformation
+    {
+        psMemId id = psMemGetId();
+        s1 = psSphereRotGalacticToICRS();
+        psSphere *test = psSphereRotApply(NULL, s1, galactic);
+        //XXX: Pretty sure the following can be 180 degrees OR 0 degrees. (= the poles)
+        is_double_tol(DEG_TO_RAD(180.0), test->r, 0.00001,
+                      "psSphereRotGalacticToICRS: return correct SphereRot.");
+        is_double_tol(DEG_TO_RAD(90.0), test->d, 0.00001,
+                      "psSphereRotGalacticToICRS: return correct SphereRot.");
+        psFree(test);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    {
+        psFree(galactic);
+        psFree(s2);
+        psFree(s1);
+        psFree(mjd2k);
+        psFree(pre1900);
+        psFree(icrs);
+        psFree(sphere);
+        psFree(myST);
+    }
+
+}
+
+
+void testSphereOffsets(void)
+{
+    psSphereRot* myST = NULL;
+    myST = psSphereRotAlloc(ALPHA_P, DELTA_P, PHI_P);
+
+    psSphere *origin = psSphereAlloc();
+    psSphere *offset = psSphereAlloc();
+    psSphere *empty = NULL;
+    psSphere *output = NULL;
+
+    // -----------------------------------------------------------
+    //Tests for psSphereGetOffset
+    //Test Get for NULL position1
+    {
+        output = psSphereGetOffset(empty, origin, PS_LINEAR, PS_RADIAN);
+        ok( output == NULL, "psSphereGetOffset: return NULL for NULL position1 input.");
+    }
+
+
+    //Test Get for NULL position2
+    {
+        output = psSphereGetOffset(origin, empty, PS_LINEAR, PS_RADIAN);
+        ok( output == NULL, "psSphereGetOffset: return NULL for NULL position2 input.");
+    }
+
+
+    //Return NULL for position1 declination > 90 degrees
+    {
+        origin->d = 100.0;
+        output = psSphereGetOffset(origin, offset, PS_LINEAR, PS_RADIAN);
+        ok( output == NULL, "psSphereGetOffset: return NULL for position1->d > 90 degrees.");
+    }
+
+
+    //Return NULL for position1 declination > 90 degrees
+    {
+        origin->d = 0.0;
+        offset->d = 100.0;
+        output = psSphereGetOffset(origin, offset, PS_LINEAR, PS_RADIAN);
+        ok( output == NULL, "psSphereGetOffset: return NULL for position2->d > 90 degrees.");
+    }
+
+
+    //Return NULL for invalid mode specification
+    {
+        offset->d = 0.0;
+        output = psSphereGetOffset(origin, offset, -1, PS_RADIAN);
+        ok( output == NULL, "psSphereGetOffset: return NULL for invalid mode input.");
+    }
+
+
+    //Return NULL for invalid unit specification
+    {
+        output = psSphereGetOffset(origin, offset, PS_SPHERICAL, -1);
+        ok( output == NULL, "psSphereGetOffset: return NULL for invalid unit input.");
+    }
+    //Return matching sphere offsets regardless of units
+    {
+        offset->r = (M_PI / 4.0);     //45 deg
+        offset->d = (M_PI / 6.0);     //30 deg
+        output = psSphereGetOffset(origin, offset, PS_SPHERICAL, PS_ARCMIN);
+        empty = psSphereGetOffset(origin, offset, PS_SPHERICAL, PS_DEGREE);
+        is_double_tol(DEG_TO_RAD(empty->r), MIN_TO_RAD(output->r), 0.0001,
+                      "psSphereGetOffset: return correct offset for differing units.");
+        is_double_tol(DEG_TO_RAD(empty->d), MIN_TO_RAD(output->d), 0.0001,
+                      "psSphereGetOffset: return correct offset for differing units.");
+        psFree(output);
+        psFree(empty);
+    }
+
+    //Tests for psSphereSetOffset
+    output = NULL;
+    empty = NULL;
+    //Return NULL for NULL position
+    {
+        output = psSphereSetOffset(empty, offset, PS_SPHERICAL, PS_DEGREE);
+        ok( output == NULL, "psSphereSetOffset: return NULL for NULL position input.");
+    }
+    //Return NULL for NULL offset
+    {
+        output = psSphereSetOffset(offset, empty, PS_SPHERICAL, PS_DEGREE);
+        ok( output == NULL, "psSphereSetOffset: return NULL for NULL offset input.");
+    }
+    //Return NULL for invalid mode specification
+    {
+        output = psSphereSetOffset(origin, offset, -1, PS_RADIAN);
+        ok( output == NULL, "psSphereSetOffset: return NULL for for invalid mode input.");
+    }
+    //Return NULL for invalid unit specification
+    {
+        output = psSphereSetOffset(origin, offset, PS_SPHERICAL, PS_RADIAN+1);
+        ok( output == NULL, "psSphereSetOffset: return NULL for for invalid unit input.");
+    }
+    //Test Set using Spherical mode, Degree units
+    origin->r = 0.0;
+    origin->d = 0.0;
+    offset->r = 45.0;
+    offset->d = 30.0;
+    {
+        output = psSphereSetOffset(origin, offset, PS_SPHERICAL, PS_DEGREE);
+        skip_start(output == NULL, 2, "Skipping 2 tests because Sphere output is NULL!");
+        is_double(output->r, M_PI/4.0, "psSphereSetOffset: return correct spherical offset.");
+        is_double(output->d, M_PI/6.0, "psSphereSetOffset: return correct spherical offset.");
+        skip_end();
+        psFree(output);
+    }
+    //Test Set and Get using Linear mode, Radian units
+    origin->r = 0.0;
+    origin->d = 0.0;
+    offset->r = 1.0;
+    offset->d = 1.0;
+    {
+        output = psSphereSetOffset(origin, offset, PS_LINEAR, PS_RADIAN);
+        empty = psSphereGetOffset(origin, output, PS_LINEAR, PS_RADIAN);
+        skip_start(empty == NULL, 2, "Skipping 2 tests because Sphere output is NULL!");
+        is_double_tol(empty->r, offset->r, 0.00001,
+                      "psSphereGetOffset: return correct spherical offset.");
+        is_double_tol(empty->d, offset->d, 0.00001,
+                      "psSphereGetOffset: return correct spherical offset.");
+        skip_end();
+        psFree(output);
+        psFree(empty);
+    }
+    //Test Set using SPHERICAL mode, Arcmin units
+    origin->r = 0.0;
+    origin->d = 0.0;
+    offset->r = RAD_TO_MIN(M_PI / 4.0);     //45 deg
+    offset->d = RAD_TO_MIN(M_PI / 6.0);     //30 deg
+    {
+        output = psSphereSetOffset(origin, offset, PS_SPHERICAL, PS_ARCMIN);
+        //Test Get using Spherical mode, Arcsec units
+        empty = psSphereGetOffset(origin, output, PS_SPHERICAL, PS_ARCSEC);
+        empty->r = SEC_TO_RAD(empty->r);
+        empty->d = SEC_TO_RAD(empty->d);
+        skip_start(empty == NULL, 2, "Skipping 2 tests because Sphere output is NULL!");
+        is_double_tol(empty->r, (M_PI / 4.0), 0.0001,
+                      "psSphereGetOffset: return correct spherical offset.");
+        is_double_tol(empty->d, (M_PI / 6.0), 0.0001,
+                      "psSphereGetOffset: return correct spherical offset.");
+        skip_end();
+        psFree(output);
+        psFree(empty);
+    }
+    //Return matching sphere offsets regardless of units
+    {
+        offset->r = RAD_TO_SEC(M_PI / 4.0);     //45 deg
+        offset->d = RAD_TO_SEC(M_PI / 6.0);     //30 deg
+        output = psSphereSetOffset(origin, offset, PS_SPHERICAL, PS_ARCSEC);
+        offset->r = (M_PI / 4.0);     //45 deg
+        offset->d = (M_PI / 6.0);     //30 deg
+        empty = psSphereSetOffset(origin, offset, PS_SPHERICAL, PS_RADIAN);
+        is_double_tol(empty->r, offset->r, 0.0001,
+                      "psSphereSetOffset: return correct offset for differing units.");
+        is_double_tol(empty->d, offset->d, 0.0001,
+                      "psSphereSetOffset: return correct offset for differing units.");
+        psFree(output);
+        psFree(empty);
+    }
+
+    //Check for Memory leaks
+    {
+        psFree(origin);
+        psFree(offset);
+        psFree(myST);
+        checkMem();
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psTime_01.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psTime_01.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psTime_01.c	(revision 22158)
@@ -0,0 +1,1155 @@
+/** @file  tst_psTime_01.c
+ *
+ *  @brief Test driver for psTime functions
+ *
+ *  This test driver contains the following tests for psTime:
+ *     1) Allocate psTime structure
+ *     2) Get current time
+ *     3) Get UT1 UTC delta
+ *     4) Convert psTime to MJD
+ *     5) Convert psTime to JD
+ *     6) Convert psTime to ISO
+ *     7) Convert psTime to timeval
+ *     8) Create psTime from MJD
+ *     9) Create psTime from JD
+ *    10) Create psTime from ISO
+ *    11) Create psTime from timeval
+ *    12) Create psTime from TM
+ *    13) Convert time between different types
+ *
+ *     O) Convert psTime time to LMST
+ *
+ *  @author  Ross Harman, MHPCC
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.7 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2007-06-05 01:10:22 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define ERROR_TOL    0.0001
+
+// Test Time 1 : July 21, 2004  18:22:24.3
+//               MJD = 53207.765559
+//               JD = 2453208.265559
+// UTC Test Time 1
+const psS64 testTime1SecondsUTC     = 1090434144;
+const psU32 testTime1NanosecondsUTC = 272044000;
+// TAI Test Time 1
+const psS64 testTime1SecondsTAI     = 1090434176;
+const psU32 testTime1NanosecondsTAI = 272044000;
+const psF64 testTime1MJDTAI         = 53207.76592937;
+const psF64 testTime1JDTAI          = 2453208.26592937;
+
+// TT Test Time 1
+const psS64 testTime1SecondsTT      = 1090434208;
+const psU32 testTime1NanosecondsTT  = 456044000;
+// Expected UT1-UTC IERS A & B
+const psF64 testTime1UT1DeltaBullA  = -0.457233186;
+const psF64 testTime1UT1DeltaBullB  = -0.457227;
+// UT1 Test Time 1
+const psS64 testTime1SecondsUT1     = 1090434143;
+//const psU32 testTime1NanosecondsUT1 = 814810814;
+const psU32 testTime1NanosecondsUT1 = 814810861;
+// Expected MJD & JD
+const psF64 testTime1MJD            = 53207.765559;
+const psF64 testTime1JD             = 2453208.265559;
+// Expected ISO string
+const char* testTime1Str     = "2004-07-21T18:22:24.2Z";
+const char* testTime1StrLeap = "2004-07-21T18:22:60.2Z";
+// Expected timeval values
+const psS32 testTime1TimevalSec = 1090434144;
+const psS32 testTime1TimevalUsec = 272044;
+
+// Test Time 2 : Jan. 1, 1973 00:00:00.0000
+//               MJD = 41683.0000
+//               JD = 2441683.5000
+const psS64 testTime2SecondsUTC     = 94694400;
+const psU32 testTime2NanosecondsUTC = 0;
+
+// Expected UT1-UTC IERS A & B
+const psF64 testTime2UT1DeltaBullA  = 0.000000;
+const psF64 testTime2UT1DeltaBullB  = 0.000000;
+
+// Test Time 3 : Sept. 21, 2006 00:00:00.0000
+//               MJD = 53999
+//               JD = 2453999.5
+const psS64 testTime3SecondsUTC     = 1158796800;
+const psU32 testTime3NanosecondsUTC = 0;
+// Expected UT1-UTC IERS A & B
+const psF64 testTime3UT1DeltaBullA  = -0.63574;
+const psF64 testTime3UT1DeltaBullB  = -0.63574;
+
+// Test Time 4 : Jan. 1, 1969 00:00:00.0000
+//               MJD = 40222
+//               JD = 2440222.5
+const psS64 testTime4SecondsUTC     = -31536000;
+const psU32 testTime4NanosecondsUTC = 0;
+// Expected MJD and JD
+const psF64 testTime4MJD            = 40222.0;
+const psF64 testTime4JD             = 2440222.5;
+
+// Test Time 5 : Dec 31, 0001 BC 23:59:59
+//               MJD = -1397755
+//               JD = 1002245.4999
+const psS64 testTime5SecondsUTC     = -62125920001;
+const psU32 testTime5NanosecondsUTC  = 0;
+
+// Test Time 6 : Jan. 1, 10000 AD 00:00:00
+const psS64 testTime6SecondsUTC      = 253202544001;
+const psU32 testTime6NanosecondsUTC  = 0;
+
+// Test Time 7 : Jan. 1, 2004 00:00:00,0
+const psS64 testTime7Seconds         = 1072915200;
+const psU32 testTime7Nanoseconds     = 0;
+const psS32 testTime7TmYear          = 104;
+const psS32 testTime7TmMon           = 0;
+const psS32 testTime7TmDay           = 1;
+const psS32 testTime7TmHour          = 0;
+const psS32 testTime7TmMin           = 0;
+const psS32 testTime7TmSec           = 0;
+
+// Test Time 8 : Dec. 31, 2003 00:00:00,0
+const psS64 testTime8Seconds         = 1072828800;
+const psU32 testTime8Nanoseconds     = 0;
+const psS32 testTime8TmYear          = 103;
+const psS32 testTime8TmMon           = 11;
+const psS32 testTime8TmDay           = 31;
+const psS32 testTime8TmHour          = 0;
+const psS32 testTime8TmMin           = 0;
+const psS32 testTime8TmSec           = 0;
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(198);
+    // Initialize library internal structures
+    psLibInit("pslib.config");
+
+
+    // Allocate new psTime with unallowed time type
+    // Following should generate error message
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(-100);
+        ok(time == NULL, "psTimeAlloc(-100) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeAlloc(TAI)
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        ok(time != NULL, "psTimeAlloc() did not return NULL");
+        skip_start(time == NULL, 4, "Skipping tests because psTimeAlloc() failed");
+        ok(time->type == PS_TIME_TAI, "psTimeAlloc() correctly set psTime->type");
+        ok(time->sec == 0, "psTimeAlloc() correctly set psTime->sec");
+        ok(time->nsec == 0, "psTimeAlloc() correctly set psTime->nsec");
+        ok(time->leapsecond == false, "psTimeAlloc() correctly set psTime->leapsecond");
+        psFree(time);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeAlloc(UTC)
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        ok(time != NULL, "psTimeAlloc() did not return NULL");
+        skip_start(time == NULL, 4, "Skipping tests because psTimeAlloc() failed");
+        ok(time->type == PS_TIME_UTC, "psTimeAlloc() correctly set psTime->type");
+        ok(time->sec == 0, "psTimeAlloc() correctly set psTime->sec");
+        ok(time->nsec == 0, "psTimeAlloc() correctly set psTime->nsec");
+        ok(time->leapsecond == false, "psTimeAlloc() correctly set psTime->leapsecond");
+        psFree(time);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeAlloc(UT1)
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UT1);
+        ok(time != NULL, "psTimeAlloc() did not return NULL");
+        skip_start(time == NULL, 4, "Skipping tests because psTimeAlloc() failed");
+        ok(time->type == PS_TIME_UT1, "psTimeAlloc() correctly set psTime->type");
+        ok(time->sec == 0, "psTimeAlloc() correctly set psTime->sec");
+        ok(time->nsec == 0, "psTimeAlloc() correctly set psTime->nsec");
+        ok(time->leapsecond == false, "psTimeAlloc() correctly set psTime->leapsecond");
+        psFree(time);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeAlloc(TT)
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TT);
+        ok(time != NULL, "psTimeAlloc() did not return NULL");
+        skip_start(time == NULL, 4, "Skipping tests because psTimeAlloc() failed");
+        ok(time->type == PS_TIME_TT, "psTimeAlloc() correctly set psTime->type");
+        ok(time->sec == 0, "psTimeAlloc() correctly set psTime->sec");
+        ok(time->nsec == 0, "psTimeAlloc() correctly set psTime->nsec");
+        ok(time->leapsecond == false, "psTimeAlloc() correctly set psTime->leapsecond");
+        psFree(time);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeGetNow()
+    // Attempt to get time with unallowed type
+    // Following should generate an error message for unallowed time type
+    {
+        psMemId id = psMemGetId();
+        psTime *timeNow = psTimeGetNow(-100);
+        ok(timeNow == NULL, "psTimeGetNow(-100) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeGetNow(TAI)
+    {
+        psMemId id = psMemGetId();
+        psTime *timeNow = psTimeGetNow(PS_TIME_TAI);
+        ok(timeNow != NULL, "psTimeGetNow() returned NULL");
+        skip_start(time == NULL, 4, "Skipping tests because psTimeGetNow() failed");
+        ok(timeNow->type == PS_TIME_TAI, "psTimeGetNow() correctly set psTime->type");
+        ok(timeNow->sec != 0, "psTimeAlloc() set psTime->sec to something");
+        ok(timeNow->nsec != 0, "psTimeAlloc() set psTime->nsec to something");
+        psFree(timeNow);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeGetUT1Delta()
+    // Attempt to convert NULL time
+    // psTimeGetUT1Delta() should generate an error message for NULL time
+    {
+        psMemId id = psMemGetId();
+        psF64 ut1Delta = psTimeGetUT1Delta(NULL, PS_IERS_B);
+        is_double(ut1Delta, NAN, "psTimeGetUT1Delta(NULL, PS_IERS_B) returned NAN");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Attempt to convert unallowed time
+    // Following should generate an error message for incorrect time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec = 1;
+        time->nsec = 2e9;
+        time->leapsecond = false;
+        psF64 ut1Delta = psTimeGetUT1Delta(time, PS_IERS_B);
+        is_double(ut1Delta, NAN, "psTimeGetUT1Delta() returned NAN for incorrect time");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Attempt to convert time with unallowed bulletin
+    // Following should generate an error message for incorrect bulletin
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec = 1;
+        time->nsec = 2;
+        time->leapsecond = false;
+        psF64 ut1Delta = psTimeGetUT1Delta(time, -100);
+        is_double(ut1Delta, NAN, "psTimeGetUT1Delta(time, -100) returned NAN (incorrect bulletin)");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Attempt to get delta with valid time and bulletin A
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec  = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        time->type = PS_TIME_UTC;
+        time->leapsecond = false;
+        psF64 ut1Delta = psTimeGetUT1Delta(time, PS_IERS_A);
+
+        is_double_tol(ut1Delta, testTime1UT1DeltaBullA, ERROR_TOL, "psTimeGetUT1Delta() produced the correct result: bulletin A");
+
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Attempt to get delta with valid time and bulletin B
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec  = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        time->type = PS_TIME_UTC;
+        psF64 ut1Delta = psTimeGetUT1Delta(time, PS_IERS_B);
+
+        is_double_tol(ut1Delta, testTime1UT1DeltaBullB, ERROR_TOL, "psTimeGetUT1Delta() produced the correct result: bulletin B");
+
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to get delta with valid time and bulletin A
+    // Following should generate a warning message predating table
+    // XXX: We don't test whether the warning message is generated
+    if (1) {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec = testTime2SecondsUTC;
+        time->nsec = testTime2NanosecondsUTC;
+        time->type = PS_TIME_UTC;
+        psF64 ut1Delta = psTimeGetUT1Delta(time,PS_IERS_A);
+
+        is_double_tol(ut1Delta, testTime2UT1DeltaBullA, ERROR_TOL, "psTimeGetUT1Delta() produced the correct result: bulletin B");
+
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to get delta with valid time and bulletin B
+    // Following should generate a warning message predating table
+    // XXX: We don't test whether the warning message is generated
+    if (1) {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec = testTime2SecondsUTC;
+        time->nsec = testTime2NanosecondsUTC;
+        time->type = PS_TIME_UTC;
+        psF64 ut1Delta = psTimeGetUT1Delta(time,PS_IERS_B);
+
+        is_double_tol(ut1Delta, testTime2UT1DeltaBullB, ERROR_TOL, "psTimeGetUT1Delta() produced the correct result: bulletin B");
+
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to get delta with valid time and bulletin A
+    // Following should generate a warning message postdating table
+    // XXX: We don't test whether the warning message is generated
+    if (1) {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec  = testTime3SecondsUTC;
+        time->nsec = testTime3NanosecondsUTC;
+        time->type = PS_TIME_UTC;
+        psF64 ut1Delta = psTimeGetUT1Delta(time,PS_IERS_A);
+
+        is_double_tol(ut1Delta, testTime3UT1DeltaBullA, ERROR_TOL, "psTimeGetUT1Delta() produced the correct result: bulletin B");
+
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Attempt to get delta with valid time and bulletin B
+    // Following should generate a warning message postdating table
+    // XXX: We don't test whether the warning message is generated
+    if (1) {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec  = testTime3SecondsUTC;
+        time->nsec = testTime3NanosecondsUTC;
+        time->type = PS_TIME_UTC;
+        psF64 ut1Delta = psTimeGetUT1Delta(time,PS_IERS_B);
+
+        is_double_tol(ut1Delta, testTime3UT1DeltaBullB, ERROR_TOL, "psTimeGetUT1Delta() produced the correct result: bulletin B");
+
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeToMJD()
+    // Attempt to convert with time NULL
+    // Following should generate an error message for NULL time
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psF64 mjd = psTimeToMJD(NULL);
+        is_double(mjd, NAN, "psTimeToMJD(NULL) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeToMJD()
+    // Attempt to convert incorrect time
+    // Following should generate an error message for incorrect time
+    // Following should generate an error message for NULL time
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = 1;
+        time->nsec = 2e9;
+        time->leapsecond = false;
+        psF64 mjd = psTimeToMJD(time);
+        is_double(mjd, NAN, "psTimeToMJD() returned NAN for incorrect time");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeToMJD()
+    // Check valid time conversion to MJD after 1/1/1970 epoch
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        psF64 mjd = psTimeToMJD(time);
+        is_double_tol(mjd, 53207.765929, ERROR_TOL, "psTimeToMJD() returned correct time after 1/1/1970 epoch");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeToMJD()
+    // Check valid time conversion to MJD before 1/1/1970 epoch
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime4SecondsUTC;
+        time->nsec = testTime4NanosecondsUTC;
+        psF64 mjd = psTimeToMJD(time);
+        is_double_tol(mjd, testTime4MJD, ERROR_TOL, "psTimeToMJD() returned correct time before 1/1/1970 epoch");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeToJD()
+    // Attempt to convert with time NULL
+    // Following should generate an error message for NULL time
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psF64 jd = psTimeToJD(NULL);
+        is_double(jd, NAN, "psTimeToJD(NULL) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeToJD()
+    // Attempt to convert incorrect time
+    // Following should generate an error message for incorrect time
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = 1;
+        time->nsec = 2e9;
+        time->leapsecond = false;
+        psF64 jd = psTimeToJD(time);
+        is_double(jd, NAN, "psTimeToJD() returned NAN for incorrect time");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeToJD()
+    // Check valid time conversion to MJD after 1/1/1970 epoch
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        psF64 jd = psTimeToJD(time);
+        is_double_tol(jd, 2453208.265929, ERROR_TOL, "psTimeToJD() returned the correct time after 1/1/1970 epoch");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeToJD()
+    // Check valid time conversion to MJD before 1/1/1970 epoch
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime4SecondsUTC;
+        time->nsec = testTime4NanosecondsUTC;
+        psF64 jd = psTimeToJD(time);
+        is_double_tol(jd, testTime4JD, ERROR_TOL, "psTimeToJD() returned the correct time before 1/1/1970 epoch");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeToISO()
+    // Attempt to convert with NULL time
+    // Following should generate error message for NULL time
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        char *timeStr = psTimeToISO(NULL);
+        ok(timeStr == NULL, "psTimeToISO(NULL) returned NULL");
+        psFree(timeStr);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeToISO()
+    // Attempt to convert incorrect time
+    // Following should generate an error message for incorrect time
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->leapsecond = false;
+        time->sec = 1;
+        time->nsec = 2e9;
+        char *timeStr = psTimeToISO(time);
+        ok(timeStr == NULL, "psTimeToISO(time) returned NULL for incorrect time");
+        psFree(time);
+        psFree(timeStr);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeToISO()
+    // Verify return NULL for time prior to year 0000
+    // Following should generate error message for time prior year 0000
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime5SecondsUTC;
+        time->nsec = testTime5NanosecondsUTC;
+        char *timeStr = psTimeToISO(time);
+        ok(timeStr == NULL, "psTimeToISO(time) returned NULL for time prior to year 0000");
+        psFree(time);
+        psFree(timeStr);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeToISO()
+    // Verify return NULL for time after to year 9999
+    // Following should generate error message for time after year 9999
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->leapsecond = false;
+        time->sec = testTime6SecondsUTC;
+        time->nsec = testTime6NanosecondsUTC;
+        char *timeStr = psTimeToISO(time);
+        ok(timeStr == NULL, "psTimeToISO(time) returned NULL for time after year 9999");
+        psFree(time);
+        psFree(timeStr);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeToISO()
+    // Verify return string with valid time
+    // XXX: These tests fail.  They used to succeed in early 2006, I think
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->leapsecond = false;
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        char *timeStr = psTimeToISO(time);
+        is_str(timeStr, testTime1Str, "psTimeToISO(time) returned correct time (no leapsecond)");
+        psFree(timeStr);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeToISO()
+    // Verify return string with valid time and leap second set
+    // XXX: These tests fail.  They used to succeed in early 2006, I think
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        time->leapsecond = true;
+        char *timeStr = psTimeToISO(time);
+        is_str(timeStr, testTime1StrLeap, "psTimeToISO(time) returned correct time (with leapsecond)");
+        psFree(timeStr);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeToTimeval()
+    // Attempt to convert with NULL time
+    // Following should generate error message for NULL time
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        struct timeval *timevalTime = psTimeToTimeval(NULL);
+
+        ok(timevalTime == NULL, "psTimeToTimeval(NULL) returned NULL");
+
+        psFree(timevalTime);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeToTimeval()
+    // Attempt to convert incorrect time
+    // Following should generate an error message for incorrect time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->leapsecond = false;
+        time->sec = 1;
+        time->nsec = 2e9;
+        struct timeval *timevalTime = psTimeToTimeval(time);
+        ok(timevalTime == NULL, "psTimeToTimeval() returned NULL for incorrect time");
+        psFree(time);
+        psFree(timevalTime);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeToTimeval()
+    // Attempt to convert incorrect time
+    // Following should generate an error message for incorrect time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->leapsecond = false;
+        time->sec = -1;
+        time->nsec = 0;
+        struct timeval *timevalTime = psTimeToTimeval(time);
+        ok(timevalTime == NULL, "psTimeToTimeval() returned NULL for incorrect time");
+        psFree(time);
+        psFree(timevalTime);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeToTimeval()
+    // Verify convert to timeval with valid time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->leapsecond = false;
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        struct timeval *timevalTime = psTimeToTimeval(time);
+        is_long(timevalTime->tv_sec, testTime1TimevalSec, "psTimeToTimeval()->tv_sec");
+        is_long(timevalTime->tv_usec, testTime1TimevalUsec, "psTimeToTimeval()->tv_usec");
+        psFree(time);
+        psFree(timevalTime);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromMJD()
+    // Attempt to convert valid time to psTime
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromMJD(testTime1MJDTAI);
+        ok(time->type == PS_TIME_TAI, "psTimeFromMJD() returned the correct type");
+        is_long(time->sec, testTime1SecondsTAI, "psTimeFromMJD()->sec");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromMJD()
+    // Attempt to convert valid time before 1970 epoch
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromMJD(testTime4MJD);
+        ok(time->type == PS_TIME_TAI, "psTimeFromMJD() returned the correct type");
+        is_long(time->sec, testTime4SecondsUTC, "psTimeFromMJD()->sec");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeFromJD()
+    // Attempt to convert valid time to psTime
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromJD(testTime1JDTAI);
+        ok(time->type == PS_TIME_TAI, "psTimeFromJD() returned the correct type");
+        is_long(time->sec, testTime1SecondsTAI, "psTimeFromJD()->sec");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeFromJD()
+    // Attempt to convert valid time before 1970 epoch
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromJD(testTime4JD);
+
+        ok(time->type == PS_TIME_TAI, "psTimeFromJD() returned the correct type");
+        is_long(time->sec, testTime4SecondsUTC, "psTimeFromJD() returned the correct ->sec");
+
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromISO()
+    // Convert valid ISO string
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromISO(testTime1Str, PS_TIME_TAI);
+        ok(time->type == PS_TIME_TAI, "psTimeFromISO() returned the correct type");
+        is_long(time->sec, testTime1SecondsUTC, "psTimeFromISO()->sec");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromISO()
+    // Attempt to convert NULL string
+    // Following should generate error message for NULL ISO string");
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromISO(NULL, PS_TIME_TAI);
+        ok(time == NULL, "psTimeFromISO(NULL, PS_TIME_TAI) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromISO()
+    // Attempt to convert incorrect ISO string
+    // Following should generate an error for incorrect ISO string");
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromISO("Here I am", PS_TIME_TAI);
+        ok(time == NULL, "psTimeFromISO() returned NULL for incorrect ISO string");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeFromTimeval()
+    // Attempt to create psTime from NULL timeval ptr
+    // Following should generate error message for NULL timeval
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromTimeval(NULL);
+        ok(time == NULL, "psTimeFromTimeval(NULL) returned NULL");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeFromTimeval()
+    // Convert valid timeval structure
+    {
+        psMemId id = psMemGetId();
+        struct timeval *timevalTime = (struct timeval*)psAlloc(sizeof(struct timeval));
+        timevalTime->tv_sec = testTime1SecondsTAI;
+        timevalTime->tv_usec = testTime1NanosecondsTAI / 1000;
+        psTime *time = psTimeFromTimeval(timevalTime);
+        ok(time != NULL, "psTimeFromTimeval() returned non-NULL for correct timeval structure");
+        skip_start(time == NULL, 3, "Skipping tests because psTimeFromTimeval() returned NULL");
+        ok(time->type == PS_TIME_TAI, "psTimeFromTimeval() returned the correct type");
+        is_long(time->sec, testTime1SecondsTAI, "psTimeFromTimeval() returned the correct ->sec");
+        is_long(time->nsec, testTime1NanosecondsTAI, "psTimeFromTimeval() returned the correct ->nsec");
+        skip_end();
+        psFree(timevalTime);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromTM()
+    // Attempt to convert from NULL tm structure ptr
+    // Following should generate error message for NULL tm ptr
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromTM(NULL);
+        ok(time == NULL, "psTimeFromTM(NULL) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromTM()
+    // Verify convert for valid tm structure
+    {
+        psMemId id = psMemGetId();
+        struct tm *tmTime = (struct tm*)psAlloc(sizeof(struct tm));
+        tmTime->tm_year = testTime7TmYear;
+        tmTime->tm_mon  = testTime7TmMon;
+        tmTime->tm_mday = testTime7TmDay;
+        tmTime->tm_hour = testTime7TmHour;
+        tmTime->tm_min  = testTime7TmMin;
+        tmTime->tm_sec  = testTime7TmSec;
+        psTime *time = psTimeFromTM(tmTime);
+        ok(time != NULL, "psTimeFromTM(NULL) returned non-NULL");
+        skip_start(time == NULL, 2, "Skipping tests because psTimeFromTM() returned NULL");
+        is_long(time->sec, testTime7Seconds, "psTimeFromTM() returned the correct ->sec");
+        is_long(time->nsec, testTime7Nanoseconds, "psTimeFromTM() returned the correct ->nsec");
+        skip_end();
+        psFree(tmTime);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromTM()
+    // Verify convert for valid tm structure
+    {
+        psMemId id = psMemGetId();
+        struct tm *tmTime = (struct tm*)psAlloc(sizeof(struct tm));
+        tmTime->tm_year = testTime8TmYear;
+        tmTime->tm_mon  = testTime8TmMon;
+        tmTime->tm_mday = testTime8TmDay;
+        tmTime->tm_hour = testTime8TmHour;
+        tmTime->tm_min  = testTime8TmMin;
+        tmTime->tm_sec  = testTime8TmSec;
+        psTime *time = psTimeFromTM(tmTime);
+        // XXX should test all fields here
+        ok(time != NULL, "psTimeFromTM(NULL) returned non-NULL");
+        skip_start(time == NULL, 2, "Skipping tests because psTimeFromTM() returned NULL");
+        is_long(time->sec, testTime8Seconds, "psTimeFromTM() returned the correct ->sec");
+        is_long(time->nsec, testTime8Nanoseconds, "psTimeFromTM() returned the correct ->nsec");
+        skip_end();
+        psFree(tmTime);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert NULL time
+    // Following should generate an error message for NULL time
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time2 = psTimeConvert(NULL, PS_TIME_TAI);
+
+        ok(time2 == NULL, "psTimeConvert(NULL, PS_TIME_TAI) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+
+        psFree(time2);
+    }
+
+
+    // psTimeConvert()
+    // Following should generate an error message for incorrect type output
+    // Input psTime struct is PS_TIME_TAI
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        psTime *time2 = psTimeConvert(time1,-100);
+        ok(time2 == NULL, "psTimeConvert(time1, -100) returned NULL");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Following should generate an error message for incorrect type output
+    // Input psTime struct is PS_TIME_UTC
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        psTime *time2 = psTimeConvert(time1,-100);
+        ok(time2 == NULL, "psTimeConvert(time1, -100) returned NULL");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Following should generate an error message for incorrect type
+    // Input psTime struct is PS_TIME_TT
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TT);
+        psTime *time2 = psTimeConvert(time1,-100);
+        ok(time2 == NULL, "psTimeConvert(time1, -100) returned NULL");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Following should generate an error message for incorrect type input
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->type = -100;
+        psTime *time2 = psTimeConvert(time1,PS_TIME_TAI);
+        ok(time2 == NULL, "psTimeConvert(time1, PS_TIME_TAI) returned NULL");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert with incorrect time nsec > 1e9
+    // Following should generate an error message for incorrect time
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->nsec = 2e9;
+        psTime *time2 = psTimeConvert(time1, PS_TIME_TAI);
+        ok(time2 == NULL, "psTimeConvert(time1, PS_TIME_TAI) returns NULL for incorrect psTime object");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    //Attempt to convert a time to the same type
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->sec = 1;
+        time1->nsec = 2;
+        time1->type = PS_TIME_TAI;
+        time1->leapsecond = false;
+        psTime *time2 = psTimeConvert(time1, PS_TIME_TAI);
+        ok(time2 == time1, "psTimeConvert(time, ...) returns time for conversion to same type");
+        is_long(time2->sec, 1, "time->sec");
+        is_long(time2->nsec, 2, "time->nsec");
+        ok(time2->type == PS_TIME_TAI, "time->type");
+        is_bool(time2->leapsecond, false, "time->leapsecond");
+
+        psFree(time1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert a UTC time to a TAI
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        time1->leapsecond = false;
+
+        psTime *time2 = psTimeConvert(time1,PS_TIME_TAI);
+        ok(time2 == time1, "psTimeConvert(time, ...) returns time after conversion to a different type");
+        is_long(time2->sec, testTime1SecondsTAI, "psTimeConvert() returned the correct ->sec");
+        is_long(time2->nsec, testTime1NanosecondsTAI, "psTimeConvert() returned the correct ->nsec");
+        ok(time2->type == PS_TIME_TAI, "psTimeConvert() returned the correct type");
+        is_bool(time2->leapsecond, false, "time->leapsecond");
+
+        psFree(time1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert a UTC time to a TT
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        time1->leapsecond = false;
+
+        psTime *time2 = psTimeConvert(time1,PS_TIME_TT);
+        ok(time2 == time1, "psTimeConvert(time, ...) returns time after conversion to a different type");
+        is_long(time2->sec, testTime1SecondsTT, "psTimeConvert() returned the correct ->sec");
+        is_long(time2->nsec, testTime1NanosecondsTT, "psTimeConvert() returned the correct ->nsec");
+        ok(time2->type == PS_TIME_TT, "psTimeConvert() returned the correct type");
+        is_bool(time2->leapsecond, false, "time->leapsecond");
+
+        psFree(time1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert a UTC time to UT1
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        time1->leapsecond = false;
+
+        psTime *time2 = psTimeConvert(time1,PS_TIME_UT1);
+        ok(time2 == time1, "psTimeConvert(time, ...) returns time after conversion to a different type");
+        is_long(time2->sec, testTime1SecondsUT1, "psTimeConvert() returned the correct ->sec");
+        is_long(time2->nsec, testTime1NanosecondsUT1, "psTimeConvert() returned the correct ->nsec");
+        ok(time2->type == PS_TIME_UT1, "psTimeConvert() returned the correct type");
+        is_bool(time2->leapsecond, false, "time->leapsecond");
+
+        psFree(time1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psTimeConvert()
+    // Attempt to convert a TAI time to UTC
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->sec = testTime1SecondsTAI;
+        time1->nsec = testTime1NanosecondsTAI;
+        time1->leapsecond = false;
+
+        psTime *time2 = psTimeConvert(time1,PS_TIME_UTC);
+        ok(time2 == time1, "psTimeConvert(time, ...) returns time after conversion to a different type");
+        is_long(time2->sec, testTime1SecondsUTC, "psTimeConvert() returned the correct ->sec");
+        is_long(time2->nsec, testTime1NanosecondsUTC, "psTimeConvert() returned the correct ->nsec");
+        ok(time2->type == PS_TIME_UTC, "psTimeConvert() returned the correct type");
+        is_bool(time2->leapsecond, false, "time->leapsecond");
+
+        psFree(time1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert a TAI time to TT
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->sec = testTime1SecondsTAI;
+        time1->nsec = testTime1NanosecondsTAI;
+        time1->type = PS_TIME_TAI;
+        time1->leapsecond = false;
+
+        psTime *time2 = psTimeConvert(time1,PS_TIME_TT);
+        ok(time2 == time1, "psTimeConvert() returned time for conversion to same type");
+        is_long(time2->sec, testTime1SecondsTT, "psTimeConvert() returned the correct ->sec");
+        is_long(time2->nsec, testTime1NanosecondsTT, "psTimeConvert() returned the correct ->nsec");
+        ok(time2->type == PS_TIME_TT, "psTimeConvert() returned the correct type");
+        is_bool(time2->leapsecond, false, "time->leapsecond");
+
+        psFree(time1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert a TAI time to UT1
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->sec = testTime1SecondsTAI;
+        time1->nsec = testTime1NanosecondsTAI;
+        time1->leapsecond = false;
+
+        psTime *time2 = psTimeConvert(time1,PS_TIME_UT1);
+        ok(time1 == time2, "psTimeConvert() returned time for conversion to same type");
+        is_long(time2->sec, testTime1SecondsUT1, "psTimeConvert() returned the correct ->sec");
+        is_long(time2->nsec, testTime1NanosecondsUT1, "psTimeConvert() returned the correct ->nsec");
+        ok(time2->type == PS_TIME_UT1, "psTimeConvert() returned the correct type");
+        is_bool(time2->leapsecond, false, "time->leapsecond");
+
+        psFree(time1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert a TT time to UTC
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TT);
+        time1->sec = testTime1SecondsTT;
+        time1->nsec = testTime1NanosecondsTT;
+        time1->leapsecond = false;
+
+        psTime *time2 = psTimeConvert(time1,PS_TIME_UTC);
+        ok(time2 == time1, "psTimeConvert() returned time for conversion to same type");
+        is_long(time2->sec, testTime1SecondsUTC, "psTimeConvert() returned the correct ->sec");
+        is_long(time2->nsec, testTime1NanosecondsUTC, "psTimeConvert() returned the correct ->nsec");
+        ok(time2->type == PS_TIME_UTC, "psTimeConvert() returned the correct type");
+        is_bool(time2->leapsecond, false, "time->leapsecond");
+
+        psFree(time1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert a TT time to TAI
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TT);
+        time1->sec = testTime1SecondsTT;
+        time1->nsec = testTime1NanosecondsTT;
+        time1->leapsecond = false;
+
+        psTime *time2 = psTimeConvert(time1,PS_TIME_TAI);
+        ok(time2 == time1, "psTimeConvert() returned time for conversion to same type");
+        is_long(time2->sec, testTime1SecondsTAI, "psTimeConvert() returned the correct ->sec");
+        is_long(time2->nsec, testTime1NanosecondsTAI, "psTimeConvert() returned the correct ->nsec");
+        ok(time2->type == PS_TIME_TAI, "psTimeConvert() returned the correct type");
+        is_bool(time2->leapsecond, false, "time->leapsecond");
+
+        psFree(time1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert a TT time to UT1
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TT);
+        time1->sec = testTime1SecondsTT;
+        time1->nsec = testTime1NanosecondsTT;
+        time1->leapsecond = false;
+
+        psTime *time2 = psTimeConvert(time1,PS_TIME_UT1);
+        ok(time1 == time2, "psTimeConvert() returned time for conversion to same type");
+        is_long(time2->sec, testTime1SecondsUT1, "psTimeConvert() returned the correct ->sec");
+        is_long(time2->nsec, testTime1NanosecondsUT1, "psTimeConvert() returned the correct ->nsec");
+        ok(time2->type == PS_TIME_UT1, "psTimeConvert() returned the correct type");
+        is_bool(time2->leapsecond, false, "time->leapsecond");
+
+        psFree(time1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert from UT1 to TAI, UTC, TT
+    // Following should generate an error message converting from UT1");
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UT1);
+        time1->sec = 1;
+        time1->nsec = 2;
+        time1->leapsecond = false;
+
+        psTime *time2 = psTimeConvert(time1, PS_TIME_UTC);
+        ok(time2 == NULL, "psTimeConvert() returned NULL for conversion from UT1");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psTime_02.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psTime_02.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psTime_02.c	(revision 22158)
@@ -0,0 +1,407 @@
+/** @file  tst_psTime_02.c
+ *
+ *  @brief Test driver for psTime functions
+ *
+ *  This test driver contains the following tests for psTime:
+ *     1) Convert psTime to Local Mean Sidereal Time (LMST)
+ *     2) Calculate leap second delta between times
+ *     3) Creation of psTime of type TT
+ *     4) Creation of psTime of type UTC
+ *
+ *  @author  Ross Harman, MHPCC
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.6 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2007-06-05 01:10:22 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <pslib.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+#define ERROR_TOL  0.001
+// Test Time 1 : May 9, 2005  00:00:00,0
+//               MJD = 53499.000
+//               JD = 2453499.5
+// UTC Test Time 1
+const psS64 testTime1SecondsUTC     = 1115596900;
+const psU32 testTime1NanosecondsUTC = 0;
+// Expected LMST  15:09:18
+const psF64 testTime1LMST0          = 3.967604;
+
+// Test Time 2 : May 9, 1995 00:00:00,0
+//               MJD = 49846.00
+//               JD = 2449846.5
+// UTC Test Time 2
+const psS64 testTime2SecondsUTC     = 799977600;
+const psU32 testTime2NanosecondsUTC = 0;
+// Expected leap second delta
+const psS64 testTimeLeapSecondDelta1 = 3;
+
+// Test Time 3: Jan 1, 1999 00:00:00,0
+//              MJD = 51179
+//              JD = 2451179.5
+const psS64 testTime3SecondsUTC     = 915148800;
+const psU32 testTime3NanosecondsUTC = 0;
+
+int main(int argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+    psLogSetFormat("HLNM");
+    plan_tests(54);
+    psLibInit("pslib.config");
+
+    // psTimeToLMST()
+    // Attempt to get LMST with NULL time
+    // Following should generate an error message for NULL time
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psF64 lmst = psTimeToLMST(NULL, 0);
+        is_double(lmst, NAN, "psTimeToLMST(NULL, 0) returned NAN");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeToLMST()
+    // Attempt to get LMST with valid test time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        time->leapsecond = false;
+        psF64 lmst = psTimeToLMST(time, 0.0);
+        is_double_tol(lmst, testTime1LMST0, ERROR_TOL, "psTimeToLMST() returned the correct time");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeToLMST()
+    // Attempt to get LMST with unallowed input time UT1
+    // Following should generate error message for incorrect type
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        time->leapsecond = false;
+        time->type = PS_TIME_UT1;
+        psF64 lmst = psTimeToLMST(time,0.0);
+        is_double(lmst, NAN, "psTimeToLMST() generated a NAN for incorrect type");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeLeapSecondDelta()
+    // Attempt to get delta with NULL time1 argument
+    // Following should generate an error message for NULL time
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psS64 delta = psTimeLeapSecondDelta(NULL, NULL);
+        is_long(delta, 0, "psTimeLeapSecondDelta(NULL, NULL) returned 0");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeLeapSecondDelta()
+    // Set test time 1
+    // Attempt to get delta with NULL time2 argument
+    // Following should generate an error message for NULL time
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        time1->leapsecond = false;
+        psS64 delta = psTimeLeapSecondDelta(time1, NULL);
+        is_long(delta, 0, "psTimeLeapSecondDelta(time1, NULL) returned 0");
+        psFree(time1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeLeapSecondDelta()
+    // Set test time 2 with unallowed time
+    // Attempt to get delta with unallowed time2
+    // Following should generate an error message for unallowed time
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        time1->leapsecond = false;
+        psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+        time2->sec = 0;
+        time2->nsec = 2e9;
+        time2->leapsecond = false;
+        psS64 delta = psTimeLeapSecondDelta(time1, time2);
+        is_long(delta, 0, "psTimeLeapSecondDelta(time1, time2) returned 0 with incorrect time2");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeLeapSecondDelta()
+    // Set test time 2 valid
+    // Attempt to get delta with unallowed time1
+    // Following should generate an error message for unallowed time
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->leapsecond = false;
+        psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+        time2->leapsecond = false;
+        time2->sec = testTime2SecondsUTC;
+        time2->nsec = testTime2NanosecondsUTC;
+        // Set test time 1 incorrect
+        time1->sec = 0;
+        time1->nsec = 2e9;
+        psS64 delta = psTimeLeapSecondDelta(time1,time2);
+        is_long(delta, 0, "psTimeLeapSecondDelta(time1, time2) returned 0 with incorrect time1");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeLeapSecondDelta()
+    // Set test time 1 to greater time
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        time1->leapsecond = false;
+        psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+        time2->leapsecond = false;
+        time2->sec = testTime2SecondsUTC;
+        time2->nsec = testTime2NanosecondsUTC;
+        psS64 delta = psTimeLeapSecondDelta(time1,time2);
+        is_long(delta, testTimeLeapSecondDelta1, "psTimeLeapSecondDelta() produced the correct result");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeLeapSecondDelta()
+    // Set test time 1 to lesser time
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        time1->leapsecond = false;
+        psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+        time2->sec = testTime2SecondsUTC;
+        time2->nsec = testTime2NanosecondsUTC;
+        psS64 delta = psTimeLeapSecondDelta(time2, time1);
+        is_long(delta, testTimeLeapSecondDelta1, "psTimeLeapSecondDelta() produced the correct result");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeLeapSecondDelta()
+    // Attempt to get delta with times equal
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        time1->leapsecond = false;
+        psS64 delta = psTimeLeapSecondDelta(time1,time1);
+        is_long(delta, 0, "psTimeLeapSecondDelta() produced the correct result");
+        psFree(time1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeIsLeapSecond()
+    // Attempt to determine if leap second with NULL time
+    // Following should generate an error message for NULL time
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        bool leapsecond = psTimeIsLeapSecond(NULL);
+        is_bool(leapsecond, false, "psTimeIsLeapSecond(NULL) returned correct value");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeIsLeapSecond()
+    // Attempt to determine if leap second with non-UTC time
+    // Following should generate an error message for unallowed type
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        time->leapsecond = false;
+        bool leapsecond = psTimeIsLeapSecond(time);
+        is_bool(leapsecond, false, "psTimeIsLeapSecond() returned false with incorrect type");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeIsLeapSecond()
+    // Set time to UTC
+    // Attempt to determine if leap second with valid time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        time->leapsecond = false;
+        time->type = PS_TIME_UTC;
+        bool leapsecond = psTimeIsLeapSecond(time);
+        is_bool(leapsecond, false, "psTimeIsLeapSecond() returned false");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeIsLeapSecond()
+    // Set time to UTC with leap second
+    // Note: leapseconds are only relevent for UTC
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime3SecondsUTC;
+        time->nsec = testTime3NanosecondsUTC;
+        bool leapsecond = psTimeIsLeapSecond(time);
+        is_bool(leapsecond, true, "psTimeIsLeapSecond() returned true");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeIsLeapSecond()
+    // Set time to 1 second before a known leap second
+    // Note: leapseconds are only relevent for UTC
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime3SecondsUTC;
+        time->nsec = testTime3NanosecondsUTC;
+        time->sec--;
+        bool leapsecond = psTimeIsLeapSecond(time);
+        is_bool(leapsecond, false, "psTimeIsLeapSecond() returned false");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeIsLeapSecond()
+    // Set time to 1 second after a known leap second
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec = testTime3SecondsUTC;
+        time->nsec = testTime3NanosecondsUTC;
+        time->sec++;
+        bool leapsecond = psTimeIsLeapSecond(time);
+        is_bool(leapsecond, false, "psTimeIsLeapSecond() returned false");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromTT()
+    // Attempt to create psTime with unallowed time
+    // Following should generate an error message for unallowed time
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromTT(0,2e9);
+        ok(time == NULL, "psTimeFromTT() returned NULL with incorrect time");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromTT()
+    // Attempt to create psTime with valid time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromTT(testTime1SecondsUTC,testTime1NanosecondsUTC);
+        ok(time != NULL, "psTimeFromTT() returned non-NULL with valid time");
+        skip_start(time == NULL, 2, "Skipping tests because psTimeFromTT() returned NULL");
+        ok(time->type == PS_TIME_TT, "psTimeFromTT() returned correct type");
+        is_long(time->sec, testTime1SecondsUTC, "psTimeFromTT() returned correct ->sec"); 
+        is_long(time->nsec, testTime1NanosecondsUTC, "psTimeFromTT() returned correct ->nsec");
+        is_bool(time->leapsecond, false, "psTimeFromTT() returned the correct leapsecond flag");
+        skip_end();
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromUTC()
+    // Attempt to create psTime with unallowed time
+    // Following should generate an error message for unallowed time
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromUTC(0, 2e9, true);
+        ok(time == NULL, "psTimeFromUTC() returned NULL with incorrect time input");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromUTC()
+    // Attempt to create psTime with valid leapsecond time but leapsecond
+    // flag false
+    {
+        psMemId id = psMemGetId();
+
+        psTime *time = psTimeFromUTC(testTime3SecondsUTC, testTime3NanosecondsUTC, false);
+        ok(time != NULL, "psTimeFromUTC() returned non-NULL with correct input");
+        skip_start(time == NULL, 5, "Skipping tests because psTimeFromUTC() returned NULL");
+        ok(time->type == PS_TIME_UTC, "psTimeFromUTC() returned the correct type");
+        is_long(time->sec, testTime3SecondsUTC, "psTimeFromUTC() returned the correct ->sec");
+        is_long(time->nsec, testTime3NanosecondsUTC, "psTimeFromUTC() returned the correct ->nsec");
+        is_bool(time->leapsecond, true, "psTimeFromUTC() returned the correct leapsecond flag");
+        psFree(time);
+        skip_end();
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromUTC()
+    // Attempt to create psTime with valid non-leapsecond time and
+    // leapsecond flag true
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromUTC(testTime1SecondsUTC, testTime1NanosecondsUTC, true);
+        ok(time != NULL, "psTimeFromUTC() returned non-NULL with correct input");
+        skip_start(time == NULL, 3, "Skipping tests because psTimeFromUTC() returned NULL");
+        ok(time->type == PS_TIME_UTC, "psTimeFromUTC() returned the correct type");
+        is_long(time->sec, testTime1SecondsUTC, "psTimeFromUTC() returned the correct ->sec and ->nsec");
+        is_long(time->nsec, testTime1NanosecondsUTC, "psTimeFromUTC() returned the correct ->sec and ->nsec");
+        is_bool(time->leapsecond, false, "psTimeFromUTC() returned the correct leapsecond flag");
+        skip_end();
+
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psTime_03.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psTime_03.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psTime_03.c	(revision 22158)
@@ -0,0 +1,517 @@
+/** @file  tst_psTime_03.c
+ *
+ *  @brief Test driver for psTime functions
+ *
+ *  This test driver contains the following tests for psTime:
+ *   1) psTimeMath invalid times
+ *   2) psTimeMath valid time of different types
+ *   3) psTimeDelta valid times with different types
+ *
+ *  @author  Ross Harman, MHPCC
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.7 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2007-06-21 23:53:33 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#define ERROR_TOL    0.001
+
+// Test Time 1 : May 9, 2005 00:00:00,0
+//               MJD = 53499.00
+//               JD = 2453499.5
+// UTC Test Time 1
+const psS64 testTime1SecondsUTC         = 1115596900;
+const psU32 testTime1NanosecondsUTC     = 0;
+// TAI Test Time 1
+const psS64 testTime1SecondsTAI         = 1115596932;
+const psU32 testTime1NanosecondsTAI     = 0;
+// TT Test Time 1
+const psS64 testTime1SecondsTT          = 1115596964;
+const psU32 testTime1NanosecondsTT      = 184000000;
+// UT1 Test Time 1
+const psS64 testTime1SecondsUT1         = 1115596900;
+const psU32 testTime1NanosecondsUT1     = 184000000;
+// Delta 1
+const psF64 deltaTime1                  = -15.5;
+// Expected UTC Time 1
+const psS64 newTestTime1SecondsUTC      = 1115596884;
+const psU32 newTestTime1NanosecondsUTC  = 500000000;
+// Expected TAI Time 1
+const psS64 newTestTime1SecondsTAI      = 1115596916;
+const psU32 newTestTime1NanosecondsTAI  = 500000000;
+// Delta 2
+const psF64 deltaTime2                  = 123.066;
+// Expected TT Time 1 w/ delta 2
+const psS64 newTestTime1SecondsTT       = 1115597087;
+const psU32 newTestTime1NanosecondsTT   = 250000000;
+// Expected UT1 Time 1 w/ delta 2
+const psS64 newTestTime1SecondsUT1      = 1115597023;
+const psU32 newTestTime1NanosecondsUT1  = 250000000;
+
+// Test Time 2 : Dec. 31 1998 23:59:45,0
+//               MJD = 51178.99983
+//               JD = 2451179.49983
+// UTC Test Time 1
+const psS64 testTime2SecondsUTC         = 915148785;
+const psU32 testTime2NanosecondsUTC     = 0;
+// Delta 3
+const psF64 deltaTime3                    = 30.0;
+// Expected UTC Time
+const psS64 newTestTime2SecondsUTC      = 915148814;
+const psU32 newTestTime2NanosecondsUTC  = 0;
+
+// Appendix B time conversion tests
+//
+#define APPB_TESTS    8
+const psS64 testTimeBSeconds[APPB_TESTS] =
+    {
+        915148829,
+        915148829,
+        915148830,
+        915148830,
+        915148831,
+        915148831,
+        915148832,
+        915148832
+    };
+const psU32 testTimeBNanoseconds[APPB_TESTS] =
+    {
+        0,
+        500000000,
+        0,
+        500000000,
+        0,
+        500000000,
+        0,
+        500000000
+    };
+const psBool testTimeBLeapsecond[APPB_TESTS] =
+    {
+        false,
+        false,
+        false,
+        false,
+        true,
+        true,
+        false,
+        false
+    };
+// Expected results
+const char* testTimeBStrUTC[APPB_TESTS] =
+    {
+        "1998-12-31T23:59:58.0Z",
+        "1998-12-31T23:59:58.5Z",
+        "1998-12-31T23:59:59.0Z",
+        "1998-12-31T23:59:59.5Z",
+        "1998-12-31T23:59:60.0Z",
+        "1998-12-31T23:59:60.5Z",
+        "1999-01-01T00:00:00.0Z",
+        "1999-01-01T00:00:00.5Z"
+    };
+const char* testTimeBStrTAI[APPB_TESTS] =
+    {
+        "1999-01-01T00:00:29.0Z",
+        "1999-01-01T00:00:29.5Z",
+        "1999-01-01T00:00:30.0Z",
+        "1999-01-01T00:00:30.5Z",
+        "1999-01-01T00:00:31.0Z",
+        "1999-01-01T00:00:31.5Z",
+        "1999-01-01T00:00:32.0Z",
+        "1999-01-01T00:00:32.5Z"
+    };
+const char* testTimeBStrTT[APPB_TESTS] =
+    {
+        "1999-01-01T00:01:01.1Z",
+        "1999-01-01T00:01:01.6Z",
+        "1999-01-01T00:01:02.1Z",
+        "1999-01-01T00:01:02.6Z",
+        "1999-01-01T00:01:03.1Z",
+        "1999-01-01T00:01:03.6Z",
+        "1999-01-01T00:01:04.1Z",
+        "1999-01-01T00:01:04.6Z"
+    };
+const char* testTimeBStrUT1[APPB_TESTS] =
+    {
+        "1998-12-31T23:59:58.7Z",
+        "1998-12-31T23:59:59.2Z",
+        "1998-12-31T23:59:59.7Z",
+        "1998-12-31T23:59:60.2Z",
+        "1998-12-31T23:59:60.7Z",
+        "1999-01-01T00:00:00.2Z",
+        "1999-01-01T00:00:00.7Z",
+        "1999-01-01T00:00:01.2Z"
+    };
+
+// Test Time B1 : Dec 31, 1998 23:59:58,0
+//                MJD = 51178.99998
+//                JD = 2451179.49998
+//const psS64 testTimeB1SecondsUTC        = 915148798;
+//const psU32 testTimeB1NanosecondsUTC    = 0;
+// Expected ISO times
+//const char testTimeB1StrUTC[] = "1998-12-31T23:59:58,0Z";
+//const char testTimeB1StrTAI[] = "1999-01-01T00:00:29,0Z";
+//const char testTimeB1StrTT[]  = "1999-01-01T00:01:01,1Z";
+//const char testTimeB1StrUT1[] = "1998-12-31T23:59:57,7Z";
+//
+// Test Time B2 : Dec 31, 1998 23:59:58,5
+//
+//
+//const psS64 testTimeB2SecondsUTC       = 915148798;
+//const psU32 testTimeB2NanosecondsUTC   = 500000000;
+// Expected ISO times
+//const char testTimeB2StrUTC[] = "1998-12-31T23:59:58,5Z";
+//const char testTimeB2StrTAI[] = "1991-01-01T00:00:29,5Z";
+//const char testTimeB2StrTT[]  = "1999-01-01T00:01:01,6Z";
+//const char testTimeB2StrUT1[] = "1998-12-31T23:59:58,2Z";
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(77);
+    psLibInit("pslib.config");
+
+
+    // psTimeMath()
+    // Attempt to perform math operation on NULL time
+    // Following should generate error message for NULL time
+    // XXX: We do not test error generation here
+    {
+        psMemId id = psMemGetId();
+        ok(psTimeMath(NULL, -1.1) == NULL, "psTimeMath(NULL, -1.1) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeMath()
+    // Set up input time with invalid nanoseconds
+    // Following should generate error message for invalid time
+    // XXX: We do not test error generation here
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = 0;
+        time->nsec = 2e9;
+        ok(psTimeMath(time, -1.1) == NULL, "psTimeMath() returns NULL for unallowable time input");
+        psFree(time);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeMath()
+    // Set up input time with valid time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        psTime *newTime = psTimeMath(time, deltaTime1);
+        ok(newTime != NULL, "psTimeMath() returns non-NULL for allowable time input (PS_TIME_UTC)");
+        skip_start(newTime == NULL, 2, "Skipping tests because psTimeMath() returned NULL");
+        ok(newTime->type == PS_TIME_UTC, "psTimeMath() returns the correct type (PS_TIME_UTC)");
+        is_long(newTime->sec, newTestTime1SecondsUTC, "psTimeMath() returns the correct ->sec");
+        is_long(newTime->nsec, newTestTime1NanosecondsUTC, "psTimeMath() returns the correct ->nsec");
+        skip_end();
+        psFree(newTime);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeMath()
+    // Set up input time with valid TAI time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec = testTime1SecondsTAI;
+        time->nsec = testTime1NanosecondsTAI;
+
+        psTime *newTime = psTimeMath(time, deltaTime1);
+        ok(newTime != NULL, "psTimeMath() returns non-NULL for allowable time input (PS_TIME_TAI)");
+        skip_start(newTime == NULL, 2, "Skipping tests because psTimeMath() returned NULL");
+        ok(newTime->type == PS_TIME_TAI, "psTimeMath() returns the correct type (PS_TIME_TAI)");
+        is_long(newTime->sec, newTestTime1SecondsTAI, "psTimeMath() returns the correct ->sec");
+        is_long(newTime->nsec, newTestTime1NanosecondsTAI, "psTimeMath() returns the correct ->nsec");
+        skip_end();
+
+        psFree(newTime);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeMath()
+    // Set up input time with valid TT time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TT);
+        time->sec = testTime1SecondsTT;
+        time->nsec = testTime1NanosecondsTT;
+
+        psTime *newTime = psTimeMath(time,deltaTime2);
+        ok(newTime != NULL, "psTimeMath() returns non-NULL for allowable time input (PS_TIME_TT)");
+        skip_start(newTime == NULL, 2, "Skipping tests because psTimeMath() returned NULL");
+        ok(newTime->type == PS_TIME_TT, "psTimeMath() returns the correct type (PS_TIME_TT)");
+        is_long(newTime->sec, newTestTime1SecondsTT, "psTimeMath() returns the correct ->sec (PS_TIME_TT)");
+        is_long(newTime->nsec, newTestTime1NanosecondsTT, "psTimeMath() returns the correct ->nsec (PS_TIME_TT)");
+        skip_end();
+
+        psFree(newTime);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeMath()
+    // Set up input time with valid TT time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UT1);
+        time->sec = testTime1SecondsUT1;
+        time->nsec = testTime1NanosecondsUT1;
+
+        psTime *newTime = psTimeMath(time,deltaTime2);
+        ok(newTime != NULL, "psTimeMath() returns non-NULL for allowable time input (PS_TIME_UT1)");
+        skip_start(newTime == NULL, 2, "Skipping tests because psTimeMath() returned NULL");
+        ok(newTime->type == PS_TIME_UT1, "psTimeMath() returns the correct type (PS_TIME_UT1)");
+        is_long(newTime->sec, newTestTime1SecondsUT1, "psTimeMath() returns the correct ->sec (PS_TIME_UT1)");
+        is_long(newTime->nsec, newTestTime1NanosecondsUT1, "psTimeMath() returns the correct ->nsec (PS_TIME_UT1)");
+        skip_end();
+
+        psFree(newTime);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeMath()
+    // Set up input time with valid UTC time and delt which crosses leap second
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime2SecondsUTC;
+        time->nsec = testTime2NanosecondsUTC;
+
+        psTime *newTime = psTimeMath(time, deltaTime3);
+        ok(newTime != NULL, "psTimeMath() returns non-NULL for allowable time input (PS_TIME_UTC)");
+        skip_start(newTime == NULL, 2, "Skipping tests because psTimeMath() returned NULL");
+        ok(newTime->type == PS_TIME_UTC, "psTimeMath() returns the correct type (PS_TIME_UTC)");
+        is_long(newTime->sec, newTestTime2SecondsUTC, "psTimeMath() returns the correct ->sec (PS_TIME_UTC)");
+        is_long(newTime->nsec, newTestTime2NanosecondsUTC, "psTimeMath() returns the correct ->nsec (PS_TIME_UTC)");
+        skip_end();
+
+        psFree(newTime);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeDelta()
+    // Attempt to get delta with time1 NULL
+    // Following should generate error message for NULL time
+    // XXX: We do not test error generation here
+    {
+        psMemId id = psMemGetId();
+
+        psF64 delta = psTimeDelta(NULL, NULL);
+        is_double_tol(delta, 0.0, ERROR_TOL, "psTimeDelta(NULL, NULL) returned 0.0");
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeDelta()
+    // Attempt to get delta with time2 NULL
+    // Following should generate error message for NULL time
+    // XXX: We do not test error generation here
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+
+        psF64 delta = psTimeDelta(time1, NULL);
+        is_double_tol(delta, 0.0, ERROR_TOL, "psTimeDelta(time1, NULL) returned 0.0");
+
+        psFree(time1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeDelta()
+    // Attempt to get delta with time1 invalid
+    // Following should generate error message for invalid time
+    // XXX: We do not test error generation here
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = 0;
+        time1->nsec = 2e9;
+
+        psF64 delta = psTimeDelta(time1, time2);
+        is_double_tol(delta, 0.0, ERROR_TOL, "psTimeDelta(time1, NULL) returned 0.0 for unallowed time1 arg");
+
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeDelta()
+    // Attempt to get delta with time2 invalid
+    // Following should generate error message for invalid time
+    // XXX: We do not test error generation here
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+        time2->sec = 0;
+        time2->nsec = 2e9;
+
+        psF64 delta = psTimeDelta(time1, time2);
+        is_double_tol(delta, 0.0,  ERROR_TOL, "psTimeDelta(time1, NULL) returned 0.0 for unallowed time2 arg");
+
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeDelta()
+    // Set time 2 valid but different type
+    // Attempt to get delta with different time types
+    // Following should generate error message for incorrect type
+    // XXX: We do not test error generation here
+    // XXX: this currently fails; probably because specs have changed
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        psTime *time2 = psTimeAlloc(PS_TIME_TAI);
+        time2->sec = newTestTime1SecondsUTC;
+        time2->nsec = newTestTime1NanosecondsUTC;
+
+        psF64 delta = psTimeDelta(time1, time2);
+        is_double_tol(delta, 0.0, ERROR_TOL, "psTimeDelta(time1, NULL) returned 0.0 for different time types");
+
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeDelta()
+    // Set time 2 to same as time 1
+    // Attempt to get delta with valid times of the same type
+    // XXX: this currently fails; probably because specs have changed
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+        time2->sec = newTestTime1SecondsUTC;
+        time2->nsec = newTestTime1NanosecondsUTC;
+
+        psF64 delta = psTimeDelta(time2, time1);
+        is_double_tol(delta, deltaTime1, ERROR_TOL, "psTimeDelta(time1, NULL) returned correct delta for times of the same type");
+
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeDelta()
+    // Set time 1 and 2 as different times with same type
+    // Attempt to get delta with valid times of the same type
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsTT;
+        time1->nsec = testTime1NanosecondsTT;
+        time1->type = PS_TIME_TT;
+        psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+        time2->sec = newTestTime1SecondsTT;
+        time2->nsec = newTestTime1NanosecondsTT;
+        time2->type = PS_TIME_TT;
+
+        psF64 delta = psTimeDelta(time2,time1);
+        is_double_tol(delta, deltaTime2, ERROR_TOL, "psTimeDelta(time1, NULL) returned correct delta for times of the same type");
+
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeDelta()
+    // Set time 1 and 2 as different times with same type
+    // Attempt to get delta with valid times of the same type
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime2SecondsUTC;
+        time1->nsec = testTime2NanosecondsUTC;
+        time1->type = PS_TIME_UTC;
+        psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+        time2->sec = newTestTime2SecondsUTC;
+        time2->nsec = newTestTime2NanosecondsUTC;
+        time2->type = PS_TIME_UTC;
+        
+        psF64 delta = psTimeDelta(time2,time1);
+        is_double_tol(delta, deltaTime3, ERROR_TOL, "psTimeDelta(time1, NULL) returned correct delta for times of the same type");
+
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // XXX: This currently produces lots of errors
+    {
+        for(psS32 i = 0; i < APPB_TESTS; i++)
+        {
+            // Initialize time for test time B1
+            psTime *time = psTimeAlloc(PS_TIME_TAI);
+            time->sec = testTimeBSeconds[i];
+            time->nsec = testTimeBNanoseconds[i];
+
+            // Verify TAI ISO string
+            char *timeStr = psTimeToISO(time);
+            is_str(timeStr, testTimeBStrTAI[i], "TAI ISO string");
+            psFree(timeStr);
+
+            time = psTimeConvert(time, PS_TIME_TT);
+            timeStr = psTimeToISO(time);
+            is_str(timeStr, testTimeBStrTT[i], "TT ISO string");
+            psFree(timeStr);
+
+            // Verify UTC ISO string
+            time = psTimeConvert(time, PS_TIME_UTC);
+            time->leapsecond = testTimeBLeapsecond[i];
+            timeStr = psTimeToISO(time);
+            is_str(timeStr, testTimeBStrUTC[i], "UTC ISO string");
+            psFree(timeStr);
+
+            time = psTimeConvert(time, PS_TIME_UT1);
+            timeStr = psTimeToISO(time);
+            is_str(timeStr, testTimeBStrUT1[i], "UT1 ISO string");
+            psFree(timeStr);
+
+            psFree(time);
+        }
+
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psTime_04.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psTime_04.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tap_psTime_04.c	(revision 22158)
@@ -0,0 +1,146 @@
+/** @file  tst_psTime_04.c
+ *
+ *  @brief Test driver for psTime functions
+ *
+ *  This test driver contains the following tests for psTime:
+ *      Test A - Initialize time
+ *      Test B - Attempt to open non-existant time config file
+ *      Test C - Attempt to open non-existant time data files
+ *      Test D - Attempt to read incorrect number of files
+ *      Test E - Attempt to read incorrect number of from values
+ *      Test F - Attempt to read data file with typo in number
+ *      Test G - Free data
+ *      Test H - Attempt to use all timer functions
+ *      Test I - Tidal Corrections to UT1-UTC
+ *
+ *  @author  Ross Harman, MHPCC
+ *  @author  Eric Van Alst, MHPCC
+ *  @author  David Robbins, MHPCC
+ *
+ *  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2007-06-04 20:25:32 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(19);
+
+
+    // Test A - Initialize time
+    // XXX: Noting is actually verified here
+    {
+        psMemId id = psMemGetId();
+        psLibInit("pslib.config");
+        psLibFinalize();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test B - Attempt to open non-existant time config file
+    // XXX: Noting is actually verified here
+    {
+        psMemId id = psMemGetId();
+        psLibInit("zzz");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test C - Attempt to open non-existant time data files
+    // XXX: Noting is actually verified here
+    {
+        psMemId id = psMemGetId();
+        psLibInit("test.psTime.config1");
+        psLibFinalize();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test D - Attempt to read incorrect number of files
+    // XXX: Noting is actually verified here
+    {
+        psMemId id = psMemGetId();
+        psLibInit("test.psTime.config2");
+        psLibFinalize();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test E - Attempt to read incorrect number of from values
+    // XXX: Noting is actually verified here
+    {
+        psMemId id = psMemGetId();
+        psLibInit("test.psTime.config3");
+        psLibFinalize();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test F - Attempt to read data file with typo in number
+    // XXX: Noting is actually verified here
+    {
+        psMemId id = psMemGetId();
+        psLibInit("test.psTime.config4");
+        psLibFinalize();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testTimer1()
+    {
+        psMemId id = psMemGetId();
+        psF64 testTime = 0.0;
+        psF64 testTime2 = 0.0;
+        psF64 testTime3 = 0.0;
+
+        ok(psTimerStart("newTime"), "psTimerStart successful");
+        testTime = psTimerMark("newTime");
+        ok(testTime != 0.0, "psTimerMark() successful");
+        testTime2 = psTimerClear("newTime");
+        ok(testTime2 != 0.0, "psTimerClear() successful");
+        psTimerStart("newTime");
+        testTime3 = psTimerStop();
+        ok(testTime3 != 0.0, "psTimerStop() successful");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testTideUT1Corr()
+    // Verify NULL return with NULL input
+    // XXX: Verify error
+    {
+        psMemId id = psMemGetId();
+        psTime *empty = psTime_TideUT1Corr(NULL);
+        ok(empty == NULL, "psTime_TideUT1Corr() returned NULL for NULL input time");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testTideUT1Corr()
+    // 
+    {
+        psMemId id = psMemGetId();
+        psTime *noTide = psTimeAlloc(PS_TIME_UTC);
+        noTide->sec = 1049160600;
+        noTide->nsec = 0;
+        noTide->leapsecond = false;
+        psTime *empty = psTime_TideUT1Corr(noTide);
+        is_long(empty->sec, 1049160599, "psTime_TideUT1Corr() returned correct ->sec");
+        is_long(empty->nsec, 656981971, "psTime_TideUT1Corr() returned correct ->nsec");
+        ok(p_psTimeFinalize(), "p_psTimeFinalize() successful");
+        psFree(empty);
+        psFree(noTide);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psCoord.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psCoord.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psCoord.c	(revision 22158)
@@ -0,0 +1,469 @@
+/** @file  tst_psCoord.c
+*
+*  @brief The code will ...
+*
+*
+*  @author GLG, MHPCC
+*
+*  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2006-02-28 02:53:03 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#include "psTest.h"
+#include "pslib_strict.h"
+static psS32 testPlaneTransformAlloc(void);
+static psS32 testPlaneDistortAlloc(void);
+static psS32 testPlaneAlloc(void);
+static psS32 testPlaneTransformApply(void);
+static psS32 testPlaneDistortApply(void);
+static psS32 testPixelsTransform(void);
+
+testDescription tests[] = {
+                              {testPlaneTransformAlloc, 826, "psPlaneTransformAlloc()", 0, false},
+                              {testPlaneDistortAlloc, 827, "psPlaneDistortAlloc()", 0, false},
+                              {testPlaneAlloc, -1, "psPlaneAlloc()", 0, false},
+                              {testPlaneTransformApply, 831, "psPlaneTransformApply()", 0, false},
+                              {testPlaneDistortApply, 832, "psPlaneDistortApply()", 0, false},
+                              {testPixelsTransform, 833, "psPixelsTransform()", 0, false},
+                              {NULL}
+                          };
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel( PS_LOG_INFO );
+
+    return ( ! runTestSuite( stderr, "psCoord", tests, argc, argv ) );
+}
+
+#define ORDER_X 2
+#define ORDER_Y 3
+#define ORDER_Z 4
+#define ORDER_T 5
+
+psS32 testPlaneAlloc( void )
+{
+    // Allocate psPlane.
+    psPlane *myP = psPlaneAlloc();
+
+    // Verify returned value is not NULL
+    if(myP == NULL) {
+        psError(PS_ERR_UNKNOWN, true, "psPlaneAlloc() returned NULL not expected.");
+        return 1;
+    }
+
+    // Verify returned transform has members set properly
+    if (!isnan(myP->x)) {
+        psError(PS_ERR_UNKNOWN,true,"myP->x is %d, should be %d", myP->x, NAN);
+        return 2;
+    }
+
+    if (!isnan(myP->y)) {
+        psError(PS_ERR_UNKNOWN,true,"myP->y is %d, should be %d", myP->y, NAN);
+        return 3;
+    }
+
+    if (!isnan(myP->xErr)) {
+        psError(PS_ERR_UNKNOWN,true,"myP->xErr is %d, should be %d", myP->xErr, NAN);
+        return 4;
+    }
+
+    if (!isnan(myP->yErr)) {
+        psError(PS_ERR_UNKNOWN,true,"myP->yErr is %d, should be %d", myP->yErr, NAN);
+        return 5;
+    }
+
+    // Free psPlane
+    psFree(myP);
+
+    return 0;
+}
+
+psS32 testPlaneTransformAlloc( void )
+{
+    // Allocate psPlaneTransform with known x and y terms
+    psPlaneTransform *myPT = psPlaneTransformAlloc(ORDER_X, ORDER_Y);
+
+    // Verify returned value is not NULL
+    if(myPT == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Function returned NULL not expected.");
+        return 1;
+    }
+
+    // Verify returned transform has members set properly
+    if (myPT->x->nX != ORDER_X) {
+        psError(PS_ERR_UNKNOWN,true,"myPT->x->nX is %d, should be %d",
+                myPT->x->nX, ORDER_X);
+        return 2;
+    }
+    if (myPT->y->nX != ORDER_X) {
+        psError(PS_ERR_UNKNOWN,true,"myPT->y->nX is %d, should be %d",
+                myPT->y->nX, ORDER_X);
+        return 3;
+    }
+    if (myPT->x->nY != ORDER_Y) {
+        psError(PS_ERR_UNKNOWN,true,"myPT->x->nY is %d, should be %d",
+                myPT->x->nY, ORDER_Y);
+        return 4;
+    }
+    if (myPT->y->nY != ORDER_Y) {
+        psError(PS_ERR_UNKNOWN,true,"myPT->y->nY is %d, should be %d",
+                myPT->y->nY, ORDER_Y);
+        return 5;
+    }
+
+    // Free plane transform
+    psFree(myPT);
+
+    // Attempt to specify negative x order and verify NULL returned and errror message generated
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message: negative x order");
+    myPT = psPlaneTransformAlloc(-1, 1);
+    if (myPT != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psPlaneTransformAlloc() did not return NULL.");
+        return 6;
+    }
+
+    // Attempt to specify negative y order and verify NULL returned and error message generated
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message: negative y order");
+    myPT = psPlaneTransformAlloc(1, -1);
+    if (myPT != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psPlaneTransformAlloc() did not return NULL.");
+        return 7;
+    }
+
+    psFree(myPT);
+
+    return 0;
+}
+
+
+psS32 testPlaneDistortAlloc( void )
+{
+    // Invoke function with known parameters
+    psPlaneDistort *myPD = psPlaneDistortAlloc(ORDER_X, ORDER_Y, ORDER_Z, ORDER_T);
+
+    // Verify NULL is not returned
+    if(myPD == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Return of NULL not expected");
+        return 1;
+    }
+    // Verify the terms are properly set after allocation
+    if (myPD->x->nX != ORDER_X) {
+        psError(PS_ERR_UNKNOWN,true,"myPD->x->nX is %d, should be %d",
+                myPD->x->nX, ORDER_X);
+        return 2;
+    }
+    if (myPD->y->nX != ORDER_X) {
+        psError(PS_ERR_UNKNOWN,true,"myPD->y->nX is %d, should be %d",
+                myPD->y->nX, ORDER_X);
+        return 3;
+    }
+    if (myPD->x->nY != ORDER_Y) {
+        psError(PS_ERR_UNKNOWN,true,"myPD->x->nY is %d, should be %d",
+                myPD->x->nY, ORDER_Y);
+        return 4;
+    }
+    if (myPD->y->nY != ORDER_Y) {
+        psError(PS_ERR_UNKNOWN,true,"myPD->y->nY is %d, should be %d",
+                myPD->y->nY, ORDER_Y);
+        return 5;
+    }
+    if (myPD->x->nZ != ORDER_Z) {
+        psError(PS_ERR_UNKNOWN,true,"myPD->x->nZ is %d, should be %d",
+                myPD->x->nZ, ORDER_Z);
+        return 6;
+    }
+    if (myPD->y->nZ != ORDER_Z) {
+        psError(PS_ERR_UNKNOWN,true,"myPD->y->nZ is %d, should be %d",
+                myPD->y->nZ, ORDER_Z);
+        return 7;
+    }
+    if (myPD->x->nT != ORDER_T) {
+        psError(PS_ERR_UNKNOWN,true,"myPD->x->nT is %d, should be %d",
+                myPD->x->nT, ORDER_T);
+        return 8;
+    }
+    if (myPD->y->nT != ORDER_T) {
+        psError(PS_ERR_UNKNOWN,true,"myPD->y->nT is %d, should be %d",
+                myPD->y->nT, ORDER_T);
+        return 9;
+    }
+    // Free psPlaneTransform
+    psFree(myPD);
+
+    // Invoke function with negative x order parameter
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for negative x order");
+    myPD = psPlaneDistortAlloc(-1, 1, 1, 1);
+    if (myPD != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psPlaneDistortAlloc() did not return NULL.");
+        return 10;
+    }
+
+    // Invoke function with negative y order parameter
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for negative y order");
+    myPD = psPlaneDistortAlloc(1, -1, 1, 1);
+    if (myPD != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psPlaneDistortAlloc() did not return NULL.");
+        return 11;
+    }
+
+    // Invoke function with negative z order parameter
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for negative z order");
+    myPD = psPlaneDistortAlloc(1, 1, -1, 1);
+    if (myPD != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psPlaneDistortAlloc() did not return NULL.");
+        return 12;
+    }
+
+    // Invoke function with negative t order parameter
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for negative w order");
+    myPD = psPlaneDistortAlloc(1, 1, 1, -1);
+    if (myPD != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psPlaneDistortAlloc() did not return NULL.");
+    }
+
+    return 0;
+}
+
+#define N 10
+// We do a simple identity transformation on a few x,y pairs.
+psS32 testPlaneTransformApply( void )
+{
+    psPlane*          out = NULL;
+    psPolynomial2D*  tmp2DPoly = NULL;
+    psPlane*          rc;
+
+    // Create input coordinate
+    psPlane* in = psPlaneAlloc();
+    if(in == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return from psPlaneAlloc");
+        return 1;
+    }
+
+    // Create transform
+    psPlaneTransform* pt = psPlaneTransformAlloc(2,2);
+
+    // Set transform coefficients so the x coord input will equal x coord output, same for y
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+
+    // Apply transform for several points
+    for (psS32 i = 0; i < N; i++) {
+        in->x = (psF64) i;
+        in->y = (psF64) (i + 5.0);
+        in->xErr = 0.0;
+        in->yErr = 0.0;
+
+        // Verify function does not return NULL
+        out = psPlaneTransformApply(out, pt, in);
+        if( out  == NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Expected non-NULL return value");
+            return 1;
+        }
+        // Verify the expected values are returned
+        if (FLT_EPSILON < fabs(out->x - in->x)) {
+            psError(PS_ERR_UNKNOWN,true,"out.x is %lf, should be %lf", out->x, in->x);
+            return 3;
+        }
+        if (FLT_EPSILON < fabs(out->y - in->y)) {
+            psError(PS_ERR_UNKNOWN,true,"out.y is %lf, should be %lf", out->y, in->y);
+            return 4;
+        }
+    }
+    psFree(out);
+
+    // Verify return null and error message generater for null specified transform
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL psPlaneTransform");
+    rc = psPlaneTransformApply(NULL, NULL, in);
+    if (rc != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Function did not return NULL as expected for NULL psPlaneTransform.");
+        return 5;
+    }
+
+    // Verify return null and error message generated for null psPlaneTransform x coeff
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL x coeff psPlaneTransform");
+    tmp2DPoly = pt->x;
+    pt->x = NULL;
+    rc = psPlaneTransformApply(NULL, pt, in);
+    if (rc != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Function did not return NULL as expected for NULL x coeff psPlaneTransform");
+        return 6;
+    }
+    pt->x = tmp2DPoly;
+
+    // Verify return null and error message generated for null psPlaneTransform y coeff
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL y coeff psPlaneTransform");
+    tmp2DPoly = pt->y;
+    pt->y = NULL;
+    rc = psPlaneTransformApply(NULL, pt, in);
+    if (rc != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Function did not return NULL as expected for NULL y coeff psPlaneTransform");
+        return 7;
+    }
+    pt->y = tmp2DPoly;
+
+    // Verify return null and error message generated for null psPlane coordinate
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL psPlane");
+    rc = psPlaneTransformApply(NULL, pt, NULL);
+    if (rc != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Function did not return NULL as expected for NULL psPlane");
+        return 8;
+    }
+
+    psFree(pt);
+    psFree(in);
+
+    return 0;
+}
+
+#define COLOR 1.0
+#define MAGNITUDE 1.0
+// We do a simple identity transformation on a few x,y pairs.  For x and y,
+// we add in the COLOR and MAGNITUDE.
+psS32 testPlaneDistortApply( void )
+{
+    psPlane*         out       = NULL;
+    psPlane*         rc        = NULL;
+    psPolynomial4D* tmp4DPoly = NULL;
+
+    // Allocate input coordinate
+    psPlane* in = psPlaneAlloc();
+
+    // Create psPlaneTransform structure
+    psPlaneDistort*  pt = psPlaneDistortAlloc(2, 2, 2, 2);
+
+    pt->x->coeff[1][0][0][0] = 1.0;
+    pt->x->coeff[0][0][1][0] = 1.0;
+    pt->x->coeff[0][0][0][1] = 1.0;
+
+    pt->y->coeff[0][1][0][0] = 1.0;
+    pt->y->coeff[0][0][1][0] = 1.0;
+    pt->y->coeff[0][0][0][1] = 1.0;
+
+    for (psS32 i = 0; i < N; i++) {
+        in->x = (psF64) i;
+        in->y = (psF64) (i + 5.0);
+        in->xErr = 0.0;
+        in->yErr = 0.0;
+        out = psPlaneDistortApply(out, pt, in, COLOR, MAGNITUDE);
+
+        // Verify return value is not NULL
+        if(out == NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Expected non-NULL return");
+            return 1;
+        }
+        // Verify return value contains expected values
+        if (FLT_EPSILON < fabs(out->x - COLOR - MAGNITUDE - in->x)) {
+            psError(PS_ERR_UNKNOWN,true,"out->x is %lf, should be %lf",
+                    out->x, in->x + COLOR + MAGNITUDE);
+            return 2;
+        }
+        if (FLT_EPSILON < fabs(out->y - COLOR - MAGNITUDE - in->y)) {
+            psError(PS_ERR_UNKNOWN,true,"out->y is %lf, should be %lf",
+                    out->y, in->y + COLOR + MAGNITUDE);
+            return 3;
+        }
+    }
+    psFree(out);
+
+    // Attempt to invoke psPlaneDistortApply with NULL psPlaneDistort
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for null psPlaneDistort");
+    rc = psPlaneDistortApply(NULL, NULL, in, COLOR, MAGNITUDE);
+    if (rc != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL.");
+        return 4;
+    }
+
+    // Attempt to invoke psPlaneDistortApply with NULL psPlaneDistort x member
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for null x member psPlaneDistort");
+    tmp4DPoly = pt->x;
+    pt->x = NULL;
+    rc = psPlaneDistortApply(NULL, pt, in, COLOR, MAGNITUDE);
+    if (rc != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL.");
+        return 5;
+    }
+    pt->x = tmp4DPoly;
+
+    // Attempt to invoke psPlaneDistortApply with NULL psPlaneDistort y member
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for null y member psPlaneDistort");
+    tmp4DPoly = pt->y;
+    pt->y = NULL;
+    rc = psPlaneDistortApply(NULL, pt, in, COLOR, MAGNITUDE);
+    if (rc != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL.");
+        return 6;
+    }
+    pt->y = tmp4DPoly;
+
+    // Attempt to invoke psPlaneDistortApply with NULL input psPlane
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for null input psPlane");
+    rc = psPlaneDistortApply(NULL, pt, NULL, COLOR, MAGNITUDE);
+    if (rc != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL");
+        return 7;
+    }
+
+    psFree(pt);
+    psFree(in);
+
+    return 0;
+}
+
+psS32 testPixelsTransform(void)
+{
+    psPixels *input = NULL;
+    psPixels *output = NULL;
+    psPlaneTransform *trans = psPlaneTransformAlloc(1, 3);
+
+    //Return NULL for NULL input pixels
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    output = psPixelsTransform(output, input, trans);
+    if (output != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psPixelsTransform failed to return NULL for NULL input pixels.\n");
+        return 1;
+    }
+    //Return NULL for NULL input PlaneTransform
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    output = psPixelsTransform(output, input, NULL);
+    if (output != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psPixelsTransform failed to return NULL for NULL psPlaneTransform.\n");
+        return 2;
+    }
+
+    input = psPixelsAlloc(2);
+    input->n = 2;
+    input->data[0].x = 1.0;
+    input->data[0].y = 1.0;
+    input->data[1].x = 1.0;
+    input->data[1].y = 6.0;
+    trans->x->coeff[0][0] = 0;
+    trans->x->coeff[1][0] = 1.0;
+    trans->y->coeff[0][0] = 0;
+    trans->y->coeff[0][0] = 0;
+    trans->y->coeff[0][2] = 0.5;
+
+    //Verify that the output pixels are what we expected
+    output = psPixelsTransform(output, input, trans);
+    int nExpected = 9;
+    if (output->n != nExpected) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, false,
+                "psPixelsTransform failed to return the expected number of pixels.\n");
+        printf("\n output returned with %ld pixels\n\n", output->n);
+        for (int i = 0; i < output->n; i++) {
+            printf("  (%6.2lf, %6.2lf) pixel %d\n", output->data[i].x, output->data[i].y, i+1);
+        }
+        return 3;
+    }
+
+    psFree(trans);
+    psFree(input);
+    psFree(output);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psCoord01.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psCoord01.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psCoord01.c	(revision 22158)
@@ -0,0 +1,999 @@
+/**  @file  tst_psCoord01.c
+*
+*    @brief  The code will test several functions with PSLib source file
+*            psCoord.c
+*
+*    @author Eric Van Alst, MHPCC
+*
+* XXX: must do (r,d) -> (x, y) -> (r, d) test to ensure correctness.
+* XXX: The (Xs, Ys) scales are not be used properly.
+*
+*
+*    @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+*    @date  $Date: 2006-05-26 01:23:41 $
+*    @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+*    @date  $Date: 2006-05-26 01:23:41 $
+*
+*    Copyright 2005 Maui High Performance Computing Center, Univ. of Hawaii
+*/
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+static psS32 testProjectionAlloc(void);
+static psS32 testProjectTan(void);
+static psS32 testDeprojectTan(void);
+static psS32 testProjectSin(void);
+static psS32 testDeprojectSin(void);
+static psS32 testProjectAit(void);
+static psS32 testDeprojectAit(void);
+static psS32 testProjectPar(void);
+static psS32 testDeprojectPar(void);
+static psS32 testProjectFail(void);
+static psS32 testDeprojectFail(void);
+static psS32 testSetOffsetSphere(void);
+static psS32 testSetOffsetLinear(void);
+static psS32 testGetOffsetSphere(void);
+static psS32 testGetOffsetLinear(void);
+static psS32 testProjectTanDeProjectTan(void);
+
+testDescription tests[] = {
+                              {testProjectionAlloc, 833, "psProjectionAlloc",0,false},
+                              {testProjectFail, 834, "psProject",0,false},
+                              {testDeprojectFail, 835, "psProject",0,false},
+                              {testSetOffsetSphere, 0000, "psSphereSetOffset",0,false},
+                              {testSetOffsetLinear, 0000, "psSphereSetOffset",0,false},
+                              {testGetOffsetSphere, 0000, "psSphereGetOffset",0,false},
+                              {testGetOffsetLinear, 0000, "psSphereGetOffset",0,false},
+                              {NULL},
+                              /* XXX: Tests removed pending valuation -- test itself may be faulty. */
+                              {testProjectTan, 834, "psProject(TAN)",0,false},
+                              {testDeprojectTan, 835, "psDeproject(TAN)",0,false},
+                              {testProjectSin, 834, "psProject(SIN)",0,false},
+                              {testDeprojectSin, 835, "psDeproject(SIN)",0,false},
+                              {testProjectAit, 834, "psProject(AIT)",0,false},
+                              {testDeprojectAit, 835, "psDeproject(AIT)",0,false},
+                              {testProjectPar, 834, "psProject(PAR)",0,false},
+                              {testDeprojectPar, 835, "psDeproject(PAR)",0,false},
+                              {testProjectTanDeProjectTan, 0000, "psProject(TAN) -> psDeproject(TAN)",0,false}
+                          };
+
+
+#define ERROR_TOL    0.0001
+#define TESTPOINTS   4
+#define DEG_INC   30.0
+
+#define MY_TINY 0.0001
+#define PS_COMPARE_TINY_THEN_PRINT_ERROR(ACTUAL, EXPECT, TESTSTATUS) \
+if (MY_TINY < fabs(EXPECT - ACTUAL)) { \
+    psError(PS_ERR_UNKNOWN,true,"%s is %lg, should be %lg", #ACTUAL, ACTUAL, EXPECT, TESTSTATUS); \
+    return TESTSTATUS; \
+}
+
+
+//  alpha, delta, alpha-center, delta-center, scale-x, scale-y
+psF64 projectionTestPoint[TESTPOINTS][6] = {
+            {  0.785398,  0.785398,  0.000000,  0.000000,  1.000000,  1.000000 },
+            {  0.100000,  1.500000,  0.500000,  0.250000,  1.000000,  1.000000 },
+            {  0.628319,  0.448799,  0.000000,  0.000000,  0.250000,  0.750000 },
+            { -1.047196,  0.222222, -0.250000,  0.000000,  1.500000,  1.250000 }
+        };
+
+// Expected values for TAN
+psF64 projectionTanExpected[TESTPOINTS][2] = {
+            { -1.000000, -1.414214 },
+            {  0.088884, -3.066567 },
+            { -0.181636, -0.446444 },
+            {  1.535818, -0.404231 }
+        };
+
+// Expected values for SIN
+psF64 projectionSinExpected[TESTPOINTS][2] = {
+            { -0.500000, -0.707101 },
+            {  0.027546, -0.950366 },
+            { -0.132394, -0.325413 },
+            {  1.046712, -0.275497 }
+        };
+
+// Expected values for AIT
+psF64 projectionAitExpected[TESTPOINTS][2] = {
+            { -0.549175,  0.523375 },
+            {  0.027895,  0.313807 },
+            { -0.162822,  0.607646 },
+            {  1.455312,  0.955388 }
+        };
+
+// Expected values for PAR
+psF64 projectionParExpected[TESTPOINTS][2] = {
+            { -0.541244,  0.545532 },
+            {  0.027703,  0.329366 },
+            { -0.157157,  0.633550 },
+            {  1.432951,  0.971372 }
+        };
+
+// Testpoints, offset and expected values for psSphereSetOffset test
+#define TESTPOINTS_OFFSET  4
+psF64 setOffsetTestpoint[TESTPOINTS_OFFSET][2] = {
+            { 0.50,  0.50 },
+            {-0.50,  0.50 },
+            { 0.00,  0.00 },
+            { 1.50, -0.10 }
+        };
+
+psF64 setOffsetOffset[TESTPOINTS_OFFSET][2] = {
+            { 0.190761, -0.272205 },
+            {-0.553049, -0.460926 },
+            { 0.100335,-14.172222 },
+            {14.172222, -0.100335 }
+        };
+
+psF64 setOffsetResult[TESTPOINTS_OFFSET][2] = {
+            //XXX: Eugene says his values are correct, so i'm changing these values to the output.
+            //            { 0.25,  0.75 },
+            //            { 0.20,  0.80 },
+            //            {-0.10,  1.50 },
+            //            { 0.00,  0.00 }
+            { 0.68702,   0.230294},
+            { -0.966388,  0.0608434 },
+            {0.10,  -1.50 },
+            { 3.00141, -0.0140538  }
+        };
+
+psF64 getOffsetTestpoint1[TESTPOINTS_OFFSET][2] = {
+            { 0.00,  0.00 },
+            {-0.25,  0.50 },
+            { 0.50, -0.25 },
+            { 0.25, -0.10 }
+        };
+
+psF64 getOffsetTestpoint2[TESTPOINTS_OFFSET][2] = {
+            { 0.75,  0.25 },
+            { 0.40, -0.60 },
+            { 1.50,  0.50 },
+            { 0.10,  0.75 }
+        };
+
+psF64 getOffsetResult[TESTPOINTS_OFFSET][2] = {
+            //XXX: Eugene says his values are correct, so i'm changing these values to the output.
+            //            { -0.931596, -0.348976 },
+            //            { -1.632830,  2.649629 },
+            //            { -2.166795, -1.707211 },
+            //            {  0.167752, -1.151351 }
+            { 0.931596, 0.348976 },
+            { 1.632830,  -2.649629 },
+            { 2.166795, 1.707211 },
+            {  -0.167752, 1.151351 }
+        };
+
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel( PS_LOG_INFO );
+
+    return ( !runTestSuite(stderr,"psCoord",tests,argc,argv) );
+}
+
+psS32 testProjectionAlloc(void)
+{
+    // Allocate new psProjection structure
+    psProjection*  myProjection = psProjectionAlloc(1.1, 2.2, 3.3, 4.4, PS_PROJ_AIT);
+
+    // Verify NULL is not returned
+    if(myProjection == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Unexpected return of NULL");
+        return 1;
+    }
+    // Verify the members are set correctly
+    if(myProjection->R != 1.1) {
+        psError(PS_ERR_UNKNOWN,true,"R member set to %lg, but expected %lg",
+                myProjection->R, 1.1);
+        return 2;
+    }
+    if(myProjection->D != 2.2) {
+        psError(PS_ERR_UNKNOWN,true,"D member set to %lg, but expected %lg",
+                myProjection->D, 2.2);
+        return 3;
+    }
+    if(myProjection->Xs != 3.3) {
+        psError(PS_ERR_UNKNOWN,true,"Xs member set to %lg, but expected %lg",
+                myProjection->Xs, 3.3);
+        return 4;
+    }
+    if(myProjection->Ys != 4.4) {
+        psError(PS_ERR_UNKNOWN,true,"Ys member set to %lg, but expected %lg",
+                myProjection->Ys, 4.4);
+        return 5;
+    }
+    if(myProjection->type != PS_PROJ_AIT) {
+        psError(PS_ERR_UNKNOWN,true,"type member set to %d, but expected %d",
+                myProjection->type, PS_PROJ_AIT);
+        return 6;
+    }
+
+    // Free projection
+    psFree(myProjection);
+
+    return 0;
+}
+
+//HEY
+psS32 testProjectTan(void)
+{
+    psPlane*       out = NULL;
+    psSphere*      in = psSphereAlloc();
+    psSphere*      inTest = NULL;
+    psProjection*  myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_TAN);
+
+    // Perform projecton on various test points
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+
+        // Initialize input and project members
+        in->r = projectionTestPoint[i][0];
+        in->d = projectionTestPoint[i][1];
+        myProjection->R = projectionTestPoint[i][2];
+        myProjection->D = projectionTestPoint[i][3];
+        myProjection->Xs = projectionTestPoint[i][4];
+        myProjection->Ys = projectionTestPoint[i][5];
+
+        // Perform projection
+        out = psProject(in, myProjection);
+        inTest = psDeproject(out, myProjection);
+
+        // Verify output not NULL
+        if(out == NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Return null not expected");
+            return i*10+3;
+        }
+
+        // Verify output is as expected
+        if(fabs(out->x - projectionTanExpected[i][0]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint %d  psPlane->x = %lg  expected %lg",
+                    i,out->x, projectionTanExpected[i][0]);
+            return i*10+1;
+        }
+        if(fabs(out->y - projectionTanExpected[i][1]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint % d  psPlane->y = %lg  expected %lg",
+                    i,out->y, projectionTanExpected[i][1]);
+            return i*10+2;
+        }
+
+        // Verify output is as expected
+        if(fabs(in->r - inTest->r) > ERROR_TOL) {
+            printf("TEST ER (in->r, inTest->r) (%.2f %.2f)\n", in->r, inTest->r);
+            return i*10+4;
+        }
+        if(fabs(in->d - inTest->d) > ERROR_TOL) {
+            printf("TEST ERROR: (in->d, inTest->d) (%.2f %.2f)\n", in->d, inTest->d);
+            return i*10+5;
+        }
+
+        psFree(inTest);
+        psFree(out);
+    }
+
+    psFree(in);
+    psFree(myProjection);
+
+    return 0;
+}
+
+psS32 testDeprojectTan(void)
+{
+    psSphere*       out = NULL;
+    psPlane*        in = psPlaneAlloc();
+    psProjection*   myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_TAN);
+
+    // Perform deprojection on various test points
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+
+        // Initialize input and projection members
+        in->x = projectionTanExpected[i][0];
+        in->y = projectionTanExpected[i][1];
+        myProjection->R = projectionTestPoint[i][2];
+        myProjection->D = projectionTestPoint[i][3];
+        myProjection->Xs = projectionTestPoint[i][4];
+        myProjection->Ys = projectionTestPoint[i][5];
+
+        // Perform deprojection
+        out = psDeproject(in, myProjection);
+
+        // Verify output is not NULL
+        if(out == NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Return null not expected");
+            return 20*i;
+        }
+
+        // Verify output is as expected
+        if(fabs(out->r - projectionTestPoint[i][0]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint %d  psSphere->r = %lg  expected %lg",
+                    i,out->r,projectionTestPoint[i][0]);
+            return 20*i + 1;
+        }
+        if(fabs(out->d - projectionTestPoint[i][1]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint %d  psSphere->d = %lg expected %lg",
+                    i, out->d, projectionTestPoint[i][1]);
+            return 20*i + 2;
+        }
+        psFree(out);
+    }
+
+    psFree(in);
+    psFree(myProjection);
+
+    return 0;
+}
+
+psS32 testProjectSin(void)
+{
+    psPlane*       out = NULL;
+    psSphere*      in = psSphereAlloc();
+    psProjection*  myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_SIN);
+
+    // Perform projecton on various test points
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+
+        // Initialize input and project members
+        in->r = projectionTestPoint[i][0];
+        in->d = projectionTestPoint[i][1];
+        myProjection->R = projectionTestPoint[i][2];
+        myProjection->D = projectionTestPoint[i][3];
+        myProjection->Xs = projectionTestPoint[i][4];
+        myProjection->Ys = projectionTestPoint[i][5];
+
+        // Perform projection
+        out = psProject(in, myProjection);
+
+        // Verify output not NULL
+        if(out == NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Return null not expected");
+            return i*10;
+        }
+
+        // Verify output is as expected
+        if(fabs(out->x - projectionSinExpected[i][0]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint %d  psPlane->x = %lg  expected %lg",
+                    i,out->x, projectionSinExpected[i][0]);
+            return i*10+1;
+        }
+        if(fabs(out->y - projectionSinExpected[i][1]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint % d  psPlane->y = %lg  expected %lg",
+                    i,out->y, projectionSinExpected[i][1]);
+            return i*10+2;
+        }
+        psFree(out);
+    }
+
+    psFree(in);
+    psFree(myProjection);
+
+    return 0;
+}
+
+psS32 testDeprojectSin(void)
+{
+    psSphere*       out = NULL;
+    psPlane*        in = psPlaneAlloc();
+    psProjection*   myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_SIN);
+
+    // Perform deprojection on various test points
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+
+        // Initialize input and projection members
+        in->x = projectionSinExpected[i][0];
+        in->y = projectionSinExpected[i][1];
+        myProjection->R = projectionTestPoint[i][2];
+        myProjection->D = projectionTestPoint[i][3];
+        myProjection->Xs = projectionTestPoint[i][4];
+        myProjection->Ys = projectionTestPoint[i][5];
+
+        // Perform deprojection
+        out = psDeproject(in, myProjection);
+
+        // Verify output is not NULL
+        if(out == NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Return null not expected");
+            return 20*i;
+        }
+
+        // Verify output is as expected
+        if(fabs(out->r - projectionTestPoint[i][0]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint %d  psSphere->r = %lg  expected %lg",
+                    i,out->r,projectionTestPoint[i][0]);
+            return 20*i + 1;
+        }
+        if(fabs(out->d - projectionTestPoint[i][1]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint %d  psSphere->d = %lg expected %lg",
+                    i, out->d, projectionTestPoint[i][1]);
+            return 20*i + 2;
+        }
+        psFree(out);
+    }
+
+    psFree(in);
+    psFree(myProjection);
+
+    return 0;
+}
+
+psS32 testProjectAit(void)
+{
+    psPlane*       out = NULL;
+    psSphere*      in = psSphereAlloc();
+    psProjection*  myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_AIT);
+
+    // Perform projecton on various test points
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+
+        // Initialize input and project members
+        in->r = projectionTestPoint[i][0];
+        in->d = projectionTestPoint[i][1];
+        myProjection->R = projectionTestPoint[i][2];
+        myProjection->D = projectionTestPoint[i][3];
+        myProjection->Xs = projectionTestPoint[i][4];
+        myProjection->Ys = projectionTestPoint[i][5];
+
+        // Perform projection
+        out = psProject(in, myProjection);
+
+        // Verify output not NULL
+        if(out == NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Return null not expected");
+            return i*10;
+        }
+
+        // Verify output is as expected
+        if(fabs(out->x - projectionAitExpected[i][0]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint %d  psPlane->x = %lg  expected %lg",
+                    i,out->x, projectionAitExpected[i][0]);
+            return i*10+1;
+        }
+        if(fabs(out->y - projectionAitExpected[i][1]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint % d  psPlane->y = %lg  expected %lg",
+                    i,out->y, projectionAitExpected[i][1]);
+            return i*10+2;
+        }
+        psFree(out);
+    }
+
+    psFree(in);
+    psFree(myProjection);
+
+    return 0;
+}
+
+psS32 testDeprojectAit(void)
+{
+    psSphere*       out = NULL;
+    psPlane*        in = psPlaneAlloc();
+    psProjection*   myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_AIT);
+
+    // Perform deprojection on various test points
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+
+        // Initialize input and projection members
+        in->x = projectionAitExpected[i][0];
+        in->y = projectionAitExpected[i][1];
+        myProjection->R = projectionTestPoint[i][2];
+        myProjection->D = projectionTestPoint[i][3];
+        myProjection->Xs = projectionTestPoint[i][4];
+        myProjection->Ys = projectionTestPoint[i][5];
+
+        // Perform deprojection
+        out = psDeproject(in, myProjection);
+
+        // Verify output is not NULL
+        if(out == NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Return null not expected");
+            return 20*i;
+        }
+
+        // Verify output is as expected
+        if(fabs(out->r - projectionTestPoint[i][0]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint %d  psSphere->r = %lg  expected %lg",
+                    i,out->r,projectionTestPoint[i][0]);
+            return 20*i + 1;
+        }
+        if(fabs(out->d - projectionTestPoint[i][1]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint %d  psSphere->d = %lg expected %lg",
+                    i, out->d, projectionTestPoint[i][1]);
+            return 20*i + 2;
+        }
+        psFree(out);
+    }
+
+    psFree(in);
+    psFree(myProjection);
+
+    return 0;
+}
+
+psS32 testProjectPar(void)
+{
+    psPlane*       out = NULL;
+    psSphere*      in = psSphereAlloc();
+    psProjection*  myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_PAR);
+
+    // Perform projecton on various test points
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+
+        // Initialize input and project members
+        in->r = projectionTestPoint[i][0];
+        in->d = projectionTestPoint[i][1];
+        myProjection->R = projectionTestPoint[i][2];
+        myProjection->D = projectionTestPoint[i][3];
+        myProjection->Xs = projectionTestPoint[i][4];
+        myProjection->Ys = projectionTestPoint[i][5];
+
+        // Perform projection
+        out = psProject(in, myProjection);
+
+        // Verify output not NULL
+        if(out == NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Return null not expected");
+            return i*10;
+        }
+
+        // Verify output is as expected
+        if(fabs(out->x - projectionParExpected[i][0]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint %d  psPlane->x = %lg  expected %lg",
+                    i,out->x, projectionParExpected[i][0]);
+            return i*10+1;
+        }
+        if(fabs(out->y - projectionParExpected[i][1]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint % d  psPlane->y = %lg  expected %lg",
+                    i,out->y, projectionParExpected[i][1]);
+            return i*10+2;
+        }
+        psFree(out);
+    }
+
+    psFree(in);
+    psFree(myProjection);
+
+    return 0;
+}
+
+psS32 testDeprojectPar(void)
+{
+    psSphere*       out = NULL;
+    psPlane*        in = psPlaneAlloc();
+    psProjection*   myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_PAR);
+
+    // Perform deprojection on various test points
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+
+        // Initialize input and projection members
+        in->x = projectionParExpected[i][0];
+        in->y = projectionParExpected[i][1];
+        myProjection->R = projectionTestPoint[i][2];
+        myProjection->D = projectionTestPoint[i][3];
+        myProjection->Xs = projectionTestPoint[i][4];
+        myProjection->Ys = projectionTestPoint[i][5];
+
+        // Perform deprojection
+        out = psDeproject(in, myProjection);
+
+        // Verify output is not NULL
+        if(out == NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Return null not expected");
+            return 20*i;
+        }
+
+        // Verify output is as expected
+        if(fabs(out->r - projectionTestPoint[i][0]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint %d  psSphere->r = %lg  expected %lg",
+                    i,out->r,projectionTestPoint[i][0]);
+            return 20*i + 1;
+        }
+        if(fabs(out->d - projectionTestPoint[i][1]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint %d  psSphere->d = %lg expected %lg",
+                    i, out->d, projectionTestPoint[i][1]);
+            return 20*i + 2;
+        }
+        psFree(out);
+    }
+
+    psFree(in);
+    psFree(myProjection);
+
+    return 0;
+}
+
+psS32 testProjectFail(void)
+{
+    psPlane*       out          = NULL;
+    psProjection*  myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_TAN);
+    psSphere*      in           = psSphereAlloc();
+
+    // Invoke function with null coordinate argument
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for null coord arg");
+    out = psProject(NULL, myProjection);
+    if(out != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return null as expected");
+        return 1;
+    }
+
+    // Invoke function with null projection argument
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for null projection arg");
+    out = psProject(in, NULL);
+    if(out != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return null as expected");
+        return 2;
+    }
+
+    // Invoke function with invalid projection type
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid projection type");
+    myProjection->type = PS_PROJ_NTYPE;
+    out = psProject(in,myProjection);
+    if(out != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return null as expected");
+        return 3;
+    }
+
+    psFree(myProjection);
+    psFree(in);
+
+    return 0;
+}
+
+psS32 testDeprojectFail(void)
+{
+    psSphere*      out          = NULL;
+    psProjection*  myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_TAN);
+    psPlane*       in           = psPlaneAlloc();
+
+    // Invoke function with null coordinate argument
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for null coord arg");
+    out = psDeproject(NULL, myProjection);
+    if(out != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return null as expected");
+        return 1;
+    }
+
+    // Invoke function with null projection argument
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for null projection arg");
+    out = psDeproject(in, NULL);
+    if(out != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return null as expected");
+        return 2;
+    }
+
+    // Invoke function with invalid projection type
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid projection type");
+    myProjection->type = PS_PROJ_NTYPE;
+    out = psDeproject(in,myProjection);
+    if(out != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return null as expected");
+        return 3;
+    }
+
+    psFree(myProjection);
+    psFree(in);
+
+    return 0;
+}
+
+psS32 testSetOffsetSphere( void )
+{
+    psSphere* position1 = psSphereAlloc();
+    psSphere* position2 = NULL;
+    psSphere* offset    = psSphereAlloc();
+    psSphere* tmpOffset = psSphereAlloc();
+
+    // Initialize first position
+    position1->r = DEG_TO_RAD(90.0);
+    position1->d = DEG_TO_RAD(45.0);
+    position1->rErr = 0.0;
+    position1->dErr = 0.0;
+
+    //  Using various offset verify spherical offset
+    //  Use all the valid unit types
+    for (psF64 r = 0.0; r < 180.0; r += DEG_INC) {
+        for (psF64 d = 0.0; d < 90.0; d += DEG_INC) {
+
+            offset->r = DEG_TO_RAD(r);
+            offset->d = DEG_TO_RAD(d);
+            offset->rErr = 0.0;
+            offset->dErr = 0.0;
+
+            position2 = psSphereSetOffset(position1, offset, PS_SPHERICAL, PS_RADIAN);
+            PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->r, (position1->r + offset->r), 1);
+            PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->d, (position1->d + offset->d), 2);
+            psFree(position2);
+
+            tmpOffset->r = RAD_TO_DEG(offset->r);
+            tmpOffset->d = RAD_TO_DEG(offset->d);
+            tmpOffset->rErr = 0.0;
+            tmpOffset->dErr = 0.0;
+            position2 = psSphereSetOffset(position1, tmpOffset, PS_SPHERICAL, PS_DEGREE);
+            PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->r, (position1->r + offset->r), 3);
+            PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->d, (position1->d + offset->d), 4);
+            psFree(position2);
+
+            tmpOffset->r = RAD_TO_MIN(offset->r);
+            tmpOffset->d = RAD_TO_MIN(offset->d);
+            tmpOffset->rErr = 0.0;
+            tmpOffset->dErr = 0.0;
+            position2 = psSphereSetOffset(position1, tmpOffset, PS_SPHERICAL, PS_ARCMIN);
+            PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->r, (position1->r + offset->r), 5);
+            PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->d, (position1->d + offset->d), 6);
+            psFree(position2);
+
+            tmpOffset->r = RAD_TO_SEC(offset->r);
+            tmpOffset->d = RAD_TO_SEC(offset->d);
+            tmpOffset->rErr = 0.0;
+            tmpOffset->dErr = 0.0;
+            position2 = psSphereSetOffset(position1, tmpOffset, PS_SPHERICAL, PS_ARCSEC);
+            PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->r, (position1->r + offset->r), 7);
+            PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->d, (position1->d + offset->d), 8);
+            psFree(position2);
+        }
+    }
+
+    // Attempt to call function with null input coordinate
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message null input coord");
+    position2 = psSphereSetOffset(NULL, offset, PS_LINEAR, PS_ARCSEC);
+    if (position2 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL");
+        return 30;
+    }
+
+    // Attempt to call function with null offset
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message null offset");
+    position2 = psSphereSetOffset(position1, NULL, PS_LINEAR, PS_ARCSEC);
+    if (position2 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL");
+        return 31;
+    }
+
+    // Attempt to call function with invalid mode
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message invalid mode");
+    position2 = psSphereSetOffset(position1, offset, 0x54321, 0);
+    if (position2 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL");
+        return 32;
+    }
+
+    // Attempt to call function with invalid unit
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message invalid unit");
+    position2 = psSphereSetOffset(position1, offset, PS_SPHERICAL, 0x54321);
+    if (position2 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL");
+        return 33;
+    }
+
+    psFree(position1);
+    psFree(offset);
+    psFree(tmpOffset);
+
+    return 0;
+}
+
+psS32 testSetOffsetLinear(void)
+{
+    psSphere*   coord = psSphereAlloc();
+    psSphere*   offset = psSphereAlloc();
+    psSphere*   out = NULL;
+
+    for(psS32 i = 0; i < TESTPOINTS_OFFSET; i++) {
+
+        coord->r = setOffsetTestpoint[i][0];
+        coord->d = setOffsetTestpoint[i][1];
+
+        offset->r = setOffsetOffset[i][0];
+        offset->d = setOffsetOffset[i][1];
+
+        out = psSphereSetOffset(coord, offset, PS_LINEAR, PS_RADIAN);
+
+        if(fabs(out->r - setOffsetResult[i][0]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint %d: Result out->r = %lg not equal to expected %lg",
+                    i, out->r, setOffsetResult[i][0]);
+            return i*10+1;
+        }
+        if(fabs(out->d - setOffsetResult[i][1]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint %d: Result out->d = %lg not equal to expected %lg",
+                    i,out->d, setOffsetResult[i][1]);
+            return i*10+2;
+        }
+
+        psFree(out);
+    }
+
+    psFree(coord);
+    psFree(offset);
+
+    return 0;
+}
+
+psS32 testGetOffsetSphere( void )
+{
+    psSphere* position1 = psSphereAlloc();
+    psSphere* position2 = psSphereAlloc();
+    psSphere *offset = NULL;
+
+    position1->r = DEG_TO_RAD(90.0);
+    position1->d = DEG_TO_RAD(45.0);
+    position1->rErr = 0.0;
+    position1->dErr = 0.0;
+
+    for (psF64 r = 0.0; r < 180.0;r += DEG_INC) {
+        for (psF64 d = 0.0;d < 90.0; d += DEG_INC) {
+            position2->r = DEG_TO_RAD(r);
+            position2->d = DEG_TO_RAD(d);
+            position2->rErr = 0.0;
+            position2->dErr = 0.0;
+
+            offset = psSphereGetOffset( position1,  position2,
+                                        PS_SPHERICAL, PS_RADIAN);
+            PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->r, (position2->r - position1->r), 1);
+            PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->d, (position2->d - position1->d), 1);
+            psFree(offset);
+
+            offset = psSphereGetOffset( position1, position2,
+                                        PS_SPHERICAL, PS_DEGREE);
+            offset->r = DEG_TO_RAD(offset->r);
+            offset->d = DEG_TO_RAD(offset->d);
+            PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->r, (position2->r - position1->r), 2);
+            PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->d, (position2->d - position1->d), 3);
+            psFree(offset);
+
+            offset = psSphereGetOffset( position1,  position2,
+                                        PS_SPHERICAL, PS_ARCMIN);
+            offset->r = MIN_TO_RAD(offset->r);
+            offset->d = MIN_TO_RAD(offset->d);
+            PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->r, (position2->r - position1->r), 2);
+            PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->d, (position2->d - position1->d), 3);
+            psFree(offset);
+
+            offset = psSphereGetOffset( position1,  position2,
+                                        PS_SPHERICAL, PS_ARCSEC);
+            offset->r = SEC_TO_RAD(offset->r);
+            offset->d = SEC_TO_RAD(offset->d);
+            PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->r, (position2->r - position1->r), 2);
+            PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->d, (position2->d - position1->d), 3);
+            psFree(offset);
+        }
+    }
+
+    // Attempt to invoke function with null position 1 parameter
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for null position");
+    offset = psSphereGetOffset(NULL, position2, PS_LINEAR, 0);
+    if (offset != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL as expected");
+        return 10;
+    }
+
+    // Attempt to invoke function with null position 2 parameter
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for null position");
+    offset = psSphereGetOffset(position1, NULL, PS_LINEAR, 0);
+    if (offset != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL as expected");
+        return 11;
+    }
+
+    // Attempt to invoke function with invalid mode
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid mode");
+    offset = psSphereGetOffset(position1, position2, 0x54321, 0);
+    if (offset != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL as expected");
+        return 12;
+    }
+
+    // Attempt to invoke function with invalid unit type
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid unit type");
+    offset = psSphereGetOffset(position1, position2, PS_SPHERICAL, 0x54321);
+    if (offset != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL as expected");
+        return 13;
+    }
+
+    // Attempt to invoke function with coordinate 1 declination value 90.0 degree
+    position1->d = DEG_TO_RAD(90.0);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate warning message");
+    offset = psSphereGetOffset(position1, position2, PS_SPHERICAL, PS_RADIAN);
+    if (offset != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL as expected");
+        return 14;
+    }
+
+    // Attempt to invoke function with coordinate 2 declination value 90.0 degree
+    position1->d = DEG_TO_RAD(45.0);
+    position2->d = DEG_TO_RAD(90.0);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate warning message");
+    offset = psSphereGetOffset(position1, position2, PS_SPHERICAL, PS_RADIAN);
+    if (offset != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL as expected");
+        return 15;
+    }
+
+    psFree(position1);
+    psFree(position2);
+
+    return 0;
+}
+
+psS32 testGetOffsetLinear(void)
+{
+    psSphere*   coord1 = psSphereAlloc();
+    psSphere*   coord2 = psSphereAlloc();
+    psSphere*   out = NULL;
+
+    for(psS32 i = 0; i < TESTPOINTS_OFFSET; i++) {
+
+        coord1->r = getOffsetTestpoint1[i][0];
+        coord1->d = getOffsetTestpoint1[i][1];
+
+        coord2->r = getOffsetTestpoint2[i][0];
+        coord2->d = getOffsetTestpoint2[i][1];
+
+        out = psSphereGetOffset(coord1, coord2, PS_LINEAR, PS_RADIAN);
+
+        if(fabs(out->r - getOffsetResult[i][0]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint %d: Result out->r = %lg not equal to expected %lg",
+                    i, out->r, getOffsetResult[i][0]);
+            return i*10+1;
+        }
+        if(fabs(out->d - getOffsetResult[i][1]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Testpoint %d: Result out->d = %lg not equal to expected %lg",
+                    i,out->d, getOffsetResult[i][1]);
+            return i*10+2;
+        }
+
+        psFree(out);
+    }
+
+    psFree(coord1);
+    psFree(coord2);
+
+    return 0;
+}
+
+#define DEG_INC2 15.0
+#define VERBOSE 0
+psS32 testProjectTanDeProjectTan()
+{
+    psS32 rc = 0;
+    //
+    // I'm not convinced that the p_psProject() and p_psDeproject() functions work
+    // correctly.  If we project a set of coordinates over a wide range of (R, D)
+    // values, then deproject them, the original (R, D) values are only produced
+    // when D is larger than 0.  This code demonstrates that.
+    //
+    psProjection *tmpProj = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+    if (1) { //HEY
+        psPlane planeCoord01;
+        psSphere skyCoord01;
+        psSphere skyCoord02;
+        for (psF32 R = -90.0 ; R <= 90.0 ; R+= DEG_INC2) {
+            for (psF32 D = -90.0 ; D <= 90.0 ; D+= DEG_INC2) {
+                if ((fabs(R) != 90.0) && (fabs(D) != 90.0)) {
+                    skyCoord01.r = DEG_TO_RAD(R);
+                    skyCoord01.d = DEG_TO_RAD(D);
+                    p_psProject(&planeCoord01, &skyCoord01, tmpProj);
+                    p_psDeproject(&skyCoord02, &planeCoord01, tmpProj);
+                    if ((fabs(skyCoord01.r - skyCoord02.r) < FLT_EPSILON) &&
+                            (fabs(skyCoord01.d - skyCoord02.d) < FLT_EPSILON)) {
+                        if (VERBOSE) {
+                            printf("CORRECT: (%.2fr %.2fd) (%.2fr %.2fd) -> (%.2f %.2f) -> (%.2fr %.2fd)\n", R, D,
+                                   skyCoord01.r, skyCoord01.d,
+                                   planeCoord01.x, planeCoord01.y,
+                                   skyCoord02.r, skyCoord02.d);
+                        }
+                        rc = 1;
+                    } else {
+                        printf("TEST ERROR: (%.2fr %.2fd) (%.2fr %.2fd) -> (%.2f %.2f) -> (%.2fr %.2fd)\n", R, D,
+                               skyCoord01.r, skyCoord01.d,
+                               planeCoord01.x, planeCoord01.y,
+                               skyCoord02.r, skyCoord02.d);
+                        rc = 1;
+                    }
+                }
+            }
+        }
+    }
+    return(rc);
+}
+
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psCoord02.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psCoord02.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psCoord02.c	(revision 22158)
@@ -0,0 +1,572 @@
+/** @file  tst_psCoord02.c
+*
+*  @brief This file contains test code for:
+*
+*  @author GLG, MHPCC
+*
+*  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2006-02-17 03:24:46 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#include "psTest.h"
+#include "pslib_strict.h"
+
+static psS32 test04( void );
+static psS32 test05( void );
+static psS32 test06( void );
+static psS32 test07( void );
+
+testDescription tests[] = {
+                              {test04, 660, "psPlaneTransformCombine()", 0, false},
+                              {test05, 662, "psPlaneTransformFit()", 0, false},
+                              {test06, 663, "psPlaneTransformInvert()", 0, false},
+                              {test07, 666, "psPlaneTransformDeriv()", 0, false},
+                              {NULL}
+                          };
+
+#define PS_PERCENT_COMPARE(X, Y, PERCENT_FRACTION) (fabs((Y)-(X))/fabs(X) < (PERCENT_FRACTION))
+
+//#define PS_GEN_RAN_FLOAT (-1.0 + (psF32) (rand() % 2))
+#define PS_GEN_RAN_FLOAT (-0.5 + ((psF32)rand()) / ((psF32) RAND_MAX))
+#define RANDOM_SEED 1995
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetLevel( PS_LOG_INFO );
+    psLogSetFormat("HLNM");
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("psPlaneTransformCombine", 0);
+    psTraceSetLevel("multiplyDPoly2D", 0);
+    srand(RANDOM_SEED);
+
+    return ( ! runTestSuite( stderr, "psImage", tests, argc, argv ) );
+}
+
+
+/******************************************************************************
+TEST04: The strategy behind test04() is to generate a pair of transforms t1
+and t2 with a wide variety of sizes for the x/y components of the x/y
+transforms, then set the coefficients of t1/t2 to arbitray values, then
+generate a new transform t3 via psPlaneTransformCombine() function.  Then, for
+several arbitrary input plane coordinates, we tarnsform them via the new
+transform t3, as well as individually via t1 then t2, and verify that they
+produce identical output coordinates.
+ *****************************************************************************/
+// These macros determine the number of x/y test points which will be x-formed.
+#define TST04_X_MIN 0.0
+#define TST04_X_MAX 10.0
+#define TST04_Y_MIN 0.0
+#define TST04_Y_MAX 10.0
+#define TST04_NUM 5.0
+// These macros define the max sizes of the various input transforms.
+#define TST04_T1_X_X 2
+#define TST04_T1_X_Y 3
+#define TST04_T1_Y_X 3
+#define TST04_T1_Y_Y 3
+#define TST04_T2_X_X 3
+#define TST04_T2_X_Y 3
+#define TST04_T2_Y_X 3
+#define TST04_T2_Y_Y 3
+/******************************************************************************
+tstTransforms(t1, t2, t3): this function generates a set of arbitrary x/y
+coordinates, then transforms them into output coordinates via the t3
+transform, as well as the t1 followed by the t2 transform.  It verifies the
+output coordinates are identical and returns TRUE if so.  Otherwise, it prints
+an error message and returns FALSE.
+ *****************************************************************************/
+bool tstTransforms(psPlaneTransform *t1, psPlaneTransform *t2, psPlaneTransform *t3)
+{
+    bool testStatus = true;
+    psPlane *in = psPlaneAlloc();
+    in->xErr = 0.0;
+    in->yErr = 0.0;
+
+    for (in->x = TST04_X_MIN ; in->x <= TST04_X_MAX ; in->x+= (TST04_X_MAX-TST04_X_MIN) / TST04_NUM) {
+        for (in->y = TST04_Y_MIN ; in->y <= TST04_Y_MAX ; in->y+= (TST04_Y_MAX-TST04_Y_MIN) / TST04_NUM) {
+            // Apply the t1/t2 transforms individually to the in coords.
+            psPlane *mid = psPlaneTransformApply(NULL, t1, in);
+            if (mid == NULL) {
+                printf("TEST ERROR: intermediate psPlane coords are NULL.\n");
+                psFree(in);
+                return(false);
+            }
+
+            psPlane *outT1T2 = psPlaneTransformApply(NULL, t2, mid);
+            if (outT1T2 == NULL) {
+                printf("TEST ERROR: intermediate psPlane coords are NULL.\n");
+                psFree(mid);
+                return(false);
+            }
+
+            // Apply the t3 transforms individually to the in coords.
+            psPlane *outT3 = psPlaneTransformApply(NULL, t3, in);
+            if (outT3 == NULL) {
+                printf("TEST ERROR: intermediate psPlane coords are NULL.\n");
+                psFree(mid);
+                psFree(outT1T2);
+                return(false);
+            }
+
+            // Verify that the results are identical.
+            if (!PS_PERCENT_COMPARE(outT3->x, outT1T2->x, 0.01)) {
+                printf("TEST ERROR: x is %f, should be %f\n", outT3->x, outT1T2->x);
+                testStatus = false;
+            }
+            // Verify that the results are identical.
+            if (!PS_PERCENT_COMPARE(outT3->y, outT1T2->y, 0.01)) {
+                printf("TEST ERROR: y is %f, should be %f\n", outT3->y, outT1T2->y);
+                testStatus = false;
+            }
+            if (0) {
+                if (fabs(outT3->x - outT1T2->x) > FLT_EPSILON) {
+                    printf("TEST ERROR: x is %f, should be %f\n", outT3->x, outT1T2->x);
+                    testStatus = false;
+                    printf("(in->x, in->y) is (%f, %f)\n", in->x, in->y);
+                    printf("(mid->x, mid->y) is (%f, %f)\n", mid->x, mid->y);
+                    printf("(outT1T2->x, outT1T2->y) is (%f, %f)\n", outT1T2->x, outT1T2->y);
+                    printf("(outT3->x, outT3->y) is (%f, %f)\n", outT3->x, outT3->y);
+                    PS_POLY_PRINT_2D(t1->x);
+                    PS_POLY_PRINT_2D(t1->y);
+                    PS_POLY_PRINT_2D(t2->x);
+                    PS_POLY_PRINT_2D(t2->y);
+                    PS_POLY_PRINT_2D(t3->x);
+                    PS_POLY_PRINT_2D(t3->y);
+                }
+                if (fabs(outT3->y - outT1T2->y) > FLT_EPSILON) {
+                    printf("TEST ERROR: y is %f, should be %f\n", outT3->y, outT1T2->y);
+                    testStatus = false;
+                    printf("(in->x, in->y) is (%f, %f)\n", in->x, in->y);
+                    printf("(mid->x, mid->y) is (%f, %f)\n", mid->x, mid->y);
+                    printf("(outT1T2->x, outT1T2->y) is (%f, %f)\n", outT1T2->x, outT1T2->y);
+                    printf("(outT3->x, outT3->y) is (%f, %f)\n", outT3->x, outT3->y);
+                    PS_POLY_PRINT_2D(t1->x);
+                    PS_POLY_PRINT_2D(t1->y);
+                    PS_POLY_PRINT_2D(t2->x);
+                    PS_POLY_PRINT_2D(t2->y);
+                    PS_POLY_PRINT_2D(t3->x);
+                    PS_POLY_PRINT_2D(t3->y);
+                }
+            }
+            psFree(mid);
+            psFree(outT1T2);
+            psFree(outT3);
+        }
+    }
+
+    psFree(in);
+    return(testStatus);
+}
+
+/******************************************************************************
+setCoeffs(t1, t2): this function sets the coefficients of the t1 and t2
+transforms to somewhat arbitrary values.
+ *****************************************************************************/
+int setCoeffs(psPlaneTransform *t1, psPlaneTransform *t2)
+{
+    for (psS32 t1xx = 0 ; t1xx < t1->x->nX+1 ; t1xx++) {
+        for (psS32 t1xy = 0 ; t1xy < t1->x->nY+1 ; t1xy++) {
+            t1->x->coeff[t1xx][t1xy] = PS_GEN_RAN_FLOAT;
+            //printf("%f\n", t1->x->coeff[t1xx][t1xy]);
+        }
+    }
+
+    for (psS32 t1yx = 0 ; t1yx < t1->y->nX+1 ; t1yx++) {
+        for (psS32 t1yy = 0 ; t1yy < t1->y->nY+1 ; t1yy++) {
+            t1->y->coeff[t1yx][t1yy] = PS_GEN_RAN_FLOAT;
+            //printf("%f\n", t1->y->coeff[t1yx][t1yy]);
+        }
+    }
+    for (psS32 t2xx = 0 ; t2xx < t2->x->nX+1 ; t2xx++) {
+        for (psS32 t2xy = 0 ; t2xy < t2->x->nY+1 ; t2xy++) {
+            t2->x->coeff[t2xx][t2xy] = PS_GEN_RAN_FLOAT;
+            //printf("%f\n", t2->x->coeff[t2xx][t2xy]);
+        }
+    }
+    for (psS32 t2yx = 0 ; t2yx < t2->y->nX+1 ; t2yx++) {
+        for (psS32 t2yy = 0 ; t2yy < t2->y->nY+1 ; t2yy++) {
+            t2->y->coeff[t2yx][t2yy] = PS_GEN_RAN_FLOAT;
+            //printf("%f\n", t2->y->coeff[t2yx][t2yy]);
+        }
+    }
+
+    return(0);
+}
+
+/******************************************************************************
+test04(): We test psPlaneTransformCombine() with a variety of input
+transforms, as well as input coordinates, as well as erroneous input
+parameters.
+ *****************************************************************************/
+psS32 test04( void )
+{
+    bool testStatus = true;
+
+    //HEY
+    // Create a variety of input transforms, then test them.
+    //
+    for (psS32 t1xx = 0 ; t1xx < TST04_T1_X_X ; t1xx++) {
+        for (psS32 t1xy = 0 ; t1xy < TST04_T1_X_Y ; t1xy++) {
+            for (psS32 t1yx = 0 ; t1yx < TST04_T1_Y_X ; t1yx++) {
+                for (psS32 t1yy = 0 ; t1yy < TST04_T1_Y_Y ; t1yy++) {
+                    for (psS32 t2xx = 0 ; t2xx < TST04_T2_X_X ; t2xx++) {
+                        for (psS32 t2xy = 0 ; t2xy < TST04_T2_X_Y ; t2xy++) {
+                            for (psS32 t2yx = 0 ; t2yx < TST04_T2_Y_X ; t2yx++) {
+                                for (psS32 t2yy = 0 ; t2yy < TST04_T2_Y_Y ; t2yy++) {
+                                    //printf("(%d %d %d %d %d %d %d %d)\n", t1xx, t1xy, t1yx, t1yy, t2xx, t2xy, t2yx, t2yy);
+                                    psPlaneTransform *trans1 = psPlaneTransformAlloc(PS_MAX(t1xx, t1yx), PS_MAX(t1xy, t1yy));
+                                    psPlaneTransform *trans2 = psPlaneTransformAlloc(PS_MAX(t2xx, t2yx), PS_MAX(t2xy, t2yy));
+                                    psPlaneTransform *trans3 = NULL;
+                                    setCoeffs(trans1, trans2);
+                                    trans3 = psPlaneTransformCombine(NULL, trans1,
+                                                                     trans2, psRegionSet(NAN,NAN,NAN,NAN), 0);
+                                    //XXX: the last two parameters are bogus.  Needs to change.  -rdd
+
+                                    if (trans3 == NULL) {
+                                        printf("TEST ERROR: psPlaneTransformCombine() returned NULL/\n");
+                                        testStatus = false;
+                                    } else {
+                                        testStatus = tstTransforms(trans1, trans2, trans3);
+                                    }
+                                    psFree(trans1);
+                                    psFree(trans2);
+                                    psFree(trans3);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+
+    //
+    // Test erroneous input parameter combinations
+    //
+    psPlaneTransform *trans1 = psPlaneTransformAlloc(2, 2);
+    psPlaneTransform *trans2 = psPlaneTransformAlloc(2, 2);
+    psPlaneTransform *trans3 = NULL;
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling psPlaneTransformCombine with NULL trans1.  Should generate error and return NULL.\n");
+    trans3 = psPlaneTransformCombine(NULL, NULL, trans2, psRegionSet(0,0,0,0), 10);
+    if (trans3 != NULL) {
+        printf("TEST ERROR: psPlaneTransformCombine() returned a non-NULL psPlaneTransform.\n");
+        testStatus = false;
+        psFree(trans3);
+    }
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling psPlaneTransformCombine with NULL trans2.  Should generate error and return NULL.\n");
+    trans3 = psPlaneTransformCombine(NULL, trans1, NULL, psRegionSet(0,0,0,0), 10);
+    if (trans3 != NULL) {
+        printf("TEST ERROR: psPlaneTransformCombine() returned a non-NULL psPlaneTransform.\n");
+        testStatus = false;
+        psFree(trans3);
+    }
+
+    psFree(trans1);
+    psFree(trans2);
+    return(!testStatus);
+}
+
+
+#define TST05_X_MIN 0.0
+#define TST05_X_MAX 10.0
+#define TST05_Y_MIN 0.0
+#define TST05_Y_MAX 10.0
+#define TST05_NUM_X 5.0
+#define TST05_NUM_Y 5.0
+#define TST05_X_POLY_ORDER 3
+#define TST05_Y_POLY_ORDER 3
+#define TST05_NUM_DATA (TST05_NUM_X * TST05_NUM_Y)
+#define TST05_IGNORE 1
+#define TST05_VERBOSE 0
+/******************************************************************************
+XXX: This is only a rudimentary test of the psPlaneTransformFit() function.
+It tests a few NULL input parameter conditions, and some simple linear
+transformations.
+ 
+// HEY
+ *****************************************************************************/
+psS32 test05( void )
+{
+    bool testStatus = true;
+    psPlaneTransform *trans = psPlaneTransformAlloc(TST05_X_POLY_ORDER, TST05_Y_POLY_ORDER);
+    psPlaneTransform *transInit = psPlaneTransformAlloc(TST05_X_POLY_ORDER, TST05_Y_POLY_ORDER);
+    psArray *src = psArrayAlloc((int) TST05_NUM_DATA);
+    psArray *dst = psArrayAlloc((int) TST05_NUM_DATA);
+    bool rc;
+
+    //
+    // We set an arbitrary non-linear transformation.
+    //
+    for (psS32 x = 0 ; x < TST05_X_POLY_ORDER+1 ; x++) {
+        for (psS32 y = 0 ; y < TST05_Y_POLY_ORDER+1 ; y++) {
+            transInit->x->coeff[x][y] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+            transInit->y->coeff[x][y] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+        }
+    }
+    if (TST05_VERBOSE) {
+        PS_POLY_PRINT_2D(transInit->x);
+        PS_POLY_PRINT_2D(transInit->y);
+    }
+
+    //
+    // We generate a grid of input data points in the x1,y1 plane, calculate the
+    // corresponding values in the transformed plane, and set these to
+    // the src and dst psVectors.
+    //
+    psS32 i = 0;
+    for (psF32 x = TST05_X_MIN ; x < TST05_X_MAX ; x+= (TST05_X_MAX-TST05_X_MIN)/TST05_NUM_X) {
+        for (psF32 y = TST05_Y_MIN ; y < TST05_Y_MAX ; y+= (TST05_Y_MAX-TST05_Y_MIN)/TST05_NUM_Y) {
+            if (i == src->n) {
+                if (src->n == src->nalloc) {
+                    src = psArrayRealloc(src, src->n+1);
+                }
+                src->n++;
+            }
+            if (i == dst->n) {
+                if (dst->n == dst->nalloc) {
+                    dst = psArrayRealloc(dst, dst->n+1);
+                }
+                dst->n++;
+            }
+            src->data[i] = (psPtr *) psPlaneAlloc();
+            ((psPlane *) src->data[i])->x = x;
+            ((psPlane *) src->data[i])->y = y;
+
+            dst->data[i] = psPlaneTransformApply(NULL, transInit, ((psPlane *) src->data[i]));
+            i++;
+        }
+    }
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling psPlaneTransformFit with NULL trans.  Should generate error and return NULL.\n");
+    rc = psPlaneTransformFit(NULL, src, dst, 100, 100.0);
+    if (rc == true) {
+        printf("TEST ERROR1: psPlaneTransformFit() returned TRUE.\n");
+        testStatus = false;
+    }
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling psPlaneTransformFit with NULL src psArray.  Should generate error and return NULL.\n");
+    rc = psPlaneTransformFit(trans, NULL, dst, 100, 100.0);
+    if (rc == true) {
+        printf("TEST ERROR2: psPlaneTransformFit() returned TRUE.\n");
+        testStatus = false;
+    }
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling psPlaneTransformFit with NULL dst psArray.  Should generate error and return NULL.\n");
+    rc = psPlaneTransformFit(trans, src, NULL, 100, 100.0);
+    if (rc == true) {
+        printf("TEST ERROR3: psPlaneTransformFit() returned TRUE.\n");
+        testStatus = false;
+    }
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling psPlaneTransformFit with acceptable data.\n");
+    rc = psPlaneTransformFit(trans, src, dst, 100, 100.0);
+    if (rc != true) {
+        printf("TEST ERROR4: psPlaneTransformFit() returned FALSE.\n");
+        testStatus = false;
+    } else {
+        if (TST05_VERBOSE) {
+            PS_POLY_PRINT_2D(trans->x);
+            PS_POLY_PRINT_2D(trans->y);
+        }
+
+        //
+        // For the initial grid of input points, we transform them to output points with
+        // the derived transformation, and verify that they are within 10%.
+        //
+
+        for (psS32 i = TST05_IGNORE ; i < src->n-TST05_IGNORE ; i++) {
+            psPlane *inData = (psPlane *) src->data[i];
+            psPlane *outData = (psPlane *) dst->data[i];
+            psPlane *outDataDeriv = psPlaneTransformApply(NULL, trans, inData);
+            if (!PS_PERCENT_COMPARE(outDataDeriv->x, outData->x, 0.20) ||
+                    !PS_PERCENT_COMPARE(outDataDeriv->y, outData->y, 0.20)) {
+                printf("TEST ERROR: the derived output coords (%d) were (%.2f, %.2f) should have been (%.2f, %.2f).\n",
+                       i, outDataDeriv->x, outDataDeriv->y, outData->x, outData->y);
+                testStatus = false;
+            } else if (TST05_VERBOSE) {
+                printf("GOOD: the derived output coords (%d) were (%.2f, %.2f) should have been (%.2f, %.2f).\n",
+                       i, outDataDeriv->x, outDataDeriv->y, outData->x, outData->y);
+            }
+            psFree(outDataDeriv);
+        }
+    }
+
+    psFree(transInit);
+    psFree(trans);
+    psFree(src);
+    psFree(dst);
+
+    return(!testStatus);
+}
+
+#define NUM_TRANSFORMS 100
+/******************************************************************************
+This is only a rudimentary test of the psPlaneTransformInvert() function.
+It tests:
+    A few NULL input parameter conditions.
+    Several random linear transformations.
+XXX: Must extensively test:
+    Non-linear transformations.
+  *****************************************************************************/
+psS32 test06( void )
+{
+    bool testStatus = true;
+    psPlaneTransform *trans = psPlaneTransformAlloc(1, 1);
+    psPlaneTransform *transInverse = NULL;
+    psRegion myRegion = psRegionSet(1.0, 5.0, 1.0, 5.0);
+
+    trans->x->coeff[0][0] = 0.0;
+    trans->x->coeff[0][1] = 1.0;
+    trans->x->coeff[1][0] = 2.0;
+    trans->x->coeff[1][1] = 3.0;
+    trans->y->coeff[0][0] = 4.0;
+    trans->y->coeff[0][1] = 5.0;
+    trans->y->coeff[1][0] = 6.0;
+    trans->y->coeff[1][1] = 7.0;
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling psPlaneTransformInvert with NULL trans.  Should generate error and return NULL.\n");
+    transInverse = psPlaneTransformInvert(NULL, NULL, myRegion, 10);
+    if (transInverse != NULL) {
+        printf("TEST ERROR: psPlaneTransformInvert() returned a non-NULL psPlaneTransform.\n");
+        testStatus = false;
+        psFree(transInverse);
+    }
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling psPlaneTransformInvert with zero nSamples.  Should generate error and return NULL.\n");
+    transInverse = psPlaneTransformInvert(NULL, trans, myRegion, 0);
+    if (transInverse != NULL) {
+        printf("TEST ERROR: psPlaneTransformInvert() returned a non-NULL psPlaneTransform.\n");
+        testStatus = false;
+        psFree(transInverse);
+    }
+
+    printf("Calling psPlaneTransformInvert with acceptable linear transformations.\n");
+    for (psS32 n = 0 ; n < NUM_TRANSFORMS ; n++) {
+        if (n == 0) {
+            // I ensure that we test the identity transformation since this was
+            // giving us probs before.
+            trans->x->coeff[0][0] = 0.0;
+            trans->x->coeff[0][1] = 0.0;
+            trans->x->coeff[1][0] = 1.0;
+            trans->x->coeff[1][1] = 0.0;
+            trans->y->coeff[0][0] = 0.0;
+            trans->y->coeff[0][1] = 1.0;
+            trans->y->coeff[1][0] = 0.0;
+            trans->y->coeff[1][1] = 0.0;
+        } else {
+            // We create a random linear transformation and hope it is invertible.
+            trans->x->coeff[0][0] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+            trans->x->coeff[0][1] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+            trans->x->coeff[1][0] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+            trans->x->coeff[1][1] = 0.0;
+            trans->y->coeff[0][0] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+            trans->y->coeff[0][1] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+            trans->y->coeff[1][0] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+            trans->y->coeff[1][1] = 0.0;
+        }
+
+        transInverse = psPlaneTransformInvert(NULL, trans, myRegion, 10);
+        if (transInverse == NULL) {
+            printf("TEST ERROR: psPlaneTransformInvert() returned a NULL psPlaneTransform.\n");
+            testStatus = false;
+        }
+        //
+        // Transform the "in" coords to "mid" with psPlaneTransform "trans", then
+        // transform "mid" to "out" with psPlaneTransform "transInverse".
+        //
+        // XXX: Loop on a few data points.
+        //
+        psPlane *in = psPlaneAlloc();
+        in->x = 2.0;
+        in->y = 3.0;
+        psPlane *mid = psPlaneTransformApply(NULL, trans, in);
+        psPlane *out = psPlaneTransformApply(NULL, transInverse, mid);
+
+        if (((fabs(in->x - out->x) > FLT_EPSILON)) ||
+                ((fabs(in->y - out->y) > FLT_EPSILON)) ||
+                isnan(out->x) ||
+                isnan(out->y)) {
+            printf("TEST ERROR: in coords were (%f, %f), out coords were (%f, %f).\n",
+                   in->x, in->y, out->x, out->y);
+            testStatus = false;
+        }
+
+        psFree(in);
+        psFree(mid);
+        psFree(out);
+        psFree(transInverse);
+    }
+
+    psFree(trans);
+
+    fflush(stdout);
+
+    return(!testStatus);
+}
+
+psS32 test07( void )
+{
+    psPlane *coord = psPlaneAlloc();
+    psPlane *deriv = NULL;
+    psPlaneTransform *trans = NULL;
+
+    //Set fxn values for evaluation
+    coord->x = 3.0;
+    coord->y = 1.0;
+
+    //Return NULL for NULL input plane transform
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    deriv = psPlaneTransformDeriv(NULL, trans, coord);
+    if (deriv != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psPlaneTransformDeriv failed to return NULL for NULL plane transform input.\n");
+        return 1;
+    }
+
+    trans = psPlaneTransformAlloc(1, 3);
+
+    //Set Polynomials.  f(x) = x, f(y) = 0.5*y^2  -->  f'(x) = 1, f'(y) = y
+    //So for 1,1  -> f'(1) = 1, f'(1) = 1
+    trans->x->coeff[0][0] = 0.0;
+    trans->x->coeff[1][0] = 1.0;
+    trans->y->coeff[0][0] = 0.0;
+    trans->y->coeff[0][1] = 0.0;
+    trans->y->coeff[0][2] = 0.5;
+
+    //Return NULL for NULL input plane
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    deriv = psPlaneTransformDeriv(NULL, trans, NULL);
+    if (deriv != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psPlaneTransformDeriv failed to return NULL for NULL plane input.\n");
+        return 2;
+    }
+
+    //Return correct values.  Should have x=1.0, y=1.0.
+    deriv = psPlaneTransformDeriv(NULL, trans, coord);
+    if (deriv->x != 1.0 || deriv->y != 1.0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psPlaneTransformDeriv failed to return the correct values.\n");
+        printf("\n f' values are = %lf, %lf \n", deriv->x, deriv->y);
+        return 3;
+    }
+
+    psFree(trans);
+    psFree(deriv);
+    psFree(coord);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psEarthOrientation.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psEarthOrientation.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psEarthOrientation.c	(revision 22158)
@@ -0,0 +1,1205 @@
+/** @file  tst_psEarthOrientation.c
+*
+*  @brief The code will perform earth orientation calculations and sphere rotations.
+*
+*  @author d-Rob, MHPCC
+*
+*  @version $Revision: 1.35 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2006-05-26 01:23:41 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#include "psTest.h"
+#include "pslib_strict.h"
+
+
+static psS32 testAberration(void);
+static psS32 testGravityDeflect(void);
+static psS32 testEOCPrecession(void);
+static psS32 testEOCPrecessionCorr(void);
+static psS32 testEOCPolar(void);
+static psS32 testEOCPolarTide(void);
+static psS32 testEOCNutation(void);
+static psS32 testSphereRot_TEOtoCEO(void);
+static psS32 testSphereRot_CEOtoGCRS(void);
+static psS32 testSphereRot_ITRStoTEO(void);
+static psS32 testSphereRotPrecess(void);
+
+testDescription tests[] = {
+                              {testAberration, 666, "psAberration()", 0, false},
+                              {testGravityDeflect, 667, "psGravityDeflect()", 0, false},
+                              {testEOCPrecession, 669, "psEOCPrecession()", 0, false},
+                              {testEOCPrecessionCorr, 670, "psEOCPrecessionCorr()", 0, false},
+                              {testEOCPolar, 671, "psEOCPolar()", 0, false},
+                              {testEOCPolarTide, 672, "psEOCPolarTide()", 0, false},
+                              {testEOCNutation, 673, "psEOCNutation()", 0, false},
+                              {testSphereRot_TEOtoCEO, 674, "psSphereRot_TEOtoCEO()", 0, false},
+                              {testSphereRot_CEOtoGCRS, 675, "psSphereRot_CEOtoGCRS()", 0, false},
+                              {testSphereRot_ITRStoTEO, 676, "psSphereRRot_ITRStoTEO()", 0, false},
+                              {testSphereRotPrecess, 677, "psSphereRotPrecess()", 0, false},
+                              {NULL}
+                          };
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetLevel( PS_LOG_INFO );
+
+    // Initialize library internal structures
+    psLibInit("pslib.config");
+
+    if( !runTestSuite(stderr,"psEarthOrientation",tests,argc,argv)) {
+        return 1;
+    }
+
+    // Cleanup library
+    psLibFinalize();
+
+    return 0;
+
+    //    return ( ! runTestSuite( stderr, "psEarthOrientation", tests, argc, argv ) );
+}
+
+#define timesec 1049160600
+#define objR DEG_TO_RAD(122.9153182445501)
+#define objD DEG_TO_RAD(48.562968978679194)
+#define VERBOSE 0
+static psSphere *obj = NULL;
+static void objSetup(void);
+static double greatCircle(psSphere *in1, psSphere *in2);
+
+static void objSetup(void)
+{
+    if (obj == NULL) {
+        //        obj = psSphereAlloc();
+        //        obj->r = objR;
+        //        obj->d = objD;
+        psCube *tempCube = psCubeAlloc();
+        tempCube->x = -0.3598480726985338;
+        tempCube->y = 0.5555012823608123;
+        tempCube->z = 0.7496183628158023;
+        obj = psCubeToSphere(tempCube);
+        psFree(tempCube);
+    }
+}
+
+//returns the great circle ANGULAR distance between 2 positions (psSphere's)
+static double greatCircle(psSphere *in1, psSphere *in2)
+{
+    double r1, r2, d1, d2;
+    d1 = in1->r;
+    d2 = in2->r;
+    r1 = in1->d;
+    r2 = in2->d;
+    double out = 0.0;
+    double c1, c2, cd, s1, s2, sum, ac;
+    c1 = cos(r1);
+    c2 = cos(r2);
+    cd = cos(d1-d2);
+    s1 = sin(r1);
+    s2 = sin(r2);
+    sum = c1*c2*cd + s1*s2;
+    if (sum > 1.0)
+        sum = 1.0 - (sum - 1.0);
+
+    ac = acos(sum);
+    out = ac;
+    //    printf("\n  c1=%lf, c2=%lf, cd=%lf, s1=%lf, s2=%lf, sum=%.19g, ac=%g\n", c1,c2,cd,s1,s2,sum,ac);
+    //    out = acos(cos(r1)*cos(r2)*cos(d1-d2) + sin(r1)*sin(r2));
+    //    if (out != 0.0) printf("\n   in greatCircle, out = %lf\n", out);
+    return out;
+}
+
+psS32 testAberration(void)
+{
+    psSphere *apparent = NULL;
+    psSphere *empty = NULL;
+    psCube *actualCube = psCubeAlloc();
+    //values from After gravity deflection//
+    actualCube->x = -0.35961949760293604;
+    actualCube->y = 0.5555613950298085;
+    actualCube->z = 0.7496835020836093;
+    psSphere *actual = psCubeToSphere(actualCube);
+    psCube *cubeDir = psCubeAlloc();
+    cubeDir->x = 5148.713262821658;
+    cubeDir->y = -26945.04752348012;
+    cubeDir->z = -11682.787302030947;
+    cubeDir->x += -357.6031690489248;
+    cubeDir->y += 248.46429758174693;
+    cubeDir->z += 0.09694774143797581;
+    psSphere *direction = psCubeToSphere(cubeDir);
+    double speed = sqrt(cubeDir->x*cubeDir->x + cubeDir->y*cubeDir->y + cubeDir->z*cubeDir->z);
+    double c = 299792458.0; // Speed of light in vacuum (src:NIST)   /* m/s */
+    speed /= c;
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    empty = psAberration(empty, apparent, direction, speed);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psAberration failed to return NULL for NULL actual input.\n");
+        return 1;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    empty = psAberration(empty, actual, apparent, speed);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psAberration failed to return NULL for NULL direction input.\n");
+        return 2;
+    }
+
+    apparent = psAberration(apparent, actual, direction, speed);
+    psCube *outCube = psSphereToCube(apparent);
+    if (VERBOSE) {
+        printf("\n -- resultCube = x,y,z =     %.13g,      %.13g,    %.13g  -- \n",
+               outCube->x, outCube->y, outCube->z);
+    }
+    //expected cube values
+    double x, y, z;
+    x = -0.35963388069046304;
+    y = 0.5555192509816625;
+    z = 0.7497078321908413;
+
+    if (VERBOSE) {
+        printf(" -- expectedCube = x,y,z =   %.13g,     %.13g,    %.13g  -- \n", x, y, z);
+        printf("Cube Difference  =  x,y,z  = %.13g, %.13g, %.13g \n\n",
+               (x - outCube->x), (y - outCube->y), (z - outCube->z) );
+    }
+    psFree(actual);
+    actualCube->x = x;
+    actualCube->y = y;
+    actualCube->z = z;
+    actual = psCubeToSphere(actualCube);
+    double xxx = greatCircle(actual, apparent);
+    if (VERBOSE) {
+        printf("   The great circle angular distance between expected & result = %.13g\n",
+               xxx);
+    }
+    if ( fabs(x - outCube->x) > FLT_EPSILON || fabs(y - outCube->y) > FLT_EPSILON ||
+            fabs(z - outCube->z) > FLT_EPSILON ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psAberration returned incorrect values.\n");
+        //        printf("\nMagnitude of expected change = x,y,z = %.13g, %.13g, %.13g \n",
+        //               (actualCube->x - x), (actualCube->y - y), (actualCube->z - z) );
+        //        printf("Magnitude of actual change = x,y,z = %.13g, %.13g, %.13g \n",
+        //               (actualCube->x - outCube->x), (actualCube->y - outCube->y),
+        //               (actualCube->z - outCube->z) );
+        psFree(actual);
+        actualCube->x = x;
+        actualCube->y = y;
+        actualCube->z = z;
+        actual = psCubeToSphere(actualCube);
+        x = greatCircle(actual, apparent);
+        if (VERBOSE) {
+            printf("   The great circle angular distance between expected & result = %.13g\n",
+                   x);
+        }
+        return 3;
+    }
+
+    psFree(outCube);
+    psFree(actualCube);
+    psFree(cubeDir);
+    psFree(apparent);
+    psFree(actual);
+    psFree(direction);
+
+    return 0;
+}
+
+psS32 testGravityDeflect(void)
+{
+    psSphere *apparent = NULL;
+    psSphere *empty = NULL;
+    psCube *actualCube = psCubeAlloc();
+    actualCube->x = -0.3596195125758298;
+    actualCube->y = 0.5555613903455866;
+    actualCube->z = 0.7496834983724809;
+    psSphere *actual = psCubeToSphere(actualCube);
+    psCube *sunCube = psCubeAlloc();
+    sunCube->x = 1.467797790127511e11;
+    sunCube->y = 2.5880956908748722e10;
+    sunCube->z = 1.1220046291457653e10;
+    double sunLength = sqrt(sunCube->x*sunCube->x + sunCube->y*sunCube->y + sunCube->z*sunCube->z);
+    sunCube->x /= sunLength;
+    sunCube->y /= sunLength;
+    sunCube->z /= sunLength;
+    if (VERBOSE) {
+        printf("sunCube = x,y,z = %.13g, %.13g, %.13g\n",
+               sunCube->x, sunCube->y, sunCube->z);
+    }
+    psSphere *sun = psCubeToSphere(sunCube);
+    if (VERBOSE) {
+        printf("sunSphere  = r, d = %.13g, %.13g\n", sun->r, sun->d);
+    }
+    psCube *outCube = psCubeAlloc();
+
+    empty = psGravityDeflection(apparent, empty, sun);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "psGravityDeflection Failed to return NULL for NULL actual input sphere.\n");
+        return 1;
+    }
+    empty = psGravityDeflection(apparent, actual, empty);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "psGravityDeflection Failed to return NULL for NULL sun input sphere.\n");
+        return 2;
+    }
+
+    apparent = psGravityDeflection(NULL, actual, sun);
+    //    apparent->r *= -1.0;
+    //    apparent->d *= -1.0;
+    psSphere *result2;
+    //    psSphere *result2 = psSphereSetOffset(actual, apparent, PS_SPHERICAL, PS_RADIAN);
+    //    psSphere *result = psSphereSetOffset(actual, apparent, PS_SPHERICAL, PS_RADIAN);
+    //    psSphere *result = psSphereGetOffset(apparent, actual, PS_SPHERICAL, PS_RADIAN);
+    if (VERBOSE) {
+        printf(" -- actualCube = x,y,z = %.13g, %.13g, %.13g  -- \n",
+               actualCube->x, actualCube->y, actualCube->z);
+    }
+    //    psCube *outCube = psSphereToCube(result);
+    //    printf(" -- resultCube = x,y,z = %.13g, %.13g, %.13g  -- \n",
+    //           outCube->x, outCube->y, outCube->z);
+    psCube *outCube2 = psSphereToCube(apparent);
+    if (VERBOSE) {
+        printf(" -- resultCube2= x,y,z = %.13g, %.13g, %.13g  -- \n",
+               outCube2->x, outCube2->y, outCube2->z);
+    }
+    double x, y, z;
+    x = -0.35961949760293604;
+    y = 0.5555613950298085;
+    z = 0.7496835020836093;
+
+    if (VERBOSE) {
+        printf(" -- expectCube = x,y,z = %.13g, %.13g, %.13g  -- \n\n", x, y, z);
+
+        //    if ( fabs(x - outCube->x) > DBL_EPSILON || fabs(y - outCube->y) > DBL_EPSILON ||
+        //            fabs(z - outCube->z) > DBL_EPSILON ) {
+        //        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+        //                "psGravityDeflection returned incorrect values.\n");
+        printf("expect-actual=  x,y,z  = %.13g, %.13g, %.13g \n",
+               (x - actualCube->x), (y - actualCube->y), (z - actualCube->z) );
+        printf("expect-result=  x,y,z  = %.13g, %.13g, %.13g \n",
+               (x - outCube2->x), (y - outCube2->y), (z - outCube2->z) );
+        printf("result-actual=  x,y,z  = %.13g, %.13g, %.13g \n",
+               (outCube2->x - actualCube->x), (outCube2->y - actualCube->y),
+               (outCube2->z - actualCube->z) );
+    }
+    //        return 1;
+    //    }
+    //    psFree(result2);
+    outCube2->x = x;
+    outCube2->y = y;
+    outCube2->z = z;
+    result2 = psCubeToSphere(outCube2);
+    //    psFree(result);
+    psSphere *result = psSphereGetOffset(actual, result2, PS_SPHERICAL, PS_RADIAN);
+    psFree(result2);
+    result2 = psSphereGetOffset(actual, apparent, PS_SPHERICAL, PS_RADIAN);
+    if (VERBOSE) {
+        printf("The apparent output sphere = r,d = %.13g, %.13g\n", result2->r, result2->d);
+        printf("The expected output sphere = r,d = %.13g, %.13g\n\n", result->r, result->d);
+    }
+    psFree(result2);
+
+    psFree(outCube);
+    psFree(outCube2);
+    psFree(sunCube);
+    psFree(actualCube);
+    psFree(result);
+    psFree(actual);
+    psFree(apparent);
+    psFree(sun);
+
+    return 0;
+}
+
+psS32 testEOCPrecession(void)
+{
+    psTime *empty = NULL;
+    psTime *time = psTimeAlloc(PS_TIME_UTC);
+    time->sec = timesec;
+    time->nsec = 0;
+    time->leapsecond = false;
+
+    //Tests for Precession Model //
+    psEarthPole *pmodel = NULL;
+    //Return NULL for NULL time input
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    pmodel = psEOC_PrecessionModel(empty);
+    if (pmodel != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psEOC_PrecessionModel failed to return NULL for NULL time input.\n");
+        return 1;
+    }
+    //Return NULL for UT1 time input
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    psTime *UT1time = psTimeAlloc(PS_TIME_UT1);
+    pmodel = psEOC_PrecessionModel(UT1time);
+    if (pmodel != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psEOC_PrecessionModel failed to return NULL for UT1 input time.\n");
+        return 2;
+    }
+    psFree(UT1time);
+    //Check return values from valid precession input
+    pmodel = psEOC_PrecessionModel(time);
+    if ( pmodel == NULL ) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psEOC_PrecessionModel returned NULL for valid input.\n");
+        return 3;
+    } else {
+        double x, y, s;
+        x = 2.857175590089105e-4;
+        y = 2.3968739377734732e-5;
+        s = -1.3970066457904322e-8;
+        if ( fabs(pmodel->x - x) > FLT_EPSILON || fabs(pmodel->y - y) > FLT_EPSILON
+                || fabs(pmodel->s - s) > FLT_EPSILON) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                    "   psEOC_PrecessionModel return incorrect values.\n");
+            return 4;
+        }
+        if (VERBOSE) {
+            printf("\n  PrecessionModel output = x,y,s = %.13g,  %.13g,  %.13g\n",
+                   pmodel->x, pmodel->y, pmodel->s);
+            printf("  Expected output        = x,y,s = %.13g, %.13g,  %.13g\n", x, y, s);
+            printf("  A difference of:                 %.13g, %.13g, %.13g\n",
+                   (pmodel->x - x), (pmodel->y - y), (pmodel->s - s) );
+        }
+    }
+    psFree(pmodel);
+
+    psFree(time);
+    if (!p_psEOCFinalize() ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false, "EOC failed finalization!\n");
+        return 12;
+    }
+
+    return 0;
+}
+
+psS32 testEOCPrecessionCorr(void)
+{
+    psTime *empty = NULL;
+    psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+    time2->sec = timesec;
+    time2->nsec = 0;
+    time2->leapsecond = false;
+    //    time2 = psTimeConvert(time2, PS_TIME_TAI);
+
+    //Tests for Precession Correction function//
+    //Return NULL for NULL time input
+    psEarthPole *pcorr = NULL;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    pcorr = psEOC_PrecessionCorr(empty, PS_IERS_A);
+    if (pcorr != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psEOC_PrecessionCorr failed to return NULL for NULL time input.\n");
+        return 5;
+    }
+
+    //Return NULL for Invalid IERS table
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    pcorr = psEOC_PrecessionCorr(time2, 3);
+    if (pcorr != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psEOC_PrecessionCorr failed to return NULL for incorrect IERS table.\n");
+        return 6;
+    }
+    psFree(pcorr);
+
+    //Check values from IERS table A
+    pcorr = psEOC_PrecessionCorr(time2, PS_IERS_A);
+    if ( pcorr == NULL ) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psEOC_PrecessionCorr returned NULL for valid inputs.\n");
+        return 7;
+    } else {
+        if (VERBOSE) {
+            printf("\nPrecessionCorr output (IERSA) = x,y,s = %.13g,  %.13g, %.13g\n",
+                   pcorr->x, pcorr->y, pcorr->s);
+        }
+    }
+    psFree(pcorr);
+
+    //Check values from IERS table B
+    pcorr = psEOC_PrecessionCorr(time2, PS_IERS_B);
+    if ( pcorr == NULL ) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psEOC_PrecessionCorr returned NULL for valid inputs.\n");
+        return 9;
+    } else {
+        double xx, yy, ss;
+        xx = 0.06295703125;
+        yy = -0.0287618408203125;
+        ss = 0.0;
+        xx = SEC_TO_RAD(xx) * 1e-3;
+        yy = SEC_TO_RAD(yy) * 1e-3;
+        //        if ( fabs(pcorr->x - xx) > DBL_EPSILON || fabs(pcorr->y - yy) > DBL_EPSILON
+        //                || fabs(pcorr->s - ss) > DBL_EPSILON) {
+        //            psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+        //                    "   psEOC_PrecessionCorr return incorrect values.\n");
+        if (VERBOSE) {
+            printf("PrecessionCorr output (IERSB) = x,y,s = %.13g, %.13g, %.13g\n",
+                   pcorr->x, pcorr->y, pcorr->s);
+            printf("Expected output               = x,y,s = %.13g, %.13g, %.13g\n", xx, yy, ss);
+            printf("          A difference of:              %.13g,  %.13g, %.13g\n\n",
+                   (pcorr->x - xx), (pcorr->y - yy), (pcorr->s - ss) );
+        }
+        //            return 10;
+        //        }
+    }
+    //precess is the *actual* output from PrecessionModel + PrecessionCorr
+    psEarthPole *precess = psEOC_PrecessionModel(time2);
+    precess->x += pcorr->x;
+    precess->y += pcorr->y;
+    double xCorr, yCorr;
+    xCorr = 3.05224300720406e-10;
+    yCorr = -1.39441339235822e-10;
+    //pcorr is the *expected* output from PrecessionModel//
+    pcorr->x = 2.857175590089105e-4;
+    pcorr->y = 2.3968739377734732e-5;
+    pcorr->s = -1.3970066457904322e-8;
+    pcorr->x += xCorr;
+    pcorr->y += yCorr;
+    psSphereRot *precessNutInv = psSphereRot_CEOtoGCRS(precess);
+    psSphereRot *precessNut = psSphereRotConjugate(NULL, precessNutInv);
+    double q0, q1, q2;
+    q0 = -1.1984522406756289e-5;
+    q1 = 1.4285893358610674e-4;
+    q2 = 1.2191193518914336e-10;
+    psSphereRot *pni = psSphereRot_CEOtoGCRS(pcorr);
+    if (fabs(pni->q0-q0) > FLT_EPSILON || fabs(pni->q1-q1) > FLT_EPSILON ||
+            fabs(pni->q2-q2) > FLT_EPSILON ) {
+        printf("\n Error at CEOtoGCRS, output psSphereRot doesn't match expected.\n");
+    }
+    //    printf("  Output from CEOtoGCRS only  = %.13g,%.13g,%.13g,%.13g\n",
+    //           pni->q0, pni->q1, pni->q2, pni->q3);
+    if (VERBOSE) {
+        printf("  Expected sphere rotation    = %.13g, %.13g, %.13g\n", q0,q1,q2);
+        printf("  Result sphere rotation      = %.13g, %.13g, %.13g\n",
+               precessNutInv->q0, precessNutInv->q1, precessNutInv->q2);
+        printf("     Difference         =        %.13g, %.13g, %.13g\n\n",
+               precessNutInv->q0-q0, precessNutInv->q1-q1, precessNutInv->q2-q2);
+    }
+    psCube *objC = psCubeAlloc();
+    //    objC->x = -3.5963388069046304;
+    //    objC->y = 0.5555192509816625;
+    //    objC->z = 0.7497078321908413;
+    //    objSetup();
+
+    //This is the sphere rotation for the *expected* precession output//
+    psSphereRot *pn = psSphereRotConjugate(NULL, pni);
+
+    //    psSphere *sphere = psSphereAlloc();
+    //    *sphere = *obj;
+    //    psFree(obj);
+
+    //create a psSphere for (from) the start position given in eoc_testing//
+    objC->x = -0.35963388069046304;
+    objC->y = 0.5555192509816625;
+    objC->z = 0.7497078321908413;
+    psSphere *sphere = psCubeToSphere(objC);
+
+    psSphere *expect = psSphereRotApply(NULL, pn, sphere);
+    //expected results below - stored in:  sphere  //
+    double x,y,z;
+    x = -0.3598480726985338;
+    y = 0.5555012823608123;
+    z = 0.7496183628158023;
+    if (VERBOSE) {
+        printf("\n<<Expected out       = x,y,z = %.13g, %.13g, %.13g\n", x, y, z);
+    }
+    //    psFree(objC);
+    //    objC = psSphereToCube(expect);
+    //printf("<<Expected out (CEO)  = x,y,z = %.13g, %.13g, %.13g\n", objC->x, objC->y, objC->z);
+    //printf("     Difference     =           %.13g, %.13g, %.13g\n", objC->x-x, objC->y-y, objC->z-z);
+    //    x = objC->x;
+    //    y = objC->y;
+    //    z = objC->z;
+    psSphere *result = psSphereRotApply(NULL, precessNut, sphere);
+    psFree(objC);
+    objC = psSphereToCube(result);
+    double xx = greatCircle(result, expect);
+    if (VERBOSE) {
+        printf("<<Resulting out      = x,y,z = %.13g, %.13g, %.13g\n", objC->x, objC->y, objC->z);
+        printf("     Difference         =      %.13g, %.13g, %.13g\n\n",
+               objC->x-x, objC->y-y, objC->z-z);
+        printf("GREAT CIRCLE DIFFERENCE = %.13g \n", xx);
+    }
+
+    psFree(precess);
+    psFree(precessNut);
+    psFree(precessNutInv);
+    psFree(expect);
+    psFree(objC);
+
+    psFree(sphere);
+    psFree(result);
+    psFree(pn);
+    psFree(pni);
+    psFree(pcorr);
+    psFree(time2);
+    if (!p_psEOCFinalize() ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false, "EOC failed finalization!\n");
+        return 12;
+    }
+
+    return 0;
+}
+
+psS32 testEOCPolar(void)
+{
+    psTime *in = psTimeAlloc(PS_TIME_UTC);
+    in->sec = timesec;
+    in->nsec = 0;
+    in->leapsecond = false;
+    psTime *empty = NULL;
+    psEarthPole *polarMotion = NULL;
+
+    //Return NULL for NULL input time
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    polarMotion = psEOC_GetPolarMotion(empty, PS_IERS_B);
+    if (polarMotion != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psEOC_GetPolarMotion failed to return NULL for NULL input time.\n");
+        return 1;
+    }
+    //Return NULL for incorrect Bulletin.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    polarMotion = psEOC_GetPolarMotion(empty, 3);
+    if (polarMotion != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psEOC_GetPolarMotion failed to return NULL for NULL input time.\n");
+        return 1;
+    }
+
+    //Test for IERS bulletin A.
+    double x, y, s;
+    x = -6.454389659777e-07;
+    y = 2.112606414597e-06;
+    s = 0.0;
+    polarMotion = psEOC_GetPolarMotion(in, PS_IERS_A);
+    if (polarMotion == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psEOC_GetPolarMotion returned NULL for valid input time.\n");
+        return 4;
+    }
+    //    if ( fabs(polarMotion->x - x) > DBL_EPSILON || fabs(polarMotion->y - y) > DBL_EPSILON
+    //            || fabs(polarMotion->s - s) > DBL_EPSILON) {
+    //        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+    //                "psEOC_GetPolarMotion returned incorrect values.\n");
+    if (VERBOSE) {
+        printf("  <>PolarMotion output (IERSA)   = x,y,s = %.13g, %.13g, %.13g\n",
+               polarMotion->x, polarMotion->y, polarMotion->s);
+    }
+    //        printf("  <>PolarMotion expected (IERSA) = x,y,s = %.13g, %.13g, %.13g\n",
+    //               x, y, s);
+    //        return 5;
+    //    }
+    psFree(polarMotion);
+
+    //Return valid values for correct input time.  Test IERS Bulletin B.
+    polarMotion = psEOC_GetPolarMotion(in, PS_IERS_B);
+    //    x = -6.45381397904e-07;
+    //    y = 2.112819726698e-06;
+    //    s = 0.0;
+    if (polarMotion == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psEOC_GetPolarMotion returned NULL for valid input time.\n");
+        return 2;
+    }
+    //    if ( fabs(polarMotion->x - x) > DBL_EPSILON || fabs(polarMotion->y - y) > DBL_EPSILON
+    //            || fabs(polarMotion->s - s) > DBL_EPSILON) {
+    //        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+    //                "psEOC_GetPolarMotion returned incorrect values.\n");
+    if (VERBOSE) {
+        printf("  <>PolarMotion output (IERSB)   = x,y,s = %.13g,  %.13g, %.13g\n",
+               polarMotion->x, polarMotion->y, polarMotion->s);
+    }
+    //        printf("  <>PolarMotion expected (IERSB) = x,y,s = %.13g, %.13g, %.13g\n",
+    //               x, y, s);
+    //        return 3;
+    //    }
+    psEarthPole *nutationCorr = psEOC_NutationCorr(in);
+    if (nutationCorr == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false, "Nutation Correction returned NULL.\n");
+        return 6;
+    }
+    polarMotion->x += nutationCorr->x;
+    polarMotion->y += nutationCorr->y;
+    polarMotion->s += nutationCorr->s;
+    psEarthPole *polarTide = psEOC_PolarTideCorr(in);
+    polarMotion->x += polarTide->x;
+    polarMotion->y += polarTide->y;
+    psFree(polarTide);
+    x = -6.43607313124045e-7;
+    y = 2.11351436973568e-6;
+    s = -7.39617581324646e-12;
+    //    if ( fabs(polarMotion->x - x) > DBL_EPSILON || fabs(polarMotion->y - y) > DBL_EPSILON
+    //            || fabs(polarMotion->s - s) > DBL_EPSILON) {
+    //        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+    //                "   psEOC_GetPolarMotion returned incorrect values.\n");
+    if (VERBOSE) {
+        printf("\n  PolarMotion + NutationCorr out = x,y,s = %.13g, %.13g, %.13g\n",
+               polarMotion->x, polarMotion->y, polarMotion->s);
+        printf("  Expected output                = x,y,s = %.13g,  %.13g, %.13g\n", x, y, s);
+        printf("                     Difference  = x,y,s = %.13g, %.13g,  %.13g\n",
+               polarMotion->x - x, polarMotion->y - y, polarMotion->s - s);
+    }
+    //    }
+
+    if (!p_psEOCFinalize() ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false, "EOC failed finalization!\n");
+        return 12;
+    }
+
+    psFree(nutationCorr);
+    psFree(in);
+    psFree(polarMotion);
+    return 0;
+}
+
+psS32 testEOCPolarTide(void)
+{
+    psTime *in = psTimeAlloc(PS_TIME_UTC);
+    in->sec = timesec;
+    in->nsec = 0;
+    in->leapsecond = false;
+    psTime *empty = NULL;
+    psEarthPole *eop = NULL;
+
+    //Return NULL for NULL input time
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    eop = psEOC_PolarTideCorr(empty);
+    if (eop != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psEOC_PolarTideCorr failed to return NULL for NULL input time.\n");
+        return 1;
+    }
+
+    eop = psEOC_PolarTideCorr(in);
+    if (eop == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psEOC_PolarTideCorr returned NULL for valid input time.\n");
+        return 2;
+    } else {
+        if (VERBOSE) {
+            printf("\nPolarTideCorr output = x,y,s = %.13g, %.13g, %.13g\n",
+                   eop->x, eop->y, eop->s);
+        }
+    }
+
+    psFree(in);
+    psFree(eop);
+
+    return 0;
+}
+
+psS32 testEOCNutation(void)
+{
+    psTime *in = psTimeAlloc(PS_TIME_UTC);
+    in->sec = timesec;
+    in->nsec = 0;
+    in->leapsecond = false;
+    psTime *empty = NULL;
+    psEarthPole *nute = NULL;
+
+    //Return NULL for NULL input time.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    nute = psEOC_NutationCorr(empty);
+    if (nute != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psEOC_NutationCorr failed to return NULL for NULL input time.\n");
+        return 1;
+    }
+    //Return NULL for UT1 time input
+    /*    psTime *UT1time = psTimeAlloc(PS_TIME_UT1);
+        nute = psEOC_NutationCorr(UT1time);
+        if (nute != NULL) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                    "psEOC_NutationCorr failed to return NULL for UT1 input time.\n");
+            return 2;
+        }
+        psFree(UT1time);
+    */
+    //Check return values from valid nutation time input
+    nute = psEOC_NutationCorr(in);
+    if ( nute == NULL ) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psEOC_NutationCorr returned NULL for valid input.\n");
+        return 3;
+    } else {
+        if (VERBOSE) {
+            printf("Nutation Correction output = x,y,s = %.13g, %.13g, %.13g\n\n",
+                   nute->x, nute->y, nute->s);
+        }
+    }
+    psFree(nute);
+    psFree(in);
+
+    if (!p_psEOCFinalize() ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false, "EOC failed finalization!\n");
+        return 12;
+    }
+
+    return 0;
+}
+
+psS32 testSphereRot_TEOtoCEO(void)
+{
+    psSphereRot *rot = NULL;
+    psTime *empty = NULL;
+    psTime *time = psTimeAlloc(PS_TIME_UT1);
+    time->sec = timesec-1;
+    time->nsec = 657017200;
+    time->leapsecond = false;
+
+    //return NULL for NULL input time
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    rot = psSphereRot_TEOtoCEO(empty, NULL);
+    if (rot != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psSphereRot_TEOtoCEO failed to return NULL for NULL input time.\n");
+        return 1;
+    }
+
+    psEarthPole *polarTideCorr = psEOC_PolarTideCorr(time);
+    psSphereRot *teoceo = psSphereRot_TEOtoCEO(time, polarTideCorr);
+    //Make sure values match for other psTime type
+    empty = psTimeAlloc(PS_TIME_UTC);
+    empty->sec = timesec;
+    empty->nsec = 0;
+    empty->leapsecond = false;
+
+    rot = psSphereRot_TEOtoCEO(empty, polarTideCorr);
+    if (fabs(rot->q0-teoceo->q0) > 0.00001 || fabs(rot->q1-teoceo->q1) > 0.00001 ||
+            fabs(rot->q2-teoceo->q2) > 0.00001 || fabs(rot->q3-teoceo->q3) > 0.00001) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psSphereRot_TEOtoCEO failed to return matching values for different time types.\n");
+        if (VERBOSE) {
+            printf("\n  Output Rotation1 = q0,q1,q2,q3 = %.13g, %.13g, %.13g, %.13g\n",
+                   teoceo->q0, teoceo->q1, teoceo->q2, teoceo->q3 );
+            printf("\n  Output Rotation2 = q0,q1,q2,q3 = %.13g, %.13g, %.13g, %.13g\n",
+                   rot->q0, rot->q1, rot->q2, rot->q3 );
+        }
+        return 2;
+    }
+    if (VERBOSE) {
+        printf("\n  Output Rotation = q0,q1,q2,q3 = %.13g, %.13g, %.13g, %.13g\n",
+               teoceo->q0, teoceo->q1, teoceo->q2, teoceo->q3 );
+    }
+
+    objSetup();
+    psSphereRot *earthRot = psSphereRotConjugate(NULL, teoceo);
+    psSphere *result = psSphereRotApply(NULL, earthRot, obj);
+    //    psSphere *result = psSphereRotApply(NULL, teoceo, obj);
+    psCube *cube = psSphereToCube(result);
+
+    double x, y, z;
+    x = 0.01698625430807123;
+    y = -0.6616523084626379;
+    z = 0.7496183628158023;
+    if ( fabs(x-cube->x) > FLT_EPSILON  || fabs(y-cube->y) > FLT_EPSILON ||
+            fabs(z-cube->z) > FLT_EPSILON) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psSphereRot_TEOtoCEO returned incorrect values.\n");
+        if (VERBOSE) {
+            printf("\nOutput cube = x,y,z = %.13g, %.13g, %.13g\n",
+                   cube->x, cube->y, cube->z);
+            printf("Expected cube = x,y,z = %.13g, %.13g, %.13g\n", x, y, z);
+            printf("A difference of:   %.13g, %.13g, %.13g\n\n",
+                   (x-cube->x), (y-cube->y), (z-cube->z));
+        }
+        return 3;
+    }
+
+    psFree(polarTideCorr);
+    psFree(rot);
+    psFree(empty);
+    psFree(result);
+    psFree(obj);
+    psFree(earthRot);
+    psFree(cube);
+    psFree(time);
+    psFree(teoceo);
+    return 0;
+}
+
+psS32 testSphereRot_CEOtoGCRS(void)
+{
+    psEarthPole *in = psEarthPoleAlloc();
+    psEarthPole *empty = NULL;
+    psSphereRot *rot = NULL;
+    in->x = 2.857175590089105e-4;
+    in->y = 2.3968739377734732e-5;
+    in->s = -1.3970066457904322e-8;
+
+    double q0,q1,q2,q3;
+    q0 = -1.1984522406756289e-5;
+    q1 = 1.4285893358610674e-4;
+    q2 = 1.2191193518914336e-10;
+    q3 = -0.9999999897238481;
+
+    //Return NULL for NULL input earthpole
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    rot = psSphereRot_CEOtoGCRS(empty);
+    if (rot != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psSphereRot_CEOtoGCRS failed to return NULL for NULL input psEarthPole.\n");
+        return 1;
+    }
+
+    rot = psSphereRot_CEOtoGCRS(in);
+    if (rot == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psSphereRot_CEOtoGCRS returned NULL for valid psEarthPole input.\n");
+        return 2;
+    }
+
+    if (VERBOSE) {
+        printf("\n  Output sphere rotation   = %.13g, %.13g, %.13g, %.13g\n",
+               rot->q0, rot->q1, rot->q2, rot->q3);
+        printf("  Expected sphere rotation = %.13g, %.13g, %.13g, %.13g\n", q0,q1,q2,q3);
+        printf("  difference:                 %.13g, %.13g, %.13g \n",
+               (rot->q0-q0), (rot->q1-q1), (rot->q2-q2) );
+    }
+    if (fabs(rot->q0-q0) > FLT_EPSILON || fabs(rot->q1-q1) > FLT_EPSILON ||
+            fabs(rot->q2-q2) > FLT_EPSILON || fabs(rot->q3+q3) > FLT_EPSILON) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psSphereRot_CEOtoGCRS failed to return expected values.\n");
+        return 3;
+    }
+    psCube *tempCube = psCubeAlloc();
+    tempCube->x = -0.35963388069046304;
+    tempCube->y = 0.5555192509816625;
+    tempCube->z = 0.7497078321908413;
+    obj = psCubeToSphere(tempCube);
+    psFree(tempCube);
+    psSphereRot *precessionNutation = psSphereRotConjugate(NULL, rot);
+    psSphere *result = psSphereRotApply(NULL, precessionNutation, obj);
+    psCube *cube = psSphereToCube(result);
+    double x, y, z;
+    x = -0.3598480726985338;
+    y = 0.5555012823608123;
+    z = 0.7496183628158023;
+    if (VERBOSE) {
+        printf("\n  Output cube = x,y,z = %.13g,  %.13g,    %.13g\n", cube->x, cube->y, cube->z);
+        printf("Expected cube = x,y,z = %.13g,  %.13g,   %.13g\n", x, y, z);
+        printf("  A difference of:    %.13g, %.13g, %.13g\n\n",
+               (x-cube->x), (y-cube->y), (z-cube->z));
+    }
+    psCube *expect = psCubeAlloc();
+    expect->x = x;
+    expect->y = y;
+    expect->z = z;
+    psSphere *expected = psCubeToSphere(expect);
+    double d = greatCircle(result, expected);
+    if (VERBOSE) {
+        printf("   The great circle angular distance between expected & result = %.13g\n", d);
+    }
+
+    psFree(expect);
+    psFree(expected);
+    psFree(obj);
+    psFree(precessionNutation);
+    psFree(result);
+    psFree(cube);
+    psFree(rot);
+    psFree(in);
+
+    return 0;
+}
+
+psS32 testSphereRot_ITRStoTEO(void)
+{
+    psEarthPole *in = psEarthPoleAlloc();
+    psEarthPole *empty = NULL;
+    psSphereRot *rot = NULL;
+    in->x = -0.13275353774074533;
+    in->y = 0.4359436319739848;
+    in->s = -4.2376965863576153e-10;
+    in->x = SEC_TO_RAD(in->x);
+    in->y = SEC_TO_RAD(in->y);
+    in->s = SEC_TO_RAD(in->s);
+
+    //Return NULL for NULL input earthpole
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    rot = psSphereRot_ITRStoTEO(empty);
+    if (rot != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psSphereRot_ITRStoTEO failed to return NULL for NULL input psEarthPole.\n");
+        return 1;
+    }
+
+    rot = psSphereRot_ITRStoTEO(in);
+    if (rot == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psSphereRot_ITRStoTEO return NULL for valid psEarthPole input.\n");
+        return 2;
+    }
+
+    double q0,q1,q2,q3;
+    q0 = -1.0567571848664005e-6;
+    q1 = 3.218036562931509e-7;
+    q2 = -3.3580195807204483e-12;
+    q3 = -0.9999999999993899;
+    if (fabs(rot->q0-q0) > FLT_EPSILON || fabs(rot->q1-q1) > FLT_EPSILON ||
+            fabs(rot->q2-q2) > FLT_EPSILON
+            //            || fabs(rot->q3-q3) > DBL_EPSILON
+       ) {
+        if (VERBOSE) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                    "psSphereRot_ITRStoTEO failed to return expected values.\n");
+            printf("\n  Output sphere rotation   = %.13g, %.13g, %.13g, %.13g\n",
+                   rot->q0, rot->q1, rot->q2, rot->q3);
+            printf("  Expected sphere rotation = %.13g, %.13g, %.13g, %.13g\n", q0,q1,q2,q3);
+            printf("  a difference:   %.13g, %.13g, %.13g, %.13g \n", (rot->q0-q0), (rot->q1-q1),
+                   (rot->q2-q2), (rot->q3-q3) );
+        }
+        //        printf("Error #3\n");
+        //        return 3;
+    }
+    if (VERBOSE) {
+        printf("\n  Output sphere rotation   = %.13g, %.13g, %.13g, %.13g\n",
+               rot->q0, rot->q1, rot->q2, rot->q3);
+        printf("  Expected sphere rotation = %.13g, %.13g, %.13g, %.13g\n", q0,q1,q2,q3);
+    }
+
+    psCube *temp = psCubeAlloc();
+    //    temp->x = -0.3596195125758298;
+    //    temp->y = 0.5555613903455866;
+    //    temp->z = 0.7496834983724809;
+    temp->x = 0.01698625430807123;
+    temp->y = -0.6616523084626379;
+    temp->z = 0.7496183628158023;
+
+    obj = psCubeToSphere(temp);
+    psSphere *test = NULL;
+    psFree(temp);
+    psSphereRot *newRot = psSphereRotConjugate(NULL, rot);
+    test = psSphereRotApply(NULL, newRot, obj);
+    temp = psSphereToCube(test);
+    double x, y, z;
+    x = 0.01698577185310146;
+    y = -0.6616538927902393;
+    z = 0.7496169753347885;
+    if (VERBOSE) {
+        printf("\n  Cube -test- has x,y,z =     %.13g, %.13g, %.13g \n",
+               temp->x, temp->y, temp->z);
+        printf("\n  Cube -expected- has x,y,z = %.13g,  %.13g, %.13g \n", x, y, z );
+    }
+    temp->x = x;
+    temp->y = y;
+    temp->z = z;
+    psSphere *sphere = psCubeToSphere(temp);
+    double d = greatCircle(sphere, test);
+    if (VERBOSE) {
+        printf("Great circle difference of:  %.13g \n", d);
+    }
+
+    psFree(sphere);
+    psFree(newRot);
+    psFree(obj);
+    psFree(temp);
+    psFree(test);
+    psFree(rot);
+    psFree(in);
+
+    return 0;
+}
+
+#define SPHERE_PRECESS_TP1_R            0.0               //    0.0       degrees
+#define SPHERE_PRECESS_TP1_D            0.0               //    0.0       degrees
+#define SPHERE_PRECESS_TP1_EXPECT_R     6.238453          //  357.437     degrees
+#define SPHERE_PRECESS_TP1_EXPECT_D    -0.019426          //   -1.113     degrees
+#define SPHERE_PRECESS_TP2_R            0.0               //    0.0       degrees
+#define SPHERE_PRECESS_TP2_D            1.570796          //   90.0       degrees
+#define SPHERE_PRECESS_TP2_EXPECT_R     6.260828          //  358.719     degrees
+#define SPHERE_PRECESS_TP2_EXPECT_D     1.551353          //   88.886     degrees
+#define SPHERE_PRECESS_TP3_R            3.141593          //  180.0       degrees
+#define SPHERE_PRECESS_TP3_D            0.523599          //   30.0       degrees
+#define SPHERE_PRECESS_TP3_EXPECT_R     3.096616          //  177.423     degrees
+#define SPHERE_PRECESS_TP3_EXPECT_D     0.543024          //   31.113     degrees
+#define ERROR_TOL   0.0001
+#define MJD_1900  15021.0        // Modified Julian Day 1/1/1900 00:00:00
+#define MJD_2100  88069.0        // Modified Julian Day 1/1/2100 00:00:00
+
+psS32 testSphereRotPrecess( void )
+{
+
+    psSphere*     inputCoord  = psSphereAlloc();
+    psSphere*     outputCoord = NULL;
+    //    psTime*       fromTime    = psTimeFromMJD(MJD_1900);
+    //    psTime*       toTime      = psTimeFromMJD(MJD_2100);
+    psTime*       fromTime    = psTimeFromMJD(MJD_2100);
+    psTime*       toTime      = psTimeFromMJD(MJD_1900);
+    psSphereRot *rot = NULL;
+    // Set input coordinate
+    inputCoord->r = SPHERE_PRECESS_TP1_R;
+    inputCoord->d = SPHERE_PRECESS_TP1_D;
+    inputCoord->rErr = 0.0;
+    inputCoord->dErr = 0.0;
+
+    // Calculate precess
+    rot = psSpherePrecess(fromTime, toTime, PS_PRECESS_ROUGH);
+    outputCoord = psSphereRotApply(NULL, rot, inputCoord);
+    if (outputCoord->r < -0.0001) {
+        outputCoord->r += 2.0 * M_PI;
+    }
+    //    outputCoord = psSpherePrecess(inputCoord, fromTime, toTime, PS_PRECESS_ROUGH);
+    // Verify return is not NULL
+    if(outputCoord == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Returned NULL not expected");
+        return 1;
+    }
+    // Verify return with expected values
+    if( fabs(outputCoord->r - SPHERE_PRECESS_TP1_EXPECT_R) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Precess r = %lg not equal to expected = %lg",
+                outputCoord->r,SPHERE_PRECESS_TP1_EXPECT_R);
+        return 2;
+    }
+    if( fabs(outputCoord->d - SPHERE_PRECESS_TP1_EXPECT_D) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Precess d = %lg not equal to expected = %lg",
+                outputCoord->d,SPHERE_PRECESS_TP1_EXPECT_D);
+        return 3;
+    }
+    psFree(outputCoord);
+    psFree(rot);
+
+    // Set input coordinate
+    inputCoord->r = SPHERE_PRECESS_TP2_R;
+    inputCoord->d = SPHERE_PRECESS_TP2_D;
+    inputCoord->rErr = 0.0;
+    inputCoord->dErr = 0.0;
+
+    // Calculate precess
+    rot = psSpherePrecess(fromTime, toTime, PS_PRECESS_ROUGH);
+    outputCoord = psSphereRotApply(NULL, rot, inputCoord);
+    if (outputCoord->r < -0.0001) {
+        outputCoord->r += 2.0 * M_PI;
+    }
+    //    outputCoord = psSpherePrecess(inputCoord, fromTime, toTime, PS_PRECESS_ROUGH);
+    // Verify return is not NULL
+    if(outputCoord == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Returned NULL not expected");
+        return 4;
+    }
+    // Verify return with expected values
+    if( fabs(outputCoord->r - SPHERE_PRECESS_TP2_EXPECT_R) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Precess r = %lg not equal to expected = %lg",
+                outputCoord->r,SPHERE_PRECESS_TP2_EXPECT_R);
+        return 5;
+    }
+    if( fabs(outputCoord->d - SPHERE_PRECESS_TP2_EXPECT_D) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Precess d = %lg not equal to expected = %lg",
+                outputCoord->d,SPHERE_PRECESS_TP2_EXPECT_D);
+        return 6;
+    }
+    psFree(outputCoord);
+    psFree(rot);
+
+    // Set input coordinate
+    inputCoord->r = SPHERE_PRECESS_TP3_R;
+    inputCoord->d = SPHERE_PRECESS_TP3_D;
+    inputCoord->rErr = 0.0;
+    inputCoord->dErr = 0.0;
+
+    // Calculate precess
+    rot = psSpherePrecess(fromTime, toTime, PS_PRECESS_ROUGH);
+    outputCoord = psSphereRotApply(NULL, rot, inputCoord);
+    if (outputCoord->r < -0.0001) {
+        outputCoord->r += 2.0 * M_PI;
+    }
+    //    outputCoord = psSpherePrecess(inputCoord, fromTime, toTime, PS_PRECESS_ROUGH);
+    // Verify return is not NULL
+    if(outputCoord == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Returned NULL not expected");
+        return 7;
+    }
+    // Verify return with expected values
+    if( fabs(outputCoord->r - SPHERE_PRECESS_TP3_EXPECT_R) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Precess r = %lg not equal to expected = %lg",
+                outputCoord->r,SPHERE_PRECESS_TP3_EXPECT_R);
+        return 8;
+    }
+    if( fabs(outputCoord->d - SPHERE_PRECESS_TP3_EXPECT_D) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Precess d = %lg not equal to expected = %lg",
+                outputCoord->d,SPHERE_PRECESS_TP3_EXPECT_D);
+        return 9;
+    }
+    psFree(outputCoord);
+    psFree(rot);
+
+    //Test other modes (IAU2000A, COMPLETE_[A,B])
+    // Set input coordinate
+    inputCoord->r = SPHERE_PRECESS_TP1_R;
+    inputCoord->d = SPHERE_PRECESS_TP1_D;
+    inputCoord->rErr = 0.0;
+    inputCoord->dErr = 0.0;
+    // Calculate precess
+    rot = psSpherePrecess(fromTime, toTime, PS_PRECESS_COMPLETE_A);
+    outputCoord = psSphereRotApply(NULL, rot, inputCoord);
+    if (outputCoord->r < -0.000001) {
+        outputCoord->r += 2.0 * M_PI;
+    }
+    // Verify return is not NULL
+    if(outputCoord == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Returned NULL not expected");
+        return 10;
+    }
+    psFree(outputCoord);
+    psFree(rot);
+
+    rot = psSpherePrecess(fromTime, toTime, PS_PRECESS_COMPLETE_B);
+    outputCoord = psSphereRotApply(NULL, rot, inputCoord);
+    if (outputCoord->r < -0.000001) {
+        outputCoord->r += 2.0 * M_PI;
+    }
+    // Verify return is not NULL
+    if(outputCoord == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Returned NULL not expected");
+        return 11;
+    }
+    psFree(outputCoord);
+    psFree(rot);
+
+    rot = psSpherePrecess(fromTime, toTime, PS_PRECESS_IAU2000A);
+    outputCoord = psSphereRotApply(NULL, rot, inputCoord);
+    if (outputCoord->r < -0.000001) {
+        outputCoord->r += 2.0 * M_PI;
+    }
+    // Verify return is not NULL
+    if(outputCoord == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Returned NULL not expected");
+        return 12;
+    }
+    psFree(outputCoord);
+    psFree(rot);
+
+    // Invoke precess with invalid parameter
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    rot = psSpherePrecess(fromTime, toTime, 10);
+    if(rot != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with invalid input");
+        return 14;
+    }
+    // Return NULL for NULL input times
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    rot = psSpherePrecess(NULL, NULL, PS_PRECESS_ROUGH);
+    if(rot != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with invalid input");
+        return 15;
+    }
+
+    if (!p_psEOCFinalize() ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false, "EOC failed finalization!\n");
+        return 12;
+    }
+    // Free objects
+    psFree(fromTime);
+    psFree(toTime);
+    psFree(inputCoord);
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psSphereOps.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psSphereOps.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psSphereOps.c	(revision 22158)
@@ -0,0 +1,390 @@
+/** @file  tst_psSphereOps.c
+*
+*  @brief The code will perform sphere rotations and transformations.
+*
+*  @author d-Rob, MHPCC
+*
+*  @version $Revision: 1.18 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2006-02-02 23:19:58 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#include "psTest.h"
+#include "pslib_strict.h"
+
+static psS32 testSphereRotAlloc(void);
+static psS32 testSphereRotQuat(void);
+static psS32 testSphereRotApply1(void);
+static psS32 testSphereRotApplyCelestial(void);
+static psS32 testSphereOffset(void);
+
+testDescription tests[] = {
+                              {testSphereRotAlloc, 819, "psSphereRotAlloc()", 0, false},
+                              {testSphereRotQuat, 820, "psSphereRotQuat()", 0, false},
+                              {testSphereRotApply1, 821, "psSphereRotApply()", 0, false},
+                              {testSphereRotApplyCelestial, 822, "psSphereRotApplyCel()", 0, false},
+                              {testSphereOffset, 825, "testSphereOffset()", 0, false},
+                              {NULL}
+                          };
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetLevel( PS_LOG_INFO );
+    psLogSetFormat("HLNM");
+
+    return ( ! runTestSuite( stderr, "psSphereOps", tests, argc, argv ) );
+}
+
+#define DEG_INC   30.0
+
+#define MJD_1900  15021.0        // Modified Julian Day 1/1/1900 00:00:00
+#define MJD_2000  51544.0        // Modified Julian Day 1/1/2000 00:00:00
+#define MJD_2100  88069.0        // Modified Julian Day 1/1/2100 00:00:00
+
+#define ERROR_TOL   0.0001
+
+#define ALPHA_P 4*M_PI/3
+#define DELTA_P M_PI/4
+#define PHI_P M_PI/3
+
+psS32 testSphereRotAlloc( void )
+{
+    // Allocate data structure
+    psSphereRot* myST = psSphereRotAlloc(ALPHA_P, DELTA_P, PHI_P);
+
+    // Verify null not returned
+    if(myST == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Returned NULL with valid parameters");
+        return 1;
+    }
+
+    double a0 = (ALPHA_P - PHI_P)/2.0;
+    double a1 = (ALPHA_P - PHI_P)/2.0;
+    double a2 = (ALPHA_P + PHI_P)/2.0;
+    double a3 = (ALPHA_P + PHI_P)/2.0;
+    //From Mathworld, this is another way to calculate the quaternions of a rotation
+    double q0 = sin(a0)*sin(DELTA_P/2);
+    double q1 = cos(a1)*sin(DELTA_P/2);
+    double q2 = sin(a2)*cos(DELTA_P/2);
+    double q3 = cos(a3)*cos(DELTA_P/2);
+    //Check that the quaternion components all match
+    if (DBL_EPSILON < fabs(q0 - myST->q0)) {
+        psError(PS_ERR_UNKNOWN,true,"myST->q0 is %lf, should be %lf\n", myST->q0, q0);
+        return 2;
+    }
+    if (DBL_EPSILON < fabs(q1 - myST->q1)) {
+        psError(PS_ERR_UNKNOWN,true,"myST->q1 is %f, should be %f\n", myST->q1, q1);
+        return 3;
+    }
+    if (DBL_EPSILON < fabs(q2 - myST->q2)) {
+        psError(PS_ERR_UNKNOWN,true,"myST->q2 is %f, should be %f\n", myST->q2, q2);
+        return 4;
+    }
+    if (DBL_EPSILON < fabs(q3 - myST->q3)) {
+        psError(PS_ERR_UNKNOWN,true,"myST->q0 is %f, should be %f\n", myST->q3, q3);
+        return 5;
+    }
+
+    // Free data structure
+    psFree(myST);
+
+    return 0;
+}
+
+psS32 testSphereRotQuat(void)
+{
+    double a0 = (ALPHA_P - PHI_P)/2.0;
+    double a1 = (ALPHA_P - PHI_P)/2.0;
+    double a2 = (ALPHA_P + PHI_P)/2.0;
+    double a3 = (ALPHA_P + PHI_P)/2.0;
+    //From Mathworld, this is another way to calculate the quaternions of a rotation
+    double q0 = sin(a0)*sin(DELTA_P/2);
+    double q1 = cos(a1)*sin(DELTA_P/2);
+    double q2 = sin(a2)*cos(DELTA_P/2);
+    double q3 = cos(a3)*cos(DELTA_P/2);
+
+    psSphereRot *myST = psSphereRotQuat(q0*2.0, q1*2.0, q2*2.0, q3*2.0);
+    // Verify null not returned
+    if(myST == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Returned NULL with valid parameters");
+        return 1;
+    }
+    //Check that the quaternion components all match
+    if (FLT_EPSILON < fabs(q0 - myST->q0)) {
+        psError(PS_ERR_UNKNOWN,true,"myST->q0 is %lf, should be %lf\n", myST->q0, q0);
+        return 2;
+    }
+    if (FLT_EPSILON < fabs(q1 - myST->q1)) {
+        psError(PS_ERR_UNKNOWN,true,"myST->q1 is %f, should be %f\n", myST->q1, q1);
+        return 3;
+    }
+    if (FLT_EPSILON < fabs(q2 - myST->q2)) {
+        psError(PS_ERR_UNKNOWN,true,"myST->q2 is %f, should be %f\n", myST->q2, q2);
+        return 4;
+    }
+    if (FLT_EPSILON < fabs(q3 - myST->q3)) {
+        psError(PS_ERR_UNKNOWN,true,"myST->q0 is %f, should be %f\n", myST->q3, q3);
+        return 5;
+    }
+
+    // Free data structure
+    psFree(myST);
+
+    return 0;
+}
+
+// We do a simple identity transformation on a few RA, DEC pairs.
+psS32 testSphereRotApply1( void )
+{
+    psSphere *in = psSphereAlloc();
+    psSphere *out = psSphereAlloc();
+    psSphere *temp = NULL;
+    psSphere *rc = NULL;
+    psSphere *temp2 = psSphereAlloc();
+    psSphereRot *myST = psSphereRotAlloc(ALPHA_P, DELTA_P, PHI_P);
+    psSphereRot *yourST =  psSphereRotInvert(ALPHA_P, DELTA_P, PHI_P);
+
+    for (float r=0.0;r<180.0;r+=DEG_INC) {
+        for (float d=0.0;d<90.0;d+=DEG_INC) {
+            in->r = DEG_TO_RAD(r);
+            in->d = DEG_TO_RAD(d);
+            in->rErr = 0.0;
+            in->dErr = 0.0;
+            //Here we apply the sphere rotation, then the inverse
+            temp2 = psSphereRotApply(temp2, myST, in);
+            out = psSphereRotApply(out, yourST, temp2);
+            //Check that out matches in
+            if (ERROR_TOL < fabs(out->r - in->r)) {
+                psError(PS_ERR_UNKNOWN,true,"out->r is %f, should be %f\n", out->r, in->r);
+                return 2;
+            }
+            if (ERROR_TOL < fabs(out->d - in->d)) {
+                psError(PS_ERR_UNKNOWN,true,"out->d is %f, should be %f\n", out->d, in->d);
+                return 3;
+            }
+        }
+    }
+    // Verify new sphere object is created if out parameter NULL
+    temp = psSphereRotApply(NULL, myST, in);
+    if ( temp == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Returned NULL when out parameter was null");
+        return 4;
+    }
+    psFree(temp);
+
+    // Verify NULL returned if transform structure null
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error");
+    rc = psSphereRotApply(NULL, NULL, in);
+    if (rc != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psSphereRotApply() did not return NULL.");
+        return 5;
+    }
+
+    // Verify NULL returned when input sphere is NULL
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error");
+    rc = psSphereRotApply(NULL, myST, NULL);
+    if (rc != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psSphereRotApply() did not return NULL");
+        return 6;
+    }
+
+    psFree(myST);
+    psFree(yourST);
+    psFree(temp2);
+    psFree(out);
+    psFree(in);
+
+    return 0;
+}
+
+#define ERROR_PERCENT 0.01
+
+psS32 testSphereRotApplyCelestial( void)
+{
+    //Test cases below were provided in ADD.
+    int numTestPoints = 3;
+    // ICRS coordinates
+    double alpha[] = {  0.0,        0.0,     180.0     };
+    double delta[] = {  0.0,       90.0,      30.0     };
+    //Ecliptic coordinates
+    double lambda[] ={  0.0,       90.0,     167.072470};
+    double beta[] =  {  0.0,       66.560719, 27.308813};
+    // Galactic coordinates
+    double l[] =     { 96.337272, 122.93192, 195.639488};
+    double b[] =     {-60.188553,  27.12825,  78.353806};
+    double t[] =     {  MJD_2000,  MJD_2000,   MJD_2100};
+    double TOLERANCE = 0.001;
+
+    for (int x = 0; x < numTestPoints; x++) {
+        //Setup the appropriate rotations
+        psTime* time = psTimeFromMJD(t[x]);
+        psSphereRot* toEcliptic = psSphereRotICRSToEcliptic(time);
+        psSphereRot* fromEcliptic = psSphereRotEclipticToICRS(time);
+        psSphereRot* toGalactic = psSphereRotICRSToGalactic();
+        psSphereRot* fromGalactic = psSphereRotGalacticToICRS();
+        psFree(time);
+
+        // set the ICRS coordinate
+        psSphere* icrs = psSphereAlloc();
+        icrs->r = DEG_TO_RAD(alpha[x]);
+        icrs->d = DEG_TO_RAD(delta[x]);
+
+        // apply/unapply Ecliptic
+        psSphere* ecliptic = psSphereRotApply(NULL, toEcliptic, icrs);
+        psSphere* icrsFromEcliptic = psSphereRotApply(NULL, fromEcliptic, ecliptic);
+
+        // check ecliptic transforms for correctness
+        if (fabs(RAD_TO_DEG(ecliptic->r) - lambda[x]) > TOLERANCE ||
+                fabs(RAD_TO_DEG(ecliptic->d) - beta[x]) > TOLERANCE) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Ecliptic tranformation incorrect.  Result is (%g,%g), expected (%g,%g)",
+                    RAD_TO_DEG(ecliptic->r),RAD_TO_DEG(ecliptic->d),
+                    lambda[x], beta[x]);
+            return 1;
+        }
+        //The second condition here (d - 90) is used b/c 90 is a pole.
+        if ( (fabs(RAD_TO_DEG(icrsFromEcliptic->r) - alpha[x]) > TOLERANCE &&
+                fabs(RAD_TO_DEG(icrsFromEcliptic->d) - 90.0) > TOLERANCE ) ||
+                fabs(RAD_TO_DEG(icrsFromEcliptic->d) - delta[x]) > TOLERANCE) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "ICRS for Ecliptic tranformation incorrect.  Result is (%g,%g), expected (%g,%g)",
+                    RAD_TO_DEG(icrsFromEcliptic->r),RAD_TO_DEG(icrsFromEcliptic->d),
+                    alpha[x], delta[x]);
+            return 2;
+        }
+        psFree(ecliptic);
+        psFree(icrsFromEcliptic);
+
+        //Setup galactic transformations
+        psSphere* galactic = psSphereRotApply(NULL, toGalactic, icrs);
+        psSphere* icrsFromGalactic = psSphereRotApply(NULL, fromGalactic, galactic);
+
+        // check ecliptic transforms for correctness
+        if (fabs(RAD_TO_DEG(galactic->r) - l[x]) > TOLERANCE ||
+                fabs(RAD_TO_DEG(galactic->d) - b[x]) > TOLERANCE) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Galactic tranformation incorrect.  Result is (%g,%g), expected (%g,%g)",
+                    RAD_TO_DEG(galactic->r),RAD_TO_DEG(galactic->d),
+                    l[x], b[x]);
+            return 3;
+        }
+        //The second condition here (d - 90) is used b/c 90 is a pole.
+        if ( (fabs(RAD_TO_DEG(icrsFromGalactic->r) - alpha[x]) > TOLERANCE &&
+                fabs(RAD_TO_DEG(icrsFromGalactic->d) - 90.0) > TOLERANCE ) ||
+                fabs(RAD_TO_DEG(icrsFromGalactic->d) - delta[x]) > TOLERANCE) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "ICRS for Galactic tranformation incorrect.  Result is (%g,%g), expected (%g,%g)",
+                    RAD_TO_DEG(icrsFromGalactic->r),RAD_TO_DEG(icrsFromGalactic->d),
+                    alpha[x], delta[x]);
+            return 4;
+        }
+        psFree(galactic);
+        psFree(icrsFromGalactic);
+        psFree(icrs);
+        psFree(toEcliptic);
+        psFree(fromEcliptic);
+        psFree(toGalactic);
+        psFree(fromGalactic);
+    }
+    return 0;
+}
+
+psS32 testSphereOffset(void)
+{
+    psSphere *origin = psSphereAlloc();
+    psSphere *offset = psSphereAlloc();
+    psSphere *dest = psSphereAlloc();
+    psSphere *empty = NULL;
+    psSphere *output = NULL;
+
+    //Test Set for NULL position
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error");
+    output = psSphereSetOffset(empty, offset, PS_SPHERICAL, PS_DEGREE);
+    if (output != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psSphereSetOffset Failed to return NULL for NULL input.\n");
+        return 1;
+    }
+    //Test Set for NULL offset
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error");
+    output = psSphereSetOffset(offset, empty, PS_SPHERICAL, PS_DEGREE);
+    if (output != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psSphereSetOffset Failed to return NULL for NULL input.\n");
+        return 2;
+    }
+    //Test Get for NULL position1
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error");
+    output = psSphereGetOffset(empty, origin, PS_LINEAR, PS_RADIAN);
+    if (output != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psSphereGetOffset Failed to return NULL for NULL input.\n");
+        return 3;
+    }
+    //Test Get for NULL position2
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error");
+    output = psSphereGetOffset(origin, empty, PS_LINEAR, PS_RADIAN);
+    if (output != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psSphereGetOffset Failed to return NULL for NULL input.\n");
+        return 4;
+    }
+
+    //Test Set using Spherical mode, Degree units
+    origin->r = 0.0;
+    origin->d = 0.0;
+    offset->r = 45.0;
+    offset->d = 30.0;
+    output = psSphereSetOffset(origin, offset, PS_SPHERICAL, PS_DEGREE);
+    if ( fabs(output->r - M_PI/4.0) > 0.0001 ||
+            fabs(output->d - M_PI/6.0) > 0.0001 ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psSphereSetOffset failed to return correct spherical offset values.\n");
+        return 5;
+    }
+    psFree(output);
+
+    //Test Set and Get using Linear mode, Radian units
+    origin->r = 0.0;
+    origin->d = 0.0;
+    offset->r = 1.0;
+    offset->d = 1.0;
+    output = psSphereSetOffset(origin, offset, PS_LINEAR, PS_RADIAN);
+
+    empty = psSphereGetOffset(origin, output, PS_LINEAR, PS_RADIAN);
+    if ( fabs(offset->r - empty->r) > 0.0001 || fabs(offset->d - empty->d) > 0.0001 ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psSphereGetOffset failed to return correct linear offset values.\n");
+        return 7;
+    }
+    psFree(output);
+    psFree(empty);
+
+    //Test Set using Linear mode, Arcmin units
+    origin->r = 0.0;
+    origin->d = 0.0;
+    offset->r = RAD_TO_MIN(M_PI / 4.0);     //45 deg
+    offset->d = RAD_TO_MIN(M_PI / 6.0);     //30 deg
+    output = psSphereSetOffset(origin, offset, PS_SPHERICAL, PS_ARCMIN);
+    //Test Get using Spherical mode, Arcsec units
+    empty = psSphereGetOffset(origin, output, PS_SPHERICAL, PS_ARCSEC);
+    empty->r = SEC_TO_RAD(empty->r);
+    empty->d = SEC_TO_RAD(empty->d);
+    if (fabs(empty->r - (M_PI / 4.0)) > 0.001 || fabs(empty->d - (M_PI / 6.0)) > 0.001) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psSphereGetOffset failed to return correct offset unit values.\n");
+        printf("\n SphereGetOffset should be %lf, %lf and is %lf, %lf\n", output->r, output->d,
+               empty->r, empty->d);
+        return 8;
+    }
+    psFree(output);
+
+    psFree(origin);
+    psFree(dest);
+    psFree(offset);
+    psFree(empty);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psTime_01.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psTime_01.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psTime_01.c	(revision 22158)
@@ -0,0 +1,1163 @@
+/** @file  tst_psTime_01.c
+ *
+ *  @brief Test driver for psTime functions
+ *
+ *  This test driver contains the following tests for psTime:
+ *     1) Allocate psTime structure
+ *     2) Get current time
+ *     3) Get UT1 UTC delta
+ *     4) Convert psTime to MJD
+ *     5) Convert psTime to JD
+ *     6) Convert psTime to ISO
+ *     7) Convert psTime to timeval
+ *     8) Create psTime from MJD
+ *     9) Create psTime from JD
+ *    10) Create psTime from ISO
+ *    11) Create psTime from timeval
+ *    12) Create psTime from TM
+ *    13) Convert time between different types
+ *
+ *     O) Convert psTime time to LMST
+ *
+ *  @author  Ross Harman, MHPCC
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.7 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2006-07-21 00:08:15 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib_strict.h"
+#include "psTest.h"
+#include <string.h>
+
+#define ERROR_TOL    0.0001
+
+static psS32 testTimeAlloc(void);
+static psS32 testTimeGetNow(void);
+static psS32 testTimeGetUT1Delta(void);
+static psS32 testTimeToMJD(void);
+static psS32 testTimeToJD(void);
+static psS32 testTimeToISO(void);
+static psS32 testTimeToTimeval(void);
+static psS32 testTimeFromMJD(void);
+static psS32 testTimeFromJD(void);
+static psS32 testTimeFromISO(void);
+static psS32 testTimeFromTimeval(void);
+static psS32 testTimeFromTM(void);
+static psS32 testTimeConvert(void);
+
+testDescription tests[] = {
+                              {testTimeAlloc,1,"psTimeAlloc",0,false},
+                              {testTimeGetNow,2,"psTimeGetNow",0,false},
+                              {testTimeGetUT1Delta,3,"psTimeGetUT1Delta",0,false},
+                              {testTimeToMJD,4,"psTimeToMJD",0,false},
+                              {testTimeToJD,5,"psTimeToJD",0,false},
+                              {testTimeToISO,6,"psTimeToISO",0,false},
+                              {testTimeToTimeval,7,"psTimeToTimeval",0,false},
+                              {testTimeFromMJD,8,"psTimeFromMJD",0,false},
+                              {testTimeFromJD,9,"psTimeFromJD",0,false},
+                              {testTimeFromISO,10,"psTimeFromISO",0,false},
+                              {testTimeFromTimeval,11,"psTimeFromTimeval",0,false},
+                              {testTimeFromTM,12,"p_psTimeFromTM",0,false},
+                              {testTimeConvert,666,"psTimeConvert",0,false},
+                              {NULL}
+                          };
+
+// Test Time 1 : July 21, 2004  18:22:24.3
+//               MJD = 53207.765559
+//               JD = 2453208.265559
+// UTC Test Time 1
+const psS64 testTime1SecondsUTC     = 1090434144;
+const psU32 testTime1NanosecondsUTC = 272044000;
+// TAI Test Time 1
+const psS64 testTime1SecondsTAI     = 1090434176;
+const psU32 testTime1NanosecondsTAI = 272044000;
+const psF64 testTime1MJDTAI         = 53207.76592937;
+const psF64 testTime1JDTAI          = 2453208.26592937;
+
+// TT Test Time 1
+const psS64 testTime1SecondsTT      = 1090434208;
+const psU32 testTime1NanosecondsTT  = 456044000;
+// Expected UT1-UTC IERS A & B
+const psF64 testTime1UT1DeltaBullA  = -0.457233186;
+const psF64 testTime1UT1DeltaBullB  = -0.457227;
+// UT1 Test Time 1
+const psS64 testTime1SecondsUT1     = 1090434143;
+//const psU32 testTime1NanosecondsUT1 = 814810814;
+const psU32 testTime1NanosecondsUT1 = 814810861;
+// Expected MJD & JD
+const psF64 testTime1MJD            = 53207.765559;
+const psF64 testTime1JD             = 2453208.265559;
+// Expected ISO string
+const char* testTime1Str     = "2004-07-21T18:22:24.2Z";
+const char* testTime1StrLeap = "2004-07-21T18:22:60.2Z";
+// Expected timeval values
+const psS32 testTime1TimevalSec = 1090434144;
+const psS32 testTime1TimevalUsec = 272044;
+
+// Test Time 2 : Jan. 1, 1973 00:00:00.0000
+//               MJD = 41683.0000
+//               JD = 2441683.5000
+const psS64 testTime2SecondsUTC     = 94694400;
+const psU32 testTime2NanosecondsUTC = 0;
+
+// Expected UT1-UTC IERS A & B
+const psF64 testTime2UT1DeltaBullA  = 0.000000;
+const psF64 testTime2UT1DeltaBullB  = 0.000000;
+
+// Test Time 3 : Sept. 21, 2006 00:00:00.0000
+//               MJD = 53999
+//               JD = 2453999.5
+const psS64 testTime3SecondsUTC     = 1158796800;
+const psU32 testTime3NanosecondsUTC = 0;
+// Expected UT1-UTC IERS A & B
+const psF64 testTime3UT1DeltaBullA  = -0.63574;
+const psF64 testTime3UT1DeltaBullB  = -0.63574;
+
+// Test Time 4 : Jan. 1, 1969 00:00:00.0000
+//               MJD = 40222
+//               JD = 2440222.5
+const psS64 testTime4SecondsUTC     = -31536000;
+const psU32 testTime4NanosecondsUTC = 0;
+// Expected MJD and JD
+const psF64 testTime4MJD            = 40222.0;
+const psF64 testTime4JD             = 2440222.5;
+
+// Test Time 5 : Dec 31, 0001 BC 23:59:59
+//               MJD = -1397755
+//               JD = 1002245.4999
+const psS64 testTime5SecondsUTC     = -62125920001;
+const psU32 testTime5NanosecondsUTC  = 0;
+
+// Test Time 6 : Jan. 1, 10000 AD 00:00:00
+const psS64 testTime6SecondsUTC      = 253202544001;
+const psU32 testTime6NanosecondsUTC  = 0;
+
+// Test Time 7 : Jan. 1, 2004 00:00:00,0
+const psS64 testTime7Seconds         = 1072915200;
+const psU32 testTime7Nanoseconds     = 0;
+const psS32 testTime7TmYear          = 104;
+const psS32 testTime7TmMon           = 0;
+const psS32 testTime7TmDay           = 1;
+const psS32 testTime7TmHour          = 0;
+const psS32 testTime7TmMin           = 0;
+const psS32 testTime7TmSec           = 0;
+
+// Test Time 8 : Dec. 31, 2003 00:00:00,0
+const psS64 testTime8Seconds         = 1072828800;
+const psU32 testTime8Nanoseconds     = 0;
+const psS32 testTime8TmYear          = 103;
+const psS32 testTime8TmMon           = 11;
+const psS32 testTime8TmDay           = 31;
+const psS32 testTime8TmHour          = 0;
+const psS32 testTime8TmMin           = 0;
+const psS32 testTime8TmSec           = 0;
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    // Initialize library internal structures
+    psLibInit("pslib.config");
+
+    if( !runTestSuite(stderr,"psTime",tests,argc,argv)) {
+        return 1;
+    }
+
+    // Cleanup library
+    psLibFinalize();
+
+    return 0;
+}
+
+psS32 testTimeAlloc(void)
+{
+    psTime*  time = NULL;
+
+    // Allocate new psTime with valid time type
+    time = psTimeAlloc(PS_TIME_TAI);
+    if(time == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Return NULL when psTime object ptr expected");
+        return 1;
+    }
+    // Verify members set properly
+    if(time->type != PS_TIME_TAI) {
+        psError(PS_ERR_UNKNOWN,true,"Member type = %d not as expected %d",time->type,PS_TIME_TAI);
+        return 2;
+    }
+    if((time->sec != 0) && (time->nsec != 0) && (time->leapsecond != false)) {
+        psError(PS_ERR_UNKNOWN,true,"Members not set appropriately");
+        return 3;
+    }
+    psFree(time);
+
+    // Allocate new psTime with invalid time type
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    time = psTimeAlloc(-100);
+    if(time != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL for invalid time type");
+        return 4;
+    }
+
+    return 0;
+}
+psS32 testTimeGetNow(void)
+{
+    psTime*  timeNow = NULL;
+
+    // Get current time and verify return is psTime structure
+    timeNow = psTimeGetNow(PS_TIME_TAI);
+    if(timeNow == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return valid psTime struct");
+        return 1;
+    }
+    if(timeNow->type != PS_TIME_TAI) {
+        psError(PS_ERR_UNKNOWN,true,"Time type %d not as expected %d",
+                timeNow->type, PS_TIME_TAI);
+        return 2;
+    }
+    psFree(timeNow);
+
+    // Attempt to get time with invalid type
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid time type");
+    timeNow = psTimeGetNow(-100);
+    if(timeNow != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL for invalid time type");
+        return 3;
+    }
+
+    return 0;
+}
+
+psS32 testTimeGetUT1Delta(void)
+{
+    psTime*    time      = NULL;
+    psF64      ut1Delta  = 0.0;
+
+    // Attempt to convert NULL time
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL time");
+    ut1Delta = psTimeGetUT1Delta(time,PS_IERS_B);
+    if( !isnan(ut1Delta)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NAN for NULL psTime");
+        return 1;
+    }
+
+    // Attempt to convert invalid time
+    time = psTimeAlloc(PS_TIME_TAI);
+    time->sec = 1;
+    time->nsec = 2e9;
+    time->leapsecond = false;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid time");
+    ut1Delta = psTimeGetUT1Delta(time,PS_IERS_B);
+    if( !isnan(ut1Delta)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NAN for invalid time");
+        return 2;
+    }
+
+    // Attempt to convert time with invalid bulletin
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid bulletin");
+    time->nsec = 2;
+    ut1Delta = psTimeGetUT1Delta(time,-100);
+    if( !isnan(ut1Delta)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NAN for invalid bulletin");
+        return 3;
+    }
+
+    // Attempt to get delta with valid time and bulletin A
+    time->sec  = testTime1SecondsUTC;
+    time->nsec = testTime1NanosecondsUTC;
+    time->type = PS_TIME_UTC;
+    ut1Delta = psTimeGetUT1Delta(time,PS_IERS_A);
+    if(fabs(ut1Delta - testTime1UT1DeltaBullA) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"UT1 Delta %lf not as expected %lf test time 1 bulletin A",
+                ut1Delta,testTime1UT1DeltaBullA);
+        return 4;
+    }
+
+    // Attempt to get delta with valid time and bulletin B
+    ut1Delta = psTimeGetUT1Delta(time,PS_IERS_B);
+    if(fabs(ut1Delta - testTime1UT1DeltaBullB) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"UT1 Delta %lf not as expected %lf test time 1 bulletin B",
+                ut1Delta,testTime1UT1DeltaBullB);
+        return 5;
+    }
+
+    // Attempt to get delta with valid time and bulletin A
+    time->sec  = testTime2SecondsUTC;
+    time->nsec = testTime2NanosecondsUTC;
+    time->type = PS_TIME_UTC;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate a warning message predating table");
+    ut1Delta = psTimeGetUT1Delta(time,PS_IERS_A);
+    if(fabs(ut1Delta - testTime2UT1DeltaBullA) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"UT1 Delta %lf not as expected %lf test time 2 bulletin A",
+                ut1Delta,testTime2UT1DeltaBullA);
+        return 6;
+    }
+
+    // Attempt to get delta with valid time and bulletin B
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate a warning message predating table");
+    ut1Delta = psTimeGetUT1Delta(time,PS_IERS_B);
+    if(fabs(ut1Delta - testTime2UT1DeltaBullB) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"UT1 Delta %lf not as expected %lf test time 2 bulletin B",
+                ut1Delta,testTime2UT1DeltaBullB);
+        return 7;
+    }
+
+    // Attempt to get delta with valid time and bulletin A
+    time->sec  = testTime3SecondsUTC;
+    time->nsec = testTime3NanosecondsUTC;
+    time->type = PS_TIME_UTC;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate a warning message postdating table");
+    ut1Delta = psTimeGetUT1Delta(time,PS_IERS_A);
+    if(fabs(ut1Delta - testTime3UT1DeltaBullA) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"UT1 Delta %lf not as expected %lf test time 3 bulletin A",
+                ut1Delta,testTime3UT1DeltaBullA);
+        return 8;
+    }
+
+    // Attempt to get delta with valid time and bulletin B
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate a warning message postdating table");
+    ut1Delta = psTimeGetUT1Delta(time,PS_IERS_B);
+    if(fabs(ut1Delta - testTime3UT1DeltaBullB) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"UT1 Delta %lf not as expected %lf test time 3 bulletin B",
+                ut1Delta,testTime3UT1DeltaBullB);
+        return 9;
+    }
+
+    psFree(time);
+
+    return 0;
+}
+
+psS32 testTimeToMJD(void)
+{
+    psTime*  time = NULL;
+    psF64    mjd  = 0.0;
+
+    // Attempt to convert with time NULL
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL time");
+    mjd = psTimeToMJD(NULL);
+    if(!isnan(mjd)) {
+        psError(PS_ERR_UNKNOWN,true,"Expected NaN for NULL time");
+        return 1;
+    }
+
+    // Attempt to convert invalid time
+    time = psTimeAlloc(PS_TIME_UTC);
+    time->sec = 1;
+    time->nsec = 2e9;
+    time->leapsecond = false;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid time");
+    mjd = psTimeToMJD(time);
+    if( !isnan(mjd)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NAN for invalid time");
+        return 2;
+    }
+
+    // Check valid time conversion to MJD after 1/1/1970 epoch
+    time->sec = testTime1SecondsUTC;
+    time->nsec = testTime1NanosecondsUTC;
+    mjd = psTimeToMJD(time);
+    //    if(fabs(mjd - testTime1MJD) > ERROR_TOL) {
+    if(fabs(mjd - 53207.765929) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Expected MJD = %lf not as expected %lf",
+                mjd, testTime1MJD);
+        return 3;
+    }
+
+    // Check valid time conversion to MJD before 1/1/1970 epoch
+    time->sec = testTime4SecondsUTC;
+    time->nsec = testTime4NanosecondsUTC;
+    mjd = psTimeToMJD(time);
+    if(fabs(mjd - testTime4MJD) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Expected MJD = %lf not as expected %lf",
+                mjd, testTime4MJD);
+        return 4;
+    }
+
+    psFree(time);
+
+    return 0;
+}
+
+psS32 testTimeToJD(void)
+{
+    psTime*  time = NULL;
+    psF64    jd  = 0.0;
+
+    // Attempt to convert with time NULL
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL time");
+    jd = psTimeToJD(NULL);
+    if(!isnan(jd)) {
+        psError(PS_ERR_UNKNOWN,true,"Expected NaN for NULL time");
+        return 1;
+    }
+
+    // Attempt to convert invalid time
+    time = psTimeAlloc(PS_TIME_UTC);
+    time->sec = 1;
+    time->nsec = 2e9;
+    time->leapsecond = false;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid time");
+    jd = psTimeToJD(time);
+    if( !isnan(jd)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NAN for invalid time");
+        return 2;
+    }
+
+    // Check valid time conversion to MJD after 1/1/1970 epoch
+    time->sec = testTime1SecondsUTC;
+    time->nsec = testTime1NanosecondsUTC;
+    jd = psTimeToJD(time);
+    //    if(fabs(jd - testTime1JD) > ERROR_TOL) {
+    if(fabs(jd - 2453208.265929) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Expected JD = %lf not as expected %lf",
+                jd, testTime1JD);
+        return 3;
+    }
+
+    // Check valid time conversion to MJD before 1/1/1970 epoch
+    time->sec = testTime4SecondsUTC;
+    time->nsec = testTime4NanosecondsUTC;
+    jd = psTimeToJD(time);
+    if(fabs(jd - testTime4JD) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Expected JD = %lf not as expected %lf",
+                jd, testTime4JD);
+        return 4;
+    }
+
+    psFree(time);
+
+    return 0;
+}
+
+psS32 testTimeToISO(void)
+{
+    psTime*    time    = NULL;
+    char*      timeStr = NULL;
+
+    // Attempt to convert with NULL time
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL time");
+    timeStr = psTimeToISO(time);
+    if(timeStr != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL as expected");
+        return 1;
+    }
+
+    // Attempt to convert invalid time
+    time = psTimeAlloc(PS_TIME_UTC);
+    time->sec = 1;
+    time->nsec = 2e9;
+    time->leapsecond = false;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid time");
+    timeStr = psTimeToISO(time);
+    if( timeStr != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL for invalid time");
+        return 2;
+    }
+
+    // Verify return NULL for time prior to year 0000
+    time->sec = testTime5SecondsUTC;
+    time->nsec = testTime5NanosecondsUTC;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for time prior year 0000");
+    timeStr = psTimeToISO(time);
+    if(timeStr != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL for time prior to year 0000");
+        return 3;
+    }
+
+    // Verify return NULL for time after to year 9999
+    time->sec = testTime6SecondsUTC;
+    time->nsec = testTime6NanosecondsUTC;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for time after year 9999");
+    timeStr = psTimeToISO(time);
+    if(timeStr != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL for time after to year 9999");
+        return 4;
+    }
+
+    // Verify return string with valid time
+    time->sec = testTime1SecondsUTC;
+    time->nsec = testTime1NanosecondsUTC;
+    timeStr = psTimeToISO(time);
+    if(strcmp(timeStr,testTime1Str) != 0) {
+        psError(PS_ERR_UNKNOWN,true,"String %s not as expected %s",
+                timeStr, testTime1Str);
+        return 5;
+    }
+    psFree(timeStr);
+
+    // Verify return string with valid time and leap second set
+    time->sec = testTime1SecondsUTC;
+    time->nsec = testTime1NanosecondsUTC;
+    time->leapsecond = true;
+    timeStr = psTimeToISO(time);
+    if(strcmp(timeStr,testTime1StrLeap) != 0) {
+        psError(PS_ERR_UNKNOWN,true,"String %s not as expected %s",
+                timeStr, testTime1StrLeap);
+        return 6;
+    }
+    psFree(timeStr);
+    psFree(time);
+
+    return 0;
+}
+
+psS32 testTimeToTimeval(void)
+{
+    psTime*           time         = NULL;
+    struct timeval*   timevalTime  = NULL;
+
+    // Attempt to convert with NULL time
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL time");
+    timevalTime = psTimeToTimeval(time);
+    if(timevalTime != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL as expected");
+        return 1;
+    }
+
+    // Attempt to convert invalid time
+    time = psTimeAlloc(PS_TIME_UTC);
+    time->sec = 1;
+    time->nsec = 2e9;
+    time->leapsecond = false;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid time");
+    timevalTime = psTimeToTimeval(time);
+    if( timevalTime != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL for invalid time");
+        return 2;
+    }
+
+    // Attempt to convert invalid time
+    time->sec = -1;
+    time->nsec = 0;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid time");
+    timevalTime = psTimeToTimeval(time);
+    if( timevalTime != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL for invalid time");
+        return 2;
+    }
+
+    // Verify convert to timeval with valid time
+    time->sec = testTime1SecondsUTC;
+    time->nsec = testTime1NanosecondsUTC;
+    timevalTime = psTimeToTimeval(time);
+    if(timevalTime->tv_sec != testTime1TimevalSec) {
+        psError(PS_ERR_UNKNOWN,true,"Timeval seconds %ld not as expectd %ld",
+                timevalTime->tv_sec,testTime1TimevalSec);
+        return 4;
+    }
+    if(timevalTime->tv_usec != testTime1TimevalUsec) {
+        psError(PS_ERR_UNKNOWN,true,"Timeval useconds %ld not as expected %ld",
+                timevalTime->tv_usec,testTime1TimevalUsec);
+        return 5;
+    }
+
+    psFree(timevalTime);
+    psFree(time);
+
+    return 0;
+}
+
+psS32 testTimeFromMJD(void)
+{
+    psTime*   time = NULL;
+
+    // Attempt to convert valid time to psTime
+    time = psTimeFromMJD(testTime1MJDTAI);
+    if(time->type != PS_TIME_TAI) {
+        psError(PS_ERR_UNKNOWN,true,"Type %d not as expected %d",
+                time->type,PS_TIME_TAI);
+        return 1;
+    }
+    if(time->sec != testTime1SecondsTAI) {
+        psError(PS_ERR_UNKNOWN,true,"psTime seconds %ld not as expected %ld",
+                (long int)time->sec,testTime1SecondsTAI);
+        return 2;
+    }
+    psFree(time);
+
+    // Attempt to convert valid time before 1970 epoch
+    time = psTimeFromMJD(testTime4MJD);
+    if(time->type != PS_TIME_TAI) {
+        psError(PS_ERR_UNKNOWN,true,"Type %d not as expected %d",
+                time->type,PS_TIME_TAI);
+        return 3;
+    }
+    if(time->sec != testTime4SecondsUTC) {
+        psError(PS_ERR_UNKNOWN,true,"psTime seconds %ld not as expected %ld",
+                (long int)time->sec,testTime4SecondsUTC);
+        return 4;
+    }
+    psFree(time);
+
+    return 0;
+}
+
+psS32 testTimeFromJD(void)
+{
+    psTime*   time = NULL;
+
+    // Attempt to convert valid time to psTime
+    time = psTimeFromJD(testTime1JDTAI);
+    if(time->type != PS_TIME_TAI) {
+        psError(PS_ERR_UNKNOWN,true,"Type %d not as expected %d",
+                time->type,PS_TIME_TAI);
+        return 1;
+    }
+    if(time->sec != testTime1SecondsTAI) {
+        psError(PS_ERR_UNKNOWN,true,"psTime seconds %ld not as expected %ld",
+                (long int)time->sec,(long int)testTime1SecondsTAI);
+        return 2;
+    }
+    psFree(time);
+
+    // Attempt to convert valid time before 1970 epoch
+    time = psTimeFromJD(testTime4JD);
+    if(time->type != PS_TIME_TAI) {
+        psError(PS_ERR_UNKNOWN,true,"Type %d not as expected %d",
+                time->type,PS_TIME_TAI);
+        return 3;
+    }
+    if(time->sec != testTime4SecondsUTC) {
+        psError(PS_ERR_UNKNOWN,true,"psTime seconds %ld not as expected %ld",
+                (long int)time->sec,testTime4SecondsUTC);
+        return 4;
+    }
+    psFree(time);
+
+    return 0;
+}
+
+psS32 testTimeFromISO(void)
+{
+    psTime*   time = NULL;
+
+    // Attempt to convert NULL string
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL ISO string");
+    time = psTimeFromISO(NULL, PS_TIME_TAI);
+    if(time != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL as expected for NULL ISO string");
+        return 1;
+    }
+
+    // Convert valid ISO string
+    time = psTimeFromISO(testTime1Str, PS_TIME_TAI);
+    if(time->type != PS_TIME_TAI) {
+        psError(PS_ERR_UNKNOWN,true,"Type %d not as expected %d",
+                time->type, PS_TIME_TAI);
+        return 2;
+    }
+    if(time->sec != testTime1SecondsUTC) {
+        psError(PS_ERR_UNKNOWN,true,"psTime seconds %ld not as expected %ld",
+                (long int)time->sec,testTime1SecondsTAI);
+        return 3;
+    }
+    psFree(time);
+
+    // Attempt to convert invalid ISO string
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for invalid ISO string");
+    time = psTimeFromISO("Here I am", PS_TIME_TAI);
+    if(time != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL as expected for invalid ISO string");
+        return 4;
+    }
+    psFree(time);
+
+    return 0;
+}
+
+psS32 testTimeFromTimeval(void)
+{
+    psTime*          time        = NULL;
+    struct timeval*  timevalTime = NULL;
+
+    // Attempt to create psTime from NULL timeval ptr
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL timeval");
+    time = psTimeFromTimeval(NULL);
+    if(time != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL for NULL timeval ptr");
+        return 1;
+    }
+
+    // Convert valid timeval structure
+    timevalTime = (struct timeval*)psAlloc(sizeof(struct timeval));
+    timevalTime->tv_sec = testTime1SecondsTAI;
+    timevalTime->tv_usec = testTime1NanosecondsTAI / 1000;
+    time = psTimeFromTimeval(timevalTime);
+    if(time == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return value for valid timeval");
+        return 2;
+    }
+    if(time->type != PS_TIME_TAI) {
+        psError(PS_ERR_UNKNOWN,true,"psTime type %d not as expected %d",
+                time->type, PS_TIME_TAI);
+        return 3;
+    }
+    if(time->sec != testTime1SecondsTAI) {
+        psError(PS_ERR_UNKNOWN,true,"psTime seconds %ld not as expected %ld",
+                time->sec, testTime1SecondsTAI);
+        return 4;
+    }
+    if(time->nsec != testTime1NanosecondsTAI) {
+        psError(PS_ERR_UNKNOWN,true,"psTime nanosec %ld not as expected %ld",
+                time->nsec, testTime1NanosecondsTAI);
+        return 5;
+    }
+    psFree(timevalTime);
+    psFree(time);
+
+    return 0;
+}
+
+psS32 testTimeFromTM(void)
+{
+    psTime*     time   = NULL;
+    struct tm*  tmTime = NULL;
+
+    // Attempt to convert from NULL tm structure ptr
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL tm ptr");
+    time = psTimeFromTM(tmTime);
+    if(time != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL for NULL tm ptr");
+        return 1;
+    }
+
+    // Verify convert for valid tm structure
+    tmTime = (struct tm*)psAlloc(sizeof(struct tm));
+    tmTime->tm_year = testTime7TmYear;
+    tmTime->tm_mon  = testTime7TmMon;
+    tmTime->tm_mday = testTime7TmDay;
+    tmTime->tm_hour = testTime7TmHour;
+    tmTime->tm_min  = testTime7TmMin;
+    tmTime->tm_sec  = testTime7TmSec;
+    time = psTimeFromTM(tmTime);
+    if(time == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return value for valid tm structure");
+        return 2;
+    }
+    if(time->sec != testTime7Seconds) {
+        psError(PS_ERR_UNKNOWN,true,"psTime seconds %ld not as expected %ld",
+                (long int)time->sec, (long int)testTime7Seconds);
+        return 3;
+    }
+    if(time->nsec != testTime7Nanoseconds) {
+        psError(PS_ERR_UNKNOWN,true,"psTime nanoseconds %ld not as expected %ld",
+                time->nsec, testTime7Nanoseconds);
+        return 4;
+    }
+    psFree(tmTime);
+    psFree(time);
+
+    // Verify convert for valid tm structure
+    tmTime = (struct tm*)psAlloc(sizeof(struct tm));
+    tmTime->tm_year = testTime8TmYear;
+    tmTime->tm_mon  = testTime8TmMon;
+    tmTime->tm_mday = testTime8TmDay;
+    tmTime->tm_hour = testTime8TmHour;
+    tmTime->tm_min  = testTime8TmMin;
+    tmTime->tm_sec  = testTime8TmSec;
+    time = psTimeFromTM(tmTime);
+    if(time == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return value for valid tm structure");
+        return 2;
+    }
+    if(time->sec != testTime8Seconds) {
+        psError(PS_ERR_UNKNOWN,true,"psTime seconds %ld not as expected %ld",
+                (long int)time->sec, (long int)testTime8Seconds);
+        return 3;
+    }
+    if(time->nsec != testTime8Nanoseconds) {
+        psError(PS_ERR_UNKNOWN,true,"psTime nanoseconds %ld not as expected %ld",
+                time->nsec, testTime8Nanoseconds);
+        return 4;
+    }
+    psFree(tmTime);
+    psFree(time);
+
+    return 0;
+}
+
+psS32 testTimeConvert(void)
+{
+    psTime*  time1 = NULL;
+    psTime*  time2 = NULL;
+
+    // Attempt to convert NULL time
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL time");
+    time2 = psTimeConvert(time1,PS_TIME_TAI);
+    // Verify return value is NULL
+    if(time2 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL for NULL time specified");
+        return 1;
+    }
+
+    // Attempt to convert to invalid type
+    time1 = psTimeAlloc(PS_TIME_TAI);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid type");
+    time2 = psTimeConvert(time1,-100);
+    // Verify return value is NULL
+    if(time2 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return time for invalid type to convert to");
+        return 2;
+    }
+    time1->type = PS_TIME_UTC;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid type");
+    time2 = psTimeConvert(time1,-100);
+    // Verify return value is NULL
+    if(time2 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return time for invalid type to convert to");
+        return 2;
+    }
+    time1->type = PS_TIME_TT;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid type");
+    time2 = psTimeConvert(time1,-100);
+    // Verify return value is NULL
+    if(time2 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return time for invalid type to convert to");
+        return 2;
+    }
+    time1->type = -100;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid type");
+    time2 = psTimeConvert(time1,PS_TIME_TAI);
+    // Verify return value is NULL
+    if(time2 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return time for invalid type to convert to");
+        return 2;
+    }
+
+    // Attempt to convert with invalid time nsec > 1e9
+    time1->nsec = 2e9;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid time");
+    time2 = psTimeConvert(time1,PS_TIME_TAI);
+    if(time2 != time1) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return time for invalid time specified");
+        return 3;
+    }
+
+    //Attempt to convert a time to the same type
+    time2 = NULL;
+    time1->sec = 1;
+    time1->nsec = 2;
+    time1->type = PS_TIME_TAI;
+    time1->leapsecond = false;
+    time2 = psTimeConvert(time1,PS_TIME_TAI);
+    if(time2 != time1) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return time for conversion to same type");
+        return 4;
+    }
+    // Verify time not changed
+    if((time2->sec != 1) || (time2->nsec != 2) || (time2->type != PS_TIME_TAI) ||
+            (time2->leapsecond != false) ) {
+        psError(PS_ERR_UNKNOWN,true,"Time member changes when no change expected");
+        return 5;
+    }
+
+    // Attempt to convert a UTC time to a TAI
+    time2 = NULL;
+    time1->sec = testTime1SecondsUTC;
+    time1->nsec = testTime1NanosecondsUTC;
+    time1->type = PS_TIME_UTC;
+    time1->leapsecond = false;
+    time2 = psTimeConvert(time1,PS_TIME_TAI);
+    if(time2 != time1) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return time for conversion from UTC to TAI");
+        return 6;
+    }
+    // Verify time type
+    if(time2->type != PS_TIME_TAI) {
+        psError(PS_ERR_UNKNOWN,true,"Returned time type %d not as expected %d",
+                time2->type, PS_TIME_TAI);
+        return 7;
+    }
+    // Verify time is TAI as expected
+    if(time2->sec != testTime1SecondsTAI) {
+        psError(PS_ERR_UNKNOWN,true,"TAI seconds = %ld not as expected %ld",(long int)time2->sec,
+                (long int)testTime1SecondsTAI);
+        return 7;
+    }
+    if(time2->nsec != testTime1NanosecondsTAI) {
+        psError(PS_ERR_UNKNOWN,true,"TAI nanoseconds = %ld not as expected %ld",(long int)time2->nsec,
+                (long int)testTime1NanosecondsTAI);
+        return 8;
+    }
+
+    // Attempt to convert a UTC time to a TT
+    time2 = NULL;
+    time1->sec = testTime1SecondsUTC;
+    time1->nsec = testTime1NanosecondsUTC;
+    time1->type = PS_TIME_UTC;
+    time1->leapsecond = false;
+    time2 = psTimeConvert(time1,PS_TIME_TT);
+    if(time2 != time1) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return time for conversion from UTC to TT");
+        return 6;
+    }
+    // Verify time type
+    if(time2->type != PS_TIME_TT) {
+        psError(PS_ERR_UNKNOWN,true,"Returned time type %d not as expected %d",
+                time2->type, PS_TIME_TT);
+        return 7;
+    }
+    // Verify time is TT as expected
+    if(time2->sec != testTime1SecondsTT) {
+        psError(PS_ERR_UNKNOWN,true,"TT seconds = %ld not as expected %ld",(long int)time2->sec,
+                (long int)testTime1SecondsTT);
+        return 7;
+    }
+    if(time2->nsec != testTime1NanosecondsTT) {
+        psError(PS_ERR_UNKNOWN,true,"TT nanoseconds = %ld not as expected %ld",(long int)time2->nsec,
+                (long int)testTime1NanosecondsTT);
+        return 8;
+    }
+
+    // Attempt to convert a UTC time to UT1
+    time2 = NULL;
+    time1->sec = testTime1SecondsUTC;
+    time1->nsec = testTime1NanosecondsUTC;
+    time1->type = PS_TIME_UTC;
+    time1->leapsecond = false;
+    time2 = psTimeConvert(time1,PS_TIME_UT1);
+    if(time1 != time2) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return time for conversion from UTC to UT1");
+        return 9;
+    }
+    // Verify time type
+    if(time2->type != PS_TIME_UT1) {
+        psError(PS_ERR_UNKNOWN,true,"Returned time type %d not as expected %d",
+                time2->type, PS_TIME_UT1);
+        return 7;
+    }
+    // Verify time is UT1 as expected
+    if(time2->sec != testTime1SecondsUT1) {
+        psError(PS_ERR_UNKNOWN,true,"UT1 seconds = %ld not as expected %ld",(long int)time2->sec,
+                (long int)testTime1SecondsUT1);
+        return 9;
+    }
+    if(time2->nsec != testTime1NanosecondsUT1) {
+        psError(PS_ERR_UNKNOWN,true,"UT1 nanoseconds = %d not as expected %d",time2->nsec,
+                testTime1NanosecondsUT1);
+        return 10;
+    }
+
+    // Attempt to convert a TAI time to UTC
+    time2 = NULL;
+    time1->sec = testTime1SecondsTAI;
+    time1->nsec = testTime1NanosecondsTAI;
+    time1->type = PS_TIME_TAI;
+    time1->leapsecond = false;
+    time2 = psTimeConvert(time1,PS_TIME_UTC);
+    if(time2 != time1) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return time for conversion from TAI to UTC");
+        return 11;
+    }
+    // Verify time type
+    if(time2->type != PS_TIME_UTC) {
+        psError(PS_ERR_UNKNOWN,true,"Returned time type %d not as expected %d",
+                time2->type, PS_TIME_UTC);
+        return 7;
+    }
+    // Verify time is UTC as expected
+    if(time2->sec != testTime1SecondsUTC) {
+        psError(PS_ERR_UNKNOWN,true,"UTC seconds = %ld not as expected %ld",(long int)time2->sec,
+                (long int)testTime1SecondsUTC);
+        return 12;
+    }
+    if(time2->nsec != testTime1NanosecondsUTC) {
+        psError(PS_ERR_UNKNOWN,true,"UTC nanoseconds = %ld not as expected %ld",(long int)time2->nsec,
+                (long int)testTime1NanosecondsUTC);
+        return 13;
+    }
+
+    // Attempt to convert a TAI time to TT
+    time2 = NULL;
+    time1->sec = testTime1SecondsTAI;
+    time1->nsec = testTime1NanosecondsTAI;
+    time1->type = PS_TIME_TAI;
+    time1->leapsecond = false;
+    time2 = psTimeConvert(time1,PS_TIME_TT);
+    if(time2 != time1) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return time for conversion from TAI to TT");
+        return 14;
+    }
+    // Verify time type
+    if(time2->type != PS_TIME_TT) {
+        psError(PS_ERR_UNKNOWN,true,"Returned time type %d not as expected %d",
+                time2->type, PS_TIME_TT);
+        return 7;
+    }
+    // Verify time is TT as expected
+    if(time2->sec != testTime1SecondsTT) {
+        psError(PS_ERR_UNKNOWN,true,"TT seconds = %ld not as expected %ld",(long int)time2->sec,
+                (long int)testTime1SecondsTT);
+        return 15;
+    }
+    if(time2->nsec != testTime1NanosecondsTT) {
+        psError(PS_ERR_UNKNOWN,true,"TT nanoseconds = %ld not as expected %ld",(long int)time2->nsec,
+                (long int)testTime1NanosecondsTT);
+        return 16;
+    }
+
+    // Attempt to convert a TAI time to UT1
+    time2 = NULL;
+    time1->sec = testTime1SecondsTAI;
+    time1->nsec = testTime1NanosecondsTAI;
+    time1->type = PS_TIME_TAI;
+    time1->leapsecond = false;
+    time2 = psTimeConvert(time1,PS_TIME_UT1);
+    if(time1 != time2) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return time for conversion from TAI to UT1");
+        return 9;
+    }
+    // Verify time type
+    if(time2->type != PS_TIME_UT1) {
+        psError(PS_ERR_UNKNOWN,true,"Returned time type %d not as expected %d",
+                time2->type, PS_TIME_UT1);
+        return 7;
+    }
+    // Verify time is UT1 as expected
+    if(time2->sec != testTime1SecondsUT1) {
+        psError(PS_ERR_UNKNOWN,true,"UT1 seconds = %ld not as expected %ld",(long int)time2->sec,
+                (long int)testTime1SecondsUT1);
+        return 9;
+    }
+    if(time2->nsec != testTime1NanosecondsUT1) {
+        psError(PS_ERR_UNKNOWN,true,"UT1 nanoseconds = %d not as expected %d",time2->nsec,
+                testTime1NanosecondsUT1);
+        return 10;
+    }
+
+    // Attempt to convert a TT time to UTC
+    time2 = NULL;
+    time1->sec = testTime1SecondsTT;
+    time1->nsec = testTime1NanosecondsTT;
+    time1->type = PS_TIME_TT;
+    time1->leapsecond = false;
+    time2 = psTimeConvert(time1,PS_TIME_UTC);
+    if(time2 != time1) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return time for conversion from TT to UTC");
+        return 17;
+    }
+    // Verify time type
+    if(time2->type != PS_TIME_UTC) {
+        psError(PS_ERR_UNKNOWN,true,"Returned time type %d not as expected %d",
+                time2->type, PS_TIME_UTC);
+        return 7;
+    }
+    // Verify time is UTC as expected
+    if(time2->sec != testTime1SecondsUTC) {
+        psError(PS_ERR_UNKNOWN,true,"UTC seconds = %ld not as expected %ld",(long int)time2->sec,
+                (long int)testTime1SecondsUTC);
+        return 18;
+    }
+    if(time2->nsec != testTime1NanosecondsUTC) {
+        psError(PS_ERR_UNKNOWN,true,"UTC nanoseconds = %ld not as expected %ld",(long int)time2->nsec,
+                (long int)testTime1NanosecondsUTC);
+        return 19;
+    }
+
+    // Attempt to convert a TT time to TAI
+    time2 = NULL;
+    time1->sec = testTime1SecondsTT;
+    time1->nsec = testTime1NanosecondsTT;
+    time1->type = PS_TIME_TT;
+    time1->leapsecond = false;
+    time2 = psTimeConvert(time1,PS_TIME_TAI);
+    if(time2 != time1) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return time for conversion from TT to TAI");
+        return 20;
+    }
+    // Verify time type
+    if(time2->type != PS_TIME_TAI) {
+        psError(PS_ERR_UNKNOWN,true,"Returned time type %d not as expected %d",
+                time2->type, PS_TIME_TAI);
+        return 7;
+    }
+    // Verify time is TAI as expected
+    if(time2->sec != testTime1SecondsTAI) {
+        psError(PS_ERR_UNKNOWN,true,"TAI seconds = %ld not as expected %ld",(long int)time2->sec,
+                (long int)testTime1SecondsTAI);
+        return 21;
+    }
+    if(time2->nsec != testTime1NanosecondsTAI) {
+        psError(PS_ERR_UNKNOWN,true,"TT nanoseconds = %ld not as expected %ld",(long int)time2->nsec,
+                (long int)testTime1NanosecondsTAI);
+        return 22;
+    }
+
+    // Attempt to convert a TT time to UT1
+    time2 = NULL;
+    time1->sec = testTime1SecondsTT;
+    time1->nsec = testTime1NanosecondsTT;
+    time1->type = PS_TIME_TT;
+    time1->leapsecond = false;
+    time2 = psTimeConvert(time1,PS_TIME_UT1);
+    if(time1 != time2) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return time for conversion from TT to UT1");
+        return 9;
+    }
+    // Verify time type
+    if(time2->type != PS_TIME_UT1) {
+        psError(PS_ERR_UNKNOWN,true,"Returned time type %d not as expected %d",
+                time2->type, PS_TIME_UT1);
+        return 7;
+    }
+    // Verify time is UT1 as expected
+    if(time2->sec != testTime1SecondsUT1) {
+        psError(PS_ERR_UNKNOWN,true,"UT1 seconds = %ld not as expected %ld",(long int)time2->sec,
+                (long int)testTime1SecondsUT1);
+        return 9;
+    }
+    if(time2->nsec != testTime1NanosecondsUT1) {
+        psError(PS_ERR_UNKNOWN,true,"UT1 nanoseconds = %d not as expected %d",time2->nsec,
+                testTime1NanosecondsUT1);
+        return 10;
+    }
+
+    // Attempt to convert from UT1 to TAI, UTC, TT
+    time2 = NULL;
+    time1->sec = 1;
+    time1->nsec = 2;
+    time1->type = PS_TIME_UT1;
+    time1->leapsecond = false;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message converting from UT1");
+    time2 = psTimeConvert(time1,PS_TIME_UTC);
+    if(time2 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return time for conversion from UT1");
+        return 23;
+    }
+
+    psFree(time1);
+
+    return 0;
+}
+
+//psS32 testTimeOther(void)
+//{
+//    psTime *testTime;
+//    char *testString = "2004-07-21T18:22:24.272Z";
+//
+//    psLibInit("pslib.config");
+//
+// Test time was taken at July 21, 2004 at 18:22:24.272044
+//    testTime = (psTime*)psAlloc(sizeof(psTime));
+//    testTime->sec = 1090434144;
+//    testTime->nsec = 272044000;
+//    testTime->type = PS_TIME_TAI;
+
+// Test O - psTime to LMST
+//    printPositiveTestHeader(stdout, "psTime", "Convert psTime time to LST");
+//    char *testString2 = "2004-09-10T1:00:00.00Z";
+//    psTime* testTime2 = NULL;
+//    testTime2 = psTimeFromISO(testString2);
+//    double dblTime = psTimeToLMST(testTime2, 1);
+//    printf("LST (rad): %lf\n", dblTime);
+//    psFree(testTime2);
+//    printFooter(stdout, "psTime", "Convert psTime time to LST", true);
+
+
+//    return 0;
+//}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psTime_02.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psTime_02.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psTime_02.c	(revision 22158)
@@ -0,0 +1,368 @@
+/** @file  tst_psTime_02.c
+ *
+ *  @brief Test driver for psTime functions
+ *
+ *  This test driver contains the following tests for psTime:
+ *     1) Convert psTime to Local Mean Sidereal Time (LMST)
+ *     2) Calculate leap second delta between times
+ *     3) Creation of psTime of type TT
+ *     4) Creation of psTime of type UTC
+ *
+ *  @author  Ross Harman, MHPCC
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2006-01-31 23:24:21 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+#define ERROR_TOL  0.001
+
+static psS32 testTimeLMST(void);
+static psS32 testTimeLeapSecondDelta(void);
+static psS32 testTimeIsLeapSecond(void);
+static psS32 testTimeFromTT(void);
+static psS32 testTimeFromUTC(void);
+
+// Test Time 1 : May 9, 2005  00:00:00,0
+//               MJD = 53499.000
+//               JD = 2453499.5
+// UTC Test Time 1
+const psS64 testTime1SecondsUTC     = 1115596900;
+const psU32 testTime1NanosecondsUTC = 0;
+// Expected LMST  15:09:18
+const psF64 testTime1LMST0          = 3.967604;
+
+// Test Time 2 : May 9, 1995 00:00:00,0
+//               MJD = 49846.00
+//               JD = 2449846.5
+// UTC Test Time 2
+const psS64 testTime2SecondsUTC     = 799977600;
+const psU32 testTime2NanosecondsUTC = 0;
+// Expected leap second delta
+const psS64 testTimeLeapSecondDelta1 = 3;
+
+// Test Time 3: Jan 1, 1999 00:00:00,0
+//              MJD = 51179
+//              JD = 2451179.5
+const psS64 testTime3SecondsUTC     = 915148800;
+const psU32 testTime3NanosecondsUTC = 0;
+
+testDescription tests[] = {
+                              {testTimeLMST,1,"psTimeToLMST",0,false},
+                              {testTimeLeapSecondDelta,2,"psTimeLeapSecondDelta",0,false},
+                              {testTimeIsLeapSecond,6,"psTimeIsLeapSecond",0,false},
+                              {testTimeFromTT,66,"psTimeFromTT",0,false},
+                              {testTimeFromUTC,666,"psTimeFromUTC",0,false},
+                              {NULL}
+                          };
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    // Initialize library internal structures
+    psLibInit("pslib.config");
+
+    if( !runTestSuite(stderr,"psTime",tests,argc,argv)) {
+        return 1;
+    }
+
+    // Clean up library
+    psLibFinalize();
+
+    return 0;
+}
+
+psS32 testTimeLMST(void)
+{
+    psTime*       time      = NULL;
+    psF64         lmst      = 0.0;
+
+    // Attempt to get LMST with NULL time
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL time");
+    lmst = psTimeToLMST(time,0);
+    if(!isnan(lmst)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NaN as expected %lf",lmst);
+        return 1;
+    }
+
+    // Attempt to get LMST with valid test time
+    // Allocate test time
+    time = psTimeAlloc(PS_TIME_UTC);
+    time->sec = testTime1SecondsUTC;
+    time->nsec = testTime1NanosecondsUTC;
+    time->leapsecond = false;
+    lmst = psTimeToLMST(time,0.0);
+    if(fabs(lmst-testTime1LMST0) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"LMST %lf not as expected %lf",lmst,testTime1LMST0);
+        return 2;
+    }
+
+    // Attempt to get LMST with invalid input time UT1
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for incorrect type");
+    time->type = PS_TIME_UT1;
+    lmst = psTimeToLMST(time,0.0);
+    if(!isnan(lmst)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NaN as expected %lf",lmst);
+        return 3;
+    }
+    psFree(time);
+
+    return 0;
+}
+
+psS32 testTimeLeapSecondDelta(void)
+{
+    psTime*       time1   = NULL;
+    psTime*       time2   = NULL;
+    psS64         delta   = 0;
+
+    // Attempt to get delta with NULL time1 argument
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL time");
+    delta = psTimeLeapSecondDelta(time1,time2);
+    if(delta != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Delta of %ld not as expected 0",(long int)delta);
+        return 1;
+    }
+
+    // Set test time 1
+    time1 = psTimeAlloc(PS_TIME_UTC);
+    time1->sec = testTime1SecondsUTC;
+    time1->nsec = testTime1NanosecondsUTC;
+    time1->leapsecond = false;
+
+    // Attempt to get delta with NULL time2 argument
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL time");
+    delta = psTimeLeapSecondDelta(time1,time2);
+    if(delta != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Delta of %ld not as expected 0",(long int)delta);
+        return 2;
+    }
+
+    // Set test time 2 with invalid time
+    time2 = psTimeAlloc(PS_TIME_UTC);
+    time2->sec = 0;
+    time2->nsec = 2e9;
+    time2->leapsecond = false;
+
+    // Attempt to get delta with invalid time2
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid time");
+    delta = psTimeLeapSecondDelta(time1,time2);
+    if(delta != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Delta of %ld not as expected 0",(long int)delta);
+        return 3;
+    }
+
+    // Set test time 2 valid
+    time2->sec = testTime2SecondsUTC;
+    time2->nsec = testTime2NanosecondsUTC;
+
+    // Set test time 1 invalid
+    time1->sec = 0;
+    time1->nsec = 2e9;
+
+    // Attempt to get delta with invalid time1
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid time");
+    delta = psTimeLeapSecondDelta(time1,time2);
+    if(delta != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Delta of %ld not as expected 0",(long int)delta);
+        return 4;
+    }
+
+    // Set test time 1 to greater time
+    time1->sec = testTime1SecondsUTC;
+    time1->nsec = testTime1NanosecondsUTC;
+    delta = psTimeLeapSecondDelta(time1,time2);
+    if(delta != testTimeLeapSecondDelta1) {
+        psError(PS_ERR_UNKNOWN,true,"Delta %ld not as expected %ld",
+                (long int)delta,(long int)testTimeLeapSecondDelta1);
+        return 5;
+    }
+
+    // Set test time 1 to lesser time
+    delta = psTimeLeapSecondDelta(time2,time1);
+    if(delta != testTimeLeapSecondDelta1) {
+        psError(PS_ERR_UNKNOWN,true,"Delta %ld not as expected %ld",
+                (long int)delta,(long int)testTimeLeapSecondDelta1);
+        return 6;
+    }
+
+    // Attempt to get delta with times equal
+    delta = psTimeLeapSecondDelta(time1,time1);
+    if(delta != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Delta %ld not as expected 0",(long int)delta);
+        return 7;
+    }
+
+    psFree(time2);
+    psFree(time1);
+
+    return 0;
+}
+
+psS32 testTimeIsLeapSecond(void)
+{
+    psTime*     time        = NULL;
+    psBool      leapsecond  = false;
+
+    // Attempt to determine if leap second with NULL time
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL time");
+    leapsecond = psTimeIsLeapSecond(time);
+    if(leapsecond) {
+        psError(PS_ERR_UNKNOWN,true,"Leapsecond flag %d not as expected 0",leapsecond);
+        return 1;
+    }
+
+    // Set time
+    time = psTimeAlloc(PS_TIME_TAI);
+    time->sec = testTime1SecondsUTC;
+    time->nsec = testTime1NanosecondsUTC;
+    time->leapsecond = false;
+
+    // Attempt to determine if leap second with non-UTC time
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid type");
+    leapsecond = psTimeIsLeapSecond(time);
+    if(leapsecond) {
+        psError(PS_ERR_UNKNOWN,true,"Leapsecond flag %d not as expected 0",leapsecond);
+        return 2;
+    }
+
+    // Set time to UTC
+    time->type = PS_TIME_UTC;
+
+    // Attempt to determine if leap second with valid time
+    leapsecond = psTimeIsLeapSecond(time);
+    if(leapsecond) {
+        psError(PS_ERR_UNKNOWN,true,"Leapsecond flag %d not a expected 0",leapsecond);
+        return 3;
+    }
+
+    // Set time to UTC with leap second
+    time->sec = testTime3SecondsUTC;
+    time->nsec = testTime3NanosecondsUTC;
+    leapsecond = psTimeIsLeapSecond(time);
+    if(!leapsecond) {
+        psError(PS_ERR_UNKNOWN,true,"Leapsecond flag %d not as expected 1",leapsecond);
+        //        return 4;
+    }
+
+    // Set time to 1 second before a known leap second
+    time->sec--;
+    leapsecond = psTimeIsLeapSecond(time);
+    if(leapsecond) {
+        psError(PS_ERR_UNKNOWN,true,"Leapsecond flag %d not as expected 0",leapsecond);
+        return 5;
+    }
+
+    // Set time to 1 second after a known leap second
+    time->sec +=2;
+    leapsecond = psTimeIsLeapSecond(time);
+    if(leapsecond) {
+        psError(PS_ERR_UNKNOWN,true,"Leapsecond flag %d not as expected 0",leapsecond);
+        return 6;
+    }
+
+    psFree(time);
+
+    return 0;
+}
+
+psS32 testTimeFromTT(void)
+{
+    psTime*       time = NULL;
+
+    // Attempt to create psTime with invalid time
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid time");
+    time = psTimeFromTT(0,2e9);
+    if(time != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL as expected");
+        return 1;
+    }
+
+    // Attempt to create psTime with valid time
+    time = psTimeFromTT(testTime1SecondsUTC,testTime1NanosecondsUTC);
+    if(time == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Return NULL when not expected");
+        return 2;
+    }
+    if(time->type != PS_TIME_TT) {
+        psError(PS_ERR_UNKNOWN,true,"Type of time object %d not as expected %d",
+                time->type,PS_TIME_TT);
+        return 3;
+    }
+    if((time->sec != testTime1SecondsUTC) || (time->nsec != testTime1NanosecondsUTC)) {
+        psError(PS_ERR_UNKNOWN,true,"Seconds %ld nanoseconds %d not as expected seconds %ld nanoseconds %d",
+                (long int)time->sec,time->nsec,(long int)testTime1SecondsUTC,testTime1NanosecondsUTC);
+        return 4;
+    }
+    psFree(time);
+
+    return 0;
+}
+
+psS32 testTimeFromUTC(void)
+{
+    psTime*       time = NULL;
+
+    // Attempt to create psTime with invalid time
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid time");
+    time = psTimeFromUTC(0,2e9,true);
+    if(time != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL as expected");
+        return 1;
+    }
+
+    // Attempt to create psTime with valid non-leapsecond time and leapsecond flag true
+    time = psTimeFromUTC(testTime1SecondsUTC,testTime1NanosecondsUTC,true);
+    if(time == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Return NULL when not expected");
+        return 2;
+    }
+    if(time->type != PS_TIME_UTC) {
+        psError(PS_ERR_UNKNOWN,true,"Type of time object %d not as expected %d",
+                time->type,PS_TIME_UTC);
+        return 3;
+    }
+    if((time->sec != testTime1SecondsUTC) || (time->nsec != testTime1NanosecondsUTC)) {
+        psError(PS_ERR_UNKNOWN,true,"Seconds %ld nanoseconds %d not as expected seconds %ld nanoseconds %d",
+                (long int)time->sec,time->nsec,(long int)testTime1SecondsUTC,testTime1NanosecondsUTC);
+        return 4;
+    }
+    if(time->leapsecond) {
+        psError(PS_ERR_UNKNOWN,true,"Leapsecond flag %d not as expected 0",time->leapsecond);
+        return 5;
+    }
+    psFree(time);
+
+    // Attempt to create psTime with valid leapsecond time but leapsecond flag false
+    time = psTimeFromUTC(testTime3SecondsUTC,testTime3NanosecondsUTC,false);
+    if(time == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Return NULL when not expected");
+        return 6;
+    }
+    if(time->type != PS_TIME_UTC) {
+        psError(PS_ERR_UNKNOWN,true,"Type of time object %d not as expected %d",
+                time->type,PS_TIME_UTC);
+        return 7;
+    }
+    if((time->sec != testTime3SecondsUTC) || (time->nsec != testTime3NanosecondsUTC)) {
+        psError(PS_ERR_UNKNOWN,true,"Seconds %ld nanoseconds %d not as expected seconds %ld nanoseconds %d",
+                (long int)time->sec,time->nsec,(long int)testTime1SecondsUTC,testTime1NanosecondsUTC);
+        return 8;
+    }
+    if(!time->leapsecond) {
+        psError(PS_ERR_UNKNOWN,true,"Leapsecond flag %d not as expected 1",time->leapsecond);
+        return 9;
+    }
+
+
+    psFree(time);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psTime_03.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psTime_03.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psTime_03.c	(revision 22158)
@@ -0,0 +1,505 @@
+/** @file  tst_psTime_03.c
+ *
+ *  @brief Test driver for psTime functions
+ *
+ *  This test driver contains the following tests for psTime:
+ *   1) psTimeMath invalid times
+ *   2) psTimeMath valid time of different types
+ *   3) psTimeDelta valid times with different types
+ *
+ *  @author  Ross Harman, MHPCC
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.4 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2006-06-27 20:33:22 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib_strict.h"
+#include "psTest.h"
+#include <string.h>
+
+#define ERROR_TOL    0.001
+
+static psS32 testTimeMath(void);
+static psS32 testTimeDelta(void);
+static psS32 testTimeConvert1(void);
+
+// Test Time 1 : May 9, 2005 00:00:00,0
+//               MJD = 53499.00
+//               JD = 2453499.5
+// UTC Test Time 1
+const psS64 testTime1SecondsUTC         = 1115596900;
+const psU32 testTime1NanosecondsUTC     = 0;
+// TAI Test Time 1
+const psS64 testTime1SecondsTAI         = 1115596932;
+const psU32 testTime1NanosecondsTAI     = 0;
+// TT Test Time 1
+const psS64 testTime1SecondsTT          = 1115596964;
+const psU32 testTime1NanosecondsTT      = 184000000;
+// UT1 Test Time 1
+const psS64 testTime1SecondsUT1         = 1115596900;
+const psU32 testTime1NanosecondsUT1     = 184000000;
+// Delta 1
+const psF64 deltaTime1                  = -15.5;
+// Expected UTC Time 1
+const psS64 newTestTime1SecondsUTC      = 1115596884;
+const psU32 newTestTime1NanosecondsUTC  = 500000000;
+// Expected TAI Time 1
+const psS64 newTestTime1SecondsTAI      = 1115596916;
+const psU32 newTestTime1NanosecondsTAI  = 500000000;
+// Delta 2
+const psF64 deltaTime2                  = 123.066;
+// Expected TT Time 1 w/ delta 2
+const psS64 newTestTime1SecondsTT       = 1115597087;
+const psU32 newTestTime1NanosecondsTT   = 250000000;
+// Expected UT1 Time 1 w/ delta 2
+const psS64 newTestTime1SecondsUT1      = 1115597023;
+const psU32 newTestTime1NanosecondsUT1  = 250000000;
+
+// Test Time 2 : Dec. 31 1998 23:59:45,0
+//               MJD = 51178.99983
+//               JD = 2451179.49983
+// UTC Test Time 1
+const psS64 testTime2SecondsUTC         = 915148785;
+const psU32 testTime2NanosecondsUTC     = 0;
+// Delta 3
+const psF64 deltaTime3                    = 30.0;
+// Expected UTC Time
+const psS64 newTestTime2SecondsUTC      = 915148814;
+const psU32 newTestTime2NanosecondsUTC  = 0;
+
+// Appendix B time conversion tests
+//
+#define APPB_TESTS    8
+const psS64 testTimeBSeconds[APPB_TESTS] =
+    {
+        915148829,
+        915148829,
+        915148830,
+        915148830,
+        915148831,
+        915148831,
+        915148832,
+        915148832
+    };
+const psU32 testTimeBNanoseconds[APPB_TESTS] =
+    {
+        0,
+        500000000,
+        0,
+        500000000,
+        0,
+        500000000,
+        0,
+        500000000
+    };
+const psBool testTimeBLeapsecond[APPB_TESTS] =
+    {
+        false,
+        false,
+        false,
+        false,
+        true,
+        true,
+        false,
+        false
+    };
+// Expected results
+const char* testTimeBStrUTC[APPB_TESTS] =
+    {
+        "1998-12-31T23:59:58.0Z",
+        "1998-12-31T23:59:58.5Z",
+        "1998-12-31T23:59:59.0Z",
+        "1998-12-31T23:59:59.5Z",
+        "1998-12-31T23:59:60.0Z",
+        "1998-12-31T23:59:60.5Z",
+        "1999-01-01T00:00:00.0Z",
+        "1999-01-01T00:00:00.5Z"
+    };
+const char* testTimeBStrTAI[APPB_TESTS] =
+    {
+        "1999-01-01T00:00:29.0Z",
+        "1999-01-01T00:00:29.5Z",
+        "1999-01-01T00:00:30.0Z",
+        "1999-01-01T00:00:30.5Z",
+        "1999-01-01T00:00:31.0Z",
+        "1999-01-01T00:00:31.5Z",
+        "1999-01-01T00:00:32.0Z",
+        "1999-01-01T00:00:32.5Z"
+    };
+const char* testTimeBStrTT[APPB_TESTS] =
+    {
+        "1999-01-01T00:01:01.1Z",
+        "1999-01-01T00:01:01.6Z",
+        "1999-01-01T00:01:02.1Z",
+        "1999-01-01T00:01:02.6Z",
+        "1999-01-01T00:01:03.1Z",
+        "1999-01-01T00:01:03.6Z",
+        "1999-01-01T00:01:04.1Z",
+        "1999-01-01T00:01:04.6Z"
+    };
+const char* testTimeBStrUT1[APPB_TESTS] =
+    {
+        "1998-12-31T23:59:58.7Z",
+        "1998-12-31T23:59:59.2Z",
+        "1998-12-31T23:59:59.7Z",
+        "1998-12-31T23:59:60.2Z",
+        "1998-12-31T23:59:60.7Z",
+        "1999-01-01T00:00:00.2Z",
+        "1999-01-01T00:00:00.7Z",
+        "1999-01-01T00:00:01.2Z"
+    };
+
+// Test Time B1 : Dec 31, 1998 23:59:58,0
+//                MJD = 51178.99998
+//                JD = 2451179.49998
+//const psS64 testTimeB1SecondsUTC        = 915148798;
+//const psU32 testTimeB1NanosecondsUTC    = 0;
+// Expected ISO times
+//const char testTimeB1StrUTC[] = "1998-12-31T23:59:58,0Z";
+//const char testTimeB1StrTAI[] = "1999-01-01T00:00:29,0Z";
+//const char testTimeB1StrTT[]  = "1999-01-01T00:01:01,1Z";
+//const char testTimeB1StrUT1[] = "1998-12-31T23:59:57,7Z";
+//
+// Test Time B2 : Dec 31, 1998 23:59:58,5
+//
+//
+//const psS64 testTimeB2SecondsUTC       = 915148798;
+//const psU32 testTimeB2NanosecondsUTC   = 500000000;
+// Expected ISO times
+//const char testTimeB2StrUTC[] = "1998-12-31T23:59:58,5Z";
+//const char testTimeB2StrTAI[] = "1991-01-01T00:00:29,5Z";
+//const char testTimeB2StrTT[]  = "1999-01-01T00:01:01,6Z";
+//const char testTimeB2StrUT1[] = "1998-12-31T23:59:58,2Z";
+
+testDescription tests[] = {
+                              {testTimeMath,1,"psTimeMath",0,false},
+                              {testTimeDelta,2,"psTimeDelta",0,false},
+                              {testTimeConvert1,666,"psTimeConvert",0,false},
+                              {NULL}
+                          };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    // Initialize library internal structures
+    psLibInit("pslib.config");
+
+    if( !runTestSuite(stderr,"psTime",tests,argc,argv)) {
+        return 1;
+    }
+
+    // Clean up library
+    psLibFinalize();
+
+    return 0;
+}
+
+psS32 testTimeMath(void)
+{
+    psTime*     time      = NULL;
+    psTime*     newTime   = NULL;
+
+    // Attempt to perform math operation on NULL time
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL time");
+    if(psTimeMath(time,-1.1) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL for NULL time");
+        return 1;
+    }
+
+    // Set up input time with invalid nanoseconds
+    time = psTimeAlloc(PS_TIME_UTC);
+    time->sec = 0;
+    time->nsec = 2e9;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid time");
+    if(psTimeMath(time,-1.1) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL for invalid time");
+        return 2;
+    }
+
+    // Set up input time with valid time
+    time->sec = testTime1SecondsUTC;
+    time->nsec = testTime1NanosecondsUTC;
+    newTime = psTimeMath(time,deltaTime1);
+    if(newTime == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return");
+        return 3;
+    }
+    if(newTime->type != PS_TIME_UTC) {
+        psError(PS_ERR_UNKNOWN,true,"New time type %d not as expected %d",
+                newTime->type,PS_TIME_UTC);
+        return 4;
+    }
+    if((newTime->sec != newTestTime1SecondsUTC) || (newTime->nsec != newTestTime1NanosecondsUTC)) {
+        psError(PS_ERR_UNKNOWN,true,"UTC sec %ld nsec %d not as expected sec %ld nsec %d",
+                (long int)newTime->sec,newTime->nsec,(long int)newTestTime1SecondsUTC,
+                newTestTime1NanosecondsUTC);
+        return 5;
+    }
+    psFree(newTime);
+
+    // Set up input time with valid TAI time
+    time->sec = testTime1SecondsTAI;
+    time->nsec = testTime1NanosecondsTAI;
+    time->type = PS_TIME_TAI;
+    newTime = psTimeMath(time,deltaTime1);
+    if(newTime == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return");
+        return 3;
+    }
+    if(newTime->type != PS_TIME_TAI) {
+        psError(PS_ERR_UNKNOWN,true,"New time type %d not as expected %d",
+                newTime->type,PS_TIME_TAI);
+        return 4;
+    }
+    if((newTime->sec != newTestTime1SecondsTAI) || (newTime->nsec != newTestTime1NanosecondsTAI)) {
+        psError(PS_ERR_UNKNOWN,true,"TAI sec %ld nsec %d not as expected sec %ld nsec %d",
+                (long int)newTime->sec,newTime->nsec,(long int)newTestTime1SecondsTAI,
+                newTestTime1NanosecondsTAI);
+        return 5;
+    }
+    psFree(newTime);
+
+    // Set up input time with valid TT time
+    time->sec = testTime1SecondsTT;
+    time->nsec = testTime1NanosecondsTT;
+    time->type = PS_TIME_TT;
+    newTime = psTimeMath(time,deltaTime2);
+    if(newTime == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return");
+        return 3;
+    }
+    if(newTime->type != PS_TIME_TT) {
+        psError(PS_ERR_UNKNOWN,true,"New time type %d not as expected %d",
+                newTime->type,PS_TIME_TT);
+        return 4;
+    }
+    if((newTime->sec != newTestTime1SecondsTT) || (newTime->nsec != newTestTime1NanosecondsTT)) {
+        psError(PS_ERR_UNKNOWN,true,"TT sec %ld nsec %d not as expected sec %ld nsec %d",
+                (long int)newTime->sec,newTime->nsec,(long int)newTestTime1SecondsTT,
+                newTestTime1NanosecondsTT);
+        return 5;
+    }
+    psFree(newTime);
+
+    // Set up input time with valid TT time
+    time->sec = testTime1SecondsUT1;
+    time->nsec = testTime1NanosecondsUT1;
+    time->type = PS_TIME_UT1;
+    newTime = psTimeMath(time,deltaTime2);
+    if(newTime == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return");
+        return 3;
+    }
+    if(newTime->type != PS_TIME_UT1) {
+        psError(PS_ERR_UNKNOWN,true,"New time type %d not as expected %d",
+                newTime->type,PS_TIME_UT1);
+        return 4;
+    }
+    if((newTime->sec != newTestTime1SecondsUT1) || (newTime->nsec != newTestTime1NanosecondsUT1)) {
+        psError(PS_ERR_UNKNOWN,true,"UT1 sec %ld nsec %d not as expected sec %ld nsec %d",
+                (long int)newTime->sec,newTime->nsec,(long int)newTestTime1SecondsUT1,
+                newTestTime1NanosecondsUT1);
+        return 5;
+    }
+    psFree(newTime);
+
+    // Set up input time with valid UTC time and delt which crosses leap second
+    time->sec = testTime2SecondsUTC;
+    time->nsec = testTime2NanosecondsUTC;
+    time->type = PS_TIME_UTC;
+    newTime = psTimeMath(time,deltaTime3);
+    if(newTime == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return");
+        return 3;
+    }
+    if(newTime->type != PS_TIME_UTC) {
+        psError(PS_ERR_UNKNOWN,true,"New time type %d not as expected %d",
+                newTime->type,PS_TIME_UTC);
+        return 4;
+    }
+    if((newTime->sec != newTestTime2SecondsUTC) || (newTime->nsec != newTestTime2NanosecondsUTC)) {
+        psError(PS_ERR_UNKNOWN,true,"UTC sec %ld nsec %d not as expected sec %ld nsec %d",
+                (long int)newTime->sec,newTime->nsec,(long int)newTestTime2SecondsUTC,
+                newTestTime2NanosecondsUTC);
+        return 5;
+    }
+    psFree(newTime);
+
+    psFree(time);
+
+    return 0;
+}
+
+psS32 testTimeDelta(void)
+{
+    psTime*   time1   = NULL;
+    psTime*   time2   = NULL;
+    psF64     delta   = 0.0;
+
+    // Attempt to get delta with time1 NULL
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL time");
+    delta = psTimeDelta(time1,time2);
+    if(fabs(delta-0.0) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return 0 for NULL time argument");
+        return 1;
+    }
+
+    // Set time 1
+    time1 = psTimeAlloc(PS_TIME_UTC);
+
+    // Attempt to get delta with time2 NULL
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL time");
+    delta = psTimeDelta(time1,time2);
+    if(fabs(delta-0.0) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return 0 for NULL time argument");
+        return 2;
+    }
+
+    // Set time 2
+    time2 = psTimeAlloc(PS_TIME_UTC);
+
+    // Set time1 invalid
+    time1->sec = 0;
+    time1->nsec = 2e9;
+    // Attempt to get delta with time1 invalid
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid time");
+    delta = psTimeDelta(time1,time2);
+    if(fabs(delta-0.0) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return 0 for invalid time argument");
+        return 3;
+    }
+
+    // Set time 1 valid
+    time1->sec = testTime1SecondsUTC;
+    time1->nsec = testTime1NanosecondsUTC;
+
+    // Set time 2 invalid
+    time2->sec = 0;
+    time2->nsec = 2e9;
+    // Attempt to get delta with time2 invalid
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid time");
+    delta = psTimeDelta(time1,time2);
+    if(fabs(delta-0.0) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return 0 for invalid time argument");
+        return 4;
+    }
+
+    // Set time 2 valid but different type
+    time2->sec = newTestTime1SecondsUTC;
+    time2->nsec = newTestTime1NanosecondsUTC;
+    time2->type = PS_TIME_TAI;
+    // Attempt to get delta with different time types
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for incorrect type");
+    delta = psTimeDelta(time1,time2);
+    if(fabs(delta-0.0) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return 0 for invalid time argument");
+        return 5;
+    }
+
+    // Set time 2 to same as time 1
+    time2->type = PS_TIME_UTC;
+    // Attempt to get delta with valid times of the same type
+    delta = psTimeDelta(time2,time1);
+    if(fabs(delta-deltaTime1) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Delta %lf not as expected %lf",
+                delta,deltaTime1);
+        return 6;
+    }
+
+    // Set time 1 and 2 as different times with same type
+    time1->sec = testTime1SecondsTT;
+    time1->nsec = testTime1NanosecondsTT;
+    time1->type = PS_TIME_TT;
+    time2->sec = newTestTime1SecondsTT;
+    time2->nsec = newTestTime1NanosecondsTT;
+    time2->type = PS_TIME_TT;
+    // Attempt to get delta with valid times of the same type
+    delta = psTimeDelta(time2,time1);
+    if(fabs(delta-deltaTime2) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Delta %lf not as expected %lf",
+                delta,deltaTime2);
+        return 7;
+    }
+
+    // Set time 1 and 2 as different times with same type
+    time1->sec = testTime2SecondsUTC;
+    time1->nsec = testTime2NanosecondsUTC;
+    time1->type = PS_TIME_UTC;
+    time2->sec = newTestTime2SecondsUTC;
+    time2->nsec = newTestTime2NanosecondsUTC;
+    time2->type = PS_TIME_UTC;
+    // Attempt to get delta with valid times of the same type
+    delta = psTimeDelta(time2,time1);
+    if(fabs(delta-deltaTime3) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Delta %lf not as expected %lf",
+                delta,deltaTime3);
+        return 7;
+    }
+
+    psFree(time1);
+    psFree(time2);
+
+    return 0;
+}
+
+psS32 testTimeConvert1(void)
+{
+    psTime*     time    = NULL;
+    char*       timeStr = NULL;
+
+    for(psS32 i = 0; i < APPB_TESTS; i++) {
+
+        // Initialize time for test time B1
+        time = psTimeAlloc(PS_TIME_TAI);
+        time->sec = testTimeBSeconds[i];
+        time->nsec = testTimeBNanoseconds[i];
+
+        // Verify TAI ISO string
+        timeStr = psTimeToISO(time);
+        if(strcmp(timeStr,testTimeBStrTAI[i]) != 0) {
+            psError(PS_ERR_UNKNOWN,true,"TAI ISO string %s not as expected %s",timeStr,testTimeBStrTAI[i]);
+            return i+1;
+        }
+        psFree(timeStr);
+
+        time = psTimeConvert(time,PS_TIME_TT);
+        timeStr = psTimeToISO(time);
+        if(strcmp(timeStr,testTimeBStrTT[i]) != 0) {
+            psError(PS_ERR_UNKNOWN,true,"TT ISO string %s not as expected %s",timeStr,testTimeBStrTT[i]);
+            return i+10;
+        }
+        psFree(timeStr);
+
+        // Verify UTC ISO string
+        time = psTimeConvert(time,PS_TIME_UTC);
+        time->leapsecond = testTimeBLeapsecond[i];
+        timeStr = psTimeToISO(time);
+        if(strcmp(timeStr,testTimeBStrUTC[i]) != 0) {
+            if(strncmp(timeStr,"1999-01-01T00:00:60.0Z", 10) != 0) {
+                psError(PS_ERR_UNKNOWN,true,"UTC ISO string %s not as expected %s",timeStr,testTimeBStrUTC[i]);
+                return i+20;
+            }
+        }
+        psFree(timeStr);
+
+        time = psTimeConvert(time,PS_TIME_UT1);
+        timeStr = psTimeToISO(time);
+        if(strcmp(timeStr,testTimeBStrUT1[i]) != 0) {
+            if(strncmp(timeStr,"1999-01-01T00:00:60.2Z", 10) != 0) {
+                psError(PS_ERR_UNKNOWN,true,"UT1 ISO string %s not as expected %s",timeStr,testTimeBStrUT1[i]);
+                return i+30;
+            }
+        }
+        psFree(timeStr);
+
+        psFree(time);
+    }
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psTime_04.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psTime_04.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/astro/tst_psTime_04.c	(revision 22158)
@@ -0,0 +1,177 @@
+/** @file  tst_psTime_04.c
+ *
+ *  @brief Test driver for psTime functions
+ *
+ *  This test driver contains the following tests for psTime:
+ *      Test A - Initialize time
+ *      Test B - Attempt to open non-existant time config file
+ *      Test C - Attempt to open non-existant time data files
+ *      Test D - Attempt to read incorrect number of files
+ *      Test E - Attempt to read incorrect number of from values
+ *      Test F - Attempt to read data file with typo in number
+ *      Test G - Free data
+ *      Test H - Attempt to use all timer functions
+ *      Test I - Tidal Corrections to UT1-UTC
+ *
+ *  @author  Ross Harman, MHPCC
+ *  @author  Eric Van Alst, MHPCC
+ *  @author  David Robbins, MHPCC
+ *
+ *  @version $Revision: 1.9 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2006-01-31 23:24:21 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include "config.h"
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+static psS32 testTimeInit1(void);
+static psS32 testTimeInit2(void);
+static psS32 testTimeInit3(void);
+static psS32 testTimeInit4(void);
+static psS32 testTimeInit5(void);
+static psS32 testTimeInit6(void);
+static psS32 testTimer1(void);
+static psS32 testTideUT1Corr(void);
+
+testDescription tests[] = {
+                              {testTimeInit1,1,"p_psTimeInit",0,false},
+                              {testTimeInit2,2,"p_psTimeInit",0,false},
+                              {testTimeInit3,3,"p_psTimeInit",0,false},
+                              {testTimeInit4,4,"p_psTimeInit",0,false},
+                              {testTimeInit5,5,"p_psTimeInit",0,false},
+                              {testTimeInit6,6,"p_psTimeInit",0,false},
+                              {testTimer1,8,"psTimer",0,false},
+                              {testTideUT1Corr,9,"psTime_TideUT1Corr",0,false},
+                              {NULL}
+                          };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    if(!runTestSuite(stderr,"psTime",tests,argc,argv)) {
+        return 1;
+    }
+
+    return 0;
+}
+
+psS32 testTimeInit1(void)
+{
+    // Test A - Initialize time
+    psLibInit("pslib.config");
+    psLibFinalize();
+
+    return 0;
+}
+
+psS32 testTimeInit2(void)
+{
+    // Test B - Attempt to open non-existant time config file
+    psLibInit("zzz");
+
+    return 0;
+}
+
+psS32 testTimeInit3(void)
+{
+    // Test C - Attempt to open non-existant time data files
+    psLibInit("test.psTime.config1");
+    psLibFinalize();
+
+    return 0;
+}
+
+psS32 testTimeInit4(void)
+{
+    // Test D - Attempt to read incorrect number of files
+    psLibInit("test.psTime.config2");
+    psLibFinalize();
+
+    return 0;
+}
+
+psS32 testTimeInit5(void)
+{
+    // Test E - Attempt to read incorrect number of from values
+    psLibInit("test.psTime.config3");
+    psLibFinalize();
+
+    return 0;
+}
+
+psS32 testTimeInit6(void)
+{
+    // Test F - Attempt to read data file with typo in number
+    psLibInit("test.psTime.config4");
+    psLibFinalize();
+
+    return 0;
+}
+
+psS32 testTimer1(void)
+{
+    psF64 testTime = 0.0;
+    psF64 testTime2 = 0.0;
+    psF64 testTime3 = 0.0;
+
+    if ( !psTimerStart("newTime") ) {
+        printf("TimerStart Failed\n");
+        return 1;
+    }
+    testTime = psTimerMark("newTime");
+    if (testTime == 0.0) {
+        printf("TimerMark Failed\n");
+        return 2;
+    }
+    testTime2 = psTimerClear("newTime");
+    if (testTime2 == 0.0) {
+        printf("TimerClear Failed\n");
+        return 3;
+    }
+    psTimerStart("newTime");
+    testTime3 = psTimerStop();
+    if (testTime3 == 0.0) {
+        printf("TimerStop Failed\n");
+        return 4;
+    }
+    return 0;
+}
+
+psS32 testTideUT1Corr(void)
+{
+    psTime *empty = NULL;
+    psTime *tide = NULL;
+    psTime *noTide = psTimeAlloc(PS_TIME_UTC);
+    noTide->sec = 1049160600;
+    noTide->nsec = 0;
+    noTide->leapsecond = false;
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    empty = psTime_TideUT1Corr(tide);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psTime_TideUT1Corr failed to return NULL for NULL input time.\n");
+        return 1;
+    }
+
+    empty = psTime_TideUT1Corr(noTide);
+    if (empty->sec != 1049160599 || empty->nsec != 656981971) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psTime_TideUT1Corr failed to return correct values.\n");
+        printf("\nsec = %ld, nsec = %u\n", (long int)empty->sec, empty->nsec);
+        return 2;
+    }
+
+    if (!p_psTimeFinalize()) {
+        return 3;
+    }
+
+    psFree(empty);
+    psFree(noTide);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/db/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/db/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/db/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+temp
+.deps
+.libs
+Makefile
+Makefile.in
+tst_psDB
+*.bb
+*.bbg
+*.da
+gmon.out
+tap_psDB
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/db/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/db/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/db/Makefile.am	(revision 22158)
@@ -0,0 +1,39 @@
+AM_CPPFLAGS = \
+        $(SRCINC) \
+        -I$(top_srcdir)/test/tap/src \
+        -I$(top_srcdir)/test/pstap/src \
+        $(PSLIB_CFLAGS)
+
+AM_LDFLAGS = \
+        $(top_builddir)/src/libpslib.la  \
+        $(top_builddir)/test/tap/src/libtap.la \
+        $(top_builddir)/test/pstap/src/libpstap.la \
+        $(PSLIB_LIBS)
+
+TEST_PROGS = \
+	tap_psDB
+
+if BUILD_TESTS
+bin_PROGRAMS = $(TEST_PROGS)
+TESTS = $(TEST_PROGS)
+else
+check_PROGRAMS = $(TEST_PROGS)
+endif
+
+CLEANFILES = $(check_DATA) temp/* core core.* *~ *.bb *.bbg *.da gmon.out
+
+clean-local:
+	mysql test -e "drop table1" 2> /dev/null || \
+	mysql test -e "drop table2" 2> /dev/null || \
+	mysql test -e "drop table3" 2> /dev/null || \
+	mysql test -e "drop table4" 2> /dev/null || \
+	mysql test -e "drop table5" 2> /dev/null || \
+	mysql test -e "drop table6" 2> /dev/null || \
+	mysql test -e "drop table7" 2> /dev/null || \
+	mysql test -e "drop table8" 2> /dev/null || \
+	mysql test -e "drop table9" 2> /dev/null || \
+	mysql test -e "drop table10" 2> /dev/null || \
+	mysql test -e "drop table11" 2> /dev/null || \
+	true
+
+test: check
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/db/tap_psDB.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/db/tap_psDB.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/db/tap_psDB.c	(revision 22158)
@@ -0,0 +1,266 @@
+/** @file  tap_psDB.c
+ *
+ *  @brief Contains the tests for psDB.[ch]
+ *
+ *  @author Aaron Culliney, MHPCC
+ *  @author Joshua Hoblitt, University of Hawaii
+ *
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-03-27 22:52:02 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include <string.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+#include "pslib.h"
+
+#define HOST    "localhost"
+#define USER    "test"
+#define PASSWD  ""
+#define DBNAME  "test"
+#define PORT    0
+
+int main(int argc, char* argv[])
+{
+#if DEBUG
+    psTraceSetLevel("psLib.db", 10);
+    psTraceSetLevel("err", 10);
+#endif
+
+    plan_tests(34 + 1);
+
+    // see if we can open a db connection at all
+    {
+        psDB *dbh = psDBInit(HOST, USER, PASSWD, DBNAME, PORT);
+        ok(dbh, "open a database handle");
+        if (!dbh) {
+            done();
+        }
+        psFree(dbh);
+    }
+
+    // test new database creation
+    // the next 3 tests will fail as the MySQL test account has insufficent
+    // permissions
+    {
+        psDB *dbh = psDBInit(HOST, USER, PASSWD, DBNAME, PORT);
+
+        skip_start(!psDBCreate(dbh, "foobar"), 4,
+                "you probably don't have proper database permissions");
+        ok(psDBCreate(dbh, "foobar"), "psDBCreate()");
+        ok(psDBChange(dbh, "foobar"), "psDBChange()");
+        ok(psDBDrop(dbh, "foobar"), "psDBDrop()");
+        // change back to the test dbname
+        ok(psDBChange(dbh, DBNAME), "psDBChange()");
+        skip_end();
+
+        psFree(dbh);
+    }
+
+    // psDBCreateTable() & psDBDropTable()
+    {
+        psDB *dbh = psDBInit(HOST, USER, PASSWD, DBNAME, PORT);
+        psMetadata *md = psMetadataAlloc();
+        psMetadataAdd(md, PS_LIST_TAIL, "foo", PS_DATA_S32, "Primary Key", 0);
+        psMetadataAdd(md, PS_LIST_TAIL, "bar", PS_DATA_BOOL, "Key", false);
+        psMetadataAdd(md, PS_LIST_TAIL, "baz", PS_DATA_F64,  NULL, 0.0);
+        psMetadataAdd(md, PS_LIST_TAIL, "boing", PS_DATA_STRING, NULL, "60");
+
+        ok(psDBCreateTable(dbh, "bar", md), "psDBCreateTable() - create table");
+        psFree(md);
+
+        ok(psDBDropTable(dbh, "bar"), "psDBDropTable() - drop table");
+
+        psFree(dbh);
+    }
+
+    {
+        psDB *dbh = psDBInit(HOST, USER, PASSWD, DBNAME, PORT);
+        psMetadata *md = psMetadataAlloc();
+        psMetadataAdd(md, PS_LIST_TAIL, "foo", PS_TYPE_S32, "Primary Key", 0);
+        psDBCreateTable(dbh, "bar", md);
+
+        ok(!psDBCreateTable(dbh, "bar", md), "psDBCreateTable() - table already exists");
+
+        psFree(md);
+
+        psDBDropTable(dbh, "bar");
+
+        ok(!psDBDropTable(dbh, "fubar"), "psDBDropTable() - non-existant table");
+        psFree(dbh);
+    }
+
+    {
+        psDB *dbh = psDBInit(HOST, USER, PASSWD, DBNAME, PORT);
+
+        // setup yak table for later tests
+        {
+            psMetadata *md = psMetadataAlloc();
+            psMetadataAdd(md, PS_LIST_TAIL, "hair", PS_TYPE_F32, NULL, 0.0);
+            psDBCreateTable(dbh, "yak", md);
+            psFree(md);
+        }
+
+        // setup horse table for later tests
+        {
+            psMetadata *md = psMetadataAlloc();
+            psMetadataAdd(md, PS_LIST_TAIL, "color", PS_DATA_STRING, NULL, "100");
+            psDBCreateTable(dbh, "horse", md);
+            psFree(md);
+        }
+
+        // psDBInsertOneRow()
+        {
+            psMetadata *md = psMetadataAlloc();
+            psMetadataAdd(md, PS_LIST_TAIL, "hair", PS_TYPE_F32, NULL, 10e3);
+
+            ok(psDBInsertOneRow(dbh, "yak", md),"psDBInsertOneRow() - number");
+
+            psFree(md);
+        }
+
+        {
+            psMetadata *md = psMetadataAlloc();
+            psMetadataAdd(md, PS_LIST_TAIL, "hair", PS_TYPE_F32, NULL, NAN);
+            ok(psDBInsertOneRow(dbh, "yak", md),"psDBInsertOneRow() - nan");
+
+            psFree(md);
+        }
+
+        // psDBInsertRows()
+        {
+            psArray *rowSet = psArrayAllocEmpty(3);
+            psMetadata *row = psMetadataAlloc();
+            psMetadataAdd(row, PS_LIST_TAIL, "color", PS_DATA_STRING, NULL, "brown");
+            psArrayAdd(rowSet, 0, row);
+            psFree(row);
+
+            row = psMetadataAlloc();
+            psMetadataAdd(row, PS_LIST_TAIL, "color", PS_DATA_STRING, NULL, NULL);
+            psArrayAdd(rowSet, 0, row);
+            psFree(row);
+
+            row = psMetadataAlloc();
+            psMetadataAdd(row, PS_LIST_TAIL, "color", PS_DATA_STRING, NULL, "pink");
+            psArrayAdd(rowSet, 0, row);
+            psFree(row);
+
+            ok(psDBInsertRows(dbh, "horse", rowSet), "psDBInsertRows() - multi-row insert");
+
+            psFree(rowSet);
+        }
+
+        // psDBSelectColumn()
+        {
+            psArray *column = psDBSelectColumn(dbh, "horse", "color", 42);
+            ok(column, "psDBSelectColumn() - select");
+            is_long(psArrayLength(column), 3, "psDBSelectColumn() - number of elements");
+
+            // XXX this test is depending on the order the rows come out it...
+            // this shouldn't be depended upon
+            is_str((char *)column->data[0], "brown", "horse.color == 'brown'");
+            ok((char *)column->data[1] == NULL,    "horse.color == NULL");
+            is_str((char *)column->data[2], "pink",  "horse.color == 'pink'");
+
+            psFree(column);
+        }
+
+        // psDBSelectColumnNum()
+        {
+            psVector *column = psDBSelectColumnNum(dbh, "yak", "hair", PS_TYPE_F32, 42);
+            ok(column, "psDBSelectColumnNum() - select");
+            is_long(psVectorLength(column), 2, "psDBSelectColumnNum() - number of elements");
+
+            is_float(column->data.F32[0], 10e3, "hair == 10e3")
+            is_float(column->data.F32[1], NAN, "hair == NAN")
+
+            psFree(column);
+        }
+
+        // psDBSelectRows()
+        {
+            psMetadata *md = psMetadataAlloc();
+            psMetadataAdd(md, PS_LIST_TAIL, "color", PS_DATA_STRING, NULL, "brown");
+
+            psArray *resultSet = psDBSelectRows(dbh, "horse", md, 0);
+            ok(resultSet, "psDBSelectRows() - select");
+            is_long(psArrayLength(resultSet), 1, "psDBSelectRows() - number of rows");
+
+            psFree(md);
+            for (long i = 0; i < resultSet->n; i++) {
+                md = (psMetadata *)resultSet->data[0];
+
+                psMetadataItem *item = psListGet(md->list, 0);
+                is_str(item->name, "color", "column name");
+                is_str((char *)item->data.V, "brown", "column value");
+            }
+            psFree(resultSet);
+
+        }
+
+        // psDBDumpRows()
+        {
+            psArray *resultSet = psDBDumpRows(dbh, "horse");
+            ok(resultSet, "psDBDumpRows() - dump");
+            ok(psArrayLength(resultSet) == 3, "psDBDumpRows() - number of rows");
+            psFree(resultSet);
+        }
+
+        // psDBDumpCols()
+        {
+            psMetadata *columns = psDBDumpCols(dbh, "horse");
+            ok(columns, "psDBDumpCols() - dump");
+            ok(psListLength(columns->list) == 1, "psDBDumpCols() - number of columns");
+
+            psMetadataItem *item = psListGet(columns->list, 0);
+            is_str(item->name, "color", "column name");
+            is_long(psArrayLength((psArray*)item->data.V), 3, "column array length");
+
+            psFree(columns);
+        }
+
+        // psDBUpdateRows()
+        {
+            psMetadata *where = psMetadataAlloc();
+            psMetadataAdd(where, PS_LIST_TAIL, "color", PS_DATA_STRING, NULL, "pink");
+
+            psMetadata *value = psMetadataAlloc();
+            psMetadataAdd(value, PS_LIST_TAIL, "color", PS_DATA_STRING, NULL, "HOT pink");
+
+            psU64 rowsAffected = psDBUpdateRows(dbh, "horse", where, value);
+            psFree(where);
+
+            ok(rowsAffected, "psDBUpdateRows() - pink -> HOT pink");
+
+            psArray *resultSet = psDBSelectRows(dbh, "horse", value, 0);
+            psFree(value);
+
+            for (long i = 0; i < resultSet->n; i++) {
+                psMetadata *md = (psMetadata *)resultSet->data[0];
+
+                psMetadataItem *item = psListGet(md->list, 0);
+                is_str((char *)item->data.V, "HOT pink", "psDBUpdateRows() - psDBSelectRows() found HOT pink");
+
+            }
+
+            psFree(resultSet);
+        }
+
+        // psDBDeleteRows()
+        ok(psDBDeleteRows(dbh, "yak", NULL, 0), "psDBDeleteRows()");
+
+        // cleanup other tests
+        psDBDropTable(dbh, "horse");
+        psDBDropTable(dbh, "yak");
+
+        psFree(dbh);
+    }
+
+
+    done();
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/db/tst_psDB.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/db/tst_psDB.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/db/tst_psDB.c	(revision 22158)
@@ -0,0 +1,2224 @@
+/** @file  tst_psDB.c
+ *
+ * -*- mode: C; c-basic-indent: 4; tab-width: 8; indent-tabs-mode: nil -*-
+ * vim: set cindent ts=8 sw=4 expandtab:
+ *
+ *  @brief Contains the tests for psDB.[ch]
+ *
+ *
+ *  @author Aaron Culliney, MHPCC
+ *
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-04-20 01:13:11 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "psTest.h"
+#include "pslib_strict.h"
+
+#define STR_1 "hello world!"
+#define STR_2 "foobar"
+#define S32_1 1974
+#define S32_2 -18
+#define F32_1 3.14159
+#define F32_2 3.33
+#define F64_1 2.7182818
+#define F64_2 1.23456789
+#define B_1 TRUE
+#define B_2 FALSE
+
+#define ERROR_TOL   0.001
+
+#define CONST_ROW_1_STR      "randrow1"
+#define CONST_ROW_1_S32      12345
+#define CONST_ROW_1_F32      9876.5
+#define CONST_ROW_1_F64      456.75
+#define CONST_ROW_1_BOOL     TRUE
+
+#define CONST_ROW_2_STR      "randrow2"
+#define CONST_ROW_2_S32      2345
+#define CONST_ROW_2_F32      876.5
+#define CONST_ROW_2_F64      56.75
+#define CONST_ROW_2_BOOL     FALSE
+
+#define TAB_COL_0_NAME      "key_string"
+#define TAB_COL_1_NAME      "key_s32"
+#define TAB_COL_2_NAME      "key_f32"
+#define TAB_COL_3_NAME      "key_f64"
+#define TAB_COL_4_NAME      "key_bool"
+#define TAB_COL_5_NAME      "key_s32_0"
+
+static psDB *_init_psDB( void );
+static psMetadata *_get_CreateTableMetadata( void );
+static psMetadata *_get_RowMetadataValues(const char *val0, psS32 val1, psF32 val2, psF64 val3, psBool val4);
+static psMetadata *_get_RowMetadata(
+    const char *key0, const char *comm0, const char *val0,
+    const char *key1, const char *comm1, psS32  val1,
+    const char *key2, const char *comm2, psF32  val2,
+    const char *key3, const char *comm3, psF64  val3,
+    const char *key4, const char *comm4, psBool val4,
+    const char *key5, const char *comm5, psS32  val5);
+static psMetadata *_get_row( void );
+static psMetadata *_get_invalid_row( void );
+static psMetadata *_get_where( void );
+static psMetadata *_get_invalid_where( void );
+static psMetadata *_get_where_bad_value( void );
+static psMetadata *_get_update_values(const char *val0, psS32 val1, psF32 val2, psF64 val3, psBool val4);
+static bool _check_row(psMetadata* row);
+static bool _check_row_update(psMetadata* row);
+static bool _check_const_row1(psMetadata* row);
+static bool _check_const_row2(psMetadata* row);
+
+//static psS32 TPDBCreate( void );
+//static psS32 TPDBDrop( void );
+static psS32 TPDBInit( void );
+static psS32 TPDBChange( void );
+static psS32 TPDBCreateTable( void );
+static psS32 TPDBDropTable( void );
+static psS32 TPDBSelectColumn( void );
+static psS32 TPDBSelectColumnNum( void );
+static psS32 TPDBSelectRows( void );
+static psS32 TPDBInsertOneRow( void );
+static psS32 TPDBInsertRows( void );
+static psS32 TPDBDumpRows( void );
+static psS32 TPDBDumpCols( void );
+static psS32 TPDBUpdateRows( void );
+static psS32 TPDBDeleteRows( void );
+
+testDescription tests[] = {
+                              {TPDBInit,           841,  "dbInit",            0, false},
+                              {TPDBChange,         842,  "dbChange",          0, false},
+                              {TPDBCreateTable,    843,  "dbCreateTable",     0, false},
+                              {TPDBDropTable,      844,  "dbDropTable",       0, false},
+                              {TPDBSelectColumn,   845,  "dbSelectColumn",    0, false},
+                              {TPDBSelectColumnNum,846,  "dbSelectColumnNum", 0, false},
+                              {TPDBSelectRows,     847,  "dbSelectRows",      0, false},
+                              {TPDBInsertOneRow,   848,  "dbInsertOneRow",    0, false},
+                              {TPDBInsertRows,     849,  "dbInsertRows",      0, false},
+                              {TPDBDumpRows,       850,  "dbDumpRows",        0, false},
+                              {TPDBDumpCols,       851,  "dbDumpCols",        0, false},
+                              {TPDBUpdateRows,     852,  "dbUpdateRows",      0, false},
+                              {TPDBDeleteRows,     853,  "dbDeleteRows",      0, false},
+                              //{TPDBCreate,        -14, "dbCreate",          0, false},
+                              //{TPDBDrop,          -15, "dbDrop",            0, false},
+                              {NULL}
+                          };
+
+static const char *host    = "localhost";
+static const char *user    = "test";
+static const char *passwd  = "";
+static const char *dbname  = "test";
+
+// internal method to initialize DB
+psDB *_init_psDB( void )
+{
+    psDB *dbh = NULL;
+
+    // Initialize database connection with test database
+    dbh = psDBInit(host, user, passwd, dbname);
+    if (dbh == NULL) {
+        psError(PS_ERR_UNKNOWN, true, "could not initialize DB connection in %s!", __func__ );
+    }
+
+    return dbh;
+}
+
+psMetadata *_get_CreateTableMetadata( void )
+{
+    return _get_RowMetadata(
+               TAB_COL_0_NAME, "comment-string",     "90000", // value used to determine size of field
+               TAB_COL_1_NAME,    "Primary Key",        0,       // values unused here ...
+               TAB_COL_2_NAME,    "Key",                0.0,
+               TAB_COL_3_NAME,    "",                   0.0,
+               TAB_COL_4_NAME,   "",                   FALSE,
+               TAB_COL_5_NAME,  "Key,AUTO_INCREMENT", 0);
+}
+
+psMetadata *_get_RowMetadataValues(const char *val0, psS32 val1, psF32 val2, psF64 val3, psBool val4)
+{
+    return _get_RowMetadata(
+               TAB_COL_0_NAME, "comment-string", val0,
+               TAB_COL_1_NAME,    "comment-s32",    val1,
+               TAB_COL_2_NAME,    "comment-f32",    val2,
+               TAB_COL_3_NAME,    "comment-f64",    val3,
+               TAB_COL_4_NAME,   "comment-bool",   val4,
+               NULL,         NULL,             0.0);
+}
+
+psMetadata *_get_RowMetadata(
+    const char *key0, const char *comm0, const char *val0,
+    const char *key1, const char *comm1, psS32  val1,
+    const char *key2, const char *comm2, psF32  val2,
+    const char *key3, const char *comm3, psF64  val3,
+    const char *key4, const char *comm4, psBool val4,
+    const char *key5, const char *comm5, psS32  val5)
+{
+    psMetadata *md = NULL;
+    psMetadataItem *str=NULL, *s32_0=NULL, *s32=NULL, *f32=NULL, *f64=NULL, *b;
+
+    md = psMetadataAlloc();
+    if (md == NULL) {
+        psError(PS_ERR_UNKNOWN, true, "could not create psMetadata in %s!", __func__ );
+        return NULL;
+    }
+    if (key0 != NULL) {
+        str = psMetadataItemAllocStr(key0, comm0, val0);
+    }
+    if (key5 != NULL) {
+        s32_0 = psMetadataItemAllocS32(key5, comm5, val5);
+    }
+    s32 = psMetadataItemAllocS32 (key1, comm1, val1);
+    f32 = psMetadataItemAllocF32 (key2, comm2, val2);
+    f64 = psMetadataItemAllocF64 (key3, comm3, val3);
+    b   = psMetadataItemAllocBool(key4, comm4, val4);
+
+    if ( ((key0 != NULL) && (str == NULL)) || (s32 == NULL) || (f32 == NULL) || (f64 == NULL) || (b == NULL) ||
+            ((key5 != NULL) && (s32_0 == NULL)) ) {
+        psError(PS_ERR_UNKNOWN, true, "could not create psMetadataItem(s) in %s!", __func__ );
+        return NULL;
+    }
+    if ( ((key0 != NULL) && !psMetadataAddItem(md, str, 0, 0)) ||
+            !psMetadataAddItem(md, s32, 0, 0) || !psMetadataAddItem(md, f32, 0, 0) ||
+            !psMetadataAddItem(md, f64, 0, 0) || !psMetadataAddItem(md, b,   0, 0) ||
+            ((key5 != NULL) && !psMetadataAddItem(md, s32_0, 0, 0))) {
+        psError(PS_ERR_UNKNOWN, true, "could not add psMetadataItem(s) to psMetadata in %s!", __func__ );
+        return NULL;
+    }
+
+    if (str != NULL) {
+        psFree(str);
+    }
+    psFree(s32);
+    psFree(f32);
+    psFree(f64);
+    psFree(b);
+    if (s32_0 != NULL) {
+        psFree(s32_0);
+    }
+
+    return md;
+}
+
+psMetadata *_get_const_row1( void )
+{
+    char buf[32];
+    snprintf(buf, 32, "%s", CONST_ROW_1_STR );
+    return _get_RowMetadata(
+               TAB_COL_0_NAME, "comment-string", buf,
+               TAB_COL_1_NAME,    "comment-s32",    CONST_ROW_1_S32,
+               TAB_COL_2_NAME,    "comment-f32",    CONST_ROW_1_F32,
+               TAB_COL_3_NAME,    "comment-f64",    CONST_ROW_1_F64,
+               TAB_COL_4_NAME,   "comment-bool",   CONST_ROW_1_BOOL,
+               NULL,         NULL,             0.0);
+}
+
+psMetadata *_get_const_row2( void )
+{
+    char buf[32];
+    snprintf(buf, 32, "%s",CONST_ROW_2_STR);
+    return _get_RowMetadata(
+               TAB_COL_0_NAME, "comment-string", buf,
+               TAB_COL_1_NAME,    "comment-s32",    CONST_ROW_2_S32,
+               TAB_COL_2_NAME,    "comment-f32",    CONST_ROW_2_F32,
+               TAB_COL_3_NAME,    "comment-f64",    CONST_ROW_2_F64,
+               TAB_COL_4_NAME,   "comment-bool",   CONST_ROW_2_BOOL,
+               NULL,         NULL,             0.0);
+}
+
+psMetadata *_get_row( void )
+{
+    return _get_RowMetadata(
+               TAB_COL_0_NAME, "comment-string", STR_1,
+               TAB_COL_1_NAME,    "comment-s32",    S32_1,
+               TAB_COL_2_NAME,    "comment-f32",    F32_1,
+               TAB_COL_3_NAME,    "comment-f64",    F64_1,
+               TAB_COL_4_NAME,   "comment-bool",   B_1,
+               NULL,         NULL,             0.0);
+}
+
+psMetadata *_get_invalid_row( void )
+{
+    return _get_RowMetadata(
+               TAB_COL_0_NAME, "comment-string", STR_1,
+               TAB_COL_1_NAME,    "comment-s32",    S32_1,
+               "key_999",    "comment-f32",    F32_1,
+               TAB_COL_3_NAME,    "comment-f64",    F64_1,
+               TAB_COL_4_NAME,   "comment-bool",   B_1,
+               NULL,         NULL,             0.0);
+}
+
+psMetadata *_get_where( void )
+{
+    psMetadata *md = NULL;
+    psMetadataItem *s32=NULL;
+
+    md = psMetadataAlloc();
+    if (md == NULL) {
+        psError(PS_ERR_UNKNOWN, true, "could not create psMetadata in %s!", __func__ );
+        return NULL;
+    }
+    s32 = psMetadataItemAllocS32(TAB_COL_1_NAME, "", S32_1);
+    if (s32 == NULL) {
+        psError(PS_ERR_UNKNOWN, true, "could not create psMetadataItem in %s!", __func__ );
+        return NULL;
+    }
+    if (!psMetadataAddItem(md, s32, 0, 0)) {
+        psError(PS_ERR_UNKNOWN, true, "could not add psMetadataItem(s) to psMetadata in %s!", __func__ );
+        return NULL;
+    }
+
+    psFree(s32);
+    return md;
+}
+
+psMetadata *_get_invalid_where( void )
+{
+    psMetadata *md = NULL;
+    psMetadataItem *s32=NULL;
+
+    md = psMetadataAlloc();
+    if (md == NULL) {
+        psError(PS_ERR_UNKNOWN, true, "could not create psMetadata in %s!", __func__ );
+        return NULL;
+    }
+    s32 = psMetadataItemAllocS32("col999", "", S32_1);
+    if (s32 == NULL) {
+        psError(PS_ERR_UNKNOWN, true, "could not create psMetadataItem in %s!", __func__ );
+        return NULL;
+    }
+    if (!psMetadataAddItem(md, s32, 0, 0)) {
+        psError(PS_ERR_UNKNOWN, true, "could not add psMetadataItem(s) to psMetadata in %s!", __func__ );
+        return NULL;
+    }
+
+    psFree(s32);
+    return md;
+}
+
+psMetadata *_get_where_bad_value( void )
+{
+    psMetadata *md = NULL;
+    psMetadataItem *s32=NULL;
+
+    md = psMetadataAlloc();
+    if (md == NULL) {
+        psError(PS_ERR_UNKNOWN, true, "could not create psMetadata in %s!", __func__ );
+        return NULL;
+    }
+    s32 = psMetadataItemAllocS32(TAB_COL_1_NAME, "", S32_1 + 1);
+    if (s32 == NULL) {
+        psError(PS_ERR_UNKNOWN, true, "could not create psMetadataItem in %s!", __func__ );
+        return NULL;
+    }
+    if (!psMetadataAddItem(md, s32, 0, 0)) {
+        psError(PS_ERR_UNKNOWN, true, "could not add psMetadataItem(s) to psMetadata in %s!", __func__ );
+        return NULL;
+    }
+
+    psFree(s32);
+    return md;
+}
+
+psMetadata *_get_update_values(const char *val0, psS32 val1, psF32 val2, psF64 val3, psBool val4)
+{
+    return _get_RowMetadataValues(val0, val1, val2, val3, val4);
+}
+
+bool _check_row(psMetadata* row)
+{
+    bool              returnValue = true;
+    psMetadataItem*   item        = NULL;
+
+    item = psMetadataLookup(row,TAB_COL_0_NAME);
+    if((item==NULL) || (strcmp(item->data.V,STR_1)!=0)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_string item %s not as expected %s",
+                item->data.V,STR_1);
+        return false;
+    }
+
+    item = psMetadataLookup(row,TAB_COL_1_NAME);
+    if((item==NULL) || (item->data.S32 != S32_1)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_s32 item %d not as expected %d",
+                item->data.S32, S32_1);
+        return false;
+    }
+
+    item = psMetadataLookup(row,TAB_COL_2_NAME);
+    if((item==NULL) || (fabs(item->data.F32-F32_1)>ERROR_TOL)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_f32 item %f not as expected %f",
+                item->data.F32, F32_1);
+        return false;
+    }
+
+    item = psMetadataLookup(row,TAB_COL_3_NAME);
+    if((item==NULL) || (fabs(item->data.F64-F64_1)>ERROR_TOL)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_f64 item %lf not as expected %lf",
+                item->data.F64,F64_1);
+        return false;
+    }
+
+    item = psMetadataLookup(row,TAB_COL_4_NAME);
+    if((item==NULL) || (item->data.B != B_1)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_bool item %d not as expected %d",
+                item->data.B, B_1);
+        return false;
+    }
+
+    return returnValue;
+}
+
+bool _check_row_update(psMetadata* row)
+{
+    bool              returnValue = true;
+    psMetadataItem*   item        = NULL;
+
+    item = psMetadataLookup(row,TAB_COL_0_NAME);
+    if((item==NULL) || (strcmp(item->data.V,STR_2)!=0)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_string item %s not as expected %s",
+                item->data.V,STR_2);
+        return false;
+    }
+
+    item = psMetadataLookup(row,TAB_COL_1_NAME);
+    if((item==NULL) || (item->data.S32 != S32_2)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_s32 item %d not as expected %d",
+                item->data.S32, S32_2);
+        return false;
+    }
+
+    item = psMetadataLookup(row,TAB_COL_2_NAME);
+    if((item==NULL) || (fabs(item->data.F32-F32_2)>ERROR_TOL)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_f32 item %f not as expected %f",
+                item->data.F32, F32_2);
+        return false;
+    }
+
+    item = psMetadataLookup(row,TAB_COL_3_NAME);
+    if((item==NULL) || (fabs(item->data.F64-F64_2)>ERROR_TOL)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_f64 item %lf not as expected %lf",
+                item->data.F64,F64_2);
+        return false;
+    }
+
+    item = psMetadataLookup(row,TAB_COL_4_NAME);
+    if((item==NULL) || (item->data.B != B_2)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_bool item %d not as expected %d",
+                item->data.B, B_2);
+        return false;
+    }
+
+    return returnValue;
+}
+
+bool _check_const_row1(psMetadata* row)
+{
+    bool              returnValue = true;
+    psMetadataItem*   item        = NULL;
+
+    item = psMetadataLookup(row,TAB_COL_0_NAME);
+    if((item==NULL) || (strcmp(item->data.V,CONST_ROW_1_STR)!=0)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_string item %s not as expected %s",
+                item->data.V,CONST_ROW_1_STR);
+        return false;
+    }
+
+    item = psMetadataLookup(row,TAB_COL_1_NAME);
+    if((item==NULL) || (item->data.S32 != CONST_ROW_1_S32)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_s32 item %d not as expected %d",
+                item->data.S32, CONST_ROW_1_S32);
+        return false;
+    }
+
+    item = psMetadataLookup(row,TAB_COL_2_NAME);
+    if((item==NULL) || (fabs(item->data.F32-CONST_ROW_1_F32)>ERROR_TOL)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_f32 item %f not as expected %f",
+                item->data.F32, CONST_ROW_1_F32);
+        return false;
+    }
+
+    item = psMetadataLookup(row,TAB_COL_3_NAME);
+    if((item==NULL) || (fabs(item->data.F64-CONST_ROW_1_F64)>ERROR_TOL)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_f64 item %lf not as expected %lf",
+                item->data.F64,CONST_ROW_1_F64);
+        return false;
+    }
+
+    item = psMetadataLookup(row,TAB_COL_4_NAME);
+    if((item==NULL) || (item->data.B != CONST_ROW_1_BOOL)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_bool item %d not as expected %d",
+                item->data.B, CONST_ROW_1_BOOL);
+        return false;
+    }
+
+    return returnValue;
+}
+
+bool _check_const_row2(psMetadata* row)
+{
+    bool              returnValue = true;
+    psMetadataItem*   item        = NULL;
+
+    item = psMetadataLookup(row,TAB_COL_0_NAME);
+    if((item==NULL) || (strcmp(item->data.V,CONST_ROW_2_STR)!=0)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_string item %s not as expected %s",
+                item->data.V,CONST_ROW_2_STR);
+        return false;
+    }
+
+    item = psMetadataLookup(row,TAB_COL_1_NAME);
+    if((item==NULL) || (item->data.S32 != CONST_ROW_2_S32)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_s32 item %d not as expected %d",
+                item->data.S32, CONST_ROW_2_S32);
+        return false;
+    }
+
+    item = psMetadataLookup(row,TAB_COL_2_NAME);
+    if((item==NULL) || (fabs(item->data.F32-CONST_ROW_2_F32)>ERROR_TOL)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_f32 item %f not as expected %f",
+                item->data.F32, CONST_ROW_2_F32);
+        return false;
+    }
+
+    item = psMetadataLookup(row,TAB_COL_3_NAME);
+    if((item==NULL) || (fabs(item->data.F64-CONST_ROW_2_F64)>ERROR_TOL)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_f64 item %lf not as expected %lf",
+                item->data.F64,CONST_ROW_2_F64);
+        return false;
+    }
+
+    item = psMetadataLookup(row,TAB_COL_4_NAME);
+    if((item==NULL) || (item->data.B != CONST_ROW_2_BOOL)) {
+        psError(PS_ERR_UNKNOWN,true,"Column key_bool item %d not as expected %d",
+                item->data.B, CONST_ROW_2_BOOL);
+        return false;
+    }
+
+    return returnValue;
+}
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel( PS_LOG_INFO );
+
+    srand(time(NULL));
+
+    return ( ! runTestSuite( stderr, "psDB", tests, argc, argv ) );
+}
+
+// Testpoint #841, initialize/break-down MySQL connection.
+psS32 TPDBInit( void )
+{
+    psDB *dbh = NULL;
+
+    // Initialize database with valid arguments
+    dbh = _init_psDB();
+    if (dbh == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL to be returned for valid arguments");
+        return 1;
+    }
+
+    // Cleanup database/connection with valid psDB object
+    psDBCleanup(dbh);
+
+    // Attempt to initialize database with invalid arguments
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid host");
+    dbh = psDBInit("xxx",NULL,NULL,NULL);
+    if(dbh != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL psDB with invalid arguments");
+        return 2;
+    }
+
+    // Attempt cleanup database/connection with NULL psDB object
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL database objec");
+    psDBCleanup(NULL);
+
+    return 0;
+}
+
+// Testpoint #842, psDBChange shall change databases.
+psS32 TPDBChange( void )
+{
+    psDB *dbh = NULL;
+
+    // Initialize database connection
+    dbh = _init_psDB();
+    if (dbh == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL for valid arguments");
+        return 1;
+    }
+
+    // Attempt to change database with valid arguments
+    if(!psDBChange(dbh, dbname)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for valid arguments");
+        return 2;
+    }
+
+    // Attemp to change database to invalid database name
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid database");
+    if(psDBChange(dbh,"abc")) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return true for unknown database name");
+        return 3;
+    }
+
+    // Cleanup database connection
+    psDBCleanup(dbh);
+
+    // Attempt to change database with NULL database object
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for null database object");
+    if(psDBChange(NULL,dbname)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return true for NULL database object");
+        return 4;
+    }
+
+    return 0;
+}
+
+// Testpoint #843, psDBCreateTable shall create tables in the test database ...
+psS32 TPDBCreateTable( void )
+{
+    psDB *dbh = NULL;
+    const char* table = "table1";
+
+    // Create metadata for table definition
+    psMetadata *md = _get_CreateTableMetadata();
+
+    // Initialize database connection
+    dbh = _init_psDB();
+    if (dbh == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL for valid argument in database connection");
+        return 1;
+    }
+
+    // Attempt to create database table with valid arguments
+    if(!psDBCreateTable(dbh, table, md)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return of false for valid arguments");
+        return 2;
+    } else {
+        // Drop the table from the test database
+        psDBDropTable(dbh, table);
+    }
+
+    // Free metadata definition of table
+    psFree(md);
+
+    // Attempt to create table with NULL table definition
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL parameter");
+    if(psDBCreateTable(dbh,table,NULL)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return of true for NULL metadata object");
+        return 3;
+    }
+
+    // Attempt to create table with NULL connection
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL parameter");
+    if(psDBCreateTable(NULL, table, md)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return of true for NULL database object");
+        return 4;
+    }
+
+    // Close/cleanup database connection
+    psDBCleanup(dbh);
+
+    return 0;
+}
+
+// Testpoint #844, psDBDropTable shall remove tables in the test database ...
+psS32 TPDBDropTable( void )
+{
+    psDB *dbh = NULL;
+    const char* table = "table2";
+
+    // Create table definition metadata
+    psMetadata *row=NULL, *md = _get_CreateTableMetadata();
+
+    // Initialize database connection
+    dbh = _init_psDB();
+    if (dbh == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return to initialize database");
+        return 1;
+    }
+
+    // Create table in database
+    if(psDBCreateTable(dbh, table, md)) {
+
+        // Drop table with valid arguments
+        if(!psDBDropTable(dbh, table)) {
+            psError(PS_ERR_UNKNOWN,true,"Did not expect return false for valid arguments");
+            return 2;
+        }
+
+        // insert should fail since the table has been drop from database
+        psLogMsg( __func__, PS_LOG_INFO, "psDBDropTable: insert should fail here...\n" );
+        row = _get_row();
+        if (psDBInsertOneRow(dbh, table, row)) {
+            psError(PS_ERR_UNKNOWN,true,"Did not expect to successfully insert row into dropped table");
+            return 3;
+        }
+        psFree(row);
+    } else {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return false to create table");
+        return 4;
+    }
+
+    // Attempt to drop table from NULL psDB object
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL database object");
+    if(psDBDropTable(NULL,table)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return false as expected for NULL database object");
+        return 5;
+    }
+
+    // Attempt to drop table from valid psDB but invalid table
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid table");
+    if(psDBDropTable(dbh,"table99")) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return false as expected for invalid table");
+        return 6;
+    }
+
+    // Attempt to drop table from valid psDB but NULL table
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL table");
+    if(psDBDropTable(dbh,NULL)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return false as expected for NULL table");
+        return 7;
+    }
+
+    psFree(md);
+    psDBCleanup(dbh);
+
+    return 0;
+}
+
+// Testpoint #845, TPDBSelectColumn shall write/select a column from a test table ...
+psS32 TPDBSelectColumn( void )
+{
+    psDB *dbh = NULL;
+    const char* table = "table3";
+    psArray *ary = NULL;
+    char *ptr=NULL;
+
+    // Create table definition metadata
+    psMetadata *row=NULL, *md = _get_CreateTableMetadata();
+
+    // Initialize database connection
+    dbh = _init_psDB();
+    if (dbh == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return NULL to initialize database connection");
+        return 1;
+    }
+
+    // Create database table
+    if(!psDBCreateTable(dbh,table,md)) {
+        psError(PS_ERR_UNKNOWN,true,"Unable to create database table for testing");
+        psDBCleanup(dbh);
+        return 2;
+    }
+
+    // Insert known constant row #1
+    row = _get_const_row1();
+    if(!psDBInsertOneRow(dbh, table, row)) {
+        psError(PS_ERR_UNKNOWN,true,"Unable to add rows to test database");
+        psDBDropTable(dbh, table);
+        psDBCleanup(dbh);
+        return 3;
+    }
+    psFree(row);
+
+    // Insert known constant row #2
+    row = _get_const_row2();
+    if(!psDBInsertOneRow(dbh, table, row)) {
+        psError(PS_ERR_UNKNOWN,true,"Unable to add rows to test database");
+        psDBDropTable(dbh, table);
+        psDBCleanup(dbh);
+        return 4;
+    }
+    psFree(row);
+
+    // Insert known row
+    row = _get_row();
+    if(!psDBInsertOneRow(dbh, table, row)) {
+        psError(PS_ERR_UNKNOWN,true,"Unable to add rows to test database");
+        psDBDropTable(dbh, table);
+        psDBCleanup(dbh);
+        return 5;
+    }
+    psFree(row);
+
+    // Select all items in column key_string with valid arguments
+    ary = psDBSelectColumn(dbh, table, TAB_COL_0_NAME, 0);
+    if (ary == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return value of NULL");
+        psDBDropTable(dbh, table);
+        psDBCleanup(dbh);
+        return 6;
+    }
+
+    // Verify array contents
+    if(ary->n != 3) {
+        psError(PS_ERR_UNKNOWN,true,"Array number of items %d not equal to expected %d",
+                ary->n, 3);
+        psDBDropTable(dbh, table);
+        psDBCleanup(dbh);
+        return 60;
+    }
+    ptr = psArrayGet(ary, 2);
+    if (strcmp(ptr, CONST_ROW_1_STR)) {
+        psError(PS_ERR_UNKNOWN,true,"key_str column entry[%d] = %s not as expected %s",
+                2,CONST_ROW_1_STR,ptr);
+        psDBDropTable(dbh, table);
+        psDBCleanup(dbh);
+        return 7;
+    }
+    //    psFree(ptr);
+    ptr = psArrayGet(ary, 1);
+    if (strcmp(ptr, CONST_ROW_2_STR)) {
+        psError(PS_ERR_UNKNOWN,true,"key_str column entry[%d] = %s not as expected %s",
+                1,CONST_ROW_2_STR,ptr);
+        psDBDropTable(dbh, table);
+        psDBCleanup(dbh);
+        return 8;
+    }
+    //    psFree(ptr);
+    ptr = psArrayGet(ary, 0);
+    if (strcmp(ptr, STR_1)) {
+        psError(PS_ERR_UNKNOWN,true,"key_str column entry[%d] = %s not as expected %s",
+                0,STR_1,ptr);
+        psDBDropTable(dbh, table);
+        psDBCleanup(dbh);
+        return 9;
+    }
+    //    psFree(ptr);
+    psFree(ary);
+
+    // Select items in column key_bool with limit 10 and valid arguments
+    ary = psDBSelectColumn(dbh, table, TAB_COL_4_NAME, 10);
+    if (ary == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return value of NULL");
+        psDBDropTable(dbh, table);
+        psDBCleanup(dbh);
+        return 10;
+    }
+
+    // Verify array contents
+    if(ary->n != 3) {
+        psError(PS_ERR_UNKNOWN,true,"Array number of items %d not equal to expected %d",
+                ary->n, 3);
+        psDBDropTable(dbh, table);
+        psDBCleanup(dbh);
+        return 100;
+    }
+    ptr = psArrayGet(ary, 2);
+    if(atoi(ptr) != CONST_ROW_1_BOOL) {
+        psError(PS_ERR_UNKNOWN,true,"key_bool column entry[%d] = %d not as expected %d",
+                2,CONST_ROW_1_BOOL,atoi(ptr));
+        psDBDropTable(dbh, table);
+        psDBCleanup(dbh);
+        return 11;
+    }
+    //    psFree(ptr);
+    ptr = psArrayGet(ary, 1);
+    if(atoi(ptr) != CONST_ROW_2_BOOL) {
+        psError(PS_ERR_UNKNOWN,true,"key_bool column entry[%d] = %d not as expected %d",
+                1,CONST_ROW_2_BOOL,atoi(ptr));
+        psDBDropTable(dbh, table);
+        psDBCleanup(dbh);
+        return 12;
+    }
+    //    psFree(ptr);
+    ptr = psArrayGet(ary, 0);
+    if(atoi(ptr) != B_1) {
+        psError(PS_ERR_UNKNOWN,true,"key_bool column entry[%d] = %d not as expected %d",
+                0,B_1,atoi(ptr));
+        psDBDropTable(dbh, table);
+        psDBCleanup(dbh);
+        return 13;
+    }
+    //    psFree(ptr);
+    psFree(ary);
+
+    // Attempt to select columns from NULL database object
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL database");
+    if(psDBSelectColumn(NULL,table,"key_str",10) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return for selecting from NULL database");
+        psDBDropTable(dbh, table);
+        psDBCleanup(dbh);
+        return 14;
+    }
+
+    // Attempt to select column from NULL table
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL table");
+    if(psDBSelectColumn(dbh,NULL,"key_str",10) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return for NULL table");
+        psDBDropTable(dbh, table);
+        psDBCleanup(dbh);
+        return 15;
+    }
+
+    // Attempt to select column from invalid table
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid table");
+    if(psDBSelectColumn(dbh,"table99","key_str",10) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return for invalid table");
+        psDBDropTable(dbh, table);
+        psDBCleanup(dbh);
+        return 16;
+    }
+
+    // Attempt to select invalid column from valid database object and valid table
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid column");
+    if(psDBSelectColumn(dbh,table,"key_null",10) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return for invalid column");
+        psDBDropTable(dbh, table);
+        psDBCleanup(dbh);
+        return 17;
+    }
+
+    // Clean up table and memory
+    psDBDropTable(dbh, table);
+    psFree(md);
+    psDBCleanup(dbh);
+
+    return 0;
+}
+
+// Testpoint #846, TPDBSelectColumnNum shall write/select a column from a test table ...
+psS32 TPDBSelectColumnNum( void )
+{
+    psDB *dbh = NULL;
+    const char* table = "table4";
+    psVector *vec = NULL;
+
+    // Create table definition metadata
+    psMetadata *row=NULL, *md = _get_CreateTableMetadata();
+
+    // Initialize database connection
+    dbh = _init_psDB();
+    if (dbh == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expected NULL return to initialize database");
+        return 1;
+    }
+
+    // Create database table for test
+    if(!psDBCreateTable(dbh, table, md)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for create table");
+        return 2;
+    }
+
+    // Initialize database table with known rows
+    row = _get_const_row1();
+    psDBInsertOneRow(dbh, table, row);
+    psFree(row);
+
+    row = _get_const_row2();
+    psDBInsertOneRow(dbh, table, row);
+    psFree(row);
+
+    row = _get_row();
+    psDBInsertOneRow(dbh, table, row);
+    psFree(row);
+
+    // Use valid arguments to select column with numeric values to return vector
+    vec = psDBSelectColumnNum(dbh, table, TAB_COL_1_NAME, PS_TYPE_S32, 0);
+
+    // Verify vector returned
+    if (vec == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return with valid arguments");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 3;
+    }
+    // Verify vector values
+    if(vec->n != 3) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return vector size not equal to 3");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 30;
+    }
+    if(vec->type.type != PS_TYPE_S32) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return vector type not equal to PS_TYPE_S32");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 31;
+    }
+    if ((vec->data.S32)[0] != S32_1) {
+        psError(PS_ERR_UNKNOWN,true,"vector value[%d] = %d not as expected %d",
+                0,vec->data.S32[0], S32_1);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 4;
+    }
+    if ((vec->data.S32)[1] != CONST_ROW_2_S32) {
+        psError(PS_ERR_UNKNOWN,true,"vector value[%d] = %d not as expected %d",
+                1,vec->data.S32[1], CONST_ROW_2_S32);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 5;
+    }
+    if ((vec->data.S32)[2] != CONST_ROW_1_S32) {
+        psError(PS_ERR_UNKNOWN,true,"vector value[%d] = %d not as expected %d",
+                2,vec->data.S32[2], CONST_ROW_1_S32);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 6;
+    }
+    psFree(vec);
+
+    // Use valid arguments to select column with numeric values to return vector
+    vec = psDBSelectColumnNum(dbh, table, TAB_COL_4_NAME, PS_TYPE_BOOL, 0);
+
+    // Verify vector returned
+    if (vec == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return with valid arguments");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 7;
+    }
+    // Verify vector values
+    if(vec->n != 3) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return vector size not equal to 3");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 8;
+    }
+    if(vec->type.type != PS_TYPE_BOOL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return vector type not equal to PS_TYPE_BOOL");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 9;
+    }
+    if ((vec->data.U8)[0] != B_1) {
+        psError(PS_ERR_UNKNOWN,true,"vector value[%d] = %d not as expected %d",
+                0,vec->data.U8[0],B_1);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 10;
+    }
+    if ((vec->data.U8)[1] != CONST_ROW_2_BOOL) {
+        psError(PS_ERR_UNKNOWN,true,"vector value[%d] = %d not as expected %d",
+                0,vec->data.U8[0],CONST_ROW_2_BOOL);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 11;
+    }
+    if ((vec->data.U8)[2] != CONST_ROW_1_BOOL) {
+        psError(PS_ERR_UNKNOWN,true,"vector value[%d] = %d not as expected %d",
+                0,vec->data.U8[0],CONST_ROW_1_BOOL);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 12;
+    }
+    psFree(vec);
+
+    // Attempt to select columns from NULL database
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for NULL database object");
+    if(psDBSelectColumnNum(NULL,table,TAB_COL_4_NAME,PS_TYPE_BOOL,10) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return with NULL database object");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 13;
+    }
+
+    // Attempt to select columns from NULL table
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for NULL table");
+    if(psDBSelectColumnNum(dbh,NULL,TAB_COL_4_NAME,PS_TYPE_BOOL,10) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return with NULL table");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 14;
+    }
+
+    // Attempt to select columns from invalid column
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for invalid column");
+    if(psDBSelectColumnNum(dbh,table,"key_999",PS_TYPE_BOOL,10) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return with NULL column");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 15;
+    }
+
+    // Attempt to select columns from invalid column
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for invalid type");
+    if(psDBSelectColumnNum(dbh,table,TAB_COL_0_NAME,0,10) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return with invalid type");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 16;
+    }
+
+    psDBDropTable(dbh, table);
+    psFree(md);
+    psDBCleanup(dbh);
+
+    return 0;
+}
+
+// Testpoint #847, TPDBSelectRows shall write/select data from a test table ...
+psS32 TPDBSelectRows( void )
+{
+    int i;
+    psDB *dbh = NULL;
+    const char* table = "table5";
+    psArray *ary=NULL, *ary1=NULL, *ary2=NULL;
+    psMetadataItem *item = NULL;
+
+    // Create database table definition
+    psMetadata *where=NULL, *row=NULL, *md = _get_CreateTableMetadata();
+
+    // Initialize database connection
+    dbh = _init_psDB();
+    if (dbh == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expected NULL return to initialize database");
+        return 1;
+    }
+
+    psDBDropTable(dbh,table);
+    // Create database table for test
+    if(!psDBCreateTable(dbh, table, md)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for create table");
+        psDBCleanup(dbh);
+        return 2;
+    }
+
+    // Initialize database table with known rows
+    row = _get_const_row1();
+    psDBInsertOneRow(dbh, table, row);
+    psFree(row);
+
+    row = _get_const_row2();
+    psDBInsertOneRow(dbh, table, row);
+    psFree(row);
+
+    row = _get_row();
+    psDBInsertOneRow(dbh, table, row);
+    psFree(row);
+
+    // Generate valid where clause
+    where = _get_where();
+
+    // Select rows with non limit
+    ary1 = psDBSelectRows(dbh, table, where, 0);
+
+    // Select rows with a limit
+    ary2 = psDBSelectRows(dbh, table, where, 1);
+    psFree(where);
+
+    // Cycle through both arrays to verify results
+    for (i=0; i<2; i++) {
+        ary = i ? ary2 : ary1;
+
+        // Verify return array not NULL
+        if (ary == NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Did not expect return NULL");
+            psDBDropTable(dbh,table);
+            psDBCleanup(dbh);
+            return 1;
+        }
+
+        if(ary->n != 1) {
+            psError(PS_ERR_UNKNOWN,true,"Number of rows %d not as expected %d",
+                    ary->n, 1);
+            psDBDropTable(dbh,table);
+            psDBCleanup(dbh);
+            return 2;
+        }
+
+        // Get metadata which contains row from array
+        row = (psMetadata*)psArrayGet(ary, 0);
+
+        // Get key_s32 item from metadata
+        item = psMetadataLookup(row, TAB_COL_1_NAME);
+        if (item == NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Could not find key_s32 item in row metadata");
+            psDBDropTable(dbh,table);
+            psDBCleanup(dbh);
+            return 2;
+        }
+        if (item->data.S32 != S32_1) {
+            psError(PS_ERR_UNKNOWN,true,"Row item %d not as expected %d",
+                    item->data.S32,S32_1);
+            psDBDropTable(dbh,table);
+            psDBCleanup(dbh);
+            return 3;
+        }
+
+        // Get key_bool item from metadata
+        item = psMetadataLookup(row, TAB_COL_4_NAME);
+        if (item == NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Could not find key_bool item in row metadata");
+            psDBDropTable(dbh,table);
+            psDBCleanup(dbh);
+            return 2;
+        }
+        if (item->data.B != B_1) {
+            psError(PS_ERR_UNKNOWN,true,"Row item %d not as expected %d",
+                    item->data.S32,S32_1);
+            psDBDropTable(dbh,table);
+            psDBCleanup(dbh);
+            return 4;
+        }
+        psFree(ary);
+        //        psFree(row);
+    }
+
+    // Attempt to select rows with NULL database object
+    psLogMsg(__func__,PS_LOG_INFO,
+             "Following should generate an error message for NULL database object");
+    if(psDBSelectRows(NULL, table, where, 0) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return for NULL database object");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 5;
+    }
+
+    // Attempt to select rows with invalid table
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid table");
+    if(psDBSelectRows(dbh, NULL, where, 0) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return for NULL database object");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 5;
+    }
+
+    // Select rows with no where specified
+    ary1 = psDBSelectRows(dbh, table, NULL, 0);
+    if(ary1 == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return using NULL where");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 6;
+    }
+    if(ary1->n != 3) {
+        psError(PS_ERR_UNKNOWN,true,"Rows return %d not as expected %d",
+                ary->n,3);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 7;
+    }
+    psFree(ary1);
+
+    psDBDropTable(dbh, table);
+    psFree(md);
+    psDBCleanup(dbh);
+
+    return 0;
+}
+
+// Testpoint #848, TPDBInsertOneRow shall write a row of data into a test table ...
+psS32 TPDBInsertOneRow( void )
+{
+    psDB *dbh = NULL;
+    const char* table = "table6";
+    psMetadata *invalidRow = NULL;
+    psArray*    ary = NULL;
+
+    // Create table definition metadata
+    psMetadata *row=NULL, *md = _get_CreateTableMetadata();
+
+    // Initialize database connection
+    dbh = _init_psDB();
+    if (dbh == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return NULL for database initialization");
+        return 1;
+    }
+
+    // Create database table
+    if(!psDBCreateTable(dbh, table, md)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for create database");
+        psDBCleanup(dbh);
+        return 2;
+    }
+
+    // Insert a single row with valid arguments
+    row = _get_const_row1();
+    if(!psDBInsertOneRow(dbh, table, row)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for inserting row w/ valid arguments");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 3;
+    }
+    // Verify row was added to table
+    ary = psDBSelectRows(dbh,table,NULL,0);
+    if(ary->n != 1) {
+        psError(PS_ERR_UNKNOWN,true,"Number of rows %d not as expected %d",
+                ary->n,1);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 30;
+    }
+    psFree(ary);
+
+    // Insert a single row with NULL database
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL database");
+    if(psDBInsertOneRow(NULL,table,row)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return value true for NULL database");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 4;
+    }
+
+    // Insert a single row which has column which does not match table
+    invalidRow = _get_invalid_row();
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid column item");
+    if(psDBInsertOneRow(dbh,table,invalidRow)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return value true for invalid column item");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 6;
+    }
+
+    // Insert a single row with invalid table
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid table");
+    if(psDBInsertOneRow(dbh,"table999",row)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return value true for invalid table");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 5;
+    }
+
+    // Insert a single row with NULL row
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL row");
+    if(psDBInsertOneRow(dbh,table,NULL)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return value true for NULL row");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 6;
+    }
+
+    psFree(row);
+    psFree(invalidRow);
+    psDBDropTable(dbh, table);
+    psFree(md);
+    psDBCleanup(dbh);
+
+    return 0;
+}
+
+// Testpoint #849, TPDBInsertRows shall write rows of data into a test table ...
+psS32 TPDBInsertRows( void )
+{
+    psDB *dbh = NULL;
+    const char* table = "table7";
+    psArray *rowSet = NULL;
+    psArray* dumpRowSet = NULL;
+    psMetadataItem *item=NULL;
+    psArray* ary = NULL;
+    psMetadata* invalidRow = NULL;
+    psArray* invalidRowSet = NULL;
+
+    //Create database table definition metadata
+    psMetadata *row=NULL, *md = _get_CreateTableMetadata();
+
+    // Initialize database connection
+    dbh = _init_psDB();
+    if (dbh == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL for initializing database connection");
+        return 1;
+    }
+
+    // Create database table for testing
+    if(!psDBCreateTable(dbh, table, md)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for creating table");
+        psDBCleanup(dbh);
+        return 2;
+    }
+
+    // Create array of row elements
+    rowSet = psArrayAlloc(3);
+    rowSet->n = 0;
+
+    row = _get_const_row1();
+    psArrayAdd(rowSet, 0, row);
+    psFree(row);
+
+    row = _get_const_row2();
+    psArrayAdd(rowSet, 0, row);
+    psFree(row);
+
+    row = _get_row();
+    psArrayAdd(rowSet, 0, row);
+    psFree(row);
+
+    // Insert rows with valid arguments
+    if(!psDBInsertRows(dbh, table, rowSet)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for inserting rows w/ valid args");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 3;
+    }
+
+    // Verify row was added to table
+    ary = psDBSelectRows(dbh,table,NULL,0);
+    if(ary->n != 3) {
+        psError(PS_ERR_UNKNOWN,true,"Number of rows %d not as expected %d",
+                ary->n,3);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 30;
+    }
+    psFree(ary);
+
+    // extra checks ...
+    dumpRowSet = psDBDumpRows(dbh, table);
+    if (dumpRowSet == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL from dump rows");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 4;
+    }
+
+    // Get first row from array
+    row = (psMetadata*)psArrayGet(dumpRowSet, 0);
+    // Verify contents for column key_s32
+    item = psMetadataLookup(row, TAB_COL_1_NAME);
+    if ((item == NULL) || (item->data.S32 != S32_1)) {
+        psError(PS_ERR_UNKNOWN,true,"Column value %d not as expected %d",
+                item->data.S32, S32_1);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 5;
+    }
+    // Verify contents for column key_bool
+    item = psMetadataLookup(row, TAB_COL_4_NAME);
+    if ((item == NULL) || (item->data.B != B_1)) {
+        psError(PS_ERR_UNKNOWN,true,"Column value %d not as expected %d",
+                item->data.B, B_1);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 6;
+    }
+    psFree(dumpRowSet);
+    //    psFree(row);
+
+    // Insert rows with NULL database object
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL database");
+    if(psDBInsertRows(NULL,table,rowSet)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return of false for NULL database");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 7;
+    }
+
+    // Insert rows with NULL table
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL table");
+    if(psDBInsertRows(dbh,NULL,rowSet)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return of false for NULL table");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 70;
+    }
+
+    // Insert rows with invalid table
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid table");
+    if(psDBInsertRows(dbh,"table999",rowSet)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return of false for invalid table");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 8;
+    }
+
+    // Insert rows with NULL array of rows to be inserted
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL row array");
+    if(psDBInsertRows(dbh,table,NULL)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return of false for NULL row array");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 9;
+    }
+
+    // Insert a single row which has column which does not match table
+    invalidRow = _get_invalid_row();
+    // Create array of invalid row element
+    invalidRowSet = psArrayAlloc(1);
+    invalidRowSet->n = 0;
+    psArrayAdd(invalidRowSet, 0, invalidRow);
+    psFree(invalidRow);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid column item");
+    if(psDBInsertRows(dbh,table,invalidRowSet)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return value true for invalid column item");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 10;
+    }
+    psFree(invalidRowSet);
+
+    psFree(rowSet);
+    psDBDropTable(dbh, table);
+    psFree(md);
+    psDBCleanup(dbh);
+
+    return 0;
+}
+
+// Testpoint #850, TPDBDumpRows shall dump all rows from a test table ...
+psS32 TPDBDumpRows( void )
+{
+    psDB *dbh = NULL;
+    const char* table = "table8";
+    psArray *ary = NULL;
+
+    // Create table definition metadata
+    psMetadata *row=NULL, *md = _get_CreateTableMetadata();
+
+    // Initialize database connection
+    dbh = _init_psDB();
+    if (dbh == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return NULL from initializing database");
+        return 1;
+    }
+
+    // Create table for testing
+    if(!psDBCreateTable(dbh, table, md)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return false from creating table");
+        psDBCleanup(dbh);
+        return 2;
+    }
+
+    // Insert known data rows into table
+    row = _get_const_row1();
+    psDBInsertOneRow(dbh, table, row);
+    psFree(row);
+
+    row = _get_const_row2();
+    psDBInsertOneRow(dbh, table, row);
+    psFree(row);
+
+    row = _get_row();
+    psDBInsertOneRow(dbh, table, row);
+    psFree(row);
+
+    // Dump row with valid parameters
+    ary = psDBDumpRows(dbh, table);
+    if (ary == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return NULL for dump rows");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 3;
+    }
+    if(ary->n != 3) {
+        psError(PS_ERR_UNKNOWN,true,"Rows dumped %d not as expected %d",
+                ary->n, 3);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 4;
+    }
+
+    row = (psMetadata*)psArrayGet(ary, 0);
+    if(!_check_row(row)) {
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 5;
+    }
+    //    psFree(row);
+    row = (psMetadata*)psArrayGet(ary, 1);
+    if(!_check_const_row2(row)) {
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 6;
+    }
+    //    psFree(row);
+    row = (psMetadata*)psArrayGet(ary, 2);
+    if(!_check_const_row1(row)) {
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 7;
+    }
+    //    psFree(row);
+    psFree(ary);
+
+    // Attempt to dump row with database NULL
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL database");
+    if(psDBDumpRows(NULL,table)!=NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return non-NULL for NULL database specified");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 8;
+    }
+
+    // Attempt to dump row with table NULL
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL table");
+    if(psDBDumpRows(dbh,NULL)!=NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return non-NULL for NULL table specified");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 9;
+    }
+
+    psDBDropTable(dbh, table);
+
+    psFree(md);
+    psDBCleanup(dbh);
+
+    return 0;
+}
+
+// Testpoint #851, TPDBDumpCols shall dump all cols from a test table ...
+psS32 TPDBDumpCols( void )
+{
+    psDB*                dbh     = NULL;
+    const char*          table   = "table9";
+    psMetadata*          row     = NULL;
+    psMetadata*          meta    = NULL;
+    psMetadata*          md      = NULL;
+    psMetadataIterator*  mdIter  = NULL;
+    psMetadataItem*      mdItem  = NULL;
+    int                  itemNum = 0;
+
+    // Create database table definition
+    md = _get_CreateTableMetadata();
+
+    // Initialize database connection
+    dbh = _init_psDB();
+    if (dbh == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return to initialize database");
+        return 1;
+    }
+
+    // Create database table for testing
+    if(!psDBCreateTable(dbh, table, md)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return of false to create test table");
+        psDBCleanup(dbh);
+        return 2;
+    }
+
+    // Add row with known data values
+    row = _get_const_row1();
+    psDBInsertOneRow(dbh, table, row);
+    psFree(row);
+
+    row = _get_const_row2();
+    psDBInsertOneRow(dbh, table, row);
+    psFree(row);
+
+    row = _get_row();
+    psDBInsertOneRow(dbh, table, row);
+    psFree(row);
+
+    // Dump columns with valid arguments
+    meta = psDBDumpCols(dbh, table);
+    mdIter = psMetadataIteratorAlloc(meta,PS_LIST_HEAD,NULL);
+
+    // Verify contents of metadata returned
+    if (meta == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return value NULL for dumpCols with valid args");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 3;
+    }
+    if(meta->list->n != 6) {
+        psError(PS_ERR_UNKNOWN,true,"Number of cols = %d not as expected %d",
+                meta->list->n,6);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 4;
+    }
+    // Verify the metadata items
+    itemNum = 0;
+    while ((mdItem = psMetadataGetAndIncrement(mdIter)) != NULL) {
+        switch(itemNum) {
+        case 0:
+            if(mdItem->type != PS_DATA_VECTOR) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d type %d not as expected %d",
+                        itemNum,mdItem->type,PS_DATA_VECTOR);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 5*(itemNum+1);
+            }
+            if(((psVector*)mdItem->data.V)->type.type != PS_TYPE_S32) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d vector type %d not as expected %d",
+                        itemNum,((psVector*)mdItem->data.V)->type.type, PS_TYPE_S32);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 6*(itemNum+1);
+            }
+            if(((psVector*)mdItem->data.V)->n != 3) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d vector size %d not as expected %d",
+                        itemNum,((psVector*)mdItem->data.V)->n,3);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 7*(itemNum+1);
+            }
+            if(strcmp(mdItem->name,TAB_COL_5_NAME) != 0) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d name %s not as expected %s",
+                        itemNum,mdItem->name,TAB_COL_5_NAME);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 8*(itemNum+1);
+            }
+            break;
+        case 1:
+            if(mdItem->type != PS_DATA_VECTOR) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d type %d not as expected %d",
+                        itemNum,mdItem->type,PS_DATA_VECTOR);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 5*(itemNum+1);
+            }
+            if(((psVector*)mdItem->data.V)->type.type != PS_TYPE_BOOL) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d vector type %d not as expected %d",
+                        itemNum,((psVector*)mdItem->data.V)->type.type, PS_TYPE_BOOL);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 6*(itemNum+1);
+            }
+            if(((psVector*)mdItem->data.V)->n != 3) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d vector size %d not as expected %d",
+                        itemNum,((psVector*)mdItem->data.V)->n,3);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 7*(itemNum+1);
+            }
+            if(strcmp(mdItem->name,TAB_COL_4_NAME) != 0) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d name %s not as expected %s",
+                        itemNum,mdItem->name,TAB_COL_4_NAME);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 8*(itemNum+1);
+            }
+            break;
+        case 2:
+            if(mdItem->type != PS_DATA_VECTOR) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d type %d not as expected %d",
+                        itemNum,mdItem->type,PS_DATA_VECTOR);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 5*(itemNum+1);
+            }
+            if(((psVector*)mdItem->data.V)->type.type != PS_TYPE_F64) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d vector type %d not as expected %d",
+                        itemNum,((psVector*)mdItem->data.V)->type.type, PS_TYPE_F64);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 6*(itemNum+1);
+            }
+            if(((psVector*)mdItem->data.V)->n != 3) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d vector size %d not as expected %d",
+                        itemNum,((psVector*)mdItem->data.V)->n,3);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 7*(itemNum+1);
+            }
+            if(strcmp(mdItem->name,TAB_COL_3_NAME) != 0) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d name %s not as expected %s",
+                        itemNum,mdItem->name,TAB_COL_3_NAME);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 8*(itemNum+1);
+            }
+            break;
+        case 3:
+            if(mdItem->type != PS_DATA_VECTOR) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d type %d not as expected %d",
+                        itemNum,mdItem->type,PS_DATA_VECTOR);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 5*(itemNum+1);
+            }
+            if(((psVector*)mdItem->data.V)->type.type != PS_TYPE_F32) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d vector type %d not as expected %d",
+                        itemNum,((psVector*)mdItem->data.V)->type.type, PS_TYPE_F32);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 6*(itemNum+1);
+            }
+            if(((psVector*)mdItem->data.V)->n != 3) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d vector size %d not as expected %d",
+                        itemNum,((psVector*)mdItem->data.V)->n,3);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 7*(itemNum+1);
+            }
+            if(strcmp(mdItem->name,TAB_COL_2_NAME) != 0) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d name %s not as expected %s",
+                        itemNum,mdItem->name,TAB_COL_2_NAME);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 8*(itemNum+1);
+            }
+            break;
+        case 4:
+            if(mdItem->type != PS_DATA_VECTOR) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d type %d not as expected %d",
+                        itemNum,mdItem->type,PS_DATA_VECTOR);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 5*(itemNum+1);
+            }
+            if(((psVector*)mdItem->data.V)->type.type != PS_TYPE_S32) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d vector type %d not as expected %d",
+                        itemNum,((psVector*)mdItem->data.V)->type.type, PS_TYPE_S32);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 6*(itemNum+1);
+            }
+            if(((psVector*)mdItem->data.V)->n != 3) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d vector size %d not as expected %d",
+                        itemNum,((psVector*)mdItem->data.V)->n,3);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 7*(itemNum+1);
+            }
+            if(strcmp(mdItem->name,TAB_COL_1_NAME) != 0) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d name %s not as expected %s",
+                        itemNum,mdItem->name,TAB_COL_1_NAME);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 8*(itemNum+1);
+            }
+            break;
+        case 5:
+            if(mdItem->type != PS_DATA_ARRAY) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d type %d not as expected %d",
+                        itemNum,mdItem->type,PS_DATA_ARRAY);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 5*(itemNum+1);
+            }
+            if(((psArray*)mdItem->data.V)->n != 3) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d vector size %d not as expected %d",
+                        itemNum,((psArray*)mdItem->data.V)->n,3);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 7*(itemNum+1);
+            }
+            if(strcmp(mdItem->name,TAB_COL_0_NAME) != 0) {
+                psError(PS_ERR_UNKNOWN,true,"Column #%d name %s not as expected %s",
+                        itemNum,mdItem->name,TAB_COL_0_NAME);
+                psDBDropTable(dbh,table);
+                psDBCleanup(dbh);
+                return 8*(itemNum+1);
+            }
+            break;
+
+        default:
+            break;
+        }
+        itemNum++;
+    }
+    psFree(mdIter);
+    psFree(meta);
+
+    // Attempt to dump columns from NULL database object
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL database");
+    if(psDBDumpCols(NULL,table) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL when dumping columns from NULL database");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 10;
+    }
+
+    // Attempt to dump columns for NULL table
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL table");
+    if(psDBDumpCols(dbh,NULL) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL when dumping columns from NULL table");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 11;
+    }
+
+
+    psDBDropTable(dbh, table);
+
+    psFree(md);
+
+    psDBCleanup(dbh);
+
+    return 0;
+}
+
+// Testpoint #852, TPDBUpdateRows shall update rows in a test table ...
+psS32 TPDBUpdateRows( void )
+{
+    psDB*            dbh       = NULL;
+    const char*      table     = "table10";
+    psArray*         ary       = NULL;
+    psArray*         rowSet    = NULL;
+    psMetadata*      row       = NULL;
+    psMetadata*      where     = NULL;
+    psMetadata*      updates   = NULL;
+    psMetadata*      md        = NULL;
+    int              chgRows   = 0;
+
+    // Create database table definition
+    md = _get_CreateTableMetadata();
+
+    // Initialize database connection
+    dbh = _init_psDB();
+    if (dbh == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return NULL when initializing database");
+        return 1;
+    }
+
+    // Create test table
+    if(!psDBCreateTable(dbh, table, md)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return false to create test table");
+        psDBCleanup(dbh);
+        return 2;
+    }
+
+    // Create array to hold rows to be added to test table
+    rowSet = psArrayAlloc(3);
+    rowSet->n = 0;
+
+    row = _get_const_row1();
+    psArrayAdd(rowSet, 0, row);
+    psFree(row);
+
+    row = _get_const_row2();
+    psArrayAdd(rowSet, 0, row);
+    psFree(row);
+
+    row = _get_row();
+    psArrayAdd(rowSet, 0, row);
+    psFree(row);
+
+    // Insert rows into test table
+    if(!psDBInsertRows(dbh, table, rowSet)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for inserting rows");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 3;
+    }
+
+    // Create where metadata to specify update - only one row
+    where = _get_where();
+
+    // Create update metadata to specify values
+    updates = _get_update_values(STR_2, S32_2, F32_2, F64_2, B_2);
+
+    // Perform database update with valid parameters
+    chgRows = psDBUpdateRows(dbh,table,where,updates);
+    if(chgRows != 1) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return other than 1 for valid arguments");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 4;
+    }
+    // Verify row contents after update
+    ary = psDBDumpRows(dbh, table);
+    if (ary == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return from dump rows");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 5;
+    }
+    row = (psMetadata*)psArrayGet(ary, 0);
+    if(!_check_row_update(row)) {
+        psError(PS_ERR_UNKNOWN,true,"Update row not verified");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 6;
+    }
+    //    psFree(row);
+    psFree(ary);
+
+    // Attempt to update rows with NULL database
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL database");
+    chgRows = psDBUpdateRows(NULL,table,where,updates);
+    if(chgRows != -1) {
+        psError(PS_ERR_UNKNOWN,true,"Updated rows %ld not as expected %ld",
+                chgRows,-1);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 7;
+    }
+
+    // Attempt to update rows with invalid table
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid table");
+    chgRows = psDBUpdateRows(dbh,"table999",where,updates);
+    if(chgRows != -1) {
+        psError(PS_ERR_UNKNOWN,true,"Updated rows %ld not as expected %ld",
+                chgRows,-1);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 8;
+    }
+
+    // Attempt to update rows with NULL updates
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL updates");
+    chgRows = psDBUpdateRows(dbh,table,where,NULL);
+    if(chgRows != -1) {
+        psError(PS_ERR_UNKNOWN,true,"Updated rows %ld not as expected %ld",
+                chgRows,-1);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 8;
+    }
+
+    // Attempt to update rows with invalid where specifying non-existent column
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid where");
+    psFree(where);
+    where = _get_invalid_where();
+    chgRows = psDBUpdateRows(dbh,table,where,updates);
+    if(chgRows != -1) {
+        psError(PS_ERR_UNKNOWN,true,"Updated rows %ld not as expected %ld",
+                chgRows,-1);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 9;
+    }
+
+    // Attempt to update rows with bad value in where statement
+    psFree(where);
+    where = _get_where_bad_value();
+    chgRows = psDBUpdateRows(dbh,table,where,updates);
+    if(chgRows != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Updated rows %ld not as expected %ld",
+                chgRows,0);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 10;
+    }
+    // Verify row contents after update - no change
+    ary = psDBDumpRows(dbh, table);
+    if (ary == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return from dump rows");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 11;
+    }
+    row = (psMetadata*)psArrayGet(ary, 0);
+    if(!_check_row_update(row)) {
+        psError(PS_ERR_UNKNOWN,true,"Update row not verified");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 12;
+    }
+    //    psFree(row);
+    psFree(ary);
+
+    psFree(updates);
+    psFree(where);
+    psFree(rowSet);
+    psDBDropTable(dbh, table);
+
+    psFree(md);
+    psDBCleanup(dbh);
+
+    return 0;
+}
+
+// Testpoint #853, TPDBDeleteRows shall update rows in a test table ...
+psS32 TPDBDeleteRows( void )
+{
+    psDB*         dbh       = NULL;
+    const char*   table     = "table11";
+    psArray*      ary       = NULL;
+    psArray*      rowSet    = NULL;
+    psMetadata*   where     = NULL;
+    psMetadata*   row       = NULL;
+    psMetadata*   md        = NULL;
+    int           chgRows   = 0;
+
+    // Create database table definition
+    md = _get_CreateTableMetadata();
+
+    // Initialize database connection
+    dbh = _init_psDB();
+    if (dbh == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return NULL for initialize database");
+        return 1;
+    }
+
+    // Create test table
+    if(!psDBCreateTable(dbh, table, md)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for creating test table");
+        psDBCleanup(dbh);
+        return 2;
+    }
+
+    // Create known data rows to put into test table
+    rowSet = psArrayAlloc(3);
+    rowSet->n = 0;
+    row = _get_const_row1();
+    psArrayAdd(rowSet, 0, row);
+    psFree(row);
+    row = _get_const_row2();
+    psArrayAdd(rowSet, 0, row);
+    psFree(row);
+    row = _get_row();
+    psArrayAdd(rowSet, 0, row);
+    psFree(row);
+    if(!psDBInsertRows(dbh, table, rowSet)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for inserting data into table");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 3;
+    }
+
+    // Create where clause to specify the row to remove
+    where = _get_where();
+
+    // Delete row with valid arguments
+    chgRows = psDBDeleteRows(dbh,table,where,10);
+    if(chgRows != 1) {
+        psError(PS_ERR_UNKNOWN,true,"Deleted rows %ld not as expected %ld",
+                chgRows,1);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 4;
+    }
+    // Verify table contents
+    ary = psDBDumpRows(dbh, table);
+    if (ary == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return NULL for dump rows");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 5;
+    }
+    if (ary->n != 2) {
+        psError(PS_ERR_UNKNOWN,true,"Remaining rows %d not as expected %d",
+                ary->n,2);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 6;
+    }
+    psFree(ary);
+
+    // Attempt to delete row just deleted again
+    chgRows = psDBDeleteRows(dbh,table,where,10);
+    if(chgRows != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Deleted rows %ld not as expected %ld",
+                chgRows,0);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 7;
+    }
+    // Verify table contents
+    ary = psDBDumpRows(dbh, table);
+    if (ary == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return NULL for dump rows");
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 8;
+    }
+    if (ary->n != 2) {
+        psError(PS_ERR_UNKNOWN,true,"Remaining rows %d not as expected %d",
+                ary->n,2);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 9;
+    }
+    psFree(ary);
+
+    // Attempt to delete row with NULL database
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL database");
+    chgRows = psDBDeleteRows(NULL,table,where,10);
+    if(chgRows > 0) {
+        psError(PS_ERR_UNKNOWN,true,"Deleted rows %ld not as expected %ld",
+                chgRows, -1);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 10;
+    }
+
+    // Attempt to delete row with invalid table
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid table");
+    chgRows = psDBDeleteRows(dbh,"table999",where,10);
+    if(chgRows > 0) {
+        psError(PS_ERR_UNKNOWN,true,"Deleted rows %ld not as expected %ld",
+                chgRows, -1);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 11;
+    }
+
+    // Attempt to delete row with NULL where - deletes all rows
+    chgRows = psDBDeleteRows(dbh,table,NULL,10);
+    if(chgRows != 2) {
+        psError(PS_ERR_UNKNOWN,true,"Deleted rows %ld not as expected %ld",
+                chgRows, 2);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 12;
+    }
+    // Verify table contents
+    ary = psDBDumpRows(dbh, table);
+    if (ary != NULL && ary->n != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Remaining rows %d not as expected %d",
+                ary->n,0);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 14;
+    }
+    psFree(ary);
+
+    // Attempt to delete row with NULL where - deletes all rows from an empty table
+    chgRows = psDBDeleteRows(dbh,table,NULL,10);
+    if(chgRows != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Deleted rows %ld not as expected %d",
+                chgRows, 0);
+        psDBDropTable(dbh,table);
+        psDBCleanup(dbh);
+        return 15;
+    }
+
+    psFree(where);
+    psFree(rowSet);
+    psDBDropTable(dbh, table);
+
+    psFree(md);
+    psDBCleanup(dbh);
+
+    return 0;
+}
+
+//
+// Tests for psDBCreate and psDBDrop can only be executed if the user
+// has system admin privileges for the SQL server so the tests have been
+// commented out.
+//
+// Testpoint #XXX, psDBCreate shall create a new test database.
+//psS32 TPDBCreate( void )
+//{
+//    const char *test_db = "ps_test_db";
+//    psS32 failed = 0;
+//    psDB *dbh = NULL;
+//
+//    dbh = _init_psDB();
+//    if (dbh == NULL) {
+//        return 1;
+//    }
+//
+//    psLogMsg( __func__, PS_LOG_INFO, "psDBCreate shall create new new test database.\n" );
+//
+//    failed = ! psDBCreate(dbh, test_db);
+//    if (!failed) {
+//        psDBDrop(dbh, test_db);
+//    }
+//
+//    psDBCleanup(dbh);
+//
+//    return failed;
+//}
+
+// Testpoint #XXX, psDBDrop shall create a new test database.
+//psS32 TPDBDrop( void )
+//{
+//    const char *test_db = "ps_test_db";
+//    psS32 failed = 0;
+//    psDB *dbh = NULL;
+//
+//    dbh = _init_psDB();
+//    if (dbh == NULL) {
+//        return 1;
+//    }
+//
+//    psLogMsg( __func__, PS_LOG_INFO, "psDBDrop shall create/drop a new new test database.\n" );
+//
+//    failed = psDBCreate(dbh, test_db);
+//    if (!failed) {
+//        failed = ! psDBDrop(dbh, test_db);
+//    }
+//
+//    psDBCleanup(dbh);
+//
+//    return failed;
+//}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/fft/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/fft/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/fft/.cvsignore	(revision 22158)
@@ -0,0 +1,15 @@
+temp
+.deps
+.libs
+Makefile
+Makefile.in
+tst_psImageFFT
+tst_psVectorFFT
+*.bb
+*.bbg
+*.da
+gmon.out
+tap_psImageFFT2
+tap_psVectorFFT2
+tap_psImageFFT
+tap_psVectorFFT
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/fft/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/fft/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/fft/Makefile.am	(revision 22158)
@@ -0,0 +1,26 @@
+AM_CPPFLAGS = \
+    $(SRCINC) \
+    -I$(top_srcdir)/test/tap/src \
+    -I$(top_srcdir)/test/pstap/src \
+    $(PSLIB_CFLAGS)
+
+AM_LDFLAGS = \
+    $(top_builddir)/src/libpslib.la  \
+    $(top_builddir)/test/tap/src/libtap.la \
+    $(top_builddir)/test/pstap/src/libpstap.la \
+    $(PSLIB_LIBS)
+
+TEST_PROGS = \
+	tap_psImageFFT \
+	tap_psVectorFFT
+
+if BUILD_TESTS
+bin_PROGRAMS = $(TEST_PROGS)
+TESTS = $(TEST_PROGS)
+else
+check_PROGRAMS = $(TEST_PROGS)
+endif
+
+CLEANFILES = $(check_DATA) temp/* core core.* *~ *.bb *.bbg *.da gmon.out
+
+test: check
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/fft/tap_psImageFFT.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/fft/tap_psImageFFT.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/fft/tap_psImageFFT.c	(revision 22158)
@@ -0,0 +1,129 @@
+#include <stdio.h>
+#include <math.h>
+#include <pslib.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+#define TOL 2.0e-5                      // Tolerance for comparison
+
+
+// Generate image with single high pixel
+static psImage *generateImage(int numCols, int numRows)
+{
+    psImage *image = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    for (int y = 0; y < numRows; y++) {
+        for (int x = 0; x < numCols; x++) {
+            image->data.F32[y][x] = 1.2 * cos(2.0 * M_PI * x / numCols + M_PI / 4.0) +
+                3.4 * sin(2.0 * M_PI * y / numRows + M_PI);
+        }
+    }
+    return image;
+}
+
+// FFT forward, then back --- do I get what I started with?
+// A total of 6 tests here.
+static void testFFT(int numCols, int numRows)
+{
+    psMemId id = psMemGetId();
+
+    psImage *old = generateImage(numCols, numRows);
+    psImage *fftReal = NULL, *fftImag = NULL;
+    bool result = psImageForwardFFT(&fftReal, &fftImag, old);
+    ok(result, "forward fft result");
+    skip_start(!result || !fftReal || !fftImag, 3, "forward fft failed");
+    ok(fftReal->type.type == PS_TYPE_F32 && fftImag->type.type == PS_TYPE_F32, "forward fft types");
+    psImage *new = NULL;
+    result = psImageBackwardFFT(&new, fftReal, fftImag, old->numCols);
+    ok(result, "backward fft result");
+    skip_start(!result || !new, 2, "backward fft failed");
+    ok(new->type.type == PS_TYPE_F32, "backward fft type");
+    float maxDev = 0.0;                 // Maximum deviation from expected
+    for (int y = 0; y < old->numRows; y++) {
+        for (int x = 0; x < old->numCols; x++) {
+            float dev = fabs(new->data.F32[y][x] / numCols / numRows - old->data.F32[y][x]);
+            if (dev > maxDev) {
+                maxDev = dev;
+            }
+        }
+    }
+    ok(maxDev < TOL, "maximum deviation: %f", maxDev);
+    psFree(new);
+    skip_end();
+    skip_end();
+
+    psFree(fftReal);
+    psFree(fftImag);
+    psFree(old);
+    ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+
+    return;
+}
+
+
+int main(int argc, char *argv[])
+{
+    plan_tests(8 + 6 * 5);
+
+    // Test with NULL real arg
+    {
+        psMemId id = psMemGetId();
+        psImage *real = psImageAlloc(512, 512, PS_TYPE_F32);
+        psImage *imag = psImageAlloc(512, 512, PS_TYPE_F32);
+        psImage *in = psImageAlloc(512, 512, PS_TYPE_F32);
+        bool rc = psImageForwardFFT(NULL, &imag, in);
+        ok(rc == false, "psImageForwardFFT() returned FALSE with a NULL real image input");
+        psFree(real);
+        psFree(imag);
+        psFree(in);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test with NULL imag arg
+    {
+        psMemId id = psMemGetId();
+        psImage *real = psImageAlloc(512, 512, PS_TYPE_F32);
+        psImage *imag = psImageAlloc(512, 512, PS_TYPE_F32);
+        psImage *in = psImageAlloc(512, 512, PS_TYPE_F32);
+        bool rc = psImageForwardFFT(&real, NULL, in);
+        ok(rc == false, "psImageForwardFFT() returned FALSE with a NULL imaginary image input");
+        psFree(real);
+        psFree(imag);
+        psFree(in);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test with NULL input arg
+    {
+        psMemId id = psMemGetId();
+        psImage *real = psImageAlloc(512, 512, PS_TYPE_F32);
+        psImage *imag = psImageAlloc(512, 512, PS_TYPE_F32);
+        psImage *in = psImageAlloc(512, 512, PS_TYPE_F32);
+        bool rc = psImageForwardFFT(&real, &imag, NULL);
+        ok(rc == false, "psImageForwardFFT() returned FALSE with a NULL real image input");
+        psFree(real);
+        psFree(imag);
+        psFree(in);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test with incorrect input image type
+    {
+        psMemId id = psMemGetId();
+        psImage *real = psImageAlloc(512, 512, PS_TYPE_F32);
+        psImage *imag = psImageAlloc(512, 512, PS_TYPE_F32);
+        psImage *in = psImageAlloc(512, 512, PS_TYPE_F64);
+        bool rc = psImageForwardFFT(NULL, &imag, in);
+        ok(rc == false, "psImageForwardFFT() returned FALSE with incorrect input image type");
+        psFree(real);
+        psFree(imag);
+        psFree(in);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    testFFT(10, 10);                    // Real quick test
+    testFFT(10, 20);                    // Testing differing numCols, numRows
+    testFFT(20, 10);                    // Testing differing numCols, numRows
+    testFFT(611, 610);                  // Test something like an OTA cell
+    testFFT(2048, 4096);                // Test something like a megacam chip
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/fft/tap_psVectorFFT.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/fft/tap_psVectorFFT.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/fft/tap_psVectorFFT.c	(revision 22158)
@@ -0,0 +1,123 @@
+#include <stdio.h>
+#include <math.h>
+#include <pslib.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+#define TOL 2.5e-5                      // Tolerance for comparison
+
+
+// Generate image with single high pixel
+static psVector *generateVector(long num)
+{
+    psVector *vector = psVectorAlloc(num, PS_TYPE_F32);
+    for (long i = 0; i < num; i++) {
+        vector->data.F32[i] = 1.2 * cos(2.0 * M_PI * i / num + M_PI / 4.0) +
+            3.4 * sin(0.5 * 2.0 * M_PI * i / num + M_PI);
+    }
+    return vector;
+}
+
+// FFT forward, then back --- do I get what I started with?
+// A total of 6 tests here.
+static void testFFT(long num)
+{
+    psMemId id = psMemGetId();
+
+    psVector *old = generateVector(num);
+    psVector *fftReal = NULL, *fftImag = NULL;
+    bool result = psVectorForwardFFT(&fftReal, &fftImag, old);
+    ok(result, "forward fft result");
+    skip_start(!result || !fftReal || !fftImag, 3, "forward fft failed");
+    ok(fftReal->type.type == PS_TYPE_F32 && fftImag->type.type == PS_TYPE_F32, "forward fft types");
+    psVector *new = NULL;
+    result = psVectorBackwardFFT(&new, fftReal, fftImag, old->n);
+    ok(result, "backward fft result");
+    skip_start(!result || !new, 2, "backward fft failed");
+    ok(new->type.type == PS_TYPE_F32, "backward fft type");
+    float maxDev = 0.0;                 // Maximum deviation from expected
+    for (long i = 0; i < old->n; i++) {
+        float dev = fabs(new->data.F32[i] / num - old->data.F32[i]);
+        if (dev > maxDev) {
+            maxDev = dev;
+        }
+    }
+    ok(maxDev < TOL, "maximum deviation: %f", maxDev);
+    psFree(new);
+    skip_end();
+    skip_end();
+
+    psFree(fftReal);
+    psFree(fftImag);
+    psFree(old);
+    ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+
+    return;
+}
+
+
+int main(int argc, char *argv[])
+{
+    plan_tests(8 + 6 * 3);
+
+    // Test with NULL real arg
+    {
+        psMemId id = psMemGetId();
+        psVector *real = psVectorAlloc(512, PS_TYPE_F32);;
+        psVector *imag = psVectorAlloc(512, PS_TYPE_F32);
+        psVector *in = psVectorAlloc(512, PS_TYPE_F32);
+        bool rc = psVectorForwardFFT(NULL, &imag, in);
+        ok(rc == false, "psVectorForwardFFT() returned FALSE with a null real vector input");
+        psFree(real);
+        psFree(imag);
+        psFree(in);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test with NULL imag arg
+    {
+        psMemId id = psMemGetId();
+        psVector *real = psVectorAlloc(512, PS_TYPE_F32);;
+        psVector *imag = psVectorAlloc(512, PS_TYPE_F32);
+        psVector *in = psVectorAlloc(512, PS_TYPE_F32);
+        bool rc = psVectorForwardFFT(&real, NULL, in);
+        ok(rc == false, "psVectorForwardFFT() returned FALSE with a null imag vector input");
+        psFree(real);
+        psFree(imag);
+        psFree(in);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test with NULL input arg
+    {
+        psMemId id = psMemGetId();
+        psVector *real = psVectorAlloc(512, PS_TYPE_F32);;
+        psVector *imag = psVectorAlloc(512, PS_TYPE_F32);
+        psVector *in = psVectorAlloc(512, PS_TYPE_F32);
+        bool rc = psVectorForwardFFT(&real, &imag, NULL);
+        ok(rc == false, "psVectorForwardFFT() returned FALSE with a null input vector input");
+        psFree(real);
+        psFree(imag);
+        psFree(in);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test with incorrect type for input arg
+    {
+        psMemId id = psMemGetId();
+        psVector *real = psVectorAlloc(512, PS_TYPE_F32);;
+        psVector *imag = psVectorAlloc(512, PS_TYPE_F32);
+        psVector *in = psVectorAlloc(512, PS_TYPE_F64);
+        bool rc = psVectorForwardFFT(&real, &imag, in);
+        ok(rc == false, "psVectorForwardFFT() returned FALSE with a incorrect input vector type");
+        psFree(real);
+        psFree(imag);
+        psFree(in);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    testFFT(128);                       // Real quick test
+    testFFT(2048);                      // Test something big
+    testFFT(123456);                    // Test something really big
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/fft/tst_psImageFFT.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/fft/tst_psImageFFT.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/fft/tst_psImageFFT.c	(revision 22158)
@@ -0,0 +1,664 @@
+/** @file  tst_psImageFFT.c
+ *
+ *  @brief Contains the tests for psFFT.[ch]
+ *
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-07-13 02:46:59 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <complex.h>
+#include <math.h>
+#include <float.h>
+
+#include "psTest.h"
+#include "pslib_strict.h"
+
+#define GENIMAGE(img,c,r,TYP, valueFcn) \
+img = psImageAlloc(c,r,PS_TYPE_##TYP); \
+for (psU32 row=0;row<r;row++) { \
+    ps##TYP* imgRow = img->data.TYP[row]; \
+    for (psU32 col=0;col<c;col++) { \
+        imgRow[col] = (ps##TYP)(valueFcn); \
+    } \
+}
+
+static psS32 testImageFFT(void);
+static psS32 testImageRealImaginary(void);
+static psS32 testImageComplex(void);
+static psS32 testImageConjugate(void);
+static psS32 testImagePowerSpectrum(void);
+
+testDescription tests[] = {
+                              {testImageFFT,632,"psImageFFT",0,false},
+                              {testImageRealImaginary,633,"psImageRealImaginary",0,false},
+                              {testImageComplex,634,"psImageComplex",0,false},
+                              {testImageConjugate,635,"psImageConjugate",0,false},
+                              {testImagePowerSpectrum,636,"psImagePowerSpectrum",0,false},
+                              {NULL}
+                          };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    return (! runTestSuite(stderr,"psFFT",tests,argc,argv) );
+}
+
+psS32 testImageFFT(void)
+{
+    psImage* img = NULL;
+    psImage* img2 = NULL;
+    psImage* img3 = NULL;
+    psU32 m = 128;
+    psU32 n = 64;
+    psImage* img4 = NULL;
+    psImage* img5 = NULL;
+
+    /*
+    1. assign a image to a radial sinisoid
+    2. perform a forward transform
+    3. verify that the only significant component cooresponds to the freqency of the input in step 1.
+    4. perform a reverse transform
+    5. compare to original (should be equal to within a reasonable error)
+    */
+
+    // 1. assign a image to a radial sinisoid
+    GENIMAGE(img,m,n,F32, sinf((32.0f-row)/32.0f*M_PI)+sinf((64.0f-col)/64.0f*M_PI));
+
+    // 2. perform a forward transform
+    img2 = psImageFFT(img2,img,PS_FFT_FORWARD);
+    if (img2->type.type != PS_TYPE_C32) {
+        psError(PS_ERR_UNKNOWN, true,"FFT didn't produce complex values?");
+        return 1;
+    }
+    if (img2->numCols != m || img2->numRows != n) {
+        psError(PS_ERR_UNKNOWN, true,"FFT didn't produce proper size result (%dx%d vs. expected %dx%d).",
+                img2->numCols,img2->numRows,m,n);
+        return 2;
+    }
+
+    // 3. verify that the only significant component cooresponds to the freqency of the input in step 1.
+    for (psU32 row=0;row<n;row++) {
+        psC32* img2Row = img2->data.C32[row];
+        for (psU32 col=0;col<m;col++) {
+            psF32 mag = cabsf(img2Row[col])/m/n;
+            if (mag > 0.1f) {
+                // must be (0,1) or (0,n-1) or (1,0) or (m-1,0)
+                if (! (col == 0 && (row == 1 || row == n-1))
+                        && ! (row == 0 && (col==1 || col == m-1)) ) {
+                    psError(PS_ERR_UNKNOWN, true,"Result invalid at %d,%d (%.2f)",col,row,mag);
+                    return 3;
+                }
+            } else
+                if ( (col == 0 && (row == 1 || row == n-1))
+                        || (row == 0 && (col==1 || col == m-1)) ) {
+                    psError(PS_ERR_UNKNOWN, true,"Result invalid at %d,%d (%.2f)",col,row,mag);
+                    return 4;
+                }
+        }
+    }
+
+
+    // 4. perform a reverse transform
+    img3 = psImageFFT(img3,img2,PS_FFT_REVERSE);
+
+    if (img3->type.type != PS_TYPE_C32) {
+        psError(PS_ERR_UNKNOWN, true,"FFT didn't produce complex values?");
+        return 5;
+    }
+
+    if (img3->numCols != m || img3->numRows != n) {
+        psError(PS_ERR_UNKNOWN, true,"FFT didn't produce proper size result (%dx%d vs. expected %dx%d).",
+                img3->numCols,img3->numRows,m,n);
+        return 6;
+    }
+
+    for (psU32 row=0;row<n;row++) {
+        psC32* img3Row = img3->data.C32[row];
+        psF32* imgRow = img->data.F32[row];
+        for (psU32 col=0;col<m;col++) {
+            psF32 pixel = creal(img3Row[col])/m/n;
+            if (fabsf(pixel-imgRow[col]) > 0.1) {
+                psError(PS_ERR_UNKNOWN, true,"Reverse FFT didn't give original image back (%d,%d %.2f vs %.2f)",
+                        col,row,pixel,imgRow[col]);
+                return 7;
+            }
+        }
+    }
+
+    // 4. perform a reverse transform to real result
+    img3 = psImageFFT(img3,img2,PS_FFT_REVERSE|PS_FFT_REAL_RESULT);
+
+    if (img3->type.type != PS_TYPE_F32) {
+        char* typeStr;
+        PS_TYPE_NAME(typeStr,img3->type.type)
+        psError(PS_ERR_UNKNOWN, true,"FFT asked to make real result, but I got a %s type image?",typeStr);
+        return 8;
+    }
+
+    if (img3->numCols != m || img3->numRows != n) {
+        psError(PS_ERR_UNKNOWN, true,"FFT didn't produce proper size result (%dx%d vs. expected %dx%d).",
+                img3->numCols,img3->numRows,m,n);
+        return 9;
+    }
+
+    for (psU32 row=0;row<n;row++) {
+        psF32* img3Row = img3->data.F32[row];
+        psF32* imgRow = img->data.F32[row];
+        for (psU32 col=0;col<m;col++) {
+            psF32 pixel = img3Row[col]/m/n;
+            if (fabsf(pixel-imgRow[col]) > 0.1) {
+                psError(PS_ERR_UNKNOWN, true,"Reverse FFT didn't give original image back (%d,%d %.2f vs %.2f)",
+                        col,row,pixel,imgRow[col]);
+                return 10;
+            }
+        }
+    }
+
+    // check if error occurs if FORWARD and REVERSE are both given.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error.");
+    if (psImageFFT(NULL,img2,PS_FFT_REVERSE|PS_FFT_FORWARD) != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"PS_FFT_REVERSE|PS_FFT_FORWARD option produced something?");
+        return 11;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error.");
+    if (psImageFFT(NULL,img2,PS_FFT_FORWARD|PS_FFT_REAL_RESULT) != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"PS_FFT_FORWARD|PS_FFT_REAL_RESULT option produced something?");
+        return 12;
+    }
+
+    /* Verify return null and program execution doesn't stop if input image is null */
+    img4 = psImageFFT(NULL,NULL,PS_FFT_FORWARD);
+    if (img4 != NULL ) {
+        psError(PS_ERR_UNKNOWN, true,"psImageFFT should return null for a null input image.");
+        return 10;
+    }
+
+    /* Verify return null and program execution doesn't stop if input image is invalid direction */
+    GENIMAGE(img4,8,8,S8,row+col);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error for invalid direction.");
+    img5 = psImageFFT(NULL,img4,PS_FFT_REAL_RESULT);
+    if (img5 != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psImageFFT should return null for an invalid FFT direction.");
+        return 11;
+    }
+    psFree(img4);
+
+    psFree(img);
+    psFree(img2);
+    psFree(img3);
+
+    return 0;
+}
+
+psS32 testImageRealImaginary(void)
+{
+    psImage* img = NULL;
+    psImage* img2 = NULL;
+    psImage* img3 = NULL;
+    psImage* c64Img = NULL;
+    psImage* c64Img2 = NULL;
+    psImage* c64Img3 = NULL;
+    psImage* ncImg = NULL;
+    psImage* ncImg2 = NULL;
+    psImage* ncImg3 = NULL;
+
+    psU32 m = 128;
+    psU32 n = 64;
+
+    /*
+    1. create a C32 complex vector with distinctly different real and imaginary parts.
+    2. call psImageReal and psImageImaginary
+    3. compare results to the real/imaginary components of input
+    */
+
+    // 1. create a C32 complex vector with distinctly different real and imaginary parts.
+    GENIMAGE(img,m,n,C32, row + I * col);
+
+    // 2. call psImageReal and psImageImaginary
+    img2 = psImageReal(img2,img);
+    if (img2 == NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psImageReal returned a NULL?");
+        return 1;
+    }
+    if (img2->type.type != PS_TYPE_F32) {
+        psError(PS_ERR_UNKNOWN, true,"psImageReal returned a wrong type (%d)?",
+                img2->type.type);
+        return 2;
+    }
+
+    img3 = psImageImaginary(img3,img);
+    if (img3 == NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psImageImaginary returned a NULL?");
+        return 3;
+    }
+    if (img3->type.type != PS_TYPE_F32) {
+        psError(PS_ERR_UNKNOWN, true,"psImageImaginary returned a wrong type (%d)?",
+                img3->type.type);
+        return 4;
+    }
+
+    // 3. compare results to the real/imaginary components of input
+    for (psU32 row=0;row<n;row++) {
+        psF32* img2Row = img2->data.F32[row];
+        psF32* img3Row = img3->data.F32[row];
+        for (psU32 col=0;col<m;col++) {
+            if (fabsf(img2Row[col] - row) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN, true,"psImageReal didn't return the real portion at n=%d",
+                        n);
+                return 5;
+            }
+            if (fabsf(img3Row[col] - col) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN, true,"psImageImaginary didn't return the imag portion at n=%d",
+                        n);
+                return 6;
+            }
+        }
+    }
+
+    psFree(img);
+    psFree(img2);
+    psFree(img3);
+
+    /*
+    1. create a C64 complex vector with distinctly different real and imaginary parts.
+    2. call psImageReal and psImageImaginary
+    3. compare results to the real/imaginary components of input
+    */
+
+    // 1. create a C64 complex vector with distinctly different real and imaginary parts.
+    GENIMAGE(c64Img,m,n,C64, row + I * col);
+
+    // 2. call psImageReal and psImageImaginary
+    c64Img2 = psImageReal(c64Img2,c64Img);
+    if (c64Img2 == NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psImageReal returned a NULL?");
+        return 1;
+    }
+    if (c64Img2->type.type != PS_TYPE_F64) {
+        psError(PS_ERR_UNKNOWN, true,"psImageReal returned a wrong type (%d)?",
+                img2->type.type);
+        return 2;
+    }
+
+    c64Img3 = psImageImaginary(c64Img3,c64Img);
+    if (c64Img3 == NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psImageImaginary returned a NULL?");
+        return 3;
+    }
+    if (c64Img3->type.type != PS_TYPE_F64) {
+        psError(PS_ERR_UNKNOWN, true,"psImageImaginary returned a wrong type (%d)?",
+                c64Img3->type.type);
+        return 4;
+    }
+
+    // 3. compare results to the real/imaginary components of input
+    for (psU32 row=0;row<n;row++) {
+        psF64* img2Row = c64Img2->data.F64[row];
+        psF64* img3Row = c64Img3->data.F64[row];
+        for (psU32 col=0;col<m;col++) {
+            if (fabsf(img2Row[col] - row) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN, true,"psImageReal didn't return the real portion at n=%d",
+                        n);
+                return 5;
+            }
+            if (fabsf(img3Row[col] - col) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN, true,"psImageImaginary didn't return the imag portion at n=%d",
+                        n);
+                return 6;
+            }
+        }
+    }
+
+    GENIMAGE(ncImg,m,n,F32,row+col);
+    ncImg2 = psImageReal(ncImg2,ncImg);
+    ncImg3 = psImageImaginary(ncImg3,ncImg);
+    if(ncImg2 == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psImageReal returned NULL");
+        return 40;
+    }
+    if(ncImg2->type.type != PS_TYPE_F32) {
+        psError(PS_ERR_UNKNOWN,true,"psImageReal returned a wrong type");
+        return 41;
+    }
+    if(ncImg3 == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psImageImaginary returned NULL");
+        return 42;
+    }
+    if(ncImg3->type.type != PS_TYPE_F32) {
+        psError(PS_ERR_UNKNOWN,true,"psImageImaginary returned NULL");
+        return 43;
+    }
+    for(psU32 row=0; row<n; row++) {
+        psF32* ncImg2Row = ncImg2->data.F32[row];
+        psF32* ncImg3Row = ncImg3->data.F32[row];
+        for(psU32 col=0; col<m; col++) {
+            if(fabsf(ncImg2Row[col] - (row+col)) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN,true,"psImageReal didn't return the real portion");
+                return 45;
+            }
+            if(fabsf(ncImg3Row[col] - 0) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN,true,"psImageImaginary didn't return the imaginary portion");
+                return 46;
+            }
+        }
+    }
+    psFree(ncImg);
+    psFree(ncImg2);
+    psFree(ncImg3);
+
+    psFree(c64Img);
+    psFree(c64Img2);
+    psFree(c64Img3);
+
+    // Perform psImageReal with null input
+    if(psImageReal(NULL,NULL) != NULL ) {
+        psError(PS_ERR_UNKNOWN,true,"psImageReal did not return null with null input");
+        return 10;
+    }
+
+    // Perform psImageImaginary with null input
+    if(psImageImaginary(NULL,NULL) != NULL ) {
+        psError(PS_ERR_UNKNOWN,true,"psImageImaginary did not return null with null input");
+        return 10;
+    }
+
+    return 0;
+}
+
+psS32 testImageComplex(void)
+{
+    psImage* img = NULL;
+    psImage* img2 = NULL;
+    psImage* img3 = NULL;
+    psImage* c64Img = NULL;
+    psImage* c64Img2 = NULL;
+    psImage* c64Img3 = NULL;
+    psImage* pImg = NULL;
+    psImage* pImg2 = NULL;
+    psImage* pImg3 = NULL;
+
+    psU32 m = 128;
+    psU32 n = 64;
+
+    /*
+    1. create two unique psF32 vectors of the same size
+    2. call psImageComplex
+    3. verify that the result is a psC32
+    4. use crealf and cimagf on step 2 results
+    5. compare step 4 results to input.
+
+    6. create a psF32 and a psF64 vector of the same size
+    7. call psImageComplex
+    8. verify that an appropriate error occurred.
+
+    9. create two psf32 vectors of different sizes
+    10. call psImageComplex
+    11. verify thet an appropriate error occurred.
+    */
+
+    // 1. create two unique psF32 vectors of the same size
+    GENIMAGE(img,m,n,F32,row);
+    GENIMAGE(img2,m,n,F32,col);
+    GENIMAGE(c64Img,m,n,F64,row);
+    GENIMAGE(c64Img2,m,n,F64,col);
+    GENIMAGE(pImg,m,n,S16,row);
+    GENIMAGE(pImg2,m,n,S16,col);
+
+    // 2. call psImageComplex
+    img3 = psImageComplex(img3,img,img2);
+    c64Img3 = psImageComplex(c64Img3,c64Img,c64Img2);
+
+    // 3. verify that the result is a psC32
+    if (img3->type.type != PS_TYPE_C32) {
+        psError(PS_ERR_UNKNOWN, true,"Image Type from psImageComplex is not complex? (%d)",
+                img3->type.type);
+        return 1;
+    }
+    if (c64Img3->type.type != PS_TYPE_C64) {
+        psError(PS_ERR_UNKNOWN,true,"Image type from psImageComplex is not complex");
+        return 10;
+    }
+
+    // 4. call psImageReal and psImageImaginary on step 2 results (not needed, just use crealf/cimagf)
+    // 5. compare step 4 results to input.
+    for (psU32 row=0;row<n;row++) {
+        psC32* img3Row = img3->data.C32[row];
+        psC64* c64Img3Row = c64Img3->data.C64[row];
+        for (psU32 col=0;col<m;col++) {
+            if (fabsf(crealf(img3Row[col]) - row) > FLT_EPSILON ||
+                    fabsf(cimagf(img3Row[col]) - col) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN, true,"psImageComplex result is invalid (%d,%d, %.2f+%.2fi)",
+                        col,row,crealf(img3Row[col]),cimagf(img3Row[col]));
+                return 2;
+            }
+            if (fabsf(crealf(c64Img3Row[col]) - row) > FLT_EPSILON ||
+                    fabsf(cimagf(c64Img3Row[col]) - col) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN,true,"psImageComplex result is invalid");
+                return 3;
+            }
+        }
+    }
+
+    // 6. create a psF32 and a psF64 image of the same size
+    img2 = psImageRecycle(img2,m,n,PS_TYPE_F64);
+
+    // 7. call psImageComplex
+    psLogMsg(__func__,PS_LOG_INFO, "Following should be an error (type mismatch).");
+    img3 = psImageComplex(img3,img,img2);
+    // 8. verify that an appropriate error occurred. (this partially has to be done via inspection)
+    if (img3 != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psImageComplex returned a image though input types mismatched.");
+        return 3;
+    }
+
+    // 9. create two psf32 vectors of different sizes
+    img2 = psImageRecycle(img2,m/2,n,PS_TYPE_F32);
+
+    // 10. call psImageComplex
+    psLogMsg(__func__,PS_LOG_INFO, "Following should be an error (size mismatch).");
+    img3 = psImageComplex(img3,img,img2);
+
+    // 11. verify thet an appropriate error occurred.
+    if (img3 != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psImageComplex returned a image though input sizes mismatched.");
+        return 4;
+    }
+
+    // Perform psImageComplex with invalid type
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message.");
+    pImg3 = psImageComplex(pImg3,pImg,pImg2);
+    if ( pImg3 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psImageComplex did not return NULL");
+        return 50;
+    }
+
+    psFree(img);
+    psFree(img2);
+    psFree(img3);
+    psFree(c64Img);
+    psFree(c64Img2);
+    psFree(c64Img3);
+    psFree(pImg);
+    psFree(pImg2);
+
+    // Perform psImageComplex with null input
+    if(psImageComplex(NULL,NULL,NULL) != NULL ) {
+        psError(PS_ERR_UNKNOWN,true,"psImageComplex did not return null with null input");
+        return 20;
+    }
+
+    return 0;
+}
+
+psS32 testImageConjugate(void)
+{
+    psImage* img = NULL;
+    psImage* img2 = NULL;
+    psImage* c64Img = NULL;
+    psImage* c64Img2 = NULL;
+    psImage* pImg = NULL;
+    psImage* pImg2 = NULL;
+
+    psU32 m = 128;
+    psU32 n = 64;
+
+    /*
+    1. create a psC32 with unique real and imaginary values.
+    2. call psImageConjugate
+    3. verify result is psC32
+    4. verify each value is conjugate of input (a+bi -> a-bi)
+    */
+
+    // 1. create a psC32 with unique real and imaginary values.
+    GENIMAGE(img,m,n,C32, row + I * col);
+    GENIMAGE(c64Img,m,n,C64,row + I*col);
+    GENIMAGE(pImg,m,n,F32,row+col);
+
+    // 2. call psImageConjugate
+    img2 = psImageConjugate(img2,img);
+    c64Img2 = psImageConjugate(c64Img2,c64Img);
+    pImg2 = psImageConjugate(pImg2,pImg);
+
+    // 3. verify result is psC32
+    if (img2->type.type != PS_TYPE_C32) {
+        psError(PS_ERR_UNKNOWN, true,"the psImageConjugate didn't return a C32 image.");
+        return 1;
+    }
+    if (c64Img2->type.type != PS_TYPE_C64) {
+        psError(PS_ERR_UNKNOWN,true,"psImageConjugate did not return a C64 image");
+        return 10;
+    }
+    if (pImg2->type.type != PS_TYPE_F32) {
+        psError(PS_ERR_UNKNOWN,true,"psImageConjugate did not return a F32 image");
+        return 11;
+    }
+
+    // 4. verify each value is conjugate of input (a+bi -> a-bi)
+    for (psU32 row=0;row<n;row++) {
+        psC32* img2Row = img2->data.C32[row];
+        psC64* c64Img2Row = c64Img2->data.C64[row];
+        psF32* pImg2Row = pImg2->data.F32[row];
+        for (psU32 col=0;col<m;col++) {
+            if (fabsf(crealf(img2Row[col]) - row) > FLT_EPSILON ||
+                    fabsf(cimagf(img2Row[col]) + col) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN, true,"psImageComplex result is invalid (%d,%d, %.2f+%.2fi)",
+                        col,row,crealf(img2Row[col]),cimagf(img2Row[col]));
+                return 2;
+            }
+            if (fabsf(crealf(c64Img2Row[col]) - row) > FLT_EPSILON ||
+                    fabsf(cimagf(c64Img2Row[col]) + col) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN,true,"psImageComplex result is invalid");
+                return 20;
+            }
+            if (fabsf(pImg2Row[col] - (row+col)) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN,true,"psImageComplex result is invalid");
+                return 21;
+            }
+        }
+    }
+
+    psFree(img);
+    psFree(img2);
+    psFree(c64Img);
+    psFree(c64Img2);
+    psFree(pImg);
+    psFree(pImg2);
+
+    // Perform psImageConjugate with null input
+    if(psImageConjugate(NULL,NULL) != NULL ) {
+        psError(PS_ERR_UNKNOWN,true,"psImageConjugate did not return null with null input");
+        return 30;
+    }
+
+    return 0;
+}
+
+psS32 testImagePowerSpectrum(void)
+{
+    psImage* img = NULL;
+    psImage* img2 = NULL;
+    psImage* c64Img = NULL;
+    psImage* c64Img2 = NULL;
+    psImage* pImg = NULL;
+
+    psU32 m = 128;
+    psU32 n = 64;
+
+    /*
+    1. create a psC32 vector with unique real and imaginary components
+    2. call psImagePowerSpectrum
+    3. verify result is psF32
+    4. verify the values are the square of the absolute values of the original
+    */
+
+    // 1. create a psC32 vector with unique real and imaginary components
+    GENIMAGE(img,m,n,C32, row + I * col);
+    GENIMAGE(c64Img,m,n,C64,row+I*col);
+    GENIMAGE(pImg,m,n,F32,row+col);
+
+    // 2. call psImagePowerSpectrum
+    img2 = psImagePowerSpectrum(img2,img);
+    c64Img2 = psImagePowerSpectrum(c64Img2, c64Img);
+
+    // 3. verify result is psF32
+    if (img2->type.type != PS_TYPE_F32) {
+        psError(PS_ERR_UNKNOWN, true,"the type was not PS_TYPE_F32.");
+        return 1;
+    }
+    if (c64Img2->type.type != PS_TYPE_F64) {
+        psError(PS_ERR_UNKNOWN,true,"psImagePowerSpectrum did not return PS_TYPE_F64");
+        return 10;
+    }
+
+    // 4. verify the values are the square of the absolute values of the original
+    for (psU32 row=0;row<n;row++) {
+        psC32* imgRow = img->data.C32[row];
+        psF32* img2Row = img2->data.F32[row];
+        psC64* c64ImgRow = c64Img->data.C64[row];
+        psF64* c64Img2Row = c64Img2->data.F64[row];
+        for (psU32 col=0;col<m;col++) {
+            psF32 power = cabs(imgRow[col]);
+            psF64 power64 = cabs(c64ImgRow[col]);
+            power *= power/n/n/m/m;
+            power64 *= power64/n/n/m/m;
+
+            if (fabsf(img2Row[col] - power) > 2.0f*FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN, true,"psImagePowerSpectrum result is invalid (%d,%d, %.2f vs %.2f)",
+                        col,row,img2Row[col],power);
+                return 2;
+            }
+            if (fabsf(c64Img2Row[col] - power64) > 2.0f*FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN,true,"psImagePowerSpectrum result is invalid");
+                return 22;
+            }
+        }
+    }
+
+    psFree(img);
+    psFree(img2);
+    psFree(c64Img);
+    psFree(c64Img2);
+
+    // Perform psImagePowerSpectrum with invalid input
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message.");
+    if(psImagePowerSpectrum(NULL,pImg) != NULL ) {
+        psError(PS_ERR_UNKNOWN,true,"psImagePowerSpectrum did not return null with invalid type");
+        return 41;
+    }
+    psFree(pImg);
+
+    // Perform psImagePowerSpectrum with null input
+    if(psImagePowerSpectrum(NULL,NULL) != NULL ) {
+        psError(PS_ERR_UNKNOWN,true,"psImagePowerSpectrum did not return null with null input");
+        return 40;
+    }
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/fft/tst_psVectorFFT.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/fft/tst_psVectorFFT.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/fft/tst_psVectorFFT.c	(revision 22158)
@@ -0,0 +1,642 @@
+/** @file  tst_psVectorFFT.c
+*
+*  @brief Contains the tests for psFFT.[ch]
+*
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-07-13 02:46:59 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#include <math.h>
+#include <float.h>
+
+#include "psTest.h"
+#include "pslib_strict.h"
+
+#define GENIMAGE(img,c,r,TYP, valueFcn) \
+img = psImageAlloc(c,r,PS_TYPE_##TYP); \
+for (psU32 row=0;row<r;row++) { \
+    ps##TYP* imgRow = img->data.TYP[row]; \
+    for (psU32 col=0;col<c;col++) { \
+        imgRow[col] = (ps##TYP)(valueFcn); \
+    } \
+}
+
+static psS32 testVectorFFT( void );
+static psS32 testVectorRealImaginary( void );
+static psS32 testVectorComplex( void );
+static psS32 testVectorConjugate( void );
+static psS32 testVectorPowerSpectrum( void );
+
+testDescription tests[] = {
+                              {testVectorFFT, 600, "psVectorFFT", 0, false},
+                              {testVectorRealImaginary, 601, "psVectorRealImaginary", 0, false},
+                              {testVectorComplex, 602, "psVectorComplex", 0, false},
+                              {testVectorConjugate, 603, "psVectorConjugate", 0, false},
+                              {testVectorPowerSpectrum, 604, "psVectorPowerSpectrum", 0, false},
+                              {NULL}
+                          };
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetLevel( PS_LOG_INFO );
+
+    return ( ! runTestSuite( stderr, "psFFT", tests, argc, argv ) );
+}
+
+psS32 testVectorFFT( void )
+{
+    psVector * vec = NULL;
+    psVector* vec2 = NULL;
+    psVector* vec3 = NULL;
+    psVector* vec4 = NULL;
+
+    /*
+    1. assign a vector to a sinisoid
+    2. perform a forward transform
+    3. verify that the only significant component cooresponds to the freqency of the input in step 1.
+    4. perform a reverse transform
+    5. compare to original (should be equal to within a reasonable error)
+    */
+
+    // 1. assign a vector to a sinisoid
+    vec = psVectorAlloc( 100, PS_TYPE_F32 );
+    vec->n = vec->nalloc;
+    for ( psU32 n = 0; n < 100; n++ ) {
+        vec->data.F32[ n ] = sinf( ( psF32 ) n / 50.0f * M_PI );
+    }
+
+    // 2. perform a forward transform
+    vec2 = psVectorFFT( NULL, vec, PS_FFT_FORWARD );
+    if ( vec2->type.type != PS_TYPE_C32 ) {
+        psError(PS_ERR_UNKNOWN,true, "FFT didn't produce complex values?" );
+        return 1;
+    }
+
+    // 2a. verify output vector is same size as input
+    if ( vec2->n != vec->n ) {
+        psError(PS_ERR_UNKNOWN,true, "FFT didn't return vector with same size as input");
+        return 10;
+    }
+
+
+    // 3. verify that the only significant component cooresponds to the freqency of the input in step 1.
+    for ( psU32 n = 0; n < 100; n++ ) {
+        if ( n == 1 || n == 99 ) {
+            if ( fabsf( cabsf( vec2->data.C32[ n ] ) - 50.0f ) > 0.1f ) {
+                psError(PS_ERR_UNKNOWN,true, "FFT didn't work for vector (n=%d)", n );
+                return 2;
+            }
+        } else {
+            if ( fabsf( cabsf( vec2->data.C32[ n ] ) ) > 0.1f ) {
+                psError(PS_ERR_UNKNOWN,true, "FFT didn't work for vector (n=%d)", n );
+                return 3;
+            }
+        }
+    }
+
+    // 4. perform a reverse transform
+    vec3 = psVectorFFT( NULL, vec2, PS_FFT_REVERSE );
+    if ( vec3->type.type != PS_TYPE_C32 ) {
+        psError(PS_ERR_UNKNOWN,true, "FFT didn't produce complex values?" );
+        return 4;
+    }
+    if ( vec3->n != vec2->n ) {
+        psError(PS_ERR_UNKNOWN,true, "FFT didn't return vector with same size as input");
+        return 40;
+    }
+    for ( psU32 n = 0; n < 100; n++ ) {
+        psF32 val = sinf( ( psF32 ) n / 50.0f * M_PI );
+        psF32 vecVal = crealf( vec3->data.C32[ n ] ) / 100;
+        if ( fabsf( vecVal - val ) > 0.1f ) {
+            psError(PS_ERR_UNKNOWN,true, "Reverse FFT didn't give me the original vector back (n=%d) (%.2f vs %.2f)",
+                    n, vecVal, val );
+            return 5;
+        }
+    }
+
+    // Perform a reverse transform with real flag set
+    vec4 = psVectorFFT(NULL,vec2, (PS_FFT_REVERSE | PS_FFT_REAL_RESULT));
+    if(vec4->type.type != PS_TYPE_F32) {
+        psError(PS_ERR_UNKNOWN,true,"FFT with real result did not produce real values");
+        return 80;
+    }
+
+    // Perform vector FFT with invalid direction flags
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message.");
+    if ( psVectorFFT(NULL,vec2,(psFFTFlags)0) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with invalid direction");
+        return 70;
+    }
+
+    psFree( vec );
+    psFree( vec2 );
+    psFree( vec3 );
+    psFree( vec4 );
+
+    // Perform vector FFT with null input
+    if ( psVectorFFT(NULL,NULL,PS_FFT_FORWARD) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with null input vector");
+        return 64;
+    }
+
+    return 0;
+}
+
+psS32 testVectorRealImaginary( void )
+{
+    psVector * vec = NULL;
+    psVector* vec2 = NULL;
+    psVector* vec3 = NULL;
+    psVector* vec4 = NULL;
+    psVector* vec5 = NULL;
+    psVector* vec6 = NULL;
+    psVector* vec7 = NULL;
+    psVector* vec8 = NULL;
+    psVector* vec9 = NULL;
+    psVector* vec10 = NULL;
+    psVector* vec11 = NULL;
+
+    /*
+    1. create a C32 complex vector with distinctly different real and imaginary parts.
+    2. call psVectorReal and psVectorImaginary
+    3. compare results to the real/imaginary components of input
+    */
+
+    // 1. create a C32 complex vector with distinctly different real and imaginary parts.
+    vec = psVectorAlloc( 100, PS_TYPE_C32 );
+    vec8 = psVectorAlloc( 100, PS_TYPE_C64 );
+    vec10 = psVectorAlloc( 100, PS_TYPE_C64 );
+    vec->n = vec->nalloc;
+    vec8->n = vec8->nalloc;
+    vec10->n = vec10->nalloc;
+    for ( psU32 n = 0; n < 100; n++ ) {
+        vec->data.C32[ n ] = n + I * ( n * 2 );
+        vec8->data.C64[n] = n + I * ( n * 2 );
+        vec10->data.C64[n] = n + I * ( n * 2 );
+    }
+    vec4 = psVectorAlloc( 100, PS_TYPE_F32);
+    vec4->n = vec4->nalloc;
+    vec6 = psVectorAlloc( 100, PS_TYPE_F32);
+    vec6->n = vec6->nalloc;
+    for ( psU32 n = 0; n < 100; n++ ) {
+        vec4->data.F32[n] = n;
+        vec6->data.F32[n] = n;
+    }
+
+    // 2. call psVectorReal and psVectorImaginary
+    vec2 = psVectorReal( vec2, vec );
+    if ( vec2 == NULL ) {
+        psError(PS_ERR_UNKNOWN,true, "psVectorReal returned a NULL?" );
+        return 1;
+    }
+    if ( vec2->type.type != PS_TYPE_F32 ) {
+        psError(PS_ERR_UNKNOWN,true, "psVectorReal returned a wrong type (%d)?",
+                vec2->type.type );
+        return 2;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate a warning.");
+    vec5 = psVectorReal(vec5, vec4);
+    if (vec5 == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psVectorReal returned NULL");
+        return 10;
+    }
+    if ( vec5->type.type != PS_TYPE_F32) {
+        psError(PS_ERR_UNKNOWN,true,"psVectorReal returned the wrong type");
+        return 11;
+    }
+
+    vec9 = psVectorReal(vec9,vec8);
+    if(vec9 == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psVectorReal returned NULL");
+        return 20;
+    }
+    if(vec9->type.type != PS_TYPE_F64) {
+        psError(PS_ERR_UNKNOWN,true,"psVectorReal returned the wrong type");
+        return 21;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate a warning.");
+    vec3 = psVectorImaginary( vec3, vec );
+    if ( vec3 == NULL ) {
+        psError(PS_ERR_UNKNOWN,true, "psVectorImaginary returned a NULL?" );
+        return 3;
+    }
+    if ( vec3->type.type != PS_TYPE_F32 ) {
+        psError(PS_ERR_UNKNOWN,true, "psVectorImaginary returned a wrong type (%d)?",
+                vec3->type.type );
+        return 4;
+    }
+
+    vec7 = psVectorImaginary(vec7, vec6);
+    if(vec7 == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psVectorImage returned NULL");
+        return 12;
+    }
+    if(vec7->type.type != PS_TYPE_F32) {
+        psError(PS_ERR_UNKNOWN,true,"psVectorImaginary returned the wrong type");
+        return 13;
+    }
+
+    vec11 = psVectorImaginary(vec11, vec10);
+    if(vec11 == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psVectorImaginary returned NULL");
+        return 14;
+    }
+    if(vec11->type.type != PS_TYPE_F64) {
+        psError(PS_ERR_UNKNOWN,true,"psVectorImaginary returned the wrong type");
+        return 15;
+    }
+
+    // 3. compare results to the real/imaginary components of input
+    for ( psU32 n = 0; n < 100; n++ ) {
+        psF32 r = n;
+        psF32 i = ( n * 2 );
+        psF64 rr = n;
+        psF64 ii = ( n * 2 );
+        if ( fabsf( vec2->data.F32[ n ] - r ) > FLT_EPSILON ) {
+            psError(PS_ERR_UNKNOWN,true, "psVectorReal didn't return the real portion at n=%d",
+                    n );
+            return 5;
+        }
+        if ( fabsf( vec3->data.F32[ n ] - i ) > FLT_EPSILON ) {
+            psError(PS_ERR_UNKNOWN,true, "psVectorImaginary didn't return the real portion at n=%d",
+                    n );
+            return 6;
+        }
+        if ( fabsf( vec5->data.F32[n] - r) > FLT_EPSILON) {
+            psError(PS_ERR_UNKNOWN,true,"psVectorReal didn't return the real portion at n=%d",n);
+            return 50;
+        }
+        if ( fabsf( vec7->data.F32[n] - 0) > FLT_EPSILON) {
+            psError(PS_ERR_UNKNOWN,true,"psVectorImaginary did not return the imaginary portion at n=%d",n);
+            return 51;
+        }
+        if ( fabsf(vec9->data.F64[n] - rr) > FLT_EPSILON ) {
+            psError(PS_ERR_UNKNOWN,true,"psVectorReal did not return the real portion at n=%d",n);
+            return 52;
+        }
+        if ( fabsf(vec11->data.F64[n] - ii) > FLT_EPSILON) {
+            psError(PS_ERR_UNKNOWN,true,"psVectorImaginary did not return the imaginary portion at n=%d",n);
+            return 53;
+        }
+    }
+
+    psFree( vec );
+    psFree( vec2 );
+    psFree( vec3 );
+    psFree( vec4 );
+    psFree( vec5 );
+    psFree( vec6 );
+    psFree( vec7 );
+    psFree( vec8 );
+    psFree( vec9 );
+    psFree( vec10 );
+    psFree( vec11 );
+
+    // Perform vector Real with null input
+    if ( psVectorReal(NULL,NULL) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with null input vector");
+        return 63;
+    }
+    // Perform vector Imaginary with null input
+    if ( psVectorImaginary(NULL,NULL) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with null input vector");
+        return 73;
+    }
+
+    return 0;
+}
+
+psS32 testVectorComplex( void )
+{
+    psVector * vec = NULL;
+    psVector* vec2 = NULL;
+    psVector* vec3 = NULL;
+    psVector* vec4 = NULL;
+    psVector* vec5 = NULL;
+    psVector* vec6 = NULL;
+
+    /*
+    1. create two unique psF32 vectors of the same size
+    2. call psVectorComplex
+    3. verify that the result is a psC32
+    4. call psVectorReal and psVectorImaginary on step 2 results
+    5. compare step 4 results to input.
+
+    6. create a psF32 and a psF64 vector of the same size
+    7. call psVectorComplex
+    8. verify that an appropriate error occurred.
+
+    9. create two psf32 vectors of different sizes
+    10. call psVectorComplex
+    11. verify thet an appropriate error occurred.
+    */
+
+    // 1. create two unique psF32 vectors of the same size
+    vec = psVectorAlloc( 100, PS_TYPE_F32 );
+    vec2 = psVectorAlloc( 100, PS_TYPE_F32 );
+    vec4 = psVectorAlloc( 100, PS_TYPE_F64 );
+    vec5 = psVectorAlloc( 100, PS_TYPE_F64 );
+    vec->n = vec->nalloc;
+    vec2->n = vec2->nalloc;
+    vec4->n = vec4->nalloc;
+    vec5->n = vec5->nalloc;
+    for ( psU32 n = 0; n < 100; n++ ) {
+        vec->data.F32[ n ] = n;
+        vec2->data.F32[ n ] = ( n * 2 );
+        vec4->data.F64[ n ] = n;
+        vec5->data.F64[ n ] = ( n * 2 );
+    }
+
+    // 2. call psVectorComplex
+    vec3 = psVectorComplex( vec3, vec, vec2 );
+
+    // 3. verify that the result is a psC32
+    if ( vec3->type.type != PS_TYPE_C32 ) {
+        psError(PS_ERR_UNKNOWN,true, "Vector Type from psVectorComplex is not complex? (%d)",
+                vec3->type.type );
+        return 1;
+    }
+
+    // 4. call psVectorReal and psVectorImaginary on step 2 results (not needed, just use crealf/cimagf)
+    // 5. compare step 4 results to input.
+    for ( psU32 n = 0; n < 100; n++ ) {
+        if ( fabsf( crealf( vec3->data.C32[ n ] ) - n ) > FLT_EPSILON ||
+                fabsf( cimagf( vec3->data.C32[ n ] ) - ( n * 2 ) ) > FLT_EPSILON ) {
+            psError(PS_ERR_UNKNOWN,true, "psVectorComplex result is invalid (n=%d, %.2f+%.2fi)",
+                    n, crealf( vec3->data.C32[ n ] ), cimagf( vec3->data.C32[ n ] ) );
+            return 2;
+        };
+    }
+
+
+    // 6. create a psF32 and a psF64 vector of the same size
+    vec2 = psVectorRecycle( vec2, 100, PS_TYPE_F64 );
+
+    // 7. call psVectorComplex
+    psLogMsg(__func__, PS_LOG_INFO, "Following should be an error (type mismatch)." );
+    vec3 = psVectorComplex( vec3, vec, vec2 );
+    // 8. verify that an appropriate error occurred. (this partially has to be done via inspection)
+    if ( vec3 != NULL ) {
+        psError(PS_ERR_UNKNOWN,true, "psVectorComplex returned a vector though input types mismatched." );
+        return 3;
+    }
+
+    // 9. create two psf32 vectors of different sizes
+    vec2 = psVectorRecycle( vec2, 200, PS_TYPE_F32 );
+
+    // 10. call psVectorComplex
+    vec3 = psVectorComplex( vec3, vec, vec2 );
+
+    // 11. verify thet an appropriate error occurred. (actually, it isn't an error...)
+    if ( vec3->n != 100 ) {
+        psError(PS_ERR_UNKNOWN,true, "psVectorComplex returned a larger vector than the input supported (%d).", vec3->n );
+        return 4;
+    }
+
+    // Verify the function works with psF64 type
+    vec6 = psVectorComplex(vec6, vec4, vec5);
+    if( vec6->type.type != PS_TYPE_C64 ) {
+        psError(PS_ERR_UNKNOWN,true,"Vector return type is not complex");
+        return 40;
+    }
+
+    // Verify error message generated with input of invalid type
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message.");
+    vec4->type.type = PS_TYPE_S8;
+    vec5->type.type = PS_TYPE_S8;
+    vec6 = psVectorComplex(vec6, vec4, vec5);
+    if(vec6 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL for invalid type");
+        return 50;
+    }
+    vec4->type.type = PS_TYPE_F64;
+    vec5->type.type = PS_TYPE_F64;
+
+    psFree( vec );
+    psFree( vec2 );
+    psFree( vec3 );
+    psFree( vec4 );
+    psFree( vec5 );
+
+    // Perform vector complex with null input
+    if ( psVectorComplex(NULL,NULL,NULL) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with null input vector");
+        return 62;
+    }
+
+    return 0;
+}
+
+psS32 testVectorConjugate( void )
+{
+    psVector * vec = NULL;
+    psVector* vec2 = NULL;
+
+    /*
+    1. create a psC32 with unique real and imaginary values.
+    2. call psVectorConjugate
+    3. verify result is psC32
+    4. verify each value is conjugate of input (a+bi -> a-bi)
+    */
+
+    // 1. create a psC32 with unique real and imaginary values.
+    vec = psVectorAlloc( 100, PS_TYPE_C32 );
+    vec->n = vec->nalloc;
+    for ( psU32 n = 0; n < 100; n++ ) {
+        vec->data.C32[ n ] = n + I * ( n * 2 );
+    }
+
+    // 2. call psVectorConjugate
+    vec2 = psVectorConjugate( vec2, vec );
+
+    // 3. verify result is psC32
+    if ( vec2->type.type != PS_TYPE_C32 ) {
+        psError(PS_ERR_UNKNOWN,true, "the psVectorConjugate didn't return a C32 vector" );
+        return 1;
+    }
+
+    // 4. verify each value is conjugate of input (a+bi -> a-bi)
+    for ( psU32 n = 0; n < 100; n++ ) {
+        if ( fabsf( crealf( vec->data.C32[ n ] ) - crealf( vec2->data.C32[ n ] ) ) > FLT_EPSILON ||
+                fabsf( cimagf( vec->data.C32[ n ] ) + cimagf( vec2->data.C32[ n ] ) ) > FLT_EPSILON ) {
+            psError(PS_ERR_UNKNOWN,true, "psVectorConjugate result is invalid (n=%d, %.2f+%.2fi)",
+                    n, crealf( vec2->data.C32[ n ] ), cimagf( vec2->data.C32[ n ] ) );
+            return 2;
+        };
+    }
+
+    psFree( vec );
+
+    // Perform conjugate for non-complex number
+    vec = psVectorAlloc( 100, PS_TYPE_F32 );
+    vec->n = vec->nalloc;
+    for ( psU32 n = 0; n < 100; n++ ) {
+        vec->data.F32[ n ] = n;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate a warning message.");
+    vec2 = psVectorConjugate(vec2,vec);
+    if(vec2->type.type != PS_TYPE_F32) {
+        psError(PS_ERR_UNKNOWN,true,"psVectorConjugate did not return a F32 vector");
+        return 10;
+    }
+    for ( psU32 n = 0; n < 100; n++ ) {
+        if( vec->data.F32[n] != vec2->data.F32[n] ) {
+            psError(PS_ERR_UNKNOWN,true,"psVectorConjugate result is invalid (n=%d)",n);
+            return 11;
+        }
+    }
+    psFree(vec);
+
+    // Perform vector conjugate with C64 type
+    vec = psVectorAlloc( 100, PS_TYPE_C64 );
+    vec->n = vec->nalloc;
+    for ( psU32 n = 0; n < 100; n++ ) {
+        vec->data.C64[n] = n + I * ( n * 2 );
+    }
+    vec2 = psVectorConjugate(vec2,vec);
+    if(vec2->type.type != PS_TYPE_C64) {
+        psError(PS_ERR_UNKNOWN,true,"psVectorConjugate did not return a C64 vector");
+        return 12;
+    }
+    for ( psU32 n = 0; n < 100; n++ ) {
+        if ( fabsf( crealf(vec->data.C64[n]) - crealf(vec2->data.C64[n])) > FLT_EPSILON ||
+                fabsf( cimagf(vec->data.C64[n]) + cimagf(vec2->data.C64[n])) > FLT_EPSILON ) {
+            psError(PS_ERR_UNKNOWN,true,"psVectorConjugate result is invalid (n=%d)",n);
+            return 13;
+        }
+    }
+    psFree(vec);
+
+    // Perform vector conjugate with null input (vec2 should be freed too)
+    if ( psVectorConjugate(vec2,NULL) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with null input vector");
+        return 61;
+    }
+
+    return 0;
+}
+
+psS32 testVectorPowerSpectrum( void )
+{
+    psVector * vec = NULL;
+    psVector* vec2 = NULL;
+    psVector* vec3 = NULL;
+    psVector* vec4 = NULL;
+
+    psF32 val;
+    psF64 val1;
+
+    /*
+    1. create a psC32 vector with unique real and imaginary components
+    2. call psVectorPowerSpectrum
+    3. verify result is psF32
+    4. verify the values are the square of the absolute values of the original
+    */
+
+    // 1. create a psC32 vector with unique real and imaginary components
+    vec = psVectorAlloc( 100, PS_TYPE_C32 );
+    vec->n = vec->nalloc;
+    vec3 = psVectorAlloc(100,PS_TYPE_C64);
+    vec3->n = vec3->nalloc;
+    for ( psU32 n = 0; n < 100; n++ ) {
+        vec->data.C32[ n ] = n + I * sinf( ( ( psF32 ) n ) / 50.f * M_PI );
+        vec3->data.C64[ n ] = n + I * sinf( ( ( psF64 ) n ) / 50.f * M_PI );
+    }
+
+    // 2. call psVectorPowerSpectrum
+    vec2 = psVectorPowerSpectrum( vec2, vec );
+    vec4 = psVectorPowerSpectrum( vec4, vec3 );
+
+    // 3. verify result is psF32
+    if ( vec2->type.type != PS_TYPE_F32 ) {
+        psError(PS_ERR_UNKNOWN,true, "the type was not PS_TYPE_F32." );
+        return 1;
+    }
+    if ( vec4->type.type != PS_TYPE_F64 ) {
+        psError(PS_ERR_UNKNOWN,true,"psPowerSpectrum did not return type PS_TYPE_F64 type = %d",vec4->type.type);
+        return 20;
+    }
+
+    // 3a. verify result is the same size a input
+    // Awaiting IfA direction on bug #228
+    //    if ( vec2->n != vec->n ) {
+    //       psError(PS_ERR_UNKNOWN,true, "Output vector size different(%d) than input vector(%d)",vec2->n, vec->n);
+    //       return 10;
+    //    }
+
+    // 4. verify the values are the square of the absolute values of the original
+    //   (ADD specifies something else)
+    //   P_0 = |C_0|^2/N^2
+    //   P_j = (|C_j|^2+|C_N-j|^2)/N^2
+    //   P_N/2 = |C_N/2|^2/N^2
+    //  where j = 1,2,...,(N/2-1)
+
+    val = cabsf( vec->data.C32[ 0 ] ) * cabsf( vec->data.C32[ 0 ] ) / 100 / 100;
+    val1= cabsf( vec3->data.C64[0] ) * cabsf(vec3->data.C64[0])/100/100;
+    if ( fabsf( vec2->data.F32[ 0 ] - val ) > FLT_EPSILON ) {
+        psError(PS_ERR_UNKNOWN,true, "psVectorPowerSpectrum result is invalid (n=0, %.2f %.2f)",
+                vec2->data.F32[ 0 ], val );
+        return 2;
+    }
+    if ( fabsf( vec4->data.C64[0] - val1 ) > FLT_EPSILON ) {
+        psError(PS_ERR_UNKNOWN,true,"psVectorPowerSpectrum result is invalid (n=0)");
+        return 21;
+    }
+
+    for ( psU32 n = 1; n < 50; n++ ) {
+        val = ( cabsf( vec->data.C32[ n ] ) * cabsf( vec->data.C32[ n ] ) +
+                cabsf( vec->data.C32[ 100 - n ] ) * cabsf( vec->data.C32[ 100 - n ] ) ) / 100 / 100;
+        val1 = (cabsf(vec3->data.C64[n]) * cabsf(vec3->data.C64[n]) +
+                cabsf(vec3->data.C64[100-n]) * cabsf(vec3->data.C64[100-n]))/100/100;
+        if ( fabsf( val - vec2->data.F32[ n ] ) > 10*FLT_EPSILON ) {
+            psError(PS_ERR_UNKNOWN,true, "psVectorPowerSpectrum result is invalid (n=%d, %.2f %.2f)",
+                    n, vec2->data.F32[ n ], val );
+            return 2;
+        }
+        if (fabsf(val1 - vec4->data.F64[n]) > 10*FLT_EPSILON) {
+            psError(PS_ERR_UNKNOWN,true,"psVectorPowerSpectrum result is invalid (n=%d, %.2f %.2f)",n,vec4->data.F64[n],val1);
+            return 22;
+        }
+    }
+
+    val = cabsf( vec->data.C32[ 50 ] ) * cabsf( vec->data.C32[ 50 ] ) / 100 / 100;
+    if ( fabsf( vec2->data.F32[ 50 ] - val ) > 10*FLT_EPSILON ) {
+        psError(PS_ERR_UNKNOWN,true, "psVectorPowerSpectrum result is invalid (n=50, %.2f %.2f)",
+                vec2->data.F32[ 0 ], val );
+        return 2;
+    };
+
+    psFree( vec );
+    psFree( vec2 );
+    psFree( vec3 );
+    psFree( vec4 );
+
+    // Perform vector power spectrum with non-complex number
+    vec = psVectorAlloc(100,PS_TYPE_F32);
+    vec->n = vec->nalloc;
+    for( psU32 n=0; n<100; n++) {
+        vec->data.F32[n] = n;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message.");
+    if(psVectorPowerSpectrum(NULL,vec) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psVectorPowerSpectrum did not return a null vector.");
+        return 10;
+    }
+
+    // Perform vector power spectrum with null input
+    if ( psVectorPowerSpectrum(NULL,NULL) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with null input vector");
+        return 60;
+    }
+
+    psFree(vec);
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/fits/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/fits/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/fits/.cvsignore	(revision 22158)
@@ -0,0 +1,15 @@
+temp
+.deps
+.libs
+Makefile
+Makefile.in
+multi.fits
+table.fits
+tmpImages
+tap_psFitsBlank_00
+*.bb
+*.bbg
+*.da
+gmon.out
+tap_psFits
+tap_psFitsImage
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/fits/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/fits/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/fits/Makefile.am	(revision 22158)
@@ -0,0 +1,30 @@
+AM_CPPFLAGS = \
+	$(SRCINC) \
+	-I$(top_srcdir)/test/tap/src \
+	-I$(top_srcdir)/test/pstap/src \
+	$(PSLIB_CFLAGS)
+AM_LDFLAGS = \
+	$(top_builddir)/src/libpslib.la  \
+	$(top_builddir)/test/tap/src/libtap.la \
+	$(top_builddir)/test/pstap/src/libpstap.la \
+	$(PSLIB_LIBS)
+
+TEST_PROGS = \
+	tap_psFits \
+	tap_psFitsBlank_00 \
+	tap_psFitsImage
+
+if BUILD_TESTS
+bin_PROGRAMS = $(TEST_PROGS)
+TESTS = $(TEST_PROGS)
+else
+check_PROGRAMS = $(TEST_PROGS)
+endif
+
+CLEANFILES = $(check_DATA) temp/* multi.fits table.fits tmpImages/* core core.* *~ \
+	*.bb *.bbg *.da gmon.out
+
+test: check
+
+tests: $(check_PROGRAMS)
+	$(top_srcdir)/test/test.pl
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/fits/tap_psFits.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/fits/tap_psFits.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/fits/tap_psFits.c	(revision 22158)
@@ -0,0 +1,1233 @@
+/** @file  tst_psFits.c
+*
+*  @brief Contains the tests for psFits.[ch]
+*
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-11-29 01:29:20 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#include <unistd.h>
+
+#define GENIMAGE(img,c,r,TYP, valueFcn) \
+img = psImageAlloc(c,r,PS_TYPE_##TYP); \
+for (psU32 row=0;row<r;row++) { \
+    ps##TYP* imgRow = img->data.TYP[row]; \
+    for (psU32 col=0;col<c;col++) { \
+        imgRow[col] = (ps##TYP)(valueFcn); \
+    } \
+}
+
+//static bool makeMulti(void);  // implicitly tests psFitsSetExtName
+//static bool makeTable(void);
+const char* multiFilename = "multi.fits";
+const char* tableFilename = "table.fits";
+const int tableNumRows = 10;
+
+
+// N.B., the tests to Image read/write was liberally taken from the now
+// deprecated psImageReadSection/psImageWriteSection function tests.
+
+bool makeMulti(void)
+{
+    psFits* fitsFile = psFitsOpen(multiFilename,"w");
+
+    if (fitsFile == NULL) {
+        diag("Could not create 'multi' FITS file");
+        return false;
+    }
+
+    psImage* image = psImageAlloc(16,16,PS_TYPE_F32);
+
+    char extname[80];
+    for (int lcv = 0; lcv < 8; lcv++) {
+        snprintf(extname,80,"ext-%d", lcv);
+
+        psMetadata* header = psMetadataAlloc();
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYINT",
+                      PS_DATA_S32,
+                      "psS32 Item", (psS32)lcv);
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYFLT",
+                      PS_DATA_F32,
+                      "psF32 Item", (float)(1.0f/(float)(1+lcv)));
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYDBL",
+                      PS_DATA_F64,
+                      "psF64 Item", (double)(1.0/(double)(1+lcv)));
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYBOOL",
+                      PS_DATA_BOOL,
+                      "psBool Item",
+                      (lcv%2 == 0));
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYSTR",
+                      PS_DATA_STRING,
+                      "String Item",
+                      extname);
+
+        // set the pixels in the image
+        psImageInit(image, (float)lcv);
+        if (!psFitsWriteImage(fitsFile,header,image,0,extname)) {
+            diag("Could not write image");
+        }
+        psFree(header);
+    }
+    psFree(image);
+    psFree(fitsFile);
+
+    return true;
+}
+
+bool makeTable(void)
+{
+// XXX: Should we be checking for memory leaks in this function?
+//    psMemId id = psMemGetId();
+    psFits* fitsFile = psFitsOpen(tableFilename, "w");
+    if (fitsFile == NULL) {
+        diag("Could not create 'table' FITS file");
+        return false;
+    }
+
+    // make the PHU an image (per FITS standard, it must be)
+    psImage* image = psImageAlloc(16,16,PS_TYPE_F32);
+
+    if (!psFitsWriteImage(fitsFile,NULL,image,1,NULL)) {
+        diag("Could not write PHU image");
+        return false;
+    }
+
+    psFree(image);
+
+    // build a table structure
+    psArray* table = psArrayAlloc(tableNumRows);
+    psMetadata* header = NULL;
+    for (int row = 0; row < tableNumRows; row++) {
+        header = psMetadataAlloc();
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYINT",
+                      PS_DATA_S32,
+                      "psS32 Item",
+                      (psS32)row);
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYFLT",
+                      PS_DATA_F32,
+                      "psF32 Item",
+                      (float)(1.0f/(float)(1+row)));
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYDBL",
+                      PS_DATA_F64,
+                      "psF64 Item",
+                      (double)(1.0/(double)(1+row)));
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYBOOL",
+                      PS_DATA_BOOL,
+                      "psBool Item",
+                      (row%2 == 0));
+
+        char* str = NULL;
+        psStringAppend(&str,"row=%d",row+1);
+        psMetadataAdd(header,PS_LIST_TAIL, "MYSTR",
+                      PS_DATA_STRING,
+                      "psString Item",
+                      str);
+        psFree(str);
+
+        psVector* vec = psVectorAlloc(5,PS_TYPE_S32);
+        for (int x=0; x < 4; x++) {
+            vec->data.S32[x] = x*10+row;
+        }
+        psMetadataAdd(header,PS_LIST_TAIL, "MYVEC",
+                      PS_DATA_VECTOR,
+                      "psVector Item",
+                      vec);
+        psFree(vec);
+
+        table->data[row] = header;
+    }
+
+    bool rc = psFitsWriteTable(fitsFile, NULL, table, NULL);
+
+    psFree(table);
+    psFree(fitsFile);
+    return(rc);
+}
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(509);
+
+    // tst_psFitsOpen()
+    {
+        psMemId id = psMemGetId();
+        ok(makeMulti(), "Created 'multi' FITS file");
+        psFits* fitsFile = psFitsOpen(multiFilename,"r");
+        ok(fitsFile != NULL, "psFitsOpen returned non-NULL on existing file");
+        int extNum = psFitsGetExtNum(fitsFile);
+        ok(extNum == 0, "psFitsOpen was queued to the PHU");
+        psFitsClose(fitsFile);
+
+        // make sure the file doesn't already exist.
+        // XXX: What is F_OK?
+        //        if (access("new.fits", F_OK) == 0) {
+        //            if (remove
+        //                    ("new.fits") != 0) {
+        //                psError(PS_ERR_UNKNOWN, false,
+        //                        "Couldn't delete the new.fits file");
+        //                return 3;
+        //            }
+        //        }
+
+        fitsFile = psFitsOpen("new.fits","w");
+        ok(fitsFile != NULL, "psFitsOpen returned non-NULL on w mode");
+
+        // write something to the file, otherwise CFITSIO will complain on close
+        psImage* img = psImageAlloc(16,16,PS_TYPE_F32);
+        psFitsWriteImage(fitsFile,NULL,img,1,NULL);
+        // psFree should be equivalent to psFitsClose
+        psFree(fitsFile);
+
+        // now, if psFitsOpen actually created the file, I shouldn't error in removing it.
+        ok(remove
+           ("new.fits") == 0, "psFitsOpen seemed to have created a new file");
+
+        fitsFile = psFitsOpen("new.fits","w+");
+        ok(fitsFile != NULL, "psFitsOpen returned non-NULL on w+ mode");
+
+        // write something to the file, otherwise CFITSIO will complain on close
+        psFitsWriteImage(fitsFile,NULL,img,1,NULL);
+        psFitsClose(fitsFile);
+
+        // now, if psFitsOpen actually created the file, I shouldn't error in removing it.
+        ok(remove
+           ("new.fits") == 0, "psFitsOpen seemed to have created a new file");
+
+        fitsFile = psFitsOpen("new.fits","a");
+        ok(fitsFile != NULL, "psFitsOpen returned non-NULL on a mode");
+
+        // write something to the file, otherwise CFITSIO will complain on close
+        psFitsWriteImage(fitsFile,NULL,img,1,NULL);
+        psFitsClose(fitsFile);
+        fitsFile = psFitsOpen("new.fits","a+");
+        ok(fitsFile != NULL, "psFitsOpen returned non-NULL on a+ mode");
+
+        psFitsClose(fitsFile);
+        // now, if psFitsOpen actually created the file, I shouldn't error in removing it.
+        ok(remove
+           ("new.fits") == 0, "psFitsOpen seemed to have created a new file");
+
+        // Attempt to allocate with NULL filename
+        // Following should generate an error message
+        // XXX: Verify error
+        fitsFile = psFitsOpen(NULL,"r");
+        ok(fitsFile == NULL, "psFitsOpen returned NULL for NULL input");
+
+        // Attempt to use an unallowed mode
+        // Following should generate an error message
+        // XXX: Verify error
+        fitsFile = psFitsOpen("new.fits","b+");
+        ok(fitsFile == NULL, "psFitsOpen returned NULL for NULL input");
+
+        psFree(img);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // tst_psFitsMoveExtName()
+    {
+        psMemId id = psMemGetId();
+
+        ok(makeMulti(), "Created 'multi' FITS file");
+        if (! makeMulti() )
+        {
+            return 1;
+        }
+
+        psFits* fits = psFitsOpen(multiFilename,"r");
+
+        if (fits == NULL)
+        {
+            psError(PS_ERR_UNKNOWN, false,
+                    "psFitsOpen returned NULL on existing file");
+            return 1;
+        }
+
+        int numHDUs = psFitsGetSize(fits);
+
+        if (numHDUs < 2)
+        {
+            psError(PS_ERR_UNKNOWN,true,
+                    "The 'multi' FITS file does not have multiple HDUs");
+            return 2;
+        }
+
+        char extName[80];
+        psRegion region = {0,0,0,0};
+
+        for (int lcv = 0; lcv < numHDUs; lcv++)
+        {
+            snprintf(extName,80,"ext-%d",lcv);
+            // try to move to the named extension.
+            if (! psFitsMoveExtName(fits, extName) ) {
+                psError(PS_ERR_UNKNOWN, false,
+                        "Failed to move to ext-%d",
+                        lcv);
+                return 3;
+            }
+
+            // check to see if I can retrieve the name back from the psFits object.
+            char* nameFromFile = psFitsGetExtName(fits);
+            if (strcmp(nameFromFile,extName) != 0) { // hey, it didn't move?
+                psError(PS_ERR_UNKNOWN, false,
+                        "Failed to retrieve the extension name back ('%s' vs '%s'",
+                        nameFromFile, extName);
+                return 3;
+            }
+            psFree(nameFromFile);
+
+            // check that the image is associated to the extension moved, i.e.,
+            // did we really move to the proper extension?
+            psImage* image = NULL;
+            image = psFitsReadImage(fits,region,0);
+
+            if (image == NULL || abs(image->data.F32[0][0] - (float)lcv) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN, true,
+                        "The image pixel 0,0 of ext-%d was %g, expected %d",
+                        lcv,image->data.F32[0][0],lcv);
+                return 4;
+            }
+            psFree(image);
+        }
+
+        for (int lcv = numHDUs-1; lcv >= 0; lcv--)
+        {
+            snprintf(extName,80,"ext-%d",lcv);
+            // try to move to the named extension.
+            if (! psFitsMoveExtName(fits, extName) ) {
+                psError(PS_ERR_UNKNOWN, false,
+                        "Failed to move to ext-%d",
+                        lcv);
+                return 5;
+            }
+
+            // check to see if I can retrieve the name back from the psFits object.
+            char* nameFromFile = psFitsGetExtName(fits);
+            if (strcmp(nameFromFile,extName) != 0) { // hey, it didn't move?
+                psError(PS_ERR_UNKNOWN, false,
+                        "Failed to retrieve the extension name back ('%s' vs '%s'",
+                        nameFromFile, extName);
+                return 5;
+            }
+            psFree(nameFromFile);
+
+            // check that the image is associated to the extension moved, i.e.,
+            // did we really move to the proper extension?
+            psImage* image = NULL;
+            image = psFitsReadImage(fits,region,0);
+
+            if (abs(image->data.F32[0][0] - (float)lcv) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN, true,
+                        "The image pixel 0,0 of ext-%d was %g, expected %d",
+                        lcv,image->data.F32[0][0],lcv);
+                return 6;
+            }
+            psFree(image);
+        }
+
+        // check to see if given a bogus extension name, it errors.
+        // Following should be an error
+        // XXX: Verify error
+        if (psFitsMoveExtName(fits, "bogus") || psErrorGetStackSize() != 1)
+        {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Moving to non-existant HDU didn't fail");
+            return 7;
+        }
+
+        // check to see if given a NULL psFits, it errors.
+        // Following should be an error
+        // XXX: Verify error
+        if (psFitsMoveExtName(NULL, "bogus") || psErrorGetStackSize() != 1)
+        {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Operation of NULL psFits didn't fail");
+            return 8;
+        }
+
+        // check to see if given a NULL extname, it errors.
+        // Following should be an error
+        // XXX: Verify error
+        if (psFitsMoveExtName(fits, NULL) || psErrorGetStackSize() != 1)
+        {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Operation of NULL extname didn't fail");
+            return 9;
+        }
+
+        psFree(fits);
+
+        // Attempt to get ext name from null fits file
+        // Following should generate an error for NULL fits file
+        if(psFitsGetExtName(NULL) != NULL)
+        {
+            psError(PS_ERR_UNKNOWN,true,"Expected NULL return from psFitsGetExtName with NULL fits file");
+            return 10;
+        }
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // tst_psFitsMoveExtNum()
+    {
+        psMemId id = psMemGetId();
+
+        ok(makeMulti(), "Created 'multi' FITS file");
+        psFits* fits = psFitsOpen(multiFilename,"r");
+        ok(fits != NULL, "psFitsOpen returned non-NULL on existing file");
+
+        int numHDUs = psFitsGetSize(fits);
+        // as a side test, let's make sure psFitsGetSize can handle NULL.
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        ok(psFitsGetSize(NULL) == 0 && psErrorGetStackSize() == 1,
+           "The 'multi' FITS file has multiple HDUs");
+
+        ok(numHDUs == 8, "The 'multi' FITS file does not have multiple HDUs");
+
+        psRegion region = {0,0,0,0};
+        // test absolute positioning
+        for (int lcv = 0; lcv < numHDUs; lcv++)
+        {
+            // try to move to the extension
+            ok(psFitsMoveExtNum(fits, lcv, false), "Moved to extension %d", lcv);
+
+            // check to see if I can retrieve the number back from the psFits object.
+            ok(psFitsGetExtNum(fits) == lcv, "Retrieved the extension number back (%d vs %d)",
+               psFitsGetExtNum(fits), lcv);
+
+            // check that the image is associated to the extension moved, i.e.,
+            // did we really move to the proper extension?
+            psImage* image = NULL;
+            image = psFitsReadImage(fits,region,0);
+            ok(image != NULL && abs(image->data.F32[0][0] - (float)lcv) <= FLT_EPSILON,
+               "The image pixel 0,0 of ext-%d was %g, expected %d",
+               lcv,image->data.F32[0][0],lcv);
+            psFree(image);
+        }
+
+        for (int lcv = numHDUs-1; lcv >= 0; lcv--)
+        {
+            // try to move to the extension
+            ok(psFitsMoveExtNum(fits, lcv, false), "Moved to extension %d", lcv);
+
+            // check that the image is associated to the extension moved, i.e.,
+            // did we really move to the proper extension?
+            psImage* image = NULL;
+            image = psFitsReadImage(fits,region,0);
+
+            ok(abs(image->data.F32[0][0] - (float)lcv) <= FLT_EPSILON,
+               "The image pixel 0,0 of ext-%d was %g, expected %d",
+               lcv, image->data.F32[0][0],lcv);
+            psFree(image);
+        }
+
+        // test relative positioning
+        psFitsMoveExtNum(fits,0,false);
+        for (int lcv = 1; lcv < numHDUs; lcv++)
+        {
+            // try to move to the extension
+            ok(psFitsMoveExtNum(fits, 1, true), "Failed to move to extension %d", lcv);
+
+            // check to see if I can retrieve the number back from the psFits object.
+            ok(psFitsGetExtNum(fits) == lcv,
+               "Failed to retrieve the extension number back (%d vs %d)",
+               psFitsGetExtNum(fits), lcv);
+
+            // check that the image is associated to the extension moved, i.e.,
+            // did we really move to the proper extension?
+            psImage* image = NULL;
+            image = psFitsReadImage(fits,region,0);
+
+            ok(image != NULL && abs(image->data.F32[0][0] - (float)lcv) <= FLT_EPSILON,
+               "The image pixel 0,0 of ext-%d was %g, expected %d",
+               lcv,image->data.F32[0][0],lcv);
+            psFree(image);
+        }
+
+        for (int lcv = numHDUs-2; lcv >= 0; lcv--)
+        {
+            // try to move to the extension
+            ok(psFitsMoveExtNum(fits, -1, true), "Failed to move to extension %d", lcv);
+
+            // check to see if I can retrieve the number back from the psFits object.
+            ok(psFitsGetExtNum(fits) == lcv,
+               "Failed to retrieve the extension number back (%d vs %d)",
+               psFitsGetExtNum(fits), lcv);
+
+            // check that the image is associated to the extension moved, i.e.,
+            // did we really move to the proper extension?
+            psImage* image = NULL;
+            image = psFitsReadImage(fits,region,0);
+
+            ok(abs(image->data.F32[0][0] - (float)lcv) <= FLT_EPSILON,
+               "The image pixel 0,0 of ext-%d was %g, expected %d",
+               lcv,image->data.F32[0][0],lcv);
+            psFree(image);
+        }
+
+
+        // check to see if given a negative extension number, it errors.
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        ok(!psFitsMoveExtNum(fits, -1, false) && psErrorGetStackSize() == 1,
+           "Moving to negative HDU did fail");
+
+        // check to see if relative positioning beyond PHU, it errors.
+        psFitsMoveExtNum(fits,0,false);
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        ok(!psFitsMoveExtNum(fits, -1, true) && psErrorGetStackSize() == 1,
+           "Moving to negative HDU did fail");
+
+        // check to see if given a extension greater than the total #HDUs, it errors.
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        ok(!psFitsMoveExtNum(fits, numHDUs, false) && psErrorGetStackSize() == 1,
+           "Moving to a HDU beyond the file's contents did fail");
+
+        // check to see if relative positioning beyond PHU, it errors.
+        psFitsMoveExtNum(fits,numHDUs-1,false);
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        ok(!psFitsMoveExtNum(fits, 1, true) && psErrorGetStackSize() == 1,
+           "Moving to negative HDU did fail");
+
+        // check to see if given a NULL psFits, it errors.
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        ok(!psFitsMoveExtNum(NULL, 0, false) && psErrorGetStackSize() == 1,
+           "Operation of NULL psFits didt fail");
+        psFitsClose(fits);
+
+        // Attempt to get ext name from null fits file
+        // Following should generate an error for NULL fits file
+        // XXX: Verify error
+        ok(psFitsGetExtNum(NULL) == PS_FITS_TYPE_NONE,
+           "Expected NULL return from psFitsGetExtNum with NULL fits file");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+
+    }
+
+
+    // tst_psFitsReadHeader()
+    {
+        psMemId id = psMemGetId();
+        ok(makeMulti(), "Created 'multi' FITS file");
+
+        psFits* fits = psFitsOpen(multiFilename,"r");
+        ok(fits != NULL, "psFitsOpen returned non-NULL on existing file");
+
+        int numHDUs = psFitsGetSize(fits);
+        ok(numHDUs >= 8, "The 'multi' FITS file has multiple HDUs");
+
+        char extname[80];
+        for (int hdunum = 0; hdunum < numHDUs; hdunum++)
+        {
+            snprintf(extname,80,"ext-%d",hdunum);
+            psFitsMoveExtNum(fits,hdunum,false);
+
+            psMetadata* header = psFitsReadHeader(NULL,fits);
+            ok(header != NULL, "Read header");
+
+            psMetadata* header2 = psMetadataAlloc();
+            header2 = psFitsReadHeader(header2,fits);
+            ok(header2 != NULL, "Read header");
+
+            ok(header->list->n >= 1 && header->list->n == header2->list->n,
+               "Reading the header given a NULL input psMetadata did not differ from giving an existing psMetadata");
+
+            // check for the extra metadata items
+            psS32 intItem = psMetadataLookupS32(NULL,header, "MYINT");
+            psF32 fltItem = psMetadataLookupF32(NULL,header, "MYFLT");
+            psF64 dblItem = psMetadataLookupF64(NULL,header, "MYDBL");
+            psMetadataItem* boolItem = psMetadataLookup(header, "MYBOOL");
+            psString strItem = psMetadataLookupStr(NULL, header, "MYSTR");
+
+            ok(intItem == hdunum, "Retrieved psS32 metadata item from file");
+
+            ok(fabsf(fltItem - 1.0f/(float)(1+hdunum)) <= FLT_EPSILON,
+               "Retrieved psF32 metadata item from file.  Got %f vs %f",
+               fltItem,1.0f/(float)(1+hdunum));
+
+            ok(abs(dblItem - 1.0/(double)(1+hdunum)) <= DBL_EPSILON,
+               "Retrieved psF64 metadata item from file.  Got %g vs %g",
+               dblItem, 1.0/(double)(1+hdunum));
+
+            ok(boolItem != NULL && boolItem->type == PS_DATA_BOOL,
+               "Retrieved psBool metadata item from file");
+
+            ok(strItem != NULL && strncmp(strItem,extname,strlen(extname)) == 0,
+               "Retrieved string metadata item from file.  Got '%s' vs '%s' (%d)",
+               strItem,extname,strlen(extname));
+
+            psFree(header);
+            psFree(header2);
+        }
+
+        // Following should be an error (input psFits = NULL)
+        // XXX: Verify error
+        psMetadata* header = psFitsReadHeader(NULL,NULL);
+        ok(header == NULL && psErrorGetStackSize() == 1,
+           "psFitsReadHeader didn't error on a NULL psFits");
+
+        psFree(fits);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // tst_psFitsReadHeaderSet()
+    {
+        psMemId id = psMemGetId();
+        ok(makeMulti(), "Created 'multi' FITS file");
+
+        psFits* fits = psFitsOpen(multiFilename,"r");
+        ok(fits != NULL, "psFitsOpen returned non-NULL on existing file");
+
+        int numHDUs = psFitsGetSize(fits);
+        ok(numHDUs >= 8, "The 'multi' FITS file has multiple HDUs");
+
+        // move to the middle
+        psFitsMoveExtNum(fits,numHDUs/2, false);
+        psMetadata* headerSet = psFitsReadHeaderSet(NULL,fits);
+        ok(headerSet != NULL, "psFitsReadHeaderSet returned non-NULL");
+
+        ok(psFitsGetExtNum(fits) == numHDUs/2, "psFitsReadHeaderSet did not change the CHU");
+
+        char extname[80];
+        for (int i = 0; i < numHDUs; i++)
+        {
+            if (i == 0) {
+                snprintf(extname, 80, "PHU");
+            } else {
+                snprintf(extname, 80, "ext-%d", i);
+            }
+
+            psMetadata* header = psMetadataLookupPtr(NULL,headerSet, extname);
+
+            ok(header != NULL, "psFitsReadHeader returned non-NULL for HDU#%d", i);
+
+            psS32 intItem = psMetadataLookupS32(NULL, header, "MYINT");
+            ok(intItem == i, "psFitsReadHeader for HDU#%d had a MYINT of %d, expected %d",
+               intItem, i);
+        }
+
+        psMetadata* set3 = psFitsReadHeaderSet(NULL,fits);
+        ok(set3 != NULL, "psFitsReadHeaderSet returned non-NULL");
+
+        for (int i = 0; i < numHDUs; i++)
+        {
+            if (i == 0) {
+                snprintf(extname, 80, "PHU");
+            } else {
+                snprintf(extname, 80, "ext-%d", i);
+            }
+
+            psMetadata* header = psMetadataLookupPtr(NULL, set3, extname);
+            ok(header != NULL, "psFitsReadHeader returned non-NULL for HDU#%d", i);
+
+            psS32 intItem = psMetadataLookupS32(NULL, header, "MYINT");
+            ok(intItem == i, "psFitsReadHeader for HDU#%d had a MYINT of %d, expected %d",
+               intItem, i);
+        }
+
+        set3 = psFitsReadHeaderSet(set3,NULL);
+        ok(set3 == NULL, "psFitsReadHeaderSet returned NULL given a NULL psFits");
+
+
+        psFree(headerSet);
+        psFitsClose(fits);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // tst_psFitsReadTable()
+    if (1) {
+        psMemId id = psMemGetId();
+        ok(makeTable(), "Created 'table' FITS file");
+        psFits* fits = psFitsOpen(tableFilename, "r");
+        ok(fits != NULL, "psFitsOpen returned non-NULL on existing file");
+
+        psFitsMoveExtNum(fits,1,false);
+        psArray* table = psFitsReadTable(fits);
+        ok(table != NULL, "psFitsReadTable returned non-NULL");
+        ok(table->n == tableNumRows, "Expected %d rows, read %d",
+           tableNumRows, table->n);
+
+        for (int row = 0; row < table->n; row++) {
+            psMetadata* rowData = table->data[row];
+
+            psS32 intItem = psMetadataLookupS32(NULL, rowData, "MYINT");
+            psF32 fltItem = psMetadataLookupF32(NULL, rowData, "MYFLT");
+            psF64 dblItem = psMetadataLookupF64(NULL, rowData, "MYDBL");
+            psBool boolItem = psMetadataLookupBool(NULL, rowData, "MYBOOL");
+            psString strItem = psMetadataLookupStr(NULL, rowData, "MYSTR");
+            psVector* vecItem = psMetadataLookupPtr(NULL, rowData, "MYVEC");
+
+            ok(intItem == row,
+               "Failed to retrieve psS32 metadata item from file (row=%d).  Got %d vs %d",
+               row, intItem, row);
+
+            ok(fabsf(fltItem - 1.0f/(float)(1+row)) <= FLT_EPSILON,
+               "Retrieved psF32 metadata item from file (row=%d).  Got %f vs %f",
+               row, fltItem,1.0f/(float)(1+row));
+
+            ok(abs(dblItem - 1.0/(double)(1+row)) <= DBL_EPSILON,
+               "Retrieved psF64 metadata item from file (row=%d).  Got %g vs %g",
+               row, dblItem, 1.0/(double)(1+row));
+
+            ok(!(boolItem != ((row&0x01) == 0)),
+               "Retrieved psBool metadata item from file (row=%d). Got %d vs %d",
+               row, boolItem, ((row&0x01) == 0));
+
+            char strValue[16];
+            snprintf(strValue,16,"row=%d",row+1);
+            ok(strncmp(strItem,strValue,strlen(strValue)) == 0,
+               "Retrieved psString metadata item from file (row=%d). Got '%s' vs '%s'",
+               row, strItem, strValue);
+
+            ok(vecItem != NULL, "Retrieved psVector metadata item from file (row=%d)", row);
+
+            ok(vecItem->type.type == PS_DATA_S32 &&
+               vecItem->data.S32[0] == row &&
+               vecItem->data.S32[3] == row+30,
+               "Retrieved psVector (row=%d) had expected values [%d,%d,%d,%d] vs [%d,%d,%d,%d]",
+               row,vecItem->data.S32[0], vecItem->data.S32[1],
+               vecItem->data.S32[2], vecItem->data.S32[3],
+               row,row+10,row+20,row+30);
+        }
+
+        psFree(table);
+        psFree(fits);
+
+        psArray* nullTest = psFitsReadTable(NULL);
+        ok(nullTest == NULL && psErrorGetStackSize() == 1,
+           "psFitsReadTable returned NULL when given NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // tst_psFitsReadTableColumnNum()
+    if (1) {
+        psMemId id = psMemGetId();
+        ok(makeTable(), "Created 'table' FITS file");
+        psFits* fits = psFitsOpen(tableFilename,"r");
+        ok(fits != NULL, "psFitsOpen returned non-NULL on existing file");
+
+        psFitsMoveExtNum(fits,1,false);
+        // read the column data via number
+        psVector* colData;
+        psElemType type[4] = {PS_TYPE_S32, PS_TYPE_F32, PS_TYPE_F32, PS_TYPE_BOOL};
+        psElemType altType[4] = {PS_TYPE_S64, PS_TYPE_F64, PS_TYPE_F64, PS_TYPE_BOOL};
+        char* colname[4] = {"MYINT","MYFLT","MYDBL","MYBOOL"};
+        psF64 expectedValues[4][10] = {
+                                          {0,1,2,3,4,5,6,7,8,9},
+                                          {1.0,1.0/2.0,1.0/3.0,1.0/4.0,1.0/5.0,1.0/6.0,1.0/7.0,1.0/8.0,1.0/9.0},
+                                          {1.0,1.0/2.0,1.0/3.0,1.0/4.0,1.0/5.0,1.0/6.0,1.0/7.0,1.0/8.0,1.0/9.0},
+                                          {1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0}
+                                      };
+
+        for (int col = 0; col < 4; col++) {
+            colData = psFitsReadTableColumnNum(fits,colname[col]);
+            ok(colData != NULL, "psFitsReadTableColumnNum returned non-NULL for col=%d");
+
+            if (colData->type.type != type[col] &&
+                    colData->type.type != altType[col]) {
+                char* typeRead;
+                char* typeExpected;
+                PS_TYPE_NAME(typeRead, colData->type.type);
+                PS_TYPE_NAME(typeExpected, type[col]);
+
+                ok(false, "psFitsReadTableColumnNum returned different type, %s vs %s, for col=%d",
+                   typeRead, typeExpected, col);
+            } else {
+                ok(true, "psFitsReadTableColumnNum returned same type");
+            }
+            ok(colData->n == tableNumRows,
+               "psFitsReadTableColumnNum returned same number of rows, %d vs %d, for col=%d",
+               colData->n, tableNumRows, col);
+            for (int row = 0; row < tableNumRows; row++) {
+                ok(abs(p_psVectorGetElementF64(colData,row) - expectedValues[col][row]) <= FLT_EPSILON,
+                   "psFitsReadTableColumnNum returned values (%g vs %g) for col=%d",
+                   p_psVectorGetElementF64(colData,row), expectedValues[col][row], col);
+            }
+            psFree(colData);
+        }
+
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        psVector* data = psFitsReadTableColumnNum(NULL,colname[0]);
+        psErr* err = psErrorLast();
+        ok(data == NULL, "psFitsReadTableColumnNum did return NULL with NULL psFits");
+        ok(err->code == PS_ERR_BAD_PARAMETER_NULL,
+           "psFitsReadTableColumnNum did return error with NULL psFits");
+        psFree(err);
+
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        data = psFitsReadTableColumnNum(fits,"BOGUS");
+        err = psErrorLast();
+        ok(data == NULL, "psFitsReadTableColumnNum did return NULL with bogus column name");
+        ok(err->code == PS_ERR_IO, "psFitsReadTableColumnNum did return error with bogus column name");
+        psFree(err);
+        psFree(fits);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // tst_psFitsReadTableColumn()
+    if (1) {
+        psMemId id = psMemGetId();
+        ok(makeTable(), "Created 'table' FITS file");
+        psFits* fits = psFitsOpen(tableFilename,"r");
+        ok(fits != NULL, "psFitsOpen returned non-NULL on existing file");
+
+        psFitsMoveExtNum(fits,1,false);
+        // read the column data via number
+        psArray* colData;
+        char* colname[4] = {"MYINT","MYFLT","MYDBL","MYBOOL"};
+        psF64 expectedValues[3][10] = {
+                                          {0,1,2,3,4,5,6,7,8,9},
+                                          {1.0,1.0/2.0,1.0/3.0,1.0/4.0,1.0/5.0,1.0/6.0,1.0/7.0,1.0/8.0,1.0/9.0},
+                                          {1.0,1.0/2.0,1.0/3.0,1.0/4.0,1.0/5.0,1.0/6.0,1.0/7.0,1.0/8.0,1.0/9.0}
+                                      };
+        char* expectedBoolValues[10] = {"T","F","T","F","T","F","T","F","T","F"};
+        char* expectedStrValues[10] = {"row=1","row=2","row=3","row=4","row=5","row=6","row=7","row=8","row=9","row=10"};
+
+        bool errorFlag = false;
+        for (int col = 0; col < 4; col++) {
+            colData = psFitsReadTableColumn(fits,colname[col]);
+            if (colData == NULL) {
+                diag("psFitsReadTableColumn returned NULL for col=%d", col);
+                errorFlag = true;
+            }
+            if (colData->n != tableNumRows) {
+                diag("psFitsReadTableColumn returned different number of rows, %d vs %d, for col=%d",
+                     colData->n, tableNumRows, col);
+                errorFlag = true;
+            }
+            if (col < 3) {
+                for (int row = 0; row < tableNumRows; row++) {
+                    if (abs(atof((char*)colData->data[row]) - expectedValues[col][row]) > 0.0001) {
+                        diag("psFitsReadTableColumn returned unexpected values (%g vs %g) for col=%d",
+                             atof((char*)colData->data[row]), expectedValues[col][row], col);
+                        errorFlag = true;
+                    }
+                }
+            } else if (col == 3) {
+                for (int row = 0; row < tableNumRows; row++) {
+                    if (strncmp(colData->data[row],expectedBoolValues[row],
+                                strlen(expectedBoolValues[row])) != 0) {
+                        diag("psFitsReadTableColumn returned unexpected values ('%s' vs '%s') for col=%d",
+                             (char*)colData->data[row], expectedBoolValues[row], col);
+                        errorFlag = true;
+                    }
+                }
+            } else if (col == 4) {
+                for (int row = 0; row < tableNumRows; row++) {
+                    if (strncmp(colData->data[row],expectedStrValues[row],
+                                strlen(expectedStrValues[row])) != 0) {
+                        diag("psFitsReadTableColumn returned unexpected values ('%s' vs '%s') for col=%d",
+                             (char*)colData->data[row], expectedStrValues[row], col);
+                        errorFlag = true;
+                    }
+                }
+            }
+            psFree(colData);
+        }
+        ok(!errorFlag, "psFitsReadTableColumn() produced the correct data");
+
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        psArray* data = psFitsReadTableColumn(NULL,"MYINT");
+        psErr* err = psErrorLast();
+        ok(data == NULL, "psFitsReadTableColumn did return NULL with NULL psFits");
+        ok(err->code == PS_ERR_BAD_PARAMETER_NULL,
+           "psFitsReadTableColumn did error with NULL psFits");
+        psFree(err);
+
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        data = psFitsReadTableColumn(fits,"BOGUS");
+        err = psErrorLast();
+        ok(data == NULL, "psFitsReadTableColumn did return NULL with col=\"BOGUS\"");
+        ok(err->code == PS_ERR_IO, "psFitsReadTableColumn did error with col=\"BOGUS\"");
+        psFree(err);
+
+        psFree(fits);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // tst_psFitsUpdateTable()
+    if (1) {
+        psMemId id = psMemGetId();
+        psErr* err;
+        char* strValue[] = {
+                               "row A",
+                               "row B",
+                               "row C",
+                               "row D",
+                               "row E",
+                               "row F",
+                               "row G",
+                               "row H",
+                               "row I",
+                               "row J",
+                               "row K"
+                           };
+        ok(makeTable(), "Created 'table' FITS file");
+        psFits* fits = psFitsOpen(tableFilename,"rw");
+        ok(fits != NULL, "psFitsOpen returned NULL on existing file");
+        psFitsMoveExtNum(fits,1,false);
+        // change the data in the file, going past by one (implicit new row of data)
+        bool errorFlag = false;
+        for (int row = 0; row < tableNumRows+1; row++) {
+            psMetadata* md = psMetadataAlloc();
+            psMetadataAddF32(md,PS_LIST_TAIL,"MYFLT", 0,"",(float)row/-10.0);
+            psMetadataAddF64(md,PS_LIST_TAIL,"MYDBL", 0,"",(double)row/-100.0);
+            psMetadataAddS32(md,PS_LIST_TAIL,"MYINT", 0,"",-row);
+            psMetadataAddBool(md,PS_LIST_TAIL,"MYBOOL", 0,"",((row & 1) == 1));
+            psMetadataAddStr(md,PS_LIST_TAIL,"MYSTR", 0,"",strValue[row]);
+
+            if (!psFitsUpdateTable(fits,md,row)) {
+                diag("psFitsUpdateTable returned false, but expected true for row=%d", row);
+                errorFlag = true;
+            }
+            psFree(md);
+        }
+        ok(!errorFlag, "psFitsUpdateTable() produced the correct data");
+
+        for (int row = 0; row < tableNumRows+1; row++) {
+            psMetadata* md = psFitsReadTableRow(fits, row);
+            if (abs(psMetadataLookupF32(NULL,md,"MYFLT") - (float)row/-10.0) > FLT_EPSILON) {
+                diag("psFitsUpdateTable did not change the float value for row=%d", row);
+                errorFlag = true;
+            }
+            if (abs(psMetadataLookupF64(NULL,md,"MYDBL") - (float)row/-100.0) > FLT_EPSILON) {
+                diag("psFitsUpdateTable did not change the double value for row=%d", row);
+                errorFlag = true;
+            }
+            if (psMetadataLookupS32(NULL,md,"MYINT") != -row) {
+                diag("psFitsUpdateTable did not change the integer value for row=%d", row);
+                errorFlag = true;
+            }
+            if (psMetadataLookupBool(NULL,md,"MYBOOL") != ((row &1) == 1)) {
+                diag("psFitsUpdateTable did not change the boolean value for row=%d", row);
+                errorFlag = true;
+            }
+            psString mystr = psMetadataLookupStr(NULL,md,"MYSTR");
+            if (strncmp(mystr,strValue[row], strlen(strValue[row])) != 0) {
+                diag("psFitsUpdateTable did not change the string value for row=%d", row);
+                errorFlag = true;
+            }
+            psFree(md);
+        }
+        ok(!errorFlag, "psFitsUpdateTable() produced the correct data");
+
+        psMetadata* md = psMetadataAlloc();
+        psMetadataAddF32(md,PS_LIST_TAIL,"BOGUS", 0,"",-1.0f);
+        // Following should be a warning
+        // XXX: Verify warning
+        psErrorClear();
+        ok(psFitsUpdateTable(fits,md,0), "psFitsUpdateTable did return false with bogus column data");
+        psFree(md);
+
+        md = psMetadataAlloc();
+        psMetadataAddF32(md,PS_LIST_TAIL,"MYFLT", 0,"",-1.0f);
+        psMetadataAddF64(md,PS_LIST_TAIL,"MYDBL", 0,"",-2.0);
+        psMetadataAddS32(md,PS_LIST_TAIL,"MYINT", 0,"",-3);
+
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        ok(psFitsUpdateTable(NULL,md,0), "psFitsUpdateTable did return false with NULL psFits");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_NULL, "psFitsUpdateTable did error with NULL psFits");
+        psFree(err);
+
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        ok(psFitsUpdateTable(fits,NULL,0), "psFitsUpdateTable did return false with NULL psMetadata");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_NULL, "psFitsUpdateTable did error with NULL psMetadata");
+        psFree(err);
+
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        ok(psFitsUpdateTable(fits,md,-1), "psFitsUpdateTable did return false with row=-1");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_IO, "psFitsUpdateTable did error with row=-1");
+
+        psFree(err);
+        psFree(md);
+        psFitsClose(fits);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageRead()
+    {
+        psS32 N = 256;
+        psS32 M = 128;
+
+        // This function shall open the specified FITS file, read the specified data
+        // and place the data into a psImage structure. This function shall generate
+        // an error message and return NULL if any of the input parameters are out of
+        // range, image file doesn't exist or image is zero or one dimensional.
+        // Verify the returned psImage structure contains expected values, if the input
+        // parameter filename specifies an available FITS file with known 2dimensional
+        // data, input parameters col, row, ncol, nrow, z specify data range with the
+        // FITS file. Cases should include 1x1, Nx1, 1xN, NxN and MxN sub images and
+        // total FITS file image. (done in macro)
+        // Verify the returned psImage structure is equal to the input parameter
+        // 'output', if specified. (done in macro)
+
+        #define testReadTypeSize(m, n, readM0, readN0, readM, readN, TYP, filename) \
+        { \
+            psMemId id = psMemGetId(); \
+            psImage* img = NULL; \
+            psImage* img2 = NULL; \
+            psImage* img3 = NULL; \
+            psImage* img4 = NULL; \
+            \
+            GENIMAGE(img,m,n,TYP,row+2*col); \
+            img2 = psImageCopy(img2,img,PS_TYPE_##TYP); \
+            GENIMAGE(img3,m,n,TYP,row+2*col); \
+            psImageClip(img3,32.0,32.0,120.0,120.0); \
+            img4 = psImageCopy(img4,img3,PS_TYPE_##TYP); \
+            psFits* fits = psFitsOpen(filename, "w"); \
+            ok(psFitsWriteImage(fits, NULL, img, 2, NULL), "Wrote test image %s",filename); \
+            ok(psFitsUpdateImage(fits,img3, 0,0, 1), "Wrote test image %s",filename); \
+            ok(psFitsWriteImage(fits,NULL, img3, 2, NULL), "Wrote test image %s",filename); \
+            ok(psFitsUpdateImage(fits,img, 0, 0, 1), "Wrote test image %s",filename); \
+            psFree(img); \
+            psFree(fits); \
+            img = NULL; \
+            psFree(img3); \
+            img3 = NULL; \
+            fits = psFitsOpen(filename,"r"); \
+            psRegion reg = {readM0, readM, readN0, readN}; \
+            img = psFitsReadImage(fits, reg, 0); \
+            img3 = psFitsReadImage(fits, reg, 1); \
+            ok(img3 != NULL, "Read test image %s",filename); \
+            bool errorFlag = false; \
+            for (psU32 row = readN0; row < readN; row++) { \
+                ps##TYP* imgRow = img->data.TYP[row-readN0]; \
+                ps##TYP* img2Row = img2->data.TYP[row]; \
+                ps##TYP* img3Row = img3->data.TYP[row-readN0]; \
+                ps##TYP* img4Row = img4->data.TYP[row]; \
+                for (psU32 col = readM0; col < readM; col++) { \
+                    if (fabsf(imgRow[col-readM0]-img2Row[col]) > FLT_EPSILON) { \
+                        diag("Image changed in I/O operation at %d,%d,0 (%.2f vs %.2f) for %s", \
+                             col,row,(psF32)imgRow[col-readM0],(psF32)img2Row[col],filename); \
+                        errorFlag = true; \
+                    } \
+                    if (fabsf(img3Row[col-readM0]-img4Row[col]) > FLT_EPSILON) { \
+                        diag("Image changed in I/O operation at %d,%d,1 (%.2f vs %.2f) for %s", \
+                             col,row,(psF32)img3Row[col-readM0],(psF32)img4Row[col],filename); \
+                        errorFlag = true; \
+                    } \
+                } \
+            } \
+            ok(!errorFlag, "psFitsReadImage() produced the correct data"); \
+            psFree(img); \
+            img = NULL; \
+            psFree(img3); \
+            img3 = NULL; \
+            psFitsMoveExtNum(fits,1, false); \
+            img3 = psFitsReadImage(fits, reg, 0); \
+            img = psFitsReadImage(fits, reg, 1); \
+            ok(img != NULL, "Read test image %s",filename); \
+            errorFlag = false; \
+            for (psU32 row = readN0; row < readN; row++) { \
+                ps##TYP* imgRow = img->data.TYP[row-readN0]; \
+                ps##TYP* img2Row = img2->data.TYP[row]; \
+                ps##TYP* img3Row = img3->data.TYP[row-readN0]; \
+                ps##TYP* img4Row = img4->data.TYP[row]; \
+                for (psU32 col = readM0; col < readM; col++) { \
+                    if (fabsf(imgRow[col-readM0]-img2Row[col]) > FLT_EPSILON) { \
+                        diag("Image changed in I/O operation at %d,%d,0 (%.2f vs %.2f) for %s", \
+                             col,row,(psF32)imgRow[col-readM0],(psF32)img2Row[col],filename); \
+                        errorFlag = true; \
+                    } \
+                    if (fabsf(img3Row[col-readM0]-img4Row[col]) > FLT_EPSILON) { \
+                        diag("Image changed in I/O operation at %d,%d,1 (%.2f vs %.2f) for %s", \
+                             col,row,(psF32)img3Row[col-readM0],(psF32)img4Row[col],filename); \
+                        errorFlag = true; \
+                    } \
+                } \
+            } \
+            ok(!errorFlag, "psFitsReadImage() produced the correct data"); \
+            psFree(img); \
+            psFree(img2); \
+            psFree(img3); \
+            psFree(img4); \
+            psFree(fits); \
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); \
+        }
+
+        #define testReadType(TYP,filename) \
+        testReadTypeSize(1,1,0,0,0,0,TYP,"tmpImages/1x1_" filename); \
+        testReadTypeSize(M,1,M/4,0,M*3/4,0,TYP,"tmpImages/Mx1_" filename); \
+        testReadTypeSize(1,N,0,N/4,0,N*3/4,TYP,"tmpImages/1xN_" filename); \
+        testReadTypeSize(M,N,M/4,N/4,M*3/4,N*3/4,TYP,"tmpImages/MxN_" filename);
+
+        system("mkdir tmpImages");
+
+        testReadType(U8,"U8.fits");
+        testReadType(S8,"S8.fits");   // Not a requirement
+        testReadType(S16,"S16.fits");
+        testReadType(U16,"U16.fits"); // Not a requirement
+        testReadType(S32,"S32.fits");
+        testReadType(U32,"U32.fits"); // Not a requirement
+        testReadType(F32,"F32.fits");
+        testReadType(F64,"F64.fits");
+
+        // Attempt to read from NULL fits object
+        // Following should generate error message for NULL psFits
+        // XXX: Verify error
+        // XXXX: This is seg-faulting
+        if (0)
+        {
+            psMemId id = psMemGetId();
+            psRegion region = {
+                                  0,0,0,0
+                              };
+            ok(psFitsReadImage(NULL,region,0) == NULL, "Did return NULL for NULL psFits");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+            \
+        }
+    }
+
+
+    // testImageWrite()
+    {
+        psMemId id = psMemGetId();
+        psImage* img = NULL;
+        psImage* img2 = NULL;
+        psS32 m = 64;
+        psS32 n = 96;
+
+        // This function shall write the specified section within a psImage structure
+        // to a FITS file. If the specifiedfile exists, then data should overwrite the
+        // section to write. If the specified file doesn't exist, it shall be created.
+        // If an extenstion is specified, then a basic primary header data unit shall
+        //  be created.
+        //
+        // Verify a FITS file named filename is generated and contains expected
+        // values, if the input parameter input contains known data values, input
+        // parameters col, row, ncol, nrow specify a valid data region within psImage
+        // structure.
+        //
+        // Verify a FITS file named filename is generated and contains a primary
+        // header data unit with extension with expected values, if the input
+        // parameter input contains known data values, input parameters col, row,
+        // ncol, nrow specify a valid data region within psImage structure and
+        // extname and/or extnum specify an extenstion to write.
+        //
+        // N.B. : these are done in testImageRead tests, see above.
+        //
+        // Verify a FITS file named filename is overwritten and contains
+        // expected values, if the input parameter input contains known data values,
+        // input parameters col, row, ncol, nrow specify a valid data region within
+        // psImage structure.
+
+        GENIMAGE(img,m,n,F32,0);
+        GENIMAGE(img2,m,n,F32,row+2*col);
+        system("mkdir tmpImages");
+        psFits* fits = psFitsOpen("tmpImages/writeTest.fits","w");
+
+        ok(psFitsWriteImage(fits, NULL, img,1, NULL), "Wrote writeTest.fits");
+        ok(psFitsUpdateImage(fits, img2, 0, 0, 0), "Updated writeTest.fits");
+        psFree(img);
+        psFree(img2);
+
+        // Did it really overwrite the pixel values?  Let's read it in and see.
+        psFitsClose(fits);
+
+        psRegion region = {0,0,0,0};
+        fits = psFitsOpen("tmpImages/writeTest.fits","r");
+        img = NULL;
+        img = psFitsReadImage(fits, region, 0);
+        ok(img != NULL, "Read in writeTest.fits");
+        bool errorFlag = false;
+        for (psU32 row=0;row<n;row++)
+        {
+            psF32* imgRow = img->data.F32[row];
+            for (psU32 col=0;col<m;col++) {
+                if (fabsf(imgRow[col] - (row+2*col)) > FLT_EPSILON) {
+                    diag("The image values were not overwritten at %d,%d (%.2f vs %.2f)",
+                         col,row,imgRow[col],(row+2*col));
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psFitsReadImage() produced the correct data");
+
+        psFree(img);
+
+        // Verify false is returned and program execution is not stopped, if the input image
+        // is null.
+        // Following should generate an error message because input image is null
+        // XXX: Verify error
+        ok(!psFitsWriteImage(fits,NULL,NULL, 1, NULL),
+           "psImageWriteSection did return false when input image is NULL");
+        psFree(fits);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // tst_psFitsWriteHeader()
+    {
+        psMemId id = psMemGetId();
+        ok(makeMulti(), "Created 'multi' FITS file");
+
+        psMetadata* header   = psMetadataAlloc();
+        psFits*     fitsFile = psFitsOpen(multiFilename,"a+");
+
+        // Test psFitsReadWrite generates files from psFitsWriteImage which calls psFitsWriteHeader
+        // so these additional tests check for error conditions
+        // Attempt call function with NULL metadata
+        ok(!psFitsWriteHeader(fitsFile, NULL), "Expected return of true for NULL metadata pointer");
+        psFree(fitsFile);
+
+        // Attempt to call function with NULL fits
+        ok(!psFitsWriteHeader(NULL, header), "Expected return of true for NULL fits file pointer");
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/fits/tap_psFitsBlank_00.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/fits/tap_psFitsBlank_00.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/fits/tap_psFitsBlank_00.c	(revision 22158)
@@ -0,0 +1,82 @@
+#include <pslib.h>
+#include <string.h>
+#include <unistd.h>     // needed for unlink()
+
+#include "tap.h"
+#include "pstap.h"
+
+int main(void)
+
+{
+    plan_tests(15);
+
+    psArray *table = psArrayAllocEmpty (10);
+    for (int i = 0; i < table->nalloc; i++) {
+        psMetadata *row = psMetadataAlloc ();
+        psMetadataAdd (row, PS_LIST_TAIL, "X_PIX",   PS_DATA_F32, "", 2.0*i);
+        psMetadataAdd (row, PS_LIST_TAIL, "Y_PIX",   PS_DATA_F32, "", 4.0*i);
+        psArrayAdd (table, 10, row);
+    }
+
+    psImage *image = psImageAlloc (512, 512, PS_DATA_F32);
+
+    psFits *fits = psFitsOpen ("test.fits", "w");
+
+    psMetadata *header = psMetadataAlloc ();
+
+    for (int i = 0; i < 5; i++) {
+        char name[80];
+
+        sprintf (name, "blank.%02d", i);
+        psMetadataAddStr (header, PS_LIST_TAIL, "TESTNAME", PS_META_REPLACE, "test name", name);
+        // psFitsMoveLast (fits);
+        psFitsWriteBlank (fits, header, "testext");
+
+        sprintf (name, "image.%02d", i);
+        psMetadataAddStr (header, PS_LIST_TAIL, "TESTNAME", PS_META_REPLACE, "test name", name);
+        psFitsWriteImage (fits, header, image, 1, "testext");
+
+        sprintf (name, "table.%02d", i);
+        psMetadataAddStr (header, PS_LIST_TAIL, "TESTNAME", PS_META_REPLACE, "test name", name);
+        psMetadataAddStr (header, PS_LIST_TAIL, "EXTTYPE", PS_META_REPLACE, "type", "SMPDATA");
+        psMetadataAddStr (header, PS_LIST_TAIL, "EXTHEAD", PS_META_REPLACE, "head", "image.00");
+        psMetadataAddStr (header, PS_LIST_TAIL, "EXTDATA", PS_META_REPLACE, "data", "blank.00");
+        psFitsWriteTable (fits, header, table, "testext");
+    }
+
+    psFitsClose (fits);
+
+    fits = psFitsOpen ("test.fits", "r");
+    for (int i = 0; i < 5; i++) {
+        char *name, expect[80];
+
+        psMetadata *outhead = psMetadataAlloc ();
+
+        fprintf (stderr, "top: %d\n", psFitsGetExtNum (fits));
+
+        psFitsReadHeader (outhead, fits);
+        sprintf (expect, "blank.%02d", i);
+        name = psMetadataLookupStr (NULL, outhead, "TESTNAME");
+        ok (!strcmp(name, expect), "got TESTNAME = %s, expected %s", name, expect);
+        psFitsMoveExtNum (fits, 1, true);
+        fprintf (stderr, "curr: %d\n", psFitsGetExtNum (fits));
+
+        psFitsReadHeader (outhead, fits);
+        sprintf (expect, "image.%02d", i);
+        name = psMetadataLookupStr (NULL, outhead, "TESTNAME");
+        ok (!strcmp(name, expect), "got TESTNAME = %s, expected %s", name, expect);
+        psFitsMoveExtNum (fits, 1, true);
+        fprintf (stderr, "curr: %d\n", psFitsGetExtNum (fits));
+
+        psFitsReadHeader (outhead, fits);
+        sprintf (expect, "table.%02d", i);
+        name = psMetadataLookupStr (NULL, outhead, "TESTNAME");
+        ok (!strcmp(name, expect), "got TESTNAME = %s, expected %s", name, expect);
+        psFitsMoveExtNum (fits, 1, true);
+        fprintf (stderr, "curr: %d\n", psFitsGetExtNum (fits));
+    }
+    psFitsClose (fits);
+    unlink ("test.fits");
+
+    exit (0);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/fits/tap_psFitsImage.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/fits/tap_psFitsImage.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/fits/tap_psFitsImage.c	(revision 22158)
@@ -0,0 +1,95 @@
+#include <stdio.h>
+#include "tap.h"
+#include "pstap.h"
+#include <pslib.h>
+
+#define NUMCOLS 12                      // Number of columns for image
+#define NUMROWS 34                      // Number of rows for image
+#define BITPIX 32                       // Bits per pixel
+#define OUTTYPE PS_TYPE_F64             // Expected output type
+
+// Generate an image
+static psImage *generateImage(void)
+{
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 12345); // Random number generator
+    psImage *image = psImageAlloc(NUMCOLS, NUMROWS, PS_TYPE_F32); // Generated image
+    for (int y = 0; y < NUMROWS; y++) {
+        for (int x = 0; x < NUMCOLS; x++) {
+            image->data.F32[y][x] = ((x + y) % 2) ? NAN : psRandomUniform(rng);
+        }
+    }
+    psFree(rng);
+    return image;
+}
+
+
+int main(int argc, const char *argv[])
+{
+    plan_tests(7);
+
+    {
+        psMemId id = psMemGetId();
+
+        psString name = NULL;           // Name of FITS image
+        psStringAppend(&name, "%s.fits", argv[0]);
+
+        psImage *original = generateImage(); // Image to test
+        psMetadata *header = psMetadataAlloc(); // FITS header
+
+        psFits *fits = psFitsOpen(name, "w");
+
+        // Set compression
+        psVector *tiles = psVectorAlloc(2, PS_TYPE_S32);
+        tiles->data.S32[0] = 0;
+        tiles->data.S32[1] = 1;
+        ok(psFitsSetCompression(fits, PS_FITS_COMPRESS_RICE, tiles, 4, 0, 0), "Set compression");
+        psFree(tiles);
+
+        // Set quantisation
+        fits->options = psFitsOptionsAlloc();
+        fits->options->bitpix = BITPIX;
+        fits->options->scaling = PS_FITS_SCALE_RANGE;
+
+        bool write = psFitsWriteImage(fits, header, original, 0, NULL);
+        psFitsClose(fits);
+
+        ok(write, "Write image");
+        skip_start(!fits || !write, 4, "Unable to write image");
+        {
+            psFits *fits = psFitsOpen(name, "r");
+            psImage *image = psFitsReadImage(fits, psRegionSet(0,0,0,0), 0);
+            psFitsClose(fits);
+
+            ok(image, "Read image");
+            skip_start(!image, 3, "Unable to read image");
+            {
+                ok(image->type.type == OUTTYPE, "Image type");
+                ok(image->numCols == NUMCOLS && image->numRows == NUMROWS, "Image size");
+                bool consistent = true; // Images are consistent?
+                double tol = 1.0 / (double)(1 << (BITPIX - 1)) + FLT_EPSILON; // Expected tolerance
+                for (int y = 0; y < NUMROWS; y++) {
+                    for (int x = 0; x < NUMCOLS; x++) {
+                        double imageVal = psImageGet(image, x, y);
+                        if ((!isfinite(original->data.F32[y][x]) && isfinite(imageVal)) ||
+                            (isfinite(original->data.F32[y][x]) && !isfinite(imageVal) &&
+                             original->data.F32[y][x] < 1.0 - 0.5 * tol) ||
+                            (fabs(original->data.F32[y][x] - imageVal) > tol)) {
+                            consistent = false;
+                            diag("Inconsistent at %d,%d: %lf vs %f --> %le", x, y,
+                                 imageVal, original->data.F32[y][x], imageVal - original->data.F32[y][x]);
+                        }
+                    }
+                }
+                ok(consistent, "Images consistent.");
+                psFree(image);
+            }
+            skip_end();
+        }
+        skip_end();
+        psFree(original);
+        psFree(header);
+        psFree(name);
+
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/fits/tst_psFits.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/fits/tst_psFits.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/fits/tst_psFits.c	(revision 22158)
@@ -0,0 +1,1665 @@
+/** @file  tst_psFits.c
+*
+*  @brief Contains the tests for psFits.[ch]
+*
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.25 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2006-07-26 03:37:04 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#include <unistd.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "psTest.h"
+#include "pslib_strict.h"
+
+#define GENIMAGE(img,c,r,TYP, valueFcn) \
+img = psImageAlloc(c,r,PS_TYPE_##TYP); \
+for (psU32 row=0;row<r;row++) { \
+    ps##TYP* imgRow = img->data.TYP[row]; \
+    for (psU32 col=0;col<c;col++) { \
+        imgRow[col] = (ps##TYP)(valueFcn); \
+    } \
+}
+
+static bool makeMulti(void);  // implicitly tests psFitsSetExtName
+static bool makeTable(void);
+const char* multiFilename = "multi.fits";
+const char* tableFilename = "table.fits";
+const int tableNumRows = 10;
+
+
+// N.B., the tests to Image read/write was liberally taken from the now
+// deprecated psImageReadSection/psImageWriteSection function tests.
+static psS32 testImageRead(void);
+static psS32 testImageWrite(void);
+
+static psS32 tst_psFitsOpen( void );
+static psS32 tst_psFitsMoveExtName( void ); // also tests psFitsGetExtName
+static psS32 tst_psFitsMoveExtNum( void );  // also tests psFitsGetExtNum, psFitsGetSize
+static psS32 tst_psFitsReadHeader( void );
+static psS32 tst_psFitsReadHeaderSet( void );
+static psS32 tst_psFitsReadTable( void );
+static psS32 tst_psFitsReadTableColumnNum(void);
+static psS32 tst_psFitsReadTableColumn(void);
+static psS32 tst_psFitsUpdateTable(void);
+static psS32 tst_psFitsWriteHeader(void);
+
+testDescription tests[] = {
+                              {tst_psFitsOpen, 801, "psFitsOpen", 0, false},
+                              {tst_psFitsMoveExtName, 802, "psFitsMoveExtName", 0, false},
+                              {tst_psFitsMoveExtName, 802, "psFitsGetExtName", 0, true},
+                              {tst_psFitsMoveExtNum, 803, "psFitsMoveExtNum", 0, false},
+                              {tst_psFitsMoveExtNum, 803, "psFitsGetExtNum", 0, true},
+                              {tst_psFitsMoveExtNum, 803, "psFitsGetSize", 0, true},
+                              {tst_psFitsReadHeader, 804, "psFitsReadHeader", 0, false},
+                              {tst_psFitsReadHeaderSet,805, "psFitsReadHeaderSet", 0, false},
+                              {tst_psFitsReadTable,809, "psFitsReadTable", 0, false},
+                              {tst_psFitsReadTableColumnNum,836, "psFitsReadTableColumnNum", 0, false},
+                              {tst_psFitsReadTableColumn,839, "psFitsReadTableColumn", 0, false},
+                              {tst_psFitsUpdateTable,840, "psFitsUpdateTable", 0, false},
+                              {testImageRead,567, "psFitsReadImage", 0, false},
+                              {testImageWrite,569, "psFitsWriteImage", 0, false},
+                              {tst_psFitsWriteHeader,000,"psFitsWriteHeader",0,false},
+                              {NULL}
+                          };
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetLevel( PS_LOG_INFO );
+
+    return ( ! runTestSuite( stderr, "psFits", tests, argc, argv ) );
+}
+
+bool makeMulti(void)
+{
+    psFits* fitsFile = psFitsOpen(multiFilename,"w");
+
+    if (fitsFile == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "Could not create 'multi' FITS file.");
+        return false;
+    }
+
+    psImage* image = psImageAlloc(16,16,PS_TYPE_F32);
+
+    char extname[80];
+    for (int lcv = 0; lcv < 8; lcv++) {
+        snprintf(extname,80,"ext-%d", lcv);
+
+        psMetadata* header = psMetadataAlloc();
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYINT",
+                      PS_DATA_S32,
+                      "psS32 Item", (psS32)lcv);
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYFLT",
+                      PS_DATA_F32,
+                      "psF32 Item", (float)(1.0f/(float)(1+lcv)));
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYDBL",
+                      PS_DATA_F64,
+                      "psF64 Item", (double)(1.0/(double)(1+lcv)));
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYBOOL",
+                      PS_DATA_BOOL,
+                      "psBool Item",
+                      (lcv%2 == 0));
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYSTR",
+                      PS_DATA_STRING,
+                      "String Item",
+                      extname);
+
+        // set the pixels in the image
+        psImageInit(image, (float)lcv);
+        if (! psFitsWriteImage(fitsFile,header,image,0,extname) ) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Could not write image.");
+            return false;
+        }
+
+        psFree(header);
+    }
+    psFree(image);
+    psFree(fitsFile);
+
+    return true;
+}
+
+bool makeTable(void)
+{
+    psFits* fitsFile = psFitsOpen(tableFilename,"w");
+
+    if (fitsFile == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "Could not create 'table' FITS file.");
+        return false;
+    }
+
+    // make the PHU an image (per FITS standard, it must be)
+    psImage* image = psImageAlloc(16,16,PS_TYPE_F32);
+
+    if (! psFitsWriteImage(fitsFile,NULL,image,1,NULL) ) {
+        psError(PS_ERR_UNKNOWN, false,
+                "Could not write PHU image.");
+        return false;
+    }
+
+    psFree(image);
+
+    // build a table structure
+    psArray* table = psArrayAlloc(tableNumRows);
+    //    table->n = tableNumRows;
+    psMetadata* header = NULL;
+    for (int row = 0; row < tableNumRows; row++) {
+        header = psMetadataAlloc();
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYINT",
+                      PS_DATA_S32,
+                      "psS32 Item",
+                      (psS32)row);
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYFLT",
+                      PS_DATA_F32,
+                      "psF32 Item",
+                      (float)(1.0f/(float)(1+row)));
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYDBL",
+                      PS_DATA_F64,
+                      "psF64 Item",
+                      (double)(1.0/(double)(1+row)));
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYBOOL",
+                      PS_DATA_BOOL,
+                      "psBool Item",
+                      (row%2 == 0));
+
+        char* str = NULL;
+        psStringAppend(&str,"row=%d",row+1);
+        psMetadataAdd(header,PS_LIST_TAIL, "MYSTR",
+                      PS_DATA_STRING,
+                      "psString Item",
+                      str);
+        psFree(str);
+
+        psVector* vec = psVectorAlloc(5,PS_TYPE_S32);
+        for (int x=0; x < 4; x++) {
+            vec->data.S32[x] = x*10+row;
+            vec->n++;
+        }
+        psMetadataAdd(header,PS_LIST_TAIL, "MYVEC",
+                      PS_DATA_VECTOR,
+                      "psVector Item",
+                      vec);
+        psFree(vec);
+
+        table->data[row] = header;
+        table->n++;
+    }
+
+    psFitsWriteTable(fitsFile, NULL, table, NULL);
+
+    psFree(table);
+    psFree(fitsFile);
+    //    return 1;
+    return (!psMemCheckLeaks(15,NULL,stderr,false));
+}
+
+psS32 tst_psFitsOpen( void )
+{
+
+    if (! makeMulti() ) {
+        return 1;
+    }
+
+    psFits* fitsFile = psFitsOpen(multiFilename,"r");
+
+    if (fitsFile == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsOpen returned NULL on existing file.");
+        return 1;
+    }
+
+    int extNum = psFitsGetExtNum(fitsFile);
+    if (extNum != 0) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsOpen was not queued to the PHU, but to extension #%d.",
+                extNum);
+        return 2;
+    }
+
+    psFitsClose(fitsFile);
+
+    // make sure the file doesn't already exist.
+    if (access("new.fits", F_OK) == 0) {
+        if (remove
+                ("new.fits") != 0) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Couldn't delete the new.fits file.");
+            return 3;
+        }
+    }
+
+    fitsFile = psFitsOpen("new.fits","w");
+
+    if (fitsFile == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsOpen returned NULL on w mode.");
+        return 4;
+    }
+
+    // write something to the file, otherwise CFITSIO will complain on close
+    psImage* img = psImageAlloc(16,16,PS_TYPE_F32);
+    psFitsWriteImage(fitsFile,NULL,img,1,NULL);
+
+    psFree(fitsFile); // psFree should be equivalent to psFitsClose
+
+    // now, if psFitsOpen actually created the file, I shouldn't error in removing it.
+    if (remove
+            ("new.fits") != 0) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsOpen seemed to not have created a new file.");
+        return 5;
+    }
+
+    fitsFile = psFitsOpen("new.fits","w+");
+
+    if (fitsFile == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsOpen returned NULL on w+ mode.");
+        return 6;
+    }
+
+    // write something to the file, otherwise CFITSIO will complain on close
+    psFitsWriteImage(fitsFile,NULL,img,1,NULL);
+
+    psFitsClose(fitsFile);
+
+    // now, if psFitsOpen actually created the file, I shouldn't error in removing it.
+    if (remove
+            ("new.fits") != 0) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsOpen seemed to not have created a new file.");
+        return 7;
+    }
+
+    fitsFile = psFitsOpen("new.fits","a");
+
+    if (fitsFile == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsOpen returned NULL on a mode.");
+        return 8;
+    }
+
+    // write something to the file, otherwise CFITSIO will complain on close
+    psFitsWriteImage(fitsFile,NULL,img,1,NULL);
+
+    psFitsClose(fitsFile);
+
+    fitsFile = psFitsOpen("new.fits","a+");
+
+    if (fitsFile == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsOpen returned NULL on a+ mode.");
+        return 9;
+    }
+
+    psFitsClose(fitsFile);
+
+    // now, if psFitsOpen actually created the file, I shouldn't error in removing it.
+    if (remove
+            ("new.fits") != 0) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsOpen seemed to not have created a new file.");
+        return 10;
+    }
+
+    // Attempt to allocate with NULL filename
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    fitsFile = psFitsOpen(NULL,"r");
+    if(fitsFile != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psFitsOpen did not return NULL for NULL input");
+        return 11;
+    }
+
+    // Attempt to use an invalid mode
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    fitsFile = psFitsOpen("new.fits","b+");
+    if(fitsFile != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psFitsOpen did not return NULL for NULL input");
+        return 12;
+    }
+
+    psFree(img);
+
+    return 0;
+}
+
+psS32 tst_psFitsMoveExtName( void )
+{
+
+    if (! makeMulti() ) {
+        return 1;
+    }
+
+    psFits* fits = psFitsOpen(multiFilename,"r");
+
+    if (fits == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsOpen returned NULL on existing file.");
+        return 1;
+    }
+
+    int numHDUs = psFitsGetSize(fits);
+
+    if (numHDUs < 2) {
+        psError(PS_ERR_UNKNOWN,true,
+                "The 'multi' FITS file does not have multiple HDUs.");
+        return 2;
+    }
+
+    char extName[80];
+    psRegion region = {0,0,0,0};
+
+    for (int lcv = 0; lcv < numHDUs; lcv++) {
+        snprintf(extName,80,"ext-%d",lcv);
+        // try to move to the named extension.
+        if (! psFitsMoveExtName(fits, extName) ) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Failed to move to ext-%d.",
+                    lcv);
+            return 3;
+        }
+
+        // check to see if I can retrieve the name back from the psFits object.
+        char* nameFromFile = psFitsGetExtName(fits);
+        if (strcmp(nameFromFile,extName) != 0) { // hey, it didn't move?
+            psError(PS_ERR_UNKNOWN, false,
+                    "Failed to retrieve the extension name back ('%s' vs '%s'",
+                    nameFromFile, extName);
+            return 3;
+        }
+        psFree(nameFromFile);
+
+        // check that the image is associated to the extension moved, i.e.,
+        // did we really move to the proper extension?
+        psImage* image = NULL;
+        image = psFitsReadImage(fits,region,0);
+
+        if (image == NULL || abs(image->data.F32[0][0] - (float)lcv) > FLT_EPSILON) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "The image pixel 0,0 of ext-%d was %g, expected %d.",
+                    lcv,image->data.F32[0][0],lcv);
+            return 4;
+        }
+        psFree(image);
+    }
+
+    for (int lcv = numHDUs-1; lcv >= 0; lcv--) {
+        snprintf(extName,80,"ext-%d",lcv);
+        // try to move to the named extension.
+        if (! psFitsMoveExtName(fits, extName) ) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Failed to move to ext-%d.",
+                    lcv);
+            return 5;
+        }
+
+        // check to see if I can retrieve the name back from the psFits object.
+        char* nameFromFile = psFitsGetExtName(fits);
+        if (strcmp(nameFromFile,extName) != 0) { // hey, it didn't move?
+            psError(PS_ERR_UNKNOWN, false,
+                    "Failed to retrieve the extension name back ('%s' vs '%s'",
+                    nameFromFile, extName);
+            return 5;
+        }
+        psFree(nameFromFile);
+
+        // check that the image is associated to the extension moved, i.e.,
+        // did we really move to the proper extension?
+        psImage* image = NULL;
+        image = psFitsReadImage(fits,region,0);
+
+        if (abs(image->data.F32[0][0] - (float)lcv) > FLT_EPSILON) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "The image pixel 0,0 of ext-%d was %g, expected %d.",
+                    lcv,image->data.F32[0][0],lcv);
+            return 6;
+        }
+        psFree(image);
+    }
+
+    // check to see if given a bogus extension name, it errors.
+    psLogMsg(__func__,PS_LOG_INFO, "Following should be an error.");
+    if (psFitsMoveExtName(fits, "bogus") || psErrorGetStackSize() != 1) {
+        psError(PS_ERR_UNKNOWN, false,
+                "Moving to non-existant HDU didn't fail.");
+        return 7;
+    }
+
+    // check to see if given a NULL psFits, it errors.
+    psLogMsg(__func__,PS_LOG_INFO, "Following should be an error.");
+    if (psFitsMoveExtName(NULL, "bogus") || psErrorGetStackSize() != 1) {
+        psError(PS_ERR_UNKNOWN, false,
+                "Operation of NULL psFits didn't fail.");
+        return 8;
+    }
+
+    // check to see if given a NULL extname, it errors.
+    psLogMsg(__func__,PS_LOG_INFO, "Following should be an error.");
+    if (psFitsMoveExtName(fits, NULL) || psErrorGetStackSize() != 1) {
+        psError(PS_ERR_UNKNOWN, false,
+                "Operation of NULL extname didn't fail.");
+        return 9;
+    }
+
+    psFree(fits);
+
+    // Attempt to get ext name from null fits file
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for NULL fits file");
+    if(psFitsGetExtName(NULL) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Expected NULL return from psFitsGetExtName with NULL fits file");
+        return 10;
+    }
+
+    return 0;
+}
+
+psS32 tst_psFitsMoveExtNum( void )
+{
+
+    if (! makeMulti() ) {
+        return 1;
+    }
+
+    psFits* fits = psFitsOpen(multiFilename,"r");
+
+    if (fits == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsOpen returned NULL on existing file.");
+        return 1;
+    }
+
+    int numHDUs = psFitsGetSize(fits);
+
+    // as a side test, let's make sure psFitsGetSize can handle NULL.
+    psLogMsg(__func__,PS_LOG_INFO,
+             "Following should be an error.");
+    psErrorClear();
+    if (psFitsGetSize(NULL) != 0 || psErrorGetStackSize() != 1) {
+        psError(PS_ERR_UNKNOWN,true,
+                "The 'multi' FITS file does not have multiple HDUs.");
+        return 2;
+    }
+
+    if (numHDUs != 8) {
+        psError(PS_ERR_UNKNOWN,true,
+                "The 'multi' FITS file does not have multiple HDUs.");
+        return 2;
+    }
+
+    psRegion region = {0,0,0,0};
+
+    // test absolute positioning
+    for (int lcv = 0; lcv < numHDUs; lcv++) {
+        // try to move to the extension
+        if (! psFitsMoveExtNum(fits, lcv, false) ) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Failed to move to extension %d.",
+                    lcv);
+            return 3;
+        }
+
+        // check to see if I can retrieve the number back from the psFits object.
+        if (psFitsGetExtNum(fits) != lcv) { // hey, it didn't move?
+            psError(PS_ERR_UNKNOWN, false,
+                    "Failed to retrieve the extension number back (%d vs %d)",
+                    psFitsGetExtNum(fits), lcv);
+            return 5;
+        }
+
+        // check that the image is associated to the extension moved, i.e.,
+        // did we really move to the proper extension?
+        psImage* image = NULL;
+        image = psFitsReadImage(fits,region,0);
+        if (image == NULL || abs(image->data.F32[0][0] - (float)lcv) > FLT_EPSILON) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "The image pixel 0,0 of ext-%d was %g, expected %d.",
+                    lcv,image->data.F32[0][0],lcv);
+            return 4;
+        }
+        psFree(image);
+    }
+
+    for (int lcv = numHDUs-1; lcv >= 0; lcv--) {
+        // try to move to the extension
+        if (! psFitsMoveExtNum(fits, lcv, false) ) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Failed to move to extension %d.",
+                    lcv);
+            return 5;
+        }
+
+        // check that the image is associated to the extension moved, i.e.,
+        // did we really move to the proper extension?
+        psImage* image = NULL;
+        image = psFitsReadImage(fits,region,0);
+
+        if (abs(image->data.F32[0][0] - (float)lcv) > FLT_EPSILON) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "The image pixel 0,0 of ext-%d was %g, expected %d.",
+                    lcv,image->data.F32[0][0],lcv);
+            return 6;
+        }
+        psFree(image);
+    }
+
+    // test relative positioning
+    psFitsMoveExtNum(fits,0,false);
+    for (int lcv = 1; lcv < numHDUs; lcv++) {
+        // try to move to the extension
+        if (! psFitsMoveExtNum(fits, 1, true) ) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Failed to move to extension %d.",
+                    lcv);
+            return 13;
+        }
+
+        // check to see if I can retrieve the number back from the psFits object.
+        if (psFitsGetExtNum(fits) != lcv) { // hey, it didn't move?
+            psError(PS_ERR_UNKNOWN, false,
+                    "Failed to retrieve the extension number back (%d vs %d)",
+                    psFitsGetExtNum(fits), lcv);
+            return 13;
+        }
+
+        // check that the image is associated to the extension moved, i.e.,
+        // did we really move to the proper extension?
+        psImage* image = NULL;
+        image = psFitsReadImage(fits,region,0);
+
+        if (image == NULL || abs(image->data.F32[0][0] - (float)lcv) > FLT_EPSILON) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "The image pixel 0,0 of ext-%d was %g, expected %d.",
+                    lcv,image->data.F32[0][0],lcv);
+            return 14;
+        }
+        psFree(image);
+    }
+
+    for (int lcv = numHDUs-2; lcv >= 0; lcv--) {
+        // try to move to the extension
+        if (! psFitsMoveExtNum(fits, -1, true) ) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Failed to move to extension %d.",
+                    lcv);
+            return 15;
+        }
+
+        // check to see if I can retrieve the number back from the psFits object.
+        if (psFitsGetExtNum(fits) != lcv) { // hey, it didn't move?
+            psError(PS_ERR_UNKNOWN, false,
+                    "Failed to retrieve the extension number back (%d vs %d)",
+                    psFitsGetExtNum(fits), lcv);
+            return 15;
+        }
+
+        // check that the image is associated to the extension moved, i.e.,
+        // did we really move to the proper extension?
+        psImage* image = NULL;
+        image = psFitsReadImage(fits,region,0);
+
+        if (abs(image->data.F32[0][0] - (float)lcv) > FLT_EPSILON) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "The image pixel 0,0 of ext-%d was %g, expected %d.",
+                    lcv,image->data.F32[0][0],lcv);
+            return 16;
+        }
+        psFree(image);
+    }
+
+    // check to see if given a negative extension number, it errors.
+    psLogMsg(__func__,PS_LOG_INFO, "Following should be an error.");
+    psErrorClear();
+    if (psFitsMoveExtNum(fits, -1, false) || psErrorGetStackSize() != 1) {
+        psError(PS_ERR_UNKNOWN, false,
+                "Moving to negative HDU didn't fail.");
+        return 21;
+    }
+
+    // check to see if relative positioning beyond PHU, it errors.
+    psFitsMoveExtNum(fits,0,false);
+    psLogMsg(__func__,PS_LOG_INFO, "Following should be an error.");
+    psErrorClear();
+    if (psFitsMoveExtNum(fits, -1, true) || psErrorGetStackSize() != 1) {
+        psError(PS_ERR_UNKNOWN, false,
+                "Moving to negative HDU didn't fail.");
+        return 22;
+    }
+
+
+    // check to see if given a extension greater than the total #HDUs, it errors.
+    psLogMsg(__func__,PS_LOG_INFO, "Following should be an error.");
+    psErrorClear();
+    if (psFitsMoveExtNum(fits, numHDUs, false) || psErrorGetStackSize() != 1) {
+        psError(PS_ERR_UNKNOWN, false,
+                "Moving to a HDU beyond the file's contents didn't fail.");
+        return 31;
+    }
+
+    // check to see if relative positioning beyond PHU, it errors.
+    psFitsMoveExtNum(fits,numHDUs-1,false);
+    psLogMsg(__func__,PS_LOG_INFO, "Following should be an error.");
+    psErrorClear();
+    if (psFitsMoveExtNum(fits, 1, true) || psErrorGetStackSize() != 1) {
+        psError(PS_ERR_UNKNOWN, false,
+                "Moving to negative HDU didn't fail.");
+        return 32;
+    }
+
+    // check to see if given a NULL psFits, it errors.
+    psLogMsg(__func__,PS_LOG_INFO, "Following should be an error.");
+    psErrorClear();
+    if (psFitsMoveExtNum(NULL, 0, false) || psErrorGetStackSize() != 1) {
+        psError(PS_ERR_UNKNOWN, false,
+                "Operation of NULL psFits didn't fail.");
+        return 40;
+    }
+
+    psFitsClose(fits);
+
+    // Attempt to get ext name from null fits file
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for NULL fits file");
+    if(psFitsGetExtNum(NULL) != PS_FITS_TYPE_NONE) {
+        psError(PS_ERR_UNKNOWN,true,"Expected NULL return from psFitsGetExtNum with NULL fits file");
+        return 10;
+    }
+
+    return 0;
+}
+
+static psS32 tst_psFitsReadHeader( void )
+{
+    if (! makeMulti() ) {
+        return 1;
+    }
+
+    psFits* fits = psFitsOpen(multiFilename,"r");
+
+    if (fits == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsOpen returned NULL on existing file.");
+        return 1;
+    }
+
+    int numHDUs = psFitsGetSize(fits);
+
+    if (numHDUs < 8) {
+        psError(PS_ERR_UNKNOWN,true,
+                "The 'multi' FITS file does not have multiple HDUs.");
+        return 2;
+    }
+
+    char extname[80];
+    for (int hdunum = 0; hdunum < numHDUs; hdunum++) {
+        snprintf(extname,80,"ext-%d",hdunum);
+
+        psFitsMoveExtNum(fits,hdunum,false);
+
+        psMetadata* header = psFitsReadHeader(NULL,fits);
+        if (header == NULL) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Failed to read header");
+            return 3;
+        }
+
+        psMetadata* header2 = psMetadataAlloc();
+        header2 = psFitsReadHeader(header2,fits);
+        if (header2 == NULL) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Failed to read header");
+            return 11;
+        }
+
+        if (header->list->n < 1 || header->list->n != header2->list->n) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Reading the header given a NULL input psMetadata differed "
+                    "from giving an existing psMetadata.");
+            return 12;
+        }
+
+        // check for the extra metadata items
+        psS32 intItem = psMetadataLookupS32(NULL,header, "MYINT");
+        psF32 fltItem = psMetadataLookupF32(NULL,header, "MYFLT");
+        psF64 dblItem = psMetadataLookupF64(NULL,header, "MYDBL");
+        psMetadataItem* boolItem = psMetadataLookup(header, "MYBOOL");
+        psString strItem = psMetadataLookupStr(NULL, header, "MYSTR");
+
+        if (intItem != hdunum) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to retrieve psS32 metadata item from file.");
+            return 20;
+        }
+
+        if (fabsf(fltItem - 1.0f/(float)(1+hdunum)) > FLT_EPSILON) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to retrieve psF32 metadata item from file.  Got %f vs %f",
+                    fltItem,1.0f/(float)(1+hdunum));
+            return 21;
+        }
+
+        if (abs(dblItem - 1.0/(double)(1+hdunum)) > DBL_EPSILON) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to retrieve psF64 metadata item from file.  Got %g vs %g",
+                    dblItem, 1.0/(double)(1+hdunum));
+            return 22;
+        }
+
+        if (boolItem == NULL ||
+                boolItem->type != PS_DATA_BOOL) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to retrieve psBool metadata item from file.");
+            return 23;
+        }
+
+        if (strItem == NULL || strncmp(strItem,extname,strlen(extname)) != 0) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to retrieve string metadata item from file.  Got '%s' vs '%s' (%d)",
+                    strItem,extname,strlen(extname));
+            return 24;
+        }
+
+        psFree(header);
+        psFree(header2);
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"following should be an error (input psFits = NULL)");
+    psMetadata* header = psFitsReadHeader(NULL,NULL);
+
+    if (header != NULL || psErrorGetStackSize() != 1) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psFitsReadHeader didn't error on a NULL psFits.");
+        return 30;
+    }
+
+
+    psFree(fits);
+
+    return 0;
+}
+
+static psS32 tst_psFitsReadHeaderSet( void )
+{
+    if (! makeMulti() ) {
+        return 1;
+    }
+
+    psFits* fits = psFitsOpen(multiFilename,"r");
+
+    if (fits == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsOpen returned NULL on existing file.");
+        return 1;
+    }
+
+    int numHDUs = psFitsGetSize(fits);
+
+    if (numHDUs < 8) {
+        psError(PS_ERR_UNKNOWN,true,
+                "The 'multi' FITS file does not have multiple HDUs.");
+        return 2;
+    }
+
+    // move to the middle
+    psFitsMoveExtNum(fits,numHDUs/2, false);
+
+    psMetadata* headerSet = psFitsReadHeaderSet(NULL,fits);
+
+    if (headerSet == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsReadHeaderSet returned NULL unexpectedly.");
+        return 3;
+    }
+
+    if (psFitsGetExtNum(fits) != numHDUs/2) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsReadHeaderSet changed the CHU.");
+        return 4;
+    }
+
+    char extname[80];
+    for (int i = 0; i < numHDUs; i++) {
+        if (i == 0) {
+            snprintf(extname, 80, "PHU");
+        } else {
+            snprintf(extname, 80, "ext-%d", i);
+        }
+
+        psMetadata* header = psMetadataLookupPtr(NULL,headerSet, extname);
+
+        if (header == NULL) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "psFitsReadHeader returned NULL unexpectedly for HDU#%d.",
+                    i);
+            return 5;
+        }
+
+        psS32 intItem = psMetadataLookupS32(NULL, header, "MYINT");
+
+        if (intItem != i) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "psFitsReadHeader for HDU#%d had a MYINT of %d, expected %d.",
+                    intItem, i);
+            return 6;
+        }
+    }
+
+    psMetadata* set3 = psFitsReadHeaderSet(NULL,fits);
+    if (set3 == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsReadHeaderSet returned NULL unexpectedly.");
+        return 11;
+    }
+
+    for (int i = 0; i < numHDUs; i++) {
+        if (i == 0) {
+            snprintf(extname, 80, "PHU");
+        } else {
+            snprintf(extname, 80, "ext-%d", i);
+        }
+
+        psMetadata* header = psMetadataLookupPtr(NULL, set3, extname);
+
+        if (header == NULL) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "psFitsReadHeader returned NULL unexpectedly for HDU#%d.",
+                    i);
+            return 5;
+        }
+
+        psS32 intItem = psMetadataLookupS32(NULL, header, "MYINT");
+
+        if (intItem != i) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "psFitsReadHeader for HDU#%d had a MYINT of %d, expected %d.",
+                    intItem, i);
+            return 6;
+        }
+    }
+
+    set3 = psFitsReadHeaderSet(set3,NULL);
+    if (set3 != NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsReadHeaderSet returned non-NULL given a NULL psFits.");
+        return 10;
+    }
+
+    psFree(headerSet);
+
+    psFitsClose(fits);
+
+    return 0;
+}
+
+static psS32 tst_psFitsReadTable( void )
+{
+
+
+    if (! makeTable()) {
+        return 111;
+    }
+
+    psFits* fits = psFitsOpen(tableFilename,"r");
+
+    if (fits == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsOpen returned NULL on existing file.");
+        return 1;
+    }
+
+    psFitsMoveExtNum(fits,1,false);
+
+    psArray* table = psFitsReadTable(fits);
+
+    if (table == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsReadTable returned NULL unexpectedly.");
+        return 2;
+    }
+
+    if (table->n != tableNumRows) {
+        psError(PS_ERR_UNKNOWN, false,
+                "Expected %d rows, but read %d.",
+                tableNumRows, table->n);
+        return 3;
+    }
+
+
+    for (int row = 0; row < table->n; row++) {
+        psMetadata* rowData = table->data[row];
+
+        psS32 intItem = psMetadataLookupS32(NULL, rowData, "MYINT");
+        psF32 fltItem = psMetadataLookupF32(NULL, rowData, "MYFLT");
+        psF64 dblItem = psMetadataLookupF64(NULL, rowData, "MYDBL");
+        psBool boolItem = psMetadataLookupBool(NULL, rowData, "MYBOOL");
+        psString strItem = psMetadataLookupStr(NULL, rowData, "MYSTR");
+        psVector* vecItem = psMetadataLookupPtr(NULL, rowData, "MYVEC");
+
+        if (intItem != row) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to retrieve psS32 metadata item from file (row=%d).  Got %d vs %d",
+                    row, intItem, row);
+            return 20;
+        }
+
+        if (fabsf(fltItem - 1.0f/(float)(1+row)) > FLT_EPSILON) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to retrieve psF32 metadata item from file (row=%d).  Got %f vs %f",
+                    row, fltItem,1.0f/(float)(1+row));
+            return 21;
+        }
+
+        if (abs(dblItem - 1.0/(double)(1+row)) > DBL_EPSILON) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to retrieve psF64 metadata item from file (row=%d).  Got %g vs %g",
+                    row, dblItem, 1.0/(double)(1+row));
+            return 22;
+        }
+
+        if ( boolItem != ((row&0x01) == 0)) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to retrieve psBool metadata item from file (row=%d). Got %d vs %d",
+                    row, boolItem, ((row&0x01) == 0));
+            return 23;
+        }
+
+        char strValue[16];
+        snprintf(strValue,16,"row=%d",row+1);
+        if ( strncmp(strItem,strValue,strlen(strValue)) != 0) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to retrieve psString metadata item from file (row=%d). Got '%s' vs '%s'",
+                    row, strItem, strValue);
+            return 24;
+        }
+
+        if ( vecItem == NULL ) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to retrieve psVector metadata item from file (row=%d).",
+                    row);
+            return 25;
+        }
+
+        if ( vecItem->type.type != PS_DATA_S32 ||
+                vecItem->data.S32[0] != row ||
+                vecItem->data.S32[3] != row+30 ) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Retrieved psVector (row=%d) didn't match expected values [%d,%d,%d,%d] vs [%d,%d,%d,%d].",
+                    row,vecItem->data.S32[0], vecItem->data.S32[1],
+                    vecItem->data.S32[2], vecItem->data.S32[3],
+                    row,row+10,row+20,row+30);
+            return 26;
+        }
+
+    }
+
+    psFree(table);
+    psFree(fits);
+
+    psArray* nullTest = psFitsReadTable(NULL);
+
+    if (nullTest != NULL || psErrorGetStackSize() != 1) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psFitsReadTable returned non-NULL when given NULL.");
+        return 30;
+    }
+
+    return 0;
+}
+
+static psS32 tst_psFitsReadTableColumnNum( void )
+{
+    if (! makeTable()) {
+        return 111;
+    }
+
+    psFits* fits = psFitsOpen(tableFilename,"r");
+
+    if (fits == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsOpen returned NULL on existing file.");
+        return 1;
+    }
+
+    psFitsMoveExtNum(fits,1,false);
+
+    // read the column data via number
+    psVector* colData;
+    psElemType type[4] = {PS_TYPE_S32, PS_TYPE_F32, PS_TYPE_F32, PS_TYPE_BOOL};
+    psElemType altType[4] = {PS_TYPE_S64, PS_TYPE_F64, PS_TYPE_F64, PS_TYPE_BOOL};
+    char* colname[4] = {"MYINT","MYFLT","MYDBL","MYBOOL"};
+    psF64 expectedValues[4][10] = {
+                                      {0,1,2,3,4,5,6,7,8,9},
+                                      {1.0,1.0/2.0,1.0/3.0,1.0/4.0,1.0/5.0,1.0/6.0,1.0/7.0,1.0/8.0,1.0/9.0},
+                                      {1.0,1.0/2.0,1.0/3.0,1.0/4.0,1.0/5.0,1.0/6.0,1.0/7.0,1.0/8.0,1.0/9.0},
+                                      {1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0}
+                                  };
+
+    for (int col = 0; col < 4; col++) {
+        colData = psFitsReadTableColumnNum(fits,colname[col]);
+        if (colData == NULL) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "psFitsReadTableColumnNum returned NULL for col=%d",
+                    col);
+            return 2;
+        }
+        if (colData->type.type != type[col] &&
+                colData->type.type != altType[col]) {
+            char* typeRead;
+            char* typeExpected;
+            PS_TYPE_NAME(typeRead, colData->type.type);
+            PS_TYPE_NAME(typeExpected, type[col]);
+
+            psError(PS_ERR_UNKNOWN, false,
+                    "psFitsReadTableColumnNum returned different type, %s vs %s, for col=%d",
+                    typeRead, typeExpected, col);
+            return 3;
+        }
+        if (colData->n != tableNumRows) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "psFitsReadTableColumnNum returned different number of rows, %d vs %d, for col=%d",
+                    colData->n, tableNumRows, col);
+            return 4;
+        }
+        for (int row = 0; row < tableNumRows; row++) {
+            if (abs(p_psVectorGetElementF64(colData,row) - expectedValues[col][row]) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN, false,
+                        "psFitsReadTableColumnNum returned unexpected values (%g vs %g) for col=%d",
+                        p_psVectorGetElementF64(colData,row), expectedValues[col][row], col);
+                return 5;
+            }
+        }
+        psFree(colData);
+    }
+
+    psWarning("Following should be an error.");
+    psErrorClear();
+    psVector* data = psFitsReadTableColumnNum(NULL,colname[0]);
+    psErr* err = psErrorLast();
+    if (data != NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsReadTableColumnNum did not return NULL with NULL psFits");
+        return 6;
+    }
+    if (err->code != PS_ERR_BAD_PARAMETER_NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsReadTableColumnNum did not error with NULL psFits");
+        return 7;
+    }
+    psFree(err);
+
+    psWarning("Following should be an error.");
+    psErrorClear();
+    data = psFitsReadTableColumnNum(fits,"BOGUS");
+    err = psErrorLast();
+    if (data != NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsReadTableColumnNum did not return NULL with bogus column name.");
+        return 8;
+    }
+    if (err->code != PS_ERR_IO) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsReadTableColumnNum did not error with bogus column name.");
+        return 9;
+    }
+    psFree(err);
+
+    psFree(fits);
+
+    return 0;
+}
+
+static psS32 tst_psFitsReadTableColumn( void )
+{
+    if (! makeTable()) {
+        return 111;
+    }
+
+    psFits* fits = psFitsOpen(tableFilename,"r");
+
+    if (fits == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsOpen returned NULL on existing file.");
+        return 1;
+    }
+
+    psFitsMoveExtNum(fits,1,false);
+
+    // read the column data via number
+    psArray* colData;
+    char* colname[4] = {"MYINT","MYFLT","MYDBL","MYBOOL"};
+    psF64 expectedValues[3][10] = {
+                                      {0,1,2,3,4,5,6,7,8,9},
+                                      {1.0,1.0/2.0,1.0/3.0,1.0/4.0,1.0/5.0,1.0/6.0,1.0/7.0,1.0/8.0,1.0/9.0},
+                                      {1.0,1.0/2.0,1.0/3.0,1.0/4.0,1.0/5.0,1.0/6.0,1.0/7.0,1.0/8.0,1.0/9.0}
+                                  };
+    char* expectedBoolValues[10] = {"T","F","T","F","T","F","T","F","T","F"};
+    char* expectedStrValues[10] = {"row=1","row=2","row=3","row=4","row=5","row=6","row=7","row=8","row=9","row=10"};
+
+    for (int col = 0; col < 4; col++) {
+        colData = psFitsReadTableColumn(fits,colname[col]);
+        if (colData == NULL) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "psFitsReadTableColumn returned NULL for col=%d",
+                    col);
+            return 2;
+        }
+        if (colData->n != tableNumRows) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "psFitsReadTableColumn returned different number of rows, %d vs %d, for col=%d",
+                    colData->n, tableNumRows, col);
+            return 4;
+        }
+        if (col < 3) {
+            for (int row = 0; row < tableNumRows; row++) {
+                if (abs(atof((char*)colData->data[row]) - expectedValues[col][row]) > 0.0001) {
+                    psError(PS_ERR_UNKNOWN, false,
+                            "psFitsReadTableColumn returned unexpected values (%g vs %g) for col=%d",
+                            atof((char*)colData->data[row]), expectedValues[col][row], col);
+                    return 5;
+                }
+            }
+        } else if (col == 3) {
+            for (int row = 0; row < tableNumRows; row++) {
+                if (strncmp(colData->data[row],expectedBoolValues[row],
+                            strlen(expectedBoolValues[row])) != 0) {
+                    psError(PS_ERR_UNKNOWN, false,
+                            "psFitsReadTableColumn returned unexpected values ('%s' vs '%s') for col=%d",
+                            (char*)colData->data[row], expectedBoolValues[row], col);
+                    return 5;
+                }
+            }
+        } else if (col == 4) {
+            for (int row = 0; row < tableNumRows; row++) {
+                if (strncmp(colData->data[row],expectedStrValues[row],
+                            strlen(expectedStrValues[row])) != 0) {
+                    psError(PS_ERR_UNKNOWN, false,
+                            "psFitsReadTableColumn returned unexpected values ('%s' vs '%s') for col=%d",
+                            (char*)colData->data[row], expectedStrValues[row], col);
+                    return 5;
+                }
+            }
+        }
+
+        psFree(colData);
+    }
+
+    psWarning("Following should be an error.");
+    psErrorClear();
+    psArray* data = psFitsReadTableColumn(NULL,"MYINT");
+    psErr* err = psErrorLast();
+    if (data != NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsReadTableColumn did not return NULL with NULL psFits");
+        return 6;
+    }
+    if (err->code != PS_ERR_BAD_PARAMETER_NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsReadTableColumn did not error with NULL psFits");
+        return 7;
+    }
+    psFree(err);
+
+    psWarning(__func__,"Following should be an error.");
+    psErrorClear();
+    data = psFitsReadTableColumn(fits,"BOGUS");
+    err = psErrorLast();
+    if (data != NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsReadTableColumn did not return NULL with col=\"BOGUS\"");
+        return 8;
+    }
+    if (err->code != PS_ERR_IO) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsReadTableColumn did not error with col=\"BOGUS\"");
+        return 9;
+    }
+    psFree(err);
+
+    psFree(fits);
+
+    return 0;
+}
+
+static psS32 tst_psFitsUpdateTable( void )
+{
+    psErr* err;
+    char* strValue[] = {
+                           "row A",
+                           "row B",
+                           "row C",
+                           "row D",
+                           "row E",
+                           "row F",
+                           "row G",
+                           "row H",
+                           "row I",
+                           "row J",
+                           "row K"
+                       };
+
+
+    if (! makeTable()) {
+        return 111;
+    }
+
+    psFits* fits = psFitsOpen(tableFilename,"rw");
+
+    if (fits == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsOpen returned NULL on existing file.");
+        return 2;
+    }
+
+    psFitsMoveExtNum(fits,1,false);
+
+    // change the data in the file, going past by one (implicit new row of data)
+    for (int row = 0; row < tableNumRows+1; row++) {
+        psMetadata* md = psMetadataAlloc();
+        psMetadataAddF32(md,PS_LIST_TAIL,"MYFLT", 0,"",(float)row/-10.0);
+        psMetadataAddF64(md,PS_LIST_TAIL,"MYDBL", 0,"",(double)row/-100.0);
+        psMetadataAddS32(md,PS_LIST_TAIL,"MYINT", 0,"",-row);
+        psMetadataAddBool(md,PS_LIST_TAIL,"MYBOOL", 0,"",((row & 1) == 1));
+        psMetadataAddStr(md,PS_LIST_TAIL,"MYSTR", 0,"",strValue[row]);
+
+        if (! psFitsUpdateTable(fits,md,row)) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "psFitsUpdateTable returned false, but expected true for row=%d.",
+                    row);
+            return 3;
+        }
+        psFree(md);
+    }
+
+    for (int row = 0; row < tableNumRows+1; row++) {
+        psMetadata* md = psFitsReadTableRow(fits, row);
+        if (abs(psMetadataLookupF32(NULL,md,"MYFLT") - (float)row/-10.0) > FLT_EPSILON) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "psFitsUpdateTable did not change the float value for row=%d.",
+                    row);
+            return 4;
+        }
+        if (abs(psMetadataLookupF64(NULL,md,"MYDBL") - (float)row/-100.0) > FLT_EPSILON) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "psFitsUpdateTable did not change the double value for row=%d.",
+                    row);
+            return 5;
+        }
+        if (psMetadataLookupS32(NULL,md,"MYINT") != -row) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "psFitsUpdateTable did not change the integer value for row=%d.",
+                    row);
+            return 6;
+        }
+        if (psMetadataLookupBool(NULL,md,"MYBOOL") != ((row &1) == 1)) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "psFitsUpdateTable did not change the boolean value for row=%d.",
+                    row);
+            return 7;
+        }
+        psString mystr = psMetadataLookupStr(NULL,md,"MYSTR");
+        if (strncmp(mystr,strValue[row],
+                    strlen(strValue[row])) != 0) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "psFitsUpdateTable did not change the string value for row=%d.",
+                    row);
+            return 8;
+        }
+        psFree(md);
+    }
+
+    psMetadata* md = psMetadataAlloc();
+    psMetadataAddF32(md,PS_LIST_TAIL,"BOGUS", 0,"",-1.0f);
+    psWarning("Following should be a warning.");
+    psErrorClear();
+    if (! psFitsUpdateTable(fits,md,0)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsUpdateTable did not return false with bogus column data");
+        return 10;
+    }
+    psFree(md);
+
+    md = psMetadataAlloc();
+    psMetadataAddF32(md,PS_LIST_TAIL,"MYFLT", 0,"",-1.0f);
+    psMetadataAddF64(md,PS_LIST_TAIL,"MYDBL", 0,"",-2.0);
+    psMetadataAddS32(md,PS_LIST_TAIL,"MYINT", 0,"",-3);
+
+    psWarning("Following should be an error.");
+    psErrorClear();
+    if (psFitsUpdateTable(NULL,md,0)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsUpdateTable did not return false with NULL psFits");
+        return 20;
+    }
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsUpdateTable did not error with NULL psFits");
+        return 21;
+    }
+    psFree(err);
+
+    psWarning("Following should be an error.");
+    psErrorClear();
+    if (psFitsUpdateTable(fits,NULL,0)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsUpdateTable did not return false with NULL psMetadata");
+        return 22;
+    }
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsUpdateTable did not error with NULL psMetadata");
+        return 23;
+    }
+    psFree(err);
+
+    psWarning("Following should be an error.");
+    psErrorClear();
+    if (psFitsUpdateTable(fits,md,-1)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsUpdateTable did not return false with row=-1");
+        return 24;
+    }
+    err = psErrorLast();
+    if (err->code != PS_ERR_IO) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psFitsUpdateTable did not error with row=-1");
+        return 25;
+    }
+
+    psFree(err);
+    psFree(md);
+    psFitsClose(fits);
+
+    return 0;
+}
+
+psS32 testImageRead(void)
+{
+    psS32 N = 256;
+    psS32 M = 128;
+
+    /*
+        This function shall open the specified FITS file, read the specified data
+        and place the data into a psImage structure. This function shall generate
+        an error message and return NULL if any of the input parameters are out of
+        range, image file doesn't exist or image is zero or one dimensional.
+
+        Verify the returned psImage structure contains expected values, if the input
+        parameter filename specifies an available FITS file with known 2dimensional
+        data, input parameters col, row, ncol, nrow, z specify data range with the
+        FITS file. Cases should include 1x1, Nx1, 1xN, NxN and MxN sub images and
+        total FITS file image. (done in macro)
+
+        Verify the returned psImage structure is equal to the input parameter
+        'output', if specified. (done in macro)
+
+        */
+
+    /* generate FITS file to read */
+
+    #define testReadTypeSize(m, n, readM0, readN0, readM, readN, TYP, filename) \
+    { \
+        psImage* img = NULL; \
+        psImage* img2 = NULL; \
+        psImage* img3 = NULL; \
+        psImage* img4 = NULL; \
+        /*        psImagimge* img_ref = NULL; */ \
+        \
+        GENIMAGE(img,m,n,TYP,row+2*col); \
+        img2 = psImageCopy(img2,img,PS_TYPE_##TYP); \
+        GENIMAGE(img3,m,n,TYP,row+2*col); \
+        psImageClip(img3,32.0,32.0,120.0,120.0); \
+        img4 = psImageCopy(img4,img3,PS_TYPE_##TYP); \
+        psFits* fits = psFitsOpen(filename, "w"); \
+        if (! psFitsWriteImage(fits, NULL, img, 2, NULL)) { \
+            psError(PS_ERR_UNKNOWN, true,"Failed to write test image %s",filename); \
+            return 1; \
+        } \
+        if (! psFitsUpdateImage(fits,img3, 0,0, 1)) { \
+            psError(PS_ERR_UNKNOWN, true,"Failed to write test image %s",filename); \
+            return 2; \
+        } \
+        if (! psFitsWriteImage(fits,NULL, img3, 2, NULL)) { \
+            psError(PS_ERR_UNKNOWN, true,"Failed to write test image %s",filename); \
+            return 3; \
+        } \
+        if (! psFitsUpdateImage(fits,img, 0, 0, 1)) { \
+            psError(PS_ERR_UNKNOWN, true,"Failed to write test image %s",filename); \
+            return 4; \
+        } \
+        psFree(img); \
+        psFree(fits); \
+        img = NULL; \
+        psFree(img3); \
+        img3 = NULL; \
+        fits = psFitsOpen(filename,"r"); \
+        psRegion reg = {readM0, readM, readN0, readN}; \
+        img = psFitsReadImage(fits, reg, 0); \
+        img3 = psFitsReadImage(fits, reg, 1); \
+        if (img3 == NULL) { \
+            psError(PS_ERR_UNKNOWN, true,"Failed to read test image %s",filename); \
+            return 6; \
+        } \
+        for (psU32 row = readN0; row < readN; row++) { \
+            ps##TYP* imgRow = img->data.TYP[row-readN0]; \
+            ps##TYP* img2Row = img2->data.TYP[row]; \
+            ps##TYP* img3Row = img3->data.TYP[row-readN0]; \
+            ps##TYP* img4Row = img4->data.TYP[row]; \
+            for (psU32 col = readM0; col < readM; col++) { \
+                if (fabsf(imgRow[col-readM0]-img2Row[col]) > FLT_EPSILON) { \
+                    psError(PS_ERR_UNKNOWN, true,"Image changed in I/O operation at %d,%d,0 (%.2f vs %.2f) for %s", \
+                            col,row,(psF32)imgRow[col-readM0],(psF32)img2Row[col],filename); \
+                    return 7; \
+                } \
+                if (fabsf(img3Row[col-readM0]-img4Row[col]) > FLT_EPSILON) { \
+                    psError(PS_ERR_UNKNOWN, true,"Image changed in I/O operation at %d,%d,1 (%.2f vs %.2f) for %s", \
+                            col,row,(psF32)img3Row[col-readM0],(psF32)img4Row[col],filename); \
+                    return 8; \
+                } \
+            } \
+        } \
+        psFree(img); \
+        img = NULL; \
+        psFree(img3); \
+        img3 = NULL; \
+        psFitsMoveExtNum(fits,1, false); \
+        img3 = psFitsReadImage(fits, reg, 0); \
+        img = psFitsReadImage(fits, reg, 1); \
+        if (img == NULL) { \
+            psError(PS_ERR_UNKNOWN, true,"Failed to read test image %s",filename); \
+            return 9; \
+        } \
+        for (psU32 row = readN0; row < readN; row++) { \
+            ps##TYP* imgRow = img->data.TYP[row-readN0]; \
+            ps##TYP* img2Row = img2->data.TYP[row]; \
+            ps##TYP* img3Row = img3->data.TYP[row-readN0]; \
+            ps##TYP* img4Row = img4->data.TYP[row]; \
+            for (psU32 col = readM0; col < readM; col++) { \
+                if (fabsf(imgRow[col-readM0]-img2Row[col]) > FLT_EPSILON) { \
+                    psError(PS_ERR_UNKNOWN, true,"Image changed in I/O operation at %d,%d,0 (%.2f vs %.2f) for %s", \
+                            col,row,(psF32)imgRow[col-readM0],(psF32)img2Row[col],filename); \
+                    return 10; \
+                } \
+                if (fabsf(img3Row[col-readM0]-img4Row[col]) > FLT_EPSILON) { \
+                    psError(PS_ERR_UNKNOWN, true,"Image changed in I/O operation at %d,%d,1 (%.2f vs %.2f) for %s", \
+                            col,row,(psF32)img3Row[col-readM0],(psF32)img4Row[col],filename); \
+                    return 11; \
+                } \
+            } \
+        } \
+        psFree(img); \
+        psFree(img2); \
+        psFree(img3); \
+        psFree(img4); \
+        psFree(fits); \
+    }
+
+    #define testReadType(TYP,filename) \
+    testReadTypeSize(1,1,0,0,0,0,TYP,"tmpImages/1x1_" filename); \
+    testReadTypeSize(M,1,M/4,0,M*3/4,0,TYP,"tmpImages/Mx1_" filename); \
+    testReadTypeSize(1,N,0,N/4,0,N*3/4,TYP,"tmpImages/1xN_" filename); \
+    testReadTypeSize(M,N,M/4,N/4,M*3/4,N*3/4,TYP,"tmpImages/MxN_" filename);
+
+    mkdir("tmpImages",0777);
+
+    testReadType(U8,"U8.fits");
+    testReadType(S8,"S8.fits");   // Not a requirement
+    testReadType(S16,"S16.fits");
+    testReadType(U16,"U16.fits"); // Not a requirement
+    testReadType(S32,"S32.fits");
+    testReadType(U32,"U32.fits"); // Not a requirement
+    testReadType(F32,"F32.fits");
+    testReadType(F64,"F64.fits");
+
+    // Attempt to read from NULL fits object
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL psFits");
+    psRegion region = {
+                          0,0,0,0
+                      };
+    if(psFitsReadImage(NULL,region,0) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL for NULL psFits");
+        return 100;
+    }
+
+    return 0;
+}
+
+psS32 testImageWrite(void)
+{
+    psImage* img = NULL;
+    psImage* img2 = NULL;
+    psS32 m = 64;
+    psS32 n = 96;
+
+    /*
+    This function shall write the specified section within a psImage structure
+    to a FITS file. If the specifiedfile exists, then data should overwrite the
+    section to write. If the specified file doesn't exist, it shall be created.
+    If an extenstion is specified, then a basic primary header data unit shall
+    be created.
+    */
+
+    /*
+    Verify a FITS file named filename is generated and contains expected
+    values, if the input parameter input contains known data values, input
+    parameters col, row, ncol, nrow specify a valid data region within psImage
+    structure.
+
+    Verify a FITS file named filename is generated and contains a primary
+    header data unit with extension with expected values, if the input
+    parameter input contains known data values, input parameters col, row,
+    ncol, nrow specify a valid data region within psImage structure and
+    extname and/or extnum specify an extenstion to write.
+
+    N.B. : these are done in testImageRead tests, see above.
+    */
+
+    /*
+    Verify a FITS file named filename is overwritten and contains
+    expected values, if the input parameter input contains known data values,
+    input parameters col, row, ncol, nrow specify a valid data region within
+    psImage structure.
+    */
+
+    GENIMAGE(img,m,n,F32,0);
+    GENIMAGE(img2,m,n,F32,row+2*col);
+    mkdir("tmpImages",0777);
+    psFits* fits = psFitsOpen("tmpImages/writeTest.fits","w");
+
+    if (! psFitsWriteImage(fits, NULL, img,1, NULL)) {
+        psError(PS_ERR_UNKNOWN, true,"Couldn't write writeTest.fits.");
+        return 14;
+    }
+    if (! psFitsUpdateImage(fits, img2, 0, 0, 0)) {
+        psError(PS_ERR_UNKNOWN, true,"Couldn't update writeTest.fits.");
+        return 15;
+    }
+    psFree(img);
+    psFree(img2);
+
+    // Did it really overwrite the pixel values?  Let's read it in and see.
+    psFitsClose(fits);
+
+    psRegion region = {0,0,0,0};
+    fits = psFitsOpen("tmpImages/writeTest.fits","r");
+    img = NULL;
+    img = psFitsReadImage(fits, region, 0);
+    if (img == NULL) {
+        psError(PS_ERR_UNKNOWN, true,"Could not read in writeTest.fits.");
+        return 16;
+    }
+    for (psU32 row=0;row<n;row++) {
+        psF32* imgRow = img->data.F32[row];
+        for (psU32 col=0;col<m;col++) {
+            if (fabsf(imgRow[col] - (row+2*col)) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN, true,"The image values were not overwritten at %d,%d (%.2f vs %.2f)",
+                        col,row,imgRow[col],(row+2*col));
+                return 17;
+            }
+        }
+    }
+
+    psFree(img);
+
+    /*
+    Verify false is returned and program execution is not stopped, if the input image
+    is null.
+    */
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message because input image is null.");
+    if ( psFitsWriteImage(fits,NULL,NULL, 1, NULL) ) {
+        psError(PS_ERR_UNKNOWN, true,"psImageWriteSection did not return false when input image is NULL.");
+        return 20;
+    }
+
+    psFree(fits);
+
+    return 0;
+}
+
+psS32 tst_psFitsWriteHeader(void)
+{
+    if (! makeMulti() ) {
+        return 1;
+    }
+
+    psMetadata* header   = psMetadataAlloc();
+    psFits*     fitsFile = psFitsOpen(multiFilename,"a+");
+
+    // Test psFitsReadWrite generates files from psFitsWriteImage which calls psFitsWriteHeader
+    // so these additional tests check for error conditions
+    // Attempt call function with NULL metadata
+    if(psFitsWriteHeader(fitsFile, NULL)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return of true for NULL metadata pointer");
+        return 2;
+    }
+
+    psFree(fitsFile);
+
+    // Attempt to call function with NULL fits
+    if(psFitsWriteHeader(NULL, header)) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return of true for NULL fits file pointer");
+        return 3;
+    }
+    psFree(header);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/fits/verified/fBiOut.fits
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/fits/verified/fBiOut.fits	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/fits/verified/fBiOut.fits	(revision 22158)
@@ -0,0 +1,6427 @@
+SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             B~
+B~záB~p€B~ffB~\)B~QìB~G®B~=qB~33B~(öB~
+žB~{B~
+=B~  B}õÃB}ë
+B}áHB}×
+B}ÌÍB}ÂB}žRB}®B}£×B}B}\B}
+B}záB}p€B}ffB}\)B}QìB}G®B}=qB}33B}(öB}
+žB}{B}
+=B}  B|õÃB|ë
+B|áHB|×
+B|ÌÍB|ÂB|žRB|®B|£×B|B|\B|
+B|záB|p€B|ffB|\)B|QìB|G®B|=qB|33B|(öB|
+žB|{B|
+=B|  Bz
+BzzáBzp€BzffBz\)BzQìBzG®Bz=qBz33Bz(öBz
+žBz{Bz
+=Bz  ByõÃByë
+ByáHBy×
+ByÌÍByÂByžRBy®By£×ByBy\By
+ByzáByp€ByffBy\)ByQìByG®By=qBy33By(öBy
+žBy{By
+=By  BxõÃBxë
+BxáHBx×
+BxÌÍBxÂBxžRBx®Bx£×BxBx\Bx
+BxzáBxp€BxffBx\)BxQìBxG®Bx=qBx33Bx(öBx
+žBx{Bx
+=Bx  Bv
+BvzáBvp€BvffBv\)BvQìBvG®Bv=qBv33Bv(öBv
+žBv{Bv
+=Bv  BuõÃBuë
+BuáHBu×
+BuÌÍBuÂBužRBu®Bu£×BuBu\Bu
+BuzáBup€BuffBu\)BuQìBuG®Bu=qBu33Bu(öBu
+žBu{Bu
+=Bu  BtõÃBtë
+BtáHBt×
+BtÌÍBtÂBtžRBt®Bt£×BtBt\Bt
+BtzáBtp€BtffBt\)BtQìBtG®Bt=qBt33Bt(öBt
+žBt{Bt
+=Bt  Br
+BrzáBrp€BrffBr\)BrQìBrG®Br=qBr33Br(öBr
+žBr{Br
+=Br  BqõÃBqë
+BqáHBq×
+BqÌÍBqÂBqžRBq®Bq£×BqBq\Bq
+BqzáBqp€BqffBq\)BqQìBqG®Bq=qBq33Bq(öBq
+žBq{Bq
+=Bq  BpõÃBpë
+BpáHBp×
+BpÌÍBpÂBpžRBp®Bp£×BpBp\Bp
+BpzáBpp€BpffBp\)BpQìBpG®Bp=qBp33Bp(öBp
+žBp{Bp
+=Bp  Bn
+BnzáBnp€BnffBn\)BnQìBnG®Bn=qBn33Bn(öBn
+žBn{Bn
+=Bn  BmõÃBmë
+BmáHBm×
+BmÌÍBmÂBmžRBm®Bm£×BmBm\Bm
+BmzáBmp€BmffBm\)BmQìBmG®Bm=qBm33Bm(öBm
+žBm{Bm
+=Bm  BlõÃBlë
+BláHBl×
+BlÌÍBlÂBlžRBl®Bl£×BlBl\Bl
+BlzáBlp€BlffBl\)BlQìBlG®Bl=qBl33Bl(öBl
+žBl{Bl
+=Bl  Bj
+BjzáBjp€BjffBj\)BjQìBjG®Bj=qBj33Bj(öBj
+žBj{Bj
+=Bj  BiõÃBië
+BiáHBi×
+BiÌÍBiÂBižRBi®Bi£×BiBi\Bi
+BizáBip€BiffBi\)BiQìBiG®Bi=qBi33Bi(öBi
+žBi{Bi
+=Bi  BhõÃBhë
+BháHBh×
+BhÌÍBhÂBhžRBh®Bh£×BhBh\Bh
+BhzáBhp€BhffBh\)BhQìBhG®Bh=qBh33Bh(öBh
+žBh{Bh
+=Bh  Bf
+BfzáBfp€BfffBf\)BfQìBfG®Bf=qBf33Bf(öBf
+žBf{Bf
+=Bf  BeõÃBeë
+BeáHBe×
+BeÌÍBeÂBežRBe®Be£×BeBe\Be
+BezáBep€BeffBe\)BeQìBeG®Be=qBe33Be(öBe
+žBe{Be
+=Be  BdõÃBdë
+BdáHBd×
+BdÌÍBdÂBdžRBd®Bd£×BdBd\Bd
+BdzáBdp€BdffBd\)BdQìBdG®Bd=qBd33Bd(öBd
+žBd{Bd
+=Bd  Bb
+BbzáBbp€BbffBb\)BbQìBbG®Bb=qBb33Bb(öBb
+žBb{Bb
+=Bb  BaõÃBaë
+BaáHBa×
+BaÌÍBaÂBažRBa®Ba£×BaBa\Ba
+BazáBap€BaffBa\)BaQìBaG®Ba=qBa33Ba(öBa
+žBa{Ba
+=Ba  B`õÃB`ë
+B`áHB`×
+B`ÌÍB`ÂB`žRB`®B`£×B`B`\B`
+B`záB`p€B`ffB`\)B`QìB`G®B`=qB`33B`(öB`
+žB`{B`
+=B`  B^
+B^záB^p€B^ffB^\)B^QìB^G®B^=qB^33B^(öB^
+žB^{B^
+=B^  B]õÃB]ë
+B]áHB]×
+B]ÌÍB]ÂB]žRB]®B]£×B]B]\B]
+B]záB]p€B]ffB]\)B]QìB]G®B]=qB]33B](öB]
+žB]{B]
+=B]  B\õÃB\ë
+B\áHB\×
+B\ÌÍB\ÂB\žRB\®B\£×B\B\\B\
+B\záB\p€B\ffB\\)B\QìB\G®B\=qB\33B\(öB\
+žB\{B\
+=B\  BZ
+BZzáBZp€BZffBZ\)BZQìBZG®BZ=qBZ33BZ(öBZ
+žBZ{BZ
+=BZ  BYõÃBYë
+BYáHBY×
+BYÌÍBYÂBYžRBY®BY£×BYBY\BY
+BYzáBYp€BYffBY\)BYQìBYG®BY=qBY33BY(öBY
+žBY{BY
+=BY  BXõÃBXë
+BXáHBX×
+BXÌÍBXÂBXžRBX®BX£×BXBX\BX
+BXzáBXp€BXffBX\)BXQìBXG®BX=qBX33BX(öBX
+žBX{BX
+=BX  BV
+BVzáBVp€BVffBV\)BVQìBVG®BV=qBV33BV(öBV
+žBV{BV
+=BV  BUõÃBUë
+BUáHBU×
+BUÌÍBUÂBUžRBU®BU£×BUBU\BU
+BUzáBUp€BUffBU\)BUQìBUG®BU=qBU33BU(öBU
+žBU{BU
+=BU  BTõÃBTë
+BTáHBT×
+BTÌÍBTÂBTžRBT®BT£×BTBT\BT
+BTzáBTp€BTffBT\)BTQìBTG®BT=qBT33BT(öBT
+žBT{BT
+=BT  BR
+BRzáBRp€BRffBR\)BRQìBRG®BR=qBR33BR(öBR
+žBR{BR
+=BR  BQõÃBQë
+BQáHBQ×
+BQÌÍBQÂBQžRBQ®BQ£×BQBQ\BQ
+BQzáBQp€BQffBQ\)BQQìBQG®BQ=qBQ33BQ(öBQ
+žBQ{BQ
+=BQ  BPõÃBPë
+BPáHBP×
+BPÌÍBPÂBPžRBP®BP£×BPBP\BP
+BPzáBPp€BPffBP\)BPQìBPG®BP=qBP33BP(öBP
+žBP{BP
+=BP  BN
+BNzáBNp€BNffBN\)BNQìBNG®BN=qBN33BN(öBN
+žBN{BN
+=BN  BMõÃBMë
+BMáHBM×
+BMÌÍBMÂBMžRBM®BM£×BMBM\BM
+BMzáBMp€BMffBM\)BMQìBMG®BM=qBM33BM(öBM
+žBM{BM
+=BM  BLõÃBLë
+BLáHBL×
+BLÌÍBLÂBLžRBL®BL£×BLBL\BL
+BLzáBLp€BLffBL\)BLQìBLG®BL=qBL33BL(öBL
+žBL{BL
+=BL  BJ
+BJzáBJp€BJffBJ\)BJQìBJG®BJ=qBJ33BJ(öBJ
+žBJ{BJ
+=BJ  BIõÃBIë
+BIáHBI×
+BIÌÍBIÂBIžRBI®BI£×BIBI\BI
+BIzáBIp€BIffBI\)BIQìBIG®BI=qBI33BI(öBI
+žBI{BI
+=BI  BHõÃBHë
+BHáHBH×
+BHÌÍBHÂBHžRBH®BH£×BHBH\BH
+BHzáBHp€BHffBH\)BHQìBHG®BH=qBH33BH(öBH
+žBH{BH
+=BH  BF
+BFzáBFp€BFffBF\)BFQìBFG®BF=qBF33BF(öBF
+žBF{BF
+=BF  BEõÃBEë
+BEáHBE×
+BEÌÍBEÂBEžRBE®BE£×BEBE\BE
+BEzáBEp€BEffBE\)BEQìBEG®BE=qBE33BE(öBE
+žBE{BE
+=BE  BDõÃBDë
+BDáHBD×
+BDÌÍBDÂBDžRBD®BD£×BDBD\BD
+BDzáBDp€BDffBD\)BDQìBDG®BD=qBD33BD(öBD
+žBD{BD
+=BD  BB
+BBzáBBp€BBffBB\)BBQìBBG®BB=qBB33BB(öBB
+žBB{BB
+=BB  BAõÃBAë
+BAáHBA×
+BAÌÍBAÂBAžRBA®BA£×BABA\BA
+BAzáBAp€BAffBA\)BAQìBAG®BA=qBA33BA(öBA
+žBA{BA
+=BA  B@õÃB@ë
+B@áHB@×
+B@ÌÍB@ÂB@žRB@®B@£×B@B@\B@
+B@záB@p€B@ffB@\)B@QìB@G®B@=qB@33B@(öB@
+žB@{B@
+=B@  B>
+B>záB>p€B>ffB>\)B>QìB>G®B>=qB>33B>(öB>
+žB>{B>
+=B>  B=õÃB=ë
+B=áHB=×
+B=ÌÍB=ÂB=žRB=®B=£×B=B=\B=
+B=záB=p€B=ffB=\)B=QìB=G®B==qB=33B=(öB=
+žB={B=
+=B=  B<õÃB<ë
+B<áHB<×
+B<ÌÍB<ÂB<žRB<®B<£×B<B<\B<
+B<záB<p€B<ffB<\)B<QìB<G®B<=qB<33B<(öB<
+žB<{B<
+=B<  B:
+B:záB:p€B:ffB:\)B:QìB:G®B:=qB:33B:(öB:
+žB:{B:
+=B:  B9õÃB9ë
+B9áHB9×
+B9ÌÍB9ÂB9žRB9®B9£×B9B9\B9
+B9záB9p€B9ffB9\)B9QìB9G®B9=qB933B9(öB9
+žB9{B9
+=B9  B8õÃB8ë
+B8áHB8×
+B8ÌÍB8ÂB8žRB8®B8£×B8B8\B8
+B8záB8p€B8ffB8\)B8QìB8G®B8=qB833B8(öB8
+žB8{B8
+=B8  B6
+B6záB6p€B6ffB6\)B6QìB6G®B6=qB633B6(öB6
+žB6{B6
+=B6  B5õÃB5ë
+B5áHB5×
+B5ÌÍB5ÂB5žRB5®B5£×B5B5\B5
+B5záB5p€B5ffB5\)B5QìB5G®B5=qB533B5(öB5
+žB5{B5
+=B5  B4õÃB4ë
+B4áHB4×
+B4ÌÍB4ÂB4žRB4®B4£×B4B4\B4
+B4záB4p€B4ffB4\)B4QìB4G®B4=qB433B4(öB4
+žB4{B4
+=B4  B2
+B2záB2p€B2ffB2\)B2QìB2G®B2=qB233B2(öB2
+žB2{B2
+=B2  B1õÃB1ë
+B1áHB1×
+B1ÌÍB1ÂB1žRB1®B1£×B1B1\B1
+B1záB1p€B1ffB1\)B1QìB1G®B1=qB133B1(öB1
+žB1{B1
+=B1  B0õÃB0ë
+B0áHB0×
+B0ÌÍB0ÂB0žRB0®B0£×B0B0\B0
+B0záB0p€B0ffB0\)B0QìB0G®B0=qB033B0(öB0
+žB0{B0
+=B0  B.
+B.záB.p€B.ffB.\)B.QìB.G®B.=qB.33B.(öB.
+žB.{B.
+=B.  B-õÃB-ë
+B-áHB-×
+B-ÌÍB-ÂB-žRB-®B-£×B-B-\B-
+B-záB-p€B-ffB-\)B-QìB-G®B-=qB-33B-(öB-
+žB-{B-
+=B-  B,õÃB,ë
+B,áHB,×
+B,ÌÍB,ÂB,žRB,®B,£×B,B,\B,
+B,záB,p€B,ffB,\)B,QìB,G®B,=qB,33B,(öB,
+žB,{B,
+=B,  B*
+B*záB*p€B*ffB*\)B*QìB*G®B*=qB*33B*(öB*
+žB*{B*
+=B*  B)õÃB)ë
+B)áHB)×
+B)ÌÍB)ÂB)žRB)®B)£×B)B)\B)
+B)záB)p€B)ffB)\)B)QìB)G®B)=qB)33B)(öB)
+žB){B)
+=B)  B(õÃB(ë
+B(áHB(×
+B(ÌÍB(ÂB(žRB(®B(£×B(B(\B(
+B(záB(p€B(ffB(\)B(QìB(G®B(=qB(33B((öB(
+žB({B(
+=B(  B&
+B&záB&p€B&ffB&\)B&QìB&G®B&=qB&33B&(öB&
+žB&{B&
+=B&  B%õÃB%ë
+B%áHB%×
+B%ÌÍB%ÂB%žRB%®B%£×B%B%\B%
+B%záB%p€B%ffB%\)B%QìB%G®B%=qB%33B%(öB%
+žB%{B%
+=B%  B$õÃB$ë
+B$áHB$×
+B$ÌÍB$ÂB$žRB$®B$£×B$B$\B$
+B$záB$p€B$ffB$\)B$QìB$G®B$=qB$33B$(öB$
+žB${B$
+=B$  B"
+B"záB"p€B"ffB"\)B"QìB"G®B"=qB"33B"(öB"
+žB"{B"
+=B"  B!õÃB!ë
+B!áHB!×
+B!ÌÍB!ÂB!žRB!®B!£×B!B!\B!
+B!záB!p€B!ffB!\)B!QìB!G®B!=qB!33B!(öB!
+žB!{B!
+=B!  B õÃB ë
+B áHB ×
+B ÌÍB ÂB žRB ®B £×B B \B 
+B záB p€B ffB \)B QìB G®B =qB 33B (öB 
+žB {B 
+=B   B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B	õÃB	ë
+B	áHB	×
+B	ÌÍB	ÂB	žRB	®B	£×B	B	\B	
+B	záB	p€B	ffB	\)B	QìB	G®B	=qB	33B	(öB	
+žB	{B	
+=B	  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B õÃB ë
+B áHB ×
+B ÌÍB ÂB žRB ®B £×B B \B 
+B záB p€B ffB \)B QìB G®B =qB 33B (öB 
+žB {B 
+=B   Aý
+=AüõÃAüáHAüÌÍAüžRAü£×Aü\AüzáAüffAüQìAü=qAü(öAü{Aü  Aûë
+Aû×
+AûÂAû®AûAû
+Aûp€Aû\)AûG®Aû33Aû
+žAû
+=AúõÃAúáHAúÌÍAúžRAú£×Aú\AúzáAúffAúQìAú=qAú(öAú{Aú  Aùë
+Aù×
+AùÂAù®AùAù
+Aùp€Aù\)AùG®Aù33Aù
+žAù
+=AøõÃAøáHAøÌÍAøžRAø£×Aø\AøzáAøffAøQìAø=qAø(öAø{Aø  Aõ
+=AôõÃAôáHAôÌÍAôžRAô£×Aô\AôzáAôffAôQìAô=qAô(öAô{Aô  Aóë
+Aó×
+AóÂAó®AóAó
+Aóp€Aó\)AóG®Aó33Aó
+žAó
+=AòõÃAòáHAòÌÍAòžRAò£×Aò\AòzáAòffAòQìAò=qAò(öAò{Aò  Añë
+Añ×
+AñÂAñ®AñAñ
+Añp€Añ\)AñG®Añ33Añ
+žAñ
+=AðõÃAðáHAðÌÍAðžRAð£×Að\AðzáAðffAðQìAð=qAð(öAð{Að  Aí
+=AìõÃAìáHAìÌÍAìžRAì£×Aì\AìzáAìffAìQìAì=qAì(öAì{Aì  Aëë
+Aë×
+AëÂAë®AëAë
+Aëp€Aë\)AëG®Aë33Aë
+žAë
+=AêõÃAêáHAêÌÍAêžRAê£×Aê\AêzáAêffAêQìAê=qAê(öAê{Aê  Aéë
+Aé×
+AéÂAé®AéAé
+Aép€Aé\)AéG®Aé33Aé
+žAé
+=AèõÃAèáHAèÌÍAèžRAè£×Aè\AèzáAèffAèQìAè=qAè(öAè{Aè  Aå
+=AäõÃAäáHAäÌÍAäžRAä£×Aä\AäzáAäffAäQìAä=qAä(öAä{Aä  Aãë
+Aã×
+AãÂAã®AãAã
+Aãp€Aã\)AãG®Aã33Aã
+žAã
+=AâõÃAâáHAâÌÍAâžRAâ£×Aâ\AâzáAâffAâQìAâ=qAâ(öAâ{Aâ  Aáë
+Aá×
+AáÂAá®AáAá
+Aáp€Aá\)AáG®Aá33Aá
+žAá
+=AàõÃAàáHAàÌÍAàžRAà£×Aà\AàzáAàffAàQìAà=qAà(öAà{Aà  AÝ
+=AÜõÃAÜáHAÜÌÍAÜžRAÜ£×AÜ\AÜzáAÜffAÜQìAÜ=qAÜ(öAÜ{AÜ  AÛë
+AÛ×
+AÛÂAÛ®AÛAÛ
+AÛp€AÛ\)AÛG®AÛ33AÛ
+žAÛ
+=AÚõÃAÚáHAÚÌÍAÚžRAÚ£×AÚ\AÚzáAÚffAÚQìAÚ=qAÚ(öAÚ{AÚ  AÙë
+AÙ×
+AÙÂAÙ®AÙAÙ
+AÙp€AÙ\)AÙG®AÙ33AÙ
+žAÙ
+=AØõÃAØáHAØÌÍAØžRAØ£×AØ\AØzáAØffAØQìAØ=qAØ(öAØ{AØ  AÕ
+=AÔõÃAÔáHAÔÌÍAÔžRAÔ£×AÔ\AÔzáAÔffAÔQìAÔ=qAÔ(öAÔ{AÔ  AÓë
+AÓ×
+AÓÂAÓ®AÓAÓ
+AÓp€AÓ\)AÓG®AÓ33AÓ
+žAÓ
+=AÒõÃAÒáHAÒÌÍAÒžRAÒ£×AÒ\AÒzáAÒffAÒQìAÒ=qAÒ(öAÒ{AÒ  AÑë
+AÑ×
+AÑÂAÑ®AÑAÑ
+AÑp€AÑ\)AÑG®AÑ33AÑ
+žAÑ
+=AÐõÃAÐáHAÐÌÍAÐžRAÐ£×AÐ\AÐzáAÐffAÐQìAÐ=qAÐ(öAÐ{AÐ  AÍ
+=AÌõÃAÌáHAÌÌÍAÌžRAÌ£×AÌ\AÌzáAÌffAÌQìAÌ=qAÌ(öAÌ{AÌ  AËë
+AË×
+AËÂAË®AËAË
+AËp€AË\)AËG®AË33AË
+žAË
+=AÊõÃAÊáHAÊÌÍAÊžRAÊ£×AÊ\AÊzáAÊffAÊQìAÊ=qAÊ(öAÊ{AÊ  AÉë
+AÉ×
+AÉÂAÉ®AÉAÉ
+AÉp€AÉ\)AÉG®AÉ33AÉ
+žAÉ
+=AÈõÃAÈáHAÈÌÍAÈžRAÈ£×AÈ\AÈzáAÈffAÈQìAÈ=qAÈ(öAÈ{AÈ  AÅ
+=AÄõÃAÄáHAÄÌÍAÄžRAÄ£×AÄ\AÄzáAÄffAÄQìAÄ=qAÄ(öAÄ{AÄ  AÃë
+AÃ×
+AÃÂAÃ®AÃAÃ
+AÃp€AÃ\)AÃG®AÃ33AÃ
+žAÃ
+=AÂõÃAÂáHAÂÌÍAÂžRAÂ£×AÂ\AÂzáAÂffAÂQìAÂ=qAÂ(öAÂ{AÂ  AÁë
+AÁ×
+AÁÂAÁ®AÁAÁ
+AÁp€AÁ\)AÁG®AÁ33AÁ
+žAÁ
+=AÀõÃAÀáHAÀÌÍAÀžRAÀ£×AÀ\AÀzáAÀffAÀQìAÀ=qAÀ(öAÀ{AÀ  Aœ
+=AŒõÃAŒáHAŒÌÍAŒžRAŒ£×AŒ\AŒzáAŒffAŒQìAŒ=qAŒ(öAŒ{AŒ  A»ë
+A»×
+A»ÂA»®A»A»
+A»p€A»\)A»G®A»33A»
+žA»
+=AºõÃAºáHAºÌÍAºžRAº£×Aº\AºzáAºffAºQìAº=qAº(öAº{Aº  A¹ë
+A¹×
+A¹ÂA¹®A¹A¹
+A¹p€A¹\)A¹G®A¹33A¹
+žA¹
+=AžõÃAžáHAžÌÍAžžRAž£×Až\AžzáAžffAžQìAž=qAž(öAž{Až  Aµ
+=AŽõÃAŽáHAŽÌÍAŽžRAŽ£×AŽ\AŽzáAŽffAŽQìAŽ=qAŽ(öAŽ{AŽ  A³ë
+A³×
+A³ÂA³®A³A³
+A³p€A³\)A³G®A³33A³
+žA³
+=A²õÃA²áHA²ÌÍA²žRA²£×A²\A²záA²ffA²QìA²=qA²(öA²{A²  A±ë
+A±×
+A±ÂA±®A±A±
+A±p€A±\)A±G®A±33A±
+žA±
+=A°õÃA°áHA°ÌÍA°žRA°£×A°\A°záA°ffA°QìA°=qA°(öA°{A°  A­
+=A¬õÃA¬áHA¬ÌÍA¬žRA¬£×A¬\A¬záA¬ffA¬QìA¬=qA¬(öA¬{A¬  A«ë
+A«×
+A«ÂA«®A«A«
+A«p€A«\)A«G®A«33A«
+žA«
+=AªõÃAªáHAªÌÍAªžRAª£×Aª\AªzáAªffAªQìAª=qAª(öAª{Aª  A©ë
+A©×
+A©ÂA©®A©A©
+A©p€A©\)A©G®A©33A©
+žA©
+=AšõÃAšáHAšÌÍAšžRAš£×Aš\AšzáAšffAšQìAš=qAš(öAš{Aš  A¥
+=A€õÃA€áHA€ÌÍA€žRA€£×A€\A€záA€ffA€QìA€=qA€(öA€{A€  A£ë
+A£×
+A£ÂA£®A£A£
+A£p€A£\)A£G®A£33A£
+žA£
+=A¢õÃA¢áHA¢ÌÍA¢žRA¢£×A¢\A¢záA¢ffA¢QìA¢=qA¢(öA¢{A¢  A¡ë
+A¡×
+A¡ÂA¡®A¡A¡
+A¡p€A¡\)A¡G®A¡33A¡
+žA¡
+=A õÃA áHA ÌÍA žRA £×A \A záA ffA QìA =qA (öA {A   A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Az{Ayë
+AyÂAyAyp€AyG®Ay
+žAxõÃAxÌÍAx£×AxzáAxQìAx(öAx  Aw×
+Aw®Aw
+Aw\)Aw33Aw
+=AváHAvžRAv\AvffAv=qAv{Auë
+AuÂAuAup€AuG®Au
+žAtõÃAtÌÍAt£×AtzáAtQìAt(öAt  As×
+As®As
+As\)As33As
+=AráHAržRAr\ArffAr=qAr{Aqë
+AqÂAqAqp€AqG®Aq
+žApõÃApÌÍAp£×ApzáApQìAp(öAp  Aj{Aië
+AiÂAiAip€AiG®Ai
+žAhõÃAhÌÍAh£×AhzáAhQìAh(öAh  Ag×
+Ag®Ag
+Ag\)Ag33Ag
+=AfáHAfžRAf\AfffAf=qAf{Aeë
+AeÂAeAep€AeG®Ae
+žAdõÃAdÌÍAd£×AdzáAdQìAd(öAd  Ac×
+Ac®Ac
+Ac\)Ac33Ac
+=AbáHAbžRAb\AbffAb=qAb{Aaë
+AaÂAaAap€AaG®Aa
+žA`õÃA`ÌÍA`£×A`záA`QìA`(öA`  AZ{AYë
+AYÂAYAYp€AYG®AY
+žAXõÃAXÌÍAX£×AXzáAXQìAX(öAX  AW×
+AW®AW
+AW\)AW33AW
+=AVáHAVžRAV\AVffAV=qAV{AUë
+AUÂAUAUp€AUG®AU
+žATõÃATÌÍAT£×ATzáATQìAT(öAT  AS×
+AS®AS
+AS\)AS33AS
+=ARáHARžRAR\ARffAR=qAR{AQë
+AQÂAQAQp€AQG®AQ
+žAPõÃAPÌÍAP£×APzáAPQìAP(öAP  AJ{AIë
+AIÂAIAIp€AIG®AI
+žAHõÃAHÌÍAH£×AHzáAHQìAH(öAH  AG×
+AG®AG
+AG\)AG33AG
+=AFáHAFžRAF\AFffAF=qAF{AEë
+AEÂAEAEp€AEG®AE
+žADõÃADÌÍAD£×ADzáADQìAD(öAD  AC×
+AC®AC
+AC\)AC33AC
+=ABáHABžRAB\ABffAB=qAB{AAë
+AAÂAAAAp€AAG®AA
+žA@õÃA@ÌÍA@£×A@záA@QìA@(öA@  A:{A9ë
+A9ÂA9A9p€A9G®A9
+žA8õÃA8ÌÍA8£×A8záA8QìA8(öA8  A7×
+A7®A7
+A7\)A733A7
+=A6áHA6žRA6\A6ffA6=qA6{A5ë
+A5ÂA5A5p€A5G®A5
+žA4õÃA4ÌÍA4£×A4záA4QìA4(öA4  A3×
+A3®A3
+A3\)A333A3
+=A2áHA2žRA2\A2ffA2=qA2{A1ë
+A1ÂA1A1p€A1G®A1
+žA0õÃA0ÌÍA0£×A0záA0QìA0(öA0  A*{A)ë
+A)ÂA)A)p€A)G®A)
+žA(õÃA(ÌÍA(£×A(záA(QìA((öA(  A'×
+A'®A'
+A'\)A'33A'
+=A&áHA&žRA&\A&ffA&=qA&{A%ë
+A%ÂA%A%p€A%G®A%
+žA$õÃA$ÌÍA$£×A$záA$QìA$(öA$  A#×
+A#®A#
+A#\)A#33A#
+=A"áHA"žRA"\A"ffA"=qA"{A!ë
+A!ÂA!A!p€A!G®A!
+žA õÃA ÌÍA £×A záA QìA (öA   A{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A
+{A	ë
+A	ÂA	A	p€A	G®A	
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žA õÃA ÌÍA £×A záA QìA (öA   @ô(ö@ó×
+@ó
+@ó33@òáH@ò\@ò=q@ñë
+@ñ@ñG®@ðõÂ@ð£×@ðQì@ð  @ï®@ï\)@ï
+=@îžR@îff@î{@íÂ@íp€@í
+ž@ìÌÍ@ìzá@ì(ö@ë×
+@ë
+@ë33@êáH@ê\@ê=q@éë
+@é@éG®@èõÃ@è£×@èQì@è  @ç®@ç\)@ç
+=@æžR@æff@æ{@åÂ@åp€@å
+ž@äÌÍ@äzá@ä(ö@ã×
+@ã
+@ã33@âáH@â\@â=q@áë
+@á@áG®@àõÃ@à£×@àQì@à  @Ô(ö@Ó×
+@Ó
+@Ó33@ÒáH@Ò\@Ò=q@Ñë
+@Ñ@ÑG®@ÐõÂ@Ð£×@ÐQì@Ð  @Ï®@Ï\)@Ï
+=@ÎžR@Îff@Î{@ÍÂ@Íp€@Í
+ž@ÌÌÍ@Ìzá@Ì(ö@Ë×
+@Ë
+@Ë33@ÊáH@Ê\@Ê=q@Éë
+@É@ÉG®@ÈõÃ@È£×@ÈQì@È  @Ç®@Ç\)@Ç
+=@ÆžR@Æff@Æ{@ÅÂ@Åp€@Å
+ž@ÄÌÍ@Äzá@Ä(ö@Ã×
+@Ã
+@Ã33@ÂáH@Â\@Â=q@Áë
+@Á@ÁG®@ÀõÃ@À£×@ÀQì@À  @Ž(ö@³×
+@³
+@³33@²áH@²\@²=q@±ë
+@±@±G®@°õÂ@°£×@°Qì@°  @¯®@¯\)@¯
+=@®žR@®ff@®{@­Â@­p€@­
+ž@¬ÌÍ@¬zá@¬(ö@«×
+@«
+@«33@ªáH@ª\@ª=q@©ë
+@©@©G®@šõÃ@š£×@šQì@š  @§®@§\)@§
+=@ŠžR@Šff@Š{@¥Â@¥p€@¥
+ž@€ÌÍ@€zá@€(ö@£×
+@£
+@£33@¢áH@¢\@¢=q@¡ë
+@¡@¡G®@ õÃ@ £×@ Qì@   @(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÂ@£×@Qì@  @®@\)@
+=@žR@ff@{@Â@p€@
+ž@ÌÍ@zá@(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÃ@£×@Qì@  @®@\)@
+=@žR@ff@{@
+Â@
+p€@
+
+ž@ÌÍ@zá@(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÃ@£×@Qì@  @hQì@g®@g
+>@fff@eÂ@e
+ž@dzá@c×
+@c33@b\@aë
+@aG®@`£×@`  @_\)@^žR@^{@]p€@\ÌÍ@\(ö@[
+@ZáH@Z=q@Y@XõÂ@XQì@W®@W
+>@Vff@UÂ@U
+ž@Tzá@S×
+@S33@R\@Që
+@QG®@P£×@P  @O\)@NžR@N{@Mp€@LÌÍ@L(ö@K
+@JáH@J=q@I@HõÃ@HQì@G®@G
+=@Fff@EÂ@E
+ž@Dzá@C×
+@C33@B\@Aë
+@AG®@@£×@@  @(Qì@'®@'
+>@&ff@%Â@%
+ž@$zá@#×
+@#33@"\@!ë
+@!G®@ £×@   @\)@
+žR@
+{@
+p€@
+ÌÍ@
+(ö@
+@áH@=q@@õÂ@Qì@®@
+>@ff@Â@
+ž@zá@×
+@33@\@ë
+@G®@£×@  @\)@žR@{@
+p€@
+ÌÍ@
+(ö@
+
+@
+áH@
+=q@	@õÃ@Qì@®@
+=@ff@Â@
+ž@zá@×
+@33@\@ë
+@G®@ £×@   ?Ð£×?Ï\)?Î{?ÌÌÍ?Ë
+
+?Ê=p?ÈõÂ?Ç®?Æff?Å
+ž?Ã×
+?Â\?ÁG®?À  ?ŸžR?œp€?Œ(ö?ºáH?¹?žQì?·
+>?µÂ?Žzá?³33?±ë
+?°£×?¯\)?®{?¬ÌÍ?«
+?ª=q?šõÂ?§®?Šff?¥
+ž?£×
+?¢\?¡G®?   ?žR?p€?(ö?áH??Qì?
+>?Â?zá?33?ë
+?£×?\)?{?ÌÍ?
+?=q?õÃ?®?ff?
+
+ž?×
+?\?G®?  ?!G®?
+žR?
+(ö??
+=?zá?ë
+?\)?
+ÌÍ?
+=q?®?
+ž?\?   >úáH>õÂ>ð£×>ë
+>æff>áG®>Ü(ö>×
+=>Ñë
+>ÌÌÍ>Ç®>Â\>œp€>žQì>³33>®{>šõÃ>£×
+>žR>>zá>\)>=q>
+
+ž>  >uÂ>k
+>aG®>W
+=>LÌÍ>B\>8Qì>.{>#×
+>>\)>
+ž=õÂ=áG®=ÌÌÍ=žQì=£×
+=\)=uÂ=LÌÍ=#×
+<õÂ<£×
+<#×
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~bB~Æ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BxºrB{-B~[B~vK¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BsKBuæBx²ÜB{³B~LB~gÏ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bmj#Bp=ÞBs
+ŽBu×Bx€aB{q7B~>B~YT¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BgÁûBj¶BmbBp/cBrü9BuÉBxæB{bœB~/B~JÙ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BbÓBdíBgºdBj;BmTBp çBríŸBuºBxkB{TAB~!B~<^¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B\q«B_EfBb<BdßBg«éBjx¿BmEBpmBrßCBu¬BxxðB{EÆB~B~-ã¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BVÉBY?B\jB_6ìBbÂBdÐBgoBjjFBm7
+BpòBrÐÉBuBxjuB{7LB~"B~g¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BQ!\BSõBVÁíBYÄB\[B_(pBaõGBdÂ
+BgôBj[ÊBm(¡BoõwBrÂMBu$Bx[úB{(ÐB}õ§B~ì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BKy4BNLïBQÅBSæBV³rBYHB\MB_öBaæÌBd³¢BgyBjMOBm%BoæüBr³ÒBušBxMB{UB}ç+B~q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BEÑ
+BH€ÇBKqBN>tBQ
+JBSØ BV€÷BYqÎB\>€B_
+zBaØQBd¥'BgqýBj>ÔBm
+ªBoØBr¥WBur-Bx?B{
+ÚB}Ø°B}óö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B@(äBBüBEÉuBHLBKc"BN/øBPüÏBSÉŠBV|BYcRB\0)B^üÿBaÉÕBd¬BgcBj0XBlý/BoÊBrÛBuc²Bx0Bzý_B}Ê5B}åz¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B:œB=TxB@!NBBî%BEºûBHÑBKTšBN!BPîUBS»+BVBYTØB\!®B^î
+Ba»[Bd1BgUBj!ÞBlîŽBo»BraBuU8Bx"BzîäB}»»B}Öÿ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B4ØB7¬PB:y&B=EýB@ÓBBß©BE¬BHyWBKF-BNBPßÚBS¬°BVyBYF]B\3B^à	Ba¬àBdy¶BgFBjcBlà9Bo­BryæBuFŒBxBzàiB}­?B}È¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B/0mB2(B4ÐþB7ÕB:j«B=7B@XBBÑ/BEBHjÛBK7²BNBPÑ^BS5BVk
+BY7áB\žB^ÑBadBdk;Bg8BjèBlÑŸBoBrkkBu8ABxBzÑîB}ÄB}º¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B)EB,\ B/(ÖB1õ­B4ÂB7YB:\0B=)B?õÝBBÂ³BEBH\`BK)6BMö
+BPÂãBS¹BV\BY)fB[ö<B^ÃBaéBd\ÀBg)BiölBlÃCBoBr\ïBu)ÆBwöBzÃrB}HB}«¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B#à
+B&³ØB)®B,M
+B/[B1ç1B4ŽB7ßB:MµB=B?çbBBŽ8BEBHMåBK»BMçBPŽhBS>BVNBYëB[çÁB^ŽBanBdNDBgBiçñBlŽÇBoBrNtBuJBwè BzŽ÷B}ÍB}¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+7õB!
+°B#ØB&¥]B)r3B,?	B/
+àB1Ø·B4¥B7rcB:?:B=
+B?ØæBB¥œBErBH?iBK
+@BMÙBP¥ìBSrÃBV?BY
+pB[ÙFB^Š
+BaróBd?ÉBg
+BiÙvBlŠLBos"Br?øBu
+ÏBwÙ¥BzŠ|B}sRB}¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BÎBcB
+0_B ý6B#Ê
+B&âB)c¹B,0B.ýfB1Ê<B4B7céB:0¿B<ýB?ÊlBBBBEdBH0ïBJýÅBMÊBPrBSdIBV1BXýõB[ÊÌB^¢BadxBd1OBfþ%BiÊûBlÑBodšBr1~BtþUBwË+BzB}dØB}¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BçŠB»aB7BUB
+!äB îºB#»B&hB)U>B,"B.îëB1»ÁB4B7UnB:"DB<ïB?»ñBBÇBEUBH"tBJïJBMŒ!BP÷BSUÍBV"€BXïzB[ŒPB^'BaUýBd"ÓBfï©BiŒBlVBoV-Br#BtïÙBwŒ°BzB}V\B}q ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+?~B9BàB¬æByŒBFB
+iB à@B#­B&yìB)FÃB,B.àoB1­FB4z
+B7FòB:ÉB<àB?­uBBzLBEG"BHùBJàÏBM­¥BPz|BSGRBV(BXàÿB[­ÕB^z«BaGBdXBfá.Bi®BlzÛBoG±BrBtá^Bw®4Bz{
+B}GáB}c$¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BVB
+kB
+7çBŸBÑBjBkAB8B
+îB ÑÄB#B&kqB)8GB,
+B.ÑôB1ÊB4k¡B78wB:MB<Ò$B?úBBkÑBE8§BH}BJÒTBM*BPl BS8×BV­BXÒB[YB^l0Ba9BdÝBfÒ³BiBll`Bo96Br
+BtÒãBw¹BzlB}9fB}Tª¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bï.BÂéB¿B
+\B
+)lBöBBÃBðB\ÆB)B
+ösB ÃIB#B&\öB))ÌB+ö¢B.ÃyB1OB4]%B7)üB9öÒB<Ã©B?BB]UBE*,BG÷BJÃØBM¯BP]
+BS*[BU÷1BXÄB[ÞB^]µBa*Bc÷aBfÄ8BiBl]äBo*»Bq÷BtÄgBw>Bz^B}*ëB}F.¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aø
+Aþ5BçBŽnBDB
+NB
+ñBçÈBŽBtBNKB!B
+ç÷B ŽÎB#€B&NzB)QB+è'B.ŽýB1ÔB4NªB7B9èWB<µ-B?BBNÚBE°BGèBJµ]BM3BPO	BSàBUè¶BXµB[cB^O9Ba
+BcèæBfµŒBiBlOiBo
+?BqéBtµíBwÃBzOB}
+pB}7³¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aí=ŒAòå3Aø~àAþBÙ
+B¥òBrÉB
+? B
+
+vBÙLBŠ#BrùB?ÏB
+ŠB
+Ù|B ŠRB#s)B&?ÿB)
+ÕB+Ù¬B.ŠB1sYB4@/B7
+B9ÙÜB<Š²B?sBB@_BE
+5BGÚ
+BJŠáBMsžBP@BS
+eBUÚ;BX§B[sèB^@ŸBa
+BcÚkBf§ABitBl@îBo
+ÅBqÚBt§qBwtHBzA
+B}
+ôB})8¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AáílAçãAí.AòÈ=AøaêAýûBÊ¡BxBdNB
+1$B
+ýûBÊÑB§Bd~B1TBþ*B
+ËB ×B#d­B&1B(þZB+Ë1B.B1dÝB41ŽB6þB9Ë`B<7B?e
+BB1ãBDþ¹BGËBJfBMe=BP2BRþéBUËÀBXB[elB^2CB`ÿBcËïBfÆBieBl2sBnÿIBqÌ BtöBweÌBz2£B|ÿyB}Œ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÖ
+AÜDAáÞ@AçwíAíAò«GAøDóAýÞ BŒ&BüBUÓB
+"©B
+ïBŒVB,BVB"ÙBï¯B
+Œ
+B \B#V2B&#	B(ïßB+ŒµB.B1VbB4#8B6ðB9ŒåB<»B?VBB#hBDð>BGœBJëBMVÁBP#BRðnBUœDBXB[VñB^#ÇB`ðBcœuBfKBiW!Bl#øBnðÎBqœ€Bt{BwWQBz$'B|ðþB}
+A¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AËLÌAÐôCAÖðAÜ'AáÁJAçZ÷Aìô£AòPAø'üAýÁ©B­«BzBGWB
+.B
+áB­ÚBz±BGB]Bá4B
+®
+B záB#G·B&B(ádB+®:B.{B1GçB4œB6áB9®iB<{@B?HBBíBDáÃBG®BJ{pBMHFBP
+BRáóBU®ÉBX{B[HvB^MB`â#Bc®ùBf{ÐBiHŠBl|BnâSBq¯)Bt{ÿBwHÖBz¬B|âB|ýÆ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A¿ü|AÅ£óAË= AÐ×MAÖpúAÜ
+§Aá€SAç> Aì×¬AòqYAø
+Aý€²B/BlB8ÜB
+²B
+ÒB_Bl5B9
+BâBÒ¹B
+B leB#9<B&B(ÒèB+¿B.lB19kB4AB6ÓB9îB<lÅB?9BBqBDÓHBG 
+BJlôBM9ËBP¡BRÓwBU NBXm%B[9ûB^ÑB`ÓšBc ~BfmTBi:+BlBnÓ×Bq ®BtmBw:ZBz1B|ÔB|ïJ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AŽ¬,AºS£A¿íPAÅýAË ªAÐºWAÖTAÛí°Aá\Aç!	Aìº¶AòTbA÷îAýŒBŽB]B*aB	÷7B
+Ä
+BäB]ºB*B÷gBÄ=B
+B ]êB#*ÀB%÷B(ÄmB+CB.^B1*ðB3÷ÆB6ÄB9sB<^IB?+ BA÷öBDÄÌBG£BJ^yBM+OBOø&BRÄýBUÓBX^©B[+B]øVB`Å,BcBf^ÙBi+¯BkøBnÅ\Bq2Bt_	Bw+ßByøµB|ÅB|àÏ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A©[ÜA¯SAŽ Aº6­A¿ÐZAÅjAË³AÐ`AÖ7
+AÛÐ¹AájfAçAì¿Aò7lA÷ÑAýjÆB9BOBåB	èŒB
+µBiBO?B
+BèìBµÂB
+B OoB#
+EB%éB(µñB+ÈB.OB1
+uB3éKB6¶!B9øB<OÎB?
+€BAé{BD¶QBG'BJOþBM
+ÕBOé«BR¶BUXBXP.B[
+B]éÛB`¶±BcBfP^Bi
+4Bkê
+Bn¶áBq·BtPBw
+dByê:B|·B|ÒT¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+A£³A©L¯A®æ\AŽ	Aº¶A¿³bAÅMAÊæ»AÐhAÖAÛ³ÁAáMnAæçAìÈAòuA÷Ž"AýMÎBsœB@B
+jB	ÚAB
+§BsíB@ÄB
+BÚpB§GB
+t
+B @óB#
+ÉB%Ú B(§vB+tMB.A#B1
+ùB3ÚÐB6§ŠB9t|B<ASB?)BAÚÿBD§ÖBGt­BJABMYBOÛ0BRšBUtÜBXA³B[B]Û_B`š6Bcu
+BfAâBi¹BkÛBnšeBqu<BtBBwèByÛ¿B|šB|ÃØ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A»;Ab²Aü_A£
+A©/¹A®ÉfAŽcA¹ü¿A¿kAÅ0AÊÉÅAÐcqAÕý
+AÛËAá0xAæÊ%AìcÒAñý~A÷+Aý0×BeBB2BþïB	ËÅB
+BerB2HBÿBËõBËB
+e¡B 2xB"ÿNB%Ì%B(ûB+eÑB.2šB0ÿ~B3ÌTB6+B9fB<2×B>ÿ®BAÌ
+BD[BGf1BJ3BLÿÞBOÌŽBRBUfaBX37B[ B]ÌäB`ºBcfBf3gBi =BkÍBnêBqfÀBt3Bw mByÍCB|B|µ]¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AjëAbA¬AEŒAßiA£yA©ÂA®¬oAŽFA¹ßÈA¿yuAÅ!AÊ¬ÎAÐF{AÕà(AÛyÕAáAæ­.AìFÛAñàA÷z4AýáBVÇB#BðtB	œJB
+ BV÷B#ÍBð£BœyBPB
+W&B #ýB"ðÓB%œ©B(B+WVB.$,B0ñB3œÙB6¯B9WB<$]B>ñ3BAŸ	BDàBGW¶BJ$BLñcBOŸ9BRBUWæBX$ŒBZñB]ŸiB`?BcXBf$ìBhñÂBkŸBnoBqXEBt%BvñòByŸÈB|B|Šâ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Ax58AÂA[¿AõlAA(ÆAÂrA£\AšõËA®xAŽ)%A¹ÂÑA¿\~AÄö+AÊØAÐ)
+AÕÃ2AÛ\ÞAàöAæ7Aì)äAñÃA÷]=AüöêBHLB"BáøB	®ÏB
+{¥BH{BQBâ(B®þB{ÕB
+H«B B"âXB%¯.B(|B+HÛB.±B0âB3¯^B6|5B9I
+B<áB>âžBA¯BD|dBGI;BJBLâçBO¯ŸBR|BUIjBXABZãB]¯íB`|ÄBcIBfpBhãGBk°
+Bn|óBqIÊBt BvãvBy°MB|}$B|g¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AaAlãAxßA¥
+A>ÉAØvAr"A
+ÏA¥{A£?(AšØÕA®rAŽ
+.A¹¥ÛA¿?AÄÙ5AÊrâAÐ
+AÕŠ;AÛ?çAàÙAæsAAì
+íAñŠA÷@GAüÙóB9ÐB§BÓ}B	 SB
+m)B: BÖBÓ­B BmYB
+:0B B"ÓÜB% ³B(mB+:_B.6B0Ô
+B3 ãB6m¹B9:B<fB>Ô<BA¡BDméBG:¿BJBLÔlBO¡BBRnBU:ïBXÅBZÔB]¡rB`nHBc;BfõBhÔËBk¡¢BnnxBq;NBt%BvÔüBy¡ÒB|nšB|ì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AJóûAVBèAav@Al©AwÜñA&A!ÒA»AU+AîØA
+A£"1Aš»ÞA®UA³ï8A¹åA¿"AÄŒ>AÊUëAÏïAÕDAÛ"ñAàŒAæVJAëï÷Añ£A÷#QAüŒýB+UBø+BÅB	ØB
+^®B+
+Bø[BÅ1BB^ÞB
++ŽBøB"ÅaB%7B(_B++åB-ø»B0ÅB3hB6_>B9,B;øëB>ÅÁBABD_nBG,DBIùBLÅñBOÇBR_BU,tBWùJBZÆ B]÷B`_ÍBc,£BeùzBhÆPBk&Bn_ýBq,ÔBsùªBvÆByWB|`-B|{p¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A4S]A?¢JAJÕ¢AVûAa<SAlo¬Aw£Ak/AÛAA85AÑáAkA£;AšèA®8A³ÒBA¹kîA¿AÄGAÊ8ôAÏÒ¡AÕlMAÛúAà§Aæ9SAëÓAñl®A÷ZAü B
+ÙBé°B¶B	]B
+P3B
+	BéàB¶¶BBPcB
+
+9BêB"¶æB%œB(PB+
+iB-ê@B0·B3ìB6PÃB9
+B;êoB>·FBA
+BDPòBG
+ÉBIêBL·uBOLBRQ"BU
+øBWêÏBZ·¥B]{B`QRBc
+(BeêþBh·ÕBk¬BnQBq
+XBsë/BvžByÛB|Q²B|lõ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+²¿A)¬A45A?h]AJµAUÏAafAl5¿AwiAN8AçåAA>AŽëANA¢èEAšòA®A³µKA¹N÷AŸè€AÄQAÊýAÏµªAÕOWAÚéAà±Aæ
+^Aë¶
+AñO·AöécAüB^BÛ5Bš
+B	táB
+AžBBÛdBš;BuBAçB
+ŸBÛB"škB%uAB(BB+îB-ÛÄB0šB3uqB6BGB9
+B;ÛôB>šÊBAu¡BDBwBGMBIÜ$BLšúBOuÐBRB§BU}BWÜSBZ©*B]v B`BÖBc­BeÜBh©ZBkv0BnCBqÝBsÜ³Bv©Byv`B|C6B|^z¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A!AaA
+fA(Ç¿A3ûA?.pAJaÈAU!A`ÈyAkûÑAw/*A1BAÊîAdAþHAõA1¢A¢ËNAšdûA­þ§A³TA¹2AŸË­AÄeZAÉÿAÏ³AÕ2aAÚÌAàeºAåÿgAëAñ2ÀAöÌmAüfB ÿãBÌ¹BB	ffB
+3<B BÌéB¿BfB3mB
+ CBÍB"ðB%fÆB(3B+ sB-ÍIB0B3föB63ÌB9 ¢B;ÍyB>OBAg%BD3üBG ÒBIÍšBLBOgUBR4+BUBWÍØBZ®B]g
+B`4\Bc2BeÎBhßBkgµBn4BqbBsÎ8BvBygåB|4»B|Oÿ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @àã@÷ÞAóÇA' A
+ZxA(ÑA3Á)A>ôAJ'ÚAU[2A`AkÁäAvõ<AJA­÷AG€AáQAzýAªA¢®VAšHA­á°A³{\A¹	AŸ®¶AÄHbAÉâAÏ{œAÕiAÚ¯AàHÂAåâoAë|
+AñÈAö¯uAüI"B ñgBŸ=BB	WêB
+$ÀBñBŸmBDBXB$ðB
+ñÇBŸB"sB%XJB(% B*ñöB-ŸÍB0£B3XyB6%PB8ò&B;ŸüB>ÓBAX©BD%BFòVBI¿,BLBOXÙBR%¯BTò
+BW¿\BZ3B]Y	B`%ßBbò¶Be¿BhbBkY9Bn&BpòåBs¿ŒBvByYiB|&?B|A¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @³¡È@Ê?¢@àŠS@÷
+A¹ÚAí3A
+ A(SäA3<A>ºAIííAU!FA`TAköAv»OA÷TAA*­AÄZA^A÷³A¢`Aš+
+A­Ä¹A³^fAžøAŸÀAÄ+mAÉÅAÏ^ÆAÔørAÚAà+ÌAåÅxAë_%AðøÒAö~Aü,+B âëB¯ÂB|B	InB
+EBã
+B¯òB|ÈBIBuB
+ãKB°"B"|øB%IÎB(¥B*ã{B-°QB0}(B3IþB6ÕB8ã«B;°B>}WBAJ.BDBFãÚBI°±BL}BOJ]BR4BTä
+BW°áBZ}·B]JB`dBbä:Be±Bh}çBkJœBnBpäjBs±ABv~ByJíB|ÄB|3¿  ¿  ¿  ¿  ¿  ¿  @`@þe@³e@ÉËÇ@à2x@ö)AíA³FA
+æA(öA3MOA>šAIŽ ATçXA`±AkN	AvbAÚ]At
+A
+·A§cAAAÚŒA¢tiAšA­§ÂA³ApAžÛ
+AŸtÉAÄvAÉš"AÏAÏAÔÛ|AÚu(AàÕAåšAëB.AðÛÛAöuAü5B ÔpB¡FBn
+B	:ôB
+ÊBÔ B¡wBnMB;#BúB
+ÔÐB¡ŠB"n}B%;SB()B*Õ B-¡ÖB0n­B3;B6YB8Õ/B;¢B>nÜBA;²BDBFÕ_BI¢5BLo
+BO;ãBR¹BTÕBW¢fBZo<B]<B`éBbÕ¿Be¢BholBk<BBn	BpÕïBs¢ÅBvoBy<rB|	HB|$¿  ¿  ¿  ¿  @2>@_zS@#Ú@@²ñ<@ÉWì@ßŸ@ö%OAF AyXA
+¬±A'à
+A3bA>FºAIzAT­kA_àÄAk
+AvGuAœgAWAðÀAlA$AœÆA¢WrA§ñ A­ÍA³$yAžŸ&AŸWÒAÃñAÉ,AÏ$ØAÔŸ
+AÚX2AßñÞAåAë%9AðŸåAöXAûò>B ÅõBÌB_¢B	,xB
+ùOBÆ%BûB_ÒB,šBù~B
+ÆUB+B"`B%,ØB'ù®B*Æ
+B-[B0`1B3-B5ùÞB8ÆŽB;B>`aBA-7BCú
+BFÆäBI»BL`BO-gBQú>BTÇBWêBZ`ÁB]-B_úmBbÇDBeBh`ñBk-ÇBmúBpÇtBsJBva By-÷B{úÍB|¿  ¿  ?¯xI@÷Ú@1Å<@^@
+° @°@²}b@Èä@ßJÃ@õ±tA
+A?lA
+rÄA'Š
+A2ÙuA>
+ÍAI@&ATs~A_Š×AjÚ/Av
+A pA:
+AÓÉAmvA"A ÐA¢:}A§Ô)A­mÖA³Až¡/AŸ:ÜAÃÔAÉn5AÏâAÔ¡AÚ;;AßÔéAånAëBAð¡îAö;AûÕHB ·zBPBQ'B	
+ýB
+êÓB·ªBBQVB
+-BëB
+·ÙB°B"QB%
+]B'ë3B*ž	B-ßB0Q¶B3
+B5ëbB8ž9B;
+B>QåBA
+ŒBCëBFžiBI
+?BLRBO
+ìBQëÂBTžBW
+oBZREB]
+B_ëòBbžÉBe
+BhRuBkLBmì"BpžøBs
+ÏBvR¥By{B{ìQB|?!G®?)Õ?®
+@$@0Ý@]ªé@
+<%@¢×@²	@Èp8@ÞÖé@õ=AÒ&A~A
+8×A'l/A2A=ÒàAI9AT9A_léAj BAuÓAyA
+&A¶ÒAPAê-AÙA¢
+A§·2A­PßA²êAž8AŸ
+åAÃ·AÉQ>AÎêëAÔAÚ
+EAß·òAåQAêëKAðøAö
+€AûžQB šÿBuÕBB«B	B
+ÜXB©.BvBBÛB±BÜB
+©^Bv5B"C
+B%áB'Ü·B*©B-vdB0C:B3B5ÜçB8©œB;vB>CkBAABCÝBF©îBIvÄBLCBOqBQÝGBTª
+BWvôBZCÊB]¡B_ÝwBbªMBew$BhCúBkÐBmÝ§Bpª}BswSBvD)By B{ÝÖ¿  ?b(?&6¬?¬¶@(p@/õÒ@\Ã4@ÈK@.ü@±­@Çü^@Þc@ôÉÀA9AËAþêA'2BA2eA=óAHÌKASÿ€A_2üAjfUAu­AfA 0AÝA3AÍ6AfâA¢ A§<A­3èA²ÍAžgBAŸ îAÃAÉ4IAÎÍõAÔg¢AÚNAßûAå4šAêÎTAðhAö®AûZB BgZB40B	B
+ÍÝB³BgB4`B6BÎ
+B
+ãBg¹B"4B%fB'Î<B*B-géB04¿B3B5ÎlB8CB;hB>4ïBAÆBCÎBFrBIhIBL5BOõBQÎÌBT¢BWhyBZ5OB]%B_ÎüBbÒBehšBh5BkUBmÏ+BpBshØBv5®By	j¿  ¿  ?ÃV?"×?ªæ°@@º@/
+@[Û~@Tp@»!@±!Ò@Ç@Ýï3@ôUäA^KA£AÄüA&øTA2+¬A=_AH]ASÅ¶A^ùAj,gAu_¿AIA
+ã9A|æAA°?AIìA¡ãA§}EA­òA²°AžJKAœãùAÃ}¥AÉRAÎ°þAÔJ«AÙäXAß~Aå±Aê±^AðK
+Aõä·Aû~eB BXÞB%µBòB
+¿aB8BYB%åBò»B¿B
+gBY>B"&B$òêB'¿ÁB*B-YmB0&DB2óB5¿ñB8ÇB;YB>&tB@óJBCÀ!BF÷BIYÍBL&€BNózBQÀQBT'BWYýBZ&ÔB\óªB_ÀBbWBeZ-Bh'BjóÙBmÀ°BpBsaB¿  ¿  ¿  ¿  ?$?
+ù?©F@Y@.&h@ZóÊ@à@GG@°­÷@Çš@Ý{Y@óâ
+A$^AW¶AA&ŸgA1ñ¿A=%AHXpASÉA^¿!AiòyAu%ÒA,A
+ÆCA_ïAùAHA,õA¡Æ¢A§`NA¬ùûA²©Až-UAœÇAÃ`¯AÈú[AÎAÔ-ŽAÙÇaAßaAäúºAêgAð.AõÇÁAûanB }BJcB9BäB
+°æB}œBJBiBä?B±B
+}ìBJÂB"B$äoB'±EB*~
+B-JóB0ÉB2äB5±vB8~LB;K"B>ùB@äÏBC±¥BF~|BIKRBL)BNäÿBQ±ÕBT~¬BWKBZXB\å/B_²Bb~ÛBeK±BhBjå^Bm¹¿  ¿  ¿  ¿  ¿  ¿  ?
+²?Z1?§GÝ@ qQ@->³@Z
+@l»@Ól@°:
+@Æ Î@Ý@ón0AêpA
+ÉAQ!A&zA1·ÒA<ë+AH
+ASQÛA^
+4AižAtëåAA
+©LABøAÜ¥AvRAþA¡©«A§CYA¬ÝA²v²Až_Aœª
+AÃCžAÈÝdAÎwAÔŸAÙªjAßDAäÝÅAêwqAð
+AõªÊAûDwB oB;èBŸBÕB
+¢kBoAB<BîBÕÄB¢B
+oqB<GB"	
+B$ÕôB'¢ËB*o¡B-<wB0	NB2Ö$B5¢úB8oÑB;<§B>	}B@ÖTBC£*BFpBI<×BL	­BNÖBQ£ZBTp0BW=BZ	ÝB\Ö³B_£Bbp`Be=6Bhò¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?æá?»X?¥xp?ÿ5@,Vý@Y$_@øà@_@¯ÆC@Æ,ó@Ü€@òúTA°AãÜA4A&JA1}åA<±=AGäASïA^KGAi~At±øAåQA
+UA&A¿®AY[Aó	A¡µA§&bA¬ÀA²Y»A·óhAœAÃ&ÁAÈÀnAÎZAÓóÇAÙuAß'!AäÀÎAêZzAïô'AõÔAû'B `B-mBúCBÇB
+ïB`ÆB-BúrBÇIBB
+`õB-ÌB!ú£B$ÇyB'OB*a&B--üB/úÒB2Ç©B5B8aUB;.,B=ûB@ÇÙBC¯BFa
+BI.\BKû2BNÈBQßBTaµBW.BYûaB\È8B_BbhÊ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+H?
+?£©?ýCÌ@+oI@X<ª@
+@ë·@¯Rh@Å¹@ÜÊ@òzAvA©ïAÝGA&A1CøA<wQAGª©ARÞA^ZAiD²Atx
+A«dA
+o^A	
+A¢¹A<eAÖA¡o¿A§	kA¬£A²<ÄA·ÖqAœp
+AÃ	ÊAÈ£wAÎ=%AÓÖÑAÙp~Aß
+*Aä£×Aê=Aï×0AõpÝAû
+B RB
+ñBëÇBžB
+
+tBRJB!Bë÷BžÍB
+€B
+R{BQB!ì'B$žþB'
+ÔB*RªB-B/ìWB2¹-B5B8RÚB;±B=ìB@¹]BC4BFS
+BIàBKì·BN¹BQcBTS9BW BYìæB\À¢¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?	©>?}¬?¡Ù?ût_@*@WTô@+@wÛ@®Þ@ÅE=@Û«î@òA<šAp A£YA%Ö²A1
+
+A<=bAGp»AR€A]×lAi
+ÄAt>
+AquA
+RhAìA
+ÁAnA¹A¡RÇAŠìsA¬ A²ÍA·¹yAœS&AÂìÔAÈAÎ -AÓ¹ÚAÙSAÞí3AäßAê Aïº9AõSåAúíB CBvBÝLBª"B
+vùBCÏB¥BÝ|BªSBw)B
+CÿBÖB!Ý¬B$ªB'wYB*D/B-B/ÝÜB2ª²B5wB8D_B;5B=Þ
+B@ªâBCwžBFDBIeBKÞ;BN«BQwèBTDŸBWz¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+k?
+ÞÚ? 
+2?ù€ö@)Þ@Vm@@Q@@®j²@ÄÑc@Û8@ñÅA»A6AilA%ÄA0Ð
+A<uAG6ÎARj&A]AhÐ×At/A7A
+5qAÏ
+AhÊAwA#A¡5ÐAŠÏ}A¬i)A²ÖA·Aœ60AÂÏÝAÈiAÎ6AÓãAÙ6AÞÐ<AäiéAêAïBAõ6ïAúÐB 5$BúBÎÑB§B
+h}B5TB+BÏB×Bh®B
+5BZB!Ï1B$B'hÝB*5ŽB-B/ÏaB27B5i
+B85äB;ºB=ÏB@gBCi=BF6BIéBKÏÀBNBQpR¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?k?	@?:Å?÷Õ@(ž(@U
+@)u@&@­ö×@Ä]@ÚÄ9@ñ*êAÈÎAü&A/A%b×A00A;ÉAFüáAR09A]cAhêAsÊBA~ýA
+zA²'AKÓAåA-A¡ÙAŠ²A¬L4A±åàA·Aœ:AÂ²æAÈLAÍæ?AÓìAÙAÞ³EAäLòAéæAïLAõùAú³¥B &©BóBÀUB,B
+ZB&ÙBó¯BÀB\BZ2B
+'	B
+óßB!ÀµB$B'ZbB*'9B,ôB/ÀåB2ŒB5ZB8'hB:ô?B=ÁB@ëBCZÁBF'BHônBKÈ*¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ý?¡/?k\?ö!@'Ðs@TÕ@µ@
+L@­ý@Ãé®@ÚP_@ð·AáAÂ9AõA%(êA0\CA;AFÂóAQöLA])€Ah\ýAsUA~Ã®AûA0A.ÝAÈAb6A ûäAŠA¬/=A±ÈêA·bAŒüCAÂïAÈ/AÍÉIAÓbõAØü¢AÞOAä/üAéÉ©AïcUAôýAú¯B -BåB±ÛB~±B
+KB^Bå4B²
+B~áBK·B
+B
+ådB!²:B$B'KçB*œB,åB/²jB2@B5LB8íB:åÃB=²B@pBCLFBF ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ö[ë?U?ï?ô6Ž@&èœ@S¶
+@AÀ@šq@­"@ÃuÓ@ÙÜ@ðC4ATóAKA»€A$îüA0"TA;U­AFAQŒ^A\ï¶Ah#AsVgA~ÀAÞAx9AæA«AE@A ÞíAŠxA¬FA±«óA·EAŒßLAÂxùAÈ¥AÍ¬RAÓEÿAØß¬AÞyYAäAé¬²AïF_Aôà
+AúyžB 	³BÖB£_Bp6B
+=
+B	âBÖ¹B£BpeB=<B
+
+B
+ÖéB!£¿B$pB'=lB*
+BB,×B/£ïB2pÅB5=B8
+qB:×HB=€
+B@wÚ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ï
+I>üÇ?Ì?ògK@&@RÎj@Ì@4@¬G@Ãù@Ùh©@ïÏZAAN^A¶A$µA/ègA;ÀAFOAQqA\µÉAgé!As
+zA~OÓAÁA[DAôðAA(JA ÁöAŠ[£A«õOA±üA·(©AŒÂUAÂ\AÇõ¯AÍ\AÓ)	AØÂ¶AÞ\bAãöAé»Aï)hAôÃAú\ÁAÿönBÈBäBaºB
+.B
+ûgBÈ=BBaêB.ÁBûB
+ÈmB!DB$bB'.ðB)ûÇB,ÈB/sB2bIB5/ B7ûöB:Ï²¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >çà¥>õc?ý
+?ðâ@%T@Qæ¶@~Ž@Àœ@¬'m@Â
+@ØôÏ@ï[AáAqAGÉA${"A/®zA:áÓAF+AQHA\{ÜAg¯5ArâA~çA€ A>MA×úAqŠA
+SA €ÿAŠ>¬A«ØYA±rA·
+²AŒ¥_AÂ?
+AÇØ¹AÍrfAÓ
+AØ¥¿AÞ?kAãÙAérÅAï
+qAôŠ
+Aú?ËAÿÙxB¹BiBS?B
+ B
+ììB¹ÂBBSoB EBí
+B
+¹òB!ÈB$SB' uB)íKB,º!B/øB2SÎB5'¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >à£>îK ?-¬?îÈq@$1@Pþý@}Ì_@Là@«³@ÂB@Øó@îç€A§*A
+ÚA
+ÛA$A4A/tA:§äAEÛ=AQA\AîAguFAršA}ÛøA©A!UA»AT®Aî[A AŠ!ŽA«»aA±UA¶î»AŒhAÂ"AÇ»ÁAÍUnAÒïAØÇAÞ"tAãŒ AéUÍAîïzAô&Aú"ÔAÿŒB«BwìBDÃB
+B
+ÞpB«FBx
+BDóBÉBÞB
+«vB!xLB$E"B'øB)ÞÏB,«¥B/a¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Ùe]>ç
+û?^C?ìù@#Iç@PH@|äª@Ù@«?·@ÁŠh@Ø
+@îsÊAm=A
+ AÓîA$FA/:A:møAE¡PAPÔšA\Ag;YArn²A}¢
+Aj²A^A
+A7žAÑdA kAŠŸA«kA±8A¶ÑÅAŒkqAÂ
+AÇÊAÍ8wAÒÒ$AØkÐAÞ}Aã*Aé8ÖAîÒAôl1AúÝAÿBBiqB6HB
+
+B
+ÏôBËBi¡B6wBNBÐ$B
+úB!iÐB$6§B'}B)×9¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Ò'»>ßÐY?Û?ë)@"b3@O/@{üö@e,@ªËÝ@Á2@×?@íÿïA3PA
+fšAA#ÍZA/ ²A:4
+AEgcAP»A[ÎAglAr4ÅA}h
+AM»AçhAAÁAŽnA NA¥çÈA«uA±!A¶ŽÎAŒNzAÁè'AÇÔAÍAÒµ-AØNÚAÝèAã4AéáAîµAôO:AùèæAÿB BZöB'ÌB
+ô£B
+ÁyBOB[&B'üBôÒBÁšB
+B![UB$/¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Êê>Øµ?¿r?éZ6@!z~@NGà@{A@ñR@ªX@ÀŸ³@×%d@íAùcA
+,ŒA`A#lA.ÆÅA9ú
+AE-vAP`ÎA['AfÇAqú×A}./A0ÄAÊqAd
+AýËAxA 1%A¥ÊÑA«d~A°þ*A¶×AŒ1AÁË0AÇdÝAÌþAÒ7AØ1äAÝËAãe=AèþêAîAô2CAùËðAÿeB€BL{BQB
+æ'B
+²þBÔBLªBBæWB³-B
+é¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Ã¬s>ÑTñ?ð?çÆ@ Å@M`'@z-@}u@©ä&@ÀJ×@Ö±@í9A¿uA
+òÍA&&A#Y~A.×A9À/ADóAP&àA[Z8AfAqÀéA|ôBAÎA­{AG(AàÕAzA .A¥­ÚA«GA°á4A¶zàAŒAÁ®:AÇGçAÌáAÒ{AAØíAÝ®AãHFAèáóAî{ AôLAù®ùAÿH¥Bq)B=ÿB
+ÖB
+×¬B
+€BqXB>/B
+BÞÁ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ŒnÐ>ÊN? ?å»\@«@Lxr@yEÔ@	@©pL@¿Öý@Ö=®@ì€_A
+A
+žàAì9A#A.RêA9BAD¹AOìòA[ KAfS€AqüA|ºUAöØA
+A*1AÃÞA]A÷7A¥äA«*A°Ä=A¶]êA»÷AÁDAÇ*ñAÌÄAÒ^JA×÷öAÝ£Aã+PAèÄüAî^©AóøVAùAÿ+¯Bb®B/BüZB
+É0B
+BbÝB6¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >µ1,>ÂÙª?Q/?ãëó@
+Ã\@KŸ@x^ @Á@šür@¿c#@ÕÉÔ@ì0
+AKA
+~óA²LA"å€A.üA9LTAD­AO³AZæ^Af·AqMA|iAÙáAsA
+:AŠçA@AÚ@A¥síA«
+A°§GA¶@ôA»Ú¡AÁtMAÇ
+úAÌ§ŠAÒASA×Û AÝt¬AãYAèšAîA²AóÛ`Aùu
+Aÿ·BT2B!BíßB
+ºµB
+q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >­ó>»?Æ?â
+@
+Ûš@J©
+@wvl@!ç@š@ŸïI@ÕUù@ëŒ«A®A
+EAx^A"«¶A-ßA9hADEÀAOyAZ¬qAeßÉAq"A|F|AŒêAVAðDAðA#AœJA¥V÷Aªð€A°QA¶#ýA»œªAÁWVAÆñAÌ°AÒ$\A×Ÿ	AÝW¶AâñbAèAî$œAóŸiAùXAþñÁBE·BBæI¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Šµå>Ž^C?²U?àM@
+óï@IÁQ@v³@®
+@š»@Ÿ{m@Ôâ
+@ëHÎA ×¿A
+
+A>pA"qÉA-¥!A8ØzAD
+ÒAO?*AZrAe¥ÜApÙ4A|
+AóA9AÓLAlùAŠA SA¥: AªÓ¬A°mYA¶A» ²AÁ:_AÆÔ
+AÌmžAÒeA×¡AÝ:¿AâÔlAènAîÅAó¡rAù;
+AþÔËB>!¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >xA>­ À?âô?Þ}¹@
+
+?@HÙ¡@u§@:3@§ ã@Ÿ@ÔnD@êÔöA ÓA
+Ñ,AA"7ÝA-k5A8ACÑæAO?AZ8AekïApGA{Ò¡AýA
+ªA¶WAPAé±A]A¥
+
+Aª¶¶A°PcAµêA»ŒAÁ
+iAÆ·AÌPÂAÑêpA×
+AÝ
+ÉAâ·vAèQ#AíêÏAó|Aù+ó¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >:>¥ã??Ü®P@$@Gñì@t¿N@ÆX@§-@œº@Óúk@êaA cæA
+?AÊA!ýïA-1HA8d¡ACùANËQAYþ©Ae2Ape[A{ŽAfAÿŽAaA3
+AÌºAffA¥ AªÀA°3lAµÍA»fÆAÁ rAÆ AÌ3ÍAÑÍyA×g&AÝ ÓAâAè4,AíÛ£¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >üú>¥x?D"?ÚÞç@<Ö@G
+8@s×@R~@Š¹/@œß@Ó@éíAA )ùA
+]QAªA!ÄA,÷[A8*³AC^
+ANdAYÄœAdøAp+nA{^ÇAIAâœA|jAA¯ÃAIpA€ã
+Aª|ÉA°vAµ°"A»IÐAÀã}AÆ})AÌÖAÑ°A×J/AÜãÜAâS¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >¿W>h?~é?Ù@U*@F"@rïí@Þ§@ŠEX@Œ¬	@Óº@éyk@ÿà
+A
+#gAV¿A!A,œpA7ðÈAC$!ANWyAYÒAdŸ*AoñA{$ÜA,AÅÈA_tAù!AÍA,zA€Æ'Aª_ÓA¯ùAµ.A»,ÚAÀÆAÆ`4AËùàAÑA×;¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >³>*q?{JÂ?×@%@mv@E:×@r9@jÍ@¥Ñ~@Œ8/@Òà@é@ÿlBA
+éyA
+ÒA!P*A,A7¶ÛABê4AN
+AYPäAd=Ao·AzêïA$AšÑAB}AÜ*Au×AA€©1AªBÞA¯ÜAµv7A»äAÀ©AÆC=AËêŽ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >v
+>ìÍ?w«ð?Õpœ@
+Á@DS#@q @öó@¥]€@»ÄU@Ò+@è¶@þøgA
+¯AâåA!=A,IA7|îAB°FAMãAYøAdJPAo}šAz±Aò-AÚA%A¿3AXáAòA€:Aª%çA¯¿AµY@AºòíAÀd¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >h
+×>¯j?t
+>?Ó¡d@@Ckv@p8Ø@
+@€éÎ@»P~@Ñ·/@è
+à@þA
+u¡AšúA ÜRA,ªA7CABv\AM©ŽAXÝ
+AdeAoCœAzwAÕ8AnäAA¢?A;ëAÕA€oEAªñA¯¢AµJ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Y>tã?pnm?ÑÑû@¶`@BÂ@oQ$@C@€uó@ºÜ¥@ÑCU@çª@þ·A
+;ŽAo
+A ¢eA+ÕŸA7	AB<nAMoÇAX£AcÖxAo	ÐAz=)AžBAQïAëA
+HA
+õAž¡A€RNA©ùÅ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >KJ>fhÆ?lÏ»?Ð¢@ÎŽ@A@niw@m@€
+@ºhÎ@ÐÏ@ç60@ýáA
+ÉA5"A hzA+ÒA6Ï+ABAM5ÜAXi4AcAnÏåAz?ALA4ùAÎŠAhRAÿA©v¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ><>Wí?i0è?Î39@ç @@Ža@mÃ@'@£C@¹ôô@Ð[¥@æÂV@ý)A	ÇÜAû4A .A+aåA6>AAÈALûïAX/GAcbAnøAyÉRA~VAA±¯AY&¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >.»>Ir7?e?ÌcÐ@ÿK@?Ì­@l@³ž@£i@¹@ÏçË@æN|@üµ-A	ïAÁGAô A+'øA6[QAA©ALÂAWõZAc(³An\
+AydAa_AÖ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >€s>:÷p?aóe?Êx@@>å @k²b@?â@¢Š@¹
+D@Ïsõ@åÚ¥@üAVA	TA\AºµA*î
+A6!eAATŸALAW»oAbîÇAn" Ayq¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >)/>,|,?^T?ÈÅ@/ê@=ýL@jÊ­@Ì@¢2¹@žj@Ï @åfË@ûÍ}A	AMoAÇA*Ž A5çyAAÑALN)AWAbÐo¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >­é>
+ æ?ZµÃ?ÆõŠ@H5@=@iâù@X.@¡Ÿß@ž%@Î@@äòò@ûY¢Aà)AAFÛA*z3A5­A@àäAL/Ñ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =èeE>?W?Å&M@`@<-ë@hûM@äW@¡K@·±º@Îj@ä@úåÌAŠ?AÙA
+ïA*@HA55¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =Ën¹>
+Ù?Sx@?ÃVä@xÕ@;F7@h@p~@ ×.@·=ß@Í€@ä
+A@úqòAlQAªA
+î¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =®x1=å *?OÙ?Á@
+(@:^@g+ì@ü§@ cX@¶Ê	@Í0º@ãk@ùþ
+AMû¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =€=È)?L:Œ?¿ž#@
+©t@9vÖ@fD8@Í@ï~@¶V/@ÌŒà@ãZº¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =i.=«3?Hë?œèº@
+ÁÀ@8"@e\@ó@{€@¶~¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =/)==?Dý9?Œa@
+Ú@7§u@dt×@ØF¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  <êwô=bì?A^h?ºIù@	ò_@7.¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  <m;Š=( Ü?=¿?¹W6¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  9°ç\=
+J¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ?!G®?Ð£×@(Qì@hQì@(ö@Ž(ö@Ô(ö@ô(öA
+{A{A*{A:{AJ{AZ{Aj{Az{A
+
+=A
+=A
+=A
+=A¥
+=A­
+=Aµ
+=Aœ
+=AÅ
+=AÍ
+=AÕ
+=AÝ
+=Aå
+=Aí
+=Aõ
+=Aý
+=B
+B
+B
+
+B
+B
+B
+B
+B
+
+B"
+B&
+B*
+B.
+B2
+B6
+B:
+B>
+BB
+BF
+BJ
+BN
+BR
+BV
+BZ
+B^
+Bb
+Bf
+Bj
+Bn
+Br
+Bv
+Bz
+B~
+?
+žR?Ï\)@'®@g®@×
+@³×
+@Ó×
+@ó×
+A	ë
+Aë
+A)ë
+A9ë
+AIë
+AYë
+Aië
+Ayë
+AõÃAõÃAõÃAõÃA€õÃA¬õÃAŽõÃAŒõÃAÄõÃAÌõÃAÔõÃAÜõÃAäõÃAìõÃAôõÃAüõÃBzáBzáB
+záBzáBzáBzáBzáB
+záB"záB&záB*záB.záB2záB6záB:záB>záBBzáBFzáBJzáBNzáBRzáBVzáBZzáB^záBbzáBfzáBjzáBnzáBrzáBvzáBzzáB~zá?
+(ö?Î{@'
+>@g
+>@
+@³
+@Ó
+@ó
+A	ÂAÂA)ÂA9ÂAIÂAYÂAiÂAyÂAáHAáHAáHAáHA€áHA¬áHAŽáHAŒáHAÄáHAÌáHAÔáHAÜáHAäáHAìáHAôáHAüáHBp€Bp€B
+p€Bp€Bp€Bp€Bp€B
+p€B"p€B&p€B*p€B.p€B2p€B6p€B:p€B>p€BBp€BFp€BJp€BNp€BRp€BVp€BZp€B^p€Bbp€Bfp€Bjp€Bnp€Brp€Bvp€Bzp€B~p€??ÌÌÍ@&ff@fff@33@³33@Ó33@ó33A	AA)A9AIAYAiAyAÌÍAÌÍAÌÍAÌÍA€ÌÍA¬ÌÍAŽÌÍAŒÌÍAÄÌÍAÌÌÍAÔÌÍAÜÌÍAäÌÍAìÌÍAôÌÍAüÌÍBffBffB
+ffBffBffBffBffB
+ffB"ffB&ffB*ffB.ffB2ffB6ffB:ffB>ffBBffBFffBJffBNffBRffBVffBZffB^ffBbffBfffBjffBnffBrffBvffBzffB~ff?
+=?Ë
+
+@%Â@eÂ@áH@²áH@ÒáH@òáHA	p€Ap€A)p€A9p€AIp€AYp€Aip€Ayp€AžRAžRAžRAžRA€žRA¬žRAŽžRAŒžRAÄžRAÌžRAÔžRAÜžRAäžRAìžRAôžRAüžRB\)B\)B
+\)B\)B\)B\)B\)B
+\)B"\)B&\)B*\)B.\)B2\)B6\)B:\)B>\)BB\)BF\)BJ\)BN\)BR\)BV\)BZ\)B^\)Bb\)Bf\)Bj\)Bn\)Br\)Bv\)Bz\)B~\)?zá?Ê=p@%
+ž@e
+ž@\@²\@Ò\@ò\A	G®AG®A)G®A9G®AIG®AYG®AiG®AyG®A£×A£×A£×A£×A€£×A¬£×AŽ£×AŒ£×AÄ£×AÌ£×AÔ£×AÜ£×Aä£×Aì£×Aô£×Aü£×BQìBQìB
+QìBQìBQìBQìBQìB
+QìB"QìB&QìB*QìB.QìB2QìB6QìB:QìB>QìBBQìBFQìBJQìBNQìBRQìBVQìBZQìB^QìBbQìBfQìBjQìBnQìBrQìBvQìBzQìB~Qì?ë
+?ÈõÂ@$zá@dzá@=q@²=q@Ò=q@ò=qA	
+žA
+žA)
+žA9
+žAI
+žAY
+žAi
+žAy
+žA\A\A\A\A€\A¬\AŽ\AŒ\AÄ\AÌ\AÔ\AÜ\Aä\Aì\Aô\Aü\BG®BG®B
+G®BG®BG®BG®BG®B
+G®B"G®B&G®B*G®B.G®B2G®B6G®B:G®B>G®BBG®BFG®BJG®BNG®BRG®BVG®BZG®B^G®BbG®BfG®BjG®BnG®BrG®BvG®BzG®B~G®?\)?Ç®@#×
+@c×
+@ë
+@±ë
+@Ñë
+@ñë
+AõÃAõÃA(õÃA8õÃAHõÃAXõÃAhõÃAxõÃAzáAzáAzáAzáA€záA¬záAŽzáAŒzáAÄzáAÌzáAÔzáAÜzáAäzáAìzáAôzáAüzáB=qB=qB
+=qB=qB=qB=qB=qB
+=qB"=qB&=qB*=qB.=qB2=qB6=qB:=qB>=qBB=qBF=qBJ=qBN=qBR=qBV=qBZ=qB^=qBb=qBf=qBj=qBn=qBr=qBv=qBz=qB~=q?
+ÌÍ?Æff@#33@c33@@±@Ñ@ñAÌÍAÌÍA(ÌÍA8ÌÍAHÌÍAXÌÍAhÌÍAxÌÍAffAffAffAffA€ffA¬ffAŽffAŒffAÄffAÌffAÔffAÜffAäffAìffAôffAüffB33B33B
+33B33B33B33B33B
+33B"33B&33B*33B.33B233B633B:33B>33BB33BF33BJ33BN33BR33BV33BZ33B^33Bb33Bf33Bj33Bn33Br33Bv33Bz33B~33?
+=q?Å
+ž@"\@b\@G®@±G®@ÑG®@ñG®A£×A£×A(£×A8£×AH£×AX£×Ah£×Ax£×AQìAQìAQìAQìA€QìA¬QìAŽQìAŒQìAÄQìAÌQìAÔQìAÜQìAäQìAìQìAôQìAüQìB(öB(öB
+(öB(öB(öB(öB(öB
+(öB"(öB&(öB*(öB.(öB2(öB6(öB:(öB>(öBB(öBF(öBJ(öBN(öBR(öBV(öBZ(öB^(öBb(öBf(öBj(öBn(öBr(öBv(öBz(öB~(ö?®?Ã×
+@!ë
+@aë
+@õÂ@°õÂ@ÐõÂ@ðõÂAzáAzáA(záA8záAHzáAXzáAhzáAxzáA=qA=qA=qA=qA€=qA¬=qAŽ=qAŒ=qAÄ=qAÌ=qAÔ=qAÜ=qAä=qAì=qAô=qAü=qB
+žB
+žB
+
+žB
+žB
+žB
+žB
+žB
+
+žB"
+žB&
+žB*
+žB.
+žB2
+žB6
+žB:
+žB>
+žBB
+žBF
+žBJ
+žBN
+žBR
+žBV
+žBZ
+žB^
+žBb
+žBf
+žBj
+žBn
+žBr
+žBv
+žBz
+žB~
+ž?
+ž?Â\@!G®@aG®@£×@°£×@Ð£×@ð£×AQìAQìA(QìA8QìAHQìAXQìAhQìAxQìA(öA(öA(öA(öA€(öA¬(öAŽ(öAŒ(öAÄ(öAÌ(öAÔ(öAÜ(öAä(öAì(öAô(öAü(öB{B{B
+{B{B{B{B{B
+{B"{B&{B*{B.{B2{B6{B:{B>{BB{BF{BJ{BN{BR{BV{BZ{B^{Bb{Bf{Bj{Bn{Br{Bv{Bz{B~{?\?ÁG®@ £×@`£×@Qì@°Qì@ÐQì@ðQìA(öA(öA((öA8(öAH(öAX(öAh(öAx(öA{A{A{A{A€{A¬{AŽ{AŒ{AÄ{AÌ{AÔ{AÜ{Aä{Aì{Aô{Aü{B
+=B
+=B
+
+=B
+=B
+=B
+=B
+=B
+
+=B"
+=B&
+=B*
+=B.
+=B2
+=B6
+=B:
+=B>
+=BB
+=BF
+=BJ
+=BN
+=BR
+=BV
+=BZ
+=B^
+=Bb
+=Bf
+=Bj
+=Bn
+=Br
+=Bv
+=Bz
+=B~
+=?   ?À  @   @`  @  @°  @Ð  @ð  A  A  A(  A8  AH  AX  Ah  Ax  A  A  A  A  A€  A¬  AŽ  AŒ  AÄ  AÌ  AÔ  AÜ  Aä  Aì  Aô  Aü  B  B  B
+  B  B  B  B  B
+  B"  B&  B*  B.  B2  B6  B:  B>  BB  BF  BJ  BN  BR  BV  BZ  B^  Bb  Bf  Bj  Bn  Br  Bv  Bz  B~  >úáH?ŸžR@\)@_\)@®@¯®@Ï®@ï®A×
+A×
+A'×
+A7×
+AG×
+AW×
+Ag×
+Aw×
+Aë
+Aë
+Aë
+Aë
+A£ë
+A«ë
+A³ë
+A»ë
+AÃë
+AËë
+AÓë
+AÛë
+Aãë
+Aëë
+Aóë
+Aûë
+BõÃBõÃB	õÃB
+õÃBõÃBõÃBõÃB
+õÃB!õÃB%õÃB)õÃB-õÃB1õÃB5õÃB9õÃB=õÃBAõÃBEõÃBIõÃBMõÃBQõÃBUõÃBYõÃB]õÃBaõÃBeõÃBiõÃBmõÃBqõÃBuõÃByõÃB}õÃ>õÂ?œp€@
+žR@^žR@\)@¯\)@Ï\)@ï\)A®A®A'®A7®AG®AW®Ag®Aw®A×
+A×
+A×
+A×
+A£×
+A«×
+A³×
+A»×
+AÃ×
+AË×
+AÓ×
+AÛ×
+Aã×
+Aë×
+Aó×
+Aû×
+Bë
+Bë
+B	ë
+B
+ë
+Bë
+Bë
+Bë
+B
+ë
+B!ë
+B%ë
+B)ë
+B-ë
+B1ë
+B5ë
+B9ë
+B=ë
+BAë
+BEë
+BIë
+BMë
+BQë
+BUë
+BYë
+B]ë
+Baë
+Beë
+Bië
+Bmë
+Bqë
+Buë
+Byë
+B}ë
+>ð£×?Œ(ö@
+{@^{@
+=@¯
+=@Ï
+=@ï
+=A
+A
+A'
+A7
+AG
+AW
+Ag
+Aw
+AÂAÂAÂAÂA£ÂA«ÂA³ÂA»ÂAÃÂAËÂAÓÂAÛÂAãÂAëÂAóÂAûÂBáHBáHB	áHB
+áHBáHBáHBáHB
+áHB!áHB%áHB)áHB-áHB1áHB5áHB9áHB=áHBAáHBEáHBIáHBMáHBQáHBUáHBYáHB]áHBaáHBeáHBiáHBmáHBqáHBuáHByáHB}áH>ë
+?ºáH@
+p€@]p€@žR@®žR@ÎžR@îžRA\)A\)A'\)A7\)AG\)AW\)Ag\)Aw\)A®A®A®A®A£®A«®A³®A»®AÃ®AË®AÓ®AÛ®Aã®Aë®Aó®Aû®B×
+B×
+B	×
+B
+×
+B×
+B×
+B×
+B
+×
+B!×
+B%×
+B)×
+B-×
+B1×
+B5×
+B9×
+B=×
+BA×
+BE×
+BI×
+BM×
+BQ×
+BU×
+BY×
+B]×
+Ba×
+Be×
+Bi×
+Bm×
+Bq×
+Bu×
+By×
+B}×
+>æff?¹@
+ÌÍ@\ÌÍ@ff@®ff@Îff@îffA33A33A'33A733AG33AW33Ag33Aw33AAAAA£A«A³A»AÃAËAÓAÛAãAëAóAûBÌÍBÌÍB	ÌÍB
+ÌÍBÌÍBÌÍBÌÍB
+ÌÍB!ÌÍB%ÌÍB)ÌÍB-ÌÍB1ÌÍB5ÌÍB9ÌÍB=ÌÍBAÌÍBEÌÍBIÌÍBMÌÍBQÌÍBUÌÍBYÌÍB]ÌÍBaÌÍBeÌÍBiÌÍBmÌÍBqÌÍBuÌÍByÌÍB}ÌÍ>áG®?žQì@
+(ö@\(ö@{@®{@Î{@î{A
+=A
+=A'
+=A7
+=AG
+=AW
+=Ag
+=Aw
+=A
+A
+A
+A
+A£
+A«
+A³
+A»
+AÃ
+AË
+AÓ
+AÛ
+Aã
+Aë
+Aó
+Aû
+BÂBÂB	ÂB
+ÂBÂBÂBÂB
+ÂB!ÂB%ÂB)ÂB-ÂB1ÂB5ÂB9ÂB=ÂBAÂBEÂBIÂBMÂBQÂBUÂBYÂB]ÂBaÂBeÂBiÂBmÂBqÂBuÂByÂB}Â>Ü(ö?·
+>@
+@[
+@Â@­Â@ÍÂ@íÂAáHAáHA&áHA6áHAFáHAVáHAfáHAváHAp€Ap€Ap€Ap€A£p€A«p€A³p€A»p€AÃp€AËp€AÓp€AÛp€Aãp€Aëp€Aóp€Aûp€BžRBžRB	žRB
+žRBžRBžRBžRB
+žRB!žRB%žRB)žRB-žRB1žRB5žRB9žRB=žRBAžRBEžRBIžRBMžRBQžRBUžRBYžRB]žRBažRBežRBižRBmžRBqžRBužRByžRB}žR>×
+=?µÂ@áH@ZáH@p€@­p€@Íp€@íp€AžRAžRA&žRA6žRAFžRAVžRAfžRAvžRA\)A\)A\)A\)A£\)A«\)A³\)A»\)AÃ\)AË\)AÓ\)AÛ\)Aã\)Aë\)Aó\)Aû\)B®B®B	®B
+®B®B®B®B
+®B!®B%®B)®B-®B1®B5®B9®B=®BA®BE®BI®BM®BQ®BU®BY®B]®Ba®Be®Bi®Bm®Bq®Bu®By®B}®>Ñë
+?Žzá@=q@Z=q@
+ž@­
+ž@Í
+ž@í
+žA\A\A&\A6\AF\AV\Af\Av\AG®AG®AG®AG®A£G®A«G®A³G®A»G®AÃG®AËG®AÓG®AÛG®AãG®AëG®AóG®AûG®B£×B£×B	£×B
+£×B£×B£×B£×B
+£×B!£×B%£×B)£×B-£×B1£×B5£×B9£×B=£×BA£×BE£×BI£×BM£×BQ£×BU£×BY£×B]£×Ba£×Be£×Bi£×Bm£×Bq£×Bu£×By£×B}£×>ÌÌÍ?³33@@Y@ÌÍ@¬ÌÍ@ÌÌÍ@ìÌÍAffAffA&ffA6ffAFffAVffAfffAvffA33A33A33A33A£33A«33A³33A»33AÃ33AË33AÓ33AÛ33Aã33Aë33Aó33Aû33BBB	B
+BBBB
+B!B%B)B-B1B5B9B=BABEBIBMBQBUBYB]BaBeBiBmBqBuByB}>Ç®?±ë
+@õÂ@XõÂ@zá@¬zá@Ìzá@ìzáA=qA=qA&=qA6=qAF=qAV=qAf=qAv=qA
+žA
+žA
+žA
+žA£
+žA«
+žA³
+žA»
+žAÃ
+žAË
+žAÓ
+žAÛ
+žAã
+žAë
+žAó
+žAû
+žB\B\B	\B
+\B\B\B\B
+\B!\B%\B)\B-\B1\B5\B9\B=\BA\BE\BI\BM\BQ\BU\BY\B]\Ba\Be\Bi\Bm\Bq\Bu\By\B}\>Â\?°£×@Qì@XQì@(ö@¬(ö@Ì(ö@ì(öA{A{A&{A6{AF{AV{Af{Av{A
+=A
+=A
+=A
+=A£
+=A«
+=A³
+=A»
+=AÃ
+=AË
+=AÓ
+=AÛ
+=Aã
+=Aë
+=Aó
+=Aû
+=B
+B
+B	
+B
+
+B
+B
+B
+B
+
+B!
+B%
+B)
+B-
+B1
+B5
+B9
+B=
+BA
+BE
+BI
+BM
+BQ
+BU
+BY
+B]
+Ba
+Be
+Bi
+Bm
+Bq
+Bu
+By
+B}
+>œp€?¯\)@®@W®@×
+@«×
+@Ë×
+@ë×
+Aë
+Aë
+A%ë
+A5ë
+AEë
+AUë
+Aeë
+Auë
+AõÃAõÃAõÃAõÃA¢õÃAªõÃA²õÃAºõÃAÂõÃAÊõÃAÒõÃAÚõÃAâõÃAêõÃAòõÃAúõÃBzáBzáB	záB
+záBzáBzáBzáB
+záB!záB%záB)záB-záB1záB5záB9záB=záBAzáBEzáBIzáBMzáBQzáBUzáBYzáB]záBazáBezáBizáBmzáBqzáBuzáByzáB}zá>žQì?®{@
+>@W
+>@
+@«
+@Ë
+@ë
+AÂAÂA%ÂA5ÂAEÂAUÂAeÂAuÂAáHAáHAáHAáHA¢áHAªáHA²áHAºáHAÂáHAÊáHAÒáHAÚáHAâáHAêáHAòáHAúáHBp€Bp€B	p€B
+p€Bp€Bp€Bp€B
+p€B!p€B%p€B)p€B-p€B1p€B5p€B9p€B=p€BAp€BEp€BIp€BMp€BQp€BUp€BYp€B]p€Bap€Bep€Bip€Bmp€Bqp€Bup€Byp€B}p€>³33?¬ÌÍ@ff@Vff@33@«33@Ë33@ë33AAA%A5AEAUAeAuAÌÍAÌÍAÌÍAÌÍA¢ÌÍAªÌÍA²ÌÍAºÌÍAÂÌÍAÊÌÍAÒÌÍAÚÌÍAâÌÍAêÌÍAòÌÍAúÌÍBffBffB	ffB
+ffBffBffBffB
+ffB!ffB%ffB)ffB-ffB1ffB5ffB9ffB=ffBAffBEffBIffBMffBQffBUffBYffB]ffBaffBeffBiffBmffBqffBuffByffB}ff>®{?«
+@Â@UÂ@áH@ªáH@ÊáH@êáHAp€Ap€A%p€A5p€AEp€AUp€Aep€Aup€AžRAžRAžRAžRA¢žRAªžRA²žRAºžRAÂžRAÊžRAÒžRAÚžRAâžRAêžRAòžRAúžRB\)B\)B	\)B
+\)B\)B\)B\)B
+\)B!\)B%\)B)\)B-\)B1\)B5\)B9\)B=\)BA\)BE\)BI\)BM\)BQ\)BU\)BY\)B]\)Ba\)Be\)Bi\)Bm\)Bq\)Bu\)By\)B}\)>šõÃ?ª=q@
+ž@U
+ž@\@ª\@Ê\@ê\AG®AG®A%G®A5G®AEG®AUG®AeG®AuG®A£×A£×A£×A£×A¢£×Aª£×A²£×Aº£×AÂ£×AÊ£×AÒ£×AÚ£×Aâ£×Aê£×Aò£×Aú£×BQìBQìB	QìB
+QìBQìBQìBQìB
+QìB!QìB%QìB)QìB-QìB1QìB5QìB9QìB=QìBAQìBEQìBIQìBMQìBQQìBUQìBYQìB]QìBaQìBeQìBiQìBmQìBqQìBuQìByQìB}Qì>£×
+?šõÂ@zá@Tzá@=q@ª=q@Ê=q@ê=qA
+žA
+žA%
+žA5
+žAE
+žAU
+žAe
+žAu
+žA\A\A\A\A¢\Aª\A²\Aº\AÂ\AÊ\AÒ\AÚ\Aâ\Aê\Aò\Aú\BG®BG®B	G®B
+G®BG®BG®BG®B
+G®B!G®B%G®B)G®B-G®B1G®B5G®B9G®B=G®BAG®BEG®BIG®BMG®BQG®BUG®BYG®B]G®BaG®BeG®BiG®BmG®BqG®BuG®ByG®B}G®>žR?§®@×
+@S×
+@ë
+@©ë
+@Éë
+@éë
+AõÃAõÃA$õÃA4õÃADõÃATõÃAdõÃAtõÃAzáAzáAzáAzáA¢záAªzáA²záAºzáAÂzáAÊzáAÒzáAÚzáAâzáAêzáAòzáAúzáB=qB=qB	=qB
+=qB=qB=qB=qB
+=qB!=qB%=qB)=qB-=qB1=qB5=qB9=qB==qBA=qBE=qBI=qBM=qBQ=qBU=qBY=qB]=qBa=qBe=qBi=qBm=qBq=qBu=qBy=qB}=q>?Šff@33@S33@@©@É@éAÌÍAÌÍA$ÌÍA4ÌÍADÌÍATÌÍAdÌÍAtÌÍAffAffAffAffA¢ffAªffA²ffAºffAÂffAÊffAÒffAÚffAâffAêffAòffAúffB33B33B	33B
+33B33B33B33B
+33B!33B%33B)33B-33B133B533B933B=33BA33BE33BI33BM33BQ33BU33BY33B]33Ba33Be33Bi33Bm33Bq33Bu33By33B}33>zá?¥
+ž@\@R\@G®@©G®@ÉG®@éG®A£×A£×A$£×A4£×AD£×AT£×Ad£×At£×AQìAQìAQìAQìA¢QìAªQìA²QìAºQìAÂQìAÊQìAÒQìAÚQìAâQìAêQìAòQìAúQìB(öB(öB	(öB
+(öB(öB(öB(öB
+(öB!(öB%(öB)(öB-(öB1(öB5(öB9(öB=(öBA(öBE(öBI(öBM(öBQ(öBU(öBY(öB](öBa(öBe(öBi(öBm(öBq(öBu(öBy(öB}(ö>\)?£×
+@ë
+@Që
+@õÃ@šõÃ@ÈõÃ@èõÃAzáAzáA$záA4záADzáATzáAdzáAtzáA=qA=qA=qA=qA¢=qAª=qA²=qAº=qAÂ=qAÊ=qAÒ=qAÚ=qAâ=qAê=qAò=qAú=qB
+žB
+žB	
+žB
+
+žB
+žB
+žB
+žB
+
+žB!
+žB%
+žB)
+žB-
+žB1
+žB5
+žB9
+žB=
+žBA
+žBE
+žBI
+žBM
+žBQ
+žBU
+žBY
+žB]
+žBa
+žBe
+žBi
+žBm
+žBq
+žBu
+žBy
+žB}
+ž>=q?¢\@G®@QG®@£×@š£×@È£×@è£×AQìAQìA$QìA4QìADQìATQìAdQìAtQìA(öA(öA(öA(öA¢(öAª(öA²(öAº(öAÂ(öAÊ(öAÒ(öAÚ(öAâ(öAê(öAò(öAú(öB{B{B	{B
+{B{B{B{B
+{B!{B%{B){B-{B1{B5{B9{B={BA{BE{BI{BM{BQ{BU{BY{B]{Ba{Be{Bi{Bm{Bq{Bu{By{B}{>
+
+ž?¡G®@£×@P£×@Qì@šQì@ÈQì@èQìA(öA(öA$(öA4(öAD(öAT(öAd(öAt(öA{A{A{A{A¢{Aª{A²{Aº{AÂ{AÊ{AÒ{AÚ{Aâ{Aê{Aò{Aú{B
+=B
+=B	
+=B
+=B
+=B
+=B
+=B
+
+=B!
+=B%
+=B)
+=B-
+=B1
+=B5
+=B9
+=B=
+=BA
+=BE
+=BI
+=BM
+=BQ
+=BU
+=BY
+=B]
+=Ba
+=Be
+=Bi
+=Bm
+=Bq
+=Bu
+=By
+=B}
+=>  ?   @  @P  @  @š  @È  @è  A  A  A$  A4  AD  AT  Ad  At  A  A  A  A  A¢  Aª  A²  Aº  AÂ  AÊ  AÒ  AÚ  Aâ  Aê  Aò  Aú  B  B  B	  B
+  B  B  B  B
+  B!  B%  B)  B-  B1  B5  B9  B=  BA  BE  BI  BM  BQ  BU  BY  B]  Ba  Be  Bi  Bm  Bq  Bu  By  B}  >uÂ?žR@\)@O\)@®@§®@Ç®@ç®A×
+A×
+A#×
+A3×
+AC×
+AS×
+Ac×
+As×
+Aë
+Aë
+Aë
+Aë
+A¡ë
+A©ë
+A±ë
+A¹ë
+AÁë
+AÉë
+AÑë
+AÙë
+Aáë
+Aéë
+Añë
+Aùë
+B õÃBõÃBõÃB
+õÃBõÃBõÃBõÃB
+õÃB õÃB$õÃB(õÃB,õÃB0õÃB4õÃB8õÃB<õÃB@õÃBDõÃBHõÃBLõÃBPõÃBTõÃBXõÃB\õÃB`õÃBdõÃBhõÃBlõÃBpõÃBtõÃBxõÃB|õÃ>k
+?p€@žR@NžR@\)@§\)@Ç\)@ç\)A®A®A#®A3®AC®AS®Ac®As®A×
+A×
+A×
+A×
+A¡×
+A©×
+A±×
+A¹×
+AÁ×
+AÉ×
+AÑ×
+AÙ×
+Aá×
+Aé×
+Añ×
+Aù×
+B ë
+Bë
+Bë
+B
+ë
+Bë
+Bë
+Bë
+B
+ë
+B ë
+B$ë
+B(ë
+B,ë
+B0ë
+B4ë
+B8ë
+B<ë
+B@ë
+BDë
+BHë
+BLë
+BPë
+BTë
+BXë
+B\ë
+B`ë
+Bdë
+Bhë
+Blë
+Bpë
+Btë
+Bxë
+B|ë
+>aG®?(ö@{@N{@
+=@§
+=@Ç
+=@ç
+=A
+A
+A#
+A3
+AC
+AS
+Ac
+As
+AÂAÂAÂAÂA¡ÂA©ÂA±ÂA¹ÂAÁÂAÉÂAÑÂAÙÂAáÂAéÂAñÂAùÂB áHBáHBáHB
+áHBáHBáHBáHB
+áHB áHB$áHB(áHB,áHB0áHB4áHB8áHB<áHB@áHBDáHBHáHBLáHBPáHBTáHBXáHB\áHB`áHBdáHBháHBláHBpáHBtáHBxáHB|áH>W
+=?áH@
+p€@Mp€@žR@ŠžR@ÆžR@æžRA\)A\)A#\)A3\)AC\)AS\)Ac\)As\)A®A®A®A®A¡®A©®A±®A¹®AÁ®AÉ®AÑ®AÙ®Aá®Aé®Añ®Aù®B ×
+B×
+B×
+B
+×
+B×
+B×
+B×
+B
+×
+B ×
+B$×
+B(×
+B,×
+B0×
+B4×
+B8×
+B<×
+B@×
+BD×
+BH×
+BL×
+BP×
+BT×
+BX×
+B\×
+B`×
+Bd×
+Bh×
+Bl×
+Bp×
+Bt×
+Bx×
+B|×
+>LÌÍ?@
+ÌÍ@LÌÍ@ff@Šff@Æff@æffA33A33A#33A333AC33AS33Ac33As33AAAAA¡A©A±A¹AÁAÉAÑAÙAáAéAñAùB ÌÍBÌÍBÌÍB
+ÌÍBÌÍBÌÍBÌÍB
+ÌÍB ÌÍB$ÌÍB(ÌÍB,ÌÍB0ÌÍB4ÌÍB8ÌÍB<ÌÍB@ÌÍBDÌÍBHÌÍBLÌÍBPÌÍBTÌÍBXÌÍB\ÌÍB`ÌÍBdÌÍBhÌÍBlÌÍBpÌÍBtÌÍBxÌÍB|ÌÍ>B\?Qì@
+(ö@L(ö@{@Š{@Æ{@æ{A
+=A
+=A#
+=A3
+=AC
+=AS
+=Ac
+=As
+=A
+A
+A
+A
+A¡
+A©
+A±
+A¹
+AÁ
+AÉ
+AÑ
+AÙ
+Aá
+Aé
+Añ
+Aù
+B ÂBÂBÂB
+ÂBÂBÂBÂB
+ÂB ÂB$ÂB(ÂB,ÂB0ÂB4ÂB8ÂB<ÂB@ÂBDÂBHÂBLÂBPÂBTÂBXÂB\ÂB`ÂBdÂBhÂBlÂBpÂBtÂBxÂB|Â>8Qì?
+>@
+
+@K
+@
+Â@¥Â@ÅÂ@åÂAáHAáHA"áHA2áHABáHARáHAbáHAráHAp€Ap€Ap€Ap€A¡p€A©p€A±p€A¹p€AÁp€AÉp€AÑp€AÙp€Aáp€Aép€Añp€Aùp€B žRBžRBžRB
+žRBžRBžRBžRB
+žRB žRB$žRB(žRB,žRB0žRB4žRB8žRB<žRB@žRBDžRBHžRBLžRBPžRBTžRBXžRB\žRB`žRBdžRBhžRBlžRBpžRBtžRBxžRB|žR>.{?Â@
+áH@JáH@
+p€@¥p€@Åp€@åp€AžRAžRA"žRA2žRABžRARžRAbžRAržRA\)A\)A\)A\)A¡\)A©\)A±\)A¹\)AÁ\)AÉ\)AÑ\)AÙ\)Aá\)Aé\)Añ\)Aù\)B ®B®B®B
+®B®B®B®B
+®B ®B$®B(®B,®B0®B4®B8®B<®B@®BD®BH®BL®BP®BT®BX®B\®B`®Bd®Bh®Bl®Bp®Bt®Bx®B|®>#×
+?zá@
+=q@J=q@
+
+ž@¥
+ž@Å
+ž@å
+žA\A\A"\A2\AB\AR\Ab\Ar\AG®AG®AG®AG®A¡G®A©G®A±G®A¹G®AÁG®AÉG®AÑG®AÙG®AáG®AéG®AñG®AùG®B £×B£×B£×B
+£×B£×B£×B£×B
+£×B £×B$£×B(£×B,£×B0£×B4£×B8£×B<£×B@£×BD£×BH£×BL£×BP£×BT£×BX£×B\£×B`£×Bd£×Bh£×Bl£×Bp£×Bt£×Bx£×B|£×>?33@	@I@ÌÍ@€ÌÍ@ÄÌÍ@äÌÍAffAffA"ffA2ffABffARffAbffArffA33A33A33A33A¡33A©33A±33A¹33AÁ33AÉ33AÑ33AÙ33Aá33Aé33Añ33Aù33B BBB
+BBBB
+B B$B(B,B0B4B8B<B@BDBHBLBPBTBXB\B`BdBhBlBpBtBxB|>\)?ë
+@õÃ@HõÃ@zá@€zá@Äzá@äzáA=qA=qA"=qA2=qAB=qAR=qAb=qAr=qA
+žA
+žA
+žA
+žA¡
+žA©
+žA±
+žA¹
+žAÁ
+žAÉ
+žAÑ
+žAÙ
+žAá
+žAé
+žAñ
+žAù
+žB \B\B\B
+\B\B\B\B
+\B \B$\B(\B,\B0\B4\B8\B<\B@\BD\BH\BL\BP\BT\BX\B\\B`\Bd\Bh\Bl\Bp\Bt\Bx\B|\>
+ž?£×@Qì@HQì@(ö@€(ö@Ä(ö@ä(öA{A{A"{A2{AB{AR{Ab{Ar{A
+=A
+=A
+=A
+=A¡
+=A©
+=A±
+=A¹
+=AÁ
+=AÉ
+=AÑ
+=AÙ
+=Aá
+=Aé
+=Añ
+=Aù
+=B 
+B
+B
+B
+
+B
+B
+B
+B
+
+B 
+B$
+B(
+B,
+B0
+B4
+B8
+B<
+B@
+BD
+BH
+BL
+BP
+BT
+BX
+B\
+B`
+Bd
+Bh
+Bl
+Bp
+Bt
+Bx
+B|
+=õÂ?\)@®@G®@×
+@£×
+@Ã×
+@ã×
+Aë
+Aë
+A!ë
+A1ë
+AAë
+AQë
+Aaë
+Aqë
+AõÃAõÃAõÃAõÃA õÃAšõÃA°õÃAžõÃAÀõÃAÈõÃAÐõÃAØõÃAàõÃAèõÃAðõÃAøõÃB záBzáBzáB
+záBzáBzáBzáB
+záB záB$záB(záB,záB0záB4záB8záB<záB@záBDzáBHzáBLzáBPzáBTzáBXzáB\záB`záBdzáBhzáBlzáBpzáBtzáBxzáB|zá=áG®?{@
+=@G
+=@
+@£
+@Ã
+@ã
+AÂAÂA!ÂA1ÂAAÂAQÂAaÂAqÂAáHAáHAáHAáHA áHAšáHA°áHAžáHAÀáHAÈáHAÐáHAØáHAàáHAèáHAðáHAøáHB p€Bp€Bp€B
+p€Bp€Bp€Bp€B
+p€B p€B$p€B(p€B,p€B0p€B4p€B8p€B<p€B@p€BDp€BHp€BLp€BPp€BTp€BXp€B\p€B`p€Bdp€Bhp€Blp€Bpp€Btp€Bxp€B|p€=ÌÌÍ?ÌÍ@ff@Fff@33@£33@Ã33@ã33AAA!A1AAAQAaAqAÌÍAÌÍAÌÍAÌÍA ÌÍAšÌÍA°ÌÍAžÌÍAÀÌÍAÈÌÍAÐÌÍAØÌÍAàÌÍAèÌÍAðÌÍAøÌÍB ffBffBffB
+ffBffBffBffB
+ffB ffB$ffB(ffB,ffB0ffB4ffB8ffB<ffB@ffBDffBHffBLffBPffBTffBXffB\ffB`ffBdffBhffBlffBpffBtffBxffB|ff=žQì?
+@Â@EÂ@áH@¢áH@ÂáH@âáHAp€Ap€A!p€A1p€AAp€AQp€Aap€Aqp€AžRAžRAžRAžRA žRAšžRA°žRAžžRAÀžRAÈžRAÐžRAØžRAàžRAèžRAðžRAøžRB \)B\)B\)B
+\)B\)B\)B\)B
+\)B \)B$\)B(\)B,\)B0\)B4\)B8\)B<\)B@\)BD\)BH\)BL\)BP\)BT\)BX\)B\\)B`\)Bd\)Bh\)Bl\)Bp\)Bt\)Bx\)B|\)=£×
+?=q@
+ž@E
+ž@\@¢\@Â\@â\AG®AG®A!G®A1G®AAG®AQG®AaG®AqG®A£×A£×A£×A£×A £×Aš£×A°£×Až£×AÀ£×AÈ£×AÐ£×AØ£×Aà£×Aè£×Að£×Aø£×B QìBQìBQìB
+QìBQìBQìBQìB
+QìB QìB$QìB(QìB,QìB0QìB4QìB8QìB<QìB@QìBDQìBHQìBLQìBPQìBTQìBXQìB\QìB`QìBdQìBhQìBlQìBpQìBtQìBxQìB|Qì=\)?õÃ@zá@Dzá@=q@¢=q@Â=q@â=qA
+žA
+žA!
+žA1
+žAA
+žAQ
+žAa
+žAq
+žA\A\A\A\A \Aš\A°\Až\AÀ\AÈ\AÐ\AØ\Aà\Aè\Að\Aø\B G®BG®BG®B
+G®BG®BG®BG®B
+G®B G®B$G®B(G®B,G®B0G®B4G®B8G®B<G®B@G®BDG®BHG®BLG®BPG®BTG®BXG®B\G®B`G®BdG®BhG®BlG®BpG®BtG®BxG®B|G®=uÂ?®@×
+@C×
+@ë
+@¡ë
+@Áë
+@áë
+A õÃAõÃA õÃA0õÃA@õÃAPõÃA`õÃApõÃAzáAzáAzáAzáA záAšzáA°záAžzáAÀzáAÈzáAÐzáAØzáAàzáAèzáAðzáAøzáB =qB=qB=qB
+=qB=qB=qB=qB
+=qB =qB$=qB(=qB,=qB0=qB4=qB8=qB<=qB@=qBD=qBH=qBL=qBP=qBT=qBX=qB\=qB`=qBd=qBh=qBl=qBp=qBt=qBx=qB|=q=LÌÍ?ff@33@C33@@¡@Á@áA ÌÍAÌÍA ÌÍA0ÌÍA@ÌÍAPÌÍA`ÌÍApÌÍAffAffAffAffA ffAšffA°ffAžffAÀffAÈffAÐffAØffAàffAèffAðffAøffB 33B33B33B
+33B33B33B33B
+33B 33B$33B(33B,33B033B433B833B<33B@33BD33BH33BL33BP33BT33BX33B\33B`33Bd33Bh33Bl33Bp33Bt33Bx33B|33=#×
+?
+
+ž@\@B\@G®@¡G®@ÁG®@áG®A £×A£×A £×A0£×A@£×AP£×A`£×Ap£×AQìAQìAQìAQìA QìAšQìA°QìAžQìAÀQìAÈQìAÐQìAØQìAàQìAèQìAðQìAøQìB (öB(öB(öB
+(öB(öB(öB(öB
+(öB (öB$(öB((öB,(öB0(öB4(öB8(öB<(öB@(öBD(öBH(öBL(öBP(öBT(öBX(öB\(öB`(öBd(öBh(öBl(öBp(öBt(öBx(öB|(ö<õÂ?×
+@ë
+@Aë
+@õÃ@ õÃ@ÀõÃ@àõÃA záAzáA záA0záA@záAPzáA`záApzáA=qA=qA=qA=qA =qAš=qA°=qAž=qAÀ=qAÈ=qAÐ=qAØ=qAà=qAè=qAð=qAø=qB 
+žB
+žB
+žB
+
+žB
+žB
+žB
+žB
+
+žB 
+žB$
+žB(
+žB,
+žB0
+žB4
+žB8
+žB<
+žB@
+žBD
+žBH
+žBL
+žBP
+žBT
+žBX
+žB\
+žB`
+žBd
+žBh
+žBl
+žBp
+žBt
+žBx
+žB|
+ž<£×
+?\@G®@AG®@£×@ £×@À£×@à£×A QìAQìA QìA0QìA@QìAPQìA`QìApQìA(öA(öA(öA(öA (öAš(öA°(öAž(öAÀ(öAÈ(öAÐ(öAØ(öAà(öAè(öAð(öAø(öB {B{B{B
+{B{B{B{B
+{B {B${B({B,{B0{B4{B8{B<{B@{BD{BH{BL{BP{BT{BX{B\{B`{Bd{Bh{Bl{Bp{Bt{Bx{B|{<#×
+?G®@ £×@@£×@Qì@ Qì@ÀQì@àQìA (öA(öA (öA0(öA@(öAP(öA`(öAp(öA{A{A{A{A {Aš{A°{Až{AÀ{AÈ{AÐ{AØ{Aà{Aè{Að{Aø{B 
+=B
+=B
+=B
+
+=B
+=B
+=B
+=B
+
+=B 
+=B$
+=B(
+=B,
+=B0
+=B4
+=B8
+=B<
+=B@
+=BD
+=BH
+=BL
+=BP
+=BT
+=BX
+=B\
+=B`
+=Bd
+=Bh
+=Bl
+=Bp
+=Bt
+=Bx
+=B|
+=    ?  @   @@  @  @   @À  @à  A   A  A   A0  A@  AP  A`  Ap  A  A  A  A  A   Aš  A°  Až  AÀ  AÈ  AÐ  AØ  Aà  Aè  Að  Aø  B   B  B  B
+  B  B  B  B
+  B   B$  B(  B,  B0  B4  B8  B<  B@  BD  BH  BL  BP  BT  BX  B\  B`  Bd  Bh  Bl  Bp  Bt  Bx  B|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?!1?)ì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+Æ?(þ?¯m®@ý¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?óô?$h,?­E@:@29Q@_¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?U"? É:?«ÎÌ@}@1Q@_«@]â@D¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?¶P?
+*h?©ÿb@ŽÈ@0ià@^
+ø@
+ê@Ä@³ @ÊB¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ??w?š/ê@Í
+@/#@]7;@
+v)@P¶@³+B@ÊÎ@ààZ@÷Œ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+x­?ì¥?Š`@ åX@.o@\O@
+O@ÜÜ@²·g@Éô@àl@÷G
+AÌAb|¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?ÙÚ?M³?€?ÿû6@-²²@[gÊ@q@hý@²C@É
+@ßø¡@öÓ.AÖÜAD"A
+±hA)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?;	?®á?¢Á?þ+Î@,Êþ@Z@@õ#@±Ï¯@Èª;@ßÈ@ö_TAðA
+5A
+wzA(äÀA4RA?£¶¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ? 7?
+? ò6?ü\e@+ãJ@Ya@Šœ@I@±[Õ@È6a@ßí@õëyAcAÐHA
+=A(ªÓA4A?
+^AJò€AVDT¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ùúÊ?q
+?"Ÿ?úì@*û@X°€@2Þ@
+j@°ç÷@ÇÂ@Þ@õwA)AYA
+A(päA3Þ*A?KoAJžŽAV%úAa@Aläð¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >òœ(?ÒL?SU?øœ@*Ù@WÈð@¿@@°t
+@ÇNš@Þ)5@õÁAï&A\lA
+É±A(6÷A3€<A?AJ~ÈAUì
+AaYRAlÆAx3ÞAÂÇ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ë? 3Z?Ü?öî
+@),
+@Vá4@K&@%³@° >@ÆÚÊ@ÝµV@ôâAµ7A"}A
+ÂA'ýA3jMA>×AJDØAU²
+AadAl©AwùîA³Aj=A¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >äAà>ù)?Žs?õ
+¢@(Dh@Uù@×L@±Ø@¯d@Æfñ@ÝA|@ô
+A{IAèA
+UÕA'ÃA30`A>ŠAJ
+ëAUx1A`åvAlRŒAwÀA€AMHAëAºAcf¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Ý<>ñë,?äú?óO)@'\¬@UÃ@cm@=ú@¯
+@Åó@ÜÍ@óš+AA[A® A
+åA'+A2öqA>c·AIÐüAU>BA`«AlÍAwAy­A0PAæóAAT:A
+ÜA£³µ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ÕÆ>ê­??ñÀ@&t÷@T*@ï@Ê@®€«@Å8@ÜYÃ@ó4PAnAt³AáùA'O>A2ŒA>)ÉAIAUUA`qAkÞàAwL%A\¶AYAÉýA A7CAíçA£€A©[,A¯¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Îõ>ão€?F?ï°G@%;@SBR@{µ@VA@®0Í@Å
+Y@Ûåå@òÀqAÍ~A:ÄAš
+A'OA2A=ïÚAI]ATÊeA`7«Ak€ñAw6A?ŸAöaA­AcšALAÐïA£A©>6A®ôÙAŽ«{AºTT¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ÇKQ>Ü2?v¯?íàÞ@$¥@RZ@Û@âg@­Œó@Ä@Ûr
+@òLAA ÖAn
+A&ÛbA2HšA=µíAI#3ATxA_ýœAkkAvØIA"ÈAÙkAAF±AýUA³øA£jA©!?A®×âAŽAºE)A¿ûËAÅ€€¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >À
+®>Ôô
+?§6?ìe@#œÊ@Qrá@'ù@n@­I@Ä#¡@Úþ-@ñØ¹AY¢AÆèA4-A&¡rA2žA={þAHéDATVA_ÃÏAk1AvYAÐAŒsAsA)ºAà]A A£M€A©GA®ºëAŽqAº(1A¿ÞÕAÅxAËLAÐôó¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >žÐ
+>Í¶z?×Î?êAü@"Ö@P-@~@E@ú®@¬Õ;@Ã¯Ç@ÚS@ñdßAµAúAú@A&gA1ÔËA=BAH¯VAT
+A_âAj÷'AvdmAèÚA}AV!A
+ÃAÃfAz
+A£0­AšçPA®ôAŽTAº
+;A¿ÁÞAÅxAË/%AÐåÈAÖjAÜEC¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >±f>Æx?U?èr@!îY@O£p@}X@Ð@¬a\@Ã;è@Úu@ðñAåÆAS
+AÀQA&-A1ÜA="AHugASâ¬A_OòAjœ8Av*~AËâAA9)AïÌAŠpA]A£µAšÊYA®üAŽ7A¹îCA¿€æAÅ[AË-AÐÈÐAÖtAÜ6Aáì¹Aç¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ªTÃ>¿:ó?8ì?æ£@!¥@N»»@|pÔ@ö@«í@ÂÈ@Ù¢@ð}&A«ÙAAdA%ó©A1`ïA<Î4AH;zASšÀA_AjJAuðA®ëAeA
+2AÒÖAyA@
+A¢öÀAš­bA®dAŽ©A¹ÑLA¿ïAÅ>AÊõ6AÐ«ÚAÖb}AÜ AáÏÄAçgAí=	Aòåâ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >£>·ý?is?äÓ¡@ 
+ç@MÓÿ@{@@«y€@ÂT0@Ù.Œ@ð	HAqéAß/ALuA%¹»A1' A<EAHASnÐA^ÜAjI\Au¶¡AôAHAÿ:AµÞAlA#%A¢ÙÈAškA®GA³ý±A¹ŽTA¿jøAÅ!AÊØ>AÐâAÖE
+AÛü)Aá²ÌAçioAí AòÖ¶AøXAþ61¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Ù|>°¿??ã@@77@LìN@z¡g@+@@«Ì@ÁàX@Øºä@ïpA7þA¥CAA%ÎA0íA<ZZAGÇAS4äA^¢*AjpAu|µAtýA+ AâDAçAOA.A¢ŒÑAšsuA®*A³à»A¹_A¿NAÅ€AÊ»HAÐqëAÖ(AÛß2AáÕAçLyAí
+Aò¹¿AøpcAþ'BîÕBÃA¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >×>©è?
+Ê©?á4×@
+O@L@y¹²@·f@ªñ@Ál~@ØG
+@ï!AþAkVAØA%EáA0³&A< lAG²ARúøA^h=AiÕAuBÈAXAªAÅMA{ðA2Aé7A¢ÚAšV~A®
+!A³ÃÅA¹zhA¿1
+AÄç¯AÊQAÐTôAÖ
+AÛÂ;AáxÞAç/Aìæ%AòÉAøSlAþ
+BàYB»«BýB
+ki¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >^4>¢DD?û@?ßen@
+gÎ@K
+å@xÑþ@C@ª
+@Àø€@×Ó/@î­ŒAÄ#A1iA®A%
+ôA0y:A;æAGSÄARÁ
+A^.PAiAuÛA;A
+ñŽAšWA^úAAÌ@A¢äAš9A­ð*A³ŠÎA¹]qA¿AÄÊžAÊ[AÐ7ÿAÕî¡AÛ¥DAá[èAçAìÉ.AòÒAø6uAýíBÑÞB­0BB
+cÓB
+?%B¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  > > ?+×?Ý@
+@J51@wêJ@Ï±@©ª=@ÀÉ@×_U@î9âA6A
+÷|AdÁA$ÒA0?LA;¬AGØAR
+A]ôbAiašAtÎîA
+A
+ÔœAaABAø§A¯JA¢eíAš
+A­Ó4A³×A¹@zAŸ÷
+AÄ­ÁAÊdeAÐAÕÑ«AÛOAá>ñAæõAì¬8AòbÛAø~AýÐ"BÃcBŽBzB
+UXB
+0©B
+ûBçMB»¹¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >}ÅØ>Èü?\n?ÛÆ@e@IM}@w@[×@©6c@Àï@Öë{@íÆAPIA
+œA*ÕA$A0_A;r¥AFßêARM0A]ºvAi'»At A#A
+·ÆAnjA%
+AÛ±ATA¢H÷A§ÿA­¶=A³làA¹#AŸÚ'AÄÊAÊGnAÏþAÕŽµAÛkXAá!ûAæØAìAAòEäA÷üAý³+BŽçB9BkB
+FÜB
+".BýBØÑBŽ#BuBcá¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >oJ>X?}
+?Ù÷3@°±@HeÈ@vá@çý@šÂ@¿@Öw¡@íR-A\A
+¡AðçA$^-A/ËsA;8žAF¥ýARCA]AhíÎAt[AÈYA
+ÐAQsAAŸºAu]A¢,A§â€A­GA³OêA¹AŸœ0AÄsÔAÊ*wAÏáAÕŸAÛNaAáAæ»šAìrKAò(ïA÷ßAý4BŠlBŸB]B
+8aB
+³BïBÊVB¥šBùB\KB
+7B!
+	¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >`ÏI>
+Mµ?y{8?Ø'Ë@Èý@G~@u3,@t"@šN®@¿);@ÖÆ@ìÞSAÜoA
+IµA¶úA$$?A/
+A:þËAFlAQÙVA]FAh³áAt!&AlA
+}ÙA4|Aë A¡ÃAXfA¢
+A§Å­A­|QA³2ôAžéAŸ :AÄVÝAÊ
+AÏÄ$AÕzÇAÛ1jAàèAæ±AìUUAò
+øA÷ÂAýy?BñBsBBNB
+)æB
+7BàB»ÛB,Br~BMÐB
+)!B!sB#ßÅB&Ž1¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >RT >|  ?uÜf?ÖXb@áH@F_@tKw@ H@§ÚÔ@Ÿµ`@Õì@ìjyA¢A
+ÇA}
+A#êSA/WA:ÄÝAF2#AQiA]
+¯AhyôAsç9ATA
+`ãAAÎ)AÌA;pA¡òA§š¶A­_ZA³ýAžÌ¡AŸDAÄ9çAÉðAÏ§-AÕ]ÐAÛtAàËAæºAì8^AñïA÷¥¥Aý\HBuBdÇB@B
+jB
+öŒBÒB­_B±BdB?TB
+ŠB õøB#ÑIB&¬B)íB,\Y¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >CØž>m€Ø?r=?Ôù@ù@E®«@scÃ@m@§fú@ŸA@Õ
+@ëöAhA
+ÕÚAC A#°eA/
+«A:ñAEø6AQe{A\ÒÁAh@As­MAA
+CìAúA±3AgÖA
+yA¡Õ
+A§ÀA­BcA²ùAž¯ªAŸfMAÄ
+ñAÉÓAÏ7AÕ@ÚAÚ÷}Aà® AædÄAìgAñÒ
+A÷®Aý?QBzúBVLB1B
+
+ïB
+èABÃBäBz6BUB0ÙB
+
++B ç|B#ÂÎB& B)yqB,TÃB/0B2¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >5]q>_)?nÃ?Ò¹@ß@DÆö@r|@@Šó@œÍ«@Ôš8@ëÄA.šA
+íA	3A#vxA.ãŸA:QAEŸIAQ+A\ÔAhAss_A~à¥A
+&öAÝA<AJàAA¡ž&A§nÉA­%lA²ÜAž³AŸIVAÃÿúAÉ¶AÏmAAÕ#äAÚÚAà*AæGÍAëþpAñµA÷k·Aý"ZBlBGÐB#"B	þtB
+ÙÅBµBiBkºBG
+B"^B
+ý¯B ÙB#ŽSB&€B)jöB,FHB/!B1üëB4Ø=B7¬©¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >&â)>P®?k ?Ðê/@*/@CßF@q^@€»@ŠG@œYÓ@Ô4_@ëëA ô»A
+bAÏGA#<A.©ÒA:AE]APñ¢A\^èAgÌ.As9sA~Š¹A
+
+ AÀ£AwGA-êAäA¡1A§QÔA­wA²¿AžuœAŸ,aAÃãAÉ§AÏPKAÕîAÚœAàt5Aæ*ØAëá{Añ
+A÷NÁAýeB^B9UB§B	ïøB
+ËJBŠBíB]?B8BâB
+ï4B ÊB#¥×B&)B)\{B,7ÌB/
+B1îpB4ÉÁB7¥B:eB=TÑ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >fâ>B3?ga
+?ÏŸ@Bv@B÷@p¬Š@0ß@Š
+k@Œå÷@ÓÀ@êA ºÍA
+(AXA#A.oäA9Ý)AEJoAP·ŽA\$úAg?Arÿ
+A~lÊAíA£¬AZOAòAÇA¡~9A§4ÜA¬ëA²¢#AžXÆAŸiAÃÆ
+AÉ|°AÏ3SAÔéöAÚ AàW=Aæ
+áAëÄAñ{'A÷1ÊAüèmBOB*ÚB,B	á}B
+ŒÏB BsrBNÄB*BgB
+à¹B Œ
+B#\B&r®B)MÿB,)QB/£B1ßôB4»FB7B:qéB=M;B@(BBüù¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >	ë>3·?cÂD?ÍKQ@ZÀ@B×@oÄï@œ@¥@Œr
+@ÓLš@ê'4A àA
+î%A[kA"È±A.5öA9£<AEAP}ÇA[ë
+AgXRArÅA~2ÝAÐAµA=XAóüAªA¡aBA§æA¬ÎA²
+,Až;ÐAœòsAÃ©AÉ_¹AÏ\AÔÍ AÚ£Aà:FAåðêAë§Añ^1A÷ÔAüËwBA
+B
+_B÷°B	ÓB
+®TB¥Bd÷B@HBBöìB
+Ò=B ­B#áB&d2B)?B,ÖB.ö'B1ÑyB4¬ËB7
+B:cnB=>ÀB@BBõcBEÐµBH¥!¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =öà©>%<3?`#k?Ë{ä@s	@A(!@nÝ9@I)@¥#Ž@»þ@@ÒØÍ@é³YA FòA
+Ž8A!}A"ÂA-üA9iNADÖAPCÙA[±Ag
+dArªA}øñA³
+AiŸA bA×AšA¡DLAŠúïA¬±A²h6Až
+ÙAœÕ|AÃ AÉBÃAÎùfAÔ°	AÚf¬Aà
+PAåÓóAëAñA:Aö÷ÝAü®B2B
+ãBé5B	ÄB
+ØB{*BV|B1ÍB
+BèpB
+ÃÂB B#zeB&U·B)1	B,
+ZB.ç¬B1ÂþB4OB7y¡B:TóB=0DB@
+BBæèBEÂ9BHBKxÝBNMI¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =Ùê>Àí?\?É¬{@U@@@l@mõ@ÕN@€¯Ú@»g@Òdò@é?~A 
+A
+zJAçA"TÖA-ÂA9/`ADŠAP	ìA[w1AfäwArQœA}¿A%ALÈAlAºAp²A¡'UAŠÝøA¬A²K?AžâAœžAÃo)AÉ%ÌAÎÜpAÔAÚI¶Aà YAå¶üAëm Añ$CAöÚæAüB$BÿhBÚºB	¶
+B
+]Bl¯BH B#RBþ€BÙõB
+µGB B#kêB&G<B)"B+ýßB.Ù1B1ŽB4ÔB7k&B:FwB=!ÉB?ýBBØlBE³ŸBHBKjaBNE³BQ!BSõq¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =Œó>E?XåÀ?ÇÝ@£@?X¶@m
+Î@as@€;ÿ@»@Ññ@èË€@ÿŠ0A
+@]A­¢A"èA-.A8õtADb¹AOÏþA[=DAfªArÏA}
+Ay.A/ÒAæuAASŒA¡
+^AŠÁA¬w¥A².HA·äìAœAÃR2AÉÖAÎ¿yAÔv
+AÚ,ÀAßãcAåAëP©AñLAöœðAütBBðíBÌ>B	§B
+âB^3B9
+B×Bð(BËzB
+ŠÌB 
+B#]oB&8ÀB)B+ïdB.ÊµB1ŠB4YB7\ªB:7üB=NB?îBBÉñBE¥CBHBK[æBN78BQBSíÛBVÉ-BY¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =ý=ó@?UFæ?Æ
+¡@»ç@>pÿ@l&@í@£È$@º¢°@Ñ}<@èWÈ@ÿ2SA
+oAsµA!àúA-N?A8»
+AD(ËAOA[VAfpAqÝáA}K'A\7AÚAÉ}A!A6ÄA ígAŠ€
+A¬Z­A²QA·ÇôAœ~AÃ5;AÈëÞAÎ¢AÔY%AÚÈAßÆkAå}Aë3²AðêUAö øAüWBBâpBœÂB	B
+teBO·B+	BZBá¬BŒþB
+OB s¡B#NóB&*DB)B+àçB.Œ9B1B4rÜB7N.B:)B=ÑB?à#BB»uBEÆBHrBKMjBN(»BQ
+BSß_BVº°BYB\qTB_EÀ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =t=Ö?Qš?Ä>6@Ô2@=I@k>a@yœ@£TH@º.Õ@Ñ	a@çãí@þŸyA
+ÌA9ÈA!§
+A-SA8ACîÝAO\#AZÉiAf6¯Aq£ôA}9A?@AõãA¬Ac*AÍA ÐqAŠA¬=·A±ô[A·ªýAœa¡AÃDAÈÎçAÎ
+AÔ<.AÙòÑAß©uAå`Aë»AðÍ_AöAü:¥B ø£BÓõB¯GB	B
+eêBA<B
+B÷ßBÓ1B®B
+ÔB e&B#@wB&ÉB(÷B+ÒlB.­ŸB1B4daB7?³B:B<öVB?ÑšBB¬ùBEKBHcBK>îBN@BPõBSÐãBV¬5BYB\bØB_>*Bb|Bdíè¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =LÍ=¹Šä?N	:?ÂnÌ@ì}@<¡@jV¬@â@¢ào@¹ºû@Ð@çp@þJA
+AÿÚA!m A,ÚfA8G«ACŽñAO"6AZ{AeüÁAqjA|×LA"IAØíAAF3Aü×A ³zAŠj
+A¬ ÁA±×dA·AœD«AÂûMAÈ±ñAÎhAÔ7AÙÕÛAß~AåC!AêùÅAð°hAög
+Aü
+¯B ê(BÅzB ÌB	|
+B
+WoB2ÀBBédBÄµB B
+{YB VªB#1üB&
+NB(èB+ÃñB.CB1zB4UæB717B:
+B<çÛB?Ã,BB~BEyÐBHU!BK0sBN
+ÅBPçBSÂhBVºBYy
+B\T]B_/¯Bb
+ BdæRBgÁ€Bj¿  ¿  ¿  ¿  ¿  ¿  =2³=°8?Jjd?À`@Ç@;¹ß@inö@@¢l@¹G@Ð!¬@æü8@ýÖÂA
+X§AÅíA!32A, wA8
+œAC{ANèHAZUAeÂÓAq0A|`ASA»öArA)=AßàA AŠM'A¬ÊA±ºmA·qAœ'ŽAÂÞWAÈûAÎKAÔAAÙžäAßoAå&+AêÜÎAðqAöJAü žB Û­B¶ÿBPB	m¢B
+HôB$EBÿBÚèB¶:BB
+lÝB H/B##B%þÒB(Ú$B+µvB.ÇB1lB4GkB7"ŒB9þB<Ù_B?Ž±BBBEkTBHFŠBK!øBMýIBPØBS³íBV>BYjB\EâB_!3Baü
+Bd××Bg³(BjzBmiÌBp>8¿  ¿  ¿  ¿  <°/=s4?FË?ŸÏø@
+
+@:Ò*@hB@
+-@¡ø¹@žÓE@Ï­Ñ@æ]@ýbèA
+
+¹AÿA ùEA,fA7ÓÐACAAN®[AZ¡AeæApö,A|csAè]A AU£A
+FAÂéA yAŠ00A«æÓA±wA·TAœ
+œAÂÁaAÈxAÎ.§AÓåKAÙíAßRAå	4Aê¿×Aðv{Aö-
+AûãÁB Í2BšBÕB	_'B
+:xBÊBñ
+BÌmB§¿BB
+^bB 9ŽB#B%ðWB(Ë©B+ŠúB.LB1]B48ïB7AB9ïB<ÊäB?Š6BBBE\ÙBH8+BK|BMîÎBPÊ BS¥qBVÃBY\B\7fB_žBaî
+BdÉ[Bg€­BjÿBm[PBp6¢BsôBuæ`¿  ¿  ;òÃë=E
+ê?C,œ?œ @
+5^@9êu@g@ªS@¡ß@ž_k@Ï9÷@æ@üïA	äÍARA ¿WA,,A7ãAC)ANtnAYá³AeNùApŒ?A|)
+AËfA	A8­AïPA¥óA \AŠ9A«ÉÝA±A·7#AŒíÇAÂ€jAÈ[
+AÎ±AÓÈTAÙ~÷Aß5Aäì=Aê¢áAðYAö'AûÆËB Ÿ·BBuZB	P«B
++ýBOBâ BœòBDBtB
+OçB +8B#B%áÜB(œ-B+B.sÑB1O"B4*tB7ÆB9áB<ŒiB?»BBs
+BEN^BH)¯BKBMàSBP»€BSöBVrHBYMB\(ëB_=BaßBdºàBg2BjqBmLÕBp('BsxBuÞÊBxº
+B{    =
+??è?»1"@
+Mš@9¿@f·×@6x@¡@·ë@ÎÆ
+@å š@ü{4A	ªàA%A 
+kA+ò°A7_õABÍ;AN:AY§ÇAe
+ApQA{ïA®oAeA¶AÒYAýA ? A¥öCA«¬æA±cA·-AŒÐÐAÂsAÈ>AÍôºAÓ«]AÙbAß€AäÏGAê
+ëAð<Aõó1Aû©ÔB °;BBfßB	B0B
+
+BøÓBÔ%B¯wBÈBfB
+AlB 
+œB"øB%Ó`B(®²B+B.eUB1@§B4ùB6÷JB9ÒB<­îB??BBdBE?ãBH4BJöBMÑ×BP­)BS{BVcÌBY?
+B\pB^õÁBaÑBd¬eBg¶BjcBm>ZBp«BrôýBuÐOBx« B{òB~bD¿  ?=š\?¹a·@
+eó@8
+@eÐ"@Â@ *@·w¶@ÎRB@å,Î@üZA	pòAÞ8A K~A+žÃA7&	ABNAN AYmÙAdÛApHeA{µ«AyAH
+Aþ¿AµcAlA "©A¥ÙMA«ðA±FA¶ý6AŒ³ÙAÂj}AÈ! AÍ×ÃAÓgAÙE
+AÞû­Aä²QAêhôAðAõÖ;AûÝB ¡ÀB}BXcB	3µB
+BêXBÅªB ûB|MBWB
+2ðB BB"éB%ÄåB( 7B+{B.VÚB12,B4
+}B6èÏB9Ä!B<rB?zÄBBVBE1gBH
+¹BJè
+BMÃ\BP®BSyÿBVUQBY0£B\
+ôB^çFBaÂBdéBgy;BjTBm/ÞBp
+0BræBuÁÓBx%B{xwB~SÈB~}¿  ¿  @	ì@73U@dèl@NÂ@ )N@·Û@ÍÞg@äžó@û~A	7A€JA A+~ÕA6ìABY`AMÆŠAY3ëAd¡0ApvA{{ŒAtA+$AáÈAkAOA ²A¥ŒUA«røA±)A¶à?AŒâAÂM
+AÈ(AÍºÌAÓqoAÙ(AÞÞ¶AäYAêKüAð Aõ¹CAûoæB EBnBIèB	%:B
+ BÛÝB·/BBmÒBI#B
+$uBÿÇB"ÛB%¶jB(ŒB+m
+B.H_B1#°B3ÿB6ÚTB9µ¥B<÷B?lIBBGBE"ìBGþ>BJÙBMŽáBP3BSkBVFÖBY"'B[ýyB^ØËBaŽ
+BdnBgjÀBjFBm!cBoüµBrØBu³XBxªB{iûB~EMB~o¿  ¿  ¿  ¿  @do
+@Úè@µt@¶ @Íj@äE@û£AýAj]A×£A+DèA6²-ABsAM¹AXùþAdgDAoÔA{AÏAWA.AÄÑA{tA2Aè»A¥^A«VA±
+¥A¶ÃHAŒyìAÂ0AÇç2AÍÕAÓTxAÙ
+
+AÞÁ¿AäxbAê/Aïå©AõLAûRðB ÉB`B;mB	ŸB
+òBÍbBš³BB_WB:šB
+úBñKB"ÌB%§ïB(@B+^B.9äB15B3ðB6ËØB9§*B<|B?]ÍBB9BEqBGïÂBJËBMŠfBP·BS]	BV8[BY¬B[îþB^ÊOBa¥¡BdóBg\DBj7BmèBoî9BrÉBu€ÝBx.B{[B~6ÒB~`¿  ¿  ¿  ¿  ¿  ¿  @xÂ@¶
+%@Ìö±@ãÑ=@ú«ÊAÃ*A0pAµA+
+ûA6xAAAåAMRËAXÀAd-WAoA{âA:Añ8A§ÛA^~A!AËÄA¥hA«9
+A°ï®A¶ŠRAŒ\õAÂAÇÊ<AÍßAÓ7AØî%AÞ€ÈAä[lAêAïÈ²AõVAû5ùB vNBQ B,ñB	CB
+ãBŸæB8BuBPÛB,-B
+BâÐB"Ÿ"B%sB(tÅB+PB.+hB1ºB3â
+B6œ]B9¯B<t B?ORBB*€BEõBGáGBJŒBMêBPs<BSNBV)ßBY1B[àB^»ÔBa&BdrwBgMÉBj)BmlBoßŸBr»BuaBxq³B{MB~(VB~R¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @Ìº @ã]c@ú7ïA=AöAcÈA*ÑA6>SAA«AMßAX$AcóiAo`¯AzÍõA
+AÔAAäAAAø+A®ÎA¥eqA«
+A°ÒžA¶[AŒ?þAÁö¢AÇ­EAÍcèAÓAØÑ/AÞÒAä>uAéõAï«ŒAõb_AûB gÓBC$B
+vBùÈB
+ÕB°kBœBgBB`B
+²B
+ùBÔUB"¯§B%øB(fJB+AB.
+íB0ø?B3ÓB6®âB94B<e
+B?@×BB
+(BD÷zBGÒÌBJ®
+BMoBPdÁBS@BVdBXö¶B[ÒB^­YBa«BdcüBg?NBjBlõñBoÑCBr¬BuæBxc8B{>B~ÛB~C¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @ùû<AOOAŒA)ÚA* A6eAAq«ALÞðAXL6Ac¹|Ao&ÁAzA §A·JAmîA$AÛ4AØA¥H{Aªÿ
+A°µÁA¶ldAŒ#AÁÙ«AÇNAÍFòAÒýAØŽ8AÞjÜAä!AéØ"AïÅAõEhAúü
+B YXB4ªBûBëLB
+ÆB¡ðB}ABXB3åB6B
+êBÅÚB"¡+B%|}B(WÏB+3 B.rB0éÃB3ÅB6 gB9{žB<W
+B?2\BB
+­BDèÿBGÄPBJ¢BMzôBPVEBS1BV
+éBXè:B[ÃB^ÞBaz/BdUBg0ÓBj
+$BlçvBoÂÇBrBuykBxTŒB{0B~
+`B~5 ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A<A
+ïíA*]3A5ÊxAA7ŸAL¥AXIAcAnìÔAzZAã°ATAP÷AAŸ>AtáA¥+Aªâ(A°ËA¶OnAŒAÁŒŽAÇsXAÍ)ûAÒàAØBAÞMåAäAé»,AïqÏAõ(rAúßB JÜB&.BBÜÒB
+ž#BtBnÆBJB%iB »B
+Ü
+B·^B"°B%nB(ISB+$¥B-ÿ÷B0ÛHB3¶B6ëB9m=B<HB?#àBAÿ2BDÚBGµÕBJ'BMlxBPGÊBS#
+BUþmBXÙ¿B[µB^bBakŽBdGBg"WBiý©BlØûBoŽLBrBujïBxFAB{!B}üäB~&¥¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A*>ÚA5A@ýÑALkAWØ\AcE¡An²çAz .AÆ¹A}]A4 Aê€A¡GAWêA¥AªÅ1A°{ÔA¶2xA»éAÁŸAÇVaAÍ
+AÒÃšAØzKAÞ0îAãçAé5AïTØAõ
+|AúÂB <aB³BóBÎVB
+©šBúB`KB;BîBò@B
+ÍBšãB"5B%_B(:ØB+*B-ñ{B0ÌÍB3šB6pB9^ÂB<:B?eBAð·BDÌBG§ZBJ«BM]ýBP9OBS BUïòBXËDB[ŠB^çBa]9Bd8BgÜBiï.BlÊBo¥ÑBr#Bu\tBx7ÆB{B}îiB~*¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A@ßwAL1(AWnAc
+³AnxùAyæ>A©ÃA`fAAÍ¬AOA:óA€ñAªš9A°^ÝA¶A»Ì#AÁÇAÇ9jAÌð
+AÒŠ°AØ]SAÞ÷AãÊAé=Aï7áAôîAú¥'B -äB	6BäB¿ÚB
+,Bv}BQÏB-!BrBãÃB
+¿BgB"užB%Q
+B(,\B+­B-âÿB0ŸQB3¢B6tôB9PFB<+B?éBAâ:BDœBGÞBJt/BMOBP*ÒBS$BUávBXŒÇB[B^skBaNŒBd*Bg`Bià±BlŒBoUBrrŠBuMøBx)JB{B}ßíB~	®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AWAbÑÆAn?
+Ay¬QAÌACoAúA°¶AgXA
+üA€ÔAªCA°AæAµøA»¯-AÁeÐAÇ
+sAÌÓAÒºAØ@]AÝ÷ Aã­£AédGAïêAôÑAú0B iBú»BÖ
+B±^B
+°BhBCTB
+¥Bù÷BÕIB
+°BëB"g=B%BB(
+àB*ù2B-ÔB0¯ÕB3'B6fyB9AÊB<
+
+B>ønBAÓ¿BD¯BGbBJeŽBMABP
+WBR÷©BUÒúBX®LB[B^dïBa@ABdBföäBiÒ6Bl­BoÙBrd+Bu?}BxÎBzö B}ÑrB}û3¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  An ²AyrdAoÕA&yAÝ
+A¿AJcAA€·šAªnLA°$ïAµÛA»6AÁHÙAÆÿ}AÌ¶ AÒlÃAØ#gAÝÚ
+Aã­AéGPAîýóAôŽAúk:B îBì?BÇB¢ãB
+~4BYB4ØB*Bë|BÆÍB
+¢B}qB"XÂB%4B(eB*ê·B-ÆB0¡ZB3|¬B6WýB93OB<¡B>éòBAÅDBD BG{çBJW9BM2BP
+ÜBRé.BUÄBXÑB[{"B^VtBa1ÆBd
+BfèiBiÃ»Bl
+Boz^BrU°Bu1Bx
+SBzç¥B}ÂöB}ìž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A`©A	AÀ%AvÉA-lAäA€³AªQVA°øAµŸA»u?AÁ+ãAÆâAÌ)AÒOÍAØpAÝœAãs·Aé*ZAîàýAô AúNCB sBÝÅB¹BgB
+o¹BK
+B&\B®BÝ BžRB
+€BnõB"JGB%%B( êB*Ü;B-·B0ßB3n0B6IB9$ÔB< %B>ÛwBA¶ÉBDBGmlBJHŸBM$BOÿaBRÚ²BU¶BXVB[l§B^GùBa#JBcþBfÙîBiµ?BlBokãBrG4Bu"BwýØBzÙ)B}Ž{B}Þ=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A°ùAYÒAuAÇA€}ŒAª4_A¯ëAµ¡ŠA»XHAÁìAÆÅAÌ|3AÒ2ÖA×éyAÝ 
+AãVÀAé
+cAîÄAôzªAú1MAÿçïBÏIBªB
+íB
+a>B<BáBó3BÎB©ÖB
+
+(B`zB";ÌB%
+B'òoB*ÍÁB-©B0cB3_µB6;B9XB;ñªB>ÌüBAšMBDBG^ñBJ:BBMBOðæBRÌ7BU§BXÚB[^,B^9~BaÏBcð!BfËrBiŠÄBlBo]gBr8¹Bu
+Bwï\BzÊ®B}Š B}ÏÁ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AIAª"A€`ÅAªiA¯Î
+Aµ¯A»;SAÀñöAÆšAÌ_<AÒßA×ÌAÝ&Aã9ÉAèðmAî§Aô]³AúWAÿÊøBÀÎB BwqB
+RÃB.B	fBä·BÀ	B[B
+v¬BQþB"-PB%¢B'ãôB*¿EB-B0uéB3Q:B6,B9ÝB;ã/B>ŸBAÒBDu$BGPuBJ+ÇBMBOâjBRœŒBUBXt_B[O±B^+BaTBcáŠBfŒ÷BiIBlsBoNìBr*>BuBwàáBzŒ3B}B}ÁF¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A€QA©úrA¯±Aµg¹A»
+\AÀÔÿAÆ£AÌBFAÑøèA×¯AÝf/Aã
+ÓAèÓvAîAô@œAù÷`Aÿ®B²SB€BhöB
+DHBBúëBÖ=B±BßB
+h1BCB"
+ÔB$ú&B'ÕxB*°ÊB-
+B0gmB3B¿B6
+B8ùbB;Ô³B>°BAWBDfšBGAúBJ
+LBLøBOÓïBR¯ABUBXeäB[A6B^
+B`÷ÙBcÓ*Bf®|BiÎBleBo@qBrÂBt÷BwÒfBz­·B}	B}²Ë¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A¯¡éAµJÂA»eAÀž	AÆn¬AÌ%OAÑÛóA×AÝI8AâÿÜAè¶Aîm#Aô#ÆAùÚiAÿ
+B£×B)BZ{B
+5ÌB
+BìpBÇÁB£B~eB
+Y¶B5B"YB$ë«B'ÆüB*¢NB-} B0XòB34DB6B8êçB;Æ9B>¡BA|ÛBDX-BG3BJÐBLê"BOÅtBR ÅBU|BXWiB[2ºB^
+B`é^BcÄ¯Bf Bi{RBlV€Bo1öBr
+GBtèBwÃêBz<B}zB}€O¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aºò9AÀAÆQµAÌYAÑŸüA×uAÝ,CAââæAèAîP,AôÏAùœsAÿtB\Bp®BKÿB
+'QB£BÝôB¹FBBoéB
+K;B&B"ÞB$Ý/B'žB*ÓB-o$B0JvB3%ÈB6B8ÜlB;·œB>BAnaBDI²BG%BJ UBLÛ§BO¶øBRJBUmBXHíB[$?B]ÿB`ÚâBc¶4BfBil×BlH)Bo#zBqþÌBtÚ
+BwµoBzÁB}lB}Ô¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÆBAËëbAÑ¢A×X©AÝLAâÅïAè|Aî36AóéØAù |AÿWBáBb3B=B
+ÖB
+ô'BÏyBªËB
+BanB
+<ÀBB!ócB$ÎµB'ªB*
+WB-`©B0;ûB3LB5òB8ÍðB;©BB>BA_åBD;7BGBIñÚBLÍ+BOš}BRÏBU_ BX:rB[ÄB]ñB`ÌgBc§¹Bf
+Bi^\Bl9®BoÿBqðQBtË¢BwŠôBzFB}]B}Y¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÑÙA×;²AÜòUAâšùAè_Aî?AóÌãAùAÿ:'BxfBS·B/	B
+
+[B
+å¬BÀþBOBw¡BRóB
+.DB	B!äèB$À9B'B*vÝB-R.B0-B3ÑB5ä#B8¿tB;ÆB>vBAQjBD,ŒBG
+BIã_BLŸ±BOBRuSBUP¥BX+÷B[HB]âB`œìBc=BftBiOáBl+2BoBqáÖBtœ'BwyBzsÊB}O
+B}xÞ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÜã)AâAèB¥AíùIAó¯ìAùfAÿ
+1BiêBE<B B
+ûßB
+×1B²BÔBi&BDwB
+ÉB
+ûB!ÖlB$±ŸB'B*haB-C³B0B2úVB5Õ§B8°ùB;KB>gBABîBD
+@BFùBIÔäBL°5BOBRfÙBUB*BX
+{BZøÍB]ÔB`¯pBcÂBffBiAeBl
+·Bnø	BqÓZBt®¬BwþBzeOB}@¡B}jb¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aè3yAíÜRAóõAùIAÿ ;B[oB6ÁBB
+ídB
+È¶B€BYBZ«B5üB
+NB
+ìB!ÇñB$£CB'~B*YæB-58B0B2ëÛB5Ç-B8¢~B;}ÏB>Y!BA4sBDÄBFëBIÆhBL¡ºBO}
+BRX]BU3¯BXBZêRB]Å£B` õBc|GBfWBi2êBl<BnéBqÄßBt 1Bw{BzVÔB}2&B}[ç¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AóÉAù,¢AþãDBLôB(EBB
+ÞéB
+º:BBpÞBL/B'B
+ÓB
+Þ$B!¹vB$ÇB'pB*KkB-&ŒB0B2Ý`B5ž±B8B;oUB>JŠBA%÷BDIBFÜBI·ìBL>BOnBRIâBU%4BX 
+BZÛ×B]·)B`zBcmËBfI
+Bi$oBkÿÀBnÛBq¶dBtµBwmBzHYB}#ªB}Ml¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AþÔB>xBÊBõ
+B
+ÐmB
+«¿BBbbB=ŽBBôWB
+Ï©B!ªûB$LB'aB*<ïB-AB/óB2ÎäB5ª6B8
+B;`ÙB><+BA}BCòÎBFÎBI©qBLÃBO`BR;fBUžBWò
+BZÍ\B]š­B`ÿBc_QBf:¢BióBkñEBnÌBq§èBt:Bw^Bz9ÝB}/B}>ñ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B4Bæ B
+ÁòB
+DBxBSçB/9B
+BåÜB
+Á.B!B$wÑB'S#B*.tB-	ÆB/åB2ÀiB5»B8w
+B;R^B>-°BA	BCäSBF¿¥BIöBLvGBOQBR,ëBU<BWãBZŸàB]2B`uBcPÕBf,'BiyBkâÊBnŸBqmBtt¿BwPBz+bB}ŽB}0u¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+º\B
+ÈBjBElB œBüB×aB
+²²B!B$iVB'D§B*ùB,ûKB/ÖB2±îB5?B8hB;CãB>4B@úBCÕØBF±)BI{BLgÍBOC
+BR
+oBTùÁBWÕBZ°dB]¶B`gBcBZBf
+¬BhøýBkÔOBn¯¡BqòBtfCBwABz
+çB|ø8B}!ú¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BbB6ïBABíBÈäB
+€6B!B$ZÙB'6+B*}B,ìÎB/È B2£rB5~ÃB8ZB;5fB>žB@ì
+BCÇ[BF¢­BI}ÿBLYPBO4¢BRôBTëEBWÆBZ¡èB]}:B`XBc3ÝBf/BhêBkÅÓBn¡$Bq|vBtWÈBw3BzjB|éŒB}¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+«BßBºiB
+»B!q
+B$L^B''°B*B,ÞSB/¹¥B2öB5pHB8KB;&ëB>=B@ÝBCžàBF2BIoBLJÕBO&'BRxBTÜÊBWž
+BZmB]nŸB`JBc%bBf ³BhÜBk·WBn©BqmûBtILBw$ByÿðB|ÛAB}¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B²ÓB
+?B!bB$=ãB'4B)ôB,ÏØB/«)B2{B5aÍB8=
+B;pB=óÂB@ÏBCªeBF
+¶BIaBL<ZBO«BQòýBTÎOBW© BZòB]`DB`;BcæBeò8BhÍBkšÛBn-Bq_Bt:ÑBw#ByñtB|ÌÆB|ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B!ZûB$/gB'
+¹B)æ
+B,Á\B/®B2x B5SQB8.£B;	õB=åFB@ÀBCêBFw;BIRBL-ÞBO	0BQäBT¿ÓBW%BZvwB]QÈB`-BclBeãœBh¿Bk`Bnu²BqQBt,UBw§ByâùB|ŸKB|è
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B'#B)×B,²áB/3B2iB5DÖB8 (B:ûyB=ÖËB@²
+BCnBFhÀBIDBLcBNúµBQÖBT±XBWªBZgûB]CMB`
+BbùðBeÕBBh°BkåBng6BqBBt
+ÚBvù+ByÔ}B|¯ÏB|Ù¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B,«JB/¶B2[B56ZB8«B:ìýB=ÈOB@£ BC~òBFZDBI5BLçBNì9BQÇBT¢ÜBW~-BZYB]4ÑB`"BbëtBeÆÆBh¢Bk}iBnX»Bq4
+Bt]Bvê¯ByÆB|¡RB|Ë¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B2SrB5'ÞB80B:ÞB=¹ÓB@%BCpwBFKÈBI'BLlBNÝœBQ¹BTaBWo²BZKB]&UB`§BbÜùBežJBhBknîBnJ?Bq%Bt ãBvÜ4By·
+B|×B|Œ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B7ûB:ÐB=«XB@ªBCaûBF=MBIBKóðBNÏBBQªBT
+åBWa7BZ<B]ÚB_ó,BbÎ}Be©ÏBh
+!Bk`rBn;ÄBqBsògBvÍ¹By©
+B|\B|®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B=£ÂB@x.BCSBF.ÒBI
+#BKåuBNÀÇBQBTwjBWRŒBZ.
+B]	_B_ä±BbÀBeTBhv¥BkQ÷Bn-IBqBsãìBv¿>ByB|uáB|¥¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BCKéBF UBHû§BKÖùBN²JBQBThîBWD?BZB\úãB_Ö4Bb±BeØBhh)BkC{Bn
+ÌBpú
+BsÕpBv°ÁByB|geB|)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BHôBKÈ}BN£ÏBQ!BTZrBW5ÄBZB\ìgB_Ç¹Bb£
+Be~\BhY®Bk5 BnQBpë£BsÆôBv¢FBy}B|XéB|®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BN9BQp¥BTK÷BW'IBZB\ÝìB_¹>BbBeoáBhK3Bk&BnÖBpÝ(BsžyBvËByo
+B|JnB|t3¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BTDaBWÍBYôB\ÏqB_ªÂBbBeafBh<·Bk	Bmó[BpÎ¬Bs©þBv
+PBy`¡B|;óB|e·¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BYìB\ÀôB_FBbwBeRéBh.;Bk	BmäÞBpÀ0BsBvvÓByR%B|-wB|W<¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B_°Bbi
+BeDnBhÀBjûBmÖcBp±µBsBvhXByCªB|
+ûB|HÁ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Be<ØBhDBjìBmÇèBp£9Bs~BvYÝBy5.B|B|:F¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bjå Bm¹lBpŸBspBvKaBy&³B|B|+Ê¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bp'BsaBv<åBy7B{óB|
+O¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bv5OBy	»B{å
+B|Ô¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B{ÝwB| X¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 <#×
+<£×
+<õÂ=#×
+=LÌÍ=uÂ=\)=£×
+=žQì=ÌÌÍ=áG®=õÂ>
+ž>\)>>#×
+>.{>8Qì>B\>LÌÍ>W
+=>aG®>k
+>uÂ>  >
+
+ž>=q>\)>zá>>žR>£×
+>šõÃ>®{>³33>žQì>œp€>Â\>Ç®>ÌÌÍ>Ñë
+>×
+=>Ü(ö>áG®>æff>ë
+>ð£×>õÂ>úáH?   ?\?
+ž?®?
+=q?
+ÌÍ?\)?ë
+?zá?
+=??
+(ö?
+žR?!G®?  ?G®?\?×
+?
+
+ž?ff?®?õÃ?=q?
+?ÌÍ?{?\)?£×?ë
+?33?zá?Â?
+>?Qì??áH?(ö?p€?žR?   ?¡G®?¢\?£×
+?¥
+ž?Šff?§®?šõÂ?ª=q?«
+?¬ÌÍ?®{?¯\)?°£×?±ë
+?³33?Žzá?µÂ?·
+>?žQì?¹?ºáH?Œ(ö?œp€?ŸžR?À  ?ÁG®?Â\?Ã×
+?Å
+ž?Æff?Ç®?ÈõÂ?Ê=p?Ë
+
+?ÌÌÍ?Î{?Ï\)?Ð£×@   @ £×@G®@ë
+@\@33@×
+@zá@
+ž@Â@ff@
+=@®@Qì@õÃ@	@
+=q@
+áH@
+
+@
+(ö@
+ÌÍ@
+p€@{@žR@\)@  @£×@G®@ë
+@\@33@×
+@zá@
+ž@Â@ff@
+>@®@Qì@õÂ@@=q@áH@
+@
+(ö@
+ÌÍ@
+p€@
+{@
+žR@\)@   @ £×@!G®@!ë
+@"\@#33@#×
+@$zá@%
+ž@%Â@&ff@'
+>@'®@(Qì@@  @@£×@AG®@Aë
+@B\@C33@C×
+@Dzá@E
+ž@EÂ@Fff@G
+=@G®@HQì@HõÃ@I@J=q@JáH@K
+@L(ö@LÌÍ@Mp€@N{@NžR@O\)@P  @P£×@QG®@Që
+@R\@S33@S×
+@Tzá@U
+ž@UÂ@Vff@W
+>@W®@XQì@XõÂ@Y@Z=q@ZáH@[
+@\(ö@\ÌÍ@]p€@^{@^žR@_\)@`  @`£×@aG®@aë
+@b\@c33@c×
+@dzá@e
+ž@eÂ@fff@g
+>@g®@hQì@  @Qì@£×@õÃ@G®@@ë
+@=q@\@áH@33@
+@×
+@(ö@zá@ÌÍ@
+
+ž@
+p€@
+Â@{@ff@žR@
+=@\)@®@  @Qì@£×@õÃ@G®@@ë
+@=q@\@áH@33@
+@×
+@(ö@zá@ÌÍ@
+ž@p€@Â@{@ff@žR@
+=@\)@®@  @Qì@£×@õÂ@G®@@ë
+@=q@\@áH@33@
+@×
+@(ö@   @ Qì@ £×@ õÃ@¡G®@¡@¡ë
+@¢=q@¢\@¢áH@£33@£
+@£×
+@€(ö@€zá@€ÌÍ@¥
+ž@¥p€@¥Â@Š{@Šff@ŠžR@§
+=@§\)@§®@š  @šQì@š£×@šõÃ@©G®@©@©ë
+@ª=q@ª\@ªáH@«33@«
+@«×
+@¬(ö@¬zá@¬ÌÍ@­
+ž@­p€@­Â@®{@®ff@®žR@¯
+=@¯\)@¯®@°  @°Qì@°£×@°õÂ@±G®@±@±ë
+@²=q@²\@²áH@³33@³
+@³×
+@Ž(ö@À  @ÀQì@À£×@ÀõÃ@ÁG®@Á@Áë
+@Â=q@Â\@ÂáH@Ã33@Ã
+@Ã×
+@Ä(ö@Äzá@ÄÌÍ@Å
+ž@Åp€@ÅÂ@Æ{@Æff@ÆžR@Ç
+=@Ç\)@Ç®@È  @ÈQì@È£×@ÈõÃ@ÉG®@É@Éë
+@Ê=q@Ê\@ÊáH@Ë33@Ë
+@Ë×
+@Ì(ö@Ìzá@ÌÌÍ@Í
+ž@Íp€@ÍÂ@Î{@Îff@ÎžR@Ï
+=@Ï\)@Ï®@Ð  @ÐQì@Ð£×@ÐõÂ@ÑG®@Ñ@Ñë
+@Ò=q@Ò\@ÒáH@Ó33@Ó
+@Ó×
+@Ô(ö@à  @àQì@à£×@àõÃ@áG®@á@áë
+@â=q@â\@âáH@ã33@ã
+@ã×
+@ä(ö@äzá@äÌÍ@å
+ž@åp€@åÂ@æ{@æff@æžR@ç
+=@ç\)@ç®@è  @èQì@è£×@èõÃ@éG®@é@éë
+@ê=q@ê\@êáH@ë33@ë
+@ë×
+@ì(ö@ìzá@ìÌÍ@í
+ž@íp€@íÂ@î{@îff@îžR@ï
+=@ï\)@ï®@ð  @ðQì@ð£×@ðõÂ@ñG®@ñ@ñë
+@ò=q@ò\@òáH@ó33@ó
+@ó×
+@ô(öA   A (öA QìA záA £×A ÌÍA õÃA
+žAG®Ap€AAÂAë
+A{A=qAffA\AžRAáHA
+=A33A\)A
+A®A×
+A  A(öAQìAzáA£×AÌÍAõÃA
+žAG®Ap€AAÂAë
+A{A=qAffA\AžRAáHA
+=A33A\)A
+A®A×
+A  A(öAQìAzáA£×AÌÍAõÃA	
+žA	G®A	p€A	A	ÂA	ë
+A
+{A  A(öAQìAzáA£×AÌÍAõÃA
+žAG®Ap€AAÂAë
+A{A=qAffA\AžRAáHA
+=A33A\)A
+A®A×
+A  A(öAQìAzáA£×AÌÍAõÃA
+žAG®Ap€AAÂAë
+A{A=qAffA\AžRAáHA
+=A33A\)A
+A®A×
+A  A(öAQìAzáA£×AÌÍAõÃA
+žAG®Ap€AAÂAë
+A{A   A (öA QìA záA £×A ÌÍA õÃA!
+žA!G®A!p€A!A!ÂA!ë
+A"{A"=qA"ffA"\A"žRA"áHA#
+=A#33A#\)A#
+A#®A#×
+A$  A$(öA$QìA$záA$£×A$ÌÍA$õÃA%
+žA%G®A%p€A%A%ÂA%ë
+A&{A&=qA&ffA&\A&žRA&áHA'
+=A'33A'\)A'
+A'®A'×
+A(  A((öA(QìA(záA(£×A(ÌÍA(õÃA)
+žA)G®A)p€A)A)ÂA)ë
+A*{A0  A0(öA0QìA0záA0£×A0ÌÍA0õÃA1
+žA1G®A1p€A1A1ÂA1ë
+A2{A2=qA2ffA2\A2žRA2áHA3
+=A333A3\)A3
+A3®A3×
+A4  A4(öA4QìA4záA4£×A4ÌÍA4õÃA5
+žA5G®A5p€A5A5ÂA5ë
+A6{A6=qA6ffA6\A6žRA6áHA7
+=A733A7\)A7
+A7®A7×
+A8  A8(öA8QìA8záA8£×A8ÌÍA8õÃA9
+žA9G®A9p€A9A9ÂA9ë
+A:{A@  A@(öA@QìA@záA@£×A@ÌÍA@õÃAA
+žAAG®AAp€AAAAÂAAë
+AB{AB=qABffAB\ABžRABáHAC
+=AC33AC\)AC
+AC®AC×
+AD  AD(öADQìADzáAD£×ADÌÍADõÃAE
+žAEG®AEp€AEAEÂAEë
+AF{AF=qAFffAF\AFžRAFáHAG
+=AG33AG\)AG
+AG®AG×
+AH  AH(öAHQìAHzáAH£×AHÌÍAHõÃAI
+žAIG®AIp€AIAIÂAIë
+AJ{AP  AP(öAPQìAPzáAP£×APÌÍAPõÃAQ
+žAQG®AQp€AQAQÂAQë
+AR{AR=qARffAR\ARžRARáHAS
+=AS33AS\)AS
+AS®AS×
+AT  AT(öATQìATzáAT£×ATÌÍATõÃAU
+žAUG®AUp€AUAUÂAUë
+AV{AV=qAVffAV\AVžRAVáHAW
+=AW33AW\)AW
+AW®AW×
+AX  AX(öAXQìAXzáAX£×AXÌÍAXõÃAY
+žAYG®AYp€AYAYÂAYë
+AZ{A`  A`(öA`QìA`záA`£×A`ÌÍA`õÃAa
+žAaG®Aap€AaAaÂAaë
+Ab{Ab=qAbffAb\AbžRAbáHAc
+=Ac33Ac\)Ac
+Ac®Ac×
+Ad  Ad(öAdQìAdzáAd£×AdÌÍAdõÃAe
+žAeG®Aep€AeAeÂAeë
+Af{Af=qAfffAf\AfžRAfáHAg
+=Ag33Ag\)Ag
+Ag®Ag×
+Ah  Ah(öAhQìAhzáAh£×AhÌÍAhõÃAi
+žAiG®Aip€AiAiÂAië
+Aj{Ap  Ap(öApQìApzáAp£×ApÌÍApõÃAq
+žAqG®Aqp€AqAqÂAqë
+Ar{Ar=qArffAr\AržRAráHAs
+=As33As\)As
+As®As×
+At  At(öAtQìAtzáAt£×AtÌÍAtõÃAu
+žAuG®Aup€AuAuÂAuë
+Av{Av=qAvffAv\AvžRAváHAw
+=Aw33Aw\)Aw
+Aw®Aw×
+Ax  Ax(öAxQìAxzáAx£×AxÌÍAxõÃAy
+žAyG®Ayp€AyAyÂAyë
+Az{A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+
+=A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A   A {A (öA =qA QìA ffA záA \A £×A žRA ÌÍA áHA õÃA¡
+=A¡
+žA¡33A¡G®A¡\)A¡p€A¡
+A¡A¡®A¡ÂA¡×
+A¡ë
+A¢  A¢{A¢(öA¢=qA¢QìA¢ffA¢záA¢\A¢£×A¢žRA¢ÌÍA¢áHA¢õÃA£
+=A£
+žA£33A£G®A£\)A£p€A£
+A£A£®A£ÂA£×
+A£ë
+A€  A€{A€(öA€=qA€QìA€ffA€záA€\A€£×A€žRA€ÌÍA€áHA€õÃA¥
+=Aš  Aš{Aš(öAš=qAšQìAšffAšzáAš\Aš£×AšžRAšÌÍAšáHAšõÃA©
+=A©
+žA©33A©G®A©\)A©p€A©
+A©A©®A©ÂA©×
+A©ë
+Aª  Aª{Aª(öAª=qAªQìAªffAªzáAª\Aª£×AªžRAªÌÍAªáHAªõÃA«
+=A«
+žA«33A«G®A«\)A«p€A«
+A«A«®A«ÂA«×
+A«ë
+A¬  A¬{A¬(öA¬=qA¬QìA¬ffA¬záA¬\A¬£×A¬žRA¬ÌÍA¬áHA¬õÃA­
+=A°  A°{A°(öA°=qA°QìA°ffA°záA°\A°£×A°žRA°ÌÍA°áHA°õÃA±
+=A±
+žA±33A±G®A±\)A±p€A±
+A±A±®A±ÂA±×
+A±ë
+A²  A²{A²(öA²=qA²QìA²ffA²záA²\A²£×A²žRA²ÌÍA²áHA²õÃA³
+=A³
+žA³33A³G®A³\)A³p€A³
+A³A³®A³ÂA³×
+A³ë
+AŽ  AŽ{AŽ(öAŽ=qAŽQìAŽffAŽzáAŽ\AŽ£×AŽžRAŽÌÍAŽáHAŽõÃAµ
+=Až  Až{Až(öAž=qAžQìAžffAžzáAž\Až£×AžžRAžÌÍAžáHAžõÃA¹
+=A¹
+žA¹33A¹G®A¹\)A¹p€A¹
+A¹A¹®A¹ÂA¹×
+A¹ë
+Aº  Aº{Aº(öAº=qAºQìAºffAºzáAº\Aº£×AºžRAºÌÍAºáHAºõÃA»
+=A»
+žA»33A»G®A»\)A»p€A»
+A»A»®A»ÂA»×
+A»ë
+AŒ  AŒ{AŒ(öAŒ=qAŒQìAŒffAŒzáAŒ\AŒ£×AŒžRAŒÌÍAŒáHAŒõÃAœ
+=AÀ  AÀ{AÀ(öAÀ=qAÀQìAÀffAÀzáAÀ\AÀ£×AÀžRAÀÌÍAÀáHAÀõÃAÁ
+=AÁ
+žAÁ33AÁG®AÁ\)AÁp€AÁ
+AÁAÁ®AÁÂAÁ×
+AÁë
+AÂ  AÂ{AÂ(öAÂ=qAÂQìAÂffAÂzáAÂ\AÂ£×AÂžRAÂÌÍAÂáHAÂõÃAÃ
+=AÃ
+žAÃ33AÃG®AÃ\)AÃp€AÃ
+AÃAÃ®AÃÂAÃ×
+AÃë
+AÄ  AÄ{AÄ(öAÄ=qAÄQìAÄffAÄzáAÄ\AÄ£×AÄžRAÄÌÍAÄáHAÄõÃAÅ
+=AÈ  AÈ{AÈ(öAÈ=qAÈQìAÈffAÈzáAÈ\AÈ£×AÈžRAÈÌÍAÈáHAÈõÃAÉ
+=AÉ
+žAÉ33AÉG®AÉ\)AÉp€AÉ
+AÉAÉ®AÉÂAÉ×
+AÉë
+AÊ  AÊ{AÊ(öAÊ=qAÊQìAÊffAÊzáAÊ\AÊ£×AÊžRAÊÌÍAÊáHAÊõÃAË
+=AË
+žAË33AËG®AË\)AËp€AË
+AËAË®AËÂAË×
+AËë
+AÌ  AÌ{AÌ(öAÌ=qAÌQìAÌffAÌzáAÌ\AÌ£×AÌžRAÌÌÍAÌáHAÌõÃAÍ
+=AÐ  AÐ{AÐ(öAÐ=qAÐQìAÐffAÐzáAÐ\AÐ£×AÐžRAÐÌÍAÐáHAÐõÃAÑ
+=AÑ
+žAÑ33AÑG®AÑ\)AÑp€AÑ
+AÑAÑ®AÑÂAÑ×
+AÑë
+AÒ  AÒ{AÒ(öAÒ=qAÒQìAÒffAÒzáAÒ\AÒ£×AÒžRAÒÌÍAÒáHAÒõÃAÓ
+=AÓ
+žAÓ33AÓG®AÓ\)AÓp€AÓ
+AÓAÓ®AÓÂAÓ×
+AÓë
+AÔ  AÔ{AÔ(öAÔ=qAÔQìAÔffAÔzáAÔ\AÔ£×AÔžRAÔÌÍAÔáHAÔõÃAÕ
+=AØ  AØ{AØ(öAØ=qAØQìAØffAØzáAØ\AØ£×AØžRAØÌÍAØáHAØõÃAÙ
+=AÙ
+žAÙ33AÙG®AÙ\)AÙp€AÙ
+AÙAÙ®AÙÂAÙ×
+AÙë
+AÚ  AÚ{AÚ(öAÚ=qAÚQìAÚffAÚzáAÚ\AÚ£×AÚžRAÚÌÍAÚáHAÚõÃAÛ
+=AÛ
+žAÛ33AÛG®AÛ\)AÛp€AÛ
+AÛAÛ®AÛÂAÛ×
+AÛë
+AÜ  AÜ{AÜ(öAÜ=qAÜQìAÜffAÜzáAÜ\AÜ£×AÜžRAÜÌÍAÜáHAÜõÃAÝ
+=Aà  Aà{Aà(öAà=qAàQìAàffAàzáAà\Aà£×AàžRAàÌÍAàáHAàõÃAá
+=Aá
+žAá33AáG®Aá\)Aáp€Aá
+AáAá®AáÂAá×
+Aáë
+Aâ  Aâ{Aâ(öAâ=qAâQìAâffAâzáAâ\Aâ£×AâžRAâÌÍAâáHAâõÃAã
+=Aã
+žAã33AãG®Aã\)Aãp€Aã
+AãAã®AãÂAã×
+Aãë
+Aä  Aä{Aä(öAä=qAäQìAäffAäzáAä\Aä£×AäžRAäÌÍAäáHAäõÃAå
+=Aè  Aè{Aè(öAè=qAèQìAèffAèzáAè\Aè£×AèžRAèÌÍAèáHAèõÃAé
+=Aé
+žAé33AéG®Aé\)Aép€Aé
+AéAé®AéÂAé×
+Aéë
+Aê  Aê{Aê(öAê=qAêQìAêffAêzáAê\Aê£×AêžRAêÌÍAêáHAêõÃAë
+=Aë
+žAë33AëG®Aë\)Aëp€Aë
+AëAë®AëÂAë×
+Aëë
+Aì  Aì{Aì(öAì=qAìQìAìffAìzáAì\Aì£×AìžRAìÌÍAìáHAìõÃAí
+=Að  Að{Að(öAð=qAðQìAðffAðzáAð\Að£×AðžRAðÌÍAðáHAðõÃAñ
+=Añ
+žAñ33AñG®Añ\)Añp€Añ
+AñAñ®AñÂAñ×
+Añë
+Aò  Aò{Aò(öAò=qAòQìAòffAòzáAò\Aò£×AòžRAòÌÍAòáHAòõÃAó
+=Aó
+žAó33AóG®Aó\)Aóp€Aó
+AóAó®AóÂAó×
+Aóë
+Aô  Aô{Aô(öAô=qAôQìAôffAôzáAô\Aô£×AôžRAôÌÍAôáHAôõÃAõ
+=Aø  Aø{Aø(öAø=qAøQìAøffAøzáAø\Aø£×AøžRAøÌÍAøáHAøõÃAù
+=Aù
+žAù33AùG®Aù\)Aùp€Aù
+AùAù®AùÂAù×
+Aùë
+Aú  Aú{Aú(öAú=qAúQìAúffAúzáAú\Aú£×AúžRAúÌÍAúáHAúõÃAû
+=Aû
+žAû33AûG®Aû\)Aûp€Aû
+AûAû®AûÂAû×
+Aûë
+Aü  Aü{Aü(öAü=qAüQìAüffAüzáAü\Aü£×AüžRAüÌÍAüáHAüõÃAý
+=B   B 
+=B {B 
+žB (öB 33B =qB G®B QìB \)B ffB p€B záB 
+B \B B £×B ®B žRB ÂB ÌÍB ×
+B áHB ë
+B õÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB	  B	
+=B	{B	
+žB	(öB	33B	=qB	G®B	QìB	\)B	ffB	p€B	záB	
+B	\B	B	£×B	®B	žRB	ÂB	ÌÍB	×
+B	áHB	ë
+B	õÃB
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+\B
+B
+£×B
+®B
+žRB
+ÂB
+ÌÍB
+×
+B
+áHB
+ë
+B
+õÃB
+  B
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+\B
+B
+£×B
+®B
+žRB
+ÂB
+ÌÍB
+×
+B
+áHB
+ë
+B
+õÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+\B
+B
+£×B
+®B
+žRB
+ÂB
+ÌÍB
+×
+B
+áHB
+ë
+B
+õÃB
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+\B
+B
+£×B
+®B
+žRB
+ÂB
+ÌÍB
+×
+B
+áHB
+ë
+B
+õÃB
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B   B 
+=B {B 
+žB (öB 33B =qB G®B QìB \)B ffB p€B záB 
+B \B B £×B ®B žRB ÂB ÌÍB ×
+B áHB ë
+B õÃB!  B!
+=B!{B!
+žB!(öB!33B!=qB!G®B!QìB!\)B!ffB!p€B!záB!
+B!\B!B!£×B!®B!žRB!ÂB!ÌÍB!×
+B!áHB!ë
+B!õÃB"  B"
+=B"{B"
+žB"(öB"33B"=qB"G®B"QìB"\)B"ffB"p€B"záB"
+B$  B$
+=B${B$
+žB$(öB$33B$=qB$G®B$QìB$\)B$ffB$p€B$záB$
+B$\B$B$£×B$®B$žRB$ÂB$ÌÍB$×
+B$áHB$ë
+B$õÃB%  B%
+=B%{B%
+žB%(öB%33B%=qB%G®B%QìB%\)B%ffB%p€B%záB%
+B%\B%B%£×B%®B%žRB%ÂB%ÌÍB%×
+B%áHB%ë
+B%õÃB&  B&
+=B&{B&
+žB&(öB&33B&=qB&G®B&QìB&\)B&ffB&p€B&záB&
+B(  B(
+=B({B(
+žB((öB(33B(=qB(G®B(QìB(\)B(ffB(p€B(záB(
+B(\B(B(£×B(®B(žRB(ÂB(ÌÍB(×
+B(áHB(ë
+B(õÃB)  B)
+=B){B)
+žB)(öB)33B)=qB)G®B)QìB)\)B)ffB)p€B)záB)
+B)\B)B)£×B)®B)žRB)ÂB)ÌÍB)×
+B)áHB)ë
+B)õÃB*  B*
+=B*{B*
+žB*(öB*33B*=qB*G®B*QìB*\)B*ffB*p€B*záB*
+B,  B,
+=B,{B,
+žB,(öB,33B,=qB,G®B,QìB,\)B,ffB,p€B,záB,
+B,\B,B,£×B,®B,žRB,ÂB,ÌÍB,×
+B,áHB,ë
+B,õÃB-  B-
+=B-{B-
+žB-(öB-33B-=qB-G®B-QìB-\)B-ffB-p€B-záB-
+B-\B-B-£×B-®B-žRB-ÂB-ÌÍB-×
+B-áHB-ë
+B-õÃB.  B.
+=B.{B.
+žB.(öB.33B.=qB.G®B.QìB.\)B.ffB.p€B.záB.
+B0  B0
+=B0{B0
+žB0(öB033B0=qB0G®B0QìB0\)B0ffB0p€B0záB0
+B0\B0B0£×B0®B0žRB0ÂB0ÌÍB0×
+B0áHB0ë
+B0õÃB1  B1
+=B1{B1
+žB1(öB133B1=qB1G®B1QìB1\)B1ffB1p€B1záB1
+B1\B1B1£×B1®B1žRB1ÂB1ÌÍB1×
+B1áHB1ë
+B1õÃB2  B2
+=B2{B2
+žB2(öB233B2=qB2G®B2QìB2\)B2ffB2p€B2záB2
+B4  B4
+=B4{B4
+žB4(öB433B4=qB4G®B4QìB4\)B4ffB4p€B4záB4
+B4\B4B4£×B4®B4žRB4ÂB4ÌÍB4×
+B4áHB4ë
+B4õÃB5  B5
+=B5{B5
+žB5(öB533B5=qB5G®B5QìB5\)B5ffB5p€B5záB5
+B5\B5B5£×B5®B5žRB5ÂB5ÌÍB5×
+B5áHB5ë
+B5õÃB6  B6
+=B6{B6
+žB6(öB633B6=qB6G®B6QìB6\)B6ffB6p€B6záB6
+B8  B8
+=B8{B8
+žB8(öB833B8=qB8G®B8QìB8\)B8ffB8p€B8záB8
+B8\B8B8£×B8®B8žRB8ÂB8ÌÍB8×
+B8áHB8ë
+B8õÃB9  B9
+=B9{B9
+žB9(öB933B9=qB9G®B9QìB9\)B9ffB9p€B9záB9
+B9\B9B9£×B9®B9žRB9ÂB9ÌÍB9×
+B9áHB9ë
+B9õÃB:  B:
+=B:{B:
+žB:(öB:33B:=qB:G®B:QìB:\)B:ffB:p€B:záB:
+B<  B<
+=B<{B<
+žB<(öB<33B<=qB<G®B<QìB<\)B<ffB<p€B<záB<
+B<\B<B<£×B<®B<žRB<ÂB<ÌÍB<×
+B<áHB<ë
+B<õÃB=  B=
+=B={B=
+žB=(öB=33B==qB=G®B=QìB=\)B=ffB=p€B=záB=
+B=\B=B=£×B=®B=žRB=ÂB=ÌÍB=×
+B=áHB=ë
+B=õÃB>  B>
+=B>{B>
+žB>(öB>33B>=qB>G®B>QìB>\)B>ffB>p€B>záB>
+B@  B@
+=B@{B@
+žB@(öB@33B@=qB@G®B@QìB@\)B@ffB@p€B@záB@
+B@\B@B@£×B@®B@žRB@ÂB@ÌÍB@×
+B@áHB@ë
+B@õÃBA  BA
+=BA{BA
+žBA(öBA33BA=qBAG®BAQìBA\)BAffBAp€BAzáBA
+BA\BABA£×BA®BAžRBAÂBAÌÍBA×
+BAáHBAë
+BAõÃBB  BB
+=BB{BB
+žBB(öBB33BB=qBBG®BBQìBB\)BBffBBp€BBzáBB
+BD  BD
+=BD{BD
+žBD(öBD33BD=qBDG®BDQìBD\)BDffBDp€BDzáBD
+BD\BDBD£×BD®BDžRBDÂBDÌÍBD×
+BDáHBDë
+BDõÃBE  BE
+=BE{BE
+žBE(öBE33BE=qBEG®BEQìBE\)BEffBEp€BEzáBE
+BE\BEBE£×BE®BEžRBEÂBEÌÍBE×
+BEáHBEë
+BEõÃBF  BF
+=BF{BF
+žBF(öBF33BF=qBFG®BFQìBF\)BFffBFp€BFzáBF
+BH  BH
+=BH{BH
+žBH(öBH33BH=qBHG®BHQìBH\)BHffBHp€BHzáBH
+BH\BHBH£×BH®BHžRBHÂBHÌÍBH×
+BHáHBHë
+BHõÃBI  BI
+=BI{BI
+žBI(öBI33BI=qBIG®BIQìBI\)BIffBIp€BIzáBI
+BI\BIBI£×BI®BIžRBIÂBIÌÍBI×
+BIáHBIë
+BIõÃBJ  BJ
+=BJ{BJ
+žBJ(öBJ33BJ=qBJG®BJQìBJ\)BJffBJp€BJzáBJ
+BL  BL
+=BL{BL
+žBL(öBL33BL=qBLG®BLQìBL\)BLffBLp€BLzáBL
+BL\BLBL£×BL®BLžRBLÂBLÌÍBL×
+BLáHBLë
+BLõÃBM  BM
+=BM{BM
+žBM(öBM33BM=qBMG®BMQìBM\)BMffBMp€BMzáBM
+BM\BMBM£×BM®BMžRBMÂBMÌÍBM×
+BMáHBMë
+BMõÃBN  BN
+=BN{BN
+žBN(öBN33BN=qBNG®BNQìBN\)BNffBNp€BNzáBN
+BP  BP
+=BP{BP
+žBP(öBP33BP=qBPG®BPQìBP\)BPffBPp€BPzáBP
+BP\BPBP£×BP®BPžRBPÂBPÌÍBP×
+BPáHBPë
+BPõÃBQ  BQ
+=BQ{BQ
+žBQ(öBQ33BQ=qBQG®BQQìBQ\)BQffBQp€BQzáBQ
+BQ\BQBQ£×BQ®BQžRBQÂBQÌÍBQ×
+BQáHBQë
+BQõÃBR  BR
+=BR{BR
+žBR(öBR33BR=qBRG®BRQìBR\)BRffBRp€BRzáBR
+BT  BT
+=BT{BT
+žBT(öBT33BT=qBTG®BTQìBT\)BTffBTp€BTzáBT
+BT\BTBT£×BT®BTžRBTÂBTÌÍBT×
+BTáHBTë
+BTõÃBU  BU
+=BU{BU
+žBU(öBU33BU=qBUG®BUQìBU\)BUffBUp€BUzáBU
+BU\BUBU£×BU®BUžRBUÂBUÌÍBU×
+BUáHBUë
+BUõÃBV  BV
+=BV{BV
+žBV(öBV33BV=qBVG®BVQìBV\)BVffBVp€BVzáBV
+BX  BX
+=BX{BX
+žBX(öBX33BX=qBXG®BXQìBX\)BXffBXp€BXzáBX
+BX\BXBX£×BX®BXžRBXÂBXÌÍBX×
+BXáHBXë
+BXõÃBY  BY
+=BY{BY
+žBY(öBY33BY=qBYG®BYQìBY\)BYffBYp€BYzáBY
+BY\BYBY£×BY®BYžRBYÂBYÌÍBY×
+BYáHBYë
+BYõÃBZ  BZ
+=BZ{BZ
+žBZ(öBZ33BZ=qBZG®BZQìBZ\)BZffBZp€BZzáBZ
+B\  B\
+=B\{B\
+žB\(öB\33B\=qB\G®B\QìB\\)B\ffB\p€B\záB\
+B\\B\B\£×B\®B\žRB\ÂB\ÌÍB\×
+B\áHB\ë
+B\õÃB]  B]
+=B]{B]
+žB](öB]33B]=qB]G®B]QìB]\)B]ffB]p€B]záB]
+B]\B]B]£×B]®B]žRB]ÂB]ÌÍB]×
+B]áHB]ë
+B]õÃB^  B^
+=B^{B^
+žB^(öB^33B^=qB^G®B^QìB^\)B^ffB^p€B^záB^
+B`  B`
+=B`{B`
+žB`(öB`33B`=qB`G®B`QìB`\)B`ffB`p€B`záB`
+B`\B`B`£×B`®B`žRB`ÂB`ÌÍB`×
+B`áHB`ë
+B`õÃBa  Ba
+=Ba{Ba
+žBa(öBa33Ba=qBaG®BaQìBa\)BaffBap€BazáBa
+Ba\BaBa£×Ba®BažRBaÂBaÌÍBa×
+BaáHBaë
+BaõÃBb  Bb
+=Bb{Bb
+žBb(öBb33Bb=qBbG®BbQìBb\)BbffBbp€BbzáBb
+Bd  Bd
+=Bd{Bd
+žBd(öBd33Bd=qBdG®BdQìBd\)BdffBdp€BdzáBd
+Bd\BdBd£×Bd®BdžRBdÂBdÌÍBd×
+BdáHBdë
+BdõÃBe  Be
+=Be{Be
+žBe(öBe33Be=qBeG®BeQìBe\)BeffBep€BezáBe
+Be\BeBe£×Be®BežRBeÂBeÌÍBe×
+BeáHBeë
+BeõÃBf  Bf
+=Bf{Bf
+žBf(öBf33Bf=qBfG®BfQìBf\)BfffBfp€BfzáBf
+Bh  Bh
+=Bh{Bh
+žBh(öBh33Bh=qBhG®BhQìBh\)BhffBhp€BhzáBh
+Bh\BhBh£×Bh®BhžRBhÂBhÌÍBh×
+BháHBhë
+BhõÃBi  Bi
+=Bi{Bi
+žBi(öBi33Bi=qBiG®BiQìBi\)BiffBip€BizáBi
+Bi\BiBi£×Bi®BižRBiÂBiÌÍBi×
+BiáHBië
+BiõÃBj  Bj
+=Bj{Bj
+žBj(öBj33Bj=qBjG®BjQìBj\)BjffBjp€BjzáBj
+Bl  Bl
+=Bl{Bl
+žBl(öBl33Bl=qBlG®BlQìBl\)BlffBlp€BlzáBl
+Bl\BlBl£×Bl®BlžRBlÂBlÌÍBl×
+BláHBlë
+BlõÃBm  Bm
+=Bm{Bm
+žBm(öBm33Bm=qBmG®BmQìBm\)BmffBmp€BmzáBm
+Bm\BmBm£×Bm®BmžRBmÂBmÌÍBm×
+BmáHBmë
+BmõÃBn  Bn
+=Bn{Bn
+žBn(öBn33Bn=qBnG®BnQìBn\)BnffBnp€BnzáBn
+Bp  Bp
+=Bp{Bp
+žBp(öBp33Bp=qBpG®BpQìBp\)BpffBpp€BpzáBp
+Bp\BpBp£×Bp®BpžRBpÂBpÌÍBp×
+BpáHBpë
+BpõÃBq  Bq
+=Bq{Bq
+žBq(öBq33Bq=qBqG®BqQìBq\)BqffBqp€BqzáBq
+Bq\BqBq£×Bq®BqžRBqÂBqÌÍBq×
+BqáHBqë
+BqõÃBr  Br
+=Br{Br
+žBr(öBr33Br=qBrG®BrQìBr\)BrffBrp€BrzáBr
+Bt  Bt
+=Bt{Bt
+žBt(öBt33Bt=qBtG®BtQìBt\)BtffBtp€BtzáBt
+Bt\BtBt£×Bt®BtžRBtÂBtÌÍBt×
+BtáHBtë
+BtõÃBu  Bu
+=Bu{Bu
+žBu(öBu33Bu=qBuG®BuQìBu\)BuffBup€BuzáBu
+Bu\BuBu£×Bu®BužRBuÂBuÌÍBu×
+BuáHBuë
+BuõÃBv  Bv
+=Bv{Bv
+žBv(öBv33Bv=qBvG®BvQìBv\)BvffBvp€BvzáBv
+Bx  Bx
+=Bx{Bx
+žBx(öBx33Bx=qBxG®BxQìBx\)BxffBxp€BxzáBx
+Bx\BxBx£×Bx®BxžRBxÂBxÌÍBx×
+BxáHBxë
+BxõÃBy  By
+=By{By
+žBy(öBy33By=qByG®ByQìBy\)ByffByp€ByzáBy
+By\ByBy£×By®ByžRByÂByÌÍBy×
+ByáHByë
+ByõÃBz  Bz
+=Bz{Bz
+žBz(öBz33Bz=qBzG®BzQìBz\)BzffBzp€BzzáBz
+B|  B|
+=B|{B|
+žB|(öB|33B|=qB|G®B|QìB|\)B|ffB|p€B|záB|
+B|\B|B|£×B|®B|žRB|ÂB|ÌÍB|×
+B|áHB|ë
+B|õÃB}  B}
+=B}{B}
+žB}(öB}33B}=qB}G®B}QìB}\)B}ffB}p€B}záB}
+B}\B}B}£×B}®B}žRB}ÂB}ÌÍB}×
+B}áHB}ë
+B}õÃB~  B~
+=B~{B~
+žB~(öB~33B~=qB~G®B~QìB~\)B~ffB~p€B~záB~
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =
+(Ð9±¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?¹V:?=œ =(a<m<{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @7-@	ñâ?ºHþ?A\r=bn|<êxs¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @Ø@dt\@7Šù@
+Ù?Œg?DûC=-Ë=/)S¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @¶<@{b@±@e\@8@
+Á;?œç°?HÔ=«"U=ig¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @ãZx@ÌŒ@¶Uí@ï<@@fCµ@9vR@
+šï?¿·?L8Š=Èâ=Á¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AMÚ@ùýÚ@ã)@Í0x@¶ÉÇ@ c@üf@g+i@:^@
+£?Á?O×x=åm=®xL¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+îxAAl3@úqµ@ä
+@Í€S@·=¢@ Öñ@p@@h
+@;Eº@xX?ÃUê?SvJ>ý=ËnÙ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A5A*@)A
+ÑAÙxAŠ @úå@ä~Þ@Î-@·±|@¡JË@ä@húÒ@<-o@`
+?Å%S?W>~C=èee¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AL/°A@àÃA5­kA*zAFºAaAà	@ûYa@äò°@Îÿ@ž%N@¡Ÿ@Wì@iâv@=@G°?Æô?Z³¬>
+ø>­÷¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AbÐNAWaALN	AA°A5çXA*³ÿA§AMNA	ö@ûÍ;@åf@ÎÿÙ@ž(@¢2w@ËÆ@jÊ*@=üÇ@/e?ÈÄ?^R~>,sÏ>)>¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AypìAn!ÿAbî§AW»NALöAATA6!EA*íìAºA<A	Sã@üA@åÚd@Ïs³@¹
+@¢ŠQ@?¡@k±ß@>ä|@?Ên?añO>:ï>€¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÆAaOAyEAn[ìAc(AWõ;ALÁãAAA6[2A+'ÚAôAÁ(A	Ð@üŽï@æN>@Ïç@¹Ý@£,@³z@l@?Ì1@þÎ?ÌbÖ?e!>Ij[>.Ì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AYA±AðA~DAyÉ.AnÕAcb}AX/$ALûÌAAÈtA6A+aÂA .jAûA	Ç¹@ý(Â@æÂ@Ð[`@¹ô®@£þ@'M@m8@@³Õ@æs?Î2?i.²>Wä£><¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A©dAíAh@AÎA4çA:AzAnÏÂAcjAXiAM5¹AB`A6ÏA+°A hWA4ÿA
+Š@ý@ç5ê@ÐÏ:@ºh@€Ø@'@nhì@A@Î'?Ð?lÍ
+>f_ê>KZ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A©ùŽA€R=AžA
+äA
+7AëAQÞAž1Az=Ao	°AcÖWAX¢þAMoŠAB<NA7õA+ÕA ¢DAnëA
+;@þv@ç©Å@ÑC@ºÜc@€u²@@oP¡@B>@µÛ?ÑÐñ?plW>tÛ1>Y¡¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AµJA¯¢AªàA€o4AÕA;ÚA¢.AAnÓAÕ'AzvõAoCAdDAXÜìAM©ABv;A7BâA,A Ü1AšÙA
+u@þP@è
+@Ñ¶î@»P=@€é@Û@p8U@Cjó@?Ó Z?t
+(>«<>h
+è¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÀTAºòÝAµY0A¯¿Aª%×A€*Aò~AXÑA¿#A%wAÊAò
+Az°âAo}AdJ1AYÙAMãAB°'A7|ÏA,IwA!AâÆA
+¯m@þø*@èy@Ò*È@»Ä@¥]f@ö¶@q 	@DR§@
+D?ÕoÃ?w©ú>èà>v/¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AËê¢AÆC+AÀ©~A»ÒAµv%A¯ÜxAªBÌA€©AqAuÅAÜABlAš¿AAzêËAo·sAdAYPÁAN
+iABêA7¶¹A,`A!PA
+¯A
+éV@ÿkü@éK@Ò@Œ7ê@¥Ñ8@j@r®@E:K@lè?×?
+?{H>&>»¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A×:òAÑ{AËùÎAÆ`"AÀÆuA»,ÈAµ
+A¯ùoAª_ÁA€ÆA,hAŒAùA_bAÅ¶A,	A{$žAoñ_AdŸAY¯ANWWAC#þA7ð¥A,œMA!ôAVA
+#D@ÿßÖ@éy&@Ót@Œ«Ä@ŠE@Þb@rïb@F" @T?Ùt?~ç]>c§>¿_¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AâBAÜãËA×J
+AÑ°rAÌÅAÆ}AÀãlA»I¿Aµ°A°eAª|žA€ã
+AI_A¯²AA|YAâ¬AI A{^ŠAp+MAd÷õAYÄANCAC]ëA8*A,÷:A!ÃâAA
+]0A )Ø@éí @ÓO@œ@Šží@R<@s×@G	Ž@<Q?ÚÝÝ?C>¡K>ý¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AíÛAè4AânAÝ ÂA×gAÑÍhAÌ3ŒAÆAÁ aA»fµAµÍA°3\Aª¯A¥ AfVAÌ©A2üAPAÿ£AeöA{Ape:Ae1áAYþANË0ACØA8dA-1'A!ýÎAÊvA
+
+A cÆ@ê`Ú@Óú)@œx@§,Ç@Æ@tŸÌ@Gñh@$?Ü­F?>¥Þî>:Š¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aù+âAókAíêŸAèQAâ·eAÝ
+žA×
+AÑê_AÌP±AÆ·AÁ
+XA»¬AµéÿA°PRAª¶ŠA¥
+ùALAé AOóA¶FA
+AìA{ÒAp'AekÎAZ8vAO
+ACÑÅA8lA-kA"7ŒAdA
+Ñ
+A ²@êÔŽ@Ôn@ŸR@§ ¢@9ñ@uŠ@HÙ
+@
+
+º?Þ|¯?áé>­
+>xJ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B>AþÔ¹Aù;
+Aó¡`Aî³AènAâÔZAÝ:­A× ÿAÒSAÌmŠAÆÓúAÁ:MA»  A¶ôA°mGAªÓA¥9îA AAAlçAÓ:A9AáA|
+hApÙAe¥žAZr_AO?AD
+®A8ØVA-€þA"q¥A>LA
+
+ôA ×@ëH@ÔáÖ@Ÿ{%@št@­Ã@v$@IÀÁ@
+ó_?àK÷?±2>ŽYµ>Šµí¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bæ@BBE®Aþñ¯AùXAóŸVAî$ªAèýAâñOAÝW£A×œöAÒ$JAÌAÆððAÁWDA»œA¶#êA°>AªðA¥VäAœ7A#AÝAð1AVAŒØA|FVAqýAeß€AZ¬LAOxôADEA9CA-ÞêA"«Ax9A
+DáA@ëŒa@ÕU°@Ÿîÿ@šN@!@wuÙ@Jšv@
+Û?â`?>»Y>­ó¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+hB
+º¬BíÖB! BT)AÿŠAùtúAóÛMAîAAè§óAãFAÝtA×ÚíAÒA@AÌ§AÇ
+çAÁt:A»ÚA¶@áA°§4A«
+A¥sÚAÚ-A@AŠÔA
+(As{AÙÎA|CAqLêAfAZæ:AO²áADA9L0A.×A"åA²'A
+~ÏAKv@ì0;@ÕÉ@¿bÙ@šü)@x@x]@K*@
+ÂÇ?ãêÊ?P>ÂÔü>µ15¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B6BbÔB
+þB
+É(BüQB/{Bb¥Aÿ+AùïAóøCAî^AèÄêAã+=AÝA×÷äAÒ^7AÌÄAÇ*ÞAÁ1A»÷A¶]×A°Ä*A«*}A¥ÑA÷$A]xAÃËA*
+ArAöÅA|º0AqØAfSA[ &AOìÎAD¹uA9
+A.RÅA#mAìA
+žŒA
+c@ì€@Ö=e@¿ÖŽ@©p@	R@yEB@Lwß@ª|?åº2?m>Ê¡>ŒnÙ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BÞžB
+üB>&BqPB
+€yB
+×£B
+ÍB=öBq AÿHAù®æAô:Aî{AèáàAãH4AÝ®AØÚAÒ{.AÌáAÇGÔAÁ®'AŒzA¶zÎA°á!A«GtA¥­ÈA AznAàÂAGA­hA»A|ô
+AqÀÄAflA[ZAP&»ADócA9À
+A.²A#YZA&A
+ò©A¿P@íð@Ö±?@ÀJ@©ãÝ@},@z,ö@M_@ 1?ç?îÖ>ÑPD>Ã¬|¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+ßB³#BæMBwBL BÊB
+²ôB
+æ
+BGBLqBAÿeAùËÛAô2.AîAèþÕAãe(AÝË|AØ1ÏAÒ"AÌþuAÇdÈAÁË
+AŒ1oA¶ÂA°þA«diA¥ÊŒA 1AcAý¶Ad	AÊ\A0°A}.Aqú­AfÇUA[ýAP`¥AE-LA9ùôA.ÆA#CA_êA
+,Aù:@íÂ@×%@ÀŸ`@ªW¯@ðþ@{@NG8@!yÕ?éXå?Ÿ>Øh>Êê ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B$/B![KB
+uBÁBôÈB'òB[
+BEB
+ÁoB
+ôB'ÂBZìBAÿAùèÒAôO%AîµxAéÌAãAÝèrAØNÅAÒµAÍlAÇ¿AÁèAŒNfA¶Ž¹A±
+A«`A¥ç³A NAŽYA¬A AçSAMŠA}góAr4AgCA[ÍêAPAEg9A:3áA/ A#Í0AØA
+fA3&@íÿ@×ë@Á2:@ªË@dÙ@{üO@O.ì@"a?ë(M?>ßË
+>Ò'Ä¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B)×/B'sB$6B!iÇB
+ðBÐBDB6mBiBÁB
+ÏêB
+B6>BigBAÿtAúÈAôl
+AîÒoAé8ÂAãAÞhAØkŒAÒÒAÍ8bAÇ¶AÂ	AŒk\A¶Ñ°A±8A«VAŠ©A jüAÑPA7£AöAJAjA}¡áArnAg;0A\×APÔAE¡&A:mÎA/:vA$
+AÓÄA
+ lAm@îsv@Ø
+Å@ÁŠ@«?c@Ø³@|ä@P @#I>?ì÷·?\ñ>ç¯>Ùeh¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B/WB,«B)ÞÅB'ïB$EB!xBB
+«lBÞB¿BDéBxB«<B
+ÞfB
+BD¹BwâB«
+AÿŒkAú"¿AôAîïeAéUžAãŒ
+AÞ"_AØ²AÒïAÍUYAÇ»¬AÂ" AŒSA¶îŠA±TùA«»LAŠ! A óAîFATAºíA!@AA}ÛÎAršuAgu
+A\AÄAQlAEÛA:§»A/tbA$A
+A
+²A
+ÚYA§@îçQ@Ø@Âï@«³>@L@}Ëž@PþV@$0ó?îÇ ?,Z>îFT>à£
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B5'B2SÃB/íB,ºB)í@B' jB$SB!œB
+¹çBíB :BSdBB¹·B
+ìáB
+ 
+BS4B^B¹AÿÙbAú?µAôŠAï
+\Aér¯AãÙAÞ?VAØ¥©AÓ
+üAÍrPAÇØ£AÂ>öAŒ¥IA·
+A±qðA«ØCAŠ>A €êA
+=AqA×äA>7A€A~»ArâbAg¯
+A\{²AQHYAF A:ášA/®PA$z÷AGAFAàî@ï[+@Øôz@ÂÉ@¬'@Àg@~³l@Qæ
+@%§?ð?ûÄ>õù>çà°¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B:ÏŠB7ûêB5/B2b>B/gB,ÈB)û»B'.äB$bB!8B
+ÈaBûB.µBaÞBBÈ1B
+û[B
+.
+Ba®BØBÈAÿöVAú\ªAôÂýAï)PAé€Aãõ÷AÞ\JAØÂAÓ(ñAÍDAÇõAÂ[êAŒÂ>A·(A±äA«õ8AŠ[A ÁÞA(2A
+AôØA[,AÁ~A~O£As
+LAgèóA\µAQBAFNêA;A/è9A$ŽàAAN/A×@ïÎý@ÙhL@Ã@¬ê@49@@RÍ¯@& L?òeÒ?Ë
+>üÁ
+>ï
+U¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B@wÎB=€B:×<B8
+fB5=B2p¹B/£ãB,×
+B*
+6B'=`B$pB!£³B
+ÖÝB
+
+B=0BpYB£BÖ­B	ÖB
+= Bp*B£SBÖ}B 	§Aúy AôßôAïFGAé¬AäîAÞyAAØßAÓEçAÍ¬:AÈAÂxáAŒß4A·EA±«ÛA¬.AŠxA ÞÕAE(A«|AÎAx"AÞuA~AsV8Ah"àA\ïAQŒ/AF×A;U~A0"&A$îÍA»uA
+ATÄ@ðB×@ÙÜ&@Ãuu@­Ä@š@Ac@Sµc@&è ?ô5;?u?ÿ`>ö[ø¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BFöBCL:B@dB=²B:å·B8áB5L
+B24B/²^B,åB*±B'KÛB$B!².B
+åXB
+BK«B~ÕB±þBå(BRB
+K{B~¥B±ÏBäøB !AúAôüêAïc>AéÉAä/äAÞ7AØüAÓbÞAÍÉ1AÈ/AÂØAŒü+A·b~A±ÈÒA¬/%AŠxA ûÌAb
+AÈrA.ÅAAûlA~Ã~As&Ah\ÍA])uAQö
+AFÂÄA;kA0\A%(»AõbAÂ	A±@ð¶±@ÚP @ÃéO@­@î@µ=@T@'Ïµ?ö€?iÞ?2>ý¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BKÈ
+BHôbBF'BCZ¶B@ßB=Á	B:ô3B8'\B5ZB2°B/ÀÙB,ôB*'-B'ZVB$B!À©B
+óÓB
+&ýBZ&BPBÀzBó£B&ÍB
+Y÷B BÀIBósB &Aú³AõáAï4AéæAäLÚAÞ³.AÙAÓÔAÍæ(AÈL{AÂ²ÎAœ"A·uA±åÈA¬L
+AŠ²nA¡ÂAAåhAKŒA²A
+bA~ýkAsÊAhºA]cbAR0	AFü±A;ÉYA0 A%b§A/OAû÷AÈ@ñ*@ÚÃÛ@Ä]*@­öy@È@)@UÌ@(·i?÷Ô
+?9G?	=?k ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BQpFBNBKÏŽBIÞBF6BCi1B@[B=ÏB;®B85ØB5iB2+B/ÏUB-~B*5šB'hÑB$ûB!Ï%BNB
+5xBh¢BËBÎõBB5HB
+hqBBÎÅBîB 5AúÐAõ6×Aï*Aê~AäiÑAÞÐ$AÙ6xAÓËAÎ
+AÈirAÂÏÅAœ6A·lA²ŸA¬iAŠÏeA¡5žA
+A_Ah²AÏA
+5YA7XAt AhÐ§A]OARi÷AG6A<EA0ÏíA%Ai<A5äA@ñf@Û7µ@ÄÑ@®jS@¢@ò@Vl@)
+?ù£v? °?
+ÛÖ?
+r¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BWmBTD±BQwÛBN«BKÞ.BIXBFDBCw«B@ªÕB=ÝÿB;(B8DRB5w|B2ª¥B/ÝÏB-øB*D"B'wLB$ªuB!ÝBÉB
+CòBw
+BªFBÝoBBCÂB
+vìBªBÝ?BiB CAúíxAõSÌAïºAê rAäÆAÞíAÙSlAÓ¹ÀAÎ AÈfAÂìºAœS
+A·¹`A²³A¬AŠìZA¡R­A¹ ATA
+§AëúA
+RNAqAAt=éAi
+A]×8AR£ßAGpA<=/A1	ÖA%Ö~A£%AoÍA<t@ò8@Û«@ÅDÖ@®Þ%@wt@Ä@WT%@*Â?ûrŸ?¡×ù?zg?	©D¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B\ÀBYìÙBW BTS-BQVBN¹BKìªBIÓBFRýBC'B@¹PB=ìzB;€B8RÍB5
+÷B2¹ B/ìJB-tB*RB'
+ÇB$žñB!ìBDB
+RnB
+BžÀBëêBBR=B
+
+gBžBë»B
+åB RAû
+oAõpÂAï×Aê=iAä£ŒAß
+AÙpcAÓÖ¶AÎ=
+AÈ£\AÃ	°AœpA·ÖVA²<ªA¬¢ýA§	PA¡o€AÕ÷A<JA¢AñA
+oDA«.AtwÖAiD}A^%ARÝÍAGªtA<w
+A1CÃA&kAÝA©ºAvb@ò@Üa@Åž°@¯R @ëO@@X;Ù@+nv?ýB'?£§b?:?
+H¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BbhœB_B\È+BYûUBW.~BTašBQÒBNÇûBKû%BI.OBFaxBC¢B@ÇÌB=úõB;.B8aHB5rB2ÇB/úÅB--ïB*aB'BB$ÇlB!úB-¿B
+`èBBÇ<BúeB-B`¹B
+ãBÇ
+Bú6B-`B `Aû'fAõ¹Aïô
+AêZ`AäÀ³Aß'AÙZAÓó¬AÎZ AÈÀSAÃ&ŠAœúA·óMA²Y A¬¿ôA§&GA¡AòîAYAA¿A%çA
+:AåAt±ÃAi~kA^KASºAGäaA<±	A1}°A&JXA Aã§A°N@òùì@Ü<@Æ,@¯ÅÚ@_)@øx@Y#@,V+?ÿ?¥vË?ž
+?æè¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BhåBe=)BbpSB_£}B\ÖŠBZ	ÐBW<úBTp#BQ£MBNÖwBL	 BI<ÊBFoôBC£
+B@ÖGB>	pB;<B8oÄB5¢íB2ÖB0	AB-<jB*oB'¢ŸB$ÕçB"	B<:B
+odB¢BÕ·BáB<
+Bo5B
+¢^BÕB²B;ÛB oAûD\Aõª°AðAêwVAäÝªAßCüAÙªPAÔ£AÎvöAÈÝJAÃCAœ©ðAžDA²vA¬ÜêA§C>A¡©AäAv7AÜABÞA
+©1AAtë°AižXA^ÿASQ§AH
+NA<êöA1·A&EAPìA
+Aê<@ómÇ@Ý@Æ e@°9Ž@Ó@lR@Z
+B@-=ß@ p|?§F3?VÝ?
+¹¿  ¿  ¿  ¿  ¿  ¿  Bm¹
+BjåQBh{BeK¥Bb~ÎB_±øB\å"BZKBWKuBT~BQ±ÈBNäòBL
+BIKEBF~oBC±B@äÂB>ìB;KB8~?B5±iB2äB0ŒB-JæB*~B'±8B$äbB"BJµB
+}ßB±	Bä3B]BJB}°B
+°ÚBäB,BJVB }AûaSAõÇŠAð-úAêLAäú Aß`óAÙÇFAÔ-AÎíAÈú@AÃ`AœÆçAž-:A²A¬ùáA§`4A¡ÆA,ÚA.AùA_ÔA
+Æ(A,{Au%AiòEA^ŸìASAHX<A=$ãA1ñA&Ÿ2AÚAWA$)@óá¡@Ýzð@Ç?@°­@FÞ@à-@Zòö@.%@X1?©?
+õ¯?$¿  ¿  ¿  ¿  Bsa4BpxBmÀ¢BjóÌBh&õBeZBbIB_ÀrB\óBZ&ÆBWYïBTBQÀCBNólBL&BIY¿BFéBCÀB@ó<B>&fB;YB8¹B5¿ãB2ó
+B0&6B-Y_B*B'¿³B$òÜB"&BY0B
+ZB¿Bò­B%×BYB*B
+¿SBò}B%§BXÐB úAû~HAõäAðJîAê±AAåAß}èAÙä;AÔJAÎ°âAÉ5AÃ}AœãÜAžJ/A²°A­ÕA§}(A¡ã|AIÏA°"AvA|ÉA
+ã
+AIpAu_Aj,.A^øÖASÅ}AH$A=^ÌA2+tA&øAÄÃAkA^@ôUs@ÝîÂ@Ç@±!a@º°@Sÿ@[Ú@/
+8@?Õ?ªäæ?"B?Ã^¿  ¿  By	\Bv5 BshÊBpôBmÏ
+BkGBh5qBehBbÄB_ÎîB]BZ5ABWhkBTBQÎŸBOçBL5BIh;BFdBCÎBAžB>4áB;h
+B85B5Î^B3B04±B-gÛB*B'Î.B%XB"4Bg¬B
+ÕBÍÿB)B4RBg{B¥B
+ÍÏB	 øB4"BgLB uAû>AöAðgäAêÎ8Aå4AßÞAÚ2AÔg
+AÎÍØAÉ4,AÃAŸ ÒAžg%A²ÍxA­3ÌA§A¢ rAfÆAÍA3lAÀA AffAutAjfA_2ÂASÿjAHÌA=¹A2eaA'2	Aþ°AËWAÿ@ôÉN@Þb@Çûì@±;@.@ÇÙ@\ÂO@/ôí@'?¬ŽO?&3?b/B|  B{ÝÈByòBvD
+BswEBpªoBmÝBkÂBhCìBewBbª?B_ÝiB]BZCŒBWvæBTªBQÝ9BOcBLCBIv¶BF©àBCÝ	BA3B>C]B;vB8©¯B5ÜÙB3B0C,B-vVB*©B'ÜªB%ÔB"BýBv'B
+©QBÜzB£BBÍBu÷B© B
+ÜJB	tBBBuÇB šñAûž4Aö
+AðÛAêë.AåQAß·ÕAÚ
+(AÔ|AÎêÏAÉQ"AÃ·uAŸ
+ÈAž
+A²êoA­PÂA§·A¢
+iAŒAêAPcA¶¶A
+	A\AuÓ`Aj A_l°AT9WAIÿA=Ò§A2NA'kõA
+8AEAÑí@õ=(@ÞÖw@ÈoÆ@²	@¢e@
+;³@]ª@0Ü¢@??®ž?)Ñå¿  B|B{ìDBymBvRBs
+ÁBpžêBmìBk>BhRgBe
+Bbž»B_ëäB]BZR7BW
+aBTžBQëŽBO
+ÞBLRBI
+1BFž[BCë
+BA
+®B>Q×B;
+B8ž+B5ëTB3
+~B0QšB-ÒB*·üB'ë%B%
+OB"QyB¢B
+·ËBêõB
+BQHBrB·B
+êÅB	
+ïBQBBB ·lAûÕ+Aö;~Að¡ÒAë%AånxAßÔÌAÚ;AÔ¡rAÏÅAÉnAÃÔlAŸ:¿Až¡A³fA­m¹A§Ô
+A¢:`A ³AAmYAÓ¬A: A SAv
+NAjÙõA_ŠATsEAI?ìA>
+A2Ù;A'¥ãA
+rA?2A
+Ù@õ±@ßJQ@Èã¡@²|ð@>@
+¯@^¹@1ÄV@öó?¯vw¿  ¿  B|B{ú¿By-éBvaBs<BpÇfBmúBk-¹Bh`ãBe
+BbÇ6B_ú_B]-BZ`³BWÜBTÇBQú0BO-YBL`BI­BFÆÖBCùÿBA-)B>`SB;|B8ÆŠB5ùÐB3,úB0`$B-MB*ÆwB'ù¡B%,ÊB"_óB
+B
+ÆGBùpB,B_ÄBíBÆB
+ùAB	,jB_BŸB ÅçAûò"AöXuAðŸÈAë%
+AåoAßñÂAÚXAÔŸhAÏ$ŒAÉAÃñbAŸW¶AžŸ	A³$\A­°A§ñA¢WVAœ©A#üAPAð£AVöAœJAvG;AkãA_àAT­1AIyÙA>FA3)A'ßÐA
+¬wAyAEÇ@ö$Ý@ßŸ,@ÉWz@²ðÊ@@#h@_yn@2=¶¿  ¿  ¿  ¿  B|$B|	:By<dBvoBs¢·BpÕáBn	
+Bk<4Bho^Be¢BbÕ±B`ÛB]<BZo.BW¢XBTÕBR«BO;ÕBLnþBI¢'BFÕQBD{BA;€B>nÎB;¡øB8Õ"B6LB3;uB0nB-¡ÉB*ÔòB(B%;EB"noB¡B
+ÔÂBìB;Bn?B¡iBÔB
+ŒB	:æBnB¡9B ÔbAüAöulAðÛ¿AëBAåšeAàžAÚu
+AÔÛ_AÏA²AÉšAÄYAŸt¬AžÛ A³ASA­§ŠAš
+ùA¢tLAÚ A@óA§FA
+AsíAÚ@Av(AkMÏA`wATçAI³ÇA>nA3MA(œA
+æeA³
+AŽ@ö·@à2@ÉËU@³d€@ýó@`¿  ¿  ¿  ¿  ¿  ¿  B|3B|¶ByJßBv~	Bs±3Bpä\BnBkJ¯Bh}ÙBe±Bbä,B`VB]JBZ}©BW°ÓBTãýBR&BOJOBL}yBI°£BFãÌBDöBAJ B>}JB;°tB8ãB6ÇB3IñB0}B-°CB*ãmB(B%IÀB"|êB°B
+ã=BgBIB|ºB¯äBãB
+7B	IaB|B¯ŽB âÞAü,AöbAðøµAë_AåÅ\Aà+¯AÚAÔøVAÏ^©AÉÄüAÄ+PAŸ£Až÷öA³^IA­ÄAš*ðA¢CA÷A]êAÄ=A*AäA÷7Av»AkœA`TeAU!
+AIí³A>º[A3A(SªA
+ RAìúA¹¡@÷
+@à¥à@Ê?/@³¡T¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|AB|&/ByYYBvBs¿¬BpòÕBn%ÿBkY)BhRBe¿|BbòŠB`%ÏB]XùBZ#BW¿LBTòuBR%BOXÉBLòBI¿
+BFòFBD%pBAXB>ÃB;ŸíB8òB6%@B3XiB0B-ŸœB*ñæB(%B%X:B"cBŸB
+ñ·B$àBX
+B4BŸ]BñB
+$°B	WÚBBŸ-B ñWAüIAö¯TAñšAë{ûAåâNAàH¢AÚ®õAÕHAÏ{AÉáïAÄHBAŸ®A¹èA³{<A­áAšGâA¢®6AAzÜAá0AGA­×A)AvôûAkÁ¢A`IAUZñAJ'A>ô@A3ÀèA(A
+Z7A&ÞAó@÷[@àâ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|OÿB|4ªBygÔBvýBsÎ'BqQBn4zBkg€BhÎBeÍ÷Bc!B`4KB]gtBZBWÍÇBU ñBR4BOgDBLnBIÍBG ÂBD3ëBAgB>?B;ÍhB9 B63»B3fåB0B-Í8B+ bB(3B%fµB"ßBÍB
+ 2B3\Bf
+B¯BÌØB B
+3,B	fUBBÌšB ÿÒAüeøAöÌKAñ2AëòAåÿEAàeAÚËìAÕ2?AÏAÉþåAÄe8AŸËA¹1ßA³2A­þAšdÙA¢Ë,A1AÓAþ'AdyAÊÌA1 Aw.çAkûA`È7AUÞAJaA?..A3úÕA(Ç|A
+$A`ÌAÞ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|^zB|C%ByvOBv©yBsÜ¢BqÌBnBöBkvBh©IBeÜsBcB`BÅB]uïBZ©BWÜBBUlBRBBOuÀBLšêBIÜBG=BDBgBAuB>š¹B;ÛãB9
+B6B6B3u`B0šB-Û³B+ÝB(BB%u0B"šZBÛB
+­BA×Bu Bš*BÛTB}B
+A§B	tÐB§úBÛ$BMAüîAöéBAñOAëµèAæ
+<AàAÚèâAÕO5AÏµAÊÜAÄ/AŸèA¹NÖA³µ)A®|AšÐA¢è#ANwAŽÉA
+ApAçÃANAwhÕAl5|Aa$AUÎÌAJsA?hA44ÂA)jA
+²|¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|lõB|Q¡ByÊBv·ôBsë
+Bq
+GBnQqBkBh·ÄBeêíBc
+B`QAB]jBZ·BWêŸBU
+èBRQBO;BL·eBIêBG
+žBDPáBA
+B>·5B;ê^B9
+B6P²B3ÛB0·B-ê/B+
+XB(PB%¬B"¶ÕBéÿB
+
+(BPRB|B¶¥BéÏB
+øB
+P"B	LB¶uBéB
+ÉAüåA÷8AñlAëÒßAæ92Aà
+AÛØAÕl,AÏÒAÊ8ÒAÄ&A¿yA¹kÌA³Ò A®8sAšÇA£AklAÑÀA8AfAºAk
+Aw¢ÂAlojAa<AVžAJÕ`A?¢A4S¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|{pB|`
+ByFBvÆoBsùBq,ÃBn_ìBkBhÆ?BeùiBc,B`_ŒB]æBZÆBWù:BU,cBR_BO·BLÅàBIù	BG,3BD_]BAB>Å°B;øÚB9,B6_-B3WB0ÅB-øªB++ÔB(^ýB%'B"ÅPBøzB
++€B^ÍB÷BÅ BøJB+tB
+^B	ÇBÄñBøB+DAüŒÜA÷#/AñAëïÕAæV(AàŒ|AÛ"ÏAÕ"AÏïvAÊUÉAÄŒ
+A¿"pA¹ÃA³ïA®UiAš»ŒA£"AcAî¶AU
+A»]A!°AAwÜ¯Al©VAauþAVBŠAJóž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ìB|nBy¡ÁBvÔëBtBq;=BnngBk¡BhÔºBfäBc;B`n8B]¡bBZÔBXµBU:ßBRnBO¡1BLÔ[BJ
+BG:®BDmØBA¡B>Ô+B<UB9:B6mšB3 ÒB0ÓüB.%B+:OB(mxB% ¢B"ÓÌB õB
+:BmHB rBÓBÅB9ïB
+mB	 BBÓlBB9¿AüÙÒA÷@%AñŠxAì
+ÌAæsAàÙrAÛ?ÆAÕŠAÐ
+lAÊrÀAÄÙA¿?gA¹¥¹AŽ
+
+A®r`AšØ³A£?A¥ZA
+­Ar AØTA>§A€úAxAlãDAaV¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|gB|}By°<BvãeBtBqI¹Bn|âBk°
+Bhã6Bf`BcIB`|³B]¯ÝBZãBX0BUIYBR|BO¯­BLâÖBJ BGI*BD|SBA¯}B>â§B<ÐB9HúB6|$B3¯MB0âwB. B+HÊB({ôB%¯
+B"âGB pB
+HB{ÄB®íBâBABHjB
+{B	®ŸBáçBBH;AüöÈA÷]
+AñÃoAì)ÂAæAàöiAÛ\ŒAÕÃAÐ)cAÊ·AÄö	A¿\\A¹Â°AŽ)A®VAšõªA£[ýAÂPA(€A÷AõKA[AÁñAx4ô¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ŠâB|ByŸ·BvñáBt%
+BqX4Bn^BkŸBhñ²Bf$ÛBcXB`/B]ŸXBZñBX$«BUWÕBRþBOŸ(BLñRBJ${BGW¥BDÏBAœøB>ñ"B<$LB9WuB6B3œÈB0ðòB.$
+B+WEB(oB%œB"ðÂB #ìB
+WB?BœiBðB#ŒBVæB
+B	œ9BðcB#BV¶Aý¿A÷zAñàfAìF¹Aæ­
+Aá`AÛy³AÕàAÐFYAÊ¬¬AÅ A¿ySA¹ßŠAŽEúA®¬MA© A£xôAßGAEA«îA@AjÉ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|µ]B|	ByÍ2Bw \Bt3Bqf°BnÚBkÍBi -Bf3WBcfB`©B]ÌÓBZÿýBX3&BUfPBRzBOÌ£BLÿÍBJ2÷BGf BDJBAÌtB>ÿB<2ÇB9eðB6B3ÌDB0ÿmB.2B+eÀB(êB%ÌB"ÿ=B 2gB
+eBºBËäBÿB27BeaB
+B	ËŽBþÞB2Be1Aý0¶A÷	Añý\Aìc°AæÊAá0WAÛ©AÕüüAÐcPAÊÉ£AÅ/öA¿JA¹üAŽbðA®ÉDA©/A£ëAü>AbA»¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ÃØB|šByÛ®BwØBtBBqu+BnšUBkÛBišBfAÑBctûB`š%B]ÛNB[xBXA¢BUtËBR§õBOÛBMHBJArBGtBD§ÅBAÚïB?B<ABB9tlB6§B3Ú¿B1
+èB.AB+t<B(§eB%ÚB#
+¹B @âB
+t
+B§6BÚ_B
+B@³BsÜB
+§B	Ú0B
+YB@Bs¬AýM¬A÷Ž AòSAì§AææùAáMLAÛ³ AÖóAÐFAÊæAÅLíA¿³@AºAŽçA®æ;A©LA£²àA
+i¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ÒTB|¶þByê(Bw
+QBtP{Bq¥Bn¶ÎBké÷Bi
+!BfPKBctB`¶B]éÈB[
+ñBXPBUEBR¶nBOéBM
+ÂBJOëBGBD¶>BAéhB?
+B<O»B9åB6¶B3é8B1
+bB.OB+µB(µßB%éB#
+2B O\B
+
+Bµ¯BèÙB
+BO,BVB
+µB	è©BÒBNüB&AýjA÷ÐóAò7EAìAçìAáj?AÛÐAÖ6æAÐ9AËAÅiàA¿Ð3Aº6AŽÚA¯,A©[µ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|àÐB|ÅyByø£Bw+ÍBt^öBqBnÅIBkøsBi+Bf^ÆBcðB`ÅB]øCB[+mBX^BUÀBRÄêBOøBM+=BJ^fBGBDÄºBA÷ãB?+
+B<^6B9`B6ÄB3÷³B1*ÝB.^B+0B(ÄZB%÷B#*­B ]×B
+BÄ*B÷TB*~B]§BÑB
+ÃúB	÷$B*NB]wB¡AýA÷íèAòT<AìºAç âAá6AÛíAÖSÜAÐº0AË AÅ×A¿í*AºS|AŽ¬¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ïKB|ÓõBz
+Bw:GBtmqBq BnÓÄBlîBi:BfmABc kB`ÓB^ŸB[9èBXmBU ;BRÓeBPBM9žBJlâBG 
+BDÓ5BB^B?9B<l²B9ÛB6ÓB4/B19XB.lB+¬B(ÒÕB&ÿB#9)B lRB
+|BÒŠBÏB8ùBl"BLB
+ÒvB
+B8ÉBkóB
+Aý€Aø
+ßAòq2Aì×Aç=ÙAá€,AÜ
+AÖpÓAÐ×'AË=zAÅ£ÌA¿üU¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ýÆB|âoBzBwHÃBt{ìBq¯Bnâ@BliBiHBf{œBc®æB`âB^:B[HcBX{BU®¶BRáàBP
+BMH3BJ{]BG®BDá°BBÚB?HB<{-B9®WB6áB4ªB1GÔB.zýB+®'B(áQB&zB#G€B zÎB
+­÷Bá!BJBGtBzB­ÇB
+àñB
+BGDBznB­AýÁAø'ÖAò)Aìô|AçZÐAáÁ#AÜ'wAÖÊAÐô
+AËL¥¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}
+AB|ðëBz$BwW>BthBqœBnð»Bl#åBiWBf8BcœbB`ðB^#µB[VÞBXBUœ2BRð[BP#
+BMV®BJØBGœBDð+BB#UB?VB<šB9ŒÒB6ïüB4#%B1VOB.yB+Œ¢B(ïÌB&"öB#VB IB
+ŒrBïB"ÆBUïBBŒCB
+ïlB
+"BUÀBéBŒAýÞyAøDÌAò« AísAçwÇAáÞAÜDlAÖõ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ŒB|ÿfBz2Bwe¹BtãBqÌ
+Bnÿ6Bl2`BieBf³BcËÝB`ÿB^20B[eZBXBUË­BRþÖBP2 BMe*BJSBGË}BDþ§BB1ÐB?dúB<$B9ËMB6þwB41¡B1dÊB.ôB+Ë
+B(þGB&1qB#dB ÄB
+ÊîBþB1ABdkBBÊŸB
+ýèB
+1Bd;BeBÊAýûpAøaÃAòÈAí.jAçŒAáíE¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B})8B}
+áBzA
+Bwt5Bt§^BqÚBo
+²Bl@ÛBitBf§.BcÚXBa
+B^@«B[sÕBXŠþBUÚ(BS
+RBP@{BMs¥BJŠÏBGÙøBE
+"BB@LB?suB<ŠB9ÙÉB7
+òB4@
+B1sFB.ŠoB+ÙB)
+ÂB&?ìB#sB Š?B
+ÙiB
+B?ŒBræBŠBÙ9B
+
+cB
+?Br¶B¥ßBÙ
+AþgAø~ºAòå
+Aí=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}7³B}
+]BzOBw°BtµÚBqéBo
+-BlOVBiBfµªBcèÓBaýB^O&B[PBXµzBUè£BSÍBPN÷BM BJµJBGètBEBBNÇB?ñB<µB9èDB7nB4NB1ÁB.ŽêB+èB)>B&NgB#B Ž»B
+çäBBN8BaBŽBçµB
+ÞB
+NB2BŽ[Bç
+Aþ5\Aøå¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}F.B}*ØBz^Bw+BtÄUBq÷~Bo*šBl]ÒBiûBfÄ%Bc÷NBa*xB^]¢B[ËBXÃõBU÷BS*HBP]rBMBJÃÅBGöïBE*BB]BB?lB<ÃB9ö¿B7)éB4]B1<B.ÃfB+öB))¹B&\ãB#
+B Ã6B
+ö`B)B\³BÝBÃBö/B
+)ZB
+\B­BÂ×Bï¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}TªB}9SBzl}BwŠBtÒÐBrúBo9#BllMBivBfÒ BdÊBa8óB^l
+B[GBXÒpBVBS8ÄBPkíBMBJÒABHjBE8BBkŸB?çB<ÒB::B78dB4kB1·B.ÑáB,
+B)84B&k^B#B Ñ±B
+ÛB8Bk.BWBÑB«B
+7ÕB
+jÿBC¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}c%B}GÌBzzöBw® BtáIBrsBoGBlzÆBi­ðBfáBdCBaGmB^zB[­ÀBXàêBVBSG=BPzgBM­BJàºBHäBEG
+BBz7B?­`B<àB:ŽB7FÝB4zB1­1B.àZB,B)F®B&y×B#­B à+B
+TBF}ByšB¬ÑBßûB%B
+?i¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}q B}VHBzqBwŒBtïÄBr"îBoVBlABiŒkBfïBd"ŸBaUèB^B[Œ;BXïeBV"BSUžBPâBMŒ
+BJï5BH"_BEUBB²B?»ÜB<ïB:"/B7UYB4B1»¬B.îÖB,!ÿB)U)B&SB#»|B î¥B
+!ÐBTùB#B»MBç¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}B}dÃBzìBwËBtþ@Br1iBodBlœBiÊæBfþBd1:BadcB^B[Ê·BXýàBV1
+BSd4BP]BMÊBJý°BH0ÚBEdBB-B?ÊWB<ýB:0ªB7cÔB4þB1Ê'B.ýQB,0{B)c€B&ÍB#ÉøB ý!B
+0KBcuB¹¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}B}s>BzŠhBwÙBu
+»Br?åBosBlŠ8BiÙbBg
+Bd?µBarßB^ŠB[Ù2BY
+\BV?
+BSr¯BP¥ØBMÙBK
+,BH?UBErBB¥©B?ØÒB=
+üB:?&B7rOB4¥yB1Ø£B/
+ÌB,>õB)r B&¥IB#ØsB!
+B
+7á¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}B}¹BzŽãBwè
+Bu6BrN`BoBlŽ³BiçÝBgBdN0BaZB^ŽB[ç­BY×BVN BS*BPŽTBMç}BK§BHMÑBEúBBŽ$B?çNB=wB:M¡B7ËB4³ôB1ç
+B/HB,MqB)B&³ÅB#à	¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}«B}5BzÃ^BwöBu)²Br\ÛBoBlÃ/BiöXBg)Bd\¬BaÕB^ÂÿB[ö(BY)RBV\|BS¥BPÂÏBMõùBK)"BH\LBEvBBÂB?õÉB=(óB:\
+B7EB4ÂpB1õB/(ÃB,[íB)1¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ºB}°BzÑÚBxBu8-BrkWBoBlÑªBjÔBg7ýBdk'BaPB^ÑzB\€BY7ÍBVj÷BS!BPÑJBNtBK7BHjÇBEñBBÑB@DB=7mB:jB7ÁB4ÐëB2B/0Y¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ÈB}­+BzàUBxBuFšBryÒBo¬üBlà%BjOBgFxBdy¢Ba¬ÌB^ßõB\BYFIBVyrBS¬BPßÆBNïBKFBHyCBE¬lBBßB@ÀB=EéB:yB7¬=B4Ø¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ÖÿB}»§BzîÐBx!úBuU$BrMBo»wBlî Bj!ÊBgTôBd
+Ba»GB^îqB\!BYTÄBVîBS»BPîABN!kBKTBHœBEºèBBîB@!;B=TeB:©¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}åzB}Ê"BzýLBx0uBucBrÈBoÉòBlý
+Bj0EBgcoBdBaÉÂB^üìB\0BYc?BViBSÉBPüŒBN/åBKcBH9BEÉcBBüB@(Ñ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}óöB}ØB{
+ÅBx>îBurBr¥BBoØkBm
+Bj>¿BgqèBd¥BaØ<B_
+eB\>BYq¹BV€âBSØ
+BQ
+6BN>_BKqBH€³BEÐ÷¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~qB}çB{@BxMjBuBr³œBoæçBmBjM:BgdBd³Baæ·B_áB\M
+BY3BV³^BSæBQ±BNLÛBKy¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~ìB}õB{(»Bx[åBuBrÂ8BoõbBm(Bj[µBgßBdÂ	Baõ2B_([B\[BY¯BVÁÙBSõBQ!G¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~gB~
+B{77Bxj`BuBrÐŽBpÝBm7Bjj1BgZBdÐBb®B_6×B\jBY+BVÉo¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~-ãB~B{E²BxxÜBu¬Brß/BpYBmEBjx«Bg«ÖBdÞÿBb)B_ESB\q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~<^B~!B{T-BxWBuºBríªBp ÓBmSþBj'BgºQBdí{Bb¿¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~JÙB~/B{b©BxÒBuÈûBrü&Bp/OBmbyBj£BgÁç¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~YUB~=úB{q#Bx€MBu×wBs
+¡Bp=ËBmj¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~gÏB~LuB{Bx²ÉBuåóBs7¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~vKB~ZñB{Bxº_¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~ÇB~b
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             B|  Bx  Bt  Bp  Bl  Bh  Bd  B`  B\  BX  BT  BP  BL  BH  BD  B@  B<  B8  B4  B0  B,  B(  B$  B   B
+  B  B  B  B
+  B  B  B   Aø  Að  Aè  Aà  AØ  AÐ  AÈ  AÀ  Až  A°  Aš  A   A  A  A  A  Ap  A`  AP  A@  A0  A   A  A   @à  @À  @   @  @@  @   ?      B|
+=Bx
+=Bt
+=Bp
+=Bl
+=Bh
+=Bd
+=B`
+=B\
+=BX
+=BT
+=BP
+=BL
+=BH
+=BD
+=B@
+=B<
+=B8
+=B4
+=B0
+=B,
+=B(
+=B$
+=B 
+=B
+
+=B
+=B
+=B
+=B
+
+=B
+=B
+=B 
+=Aø{Að{Aè{Aà{AØ{AÐ{AÈ{AÀ{Až{A°{Aš{A {A{A{A{A{Ap(öA`(öAP(öA@(öA0(öA (öA(öA (ö@àQì@ÀQì@ Qì@Qì@@£×@ £×?G®<#×
+B|{Bx{Bt{Bp{Bl{Bh{Bd{B`{B\{BX{BT{BP{BL{BH{BD{B@{B<{B8{B4{B0{B,{B({B${B {B
+{B{B{B{B
+{B{B{B {Aø(öAð(öAè(öAà(öAØ(öAÐ(öAÈ(öAÀ(öAž(öA°(öAš(öA (öA(öA(öA(öA(öApQìA`QìAPQìA@QìA0QìA QìAQìA Qì@à£×@À£×@ £×@£×@AG®@G®?\<£×
+B|
+žBx
+žBt
+žBp
+žBl
+žBh
+žBd
+žB`
+žB\
+žBX
+žBT
+žBP
+žBL
+žBH
+žBD
+žB@
+žB<
+žB8
+žB4
+žB0
+žB,
+žB(
+žB$
+žB 
+žB
+
+žB
+žB
+žB
+žB
+
+žB
+žB
+žB 
+žAø=qAð=qAè=qAà=qAØ=qAÐ=qAÈ=qAÀ=qAž=qA°=qAš=qA =qA=qA=qA=qA=qApzáA`záAPzáA@záA0záA záAzáA zá@àõÃ@ÀõÃ@ õÃ@õÃ@Aë
+@ë
+?×
+<õÂB|(öBx(öBt(öBp(öBl(öBh(öBd(öB`(öB\(öBX(öBT(öBP(öBL(öBH(öBD(öB@(öB<(öB8(öB4(öB0(öB,(öB((öB$(öB (öB
+(öB(öB(öB(öB
+(öB(öB(öB (öAøQìAðQìAèQìAàQìAØQìAÐQìAÈQìAÀQìAžQìA°QìAšQìA QìAQìAQìAQìAQìAp£×A`£×AP£×A@£×A0£×A £×A£×A £×@áG®@ÁG®@¡G®@G®@B\@\?
+
+ž=#×
+B|33Bx33Bt33Bp33Bl33Bh33Bd33B`33B\33BX33BT33BP33BL33BH33BD33B@33B<33B833B433B033B,33B(33B$33B 33B
+33B33B33B33B
+33B33B33B 33AøffAðffAèffAàffAØffAÐffAÈffAÀffAžffA°ffAšffA ffAffAffAffAffApÌÍA`ÌÍAPÌÍA@ÌÍA0ÌÍA ÌÍAÌÍA ÌÍ@á@Á@¡@@C33@33?ff=LÌÍB|=qBx=qBt=qBp=qBl=qBh=qBd=qB`=qB\=qBX=qBT=qBP=qBL=qBH=qBD=qB@=qB<=qB8=qB4=qB0=qB,=qB(=qB$=qB =qB
+=qB=qB=qB=qB
+=qB=qB=qB =qAøzáAðzáAèzáAàzáAØzáAÐzáAÈzáAÀzáAžzáA°záAšzáA záAzáAzáAzáAzáApõÃA`õÃAPõÃA@õÃA0õÃA õÃAõÃA õÃ@áë
+@Áë
+@¡ë
+@ë
+@C×
+@×
+?®=uÂB|G®BxG®BtG®BpG®BlG®BhG®BdG®B`G®B\G®BXG®BTG®BPG®BLG®BHG®BDG®B@G®B<G®B8G®B4G®B0G®B,G®B(G®B$G®B G®B
+G®BG®BG®BG®B
+G®BG®BG®B G®Aø\Að\Aè\Aà\AØ\AÐ\AÈ\AÀ\Až\A°\Aš\A \A\A\A\A\Aq
+žAa
+žAQ
+žAA
+žA1
+žA!
+žA
+žA
+ž@â=q@Â=q@¢=q@=q@Dzá@zá?õÃ=\)B|QìBxQìBtQìBpQìBlQìBhQìBdQìB`QìB\QìBXQìBTQìBPQìBLQìBHQìBDQìB@QìB<QìB8QìB4QìB0QìB,QìB(QìB$QìB QìB
+QìBQìBQìBQìB
+QìBQìBQìB QìAø£×Að£×Aè£×Aà£×AØ£×AÐ£×AÈ£×AÀ£×Až£×A°£×Aš£×A £×A£×A£×A£×A£×AqG®AaG®AQG®AAG®A1G®A!G®AG®AG®@â\@Â\@¢\@\@E
+ž@
+ž?=q=£×
+B|\)Bx\)Bt\)Bp\)Bl\)Bh\)Bd\)B`\)B\\)BX\)BT\)BP\)BL\)BH\)BD\)B@\)B<\)B8\)B4\)B0\)B,\)B(\)B$\)B \)B
+\)B\)B\)B\)B
+\)B\)B\)B \)AøžRAðžRAèžRAàžRAØžRAÐžRAÈžRAÀžRAžžRA°žRAšžRA žRAžRAžRAžRAžRAqp€Aap€AQp€AAp€A1p€A!p€Ap€Ap€@âáH@ÂáH@¢áH@áH@EÂ@Â?
+=žQìB|ffBxffBtffBpffBlffBhffBdffB`ffB\ffBXffBTffBPffBLffBHffBDffB@ffB<ffB8ffB4ffB0ffB,ffB(ffB$ffB ffB
+ffBffBffBffB
+ffBffBffB ffAøÌÍAðÌÍAèÌÍAàÌÍAØÌÍAÐÌÍAÈÌÍAÀÌÍAžÌÍA°ÌÍAšÌÍA ÌÍAÌÍAÌÍAÌÍAÌÍAqAaAQAAA1A!AA@ã33@Ã33@£33@33@Fff@ff?ÌÍ=ÌÌÍB|p€Bxp€Btp€Bpp€Blp€Bhp€Bdp€B`p€B\p€BXp€BTp€BPp€BLp€BHp€BDp€B@p€B<p€B8p€B4p€B0p€B,p€B(p€B$p€B p€B
+p€Bp€Bp€Bp€B
+p€Bp€Bp€B p€AøáHAðáHAèáHAàáHAØáHAÐáHAÈáHAÀáHAžáHA°áHAšáHA áHAáHAáHAáHAáHAqÂAaÂAQÂAAÂA1ÂA!ÂAÂAÂ@ã
+@Ã
+@£
+@
+@G
+=@
+=?{=áG®B|záBxzáBtzáBpzáBlzáBhzáBdzáB`záB\záBXzáBTzáBPzáBLzáBHzáBDzáB@záB<záB8záB4záB0záB,záB(záB$záB záB
+záBzáBzáBzáB
+záBzáBzáB záAøõÃAðõÃAèõÃAàõÃAØõÃAÐõÃAÈõÃAÀõÃAžõÃA°õÃAšõÃA õÃAõÃAõÃAõÃAõÃAqë
+Aaë
+AQë
+AAë
+A1ë
+A!ë
+Aë
+Aë
+@ã×
+@Ã×
+@£×
+@×
+@G®@®?\)=õÂB|
+Bx
+Bt
+Bp
+Bl
+Bh
+Bd
+B`
+B\
+BX
+BT
+BP
+BL
+BH
+BD
+B@
+B<
+B8
+B4
+B0
+B,
+B(
+B$
+B 
+B
+
+B
+B
+B
+B
+
+B
+B
+B 
+Aù
+=Añ
+=Aé
+=Aá
+=AÙ
+=AÑ
+=AÉ
+=AÁ
+=A¹
+=A±
+=A©
+=A¡
+=A
+=A
+=A
+=A
+=Ar{Ab{AR{AB{A2{A"{A{A{@ä(ö@Ä(ö@€(ö@(ö@HQì@Qì?£×>
+žB|\Bx\Bt\Bp\Bl\Bh\Bd\B`\B\\BX\BT\BP\BL\BH\BD\B@\B<\B8\B4\B0\B,\B(\B$\B \B
+\B\B\B\B
+\B\B\B \Aù
+žAñ
+žAé
+žAá
+žAÙ
+žAÑ
+žAÉ
+žAÁ
+žA¹
+žA±
+žA©
+žA¡
+žA
+žA
+žA
+žA
+žAr=qAb=qAR=qAB=qA2=qA"=qA=qA=q@äzá@Äzá@€zá@zá@HõÃ@õÃ?ë
+>\)B|BxBtBpBlBhBdB`B\BXBTBPBLBHBDB@B<B8B4B0B,B(B$B B
+BBBB
+BBB Aù33Añ33Aé33Aá33AÙ33AÑ33AÉ33AÁ33A¹33A±33A©33A¡33A33A33A33A33ArffAbffARffABffA2ffA"ffAffAff@äÌÍ@ÄÌÍ@€ÌÍ@ÌÍ@I@	?33>B|£×Bx£×Bt£×Bp£×Bl£×Bh£×Bd£×B`£×B\£×BX£×BT£×BP£×BL£×BH£×BD£×B@£×B<£×B8£×B4£×B0£×B,£×B(£×B$£×B £×B
+£×B£×B£×B£×B
+£×B£×B£×B £×AùG®AñG®AéG®AáG®AÙG®AÑG®AÉG®AÁG®A¹G®A±G®A©G®A¡G®AG®AG®AG®AG®Ar\Ab\AR\AB\A2\A"\A\A\@å
+ž@Å
+ž@¥
+ž@
+
+ž@J=q@
+=q?zá>#×
+B|®Bx®Bt®Bp®Bl®Bh®Bd®B`®B\®BX®BT®BP®BL®BH®BD®B@®B<®B8®B4®B0®B,®B(®B$®B ®B
+®B®B®B®B
+®B®B®B ®Aù\)Añ\)Aé\)Aá\)AÙ\)AÑ\)AÉ\)AÁ\)A¹\)A±\)A©\)A¡\)A\)A\)A\)A\)AržRAbžRARžRABžRA2žRA"žRAžRAžR@åp€@Åp€@¥p€@
+p€@JáH@
+áH?Â>.{B|žRBxžRBtžRBpžRBlžRBhžRBdžRB`žRB\žRBXžRBTžRBPžRBLžRBHžRBDžRB@žRB<žRB8žRB4žRB0žRB,žRB(žRB$žRB žRB
+žRBžRBžRBžRB
+žRBžRBžRB žRAùp€Añp€Aép€Aáp€AÙp€AÑp€AÉp€AÁp€A¹p€A±p€A©p€A¡p€Ap€Ap€Ap€Ap€AráHAbáHARáHABáHA2áHA"áHAáHAáH@åÂ@ÅÂ@¥Â@
+Â@K
+@
+
+?
+>>8QìB|ÂBxÂBtÂBpÂBlÂBhÂBdÂB`ÂB\ÂBXÂBTÂBPÂBLÂBHÂBDÂB@ÂB<ÂB8ÂB4ÂB0ÂB,ÂB(ÂB$ÂB ÂB
+ÂBÂBÂBÂB
+ÂBÂBÂB ÂAù
+Añ
+Aé
+Aá
+AÙ
+AÑ
+AÉ
+AÁ
+A¹
+A±
+A©
+A¡
+A
+A
+A
+A
+As
+=Ac
+=AS
+=AC
+=A3
+=A#
+=A
+=A
+=@æ{@Æ{@Š{@{@L(ö@
+(ö?Qì>B\B|ÌÍBxÌÍBtÌÍBpÌÍBlÌÍBhÌÍBdÌÍB`ÌÍB\ÌÍBXÌÍBTÌÍBPÌÍBLÌÍBHÌÍBDÌÍB@ÌÍB<ÌÍB8ÌÍB4ÌÍB0ÌÍB,ÌÍB(ÌÍB$ÌÍB ÌÍB
+ÌÍBÌÍBÌÍBÌÍB
+ÌÍBÌÍBÌÍB ÌÍAùAñAéAáAÙAÑAÉAÁA¹A±A©A¡AAAAAs33Ac33AS33AC33A333A#33A33A33@æff@Æff@Šff@ff@LÌÍ@
+ÌÍ?>LÌÍB|×
+Bx×
+Bt×
+Bp×
+Bl×
+Bh×
+Bd×
+B`×
+B\×
+BX×
+BT×
+BP×
+BL×
+BH×
+BD×
+B@×
+B<×
+B8×
+B4×
+B0×
+B,×
+B(×
+B$×
+B ×
+B
+×
+B×
+B×
+B×
+B
+×
+B×
+B×
+B ×
+Aù®Añ®Aé®Aá®AÙ®AÑ®AÉ®AÁ®A¹®A±®A©®A¡®A®A®A®A®As\)Ac\)AS\)AC\)A3\)A#\)A\)A\)@æžR@ÆžR@ŠžR@žR@Mp€@
+p€?áH>W
+=B|áHBxáHBtáHBpáHBláHBháHBdáHB`áHB\áHBXáHBTáHBPáHBLáHBHáHBDáHB@áHB<áHB8áHB4áHB0áHB,áHB(áHB$áHB áHB
+áHBáHBáHBáHB
+áHBáHBáHB áHAùÂAñÂAéÂAáÂAÙÂAÑÂAÉÂAÁÂA¹ÂA±ÂA©ÂA¡ÂAÂAÂAÂAÂAs
+Ac
+AS
+AC
+A3
+A#
+A
+A
+@ç
+=@Ç
+=@§
+=@
+=@N{@{?(ö>aG®B|ë
+Bxë
+Btë
+Bpë
+Blë
+Bhë
+Bdë
+B`ë
+B\ë
+BXë
+BTë
+BPë
+BLë
+BHë
+BDë
+B@ë
+B<ë
+B8ë
+B4ë
+B0ë
+B,ë
+B(ë
+B$ë
+B ë
+B
+ë
+Bë
+Bë
+Bë
+B
+ë
+Bë
+Bë
+B ë
+Aù×
+Añ×
+Aé×
+Aá×
+AÙ×
+AÑ×
+AÉ×
+AÁ×
+A¹×
+A±×
+A©×
+A¡×
+A×
+A×
+A×
+A×
+As®Ac®AS®AC®A3®A#®A®A®@ç\)@Ç\)@§\)@\)@NžR@žR?p€>k
+B|õÃBxõÃBtõÃBpõÃBlõÃBhõÃBdõÃB`õÃB\õÃBXõÃBTõÃBPõÃBLõÃBHõÃBDõÃB@õÃB<õÃB8õÃB4õÃB0õÃB,õÃB(õÃB$õÃB õÃB
+õÃBõÃBõÃBõÃB
+õÃBõÃBõÃB õÃAùë
+Añë
+Aéë
+Aáë
+AÙë
+AÑë
+AÉë
+AÁë
+A¹ë
+A±ë
+A©ë
+A¡ë
+Aë
+Aë
+Aë
+Aë
+As×
+Ac×
+AS×
+AC×
+A3×
+A#×
+A×
+A×
+@ç®@Ç®@§®@®@O\)@\)?žR>uÂB}  By  Bu  Bq  Bm  Bi  Be  Ba  B]  BY  BU  BQ  BM  BI  BE  BA  B=  B9  B5  B1  B-  B)  B%  B!  B
+  B  B  B  B
+  B	  B  B  Aú  Aò  Aê  Aâ  AÚ  AÒ  AÊ  AÂ  Aº  A²  Aª  A¢  A  A  A  A  At  Ad  AT  AD  A4  A$  A  A  @è  @È  @š  @  @P  @  ?   >  B}
+=By
+=Bu
+=Bq
+=Bm
+=Bi
+=Be
+=Ba
+=B]
+=BY
+=BU
+=BQ
+=BM
+=BI
+=BE
+=BA
+=B=
+=B9
+=B5
+=B1
+=B-
+=B)
+=B%
+=B!
+=B
+
+=B
+=B
+=B
+=B
+=B	
+=B
+=B
+=Aú{Aò{Aê{Aâ{AÚ{AÒ{AÊ{AÂ{Aº{A²{Aª{A¢{A{A{A{A{At(öAd(öAT(öAD(öA4(öA$(öA(öA(ö@èQì@ÈQì@šQì@Qì@P£×@£×?¡G®>
+
+žB}{By{Bu{Bq{Bm{Bi{Be{Ba{B]{BY{BU{BQ{BM{BI{BE{BA{B={B9{B5{B1{B-{B){B%{B!{B
+{B{B{B{B
+{B	{B{B{Aú(öAò(öAê(öAâ(öAÚ(öAÒ(öAÊ(öAÂ(öAº(öA²(öAª(öA¢(öA(öA(öA(öA(öAtQìAdQìATQìADQìA4QìA$QìAQìAQì@è£×@È£×@š£×@£×@QG®@G®?¢\>=qB}
+žBy
+žBu
+žBq
+žBm
+žBi
+žBe
+žBa
+žB]
+žBY
+žBU
+žBQ
+žBM
+žBI
+žBE
+žBA
+žB=
+žB9
+žB5
+žB1
+žB-
+žB)
+žB%
+žB!
+žB
+
+žB
+žB
+žB
+žB
+
+žB	
+žB
+žB
+žAú=qAò=qAê=qAâ=qAÚ=qAÒ=qAÊ=qAÂ=qAº=qA²=qAª=qA¢=qA=qA=qA=qA=qAtzáAdzáATzáADzáA4záA$záAzáAzá@èõÃ@ÈõÃ@šõÃ@õÃ@Që
+@ë
+?£×
+>\)B}(öBy(öBu(öBq(öBm(öBi(öBe(öBa(öB](öBY(öBU(öBQ(öBM(öBI(öBE(öBA(öB=(öB9(öB5(öB1(öB-(öB)(öB%(öB!(öB
+(öB(öB(öB(öB
+(öB	(öB(öB(öAúQìAòQìAêQìAâQìAÚQìAÒQìAÊQìAÂQìAºQìA²QìAªQìA¢QìAQìAQìAQìAQìAt£×Ad£×AT£×AD£×A4£×A$£×A£×A£×@éG®@ÉG®@©G®@G®@R\@\?¥
+ž>záB}33By33Bu33Bq33Bm33Bi33Be33Ba33B]33BY33BU33BQ33BM33BI33BE33BA33B=33B933B533B133B-33B)33B%33B!33B
+33B33B33B33B
+33B	33B33B33AúffAòffAêffAâffAÚffAÒffAÊffAÂffAºffA²ffAªffA¢ffAffAffAffAffAtÌÍAdÌÍATÌÍADÌÍA4ÌÍA$ÌÍAÌÍAÌÍ@é@É@©@@S33@33?Šff>B}=qBy=qBu=qBq=qBm=qBi=qBe=qBa=qB]=qBY=qBU=qBQ=qBM=qBI=qBE=qBA=qB==qB9=qB5=qB1=qB-=qB)=qB%=qB!=qB
+=qB=qB=qB=qB
+=qB	=qB=qB=qAúzáAòzáAêzáAâzáAÚzáAÒzáAÊzáAÂzáAºzáA²záAªzáA¢záAzáAzáAzáAzáAtõÃAdõÃATõÃADõÃA4õÃA$õÃAõÃAõÃ@éë
+@Éë
+@©ë
+@ë
+@S×
+@×
+?§®>žRB}G®ByG®BuG®BqG®BmG®BiG®BeG®BaG®B]G®BYG®BUG®BQG®BMG®BIG®BEG®BAG®B=G®B9G®B5G®B1G®B-G®B)G®B%G®B!G®B
+G®BG®BG®BG®B
+G®B	G®BG®BG®Aú\Aò\Aê\Aâ\AÚ\AÒ\AÊ\AÂ\Aº\A²\Aª\A¢\A\A\A\A\Au
+žAe
+žAU
+žAE
+žA5
+žA%
+žA
+žA
+ž@ê=q@Ê=q@ª=q@=q@Tzá@zá?šõÂ>£×
+B}QìByQìBuQìBqQìBmQìBiQìBeQìBaQìB]QìBYQìBUQìBQQìBMQìBIQìBEQìBAQìB=QìB9QìB5QìB1QìB-QìB)QìB%QìB!QìB
+QìBQìBQìBQìB
+QìB	QìBQìBQìAú£×Aò£×Aê£×Aâ£×AÚ£×AÒ£×AÊ£×AÂ£×Aº£×A²£×Aª£×A¢£×A£×A£×A£×A£×AuG®AeG®AUG®AEG®A5G®A%G®AG®AG®@ê\@Ê\@ª\@\@U
+ž@
+ž?ª=q>šõÃB}\)By\)Bu\)Bq\)Bm\)Bi\)Be\)Ba\)B]\)BY\)BU\)BQ\)BM\)BI\)BE\)BA\)B=\)B9\)B5\)B1\)B-\)B)\)B%\)B!\)B
+\)B\)B\)B\)B
+\)B	\)B\)B\)AúžRAòžRAêžRAâžRAÚžRAÒžRAÊžRAÂžRAºžRA²žRAªžRA¢žRAžRAžRAžRAžRAup€Aep€AUp€AEp€A5p€A%p€Ap€Ap€@êáH@ÊáH@ªáH@áH@UÂ@Â?«
+>®{B}ffByffBuffBqffBmffBiffBeffBaffB]ffBYffBUffBQffBMffBIffBEffBAffB=ffB9ffB5ffB1ffB-ffB)ffB%ffB!ffB
+ffBffBffBffB
+ffB	ffBffBffAúÌÍAòÌÍAêÌÍAâÌÍAÚÌÍAÒÌÍAÊÌÍAÂÌÍAºÌÍA²ÌÍAªÌÍA¢ÌÍAÌÍAÌÍAÌÍAÌÍAuAeAUAEA5A%AA@ë33@Ë33@«33@33@Vff@ff?¬ÌÍ>³33B}p€Byp€Bup€Bqp€Bmp€Bip€Bep€Bap€B]p€BYp€BUp€BQp€BMp€BIp€BEp€BAp€B=p€B9p€B5p€B1p€B-p€B)p€B%p€B!p€B
+p€Bp€Bp€Bp€B
+p€B	p€Bp€Bp€AúáHAòáHAêáHAâáHAÚáHAÒáHAÊáHAÂáHAºáHA²áHAªáHA¢áHAáHAáHAáHAáHAuÂAeÂAUÂAEÂA5ÂA%ÂAÂAÂ@ë
+@Ë
+@«
+@
+@W
+>@
+>?®{>žQìB}záByzáBuzáBqzáBmzáBizáBezáBazáB]záBYzáBUzáBQzáBMzáBIzáBEzáBAzáB=záB9záB5záB1záB-záB)záB%záB!záB
+záBzáBzáBzáB
+záB	záBzáBzáAúõÃAòõÃAêõÃAâõÃAÚõÃAÒõÃAÊõÃAÂõÃAºõÃA²õÃAªõÃA¢õÃAõÃAõÃAõÃAõÃAuë
+Aeë
+AUë
+AEë
+A5ë
+A%ë
+Aë
+Aë
+@ë×
+@Ë×
+@«×
+@×
+@W®@®?¯\)>œp€B}
+By
+Bu
+Bq
+Bm
+Bi
+Be
+Ba
+B]
+BY
+BU
+BQ
+BM
+BI
+BE
+BA
+B=
+B9
+B5
+B1
+B-
+B)
+B%
+B!
+B
+
+B
+B
+B
+B
+
+B	
+B
+B
+Aû
+=Aó
+=Aë
+=Aã
+=AÛ
+=AÓ
+=AË
+=AÃ
+=A»
+=A³
+=A«
+=A£
+=A
+=A
+=A
+=A
+=Av{Af{AV{AF{A6{A&{A{A{@ì(ö@Ì(ö@¬(ö@(ö@XQì@Qì?°£×>Â\B}\By\Bu\Bq\Bm\Bi\Be\Ba\B]\BY\BU\BQ\BM\BI\BE\BA\B=\B9\B5\B1\B-\B)\B%\B!\B
+\B\B\B\B
+\B	\B\B\Aû
+žAó
+žAë
+žAã
+žAÛ
+žAÓ
+žAË
+žAÃ
+žA»
+žA³
+žA«
+žA£
+žA
+žA
+žA
+žA
+žAv=qAf=qAV=qAF=qA6=qA&=qA=qA=q@ìzá@Ìzá@¬zá@zá@XõÂ@õÂ?±ë
+>Ç®B}ByBuBqBmBiBeBaB]BYBUBQBMBIBEBAB=B9B5B1B-B)B%B!B
+BBBB
+B	BBAû33Aó33Aë33Aã33AÛ33AÓ33AË33AÃ33A»33A³33A«33A£33A33A33A33A33AvffAfffAVffAFffA6ffA&ffAffAff@ìÌÍ@ÌÌÍ@¬ÌÍ@ÌÍ@Y@?³33>ÌÌÍB}£×By£×Bu£×Bq£×Bm£×Bi£×Be£×Ba£×B]£×BY£×BU£×BQ£×BM£×BI£×BE£×BA£×B=£×B9£×B5£×B1£×B-£×B)£×B%£×B!£×B
+£×B£×B£×B£×B
+£×B	£×B£×B£×AûG®AóG®AëG®AãG®AÛG®AÓG®AËG®AÃG®A»G®A³G®A«G®A£G®AG®AG®AG®AG®Av\Af\AV\AF\A6\A&\A\A\@í
+ž@Í
+ž@­
+ž@
+ž@Z=q@=q?Žzá>Ñë
+B}®By®Bu®Bq®Bm®Bi®Be®Ba®B]®BY®BU®BQ®BM®BI®BE®BA®B=®B9®B5®B1®B-®B)®B%®B!®B
+®B®B®B®B
+®B	®B®B®Aû\)Aó\)Aë\)Aã\)AÛ\)AÓ\)AË\)AÃ\)A»\)A³\)A«\)A£\)A\)A\)A\)A\)AvžRAfžRAVžRAFžRA6žRA&žRAžRAžR@íp€@Íp€@­p€@p€@ZáH@áH?µÂ>×
+=B}žRByžRBužRBqžRBmžRBižRBežRBažRB]žRBYžRBUžRBQžRBMžRBIžRBEžRBAžRB=žRB9žRB5žRB1žRB-žRB)žRB%žRB!žRB
+žRBžRBžRBžRB
+žRB	žRBžRBžRAûp€Aóp€Aëp€Aãp€AÛp€AÓp€AËp€AÃp€A»p€A³p€A«p€A£p€Ap€Ap€Ap€Ap€AváHAfáHAVáHAFáHA6áHA&áHAáHAáH@íÂ@ÍÂ@­Â@Â@[
+@
+?·
+>>Ü(öB}ÂByÂBuÂBqÂBmÂBiÂBeÂBaÂB]ÂBYÂBUÂBQÂBMÂBIÂBEÂBAÂB=ÂB9ÂB5ÂB1ÂB-ÂB)ÂB%ÂB!ÂB
+ÂBÂBÂBÂB
+ÂB	ÂBÂBÂAû
+Aó
+Aë
+Aã
+AÛ
+AÓ
+AË
+AÃ
+A»
+A³
+A«
+A£
+A
+A
+A
+A
+Aw
+=Ag
+=AW
+=AG
+=A7
+=A'
+=A
+=A
+=@î{@Î{@®{@{@\(ö@
+(ö?žQì>áG®B}ÌÍByÌÍBuÌÍBqÌÍBmÌÍBiÌÍBeÌÍBaÌÍB]ÌÍBYÌÍBUÌÍBQÌÍBMÌÍBIÌÍBEÌÍBAÌÍB=ÌÍB9ÌÍB5ÌÍB1ÌÍB-ÌÍB)ÌÍB%ÌÍB!ÌÍB
+ÌÍBÌÍBÌÍBÌÍB
+ÌÍB	ÌÍBÌÍBÌÍAûAóAëAãAÛAÓAËAÃA»A³A«A£AAAAAw33Ag33AW33AG33A733A'33A33A33@îff@Îff@®ff@ff@\ÌÍ@
+ÌÍ?¹>æffB}×
+By×
+Bu×
+Bq×
+Bm×
+Bi×
+Be×
+Ba×
+B]×
+BY×
+BU×
+BQ×
+BM×
+BI×
+BE×
+BA×
+B=×
+B9×
+B5×
+B1×
+B-×
+B)×
+B%×
+B!×
+B
+×
+B×
+B×
+B×
+B
+×
+B	×
+B×
+B×
+Aû®Aó®Aë®Aã®AÛ®AÓ®AË®AÃ®A»®A³®A«®A£®A®A®A®A®Aw\)Ag\)AW\)AG\)A7\)A'\)A\)A\)@îžR@ÎžR@®žR@žR@]p€@
+p€?ºáH>ë
+B}áHByáHBuáHBqáHBmáHBiáHBeáHBaáHB]áHBYáHBUáHBQáHBMáHBIáHBEáHBAáHB=áHB9áHB5áHB1áHB-áHB)áHB%áHB!áHB
+áHBáHBáHBáHB
+áHB	áHBáHBáHAûÂAóÂAëÂAãÂAÛÂAÓÂAËÂAÃÂA»ÂA³ÂA«ÂA£ÂAÂAÂAÂAÂAw
+Ag
+AW
+AG
+A7
+A'
+A
+A
+@ï
+=@Ï
+=@¯
+=@
+=@^{@
+{?Œ(ö>ð£×B}ë
+Byë
+Buë
+Bqë
+Bmë
+Bië
+Beë
+Baë
+B]ë
+BYë
+BUë
+BQë
+BMë
+BIë
+BEë
+BAë
+B=ë
+B9ë
+B5ë
+B1ë
+B-ë
+B)ë
+B%ë
+B!ë
+B
+ë
+Bë
+Bë
+Bë
+B
+ë
+B	ë
+Bë
+Bë
+Aû×
+Aó×
+Aë×
+Aã×
+AÛ×
+AÓ×
+AË×
+AÃ×
+A»×
+A³×
+A«×
+A£×
+A×
+A×
+A×
+A×
+Aw®Ag®AW®AG®A7®A'®A®A®@ï\)@Ï\)@¯\)@\)@^žR@
+žR?œp€>õÂB}õÃByõÃBuõÃBqõÃBmõÃBiõÃBeõÃBaõÃB]õÃBYõÃBUõÃBQõÃBMõÃBIõÃBEõÃBAõÃB=õÃB9õÃB5õÃB1õÃB-õÃB)õÃB%õÃB!õÃB
+õÃBõÃBõÃBõÃB
+õÃB	õÃBõÃBõÃAûë
+Aóë
+Aëë
+Aãë
+AÛë
+AÓë
+AËë
+AÃë
+A»ë
+A³ë
+A«ë
+A£ë
+Aë
+Aë
+Aë
+Aë
+Aw×
+Ag×
+AW×
+AG×
+A7×
+A'×
+A×
+A×
+@ï®@Ï®@¯®@®@_\)@\)?ŸžR>úáHB~  Bz  Bv  Br  Bn  Bj  Bf  Bb  B^  BZ  BV  BR  BN  BJ  BF  BB  B>  B:  B6  B2  B.  B*  B&  B"  B
+  B  B  B  B  B
+  B  B  Aü  Aô  Aì  Aä  AÜ  AÔ  AÌ  AÄ  AŒ  AŽ  A¬  A€  A  A  A  A  Ax  Ah  AX  AH  A8  A(  A  A  @ð  @Ð  @°  @  @`  @   ?À  ?   B~
+=Bz
+=Bv
+=Br
+=Bn
+=Bj
+=Bf
+=Bb
+=B^
+=BZ
+=BV
+=BR
+=BN
+=BJ
+=BF
+=BB
+=B>
+=B:
+=B6
+=B2
+=B.
+=B*
+=B&
+=B"
+=B
+
+=B
+=B
+=B
+=B
+=B
+
+=B
+=B
+=Aü{Aô{Aì{Aä{AÜ{AÔ{AÌ{AÄ{AŒ{AŽ{A¬{A€{A{A{A{A{Ax(öAh(öAX(öAH(öA8(öA((öA(öA(ö@ðQì@ÐQì@°Qì@Qì@`£×@ £×?ÁG®?\B~{Bz{Bv{Br{Bn{Bj{Bf{Bb{B^{BZ{BV{BR{BN{BJ{BF{BB{B>{B:{B6{B2{B.{B*{B&{B"{B
+{B{B{B{B{B
+{B{B{Aü(öAô(öAì(öAä(öAÜ(öAÔ(öAÌ(öAÄ(öAŒ(öAŽ(öA¬(öA€(öA(öA(öA(öA(öAxQìAhQìAXQìAHQìA8QìA(QìAQìAQì@ð£×@Ð£×@°£×@£×@aG®@!G®?Â\?
+žB~
+žBz
+žBv
+žBr
+žBn
+žBj
+žBf
+žBb
+žB^
+žBZ
+žBV
+žBR
+žBN
+žBJ
+žBF
+žBB
+žB>
+žB:
+žB6
+žB2
+žB.
+žB*
+žB&
+žB"
+žB
+
+žB
+žB
+žB
+žB
+žB
+
+žB
+žB
+žAü=qAô=qAì=qAä=qAÜ=qAÔ=qAÌ=qAÄ=qAŒ=qAŽ=qA¬=qA€=qA=qA=qA=qA=qAxzáAhzáAXzáAHzáA8záA(záAzáAzá@ðõÂ@ÐõÂ@°õÂ@õÂ@aë
+@!ë
+?Ã×
+?®B~(öBz(öBv(öBr(öBn(öBj(öBf(öBb(öB^(öBZ(öBV(öBR(öBN(öBJ(öBF(öBB(öB>(öB:(öB6(öB2(öB.(öB*(öB&(öB"(öB
+(öB(öB(öB(öB(öB
+(öB(öB(öAüQìAôQìAìQìAäQìAÜQìAÔQìAÌQìAÄQìAŒQìAŽQìA¬QìA€QìAQìAQìAQìAQìAx£×Ah£×AX£×AH£×A8£×A(£×A£×A£×@ñG®@ÑG®@±G®@G®@b\@"\?Å
+ž?
+=qB~33Bz33Bv33Br33Bn33Bj33Bf33Bb33B^33BZ33BV33BR33BN33BJ33BF33BB33B>33B:33B633B233B.33B*33B&33B"33B
+33B33B33B33B33B
+33B33B33AüffAôffAìffAäffAÜffAÔffAÌffAÄffAŒffAŽffA¬ffA€ffAffAffAffAffAxÌÍAhÌÍAXÌÍAHÌÍA8ÌÍA(ÌÍAÌÍAÌÍ@ñ@Ñ@±@@c33@#33?Æff?
+ÌÍB~=qBz=qBv=qBr=qBn=qBj=qBf=qBb=qB^=qBZ=qBV=qBR=qBN=qBJ=qBF=qBB=qB>=qB:=qB6=qB2=qB.=qB*=qB&=qB"=qB
+=qB=qB=qB=qB=qB
+=qB=qB=qAüzáAôzáAìzáAäzáAÜzáAÔzáAÌzáAÄzáAŒzáAŽzáA¬záA€záAzáAzáAzáAzáAxõÃAhõÃAXõÃAHõÃA8õÃA(õÃAõÃAõÃ@ñë
+@Ñë
+@±ë
+@ë
+@c×
+@#×
+?Ç®?\)B~G®BzG®BvG®BrG®BnG®BjG®BfG®BbG®B^G®BZG®BVG®BRG®BNG®BJG®BFG®BBG®B>G®B:G®B6G®B2G®B.G®B*G®B&G®B"G®B
+G®BG®BG®BG®BG®B
+G®BG®BG®Aü\Aô\Aì\Aä\AÜ\AÔ\AÌ\AÄ\AŒ\AŽ\A¬\A€\A\A\A\A\Ay
+žAi
+žAY
+žAI
+žA9
+žA)
+žA
+žA	
+ž@ò=q@Ò=q@²=q@=q@dzá@$zá?ÈõÂ?ë
+B~QìBzQìBvQìBrQìBnQìBjQìBfQìBbQìB^QìBZQìBVQìBRQìBNQìBJQìBFQìBBQìB>QìB:QìB6QìB2QìB.QìB*QìB&QìB"QìB
+QìBQìBQìBQìBQìB
+QìBQìBQìAü£×Aô£×Aì£×Aä£×AÜ£×AÔ£×AÌ£×AÄ£×AŒ£×AŽ£×A¬£×A€£×A£×A£×A£×A£×AyG®AiG®AYG®AIG®A9G®A)G®AG®A	G®@ò\@Ò\@²\@\@e
+ž@%
+ž?Ê=p?záB~\)Bz\)Bv\)Br\)Bn\)Bj\)Bf\)Bb\)B^\)BZ\)BV\)BR\)BN\)BJ\)BF\)BB\)B>\)B:\)B6\)B2\)B.\)B*\)B&\)B"\)B
+\)B\)B\)B\)B\)B
+\)B\)B\)AüžRAôžRAìžRAäžRAÜžRAÔžRAÌžRAÄžRAŒžRAŽžRA¬žRA€žRAžRAžRAžRAžRAyp€Aip€AYp€AIp€A9p€A)p€Ap€A	p€@òáH@ÒáH@²áH@áH@eÂ@%Â?Ë
+
+?
+=B~ffBzffBvffBrffBnffBjffBfffBbffB^ffBZffBVffBRffBNffBJffBFffBBffB>ffB:ffB6ffB2ffB.ffB*ffB&ffB"ffB
+ffBffBffBffBffB
+ffBffBffAüÌÍAôÌÍAìÌÍAäÌÍAÜÌÍAÔÌÍAÌÌÍAÄÌÍAŒÌÍAŽÌÍA¬ÌÍA€ÌÍAÌÍAÌÍAÌÍAÌÍAyAiAYAIA9A)AA	@ó33@Ó33@³33@33@fff@&ff?ÌÌÍ?B~p€Bzp€Bvp€Brp€Bnp€Bjp€Bfp€Bbp€B^p€BZp€BVp€BRp€BNp€BJp€BFp€BBp€B>p€B:p€B6p€B2p€B.p€B*p€B&p€B"p€B
+p€Bp€Bp€Bp€Bp€B
+p€Bp€Bp€AüáHAôáHAìáHAäáHAÜáHAÔáHAÌáHAÄáHAŒáHAŽáHA¬áHA€áHAáHAáHAáHAáHAyÂAiÂAYÂAIÂA9ÂA)ÂAÂA	Â@ó
+@Ó
+@³
+@
+@g
+>@'
+>?Î{?
+(öB~záBzzáBvzáBrzáBnzáBjzáBfzáBbzáB^záBZzáBVzáBRzáBNzáBJzáBFzáBBzáB>záB:záB6záB2záB.záB*záB&záB"záB
+záBzáBzáBzáBzáB
+záBzáBzáAüõÃAôõÃAìõÃAäõÃAÜõÃAÔõÃAÌõÃAÄõÃAŒõÃAŽõÃA¬õÃA€õÃAõÃAõÃAõÃAõÃAyë
+Aië
+AYë
+AIë
+A9ë
+A)ë
+Aë
+A	ë
+@ó×
+@Ó×
+@³×
+@×
+@g®@'®?Ï\)?
+žRB~
+Bz
+Bv
+Br
+Bn
+Bj
+Bf
+Bb
+B^
+BZ
+BV
+BR
+BN
+BJ
+BF
+BB
+B>
+B:
+B6
+B2
+B.
+B*
+B&
+B"
+B
+
+B
+B
+B
+B
+B
+
+B
+B
+Aý
+=Aõ
+=Aí
+=Aå
+=AÝ
+=AÕ
+=AÍ
+=AÅ
+=Aœ
+=Aµ
+=A­
+=A¥
+=A
+=A
+=A
+=A
+
+=Az{Aj{AZ{AJ{A:{A*{A{A
+{@ô(ö@Ô(ö@Ž(ö@(ö@hQì@(Qì?Ð£×?!G®                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B| XB{Ýf¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ÔB{äþBy	¬Bv5@¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|
+OB{óyBy(Bv<ÖBsaBp¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|+ÊB|õBy&£BvKQBsp Bp®Bm¹\Bjäð¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|:FB|pBy5
+BvYÍBs~{Bp£)BmÇ×BjìBh4Be<È¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|HÁB|
+ëByCBvhHBsöBp±¥BmÖSBjûBh¯BeD^Bbi
+B_ ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|W<B|-gByRBvvÃBsrBpÀ BmäÎBk	}Bh.+BeRÙBbwB_6B\ÀäBYìx¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|e·B|;âBy`Bv
+?Bs©íBpÎBmóJBkøBh<ŠBeaUBbB_ª±B\Ï_BYôBWŒBTDP¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|t3B|J]Byo
+BvºBsžhBpÝBnÅBk&sBhK"BeoÐBb~B_¹-B\ÝÛBZBW'7BTKæBQpBN(¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|®B|XØBy}Bv¢5BsÆãBpëBn@Bk4ïBhYBe~KBb¢úB_ÇšB\ìVBZBW5³BTZaBQBN£ŸBKÈlBHô ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|)B|gTByBv°°BsÕ_Bpú
+Bn
+»BkCjBhhBeÇBb±uB_Ö#B\úÒBZBWD.BThÝBQBN²9BKÖçBHûBF DBCKØ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|¥B|uÑByBv¿.BsãÜBqBn-9BkQçBhvBeDBb¿òB_ä¡B]	OBZ-ýBWR¬BTwZBQBNÀ·BKåeBI
+BF.ÁBCSpB@x
+B=£²¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|®B|LByšûBvÍ©BsòWBqBn;ŽBk`bBh
+Be©¿BbÎmB_ó
+B]ÊBZ<yBWa'BT
+ÕBQªBNÏ2BKóàBIBF==BCaëB@B=«HB:ÏöB7û¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ŒB|ÇBy·uBvÜ$Bt ÓBq%BnJ/BknÞBhBež:BbÜéB`B]&EBZJôBWo¢BTQBQžÿBNÝ­BL\BI'
+BFKžBCpgB@B=¹ÃB:ÞqB8 B5'ÎB2Sb¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ËB|¡BByÅñBvêBtMBq3üBnX«Bk}YBh¢BeÆ¶BbëdB`B]4ÁBZYoBW~
+BT¢ÌBQÇzBNì)BL×BI5
+BFZ4BC~âB@£B=È?B:ìíB8B56IB2ZøB/ŠB,«:¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ÙB|¯ŸByÔlBvùBt
+ÉBqBwBng%BkÔBh°BeÕ1BbùßB`
+B]C<BZgêBWBT±GBQÕõBNú€BLRBIDBFh¯BC]B@²
+B=ÖºB:ûhB8 B5DÅB2isB/!B,²ÐB)×~B'¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|è
+B|Ÿ9ByâçBwBt,DBqPòBnu¡BkOBhŸýBeã¬Bc[B`-	B]Q·BZvfBWBT¿ÂBQäqBO	BL-ÍBIR|BFw*BCÙB@ÀB=å5B;	äB8.B5S@B2wïB/B,ÁKB)åùB'
+šB$/VB!Zê¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|öB|ÌµByñcBwBt:¿Bq_nBn
+BkšÊBhÍyBeò'BcÕB`;B]`3BZáBW©BTÎ>BQòìBOBL<IBI`÷BF
+¥BCªTB@ÏB=ó±B;_B8=
+B5aŒB2jB/«B,ÏÇB)ôuB'#B$=ÑB!bB
+.B²Â¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}B|Û0ByÿÞBw$BtI;BqméBnBk·FBhÛôBf ¢Bc%QB`IÿB]n­BZ\BWž
+BTÜ¹BRgBO&BLJÄBIorBF!BCžÏB@Ý}B>,B;&ÚB8KB5p7B2åB/¹B,ÞBB*ðB''B$LMB!pûB
+©BºXBßB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}B|é«BzYBw3BtW¶Bq|eBn¡BkÅÁBhêoBf
+Bc3ÌB`XzB]})BZ¡×BWÆ
+BTë4BRãBO4BLY?BI}îBF¢BCÇJB@ëùB>§B;5UB8ZB5~²B2£aB/ÈB,ìœB*lB'6B$ZÈB!wB
+€%BÈÓBíB0B6ÞBbr¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}!úB|ø&Bz
+ÕBwABtf1BqàBn¯BkÔ=BhøëBf
+BcBGB`föB]€BZ°RBWÕBTù¯BR
+]BOC
+BLg»BIiBF±BCÕÆB@útB>"B;CÑB8hB5-B2±ÜB/ÖB,û9B*çB'DB$iDB!òB
+² B×OBûýB «BEYBjB
+¶B
+ºJ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}0uB}€Bz+RBwP Btt¯Bq]BnŸ
+BkâºBihBf,BcPÅB`usB]!BZŸÐBWã~BU,BR,ÛBOQBLv7BIæBF¿BCäCBAñB>- B;RNB8vüB5«B2ÀYB/åB-	¶B*.dB'SB$wÁB!oB
+Á
+BåÌB
+zB/)BS×Bx
+B
+3B
+ÁâBæB$¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}>ñB}Bz9ÍBw^|Bt*Bq§ØBnÌBkñ5BiãBf:Bc_@B`ïB]šBZÍKBWñùBUšBR;VBO`BL³BI©aBFÎBCòŸBAmB><B;`ÉB8
+xB5ª&B2ÎÔB/óB-1B*<ßB'aB$<B!ªëB
+ÏBôGBöB=€BbRBB
+«¯B
+Ð]Bõ
+BºB>hAþÓø¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}MlB}#BzHIBwl÷Bt¥Bq¶TBnÛBkÿ°Bi$_BfI
+Bcm»B`jB]·BZÛÇBX uBU%#BRIÑBOnBL.BI·ÜBFÜBD9BA%çB>JB;oEB8óB5ž¡B2ÝPB0þB-&¬B*K[B'p	B$·B!¹fB
+ÞB
+ÃB'qBLBpÎB|B
+º*B
+ÞÙBB(5BLãAþã#Aù,Aóš¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}[çB}2BzVÄBw{rBt !BqÄÏBné}Bl,Bi2ÚBfWBc|7B` åB]ÅBZêBBXðBU3BRXMBO|ûBL¡©BIÆXBFëBDŽBA4cB>YB;}¿B8¢nB5Ç
+B2ëËB0yB-5(B*YÖB'~B$£3B!ÇáB
+ìB
+>B5ìBZBIB£÷B
+ÈŠB
+íTBB6±B[_Aÿ AùIwAóÔAíÜ1Aè3X¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}jbB}@Bze?BwîBt®BqÓJBn÷ùBl
+§BiAUBffBc²B`¯`B]ÔBZøœBX
+kBUBBRfÈBOwBL°%BIÔÓBFùBD
+0BABÞB>gB;;B8°éB5ÕB2úFB0
+õB-C£B*hQB' B$±®B!Ö\B
+û
+B
+¹BDgBiBÄB²sB
+×!B
+ûÏB ~BE,BiÚAÿ
+AùfnAó¯ËAíù'AèBAâáAÜã¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}xÝB}O
+BzsºBwhBtœBqáÆBotBl+"BiOÑBftBc-B`œÜB]âB[8BX+çBUPBRuCBOòBLŸ BIãOBGýBD,«BAQYB>vB;¶B8¿dB5äB3ÁB0-oB-R
+B*vÍB'{B$À)B!äØB	B
+.4BRãBwB?BÀîB
+åB
+
+KB.ùBS§BxVAÿ:AùeAóÌÂAî
+Aè_{Aâš×AÜò4A×;AÑž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}YB}]Bz5BwŠäBtËBqð@BoïBl9Bi^LBfúBc§©B`ÌWB]ñB[ŽBX:bBU_BR¿BOšmBLÍBIñÊBGxBD;'BA_ÕB>B;©1B8ÍàB5òB3<B0;ëB-`B*
+GB'©öB$Î¥B!óSBB
+<°Ba^B
+Bª»BÏiB
+ôB
+ÆB=tBb#BÑAÿVÿAù [Aóé·Aî3Aè|rAâÅÎAÝ+A×XAÑ¡äAËëAAÆBh¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ÔB}lBz±Bwµ_BtÚ
+BqþŒBo#jBlHBilÇBfvBc¶$B`ÚÒB]ÿB[$/BXHÝBUmBR:BO¶èBLÛBJ EBG$óBDI¢BAnPB>ÿB;·­B8Ü[B6	B3%žB0JfB-oB*ÃB'žqB$ÝB"ÎB&}B
+K+BoÙBB¹6BÝäBB
+'ABKïBpBLAÿsõAùœQAô®AîP
+AègAââÅAÝ,"A×u~AÑŸÛAÌ7AÆQAÀñAºò¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}€OB}z~Bz,BwÃÚBtèBr
+7Bo1åBlVBi{BBfðBcÄB`éNB^
+üB[2ªBXWYBU|BR µBOÅdBLêBJÀBG3oBDX
+BA|ËB>¡zB;Æ(B8ê×B6
+B343B0XáB-}B*¢>B'ÆìB$ëB"IB4÷B
+YŠB~UB£BÇ±Bì`BB
+5ŒBZkBB£ÇAÿëAùÚHAô#¥AîmAè¶^Aâÿ»AÝIA×uAÑÛÒAÌ%.AÆnAÀ·çA»DAµJ¡A¯¡È¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}²ÊB}ùBz­§BwÒVBt÷Br²Bo@aBleBiœBf®lBcÓB`÷ÈB^
+wB[A&BXeÔBUBR¯1BOÓßBLøBJ
+<BGAêBDfBAGB>¯õB;Ô£B8ùRB6
+ B3B¯B0g]B-
+B*°¹B'ÕhB$úB"
+ÄBCsB
+h!BÏB±~BÖ-BúÛBB
+D8BhæBB²CAÿ­âAù÷?Aô@AîøAèÓUAã
+±AÝfA×¯kAÑøÇAÌB%AÆAÀÔÞA»
+;AµgA¯°ôA©úQA€Qx¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ÁFB}vBzŒ$BwàÓBuBr*0BoNÞBlsBi;BfŒéBcáBaFB^*ôB[O¢BXtQBU BRœ®BOâ\BM
+BJ+¹BGPgBDuBAÄB>ŸrB;ã!B9ÏB6,}B3Q,B0uÚB-B*¿7B'ãåB%B"-BBQðB
+vBMB¿ûBä©B	XB.B
+RµBwcBBÀÀAÿÊÜAú9Aô]AîŠóAèðOAã9¬AÝ	A×ÌeAÒÂAÌ_AÆš{AÀñÙA»;6AµA¯ÍïAªKA€`šAªA,¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ÏÁB}¥òBzÊ BwïNBuüBr8«Bo]YBlBiŠ¶BfËdBcðBaÁB^9oB[^
+BXÌBU§zBRÌ)BOðØBMBJ:4BG^ãBDBAš?B>ÌîB;ñB9JB6:ùB3_§B0UB-©B*Í²B'òaB%B";œB`kB
+
+B©ÈBÎvBó%BÓB<B
+a0B
+ßBªBÏ;AÿçÓAú10AôzAîÃéAé
+FAãV£AÝÿA×é\AÒ2¹AÌ|AÆÅrAÁÏA»X+Aµ¡A¯êæAª4BA€}AÆûAXAYµA°Ü¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}Þ=B}ŽmBzÙBwýÊBu"xBrG&BokÔBlBiµ1BfÙàBcþBa#<B^GëB[lBXGBUµöBRÚ€BOÿRBM$BJH°BGm^BD
+BA¶»B>ÛiB< B9$ÆB6ItB3n"B0ÑB-·B*Ü-B( ÜB%%B"J9BnçB
+BžCBÜòB B&NBJýB
+o«BYB¹BÝ·B eAúN&AôAîàßAé*=AãsAÝŒöAØSAÒO¯AÌ
+AÆâiAÁ+ÅA»u"AµŸA°ÛAªQ9A€AãòA-OAv«AÀA	eA`¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ìžB}ÂèBzçBx
+EBu0óBrU¢BozPBlþBiÃ¬Bfè[Bd
+	Ba1žB^VfB[{BXÃBUÄqBRéBP
+ÎBM2|BJW*BG{ÙBD BAÅ6B>éäB<B93AB6WïB3|B0¡LB-ÅúB*ê©B(WB%4B"XŽB}bB
+¢BÆ¿BëmBB4ÊBYxB
+~&B¢ÕBÇBì1B àAúk
+AôŽyAîýÖAéG3AãAÝÙíAØ#IAÒlŠAÌ¶AÆÿ_AÁHŒA»AµÛuA°$ÒAªn/A€·A éAJFA¢AÜÿA&[AožAyr)An y¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}û3B}ÑdBzöBxÀBu?oBrd
+BoËBl­zBiÒ(BföÖBdBa@3B^dáB[BX®>BUÒìBR÷BP
+IBM@÷BJeŠBGTBD¯BAÓ±B>ø`B<
+B9AŒB6fkB3B0¯ÇB-ÔvB*ù$B(
+ÒB%BB"g/BÝB
+°BÕ:BùéB
+BCEBgóB
+¢B±PBÕþBú­B [AúAôÑpAïÍAéd)Aã­AÝöãAØ@?AÒAÌÒùAÇ
+VAÁe³A»¯AµølA°AÉAª%A€ÔA
+ßAg;A°AùöACRA¯Ay¬An>ÑAbÑAWÛ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~	®B}ßßB{Bx)<BuMêBrrBoGBl»õBià£BgRBd* BaN®B^s\B[
+BXŒ¹BUáhBSBP*ÄBMOsBJt!BGÏBDœ~BAâ,B?ÚB<+B9P8B6tæB3B0ŸCB-âñB+B(,NB%PüB"uªBYB
+¿BãµBdB-BQÁBvoB
+
+B¿ËBäzB	(B -ÖAú¥
+AôîgAï7ÃAé AãÊ}AÞÙAØ]6AÒŠAÌïïAÇ9MAÁ©A»ÌA¶cA°^¿Aªš
+A€ñyA:ÕA2AÍAëA`IA©ŠAyæAnxŸAc
+yAW3AL0íA@ß=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~*B}îZB{Bx7·Bu\eBrBo¥ÂBlÊpBiïBgÍBd8{Ba]*B^ØB[ŠBXË4BUïãBSBP9@BM]îBJBG§KBDËùBAð§B?VB<:B9^²B6aB3šB0ÌŸB-ñlB+B(:ÉB%_wB"&BšÔB
+ÍBò1BßB;B`<BêB
+©BÎGBòõB£B <RAúÂAõ
+]AïTºAéAãçsAÞ0ÐAØz-AÒÃAÍ
+æAÇVCAÁA»èýA¶2YA°{¶AªÅA¥oAWÌA¡)Aê
+A3âA}?AÆAzñAn²«AcEeAWØ ALjÛA@ýA5OA*>¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~&¥B}üÕB{!BxF2BujàBrBoŽ=BlØìBiýBg"HBdF÷Bak¥B^SB[µBXÙ°BUþ^BS#
+BPG»BMliBJBGµÆBDÚtBAÿ#B?#ÑB<HB9m.B6ÜB3¶B0Û9B-ÿèB+$B(IDB%móB"¡B·OB
+ÛþB ¬B%ZBJ	Bn·BeB
+žBÜÂBpB&B JÍAúÞ÷Aõ(TAïq±Aé»
+AäjAÞMÇAØ#AÒàAÍ)ÝAÇs9AÁŒAŒóA¶OOA°­Aªâ	A¥+fAtÃAŸA|APÙA5AãAzYÞAnìAcSAX
+AL€ÇAA7A5Ê=A*\÷A
+ï±A¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~5 B~
+QB{/ÿBxT­Buy\Br
+BoÂžBlçgBj
+Bg0ÄBdUrBaz B^ÏB[Ã}BXè+BV
+ÚBS1BPV6BMzäBJBGÄABDèðBB
+B?2LB<VûB9{©B6 WB3ÅB0éŽB.bB+3B(WÀB%|nB"¡
+BÅËB
+êyB'B3ÖBXB}2B¡áB
+ÆBë=BìB4B YHAúûíAõEJAï§AéØAä!aAÞjœAØŽAÒýwAÍFÓAÇ0AÁÙAŒ"éA¶lFA°µ£AªþÿA¥H]A¹AÛA$sAmÏA·,A AzËAo&
+Ac¹@AXKúALÞµAAqoA6)A*äA)AŒYAO@ùúÆ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~CB~ÌB{>zBxc)Bu×Br¬
+BoÑ4BlõâBjBg??BdcíBaB^­JB[ÑøBXö§BVUBS@BPd²BM`BJ®BGÒŒBD÷kBB
+B?@ÈB<evB9$B6®ÓB3ÓB0ø/B.
+ÞB+AB(f:B%éB"¯BÔFB
+øôB
+£BBQBfÿB®B°\B
+Õ
+Bù¹B
+gBCB gÄAûäAõbAAï«AéôúAä>WAÞŽAØÑAÓmAÍcÊAÇ­'AÁöAŒ?àA¶=A°ÒA«öA¥eSA®¯Aø
+AAiAÆAÔ#A
+AzÍžAo`rAcó-AX
+çAM¢AA«\A6>A*ÐÑAcAöFA@ú7v@ã\ë@Ì¹¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~RB~(IB{LøBxqŠBuTBr»Boß±Bm_Bj)BgMŒBdrjBaB^»ÇB[àvBY$BV)ÒBSNBPs/BMÝBJŒBGá:BEèBB*B?OEB<sóB9¢B6œPB3áþB1­B.+[B+P	B(tžB%fB"ŸBâÃB
+rB, BPÎBu}B+BŸÙB
+ãB	6B,äBQB vAAû5ßAõ;AïÈAêõAä[QAÞ€®AØî
+AÓ7hAÍÅAÇÊ!AÂ~AŒ\ÛA¶Š7A°ïA«8ñA¥MAËªAA^cA§ÁAñ
+A:zA{­AohAd-"AX¿ÜAMRAAåQA6x
+A+
+ÆAA0;AÂõ@ú«a@ãÐÕ@ÌöJ@¶¿@x^¿  ¿  ¿  ¿  ¿  ¿  B~`B~6ÅB{[sBx!Bu€ÐBrÉ~Boî,BmÛBj7Bg\7BdæBa¥B^ÊBB[îñBYBV8NBS\üBPªBMŠYBJËBGïµBEdBB9B?]ÀB<nB9§
+B6ËËB3ðzB1(B.9ÖB+^
+B(3B%§áB"ÌBñ>B
+ìB:B_JBøBšŠBÍUB
+òB	±B;`B`B ŒAûRÕAõ2AïåAê.ëAäxHAÞÁ¥AÙ
+AÓT^AÍ»AÇçAÂ0uAŒyÑA¶Ã.A±
+A«UçA¥DAè¡A1ýA{ZAÄ·AAWqA{AAoÔUAdgAXùÊAMAB>A6±ùA+D³A×nAj(Aüã@û:@äD¯@Íj$@¶@µ@Ú@dnD¿  ¿  ¿  ¿  B~o
+B~E?B{iîBxBu³KBr×ùBoüšBm!VBjFBgj³BdaBaŽB^ØŸB[ýlBY"BVFÉBSkwBP&BMŽÔBJÙBGþ1BE"ßBBGB?l<B<êB9µB6ÚFB3þõB1#£B.HRB+m B(®B%¶]B"Û
+Bÿ¹B
+$hBIBmÄBsB·"BÛÐB
+ ~B	%-BIÛBnB 8AûoÌAõ¹)Að
+AêKâAä?AÞÞAÙ'øAÓqUAÍº±AÈAÂMkAŒÈA¶à%A±)A«rÞA¥Œ;A ANôAQAá­A+
+AtgA{{ApBAd üAY3·AMÆqABY,A6ëæA+~ A [A€A	6Ð@û@äž@ÍÝþ@·s@ (è@N]@dç€@72@	ëÊ¿  ¿  B~}B~S»B{xiBxBuÁÆBræuBp
+#Bm/ÑBjTBgy.BdÜBaÂB^ç9B\
+çBY0BVUDBSyòBP¡BMÃOBJçþBH
+¬BE1ZBBV	B?z·B<eB9ÄB6èÂB4
+pB12
+B.VÍB+{{B( *B%ÄØB"éB 5B
+2ãBWB|@B îBÅBêKB
+úB	3šBXVB}B ¡³AûÂAõÖAð|AêhÙAä²5AÞûAÙDïAÓKAÍ×šAÈ!AÂjaAŒ³ŸA¶ýA±FxA«ÕA¥Ù1A "AkëAµGAþ€AHA]A{µtApH/AdÚéAYm€AN ^ABA7%ÓA+žA KHAÞA	pœ@üï@å,d@ÎQÙ@·wM@ Â@Â7@eÏX@8A@
+e)?¹`%?=¥@B~
+B~b7B{äBx«BuÐABrôïBpBm>MBjbûBg©Bd¬XBaÑB^õŽB\cBY?BVc¿BSnBP­
+BMÑÊBJöyBH'BE?ÖBBdB?2B<­áB9ÒB6÷=B4ìB1@B.eHB+öB(®¥B%ÓSB"øB 
+°B
+A^Bf
+B»B¯iBÔBøÆB
+
+tB	B#BfÒBB °.Aû©¹AõóAð<rAê
+ÏAäÏ,AßAÙaåAÓ«BAÍôAÈ=ûAÂXAŒÐµA·A±cnA«¬ËA¥ö(A ?
+AáAÒ>AAd÷A®TA{ïaAp
+Ae×AY§AN:KABÍA7_ÀA+ò{A 
+5AðA	ªª@üzÉ@å >@ÎÅ³@·ë(@¡@6@f·
+@9õ@
+LÞ?»/??Ÿ=
+f$¿  B{{BxºBuÞŒBskBp(BmLÇBjqvBg%BdºÓBaßB_0B\(ÞBYMBVr;BSéBP»BMàFBKôBH)¢BENQBBrÿB?®B<Œ\B9á
+B7¹B4*gB1OB.sÄB+rB(œ B%áÎB#}B ++B
+OÚBtB6BœåBâBAB
++ðB	PBuLBûB ŸªAûÆ¯Aö
+AðYiAê¢ÅAäì"Aß5AÙ~ÜAÓÈ9AÎAÈZòAÂ€OAŒí«A·7A±eA«ÉÁAŠ
+A \{A¥ØAï5A8AîAËKA|)OApŒ	AeNÃAYá~ANt9ACóA7­A,,hA ¿"AQÝA	ä@üî£@æ@Ï9@ž_@¡w@©ì@gÁ@9é©@
+4?Œþö?C)=ES?;ò¿
+¿  ¿  BuæSBsçBp6Bm[CBjñBg€BdÉNBaíýB_«B\7YBY\BV¶BS¥dBPÊBMîÁBKoBH8
+BE\ÌBBzB?Š)B<Ê×B9ïB74B48âB1]B.?B+ŠíB(ËB%ðJB#øB 9ŠB
+^UBB§²BÌ`BñBœB
+:kB	_BÈBšvB Í$AûãŠAö-Aðv_Aê¿ŒAå	AßRuAÙÒAÓå/AÎ.AÈwéAÂÁEAœ
+¢A·SÿA±[A«æžAŠ0A yqAÂÎA
++AUAåAèAA|c<ApõöAe±AZkAN®%AC@àA7ÓA,fUA ùAÊA
+
+@ýb}@æò@Ï­g@žÒÜ@¡øQ@
+Æ@hu@:Ñ^@
+
+G?ŸÎ_?FÈa=@Y<°ø¿  ¿  ¿  ¿  Bp>,BmiÀBjmBg³
+Bd×ÊBaüxB_!'B\EÖBYjBV2BS³áBPØBMý=BK!ìBHFBEkHBB÷B?Ž¥B<ÙSB9þB7"°B4G_B1l
+B.»B+µjB(ÚB%þÆB##uB H#B
+lÑBB¶.BÚÜBÿB$9B
+HçB	mBDB¶òB Û¡Aü AöIûAðXAêÜµAå&AßonAÙžËAÔ'AÎKAÈáAÂÞ>Aœ'A·p÷A±ºTA¬±AŠM
+A jAßÇA)#ArA»ÝA:A|-Aq/çAeÂ¢AZU\ANèACzÑA8
+A, FA!3AÅ»A
+Xu@ýÖ_@æûÔ@Ð!I@¹FŸ@¢l3@š@in9@;¹"@
+?Àç?Jgr=º=2¿  ¿  ¿  ¿  ¿  ¿  BjBgÁBdæEBb
+ôB_/¢B\TPBYxÿBV®BSÂ\BPç
+BN
+¹BK0gBHUBEyÄBBrB?Ã B<çÏB:
+}B71+B4UÚB1zB.7B+ÃåB(èB&
+BB#1ðB VB
+{MBûBÄ©BéWBB2ŽB
+WcB	|B ¿BÅnB ê
+Aü
+AöfòAð°OAêù«AåCAßeAÙÕÁAÔ
+AÎh{AÈ±×AÂû4AœDA·îA±×KA¬ §AŠjA ³aAüœAFAwAØÓA"0A|×AqiÔAeüAZIAO"ACŽŸA8GyA,Ú3A!líAÿšA
+c@þJ:@ço¯@Ð#@¹º@¢à
+@@jUî@< Ö@ë¿?ÂmQ?ND=¹F=L1¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BdíÜBboB_>
+B\bÌBYzBV¬(BSÐ×BPõBN4BK>âBHcBE?BB¬íB?ÑB<öJB:øB7?§B4dUB1B.­²B+Ò`B(÷B&œB#@kB eB
+ÈB®vBÓ%B÷ÓB
+BA/B
+eÞB	B¯;BÓéB øAü:AöèAðÍEAë¢Aå_ÿAß©[AÙòžAÔ<AÎ
+qAÈÎÎAÃ+AœaA·ªäA±ôAA¬=AŠûA ÐWAŽAcA¬mAõÊA?'A}Aq£ÂAf6|AZÉ6AO[ðACî«A8fA- A!ŠÛA9A
+ÌO@þŸ@çã@Ñý@º.r@£Sç@y\@k=¢@=@Ós?Ä<¹?Q¥=Ö
+Ê=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B_EŽB\qGBYõBVº€BSßRBQ BN(¯BKM^BHr
+BEºBB»iB?àB=ÅB:)tB7N"B4rÐB1B.Œ-B+àÛB)B&*8B#NçB sB
+CBŒòBá BNB*ýBO«B
+tYB	Bœ¶BâdBAüWAö ßAðê;Aë3Aå|õAßÆRAÚ¯AÔY
+AÎ¢hAÈëÅAÃ5!Aœ~~A·ÇÛA²7A¬ZAŠ£ñA íNA6«AAÉdAÁA\
+A}JôAqÝ®AfpiA[$AOÞAD(A8»RA-N
+A!àÈAsA
+=@ÿ1î@èWc@Ñ|Ø@º¢L@£ÇÁ@í6@l%V@>p?@»(?Æ
+!?UCç=ó|V=ü§¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BYBVÉBSíÍBQ|BN7*BK[ØBHBE¥6BBÉäB?îB=AB:7ïB7\B4LB1¥úB.ÊšB+ïWB)B&8³B#]bB B
+Š¿BËmBðBÊB9xB^&B
+ÕB	§BÌ1BðßBAütyAöœÕAñ2AëPAåëAßãHAÚ,¥AÔvAÎ¿_AÉ»AÃRAœuA·äÑA²..A¬wAŠÀçA¡
+DAS¡AþAæ[A/·AyA}áArAfªVA[=AOÏËADbA8õ@A-úA"ŽA­oA
+@*@ÿ¥È@èË=@Ñð²@»'@€;@a@m
+
+@?Wô@¢Ü?ÇÛ?Xâž>9r=Œó5¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BSõeBQ øBNEŠBKjUBHBE³±BBØ`B?ýB=!œB:FkB7kB4ÈB1ŽvB.Ù%B+ýÓB)"B&G0B#kÞB B
+µ;BÙéBþB#FBGôBl£B
+QB	µÿBÚ®Bÿ\B$
+AüqAöÚÎAñ$+AëmAå¶äAà AAÚIAÔúAÎÜWAÉ%ŽAÃoAœžmAžÊA²K'A¬AŠÝàA¡'=ApA¹öASAL°A
+A}ŸÓArQAfäGA[wAP	ŒADvA9/1A-ÁìA"TŠAç`A
+zA 
+Õ@é?@Òd@»	@€¯~@Ôó@môÐ@@?ž@¡?É«?\Ê>µž=ÙéÁ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BNM=BKxÐBH~BEÂ-BBæÛB@
+B=08B:TçB7yB4CB1ÂòB.ç B,
+NB)0ýB&U«B#zYB B
+Ã¶BèdB
+B1ÁBVpB{
+B
+ÌB	Ä{Bé)B
+×B2Aü®hAö÷ÅAñA!Aë~AåÓÛAà
+7AÚfAÔ¯ñAÎùMAÉBªAÃAœÕdAž
+ÁA²h
+A¬±zAŠú×A¡D3AAÖíA IAiŠA³A}øÀArzAg
+5A[°ïAPC©ADÖdA9i
+A-ûØA"A!NA
+ŽA FÂ@é²ù@ÒØn@»ýã@¥#X@HÍ@nÜ@A'm@rV?Ëz|?` >%0þ=öàN¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BH¥BEÐšBBõVB@B=>³B:caB7B4¬¿B1ÑmB.öB,ÊB)?xB&d&B#ÕB ­B
+Ò1BöàBB@<BdëBB
+®HB	ÒöB÷€B
+SBAAüË_A÷ŒAñ^Aë§uAåðÑAà:.AÚAÔÌçAÏDAÉ_¡AÃšýAœòZAž;·A²
+A¬ÎqA§ÍA¡a*AªAóãA=@AAÏùA~2¬ArÅgAgX!A[êÜAP}AEQA9£
+A.5ÆA"ÈA[:A
+íõA °@ê&Ô@ÓLH@Œqœ@¥2@Œ§@oÄ8@B!@Z
+?ÍIå?c¿m>3¬E>	ëm¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BBüíB@(B=M.B:qÝB7B4»9B1ßèB/B,)EB)MóB&r¢B#PB »þB
+à­B[B*	BNžBsfBB
+ŒÃB	áqB B*ÎBO|AüèUA÷1±Añ{AëÄlAæ
+ÈAàW%AÚ AÔéÞAÏ3;AÉ|AÃÅôAŸQAžX­A²¢
+A¬ëgA§4ÄA¡~!AÇ}AÚAZ7A£AìðA~lArÿTAgA\$ÉAP·AEJ>A9ÜùA.o³A#mA(A
+'âA º@ê®@ÓÀ"@Œå@Š
+
+@0@p«í@BöÖ@AŸ?ÏN?g^>>B'>fŽ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B=TÅB:XB7¥B4ÉµB1îcB/B,7ÀB)\oB&
+B#¥ËB ÊzB
+ï(BÖB8
+B]3BáBŠB
+Ë>B	ïìBB9IB]øAýKA÷NšAñAëáaAæ*¿Aàt
+AÚœxAÕÕAÏP1AÉAÃâëAŸ,GAžu€A²¿A­]A§QºA¡AätA-ÑAw-AÀA
+	çA~ŠAs9AAgËüA\^¶APñqAE+A:åA.© A#<[AÏA
+aÏA ô@ë@Ô3ý@œYr@Š~æ@€\@q¡@CÞ@)s?Ðè·?jý>P¢Ó>&áû¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B7¬B4Ø1B1üßB/!B,F<B)jêB&B#ŽHB ØöB
+ý€B"SBGBk¯B^Bµ
+B
+ÙºB	þiB#BGÅBltAý"DA÷k¡AñŽýAëþZAæG·AàAÚÚqAÕ#ÎAÏm*AÉ¶AÃÿãAŸI@AžA²ÛùA­%VA§n³A¡žAlAJÉA&AÝA
+&ßA~àxAss2AhíA\§AQ+bAEŸ
+A:P×A.ãA#vKA	A
+ÁA.{@ëk@Ô§ß@œÍT@ŠòÉ@>@r{e@DÆO@7?Òž@?n#>_>5]C¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B2vB/0	B,T·B)yfB&B#ÂÂB çqB
+
+ B0ÎBU|Bz+BÙBÃB
+è6B
+
+äB1BVABzïAý?;A÷AñÑôAìQAæd­Aà®
+AÚ÷gAÕ@ÃAÏ!AÉÓ~AÄ
+ÚAŸf7Až¯A²øðA­BMA§©A¡ÕA
+cAg¿A±
+AúyA
+CÖAeAs­ Ah?ÚA\ÒAQeOAEø	A:ÄA/
+~A#°9ABóA
+Õ­Ahh@ëöE@Õº@ŸA/@§f£@@sc@E®@øì?Ô©?r:õ>mb>CØ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B,\NB)áB&¬B#Ñ>B õìB
+B?IBcøBŠB­TBÒB
+ö±B
+_B@BdŒBjAý\1A÷¥AñîëAì8GAæ€AàËAÛ]AÕ]ºAÏ§AÉðsAÄ9ÑAŸ-AžÌA³çA­_CA§š A¡ñýA;YA¶AÎAoA
+`ÌATSAsç
+AhyÇA]
+AQ<AF1öA:Ä±A/WkA#ê&A|àA
+A¢U@ìj@Õ@Ÿµ@§Ú~@ÿò@tJÎ@F·@à ?ÖW?uÙÅ>|€>RSÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B&Ž&B#ß¹B!gB
+)BMÄBrrB!B»ÐBà~B
+,B
+)ÛBNBs7BæAýy(A÷Â
+Aò
+áAìU>AæAàç÷AÛ1TAÕz±AÏÄ
+AÊ
+jAÄVÇAŸ #AžéA³2ÝA­|:A§ÅA¢óAXPA¡­Aë	A4fA
+}ÃA?At úAh³ŽA]FnAQÙ)AFkäA:þA/XA$$A¶ÍA
+IAÜB@ìÝù@Ön@¿(ã@šNX@sÌ@u2@G}k@ÈT?Ø&z?yx>
+Hv>`Ï¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B!
+þB
+7B\?BîB¥BÊJBîùB
+šB
+8VB]B³BŠaAý
+A÷ß{Aò(ØAìr5Aæ»AáîAÛNKAÕ§AÏáAÊ*aAÄsœAŸœA¹wA³OÓA­1A§âA¢+êAuGAŸ£A AQ]A
+¹AÈ,AtZçAhí¡A]\ARAF¥ÐA;8A/ËFA$^ AðºA
+uA/@íQÓ@ÖwH@¿œ@šÂ2@ç§@v7@He @°	?Ùõã?}i>>oJ\¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bc×BjBŽBØÇBýuB
+"#B
+FÒBkB/BŽÝAý³A÷üsAòEÐAì-AæØAá!çAÛkCAÕŽ AÏýýAÊGYAÄ¶AŸÚA¹#oA³lÌA­¶)A§ÿ
+A¢HãA?AÛA$ùAnUA
+·²AAtØAi'A]ºMARMAFßÂA;r|A06A$ñA*¬A
+œfAP @íÅµ@Öë+@À@©6@[@wü@ILä@Í?ÛÅl?[=>Ä>>}Å€¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B»¯BçBB
+ðB
+0B
+UMByûBªBÃYAýÐAøjAòbÇAì¬#AæõAá>ÝAÛ:AÕÑAÐóAÊdPAÄ­­AŸ÷	A¹@fA³ÃA­ÓAš
+|A¢eÙA¯5AøAAïALA
+Ô©A
+AtÎÅAiaA]ô:ARôAG¯A;¬iA0?$A$ÑÞAdA
+÷SA@î9@×_@Àz@©©ï@Ïc@wé°@J4@
+?ÝÕ?*Š>â> v¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BB
+?B
+cÈBwB­%BÑÓAýíAø6aAòœAìÉAçwAá[ÓAÛ¥0AÕîAÐ7êAÊGAÄÊ£A¿ A¹]]A³Š¹A­ðAš9sA¢ÏAÌ,AA^åAšCA
+ñA:üAu²AimA^.'ARÀáAGSA;æVA0yA%
+ËAA1@AÃú@î­j@×Òß@ÀøT@ª
+É@C>@xÑe@K
+M@
+g6?ßd=?ú>¢?
+>^¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+k_BòB» BàOAþ	ûAøSWAòŽAìæAç/mAáxÊAÛÂ'AÖ
+AÐTàAÊ=AÄçA¿0÷A¹zSA³Ã°A®
+
+AšViA¢ÆAé#A2A{ÜAÅ9AAWòAuBAiÕYA^hARúÏAGA< CA0²þA%EžAØsAk-Aýè@ï!D@ØF¹@Ál.@ª£@·@y¹@L@
+Nê?á3Š?
+Éx>©}*>œ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BÃ7BîÊAþ&ñAøpNAò¹«AíAçLdAáÁAÛß
+AÖ(zAÐq×AÊ»3AÅA¿MíA¹JA³à§A®*Ašs`A¢ŒœAAOvAÓAâ/A+AtéAu|AjGA^¢AS4»AGÇvA<Z1A0ìëA%¥A`A¥A7Õ@ï@Øº@Áà@«}@*ò@z Í@Lë¶@6?ã?á>°ºÍ>Ùb¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aþ6AøFAòÖ£Aí  Açi]Aá²¹AÛüAÖEsAÐÏAÊØ,AÅ!A¿jåA¹ŽBA³ýA®FüAšYA¢ÙµA#AloAµËAÿ(AH
+AáAu¶}AjI8A^ÛòASn­AHgA<!A1&ÜA%¹ALQAß
+AqÆ@ð	@Ù.u@ÂSë@«y_@Ô@{@MÓ{@ 
+c?äÒ?hk>·øñ>£¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AòåÏAí<öAçSAáÏ°AÜ
+AÖbiAÐ«ÆAÊõ#AÅ>A¿ÜA¹Ñ9AŽA®còAš­OA¢ö¬A@	AeAÒÂA
+Ae{A®ØAuðjAj%A_ßASšAH;TA<ÎA1`ÉA%óA>AùA«³@ð|Û@Ù¢P@ÂÇÅ@«í9@¯@|pG@N»/@!?æ¢?7Ó>¿6>ªT©¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AçAáìŠAÜ6AÖ`AÐÈœAËAÅ[vA¿€ÓA¹î/AŽ7A®éAšÊEA£¢A\ÿAŠ\Aï¹A9ArAËÏAv*XAjœA_OÌASâAHuAA=üA1¶A&-qAÀ+ARåAå @ððµ@Ú*@Ã;@¬a@@}Wú@O¢ä@!íÌ?èqj?<>Æt6>±J¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÜE/AÖVAÐå³AË/AÅxmA¿ÁÉAº
+&AŽTA®ßAšç<A£0AyõAÃRA
+¯AV
+AiAèÅAvdEAjöÿA_ºAT
+tAH¯.A=AéA1Ô£A&g^AúAÓA@ñd@Ú@Ã¯y@¬Ôî@úb@~?¯@P@"Õ?ê@Ó?Ö€>Í±Ú>žÏï¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÐôßAËLAÅcA¿ÞÀAº(
+AŽqyA®ºÖA©3A£MAìAàIA)¥AsAŒ_AŒAv2Ak0íA_Ã§ATVaAHé
+A={ÖA2A&¡KA4AÆÀAYz@ñØi@ÚýÞ@Ä#S@­HÈ@n=@'d@QrM@#œ6?ì<?Š
+>Ôï~>À
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÅ€A¿ûžAºEAŽrA®×ÏA©!+A£jA³åAýAAFAûAÙWA"ŽAvØ#AkjÝA_ýATSAI#
+A=µÇA2HA&Û<AmöA ±Ak@òLK@ÛqÁ@Ä5@­Œª@â@@RZ@$€ú?íßÅ?u>Ü-¢>ÇK5¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AºTAAŽ«hA®ôÅA©>"A£AÐÛA8AcA¬ñAöNA?«AwAk€ËA`7
+ATÊ?AI\úA=ïµA2oA')A§äA:AÍX@òÀ&@Ûå@Å
+@®0
+@Uù@{n@SAÆ@%®?ï¯.?Dÿ>ãkE>ÎÚ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A¯ñA©[A£€uAíÒA7/AAÉèAEA\¡AwKýAkÞžA`qsAU-AIçA>)¡A2Œ\A'OAáÑAtAF@ó4 @ÜYu@Å~ê@®€_@ÉÓ@ïI@T)z@&tc?ñ~?i>êšé>ÕÆ}¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A£³¡A
+ÈAT%AAæßA0;AyAw
+êAl¥A`«_AU>AIÐÕA>cA2öIA'A
+ŸA®yAA3@ó§Û@ÜÍO@ÅòÄ@¯9@=®@c#@U.@'\?óN ?ãÒ>ñæ>Ý!¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AcQAºxAÕAM2AAw¿ØAlRA`åLAUxAJ
+ÁA>|A307A'ÂñA
+U«AèeA{ @ôŽ@ÝA*@Æf@¯@±@Öý@Uøã@(CÌ?õ
+i?³:>ù$1>äAÅ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AAj*A³AwùÈAlAa>AU±øAJD²A>×mA3j'A'üâA
+A"WAµ@ô@Ýµ
+@ÆÚ@¯ÿö@%k@Jß@Và§@)+?öìò?Ã? 1*>ëi¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÂ³Ax3¶AlÆpAaY*AUëåAJ~ A?ZA3€A(6ÏA
+ÉA\DAîþ@õq@Þ(æ@ÇN[@°sÏ@D@Ÿº@WÈ\@*E?øŒ[?R,?Ïü>òœ
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AläÉAaAV%ÒAJžA?KGA3ÞA(pŒA
+vA1A(ë@õwK@ÞÀ@ÇÂ5@°çª@
+@2@X°@*úù?úÃ?!?nÍ>ùú®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AVD+AJòzA?
+4A4îA(ª©A
+=dAÐ
+AbØ@õë%@ß@È6@±[@ù@Šn@YÄ@+â­?ü[,? ðý?
+
+? )¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A?£A4QàA(äA
+wTA
+AÊ@ö_@ß}@È©ñ@±Ïg@ôÛ@P@Z@,Êr?þ*µ?¢À?¬°?:û¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A)óA
+±BACüAÖ¶@öÒâ@ßøW@É
+Ì@²CA@hµ@*@[g=@-²&?ÿú
+?€ï?K?ÙÌ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AbUA€@÷FŒ@àl1@ÉŠ@²·@Ü@
+@\Nò@.Ú@ äÃ?Š_X?êU?
+x¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @÷n@àà
+@Ê@³*õ@Pj@
+uß@]6Š@/@Ìx?š.Á?'?q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @ÊB2@³Ð@ÄD@
+é¹@^
+[@0iC@Ž,?©þ*?
+'ø?¶B¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @ þ@]@_@1Q@ñ?«Í³? Ç
+?U¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @_@28œ@¥?­
+?$eÝ?óç¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @ý	?¯l
+?(®?
+ž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?)ê;?!1¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             B~
+B~záB~p€B~ffB~\)B~QìB~G®B~=qB~33B~(öB~
+žB~{B~
+=B~  B}õÃB}ë
+B}áHB}×
+B}ÌÍB}ÂB}žRB}®B}£×B}B}\B}
+B}záB}p€B}ffB}\)B}QìB}G®B}=qB}33B}(öB}
+žB}{B}
+=B}  B|õÃB|ë
+B|áHB|×
+B|ÌÍB|ÂB|žRB|®B|£×B|B|\B|
+B|záB|p€B|ffB|\)B|QìB|G®B|=qB|33B|(öB|
+žB|{B|
+=B|  Bz
+BzzáBzp€BzffBz\)BzQìBzG®Bz=qBz33Bz(öBz
+žBz{Bz
+=Bz  ByõÃByë
+ByáHBy×
+ByÌÍByÂByžRBy®By£×ByBy\By
+ByzáByp€ByffBy\)ByQìByG®By=qBy33By(öBy
+žBy{By
+=By  BxõÃBxë
+BxáHBx×
+BxÌÍBxÂBxžRBx®Bx£×BxBx\Bx
+BxzáBxp€BxffBx\)BxQìBxG®Bx=qBx33Bx(öBx
+žBx{Bx
+=Bx  Bv
+BvzáBvp€BvffBv\)BvQìBvG®Bv=qBv33Bv(öBv
+žBv{Bv
+=Bv  BuõÃBuë
+BuáHBu×
+BuÌÍBuÂBužRBu®Bu£×BuBu\Bu
+BuzáBup€BuffBu\)BuQìBuG®Bu=qBu33Bu(öBu
+žBu{Bu
+=Bu  BtõÃBtë
+BtáHBt×
+BtÌÍBtÂBtžRBt®Bt£×BtBt\Bt
+BtzáBtp€BtffBt\)BtQìBtG®Bt=qBt33Bt(öBt
+žBt{Bt
+=Bt  Br
+BrzáBrp€BrffBr\)BrQìBrG®Br=qBr33Br(öBr
+žBr{Br
+=Br  BqõÃBqë
+BqáHBq×
+BqÌÍBqÂBqžRBq®Bq£×BqBq\Bq
+BqzáBqp€BqffBq\)BqQìBqG®Bq=qBq33Bq(öBq
+žBq{Bq
+=Bq  BpõÃBpë
+BpáHBp×
+BpÌÍBpÂBpžRBp®Bp£×BpBp\Bp
+BpzáBpp€BpffBp\)BpQìBpG®Bp=qBp33Bp(öBp
+žBp{Bp
+=Bp  Bn
+BnzáBnp€BnffBn\)BnQìBnG®Bn=qBn33Bn(öBn
+žBn{Bn
+=Bn  BmõÃBmë
+BmáHBm×
+BmÌÍBmÂBmžRBm®Bm£×BmBm\Bm
+BmzáBmp€BmffBm\)BmQìBmG®Bm=qBm33Bm(öBm
+žBm{Bm
+=Bm  BlõÃBlë
+BláHBl×
+BlÌÍBlÂBlžRBl®Bl£×BlBl\Bl
+BlzáBlp€BlffBl\)BlQìBlG®Bl=qBl33Bl(öBl
+žBl{Bl
+=Bl  Bj
+BjzáBjp€BjffBj\)BjQìBjG®Bj=qBj33Bj(öBj
+žBj{Bj
+=Bj  BiõÃBië
+BiáHBi×
+BiÌÍBiÂBižRBi®Bi£×BiBi\Bi
+BizáBip€BiffBi\)BiQìBiG®Bi=qBi33Bi(öBi
+žBi{Bi
+=Bi  BhõÃBhë
+BháHBh×
+BhÌÍBhÂBhžRBh®Bh£×BhBh\Bh
+BhzáBhp€BhffBh\)BhQìBhG®Bh=qBh33Bh(öBh
+žBh{Bh
+=Bh  Bf
+BfzáBfp€BfffBf\)BfQìBfG®Bf=qBf33Bf(öBf
+žBf{Bf
+=Bf  BeõÃBeë
+BeáHBe×
+BeÌÍBeÂBežRBe®Be£×BeBe\Be
+BezáBep€BeffBe\)BeQìBeG®Be=qBe33Be(öBe
+žBe{Be
+=Be  BdõÃBdë
+BdáHBd×
+BdÌÍBdÂBdžRBd®Bd£×BdBd\Bd
+BdzáBdp€BdffBd\)BdQìBdG®Bd=qBd33Bd(öBd
+žBd{Bd
+=Bd  Bb
+BbzáBbp€BbffBb\)BbQìBbG®Bb=qBb33Bb(öBb
+žBb{Bb
+=Bb  BaõÃBaë
+BaáHBa×
+BaÌÍBaÂBažRBa®Ba£×BaBa\Ba
+BazáBap€BaffBa\)BaQìBaG®Ba=qBa33Ba(öBa
+žBa{Ba
+=Ba  B`õÃB`ë
+B`áHB`×
+B`ÌÍB`ÂB`žRB`®B`£×B`B`\B`
+B`záB`p€B`ffB`\)B`QìB`G®B`=qB`33B`(öB`
+žB`{B`
+=B`  B^
+B^záB^p€B^ffB^\)B^QìB^G®B^=qB^33B^(öB^
+žB^{B^
+=B^  B]õÃB]ë
+B]áHB]×
+B]ÌÍB]ÂB]žRB]®B]£×B]B]\B]
+B]záB]p€B]ffB]\)B]QìB]G®B]=qB]33B](öB]
+žB]{B]
+=B]  B\õÃB\ë
+B\áHB\×
+B\ÌÍB\ÂB\žRB\®B\£×B\B\\B\
+B\záB\p€B\ffB\\)B\QìB\G®B\=qB\33B\(öB\
+žB\{B\
+=B\  BZ
+BZzáBZp€BZffBZ\)BZQìBZG®BZ=qBZ33BZ(öBZ
+žBZ{BZ
+=BZ  BYõÃBYë
+BYáHBY×
+BYÌÍBYÂBYžRBY®BY£×BYBY\BY
+BYzáBYp€BYffBY\)BYQìBYG®BY=qBY33BY(öBY
+žBY{BY
+=BY  BXõÃBXë
+BXáHBX×
+BXÌÍBXÂBXžRBX®BX£×BXBX\BX
+BXzáBXp€BXffBX\)BXQìBXG®BX=qBX33BX(öBX
+žBX{BX
+=BX  BV
+BVzáBVp€BVffBV\)BVQìBVG®BV=qBV33BV(öBV
+žBV{BV
+=BV  BUõÃBUë
+BUáHBU×
+BUÌÍBUÂBUžRBU®BU£×BUBU\BU
+BUzáBUp€BUffBU\)BUQìBUG®BU=qBU33BU(öBU
+žBU{BU
+=BU  BTõÃBTë
+BTáHBT×
+BTÌÍBTÂBTžRBT®BT£×BTBT\BT
+BTzáBTp€BTffBT\)BTQìBTG®BT=qBT33BT(öBT
+žBT{BT
+=BT  BR
+BRzáBRp€BRffBR\)BRQìBRG®BR=qBR33BR(öBR
+žBR{BR
+=BR  BQõÃBQë
+BQáHBQ×
+BQÌÍBQÂBQžRBQ®BQ£×BQBQ\BQ
+BQzáBQp€BQffBQ\)BQQìBQG®BQ=qBQ33BQ(öBQ
+žBQ{BQ
+=BQ  BPõÃBPë
+BPáHBP×
+BPÌÍBPÂBPžRBP®BP£×BPBP\BP
+BPzáBPp€BPffBP\)BPQìBPG®BP=qBP33BP(öBP
+žBP{BP
+=BP  BN
+BNzáBNp€BNffBN\)BNQìBNG®BN=qBN33BN(öBN
+žBN{BN
+=BN  BMõÃBMë
+BMáHBM×
+BMÌÍBMÂBMžRBM®BM£×BMBM\BM
+BMzáBMp€BMffBM\)BMQìBMG®BM=qBM33BM(öBM
+žBM{BM
+=BM  BLõÃBLë
+BLáHBL×
+BLÌÍBLÂBLžRBL®BL£×BLBL\BL
+BLzáBLp€BLffBL\)BLQìBLG®BL=qBL33BL(öBL
+žBL{BL
+=BL  BJ
+BJzáBJp€BJffBJ\)BJQìBJG®BJ=qBJ33BJ(öBJ
+žBJ{BJ
+=BJ  BIõÃBIë
+BIáHBI×
+BIÌÍBIÂBIžRBI®BI£×BIBI\BI
+BIzáBIp€BIffBI\)BIQìBIG®BI=qBI33BI(öBI
+žBI{BI
+=BI  BHõÃBHë
+BHáHBH×
+BHÌÍBHÂBHžRBH®BH£×BHBH\BH
+BHzáBHp€BHffBH\)BHQìBHG®BH=qBH33BH(öBH
+žBH{BH
+=BH  BF
+BFzáBFp€BFffBF\)BFQìBFG®BF=qBF33BF(öBF
+žBF{BF
+=BF  BEõÃBEë
+BEáHBE×
+BEÌÍBEÂBEžRBE®BE£×BEBE\BE
+BEzáBEp€BEffBE\)BEQìBEG®BE=qBE33BE(öBE
+žBE{BE
+=BE  BDõÃBDë
+BDáHBD×
+BDÌÍBDÂBDžRBD®BD£×BDBD\BD
+BDzáBDp€BDffBD\)BDQìBDG®BD=qBD33BD(öBD
+žBD{BD
+=BD  BB
+BBzáBBp€BBffBB\)BBQìBBG®BB=qBB33BB(öBB
+žBB{BB
+=BB  BAõÃBAë
+BAáHBA×
+BAÌÍBAÂBAžRBA®BA£×BABA\BA
+BAzáBAp€BAffBA\)BAQìBAG®BA=qBA33BA(öBA
+žBA{BA
+=BA  B@õÃB@ë
+B@áHB@×
+B@ÌÍB@ÂB@žRB@®B@£×B@B@\B@
+B@záB@p€B@ffB@\)B@QìB@G®B@=qB@33B@(öB@
+žB@{B@
+=B@  B>
+B>záB>p€B>ffB>\)B>QìB>G®B>=qB>33B>(öB>
+žB>{B>
+=B>  B=õÃB=ë
+B=áHB=×
+B=ÌÍB=ÂB=žRB=®B=£×B=B=\B=
+B=záB=p€B=ffB=\)B=QìB=G®B==qB=33B=(öB=
+žB={B=
+=B=  B<õÃB<ë
+B<áHB<×
+B<ÌÍB<ÂB<žRB<®B<£×B<B<\B<
+B<záB<p€B<ffB<\)B<QìB<G®B<=qB<33B<(öB<
+žB<{B<
+=B<  B:
+B:záB:p€B:ffB:\)B:QìB:G®B:=qB:33B:(öB:
+žB:{B:
+=B:  B9õÃB9ë
+B9áHB9×
+B9ÌÍB9ÂB9žRB9®B9£×B9B9\B9
+B9záB9p€B9ffB9\)B9QìB9G®B9=qB933B9(öB9
+žB9{B9
+=B9  B8õÃB8ë
+B8áHB8×
+B8ÌÍB8ÂB8žRB8®B8£×B8B8\B8
+B8záB8p€B8ffB8\)B8QìB8G®B8=qB833B8(öB8
+žB8{B8
+=B8  B6
+B6záB6p€B6ffB6\)B6QìB6G®B6=qB633B6(öB6
+žB6{B6
+=B6  B5õÃB5ë
+B5áHB5×
+B5ÌÍB5ÂB5žRB5®B5£×B5B5\B5
+B5záB5p€B5ffB5\)B5QìB5G®B5=qB533B5(öB5
+žB5{B5
+=B5  B4õÃB4ë
+B4áHB4×
+B4ÌÍB4ÂB4žRB4®B4£×B4B4\B4
+B4záB4p€B4ffB4\)B4QìB4G®B4=qB433B4(öB4
+žB4{B4
+=B4  B2
+B2záB2p€B2ffB2\)B2QìB2G®B2=qB233B2(öB2
+žB2{B2
+=B2  B1õÃB1ë
+B1áHB1×
+B1ÌÍB1ÂB1žRB1®B1£×B1B1\B1
+B1záB1p€B1ffB1\)B1QìB1G®B1=qB133B1(öB1
+žB1{B1
+=B1  B0õÃB0ë
+B0áHB0×
+B0ÌÍB0ÂB0žRB0®B0£×B0B0\B0
+B0záB0p€B0ffB0\)B0QìB0G®B0=qB033B0(öB0
+žB0{B0
+=B0  B.
+B.záB.p€B.ffB.\)B.QìB.G®B.=qB.33B.(öB.
+žB.{B.
+=B.  B-õÃB-ë
+B-áHB-×
+B-ÌÍB-ÂB-žRB-®B-£×B-B-\B-
+B-záB-p€B-ffB-\)B-QìB-G®B-=qB-33B-(öB-
+žB-{B-
+=B-  B,õÃB,ë
+B,áHB,×
+B,ÌÍB,ÂB,žRB,®B,£×B,B,\B,
+B,záB,p€B,ffB,\)B,QìB,G®B,=qB,33B,(öB,
+žB,{B,
+=B,  B*
+B*záB*p€B*ffB*\)B*QìB*G®B*=qB*33B*(öB*
+žB*{B*
+=B*  B)õÃB)ë
+B)áHB)×
+B)ÌÍB)ÂB)žRB)®B)£×B)B)\B)
+B)záB)p€B)ffB)\)B)QìB)G®B)=qB)33B)(öB)
+žB){B)
+=B)  B(õÃB(ë
+B(áHB(×
+B(ÌÍB(ÂB(žRB(®B(£×B(B(\B(
+B(záB(p€B(ffB(\)B(QìB(G®B(=qB(33B((öB(
+žB({B(
+=B(  B&
+B&záB&p€B&ffB&\)B&QìB&G®B&=qB&33B&(öB&
+žB&{B&
+=B&  B%õÃB%ë
+B%áHB%×
+B%ÌÍB%ÂB%žRB%®B%£×B%B%\B%
+B%záB%p€B%ffB%\)B%QìB%G®B%=qB%33B%(öB%
+žB%{B%
+=B%  B$õÃB$ë
+B$áHB$×
+B$ÌÍB$ÂB$žRB$®B$£×B$B$\B$
+B$záB$p€B$ffB$\)B$QìB$G®B$=qB$33B$(öB$
+žB${B$
+=B$  B"
+B"záB"p€B"ffB"\)B"QìB"G®B"=qB"33B"(öB"
+žB"{B"
+=B"  B!õÃB!ë
+B!áHB!×
+B!ÌÍB!ÂB!žRB!®B!£×B!B!\B!
+B!záB!p€B!ffB!\)B!QìB!G®B!=qB!33B!(öB!
+žB!{B!
+=B!  B õÃB ë
+B áHB ×
+B ÌÍB ÂB žRB ®B £×B B \B 
+B záB p€B ffB \)B QìB G®B =qB 33B (öB 
+žB {B 
+=B   B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B	õÃB	ë
+B	áHB	×
+B	ÌÍB	ÂB	žRB	®B	£×B	B	\B	
+B	záB	p€B	ffB	\)B	QìB	G®B	=qB	33B	(öB	
+žB	{B	
+=B	  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B õÃB ë
+B áHB ×
+B ÌÍB ÂB žRB ®B £×B B \B 
+B záB p€B ffB \)B QìB G®B =qB 33B (öB 
+žB {B 
+=B   Aý
+=AüõÃAüáHAüÌÍAüžRAü£×Aü\AüzáAüffAüQìAü=qAü(öAü{Aü  Aûë
+Aû×
+AûÂAû®AûAû
+Aûp€Aû\)AûG®Aû33Aû
+žAû
+=AúõÃAúáHAúÌÍAúžRAú£×Aú\AúzáAúffAúQìAú=qAú(öAú{Aú  Aùë
+Aù×
+AùÂAù®AùAù
+Aùp€Aù\)AùG®Aù33Aù
+žAù
+=AøõÃAøáHAøÌÍAøžRAø£×Aø\AøzáAøffAøQìAø=qAø(öAø{Aø  Aõ
+=AôõÃAôáHAôÌÍAôžRAô£×Aô\AôzáAôffAôQìAô=qAô(öAô{Aô  Aóë
+Aó×
+AóÂAó®AóAó
+Aóp€Aó\)AóG®Aó33Aó
+žAó
+=AòõÃAòáHAòÌÍAòžRAò£×Aò\AòzáAòffAòQìAò=qAò(öAò{Aò  Añë
+Añ×
+AñÂAñ®AñAñ
+Añp€Añ\)AñG®Añ33Añ
+žAñ
+=AðõÃAðáHAðÌÍAðžRAð£×Að\AðzáAðffAðQìAð=qAð(öAð{Að  Aí
+=AìõÃAìáHAìÌÍAìžRAì£×Aì\AìzáAìffAìQìAì=qAì(öAì{Aì  Aëë
+Aë×
+AëÂAë®AëAë
+Aëp€Aë\)AëG®Aë33Aë
+žAë
+=AêõÃAêáHAêÌÍAêžRAê£×Aê\AêzáAêffAêQìAê=qAê(öAê{Aê  Aéë
+Aé×
+AéÂAé®AéAé
+Aép€Aé\)AéG®Aé33Aé
+žAé
+=AèõÃAèáHAèÌÍAèžRAè£×Aè\AèzáAèffAèQìAè=qAè(öAè{Aè  Aå
+=AäõÃAäáHAäÌÍAäžRAä£×Aä\AäzáAäffAäQìAä=qAä(öAä{Aä  Aãë
+Aã×
+AãÂAã®AãAã
+Aãp€Aã\)AãG®Aã33Aã
+žAã
+=AâõÃAâáHAâÌÍAâžRAâ£×Aâ\AâzáAâffAâQìAâ=qAâ(öAâ{Aâ  Aáë
+Aá×
+AáÂAá®AáAá
+Aáp€Aá\)AáG®Aá33Aá
+žAá
+=AàõÃAàáHAàÌÍAàžRAà£×Aà\AàzáAàffAàQìAà=qAà(öAà{Aà  AÝ
+=AÜõÃAÜáHAÜÌÍAÜžRAÜ£×AÜ\AÜzáAÜffAÜQìAÜ=qAÜ(öAÜ{AÜ  AÛë
+AÛ×
+AÛÂAÛ®AÛAÛ
+AÛp€AÛ\)AÛG®AÛ33AÛ
+žAÛ
+=AÚõÃAÚáHAÚÌÍAÚžRAÚ£×AÚ\AÚzáAÚffAÚQìAÚ=qAÚ(öAÚ{AÚ  AÙë
+AÙ×
+AÙÂAÙ®AÙAÙ
+AÙp€AÙ\)AÙG®AÙ33AÙ
+žAÙ
+=AØõÃAØáHAØÌÍAØžRAØ£×AØ\AØzáAØffAØQìAØ=qAØ(öAØ{AØ  AÕ
+=AÔõÃAÔáHAÔÌÍAÔžRAÔ£×AÔ\AÔzáAÔffAÔQìAÔ=qAÔ(öAÔ{AÔ  AÓë
+AÓ×
+AÓÂAÓ®AÓAÓ
+AÓp€AÓ\)AÓG®AÓ33AÓ
+žAÓ
+=AÒõÃAÒáHAÒÌÍAÒžRAÒ£×AÒ\AÒzáAÒffAÒQìAÒ=qAÒ(öAÒ{AÒ  AÑë
+AÑ×
+AÑÂAÑ®AÑAÑ
+AÑp€AÑ\)AÑG®AÑ33AÑ
+žAÑ
+=AÐõÃAÐáHAÐÌÍAÐžRAÐ£×AÐ\AÐzáAÐffAÐQìAÐ=qAÐ(öAÐ{AÐ  AÍ
+=AÌõÃAÌáHAÌÌÍAÌžRAÌ£×AÌ\AÌzáAÌffAÌQìAÌ=qAÌ(öAÌ{AÌ  AËë
+AË×
+AËÂAË®AËAË
+AËp€AË\)AËG®AË33AË
+žAË
+=AÊõÃAÊáHAÊÌÍAÊžRAÊ£×AÊ\AÊzáAÊffAÊQìAÊ=qAÊ(öAÊ{AÊ  AÉë
+AÉ×
+AÉÂAÉ®AÉAÉ
+AÉp€AÉ\)AÉG®AÉ33AÉ
+žAÉ
+=AÈõÃAÈáHAÈÌÍAÈžRAÈ£×AÈ\AÈzáAÈffAÈQìAÈ=qAÈ(öAÈ{AÈ  AÅ
+=AÄõÃAÄáHAÄÌÍAÄžRAÄ£×AÄ\AÄzáAÄffAÄQìAÄ=qAÄ(öAÄ{AÄ  AÃë
+AÃ×
+AÃÂAÃ®AÃAÃ
+AÃp€AÃ\)AÃG®AÃ33AÃ
+žAÃ
+=AÂõÃAÂáHAÂÌÍAÂžRAÂ£×AÂ\AÂzáAÂffAÂQìAÂ=qAÂ(öAÂ{AÂ  AÁë
+AÁ×
+AÁÂAÁ®AÁAÁ
+AÁp€AÁ\)AÁG®AÁ33AÁ
+žAÁ
+=AÀõÃAÀáHAÀÌÍAÀžRAÀ£×AÀ\AÀzáAÀffAÀQìAÀ=qAÀ(öAÀ{AÀ  Aœ
+=AŒõÃAŒáHAŒÌÍAŒžRAŒ£×AŒ\AŒzáAŒffAŒQìAŒ=qAŒ(öAŒ{AŒ  A»ë
+A»×
+A»ÂA»®A»A»
+A»p€A»\)A»G®A»33A»
+žA»
+=AºõÃAºáHAºÌÍAºžRAº£×Aº\AºzáAºffAºQìAº=qAº(öAº{Aº  A¹ë
+A¹×
+A¹ÂA¹®A¹A¹
+A¹p€A¹\)A¹G®A¹33A¹
+žA¹
+=AžõÃAžáHAžÌÍAžžRAž£×Až\AžzáAžffAžQìAž=qAž(öAž{Až  Aµ
+=AŽõÃAŽáHAŽÌÍAŽžRAŽ£×AŽ\AŽzáAŽffAŽQìAŽ=qAŽ(öAŽ{AŽ  A³ë
+A³×
+A³ÂA³®A³A³
+A³p€A³\)A³G®A³33A³
+žA³
+=A²õÃA²áHA²ÌÍA²žRA²£×A²\A²záA²ffA²QìA²=qA²(öA²{A²  A±ë
+A±×
+A±ÂA±®A±A±
+A±p€A±\)A±G®A±33A±
+žA±
+=A°õÃA°áHA°ÌÍA°žRA°£×A°\A°záA°ffA°QìA°=qA°(öA°{A°  A­
+=A¬õÃA¬áHA¬ÌÍA¬žRA¬£×A¬\A¬záA¬ffA¬QìA¬=qA¬(öA¬{A¬  A«ë
+A«×
+A«ÂA«®A«A«
+A«p€A«\)A«G®A«33A«
+žA«
+=AªõÃAªáHAªÌÍAªžRAª£×Aª\AªzáAªffAªQìAª=qAª(öAª{Aª  A©ë
+A©×
+A©ÂA©®A©A©
+A©p€A©\)A©G®A©33A©
+žA©
+=AšõÃAšáHAšÌÍAšžRAš£×Aš\AšzáAšffAšQìAš=qAš(öAš{Aš  A¥
+=A€õÃA€áHA€ÌÍA€žRA€£×A€\A€záA€ffA€QìA€=qA€(öA€{A€  A£ë
+A£×
+A£ÂA£®A£A£
+A£p€A£\)A£G®A£33A£
+žA£
+=A¢õÃA¢áHA¢ÌÍA¢žRA¢£×A¢\A¢záA¢ffA¢QìA¢=qA¢(öA¢{A¢  A¡ë
+A¡×
+A¡ÂA¡®A¡A¡
+A¡p€A¡\)A¡G®A¡33A¡
+žA¡
+=A õÃA áHA ÌÍA žRA £×A \A záA ffA QìA =qA (öA {A   A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Az{Ayë
+AyÂAyAyp€AyG®Ay
+žAxõÃAxÌÍAx£×AxzáAxQìAx(öAx  Aw×
+Aw®Aw
+Aw\)Aw33Aw
+=AváHAvžRAv\AvffAv=qAv{Auë
+AuÂAuAup€AuG®Au
+žAtõÃAtÌÍAt£×AtzáAtQìAt(öAt  As×
+As®As
+As\)As33As
+=AráHAržRAr\ArffAr=qAr{Aqë
+AqÂAqAqp€AqG®Aq
+žApõÃApÌÍAp£×ApzáApQìAp(öAp  Aj{Aië
+AiÂAiAip€AiG®Ai
+žAhõÃAhÌÍAh£×AhzáAhQìAh(öAh  Ag×
+Ag®Ag
+Ag\)Ag33Ag
+=AfáHAfžRAf\AfffAf=qAf{Aeë
+AeÂAeAep€AeG®Ae
+žAdõÃAdÌÍAd£×AdzáAdQìAd(öAd  Ac×
+Ac®Ac
+Ac\)Ac33Ac
+=AbáHAbžRAb\AbffAb=qAb{Aaë
+AaÂAaAap€AaG®Aa
+žA`õÃA`ÌÍA`£×A`záA`QìA`(öA`  AZ{AYë
+AYÂAYAYp€AYG®AY
+žAXõÃAXÌÍAX£×AXzáAXQìAX(öAX  AW×
+AW®AW
+AW\)AW33AW
+=AVáHAVžRAV\AVffAV=qAV{AUë
+AUÂAUAUp€AUG®AU
+žATõÃATÌÍAT£×ATzáATQìAT(öAT  AS×
+AS®AS
+AS\)AS33AS
+=ARáHARžRAR\ARffAR=qAR{AQë
+AQÂAQAQp€AQG®AQ
+žAPõÃAPÌÍAP£×APzáAPQìAP(öAP  AJ{AIë
+AIÂAIAIp€AIG®AI
+žAHõÃAHÌÍAH£×AHzáAHQìAH(öAH  AG×
+AG®AG
+AG\)AG33AG
+=AFáHAFžRAF\AFffAF=qAF{AEë
+AEÂAEAEp€AEG®AE
+žADõÃADÌÍAD£×ADzáADQìAD(öAD  AC×
+AC®AC
+AC\)AC33AC
+=ABáHABžRAB\ABffAB=qAB{AAë
+AAÂAAAAp€AAG®AA
+žA@õÃA@ÌÍA@£×A@záA@QìA@(öA@  A:{A9ë
+A9ÂA9A9p€A9G®A9
+žA8õÃA8ÌÍA8£×A8záA8QìA8(öA8  A7×
+A7®A7
+A7\)A733A7
+=A6áHA6žRA6\A6ffA6=qA6{A5ë
+A5ÂA5A5p€A5G®A5
+žA4õÃA4ÌÍA4£×A4záA4QìA4(öA4  A3×
+A3®A3
+A3\)A333A3
+=A2áHA2žRA2\A2ffA2=qA2{A1ë
+A1ÂA1A1p€A1G®A1
+žA0õÃA0ÌÍA0£×A0záA0QìA0(öA0  A*{A)ë
+A)ÂA)A)p€A)G®A)
+žA(õÃA(ÌÍA(£×A(záA(QìA((öA(  A'×
+A'®A'
+A'\)A'33A'
+=A&áHA&žRA&\A&ffA&=qA&{A%ë
+A%ÂA%A%p€A%G®A%
+žA$õÃA$ÌÍA$£×A$záA$QìA$(öA$  A#×
+A#®A#
+A#\)A#33A#
+=A"áHA"žRA"\A"ffA"=qA"{A!ë
+A!ÂA!A!p€A!G®A!
+žA õÃA ÌÍA £×A záA QìA (öA   A{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A
+{A	ë
+A	ÂA	A	p€A	G®A	
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žA õÃA ÌÍA £×A záA QìA (öA   @ô(ö@ó×
+@ó
+@ó33@òáH@ò\@ò=q@ñë
+@ñ@ñG®@ðõÂ@ð£×@ðQì@ð  @ï®@ï\)@ï
+=@îžR@îff@î{@íÂ@íp€@í
+ž@ìÌÍ@ìzá@ì(ö@ë×
+@ë
+@ë33@êáH@ê\@ê=q@éë
+@é@éG®@èõÃ@è£×@èQì@è  @ç®@ç\)@ç
+=@æžR@æff@æ{@åÂ@åp€@å
+ž@äÌÍ@äzá@ä(ö@ã×
+@ã
+@ã33@âáH@â\@â=q@áë
+@á@áG®@àõÃ@à£×@àQì@à  @Ô(ö@Ó×
+@Ó
+@Ó33@ÒáH@Ò\@Ò=q@Ñë
+@Ñ@ÑG®@ÐõÂ@Ð£×@ÐQì@Ð  @Ï®@Ï\)@Ï
+=@ÎžR@Îff@Î{@ÍÂ@Íp€@Í
+ž@ÌÌÍ@Ìzá@Ì(ö@Ë×
+@Ë
+@Ë33@ÊáH@Ê\@Ê=q@Éë
+@É@ÉG®@ÈõÃ@È£×@ÈQì@È  @Ç®@Ç\)@Ç
+=@ÆžR@Æff@Æ{@ÅÂ@Åp€@Å
+ž@ÄÌÍ@Äzá@Ä(ö@Ã×
+@Ã
+@Ã33@ÂáH@Â\@Â=q@Áë
+@Á@ÁG®@ÀõÃ@À£×@ÀQì@À  @Ž(ö@³×
+@³
+@³33@²áH@²\@²=q@±ë
+@±@±G®@°õÂ@°£×@°Qì@°  @¯®@¯\)@¯
+=@®žR@®ff@®{@­Â@­p€@­
+ž@¬ÌÍ@¬zá@¬(ö@«×
+@«
+@«33@ªáH@ª\@ª=q@©ë
+@©@©G®@šõÃ@š£×@šQì@š  @§®@§\)@§
+=@ŠžR@Šff@Š{@¥Â@¥p€@¥
+ž@€ÌÍ@€zá@€(ö@£×
+@£
+@£33@¢áH@¢\@¢=q@¡ë
+@¡@¡G®@ õÃ@ £×@ Qì@   @(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÂ@£×@Qì@  @®@\)@
+=@žR@ff@{@Â@p€@
+ž@ÌÍ@zá@(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÃ@£×@Qì@  @®@\)@
+=@žR@ff@{@
+Â@
+p€@
+
+ž@ÌÍ@zá@(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÃ@£×@Qì@  @hQì@g®@g
+>@fff@eÂ@e
+ž@dzá@c×
+@c33@b\@aë
+@aG®@`£×@`  @_\)@^žR@^{@]p€@\ÌÍ@\(ö@[
+@ZáH@Z=q@Y@XõÂ@XQì@W®@W
+>@Vff@UÂ@U
+ž@Tzá@S×
+@S33@R\@Që
+@QG®@P£×@P  @O\)@NžR@N{@Mp€@LÌÍ@L(ö@K
+@JáH@J=q@I@HõÃ@HQì@G®@G
+=@Fff@EÂ@E
+ž@Dzá@C×
+@C33@B\@Aë
+@AG®@@£×@@  @(Qì@'®@'
+>@&ff@%Â@%
+ž@$zá@#×
+@#33@"\@!ë
+@!G®@ £×@   @\)@
+žR@
+{@
+p€@
+ÌÍ@
+(ö@
+@áH@=q@@õÂ@Qì@®@
+>@ff@Â@
+ž@zá@×
+@33@\@ë
+@G®@£×@  @\)@žR@{@
+p€@
+ÌÍ@
+(ö@
+
+@
+áH@
+=q@	@õÃ@Qì@®@
+=@ff@Â@
+ž@zá@×
+@33@\@ë
+@G®@ £×@   ?Ð£×?Ï\)?Î{?ÌÌÍ?Ë
+
+?Ê=p?ÈõÂ?Ç®?Æff?Å
+ž?Ã×
+?Â\?ÁG®?À  ?ŸžR?œp€?Œ(ö?ºáH?¹?žQì?·
+>?µÂ?Žzá?³33?±ë
+?°£×?¯\)?®{?¬ÌÍ?«
+?ª=q?šõÂ?§®?Šff?¥
+ž?£×
+?¢\?¡G®?   ?žR?p€?(ö?áH??Qì?
+>?Â?zá?33?ë
+?£×?\)?{?ÌÍ?
+?=q?õÃ?®?ff?
+
+ž?×
+?\?G®?  ?!G®?
+žR?
+(ö??
+=?zá?ë
+?\)?
+ÌÍ?
+=q?®?
+ž?\?   >úáH>õÂ>ð£×>ë
+>æff>áG®>Ü(ö>×
+=>Ñë
+>ÌÌÍ>Ç®>Â\>œp€>žQì>³33>®{>šõÃ>£×
+>žR>>zá>\)>=q>
+
+ž>  >uÂ>k
+>aG®>W
+=>LÌÍ>B\>8Qì>.{>#×
+>>\)>
+ž=õÂ=áG®=ÌÌÍ=žQì=£×
+=\)=uÂ=LÌÍ=#×
+<õÂ<£×
+<#×
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/fits/verified/fOut.fits
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/fits/verified/fOut.fits	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/fits/verified/fOut.fits	(revision 22158)
@@ -0,0 +1,8424 @@
+SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             B~
+B~záB~p€B~ffB~\)B~QìB~G®B~=qB~33B~(öB~
+žB~{B~
+=B~  B}õÃB}ë
+B}áHB}×
+B}ÌÍB}ÂB}žRB}®B}£×B}B}\B}
+B}záB}p€B}ffB}\)B}QìB}G®B}=qB}33B}(öB}
+žB}{B}
+=B}  B|õÃB|ë
+B|áHB|×
+B|ÌÍB|ÂB|žRB|®B|£×B|B|\B|
+B|záB|p€B|ffB|\)B|QìB|G®B|=qB|33B|(öB|
+žB|{B|
+=B|  Bz
+BzzáBzp€BzffBz\)BzQìBzG®Bz=qBz33Bz(öBz
+žBz{Bz
+=Bz  ByõÃByë
+ByáHBy×
+ByÌÍByÂByžRBy®By£×ByBy\By
+ByzáByp€ByffBy\)ByQìByG®By=qBy33By(öBy
+žBy{By
+=By  BxõÃBxë
+BxáHBx×
+BxÌÍBxÂBxžRBx®Bx£×BxBx\Bx
+BxzáBxp€BxffBx\)BxQìBxG®Bx=qBx33Bx(öBx
+žBx{Bx
+=Bx  Bv
+BvzáBvp€BvffBv\)BvQìBvG®Bv=qBv33Bv(öBv
+žBv{Bv
+=Bv  BuõÃBuë
+BuáHBu×
+BuÌÍBuÂBužRBu®Bu£×BuBu\Bu
+BuzáBup€BuffBu\)BuQìBuG®Bu=qBu33Bu(öBu
+žBu{Bu
+=Bu  BtõÃBtë
+BtáHBt×
+BtÌÍBtÂBtžRBt®Bt£×BtBt\Bt
+BtzáBtp€BtffBt\)BtQìBtG®Bt=qBt33Bt(öBt
+žBt{Bt
+=Bt  Br
+BrzáBrp€BrffBr\)BrQìBrG®Br=qBr33Br(öBr
+žBr{Br
+=Br  BqõÃBqë
+BqáHBq×
+BqÌÍBqÂBqžRBq®Bq£×BqBq\Bq
+BqzáBqp€BqffBq\)BqQìBqG®Bq=qBq33Bq(öBq
+žBq{Bq
+=Bq  BpõÃBpë
+BpáHBp×
+BpÌÍBpÂBpžRBp®Bp£×BpBp\Bp
+BpzáBpp€BpffBp\)BpQìBpG®Bp=qBp33Bp(öBp
+žBp{Bp
+=Bp  Bn
+BnzáBnp€BnffBn\)BnQìBnG®Bn=qBn33Bn(öBn
+žBn{Bn
+=Bn  BmõÃBmë
+BmáHBm×
+BmÌÍBmÂBmžRBm®Bm£×BmBm\Bm
+BmzáBmp€BmffBm\)BmQìBmG®Bm=qBm33Bm(öBm
+žBm{Bm
+=Bm  BlõÃBlë
+BláHBl×
+BlÌÍBlÂBlžRBl®Bl£×BlBl\Bl
+BlzáBlp€BlffBl\)BlQìBlG®Bl=qBl33Bl(öBl
+žBl{Bl
+=Bl  Bj
+BjzáBjp€BjffBj\)BjQìBjG®Bj=qBj33Bj(öBj
+žBj{Bj
+=Bj  BiõÃBië
+BiáHBi×
+BiÌÍBiÂBižRBi®Bi£×BiBi\Bi
+BizáBip€BiffBi\)BiQìBiG®Bi=qBi33Bi(öBi
+žBi{Bi
+=Bi  BhõÃBhë
+BháHBh×
+BhÌÍBhÂBhžRBh®Bh£×BhBh\Bh
+BhzáBhp€BhffBh\)BhQìBhG®Bh=qBh33Bh(öBh
+žBh{Bh
+=Bh  Bf
+BfzáBfp€BfffBf\)BfQìBfG®Bf=qBf33Bf(öBf
+žBf{Bf
+=Bf  BeõÃBeë
+BeáHBe×
+BeÌÍBeÂBežRBe®Be£×BeBe\Be
+BezáBep€BeffBe\)BeQìBeG®Be=qBe33Be(öBe
+žBe{Be
+=Be  BdõÃBdë
+BdáHBd×
+BdÌÍBdÂBdžRBd®Bd£×BdBd\Bd
+BdzáBdp€BdffBd\)BdQìBdG®Bd=qBd33Bd(öBd
+žBd{Bd
+=Bd  Bb
+BbzáBbp€BbffBb\)BbQìBbG®Bb=qBb33Bb(öBb
+žBb{Bb
+=Bb  BaõÃBaë
+BaáHBa×
+BaÌÍBaÂBažRBa®Ba£×BaBa\Ba
+BazáBap€BaffBa\)BaQìBaG®Ba=qBa33Ba(öBa
+žBa{Ba
+=Ba  B`õÃB`ë
+B`áHB`×
+B`ÌÍB`ÂB`žRB`®B`£×B`B`\B`
+B`záB`p€B`ffB`\)B`QìB`G®B`=qB`33B`(öB`
+žB`{B`
+=B`  B^
+B^záB^p€B^ffB^\)B^QìB^G®B^=qB^33B^(öB^
+žB^{B^
+=B^  B]õÃB]ë
+B]áHB]×
+B]ÌÍB]ÂB]žRB]®B]£×B]B]\B]
+B]záB]p€B]ffB]\)B]QìB]G®B]=qB]33B](öB]
+žB]{B]
+=B]  B\õÃB\ë
+B\áHB\×
+B\ÌÍB\ÂB\žRB\®B\£×B\B\\B\
+B\záB\p€B\ffB\\)B\QìB\G®B\=qB\33B\(öB\
+žB\{B\
+=B\  BZ
+BZzáBZp€BZffBZ\)BZQìBZG®BZ=qBZ33BZ(öBZ
+žBZ{BZ
+=BZ  BYõÃBYë
+BYáHBY×
+BYÌÍBYÂBYžRBY®BY£×BYBY\BY
+BYzáBYp€BYffBY\)BYQìBYG®BY=qBY33BY(öBY
+žBY{BY
+=BY  BXõÃBXë
+BXáHBX×
+BXÌÍBXÂBXžRBX®BX£×BXBX\BX
+BXzáBXp€BXffBX\)BXQìBXG®BX=qBX33BX(öBX
+žBX{BX
+=BX  BV
+BVzáBVp€BVffBV\)BVQìBVG®BV=qBV33BV(öBV
+žBV{BV
+=BV  BUõÃBUë
+BUáHBU×
+BUÌÍBUÂBUžRBU®BU£×BUBU\BU
+BUzáBUp€BUffBU\)BUQìBUG®BU=qBU33BU(öBU
+žBU{BU
+=BU  BTõÃBTë
+BTáHBT×
+BTÌÍBTÂBTžRBT®BT£×BTBT\BT
+BTzáBTp€BTffBT\)BTQìBTG®BT=qBT33BT(öBT
+žBT{BT
+=BT  BR
+BRzáBRp€BRffBR\)BRQìBRG®BR=qBR33BR(öBR
+žBR{BR
+=BR  BQõÃBQë
+BQáHBQ×
+BQÌÍBQÂBQžRBQ®BQ£×BQBQ\BQ
+BQzáBQp€BQffBQ\)BQQìBQG®BQ=qBQ33BQ(öBQ
+žBQ{BQ
+=BQ  BPõÃBPë
+BPáHBP×
+BPÌÍBPÂBPžRBP®BP£×BPBP\BP
+BPzáBPp€BPffBP\)BPQìBPG®BP=qBP33BP(öBP
+žBP{BP
+=BP  BN
+BNzáBNp€BNffBN\)BNQìBNG®BN=qBN33BN(öBN
+žBN{BN
+=BN  BMõÃBMë
+BMáHBM×
+BMÌÍBMÂBMžRBM®BM£×BMBM\BM
+BMzáBMp€BMffBM\)BMQìBMG®BM=qBM33BM(öBM
+žBM{BM
+=BM  BLõÃBLë
+BLáHBL×
+BLÌÍBLÂBLžRBL®BL£×BLBL\BL
+BLzáBLp€BLffBL\)BLQìBLG®BL=qBL33BL(öBL
+žBL{BL
+=BL  BJ
+BJzáBJp€BJffBJ\)BJQìBJG®BJ=qBJ33BJ(öBJ
+žBJ{BJ
+=BJ  BIõÃBIë
+BIáHBI×
+BIÌÍBIÂBIžRBI®BI£×BIBI\BI
+BIzáBIp€BIffBI\)BIQìBIG®BI=qBI33BI(öBI
+žBI{BI
+=BI  BHõÃBHë
+BHáHBH×
+BHÌÍBHÂBHžRBH®BH£×BHBH\BH
+BHzáBHp€BHffBH\)BHQìBHG®BH=qBH33BH(öBH
+žBH{BH
+=BH  BF
+BFzáBFp€BFffBF\)BFQìBFG®BF=qBF33BF(öBF
+žBF{BF
+=BF  BEõÃBEë
+BEáHBE×
+BEÌÍBEÂBEžRBE®BE£×BEBE\BE
+BEzáBEp€BEffBE\)BEQìBEG®BE=qBE33BE(öBE
+žBE{BE
+=BE  BDõÃBDë
+BDáHBD×
+BDÌÍBDÂBDžRBD®BD£×BDBD\BD
+BDzáBDp€BDffBD\)BDQìBDG®BD=qBD33BD(öBD
+žBD{BD
+=BD  BB
+BBzáBBp€BBffBB\)BBQìBBG®BB=qBB33BB(öBB
+žBB{BB
+=BB  BAõÃBAë
+BAáHBA×
+BAÌÍBAÂBAžRBA®BA£×BABA\BA
+BAzáBAp€BAffBA\)BAQìBAG®BA=qBA33BA(öBA
+žBA{BA
+=BA  B@õÃB@ë
+B@áHB@×
+B@ÌÍB@ÂB@žRB@®B@£×B@B@\B@
+B@záB@p€B@ffB@\)B@QìB@G®B@=qB@33B@(öB@
+žB@{B@
+=B@  B>
+B>záB>p€B>ffB>\)B>QìB>G®B>=qB>33B>(öB>
+žB>{B>
+=B>  B=õÃB=ë
+B=áHB=×
+B=ÌÍB=ÂB=žRB=®B=£×B=B=\B=
+B=záB=p€B=ffB=\)B=QìB=G®B==qB=33B=(öB=
+žB={B=
+=B=  B<õÃB<ë
+B<áHB<×
+B<ÌÍB<ÂB<žRB<®B<£×B<B<\B<
+B<záB<p€B<ffB<\)B<QìB<G®B<=qB<33B<(öB<
+žB<{B<
+=B<  B:
+B:záB:p€B:ffB:\)B:QìB:G®B:=qB:33B:(öB:
+žB:{B:
+=B:  B9õÃB9ë
+B9áHB9×
+B9ÌÍB9ÂB9žRB9®B9£×B9B9\B9
+B9záB9p€B9ffB9\)B9QìB9G®B9=qB933B9(öB9
+žB9{B9
+=B9  B8õÃB8ë
+B8áHB8×
+B8ÌÍB8ÂB8žRB8®B8£×B8B8\B8
+B8záB8p€B8ffB8\)B8QìB8G®B8=qB833B8(öB8
+žB8{B8
+=B8  B6
+B6záB6p€B6ffB6\)B6QìB6G®B6=qB633B6(öB6
+žB6{B6
+=B6  B5õÃB5ë
+B5áHB5×
+B5ÌÍB5ÂB5žRB5®B5£×B5B5\B5
+B5záB5p€B5ffB5\)B5QìB5G®B5=qB533B5(öB5
+žB5{B5
+=B5  B4õÃB4ë
+B4áHB4×
+B4ÌÍB4ÂB4žRB4®B4£×B4B4\B4
+B4záB4p€B4ffB4\)B4QìB4G®B4=qB433B4(öB4
+žB4{B4
+=B4  B2
+B2záB2p€B2ffB2\)B2QìB2G®B2=qB233B2(öB2
+žB2{B2
+=B2  B1õÃB1ë
+B1áHB1×
+B1ÌÍB1ÂB1žRB1®B1£×B1B1\B1
+B1záB1p€B1ffB1\)B1QìB1G®B1=qB133B1(öB1
+žB1{B1
+=B1  B0õÃB0ë
+B0áHB0×
+B0ÌÍB0ÂB0žRB0®B0£×B0B0\B0
+B0záB0p€B0ffB0\)B0QìB0G®B0=qB033B0(öB0
+žB0{B0
+=B0  B.
+B.záB.p€B.ffB.\)B.QìB.G®B.=qB.33B.(öB.
+žB.{B.
+=B.  B-õÃB-ë
+B-áHB-×
+B-ÌÍB-ÂB-žRB-®B-£×B-B-\B-
+B-záB-p€B-ffB-\)B-QìB-G®B-=qB-33B-(öB-
+žB-{B-
+=B-  B,õÃB,ë
+B,áHB,×
+B,ÌÍB,ÂB,žRB,®B,£×B,B,\B,
+B,záB,p€B,ffB,\)B,QìB,G®B,=qB,33B,(öB,
+žB,{B,
+=B,  B*
+B*záB*p€B*ffB*\)B*QìB*G®B*=qB*33B*(öB*
+žB*{B*
+=B*  B)õÃB)ë
+B)áHB)×
+B)ÌÍB)ÂB)žRB)®B)£×B)B)\B)
+B)záB)p€B)ffB)\)B)QìB)G®B)=qB)33B)(öB)
+žB){B)
+=B)  B(õÃB(ë
+B(áHB(×
+B(ÌÍB(ÂB(žRB(®B(£×B(B(\B(
+B(záB(p€B(ffB(\)B(QìB(G®B(=qB(33B((öB(
+žB({B(
+=B(  B&
+B&záB&p€B&ffB&\)B&QìB&G®B&=qB&33B&(öB&
+žB&{B&
+=B&  B%õÃB%ë
+B%áHB%×
+B%ÌÍB%ÂB%žRB%®B%£×B%B%\B%
+B%záB%p€B%ffB%\)B%QìB%G®B%=qB%33B%(öB%
+žB%{B%
+=B%  B$õÃB$ë
+B$áHB$×
+B$ÌÍB$ÂB$žRB$®B$£×B$B$\B$
+B$záB$p€B$ffB$\)B$QìB$G®B$=qB$33B$(öB$
+žB${B$
+=B$  B"
+B"záB"p€B"ffB"\)B"QìB"G®B"=qB"33B"(öB"
+žB"{B"
+=B"  B!õÃB!ë
+B!áHB!×
+B!ÌÍB!ÂB!žRB!®B!£×B!B!\B!
+B!záB!p€B!ffB!\)B!QìB!G®B!=qB!33B!(öB!
+žB!{B!
+=B!  B õÃB ë
+B áHB ×
+B ÌÍB ÂB žRB ®B £×B B \B 
+B záB p€B ffB \)B QìB G®B =qB 33B (öB 
+žB {B 
+=B   B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B	õÃB	ë
+B	áHB	×
+B	ÌÍB	ÂB	žRB	®B	£×B	B	\B	
+B	záB	p€B	ffB	\)B	QìB	G®B	=qB	33B	(öB	
+žB	{B	
+=B	  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B õÃB ë
+B áHB ×
+B ÌÍB ÂB žRB ®B £×B B \B 
+B záB p€B ffB \)B QìB G®B =qB 33B (öB 
+žB {B 
+=B   Aý
+=AüõÃAüáHAüÌÍAüžRAü£×Aü\AüzáAüffAüQìAü=qAü(öAü{Aü  Aûë
+Aû×
+AûÂAû®AûAû
+Aûp€Aû\)AûG®Aû33Aû
+žAû
+=AúõÃAúáHAúÌÍAúžRAú£×Aú\AúzáAúffAúQìAú=qAú(öAú{Aú  Aùë
+Aù×
+AùÂAù®AùAù
+Aùp€Aù\)AùG®Aù33Aù
+žAù
+=AøõÃAøáHAøÌÍAøžRAø£×Aø\AøzáAøffAøQìAø=qAø(öAø{Aø  Aõ
+=AôõÃAôáHAôÌÍAôžRAô£×Aô\AôzáAôffAôQìAô=qAô(öAô{Aô  Aóë
+Aó×
+AóÂAó®AóAó
+Aóp€Aó\)AóG®Aó33Aó
+žAó
+=AòõÃAòáHAòÌÍAòžRAò£×Aò\AòzáAòffAòQìAò=qAò(öAò{Aò  Añë
+Añ×
+AñÂAñ®AñAñ
+Añp€Añ\)AñG®Añ33Añ
+žAñ
+=AðõÃAðáHAðÌÍAðžRAð£×Að\AðzáAðffAðQìAð=qAð(öAð{Að  Aí
+=AìõÃAìáHAìÌÍAìžRAì£×Aì\AìzáAìffAìQìAì=qAì(öAì{Aì  Aëë
+Aë×
+AëÂAë®AëAë
+Aëp€Aë\)AëG®Aë33Aë
+žAë
+=AêõÃAêáHAêÌÍAêžRAê£×Aê\AêzáAêffAêQìAê=qAê(öAê{Aê  Aéë
+Aé×
+AéÂAé®AéAé
+Aép€Aé\)AéG®Aé33Aé
+žAé
+=AèõÃAèáHAèÌÍAèžRAè£×Aè\AèzáAèffAèQìAè=qAè(öAè{Aè  Aå
+=AäõÃAäáHAäÌÍAäžRAä£×Aä\AäzáAäffAäQìAä=qAä(öAä{Aä  Aãë
+Aã×
+AãÂAã®AãAã
+Aãp€Aã\)AãG®Aã33Aã
+žAã
+=AâõÃAâáHAâÌÍAâžRAâ£×Aâ\AâzáAâffAâQìAâ=qAâ(öAâ{Aâ  Aáë
+Aá×
+AáÂAá®AáAá
+Aáp€Aá\)AáG®Aá33Aá
+žAá
+=AàõÃAàáHAàÌÍAàžRAà£×Aà\AàzáAàffAàQìAà=qAà(öAà{Aà  AÝ
+=AÜõÃAÜáHAÜÌÍAÜžRAÜ£×AÜ\AÜzáAÜffAÜQìAÜ=qAÜ(öAÜ{AÜ  AÛë
+AÛ×
+AÛÂAÛ®AÛAÛ
+AÛp€AÛ\)AÛG®AÛ33AÛ
+žAÛ
+=AÚõÃAÚáHAÚÌÍAÚžRAÚ£×AÚ\AÚzáAÚffAÚQìAÚ=qAÚ(öAÚ{AÚ  AÙë
+AÙ×
+AÙÂAÙ®AÙAÙ
+AÙp€AÙ\)AÙG®AÙ33AÙ
+žAÙ
+=AØõÃAØáHAØÌÍAØžRAØ£×AØ\AØzáAØffAØQìAØ=qAØ(öAØ{AØ  AÕ
+=AÔõÃAÔáHAÔÌÍAÔžRAÔ£×AÔ\AÔzáAÔffAÔQìAÔ=qAÔ(öAÔ{AÔ  AÓë
+AÓ×
+AÓÂAÓ®AÓAÓ
+AÓp€AÓ\)AÓG®AÓ33AÓ
+žAÓ
+=AÒõÃAÒáHAÒÌÍAÒžRAÒ£×AÒ\AÒzáAÒffAÒQìAÒ=qAÒ(öAÒ{AÒ  AÑë
+AÑ×
+AÑÂAÑ®AÑAÑ
+AÑp€AÑ\)AÑG®AÑ33AÑ
+žAÑ
+=AÐõÃAÐáHAÐÌÍAÐžRAÐ£×AÐ\AÐzáAÐffAÐQìAÐ=qAÐ(öAÐ{AÐ  AÍ
+=AÌõÃAÌáHAÌÌÍAÌžRAÌ£×AÌ\AÌzáAÌffAÌQìAÌ=qAÌ(öAÌ{AÌ  AËë
+AË×
+AËÂAË®AËAË
+AËp€AË\)AËG®AË33AË
+žAË
+=AÊõÃAÊáHAÊÌÍAÊžRAÊ£×AÊ\AÊzáAÊffAÊQìAÊ=qAÊ(öAÊ{AÊ  AÉë
+AÉ×
+AÉÂAÉ®AÉAÉ
+AÉp€AÉ\)AÉG®AÉ33AÉ
+žAÉ
+=AÈõÃAÈáHAÈÌÍAÈžRAÈ£×AÈ\AÈzáAÈffAÈQìAÈ=qAÈ(öAÈ{AÈ  AÅ
+=AÄõÃAÄáHAÄÌÍAÄžRAÄ£×AÄ\AÄzáAÄffAÄQìAÄ=qAÄ(öAÄ{AÄ  AÃë
+AÃ×
+AÃÂAÃ®AÃAÃ
+AÃp€AÃ\)AÃG®AÃ33AÃ
+žAÃ
+=AÂõÃAÂáHAÂÌÍAÂžRAÂ£×AÂ\AÂzáAÂffAÂQìAÂ=qAÂ(öAÂ{AÂ  AÁë
+AÁ×
+AÁÂAÁ®AÁAÁ
+AÁp€AÁ\)AÁG®AÁ33AÁ
+žAÁ
+=AÀõÃAÀáHAÀÌÍAÀžRAÀ£×AÀ\AÀzáAÀffAÀQìAÀ=qAÀ(öAÀ{AÀ  Aœ
+=AŒõÃAŒáHAŒÌÍAŒžRAŒ£×AŒ\AŒzáAŒffAŒQìAŒ=qAŒ(öAŒ{AŒ  A»ë
+A»×
+A»ÂA»®A»A»
+A»p€A»\)A»G®A»33A»
+žA»
+=AºõÃAºáHAºÌÍAºžRAº£×Aº\AºzáAºffAºQìAº=qAº(öAº{Aº  A¹ë
+A¹×
+A¹ÂA¹®A¹A¹
+A¹p€A¹\)A¹G®A¹33A¹
+žA¹
+=AžõÃAžáHAžÌÍAžžRAž£×Až\AžzáAžffAžQìAž=qAž(öAž{Až  Aµ
+=AŽõÃAŽáHAŽÌÍAŽžRAŽ£×AŽ\AŽzáAŽffAŽQìAŽ=qAŽ(öAŽ{AŽ  A³ë
+A³×
+A³ÂA³®A³A³
+A³p€A³\)A³G®A³33A³
+žA³
+=A²õÃA²áHA²ÌÍA²žRA²£×A²\A²záA²ffA²QìA²=qA²(öA²{A²  A±ë
+A±×
+A±ÂA±®A±A±
+A±p€A±\)A±G®A±33A±
+žA±
+=A°õÃA°áHA°ÌÍA°žRA°£×A°\A°záA°ffA°QìA°=qA°(öA°{A°  A­
+=A¬õÃA¬áHA¬ÌÍA¬žRA¬£×A¬\A¬záA¬ffA¬QìA¬=qA¬(öA¬{A¬  A«ë
+A«×
+A«ÂA«®A«A«
+A«p€A«\)A«G®A«33A«
+žA«
+=AªõÃAªáHAªÌÍAªžRAª£×Aª\AªzáAªffAªQìAª=qAª(öAª{Aª  A©ë
+A©×
+A©ÂA©®A©A©
+A©p€A©\)A©G®A©33A©
+žA©
+=AšõÃAšáHAšÌÍAšžRAš£×Aš\AšzáAšffAšQìAš=qAš(öAš{Aš  A¥
+=A€õÃA€áHA€ÌÍA€žRA€£×A€\A€záA€ffA€QìA€=qA€(öA€{A€  A£ë
+A£×
+A£ÂA£®A£A£
+A£p€A£\)A£G®A£33A£
+žA£
+=A¢õÃA¢áHA¢ÌÍA¢žRA¢£×A¢\A¢záA¢ffA¢QìA¢=qA¢(öA¢{A¢  A¡ë
+A¡×
+A¡ÂA¡®A¡A¡
+A¡p€A¡\)A¡G®A¡33A¡
+žA¡
+=A õÃA áHA ÌÍA žRA £×A \A záA ffA QìA =qA (öA {A   A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Az{Ayë
+AyÂAyAyp€AyG®Ay
+žAxõÃAxÌÍAx£×AxzáAxQìAx(öAx  Aw×
+Aw®Aw
+Aw\)Aw33Aw
+=AváHAvžRAv\AvffAv=qAv{Auë
+AuÂAuAup€AuG®Au
+žAtõÃAtÌÍAt£×AtzáAtQìAt(öAt  As×
+As®As
+As\)As33As
+=AráHAržRAr\ArffAr=qAr{Aqë
+AqÂAqAqp€AqG®Aq
+žApõÃApÌÍAp£×ApzáApQìAp(öAp  Aj{Aië
+AiÂAiAip€AiG®Ai
+žAhõÃAhÌÍAh£×AhzáAhQìAh(öAh  Ag×
+Ag®Ag
+Ag\)Ag33Ag
+=AfáHAfžRAf\AfffAf=qAf{Aeë
+AeÂAeAep€AeG®Ae
+žAdõÃAdÌÍAd£×AdzáAdQìAd(öAd  Ac×
+Ac®Ac
+Ac\)Ac33Ac
+=AbáHAbžRAb\AbffAb=qAb{Aaë
+AaÂAaAap€AaG®Aa
+žA`õÃA`ÌÍA`£×A`záA`QìA`(öA`  AZ{AYë
+AYÂAYAYp€AYG®AY
+žAXõÃAXÌÍAX£×AXzáAXQìAX(öAX  AW×
+AW®AW
+AW\)AW33AW
+=AVáHAVžRAV\AVffAV=qAV{AUë
+AUÂAUAUp€AUG®AU
+žATõÃATÌÍAT£×ATzáATQìAT(öAT  AS×
+AS®AS
+AS\)AS33AS
+=ARáHARžRAR\ARffAR=qAR{AQë
+AQÂAQAQp€AQG®AQ
+žAPõÃAPÌÍAP£×APzáAPQìAP(öAP  AJ{AIë
+AIÂAIAIp€AIG®AI
+žAHõÃAHÌÍAH£×AHzáAHQìAH(öAH  AG×
+AG®AG
+AG\)AG33AG
+=AFáHAFžRAF\AFffAF=qAF{AEë
+AEÂAEAEp€AEG®AE
+žADõÃADÌÍAD£×ADzáADQìAD(öAD  AC×
+AC®AC
+AC\)AC33AC
+=ABáHABžRAB\ABffAB=qAB{AAë
+AAÂAAAAp€AAG®AA
+žA@õÃA@ÌÍA@£×A@záA@QìA@(öA@  A:{A9ë
+A9ÂA9A9p€A9G®A9
+žA8õÃA8ÌÍA8£×A8záA8QìA8(öA8  A7×
+A7®A7
+A7\)A733A7
+=A6áHA6žRA6\A6ffA6=qA6{A5ë
+A5ÂA5A5p€A5G®A5
+žA4õÃA4ÌÍA4£×A4záA4QìA4(öA4  A3×
+A3®A3
+A3\)A333A3
+=A2áHA2žRA2\A2ffA2=qA2{A1ë
+A1ÂA1A1p€A1G®A1
+žA0õÃA0ÌÍA0£×A0záA0QìA0(öA0  A*{A)ë
+A)ÂA)A)p€A)G®A)
+žA(õÃA(ÌÍA(£×A(záA(QìA((öA(  A'×
+A'®A'
+A'\)A'33A'
+=A&áHA&žRA&\A&ffA&=qA&{A%ë
+A%ÂA%A%p€A%G®A%
+žA$õÃA$ÌÍA$£×A$záA$QìA$(öA$  A#×
+A#®A#
+A#\)A#33A#
+=A"áHA"žRA"\A"ffA"=qA"{A!ë
+A!ÂA!A!p€A!G®A!
+žA õÃA ÌÍA £×A záA QìA (öA   A{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A
+{A	ë
+A	ÂA	A	p€A	G®A	
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žA õÃA ÌÍA £×A záA QìA (öA   @ô(ö@ó×
+@ó
+@ó33@òáH@ò\@ò=q@ñë
+@ñ@ñG®@ðõÂ@ð£×@ðQì@ð  @ï®@ï\)@ï
+=@îžR@îff@î{@íÂ@íp€@í
+ž@ìÌÍ@ìzá@ì(ö@ë×
+@ë
+@ë33@êáH@ê\@ê=q@éë
+@é@éG®@èõÃ@è£×@èQì@è  @ç®@ç\)@ç
+=@æžR@æff@æ{@åÂ@åp€@å
+ž@äÌÍ@äzá@ä(ö@ã×
+@ã
+@ã33@âáH@â\@â=q@áë
+@á@áG®@àõÃ@à£×@àQì@à  @Ô(ö@Ó×
+@Ó
+@Ó33@ÒáH@Ò\@Ò=q@Ñë
+@Ñ@ÑG®@ÐõÂ@Ð£×@ÐQì@Ð  @Ï®@Ï\)@Ï
+=@ÎžR@Îff@Î{@ÍÂ@Íp€@Í
+ž@ÌÌÍ@Ìzá@Ì(ö@Ë×
+@Ë
+@Ë33@ÊáH@Ê\@Ê=q@Éë
+@É@ÉG®@ÈõÃ@È£×@ÈQì@È  @Ç®@Ç\)@Ç
+=@ÆžR@Æff@Æ{@ÅÂ@Åp€@Å
+ž@ÄÌÍ@Äzá@Ä(ö@Ã×
+@Ã
+@Ã33@ÂáH@Â\@Â=q@Áë
+@Á@ÁG®@ÀõÃ@À£×@ÀQì@À  @Ž(ö@³×
+@³
+@³33@²áH@²\@²=q@±ë
+@±@±G®@°õÂ@°£×@°Qì@°  @¯®@¯\)@¯
+=@®žR@®ff@®{@­Â@­p€@­
+ž@¬ÌÍ@¬zá@¬(ö@«×
+@«
+@«33@ªáH@ª\@ª=q@©ë
+@©@©G®@šõÃ@š£×@šQì@š  @§®@§\)@§
+=@ŠžR@Šff@Š{@¥Â@¥p€@¥
+ž@€ÌÍ@€zá@€(ö@£×
+@£
+@£33@¢áH@¢\@¢=q@¡ë
+@¡@¡G®@ õÃ@ £×@ Qì@   @(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÂ@£×@Qì@  @®@\)@
+=@žR@ff@{@Â@p€@
+ž@ÌÍ@zá@(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÃ@£×@Qì@  @®@\)@
+=@žR@ff@{@
+Â@
+p€@
+
+ž@ÌÍ@zá@(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÃ@£×@Qì@  @hQì@g®@g
+>@fff@eÂ@e
+ž@dzá@c×
+@c33@b\@aë
+@aG®@`£×@`  @_\)@^žR@^{@]p€@\ÌÍ@\(ö@[
+@ZáH@Z=q@Y@XõÂ@XQì@W®@W
+>@Vff@UÂ@U
+ž@Tzá@S×
+@S33@R\@Që
+@QG®@P£×@P  @O\)@NžR@N{@Mp€@LÌÍ@L(ö@K
+@JáH@J=q@I@HõÃ@HQì@G®@G
+=@Fff@EÂ@E
+ž@Dzá@C×
+@C33@B\@Aë
+@AG®@@£×@@  @(Qì@'®@'
+>@&ff@%Â@%
+ž@$zá@#×
+@#33@"\@!ë
+@!G®@ £×@   @\)@
+žR@
+{@
+p€@
+ÌÍ@
+(ö@
+@áH@=q@@õÂ@Qì@®@
+>@ff@Â@
+ž@zá@×
+@33@\@ë
+@G®@£×@  @\)@žR@{@
+p€@
+ÌÍ@
+(ö@
+
+@
+áH@
+=q@	@õÃ@Qì@®@
+=@ff@Â@
+ž@zá@×
+@33@\@ë
+@G®@ £×@   ?Ð£×?Ï\)?Î{?ÌÌÍ?Ë
+
+?Ê=p?ÈõÂ?Ç®?Æff?Å
+ž?Ã×
+?Â\?ÁG®?À  ?ŸžR?œp€?Œ(ö?ºáH?¹?žQì?·
+>?µÂ?Žzá?³33?±ë
+?°£×?¯\)?®{?¬ÌÍ?«
+?ª=q?šõÂ?§®?Šff?¥
+ž?£×
+?¢\?¡G®?   ?žR?p€?(ö?áH??Qì?
+>?Â?zá?33?ë
+?£×?\)?{?ÌÍ?
+?=q?õÃ?®?ff?
+
+ž?×
+?\?G®?  ?!G®?
+žR?
+(ö??
+=?zá?ë
+?\)?
+ÌÍ?
+=q?®?
+ž?\?   >úáH>õÂ>ð£×>ë
+>æff>áG®>Ü(ö>×
+=>Ñë
+>ÌÌÍ>Ç®>Â\>œp€>žQì>³33>®{>šõÃ>£×
+>žR>>zá>\)>=q>
+
+ž>  >uÂ>k
+>aG®>W
+=>LÌÍ>B\>8Qì>.{>#×
+>>\)>
+ž=õÂ=áG®=ÌÌÍ=žQì=£×
+=\)=uÂ=LÌÍ=#×
+<õÂ<£×
+<#×
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bz
+B~zá¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bv
+BzzáBzzáB~p€¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bn
+BrzáBvzáBzp€BzffB~\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bj
+BnzáBnzáBrp€BvffBz\)Bz\)B~Qì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bf
+BfzáBjzáBnp€BnffBr\)Bv\)BzQìBzG®B~G®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B^
+BbzáBfzáBfp€BjffBn\)Bn\)BrQìBvG®BzG®Bz=qB~33¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BZ
+BZzáB^záBbp€BfffBf\)Bj\)BnQìBnG®BrG®Bv=qBz33Bz(öB~(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BR
+BVzáBZzáBZp€B^ffBb\)Bf\)BfQìBjG®BnG®Bn=qBr33Bv(öBz(öBz
+žB~{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BN
+BRzáBRzáBVp€BZffBZ\)B^\)BbQìBfG®BfG®Bj=qBn33Bn(öBr(öBv
+žBz{Bz{B~
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BJ
+BJzáBNzáBRp€BRffBV\)BZ\)BZQìB^G®BbG®Bf=qBf33Bj(öBn(öBn
+žBr{Bv{Bz
+=Bz  B~  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BB
+BFzáBJzáBJp€BNffBR\)BR\)BVQìBZG®BZG®B^=qBb33Bf(öBf(öBj
+žBn{Bn{Br
+=Bv  Bz  ByõÃB}ë
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B>
+B>záBBzáBFp€BJffBJ\)BN\)BRQìBRG®BVG®BZ=qBZ33B^(öBb(öBf
+žBf{Bj{Bn
+=Bn  Br  BuõÃByë
+ByáHB}áH¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B6
+B:záB>záB>p€BBffBF\)BJ\)BJQìBNG®BRG®BR=qBV33BZ(öBZ(öB^
+žBb{Bf{Bf
+=Bj  Bn  BmõÃBqë
+BuáHByáHBy×
+B}ÌÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B2
+B6záB6záB:p€B>ffB>\)BB\)BFQìBJG®BJG®BN=qBR33BR(öBV(öBZ
+žBZ{B^{Bb
+=Bf  Bf  BiõÃBmë
+BmáHBqáHBu×
+ByÌÍByÌÍB}Â¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B*
+B.záB2záB6p€B6ffB:\)B>\)B>QìBBG®BFG®BJ=qBJ33BN(öBR(öBR
+žBV{BZ{BZ
+=B^  Bb  BeõÃBeë
+BiáHBmáHBm×
+BqÌÍBuÌÍByÂByžRB}®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B&
+B*záB*záB.p€B2ffB6\)B6\)B:QìB>G®B>G®BB=qBF33BJ(öBJ(öBN
+žBR{BR{BV
+=BZ  BZ  B]õÃBaë
+BeáHBeáHBi×
+BmÌÍBmÌÍBqÂBužRBy®By®B}£×¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B"
+B"záB&záB*p€B*ffB.\)B2\)B6QìB6G®B:G®B>=qB>33BB(öBF(öBJ
+žBJ{BN{BR
+=BR  BV  BYõÃBYë
+B]áHBaáHBe×
+BeÌÍBiÌÍBmÂBmžRBq®Bu®By£×ByB}¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+B
+záB"záB"p€B&ffB*\)B*\)B.QìB2G®B6G®B6=qB:33B>(öB>(öBB
+žBF{BJ{BJ
+=BN  BR  BQõÃBUë
+BYáHBYáHB]×
+BaÌÍBeÌÍBeÂBižRBm®Bm®Bq£×BuByBy\B}
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+BzáBzáB
+p€B"ffB"\)B&\)B*QìB*G®B.G®B2=qB633B6(öB:(öB>
+žB>{BB{BF
+=BJ  BJ  BMõÃBQë
+BQáHBUáHBY×
+BYÌÍB]ÌÍBaÂBežRBe®Bi®Bm£×BmBqBu\By
+By
+B}zá¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+BzáBzáBp€BffB
+\)B"\)B"QìB&G®B*G®B*=qB.33B2(öB6(öB6
+žB:{B>{B>
+=BB  BF  BIõÃBIë
+BMáHBQáHBQ×
+BUÌÍBYÌÍBYÂB]žRBa®Be®Be£×BiBmBm\Bq
+Bu
+ByzáByp€B}ff¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+
+BzáBzáBp€BffB\)B\)B
+QìB"G®B"G®B&=qB*33B*(öB.(öB2
+žB6{B6{B:
+=B>  B>  BAõÃBEë
+BIáHBIáHBM×
+BQÌÍBQÌÍBUÂBYžRBY®B]®Ba£×BeBeBi\Bm
+Bm
+BqzáBup€ByffByffB}\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+BzáB
+záBp€BffB\)B\)BQìBG®B
+G®B"=qB"33B&(öB*(öB*
+žB.{B2{B6
+=B6  B:  B=õÃB=ë
+BAáHBEáHBI×
+BIÌÍBMÌÍBQÂBQžRBU®BY®BY£×B]BaBe\Be
+Bi
+BmzáBmp€BqffBuffBy\)ByQìB}Qì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aý
+=BzáBzáBp€B
+ffB\)B\)BQìBG®BG®B=qB
+33B"(öB"(öB&
+žB*{B*{B.
+=B2  B6  B5õÃB9ë
+B=áHB=áHBA×
+BEÌÍBIÌÍBIÂBMžRBQ®BQ®BU£×BYBYB]\Ba
+Be
+BezáBip€BmffBmffBq\)BuQìByQìByG®B}=q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aõ
+=AôõÃAüõÃBp€BffB\)B
+\)BQìBG®BG®B=qB33B(öB
+(öB"
+žB"{B&{B*
+=B*  B.  B1õÃB5ë
+B5áHB9áHB=×
+B=ÌÍBAÌÍBEÂBIžRBI®BM®BQ£×BQBUBY\BY
+B]
+BazáBep€BeffBiffBm\)BmQìBqQìBuG®By=qBy33B}33¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aå
+=AìõÃAôõÃAôáHAüÌÍB\)B\)BQìB
+G®BG®B=qB33B(öB(öB
+žB
+{B"{B"
+=B&  B*  B)õÃB-ë
+B1áHB5áHB5×
+B9ÌÍB=ÌÍB=ÂBAžRBE®BI®BI£×BMBQBQ\BU
+BY
+BYzáB]p€BaffBeffBe\)BiQìBmQìBmG®Bq=qBu33By33By(öB}
+ž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÝ
+=AäõÃAäõÃAìáHAôÌÍAôžRAüžRBQìBG®BG®B
+=qB33B(öB(öB
+žB{B{B
+
+=B"  B"  B%õÃB)ë
+B)áHB-áHB1×
+B5ÌÍB5ÌÍB9ÂB=žRB=®BA®BE£×BIBIBM\BQ
+BQ
+BUzáBYp€BYffB]ffBa\)BeQìBeQìBiG®Bm=qBm33Bq33Bu(öBy
+žBy
+žB}{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÍ
+=AÔõÃAÜõÃAäáHAäÌÍAìžRAôžRAô£×Aü\BG®B=qB33B
+(öB(öB
+žB{B{B
+=B  B
+  B!õÃB!ë
+B%áHB)áHB)×
+B-ÌÍB1ÌÍB5ÂB5žRB9®B=®B=£×BABEBI\BI
+BM
+BQzáBQp€BUffBYffBY\)B]QìBaQìBeG®Be=qBi33Bm33Bm(öBq
+žBu
+žBy{By
+=B}  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÅ
+=AÌõÃAÌõÃAÔáHAÜÌÍAäžRAäžRAì£×Aô\Aô\AüzáB33B(öB(öB
+
+žB{B{B
+=B  B  BõÃB
+ë
+B!áHB!áHB%×
+B)ÌÍB)ÌÍB-ÂB1žRB5®B5®B9£×B=B=BA\BE
+BI
+BIzáBMp€BQffBQffBU\)BYQìBYQìB]G®Ba=qBe33Be33Bi(öBm
+žBm
+žBq{Bu
+=By  By  B|õÃ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aœ
+=AŒõÃAÄõÃAÌáHAÌÌÍAÔžRAÜžRAä£×Aä\Aì\AôzáAôffAüQìB(öB
+žB{B
+{B
+=B  B  BõÃBë
+BáHB
+áHB!×
+B!ÌÍB%ÌÍB)ÂB)žRB-®B1®B5£×B5B9B=\B=
+BA
+BEzáBIp€BIffBMffBQ\)BQQìBUQìBYG®BY=qB]33Ba33Be(öBe
+žBi
+žBm{Bm
+=Bq  Bu  BxõÃBxë
+B|ë
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A­
+=AŽõÃAŒõÃAŒáHAÄÌÍAÌžRAÌžRAÔ£×AÜ\Aä\AäzáAìffAôQìAôQìAü=qB{B{B
+=B
+  B  B
+õÃBë
+BáHBáHB×
+B
+ÌÍB!ÌÍB!ÂB%žRB)®B)®B-£×B1B5B5\B9
+B=
+B=záBAp€BEffBIffBI\)BMQìBQQìBQG®BU=qBY33BY33B](öBa
+žBe
+žBe{Bi
+=Bm  Bm  BpõÃBtë
+Bxë
+BxáHB|×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A¥
+=A¬õÃA¬õÃAŽáHAŒÌÍAŒžRAÄžRAÌ£×AÌ\AÔ\AÜzáAäffAäQìAìQìAô=qAô(öAü(öB
+=B  B  B	õÃB
+ë
+B
+áHBáHB×
+BÌÍBÌÍB
+ÂB!žRB!®B%®B)£×B)B-B1\B5
+B5
+B9záB=p€B=ffBAffBE\)BIQìBIQìBMG®BQ=qBQ33BU33BY(öBY
+žB]
+žBa{Be
+=Be  Bi  BlõÃBlë
+Bpë
+BtáHBx×
+Bx×
+B|ÌÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+=AõÃA€õÃA¬áHA¬ÌÍAŽžRAŒžRAŒ£×AÄ\AÌ\AÌzáAÔffAÜQìAäQìAä=qAì(öAô(öAô{Aü  B  BõÃBë
+B	áHB
+áHB
+×
+BÌÍBÌÍBÂBžRB
+®B!®B!£×B%B)B)\B-
+B1
+B5záB5p€B9ffB=ffB=\)BAQìBEQìBIG®BI=qBM33BQ33BQ(öBU
+žBY
+žBY{B]
+=Ba  Be  BdõÃBhë
+Blë
+BláHBp×
+Bt×
+BxÌÍBxÂB|žR¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+=AõÃAõÃAáHA€ÌÍA¬žRA¬žRAŽ£×AŒ\AŒ\AÄzáAÌffAÌQìAÔQìAÜ=qAä(öAä(öAì{Aô  Aô  Aûë
+Bë
+BáHBáHB	×
+B
+ÌÍB
+ÌÍBÂBžRB®B®B
+£×B!B!B%\B)
+B)
+B-záB1p€B5ffB5ffB9\)B=QìB=QìBAG®BE=qBI33BI33BM(öBQ
+žBQ
+žBU{BY
+=BY  B]  B`õÃBdë
+Bdë
+BháHBl×
+Bl×
+BpÌÍBtÂBxžRBxžRB|®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+
+=AõÃAõÃAáHAÌÍAžRA€žRA¬£×A¬\AŽ\AŒzáAŒffAÄQìAÌQìAÌ=qAÔ(öAÜ(öAä{Aä  Aì  Aóë
+Aó×
+AûÂBáHB×
+BÌÍB	ÌÍB
+ÂB
+žRB®B®B£×BB
+B!\B!
+B%
+B)záB)p€B-ffB1ffB5\)B5QìB9QìB=G®B==qBA33BE33BI(öBI
+žBM
+žBQ{BQ
+=BU  BY  BXõÃB\ë
+B`ë
+BdáHBd×
+Bh×
+BlÌÍBlÂBpžRBtžRBx®Bx£×B|£×¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aj{Ayë
+AõÃAáHAÌÍAžRAžRA£×A€\A¬\A¬záAŽffAŒQìAŒQìAÄ=qAÌ(öAÌ(öAÔ{AÜ  Aä  Aãë
+Aë×
+AóÂAóÂAû®BÌÍBÌÍBÂB	žRB
+®B
+®B£×BBB\B
+
+B!
+B!záB%p€B)ffB)ffB-\)B1QìB5QìB5G®B9=qB=33B=33BA(öBE
+žBI
+žBI{BM
+=BQ  BQ  BTõÃBXë
+BXë
+B\áHB`×
+Bd×
+BdÌÍBhÂBlžRBlžRBp®Bt£×Bx£×BxB|\¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AZ{AYë
+Aië
+AyÂAÌÍAžRAžRA£×A\A\A€záA¬ffA¬QìAŽQìAŒ=qAŒ(öAÄ(öAÌ{AÌ  AÔ  AÛë
+Aã×
+AãÂAëÂAó®AóAûBÂBžRB®B	®B
+£×B
+BB\B
+B
+B
+záB!p€B!ffB%ffB)\)B)QìB-QìB1G®B5=qB533B933B=(öB=
+žBA
+žBE{BI
+=BI  BM  BPõÃBPë
+BTë
+BXáHBX×
+B\×
+B`ÌÍBdÂBdžRBhžRBl®Bl£×Bp£×BtBx\Bx
+B|
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A:{AIë
+AYë
+AYÂAiAyp€AžRA£×A\A\AzáAffA€QìA¬QìA¬=qAŽ(öAŒ(öAŒ{AÄ  AÌ  AËë
+AÓ×
+AÛÂAãÂAã®AëAóAó
+Aûp€B®B®B£×B	B
+B
+\B
+B
+BzáBp€B
+ffB!ffB!\)B%QìB)QìB)G®B-=qB133B533B5(öB9
+žB=
+žB={BA
+=BE  BI  BHõÃBLë
+BPë
+BPáHBT×
+BX×
+BXÌÍB\ÂB`žRBdžRBd®Bh£×Bl£×BlBp\Bt
+Bx
+BxzáB|p€¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A*{A9ë
+A9ë
+AIÂAYAYp€Aip€AyG®A\A\AzáAffAQìAQìA€=qA¬(öA¬(öAŽ{AŒ  AŒ  AÃë
+AË×
+AËÂAÓÂAÛ®AãAãAë
+Aóp€Aó\)Aû\)B£×BBB	\B
+
+B
+
+BzáBp€BffBffB
+\)B!QìB!QìB%G®B)=qB)33B-33B1(öB5
+žB5
+žB9{B=
+=B=  BA  BDõÃBHë
+BHë
+BLáHBP×
+BP×
+BTÌÍBXÂBXžRB\žRB`®Bd£×Bd£×BhBl\Bl
+Bp
+BtzáBxp€Bxp€B|ff¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A{Aë
+A)ë
+A9ÂA9AIp€AYp€AYG®Ai
+žAy
+žAzáAffAQìAQìA=qA(öA€(öA¬{A¬  AŽ  A»ë
+A»×
+AÃÂAËÂAË®AÓAÛAã
+Aãp€Aë\)Aó\)AóG®Aû33BB\B
+B	
+B
+záB
+p€BffBffB\)BQìB
+QìB!G®B!=qB%33B)33B)(öB-
+žB1
+žB5{B5
+=B9  B=  B<õÃB@ë
+BDë
+BHáHBH×
+BL×
+BPÌÍBPÂBTžRBXžRBX®B\£×B`£×BdBd\Bh
+Bl
+BlzáBpp€Btp€BxffBx\)B|\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @ô(öA	ë
+Aë
+AÂA)A9p€A9p€AIG®AY
+žAY
+žAhõÃAxÌÍAQìAQìA=qA(öA(öA{A€  A¬  A«ë
+A³×
+A»ÂA»ÂAÃ®AËAËAÓ
+AÛp€Aã\)Aã\)AëG®Aó33Aó33Aû
+žB
+B
+BzáB	p€B
+ffB
+ffB\)BQìBQìBG®B
+=qB!33B!33B%(öB)
+žB)
+žB-{B1
+=B5  B5  B8õÃB<ë
+B<ë
+B@áHBD×
+BH×
+BHÌÍBLÂBPžRBPžRBT®BX£×BX£×B\B`\Bd
+Bd
+BhzáBlp€Blp€BpffBt\)Bx\)BxQìB|G®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @Ô(ö@Ó×
+@ó×
+A	ÂAAp€A)p€A9G®A9
+žAI
+žAXõÃAXÌÍAh£×Ax£×A=qA(öA(öA{A  A  A£ë
+A«×
+A«ÂA³ÂA»®A»AÃAË
+AËp€AÓ\)AÛ\)AãG®Aã33Aë33Aó
+žAó
+=Aû
+=BzáBp€BffB	ffB
+\)B
+QìBQìBG®B=qB33B
+33B!(öB!
+žB%
+žB){B)
+=B-  B1  B4õÃB4ë
+B8ë
+B<áHB<×
+B@×
+BDÌÍBHÂBHžRBLžRBP®BP£×BT£×BXBX\B\
+B`
+BdzáBdp€Bhp€BlffBl\)Bp\)BtQìBxG®Bx=qB|=q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @(ö@³×
+@Ó×
+@Ó
+@ó33A	p€Ap€AG®A)
+žA9
+žA8õÃAHÌÍAX£×AX£×AhzáAxQìA(öA{A  A  Aë
+A×
+A£ÂA«ÂA«®A³A»A»
+AÃp€AË\)AË\)AÓG®AÛ33Aã33Aã
+žAë
+=Aó
+=AòõÃAúáHBffBffB\)B	QìB
+QìB
+G®B=qB33B33B(öB
+
+žB!
+žB!{B%
+=B)  B)  B,õÃB0ë
+B4ë
+B4áHB8×
+B<×
+B<ÌÍB@ÂBDžRBHžRBH®BL£×BP£×BPBT\BX
+BX
+B\záB`p€Bdp€BdffBh\)Bl\)BlQìBpG®Bt=qBx=qBx33B|(ö¿  ¿  ¿  ¿  ¿  ¿  @hQì@×
+@×
+@³
+@Ó33@ÒáH@òáHA	G®A
+žA
+žA(õÃA8ÌÍA8£×AH£×AXzáAXQìAhQìAx(öA  A  Aë
+A×
+AÂAÂA£®A«A«A³
+A»p€A»\)AÃ\)AËG®AË33AÓ33AÛ
+žAã
+=Aã
+=AêõÃAòáHAòÌÍAúÌÍB\)BQìBQìB	G®B
+=qB
+33B33B(öB
+žB
+žB
+{B!
+=B!  B%  B(õÃB(ë
+B,ë
+B0áHB4×
+B4×
+B8ÌÍB<ÂB<žRB@žRBD®BH£×BH£×BLBP\BP
+BT
+BXzáBXp€B\p€B`ffBd\)Bd\)BhQìBlG®Bl=qBp=qBt33Bx(öBx(öB|
+ž¿  ¿  ¿  ¿  ?Ð£×@'®@g®@
+@33@²áH@ÒáH@Ò\@ò=qA	
+žAõÃAÌÍA(£×A8£×A8záAHQìAXQìAX(öAh  Ax  Aë
+A×
+AÂAÂA®AA£A«
+A«p€A³\)A»\)A»G®AÃ33AË33AË
+žAÓ
+=AÛ
+=AâõÃAâáHAêÌÍAòÌÍAòžRAú£×BQìBG®B=qB	33B
+33B
+(öB
+žB
+žB{B
+=B
+  B!  B õÃB$ë
+B(ë
+B(áHB,×
+B0×
+B4ÌÍB4ÂB8žRB<žRB<®B@£×BD£×BHBH\BL
+BP
+BPzáBTp€BXp€BXffB\\)B`\)BdQìBdG®Bh=qBl=qBl33Bp(öBt(öBx
+žBx{B|
+=¿  ¿  ?!G®?Ï\)?Ï\)@'
+>@fff@áH@áH@²\@Ò=q@Ò=q@ñë
+AÌÍA£×A£×A(záA8QìA8QìAH(öAX  AX  Ag×
+Aw®AÂAÂA®AAA
+A£p€A«\)A«\)A³G®A»33A»33AÃ
+žAË
+=AË
+=AÒõÃAÚáHAâÌÍAâÌÍAêžRAò£×Aò£×Aú\B=qB33B33B	(öB
+
+žB
+
+žB{B
+=B  B  B
+õÃB ë
+B ë
+B$áHB(×
+B(×
+B,ÌÍB0ÂB4žRB4žRB8®B<£×B<£×B@BD\BH
+BH
+BLzáBPp€BPp€BTffBX\)BX\)B\QìB`G®Bd=qBd=qBh33Bl(öBl(öBp
+žBt{Bx
+=Bx
+=B|  ¿  ¿  ?
+žR?Î{?ÌÌÍ@%Â@eÂ@\@=q@²=q@Ñë
+@Ñ@ñG®A£×AzáAQìA(QìA8(öA8  AH  AW×
+AW®Ag
+Aw
+A®AAA
+Ap€A\)A£\)A«G®A«33A³33A»
+žA»
+=AÃ
+=AÊõÃAÊáHAÒÌÍAÚÌÍAâžRAâ£×Aê£×Aò\AòzáAúffB33B(öB
+žB	
+žB
+{B
+=B  B  BõÃBë
+B
+ë
+B áHB ×
+B$×
+B(ÌÍB(ÂB,žRB0žRB4®B4£×B8£×B<B<\B@
+BD
+BHzáBHp€BLp€BPffBP\)BT\)BXQìBXG®B\=qB`=qBd33Bd(öBh(öBl
+žBl{Bp
+=Bt
+=Bx  ¿  ¿  ¿  ¿  ??Ë
+
+?Ë
+
+@%
+ž@dzá@=q@ë
+@±@ÑG®@ÑG®@ðõÂAQìAQìA(öA(  A8  A7×
+AG®AW
+AW
+Ag\)Aw33AA
+Ap€A\)A\)AG®A£33A«33A«
+žA³
+=A»
+=AºõÃAÂáHAÊÌÍAÊÌÍAÒžRAÚ£×Aâ£×Aâ\AêzáAòffAòffAúQìB
+žB
+žB{B	
+=B
+  B
+  BõÃBë
+Bë
+BáHB
+×
+B ×
+B ÌÍB$ÂB(žRB(žRB,®B0£×B4£×B4B8\B<
+B<
+B@záBDp€BHp€BHffBL\)BP\)BPQìBTG®BX=qBX=qB\33B`(öBd(öBd
+žBh{Bl
+=Bl
+=Bp  ¿  ¿  ¿  ¿  ¿  ¿  ?
+=?Ê=p?ÈõÂ@$zá@c×
+@@G®@±G®@ÐõÂ@Ð£×@ð£×A(öA  A  A'×
+A7®A7
+AG
+AW\)AW33Ag33Aw
+=Ap€A\)A\)AG®A33A33A£
+žA«
+=A«
+=A²õÃAºáHAºÌÍAÂÌÍAÊžRAÊ£×AÒ£×AÚ\AâzáAâffAêffAòQìAò=qAú=qB{B
+=B  B	  B
+õÃB
+ë
+Bë
+BáHB×
+B×
+B
+ÌÍB ÂB žRB$žRB(®B(£×B,£×B0B4\B4
+B8
+B<záB<p€B@p€BDffBH\)BH\)BLQìBPG®BP=qBT=qBX33BX(öB\(öB`
+žBd{Bd
+=Bh
+=Bl  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?ë
+?ÈõÂ?Ç®@#33@b\@G®@õÂ@°£×@Ð£×@ÐQì@ð  A  A×
+A®A'
+A7
+A7\)AG33AW33AW
+=AfáHAvžRA\)AG®A33A33A
+žA
+=A£
+=AªõÃAªáHA²ÌÍAºÌÍAºžRAÂ£×AÊ£×AÊ\AÒzáAÚffAâffAâQìAê=qAò=qAò(öAú{B  B  BõÃBë
+B
+ë
+B
+áHB×
+B×
+BÌÍBÂB
+žRB žRB ®B$£×B(£×B(B,\B0
+B4
+B4záB8p€B<p€B<ffB@\)BD\)BHQìBHG®BL=qBP=qBP33BT(öBX(öBX
+žB\{B`
+=Bd
+=Bd  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?\)?Æff?Å
+ž@"\@aë
+@£×@£×@°Qì@Ð  @Ð  @ï®A®A
+A
+A'\)A733A733AG
+=AVáHAVžRAfžRAv\A33A33A
+žA
+=A
+=AõÃA¢áHAªÌÍAªÌÍA²žRAº£×Aº£×AÂ\AÊzáAÊffAÒffAÚQìAâ=qAâ=qAê(öAò{Aò  Aú  B õÃBë
+Bë
+BáHB
+×
+B
+×
+BÌÍBÂBžRBžRB
+®B £×B £×B$B(\B(
+B,
+B0záB4p€B4p€B8ffB<\)B<\)B@QìBDG®BH=qBH=qBL33BP(öBP(öBT
+žBX{BX
+=B\
+=B`  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+=q?Å
+ž?Ã×
+@!G®@aG®@Qì@  @°  @Ï®@Ï\)@ï
+=A
+A\)A33A'33A7
+=A6áHAFžRAVžRAV\AfffAvffA
+žA
+=A
+=AõÃAáHAÌÍA¢ÌÍAªžRAª£×A²£×Aº\AºzáAÂffAÊffAÊQìAÒ=qAÚ=qAâ(öAâ{Aê  Aò  Añë
+Aù×
+B ë
+BáHB×
+B×
+B
+ÌÍB
+ÂBžRBžRB®B£×B
+£×B B \B$
+B(
+B(záB,p€B0p€B4ffB4\)B8\)B<QìB<G®B@=qBD=qBH33BH(öBL(öBP
+žBP{BT
+=BX
+=BX  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?®?Â\?Â\@ £×@`  @  @®@¯\)@Ï
+=@Ï
+=@îžRA33A33A
+=A&áHA6žRA6žRAF\AVffAVffAf=qAv{A
+=AõÃAáHAÌÍAÌÍAžRA¢£×Aª£×Aª\A²záAºffAºffAÂQìAÊ=qAÊ=qAÒ(öAÚ{Aâ  Aâ  Aéë
+Añ×
+Añ×
+AùÂB ×
+B×
+BÌÍBÂB
+žRB
+žRB®B£×B£×BB
+\B 
+B 
+B$záB(p€B(p€B,ffB0\)B4\)B4QìB8G®B<=qB<=qB@33BD(öBH(öBH
+žBL{BP
+=BP
+=BT  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+ž?ÁG®?À  @   @_\)@\)@
+=@¯
+=@ÎžR@Îff@îffA
+=AáHAžRA&žRA6\A6ffAFffAV=qAV{Af{Auë
+AáHAÌÍAÌÍAžRA£×A£×A¢\AªzáAªffA²ffAºQìAº=qAÂ=qAÊ(öAÊ{AÒ  AÚ  Aáë
+Aá×
+Aé×
+AñÂAñ®Aù®B ÌÍBÂBžRBžRB
+®B
+£×B£×BB\B
+B
+
+B záB p€B$p€B(ffB(\)B,\)B0QìB4G®B4=qB8=qB<33B<(öB@(öBD
+žBH{BH
+=BL
+=BP  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?   ?À  ?ŸžR@
+žR@^{@
+=@žR@®ff@Îff@Î{@íÂAžRAžRA\A&ffA6ffA6=qAF{AV{AUë
+AeÂAuAÌÍAžRA£×A£×A\AzáA¢ffAªffAªQìA²=qAº=qAº(öAÂ{AÊ  AÊ  AÑë
+AÙ×
+Aá×
+AáÂAé®Añ®AñAù
+B žRBžRB®B£×B
+£×B
+B\B
+B
+BzáB
+p€B p€B ffB$\)B(\)B(QìB,G®B0=qB4=qB433B8(öB<(öB<
+žB@{BD
+=BH
+=BH  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >úáH?œp€?Œ(ö@
+{@]p€@ff@ff@®{@ÍÂ@Íp€@íp€A\AffAffA&=qA6{A6{AEë
+AUÂAUAeAup€A£×A£×A\AzáAffAffA¢QìAª=qAª=qA²(öAº{Aº  AÂ  AÉë
+AÉ×
+AÑ×
+AÙÂAá®Aá®AéAñ
+Añp€Aùp€B ®B£×B£×BB
+\B
+
+B
+BzáBp€Bp€B
+ffB \)B \)B$QìB(G®B(=qB,=qB033B4(öB4(öB8
+žB<{B<
+=B@
+=BD  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ð£×?Œ(ö?ºáH@
+ÌÍ@\ÌÍ@{@Â@­p€@Íp€@Í
+ž@ìÌÍAffA=qA{A&{A5ë
+A5ÂAEAUAUp€AeG®AuG®A\AzáAffAffAQìA=qA¢=qAª(öAª{A²  Aº  A¹ë
+AÁ×
+AÉ×
+AÉÂAÑ®AÙ®AáAá
+Aép€Añp€Añ\)AùG®B £×BB\B
+B
+
+B
+záBp€Bp€BffB\)B
+\)B QìB G®B$=qB(=qB(33B,(öB0(öB4
+žB4{B8
+=B<
+=B<  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ë
+?¹?¹@
+(ö@[
+@p€@p€@­
+ž@ÌÌÍ@ÌÌÍ@ìzáA{A{Aë
+A%ÂA5A5AEp€AUG®AUG®Ae
+žAtõÃAffAffAQìA=qA=qA(öA¢{Aª  Aª  A±ë
+A¹×
+A¹×
+AÁÂAÉ®AÉ®AÑAÙ
+Aáp€Aáp€Aé\)AñG®AñG®Aù33B \B
+B
+BzáB
+p€B
+p€BffB\)B\)BQìB
+G®B =qB =qB$33B((öB((öB,
+žB0{B4
+=B4
+=B8  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >æff?žQì?·
+>@áH@ZáH@
+ž@ÌÍ@¬ÌÍ@Ìzá@Ì(ö@ì(öAë
+AÂAA%A5p€A5G®AEG®AU
+žATõÃAdÌÍAtÌÍAQìA=qA=qA(öA{A  A¢  A©ë
+A©×
+A±×
+A¹ÂA¹®AÁ®AÉAÉ
+AÑp€AÙp€Aá\)AáG®AéG®Añ33Añ
+žAù
+=B 
+BzáBp€Bp€B
+ffB
+\)B\)BQìBG®B=qB
+=qB 33B (öB$(öB(
+žB({B,
+=B0
+=B4  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Ü(ö?µÂ?µÂ@=q@Y@ÌÍ@zá@¬(ö@Ì(ö@Ë×
+@ë
+AAAp€A%G®A5G®A5
+žADõÃATÌÍATÌÍAd£×AtzáA=qA(öA{A  A  Aë
+A¡×
+A©×
+A©ÂA±®A¹®A¹AÁ
+AÉp€AÉp€AÑ\)AÙG®AáG®Aá33Aé
+žAñ
+=Añ
+=AøõÃB p€Bp€BffB\)B
+\)B
+QìBG®B=qB=qB33B
+(öB (öB 
+žB${B(
+=B(
+=B,  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >×
+=?Žzá?³33@@XõÂ@(ö@(ö@«×
+@Ë
+@Ë33@ë33Ap€AG®AG®A%
+žA4õÃA4ÌÍADÌÍAT£×ATzáAdzáAtQìA{A  A  Aë
+A×
+A×
+A¡ÂA©®A©®A±A¹
+A¹p€AÁp€AÉ\)AÉG®AÑG®AÙ33Aá
+žAá
+=Aé
+=AðõÃAðáHAøáHB ffB\)B\)BQìB
+G®B
+=qB=qB33B(öB(öB
+
+žB {B 
+=B$
+=B(  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ÌÌÍ?³33?±ë
+@Qì@XQì@×
+@
+@«33@Ë33@ÊáH@ê\AG®A
+žAõÃA$ÌÍA4ÌÍA4£×ADzáATzáATQìAd(öAt  A  Aë
+A×
+A×
+AÂA®A¡®A©A©
+A±p€A¹p€A¹\)AÁG®AÉG®AÉ33AÑ
+žAÙ
+=Aá
+=AàõÃAèáHAðáHAðÌÍAøžRB \)BQìBG®B=qB
+=qB
+33B(öB(öB
+žB{B
+
+=B 
+=B   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Ç®?°£×?°£×@®@W
+>@33@33@ªáH@Ê\@Ê\@ê=qAõÃAÌÍAÌÍA$£×A4záA4záADQìAT(öAT  Ad  As×
+A×
+A×
+AÂA®A®AA¡
+A©p€A©p€A±\)A¹G®A¹G®AÁ33AÉ
+žAÉ
+=AÑ
+=AØõÃAàáHAàáHAèÌÍAðžRAðžRAø£×B G®B=qB=qB33B
+(öB
+(öB
+žB{B
+=B
+=B
+  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Â\?¯\)?®{@ff@Vff@áH@\@ª\@Ê=q@Éë
+@éAÌÍA£×AzáA$záA4QìA4(öAD  AT  AS×
+Ac®As®AÂA®A®AA
+Ap€A¡p€A©\)A©G®A±G®A¹33A¹
+žAÁ
+=AÉ
+=AÈõÃAÐáHAØáHAàÌÍAàžRAèžRAð£×Að\AøzáB =qB33B(öB(öB
+
+žB
+{B
+=B
+=B  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >žQì?¬ÌÍ?¬ÌÍ@Â@U
+ž@\@=q@©ë
+@É@É@éG®AzáAzáAQìA$(öA4  A4  AC×
+AS®AS®Ac
+As\)A®AA
+Ap€Ap€A\)A¡G®A©G®A©33A±
+žA¹
+=A¹
+=AÀõÃAÈáHAÈáHAÐÌÍAØžRAàžRAà£×Aè\AðzáAðzáAøffB (öB(öB
+žB{B
+
+=B
+
+=B  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >³33?«
+?ª=q@
+ž@Tzá@ë
+@@©@ÉG®@ÈõÃ@èõÃAQìA(öA  A$  A3×
+A3®AC®AS
+AS\)Ac\)As33A
+Ap€Ap€A\)AG®AG®A¡33A©
+žA©
+=A±
+=AžõÃAžáHAÀáHAÈÌÍAÈžRAÐžRAØ£×Aà\AàzáAèzáAðffAðQìAøQìB 
+žB{B
+=B
+=B
+  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >šõÃ?ª=q?šõÂ@×
+@S33@@G®@šõÃ@ÈõÃ@È£×@èQìA  A  A×
+A#®A3®A3
+AC\)AS\)AS33Ac
+=AráHAp€A\)AG®AG®A33A
+žA¡
+=A©
+=AšõÃA°áHAžáHAžÌÍAÀžRAÈžRAÈ£×AÐ\AØzáAàzáAàffAèQìAðQìAð=qAø(öB 
+=B
+=B  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >£×
+?§®?Šff@33@R\@õÃ@õÃ@š£×@ÈQì@È  @è  A×
+A®A®A#
+A3\)A3\)AC33AS
+=ARáHAbáHAržRAG®AG®A33A
+žA
+=A
+=A õÃAšáHAšáHA°ÌÍAžžRAžžRAÀ£×AÈ\AÈzáAÐzáAØffAàQìAàQìAè=qAð(öAð{Aø{B   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >?Šff?¥
+ž@ë
+@Që
+@£×@Qì@š  @È  @Ç®@ç\)A®A
+A\)A#\)A333A3
+=ABáHARáHARžRAb\Ar\A33A
+žA
+=A
+=AõÃAáHA áHAšÌÍAšžRA°žRAž£×Až\AÀzáAÈzáAÈffAÐQìAØQìAà=qAà(öAè{Að{Að  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >zá?£×
+?£×
+@G®@P£×@  @  @§®@Ç\)@Ç\)@ç
+=A\)A\)A33A#
+=A2áHA2áHABžRAR\AR\AbffAr=qA
+=A
+=AõÃAáHAáHAÌÍA žRAšžRAš£×A°\AžzáAžzáAÀffAÈQìAÈQìAÐ=qAØ(öAà{Aà{Aè  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >\)?¢\?¡G®@  @P  @®@\)@§\)@Ç
+=@ÆžR@æžRA33A
+=AáHA"áHA2žRA2\AB\ARffAR=qAb{Ar{AõÃAáHAáHAÌÍAžRAžRA £×Aš\AšzáA°záAžffAžQìAÀQìAÈ=qAÈ(öAÐ{AØ{Aà  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >
+
+ž?   ?   @\)@NžR@\)@
+=@ŠžR@ÆžR@Æff@æ{AáHAáHAžRA"\A2\A2ffAB=qAR{AR{Aaë
+AqÂAáHAÌÍAžRAžRA£×A\A záAšzáAšffA°QìAžQìAž=qAÀ(öAÈ{AÈ{AÐ  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >  ?žR?p€@žR@N{@žR@žR@Šff@Æ{@ÅÂ@åÂAžRA\A\A"ffA2=qA2{AB{AQë
+AQÂAaÂAqAžRAžRA£×A\AzáAzáA ffAšQìAšQìA°=qAž(öAž{AÀ{AÈ  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >k
+?p€?(ö@
+p€@Mp€@ff@{@¥Â@ÅÂ@Åp€@å
+žA\AffA=qA"{A2{A1ë
+AAÂAQÂAQAap€Aqp€A£×A\AzáAzáAffAQìA QìAš=qAš(öA°{Až{Až  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >aG®?áH?áH@
+ÌÍ@L(ö@
+Â@
+Â@¥p€@Å
+ž@Å
+ž@äÌÍA=qA{A{A!ë
+A1ÂA1ÂAAAQp€AQp€AaG®Aq
+žAzáAzáAffAQìAQìA=qA (öAš{Aš{A°  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >W
+=??Qì@
+
+@K
+@
+p€@
+
+ž@¥
+ž@ÄÌÍ@Äzá@ä(öA{Aë
+AÂA!ÂA1A1p€AAp€AQG®AQ
+žA`õÃApõÃAffAQìAQìA=qA(öA{A {Aš  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >B\?
+>?
+>@
+áH@J=q@
+
+ž@ÌÍ@€zá@Ä(ö@Ä(ö@ã×
+AÂAÂAA!p€A1p€A1G®AA
+žAPõÃAPõÃA`ÌÍAp£×AQìA=qA(öA{A{A  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >8Qì?Â?zá@
+=q@I@zá@(ö@€(ö@Ã×
+@Ã
+@ã
+AAp€Ap€A!G®A1
+žA0õÃA@õÃAPÌÍAP£×A`£×ApzáA(öA{A{A  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >#×
+?zá?33@õÃ@HQì@(ö@×
+@£
+@Ã
+@Ã33@âáHAp€AG®A
+žA õÃA0õÃA0ÌÍA@£×AP£×APzáA`QìAp(öA{A  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >?ë
+?£×@Qì@G®@
+@
+@£33@ÂáH@ÂáH@â\A
+žAõÃAõÃA ÌÍA0£×A0£×A@záAPQìAP(öA`(öAp  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >
+ž?£×?\)@
+=@G
+=@33@áH@¢áH@Â\@Â=q@áë
+A õÃAÌÍA£×A £×A0záA0QìA@(öAP(öAP  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =õÂ?{?{@ff@EÂ@áH@\@¢=q@Áë
+@Áë
+@áA £×A£×AzáA QìA0(öA0(öA@  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =áG®?ÌÍ?
+@Â@E
+ž@=q@ë
+@¡ë
+@Á@ÁG®@áG®A záAQìA(öA (öA0  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =žQì?
+?=q@zá@C×
+@ë
+@@¡G®@ÁG®@ÀõÃ@à£×A (öA(öA  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =£×
+?õÃ?®@×
+@C33@G®@G®@ õÃ@À£×@ÀQì@àQìA   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =uÂ?®?ff@\@B\@õÃ@£×@ Qì@ÀQì@À  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =LÌÍ?
+
+ž?
+
+ž@ë
+@AG®@Qì@Qì@   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =#×
+?×
+?\@ £×@@£×@  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  <£×
+?G®?G®@   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  <#×
+?  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ?!G®?Ð£×@(Qì@hQì@(ö@Ž(ö@Ô(ö@ô(öA
+{A{A*{A:{AJ{AZ{Aj{Az{A
+
+=A
+=A
+=A
+=A¥
+=A­
+=Aµ
+=Aœ
+=AÅ
+=AÍ
+=AÕ
+=AÝ
+=Aå
+=Aí
+=Aõ
+=Aý
+=B
+B
+B
+
+B
+B
+B
+B
+B
+
+B"
+B&
+B*
+B.
+B2
+B6
+B:
+B>
+BB
+BF
+BJ
+BN
+BR
+BV
+BZ
+B^
+Bb
+Bf
+Bj
+Bn
+Br
+Bv
+Bz
+B~
+?
+žR?Ï\)@'®@g®@×
+@³×
+@Ó×
+@ó×
+A	ë
+Aë
+A)ë
+A9ë
+AIë
+AYë
+Aië
+Ayë
+AõÃAõÃAõÃAõÃA€õÃA¬õÃAŽõÃAŒõÃAÄõÃAÌõÃAÔõÃAÜõÃAäõÃAìõÃAôõÃAüõÃBzáBzáB
+záBzáBzáBzáBzáB
+záB"záB&záB*záB.záB2záB6záB:záB>záBBzáBFzáBJzáBNzáBRzáBVzáBZzáB^záBbzáBfzáBjzáBnzáBrzáBvzáBzzáB~zá?
+(ö?Î{@'
+>@g
+>@
+@³
+@Ó
+@ó
+A	ÂAÂA)ÂA9ÂAIÂAYÂAiÂAyÂAáHAáHAáHAáHA€áHA¬áHAŽáHAŒáHAÄáHAÌáHAÔáHAÜáHAäáHAìáHAôáHAüáHBp€Bp€B
+p€Bp€Bp€Bp€Bp€B
+p€B"p€B&p€B*p€B.p€B2p€B6p€B:p€B>p€BBp€BFp€BJp€BNp€BRp€BVp€BZp€B^p€Bbp€Bfp€Bjp€Bnp€Brp€Bvp€Bzp€B~p€??ÌÌÍ@&ff@fff@33@³33@Ó33@ó33A	AA)A9AIAYAiAyAÌÍAÌÍAÌÍAÌÍA€ÌÍA¬ÌÍAŽÌÍAŒÌÍAÄÌÍAÌÌÍAÔÌÍAÜÌÍAäÌÍAìÌÍAôÌÍAüÌÍBffBffB
+ffBffBffBffBffB
+ffB"ffB&ffB*ffB.ffB2ffB6ffB:ffB>ffBBffBFffBJffBNffBRffBVffBZffB^ffBbffBfffBjffBnffBrffBvffBzffB~ff?
+=?Ë
+
+@%Â@eÂ@áH@²áH@ÒáH@òáHA	p€Ap€A)p€A9p€AIp€AYp€Aip€Ayp€AžRAžRAžRAžRA€žRA¬žRAŽžRAŒžRAÄžRAÌžRAÔžRAÜžRAäžRAìžRAôžRAüžRB\)B\)B
+\)B\)B\)B\)B\)B
+\)B"\)B&\)B*\)B.\)B2\)B6\)B:\)B>\)BB\)BF\)BJ\)BN\)BR\)BV\)BZ\)B^\)Bb\)Bf\)Bj\)Bn\)Br\)Bv\)Bz\)B~\)?zá?Ê=p@%
+ž@e
+ž@\@²\@Ò\@ò\A	G®AG®A)G®A9G®AIG®AYG®AiG®AyG®A£×A£×A£×A£×A€£×A¬£×AŽ£×AŒ£×AÄ£×AÌ£×AÔ£×AÜ£×Aä£×Aì£×Aô£×Aü£×BQìBQìB
+QìBQìBQìBQìBQìB
+QìB"QìB&QìB*QìB.QìB2QìB6QìB:QìB>QìBBQìBFQìBJQìBNQìBRQìBVQìBZQìB^QìBbQìBfQìBjQìBnQìBrQìBvQìBzQìB~Qì?ë
+?ÈõÂ@$zá@dzá@=q@²=q@Ò=q@ò=qA	
+žA
+žA)
+žA9
+žAI
+žAY
+žAi
+žAy
+žA\A\A\A\A€\A¬\AŽ\AŒ\AÄ\AÌ\AÔ\AÜ\Aä\Aì\Aô\Aü\BG®BG®B
+G®BG®BG®BG®BG®B
+G®B"G®B&G®B*G®B.G®B2G®B6G®B:G®B>G®BBG®BFG®BJG®BNG®BRG®BVG®BZG®B^G®BbG®BfG®BjG®BnG®BrG®BvG®BzG®B~G®?\)?Ç®@#×
+@c×
+@ë
+@±ë
+@Ñë
+@ñë
+AõÃAõÃA(õÃA8õÃAHõÃAXõÃAhõÃAxõÃAzáAzáAzáAzáA€záA¬záAŽzáAŒzáAÄzáAÌzáAÔzáAÜzáAäzáAìzáAôzáAüzáB=qB=qB
+=qB=qB=qB=qB=qB
+=qB"=qB&=qB*=qB.=qB2=qB6=qB:=qB>=qBB=qBF=qBJ=qBN=qBR=qBV=qBZ=qB^=qBb=qBf=qBj=qBn=qBr=qBv=qBz=qB~=q?
+ÌÍ?Æff@#33@c33@@±@Ñ@ñAÌÍAÌÍA(ÌÍA8ÌÍAHÌÍAXÌÍAhÌÍAxÌÍAffAffAffAffA€ffA¬ffAŽffAŒffAÄffAÌffAÔffAÜffAäffAìffAôffAüffB33B33B
+33B33B33B33B33B
+33B"33B&33B*33B.33B233B633B:33B>33BB33BF33BJ33BN33BR33BV33BZ33B^33Bb33Bf33Bj33Bn33Br33Bv33Bz33B~33?
+=q?Å
+ž@"\@b\@G®@±G®@ÑG®@ñG®A£×A£×A(£×A8£×AH£×AX£×Ah£×Ax£×AQìAQìAQìAQìA€QìA¬QìAŽQìAŒQìAÄQìAÌQìAÔQìAÜQìAäQìAìQìAôQìAüQìB(öB(öB
+(öB(öB(öB(öB(öB
+(öB"(öB&(öB*(öB.(öB2(öB6(öB:(öB>(öBB(öBF(öBJ(öBN(öBR(öBV(öBZ(öB^(öBb(öBf(öBj(öBn(öBr(öBv(öBz(öB~(ö?®?Ã×
+@!ë
+@aë
+@õÂ@°õÂ@ÐõÂ@ðõÂAzáAzáA(záA8záAHzáAXzáAhzáAxzáA=qA=qA=qA=qA€=qA¬=qAŽ=qAŒ=qAÄ=qAÌ=qAÔ=qAÜ=qAä=qAì=qAô=qAü=qB
+žB
+žB
+
+žB
+žB
+žB
+žB
+žB
+
+žB"
+žB&
+žB*
+žB.
+žB2
+žB6
+žB:
+žB>
+žBB
+žBF
+žBJ
+žBN
+žBR
+žBV
+žBZ
+žB^
+žBb
+žBf
+žBj
+žBn
+žBr
+žBv
+žBz
+žB~
+ž?
+ž?Â\@!G®@aG®@£×@°£×@Ð£×@ð£×AQìAQìA(QìA8QìAHQìAXQìAhQìAxQìA(öA(öA(öA(öA€(öA¬(öAŽ(öAŒ(öAÄ(öAÌ(öAÔ(öAÜ(öAä(öAì(öAô(öAü(öB{B{B
+{B{B{B{B{B
+{B"{B&{B*{B.{B2{B6{B:{B>{BB{BF{BJ{BN{BR{BV{BZ{B^{Bb{Bf{Bj{Bn{Br{Bv{Bz{B~{?\?ÁG®@ £×@`£×@Qì@°Qì@ÐQì@ðQìA(öA(öA((öA8(öAH(öAX(öAh(öAx(öA{A{A{A{A€{A¬{AŽ{AŒ{AÄ{AÌ{AÔ{AÜ{Aä{Aì{Aô{Aü{B
+=B
+=B
+
+=B
+=B
+=B
+=B
+=B
+
+=B"
+=B&
+=B*
+=B.
+=B2
+=B6
+=B:
+=B>
+=BB
+=BF
+=BJ
+=BN
+=BR
+=BV
+=BZ
+=B^
+=Bb
+=Bf
+=Bj
+=Bn
+=Br
+=Bv
+=Bz
+=B~
+=?   ?À  @   @`  @  @°  @Ð  @ð  A  A  A(  A8  AH  AX  Ah  Ax  A  A  A  A  A€  A¬  AŽ  AŒ  AÄ  AÌ  AÔ  AÜ  Aä  Aì  Aô  Aü  B  B  B
+  B  B  B  B  B
+  B"  B&  B*  B.  B2  B6  B:  B>  BB  BF  BJ  BN  BR  BV  BZ  B^  Bb  Bf  Bj  Bn  Br  Bv  Bz  B~  >úáH?ŸžR@\)@_\)@®@¯®@Ï®@ï®A×
+A×
+A'×
+A7×
+AG×
+AW×
+Ag×
+Aw×
+Aë
+Aë
+Aë
+Aë
+A£ë
+A«ë
+A³ë
+A»ë
+AÃë
+AËë
+AÓë
+AÛë
+Aãë
+Aëë
+Aóë
+Aûë
+BõÃBõÃB	õÃB
+õÃBõÃBõÃBõÃB
+õÃB!õÃB%õÃB)õÃB-õÃB1õÃB5õÃB9õÃB=õÃBAõÃBEõÃBIõÃBMõÃBQõÃBUõÃBYõÃB]õÃBaõÃBeõÃBiõÃBmõÃBqõÃBuõÃByõÃB}õÃ>õÂ?œp€@
+žR@^žR@\)@¯\)@Ï\)@ï\)A®A®A'®A7®AG®AW®Ag®Aw®A×
+A×
+A×
+A×
+A£×
+A«×
+A³×
+A»×
+AÃ×
+AË×
+AÓ×
+AÛ×
+Aã×
+Aë×
+Aó×
+Aû×
+Bë
+Bë
+B	ë
+B
+ë
+Bë
+Bë
+Bë
+B
+ë
+B!ë
+B%ë
+B)ë
+B-ë
+B1ë
+B5ë
+B9ë
+B=ë
+BAë
+BEë
+BIë
+BMë
+BQë
+BUë
+BYë
+B]ë
+Baë
+Beë
+Bië
+Bmë
+Bqë
+Buë
+Byë
+B}ë
+>ð£×?Œ(ö@
+{@^{@
+=@¯
+=@Ï
+=@ï
+=A
+A
+A'
+A7
+AG
+AW
+Ag
+Aw
+AÂAÂAÂAÂA£ÂA«ÂA³ÂA»ÂAÃÂAËÂAÓÂAÛÂAãÂAëÂAóÂAûÂBáHBáHB	áHB
+áHBáHBáHBáHB
+áHB!áHB%áHB)áHB-áHB1áHB5áHB9áHB=áHBAáHBEáHBIáHBMáHBQáHBUáHBYáHB]áHBaáHBeáHBiáHBmáHBqáHBuáHByáHB}áH>ë
+?ºáH@
+p€@]p€@žR@®žR@ÎžR@îžRA\)A\)A'\)A7\)AG\)AW\)Ag\)Aw\)A®A®A®A®A£®A«®A³®A»®AÃ®AË®AÓ®AÛ®Aã®Aë®Aó®Aû®B×
+B×
+B	×
+B
+×
+B×
+B×
+B×
+B
+×
+B!×
+B%×
+B)×
+B-×
+B1×
+B5×
+B9×
+B=×
+BA×
+BE×
+BI×
+BM×
+BQ×
+BU×
+BY×
+B]×
+Ba×
+Be×
+Bi×
+Bm×
+Bq×
+Bu×
+By×
+B}×
+>æff?¹@
+ÌÍ@\ÌÍ@ff@®ff@Îff@îffA33A33A'33A733AG33AW33Ag33Aw33AAAAA£A«A³A»AÃAËAÓAÛAãAëAóAûBÌÍBÌÍB	ÌÍB
+ÌÍBÌÍBÌÍBÌÍB
+ÌÍB!ÌÍB%ÌÍB)ÌÍB-ÌÍB1ÌÍB5ÌÍB9ÌÍB=ÌÍBAÌÍBEÌÍBIÌÍBMÌÍBQÌÍBUÌÍBYÌÍB]ÌÍBaÌÍBeÌÍBiÌÍBmÌÍBqÌÍBuÌÍByÌÍB}ÌÍ>áG®?žQì@
+(ö@\(ö@{@®{@Î{@î{A
+=A
+=A'
+=A7
+=AG
+=AW
+=Ag
+=Aw
+=A
+A
+A
+A
+A£
+A«
+A³
+A»
+AÃ
+AË
+AÓ
+AÛ
+Aã
+Aë
+Aó
+Aû
+BÂBÂB	ÂB
+ÂBÂBÂBÂB
+ÂB!ÂB%ÂB)ÂB-ÂB1ÂB5ÂB9ÂB=ÂBAÂBEÂBIÂBMÂBQÂBUÂBYÂB]ÂBaÂBeÂBiÂBmÂBqÂBuÂByÂB}Â>Ü(ö?·
+>@
+@[
+@Â@­Â@ÍÂ@íÂAáHAáHA&áHA6áHAFáHAVáHAfáHAváHAp€Ap€Ap€Ap€A£p€A«p€A³p€A»p€AÃp€AËp€AÓp€AÛp€Aãp€Aëp€Aóp€Aûp€BžRBžRB	žRB
+žRBžRBžRBžRB
+žRB!žRB%žRB)žRB-žRB1žRB5žRB9žRB=žRBAžRBEžRBIžRBMžRBQžRBUžRBYžRB]žRBažRBežRBižRBmžRBqžRBužRByžRB}žR>×
+=?µÂ@áH@ZáH@p€@­p€@Íp€@íp€AžRAžRA&žRA6žRAFžRAVžRAfžRAvžRA\)A\)A\)A\)A£\)A«\)A³\)A»\)AÃ\)AË\)AÓ\)AÛ\)Aã\)Aë\)Aó\)Aû\)B®B®B	®B
+®B®B®B®B
+®B!®B%®B)®B-®B1®B5®B9®B=®BA®BE®BI®BM®BQ®BU®BY®B]®Ba®Be®Bi®Bm®Bq®Bu®By®B}®>Ñë
+?Žzá@=q@Z=q@
+ž@­
+ž@Í
+ž@í
+žA\A\A&\A6\AF\AV\Af\Av\AG®AG®AG®AG®A£G®A«G®A³G®A»G®AÃG®AËG®AÓG®AÛG®AãG®AëG®AóG®AûG®B£×B£×B	£×B
+£×B£×B£×B£×B
+£×B!£×B%£×B)£×B-£×B1£×B5£×B9£×B=£×BA£×BE£×BI£×BM£×BQ£×BU£×BY£×B]£×Ba£×Be£×Bi£×Bm£×Bq£×Bu£×By£×B}£×>ÌÌÍ?³33@@Y@ÌÍ@¬ÌÍ@ÌÌÍ@ìÌÍAffAffA&ffA6ffAFffAVffAfffAvffA33A33A33A33A£33A«33A³33A»33AÃ33AË33AÓ33AÛ33Aã33Aë33Aó33Aû33BBB	B
+BBBB
+B!B%B)B-B1B5B9B=BABEBIBMBQBUBYB]BaBeBiBmBqBuByB}>Ç®?±ë
+@õÂ@XõÂ@zá@¬zá@Ìzá@ìzáA=qA=qA&=qA6=qAF=qAV=qAf=qAv=qA
+žA
+žA
+žA
+žA£
+žA«
+žA³
+žA»
+žAÃ
+žAË
+žAÓ
+žAÛ
+žAã
+žAë
+žAó
+žAû
+žB\B\B	\B
+\B\B\B\B
+\B!\B%\B)\B-\B1\B5\B9\B=\BA\BE\BI\BM\BQ\BU\BY\B]\Ba\Be\Bi\Bm\Bq\Bu\By\B}\>Â\?°£×@Qì@XQì@(ö@¬(ö@Ì(ö@ì(öA{A{A&{A6{AF{AV{Af{Av{A
+=A
+=A
+=A
+=A£
+=A«
+=A³
+=A»
+=AÃ
+=AË
+=AÓ
+=AÛ
+=Aã
+=Aë
+=Aó
+=Aû
+=B
+B
+B	
+B
+
+B
+B
+B
+B
+
+B!
+B%
+B)
+B-
+B1
+B5
+B9
+B=
+BA
+BE
+BI
+BM
+BQ
+BU
+BY
+B]
+Ba
+Be
+Bi
+Bm
+Bq
+Bu
+By
+B}
+>œp€?¯\)@®@W®@×
+@«×
+@Ë×
+@ë×
+Aë
+Aë
+A%ë
+A5ë
+AEë
+AUë
+Aeë
+Auë
+AõÃAõÃAõÃAõÃA¢õÃAªõÃA²õÃAºõÃAÂõÃAÊõÃAÒõÃAÚõÃAâõÃAêõÃAòõÃAúõÃBzáBzáB	záB
+záBzáBzáBzáB
+záB!záB%záB)záB-záB1záB5záB9záB=záBAzáBEzáBIzáBMzáBQzáBUzáBYzáB]záBazáBezáBizáBmzáBqzáBuzáByzáB}zá>žQì?®{@
+>@W
+>@
+@«
+@Ë
+@ë
+AÂAÂA%ÂA5ÂAEÂAUÂAeÂAuÂAáHAáHAáHAáHA¢áHAªáHA²áHAºáHAÂáHAÊáHAÒáHAÚáHAâáHAêáHAòáHAúáHBp€Bp€B	p€B
+p€Bp€Bp€Bp€B
+p€B!p€B%p€B)p€B-p€B1p€B5p€B9p€B=p€BAp€BEp€BIp€BMp€BQp€BUp€BYp€B]p€Bap€Bep€Bip€Bmp€Bqp€Bup€Byp€B}p€>³33?¬ÌÍ@ff@Vff@33@«33@Ë33@ë33AAA%A5AEAUAeAuAÌÍAÌÍAÌÍAÌÍA¢ÌÍAªÌÍA²ÌÍAºÌÍAÂÌÍAÊÌÍAÒÌÍAÚÌÍAâÌÍAêÌÍAòÌÍAúÌÍBffBffB	ffB
+ffBffBffBffB
+ffB!ffB%ffB)ffB-ffB1ffB5ffB9ffB=ffBAffBEffBIffBMffBQffBUffBYffB]ffBaffBeffBiffBmffBqffBuffByffB}ff>®{?«
+@Â@UÂ@áH@ªáH@ÊáH@êáHAp€Ap€A%p€A5p€AEp€AUp€Aep€Aup€AžRAžRAžRAžRA¢žRAªžRA²žRAºžRAÂžRAÊžRAÒžRAÚžRAâžRAêžRAòžRAúžRB\)B\)B	\)B
+\)B\)B\)B\)B
+\)B!\)B%\)B)\)B-\)B1\)B5\)B9\)B=\)BA\)BE\)BI\)BM\)BQ\)BU\)BY\)B]\)Ba\)Be\)Bi\)Bm\)Bq\)Bu\)By\)B}\)>šõÃ?ª=q@
+ž@U
+ž@\@ª\@Ê\@ê\AG®AG®A%G®A5G®AEG®AUG®AeG®AuG®A£×A£×A£×A£×A¢£×Aª£×A²£×Aº£×AÂ£×AÊ£×AÒ£×AÚ£×Aâ£×Aê£×Aò£×Aú£×BQìBQìB	QìB
+QìBQìBQìBQìB
+QìB!QìB%QìB)QìB-QìB1QìB5QìB9QìB=QìBAQìBEQìBIQìBMQìBQQìBUQìBYQìB]QìBaQìBeQìBiQìBmQìBqQìBuQìByQìB}Qì>£×
+?šõÂ@zá@Tzá@=q@ª=q@Ê=q@ê=qA
+žA
+žA%
+žA5
+žAE
+žAU
+žAe
+žAu
+žA\A\A\A\A¢\Aª\A²\Aº\AÂ\AÊ\AÒ\AÚ\Aâ\Aê\Aò\Aú\BG®BG®B	G®B
+G®BG®BG®BG®B
+G®B!G®B%G®B)G®B-G®B1G®B5G®B9G®B=G®BAG®BEG®BIG®BMG®BQG®BUG®BYG®B]G®BaG®BeG®BiG®BmG®BqG®BuG®ByG®B}G®>žR?§®@×
+@S×
+@ë
+@©ë
+@Éë
+@éë
+AõÃAõÃA$õÃA4õÃADõÃATõÃAdõÃAtõÃAzáAzáAzáAzáA¢záAªzáA²záAºzáAÂzáAÊzáAÒzáAÚzáAâzáAêzáAòzáAúzáB=qB=qB	=qB
+=qB=qB=qB=qB
+=qB!=qB%=qB)=qB-=qB1=qB5=qB9=qB==qBA=qBE=qBI=qBM=qBQ=qBU=qBY=qB]=qBa=qBe=qBi=qBm=qBq=qBu=qBy=qB}=q>?Šff@33@S33@@©@É@éAÌÍAÌÍA$ÌÍA4ÌÍADÌÍATÌÍAdÌÍAtÌÍAffAffAffAffA¢ffAªffA²ffAºffAÂffAÊffAÒffAÚffAâffAêffAòffAúffB33B33B	33B
+33B33B33B33B
+33B!33B%33B)33B-33B133B533B933B=33BA33BE33BI33BM33BQ33BU33BY33B]33Ba33Be33Bi33Bm33Bq33Bu33By33B}33>zá?¥
+ž@\@R\@G®@©G®@ÉG®@éG®A£×A£×A$£×A4£×AD£×AT£×Ad£×At£×AQìAQìAQìAQìA¢QìAªQìA²QìAºQìAÂQìAÊQìAÒQìAÚQìAâQìAêQìAòQìAúQìB(öB(öB	(öB
+(öB(öB(öB(öB
+(öB!(öB%(öB)(öB-(öB1(öB5(öB9(öB=(öBA(öBE(öBI(öBM(öBQ(öBU(öBY(öB](öBa(öBe(öBi(öBm(öBq(öBu(öBy(öB}(ö>\)?£×
+@ë
+@Që
+@õÃ@šõÃ@ÈõÃ@èõÃAzáAzáA$záA4záADzáATzáAdzáAtzáA=qA=qA=qA=qA¢=qAª=qA²=qAº=qAÂ=qAÊ=qAÒ=qAÚ=qAâ=qAê=qAò=qAú=qB
+žB
+žB	
+žB
+
+žB
+žB
+žB
+žB
+
+žB!
+žB%
+žB)
+žB-
+žB1
+žB5
+žB9
+žB=
+žBA
+žBE
+žBI
+žBM
+žBQ
+žBU
+žBY
+žB]
+žBa
+žBe
+žBi
+žBm
+žBq
+žBu
+žBy
+žB}
+ž>=q?¢\@G®@QG®@£×@š£×@È£×@è£×AQìAQìA$QìA4QìADQìATQìAdQìAtQìA(öA(öA(öA(öA¢(öAª(öA²(öAº(öAÂ(öAÊ(öAÒ(öAÚ(öAâ(öAê(öAò(öAú(öB{B{B	{B
+{B{B{B{B
+{B!{B%{B){B-{B1{B5{B9{B={BA{BE{BI{BM{BQ{BU{BY{B]{Ba{Be{Bi{Bm{Bq{Bu{By{B}{>
+
+ž?¡G®@£×@P£×@Qì@šQì@ÈQì@èQìA(öA(öA$(öA4(öAD(öAT(öAd(öAt(öA{A{A{A{A¢{Aª{A²{Aº{AÂ{AÊ{AÒ{AÚ{Aâ{Aê{Aò{Aú{B
+=B
+=B	
+=B
+=B
+=B
+=B
+=B
+
+=B!
+=B%
+=B)
+=B-
+=B1
+=B5
+=B9
+=B=
+=BA
+=BE
+=BI
+=BM
+=BQ
+=BU
+=BY
+=B]
+=Ba
+=Be
+=Bi
+=Bm
+=Bq
+=Bu
+=By
+=B}
+=>  ?   @  @P  @  @š  @È  @è  A  A  A$  A4  AD  AT  Ad  At  A  A  A  A  A¢  Aª  A²  Aº  AÂ  AÊ  AÒ  AÚ  Aâ  Aê  Aò  Aú  B  B  B	  B
+  B  B  B  B
+  B!  B%  B)  B-  B1  B5  B9  B=  BA  BE  BI  BM  BQ  BU  BY  B]  Ba  Be  Bi  Bm  Bq  Bu  By  B}  >uÂ?žR@\)@O\)@®@§®@Ç®@ç®A×
+A×
+A#×
+A3×
+AC×
+AS×
+Ac×
+As×
+Aë
+Aë
+Aë
+Aë
+A¡ë
+A©ë
+A±ë
+A¹ë
+AÁë
+AÉë
+AÑë
+AÙë
+Aáë
+Aéë
+Añë
+Aùë
+B õÃBõÃBõÃB
+õÃBõÃBõÃBõÃB
+õÃB õÃB$õÃB(õÃB,õÃB0õÃB4õÃB8õÃB<õÃB@õÃBDõÃBHõÃBLõÃBPõÃBTõÃBXõÃB\õÃB`õÃBdõÃBhõÃBlõÃBpõÃBtõÃBxõÃB|õÃ>k
+?p€@žR@NžR@\)@§\)@Ç\)@ç\)A®A®A#®A3®AC®AS®Ac®As®A×
+A×
+A×
+A×
+A¡×
+A©×
+A±×
+A¹×
+AÁ×
+AÉ×
+AÑ×
+AÙ×
+Aá×
+Aé×
+Añ×
+Aù×
+B ë
+Bë
+Bë
+B
+ë
+Bë
+Bë
+Bë
+B
+ë
+B ë
+B$ë
+B(ë
+B,ë
+B0ë
+B4ë
+B8ë
+B<ë
+B@ë
+BDë
+BHë
+BLë
+BPë
+BTë
+BXë
+B\ë
+B`ë
+Bdë
+Bhë
+Blë
+Bpë
+Btë
+Bxë
+B|ë
+>aG®?(ö@{@N{@
+=@§
+=@Ç
+=@ç
+=A
+A
+A#
+A3
+AC
+AS
+Ac
+As
+AÂAÂAÂAÂA¡ÂA©ÂA±ÂA¹ÂAÁÂAÉÂAÑÂAÙÂAáÂAéÂAñÂAùÂB áHBáHBáHB
+áHBáHBáHBáHB
+áHB áHB$áHB(áHB,áHB0áHB4áHB8áHB<áHB@áHBDáHBHáHBLáHBPáHBTáHBXáHB\áHB`áHBdáHBháHBláHBpáHBtáHBxáHB|áH>W
+=?áH@
+p€@Mp€@žR@ŠžR@ÆžR@æžRA\)A\)A#\)A3\)AC\)AS\)Ac\)As\)A®A®A®A®A¡®A©®A±®A¹®AÁ®AÉ®AÑ®AÙ®Aá®Aé®Añ®Aù®B ×
+B×
+B×
+B
+×
+B×
+B×
+B×
+B
+×
+B ×
+B$×
+B(×
+B,×
+B0×
+B4×
+B8×
+B<×
+B@×
+BD×
+BH×
+BL×
+BP×
+BT×
+BX×
+B\×
+B`×
+Bd×
+Bh×
+Bl×
+Bp×
+Bt×
+Bx×
+B|×
+>LÌÍ?@
+ÌÍ@LÌÍ@ff@Šff@Æff@æffA33A33A#33A333AC33AS33Ac33As33AAAAA¡A©A±A¹AÁAÉAÑAÙAáAéAñAùB ÌÍBÌÍBÌÍB
+ÌÍBÌÍBÌÍBÌÍB
+ÌÍB ÌÍB$ÌÍB(ÌÍB,ÌÍB0ÌÍB4ÌÍB8ÌÍB<ÌÍB@ÌÍBDÌÍBHÌÍBLÌÍBPÌÍBTÌÍBXÌÍB\ÌÍB`ÌÍBdÌÍBhÌÍBlÌÍBpÌÍBtÌÍBxÌÍB|ÌÍ>B\?Qì@
+(ö@L(ö@{@Š{@Æ{@æ{A
+=A
+=A#
+=A3
+=AC
+=AS
+=Ac
+=As
+=A
+A
+A
+A
+A¡
+A©
+A±
+A¹
+AÁ
+AÉ
+AÑ
+AÙ
+Aá
+Aé
+Añ
+Aù
+B ÂBÂBÂB
+ÂBÂBÂBÂB
+ÂB ÂB$ÂB(ÂB,ÂB0ÂB4ÂB8ÂB<ÂB@ÂBDÂBHÂBLÂBPÂBTÂBXÂB\ÂB`ÂBdÂBhÂBlÂBpÂBtÂBxÂB|Â>8Qì?
+>@
+
+@K
+@
+Â@¥Â@ÅÂ@åÂAáHAáHA"áHA2áHABáHARáHAbáHAráHAp€Ap€Ap€Ap€A¡p€A©p€A±p€A¹p€AÁp€AÉp€AÑp€AÙp€Aáp€Aép€Añp€Aùp€B žRBžRBžRB
+žRBžRBžRBžRB
+žRB žRB$žRB(žRB,žRB0žRB4žRB8žRB<žRB@žRBDžRBHžRBLžRBPžRBTžRBXžRB\žRB`žRBdžRBhžRBlžRBpžRBtžRBxžRB|žR>.{?Â@
+áH@JáH@
+p€@¥p€@Åp€@åp€AžRAžRA"žRA2žRABžRARžRAbžRAržRA\)A\)A\)A\)A¡\)A©\)A±\)A¹\)AÁ\)AÉ\)AÑ\)AÙ\)Aá\)Aé\)Añ\)Aù\)B ®B®B®B
+®B®B®B®B
+®B ®B$®B(®B,®B0®B4®B8®B<®B@®BD®BH®BL®BP®BT®BX®B\®B`®Bd®Bh®Bl®Bp®Bt®Bx®B|®>#×
+?zá@
+=q@J=q@
+
+ž@¥
+ž@Å
+ž@å
+žA\A\A"\A2\AB\AR\Ab\Ar\AG®AG®AG®AG®A¡G®A©G®A±G®A¹G®AÁG®AÉG®AÑG®AÙG®AáG®AéG®AñG®AùG®B £×B£×B£×B
+£×B£×B£×B£×B
+£×B £×B$£×B(£×B,£×B0£×B4£×B8£×B<£×B@£×BD£×BH£×BL£×BP£×BT£×BX£×B\£×B`£×Bd£×Bh£×Bl£×Bp£×Bt£×Bx£×B|£×>?33@	@I@ÌÍ@€ÌÍ@ÄÌÍ@äÌÍAffAffA"ffA2ffABffARffAbffArffA33A33A33A33A¡33A©33A±33A¹33AÁ33AÉ33AÑ33AÙ33Aá33Aé33Añ33Aù33B BBB
+BBBB
+B B$B(B,B0B4B8B<B@BDBHBLBPBTBXB\B`BdBhBlBpBtBxB|>\)?ë
+@õÃ@HõÃ@zá@€zá@Äzá@äzáA=qA=qA"=qA2=qAB=qAR=qAb=qAr=qA
+žA
+žA
+žA
+žA¡
+žA©
+žA±
+žA¹
+žAÁ
+žAÉ
+žAÑ
+žAÙ
+žAá
+žAé
+žAñ
+žAù
+žB \B\B\B
+\B\B\B\B
+\B \B$\B(\B,\B0\B4\B8\B<\B@\BD\BH\BL\BP\BT\BX\B\\B`\Bd\Bh\Bl\Bp\Bt\Bx\B|\>
+ž?£×@Qì@HQì@(ö@€(ö@Ä(ö@ä(öA{A{A"{A2{AB{AR{Ab{Ar{A
+=A
+=A
+=A
+=A¡
+=A©
+=A±
+=A¹
+=AÁ
+=AÉ
+=AÑ
+=AÙ
+=Aá
+=Aé
+=Añ
+=Aù
+=B 
+B
+B
+B
+
+B
+B
+B
+B
+
+B 
+B$
+B(
+B,
+B0
+B4
+B8
+B<
+B@
+BD
+BH
+BL
+BP
+BT
+BX
+B\
+B`
+Bd
+Bh
+Bl
+Bp
+Bt
+Bx
+B|
+=õÂ?\)@®@G®@×
+@£×
+@Ã×
+@ã×
+Aë
+Aë
+A!ë
+A1ë
+AAë
+AQë
+Aaë
+Aqë
+AõÃAõÃAõÃAõÃA õÃAšõÃA°õÃAžõÃAÀõÃAÈõÃAÐõÃAØõÃAàõÃAèõÃAðõÃAøõÃB záBzáBzáB
+záBzáBzáBzáB
+záB záB$záB(záB,záB0záB4záB8záB<záB@záBDzáBHzáBLzáBPzáBTzáBXzáB\záB`záBdzáBhzáBlzáBpzáBtzáBxzáB|zá=áG®?{@
+=@G
+=@
+@£
+@Ã
+@ã
+AÂAÂA!ÂA1ÂAAÂAQÂAaÂAqÂAáHAáHAáHAáHA áHAšáHA°áHAžáHAÀáHAÈáHAÐáHAØáHAàáHAèáHAðáHAøáHB p€Bp€Bp€B
+p€Bp€Bp€Bp€B
+p€B p€B$p€B(p€B,p€B0p€B4p€B8p€B<p€B@p€BDp€BHp€BLp€BPp€BTp€BXp€B\p€B`p€Bdp€Bhp€Blp€Bpp€Btp€Bxp€B|p€=ÌÌÍ?ÌÍ@ff@Fff@33@£33@Ã33@ã33AAA!A1AAAQAaAqAÌÍAÌÍAÌÍAÌÍA ÌÍAšÌÍA°ÌÍAžÌÍAÀÌÍAÈÌÍAÐÌÍAØÌÍAàÌÍAèÌÍAðÌÍAøÌÍB ffBffBffB
+ffBffBffBffB
+ffB ffB$ffB(ffB,ffB0ffB4ffB8ffB<ffB@ffBDffBHffBLffBPffBTffBXffB\ffB`ffBdffBhffBlffBpffBtffBxffB|ff=žQì?
+@Â@EÂ@áH@¢áH@ÂáH@âáHAp€Ap€A!p€A1p€AAp€AQp€Aap€Aqp€AžRAžRAžRAžRA žRAšžRA°žRAžžRAÀžRAÈžRAÐžRAØžRAàžRAèžRAðžRAøžRB \)B\)B\)B
+\)B\)B\)B\)B
+\)B \)B$\)B(\)B,\)B0\)B4\)B8\)B<\)B@\)BD\)BH\)BL\)BP\)BT\)BX\)B\\)B`\)Bd\)Bh\)Bl\)Bp\)Bt\)Bx\)B|\)=£×
+?=q@
+ž@E
+ž@\@¢\@Â\@â\AG®AG®A!G®A1G®AAG®AQG®AaG®AqG®A£×A£×A£×A£×A £×Aš£×A°£×Až£×AÀ£×AÈ£×AÐ£×AØ£×Aà£×Aè£×Að£×Aø£×B QìBQìBQìB
+QìBQìBQìBQìB
+QìB QìB$QìB(QìB,QìB0QìB4QìB8QìB<QìB@QìBDQìBHQìBLQìBPQìBTQìBXQìB\QìB`QìBdQìBhQìBlQìBpQìBtQìBxQìB|Qì=\)?õÃ@zá@Dzá@=q@¢=q@Â=q@â=qA
+žA
+žA!
+žA1
+žAA
+žAQ
+žAa
+žAq
+žA\A\A\A\A \Aš\A°\Až\AÀ\AÈ\AÐ\AØ\Aà\Aè\Að\Aø\B G®BG®BG®B
+G®BG®BG®BG®B
+G®B G®B$G®B(G®B,G®B0G®B4G®B8G®B<G®B@G®BDG®BHG®BLG®BPG®BTG®BXG®B\G®B`G®BdG®BhG®BlG®BpG®BtG®BxG®B|G®=uÂ?®@×
+@C×
+@ë
+@¡ë
+@Áë
+@áë
+A õÃAõÃA õÃA0õÃA@õÃAPõÃA`õÃApõÃAzáAzáAzáAzáA záAšzáA°záAžzáAÀzáAÈzáAÐzáAØzáAàzáAèzáAðzáAøzáB =qB=qB=qB
+=qB=qB=qB=qB
+=qB =qB$=qB(=qB,=qB0=qB4=qB8=qB<=qB@=qBD=qBH=qBL=qBP=qBT=qBX=qB\=qB`=qBd=qBh=qBl=qBp=qBt=qBx=qB|=q=LÌÍ?ff@33@C33@@¡@Á@áA ÌÍAÌÍA ÌÍA0ÌÍA@ÌÍAPÌÍA`ÌÍApÌÍAffAffAffAffA ffAšffA°ffAžffAÀffAÈffAÐffAØffAàffAèffAðffAøffB 33B33B33B
+33B33B33B33B
+33B 33B$33B(33B,33B033B433B833B<33B@33BD33BH33BL33BP33BT33BX33B\33B`33Bd33Bh33Bl33Bp33Bt33Bx33B|33=#×
+?
+
+ž@\@B\@G®@¡G®@ÁG®@áG®A £×A£×A £×A0£×A@£×AP£×A`£×Ap£×AQìAQìAQìAQìA QìAšQìA°QìAžQìAÀQìAÈQìAÐQìAØQìAàQìAèQìAðQìAøQìB (öB(öB(öB
+(öB(öB(öB(öB
+(öB (öB$(öB((öB,(öB0(öB4(öB8(öB<(öB@(öBD(öBH(öBL(öBP(öBT(öBX(öB\(öB`(öBd(öBh(öBl(öBp(öBt(öBx(öB|(ö<õÂ?×
+@ë
+@Aë
+@õÃ@ õÃ@ÀõÃ@àõÃA záAzáA záA0záA@záAPzáA`záApzáA=qA=qA=qA=qA =qAš=qA°=qAž=qAÀ=qAÈ=qAÐ=qAØ=qAà=qAè=qAð=qAø=qB 
+žB
+žB
+žB
+
+žB
+žB
+žB
+žB
+
+žB 
+žB$
+žB(
+žB,
+žB0
+žB4
+žB8
+žB<
+žB@
+žBD
+žBH
+žBL
+žBP
+žBT
+žBX
+žB\
+žB`
+žBd
+žBh
+žBl
+žBp
+žBt
+žBx
+žB|
+ž<£×
+?\@G®@AG®@£×@ £×@À£×@à£×A QìAQìA QìA0QìA@QìAPQìA`QìApQìA(öA(öA(öA(öA (öAš(öA°(öAž(öAÀ(öAÈ(öAÐ(öAØ(öAà(öAè(öAð(öAø(öB {B{B{B
+{B{B{B{B
+{B {B${B({B,{B0{B4{B8{B<{B@{BD{BH{BL{BP{BT{BX{B\{B`{Bd{Bh{Bl{Bp{Bt{Bx{B|{<#×
+?G®@ £×@@£×@Qì@ Qì@ÀQì@àQìA (öA(öA (öA0(öA@(öAP(öA`(öAp(öA{A{A{A{A {Aš{A°{Až{AÀ{AÈ{AÐ{AØ{Aà{Aè{Að{Aø{B 
+=B
+=B
+=B
+
+=B
+=B
+=B
+=B
+
+=B 
+=B$
+=B(
+=B,
+=B0
+=B4
+=B8
+=B<
+=B@
+=BD
+=BH
+=BL
+=BP
+=BT
+=BX
+=B\
+=B`
+=Bd
+=Bh
+=Bl
+=Bp
+=Bt
+=Bx
+=B|
+=    ?  @   @@  @  @   @À  @à  A   A  A   A0  A@  AP  A`  Ap  A  A  A  A  A   Aš  A°  Až  AÀ  AÈ  AÐ  AØ  Aà  Aè  Að  Aø  B   B  B  B
+  B  B  B  B
+  B   B$  B(  B,  B0  B4  B8  B<  B@  BD  BH  BL  BP  BT  BX  B\  B`  Bd  Bh  Bl  Bp  Bt  Bx  B|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+žR?Ð£×¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+(ö?Ï\)?Ï\)@(Qì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+=?ÌÌÍ?Î{@'®@g®@(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?zá?Ë
+
+?Ë
+
+@&ff@g
+>@×
+@×
+@Ž(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?ë
+?ÈõÂ?Ê=p@%Â@eÂ@33@
+@³×
+@Ó×
+@Ô(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+ÌÍ?Ç®?ÈõÂ@$zá@e
+ž@áH@áH@³33@Ó
+@Ó×
+@ó×
+A
+{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+=q?Å
+ž?Æff@#×
+@dzá@=q@\@²áH@ÒáH@Ó33@ó
+A	ë
+Aë
+A{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+ž?Ã×
+?Å
+ž@"\@c33@ë
+@=q@²=q@Ò\@ÒáH@òáHA	AÂAë
+A)ë
+A:{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?\?Â\?Â\@!ë
+@b\@G®@@±ë
+@Ò=q@Ò=q@ò\A	p€Ap€AA)ÂA9ë
+A9ë
+AJ{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?   ?À  ?ÁG®@!G®@aG®@õÂ@G®@±G®@Ñ@Ñë
+@ò=qA	
+žAG®Ap€A)p€A9A9ÂAIë
+AYë
+AZ{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >õÂ?ŸžR?À  @   @`£×@£×@£×@°õÂ@ÑG®@ÑG®@ñAõÃA
+žA
+žA)G®A9p€A9p€AIAYÂAYë
+Aië
+Az{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ð£×?Œ(ö?œp€@\)@`  @  @Qì@°£×@Ð£×@ÐõÂ@ñG®A£×AÌÍAõÃA)
+žA9
+žA9G®AIp€AYp€AYAiÂAyë
+AõÃA
+
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >æff?ºáH?Œ(ö@
+{@^žR@®@  @°  @ÐQì@Ð£×@ð£×AzáA£×A£×A(ÌÍA8õÃA9
+žAI
+žAYG®AYp€Aip€AyAáHAõÃAõÃA
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >áG®?¹?¹@
+p€@^{@
+=@\)@¯®@Ð  @Ð  @ðQìAQìAQìAzáA(£×A8£×A8ÌÍAHõÃAY
+žAY
+žAiG®Ayp€AžRAÌÍAáHAõÃAõÃA
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >×
+=?·
+>?žQì@
+ÌÍ@\ÌÍ@žR@
+=@¯
+=@Ï\)@Ï®@ð  A  A(öAQìA(QìA8záA8£×AH£×AXÌÍAXõÃAi
+žAy
+žA£×AžRAžRAÌÍAáHAõÃA€õÃA­
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Ñë
+?µÂ?µÂ@
+@\(ö@ff@ff@®žR@Ï
+=@Ï
+=@ï\)A×
+A  A  A((öA8QìA8QìAHzáAX£×AX£×AhÌÍAxõÃA\A\A£×AžRAžRAÌÍA€áHA¬õÃA¬õÃAµ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ÌÌÍ?³33?Žzá@áH@ZáH@Â@{@®ff@Îff@ÎžR@ï
+=A
+A®A×
+A(  A8  A8(öAHQìAXQìAXzáAh£×Ax£×AffAzáA\A\A£×AžRA€žRA¬ÌÍA¬áHAŽõÃAŒõÃAœ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Â\?±ë
+?³33@@Z=q@p€@p€@­Â@Î{@Îff@îffA\)A
+A
+A'®A7×
+A8  AH  AX(öAXQìAhQìAxzáAQìAQìAffAzáA\A\A€£×A¬žRA¬žRAŽÌÍAŒáHAŒõÃAÄõÃAÍ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >œp€?°£×?°£×@õÂ@Y@ÌÍ@
+ž@­p€@Íp€@ÍÂ@î{A33A33A\)A'
+A7
+A7®AG×
+AX  AX  Ah(öAxQìA(öA=qAQìAQìAffAzáA€\A¬\A¬£×AŽžRAŒžRAŒÌÍAÄáHAÌõÃAÌõÃAÕ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >³33?®{?¯\)@Qì@XQì@zá@ÌÍ@¬ÌÍ@Í
+ž@Íp€@íp€AáHA
+=A33A'33A7\)A7
+AG
+AW®AW×
+Ah  Ax  A{A(öA(öA=qAQìAQìA€ffA¬záA¬\AŽ\AŒ£×AŒžRAÄžRAÌÌÍAÌáHAÔõÃAÜõÃAå
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >®{?¬ÌÍ?¬ÌÍ@
+>@W®@(ö@(ö@¬zá@ÌÌÍ@ÌÌÍ@í
+žAžRAžRAáHA'
+=A733A733AG\)AW
+AW
+Ag®Aw×
+A  A  A{A(öA(öA=qA€QìA¬QìA¬ffAŽzáAŒ\AŒ\AÄ£×AÌžRAÌžRAÔÌÍAÜáHAäõÃAäõÃAí
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >šõÃ?ª=q?«
+@ff@Vff@
+@×
+@¬(ö@Ì(ö@Ìzá@ìÌÍAffA\AžRA&žRA6áHA7
+=AG33AW33AW\)Ag
+Aw
+A×
+Aë
+A  A  A{A(öA€(öA¬=qA¬QìAŽQìAŒffAŒzáAÄ\AÌ\AÌ£×AÔžRAÜžRAäÌÍAäáHAìõÃAôõÃAõ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >žR?šõÂ?ª=q@
+ž@UÂ@33@33@«
+@Ë×
+@Ì(ö@ì(öA=qAffAffA&\A6žRA6žRAFáHAW
+=AW33Ag33Aw\)AÂAÂA×
+Aë
+A  A  A€{A¬(öA¬(öAŽ=qAŒQìAŒQìAÄffAÌzáAÌ\AÔ\AÜ£×AäžRAäžRAìÌÍAôáHAôõÃAüõÃB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >?Šff?§®@zá@U
+ž@\@áH@«33@Ë33@Ë
+@ë×
+A{A{A=qA&ffA6ffA6\AFžRAVžRAVáHAg
+=Aw33AA®AÂAÂA×
+Aë
+A€  A¬  A¬{AŽ(öAŒ(öAŒ=qAÄQìAÌQìAÌffAÔzáAÜ\Aä\Aä£×AìžRAôžRAôÌÍAüáHBzáBzáB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >\)?¥
+ž?Šff@33@S×
+@=q@\@ª\@ÊáH@Ë33@ë33AÂAë
+A{A&{A6=qA6ffAFffAV\AVžRAfžRAváHA
+AAA®AÂAÂA£×
+A«ë
+A¬  AŽ  AŒ{AŒ(öAÄ(öAÌ=qAÌQìAÔQìAÜffAäzáAä\Aì\Aô£×AôžRAüžRBffBp€BzáB
+záB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >=q?£×
+?£×
+@\@S33@@ë
+@ª=q@Ê\@Ê\@êáHAAAÂA%ë
+A6{A6{AF=qAVffAVffAf\AvžRA\)Ap€A
+AAA®A£ÂA«ÂA«×
+A³ë
+AŒ  AŒ  AÄ{AÌ(öAÌ(öAÔ=qAÜQìAäQìAäffAìzáAô\Aô\Aü£×B\)B\)BffB
+p€BzáBzáB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >  ?¡G®?¢\@ë
+@Që
+@G®@@©@Éë
+@Ê=q@ê\AG®Ap€AA%A5ÂA5ë
+AF{AV{AV=qAfffAvffAG®A\)A\)Ap€A
+AA£A«®A«ÂA³ÂA»×
+A»ë
+AÄ  AÌ  AÌ{AÔ(öAÜ(öAä=qAäQìAìQìAôffAôzáAü\BG®BQìB\)B
+\)BffBp€BzáBzáB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >uÂ?   ?   @£×@QG®@õÃ@õÃ@©G®@É@É@éë
+A
+žAG®AG®A%p€A5A5AEÂAUë
+AV{Af{Av=qA33A33AG®A\)A\)Ap€A£
+A«A«A³®A»ÂA»ÂAÃ×
+AËë
+AÌ  AÔ  AÜ{Aä(öAä(öAì=qAôQìAôQìAüffB=qBG®BG®B
+QìB\)B\)BffBp€BzáBzáB
+
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >k
+?p€?žR@  @P  @Qì@£×@šõÃ@ÈõÃ@ÉG®@éAÌÍAõÃA
+žA%G®A5G®A5p€AEAUAUÂAeë
+Av{A
+=A
+žA33A33AG®A\)A£\)A«p€A«
+A³A»A»®AÃÂAËÂAË×
+AÓë
+AÜ  Aä  Aä{Aì(öAô(öAô=qAüQìB(öB33B=qB
+G®BG®BQìB\)B\)BffBp€B
+záB"záB"
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >W
+=?(ö?p€@žR@O\)@  @  @šQì@È£×@ÈõÃ@èõÃA£×AÌÍAÌÍA$õÃA5
+žA5G®AEG®AUp€AUAeAuÂAõÃA
+=A
+=A
+žA33A33A£G®A«\)A«\)A³p€A»
+A»AÃAË®AËÂAÓÂAÛ×
+Aãë
+Aä  Aì  Aô{Aô(öAü(öB
+žB(öB(öB
+33B=qBG®BG®BQìB\)B\)B
+ffB"p€B"záB&záB*
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >LÌÍ?áH?áH@{@NžR@\)@®@š  @È  @ÈQì@è£×AzáAzáA£×A$ÌÍA4ÌÍA4õÃAE
+žAUG®AUG®Aep€AuAÌÍAáHAõÃA
+=A
+=A
+žA£33A«33A«G®A³\)A»\)A»p€AÃ
+AËAËAÓ®AÛÂAãÂAã×
+Aëë
+Aô  Aô  Aü{B{B{B
+žB
+(öB(öB33B=qBG®BG®BQìB
+\)B"\)B"ffB&p€B*záB*záB.
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >8Qì?Qì?@
+p€@Mp€@
+=@\)@§\)@Ç®@È  @è  A(öAQìAzáA$záA4£×A4ÌÍADÌÍATõÃAU
+žAeG®AuG®AžRAÌÍAÌÍAáHAõÃA
+=A£
+=A«
+žA«33A³33A»G®A»\)AÃ\)AËp€AË
+AÓAÛAã®AãÂAëÂAó×
+Aóë
+Aü  B  B
+=B{B
+{B
+žB(öB(öB33B=qBG®B
+G®B"QìB"\)B&\)B*ffB*p€B.záB2záB6
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >.{?
+>?
+>@
+(ö@LÌÍ@žR@žR@§
+=@Ç\)@Ç\)@ç®A  A  A(öA$QìA4záA4záAD£×ATÌÍATÌÍAdõÃAu
+žA£×A£×AžRAÌÍAÌÍAáHA¢õÃA«
+=A«
+=A³
+žA»33A»33AÃG®AË\)AË\)AÓp€AÛ
+AãAãAë®AóÂAóÂAû×
+BõÃB  B  B
+
+=B{B{B
+žB(öB(öB33B
+=qB"G®B"G®B&QìB*\)B*\)B.ffB2p€B6záB6záB:
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >#×
+?zá?Â@
+
+@K
+@{@ff@ŠžR@ÆžR@Ç
+=@ç\)A®A×
+A  A$  A4(öA4QìADzáATzáAT£×AdÌÍAtÌÍAzáA\A£×A£×AžRAÌÍA¢ÌÍAªáHAªõÃA³
+=A»
+=A»
+žAÃ33AË33AËG®AÓ\)AÛ\)Aãp€Aã
+AëAóAó®AûÂBáHBë
+BõÃB
+  B  B
+=B{B{B
+žB(öB
+(öB"33B"=qB&G®B*G®B*QìB.\)B2\)B6ffB6p€B:záB>záB>
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >\)?33?zá@
+=q@JáH@
+Â@
+Â@Š{@Æff@ÆžR@æžRA
+A®A®A#×
+A4  A4  AD(öATQìATzáAdzáAt£×AffAffAzáA\A£×A£×A¢žRAªÌÍAªÌÍA²áHAºõÃA»
+=AÃ
+=AË
+žAË33AÓ33AÛG®Aã\)Aã\)Aëp€Aó
+AóAûB×
+BáHBáHB	ë
+B
+õÃB  B  B
+=B{B{B
+
+žB"(öB"(öB&33B*=qB*G®B.G®B2QìB6\)B6\)B:ffB>p€B>záBBzáBF
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >
+ž?£×?ë
+@	@J=q@
+
+ž@
+p€@¥Â@ÅÂ@Æ{@æffA\)A\)A
+A#®A3®A3×
+AD  AT  AT(öAdQìAtzáA=qAQìAffAffAzáA\A¢£×Aª£×AªžRA²ÌÍAºÌÍAºáHAÂõÃAË
+=AË
+=AÓ
+žAÛ33Aã33AãG®Aë\)Aó\)Aóp€Aû
+BÌÍBÌÍB×
+B	áHB
+áHB
+ë
+BõÃB  B  B
+=B
+{B"{B"
+žB&(öB*(öB*33B.=qB2G®B6G®B6QìB:\)B>\)B>ffBBp€BFzáBJzáBJ
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =áG®?\)?£×@Qì@HõÃ@ÌÍ@
+
+ž@¥
+ž@Åp€@ÅÂ@åÂA
+=A33A\)A#\)A3
+A3®AC®AS×
+AT  Ad  At(öA(öA=qA=qAQìAffAffA¢záAª\Aª£×A²£×AºžRAºÌÍAÂÌÍAÊáHAÊõÃAÓ
+=AÛ
+=Aã
+žAã33Aë33AóG®Aó\)Aû\)BžRBÂBÌÍB	ÌÍB
+×
+B
+áHBáHBë
+BõÃB  B
+  B"
+=B"{B&{B*
+žB*(öB.(öB233B6=qB6G®B:G®B>QìB>\)BB\)BFffBJp€BJzáBNzáBR
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =ÌÌÍ?{?{@®@HQì@(ö@zá@€ÌÍ@Å
+ž@Å
+ž@åp€AáHAáHA
+=A#33A3\)A3\)AC
+AS®AS®Ac×
+At  A  A{A(öA=qA=qAQìA¢ffAªffAªzáA²\Aº£×Aº£×AÂžRAÊÌÍAÊÌÍAÒáHAÚõÃAã
+=Aã
+=Aë
+žAó33Aó33AûG®B®B®BžRB	ÂB
+ÌÍB
+ÌÍB×
+BáHBáHBë
+B
+õÃB"  B"  B&
+=B*{B*{B.
+žB2(öB6(öB633B:=qB>G®B>G®BBQìBF\)BJ\)BJffBNp€BRzáBRzáBV
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =žQì?
+?ÌÍ@
+=@G
+=@×
+@(ö@€(ö@Äzá@ÄÌÍ@å
+žA\AžRAáHA"áHA3
+=A333AC\)AS\)AS
+Ac®As®Aë
+A  A  A{A(öA=qA¢=qAªQìAªffA²ffAºzáAº\AÂ£×AÊ£×AÊžRAÒÌÍAÚÌÍAâáHAâõÃAë
+=Aó
+=Aó
+žAû33BB£×B®B	®B
+žRB
+ÂBÌÍBÌÍB×
+BáHB
+áHB!ë
+B!õÃB&  B*  B*
+=B.{B2{B6
+žB6(öB:(öB>33B>=qBBG®BFG®BJQìBJ\)BN\)BRffBRp€BVzáBZzáBZ
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =\)?=q?
+@Â@Fff@
+@
+@£×
+@Ä(ö@Ä(ö@äzáAffA\A\A"žRA2áHA2áHAC
+=AS33AS\)Ac\)As
+A×
+A×
+Aë
+A  A  A{A¢(öAª=qAª=qA²QìAºffAºffAÂzáAÊ\AÊ£×AÒ£×AÚžRAâÌÍAâÌÍAêáHAòõÃAó
+=Aû
+=B\BBB	£×B
+®B
+®BžRBÂBÌÍBÌÍB
+×
+B!áHB!áHB%ë
+B)õÃB*  B.  B2
+=B6{B6{B:
+žB>(öB>(öBB33BF=qBJG®BJG®BNQìBR\)BR\)BVffBZp€BZzáB^záBb
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =uÂ?®?õÃ@
+ž@EÂ@áH@33@£
+@Ã
+@Ã×
+@ä(öA{A=qAffA"\A2\A2žRABáHARáHAS
+=Ac33As\)A®AÂA×
+A×
+Aë
+A  A¢  Aª{Aª(öA²=qAº=qAºQìAÂffAÊffAÊzáAÒ\AÚ£×Aâ£×AâžRAêÌÍAòÌÍAòáHAúõÃB
+B
+B\B	B
+B
+£×B®B®BžRBÂB
+ÌÍB!ÌÍB!×
+B%áHB)áHB)ë
+B-õÃB2  B6  B6
+=B:{B>{B>
+žBB(öBF(öBJ33BJ=qBNG®BRG®BRQìBV\)BZ\)BZffB^p€BbzáBfzáBf
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =#×
+?ff?®@×
+@Dzá@\@áH@¢áH@Ã33@Ã
+@ã
+Aë
+A{A{A"=qA2ffA2\AB\ARžRARáHAbáHAs
+=AA®A®AÂA×
+A×
+A¡ë
+Aª  Aª  A²{Aº(öAº=qAÂ=qAÊQìAÊffAÒffAÚzáAâ\Aâ£×Aê£×AòžRAòÌÍAúÌÍBp€BzáB
+B	
+B
+\B
+BB£×B®B®B
+žRB!ÂB!ÌÍB%ÌÍB)×
+B)áHB-áHB1ë
+B5õÃB6  B:  B>
+=B>{BB{BF
+žBJ(öBJ(öBN33BR=qBRG®BVG®BZQìBZ\)B^\)BbffBfp€BfzáBjzáBn
+¿  ¿  ¿  ¿  ¿  ¿  <õÂ?
+
+ž?
+
+ž@33@C×
+@ë
+@=q@¢\@ÂáH@ÂáH@ã33AÂAÂAë
+A"{A2{A2=qABffAR\AR\AbžRAráHAp€A
+AA®A®AÂA¡×
+A©×
+A©ë
+A²  Aº  Aº{AÂ(öAÊ=qAÊ=qAÒQìAÚffAâffAâzáAê\Aò£×Aò£×AúžRBffBffBp€B	záB
+
+B
+
+B\BBB£×B
+®B!®B!žRB%ÂB)ÌÍB)ÌÍB-×
+B1áHB5áHB5ë
+B9õÃB>  B>  BB
+=BF{BJ{BJ
+žBN(öBR(öBR33BV=qBZG®BZG®B^QìBb\)Bf\)BfffBjp€BnzáBnzáBr
+¿  ¿  ¿  ¿  <#×
+?\?×
+@\@B\@@ë
+@¡ë
+@Â=q@Â\@âáHAp€AAÂA!ÂA1ë
+A2{AB{AR=qARffAb\Ar\A\)Ap€Ap€A
+AA®A¡®A©ÂA©×
+A±×
+A¹ë
+Aº  AÂ  AÊ{AÊ(öAÒ=qAÚ=qAâQìAâffAêffAòzáAò\Aú£×BQìB\)BffB	ffB
+p€B
+záB
+B
+B\BB
+B!£×B!®B%®B)žRB)ÂB-ÌÍB1ÌÍB5×
+B5áHB9áHB=ë
+B=õÃBB  BF  BJ
+=BJ{BN{BR
+žBR(öBV(öBZ33BZ=qB^G®BbG®BfQìBf\)Bj\)BnffBnp€BrzáBvzáBz
+¿  ¿      ?G®?G®@G®@Aë
+@G®@G®@¡@Áë
+@Áë
+@â=qAG®Ap€Ap€A!A1ÂA1ÂAAë
+AR{AR{Ab=qArffAG®AG®A\)Ap€Ap€A
+A¡A©®A©®A±ÂA¹×
+A¹×
+AÁë
+AÊ  AÊ  AÒ{AÚ(öAâ=qAâ=qAêQìAòffAòffAúzáBG®BQìBQìB	\)B
+ffB
+ffBp€BzáB
+B
+B
+\B!B!B%£×B)®B)®B-žRB1ÂB5ÌÍB5ÌÍB9×
+B=áHB=áHBAë
+BEõÃBJ  BJ  BN
+=BR{BR{BV
+žBZ(öBZ(öB^33Bb=qBfG®BfG®BjQìBn\)Bn\)BrffBvp€BzzáBzzáB~
+¿  ¿  ?  @ £×@@£×@£×@õÃ@¡G®@ÁG®@Á@áë
+A õÃA
+žAG®A!p€A1p€A1AAÂAQÂAQë
+Ab{Ar{A
+žA33AG®AG®A\)Ap€A¡p€A©
+A©A±®A¹®A¹ÂAÁ×
+AÉ×
+AÉë
+AÒ  AÚ  Aâ{Aâ(öAê=qAò=qAòQìAúffB33B=qBG®B	QìB
+QìB
+\)BffBffBp€BzáB
+
+B!
+B!\B%B)B)£×B-®B1®B5žRB5ÂB9ÌÍB=ÌÍB=×
+BAáHBEáHBIë
+BIõÃBN  BR  BR
+=BV{BZ{BZ
+žB^(öBb(öBf33Bf=qBjG®BnG®BnQìBr\)Bv\)BzffBzp€B~zá¿  ¿  ¿  ¿  @@  @Qì@Qì@ £×@ÀõÃ@ÁG®@áG®A ÌÍAõÃAõÃA!
+žA1G®A1p€AAp€AQAQÂAaÂAqë
+A
+=A
+=A
+žA33AG®AG®A¡\)A©p€A©p€A±
+A¹A¹®AÁ®AÉÂAÉ×
+AÑ×
+AÙë
+Aâ  Aâ  Aê{Aò(öAò=qAú=qB(öB33B33B	=qB
+G®B
+QìBQìB\)BffBffB
+p€B!záB!
+B%
+B)\B)B-B1£×B5®B5®B9žRB=ÂB=ÌÍBAÌÍBE×
+BIáHBIáHBMë
+BQõÃBR  BV  BZ
+=BZ{B^{Bb
+žBf(öBf(öBj33Bn=qBnG®BrG®BvQìBz\)Bz\)B~ff¿  ¿  ¿  ¿  ¿  ¿  @  @ Qì@ÀQì@À£×@àõÃA £×A£×AÌÍA õÃA0õÃA1
+žAAG®AQp€AQp€AaAqÂAáHAõÃA
+=A
+=A
+žA33A¡G®A©G®A©\)A±p€A¹p€A¹
+AÁAÉ®AÉ®AÑÂAÙ×
+Aá×
+Aáë
+Aê  Aò  Aò{Aú(öB
+žB
+žB(öB	33B
+33B
+=qBG®BQìBQìB\)B
+ffB!ffB!p€B%záB)
+B)
+B-\B1B5B5£×B9®B=®B=žRBAÂBEÌÍBIÌÍBI×
+BMáHBQáHBQë
+BUõÃBZ  BZ  B^
+=Bb{Bf{Bf
+žBj(öBn(öBn33Br=qBvG®BzG®BzQìB~\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @À  @ÀQì@àQìA QìAzáA£×A £×A0ÌÍA0õÃA@õÃAQ
+žAQG®Aap€Aqp€AÌÍAáHAáHAõÃA
+=A
+=A¡
+žA©33A©G®A±G®A¹\)A¹p€AÁp€AÉ
+AÉAÑ®AÙ®AáÂAá×
+Aé×
+Añë
+Aò  Aú  B
+=B{B
+žB	
+žB
+(öB
+33B33B=qBG®BQìB
+QìB!\)B!ffB%ffB)p€B)záB-
+B1
+B5\B5B9B=£×B=®BA®BEžRBIÂBIÌÍBMÌÍBQ×
+BQáHBUáHBYë
+BYõÃB^  Bb  Bf
+=Bf{Bj{Bn
+žBn(öBr(öBv33Bz=qBzG®B~G®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @à  A (öA(öAQìA záA0£×A0£×A@ÌÍAPõÃAPõÃAa
+žAqG®AžRAžRAÌÍAáHAáHAõÃA¡
+=A©
+=A©
+žA±33A¹G®A¹G®AÁ\)AÉp€AÉp€AÑ
+AÙAá®Aá®AéÂAñ×
+Añ×
+Aùë
+B  B  B
+=B	{B
+
+žB
+
+žB(öB33B33B=qB
+G®B!QìB!QìB%\)B)ffB)ffB-p€B1záB5
+B5
+B9\B=B=BA£×BE®BI®BIžRBMÂBQÌÍBQÌÍBU×
+BYáHBYáHB]ë
+BaõÃBf  Bf  Bj
+=Bn{Bn{Br
+žBv(öBz(öBz33B~=q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A  A(öA (öA0QìA0záA@£×AP£×APÌÍA`õÃApõÃA\A£×AžRAžRAÌÍAáHA áHAšõÃA©
+=A±
+=A¹
+žA¹33AÁG®AÉG®AÉ\)AÑp€AÙp€Aá
+AáAé®Añ®AñÂAù×
+B ë
+BõÃB  B	  B
+=B
+{B
+žB
+žB(öB33B
+33B!=qB!G®B%QìB)QìB)\)B-ffB1ffB5p€B5záB9
+B=
+B=\BABEBI£×BI®BM®BQžRBQÂBUÌÍBYÌÍBY×
+B]áHBaáHBeë
+BeõÃBj  Bn  Bn
+=Br{Bv{Bz
+žBz(öB~(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A   A0(öA0(öA@QìAPzáAP£×A`£×ApÌÍAzáAzáA\A£×AžRAžRA ÌÍAšáHAšáHA°õÃA¹
+=A¹
+=AÁ
+žAÉ33AÉG®AÑG®AÙ\)Aáp€Aáp€Aé
+AñAñ®Aù®B áHBë
+Bë
+BõÃB
+  B
+  B
+=B{B
+žB
+žB
+(öB!33B!33B%=qB)G®B)QìB-QìB1\)B5ffB5ffB9p€B=záB=
+BA
+BE\BIBIBM£×BQ®BQ®BUžRBYÂBYÌÍB]ÌÍBa×
+BeáHBeáHBië
+BmõÃBn  Br  Bv
+=Bz{Bz{B~
+ž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A0  A@(öAP(öAPQìA`záAp£×AQìAffAzáAzáA\A£×A žRAšžRAšÌÍA°áHAžáHAžõÃAÁ
+=AÉ
+=AÉ
+žAÑ33AÙG®AáG®Aá\)Aép€Añp€Añ
+AùB ×
+B×
+BáHBë
+B
+ë
+B
+õÃB  B  B
+=B{B
+
+žB!
+žB!(öB%33B)33B)=qB-G®B1QìB5QìB5\)B9ffB=ffB=p€BAzáBE
+BI
+BI\BMBQBQ£×BU®BY®BYžRB]ÂBaÌÍBeÌÍBe×
+BiáHBmáHBmë
+BqõÃBv  Bz  Bz
+=B~{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AP  AP(öA`(öApQìA=qAQìAQìAffAzáAzáA \Aš£×AšžRA°žRAžÌÍAžáHAÀáHAÈõÃAÉ
+=AÑ
+=AÙ
+žAá33AáG®AéG®Añ\)Añp€Aùp€B ÂBÌÍB×
+B×
+B
+áHB
+ë
+Bë
+BõÃB  B  B
+
+=B!{B!
+žB%
+žB)(öB)33B-33B1=qB5G®B5QìB9QìB=\)B=ffBAffBEp€BIzáBI
+BM
+BQ\BQBUBY£×BY®B]®BažRBeÂBeÌÍBiÌÍBm×
+BmáHBqáHBuë
+ByõÃBz  B~  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A`  Ap(öA{A(öA=qAQìAQìAffA záAšzáAš\A°£×AžžRAžžRAÀÌÍAÈáHAÈáHAÐõÃAÙ
+=Aá
+=Aá
+žAé33AñG®AñG®Aù\)B žRBžRBÂBÌÍB
+×
+B
+×
+BáHBë
+Bë
+BõÃB
+  B!  B!
+=B%{B)
+žB)
+žB-(öB133B533B5=qB9G®B=QìB=QìBA\)BEffBIffBIp€BMzáBQ
+BQ
+BU\BYBYB]£×Ba®Be®BežRBiÂBmÌÍBmÌÍBq×
+BuáHByáHByë
+B}õÃ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A  A{A{A(öA=qAQìA QìAšffAšzáA°záAž\Až£×AÀžRAÈžRAÈÌÍAÐáHAØáHAàõÃAá
+=Aé
+=Añ
+žAñ33AùG®B £×B®BžRBžRB
+ÂB
+ÌÍB×
+B×
+BáHBë
+B
+ë
+B õÃB!  B%  B)
+=B){B-
+žB1
+žB5(öB533B933B==qB=G®BAQìBEQìBI\)BIffBMffBQp€BQzáBU
+BY
+BY\B]BaBe£×Be®Bi®BmžRBmÂBqÌÍBuÌÍBy×
+ByáHB}áH¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A  A{A{A(öA =qAšQìAšQìA°ffAžzáAžzáAÀ\AÈ£×AÈžRAÐžRAØÌÍAàáHAàáHAèõÃAñ
+=Añ
+=Aù
+žB B£×B£×B®B
+žRB
+žRBÂBÌÍB×
+B×
+B
+áHB ë
+B ë
+B$õÃB)  B)  B-
+=B1{B5
+žB5
+žB9(öB=33B=33BA=qBEG®BIQìBIQìBM\)BQffBQffBUp€BYzáBY
+B]
+Ba\BeBeBi£×Bm®Bm®BqžRBuÂByÌÍByÌÍB}×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A  A{A {Aš(öAš=qA°QìAžQìAžffAÀzáAÈzáAÈ\AÐ£×AØžRAàžRAàÌÍAèáHAðáHAðõÃAù
+=B 
+B\BB£×B
+£×B
+®BžRBžRBÂBÌÍB
+×
+B ×
+B áHB$ë
+B(ë
+B(õÃB-  B1  B5
+=B5{B9
+žB=
+žB=(öBA33BE33BI=qBIG®BMQìBQQìBQ\)BUffBYffBYp€B]záBa
+Be
+Be\BiBmBm£×Bq®Bu®ByžRByÂB}ÌÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A   Aš{Aš{A°(öAž=qAžQìAÀQìAÈffAÈzáAÐzáAØ\Aà£×AàžRAèžRAðÌÍAðáHAøáHB záB
+B
+B\B
+B
+£×B£×B®BžRBžRB
+ÂB ÌÍB ×
+B$×
+B(áHB(ë
+B,ë
+B0õÃB5  B5  B9
+=B={B=
+žBA
+žBE(öBI33BI33BM=qBQG®BQQìBUQìBY\)BYffB]ffBap€BezáBe
+Bi
+Bm\BmBqBu£×By®By®B}žR¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aš  A°{Až{Až(öAÀ=qAÈQìAÈQìAÐffAØzáAàzáAà\Aè£×AðžRAðžRAøÌÍB p€Bp€BzáB
+B
+
+B
+\BB£×B£×B®B
+žRB žRB ÂB$ÌÍB(×
+B(×
+B,áHB0ë
+B4ë
+B4õÃB9  B=  B=
+=BA{BE
+žBI
+žBI(öBM33BQ33BQ=qBUG®BYQìBYQìB]\)BaffBeffBep€BizáBm
+Bm
+Bq\BuByBy£×B}®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Až  Až{AÀ{AÈ(öAÈ=qAÐQìAØQìAàffAàzáAèzáAð\Að£×AøžRB \)BffBp€Bp€B
+záB
+
+B
+B\BB£×B
+£×B ®B žRB$žRB(ÂB(ÌÍB,×
+B0×
+B4áHB4ë
+B8ë
+B<õÃB=  BA  BE
+=BI{BI
+žBM
+žBQ(öBQ33BU33BY=qBYG®B]QìBaQìBe\)BeffBiffBmp€BmzáBq
+Bu
+By\ByB}¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÀ  AÈ{AÈ{AÐ(öAØ=qAàQìAàQìAèffAðzáAðzáAø\B QìB\)B\)BffB
+p€B
+p€BzáB
+B
+B\B
+B £×B £×B$®B(žRB(žRB,ÂB0ÌÍB4×
+B4×
+B8áHB<ë
+B<ë
+B@õÃBE  BI  BI
+=BM{BQ
+žBQ
+žBU(öBY33BY33B]=qBaG®BeQìBeQìBi\)BmffBmffBqp€BuzáBy
+By
+B}\¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÈ  AÐ{AØ{Aà(öAà=qAèQìAðQìAðffAøzáB =qBG®BQìB\)B
+\)B
+ffBp€Bp€BzáB
+B
+
+B \B B$£×B(£×B(®B,žRB0žRB4ÂB4ÌÍB8×
+B<×
+B<áHB@ë
+BDë
+BHõÃBI  BM  BQ
+=BQ{BU
+žBY
+žBY(öB]33Ba33Be=qBeG®BiQìBmQìBm\)BqffBuffByp€ByzáB}
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AØ  Aà{Aà{Aè(öAð=qAðQìAøQìB 33B=qB=qBG®B
+QìB
+\)B\)BffBp€Bp€B
+záB 
+B 
+B$\B(B(£×B,£×B0®B4žRB4žRB8ÂB<ÌÍB<×
+B@×
+BDáHBHë
+BHë
+BLõÃBQ  BQ  BU
+=BY{BY
+žB]
+žBa(öBe33Be33Bi=qBmG®BmQìBqQìBu\)ByffByffB}p€¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aà  Aè{Að{Að(öAø=qB (öB(öB33B=qB
+=qB
+G®BQìB\)B\)BffB
+p€B p€B záB$
+B(
+B(\B,B0£×B4£×B4®B8žRB<žRB<ÂB@ÌÍBD×
+BH×
+BHáHBLë
+BPë
+BPõÃBU  BY  BY
+=B]{Ba
+žBe
+žBe(öBi33Bm33Bm=qBqG®BuQìByQìBy\)B}ff¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Að  Að{Aø{B {B
+žB(öB(öB
+33B
+=qB=qBG®BQìB\)B
+\)B ffB p€B$p€B(záB(
+B,
+B0\B4B4£×B8£×B<®B<žRB@žRBDÂBHÌÍBH×
+BL×
+BPáHBPë
+BTë
+BXõÃBY  B]  Ba
+=Be{Be
+žBi
+žBm(öBm33Bq33Bu=qByG®ByQìB}Qì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aø  B 
+=B
+=B{B
+žB
+(öB
+(öB33B=qB=qBG®B
+QìB \)B \)B$ffB(p€B(p€B,záB0
+B4
+B4\B8B<£×B<£×B@®BDžRBHžRBHÂBLÌÍBP×
+BP×
+BTáHBXë
+BXë
+B\õÃBa  Be  Be
+=Bi{Bm
+žBm
+žBq(öBu33By33By=qB}G®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B  B
+=B
+=B
+{B
+
+žB(öB(öB33B=qB
+=qB G®B QìB$\)B(\)B(ffB,p€B0p€B4záB4
+B8
+B<\B<B@£×BD£×BH®BHžRBLžRBPÂBPÌÍBT×
+BX×
+BXáHB\ë
+B`ë
+BdõÃBe  Bi  Bm
+=Bm{Bq
+žBu
+žBy(öBy33B}33¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B  B
+
+=B
+
+=B{B
+žB(öB(öB
+33B =qB =qB$G®B(QìB(\)B,\)B0ffB4p€B4p€B8záB<
+B<
+B@\BDBH£×BH£×BL®BPžRBPžRBTÂBXÌÍBX×
+B\×
+B`áHBdë
+Bdë
+BhõÃBm  Bm  Bq
+=Bu{By
+žBy
+žB}(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+  B
+=B
+=B{B
+žB
+(öB (öB 33B$=qB(=qB(G®B,QìB0\)B4\)B4ffB8p€B<p€B<záB@
+BD
+BH\BHBL£×BP£×BP®BTžRBXžRBXÂB\ÌÍB`×
+Bd×
+BdáHBhë
+Blë
+BlõÃBq  Bu  By
+=By{B}
+ž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B  B
+=B
+=B
+{B 
+žB (öB$(öB(33B(=qB,=qB0G®B4QìB4\)B8\)B<ffB<p€B@p€BDzáBH
+BH
+BL\BPBP£×BT£×BX®BXžRB\žRB`ÂBdÌÍBd×
+Bh×
+BláHBlë
+Bpë
+BtõÃBy  By  B}
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B  B
+
+=B 
+=B {B$
+žB((öB((öB,33B0=qB4=qB4G®B8QìB<\)B<\)B@ffBDp€BHp€BHzáBL
+BP
+BP\BTBX£×BX£×B\®B`žRBdžRBdÂBhÌÍBl×
+Bl×
+BpáHBtë
+Bxë
+BxõÃB}  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B   B 
+=B$
+=B({B(
+žB,(öB0(öB433B4=qB8=qB<G®B<QìB@\)BD\)BHffBHp€BLp€BPzáBP
+BT
+BX\BXB\£×B`£×Bd®BdžRBhžRBlÂBlÌÍBp×
+Bt×
+BxáHBxë
+B|ë
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B$  B(
+=B(
+=B,{B0
+žB4(öB4(öB833B<=qB<=qB@G®BDQìBH\)BH\)BLffBPp€BPp€BTzáBX
+BX
+B\\B`Bd£×Bd£×Bh®BlžRBlžRBpÂBtÌÍBx×
+Bx×
+B|áH¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B(  B,
+=B0
+=B4{B4
+žB8(öB<(öB<33B@=qBD=qBHG®BHQìBL\)BP\)BPffBTp€BXp€BXzáB\
+B`
+Bd\BdBh£×Bl£×Bl®BpžRBtžRBxÂBxÌÍB|×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B0  B4
+=B4
+=B8{B<
+žB<(öB@(öBD33BH=qBH=qBLG®BPQìBP\)BT\)BXffBXp€B\p€B`záBd
+Bd
+Bh\BlBl£×Bp£×Bt®BxžRBxžRB|Â¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B4  B8
+=B<
+=B<{B@
+žBD(öBH(öBH33BL=qBP=qBPG®BTQìBX\)BX\)B\ffB`p€Bdp€BdzáBh
+Bl
+Bl\BpBt£×Bx£×Bx®B|žR¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B<  B<
+=B@
+=BD{BH
+žBH(öBL(öBP33BP=qBT=qBXG®BXQìB\\)B`\)BdffBdp€Bhp€BlzáBl
+Bp
+Bt\BxBx£×B|£×¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B@  BD
+=BH
+=BH{BL
+žBP(öBP(öBT33BX=qBX=qB\G®B`QìBd\)Bd\)BhffBlp€Blp€BpzáBt
+Bx
+Bx\B|¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BH  BH
+=BL
+=BP{BP
+žBT(öBX(öBX33B\=qB`=qBdG®BdQìBh\)Bl\)BlffBpp€Btp€BxzáBx
+B|
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BL  BP
+=BP
+=BT{BX
+žBX(öB\(öB`33Bd=qBd=qBhG®BlQìBl\)Bp\)BtffBxp€Bxp€B|zá¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BP  BT
+=BX
+=BX{B\
+žB`(öBd(öBd33Bh=qBl=qBlG®BpQìBt\)Bx\)BxffB|p€¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BX  BX
+=B\
+=B`{Bd
+žBd(öBh(öBl33Bl=qBp=qBtG®BxQìBx\)B|\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B\  B`
+=Bd
+=Bd{Bh
+žBl(öBl(öBp33Bt=qBx=qBxG®B|Qì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bd  Bd
+=Bh
+=Bl{Bl
+žBp(öBt(öBx33Bx=qB|=q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bh  Bl
+=Bl
+=Bp{Bt
+žBx(öBx(öB|33¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bl  Bp
+=Bt
+=Bx{Bx
+žB|(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bt  Bx
+=Bx
+=B|{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bx  B|
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 <#×
+<£×
+<õÂ=#×
+=LÌÍ=uÂ=\)=£×
+=žQì=ÌÌÍ=áG®=õÂ>
+ž>\)>>#×
+>.{>8Qì>B\>LÌÍ>W
+=>aG®>k
+>uÂ>  >
+
+ž>=q>\)>zá>>žR>£×
+>šõÃ>®{>³33>žQì>œp€>Â\>Ç®>ÌÌÍ>Ñë
+>×
+=>Ü(ö>áG®>æff>ë
+>ð£×>õÂ>úáH?   ?\?
+ž?®?
+=q?
+ÌÍ?\)?ë
+?zá?
+=??
+(ö?
+žR?!G®?  ?G®?\?×
+?
+
+ž?ff?®?õÃ?=q?
+?ÌÍ?{?\)?£×?ë
+?33?zá?Â?
+>?Qì??áH?(ö?p€?žR?   ?¡G®?¢\?£×
+?¥
+ž?Šff?§®?šõÂ?ª=q?«
+?¬ÌÍ?®{?¯\)?°£×?±ë
+?³33?Žzá?µÂ?·
+>?žQì?¹?ºáH?Œ(ö?œp€?ŸžR?À  ?ÁG®?Â\?Ã×
+?Å
+ž?Æff?Ç®?ÈõÂ?Ê=p?Ë
+
+?ÌÌÍ?Î{?Ï\)?Ð£×@   @ £×@G®@ë
+@\@33@×
+@zá@
+ž@Â@ff@
+=@®@Qì@õÃ@	@
+=q@
+áH@
+
+@
+(ö@
+ÌÍ@
+p€@{@žR@\)@  @£×@G®@ë
+@\@33@×
+@zá@
+ž@Â@ff@
+>@®@Qì@õÂ@@=q@áH@
+@
+(ö@
+ÌÍ@
+p€@
+{@
+žR@\)@   @ £×@!G®@!ë
+@"\@#33@#×
+@$zá@%
+ž@%Â@&ff@'
+>@'®@(Qì@@  @@£×@AG®@Aë
+@B\@C33@C×
+@Dzá@E
+ž@EÂ@Fff@G
+=@G®@HQì@HõÃ@I@J=q@JáH@K
+@L(ö@LÌÍ@Mp€@N{@NžR@O\)@P  @P£×@QG®@Që
+@R\@S33@S×
+@Tzá@U
+ž@UÂ@Vff@W
+>@W®@XQì@XõÂ@Y@Z=q@ZáH@[
+@\(ö@\ÌÍ@]p€@^{@^žR@_\)@`  @`£×@aG®@aë
+@b\@c33@c×
+@dzá@e
+ž@eÂ@fff@g
+>@g®@hQì@  @Qì@£×@õÃ@G®@@ë
+@=q@\@áH@33@
+@×
+@(ö@zá@ÌÍ@
+
+ž@
+p€@
+Â@{@ff@žR@
+=@\)@®@  @Qì@£×@õÃ@G®@@ë
+@=q@\@áH@33@
+@×
+@(ö@zá@ÌÍ@
+ž@p€@Â@{@ff@žR@
+=@\)@®@  @Qì@£×@õÂ@G®@@ë
+@=q@\@áH@33@
+@×
+@(ö@   @ Qì@ £×@ õÃ@¡G®@¡@¡ë
+@¢=q@¢\@¢áH@£33@£
+@£×
+@€(ö@€zá@€ÌÍ@¥
+ž@¥p€@¥Â@Š{@Šff@ŠžR@§
+=@§\)@§®@š  @šQì@š£×@šõÃ@©G®@©@©ë
+@ª=q@ª\@ªáH@«33@«
+@«×
+@¬(ö@¬zá@¬ÌÍ@­
+ž@­p€@­Â@®{@®ff@®žR@¯
+=@¯\)@¯®@°  @°Qì@°£×@°õÂ@±G®@±@±ë
+@²=q@²\@²áH@³33@³
+@³×
+@Ž(ö@À  @ÀQì@À£×@ÀõÃ@ÁG®@Á@Áë
+@Â=q@Â\@ÂáH@Ã33@Ã
+@Ã×
+@Ä(ö@Äzá@ÄÌÍ@Å
+ž@Åp€@ÅÂ@Æ{@Æff@ÆžR@Ç
+=@Ç\)@Ç®@È  @ÈQì@È£×@ÈõÃ@ÉG®@É@Éë
+@Ê=q@Ê\@ÊáH@Ë33@Ë
+@Ë×
+@Ì(ö@Ìzá@ÌÌÍ@Í
+ž@Íp€@ÍÂ@Î{@Îff@ÎžR@Ï
+=@Ï\)@Ï®@Ð  @ÐQì@Ð£×@ÐõÂ@ÑG®@Ñ@Ñë
+@Ò=q@Ò\@ÒáH@Ó33@Ó
+@Ó×
+@Ô(ö@à  @àQì@à£×@àõÃ@áG®@á@áë
+@â=q@â\@âáH@ã33@ã
+@ã×
+@ä(ö@äzá@äÌÍ@å
+ž@åp€@åÂ@æ{@æff@æžR@ç
+=@ç\)@ç®@è  @èQì@è£×@èõÃ@éG®@é@éë
+@ê=q@ê\@êáH@ë33@ë
+@ë×
+@ì(ö@ìzá@ìÌÍ@í
+ž@íp€@íÂ@î{@îff@îžR@ï
+=@ï\)@ï®@ð  @ðQì@ð£×@ðõÂ@ñG®@ñ@ñë
+@ò=q@ò\@òáH@ó33@ó
+@ó×
+@ô(öA   A (öA QìA záA £×A ÌÍA õÃA
+žAG®Ap€AAÂAë
+A{A=qAffA\AžRAáHA
+=A33A\)A
+A®A×
+A  A(öAQìAzáA£×AÌÍAõÃA
+žAG®Ap€AAÂAë
+A{A=qAffA\AžRAáHA
+=A33A\)A
+A®A×
+A  A(öAQìAzáA£×AÌÍAõÃA	
+žA	G®A	p€A	A	ÂA	ë
+A
+{A  A(öAQìAzáA£×AÌÍAõÃA
+žAG®Ap€AAÂAë
+A{A=qAffA\AžRAáHA
+=A33A\)A
+A®A×
+A  A(öAQìAzáA£×AÌÍAõÃA
+žAG®Ap€AAÂAë
+A{A=qAffA\AžRAáHA
+=A33A\)A
+A®A×
+A  A(öAQìAzáA£×AÌÍAõÃA
+žAG®Ap€AAÂAë
+A{A   A (öA QìA záA £×A ÌÍA õÃA!
+žA!G®A!p€A!A!ÂA!ë
+A"{A"=qA"ffA"\A"žRA"áHA#
+=A#33A#\)A#
+A#®A#×
+A$  A$(öA$QìA$záA$£×A$ÌÍA$õÃA%
+žA%G®A%p€A%A%ÂA%ë
+A&{A&=qA&ffA&\A&žRA&áHA'
+=A'33A'\)A'
+A'®A'×
+A(  A((öA(QìA(záA(£×A(ÌÍA(õÃA)
+žA)G®A)p€A)A)ÂA)ë
+A*{A0  A0(öA0QìA0záA0£×A0ÌÍA0õÃA1
+žA1G®A1p€A1A1ÂA1ë
+A2{A2=qA2ffA2\A2žRA2áHA3
+=A333A3\)A3
+A3®A3×
+A4  A4(öA4QìA4záA4£×A4ÌÍA4õÃA5
+žA5G®A5p€A5A5ÂA5ë
+A6{A6=qA6ffA6\A6žRA6áHA7
+=A733A7\)A7
+A7®A7×
+A8  A8(öA8QìA8záA8£×A8ÌÍA8õÃA9
+žA9G®A9p€A9A9ÂA9ë
+A:{A@  A@(öA@QìA@záA@£×A@ÌÍA@õÃAA
+žAAG®AAp€AAAAÂAAë
+AB{AB=qABffAB\ABžRABáHAC
+=AC33AC\)AC
+AC®AC×
+AD  AD(öADQìADzáAD£×ADÌÍADõÃAE
+žAEG®AEp€AEAEÂAEë
+AF{AF=qAFffAF\AFžRAFáHAG
+=AG33AG\)AG
+AG®AG×
+AH  AH(öAHQìAHzáAH£×AHÌÍAHõÃAI
+žAIG®AIp€AIAIÂAIë
+AJ{AP  AP(öAPQìAPzáAP£×APÌÍAPõÃAQ
+žAQG®AQp€AQAQÂAQë
+AR{AR=qARffAR\ARžRARáHAS
+=AS33AS\)AS
+AS®AS×
+AT  AT(öATQìATzáAT£×ATÌÍATõÃAU
+žAUG®AUp€AUAUÂAUë
+AV{AV=qAVffAV\AVžRAVáHAW
+=AW33AW\)AW
+AW®AW×
+AX  AX(öAXQìAXzáAX£×AXÌÍAXõÃAY
+žAYG®AYp€AYAYÂAYë
+AZ{A`  A`(öA`QìA`záA`£×A`ÌÍA`õÃAa
+žAaG®Aap€AaAaÂAaë
+Ab{Ab=qAbffAb\AbžRAbáHAc
+=Ac33Ac\)Ac
+Ac®Ac×
+Ad  Ad(öAdQìAdzáAd£×AdÌÍAdõÃAe
+žAeG®Aep€AeAeÂAeë
+Af{Af=qAfffAf\AfžRAfáHAg
+=Ag33Ag\)Ag
+Ag®Ag×
+Ah  Ah(öAhQìAhzáAh£×AhÌÍAhõÃAi
+žAiG®Aip€AiAiÂAië
+Aj{Ap  Ap(öApQìApzáAp£×ApÌÍApõÃAq
+žAqG®Aqp€AqAqÂAqë
+Ar{Ar=qArffAr\AržRAráHAs
+=As33As\)As
+As®As×
+At  At(öAtQìAtzáAt£×AtÌÍAtõÃAu
+žAuG®Aup€AuAuÂAuë
+Av{Av=qAvffAv\AvžRAváHAw
+=Aw33Aw\)Aw
+Aw®Aw×
+Ax  Ax(öAxQìAxzáAx£×AxÌÍAxõÃAy
+žAyG®Ayp€AyAyÂAyë
+Az{A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+
+=A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A   A {A (öA =qA QìA ffA záA \A £×A žRA ÌÍA áHA õÃA¡
+=A¡
+žA¡33A¡G®A¡\)A¡p€A¡
+A¡A¡®A¡ÂA¡×
+A¡ë
+A¢  A¢{A¢(öA¢=qA¢QìA¢ffA¢záA¢\A¢£×A¢žRA¢ÌÍA¢áHA¢õÃA£
+=A£
+žA£33A£G®A£\)A£p€A£
+A£A£®A£ÂA£×
+A£ë
+A€  A€{A€(öA€=qA€QìA€ffA€záA€\A€£×A€žRA€ÌÍA€áHA€õÃA¥
+=Aš  Aš{Aš(öAš=qAšQìAšffAšzáAš\Aš£×AšžRAšÌÍAšáHAšõÃA©
+=A©
+žA©33A©G®A©\)A©p€A©
+A©A©®A©ÂA©×
+A©ë
+Aª  Aª{Aª(öAª=qAªQìAªffAªzáAª\Aª£×AªžRAªÌÍAªáHAªõÃA«
+=A«
+žA«33A«G®A«\)A«p€A«
+A«A«®A«ÂA«×
+A«ë
+A¬  A¬{A¬(öA¬=qA¬QìA¬ffA¬záA¬\A¬£×A¬žRA¬ÌÍA¬áHA¬õÃA­
+=A°  A°{A°(öA°=qA°QìA°ffA°záA°\A°£×A°žRA°ÌÍA°áHA°õÃA±
+=A±
+žA±33A±G®A±\)A±p€A±
+A±A±®A±ÂA±×
+A±ë
+A²  A²{A²(öA²=qA²QìA²ffA²záA²\A²£×A²žRA²ÌÍA²áHA²õÃA³
+=A³
+žA³33A³G®A³\)A³p€A³
+A³A³®A³ÂA³×
+A³ë
+AŽ  AŽ{AŽ(öAŽ=qAŽQìAŽffAŽzáAŽ\AŽ£×AŽžRAŽÌÍAŽáHAŽõÃAµ
+=Až  Až{Až(öAž=qAžQìAžffAžzáAž\Až£×AžžRAžÌÍAžáHAžõÃA¹
+=A¹
+žA¹33A¹G®A¹\)A¹p€A¹
+A¹A¹®A¹ÂA¹×
+A¹ë
+Aº  Aº{Aº(öAº=qAºQìAºffAºzáAº\Aº£×AºžRAºÌÍAºáHAºõÃA»
+=A»
+žA»33A»G®A»\)A»p€A»
+A»A»®A»ÂA»×
+A»ë
+AŒ  AŒ{AŒ(öAŒ=qAŒQìAŒffAŒzáAŒ\AŒ£×AŒžRAŒÌÍAŒáHAŒõÃAœ
+=AÀ  AÀ{AÀ(öAÀ=qAÀQìAÀffAÀzáAÀ\AÀ£×AÀžRAÀÌÍAÀáHAÀõÃAÁ
+=AÁ
+žAÁ33AÁG®AÁ\)AÁp€AÁ
+AÁAÁ®AÁÂAÁ×
+AÁë
+AÂ  AÂ{AÂ(öAÂ=qAÂQìAÂffAÂzáAÂ\AÂ£×AÂžRAÂÌÍAÂáHAÂõÃAÃ
+=AÃ
+žAÃ33AÃG®AÃ\)AÃp€AÃ
+AÃAÃ®AÃÂAÃ×
+AÃë
+AÄ  AÄ{AÄ(öAÄ=qAÄQìAÄffAÄzáAÄ\AÄ£×AÄžRAÄÌÍAÄáHAÄõÃAÅ
+=AÈ  AÈ{AÈ(öAÈ=qAÈQìAÈffAÈzáAÈ\AÈ£×AÈžRAÈÌÍAÈáHAÈõÃAÉ
+=AÉ
+žAÉ33AÉG®AÉ\)AÉp€AÉ
+AÉAÉ®AÉÂAÉ×
+AÉë
+AÊ  AÊ{AÊ(öAÊ=qAÊQìAÊffAÊzáAÊ\AÊ£×AÊžRAÊÌÍAÊáHAÊõÃAË
+=AË
+žAË33AËG®AË\)AËp€AË
+AËAË®AËÂAË×
+AËë
+AÌ  AÌ{AÌ(öAÌ=qAÌQìAÌffAÌzáAÌ\AÌ£×AÌžRAÌÌÍAÌáHAÌõÃAÍ
+=AÐ  AÐ{AÐ(öAÐ=qAÐQìAÐffAÐzáAÐ\AÐ£×AÐžRAÐÌÍAÐáHAÐõÃAÑ
+=AÑ
+žAÑ33AÑG®AÑ\)AÑp€AÑ
+AÑAÑ®AÑÂAÑ×
+AÑë
+AÒ  AÒ{AÒ(öAÒ=qAÒQìAÒffAÒzáAÒ\AÒ£×AÒžRAÒÌÍAÒáHAÒõÃAÓ
+=AÓ
+žAÓ33AÓG®AÓ\)AÓp€AÓ
+AÓAÓ®AÓÂAÓ×
+AÓë
+AÔ  AÔ{AÔ(öAÔ=qAÔQìAÔffAÔzáAÔ\AÔ£×AÔžRAÔÌÍAÔáHAÔõÃAÕ
+=AØ  AØ{AØ(öAØ=qAØQìAØffAØzáAØ\AØ£×AØžRAØÌÍAØáHAØõÃAÙ
+=AÙ
+žAÙ33AÙG®AÙ\)AÙp€AÙ
+AÙAÙ®AÙÂAÙ×
+AÙë
+AÚ  AÚ{AÚ(öAÚ=qAÚQìAÚffAÚzáAÚ\AÚ£×AÚžRAÚÌÍAÚáHAÚõÃAÛ
+=AÛ
+žAÛ33AÛG®AÛ\)AÛp€AÛ
+AÛAÛ®AÛÂAÛ×
+AÛë
+AÜ  AÜ{AÜ(öAÜ=qAÜQìAÜffAÜzáAÜ\AÜ£×AÜžRAÜÌÍAÜáHAÜõÃAÝ
+=Aà  Aà{Aà(öAà=qAàQìAàffAàzáAà\Aà£×AàžRAàÌÍAàáHAàõÃAá
+=Aá
+žAá33AáG®Aá\)Aáp€Aá
+AáAá®AáÂAá×
+Aáë
+Aâ  Aâ{Aâ(öAâ=qAâQìAâffAâzáAâ\Aâ£×AâžRAâÌÍAâáHAâõÃAã
+=Aã
+žAã33AãG®Aã\)Aãp€Aã
+AãAã®AãÂAã×
+Aãë
+Aä  Aä{Aä(öAä=qAäQìAäffAäzáAä\Aä£×AäžRAäÌÍAäáHAäõÃAå
+=Aè  Aè{Aè(öAè=qAèQìAèffAèzáAè\Aè£×AèžRAèÌÍAèáHAèõÃAé
+=Aé
+žAé33AéG®Aé\)Aép€Aé
+AéAé®AéÂAé×
+Aéë
+Aê  Aê{Aê(öAê=qAêQìAêffAêzáAê\Aê£×AêžRAêÌÍAêáHAêõÃAë
+=Aë
+žAë33AëG®Aë\)Aëp€Aë
+AëAë®AëÂAë×
+Aëë
+Aì  Aì{Aì(öAì=qAìQìAìffAìzáAì\Aì£×AìžRAìÌÍAìáHAìõÃAí
+=Að  Að{Að(öAð=qAðQìAðffAðzáAð\Að£×AðžRAðÌÍAðáHAðõÃAñ
+=Añ
+žAñ33AñG®Añ\)Añp€Añ
+AñAñ®AñÂAñ×
+Añë
+Aò  Aò{Aò(öAò=qAòQìAòffAòzáAò\Aò£×AòžRAòÌÍAòáHAòõÃAó
+=Aó
+žAó33AóG®Aó\)Aóp€Aó
+AóAó®AóÂAó×
+Aóë
+Aô  Aô{Aô(öAô=qAôQìAôffAôzáAô\Aô£×AôžRAôÌÍAôáHAôõÃAõ
+=Aø  Aø{Aø(öAø=qAøQìAøffAøzáAø\Aø£×AøžRAøÌÍAøáHAøõÃAù
+=Aù
+žAù33AùG®Aù\)Aùp€Aù
+AùAù®AùÂAù×
+Aùë
+Aú  Aú{Aú(öAú=qAúQìAúffAúzáAú\Aú£×AúžRAúÌÍAúáHAúõÃAû
+=Aû
+žAû33AûG®Aû\)Aûp€Aû
+AûAû®AûÂAû×
+Aûë
+Aü  Aü{Aü(öAü=qAüQìAüffAüzáAü\Aü£×AüžRAüÌÍAüáHAüõÃAý
+=B   B 
+=B {B 
+žB (öB 33B =qB G®B QìB \)B ffB p€B záB 
+B \B B £×B ®B žRB ÂB ÌÍB ×
+B áHB ë
+B õÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB	  B	
+=B	{B	
+žB	(öB	33B	=qB	G®B	QìB	\)B	ffB	p€B	záB	
+B	\B	B	£×B	®B	žRB	ÂB	ÌÍB	×
+B	áHB	ë
+B	õÃB
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+\B
+B
+£×B
+®B
+žRB
+ÂB
+ÌÍB
+×
+B
+áHB
+ë
+B
+õÃB
+  B
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+\B
+B
+£×B
+®B
+žRB
+ÂB
+ÌÍB
+×
+B
+áHB
+ë
+B
+õÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+\B
+B
+£×B
+®B
+žRB
+ÂB
+ÌÍB
+×
+B
+áHB
+ë
+B
+õÃB
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+\B
+B
+£×B
+®B
+žRB
+ÂB
+ÌÍB
+×
+B
+áHB
+ë
+B
+õÃB
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B   B 
+=B {B 
+žB (öB 33B =qB G®B QìB \)B ffB p€B záB 
+B \B B £×B ®B žRB ÂB ÌÍB ×
+B áHB ë
+B õÃB!  B!
+=B!{B!
+žB!(öB!33B!=qB!G®B!QìB!\)B!ffB!p€B!záB!
+B!\B!B!£×B!®B!žRB!ÂB!ÌÍB!×
+B!áHB!ë
+B!õÃB"  B"
+=B"{B"
+žB"(öB"33B"=qB"G®B"QìB"\)B"ffB"p€B"záB"
+B$  B$
+=B${B$
+žB$(öB$33B$=qB$G®B$QìB$\)B$ffB$p€B$záB$
+B$\B$B$£×B$®B$žRB$ÂB$ÌÍB$×
+B$áHB$ë
+B$õÃB%  B%
+=B%{B%
+žB%(öB%33B%=qB%G®B%QìB%\)B%ffB%p€B%záB%
+B%\B%B%£×B%®B%žRB%ÂB%ÌÍB%×
+B%áHB%ë
+B%õÃB&  B&
+=B&{B&
+žB&(öB&33B&=qB&G®B&QìB&\)B&ffB&p€B&záB&
+B(  B(
+=B({B(
+žB((öB(33B(=qB(G®B(QìB(\)B(ffB(p€B(záB(
+B(\B(B(£×B(®B(žRB(ÂB(ÌÍB(×
+B(áHB(ë
+B(õÃB)  B)
+=B){B)
+žB)(öB)33B)=qB)G®B)QìB)\)B)ffB)p€B)záB)
+B)\B)B)£×B)®B)žRB)ÂB)ÌÍB)×
+B)áHB)ë
+B)õÃB*  B*
+=B*{B*
+žB*(öB*33B*=qB*G®B*QìB*\)B*ffB*p€B*záB*
+B,  B,
+=B,{B,
+žB,(öB,33B,=qB,G®B,QìB,\)B,ffB,p€B,záB,
+B,\B,B,£×B,®B,žRB,ÂB,ÌÍB,×
+B,áHB,ë
+B,õÃB-  B-
+=B-{B-
+žB-(öB-33B-=qB-G®B-QìB-\)B-ffB-p€B-záB-
+B-\B-B-£×B-®B-žRB-ÂB-ÌÍB-×
+B-áHB-ë
+B-õÃB.  B.
+=B.{B.
+žB.(öB.33B.=qB.G®B.QìB.\)B.ffB.p€B.záB.
+B0  B0
+=B0{B0
+žB0(öB033B0=qB0G®B0QìB0\)B0ffB0p€B0záB0
+B0\B0B0£×B0®B0žRB0ÂB0ÌÍB0×
+B0áHB0ë
+B0õÃB1  B1
+=B1{B1
+žB1(öB133B1=qB1G®B1QìB1\)B1ffB1p€B1záB1
+B1\B1B1£×B1®B1žRB1ÂB1ÌÍB1×
+B1áHB1ë
+B1õÃB2  B2
+=B2{B2
+žB2(öB233B2=qB2G®B2QìB2\)B2ffB2p€B2záB2
+B4  B4
+=B4{B4
+žB4(öB433B4=qB4G®B4QìB4\)B4ffB4p€B4záB4
+B4\B4B4£×B4®B4žRB4ÂB4ÌÍB4×
+B4áHB4ë
+B4õÃB5  B5
+=B5{B5
+žB5(öB533B5=qB5G®B5QìB5\)B5ffB5p€B5záB5
+B5\B5B5£×B5®B5žRB5ÂB5ÌÍB5×
+B5áHB5ë
+B5õÃB6  B6
+=B6{B6
+žB6(öB633B6=qB6G®B6QìB6\)B6ffB6p€B6záB6
+B8  B8
+=B8{B8
+žB8(öB833B8=qB8G®B8QìB8\)B8ffB8p€B8záB8
+B8\B8B8£×B8®B8žRB8ÂB8ÌÍB8×
+B8áHB8ë
+B8õÃB9  B9
+=B9{B9
+žB9(öB933B9=qB9G®B9QìB9\)B9ffB9p€B9záB9
+B9\B9B9£×B9®B9žRB9ÂB9ÌÍB9×
+B9áHB9ë
+B9õÃB:  B:
+=B:{B:
+žB:(öB:33B:=qB:G®B:QìB:\)B:ffB:p€B:záB:
+B<  B<
+=B<{B<
+žB<(öB<33B<=qB<G®B<QìB<\)B<ffB<p€B<záB<
+B<\B<B<£×B<®B<žRB<ÂB<ÌÍB<×
+B<áHB<ë
+B<õÃB=  B=
+=B={B=
+žB=(öB=33B==qB=G®B=QìB=\)B=ffB=p€B=záB=
+B=\B=B=£×B=®B=žRB=ÂB=ÌÍB=×
+B=áHB=ë
+B=õÃB>  B>
+=B>{B>
+žB>(öB>33B>=qB>G®B>QìB>\)B>ffB>p€B>záB>
+B@  B@
+=B@{B@
+žB@(öB@33B@=qB@G®B@QìB@\)B@ffB@p€B@záB@
+B@\B@B@£×B@®B@žRB@ÂB@ÌÍB@×
+B@áHB@ë
+B@õÃBA  BA
+=BA{BA
+žBA(öBA33BA=qBAG®BAQìBA\)BAffBAp€BAzáBA
+BA\BABA£×BA®BAžRBAÂBAÌÍBA×
+BAáHBAë
+BAõÃBB  BB
+=BB{BB
+žBB(öBB33BB=qBBG®BBQìBB\)BBffBBp€BBzáBB
+BD  BD
+=BD{BD
+žBD(öBD33BD=qBDG®BDQìBD\)BDffBDp€BDzáBD
+BD\BDBD£×BD®BDžRBDÂBDÌÍBD×
+BDáHBDë
+BDõÃBE  BE
+=BE{BE
+žBE(öBE33BE=qBEG®BEQìBE\)BEffBEp€BEzáBE
+BE\BEBE£×BE®BEžRBEÂBEÌÍBE×
+BEáHBEë
+BEõÃBF  BF
+=BF{BF
+žBF(öBF33BF=qBFG®BFQìBF\)BFffBFp€BFzáBF
+BH  BH
+=BH{BH
+žBH(öBH33BH=qBHG®BHQìBH\)BHffBHp€BHzáBH
+BH\BHBH£×BH®BHžRBHÂBHÌÍBH×
+BHáHBHë
+BHõÃBI  BI
+=BI{BI
+žBI(öBI33BI=qBIG®BIQìBI\)BIffBIp€BIzáBI
+BI\BIBI£×BI®BIžRBIÂBIÌÍBI×
+BIáHBIë
+BIõÃBJ  BJ
+=BJ{BJ
+žBJ(öBJ33BJ=qBJG®BJQìBJ\)BJffBJp€BJzáBJ
+BL  BL
+=BL{BL
+žBL(öBL33BL=qBLG®BLQìBL\)BLffBLp€BLzáBL
+BL\BLBL£×BL®BLžRBLÂBLÌÍBL×
+BLáHBLë
+BLõÃBM  BM
+=BM{BM
+žBM(öBM33BM=qBMG®BMQìBM\)BMffBMp€BMzáBM
+BM\BMBM£×BM®BMžRBMÂBMÌÍBM×
+BMáHBMë
+BMõÃBN  BN
+=BN{BN
+žBN(öBN33BN=qBNG®BNQìBN\)BNffBNp€BNzáBN
+BP  BP
+=BP{BP
+žBP(öBP33BP=qBPG®BPQìBP\)BPffBPp€BPzáBP
+BP\BPBP£×BP®BPžRBPÂBPÌÍBP×
+BPáHBPë
+BPõÃBQ  BQ
+=BQ{BQ
+žBQ(öBQ33BQ=qBQG®BQQìBQ\)BQffBQp€BQzáBQ
+BQ\BQBQ£×BQ®BQžRBQÂBQÌÍBQ×
+BQáHBQë
+BQõÃBR  BR
+=BR{BR
+žBR(öBR33BR=qBRG®BRQìBR\)BRffBRp€BRzáBR
+BT  BT
+=BT{BT
+žBT(öBT33BT=qBTG®BTQìBT\)BTffBTp€BTzáBT
+BT\BTBT£×BT®BTžRBTÂBTÌÍBT×
+BTáHBTë
+BTõÃBU  BU
+=BU{BU
+žBU(öBU33BU=qBUG®BUQìBU\)BUffBUp€BUzáBU
+BU\BUBU£×BU®BUžRBUÂBUÌÍBU×
+BUáHBUë
+BUõÃBV  BV
+=BV{BV
+žBV(öBV33BV=qBVG®BVQìBV\)BVffBVp€BVzáBV
+BX  BX
+=BX{BX
+žBX(öBX33BX=qBXG®BXQìBX\)BXffBXp€BXzáBX
+BX\BXBX£×BX®BXžRBXÂBXÌÍBX×
+BXáHBXë
+BXõÃBY  BY
+=BY{BY
+žBY(öBY33BY=qBYG®BYQìBY\)BYffBYp€BYzáBY
+BY\BYBY£×BY®BYžRBYÂBYÌÍBY×
+BYáHBYë
+BYõÃBZ  BZ
+=BZ{BZ
+žBZ(öBZ33BZ=qBZG®BZQìBZ\)BZffBZp€BZzáBZ
+B\  B\
+=B\{B\
+žB\(öB\33B\=qB\G®B\QìB\\)B\ffB\p€B\záB\
+B\\B\B\£×B\®B\žRB\ÂB\ÌÍB\×
+B\áHB\ë
+B\õÃB]  B]
+=B]{B]
+žB](öB]33B]=qB]G®B]QìB]\)B]ffB]p€B]záB]
+B]\B]B]£×B]®B]žRB]ÂB]ÌÍB]×
+B]áHB]ë
+B]õÃB^  B^
+=B^{B^
+žB^(öB^33B^=qB^G®B^QìB^\)B^ffB^p€B^záB^
+B`  B`
+=B`{B`
+žB`(öB`33B`=qB`G®B`QìB`\)B`ffB`p€B`záB`
+B`\B`B`£×B`®B`žRB`ÂB`ÌÍB`×
+B`áHB`ë
+B`õÃBa  Ba
+=Ba{Ba
+žBa(öBa33Ba=qBaG®BaQìBa\)BaffBap€BazáBa
+Ba\BaBa£×Ba®BažRBaÂBaÌÍBa×
+BaáHBaë
+BaõÃBb  Bb
+=Bb{Bb
+žBb(öBb33Bb=qBbG®BbQìBb\)BbffBbp€BbzáBb
+Bd  Bd
+=Bd{Bd
+žBd(öBd33Bd=qBdG®BdQìBd\)BdffBdp€BdzáBd
+Bd\BdBd£×Bd®BdžRBdÂBdÌÍBd×
+BdáHBdë
+BdõÃBe  Be
+=Be{Be
+žBe(öBe33Be=qBeG®BeQìBe\)BeffBep€BezáBe
+Be\BeBe£×Be®BežRBeÂBeÌÍBe×
+BeáHBeë
+BeõÃBf  Bf
+=Bf{Bf
+žBf(öBf33Bf=qBfG®BfQìBf\)BfffBfp€BfzáBf
+Bh  Bh
+=Bh{Bh
+žBh(öBh33Bh=qBhG®BhQìBh\)BhffBhp€BhzáBh
+Bh\BhBh£×Bh®BhžRBhÂBhÌÍBh×
+BháHBhë
+BhõÃBi  Bi
+=Bi{Bi
+žBi(öBi33Bi=qBiG®BiQìBi\)BiffBip€BizáBi
+Bi\BiBi£×Bi®BižRBiÂBiÌÍBi×
+BiáHBië
+BiõÃBj  Bj
+=Bj{Bj
+žBj(öBj33Bj=qBjG®BjQìBj\)BjffBjp€BjzáBj
+Bl  Bl
+=Bl{Bl
+žBl(öBl33Bl=qBlG®BlQìBl\)BlffBlp€BlzáBl
+Bl\BlBl£×Bl®BlžRBlÂBlÌÍBl×
+BláHBlë
+BlõÃBm  Bm
+=Bm{Bm
+žBm(öBm33Bm=qBmG®BmQìBm\)BmffBmp€BmzáBm
+Bm\BmBm£×Bm®BmžRBmÂBmÌÍBm×
+BmáHBmë
+BmõÃBn  Bn
+=Bn{Bn
+žBn(öBn33Bn=qBnG®BnQìBn\)BnffBnp€BnzáBn
+Bp  Bp
+=Bp{Bp
+žBp(öBp33Bp=qBpG®BpQìBp\)BpffBpp€BpzáBp
+Bp\BpBp£×Bp®BpžRBpÂBpÌÍBp×
+BpáHBpë
+BpõÃBq  Bq
+=Bq{Bq
+žBq(öBq33Bq=qBqG®BqQìBq\)BqffBqp€BqzáBq
+Bq\BqBq£×Bq®BqžRBqÂBqÌÍBq×
+BqáHBqë
+BqõÃBr  Br
+=Br{Br
+žBr(öBr33Br=qBrG®BrQìBr\)BrffBrp€BrzáBr
+Bt  Bt
+=Bt{Bt
+žBt(öBt33Bt=qBtG®BtQìBt\)BtffBtp€BtzáBt
+Bt\BtBt£×Bt®BtžRBtÂBtÌÍBt×
+BtáHBtë
+BtõÃBu  Bu
+=Bu{Bu
+žBu(öBu33Bu=qBuG®BuQìBu\)BuffBup€BuzáBu
+Bu\BuBu£×Bu®BužRBuÂBuÌÍBu×
+BuáHBuë
+BuõÃBv  Bv
+=Bv{Bv
+žBv(öBv33Bv=qBvG®BvQìBv\)BvffBvp€BvzáBv
+Bx  Bx
+=Bx{Bx
+žBx(öBx33Bx=qBxG®BxQìBx\)BxffBxp€BxzáBx
+Bx\BxBx£×Bx®BxžRBxÂBxÌÍBx×
+BxáHBxë
+BxõÃBy  By
+=By{By
+žBy(öBy33By=qByG®ByQìBy\)ByffByp€ByzáBy
+By\ByBy£×By®ByžRByÂByÌÍBy×
+ByáHByë
+ByõÃBz  Bz
+=Bz{Bz
+žBz(öBz33Bz=qBzG®BzQìBz\)BzffBzp€BzzáBz
+B|  B|
+=B|{B|
+žB|(öB|33B|=qB|G®B|QìB|\)B|ffB|p€B|záB|
+B|\B|B|£×B|®B|žRB|ÂB|ÌÍB|×
+B|áHB|ë
+B|õÃB}  B}
+=B}{B}
+žB}(öB}33B}=qB}G®B}QìB}\)B}ffB}p€B}záB}
+B}\B}B}£×B}®B}žRB}ÂB}ÌÍB}×
+B}áHB}ë
+B}õÃB~  B~
+=B~{B~
+žB~(öB~33B~=qB~G®B~QìB~\)B~ffB~p€B~záB~
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?  <#×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @   ?G®?G®<£×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @  @@£×@ £×?\?×
+=#×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @   @Qì@Qì@AG®@ë
+?
+
+ž?
+
+ž=LÌÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @À  @ÀQì@ Qì@£×@õÃ@B\@\?ff?®=uÂ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A   @àQì@ÀQì@À£×@ õÃ@G®@G®@C33@×
+?®?õÃ=£×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A  A(öA (ö@à£×@ÀõÃ@ÁG®@¡G®@@ë
+@C×
+@zá?=q?
+=žQì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A0  A (öA(öAQìA zá@áG®@ÁG®@Á@¡ë
+@ë
+@=q@E
+ž@Â?
+?ÌÍ=áG®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A@  A0(öA0(öA QìAzáA£×A £×@á@Áë
+@Áë
+@¢=q@\@áH@EÂ@ff?{?{=õÂ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AP  AP(öA@(öA0QìA0záA £×A£×AÌÍA õÃ@áë
+@Â=q@Â\@¢áH@áH@33@G
+=@
+=?\)?£×>
+ž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Ap  A`(öAP(öAPQìA@záA0£×A0£×A ÌÍAõÃAõÃA
+ž@â\@ÂáH@ÂáH@£33@
+@
+@G®@Qì?£×?ë
+>¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A  A{Ap(öA`QìAPzáAP£×A@£×A0ÌÍA0õÃA õÃA
+žAG®Ap€@âáH@Ã33@Ã
+@£
+@×
+@(ö@HQì@õÃ?33?zá>#×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A  A{A{A(öApzáA`£×AP£×APÌÍA@õÃA0õÃA1
+žA!G®Ap€Ap€A@ã
+@Ã
+@Ã×
+@€(ö@(ö@zá@I@
+=q?zá?Â>8Qì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A  A{A{A(öA=qAQìAp£×A`ÌÍAPõÃAPõÃAA
+žA1G®A1p€A!p€AAÂAÂ@ã×
+@Ä(ö@Ä(ö@€zá@ÌÍ@
+
+ž@J=q@
+áH?
+>?
+>>B\¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aš  A {A{A(öA=qAQìAQìAffApõÃA`õÃAQ
+žAQG®AAp€A1p€A1A!ÂAÂAë
+A{@ä(ö@Äzá@ÄÌÍ@¥
+ž@
+
+ž@
+p€@K
+@
+
+?Qì?>W
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A°  Aš{Aš{A (öA=qAQìAQìAffAzáAzáAq
+žAaG®AQp€AQp€AAA1ÂA1ÂA!ë
+A{A{A=q@äÌÍ@Å
+ž@Å
+ž@¥p€@
+Â@
+Â@L(ö@
+ÌÍ?áH?áH>aG®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Až  Až{A°{Aš(öAš=qA QìAQìAffAzáAzáA\A£×Aqp€Aap€AQAQÂAAÂA1ë
+A2{A"{A=qAffA\@å
+ž@Åp€@ÅÂ@¥Â@{@ff@Mp€@
+p€?(ö?p€>k
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÈ  AÀ{Až{Až(öA°=qAšQìAšQìA ffAzáAzáA\A£×AžRAžRAqAaÂAQÂAQë
+AB{A2{A2=qA"ffA\A\AžR@åÂ@ÅÂ@Æ{@Šff@žR@žR@N{@žR?p€?žR>  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÐ  AÈ{AÈ{AÀ(öAž=qAžQìA°QìAšffAšzáA záA\A£×AžRAžRAÌÍAáHAqÂAaë
+AR{AR{AB=qA2ffA2\A"\AžRAáHAáH@æ{@Æff@ÆžR@ŠžR@
+=@\)@NžR@\)?   ?   >
+
+ž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aà  AØ{AÐ{AÈ(öAÈ=qAÀQìAžQìAžffA°záAšzáAš\A £×AžRAžRAÌÍAáHAáHAõÃAr{Ab{AR=qARffAB\A2\A2žRA"áHAáHA
+=A33@æžR@ÆžR@Ç
+=@§\)@\)@®@P  @  ?¡G®?¢\>\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aè  Aà{Aà{AØ(öAÐ=qAÈQìAÈQìAÀffAžzáAžzáA°\Aš£×AšžRA žRAÌÍAáHAáHAõÃA
+=A
+=Ar=qAbffAR\AR\ABžRA2áHA2áHA#
+=A33A\)A\)@ç
+=@Ç\)@Ç\)@§®@  @  @P£×@G®?£×
+?£×
+>zá¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Að  Að{Aè{Aà(öAà=qAØQìAÐQìAÈffAÈzáAÀzáAž\Až£×A°žRAšžRAšÌÍA áHAáHAõÃA
+=A
+=A
+žA33Ar\Ab\ARžRARáHABáHA3
+=A333A#\)A\)A
+A®@ç\)@Ç®@È  @š  @Qì@£×@Që
+@ë
+?¥
+ž?Šff>¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B   Aø{Að{Að(öAè=qAàQìAàQìAØffAÐzáAÈzáAÈ\AÀ£×AžžRAžžRA°ÌÍAšáHAšáHA õÃA
+=A
+=A
+žA33AG®AG®AržRAbáHARáHAS
+=AC33A3\)A3\)A#
+A®A®A×
+@è  @È  @ÈQì@š£×@õÃ@õÃ@R\@33?Šff?§®>£×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B  B
+=B 
+=Aø(öAð=qAðQìAèQìAàffAàzáAØzáAÐ\AÈ£×AÈžRAÀžRAžÌÍAžáHA°áHAšõÃA©
+=A¡
+=A
+žA33AG®AG®A\)Ap€AráHAc
+=AS33AS\)AC\)A3
+A3®A#®A×
+A  A  @èQì@È£×@ÈõÃ@šõÃ@G®@@S33@×
+?šõÂ?ª=q>šõÃ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+  B
+=B
+=B{B 
+žAøQìAðQìAðffAèzáAàzáAà\AØ£×AÐžRAÈžRAÈÌÍAÀáHAžáHAžõÃA±
+=A©
+=A©
+žA¡33AG®AG®A\)Ap€Ap€A
+As33Ac\)AS\)AS
+AC®A3®A3×
+A$  A  A(öAQì@èõÃ@ÈõÃ@ÉG®@©@@ë
+@Tzá@
+ž?ª=q?«
+>³33¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B  B
+
+=B
+
+=B{B
+žB(öB (öAøffAðzáAðzáAè\Aà£×AàžRAØžRAÐÌÍAÈáHAÈáHAÀõÃA¹
+=A¹
+=A±
+žA©33A©G®A¡G®A\)Ap€Ap€A
+AA®As\)Ac
+AS®AS®AC×
+A4  A4  A$(öAQìAzáAzá@éG®@É@É@©ë
+@=q@\@U
+ž@Â?¬ÌÍ?¬ÌÍ>žQì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B  B
+=B
+=B
+{B
+
+žB(öB(öB33B =qAøzáAð\Að£×AèžRAàžRAàÌÍAØáHAÐáHAÈõÃAÉ
+=AÁ
+=A¹
+žA¹33A±G®A©G®A©\)A¡p€Ap€A
+AA®A®AÂAs®Ac®AS×
+AT  AD  A4(öA4QìA$záAzáA£×AÌÍ@é@Éë
+@Ê=q@ª\@\@áH@Vff@ff?®{?¯\)>Â\¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+  B
+=B
+=B{B
+žB
+(öB
+(öB33B=qB=qB G®Aø£×AðžRAðžRAèÌÍAàáHAàáHAØõÃAÑ
+=AÉ
+=AÉ
+žAÁ33A¹G®A¹G®A±\)A©p€A©p€A¡
+AA®A®AÂA×
+A×
+As×
+Ad  AT  AT(öADQìA4záA4záA$£×AÌÍAÌÍAõÃ@ê=q@Ê\@Ê\@ªáH@33@33@W
+>@®?°£×?°£×>Ç®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B   B 
+=B
+
+=B{B
+žB(öB(öB
+33B
+=qB=qBG®BQìB \)AøžRAðÌÍAðáHAèáHAàõÃAá
+=AÙ
+=AÑ
+žAÉ33AÉG®AÁG®A¹\)A¹p€A±p€A©
+A©A¡®A®AÂA×
+A×
+Aë
+A  At  Ad(öATQìATzáADzáA4£×A4ÌÍA$ÌÍAõÃA
+žAG®@ê\@ÊáH@Ë33@«33@
+@×
+@XQì@Qì?±ë
+?³33>ÌÌÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B(  B$
+=B 
+=B {B
+
+žB(öB(öB33B=qB
+=qB
+G®BQìB\)B\)B ffAøáHAðáHAðõÃAé
+=Aá
+=Aá
+žAÙ33AÑG®AÉG®AÉ\)AÁp€A¹p€A¹
+A±A©®A©®A¡ÂA×
+A×
+Aë
+A  A  A{AtQìAdzáATzáAT£×ADÌÍA4ÌÍA4õÃA%
+žAG®AG®Ap€@ë33@Ë33@Ë
+@«×
+@(ö@(ö@XõÂ@?³33?Žzá>×
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B,  B(
+=B(
+=B${B 
+žB (öB
+(öB33B=qB=qBG®B
+QìB
+\)B\)BffBp€B p€AøõÃAñ
+=Añ
+=Aé
+žAá33AáG®AÙG®AÑ\)AÉp€AÉp€AÁ
+A¹A¹®A±®A©ÂA©×
+A¡×
+Aë
+A  A  A{A(öA=qAtzáAd£×ATÌÍATÌÍADõÃA5
+žA5G®A%G®Ap€AA@ë
+@Ë×
+@Ì(ö@¬(ö@zá@ÌÍ@Y@=q?µÂ?µÂ>Ü(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B4  B0
+=B,
+=B({B(
+žB$(öB (öB 33B
+=qB=qBG®BQìB\)B
+\)B
+ffBp€Bp€BzáB 
+Aù
+=Añ
+žAñ33AéG®AáG®Aá\)AÙp€AÑp€AÉ
+AÉAÁ®A¹®A¹ÂA±×
+A©×
+A©ë
+A¢  A  A{A(öA=qA=qAQìAtÌÍAdÌÍATõÃAU
+žAEG®A5G®A5p€A%AAÂAë
+@ì(ö@Ì(ö@Ìzá@¬ÌÍ@ÌÍ@
+ž@ZáH@áH?·
+>?žQì>æff¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B8  B4
+=B4
+=B0{B,
+žB((öB((öB$33B =qB =qB
+G®BQìB\)B\)BffB
+p€B
+p€BzáB
+B
+B \Aù33AñG®AñG®Aé\)Aáp€Aáp€AÙ
+AÑAÉ®AÉ®AÁÂA¹×
+A¹×
+A±ë
+Aª  Aª  A¢{A(öA=qA=qAQìAffAffAtõÃAe
+žAUG®AUG®AEp€A5A5A%ÂAë
+A{A{@ìzá@ÌÌÍ@ÌÌÍ@­
+ž@p€@p€@[
+@
+(ö?¹?¹>ë
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B<  B<
+=B8
+=B4{B4
+žB0(öB,(öB(33B(=qB$=qB G®B QìB
+\)B\)BffBp€Bp€B
+záB
+
+B
+B\BB £×AùG®Añ\)Añp€Aép€Aá
+AáAÙ®AÑ®AÉÂAÉ×
+AÁ×
+A¹ë
+Aº  A²  Aª{Aª(öA¢=qA=qAQìAffAffAzáA\AuG®AeG®AUp€AUAEA5ÂA5ë
+A&{A{A=qAff@ìÌÍ@Í
+ž@Íp€@­p€@Â@{@\ÌÍ@
+ÌÍ?ºáH?Œ(ö>ð£×¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BD  B@
+=B<
+=B<{B8
+žB4(öB4(öB033B,=qB(=qB(G®B$QìB \)B \)B
+ffBp€Bp€BzáB
+B
+
+B
+\BB£×B£×B ®Aùp€Añp€Añ
+AéAá®Aá®AÙÂAÑ×
+AÉ×
+AÉë
+AÂ  Aº  Aº{A²(öAª=qAª=qA¢QìAffAffAzáA\A£×A£×Aup€AeAUAUÂAEë
+A6{A6{A&=qAffAffA\@íp€@Íp€@ÍÂ@®{@ff@ff@]p€@
+{?Œ(ö?œp€>úáH¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BH  BH
+=BD
+=B@{B<
+žB<(öB8(öB433B4=qB0=qB,G®B(QìB(\)B$\)B ffB p€B
+p€BzáB
+B
+B\B
+B
+£×B£×B®BžRB žRAù
+AñAñ®Aé®AáÂAá×
+AÙ×
+AÑë
+AÊ  AÊ  AÂ{Aº(öAº=qA²=qAªQìAªffA¢ffAzáA\A£×A£×AžRAÌÍAuAeÂAUë
+AV{AF{A6=qA6ffA&ffA\AžRAžR@íÂ@Î{@Îff@®ff@žR@
+=@^{@
+žR?ŸžR?À  ?   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BP  BL
+=BH
+=BH{BD
+žB@(öB<(öB<33B8=qB4=qB4G®B0QìB,\)B(\)B(ffB$p€B p€B záB
+
+B
+B\BB£×B
+£×B
+®BžRBžRBÂB ÌÍAù®Añ®AñÂAé×
+Aá×
+Aáë
+AÚ  AÒ  AÊ{AÊ(öAÂ=qAº=qAºQìA²ffAªffAªzáA¢\A£×A£×AžRAÌÍAÌÍAáHAuë
+Af{AV{AV=qAFffA6ffA6\A&žRAžRAáHA
+=@îff@Îff@ÎžR@¯
+=@
+=@\)@_\)@   ?À  ?ÁG®?
+ž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BT  BP
+=BP
+=BL{BH
+žBH(öBD(öB@33B<=qB<=qB8G®B4QìB4\)B0\)B,ffB(p€B(p€B$záB 
+B 
+B
+\BB£×B£×B®B
+žRB
+žRBÂBÌÍB×
+B ×
+AùÂAñ×
+Añ×
+Aéë
+Aâ  Aâ  AÚ{AÒ(öAÊ=qAÊ=qAÂQìAºffAºffA²záAª\Aª£×A¢£×AžRAÌÍAÌÍAáHAõÃA
+=Av{Af=qAVffAVffAF\A6žRA6žRA&áHA
+=A33A33@îžR@Ï
+=@Ï
+=@¯\)@®@  @`  @ £×?Â\?Â\?®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BX  BX
+=BT
+=BP{BP
+žBL(öBH(öBH33BD=qB@=qB<G®B<QìB8\)B4\)B4ffB0p€B,p€B(záB(
+B$
+B \B B
+£×B£×B®BžRBžRB
+ÂB
+ÌÍB×
+B×
+BáHB ë
+Aù×
+Añë
+Aò  Aê  Aâ{Aâ(öAÚ=qAÒ=qAÊQìAÊffAÂffAºzáAº\A²£×Aª£×AªžRA¢ÌÍAÌÍAáHAõÃA
+=A
+=A
+žAvffAfffAV\AVžRAFžRA6áHA7
+=A'33A33A\)A
+@ï
+=@Ï\)@Ï®@°  @  @Qì@aG®@!G®?Ã×
+?Å
+ž?
+=q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B`  B\
+=BX
+=BX{BT
+žBP(öBP(öBL33BH=qBH=qBDG®B@QìB<\)B<\)B8ffB4p€B4p€B0záB,
+B(
+B(\B$B £×B £×B
+®BžRBžRBÂBÌÍB
+×
+B
+×
+BáHBë
+Bë
+B õÃAú  Aò  Aò{Aê(öAâ=qAâ=qAÚQìAÒffAÊffAÊzáAÂ\Aº£×Aº£×A²žRAªÌÍAªÌÍA¢áHAõÃA
+=A
+=A
+žA33A33Av\AfžRAVžRAVáHAG
+=A733A733A'\)A
+A
+A®@ï®@Ð  @Ð  @°Qì@£×@£×@aë
+@"\?Å
+ž?Æff?\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bd  Bd
+=B`
+=B\{BX
+žBX(öBT(öBP33BP=qBL=qBHG®BHQìBD\)B@\)B<ffB<p€B8p€B4záB4
+B0
+B,\B(B(£×B$£×B ®B žRB
+žRBÂBÌÍB×
+B×
+B
+áHB
+ë
+Bë
+BõÃB  B  Aú{Aò(öAò=qAê=qAâQìAâffAÚffAÒzáAÊ\AÊ£×AÂ£×AºžRAºÌÍA²ÌÍAªáHAªõÃA£
+=A
+=A
+žA33A33AG®A\)AvžRAfáHAW
+=AW33AG33A7\)A7
+A'
+A®A×
+A  @ð  @ÐQì@Ð£×@°£×@õÂ@G®@b\@#33?Ç®?ÈõÂ?ë
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bl  Bh
+=Bd
+=Bd{B`
+žB\(öBX(öBX33BT=qBP=qBPG®BLQìBH\)BH\)BDffB@p€B<p€B<záB8
+B4
+B4\B0B,£×B(£×B(®B$žRB žRB ÂB
+ÌÍB×
+B×
+BáHBë
+B
+ë
+B
+õÃB	  B  B
+=B{Aú=qAò=qAòQìAêffAâffAâzáAÚ\AÒ£×AÊ£×AÊžRAÂÌÍAºÌÍAºáHA²õÃA«
+=A«
+=A£
+žA33A33AG®A\)A\)Ap€Aw
+=Ag33AW33AW\)AG
+A7
+A7®A'×
+A  A  A(ö@ð£×@Ð£×@ÐõÂ@±G®@G®@@c×
+@$zá?ÈõÂ?Ê=p?
+=¿  ¿  ¿  ¿  ¿  ¿  Bp  Bl
+=Bl
+=Bh{Bd
+žBd(öB`(öB\33BX=qBX=qBTG®BPQìBP\)BL\)BHffBHp€BDp€B@záB<
+B<
+B8\B4B4£×B0£×B,®B(žRB(žRB$ÂB ÌÍB ×
+B
+×
+BáHBë
+Bë
+BõÃB
+  B
+  B	
+=B{B
+žB
+žAúQìAòffAòffAêzáAâ\Aâ£×AÚ£×AÒžRAÊÌÍAÊÌÍAÂáHAºõÃA»
+=A³
+=A«
+žA«33A£33AG®A\)A\)Ap€A
+AAw33Ag\)AW
+AW
+AG®A7×
+A8  A(  A(öAQìAQì@ðõÂ@ÑG®@ÑG®@±@ë
+@=q@dzá@%
+ž?Ë
+
+?Ë
+
+?¿  ¿  ¿  ¿  Bx  Bt
+=Bp
+=Bl{Bl
+žBh(öBd(öBd33B`=qB\=qBXG®BXQìBT\)BP\)BPffBLp€BHp€BHzáBD
+B@
+B<\B<B8£×B4£×B4®B0žRB,žRB(ÂB(ÌÍB$×
+B ×
+B áHB
+ë
+Bë
+BõÃB  B  B
+=B
+{B	
+žB
+žB(öB33AúffAòzáAò\Aê£×Aâ£×AâžRAÚÌÍAÒÌÍAÊáHAÊõÃAÃ
+=A»
+=A»
+žA³33A«33A«G®A£\)A\)Ap€A
+AAA®Aw
+Ag
+AW®AW×
+AH  A8  A8(öA(QìAQìAzáA£×@ñG®@Ñ@Ñë
+@²=q@=q@\@eÂ@%Â?ÌÌÍ?Î{?
+žR¿  ¿  B|  Bx
+=Bx
+=Bt{Bp
+žBl(öBl(öBh33Bd=qBd=qB`G®B\QìBX\)BX\)BTffBPp€BPp€BLzáBH
+BH
+BD\B@B<£×B<£×B8®B4žRB4žRB0ÂB,ÌÍB(×
+B(×
+B$áHB ë
+B ë
+B
+õÃB  B  B
+=B{B
+
+žB
+
+žB	(öB33B33B=qAú\Aò£×Aò£×AêžRAâÌÍAâÌÍAÚáHAÒõÃAË
+=AË
+=AÃ
+žA»33A»33A³G®A«\)A«\)A£p€A
+AAA®AÂAÂAw®Ag×
+AX  AX  AH(öA8QìA8QìA(záA£×A£×AÌÍ@ñë
+@Ò=q@Ò=q@²\@áH@áH@fff@'
+>?Ï\)?Ï\)?!G®¿  ¿  B|
+=Bx{Bx
+žBt(öBp(öBl33Bl=qBh=qBdG®BdQìB`\)B\\)BXffBXp€BTp€BPzáBP
+BL
+BH\BHBD£×B@£×B<®B<žRB8žRB4ÂB4ÌÍB0×
+B,×
+B(áHB(ë
+B$ë
+B õÃB!  B
+  B
+=B{B
+žB
+žB
+(öB
+33B	33B=qBG®BQìAú£×AòžRAòÌÍAêÌÍAâáHAâõÃAÛ
+=AÓ
+=AË
+žAË33AÃ33A»G®A»\)A³\)A«p€A«
+A£AA®AÂAÂA×
+Aë
+Ax  Ah  AX(öAXQìAHQìA8záA8£×A(£×AÌÍAõÃA	
+ž@ò=q@Ò\@ÒáH@²áH@33@
+@g®@'®?Ð£×¿  ¿  ¿  ¿  B|
+žBx(öBx(öBt33Bp=qBl=qBlG®BhQìBd\)Bd\)B`ffB\p€BXp€BXzáBT
+BP
+BP\BLBH£×BH£×BD®B@žRB<žRB<ÂB8ÌÍB4×
+B4×
+B0áHB,ë
+B(ë
+B(õÃB%  B!  B!
+=B
+{B
+žB
+žB(öB33B
+33B
+=qB	G®BQìBQìB\)AúÌÍAòÌÍAòáHAêõÃAã
+=Aã
+=AÛ
+žAÓ33AË33AËG®AÃ\)A»\)A»p€A³
+A«A«A£®AÂAÂA×
+Aë
+A  A  Ax(öAhQìAXQìAXzáAH£×A8£×A8ÌÍA(õÃA
+žA
+žA	G®@òáH@ÒáH@Ó33@³
+@×
+@×
+@hQì¿  ¿  ¿  ¿  ¿  ¿  B|(öBx33Bx=qBt=qBpG®BlQìBl\)Bh\)BdffBdp€B`p€B\záBX
+BX
+BT\BPBP£×BL£×BH®BHžRBDžRB@ÂB<ÌÍB<×
+B8×
+B4áHB4ë
+B0ë
+B,õÃB)  B)  B%
+=B!{B!
+žB
+
+žB(öB33B33B=qB
+G®B
+QìB	QìB\)BffBffAúáHAòõÃAó
+=Aë
+=Aã
+žAã33AÛ33AÓG®AË\)AË\)AÃp€A»
+A»A³A«®A«ÂA£ÂA×
+Aë
+A  A  A{A(öAxQìAhzáAX£×AX£×AHÌÍA8õÃA9
+žA)
+žAG®Ap€A	p€@ó33@Ó
+@Ó×
+@³×
+@(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|=qBx=qBxG®BtQìBp\)Bl\)BlffBhp€Bdp€BdzáB`
+B\
+BX\BXBT£×BP£×BP®BLžRBHžRBHÂBDÌÍB@×
+B<×
+B<áHB8ë
+B4ë
+B4õÃB1  B-  B)
+=B){B%
+žB!
+žB!(öB
+33B33B=qBG®BQìB
+QìB
+\)B	ffBffBp€BzáAû
+=Aó
+=Aó
+žAë33Aã33AãG®AÛ\)AÓ\)AËp€AË
+AÃA»A»®A³ÂA«ÂA«×
+A£ë
+A  A  A{A(öA(öA=qAx£×Ah£×AXÌÍAXõÃAI
+žA9
+žA9G®A)p€Ap€AA	Â@ó×
+@Ó×
+@Ô(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|G®BxQìBx\)Bt\)BpffBlp€Blp€BhzáBd
+Bd
+B`\B\BX£×BX£×BT®BPžRBPžRBLÂBHÌÍBH×
+BD×
+B@áHB<ë
+B<ë
+B8õÃB5  B5  B1
+=B-{B)
+žB)
+žB%(öB!33B!33B
+=qBG®BQìBQìB\)B
+ffB
+ffB	p€BzáB
+B
+Aû
+žAó33Aó33AëG®Aã\)Aã\)AÛp€AÓ
+AËAËAÃ®A»ÂA»ÂA³×
+A«ë
+A¬  A€  A{A(öA(öA=qAQìAQìAxÌÍAhõÃAY
+žAY
+žAIG®A9p€A9p€A)AÂAë
+A	ë
+@ô(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|\)Bx\)BxffBtp€Bpp€BlzáBl
+Bh
+Bd\BdB`£×B\£×BX®BXžRBTžRBPÂBPÌÍBL×
+BH×
+BHáHBDë
+B@ë
+B<õÃB=  B9  B5
+=B5{B1
+žB-
+žB)(öB)33B%33B!=qB!G®B
+QìBQìB\)BffBffB
+p€B
+záB	
+B
+B\BAû33AóG®Aó\)Aë\)Aãp€Aã
+AÛAÓAË®AËÂAÃÂA»×
+A»ë
+AŽ  A¬  A¬{A€(öA(öA=qAQìAQìAffAzáAy
+žAi
+žAYG®AYp€AIp€A9A9ÂA)ë
+Aë
+A{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ffBxp€Bxp€BtzáBp
+Bl
+Bl\BhBd£×Bd£×B`®B\žRBXžRBXÂBTÌÍBP×
+BP×
+BLáHBHë
+BHë
+BDõÃBA  B=  B=
+=B9{B5
+žB5
+žB1(öB-33B)33B)=qB%G®B!QìB!QìB
+\)BffBffBp€BzáB
+
+B
+
+B	\BBB£×Aû\)Aó\)Aóp€Aë
+AãAãAÛ®AÓÂAËÂAË×
+AÃë
+AŒ  AŒ  AŽ{A¬(öA¬(öA€=qAQìAQìAffAzáA\A\AyG®Aip€AYp€AYAIÂA9ë
+A9ë
+A*{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|p€BxzáBx
+Bt
+Bp\BlBl£×Bh£×Bd®BdžRB`žRB\ÂBXÌÍBX×
+BT×
+BPáHBPë
+BLë
+BHõÃBI  BE  BA
+=B={B=
+žB9
+žB5(öB533B133B-=qB)G®B)QìB%QìB!\)B!ffB
+ffBp€BzáB
+B
+B
+\B
+B	B£×B®B®Aûp€Aó
+AóAëAã®AãÂAÛÂAÓ×
+AËë
+AÌ  AÄ  AŒ{AŒ(öAŽ(öA¬=qA¬QìA€QìAffAzáA\A\A£×AžRAyp€AiAYÂAYë
+AIë
+A:{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|
+Bx
+Bx\BtBp£×Bl£×Bl®BhžRBdžRBdÂB`ÌÍB\×
+BX×
+BXáHBTë
+BPë
+BPõÃBM  BI  BI
+=BE{BA
+žB=
+žB=(öB933B533B5=qB1G®B-QìB)QìB)\)B%ffB!ffB!p€B
+záB
+B
+B\BB
+B
+£×B	®B®BžRBÂAûAóAó®AëÂAãÂAã×
+AÛë
+AÔ  AÌ  AÌ{AÄ(öAŒ(öAŒ=qAŽQìA¬QìA¬ffA€záA\A\A£×AžRAžRAÌÍAyÂAië
+AYë
+AZ{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|\BxBx£×Bt£×Bp®BlžRBlžRBhÂBdÌÍBd×
+B`×
+B\áHBXë
+BXë
+BTõÃBQ  BQ  BM
+=BI{BI
+žBE
+žBA(öB=33B=33B9=qB5G®B5QìB1QìB-\)B)ffB)ffB%p€B!záB!
+B
+
+B\BBB£×B
+®B
+®B	žRBÂBÌÍBÌÍAû®AóÂAóÂAë×
+Aãë
+Aä  AÜ  AÔ{AÌ(öAÌ(öAÄ=qAŒQìAŒQìAŽffA¬záA¬\A€\A£×AžRAžRAÌÍAáHAõÃAyë
+Aj{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|£×Bx£×Bx®BtžRBpžRBlÂBlÌÍBh×
+Bd×
+BdáHB`ë
+B\ë
+BXõÃBY  BU  BQ
+=BQ{BM
+žBI
+žBI(öBE33BA33B==qB=G®B9QìB5QìB5\)B1ffB-ffB)p€B)záB%
+B!
+B!\B
+BB£×B®B®B
+žRB
+ÂB	ÌÍBÌÍB×
+BáHAûÂAó×
+Aóë
+Aì  Aä  Aä{AÜ(öAÔ(öAÌ=qAÌQìAÄQìAŒffAŒzáAŽ\A¬\A¬£×A€žRAžRAÌÍAáHAõÃAõÃA
+
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|®BxžRBxžRBtÂBpÌÍBl×
+Bl×
+BháHBdë
+Bdë
+B`õÃB]  BY  BY
+=BU{BQ
+žBQ
+žBM(öBI33BI33BE=qBAG®B=QìB=QìB9\)B5ffB5ffB1p€B-záB)
+B)
+B%\B!B!B
+£×B®B®BžRBÂB
+ÌÍB
+ÌÍB	×
+BáHBáHBë
+Aûë
+Aô  Aô  Aì{Aä(öAä(öAÜ=qAÔQìAÌQìAÌffAÄzáAŒ\AŒ\AŽ£×A¬žRA¬žRA€ÌÍAáHAõÃAõÃA
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|žRBxÂBxÌÍBt×
+Bp×
+BláHBlë
+Bhë
+BdõÃBe  Ba  B]
+=BY{BY
+žBU
+žBQ(öBQ33BM33BI=qBIG®BEQìBAQìB=\)B=ffB9ffB5p€B5záB1
+B-
+B)\B)B%B!£×B!®B
+®BžRBÂBÌÍBÌÍB
+×
+B
+áHB	áHBë
+BõÃB  Aü  Aô{Aô(öAì(öAä=qAäQìAÜQìAÔffAÌzáAÌ\AÄ\AŒ£×AŒžRAŽžRA¬ÌÍA¬áHA€õÃAõÃA
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ÌÍBx×
+Bx×
+BtáHBpë
+Blë
+BlõÃBi  Be  Be
+=Ba{B]
+žBY
+žBY(öBU33BQ33BQ=qBMG®BIQìBIQìBE\)BAffB=ffB=p€B9záB5
+B5
+B1\B-B)B)£×B%®B!®B!žRB
+ÂBÌÍBÌÍB×
+BáHB
+áHB
+ë
+B	õÃB  B  B
+=Aü(öAô(öAô=qAìQìAäQìAäffAÜzáAÔ\AÌ\AÌ£×AÄžRAŒžRAŒÌÍAŽáHA¬õÃA¬õÃA¥
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|×
+BxáHBxë
+Btë
+BpõÃBm  Bm  Bi
+=Be{Be
+žBa
+žB](öBY33BY33BU=qBQG®BQQìBMQìBI\)BIffBEffBAp€B=záB=
+B9
+B5\B5B1B-£×B)®B)®B%žRB!ÂB!ÌÍB
+ÌÍB×
+BáHBáHBë
+B
+õÃB  B
+  B
+=B{B{Aü=qAôQìAôQìAìffAäzáAä\AÜ\AÔ£×AÌžRAÌžRAÄÌÍAŒáHAŒõÃAŽõÃA­
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ë
+Bxë
+BxõÃBu  Bq  Bm
+=Bm{Bi
+žBe
+žBe(öBa33B]33BY=qBYG®BUQìBQQìBQ\)BMffBIffBIp€BEzáBA
+B=
+B=\B9B5B5£×B1®B-®B)žRB)ÂB%ÌÍB!ÌÍB!×
+B
+áHBáHBë
+BõÃB  B  B
+=B
+{B{B
+žB(öAüQìAôffAôzáAì\Aä\Aä£×AÜžRAÔžRAÌÌÍAÌáHAÄõÃAŒõÃAœ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|õÃBy  By  Bu
+=Bq{Bm
+žBm
+žBi(öBe33Be33Ba=qB]G®BYQìBYQìBU\)BQffBQffBMp€BIzáBI
+BE
+BA\B=B=B9£×B5®B5®B1žRB-ÂB)ÌÍB)ÌÍB%×
+B!áHB!áHB
+ë
+BõÃB  B  B
+=B{B{B
+
+žB(öB(öB33AüzáAô\Aô\Aì£×AäžRAäžRAÜÌÍAÔáHAÌõÃAÌõÃAÅ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}  By
+=By{Bu
+žBq
+žBm(öBm33Bi33Be=qBeG®BaQìB]QìBY\)BYffBUffBQp€BQzáBM
+BI
+BI\BEBAB=£×B=®B9®B5žRB5ÂB1ÌÍB-ÌÍB)×
+B)áHB%áHB!ë
+B!õÃB
+  B  B
+=B{B{B
+žB(öB
+(öB33B=qBG®Aü\Aô£×AôžRAìžRAäÌÍAäáHAÜõÃAÔõÃAÍ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}{By
+žBy
+žBu(öBq33Bm33Bm=qBiG®BeQìBeQìBa\)B]ffBYffBYp€BUzáBQ
+BQ
+BM\BIBIBE£×BA®B=®B=žRB9ÂB5ÌÍB5ÌÍB1×
+B-áHB)áHB)ë
+B%õÃB"  B"  B
+
+=B{B{B
+žB(öB(öB33B
+=qBG®BG®BQìAüžRAôžRAôÌÍAìáHAäõÃAäõÃAÝ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}
+žBy(öBy33Bu33Bq=qBmG®BmQìBiQìBe\)BeffBaffB]p€BYzáBY
+BU
+BQ\BQBMBI£×BI®BE®BAžRB=ÂB=ÌÍB9ÌÍB5×
+B5áHB1áHB-ë
+B)õÃB*  B&  B"
+=B"{B
+{B
+žB(öB(öB33B=qBG®B
+G®BQìB\)B\)AüÌÍAôáHAôõÃAìõÃAå
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}33By33By=qBuG®BqQìBmQìBm\)BiffBeffBep€BazáB]
+BY
+BY\BUBQBQ£×BM®BI®BIžRBEÂBAÌÍB=ÌÍB=×
+B9áHB5áHB5ë
+B1õÃB.  B*  B*
+=B&{B"{B"
+žB
+(öB(öB33B=qBG®BG®BQìB
+\)B\)BffBp€AüõÃAôõÃAõ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}=qByG®ByQìBuQìBq\)BmffBmffBip€BezáBe
+Ba
+B]\BYBYBU£×BQ®BQ®BMžRBIÂBIÌÍBEÌÍBA×
+B=áHB=áHB9ë
+B5õÃB6  B2  B.
+=B*{B*{B&
+žB"(öB"(öB
+33B=qBG®BG®BQìB\)B\)B
+ffBp€BzáBzáAý
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}QìByQìBy\)BuffBqffBmp€BmzáBi
+Be
+Be\BaB]BY£×BY®BU®BQžRBQÂBMÌÍBIÌÍBI×
+BEáHBAáHB=ë
+B=õÃB:  B6  B6
+=B2{B.{B*
+žB*(öB&(öB"33B"=qB
+G®BG®BQìB\)B\)BffBp€B
+záBzáB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}\)ByffByffBup€BqzáBm
+Bm
+Bi\BeBeBa£×B]®BY®BYžRBUÂBQÌÍBQÌÍBM×
+BIáHBIáHBEë
+BAõÃB>  B>  B:
+=B6{B6{B2
+žB.(öB*(öB*33B&=qB"G®B"G®B
+QìB\)B\)BffBp€BzáBzáB
+
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ffByp€ByzáBu
+Bq
+Bm\BmBiBe£×Be®Ba®B]žRBYÂBYÌÍBUÌÍBQ×
+BQáHBMáHBIë
+BIõÃBF  BB  B>
+=B>{B:{B6
+žB6(öB2(öB.33B*=qB*G®B&G®B"QìB"\)B
+\)BffBp€BzáBzáB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}záBy
+By
+Bu\BqBmBm£×Bi®Be®BežRBaÂB]ÌÍBYÌÍBY×
+BUáHBQáHBQë
+BMõÃBJ  BJ  BF
+=BB{B>{B>
+žB:(öB6(öB633B2=qB.G®B*G®B*QìB&\)B"\)B"ffB
+p€BzáBzáB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}
+By\ByBuBq£×Bm®Bm®BižRBeÂBeÌÍBaÌÍB]×
+BYáHBYáHBUë
+BQõÃBR  BN  BJ
+=BJ{BF{BB
+žB>(öB>(öB:33B6=qB6G®B2G®B.QìB*\)B*\)B&ffB"p€B"záB
+záB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ByBy£×Bu®Bq®BmžRBmÂBiÌÍBeÌÍBe×
+BaáHB]áHBYë
+BYõÃBV  BR  BR
+=BN{BJ{BJ
+žBF(öBB(öB>33B>=qB:G®B6G®B6QìB2\)B.\)B*ffB*p€B&záB"záB"
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}£×By®By®BužRBqÂBmÌÍBmÌÍBi×
+BeáHBeáHBaë
+B]õÃBZ  BZ  BV
+=BR{BR{BN
+žBJ(öBJ(öBF33BB=qB>G®B>G®B:QìB6\)B6\)B2ffB.p€B*záB*záB&
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}®ByžRByÂBuÌÍBqÌÍBm×
+BmáHBiáHBeë
+BeõÃBb  B^  BZ
+=BZ{BV{BR
+žBR(öBN(öBJ33BJ=qBFG®BBG®B>QìB>\)B:\)B6ffB6p€B2záB.záB*
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ÂByÌÍByÌÍBu×
+BqáHBmáHBmë
+BiõÃBf  Bf  Bb
+=B^{BZ{BZ
+žBV(öBR(öBR33BN=qBJG®BJG®BFQìBB\)B>\)B>ffB:p€B6záB6záB2
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ÌÍBy×
+ByáHBuáHBqë
+BmõÃBn  Bj  Bf
+=Bf{Bb{B^
+žBZ(öBZ(öBV33BR=qBRG®BNG®BJQìBJ\)BF\)BBffB>p€B>záB:záB6
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}áHByáHByë
+BuõÃBr  Bn  Bn
+=Bj{Bf{Bf
+žBb(öB^(öBZ33BZ=qBVG®BRG®BRQìBN\)BJ\)BJffBFp€BBzáB>záB>
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ë
+ByõÃBz  Bv  Br
+=Bn{Bn{Bj
+žBf(öBf(öBb33B^=qBZG®BZG®BVQìBR\)BR\)BNffBJp€BJzáBFzáBB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~  Bz  Bz
+=Bv{Br{Bn
+žBn(öBj(öBf33Bf=qBbG®B^G®BZQìBZ\)BV\)BRffBRp€BNzáBJzáBJ
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~
+=Bz{Bz{Bv
+žBr(öBn(öBn33Bj=qBfG®BfG®BbQìB^\)BZ\)BZffBVp€BRzáBRzáBN
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~{Bz
+žBz(öBv(öBr33Bn=qBnG®BjG®BfQìBf\)Bb\)B^ffBZp€BZzáBVzáBR
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~(öBz(öBz33Bv=qBrG®BnG®BnQìBj\)Bf\)BfffBbp€B^záBZzáBZ
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~33Bz=qBzG®BvG®BrQìBn\)Bn\)BjffBfp€BfzáBbzáB^
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~G®BzG®BzQìBv\)Br\)BnffBnp€BjzáBfzáBf
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~QìBz\)Bz\)BvffBrp€BnzáBnzáBj
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~\)BzffBzp€BvzáBrzáBn
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~p€BzzáBzzáBv
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~záBz
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             B|  Bx  Bt  Bp  Bl  Bh  Bd  B`  B\  BX  BT  BP  BL  BH  BD  B@  B<  B8  B4  B0  B,  B(  B$  B   B
+  B  B  B  B
+  B  B  B   Aø  Að  Aè  Aà  AØ  AÐ  AÈ  AÀ  Až  A°  Aš  A   A  A  A  A  Ap  A`  AP  A@  A0  A   A  A   @à  @À  @   @  @@  @   ?      B|
+=Bx
+=Bt
+=Bp
+=Bl
+=Bh
+=Bd
+=B`
+=B\
+=BX
+=BT
+=BP
+=BL
+=BH
+=BD
+=B@
+=B<
+=B8
+=B4
+=B0
+=B,
+=B(
+=B$
+=B 
+=B
+
+=B
+=B
+=B
+=B
+
+=B
+=B
+=B 
+=Aø{Að{Aè{Aà{AØ{AÐ{AÈ{AÀ{Až{A°{Aš{A {A{A{A{A{Ap(öA`(öAP(öA@(öA0(öA (öA(öA (ö@àQì@ÀQì@ Qì@Qì@@£×@ £×?G®<#×
+B|{Bx{Bt{Bp{Bl{Bh{Bd{B`{B\{BX{BT{BP{BL{BH{BD{B@{B<{B8{B4{B0{B,{B({B${B {B
+{B{B{B{B
+{B{B{B {Aø(öAð(öAè(öAà(öAØ(öAÐ(öAÈ(öAÀ(öAž(öA°(öAš(öA (öA(öA(öA(öA(öApQìA`QìAPQìA@QìA0QìA QìAQìA Qì@à£×@À£×@ £×@£×@AG®@G®?\<£×
+B|
+žBx
+žBt
+žBp
+žBl
+žBh
+žBd
+žB`
+žB\
+žBX
+žBT
+žBP
+žBL
+žBH
+žBD
+žB@
+žB<
+žB8
+žB4
+žB0
+žB,
+žB(
+žB$
+žB 
+žB
+
+žB
+žB
+žB
+žB
+
+žB
+žB
+žB 
+žAø=qAð=qAè=qAà=qAØ=qAÐ=qAÈ=qAÀ=qAž=qA°=qAš=qA =qA=qA=qA=qA=qApzáA`záAPzáA@záA0záA záAzáA zá@àõÃ@ÀõÃ@ õÃ@õÃ@Aë
+@ë
+?×
+<õÂB|(öBx(öBt(öBp(öBl(öBh(öBd(öB`(öB\(öBX(öBT(öBP(öBL(öBH(öBD(öB@(öB<(öB8(öB4(öB0(öB,(öB((öB$(öB (öB
+(öB(öB(öB(öB
+(öB(öB(öB (öAøQìAðQìAèQìAàQìAØQìAÐQìAÈQìAÀQìAžQìA°QìAšQìA QìAQìAQìAQìAQìAp£×A`£×AP£×A@£×A0£×A £×A£×A £×@áG®@ÁG®@¡G®@G®@B\@\?
+
+ž=#×
+B|33Bx33Bt33Bp33Bl33Bh33Bd33B`33B\33BX33BT33BP33BL33BH33BD33B@33B<33B833B433B033B,33B(33B$33B 33B
+33B33B33B33B
+33B33B33B 33AøffAðffAèffAàffAØffAÐffAÈffAÀffAžffA°ffAšffA ffAffAffAffAffApÌÍA`ÌÍAPÌÍA@ÌÍA0ÌÍA ÌÍAÌÍA ÌÍ@á@Á@¡@@C33@33?ff=LÌÍB|=qBx=qBt=qBp=qBl=qBh=qBd=qB`=qB\=qBX=qBT=qBP=qBL=qBH=qBD=qB@=qB<=qB8=qB4=qB0=qB,=qB(=qB$=qB =qB
+=qB=qB=qB=qB
+=qB=qB=qB =qAøzáAðzáAèzáAàzáAØzáAÐzáAÈzáAÀzáAžzáA°záAšzáA záAzáAzáAzáAzáApõÃA`õÃAPõÃA@õÃA0õÃA õÃAõÃA õÃ@áë
+@Áë
+@¡ë
+@ë
+@C×
+@×
+?®=uÂB|G®BxG®BtG®BpG®BlG®BhG®BdG®B`G®B\G®BXG®BTG®BPG®BLG®BHG®BDG®B@G®B<G®B8G®B4G®B0G®B,G®B(G®B$G®B G®B
+G®BG®BG®BG®B
+G®BG®BG®B G®Aø\Að\Aè\Aà\AØ\AÐ\AÈ\AÀ\Až\A°\Aš\A \A\A\A\A\Aq
+žAa
+žAQ
+žAA
+žA1
+žA!
+žA
+žA
+ž@â=q@Â=q@¢=q@=q@Dzá@zá?õÃ=\)B|QìBxQìBtQìBpQìBlQìBhQìBdQìB`QìB\QìBXQìBTQìBPQìBLQìBHQìBDQìB@QìB<QìB8QìB4QìB0QìB,QìB(QìB$QìB QìB
+QìBQìBQìBQìB
+QìBQìBQìB QìAø£×Að£×Aè£×Aà£×AØ£×AÐ£×AÈ£×AÀ£×Až£×A°£×Aš£×A £×A£×A£×A£×A£×AqG®AaG®AQG®AAG®A1G®A!G®AG®AG®@â\@Â\@¢\@\@E
+ž@
+ž?=q=£×
+B|\)Bx\)Bt\)Bp\)Bl\)Bh\)Bd\)B`\)B\\)BX\)BT\)BP\)BL\)BH\)BD\)B@\)B<\)B8\)B4\)B0\)B,\)B(\)B$\)B \)B
+\)B\)B\)B\)B
+\)B\)B\)B \)AøžRAðžRAèžRAàžRAØžRAÐžRAÈžRAÀžRAžžRA°žRAšžRA žRAžRAžRAžRAžRAqp€Aap€AQp€AAp€A1p€A!p€Ap€Ap€@âáH@ÂáH@¢áH@áH@EÂ@Â?
+=žQìB|ffBxffBtffBpffBlffBhffBdffB`ffB\ffBXffBTffBPffBLffBHffBDffB@ffB<ffB8ffB4ffB0ffB,ffB(ffB$ffB ffB
+ffBffBffBffB
+ffBffBffB ffAøÌÍAðÌÍAèÌÍAàÌÍAØÌÍAÐÌÍAÈÌÍAÀÌÍAžÌÍA°ÌÍAšÌÍA ÌÍAÌÍAÌÍAÌÍAÌÍAqAaAQAAA1A!AA@ã33@Ã33@£33@33@Fff@ff?ÌÍ=ÌÌÍB|p€Bxp€Btp€Bpp€Blp€Bhp€Bdp€B`p€B\p€BXp€BTp€BPp€BLp€BHp€BDp€B@p€B<p€B8p€B4p€B0p€B,p€B(p€B$p€B p€B
+p€Bp€Bp€Bp€B
+p€Bp€Bp€B p€AøáHAðáHAèáHAàáHAØáHAÐáHAÈáHAÀáHAžáHA°áHAšáHA áHAáHAáHAáHAáHAqÂAaÂAQÂAAÂA1ÂA!ÂAÂAÂ@ã
+@Ã
+@£
+@
+@G
+=@
+=?{=áG®B|záBxzáBtzáBpzáBlzáBhzáBdzáB`záB\záBXzáBTzáBPzáBLzáBHzáBDzáB@záB<záB8záB4záB0záB,záB(záB$záB záB
+záBzáBzáBzáB
+záBzáBzáB záAøõÃAðõÃAèõÃAàõÃAØõÃAÐõÃAÈõÃAÀõÃAžõÃA°õÃAšõÃA õÃAõÃAõÃAõÃAõÃAqë
+Aaë
+AQë
+AAë
+A1ë
+A!ë
+Aë
+Aë
+@ã×
+@Ã×
+@£×
+@×
+@G®@®?\)=õÂB|
+Bx
+Bt
+Bp
+Bl
+Bh
+Bd
+B`
+B\
+BX
+BT
+BP
+BL
+BH
+BD
+B@
+B<
+B8
+B4
+B0
+B,
+B(
+B$
+B 
+B
+
+B
+B
+B
+B
+
+B
+B
+B 
+Aù
+=Añ
+=Aé
+=Aá
+=AÙ
+=AÑ
+=AÉ
+=AÁ
+=A¹
+=A±
+=A©
+=A¡
+=A
+=A
+=A
+=A
+=Ar{Ab{AR{AB{A2{A"{A{A{@ä(ö@Ä(ö@€(ö@(ö@HQì@Qì?£×>
+žB|\Bx\Bt\Bp\Bl\Bh\Bd\B`\B\\BX\BT\BP\BL\BH\BD\B@\B<\B8\B4\B0\B,\B(\B$\B \B
+\B\B\B\B
+\B\B\B \Aù
+žAñ
+žAé
+žAá
+žAÙ
+žAÑ
+žAÉ
+žAÁ
+žA¹
+žA±
+žA©
+žA¡
+žA
+žA
+žA
+žA
+žAr=qAb=qAR=qAB=qA2=qA"=qA=qA=q@äzá@Äzá@€zá@zá@HõÃ@õÃ?ë
+>\)B|BxBtBpBlBhBdB`B\BXBTBPBLBHBDB@B<B8B4B0B,B(B$B B
+BBBB
+BBB Aù33Añ33Aé33Aá33AÙ33AÑ33AÉ33AÁ33A¹33A±33A©33A¡33A33A33A33A33ArffAbffARffABffA2ffA"ffAffAff@äÌÍ@ÄÌÍ@€ÌÍ@ÌÍ@I@	?33>B|£×Bx£×Bt£×Bp£×Bl£×Bh£×Bd£×B`£×B\£×BX£×BT£×BP£×BL£×BH£×BD£×B@£×B<£×B8£×B4£×B0£×B,£×B(£×B$£×B £×B
+£×B£×B£×B£×B
+£×B£×B£×B £×AùG®AñG®AéG®AáG®AÙG®AÑG®AÉG®AÁG®A¹G®A±G®A©G®A¡G®AG®AG®AG®AG®Ar\Ab\AR\AB\A2\A"\A\A\@å
+ž@Å
+ž@¥
+ž@
+
+ž@J=q@
+=q?zá>#×
+B|®Bx®Bt®Bp®Bl®Bh®Bd®B`®B\®BX®BT®BP®BL®BH®BD®B@®B<®B8®B4®B0®B,®B(®B$®B ®B
+®B®B®B®B
+®B®B®B ®Aù\)Añ\)Aé\)Aá\)AÙ\)AÑ\)AÉ\)AÁ\)A¹\)A±\)A©\)A¡\)A\)A\)A\)A\)AržRAbžRARžRABžRA2žRA"žRAžRAžR@åp€@Åp€@¥p€@
+p€@JáH@
+áH?Â>.{B|žRBxžRBtžRBpžRBlžRBhžRBdžRB`žRB\žRBXžRBTžRBPžRBLžRBHžRBDžRB@žRB<žRB8žRB4žRB0žRB,žRB(žRB$žRB žRB
+žRBžRBžRBžRB
+žRBžRBžRB žRAùp€Añp€Aép€Aáp€AÙp€AÑp€AÉp€AÁp€A¹p€A±p€A©p€A¡p€Ap€Ap€Ap€Ap€AráHAbáHARáHABáHA2áHA"áHAáHAáH@åÂ@ÅÂ@¥Â@
+Â@K
+@
+
+?
+>>8QìB|ÂBxÂBtÂBpÂBlÂBhÂBdÂB`ÂB\ÂBXÂBTÂBPÂBLÂBHÂBDÂB@ÂB<ÂB8ÂB4ÂB0ÂB,ÂB(ÂB$ÂB ÂB
+ÂBÂBÂBÂB
+ÂBÂBÂB ÂAù
+Añ
+Aé
+Aá
+AÙ
+AÑ
+AÉ
+AÁ
+A¹
+A±
+A©
+A¡
+A
+A
+A
+A
+As
+=Ac
+=AS
+=AC
+=A3
+=A#
+=A
+=A
+=@æ{@Æ{@Š{@{@L(ö@
+(ö?Qì>B\B|ÌÍBxÌÍBtÌÍBpÌÍBlÌÍBhÌÍBdÌÍB`ÌÍB\ÌÍBXÌÍBTÌÍBPÌÍBLÌÍBHÌÍBDÌÍB@ÌÍB<ÌÍB8ÌÍB4ÌÍB0ÌÍB,ÌÍB(ÌÍB$ÌÍB ÌÍB
+ÌÍBÌÍBÌÍBÌÍB
+ÌÍBÌÍBÌÍB ÌÍAùAñAéAáAÙAÑAÉAÁA¹A±A©A¡AAAAAs33Ac33AS33AC33A333A#33A33A33@æff@Æff@Šff@ff@LÌÍ@
+ÌÍ?>LÌÍB|×
+Bx×
+Bt×
+Bp×
+Bl×
+Bh×
+Bd×
+B`×
+B\×
+BX×
+BT×
+BP×
+BL×
+BH×
+BD×
+B@×
+B<×
+B8×
+B4×
+B0×
+B,×
+B(×
+B$×
+B ×
+B
+×
+B×
+B×
+B×
+B
+×
+B×
+B×
+B ×
+Aù®Añ®Aé®Aá®AÙ®AÑ®AÉ®AÁ®A¹®A±®A©®A¡®A®A®A®A®As\)Ac\)AS\)AC\)A3\)A#\)A\)A\)@æžR@ÆžR@ŠžR@žR@Mp€@
+p€?áH>W
+=B|áHBxáHBtáHBpáHBláHBháHBdáHB`áHB\áHBXáHBTáHBPáHBLáHBHáHBDáHB@áHB<áHB8áHB4áHB0áHB,áHB(áHB$áHB áHB
+áHBáHBáHBáHB
+áHBáHBáHB áHAùÂAñÂAéÂAáÂAÙÂAÑÂAÉÂAÁÂA¹ÂA±ÂA©ÂA¡ÂAÂAÂAÂAÂAs
+Ac
+AS
+AC
+A3
+A#
+A
+A
+@ç
+=@Ç
+=@§
+=@
+=@N{@{?(ö>aG®B|ë
+Bxë
+Btë
+Bpë
+Blë
+Bhë
+Bdë
+B`ë
+B\ë
+BXë
+BTë
+BPë
+BLë
+BHë
+BDë
+B@ë
+B<ë
+B8ë
+B4ë
+B0ë
+B,ë
+B(ë
+B$ë
+B ë
+B
+ë
+Bë
+Bë
+Bë
+B
+ë
+Bë
+Bë
+B ë
+Aù×
+Añ×
+Aé×
+Aá×
+AÙ×
+AÑ×
+AÉ×
+AÁ×
+A¹×
+A±×
+A©×
+A¡×
+A×
+A×
+A×
+A×
+As®Ac®AS®AC®A3®A#®A®A®@ç\)@Ç\)@§\)@\)@NžR@žR?p€>k
+B|õÃBxõÃBtõÃBpõÃBlõÃBhõÃBdõÃB`õÃB\õÃBXõÃBTõÃBPõÃBLõÃBHõÃBDõÃB@õÃB<õÃB8õÃB4õÃB0õÃB,õÃB(õÃB$õÃB õÃB
+õÃBõÃBõÃBõÃB
+õÃBõÃBõÃB õÃAùë
+Añë
+Aéë
+Aáë
+AÙë
+AÑë
+AÉë
+AÁë
+A¹ë
+A±ë
+A©ë
+A¡ë
+Aë
+Aë
+Aë
+Aë
+As×
+Ac×
+AS×
+AC×
+A3×
+A#×
+A×
+A×
+@ç®@Ç®@§®@®@O\)@\)?žR>uÂB}  By  Bu  Bq  Bm  Bi  Be  Ba  B]  BY  BU  BQ  BM  BI  BE  BA  B=  B9  B5  B1  B-  B)  B%  B!  B
+  B  B  B  B
+  B	  B  B  Aú  Aò  Aê  Aâ  AÚ  AÒ  AÊ  AÂ  Aº  A²  Aª  A¢  A  A  A  A  At  Ad  AT  AD  A4  A$  A  A  @è  @È  @š  @  @P  @  ?   >  B}
+=By
+=Bu
+=Bq
+=Bm
+=Bi
+=Be
+=Ba
+=B]
+=BY
+=BU
+=BQ
+=BM
+=BI
+=BE
+=BA
+=B=
+=B9
+=B5
+=B1
+=B-
+=B)
+=B%
+=B!
+=B
+
+=B
+=B
+=B
+=B
+=B	
+=B
+=B
+=Aú{Aò{Aê{Aâ{AÚ{AÒ{AÊ{AÂ{Aº{A²{Aª{A¢{A{A{A{A{At(öAd(öAT(öAD(öA4(öA$(öA(öA(ö@èQì@ÈQì@šQì@Qì@P£×@£×?¡G®>
+
+žB}{By{Bu{Bq{Bm{Bi{Be{Ba{B]{BY{BU{BQ{BM{BI{BE{BA{B={B9{B5{B1{B-{B){B%{B!{B
+{B{B{B{B
+{B	{B{B{Aú(öAò(öAê(öAâ(öAÚ(öAÒ(öAÊ(öAÂ(öAº(öA²(öAª(öA¢(öA(öA(öA(öA(öAtQìAdQìATQìADQìA4QìA$QìAQìAQì@è£×@È£×@š£×@£×@QG®@G®?¢\>=qB}
+žBy
+žBu
+žBq
+žBm
+žBi
+žBe
+žBa
+žB]
+žBY
+žBU
+žBQ
+žBM
+žBI
+žBE
+žBA
+žB=
+žB9
+žB5
+žB1
+žB-
+žB)
+žB%
+žB!
+žB
+
+žB
+žB
+žB
+žB
+
+žB	
+žB
+žB
+žAú=qAò=qAê=qAâ=qAÚ=qAÒ=qAÊ=qAÂ=qAº=qA²=qAª=qA¢=qA=qA=qA=qA=qAtzáAdzáATzáADzáA4záA$záAzáAzá@èõÃ@ÈõÃ@šõÃ@õÃ@Që
+@ë
+?£×
+>\)B}(öBy(öBu(öBq(öBm(öBi(öBe(öBa(öB](öBY(öBU(öBQ(öBM(öBI(öBE(öBA(öB=(öB9(öB5(öB1(öB-(öB)(öB%(öB!(öB
+(öB(öB(öB(öB
+(öB	(öB(öB(öAúQìAòQìAêQìAâQìAÚQìAÒQìAÊQìAÂQìAºQìA²QìAªQìA¢QìAQìAQìAQìAQìAt£×Ad£×AT£×AD£×A4£×A$£×A£×A£×@éG®@ÉG®@©G®@G®@R\@\?¥
+ž>záB}33By33Bu33Bq33Bm33Bi33Be33Ba33B]33BY33BU33BQ33BM33BI33BE33BA33B=33B933B533B133B-33B)33B%33B!33B
+33B33B33B33B
+33B	33B33B33AúffAòffAêffAâffAÚffAÒffAÊffAÂffAºffA²ffAªffA¢ffAffAffAffAffAtÌÍAdÌÍATÌÍADÌÍA4ÌÍA$ÌÍAÌÍAÌÍ@é@É@©@@S33@33?Šff>B}=qBy=qBu=qBq=qBm=qBi=qBe=qBa=qB]=qBY=qBU=qBQ=qBM=qBI=qBE=qBA=qB==qB9=qB5=qB1=qB-=qB)=qB%=qB!=qB
+=qB=qB=qB=qB
+=qB	=qB=qB=qAúzáAòzáAêzáAâzáAÚzáAÒzáAÊzáAÂzáAºzáA²záAªzáA¢záAzáAzáAzáAzáAtõÃAdõÃATõÃADõÃA4õÃA$õÃAõÃAõÃ@éë
+@Éë
+@©ë
+@ë
+@S×
+@×
+?§®>žRB}G®ByG®BuG®BqG®BmG®BiG®BeG®BaG®B]G®BYG®BUG®BQG®BMG®BIG®BEG®BAG®B=G®B9G®B5G®B1G®B-G®B)G®B%G®B!G®B
+G®BG®BG®BG®B
+G®B	G®BG®BG®Aú\Aò\Aê\Aâ\AÚ\AÒ\AÊ\AÂ\Aº\A²\Aª\A¢\A\A\A\A\Au
+žAe
+žAU
+žAE
+žA5
+žA%
+žA
+žA
+ž@ê=q@Ê=q@ª=q@=q@Tzá@zá?šõÂ>£×
+B}QìByQìBuQìBqQìBmQìBiQìBeQìBaQìB]QìBYQìBUQìBQQìBMQìBIQìBEQìBAQìB=QìB9QìB5QìB1QìB-QìB)QìB%QìB!QìB
+QìBQìBQìBQìB
+QìB	QìBQìBQìAú£×Aò£×Aê£×Aâ£×AÚ£×AÒ£×AÊ£×AÂ£×Aº£×A²£×Aª£×A¢£×A£×A£×A£×A£×AuG®AeG®AUG®AEG®A5G®A%G®AG®AG®@ê\@Ê\@ª\@\@U
+ž@
+ž?ª=q>šõÃB}\)By\)Bu\)Bq\)Bm\)Bi\)Be\)Ba\)B]\)BY\)BU\)BQ\)BM\)BI\)BE\)BA\)B=\)B9\)B5\)B1\)B-\)B)\)B%\)B!\)B
+\)B\)B\)B\)B
+\)B	\)B\)B\)AúžRAòžRAêžRAâžRAÚžRAÒžRAÊžRAÂžRAºžRA²žRAªžRA¢žRAžRAžRAžRAžRAup€Aep€AUp€AEp€A5p€A%p€Ap€Ap€@êáH@ÊáH@ªáH@áH@UÂ@Â?«
+>®{B}ffByffBuffBqffBmffBiffBeffBaffB]ffBYffBUffBQffBMffBIffBEffBAffB=ffB9ffB5ffB1ffB-ffB)ffB%ffB!ffB
+ffBffBffBffB
+ffB	ffBffBffAúÌÍAòÌÍAêÌÍAâÌÍAÚÌÍAÒÌÍAÊÌÍAÂÌÍAºÌÍA²ÌÍAªÌÍA¢ÌÍAÌÍAÌÍAÌÍAÌÍAuAeAUAEA5A%AA@ë33@Ë33@«33@33@Vff@ff?¬ÌÍ>³33B}p€Byp€Bup€Bqp€Bmp€Bip€Bep€Bap€B]p€BYp€BUp€BQp€BMp€BIp€BEp€BAp€B=p€B9p€B5p€B1p€B-p€B)p€B%p€B!p€B
+p€Bp€Bp€Bp€B
+p€B	p€Bp€Bp€AúáHAòáHAêáHAâáHAÚáHAÒáHAÊáHAÂáHAºáHA²áHAªáHA¢áHAáHAáHAáHAáHAuÂAeÂAUÂAEÂA5ÂA%ÂAÂAÂ@ë
+@Ë
+@«
+@
+@W
+>@
+>?®{>žQìB}záByzáBuzáBqzáBmzáBizáBezáBazáB]záBYzáBUzáBQzáBMzáBIzáBEzáBAzáB=záB9záB5záB1záB-záB)záB%záB!záB
+záBzáBzáBzáB
+záB	záBzáBzáAúõÃAòõÃAêõÃAâõÃAÚõÃAÒõÃAÊõÃAÂõÃAºõÃA²õÃAªõÃA¢õÃAõÃAõÃAõÃAõÃAuë
+Aeë
+AUë
+AEë
+A5ë
+A%ë
+Aë
+Aë
+@ë×
+@Ë×
+@«×
+@×
+@W®@®?¯\)>œp€B}
+By
+Bu
+Bq
+Bm
+Bi
+Be
+Ba
+B]
+BY
+BU
+BQ
+BM
+BI
+BE
+BA
+B=
+B9
+B5
+B1
+B-
+B)
+B%
+B!
+B
+
+B
+B
+B
+B
+
+B	
+B
+B
+Aû
+=Aó
+=Aë
+=Aã
+=AÛ
+=AÓ
+=AË
+=AÃ
+=A»
+=A³
+=A«
+=A£
+=A
+=A
+=A
+=A
+=Av{Af{AV{AF{A6{A&{A{A{@ì(ö@Ì(ö@¬(ö@(ö@XQì@Qì?°£×>Â\B}\By\Bu\Bq\Bm\Bi\Be\Ba\B]\BY\BU\BQ\BM\BI\BE\BA\B=\B9\B5\B1\B-\B)\B%\B!\B
+\B\B\B\B
+\B	\B\B\Aû
+žAó
+žAë
+žAã
+žAÛ
+žAÓ
+žAË
+žAÃ
+žA»
+žA³
+žA«
+žA£
+žA
+žA
+žA
+žA
+žAv=qAf=qAV=qAF=qA6=qA&=qA=qA=q@ìzá@Ìzá@¬zá@zá@XõÂ@õÂ?±ë
+>Ç®B}ByBuBqBmBiBeBaB]BYBUBQBMBIBEBAB=B9B5B1B-B)B%B!B
+BBBB
+B	BBAû33Aó33Aë33Aã33AÛ33AÓ33AË33AÃ33A»33A³33A«33A£33A33A33A33A33AvffAfffAVffAFffA6ffA&ffAffAff@ìÌÍ@ÌÌÍ@¬ÌÍ@ÌÍ@Y@?³33>ÌÌÍB}£×By£×Bu£×Bq£×Bm£×Bi£×Be£×Ba£×B]£×BY£×BU£×BQ£×BM£×BI£×BE£×BA£×B=£×B9£×B5£×B1£×B-£×B)£×B%£×B!£×B
+£×B£×B£×B£×B
+£×B	£×B£×B£×AûG®AóG®AëG®AãG®AÛG®AÓG®AËG®AÃG®A»G®A³G®A«G®A£G®AG®AG®AG®AG®Av\Af\AV\AF\A6\A&\A\A\@í
+ž@Í
+ž@­
+ž@
+ž@Z=q@=q?Žzá>Ñë
+B}®By®Bu®Bq®Bm®Bi®Be®Ba®B]®BY®BU®BQ®BM®BI®BE®BA®B=®B9®B5®B1®B-®B)®B%®B!®B
+®B®B®B®B
+®B	®B®B®Aû\)Aó\)Aë\)Aã\)AÛ\)AÓ\)AË\)AÃ\)A»\)A³\)A«\)A£\)A\)A\)A\)A\)AvžRAfžRAVžRAFžRA6žRA&žRAžRAžR@íp€@Íp€@­p€@p€@ZáH@áH?µÂ>×
+=B}žRByžRBužRBqžRBmžRBižRBežRBažRB]žRBYžRBUžRBQžRBMžRBIžRBEžRBAžRB=žRB9žRB5žRB1žRB-žRB)žRB%žRB!žRB
+žRBžRBžRBžRB
+žRB	žRBžRBžRAûp€Aóp€Aëp€Aãp€AÛp€AÓp€AËp€AÃp€A»p€A³p€A«p€A£p€Ap€Ap€Ap€Ap€AváHAfáHAVáHAFáHA6áHA&áHAáHAáH@íÂ@ÍÂ@­Â@Â@[
+@
+?·
+>>Ü(öB}ÂByÂBuÂBqÂBmÂBiÂBeÂBaÂB]ÂBYÂBUÂBQÂBMÂBIÂBEÂBAÂB=ÂB9ÂB5ÂB1ÂB-ÂB)ÂB%ÂB!ÂB
+ÂBÂBÂBÂB
+ÂB	ÂBÂBÂAû
+Aó
+Aë
+Aã
+AÛ
+AÓ
+AË
+AÃ
+A»
+A³
+A«
+A£
+A
+A
+A
+A
+Aw
+=Ag
+=AW
+=AG
+=A7
+=A'
+=A
+=A
+=@î{@Î{@®{@{@\(ö@
+(ö?žQì>áG®B}ÌÍByÌÍBuÌÍBqÌÍBmÌÍBiÌÍBeÌÍBaÌÍB]ÌÍBYÌÍBUÌÍBQÌÍBMÌÍBIÌÍBEÌÍBAÌÍB=ÌÍB9ÌÍB5ÌÍB1ÌÍB-ÌÍB)ÌÍB%ÌÍB!ÌÍB
+ÌÍBÌÍBÌÍBÌÍB
+ÌÍB	ÌÍBÌÍBÌÍAûAóAëAãAÛAÓAËAÃA»A³A«A£AAAAAw33Ag33AW33AG33A733A'33A33A33@îff@Îff@®ff@ff@\ÌÍ@
+ÌÍ?¹>æffB}×
+By×
+Bu×
+Bq×
+Bm×
+Bi×
+Be×
+Ba×
+B]×
+BY×
+BU×
+BQ×
+BM×
+BI×
+BE×
+BA×
+B=×
+B9×
+B5×
+B1×
+B-×
+B)×
+B%×
+B!×
+B
+×
+B×
+B×
+B×
+B
+×
+B	×
+B×
+B×
+Aû®Aó®Aë®Aã®AÛ®AÓ®AË®AÃ®A»®A³®A«®A£®A®A®A®A®Aw\)Ag\)AW\)AG\)A7\)A'\)A\)A\)@îžR@ÎžR@®žR@žR@]p€@
+p€?ºáH>ë
+B}áHByáHBuáHBqáHBmáHBiáHBeáHBaáHB]áHBYáHBUáHBQáHBMáHBIáHBEáHBAáHB=áHB9áHB5áHB1áHB-áHB)áHB%áHB!áHB
+áHBáHBáHBáHB
+áHB	áHBáHBáHAûÂAóÂAëÂAãÂAÛÂAÓÂAËÂAÃÂA»ÂA³ÂA«ÂA£ÂAÂAÂAÂAÂAw
+Ag
+AW
+AG
+A7
+A'
+A
+A
+@ï
+=@Ï
+=@¯
+=@
+=@^{@
+{?Œ(ö>ð£×B}ë
+Byë
+Buë
+Bqë
+Bmë
+Bië
+Beë
+Baë
+B]ë
+BYë
+BUë
+BQë
+BMë
+BIë
+BEë
+BAë
+B=ë
+B9ë
+B5ë
+B1ë
+B-ë
+B)ë
+B%ë
+B!ë
+B
+ë
+Bë
+Bë
+Bë
+B
+ë
+B	ë
+Bë
+Bë
+Aû×
+Aó×
+Aë×
+Aã×
+AÛ×
+AÓ×
+AË×
+AÃ×
+A»×
+A³×
+A«×
+A£×
+A×
+A×
+A×
+A×
+Aw®Ag®AW®AG®A7®A'®A®A®@ï\)@Ï\)@¯\)@\)@^žR@
+žR?œp€>õÂB}õÃByõÃBuõÃBqõÃBmõÃBiõÃBeõÃBaõÃB]õÃBYõÃBUõÃBQõÃBMõÃBIõÃBEõÃBAõÃB=õÃB9õÃB5õÃB1õÃB-õÃB)õÃB%õÃB!õÃB
+õÃBõÃBõÃBõÃB
+õÃB	õÃBõÃBõÃAûë
+Aóë
+Aëë
+Aãë
+AÛë
+AÓë
+AËë
+AÃë
+A»ë
+A³ë
+A«ë
+A£ë
+Aë
+Aë
+Aë
+Aë
+Aw×
+Ag×
+AW×
+AG×
+A7×
+A'×
+A×
+A×
+@ï®@Ï®@¯®@®@_\)@\)?ŸžR>úáHB~  Bz  Bv  Br  Bn  Bj  Bf  Bb  B^  BZ  BV  BR  BN  BJ  BF  BB  B>  B:  B6  B2  B.  B*  B&  B"  B
+  B  B  B  B  B
+  B  B  Aü  Aô  Aì  Aä  AÜ  AÔ  AÌ  AÄ  AŒ  AŽ  A¬  A€  A  A  A  A  Ax  Ah  AX  AH  A8  A(  A  A  @ð  @Ð  @°  @  @`  @   ?À  ?   B~
+=Bz
+=Bv
+=Br
+=Bn
+=Bj
+=Bf
+=Bb
+=B^
+=BZ
+=BV
+=BR
+=BN
+=BJ
+=BF
+=BB
+=B>
+=B:
+=B6
+=B2
+=B.
+=B*
+=B&
+=B"
+=B
+
+=B
+=B
+=B
+=B
+=B
+
+=B
+=B
+=Aü{Aô{Aì{Aä{AÜ{AÔ{AÌ{AÄ{AŒ{AŽ{A¬{A€{A{A{A{A{Ax(öAh(öAX(öAH(öA8(öA((öA(öA(ö@ðQì@ÐQì@°Qì@Qì@`£×@ £×?ÁG®?\B~{Bz{Bv{Br{Bn{Bj{Bf{Bb{B^{BZ{BV{BR{BN{BJ{BF{BB{B>{B:{B6{B2{B.{B*{B&{B"{B
+{B{B{B{B{B
+{B{B{Aü(öAô(öAì(öAä(öAÜ(öAÔ(öAÌ(öAÄ(öAŒ(öAŽ(öA¬(öA€(öA(öA(öA(öA(öAxQìAhQìAXQìAHQìA8QìA(QìAQìAQì@ð£×@Ð£×@°£×@£×@aG®@!G®?Â\?
+žB~
+žBz
+žBv
+žBr
+žBn
+žBj
+žBf
+žBb
+žB^
+žBZ
+žBV
+žBR
+žBN
+žBJ
+žBF
+žBB
+žB>
+žB:
+žB6
+žB2
+žB.
+žB*
+žB&
+žB"
+žB
+
+žB
+žB
+žB
+žB
+žB
+
+žB
+žB
+žAü=qAô=qAì=qAä=qAÜ=qAÔ=qAÌ=qAÄ=qAŒ=qAŽ=qA¬=qA€=qA=qA=qA=qA=qAxzáAhzáAXzáAHzáA8záA(záAzáAzá@ðõÂ@ÐõÂ@°õÂ@õÂ@aë
+@!ë
+?Ã×
+?®B~(öBz(öBv(öBr(öBn(öBj(öBf(öBb(öB^(öBZ(öBV(öBR(öBN(öBJ(öBF(öBB(öB>(öB:(öB6(öB2(öB.(öB*(öB&(öB"(öB
+(öB(öB(öB(öB(öB
+(öB(öB(öAüQìAôQìAìQìAäQìAÜQìAÔQìAÌQìAÄQìAŒQìAŽQìA¬QìA€QìAQìAQìAQìAQìAx£×Ah£×AX£×AH£×A8£×A(£×A£×A£×@ñG®@ÑG®@±G®@G®@b\@"\?Å
+ž?
+=qB~33Bz33Bv33Br33Bn33Bj33Bf33Bb33B^33BZ33BV33BR33BN33BJ33BF33BB33B>33B:33B633B233B.33B*33B&33B"33B
+33B33B33B33B33B
+33B33B33AüffAôffAìffAäffAÜffAÔffAÌffAÄffAŒffAŽffA¬ffA€ffAffAffAffAffAxÌÍAhÌÍAXÌÍAHÌÍA8ÌÍA(ÌÍAÌÍAÌÍ@ñ@Ñ@±@@c33@#33?Æff?
+ÌÍB~=qBz=qBv=qBr=qBn=qBj=qBf=qBb=qB^=qBZ=qBV=qBR=qBN=qBJ=qBF=qBB=qB>=qB:=qB6=qB2=qB.=qB*=qB&=qB"=qB
+=qB=qB=qB=qB=qB
+=qB=qB=qAüzáAôzáAìzáAäzáAÜzáAÔzáAÌzáAÄzáAŒzáAŽzáA¬záA€záAzáAzáAzáAzáAxõÃAhõÃAXõÃAHõÃA8õÃA(õÃAõÃAõÃ@ñë
+@Ñë
+@±ë
+@ë
+@c×
+@#×
+?Ç®?\)B~G®BzG®BvG®BrG®BnG®BjG®BfG®BbG®B^G®BZG®BVG®BRG®BNG®BJG®BFG®BBG®B>G®B:G®B6G®B2G®B.G®B*G®B&G®B"G®B
+G®BG®BG®BG®BG®B
+G®BG®BG®Aü\Aô\Aì\Aä\AÜ\AÔ\AÌ\AÄ\AŒ\AŽ\A¬\A€\A\A\A\A\Ay
+žAi
+žAY
+žAI
+žA9
+žA)
+žA
+žA	
+ž@ò=q@Ò=q@²=q@=q@dzá@$zá?ÈõÂ?ë
+B~QìBzQìBvQìBrQìBnQìBjQìBfQìBbQìB^QìBZQìBVQìBRQìBNQìBJQìBFQìBBQìB>QìB:QìB6QìB2QìB.QìB*QìB&QìB"QìB
+QìBQìBQìBQìBQìB
+QìBQìBQìAü£×Aô£×Aì£×Aä£×AÜ£×AÔ£×AÌ£×AÄ£×AŒ£×AŽ£×A¬£×A€£×A£×A£×A£×A£×AyG®AiG®AYG®AIG®A9G®A)G®AG®A	G®@ò\@Ò\@²\@\@e
+ž@%
+ž?Ê=p?záB~\)Bz\)Bv\)Br\)Bn\)Bj\)Bf\)Bb\)B^\)BZ\)BV\)BR\)BN\)BJ\)BF\)BB\)B>\)B:\)B6\)B2\)B.\)B*\)B&\)B"\)B
+\)B\)B\)B\)B\)B
+\)B\)B\)AüžRAôžRAìžRAäžRAÜžRAÔžRAÌžRAÄžRAŒžRAŽžRA¬žRA€žRAžRAžRAžRAžRAyp€Aip€AYp€AIp€A9p€A)p€Ap€A	p€@òáH@ÒáH@²áH@áH@eÂ@%Â?Ë
+
+?
+=B~ffBzffBvffBrffBnffBjffBfffBbffB^ffBZffBVffBRffBNffBJffBFffBBffB>ffB:ffB6ffB2ffB.ffB*ffB&ffB"ffB
+ffBffBffBffBffB
+ffBffBffAüÌÍAôÌÍAìÌÍAäÌÍAÜÌÍAÔÌÍAÌÌÍAÄÌÍAŒÌÍAŽÌÍA¬ÌÍA€ÌÍAÌÍAÌÍAÌÍAÌÍAyAiAYAIA9A)AA	@ó33@Ó33@³33@33@fff@&ff?ÌÌÍ?B~p€Bzp€Bvp€Brp€Bnp€Bjp€Bfp€Bbp€B^p€BZp€BVp€BRp€BNp€BJp€BFp€BBp€B>p€B:p€B6p€B2p€B.p€B*p€B&p€B"p€B
+p€Bp€Bp€Bp€Bp€B
+p€Bp€Bp€AüáHAôáHAìáHAäáHAÜáHAÔáHAÌáHAÄáHAŒáHAŽáHA¬áHA€áHAáHAáHAáHAáHAyÂAiÂAYÂAIÂA9ÂA)ÂAÂA	Â@ó
+@Ó
+@³
+@
+@g
+>@'
+>?Î{?
+(öB~záBzzáBvzáBrzáBnzáBjzáBfzáBbzáB^záBZzáBVzáBRzáBNzáBJzáBFzáBBzáB>záB:záB6záB2záB.záB*záB&záB"záB
+záBzáBzáBzáBzáB
+záBzáBzáAüõÃAôõÃAìõÃAäõÃAÜõÃAÔõÃAÌõÃAÄõÃAŒõÃAŽõÃA¬õÃA€õÃAõÃAõÃAõÃAõÃAyë
+Aië
+AYë
+AIë
+A9ë
+A)ë
+Aë
+A	ë
+@ó×
+@Ó×
+@³×
+@×
+@g®@'®?Ï\)?
+žRB~
+Bz
+Bv
+Br
+Bn
+Bj
+Bf
+Bb
+B^
+BZ
+BV
+BR
+BN
+BJ
+BF
+BB
+B>
+B:
+B6
+B2
+B.
+B*
+B&
+B"
+B
+
+B
+B
+B
+B
+B
+
+B
+B
+Aý
+=Aõ
+=Aí
+=Aå
+=AÝ
+=AÕ
+=AÍ
+=AÅ
+=Aœ
+=Aµ
+=A­
+=A¥
+=A
+=A
+=A
+=A
+
+=Az{Aj{AZ{AJ{A:{A*{A{A
+{@ô(ö@Ô(ö@Ž(ö@(ö@hQì@(Qì?Ð£×?!G®                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|
+=Bx  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|{Bx
+=Bx
+=Bt  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|(öBx
+žBx{Bt
+=Bp
+=Bl  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|33Bx(öBx(öBt
+žBp{Bl
+=Bl
+=Bh  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|=qBx=qBx33Bt(öBp(öBl
+žBl{Bh
+=Bd
+=Bd  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|QìBxG®Bx=qBt=qBp33Bl(öBl(öBh
+žBd{Bd
+=B`
+=B\  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|\)Bx\)BxQìBtG®Bp=qBl=qBl33Bh(öBd(öBd
+žB`{B\
+=BX
+=BX  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|p€BxffBx\)Bt\)BpQìBlG®Bl=qBh=qBd33Bd(öB`(öB\
+žBX{BX
+=BT
+=BP  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|záBxp€Bxp€BtffBp\)Bl\)BlQìBhG®Bd=qBd=qB`33B\(öBX(öBX
+žBT{BP
+=BP
+=BL  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|
+Bx
+BxzáBtp€Bpp€BlffBl\)Bh\)BdQìBdG®B`=qB\=qBX33BX(öBT(öBP
+žBP{BL
+=BH
+=BH  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|Bx\Bx
+Bt
+BpzáBlp€Blp€BhffBd\)Bd\)B`QìB\G®BX=qBX=qBT33BP(öBP(öBL
+žBH{BH
+=BD
+=B@  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|£×Bx£×BxBt\Bp
+Bl
+BlzáBhp€Bdp€BdffB`\)B\\)BXQìBXG®BT=qBP=qBP33BL(öBH(öBH
+žBD{B@
+=B<
+=B<  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|žRBx®Bx£×Bt£×BpBl\Bl
+Bh
+BdzáBdp€B`p€B\ffBX\)BX\)BTQìBPG®BP=qBL=qBH33BH(öBD(öB@
+žB<{B<
+=B8
+=B4  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ÂBxžRBxžRBt®Bp£×Bl£×BlBh\Bd
+Bd
+B`záB\p€BXp€BXffBT\)BP\)BPQìBLG®BH=qBH=qBD33B@(öB<(öB<
+žB8{B4
+=B4
+=B0  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|×
+BxÌÍBxÂBtžRBpžRBl®Bl£×Bh£×BdBd\B`
+B\
+BXzáBXp€BTp€BPffBP\)BL\)BHQìBHG®BD=qB@=qB<33B<(öB8(öB4
+žB4{B0
+=B,
+=B(  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|áHBx×
+Bx×
+BtÌÍBpÂBlžRBlžRBh®Bd£×Bd£×B`B\\BX
+BX
+BTzáBPp€BPp€BLffBH\)BH\)BDQìB@G®B<=qB<=qB833B4(öB4(öB0
+žB,{B(
+=B(
+=B$  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ë
+Bxë
+BxáHBt×
+Bp×
+BlÌÍBlÂBhžRBdžRBd®B`£×B\£×BXBX\BT
+BP
+BPzáBLp€BHp€BHffBD\)B@\)B<QìB<G®B8=qB4=qB433B0(öB,(öB(
+žB({B$
+=B 
+=B   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}  BxõÃBxë
+Btë
+BpáHBl×
+Bl×
+BhÌÍBdÂBdžRB`žRB\®BX£×BX£×BTBP\BP
+BL
+BHzáBHp€BDp€B@ffB<\)B<\)B8QìB4G®B4=qB0=qB,33B((öB((öB$
+žB {B 
+=B
+
+=B  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}
+=By  By  BtõÃBpë
+Blë
+BláHBh×
+Bd×
+BdÌÍB`ÂB\žRBXžRBX®BT£×BP£×BPBL\BH
+BH
+BDzáB@p€B<p€B<ffB8\)B4\)B4QìB0G®B,=qB(=qB(33B$(öB (öB 
+žB
+{B
+=B
+=B  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}
+žBy{By
+=Bu  Bq  BlõÃBlë
+Bhë
+BdáHBd×
+B`×
+B\ÌÍBXÂBXžRBTžRBP®BP£×BL£×BHBH\BD
+B@
+B<záB<p€B8p€B4ffB4\)B0\)B,QìB(G®B(=qB$=qB 33B (öB
+(öB
+žB{B
+=B
+=B
+  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}(öBy
+žBy
+žBu{Bq
+=Bm  Bm  BhõÃBdë
+Bdë
+B`áHB\×
+BX×
+BXÌÍBTÂBPžRBPžRBL®BH£×BH£×BDB@\B<
+B<
+B8záB4p€B4p€B0ffB,\)B(\)B(QìB$G®B =qB =qB
+33B(öB(öB
+žB{B
+
+=B
+
+=B  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}33By33By(öBu
+žBq
+žBm{Bm
+=Bi  Be  BdõÃB`ë
+B\ë
+BXáHBX×
+BT×
+BPÌÍBPÂBLžRBHžRBH®BD£×B@£×B<B<\B8
+B4
+B4záB0p€B,p€B(ffB(\)B$\)B QìB G®B
+=qB=qB33B(öB(öB
+
+žB
+{B
+=B
+=B  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}G®By=qBy33Bu33Bq(öBm
+žBm
+žBi{Be
+=Be  Ba  B\õÃBXë
+BXë
+BTáHBP×
+BP×
+BLÌÍBHÂBHžRBDžRB@®B<£×B<£×B8B4\B4
+B0
+B,záB(p€B(p€B$ffB \)B \)B
+QìBG®B=qB=qB33B
+(öB
+(öB
+žB{B
+=B 
+=Aø  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}QìByQìByG®Bu=qBq33Bm33Bm(öBi
+žBe
+žBe{Ba
+=B]  BY  BXõÃBTë
+BPë
+BPáHBL×
+BH×
+BHÌÍBDÂB@žRB<žRB<®B8£×B4£×B4B0\B,
+B(
+B(záB$p€B p€B ffB
+\)B\)BQìBG®B=qB
+=qB
+33B(öB(öB
+žB {Aø{Að{Að  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ffBy\)ByQìBuQìBqG®Bm=qBm33Bi33Be(öBe
+žBa
+žB]{BY
+=BY  BU  BPõÃBPë
+BLë
+BHáHBH×
+BD×
+B@ÌÍB<ÂB<žRB8žRB4®B4£×B0£×B,B(\B(
+B$
+B záB p€B
+p€BffB\)B\)BQìB
+G®B
+=qB=qB33B(öB (öAø=qAð(öAð{Aè{Aà  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}p€ByffByffBu\)BqQìBmQìBmG®Bi=qBe33Be33Ba(öB]
+žBY
+žBY{BU
+=BQ  BQ  BLõÃBHë
+BHë
+BDáHB@×
+B<×
+B<ÌÍB8ÂB4žRB4žRB0®B,£×B(£×B(B$\B 
+B 
+B
+záBp€Bp€BffB\)B
+\)B
+QìBG®B=qB=qB 33AøQìAðQìAð=qAè(öAà{Aà{AØ  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}
+ByzáByp€BuffBqffBm\)BmQìBiQìBeG®Be=qBa33B]33BY(öBY
+žBU
+žBQ{BQ
+=BM  BI  BHõÃBDë
+B@ë
+B<áHB<×
+B8×
+B4ÌÍB4ÂB0žRB,žRB(®B(£×B$£×B B \B
+
+B
+BzáBp€Bp€B
+ffB
+\)B\)BQìBG®B =qAøzáAðffAðQìAèQìAà=qAà(öAØ{AÐ{AÈ  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}\By
+By
+BuzáBqp€BmffBmffBi\)BeQìBeQìBaG®B]=qBY33BY33BU(öBQ
+žBQ
+žBM{BI
+=BI  BE  B@õÃB<ë
+B<ë
+B8áHB4×
+B4×
+B0ÌÍB,ÂB(žRB(žRB$®B £×B £×B
+B\B
+B
+BzáB
+p€B
+p€BffB\)B\)B QìAø\AðzáAðzáAèffAàQìAàQìAØ=qAÐ(öAÈ{AÈ{AÀ  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ByBy\Bu
+Bq
+BmzáBmp€BiffBeffBe\)BaQìB]QìBYG®BY=qBU33BQ33BQ(öBM
+žBI
+žBI{BE
+=BA  B=  B<õÃB8ë
+B4ë
+B4áHB0×
+B,×
+B(ÌÍB(ÂB$žRB žRB ®B
+£×B£×BB\B
+B
+
+B
+záBp€Bp€BffB \)AøžRAð£×Að\AèzáAàzáAàffAØQìAÐQìAÈ=qAÈ(öAÀ{Až{Až  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}®By£×ByBuBq\Bm
+Bm
+BizáBep€BeffBaffB]\)BYQìBYQìBUG®BQ=qBQ33BM33BI(öBI
+žBE
+žBA{B=
+=B=  B9  B4õÃB4ë
+B0ë
+B,áHB(×
+B(×
+B$ÌÍB ÂB žRB
+žRB®B£×B£×BB
+\B
+
+B
+BzáBp€B p€AøÌÍAðžRAðžRAè£×Aà\AàzáAØzáAÐffAÈQìAÈQìAÀ=qAž(öAž{A°{Aš  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}žRBy®By®Bu£×BqBmBm\Bi
+Be
+BezáBap€B]ffBYffBY\)BUQìBQQìBQG®BM=qBI33BI33BE(öBA
+žB=
+žB={B9
+=B5  B5  B0õÃB,ë
+B(ë
+B(áHB$×
+B ×
+B ÌÍB
+ÂBžRBžRB®B£×B
+£×B
+B\B
+B
+B záAøáHAðáHAðÌÍAèžRAàžRAà£×AØ\AÐzáAÈzáAÈffAÀQìAžQìAž=qA°(öAš{Aš{A   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ÌÍByÂByžRBu®Bq®Bm£×BmBiBe\Be
+Ba
+B]záBYp€BYffBUffBQ\)BQQìBMQìBIG®BI=qBE33BA33B=(öB=
+žB9
+žB5{B5
+=B1  B-  B(õÃB(ë
+B$ë
+B áHB ×
+B
+×
+BÌÍBÂBžRBžRB
+®B
+£×B£×BB\B 
+Aù
+=AðõÃAðáHAèáHAàÌÍAàžRAØžRAÐ£×AÈ\AÈzáAÀzáAžffAžQìA°QìAš=qAš(öA {A{A  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}×
+ByÌÍByÌÍBuÂBqžRBm®Bm®Bi£×BeBeBa\B]
+BY
+BYzáBUp€BQffBQffBM\)BIQìBIQìBEG®BA=qB=33B=33B9(öB5
+žB5
+žB1{B-
+=B)  B)  B$õÃB ë
+B ë
+B
+áHB×
+B×
+BÌÍBÂB
+žRB
+žRB®B£×B£×B Aù
+žAñ
+=Añ
+=AèõÃAàáHAàáHAØÌÍAÐžRAÈžRAÈ£×AÀ\AžzáAžzáA°ffAšQìAšQìA =qA(öA{A{A  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}áHByáHBy×
+BuÌÍBqÌÍBmÂBmžRBi®Be®Be£×BaB]BY\BY
+BU
+BQzáBQp€BMffBIffBI\)BEQìBAQìB=G®B==qB933B533B5(öB1
+žB-
+žB){B)
+=B%  B!  B õÃB
+ë
+Bë
+BáHB×
+B×
+B
+ÌÍB
+ÂBžRBžRB®B £×AùG®Añ33Añ
+žAé
+=Aá
+=AàõÃAØáHAÐáHAÈÌÍAÈžRAÀžRAž£×Až\A°záAšzáAšffA QìAQìA=qA(öA{A{A  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}õÃByë
+ByáHBuáHBq×
+BmÌÍBmÌÍBiÂBežRBe®Ba®B]£×BYBYBU\BQ
+BQ
+BMzáBIp€BIffBEffBA\)B=QìB=QìB9G®B5=qB533B133B-(öB)
+žB)
+žB%{B!
+=B!  B
+  BõÃBë
+Bë
+BáHB
+×
+B
+×
+BÌÍBÂBžRB žRAù\)AñG®AñG®Aé33Aá
+žAá
+=AÙ
+=AÐõÃAÈáHAÈáHAÀÌÍAžžRAžžRA°£×Aš\AšzáA záAffAQìAQìA=qA(öA{Ap(öA`  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~  Bz  ByõÃBuë
+BqáHBmáHBm×
+BiÌÍBeÌÍBeÂBažRB]®BY®BY£×BUBQBQ\BM
+BI
+BIzáBEp€BAffB=ffB=\)B9QìB5QìB5G®B1=qB-33B)33B)(öB%
+žB!
+žB!{B
+
+=B  B  BõÃBë
+B
+ë
+B
+áHB×
+B×
+BÌÍB ÂAùp€Añp€Añ\)AéG®AáG®Aá33AÙ
+žAÑ
+=AÉ
+=AÈõÃAÀáHAžáHAžÌÍA°žRAšžRAš£×A \AzáAzáAffAQìAQìA=qApQìA`(öAP(öAP  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~{Bz
+=Bz  Bv  BqõÃBmë
+BmáHBiáHBe×
+BeÌÍBaÌÍB]ÂBYžRBY®BU®BQ£×BQBMBI\BI
+BE
+BAzáB=p€B=ffB9ffB5\)B5QìB1QìB-G®B)=qB)33B%33B!(öB!
+žB
+
+žB{B
+=B  B  B
+õÃB
+ë
+Bë
+BáHB×
+B ×
+AùAñ
+Añp€Aép€Aá\)AáG®AÙG®AÑ33AÉ
+žAÉ
+=AÁ
+=AžõÃAžáHA°áHAšÌÍAšžRA žRA£×A\AzáAzáAffAQìAp£×A`záAPQìAP(öA@(öA0  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~
+žBz{Bz{Bv
+=Br  Bn  BmõÃBië
+BeáHBeáHBa×
+B]ÌÍBYÌÍBYÂBUžRBQ®BQ®BM£×BIBIBE\BA
+B=
+B=záB9p€B5ffB5ffB1\)B-QìB)QìB)G®B%=qB!33B!33B
+(öB
+žB
+žB{B
+=B
+  B
+  BõÃBë
+Bë
+B áHAù®Añ®AñAé
+Aáp€Aáp€AÙ\)AÑG®AÉG®AÉ33AÁ
+žA¹
+=A¹
+=A°õÃAšáHAšáHA ÌÍAžRAžRA£×A\AzáAzáApÌÍA`£×AP£×APzáA@QìA0(öA0(öA   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~(öBz(öBz
+žBv{Br{Bn
+=Bn  Bj  BeõÃBeë
+BaáHB]áHBY×
+BYÌÍBUÌÍBQÂBQžRBM®BI®BI£×BEBAB=\B=
+B9
+B5záB5p€B1ffB-ffB)\)B)QìB%QìB!G®B!=qB
+33B33B(öB
+žB
+žB
+{B
+=B	  B  BõÃB ë
+Aù×
+AñÂAñ®Aé®AáAá
+AÙp€AÑp€AÉ\)AÉG®AÁG®A¹33A¹
+žA±
+=A©
+=AšõÃA áHAáHAÌÍAžRAžRA£×A\ApõÃA`õÃAPÌÍAP£×A@£×A0záA0QìA (öA(öA  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~=qBz33Bz(öBv(öBr
+žBn{Bn{Bj
+=Bf  Bf  BaõÃB]ë
+BYáHBYáHBU×
+BQÌÍBQÌÍBMÂBIžRBI®BE®BA£×B=B=B9\B5
+B5
+B1záB-p€B)ffB)ffB%\)B!QìB!QìB
+G®B=qB33B33B(öB
+
+žB
+
+žB	{B
+=B  B  Aùë
+Añ×
+Añ×
+AéÂAá®Aá®AÙAÑ
+AÉp€AÉp€AÁ\)A¹G®A¹G®A±33A©
+žA©
+=A¡
+=AõÃAáHAáHAÌÍAžRAžRAqG®Aa
+žAPõÃAPõÃA@ÌÍA0£×A0£×A záAQìA(öA (ö@à  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~G®BzG®Bz=qBv33Br(öBn(öBn
+žBj{Bf{Bf
+=Bb  B^  BYõÃBYë
+BUáHBQáHBQ×
+BMÌÍBIÌÍBIÂBEžRBA®B=®B=£×B9B5B5\B1
+B-
+B)záB)p€B%ffB!ffB!\)B
+QìBQìBG®B=qB33B
+33B
+(öB	
+žB
+žB{B
+=Aú  Aò  Añë
+Aé×
+Aá×
+AáÂAÙ®AÑ®AÉAÉ
+AÁp€A¹p€A¹\)A±G®A©G®A©33A¡
+žA
+=A
+=AõÃAáHAáHAÌÍAqp€Aap€AQG®AQ
+žA@õÃA0õÃA0ÌÍA £×A£×AzáA Qì@àQì@ÀQì@À  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~\)BzQìBzG®BvG®Br=qBn33Bn(öBj(öBf
+žBf{Bb{B^
+=BZ  BZ  BUõÃBQë
+BQáHBMáHBI×
+BIÌÍBEÌÍBAÂB=žRB=®B9®B5£×B5B1B-\B)
+B)
+B%záB!p€B!ffB
+ffB\)BQìBQìBG®B
+=qB
+33B	33B(öB
+žB
+žAú(öAò{Aò  Aê  Aáë
+Aá×
+AÙ×
+AÑÂAÉ®AÉ®AÁA¹
+A¹p€A±p€A©\)A©G®A¡G®A33A
+žA
+=A
+=AõÃAáHAqÂAaAQp€AQp€AAG®A1
+žA0õÃA õÃAÌÍA£×A £×@àõÃ@À£×@ÀQì@ Qì@  ¿  ¿  ¿  ¿  ¿  ¿  B~ffBz\)Bz\)BvQìBrG®BnG®Bn=qBj33Bf(öBf(öBb
+žB^{BZ{BZ
+=BV  BR  BQõÃBMë
+BIáHBIáHBE×
+BAÌÍB=ÌÍB=ÂB9žRB5®B5®B1£×B-B)B)\B%
+B!
+B!záB
+p€BffBffB\)BQìB
+QìB
+G®B	=qB33B33B(öAú=qAò=qAò(öAê{Aâ  Aâ  AÙë
+AÑ×
+AÉ×
+AÉÂAÁ®A¹®A¹A±
+A©p€A©p€A¡\)AG®AG®A33A
+žA
+=A
+=Aqë
+AaÂAQÂAQAAp€A1p€A1G®A!
+žAõÃAõÃA ÌÍ@áG®@ÁG®@ÀõÃ@ £×@Qì@Qì@@  ¿  ¿  ¿  ¿  B~záBzp€BzffBv\)Br\)BnQìBnG®BjG®Bf=qBf33Bb(öB^(öBZ
+žBZ{BV{BR
+=BR  BN  BIõÃBIë
+BEáHBAáHB=×
+B=ÌÍB9ÌÍB5ÂB5žRB1®B-®B)£×B)B%B!\B!
+B
+
+BzáBp€BffBffB
+\)B
+QìB	QìBG®B=qB33AúffAòQìAò=qAê=qAâ(öAâ{AÚ  AÒ  AÉë
+AÉ×
+AÁ×
+A¹ÂA¹®A±®A©A©
+A¡p€Ap€A\)AG®AG®A33A
+žAr{Ab{AQë
+AQÂAAÂA1A1p€A!p€AG®A
+žA õÃ@áë
+@Á@ÁG®@¡G®@õÃ@£×@@£×@ £×?  ¿  ¿  B~
+BzzáBzzáBvp€BrffBn\)Bn\)BjQìBfG®BfG®Bb=qB^33BZ(öBZ(öBV
+žBR{BR{BN
+=BJ  BJ  BEõÃBAë
+B=áHB=áHB9×
+B5ÌÍB5ÌÍB1ÂB-žRB)®B)®B%£×B!B!B
+\B
+B
+BzáBp€B
+ffB
+ffB	\)BQìBQìBG®AúzáAòffAòffAêQìAâ=qAâ=qAÚ(öAÒ{AÊ  AÊ  AÁë
+A¹×
+A¹×
+A±ÂA©®A©®A¡A
+Ap€Ap€A\)AG®AG®ArffAb=qAR{AR{AAë
+A1ÂA1ÂA!Ap€Ap€AG®@â=q@Áë
+@Áë
+@¡@G®@G®@Aë
+@G®?G®?G®    ¿  ¿  Bz
+BvzáBrzáBnp€BnffBj\)Bf\)BfQìBbG®B^G®BZ=qBZ33BV(öBR(öBR
+žBN{BJ{BJ
+=BF  BB  B=õÃB=ë
+B9áHB5áHB5×
+B1ÌÍB-ÌÍB)ÂB)žRB%®B!®B!£×B
+BB\B
+B
+B
+záB
+p€B	ffBffB\)BQìAú£×Aò\AòzáAêffAâffAâQìAÚ=qAÒ=qAÊ(öAÊ{AÂ  Aº  A¹ë
+A±×
+A©×
+A©ÂA¡®A®AA
+Ap€Ap€A\)Ar\Ab\ARffAR=qAB{A2{A1ë
+A!ÂAÂAAp€@âáH@Â\@Â=q@¡ë
+@ë
+@@B\@\?×
+?\<#×
+¿  ¿  ¿  ¿  Br
+BnzáBnzáBjp€BfffBf\)Bb\)B^QìBZG®BZG®BV=qBR33BR(öBN(öBJ
+žBJ{BF{BB
+=B>  B>  B9õÃB5ë
+B5áHB1áHB-×
+B)ÌÍB)ÌÍB%ÂB!žRB!®B
+®B£×BBB\B
+
+B
+
+B	záBp€BffBffAúžRAò£×Aò£×Aê\AâzáAâffAÚffAÒQìAÊ=qAÊ=qAÂ(öAº{Aº  A²  A©ë
+A©×
+A¡×
+AÂA®A®AA
+Ap€AráHAbžRAR\AR\ABffA2=qA2{A"{Aë
+AÂAÂ@ã33@ÂáH@ÂáH@¢\@=q@ë
+@C×
+@33?
+
+ž?
+
+ž<õÂ¿  ¿  ¿  ¿  ¿  ¿  Bn
+BjzáBfzáBfp€BbffB^\)BZ\)BZQìBVG®BRG®BR=qBN33BJ(öBJ(öBF
+žBB{B>{B>
+=B:  B6  B5õÃB1ë
+B-áHB)áHB)×
+B%ÌÍB!ÌÍB!ÂB
+žRB®B®B£×BB
+B
+\B	
+B
+BzáBp€AúÌÍAòÌÍAòžRAê£×Aâ£×Aâ\AÚzáAÒffAÊffAÊQìAÂ=qAº=qAº(öA²{Aª  Aª  A¡ë
+A×
+A×
+AÂA®A®AAs
+=AbáHARáHARžRAB\A2\A2ffA"=qA{A{Aë
+@ã
+@Ã
+@Ã33@¢áH@áH@\@Dzá@×
+?®?ff=#×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bf
+BfzáBbzáB^p€BZffBZ\)BV\)BRQìBRG®BNG®BJ=qBJ33BF(öBB(öB>
+žB>{B:{B6
+=B6  B2  B-õÃB)ë
+B)áHB%áHB!×
+B!ÌÍB
+ÌÍBÂBžRB®B®B
+£×B
+B	B\B
+B
+AúõÃAòáHAòÌÍAêÌÍAâžRAâ£×AÚ£×AÒ\AÊzáAÊffAÂffAºQìAº=qA²=qAª(öAª{A¢  A  Aë
+A×
+A×
+AÂA®As\)Ac33AS
+=ARáHABáHA2žRA2\A"\AffA=qA{@ä(ö@Ã×
+@Ã
+@£
+@33@áH@EÂ@
+ž?õÃ?®=uÂ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bb
+B^záBZzáBZp€BVffBR\)BR\)BNQìBJG®BJG®BF=qBB33B>(öB>(öB:
+žB6{B6{B2
+=B.  B*  B)õÃB%ë
+B!áHB!áHB
+×
+BÌÍBÌÍBÂBžRB
+®B
+®B	£×BBB\Aû
+=Aó
+=AòõÃAêáHAâÌÍAâÌÍAÚžRAÒ£×AÊ£×AÊ\AÂzáAºffAºffA²QìAª=qAª=qA¢(öA{A  A  Aë
+A×
+A×
+As
+Ac\)AS\)AS33AC
+=A2áHA2áHA"žRA\A\Aff@äzá@Ä(ö@Ä(ö@£×
+@
+@
+@Fff@Â?
+?=q=\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BZ
+BZzáBVzáBRp€BRffBN\)BJ\)BJQìBFG®BBG®B>=qB>33B:(öB6(öB6
+žB2{B.{B*
+=B*  B&  B!õÃB!ë
+B
+áHBáHB×
+BÌÍBÌÍB
+ÂB
+žRB	®B®B£×BAû33Aó
+žAó
+=Aë
+=AâõÃAâáHAÚÌÍAÒÌÍAÊžRAÊ£×AÂ£×Aº\AºzáA²ffAªffAªQìA¢=qA=qA(öA{A  A  Aë
+As®Ac®AS
+AS\)AC\)A333A3
+=A"áHAáHAžRA\@å
+ž@ÄÌÍ@Äzá@€(ö@(ö@×
+@G
+=@
+=?ÌÍ?
+=žQì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BV
+BRzáBRzáBNp€BJffBJ\)BF\)BBQìB>G®B>G®B:=qB633B6(öB2(öB.
+žB*{B*{B&
+=B"  B"  B
+õÃBë
+BáHBáHB×
+B
+ÌÍB
+ÌÍB	ÂBžRB®B®AûG®Aó33Aó33Aë
+žAã
+=Aã
+=AÚõÃAÒáHAÊÌÍAÊÌÍAÂžRAº£×Aº£×A²\AªzáAªffA¢ffAQìA=qA=qA(öA{A  At  Ac×
+AS®AS®AC
+A3\)A3\)A#33A
+=AáHAáH@åp€@Å
+ž@Å
+ž@€ÌÍ@zá@(ö@HQì@®?{?{=ÌÌÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BR
+BNzáBJzáBJp€BFffBB\)B>\)B>QìB:G®B6G®B6=qB233B.(öB*(öB*
+žB&{B"{B"
+=B
+  B  BõÃBë
+BáHB
+áHB
+×
+B	ÌÍBÌÍBÂBžRAû\)Aó\)AóG®Aë33Aã33Aã
+žAÛ
+=AÓ
+=AÊõÃAÊáHAÂÌÍAºÌÍAºžRA²£×Aª£×Aª\A¢záAffAffAQìA=qA=qA(öAt(öAd  AT  AS×
+AC®A3®A3
+A#\)A\)A33A
+=@åÂ@ÅÂ@Åp€@¥
+ž@
+
+ž@ÌÍ@HõÃ@Qì?£×?\)=áG®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BJ
+BJzáBFzáBBp€B>ffB>\)B:\)B6QìB6G®B2G®B.=qB*33B*(öB&(öB"
+žB"{B
+{B
+=B  B  BõÃB
+ë
+B
+áHB	áHB×
+BÌÍBÌÍAû
+Aóp€Aó\)Aë\)AãG®Aã33AÛ33AÓ
+žAË
+=AË
+=AÂõÃAºáHAºÌÍA²ÌÍAªžRAª£×A¢£×A\AzáAffAffAQìA=qAtzáAdQìAT(öAT  AD  A3×
+A3®A#®A
+A\)A\)@æff@Æ{@ÅÂ@¥Â@
+p€@
+
+ž@J=q@	?ë
+?£×>
+ž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BF
+BBzáB>záB>p€B:ffB6\)B6\)B2QìB.G®B*G®B*=qB&33B"(öB"(öB
+
+žB{B{B
+=B  B  B
+õÃB	ë
+BáHBáHB×
+AûAóAó
+Aëp€Aã\)Aã\)AÛG®AÓ33AË33AË
+žAÃ
+=A»
+=AºõÃA²áHAªÌÍAªÌÍA¢žRA£×A£×A\AzáAffAffAt£×AdzáATzáATQìAD(öA4  A4  A#×
+A®A®A
+@æžR@ÆžR@Æff@Š{@
+Â@
+Â@JáH@
+=q?zá?33>\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B>
+B>záB:záB6p€B6ffB2\)B.\)B*QìB*G®B&G®B"=qB"33B
+(öB(öB
+žB{B{B
+=B  B
+  BõÃBë
+BáHAûÂAó®AóAëAã
+Aãp€AÛ\)AÓ\)AËG®AË33AÃ33A»
+žA»
+=A³
+=AªõÃAªáHA¢ÌÍAÌÍAžRA£×A£×A\AzáAtÌÍAdÌÍAT£×ATzáADzáA4QìA4(öA$  A  A×
+A®@ç\)@Ç
+=@ÆžR@ŠžR@ff@{@K
+@
+
+?Â?zá>#×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B:
+B6záB6záB2p€B.ffB*\)B*\)B&QìB"G®B"G®B
+=qB33B(öB(öB
+žB{B{B
+
+=B  B  BõÃAû×
+AóÂAóÂAë®AãAãAÛ
+AÓp€AË\)AË\)AÃG®A»33A»33A³
+žA«
+=A«
+=A¢õÃAáHAÌÍAÌÍAžRA£×A£×Au
+žAdõÃATÌÍATÌÍAD£×A4záA4záA$QìA(öA  A  @ç®@Ç\)@Ç\)@§
+=@žR@žR@LÌÍ@
+(ö?
+>?
+>>.{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B6
+B2záB.záB*p€B*ffB&\)B"\)B"QìB
+G®BG®B=qB33B(öB(öB
+žB
+{B{B
+=B  Aü  Aóë
+Aó×
+AëÂAãÂAã®AÛAÓAË
+AËp€AÃ\)A»\)A»G®A³33A«33A«
+žA£
+=A
+=AõÃAáHAÌÍAÌÍAžRAuG®AeG®AU
+žATõÃADÌÍA4ÌÍA4£×A$záAzáAQìA(ö@è  @È  @Ç®@§\)@\)@
+=@Mp€@
+p€??Qì>8Qì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B.
+B*záB*záB&p€B"ffB"\)B
+\)BQìBG®BG®B=qB33B(öB
+(öB
+žB{B{Aü{Aô  Aô  Aëë
+Aã×
+AãÂAÛÂAÓ®AËAËAÃ
+A»p€A»\)A³\)A«G®A«33A£33A
+žA
+=A
+=AõÃAáHAÌÍAuAep€AUG®AUG®AE
+žA4õÃA4ÌÍA$ÌÍA£×AzáAzá@è£×@ÈQì@È  @š  @®@\)@NžR@{?áH?áH>LÌÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B*
+B&záB"záB"p€B
+ffB\)B\)BQìBG®BG®B=qB
+33B(öB(öB
+žAü(öAô(öAô{Aì  Aä  Aãë
+AÛ×
+AÓÂAËÂAË®AÃA»A»
+A³p€A«\)A«\)A£G®A33A33A
+žA
+=A
+=AõÃAuÂAeAUAUp€AEG®A5G®A5
+žA$õÃAÌÍAÌÍA£×@èõÃ@ÈõÃ@È£×@šQì@  @  @O\)@žR?p€?(ö>W
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B"
+B"záB
+záBp€BffB\)B\)BQìBG®B
+G®B=qB33B(öAüQìAô=qAô(öAì(öAä{Aä  AÜ  AÓë
+AË×
+AËÂAÃÂA»®A»A³A«
+A«p€A£\)A\)AG®A33A33A
+žA
+=Av{Aeë
+AUÂAUAEA5p€A5G®A%G®A
+žAõÃAÌÍ@é@ÉG®@ÈõÃ@šõÃ@£×@Qì@P  @  ?žR?p€>k
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+
+BzáBzáBp€BffB\)B\)B
+QìBG®BG®B=qAüffAôQìAôQìAì=qAä(öAä(öAÜ{AÔ  AÌ  AËë
+AÃ×
+A»ÂA»ÂA³®A«A«A£
+Ap€A\)A\)AG®A33A33Av=qAf{AV{AUë
+AEÂA5A5A%p€AG®AG®A
+ž@éë
+@É@É@©G®@õÃ@õÃ@QG®@£×?   ?   >uÂ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+BzáBzáBp€BffB
+\)B\)BQìBG®Aü\AôzáAôffAìQìAäQìAä=qAÜ(öAÔ(öAÌ{AÌ  AÄ  A»ë
+A»×
+A³ÂA«ÂA«®A£AA
+Ap€A\)A\)AG®AvffAfffAV=qAV{AF{A5ë
+A5ÂA%AAp€AG®@ê\@Ê=q@Éë
+@©@@G®@Që
+@ë
+?¢\?¡G®>  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+BzáBzáB
+p€BffB\)B\)Aü£×Aô\Aô\AìzáAäffAäQìAÜQìAÔ=qAÌ(öAÌ(öAÄ{AŒ  AŒ  A³ë
+A«×
+A«ÂA£ÂA®AAA
+Ap€A\)AvžRAf\AVffAVffAF=qA6{A6{A%ë
+AÂAA@êáH@Ê\@Ê\@ª=q@ë
+@@S33@\?£×
+?£×
+>=q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+B
+záBzáBp€BffAüžRAôžRAô£×Aì\Aä\AäzáAÜffAÔQìAÌQìAÌ=qAÄ(öAŒ(öAŒ{AŽ  A¬  A«ë
+A£×
+AÂAÂA®AAA
+AváHAfžRAVžRAV\AFffA6ffA6=qA&{A{Aë
+AÂ@ë33@Ë33@ÊáH@ª\@\@=q@S×
+@33?Šff?¥
+ž>\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+BzáBzáAüáHAôÌÍAôžRAìžRAä£×Aä\AÜ\AÔzáAÌffAÌQìAÄQìAŒ=qAŒ(öAŽ(öA¬{A¬  A€  Aë
+A×
+AÂAÂA®AAw33Ag
+=AVáHAVžRAFžRA6\A6ffA&ffA=qA{A{@ë×
+@Ë
+@Ë33@«33@áH@\@U
+ž@zá?§®?Šff>¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+AüõÃAôõÃAôáHAìÌÍAäžRAäžRAÜ£×AÔ\AÌ\AÌzáAÄffAŒQìAŒQìAŽ=qA¬(öA¬(öA€{A  A  Aë
+A×
+AÂAÂAw\)Ag33AW33AW
+=AFáHA6žRA6žRA&\AffAffA=q@ì(ö@Ì(ö@Ë×
+@«
+@33@33@UÂ@
+ž?ª=q?šõÂ>žR¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aõ
+=AôõÃAìõÃAäáHAäÌÍAÜžRAÔžRAÌ£×AÌ\AÄ\AŒzáAŒffAŽQìA¬QìA¬=qA€(öA(öA{A  A  Aë
+A×
+Aw
+Ag
+AW\)AW33AG33A7
+=A6áHA&žRAžRA\Aff@ìÌÍ@Ìzá@Ì(ö@¬(ö@×
+@
+@Vff@ff?«
+?ª=q>šõÃ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aí
+=AäõÃAäõÃAÜáHAÔÌÍAÌžRAÌžRAÄ£×AŒ\AŒ\AŽzáA¬ffA¬QìA€QìA=qA(öA(öA{A  A  Aw×
+Ag®AW
+AW
+AG\)A733A733A'
+=AáHAžRAžR@í
+ž@ÌÌÍ@ÌÌÍ@¬zá@(ö@(ö@W®@
+>?¬ÌÍ?¬ÌÍ>®{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aå
+=AÜõÃAÔõÃAÌáHAÌÌÍAÄžRAŒžRAŒ£×AŽ\A¬\A¬záA€ffAQìAQìA=qA(öA(öA{Ax  Ah  AW×
+AW®AG
+A7
+A7\)A'33A33A
+=AáH@íp€@Íp€@Í
+ž@¬ÌÍ@ÌÍ@zá@XQì@Qì?¯\)?®{>³33¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÕ
+=AÌõÃAÌõÃAÄáHAŒÌÍAŒžRAŽžRA¬£×A¬\A€\AzáAffAQìAQìA=qA(öAxQìAh(öAX  AX  AG×
+A7®A7
+A'
+A\)A33A33@î{@ÍÂ@Íp€@­p€@
+ž@ÌÍ@Y@õÂ?°£×?°£×>œp€¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÍ
+=AÄõÃAŒõÃAŒáHAŽÌÍA¬žRA¬žRA€£×A\A\AzáAffAQìAQìAxzáAhQìAXQìAX(öAH  A8  A7×
+A'®A
+A
+A\)@îff@Îff@Î{@­Â@p€@p€@Z=q@?³33?±ë
+>Â\¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aœ
+=AŒõÃAŽõÃA¬áHA¬ÌÍA€žRAžRA£×A\A\AzáAffAx£×Ah£×AXzáAXQìAHQìA8(öA8  A(  A×
+A®A
+@ï
+=@ÎžR@Îff@®ff@{@Â@ZáH@áH?Žzá?³33>ÌÌÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aµ
+=A¬õÃA¬õÃA€áHAÌÍAžRAžRA£×A\A\AxõÃAhÌÍAX£×AX£×AHzáA8QìA8QìA((öA  A  A×
+@ï\)@Ï
+=@Ï
+=@®žR@ff@ff@\(ö@
+?µÂ?µÂ>Ñë
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A­
+=A€õÃAõÃAáHAÌÍAžRAžRA£×Ay
+žAi
+žAXõÃAXÌÍAH£×A8£×A8záA(QìAQìA(öA  @ð  @Ï®@Ï\)@¯
+=@
+=@žR@\ÌÍ@
+ÌÍ?žQì?·
+>>×
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+=AõÃAõÃAáHAÌÍAžRAyp€AiG®AY
+žAY
+žAHõÃA8ÌÍA8£×A(£×AzáAQìAQì@ðQì@Ð  @Ð  @¯®@\)@
+=@^{@
+p€?¹?¹>áG®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+=AõÃAõÃAáHAyAip€AYp€AYG®AI
+žA9
+žA8õÃA(ÌÍA£×A£×Azá@ð£×@Ð£×@ÐQì@°  @  @®@^žR@
+{?Œ(ö?ºáH>æff¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+
+=AõÃAyë
+AiÂAYAYp€AIp€A9G®A9
+žA)
+žAõÃAÌÍA£×@ñG®@ÐõÂ@Ð£×@°£×@Qì@  @`  @\)?œp€?Œ(ö>ð£×¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Az{Aië
+AYë
+AYÂAIA9p€A9p€A)G®A
+žA
+žAõÃ@ñ@ÑG®@ÑG®@°õÂ@£×@£×@`£×@   ?À  ?ŸžR>õÂ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AZ{AYë
+AIë
+A9ÂA9A)p€Ap€AG®A	
+ž@ò=q@Ñë
+@Ñ@±G®@G®@õÂ@aG®@!G®?ÁG®?À  ?   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AJ{A9ë
+A9ë
+A)ÂAAp€A	p€@ò\@Ò=q@Ò=q@±ë
+@@G®@b\@!ë
+?Â\?Â\?\¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A:{A)ë
+Aë
+AÂA	@òáH@ÒáH@Ò\@²=q@=q@ë
+@c33@"\?Å
+ž?Ã×
+?
+ž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A{Aë
+A	ë
+@ó
+@Ó33@ÒáH@²áH@\@=q@dzá@#×
+?Æff?Å
+ž?
+=q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+{@ó×
+@Ó×
+@Ó
+@³33@áH@áH@e
+ž@$zá?ÈõÂ?Ç®?
+ÌÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @Ô(ö@Ó×
+@³×
+@
+@33@eÂ@%Â?Ê=p?ÈõÂ?ë
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @Ž(ö@×
+@×
+@g
+>@&ff?Ë
+
+?Ë
+
+?zá¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @(ö@g®@'®?Î{?ÌÌÍ?
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @(Qì?Ï\)?Ï\)?
+(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?Ð£×?
+žR¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             B~
+B~záB~p€B~ffB~\)B~QìB~G®B~=qB~33B~(öB~
+žB~{B~
+=B~  B}õÃB}ë
+B}áHB}×
+B}ÌÍB}ÂB}žRB}®B}£×B}B}\B}
+B}záB}p€B}ffB}\)B}QìB}G®B}=qB}33B}(öB}
+žB}{B}
+=B}  B|õÃB|ë
+B|áHB|×
+B|ÌÍB|ÂB|žRB|®B|£×B|B|\B|
+B|záB|p€B|ffB|\)B|QìB|G®B|=qB|33B|(öB|
+žB|{B|
+=B|  Bz
+BzzáBzp€BzffBz\)BzQìBzG®Bz=qBz33Bz(öBz
+žBz{Bz
+=Bz  ByõÃByë
+ByáHBy×
+ByÌÍByÂByžRBy®By£×ByBy\By
+ByzáByp€ByffBy\)ByQìByG®By=qBy33By(öBy
+žBy{By
+=By  BxõÃBxë
+BxáHBx×
+BxÌÍBxÂBxžRBx®Bx£×BxBx\Bx
+BxzáBxp€BxffBx\)BxQìBxG®Bx=qBx33Bx(öBx
+žBx{Bx
+=Bx  Bv
+BvzáBvp€BvffBv\)BvQìBvG®Bv=qBv33Bv(öBv
+žBv{Bv
+=Bv  BuõÃBuë
+BuáHBu×
+BuÌÍBuÂBužRBu®Bu£×BuBu\Bu
+BuzáBup€BuffBu\)BuQìBuG®Bu=qBu33Bu(öBu
+žBu{Bu
+=Bu  BtõÃBtë
+BtáHBt×
+BtÌÍBtÂBtžRBt®Bt£×BtBt\Bt
+BtzáBtp€BtffBt\)BtQìBtG®Bt=qBt33Bt(öBt
+žBt{Bt
+=Bt  Br
+BrzáBrp€BrffBr\)BrQìBrG®Br=qBr33Br(öBr
+žBr{Br
+=Br  BqõÃBqë
+BqáHBq×
+BqÌÍBqÂBqžRBq®Bq£×BqBq\Bq
+BqzáBqp€BqffBq\)BqQìBqG®Bq=qBq33Bq(öBq
+žBq{Bq
+=Bq  BpõÃBpë
+BpáHBp×
+BpÌÍBpÂBpžRBp®Bp£×BpBp\Bp
+BpzáBpp€BpffBp\)BpQìBpG®Bp=qBp33Bp(öBp
+žBp{Bp
+=Bp  Bn
+BnzáBnp€BnffBn\)BnQìBnG®Bn=qBn33Bn(öBn
+žBn{Bn
+=Bn  BmõÃBmë
+BmáHBm×
+BmÌÍBmÂBmžRBm®Bm£×BmBm\Bm
+BmzáBmp€BmffBm\)BmQìBmG®Bm=qBm33Bm(öBm
+žBm{Bm
+=Bm  BlõÃBlë
+BláHBl×
+BlÌÍBlÂBlžRBl®Bl£×BlBl\Bl
+BlzáBlp€BlffBl\)BlQìBlG®Bl=qBl33Bl(öBl
+žBl{Bl
+=Bl  Bj
+BjzáBjp€BjffBj\)BjQìBjG®Bj=qBj33Bj(öBj
+žBj{Bj
+=Bj  BiõÃBië
+BiáHBi×
+BiÌÍBiÂBižRBi®Bi£×BiBi\Bi
+BizáBip€BiffBi\)BiQìBiG®Bi=qBi33Bi(öBi
+žBi{Bi
+=Bi  BhõÃBhë
+BháHBh×
+BhÌÍBhÂBhžRBh®Bh£×BhBh\Bh
+BhzáBhp€BhffBh\)BhQìBhG®Bh=qBh33Bh(öBh
+žBh{Bh
+=Bh  Bf
+BfzáBfp€BfffBf\)BfQìBfG®Bf=qBf33Bf(öBf
+žBf{Bf
+=Bf  BeõÃBeë
+BeáHBe×
+BeÌÍBeÂBežRBe®Be£×BeBe\Be
+BezáBep€BeffBe\)BeQìBeG®Be=qBe33Be(öBe
+žBe{Be
+=Be  BdõÃBdë
+BdáHBd×
+BdÌÍBdÂBdžRBd®Bd£×BdBd\Bd
+BdzáBdp€BdffBd\)BdQìBdG®Bd=qBd33Bd(öBd
+žBd{Bd
+=Bd  Bb
+BbzáBbp€BbffBb\)BbQìBbG®Bb=qBb33Bb(öBb
+žBb{Bb
+=Bb  BaõÃBaë
+BaáHBa×
+BaÌÍBaÂBažRBa®Ba£×BaBa\Ba
+BazáBap€BaffBa\)BaQìBaG®Ba=qBa33Ba(öBa
+žBa{Ba
+=Ba  B`õÃB`ë
+B`áHB`×
+B`ÌÍB`ÂB`žRB`®B`£×B`B`\B`
+B`záB`p€B`ffB`\)B`QìB`G®B`=qB`33B`(öB`
+žB`{B`
+=B`  B^
+B^záB^p€B^ffB^\)B^QìB^G®B^=qB^33B^(öB^
+žB^{B^
+=B^  B]õÃB]ë
+B]áHB]×
+B]ÌÍB]ÂB]žRB]®B]£×B]B]\B]
+B]záB]p€B]ffB]\)B]QìB]G®B]=qB]33B](öB]
+žB]{B]
+=B]  B\õÃB\ë
+B\áHB\×
+B\ÌÍB\ÂB\žRB\®B\£×B\B\\B\
+B\záB\p€B\ffB\\)B\QìB\G®B\=qB\33B\(öB\
+žB\{B\
+=B\  BZ
+BZzáBZp€BZffBZ\)BZQìBZG®BZ=qBZ33BZ(öBZ
+žBZ{BZ
+=BZ  BYõÃBYë
+BYáHBY×
+BYÌÍBYÂBYžRBY®BY£×BYBY\BY
+BYzáBYp€BYffBY\)BYQìBYG®BY=qBY33BY(öBY
+žBY{BY
+=BY  BXõÃBXë
+BXáHBX×
+BXÌÍBXÂBXžRBX®BX£×BXBX\BX
+BXzáBXp€BXffBX\)BXQìBXG®BX=qBX33BX(öBX
+žBX{BX
+=BX  BV
+BVzáBVp€BVffBV\)BVQìBVG®BV=qBV33BV(öBV
+žBV{BV
+=BV  BUõÃBUë
+BUáHBU×
+BUÌÍBUÂBUžRBU®BU£×BUBU\BU
+BUzáBUp€BUffBU\)BUQìBUG®BU=qBU33BU(öBU
+žBU{BU
+=BU  BTõÃBTë
+BTáHBT×
+BTÌÍBTÂBTžRBT®BT£×BTBT\BT
+BTzáBTp€BTffBT\)BTQìBTG®BT=qBT33BT(öBT
+žBT{BT
+=BT  BR
+BRzáBRp€BRffBR\)BRQìBRG®BR=qBR33BR(öBR
+žBR{BR
+=BR  BQõÃBQë
+BQáHBQ×
+BQÌÍBQÂBQžRBQ®BQ£×BQBQ\BQ
+BQzáBQp€BQffBQ\)BQQìBQG®BQ=qBQ33BQ(öBQ
+žBQ{BQ
+=BQ  BPõÃBPë
+BPáHBP×
+BPÌÍBPÂBPžRBP®BP£×BPBP\BP
+BPzáBPp€BPffBP\)BPQìBPG®BP=qBP33BP(öBP
+žBP{BP
+=BP  BN
+BNzáBNp€BNffBN\)BNQìBNG®BN=qBN33BN(öBN
+žBN{BN
+=BN  BMõÃBMë
+BMáHBM×
+BMÌÍBMÂBMžRBM®BM£×BMBM\BM
+BMzáBMp€BMffBM\)BMQìBMG®BM=qBM33BM(öBM
+žBM{BM
+=BM  BLõÃBLë
+BLáHBL×
+BLÌÍBLÂBLžRBL®BL£×BLBL\BL
+BLzáBLp€BLffBL\)BLQìBLG®BL=qBL33BL(öBL
+žBL{BL
+=BL  BJ
+BJzáBJp€BJffBJ\)BJQìBJG®BJ=qBJ33BJ(öBJ
+žBJ{BJ
+=BJ  BIõÃBIë
+BIáHBI×
+BIÌÍBIÂBIžRBI®BI£×BIBI\BI
+BIzáBIp€BIffBI\)BIQìBIG®BI=qBI33BI(öBI
+žBI{BI
+=BI  BHõÃBHë
+BHáHBH×
+BHÌÍBHÂBHžRBH®BH£×BHBH\BH
+BHzáBHp€BHffBH\)BHQìBHG®BH=qBH33BH(öBH
+žBH{BH
+=BH  BF
+BFzáBFp€BFffBF\)BFQìBFG®BF=qBF33BF(öBF
+žBF{BF
+=BF  BEõÃBEë
+BEáHBE×
+BEÌÍBEÂBEžRBE®BE£×BEBE\BE
+BEzáBEp€BEffBE\)BEQìBEG®BE=qBE33BE(öBE
+žBE{BE
+=BE  BDõÃBDë
+BDáHBD×
+BDÌÍBDÂBDžRBD®BD£×BDBD\BD
+BDzáBDp€BDffBD\)BDQìBDG®BD=qBD33BD(öBD
+žBD{BD
+=BD  BB
+BBzáBBp€BBffBB\)BBQìBBG®BB=qBB33BB(öBB
+žBB{BB
+=BB  BAõÃBAë
+BAáHBA×
+BAÌÍBAÂBAžRBA®BA£×BABA\BA
+BAzáBAp€BAffBA\)BAQìBAG®BA=qBA33BA(öBA
+žBA{BA
+=BA  B@õÃB@ë
+B@áHB@×
+B@ÌÍB@ÂB@žRB@®B@£×B@B@\B@
+B@záB@p€B@ffB@\)B@QìB@G®B@=qB@33B@(öB@
+žB@{B@
+=B@  B>
+B>záB>p€B>ffB>\)B>QìB>G®B>=qB>33B>(öB>
+žB>{B>
+=B>  B=õÃB=ë
+B=áHB=×
+B=ÌÍB=ÂB=žRB=®B=£×B=B=\B=
+B=záB=p€B=ffB=\)B=QìB=G®B==qB=33B=(öB=
+žB={B=
+=B=  B<õÃB<ë
+B<áHB<×
+B<ÌÍB<ÂB<žRB<®B<£×B<B<\B<
+B<záB<p€B<ffB<\)B<QìB<G®B<=qB<33B<(öB<
+žB<{B<
+=B<  B:
+B:záB:p€B:ffB:\)B:QìB:G®B:=qB:33B:(öB:
+žB:{B:
+=B:  B9õÃB9ë
+B9áHB9×
+B9ÌÍB9ÂB9žRB9®B9£×B9B9\B9
+B9záB9p€B9ffB9\)B9QìB9G®B9=qB933B9(öB9
+žB9{B9
+=B9  B8õÃB8ë
+B8áHB8×
+B8ÌÍB8ÂB8žRB8®B8£×B8B8\B8
+B8záB8p€B8ffB8\)B8QìB8G®B8=qB833B8(öB8
+žB8{B8
+=B8  B6
+B6záB6p€B6ffB6\)B6QìB6G®B6=qB633B6(öB6
+žB6{B6
+=B6  B5õÃB5ë
+B5áHB5×
+B5ÌÍB5ÂB5žRB5®B5£×B5B5\B5
+B5záB5p€B5ffB5\)B5QìB5G®B5=qB533B5(öB5
+žB5{B5
+=B5  B4õÃB4ë
+B4áHB4×
+B4ÌÍB4ÂB4žRB4®B4£×B4B4\B4
+B4záB4p€B4ffB4\)B4QìB4G®B4=qB433B4(öB4
+žB4{B4
+=B4  B2
+B2záB2p€B2ffB2\)B2QìB2G®B2=qB233B2(öB2
+žB2{B2
+=B2  B1õÃB1ë
+B1áHB1×
+B1ÌÍB1ÂB1žRB1®B1£×B1B1\B1
+B1záB1p€B1ffB1\)B1QìB1G®B1=qB133B1(öB1
+žB1{B1
+=B1  B0õÃB0ë
+B0áHB0×
+B0ÌÍB0ÂB0žRB0®B0£×B0B0\B0
+B0záB0p€B0ffB0\)B0QìB0G®B0=qB033B0(öB0
+žB0{B0
+=B0  B.
+B.záB.p€B.ffB.\)B.QìB.G®B.=qB.33B.(öB.
+žB.{B.
+=B.  B-õÃB-ë
+B-áHB-×
+B-ÌÍB-ÂB-žRB-®B-£×B-B-\B-
+B-záB-p€B-ffB-\)B-QìB-G®B-=qB-33B-(öB-
+žB-{B-
+=B-  B,õÃB,ë
+B,áHB,×
+B,ÌÍB,ÂB,žRB,®B,£×B,B,\B,
+B,záB,p€B,ffB,\)B,QìB,G®B,=qB,33B,(öB,
+žB,{B,
+=B,  B*
+B*záB*p€B*ffB*\)B*QìB*G®B*=qB*33B*(öB*
+žB*{B*
+=B*  B)õÃB)ë
+B)áHB)×
+B)ÌÍB)ÂB)žRB)®B)£×B)B)\B)
+B)záB)p€B)ffB)\)B)QìB)G®B)=qB)33B)(öB)
+žB){B)
+=B)  B(õÃB(ë
+B(áHB(×
+B(ÌÍB(ÂB(žRB(®B(£×B(B(\B(
+B(záB(p€B(ffB(\)B(QìB(G®B(=qB(33B((öB(
+žB({B(
+=B(  B&
+B&záB&p€B&ffB&\)B&QìB&G®B&=qB&33B&(öB&
+žB&{B&
+=B&  B%õÃB%ë
+B%áHB%×
+B%ÌÍB%ÂB%žRB%®B%£×B%B%\B%
+B%záB%p€B%ffB%\)B%QìB%G®B%=qB%33B%(öB%
+žB%{B%
+=B%  B$õÃB$ë
+B$áHB$×
+B$ÌÍB$ÂB$žRB$®B$£×B$B$\B$
+B$záB$p€B$ffB$\)B$QìB$G®B$=qB$33B$(öB$
+žB${B$
+=B$  B"
+B"záB"p€B"ffB"\)B"QìB"G®B"=qB"33B"(öB"
+žB"{B"
+=B"  B!õÃB!ë
+B!áHB!×
+B!ÌÍB!ÂB!žRB!®B!£×B!B!\B!
+B!záB!p€B!ffB!\)B!QìB!G®B!=qB!33B!(öB!
+žB!{B!
+=B!  B õÃB ë
+B áHB ×
+B ÌÍB ÂB žRB ®B £×B B \B 
+B záB p€B ffB \)B QìB G®B =qB 33B (öB 
+žB {B 
+=B   B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B	õÃB	ë
+B	áHB	×
+B	ÌÍB	ÂB	žRB	®B	£×B	B	\B	
+B	záB	p€B	ffB	\)B	QìB	G®B	=qB	33B	(öB	
+žB	{B	
+=B	  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B õÃB ë
+B áHB ×
+B ÌÍB ÂB žRB ®B £×B B \B 
+B záB p€B ffB \)B QìB G®B =qB 33B (öB 
+žB {B 
+=B   Aý
+=AüõÃAüáHAüÌÍAüžRAü£×Aü\AüzáAüffAüQìAü=qAü(öAü{Aü  Aûë
+Aû×
+AûÂAû®AûAû
+Aûp€Aû\)AûG®Aû33Aû
+žAû
+=AúõÃAúáHAúÌÍAúžRAú£×Aú\AúzáAúffAúQìAú=qAú(öAú{Aú  Aùë
+Aù×
+AùÂAù®AùAù
+Aùp€Aù\)AùG®Aù33Aù
+žAù
+=AøõÃAøáHAøÌÍAøžRAø£×Aø\AøzáAøffAøQìAø=qAø(öAø{Aø  Aõ
+=AôõÃAôáHAôÌÍAôžRAô£×Aô\AôzáAôffAôQìAô=qAô(öAô{Aô  Aóë
+Aó×
+AóÂAó®AóAó
+Aóp€Aó\)AóG®Aó33Aó
+žAó
+=AòõÃAòáHAòÌÍAòžRAò£×Aò\AòzáAòffAòQìAò=qAò(öAò{Aò  Añë
+Añ×
+AñÂAñ®AñAñ
+Añp€Añ\)AñG®Añ33Añ
+žAñ
+=AðõÃAðáHAðÌÍAðžRAð£×Að\AðzáAðffAðQìAð=qAð(öAð{Að  Aí
+=AìõÃAìáHAìÌÍAìžRAì£×Aì\AìzáAìffAìQìAì=qAì(öAì{Aì  Aëë
+Aë×
+AëÂAë®AëAë
+Aëp€Aë\)AëG®Aë33Aë
+žAë
+=AêõÃAêáHAêÌÍAêžRAê£×Aê\AêzáAêffAêQìAê=qAê(öAê{Aê  Aéë
+Aé×
+AéÂAé®AéAé
+Aép€Aé\)AéG®Aé33Aé
+žAé
+=AèõÃAèáHAèÌÍAèžRAè£×Aè\AèzáAèffAèQìAè=qAè(öAè{Aè  Aå
+=AäõÃAäáHAäÌÍAäžRAä£×Aä\AäzáAäffAäQìAä=qAä(öAä{Aä  Aãë
+Aã×
+AãÂAã®AãAã
+Aãp€Aã\)AãG®Aã33Aã
+žAã
+=AâõÃAâáHAâÌÍAâžRAâ£×Aâ\AâzáAâffAâQìAâ=qAâ(öAâ{Aâ  Aáë
+Aá×
+AáÂAá®AáAá
+Aáp€Aá\)AáG®Aá33Aá
+žAá
+=AàõÃAàáHAàÌÍAàžRAà£×Aà\AàzáAàffAàQìAà=qAà(öAà{Aà  AÝ
+=AÜõÃAÜáHAÜÌÍAÜžRAÜ£×AÜ\AÜzáAÜffAÜQìAÜ=qAÜ(öAÜ{AÜ  AÛë
+AÛ×
+AÛÂAÛ®AÛAÛ
+AÛp€AÛ\)AÛG®AÛ33AÛ
+žAÛ
+=AÚõÃAÚáHAÚÌÍAÚžRAÚ£×AÚ\AÚzáAÚffAÚQìAÚ=qAÚ(öAÚ{AÚ  AÙë
+AÙ×
+AÙÂAÙ®AÙAÙ
+AÙp€AÙ\)AÙG®AÙ33AÙ
+žAÙ
+=AØõÃAØáHAØÌÍAØžRAØ£×AØ\AØzáAØffAØQìAØ=qAØ(öAØ{AØ  AÕ
+=AÔõÃAÔáHAÔÌÍAÔžRAÔ£×AÔ\AÔzáAÔffAÔQìAÔ=qAÔ(öAÔ{AÔ  AÓë
+AÓ×
+AÓÂAÓ®AÓAÓ
+AÓp€AÓ\)AÓG®AÓ33AÓ
+žAÓ
+=AÒõÃAÒáHAÒÌÍAÒžRAÒ£×AÒ\AÒzáAÒffAÒQìAÒ=qAÒ(öAÒ{AÒ  AÑë
+AÑ×
+AÑÂAÑ®AÑAÑ
+AÑp€AÑ\)AÑG®AÑ33AÑ
+žAÑ
+=AÐõÃAÐáHAÐÌÍAÐžRAÐ£×AÐ\AÐzáAÐffAÐQìAÐ=qAÐ(öAÐ{AÐ  AÍ
+=AÌõÃAÌáHAÌÌÍAÌžRAÌ£×AÌ\AÌzáAÌffAÌQìAÌ=qAÌ(öAÌ{AÌ  AËë
+AË×
+AËÂAË®AËAË
+AËp€AË\)AËG®AË33AË
+žAË
+=AÊõÃAÊáHAÊÌÍAÊžRAÊ£×AÊ\AÊzáAÊffAÊQìAÊ=qAÊ(öAÊ{AÊ  AÉë
+AÉ×
+AÉÂAÉ®AÉAÉ
+AÉp€AÉ\)AÉG®AÉ33AÉ
+žAÉ
+=AÈõÃAÈáHAÈÌÍAÈžRAÈ£×AÈ\AÈzáAÈffAÈQìAÈ=qAÈ(öAÈ{AÈ  AÅ
+=AÄõÃAÄáHAÄÌÍAÄžRAÄ£×AÄ\AÄzáAÄffAÄQìAÄ=qAÄ(öAÄ{AÄ  AÃë
+AÃ×
+AÃÂAÃ®AÃAÃ
+AÃp€AÃ\)AÃG®AÃ33AÃ
+žAÃ
+=AÂõÃAÂáHAÂÌÍAÂžRAÂ£×AÂ\AÂzáAÂffAÂQìAÂ=qAÂ(öAÂ{AÂ  AÁë
+AÁ×
+AÁÂAÁ®AÁAÁ
+AÁp€AÁ\)AÁG®AÁ33AÁ
+žAÁ
+=AÀõÃAÀáHAÀÌÍAÀžRAÀ£×AÀ\AÀzáAÀffAÀQìAÀ=qAÀ(öAÀ{AÀ  Aœ
+=AŒõÃAŒáHAŒÌÍAŒžRAŒ£×AŒ\AŒzáAŒffAŒQìAŒ=qAŒ(öAŒ{AŒ  A»ë
+A»×
+A»ÂA»®A»A»
+A»p€A»\)A»G®A»33A»
+žA»
+=AºõÃAºáHAºÌÍAºžRAº£×Aº\AºzáAºffAºQìAº=qAº(öAº{Aº  A¹ë
+A¹×
+A¹ÂA¹®A¹A¹
+A¹p€A¹\)A¹G®A¹33A¹
+žA¹
+=AžõÃAžáHAžÌÍAžžRAž£×Až\AžzáAžffAžQìAž=qAž(öAž{Až  Aµ
+=AŽõÃAŽáHAŽÌÍAŽžRAŽ£×AŽ\AŽzáAŽffAŽQìAŽ=qAŽ(öAŽ{AŽ  A³ë
+A³×
+A³ÂA³®A³A³
+A³p€A³\)A³G®A³33A³
+žA³
+=A²õÃA²áHA²ÌÍA²žRA²£×A²\A²záA²ffA²QìA²=qA²(öA²{A²  A±ë
+A±×
+A±ÂA±®A±A±
+A±p€A±\)A±G®A±33A±
+žA±
+=A°õÃA°áHA°ÌÍA°žRA°£×A°\A°záA°ffA°QìA°=qA°(öA°{A°  A­
+=A¬õÃA¬áHA¬ÌÍA¬žRA¬£×A¬\A¬záA¬ffA¬QìA¬=qA¬(öA¬{A¬  A«ë
+A«×
+A«ÂA«®A«A«
+A«p€A«\)A«G®A«33A«
+žA«
+=AªõÃAªáHAªÌÍAªžRAª£×Aª\AªzáAªffAªQìAª=qAª(öAª{Aª  A©ë
+A©×
+A©ÂA©®A©A©
+A©p€A©\)A©G®A©33A©
+žA©
+=AšõÃAšáHAšÌÍAšžRAš£×Aš\AšzáAšffAšQìAš=qAš(öAš{Aš  A¥
+=A€õÃA€áHA€ÌÍA€žRA€£×A€\A€záA€ffA€QìA€=qA€(öA€{A€  A£ë
+A£×
+A£ÂA£®A£A£
+A£p€A£\)A£G®A£33A£
+žA£
+=A¢õÃA¢áHA¢ÌÍA¢žRA¢£×A¢\A¢záA¢ffA¢QìA¢=qA¢(öA¢{A¢  A¡ë
+A¡×
+A¡ÂA¡®A¡A¡
+A¡p€A¡\)A¡G®A¡33A¡
+žA¡
+=A õÃA áHA ÌÍA žRA £×A \A záA ffA QìA =qA (öA {A   A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Az{Ayë
+AyÂAyAyp€AyG®Ay
+žAxõÃAxÌÍAx£×AxzáAxQìAx(öAx  Aw×
+Aw®Aw
+Aw\)Aw33Aw
+=AváHAvžRAv\AvffAv=qAv{Auë
+AuÂAuAup€AuG®Au
+žAtõÃAtÌÍAt£×AtzáAtQìAt(öAt  As×
+As®As
+As\)As33As
+=AráHAržRAr\ArffAr=qAr{Aqë
+AqÂAqAqp€AqG®Aq
+žApõÃApÌÍAp£×ApzáApQìAp(öAp  Aj{Aië
+AiÂAiAip€AiG®Ai
+žAhõÃAhÌÍAh£×AhzáAhQìAh(öAh  Ag×
+Ag®Ag
+Ag\)Ag33Ag
+=AfáHAfžRAf\AfffAf=qAf{Aeë
+AeÂAeAep€AeG®Ae
+žAdõÃAdÌÍAd£×AdzáAdQìAd(öAd  Ac×
+Ac®Ac
+Ac\)Ac33Ac
+=AbáHAbžRAb\AbffAb=qAb{Aaë
+AaÂAaAap€AaG®Aa
+žA`õÃA`ÌÍA`£×A`záA`QìA`(öA`  AZ{AYë
+AYÂAYAYp€AYG®AY
+žAXõÃAXÌÍAX£×AXzáAXQìAX(öAX  AW×
+AW®AW
+AW\)AW33AW
+=AVáHAVžRAV\AVffAV=qAV{AUë
+AUÂAUAUp€AUG®AU
+žATõÃATÌÍAT£×ATzáATQìAT(öAT  AS×
+AS®AS
+AS\)AS33AS
+=ARáHARžRAR\ARffAR=qAR{AQë
+AQÂAQAQp€AQG®AQ
+žAPõÃAPÌÍAP£×APzáAPQìAP(öAP  AJ{AIë
+AIÂAIAIp€AIG®AI
+žAHõÃAHÌÍAH£×AHzáAHQìAH(öAH  AG×
+AG®AG
+AG\)AG33AG
+=AFáHAFžRAF\AFffAF=qAF{AEë
+AEÂAEAEp€AEG®AE
+žADõÃADÌÍAD£×ADzáADQìAD(öAD  AC×
+AC®AC
+AC\)AC33AC
+=ABáHABžRAB\ABffAB=qAB{AAë
+AAÂAAAAp€AAG®AA
+žA@õÃA@ÌÍA@£×A@záA@QìA@(öA@  A:{A9ë
+A9ÂA9A9p€A9G®A9
+žA8õÃA8ÌÍA8£×A8záA8QìA8(öA8  A7×
+A7®A7
+A7\)A733A7
+=A6áHA6žRA6\A6ffA6=qA6{A5ë
+A5ÂA5A5p€A5G®A5
+žA4õÃA4ÌÍA4£×A4záA4QìA4(öA4  A3×
+A3®A3
+A3\)A333A3
+=A2áHA2žRA2\A2ffA2=qA2{A1ë
+A1ÂA1A1p€A1G®A1
+žA0õÃA0ÌÍA0£×A0záA0QìA0(öA0  A*{A)ë
+A)ÂA)A)p€A)G®A)
+žA(õÃA(ÌÍA(£×A(záA(QìA((öA(  A'×
+A'®A'
+A'\)A'33A'
+=A&áHA&žRA&\A&ffA&=qA&{A%ë
+A%ÂA%A%p€A%G®A%
+žA$õÃA$ÌÍA$£×A$záA$QìA$(öA$  A#×
+A#®A#
+A#\)A#33A#
+=A"áHA"žRA"\A"ffA"=qA"{A!ë
+A!ÂA!A!p€A!G®A!
+žA õÃA ÌÍA £×A záA QìA (öA   A{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A
+{A	ë
+A	ÂA	A	p€A	G®A	
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žA õÃA ÌÍA £×A záA QìA (öA   @ô(ö@ó×
+@ó
+@ó33@òáH@ò\@ò=q@ñë
+@ñ@ñG®@ðõÂ@ð£×@ðQì@ð  @ï®@ï\)@ï
+=@îžR@îff@î{@íÂ@íp€@í
+ž@ìÌÍ@ìzá@ì(ö@ë×
+@ë
+@ë33@êáH@ê\@ê=q@éë
+@é@éG®@èõÃ@è£×@èQì@è  @ç®@ç\)@ç
+=@æžR@æff@æ{@åÂ@åp€@å
+ž@äÌÍ@äzá@ä(ö@ã×
+@ã
+@ã33@âáH@â\@â=q@áë
+@á@áG®@àõÃ@à£×@àQì@à  @Ô(ö@Ó×
+@Ó
+@Ó33@ÒáH@Ò\@Ò=q@Ñë
+@Ñ@ÑG®@ÐõÂ@Ð£×@ÐQì@Ð  @Ï®@Ï\)@Ï
+=@ÎžR@Îff@Î{@ÍÂ@Íp€@Í
+ž@ÌÌÍ@Ìzá@Ì(ö@Ë×
+@Ë
+@Ë33@ÊáH@Ê\@Ê=q@Éë
+@É@ÉG®@ÈõÃ@È£×@ÈQì@È  @Ç®@Ç\)@Ç
+=@ÆžR@Æff@Æ{@ÅÂ@Åp€@Å
+ž@ÄÌÍ@Äzá@Ä(ö@Ã×
+@Ã
+@Ã33@ÂáH@Â\@Â=q@Áë
+@Á@ÁG®@ÀõÃ@À£×@ÀQì@À  @Ž(ö@³×
+@³
+@³33@²áH@²\@²=q@±ë
+@±@±G®@°õÂ@°£×@°Qì@°  @¯®@¯\)@¯
+=@®žR@®ff@®{@­Â@­p€@­
+ž@¬ÌÍ@¬zá@¬(ö@«×
+@«
+@«33@ªáH@ª\@ª=q@©ë
+@©@©G®@šõÃ@š£×@šQì@š  @§®@§\)@§
+=@ŠžR@Šff@Š{@¥Â@¥p€@¥
+ž@€ÌÍ@€zá@€(ö@£×
+@£
+@£33@¢áH@¢\@¢=q@¡ë
+@¡@¡G®@ õÃ@ £×@ Qì@   @(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÂ@£×@Qì@  @®@\)@
+=@žR@ff@{@Â@p€@
+ž@ÌÍ@zá@(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÃ@£×@Qì@  @®@\)@
+=@žR@ff@{@
+Â@
+p€@
+
+ž@ÌÍ@zá@(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÃ@£×@Qì@  @hQì@g®@g
+>@fff@eÂ@e
+ž@dzá@c×
+@c33@b\@aë
+@aG®@`£×@`  @_\)@^žR@^{@]p€@\ÌÍ@\(ö@[
+@ZáH@Z=q@Y@XõÂ@XQì@W®@W
+>@Vff@UÂ@U
+ž@Tzá@S×
+@S33@R\@Që
+@QG®@P£×@P  @O\)@NžR@N{@Mp€@LÌÍ@L(ö@K
+@JáH@J=q@I@HõÃ@HQì@G®@G
+=@Fff@EÂ@E
+ž@Dzá@C×
+@C33@B\@Aë
+@AG®@@£×@@  @(Qì@'®@'
+>@&ff@%Â@%
+ž@$zá@#×
+@#33@"\@!ë
+@!G®@ £×@   @\)@
+žR@
+{@
+p€@
+ÌÍ@
+(ö@
+@áH@=q@@õÂ@Qì@®@
+>@ff@Â@
+ž@zá@×
+@33@\@ë
+@G®@£×@  @\)@žR@{@
+p€@
+ÌÍ@
+(ö@
+
+@
+áH@
+=q@	@õÃ@Qì@®@
+=@ff@Â@
+ž@zá@×
+@33@\@ë
+@G®@ £×@   ?Ð£×?Ï\)?Î{?ÌÌÍ?Ë
+
+?Ê=p?ÈõÂ?Ç®?Æff?Å
+ž?Ã×
+?Â\?ÁG®?À  ?ŸžR?œp€?Œ(ö?ºáH?¹?žQì?·
+>?µÂ?Žzá?³33?±ë
+?°£×?¯\)?®{?¬ÌÍ?«
+?ª=q?šõÂ?§®?Šff?¥
+ž?£×
+?¢\?¡G®?   ?žR?p€?(ö?áH??Qì?
+>?Â?zá?33?ë
+?£×?\)?{?ÌÍ?
+?=q?õÃ?®?ff?
+
+ž?×
+?\?G®?  ?!G®?
+žR?
+(ö??
+=?zá?ë
+?\)?
+ÌÍ?
+=q?®?
+ž?\?   >úáH>õÂ>ð£×>ë
+>æff>áG®>Ü(ö>×
+=>Ñë
+>ÌÌÍ>Ç®>Â\>œp€>žQì>³33>®{>šõÃ>£×
+>žR>>zá>\)>=q>
+
+ž>  >uÂ>k
+>aG®>W
+=>LÌÍ>B\>8Qì>.{>#×
+>>\)>
+ž=õÂ=áG®=ÌÌÍ=žQì=£×
+=\)=uÂ=LÌÍ=#×
+<õÂ<£×
+<#×
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/fits/verified/sBiOut.fits
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/fits/verified/sBiOut.fits	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/fits/verified/sBiOut.fits	(revision 22158)
@@ -0,0 +1,1414 @@
+SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ; = ?ÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 : < >ÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ; =ÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 : <ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ;ÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 :ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9ÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6ÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - /ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , .ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + -ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * ,ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) +ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( *ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' )ÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & (ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % 'ÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ &ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # %ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! #ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   "ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  !ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+  ÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+ ÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+ÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+ÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+       ÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+       ÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+      ÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+      ÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+     ÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+     ÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+    ÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+    ÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+   ÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+   ÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+  ÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+  ÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+ ÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+ ÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+ÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+ÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	ÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ      ÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ    ÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ    ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ   ÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ                                                                                                                                                                                                                                                                                                                                                                                                                                                                  XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÁÿÂÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀÿÁÿÃÿÄÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿ÿ¿ÿÂÿÄÿÆÿÇÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿœÿŸÿÀÿÂÿÄÿÆÿÉÿÊÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŒÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¹ÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿžÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÕÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¶ÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿØÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿµÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ³ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ°ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿæÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿéÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ«ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ©ÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿšÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ§ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿ÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¥ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ      ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+      ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  !ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % &ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ & ( )ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ & ( + ,ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % ' ) + - /ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ & ( * , . 0 2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ & ( + - / 1 3 5ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % ' ) + - 0 2 4 6 7ÿÿÿÿÿÿÿÿÿ
+ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ & ( * , . 0 2 4 7 9 :ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ & ( + - / 1 3 5 7 9 < =ÿÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % ' ) + - 0 2 4 6 8 : < >ÿÿÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ & ( * , . 0 2 4 7 9 ; = >ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ & ( + - / 1 3 5 7 9 < <ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % ' ) + - 0 2 4 6 8 : ;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ & ( * , . 0 2 4 7 9 :ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ & ( + - / 1 3 5 7 8ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % ' ) + - 0 2 4 6 7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ & ( * , . 0 2 4 5ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ & ( + - / 1 3 4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % ' ) + - 0 2 2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ & ( * , . 0 1ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ & ( + - / 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % ' ) + - .ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŠÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ & ( * , -ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ©ÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ & ( + +ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % ' ) *ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ & ( )ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ & 'ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % &ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ·ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ $ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " #ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿœÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! !ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÎÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+       ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+      ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÜÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿäÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿêÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 	ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïÿñÿóÿõÿ÷ÿùÿüÿþ       ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòÿôÿöÿøÿúÿüÿþ      ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõÿ÷ÿùÿûÿýÿÿ     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿùÿüÿþ     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûÿüÿþ    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ   ÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ     ÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ       ÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ         ÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	ÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+ÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+  ÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+    ÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+      ÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+        ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+          ÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+            ÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+              ÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+ ÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    !ÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " #ÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ %ÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & 'ÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( )ÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * +ÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , -ÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . /ÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1ÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3ÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7ÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9ÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ;ÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < =           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ?                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿ
+ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¥ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿªÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ­ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ°ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ³ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»ÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÁÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÄÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ£ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿŠÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÌÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿ§ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÏÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÒÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿªÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÕÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿ¬ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ­ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ®ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÝÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ±ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ³ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿæÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿŽÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿµÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ·ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿîÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿžÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿºÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿ»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷ÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿœÿÿÿÿÿÿÿÿÿÿÿÿÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿŸÿÿÿÿÿÿÿÿÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿ¿ÿÿÿÿÿÿÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿÁ      ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÿ         ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÃÿÿÿÿ          ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÿÿÿÿÿÿÿ            ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÿÿÿÿÿÿÿÿÿÿÿ              ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÎÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                  ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÑÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 	 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÔÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+  
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÜÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿßÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ       
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿâÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ         
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿåÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ           
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ             
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ               
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                 
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                   
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                     
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿöÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+                     
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+  
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+ 
+ 	 	                 ÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+ 
+ 	 	            ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ! ! !     
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+ 
+ 	 	       ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ " # " ! !     
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+ 
+ 	 	   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ $ $ $ # " ! !     
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+ 
+ 	ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ % & % $ $ # " ! !     
+ 
+ 
+ 
+                     
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ & ' & & % $ $ # " ! !     
+ 
+ 
+ 
+                  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ( ( ( ' & & % $ $ # " ! !     
+ 
+ 
+ 
+              ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ) * ) ( ( ' & & % $ $ # " ! !     
+ 
+ 
+ 
+          ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ + + + * ) ( ( ' & & % $ $ # " ! !     
+ 
+ 
+ 
+      ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ , - , + + * ) ( ( ' & & % $ $ # " ! !     
+ 
+ 
+ 
+  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ - . - - , + + * ) ( ( ' & & % $ $ # " ! !     
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ / 0 / . - - , + + * ) ( ( ' & & % $ $ # " ! ! ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0 1 0 0 / . - - , + + * ) ( ( ' & & % $ $ "ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 2 2 2 1 0 0 / . - - , + + * ) ( ( ' & %ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 3 4 3 2 2 1 0 0 / . - - , + + * ) (ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 5 5 4 4 3 2 2 1 0 0 / . - - , +ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 6 7 6 5 4 4 3 2 2 1 0 0 / -ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 7 8 7 7 6 5 4 4 3 2 2 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 9 9 9 8 7 7 6 5 4 3ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ : ; : 9 9 8 7 6ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ < < < ; : 9ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ = > = <ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ > >ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿ   ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+    ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿ   ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿ     ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿ    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿ      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿ 
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿ 
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿ  
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿ  
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿ   
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿ   
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿ    
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿ    
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿ     
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿ     
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿ      
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿ      
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿ       
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿ       
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿ        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿ        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿ 
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿ 
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ   
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠ % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿš ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ© ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿª ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ« * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ® - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ° / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ± 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ² 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽ 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµ 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ· 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿž 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ 8 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿº 9 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ» : 8 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒ ; 9 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœ < : 8 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸ = ; 9 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ > < : 8 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀ ? = ; 9 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁ                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   ÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    ÿþÿüÿûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     ÿþÿüÿùÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     ÿÿÿýÿûÿùÿ÷ÿõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      ÿþÿüÿúÿøÿöÿôÿòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ       ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 	 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿçÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿäÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÜÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿÙÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ       
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÎÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ        
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÅÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ! !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿœÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ # "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿºÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ $ $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ·ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ & % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ' & $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ) ( & $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ * ) ' % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ¬ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ + + ( & $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿ©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ - , * ( & $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿŠÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ . - + ) ' % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0 / - + ( & $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 1 0 . , * ( & $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 2 2 0 - + ) ' % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 4 3 1 / - + ( & $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 5 4 2 0 . , * ( & $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 7 6 4 2 0 - + ) ' % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 8 7 5 3 1 / - + ( & $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ : 9 7 4 2 0 . , * ( & $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ; : 8 6 4 2 0 - + ) ' % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ < < 9 7 5 3 1 / - + ( & $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ > = ; 9 7 4 2 0 . , * ( & $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿ ? > < : 8 6 4 2 0 - + ) ' % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿÿÿ = < 9 7 5 3 1 / - + ( & $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ : 9 7 4 2 0 . , * ( & $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿ
+ÿÿÿÿÿÿÿÿ 7 6 4 2 0 - + ) ' % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 5 3 1 / - + ( & $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 2 0 . , * ( & $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ / - + ) ' % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ , + ( & $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ) ( & $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ & % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ        
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ       
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ¥ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷ÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ§ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿšÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿ©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ«ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ¬ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿéÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ®ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿæÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ¯ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ³ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿµÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿØÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿ¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÕÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿžÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿ¹ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿºÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿŒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÊÿÉÿÆÿÄÿÂÿÀÿŸÿœÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÇÿÆÿÄÿÂÿ¿ÿ¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÄÿÃÿÁÿÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÂÿÁÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              ? > = < ; : 9 8 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	           = < ; : 9 8 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþ ; : 9 8 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿü 9 8 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿú 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿø 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿö 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿô 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿò / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿð - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿî + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿì ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿê ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿè % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿä !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâ  
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿà 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞ               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜ             
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚ           
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØ         
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖ       
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔ     
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒ   
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐ 
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊ         ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈ       ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆ     ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄ   ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ > >ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ < = > =ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 9 : ; < < <ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 6 7 8 9 9 : ; :ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 3 4 5 6 7 7 8 9 9 9ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0 2 2 3 4 4 5 6 7 7 8 7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ - / 0 0 1 2 2 3 4 4 5 6 7 6ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ + , - - . / 0 0 1 2 2 3 4 4 5 5ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ( ) * + + , - - . / 0 0 1 2 2 3 4 3ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ % & ' ( ( ) * + + , - - . / 0 0 1 2 2 2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ " $ $ % & & ' ( ( ) * + + , - - . / 0 0 1 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  ! ! " # $ $ % & & ' ( ( ) * + + , - - . / 0 /ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+     ! ! " # $ $ % & & ' ( ( ) * + + , - - . -ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   
+ 
+ 
+ 
+     ! ! " # $ $ % & & ' ( ( ) * + + , - ,ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ       
+ 
+ 
+ 
+     ! ! " # $ $ % & & ' ( ( ) * + + +ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ           
+ 
+ 
+ 
+     ! ! " # $ $ % & & ' ( ( ) * )ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ               
+ 
+ 
+ 
+     ! ! " # $ $ % & & ' ( ( (ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                   
+ 
+ 
+ 
+     ! ! " # $ $ % & & ' &ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+                     
+ 
+ 
+ 
+     ! ! " # $ $ % & %ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 	 
+ 
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+     ! ! " # $ $ $ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    	 	 
+ 
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+     ! ! " # "ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ        	 	 
+ 
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+     ! ! !ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ             	 	 
+ 
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ                  	 	 
+ 
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+  
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+                     
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+                    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+                  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+                ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+              ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+            ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+          ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿåÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+        ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+      ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÜÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+  
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÔÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 	ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÑÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÎÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ              ÿÿÿÿÿÿÿÿÿÿÿÿÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ            ÿÿÿÿÿÿÿÿÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ          ÿÿÿÿÿÃÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ         ÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ    ÿÿÿÁÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿÿÿÿÿÿÿ¿ÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿÿÿÿÿÿÿÿÿŸÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿÿÿÿÿÿÿÿÿÿÿÿÿœÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿ÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»ÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿžÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ·ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿµÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŽÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿæÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ³ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿãÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ±ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ°ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÝÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ­ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬ÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÕÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿªÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ©ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÏÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ§ÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿÌÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŠÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ£ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÄÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÁÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿŸÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿ»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ³ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ­ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿªÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ¥ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿ
+ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ; = ?ÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 : < >ÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ; =ÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 : <ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ;ÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 :ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9ÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6ÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - /ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , .ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + -ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * ,ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) +ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( *ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' )ÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & (ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % 'ÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ &ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # %ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! #ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   "ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  !ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+  ÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+ ÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+ÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+ÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+       ÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+       ÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+      ÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+      ÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+     ÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+     ÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+    ÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+    ÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+   ÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+   ÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+  ÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+  ÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+ ÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+ ÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+ÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+ÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	ÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ      ÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ    ÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ    ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ   ÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/fits/verified/sOut.fits
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/fits/verified/sOut.fits	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/fits/verified/sOut.fits	(revision 22158)
@@ -0,0 +1,1450 @@
+SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ; = ?ÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 : < >ÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ; =ÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 : <ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ;ÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 :ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9ÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6ÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - /ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , .ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + -ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * ,ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) +ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( *ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' )ÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & (ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % 'ÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ &ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # %ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! #ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   "ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  !ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+  ÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+ ÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+ÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+ÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+       ÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+       ÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+      ÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+      ÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+     ÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+     ÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+    ÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+    ÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+   ÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+   ÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+  ÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+  ÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+ ÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+ ÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+ÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+ÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	ÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ      ÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ    ÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ    ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ   ÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ                                                                                                                                                                                                                                                                                                                                                                                                                                                                  XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀÿÃÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿ÿÂÿÂÿÅÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿœÿÀÿÁÿÄÿÆÿÉÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŒÿ¿ÿ¿ÿÂÿÅÿÈÿÈÿËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»ÿœÿŸÿÁÿÃÿÆÿÇÿÊÿÌÿÍÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¹ÿŒÿœÿ¿ÿÂÿÅÿÅÿÈÿËÿÌÿÎÿÑÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿžÿºÿ»ÿŸÿÁÿÃÿÄÿÇÿÉÿÊÿÍÿÐÿÒÿÓÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¶ÿ¹ÿºÿŒÿ¿ÿÂÿÃÿÅÿÈÿÉÿËÿÎÿÑÿÒÿÔÿ×ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿµÿžÿžÿ»ÿŸÿÀÿÁÿÄÿÇÿÇÿÊÿÍÿÏÿÐÿÓÿÖÿÖÿÙÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŽÿ¶ÿ·ÿºÿŒÿ¿ÿÀÿÂÿÅÿÆÿÉÿËÿÎÿÏÿÑÿÔÿÕÿØÿÚÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²ÿµÿ¶ÿžÿ»ÿŸÿŸÿÁÿÄÿÄÿÇÿÊÿÍÿÍÿÐÿÓÿÓÿÖÿÙÿÚÿÜÿßÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ±ÿ³ÿŽÿ·ÿºÿŒÿœÿÀÿÂÿÃÿÆÿÈÿËÿÌÿÏÿÑÿÒÿÕÿ×ÿØÿÛÿÞÿàÿáÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯ÿ²ÿ³ÿµÿžÿ»ÿŒÿŸÿÁÿÂÿÄÿÇÿÊÿÊÿÍÿÐÿÑÿÓÿÖÿ×ÿÙÿÜÿßÿàÿâÿåÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ÿ±ÿ±ÿŽÿ·ÿ¹ÿºÿœÿÀÿÀÿÃÿÆÿÈÿÉÿÌÿÎÿÏÿÒÿÕÿÕÿØÿÛÿÝÿÞÿáÿäÿäÿçÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬ÿ¯ÿ°ÿ³ÿµÿžÿ¹ÿ»ÿŸÿ¿ÿÂÿÄÿÇÿÈÿÊÿÍÿÎÿÐÿÓÿÔÿ×ÿÙÿÜÿÝÿßÿâÿãÿæÿèÿëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ«ÿ®ÿ®ÿ±ÿŽÿ·ÿ·ÿºÿœÿœÿÀÿÃÿÆÿÆÿÉÿÌÿÌÿÏÿÒÿÒÿÕÿØÿÛÿÛÿÞÿáÿáÿäÿçÿêÿêÿíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿªÿ¬ÿ­ÿ°ÿ²ÿµÿ¶ÿ¹ÿ»ÿŒÿ¿ÿÁÿÄÿÅÿÈÿÊÿËÿÎÿÐÿÑÿÔÿÖÿÙÿÚÿÝÿßÿàÿãÿåÿèÿéÿìÿîÿïÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿšÿ«ÿ¬ÿ®ÿ±ÿŽÿŽÿ·ÿºÿ»ÿœÿÀÿÃÿÃÿÆÿÉÿÊÿÌÿÏÿÐÿÒÿÕÿØÿØÿÛÿÞÿßÿáÿäÿçÿçÿêÿíÿîÿðÿóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ§ÿªÿªÿ­ÿ°ÿ²ÿ³ÿ¶ÿžÿ¹ÿŒÿ¿ÿÁÿÂÿÅÿÇÿÈÿËÿÎÿÎÿÑÿÔÿÖÿ×ÿÚÿÜÿÝÿàÿãÿåÿæÿéÿëÿìÿïÿòÿòÿõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¥ÿšÿ©ÿ¬ÿ®ÿ±ÿ²ÿŽÿ·ÿžÿºÿœÿÀÿÁÿÃÿÆÿÇÿÉÿÌÿÍÿÐÿÒÿÕÿÖÿØÿÛÿÜÿÞÿáÿäÿåÿçÿêÿëÿíÿðÿñÿôÿöÿùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿ§ÿ§ÿªÿ­ÿ°ÿ°ÿ³ÿ¶ÿ¶ÿ¹ÿŒÿŸÿ¿ÿÂÿÅÿÅÿÈÿËÿËÿÎÿÑÿÔÿÔÿ×ÿÚÿÚÿÝÿàÿâÿãÿæÿéÿéÿìÿïÿïÿòÿõÿøÿøÿûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ£ÿ¥ÿŠÿ©ÿ«ÿ®ÿ¯ÿ²ÿŽÿµÿžÿºÿœÿŸÿÀÿÃÿÄÿÇÿÉÿÊÿÍÿÏÿÒÿÓÿÖÿØÿÙÿÜÿÞÿáÿâÿäÿçÿèÿëÿíÿîÿñÿóÿöÿ÷ÿúÿüÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ€ÿ¥ÿ§ÿªÿ­ÿ­ÿ°ÿ³ÿŽÿ¶ÿ¹ÿŒÿŒÿ¿ÿÂÿÂÿÅÿÈÿÉÿËÿÎÿÑÿÑÿÔÿ×ÿØÿÚÿÝÿàÿàÿãÿæÿæÿéÿìÿíÿïÿòÿõÿõÿøÿûÿüÿþ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ£ÿŠÿ©ÿ«ÿ¬ÿ¯ÿ±ÿ²ÿµÿžÿºÿ»ÿŸÿÀÿÁÿÄÿÆÿÇÿÊÿÍÿÏÿÐÿÓÿÕÿÖÿÙÿÜÿÞÿßÿâÿäÿåÿèÿêÿëÿîÿñÿóÿôÿ÷ÿùÿúÿý    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ¢ÿ€ÿ§ÿªÿ«ÿ­ÿ°ÿ±ÿ³ÿ¶ÿ¹ÿºÿŒÿ¿ÿÀÿÂÿÅÿÆÿÈÿËÿÎÿÏÿÑÿÔÿÕÿ×ÿÚÿÝÿÞÿàÿãÿäÿæÿéÿêÿìÿïÿòÿóÿõÿøÿùÿûÿþ    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ£ÿŠÿšÿ©ÿ¬ÿ¯ÿ¯ÿ²ÿµÿ·ÿžÿ»ÿŸÿŸÿÁÿÄÿÄÿÇÿÊÿÌÿÍÿÐÿÓÿÓÿÖÿÙÿÛÿÜÿßÿâÿâÿåÿèÿèÿëÿîÿðÿñÿôÿ÷ÿ÷ÿúÿýÿÿ      	ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ€ÿ§ÿšÿªÿ­ÿ®ÿ±ÿ³ÿ¶ÿ·ÿ¹ÿŒÿœÿÀÿÂÿÃÿÆÿÈÿËÿÌÿÎÿÑÿÒÿÕÿ×ÿÚÿÛÿÝÿàÿáÿäÿæÿçÿêÿìÿïÿðÿòÿõÿöÿùÿûÿþÿÿ     
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ£ÿŠÿŠÿ©ÿ¬ÿ¬ÿ¯ÿ²ÿµÿµÿžÿ»ÿ»ÿŸÿÁÿÂÿÄÿÇÿÊÿÊÿÍÿÐÿÐÿÓÿÖÿÙÿÙÿÜÿßÿßÿâÿåÿæÿèÿëÿîÿîÿñÿôÿôÿ÷ÿúÿýÿý      	 
+ 
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ€ÿ¥ÿšÿªÿ«ÿ®ÿ°ÿ³ÿŽÿ·ÿ¹ÿºÿœÿ¿ÿÀÿÃÿÆÿÈÿÉÿÌÿÎÿÏÿÒÿÔÿ×ÿØÿÛÿÝÿÞÿáÿãÿäÿçÿêÿìÿíÿðÿòÿóÿöÿøÿûÿüÿÿ     
+ 
+   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ£ÿ£ÿŠÿ©ÿªÿ¬ÿ¯ÿ²ÿ²ÿµÿžÿ¹ÿ»ÿŸÿ¿ÿÁÿÄÿÇÿÈÿÊÿÍÿÎÿÐÿÓÿÖÿÖÿÙÿÜÿÝÿßÿâÿãÿåÿèÿëÿìÿîÿñÿòÿôÿ÷ÿúÿúÿý      	 	 
+    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ¢ÿ¥ÿ§ÿšÿ«ÿ®ÿ°ÿ±ÿŽÿ¶ÿ·ÿºÿœÿœÿÀÿÃÿÅÿÆÿÉÿÌÿÌÿÏÿÒÿÔÿÕÿØÿÚÿÛÿÞÿáÿáÿäÿçÿéÿêÿíÿðÿðÿóÿöÿøÿùÿüÿþÿÿ     
+ 
+     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ£ÿŠÿ§ÿ©ÿ¬ÿ¯ÿ°ÿ²ÿµÿ¶ÿžÿ»ÿŒÿ¿ÿÁÿÄÿÅÿÇÿÊÿËÿÎÿÐÿÓÿÔÿÖÿÙÿÚÿÜÿßÿàÿãÿåÿèÿéÿëÿîÿïÿòÿôÿ÷ÿøÿúÿýÿþ      	 
+ 
+      ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ¥ÿ¥ÿšÿ«ÿ­ÿ®ÿ±ÿŽÿŽÿ·ÿºÿºÿœÿÀÿÃÿÃÿÆÿÉÿÉÿÌÿÏÿÒÿÒÿÕÿØÿØÿÛÿÞÿÞÿáÿäÿçÿçÿêÿíÿíÿðÿóÿöÿöÿùÿüÿüÿÿ     
+ 
+        
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ€ÿ§ÿ©ÿ¬ÿ­ÿ¯ÿ²ÿ³ÿ¶ÿžÿ¹ÿŒÿŸÿÁÿÂÿÅÿÇÿÈÿËÿÍÿÐÿÑÿÔÿÖÿ×ÿÚÿÜÿÝÿàÿâÿåÿæÿéÿëÿìÿïÿñÿôÿõÿøÿúÿûÿþ      	 
+ 
+       
+ 
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ£ÿ¥ÿšÿ«ÿ«ÿ®ÿ±ÿ±ÿŽÿ·ÿžÿºÿœÿÀÿÀÿÃÿÆÿÇÿÉÿÌÿÏÿÏÿÒÿÕÿÖÿØÿÛÿÜÿÞÿáÿäÿäÿçÿêÿëÿíÿðÿóÿóÿöÿùÿúÿüÿÿ      
+        
+ 
+   #ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ€ÿ§ÿ©ÿªÿ­ÿ¯ÿ°ÿ³ÿµÿ¶ÿ¹ÿŒÿŸÿ¿ÿÂÿÄÿÅÿÈÿËÿÍÿÎÿÑÿÓÿÔÿ×ÿÚÿÚÿÝÿàÿâÿãÿæÿèÿéÿìÿïÿñÿòÿõÿ÷ÿøÿûÿþ       
+ 
+ 
+       
+  " $ %ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿšÿ©ÿ«ÿ®ÿ¯ÿ±ÿŽÿµÿ·ÿºÿœÿŸÿÀÿÃÿÄÿÆÿÉÿÌÿÍÿÏÿÒÿÓÿÕÿØÿÙÿÜÿÞÿáÿâÿäÿçÿèÿêÿíÿðÿñÿóÿöÿ÷ÿùÿüÿÿ       
+ 
+        
+   # $ & )ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ€ÿŠÿ§ÿªÿ­ÿ­ÿ°ÿ³ÿ³ÿ¶ÿ¹ÿ»ÿŒÿ¿ÿÂÿÂÿÅÿÈÿÊÿËÿÎÿÑÿÑÿÔÿ×ÿ×ÿÚÿÝÿàÿàÿãÿæÿæÿéÿìÿîÿïÿòÿõÿõÿøÿûÿýÿþ     
+ 
+ 
+       
+  ! " % ( ( +ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿŠÿšÿ«ÿ¬ÿ¯ÿ±ÿ²ÿµÿ·ÿºÿ»ÿœÿÀÿÁÿÄÿÆÿÉÿÊÿÌÿÏÿÐÿÓÿÕÿÖÿÙÿÛÿÞÿßÿâÿäÿåÿèÿêÿíÿîÿðÿóÿôÿ÷ÿùÿüÿýÿÿ     	 
+        
+   ! # & ' * , -ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ€ÿ€ÿ§ÿªÿªÿ­ÿ°ÿ±ÿ³ÿ¶ÿ¹ÿ¹ÿŒÿ¿ÿ¿ÿÂÿÅÿÈÿÈÿËÿÎÿÎÿÑÿÔÿÕÿ×ÿÚÿÝÿÝÿàÿãÿäÿæÿéÿìÿìÿïÿòÿòÿõÿøÿûÿûÿþ      
+ 
+       
+   " % % ( + , . 1ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ£ÿŠÿšÿ©ÿ¬ÿ®ÿ¯ÿ²ÿµÿ·ÿžÿ»ÿœÿŸÿÁÿÃÿÆÿÇÿÊÿÌÿÍÿÐÿÒÿÓÿÖÿÙÿÛÿÜÿßÿáÿâÿåÿèÿêÿëÿîÿðÿñÿôÿöÿùÿúÿýÿÿ      	 
+        
+ 
+ ! # $ ' ) * - 0 2 3ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ¡ÿ€ÿ§ÿšÿªÿ­ÿ®ÿ°ÿ³ÿ¶ÿ·ÿ¹ÿŒÿœÿ¿ÿÂÿÅÿÅÿÈÿËÿÌÿÎÿÑÿÒÿÔÿ×ÿÚÿÛÿÝÿàÿáÿãÿæÿéÿêÿìÿïÿðÿòÿõÿøÿøÿûÿþÿÿ     
+ 
+       
+ 
+  " # % ( ) + . 1 2 4 7ÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ£ÿ¥ÿŠÿ©ÿ¬ÿ¬ÿ¯ÿ²ÿŽÿµÿžÿ»ÿ»ÿŸÿÁÿÃÿÄÿÇÿÉÿÊÿÍÿÐÿÐÿÓÿÖÿØÿÙÿÜÿßÿßÿâÿåÿçÿèÿëÿîÿîÿñÿôÿöÿ÷ÿúÿüÿý      	 
+ 
+        
+   ! $ ' ' * - / 0 3 6 6 9ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ€ÿ¥ÿ§ÿªÿ«ÿ®ÿ°ÿ³ÿŽÿ¶ÿ¹ÿºÿœÿ¿ÿÂÿÃÿÅÿÈÿÉÿËÿÎÿÏÿÒÿÔÿ×ÿØÿÚÿÝÿÞÿáÿãÿæÿçÿéÿìÿíÿðÿòÿõÿöÿøÿûÿüÿþ     
+ 
+ 
+       
+    " % & ) + . / 1 4 5 8 : =ÿÿÿÿÿÿ
+ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿ ÿ£ÿ£ÿŠÿ©ÿ©ÿ¬ÿ¯ÿ²ÿ²ÿµÿžÿžÿ»ÿŸÿÁÿÁÿÄÿÇÿÇÿÊÿÍÿÍÿÐÿÓÿÖÿÖÿÙÿÜÿÜÿßÿâÿåÿåÿèÿëÿëÿîÿñÿôÿôÿ÷ÿúÿúÿý       	 	 
+        
+ 
+ ! $ $ ' * - - 0 3 3 6 9 < < ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ¢ÿ¥ÿ§ÿšÿ«ÿ­ÿ°ÿ±ÿŽÿ¶ÿ·ÿºÿŒÿ¿ÿÀÿÃÿÅÿÆÿÉÿËÿÌÿÏÿÑÿÔÿÕÿØÿÚÿÛÿÞÿàÿãÿäÿçÿéÿêÿíÿïÿòÿóÿöÿøÿùÿüÿþÿÿ     
+ 
+       
+ 
+   " # & ( + , / 1 2 5 7 : ; >ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ£ÿŠÿ§ÿ©ÿ¬ÿ¯ÿ¯ÿ²ÿµÿ¶ÿžÿ»ÿŸÿŸÿÁÿÄÿÅÿÇÿÊÿËÿÍÿÐÿÓÿÓÿÖÿÙÿÚÿÜÿßÿâÿâÿåÿèÿéÿëÿîÿñÿñÿôÿ÷ÿøÿúÿýÿþ      	 
+ 
+       
+ 
+ ! " $ ' * * - 0 1 3 6 9 9 <ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ¥ÿ¥ÿšÿ«ÿ­ÿ®ÿ±ÿ³ÿŽÿ·ÿºÿŒÿœÿÀÿÂÿÃÿÆÿÉÿÉÿÌÿÏÿÑÿÒÿÕÿ×ÿØÿÛÿÞÿàÿáÿäÿæÿçÿêÿíÿïÿðÿóÿõÿöÿùÿüÿüÿÿ     
+ 
+        
+     # & ( ) , . / 2 5 7 8 ;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ£ÿ€ÿ§ÿ©ÿ¬ÿ­ÿ¯ÿ²ÿ³ÿµÿžÿ»ÿŒÿŸÿÁÿÂÿÄÿÇÿÈÿËÿÍÿÐÿÑÿÓÿÖÿ×ÿÙÿÜÿßÿàÿâÿåÿæÿèÿëÿîÿïÿñÿôÿõÿ÷ÿúÿûÿþ      	 
+ 
+        
+  " $ ' ( * - . 0 3 6 7 9ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ¢ÿ¥ÿšÿ«ÿ«ÿ®ÿ±ÿ±ÿŽÿ·ÿ¹ÿºÿœÿÀÿÀÿÃÿÆÿÆÿÉÿÌÿÏÿÏÿÒÿÕÿÕÿØÿÛÿÝÿÞÿáÿäÿäÿçÿêÿìÿíÿðÿóÿóÿöÿùÿùÿüÿÿ      
+        
+ 
+   # & & ) , , / 2 4 5 8ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ€ÿŠÿ©ÿªÿ­ÿ¯ÿ°ÿ³ÿµÿžÿ¹ÿ»ÿŸÿ¿ÿÂÿÄÿÅÿÈÿÊÿÍÿÎÿÑÿÓÿÔÿ×ÿÙÿÜÿÝÿßÿâÿãÿæÿèÿëÿìÿîÿñÿòÿõÿ÷ÿøÿûÿý       
+ 
+        
+  ! $ % ( * + . 0 3 4 6ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿšÿšÿ«ÿ®ÿ¯ÿ±ÿŽÿ·ÿ·ÿºÿœÿœÿÀÿÃÿÄÿÆÿÉÿÌÿÌÿÏÿÒÿÓÿÕÿØÿÛÿÛÿÞÿáÿáÿäÿçÿêÿêÿíÿðÿðÿóÿöÿ÷ÿùÿüÿÿÿÿ     
+         
+   # # & ) * , / 2 2 5ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ€ÿŠÿ§ÿªÿ¬ÿ­ÿ°ÿ³ÿµÿ¶ÿ¹ÿ»ÿŒÿ¿ÿÁÿÂÿÅÿÈÿÊÿËÿÎÿÐÿÑÿÔÿ×ÿÙÿÚÿÝÿßÿàÿãÿåÿèÿéÿìÿîÿïÿòÿôÿõÿøÿûÿýÿþ     
+ 
+ 
+       
+  ! " % ' ( + . 0 1 4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ¥ÿŠÿšÿ«ÿ¬ÿ®ÿ±ÿŽÿµÿ·ÿºÿ»ÿœÿÀÿÁÿÃÿÆÿÉÿÊÿÌÿÏÿÐÿÒÿÕÿØÿÙÿÛÿÞÿßÿáÿäÿçÿçÿêÿíÿîÿðÿóÿôÿöÿùÿüÿýÿÿ     
+ 
+        
+   ! # & ' ) , / 0 2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ€ÿ§ÿªÿªÿ­ÿ°ÿ²ÿ³ÿ¶ÿ¹ÿ¹ÿŒÿ¿ÿ¿ÿÂÿÅÿÇÿÈÿËÿÎÿÎÿÑÿÔÿÖÿ×ÿÚÿÝÿÝÿàÿãÿåÿæÿéÿëÿìÿïÿòÿòÿõÿøÿúÿûÿþ     	 
+ 
+       
+ 
+  " % % ( + - . 1ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ£ÿ¥ÿšÿ©ÿ¬ÿ®ÿ±ÿ²ÿŽÿ·ÿžÿ»ÿœÿŸÿÁÿÃÿÆÿÇÿÉÿÌÿÍÿÐÿÒÿÕÿÖÿØÿÛÿÜÿßÿáÿäÿåÿçÿêÿëÿíÿðÿñÿôÿöÿùÿúÿüÿÿ      	 
+        
+ 
+   # $ ' ) , - /ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿ§ÿ§ÿªÿ­ÿ°ÿ°ÿ³ÿ¶ÿ¶ÿ¹ÿŒÿœÿ¿ÿÂÿÅÿÅÿÈÿËÿËÿÎÿÑÿÔÿÔÿ×ÿÚÿÚÿÝÿàÿãÿãÿæÿéÿéÿìÿïÿïÿòÿõÿøÿøÿûÿþÿþ     
+ 
+ 
+      
+ 
+  " " % ( + + .ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŠÿ©ÿ«ÿ®ÿ¯ÿ²ÿŽÿµÿžÿºÿ»ÿŸÿÁÿÃÿÄÿÇÿÉÿÊÿÍÿÏÿÒÿÓÿÖÿØÿÙÿÜÿÞÿáÿâÿåÿçÿèÿëÿíÿîÿñÿóÿöÿ÷ÿúÿüÿý      	 
+ 
+        
+   ! $ & ) * -ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿªÿ­ÿ­ÿ°ÿ³ÿŽÿ¶ÿ¹ÿºÿŒÿ¿ÿÂÿÃÿÅÿÈÿÉÿËÿÎÿÑÿÑÿÔÿ×ÿØÿÚÿÝÿàÿàÿãÿæÿçÿéÿìÿíÿïÿòÿõÿõÿøÿûÿüÿþ     
+ 
+ 
+       
+    " % ( ( +ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬ÿ¯ÿ±ÿ²ÿµÿžÿžÿ»ÿŸÿÀÿÁÿÄÿÇÿÇÿÊÿÍÿÏÿÐÿÓÿÕÿÖÿÙÿÜÿÞÿßÿâÿäÿåÿèÿëÿëÿîÿñÿóÿôÿ÷ÿùÿúÿý       	 
+        
+ 
+ ! $ & ' *ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ°ÿ±ÿ³ÿ¶ÿ·ÿºÿŒÿ¿ÿÀÿÂÿÅÿÆÿÉÿËÿÎÿÏÿÑÿÔÿÕÿ×ÿÚÿÝÿÞÿàÿãÿäÿæÿéÿêÿíÿïÿòÿóÿõÿøÿùÿûÿþ      
+ 
+       
+ 
+   " % & (ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²ÿµÿµÿžÿ»ÿŸÿŸÿÁÿÄÿÄÿÇÿÊÿÍÿÍÿÐÿÓÿÓÿÖÿÙÿÛÿÜÿßÿâÿâÿåÿèÿèÿëÿîÿñÿñÿôÿ÷ÿ÷ÿúÿýÿÿ      	 
+ 
+        
+ ! $ $ 'ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŽÿ·ÿ¹ÿŒÿœÿÀÿÂÿÃÿÆÿÈÿËÿÌÿÏÿÑÿÒÿÕÿ×ÿÚÿÛÿÝÿàÿáÿäÿæÿçÿêÿìÿïÿðÿóÿõÿöÿùÿûÿþÿÿ     
+ 
+        
+  " # &ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿžÿ»ÿ»ÿŸÿÁÿÂÿÄÿÇÿÊÿÊÿÍÿÐÿÑÿÓÿÖÿÙÿÙÿÜÿßÿßÿâÿåÿæÿèÿëÿîÿîÿñÿôÿõÿ÷ÿúÿýÿý      	 
+ 
+        
+ ! ! $ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºÿœÿ¿ÿÀÿÃÿÆÿÈÿÉÿÌÿÎÿÏÿÒÿÕÿ×ÿØÿÛÿÝÿÞÿáÿãÿäÿçÿêÿìÿíÿðÿòÿóÿöÿùÿûÿüÿÿ      
+        
+    #ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸÿ¿ÿÁÿÄÿÇÿÈÿÊÿÍÿÎÿÐÿÓÿÖÿ×ÿÙÿÜÿÝÿßÿâÿãÿåÿèÿëÿìÿîÿñÿòÿôÿ÷ÿúÿûÿý       	 
+        
+  !ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀÿÃÿÅÿÆÿÉÿÌÿÌÿÏÿÒÿÔÿÕÿØÿÛÿÛÿÞÿáÿáÿäÿçÿéÿêÿíÿðÿðÿóÿöÿøÿùÿüÿÿÿÿ     
+ 
+       
+ 
+  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÄÿÅÿÇÿÊÿËÿÎÿÐÿÓÿÔÿÖÿÙÿÚÿÝÿßÿàÿãÿåÿèÿéÿëÿîÿïÿòÿôÿ÷ÿøÿúÿýÿþ     	 
+ 
+       
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÆÿÉÿÉÿÌÿÏÿÒÿÒÿÕÿØÿØÿÛÿÞÿßÿáÿäÿçÿçÿêÿíÿíÿðÿóÿöÿöÿùÿüÿüÿÿ     
+ 
+        
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÿËÿÍÿÐÿÑÿÔÿÖÿ×ÿÚÿÜÿÝÿàÿãÿåÿæÿéÿëÿìÿïÿñÿôÿõÿøÿúÿûÿþ      	 
+ 
+       
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÌÿÏÿÏÿÒÿÕÿÖÿØÿÛÿÜÿÞÿáÿäÿåÿçÿêÿëÿíÿðÿóÿóÿöÿùÿúÿüÿÿ      	 
+       ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÎÿÑÿÓÿÔÿ×ÿÚÿÚÿÝÿàÿâÿãÿæÿéÿéÿìÿïÿñÿòÿõÿ÷ÿøÿûÿþÿþ     
+ 
+ 
+     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÒÿÓÿÕÿØÿÙÿÜÿÞÿáÿâÿäÿçÿèÿëÿíÿðÿñÿóÿöÿ÷ÿùÿüÿý       
+ 
+     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÔÿ×ÿ×ÿÚÿÝÿàÿàÿãÿæÿæÿéÿìÿïÿïÿòÿõÿõÿøÿûÿûÿþ     
+ 
+ 
+    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖÿÙÿÛÿÞÿßÿâÿäÿåÿèÿêÿíÿîÿñÿóÿôÿ÷ÿùÿúÿýÿÿ     	 
+    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÚÿÝÿÝÿàÿãÿäÿæÿéÿìÿìÿïÿòÿóÿõÿøÿùÿûÿþ      
+ 
+   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÜÿßÿáÿâÿåÿèÿêÿëÿîÿðÿñÿôÿ÷ÿ÷ÿúÿýÿÿ      	 
+   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàÿáÿãÿæÿéÿêÿìÿïÿðÿòÿõÿöÿùÿûÿþÿÿ     
+ 
+  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâÿåÿçÿèÿëÿîÿîÿñÿôÿôÿ÷ÿúÿýÿý      	 
+ 
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿæÿçÿéÿìÿíÿðÿòÿóÿöÿøÿûÿüÿÿ     
+ 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿëÿëÿîÿñÿòÿôÿ÷ÿúÿúÿý      	 	 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿêÿíÿïÿðÿóÿöÿøÿùÿüÿþÿÿ     
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿîÿïÿñÿôÿ÷ÿøÿúÿýÿþ      	ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿóÿõÿöÿùÿüÿüÿÿ    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôÿõÿ÷ÿúÿûÿþ     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöÿùÿùÿüÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿûÿý    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ   ÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ     ÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ       ÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ         ÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	ÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+ÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+  ÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+    ÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+      ÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+        ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+          ÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+            ÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+              ÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+ ÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    !ÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " #ÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ %ÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & 'ÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( )ÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * +ÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , -ÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . /ÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1ÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3ÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7ÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9ÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ;ÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < =           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ?                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ£ÿ¡ÿ ÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŠÿ¥ÿ£ÿ€ÿ£ÿ¢ÿ ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿšÿ§ÿ§ÿŠÿ¥ÿŠÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬ÿ«ÿ©ÿšÿ©ÿšÿŠÿ§ÿŠÿ€ÿ£ÿ€ÿ£ÿ¡ÿ¢ÿ¡ÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ÿ­ÿ­ÿ¬ÿ«ÿªÿªÿ©ÿšÿšÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ£ÿ¢ÿ¡ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ°ÿ±ÿ¯ÿ®ÿ¯ÿ®ÿ¬ÿ«ÿ¬ÿªÿ©ÿªÿ©ÿ§ÿŠÿ§ÿ¥ÿ€ÿ¥ÿ£ÿ¢ÿ£ÿ¢ÿ ÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŽÿ³ÿ±ÿ²ÿ±ÿ°ÿ°ÿ¯ÿ®ÿ¬ÿ­ÿ¬ÿ«ÿ«ÿªÿ©ÿ§ÿšÿ§ÿ¥ÿŠÿ¥ÿ€ÿ€ÿ£ÿ¢ÿ ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¶ÿµÿµÿŽÿ³ÿŽÿ²ÿ±ÿ²ÿ°ÿ¯ÿ®ÿ¯ÿ­ÿ¬ÿ­ÿ«ÿªÿ©ÿ©ÿšÿ§ÿšÿŠÿ¥ÿŠÿ€ÿ£ÿ¢ÿ£ÿ¡ÿ ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºÿ¹ÿ·ÿ¶ÿ·ÿ¶ÿŽÿµÿŽÿ²ÿ³ÿ²ÿ±ÿ¯ÿ°ÿ¯ÿ­ÿ®ÿ­ÿ«ÿªÿ«ÿªÿšÿ©ÿšÿŠÿ§ÿŠÿ¥ÿ£ÿ€ÿ£ÿ¡ÿ¢ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŒÿ»ÿ»ÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿµÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ¯ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿªÿ©ÿšÿ©ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ£ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸÿ¿ÿœÿŒÿœÿŒÿºÿ¹ÿºÿžÿ·ÿžÿ·ÿµÿ¶ÿµÿ³ÿ²ÿ³ÿ±ÿ°ÿ±ÿ°ÿ®ÿ­ÿ®ÿ¬ÿ«ÿ¬ÿ«ÿ©ÿªÿ©ÿ§ÿŠÿ§ÿ¥ÿ€ÿ¥ÿ€ÿ¢ÿ¡ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÂÿÁÿ¿ÿÀÿ¿ÿŸÿŸÿœÿŒÿºÿ»ÿºÿ¹ÿ¹ÿžÿ·ÿ·ÿ¶ÿµÿ³ÿŽÿ³ÿ²ÿ²ÿ±ÿ°ÿ®ÿ¯ÿ®ÿ­ÿ­ÿ¬ÿ«ÿ«ÿªÿ©ÿ§ÿšÿ§ÿŠÿŠÿ¥ÿ€ÿ¢ÿ£ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÄÿÅÿÃÿÂÿÁÿÂÿÀÿ¿ÿÀÿŸÿœÿŒÿœÿ»ÿºÿ»ÿ¹ÿžÿ¹ÿ·ÿ¶ÿµÿ¶ÿŽÿ³ÿŽÿ²ÿ±ÿ°ÿ±ÿ¯ÿ®ÿ¯ÿ­ÿ¬ÿ­ÿ«ÿªÿ©ÿªÿšÿ§ÿšÿŠÿ¥ÿ€ÿ¥ÿ£ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÿÇÿÅÿÆÿÅÿÄÿÂÿÃÿÂÿÀÿÁÿÀÿ¿ÿœÿŸÿœÿ»ÿŒÿ»ÿ¹ÿºÿ¹ÿžÿ¶ÿ·ÿ¶ÿŽÿµÿŽÿ³ÿ±ÿ²ÿ±ÿ¯ÿ°ÿ¯ÿ­ÿ®ÿ­ÿ¬ÿªÿ«ÿªÿšÿ©ÿšÿ§ÿ¥ÿŠÿ¥ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÊÿÉÿÉÿÈÿÇÿÈÿÆÿÅÿÄÿÄÿÃÿÂÿÃÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿŒÿºÿ¹ÿžÿžÿ·ÿ¶ÿ·ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ°ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ«ÿ©ÿšÿ§ÿ§ÿŠÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÎÿÍÿËÿÊÿËÿÊÿÈÿÉÿÈÿÆÿÅÿÆÿÅÿÃÿÄÿÃÿÁÿÀÿÁÿ¿ÿŸÿ¿ÿŸÿŒÿœÿŒÿºÿ¹ÿºÿ¹ÿ·ÿžÿ·ÿµÿŽÿµÿ³ÿ²ÿ³ÿ²ÿ°ÿ±ÿ°ÿ®ÿ­ÿ®ÿ­ÿ«ÿ¬ÿ«ÿ©ÿšÿ©ÿšÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÐÿÏÿÏÿÎÿÍÿÌÿÌÿËÿÊÿÊÿÉÿÈÿÇÿÇÿÆÿÅÿÅÿÄÿÃÿÁÿÂÿÁÿÀÿÀÿ¿ÿŸÿŸÿœÿŒÿ»ÿ»ÿºÿ¹ÿ¹ÿžÿ·ÿµÿ¶ÿµÿŽÿŽÿ³ÿ²ÿ²ÿ±ÿ°ÿ¯ÿ¯ÿ®ÿ­ÿ­ÿ¬ÿ«ÿªÿªÿ©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÒÿÓÿÑÿÐÿÑÿÐÿÎÿÍÿÎÿÌÿËÿÌÿËÿÉÿÈÿÉÿÇÿÆÿÇÿÅÿÄÿÃÿÄÿÂÿÁÿÂÿÀÿ¿ÿÀÿ¿ÿœÿŒÿœÿ»ÿºÿ»ÿ¹ÿžÿ·ÿžÿ¶ÿµÿ¶ÿŽÿ³ÿŽÿ³ÿ±ÿ°ÿ±ÿ¯ÿ®ÿ¯ÿ®ÿ¬ÿ«ÿ¬ÿªÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖÿÕÿÓÿÔÿÓÿÒÿÒÿÑÿÐÿÎÿÏÿÎÿÍÿÍÿÌÿËÿÉÿÊÿÉÿÇÿÈÿÇÿÆÿÄÿÅÿÄÿÂÿÃÿÂÿÁÿÁÿÀÿ¿ÿœÿŸÿœÿ»ÿŒÿ»ÿºÿžÿ¹ÿžÿ¶ÿ·ÿ¶ÿµÿµÿŽÿ³ÿ±ÿ²ÿ±ÿ°ÿ°ÿ¯ÿ®ÿ¬ÿ­ÿ¬ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿØÿ×ÿ×ÿÖÿÕÿÖÿÔÿÓÿÔÿÒÿÑÿÐÿÑÿÏÿÎÿÏÿÍÿÌÿËÿËÿÊÿÉÿÊÿÈÿÇÿÆÿÆÿÅÿÄÿÅÿÃÿÂÿÃÿÁÿÀÿ¿ÿ¿ÿŸÿœÿŸÿŒÿ»ÿºÿºÿ¹ÿžÿ¹ÿ·ÿ¶ÿ·ÿµÿŽÿ³ÿŽÿ²ÿ±ÿ²ÿ°ÿ¯ÿ®ÿ®ÿ­ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÜÿÛÿÙÿØÿÙÿØÿÖÿ×ÿÖÿÔÿÕÿÔÿÓÿÑÿÒÿÑÿÏÿÐÿÏÿÍÿÌÿÍÿÌÿÊÿËÿÊÿÈÿÇÿÈÿÇÿÅÿÆÿÅÿÃÿÄÿÃÿÁÿÀÿÁÿÀÿŸÿ¿ÿŸÿŒÿ»ÿŒÿ»ÿ¹ÿºÿ¹ÿ·ÿžÿ·ÿ¶ÿŽÿµÿŽÿ²ÿ³ÿ²ÿ°ÿ¯ÿ°ÿ¯ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞÿÝÿÝÿÜÿÛÿÚÿÚÿÙÿØÿØÿ×ÿÖÿ×ÿÕÿÔÿÓÿÓÿÒÿÑÿÑÿÐÿÏÿÎÿÎÿÍÿÌÿÌÿËÿÊÿÉÿÉÿÈÿÇÿÇÿÆÿÅÿÅÿÄÿÃÿÂÿÂÿÁÿÀÿÀÿ¿ÿŸÿœÿœÿŒÿ»ÿ»ÿºÿ¹ÿºÿžÿ·ÿ¶ÿ¶ÿµÿŽÿŽÿ³ÿ²ÿ±ÿ±ÿ°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàÿáÿßÿÞÿßÿÞÿÜÿÛÿÜÿÚÿÙÿÚÿÙÿ×ÿØÿ×ÿÕÿÔÿÕÿÓÿÒÿÓÿÒÿÐÿÏÿÐÿÎÿÍÿÎÿÍÿËÿÊÿËÿÉÿÈÿÉÿÇÿÆÿÇÿÆÿÄÿÃÿÄÿÂÿÁÿÂÿÁÿ¿ÿŸÿ¿ÿœÿŒÿœÿŒÿºÿ»ÿºÿžÿ·ÿžÿ¶ÿµÿ¶ÿµÿ³ÿ²ÿ³ÿ±ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿäÿãÿáÿâÿáÿàÿàÿßÿÞÿÜÿÝÿÜÿÛÿÛÿÚÿÙÿÙÿØÿ×ÿÕÿÖÿÕÿÔÿÔÿÓÿÒÿÐÿÑÿÐÿÏÿÏÿÎÿÍÿËÿÌÿËÿÉÿÊÿÉÿÈÿÈÿÇÿÆÿÄÿÅÿÄÿÃÿÃÿÂÿÁÿ¿ÿÀÿ¿ÿŸÿŸÿœÿŒÿŒÿ»ÿºÿžÿ¹ÿžÿ·ÿ·ÿ¶ÿµÿ³ÿŽÿ³ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿæÿçÿåÿäÿãÿäÿâÿáÿâÿàÿßÿÞÿßÿÝÿÜÿÝÿÛÿÚÿÛÿÙÿØÿ×ÿØÿÖÿÕÿÖÿÔÿÓÿÒÿÓÿÑÿÐÿÑÿÏÿÎÿÍÿÍÿÌÿËÿÌÿÊÿÉÿÊÿÈÿÇÿÆÿÇÿÅÿÄÿÅÿÃÿÂÿÁÿÂÿÀÿ¿ÿÀÿŸÿœÿŸÿŒÿ»ÿºÿ»ÿ¹ÿžÿ¹ÿ·ÿ¶ÿµÿ¶ÿŽÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿêÿéÿçÿèÿçÿæÿäÿåÿäÿâÿãÿâÿáÿßÿàÿßÿÝÿÞÿÝÿÛÿÜÿÛÿÚÿØÿÙÿØÿÖÿ×ÿÖÿÕÿÓÿÔÿÓÿÑÿÒÿÑÿÏÿÎÿÏÿÎÿÌÿÍÿÌÿÊÿËÿÊÿÉÿÇÿÈÿÇÿÅÿÆÿÅÿÄÿÂÿÃÿÂÿÀÿÁÿÀÿŸÿ¿ÿŸÿœÿ»ÿŒÿ»ÿ¹ÿºÿ¹ÿžÿ¶ÿ·ÿ¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìÿëÿëÿêÿéÿêÿèÿçÿæÿæÿåÿäÿåÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÞÿÜÿÛÿÚÿÚÿÙÿØÿÙÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿÍÿËÿÊÿÉÿÉÿÈÿÇÿÈÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿÁÿ¿ÿŸÿœÿœÿŒÿ»ÿŒÿºÿ¹ÿžÿžÿ·ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿîÿïÿíÿìÿíÿìÿêÿëÿêÿèÿçÿèÿçÿåÿæÿåÿãÿâÿãÿáÿàÿáÿàÿÞÿßÿÞÿÜÿÛÿÜÿÛÿÙÿÚÿÙÿ×ÿÖÿ×ÿÕÿÔÿÕÿÔÿÒÿÑÿÒÿÐÿÏÿÐÿÏÿÍÿÎÿÍÿËÿÊÿËÿÊÿÈÿÉÿÈÿÆÿÅÿÆÿÄÿÃÿÄÿÃÿÁÿÂÿÁÿ¿ÿŸÿ¿ÿŸÿŒÿœÿŒÿºÿ¹ÿºÿžÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòÿñÿïÿðÿïÿîÿîÿíÿìÿìÿëÿêÿéÿéÿèÿçÿçÿæÿåÿãÿäÿãÿâÿâÿáÿàÿàÿßÿÞÿÝÿÝÿÜÿÛÿÛÿÚÿÙÿ×ÿØÿ×ÿÖÿÖÿÕÿÔÿÒÿÓÿÒÿÑÿÑÿÐÿÏÿÏÿÎÿÍÿÌÿÌÿËÿÊÿÊÿÉÿÈÿÆÿÇÿÆÿÅÿÅÿÄÿÃÿÃÿÂÿÁÿÀÿÀÿ¿ÿŸÿŸÿœÿŒÿºÿ»ÿºÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôÿõÿóÿòÿñÿòÿðÿïÿðÿîÿíÿîÿíÿëÿêÿëÿéÿèÿéÿçÿæÿåÿæÿäÿãÿäÿâÿáÿâÿáÿßÿÞÿßÿÝÿÜÿÝÿÛÿÚÿÙÿÚÿØÿ×ÿØÿÖÿÕÿÔÿÕÿÓÿÒÿÓÿÑÿÐÿÑÿÐÿÎÿÍÿÎÿÌÿËÿÌÿÊÿÉÿÈÿÉÿÇÿÆÿÇÿÅÿÄÿÅÿÄÿÂÿÁÿÂÿÀÿ¿ÿÀÿŸÿœÿŒÿœÿ»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿ÷ÿõÿöÿõÿôÿòÿóÿòÿðÿñÿðÿïÿïÿîÿíÿëÿìÿëÿéÿêÿéÿèÿæÿçÿæÿäÿåÿäÿãÿãÿâÿáÿßÿàÿßÿÝÿÞÿÝÿÜÿÚÿÛÿÚÿØÿÙÿØÿ×ÿÕÿÖÿÕÿÓÿÔÿÓÿÒÿÒÿÑÿÐÿÎÿÏÿÎÿÌÿÍÿÌÿËÿÉÿÊÿÉÿÇÿÈÿÇÿÆÿÆÿÅÿÄÿÂÿÃÿÂÿÀÿÁÿÀÿ¿ÿœÿŸÿœÿÿÿÿÿÿÿÿÿÿÿÿÿúÿùÿùÿøÿ÷ÿøÿöÿõÿôÿôÿóÿòÿóÿñÿðÿñÿïÿîÿíÿíÿìÿëÿìÿêÿéÿèÿèÿçÿæÿçÿåÿäÿåÿãÿâÿáÿáÿàÿßÿàÿÞÿÝÿÜÿÜÿÛÿÚÿÛÿÙÿØÿ×ÿ×ÿÖÿÕÿÖÿÔÿÓÿÔÿÒÿÑÿÐÿÐÿÏÿÎÿÏÿÍÿÌÿËÿËÿÊÿÉÿÊÿÈÿÇÿÈÿÆÿÅÿÄÿÄÿÃÿÂÿÃÿÁÿÀÿ¿ÿ¿ÿŸÿÿÿÿÿÿÿÿÿþÿýÿûÿúÿûÿúÿøÿùÿøÿöÿõÿöÿõÿóÿôÿóÿñÿòÿñÿïÿîÿïÿîÿìÿíÿìÿêÿéÿêÿéÿçÿèÿçÿåÿæÿåÿãÿâÿãÿâÿàÿáÿàÿÞÿÝÿÞÿÝÿÛÿÜÿÛÿÙÿØÿÙÿØÿÖÿ×ÿÖÿÔÿÕÿÔÿÒÿÑÿÒÿÑÿÏÿÐÿÏÿÍÿÌÿÍÿÌÿÊÿËÿÊÿÈÿÉÿÈÿÆÿÅÿÆÿÅÿÃÿÄÿÃÿÁÿÀÿÁÿÀÿÿÿÿ  ÿÿÿÿÿþÿýÿüÿüÿûÿúÿúÿùÿøÿ÷ÿ÷ÿöÿõÿõÿôÿóÿóÿòÿñÿðÿðÿïÿîÿîÿíÿìÿëÿëÿêÿéÿéÿèÿçÿçÿæÿåÿäÿäÿãÿâÿâÿáÿàÿßÿßÿÞÿÝÿÝÿÜÿÛÿÚÿÚÿÙÿØÿØÿ×ÿÖÿÖÿÕÿÔÿÓÿÓÿÒÿÑÿÑÿÐÿÏÿÎÿÎÿÍÿÌÿÌÿËÿÊÿÊÿÉÿÈÿÇÿÇÿÆÿÅÿÅÿÄÿÃÿÂÿÂÿÁÿÿÿÿ      ÿþÿýÿþÿüÿûÿüÿûÿùÿøÿùÿ÷ÿöÿ÷ÿõÿôÿõÿôÿòÿñÿòÿðÿïÿðÿïÿíÿìÿíÿëÿêÿëÿéÿèÿéÿèÿæÿåÿæÿäÿãÿäÿãÿáÿàÿáÿßÿÞÿßÿÞÿÜÿÛÿÜÿÚÿÙÿÚÿØÿ×ÿØÿ×ÿÕÿÔÿÕÿÓÿÒÿÓÿÒÿÐÿÏÿÐÿÎÿÍÿÎÿÌÿËÿÌÿËÿÉÿÈÿÉÿÇÿÆÿÇÿÆÿÄÿÃÿÿÿÿÿÿÿÿ      ÿþÿÿÿþÿýÿýÿüÿûÿùÿúÿùÿ÷ÿøÿ÷ÿöÿöÿõÿôÿòÿóÿòÿñÿñÿðÿïÿíÿîÿíÿëÿìÿëÿêÿêÿéÿèÿæÿçÿæÿåÿåÿäÿãÿáÿâÿáÿàÿàÿßÿÞÿÜÿÝÿÜÿÚÿÛÿÚÿÙÿÙÿØÿ×ÿÕÿÖÿÕÿÔÿÔÿÓÿÒÿÐÿÑÿÐÿÎÿÏÿÎÿÍÿÍÿÌÿËÿÉÿÊÿÉÿÈÿÈÿÇÿÿÿÿÿÿÿÿÿÿÿÿ        ÿÿÿþÿÿÿýÿüÿûÿûÿúÿùÿúÿøÿ÷ÿøÿöÿõÿôÿõÿóÿòÿóÿñÿðÿïÿïÿîÿíÿîÿìÿëÿìÿêÿéÿèÿéÿçÿæÿçÿåÿäÿãÿäÿâÿáÿâÿàÿßÿÞÿÞÿÝÿÜÿÝÿÛÿÚÿÛÿÙÿØÿ×ÿØÿÖÿÕÿÖÿÔÿÓÿÒÿÒÿÑÿÐÿÑÿÏÿÎÿÏÿÍÿÌÿËÿÌÿÊÿÉÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ        ÿÿ  ÿÿÿýÿüÿýÿüÿúÿûÿúÿøÿùÿøÿ÷ÿõÿöÿõÿóÿôÿóÿñÿðÿñÿðÿîÿïÿîÿìÿíÿìÿëÿéÿêÿéÿçÿèÿçÿæÿäÿåÿäÿâÿãÿâÿàÿßÿàÿßÿÝÿÞÿÝÿÛÿÜÿÛÿÚÿØÿÙÿØÿÖÿ×ÿÖÿÔÿÓÿÔÿÓÿÑÿÒÿÑÿÏÿÐÿÏÿÎÿÌÿÍÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ            ÿÿÿþÿþÿýÿüÿüÿûÿúÿûÿùÿøÿ÷ÿ÷ÿöÿõÿõÿôÿóÿòÿòÿñÿðÿðÿïÿîÿïÿíÿìÿëÿëÿêÿéÿêÿèÿçÿæÿæÿåÿäÿäÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÞÿÜÿÛÿÚÿÚÿÙÿØÿØÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÒÿÐÿÏÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 	            ÿÿ  ÿþÿýÿþÿýÿûÿüÿûÿùÿøÿùÿ÷ÿöÿ÷ÿöÿôÿóÿôÿòÿñÿòÿñÿïÿðÿïÿíÿìÿíÿìÿêÿëÿêÿèÿçÿèÿæÿåÿæÿåÿãÿâÿãÿáÿàÿáÿàÿÞÿßÿÞÿÜÿÛÿÜÿÚÿÙÿÚÿÙÿ×ÿÖÿ×ÿÕÿÔÿÕÿÔÿÒÿÓÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 	 	              ÿÿÿÿÿþÿýÿýÿüÿûÿùÿúÿùÿøÿøÿ÷ÿöÿôÿõÿôÿóÿóÿòÿñÿñÿðÿïÿîÿîÿíÿìÿìÿëÿêÿèÿéÿèÿçÿçÿæÿåÿãÿäÿãÿâÿâÿáÿàÿàÿßÿÞÿÜÿÝÿÜÿÛÿÛÿÚÿÙÿ×ÿØÿ×ÿÖÿÖÿÕÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 
+ 	              ÿÿÿþÿÿÿýÿüÿûÿüÿúÿùÿúÿøÿ÷ÿöÿ÷ÿõÿôÿõÿóÿòÿóÿòÿðÿïÿðÿîÿíÿîÿìÿëÿêÿëÿéÿèÿéÿçÿæÿåÿæÿäÿãÿäÿâÿáÿâÿàÿßÿÞÿßÿÝÿÜÿÝÿÛÿÚÿÙÿÚÿØÿ×ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 
+ 
+ 
+  	           ÿÿ  ÿÿÿþÿüÿýÿüÿúÿûÿúÿùÿ÷ÿøÿ÷ÿõÿöÿõÿôÿôÿóÿòÿðÿñÿðÿîÿïÿîÿíÿëÿìÿëÿéÿêÿéÿèÿæÿçÿæÿäÿåÿäÿâÿãÿâÿáÿßÿàÿßÿÝÿÞÿÝÿÜÿÚÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+  
+ 
+ 
+ 
+ 	  	            ÿÿÿþÿþÿýÿüÿýÿûÿúÿùÿùÿøÿ÷ÿøÿöÿõÿöÿôÿóÿòÿòÿñÿðÿñÿïÿîÿíÿíÿìÿëÿìÿêÿéÿèÿèÿçÿæÿæÿåÿäÿåÿãÿâÿáÿáÿàÿßÿàÿÞÿÝÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     
+ 
+ 
+ 
+ 	 
+ 	            ÿÿ  ÿÿÿýÿþÿýÿûÿúÿûÿúÿøÿùÿøÿöÿ÷ÿöÿôÿóÿôÿóÿñÿòÿñÿïÿîÿïÿîÿìÿíÿìÿêÿéÿêÿèÿçÿèÿçÿåÿæÿåÿãÿâÿãÿâÿàÿáÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      
+ 
+ 
+ 
+ 
+ 
+ 	              ÿÿÿÿÿþÿýÿüÿüÿûÿúÿúÿùÿøÿøÿ÷ÿöÿõÿõÿôÿóÿóÿòÿñÿðÿðÿïÿîÿîÿíÿìÿêÿëÿêÿéÿéÿèÿçÿçÿæÿåÿäÿäÿãÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ        
+ 
+ 
+ 
+ 
+ 	 
+                ÿþÿýÿþÿüÿûÿüÿúÿùÿúÿùÿ÷ÿöÿ÷ÿõÿôÿõÿôÿòÿñÿòÿðÿïÿðÿîÿíÿìÿíÿëÿêÿëÿéÿèÿéÿèÿæÿåÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ         
+  
+ 
+ 
+ 
+ 
+  	             ÿþÿÿÿþÿüÿýÿüÿûÿûÿúÿùÿ÷ÿøÿ÷ÿöÿöÿõÿôÿòÿóÿòÿðÿñÿðÿïÿíÿîÿíÿëÿìÿëÿêÿêÿéÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ            
+ 
+ 
+ 
+ 
+ 
+ 	  	             ÿÿÿþÿÿÿýÿüÿýÿûÿúÿùÿúÿøÿ÷ÿøÿöÿõÿôÿôÿóÿòÿóÿñÿðÿïÿïÿîÿíÿîÿìÿëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ             
+  
+ 
+ 
+ 
+ 	 
+ 	           ÿÿ  ÿÿÿýÿþÿýÿüÿúÿûÿúÿøÿùÿøÿöÿõÿöÿõÿóÿôÿóÿñÿðÿñÿðÿîÿïÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                
+ 
+ 
+ 
+ 
+ 
+ 	              ÿÿ  ÿþÿýÿüÿüÿûÿúÿúÿùÿøÿ÷ÿ÷ÿöÿõÿõÿôÿóÿòÿòÿñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                   
+ 
+ 
+ 
+ 	 
+                ÿþÿýÿþÿüÿûÿüÿûÿùÿøÿùÿ÷ÿöÿ÷ÿöÿôÿóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                     
+ 
+ 
+ 
+ 
+ 	 	             ÿþÿÿÿþÿýÿýÿüÿûÿùÿúÿùÿøÿøÿ÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+  
+                   
+ 
+ 
+ 
+ 
+ 
+ 	              ÿÿÿþÿÿÿýÿüÿûÿüÿúÿùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 
+ 
+                   
+  
+ 
+ 
+ 
+ 
+  	           ÿÿ  ÿÿÿþÿüÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+  
+ 
+                     
+  
+ 
+ 
+ 
+ 	              ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ !     
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+ 	 
+ 	         ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ " ! !    
+ 
+ 
+ 
+ 
+                    
+ 
+ 
+ 
+ 
+ 
+ 	 	     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ # " # "      
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+ 
+ 
+ 
+  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ % $ $ # "   !   
+  
+ 
+  
+                   
+  
+ 
+ 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ & % & $ # " " !   !  
+ 
+ 
+ 
+  
+                   
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ( & ' & $ # $ # ! " !  
+  
+ 
+ 
+ 
+                ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ) ( ( ' & % % $ # # " !      
+ 
+ 
+ 
+ 
+            ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ * ) * ) ' & ' % $ % $ " ! "      
+ 
+ 
+ 
+         ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ , + + * ) ' ( ' & & % $ " # "   !     
+ 
+  
+    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ - , - + * ) * ( ' ( & % $ $ # " # !   !  
+ 
+ 
+ 
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ / - . - , * + * ( ) ( & % & % # $ # ! " !   
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0 / 0 . - , , + * * ) ( ' ' & % % $ # $ " !ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 2 0 1 0 . - . , + , + ) ( ) ' & ' & $ %ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 3 2 2 1 0 . / . - - , + ) * ) ( ( 'ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 4 3 4 2 1 0 1 / . / - , + , * )ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 6 4 5 4 3 1 2 1 / 0 / . , -ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 7 6 7 5 4 3 3 2 1 2 0 /ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 9 7 8 7 5 4 5 4 2 3ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ : 9 9 8 7 6 6 5ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ; : ; : 8 7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ = < < ;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ > =ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿ   ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+    ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿ   ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿ     ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿ    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿ      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿ 
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿ 
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿ  
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿ  
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿ   
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿ   
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿ    
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿ    
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿ     
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿ     
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿ      
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿ      
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿ       
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿ       
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿ        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿ        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿ 
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿ 
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ   
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠ % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿš ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ© ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿª ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ« * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ® - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ° / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ± 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ² 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽ 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµ 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ· 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿž 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ 8 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿº 9 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ» : 8 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒ ; 9 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœ < : 8 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸ = ; 9 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ > < : 8 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀ ? = ; 9 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁ                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    ÿýÿûÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   ÿÿÿüÿùÿùÿöÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     ÿþÿûÿúÿ÷ÿõÿôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    ÿÿÿüÿüÿùÿöÿõÿóÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 	     ÿþÿýÿúÿøÿ÷ÿôÿñÿïÿîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+    ÿÿÿþÿüÿùÿøÿöÿóÿðÿïÿíÿêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 	 	     ÿýÿúÿúÿ÷ÿôÿòÿñÿîÿëÿëÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 
+    ÿÿÿüÿûÿøÿöÿóÿòÿðÿíÿìÿéÿçÿæÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+ 
+ 	     ÿýÿýÿúÿ÷ÿôÿôÿñÿîÿîÿëÿèÿçÿåÿâÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   
+ 
+    ÿÿÿþÿûÿùÿöÿõÿòÿðÿïÿìÿêÿéÿæÿãÿáÿàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    
+ 	     ÿÿÿýÿúÿ÷ÿ÷ÿôÿñÿðÿîÿëÿêÿèÿåÿâÿáÿßÿÜÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    
+ 
+     ÿþÿûÿùÿøÿõÿóÿòÿïÿìÿìÿéÿæÿäÿãÿàÿÝÿÝÿÚÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     
+ 	    ÿÿÿýÿúÿùÿ÷ÿôÿóÿñÿîÿíÿêÿèÿåÿäÿâÿßÿÞÿÛÿÙÿÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     
+ 
+ 
+    ÿþÿûÿûÿøÿõÿõÿòÿïÿïÿìÿéÿæÿæÿãÿàÿàÿÝÿÚÿ×ÿ×ÿÔÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      
+ 
+      ÿýÿüÿùÿ÷ÿöÿóÿñÿðÿíÿëÿèÿçÿäÿâÿáÿÞÿÜÿÙÿØÿÕÿÓÿÒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      
+ 
+ 
+    ÿþÿþÿûÿøÿ÷ÿõÿòÿñÿïÿìÿéÿéÿæÿãÿâÿàÿÝÿÚÿÚÿ×ÿÔÿÓÿÑÿÎÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ        
+ 	     ÿÿÿüÿúÿùÿöÿóÿóÿðÿíÿëÿêÿçÿåÿäÿáÿÞÿÜÿÛÿØÿÖÿÕÿÒÿÏÿÏÿÌÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+       
+ 
+ 	     ÿþÿûÿúÿøÿõÿôÿñÿïÿìÿëÿéÿæÿåÿãÿàÿÝÿÜÿÚÿ×ÿÖÿÔÿÑÿÐÿÍÿËÿÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+        
+ 
+    ÿÿÿüÿüÿùÿöÿöÿóÿðÿíÿíÿêÿçÿçÿäÿáÿßÿÞÿÛÿØÿØÿÕÿÒÿÒÿÏÿÌÿÉÿÉÿÆÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+       
+ 
+ 	    ÿþÿýÿúÿøÿ÷ÿôÿòÿïÿîÿëÿéÿèÿåÿãÿàÿßÿÝÿÚÿÙÿÖÿÔÿÓÿÐÿÎÿËÿÊÿÇÿÅÿÄÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   
+ 
+       
+ 
+    ÿÿÿÿÿüÿùÿøÿöÿóÿðÿðÿíÿêÿéÿçÿäÿáÿáÿÞÿÛÿÛÿØÿÕÿÔÿÒÿÏÿÌÿÌÿÉÿÆÿÅÿÃÿÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ !  
+        
+ 	      ÿýÿûÿúÿ÷ÿôÿòÿñÿîÿìÿëÿèÿåÿãÿâÿßÿÝÿÜÿÙÿ×ÿÖÿÓÿÐÿÎÿÍÿÊÿÈÿÇÿÄÿÁÿ¿ÿŸÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ #    
+        
+     ÿÿÿüÿûÿùÿöÿóÿòÿðÿíÿìÿêÿçÿäÿãÿáÿÞÿÝÿÛÿØÿ×ÿÕÿÒÿÏÿÎÿÌÿÉÿÈÿÆÿÃÿÀÿ¿ÿœÿºÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ $ ! ! 
+        
+ 
+ 	     ÿýÿýÿúÿ÷ÿõÿôÿñÿîÿîÿëÿèÿæÿåÿâÿßÿßÿÜÿÙÿÙÿÖÿÓÿÑÿÐÿÍÿÊÿÊÿÇÿÄÿÂÿÁÿŸÿ»ÿ»ÿžÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ & # "  
+        
+ 
+    ÿÿÿþÿûÿùÿöÿõÿóÿðÿïÿìÿêÿçÿæÿäÿáÿàÿÝÿÛÿÚÿ×ÿÕÿÒÿÑÿÏÿÌÿËÿÈÿÆÿÃÿÂÿÀÿœÿŒÿ¹ÿ·ÿŽÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ' $ $ ! 
+        
+ 
+ 	     ÿÿÿýÿúÿ÷ÿ÷ÿôÿñÿñÿîÿëÿèÿèÿåÿâÿâÿßÿÜÿÛÿÙÿÖÿÓÿÓÿÐÿÍÿÍÿÊÿÇÿÄÿÄÿÁÿŸÿŸÿ»ÿžÿµÿµÿ²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ( & % "   
+ 
+       
+ 
+     ÿþÿûÿùÿøÿõÿóÿòÿïÿíÿêÿéÿæÿäÿãÿàÿÞÿÝÿÚÿ×ÿÕÿÔÿÑÿÏÿÎÿËÿÉÿÆÿÅÿÂÿÀÿ¿ÿŒÿºÿ·ÿ¶ÿ³ÿ±ÿ°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ * ' & $ ! 
+ 
+        
+ 	      ÿýÿúÿùÿ÷ÿôÿóÿñÿîÿëÿëÿèÿåÿäÿâÿßÿÞÿÜÿÙÿÖÿÕÿÓÿÐÿÏÿÍÿÊÿÇÿÇÿÄÿÁÿÀÿŸÿ»ÿžÿžÿµÿ²ÿ±ÿ¯ÿ¬ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ + ( ( % "    
+       
+ 
+ 
+    ÿþÿüÿûÿøÿõÿõÿòÿïÿíÿìÿéÿçÿæÿãÿàÿàÿÝÿÚÿØÿ×ÿÔÿÑÿÑÿÎÿËÿÉÿÈÿÅÿÃÿÂÿ¿ÿŒÿºÿ¹ÿ¶ÿŽÿ³ÿ°ÿ­ÿ­ÿªÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ - * ) & $ !   
+        
+ 
+ 	     ÿýÿüÿúÿ÷ÿöÿóÿñÿîÿíÿëÿèÿçÿåÿâÿáÿÞÿÜÿÙÿØÿÖÿÓÿÒÿÏÿÍÿÊÿÉÿÇÿÄÿÃÿÁÿŸÿ»ÿºÿžÿµÿŽÿ²ÿ¯ÿ®ÿ«ÿ©ÿŠÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ . + + ( % " "  
+ 
+      
+ 
+ 
+    ÿþÿþÿûÿøÿøÿõÿòÿïÿïÿìÿéÿéÿæÿãÿãÿàÿÝÿÚÿÚÿ×ÿÔÿÔÿÑÿÎÿËÿËÿÈÿÅÿÅÿÂÿ¿ÿœÿŒÿ¹ÿ¶ÿ¶ÿ³ÿ°ÿ°ÿ­ÿªÿ§ÿ§ÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ / - , ) ' $ #   
+ 
+        
+ 	     ÿÿÿüÿúÿùÿöÿôÿñÿðÿíÿëÿêÿçÿåÿäÿáÿßÿÜÿÛÿØÿÖÿÕÿÒÿÐÿÍÿÌÿÉÿÇÿÆÿÃÿÁÿŸÿœÿ»ÿžÿ·ÿŽÿ²ÿ±ÿ®ÿ¬ÿ©ÿšÿ¥ÿ£ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 1 . - + ( % % "  
+ 
+       
+ 
+ 	    ÿþÿûÿúÿøÿõÿòÿòÿïÿìÿëÿéÿæÿåÿãÿàÿÝÿÝÿÚÿ×ÿÖÿÔÿÑÿÎÿÎÿËÿÈÿÇÿÅÿÂÿ¿ÿ¿ÿŒÿ¹ÿ¹ÿ¶ÿ³ÿ²ÿ°ÿ­ÿªÿªÿ§ÿ€ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 2 0 / , ) ' & # !   
+        
+ 
+    ÿÿÿýÿüÿùÿöÿôÿóÿðÿîÿíÿêÿçÿçÿäÿáÿßÿÞÿÛÿÙÿØÿÕÿÒÿÐÿÏÿÌÿÊÿÉÿÆÿÃÿÁÿÀÿœÿ»ÿºÿ·ÿµÿŽÿ±ÿ®ÿ¬ÿ«ÿšÿŠÿ¥ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 4 1 0 . + ( ' % " !  
+       
+ 
+ 
+    ÿþÿýÿûÿøÿõÿôÿòÿïÿîÿìÿéÿèÿåÿãÿàÿßÿÝÿÚÿÙÿ×ÿÔÿÑÿÐÿÎÿËÿÊÿÈÿÅÿÂÿÁÿ¿ÿŒÿ»ÿ¹ÿ¶ÿµÿ³ÿ°ÿ­ÿ¬ÿªÿ§ÿŠÿ€ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 5 2 2 / , * ) & # #   
+         
+    ÿÿÿÿÿüÿùÿ÷ÿöÿóÿðÿðÿíÿêÿêÿçÿäÿáÿáÿÞÿÛÿÛÿØÿÕÿÓÿÒÿÏÿÌÿÌÿÉÿÆÿÄÿÃÿÀÿœÿœÿºÿ·ÿ·ÿŽÿ±ÿ¯ÿ®ÿ«ÿšÿšÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 6 4 3 0 . + * ( % $ !  
+        
+ 
+      ÿýÿûÿøÿ÷ÿõÿòÿñÿîÿìÿëÿèÿæÿãÿâÿßÿÝÿÜÿÙÿ×ÿÔÿÓÿÑÿÎÿÍÿÊÿÈÿÅÿÄÿÂÿ¿ÿŸÿ»ÿ¹ÿžÿµÿ³ÿ°ÿ¯ÿ­ÿªÿ©ÿŠÿ€ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 8 5 4 2 / , , ) & & #   
+ 
+        
+     ÿÿÿüÿùÿùÿöÿóÿóÿðÿíÿìÿêÿçÿäÿäÿáÿÞÿÝÿÛÿØÿÕÿÕÿÒÿÏÿÏÿÌÿÉÿÆÿÆÿÃÿÀÿÀÿœÿºÿ¹ÿ·ÿŽÿ±ÿ±ÿ®ÿ«ÿ«ÿšÿ¥ÿ¢ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 9 7 6 3 0 . - * ( ' $ "  
+        
+ 
+ 	     ÿþÿûÿúÿ÷ÿõÿôÿñÿïÿîÿëÿèÿæÿåÿâÿàÿßÿÜÿÙÿ×ÿÖÿÓÿÑÿÐÿÍÿËÿÈÿÇÿÄÿÂÿÁÿŸÿŒÿ»ÿžÿµÿ³ÿ²ÿ¯ÿ­ÿ¬ÿ©ÿ§ÿ€ÿ£ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ; 8 7 5 2 / . , ) ( & #     
+        
+ 
+    ÿÿÿüÿüÿùÿöÿõÿóÿðÿïÿíÿêÿçÿæÿäÿáÿàÿÞÿÛÿØÿ×ÿÕÿÒÿÑÿÏÿÌÿÉÿÉÿÆÿÃÿÂÿÀÿœÿŒÿºÿ·ÿŽÿ³ÿ±ÿ®ÿ­ÿ«ÿšÿ¥ÿ¥ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ < 9 9 6 3 1 0 - * * ' $ " ! 
+ 
+       
+ 
+ 	     ÿþÿýÿúÿøÿ÷ÿôÿñÿñÿîÿëÿéÿèÿåÿâÿâÿßÿÜÿÚÿÙÿÖÿÓÿÓÿÐÿÍÿËÿÊÿÇÿÅÿÄÿÁÿŸÿŸÿ»ÿžÿ¶ÿµÿ²ÿ¯ÿ¯ÿ¬ÿ©ÿ§ÿŠÿ£ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ > ; : 7 5 2 1 / , + ( & # "   
+ 
+       
+ 
+    ÿÿÿþÿüÿùÿøÿöÿóÿòÿïÿíÿêÿéÿçÿäÿãÿàÿÞÿÛÿÚÿØÿÕÿÔÿÑÿÏÿÌÿËÿÉÿÆÿÅÿÃÿÀÿ¿ÿŒÿºÿ·ÿ¶ÿŽÿ±ÿ°ÿ­ÿ«ÿšÿ§ÿ¥ÿ¢ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ? < < 9 6 3 3 0 - - * ' $ $ ! 
+ 
+        
+ 	 	      ÿýÿúÿúÿ÷ÿôÿôÿñÿîÿëÿëÿèÿåÿåÿâÿßÿÜÿÜÿÙÿÖÿÖÿÓÿÐÿÍÿÍÿÊÿÇÿÇÿÄÿÁÿÁÿŸÿ»ÿžÿžÿµÿ²ÿ²ÿ¯ÿ¬ÿ©ÿ©ÿŠÿ£ÿ£ÿ ÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿ
+ÿÿÿÿÿ = : 8 5 4 1 / . + ) & % "    
+       
+ 
+ 
+    ÿþÿüÿûÿøÿöÿõÿòÿðÿíÿìÿéÿçÿæÿãÿáÿÞÿÝÿÚÿØÿ×ÿÔÿÒÿÏÿÎÿËÿÉÿÈÿÅÿÃÿÂÿ¿ÿœÿºÿ¹ÿ¶ÿŽÿ³ÿ°ÿ®ÿ«ÿªÿ§ÿ¥ÿ€ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 9 6 6 3 0 / - * ' ' $ !   
+        
+ 
+ 	     ÿýÿüÿúÿ÷ÿöÿôÿñÿîÿîÿëÿèÿçÿåÿâÿßÿßÿÜÿÙÿØÿÖÿÓÿÐÿÐÿÍÿÊÿÉÿÇÿÄÿÃÿÁÿŸÿ»ÿ»ÿžÿµÿŽÿ²ÿ¯ÿ¬ÿ¬ÿ©ÿŠÿ¥ÿ£ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿ 7 4 2 1 . + ) ( % # "  
+ 
+       
+ 
+    ÿÿÿþÿûÿøÿøÿõÿòÿðÿïÿìÿêÿéÿæÿãÿáÿàÿÝÿÛÿÚÿ×ÿÔÿÒÿÑÿÎÿÌÿËÿÈÿÅÿÅÿÂÿ¿ÿœÿŒÿ¹ÿ·ÿ¶ÿ³ÿ°ÿ®ÿ­ÿªÿšÿ§ÿ€ÿ¡ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 3 2 0 - * ) ' $ # ! 
+ 
+        
+ 	     ÿÿÿýÿúÿùÿöÿôÿñÿðÿîÿëÿêÿèÿåÿâÿáÿßÿÜÿÛÿÙÿÖÿÓÿÒÿÐÿÍÿÌÿÊÿÇÿÆÿÃÿÁÿŸÿœÿ»ÿžÿ·ÿµÿ²ÿ¯ÿ®ÿ¬ÿ©ÿšÿŠÿ£ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 1 . , + ( % % "   
+       
+ 
+     ÿþÿûÿûÿøÿõÿòÿòÿïÿìÿìÿéÿæÿäÿãÿàÿÝÿÝÿÚÿ×ÿÕÿÔÿÑÿÎÿÎÿËÿÈÿÈÿÅÿÂÿ¿ÿ¿ÿŒÿ¹ÿ¹ÿ¶ÿ³ÿ±ÿ°ÿ­ÿªÿªÿ§ÿ€ÿ€ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ - , * ' & # !   
+        
+ 	    ÿÿÿýÿüÿùÿ÷ÿôÿóÿðÿîÿíÿêÿèÿåÿäÿâÿßÿÞÿÛÿÙÿÖÿÕÿÓÿÐÿÏÿÌÿÊÿÉÿÆÿÄÿÁÿÀÿœÿ»ÿºÿ·ÿµÿ²ÿ±ÿ¯ÿ¬ÿ«ÿšÿŠÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ + ( ( % " !  
+       
+ 
+ 
+    ÿþÿýÿûÿøÿõÿõÿòÿïÿîÿìÿéÿæÿæÿãÿàÿàÿÝÿÚÿ×ÿ×ÿÔÿÑÿÑÿÎÿËÿÊÿÈÿÅÿÂÿÂÿ¿ÿŒÿ»ÿ¹ÿ¶ÿ³ÿ³ÿ°ÿ­ÿ­ÿªÿ§ÿŠÿ€ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ) & $ #   
+        
+ 
+      ÿÿÿüÿùÿ÷ÿöÿóÿñÿðÿíÿêÿèÿçÿäÿâÿáÿÞÿÜÿÙÿØÿÕÿÓÿÒÿÏÿÍÿÌÿÉÿÆÿÄÿÃÿÀÿŸÿœÿºÿ·ÿµÿŽÿ±ÿ¯ÿ®ÿ«ÿ©ÿšÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ % $ "  
+       
+ 
+ 
+      ÿþÿûÿøÿ÷ÿõÿòÿñÿïÿìÿéÿèÿæÿãÿâÿàÿÝÿÚÿÚÿ×ÿÔÿÓÿÑÿÎÿÍÿËÿÈÿÅÿÄÿÂÿ¿ÿŸÿŒÿ¹ÿ¶ÿµÿ³ÿ°ÿ¯ÿ­ÿªÿ©ÿ§ÿ€ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ #   
+ 
+        
+     ÿÿÿüÿúÿùÿöÿóÿóÿðÿíÿëÿêÿçÿäÿäÿáÿÞÿÜÿÛÿØÿÖÿÕÿÒÿÏÿÏÿÌÿÉÿÇÿÆÿÃÿÀÿÀÿœÿºÿžÿ·ÿŽÿ±ÿ±ÿ®ÿ«ÿ«ÿšÿ¥ÿ£ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+ 
+       
+ 
+ 	     ÿþÿûÿúÿøÿõÿôÿñÿïÿìÿëÿéÿæÿåÿâÿàÿÝÿÜÿÚÿ×ÿÖÿÔÿÑÿÐÿÍÿËÿÈÿÇÿÅÿÂÿÁÿŸÿŒÿ¹ÿžÿ¶ÿ³ÿ²ÿ¯ÿ­ÿ¬ÿ©ÿ§ÿ€ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+        
+ 
+    ÿÿÿüÿüÿùÿöÿöÿóÿðÿíÿíÿêÿçÿçÿäÿáÿÞÿÞÿÛÿØÿØÿÕÿÒÿÒÿÏÿÌÿÉÿÉÿÆÿÃÿÃÿÀÿœÿºÿºÿ·ÿŽÿŽÿ±ÿ®ÿ­ÿ«ÿšÿ¥ÿ¥ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ       
+ 
+ 	     ÿþÿýÿúÿøÿ÷ÿôÿòÿïÿîÿëÿéÿèÿåÿãÿàÿßÿÜÿÚÿÙÿÖÿÔÿÓÿÐÿÎÿËÿÊÿÇÿÅÿÄÿÁÿ¿ÿŒÿ»ÿžÿ¶ÿµÿ²ÿ°ÿ¯ÿ¬ÿ©ÿ§ÿŠÿ£ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      
+ 
+    ÿÿÿþÿüÿùÿøÿöÿóÿðÿðÿíÿêÿéÿçÿäÿáÿáÿÞÿÛÿÚÿØÿÕÿÔÿÒÿÏÿÌÿÌÿÉÿÆÿÅÿÃÿÀÿœÿœÿºÿ·ÿ¶ÿŽÿ±ÿ°ÿ®ÿ«ÿšÿ§ÿ¥ÿ¢ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     
+ 	 	     ÿýÿúÿúÿ÷ÿôÿòÿñÿîÿìÿëÿèÿåÿãÿâÿßÿÝÿÜÿÙÿÖÿÖÿÓÿÐÿÎÿÍÿÊÿÈÿÇÿÄÿÁÿ¿ÿŸÿ»ÿ¹ÿžÿµÿ²ÿ²ÿ¯ÿ¬ÿªÿ©ÿŠÿ£ÿ£ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    
+ 
+    ÿÿÿüÿûÿøÿöÿóÿòÿðÿíÿìÿêÿçÿäÿãÿáÿÞÿÝÿÛÿØÿ×ÿÔÿÒÿÏÿÎÿÌÿÉÿÈÿÆÿÃÿÀÿ¿ÿœÿºÿ¹ÿ·ÿŽÿ³ÿ°ÿ®ÿ«ÿªÿšÿ¥ÿ€ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+ 
+ 	     ÿýÿýÿúÿ÷ÿôÿôÿñÿîÿîÿëÿèÿæÿåÿâÿßÿßÿÜÿÙÿÙÿÖÿÓÿÐÿÐÿÍÿÊÿÊÿÇÿÄÿÂÿÁÿŸÿ»ÿ»ÿžÿµÿµÿ²ÿ¯ÿ¬ÿ¬ÿ©ÿŠÿŠÿ£ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+    ÿÿÿþÿûÿùÿöÿõÿòÿðÿïÿìÿêÿçÿæÿäÿáÿàÿÝÿÛÿÚÿ×ÿÕÿÒÿÑÿÎÿÌÿËÿÈÿÆÿÃÿÂÿÀÿœÿŒÿ¹ÿ·ÿ¶ÿ³ÿ±ÿ®ÿ­ÿªÿšÿ§ÿ€ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 	     ÿÿÿýÿúÿ÷ÿ÷ÿôÿñÿðÿîÿëÿèÿèÿåÿâÿâÿßÿÜÿÛÿÙÿÖÿÓÿÓÿÐÿÍÿÌÿÊÿÇÿÄÿÄÿÁÿŸÿŸÿ»ÿžÿ·ÿµÿ²ÿ¯ÿ¯ÿ¬ÿ©ÿšÿŠÿ£ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    ÿþÿûÿùÿøÿõÿóÿòÿïÿìÿêÿéÿæÿäÿãÿàÿÞÿÝÿÚÿ×ÿÕÿÔÿÑÿÏÿÎÿËÿÈÿÆÿÅÿÂÿÀÿ¿ÿŒÿºÿ¹ÿ¶ÿ³ÿ±ÿ°ÿ­ÿ«ÿªÿ§ÿ€ÿ¢ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    ÿýÿúÿùÿ÷ÿôÿóÿñÿîÿëÿêÿèÿåÿäÿâÿßÿÞÿÜÿÙÿÖÿÕÿÓÿÐÿÏÿÍÿÊÿÇÿÆÿÄÿÁÿÀÿŸÿ»ÿºÿžÿµÿ²ÿ±ÿ¯ÿ¬ÿ«ÿ©ÿŠÿ£ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿþÿüÿûÿøÿõÿõÿòÿïÿíÿìÿéÿæÿæÿãÿàÿàÿÝÿÚÿØÿ×ÿÔÿÑÿÑÿÎÿËÿÉÿÈÿÅÿÂÿÂÿ¿ÿŒÿŒÿ¹ÿ¶ÿŽÿ³ÿ°ÿ­ÿ­ÿªÿ§ÿ¥ÿ€ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿüÿúÿ÷ÿöÿóÿñÿîÿíÿëÿèÿçÿäÿâÿáÿÞÿÜÿÙÿØÿÖÿÓÿÒÿÏÿÍÿÊÿÉÿÇÿÄÿÃÿÀÿŸÿœÿºÿžÿµÿŽÿ²ÿ¯ÿ®ÿ«ÿ©ÿŠÿ¥ÿ£ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûÿøÿøÿõÿòÿïÿïÿìÿéÿéÿæÿãÿâÿàÿÝÿÚÿÚÿ×ÿÔÿÔÿÑÿÎÿËÿËÿÈÿÅÿÅÿÂÿ¿ÿŸÿŒÿ¹ÿ¶ÿ¶ÿ³ÿ°ÿ°ÿ­ÿªÿ§ÿ§ÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùÿöÿôÿñÿðÿíÿëÿêÿçÿåÿäÿáÿÞÿÜÿÛÿØÿÖÿÕÿÒÿÐÿÍÿÌÿÉÿÇÿÆÿÃÿÁÿÀÿœÿºÿžÿ·ÿŽÿ²ÿ±ÿ®ÿ¬ÿ©ÿšÿ¥ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõÿòÿòÿïÿìÿëÿéÿæÿåÿãÿàÿÝÿÜÿÚÿ×ÿÖÿÔÿÑÿÎÿÎÿËÿÈÿÇÿÅÿÂÿÁÿ¿ÿŒÿ¹ÿžÿ¶ÿ³ÿ²ÿ°ÿ­ÿªÿªÿ§ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÿðÿîÿíÿêÿçÿçÿäÿáÿßÿÞÿÛÿØÿØÿÕÿÒÿÐÿÏÿÌÿÊÿÉÿÆÿÃÿÃÿÀÿœÿ»ÿºÿ·ÿŽÿŽÿ±ÿ®ÿ¬ÿ«ÿšÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïÿîÿìÿéÿèÿåÿãÿàÿßÿÝÿÚÿÙÿÖÿÔÿÑÿÐÿÎÿËÿÊÿÈÿÅÿÄÿÁÿ¿ÿŒÿ»ÿ¹ÿ¶ÿµÿ²ÿ°ÿ­ÿ¬ÿªÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíÿêÿêÿçÿäÿáÿáÿÞÿÛÿÛÿØÿÕÿÒÿÒÿÏÿÌÿÌÿÉÿÆÿÆÿÃÿÀÿœÿœÿºÿ·ÿ·ÿŽÿ±ÿ®ÿ®ÿ«ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëÿèÿæÿãÿâÿßÿÝÿÜÿÙÿ×ÿÔÿÓÿÐÿÎÿÍÿÊÿÈÿÇÿÄÿÂÿ¿ÿŸÿ»ÿ¹ÿžÿµÿ³ÿ°ÿ¯ÿ¬ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçÿäÿäÿáÿÞÿÝÿÛÿØÿÕÿÕÿÒÿÏÿÎÿÌÿÉÿÈÿÆÿÃÿÀÿÀÿœÿºÿ¹ÿ·ÿŽÿ±ÿ±ÿ®ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿåÿâÿàÿßÿÜÿÙÿ×ÿÖÿÓÿÑÿÐÿÍÿÊÿÊÿÇÿÄÿÂÿÁÿŸÿŒÿ»ÿžÿµÿ³ÿ²ÿ¯ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿáÿàÿÞÿÛÿØÿ×ÿÕÿÒÿÑÿÏÿÌÿËÿÈÿÆÿÃÿÂÿÀÿœÿŒÿºÿ·ÿŽÿ³ÿ±ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßÿÜÿÚÿÙÿÖÿÓÿÓÿÐÿÍÿÍÿÊÿÇÿÄÿÄÿÁÿŸÿŸÿ»ÿžÿ¶ÿµÿ²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÚÿØÿÕÿÔÿÑÿÏÿÎÿËÿÉÿÆÿÅÿÂÿÀÿ¿ÿŒÿºÿ·ÿ¶ÿŽÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙÿÖÿÖÿÓÿÐÿÏÿÍÿÊÿÇÿÇÿÄÿÁÿÀÿŸÿ»ÿžÿžÿµÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ×ÿÔÿÒÿÑÿÎÿËÿÉÿÈÿÅÿÃÿÂÿ¿ÿŒÿºÿ¹ÿ¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÓÿÒÿÐÿÍÿÊÿÉÿÇÿÄÿÃÿÁÿŸÿ»ÿºÿžÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÑÿÎÿÌÿËÿÈÿÅÿÅÿÂÿ¿ÿœÿŒÿ¹ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍÿÌÿÊÿÇÿÆÿÃÿÁÿŸÿœÿ»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËÿÈÿÈÿÅÿÂÿ¿ÿ¿ÿŒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÉÿÆÿÄÿÁÿÀÿœÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅÿÂÿÂÿ¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÃÿÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              ? > = < ; : 9 8 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	           = < ; : 9 8 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþ ; : 9 8 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿü 9 8 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿú 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿø 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿö 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿô 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿò / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿð - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿî + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿì ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿê ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿè % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿä !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâ  
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿà 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞ               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜ             
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚ           
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØ         
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖ       
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔ     
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒ   
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐ 
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊ         ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈ       ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆ     ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄ   ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ = >ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ; < < =ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 7 8 : ; : ;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 5 6 6 7 8 9 9 :ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 3 2 4 5 4 5 7 8 7 9ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ / 0 2 1 2 3 3 4 5 7 6 7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ - , . / 0 / 1 2 1 3 4 5 4 6ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ) * , + , - / . / 1 0 1 2 4 3 4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ' ( ( ) * ) + , - - . / . 0 1 2 2 3ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ % $ & ' & ' ) ( ) + , + , . - . 0 1 0 2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ! " $ # $ % % & ' ' ( ) * * + , , - . 0 / 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+   ! " ! # $ # % & % & ( ) ( * + * , - . - /ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+ 
+ 
+ 
+  !   ! # " # $ $ % & ( ' ( * ) * + - , -ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     
+  
+ 
+     !   " # " $ % & & ' ( ' ) * + + ,ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ          
+ 
+ 
+ 
+      " ! " $ % $ % ' & ' ) * ) *ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ             
+ 
+ 
+ 
+ 
+      ! " # # $ % % & ' ( ( )ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                 
+ 
+ 
+ 
+  
+  ! " ! # $ # $ & ' & (ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+                   
+  
+ 
+ 
+ 
+  !   ! " " # $ & % &ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 
+ 
+  
+                   
+  
+ 
+  
+   !   " # $ $ %ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   
+ 
+ 
+ 
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+      " # " #ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      	 	 
+ 
+ 
+ 
+ 
+ 
+                    
+ 
+ 
+ 
+ 
+    ! ! "ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ          	 
+ 	 
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+     !ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ               	 
+ 
+ 
+ 
+  
+                     
+ 
+  
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿüÿþÿÿ  ÿÿ            	  
+ 
+ 
+ 
+ 
+  
+                   
+ 
+ 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùÿúÿüÿûÿüÿýÿÿÿþÿÿ               	 
+ 
+ 
+ 
+ 
+ 
+                   
+  
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷ÿøÿøÿùÿúÿùÿûÿüÿýÿýÿþÿÿÿþ              	 	 
+ 
+ 
+ 
+ 
+                    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÿôÿöÿ÷ÿöÿ÷ÿùÿøÿùÿûÿüÿûÿüÿþÿýÿþ                 
+ 	 
+ 
+ 
+ 
+                  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñÿòÿòÿóÿôÿõÿõÿöÿ÷ÿ÷ÿøÿùÿúÿúÿûÿüÿüÿýÿþ  ÿÿ               	 
+ 
+ 
+ 
+ 
+ 
+               ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïÿîÿðÿñÿðÿñÿóÿôÿóÿõÿöÿõÿöÿøÿùÿøÿúÿûÿúÿüÿýÿþÿýÿÿ  ÿÿ            	 
+ 	 
+ 
+ 
+ 
+  
+            ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëÿìÿîÿíÿîÿïÿïÿðÿñÿóÿòÿóÿôÿôÿõÿöÿøÿ÷ÿøÿúÿùÿúÿûÿýÿüÿýÿÿÿþÿÿ              	  	 
+ 
+ 
+ 
+ 
+ 
+           ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿéÿêÿêÿëÿìÿëÿíÿîÿíÿïÿðÿñÿðÿòÿóÿòÿôÿõÿöÿöÿ÷ÿøÿ÷ÿùÿúÿûÿûÿüÿýÿüÿþÿÿÿþ              	  
+ 
+ 
+ 
+ 
+  
+        ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿåÿæÿèÿéÿèÿéÿëÿêÿëÿíÿìÿíÿîÿðÿïÿðÿòÿñÿòÿôÿõÿôÿõÿ÷ÿöÿ÷ÿùÿúÿùÿúÿüÿûÿüÿþÿýÿþ                 
+ 	 
+ 
+ 
+ 
+ 
+       ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãÿäÿäÿåÿæÿçÿçÿèÿéÿéÿêÿëÿêÿìÿíÿîÿîÿïÿðÿðÿñÿòÿóÿóÿôÿõÿõÿöÿ÷ÿøÿøÿùÿúÿúÿûÿüÿüÿýÿþÿÿÿÿ               	 
+ 
+ 
+ 
+ 
+ 
+     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿáÿàÿâÿãÿâÿãÿåÿæÿåÿçÿèÿçÿèÿêÿéÿêÿìÿíÿìÿîÿïÿîÿïÿñÿòÿñÿóÿôÿóÿôÿöÿ÷ÿöÿøÿùÿøÿúÿûÿúÿûÿýÿþÿýÿÿ  ÿÿ             	 
+ 	 
+ 
+ 
+ 
+    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÝÿÞÿàÿßÿàÿáÿáÿâÿãÿåÿäÿåÿæÿæÿçÿèÿèÿéÿêÿìÿëÿìÿíÿíÿîÿïÿñÿðÿñÿòÿòÿóÿôÿöÿõÿöÿøÿ÷ÿøÿùÿùÿúÿûÿýÿüÿýÿþÿþÿÿ             	  	 
+ 
+ 
+ 
+  
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÚÿÜÿÝÿÞÿÝÿßÿàÿßÿáÿâÿãÿâÿäÿåÿäÿæÿçÿæÿèÿéÿêÿéÿëÿìÿëÿíÿîÿïÿîÿðÿñÿðÿòÿóÿôÿôÿõÿöÿõÿ÷ÿøÿ÷ÿùÿúÿûÿúÿüÿýÿüÿþÿÿ  ÿÿ            	  
+ 
+ 
+ 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ×ÿØÿÚÿÙÿÚÿÛÿÝÿÜÿÝÿßÿÞÿßÿàÿâÿáÿâÿäÿãÿäÿæÿåÿæÿçÿéÿèÿéÿëÿêÿëÿìÿîÿíÿîÿðÿïÿðÿòÿóÿòÿóÿõÿôÿõÿ÷ÿöÿ÷ÿøÿúÿùÿúÿüÿûÿüÿýÿÿÿþÿÿ               	 
+ 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÕÿÖÿÖÿ×ÿØÿ×ÿÙÿÚÿÛÿÛÿÜÿÝÿÜÿÞÿßÿàÿàÿáÿâÿâÿãÿäÿãÿåÿæÿçÿçÿèÿéÿèÿêÿëÿìÿìÿíÿîÿîÿïÿðÿñÿñÿòÿóÿóÿôÿõÿôÿöÿ÷ÿøÿøÿùÿúÿùÿûÿüÿýÿýÿþÿÿÿÿ               	 	 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÓÿÒÿÔÿÕÿÔÿÕÿ×ÿÖÿ×ÿÙÿÚÿÙÿÚÿÜÿÛÿÜÿÞÿßÿÞÿàÿáÿàÿáÿãÿâÿãÿåÿæÿåÿæÿèÿçÿèÿêÿëÿêÿìÿíÿìÿíÿïÿðÿïÿñÿòÿñÿòÿôÿóÿôÿöÿ÷ÿöÿ÷ÿùÿøÿùÿûÿüÿûÿýÿþÿýÿþ  ÿÿ             	ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÏÿÐÿÒÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿØÿØÿÙÿÚÿÚÿÛÿÜÿÞÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿäÿäÿåÿæÿæÿçÿèÿêÿéÿêÿëÿëÿìÿíÿïÿîÿïÿðÿðÿñÿòÿòÿóÿôÿõÿõÿöÿ÷ÿ÷ÿøÿùÿûÿúÿûÿüÿüÿýÿþÿþÿÿ            ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍÿÌÿÎÿÏÿÐÿÏÿÑÿÒÿÑÿÓÿÔÿÓÿÔÿÖÿ×ÿÖÿØÿÙÿØÿÚÿÛÿÜÿÛÿÝÿÞÿÝÿßÿàÿßÿàÿâÿãÿâÿäÿåÿäÿæÿçÿèÿçÿéÿêÿéÿëÿìÿíÿìÿîÿïÿîÿðÿñÿðÿñÿóÿôÿóÿõÿöÿõÿ÷ÿøÿùÿøÿúÿûÿúÿüÿýÿüÿýÿÿ  ÿÿ        ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÉÿÊÿÌÿËÿÌÿÍÿÏÿÎÿÏÿÑÿÐÿÑÿÒÿÒÿÓÿÔÿÖÿÕÿÖÿØÿ×ÿØÿÙÿÛÿÚÿÛÿÝÿÜÿÝÿÞÿÞÿßÿàÿâÿáÿâÿäÿãÿäÿåÿçÿæÿçÿéÿèÿéÿêÿìÿëÿìÿîÿíÿîÿïÿïÿðÿñÿóÿòÿóÿõÿôÿõÿöÿøÿ÷ÿøÿúÿùÿúÿûÿûÿüÿýÿÿÿþÿÿ        ÿÿÿÿÿÿÿÿÿÿÿÿÿÇÿÈÿÈÿÉÿÊÿÉÿËÿÌÿÍÿÍÿÎÿÏÿÎÿÐÿÑÿÐÿÒÿÓÿÔÿÔÿÕÿÖÿÕÿ×ÿØÿÙÿÙÿÚÿÛÿÚÿÜÿÝÿÜÿÞÿßÿàÿàÿáÿâÿáÿãÿäÿåÿåÿæÿçÿæÿèÿéÿêÿêÿëÿìÿëÿíÿîÿíÿïÿðÿñÿñÿòÿóÿòÿôÿõÿöÿöÿ÷ÿøÿ÷ÿùÿúÿùÿûÿüÿýÿýÿþÿÿÿþ      ÿÿÿÿÿÿÿÿÿÃÿÄÿÆÿÇÿÆÿÇÿÉÿÈÿÉÿËÿÌÿËÿÌÿÎÿÍÿÎÿÐÿÏÿÐÿÒÿÓÿÒÿÓÿÕÿÔÿÕÿ×ÿØÿ×ÿØÿÚÿÙÿÚÿÜÿÛÿÜÿÞÿßÿÞÿßÿáÿàÿáÿãÿäÿãÿäÿæÿåÿæÿèÿéÿèÿéÿëÿêÿëÿíÿìÿíÿïÿðÿïÿðÿòÿñÿòÿôÿõÿôÿõÿ÷ÿöÿ÷ÿùÿøÿùÿûÿüÿûÿüÿþÿýÿþ      ÿÿÿÿÿÁÿÂÿÂÿÃÿÄÿÅÿÅÿÆÿÇÿÇÿÈÿÉÿÊÿÊÿËÿÌÿÌÿÍÿÎÿÎÿÏÿÐÿÑÿÑÿÒÿÓÿÓÿÔÿÕÿÖÿÖÿ×ÿØÿØÿÙÿÚÿÚÿÛÿÜÿÝÿÝÿÞÿßÿßÿàÿáÿâÿâÿãÿäÿäÿåÿæÿçÿçÿèÿéÿéÿêÿëÿëÿìÿíÿîÿîÿïÿðÿðÿñÿòÿóÿóÿôÿõÿõÿöÿ÷ÿ÷ÿøÿùÿúÿúÿûÿüÿüÿýÿþÿÿÿÿ  ÿÿÿÿÿÀÿÁÿÀÿÁÿÃÿÄÿÃÿÅÿÆÿÅÿÆÿÈÿÉÿÈÿÊÿËÿÊÿÌÿÍÿÌÿÍÿÏÿÐÿÏÿÑÿÒÿÑÿÒÿÔÿÕÿÔÿÖÿ×ÿÖÿØÿÙÿØÿÙÿÛÿÜÿÛÿÝÿÞÿÝÿÞÿàÿáÿàÿâÿãÿâÿãÿåÿæÿåÿçÿèÿçÿéÿêÿéÿêÿìÿíÿìÿîÿïÿîÿïÿñÿòÿñÿóÿôÿóÿõÿöÿõÿöÿøÿùÿøÿúÿûÿúÿûÿýÿþÿÿÿÿÿÿÿÿÿŸÿ¿ÿ¿ÿÀÿÁÿÃÿÂÿÃÿÄÿÄÿÅÿÆÿÈÿÇÿÈÿÊÿÉÿÊÿËÿËÿÌÿÍÿÏÿÎÿÏÿÐÿÐÿÑÿÒÿÔÿÓÿÔÿÖÿÕÿÖÿ×ÿ×ÿØÿÙÿÛÿÚÿÛÿÜÿÜÿÝÿÞÿàÿßÿàÿáÿáÿâÿãÿåÿäÿåÿçÿæÿçÿèÿèÿéÿêÿìÿëÿìÿíÿíÿîÿïÿñÿðÿñÿóÿòÿóÿôÿôÿõÿöÿøÿ÷ÿøÿùÿùÿúÿÿÿÿÿÿÿÿÿÿÿÿÿœÿŸÿœÿ¿ÿÀÿÁÿÀÿÂÿÃÿÂÿÄÿÅÿÆÿÆÿÇÿÈÿÇÿÉÿÊÿÉÿËÿÌÿÍÿÌÿÎÿÏÿÎÿÐÿÑÿÒÿÒÿÓÿÔÿÓÿÕÿÖÿÕÿ×ÿØÿÙÿØÿÚÿÛÿÚÿÜÿÝÿÞÿÝÿßÿàÿßÿáÿâÿãÿãÿäÿåÿäÿæÿçÿæÿèÿéÿêÿéÿëÿìÿëÿíÿîÿïÿïÿðÿñÿðÿòÿóÿòÿôÿõÿöÿõÿ÷ÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»ÿœÿŒÿœÿŸÿÀÿ¿ÿÀÿÂÿÁÿÂÿÄÿÅÿÄÿÅÿÇÿÆÿÇÿÉÿÈÿÉÿÊÿÌÿËÿÌÿÎÿÍÿÎÿÐÿÑÿÐÿÑÿÓÿÒÿÓÿÕÿÔÿÕÿÖÿØÿ×ÿØÿÚÿÙÿÚÿÛÿÝÿÜÿÝÿßÿÞÿßÿáÿâÿáÿâÿäÿãÿäÿæÿåÿæÿçÿéÿèÿéÿëÿêÿëÿíÿîÿíÿîÿðÿïÿðÿòÿñÿòÿóÿõÿôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºÿ»ÿºÿŒÿœÿŸÿŸÿ¿ÿÀÿÀÿÁÿÂÿÃÿÃÿÄÿÅÿÅÿÆÿÇÿÆÿÈÿÉÿÊÿÊÿËÿÌÿÌÿÍÿÎÿÏÿÏÿÐÿÑÿÑÿÒÿÓÿÒÿÔÿÕÿÖÿÖÿ×ÿØÿ×ÿÙÿÚÿÛÿÛÿÜÿÝÿÝÿÞÿßÿàÿàÿáÿâÿâÿãÿäÿãÿåÿæÿçÿçÿèÿéÿéÿêÿëÿìÿìÿíÿîÿîÿïÿðÿïÿñÿòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿžÿºÿ¹ÿºÿŒÿœÿŒÿŸÿ¿ÿŸÿ¿ÿÁÿÂÿÁÿÃÿÄÿÃÿÄÿÆÿÅÿÆÿÈÿÉÿÈÿÊÿËÿÊÿËÿÍÿÎÿÍÿÏÿÐÿÏÿÐÿÒÿÑÿÒÿÔÿÕÿÔÿÕÿ×ÿÖÿ×ÿÙÿÚÿÙÿÛÿÜÿÛÿÜÿÞÿßÿÞÿàÿáÿàÿáÿãÿâÿãÿåÿæÿåÿçÿèÿçÿèÿêÿëÿêÿìÿíÿìÿíÿïÿîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ·ÿžÿžÿ¹ÿºÿŒÿ»ÿŒÿœÿœÿŸÿ¿ÿÁÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÈÿÇÿÈÿÉÿÉÿÊÿËÿÍÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿÙÿØÿÙÿÚÿÚÿÛÿÜÿÞÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿåÿäÿåÿæÿæÿçÿèÿêÿéÿêÿëÿëÿìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¶ÿ·ÿ¶ÿžÿ¹ÿºÿ¹ÿ»ÿŒÿ»ÿœÿŸÿ¿ÿŸÿÀÿÁÿÀÿÂÿÃÿÂÿÄÿÅÿÆÿÅÿÇÿÈÿÇÿÉÿÊÿËÿÊÿÌÿÍÿÌÿÎÿÏÿÎÿÏÿÑÿÒÿÑÿÓÿÔÿÓÿÕÿÖÿ×ÿÖÿØÿÙÿØÿÚÿÛÿÜÿÛÿÝÿÞÿÝÿßÿàÿßÿáÿâÿãÿâÿäÿåÿäÿæÿçÿèÿçÿéÿêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŽÿ¶ÿµÿ¶ÿ·ÿ¹ÿžÿ¹ÿ»ÿºÿ»ÿŒÿŸÿœÿŸÿÀÿ¿ÿÀÿÂÿÁÿÂÿÃÿÅÿÄÿÅÿÇÿÆÿÇÿÈÿÊÿÉÿÊÿÌÿËÿÌÿÍÿÍÿÎÿÏÿÑÿÐÿÑÿÓÿÒÿÓÿÔÿÖÿÕÿÖÿØÿ×ÿØÿÙÿÛÿÚÿÛÿÝÿÜÿÝÿßÿÞÿßÿàÿâÿáÿâÿäÿãÿäÿåÿçÿæÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ³ÿŽÿ³ÿµÿ¶ÿ·ÿ·ÿžÿ¹ÿžÿºÿ»ÿŒÿŒÿœÿŸÿŸÿ¿ÿÀÿ¿ÿÁÿÂÿÃÿÃÿÄÿÅÿÄÿÆÿÇÿÈÿÈÿÉÿÊÿÉÿËÿÌÿËÿÍÿÎÿÏÿÏÿÐÿÑÿÐÿÒÿÓÿÔÿÔÿÕÿÖÿÕÿ×ÿØÿÙÿÙÿÚÿÛÿÛÿÜÿÝÿÜÿÞÿßÿàÿàÿáÿâÿáÿãÿäÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ±ÿ³ÿ²ÿ³ÿµÿ¶ÿµÿ¶ÿžÿ·ÿžÿºÿ»ÿºÿŒÿœÿŒÿœÿ¿ÿŸÿ¿ÿÁÿÂÿÁÿÂÿÄÿÃÿÄÿÆÿÇÿÆÿÇÿÉÿÈÿÉÿËÿÊÿËÿÍÿÎÿÍÿÎÿÐÿÏÿÐÿÒÿÓÿÒÿÓÿÕÿÔÿÕÿ×ÿØÿ×ÿÙÿÚÿÙÿÚÿÜÿÛÿÜÿÞÿßÿÞÿßÿáÿàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ°ÿ±ÿ±ÿ²ÿ³ÿŽÿŽÿµÿ¶ÿ¶ÿ·ÿžÿºÿ¹ÿºÿ»ÿ»ÿŒÿœÿœÿŸÿ¿ÿÀÿÀÿÁÿÂÿÂÿÃÿÄÿÅÿÅÿÆÿÇÿÇÿÈÿÉÿÉÿÊÿËÿÌÿÌÿÍÿÎÿÎÿÏÿÐÿÑÿÑÿÒÿÓÿÓÿÔÿÕÿ×ÿÖÿ×ÿØÿØÿÙÿÚÿÚÿÛÿÜÿÝÿÝÿÞÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯ÿ°ÿ¯ÿ°ÿ²ÿ³ÿ²ÿŽÿµÿŽÿ¶ÿ·ÿžÿ·ÿ¹ÿºÿ¹ÿ»ÿŒÿ»ÿŒÿŸÿ¿ÿŸÿÀÿÁÿÀÿÁÿÃÿÄÿÃÿÅÿÆÿÅÿÇÿÈÿÇÿÈÿÊÿËÿÊÿÌÿÍÿÌÿÍÿÏÿÐÿÏÿÑÿÒÿÑÿÓÿÔÿÕÿÔÿÖÿ×ÿÖÿØÿÙÿØÿÙÿÛÿÜÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ­ÿ®ÿ®ÿ¯ÿ°ÿ²ÿ±ÿ²ÿŽÿ³ÿŽÿµÿ·ÿ¶ÿ·ÿ¹ÿžÿ¹ÿºÿºÿ»ÿŒÿŸÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÃÿÂÿÃÿÅÿÄÿÅÿÆÿÆÿÇÿÈÿÊÿÉÿÊÿËÿËÿÌÿÍÿÏÿÎÿÏÿÑÿÐÿÑÿÒÿÔÿÓÿÔÿÖÿÕÿÖÿ×ÿ×ÿØÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬ÿ­ÿ¬ÿ®ÿ¯ÿ°ÿ°ÿ±ÿ²ÿ±ÿ³ÿŽÿµÿµÿ¶ÿ·ÿ¶ÿžÿ¹ÿžÿºÿ»ÿŒÿ»ÿœÿŸÿœÿ¿ÿÀÿÁÿÁÿÂÿÃÿÂÿÄÿÅÿÄÿÆÿÇÿÈÿÇÿÉÿÊÿÉÿËÿÌÿÍÿÍÿÎÿÏÿÎÿÐÿÑÿÒÿÒÿÓÿÔÿÓÿÕÿÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿªÿ¬ÿ«ÿ¬ÿ®ÿ¯ÿ®ÿ¯ÿ±ÿ°ÿ±ÿ³ÿŽÿ³ÿŽÿ¶ÿµÿ¶ÿžÿ·ÿžÿ¹ÿ»ÿºÿ»ÿœÿŒÿœÿ¿ÿÀÿ¿ÿÀÿÂÿÁÿÂÿÄÿÃÿÄÿÅÿÇÿÆÿÇÿÉÿÈÿÉÿËÿÌÿËÿÌÿÎÿÍÿÎÿÐÿÑÿÐÿÑÿÓÿÒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ©ÿªÿªÿ«ÿ¬ÿ­ÿ­ÿ®ÿ¯ÿ¯ÿ°ÿ±ÿ²ÿ²ÿ³ÿŽÿŽÿµÿ¶ÿµÿ·ÿžÿ¹ÿ¹ÿºÿ»ÿ»ÿŒÿœÿŸÿŸÿ¿ÿÀÿÀÿÁÿÂÿÁÿÃÿÄÿÅÿÅÿÆÿÇÿÇÿÈÿÉÿÊÿÊÿËÿÌÿÌÿÍÿÎÿÏÿÏÿÐÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿšÿ©ÿšÿ©ÿ«ÿ¬ÿ«ÿ­ÿ®ÿ­ÿ®ÿ°ÿ±ÿ°ÿ²ÿ³ÿ²ÿ³ÿµÿŽÿµÿ·ÿžÿ·ÿ¹ÿºÿ¹ÿºÿŒÿœÿŒÿŸÿ¿ÿŸÿ¿ÿÁÿÀÿÁÿÃÿÄÿÃÿÅÿÆÿÅÿÆÿÈÿÉÿÈÿÊÿËÿÊÿËÿÍÿÎÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŠÿ§ÿ§ÿšÿ©ÿ«ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ°ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ·ÿ¶ÿ·ÿžÿžÿ¹ÿºÿŒÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÃÿÂÿÃÿÄÿÄÿÅÿÆÿÈÿÇÿÈÿÉÿÉÿÊÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¥ÿŠÿ¥ÿ§ÿšÿ©ÿšÿªÿ«ÿªÿ¬ÿ­ÿ®ÿ­ÿ¯ÿ°ÿ¯ÿ±ÿ²ÿ±ÿ³ÿŽÿµÿŽÿ¶ÿ·ÿ¶ÿžÿ¹ÿºÿ¹ÿ»ÿŒÿ»ÿœÿŸÿœÿ¿ÿÀÿÁÿÀÿÂÿÃÿÂÿÄÿÅÿÆÿÅÿÇÿÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ£ÿ¥ÿ€ÿ¥ÿŠÿšÿ§ÿšÿªÿ©ÿªÿ«ÿ­ÿ¬ÿ­ÿ¯ÿ®ÿ¯ÿ±ÿ°ÿ±ÿ²ÿŽÿ³ÿŽÿ¶ÿµÿ¶ÿ·ÿ¹ÿžÿ¹ÿ»ÿºÿ»ÿœÿŒÿœÿŸÿÀÿ¿ÿÀÿÂÿÁÿÂÿÃÿÅÿÄÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ£ÿ¢ÿ€ÿ¥ÿŠÿŠÿ§ÿšÿ§ÿ©ÿªÿ«ÿ«ÿ¬ÿ­ÿ­ÿ®ÿ¯ÿ®ÿ°ÿ±ÿ²ÿ²ÿ³ÿŽÿ³ÿµÿ¶ÿ·ÿ·ÿžÿ¹ÿ¹ÿºÿ»ÿºÿŒÿœÿŸÿŸÿ¿ÿÀÿ¿ÿÁÿÂÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¡ÿ¢ÿ€ÿ¥ÿ€ÿ¥ÿ§ÿŠÿ§ÿ©ÿªÿ©ÿ«ÿ¬ÿ«ÿ¬ÿ®ÿ­ÿ®ÿ°ÿ±ÿ°ÿ±ÿ³ÿ²ÿ³ÿµÿ¶ÿµÿ·ÿžÿ·ÿžÿºÿ¹ÿºÿŒÿœÿŒÿœÿ¿ÿŸÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ£ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ©ÿšÿ©ÿªÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ¯ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿµÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿ»ÿ»ÿŒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ¢ÿ¡ÿ£ÿ€ÿ£ÿ¥ÿŠÿ§ÿŠÿšÿ©ÿšÿªÿ«ÿªÿ«ÿ­ÿ®ÿ­ÿ¯ÿ°ÿ¯ÿ±ÿ²ÿ³ÿ²ÿŽÿµÿŽÿ¶ÿ·ÿ¶ÿ·ÿ¹ÿºÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ ÿ¡ÿ£ÿ¢ÿ£ÿ€ÿŠÿ¥ÿŠÿšÿ§ÿšÿ©ÿ©ÿªÿ«ÿ­ÿ¬ÿ­ÿ¯ÿ®ÿ¯ÿ°ÿ²ÿ±ÿ²ÿŽÿ³ÿŽÿµÿµÿ¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ ÿ¢ÿ£ÿ€ÿ€ÿ¥ÿŠÿ¥ÿ§ÿšÿ§ÿ©ÿªÿ«ÿ«ÿ¬ÿ­ÿ¬ÿ®ÿ¯ÿ°ÿ°ÿ±ÿ²ÿ±ÿ³ÿŽÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ ÿ¢ÿ£ÿ¢ÿ£ÿ¥ÿ€ÿ¥ÿ§ÿŠÿ§ÿ©ÿªÿ©ÿªÿ¬ÿ«ÿ¬ÿ®ÿ¯ÿ®ÿ¯ÿ±ÿ°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¡ÿ¢ÿ£ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿšÿšÿ©ÿªÿªÿ«ÿ¬ÿ­ÿ­ÿ®ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ¡ÿ¢ÿ¡ÿ£ÿ€ÿ£ÿ€ÿŠÿ§ÿŠÿšÿ©ÿšÿ©ÿ«ÿ¬ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿŠÿ¥ÿŠÿ§ÿ§ÿšÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ ÿ¢ÿ£ÿ€ÿ£ÿ¥ÿŠÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ ÿ¡ÿ£ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ; = ?ÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 : < >ÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ; =ÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 : <ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ;ÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 :ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9ÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6ÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - /ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , .ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + -ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * ,ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) +ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( *ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' )ÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & (ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % 'ÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ &ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # %ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! #ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   "ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  !ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+  ÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+ ÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+ÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+ÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+       ÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+       ÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+      ÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+      ÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+     ÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+     ÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+    ÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+    ÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+   ÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+   ÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+  ÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+  ÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+ ÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+ ÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+ÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+ÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	ÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ      ÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ    ÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ    ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ   ÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/.cvsignore	(revision 22158)
@@ -0,0 +1,38 @@
+temp
+.deps
+.libs
+Makefile
+Makefile.in
+tst_psImageConvolve
+tst_psImageGeomManip
+tst_psImageInterpolate
+tst_psImagePixelExtract
+tst_psImagePixelManip
+tst_psImageStats
+tst_psImageStructManip
+fBiOut.fits
+fOut.fits
+sBiOut.fits
+sOut.fits
+tst_psImageMaskOps
+tst_psImageSmooth
+*.bb
+*.bbg
+*.da
+gmon.out
+tap_psImageShift
+tap_psImageShiftKernel
+tap_psImageConvolve
+tap_psImageConvolve2
+convolutionBench
+tap_psImageInterpolate2
+tap_psImageGeomManip
+tap_psImageMaskOps
+tap_psImagePixelExtract
+tap_psImagePixelManip
+tap_psImageSmooth
+tap_psImageStructManip
+tap_psImageMap
+
+tap_psImageMapFit
+tap_psImageMapFit2
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/Makefile.am	(revision 22158)
@@ -0,0 +1,46 @@
+
+AM_CPPFLAGS = \
+	$(SRCINC) \
+	-I$(top_srcdir)/test/tap/src \
+	-I$(top_srcdir)/test/pstap/src \
+	$(PSLIB_CFLAGS)
+
+AM_LDFLAGS = \
+	$(top_builddir)/src/libpslib.la  \
+	$(top_builddir)/test/tap/src/libtap.la \
+	$(top_builddir)/test/pstap/src/libpstap.la \
+	$(PSLIB_LIBS)
+
+TEST_PROGS = \
+	tap_psImageShift \
+	tap_psImageGeomManip \
+	tap_psImagePixelManip \
+	tap_psImageSmooth \
+	tap_psImageStructManip \
+	tap_psImageConvolve \
+	tap_psImageConvolve2 \
+	tap_psImagePixelExtract \
+	tap_psImageInterpolate2 \
+	tap_psImageMap \
+	tap_psImageMapFit \
+	tap_psImageMapFit2 \
+	tap_psImageMaskOps
+
+#	tap_psImageShiftKernel
+#	tap_psImageInterpolate
+
+if BUILD_TESTS
+bin_PROGRAMS = $(TEST_PROGS)
+TESTS = $(TEST_PROGS)
+else
+check_PROGRAMS = $(TEST_PROGS)
+endif
+
+CLEANFILES = $(check_DATA) temp/* fOut.fits sOut.fits fBiOut.fits sBiOut.fits \
+	core core.* *~ *.bb *.bbg *.da gmon.out
+
+test: check
+
+noinst_PROGRAMS = convolutionBench
+convolutionBench_SOURCES = convolutionBench.c
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/convolutionBench.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/convolutionBench.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/convolutionBench.c	(revision 22158)
@@ -0,0 +1,95 @@
+#include <stdio.h>
+#include <pslib.h>
+
+// Generate image with single high pixel
+static psImage *generateImage(int numCols, int numRows, psRandom *rng)
+{
+    psImage *image = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    for (int y = 0; y < numRows; y++) {
+        for (int x = 0; x < numCols; x++) {
+            image->data.F32[y][x] = psRandomGaussian(rng);
+        }
+    }
+    return image;
+}
+
+
+static psKernel *generateKernel(int numCols, int numRows)
+{
+    psKernel *kernel = psKernelAlloc(-numCols, numCols, -numRows, numRows);
+    for (int y = -numRows; y <= numRows; y++) {
+        for (int x = -numCols; x <= numCols; x++) {
+            kernel->kernel[y][x] = psGaussian(sqrtf((float)(x*x + y*y)), 0.0,
+                                              (float)PS_MIN(numCols, numRows) / 3.0, true);
+        }
+    }
+    return kernel;
+}
+
+static void runBench(int imageCols, int imageRows, int kernelCols, int kernelRows, int iter, psRandom *rng)
+{
+    double direct = 0.0, fft = 0.0;     // Sum of elapsed times for the two methods
+    for (int i = 0; i < iter; i++) {
+        {
+            psImage *image = generateImage(imageCols, imageRows, rng);
+            psKernel *kernel = generateKernel(kernelCols, kernelRows);
+            psTimerStart("direct");
+            psImage *convolved = psImageConvolveDirect(NULL, image, kernel);
+            direct += psTimerMark("direct");
+            psFree(convolved);
+            psFree(kernel);
+            psFree(image);
+            psTimerClear("direct");
+        }
+
+        {
+            psImage *image = generateImage(imageCols, imageRows, rng);
+            psKernel *kernel = generateKernel(kernelCols, kernelRows);
+            psTimerStart("fft");
+            psImage *convolved = psImageConvolveFFT(NULL, image, NULL, 0, kernel);
+            fft += psTimerMark("fft");
+            psFree(convolved);
+            psFree(kernel);
+            psFree(image);
+            psTimerClear("fft");
+        }
+    }
+
+    char size[16];
+    sprintf(size, "%dx%d", imageCols, imageRows);
+    printf("%15s", size);
+    sprintf(size, "%dx%d", 2*kernelCols+1, 2*kernelRows+1);
+    printf(" %15s", size);
+    printf("        %8f        %8f\n", direct / iter, fft / iter);
+}
+
+
+
+int main(int argc, char *argv[])
+{
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0); // Random number generator
+
+    printf("#%14s%16s        %8s        %8s\n", "Image", "Kernel", "Direct", "FFT");
+    runBench( 100,  100, 3, 3, 10, rng);
+    runBench( 200,  200, 3, 3, 10, rng);
+    runBench( 400,  400, 3, 3, 10, rng);
+    runBench( 600,  600, 3, 3, 10, rng);
+    runBench( 800,  800, 3, 3,  8, rng);
+    runBench(1000, 1000, 3, 3,  6, rng);
+    runBench(2000, 2000, 3, 3,  4, rng);
+    runBench(4000, 4000, 3, 3,  2, rng);
+
+    runBench(600, 600,  1,  1, 10, rng);
+    runBench(600, 600,  2,  2, 10, rng);
+    runBench(600, 600,  3,  3, 10, rng);
+    runBench(600, 600,  4,  4, 10, rng);
+    runBench(600, 600,  6,  6,  8, rng);
+    runBench(600, 600,  8,  8,  4, rng);
+    runBench(600, 600, 10, 10,  2, rng);
+    runBench(600, 600, 15, 15,  2, rng);
+
+    psFree(rng);
+    psTimerStop();
+
+    return EXIT_SUCCESS;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageConvolve.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageConvolve.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageConvolve.c	(revision 22158)
@@ -0,0 +1,390 @@
+/** @file  tst_psImageConvolve.c
+ *
+ *  @brief Contains the tests for psImageConvolve.[ch]
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-05-01 00:08:52 $
+ *
+ *  XXX: Must test the tRelative parameter to psKernelGenerate()
+ *  XXX: Must test psImageConvolveFFT()
+ *  XXX: Make sure psImageConvolveDirect() is correct.
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+bool testKernelAlloc(psS32 xMin, psS32 xMax, psS32 yMin, psS32 yMax)
+{
+    {
+        psMemId id = psMemGetId();
+        psKernel *k = psKernelAlloc(xMin, xMax, yMin, yMax);
+        ok(k != NULL, "psKernelAlloc returned non-NULL for [%d:%d,%d:%d]",
+           xMin, xMax, yMin, yMax);
+        skip_start(k == NULL, 2, "Skipping tests because psKernelAlloc() returned NULL");
+        ok(k->xMin == xMin && k->xMax == xMax &&
+           k->yMin == yMin && k->yMax == yMax, "Min/max members, [%d:%d,%d:%d].  Should be [%d:%d,%d:%d]",
+           k->xMin,k->xMax, k->yMin, k->yMax,
+           xMin, xMax, yMin, yMax);
+
+        ok(k->image->numCols == xMax-xMin+1 && k->image->numRows == yMax-yMin+1,
+           "Size of the kernel image (%dx%d vs %dx%d)",
+           xMax-xMin+1, yMax-yMin+1, k->image->numCols, k->image->numRows);
+
+        bool errorFlag = false;
+        for (psS32 j=yMin; j<yMax; j++) {
+            if (k->kernel[j]+xMin != k->image->data.PS_TYPE_KERNEL_DATA[j-yMin]) {
+                diag("ERROR: The kernel pointer was set wrong for row %d", j);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psKernelAlloc() produced the correct data values");
+        skip_end();
+        psFree(k);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Following should be a warning (xMin > xMax)
+    {
+        psMemId id = psMemGetId();
+        psKernel *k = psKernelAlloc(5, -5, -2, 2);
+        ok(k != NULL, "psKernelAlloc returned non-NULL with xMin > xMax");
+        skip_start(k == NULL, 1, "Skipping tests because psKernelAlloc() returned NULL");
+        ok(k->xMin == -5 && k->xMax == 5, "psKernelAlloc did swap xMin & xMax");
+        skip_end();
+        psFree(k);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Following should be a warning (yMin > yMax)
+    {
+        psMemId id = psMemGetId();
+        psKernel *k = psKernelAlloc(-2, 2, 5, -5);
+        ok(k != NULL, "psKernelAlloc returned non-NULL with yMin > yMax");
+        skip_start(k == NULL, 1, "Skipping tests because psKernelAlloc() returned NULL");
+        ok(k->yMin == -5 && k->yMax == 5, "psKernelAlloc did swap yMin & yMax");
+        skip_end();
+        psFree(k);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    return(true);
+}
+
+bool testKernelGenerate(void)
+{
+    psS32 size = 5;
+    psS32 t[] = { 1, 2, 8, 9, 10 };
+    psS32 x[] = { 0, 1, 0, -1, 0 };
+    psS32 y[] = { 2, 1, -1, -2, 0 };
+    float sum;
+
+    {
+        psMemId id = psMemGetId();
+        psVector* xVec = psVectorAlloc(size,PS_TYPE_U32);
+        psVector* yVec = psVectorAlloc(size,PS_TYPE_U32);
+        psVector* tVec = psVectorAlloc(size,PS_TYPE_U32);
+
+        for (psS32 i = 0; i < size; i++) {
+            xVec->data.U32[i] = x[i];
+            yVec->data.U32[i] = y[i];
+            tVec->data.U32[i] = t[i];
+        }
+
+        psKernel* result = psKernelGenerate(tVec, xVec, yVec, false, false);
+        ok(result != NULL, "psKernelGenerate() returned non-NULL");
+        skip_start(result == NULL, 3, "Skipping tests because psKernelGenerate() returned NULL");
+        ok(result->xMin == -1 && result->xMax == 1 &&
+           result->yMin == -2 && result->yMax == 2,
+           "psKernelGenerate result had a range of [%d:%d,%d:%d].  Suppose to be [-2:2,-1:1]",
+           result->xMin, result->xMax, result->yMin, result->yMax);
+
+        sum = 0.0;
+        printf("Resulting kernel:\n");
+        for (psS32 y = result->yMin; y <= result->yMax; y++) {
+            for (psS32 x = result->xMin; x <= result->xMax; x++) {
+                printf(" %6.2f ", result->kernel[y][x]);
+                sum += result->kernel[y][x];
+            }
+            printf("\n");
+        }
+        ok(fabsf(1.0 - sum) <= FLT_EPSILON, "psKernelGenerate result is normalized (sum=%g)", sum);
+
+        ok(fabsf(result->kernel[-2][0] - 0.1) <= FLT_EPSILON &&
+           fabsf(result->kernel[ -1][ -1] - 0.1) <= FLT_EPSILON &&
+           fabsf(result->kernel[ 1][ 0] - 0.6) <= FLT_EPSILON &&
+           fabsf(result->kernel[2][1] - 0.1) <= FLT_EPSILON,
+           "psKernelGenerate result values, %g,%g,%g,%g.  Suppose to be 0.1,0.1,0.6,0.1",
+           result->kernel[-2][0], result->kernel[-1][-1],
+           result->kernel[1][0], result->kernel[2][1]);
+        skip_end();
+        psFree(result);
+        psFree(xVec);
+        psFree(yVec);
+        psFree(tVec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    ok(false, "XXXX: Skipping this psKernelGenerate() because of bugs");
+    if (0) {
+        psMemId id = psMemGetId();
+        psVector* xVec = psVectorAlloc(size,PS_TYPE_U32);
+        psVector* yVec = psVectorAlloc(size,PS_TYPE_U32);
+        psVector* tVec = psVectorAlloc(size,PS_TYPE_U32);
+
+        for (psS32 i = 0; i < size; i++) {
+            xVec->data.S16[i] = x[i];
+            yVec->data.S16[i] = y[i];
+            tVec->data.S16[i] = t[i];
+        }
+
+        psKernel *result = psKernelGenerate(tVec, xVec, yVec, false, true);
+        ok(result != NULL, "psKernelGenerate() returned non-NULL");
+        skip_start(result == NULL, 3, "Skipping tests because psKernelGenerate() returned NULL");
+        ok (result->xMin == 0 && result->xMax == 1 &&
+            result->yMin == 0 && result->yMax == 3,
+            "psKernelGenerate result had a range of [%d:%d,%d:%d].  Suppose to be [0:1,1:2]",
+            result->xMin, result->xMax, result->yMin, result->yMax);
+
+        // XXXX: The bug surfaces here
+        sum = 0.0;
+        if (1) {
+            printf("Resulting kernel (relative=true) (%u - %u) (%u - %u):\n",
+                   result->yMin, result->yMax, result->xMin, result->xMax);
+            for (psS32 y = result->yMin; y <= result->yMax; y++) {
+                // printf("y is %d\n", y);
+                for (psS32 x = result->xMin; x <= result->xMax; x++) {
+                    printf(" %6.2f ", result->kernel[y][x]);
+                    sum += result->kernel[y][x];
+                }
+                printf("\n");
+            }
+        }
+        ok(fabsf(1.0 - sum) <= FLT_EPSILON, "psKernelGenerate result is normalized (sum=%g)", sum);
+
+        ok(fabsf(result->kernel[0][0] - 19.0/30.0) <= FLT_EPSILON &&
+           fabsf(result->kernel[2][0] - 1.0/30.0) <= FLT_EPSILON &&
+           fabsf(result->kernel[2][1] - 8.0/30.0) <= FLT_EPSILON &&
+           fabsf(result->kernel[3][1] - 2.0/30.0) <= FLT_EPSILON,
+           "psKernelGenerate result values, %g,%g;%g,%g. Suppose to be 2,6;1,0",
+           result->kernel[0][0], result->kernel[2][0],
+           result->kernel[2][1], result->kernel[3][1]);
+        skip_end();
+        psFree(result);
+        psFree(xVec);
+        psFree(yVec);
+        psFree(tVec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Following should be an error
+    if (1) {
+        psMemId id = psMemGetId();
+        psVector* xVec = psVectorAlloc(size,PS_TYPE_U32);
+        psVector* yVec = psVectorAlloc(size,PS_TYPE_U32);
+        psVector* tVec = psVectorAlloc(size,PS_TYPE_U32);
+
+        for (psS32 i = 0; i < size; i++) {
+            psVectorSet(xVec, i, x[i]+0.1);
+            yVec->data.F32[i] = y[i]+0.2;
+            tVec->data.F32[i] = t[i]+0.3;
+        }
+
+        tVec->n--; // decrease size by one to make vectors unequal in length.
+        psKernel *result = psKernelGenerate(tVec, xVec, yVec, false, false);
+        ok(result == NULL, "psKernelGenerate returned NULL given differing sized vectors");
+        psFree(result);
+        psFree(xVec);
+        psFree(yVec);
+        psFree(tVec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    psVector* xVec = psVectorAlloc(size,PS_TYPE_U32);
+    psVector* yVec = psVectorAlloc(size,PS_TYPE_U32);
+    psVector* tVec = psVectorAlloc(size,PS_TYPE_U32);
+    // Following should be a error (time vector NULL)
+    {
+        psMemId id = psMemGetId();
+        psKernel *result = psKernelGenerate(NULL, xVec, yVec, false, true);
+        ok(result == NULL, "psKernelGenerate returned NULL with no time vector");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Following should be a error (x vector NULL)
+    {
+        psMemId id = psMemGetId();
+        psKernel *result = psKernelGenerate(tVec, NULL, yVec, false, true);
+        ok(result == NULL, "psKernelGenerate returned NULL with no x vector");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Following should be a error (y vector NULL
+    {
+        psMemId id = psMemGetId();
+        psKernel *result = psKernelGenerate(tVec, xVec, NULL, false, true);
+        ok(result == NULL, "psKernelGenerate returned NULL with no y vector");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    psFree(xVec);
+    psFree(yVec);
+    psFree(tVec);
+    return(true);
+}
+
+
+bool testImageConvolve(void)
+{
+    psMemId id = psMemGetId();
+    const psS32 r = 200;
+    const psS32 c = 300;
+    psS32 sum;
+
+    // approximate a normalized gaussian kernel.
+    psKernel* g = psKernelAlloc(-1,1,-1,1);
+    g->kernel[-1][-1] = g->kernel[-1][1] = g->kernel[1][-1] = g->kernel[1][1] = 0.0113;
+    g->kernel[1][0] = g->kernel[-1][0] = g->kernel[0][-1] = g->kernel[0][1] = 0.0838;
+    g->kernel[0][0] = 0.6193;
+
+    // create a normalized non-symetric kernel.
+    psKernel* nsk = psKernelAlloc(0,2,0,2);
+    sum = 0.0;
+    for (psS32 i=0;i<2;i++) {
+        for (psS32 j=0;j<2;j++) {
+            nsk->kernel[i][j] = i+j;
+            sum = i+j;
+        }
+    }
+    for (psS32 i=0;i<2;i++) {
+        for (psS32 j=0;j<2;j++) {
+            nsk->kernel[i][j] /= sum;
+        }
+    }
+
+
+    psImage* img = psImageAlloc(c,r,PS_TYPE_F32);
+    memset(img->data.F32[0],0,c*r*PSELEMTYPE_SIZEOF(PS_TYPE_F32));
+    img->data.F32[0][0] = 1.0f;
+    img->data.F32[r/2][c/2] = 1.0f;
+    img->data.F32[r-1][c/2] = 1.0f;
+
+    // test spacial convolution of gaussian
+    ok(false, "XXXX: Skipping this psImageConvolve() because of bugs");
+/*
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage* out = psImageConvolveDirect(NULL, img, g);
+        ok(out != NULL, "psImageConvolveDirect() returned non-NULL");
+        skip_start(out == NULL, 3, "Skipping tests because psImageConvolveDirect() returned NULL");
+        ok(out->numCols == c && out->numRows == r,
+           "psImageConvolveDirect result image is %dx%d, expected %dx%d",
+           out->numCols, out->numRows, c,r);
+        ok(out->type.type == PS_TYPE_F32, "psImageConvolveDirect() produced the correct type");
+
+        // test values
+        bool errorFlag = false;
+        for (psS32 i=-1;i<1;i++) {
+            for (psS32 j=-1;j<1;j++) {
+                if (fabsf(out->data.F32[r/2+i][c/2+j] - g->kernel[i][j]) > 0.0001) {
+                    diag("Convolved image wrong at %d,%d.  Value is %g, expected %g",
+                         c/2+j,r/2+i, out->data.F32[r/2+i][c/2+j], g->kernel[i][j]);
+                    errorFlag = true;
+                }
+                if (i >= 0 && j >= 0 && fabsf(out->data.F32[i][j] - g->kernel[i][j]) > 0.0001) {
+                    diag("Convolved image wrong at %d,%d.  Value is %g, expected %g",
+                         j, i, out->data.F32[i][j], g->kernel[i][j]);
+                    errorFlag = true;
+                }
+                if (i <= 0 && fabsf(out->data.F32[r-1+i][c/2+j] - g->kernel[i][j]) > 0.0001) {
+                    diag("Convolved image wrong at %d,%d.  Value is %g, expected %g",
+                         c/2+j,r-1+i, out->data.F32[r-1+i][c/2+j], g->kernel[i][j]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psKernelGenerate() produced the correct data values");
+        skip_end();
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test fourier convolution of gaussian
+    ok(false, "XXXX: Skipping this psImageConvolveDirect() because of bugs");
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage* out = psImageConvolveDirect(NULL, img, g);
+        psImage* out2 = psImageConvolveDirect(out, img, g);
+
+        ok(out != NULL, "psImageConvolveDirect() returned non-NULL");
+        ok(out2 != NULL, "psImageConvolveDirect() returned non-NULL");
+        skip_start(out == NULL || out2 == NULL, 3, "Skipping tests because psImageConvolveDirect() returned NULL");
+        ok(out == out2, "psImageConvolveDirect did recycle the supplied out image struct");
+        ok(out->numCols == c && out->numRows == r,
+           "psImageConvolveDirect result image is %dx%d, expected %dx%d",
+           out->numCols, out->numRows, c,r);
+        ok(out->type.type == PS_TYPE_F32, "psImageConvolveDirect() produced the correct type");
+
+        // test values
+        bool errorFlag = false;
+        for (psS32 i=-1;i<1;i++) {
+            for (psS32 j=-1;j<1;j++) {
+                if (fabsf(out->data.F32[r/2+i][c/2+j] - g->kernel[i][j]) > 0.01) {
+                    diag("Convolved image wrong at %d,%d.  Value is %g, expected %g",
+                         c/2+j,r/2+i, out->data.F32[r/2+i][c/2+j], g->kernel[i][j]);
+                    errorFlag = true;
+                }
+                if (i >= 0 && j >= 0 && fabsf(out->data.F32[i][j] - g->kernel[i][j]) > 0.01) {
+                    diag("Convolved image wrong at %d,%d.  Value is %g, expected %g",
+                         j,i, out->data.F32[i][j], g->kernel[i][j]);
+                    errorFlag = true;
+                }
+                if (i <= 0 && fabsf(out->data.F32[r-1+i][c/2+j] - g->kernel[i][j]) > 0.01) {
+                    diag("Convolved image wrong at %d,%d.  Value is %g, expected %g",
+                         c/2+j,r-1+i, out->data.F32[r-1+i][c/2+j], g->kernel[i][j]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psKernelGenerate() produced the correct data values");
+        skip_end();
+        psFree(out);
+        psFree(out2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+*/
+
+    psFree(g);
+    psFree(img);
+    psFree(nsk);
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    return(true);
+}
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(62);
+
+    testKernelAlloc(-5, 0, -4, 0);
+    testKernelAlloc(0, 5, 0, 4);
+    testKernelAlloc(-10, -5, -8, -4);
+    testKernelAlloc(5, 10, 4, 8);
+    testKernelGenerate();
+    testImageConvolve();
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageConvolve2.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageConvolve2.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageConvolve2.c	(revision 22158)
@@ -0,0 +1,244 @@
+#include <stdio.h>
+#include <pslib.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+#define IMAGE_SIZE 21
+#define KERNEL_SIZE 3
+#define TOL 1.0e-6
+#define MASK_INITIAL 0x08
+#define MASK_FINAL   0x80
+
+
+// Generate image with single high pixel
+static psImage *generateImage(void)
+{
+    psImage *image = psImageAlloc(IMAGE_SIZE, IMAGE_SIZE, PS_TYPE_F32);
+    psImageInit(image, 0.0);
+    image->data.F32[IMAGE_SIZE/2][IMAGE_SIZE/2] = 1.0;
+    return image;
+}
+
+// Generate mask with single pixel set
+static psImage *generateMask(void)
+{
+    psImage *mask = psImageAlloc(IMAGE_SIZE, IMAGE_SIZE, PS_TYPE_MASK);
+    psImageInit(mask, 0);
+    mask->data.PS_TYPE_MASK_DATA[IMAGE_SIZE/2][IMAGE_SIZE/2] = MASK_INITIAL;
+    return mask;
+}
+
+// Generate Gaussian kernel
+static psKernel *generateKernel(void)
+{
+    psKernel *kernel = psKernelAlloc(- KERNEL_SIZE, KERNEL_SIZE, - KERNEL_SIZE, KERNEL_SIZE);
+    for (int y = - KERNEL_SIZE; y <= KERNEL_SIZE; y++) {
+        for (int x = - KERNEL_SIZE; x <= KERNEL_SIZE; x++) {
+            kernel->kernel[y][x] = exp(- x*x - y*y);
+        }
+    }
+    kernel->kernel[KERNEL_SIZE/3][KERNEL_SIZE/2] = 1.0;
+    return kernel;
+}
+
+// Check the convolved image matches the kernel
+static bool checkConvolved(const psImage *image, const psKernel *kernel)
+{
+    bool correct = true;
+    for (int y = 0; y < IMAGE_SIZE; y++) {
+        for (int x = 0; x < IMAGE_SIZE; x++) {
+            if (x < IMAGE_SIZE/2 - KERNEL_SIZE || x > IMAGE_SIZE/2 + KERNEL_SIZE ||
+                y < IMAGE_SIZE/2 - KERNEL_SIZE || y > IMAGE_SIZE/2 + KERNEL_SIZE) {
+                if (fabs(image->data.F32[y][x]) > TOL) {
+                    diag("%d,%d --> %f", x, y, fabs(image->data.F32[y][x]));
+                    correct = false;
+                }
+            } else {
+                // Position relative to the centre
+                int kx = x - IMAGE_SIZE/2;
+                int ky = y - IMAGE_SIZE/2;
+                if (fabs(image->data.F32[y][x] - kernel->kernel[ky][kx]) > TOL) {
+                    diag("%d,%d --> %f", x, y, fabs(image->data.F32[y][x] - kernel->kernel[ky][kx]));
+                    correct = false;
+                }
+            }
+        }
+    }
+    return correct;
+}
+
+// Check the convolved mask matches the kernel
+static bool checkConvolvedMask(const psImage *mask)
+{
+    bool correct = true;
+    for (int y = 0; y < IMAGE_SIZE; y++) {
+        for (int x = 0; x < IMAGE_SIZE; x++) {
+            if (x < IMAGE_SIZE/2 - KERNEL_SIZE || x > IMAGE_SIZE/2 + KERNEL_SIZE ||
+                y < IMAGE_SIZE/2 - KERNEL_SIZE || y > IMAGE_SIZE/2 + KERNEL_SIZE) {
+                if (mask->data.PS_TYPE_MASK_DATA[y][x] != 0) {
+                    diag("%d,%d --> %d", x, y, mask->data.PS_TYPE_MASK_DATA[y][x]);
+                    correct = false;
+                }
+            } else if (x == IMAGE_SIZE/2 && y == IMAGE_SIZE/2) {
+                if (mask->data.PS_TYPE_MASK_DATA[y][x] != (MASK_INITIAL | MASK_FINAL)) {
+                    diag("%d,%d --> %d", x, y, mask->data.PS_TYPE_MASK_DATA[y][x]);
+                    correct = false;
+                }
+            } else if (mask->data.PS_TYPE_MASK_DATA[y][x] != MASK_FINAL) {
+                diag("%d,%d --> %d", x, y, mask->data.PS_TYPE_MASK_DATA[y][x]);
+                correct = false;
+            }
+        }
+    }
+    return correct;
+}
+
+
+int main(int argc, char *argv[])
+{
+    plan_tests(30);
+
+    diag("psImageConvolve tests");
+
+    {
+        diag("Mask convolution");
+        // Better (separable) mask convolution: 5 tests
+        psMemId id = psMemGetId();
+
+        psImage *mask = generateMask();
+
+        psImage *convolved = psImageConvolveMask(NULL, mask, MASK_INITIAL, MASK_FINAL,
+                                                 -KERNEL_SIZE, KERNEL_SIZE, -KERNEL_SIZE, KERNEL_SIZE);
+        ok(convolved, "convolution result");
+        skip_start(!convolved, 3, "convolution failed");
+        ok(convolved->type.type == PS_TYPE_MASK, "output type");
+        ok(convolved->numCols == IMAGE_SIZE && convolved->numRows == IMAGE_SIZE, "output size %dx%d",
+           convolved->numCols, convolved->numRows);
+        ok(checkConvolvedMask(convolved), "convolved mask correct");
+        psFree(convolved);
+        skip_end();
+
+        psFree(mask);
+
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    {
+        diag("Mask convolution in-place");
+        // Better (separable) in-place FFT mask convolution: 5 tests
+        psMemId id = psMemGetId();
+
+        psImage *mask = generateMask();
+
+        bool result = psImageConvolveMask(mask, mask, MASK_INITIAL, MASK_FINAL, -KERNEL_SIZE, KERNEL_SIZE,
+                                          -KERNEL_SIZE, KERNEL_SIZE);
+        ok(result, "convolution result");
+        skip_start(!result, 3, "convolution failed");
+        ok(mask->type.type == PS_TYPE_MASK, "output type");
+        ok(mask->numCols == IMAGE_SIZE && mask->numRows == IMAGE_SIZE, "output size %dx%d",
+           mask->numCols, mask->numRows);
+        ok(checkConvolvedMask(mask), "convolved mask correct");
+        skip_end();
+
+        psFree(mask);
+
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    {
+        diag("Direct convolution");
+        // Direct convolution: 5 tests
+        psMemId id = psMemGetId();
+
+        psImage *image = generateImage();
+        psKernel *kernel = generateKernel();
+
+        psImage *convolved = psImageConvolveDirect(NULL, image, kernel);
+        ok(convolved, "convolution result");
+        skip_start(!convolved, 3, "convolution failed");
+        ok(convolved->type.type == PS_TYPE_F32, "output type");
+        ok(convolved->numCols == IMAGE_SIZE && convolved->numRows == IMAGE_SIZE, "output size %dx%d",
+           convolved->numCols, convolved->numRows);
+        ok(checkConvolved(convolved, kernel), "convolved image correct");
+        psFree(convolved);
+        skip_end();
+
+        psFree(kernel);
+        psFree(image);
+
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    {
+        diag("FFT convolution");
+        // FFT convolution: 5 tests
+        psMemId id = psMemGetId();
+
+        psImage *image = generateImage();
+        psKernel *kernel = generateKernel();
+
+        psImage *convolved = psImageConvolveFFT(NULL, image, NULL, 0, kernel);
+        ok(convolved, "convolution result");
+        skip_start(!convolved, 3, "convolution failed");
+        ok(convolved->type.type == PS_TYPE_F32, "output type");
+        ok(convolved->numCols == IMAGE_SIZE && convolved->numRows == IMAGE_SIZE, "output size %dx%d",
+           convolved->numCols, convolved->numRows);
+        ok(checkConvolved(convolved, kernel), "convolved image correct");
+        psFree(convolved);
+        skip_end();
+
+        psFree(kernel);
+        psFree(image);
+
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    {
+        diag("FFT mask convolution");
+        // FFT mask convolution: 5 tests
+        psMemId id = psMemGetId();
+
+        psImage *mask = generateMask();
+
+        psImage *convolved = psImageConvolveMaskFFT(NULL, mask, MASK_INITIAL, MASK_FINAL,
+                                                    -KERNEL_SIZE, KERNEL_SIZE, -KERNEL_SIZE, KERNEL_SIZE,
+                                                    0.5);
+        ok(convolved, "convolution result");
+        skip_start(!convolved, 3, "convolution failed");
+        ok(convolved->type.type == PS_TYPE_MASK, "output type");
+        ok(convolved->numCols == IMAGE_SIZE && convolved->numRows == IMAGE_SIZE, "output size %dx%d",
+           convolved->numCols, convolved->numRows);
+        ok(checkConvolvedMask(convolved), "convolved mask correct");
+        psFree(convolved);
+        skip_end();
+
+        psFree(mask);
+
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    {
+        diag("FFT mask convolution in-place");
+        // In-place FFT mask convolution: 5 tests
+        psMemId id = psMemGetId();
+
+        psImage *mask = generateMask();
+
+        bool result = psImageConvolveMaskFFT(mask, mask, MASK_INITIAL, MASK_FINAL, -KERNEL_SIZE, KERNEL_SIZE,
+                                             -KERNEL_SIZE, KERNEL_SIZE, 0.5);
+        ok(result, "convolution result");
+        skip_start(!result, 3, "convolution failed");
+        ok(mask->type.type == PS_TYPE_MASK, "output type");
+        ok(mask->numCols == IMAGE_SIZE && mask->numRows == IMAGE_SIZE, "output size %dx%d",
+           mask->numCols, mask->numRows);
+        ok(checkConvolvedMask(mask), "convolved mask correct");
+        skip_end();
+
+        psFree(mask);
+
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    return exit_status();
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageGeomManip.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageGeomManip.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageGeomManip.c	(revision 22158)
@@ -0,0 +1,1074 @@
+/** @file  tst_psImageGeomManip.c
+ *
+ *  @brief Contains the tests for psImageManip.[ch]
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-06-04 20:25:32 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#define VERBOSE 0
+
+void genericImageRollTest(int numRows, int numCols)
+{
+    psMemId id = psMemGetId();
+    psImage *in;
+    psImage *out;
+    psImage *out2;
+
+    // The function psImageRoll shall generate a new psImage structure by
+    // rolling the input image the correponding number of pixels in the vertical
+    // and/or horizontal direction. The image output image shall be the same size
+    // as the input image. Values which roll off the image are wrapped to the
+    // other side.
+    //
+    // Verify the returned psImage structure contains expected values, if the
+    // input image contains known values and the roll performed is known.
+    // Cases should include no roll, vertical roll, horizontal roll and
+    // combination vertical/horizontal rolls. Positive and negative rolls
+    // should be performed.
+
+    in = psImageAlloc(numCols,numRows,PS_TYPE_F32);
+    for (psS32 row=0;row<numRows;row++) {
+        for (psS32 col=0;col<numCols;col++) {
+            in->data.F32[row][col] = (psF32)row+(psF32)col/1000.0f;
+        }
+    }
+
+    out = psImageRoll(NULL,in,0,0);
+    bool errorFlag = false;
+    for (psS32 row=0;row<numRows;row++) {
+        psF32 *inRow = in->data.F32[row];
+        psF32 *outRow = out->data.F32[row];
+        for (psS32 col=0;col<numCols;col++) {
+            if (inRow[col] != outRow[col]) {
+                diag("psImageRoll didn't produce expected result "
+                     "at %d,%d (%f vs %f) for dx=0, dy=0",
+                     col,row,inRow[col],outRow[col]);
+                errorFlag = true;
+            }
+        }
+    }
+    ok(!errorFlag, "psImageRoll() produced the correct data values (no roll)");
+
+    errorFlag = false;
+    out2 = psImageRoll(out,in,numCols/4,0);
+    for (psS32 row=0;row<numRows;row++)
+    {
+        psF32 *inRow = in->data.F32[row];
+        psF32 *outRow = out->data.F32[row];
+        for (psS32 col=0;col<numCols;col++) {
+            if (inRow[(col+numCols/4) % numCols] != outRow[col]) {
+                diag("psImageRoll didn't produce expected result "
+                     "at %d,%d (%f vs %f) for dx=numCols/4, dy=0",
+                     col,row,inRow[(col+numCols/4) % numCols],outRow[col]);
+                errorFlag = true;
+            }
+        }
+    }
+    ok(!errorFlag, "psImageRoll() produced the correct data values (column roll only");
+
+    // Verify the returned psImage structure pointer is equal to the input
+    // parameter out if provided.
+    ok(out2 == out, "psImageRoll did recycle the out psImage");
+
+    errorFlag = false;
+    out = psImageRoll(out,in,0,numRows/4);
+    for (psS32 row=0;row<numRows;row++)
+    {
+        psF32 *inRow = in->data.F32[(row+numRows/4)%numRows];
+        psF32 *outRow = out->data.F32[row];
+        for (psS32 col=0;col<numCols;col++) {
+            if (inRow[col] != outRow[col]) {
+                diag("psImageRoll didn't produce expected result "
+                     "at %d,%d (%f vs %f) for dx=0, dy=numRows/4",
+                     col,row,inRow[col],outRow[col]);
+                errorFlag = true;
+            }
+        }
+    }
+    ok(!errorFlag, "psImageRoll() produced the correct data values (row roll onlt)");
+
+    errorFlag = false;
+    out = psImageRoll(out,in,numCols/4,numRows/4);
+    for (psS32 row=0;row<numRows;row++)
+    {
+        psF32 *inRow = in->data.F32[(row+numRows/4)%numRows];
+        psF32 *outRow = out->data.F32[row];
+        for (psS32 col=0;col<numCols;col++) {
+            if (inRow[(col+numCols/4) % numCols] != outRow[col]) {
+                diag("psImageRoll didn't produce expected result "
+                     "at %d,%d (%f vs %f) for dx=numCols/4, dy=numRows/4",
+                     col,row,inRow[(col+numCols/4) % numCols],outRow[col]);
+                errorFlag = true;
+            }
+        }
+    }
+    ok(!errorFlag, "psImageRoll() produced the correct data values (column and row roll)");
+
+    errorFlag = false;
+    out = psImageRoll(out,in,-numCols/4,0);
+    for (psS32 row=0;row<numRows;row++)
+    {
+        psF32 *inRow = in->data.F32[row];
+        psF32 *outRow = out->data.F32[row];
+        for (psS32 col=0;col<numCols;col++) {
+            if (inRow[(col+(numCols-numCols/4)) % numCols] != outRow[col]) {
+                diag("psImageRoll didn't produce expected result "
+                     "at %d,%d (%f vs %f) for dx=-numCols/4, dy=0",
+                     col,row,inRow[(col+(numCols-numCols/4)) % numCols],outRow[col]);
+                errorFlag = true;
+            }
+        }
+    }
+    ok(!errorFlag, "psImageRoll() produced the correct data values (negative column roll)");
+
+    errorFlag = false;
+    out = psImageRoll(out,in,0,-numRows/4);
+    for (psS32 row=0;row<numRows;row++)
+    {
+        psF32 *inRow = in->data.F32[(row+numRows-numRows/4)%numRows];
+        psF32 *outRow = out->data.F32[row];
+        for (psS32 col=0;col<numCols;col++) {
+            if (inRow[col] != outRow[col]) {
+                diag("psImageRoll didn't produce expected result "
+                     "at %d,%d (%f vs %f) for dx=0, dy=-numRows/4",
+                     col,row,inRow[col],outRow[col]);
+                errorFlag = true;
+            }
+        }
+    }
+    ok(!errorFlag, "psImageRoll() produced the correct data values (negative row roll)");
+
+    errorFlag = false;
+    out = psImageRoll(out,in,-numCols/4,-numRows/4);
+    for (psS32 row=0;row<numRows;row++)
+    {
+        psF32 *inRow = in->data.F32[(row+numRows-numRows/4)%numRows];
+        psF32 *outRow = out->data.F32[row];
+        for (psS32 col=0;col<numCols;col++) {
+            if (inRow[(col+numCols-numCols/4) % numCols] != outRow[col]) {
+                diag("psImageRoll didn't produce expected result "
+                     "at %d,%d (%f vs %f) for dx=numCols/4, dy=numRows/4",
+                     col,row,inRow[(col+numCols-numCols/4) % numCols],outRow[col]);
+                errorFlag = true;
+            }
+        }
+    }
+    ok(!errorFlag, "psImageRoll() produced the correct data values (negative column and row roll)");
+    psFree(in);
+    psFree(out);
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+}
+
+
+
+bool testImageShiftCase(psS32 cols,
+                        psS32 rows,
+                        float colShift,
+                        float rowShift)
+{
+    psImage *fOut = NULL;
+    psImage *sOut = NULL;
+    psImage *fImg = psImageAlloc(cols,rows,PS_TYPE_F32);
+    psImage *sImg = psImageAlloc(cols,rows,PS_TYPE_S16);
+    psImage *fBiOut = psImageAlloc(cols,rows,PS_TYPE_F32);
+    psImage *sBiOut = psImageAlloc(cols,rows,PS_TYPE_S16);
+    bool errorFlag = false;
+
+    for(psS32 row=0;row<rows;row++) {
+        psF32 *fRow = fImg->data.F32[row];
+        psS16 *sRow = sImg->data.S16[row];
+        for (psS32 col=0;col<cols;col++) {
+            fRow[col] = (psF32)(row)+(psF32)(col)/100.0f;
+            sRow[col] = row-2*col;
+        }
+    }
+
+    fOut = psImageShift(fOut, fImg, colShift, rowShift, NAN, PS_INTERPOLATE_FLAT);
+    sOut = psImageShift(sOut, sImg, colShift, rowShift, -1, PS_INTERPOLATE_FLAT);
+    fBiOut = psImageShift(fBiOut, fImg, colShift, rowShift, NAN, PS_INTERPOLATE_BILINEAR);
+    sBiOut = psImageShift(sBiOut, sImg, colShift, rowShift, -1, PS_INTERPOLATE_BILINEAR);
+
+    {
+        psImageInterpolateOptions *tmpIntOpts = psImageInterpolateOptionsAlloc(
+            PS_INTERPOLATE_FLAT, fImg, NULL, NULL, 0, NAN, NAN, 0, 0, 0.0);
+        double imgVal;
+        double varVal;
+        psMaskType maskVal;
+        for(psS32 row=0;row<rows;row++) {
+            psF32 *fRow = fOut->data.F32[row];
+            for (psS32 col=0;col<cols;col++) {
+                psImageInterpolate(&imgVal, &varVal, &maskVal, col+0.5-colShift,
+                                   row+0.5-rowShift, tmpIntOpts);
+                if (fabsf(fRow[col] - imgVal) > FLT_EPSILON) {
+                    if (VERBOSE) diag("Float image not shifted correctly at %d,%d (%g vs %g) (flat interpolation)",
+                         row,col,fRow[col],imgVal);
+                    errorFlag = true;
+                }
+            }
+        }
+        psFree(tmpIntOpts);
+    }
+
+    {
+        psImageInterpolateOptions *tmpIntOpts = psImageInterpolateOptionsAlloc(
+            PS_INTERPOLATE_FLAT, sImg, NULL, NULL, 0, -1, NAN, 0, 0, 0.0);
+        double imgVal;
+        double varVal;
+        psMaskType maskVal;
+
+        for(psS32 row=0;row<rows;row++) {
+            psS16 *sRow = sOut->data.S16[row];
+            for (psS32 col=0;col<cols;col++) {
+                psImageInterpolate(&imgVal, &varVal, &maskVal, col+0.5-colShift,
+                                   row+0.5-rowShift, tmpIntOpts);
+                psS16 sValue = (psS16) imgVal;
+                if (sRow[col] != sValue) {
+                    if (VERBOSE) diag("Short image not shifted correctly at %d,%d (%d vs %d) (flat interpolation)",
+                        row,col,sRow[col],sValue);
+                    errorFlag = true;
+                }
+            }
+        }
+        psFree(tmpIntOpts);
+    }
+
+
+    {
+        psImageInterpolateOptions *tmpIntOpts = psImageInterpolateOptionsAlloc(
+            PS_INTERPOLATE_BILINEAR, fImg, NULL, NULL, 0, NAN, NAN, 0, 0, 0.0);
+        double imgVal;
+        double varVal;
+        psMaskType maskVal;
+        for(psS32 row=0;row<rows;row++) {
+            psF32 *fBiRow = fBiOut->data.F32[row];
+            for (psS32 col=0;col<cols;col++) {
+                psImageInterpolate(&imgVal, &varVal, &maskVal, col+0.5-colShift,
+                                   row+0.5-rowShift, tmpIntOpts);
+                psF32 fBiValue = imgVal;
+                if (fabsf(fBiRow[col] - fBiValue) > FLT_EPSILON) {
+                    if (VERBOSE) diag("Float image not shifted correctly at %d,%d (%g vs %g) (bilinear interpolation)",
+                         row,col,fBiRow[col],fBiValue);
+                    errorFlag = true;
+                }
+            }
+        }
+        psFree(tmpIntOpts);
+    }
+
+
+    {
+        psImageInterpolateOptions *tmpIntOpts = psImageInterpolateOptionsAlloc(
+            PS_INTERPOLATE_BILINEAR, sImg, NULL, NULL, 0, -1, NAN, 0, 0, 0.0);
+        double imgVal;
+        double varVal;
+        psMaskType maskVal;
+        for(psS32 row=0;row<rows;row++) {
+            psS16 *sBiRow = sBiOut->data.S16[row];
+            for (psS32 col=0;col<cols;col++) {
+                psImageInterpolate(&imgVal, &varVal, &maskVal, col+0.5-colShift,
+                                   row+0.5-rowShift, tmpIntOpts);
+                psS16 sBiValue = (psS16) imgVal;
+                if (sBiRow[col] != sBiValue) {
+                    if (VERBOSE) diag("Short image not shifted correctly at %d,%d (%d vs %d) (bilinear interpolation)",
+                         row,col,sBiRow[col],sBiValue);
+                    errorFlag = true;
+                }
+            }
+        }
+        psFree(tmpIntOpts);
+    }
+
+    if (errorFlag) {
+        diag("Short or Float image not shifted correctly");
+    }
+    psFree(fImg);
+    psFree(sImg);
+    psFree(fOut);
+    psFree(sOut);
+    psFree(fBiOut);
+    psFree(sBiOut);
+
+    return !errorFlag;
+}
+
+
+psS32 main(psS32 argc, char *argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(280);
+
+    // test psImageRebin()
+    // This function shall generate a rescaled version of a psImage
+    // structure derived from a specified statistics method.
+    if (1) {
+        psMemId id = psMemGetId();
+        psImage *in = NULL;
+        psImage *out = NULL;
+        psImage *out2 = NULL;
+        psImage *out3 = NULL;
+        psImage *mask = NULL;
+        psImage *meanTruth = NULL;
+        psImage *meanTruthWMask = NULL;
+        psImage *maxTruth = NULL;
+        psStats stats;
+
+        //        Verify the returned psImage structure contains expected values, if the
+        //        input parameter input contains known data, the input scale is a known
+        //        value with a known statistical method specified in stats. Cases should
+        //        include at least two different scales and statistical methods. Comparison
+        //        of expected values should include a delta to allow testing on different
+        //        platforms.
+        #define testRebinType(DATATYPE)  \
+        { \
+            psMemId id = psMemGetId();\
+            in = psImageAlloc(16,16,PS_TYPE_##DATATYPE); \
+            mask = psImageAlloc(16,16,PS_TYPE_U8); \
+            meanTruth = psImageAlloc(4,4,PS_TYPE_F32); \
+            meanTruthWMask = psImageAlloc(4,4,PS_TYPE_F32); \
+            maxTruth = psImageAlloc(6,6,PS_TYPE_F32); \
+            memset(meanTruth->data.F32[0],0,sizeof(psF32)*4*4); \
+            memset(meanTruthWMask->data.F32[0],0,sizeof(psF32)*4*4); \
+            memset(maxTruth->data.F32[0],0,sizeof(psF32)*6*6); \
+            for (psS32 row = 0; row<16; row++) { \
+                ps##DATATYPE *inRow = in->data.DATATYPE[row]; \
+                psF32 *meanTruthRow = meanTruth->data.F32[row/4]; \
+                psF32 *meanTruthWMaskRow = meanTruthWMask->data.F32[row/4]; \
+                psF32 *maxTruthRow = maxTruth->data.F32[row/3]; \
+                psU8 *maskRow = mask->data.U8[row]; \
+                for (psS32 col = 0; col<16; col++) { \
+                    if(col != 15) { \
+                        maskRow[col] = 0; \
+                    } else { \
+                        maskRow[col] = 1; \
+                    } \
+                    inRow[col] = row + col; \
+                    meanTruthRow[col/4] += row + col; \
+                    if (maxTruthRow[col/3] < row + col) { \
+                        maxTruthRow[col/3] = row+col; \
+                    } \
+                    if(maskRow[col] == 0 ) { \
+                        meanTruthWMaskRow[col/4] += row + col; \
+                    } \
+                } \
+            } \
+            for (psS32 row = 0; row<4; row++) { \
+                psF32 *meanTruthRow = meanTruth->data.F32[row]; \
+                psF32 *meanTruthWMaskRow = meanTruthWMask->data.F32[row]; \
+                for (psS32 col = 0; col<4; col++) { \
+                    meanTruthRow[col] /= 16; \
+                    if ( col == 3 ) { \
+                        meanTruthWMaskRow[col] /= 12; \
+                    } else { \
+                        meanTruthWMaskRow[col] /= 16; \
+                    } \
+                } \
+            } \
+            stats.options = PS_STAT_SAMPLE_MEAN; \
+            { \
+                out = psImageRebin(NULL,in,NULL,0,4,&stats); \
+                ok(out != NULL, "psImageRebin returned non-NULL"); \
+                ok(out->numRows == 4 && out->numCols == 4, \
+                   "psImageRebin did produce the proper size image"); \
+                bool errorFlag = false; \
+                for (psS32 row = 0; row<4; row++) { \
+                    ps##DATATYPE *outRow = out->data.DATATYPE[row]; \
+                    psF32 *truthRow = meanTruth->data.F32[row]; \
+                    for (psS32 col = 0; col<4; col++) { \
+                        if (fabsf((float)outRow[col]-(float)truthRow[col]) > FLT_EPSILON) { \
+                            diag("psImageRebin didn't produce the proper mean " \
+                                 "result at (%d,%d) [%f vs %f]", \
+                                 col,row,outRow[col],truthRow[col]); \
+                            errorFlag = true;\
+                        } \
+                    } \
+                } \
+                ok(!errorFlag, "psImageRebin() produced the correct data"); \
+            } \
+            { \
+                stats.options = PS_STAT_SAMPLE_MEAN; \
+                out3 = psImageRebin(NULL,in,mask,1,4,&stats); \
+                bool errorFlag = false; \
+                for (psS32 row = 0; row<4; row++) { \
+                    ps##DATATYPE *outRow = out3->data.DATATYPE[row]; \
+                    psF32 *truthRow = meanTruthWMask->data.F32[row]; \
+                    for ( psS32 col = 0; col<4; col++) { \
+                        if(abs((psS32)outRow[col]-(psS32)truthRow[col]) > FLT_EPSILON) { \
+                            diag("psImageRebin with mask didn't produce the proper mean " \
+                                 "result at (%d,%d) [%f vs %f]", \
+                                 col,row,outRow[col],truthRow[col]); \
+                            errorFlag = true;\
+                        } \
+                    } \
+                    ok(!errorFlag, "psImageRebin() produced the correct data"); \
+                } \
+            } \
+            stats.options = PS_STAT_MAX; \
+            { \
+                out2 = psImageRebin(out,in,NULL,0,3,&stats); \
+                ok(out == out2, "psImageRebin didt recycle a psImage properly"); \
+                ok(out != NULL, "psImageRebin returned non-NULL"); \
+                ok(out->numRows == 6 && out->numCols == 6, \
+                   "psImageRebin did produce the proper size image"); \
+                bool errorFlag = false; \
+                for (psS32 row = 0; row<6; row++) { \
+                    ps##DATATYPE *outRow = out->data.DATATYPE[row]; \
+                    psF32 *truthRow = maxTruth->data.F32[row]; \
+                    for (psS32 col = 0; col<6; col++) { \
+                        if (fabsf((float)outRow[col]-(float)truthRow[col]) > FLT_EPSILON) { \
+                            diag("psImageRebin didn't produce the proper " \
+                                 "max result at (%d,%d) [%f vs %f]", \
+                                 col,row,outRow[col],truthRow[col]); \
+                            errorFlag = true;\
+                        } \
+                    } \
+                } \
+                ok(!errorFlag, "psImageRebin() produced the correct data"); \
+            } \
+            psFree(in); \
+            psFree(out); \
+            psFree(out3); \
+            psFree(mask); \
+            psFree(meanTruth); \
+            psFree(meanTruthWMask); \
+            psFree(maxTruth); \
+            ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks"); \
+        }
+
+        testRebinType(F32);
+        testRebinType(F64);
+        testRebinType(U16);
+        testRebinType(S8);
+        // Verify the returned psImage structure is NULL and program execution
+        // doesn't stop, if the input image type is not supported.
+        // Following should be an error for unsupported type
+        // XXX: Verify error
+        in = psImageAlloc(16,16,PS_TYPE_U8);
+        mask = psImageAlloc(16,16,PS_TYPE_F32);
+        stats.options = PS_STAT_SAMPLE_MEAN;
+        out = psImageRebin(NULL,in,NULL,0,4,&stats);
+        ok(out == NULL, "psImageRebin returned NULL for unsupported type");
+
+        // Verify the returned psImage structure is NULL and program execution
+        // doesn't stop, if the mask type is not U8
+        // Following should be an error for invallid mask type
+        // XXX: Verify error
+        out = psImageRebin(NULL,in,mask,1,4,&stats);
+        ok(out == NULL, "psImageRebin returned NULL for incorrect mask");
+        psFree(mask);
+        psFree(in);
+
+        // Verify the returned psImage structure is NULL and program execution
+        // doesn't stop, if the input parameter input is NULL.
+        out2 = psImageRebin(NULL,NULL,NULL,0,1,&stats);
+        ok(out2 == NULL, "psImageRebin returned NULL with NULL input");
+
+        // Verify the returned psImage structure is NULL and program execution
+        // doesn't stop, if the input parameter scale is less than or equal to zero.
+        in = psImageAlloc(16, 16, PS_TYPE_F32);
+        // Following should be an error for scale < 0
+        // XXX: Verify error
+        out2 = psImageRebin(NULL,in,NULL,0,0,&stats);
+        ok(out2 == NULL, "psImageRebin returned NULL when the scale was zero");
+
+        // Verify the returned psImage structure is NULL and program execution
+        // doesn't stop, if the input parameter stats is NULL.
+        // Following should be an error for stats NULL
+        // XXX: Verify error
+        out2 = psImageRebin(NULL,in,NULL,0,1,NULL);
+        ok(out2 == NULL, "psImageRebin returned an NULL when the stats was NULL");
+
+        // Verify the returned psImage structure is NULL and program execution
+        // doesn't stop, if the input parameter psStats structure member options
+        // is zero or any value which doesn't correspond to a valid statistical
+        // method.
+        // Following should be an error for stats options 0
+        // XXX: Verify error
+        stats.options = 0;
+        out2 = psImageRebin(NULL,in,NULL,0,1,&stats);
+        ok(out2 == NULL, "psImageRebin returned an NULL when the stats options was zero");
+
+        //Following should be an error for stat options use range");
+        // XXX: Verify error
+        stats.options = PS_STAT_USE_RANGE;
+        out2 = psImageRebin(NULL,in,NULL,0,1,&stats);
+        ok(out2 == NULL, "psImageRebin returned an image though the stats options was PS_STAT_USE_RANGE");
+
+        // Verify the returned psImage structure is NULL and program execution
+        // doesn't stop, if the input parameter psStats structure member options
+        // specifies more than one valid statistical method.
+        // Following should be an error for stats with multiple options
+        // XXX: Verify error
+        stats.options = PS_STAT_SAMPLE_MEAN + PS_STAT_MAX;
+        out2 = psImageRebin(NULL,in,NULL,0,1,&stats);
+        ok(out2 == NULL, "psImageRebin returned an NULL when the stats options was PS_STAT_SAMPLE_MEAN+PS_STAT_MAX");
+
+        psFree(in);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test psImageRoll()
+    if (1) {
+        psMemId id = psMemGetId();
+        // Perform generic tests with various image sizes
+        genericImageRollTest(8, 1);
+        genericImageRollTest(1, 8);
+        genericImageRollTest(8, 8);
+        genericImageRollTest(8, 16);
+        genericImageRollTest(16, 8);
+
+        psImage *in;
+        psImage *out;
+        psImage *out2;
+        psS32 rows = 64;
+        psS32 cols = 64;
+        psS32 rows1 = 8;
+        psS32 cols1 = 8;
+        in = psImageAlloc(cols,rows,PS_TYPE_F32);
+        for (psS32 row=0;row<rows;row++) {
+            for (psS32 col=0;col<cols;col++) {
+                in->data.F32[row][col] = (psF32)row+(psF32)col/1000.0f;
+            }
+        }
+
+        bool errorFlag = false;
+        // Verify the returned psImage structure pointer is NULL and program
+        // execution doesn't stop, if input parameter input is NULL.
+        out2 = psImageRoll(NULL,NULL,0,0);
+        if (out2 != NULL) {
+            psError(PS_ERR_UNKNOWN, true,"psImageRoll did not return NULL though input image was NULL!?");
+            return 2;
+        }
+
+        psFree(in);
+        psFree(out);
+
+        #define testRollType(DATATYPE) \
+        in = psImageAlloc(rows1,cols1,PS_TYPE_##DATATYPE); \
+        \
+        for (psS32 row=0;row<rows1;row++) { \
+            ps##DATATYPE *inRow = in->data.DATATYPE[row]; \
+            for (psS32 col=0;col<cols1;col++) { \
+                inRow[col] = (ps##DATATYPE)row+(ps##DATATYPE)col; \
+            } \
+        } \
+        \
+        errorFlag = false; \
+        out = psImageRoll(NULL,in,rows1/4,cols1/4); \
+        for (psS32 row=0;row<rows1;row++) { \
+            ps##DATATYPE *inRow = in->data.DATATYPE[(row+rows1/4)%rows1]; \
+            ps##DATATYPE *outRow = out->data.DATATYPE[row]; \
+            for (psS32 col=0;col<cols1;col++) { \
+                if (inRow[(col+cols1/4)%cols1] != outRow[col]) { \
+                    diag("psImageRoll didn't produce expected result " \
+                         "at %d,%d (%f vs %f) for dx=0, dy=0", \
+                         col,row,(float)inRow[col],(float)outRow[col]); \
+                    errorFlag = true; \
+                } \
+            } \
+        } \
+        psFree(in); \
+        psFree(out); \
+        ok(!errorFlag, "psImageRoll() produced the correct data values");
+
+        testRollType(U8);
+        testRollType(U16);
+        testRollType(S8);
+        testRollType(S16);
+        testRollType(F64);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test psImageRotate()
+    if (1) {
+        psMemId id = psMemGetId();
+        // This function shall calculate a new psImage structure based upon the
+        // rotation of a given psImage structure. The center of rotation shall be the
+        // center pixel of the input image.
+        //
+        // The following steps of the testpoint are done manually via inspection of
+        // fOut.fits & sOut.fits.
+        //
+        //  * Verify the returned psImage structure contains expected values, if
+        //    the input parameter psImage contains known values. Cases should
+        //    include rotations of 0, 45, 90, 135, 180, 225, 270, 315, 360 and at leat one
+        //    other arbitrary angle. Cases of the input image should include image
+        //    with a center pixel and an image without a center pixel.
+        //  * Verify the returned psImage structure contains pixels set to exposed value, if
+        //    the rotation and input psImage to not correspond to the output image.
+
+        psS32 rows = 64;
+        psS32 cols = 64;
+        psImage *fOut = psImageAlloc(cols,rows,PS_TYPE_F32);
+        psImage *sOut = NULL;
+        psImage *fBiOut = psImageAlloc(cols,rows,PS_TYPE_F32);
+        psImage *sBiOut = NULL;
+        psImage *fTruth = NULL;
+        psImage *sTruth = NULL;
+        psImage *fBiTruth = NULL;
+        psImage *sBiTruth = NULL;
+        psImage *fImg = psImageAlloc(cols,rows,PS_TYPE_F32);
+        psImage *sImg = psImageAlloc(cols,rows,PS_TYPE_S16);
+
+        for(psS32 row=0;row<rows;row++) {
+            psF32 *fRow = fImg->data.F32[row];
+            psS16 *sRow = sImg->data.S16[row];
+            for (psS32 col=0;col<cols;col++) {
+                fRow[col] = (psF32)(row)+(psF32)(col)/100.0f;
+                sRow[col] = row-2*col;
+            }
+        }
+
+        // since interpolation is involved, etc., the simplist way to verify things
+        // is to verify the results manually and bless it for automated comparison
+        // thereafter
+
+        // write results of various rotates to a file and verify with truth images
+        system("mkdir temp");
+        psS32 index = 0;
+        psBool fail = false;
+        psF32 radianRot;
+
+        psFits *fOutFile = psFitsOpen("fOut.fits","w");
+        psFits *sOutFile = psFitsOpen("sOut.fits","w");
+        psFits *fBiOutFile = psFitsOpen("fBiOut.fits","w");
+        psFits *sBiOutFile = psFitsOpen("sBiOut.fits","w");
+        ok(fOutFile != NULL && sOutFile != NULL && fBiOutFile != NULL && sBiOutFile != NULL,
+           "psFitsOpen() created the output files");
+
+//            psFits *fTruthFile = psFitsOpen("imageops/verified/fOut.fits","r");
+//            psFits *sTruthFile = psFitsOpen("imageops/verified/sOut.fits","r");
+//            psFits *fBiTruthFile = psFitsOpen("imageops/verified/fBiOut.fits","r");
+//            psFits *sBiTruthFile = psFitsOpen("imageops/verified/sBiOut.fits","r");
+        psFits *fTruthFile = psFitsOpen("verified/fOut.fits","r");
+        psFits *sTruthFile = psFitsOpen("verified/sOut.fits","r");
+        psFits *fBiTruthFile = psFitsOpen("verified/fBiOut.fits","r");
+        psFits *sBiTruthFile = psFitsOpen("verified/sBiOut.fits","r");
+        ok(fTruthFile != NULL && sTruthFile != NULL && fBiTruthFile != NULL && sBiTruthFile != NULL,
+
+           "psFitsOpen() opened the truth files");
+
+        psRegion regionAll = psRegionSet(0,0,0,0);
+        for (psS32 rot=-180;rot<=180;rot+=45)
+        {
+            psImage *oldOut = fOut;
+            psImage *oldBiOut = fBiOut;
+            if (rot == 90) {
+                radianRot = M_PI_2;
+            } else if (rot == -90) {
+                radianRot = M_PI+M_PI_2;
+            } else if (rot == 180 || rot == -180) {
+                radianRot = M_PI;
+            } else {
+                radianRot = ((float)rot)*M_PI/180.0;
+            }
+
+            fOut = psImageRotate(fOut,fImg,radianRot,-1.0,PS_INTERPOLATE_FLAT);
+            fBiOut = psImageRotate(fBiOut,fImg,radianRot,-1.0,PS_INTERPOLATE_BILINEAR);
+            // Verify the returned psImage structure is equal to the input
+            // parameter out if provided.
+            ok(fOut != NULL, "psImageRotate() returned non-NULL (psImageRotate(), float image, with FLAT interpolation)");
+            ok(oldOut == fOut, "psImageRotate(): the output recycle functionality was successful");
+            ok(fBiOut != NULL, "psImageRotate() returned non-NULL (psImageRotate(), float image, with BILINEAR interpolation)");
+            ok(oldBiOut == fBiOut, "psImageRotate(): the output recycle functionality was successful");
+            sOut = psImageRotate(sOut,sImg,radianRot,-1.0,PS_INTERPOLATE_FLAT);
+            ok(sOut != NULL, "psImageRotate() returned non-NULL (psImageRotate(), short image, with FLAT interpolation)");
+            sBiOut = psImageRotate(sBiOut,sImg,radianRot,-1.0,PS_INTERPOLATE_BILINEAR);
+            ok(sBiOut != NULL, "psImageRotate() returned non-NULL (psImageRotate(), short image, with BILINEAR interpolation)");
+            ok(psFitsWriteImage(fOutFile, NULL, fOut, 1, NULL), "psFitsWriteImage() successful");
+            ok(psFitsWriteImage(sOutFile, NULL, sOut, 1, NULL), "psFitsWriteImage() successful");
+            ok(psFitsWriteImage(fBiOutFile, NULL, fBiOut, 1, NULL), "psFitsWriteImage() successful");
+            ok(psFitsWriteImage(sBiOutFile, NULL, sBiOut, 1, NULL), "psFitsWriteImage() successful");
+
+            // now, let's compare this with the verified file
+            psFitsMoveExtNum(fTruthFile, index, false);
+            psFitsMoveExtNum(sTruthFile, index, false);
+            psFitsMoveExtNum(fBiTruthFile, index, false);
+            psFitsMoveExtNum(sBiTruthFile, index, false);
+            psFree(fTruth);
+            psFree(sTruth);
+            psFree(fBiTruth);
+            psFree(sBiTruth);
+            fTruth = NULL;
+            sTruth = NULL;
+            fBiTruth = NULL;
+            sBiTruth = NULL;
+            fTruth = psFitsReadImage(fTruthFile, regionAll, 0);
+            sTruth = psFitsReadImage(sTruthFile, regionAll, 0);
+            fBiTruth = psFitsReadImage(fBiTruthFile, regionAll, 0);
+            sBiTruth = psFitsReadImage(sBiTruthFile, regionAll, 0);
+            bool errorFlag = false;
+            if (fTruth == NULL) {
+                diag("verified psF32 image failed to be read (%d deg. rotation)", rot);
+                errorFlag = true;
+                fail = true;
+            } else {
+                if(fTruth->numRows != fOut->numRows || fTruth->numCols != fOut->numCols) {
+                    diag("Rotated float image size did not equal truth image for %d deg rotation (%dx%d vs %dx%d)",
+                         rot,fOut->numCols,fOut->numRows,fTruth->numCols,fTruth->numRows);
+                    errorFlag = true;
+                } else {
+                    for (psS32 row=0;row<fTruth->numRows;row++) {
+                        psF32 *truthRow = fTruth->data.F32[row];
+                        psF32 *outRow = fOut->data.F32[row];
+                        for (psS32 col=0;col<fTruth->numCols;col++) {
+                            if (fabsf(truthRow[col]-outRow[col]) > 1) {
+                                if (VERBOSE) diag("Float Image mismatch (%f vs %f) at %d,%d",
+                                     outRow[col], truthRow[col],col,row);
+                                errorFlag = true;
+                            }
+                        }
+                    }
+                }
+            }
+            ok(!errorFlag, "psImageRotate() produced the correct data values (%d degree rotation), float images, FLAT interpolation", rot);
+
+
+            errorFlag = false;
+            if (sTruth == NULL) {
+                diag("verified psS16 image failed to be read (%d deg. rotation)",rot);
+                errorFlag = true;
+            } else {
+                if (sTruth->numRows != sOut->numRows ||
+                        sTruth->numCols != sOut->numCols) {
+                    diag("Rotated psS16 image size did not match truth image for %d deg rotation",rot);
+                    errorFlag = true;
+                } else {
+                    for (psS32 row=0;row<sTruth->numRows;row++) {
+                        psS16 *truthRow = sTruth->data.S16[row];
+                        psS16 *outRow = sOut->data.S16[row];
+                        for (psS32 col=0;col<sTruth->numCols;col++) {
+                            if (fabsf(truthRow[col]-outRow[col]) > 1) {
+                                if (VERBOSE) diag("Short Image mismatch (%d vs %d) at %d,%d",
+                                     outRow[col], truthRow[col],col,row);
+                                errorFlag = true;
+                            }
+                        }
+                    }
+                }
+            }
+            ok(!errorFlag, "psImageRotate() produced the correct data values (%d degree rotation), short images, FLAT interpolation", rot);
+            errorFlag = false;
+            if (fBiTruth == NULL) {
+                diag("verified psF32 Bi image failed to be read (%d deg. rotation)",
+                     rot);
+                errorFlag = true;
+            } else {
+                if (fBiTruth->numRows != fBiOut->numRows || fBiTruth->numCols != fBiOut->numCols) {
+                    diag("Rotated float image size did not match truth "
+                         "image for %d deg rotation (%dx%d vs %dx%d). BILINEAR",
+                         rot,fBiOut->numCols,fBiOut->numRows,fBiTruth->numCols,fBiTruth->numRows);
+                    errorFlag = true;
+                } else {
+                    for (psS32 row=0;row<fBiTruth->numRows;row++) {
+                        psF32 *truthRow = fBiTruth->data.F32[row];
+                        psF32 *outRow = fBiOut->data.F32[row];
+                        for (psS32 col=0;col<fBiTruth->numCols;col++) {
+                            if (fabsf(truthRow[col]-outRow[col]) > 1) {
+                                if (VERBOSE) diag("Float Image mismatch (%f vs %f) at %d,%d. BILINEAR",
+                                     outRow[col], truthRow[col],col,row);
+                                errorFlag = true;
+                            }
+                        }
+                    }
+                }
+            }
+            ok(!errorFlag, "psImageRotate() produced the correct data values (%d degree rotation), float images, BILINEAR interpolation", rot);
+            if (sBiTruth == NULL) {
+                diag("verified psS16 image failed to be read "
+                     "(%d deg. rotation) BILINEAR",rot);
+                errorFlag = true;
+                fail = true;
+            } else {
+                if (sBiTruth->numRows != sBiOut->numRows ||
+                        sBiTruth->numCols != sBiOut->numCols) {
+                    diag("Rotated psS16 image size did not match truth "
+                         "image for %d deg rotation. BILINEAR",rot);
+                    errorFlag = true;
+                } else {
+                    for (psS32 row=0;row<sBiTruth->numRows;row++) {
+                        psS16 *truthRow = sBiTruth->data.S16[row];
+                        psS16 *outRow = sBiOut->data.S16[row];
+                        for (psS32 col=0;col<sBiTruth->numCols;col++) {
+                            if (fabsf(truthRow[col]-outRow[col]) > 1) {
+                                if (VERBOSE) diag("Short Image mismatch (%d vs %d) "
+                                     "at %d,%d. BILINEAR",
+                                     outRow[col], truthRow[col],col,row);
+                                errorFlag = true;
+                            }
+                        }
+                    }
+                }
+            }
+            ok(!errorFlag, "psImageRotate() produced the correct data values (%d degree rotation), short images, BILINEAR interpolation", rot);
+
+            index++;
+        }
+//HERE
+        // Verify the returned psImage structure pointer is NULL and program
+        // execution doesn't stop, if the input parameter input is NULL.
+        // Following should be an error
+        // XXX: Verify error
+        fOut = psImageRotate(fOut,NULL,0,0,PS_INTERPOLATE_FLAT);
+        ok(fOut == NULL, "NULL was returned when the input image was NULL");
+
+        // Verify the returned psImage structure pointer is NULL and program
+        // execution doesn't stop, if the specified interpolation mode is unallowed
+        // Following should be an error for unallowed interpolation type
+        // XXX: Verify error
+        fOut = psImageRotate(fOut, fImg, 33, 0, -1);
+        ok(fOut == NULL, "NULL was returned when the interpolation mode is unallowed");
+
+        psFree(sOut);
+        psFree(fImg);
+        psFree(sImg);
+        psFree(fTruth);
+        psFree(sTruth);
+        psFree(sBiOut);
+        psFree(fBiTruth);
+        psFree(sBiTruth);
+        psFree(fBiOut);
+
+        psFree(fOutFile);
+        psFree(sOutFile);
+        psFree(fBiOutFile);
+        psFree(sBiOutFile);
+
+        psFree(fTruthFile);
+        psFree(sTruthFile);
+        psFree(fBiTruthFile);
+        psFree(sBiTruthFile);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageShift()
+    if (1) {
+        psMemId id = psMemGetId();
+        // This functions shall generate a new psImage structure by shifting the
+        // input psImage structure a specified number of pixels in the horizontal
+        // and/or vertical directions.
+        //
+        // Verify the returned psImage structure contains expected values, if the
+        // input psImage structure contains known values and a know shift in the
+        // vertical and/or horizontal directions. Cases should include no shift,
+        // vertical only(up,down), horizontal only(right, left), and combination
+        // shift. Cases should include fractional shifts. Comparison of expected
+        // values should include a delta to allow for testing on different
+        // platforms.
+        //
+        // Verify the returned psImage structure contains values for pixels not in
+        // the original image set to the input parameter exposed.
+
+        // integer shift
+        if (1)
+        {
+            ok(testImageShiftCase(64,128,0.0f,0.0f), "psImageShift (0, 0)");
+            ok(testImageShiftCase(64,128,0.0f,2.0f), "psImageShift (0, 16)");
+            ok(testImageShiftCase(64,128,0.0f,-16.0f), "psImageShift (0, -16)");
+            ok(testImageShiftCase(64,128,32.0f,0.0f), "psImageShift (32, 0)");
+            ok(testImageShiftCase(64,128,-32.0f,0.0f), "psImageShift (-32, 0)");
+            ok(testImageShiftCase(64,128,32.0f,16.0f), "psImageShift (32, 16)");
+            ok(testImageShiftCase(64,128,32.0f,-16.0f), "psImageShift (32, -16)");
+            ok(testImageShiftCase(64,128,-32.0f,16.0f), "psImageShift (-32, 16)");
+            ok(testImageShiftCase(64,128,-32.0f,-16.0f), "psImageShift (-32, -16)");
+
+            // fractional shift
+            ok(testImageShiftCase(64,128,0.0f,16.4f), "psImageShift (0, 16.4)");
+            ok(testImageShiftCase(64,128,0.0f,-16.4f), "psImageShift (0, -16.4)");
+            ok(testImageShiftCase(64,128,32.7f,0.0f), "psImageShift (32.7, 0)");
+            ok(testImageShiftCase(64,128,-32.7f,0.0f), "psImageShift (-32.7, 0)");
+            ok(testImageShiftCase(64,128,32.6f,16.2f), "psImageShift (32.6, 16.2)");
+            ok(testImageShiftCase(64,128,32.6f,-16.2f), "psImageShift (32.6, -16.2)");
+            ok(testImageShiftCase(64,128,-32.6f,16.2f), "psImageShift (-32.6, 16.2)");
+            ok(testImageShiftCase(64,128,-32.6f,-16.2f), "psImageShift (-32.6, -16.2)");
+        }
+
+        // Verify the returned psImage structure pointer is equal to the input
+        // parameter out if provided.
+        psImage *fImg = psImageAlloc(32,32,PS_TYPE_F32);
+        psImage *fRecycle = psImageAlloc(32,32,PS_TYPE_F32);
+        psImage *fOut = psImageShift(fRecycle, fImg, 8,8, NAN, PS_INTERPOLATE_FLAT);
+        ok(fRecycle == fOut, "psImageShift did recycle my image");
+
+        // Verify the returned psImage structure pointer is NULL and program
+        // execution doesn't stop, if the input psImage structure pointer is NULL.
+        // Following should be an error
+        // XXX: Verify error
+        fOut = psImageShift(fOut,NULL,8,8,NAN,PS_INTERPOLATE_FLAT);
+        ok(fOut == NULL, "psImageShift did return NULL given a NULL input image");
+
+        // Verify the returned psImage structure is NULL and program execution
+        // doesn't stop, if the specified interpolation mode is unallowed.
+        // Following should be an error for unallowed interpolation mode
+        // XXX: Verify error
+        fOut = psImageShift(fOut,fImg,8,8,NAN,-1);
+        ok(fOut == NULL, "psImageShift did return NULL given an unallowed interpolation mode");
+
+        psFree(fImg);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // test psImageResample()
+    if (1) {
+        psMemId id = psMemGetId();
+        psS32 rows = 60;
+        psS32 cols = 80;
+        psImage *result = NULL;
+        psS32 scale = 4;
+        psErr *err;
+
+        psImage *image = psImageAlloc(cols, rows, PS_TYPE_F32);
+        for(psS32 row=0;row<rows;row++) {
+            for (psS32 col=0;col<cols;col++) {
+                image->data.F32[row][col] = row+2*col;
+            }
+        }
+        result = psImageCopy(NULL,image,PS_TYPE_F64);
+        psImage *orig = result;
+        result = psImageResample(result,image,scale,PS_INTERPOLATE_FLAT);
+        ok(result != NULL, "psImageResample() returned non-NULL");
+        ok(result == orig, "psImageResample() recycled image");
+        ok(result->type.type == PS_TYPE_F32, "psImageResample() produced the correct type");
+        ok(result->numCols == image->numCols*scale && result->numRows == image->numRows*scale,
+           "psImageResample() produced the correct size");
+
+        bool errorFlag = false;
+        {
+            psImageInterpolateOptions *tmpIntOpts = psImageInterpolateOptionsAlloc(
+                PS_INTERPOLATE_FLAT, image, NULL, NULL, 0, -1.0, NAN, 0, 0, 0.0);
+            double imgVal;
+            double varVal;
+            psMaskType maskVal;
+            psF32 truthValue;
+            for(psS32 row=0;row<result->numRows;row++) {
+                for (psS32 col=0;col<result->numCols;col++) {
+//                    truthValue = psImagePixelInterpolate(image,
+//                                                         (float)col/(float)scale,(float)row/(float)scale,
+//                                                         NULL,0,-1,PS_INTERPOLATE_FLAT);
+                    psImageInterpolate(&imgVal, &varVal, &maskVal, 
+                                       (float)col/(float)scale,(float)row/(float)scale,
+                                       tmpIntOpts);
+
+                    if (fabs(truthValue - result->data.F32[row][col]) > FLT_EPSILON) {
+                        if (VERBOSE) diag("value bad at (%d,%d).  Got %g, expected %g",
+                             col,row,result->data.F32[row][col], truthValue);
+                        errorFlag = true;
+                    }
+                }
+            }
+            psFree(tmpIntOpts);
+        }
+
+        ok(!errorFlag, "psImageResample() produced the correct data values");
+
+        // verify that image=NULL is handled properly.
+        psErrorClear();
+        result = psImageResample(result,NULL,scale,PS_INTERPOLATE_FLAT);
+        ok(result == NULL, "psImageResample() returned NULL with NULL input");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_NULL, "psImageResample() produced the correct error message");
+        psFree(err);
+
+        // verify that scale < 1 is handled properly
+        psErrorClear();
+        result = psImageResample(result,image,0,PS_INTERPOLATE_FLAT);
+        ok(result == NULL, "psImageResample() returned NULL with scale < 1");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_VALUE, "psImageResample() produced the correct error message");
+        psFree(err);
+
+        // verify that unallowed interpolation mode is handled properly
+        psErrorClear();
+        result = psImageResample(result,image,2,-1);
+        ok(result == NULL, "psImageResample() returned NULL with unallowed interpolation mode");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_VALUE, "psImageResample() produced the correct error message");
+        psFree(err);
+
+        // Verify that that an unallowed image type is handled properly
+        psErrorClear();
+        psImage *invImage = psImageAlloc(cols,rows,PS_TYPE_BOOL);
+        memset(invImage->p_rawDataBuffer,0,cols*rows*PSELEMTYPE_SIZEOF(PS_TYPE_BOOL)); // make sure the image is of all NULLs
+        result = psImageResample(result,invImage,2,PS_INTERPOLATE_FLAT);
+        ok(result == NULL, "psImageResample() returned NULL with unallowed image type");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_TYPE, "psImageResample() produced the correct error message");
+        psFree(err);
+
+        psFree(image);
+        psFree(result);
+        psFree(invImage);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // test psImageTransform()
+    if (1) {
+        psMemId id = psMemGetId();
+        int cols = 16;
+        int rows = 32;
+
+        psPlaneTransform *trans = psPlaneTransformAlloc(2,2);
+        trans->x->coeff[1][0] = 0.5;
+        trans->y->coeff[0][1] = 1.5;
+
+        psImage *in = psImageAlloc(cols,rows,PS_TYPE_F32);
+        for (psS32 row=0;row<rows;row++) {
+            for (psS32 col=0;col<cols;col++) {
+                in->data.F32[row][col] = (psF32)row+(psF32)col/1000.0f;
+            }
+        }
+        P_PSIMAGE_SET_COL0(in, 1);
+        psImage *out = psImageTransform(NULL, NULL, in, NULL, 0, trans,
+                                        psRegionSet(1,1+cols*2,0,rows*2), NULL,
+                                        PS_INTERPOLATE_FLAT, -1);
+
+        ok(out != NULL, "psImageTransform() returned non-NULL");
+        ok(out->type.type == PS_TYPE_F32, "psImageTransform() produced the correct type");
+        ok(out->numRows == rows*2 && out->numCols == cols*2, "psImageTransform() produced the correct size");
+
+        if (1) {
+            psMemId id = psMemGetId();
+            psImageInterpolateOptions *tmpIntOpts = psImageInterpolateOptionsAlloc(
+                PS_INTERPOLATE_FLAT, in, NULL, NULL, 0, -1.0, NAN, 0, 0, 0.0);
+
+            double imgVal;
+            double varVal;
+            psMaskType maskVal;
+            bool errorFlag = false;
+            for (psS32 row=0;row<out->numRows;row++) {
+                for (psS32 col=0;col<cols;col++) {
+                    psImageInterpolate(&imgVal, &varVal, &maskVal, 
+                                       col*trans->x->coeff[1][0]+trans->x->coeff[0][0]+1,
+                                       row*trans->y->coeff[0][1]+trans->y->coeff[0][0],
+                                       tmpIntOpts);
+                    float inValue = imgVal;
+                    if (fabsf(out->data.F32[row][col] - inValue) > 0.01) {
+                        diag("out at %d,%d was %g, expected %g", col,row,
+                              out->data.F32[row][col], inValue);
+                        errorFlag = true;
+                    }
+                }
+            }
+            psFree(tmpIntOpts);
+            ok(!errorFlag, "psImageTransform() produced the correct data values");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+        psFree(out);
+        psFree(in);
+        psFree(trans);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageInterpolate.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageInterpolate.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageInterpolate.c	(revision 22158)
@@ -0,0 +1,327 @@
+/** @file tst_psImageInterpolate.c
+ *
+ * @brief Contains the tests for psImagePixelInterpolate
+ *
+ * @author Eric Van Alst, MHPCC
+ *
+ * @version $Revision: 1.3 $
+ *          $Name: not supported by cvs2svn $
+ * @date $Date: 2007-03-14 21:20:28 $
+ *
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define GENIMAGE(img,c,r,TYP,valueFcn) \
+img = psImageAlloc(c,r,PS_TYPE_##TYP); \
+for(psU32 row=0; row<r; row++) { \
+    ps##TYP* imgRow = img->data.TYP[row]; \
+    for(psU32 col=0; col<c; col++) { \
+        imgRow[col] = (ps##TYP)(valueFcn); \
+    } \
+}
+
+#define CHECK_INTERP_VALUE(img,x,y,mask,maskval,exposed,TYPE,expected) \
+{ \
+    psF32 val = (psF32)psImagePixelInterpolate(img,x,y,mask,maskval,exposed,PS_INTERPOLATE_##TYPE); \
+    ok(fabsf(val-expected)<FLT_EPSILON, "psImagePixelInterpolate() correct"); \
+}
+
+#define CHECK_INTERP_BY_TYPE(TYPE) \
+{ \
+    psImage* img1; \
+    GENIMAGE(img1,10,10,TYPE,row+col) \
+    CHECK_INTERP_VALUE(img1,1.9,1.6,NULL,0,0,FLAT,2.0) \
+    CHECK_INTERP_VALUE(img1,4.0,2.0,NULL,0,0,BILINEAR,5.0) \
+    psFree(img1); \
+}
+
+#define CHECK_INTERP_BY_TYPE_ORIG(TYPE) \
+{ \
+    psImage* img1; \
+    GENIMAGE(img1,10,10,TYPE,row+col) \
+    CHECK_INTERP_VALUE(img1,1.9,1.6,NULL,0,0,FLAT,2.0) \
+}
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(53);
+
+    // testInterpolateFlatBilinear(void)
+    // Perform simple(four neighbor) FLAT interpolation for all types
+    // Perform bilinear interpolation for all types
+    CHECK_INTERP_BY_TYPE(S8)
+    CHECK_INTERP_BY_TYPE(S16)
+    CHECK_INTERP_BY_TYPE(S32)
+    CHECK_INTERP_BY_TYPE(S64)
+    CHECK_INTERP_BY_TYPE(U8)
+    CHECK_INTERP_BY_TYPE(U16)
+    CHECK_INTERP_BY_TYPE(U32)
+    CHECK_INTERP_BY_TYPE(U64)
+    CHECK_INTERP_BY_TYPE(F32)
+    CHECK_INTERP_BY_TYPE(F64)
+
+    // testInterpolateError(void)
+    // Perform interpolation with NULL input image
+    // Following should generate an error message
+    // XXX: we do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psF32 val = psImagePixelInterpolate(NULL,1.2,1.2,NULL,0,5.0,PS_INTERPOLATE_FLAT);
+        ok(val == 5.0, "psImagePixelInterpolate() returned the unexposed value (NULL image)");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Perform interpolation with unallowed input image type
+    // Following should generate an error message
+    // XXX: we do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psImage *img1 = psImageAlloc(10,10,PS_TYPE_BOOL);
+        psF32 val = psImagePixelInterpolate(img1,1.2,1.2,NULL,0,10.0,PS_INTERPOLATE_FLAT);
+        ok(val == 10.0, "psImagePixelInterpolate() returned the unexposed value (unallowed image type)");
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Perform interpolation with unallowed method
+    // Following should generate an error message
+    // XXX: we do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psImage *img1 = psImageAlloc(10,10,PS_TYPE_BOOL);
+        psF32 val = psImagePixelInterpolate(img1,1.2,1.2,NULL,0,10.0,PS_INTERPOLATE_BILINEAR+1);
+        ok(val == 10.0, "psImagePixelInterpolate() returned the unexposed value (unallowed interpolation method)");
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // The following assumptions about the test image are:
+    //
+    //                     col
+    //             0   1   2   3   4   5   6   7  ...
+    //
+    // row 0       0   1   2   3   4   5   6   7
+    // row 1       1   2   3   4   5   6   7   8
+    // row 2       2   3   4   5   6   7   8   9
+    // ...
+    // testInterpolateMaskFlatBilinear(void)
+    psImage* img1 = NULL;
+    psImage* msk1 = NULL;
+
+    // Perform interpolate with mask and mask value set at nearest pixel to verify
+    // the unexposed value is return
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][1] = 1;
+        CHECK_INTERP_VALUE(img1,1.9,1.6,msk1,1,10.0,FLAT,10.0)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask and one mask value for bilinear (upper left pixel)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][3] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,5.25)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask and one mask value for bilinear (upper right pixel)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][4] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,4.75)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask and one mask value for bilinear (lower left pixel)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[2][3] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,5.25)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask and one mask value for bilinear (lower right pixel)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[2][4] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,4.75)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask and one mask value for bilinear (upper pixels)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][3] = 1;
+        msk1->data.U8[1][4] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,5.5)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask and one mask value for bilinear (lower pixels)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[2][3] = 1;
+        msk1->data.U8[2][4] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,4.5)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask and one mask value for bilinear (left pixels)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][3] = 1;
+        msk1->data.U8[2][3] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,5.5)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask and one mask value for bilinear (right pixels)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][4] = 1;
+        msk1->data.U8[2][4] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,4.5)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask only one valid pixel (upper left)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][4] = 1;
+        msk1->data.U8[2][3] = 1;
+        msk1->data.U8[2][4] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,4.0)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask only one valid pixel (upper right)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][3] = 1;
+        msk1->data.U8[2][3] = 1;
+        msk1->data.U8[2][4] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,5.0)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask only one valid pixel (lower left)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][3] = 1;
+        msk1->data.U8[1][4] = 1;
+        msk1->data.U8[2][4] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,5.0)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask only one valid pixel (lower right)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][3] = 1;
+        msk1->data.U8[1][4] = 1;
+        msk1->data.U8[2][3] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,6.0)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask no valid pixels
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][3] = 1;
+        msk1->data.U8[1][4] = 1;
+        msk1->data.U8[2][3] = 1;
+        msk1->data.U8[2][4] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,0.0)
+        psFree(msk1);
+        psFree(img1);
+        return 0;
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Perform interpolation for a 1D image
+    {
+        psMemId id = psMemGetId();
+        psImage* img1 = NULL;
+        GENIMAGE(img1,10,1,F32,row+col)
+        CHECK_INTERP_VALUE(img1,4.0,0.0,NULL,0,100.0,BILINEAR,3.5)
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageInterpolate2.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageInterpolate2.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageInterpolate2.c	(revision 22158)
@@ -0,0 +1,164 @@
+#include <stdio.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+
+#define NUM_POINTS 32
+
+// Function to define mask values
+psMaskType maskFunc(float x, float y)
+{
+    return 0;
+}
+
+// Function to define variance values
+double varianceFunc(float x, float y)
+{
+    return sqrtf(10.0 + 0.1 * x + 0.2 * y);
+}
+
+// Function to define image values
+double imageFunc(float x, float y)
+{
+    return 0.01 * x + 0.02 * y;
+}
+
+// Generate a dummy mask image
+psImage *generateMask(int numCols, int numRows)
+{
+    psImage *image = psImageAlloc(numCols, numRows, PS_TYPE_MASK);
+    for (int j = 0; j < numRows; j++) {
+        for (int i = 0; i < numCols; i++) {
+            psImageSet(image, i, j, maskFunc(i + 0.5, j + 0.5));
+        }
+    }
+    return image;
+}
+
+// Generate a dummy variance image
+psImage *generateVariance(int numCols, int numRows, psElemType type)
+{
+    psImage *image = psImageAlloc(numCols, numRows, type);
+    for (int j = 0; j < numRows; j++) {
+        for (int i = 0; i < numCols; i++) {
+            psImageSet(image, i, j, varianceFunc(i + 0.5, j + 0.5));
+        }
+    }
+    return image;
+}
+
+// Generate a dummy image
+psImage *generateImage(int numCols, int numRows, psElemType type)
+{
+    psImage *image = psImageAlloc(numCols, numRows, type);
+    for (int j = 0; j < numRows; j++) {
+        for (int i = 0; i < numCols; i++) {
+            psImageSet(image, i, j, imageFunc(i + 0.5, j + 0.5));
+        }
+    }
+    return image;
+}
+
+// Check a particular combination of image and interpolation parameters
+// Each has 2 + 2*num tests
+void check(int xSize, int ySize,        // Size of image
+           psElemType type,             // Type for image
+           int num,                     // Number of samples over image
+           psImageInterpolateMode mode, // Interpolation mode
+           int xKernel, int yKernel,    // Size of interpolation kernel
+           float tol                    // Tolerance
+    )
+{
+
+    psMemId id = psMemGetLastId();
+
+    psImage *image = generateImage(xSize, ySize, type);
+    psImage *variance = NULL; // generateVariance(xSize, ySize, type);
+    psImage *mask = NULL; // generateMask(xSize, ySize);
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 12345);
+
+    psImageInterpolateOptions *interp = psImageInterpolateOptionsAlloc(mode, image,
+                                                                       variance, mask, 0, NAN, NAN,
+                                                                       0, 0, 0.0);
+    ok(interp, "Interpolation options set");
+    skip_start(!interp, 2 * num, "Interpolation options failed");
+
+    for (int i = 0; i < num; i++) {
+        float x = psRandomUniform(rng) * xSize;
+        float y = psRandomUniform(rng) * ySize;
+
+        // Values from interpolation
+        double imageVal, varianceVal;
+        psMaskType maskVal;
+
+        bool success = psImageInterpolate(&imageVal, &varianceVal, &maskVal, x, y, interp);
+        ok(success, "Interpolation at %.2f,%.2f", x, y);
+        skip_start(!success, 1, "Interpolation failed");
+
+        int xCentral, yCentral;         // Central pixel of interpolation
+        switch (mode) {
+          case PS_INTERPOLATE_BICUBE:
+          case PS_INTERPOLATE_GAUSS:
+            xCentral = x;
+            yCentral = y;
+            break;
+          default:
+            xCentral = floor(x - 0.5);
+            yCentral = floor(y - 0.5);
+            break;
+        }
+
+        if (xCentral - (xKernel - 1) / 2 < 0 || xCentral + xKernel / 2 > xSize - 1 ||
+            yCentral - (yKernel - 1) / 2 < 0 || yCentral + yKernel / 2 > ySize - 1) {
+            ok(isnan(imageVal), "Interpolation = %f vs NAN (border)", imageVal);
+        } else {
+            is_double_tol(imageVal, imageFunc(x, y), tol, "Interpolation = %f vs %f",
+                          imageVal, imageFunc(x, y));
+        }
+
+        // Variance is very very very difficult to test without having the answer already
+        // Mask might be a bit easier.
+        // Defer these for now.
+
+        skip_end();
+    }
+
+    psFree(interp);
+    skip_end();
+
+    psFree(rng);
+    psFree(image);
+    psFree(variance);
+    psFree(mask);
+
+    ok(!psMemCheckLeaks(id, NULL, NULL, false), "No memory leaks");
+
+    return;
+}
+
+int main(int argc, char *argv[])
+{
+    plan_tests(792);
+
+    check(16, 16, PS_TYPE_F32, 32, PS_INTERPOLATE_BILINEAR, 2, 2, 1.0e-6); // 66 tests
+    check(16, 16, PS_TYPE_F64, 32, PS_INTERPOLATE_BILINEAR, 2, 2, 1.0e-6); // 66 tests
+
+    check(16, 16, PS_TYPE_F32, 32, PS_INTERPOLATE_BICUBE, 3, 3, 1.0e-6); // 66 tests
+    check(16, 16, PS_TYPE_F64, 32, PS_INTERPOLATE_BICUBE, 3, 3, 1.0e-6); // 66 tests
+
+    check(16, 16, PS_TYPE_F32, 32, PS_INTERPOLATE_GAUSS, 3, 3, 1.0e-3); // 66 tests
+    check(16, 16, PS_TYPE_F64, 32, PS_INTERPOLATE_GAUSS, 3, 3, 1.0e-3); // 66 tests
+
+    check(16, 16, PS_TYPE_F32, 32, PS_INTERPOLATE_LANCZOS2, 4, 4, 1.0e-3); // 66 tests
+    check(16, 16, PS_TYPE_F64, 32, PS_INTERPOLATE_LANCZOS2, 4, 4, 1.0e-3); // 66 tests
+
+    check(32, 32, PS_TYPE_F32, 32, PS_INTERPOLATE_LANCZOS3, 6, 6, 1.0e-3); // 66 tests
+    check(32, 32, PS_TYPE_F64, 32, PS_INTERPOLATE_LANCZOS3, 6, 6, 1.0e-3); // 66 tests
+
+    check(32, 32, PS_TYPE_F32, 32, PS_INTERPOLATE_LANCZOS4, 8, 8, 1.0e-3); // 66 tests
+    check(32, 32, PS_TYPE_F64, 32, PS_INTERPOLATE_LANCZOS4, 8, 8, 1.0e-3); // 66 tests
+
+    return exit_status();
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageMap.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageMap.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageMap.c	(revision 22158)
@@ -0,0 +1,244 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+int SaveImage (psMetadata *header, psImage *image, char *filename) {
+
+    psFits *fits = psFitsOpen (filename, "w");
+    psFitsWriteImage (fits, NULL, image, 0, NULL);
+    psFitsClose (fits);
+    return (TRUE);
+}
+
+# define C00 +0.5
+# define C01 +0.1
+# define C10 -0.2
+
+int main (void)
+{
+
+    // plan_tests(0);
+    
+    // *** tests to demonstrate the validity of the algorithm or concept ***
+
+    // make a model for a well-sampled field of a simple function (f = ax + by + c)
+    # if (0)
+    {
+	// function is defined over the range 0-1000, 0-1000
+	psImageBinning *binning = psImageBinningAlloc();
+	binning->nXfine = 1000;
+	binning->nYfine = 1000;
+	binning->nXruff = 5;
+	binning->nYruff = 5;
+
+	// generate a grid of test data points
+	psVector *x = psVectorAllocEmpty (100, PS_TYPE_F32);
+	psVector *y = psVectorAllocEmpty (100, PS_TYPE_F32);
+	psVector *f = psVectorAllocEmpty (100, PS_TYPE_F32);
+
+	for (int ix = 0; ix < 1000; ix += 20) {
+	    for (int iy = 0; iy < 1000; iy += 20) {
+		x->data.F32[x->n] = ix;
+		y->data.F32[y->n] = iy;
+		f->data.F32[f->n] = C00 + C10*ix + C01*iy;
+		psVectorExtend (x, 100, 1);
+		psVectorExtend (y, 100, 1);
+		psVectorExtend (f, 100, 1);
+	    }
+	}
+
+	psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+
+	// scale defines both field and map image sizes (nXfine, nXruff)
+	psImageMap *map = psImageMapAlloc (NULL, binning, stats);
+
+	// allocate a map, but we have no field image to supply
+	// XXX this function needs to correct for the mean superpixel position 
+	// which is sampled...
+	psImageMapGenerate (map, x, y, f, 0.1);
+	psFree (binning);
+
+	fprintf (stderr, "nGood: %d\n", map->nGood);
+	fprintf (stderr, "nPoor: %d\n", map->nPoor);
+	fprintf (stderr, "nBad:  %d\n", map->nBad);
+	
+	SaveImage (NULL, map->map, "map.fits");
+	
+	psImage *field = psImageAlloc(1000, 1000, PS_TYPE_F32);
+	for (int ix = 0; ix < 1000; ix++) {
+	    for (int iy = 0; iy < 1000; iy++) {
+		field->data.F32[iy][ix] = C00 + C10*ix + C01*iy;
+	    }
+	}
+	SaveImage (NULL, field, "field.fits");
+
+	// measure difference between model (map) and data (field)
+	for (int ix = 0; ix < map->map->numCols; ix++) {
+	    for (int iy = 0; iy < map->map->numRows; iy++) {
+		int xo = psImageBinningGetFineX(map->binning, ix + 0.5);
+		int yo = psImageBinningGetFineY(map->binning, iy + 0.5);
+		float df = field->data.F32[yo][xo] - map->map->data.F32[iy][ix];
+		fprintf (stderr, "%d %d -> %d %d  :  %f = %f - %f\n", ix, iy, xo, yo, df, field->data.F32[yo][xo], map->map->data.F32[iy][ix]);
+	    }
+	}
+
+	psImage *model = psImageAlloc(1000, 1000, PS_TYPE_F32);
+	for (int ix = 0; ix < 1000; ix++) {
+	    for (int iy = 0; iy < 1000; iy++) {
+		model->data.F32[iy][ix] = psImageUnbinPixel (ix + 0.5, iy + 0.5, map->map, map->binning);
+	    }
+	}
+	SaveImage (NULL, model, "model.fits");
+    }
+    # endif
+
+    // make a model for a poorly-sampled field of a simple function (f = ax + by + c)
+
+    // choose a model scale for a poorly-sampled field of a simple function (f = ax + by + c)
+
+    // make a model for a well-sampled field of a high-order polynomial function (f = (a(x-xo)^2 + b(y-yo)^2) + c)
+    # if (0)
+    {
+	// function is defined over the range 0-1000, 0-1000
+	psImageBinning *binning = psImageBinningAlloc();
+	binning->nXfine = 1000;
+	binning->nYfine = 1000;
+	binning->nXruff = 5;
+	binning->nYruff = 5;
+
+	// generate a grid of test data points
+	psVector *x = psVectorAllocEmpty (100, PS_TYPE_F32);
+	psVector *y = psVectorAllocEmpty (100, PS_TYPE_F32);
+	psVector *f = psVectorAllocEmpty (100, PS_TYPE_F32);
+
+	for (int ix = 0; ix < 1000; ix += 20) {
+	    for (int iy = 0; iy < 1000; iy += 20) {
+		x->data.F32[x->n] = ix;
+		y->data.F32[y->n] = iy;
+		f->data.F32[f->n] = C10*PS_SQR(ix-500) + C01*PS_SQR(iy-500);
+		psVectorExtend (x, 100, 1);
+		psVectorExtend (y, 100, 1);
+		psVectorExtend (f, 100, 1);
+	    }
+	}
+
+	psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+
+	// scale defines both field and map image sizes (nXfine, nXruff)
+	psImageMap *map = psImageMapAlloc (NULL, binning, stats);
+
+	// allocate a map, but we have no field image to supply
+	// XXX this function needs to correct for the mean superpixel position 
+	// which is sampled...
+	psImageMapGenerate (map, x, y, f, 0.1);
+	psFree (binning);
+
+	fprintf (stderr, "nGood: %d\n", map->nGood);
+	fprintf (stderr, "nPoor: %d\n", map->nPoor);
+	fprintf (stderr, "nBad:  %d\n", map->nBad);
+	
+	SaveImage (NULL, map->map, "map.fits");
+	
+	psImage *field = psImageAlloc(1000, 1000, PS_TYPE_F32);
+	for (int ix = 0; ix < 1000; ix++) {
+	    for (int iy = 0; iy < 1000; iy++) {
+		field->data.F32[iy][ix] = C10*PS_SQR(ix-500) + C01*PS_SQR(iy-500);
+	    }
+	}
+	SaveImage (NULL, field, "field.fits");
+
+	// measure difference between model (map) and data (field)
+	for (int ix = 0; ix < map->map->numCols; ix++) {
+	    for (int iy = 0; iy < map->map->numRows; iy++) {
+		int xo = psImageBinningGetFineX(map->binning, ix + 0.5);
+		int yo = psImageBinningGetFineY(map->binning, iy + 0.5);
+		float df = field->data.F32[yo][xo] - map->map->data.F32[iy][ix];
+		fprintf (stderr, "%d %d -> %d %d  :  %f = %f - %f\n", ix, iy, xo, yo, df, field->data.F32[yo][xo], map->map->data.F32[iy][ix]);
+	    }
+	}
+    }
+    # endif
+
+    // make a model for a well-sampled field of a high-order polynomial function (f = (a(x-xo)^2 + b(y-yo)^2) + c)
+    # if (1)
+    {
+	// function is defined over the range 0-1000, 0-1000
+	psImageBinning *binning = psImageBinningAlloc();
+	binning->nXfine = 1000;
+	binning->nYfine = 1000;
+	binning->nXruff = 5;
+	binning->nYruff = 5;
+
+	// generate a grid of test data points
+	psVector *x = psVectorAllocEmpty (100, PS_TYPE_F32);
+	psVector *y = psVectorAllocEmpty (100, PS_TYPE_F32);
+	psVector *f = psVectorAllocEmpty (100, PS_TYPE_F32);
+
+	for (int ix = 0; ix < 1000; ix += 20) {
+	    for (int iy = 0; iy < 1000; iy += 20) {
+		x->data.F32[x->n] = ix;
+		y->data.F32[y->n] = iy;
+		f->data.F32[f->n] = C10*(ix-500) + PS_SQR(C01*(iy-500));
+		psVectorExtend (x, 100, 1);
+		psVectorExtend (y, 100, 1);
+		psVectorExtend (f, 100, 1);
+	    }
+	}
+
+	psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+
+	// scale defines both field and map image sizes (nXfine, nXruff)
+	psImageMap *map = psImageMapAlloc (NULL, binning, stats);
+
+	// allocate a map, but we have no field image to supply
+	// XXX this function needs to correct for the mean superpixel position 
+	// which is sampled...
+	psImageMapGenerate (map, x, y, f, NULL, 0.1);
+	psFree (binning);
+
+	fprintf (stderr, "nGood: %d\n", map->nGood);
+	fprintf (stderr, "nPoor: %d\n", map->nPoor);
+	fprintf (stderr, "nBad:  %d\n", map->nBad);
+	
+	SaveImage (NULL, map->map, "map.fits");
+	
+	psImage *field = psImageAlloc(1000, 1000, PS_TYPE_F32);
+	for (int ix = 0; ix < 1000; ix++) {
+	    for (int iy = 0; iy < 1000; iy++) {
+		field->data.F32[iy][ix] = C10*(ix-500) + PS_SQR(C01*(iy-500));
+	    }
+	}
+	SaveImage (NULL, field, "field.fits");
+
+	// measure difference between model (map) and data (field)
+	for (int ix = 0; ix < map->map->numCols; ix++) {
+	    for (int iy = 0; iy < map->map->numRows; iy++) {
+		int xo = psImageBinningGetFineX(map->binning, ix + 0.5);
+		int yo = psImageBinningGetFineY(map->binning, iy + 0.5);
+		float df = field->data.F32[yo][xo] - map->map->data.F32[iy][ix];
+		fprintf (stderr, "%d %d -> %d %d  :  %f = %f - %f\n", ix, iy, xo, yo, df, field->data.F32[yo][xo], map->map->data.F32[iy][ix]);
+	    }
+	}
+
+
+	psImage *model = psImageAlloc(1000, 1000, PS_TYPE_F32);
+	for (int ix = 0; ix < 1000; ix++) {
+	    for (int iy = 0; iy < 1000; iy++) {
+		// XXX the binned coordinates are probably off by 0.5 pix, or we are interpolating 
+		// to the wrong binned coordinate.  
+		// XXX fix edge cases
+		model->data.F32[iy][ix] = psImageUnbinPixel (ix + 0.5, iy + 0.5, map->map, map->binning);
+	    }
+	}
+	SaveImage (NULL, model, "model.fits");
+    }
+    # endif
+
+    // make a model for a poorly-sampled field of a non-polynomial function (f = (a(x-xo)^2 + b(y-yo)^2)^-1)
+
+    // choose a model scale for a poorly-sampled field of a non-polynomial function (f = (a(x-xo)^2 + b(y-yo)^2)^-1)
+
+}   
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageMapFit.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageMapFit.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageMapFit.c	(revision 22158)
@@ -0,0 +1,843 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+// save function used to dump out test images while debugging algorithm
+int SaveImage (psMetadata *header, psImage *image, char *filename) {
+
+    psFits *fits = psFitsOpen (filename, "w");
+    psFitsWriteImage (fits, NULL, image, 0, NULL);
+    psFitsClose (fits);
+    return (TRUE);
+}
+
+# define TEST_4PT_0 1
+# define TEST_4PT_1 1
+# define TEST_4PT_2 1
+# define TEST_4PT_3 1
+# define TEST_6PT_0 1
+# define TEST_9PT_0 1
+# define TEST_9PT_1 1
+# define TEST_9PT_2 1
+# define TEST_9PT_3 1
+# define TEST_9PT_4 1
+# define TEST_9PT_5 1
+
+int main (void)
+{
+
+    plan_tests(219);
+    
+    // *** tests to demonstrate the validity of the algorithm or concept ***
+
+    // test with unconstrained cell: 3x3 grid fitted to 8 points with simple slope and scale difference
+    # if (TEST_9PT_5)
+    {
+        psMemId id = psMemGetId();
+
+	psImageBinning *binning = psImageBinningAlloc();
+	binning->nXfine = 6;
+	binning->nYfine = 6;
+	binning->nXruff = 3;
+	binning->nYruff = 3;
+
+	// generate a grid of test data points
+	psVector *x = psVectorAlloc (50, PS_TYPE_F32);
+	psVector *y = psVectorAlloc (50, PS_TYPE_F32);
+	psVector *f = psVectorAlloc (50, PS_TYPE_F32);
+
+	// the underlying field is f = ix + iy, where ix,iy are fine pixel coordinates
+	// place the measurement points exactly on the ruff reference pixel centers
+	int n = 0;
+	for (float ix = 1.0; ix < 6.0; ix += 2.0) {
+	    for (float iy = 1.0; iy < 6.0; iy += 2.0) {
+		if ((ix == 1.0) && (iy == 1.0)) continue;
+		x->data.F32[n] = ix;
+		y->data.F32[n] = iy;
+		f->data.F32[n] = x->data.F32[n] + y->data.F32[n];
+		n++;
+	    }
+	}
+	x->n = n;
+	y->n = n;
+	f->n = n;
+
+	psImage *field = psImageAlloc(6, 6, PS_TYPE_F32);
+	for (int ix = 0; ix < 6; ix++) {
+	    for (int iy = 0; iy < 6; iy++) {
+		field->data.F32[iy][ix] = (ix + 0.5) + (iy + 0.5);
+	    }
+	}
+
+	psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+
+	// scale defines both field and map image sizes (nXfine, nXruff)
+	psImageMap *map = psImageMapAlloc (NULL, binning, stats);
+
+	// fit the data to the map
+	psImageMapFit (map, NULL, 0, x, y, f, NULL);
+
+	psImage *model = psImageAlloc(field->numCols, field->numRows, PS_TYPE_F32);
+	for (int ix = 0; ix < model->numCols; ix++) {
+	    for (int iy = 0; iy < model->numRows; iy++) {
+		model->data.F32[iy][ix] = psImageUnbinPixel_V2 (ix + 0.5, iy + 0.5, map->map, map->binning);
+		if ((ix < 3) && (iy < 3)) {
+		    is_float (model->data.F32[iy][ix], NAN, "model matches expected NaN");
+		} else {
+		    is_float_tol (model->data.F32[iy][ix], field->data.F32[iy][ix], 1e-5, "model matches inputs");
+		}
+	    }
+	}
+
+	// SaveImage (NULL, map->map, "map.fits");
+	// SaveImage (NULL, field, "field.fits");
+	// SaveImage (NULL, model, "model.fits");
+
+	psFree (model);
+	psFree (binning);
+	psFree (map);
+	psFree (stats);
+	psFree (field);
+	psFree (x);
+	psFree (y);
+	psFree (f);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    # endif
+
+    // test for more points: 3x3 grid fitted to 9 points with simple slope and scale difference
+    # if (TEST_9PT_4)
+    {
+        psMemId id = psMemGetId();
+
+	psImageBinning *binning = psImageBinningAlloc();
+	binning->nXfine = 6;
+	binning->nYfine = 6;
+	binning->nXruff = 3;
+	binning->nYruff = 3;
+
+	// generate a grid of test data points
+	psVector *x = psVectorAlloc (50, PS_TYPE_F32);
+	psVector *y = psVectorAlloc (50, PS_TYPE_F32);
+	psVector *f = psVectorAlloc (50, PS_TYPE_F32);
+
+	// the underlying field is f = ix + iy, where ix,iy are fine pixel coordinates
+	// place the measurement points exactly on the ruff reference pixel centers
+	int n = 0;
+	for (float ix = 0.5; ix < 6.0; ix += 1.0) {
+	    for (float iy = 0.5; iy < 6.0; iy += 1.0) {
+		x->data.F32[n] = ix;
+		y->data.F32[n] = iy;
+		f->data.F32[n] = x->data.F32[n] + y->data.F32[n];
+		n++;
+	    }
+	}
+	x->n = n;
+	y->n = n;
+	f->n = n;
+
+	psImage *field = psImageAlloc(6, 6, PS_TYPE_F32);
+	for (int ix = 0; ix < 6; ix++) {
+	    for (int iy = 0; iy < 6; iy++) {
+		field->data.F32[iy][ix] = (ix + 0.5) + (iy + 0.5);
+	    }
+	}
+
+	psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+
+	// scale defines both field and map image sizes (nXfine, nXruff)
+	psImageMap *map = psImageMapAlloc (NULL, binning, stats);
+
+	// fit the data to the map
+	psImageMapFit (map, NULL, 0, x, y, f, NULL);
+
+	psImage *model = psImageAlloc(field->numCols, field->numRows, PS_TYPE_F32);
+	for (int ix = 0; ix < model->numCols; ix++) {
+	    for (int iy = 0; iy < model->numRows; iy++) {
+		model->data.F32[iy][ix] = psImageUnbinPixel_V2 (ix + 0.5, iy + 0.5, map->map, map->binning);
+		is_float_tol (model->data.F32[iy][ix], field->data.F32[iy][ix], 1e-5, "model matches inputs");
+	    }
+	}
+
+	// SaveImage (NULL, map->map, "map.fits");
+	// SaveImage (NULL, field, "field.fits");
+	// SaveImage (NULL, model, "model.fits");
+
+	psFree (model);
+	psFree (binning);
+	psFree (map);
+	psFree (stats);
+	psFree (field);
+	psFree (x);
+	psFree (y);
+	psFree (f);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    # endif
+
+    // test for more points: 3x3 grid fitted to 9 points with simple slope and scale difference
+    # if (TEST_9PT_3)
+    {
+        psMemId id = psMemGetId();
+
+	psImageBinning *binning = psImageBinningAlloc();
+	binning->nXfine = 6;
+	binning->nYfine = 6;
+	binning->nXruff = 3;
+	binning->nYruff = 3;
+
+	// generate a grid of test data points
+	psVector *x = psVectorAlloc (50, PS_TYPE_F32);
+	psVector *y = psVectorAlloc (50, PS_TYPE_F32);
+	psVector *f = psVectorAlloc (50, PS_TYPE_F32);
+
+	// the underlying field is f = ix + iy, where ix,iy are fine pixel coordinates
+	// place the measurement points exactly on the ruff reference pixel centers
+	int n = 0;
+	for (float ix = 1.0; ix < 6; ix += 2.0) {
+	    for (float iy = 1.0; iy < 6; iy += 2.0) {
+		y->data.F32[n] = iy;
+		x->data.F32[n] = ix;
+		if ((ix == 1.0) && (iy == 1.0)) {
+		    x->data.F32[n] = ix - 0.1;
+		}
+		if ((ix == 3.0) && (iy == 1.0)) {
+		    y->data.F32[n] = iy - 0.1;
+		}
+		if ((ix == 5.0) && (iy == 3.0)) {
+		    x->data.F32[n] = ix + 0.1;
+		}
+		if ((ix == 3.0) && (iy == 5.0)) {
+		    y->data.F32[n] = iy + 0.1;
+		}
+		f->data.F32[n] = x->data.F32[n] + y->data.F32[n];
+		n++;
+	    }
+	}
+	x->n = n;
+	y->n = n;
+	f->n = n;
+
+	psImage *field = psImageAlloc(6, 6, PS_TYPE_F32);
+	for (int ix = 0; ix < 6; ix++) {
+	    for (int iy = 0; iy < 6; iy++) {
+		field->data.F32[iy][ix] = (ix + 0.5) + (iy + 0.5);
+	    }
+	}
+
+	psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+
+	// scale defines both field and map image sizes (nXfine, nXruff)
+	psImageMap *map = psImageMapAlloc (NULL, binning, stats);
+
+	// fit the data to the map
+	psImageMapFit (map, NULL, 0, x, y, f, NULL);
+
+	psImage *model = psImageAlloc(field->numCols, field->numRows, PS_TYPE_F32);
+	for (int ix = 0; ix < model->numCols; ix++) {
+	    for (int iy = 0; iy < model->numRows; iy++) {
+		model->data.F32[iy][ix] = psImageUnbinPixel_V2 (ix + 0.5, iy + 0.5, map->map, map->binning);
+		is_float_tol (model->data.F32[iy][ix], field->data.F32[iy][ix], 1e-5, "model matches inputs");
+	    }
+	}
+
+	// SaveImage (NULL, map->map, "map.fits");
+	// SaveImage (NULL, field, "field.fits");
+	// SaveImage (NULL, model, "model.fits");
+	
+	psFree (model);
+	psFree (binning);
+	psFree (map);
+	psFree (stats);
+	psFree (field);
+	psFree (x);
+	psFree (y);
+	psFree (f);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    # endif
+
+    // test for more points: 3x3 grid fitted to 9 points with simple slope and scale difference
+# if (TEST_9PT_2)
+    {
+        psMemId id = psMemGetId();
+
+	psImageBinning *binning = psImageBinningAlloc();
+	binning->nXfine = 3;
+	binning->nYfine = 3;
+	binning->nXruff = 3;
+	binning->nYruff = 3;
+
+	// generate a grid of test data points
+	psVector *x = psVectorAlloc (50, PS_TYPE_F32);
+	psVector *y = psVectorAlloc (50, PS_TYPE_F32);
+	psVector *f = psVectorAlloc (50, PS_TYPE_F32);
+
+	// the underlying field is f = ix + iy, where ix,iy are fine pixel coordinates
+	// place the measurement points exactly on the ruff reference pixel centers
+	int n = 0;
+	for (float ix = 0.0; ix < 3; ix += 1.0) {
+	    for (float iy = 0.0; iy < 3; iy += 1.0) {
+		x->data.F32[n] = ix + 0.5;
+		y->data.F32[n] = iy + 0.5;
+
+		if (ix == 0.0) {
+		    x->data.F32[n] -= 0.1;
+		}
+		if (iy == 0.0) {
+		    y->data.F32[n] -= 0.1;
+		}
+		if (ix == 2.0) {
+		    x->data.F32[n] += 0.1;
+		}
+		if (iy == 2.0) {
+		    y->data.F32[n] += 0.1;
+		}
+		f->data.F32[n] = x->data.F32[n] + y->data.F32[n];
+		n++;
+	    }
+	}
+	x->n = n;
+	y->n = n;
+	f->n = n;
+
+	psImage *field = psImageAlloc(3, 3, PS_TYPE_F32);
+	for (int ix = 0; ix < 3; ix++) {
+	    for (int iy = 0; iy < 3; iy++) {
+		field->data.F32[iy][ix] = (ix + 0.5) + (iy + 0.5);
+	    }
+	}
+
+	psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+
+	// scale defines both field and map image sizes (nXfine, nXruff)
+	psImageMap *map = psImageMapAlloc (NULL, binning, stats);
+
+	// fit the data to the map
+	psImageMapFit (map, NULL, 0, x, y, f, NULL);
+
+	psImage *model = psImageAlloc(field->numCols, field->numRows, PS_TYPE_F32);
+	for (int ix = 0; ix < model->numCols; ix++) {
+	    for (int iy = 0; iy < model->numRows; iy++) {
+		model->data.F32[iy][ix] = psImageUnbinPixel_V2 (ix + 0.5, iy + 0.5, map->map, map->binning);
+		is_float_tol (model->data.F32[iy][ix], field->data.F32[iy][ix], 1e-5, "model matches inputs");
+	    }
+	}
+	// SaveImage (NULL, map->map, "map.fits");
+	// SaveImage (NULL, field, "field.fits");
+	// SaveImage (NULL, model, "model.fits");
+
+	psFree (model);
+	psFree (binning);
+	psFree (map);
+	psFree (stats);
+	psFree (field);
+	psFree (x);
+	psFree (y);
+	psFree (f);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+# endif
+
+    // still a simple test: 3x3 grid fitted to 9 points with simple slope and scale difference
+    # if (TEST_9PT_1)
+    {
+        psMemId id = psMemGetId();
+
+	psImageBinning *binning = psImageBinningAlloc();
+	binning->nXfine = 6;
+	binning->nYfine = 6;
+	binning->nXruff = 3;
+	binning->nYruff = 3;
+
+	// generate a grid of test data points
+	psVector *x = psVectorAlloc (9, PS_TYPE_F32);
+	psVector *y = psVectorAlloc (9, PS_TYPE_F32);
+	psVector *f = psVectorAlloc (9, PS_TYPE_F32);
+
+	// the underlying field is f = ix + iy, where ix,iy are fine pixel coordinates
+	// place the measurement points exactly on the ruff reference pixel centers
+	int n = 0;
+	for (int ix = 1; ix < 6; ix += 2) {
+	    for (int iy = 1; iy < 6; iy += 2) {
+		x->data.F32[n] = ix;
+		y->data.F32[n] = iy;
+		f->data.F32[n] = x->data.F32[n] + y->data.F32[n];
+		n++;
+	    }
+	}
+
+	psImage *field = psImageAlloc(6, 6, PS_TYPE_F32);
+	for (int ix = 0; ix < 6; ix++) {
+	    for (int iy = 0; iy < 6; iy++) {
+		field->data.F32[iy][ix] = (ix + 0.5) + (iy + 0.5);
+	    }
+	}
+
+	psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+
+	// scale defines both field and map image sizes (nXfine, nXruff)
+	psImageMap *map = psImageMapAlloc (NULL, binning, stats);
+
+	// fit the data to the map
+	psImageMapFit (map, NULL, 0, x, y, f, NULL);
+
+	psImage *model = psImageAlloc(field->numCols, field->numRows, PS_TYPE_F32);
+	for (int ix = 0; ix < model->numCols; ix++) {
+	    for (int iy = 0; iy < model->numRows; iy++) {
+		model->data.F32[iy][ix] = psImageUnbinPixel_V2 (ix + 0.5, iy + 0.5, map->map, map->binning);
+		is_float_tol (model->data.F32[iy][ix], field->data.F32[iy][ix], FLT_EPSILON, "model matches inputs");
+	    }
+	}
+
+	// SaveImage (NULL, map->map, "map.fits");
+	// SaveImage (NULL, field, "field.fits");
+	// SaveImage (NULL, model, "model.fits");
+
+	psFree (model);
+	psFree (binning);
+	psFree (map);
+	psFree (stats);
+	psFree (field);
+	psFree (x);
+	psFree (y);
+	psFree (f);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    # endif
+
+    // very simple test: 3x3 grid fitted to 9 points with simple slope
+    # if (TEST_9PT_0)
+    {
+	// function is defined over the range 0-1000, 0-1000
+        psMemId id = psMemGetId();
+
+	psImageBinning *binning = psImageBinningAlloc();
+	binning->nXfine = 3;
+	binning->nYfine = 3;
+	binning->nXruff = 3;
+	binning->nYruff = 3;
+
+	// generate a grid of test data points
+	psVector *x = psVectorAlloc (9, PS_TYPE_F32);
+	psVector *y = psVectorAlloc (9, PS_TYPE_F32);
+	psVector *f = psVectorAlloc (9, PS_TYPE_F32);
+
+	int n = 0;
+	psImage *field = psImageAlloc(3, 3, PS_TYPE_F32);
+	for (int ix = 0; ix < 3; ix++) {
+	    for (int iy = 0; iy < 3; iy++) {
+		x->data.F32[n] = ix + 0.5;
+		y->data.F32[n] = iy + 0.5;
+		f->data.F32[n] = x->data.F32[n] + y->data.F32[n];
+		field->data.F32[iy][ix] = f->data.F32[n];
+		n++;
+	    }
+	}
+
+	psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+
+	// scale defines both field and map image sizes (nXfine, nXruff)
+	psImageMap *map = psImageMapAlloc (NULL, binning, stats);
+
+	// fit the data to the map
+	psImageMapFit (map, NULL, 0, x, y, f, NULL);
+
+	psImage *model = psImageAlloc(field->numCols, field->numRows, PS_TYPE_F32);
+	for (int ix = 0; ix < model->numCols; ix++) {
+	    for (int iy = 0; iy < model->numRows; iy++) {
+		model->data.F32[iy][ix] = psImageUnbinPixel_V2 (ix + 0.5, iy + 0.5, map->map, map->binning);
+		is_float_tol (model->data.F32[iy][ix], field->data.F32[iy][ix], FLT_EPSILON, "model matches inputs");
+	    }
+	}
+
+	// SaveImage (NULL, map->map, "map.fits");
+	// SaveImage (NULL, field, "field.fits");
+	// SaveImage (NULL, model, "model.fits");
+
+	psFree (model);
+	psFree (binning);
+	psFree (map);
+	psFree (stats);
+	psFree (field);
+	psFree (x);
+	psFree (y);
+	psFree (f);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    # endif
+
+    // test for more points: 3x3 grid fitted to 9 points with simple slope and scale difference
+    # if (TEST_6PT_0)
+    {
+        psMemId id = psMemGetId();
+
+	psImageBinning *binning = psImageBinningAlloc();
+	binning->nXfine = 3;
+	binning->nYfine = 2;
+	binning->nXruff = 3;
+	binning->nYruff = 2;
+
+	// generate a grid of test data points
+	psVector *x = psVectorAlloc (50, PS_TYPE_F32);
+	psVector *y = psVectorAlloc (50, PS_TYPE_F32);
+	psVector *f = psVectorAlloc (50, PS_TYPE_F32);
+
+	// the underlying field is f = ix + iy, where ix,iy are fine pixel coordinates
+	// place the measurement points exactly on the ruff reference pixel centers
+	int n = 0;
+	for (float ix = 0.5; ix < 3.0; ix += 1.0) {
+	    for (float iy = 0.5; iy < 2.0; iy += 1.0) {
+		// x->data.F32[n] = ix;
+		// y->data.F32[n] = iy;
+		if ((ix == 0.5) && (iy == 0.5)) {
+		    x->data.F32[n] = ix + 0.0;
+		    y->data.F32[n] = iy + 0.1; // add in both points.  
+		    // f->data.F32[n] = x->data.F32[n] + y->data.F32[n];
+		    // n++;
+		    // x->data.F32[n] = ix + 0.0;
+		    // y->data.F32[n] = iy - 0.1;
+		} else {
+		    x->data.F32[n] = ix;
+		    y->data.F32[n] = iy;
+		}
+		f->data.F32[n] = x->data.F32[n] + y->data.F32[n];
+		n++;
+	    }
+	}
+	x->n = n;
+	y->n = n;
+	f->n = n;
+
+	psImage *field = psImageAlloc(3, 2, PS_TYPE_F32);
+	for (int ix = 0; ix < 3; ix++) {
+	    for (int iy = 0; iy < 2; iy++) {
+		field->data.F32[iy][ix] = (ix + 0.5) + (iy + 0.5);
+	    }
+	}
+
+	psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+
+	// scale defines both field and map image sizes (nXfine, nXruff)
+	psImageMap *map = psImageMapAlloc (NULL, binning, stats);
+
+	// fit the data to the map
+	psImageMapFit (map, NULL, 0, x, y, f, NULL);
+
+	psImage *model = psImageAlloc(field->numCols, field->numRows, PS_TYPE_F32);
+	for (int ix = 0; ix < model->numCols; ix++) {
+	    for (int iy = 0; iy < model->numRows; iy++) {
+		model->data.F32[iy][ix] = psImageUnbinPixel_V2 (ix + 0.5, iy + 0.5, map->map, map->binning);
+		is_float_tol (model->data.F32[iy][ix], field->data.F32[iy][ix], FLT_EPSILON, "model matches inputs");
+	    }
+	}
+
+	// SaveImage (NULL, map->map, "map.fits");
+	// SaveImage (NULL, field, "field.fits");
+	// SaveImage (NULL, model, "model.fits");
+
+	psFree (model);
+	psFree (binning);
+	psFree (map);
+	psFree (stats);
+	psFree (field);
+	psFree (x);
+	psFree (y);
+	psFree (f);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    # endif
+
+    // more complex test: 2x2 grid fitted to 16 points with simple slope offset from grid centers
+    // this one uses points inset relative to the reference points so they are all visible
+    // to the reference
+    # if (TEST_4PT_3)
+    {
+	// function is defined over the range 0-1000, 0-1000
+        psMemId id = psMemGetId();
+
+	psImageBinning *binning = psImageBinningAlloc();
+	binning->nXfine = 4;
+	binning->nYfine = 4;
+	binning->nXruff = 2;
+	binning->nYruff = 2;
+
+	// generate a grid of test data points
+	psVector *x = psVectorAlloc (16, PS_TYPE_F32);
+	psVector *y = psVectorAlloc (16, PS_TYPE_F32);
+	psVector *f = psVectorAlloc (16, PS_TYPE_F32);
+
+	int n = 0;
+	// actual field is f = x + y, where x & y are the subpixel positions
+	for (float ix = 0.5; ix < 4; ix += 1.0) {
+	    for (float iy = 0.5; iy < 4; iy += 1.0) {
+		x->data.F32[n] = ix;
+		y->data.F32[n] = iy;
+		f->data.F32[n] = x->data.F32[n] + y->data.F32[n];
+		n++;
+	    }
+	}
+
+	psImage *field = psImageAlloc(4, 4, PS_TYPE_F32);
+	for (int ix = 0; ix < 4; ix++) {
+	    for (int iy = 0; iy < 4; iy++) {
+		field->data.F32[iy][ix] = (ix + 0.5) + (iy + 0.5);
+	    }
+	}
+
+	psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+
+	// scale defines both field and map image sizes (nXfine, nXruff)
+	psImageMap *map = psImageMapAlloc (NULL, binning, stats);
+
+	// fit the data to the map
+	psImageMapFit (map, NULL, 0, x, y, f, NULL);
+
+	psImage *model = psImageAlloc(field->numCols, field->numRows, PS_TYPE_F32);
+	for (int ix = 0; ix < model->numCols; ix++) {
+	    for (int iy = 0; iy < model->numRows; iy++) {
+		model->data.F32[iy][ix] = psImageUnbinPixel_V2 (ix + 0.5, iy + 0.5, map->map, map->binning);
+		is_float_tol (model->data.F32[iy][ix], field->data.F32[iy][ix], 10*FLT_EPSILON, "model matches inputs");
+	    }
+	}
+
+	// SaveImage (NULL, map->map, "map.fits");
+	// SaveImage (NULL, field, "field.fits");
+	// SaveImage (NULL, model, "model.fits");
+
+	psFree (model);
+	psFree (binning);
+	psFree (map);
+	psFree (stats);
+	psFree (field);
+	psFree (x);
+	psFree (y);
+	psFree (f);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    # endif
+
+    // more complex test: 2x2 grid fitted to 4 points with simple slope offset from grid centers
+    // this one uses points inset relative to the reference points so they are all visible
+    // to the reference
+    # if (TEST_4PT_2)
+    {
+	// function is defined over the range 0-1000, 0-1000
+        psMemId id = psMemGetId();
+
+	psImageBinning *binning = psImageBinningAlloc();
+	binning->nXfine = 2;
+	binning->nYfine = 2;
+	binning->nXruff = 2;
+	binning->nYruff = 2;
+
+	// generate a grid of test data points
+	psVector *x = psVectorAlloc (5, PS_TYPE_F32);
+	psVector *y = psVectorAlloc (5, PS_TYPE_F32);
+	psVector *f = psVectorAlloc (5, PS_TYPE_F32);
+
+	int n = 0;
+	psImage *field = psImageAlloc(2, 2, PS_TYPE_F32);
+	// actual field is f = x + y, where x & y are the subpixel positions
+	for (int ix = 0; ix < 2; ix++) {
+	    for (int iy = 0; iy < 2; iy++) {
+		# if (1)
+		if (!ix && !iy) {
+		    x->data.F32[n] = ix + 0.5 - 0.1;
+		    y->data.F32[n] = iy + 0.5 - 0.0;
+// 		    f->data.F32[n] = x->data.F32[n] + y->data.F32[n];
+// 		    n++;
+// 		    x->data.F32[n] = ix + 0.5;
+//		    y->data.F32[n] = iy + 0.5 - 0.1;
+		} else {
+		    x->data.F32[n] = ix + 0.5;
+		    y->data.F32[n] = iy + 0.5;
+		}
+		# endif
+		# if (0)
+		// offset points from centers
+		if (ix) {
+		    x->data.F32[n] = ix + 0.5 - 0.1;
+		} else {
+		    x->data.F32[n] = ix + 0.5 + 0.1;
+		}
+		if (iy) {
+		    y->data.F32[n] = iy + 0.5 - 0.1;
+		} else {
+		    y->data.F32[n] = iy + 0.5 + 0.1;
+		}
+		# endif
+		f->data.F32[n] = x->data.F32[n] + y->data.F32[n];
+		field->data.F32[iy][ix] = ix + 0.5 + iy + 0.5;
+		n++;
+	    }
+	}
+	x->n = n;
+	y->n = n;
+	f->n = n;
+
+	psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+
+	// scale defines both field and map image sizes (nXfine, nXruff)
+	psImageMap *map = psImageMapAlloc (NULL, binning, stats);
+
+	// fit the data to the map
+	psImageMapFit (map, NULL, 0, x, y, f, NULL);
+
+	psImage *model = psImageAlloc(field->numCols, field->numRows, PS_TYPE_F32);
+	for (int ix = 0; ix < model->numCols; ix++) {
+	    for (int iy = 0; iy < model->numRows; iy++) {
+		model->data.F32[iy][ix] = psImageUnbinPixel_V2 (ix + 0.5, iy + 0.5, map->map, map->binning);
+		is_float_tol (model->data.F32[iy][ix], field->data.F32[iy][ix], 5*FLT_EPSILON, "model matches inputs");
+	    }
+	}
+
+	// SaveImage (NULL, map->map, "map.fits");
+	// SaveImage (NULL, field, "field.fits");
+	// SaveImage (NULL, model, "model.fits");
+
+	psFree (model);
+	psFree (binning);
+	psFree (map);
+	psFree (stats);
+	psFree (field);
+	psFree (x);
+	psFree (y);
+	psFree (f);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    # endif
+
+    // still a simple test: 2x2 grid fitted to 4 points with simple slope and scale difference
+    # if (TEST_4PT_1)
+    {
+	// function is defined over the range 0-1000, 0-1000
+        psMemId id = psMemGetId();
+
+	psImageBinning *binning = psImageBinningAlloc();
+	binning->nXfine = 4;
+	binning->nYfine = 4;
+	binning->nXruff = 2;
+	binning->nYruff = 2;
+
+	// generate a grid of test data points
+	psVector *x = psVectorAlloc (4, PS_TYPE_F32);
+	psVector *y = psVectorAlloc (4, PS_TYPE_F32);
+	psVector *f = psVectorAlloc (4, PS_TYPE_F32);
+
+	// the underlying field is f = ix + iy, where ix,iy are fine pixel coordinates
+	int n = 0;
+	for (int ix = 1; ix < 4; ix += 2) {
+	    for (int iy = 1; iy < 4; iy += 2) {
+		x->data.F32[n] = ix;
+		y->data.F32[n] = iy;
+		f->data.F32[n] = x->data.F32[n] + y->data.F32[n];
+		n++;
+	    }
+	}
+
+	psImage *field = psImageAlloc(4, 4, PS_TYPE_F32);
+	for (int ix = 0; ix < 4; ix++) {
+	    for (int iy = 0; iy < 4; iy++) {
+		field->data.F32[iy][ix] = (ix + 0.5) + (iy + 0.5);
+	    }
+	}
+
+	psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+
+	// scale defines both field and map image sizes (nXfine, nXruff)
+	psImageMap *map = psImageMapAlloc (NULL, binning, stats);
+
+	// fit the data to the map
+	psImageMapFit (map, NULL, 0, x, y, f, NULL);
+
+	psImage *model = psImageAlloc(field->numCols, field->numRows, PS_TYPE_F32);
+	for (int ix = 0; ix < model->numCols; ix++) {
+	    for (int iy = 0; iy < model->numRows; iy++) {
+		model->data.F32[iy][ix] = psImageUnbinPixel_V2 (ix + 0.5, iy + 0.5, map->map, map->binning);
+		is_float_tol (model->data.F32[iy][ix], field->data.F32[iy][ix], FLT_EPSILON, "model matches inputs");
+	    }
+	}
+
+	// SaveImage (NULL, map->map, "map.fits");
+	// SaveImage (NULL, field, "field.fits");
+	// SaveImage (NULL, model, "model.fits");
+
+	psFree (model);
+	psFree (binning);
+	psFree (map);
+	psFree (stats);
+	psFree (field);
+	psFree (x);
+	psFree (y);
+	psFree (f);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    # endif
+
+    // simplest possible test: 2x2 grid fitted to 4 points with simple slope
+    # if (TEST_4PT_0)
+    {
+	// function is defined over the range 0-1000, 0-1000
+        psMemId id = psMemGetId();
+
+	psImageBinning *binning = psImageBinningAlloc();
+	binning->nXfine = 2;
+	binning->nYfine = 2;
+	binning->nXruff = 2;
+	binning->nYruff = 2;
+
+	// generate a grid of test data points
+	psVector *x = psVectorAlloc (4, PS_TYPE_F32);
+	psVector *y = psVectorAlloc (4, PS_TYPE_F32);
+	psVector *f = psVectorAlloc (4, PS_TYPE_F32);
+
+	int n = 0;
+	psImage *field = psImageAlloc(2, 2, PS_TYPE_F32);
+	for (int ix = 0; ix < 2; ix++) {
+	    for (int iy = 0; iy < 2; iy++) {
+		x->data.F32[n] = ix + 0.5;
+		y->data.F32[n] = iy + 0.5;
+		f->data.F32[n] = x->data.F32[n] + y->data.F32[n];
+		field->data.F32[iy][ix] = f->data.F32[n];
+		n++;
+	    }
+	}
+
+	psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+
+	// scale defines both field and map image sizes (nXfine, nXruff)
+	psImageMap *map = psImageMapAlloc (NULL, binning, stats);
+
+	// fit the data to the map
+	psImageMapFit (map, NULL, 0, x, y, f, NULL);
+
+	psImage *model = psImageAlloc(field->numCols, field->numRows, PS_TYPE_F32);
+	for (int ix = 0; ix < model->numCols; ix++) {
+	    for (int iy = 0; iy < model->numRows; iy++) {
+		model->data.F32[iy][ix] = psImageUnbinPixel_V2 (ix + 0.5, iy + 0.5, map->map, map->binning);
+		is_float_tol (model->data.F32[iy][ix], field->data.F32[iy][ix], FLT_EPSILON, "model matches inputs");
+	    }
+	}
+
+	// SaveImage (NULL, map->map, "map.fits");
+	// SaveImage (NULL, field, "field.fits");
+	// SaveImage (NULL, model, "model.fits");
+
+	psFree (model);
+	psFree (binning);
+	psFree (map);
+	psFree (stats);
+	psFree (field);
+	psFree (x);
+	psFree (y);
+	psFree (f);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    # endif
+
+    return exit_status();
+}   
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageMapFit2.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageMapFit2.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageMapFit2.c	(revision 22158)
@@ -0,0 +1,257 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+int SaveImage (psMetadata *header, psImage *image, char *filename) {
+
+    psFits *fits = psFitsOpen (filename, "w");
+    psFitsWriteImage (fits, NULL, image, 0, NULL);
+    psFitsClose (fits);
+    return (TRUE);
+}
+
+# define TEST1 0
+# define TEST2 1
+# define TEST3 0
+
+# define C00 +0.0
+# define C01 -2.0
+# define C10 +1.0
+
+int main (void)
+{
+
+    plan_tests(1);
+
+    // make a model for a well-sampled field of a simple function (f = ax + by + c)
+    # if (TEST1)
+    {
+        psMemId id = psMemGetId();
+
+	// function is defined over the range 0-1000, 0-1000
+	psImageBinning *binning = psImageBinningAlloc();
+	binning->nXfine = 1000;
+	binning->nYfine = 1000;
+	binning->nXruff = 10;
+	binning->nYruff = 10;
+
+	// generate a grid of test data points
+	psVector *x = psVectorAllocEmpty (100, PS_TYPE_F32);
+	psVector *y = psVectorAllocEmpty (100, PS_TYPE_F32);
+	psVector *f = psVectorAllocEmpty (100, PS_TYPE_F32);
+
+	for (int ix = 0; ix < 1000; ix += 20) {
+	    for (int iy = 0; iy < 1000; iy += 20) {
+		x->data.F32[x->n] = ix;
+		y->data.F32[y->n] = iy;
+		f->data.F32[f->n] = C00 + C10*ix + C01*iy;
+		psVectorExtend (x, 100, 1);
+		psVectorExtend (y, 100, 1);
+		psVectorExtend (f, 100, 1);
+	    }
+	}
+
+	psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+
+	// scale defines both field and map image sizes (nXfine, nXruff)
+	psImageMap *map = psImageMapAlloc (NULL, binning, stats);
+
+	// fit the data to the map
+	psImageMapFit (map, x, y, f, NULL);
+
+	psImage *field = psImageAlloc(1000, 1000, PS_TYPE_F32);
+	for (int ix = 0; ix < 1000; ix++) {
+	    for (int iy = 0; iy < 1000; iy++) {
+		field->data.F32[iy][ix] = C00 + C10*ix + C01*iy;
+	    }
+	}
+
+	// measure difference between model (map) and data (field)
+	for (int ix = 0; ix < map->map->numCols; ix++) {
+	    for (int iy = 0; iy < map->map->numRows; iy++) {
+		int xo = psImageBinningGetFineX(map->binning, ix + 0.5);
+		int yo = psImageBinningGetFineY(map->binning, iy + 0.5);
+		is_float_tol (field->data.F32[yo][xo], map->map->data.F32[iy][ix], 1e-3, "model matches data");
+	    }
+	}
+
+	// XXX test on the model or don't bother
+	psImage *model = psImageAlloc(1000, 1000, PS_TYPE_F32);
+	for (int ix = 0; ix < 1000; ix++) {
+	    for (int iy = 0; iy < 1000; iy++) {
+		model->data.F32[iy][ix] = psImageUnbinPixel_V2 (ix + 0.5, iy + 0.5, map->map, map->binning);
+	    }
+	}
+
+	// SaveImage (NULL, model, "model.fits");
+	// SaveImage (NULL, field, "field.fits");
+	// SaveImage (NULL, map->map, "map.fits");
+	
+	psFree (model);
+	psFree (binning);
+	psFree (map);
+	psFree (stats);
+	psFree (field);
+	psFree (x);
+	psFree (y);
+	psFree (f);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    # endif
+
+    // make a model for a poorly-sampled field of a simple function (f = ax + by + c)
+
+    // choose a model scale for a poorly-sampled field of a simple function (f = ax + by + c)
+
+    // make a model for a well-sampled field of a high-order polynomial function (f = (a(x-xo)^2 + b(y-yo)^2) + c)
+    # if (TEST2)
+    {
+	// function is defined over the range 0-1000, 0-1000
+	psImageBinning *binning = psImageBinningAlloc();
+	binning->nXfine = 1000;
+	binning->nYfine = 1000;
+	binning->nXruff = 5;
+	binning->nYruff = 5;
+
+	// generate a grid of test data points
+	psVector *x = psVectorAllocEmpty (100, PS_TYPE_F32);
+	psVector *y = psVectorAllocEmpty (100, PS_TYPE_F32);
+	psVector *f = psVectorAllocEmpty (100, PS_TYPE_F32);
+
+	for (int ix = 0; ix < 1000; ix += 20) {
+	    for (int iy = 0; iy < 1000; iy += 20) {
+		x->data.F32[x->n] = ix + 0,5;
+		y->data.F32[y->n] = iy + 0.5;
+		f->data.F32[f->n] = PS_SQR(x->data.F32[x->n]) + PS_SQR(y->data.F32[x->n]);
+		psVectorExtend (x, 100, 1);
+		psVectorExtend (y, 100, 1);
+		psVectorExtend (f, 100, 1);
+	    }
+	}
+
+	psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+
+	// scale defines both field and map image sizes (nXfine, nXruff)
+	psImageMap *map = psImageMapAlloc (NULL, binning, stats);
+
+	// allocate a map, but we have no field image to supply
+	// XXX this function needs to correct for the mean superpixel position 
+	// which is sampled...
+	psImageMapFit (map, NULL, 0, x, y, f, NULL);
+	psFree (binning);
+
+	SaveImage (NULL, map->map, "map.fits");
+	
+	psImage *field = psImageAlloc(1000, 1000, PS_TYPE_F32);
+	for (int ix = 0; ix < 1000; ix++) {
+	    for (int iy = 0; iy < 1000; iy++) {
+		field->data.F32[iy][ix] = PS_SQR(ix+0.5) + PS_SQR(iy+0.5);
+	    }
+	}
+	SaveImage (NULL, field, "field.fits");
+
+	// measure difference between model (map) and data (field)
+	for (int ix = 0; ix < map->map->numCols; ix++) {
+	    for (int iy = 0; iy < map->map->numRows; iy++) {
+		int xo = psImageBinningGetFineX(map->binning, ix + 0.5);
+		int yo = psImageBinningGetFineY(map->binning, iy + 0.5);
+		float df = field->data.F32[yo][xo] - map->map->data.F32[iy][ix];
+		fprintf (stderr, "%d %d -> %d %d  :  %f = %f - %f\n", ix, iy, xo, yo, df, field->data.F32[yo][xo], map->map->data.F32[iy][ix]);
+	    }
+	}
+
+	// XXX test on the model or don't bother
+	psImage *model = psImageAlloc(1000, 1000, PS_TYPE_F32);
+	for (int ix = 0; ix < 1000; ix++) {
+	    for (int iy = 0; iy < 1000; iy++) {
+		model->data.F32[iy][ix] = psImageUnbinPixel_V2 (ix + 0.5, iy + 0.5, map->map, map->binning);
+	    }
+	}
+	SaveImage (NULL, model, "model.fits");
+    }
+    # endif
+
+    // make a model for a well-sampled field of a high-order polynomial function (f = (a(x-xo)^2 + b(y-yo)^2) + c)
+    # if (TEST3)
+    {
+	// function is defined over the range 0-1000, 0-1000
+	psImageBinning *binning = psImageBinningAlloc();
+	binning->nXfine = 1000;
+	binning->nYfine = 1000;
+	binning->nXruff = 5;
+	binning->nYruff = 5;
+
+	// generate a grid of test data points
+	psVector *x = psVectorAllocEmpty (100, PS_TYPE_F32);
+	psVector *y = psVectorAllocEmpty (100, PS_TYPE_F32);
+	psVector *f = psVectorAllocEmpty (100, PS_TYPE_F32);
+
+	for (int ix = 0; ix < 1000; ix += 20) {
+	    for (int iy = 0; iy < 1000; iy += 20) {
+		x->data.F32[x->n] = ix;
+		y->data.F32[y->n] = iy;
+		f->data.F32[f->n] = C10*(ix-500) + PS_SQR(C01*(iy-500));
+		psVectorExtend (x, 100, 1);
+		psVectorExtend (y, 100, 1);
+		psVectorExtend (f, 100, 1);
+	    }
+	}
+
+	psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+
+	// scale defines both field and map image sizes (nXfine, nXruff)
+	psImageMap *map = psImageMapAlloc (NULL, binning, stats);
+
+	// allocate a map, but we have no field image to supply
+	// XXX this function needs to correct for the mean superpixel position 
+	// which is sampled...
+	psImageMapGenerate (map, x, y, f, 0.1);
+	psFree (binning);
+
+	fprintf (stderr, "nGood: %d\n", map->nGood);
+	fprintf (stderr, "nPoor: %d\n", map->nPoor);
+	fprintf (stderr, "nBad:  %d\n", map->nBad);
+	
+	SaveImage (NULL, map->map, "map.fits");
+	
+	psImage *field = psImageAlloc(1000, 1000, PS_TYPE_F32);
+	for (int ix = 0; ix < 1000; ix++) {
+	    for (int iy = 0; iy < 1000; iy++) {
+		field->data.F32[iy][ix] = C10*(ix-500) + PS_SQR(C01*(iy-500));
+	    }
+	}
+	SaveImage (NULL, field, "field.fits");
+
+	// measure difference between model (map) and data (field)
+	for (int ix = 0; ix < map->map->numCols; ix++) {
+	    for (int iy = 0; iy < map->map->numRows; iy++) {
+		int xo = psImageBinningGetFineX(map->binning, ix + 0.5);
+		int yo = psImageBinningGetFineY(map->binning, iy + 0.5);
+		float df = field->data.F32[yo][xo] - map->map->data.F32[iy][ix];
+		fprintf (stderr, "%d %d -> %d %d  :  %f = %f - %f\n", ix, iy, xo, yo, df, field->data.F32[yo][xo], map->map->data.F32[iy][ix]);
+	    }
+	}
+
+
+	psImage *model = psImageAlloc(1000, 1000, PS_TYPE_F32);
+	for (int ix = 0; ix < 1000; ix++) {
+	    for (int iy = 0; iy < 1000; iy++) {
+		// XXX the binned coordinates are probably off by 0.5 pix, or we are interpolating 
+		// to the wrong binned coordinate.  
+		// XXX fix edge cases
+		model->data.F32[iy][ix] = psImageUnbinPixel_V2 (ix + 0.5, iy + 0.5, map->map, map->binning);
+	    }
+	}
+	SaveImage (NULL, model, "model.fits");
+    }
+    # endif
+
+    // make a model for a poorly-sampled field of a non-polynomial function (f = (a(x-xo)^2 + b(y-yo)^2)^-1)
+
+    // choose a model scale for a poorly-sampled field of a non-polynomial function (f = (a(x-xo)^2 + b(y-yo)^2)^-1)
+    
+    return exit_status();
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageMaskOps.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageMaskOps.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageMaskOps.c	(revision 22158)
@@ -0,0 +1,741 @@
+/** @file  tst_psImageMaskOps.c
+ *
+ *  @brief Contains the tests for psMaskOps.[ch]
+ *
+ *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-05-02 04:14:33 $
+ *
+ *  XXX: In general, the image tests with (1, N) and (N, 1) failed and have
+ *  been excluded.
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#define N 20
+#define MASK_VAL 10
+#define GROW_SIZE 5
+#define GROW_VAL 15
+
+bool genericImageGrowMaskTest(int rows, int cols, int maskVal, int growSize, int growVal)
+{
+    // Try with legitimate data
+    // XXX: psImageGrowMask() is currently growing a circular mask when the SCD
+    // specs a square mask.
+    {
+        psMemId id = psMemGetId();
+        psImage *in = psImageAlloc(rows, cols, PS_TYPE_MASK);
+        psImage *inout = psImageAlloc(rows, cols, PS_TYPE_MASK);
+        for (int i = 0 ; i < rows ; i++) {
+            for (int j = 0 ; j < cols ; j++) {
+                in->data.PS_TYPE_MASK_DATA[i][j] = 0;
+            }
+        }
+        in->data.PS_TYPE_MASK_DATA[N/2][N/2] = maskVal;
+        psImage *out = psImageGrowMask(NULL, in, maskVal, growSize, growVal);
+        ok(out != NULL, "psImageGrowMask() returned non-NULL with legitimate data");
+        skip_start(out == NULL, 1, "Skipping tests because psImageGrowMask() returned NULL");
+        ok(out->type.type == PS_TYPE_MASK, "psImageGrowMask() returned correct type mask");
+        ok((out->numRows == in->numRows) && (out->numCols == in->numCols),
+          "psImageGrowMask() returned correct size mask");
+        bool errorFlag = false;
+        for (int i = 0 ; i < rows ; i++) {
+            for (int j = 0 ; j < cols ; j++) {
+                if (((rows/2-i)*(rows/2-i)+(cols/2-j)*(cols/2-j)) <= (growSize*growSize)) {
+                    if (out->data.PS_TYPE_MASK_DATA[i][j] != growVal) {
+                        diag("out[%d][%d] is incorrect (%d)", i, j, out->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                } else {
+                    if (out->data.PS_TYPE_MASK_DATA[i][j] != 0) {
+                        diag("out[%d][%d] is incorrect (%d)", i, j, out->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+        ok(!errorFlag, "psImageGrowMask() produced the correct data values");
+        skip_end();
+        psFree(in);
+        psFree(out);
+        psFree(inout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    return true;
+}
+
+bool testInRegion(psRegion region, int row, int col)
+{
+    return(row >= region.y0 && row <= region.y1 && col >= region.x0 && col <= region.x1);
+}
+
+
+bool genericImageMaskRegionTest(int numRows, int numCols)
+{
+    psMemId id = psMemGetId();
+    psMaskType maskVal = 1;
+    psRegion reg;
+    reg.x0 = numCols/4;
+    reg.x1 = 3 * numCols/4;
+    reg.y0 = numRows/4;
+    reg.y1 = 3 * numRows/4;
+    psImage *img = psImageAlloc(numRows, numCols, PS_TYPE_MASK);
+
+    psBool errorFlag = false;
+    // psImageMaskRegion(): logical or
+    {
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                img->data.PS_TYPE_MASK_DATA[i][j] = 0;
+            }
+        }
+        psImageMaskRegion(img, reg, "|", maskVal);
+        errorFlag = false;
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                if (testInRegion(reg, i, j)) {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != maskVal) {
+                        diag("ERROR: img[%d][%d] is %d, should be %d", i, j, img->data.PS_TYPE_MASK_DATA[i][j], maskVal);
+                        errorFlag = true;
+                    }
+                } else {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+    }
+    ok(!errorFlag, "psImageMaskRegion() produced the correct results for logical or");
+
+    // psImageMaskRegion(): logical or
+    {
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                img->data.PS_TYPE_MASK_DATA[i][j] = 0;
+            }
+        }
+        psImageMaskRegion(img, reg, "=", maskVal);
+        psBool errorFlag = false;
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                if (testInRegion(reg, i, j)) {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != maskVal) {
+                        diag("ERROR: img[%d][%d] is %d, should be %d", i, j, img->data.PS_TYPE_MASK_DATA[i][j], maskVal);
+                        errorFlag = true;
+                    }
+                } else {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+    }
+    ok(!errorFlag, "psImageMaskRegion() produced the correct results for =");
+
+    // psImageMaskRegion(): logical and
+    {
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                img->data.PS_TYPE_MASK_DATA[i][j] = 0xff;
+            }
+        }
+        maskVal = 0xf;
+        psImageMaskRegion(img, reg, "&", maskVal);
+        psBool errorFlag = false;
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                if (testInRegion(reg, i, j)) {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != maskVal) {
+                        diag("ERROR: img[%d][%d] is %d, should be %d", i, j, img->data.PS_TYPE_MASK_DATA[i][j], maskVal);
+                        errorFlag = true;
+                    }
+                } else {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0xff) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0xff", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+    }
+    ok(!errorFlag, "psImageMaskRegion() produced the correct results for logical and");
+
+    // psImageMaskRegion(): logical and
+    {
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                img->data.PS_TYPE_MASK_DATA[i][j] = 0xff;
+            }
+        }
+        maskVal = 0xf;
+        psImageMaskRegion(img, reg, "^", maskVal);
+        psBool errorFlag = false;
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                if (testInRegion(reg, i, j)) {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0xf0) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0xf0", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                } else {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0xff) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0xff", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+    }
+    ok(!errorFlag, "psImageMaskRegion() produced the correct results for logical xor");
+
+    psFree(img);
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    return(true);
+}
+
+
+
+bool genericImageKeepRegionTest(int numRows, int numCols)
+{
+    psMemId id = psMemGetId();
+    psMaskType maskVal = 1;
+    psRegion reg;
+    reg.x0 = numCols/4;
+    reg.x1 = 3 * numCols/4;
+    reg.y0 = numRows/4;
+    reg.y1 = 3 * numRows/4;
+    psImage *img = psImageAlloc(numRows, numCols, PS_TYPE_MASK);
+
+    psBool errorFlag = false;
+    // psImageKeepRegion(): logical or
+    {
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                img->data.PS_TYPE_MASK_DATA[i][j] = 0;
+            }
+        }
+        psImageKeepRegion(img, reg, "|", maskVal);
+        errorFlag = false;
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                if (!testInRegion(reg, i, j)) {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != maskVal) {
+                        diag("ERROR: img[%d][%d] is %d, should be %d", i, j, img->data.PS_TYPE_MASK_DATA[i][j], maskVal);
+                        errorFlag = true;
+                    }
+                } else {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+    }
+    ok(!errorFlag, "psImageKeepRegion() produced the correct results for logical or");
+
+    // psImageKeepRegion(): logical or
+    {
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                img->data.PS_TYPE_MASK_DATA[i][j] = 0;
+            }
+        }
+        psImageKeepRegion(img, reg, "=", maskVal);
+        psBool errorFlag = false;
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                if (!testInRegion(reg, i, j)) {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != maskVal) {
+                        diag("ERROR: img[%d][%d] is %d, should be %d", i, j, img->data.PS_TYPE_MASK_DATA[i][j], maskVal);
+                        errorFlag = true;
+                    }
+                } else {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+    }
+    ok(!errorFlag, "psImageKeepRegion() produced the correct results for =");
+
+    // psImageKeepRegion(): logical and
+    {
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                img->data.PS_TYPE_MASK_DATA[i][j] = 0xff;
+            }
+        }
+        maskVal = 0xf;
+        psImageKeepRegion(img, reg, "&", maskVal);
+        psBool errorFlag = false;
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                if (!testInRegion(reg, i, j)) {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != maskVal) {
+                        diag("ERROR: img[%d][%d] is %d, should be %d", i, j, img->data.PS_TYPE_MASK_DATA[i][j], maskVal);
+                        errorFlag = true;
+                    }
+                } else {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0xff) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0xff", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+    }
+    ok(!errorFlag, "psImageKeepRegion() produced the correct results for logical and");
+
+    // psImageKeepRegion(): logical and
+    {
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                img->data.PS_TYPE_MASK_DATA[i][j] = 0xff;
+            }
+        }
+        maskVal = 0xf;
+        psImageKeepRegion(img, reg, "^", maskVal);
+        psBool errorFlag = false;
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                if (!testInRegion(reg, i, j)) {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0xf0) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0xf0", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                } else {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0xff) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0xff", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+    }
+    ok(!errorFlag, "psImageKeepRegion() produced the correct results for logical xor");
+
+    psFree(img);
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    return(true);
+}
+
+
+bool testInCircle(psImage *img, double xCenter, double yCenter, double radius, double xCoord, double yCoord)
+{
+    return((((xCoord+img->col0)-xCenter) * ((xCoord+img->col0)-xCenter) +
+             ((yCoord+img->row0) - yCenter) * ((yCoord+img->row0) - yCenter)) <= (radius * radius));
+}
+
+
+
+bool genericImageMaskCircleTest(int numRows, int numCols, int x, int y, int radius)
+{
+    psMemId id = psMemGetId();
+    psMaskType maskVal = 1;
+    psImage *img = psImageAlloc(numRows, numCols, PS_TYPE_MASK);
+
+    psBool errorFlag = false;
+    // psImageMaskCircle(): logical or
+    {
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                img->data.PS_TYPE_MASK_DATA[i][j] = 0;
+            }
+        }
+        psImageMaskCircle(img, (psF64) x, (psF64) y, (psF64) radius, "|", maskVal);
+        errorFlag = false;
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                if (testInCircle(img, (psF64) x, (psF64) y, (psF64) radius, (psF64) j, (psF64) i)) {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != maskVal) {
+                        diag("ERROR: img[%d][%d] is %d, should be %d", i, j, img->data.PS_TYPE_MASK_DATA[i][j], maskVal);
+                        errorFlag = true;
+                    }
+                } else {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+    }
+    ok(!errorFlag, "psImageMaskCircle() produced the correct results for logical or");
+
+    // psImageMaskCircle(): logical or
+    {
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                img->data.PS_TYPE_MASK_DATA[i][j] = 0;
+            }
+        }
+        psImageMaskCircle(img, (psF64) x, (psF64) y, (psF64) radius, "=", maskVal);
+        psBool errorFlag = false;
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                if (testInCircle(img, (psF64) x, (psF64) y, (psF64) radius, (psF64) j, (psF64) i)) {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != maskVal) {
+                        diag("ERROR: img[%d][%d] is %d, should be %d", i, j, img->data.PS_TYPE_MASK_DATA[i][j], maskVal);
+                        errorFlag = true;
+                    }
+                } else {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+    }
+    ok(!errorFlag, "psImageMaskCircle() produced the correct results for =");
+
+    // psImageMaskCircle(): logical and
+    {
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                img->data.PS_TYPE_MASK_DATA[i][j] = 0xff;
+            }
+        }
+        maskVal = 0xf;
+        psImageMaskCircle(img, (psF64) x, (psF64) y, (psF64) radius, "&", maskVal);
+        psBool errorFlag = false;
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                if (testInCircle(img, (psF64) x, (psF64) y, (psF64) radius, (psF64) j, (psF64) i)) {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != maskVal) {
+                        diag("ERROR: img[%d][%d] is %d, should be %d", i, j, img->data.PS_TYPE_MASK_DATA[i][j], maskVal);
+                        errorFlag = true;
+                    }
+                } else {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0xff) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0xff", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+    }
+    ok(!errorFlag, "psImageMaskCircle() produced the correct results for logical and");
+
+    // psImageMaskCircle(): logical and
+    {
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                img->data.PS_TYPE_MASK_DATA[i][j] = 0xff;
+            }
+        }
+        maskVal = 0xf;
+        psImageMaskCircle(img, (psF64) x, (psF64) y, (psF64) radius, "^", maskVal);
+        psBool errorFlag = false;
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                if (testInCircle(img, (psF64) x, (psF64) y, (psF64) radius, (psF64) j, (psF64) i)) {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0xf0) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0xf0", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                } else {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0xff) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0xff", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+    }
+    ok(!errorFlag, "psImageMaskCircle() produced the correct results for logical xor");
+
+    psFree(img);
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    return(true);
+}
+
+
+bool genericImageKeepCircleTest(int numRows, int numCols, int x, int y, int radius)
+{
+    psMemId id = psMemGetId();
+    psMaskType maskVal = 1;
+    psImage *img = psImageAlloc(numRows, numCols, PS_TYPE_MASK);
+
+    psBool errorFlag = false;
+    // psImageKeepCircle(): logical or
+    {
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                img->data.PS_TYPE_MASK_DATA[i][j] = 0;
+            }
+        }
+        psImageKeepCircle(img, (psF64) x, (psF64) y, (psF64) radius, "|", maskVal);
+        errorFlag = false;
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                if (!testInCircle(img, (psF64) x, (psF64) y, (psF64) radius, (psF64) j, (psF64) i)) {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != maskVal) {
+                        diag("ERROR: img[%d][%d] is %d, should be %d", i, j, img->data.PS_TYPE_MASK_DATA[i][j], maskVal);
+                        errorFlag = true;
+                    }
+                } else {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+    }
+    ok(!errorFlag, "psImageKeepCircle() produced the correct results for logical or");
+
+    // psImageKeepCircle(): logical or
+    {
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                img->data.PS_TYPE_MASK_DATA[i][j] = 0;
+            }
+        }
+        psImageKeepCircle(img, (psF64) x, (psF64) y, (psF64) radius, "=", maskVal);
+        psBool errorFlag = false;
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                if (!testInCircle(img, (psF64) x, (psF64) y, (psF64) radius, (psF64) j, (psF64) i)) {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != maskVal) {
+                        diag("ERROR: img[%d][%d] is %d, should be %d", i, j, img->data.PS_TYPE_MASK_DATA[i][j], maskVal);
+                        errorFlag = true;
+                    }
+                } else {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+    }
+    ok(!errorFlag, "psImageKeepCircle() produced the correct results for =");
+
+    // psImageKeepCircle(): logical and
+    {
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                img->data.PS_TYPE_MASK_DATA[i][j] = 0xff;
+            }
+        }
+        maskVal = 0xf;
+        psImageKeepCircle(img, (psF64) x, (psF64) y, (psF64) radius, "&", maskVal);
+        psBool errorFlag = false;
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                if (!testInCircle(img, (psF64) x, (psF64) y, (psF64) radius, (psF64) j, (psF64) i)) {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != maskVal) {
+                        diag("ERROR: img[%d][%d] is %d, should be %d", i, j, img->data.PS_TYPE_MASK_DATA[i][j], maskVal);
+                        errorFlag = true;
+                    }
+                } else {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0xff) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0xff", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+    }
+    ok(!errorFlag, "psImageKeepCircle() produced the correct results for logical and");
+
+    // psImageKeepCircle(): logical and
+    {
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                img->data.PS_TYPE_MASK_DATA[i][j] = 0xff;
+            }
+        }
+        maskVal = 0xf;
+        psImageKeepCircle(img, (psF64) x, (psF64) y, (psF64) radius, "^", maskVal);
+        psBool errorFlag = false;
+        for (int i = 0 ; i < numRows ; i++) {
+            for (int j = 0 ; j < numCols ; j++) {
+                if (!testInCircle(img, (psF64) x, (psF64) y, (psF64) radius, (psF64) j, (psF64) i)) {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0xf0) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0xf0", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                } else {
+                    if (img->data.PS_TYPE_MASK_DATA[i][j] != 0xff) {
+                        diag("ERROR: img[%d][%d] is %d, should be 0xff", i, j, img->data.PS_TYPE_MASK_DATA[i][j]);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+    }
+    ok(!errorFlag, "psImageKeepCircle() produced the correct results for logical xor");
+
+    psFree(img);
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    return(true);
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(47);
+
+    // psImageGrowMask()
+    //   *psImageGrowMask(psImage *out, const psImage *in,
+    //                    psMaskType maskVal, unsigned int growSize,
+    //                    psMaskType growVal)
+    // psImageGrowMask grows specified values on the input mask image, in,
+    // returning the result. If out is NULL, then a new image of the same type
+    // and dimension as in shall be allocated and returned; otherwise out shall
+    // be modified. If out is non-NULL and does not have the same size and type
+    // as in, the function shall generate an error and return NULL.  Pixels in
+    // the in image within growSize pixels (either horizontal or vertical) of a
+    // pixel which matches the maskVal shall have the corresponding pixel in the
+    // out image set to the growValue.
+
+    psMaskType maskVal = 0;
+    psMaskType growVal = 0;
+    unsigned int growSize = 0;
+
+    // return null for null input image
+    {
+        psMemId id = psMemGetId();
+        psImage *inout = psImageAlloc(N, N, PS_TYPE_MASK);
+        psImage *out = psImageGrowMask(inout, NULL, maskVal, growSize, growVal);
+        ok(out == NULL, "psImageGrowMask() returned NULL with NULL input image");
+        psFree(out);
+        psFree(inout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // return null for incompatible image size
+    {
+        psMemId id = psMemGetId();
+        psImage *in = psImageAlloc(5, 5, PS_TYPE_MASK);
+        psImage *inout = psImageAlloc(2, 2, PS_TYPE_MASK);
+        psImage *out = psImageGrowMask(inout, in, maskVal, growSize, growVal);
+        ok(out == NULL, "psImageGrowMask() returned NULL with incompatible image size");
+        psFree(in);
+        psFree(out);
+        psFree(inout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // return null for incompatible out image type
+    {
+        psMemId id = psMemGetId();
+        psImage *in = psImageAlloc(5, 5, PS_TYPE_MASK);
+        psImage *inout = psImageAlloc(5, 5, PS_TYPE_F32);
+        psImage *out = psImageGrowMask(inout, in, maskVal, growSize, growVal);
+        ok(out == NULL, "psImageGrowMask() returned NULL with incompatible out image type");
+        psFree(in);
+        psFree(out);
+        psFree(inout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // return NULL for input image that doesn't match PS_TYPE_MASK
+    {
+        psMemId id = psMemGetId();
+        psImage *in = psImageAlloc(5, 5, PS_TYPE_F32);
+        psImage *inout = psImageAlloc(5, 5, PS_TYPE_MASK);
+        psImage *out = psImageGrowMask(inout, in, maskVal, growSize, growVal);
+        ok(out == NULL, "psImageGrowMask() returned NULL with incompatible in image type");
+        psFree(in);
+        psFree(out);
+        psFree(inout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    // XXX: These tests fail
+    if (0) {
+        genericImageGrowMaskTest(N, 1, MASK_VAL, GROW_SIZE, GROW_VAL);
+    }
+    if (0) {
+        genericImageGrowMaskTest(1, N, MASK_VAL, GROW_SIZE, GROW_VAL);
+    }
+    // Try with grow region outside image
+    genericImageGrowMaskTest(N, N, MASK_VAL, N*2, GROW_VAL);
+    // Try with zero-size grow region
+    genericImageGrowMaskTest(N, N, MASK_VAL, 0, GROW_VAL);
+    // Try with sensible parameters
+    genericImageGrowMaskTest(N, N, MASK_VAL, GROW_SIZE, GROW_VAL);
+
+
+
+    // psImageMaskRegion
+    // Generate error NULL input image that doesn't match PS_TYPE_MASK
+    // XXX: Verify error
+    {
+        psMemId id = psMemGetId();
+        psRegion reg;
+        reg.x0 = 1;
+        reg.x1 = 2;
+        reg.y0 = 1;
+        reg.y1 = 2;
+        psMaskType maskVal = 2;
+        psImageMaskRegion(NULL, reg, "|", maskVal);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    if (0) genericImageMaskRegionTest(N, 1);
+    if (0) genericImageMaskRegionTest(1, N);
+    genericImageMaskRegionTest(N, N);
+
+
+    // psImageKeepRegion
+    // Generate error NULL input image that doesn't match PS_TYPE_MASK
+    // XXX: Verify error
+    {
+        psMemId id = psMemGetId();
+        psRegion reg;
+        reg.x0 = 1;
+        reg.x1 = 2;
+        reg.y0 = 1;
+        reg.y1 = 2;
+        psImageKeepRegion(NULL, reg, "|", 1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    if (0) genericImageKeepRegionTest(N, 1);
+    if (0) genericImageKeepRegionTest(1, N);
+    genericImageKeepRegionTest(N, N);
+
+
+    // psImageMaskCircle
+    // Generate error NULL input image that doesn't match PS_TYPE_MASK
+    // XXX: Verify error
+    {
+        psMemId id = psMemGetId();
+        psImageMaskCircle(NULL, 1.0, 2.0, 3.0, "|", 1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    // XXX: These seg fault
+    if (0) genericImageMaskCircleTest(N, 1, N/2, 1, N/4);
+    if (0) genericImageMaskCircleTest(1, N, 1, N/2, N/4);
+    genericImageMaskCircleTest(N, N, N/2, N/2, N/4);
+
+
+    // psImageKeepCircle
+    // Generate error NULL input image that doesn't match PS_TYPE_MASK
+    // XXX: Verify error
+    {
+        psMemId id = psMemGetId();
+        psImageKeepCircle(NULL, 1.0, 2.0, 3.0, "|", 1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    // XXX: These seg fault
+    if (0) genericImageKeepCircleTest(N, 1, N/2, 1, N/4);
+    if (0) genericImageKeepCircleTest(1, N, 1, N/2, N/4);
+    genericImageKeepCircleTest(N, N, N/2, N/2, N/4);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImagePixelExtract.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImagePixelExtract.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImagePixelExtract.c	(revision 22158)
@@ -0,0 +1,1254 @@
+/** @file  tst_psImageExtraction.c
+*
+*  @brief Contains the tests for psImageExtraction.[ch]
+*
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-06-04 20:25:32 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+void genericImageRowColTests(int numRows, int numCols)
+{
+    psMemId id = psMemGetId();
+    psImage *image = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    for (int i = 0 ; i < numRows; i++) {
+        for (int j = 0 ; j < numCols; j++) {
+            image->data.F32[0][0] = (float) i+j;
+        }
+    }            
+
+    bool errorFlag = false;
+    for (int i = 0 ; i < numRows; i++) {
+        psVector *out = psImageRow(NULL, image, i);
+        ok(out != NULL, "psImageRow returned non-NULL");
+        if (out != NULL) {
+            for (int j = 0 ; j < numCols; j++) {
+                if (out->data.F32[j] != image->data.F32[i][j]) {
+                    diag("TEST ERROR: image->data.F32[%d][%d] is %f, should be %f", i, j, 
+                         image->data.F32[i][j], out->data.F32[j]);
+                    errorFlag = true;
+                }
+            }
+            psFree(out);
+        } else {
+            errorFlag = true;
+        }
+    }
+    ok(!errorFlag, "psImageRow() passed tests with correct data inputs");
+    psFree(image);
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+}
+
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(295);
+
+    // test psImageSlice()
+    {
+        psMemId id = psMemGetId();
+        const psS32 r = 200;
+        const psS32 c = 300;
+        const psS32 m = r / 2 -1;
+        const psS32 n = r / 4 -1;
+        psImage* image;
+        psPixels* positions = psPixelsAlloc(r);
+        psImage* mask = psImageAlloc(c, r, PS_TYPE_MASK);
+        psStats* stat = psStatsAlloc(PS_STAT_SAMPLE_MEDIAN);
+    
+
+        // This function shall extract pixels from a specified region of a psImage
+        // structure into a vector using a specified statistical method.
+        //    
+        // Verify the returned psVector structure contains expected data, if the
+        // input psImage input has known data and the psStats structure specifies
+        // a known statistical method. At least two different statistical methods
+        // should be used within a valid range of psImage data. Allow for a delta
+        // when comparing results to allow for testing a different platforms. Two
+        // cases should be used for each possible direction. Data region cases
+        // should include 0x0, 1x1, Nx1, 1xN, NxN, MxN
+        for (psS32 row = 0;row < r;row++) {
+            psMaskType* maskRow = mask->data.PS_TYPE_MASK_DATA[row];
+            for (psS32 col = 0;col < c;col++) {
+                maskRow[col] = 0;
+            }
+        }
+    
+        #define PSIMAGESLICE_TEST1(TYPE,M,N,DIRECTION,TRUTH_SIZE,TRUTHPIX_X,TRUTHPIX_Y,TESTNUM) \
+        { \
+            psMemId id = psMemGetId(); \
+            psVector* out = NULL; \
+            bool errorFlag = false; \
+            image = psImageAlloc(c, r, PS_TYPE_##TYPE); \
+            for (psS32 row = 0;row < r;row++) { \
+                ps##TYPE *imageRow = image->data.TYPE[row]; \
+                ps##TYPE rowOffset = row * 2; \
+                for (psS32 col = 0;col < c;col++) { \
+                    imageRow[col] = col + rowOffset; \
+                } \
+            } \
+            P_PSIMAGE_SET_COL0(image, 1); \
+            P_PSIMAGE_SET_ROW0(image, 1); \
+            out = psImageSlice(out,positions,image,mask,1, \
+                               psRegionSet(1+c/10,1+c/10+M,1+r/10,1+r/10+N),DIRECTION,stat); \
+            \
+            if (out->n != TRUTH_SIZE) { \
+                diag("Number of results is wrong (%d, not %d)", \
+                      out->n,TRUTH_SIZE); \
+                errorFlag = true; \
+            } \
+            \
+            if (positions->n != TRUTH_SIZE) { \
+                diag("Number of results for positions vector is wrong (%d, not %d)", \
+                      positions->n,TRUTH_SIZE); \
+                errorFlag = true; \
+            } \
+            \
+            for (psS32 i=0;i<out->n;i++) { \
+                if (fabs(out->data.F64[i]-image->data.TYPE[r/10+TRUTHPIX_Y][c/10+TRUTHPIX_X]) > 1.0/(psF64)r) { \
+                    diag("Improper result at position %d.  Got %g, expected %g",i, \
+                          out->data.F64[i],image->data.TYPE[r/10+TRUTHPIX_Y][c/10+TRUTHPIX_X]); \
+                    errorFlag = true; \
+                } \
+                if (DIRECTION == PS_CUT_X_POS || DIRECTION == PS_CUT_X_NEG) { \
+                    if (positions->data[i].x != c/10+TRUTHPIX_X) { \
+                        diag("Improper positions (%d vs %d) result @ %d.", \
+                              positions->data[i].x,c/10+TRUTHPIX_X,i); \
+                        errorFlag = true; \
+                    } \
+                } else { \
+                    if (positions->data[i].y != r/10+TRUTHPIX_Y) { \
+                        diag("Improper positions (%d vs %d) result @ %d.", \
+                              positions->data[i].y,r/10+TRUTHPIX_Y,i); \
+                        errorFlag = true; \
+                    } \
+                } \
+            } \
+            ok(!errorFlag, "psImageSlice() produced correct data values (test number %d", TESTNUM); \
+            psFree(out); \
+            psFree(image); \
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); \
+        }
+    
+        //
+        #define PSIMAGESLICE_TEST(TYPE) \
+        PSIMAGESLICE_TEST1(TYPE, m, n, PS_CUT_X_POS, m, i, n / 2, 0); \
+        PSIMAGESLICE_TEST1(TYPE, m, n, PS_CUT_X_NEG, m, m - 1 - i, n / 2, 1); \
+        PSIMAGESLICE_TEST1(TYPE, m, n, PS_CUT_Y_POS, n, m / 2, i, 2); \
+        PSIMAGESLICE_TEST1(TYPE, m, n, PS_CUT_Y_NEG, n, m / 2, n - 1 - i, 3); \
+        \
+        PSIMAGESLICE_TEST1(TYPE, m, 1, PS_CUT_X_POS, m, i, 0, 4); \
+        PSIMAGESLICE_TEST1(TYPE, m, 1, PS_CUT_X_NEG, m, m - 1 - i, 0, 5); \
+        PSIMAGESLICE_TEST1(TYPE, m, 1, PS_CUT_Y_POS, 1, m / 2, 0, 6); \
+        PSIMAGESLICE_TEST1(TYPE, m, 1, PS_CUT_Y_NEG, 1, m / 2, 0, 7); \
+        \
+        PSIMAGESLICE_TEST1(TYPE, 1, n, PS_CUT_X_POS, 1, 0, n / 2, 8); \
+        PSIMAGESLICE_TEST1(TYPE, 1, n, PS_CUT_X_NEG, 1, 0, n / 2, 9); \
+        PSIMAGESLICE_TEST1(TYPE, 1, n, PS_CUT_Y_POS, n, 0, i, 10); \
+        PSIMAGESLICE_TEST1(TYPE, 1, n, PS_CUT_Y_NEG, n, 0, n - 1 - i, 11); \
+        \
+        PSIMAGESLICE_TEST1(TYPE, 1, 1, PS_CUT_X_POS, 1, 0, 0, 12); \
+        PSIMAGESLICE_TEST1(TYPE, 1, 1, PS_CUT_X_NEG, 1, 0, 0, 13); \
+        PSIMAGESLICE_TEST1(TYPE, 1, 1, PS_CUT_Y_POS, 1, 0, 0, 14); \
+        PSIMAGESLICE_TEST1(TYPE, 1, 1, PS_CUT_Y_NEG, 1, 0, 0, 15); \
+    
+        PSIMAGESLICE_TEST(F32);
+
+        PSIMAGESLICE_TEST(F64);
+        PSIMAGESLICE_TEST(U16);
+    
+        image = psImageAlloc(c, r, PS_TYPE_F32);
+        // Verify the returned psVector structure pointer is null and program
+        // execution doesn't stop, if input psImage input is null.
+        // Following should be an error
+        // XXX: Verify error
+
+
+        psVector *out = NULL;
+        out = psImageSlice(out,
+                           NULL, NULL,
+                           NULL, 0,
+                           psRegionSet(c/10, c/10 + 1, r/10, r/10 + 1),
+                           PS_CUT_X_POS,
+                           stat);
+        ok(out == NULL, "psImageSlice() returned NULL with NULL input");
+    
+        // Verify the returned psVector structure pointer is null and program
+        // execution doesn't stop, if input psStats stats is null.
+        // Following should be an error
+        // XXX: Verify error
+        out = psImageSlice(out,
+                            NULL, image,
+                            mask, 1,
+                            psRegionSet(c/10, c/10 + 1, r/10, r/10 + 1),
+                            PS_CUT_X_POS,
+                            NULL);
+        ok(out == NULL, "psImageSlice() returned NULL with NULL psStats");
+            psError(PS_ERR_UNKNOWN,true, "Giving a NULL stat struct, psImageSlice didn't return NULL as expected");
+
+        // Verify the returned psVector structure pointer is null and program
+        // executions doesn't stop, if the input direction is not set to one of
+        // the two valid values.
+        // Following should be an error
+        // XXX: Verify error
+        out = psImageSlice(out, NULL,
+                           image,
+                           mask, 1,
+                           psRegionSet(c/10, c/10 + 1, r/10, r/10 + 1),
+                           5,
+                           stat);
+        ok(out == NULL, "psImageSlice() returned NULL with bogus direction flag");
+
+        // Verify the returned psVector structure pointer is null and program
+        // execution doesn't stop, if the input nrow and/or ncol are zero.
+        // Following should be an error
+        // XXX: Verify error
+        out = psImageSlice(out,
+                            NULL,
+                            image,
+                            mask, 1,
+                            psRegionSet(c/10, c/10, r/10, r/10),
+                            PS_CUT_X_POS,
+                            stat);
+        ok(out == NULL, "psImageSlice() returned NULL with 0x0 region");
+    
+        // Verify the returned psVector structure pointer is null and program
+        // execution doesn't stop, if the inputs row, col, nrow, ncol specify a
+        // regions of data that is not within the input psImage structure.
+        // Following should be an error
+        // XXX: Verify error
+        out = psImageSlice(out, NULL,
+                            image,
+                            mask, 1,
+                            psRegionSet(c+1, c+2, r/10, r/10 + 10),
+                            PS_CUT_X_POS,
+                            stat);
+        ok(out == NULL, "psImageSlice() returned NULL with unallowed x position");
+    
+        // Following should be an error
+        // XXX: Verify error
+        out = psImageSlice(out, NULL,
+                            image,
+                            mask, 1,
+                            psRegionSet(c/10, c/10 + 1, r+1,r+5),
+                            PS_CUT_X_POS,
+                            stat);
+        ok(out == NULL, "psImageSlice() returned NULL with unallowed y position");
+    
+        // Following should be an error
+        // XXX: Verify error
+        out = psImageSlice(out, NULL,
+                            image,
+                            mask, 1,
+                            psRegionSet(c/10, c+1, r/10, r/10+1),
+                            PS_CUT_X_POS,
+                            stat);
+        ok(out == NULL, "psImageSlice() returned NULL with unallowed numCols");
+    
+        // Following should be an error
+        // XXX: Verify error
+        out = psImageSlice(out, NULL,
+                            image,
+                            mask, 1,
+                            psRegionSet(c/10, c/10 + 1, r/10, r + 1),
+                            PS_CUT_X_POS,
+                            stat);
+        ok(out == NULL, "psImageSlice() returned NULL with unallowed numRows");
+    
+        // Verify the returned psVector structure pointer is null and program
+        // execution doesn't stop, if the input psStat structure member options is
+        // zero which indicates no statistic method specified.
+        // Following should be an error
+        // XXX: Verify error
+        stat->options = 0;
+        out = psImageSlice(out, NULL,
+                            image,
+                            mask, 1,
+                            psRegionSet(c/10, c/10 + 1, r/10, r/10+1),
+                            PS_CUT_X_POS,
+                            stat);
+        ok(out == NULL, "psImageSlice() returned NULL with unallowed numRows");
+    
+        // Verify that a mask of different size than the input image returns null and program
+        // execution doesn't stop.
+        // Following should be an error mask size != image size
+        // XXX: Verify error
+        stat->options = PS_STAT_SAMPLE_MEDIAN;
+        psImage* maskSz = psImageAlloc(r, c, PS_TYPE_MASK);
+        out = psImageSlice(out, NULL,
+                            image,
+                            maskSz, 1,
+                            psRegionSet(c/10, c/10 + 1, r/10, r/10 + 1),
+                            PS_CUT_X_POS,
+                            stat);
+        ok(out == NULL, "psImageSlice() returned NULL with differing mask size and image size");
+    
+        // Verify the a unallowed type mask returns null and program execution doesn't stop.
+        // Following should be an error unallowed mask type
+        // XXX: Verify error
+        psImage* maskS8 = psImageAlloc(c, r, PS_TYPE_S8);
+        out =  psImageSlice(out, NULL,
+                             image,
+                             maskS8, 1,
+                             psRegionSet(c/10, c/10 + 1, r/10, r/10 + 1),
+                             PS_CUT_X_POS,
+                             stat);
+        ok(out == NULL, "psImageSlice() returned NULL with unallowed mask type");
+    
+        //Added tests after subimage changes.
+        psFree(image);
+        image = psImageAlloc(c, r, PS_TYPE_F64);
+        for (psS32 row = 0;row < r;row++) {
+            psF64 *imageRow = image->data.F64[row];
+            psF64 rowOffset = row * 2;
+            for (psS32 col = 0;col < c;col++) {
+                imageRow[col] = col + rowOffset;
+            }
+        }
+        P_PSIMAGE_SET_COL0(image, 1);
+        P_PSIMAGE_SET_ROW0(image, 1);
+        psFree(out);
+        out = NULL;
+        out = psImageSlice(out,positions,image,mask,1,
+                           psRegionSet(1,c,1,r),PS_CUT_X_POS,stat);
+        ok(out != NULL, "psImageSlice() with correct inputs");
+        psFree(out);
+        out = NULL;
+
+        //Return NULL for incorrect image inputs.
+        P_PSIMAGE_SET_ROW0(image, -1);
+        // Following should generate error message
+        // XXX: Verify error
+        out = psImageSlice(out,positions,image,mask,1,
+                           psRegionSet(1,c,1,r),PS_CUT_X_POS,stat);
+        ok(out == NULL, "psImageSlice returned NULL for unallowed specified input");
+
+        P_PSIMAGE_SET_COL0(image, -1);
+        P_PSIMAGE_SET_ROW0(image, 1);
+        // Following should generate error message
+        // XXX: Verify error
+        out = psImageSlice(out,positions,image,mask,1,
+                           psRegionSet(1,c,1,r),PS_CUT_X_POS,stat);
+        ok(out == NULL, "psImageSlice returned NULL for unallowed specified input");
+
+        P_PSIMAGE_SET_COL0(image, -1);
+        // Return NULL for incorrect region inputs.
+        // Following should generate error message
+        // XXX: Verify error
+        out = psImageSlice(out,positions,image,mask,1,
+                           psRegionSet(0,c,1,r),PS_CUT_X_POS,stat);
+        ok(out == NULL, "psImageSlice returned NULL for unallowed specified input");
+
+        // Following should generate error message
+        // XXX: Verify error
+        out = psImageSlice(out,positions,image,mask,1,
+                           psRegionSet(1,c,1,r+1),PS_CUT_X_POS,stat);
+        ok(out == NULL, "psImageSlice returned NULL for unallowed specified input");
+
+        // Following should generate error message
+        // XXX: Verify error
+        out = psImageSlice(out,positions,image,mask,1,
+                           psRegionSet(1,c,1,-r-2),PS_CUT_X_POS,stat);
+        ok(out == NULL, "psImageSlice returned NULL for unallowed specified input");
+
+        // Following should generate error message
+        // XXX: Verify error
+        out = psImageSlice(out,positions,image,mask,1,
+                           psRegionSet(c,1,1,r),PS_CUT_X_POS,stat);
+        ok(out == NULL, "psImageSlice returned NULL for unallowed specified input");
+
+
+        // Following should generate error message
+        // XXX: Verify error
+        out = psImageSlice(out,positions,image,mask,1,
+                           psRegionSet(1,1,1,1),PS_CUT_X_POS,stat);
+        ok(out == NULL, "psImageSlice returned NULL for unallowed specified input");
+
+    
+        //Make sure that regions match appropriately...
+        out = psImageSlice(out,positions,image,mask,1,
+                           psRegionSet(1,-1,1,-1),PS_CUT_Y_NEG,stat);
+        psVector *out2 = NULL;
+        out2 = psImageSlice(out2,positions,image,mask,1,
+                            psRegionSet(0,0,0,0),PS_CUT_Y_NEG,stat);
+        ok(out != NULL, "psImageSlice returned non-NULL for valid inputs");
+        ok(out2 != NULL, "psImageSlice returned non-NULL for valid inputs");
+        skip_start(out == NULL || out2 == NULL, 2, "Skipping tests because psImageSlice() returned NULL");
+        ok(out->n == out2->n, "psImageSlice returned matching vectors for equivalent inputs");
+        ok(out->data.F64[out->n-1] == out2->data.F64[out2->n-1], "psImageSlice returned matching vectors for equivalent inputs");
+        skip_end();
+        psFree(out2);
+        psFree(image);
+        psFree(positions);
+        psFree(mask);
+        psFree(out);
+        psFree(stat);
+        psFree(maskS8);
+        psFree(maskSz);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageCut()
+    {
+        psMemId id = psMemGetId();
+        psS32 c = 300;
+        psS32 r = 200;
+        psS32 numPoints = 15;
+        float startCol[] = { 40,150, 40,  0,280, 40,280, -1,300, 20, 20, 20, 20, 20, 20};
+        float endCol[] =   {240,150,240,299, 40,240, 40,240,240, -1,300,240,240,240,240};
+        float startRow[] = { 20, 10,100,  0, 20,180,180, 10, 10, 10, 10, -1,200, 10, 10};
+        float endRow[] =   {160,180,100,199,160, 10, 10,180,180,180,180,180,180, -1,200};
+        psBool success[] = {true,true,true,true,true,true,true,false,false,false,false,false,false,false,false};
+        psU32 length = 100;
+    
+        psImage* image = psImageAlloc(c,r,PS_TYPE_F32);
+        psImage* mask = psImageAlloc(c,r,PS_TYPE_MASK);
+        for (psS32 row = 0; row < image->numRows; row++) {
+            for (psS32 col = 0; col < image->numCols; col++) {
+                image->data.F32[row][col] = (psF32)col + (psF32)row/1000.0f;
+                if ((row & 0x0F) == 0) {
+                    mask->data.PS_TYPE_MASK_DATA[row][col] = 1;
+                } else {
+                    mask->data.PS_TYPE_MASK_DATA[row][col] = 0;
+                }
+            }
+        }
+        psVector* rows = psVectorAlloc(length,PS_TYPE_F32);
+        psVector* cols = psVectorAlloc(length,PS_TYPE_F32);
+    
+        psVector* result = psVectorAlloc(length,PS_TYPE_F32);
+        for (psS32 n = 0; n < numPoints; n++) {
+            psVector* orig = result;
+            if (! success[n]) {
+                // The following should be an error
+                // XXX: Verify error
+            }
+            if (n == 1) {
+                result = psImageCut(result,
+                                    cols,rows,
+                                    image,
+                                    NULL,0,
+                                    psRegionSet(startCol[n], endCol[n], startRow[n],endRow[n]),
+                                    length,
+                                    PS_INTERPOLATE_FLAT);
+            } else {
+                result = psImageCut(result,
+                                    cols,rows,
+                                    image,
+                                    mask,1,
+                                    psRegionSet(startCol[n], endCol[n], startRow[n], endRow[n]),
+                                    length,
+                                    PS_INTERPOLATE_FLAT);
+            }
+
+            bool errorFlag = false;    
+            if (success[n]) {
+                ok(result != NULL, "psImageCut returned non-NULL");
+                ok(orig != NULL, "orig image is non-NULL");
+                ok(orig == result, "psImageCut did recycle the out parameter properly");
+                psImageInterpolateOptions *tmpIntOptsNoMask = psImageInterpolateOptionsAlloc(
+                    PS_INTERPOLATE_FLAT, image, NULL, NULL, 0, 0, NAN, 0, 0, 0.0);
+                psImageInterpolateOptions *tmpIntOptsMask = psImageInterpolateOptionsAlloc(
+                    PS_INTERPOLATE_FLAT, image, NULL, NULL, 1, 0, NAN, 0, 0, 0.0);
+                double imgVal;
+                double varVal;
+                psMaskType maskVal;
+    
+                float deltaRow = (endRow[n]-startRow[n])/(length-1);
+                float deltaCol = (endCol[n]-startCol[n])/(length-1);
+                psF32 truth;
+                for (psS32 i = 0; i < length; i++) {
+                    float x = (float)startCol[n]+(float)i*deltaCol;
+                    float y = (float)startRow[n]+(float)i*deltaRow;
+                    if (n == 1) {
+//                        truth = psImagePixelInterpolate(image, x, y,
+//                                                         NULL,0,0,PS_INTERPOLATE_FLAT);
+                          psImageInterpolate(&imgVal, &varVal, &maskVal, x, y, tmpIntOptsNoMask);
+                          truth = imgVal;
+                    } else {
+//                        truth = psImagePixelInterpolate(image, x, y,
+//                                                         mask,1,0,PS_INTERPOLATE_FLAT);
+                          psImageInterpolate(&imgVal, &varVal, &maskVal, x, y, tmpIntOptsMask);
+                          truth = imgVal;
+                    }
+                    if (fabs(result->data.F32[i]-truth) > FLT_EPSILON) {
+                        diag("Bad result in position %d; Found %g but expected %g.",
+                              i, result->data.F32[i], truth);
+                        errorFlag = true;
+                    }
+                    if (fabsf(x - cols->data.F32[i]) > FLT_EPSILON ||
+                            fabsf(y - rows->data.F32[i]) > FLT_EPSILON) {
+                        diag("Bad resulting col/row at index %d; Found (%g,%g) but expected (%g,%g).",
+                              i, cols->data.F32[i], rows->data.F32[i], x, y);
+                        errorFlag = true;
+                    }
+                }
+                psFree(tmpIntOptsNoMask);
+                psFree(tmpIntOptsMask);
+            } else {
+                if (result != NULL) {
+                    diag("psImageCut did not return NULL with a cut of (%g,%g)->(%g,%g).",
+                          startCol[n],startRow[n],endCol[n],endRow[n]);
+                    errorFlag = true;
+                }
+                psErr* err = psErrorLast();
+                if (err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+                    diag("psImageCut did not generate proper error message.");
+                    errorFlag = true;
+                }
+                psFree(err);
+            }
+            ok(!errorFlag, "psImageCut() produced the correct data values");
+        }
+
+        // Following should be an error (NULL image)
+        // XXX: Verify error
+        result = psImageCut(result,
+                            cols,rows,
+                            NULL,
+                            mask,1,
+                            psRegionSet(startCol[0], endCol[0], startRow[0], endRow[0]),
+                            length,
+                            PS_INTERPOLATE_FLAT);
+        ok(result == NULL, "psImageCut did return NULL given NULL image");
+        psErr* err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_NULL, 
+          "psImageCut did generate proper error message given NULL image");
+        psFree(err);
+    
+        // Following should be an error (length=0)
+        // XXX: Verify error
+        result = psImageCut(result,
+                            cols,rows,
+                            image,
+                            mask,1,
+                            psRegionSet(startCol[0], endCol[0], startRow[0], endRow[0]),
+                            0,
+                            PS_INTERPOLATE_FLAT);
+        ok(result == NULL, "psImageCut did return NULL given length=0");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_VALUE,
+          "psImageCut did generate proper error message given length=0");
+        psFree(err);
+    
+        psFree(result);
+        psFree(image);
+        psFree(mask);
+        psFree(rows);
+        psFree(cols);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // test psImageRadialCut()
+    {
+        psMemId id = psMemGetId();
+        psS32 c = 300;
+        psS32 r = 200;
+        psS32 centerX = c/2;
+        psS32 centerY = r/2;
+        psErr* err = NULL;
+    
+        psImage* image = psImageAlloc(c,r,PS_TYPE_F32);
+        psImage* mask = psImageAlloc(c,r,PS_TYPE_MASK);
+        for (psS32 row = 0; row < image->numRows; row++) {
+            for (psS32 col = 0; col < image->numCols; col++) {
+                image->data.F32[row][col] = sqrtf((col-centerX)*(col-centerX)+(row-centerY)*(row-centerY));
+                if ((row & 0x0F) == 0) {
+                    mask->data.PS_TYPE_MASK_DATA[row][col] = 1;
+                } else {
+                    mask->data.PS_TYPE_MASK_DATA[row][col] = 0;
+                }
+            }
+        }
+    
+        psStats* stat = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        psVector* radii = psVectorAlloc(10,PS_TYPE_F32);
+        for (psS32 i=0; i < 10; i++) {
+            radii->data.F32[i] = 10+i*10;
+        }
+    
+        bool errorFlag = false;    
+        psVector* result = psVectorAlloc(10,PS_TYPE_F32);
+        if (1) {
+            result = psImageRadialCut(result,image,mask,1,centerX,centerY,radii,stat);
+            ok(result != NULL, "psImageRadialCut returned non-NULL");
+            ok(result->type.type == PS_TYPE_F64, "psImageRadialCut produced the correct type");
+            for (psS32 i=0; i < 9; i++) {
+                if (fabs(result->data.F64[i] - (15.0+i*10)) > 1) {
+                    diag("Result was not as expected for radii #%d (%g, expected %d +/- 1)",
+                          result->data.F64[i], (15.0+i*10));
+                    errorFlag = true;
+                }
+            }
+            ok(!errorFlag, "psImageRadialCut() produced the correct data values");
+        }    
+        // again, but without mask
+        psVector* orig = result;
+        if (1) {
+            result = psImageRadialCut(result,image,NULL,1,centerX,centerY,radii,stat);
+            ok(result != NULL, "psImageRadialCut returned non-NULL");
+            ok(result == orig, "psImageRadialCut recycle output parameter");
+    
+            errorFlag = false;    
+            for (psS32 i=0; i < 9; i++) {
+                if (fabs(result->data.F64[i] - (15.0+i*10)) > 1) {
+                    diag("Result was not as expected for radii #%d (%g, expected %d +/- 1)",
+                          result->data.F64[i], (15.0+i*10));
+                    errorFlag = true;
+                }
+            }
+            ok(!errorFlag, "psImageRadialCut() produced the correct data values");
+        }    
+
+    
+        // NULL input image...
+        // Following should be an error
+        // XXX: Verify error
+        result = psImageRadialCut(result,NULL,NULL,1,centerX,centerY,radii,stat);
+        ok(result == NULL, "psImageRadialCut returned NULL with NULL input");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_NULL, 
+          "psImageRadialCut did generate proper error message");
+        psFree(err);
+    
+
+        // NULL input radii...
+        // Following should be an error
+        // XXX: Verify error
+        result = psImageRadialCut(result,image,mask,1,centerX,centerY,NULL,stat);
+        ok(result == NULL, "psImageRadialCut returned NULL with NULL input radii");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_NULL,
+          "psImageRadialCut did generate proper error message");
+        psFree(err);
+
+    
+        // NULL input stat...
+        // Following should be an error
+        // XXX: Verify error
+        result = psImageRadialCut(result,image,mask,1,centerX,centerY,radii,NULL);
+        ok(result == NULL, "psImageRadialCut returned NULL with NULL input stats");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_NULL,
+          "psImageRadialCut did generate proper error message");
+        psFree(err);
+    
+
+        // Bad center X
+        // Following should be an error
+        // XXX: Verify error
+        result = psImageRadialCut(result,image,mask,1,
+                                  c+1,centerY,radii,stat);
+        ok(result == NULL, "psImageRadialCut returned NULL with bad center X");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_VALUE,
+          "psImageRadialCut did generate proper error message");
+        psFree(err);
+
+    
+        // Bad center Y
+        // Following should be an error
+        // XXX: Verify error
+        result = psImageRadialCut(result,image,mask,1,
+                                  centerX,r+1,radii,stat);
+        ok(result == NULL, "psImageRadialCut returned NULL with bad center Y");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_VALUE,
+          "psImageRadialCut did generate proper error message");
+        psFree(err);
+
+    
+        // Bad mask type (N.B., swapped image/mask to do this)
+        // Following should be an error
+        // XXX: Verify error
+        result = psImageRadialCut(result,mask,image,1,
+                                  centerX,r+1,radii,stat);
+        ok(result == NULL, "psImageRadialCut returned NULL with bad mask type");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_TYPE,
+          "psImageRadialCut did generate proper error message");
+        psFree(err);
+
+    
+        // Bad mask size
+        psImage* mask2 = psImageAlloc(c/2,r/2,PS_TYPE_MASK);
+        // Following should be an error
+        // XXX: Verify error
+        result = psImageRadialCut(result,image, mask2, 1,
+                                  centerX,centerY,radii,stat);
+        psFree(mask2);
+        ok(result == NULL, "psImageRadialCut returned NULL with bad mask size");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_SIZE,
+          "psImageRadialCut did generate proper error message");
+        psFree(err);
+
+    
+        // Bad radii size
+        psVector* radii2 = psVectorAlloc(1,PS_TYPE_MASK);
+        // Following should be an error
+        // XXX: Verify error
+        result = psImageRadialCut(result,image, mask, 1,
+                                  centerX,centerY,radii2,stat);
+        psFree(radii2);
+        ok(result == NULL, "psImageRadialCut returned NULL with bad radii size");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_SIZE,
+          "psImageRadialCut did generate proper error message");
+        psFree(err);
+
+    
+        // bad input stat option...
+        stat->options = 0;
+        // Following should be an error
+        // XXX: Verify error
+        result = psImageRadialCut(result,image,mask,1,centerX,centerY,radii,stat);
+        stat->options = PS_STAT_SAMPLE_MEAN;
+        ok(result == NULL, "psImageRadialCut returned NULL with bad input stat option");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_VALUE,
+          "psImageRadialCut did generate proper error message");
+        psFree(err);
+    
+        psFree(image);
+        psFree(mask);
+        psFree(radii);
+        psFree(stat);
+        psFree(result);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");    
+    }
+
+
+    // testImageRowColError()
+    {
+        psMemId id = psMemGetId();
+        psImage *image = NULL;
+        psVector *out = NULL;
+        int num = 0;
+    
+        // Following should generate error message(for row)
+        // XXX: Verify error
+        out = psImageRow(NULL, NULL, num);
+        ok(out == NULL, "psImageRow() returned NULL with NULL input image");
+
+        // Following should generate error message(for col)
+        // XXX: Verify error
+        out = psImageCol(NULL, NULL, num);
+        ok(out == NULL, "psImagecol() returned NULL with NULL input image");
+        image = psImageAlloc(3, 3, PS_TYPE_F64);
+
+
+        //Test for unallowed row0.
+        P_PSIMAGE_SET_ROW0(image, -2);
+        // Following should generate error message(for row)
+        // XXX: Verify error
+        out = psImageRow(NULL, image, num);
+        ok(out == NULL, "psImageRow() returned NULL with unallowed row0");
+        // Following should generate error message(for col)
+        // XXX: Verify error
+        out = psImageCol(NULL, image, num);
+        ok(out == NULL, "psImageCol() returned NULL with unallowed row0");
+
+    
+        //Test for unallowed col0.
+        P_PSIMAGE_SET_COL0(image, -1);
+        P_PSIMAGE_SET_ROW0(image, 5);
+        // Following should generate error message(for row)
+        // XXX: Verify error
+        out = psImageRow(NULL, image, num);
+        ok(out == NULL, "psImageRow() returned NULL with unallowed col0");
+        // Following should generate error message(for col)
+        // XXX: Verify error
+        out = psImageCol(NULL, image, num);
+        ok(out == NULL, "psImageCol() returned NULL with unallowed col0");
+
+    
+        //Test for unallowed numRows
+        P_PSIMAGE_SET_COL0(image, 10);
+        *(int*)&(image->numRows) = -1;
+        // Following should generate error message(for row)
+        // XXX: Verify error
+        out = psImageRow(NULL, image, num);
+        ok(out == NULL, "psImageRow() returned NULL with unallowed numRows");
+        // Following should generate error message(for col)
+        // XXX: Verify error
+        out = psImageCol(NULL, image, num);
+        ok(out == NULL, "psImageCol() returned NULL with unallowed numRows");
+
+
+        //Test for unallowed numCols
+        *(int*)&(image->numRows) = 3;
+        *(int*)&(image->numCols) = -1;
+        // Following should generate error message(for row)
+        // XXX: Verify error
+        out = psImageRow(NULL, image, num);
+        ok(out == NULL, "psImageRow() returned NULL with unallowed numCols");
+        // Following should generate error message(for col)
+        // XXX: Verify error
+        out = psImageCol(NULL, image, num);
+        ok(out == NULL, "psImageCol() returned NULL with unallowed numCols");
+
+
+        //Test for unallowed row/col number specified.
+        *(int*)&(image->numCols) = 3;
+        num = 8;
+        // Following should generate error message(for row)
+        // XXX: Verify error
+        out = psImageRow(NULL, image, num);
+        ok(out == NULL, "psImageRow() returned NULL with unallowed row/col number");
+        num = 13;
+        // Following should generate error message(for col)
+        // XXX: Verify error
+        out = psImageCol(NULL, image, num);
+        ok(out == NULL, "psImageCol() returned NULL with unallowed row/col number");
+
+
+        num = 3;
+        // Following should generate error message(for row)
+        // XXX: Verify error
+        out = psImageRow(NULL, image, num);
+        ok(out == NULL, "psImageRow() returned NULL");
+        num = 8;
+        // Following should generate error message(for col)
+        // XXX: Verify error
+        out = psImageCol(NULL, image, num);
+        ok(out == NULL, "psImageCol() returned NULL");
+
+
+        num = -10;
+        // Following should generate error message(for row)
+        // XXX: Verify error
+        out = psImageRow(NULL, image, num);
+        ok(out == NULL, "psImageRow() returned NULL");
+        num = -14;
+        // Following should generate error message(for col)
+        // XXX: Verify error
+        out = psImageCol(NULL, image, num);
+        ok(out == NULL, "psImageCol() returned NULL");
+
+        // Test on correct input data for several sizes    
+        genericImageRowColTests(1, 8);
+        genericImageRowColTests(8, 1);
+        genericImageRowColTests(8, 8);
+        genericImageRowColTests(8, 16);
+        genericImageRowColTests(16, 8);
+        psFree(image);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");    
+    }
+
+    // testImageRowColF64()
+    {
+        psMemId id = psMemGetId();
+        psVector *rowcol = NULL;
+        psVector *empty = NULL;
+        psImage *image = NULL;
+    
+        image = psImageAlloc(3, 3, PS_TYPE_F64);
+        rowcol = psVectorAlloc(3, PS_TYPE_F64);
+
+        image->data.F64[0][0] = 666.666;
+        image->data.F64[1][0] = 66.6;
+        image->data.F64[2][0] = 6.66;
+        image->data.F64[0][1] = 6.6;
+        image->data.F64[1][1] = 6.666;
+        image->data.F64[2][1] = 66.666;
+        image->data.F64[0][2] = 666.6;
+        image->data.F64[1][2] = 666.66;
+        image->data.F64[2][2] = 66.66;
+    
+        //Test for error with NULL image
+        empty = psImageCol(empty, NULL, 0);
+        ok(empty == NULL, "psImageCol returned NULL for NULL image input");
+        //Test for error with Out of Range Row
+        empty = psImageRow(empty, image, 5);
+        ok(empty == NULL, "psImageRow returned NULL for out of range row input");
+
+        rowcol->data.F64[0] = 1.1;
+        rowcol->data.F64[2] = 2.2;
+        //Test recycling of non-NULL vector & correct output
+        rowcol = psImageCol(rowcol, image, 1);
+        double test1, test2;
+        double TOLTST = .001;
+        test1 = fabs(rowcol->data.F64[0]-6.6);
+        test2 = fabs(rowcol->data.F64[2]-66.666);
+        ok((test1<=TOLTST) && (test2<=TOLTST), "psImageCol returned correct values");
+
+        rowcol = psImageRow(rowcol, image, 1);
+        test1 = fabs(rowcol->data.F64[0]-66.6);
+        test2 = fabs(rowcol->data.F64[2]-666.66);
+        ok(!((test1>TOLTST) || (test2>TOLTST)),
+           "psImageRow returned correct values");
+        psFree(rowcol);
+        psFree(image);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageRowColF32()
+    {
+        psMemId id = psMemGetId();
+        psVector *rowcol = NULL;
+        psVector *empty = NULL;
+        psImage *image = NULL;
+        psImage *emptyImage = NULL;
+    
+        float test1;
+        float test2;
+        float TOLTST = .01;
+    
+        image = psImageAlloc(3, 3, PS_TYPE_F32);
+        rowcol = psVectorAlloc(3, PS_TYPE_F32);
+        rowcol->n = rowcol->nalloc;
+    
+        image->data.F32[0][0] = 666.666;
+        image->data.F32[1][0] = 66.6;
+        image->data.F32[2][0] = 6.66;
+        image->data.F32[0][1] = 6.6;
+        image->data.F32[1][1] = 6.666;
+        image->data.F32[2][1] = 66.666;
+        image->data.F32[0][2] = 666.6;
+        image->data.F32[1][2] = 666.66;
+        image->data.F32[2][2] = 66.66;
+    
+        //Test for error with NULL image
+        empty = psImageCol(empty, emptyImage, 0);
+        ok(empty == NULL, "psImageCol returned NULL for NULL image input");
+        //Test for error with Out of Range Row
+        empty = psImageRow(empty, image, 5);
+        ok(empty == NULL, "psImageRow returned NULL for out of range row input");
+
+        rowcol->data.F32[0] = 1.1;
+        rowcol->data.F32[2] = 2.2;
+        //Test recycling of non-NULL vector & correct output
+        rowcol = psImageCol(rowcol, image, 1);
+        test1 = fabs(rowcol->data.F32[0]-6.6);
+        test2 = fabs(rowcol->data.F32[2]-66.666);
+        ok((test1<=TOLTST) && (test2<=TOLTST), "psImageCol returned correct values");
+    
+        psFree(rowcol);
+        psFree(image);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageRowColU64()
+    {
+        psMemId id = psMemGetId();
+        psVector *rowcol = NULL;
+        psVector *empty = NULL;
+        psImage *image = NULL;
+        psImage *emptyImage = NULL;
+    
+        image = psImageAlloc(3, 3, PS_TYPE_U64);
+        rowcol = psVectorAlloc(3, PS_TYPE_U64);
+    
+        image->data.U64[0][0] = 1;
+        image->data.U64[1][0] = 2;
+        image->data.U64[2][0] = 3;
+        image->data.U64[0][1] = 4;
+        image->data.U64[1][1] = 5;
+        image->data.U64[2][1] = 6;
+        image->data.U64[0][2] = 7;
+        image->data.U64[1][2] = 8;
+        image->data.U64[2][2] = 9;
+    
+        //Test for error with NULL image
+        empty = psImageCol(empty, emptyImage, 0);
+        ok(empty == NULL, "psImageCol returned NULL for NULL image input");
+        //Test for error with Out of Range Row
+        empty = psImageRow(empty, image, 5);
+        ok(empty == NULL, "psImageRow returned NULL for out of range row input");
+
+        //Test recycling of non-NULL vector & correct output
+        rowcol = psImageCol(rowcol, image, 1);
+        ok((rowcol->data.U64[0] == 4) && (rowcol->data.U64[2] == 6),
+          "psImageCol returned correct values (%u %u)",
+           rowcol->data.U64[0], rowcol->data.U64[2]);
+        psFree(rowcol);
+        psFree(image);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageRowColU32()
+    {
+        psMemId id = psMemGetId();
+        psVector *rowcol = NULL;
+        psVector *empty = NULL;
+        psImage *image = NULL;
+        psImage *emptyImage = NULL;
+    
+        image = psImageAlloc(3, 3, PS_TYPE_U32);
+        rowcol = psVectorAlloc(3, PS_TYPE_U32);
+    
+        image->data.U32[0][0] = 1;
+        image->data.U32[1][0] = 2;
+        image->data.U32[2][0] = 3;
+        image->data.U32[0][1] = 4;
+        image->data.U32[1][1] = 5;
+        image->data.U32[2][1] = 6;
+        image->data.U32[0][2] = 7;
+        image->data.U32[1][2] = 8;
+        image->data.U32[2][2] = 9;
+    
+        //Test for error with NULL image
+        empty = psImageCol(empty, emptyImage, 0);
+        ok(empty == NULL, "psImageCol returned NULL for NULL image input");
+        //Test for error with Out of Range Row
+        empty = psImageRow(empty, image, 5);
+        ok(empty == NULL, "psImageRow returned NULL for out of range row input");
+
+        //Test recycling of non-NULL vector & correct output
+        rowcol = psImageCol(rowcol, image, 1);
+        ok(rowcol->data.U32[0] == 4 && rowcol->data.U32[2] == 6,
+          "psImageCol returned correct values (%d %d)",
+          rowcol->data.U32[0] == 4, rowcol->data.U32[2]);
+    
+        psFree(rowcol);
+        psFree(image);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageRowColS32()
+    {
+        psMemId id = psMemGetId();
+        psVector *rowcol = NULL;
+        psVector *empty = NULL;
+        psImage *image = NULL;
+        psImage *emptyImage = NULL;
+    
+        image = psImageAlloc(3, 3, PS_TYPE_S32);
+        rowcol = psVectorAlloc(3, PS_TYPE_S32);
+    
+        image->data.S32[0][0] = 1;
+        image->data.S32[1][0] = 2;
+        image->data.S32[2][0] = 3;
+        image->data.S32[0][1] = 4;
+        image->data.S32[1][1] = 5;
+        image->data.S32[2][1] = 6;
+        image->data.S32[0][2] = 7;
+        image->data.S32[1][2] = 8;
+        image->data.S32[2][2] = 9;
+
+        //Test for error with NULL image
+        empty = psImageCol(empty, emptyImage, 0);
+        ok(empty == NULL, "psImageCol returned NULL for NULL image input");
+        //Test for error with Out of Range Row
+        empty = psImageRow(empty, image, 5);
+        ok(empty == NULL, "psImageRow returned NULL for out of range row input");
+
+        //Test recycling of non-NULL vector & correct output
+        rowcol = psImageCol(rowcol, image, 1);
+        ok(rowcol->data.S32[0] == 4 && rowcol->data.S32[2] == 6,
+          "psImageCol returned correct values (%d %d)",
+           rowcol->data.S32[0], rowcol->data.S32[2]);
+        psFree(rowcol);
+        psFree(image);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageRowColS64()
+    {
+        psMemId id = psMemGetId();
+        psVector *rowcol = NULL;
+        psVector *empty = NULL;
+        psImage *image = NULL;
+        psImage *emptyImage = NULL;
+    
+        image = psImageAlloc(3, 3, PS_TYPE_S64);
+        rowcol = psVectorAlloc(3, PS_TYPE_S64);
+    
+        image->data.S64[0][0] = 1;
+        image->data.S64[1][0] = 2;
+        image->data.S64[2][0] = 3;
+        image->data.S64[0][1] = 4;
+        image->data.S64[1][1] = 5;
+        image->data.S64[2][1] = 6;
+        image->data.S64[0][2] = 7;
+        image->data.S64[1][2] = 8;
+        image->data.S64[2][2] = 9;
+    
+        //Test for error with NULL image
+        empty = psImageCol(empty, emptyImage, 0);
+        ok(empty == NULL, "psImageCol returned NULL for NULL image input");
+        //Test for error with Out of Range Row
+        empty = psImageRow(empty, image, 5);
+        ok(empty == NULL, "psImageRow returned NULL for out of range row input");
+
+        //Test recycling of non-NULL vector & correct output
+        rowcol = psImageCol(rowcol, image, 1);
+        ok(rowcol->data.S64[0] == 4 && rowcol->data.S64[2] == 6,
+          "psImageCol returned correct values");
+        psFree(rowcol);
+        psFree(image);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageRowColS16()
+    {
+        psMemId id = psMemGetId();
+        psVector *rowcol = NULL;
+        psVector *empty = NULL;
+        psImage *image = NULL;
+        psImage *emptyImage = NULL;
+    
+        image = psImageAlloc(3, 3, PS_TYPE_S16);
+        rowcol = psVectorAlloc(3, PS_TYPE_S16);
+    
+        image->data.S16[0][0] = 1;
+        image->data.S16[1][0] = 2;
+        image->data.S16[2][0] = 3;
+        image->data.S16[0][1] = 4;
+        image->data.S16[1][1] = 5;
+        image->data.S16[2][1] = 6;
+        image->data.S16[0][2] = 7;
+        image->data.S16[1][2] = 8;
+        image->data.S16[2][2] = 9;
+    
+        //Test for error with NULL image
+        empty = psImageCol(empty, emptyImage, 0);
+        ok(empty == NULL, "psImageCol returned NULL for NULL image input");
+        //Test for error with Out of Range Row
+        empty = psImageRow(empty, image, 5);
+        ok(empty == NULL, "psImageRow returned NULL for out of range row input");
+
+        //Test recycling of non-NULL vector & correct output
+        rowcol = psImageCol(rowcol, image, 1);
+        ok(rowcol->data.S16[0] == 4 && rowcol->data.S16[2] == 6,
+           "psImageRow returned correct values");
+        psFree(rowcol);
+        psFree(image);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageRowColU16()
+    {
+        psMemId id = psMemGetId();
+        psVector *rowcol = NULL;
+        psVector *empty = NULL;
+        psImage *image = NULL;
+        psImage *emptyImage = NULL;
+    
+        image = psImageAlloc(3, 3, PS_TYPE_U16);
+        rowcol = psVectorAlloc(3, PS_TYPE_U16);
+    
+        image->data.U16[0][0] = 1;
+        image->data.U16[1][0] = 2;
+        image->data.U16[2][0] = 3;
+        image->data.U16[0][1] = 4;
+        image->data.U16[1][1] = 5;
+        image->data.U16[2][1] = 6;
+        image->data.U16[0][2] = 7;
+        image->data.U16[1][2] = 8;
+        image->data.U16[2][2] = 9;
+    
+        //Test for error with NULL image
+        empty = psImageCol(empty, emptyImage, 0);
+        ok(empty == NULL, "psImageCol returned NULL for NULL image input");
+        //Test for error with Out of Range Row
+        empty = psImageRow(empty, image, 5);
+        ok(empty == NULL, "psImageRow returned NULL for out of range row input");
+
+        //Test recycling of non-NULL vector & correct output
+        rowcol = psImageCol(rowcol, image, 1);
+        ok(rowcol->data.U16[0] == 4 && rowcol->data.U16[2] == 6,
+           "psImageRow returned correct values");
+        psFree(rowcol);
+        psFree(image);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageRowColU8()
+    {
+        psMemId id = psMemGetId();
+        psVector *rowcol = NULL;
+        psVector *empty = NULL;
+        psImage *image = NULL;
+        psImage *emptyImage = NULL;
+    
+        image = psImageAlloc(3, 3, PS_TYPE_U8);
+        rowcol = psVectorAlloc(3, PS_TYPE_U8);
+    
+        image->data.U8[0][0] = 1;
+        image->data.U8[1][0] = 2;
+        image->data.U8[2][0] = 3;
+        image->data.U8[0][1] = 4;
+        image->data.U8[1][1] = 5;
+        image->data.U8[2][1] = 6;
+        image->data.U8[0][2] = 7;
+        image->data.U8[1][2] = 8;
+        image->data.U8[2][2] = 9;
+    
+        //Test for error with NULL image
+        empty = psImageCol(empty, emptyImage, 0);
+        ok(empty == NULL, "psImageCol returned NULL for NULL image input");
+        //Test for error with Out of Range Row
+        empty = psImageRow(empty, image, 5);
+        ok(empty == NULL, "psImageRow returned NULL for out of range row input");
+
+        //Test recycling of non-NULL vector & correct output
+        rowcol = psImageCol(rowcol, image, 1);
+        ok(rowcol->data.U8[0] == 4 && rowcol->data.U8[2] == 6,
+           "psImageRow returned correct values");
+        psFree(rowcol);
+        psFree(image);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageRowColS8()
+    {
+        psMemId id = psMemGetId();
+        psVector *rowcol = NULL;
+        psVector *empty = NULL;
+        psImage *image = NULL;
+        psImage *emptyImage = NULL;
+    
+        image = psImageAlloc(3, 3, PS_TYPE_S8);
+        rowcol = psVectorAlloc(3, PS_TYPE_S8);
+    
+        image->data.S8[0][0] = 1;
+        image->data.S8[1][0] = 2;
+        image->data.S8[2][0] = 3;
+        image->data.S8[0][1] = 4;
+        image->data.S8[1][1] = 5;
+        image->data.S8[2][1] = 6;
+        image->data.S8[0][2] = 7;
+        image->data.S8[1][2] = 8;
+        image->data.S8[2][2] = 9;
+
+        //Test for error with NULL image
+        empty = psImageCol(empty, emptyImage, 0);
+        ok(empty == NULL, "psImageCol returned NULL for NULL image input");
+        //Test for error with Out of Range Row
+        empty = psImageRow(empty, image, 5);
+        ok(empty == NULL, "psImageRow returned NULL for out of range row input");
+
+        //Test recycling of non-NULL vector & correct output
+        rowcol = psImageCol(rowcol, image, 1);
+        ok(rowcol->data.S8[0] == 4 && rowcol->data.S8[2] == 6,
+           "psImageRow returned correct values");
+        psFree(rowcol);
+        psFree(image);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImagePixelManip.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImagePixelManip.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImagePixelManip.c	(revision 22158)
@@ -0,0 +1,482 @@
+/** @file  tst_psImageManip.c
+ *
+ *  @brief Contains the tests for psImageManip.[ch]
+ *
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-06-04 20:25:32 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#define VERBOSE false
+
+void genericImageClipTest(int numRows, int numCols) {
+    psMemId id = psMemGetId();
+
+    psImage *image = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    for (int row = 0 ; row < numRows ; row++) {
+        for (int col = 0 ; col < numCols ; col++) {
+            image->data.F32[row][col] = (float) (row + col);
+        }
+    }
+    psF32 min = (psF64)numRows/2.0;
+    psF32 max = (psF64)numRows;
+
+    psS32 retVal = psImageClip(image, min, (double)PS_MIN_F32, max, (double)PS_MAX_F32);
+    int numClipped = 0;
+    bool errorFlag = false;
+    for (int row=0;row<numRows;row++) {
+        for (int col=0;col<numCols;col++) {
+            psF32 value = (psF32)(row+col);
+            if (value < min) {
+                numClipped++;
+                value = PS_MIN_F32;
+            } else if (value > max) {
+                numClipped++;
+                value = PS_MAX_F32;
+            }
+            if (fabsf(image->data.F32[row][col]-value) > FLT_EPSILON) {
+                diag("Pixel value is not as expected (%g vs %g) at %u,%u",
+                     (psF64)image->data.F32[row][col], (psF64)value, col, row);
+                errorFlag = true;
+            }
+        }
+    }
+    ok(!errorFlag, "psImageClip() produced the correct data values");
+    ok(retVal == numClipped, "Got the expected number of clips");
+    psFree(image);
+
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(122);
+
+    // test psImageClip()
+    {
+        psMemId id = psMemGetId();
+
+        //psImageClip shall limit the minimum and maximum data value within a psImage structure
+
+        // psImageClip shall limit the minimum and maximum data value within a
+        // psImage structure to a specified min and max value.
+        //
+        // Verify the returned integer is equal to the number of pixels clipped,
+        // if the input psImage structure contains known values and input parameters
+        // min and max have know values.
+        //
+        // Verify the psImage structure specified by the input parameter input is
+        // modified to contain the expected values, if the input psImage structure
+        // contains known values, min and max are specified and vmin and vmax
+        // parameters are known.
+        //
+        // Verify the retuned integer is zero, psImage structure input is unmodified
+        // and program executions doesn't stop, if input parameter psImage structure
+        // pointer is NULL.
+        //
+        // Verify the retuned integer is zero, psImage structure input is unmodified
+        // and program executions doesn't stop, if input parameter min is larger than max.
+        // create image
+
+        genericImageClipTest(8, 1);
+        genericImageClipTest(1, 8);
+        genericImageClipTest(8, 8);
+        genericImageClipTest(8, 16);
+        genericImageClipTest(16, 8);
+
+        #define testImageClipByType(datatype) \
+        { \
+            psU32 c = 128; \
+            psU32 r = 256; \
+            psF64 min; \
+            psF64 max; \
+            psS32 numClipped = 0; \
+            psS32 retVal; \
+            psMemId id = psMemGetId(); \
+            psImage *img = psImageAlloc(c,r,PS_TYPE_##datatype); \
+            for (psU32 row=0;row<r;row++) { \
+                ps##datatype* imgRow = img->data.datatype[row]; \
+                for (psU32 col=0;col<c;col++) { \
+                    imgRow[col] = (ps##datatype)(row+col); \
+                } \
+            } \
+            min = (psF64)r/2.0; \
+            max = (psF64)r; \
+            \
+            retVal = psImageClip(img,min,(double)PS_MIN_##datatype,max,(double)PS_MAX_##datatype); \
+            \
+            numClipped = 0; \
+            bool errorFlag = false; \
+            for (psU32 row=0;row<r;row++) { \
+                ps##datatype* imgRow = img->data.datatype[row]; \
+                for (psU32 col=0;col<c;col++) { \
+                    ps##datatype value = (ps##datatype)(row+col); \
+                    if (value < min) { \
+                        numClipped++; \
+                        value = PS_MIN_##datatype; \
+                    } else if (value > max) { \
+                        numClipped++; \
+                        value = PS_MAX_##datatype; \
+                    } \
+                    if (fabsf(imgRow[col]-value) > FLT_EPSILON) { \
+                        diag("Pixel value is not as expected (%g vs %g) at %u,%u", \
+                             (psF64)imgRow[col],(psF64)value,col,row); \
+                        errorFlag = true; \
+                    } \
+                } \
+            } \
+            ok(!errorFlag, "psImageClip() produced the correct data values"); \
+            ok(retVal == numClipped, "Got the expected number of clips"); \
+            psFree(img); \
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); \
+        }
+
+        testImageClipByType(F64);
+        testImageClipByType(F32);
+        testImageClipByType(S32);
+        testImageClipByType(S16);
+        testImageClipByType(S8);
+        testImageClipByType(U32);
+        testImageClipByType(U16);
+        testImageClipByType(U8);
+
+        psF64 min=0.0;
+        psF64 max=0.0;
+        psS32 retVal;
+        psImage *img = NULL;
+        // Verify the retuned integer is zero, psImage structure input is unmodified
+        // and program executions doesn't stop, if input parameter psImage structure
+        // pointer is NULL.
+        retVal = psImageClip(NULL,min,-1.0f,max,-2.0f);
+        ok(retVal == 0, "Expected zero return for clips of a NULL image");
+
+        // Verify the retuned integer is zero, psImage structure input is unmodified
+        // and program executions doesn't stop, if input parameter min is larger than max.
+        // Following should be an error (max<min)
+        // XXX: Verify error
+        retVal = psImageClip(img,max,-1.0f,min,-2.0f);
+        ok(retVal == 0, "Expected zero return for clips when max < min");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageClipNAN()
+    {
+        psMemId id = psMemGetId();
+        psImage* img = NULL;
+        psU32 c = 128;
+        psU32 r = 256;
+        psS32 numClipped = 0;
+        psS32 retVal;
+
+        // psImageClipNaN shall modified pixel values of NaN with a specified value");
+
+        // psImageClipNaN shall modify a psImage structure with pixel values set
+        // to NaN to a value specified as an input parameter.
+        //
+        // Verify the returned integer is equal to the number of pixels modified
+        // and the psImage is modified at locations where NaN pixels where
+        // located to the value specified in the input parameter value.
+        //
+        // Verify the returned integer is zero and program execution doesn't stop,
+        // if the input parameter psImage structure pointer is NULL.
+        // create image
+        #define testImageClipNaNByType(datatype) \
+        { \
+            psMemId id = psMemGetId(); \
+            img = psImageAlloc(c,r,PS_TYPE_##datatype); \
+            for (unsigned row=0;row<r;row++) { \
+                ps##datatype* imgRow = img->data.datatype[row]; \
+                for (unsigned col=0;col<c;col++) { \
+                    if (row == col) { \
+                        imgRow[col] = NAN; \
+                    } else if (row+1 == col) { \
+                        imgRow[col] = INFINITY; \
+                    } else { \
+                        imgRow[col] = (ps##datatype)(row+col); \
+                    } \
+                } \
+            } \
+            \
+            retVal = psImageClipNaN(img,-1.0f); \
+            \
+            numClipped = 0; \
+            bool errorFlag = false; \
+            for (unsigned row=0;row<r;row++) { \
+                ps##datatype* imgRow = img->data.datatype[row]; \
+                for (unsigned col=0;col<c;col++) { \
+                    ps##datatype value = (ps##datatype)(row+col); \
+                    if ( (row == col) || (row+1 == col) ) { \
+                        numClipped++; \
+                        value = -1.0; \
+                    } \
+                    if (fabsf(imgRow[col]-value) > FLT_EPSILON) { \
+                        diag("Pixel value is not as expected (%f vs %f) at %d,%d", \
+                             imgRow[col],value,col,row); \
+                        errorFlag = true; \
+                    } \
+                } \
+            } \
+            ok(!errorFlag, "psImageClip() produced the correct data values"); \
+            ok(retVal == numClipped, "Got the expected number of clips"); \
+            psFree(img); \
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); \
+        }
+
+        testImageClipNaNByType(F32);
+        testImageClipNaNByType(F64);
+
+        // Verify the retuned integer is zero, psImage structure input is unmodified
+        // and program executions doesn't stop, if input parameter psImage structure
+        // pointer is NULL.
+        retVal = psImageClipNaN(NULL,-1.0f);
+        ok(retVal == 0, "Expected zero return for clips of a NULL image");
+
+        // Verify program execution doesn't stop if the input image type is something
+        // other than F32, F64.
+        img = psImageAlloc(c,r,PS_TYPE_S32);
+        // Following should be an error (incorrect type)
+        // XXX: Verify error
+        retVal = psImageClipNaN(img,2.0f);
+        ok(retVal == 0, "Expected zero return for clip of incorrect image type");
+        psFree(img);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // testImageOverlay()
+    {
+        psMemId id = psMemGetId();
+        psImage* img = NULL;
+        psImage* img2 = NULL;
+        psImage* img3 = NULL;
+        psImage* img4 = NULL;
+        psU32 c = 128;
+        psU32 r = 256;
+        psS32 retVal;
+
+        // psImageSectionOverlay shall modified pixel values in a psImage structure to
+        // be equal to the value of the originaldata and an overlay image with a
+        // specified operation. Valid operations include =, +, -, *, /.
+        //
+        // Verify the returned integer is zero
+        // and the input parameter psImage structure is modified at the specified
+        // location and range with the given overlay image and the specified
+        // function. Cases should include all the valid operations. Comparison of
+        // expected values should include a delta to allow for testing on
+        // different platforms.
+        #define testOverlayTypeOP(DATATYPE,OP,OPSTRING) \
+        { \
+            psMemId id = psMemGetId(); \
+            img = psImageAlloc(c,r,PS_TYPE_##DATATYPE); \
+            for (unsigned row=0;row<r;row++) { \
+                ps##DATATYPE* imgRow = img->data.DATATYPE[row]; \
+                for (unsigned col=0;col<c;col++) { \
+                    imgRow[col] = 6.0; \
+                } \
+            } \
+            img2 = psImageAlloc(c/2,r/2,PS_TYPE_##DATATYPE); \
+            for (unsigned row=0;row<r/2;row++) { \
+                ps##DATATYPE* img2Row = img2->data.DATATYPE[row]; \
+                for (unsigned col=0;col<c/2;col++) { \
+                    img2Row[col] = 2.0; \
+                } \
+            } \
+            retVal = psImageOverlaySection(img,img2,c/4,r/4,OPSTRING); \
+            if (retVal == 0) { \
+                psError(PS_ERR_UNKNOWN, true,"psImageOverlaySection returned zero with %s op", \
+                        OPSTRING); \
+                return 1; \
+            } \
+            bool errorFlag = false; \
+            for (unsigned row=0;row<r;row++) { \
+                ps##DATATYPE* imgRow = img->data.DATATYPE[row]; \
+                ps##DATATYPE* img2Row = img2->data.DATATYPE[row]; \
+                for (unsigned col=0;col<c;col++) { \
+                    ps##DATATYPE val = 6.0; \
+                    if ( ! (row < r/4 || row >= r/2+r/4 || col < c/4 || col >= c/2+c/4)) { \
+                        val OP 2.0; \
+                    } \
+                    if (fabsf(imgRow[col] - val) > FLT_EPSILON) { \
+                        diag("Value incorrect at %d,%d (%.2f vs %.2f for %s)", \
+                             col,row,imgRow[col],val,OPSTRING); \
+                        errorFlag = true; \
+                    } \
+                    if (row < r/2 && col < c/2 && fabsf(img2Row[col] - 2.0) > FLT_EPSILON) { \
+                        diag("Overlay modified at %d,%d (%.2f for %s)", \
+                             col,row,img2Row[col],OPSTRING); \
+                        errorFlag = true; \
+                    } \
+                } \
+            } \
+            ok(!errorFlag, "psImageOverlaySection() produced the correct data values"); \
+            psFree(img); \
+            psFree(img2); \
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); \
+        }
+
+        #define testOverlayType(DATATYPE) \
+        testOverlayTypeOP(DATATYPE,+=,"+"); \
+        testOverlayTypeOP(DATATYPE,-=,"-"); \
+        testOverlayTypeOP(DATATYPE,*=,"*");\
+        testOverlayTypeOP(DATATYPE,/=,"/");\
+        testOverlayTypeOP(DATATYPE,=,"=");
+
+        testOverlayType(F64);
+        testOverlayType(F32);
+        testOverlayType(S16);
+        testOverlayType(S8);
+        testOverlayType(U16);
+        testOverlayType(U8);
+
+        // Verify the returned integer is equal to non-zero and the input psImage structure
+        // is unmodified, if the overlay specified is not within the data range of the
+        // input psImage structure.
+        img = psImageAlloc(c,r,PS_TYPE_F32);
+        for (unsigned row=0;row<r;row++)
+        {
+            psF32* imgRow = img->data.F32[row];
+            for (unsigned col=0;col<c;col++) {
+                imgRow[col] = 6.0f;
+            }
+        }
+        img2 = psImageAlloc(c,r,PS_TYPE_F32);
+        for (unsigned row=0;row<r;row++)
+        {
+            psF32* img2Row = img2->data.F32[row];
+            for (unsigned col=0;col<c;col++) {
+                img2Row[col] = 2.0f;
+            }
+        }
+        img3 = psImageAlloc(c,r,PS_TYPE_S64);
+        for (unsigned row=0;row<r;row++)
+        {
+            psS64* img3Row = img3->data.S64[row];
+            for (unsigned col=0;col<c;col++) {
+                img3Row[col] = 6.0f;
+            }
+        }
+        img4 = psImageAlloc(c,r,PS_TYPE_S64);
+        for (unsigned row=0;row<r;row++)
+        {
+            psS64* img4Row = img4->data.S64[row];
+            for (unsigned col=0;col<c;col++) {
+                img4Row[col] = 2.0f;
+            }
+        }
+
+        // Following should error as overlay isn't within image boundaries
+        // XXX: Verify error
+        retVal = psImageOverlaySection(img,img2,c/4,r/4,"+");
+        ok(retVal == 0, "psImageOverlaySection did return zero when overlay too big");
+
+        bool errorFlag = false;
+        for (unsigned row=0;row<r;row++)
+        {
+            psF32* imgRow = img->data.F32[row];
+            for (unsigned col=0;col<c;col++) {
+                if (imgRow[col] != 6.0f) {
+                    diag("Input image modified when overlay size too big");
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageOverlaySection() produced the correct data values");
+
+
+        // Verify the returned integer is equal to non-zero, the input psImage
+        // structure is unmodified and program execution doesn't stop, if the
+        // overlay specified is NULL.
+        // Following should error as overlay is NULL
+        // XXX: Verify error
+        retVal = psImageOverlaySection(img,NULL,c/4,r/4,"+");
+        ok(retVal == 0, "psImageOverlaySection did return zero when overlay too big");
+        errorFlag = false;
+        for (unsigned row=0;row<r;row++)
+        {
+            psF32* imgRow = img->data.F32[row];
+            for (unsigned col=0;col<c;col++) {
+                if (imgRow[col] != 6.0f) {
+                    diag("Input image modified when overlay NULL");
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageOverlaySection() produced the correct data values");
+
+
+        // Verify the returned integer is equal to non-zero and program execution
+        // doesn't stop, if the input parameter image is NULL.
+        // Following should error as image input is NULL
+        // XXX: Verify error
+        retVal = psImageOverlaySection(NULL,img2,c/4,r/4,"+");
+        ok(retVal == 0, "psImageOverlaySection returned zero when overlay too big");
+
+
+        // Verify the return integer is equal to non-zero and program execution
+        // doesn't stop, if the specified operator is not =,+,-,*,/
+        // Following should error as operator is incorrect
+        // XXX: Verify error
+        retVal = psImageOverlaySection(img,img2,0,0,"$");
+        ok(retVal == 0, "psImageOverlaySection returned zero when overlay too big");
+
+
+        // Verify the return integer is equal to non-zero and program execution
+        // doesn't stop, if the specified operator is NULL
+        // Following should error as operator is incorrect
+        // XXX: Verify error
+        retVal = psImageOverlaySection(img,img2,0,0,NULL);
+        ok(retVal == 0, "psImageOverlaySection returned zero when overlay operator is NULL");
+
+
+        // Verify the return integer is equal to non-zero and program execution
+        // doesn't stop, if overlay image is a different type than the input image
+        // Following should error as overlay is a different type
+        // XXX: Verify error
+        retVal = psImageOverlaySection(img,img3,0,0,"+");
+        ok(retVal == 0, "psImageOverlaySection returned zero when overlay image type is different than input image");
+
+
+        // Verify program execution doen't stop, if the overly image contains
+        // zero values with division operation is specified.
+        // XXX: This currently doesn't work.  Apparently, the psImageOverlaySection()
+        // will happily divide by 0.0.
+        for (unsigned row=0;row<r;row++)
+        {
+            psF32* img2Row = img2->data.F32[row];
+            for (unsigned col=0;col<c;col++) {
+                img2Row[col] = 0.0f;
+            }
+        }
+        retVal = psImageOverlaySection(img,img2,0,0,"/");
+        ok(retVal != 0, "psImageOverlaySection returned non-zero when checking divide-by-zero");
+        errorFlag = false;
+
+        for (unsigned row=0;row<r;row++)
+        {
+            for (unsigned col=0;col<c;col++) {
+                if (!isnan(img->data.F32[row][col])) {
+                    if (VERBOSE) diag("img[%d][%d] is %f, should be NAN\n", row, col, img->data.F32[row][col]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageOverlaySection() properly set data to NANs");
+
+        psFree(img);
+        psFree(img2);
+        psFree(img3);
+        psFree(img4);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageShift.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageShift.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageShift.c	(revision 22158)
@@ -0,0 +1,179 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+int main (void)
+{
+    plan_tests(39);
+
+//    diag("psImageShift() tests");
+
+    // tests using BILINEAR interpolation
+    {
+        psMemId id = psMemGetId();
+
+//        diag("shift a delta function by an integer offset");
+
+        // generate simple image (delta function)
+        psImage *image = psImageAlloc(32, 32, PS_TYPE_F32);
+        ok(image != NULL, "psImage successfully allocated");
+        skip_start(image == NULL, 5, "Skipping tests because psImageAlloc() failed");
+
+        // use delta function as input test image
+        image->data.F32[10][10] = 1;
+
+        // integer shifts should be exact
+        psImage *shift = psImageShift (NULL, image, 1.0, 1.0, 0.0, PS_INTERPOLATE_BILINEAR);
+        is_float (shift->data.F32[10][10], 0.0, "point 10,10 should be 0.0 : %f", shift->data.F32[10][10]);
+        is_float (shift->data.F32[10][11], 0.0, "point 10,11 should be 0.0 : %f", shift->data.F32[10][11]);
+        is_float (shift->data.F32[10][12], 0.0, "point 10,12 should be 0.0 : %f", shift->data.F32[10][12]);
+        is_float (shift->data.F32[11][10], 0.0, "point 11,10 should be 0.0 : %f", shift->data.F32[11][10]);
+        is_float (shift->data.F32[11][11], 1.0, "point 11,11 should be 1.0 : %f", shift->data.F32[11][11]);
+        is_float (shift->data.F32[11][12], 0.0, "point 11,12 should be 0.0 : %f", shift->data.F32[11][12]);
+        is_float (shift->data.F32[12][10], 0.0, "point 12,10 should be 0.0 : %f", shift->data.F32[12][10]);
+        is_float (shift->data.F32[12][11], 0.0, "point 12,11 should be 0.0 : %f", shift->data.F32[12][11]);
+        is_float (shift->data.F32[12][12], 0.0, "point 12,12 should be 0.0 : %f", shift->data.F32[12][12]);
+        psFree(shift);
+        psFree(image);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // tests using BILINEAR interpolation
+    {
+        psMemId id = psMemGetId();
+
+//        diag("shift a delta function by an fractional pixel offset");
+
+        // generate simple image (delta function)
+        psImage *image = psImageAlloc(32, 32, PS_TYPE_F32);
+        ok(image != NULL, "psImage successfully allocated");
+        skip_start(image == NULL, 5, "Skipping tests because psImageAlloc() failed");
+
+        // XXX is this needed?
+        psImageInit (image, 0.0);
+
+        // use delta function as input test image
+        image->data.F32[10][10] = 1;
+
+        // fractional shifts introduce smoothing,
+        psImage *shift = psImageShift (NULL, image, 0.2, 0.4, 0.0, PS_INTERPOLATE_BILINEAR);
+//        diag("these require tolerance of 4 epsilon (why?)");
+        is_float_tol (shift->data.F32[10][10], 0.8*0.6, 4*FLT_EPSILON, "point 10,10 should be %f : %f", 0.8*0.6, shift->data.F32[10][10]);
+        is_float_tol (shift->data.F32[10][11], 0.2*0.6, 4*FLT_EPSILON, "point 10,11 should be %f : %f", 0.2*0.6, shift->data.F32[10][11]);
+        is_float_tol (shift->data.F32[10][12], 0.0,     4*FLT_EPSILON, "point 10,12 should be %f : %f", 0.0,     shift->data.F32[10][12]);
+        is_float_tol (shift->data.F32[11][10], 0.8*0.4, 4*FLT_EPSILON, "point 11,10 should be %f : %f", 0.8*0.4, shift->data.F32[11][10]);
+        is_float_tol (shift->data.F32[11][11], 0.2*0.4, 4*FLT_EPSILON, "point 11,11 should be %f : %f", 0.2*0.4, shift->data.F32[11][11]);
+        is_float_tol (shift->data.F32[11][12], 0.0,     4*FLT_EPSILON, "point 11,12 should be %f : %f", 0.0,     shift->data.F32[11][12]);
+        is_float_tol (shift->data.F32[12][10], 0.0,     4*FLT_EPSILON, "point 12,10 should be %f : %f", 0.0,     shift->data.F32[12][10]);
+        is_float_tol (shift->data.F32[12][11], 0.0,     4*FLT_EPSILON, "point 12,11 should be %f : %f", 0.0,     shift->data.F32[12][11]);
+        is_float_tol (shift->data.F32[12][12], 0.0,     4*FLT_EPSILON, "point 12,12 should be %f : %f", 0.0,     shift->data.F32[12][12]);
+        psFree(shift);
+        psFree(image);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test by measuring gaussian centroid before and after
+    // using BILINEAR interpolation
+    {
+        psMemId id = psMemGetId();
+
+//        diag("shift a gaussian and measure centroid");
+
+        // generate simple image (gauss function)
+        psImage *image = psImageAlloc(32, 32, PS_TYPE_F32);
+        ok(image != NULL, "psImage successfully allocated");
+        skip_start(image == NULL, 5, "Skipping tests because psImageAlloc() failed");
+
+        // build a simple gaussian (16,16),(2,1) as input test image
+        for (int j = 0; j < image->numRows; j++)
+        {
+            for (int i = 0; i < image->numCols; i++) {
+                float z = PS_SQR(i - 16.0)/8.0 + PS_SQR(j - 16.0)/2.0;
+                image->data.F32[j][i] = exp(-z);
+            }
+        }
+
+        // measure centroid of unshifted gaussian (should be 16.0,16.0)
+        float xo = 0.0;
+        float yo = 0.0;
+        float no = 0.0;
+        for (int j = 0; j < image->numRows; j++)
+        {
+            for (int i = 0; i < image->numCols; i++) {
+                xo += i*image->data.F32[j][i];
+                yo += j*image->data.F32[j][i];
+                no += image->data.F32[j][i];
+            }
+        }
+        xo /= no;
+        yo /= no;
+
+//        diag ("these require a tolerance of 100 epsilon");
+        is_float_tol (xo, 16.0, 100*FLT_EPSILON, "x-centroid should be %f : %f", 16.0, xo);
+        is_float_tol (xo, 16.0, 100*FLT_EPSILON, "y-centroid should be %f : %f", 16.0, yo);
+
+        // fractional shifts introduce smoothing,
+        psImage *shift = psImageShift (NULL, image, 1.2, -1.2, 0.0, PS_INTERPOLATE_BILINEAR);
+
+        // measure centroid of shifted gaussian (should be 17.2,14.8)
+        xo = yo = no = 0.0;
+        for (int j = 0; j < shift->numRows; j++)
+        {
+            for (int i = 0; i < shift->numCols; i++) {
+                xo += i*shift->data.F32[j][i];
+                yo += j*shift->data.F32[j][i];
+                no += shift->data.F32[j][i];
+            }
+        }
+        xo /= no;
+        yo /= no;
+
+//        diag ("these require a tolerance of 100 epsilon");
+        is_float_tol (xo, 17.2, 100*FLT_EPSILON, "x-centroid should be %f : %f", 17.2, xo);
+        is_float_tol (yo, 14.8, 100*FLT_EPSILON, "y-centroid should be %f : %f", 14.8, yo);
+
+        psFree(shift);
+        psFree(image);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // tests using BICUBE interpolation
+    {
+        psMemId id = psMemGetId();
+
+        // generate simple image (x ramp)
+        psImage *image = psImageAlloc(32, 32, PS_TYPE_F32);
+        ok(image != NULL, "psImage successfully allocated");
+        skip_start(image == NULL, 5, "Skipping tests because psImageAlloc() failed");
+
+        // use delta function as input test image
+        image->data.F32[11][11] = 1;
+
+        // fractional shifts introduce smoothing,
+        psImage *shift = psImageShift (NULL, image, 0.2, 0.4, 0.0, PS_INTERPOLATE_BICUBE);
+        is_float_tol (shift->data.F32[10][10], -0.157778, 4*FLT_EPSILON, "point 10,10 should be %f : %f", -0.157778, shift->data.F32[10][10]);
+        is_float_tol (shift->data.F32[10][11], +0.168889, 4*FLT_EPSILON, "point 10,11 should be %f : %f", +0.168889, shift->data.F32[10][11]);
+        is_float_tol (shift->data.F32[10][12], -0.131111, 4*FLT_EPSILON, "point 10,12 should be %f : %f", -0.131111, shift->data.F32[10][12]);
+        is_float_tol (shift->data.F32[11][10], +0.142221, 4*FLT_EPSILON, "point 11,10 should be %f : %f", +0.142221, shift->data.F32[11][10]);
+        is_float_tol (shift->data.F32[11][11], +0.488884, 4*FLT_EPSILON, "point 11,11 should be %f : %f", +0.488884, shift->data.F32[11][11]);
+        is_float_tol (shift->data.F32[11][12], +0.208878, 4*FLT_EPSILON, "point 11,12 should be %f : %f", +0.208878, shift->data.F32[11][12]);
+        is_float_tol (shift->data.F32[12][10], -0.064500, 4*FLT_EPSILON, "point 12,10 should be %f : %f", -0.064500, shift->data.F32[12][10]);
+        is_float_tol (shift->data.F32[12][11], +0.302066, 4*FLT_EPSILON, "point 12,11 should be %f : %f", +0.302066, shift->data.F32[12][11]);
+        is_float_tol (shift->data.F32[12][12], +0.041884, 4*FLT_EPSILON, "point 12,12 should be %f : %f", +0.041884, shift->data.F32[12][12]);
+        psFree(shift);
+        psFree(image);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    return exit_status();
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageShiftKernel.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageShiftKernel.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageShiftKernel.c	(revision 22158)
@@ -0,0 +1,353 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+int main (void)
+{
+    plan_tests(34);
+
+//    diag("psImageShiftKernel() tests");
+
+    // tests using BILINEAR interpolation
+    // skip until we implement the integer shift portion
+    if (0) {
+        psMemId id = psMemGetId();
+
+//        diag("shift a delta function by an integer offset");
+
+        // generate simple image (delta function)
+        psImage *image = psImageAlloc(32, 32, PS_TYPE_F32);
+        ok(image != NULL, "psImage successfully allocated");
+        skip_start(image == NULL, 5, "Skipping tests because psImageAlloc() failed");
+
+        // use delta function as input test image
+        image->data.F32[10][10] = 1;
+
+        // integer shifts should be exact
+        psImage *shift = psImageShiftKernel (NULL, image, 1.0, 1.0, PS_INTERPOLATE_BILINEAR);
+        is_float (shift->data.F32[10][10], 0.0, "point 10,10 should be 0.0 : %f", shift->data.F32[10][10]);
+        is_float (shift->data.F32[10][11], 0.0, "point 10,11 should be 0.0 : %f", shift->data.F32[10][11]);
+        is_float (shift->data.F32[10][12], 0.0, "point 10,12 should be 0.0 : %f", shift->data.F32[10][12]);
+        is_float (shift->data.F32[11][10], 0.0, "point 11,10 should be 0.0 : %f", shift->data.F32[11][10]);
+        is_float (shift->data.F32[11][11], 1.0, "point 11,11 should be 1.0 : %f", shift->data.F32[11][11]);
+        is_float (shift->data.F32[11][12], 0.0, "point 11,12 should be 0.0 : %f", shift->data.F32[11][12]);
+        is_float (shift->data.F32[12][10], 0.0, "point 12,10 should be 0.0 : %f", shift->data.F32[12][10]);
+        is_float (shift->data.F32[12][11], 0.0, "point 12,11 should be 0.0 : %f", shift->data.F32[12][11]);
+        is_float (shift->data.F32[12][12], 0.0, "point 12,12 should be 0.0 : %f", shift->data.F32[12][12]);
+        psFree(shift);
+        psFree(image);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // tests using BILINEAR interpolation
+    // XXX skip until we implement BILINEAR
+    if (0) {
+        psMemId id = psMemGetId();
+
+//        diag("shift a delta function by an fractional pixel offset");
+
+        // generate simple image (delta function)
+        psImage *image = psImageAlloc(32, 32, PS_TYPE_F32);
+        ok(image != NULL, "psImage successfully allocated");
+        skip_start(image == NULL, 5, "Skipping tests because psImageAlloc() failed");
+
+        // XXX is this needed?
+        psImageInit (image, 0.0);
+
+        // use delta function as input test image
+        image->data.F32[10][10] = 1;
+
+        // fractional shifts introduce smoothing,
+        psImage *shift = psImageShiftKernel (NULL, image, 0.2, 0.4, PS_INTERPOLATE_BICUBE);
+//        diag("these require tolerance of 4 epsilon (why?)");
+        is_float_tol (shift->data.F32[10][10], 0.8*0.6, 4*FLT_EPSILON, "point 10,10 should be %f : %f", 0.8*0.6, shift->data.F32[10][10]);
+        is_float_tol (shift->data.F32[10][11], 0.2*0.6, 4*FLT_EPSILON, "point 10,11 should be %f : %f", 0.2*0.6, shift->data.F32[10][11]);
+        is_float_tol (shift->data.F32[10][12], 0.0,     4*FLT_EPSILON, "point 10,12 should be %f : %f", 0.0,     shift->data.F32[10][12]);
+        is_float_tol (shift->data.F32[11][10], 0.8*0.4, 4*FLT_EPSILON, "point 11,10 should be %f : %f", 0.8*0.4, shift->data.F32[11][10]);
+        is_float_tol (shift->data.F32[11][11], 0.2*0.4, 4*FLT_EPSILON, "point 11,11 should be %f : %f", 0.2*0.4, shift->data.F32[11][11]);
+        is_float_tol (shift->data.F32[11][12], 0.0,     4*FLT_EPSILON, "point 11,12 should be %f : %f", 0.0,     shift->data.F32[11][12]);
+        is_float_tol (shift->data.F32[12][10], 0.0,     4*FLT_EPSILON, "point 12,10 should be %f : %f", 0.0,     shift->data.F32[12][10]);
+        is_float_tol (shift->data.F32[12][11], 0.0,     4*FLT_EPSILON, "point 12,11 should be %f : %f", 0.0,     shift->data.F32[12][11]);
+        is_float_tol (shift->data.F32[12][12], 0.0,     4*FLT_EPSILON, "point 12,12 should be %f : %f", 0.0,     shift->data.F32[12][12]);
+        psFree(shift);
+        psFree(image);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test by measuring gaussian centroid before and after
+    // using BILINEAR interpolation
+    // XXX skip until we implement BILINEAR
+    if (0) {
+        psMemId id = psMemGetId();
+
+//        diag("shift a gaussian and measure centroid");
+
+        // generate simple image (gauss function)
+        psImage *image = psImageAlloc(32, 32, PS_TYPE_F32);
+        ok(image != NULL, "psImage successfully allocated");
+        skip_start(image == NULL, 5, "Skipping tests because psImageAlloc() failed");
+
+        // build a simple gaussian (16,16),(2,1) as input test image
+        for (int j = 0; j < image->numRows; j++) {
+            for (int i = 0; i < image->numCols; i++) {
+                float z = PS_SQR(i - 16.0)/8.0 + PS_SQR(j - 16.0)/2.0;
+                image->data.F32[j][i] = exp(-z);
+            }
+        }
+
+        // measure centroid of unshifted gaussian (should be 16.0,16.0)
+        float xo = 0.0;
+        float yo = 0.0;
+        float no = 0.0;
+        for (int j = 0; j < image->numRows; j++) {
+            for (int i = 0; i < image->numCols; i++) {
+                xo += i*image->data.F32[j][i];
+                yo += j*image->data.F32[j][i];
+                no += image->data.F32[j][i];
+            }
+        }
+        xo /= no;
+        yo /= no;
+
+//        diag ("these require a tolerance of 100 epsilon");
+        is_float_tol (xo, 16.0, 100*FLT_EPSILON, "x-centroid should be %f : %f", 16.0, xo);
+        is_float_tol (xo, 16.0, 100*FLT_EPSILON, "y-centroid should be %f : %f", 16.0, yo);
+
+        // fractional shifts introduce smoothing,
+        psImage *shift = psImageShiftKernel (NULL, image, 1.2, -1.2, PS_INTERPOLATE_BILINEAR);
+
+        // measure centroid of shifted gaussian (should be 17.2,14.8)
+        xo = yo = no = 0.0;
+        for (int j = 0; j < shift->numRows; j++) {
+            for (int i = 0; i < shift->numCols; i++) {
+                xo += i*shift->data.F32[j][i];
+                yo += j*shift->data.F32[j][i];
+                no += shift->data.F32[j][i];
+            }
+        }
+        xo /= no;
+        yo /= no;
+
+//        diag ("these require a tolerance of 100 epsilon");
+        is_float_tol (xo, 17.2, 100*FLT_EPSILON, "x-centroid should be %f : %f", 17.2, xo);
+        is_float_tol (yo, 14.8, 100*FLT_EPSILON, "y-centroid should be %f : %f", 14.8, yo);
+
+        psFree(shift);
+        psFree(image);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // tests using BICUBE interpolation
+    {
+        psMemId id = psMemGetId();
+
+        // generate simple image (x ramp)
+        psImage *image = psImageAlloc(32, 32, PS_TYPE_F32);
+        ok(image != NULL, "psImage successfully allocated");
+        skip_start(image == NULL, 5, "Skipping tests because psImageAlloc() failed");
+
+        // use delta function as input test image
+        image->data.F32[11][11] = 1;
+
+        // fractional shifts introduce smoothing,
+        psImage *shift = psImageShiftKernel (NULL, image, 0.2, 0.4, PS_INTERPOLATE_BICUBE);
+//        diag ("please check these values: this kernel is very steep and ringy.  what is the right BICUBE kernel?");
+        is_float_tol (shift->data.F32[10][10], -1.444445, 4*FLT_EPSILON, "point 10,10 should be %f : %f", -1.444445, shift->data.F32[10][10]);
+        is_float_tol (shift->data.F32[10][11], -0.277778, 4*FLT_EPSILON, "point 10,11 should be %f : %f", -0.277778, shift->data.F32[10][11]);
+        is_float_tol (shift->data.F32[10][12], -0.777778, 4*FLT_EPSILON, "point 10,12 should be %f : %f", -0.777778, shift->data.F32[10][12]);
+        is_float_tol (shift->data.F32[11][10], +0.055556, 4*FLT_EPSILON, "point 11,10 should be %f : %f", +0.055556, shift->data.F32[11][10]);
+        is_float_tol (shift->data.F32[11][11], +1.222222, 4*FLT_EPSILON, "point 11,11 should be %f : %f", +1.222222, shift->data.F32[11][11]);
+        is_float_tol (shift->data.F32[11][12], +0.722222, 4*FLT_EPSILON, "point 11,12 should be %f : %f", +0.722222, shift->data.F32[11][12]);
+        is_float_tol (shift->data.F32[12][10], -0.111111, 4*FLT_EPSILON, "point 12,10 should be %f : %f", -0.111111, shift->data.F32[12][10]);
+        is_float_tol (shift->data.F32[12][11], +1.055556, 4*FLT_EPSILON, "point 12,11 should be %f : %f", +1.055556, shift->data.F32[12][11]);
+        is_float_tol (shift->data.F32[12][12], +0.555556, 4*FLT_EPSILON, "point 12,12 should be %f : %f", +0.555556, shift->data.F32[12][12]);
+
+        psFree(shift);
+        psFree(image);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test by measuring gaussian centroid before and after
+    // using BICUBE interpolation
+    {
+        psMemId id = psMemGetId();
+
+//        diag("shift a gaussian and measure centroid");
+
+        // generate simple image (gauss function)
+        psImage *image = psImageAlloc(32, 32, PS_TYPE_F32);
+        ok(image != NULL, "psImage successfully allocated");
+        skip_start(image == NULL, 5, "Skipping tests because psImageAlloc() failed");
+
+        // build a simple gaussian (16,16),(2,1) as input test image
+        for (int j = 0; j < image->numRows; j++)
+        {
+            for (int i = 0; i < image->numCols; i++) {
+                float z = PS_SQR(i - 16.0)/8.0 + PS_SQR(j - 16.0)/2.0;
+                image->data.F32[j][i] = exp(-z);
+            }
+        }
+
+        // measure centroid of unshifted gaussian (should be 16.0,16.0)
+        float xo = 0.0;
+        float yo = 0.0;
+        float no = 0.0;
+        for (int j = 0; j < image->numRows; j++)
+        {
+            for (int i = 0; i < image->numCols; i++) {
+                xo += i*image->data.F32[j][i];
+                yo += j*image->data.F32[j][i];
+                no += image->data.F32[j][i];
+            }
+        }
+        xo /= no;
+        yo /= no;
+
+//        diag ("these require a tolerance of 100 epsilon");
+        is_float_tol (xo, 16.0, 100*FLT_EPSILON, "x-centroid should be %f : %f", 16.0, xo);
+        is_float_tol (xo, 16.0, 100*FLT_EPSILON, "y-centroid should be %f : %f", 16.0, yo);
+
+        // fractional shifts introduce smoothing,
+        psImage *shift = psImageShiftKernel (NULL, image, 0.2, -0.2, PS_INTERPOLATE_BICUBE);
+
+        // measure centroid of shifted gaussian (should be 17.2,14.8)
+        xo = yo = no = 0.0;
+        for (int j = 0; j < shift->numRows; j++)
+        {
+            for (int i = 0; i < shift->numCols; i++) {
+                xo += i*shift->data.F32[j][i];
+                yo += j*shift->data.F32[j][i];
+                no += shift->data.F32[j][i];
+            }
+        }
+        xo /= no;
+        yo /= no;
+
+//        diag ("these require a tolerance of 100 epsilon");
+        is_float_tol (xo, 16.2, 100*FLT_EPSILON, "x-centroid should be %f : %f", 16.2, xo);
+        is_float_tol (yo, 15.8, 100*FLT_EPSILON, "y-centroid should be %f : %f", 15.8, yo);
+
+        psFree(shift);
+        psFree(image);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // tests using GAUSS interpolation
+    {
+        psMemId id = psMemGetId();
+
+        // generate simple image (x ramp)
+        psImage *image = psImageAlloc(32, 32, PS_TYPE_F32);
+        ok(image != NULL, "psImage successfully allocated");
+        skip_start(image == NULL, 5, "Skipping tests because psImageAlloc() failed");
+
+        // use delta function as input test image
+        image->data.F32[11][11] = 1;
+
+        // fractional shifts introduce smoothing,
+        psImage *shift = psImageShiftKernel (NULL, image, 0.0, 0.0, PS_INTERPOLATE_GAUSS);
+        is_float_tol (shift->data.F32[10][10], -0.157778, 4*FLT_EPSILON, "point 10,10 should be %f : %f", -0.157778, shift->data.F32[10][10]);
+        is_float_tol (shift->data.F32[10][11], +0.168889, 4*FLT_EPSILON, "point 10,11 should be %f : %f", +0.168889, shift->data.F32[10][11]);
+        is_float_tol (shift->data.F32[10][12], -0.131111, 4*FLT_EPSILON, "point 10,12 should be %f : %f", -0.131111, shift->data.F32[10][12]);
+        is_float_tol (shift->data.F32[11][10], +0.142221, 4*FLT_EPSILON, "point 11,10 should be %f : %f", +0.142221, shift->data.F32[11][10]);
+        is_float_tol (shift->data.F32[11][11], +0.488884, 4*FLT_EPSILON, "point 11,11 should be %f : %f", +0.488884, shift->data.F32[11][11]);
+        is_float_tol (shift->data.F32[11][12], +0.208878, 4*FLT_EPSILON, "point 11,12 should be %f : %f", +0.208878, shift->data.F32[11][12]);
+        is_float_tol (shift->data.F32[12][10], -0.064500, 4*FLT_EPSILON, "point 12,10 should be %f : %f", -0.064500, shift->data.F32[12][10]);
+        is_float_tol (shift->data.F32[12][11], +0.302066, 4*FLT_EPSILON, "point 12,11 should be %f : %f", +0.302066, shift->data.F32[12][11]);
+        is_float_tol (shift->data.F32[12][12], +0.041884, 4*FLT_EPSILON, "point 12,12 should be %f : %f", +0.041884, shift->data.F32[12][12]);
+        psFree(shift);
+        psFree(image);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test by measuring gaussian centroid before and after
+    // using GAUSS interpolation
+    {
+        psMemId id = psMemGetId();
+
+//        diag("shift a gaussian and measure centroid");
+
+        // generate simple image (gauss function)
+        psImage *image = psImageAlloc(32, 32, PS_TYPE_F32);
+        ok(image != NULL, "psImage successfully allocated");
+        skip_start(image == NULL, 5, "Skipping tests because psImageAlloc() failed");
+
+        // build a simple gaussian (16,16),(2,1) as input test image
+        for (int j = 0; j < image->numRows; j++)
+        {
+            for (int i = 0; i < image->numCols; i++) {
+                float z = PS_SQR(i - 16.0)/8.0 + PS_SQR(j - 16.0)/2.0;
+                image->data.F32[j][i] = exp(-z);
+            }
+        }
+
+        // measure centroid of unshifted gaussian (should be 16.0,16.0)
+        float xo = 0.0;
+        float yo = 0.0;
+        float no = 0.0;
+        for (int j = 0; j < image->numRows; j++)
+        {
+            for (int i = 0; i < image->numCols; i++) {
+                xo += i*image->data.F32[j][i];
+                yo += j*image->data.F32[j][i];
+                no += image->data.F32[j][i];
+            }
+        }
+        xo /= no;
+        yo /= no;
+
+//        diag ("these require a tolerance of 100 epsilon");
+        is_float_tol (xo, 16.0, 100*FLT_EPSILON, "x-centroid should be %f : %f", 16.0, xo);
+        is_float_tol (xo, 16.0, 100*FLT_EPSILON, "y-centroid should be %f : %f", 16.0, yo);
+
+        // fractional shifts introduce smoothing,
+        psImage *shift = psImageShiftKernel (NULL, image, 0.2, 0.4, PS_INTERPOLATE_GAUSS);
+
+        // measure centroid of shifted gaussian (should be 17.2,14.8)
+        xo = yo = no = 0.0;
+        for (int j = 0; j < shift->numRows; j++)
+        {
+            for (int i = 0; i < shift->numCols; i++) {
+                xo += i*shift->data.F32[j][i];
+                yo += j*shift->data.F32[j][i];
+                no += shift->data.F32[j][i];
+            }
+        }
+        xo /= no;
+        yo /= no;
+
+//        diag ("these require a tolerance of 100 epsilon");
+        is_float_tol (xo, 16.2, 100*FLT_EPSILON, "x-centroid should be %f : %f", 16.2, xo);
+        is_float_tol (yo, 15.8, 100*FLT_EPSILON, "y-centroid should be %f : %f", 15.8, yo);
+
+        psFits *fits = psFitsOpen ("gauss.fits", "w");
+        psFitsWriteImage (fits, NULL, image, 0, NULL);
+        psFitsClose (fits);
+
+        fits = psFitsOpen ("shift.fits", "w");
+        psFitsWriteImage (fits, NULL, shift, 0, NULL);
+        psFitsClose (fits);
+
+        psFree(shift);
+        psFree(image);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    return exit_status();
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageSmooth.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageSmooth.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageSmooth.c	(revision 22158)
@@ -0,0 +1,165 @@
+/** @file  tst_psImageConvolve.c
+ *
+ *  This code will test the psImageSmooth() routine.
+ *
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-02-27 23:56:12 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define NUM_ROWS 20
+#define NUM_COLS 20
+#define SIGMA 1.0
+#define NSIGMA 5.0
+#define TS00_IM_NULL            0x00000001
+#define TS00_IM_F32             0x00000002
+#define TS00_IM_F64             0x00000004
+#define TS00_IM_S32             0x00000008
+#define VERBOSE 0
+
+static psBool testImageSmoothGeneric(
+    psU32 flags,
+    psS32 numCols,
+    psS32 numRows,
+    psF64 sigma,
+    psF64 Nsigma,
+    psBool expectedRC)
+{
+    psMemId id = psMemGetId();
+    psBool testStatus = true;
+    psImage *img = NULL;
+
+    if (VERBOSE) {
+        if (expectedRC == false) {
+            printf("This test should generate FALSE.\n");
+        } else {
+            printf("This test should generate TRUE.\n");
+        }
+    }
+
+    if (flags & TS00_IM_NULL) {
+        if (VERBOSE) printf("        using a NULL image\n");
+    }
+
+    if (flags & TS00_IM_F32) {
+        if (VERBOSE) printf("        using a psF32 image\n");
+        img = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+        // Set a checkboard pattern
+        for (psS32 i = 0 ; i < numRows ; i++) {
+            for (psS32 j = 0 ; j < numCols ; j++) {
+                if ((i%2) != (j%2)) {
+                    img->data.F32[i][j] = 1.0;
+                } else {
+                    img->data.F32[i][j] = 0.0;
+                }
+            }
+        }
+    }
+    if (VERBOSE) {
+        p_psImagePrint(1, img, "The Smoothed Image");
+    }
+
+    if (flags & TS00_IM_F64) {
+        if (VERBOSE)
+            printf("        using a psF64 image\n");
+        img = psImageAlloc(numCols, numRows, PS_TYPE_F64);
+        // Set a checkboard pattern
+        for (psS32 i = 0 ; i < numRows ; i++) {
+            for (psS32 j = 0 ; j < numCols ; j++) {
+                if ((i%2) != (j%2)) {
+                    img->data.F64[i][j] = 1.0;
+                } else {
+                    img->data.F64[i][j] = 0.0;
+                }
+            }
+        }
+    }
+
+    if (flags & TS00_IM_S32) {
+        if (VERBOSE)
+            printf("        using a psS32 image\n");
+        img = psImageAlloc(numCols, numRows, PS_TYPE_S32);
+        // Set a checkboard pattern
+        for (psS32 i = 0 ; i < numRows ; i++) {
+            for (psS32 j = 0 ; j < numCols ; j++) {
+                if ((i%2) != (j%2)) {
+                    img->data.S32[i][j] = 1;
+                } else {
+                    img->data.S32[i][j] = 0;
+                }
+            }
+        }
+    }
+    if (VERBOSE) {
+        printf(" %d columns\n", numCols);
+        printf(" %d rows\n", numRows);
+        printf(" sigma is %.2f\n", sigma);
+        printf(" Nsigma is %.2f\n", Nsigma);
+    }
+
+    psBool rc = psImageSmooth(img, sigma, Nsigma);
+    if (rc == false) {
+        if (expectedRC == true) {
+            diag("TEST ERROR: psImageSmooth returned FALSE\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            diag("TEST ERROR: psImageSmooth returned TRUE\n");
+            testStatus = false;
+        }
+        if (VERBOSE) {
+            p_psImagePrint(1, img, "The Smoothed Image");
+        }
+
+        if (flags & TS00_IM_F32) {
+            for (psS32 i = 1 ; i < numRows-1 ; i++) {
+                for (psS32 j = 1 ; j < numCols-1 ; j++) {
+                    if ((fabs(img->data.F32[i][j] - 0.5) > 0.1)) {
+                        diag("TEST ERROR: img[%d][%d] was %f, expected 0.5\n",
+                             i, j, img->data.F32[i][j]);
+                        testStatus = false;
+                    }
+                }
+            }
+        }
+
+        if (flags & TS00_IM_F64) {
+            for (psS32 i = 1 ; i < numRows-1 ; i++) {
+                for (psS32 j = 1 ; j < numCols-1 ; j++) {
+                    if ((fabs(img->data.F64[i][j] - 0.5) > 0.1)) {
+                        diag("TEST ERROR: img[%d][%d] was %f, expected 0.5\n",
+                             i, j, img->data.F64[i][j]);
+                        testStatus = false;
+                    }
+                }
+            }
+        }
+    }
+    psFree(img);
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    return(testStatus);
+}
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(14);
+
+    ok(testImageSmoothGeneric(TS00_IM_F32, NUM_COLS, NUM_ROWS, SIGMA, NSIGMA, true), "testImageSmoothGeneric() successful");
+    ok(testImageSmoothGeneric(TS00_IM_F32, 1, NUM_ROWS, SIGMA, NSIGMA, true), "testImageSmoothGeneric() successful");
+    ok(testImageSmoothGeneric(TS00_IM_F32, NUM_COLS, 1, SIGMA, NSIGMA, true), "testImageSmoothGeneric() successful");
+    ok(testImageSmoothGeneric(TS00_IM_F32, 1, 1, SIGMA, NSIGMA, true), "testImageSmoothGeneric() successful");
+    ok(testImageSmoothGeneric(TS00_IM_F64, NUM_COLS, NUM_ROWS, SIGMA, NSIGMA, true), "testImageSmoothGeneric() successful");
+    ok(testImageSmoothGeneric(TS00_IM_S32, NUM_COLS, NUM_ROWS, SIGMA, NSIGMA, false), "testImageSmoothGeneric() successful");
+    ok(testImageSmoothGeneric(TS00_IM_NULL, NUM_COLS, NUM_ROWS, SIGMA, NSIGMA, false), "testImageSmoothGeneric() successful");
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageStats.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageStats.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageStats.c	(revision 22158)
@@ -0,0 +1,615 @@
+/*
+*  C Implementation: %{MODULE}
+*
+* Description:
+*
+* XXX: Must do sub Region tests
+* XXX: Must do (1, N) and (N, 1) size tests
+*
+* Copyright: See COPYING file that comes with this distribution
+*
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+bool testInRegion(psRegion region, int row, int col)
+{
+    return(row >= region.y0 && row < region.y1 && col >= region.x0 && col < region.x1);
+}
+
+void genericImageCountPixelMaskTest(int numRows, int numCols)
+{
+    psMemId id = psMemGetId();
+
+    psRegion reg;
+    reg.x0 = 0;
+    reg.x1 = 0;
+    reg.y0 = 0;
+    reg.y1 = 0;
+    psImage *img = psImageAlloc(numRows, numCols, PS_TYPE_MASK);
+    int expNumPix = 0;
+    for (int i = 0 ; i < numRows ; i++) {
+        for (int j = 0 ; j < numCols ; j++) {
+            if (0 == i%2) {
+                img->data.PS_TYPE_MASK_DATA[i][j] = 1;
+                expNumPix++;
+            } else {
+                img->data.PS_TYPE_MASK_DATA[i][j] = 0;
+            }
+        }
+    }
+    psS32 numPix = psImageCountPixelMask(img, reg, 1);
+    ok(numPix == expNumPix, "psImageCountPixelMask() returned the correct number of pixels (no region)");
+
+    reg.x0 = numCols/4;
+    reg.x1 = 3 * numCols/4;
+    reg.y0 = numRows/4;
+    reg.y1 = 3 * numRows/4;
+    expNumPix = 0;
+    img->col0 = 0;
+    img->row0 = 0;
+    for (int i = 0 ; i < numRows ; i++) {
+        for (int j = 0 ; j < numCols ; j++) {
+            if (testInRegion(reg, i, j)) {
+                if (0 == i%2) {
+                    img->data.PS_TYPE_MASK_DATA[i][j] = 1;
+                    expNumPix++;
+                } else {
+                    img->data.PS_TYPE_MASK_DATA[i][j] = 0;
+                }
+            } else {
+                img->data.PS_TYPE_MASK_DATA[i][j] = 0;
+            }
+        }
+    }
+    numPix = psImageCountPixelMask(img, reg, 1);
+    ok(numPix == expNumPix, "psImageCountPixelMask() returned the correct number of pixels (with region)");
+    psFree(img);
+
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+}
+
+
+void genericImageStatsTest(int numRows, int numCols)
+{
+    psMemId id = psMemGetId();
+    psImage *img = psImageAlloc(numRows, numCols, PS_TYPE_F32);
+    psImage *msk = psImageAlloc(numRows, numCols, PS_TYPE_MASK);
+    psImage *imgSub = psImageSubset(img, psRegionSet(numRows/4, 3*numRows/4,
+                                    numCols/4, 3*numCols/4));
+    psImage *mskSub = psImageSubset(img, psRegionSet(numRows/4, 3*numRows/4,
+                                    numCols/4, 3*numCols/4));
+    float meanNoMask = 0.0;
+    float numPixelsNoMask = 0.0;
+    float meanMask = 0.0;
+    float numPixelsMask = 0.0;
+    for (int i = 0; i < numRows; i++) {
+        for (int j = 0; j < numRows; j++) {
+            if (0 == i%2) {
+                img->data.F32[i][j] = (float) (i + j);
+                msk->data.PS_TYPE_MASK_DATA[i][j] = 1;
+                meanNoMask+= img->data.F32[i][j];
+                numPixelsNoMask+= 1.0;
+            } else {
+                img->data.F32[i][j] = (float) (i + j + 100);
+                msk->data.PS_TYPE_MASK_DATA[i][j] = 0;
+                meanNoMask+= img->data.F32[i][j];
+                meanMask+= img->data.F32[i][j];
+                numPixelsMask+= 1.0;
+                numPixelsNoMask+= 1.0;
+            }
+        }
+    }
+    meanNoMask/= numPixelsNoMask;
+    meanMask/= numPixelsMask;
+    psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    psStats* tmpStats = myStats;
+
+    // Calculate Sample Mean with nomask
+    myStats = psImageStats(myStats, img, NULL, 0);
+    ok(myStats != NULL, "psImageStats() returned non-NULL");
+    ok(myStats == tmpStats, "psImageStats() returned the original psStats struct");
+    ok(fabs(myStats->sampleMean - meanNoMask) < .001, "psImageStats() calculated the mean correctly (no mask)");
+
+    // Calculate Sample Mean with mask
+    myStats = psImageStats(myStats, img, msk, 1);
+    ok(myStats != NULL, "psImageStats() returned non-NULL");
+    ok(fabs(myStats->sampleMean - meanMask) < .001, "psImageStats() calculated the mean correctly (with mask)");
+
+
+    // Repeat previous tests using the sub image
+    meanNoMask = 0.0;
+    numPixelsNoMask = 0.0;
+    meanMask = 0.0;
+    numPixelsMask = 0.0;
+    for (int i = 0; i < imgSub->numRows; i++) {
+        for (int j = 0; j < imgSub->numRows; j++) {
+            if (0 == i%2) {
+                imgSub->data.F32[i][j] = (float) (i + j);
+                mskSub->data.PS_TYPE_MASK_DATA[i][j] = 1;
+                meanNoMask+= imgSub->data.F32[i][j];
+                numPixelsNoMask+= 1.0;
+            } else {
+                imgSub->data.F32[i][j] = (float) (i + j + 100);
+                mskSub->data.PS_TYPE_MASK_DATA[i][j] = 0;
+                meanNoMask+= imgSub->data.F32[i][j];
+                meanMask+= imgSub->data.F32[i][j];
+                numPixelsMask+= 1.0;
+                numPixelsNoMask+= 1.0;
+            }
+        }
+    }
+    meanNoMask/= numPixelsNoMask;
+    meanMask/= numPixelsMask;
+    tmpStats = myStats;
+
+    // Calculate Sample Mean with nomask (sub image)
+    // XXXX: We skip these tests because they seg-fault.  Not sure if the source
+    // is wrong or the tests are.
+    ok(false, "XXXX: skipping psImageStats() tests on a subRegion because of seg faults");
+    if (0) {
+        myStats = psImageStats(myStats, imgSub, NULL, 0);
+        ok(myStats != NULL, "psImageStats() returned non-NULL");
+        ok(myStats == tmpStats, "psImageStats() returned the original psStats struct");
+        ok(fabs(myStats->sampleMean - meanNoMask) < .001, "psImageStats() calculated the mean correctly (no mask) (subImage)");
+        printf("Expected %f, got %f\n", meanNoMask, myStats->sampleMean);
+
+        // Calculate Sample Mean with mask (sub image)
+        myStats = psImageStats(myStats, imgSub, mskSub, 1);
+        ok(myStats != NULL, "psImageStats() returned non-NULL");
+        ok(fabs(myStats->sampleMean - meanMask) < .001, "psImageStats() calculated the mean correctly (with mask) (subImage)");
+    }
+
+    psFree(myStats);
+    psFree(img);
+    psFree(msk);
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+}
+
+
+#define I_POLY(X, Y) ((A) + (B * X) + (C * Y) + (D * X * Y) + (E * X * X) + (F * Y * Y))
+
+void genericFitChebyF32Test(int numCols, int numRows)
+{
+    psMemId id = psMemGetId();
+    const double A = 1.0;
+    const double B = 2.0;
+    const double C = 3.0;
+    const double D = 4.0;
+    const double E = 5.0;
+    const double F = 6.0;
+    const double ERROR_TOL = 0.1;
+    psImage *tmpImage = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    psImage *outImage = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    for (int i=0;i<numRows;i++) {
+        for (int j=0;j<numCols;j++) {
+            tmpImage->data.F32[i][j] = I_POLY(((float) i), ((float) j));
+        }
+    }
+
+    psPolynomial2D *chebys = psPolynomial2DAlloc(PS_POLYNOMIAL_CHEB, 5, 5);
+    skip_start(chebys == NULL, 5, "Skipping tests because psPolynomial2DAlloc() returned NULL");
+    psPolynomial2D *chebys2 = psImageFitPolynomial(chebys, tmpImage);
+    ok(chebys2 != NULL, "psImageFitPolynomial() returned non-NULL");
+    ok(chebys2 == chebys, "psImageFitPolynomial() correctly recylced polynomial input");
+    psImage *outImage2 = psImageEvalPolynomial(outImage, chebys);
+    ok(outImage2 != NULL, "psImageEvalPolynomial() returned non-NULL");
+    ok(outImage2 == outImage, "psImageEvalPolynomial() correctly recylced input image");
+
+    bool errorFlag = false;
+    for (int i=1 ; i < numRows ; i++) {
+        for (int j=0 ; j < numCols ; j++) {
+            float expect = tmpImage->data.F32[i][j];
+            float actual = outImage->data.F32[i][j];
+            if (fabs((actual - expect) / expect) > ERROR_TOL) {
+                diag("ERROR: pixel [%d][%d] is %.2f should be %.2f\n", i, j, actual, expect);
+                errorFlag = true;
+            }
+        }
+    }
+    ok(!errorFlag, "psImageFitPolynomial() and psImageEvalPolynomial() produced the correct results (F32)");
+    skip_end();
+    psFree(tmpImage);
+    psFree(outImage);
+    psFree(chebys);
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+}
+
+void genericFitChebyF64Test(int numCols, int numRows)
+{
+    psMemId id = psMemGetId();
+    const double A = 1.0;
+    const double B = 2.0;
+    const double C = 3.0;
+    const double D = 4.0;
+    const double E = 5.0;
+    const double F = 6.0;
+    const double ERROR_TOL = 0.1;
+    psImage *tmpImage = psImageAlloc(numCols, numRows, PS_TYPE_F64);
+    psImage *outImage = psImageAlloc(numCols, numRows, PS_TYPE_F64);
+    for (int i=0;i<numRows;i++) {
+        for (int j=0;j<numCols;j++) {
+            tmpImage->data.F64[i][j] = I_POLY(((float) i), ((float) j));
+        }
+    }
+
+    psPolynomial2D *chebys = psPolynomial2DAlloc(PS_POLYNOMIAL_CHEB, 5, 5);
+    skip_start(chebys == NULL, 5, "Skipping tests because psPolynomial2DAlloc() returned NULL");
+    psPolynomial2D *chebys2 = psImageFitPolynomial(chebys, tmpImage);
+    ok(chebys2 != NULL, "psImageFitPolynomial() returned non-NULL");
+    ok(chebys2 == chebys, "psImageFitPolynomial() correctly recylced polynomial input");
+    psImage *outImage2 = psImageEvalPolynomial(outImage, chebys);
+    ok(outImage2 != NULL, "psImageEvalPolynomial() returned non-NULL");
+    ok(outImage2 == outImage, "psImageEvalPolynomial() correctly recylced input image");
+
+    bool errorFlag = false;
+    for (int i=1 ; i < numRows ; i++) {
+        for (int j=0 ; j < numCols ; j++) {
+            psF64 expect = tmpImage->data.F64[i][j];
+            psF64 actual = outImage->data.F64[i][j];
+            if (fabs((actual - expect) / expect) > ERROR_TOL) {
+                diag("ERROR: pixel [%d][%d] is %.2f should be %.2f\n", i, j, actual, expect);
+                errorFlag = true;
+            }
+        }
+    }
+    ok(!errorFlag, "psImageFitPolynomial() and psImageEvalPolynomial() produced the correct results (F64)");
+    skip_end();
+    psFree(tmpImage);
+    psFree(outImage);
+    psFree(chebys);
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+}
+
+
+void testPsImageFitPolynomial()
+{
+    psMemId id = psMemGetId();
+    const int IMAGE_SIZE = 16;
+    const int CHEBY_X_DIM = 8;
+    const int CHEBY_Y_DIM = 8;
+    const int THRESHOLD = 1;
+    psImage *imgIn = psImageAlloc(IMAGE_SIZE, IMAGE_SIZE, PS_TYPE_F32);
+    psImage *imgOut = psImageAlloc(IMAGE_SIZE, IMAGE_SIZE, PS_TYPE_F32);
+    for (int i = 0;i < IMAGE_SIZE;i++) {
+        for (int j = 0;j < IMAGE_SIZE;j++) {
+            imgIn->data.F32[ i ][ j ] = 4.0;
+            imgIn->data.F32[ i ][ j ] = (float) (i + j);
+            imgIn->data.F32[ i ][ j ] = (float) (i + j) + (4.0 * (float) i);
+            imgOut->data.F32[ i ][ j ] = 0.0;
+        }
+    }
+    psPolynomial2D *my2DPoly = psPolynomial2DAlloc(PS_POLYNOMIAL_CHEB, CHEBY_X_DIM-1, CHEBY_Y_DIM-1);
+    my2DPoly = psImageFitPolynomial(my2DPoly, imgIn);
+    ok(my2DPoly != NULL, "psImageFitPolynomial() returned non-NULL");
+
+    imgOut = psImageEvalPolynomial(imgOut, my2DPoly);
+    bool errorFlag = false;
+    for (int i = 0;i < IMAGE_SIZE;i++) {
+        for (int j = 0;j < IMAGE_SIZE;j++) {
+            if (fabs(imgOut->data.F32[ i ][ j ] - imgIn->data.F32[ i ][ j ]) > THRESHOLD) {
+                diag("Pixel (%d, %d) is %.2f, should be %.2f\n", i, j,
+                     imgOut->data.F32[ i ][ j ],
+                     imgIn->data.F32[ i ][ j ]);
+                errorFlag = true;
+            }
+
+        }
+    }
+    ok(!errorFlag, "psImageFitPolynomial() and psImageEvalPolynomial() produced the correct result");
+    psFree(imgIn);
+    psFree(imgOut);
+    psFree(my2DPoly);
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+}
+
+void genericpsImageHistogramTest(int numRows, int numCols, int numBins)
+{
+    if ((0 != numRows%4) ||
+        (0 != numRows%numBins) ||
+        (0 != numBins%2)) {
+        ok(false, "numRows must be a multiple of 4, and must be a integer multiple of numBins");
+    }
+
+    psImage *img = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    psImage *msk = psImageAlloc(numCols, numRows, PS_TYPE_MASK);
+    // XXX: Do subRegion tests later
+//    psImage *imgSub = psImageSubset(img, psRegionSet(numRows/4, 3*numRows/4,
+//                                    numCols/4, 3*numCols/4));
+//    psImage *mskSub = psImageSubset(img, psRegionSet(numRows/4, 3*numRows/4,
+//                                    numCols/4, 3*numCols/4));
+    for (int i = 0; i < numRows; i++) {
+        for (int j = 0; j < numCols; j++) {
+            img->data.F32[i][j] = 0.4 + (float) (i);
+            if (i >= numRows/2) {
+                msk->data.PS_TYPE_MASK_DATA[i][j] = 1;
+            } else {
+                msk->data.PS_TYPE_MASK_DATA[i][j] = 0;
+            }
+        }
+    }
+
+    if (0) {
+        for (int i = 0; i < numRows; i++) {
+            for (int j = 0; j < numCols; j++) {
+                printf("(%.1f) ", img->data.F32[i][j]);
+            }
+            printf("\n");
+        }
+        for (int i = 0; i < numRows; i++) {
+            for (int j = 0; j < numCols; j++) {
+                printf("(%d) ", msk->data.PS_TYPE_MASK_DATA[i][j]);
+            }
+            printf("\n");
+        }
+    }
+    
+    // Calculate Histogram with no mask
+    {
+        psMemId id = psMemGetId();
+        psHistogram *hist = psHistogramAlloc(0.0, (float) (numRows), numBins);
+        psHistogram *hist2 = psImageHistogram(hist, img, NULL, 0);
+        ok(hist2 != NULL, "psImageHistogram() returned non-NULL");
+        skip_start(hist2 == NULL, 1, "Skipping tests because psImageHistogram() returned NULL");
+        ok(hist2 == hist, "psImageHistogram() correctly recycled the input psHistogram");
+        bool errorFlag = false;
+        for (int i = 0;i < numBins;i++) {
+            if (hist2->nums->data.F32[i] != (numCols * (numRows/numBins))) {
+                diag("ERROR: Bin number %d bounds: (%.1f - %.1f) data (%.2f)\n", i,
+                      hist2->bounds->data.F32[i],
+                      hist2->bounds->data.F32[i+1],
+                      hist2->nums->data.F32[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psImageHistogram() produced the correct results (no mask)");
+        skip_end();
+        psFree(hist);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Calculate Histogram with mask
+    {
+        psMemId id = psMemGetId();
+        psHistogram *hist = psHistogramAlloc(0.0, (float) (numRows), numBins);
+        psHistogram *hist2 = psImageHistogram(hist, img, msk, 1);
+        ok(hist2 != NULL, "psImageHistogram() returned non-NULL");
+        skip_start(hist2 == NULL, 1, "Skipping tests because psImageHistogram() returned NULL");
+        ok(hist2 == hist, "psImageHistogram() correctly recycled the input psHistogram");
+        bool errorFlag = false;
+        for (int i = 0 ; i < numBins ; i++) {
+            if (i < numBins/2) {
+                if (hist2->nums->data.F32[i] != (numCols * (numRows/numBins))) {
+                    diag("ERROR: Bin number %d bounds: (%.1f - %.1f) data (%.2f)\n", i,
+                          hist2->bounds->data.F32[i],
+                          hist2->bounds->data.F32[i+1],
+                          hist2->nums->data.F32[i]);
+                    errorFlag = true;
+                }
+            } else {
+                if (hist2->nums->data.F32[i] != 0) {
+                    diag("ERROR: Bin number %d bounds: (%.1f - %.1f) data (%.2f)\n", i,
+                          hist2->bounds->data.F32[i],
+                          hist2->bounds->data.F32[i+1],
+                          hist2->nums->data.F32[i]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageHistogram() produced the correct results (no mask)");
+        skip_end();
+        psFree(hist);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    psFree(img);
+    psFree(msk);
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(58);
+
+    // --------------------------------------------------------------
+    // psImageCountPixelMask()
+    // Ensure psImageCountPixelMask returns -1 for NULL input image
+    // Following should generate error
+    // XXX: Verify error
+    {
+        psMemId id = psMemGetId();
+        psRegion reg;
+        reg.x0 = 0;
+        reg.x1 = 1;
+        reg.y0 = 0;
+        reg.y1 = 4;
+        psS32 numPix = psImageCountPixelMask(NULL, reg, 1);
+        ok(numPix == -1, "psImageCountPixelMask() returned -1 for NULL input image");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Ensure psImageCountPixelMask returns -1 for wrong input image type
+    // Following should generate error
+    // XXX: Verify error
+    {
+        psMemId id = psMemGetId();
+        psImage *in = psImageAlloc(16, 16, PS_TYPE_F32);
+        psRegion reg;
+        reg.x0 = 0;
+        reg.x1 = 1;
+        reg.y0 = 0;
+        reg.y1 = 4;
+        psS32 numPix = psImageCountPixelMask(in, reg, 1);
+        ok(numPix == -1, "psImageCountPixelMask() returned -1 for incorrect input image type");
+        psFree(in);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Ensure psImageCountPixelMask returns -1 for bad region
+    // Following should generate error
+    // XXX: Verify error
+    {
+        psMemId id = psMemGetId();
+        psImage *in = psImageAlloc(16, 16, PS_TYPE_MASK);
+        psRegion reg;
+        reg.x0 = -1;
+        reg.x1 = 0;
+        reg.y0 = 0;
+        reg.y1 = 0;
+        psS32 numPix = psImageCountPixelMask(in, reg, 1);
+        ok(numPix == -1, "psImageCountPixelMask() returned -1 for bad region x0");
+        reg.x0 = 0;
+        reg.y0 = -1;
+        numPix = psImageCountPixelMask(in, reg, 1);
+        ok(numPix == -1, "psImageCountPixelMask() returned -1 for bad region y0");
+        // XXX: Should this fail?
+        if (0) {
+            reg.x0 = 1;
+            reg.x1 = 1;
+            reg.y0 = 1;
+            reg.y1 = 1;
+            numPix = psImageCountPixelMask(in, reg, 1);
+            ok(numPix == -1, "psImageCountPixelMask() returned -1 for bad region ");
+        }
+        psFree(in);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    genericImageCountPixelMaskTest(10, 10);
+
+
+
+    // --------------------------------------------------------------
+    // psImageStats()
+    // Ensure psImageStats() returns NULL for NULL input image
+    // Following should generate error
+    // XXX: Verify error
+    {
+        psMemId id = psMemGetId();
+        psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        psStats *myStats2 = psImageStats(myStats, NULL, NULL, 0);
+        ok(myStats2 == NULL, "psImageStats() returned NULL with NULL input image");
+        psFree(myStats);
+        psFree(myStats2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Ensure psImageStats() returns NULL for NULL psStats
+    // Following should generate error
+    // XXX: Verify error
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(10, 10, PS_TYPE_F32);
+        psStats *myStats = psImageStats(NULL, img, NULL, 0);
+        ok(myStats == NULL, "psImageStats() returned NULL with NULL psStats arg");
+        psFree(img);
+        psFree(myStats);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    genericImageStatsTest(10, 10);
+
+
+
+    // --------------------------------------------------------------
+    // psImageFitPolynomial() and psImageEvalPolynomial()
+    // Following should be an error message for NULL coeffs argument
+    // XXX: Verify error
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(10, 10, PS_TYPE_F32);
+        psImage *img2 = psImageEvalPolynomial(img, NULL);
+        ok(img2 == NULL, "psImageEvalPolynomial() returned NULL with NULL coeffs argument");
+        psFree(img);
+        psFree(img2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Following should be a error message for NULL input argument
+    // XXX: Verify error
+    {
+        psMemId id = psMemGetId();
+        psPolynomial2D *poly2D = psPolynomial2DAlloc(PS_POLYNOMIAL_CHEB, 5, 5);
+        psImage *img = psImageEvalPolynomial(NULL, poly2D);
+        ok(img == NULL, "psImageEvalPolynomial() returned NULL with NULL input image");
+        psFree(img);
+        psFree(poly2D);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Following should be an error message for NULL coeffs argument
+    // XXX: Verify error
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(10, 10, PS_TYPE_F32);
+        psPolynomial2D *poly2D = psImageFitPolynomial(NULL, img);
+        ok(poly2D == NULL, "psImageFitPolynomial() returned a NULL with NULL coeffs arg");
+        psFree(img);
+        psFree(poly2D);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Following should be a error message for NULL input argument
+    // XXX: Verify error
+    {
+        psMemId id = psMemGetId();
+        psPolynomial2D *poly2D = psPolynomial2DAlloc(PS_POLYNOMIAL_CHEB, 5, 5);
+        psPolynomial2D *poly2D2 = psImageFitPolynomial(poly2D, NULL);
+        ok(poly2D2 == NULL, "psImageFitPolynomial() returned a NULL with NULL input image");
+        psFree(poly2D);
+        psFree(poly2D2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    genericFitChebyF32Test(10, 10);
+    genericFitChebyF64Test(10, 10);
+    // XXX: This next test is not necessary.  Previous two functions make it redundant.
+    testPsImageFitPolynomial();
+
+
+
+    // --------------------------------------------------------------
+    // psImageHistogram()
+    // Following should be a error message for NULL psHistogram argument
+    // XXX: Verify error
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(10, 10, PS_TYPE_F32);
+        psHistogram *hist = psImageHistogram(NULL, img, NULL, 0);
+        ok(hist == NULL, "psImageHistogram() returned NULL for NULL psHistogram arg");
+        psFree(img);
+        psFree(hist);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Following should be a error message for NULL psImage argument
+    // XXX: Verify error
+    {
+        psMemId id = psMemGetId();
+        psHistogram *hist = psHistogramAlloc(0.0, 100000.0, 1000);
+        psHistogram *hist2 = psImageHistogram(hist, NULL, NULL, 0);
+        ok(hist2 == NULL, "psImageHistogram() returned NULL for NULL psHistogram arg");
+        psFree(hist);
+        psFree(hist2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Following should be a error message for incorrect mask type
+    // XXX: Verify error
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(10, 10, PS_TYPE_F32);
+        psHistogram *hist = psHistogramAlloc(0.0, 100000.0, 1000);
+        psImage *msk = psImageAlloc(10, 10, PS_TYPE_S8);
+        psHistogram *hist2 = psImageHistogram(hist, img, msk, 1);
+        ok(hist2 == NULL, "psImageHistogram() returned NULL for incorrect mask type");
+        psFree(hist);
+        psFree(hist2);
+        psFree(img);
+        psFree(msk);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    genericpsImageHistogramTest(16, 15, 4);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageStructManip.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageStructManip.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tap_psImageStructManip.c	(revision 22158)
@@ -0,0 +1,523 @@
+/** @file  tap_psImageStructManip.c
+*
+*  @brief Contains the tests for psImageExtraction.[ch]
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  psLib functions tested:
+*     psImageSubset()
+*     psImageCopy()
+*     psImageTrim()
+*
+*  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-09-20 23:56:10 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+
+void genericImageSubsetTest(int numRows, int numCols)
+{
+    // psImageSubset shall create child image of a specified size from a
+    // parent psImage structure
+    // psImageSubset()
+    {
+        psMemId id = psMemGetId();
+        psImage preSubsetStruct;
+        psRegion region1 = psRegionSet(0, numCols/2, 0, numRows/2);
+        psRegion region2 = psRegionSet(numCols/4, numCols/4+numCols/2, numRows/4, numRows/4+numRows/2);
+
+	// test basic subset creation 
+	{ 
+	    psImage* original = psImageAlloc(numCols,numRows,PS_TYPE_U32);
+	    for (psS32 row=0;row<numRows;row++) {
+		for (psS32 col=0;col<numCols;col++) {
+		    original->data.F32[row][col] = row*1000+col;
+		}
+	    }
+
+	    // XXX this is not being used in this section
+	    memcpy(&preSubsetStruct, original, sizeof(psImage));
+	    psImage* subset1 = psImageSubset(original, region2);
+	    ok(subset1, "psImageSubset() returned non-NULL (subset1)");
+	    skip_start(subset1 == NULL, 25, "Skipping tests because psImageSubset() returned NULL");
+	    psImage* subset2 = psImageSubset(original, region1);
+	    ok(subset2, "psImageSubset() returned non-NULL (subset2)");
+	    skip_start(subset2 == NULL, 24, "Skipping tests because psImageSubset() returned NULL");
+
+	    // Verify the returned psImage structure members nrow and ncol are equal to
+	    // the input parameter nrow and ncol respectively
+	    ok(subset1->numCols == numCols/2 && subset1->numRows == numRows/2,
+	       "psImageSubset output size set properly");
+	    ok(subset2->numCols == numCols/2 && subset2->numRows == numRows/2,
+	       "psImageSubset output size set properly");
+
+	    // Verify the returned psImage structure contains expected values in the
+	    // row member, if the input psImage structure image contains known values
+	    bool errorFlag = false;
+	    for (psS32 row=0;row<numRows/2;row++) {
+		for (psS32 col=0;col<numCols/2;col++) {
+		    if (subset1->data.U32[row][col] != original->data.U32[row+numRows/4][col+numCols/4]) {
+			diag("psImageSubset output #1 was wrong at %dx%d (%d vs %d).",
+			     row,col,subset1->data.U32[row][col], original->data.U32[row+numRows/4][col+numCols/4]);
+			errorFlag = true;
+		    }
+		    if (subset2->data.U32[row][col] != original->data.U32[row][col]) {
+			diag("psImageSubset output #1 was wrong at %dx%d (%d vs %d).",
+			     row,col,subset1->data.U32[row][col], original->data.U32[row][col]);
+			errorFlag = true;
+		    }
+		}
+	    }
+	    ok(!errorFlag, "psImageSubset() produced the expected values");
+
+	    // Verify the returned psImage structure member type is equal to the input
+	    // psImage structure member type
+	    ok(subset1->type.type == PS_TYPE_U32, "psImageSubset() type was correct (subset1)");
+	    ok(subset2->type.type == PS_TYPE_U32, "psImageSubset() type was correct (subset2)");
+
+	    // Verify the returned psImage structure members row0 and col0 are equal to
+	    // the input parameters row0 and col0 respectively
+	    ok(subset1->col0 == numCols/4 && subset1->row0 == numRows/4,
+	       "psImageSubset() set col0/row0 correctly (subset1)");
+	    ok(subset2->col0 == 0 && subset2->row0 == 0,
+	       "psImageSubset() set col0/row0 correctly (subset2)");
+
+	    // Verify the returned psImage structure member parent is equal to the
+	    // input psImage structure pointer image
+	    ok(subset1->parent == original && subset2->parent == original, "psImageSubset() set ->parent correctly");
+
+	    // Verify the returned psImage structure member children is null
+	    ok(subset1->children == NULL && subset2->children == NULL, "psImageSubset() set ->children correctly");
+
+	    // Verify the input psImage structure image only has the following members
+	    // changed: 1) Nchildren is increased by one. 2) parent contains pointer psImage structure
+	    // out at parent[Nchildren-1]
+	    ok(original->children != NULL && original->children->n == 2, "psImageSubset did increment number of children by one per subset.");
+	    ok(original->children->data[0] == subset1 && original->children->data[1] == subset2,
+	       "psImageSubset did properly store the children pointers.");
+
+	    psFree (subset1);
+	    psFree (subset2);
+	    skip_end();
+	    skip_end();
+	    psFree (original);
+	}
+
+	// test free in reverse order from above
+	{ 
+	    psImage* original = psImageAlloc(numCols,numRows,PS_TYPE_U32);
+	    for (psS32 row=0;row<numRows;row++) {
+		for (psS32 col=0;col<numCols;col++) {
+		    original->data.F32[row][col] = row*1000+col;
+		}
+	    }
+
+	    // XXX this is not being used in this section
+	    memcpy(&preSubsetStruct, original, sizeof(psImage));
+	    psImage* subset1 = psImageSubset(original, region2);
+	    ok(subset1, "psImageSubset() returned non-NULL (subset1)");
+	    psImage* subset2 = psImageSubset(original, region1);
+	    ok(subset2, "psImageSubset() returned non-NULL (subset2)");
+
+	    psFree (original);
+	    psFree (subset1);
+	    psFree (subset2);
+	}
+
+	{
+	    psImage* original = psImageAlloc(numCols,numRows,PS_TYPE_U32);
+	    for (psS32 row=0;row<numRows;row++) {
+		for (psS32 col=0;col<numCols;col++) {
+		    original->data.F32[row][col] = row*1000+col;
+		}
+	    }
+
+	    // XXX this is not being used in this section
+	    memcpy(&preSubsetStruct, original, sizeof(psImage));
+
+	    // Verify the returned psImage structure pointer is null and program
+	    // execution doesn't stop, if the input parameter image is null.
+	    // Also verified the input psImage structure is not modified
+	    // An error should follow...
+	    // XXX: Verify error
+	    psImage* subset1 = psImageSubset(NULL,region1);
+	    ok(subset1 == NULL, "psImageSubset returned NULL when input image was NULL.");
+
+	    // Verify the returned psImage structure pointer is null and program
+	    // execution doesn't stop, if the input parameters nrow and/or ncol are zero.
+	    // Also verify input psImage structure is not modified
+	    // An error should follow...
+	    // XXX: Verify error
+	    {
+		memcpy(&preSubsetStruct,original,sizeof(psImage));
+		subset1 = psImageSubset(original, psRegionSet(0,numCols/2,numRows/2,numRows/2));
+		ok(subset1 == NULL, "psImageSubset returned NULL when numRows=0.");
+		// An error should follow...
+		// XXX: Verify error
+		subset1 = psImageSubset(original,psRegionSet(numCols/2,numCols/2,0,numRows/2));
+		ok(subset1 == NULL, "psImageSubset returned NULL when numCols=0.");
+		ok(memcmp(original,&preSubsetStruct,sizeof(psImage)) == 0,
+		   "psImageSubset didn't change the original struct though it failed to subset.");
+	    }
+
+	    // Verify the returned psImage structure pointer is null and program
+	    // execution doesn't stop, if the input parameters row0 and col0 are not within
+	    // the range of values of psImage structure image
+	    // An error should follow...
+	    // XXX: Verify error
+	    {
+		subset1 = psImageSubset(original, psRegionSet(0,numCols/2, 0,numRows*2));
+		ok(subset1 == NULL,
+		   "psImageSubset returned NULL when subset origin was outside of image (via cols)");
+		// An error should follow...
+		// XXX: Verify error
+		subset1 = psImageSubset(original,psRegionSet(0,numCols*2,0,numRows/2));
+		ok(subset1 == NULL,
+		   "psImageSubset returned NULL when subset origin was outside of image (via rows)");
+		// An error should follow...
+		// XXX: Verify error
+		subset1 = psImageSubset(original, psRegionSet(-1,numCols/2,0,numRows/2));
+		ok(subset1 == NULL,
+		   "psImageSubset returned NULL when subset origin was outside of image (col0=-1)");
+		// An error should follow...
+		// XXX: Verify error
+		subset1 = psImageSubset(original, psRegionSet(0,numCols/2,-1,numRows/2));
+		ok(subset1 == NULL,
+		   "psImageSubset returned NULL when subset origin was outside of image (row0=-1)");
+	    }    
+
+	    // Verify the returned psImage structure pointer is null and program
+	    // execution doesn't stop if the input parameters nrow, ncol, row0 and col0
+	    // specify a range of data not within the input psImage structure image.  Also
+	    // verify the input psImage structure is not modified
+	    // An error should follow...
+	    // XXX: Verify error
+	    {
+		subset1 = psImageSubset(original,psRegionSet(0,numCols/2,0,numRows+1));
+		ok(subset1 == NULL,
+		   "psImageSubset returned NULL when subset was outside of image (via rows)");
+		// An error should follow...
+		// XXX: Verify error
+		subset1 = psImageSubset(original, psRegionSet(0,numCols+1,0,numRows/2));
+		ok(subset1 == NULL,
+		   "psImageSubset returned NULL when subset was outside of image (via cols)");
+		// An error should follow...
+		// XXX: Verify error
+		subset1 = psImageSubset(original,psRegionSet(0,numCols+1,0,numRows+1));
+		ok(subset1 == NULL,
+		   "psImageSubset returned NULL when subset was outside of image (via row+cols)");
+	    }
+	    psFree(original);
+	}
+        ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+    }
+}
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(239);
+
+    genericImageSubsetTest(128, 256);
+    genericImageSubsetTest(256, 128);
+    genericImageSubsetTest(128, 128);
+
+    // psImageCopy()
+    {
+        psMemId id = psMemGetId();
+        psU32 c = 128;
+        psU32 r = 256;
+
+        psImage *img = psImageAlloc(c,r,PS_TYPE_F32);
+        for (unsigned row=0;row<r;row++) {
+            for (unsigned col=0;col<c;col++) {
+                img->data.F32[row][col] = (psF32)(row+col);
+            }
+        }
+        psImage *img2 = psImageAlloc(c,r,PS_TYPE_F32);
+        for (unsigned row=0;row<r;row++) {
+            for (unsigned col=0;col<c;col++) {
+                img2->data.F32[row][col] = 0.0f;
+            }
+        }
+
+        psImage *img3 = psImageCopy(img2,img,PS_TYPE_F32);
+        // Verify the returned psImage structure pointer is equal to the input
+        // parameter output.
+        ok(img2 == img3, "psImageCopy(): recycled input image");
+
+        // Verify the returned psImage structure is the same type as the input image
+        // structure if the specified output argument is NULL.
+        psImage *img4 = psImageCopy(NULL,img,PS_TYPE_F32);
+        ok(img4 != NULL, "psImageCopy() returned non-NULL with NULL output argument");
+        ok(img4->type.type == img->type.type, "psImageCopy() set the correct image type");
+        bool errorFlag = false;
+        for (psU32 row=0;row<r;row++) {
+            psF32* imgInRow = img->data.F32[row];
+            psF32* imgOutRow = img4->data.F32[row];
+            for (unsigned col=0;col<c;col++) {
+                if(imgInRow[col] != imgOutRow[col]) {
+                    diag("Input image not equal to output image at %d,%d", col, row);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageCopy() set data correctly");
+
+
+        // Verify the returned psImage structure member are equal to the values in
+        // the input psImage structure input.
+        #define testImageCopyType(IN,OUT) \
+        { \
+            bool errorFlag = false; \
+            img = psImageRecycle(img,c,r,PS_TYPE_##IN); \
+            for (unsigned row=0;row<r;row++) { \
+                ps##IN* imgRow = img->data.IN[row]; \
+                for (unsigned col=0;col<c;col++) { \
+                    imgRow[col] = (ps##IN)(row+col); \
+                } \
+            } \
+            img2 = psImageCopy(img2,img,PS_TYPE_##OUT); \
+            if(img2 != NULL) { \
+                ok(img2, "psImageCopy() returned non-NULL"); \
+                for (psU32 row=0;row<r;row++) { \
+                    ps##IN* imgRow = img->data.IN[row]; \
+                    ps##OUT* img2Row = img2->data.OUT[row]; \
+                    for (psU32 col=0;col<c;col++) { \
+                        if (abs(imgRow[col] - (ps##IN)(row+col)) > 0.5) { \
+                            diag("Input image was changed at %d,%d", col,row); \
+                            errorFlag = true; \
+                        } \
+                        if (abs(img2Row[col] - (ps##OUT)(imgRow[col])) > 0.5) { \
+                            diag("returned psImage values after copy don't match at %d,%d " \
+                                 "(%d vs %d)",\
+                                 col,row,img2Row[col], (ps##OUT)(imgRow[col])); \
+                            errorFlag = true; \
+                        } \
+                    } \
+                } \
+                ok(!errorFlag, "psImageCopy() set image data correctly"); \
+            } else {\
+                ok(img2, "psImageCopy() returned non-NULL"); \
+            } \
+        }
+
+        #define testImageCopyTypes(IN) \
+        testImageCopyType(IN,F32);\
+        testImageCopyType(IN,F64); \
+        testImageCopyType(IN,U8); \
+        testImageCopyType(IN,U16); \
+        testImageCopyType(IN,U32); \
+        testImageCopyType(IN,S8);\
+        testImageCopyType(IN,S16);\
+        testImageCopyType(IN,S32);
+
+        testImageCopyTypes(U8);
+        testImageCopyTypes(U16);
+        testImageCopyTypes(U32);
+        testImageCopyTypes(S8);
+        testImageCopyTypes(S16);
+        testImageCopyTypes(S32);
+        testImageCopyTypes(F32);
+        testImageCopyTypes(F64);
+
+        // Verify the returned psImage structure pointer is null and program
+        // execution doesn't stop, if the input parameter input is null.
+        // An error should follow...
+        // XXX: Verify error
+        img3 = psImageCopy(NULL,NULL,PS_TYPE_F32);
+        ok(img3 == NULL, "psImageCopy() returned NULL when input image was NULL");
+
+        psFree(img);
+        psFree(img2);
+        psFree(img3);
+        psFree(img4);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psImageTrim()
+    // XXX: This should probably be broken into separate blocks
+    {
+        psMemId id = psMemGetId();
+        psS32 r = 200;
+        psS32 c = 300;
+        psS32 qtrR = r/4;
+        psS32 qtrC = c/4;
+        psS32 halfR = r/2;
+        psS32 halfC = c/2;
+        psRegion centerHalf = {qtrC, qtrC+halfC, qtrR, qtrR+halfR};
+
+        psImage* image = psImageAlloc(c,r,PS_TYPE_F32);
+        for (psS32 row = 0; row < image->numRows; row++) {
+            for (psS32 col = 0; col < image->numCols; col++) {
+                image->data.F32[row][col] = (psF32)col + (psF32)row/1000.0f;
+            }
+        }
+        // invoke psImageTrim with non-NULL image, and a valid region
+        // x0,y0->x1,y1 (using only positive values). Verify that:
+        // a. the return psImage is the same as the input psImage.
+        // b. the size of the psImage is x1-x0 by y1-y0.
+        // c. the pixel values coorespond to the region [x0:x1-1,y0:y1-1].
+        psImage* image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+        psImage* image2 = psImageTrim(image1,centerHalf);
+        ok(image1 == image2, "psImageTrim() Return value same as input value");
+        ok(image2->numCols == halfC && image2->numRows == halfR,
+           "The resulting image size was %dx%d, should be %dx%d.",
+           image2->numCols, image2->numRows,
+           halfC, halfR);
+
+        bool errorFlag = false;
+        for (psS32 row = 0; row < image2->numRows; row++) {
+            for (psS32 col = 0; col < image2->numCols; col++) {
+                if (fabsf(image2->data.F32[row][col] - image->data.F32[row+qtrR][col+qtrC])
+                        > FLT_EPSILON) {
+                    diag("The value at (%d,%d) was %g, but should be %g.",
+                         col,row,
+                         image2->data.F32[row][col],
+                         image->data.F32[row+qtrR][col+qtrC]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageTrim() set image data correctly");
+
+
+        // 2. invoke psImageTrim with non-NULL image and valid region where x1=0,
+        //    y1=0. Verify that:
+        //    a. the return psImage size is numCols-x0 by numRows-y0
+        //    b. the pixel values coorespond to the region
+        //       [x0:numCols-1,y0:numRows-1].
+        image1 = psImageCopy(image1,image,PS_TYPE_F32);
+        image2 = psImageTrim(image1,psRegionSet(qtrC,0,qtrR,0));
+        ok(image1 == image2, "psImageTrim() Return value same as input value");
+        ok(image2->numCols == image->numCols-qtrC && image2->numRows == image->numRows-qtrR,
+           "The resulting image size was %dx%d, it should be %dx%d.",
+           image2->numCols, image2->numRows,
+           image->numCols-qtrC, image->numRows-qtrR);
+
+        for (psS32 row = 0; row < image2->numRows; row++) {
+            for (psS32 col = 0; col < image2->numCols; col++) {
+                if (fabsf(image2->data.F32[row][col] -
+                          image->data.F32[row+qtrR][col+qtrC]) > FLT_EPSILON) {
+                    diag("The value at (%d,%d) was %g, but should be %g.",
+                         col,row,
+                         image2->data.F32[row][col],
+                         image->data.F32[row+qtrR][col+qtrC]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageTrim() set image data correctly");
+
+
+        //  Invoke psImageTrim with x1<0, y1<0. Verify:
+        //      a. the psImage size is (numCols+x1)-x0 by (numRows+y1)-y0.
+        //      b. the pixel values coorespond to the region
+        //         [x0:numCols+x1-1,y0:numRows+y1-1].
+        image1 = psImageCopy(image1,image,PS_TYPE_F32);
+        image2 = psImageTrim(image1,psRegionSet(qtrC,-qtrC, qtrR,-qtrR));
+        ok(image1 == image2, "psImageTrim() Return value same as input value");
+        ok(image2->numCols == image->numCols-qtrC-qtrC && image2->numRows == image->numRows-qtrR-qtrR,
+           "The resulting image size was %dx%d, but should be %dx%d.",
+           image2->numCols, image2->numRows,
+           image->numCols-qtrC, image->numRows-qtrR);
+        for (psS32 row = 0; row < image2->numRows; row++) {
+            for (psS32 col = 0; col < image2->numCols; col++) {
+                if (fabsf(image2->data.F32[row][col] -
+                          image->data.F32[row+qtrR][col+qtrC]) > FLT_EPSILON) {
+                    diag("The value at (%d,%d) was %g, but should be %g.",
+                         col,row,
+                         image2->data.F32[row][col],
+                         image->data.F32[row+qtrR][col+qtrC]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageTrim() set image data correctly");
+        psFree(image1);
+
+
+        //  Invoke psImageTrim with image=NULL Verify:
+        //      a. execution does not cease.
+        //      b. return value is NULL
+        //      c. appropriate error is generated.
+        // An error should follow...
+        // XXX: Verify errors
+        image2 = psImageTrim(NULL, psRegionSet(qtrC,0,qtrR,0));
+        ok(image2 == NULL, "psImageTrim returned NULL given a NULL input image");
+        psErr* err = psErrorLast();
+        ok(err != NULL && err->code == PS_ERR_BAD_PARAMETER_NULL,
+           "psImageTrim did generate an appropriate error for NULL input image.");
+        psFree(err);
+
+
+        // Verify when psRegion has a coord at -1
+        image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+        image2 = psImageTrim(image1, psRegionSet(-1,0,0,0));
+        ok(image2 == NULL, "psImageTrim returned NULL given x0=-1.");
+        err = psErrorLast();
+        ok(err != NULL && err->code == PS_ERR_BAD_PARAMETER_VALUE,
+           "psImageTrim did generate an appropriate error for x0=-1.");
+        psFree(err);
+
+
+        // Verify when psRegion has a coord at -1
+        image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+        image2 = psImageTrim(image1, psRegionSet(0,0,-1,0));
+        ok(image2 == NULL, "psImageTrim returned NULL given y0=-1.");
+        err = psErrorLast();
+        ok(err != NULL && err->code == PS_ERR_BAD_PARAMETER_VALUE,
+           "psImageTrim did generate an appropriate error for y0=-1");
+        psFree(err);
+
+
+        // Verify when psRegion has a coord at outside the image range
+        image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+        image2 = psImageTrim(image1, psRegionSet(0,image->numCols+1,0,0));
+        ok(image2 == NULL, "psImageTrim returned NULL given x1=numCols+1");
+        err = psErrorLast();
+        ok(err != NULL && err->code == PS_ERR_BAD_PARAMETER_VALUE,
+           "psImageTrim did generate an appropriate error for x1=numCols+1");
+        psFree(err);
+
+
+        // Verify when psRegion has a coord at outside the image range
+        image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+        image2 = psImageTrim(image1, psRegionSet(0,0,0,image->numRows+1));
+        ok(image2 == NULL, "psImageTrim returned NULL given y1=numRows+1");
+        err = psErrorLast();
+        ok(err != NULL && err->code == PS_ERR_BAD_PARAMETER_VALUE,
+           "psImageTrim did generate an appropriate error for y1=numRows+1");
+        psFree(err);
+
+
+        // Verify when psRegion has a coord at outside the image range
+        image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+        image2 = psImageTrim(image1, psRegionSet(0,0,0,(((psF32)image->numRows)*-1.0)));
+        ok(image2 == NULL, "psImageTrim returned NULL given y1=-numRows");
+        err = psErrorLast();
+        ok(err != NULL && err->code == PS_ERR_BAD_PARAMETER_VALUE,
+           "psImageTrim did generate an appropriate error for y1=-numRows");
+        psFree(err);
+
+
+        // Verify when psRegion has a coord at outside the image range
+        image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+        image2 = psImageTrim(image1, psRegionSet(0,(((psF32)image->numCols)*-1.0),0,0));
+        ok(image2 == NULL, "psImageTrim returned NULL given x1=-numCols");
+        err = psErrorLast();
+        ok(err != NULL && err->code == PS_ERR_BAD_PARAMETER_VALUE,
+           "psImageTrim did generate an appropriate error for x1=-numCols");
+
+
+        psFree(image);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageConvolve.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageConvolve.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageConvolve.c	(revision 22158)
@@ -0,0 +1,445 @@
+/** @file  tst_psImageConvolve.c
+ *
+ *  @brief Contains the tests for psImageConvolve.[ch]
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-02-24 23:43:15 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "psTest.h"
+#include "pslib_strict.h"
+#include "psType.h"
+
+static psS32 testKernelAlloc(void);
+static psS32 testKernelGenerate(void);
+static psS32 testImageConvolve(void);
+
+testDescription tests[] = {
+                              {testKernelAlloc,731,"psKernelAlloc",0,false},
+                              {testKernelGenerate,732,"psKernelGenerate",0,false},
+                              {testImageConvolve,733,"psImageConvolve",0,false},
+                              {NULL}
+                          };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    return ! runTestSuite(stderr,"psImage",tests,argc,argv);
+}
+
+static psS32 testKernelAlloc(void)
+{
+    psS32 numCases = 4;
+    psS32 xMin[] = { -5,  0,-10,  5};
+    psS32 xMax[] = {  0,  5, -5, 10};
+    psS32 yMin[] = { -4,  0, -8,  4};
+    psS32 yMax[] = {  0,  4, -4,  8};
+    psS32 i;
+    psKernel* k;
+
+    for (i=0;i<numCases;i++) {
+        k = psKernelAlloc(xMin[i],xMax[i],yMin[i],yMax[i]);
+
+        if (k == NULL) {
+            psError(PS_ERR_UNKNOWN, true,"psKernelAlloc returned NULL for [%d:%d,%d:%d].",
+                    xMin[i], xMax[i], yMin[i], yMax[i]);
+            return i*10+1;
+        }
+
+        if (k->xMin != xMin[i] || k->xMax != xMax[i] ||
+                k->yMin != yMin[i] || k->yMax != yMax[i]) {
+            psError(PS_ERR_UNKNOWN, true,"Min/max members, [%d:%d,%d:%d], of psKernel wrong. Should be [%d:%d,%d:%d].",
+                    k->xMin,k->xMax, k->yMin, k->yMax,
+                    xMin[i], xMax[i], yMin[i], yMax[i]);
+            return i*10+2;
+        }
+
+        if (k->image->numCols != xMax[i]-xMin[i]+1 ||
+                k->image->numRows != yMax[i]-yMin[i]+1) {
+            psError(PS_ERR_UNKNOWN, true,"Size of the kernel image is wrong (%dx%d vs %dx%d).",
+                    xMax[i]-xMin[i]+1, yMax[i]-yMin[i]+1,
+                    k->image->numCols, k->image->numRows);
+            return i*10+2;
+        }
+
+        for (psS32 j=yMin[i]; j<yMax[i]; j++) {
+            if (k->kernel[j]+xMin[i] != k->image->data.PS_TYPE_KERNEL_DATA[j-yMin[i]]) {
+                psError(PS_ERR_UNKNOWN, true,"The kernel pointer was set wrong for row %d.",
+                        j);
+                return i*10+4;
+            }
+        }
+
+        psFree(k);
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be a warning (xMin > xMax)");
+    k = psKernelAlloc(5, -5, -2, 2);
+    if (k == NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psKernelAlloc returned NULL for xMin > xMax.");
+        return i*10+5;
+    }
+
+    if (k->xMin != -5 || k->xMax != 5) {
+        psError(PS_ERR_UNKNOWN, true,"psKernelAlloc didn't swap xMin & xMax.");
+        return i*10+6;
+    }
+
+    psFree(k);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be a warning (yMin > yMax)");
+    k = psKernelAlloc(-2, 2, 5, -5);
+    if (k == NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psKernelAlloc returned NULL for yMin > yMax.");
+        return i*10+7;
+    }
+
+    if (k->yMin != -5 || k->yMax != 5) {
+        psError(PS_ERR_UNKNOWN, true,"psKernelAlloc didn't swap yMin & yMax.");
+        return i*10+8;
+    }
+
+    psFree(k);
+
+    return 0;
+}
+
+static psS32 testKernelGenerate(void)
+{
+    psS32 size = 5;
+    psS32 t[] = { 1, 2, 8, 9, 10 };
+    psS32 x[] = { 0, 1, 0, -1, 0 };
+    psS32 y[] = { 2, 1, -1, -2, 0 };
+    float sum;
+
+    psVector* xVec = psVectorAlloc(size,PS_TYPE_U32);
+    psVector* yVec = psVectorAlloc(size,PS_TYPE_U32);
+    psVector* tVec = psVectorAlloc(size,PS_TYPE_U32);
+
+    for (psS32 i = 0; i < size; i++) {
+        xVec->data.U32[i] = x[i];
+        xVec->n++;
+        yVec->data.U32[i] = y[i];
+        yVec->n++;
+        tVec->data.U32[i] = t[i];
+        tVec->n++;
+    }
+
+    psKernel* result = psKernelGenerate(tVec, xVec, yVec, false);
+
+    if (result == NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psKernelGenerate returned NULL.");
+        return 1;
+    }
+
+    if (result->xMin != -1 || result->xMax != 1 ||
+            result->yMin != -2 || result->yMax != 2) {
+        psError(PS_ERR_UNKNOWN, true,"psKernelGenerate result had a range of [%d:%d,%d:%d].  Suppose to be [-2:2,-1:1].",
+                result->xMin, result->xMax, result->yMin, result->yMax);
+        return 2;
+    }
+
+    sum = 0.0;
+    printf("Resulting kernel:\n");
+    for (psS32 y = result->yMin; y <= result->yMax; y++) {
+        for (psS32 x = result->xMin; x <= result->xMax; x++) {
+            printf(" %6.2f ", result->kernel[y][x]);
+            sum += result->kernel[y][x];
+        }
+        printf("\n");
+    }
+    if (fabsf(1.0 - sum) > FLT_EPSILON) {
+        psError(PS_ERR_UNKNOWN, true,"psKernelGenerate result is not normalized (sum=%g).",
+                sum);
+
+        return 3;
+
+    }
+
+    if (fabsf(result->kernel[-2][0] - 0.1) > FLT_EPSILON ||
+            fabsf(result->kernel[ -1][ -1] - 0.1) > FLT_EPSILON ||
+            fabsf(result->kernel[ 1][ 0] - 0.6) > FLT_EPSILON ||
+            fabsf(result->kernel[2][1] - 0.1) > FLT_EPSILON) {
+        psError(PS_ERR_UNKNOWN, true,"psKernelGenerate result values, %g,%g,%g,%g, are wrong. Suppose to be 0.1,0.1,0.6,0.1",
+                result->kernel[-2][0], result->kernel[-1][-1],
+                result->kernel[1][0], result->kernel[2][1]);
+
+        return 4;
+    }
+
+    psFree(result);
+    psFree(xVec);
+    psFree(yVec);
+    psFree(tVec);
+
+    xVec = psVectorAlloc(size,PS_TYPE_S16);
+    yVec = psVectorAlloc(size,PS_TYPE_S16);
+    tVec = psVectorAlloc(size,PS_TYPE_S16);
+
+    for (psS32 i = 0; i < size; i++) {
+        xVec->data.S16[i] = x[i];
+        xVec->n++;
+        yVec->data.S16[i] = y[i];
+        yVec->n++;
+        tVec->data.S16[i] = t[i];
+        tVec->n++;
+    }
+
+    result = psKernelGenerate(tVec, xVec, yVec, true);
+
+    if (result == NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psKernelGenerate returned NULL.");
+        return 5;
+    }
+
+    if (result->xMin != 0 || result->xMax != 1 ||
+            result->yMin != 0 || result->yMax != 3) {
+        psError(PS_ERR_UNKNOWN, true,"psKernelGenerate result had a range of [%d:%d,%d:%d].  Suppose to be [0:1,1:2].",
+                result->xMin, result->xMax, result->yMin, result->yMax);
+        return 6;
+    }
+
+    sum = 0.0;
+    printf("Resulting kernel (relative=true):\n");
+    for (psS32 y = result->yMin; y <= result->yMax; y++) {
+        for (psS32 x = result->xMin; x <= result->xMax; x++) {
+            printf(" %6.2f ", result->kernel[y][x]);
+            sum += result->kernel[y][x];
+        }
+        printf("\n");
+    }
+    if (fabsf(1.0 - sum) > FLT_EPSILON) {
+        psError(PS_ERR_UNKNOWN, true,"psKernelGenerate result is not normalized (sum=%g).",
+                sum);
+
+        return 7;
+
+    }
+
+    if (fabsf(result->kernel[0][0] - 19.0/30.0) > FLT_EPSILON ||
+            fabsf(result->kernel[2][0] - 1.0/30.0) > FLT_EPSILON ||
+            fabsf(result->kernel[2][1] - 8.0/30.0) > FLT_EPSILON ||
+            fabsf(result->kernel[3][1] - 2.0/30.0) > FLT_EPSILON) {
+        psError(PS_ERR_UNKNOWN, true,"psKernelGenerate result values, %g,%g;%g,%g, are wrong. Suppose to be 2,6;1,0.",
+                result->kernel[0][0], result->kernel[2][0],
+                result->kernel[2][1], result->kernel[3][1]);
+
+        return 8;
+    }
+
+    psFree(result);
+    psFree(xVec);
+    psFree(yVec);
+    psFree(tVec);
+
+    xVec = psVectorAlloc(size,PS_TYPE_F32);
+    yVec = psVectorAlloc(size,PS_TYPE_F32);
+    tVec = psVectorAlloc(size,PS_TYPE_F32);
+
+    for (psS32 i = 0; i < size; i++) {
+        //        xVec->data.F32[i] = x[i]+0.1;
+        //        xVec->n++;
+        psVectorSet(xVec, i, x[i]+0.1);
+        yVec->data.F32[i] = y[i]+0.2;
+        yVec->n++;
+        tVec->data.F32[i] = t[i]+0.3;
+        tVec->n++;
+    }
+
+    tVec->n--; // decrease size by one to make vectors unequal in length.
+    psLogMsg(__func__,PS_LOG_INFO, "Following should be an error.");
+    result = psKernelGenerate(tVec, xVec, yVec, false);
+    if (result != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psKernelGenerate returned non-NULL given differing sized vectors.");
+        return 9;
+    }
+
+    psFree(result);
+
+    psLogMsg(__func__,PS_LOG_INFO, "Following should be a error (time vector NULL).");
+    result = psKernelGenerate(NULL, xVec, yVec, true);
+    if (result != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psKernelGenerate returned a kernel with no time vector.");
+        return 11;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO, "Following should be a error (x vector NULL).");
+    result = psKernelGenerate(tVec, NULL, yVec, true);
+    if (result != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psKernelGenerate returned a kernel with no x vector.");
+        return 11;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO, "Following should be a error (y vector NULL).");
+    result = psKernelGenerate(tVec, xVec, NULL, true);
+    if (result != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psKernelGenerate returned a kernel with no y vector.");
+        return 11;
+    }
+
+    psFree(xVec);
+    psFree(yVec);
+    psFree(tVec);
+    psFree(result);
+
+    return 0;
+}
+
+static psS32 testImageConvolve(void)
+{
+    const psS32 r = 200;
+    const psS32 c = 300;
+    psS32 sum;
+
+    // approximate a normalized gaussian kernel.
+    psKernel* g = psKernelAlloc(-1,1,-1,1);
+    g->kernel[-1][-1] =
+        g->kernel[-1][1] =
+            g->kernel[1][-1] =
+                g->kernel[1][1] = 0.0113;
+    g->kernel[1][0] =
+        g->kernel[-1][0] =
+            g->kernel[0][-1] =
+                g->kernel[0][1] = 0.0838;
+    g->kernel[0][0] = 0.6193;
+
+    // create a normalized non-symetric kernel.
+    psKernel* nsk = psKernelAlloc(0,2,0,2);
+    sum = 0.0;
+    for (psS32 i=0;i<2;i++) {
+        for (psS32 j=0;j<2;j++) {
+            nsk->kernel[i][j] = i+j;
+            sum = i+j;
+        }
+    }
+    for (psS32 i=0;i<2;i++) {
+        for (psS32 j=0;j<2;j++) {
+            nsk->kernel[i][j] /= sum;
+        }
+    }
+
+
+    psImage* img = psImageAlloc(c,r,PS_TYPE_F32);
+    memset(img->data.F32[0],0,c*r*PSELEMTYPE_SIZEOF(PS_TYPE_F32));
+    img->data.F32[0][0] = 1.0f;
+    img->data.F32[r/2][c/2] = 1.0f;
+    img->data.F32[r-1][c/2] = 1.0f;
+
+    // test spacial convolution of gaussian
+    psLogMsg(__func__,PS_LOG_INFO,"Testing direct gaussian convolution");
+    psImage* out = psImageConvolve(NULL, img, g, true);
+
+    if (out == NULL) {
+        psError(PS_ERR_UNKNOWN, true, "psImageConvolve returned a NULL for direct gaussian case.");
+        return 1;
+    }
+
+    if (out->numCols != c || out->numRows != r) {
+        psError(PS_ERR_UNKNOWN, true, "psImageConvolve result image is %dx%d, but expected %dx%d.",
+                out->numCols, out->numRows,
+                c,r);
+        return 2;
+    }
+
+    if (out->type.type != PS_TYPE_F32) {
+        char* typeStr;
+        PS_TYPE_NAME(typeStr,out->type.type);
+        psError(PS_ERR_UNKNOWN, true, "psImageConvolve result image is of type %s, not psF32.",
+                typeStr);
+        return 3;
+    }
+
+    // test values
+    for (psS32 i=-1;i<1;i++) {
+        for (psS32 j=-1;j<1;j++) {
+            if (fabsf(out->data.F32[r/2+i][c/2+j] - g->kernel[i][j]) > 0.0001) {
+                psError(PS_ERR_UNKNOWN, true,"Convolved image wrong at %d,%d.  Value is %g, expected %g.",
+                        c/2+j,r/2+i,
+                        out->data.F32[r/2+i][c/2+j], g->kernel[i][j]);
+                return 4;
+            }
+            if (i >= 0 && j >= 0 && fabsf(out->data.F32[i][j] - g->kernel[i][j]) > 0.0001) {
+                psError(PS_ERR_UNKNOWN, true,"Convolved image wrong at %d,%d.  Value is %g, expected %g.",
+                        j,i,
+                        out->data.F32[i][j], g->kernel[i][j]);
+                return 5;
+            }
+            if (i <= 0 && fabsf(out->data.F32[r-1+i][c/2+j] - g->kernel[i][j]) > 0.0001) {
+                psError(PS_ERR_UNKNOWN, true,"Convolved image wrong at %d,%d.  Value is %g, expected %g.",
+                        c/2+j,r-1+i,
+                        out->data.F32[r-1+i][c/2+j], g->kernel[i][j]);
+                return 6;
+            }
+        }
+    }
+
+    // test fourier convolution of gaussian
+    psLogMsg(__func__,PS_LOG_INFO,"Testing fourier gaussian convolution");
+    psImage* out2 = psImageConvolve(out, img, g, false);
+
+    if (out == NULL) {
+        psError(PS_ERR_UNKNOWN, true, "psImageConvolve returned a NULL for gaussian case.");
+        return 10;
+    }
+
+    if (out != out2) {
+        psError(PS_ERR_UNKNOWN, true, "psImageConvolve didn't recycle the supplied out image struct.");
+        return 11;
+    }
+
+    if (out->numCols != c || out->numRows != r) {
+        psError(PS_ERR_UNKNOWN, true, "psImageConvolve result image is %dx%d, but expected %dx%d.",
+                out->numCols, out->numRows,
+                c,r);
+        return 12;
+    }
+
+    if (out->type.type != PS_TYPE_F32) {
+        char* typeStr;
+        PS_TYPE_NAME(typeStr,out->type.type);
+        psError(PS_ERR_UNKNOWN, true, "psImageConvolve result image is of type %s, not psF32.",
+                typeStr);
+        return 13;
+    }
+
+    // test values
+    for (psS32 i=-1;i<1;i++) {
+        for (psS32 j=-1;j<1;j++) {
+            if (fabsf(out->data.F32[r/2+i][c/2+j] - g->kernel[i][j]) > 0.01) {
+                psError(PS_ERR_UNKNOWN, true,"Convolved image wrong at %d,%d.  Value is %g, expected %g.",
+                        c/2+j,r/2+i,
+                        out->data.F32[r/2+i][c/2+j], g->kernel[i][j]);
+                return 14;
+            }
+            if (i >= 0 && j >= 0 && fabsf(out->data.F32[i][j] - g->kernel[i][j]) > 0.01) {
+                psError(PS_ERR_UNKNOWN, true,"Convolved image wrong at %d,%d.  Value is %g, expected %g.",
+                        j,i,
+                        out->data.F32[i][j], g->kernel[i][j]);
+                return 15;
+            }
+            if (i <= 0 && fabsf(out->data.F32[r-1+i][c/2+j] - g->kernel[i][j]) > 0.01) {
+                psError(PS_ERR_UNKNOWN, true,"Convolved image wrong at %d,%d.  Value is %g, expected %g.",
+                        c/2+j,r-1+i,
+                        out->data.F32[r-1+i][c/2+j], g->kernel[i][j]);
+                return 16;
+            }
+        }
+    }
+
+    psFree(g);
+    psFree(img);
+    psFree(nsk);
+    psFree(out);
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageGeomManip.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageGeomManip.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageGeomManip.c	(revision 22158)
@@ -0,0 +1,1150 @@
+/** @file  tst_psImageGeomManip.c
+ *
+ *  @brief Contains the tests for psImageManip.[ch]
+ *
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-04-20 01:13:11 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <complex.h>
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdlib.h>
+#include <string.h>                    // for memset
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "psTest.h"
+#include "pslib_strict.h"
+#include "psType.h"
+
+static psS32 testImageRebin(void);
+static psS32 testImageRoll(void);
+static psS32 testImageRotate(void);
+static psS32 testImageShift(void);
+static psS32 testImageShiftCase(psS32 cols, psS32 rows, float colShift,float rowShift);
+static psS32 testImageResample(void);
+static psS32 testImageTransform(void);
+
+testDescription tests[] = {
+                              {testImageRebin,559,"psImageRebin",0,false},
+                              {testImageRoll,562,"psImageRoll",0,false},
+                              {testImageRotate,560,"psImageRotate",0,false},
+                              {testImageShift,561,"psImageShift",0,false},
+                              {testImageResample,743,"psImageResample",0,false},
+                              {testImageTransform,-1,"psImageTransform",0,false},
+                              {NULL}
+                          };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    return ! runTestSuite(stderr,"psImage",tests,argc,argv);
+}
+
+static psS32 testImageRebin(void)
+{
+
+    /*
+    This function shall generate a rescaled version of a psImage structure
+    derived from a specified statistics method.
+    */
+
+    psImage* in = NULL;
+    psImage* out = NULL;
+    psImage* out2 = NULL;
+    psImage* out3 = NULL;
+    psImage* mask = NULL;
+    psImage* meanTruth = NULL;
+    psImage* meanTruthWMask = NULL;
+    psImage* maxTruth = NULL;
+    psStats stats;
+
+    /*
+    Verify the returned psImage structure contains expected values, if the
+    input parameter input contains known data, the input scale is a known
+    value with a known statistical method specified in stats. Cases should
+    include at least two different scales and statistical methods. Comparison
+    of expected values should include a delta to allow testing on different
+    platforms.
+    */
+
+    #define testRebinType(DATATYPE)  \
+    in = psImageAlloc(16,16,PS_TYPE_##DATATYPE); \
+    mask = psImageAlloc(16,16,PS_TYPE_U8); \
+    meanTruth = psImageAlloc(4,4,PS_TYPE_F32); \
+    meanTruthWMask = psImageAlloc(4,4,PS_TYPE_F32); \
+    maxTruth = psImageAlloc(6,6,PS_TYPE_F32); \
+    memset(meanTruth->data.F32[0],0,sizeof(psF32)*4*4); \
+    memset(meanTruthWMask->data.F32[0],0,sizeof(psF32)*4*4); \
+    memset(maxTruth->data.F32[0],0,sizeof(psF32)*6*6); \
+    for (psS32 row = 0; row<16; row++) { \
+        ps##DATATYPE* inRow = in->data.DATATYPE[row]; \
+        psF32* meanTruthRow = meanTruth->data.F32[row/4]; \
+        psF32* meanTruthWMaskRow = meanTruthWMask->data.F32[row/4]; \
+        psF32* maxTruthRow = maxTruth->data.F32[row/3]; \
+        psU8* maskRow = mask->data.U8[row]; \
+        for (psS32 col = 0; col<16; col++) { \
+            if(col != 15) { \
+                maskRow[col] = 0; \
+            } else { \
+                maskRow[col] = 1; \
+            } \
+            inRow[col] = row + col; \
+            meanTruthRow[col/4] += row + col; \
+            if (maxTruthRow[col/3] < row + col) { \
+                maxTruthRow[col/3] = row+col; \
+            } \
+            if(maskRow[col] == 0 ) { \
+                meanTruthWMaskRow[col/4] += row + col; \
+            } \
+        } \
+    } \
+    for (psS32 row = 0; row<4; row++) { \
+        psF32* meanTruthRow = meanTruth->data.F32[row]; \
+        psF32* meanTruthWMaskRow = meanTruthWMask->data.F32[row]; \
+        for (psS32 col = 0; col<4; col++) { \
+            meanTruthRow[col] /= 16; \
+            if ( col == 3 ) { \
+                meanTruthWMaskRow[col] /= 12; \
+            } else { \
+                meanTruthWMaskRow[col] /= 16; \
+            } \
+        } \
+    } \
+    stats.options = PS_STAT_SAMPLE_MEAN; \
+    out = psImageRebin(NULL,in,NULL,0,4,&stats); \
+    if (out == NULL) { \
+        psError(PS_ERR_UNKNOWN, true,"psImageRebin returned a NULL pointer!?"); \
+        return 1; \
+    } \
+    if (out->numRows != 4 || out->numCols != 4) { \
+        psError(PS_ERR_UNKNOWN, true,"psImageRebin didn't produce the proper size image " \
+                "(%d x %d).", \
+                out->numCols, out->numRows); \
+        return 2; \
+    } \
+    for (psS32 row = 0; row<4; row++) { \
+        ps##DATATYPE* outRow = out->data.DATATYPE[row]; \
+        psF32* truthRow = meanTruth->data.F32[row]; \
+        for (psS32 col = 0; col<4; col++) { \
+            if (fabsf((float)outRow[col]-(float)truthRow[col]) > FLT_EPSILON) { \
+                psError(PS_ERR_UNKNOWN, true,"psImageRebin didn't produce the proper mean " \
+                        "result at (%d,%d) [%f vs %f].", \
+                        col,row,outRow[col],truthRow[col]); \
+                return 3; \
+            } \
+        } \
+    } \
+    stats.options = PS_STAT_SAMPLE_MEAN; \
+    out3 = psImageRebin(NULL,in,mask,1,4,&stats); \
+    for (psS32 row = 0; row<4; row++) { \
+        ps##DATATYPE* outRow = out3->data.DATATYPE[row]; \
+        psF32* truthRow = meanTruthWMask->data.F32[row]; \
+        for ( psS32 col = 0; col<4; col++) { \
+            if(abs((psS32)outRow[col]-(psS32)truthRow[col]) > FLT_EPSILON) { \
+                psError(PS_ERR_UNKNOWN, true,"psImageRebin with mask didn't produce the proper mean " \
+                        "result at (%d,%d) [%f vs %f].", \
+                        col,row,outRow[col],truthRow[col]); \
+                return 3; \
+            } \
+        } \
+    } \
+    stats.options = PS_STAT_MAX; \
+    out2 = psImageRebin(out,in,NULL,0,3,&stats); \
+    if (out != out2) { \
+        psError(PS_ERR_UNKNOWN, true,"psImageRebin didn't recycle a psImage properly!?"); \
+        return 7; \
+    } \
+    if (out == NULL) { \
+        psError(PS_ERR_UNKNOWN, true,"psImageRebin returned a NULL pointer!?"); \
+        return 4; \
+    } \
+    if (out->numRows != 6 || out->numCols != 6) { \
+        psError(PS_ERR_UNKNOWN, true,"psImageRebin didn't produce the proper size image " \
+                "(%d x %d).", \
+                out->numCols, out->numRows); \
+        return 5; \
+    } \
+    for (psS32 row = 0; row<6; row++) { \
+        ps##DATATYPE* outRow = out->data.DATATYPE[row]; \
+        psF32* truthRow = maxTruth->data.F32[row]; \
+        for (psS32 col = 0; col<6; col++) { \
+            if (fabsf((float)outRow[col]-(float)truthRow[col]) > FLT_EPSILON) { \
+                psError(PS_ERR_UNKNOWN, true,"psImageRebin didn't produce the proper " \
+                        "max result at (%d,%d) [%f vs %f].", \
+                        col,row,outRow[col],truthRow[col]); \
+                return 6; \
+            } \
+        } \
+    } \
+    psFree(in); \
+    psFree(out); \
+    psFree(out3); \
+    psFree(mask); \
+    psFree(meanTruth); \
+    psFree(meanTruthWMask); \
+    psFree(maxTruth);
+
+    testRebinType(F32);
+    testRebinType(F64);
+    testRebinType(U16);
+    testRebinType(S8);
+
+    // Verify the returned psImage structure is null and program execution
+    // doesn't stop, if the input image type is not supported.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error for unsupported type.");
+    in = psImageAlloc(16,16,PS_TYPE_U8);
+    mask = psImageAlloc(16,16,PS_TYPE_F32);
+    stats.options = PS_STAT_SAMPLE_MEAN;
+    out = psImageRebin(NULL,in,NULL,0,4,&stats);
+    if(out != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psImageRebin return an image eventhough the "
+                "type is not handled.");
+        return 14;
+    }
+    // Verify the returned psImage structure is null and program execution
+    // doesn't stop, if the mask type is not U8
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error for invallid mask type.");
+    out = psImageRebin(NULL,in,mask,1,4,&stats);
+    if(out != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psImageRebin return an image eventhough the "
+                "mask is not the correct type.");
+        return 17;
+    }
+    psFree(mask);
+    psFree(in);
+
+    // Verify the returned psImage structure is null and program execution
+    // doesn't stop, if the input parameter input is null.
+
+    out2 = psImageRebin(NULL,NULL,NULL,0,1,&stats);
+
+    if (out2 != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psImageRebin returned an image though the input was "
+                "NULL!?");
+        return 8;
+    }
+
+    // Verify the returned psImage structure is null and program execution
+    // doesn't stop, if the input parameter scale is less than or equal to zero.
+    in = psImageAlloc(16, 16, PS_TYPE_F32);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error for scale < 0.");
+    out2 = psImageRebin(NULL,in,NULL,0,0,&stats);
+
+    if (out2 != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psImageRebin returned an image though the scale was "
+                "zero!?");
+        return 9;
+    }
+
+    // Verify the returned psImage structure is null and program execution
+    // doesn't stop, if the input parameter stats is null.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error for stats null.");
+    out2 = psImageRebin(NULL,in,NULL,0,1,NULL);
+
+    if (out2 != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psImageRebin returned an image though the stats was "
+                "NULL!?");
+        return 10;
+    }
+
+    // Verify the returned psImage structure is null and program execution
+    // doesn't stop, if the input parameter psStats structure member options
+    // is zero or any value which doesn't correspond to a valid statistical
+    // method.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error for stats options 0.");
+    stats.options = 0;
+    out2 = psImageRebin(NULL,in,NULL,0,1,&stats);
+
+    if (out2 != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psImageRebin returned an image though the stats "
+                "options was zero!?");
+        return 11;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error for stat options use range.");
+    stats.options = PS_STAT_USE_RANGE;
+    out2 = psImageRebin(NULL,in,NULL,0,1,&stats);
+
+    if (out2 != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psImageRebin returned an image though the stats "
+                "options was PS_STAT_USE_RANGE!?");
+        return 12;
+    }
+
+    // Verify the returned psImage structure is null and program execution
+    // doesn't stop, if the input parameter psStats structure member options
+    // specifies more than one valid statistical method.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error for stats with multiple options.");
+    stats.options = PS_STAT_SAMPLE_MEAN + PS_STAT_MAX;
+    out2 = psImageRebin(NULL,in,NULL,0,1,&stats);
+
+    if (out2 != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psImageRebin returned an image though the stats "
+                "options was PS_STAT_SAMPLE_MEAN+PS_STAT_MAX!?");
+        return 13;
+    }
+
+    psFree(in);
+
+    return 0;
+}
+
+static psS32 testImageRoll(void)
+{
+
+    psImage* in;
+    psImage* out;
+    psImage* out2;
+    psS32 rows = 64;
+    psS32 cols = 64;
+    psS32 rows1 = 8;
+    psS32 cols1 = 8;
+
+    /*
+     The function psImageRoll shall generate a new psImage structure by
+     rolling the input image the correponding number of pixels in the vertical
+     and/or horizontal direction. The image output image shall be the same size
+     as the input image. Values which roll off the image are wrapped to the
+     other side.
+
+     Verify the returned psImage structure contains expected values, if the
+     input image contains known values and the roll performed is known.
+     Cases should include no roll, vertical roll, horizontal roll and
+     combination vertical/horizontal rolls. Positive and negative rolls
+     should be performed.
+    */
+
+    in = psImageAlloc(cols,rows,PS_TYPE_F32);
+    for (psS32 row=0;row<rows;row++) {
+        psF32* inRow = in->data.F32[row];
+        for (psS32 col=0;col<cols;col++) {
+            inRow[col] = (psF32)row+(psF32)col/1000.0f;
+        }
+    }
+
+    out = psImageRoll(NULL,in,0,0);
+    for (psS32 row=0;row<rows;row++) {
+        psF32* inRow = in->data.F32[row];
+        psF32* outRow = out->data.F32[row];
+        for (psS32 col=0;col<cols;col++) {
+            if (inRow[col] != outRow[col]) {
+                psError(PS_ERR_UNKNOWN, true,"psImageRoll didn't produce expected result "
+                        "at %d,%d (%f vs %f) for dx=0, dy=0.",
+                        col,row,inRow[col],outRow[col]);
+                return 3;
+            }
+        }
+    }
+
+    out2 = psImageRoll(out,in,cols/4,0);
+    for (psS32 row=0;row<rows;row++) {
+        psF32* inRow = in->data.F32[row];
+        psF32* outRow = out->data.F32[row];
+        for (psS32 col=0;col<cols;col++) {
+            if (inRow[(col+cols/4) % cols] != outRow[col]) {
+                psError(PS_ERR_UNKNOWN, true,"psImageRoll didn't produce expected result "
+                        "at %d,%d (%f vs %f) for dx=cols/4, dy=0.",
+                        col,row,inRow[(col+cols/4) % cols],outRow[col]);
+                return 4;
+            }
+        }
+    }
+
+    // Verify the returned psImage structure pointer is equal to the input
+    // parameter out if provided.
+    if (out2 != out) {
+        psError(PS_ERR_UNKNOWN, true,"psImageRoll didn't recycle my out psImage!?");
+        return 1;
+    }
+
+    out = psImageRoll(out,in,0,rows/4);
+    for (psS32 row=0;row<rows;row++) {
+        psF32* inRow = in->data.F32[(row+rows/4)%rows];
+        psF32* outRow = out->data.F32[row];
+        for (psS32 col=0;col<cols;col++) {
+            if (inRow[col] != outRow[col]) {
+                psError(PS_ERR_UNKNOWN, true,"psImageRoll didn't produce expected result "
+                        "at %d,%d (%f vs %f) for dx=0, dy=rows/4.",
+                        col,row,inRow[col],outRow[col]);
+                return 5;
+            }
+        }
+    }
+
+    out = psImageRoll(out,in,cols/4,rows/4);
+    for (psS32 row=0;row<rows;row++) {
+        psF32* inRow = in->data.F32[(row+rows/4)%rows];
+        psF32* outRow = out->data.F32[row];
+        for (psS32 col=0;col<cols;col++) {
+            if (inRow[(col+cols/4) % cols] != outRow[col]) {
+                psError(PS_ERR_UNKNOWN, true,"psImageRoll didn't produce expected result "
+                        "at %d,%d (%f vs %f) for dx=cols/4, dy=rows/4.",
+                        col,row,inRow[(col+cols/4) % cols],outRow[col]);
+                return 6;
+            }
+        }
+    }
+
+    out = psImageRoll(out,in,-cols/4,0);
+    for (psS32 row=0;row<rows;row++) {
+        psF32* inRow = in->data.F32[row];
+        psF32* outRow = out->data.F32[row];
+        for (psS32 col=0;col<cols;col++) {
+            if (inRow[(col+(cols-cols/4)) % cols] != outRow[col]) {
+                psError(PS_ERR_UNKNOWN, true,"psImageRoll didn't produce expected result "
+                        "at %d,%d (%f vs %f) for dx=-cols/4, dy=0.",
+                        col,row,inRow[(col+(cols-cols/4)) % cols],outRow[col]);
+                return 7;
+            }
+        }
+    }
+
+    out = psImageRoll(out,in,0,-rows/4);
+    for (psS32 row=0;row<rows;row++) {
+        psF32* inRow = in->data.F32[(row+rows-rows/4)%rows];
+        psF32* outRow = out->data.F32[row];
+        for (psS32 col=0;col<cols;col++) {
+            if (inRow[col] != outRow[col]) {
+                psError(PS_ERR_UNKNOWN, true,"psImageRoll didn't produce expected result "
+                        "at %d,%d (%f vs %f) for dx=0, dy=-rows/4.",
+                        col,row,inRow[col],outRow[col]);
+                return 8;
+            }
+        }
+    }
+
+    out = psImageRoll(out,in,-cols/4,-rows/4);
+    for (psS32 row=0;row<rows;row++) {
+        psF32* inRow = in->data.F32[(row+rows-rows/4)%rows];
+        psF32* outRow = out->data.F32[row];
+        for (psS32 col=0;col<cols;col++) {
+            if (inRow[(col+cols-cols/4) % cols] != outRow[col]) {
+                psError(PS_ERR_UNKNOWN, true,"psImageRoll didn't produce expected result "
+                        "at %d,%d (%f vs %f) for dx=cols/4, dy=rows/4.",
+                        col,row,inRow[(col+cols-cols/4) % cols],outRow[col]);
+                return 9;
+            }
+        }
+    }
+
+
+    // Verify the returned psImage structure pointer is null and program
+    // execution doesn't stop, if input parameter input is null.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error.");
+    out2 = psImageRoll(NULL,NULL,0,0);
+    if (out2 != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psImageRoll did not return NULL though input image was NULL!?");
+        return 2;
+    }
+
+    psFree(in);
+    psFree(out);
+
+    #define testRollType(DATATYPE) \
+    in = psImageAlloc(rows1,cols1,PS_TYPE_##DATATYPE); \
+    \
+    for (psS32 row=0;row<rows1;row++) { \
+        ps##DATATYPE* inRow = in->data.DATATYPE[row]; \
+        for (psS32 col=0;col<cols1;col++) { \
+            inRow[col] = (ps##DATATYPE)row+(ps##DATATYPE)col; \
+        } \
+    } \
+    \
+    out = psImageRoll(NULL,in,rows1/4,cols1/4); \
+    for (psS32 row=0;row<rows1;row++) { \
+        ps##DATATYPE* inRow = in->data.DATATYPE[(row+rows1/4)%rows1]; \
+        ps##DATATYPE* outRow = out->data.DATATYPE[row]; \
+        for (psS32 col=0;col<cols1;col++) { \
+            if (inRow[(col+cols1/4)%cols1] != outRow[col]) { \
+                psError(PS_ERR_UNKNOWN, true,"psImageRoll didn't produce expected result " \
+                        "at %d,%d (%f vs %f) for dx=0, dy=0.", \
+                        col,row,(float)inRow[col],(float)outRow[col]); \
+                return 3; \
+            } \
+        } \
+    } \
+    psFree(in); \
+    psFree(out);
+
+    testRollType(U8);
+    testRollType(U16);
+    testRollType(S8);
+    testRollType(S16);
+    testRollType(F64);
+    testRollType(C32);
+    testRollType(C64);
+
+    return 0;
+}
+
+psS32 testImageRotate(void)
+{
+    /*
+
+    This function shall calculate a new psImage structure based upon the
+    rotation of a given psImage structure. The center of rotation shall be the
+    center pixel of the input image.
+
+    The following steps of the testpoint are done manually via inspection of
+    fOut.fits & sOut.fits.
+
+        * Verify the returned psImage structure contains expected values, if
+          the input parameter psImage contains known values. Cases should
+          include rotations of 0, 45, 90, 135, 180, 225, 270, 315, 360 and at leat one
+          other arbitrary angle. Cases of the input image should include image
+          with a center pixel and an image without a center pixel.
+        * Verify the returned psImage structure contains pixels set to exposed value, if
+          the rotation and input psImage to not correspond to the output image.
+
+    */
+
+    psImage* fOut = NULL;
+    psImage* sOut = NULL;
+    psImage* fBiOut = NULL;
+    psImage* sBiOut = NULL;
+    psImage* fTruth = NULL;
+    psImage* sTruth = NULL;
+    psImage* fBiTruth = NULL;
+    psImage* sBiTruth = NULL;
+    psS32 rows = 64;
+    psS32 cols = 64;
+    psImage* fImg = psImageAlloc(cols,rows,PS_TYPE_F32);
+    psImage* sImg = psImageAlloc(cols,rows,PS_TYPE_S16);
+
+    for(psS32 row=0;row<rows;row++) {
+        psF32* fRow = fImg->data.F32[row];
+        psS16* sRow = sImg->data.S16[row];
+        for (psS32 col=0;col<cols;col++) {
+            fRow[col] = (psF32)(row)+(psF32)(col)/100.0f;
+            sRow[col] = row-2*col;
+        }
+    }
+
+    // since interpolation is involved, etc., the simplist way to verify things
+    // is to verify the results manually and bless it for automated comparison
+    // thereafter
+
+
+    // write results of various rotates to a file and verify with truth images
+    mkdir("temp",0777);
+    psS32 index = 0;
+    psBool fail = false;
+    psF32 radianRot;
+
+    psFits* fOutFile = psFitsOpen("fOut.fits","w");
+    psFits* sOutFile = psFitsOpen("sOut.fits","w");
+    psFits* fBiOutFile = psFitsOpen("fBiOut.fits","w");
+    psFits* sBiOutFile = psFitsOpen("sBiOut.fits","w");
+    if (fOutFile == NULL ||sOutFile == NULL || fBiOutFile == NULL || sBiOutFile == NULL) {
+        psError(PS_ERR_UNKNOWN, true, "Can not create output files, so why continue!?");
+        return 1;
+    }
+
+    psFits* fTruthFile = psFitsOpen(VERIFIED_DIR "/fOut.fits","r");
+    psFits* sTruthFile = psFitsOpen(VERIFIED_DIR "/sOut.fits","r");
+    psFits* fBiTruthFile = psFitsOpen(VERIFIED_DIR "/fBiOut.fits","r");
+    psFits* sBiTruthFile = psFitsOpen(VERIFIED_DIR "/sBiOut.fits","r");
+    if (fTruthFile == NULL ||sTruthFile == NULL || fBiTruthFile == NULL || sBiTruthFile == NULL) {
+        psError(PS_ERR_UNKNOWN, true, "Can not open truth files, so why continue!?");
+        return 1;
+    }
+
+    psRegion regionAll = psRegionSet(0,0,0,0);
+    for (psS32 rot=-180;rot<=180;rot+=45) {
+        psImage* oldOut = fOut;
+        psImage* oldBiOut = fBiOut;
+        if (rot == 90) {
+            radianRot = M_PI_2;
+        } else if (rot == -90) {
+            radianRot = M_PI+M_PI_2;
+        } else if (rot == 180 || rot == -180) {
+            radianRot = M_PI;
+        } else {
+            radianRot = ((float)rot)*M_PI/180.0;
+        }
+
+        fOut = psImageRotate(fOut,fImg,radianRot,-1.0,PS_INTERPOLATE_FLAT);
+        fBiOut = psImageRotate(fBiOut,fImg,radianRot,-1.0,PS_INTERPOLATE_BILINEAR);
+        // Verify the returned psImage structure is equal to the input
+        // parameter out if provided.
+        if (oldOut != NULL && oldOut != fOut) {
+            psError(PS_ERR_UNKNOWN, true,"the output recycle functionality failed");
+            return 2;
+        }
+        if (oldBiOut != NULL && oldBiOut != fBiOut) {
+            psError(PS_ERR_UNKNOWN, true,"the output recycle functionality failed");
+            return 4;
+        }
+        sOut = psImageRotate(sOut,sImg,radianRot,-1.0,PS_INTERPOLATE_FLAT);
+        sBiOut = psImageRotate(sBiOut,sImg,radianRot,-1.0,PS_INTERPOLATE_BILINEAR);
+
+        if (! psFitsWriteImage(fOutFile, NULL, fOut, 1, NULL) ) {
+            psError(PS_ERR_UNKNOWN, true,"Can not write fOut.");
+            return 20;
+        }
+        if (! psFitsWriteImage(sOutFile, NULL, sOut, 1, NULL) ) {
+            psError(PS_ERR_UNKNOWN, true,"Can not write sOut.");
+            return 21;
+        }
+        if (! psFitsWriteImage(fBiOutFile, NULL, fBiOut, 1, NULL) ) {
+            psError(PS_ERR_UNKNOWN, true,"Can not write fBiOut.fits.");
+            return 40;
+        }
+        if (! psFitsWriteImage(sBiOutFile, NULL, sBiOut, 1, NULL) ) {
+            psError(PS_ERR_UNKNOWN, true,"Can not write sBiOut.fits.");
+            return 41;
+        }
+
+        // now, let's compare this with the verified file
+        psFitsMoveExtNum(fTruthFile, index, false);
+        psFitsMoveExtNum(sTruthFile, index, false);
+        psFitsMoveExtNum(fBiTruthFile, index, false);
+        psFitsMoveExtNum(sBiTruthFile, index, false);
+        psFree(fTruth);
+        psFree(sTruth);
+        psFree(fBiTruth);
+        psFree(sBiTruth);
+        fTruth = NULL;
+        sTruth = NULL;
+        fBiTruth = NULL;
+        sBiTruth = NULL;
+        fTruth = psFitsReadImage(fTruthFile, regionAll, 0);
+        sTruth = psFitsReadImage(sTruthFile, regionAll, 0);
+        fBiTruth = psFitsReadImage(fBiTruthFile, regionAll, 0);
+        sBiTruth = psFitsReadImage(sBiTruthFile, regionAll, 0);
+        if (fTruth == NULL) {
+            psError(PS_ERR_UNKNOWN, true,"verified psF32 image failed to be read (%d deg. rotation)",
+                    rot);
+            fail = true;
+        } else {
+            if (fTruth->numRows != fOut->numRows || fTruth->numCols != fOut->numCols) {
+                psError(PS_ERR_UNKNOWN, true,"Rotated float image size did not match truth "
+                        "image for %d deg rotation (%dx%d vs %dx%d).",
+                        rot,fOut->numCols,fOut->numRows,fTruth->numCols,fTruth->numRows);
+                fail = true;
+            } else {
+                for (psS32 row=0;row<fTruth->numRows;row++) {
+                    psF32* truthRow = fTruth->data.F32[row];
+                    psF32* outRow = fOut->data.F32[row];
+                    for (psS32 col=0;col<fTruth->numCols;col++) {
+                        if (fabsf(truthRow[col]-outRow[col]) > 1) {
+                            psError(PS_ERR_UNKNOWN, true,"Float Image mismatch (%f vs %f) at %d,%d.",
+                                    outRow[col], truthRow[col],col,row);
+                            fail = true;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (sTruth == NULL) {
+            psError(PS_ERR_UNKNOWN, true,"verified psS16 image failed to be read "
+                    "(%d deg. rotation)",rot);
+            fail = true;
+        } else {
+            if (sTruth->numRows != sOut->numRows ||
+                    sTruth->numCols != sOut->numCols) {
+                psError(PS_ERR_UNKNOWN, true,"Rotated psS16 image size did not match truth "
+                        "image for %d deg rotation.",rot);
+                fail = true;
+            } else {
+                for (psS32 row=0;row<sTruth->numRows;row++) {
+                    psS16* truthRow = sTruth->data.S16[row];
+                    psS16* outRow = sOut->data.S16[row];
+                    for (psS32 col=0;col<sTruth->numCols;col++) {
+                        if (fabsf(truthRow[col]-outRow[col]) > 1) {
+                            psError(PS_ERR_UNKNOWN, true,"Short Image mismatch (%d vs %d) "
+                                    "at %d,%d.",
+                                    outRow[col], truthRow[col],col,row);
+                            fail = true;
+                        }
+                    }
+                }
+            }
+        }
+
+
+        if (fBiTruth == NULL) {
+            psError(PS_ERR_UNKNOWN, true,"verified psF32 Bi image failed to be read (%d deg. rotation)",
+                    rot);
+            fail = true;
+        } else {
+            if (fBiTruth->numRows != fBiOut->numRows || fBiTruth->numCols != fBiOut->numCols) {
+                psError(PS_ERR_UNKNOWN, true,"Rotated float image size did not match truth "
+                        "image for %d deg rotation (%dx%d vs %dx%d). BILINEAR",
+                        rot,fBiOut->numCols,fBiOut->numRows,fBiTruth->numCols,fBiTruth->numRows);
+                fail = true;
+            } else {
+                for (psS32 row=0;row<fBiTruth->numRows;row++) {
+                    psF32* truthRow = fBiTruth->data.F32[row];
+                    psF32* outRow = fBiOut->data.F32[row];
+                    for (psS32 col=0;col<fBiTruth->numCols;col++) {
+                        if (fabsf(truthRow[col]-outRow[col]) > 1) {
+                            psError(PS_ERR_UNKNOWN, true,"Float Image mismatch (%f vs %f) at %d,%d. BILINEAR",
+                                    outRow[col], truthRow[col],col,row);
+                            fail = true;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (sBiTruth == NULL) {
+            psError(PS_ERR_UNKNOWN, true,"verified psS16 image failed to be read "
+                    "(%d deg. rotation) BILINEAR",rot);
+            fail = true;
+        } else {
+            if (sBiTruth->numRows != sBiOut->numRows ||
+                    sBiTruth->numCols != sBiOut->numCols) {
+                psError(PS_ERR_UNKNOWN, true,"Rotated psS16 image size did not match truth "
+                        "image for %d deg rotation. BILINEAR",rot);
+                fail = true;
+            } else {
+                for (psS32 row=0;row<sBiTruth->numRows;row++) {
+                    psS16* truthRow = sBiTruth->data.S16[row];
+                    psS16* outRow = sBiOut->data.S16[row];
+                    for (psS32 col=0;col<sBiTruth->numCols;col++) {
+                        if (fabsf(truthRow[col]-outRow[col]) > 1) {
+                            psError(PS_ERR_UNKNOWN, true,"Short Image mismatch (%d vs %d) "
+                                    "at %d,%d. BILINEAR",
+                                    outRow[col], truthRow[col],col,row);
+                            fail = true;
+                        }
+                    }
+                }
+            }
+        }
+
+        index++;
+    }
+
+    if (fail) {
+        psError(PS_ERR_UNKNOWN, true,"One or more images didn't match truth or truth did "
+                "not exist.");
+        return 10;
+    }
+
+
+    // Verify the returned psImage structure pointer is null and program
+    // execution doesn't stop, if the input parameter input is null.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error");
+    fOut = psImageRotate(fOut,NULL,0,0,PS_INTERPOLATE_FLAT);
+    if (fOut != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"NULL wasn't returned though the input image was NULL.");
+        return 3;
+    }
+
+    // Verify the returned psImage structure pointer is null and program
+    // execution doesn't stop, if the specified interpolation mode is invalid
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error for invalid "
+             "interpolation type.");
+    fOut = psImageRotate(fOut, fImg, 33, 0, -1);
+    if (fOut != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"NULL wasn't returned though the interpolation mode "
+                "is invalid.");
+        return 4;
+    }
+
+    psFree(sOut);
+    psFree(fImg);
+    psFree(sImg);
+    psFree(fTruth);
+    psFree(sTruth);
+    psFree(sBiOut);
+    psFree(fBiTruth);
+    psFree(sBiTruth);
+    psFree(fBiOut);
+
+    psFree(fOutFile);
+    psFree(sOutFile);
+    psFree(fBiOutFile);
+    psFree(sBiOutFile);
+
+    psFree(fTruthFile);
+    psFree(sTruthFile);
+    psFree(fBiTruthFile);
+    psFree(sBiTruthFile);
+
+    return 0;
+}
+
+static psS32 testImageShift(void)
+{
+    /* psImageShift:
+
+       This functions shall generate a new psImage structure by shifting the
+       input psImage structure a specified number of pixels in the horizontal
+       and/or vertical directions.
+
+       Verify the returned psImage structure contains expected values, if the
+       input psImage structure contains known values and a know shift in the
+       vertical and/or horizontal directions. Cases should include no shift,
+       vertical only(up,down), horizontal only(right, left), and combination
+       shift. Cases should include fractional shifts. Comparison of expected
+       values should include a delta to allow for testing on different
+       platforms.
+
+       Verify the returned psImage structure contains values for pixels not in
+       the original image set to the input parameter exposed.
+
+    */
+
+    psS32 retVal=0;
+
+    // integer shift
+    retVal |= testImageShiftCase(64,128,0.0f,0.0f);
+    retVal |= testImageShiftCase(64,128,0.0f,16.0f);
+    retVal |= testImageShiftCase(64,128,0.0f,-16.0f);
+    retVal |= testImageShiftCase(64,128,32.0f,0.0f);
+    retVal |= testImageShiftCase(64,128,-32.0f,0.0f);
+    retVal |= testImageShiftCase(64,128,32.0f,16.0f);
+    retVal |= testImageShiftCase(64,128,32.0f,-16.0f);
+    retVal |= testImageShiftCase(64,128,-32.0f,16.0f);
+    retVal |= testImageShiftCase(64,128,-32.0f,-16.0f);
+
+    if (retVal != 0) {
+        return retVal;
+    }
+
+    // fractional shift
+    retVal |= testImageShiftCase(64,128,0.0f,16.4f);
+    retVal |= testImageShiftCase(64,128,0.0f,-16.4f);
+    retVal |= testImageShiftCase(64,128,32.7f,0.0f);
+    retVal |= testImageShiftCase(64,128,-32.7f,0.0f);
+    retVal |= testImageShiftCase(64,128,32.6f,16.2f);
+    retVal |= testImageShiftCase(64,128,32.6f,-16.2f);
+    retVal |= testImageShiftCase(64,128,-32.6f,16.2f);
+    retVal |= testImageShiftCase(64,128,-32.6f,-16.2f);
+
+    if (retVal != 0) {
+        return retVal;
+    }
+
+    /*
+       Verify the returned psImage structure pointer is equal to the input
+       parameter out if provided.
+    */
+    psImage* fImg = psImageAlloc(32,32,PS_TYPE_F32);
+    psImage* fRecycle = psImageAlloc(32,32,PS_TYPE_F32);
+    psImage* fOut = psImageShift(fRecycle, fImg, 8,8, NAN, PS_INTERPOLATE_FLAT);
+
+    if (fRecycle != fOut) {
+        psError(PS_ERR_UNKNOWN, true,"psImageShift didn't recycle my image?");
+        return 10;
+    }
+
+    /*
+       Verify the returned psImage structure pointer is null and program
+       execution doesn't stop, if the input psImage structure pointer is null.
+    */
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error...");
+    fOut = psImageShift(fOut,NULL,8,8,NAN,PS_INTERPOLATE_FLAT);
+    if (fOut != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psImageShift didn't return NULL given a NULL input image.");
+        return 11;
+    }
+
+    // Verify the returned psImage structure is null and program execution
+    // doesn't stop, if the specified interpolation mode is invalid.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error for invalid interpolation mode.");
+    fOut = psImageShift(fOut,fImg,8,8,NAN,-1);
+    if (fOut != NULL ) {
+        psError(PS_ERR_UNKNOWN, true,"psImageShift didn't return NULL given an invalid interpolation mode.");
+        return 12;
+    }
+
+    psFree(fImg);
+
+    return 0;
+}
+
+static psS32 testImageShiftCase(psS32 cols,
+                                psS32 rows,
+                                float colShift,
+                                float rowShift)
+{
+    psImage* fOut = NULL;
+    psImage* sOut = NULL;
+
+    psLogMsg(__func__,PS_LOG_INFO,"Testing psImageShift with a %dx%d image for "
+             "a shift of %g,%g.",cols,rows,colShift,rowShift);
+
+    psImage* fImg = psImageAlloc(cols,rows,PS_TYPE_F32);
+    psImage* sImg = psImageAlloc(cols,rows,PS_TYPE_S16);
+    psImage* fBiOut = psImageAlloc(cols,rows,PS_TYPE_F32);
+    psImage* sBiOut = psImageAlloc(cols,rows,PS_TYPE_S16);
+
+    for(psS32 row=0;row<rows;row++) {
+        psF32* fRow = fImg->data.F32[row];
+        psS16* sRow = sImg->data.S16[row];
+        for (psS32 col=0;col<cols;col++) {
+            fRow[col] = (psF32)(row)+(psF32)(col)/100.0f;
+            sRow[col] = row-2*col;
+        }
+    }
+
+    fOut = psImageShift(fOut, fImg, colShift, rowShift, NAN, PS_INTERPOLATE_FLAT);
+    sOut = psImageShift(sOut, sImg, colShift, rowShift, -1, PS_INTERPOLATE_FLAT);
+    fBiOut = psImageShift(fBiOut, fImg, colShift, rowShift, NAN, PS_INTERPOLATE_BILINEAR);
+    sBiOut = psImageShift(sBiOut, sImg, colShift, rowShift, -1, PS_INTERPOLATE_BILINEAR);
+
+    for(psS32 row=0;row<rows;row++) {
+        psF32* fRow = fOut->data.F32[row];
+        psS16* sRow = sOut->data.S16[row];
+        psF32* fBiRow = fBiOut->data.F32[row];
+        psS16* sBiRow = sBiOut->data.S16[row];
+
+        for (psS32 col=0;col<cols;col++) {
+            psF32 fValue = psImagePixelInterpolate(fImg,col+colShift,
+                                                   row+rowShift,NULL,0,NAN,PS_INTERPOLATE_FLAT);
+            psS16 sValue = (psS16)psImagePixelInterpolate(sImg,col+colShift,
+                           row+rowShift,NULL,0,-1,PS_INTERPOLATE_FLAT);
+
+            psF32 fBiValue = psImagePixelInterpolate(fImg,col+colShift,
+                             row+rowShift,NULL,0,NAN,PS_INTERPOLATE_BILINEAR);
+            psS16 sBiValue = (psS16)psImagePixelInterpolate(sImg,col+colShift,
+                             row+rowShift,NULL,0,-1,PS_INTERPOLATE_BILINEAR);
+
+            if (fabsf(fRow[col] - fValue) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN, true,"Float image not shifted correctly at %d,%d (%g vs %g)",
+                        col,row,fRow[col],fValue);
+                return 1;
+            }
+            if (sRow[col] != sValue) {
+                psError(PS_ERR_UNKNOWN, true,"Short image not shifted correctly at %d,%d (%d vs %d)",
+                        col,row,sRow[col],sValue);
+                return 2;
+            }
+            if (fabsf(fBiRow[col] - fBiValue) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN, true,"Float image not shifted correctly at %d,%d (%g vs %g)",
+                        col,row,fBiRow[col],fBiValue);
+                return 1;
+            }
+            if (sBiRow[col] != sBiValue) {
+                psError(PS_ERR_UNKNOWN, true,"Short image not shifted correctly at %d,%d (%d vs %d)",
+                        col,row,sBiRow[col],sBiValue);
+                return 2;
+            }
+        }
+    }
+
+    psFree(fImg);
+    psFree(sImg);
+    psFree(fOut);
+    psFree(sOut);
+    psFree(fBiOut);
+    psFree(sBiOut);
+
+    return 0;
+}
+
+static psS32 testImageResample(void)
+{
+
+    psS32 rows = 60;
+    psS32 cols = 80;
+    psImage* result = NULL;
+    psS32 scale = 4;
+    psErr* err;
+
+    psImage* image = psImageAlloc(cols,rows,PS_TYPE_F32);
+    for(psS32 row=0;row<rows;row++) {
+        psF32* imageRow = image->data.F32[row];
+        for (psS32 col=0;col<cols;col++) {
+            imageRow[col] = row+2*col;
+        }
+    }
+    result = psImageCopy(NULL,image,PS_TYPE_F64);
+    psImage* orig = result;
+    result = psImageResample(result,image,scale,PS_INTERPOLATE_FLAT);
+
+    if (result == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "NULL return unexpected");
+        return 1;
+    }
+
+    if (result != orig) {
+        psLogMsg(__func__,PS_LOG_ERROR,"failure to recycle image.");
+        return 2;
+    }
+
+    if (result->type.type != PS_TYPE_F32) {
+        psLogMsg(__func__,PS_LOG_ERROR,"unexpected type");
+        return 3;
+    }
+
+
+    if (result->numCols != image->numCols*scale ||
+            result->numRows != image->numRows*scale) {
+        psLogMsg(__func__,PS_LOG_ERROR,"The size of the result is %dx%d, but %dx%d was expected.",
+                 result->numCols,result->numRows,
+                 image->numCols*scale, image->numRows*scale);
+        return 4;
+    }
+
+    psF32 truthValue;
+    for(psS32 row=0;row<result->numRows;row++) {
+        for (psS32 col=0;col<result->numCols;col++) {
+            truthValue = psImagePixelInterpolate(image,
+                                                 (float)col/(float)scale,(float)row/(float)scale,
+                                                 NULL,0,-1,PS_INTERPOLATE_FLAT);
+            if (fabs(truthValue - result->data.F32[row][col]) > FLT_EPSILON) {
+                psLogMsg(__func__,PS_LOG_ERROR,"value bad at (%d,%d).  Got %g, expected %g.",
+                         col,row,result->data.F32[row][col], truthValue);
+                return 5;
+            }
+        }
+    }
+
+    // verify that image=null is handled properly.
+    psErrorClear();
+    result = psImageResample(result,NULL,scale,PS_INTERPOLATE_FLAT);
+
+    if (result != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "return was not NULL, as expected.");
+        return 6;
+    }
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "error message was not appropriate type.");
+        return 7;
+    }
+    psFree(err);
+
+    // verify that scale < 1 is handled properly
+    psErrorClear();
+    result = psImageResample(result,image,0,PS_INTERPOLATE_FLAT);
+
+    if (result != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "return was not NULL, as expected.");
+        return 8;
+    }
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "error message was not appropriate type.");
+        return 9;
+    }
+    psFree(err);
+
+    // verify that invalid interpolation mode is handled properly
+    psErrorClear();
+    result = psImageResample(result,image,2,-1);
+
+    if (result != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "return was not NULL, as expected.");
+        return 10;
+    }
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "error message was not appropriate type.");
+        return 11;
+    }
+    psFree(err);
+
+    // Verify that that an invalid image type is handled properly
+    psErrorClear();
+    psImage* invImage = psImageAlloc(cols,rows,PS_TYPE_BOOL);
+    memset(invImage->p_rawDataBuffer,0,cols*rows*PSELEMTYPE_SIZEOF(PS_TYPE_BOOL)); // make sure the image is of all NULLs
+    result = psImageResample(result,invImage,2,PS_INTERPOLATE_FLAT);
+    if (result != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,"return was not NULL, as expected.");
+        return 20;
+    }
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_TYPE) {
+        psLogMsg(__func__,PS_LOG_ERROR,"error message was not appropriate type.");
+        return 21;
+    }
+    psFree(err);
+
+    psFree(image);
+    psFree(result);
+    psFree(invImage);
+
+    return 0;
+}
+
+static psS32 testImageTransform(void)
+{
+    int cols = 16;
+    int rows = 32;
+
+    psPlaneTransform* trans = psPlaneTransformAlloc(2,2);
+    trans->x->coeff[1][0] = 0.5;
+    trans->y->coeff[0][1] = 1.5;
+
+    psImage* in = psImageAlloc(cols,rows,PS_TYPE_F32);
+    for (psS32 row=0;row<rows;row++) {
+        psF32* inRow = in->data.F32[row];
+        for (psS32 col=0;col<cols;col++) {
+            inRow[col] = (psF32)row+(psF32)col/1000.0f;
+        }
+    }
+    in->col0 = 1;
+    psImage* out = psImageTransform(NULL,
+                                    NULL,
+                                    in,
+                                    NULL,
+                                    0,
+                                    trans,
+                                    psRegionSet(1,1+cols*2,0,rows*2),
+                                    NULL,
+                                    PS_INTERPOLATE_FLAT,
+                                    -1);
+
+    if (out == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "out == NULL");
+        return 1;
+    }
+    if (out->type.type != PS_TYPE_F32) {
+        psError(PS_ERR_UNKNOWN, false,
+                "out->type.type != PS_TYPE_F32, out->type.type == %d",
+                out->type.type);
+        return 2;
+    }
+    if (out->numRows != rows*2 || out->numCols != cols*2) {
+        psError(PS_ERR_UNKNOWN, false,
+                "out size is %dx%d, not %dx%d",
+                out->numCols, out->numRows, cols*2, rows);
+        return 3;
+    }
+
+    for (psS32 row=0;row<out->numRows;row++) {
+        psF32* outRow = out->data.F32[row];
+        for (psS32 col=0;col<cols;col++) {
+            float inValue = p_psImagePixelInterpolateFLAT_F32(in,
+                            col*trans->x->coeff[1][0]+trans->x->coeff[0][0]+1,
+                            row*trans->y->coeff[0][1]+trans->y->coeff[0][0],
+                            NULL, 0,
+                            -1);
+            if (fabsf(outRow[col] - inValue) > 0.01) {
+                psError(PS_ERR_UNKNOWN, false,
+                        "out at %d,%d was %g, expected %g",
+                        col,row,outRow[col], inValue);
+                return 4;
+            }
+        }
+    }
+
+    psFree(out);
+    psFree(in);
+    psFree(trans);
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageInterpolate.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageInterpolate.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageInterpolate.c	(revision 22158)
@@ -0,0 +1,282 @@
+/** @file tst_psImageInterpolate.c
+ *
+ * @brief Contains the tests for psImagePixelInterpolate
+ *
+ * @author Eric Van Alst, MHPCC
+ *
+ * @version $Revision: 1.1 $
+ *          $Name: not supported by cvs2svn $
+ * @date $Date: 2005-07-13 02:47:00 $
+ *
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "psTest.h"
+#include "pslib_strict.h"
+
+#define GENIMAGE(img,c,r,TYP,valueFcn) \
+img = psImageAlloc(c,r,PS_TYPE_##TYP); \
+for(psU32 row=0; row<r; row++) { \
+    ps##TYP* imgRow = img->data.TYP[row]; \
+    for(psU32 col=0; col<c; col++) { \
+        imgRow[col] = (ps##TYP)(valueFcn); \
+    } \
+}
+
+#define CHECK_INTERP_VALUE(img,x,y,mask,maskval,exposed,TYPE,expected) \
+val = (psF32)psImagePixelInterpolate(img,x,y,mask,maskval,exposed,PS_INTERPOLATE_##TYPE); \
+printf("returned = %.2f    expected = %.2f\n",val,expected); \
+if(fabsf(val-expected)>FLT_EPSILON) { \
+    psError(PS_ERR_UNKNOWN,true,"Return value is not as expected."); \
+    return 1; \
+}
+
+#define CHECK_INTERP_BY_TYPE(TYPE) \
+GENIMAGE(img1,10,10,TYPE,row+col) \
+CHECK_INTERP_VALUE(img1,1.9,1.6,NULL,0,0,FLAT,2.0) \
+CHECK_INTERP_VALUE(img1,4.0,2.0,NULL,0,0,BILINEAR,5.0) \
+psFree(img1);
+
+static psS32 testInterpolateFlatBilinear(void);
+static psS32 testInterpolateError(void);
+static psS32 testInterpolateMaskFlatBilinear(void);
+static psS32 testInterpolate1D(void);
+
+testDescription tests[] = {
+                              {testInterpolateFlatBilinear,999,"psImagePixelInterpolate",0,false},
+                              {testInterpolateError,999,"psImagePixelInterpolate",0,false},
+                              {testInterpolateMaskFlatBilinear,999,"psImagePixelInterpolate",0,false},
+                              {testInterpolate1D,999,"psImagePixelInterpolate",0,false},
+                              {NULL}
+                          };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    if ( !runTestSuite(stderr,"psImagePixelInterpolate",tests,argc,argv) ) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+psS32 testInterpolateFlatBilinear(void)
+{
+    psImage* img1;
+    psF32 val = 0;
+
+    // Perform simple(four neighbor) FLAT interpolation for all types
+    // Perform bilinear interpolation for all types
+    CHECK_INTERP_BY_TYPE(S8)
+    CHECK_INTERP_BY_TYPE(S16)
+    CHECK_INTERP_BY_TYPE(S32)
+    CHECK_INTERP_BY_TYPE(S64)
+    CHECK_INTERP_BY_TYPE(U8)
+    CHECK_INTERP_BY_TYPE(U16)
+    CHECK_INTERP_BY_TYPE(U32)
+    CHECK_INTERP_BY_TYPE(U64)
+    CHECK_INTERP_BY_TYPE(F32)
+    CHECK_INTERP_BY_TYPE(F64)
+    CHECK_INTERP_BY_TYPE(C32)
+    CHECK_INTERP_BY_TYPE(C64)
+
+    return 0;
+}
+
+psS32 testInterpolateError(void)
+{
+    psF32 val = 0;
+    psImage* img1 = NULL;
+
+    // Perform interpolation with NULL input image and verify return and error message
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    val = psImagePixelInterpolate(img1,1.2,1.2,NULL,0,5.0,PS_INTERPOLATE_FLAT);
+    if(val != 5.0) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return the unexposed value");
+        return 10;
+    }
+
+    // Perform interpolation with invalid input image type
+    img1 = psImageAlloc(10,10,PS_TYPE_BOOL);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    val = psImagePixelInterpolate(img1,1.2,1.2,NULL,0,10.0,PS_INTERPOLATE_FLAT);
+    if(val != 10.0) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return the unexposed value");
+        return 11;
+    }
+
+    // Perform interpolation with invalid method
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    val = psImagePixelInterpolate(img1,1.2,1.2,NULL,0,10.0,PS_INTERPOLATE_BILINEAR+1);
+    if(val != 10.0) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return the unexposed value");
+        return 12;
+    }
+
+    psFree(img1);
+
+    return 0;
+}
+
+// The following assumptions about the test image are:
+//
+//                     col
+//             0   1   2   3   4   5   6   7  ...
+//
+// row 0       0   1   2   3   4   5   6   7
+// row 1       1   2   3   4   5   6   7   8
+// row 2       2   3   4   5   6   7   8   9
+// ...
+
+psS32 testInterpolateMaskFlatBilinear(void)
+{
+    psImage* img1 = NULL;
+    psImage* msk1 = NULL;
+    psF32 val = 0;
+
+    // Perform interpolate with mask and mask value set at nearest pixel to verify
+    // the unexposed value is return
+    GENIMAGE(img1,10,10,F32,row+col)
+    GENIMAGE(msk1,10,10,U8,0)
+    msk1->data.U8[1][1] = 1;
+    CHECK_INTERP_VALUE(img1,1.9,1.6,msk1,1,10.0,FLAT,10.0)
+    psFree(msk1);
+    psFree(img1);
+
+    // Perform interpolate with mask and one mask value for bilinear (upper left pixel)
+    GENIMAGE(img1,10,10,F32,row+col)
+    GENIMAGE(msk1,10,10,U8,0)
+    msk1->data.U8[1][3] = 1;
+    CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,5.25)
+    psFree(msk1);
+    psFree(img1);
+
+    // Perform interpolate with mask and one mask value for bilinear (upper right pixel)
+    GENIMAGE(img1,10,10,F32,row+col)
+    GENIMAGE(msk1,10,10,U8,0)
+    msk1->data.U8[1][4] = 1;
+    CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,4.75)
+    psFree(msk1);
+    psFree(img1);
+
+    // Perform interpolate with mask and one mask value for bilinear (lower left pixel)
+    GENIMAGE(img1,10,10,F32,row+col)
+    GENIMAGE(msk1,10,10,U8,0)
+    msk1->data.U8[2][3] = 1;
+    CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,5.25)
+    psFree(msk1);
+    psFree(img1);
+
+    // Perform interpolate with mask and one mask value for bilinear (lower right pixel)
+    GENIMAGE(img1,10,10,F32,row+col)
+    GENIMAGE(msk1,10,10,U8,0)
+    msk1->data.U8[2][4] = 1;
+    CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,4.75)
+    psFree(msk1);
+    psFree(img1);
+
+    // Perform interpolate with mask and one mask value for bilinear (upper pixels)
+    GENIMAGE(img1,10,10,F32,row+col)
+    GENIMAGE(msk1,10,10,U8,0)
+    msk1->data.U8[1][3] = 1;
+    msk1->data.U8[1][4] = 1;
+    CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,5.5)
+    psFree(msk1);
+    psFree(img1);
+
+    // Perform interpolate with mask and one mask value for bilinear (lower pixels)
+    GENIMAGE(img1,10,10,F32,row+col)
+    GENIMAGE(msk1,10,10,U8,0)
+    msk1->data.U8[2][3] = 1;
+    msk1->data.U8[2][4] = 1;
+    CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,4.5)
+    psFree(msk1);
+    psFree(img1);
+
+    // Perform interpolate with mask and one mask value for bilinear (left pixels)
+    GENIMAGE(img1,10,10,F32,row+col)
+    GENIMAGE(msk1,10,10,U8,0)
+    msk1->data.U8[1][3] = 1;
+    msk1->data.U8[2][3] = 1;
+    CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,5.5)
+    psFree(msk1);
+    psFree(img1);
+
+    // Perform interpolate with mask and one mask value for bilinear (right pixels)
+    GENIMAGE(img1,10,10,F32,row+col)
+    GENIMAGE(msk1,10,10,U8,0)
+    msk1->data.U8[1][4] = 1;
+    msk1->data.U8[2][4] = 1;
+    CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,4.5)
+    psFree(msk1);
+    psFree(img1);
+
+    // Perform interpolate with mask only one valid pixel (upper left)
+    GENIMAGE(img1,10,10,F32,row+col)
+    GENIMAGE(msk1,10,10,U8,0)
+    msk1->data.U8[1][4] = 1;
+    msk1->data.U8[2][3] = 1;
+    msk1->data.U8[2][4] = 1;
+    CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,4.0)
+    psFree(msk1);
+    psFree(img1);
+
+    // Perform interpolate with mask only one valid pixel (upper right)
+    GENIMAGE(img1,10,10,F32,row+col)
+    GENIMAGE(msk1,10,10,U8,0)
+    msk1->data.U8[1][3] = 1;
+    msk1->data.U8[2][3] = 1;
+    msk1->data.U8[2][4] = 1;
+    CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,5.0)
+    psFree(msk1);
+    psFree(img1);
+
+    // Perform interpolate with mask only one valid pixel (lower left)
+    GENIMAGE(img1,10,10,F32,row+col)
+    GENIMAGE(msk1,10,10,U8,0)
+    msk1->data.U8[1][3] = 1;
+    msk1->data.U8[1][4] = 1;
+    msk1->data.U8[2][4] = 1;
+    CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,5.0)
+    psFree(msk1);
+    psFree(img1);
+
+    // Perform interpolate with mask only one valid pixel (lower right)
+    GENIMAGE(img1,10,10,F32,row+col)
+    GENIMAGE(msk1,10,10,U8,0)
+    msk1->data.U8[1][3] = 1;
+    msk1->data.U8[1][4] = 1;
+    msk1->data.U8[2][3] = 1;
+    CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,6.0)
+    psFree(msk1);
+    psFree(img1);
+
+    // Perform interpolate with mask no valid pixels
+    GENIMAGE(img1,10,10,F32,row+col)
+    GENIMAGE(msk1,10,10,U8,0)
+    msk1->data.U8[1][3] = 1;
+    msk1->data.U8[1][4] = 1;
+    msk1->data.U8[2][3] = 1;
+    msk1->data.U8[2][4] = 1;
+    CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,0.0)
+    psFree(msk1);
+    psFree(img1);
+    return 0;
+}
+
+// Perform interpolation for a 1D image
+psS32 testInterpolate1D(void)
+{
+    psImage* img1 = NULL;
+    psF32 val = 0;
+
+    GENIMAGE(img1,10,1,F32,row+col)
+    CHECK_INTERP_VALUE(img1,4.0,0.0,NULL,0,100.0,BILINEAR,3.5)
+
+    psFree(img1);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageMaskOps.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageMaskOps.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageMaskOps.c	(revision 22158)
@@ -0,0 +1,222 @@
+/** @file  tst_psImageMaskOps.c
+ *
+ *  @brief Contains the tests for psMaskOps.[ch]
+ *
+ *
+ *  @author David Robbins, MHPCC
+ *
+ *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-10-08 03:51:20 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <complex.h>
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdlib.h>
+#include <string.h>                    // for memset
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "psTest.h"
+#include "pslib_strict.h"
+#include "psType.h"
+
+static psS32 testImageKeepMask(void);
+static psS32 testImageGrowMask(void);
+
+testDescription tests[] = {
+                              {testImageKeepMask,0,"psImageKeep and Mask",0,false},
+                              {testImageGrowMask,0,"psImageGrowMask",0,false},
+                              {NULL}
+                          };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    return ! runTestSuite(stderr,"psImage",tests,argc,argv);
+}
+
+psS32 testImageKeepMask(void)
+{
+    //psImageMaskRegion
+    //psImageKeepRegion
+    //psImageMaskCircle
+    //psImageKeepCircle
+    psImage *in = psImageAlloc(3,3,PS_TYPE_MASK);
+    psRegion reg;
+    reg.x0 = 0;
+    reg.x1 = 1;
+    reg.y0 = 0;
+    reg.y1 = 1;
+    psMaskType mask = 2;
+    in->data.PS_TYPE_MASK_DATA[0][0] = 2;
+    in->data.PS_TYPE_MASK_DATA[0][1] = 0;
+    in->data.PS_TYPE_MASK_DATA[0][2] = 1;
+    in->data.PS_TYPE_MASK_DATA[1][0] = 4;
+    in->data.PS_TYPE_MASK_DATA[1][1] = 0;
+    in->data.PS_TYPE_MASK_DATA[1][2] = 3;
+    in->data.PS_TYPE_MASK_DATA[2][0] = 2;
+    in->data.PS_TYPE_MASK_DATA[2][1] = 1;
+    in->data.PS_TYPE_MASK_DATA[2][2] = 2;
+
+    printf("\n Mask Region------");
+    psImageMaskRegion(in, reg, "|", mask);
+    for(int i = 0; i < 3; i++) {
+        for (int j = 0; j < 3; j++) {
+            printf("\nin->data.u8 [i][j] i=%d, j=%d = %u", i, j, in->data.PS_TYPE_MASK_DATA[i][j]);
+        }
+    }
+
+    in->data.PS_TYPE_MASK_DATA[0][0] = 2;
+    in->data.PS_TYPE_MASK_DATA[0][1] = 0;
+    in->data.PS_TYPE_MASK_DATA[0][2] = 1;
+    in->data.PS_TYPE_MASK_DATA[1][0] = 4;
+    in->data.PS_TYPE_MASK_DATA[1][1] = 0;
+    in->data.PS_TYPE_MASK_DATA[1][2] = 3;
+    in->data.PS_TYPE_MASK_DATA[2][0] = 2;
+    in->data.PS_TYPE_MASK_DATA[2][1] = 1;
+    in->data.PS_TYPE_MASK_DATA[2][2] = 2;
+    psImageKeepRegion(in, reg, "AND", mask);
+    printf("\n Keep Region------");
+    for(int i = 0; i < 3; i++) {
+        for (int j = 0; j < 3; j++) {
+            printf("\nin->data.u8 [i][j] i=%d, j=%d = %u", i, j, in->data.PS_TYPE_MASK_DATA[i][j]);
+        }
+    }
+
+    //Mask Circle and Keep Circle Functions
+    in->data.PS_TYPE_MASK_DATA[0][0] = 2;
+    in->data.PS_TYPE_MASK_DATA[0][1] = 0;
+    in->data.PS_TYPE_MASK_DATA[0][2] = 1;
+    in->data.PS_TYPE_MASK_DATA[1][0] = 4;
+    in->data.PS_TYPE_MASK_DATA[1][1] = 0;
+    in->data.PS_TYPE_MASK_DATA[1][2] = 3;
+    in->data.PS_TYPE_MASK_DATA[2][0] = 2;
+    in->data.PS_TYPE_MASK_DATA[2][1] = 1;
+    in->data.PS_TYPE_MASK_DATA[2][2] = 2;
+    psImageMaskCircle(in, 1, 1, 1, "XOR", mask);
+    printf("\n Mask Circle------");
+    for(int i = 0; i < 3; i++) {
+        for (int j = 0; j < 3; j++) {
+            printf("\nin->data.u8 [i][j] i=%d, j=%d = %u", i, j, in->data.PS_TYPE_MASK_DATA[i][j]);
+        }
+    }
+
+    in->data.PS_TYPE_MASK_DATA[0][0] = 2;
+    in->data.PS_TYPE_MASK_DATA[0][1] = 0;
+    in->data.PS_TYPE_MASK_DATA[0][2] = 1;
+    in->data.PS_TYPE_MASK_DATA[1][0] = 4;
+    in->data.PS_TYPE_MASK_DATA[1][1] = 0;
+    in->data.PS_TYPE_MASK_DATA[1][2] = 3;
+    in->data.PS_TYPE_MASK_DATA[2][0] = 2;
+    in->data.PS_TYPE_MASK_DATA[2][1] = 1;
+    in->data.PS_TYPE_MASK_DATA[2][2] = 2;
+    psImageKeepCircle(in, 1, 1, 1, "=", mask);
+    printf("\n Keep Circle------");
+    for(int i = 0; i < 3; i++) {
+        for (int j = 0; j < 3; j++) {
+            printf("\nin->data.u8 [i][j] i=%d, j=%d = %u", i, j, in->data.PS_TYPE_MASK_DATA[i][j]);
+        }
+    }
+    fflush(stdout);
+
+    //Error Checks
+    //incorrect logical operation
+    printf("\n");
+    psImageKeepRegion(in, reg, "+", mask);
+    //null image
+    psImage *none = NULL;
+    psImageMaskCircle(none, 1, 1, 1, "&", mask);
+
+    psFree(in);
+    return 0;
+}
+
+psS32 testImageGrowMask(void)
+{
+    psImage *in = NULL;
+    psImage *out = NULL;
+    psImage *test = NULL;
+    psMaskType maskVal = 0;
+    psMaskType growVal = 0;
+    unsigned int growSize = 0;
+    //return null for null input image
+    out = psImageGrowMask(out, in, maskVal, growSize, growVal);
+    if (out != NULL) {
+        fprintf(stderr,
+                "psImageGrowMask failed to return NULL for NULL image input.\n");
+        return 1;
+    }
+    in = psImageAlloc(5, 5, PS_TYPE_MASK);
+    //return null for incompatible image size
+    test = psImageAlloc(2, 2, PS_TYPE_MASK);
+    out = psImageGrowMask(test, in, maskVal, growSize, growVal);
+    if (out != NULL) {
+        fprintf(stderr,
+                "psImageGrowMask failed to return NULL for incompatible image size.\n");
+        return 2;
+    }
+    //return null for incompatible out image type
+    test = psImageRecycle(test, 5, 5, PS_TYPE_F32);
+    out = psImageGrowMask(test, in, maskVal, growSize, growVal);
+    if (out != NULL) {
+        fprintf(stderr,
+                "psImageGrowMask failed to return NULL for incompatible output image type.\n");
+        return 3;
+    }
+    //return NULL for input image that doesn't match PS_TYPE_MASK
+    in = psImageRecycle(in, 5, 5, PS_TYPE_F32);
+    out = psImageGrowMask(test, in, maskVal, growSize, growVal);
+    if (out != NULL) {
+        fprintf(stderr,
+                "psImageGrowMask failed to return NULL for incompatible input image type.\n");
+        return 4;
+    }
+    //Test for valid function (image growth)
+    in = psImageRecycle(in, 5, 5, PS_TYPE_MASK);
+    in->data.PS_TYPE_MASK_DATA[0][0] = 1;
+    in->data.PS_TYPE_MASK_DATA[0][1] = 1;
+    in->data.PS_TYPE_MASK_DATA[0][2] = 1;
+    in->data.PS_TYPE_MASK_DATA[0][3] = 1;
+    in->data.PS_TYPE_MASK_DATA[0][4] = 1;
+    in->data.PS_TYPE_MASK_DATA[1][0] = 1;
+    in->data.PS_TYPE_MASK_DATA[1][1] = 1;
+    in->data.PS_TYPE_MASK_DATA[1][2] = 2;
+    in->data.PS_TYPE_MASK_DATA[1][3] = 1;
+    in->data.PS_TYPE_MASK_DATA[1][4] = 1;
+    in->data.PS_TYPE_MASK_DATA[2][0] = 1;
+    in->data.PS_TYPE_MASK_DATA[2][1] = 1;
+    in->data.PS_TYPE_MASK_DATA[2][2] = 2;
+    in->data.PS_TYPE_MASK_DATA[2][3] = 1;
+    in->data.PS_TYPE_MASK_DATA[2][4] = 1;
+    in->data.PS_TYPE_MASK_DATA[3][0] = 1;
+    in->data.PS_TYPE_MASK_DATA[3][1] = 1;
+    in->data.PS_TYPE_MASK_DATA[3][2] = 1;
+    in->data.PS_TYPE_MASK_DATA[3][3] = 1;
+    in->data.PS_TYPE_MASK_DATA[3][4] = 2;
+    in->data.PS_TYPE_MASK_DATA[4][0] = 1;
+    in->data.PS_TYPE_MASK_DATA[4][1] = 1;
+    in->data.PS_TYPE_MASK_DATA[4][2] = 1;
+    in->data.PS_TYPE_MASK_DATA[4][3] = 1;
+    in->data.PS_TYPE_MASK_DATA[4][4] = 1;
+    maskVal = 2;
+    growSize = 1;
+    growVal = 2;
+
+    out = psImageGrowMask(out, in, maskVal, growSize, growVal);
+    //0,2 1,1 1,3 2,1 2,3 3,2 should all be 3.  All other should be unchanged.
+    for (int i = 0; i < 5; i++) {
+        printf("\n ");
+        for (int j = 0; j < 5; j++) {
+            printf("  %d,%d= %d  ", i, j, out->data.PS_TYPE_MASK_DATA[i][j]);
+        }
+    }
+    psFree(out);
+    psFree(in);
+    psFree(test);
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImagePixelExtract.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImagePixelExtract.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImagePixelExtract.c	(revision 22158)
@@ -0,0 +1,1557 @@
+/** @file  tst_psImageExtraction.c
+*
+*  @brief Contains the tests for psImageExtraction.[ch]
+*
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2006-05-16 23:12:20 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+#include<stdlib.h>
+#include<string.h>
+
+#include "psTest.h"
+#include "pslib_strict.h"
+#include "psType.h"
+
+static psS32 testImageSlice(void);
+static psS32 testImageCut(void);
+static psS32 testImageRadialCut(void);
+static psS32 testImageRowColError(void);
+static psS32 testImageRowColF32(void);
+static psS32 testImageRowColF64(void);
+static psS32 testImageRowColS8(void);
+static psS32 testImageRowColS16(void);
+static psS32 testImageRowColS32(void);
+static psS32 testImageRowColS64(void);
+static psS32 testImageRowColU8(void);
+static psS32 testImageRowColU16(void);
+static psS32 testImageRowColU32(void);
+static psS32 testImageRowColU64(void);
+
+
+
+testDescription tests[] = {
+                              {testImageSlice, 552, "psImageSlice", 0, false},
+                              {testImageCut, 555, "psImageCut", 0, false},
+                              {testImageRadialCut, 556, "psImageRadialCut", 0, false},
+                              {testImageRowColError, 557, "testImageRowColError", 0, false},
+                              {testImageRowColF32, 558, "psImageRowColF32", 0, false},
+                              {testImageRowColF64, 559, "psImageRowColF64", 0, false},
+                              {testImageRowColU8, 560, "psImageRowColU8", 0, false},
+                              {testImageRowColU16, 561, "psImageRowColU16", 0, false},
+                              {testImageRowColU32, 562, "psImageRowColU32", 0, false},
+                              {testImageRowColU64, 563, "psImageRowColU64", 0, false},
+                              {testImageRowColS8, 564, "psImageRowColS8", 0, false},
+                              {testImageRowColS16, 565, "psImageRowColS16", 0, false},
+                              {testImageRowColS32, 566, "psImageRowColS32", 0, false},
+                              {testImageRowColS64, 567, "psImageRowColS64", 0, false},
+                              {NULL}
+                          };
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    return ! runTestSuite( stderr, "psImage", tests, argc, argv );
+}
+
+psS32 testImageSlice(void)
+{
+    const psS32 r = 200;
+    const psS32 c = 300;
+    const psS32 m = r / 2 -1;
+    const psS32 n = r / 4 -1;
+    psVector* out = NULL;
+    psImage* image;
+    psPixels* positions = psPixelsAlloc( r );
+    psImage* mask = psImageAlloc( c, r, PS_TYPE_MASK );
+    psStats* stat = psStatsAlloc( PS_STAT_SAMPLE_MEDIAN );
+
+    /*
+        This function shall extract pixels from a specified region of a psImage
+        structure into a vector using a specified statistical method.
+
+        Verify the returned psVector structure contains expected data, if the
+        input psImage input has known data and the psStats structure specifies
+        a known statistical method. At least two different statistical methods
+        should be used within a valid range of psImage data. Allow for a delta
+        when comparing results to allow for testing a different platforms. Two
+        cases should be used for each possible direction. Data region cases
+        should include 0x0, 1x1, Nx1, 1xN, NxN, MxN
+
+     */
+
+    for ( psS32 row = 0;row < r;row++ ) {
+        psMaskType* maskRow = mask->data.PS_TYPE_MASK_DATA[row];
+        for ( psS32 col = 0;col < c;col++ ) {
+            maskRow[ col ] = 0;
+        }
+    }
+
+    #define PSIMAGESLICE_TEST1(TYPE,M,N,DIRECTION,TRUTH_SIZE,TRUTHPIX_X,TRUTHPIX_Y,TESTNUM) \
+    image = psImageAlloc( c, r, PS_TYPE_##TYPE ); \
+    for ( psS32 row = 0;row < r;row++ ) { \
+        ps##TYPE *imageRow = image->data.TYPE[ row ]; \
+        ps##TYPE rowOffset = row * 2; \
+        for ( psS32 col = 0;col < c;col++ ) { \
+            imageRow[ col ] = col + rowOffset; \
+        } \
+    } \
+    image->col0 = 1; \
+    image->row0 = 1; \
+    out = psImageSlice(out,positions,image,mask,1, \
+                       psRegionSet(1+c/10,1+c/10+M,1+r/10,1+r/10+N),DIRECTION,stat); \
+    \
+    if (out->n != TRUTH_SIZE) { \
+        psError(PS_ERR_UNKNOWN,true,"Number of results is wrong (%d, not %d)", \
+                out->n,TRUTH_SIZE); \
+        return TESTNUM*4+1; \
+    } \
+    \
+    if (positions->n != TRUTH_SIZE) { \
+        psError(PS_ERR_UNKNOWN,true,"Number of results for positions vector is wrong (%d, not %d)", \
+                positions->n,TRUTH_SIZE); \
+        return TESTNUM*4+2; \
+    } \
+    \
+    for (psS32 i=0;i<out->n;i++) { \
+        if (fabs(out->data.F64[i]-image->data.TYPE[r/10+TRUTHPIX_Y][c/10+TRUTHPIX_X]) > 1.0/(psF64)r) { \
+            psError(PS_ERR_UNKNOWN,true,"Improper result at position %d.  Got %g, expected %g",i, \
+                    out->data.F64[i],image->data.TYPE[r/10+TRUTHPIX_Y][c/10+TRUTHPIX_X]); \
+            return TESTNUM*4+3; \
+        } \
+        if (DIRECTION == PS_CUT_X_POS || DIRECTION == PS_CUT_X_NEG) { \
+            if (positions->data[i].x != c/10+TRUTHPIX_X) { \
+                psError(PS_ERR_UNKNOWN,true,"Improper positions (%d vs %d) result @ %d.", \
+                        positions->data[i].x,c/10+TRUTHPIX_X,i); \
+                return TESTNUM*4+4; \
+            } \
+        } else { \
+            if (positions->data[i].y != r/10+TRUTHPIX_Y) { \
+                psError(PS_ERR_UNKNOWN,true,"Improper positions (%d vs %d) result @ %d.", \
+                        positions->data[i].y,r/10+TRUTHPIX_Y,i); \
+                return TESTNUM*4+4; \
+            } \
+        } \
+    } \
+    psFree(image);
+
+    #define PSIMAGESLICE_TEST(TYPE) \
+    /* test MxN case */ \
+    PSIMAGESLICE_TEST1(TYPE, m, n, PS_CUT_X_POS, m, i, n / 2, 0 ); \
+    PSIMAGESLICE_TEST1(TYPE, m, n, PS_CUT_X_NEG, m, m - 1 - i, n / 2, 1 ); \
+    PSIMAGESLICE_TEST1(TYPE, m, n, PS_CUT_Y_POS, n, m / 2, i, 2 ); \
+    PSIMAGESLICE_TEST1(TYPE, m, n, PS_CUT_Y_NEG, n, m / 2, n - 1 - i, 3 ); \
+    \
+    /* test Mx1 case */ \
+    PSIMAGESLICE_TEST1(TYPE, m, 1, PS_CUT_X_POS, m, i, 0, 4 ); \
+    PSIMAGESLICE_TEST1(TYPE, m, 1, PS_CUT_X_NEG, m, m - 1 - i, 0, 5 ); \
+    PSIMAGESLICE_TEST1(TYPE, m, 1, PS_CUT_Y_POS, 1, m / 2, 0, 6 ); \
+    PSIMAGESLICE_TEST1(TYPE, m, 1, PS_CUT_Y_NEG, 1, m / 2, 0, 7 ); \
+    \
+    /* test 1xN case */ \
+    PSIMAGESLICE_TEST1(TYPE, 1, n, PS_CUT_X_POS, 1, 0, n / 2, 8 ); \
+    PSIMAGESLICE_TEST1(TYPE, 1, n, PS_CUT_X_NEG, 1, 0, n / 2, 9 ); \
+    PSIMAGESLICE_TEST1(TYPE, 1, n, PS_CUT_Y_POS, n, 0, i, 10 ); \
+    PSIMAGESLICE_TEST1(TYPE, 1, n, PS_CUT_Y_NEG, n, 0, n - 1 - i, 11 ); \
+    \
+    /* test 1x1 case */ \
+    PSIMAGESLICE_TEST1(TYPE, 1, 1, PS_CUT_X_POS, 1, 0, 0, 12 ); \
+    PSIMAGESLICE_TEST1(TYPE, 1, 1, PS_CUT_X_NEG, 1, 0, 0, 13 ); \
+    PSIMAGESLICE_TEST1(TYPE, 1, 1, PS_CUT_Y_POS, 1, 0, 0, 14 ); \
+    PSIMAGESLICE_TEST1(TYPE, 1, 1, PS_CUT_Y_NEG, 1, 0, 0, 15 ); \
+
+    PSIMAGESLICE_TEST(F32);
+    PSIMAGESLICE_TEST(F64);
+    PSIMAGESLICE_TEST(U16);
+
+    image = psImageAlloc( c, r, PS_TYPE_F32 );
+
+    /*
+       Verify the returned psVector structure pointer is null and program
+       execution doesn't stop, if input psImage input is null.
+
+    */
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error." );
+    out = psImageSlice( out,
+                        NULL, NULL,
+                        NULL, 0,
+                        psRegionSet(c/10, c/10 + 1, r/10, r/10 + 1),
+                        PS_CUT_X_POS,
+                        stat );
+    if ( out != NULL ) {
+        psError( PS_ERR_UNKNOWN,true, "Giving a NULL image, psImageSlice didn't return NULL as expected" );
+        return 101;
+    }
+
+
+    /*
+       Verify the returned psVector structure pointer is null and program
+       execution doesn't stop, if input psStats stats is null.
+    */
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error." );
+    out = psImageSlice( out,
+                        NULL, image,
+                        mask, 1,
+                        psRegionSet(c/10, c/10 + 1, r/10, r/10 + 1),
+                        PS_CUT_X_POS,
+                        NULL );
+    if ( out != NULL ) {
+        psError( PS_ERR_UNKNOWN,true, "Giving a NULL stat struct, psImageSlice didn't return NULL as expected" );
+        return 102;
+    }
+    /*
+
+       Verify the returned psVector structure pointer is null and program
+       executions doesn't stop, if the input direction is not set to one of
+       the two valid values.
+    */
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error." );
+    out = psImageSlice( out, NULL,
+                        image,
+                        mask, 1,
+                        psRegionSet(c/10, c/10 + 1, r/10, r/10 + 1),
+                        5,
+                        stat);
+    if ( out != NULL ) {
+        psError( PS_ERR_UNKNOWN,true, "Giving a bogus direction flag, psImageSlice didn't return NULL as expected" );
+        return 103;
+    }
+
+    /*
+       Verify the returned psVector structure pointer is null and program
+       execution doesn't stop, if the input nrow and/or ncol are zero.
+    */
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error." );
+    out = psImageSlice( out,
+                        NULL,
+                        image,
+                        mask, 1,
+                        psRegionSet(c/10, c/10, r/10, r/10),
+                        PS_CUT_X_POS,
+                        stat );
+    if ( out != NULL ) {
+        psError( PS_ERR_UNKNOWN,true, "Giving a 0x0 region, psImageSlice didn't return NULL as expected" );
+        return 104;
+    }
+
+    /*
+       Verify the returned psVector structure pointer is null and program
+       execution doesn't stop, if the inputs row, col, nrow, ncol specify a
+       regions of data that is not within the input psImage structure.
+    */
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error." );
+    out = psImageSlice( out, NULL,
+                        image,
+                        mask, 1,
+                        psRegionSet(c+1, c+2, r/10, r/10 + 10),
+                        PS_CUT_X_POS,
+                        stat );
+    if ( out != NULL ) {
+        psError( PS_ERR_UNKNOWN,true, "Giving an invalid x position, psImageSlice didn't return NULL as expected" );
+        return 105;
+    }
+
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error." );
+    out = psImageSlice( out, NULL,
+                        image,
+                        mask, 1,
+                        psRegionSet(c/10, c/10 + 1, r+1,r+5),
+                        PS_CUT_X_POS,
+                        stat );
+    if ( out != NULL ) {
+        psError( PS_ERR_UNKNOWN,true, "Giving an invalid y position, psImageSlice didn't return NULL as expected" );
+        return 106;
+    }
+
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error." );
+    out = psImageSlice( out, NULL,
+                        image,
+                        mask, 1,
+                        psRegionSet(c/10, c+1, r/10, r/10+1),
+                        PS_CUT_X_POS,
+                        stat);
+    if ( out != NULL ) {
+        psError( PS_ERR_UNKNOWN,true, "Giving an invalid numCols, psImageSlice didn't return NULL as expected" );
+        return 107;
+    }
+
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error." );
+    out = psImageSlice( out, NULL,
+                        image,
+                        mask, 1,
+                        psRegionSet(c/10, c/10 + 1, r/10, r + 1),
+                        PS_CUT_X_POS,
+                        stat);
+    if ( out != NULL ) {
+        psError( PS_ERR_UNKNOWN,true, "Giving an invalid numRows, psImageSlice didn't return NULL as expected" );
+        return 108;
+    }
+
+    /*
+       Verify the returned psVector structure pointer is null and program
+       execution doesn't stop, if the input psStat structure member options is
+       zero which indicates no statistic method specified.
+    */
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error." );
+    stat->options = 0;
+    out = psImageSlice( out, NULL,
+                        image,
+                        mask, 1,
+                        psRegionSet(c/10, c/10 + 1, r/10, r/10+1),
+                        PS_CUT_X_POS,
+                        stat);
+    if ( out != NULL ) {
+        psError( PS_ERR_UNKNOWN,true, "Giving an invalid numRows, psImageSlice didn't return NULL as expected" );
+        return 109;
+    }
+
+    /* Verify that a mask of different size than the input image returns null and program
+       execution doesn't stop.
+    */
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error mask size != image size.");
+    stat->options = PS_STAT_SAMPLE_MEDIAN;
+    psImage* maskSz = psImageAlloc( r, c, PS_TYPE_MASK );
+    out = psImageSlice( out, NULL,
+                        image,
+                        maskSz, 1,
+                        psRegionSet(c/10, c/10 + 1, r/10, r/10 + 1),
+                        PS_CUT_X_POS,
+                        stat);
+    if ( out != NULL ) {
+        psError( PS_ERR_UNKNOWN,true, "Mask size different than image size didn't return NULL as expected" );
+        return 110;
+    }
+
+    /* Verify the a invalid type mask returns null and program execution doesn't stop.
+    */
+    psLogMsg( __func__, PS_LOG_INFO, "Following should be an error invalid mask type.");
+    psImage* maskS8 = psImageAlloc( c, r, PS_TYPE_S8 );
+    out =  psImageSlice( out, NULL,
+                         image,
+                         maskS8, 1,
+                         psRegionSet(c/10, c/10 + 1, r/10, r/10 + 1),
+                         PS_CUT_X_POS,
+                         stat);
+    if ( out != NULL ) {
+        psError( PS_ERR_UNKNOWN,true, "Mask invalid type didn't return NULL as expected.");
+        return 111;
+    }
+
+    //Added tests after subimage changes.
+    psFree(image);
+    image = psImageAlloc( c, r, PS_TYPE_F64 );
+    for ( psS32 row = 0;row < r;row++ ) {
+        psF64 *imageRow = image->data.F64[ row ];
+        psF64 rowOffset = row * 2;
+        for ( psS32 col = 0;col < c;col++ ) {
+            imageRow[ col ] = col + rowOffset;
+        }
+    }
+    image->col0 = 1;
+    image->row0 = 1;
+    psFree(out);
+    out = NULL;
+    out = psImageSlice(out,positions,image,mask,1,
+                       psRegionSet(1,c,1,r),PS_CUT_X_POS,stat);
+    if (out == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psImageSlice failed to return the correct psVector.  Got NULL instead.\n");
+        return 112;
+    }
+    psFree(out);
+    out = NULL;
+    //Return NULL for incorrect image inputs.
+    image->row0 = -1;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    out = psImageSlice(out,positions,image,mask,1,
+                       psRegionSet(1,c,1,r),PS_CUT_X_POS,stat);
+    if (out != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageSlice failed to return NULL for invalid specified input.\n");
+        return 113;
+    }
+    image->col0 = -1;
+    image->row0 = 1;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    out = psImageSlice(out,positions,image,mask,1,
+                       psRegionSet(1,c,1,r),PS_CUT_X_POS,stat);
+    if (out != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageSlice failed to return NULL for invalid specified input.\n");
+        return 114;
+    }
+    image->col0 = 1;
+    //Return NULL for incorrect region inputs.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    out = psImageSlice(out,positions,image,mask,1,
+                       psRegionSet(0,c,1,r),PS_CUT_X_POS,stat);
+    if (out != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageSlice failed to return NULL for invalid specified input.\n");
+        return 115;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    out = psImageSlice(out,positions,image,mask,1,
+                       psRegionSet(1,c,1,r+1),PS_CUT_X_POS,stat);
+    if (out != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageSlice failed to return NULL for invalid specified input.\n");
+        return 116;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    out = psImageSlice(out,positions,image,mask,1,
+                       psRegionSet(1,c,1,-r-2),PS_CUT_X_POS,stat);
+    if (out != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageSlice failed to return NULL for invalid specified input.\n");
+        return 117;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    out = psImageSlice(out,positions,image,mask,1,
+                       psRegionSet(c,1,1,r),PS_CUT_X_POS,stat);
+    if (out != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageSlice failed to return NULL for invalid specified input.\n");
+        return 118;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    out = psImageSlice(out,positions,image,mask,1,
+                       psRegionSet(1,1,1,1),PS_CUT_X_POS,stat);
+    if (out != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageSlice failed to return NULL for invalid specified input.\n");
+        return 119;
+    }
+
+    //Make sure that regions match appropriately...
+    out = psImageSlice(out,positions,image,mask,1,
+                       psRegionSet(1,-1,1,-1),PS_CUT_Y_NEG,stat);
+    psVector *out2 = NULL;
+    out2 = psImageSlice(out2,positions,image,mask,1,
+                        psRegionSet(0,0,0,0),PS_CUT_Y_NEG,stat);
+    if (out == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psImageSlice incorrectly returned NULL for valid inputs.\n");
+        return 120;
+    } else if (out2 == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psImageSlice incorrectly returned NULL for valid inputs.\n");
+        return 121;
+    } else if (out->n != out2->n) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageSlice failed to return matching vectors for equivalent inputs.\n");
+        return 122;
+    } else if (out->data.F64[out->n-1] != out2->data.F64[out2->n-1] ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageSlice failed to return matching vectors for equivalent inputs.\n");
+        return 123;
+    }
+    psFree(out2);
+
+    psFree( image );
+    psFree( positions );
+    psFree( mask );
+    psFree( out );
+    psFree( stat );
+    psFree( maskS8 );
+    psFree( maskSz );
+
+    return 0;
+
+}
+
+static psS32 testImageCut(void)
+{
+    psS32 c = 300;
+    psS32 r = 200;
+    psS32 numPoints = 15;
+    float startCol[] = { 40,150, 40,  0,280, 40,280, -1,300, 20, 20, 20, 20, 20, 20};
+    float endCol[] =   {240,150,240,299, 40,240, 40,240,240, -1,300,240,240,240,240};
+    float startRow[] = { 20, 10,100,  0, 20,180,180, 10, 10, 10, 10, -1,200, 10, 10};
+    float endRow[] =   {160,180,100,199,160, 10, 10,180,180,180,180,180,180, -1,200};
+    psBool success[] = {true,true,true,true,true,true,true,false,false,false,false,false,false,false,false};
+    psU32 length = 100;
+
+    psImage* image = psImageAlloc(c,r,PS_TYPE_F32);
+    psImage* mask = psImageAlloc(c,r,PS_TYPE_MASK);
+    for (psS32 row = 0; row < image->numRows; row++) {
+        for (psS32 col = 0; col < image->numCols; col++) {
+            image->data.F32[row][col] = (psF32)col + (psF32)row/1000.0f;
+            if ((row & 0x0F) == 0) {
+                mask->data.PS_TYPE_MASK_DATA[row][col] = 1;
+            } else {
+                mask->data.PS_TYPE_MASK_DATA[row][col] = 0;
+            }
+        }
+    }
+    psVector* rows = psVectorAlloc(length,PS_TYPE_F32);
+    psVector* cols = psVectorAlloc(length,PS_TYPE_F32);
+
+    psVector* result = NULL;
+    for (psS32 n = 0; n < numPoints; n++) {
+        psVector* orig = result;
+        if (! success[n]) {
+            psLogMsg(__func__,PS_LOG_INFO,"The following should be an error.");
+        }
+        if (n == 1) {
+            result = psImageCut(result,
+                                cols,rows,
+                                image,
+                                NULL,0,
+                                psRegionSet(startCol[n], endCol[n], startRow[n],endRow[n]),
+                                length,
+                                PS_INTERPOLATE_FLAT);
+        } else {
+            result = psImageCut(result,
+                                cols,rows,
+                                image,
+                                mask,1,
+                                psRegionSet(startCol[n], endCol[n], startRow[n], endRow[n]),
+                                length,
+                                PS_INTERPOLATE_FLAT);
+        }
+
+        if (success[n]) {
+            if (result == NULL) {
+                psLogMsg(__func__,PS_LOG_ERROR,
+                         "psImageCut returned NULL instead of a valid result.");
+                return n*10+1;
+            }
+
+            if (orig != NULL && orig != result) {
+                psLogMsg(__func__,PS_LOG_ERROR,
+                         "psImageCut didn't recycle the out parameter properly.");
+                return n*10+2;
+            }
+
+            float deltaRow = (endRow[n]-startRow[n])/(length-1);
+            float deltaCol = (endCol[n]-startCol[n])/(length-1);
+            psF32 truth;
+            for (psS32 i = 0; i < length; i++) {
+                float x = (float)startCol[n]+(float)i*deltaCol;
+                float y = (float)startRow[n]+(float)i*deltaRow;
+                if (n == 1) {
+                    truth = psImagePixelInterpolate( image, x, y,
+                                                     NULL,0,0,PS_INTERPOLATE_FLAT);
+                } else {
+                    truth = psImagePixelInterpolate( image, x, y,
+                                                     mask,1,0,PS_INTERPOLATE_FLAT);
+                }
+                if (fabs(result->data.F32[i]-truth) > FLT_EPSILON) {
+                    psLogMsg(__func__,PS_LOG_ERROR,
+                             "Bad result in position %d; Found %g but expected %g.",
+                             i, result->data.F32[i], truth);
+                    return n*10+5;
+                }
+                if (fabsf(x - cols->data.F32[i]) > FLT_EPSILON ||
+                        fabsf(y - rows->data.F32[i]) > FLT_EPSILON) {
+                    psLogMsg(__func__,PS_LOG_ERROR,
+                             "Bad resulting col/row at index %d; Found (%g,%g) but expected (%g,%g).",
+                             i, cols->data.F32[i], rows->data.F32[i], x, y);
+                    return n*10+6;
+                }
+            }
+        } else {
+            if (result != NULL) {
+                psLogMsg(__func__,PS_LOG_ERROR,
+                         "psImageCut did not return NULL with a cut of (%g,%g)->(%g,%g).",
+                         startCol[n],startRow[n],endCol[n],endRow[n]);
+                return n*10+7;
+            }
+            psErr* err = psErrorLast();
+            if (err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+                psLogMsg(__func__,PS_LOG_ERROR,
+                         "psImageCut did not generate proper error message.");
+                return 105;
+            }
+            psFree(err);
+        }
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error (NULL image).");
+    result = psImageCut(result,
+                        cols,rows,
+                        NULL,
+                        mask,1,
+                        psRegionSet(startCol[0], endCol[0], startRow[0], endRow[0]),
+                        length,
+                        PS_INTERPOLATE_FLAT);
+    if (result != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageCut did not return NULL given NULL image.");
+        return 100;
+    }
+    psErr* err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageCut did not generate proper error message given NULL image.");
+        return 101;
+    }
+    psFree(err);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error (length=0).");
+    result = psImageCut(result,
+                        cols,rows,
+                        image,
+                        mask,1,
+                        psRegionSet(startCol[0], endCol[0], startRow[0], endRow[0]),
+                        0,
+                        PS_INTERPOLATE_FLAT);
+    if (result != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageCut did not return NULL given length=0.");
+        return 102;
+    }
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageCut did not generate proper error message given length=0.");
+        return 103;
+    }
+    psFree(err);
+
+    psFree(result);
+    psFree(image);
+    psFree(mask);
+    psFree(rows);
+    psFree(cols);
+
+    return 0;
+}
+
+static psS32 testImageRadialCut(void)
+{
+    psS32 c = 300;
+    psS32 r = 200;
+    psS32 centerX = c/2;
+    psS32 centerY = r/2;
+    psErr* err = NULL;
+
+    psImage* image = psImageAlloc(c,r,PS_TYPE_F32);
+    psImage* mask = psImageAlloc(c,r,PS_TYPE_MASK);
+    for (psS32 row = 0; row < image->numRows; row++) {
+        for (psS32 col = 0; col < image->numCols; col++) {
+            image->data.F32[row][col] = sqrtf((col-centerX)*(col-centerX)+(row-centerY)*(row-centerY));
+            if ((row & 0x0F) == 0) {
+                mask->data.PS_TYPE_MASK_DATA[row][col] = 1;
+            } else {
+                mask->data.PS_TYPE_MASK_DATA[row][col] = 0;
+            }
+        }
+    }
+
+    psStats* stat = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    psVector* radii = psVectorAlloc(10,PS_TYPE_F32);
+    for (psS32 i=0; i < 10; i++) {
+        radii->data.F32[i] = 10+i*10;
+        radii->n++;
+    }
+
+    psVector* result = NULL;
+
+    result = psImageRadialCut(result,image,mask,1,centerX,centerY,radii,stat);
+
+    if (result == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "Return value of NULL unexpected.");
+        return 1;
+    }
+
+    if (result->type.type != PS_TYPE_F64) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "Return type not psF64, as expected.");
+        return 2;
+    }
+
+    for (psS32 i=0; i < 9; i++) {
+        if (fabs(result->data.F64[i] - (15.0+i*10)) > 1) {
+            psLogMsg(__func__,PS_LOG_ERROR,
+                     "Result was not as expected for radii #%d (%g, expected %d +/- 1)",
+                     result->data.F64[i], (15.0+i*10) );
+            return 3+i;
+        }
+    }
+
+    // again, but without mask
+    psVector* orig = result;
+    result = psImageRadialCut(result,image,NULL,1,centerX,centerY,radii,stat);
+
+    if (result == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "Return value of NULL unexpected.");
+        return 12;
+    }
+
+    if (result != orig) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "Return value of is not same as input parameter 'out'.");
+        return 13;
+    }
+
+    for (psS32 i=0; i < 9; i++) {
+        if (fabs(result->data.F64[i] - (15.0+i*10)) > 1) {
+            psLogMsg(__func__,PS_LOG_ERROR,
+                     "Result was not as expected for radii #%d (%g, expected %d +/- 1)",
+                     result->data.F64[i], (15.0+i*10) );
+            return 14+i;
+        }
+    }
+
+    // NULL input image...
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error.");
+    result = psImageRadialCut(result,NULL,NULL,1,centerX,centerY,radii,stat);
+
+    if (result != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "Return value not NULL as expected.");
+        return 23;
+    }
+
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageRadialCut did not generate proper error message.");
+        return 24;
+    }
+    psFree(err);
+
+    // NULL input radii...
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error.");
+    result = psImageRadialCut(result,image,mask,1,centerX,centerY,NULL,stat);
+
+    if (result != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "Return value not NULL as expected.");
+        return 23;
+    }
+
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageRadialCut did not generate proper error message.");
+        return 24;
+    }
+    psFree(err);
+
+    // NULL input stat...
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error.");
+    result = psImageRadialCut(result,image,mask,1,centerX,centerY,radii,NULL);
+
+    if (result != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "Return value not NULL as expected.");
+        return 23;
+    }
+
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageRadialCut did not generate proper error message.");
+        return 24;
+    }
+    psFree(err);
+
+    // Bad center X
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error.");
+    result = psImageRadialCut(result,image,mask,1,
+                              c+1,centerY,radii,stat);
+
+    if (result != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "Return value not NULL as expected.");
+        return 25;
+    }
+
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageRadialCut did not generate proper error message.");
+        return 26;
+    }
+    psFree(err);
+
+    // Bad center Y
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error.");
+    result = psImageRadialCut(result,image,mask,1,
+                              centerX,r+1,radii,stat);
+
+    if (result != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "Return value not NULL as expected.");
+        return 27;
+    }
+
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageRadialCut did not generate proper error message.");
+        return 28;
+    }
+    psFree(err);
+
+    // Bad mask type (N.B., swapped image/mask to do this)
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error.");
+    result = psImageRadialCut(result,mask,image,1,
+                              centerX,r+1,radii,stat);
+
+    if (result != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "Return value not NULL as expected.");
+        return 29;
+    }
+
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_TYPE) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageRadialCut did not generate proper error message.");
+        return 30;
+    }
+    psFree(err);
+
+    // Bad mask size
+    psImage* mask2 = psImageAlloc(c/2,r/2,PS_TYPE_MASK);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error.");
+    result = psImageRadialCut(result,image, mask2, 1,
+                              centerX,centerY,radii,stat);
+    psFree(mask2);
+    if (result != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "Return value not NULL as expected.");
+        return 31;
+    }
+
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_SIZE) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageRadialCut did not generate proper error message.");
+        return 32;
+    }
+    psFree(err);
+
+    // Bad radii size
+    psVector* radii2 = psVectorAlloc(1,PS_TYPE_MASK);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error.");
+    result = psImageRadialCut(result,image, mask, 1,
+                              centerX,centerY,radii2,stat);
+    psFree(radii2);
+    if (result != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "Return value not NULL as expected.");
+        return 33;
+    }
+
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_SIZE) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageRadialCut did not generate proper error message.");
+        return 34;
+    }
+    psFree(err);
+
+    // bad input stat option...
+    stat->options = 0;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error.");
+    result = psImageRadialCut(result,image,mask,1,centerX,centerY,radii,stat);
+    stat->options = PS_STAT_SAMPLE_MEAN;
+
+    if (result != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "Return value not NULL as expected.");
+        return 35;
+    }
+
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageRadialCut did not generate proper error message.");
+        return 36;
+    }
+    psFree(err);
+
+    psFree(image);
+    psFree(mask);
+    psFree(radii);
+    psFree(stat);
+    psFree(result);
+
+    return 0;
+}
+
+psS32 testImageRowColError(void)
+{
+    psImage *image = NULL;
+    psVector *out = NULL;
+    int num = 0;
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message(for row)");
+    out = psImageRow(NULL, image, num);
+    if (out != NULL) {
+        return 1;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message(for col)");
+    out = psImageCol(NULL, image, num);
+    if (out != NULL) {
+        return 1;
+    }
+
+    image = psImageAlloc(3, 3, PS_TYPE_F64);
+
+    //Test for invalid row0.
+    *(psS32*)&(image->row0) = -1;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message(for row)");
+    out = psImageRow(NULL, image, num);
+    if (out != NULL) {
+        return 2;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message(for col)");
+    out = psImageCol(NULL, image, num);
+    if (out != NULL) {
+        return 2;
+    }
+
+    //Test for invalid col0.
+    *(psS32*)&(image->row0) = 5;
+    *(psS32*)&(image->col0) = -1;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message(for row)");
+    out = psImageRow(NULL, image, num);
+    if (out != NULL) {
+        return 3;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message(for col)");
+    out = psImageCol(NULL, image, num);
+    if (out != NULL) {
+        return 3;
+    }
+
+    //Test for invalid numRows
+    *(psS32*)&(image->col0) = 10;
+    *(int*)&(image->numRows) = -1;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message(for row)");
+    out = psImageRow(NULL, image, num);
+    if (out != NULL) {
+        return 4;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message(for col)");
+    out = psImageCol(NULL, image, num);
+    if (out != NULL) {
+        return 4;
+    }
+    //Test for invalid numCols
+    *(int*)&(image->numRows) = 3;
+    *(int*)&(image->numCols) = -1;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message(for row)");
+    out = psImageRow(NULL, image, num);
+    if (out != NULL) {
+        return 5;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message(for col)");
+    out = psImageCol(NULL, image, num);
+    if (out != NULL) {
+        return 5;
+    }
+    //Test for invalid row/col number specified.
+    *(int*)&(image->numCols) = 3;
+    num = 8;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message(for row)");
+    out = psImageRow(NULL, image, num);
+    if (out != NULL) {
+        return 6;
+    }
+    num = 13;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message(for col)");
+    out = psImageCol(NULL, image, num);
+    if (out != NULL) {
+        return 6;
+    }
+    num = 3;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message(for row)");
+    out = psImageRow(NULL, image, num);
+    if (out != NULL) {
+        return 7;
+    }
+    num = 8;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message(for col)");
+    out = psImageCol(NULL, image, num);
+    if (out != NULL) {
+        return 7;
+    }
+    num = -10;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message(for row)");
+    out = psImageRow(NULL, image, num);
+    if (out != NULL) {
+        return 8;
+    }
+    num = -14;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message(for col)");
+    out = psImageCol(NULL, image, num);
+    if (out != NULL) {
+        return 8;
+    }
+
+    //Test valid cases.
+    image->col0 = 10;
+    image->row0 = 5;
+    *(int*)&(image->numRows) = 3;
+    *(int*)&(image->numCols) = 3;
+    image->data.F64[0][0] = 666.666;
+    image->data.F64[1][0] = 66.6;
+    image->data.F64[2][0] = 6.66;
+    image->data.F64[0][1] = 6.6;
+    image->data.F64[1][1] = 6.666;
+    image->data.F64[2][1] = 66.666;
+    image->data.F64[0][2] = 666.6;
+    image->data.F64[1][2] = 666.66;
+    image->data.F64[2][2] = 66.66;
+    num = 7;
+    out = psImageRow(out, image, num);
+    if (out == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psImageRow failed to return correct psVector output.\n");
+        return 10;
+    } else {
+        psFree(out);
+        out = NULL;
+    }
+    num = 11;
+    out = psImageCol(NULL, image, num);
+    if (out == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psImageCol failed to return correct psVector output.\n");
+        return 10;
+    } else {
+        psFree(out);
+        out = NULL;
+    }
+
+    num = -3;
+    out = psImageRow(out, image, num);
+    if (out == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psImageRow failed to return correct psVector output.\n");
+        return 10;
+    } else {
+        psFree(out);
+        out = NULL;
+    }
+    num = -1;
+    out = psImageCol(NULL, image, num);
+    if (out == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psImageCol failed to return correct psVector output.\n");
+        return 10;
+    }
+    psFree(out);
+    psFree(image);
+    return 0;
+}
+
+psS32 testImageRowColF64(void)
+{
+    psVector *rowcol = NULL;
+    psVector *empty = NULL;
+    psImage *image = NULL;
+    psImage *emptyImage = NULL;
+
+    image = psImageAlloc(3, 3, PS_TYPE_F64);
+    rowcol = psVectorAlloc(3, PS_TYPE_F64);
+
+    image->data.F64[0][0] = 666.666;
+    image->data.F64[1][0] = 66.6;
+    image->data.F64[2][0] = 6.66;
+    image->data.F64[0][1] = 6.6;
+    image->data.F64[1][1] = 6.666;
+    image->data.F64[2][1] = 66.666;
+    image->data.F64[0][2] = 666.6;
+    image->data.F64[1][2] = 666.66;
+    image->data.F64[2][2] = 66.66;
+
+    //Test for error with NULL image
+    empty = psImageCol(empty, emptyImage, 0);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return NULL for NULL image input.\n");
+        return 1;
+    }
+    //Test for error with Out of Range Row
+    empty = psImageRow(empty, image, 5);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageRow failed to return NULL for out of range row input.\n");
+        return 2;
+    }
+    rowcol->data.F64[0] = 1.1;
+    rowcol->data.F64[2] = 2.2;
+    //Test recycling of non-NULL vector & correct output
+    rowcol = psImageCol(rowcol, image, 1);
+    double test1, test2;
+    double TOLTST = .001;
+    test1 = fabs(rowcol->data.F64[0]-6.6);
+    test2 = fabs(rowcol->data.F64[2]-66.666);
+    if ( (test1>TOLTST) || (test2>TOLTST) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return correct values.\n");
+        return 3;
+    }
+    rowcol = psImageRow(rowcol, image, 1);
+    test1 = fabs(rowcol->data.F64[0]-66.6);
+    test2 = fabs(rowcol->data.F64[2]-666.66);
+    if ( (test1>TOLTST) || (test2>TOLTST) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageRow failed to return correct values.\n");
+        return 4;
+    }
+
+    psFree(rowcol);
+    psFree(image);
+    return 0;
+}
+
+psS32 testImageRowColF32(void)
+{
+    psVector *rowcol = NULL;
+    psVector *empty = NULL;
+    psImage *image = NULL;
+    psImage *emptyImage = NULL;
+
+    float test1;
+    float test2;
+    float TOLTST = .01;
+
+    image = psImageAlloc(3, 3, PS_TYPE_F32);
+    rowcol = psVectorAlloc(3, PS_TYPE_F32);
+    rowcol->n = rowcol->nalloc;
+
+    image->data.F32[0][0] = 666.666;
+    image->data.F32[1][0] = 66.6;
+    image->data.F32[2][0] = 6.66;
+    image->data.F32[0][1] = 6.6;
+    image->data.F32[1][1] = 6.666;
+    image->data.F32[2][1] = 66.666;
+    image->data.F32[0][2] = 666.6;
+    image->data.F32[1][2] = 666.66;
+    image->data.F32[2][2] = 66.66;
+
+    //Test for error with NULL image
+    empty = psImageCol(empty, emptyImage, 0);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return NULL for NULL image input.\n");
+        return 1;
+    }
+    //Test for error with Out of Range Row
+    empty = psImageRow(empty, image, 5);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageRow failed to return NULL for out of range row input.\n");
+        return 2;
+    }
+    rowcol->data.F32[0] = 1.1;
+    rowcol->data.F32[2] = 2.2;
+    //Test recycling of non-NULL vector & correct output
+    rowcol = psImageCol(rowcol, image, 1);
+    test1 = fabs(rowcol->data.F32[0]-6.6);
+    test2 = fabs(rowcol->data.F32[2]-66.666);
+    if ( (test1>TOLTST) || (test2>TOLTST) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return correct values.\n");
+        return 3;
+    }
+
+    psFree(rowcol);
+    psFree(image);
+    return 0;
+}
+
+psS32 testImageRowColU64(void)
+{
+    psVector *rowcol = NULL;
+    psVector *empty = NULL;
+    psImage *image = NULL;
+    psImage *emptyImage = NULL;
+
+    image = psImageAlloc(3, 3, PS_TYPE_U64);
+    rowcol = psVectorAlloc(3, PS_TYPE_U64);
+
+    image->data.U64[0][0] = 666666;
+    image->data.U64[1][0] = 666;
+    image->data.U64[2][0] = 666;
+    image->data.U64[0][1] = 66;
+    image->data.U64[1][1] = 6666;
+    image->data.U64[2][1] = 66666;
+    image->data.U64[0][2] = 6666;
+    image->data.U64[1][2] = 66666;
+    image->data.U64[2][2] = 6666;
+
+    //Test for error with NULL image
+    empty = psImageCol(empty, emptyImage, 0);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return NULL for NULL image input.\n");
+        return 1;
+    }
+    //Test for error with Out of Range Row
+    empty = psImageRow(empty, image, 5);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageRow failed to return NULL for out of range row input.\n");
+        return 2;
+    }
+    rowcol->data.U64[0] = 11;
+    rowcol->data.U64[2] = 22;
+    //Test recycling of non-NULL vector & correct output
+    rowcol = psImageCol(rowcol, image, 1);
+    if (rowcol->data.U64[0] != 666 && rowcol->data.U64[2] != 66666) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return correct values.\n");
+        return 3;
+    }
+
+    psFree(rowcol);
+    psFree(image);
+    return 0;
+}
+
+psS32 testImageRowColU32(void)
+{
+    psVector *rowcol = NULL;
+    psVector *empty = NULL;
+    psImage *image = NULL;
+    psImage *emptyImage = NULL;
+
+    image = psImageAlloc(3, 3, PS_TYPE_U32);
+    rowcol = psVectorAlloc(3, PS_TYPE_U32);
+
+    image->data.U32[0][0] = 666666;
+    image->data.U32[1][0] = 666;
+    image->data.U32[2][0] = 666;
+    image->data.U32[0][1] = 66;
+    image->data.U32[1][1] = 6666;
+    image->data.U32[2][1] = 66666;
+    image->data.U32[0][2] = 6666;
+    image->data.U32[1][2] = 66666;
+    image->data.U32[2][2] = 6666;
+
+    //Test for error with NULL image
+    empty = psImageCol(empty, emptyImage, 0);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return NULL for NULL image input.\n");
+        return 1;
+    }
+    //Test for error with Out of Range Row
+    empty = psImageRow(empty, image, 5);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageRow failed to return NULL for out of range row input.\n");
+        return 2;
+    }
+    rowcol->data.U32[0] = 11;
+    rowcol->data.U32[2] = 22;
+    //Test recycling of non-NULL vector & correct output
+    rowcol = psImageCol(rowcol, image, 1);
+    if (rowcol->data.U32[0] != 666 && rowcol->data.U32[2] != 66666) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return correct values.\n");
+        return 3;
+    }
+
+    psFree(rowcol);
+    psFree(image);
+    return 0;
+}
+
+psS32 testImageRowColS32(void)
+{
+    psVector *rowcol = NULL;
+    psVector *empty = NULL;
+    psImage *image = NULL;
+    psImage *emptyImage = NULL;
+
+    image = psImageAlloc(3, 3, PS_TYPE_S32);
+    rowcol = psVectorAlloc(3, PS_TYPE_S32);
+
+    image->data.S32[0][0] = 666666;
+    image->data.S32[1][0] = 666;
+    image->data.S32[2][0] = 666;
+    image->data.S32[0][1] = 66;
+    image->data.S32[1][1] = 6666;
+    image->data.S32[2][1] = 66666;
+    image->data.S32[0][2] = 6666;
+    image->data.S32[1][2] = 66666;
+    image->data.S32[2][2] = 6666;
+
+    //Test for error with NULL image
+    empty = psImageCol(empty, emptyImage, 0);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return NULL for NULL image input.\n");
+        return 1;
+    }
+    //Test for error with Out of Range Row
+    empty = psImageRow(empty, image, 5);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageRow failed to return NULL for out of range row input.\n");
+        return 2;
+    }
+    rowcol->data.S32[0] = 11;
+    rowcol->data.S32[2] = 22;
+    //Test recycling of non-NULL vector & correct output
+    rowcol = psImageCol(rowcol, image, 1);
+    if (rowcol->data.S32[0] != 666 && rowcol->data.S32[2] != 66666) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return correct values.\n");
+        return 3;
+    }
+
+    psFree(rowcol);
+    psFree(image);
+    return 0;
+}
+
+psS32 testImageRowColS64(void)
+{
+    psVector *rowcol = NULL;
+    psVector *empty = NULL;
+    psImage *image = NULL;
+    psImage *emptyImage = NULL;
+
+    image = psImageAlloc(3, 3, PS_TYPE_S64);
+    rowcol = psVectorAlloc(3, PS_TYPE_S64);
+
+    image->data.S64[0][0] = 666666;
+    image->data.S64[1][0] = 666;
+    image->data.S64[2][0] = 666;
+    image->data.S64[0][1] = 66;
+    image->data.S64[1][1] = 6666;
+    image->data.S64[2][1] = 66666;
+    image->data.S64[0][2] = 6666;
+    image->data.S64[1][2] = 66666;
+    image->data.S64[2][2] = 6666;
+
+    //Test for error with NULL image
+    empty = psImageCol(empty, emptyImage, 0);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return NULL for NULL image input.\n");
+        return 1;
+    }
+    //Test for error with Out of Range Row
+    empty = psImageRow(empty, image, 5);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageRow failed to return NULL for out of range row input.\n");
+        return 2;
+    }
+    rowcol->data.S64[0] = 11;
+    rowcol->data.S64[2] = 22;
+    //Test recycling of non-NULL vector & correct output
+    rowcol = psImageCol(rowcol, image, 1);
+    if (rowcol->data.S64[0] != 666 && rowcol->data.S64[2] != 66666) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return correct values.\n");
+        return 3;
+    }
+
+    psFree(rowcol);
+    psFree(image);
+    return 0;
+}
+
+psS32 testImageRowColS16(void)
+{
+    psVector *rowcol = NULL;
+    psVector *empty = NULL;
+    psImage *image = NULL;
+    psImage *emptyImage = NULL;
+
+    image = psImageAlloc(3, 3, PS_TYPE_S16);
+    rowcol = psVectorAlloc(3, PS_TYPE_S16);
+
+    image->data.S16[0][0] = 3333;
+    image->data.S16[1][0] = 666;
+    image->data.S16[2][0] = 666;
+    image->data.S16[0][1] = 66;
+    image->data.S16[1][1] = 6666;
+    image->data.S16[2][1] = 4444;
+    image->data.S16[0][2] = 6666;
+    image->data.S16[1][2] = 4444;
+    image->data.S16[2][2] = 6666;
+
+    //Test for error with NULL image
+    empty = psImageCol(empty, emptyImage, 0);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return NULL for NULL image input.\n");
+        return 1;
+    }
+    //Test for error with Out of Range Row
+    empty = psImageRow(empty, image, 5);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageRow failed to return NULL for out of range row input.\n");
+        return 2;
+    }
+    rowcol->data.S16[0] = 11;
+    rowcol->data.S16[2] = 22;
+    //Test recycling of non-NULL vector & correct output
+    rowcol = psImageCol(rowcol, image, 1);
+    if (rowcol->data.S16[0] != 666 && rowcol->data.S16[2] != 4444) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return correct values.\n");
+        return 3;
+    }
+
+    psFree(rowcol);
+    psFree(image);
+    return 0;
+}
+
+psS32 testImageRowColU16(void)
+{
+    psVector *rowcol = NULL;
+    psVector *empty = NULL;
+    psImage *image = NULL;
+    psImage *emptyImage = NULL;
+
+    image = psImageAlloc(3, 3, PS_TYPE_U16);
+    rowcol = psVectorAlloc(3, PS_TYPE_U16);
+
+    image->data.S16[0][0] = 3333;
+    image->data.S16[1][0] = 666;
+    image->data.S16[2][0] = 666;
+    image->data.S16[0][1] = 66;
+    image->data.S16[1][1] = 6666;
+    image->data.S16[2][1] = 4444;
+    image->data.S16[0][2] = 6666;
+    image->data.S16[1][2] = 4444;
+    image->data.S16[2][2] = 6666;
+
+    //Test for error with NULL image
+    empty = psImageCol(empty, emptyImage, 0);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return NULL for NULL image input.\n");
+        return 1;
+    }
+    //Test for error with Out of Range Row
+    empty = psImageRow(empty, image, 5);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageRow failed to return NULL for out of range row input.\n");
+        return 2;
+    }
+    rowcol->data.U16[0] = 11;
+    rowcol->data.U16[2] = 22;
+    //Test recycling of non-NULL vector & correct output
+    rowcol = psImageCol(rowcol, image, 1);
+    if (rowcol->data.U16[0] != 666 && rowcol->data.U16[2] != 4444) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return correct values.\n");
+        return 3;
+    }
+
+    psFree(rowcol);
+    psFree(image);
+    return 0;
+}
+
+psS32 testImageRowColU8(void)
+{
+    psVector *rowcol = NULL;
+    psVector *empty = NULL;
+    psImage *image = NULL;
+    psImage *emptyImage = NULL;
+
+    image = psImageAlloc(3, 3, PS_TYPE_U8);
+    rowcol = psVectorAlloc(3, PS_TYPE_U8);
+
+    image->data.U8[0][0] = 244;
+    image->data.U8[1][0] = 123;
+    image->data.U8[2][0] = 123;
+    image->data.U8[0][1] = 66;
+    image->data.U8[1][1] = 199;
+    image->data.U8[2][1] = 249;
+    image->data.U8[0][2] = 199;
+    image->data.U8[1][2] = 249;
+    image->data.U8[2][2] = 199;
+
+    //Test for error with NULL image
+    empty = psImageCol(empty, emptyImage, 0);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return NULL for NULL image input.\n");
+        return 1;
+    }
+    //Test for error with Out of Range Row
+    empty = psImageRow(empty, image, 5);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageRow failed to return NULL for out of range row input.\n");
+        return 2;
+    }
+    rowcol->data.U8[0] = 11;
+    rowcol->data.U8[2] = 22;
+    //Test recycling of non-NULL vector & correct output
+    rowcol = psImageCol(rowcol, image, 1);
+    if (rowcol->data.U8[0] != 123 && rowcol->data.U8[2] != 249) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return correct values.\n");
+        return 3;
+    }
+
+    psFree(rowcol);
+    psFree(image);
+    return 0;
+}
+psS32 testImageRowColS8(void)
+{
+    psVector *rowcol = NULL;
+    psVector *empty = NULL;
+    psImage *image = NULL;
+    psImage *emptyImage = NULL;
+
+    image = psImageAlloc(3, 3, PS_TYPE_S8);
+    rowcol = psVectorAlloc(3, PS_TYPE_S8);
+
+    image->data.S8[0][0] = 44;
+    image->data.S8[1][0] = 23;
+    image->data.S8[2][0] = 23;
+    image->data.S8[0][1] = 66;
+    image->data.S8[1][1] = 99;
+    image->data.S8[2][1] = 49;
+    image->data.S8[0][2] = 99;
+    image->data.S8[1][2] = 49;
+    image->data.S8[2][2] = 99;
+
+    //Test for error with NULL image
+    empty = psImageCol(empty, emptyImage, 0);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return NULL for NULL image input.\n");
+        return 1;
+    }
+    //Test for error with Out of Range Row
+    empty = psImageRow(empty, image, 5);
+    if (empty != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageRow failed to return NULL for out of range row input.\n");
+        return 2;
+    }
+    rowcol->data.S8[0] = 11;
+    rowcol->data.S8[2] = 22;
+    //Test recycling of non-NULL vector & correct output
+    rowcol = psImageCol(rowcol, image, 1);
+    if (rowcol->data.S8[0] != 23 && rowcol->data.S8[2] != 49) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCol failed to return correct values.\n");
+        return 3;
+    }
+
+    psFree(rowcol);
+    psFree(image);
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImagePixelManip.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImagePixelManip.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImagePixelManip.c	(revision 22158)
@@ -0,0 +1,797 @@
+/** @file  tst_psImageManip.c
+ *
+ *  @brief Contains the tests for psImageManip.[ch]
+ *
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-10-06 02:41:07 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <complex.h>
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdlib.h>
+#include <string.h>                    // for memset
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "psTest.h"
+#include "pslib_strict.h"
+#include "psType.h"
+
+static psS32 testImageClip(void);
+static psS32 testImageClipNAN(void);
+static psS32 testImageClipComplexRegion(void);
+static psS32 testImageOverlay(void);
+
+testDescription tests[] = {
+                              {testImageClip,571,"psImageClip",0,false},
+                              {testImageClipNAN,572,"psImageClipNAN",0,false},
+                              {testImageClipComplexRegion,673,"psImageClipComplexRegion",0,false},
+                              {testImageOverlay,573,"psImageOverlay",0,false},
+                              {NULL}
+                          };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    return ! runTestSuite(stderr,"psImage",tests,argc,argv);
+}
+
+
+psS32 testImageClip(void)
+{
+    psImage* img = NULL;
+    psU32 c = 128;
+    psU32 r = 256;
+    psF64 min;
+    psF64 max;
+    psS32 numClipped = 0;
+    psS32 retVal;
+
+    psLogMsg(__func__,PS_LOG_INFO,
+             "psImageClip shall limit the minimum and maximum data value within a psImage structure");
+
+    /*
+
+        psImageClip shall limit the minimum and maximum data value within a
+        psImage structure to a specified min and max value.
+
+        Verify the returned integer is equal to the number of pixels clipped,
+        if the input psImage structure contains known values and input parameters
+        min and max have know values.
+
+        Verify the psImage structure specified by the input parameter input is
+        modified to contain the expected values, if the input psImage structure
+        contains known values, min and max are specified and vmin and vmax
+        parameters are known.
+
+        Verify the retuned integer is zero, psImage structure input is unmodified
+        and program executions doesn't stop, if input parameter psImage structure
+        pointer is null.
+
+        Verify the retuned integer is zero, psImage structure input is unmodified
+        and program executions doesn't stop, if input parameter min is larger than max.
+    */
+
+    // create image
+    #define testImageClipByType(datatype) \
+    img = psImageAlloc(c,r,PS_TYPE_##datatype); \
+    for (psU32 row=0;row<r;row++) { \
+        ps##datatype* imgRow = img->data.datatype[row]; \
+        for (psU32 col=0;col<c;col++) { \
+            imgRow[col] = (ps##datatype)(row+col); \
+        } \
+    } \
+    min = (psF64)r/2.0; \
+    max = (psF64)r; \
+    \
+    retVal = psImageClip(img,min,(double)PS_MIN_##datatype,max,(double)PS_MAX_##datatype); \
+    \
+    numClipped = 0; \
+    for (psU32 row=0;row<r;row++) { \
+        ps##datatype* imgRow = img->data.datatype[row]; \
+        for (psU32 col=0;col<c;col++) { \
+            ps##datatype value = (ps##datatype)(row+col); \
+            if (value < min) { \
+                numClipped++; \
+                value = PS_MIN_##datatype; \
+            } else if (value > max) { \
+                numClipped++; \
+                value = PS_MAX_##datatype; \
+            } \
+            if (fabsf(imgRow[col]-value) > FLT_EPSILON) { \
+                psError(PS_ERR_UNKNOWN, true,"Pixel value is not as expected (%g vs %g) at %u,%u", \
+                        (psF64)imgRow[col],(psF64)value,col,row); \
+                return 1; \
+            } \
+        } \
+    } \
+    if (retVal != numClipped) { \
+        psError(PS_ERR_UNKNOWN, true,"Expected %d clips, but got %d", \
+                numClipped,retVal); \
+        return 2; \
+    } \
+    psFree(img);
+
+    #define testImageClipByComplexType(datatype) \
+    img = psImageAlloc(c,r,PS_TYPE_##datatype); \
+    for (psU32 row=0;row<r;row++) { \
+        ps##datatype* imgRow = img->data.datatype[row]; \
+        for (psU32 col=0;col<c;col++) { \
+            imgRow[col] = (ps##datatype)(row+I*col); \
+        } \
+    } \
+    min = (float)r/2.0f; \
+    max = (float)r; \
+    \
+    retVal = psImageClip(img,min,-1.0f,max,-2.0f); \
+    \
+    numClipped = 0; \
+    for (psU32 row=0;row<r;row++) { \
+        ps##datatype* imgRow = img->data.datatype[row]; \
+        for (psU32 col=0;col<c;col++) { \
+            ps##datatype value = row+I*col; \
+            if (cabs(value) < min) { \
+                numClipped++; \
+                value = -1.0f; \
+            } else if (cabs(value) > max) { \
+                numClipped++; \
+                value = -2.0f; \
+            } \
+            if (fabsf(creal(imgRow[col])-creal(value)) > FLT_EPSILON || \
+                    fabsf(cimag(imgRow[col])-cimag(value)) > FLT_EPSILON) { \
+                psError(PS_ERR_UNKNOWN, true,"Pixel value is not as expected (%.2f+%.2fi vs %.2f+%.2fi) at %u,%u", \
+                        creal(imgRow[col]),cimag(imgRow[col]),creal(value),cimag(value),col,row); \
+                return 1; \
+            } \
+        } \
+    } \
+    if (retVal != numClipped) { \
+        psError(PS_ERR_UNKNOWN, true,"Expected %d clips, but got %d", \
+                numClipped,retVal); \
+        return 2; \
+    } \
+    psFree(img);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of F64 imagery");
+    testImageClipByType(F64);
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of F32 imagery");
+    testImageClipByType(F32);
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of S32 imagery");
+    testImageClipByType(S32);
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of S16 imagery");
+    testImageClipByType(S16);
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of S8 imagery");
+    testImageClipByType(S8);
+    //    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of U32 imagery");
+    //    testImageClipByType(U32);
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of U16 imagery");
+    testImageClipByType(U16);
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of U8 imagery");
+    testImageClipByType(U8);
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of C32 imagery");
+    testImageClipByComplexType(C32);
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping of C64 imagery");
+    testImageClipByComplexType(C64);
+
+    // Verify the retuned integer is zero, psImage structure input is unmodified
+    // and program executions doesn't stop, if input parameter psImage structure
+    // pointer is null.
+    retVal = psImageClip(NULL,min,-1.0f,max,-2.0f);
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"Expected zero return for clips of a NULL image.");
+        return 3;
+    }
+
+    // Verify the retuned integer is zero, psImage structure input is unmodified
+    // and program executions doesn't stop, if input parameter min is larger than max.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error (max<min)");
+    retVal = psImageClip(img,max,-1.0f,min,-2.0f);
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"Expected zero return for clips when max < min.");
+        return 4;
+    }
+
+    return 0;
+}
+
+psS32 testImageClipNAN(void)
+{
+    psImage* img = NULL;
+    psU32 c = 128;
+    psU32 r = 256;
+    psS32 numClipped = 0;
+    psS32 retVal;
+
+    psLogMsg(__func__,PS_LOG_INFO,
+             "psImageClipNaN shall modified pixel values of NaN with a specified value");
+
+    /*
+        psImageClipNaN shall modify a psImage structure with pixel values set
+        to NaN to a value specified as an input parameter.
+
+        Verify the returned integer is equal to the number of pixels modified
+        and the psImage is modified at locations where NaN pixels where
+        located to the value specified in the input parameter value.
+
+        Verify the returned integer is zero and program execution doesn't stop,
+        if the input parameter psImage structure pointer is null.
+    */
+
+    // create image
+    #define testImageClipNaNByType(datatype) \
+    img = psImageAlloc(c,r,PS_TYPE_##datatype); \
+    for (unsigned row=0;row<r;row++) { \
+        ps##datatype* imgRow = img->data.datatype[row]; \
+        for (unsigned col=0;col<c;col++) { \
+            if (row == col) { \
+                imgRow[col] = NAN; \
+            } else if (row+1 == col) { \
+                imgRow[col] = INFINITY; \
+            } else { \
+                imgRow[col] = (ps##datatype)(row+col); \
+            } \
+        } \
+    } \
+    \
+    retVal = psImageClipNaN(img,-1.0f); \
+    \
+    numClipped = 0; \
+    for (unsigned row=0;row<r;row++) { \
+        ps##datatype* imgRow = img->data.datatype[row]; \
+        for (unsigned col=0;col<c;col++) { \
+            ps##datatype value = (ps##datatype)(row+col); \
+            if ( (row == col) || (row+1 == col) ) { \
+                numClipped++; \
+                value = -1.0; \
+            } \
+            if (fabsf(imgRow[col]-value) > FLT_EPSILON) { \
+                psError(PS_ERR_UNKNOWN, true,"Pixel value is not as expected (%f vs %f) at %d,%d", \
+                        imgRow[col],value,col,row); \
+                return 1; \
+            } \
+        } \
+    } \
+    if (retVal != numClipped) { \
+        psError(PS_ERR_UNKNOWN, true,"Expected %d clips, but got %d", \
+                numClipped,retVal); \
+        return 2; \
+    } \
+    psFree(img);
+
+    testImageClipNaNByType(F32);
+    testImageClipNaNByType(F64);
+    testImageClipNaNByType(C32);
+    testImageClipNaNByType(C64);
+
+    // Verify the retuned integer is zero, psImage structure input is unmodified
+    // and program executions doesn't stop, if input parameter psImage structure
+    // pointer is null.
+    retVal = psImageClipNaN(NULL,-1.0f);
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"Expected zero return for clips of a NULL image.");
+        return 3;
+    }
+
+    // Verify program execution doesn't stop if the input image type is something
+    // other than F32, F64, C32, C64.
+    img = psImageAlloc(c,r,PS_TYPE_S32);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error (invalid type)");
+    retVal = psImageClipNaN(img,2.0f);
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"Expected zero return for clip of invalid image type.");
+        return 4;
+    }
+    psFree(img);
+
+    return 0;
+}
+
+psS32 testImageClipComplexRegion(void)
+{
+    psImage* img = NULL;
+    psU32 c = 1024;
+    psU32 r = 2048;
+    psS32 numClipped = 0;
+    psS32 retVal;
+
+    psLogMsg(__func__,PS_LOG_INFO,
+             "psImageClipNaN shall modified pixel values of NaN with a specified value");
+
+    /*
+    1. Create a complex image with a wide range of complex values
+
+    2. call psImageClipComplexRegion with min and max where there is at least
+       2 pixels in the image above) that is:
+        a) real(p) < real(min) && complex(p) < complex(min),
+        b) real(p) < real(min) && complex(min) < complex(p) < complex(max)
+        c) real(min) < real(p) < real(max) && complex(p) < complex(min)
+        d) real(min) < real(p) < real(max) && complex(min) < complex(p) < complex(max)
+        e) real(p) > real(max) && complex(min) < complex(p) < complex(max)
+        f) real(pmin) < real(p) < real(max) && complex(p) > complex(max)
+        g) real(p) > real(max) && complex(p) > complex(max)
+        h) real(p) < real(min) && complex(p) > complex(max)
+        i) real(p) > real(max) && complex(p) < complex(min)
+
+    3. verify that All pixels in case (a), (b), and (c) have the value vmin
+
+    4. verify that all pixels in case (d) are unchanged from input
+
+    5. verify that all pixels in case (e), (f), (g), (h), and (i) have the
+       value vmax
+
+    */
+
+    #define testImageClipComplexByType(datatype,MIN,MAX) /* datatype must be complex */ \
+    /* create image */ \
+    img = psImageAlloc(c,r,PS_TYPE_##datatype); \
+    for (unsigned row=0;row<r;row++) { \
+        ps##datatype* imgRow = img->data.datatype[row]; \
+        for (unsigned col=0;col<c;col++) { \
+            imgRow[col] = row+I*col; \
+        } \
+    } \
+    \
+    retVal = psImageClipComplexRegion(img,MIN,-1.0-1.0*I,MAX,-2.0-2.0*I); \
+    \
+    numClipped = 0; \
+    for (unsigned row=0;row<r;row++) { \
+        ps##datatype* imgRow = img->data.datatype[row]; \
+        for (unsigned col=0;col<c;col++) { \
+            ps##datatype value = (ps##datatype)(row+I*col); \
+            if ( (row > creal(MAX)) || (col > cimag(MAX)) ) { \
+                numClipped++; \
+                value = -2.0-2.0*I; \
+            } else if ((row < creal(MIN)) || (col < cimag(MIN)) ) { \
+                numClipped++; \
+                value = -1.0-1.0*I; \
+            } \
+            if (cabs(imgRow[col]-value) > FLT_EPSILON) { \
+                psError(PS_ERR_UNKNOWN, true,"Pixel value is not as expected (%g%+gi vs %g%+gi) at %d,%d", \
+                        creal(imgRow[col]),cimag(imgRow[col]),creal(value),cimag(value),col,row); \
+                return 1; \
+            } \
+        } \
+    } \
+    if (retVal != numClipped) { \
+        psError(PS_ERR_UNKNOWN, true,"Expected %d clips, but got %d", \
+                numClipped,retVal); \
+        return 2; \
+    } \
+    psFree(img);
+
+    complex double min = ((double)r)/5.0+I*((double)c)/4.0;
+    complex double max = ((double)r)/3.0+I*((double)c)/2.0;
+
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping at %g%+gi to %g%+gi for psC32",
+             creal(min),cimag(min),creal(max),cimag(max));
+
+    testImageClipComplexByType(C32,min,max);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Testing clipping at %g%+gi to %g%+gi for psC64",
+             creal(min),cimag(min),creal(max),cimag(max));
+    testImageClipComplexByType(C64,min,max);
+
+    //  6. Call psImageClipComplexRegion with NULL input parameter; should error
+    //     but not stop execution.
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(NULL,0,0,0,0);
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"Expected zero return for clips of a NULL image.");
+        return 3;
+    }
+
+
+    img = psImageAlloc(c,r,PS_TYPE_C32);
+    for (unsigned row=0;row<r;row++) {
+        psC32* imgRow = img->data.C32[row];
+        for (unsigned col=0;col<c;col++) {
+            imgRow[col] = row+I*col;
+        }
+    }
+
+    //  7. Call psImageClipComplexRegion with min > max; should error and return 0,
+    //     but not stop execution
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,10.0+I*1.0,-1.0,5.0+5.0*I,-2.0);
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"Expected zero return for creal(min)>creal(max).");
+        return 3;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,1.0+I*10.0,-1.0,5.0+5.0*I,-2.0);
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"Expected zero return for cimag(min)>cimag(max).");
+        return 3;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,10.0+I*10.0,-1.0,5.0+5.0*I,-2.0);
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"Expected zero return for min>max.");
+        return 3;
+    }
+
+    //  8. Call psImageClipComplexRegion with the follow vmin/vmax values; each
+    //     should error and return 0, but not stop execution
+    //      a) vmin < datatype region's minimum
+    //      b) vmax < datatype region's minimum
+    //      c) vmin > datatype region's maximum
+    //      d) vmax > datatype region's maximum
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,
+                                      1.0+I*1.0,
+                                      -2.0*(double)FLT_MAX,
+                                      5.0+5.0*I,
+                                      0.0);
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"Expected zero return for vmin not in datatype range.");
+        return 80;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,
+                                      1.0+I*1.0,
+                                      2.0*(double)FLT_MAX,
+                                      5.0+5.0*I,
+                                      0.0);
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"Expected zero return for vmin not in datatype range.");
+        return 81;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,
+                                      1.0+I*1.0,
+                                      FLT_EPSILON-2.0*(double)FLT_MAX*I,
+                                      5.0+5.0*I,
+                                      0.0);
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"Expected zero return for vmin not in datatype range.");
+        return 82;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,
+                                      1.0+I*1.0,
+                                      FLT_EPSILON+2.0*(double)FLT_MAX*I,
+                                      5.0+5.0*I,
+                                      0.0);
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"Expected zero return for vmin not in datatype range.");
+        return 83;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,
+                                      1.0+I*1.0,
+                                      0.0,
+                                      5.0+5.0*I,
+                                      -2.0*(double)FLT_MAX);
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"Expected zero return for vmax not in datatype range.");
+        return 84;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,
+                                      1.0+I*1.0,
+                                      0.0,
+                                      5.0+5.0*I,
+                                      2.0*(double)FLT_MAX);
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"Expected zero return for vmax not in datatype range.");
+        return 85;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,
+                                      1.0+I*1.0,
+                                      0.0,
+                                      5.0+5.0*I,
+                                      FLT_EPSILON-2.0*(double)FLT_MAX*I);
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"Expected zero return for vmax not in datatype range.");
+        return 87;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error:");
+    retVal = psImageClipComplexRegion(img,
+                                      1.0+I*1.0,
+                                      0.0,
+                                      5.0+5.0*I,
+                                      FLT_EPSILON+2.0*(double)FLT_MAX*I);
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"Expected zero return for vmax not in datatype range.");
+        return 88;
+    }
+
+
+    // now check if vmin > vmax is OK
+    for (unsigned row=0;row<r;row++) {
+        psC32* imgRow = img->data.C32[row];
+        for (unsigned col=0;col<c;col++) {
+            imgRow[col] = row+I*col;
+        }
+    }
+    retVal = psImageClipComplexRegion(img,
+                                      1.0+I*1.0,
+                                      10.0,
+                                      5.0+5.0*I,
+                                      0.0);
+    if (retVal == 0) {
+        psError(PS_ERR_UNKNOWN, true,"Didn't expect zero return for vmin > vmax.");
+        return 83;
+    }
+
+
+    psFree(img);
+    img = NULL;
+
+    //  9. Call psImageClipComplexRegion with the max value out of datatype's
+    //     range; should clip as expected (see step 1-5). Repeat with min value
+    //     out of datatype's range.
+
+    testImageClipComplexByType(C32,-(double)FLT_MAX*2.0-I*(double)FLT_MAX*2.0,10.0+I*10.0);
+    testImageClipComplexByType(C32,10.0+I*10.0,(double)FLT_MAX*2.0+I*(double)FLT_MAX*2.0);
+
+    // Verify program execution doesn't stop if the input image type is something
+    // other than C32, C64.
+    img = psImageAlloc(c,r,PS_TYPE_S32);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error (invalid type)");
+    retVal = psImageClipComplexRegion(img,2.0,10.0,5.0,0.0);
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"Expected zero return for clip of invalid image type.");
+        return 84;
+    }
+    psFree(img);
+
+    return 0;
+}
+
+psS32 testImageOverlay(void)
+{
+
+    psImage* img = NULL;
+    psImage* img2 = NULL;
+    psImage* img3 = NULL;
+    psImage* img4 = NULL;
+    psU32 c = 128;
+    psU32 r = 256;
+    psS32 retVal;
+
+    /*
+    psImageSectionOverlay shall modified pixel values in a psImage structure to
+    be equal to the value of the originaldata and an overlay image with a
+    specified operation. Valid operations include =, +, -, *, /.
+
+    Verify the returned integer is zero
+    and the input parameter psImage structure is modified at the specified
+    location and range with the given overlay image and the specified
+    function. Cases should include all the valid operations. Comparison of
+    expected values should include a delta to allow for testing on
+    different platforms.
+
+    */
+
+    #define testOverlayTypeOP(DATATYPE,OP,OPSTRING) \
+    img = psImageAlloc(c,r,PS_TYPE_##DATATYPE); \
+    for (unsigned row=0;row<r;row++) { \
+        ps##DATATYPE* imgRow = img->data.DATATYPE[row]; \
+        for (unsigned col=0;col<c;col++) { \
+            imgRow[col] = 6.0; \
+        } \
+    } \
+    img2 = psImageAlloc(c/2,r/2,PS_TYPE_##DATATYPE); \
+    for (unsigned row=0;row<r/2;row++) { \
+        ps##DATATYPE* img2Row = img2->data.DATATYPE[row]; \
+        for (unsigned col=0;col<c/2;col++) { \
+            img2Row[col] = 2.0; \
+        } \
+    } \
+    retVal = psImageOverlaySection(img,img2,c/4,r/4,OPSTRING); \
+    if (retVal == 0) { \
+        psError(PS_ERR_UNKNOWN, true,"psImageOverlaySection returned zero with %s op", \
+                OPSTRING); \
+        return 1; \
+    } \
+    for (unsigned row=0;row<r;row++) { \
+        ps##DATATYPE* imgRow = img->data.DATATYPE[row]; \
+        ps##DATATYPE* img2Row = img2->data.DATATYPE[row]; \
+        for (unsigned col=0;col<c;col++) { \
+            ps##DATATYPE val = 6.0; \
+            if ( ! (row < r/4 || row >= r/2+r/4 || col < c/4 || col >= c/2+c/4)) { \
+                val OP 2.0; \
+            } \
+            if (fabsf(imgRow[col] - val) > FLT_EPSILON) { \
+                psError(PS_ERR_UNKNOWN, true,"Value incorrect at %d,%d (%.2f vs %.2f for %s)", \
+                        col,row,imgRow[col],val,OPSTRING); \
+                return 2; \
+            } \
+            if (row < r/2 && col < c/2 && fabsf(img2Row[col] - 2.0) > FLT_EPSILON) { \
+                psError(PS_ERR_UNKNOWN, true,"Overlay modified at %d,%d (%.2f for %s)", \
+                        col,row,img2Row[col],OPSTRING); \
+                return 2; \
+            } \
+        } \
+    } \
+    psFree(img); \
+    psFree(img2);
+
+    #define testOverlayType(DATATYPE) \
+    testOverlayTypeOP(DATATYPE,+=,"+"); \
+    testOverlayTypeOP(DATATYPE,-=,"-"); \
+    testOverlayTypeOP(DATATYPE,*=,"*");\
+    testOverlayTypeOP(DATATYPE,/=,"/");\
+    testOverlayTypeOP(DATATYPE,=,"=");
+
+    testOverlayType(C64);
+    testOverlayType(C32);
+    testOverlayType(F64);
+    testOverlayType(F32);
+    testOverlayType(S16);
+    testOverlayType(S8);
+    testOverlayType(U16);
+    testOverlayType(U8);
+
+    /*
+    Verify the returned integer is equal to non-zero and the input psImage structure
+    is unmodified, if the overlay specified is not within the data range of the
+    input psImage structure.
+    */
+
+    img = psImageAlloc(c,r,PS_TYPE_F32);
+    for (unsigned row=0;row<r;row++) {
+        psF32* imgRow = img->data.F32[row];
+        for (unsigned col=0;col<c;col++) {
+            imgRow[col] = 6.0f;
+        }
+    }
+    img2 = psImageAlloc(c,r,PS_TYPE_F32);
+    for (unsigned row=0;row<r;row++) {
+        psF32* img2Row = img2->data.F32[row];
+        for (unsigned col=0;col<c;col++) {
+            img2Row[col] = 2.0f;
+        }
+    }
+    img3 = psImageAlloc(c,r,PS_TYPE_S64);
+    for (unsigned row=0;row<r;row++) {
+        psS64* img3Row = img3->data.S64[row];
+        for (unsigned col=0;col<c;col++) {
+            img3Row[col] = 6.0f;
+        }
+    }
+    img4 = psImageAlloc(c,r,PS_TYPE_S64);
+    for (unsigned row=0;row<r;row++) {
+        psS64* img4Row = img4->data.S64[row];
+        for (unsigned col=0;col<c;col++) {
+            img4Row[col] = 2.0f;
+        }
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should error as overlay isn't "
+             "within image boundaries");
+    retVal = psImageOverlaySection(img,img2,c/4,r/4,"+");
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"psImageOverlaySection did not return "
+                "zero even though overlay too big");
+        return 3;
+    }
+    for (unsigned row=0;row<r;row++) {
+        psF32* imgRow = img->data.F32[row];
+        for (unsigned col=0;col<c;col++) {
+            if (imgRow[col] != 6.0f) {
+                psError(PS_ERR_UNKNOWN, true,"Input image modified when overlay size too big");
+                return 4;
+            }
+        }
+    }
+
+    /*
+    Verify the returned integer is equal to non-zero, the input psImage
+    structure is unmodified and program execution doesn't stop, if the
+    overlay specified is null.
+    */
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should error as overlay is NULL");
+    retVal = psImageOverlaySection(img,NULL,c/4,r/4,"+");
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"psImageOverlaySection did not return "
+                "zero even though overlay too big");
+        return 5;
+    }
+    for (unsigned row=0;row<r;row++) {
+        psF32* imgRow = img->data.F32[row];
+        for (unsigned col=0;col<c;col++) {
+            if (imgRow[col] != 6.0f) {
+                psError(PS_ERR_UNKNOWN, true,"Input image modified when overlay NULL");
+                return 6;
+            }
+        }
+    }
+
+    /*
+    Verify the returned integer is equal to non-zero and program execution
+    doesn't stop, if the input parameter image is null.
+    */
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should error as image input is NULL");
+    retVal = psImageOverlaySection(NULL,img2,c/4,r/4,"+");
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"psImageOverlaySection returned non-zero even though "
+                "overlay too big");
+        return 7;
+    }
+
+    /*
+    Verify the return integer is equal to non-zero and program execution
+    doesn't stop, if the specified operator is not =,+,-,*,/
+    */
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should error as operator is invalid");
+    retVal = psImageOverlaySection(img,img2,0,0,"$");
+    if (retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"psImageOverlaySection returned non-zero even though "
+                "overlay operator is invalid");
+        return 8;
+    }
+
+    /*
+    Verify the return integer is equal to non-zero and program execution
+    doesn't stop, if the specified operator is NULL
+    */
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should error as operator is invalid");
+    retVal = psImageOverlaySection(img,img2,0,0,NULL);
+    if(retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"psImageOverlaySection returned non-zero even though "
+                "overlay operator is NULL");
+        return 9;
+    }
+
+    /*
+    Verify the return integer is equal to non-zero and program execution
+    doesn't stop, if overlay image is a different type than the input image
+    */
+    psLogMsg(__func__,PS_LOG_INFO,"Following should error as overlay is "
+             "a different type");
+    retVal = psImageOverlaySection(img,img3,0,0,"+");
+    if(retVal != 0) {
+        psError(PS_ERR_UNKNOWN, true,"psImageOverlaySection returned nonzero eventhough "
+                " overlay image type is different than input image.");
+        return 10;
+    }
+
+    /*
+    Verify program execution doen't stop, if the overly image contains
+    zero values with division operation is specified.
+    */
+    for (unsigned row=0;row<r;row++) {
+        psF32* img2Row = img2->data.F32[row];
+        for (unsigned col=0;col<c;col++) {
+            img2Row[col] = 0.0f;
+        }
+    }
+    retVal = psImageOverlaySection(img,img2,0,0,"/");
+    if (retVal == 0) {
+        psError(PS_ERR_UNKNOWN, true,"psImageOverlaySection returned zero when "
+                "checking divide-by-zero.");
+        return 12;
+    }
+
+    psFree(img);
+    psFree(img2);
+    psFree(img3);
+    psFree(img4);
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageSmooth.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageSmooth.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageSmooth.c	(revision 22158)
@@ -0,0 +1,179 @@
+/** @file  tst_psImageConvolve.c
+ *
+ *  This code will test the psImageSmooth() routine.
+ *
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-05-09 03:20:00 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "psTest.h"
+#include "pslib_strict.h"
+#include "psType.h"
+
+static psS32 testImageSmooth();
+
+testDescription tests[] = {
+                              {testImageSmooth, 0, "psImageSmooth", 0, false},
+                              {NULL}
+                          };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+
+    return ! runTestSuite(stderr, "psImage", tests, argc, argv);
+}
+
+#define NUM_ROWS 20
+#define NUM_COLS 20
+#define SIGMA 1.0
+#define NSIGMA 5.0
+#define TS00_IM_NULL            0x00000001
+#define TS00_IM_F32             0x00000002
+#define TS00_IM_F64             0x00000004
+#define TS00_IM_S32             0x00000008
+#define VERBOSE 0
+
+static psBool testImageSmoothGeneric(
+    psU32 flags,
+    psS32 numCols,
+    psS32 numRows,
+    psF64 sigma,
+    psF64 Nsigma,
+    psBool expectedRC)
+{
+    psBool testStatus = true;
+    psImage *img = NULL;
+
+    printPositiveTestHeader(stdout, "psImageConvolve.c", "Image Smoothing Routine");
+
+    if (expectedRC == false) {
+        printf("This test should generate FALSE.\n");
+    } else {
+        printf("This test should generate TRUE.\n");
+    }
+
+    if (flags & TS00_IM_NULL) {
+        printf("        using a NULL image\n");
+    }
+
+    if (flags & TS00_IM_F32) {
+        printf("        using a psF32 image\n");
+        img = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+        // Set a checkboard pattern
+        for (psS32 i = 0 ; i < numRows ; i++) {
+            for (psS32 j = 0 ; j < numCols ; j++) {
+                if ((i%2) != (j%2)) {
+                    img->data.F32[i][j] = 1.0;
+                } else {
+                    img->data.F32[i][j] = 0.0;
+                }
+            }
+        }
+    }
+    if (VERBOSE) {
+        p_psImagePrint(1, img, "The Smoothed Image");
+    }
+
+    if (flags & TS00_IM_F64) {
+        printf("        using a psF64 image\n");
+        img = psImageAlloc(numCols, numRows, PS_TYPE_F64);
+        // Set a checkboard pattern
+        for (psS32 i = 0 ; i < numRows ; i++) {
+            for (psS32 j = 0 ; j < numCols ; j++) {
+                if ((i%2) != (j%2)) {
+                    img->data.F64[i][j] = 1.0;
+                } else {
+                    img->data.F64[i][j] = 0.0;
+                }
+            }
+        }
+    }
+
+    if (flags & TS00_IM_S32) {
+        printf("        using a psS32 image\n");
+        img = psImageAlloc(numCols, numRows, PS_TYPE_S32);
+        // Set a checkboard pattern
+        for (psS32 i = 0 ; i < numRows ; i++) {
+            for (psS32 j = 0 ; j < numCols ; j++) {
+                if ((i%2) != (j%2)) {
+                    img->data.S32[i][j] = 1;
+                } else {
+                    img->data.S32[i][j] = 0;
+                }
+            }
+        }
+    }
+    printf(" %d columns\n", numCols);
+    printf(" %d rows\n", numRows);
+    printf(" sigma is %.2f\n", sigma);
+    printf(" Nsigma is %.2f\n", Nsigma);
+
+    psBool rc = psImageSmooth(img, sigma, Nsigma);
+    if (rc == false) {
+        if (expectedRC == true) {
+            printf("TEST ERROR: psImageSmooth returned FALSE\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            printf("TEST ERROR: psImageSmooth returned TRUE\n");
+            testStatus = false;
+        }
+        if (VERBOSE) {
+            p_psImagePrint(1, img, "The Smoothed Image");
+        }
+
+        if (flags & TS00_IM_F32) {
+            for (psS32 i = 1 ; i < numRows-1 ; i++) {
+                for (psS32 j = 1 ; j < numCols-1 ; j++) {
+                    if ((fabs(img->data.F32[i][j] - 0.5) > 0.1)) {
+                        printf("TEST ERROR: img[%d][%d] was %f, expected 0.5\n",
+                               i, j, img->data.F32[i][j]);
+                        testStatus = false;
+                    }
+                }
+            }
+        }
+
+        if (flags & TS00_IM_F64) {
+            for (psS32 i = 1 ; i < numRows-1 ; i++) {
+                for (psS32 j = 1 ; j < numCols-1 ; j++) {
+                    if ((fabs(img->data.F64[i][j] - 0.5) > 0.1)) {
+                        printf("TEST ERROR: img[%d][%d] was %f, expected 0.5\n",
+                               i, j, img->data.F64[i][j]);
+                        testStatus = false;
+                    }
+                }
+            }
+        }
+    }
+    psFree(img);
+
+    return(testStatus);
+}
+
+static psS32 testImageSmooth()
+{
+    int bad = 0x00;            // What's bad?
+
+    bad |= (testImageSmoothGeneric(TS00_IM_F32, NUM_COLS, NUM_ROWS, SIGMA, NSIGMA, true)    ? 0x00 : 0x01);
+    bad |= (testImageSmoothGeneric(TS00_IM_F32, 1, NUM_ROWS, SIGMA, NSIGMA, true)           ? 0x00 : 0x02);
+    bad |= (testImageSmoothGeneric(TS00_IM_F32, NUM_COLS, 1, SIGMA, NSIGMA, true)           ? 0x00 : 0x04);
+    bad |= (testImageSmoothGeneric(TS00_IM_F32, 1, 1, SIGMA, NSIGMA, true)                  ? 0x00 : 0x08);
+    bad |= (testImageSmoothGeneric(TS00_IM_F64, NUM_COLS, NUM_ROWS, SIGMA, NSIGMA, true)    ? 0x00 : 0x10);
+    bad |= (testImageSmoothGeneric(TS00_IM_S32, NUM_COLS, NUM_ROWS, SIGMA, NSIGMA, false)   ? 0x00 : 0x20);
+    bad |= (testImageSmoothGeneric(TS00_IM_NULL, NUM_COLS, NUM_ROWS, SIGMA, NSIGMA, false)  ? 0x00 : 0x40);
+
+    return bad;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageStats.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageStats.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageStats.c	(revision 22158)
@@ -0,0 +1,819 @@
+/*
+*  C Implementation: %{MODULE}
+*
+* Description:
+*
+*
+* Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR}
+*
+* Copyright: See COPYING file that comes with this distribution
+*
+*/
+
+#include <stdio.h>
+#include <float.h>
+#include <math.h>
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+static psS32 testPsImageHistogram(void);
+static psS32 testPsImageStats(void);
+static psS32 testPsImageFitPolynomial(void);
+static psS32 testPsImagePixelInterpolate(void);
+static psS32 testPsImageEvalPolynom(void);
+static psS32 testImageCountPixel(void);
+
+static bool FitChebyF32(int numCols, int numRows);
+static bool FitChebyF64(int numCols, int numRows);
+
+testDescription tests[] = {
+                              {testPsImageHistogram, 0, "psImageHistogram", 0, false},
+                              {testPsImageStats, 1, "psImageStats", 0, false},
+                              {testPsImageFitPolynomial, 2, "psImageFitPolynomial", 0, false},
+                              {testPsImagePixelInterpolate, 3, "psImagePixelInterpolate", 0, false},
+                              {testPsImageEvalPolynom, 4, "psImageEvalPolynom()", 0, false},
+                              {testImageCountPixel, 5, "psImageCountPixel", 0, false},
+                              {NULL}
+                          };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+
+    return ! runTestSuite(stderr,"psImage",tests,argc,argv);
+}
+
+
+
+static psS32 testPsImageHistogram(void)
+{
+    const int NUM_BINS = 20;
+    const int N = 32;
+    const int M = 64;
+
+    psHistogram * myHist = NULL;
+    psHistogram *myHist2 = NULL;
+    psImage *tmpImage = NULL;
+    psImage *tmpImage2 = NULL;
+    psImage *tmpMask = NULL;
+    psImage *tmpMask2 = NULL;
+    psS32 testStatus = true;
+    psS32 nb = 0;
+    psS32 i = 0;
+    psS32 j = 0;
+    psS32 IMAGE_X_SIZE = 0;
+    psS32 IMAGE_Y_SIZE = 0;
+    psS32 currentId = 0;
+
+    currentId = psMemGetId();
+    for ( nb = 0;nb < 7;nb++ ) {
+        if ( nb == 0 ) {
+            IMAGE_X_SIZE = 1;
+            IMAGE_Y_SIZE = 1;
+        }
+        if ( nb == 1 ) {
+            IMAGE_X_SIZE = 1;
+            IMAGE_Y_SIZE = N;
+        }
+        if ( nb == 2 ) {
+            IMAGE_X_SIZE = N;
+            IMAGE_Y_SIZE = 1;
+        }
+        if ( nb == 3 ) {
+            IMAGE_X_SIZE = N;
+            IMAGE_Y_SIZE = N;
+        }
+        if ( nb == 4 ) {
+            IMAGE_X_SIZE = N;
+            IMAGE_Y_SIZE = M;
+        }
+        if ( nb == 5 ) {
+            IMAGE_X_SIZE = M;
+            IMAGE_Y_SIZE = N;
+        }
+        if ( nb == 6 ) {
+            IMAGE_X_SIZE = M;
+            IMAGE_Y_SIZE = N;
+        }
+        fprintf(stderr, "*******************************\n" );
+        if (nb != 6) {
+            fprintf(stderr, "* IMAGE SIZE is (%d by %d)\n", IMAGE_X_SIZE, IMAGE_Y_SIZE );
+        } else {
+            fprintf(stderr, "* IMAGE SUBSET SIZE is (%d by %d)\n", IMAGE_X_SIZE, IMAGE_Y_SIZE );
+        }
+        fprintf(stderr, "*******************************\n" );
+        /*********************************************************************/
+        /*  Allocate and initialize data structures                      */
+        /*********************************************************************/
+        if (nb != 6) {
+            tmpImage = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_F32 );
+            tmpMask = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_U8 );
+            tmpImage2 = NULL;
+            tmpMask2 = NULL;
+        } else {
+            tmpImage2 = psImageAlloc( IMAGE_X_SIZE*2, IMAGE_Y_SIZE*2, PS_TYPE_F32 );
+            tmpMask2 = psImageAlloc( IMAGE_X_SIZE*2, IMAGE_Y_SIZE*2, PS_TYPE_U8 );
+            tmpImage = psImageSubset(tmpImage2, psRegionSet(IMAGE_X_SIZE/4, IMAGE_X_SIZE/4+IMAGE_X_SIZE,
+                                     IMAGE_Y_SIZE/4, IMAGE_Y_SIZE/4+IMAGE_Y_SIZE));
+            tmpMask= psImageSubset(tmpMask2, psRegionSet(IMAGE_X_SIZE/4, IMAGE_X_SIZE/4+IMAGE_X_SIZE,
+                                   IMAGE_Y_SIZE/4, IMAGE_Y_SIZE/4+IMAGE_Y_SIZE));
+        }
+
+
+        for ( i = 0;i < tmpImage->numRows;i++ ) {
+            for ( j = 0;j < tmpImage->numCols;j++ ) {
+                tmpImage->data.F32[ i ][ j ] = ( float ) ( i + j + 0.1 );
+            }
+        }
+
+
+        for ( i = 0;i < tmpMask->numRows;i++ ) {
+            for ( j = 0;j < tmpMask->numCols;j++ ) {
+                if ( ( i > ( tmpMask->numRows / 2 ) ) &&
+                        ( j > ( tmpMask->numCols / 2 ) ) ) {
+                    tmpMask->data.U8[ i ][ j ] = 1;
+                } else {
+                    tmpMask->data.U8[ i ][ j ] = 0;
+                }
+            }
+        }
+
+        /*************************************************************************/
+        /*  Calculate Histogram with no mask                             */
+        /*************************************************************************/
+
+        myHist = psHistogramAlloc( 0.0, ( float ) ( IMAGE_X_SIZE + IMAGE_Y_SIZE ),
+                                   NUM_BINS );
+        myHist = psImageHistogram( myHist, tmpImage, NULL, 0 );
+        for ( i = 0;i < NUM_BINS;i++ ) {
+            fprintf(stderr, "Bin number %d bounds: (%.1f - %.1f) data (%.2f)\n", i,
+                    myHist->bounds->data.F32[ i ],
+                    myHist->bounds->data.F32[ i + 1 ],
+                    myHist->nums->data.F32[ i ] );
+        }
+        psFree( myHist );
+
+        /*************************************************************************/
+        /*  Calculate Histogram with mask                                */
+        /*************************************************************************/
+
+        myHist = psHistogramAlloc( 0.0, ( float ) ( IMAGE_X_SIZE + IMAGE_Y_SIZE ),
+                                   NUM_BINS );
+        myHist = psImageHistogram( myHist, tmpImage, tmpMask, 1 );
+        for ( i = 0;i < NUM_BINS;i++ ) {
+            fprintf( stderr, "Bin number %d bounds: (%.2f - %.2f) data (%.2f)\n", i,
+                     myHist->bounds->data.F32[ i ],
+                     myHist->bounds->data.F32[ i + 1 ],
+                     myHist->nums->data.F32[ i ] );
+        }
+
+        /*************************************************************************/
+        /*  Deallocate data structures                                   */
+        /*************************************************************************/
+        psFree( myHist );
+        psFree( tmpImage );
+        psFree( tmpImage2 );
+        psFree( tmpMask );
+        psFree( tmpMask2 );
+    }
+    tmpImage = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_F32 );
+    myHist = psHistogramAlloc( 0.0, ( float ) ( IMAGE_X_SIZE + IMAGE_Y_SIZE ),
+                               NUM_BINS );
+    myHist2 = psImageHistogram( NULL, tmpImage, NULL, 0 );
+    if ( myHist2 != NULL ) {
+        fprintf(stderr, "ERROR: myHist2 not equal to NULL\n" );
+    }
+
+    myHist2 = psImageHistogram( myHist, NULL, NULL, 0 );
+    myHist2 = psImageHistogram( NULL, tmpImage, NULL, 0 );
+    if ( myHist2 != NULL ) {
+        fprintf(stderr, "ERROR: myHist2 not equal to NULL\n" );
+    }
+
+
+    tmpMask = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_S8 );
+    for ( i = 0;i < tmpMask->numRows;i++ ) {
+        for ( j = 0;j < tmpMask->numCols;j++ ) {
+            if ( ( i > ( tmpMask->numRows / 2 ) ) &&
+                    ( j > ( tmpMask->numCols / 2 ) ) ) {
+                tmpMask->data.S8[ i ][ j ] = 1;
+            } else {
+                tmpMask->data.S8[ i ][ j ] = 0;
+            }
+        }
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error for invalid mask type.");
+    myHist2 = psImageHistogram(myHist,tmpImage,tmpMask,1);
+    if (myHist2 != NULL) {
+        fprintf(stderr,"ERROR: myHist2 not equal to NULL\n");
+    }
+
+    psFree( tmpMask );
+    psFree(myHist);
+    psFree(myHist2);
+    psFree( tmpImage );
+
+    return ( !testStatus );
+}
+
+static psS32 testPsImageFitPolynomial()
+{
+    const int IMAGE_SIZE = 16;
+    const int CHEBY_X_DIM = 8;
+    const int CHEBY_Y_DIM = 8;
+    const int THRESHOLD = 10;
+
+    psStats * myStats = NULL;
+    psImage *tmpImage = NULL;
+    psImage *outImage = NULL;
+    psImage *nullImage = NULL;
+    psPolynomial2D *my2DPoly = NULL;
+    psPolynomial2D *null2DPoly = NULL;
+    psS32 testStatus = true;
+    psS32 i = 0;
+    psS32 j = 0;
+    psS32 currentId = 0;
+
+    currentId = psMemGetId();
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    tmpImage = psImageAlloc( IMAGE_SIZE, IMAGE_SIZE, PS_TYPE_F32 );
+    outImage = psImageAlloc( IMAGE_SIZE, IMAGE_SIZE, PS_TYPE_F32 );
+    for ( i = 0;i < IMAGE_SIZE;i++ ) {
+        for ( j = 0;j < IMAGE_SIZE;j++ ) {
+            tmpImage->data.F32[ i ][ j ] = 4.0;
+            tmpImage->data.F32[ i ][ j ] = ( float ) ( i + j );
+            tmpImage->data.F32[ i ][ j ] = ( float ) ( i + j ) + ( 4.0 * ( float ) i );
+            outImage->data.F32[ i ][ j ] = 0.0;
+        }
+    }
+    my2DPoly = psPolynomial2DAlloc(PS_POLYNOMIAL_CHEB, CHEBY_X_DIM-1, CHEBY_Y_DIM-1);
+    /*************************************************************************/
+    /*  Calculate Chebyshev Polynomials, no mask                     */
+    /*************************************************************************/
+    my2DPoly = psImageFitPolynomial( my2DPoly, tmpImage );
+    if (my2DPoly == NULL) {
+        printf("TEST ERROR: psImageFitPolynomial() returned NULL.\n");
+        testStatus = false;
+    }
+    for ( i = 0;i < CHEBY_X_DIM;i++ ) {
+        for ( j = 0;j < CHEBY_Y_DIM;j++ ) {
+            fprintf(stderr, "Cheby Polynomial (%d, %d) coefficient is %.2f\n", i, j,
+                    0.0001f+my2DPoly->coeff[ i ][ j ] );
+        }
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error message for NULL coeffs argument.");
+    null2DPoly = psImageFitPolynomial( NULL, tmpImage );
+    if ( null2DPoly != NULL ) {
+        fprintf(stderr,"ERROR: psImageFitPolynomial did not return NULL with invalid coeffs argument.");
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be a error message for NULL input argument.");
+    null2DPoly = psImageFitPolynomial( null2DPoly, NULL );
+    if ( null2DPoly != NULL ) {
+        fprintf(stderr,"ERROR: psImageFitPolynomial did not return NULL with null input image.");
+    }
+
+    /*************************************************************************/
+    /*  Evaluate Chebyshev Polynomials, no mask                      */
+    /*************************************************************************/
+    outImage = psImageEvalPolynomial( outImage, my2DPoly );
+    for ( i = 0;i < IMAGE_SIZE;i++ ) {
+        for ( j = 0;j < IMAGE_SIZE;j++ ) {
+
+            //             fprintf(stderr,"pixel[%d][%d] is (%.2f, %.2f)\n", i, j,
+            //                     tmpImage->data.F32[i][j],
+            //                     outImage->data.F32[i][j]);
+            if ( fabs( outImage->data.F32[ i ][ j ] - tmpImage->data.F32[ i ][ j ] ) > THRESHOLD ) {
+                fprintf(stderr, "Pixel (%d, %d) is %.2f, should be %.2f\n", i, j,
+                        outImage->data.F32[ i ][ j ],
+                        tmpImage->data.F32[ i ][ j ] );
+            }
+
+        }
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error message for NULL coeffs argument.");
+    nullImage = psImageEvalPolynomial( outImage, NULL );
+    if ( nullImage != NULL ) {
+        fprintf(stderr,"ERROR: psImageEvalPolynomial did not return NULL with invalid coeffs argument.");
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be a error message for NULL input argument.");
+    nullImage = psImageEvalPolynomial( NULL, my2DPoly );
+    if ( nullImage != NULL ) {
+        fprintf(stderr,"ERROR: psImageEvalPolynomial did not return NULL with null input image.");
+    }
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+    psFree( myStats );
+    psFree( tmpImage );
+    psFree( outImage );
+    psFree( my2DPoly );
+
+    return ( !testStatus );
+}
+
+static psS32 testPsImagePixelInterpolate()
+{
+    const int IMAGE_SIZE = 10;
+
+    psImage *tmpImage   = NULL;
+    psS32 testStatus      = true;
+    psS32 i               = 0;
+    psS32 j               = 0;
+    float pixel         = 0.0;
+    float x             = 0.0;
+    float y             = 0.0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    tmpImage = psImageAlloc(IMAGE_SIZE, IMAGE_SIZE, PS_TYPE_F32);
+    for (i=0;i<IMAGE_SIZE;i++) {
+        for (j=0;j<IMAGE_SIZE;j++) {
+            tmpImage->data.F32[i][j] = 4.0;
+            tmpImage->data.F32[i][j] = (float) (i + j) + (4.0 * (float) i);
+            tmpImage->data.F32[i][j] = (float) (i + j);
+            fprintf(stderr,"%.1f ", tmpImage->data.F32[i][j]);
+        }
+        fprintf(stderr,"\n");
+    }
+    for (i=0;i<IMAGE_SIZE-1;i++) {
+        for (j=0;j<IMAGE_SIZE-1;j++) {
+            x = 0.2 + (float) i;
+            y = 0.2 + (float) j;
+            pixel = psImagePixelInterpolate(tmpImage,
+                                            x, y,
+                                            NULL, 0,
+                                            0,
+                                            PS_INTERPOLATE_BILINEAR);
+            fprintf(stderr,"%.1f ", pixel);
+        }
+        fprintf(stderr,"\n");
+    }
+
+    for (i=0;i<IMAGE_SIZE-1;i++) {
+        for (j=0;j<IMAGE_SIZE-1;j++) {
+            x = 0.2 + (float) i;
+            y = 0.2 + (float) j;
+            pixel = psImagePixelInterpolate(tmpImage,
+                                            x, y,
+                                            NULL,0,
+                                            0,
+                                            PS_INTERPOLATE_BILINEAR);
+            fprintf(stderr,"image[%.1f][%.1f] is interpolated at %.1f\n", x, y, pixel);
+        }
+    }
+
+    psFree(tmpImage);
+
+    return (!testStatus);
+}
+
+#define I_POLY(X, Y) \
+((A) + (B * X) + (C * Y) + (D * X * Y) + (E * X * X) + (F * Y * Y)) \
+
+static bool FitChebyF32(int numCols, int numRows)
+{
+    const double A = 1.0;
+    const double B = 2.0;
+    const double C = 3.0;
+    const double D = 4.0;
+    const double E = 5.0;
+    const double F = 6.0;
+    const double ERROR_TOL = 0.1;
+
+    psImage *tmpImage     = NULL;
+    psImage *outImage     = NULL;
+    bool testStatus      = true;
+    psS32 i               = 0;
+    psS32 j               = 0;
+    float chi2 = 0.0;
+
+
+    fprintf(stderr,"psImageFitPolynomial(), psImageEvalPolynom(): (%d by %d)\n", numRows, numCols);
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+
+    tmpImage = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    outImage = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols;j++) {
+            tmpImage->data.F32[i][j] = I_POLY(((float) i), ((float) j));
+        }
+    }
+
+    psPolynomial2D *chebys = psPolynomial2DAlloc(PS_POLYNOMIAL_CHEB, 5, 5);
+
+    chebys = psImageFitPolynomial(chebys, tmpImage);
+
+    outImage = psImageEvalPolynomial(outImage, chebys);
+
+    chi2 = 0.0;
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols;j++) {
+            float expect = tmpImage->data.F32[i][j];
+            float actual = outImage->data.F32[i][j];
+            chi2+= (actual-expect) * (actual-expect);
+            if (fabs((actual - expect) / expect) > ERROR_TOL) {
+                fprintf(stderr,"pixel [%d][%d] is %.2f should be %.2f\n", i, j, actual, expect);
+            }
+        }
+    }
+    chi2/= ((float) (numCols * numRows));
+    fprintf(stderr,"The chi-squared per pixel is %.2f\n", chi2);
+
+    psFree(tmpImage);
+    psFree(outImage);
+    psFree(chebys);
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+
+    return(testStatus);
+}
+
+static bool FitChebyF64(int numCols, int numRows)
+{
+    const double A = 1.0;
+    const double B = 2.0;
+    const double C = 3.0;
+    const double D = 4.0;
+    const double E = 5.0;
+    const double F = 6.0;
+    const double ERROR_TOL = 0.1;
+
+    psImage *tmpImage     = NULL;
+    psImage *outImage     = NULL;
+    bool testStatus      = true;
+    psS32 i               = 0;
+    psS32 j               = 0;
+    double chi2 = 0.0;
+
+
+    fprintf(stderr,"psImageFitPolynomial(), psImageEvalPolynom(): (%d by %d)\n", numRows, numCols);
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+
+    tmpImage = psImageAlloc(numCols, numRows, PS_TYPE_F64);
+    outImage = psImageAlloc(numCols, numRows, PS_TYPE_F64);
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols;j++) {
+            tmpImage->data.F64[i][j] = I_POLY(((double) i), ((double) j));
+        }
+    }
+
+    psPolynomial2D *chebys = psPolynomial2DAlloc(PS_POLYNOMIAL_CHEB, 5, 5);
+
+    chebys = psImageFitPolynomial(chebys, tmpImage);
+
+    outImage = psImageEvalPolynomial(outImage, chebys);
+
+    chi2 = 0.0;
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols;j++) {
+            double expect = tmpImage->data.F64[i][j];
+            double actual = outImage->data.F64[i][j];
+            chi2+= (actual-expect) * (actual-expect);
+            if (fabs((actual - expect) / expect) > ERROR_TOL) {
+                fprintf(stderr,"pixel [%d][%d] is %.2f should be %.2f\n", i, j, actual, expect);
+            }
+        }
+    }
+    chi2/= ((double) (numCols * numRows));
+    fprintf(stderr,"The chi-squared per pixel is %.2f\n", chi2);
+
+    psFree(tmpImage);
+    psFree(outImage);
+    psFree(chebys);
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+
+    return(testStatus);
+}
+
+static psS32 testPsImageEvalPolynom()
+{
+    if (!FitChebyF32(1, 1)) {
+        return 1;
+    }
+    if (!FitChebyF32(1, 5)) {
+        return 2;
+    }
+    if (!FitChebyF32(5, 1)) {
+        return 3;
+    }
+    if (!FitChebyF32(5, 5)) {
+        return 4;
+    }
+    if (!FitChebyF64(1, 1)) {
+        return 5;
+    }
+    if (!FitChebyF64(1, 5)) {
+        return 6;
+    }
+    if (!FitChebyF64(5, 1)) {
+        return 7;
+    }
+    if (!FitChebyF64(5, 5)) {
+        return 8;
+    }
+    return 0;
+}
+
+psS32 testImageCountPixel(void)
+{
+    long numPix = 0;
+    long numPix2 = 0;
+    psImage *in = NULL;
+    psRegion reg;
+    reg.x0 = 0;
+    reg.x1 = 1;
+    reg.y0 = 0;
+    reg.y1 = 4;
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    numPix = psImageCountPixelMask(in, reg, 1);
+    if (numPix != -1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCountPixelMask failed to return -1 for NULL Vector input.\n");
+        return 1;
+    }
+
+    numPix = 0;
+    in = psImageAlloc(5, 5, PS_TYPE_S32);
+
+    psImage *in2 = NULL;
+    in2 = psImageAlloc(1, 5, PS_TYPE_U8);
+
+    in->data.S32[0][0] = 0;
+    in->data.S32[1][0] = 1;
+    in->data.S32[2][0] = 0;
+    in->data.S32[3][0] = 1;
+    in->data.S32[4][0] = 0;
+    in2->data.U8[0][0] = 0;
+    in2->data.U8[1][0] = 1;
+    in2->data.U8[2][0] = 0;
+    in2->data.U8[3][0] = 1;
+    in2->data.U8[4][0] = 0;
+
+    //    numPix = psImageCountPixelMask(in, reg, 1);
+    numPix2 = psImageCountPixelMask(in2, reg, 1);
+    numPix = -1;
+    //numPix should be -1 from using S32's
+    /*    if (numPix != -1) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                    "psImageCountPixelMask failed to return -1 for wrong type of Image input.\n");
+            return 2;
+        }
+    */
+    if (numPix2 == -1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCountPixelMask returned -1 for Correct Image input\n");
+        return 3;
+    }
+    if (numPix2 != 2) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCountPixelMask returned incorrect pixel count %ld (!=2)\n", numPix2);
+        return 4;
+    }
+    //Test for smaller region than image returns only 1 pixel counted
+    reg.y1 = 2.1;
+    numPix2 = psImageCountPixelMask(in2, reg, 1);
+    if (numPix2 != 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCountPixelMask returned incorrect pixel count %ld\n", numPix2);
+        return 5;
+    }
+    //Test for -1 upper bnds in region = 5, 1 limits = 2 pixels returned
+    reg.x1 = 1;
+    reg.y1 = -1;
+    numPix2 = psImageCountPixelMask(in2, reg, 1);
+    if (numPix2 != 2) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCountPixelMask returned incorrect pixel count %ld\n", numPix2);
+        return 100;
+    }
+
+    //Test for invalid region (1 pixel, lower = upper)
+    reg.x0 = 1;
+    reg.y0 = 1;
+    reg.x1 = 1;
+    reg.y1 = 1;
+    //    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    numPix2 = psImageCountPixelMask(in2, reg, 1);
+    if (numPix2 != 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCountPixelMask failed to return correct value (0) for 1 pixel region.\n");
+        return 9;
+    }
+
+    //Test for whole image (region = 0,0 0,0 )
+    reg.x0 = 0;
+    reg.x1 = 0;
+    reg.y0 = 0;
+    reg.y1 = 0;
+    numPix2 = psImageCountPixelMask(in2, reg, 1);
+    if (numPix2 != 2) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCountPixelMask returned incorrect pixel count %ld\n", numPix2);
+        return 10;
+    }
+
+    //Test a subimage.
+    reg.x1 = 1;
+    reg.y0 = 1;
+    reg.y1 = 5;
+    numPix2 = -1;
+    in2->row0 = 1;
+    numPix2 = psImageCountPixelMask(in2, reg, 1);
+    if (numPix2 != 2) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageCountPixelMask returned incorrect pixel count %ld (!=2)\n", numPix2);
+        return 11;
+    }
+
+    psFree(in);
+    psFree(in2);
+    return 0;
+}
+
+static psS32 testPsImageStats()
+{
+    psTraceSetLevel("p_psVectorRobustStats", 0);
+
+    const int N  = 32;
+    const int M = 64;
+
+    psStats * myStats = NULL;
+    psStats *myStats2 = NULL;
+    psImage *tmpImage = NULL;
+    psImage *tmpImage2 = NULL;
+    psImage *tmpMask = NULL;
+    psImage *tmpMask2 = NULL;
+    psS32 testStatus = true;
+    psS32 nb = 0;
+    psS32 i = 0;
+    psS32 j = 0;
+    psS32 IMAGE_X_SIZE = 0;
+    psS32 IMAGE_Y_SIZE = 0;
+    psS32 currentId = 0;
+
+    currentId = psMemGetId();
+    for ( nb = 0;nb < 7;nb++ ) {
+        if ( nb == 0 ) {
+            IMAGE_X_SIZE = 1;
+            IMAGE_Y_SIZE = 1;
+        }
+        if ( nb == 1 ) {
+            IMAGE_X_SIZE = 1;
+            IMAGE_Y_SIZE = N;
+        }
+        if ( nb == 2 ) {
+            IMAGE_X_SIZE = N;
+            IMAGE_Y_SIZE = 1;
+        }
+        if ( nb == 3 ) {
+            IMAGE_X_SIZE = N;
+            IMAGE_Y_SIZE = N;
+        }
+        if ( nb == 4 ) {
+            IMAGE_X_SIZE = N;
+            IMAGE_Y_SIZE = M;
+        }
+        if ( nb == 5 ) {
+            IMAGE_X_SIZE = M;
+            IMAGE_Y_SIZE = N;
+        }
+        if ( nb == 6 ) {
+            IMAGE_X_SIZE = M;
+            IMAGE_Y_SIZE = N;
+        }
+        fprintf(stderr, "*******************************\n" );
+        if (nb != 6) {
+            fprintf(stderr, "* IMAGE SIZE is (%d by %d)\n", IMAGE_X_SIZE, IMAGE_Y_SIZE );
+        } else {
+            fprintf(stderr, "* IMAGE SUBSET SIZE is (%d by %d)\n", IMAGE_X_SIZE, IMAGE_Y_SIZE );
+        }
+        fprintf(stderr, "*******************************\n" );
+
+        /*************************************************************************/
+        /*  Allocate and initialize data structures                      */
+        /*************************************************************************/
+        if (nb != 6) {
+            tmpImage = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_F32 );
+            tmpMask = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_U8 );
+            tmpImage2 = NULL;
+            tmpMask2 = NULL;
+        } else {
+            tmpImage2 = psImageAlloc( IMAGE_X_SIZE*2, IMAGE_Y_SIZE*2, PS_TYPE_F32 );
+            tmpMask2 = psImageAlloc( IMAGE_X_SIZE*2, IMAGE_Y_SIZE*2, PS_TYPE_U8 );
+            tmpImage = psImageSubset(tmpImage2, psRegionSet(IMAGE_X_SIZE/4, IMAGE_X_SIZE/4+IMAGE_X_SIZE,
+                                     IMAGE_Y_SIZE/4, IMAGE_Y_SIZE/4+IMAGE_Y_SIZE));
+            tmpMask = psImageSubset(tmpMask2, psRegionSet(IMAGE_X_SIZE/4, IMAGE_X_SIZE/4+IMAGE_X_SIZE,
+                                    IMAGE_Y_SIZE/4, IMAGE_Y_SIZE/4+IMAGE_Y_SIZE));
+        }
+
+        for ( i = 0;i < tmpImage->numRows;i++ ) {
+            for ( j = 0;j < tmpImage->numCols;j++ ) {
+                tmpImage->data.F32[ i ][ j ] = ( float ) ( i + j );
+            }
+        }
+
+        for ( i = 0;i < tmpMask->numRows;i++ ) {
+            for ( j = 0;j < tmpMask->numCols;j++ ) {
+                if ( ( i > ( tmpMask->numRows / 2 ) ) &&
+                        ( j > ( tmpMask->numCols / 2 ) ) ) {
+                    tmpMask->data.U8[ i ][ j ] = 1;
+                } else {
+                    tmpMask->data.U8[ i ][ j ] = 0;
+                }
+            }
+        }
+
+        myStats = psStatsAlloc( PS_STAT_SAMPLE_MEAN );
+        /*************************************************************************/
+        /*  Calculate Sample Mean with no mask                           */
+        /*************************************************************************/
+        psStats* tmpStats = myStats;
+        myStats = psImageStats( myStats, tmpImage, NULL, 0 );
+        if ( myStats != tmpStats ) {
+            fprintf(stderr,"ERROR: input psStats not equal to return psStats\n");
+            psAbort("Failed input psStats equal to returned psStats");
+        }
+        fprintf(stderr, "The sample mean was %.2f\n", myStats->sampleMean );
+
+        /*************************************************************************/
+        /*  Calculate Sample Mean with mask                              */
+        /*************************************************************************/
+
+        myStats = psImageStats( myStats, tmpImage, tmpMask, 1 );
+        if (myStats == NULL) {
+            fprintf(stderr,"TEST ERROR: psImageStats() returned NULL.\n");
+        } else {
+            fprintf(stderr, "The sample mean was %.2f\n", myStats->sampleMean );
+        }
+
+        /*************************************************************************/
+        /*  Deallocate data structures                                   */
+        /*************************************************************************/
+        psFree( myStats );
+        psFree( tmpImage );
+        psFree( tmpMask );
+        psFree( tmpImage2 );
+        psFree( tmpMask2 );
+    }
+
+    /*************************************************************************/
+    /*  Test With Various Null Inputs                                        */
+    /*************************************************************************/
+
+    tmpImage = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_F32 );
+    tmpMask = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_U8 );
+    myStats = psStatsAlloc( 0 );
+
+    myStats2 = psImageStats( myStats, NULL, NULL, 0 );
+    if ( myStats2 != NULL ) {
+        fprintf(stderr, "ERROR: myStats2 = psImageStats(myStats, NULL, NULL, 0) != NULL\n" );
+    }
+
+    myStats2 = psImageStats( NULL, tmpImage, NULL, 0 );
+    if ( myStats2 != NULL ) {
+        fprintf(stderr, "ERROR: myStats2 = psImageStats(NULL, tmpImage, NULL, 0) != NULL\n" );
+    }
+
+    myStats2 = psImageStats( myStats, tmpImage, NULL, 0 );
+
+    psFree( myStats );
+    psFree( tmpImage );
+    psFree( tmpMask );
+
+    tmpImage = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_F32);
+    tmpMask = psImageAlloc( IMAGE_X_SIZE, IMAGE_Y_SIZE, PS_TYPE_U32);
+    myStats = psStatsAlloc( PS_STAT_SAMPLE_MEAN );
+    myStats2 = psImageStats( myStats, tmpImage, tmpMask, 0 );
+    if ( myStats2 != NULL ) {
+        fprintf(stderr, "ERROR: psImageStats did not return null when mask is invalid type.\n");
+    }
+    psFree(tmpImage);
+    psFree(tmpMask);
+    psFree(myStats);
+
+    return ( !testStatus );
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageStructManip.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageStructManip.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/tst_psImageStructManip.c	(revision 22158)
@@ -0,0 +1,702 @@
+/** @file  tst_psImageExtraction.c
+*
+*  @brief Contains the tests for psImageExtraction.[ch]
+*
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2006-05-05 02:48:34 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+#include<stdlib.h>
+#include<string.h>
+
+#include "psTest.h"
+#include "pslib_strict.h"
+#include "psType.h"
+
+static psS32 testImageSubset(void);
+static psS32 testImageCopy(void);
+static psS32 testImageTrim(void);
+
+
+testDescription tests[] = {
+                              {testImageSubset,547,"psImageSubset",0,false},
+                              {testImageSubset,550,"psImageSubset",0,true},
+                              {testImageCopy,551,"psImageCopy",0,false},
+                              {testImageTrim, 744, "psImageTrim", 0, false},
+                              {NULL}
+                          };
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    return ! runTestSuite( stderr, "psImage", tests, argc, argv );
+}
+
+// #547: psImageSubset shall create child image of a specified size from a parent psImage structure
+psS32 testImageSubset(void)
+{
+    psImage preSubsetStruct;
+    psImage* original;
+    psImage* subset1 = NULL;
+    psImage* subset2 = NULL;
+    psImage* subset3 = NULL;
+    psS32 c = 128;
+    psS32 r = 256;
+    psRegion region1 = psRegionSet(0,c/2,0,r/2);
+    psRegion region2 = psRegionSet(c/4,c/4+c/2,r/4,r/4+r/2);
+
+    original = psImageAlloc(c,r,PS_TYPE_U32);
+    for (psS32 row=0;row<r;row++) {
+        for (psS32 col=0;col<c;col++) {
+            original->data.F32[row][col] = row*1000+col;
+        }
+    }
+
+    memcpy(&preSubsetStruct,original,sizeof(psImage));
+
+    subset2 = psImageSubset(original,region2);
+
+    subset3 = psImageSubset(original,region1);
+
+    psLogMsg(__func__,PS_LOG_INFO,
+             "Verify the returned psImage structure members nrow and ncol are equal to "
+             "the input parameter nrow and ncol respectively.");
+
+    if (subset2->numCols != c/2 || subset2->numRows != r/2) {
+        psError(PS_ERR_UNKNOWN,true,
+                "psImageSubset output size was not proper(%dx%d, should be %dx%d).",
+                subset2->numCols, subset2->numRows, c/2,r/2);
+        return 1;
+    }
+
+    if (subset3->numCols != c/2 || subset3->numRows != r/2) {
+        psError(PS_ERR_UNKNOWN,true,
+                "psImageSubset output size was not proper(%dx%d, should be %dx%d).",
+                subset3->numCols, subset3->numRows, c/2,r/2);
+        return 2;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,
+             "Verify the returned psImage structure contains expected values in the "
+             "row member, if the input psImage structure image contains known values.");
+
+    for (psS32 row=0;row<r/2;row++) {
+        for (psS32 col=0;col<c/2;col++) {
+            if (subset2->data.U32[row][col] != original->data.U32[row+r/4][col+c/4]) {
+                psError(PS_ERR_UNKNOWN,true,"psImageSubset output #1 was wrong at %dx%d (%d vs %d).",
+                        row,col,subset2->data.U32[row][col], original->data.U32[row+r/4][col+c/4]);
+                return 3;
+            }
+            if (subset3->data.U32[row][col] != original->data.U32[row][col]) {
+                psError(PS_ERR_UNKNOWN,true,"psImageSubset output #1 was wrong at %dx%d (%d vs %d).",
+                        row,col,subset2->data.U32[row][col], original->data.U32[row][col]);
+                return 4;
+            }
+        }
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,
+             "Verify the returned psImage structure member type is equal to the input "
+             "psImage structure member type.");
+
+    if (subset2->type.type != PS_TYPE_U32) {
+        psError(PS_ERR_UNKNOWN,true,"psImageSubset output type was not proper(%d, should be %d).",
+                subset2->type.type, PS_TYPE_U32);
+        return 6;
+    }
+    if (subset3->type.type != PS_TYPE_U32) {
+        psError(PS_ERR_UNKNOWN,true,"psImageSubset output type was not proper(%d, should be %d).",
+                subset3->type.type, PS_TYPE_U32);
+        return 7;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,
+             "Verify the returned psImage structure members row0 and col0 are equal to "
+             "the input parameters row0 and col0 respectively.");
+
+    if (subset2->col0 != c/4 || subset2->row0 != r/4) {
+        psError(PS_ERR_UNKNOWN,true,
+                "psImageSubset didn't set col0/row0 for subset2 (%d/%d, should be %d/%d).",
+                subset2->col0,subset2->row0,c/4,r/4);
+        return 8;
+    }
+    if (subset3->col0 != 0 || subset3->row0 != 0) {
+        psError(PS_ERR_UNKNOWN,true,
+                "psImageSubset didn't set col0/row0 for subset3 (%d/%d, should be %d/%d).",
+                subset3->col0,subset3->row0,0,0);
+        return 9;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,
+             "Verify the returned psImage structure member parent is equal to the "
+             "input psImage structure pointer image.");
+
+    if (subset2->parent != original || subset3->parent != original) {
+        psError(PS_ERR_UNKNOWN,true,"psImageSubset didn't set parent.");
+        return 10;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure member children is null.");
+
+    if (subset2->children != NULL || subset3->children != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psImageSubset didn't set children to NULL.");
+        return 11;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,
+             "Verify the input psImage structure image only has the following members "
+             "changed: 1) Nchildren is increased by one. 2) parent contains pointer psImage structure "
+             "out at parent[Nchildren-1].");
+
+    if (original->children == NULL || original->children->n != 2) {
+        psError(PS_ERR_UNKNOWN,true,
+                "psImageSubset didn't increment number of children by one per subset.");
+        return 12;
+    }
+    if (original->children->data[0] != subset2 || original->children->data[1] != subset3) {
+        psError(PS_ERR_UNKNOWN,true,"psImageSubset didn't properly store the children pointers.");
+        return 13;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure pointer is null and program "
+             "execution doesn't stop, if the input parameter image is null. Also verified the input "
+             "psImage structure is not modified.");
+
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(NULL,region1);
+    if (subset1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psImageSubset didn't return NULL when input image was NULL.");
+        return 14;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Verify the returned psImage structure pointer is null and program "
+             " execution doesn't stop, if the input parameters nrow and/or ncol are zero. Also verify "
+             "input psImage structure is not modified.");
+
+    memcpy(&preSubsetStruct,original,sizeof(psImage));
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(original, psRegionSet(0,c/2,r/2,r/2));
+    if (subset1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psImageSubset didn't return NULL when numRows=0.");
+        return 15;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(original,psRegionSet(c/2,c/2,0,r/2));
+    if (subset1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psImageSubset didn't return NULL when numCols=0.");
+        return 16;
+    }
+    if (memcmp(original,&preSubsetStruct,sizeof(psImage)) != 0) {
+        psError(PS_ERR_UNKNOWN,true,
+                "psImageSubset changed the original struct though it failed to subset.");
+        return 17;
+    }
+
+
+    psLogMsg(__func__,PS_LOG_INFO,
+             "Verify the returned psImage structure pointer is null and program "
+             "execution doesn't stop, if the input parameters row0 and col0 are not within "
+             "the range of values of psImage structure image.");
+
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(original, psRegionSet(0,c/2, 0,r*2));
+    if (subset1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,
+                "psImageSubset didn't return NULL when subset origin was outside of "
+                "image (via cols).");
+        return 18;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(original,psRegionSet(0,c*2,0,r/2));
+    if (subset1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,
+                "psImageSubset didn't return NULL when subset origin was outside of "
+                "image (via rows).");
+        return 19;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(original, psRegionSet(-1,c/2,0,r/2));
+    if (subset1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,
+                "psImageSubset didn't return NULL when subset origin was outside of "
+                "image (col0=-1).");
+        return 20;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(original, psRegionSet(0,c/2,-1,r/2));
+    if (subset1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,
+                "psImageSubset didn't return NULL when subset origin was outside of "
+                "image (row0=-1).");
+        return 21;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,
+             "Verify the returned psImage structure pointer is null and program "
+             "execution doesn't stop if the input parameters nrow, ncol, row0 and col0 "
+             "specify a range of data not within the input psImage structure image.  Also "
+             "verify the input psImage structure is not modified.");
+
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(original,psRegionSet(0,c/2,0,r+1));
+    if (subset1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,
+                "psImageSubset didn't return NULL when subset was outside of image (via rows).");
+        return 22;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(original, psRegionSet(0,c+1,0,r/2));
+    if (subset1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,
+                "psImageSubset didn't return NULL when subset was outside of image (via cols).");
+        return 23;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    subset1 = psImageSubset(original,psRegionSet(0,c+1,0,r+1));
+    if (subset1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,
+                "psImageSubset didn't return NULL when subset was outside of image (via row+cols).");
+        return 24;
+    }
+
+    psLogMsg(__func__, PS_LOG_INFO,
+             "psImageFreeChildren shall deallocate any children images of a "
+             "psImage structure");
+
+    memcpy(&preSubsetStruct,original,sizeof(psImage));
+
+    psImageFreeChildren(original);
+
+    // Verify the returned psImage structure member Nchildren is set to zero.
+    if (original->children != NULL && original->children->n > 0) {
+        psError(PS_ERR_UNKNOWN,true,
+                "psImageFreeChildren didn't set number of children to zero.");
+        return 25;
+    }
+
+    //Verify the returned psImage structure members type, nrow, ncol, row0, col0, rows
+    // and parent are not modified.
+    if (preSubsetStruct.numRows != original->numRows ||
+            preSubsetStruct.numCols != original->numCols ||
+            preSubsetStruct.row0 != original->row0 ||
+            preSubsetStruct.col0 != original->col0) {
+
+        psError(PS_ERR_UNKNOWN,true,
+                "psImageFreeChildren modified parent's non-children elements.");
+        return 27;
+    }
+
+    psFree(original);
+
+    return 0;
+}
+
+psS32 testImageCopy(void)
+{
+    psImage* img = NULL;
+    psImage* img2 = NULL;
+    psImage* img3 = NULL;
+    psImage* img4 = NULL;
+    psU32 c = 128;
+    psU32 r = 256;
+
+    img = psImageAlloc(c,r,PS_TYPE_F32);
+    for (unsigned row=0;row<r;row++) {
+        psF32* imgRow = img->data.F32[row];
+        for (unsigned col=0;col<c;col++) {
+            imgRow[col] = (psF32)(row+col);
+        }
+    }
+    img2 = psImageAlloc(c,r,PS_TYPE_F32);
+    for (unsigned row=0;row<r;row++) {
+        psF32* img2Row = img2->data.F32[row];
+        for (unsigned col=0;col<c;col++) {
+            img2Row[col] = 0.0f;
+        }
+    }
+
+    img3 = psImageCopy(img2,img,PS_TYPE_F32);
+
+    // Verify the returned psImage structure pointer is equal to the input parameter output.
+    if (img2 != img3) {
+        psError(PS_ERR_UNKNOWN, true,"the image given for recycled wasn't");
+        return 1;
+    }
+
+    // Verify the returned psImage structure is the same type as the input image structure
+    // if the specified output argument is NULL.
+    img4 = psImageCopy(NULL,img,PS_TYPE_F32);
+    if (img4 == NULL) {
+        psError(PS_ERR_UNKNOWN, true,"output image doesn't exist");
+        return 4;
+    }
+    if (img4->type.type != img->type.type) {
+        psError(PS_ERR_UNKNOWN, true,"output image is not the same type as input image");
+        return 4;
+    }
+    for (psU32 row=0;row<r;row++) {
+        psF32* imgInRow = img->data.F32[row];
+        psF32* imgOutRow = img4->data.F32[row];
+        for (unsigned col=0;col<c;col++) {
+            if( imgInRow[col] != imgOutRow[col] ) {
+                psError(PS_ERR_UNKNOWN, true,"Input image not equal to output image at %d,%d!",
+                        col, row);
+                return 4;
+            }
+        }
+    }
+
+    // Verify the returned psImage structure member are equal to the values in
+    // the input psImage structure input.
+
+    #define testImageCopyType(IN,OUT) \
+    img = psImageRecycle(img,c,r,PS_TYPE_##IN); \
+    for (unsigned row=0;row<r;row++) { \
+        ps##IN* imgRow = img->data.IN[row]; \
+        for (unsigned col=0;col<c;col++) { \
+            imgRow[col] = (ps##IN)(row+col); \
+        } \
+    } \
+    img2 = psImageCopy(img2,img,PS_TYPE_##OUT); \
+    if (img2 == NULL) { \
+        psError(PS_ERR_UNKNOWN, true,"psImageCopy failed to copy U8."); \
+        return 2; \
+    } \
+    for (psU32 row=0;row<r;row++) { \
+        ps##IN* imgRow = img->data.IN[row]; \
+        ps##OUT* img2Row = img2->data.OUT[row]; \
+        for (psU32 col=0;col<c;col++) { \
+            if (abs(imgRow[col] - (ps##IN)(row+col)) > 0.5) { \
+                psError(PS_ERR_UNKNOWN, true,"Input image was changed at %d,%d!", \
+                        col,row); \
+                return 2; \
+            } \
+            if (abs(img2Row[col] - (ps##OUT)(imgRow[col])) > 0.5) { \
+                psError(PS_ERR_UNKNOWN, true, \
+                        "returned psImage values after copy don't match at %d,%d " \
+                        "(%d vs %d)",\
+                        col,row,img2Row[col], (ps##OUT)(imgRow[col])); \
+                return 2; \
+            } \
+        } \
+    }
+
+    #define testImageCopyTypes(IN) \
+    printf("to psF32\n"); \
+    testImageCopyType(IN,F32);\
+    printf("to psF64\n"); \
+    testImageCopyType(IN,F64); \
+    printf("to psU8\n"); \
+    testImageCopyType(IN,U8); \
+    printf("to psU16\n"); \
+    testImageCopyType(IN,U16); \
+    printf("to psU32\n"); \
+    testImageCopyType(IN,U32); \
+    printf("to psS8\n"); \
+    testImageCopyType(IN,S8);\
+    printf("to psS16\n"); \
+    testImageCopyType(IN,S16);\
+    printf("to psS32\n"); \
+    testImageCopyType(IN,S32);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Image Copy Test for psU8");
+    testImageCopyTypes(U8);
+    psLogMsg(__func__,PS_LOG_INFO,"Image Copy Test for psU16");
+    testImageCopyTypes(U16);
+    psLogMsg(__func__,PS_LOG_INFO,"Image Copy Test for psU32");
+    testImageCopyTypes(U32);
+    psLogMsg(__func__,PS_LOG_INFO,"Image Copy Test for psS8");
+    testImageCopyTypes(S8);
+    psLogMsg(__func__,PS_LOG_INFO,"Image Copy Test for psS16");
+    testImageCopyTypes(S16);
+    psLogMsg(__func__,PS_LOG_INFO,"Image Copy Test for psS32");
+    testImageCopyTypes(S32);
+    psLogMsg(__func__,PS_LOG_INFO,"Image Copy Test for psF32");
+    testImageCopyTypes(F32);
+    psLogMsg(__func__,PS_LOG_INFO,"Image Copy Test for psF64");
+    testImageCopyTypes(F64);
+
+    // Verify the returned psImage structure pointer is null and program
+    // execution doesn't stop, if the input parameter input is null.
+    psLogMsg(__func__,PS_LOG_INFO,"An error should follow...");
+    img3 = psImageCopy(NULL,NULL,PS_TYPE_F32);
+    if (img3 != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psImageCopy didn't return NULL when input image was NULL.");
+        return 3;
+    }
+
+    psFree(img);
+    psFree(img2);
+    psFree(img3);
+    psFree(img4);
+
+    return 0;
+}
+
+static psS32 testImageTrim(void)
+{
+    psS32 r = 200;
+    psS32 c = 300;
+    psS32 qtrR = r/4;
+    psS32 qtrC = c/4;
+    psS32 halfR = r/2;
+    psS32 halfC = c/2;
+    psRegion centerHalf = {qtrC,qtrC+halfC,qtrR,qtrR+halfR};
+
+    psImage* image = psImageAlloc(c,r,PS_TYPE_F32);
+    for (psS32 row = 0; row < image->numRows; row++) {
+        for (psS32 col = 0; col < image->numCols; col++) {
+            image->data.F32[row][col] = (psF32)col + (psF32)row/1000.0f;
+        }
+    }
+
+    /*
+        1. invoke psImageTrim with non-NULL image, and a valid region
+           x0,y0->x1,y1 (using only positive values). Verify that:
+            a. the return psImage is the same as the input psImage.
+            b. the size of the psImage is x1-x0 by y1-y0.
+            c. the pixel values coorespond to the region [x0:x1-1,y0:y1-1].
+    */
+    psImage* image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+    psImage* image2 = psImageTrim(image1,centerHalf);
+
+    if (image1 != image2) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "Return value not same as input value.  Not done in-place?");
+        return 1;
+    }
+
+    if (image2->numCols != halfC ||
+            image2->numRows != halfR) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "The resulting image size was %dx%d, but should be %dx%d.",
+                 image2->numCols, image2->numRows,
+                 halfC, halfR);
+        return 2;
+    }
+
+    for (psS32 row = 0; row < image2->numRows; row++) {
+        for (psS32 col = 0; col < image2->numCols; col++) {
+            if (fabsf(image2->data.F32[row][col] - image->data.F32[row+qtrR][col+qtrC])
+                    > FLT_EPSILON) {
+                psLogMsg(__func__,PS_LOG_ERROR,
+                         "The value at (%d,%d) was %g, but should be %g.",
+                         col,row,
+                         image2->data.F32[row][col],
+                         image->data.F32[row+qtrR][col+qtrC]);
+                return 3;
+            }
+        }
+    }
+
+    /*
+        2. invoke psImageTrim with non-NULL image and valid region where x1=0,
+           y1=0. Verify that:
+            a. the return psImage size is numCols-x0 by numRows-y0
+            b. the pixel values coorespond to the region
+               [x0:numCols-1,y0:numRows-1].
+    */
+    image1 = psImageCopy(image1,image,PS_TYPE_F32);
+    image2 = psImageTrim(image1,psRegionSet(qtrC,0,qtrR,0));
+
+    if (image1 != image2) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "Return value not same as input value.  Not done in-place?");
+        return 11;
+    }
+
+    if (image2->numCols != image->numCols-qtrC ||
+            image2->numRows != image->numRows-qtrR) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "The resulting image size was %dx%d, but should be %dx%d.",
+                 image2->numCols, image2->numRows,
+                 image->numCols-qtrC, image->numRows-qtrR);
+        return 12;
+    }
+
+    for (psS32 row = 0; row < image2->numRows; row++) {
+        for (psS32 col = 0; col < image2->numCols; col++) {
+            if (fabsf(image2->data.F32[row][col] -
+                      image->data.F32[row+qtrR][col+qtrC]) > FLT_EPSILON) {
+                psLogMsg(__func__,PS_LOG_ERROR,
+                         "The value at (%d,%d) was %g, but should be %g.",
+                         col,row,
+                         image2->data.F32[row][col],
+                         image->data.F32[row+qtrR][col+qtrC]);
+                return 13;
+            }
+        }
+    }
+
+    /*
+        4. invoke psImageTrim with x1<0, y1<0. Verify:
+            a. the psImage size is (numCols+x1)-x0 by (numRows+y1)-y0.
+            b. the pixel values coorespond to the region
+               [x0:numCols+x1-1,y0:numRows+y1-1].
+
+    */
+    image1 = psImageCopy(image1,image,PS_TYPE_F32);
+    image2 = psImageTrim(image1,psRegionSet(qtrC,-qtrC, qtrR,-qtrR));
+
+    if (image1 != image2) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "Return value not same as input value.  Not done in-place?");
+        return 21;
+    }
+
+    if (image2->numCols != image->numCols-qtrC-qtrC ||
+            image2->numRows != image->numRows-qtrR-qtrR) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "The resulting image size was %dx%d, but should be %dx%d.",
+                 image2->numCols, image2->numRows,
+                 image->numCols-qtrC, image->numRows-qtrR);
+        return 22;
+    }
+
+    for (psS32 row = 0; row < image2->numRows; row++) {
+        for (psS32 col = 0; col < image2->numCols; col++) {
+            if (fabsf(image2->data.F32[row][col] -
+                      image->data.F32[row+qtrR][col+qtrC]) > FLT_EPSILON) {
+                psLogMsg(__func__,PS_LOG_ERROR,
+                         "The value at (%d,%d) was %g, but should be %g.",
+                         col,row,
+                         image2->data.F32[row][col],
+                         image->data.F32[row+qtrR][col+qtrC]);
+                return 23;
+            }
+        }
+    }
+
+    psFree(image2);
+
+    /*
+        6. invoke psImageTrim with image=NULL Verify:
+            a. execution does not cease.
+            b. return value is NULL
+            c. appropriate error is generated.
+    */
+
+    image2 = psImageTrim(NULL, psRegionSet(qtrC,0,qtrR,0));
+
+    if (image2 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageTrim did not return NULL given a NULL input image.");
+        return 31;
+    }
+    psErr* err = psErrorLast();
+    if (err == NULL || err->code != PS_ERR_BAD_PARAMETER_NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageTrim did not generate an appropriate error for NULL input image.");
+        psErrorStackPrint(stderr,"Error Stack:");
+        return 32;
+    }
+    psFree(err);
+
+    image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+    image2 = psImageTrim(image1, psRegionSet(-1,0,0,0));
+
+    if (image2 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageTrim did not return NULL given x0=-1.");
+        return 33;
+    }
+    err = psErrorLast();
+    if (err == NULL || err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageTrim did not generate an appropriate error for x0=-1.");
+        psErrorStackPrint(stderr,"Error Stack:");
+        return 34;
+    }
+    psFree(err);
+
+    image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+    image2 = psImageTrim(image1, psRegionSet(0,0,-1,0));
+
+    if (image2 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageTrim did not return NULL given y0=-1.");
+        return 35;
+    }
+    err = psErrorLast();
+    if (err == NULL || err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageTrim did not generate an appropriate error for y0=-1.");
+        psErrorStackPrint(stderr,"Error Stack:");
+        return 36;
+    }
+    psFree(err);
+
+    image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+    image2 = psImageTrim(image1, psRegionSet(0,image->numCols+1,0,0));
+
+    if (image2 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageTrim did not return NULL given x1=numCols+1.");
+        return 37;
+    }
+    err = psErrorLast();
+    if (err == NULL || err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageTrim did not generate an appropriate error for x1=numCols+1.");
+        psErrorStackPrint(stderr,"Error Stack:");
+        return 38;
+    }
+    psFree(err);
+
+    image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+    image2 = psImageTrim(image1, psRegionSet(0,0,0,image->numRows+1));
+
+    if (image2 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageTrim did not return NULL given y1=numRows+1.");
+        return 39;
+    }
+    err = psErrorLast();
+    if (err == NULL || err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageTrim did not generate an appropriate error for y1=numRows+1.");
+        psErrorStackPrint(stderr,"Error Stack:");
+        return 40;
+    }
+    psFree(err);
+
+    image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+    image2 = psImageTrim(image1, psRegionSet(0,(((psF32)image->numCols)*-1.0),0,0));
+
+    if (image2 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageTrim did not return NULL given x1=-numCols.");
+        return 41;
+    }
+    err = psErrorLast();
+    if (err == NULL || err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageTrim did not generate an appropriate error for x1=-numCols.");
+        psErrorStackPrint(stderr,"Error Stack:");
+        return 42;
+    }
+    psFree(err);
+
+    image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+    image2 = psImageTrim(image1, psRegionSet(0,0,0,(((psF32)image->numRows)*-1.0)));
+
+    if (image2 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageTrim did not return NULL given y1=-numRows.");
+        return 41;
+    }
+    err = psErrorLast();
+    if (err == NULL || err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageTrim did not generate an appropriate error for y1=-numRows.");
+        psErrorStackPrint(stderr,"Error Stack:");
+        return 42;
+    }
+    psFree(err);
+
+    psFree(image);
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/verified/fBiOut.fits
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/verified/fBiOut.fits	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/verified/fBiOut.fits	(revision 22158)
@@ -0,0 +1,6427 @@
+SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             B~
+B~záB~p€B~ffB~\)B~QìB~G®B~=qB~33B~(öB~
+žB~{B~
+=B~  B}õÃB}ë
+B}áHB}×
+B}ÌÍB}ÂB}žRB}®B}£×B}B}\B}
+B}záB}p€B}ffB}\)B}QìB}G®B}=qB}33B}(öB}
+žB}{B}
+=B}  B|õÃB|ë
+B|áHB|×
+B|ÌÍB|ÂB|žRB|®B|£×B|B|\B|
+B|záB|p€B|ffB|\)B|QìB|G®B|=qB|33B|(öB|
+žB|{B|
+=B|  Bz
+BzzáBzp€BzffBz\)BzQìBzG®Bz=qBz33Bz(öBz
+žBz{Bz
+=Bz  ByõÃByë
+ByáHBy×
+ByÌÍByÂByžRBy®By£×ByBy\By
+ByzáByp€ByffBy\)ByQìByG®By=qBy33By(öBy
+žBy{By
+=By  BxõÃBxë
+BxáHBx×
+BxÌÍBxÂBxžRBx®Bx£×BxBx\Bx
+BxzáBxp€BxffBx\)BxQìBxG®Bx=qBx33Bx(öBx
+žBx{Bx
+=Bx  Bv
+BvzáBvp€BvffBv\)BvQìBvG®Bv=qBv33Bv(öBv
+žBv{Bv
+=Bv  BuõÃBuë
+BuáHBu×
+BuÌÍBuÂBužRBu®Bu£×BuBu\Bu
+BuzáBup€BuffBu\)BuQìBuG®Bu=qBu33Bu(öBu
+žBu{Bu
+=Bu  BtõÃBtë
+BtáHBt×
+BtÌÍBtÂBtžRBt®Bt£×BtBt\Bt
+BtzáBtp€BtffBt\)BtQìBtG®Bt=qBt33Bt(öBt
+žBt{Bt
+=Bt  Br
+BrzáBrp€BrffBr\)BrQìBrG®Br=qBr33Br(öBr
+žBr{Br
+=Br  BqõÃBqë
+BqáHBq×
+BqÌÍBqÂBqžRBq®Bq£×BqBq\Bq
+BqzáBqp€BqffBq\)BqQìBqG®Bq=qBq33Bq(öBq
+žBq{Bq
+=Bq  BpõÃBpë
+BpáHBp×
+BpÌÍBpÂBpžRBp®Bp£×BpBp\Bp
+BpzáBpp€BpffBp\)BpQìBpG®Bp=qBp33Bp(öBp
+žBp{Bp
+=Bp  Bn
+BnzáBnp€BnffBn\)BnQìBnG®Bn=qBn33Bn(öBn
+žBn{Bn
+=Bn  BmõÃBmë
+BmáHBm×
+BmÌÍBmÂBmžRBm®Bm£×BmBm\Bm
+BmzáBmp€BmffBm\)BmQìBmG®Bm=qBm33Bm(öBm
+žBm{Bm
+=Bm  BlõÃBlë
+BláHBl×
+BlÌÍBlÂBlžRBl®Bl£×BlBl\Bl
+BlzáBlp€BlffBl\)BlQìBlG®Bl=qBl33Bl(öBl
+žBl{Bl
+=Bl  Bj
+BjzáBjp€BjffBj\)BjQìBjG®Bj=qBj33Bj(öBj
+žBj{Bj
+=Bj  BiõÃBië
+BiáHBi×
+BiÌÍBiÂBižRBi®Bi£×BiBi\Bi
+BizáBip€BiffBi\)BiQìBiG®Bi=qBi33Bi(öBi
+žBi{Bi
+=Bi  BhõÃBhë
+BháHBh×
+BhÌÍBhÂBhžRBh®Bh£×BhBh\Bh
+BhzáBhp€BhffBh\)BhQìBhG®Bh=qBh33Bh(öBh
+žBh{Bh
+=Bh  Bf
+BfzáBfp€BfffBf\)BfQìBfG®Bf=qBf33Bf(öBf
+žBf{Bf
+=Bf  BeõÃBeë
+BeáHBe×
+BeÌÍBeÂBežRBe®Be£×BeBe\Be
+BezáBep€BeffBe\)BeQìBeG®Be=qBe33Be(öBe
+žBe{Be
+=Be  BdõÃBdë
+BdáHBd×
+BdÌÍBdÂBdžRBd®Bd£×BdBd\Bd
+BdzáBdp€BdffBd\)BdQìBdG®Bd=qBd33Bd(öBd
+žBd{Bd
+=Bd  Bb
+BbzáBbp€BbffBb\)BbQìBbG®Bb=qBb33Bb(öBb
+žBb{Bb
+=Bb  BaõÃBaë
+BaáHBa×
+BaÌÍBaÂBažRBa®Ba£×BaBa\Ba
+BazáBap€BaffBa\)BaQìBaG®Ba=qBa33Ba(öBa
+žBa{Ba
+=Ba  B`õÃB`ë
+B`áHB`×
+B`ÌÍB`ÂB`žRB`®B`£×B`B`\B`
+B`záB`p€B`ffB`\)B`QìB`G®B`=qB`33B`(öB`
+žB`{B`
+=B`  B^
+B^záB^p€B^ffB^\)B^QìB^G®B^=qB^33B^(öB^
+žB^{B^
+=B^  B]õÃB]ë
+B]áHB]×
+B]ÌÍB]ÂB]žRB]®B]£×B]B]\B]
+B]záB]p€B]ffB]\)B]QìB]G®B]=qB]33B](öB]
+žB]{B]
+=B]  B\õÃB\ë
+B\áHB\×
+B\ÌÍB\ÂB\žRB\®B\£×B\B\\B\
+B\záB\p€B\ffB\\)B\QìB\G®B\=qB\33B\(öB\
+žB\{B\
+=B\  BZ
+BZzáBZp€BZffBZ\)BZQìBZG®BZ=qBZ33BZ(öBZ
+žBZ{BZ
+=BZ  BYõÃBYë
+BYáHBY×
+BYÌÍBYÂBYžRBY®BY£×BYBY\BY
+BYzáBYp€BYffBY\)BYQìBYG®BY=qBY33BY(öBY
+žBY{BY
+=BY  BXõÃBXë
+BXáHBX×
+BXÌÍBXÂBXžRBX®BX£×BXBX\BX
+BXzáBXp€BXffBX\)BXQìBXG®BX=qBX33BX(öBX
+žBX{BX
+=BX  BV
+BVzáBVp€BVffBV\)BVQìBVG®BV=qBV33BV(öBV
+žBV{BV
+=BV  BUõÃBUë
+BUáHBU×
+BUÌÍBUÂBUžRBU®BU£×BUBU\BU
+BUzáBUp€BUffBU\)BUQìBUG®BU=qBU33BU(öBU
+žBU{BU
+=BU  BTõÃBTë
+BTáHBT×
+BTÌÍBTÂBTžRBT®BT£×BTBT\BT
+BTzáBTp€BTffBT\)BTQìBTG®BT=qBT33BT(öBT
+žBT{BT
+=BT  BR
+BRzáBRp€BRffBR\)BRQìBRG®BR=qBR33BR(öBR
+žBR{BR
+=BR  BQõÃBQë
+BQáHBQ×
+BQÌÍBQÂBQžRBQ®BQ£×BQBQ\BQ
+BQzáBQp€BQffBQ\)BQQìBQG®BQ=qBQ33BQ(öBQ
+žBQ{BQ
+=BQ  BPõÃBPë
+BPáHBP×
+BPÌÍBPÂBPžRBP®BP£×BPBP\BP
+BPzáBPp€BPffBP\)BPQìBPG®BP=qBP33BP(öBP
+žBP{BP
+=BP  BN
+BNzáBNp€BNffBN\)BNQìBNG®BN=qBN33BN(öBN
+žBN{BN
+=BN  BMõÃBMë
+BMáHBM×
+BMÌÍBMÂBMžRBM®BM£×BMBM\BM
+BMzáBMp€BMffBM\)BMQìBMG®BM=qBM33BM(öBM
+žBM{BM
+=BM  BLõÃBLë
+BLáHBL×
+BLÌÍBLÂBLžRBL®BL£×BLBL\BL
+BLzáBLp€BLffBL\)BLQìBLG®BL=qBL33BL(öBL
+žBL{BL
+=BL  BJ
+BJzáBJp€BJffBJ\)BJQìBJG®BJ=qBJ33BJ(öBJ
+žBJ{BJ
+=BJ  BIõÃBIë
+BIáHBI×
+BIÌÍBIÂBIžRBI®BI£×BIBI\BI
+BIzáBIp€BIffBI\)BIQìBIG®BI=qBI33BI(öBI
+žBI{BI
+=BI  BHõÃBHë
+BHáHBH×
+BHÌÍBHÂBHžRBH®BH£×BHBH\BH
+BHzáBHp€BHffBH\)BHQìBHG®BH=qBH33BH(öBH
+žBH{BH
+=BH  BF
+BFzáBFp€BFffBF\)BFQìBFG®BF=qBF33BF(öBF
+žBF{BF
+=BF  BEõÃBEë
+BEáHBE×
+BEÌÍBEÂBEžRBE®BE£×BEBE\BE
+BEzáBEp€BEffBE\)BEQìBEG®BE=qBE33BE(öBE
+žBE{BE
+=BE  BDõÃBDë
+BDáHBD×
+BDÌÍBDÂBDžRBD®BD£×BDBD\BD
+BDzáBDp€BDffBD\)BDQìBDG®BD=qBD33BD(öBD
+žBD{BD
+=BD  BB
+BBzáBBp€BBffBB\)BBQìBBG®BB=qBB33BB(öBB
+žBB{BB
+=BB  BAõÃBAë
+BAáHBA×
+BAÌÍBAÂBAžRBA®BA£×BABA\BA
+BAzáBAp€BAffBA\)BAQìBAG®BA=qBA33BA(öBA
+žBA{BA
+=BA  B@õÃB@ë
+B@áHB@×
+B@ÌÍB@ÂB@žRB@®B@£×B@B@\B@
+B@záB@p€B@ffB@\)B@QìB@G®B@=qB@33B@(öB@
+žB@{B@
+=B@  B>
+B>záB>p€B>ffB>\)B>QìB>G®B>=qB>33B>(öB>
+žB>{B>
+=B>  B=õÃB=ë
+B=áHB=×
+B=ÌÍB=ÂB=žRB=®B=£×B=B=\B=
+B=záB=p€B=ffB=\)B=QìB=G®B==qB=33B=(öB=
+žB={B=
+=B=  B<õÃB<ë
+B<áHB<×
+B<ÌÍB<ÂB<žRB<®B<£×B<B<\B<
+B<záB<p€B<ffB<\)B<QìB<G®B<=qB<33B<(öB<
+žB<{B<
+=B<  B:
+B:záB:p€B:ffB:\)B:QìB:G®B:=qB:33B:(öB:
+žB:{B:
+=B:  B9õÃB9ë
+B9áHB9×
+B9ÌÍB9ÂB9žRB9®B9£×B9B9\B9
+B9záB9p€B9ffB9\)B9QìB9G®B9=qB933B9(öB9
+žB9{B9
+=B9  B8õÃB8ë
+B8áHB8×
+B8ÌÍB8ÂB8žRB8®B8£×B8B8\B8
+B8záB8p€B8ffB8\)B8QìB8G®B8=qB833B8(öB8
+žB8{B8
+=B8  B6
+B6záB6p€B6ffB6\)B6QìB6G®B6=qB633B6(öB6
+žB6{B6
+=B6  B5õÃB5ë
+B5áHB5×
+B5ÌÍB5ÂB5žRB5®B5£×B5B5\B5
+B5záB5p€B5ffB5\)B5QìB5G®B5=qB533B5(öB5
+žB5{B5
+=B5  B4õÃB4ë
+B4áHB4×
+B4ÌÍB4ÂB4žRB4®B4£×B4B4\B4
+B4záB4p€B4ffB4\)B4QìB4G®B4=qB433B4(öB4
+žB4{B4
+=B4  B2
+B2záB2p€B2ffB2\)B2QìB2G®B2=qB233B2(öB2
+žB2{B2
+=B2  B1õÃB1ë
+B1áHB1×
+B1ÌÍB1ÂB1žRB1®B1£×B1B1\B1
+B1záB1p€B1ffB1\)B1QìB1G®B1=qB133B1(öB1
+žB1{B1
+=B1  B0õÃB0ë
+B0áHB0×
+B0ÌÍB0ÂB0žRB0®B0£×B0B0\B0
+B0záB0p€B0ffB0\)B0QìB0G®B0=qB033B0(öB0
+žB0{B0
+=B0  B.
+B.záB.p€B.ffB.\)B.QìB.G®B.=qB.33B.(öB.
+žB.{B.
+=B.  B-õÃB-ë
+B-áHB-×
+B-ÌÍB-ÂB-žRB-®B-£×B-B-\B-
+B-záB-p€B-ffB-\)B-QìB-G®B-=qB-33B-(öB-
+žB-{B-
+=B-  B,õÃB,ë
+B,áHB,×
+B,ÌÍB,ÂB,žRB,®B,£×B,B,\B,
+B,záB,p€B,ffB,\)B,QìB,G®B,=qB,33B,(öB,
+žB,{B,
+=B,  B*
+B*záB*p€B*ffB*\)B*QìB*G®B*=qB*33B*(öB*
+žB*{B*
+=B*  B)õÃB)ë
+B)áHB)×
+B)ÌÍB)ÂB)žRB)®B)£×B)B)\B)
+B)záB)p€B)ffB)\)B)QìB)G®B)=qB)33B)(öB)
+žB){B)
+=B)  B(õÃB(ë
+B(áHB(×
+B(ÌÍB(ÂB(žRB(®B(£×B(B(\B(
+B(záB(p€B(ffB(\)B(QìB(G®B(=qB(33B((öB(
+žB({B(
+=B(  B&
+B&záB&p€B&ffB&\)B&QìB&G®B&=qB&33B&(öB&
+žB&{B&
+=B&  B%õÃB%ë
+B%áHB%×
+B%ÌÍB%ÂB%žRB%®B%£×B%B%\B%
+B%záB%p€B%ffB%\)B%QìB%G®B%=qB%33B%(öB%
+žB%{B%
+=B%  B$õÃB$ë
+B$áHB$×
+B$ÌÍB$ÂB$žRB$®B$£×B$B$\B$
+B$záB$p€B$ffB$\)B$QìB$G®B$=qB$33B$(öB$
+žB${B$
+=B$  B"
+B"záB"p€B"ffB"\)B"QìB"G®B"=qB"33B"(öB"
+žB"{B"
+=B"  B!õÃB!ë
+B!áHB!×
+B!ÌÍB!ÂB!žRB!®B!£×B!B!\B!
+B!záB!p€B!ffB!\)B!QìB!G®B!=qB!33B!(öB!
+žB!{B!
+=B!  B õÃB ë
+B áHB ×
+B ÌÍB ÂB žRB ®B £×B B \B 
+B záB p€B ffB \)B QìB G®B =qB 33B (öB 
+žB {B 
+=B   B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B	õÃB	ë
+B	áHB	×
+B	ÌÍB	ÂB	žRB	®B	£×B	B	\B	
+B	záB	p€B	ffB	\)B	QìB	G®B	=qB	33B	(öB	
+žB	{B	
+=B	  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B õÃB ë
+B áHB ×
+B ÌÍB ÂB žRB ®B £×B B \B 
+B záB p€B ffB \)B QìB G®B =qB 33B (öB 
+žB {B 
+=B   Aý
+=AüõÃAüáHAüÌÍAüžRAü£×Aü\AüzáAüffAüQìAü=qAü(öAü{Aü  Aûë
+Aû×
+AûÂAû®AûAû
+Aûp€Aû\)AûG®Aû33Aû
+žAû
+=AúõÃAúáHAúÌÍAúžRAú£×Aú\AúzáAúffAúQìAú=qAú(öAú{Aú  Aùë
+Aù×
+AùÂAù®AùAù
+Aùp€Aù\)AùG®Aù33Aù
+žAù
+=AøõÃAøáHAøÌÍAøžRAø£×Aø\AøzáAøffAøQìAø=qAø(öAø{Aø  Aõ
+=AôõÃAôáHAôÌÍAôžRAô£×Aô\AôzáAôffAôQìAô=qAô(öAô{Aô  Aóë
+Aó×
+AóÂAó®AóAó
+Aóp€Aó\)AóG®Aó33Aó
+žAó
+=AòõÃAòáHAòÌÍAòžRAò£×Aò\AòzáAòffAòQìAò=qAò(öAò{Aò  Añë
+Añ×
+AñÂAñ®AñAñ
+Añp€Añ\)AñG®Añ33Añ
+žAñ
+=AðõÃAðáHAðÌÍAðžRAð£×Að\AðzáAðffAðQìAð=qAð(öAð{Að  Aí
+=AìõÃAìáHAìÌÍAìžRAì£×Aì\AìzáAìffAìQìAì=qAì(öAì{Aì  Aëë
+Aë×
+AëÂAë®AëAë
+Aëp€Aë\)AëG®Aë33Aë
+žAë
+=AêõÃAêáHAêÌÍAêžRAê£×Aê\AêzáAêffAêQìAê=qAê(öAê{Aê  Aéë
+Aé×
+AéÂAé®AéAé
+Aép€Aé\)AéG®Aé33Aé
+žAé
+=AèõÃAèáHAèÌÍAèžRAè£×Aè\AèzáAèffAèQìAè=qAè(öAè{Aè  Aå
+=AäõÃAäáHAäÌÍAäžRAä£×Aä\AäzáAäffAäQìAä=qAä(öAä{Aä  Aãë
+Aã×
+AãÂAã®AãAã
+Aãp€Aã\)AãG®Aã33Aã
+žAã
+=AâõÃAâáHAâÌÍAâžRAâ£×Aâ\AâzáAâffAâQìAâ=qAâ(öAâ{Aâ  Aáë
+Aá×
+AáÂAá®AáAá
+Aáp€Aá\)AáG®Aá33Aá
+žAá
+=AàõÃAàáHAàÌÍAàžRAà£×Aà\AàzáAàffAàQìAà=qAà(öAà{Aà  AÝ
+=AÜõÃAÜáHAÜÌÍAÜžRAÜ£×AÜ\AÜzáAÜffAÜQìAÜ=qAÜ(öAÜ{AÜ  AÛë
+AÛ×
+AÛÂAÛ®AÛAÛ
+AÛp€AÛ\)AÛG®AÛ33AÛ
+žAÛ
+=AÚõÃAÚáHAÚÌÍAÚžRAÚ£×AÚ\AÚzáAÚffAÚQìAÚ=qAÚ(öAÚ{AÚ  AÙë
+AÙ×
+AÙÂAÙ®AÙAÙ
+AÙp€AÙ\)AÙG®AÙ33AÙ
+žAÙ
+=AØõÃAØáHAØÌÍAØžRAØ£×AØ\AØzáAØffAØQìAØ=qAØ(öAØ{AØ  AÕ
+=AÔõÃAÔáHAÔÌÍAÔžRAÔ£×AÔ\AÔzáAÔffAÔQìAÔ=qAÔ(öAÔ{AÔ  AÓë
+AÓ×
+AÓÂAÓ®AÓAÓ
+AÓp€AÓ\)AÓG®AÓ33AÓ
+žAÓ
+=AÒõÃAÒáHAÒÌÍAÒžRAÒ£×AÒ\AÒzáAÒffAÒQìAÒ=qAÒ(öAÒ{AÒ  AÑë
+AÑ×
+AÑÂAÑ®AÑAÑ
+AÑp€AÑ\)AÑG®AÑ33AÑ
+žAÑ
+=AÐõÃAÐáHAÐÌÍAÐžRAÐ£×AÐ\AÐzáAÐffAÐQìAÐ=qAÐ(öAÐ{AÐ  AÍ
+=AÌõÃAÌáHAÌÌÍAÌžRAÌ£×AÌ\AÌzáAÌffAÌQìAÌ=qAÌ(öAÌ{AÌ  AËë
+AË×
+AËÂAË®AËAË
+AËp€AË\)AËG®AË33AË
+žAË
+=AÊõÃAÊáHAÊÌÍAÊžRAÊ£×AÊ\AÊzáAÊffAÊQìAÊ=qAÊ(öAÊ{AÊ  AÉë
+AÉ×
+AÉÂAÉ®AÉAÉ
+AÉp€AÉ\)AÉG®AÉ33AÉ
+žAÉ
+=AÈõÃAÈáHAÈÌÍAÈžRAÈ£×AÈ\AÈzáAÈffAÈQìAÈ=qAÈ(öAÈ{AÈ  AÅ
+=AÄõÃAÄáHAÄÌÍAÄžRAÄ£×AÄ\AÄzáAÄffAÄQìAÄ=qAÄ(öAÄ{AÄ  AÃë
+AÃ×
+AÃÂAÃ®AÃAÃ
+AÃp€AÃ\)AÃG®AÃ33AÃ
+žAÃ
+=AÂõÃAÂáHAÂÌÍAÂžRAÂ£×AÂ\AÂzáAÂffAÂQìAÂ=qAÂ(öAÂ{AÂ  AÁë
+AÁ×
+AÁÂAÁ®AÁAÁ
+AÁp€AÁ\)AÁG®AÁ33AÁ
+žAÁ
+=AÀõÃAÀáHAÀÌÍAÀžRAÀ£×AÀ\AÀzáAÀffAÀQìAÀ=qAÀ(öAÀ{AÀ  Aœ
+=AŒõÃAŒáHAŒÌÍAŒžRAŒ£×AŒ\AŒzáAŒffAŒQìAŒ=qAŒ(öAŒ{AŒ  A»ë
+A»×
+A»ÂA»®A»A»
+A»p€A»\)A»G®A»33A»
+žA»
+=AºõÃAºáHAºÌÍAºžRAº£×Aº\AºzáAºffAºQìAº=qAº(öAº{Aº  A¹ë
+A¹×
+A¹ÂA¹®A¹A¹
+A¹p€A¹\)A¹G®A¹33A¹
+žA¹
+=AžõÃAžáHAžÌÍAžžRAž£×Až\AžzáAžffAžQìAž=qAž(öAž{Až  Aµ
+=AŽõÃAŽáHAŽÌÍAŽžRAŽ£×AŽ\AŽzáAŽffAŽQìAŽ=qAŽ(öAŽ{AŽ  A³ë
+A³×
+A³ÂA³®A³A³
+A³p€A³\)A³G®A³33A³
+žA³
+=A²õÃA²áHA²ÌÍA²žRA²£×A²\A²záA²ffA²QìA²=qA²(öA²{A²  A±ë
+A±×
+A±ÂA±®A±A±
+A±p€A±\)A±G®A±33A±
+žA±
+=A°õÃA°áHA°ÌÍA°žRA°£×A°\A°záA°ffA°QìA°=qA°(öA°{A°  A­
+=A¬õÃA¬áHA¬ÌÍA¬žRA¬£×A¬\A¬záA¬ffA¬QìA¬=qA¬(öA¬{A¬  A«ë
+A«×
+A«ÂA«®A«A«
+A«p€A«\)A«G®A«33A«
+žA«
+=AªõÃAªáHAªÌÍAªžRAª£×Aª\AªzáAªffAªQìAª=qAª(öAª{Aª  A©ë
+A©×
+A©ÂA©®A©A©
+A©p€A©\)A©G®A©33A©
+žA©
+=AšõÃAšáHAšÌÍAšžRAš£×Aš\AšzáAšffAšQìAš=qAš(öAš{Aš  A¥
+=A€õÃA€áHA€ÌÍA€žRA€£×A€\A€záA€ffA€QìA€=qA€(öA€{A€  A£ë
+A£×
+A£ÂA£®A£A£
+A£p€A£\)A£G®A£33A£
+žA£
+=A¢õÃA¢áHA¢ÌÍA¢žRA¢£×A¢\A¢záA¢ffA¢QìA¢=qA¢(öA¢{A¢  A¡ë
+A¡×
+A¡ÂA¡®A¡A¡
+A¡p€A¡\)A¡G®A¡33A¡
+žA¡
+=A õÃA áHA ÌÍA žRA £×A \A záA ffA QìA =qA (öA {A   A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Az{Ayë
+AyÂAyAyp€AyG®Ay
+žAxõÃAxÌÍAx£×AxzáAxQìAx(öAx  Aw×
+Aw®Aw
+Aw\)Aw33Aw
+=AváHAvžRAv\AvffAv=qAv{Auë
+AuÂAuAup€AuG®Au
+žAtõÃAtÌÍAt£×AtzáAtQìAt(öAt  As×
+As®As
+As\)As33As
+=AráHAržRAr\ArffAr=qAr{Aqë
+AqÂAqAqp€AqG®Aq
+žApõÃApÌÍAp£×ApzáApQìAp(öAp  Aj{Aië
+AiÂAiAip€AiG®Ai
+žAhõÃAhÌÍAh£×AhzáAhQìAh(öAh  Ag×
+Ag®Ag
+Ag\)Ag33Ag
+=AfáHAfžRAf\AfffAf=qAf{Aeë
+AeÂAeAep€AeG®Ae
+žAdõÃAdÌÍAd£×AdzáAdQìAd(öAd  Ac×
+Ac®Ac
+Ac\)Ac33Ac
+=AbáHAbžRAb\AbffAb=qAb{Aaë
+AaÂAaAap€AaG®Aa
+žA`õÃA`ÌÍA`£×A`záA`QìA`(öA`  AZ{AYë
+AYÂAYAYp€AYG®AY
+žAXõÃAXÌÍAX£×AXzáAXQìAX(öAX  AW×
+AW®AW
+AW\)AW33AW
+=AVáHAVžRAV\AVffAV=qAV{AUë
+AUÂAUAUp€AUG®AU
+žATõÃATÌÍAT£×ATzáATQìAT(öAT  AS×
+AS®AS
+AS\)AS33AS
+=ARáHARžRAR\ARffAR=qAR{AQë
+AQÂAQAQp€AQG®AQ
+žAPõÃAPÌÍAP£×APzáAPQìAP(öAP  AJ{AIë
+AIÂAIAIp€AIG®AI
+žAHõÃAHÌÍAH£×AHzáAHQìAH(öAH  AG×
+AG®AG
+AG\)AG33AG
+=AFáHAFžRAF\AFffAF=qAF{AEë
+AEÂAEAEp€AEG®AE
+žADõÃADÌÍAD£×ADzáADQìAD(öAD  AC×
+AC®AC
+AC\)AC33AC
+=ABáHABžRAB\ABffAB=qAB{AAë
+AAÂAAAAp€AAG®AA
+žA@õÃA@ÌÍA@£×A@záA@QìA@(öA@  A:{A9ë
+A9ÂA9A9p€A9G®A9
+žA8õÃA8ÌÍA8£×A8záA8QìA8(öA8  A7×
+A7®A7
+A7\)A733A7
+=A6áHA6žRA6\A6ffA6=qA6{A5ë
+A5ÂA5A5p€A5G®A5
+žA4õÃA4ÌÍA4£×A4záA4QìA4(öA4  A3×
+A3®A3
+A3\)A333A3
+=A2áHA2žRA2\A2ffA2=qA2{A1ë
+A1ÂA1A1p€A1G®A1
+žA0õÃA0ÌÍA0£×A0záA0QìA0(öA0  A*{A)ë
+A)ÂA)A)p€A)G®A)
+žA(õÃA(ÌÍA(£×A(záA(QìA((öA(  A'×
+A'®A'
+A'\)A'33A'
+=A&áHA&žRA&\A&ffA&=qA&{A%ë
+A%ÂA%A%p€A%G®A%
+žA$õÃA$ÌÍA$£×A$záA$QìA$(öA$  A#×
+A#®A#
+A#\)A#33A#
+=A"áHA"žRA"\A"ffA"=qA"{A!ë
+A!ÂA!A!p€A!G®A!
+žA õÃA ÌÍA £×A záA QìA (öA   A{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A
+{A	ë
+A	ÂA	A	p€A	G®A	
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žA õÃA ÌÍA £×A záA QìA (öA   @ô(ö@ó×
+@ó
+@ó33@òáH@ò\@ò=q@ñë
+@ñ@ñG®@ðõÂ@ð£×@ðQì@ð  @ï®@ï\)@ï
+=@îžR@îff@î{@íÂ@íp€@í
+ž@ìÌÍ@ìzá@ì(ö@ë×
+@ë
+@ë33@êáH@ê\@ê=q@éë
+@é@éG®@èõÃ@è£×@èQì@è  @ç®@ç\)@ç
+=@æžR@æff@æ{@åÂ@åp€@å
+ž@äÌÍ@äzá@ä(ö@ã×
+@ã
+@ã33@âáH@â\@â=q@áë
+@á@áG®@àõÃ@à£×@àQì@à  @Ô(ö@Ó×
+@Ó
+@Ó33@ÒáH@Ò\@Ò=q@Ñë
+@Ñ@ÑG®@ÐõÂ@Ð£×@ÐQì@Ð  @Ï®@Ï\)@Ï
+=@ÎžR@Îff@Î{@ÍÂ@Íp€@Í
+ž@ÌÌÍ@Ìzá@Ì(ö@Ë×
+@Ë
+@Ë33@ÊáH@Ê\@Ê=q@Éë
+@É@ÉG®@ÈõÃ@È£×@ÈQì@È  @Ç®@Ç\)@Ç
+=@ÆžR@Æff@Æ{@ÅÂ@Åp€@Å
+ž@ÄÌÍ@Äzá@Ä(ö@Ã×
+@Ã
+@Ã33@ÂáH@Â\@Â=q@Áë
+@Á@ÁG®@ÀõÃ@À£×@ÀQì@À  @Ž(ö@³×
+@³
+@³33@²áH@²\@²=q@±ë
+@±@±G®@°õÂ@°£×@°Qì@°  @¯®@¯\)@¯
+=@®žR@®ff@®{@­Â@­p€@­
+ž@¬ÌÍ@¬zá@¬(ö@«×
+@«
+@«33@ªáH@ª\@ª=q@©ë
+@©@©G®@šõÃ@š£×@šQì@š  @§®@§\)@§
+=@ŠžR@Šff@Š{@¥Â@¥p€@¥
+ž@€ÌÍ@€zá@€(ö@£×
+@£
+@£33@¢áH@¢\@¢=q@¡ë
+@¡@¡G®@ õÃ@ £×@ Qì@   @(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÂ@£×@Qì@  @®@\)@
+=@žR@ff@{@Â@p€@
+ž@ÌÍ@zá@(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÃ@£×@Qì@  @®@\)@
+=@žR@ff@{@
+Â@
+p€@
+
+ž@ÌÍ@zá@(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÃ@£×@Qì@  @hQì@g®@g
+>@fff@eÂ@e
+ž@dzá@c×
+@c33@b\@aë
+@aG®@`£×@`  @_\)@^žR@^{@]p€@\ÌÍ@\(ö@[
+@ZáH@Z=q@Y@XõÂ@XQì@W®@W
+>@Vff@UÂ@U
+ž@Tzá@S×
+@S33@R\@Që
+@QG®@P£×@P  @O\)@NžR@N{@Mp€@LÌÍ@L(ö@K
+@JáH@J=q@I@HõÃ@HQì@G®@G
+=@Fff@EÂ@E
+ž@Dzá@C×
+@C33@B\@Aë
+@AG®@@£×@@  @(Qì@'®@'
+>@&ff@%Â@%
+ž@$zá@#×
+@#33@"\@!ë
+@!G®@ £×@   @\)@
+žR@
+{@
+p€@
+ÌÍ@
+(ö@
+@áH@=q@@õÂ@Qì@®@
+>@ff@Â@
+ž@zá@×
+@33@\@ë
+@G®@£×@  @\)@žR@{@
+p€@
+ÌÍ@
+(ö@
+
+@
+áH@
+=q@	@õÃ@Qì@®@
+=@ff@Â@
+ž@zá@×
+@33@\@ë
+@G®@ £×@   ?Ð£×?Ï\)?Î{?ÌÌÍ?Ë
+
+?Ê=p?ÈõÂ?Ç®?Æff?Å
+ž?Ã×
+?Â\?ÁG®?À  ?ŸžR?œp€?Œ(ö?ºáH?¹?žQì?·
+>?µÂ?Žzá?³33?±ë
+?°£×?¯\)?®{?¬ÌÍ?«
+?ª=q?šõÂ?§®?Šff?¥
+ž?£×
+?¢\?¡G®?   ?žR?p€?(ö?áH??Qì?
+>?Â?zá?33?ë
+?£×?\)?{?ÌÍ?
+?=q?õÃ?®?ff?
+
+ž?×
+?\?G®?  ?!G®?
+žR?
+(ö??
+=?zá?ë
+?\)?
+ÌÍ?
+=q?®?
+ž?\?   >úáH>õÂ>ð£×>ë
+>æff>áG®>Ü(ö>×
+=>Ñë
+>ÌÌÍ>Ç®>Â\>œp€>žQì>³33>®{>šõÃ>£×
+>žR>>zá>\)>=q>
+
+ž>  >uÂ>k
+>aG®>W
+=>LÌÍ>B\>8Qì>.{>#×
+>>\)>
+ž=õÂ=áG®=ÌÌÍ=žQì=£×
+=\)=uÂ=LÌÍ=#×
+<õÂ<£×
+<#×
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~bB~Æ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BxºrB{-B~[B~vK¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BsKBuæBx²ÜB{³B~LB~gÏ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bmj#Bp=ÞBs
+ŽBu×Bx€aB{q7B~>B~YT¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BgÁûBj¶BmbBp/cBrü9BuÉBxæB{bœB~/B~JÙ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BbÓBdíBgºdBj;BmTBp çBríŸBuºBxkB{TAB~!B~<^¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B\q«B_EfBb<BdßBg«éBjx¿BmEBpmBrßCBu¬BxxðB{EÆB~B~-ã¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BVÉBY?B\jB_6ìBbÂBdÐBgoBjjFBm7
+BpòBrÐÉBuBxjuB{7LB~"B~g¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BQ!\BSõBVÁíBYÄB\[B_(pBaõGBdÂ
+BgôBj[ÊBm(¡BoõwBrÂMBu$Bx[úB{(ÐB}õ§B~ì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BKy4BNLïBQÅBSæBV³rBYHB\MB_öBaæÌBd³¢BgyBjMOBm%BoæüBr³ÒBušBxMB{UB}ç+B~q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BEÑ
+BH€ÇBKqBN>tBQ
+JBSØ BV€÷BYqÎB\>€B_
+zBaØQBd¥'BgqýBj>ÔBm
+ªBoØBr¥WBur-Bx?B{
+ÚB}Ø°B}óö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B@(äBBüBEÉuBHLBKc"BN/øBPüÏBSÉŠBV|BYcRB\0)B^üÿBaÉÕBd¬BgcBj0XBlý/BoÊBrÛBuc²Bx0Bzý_B}Ê5B}åz¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B:œB=TxB@!NBBî%BEºûBHÑBKTšBN!BPîUBS»+BVBYTØB\!®B^î
+Ba»[Bd1BgUBj!ÞBlîŽBo»BraBuU8Bx"BzîäB}»»B}Öÿ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B4ØB7¬PB:y&B=EýB@ÓBBß©BE¬BHyWBKF-BNBPßÚBS¬°BVyBYF]B\3B^à	Ba¬àBdy¶BgFBjcBlà9Bo­BryæBuFŒBxBzàiB}­?B}È¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B/0mB2(B4ÐþB7ÕB:j«B=7B@XBBÑ/BEBHjÛBK7²BNBPÑ^BS5BVk
+BY7áB\žB^ÑBadBdk;Bg8BjèBlÑŸBoBrkkBu8ABxBzÑîB}ÄB}º¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B)EB,\ B/(ÖB1õ­B4ÂB7YB:\0B=)B?õÝBBÂ³BEBH\`BK)6BMö
+BPÂãBS¹BV\BY)fB[ö<B^ÃBaéBd\ÀBg)BiölBlÃCBoBr\ïBu)ÆBwöBzÃrB}HB}«¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B#à
+B&³ØB)®B,M
+B/[B1ç1B4ŽB7ßB:MµB=B?çbBBŽ8BEBHMåBK»BMçBPŽhBS>BVNBYëB[çÁB^ŽBanBdNDBgBiçñBlŽÇBoBrNtBuJBwè BzŽ÷B}ÍB}¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+7õB!
+°B#ØB&¥]B)r3B,?	B/
+àB1Ø·B4¥B7rcB:?:B=
+B?ØæBB¥œBErBH?iBK
+@BMÙBP¥ìBSrÃBV?BY
+pB[ÙFB^Š
+BaróBd?ÉBg
+BiÙvBlŠLBos"Br?øBu
+ÏBwÙ¥BzŠ|B}sRB}¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BÎBcB
+0_B ý6B#Ê
+B&âB)c¹B,0B.ýfB1Ê<B4B7céB:0¿B<ýB?ÊlBBBBEdBH0ïBJýÅBMÊBPrBSdIBV1BXýõB[ÊÌB^¢BadxBd1OBfþ%BiÊûBlÑBodšBr1~BtþUBwË+BzB}dØB}¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BçŠB»aB7BUB
+!äB îºB#»B&hB)U>B,"B.îëB1»ÁB4B7UnB:"DB<ïB?»ñBBÇBEUBH"tBJïJBMŒ!BP÷BSUÍBV"€BXïzB[ŒPB^'BaUýBd"ÓBfï©BiŒBlVBoV-Br#BtïÙBwŒ°BzB}V\B}q ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+?~B9BàB¬æByŒBFB
+iB à@B#­B&yìB)FÃB,B.àoB1­FB4z
+B7FòB:ÉB<àB?­uBBzLBEG"BHùBJàÏBM­¥BPz|BSGRBV(BXàÿB[­ÕB^z«BaGBdXBfá.Bi®BlzÛBoG±BrBtá^Bw®4Bz{
+B}GáB}c$¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BVB
+kB
+7çBŸBÑBjBkAB8B
+îB ÑÄB#B&kqB)8GB,
+B.ÑôB1ÊB4k¡B78wB:MB<Ò$B?úBBkÑBE8§BH}BJÒTBM*BPl BS8×BV­BXÒB[YB^l0Ba9BdÝBfÒ³BiBll`Bo96Br
+BtÒãBw¹BzlB}9fB}Tª¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bï.BÂéB¿B
+\B
+)lBöBBÃBðB\ÆB)B
+ösB ÃIB#B&\öB))ÌB+ö¢B.ÃyB1OB4]%B7)üB9öÒB<Ã©B?BB]UBE*,BG÷BJÃØBM¯BP]
+BS*[BU÷1BXÄB[ÞB^]µBa*Bc÷aBfÄ8BiBl]äBo*»Bq÷BtÄgBw>Bz^B}*ëB}F.¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aø
+Aþ5BçBŽnBDB
+NB
+ñBçÈBŽBtBNKB!B
+ç÷B ŽÎB#€B&NzB)QB+è'B.ŽýB1ÔB4NªB7B9èWB<µ-B?BBNÚBE°BGèBJµ]BM3BPO	BSàBUè¶BXµB[cB^O9Ba
+BcèæBfµŒBiBlOiBo
+?BqéBtµíBwÃBzOB}
+pB}7³¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aí=ŒAòå3Aø~àAþBÙ
+B¥òBrÉB
+? B
+
+vBÙLBŠ#BrùB?ÏB
+ŠB
+Ù|B ŠRB#s)B&?ÿB)
+ÕB+Ù¬B.ŠB1sYB4@/B7
+B9ÙÜB<Š²B?sBB@_BE
+5BGÚ
+BJŠáBMsžBP@BS
+eBUÚ;BX§B[sèB^@ŸBa
+BcÚkBf§ABitBl@îBo
+ÅBqÚBt§qBwtHBzA
+B}
+ôB})8¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AáílAçãAí.AòÈ=AøaêAýûBÊ¡BxBdNB
+1$B
+ýûBÊÑB§Bd~B1TBþ*B
+ËB ×B#d­B&1B(þZB+Ë1B.B1dÝB41ŽB6þB9Ë`B<7B?e
+BB1ãBDþ¹BGËBJfBMe=BP2BRþéBUËÀBXB[elB^2CB`ÿBcËïBfÆBieBl2sBnÿIBqÌ BtöBweÌBz2£B|ÿyB}Œ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÖ
+AÜDAáÞ@AçwíAíAò«GAøDóAýÞ BŒ&BüBUÓB
+"©B
+ïBŒVB,BVB"ÙBï¯B
+Œ
+B \B#V2B&#	B(ïßB+ŒµB.B1VbB4#8B6ðB9ŒåB<»B?VBB#hBDð>BGœBJëBMVÁBP#BRðnBUœDBXB[VñB^#ÇB`ðBcœuBfKBiW!Bl#øBnðÎBqœ€Bt{BwWQBz$'B|ðþB}
+A¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AËLÌAÐôCAÖðAÜ'AáÁJAçZ÷Aìô£AòPAø'üAýÁ©B­«BzBGWB
+.B
+áB­ÚBz±BGB]Bá4B
+®
+B záB#G·B&B(ádB+®:B.{B1GçB4œB6áB9®iB<{@B?HBBíBDáÃBG®BJ{pBMHFBP
+BRáóBU®ÉBX{B[HvB^MB`â#Bc®ùBf{ÐBiHŠBl|BnâSBq¯)Bt{ÿBwHÖBz¬B|âB|ýÆ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A¿ü|AÅ£óAË= AÐ×MAÖpúAÜ
+§Aá€SAç> Aì×¬AòqYAø
+Aý€²B/BlB8ÜB
+²B
+ÒB_Bl5B9
+BâBÒ¹B
+B leB#9<B&B(ÒèB+¿B.lB19kB4AB6ÓB9îB<lÅB?9BBqBDÓHBG 
+BJlôBM9ËBP¡BRÓwBU NBXm%B[9ûB^ÑB`ÓšBc ~BfmTBi:+BlBnÓ×Bq ®BtmBw:ZBz1B|ÔB|ïJ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AŽ¬,AºS£A¿íPAÅýAË ªAÐºWAÖTAÛí°Aá\Aç!	Aìº¶AòTbA÷îAýŒBŽB]B*aB	÷7B
+Ä
+BäB]ºB*B÷gBÄ=B
+B ]êB#*ÀB%÷B(ÄmB+CB.^B1*ðB3÷ÆB6ÄB9sB<^IB?+ BA÷öBDÄÌBG£BJ^yBM+OBOø&BRÄýBUÓBX^©B[+B]øVB`Å,BcBf^ÙBi+¯BkøBnÅ\Bq2Bt_	Bw+ßByøµB|ÅB|àÏ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A©[ÜA¯SAŽ Aº6­A¿ÐZAÅjAË³AÐ`AÖ7
+AÛÐ¹AájfAçAì¿Aò7lA÷ÑAýjÆB9BOBåB	èŒB
+µBiBO?B
+BèìBµÂB
+B OoB#
+EB%éB(µñB+ÈB.OB1
+uB3éKB6¶!B9øB<OÎB?
+€BAé{BD¶QBG'BJOþBM
+ÕBOé«BR¶BUXBXP.B[
+B]éÛB`¶±BcBfP^Bi
+4Bkê
+Bn¶áBq·BtPBw
+dByê:B|·B|ÒT¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+A£³A©L¯A®æ\AŽ	Aº¶A¿³bAÅMAÊæ»AÐhAÖAÛ³ÁAáMnAæçAìÈAòuA÷Ž"AýMÎBsœB@B
+jB	ÚAB
+§BsíB@ÄB
+BÚpB§GB
+t
+B @óB#
+ÉB%Ú B(§vB+tMB.A#B1
+ùB3ÚÐB6§ŠB9t|B<ASB?)BAÚÿBD§ÖBGt­BJABMYBOÛ0BRšBUtÜBXA³B[B]Û_B`š6Bcu
+BfAâBi¹BkÛBnšeBqu<BtBBwèByÛ¿B|šB|ÃØ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A»;Ab²Aü_A£
+A©/¹A®ÉfAŽcA¹ü¿A¿kAÅ0AÊÉÅAÐcqAÕý
+AÛËAá0xAæÊ%AìcÒAñý~A÷+Aý0×BeBB2BþïB	ËÅB
+BerB2HBÿBËõBËB
+e¡B 2xB"ÿNB%Ì%B(ûB+eÑB.2šB0ÿ~B3ÌTB6+B9fB<2×B>ÿ®BAÌ
+BD[BGf1BJ3BLÿÞBOÌŽBRBUfaBX37B[ B]ÌäB`ºBcfBf3gBi =BkÍBnêBqfÀBt3Bw mByÍCB|B|µ]¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AjëAbA¬AEŒAßiA£yA©ÂA®¬oAŽFA¹ßÈA¿yuAÅ!AÊ¬ÎAÐF{AÕà(AÛyÕAáAæ­.AìFÛAñàA÷z4AýáBVÇB#BðtB	œJB
+ BV÷B#ÍBð£BœyBPB
+W&B #ýB"ðÓB%œ©B(B+WVB.$,B0ñB3œÙB6¯B9WB<$]B>ñ3BAŸ	BDàBGW¶BJ$BLñcBOŸ9BRBUWæBX$ŒBZñB]ŸiB`?BcXBf$ìBhñÂBkŸBnoBqXEBt%BvñòByŸÈB|B|Šâ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Ax58AÂA[¿AõlAA(ÆAÂrA£\AšõËA®xAŽ)%A¹ÂÑA¿\~AÄö+AÊØAÐ)
+AÕÃ2AÛ\ÞAàöAæ7Aì)äAñÃA÷]=AüöêBHLB"BáøB	®ÏB
+{¥BH{BQBâ(B®þB{ÕB
+H«B B"âXB%¯.B(|B+HÛB.±B0âB3¯^B6|5B9I
+B<áB>âžBA¯BD|dBGI;BJBLâçBO¯ŸBR|BUIjBXABZãB]¯íB`|ÄBcIBfpBhãGBk°
+Bn|óBqIÊBt BvãvBy°MB|}$B|g¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AaAlãAxßA¥
+A>ÉAØvAr"A
+ÏA¥{A£?(AšØÕA®rAŽ
+.A¹¥ÛA¿?AÄÙ5AÊrâAÐ
+AÕŠ;AÛ?çAàÙAæsAAì
+íAñŠA÷@GAüÙóB9ÐB§BÓ}B	 SB
+m)B: BÖBÓ­B BmYB
+:0B B"ÓÜB% ³B(mB+:_B.6B0Ô
+B3 ãB6m¹B9:B<fB>Ô<BA¡BDméBG:¿BJBLÔlBO¡BBRnBU:ïBXÅBZÔB]¡rB`nHBc;BfõBhÔËBk¡¢BnnxBq;NBt%BvÔüBy¡ÒB|nšB|ì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AJóûAVBèAav@Al©AwÜñA&A!ÒA»AU+AîØA
+A£"1Aš»ÞA®UA³ï8A¹åA¿"AÄŒ>AÊUëAÏïAÕDAÛ"ñAàŒAæVJAëï÷Añ£A÷#QAüŒýB+UBø+BÅB	ØB
+^®B+
+Bø[BÅ1BB^ÞB
++ŽBøB"ÅaB%7B(_B++åB-ø»B0ÅB3hB6_>B9,B;øëB>ÅÁBABD_nBG,DBIùBLÅñBOÇBR_BU,tBWùJBZÆ B]÷B`_ÍBc,£BeùzBhÆPBk&Bn_ýBq,ÔBsùªBvÆByWB|`-B|{p¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A4S]A?¢JAJÕ¢AVûAa<SAlo¬Aw£Ak/AÛAA85AÑáAkA£;AšèA®8A³ÒBA¹kîA¿AÄGAÊ8ôAÏÒ¡AÕlMAÛúAà§Aæ9SAëÓAñl®A÷ZAü B
+ÙBé°B¶B	]B
+P3B
+	BéàB¶¶BBPcB
+
+9BêB"¶æB%œB(PB+
+iB-ê@B0·B3ìB6PÃB9
+B;êoB>·FBA
+BDPòBG
+ÉBIêBL·uBOLBRQ"BU
+øBWêÏBZ·¥B]{B`QRBc
+(BeêþBh·ÕBk¬BnQBq
+XBsë/BvžByÛB|Q²B|lõ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+²¿A)¬A45A?h]AJµAUÏAafAl5¿AwiAN8AçåAA>AŽëANA¢èEAšòA®A³µKA¹N÷AŸè€AÄQAÊýAÏµªAÕOWAÚéAà±Aæ
+^Aë¶
+AñO·AöécAüB^BÛ5Bš
+B	táB
+AžBBÛdBš;BuBAçB
+ŸBÛB"škB%uAB(BB+îB-ÛÄB0šB3uqB6BGB9
+B;ÛôB>šÊBAu¡BDBwBGMBIÜ$BLšúBOuÐBRB§BU}BWÜSBZ©*B]v B`BÖBc­BeÜBh©ZBkv0BnCBqÝBsÜ³Bv©Byv`B|C6B|^z¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A!AaA
+fA(Ç¿A3ûA?.pAJaÈAU!A`ÈyAkûÑAw/*A1BAÊîAdAþHAõA1¢A¢ËNAšdûA­þ§A³TA¹2AŸË­AÄeZAÉÿAÏ³AÕ2aAÚÌAàeºAåÿgAëAñ2ÀAöÌmAüfB ÿãBÌ¹BB	ffB
+3<B BÌéB¿BfB3mB
+ CBÍB"ðB%fÆB(3B+ sB-ÍIB0B3föB63ÌB9 ¢B;ÍyB>OBAg%BD3üBG ÒBIÍšBLBOgUBR4+BUBWÍØBZ®B]g
+B`4\Bc2BeÎBhßBkgµBn4BqbBsÎ8BvBygåB|4»B|Oÿ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @àã@÷ÞAóÇA' A
+ZxA(ÑA3Á)A>ôAJ'ÚAU[2A`AkÁäAvõ<AJA­÷AG€AáQAzýAªA¢®VAšHA­á°A³{\A¹	AŸ®¶AÄHbAÉâAÏ{œAÕiAÚ¯AàHÂAåâoAë|
+AñÈAö¯uAüI"B ñgBŸ=BB	WêB
+$ÀBñBŸmBDBXB$ðB
+ñÇBŸB"sB%XJB(% B*ñöB-ŸÍB0£B3XyB6%PB8ò&B;ŸüB>ÓBAX©BD%BFòVBI¿,BLBOXÙBR%¯BTò
+BW¿\BZ3B]Y	B`%ßBbò¶Be¿BhbBkY9Bn&BpòåBs¿ŒBvByYiB|&?B|A¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @³¡È@Ê?¢@àŠS@÷
+A¹ÚAí3A
+ A(SäA3<A>ºAIííAU!FA`TAköAv»OA÷TAA*­AÄZA^A÷³A¢`Aš+
+A­Ä¹A³^fAžøAŸÀAÄ+mAÉÅAÏ^ÆAÔørAÚAà+ÌAåÅxAë_%AðøÒAö~Aü,+B âëB¯ÂB|B	InB
+EBã
+B¯òB|ÈBIBuB
+ãKB°"B"|øB%IÎB(¥B*ã{B-°QB0}(B3IþB6ÕB8ã«B;°B>}WBAJ.BDBFãÚBI°±BL}BOJ]BR4BTä
+BW°áBZ}·B]JB`dBbä:Be±Bh}çBkJœBnBpäjBs±ABv~ByJíB|ÄB|3¿  ¿  ¿  ¿  ¿  ¿  @`@þe@³e@ÉËÇ@à2x@ö)AíA³FA
+æA(öA3MOA>šAIŽ ATçXA`±AkN	AvbAÚ]At
+A
+·A§cAAAÚŒA¢tiAšA­§ÂA³ApAžÛ
+AŸtÉAÄvAÉš"AÏAÏAÔÛ|AÚu(AàÕAåšAëB.AðÛÛAöuAü5B ÔpB¡FBn
+B	:ôB
+ÊBÔ B¡wBnMB;#BúB
+ÔÐB¡ŠB"n}B%;SB()B*Õ B-¡ÖB0n­B3;B6YB8Õ/B;¢B>nÜBA;²BDBFÕ_BI¢5BLo
+BO;ãBR¹BTÕBW¢fBZo<B]<B`éBbÕ¿Be¢BholBk<BBn	BpÕïBs¢ÅBvoBy<rB|	HB|$¿  ¿  ¿  ¿  @2>@_zS@#Ú@@²ñ<@ÉWì@ßŸ@ö%OAF AyXA
+¬±A'à
+A3bA>FºAIzAT­kA_àÄAk
+AvGuAœgAWAðÀAlA$AœÆA¢WrA§ñ A­ÍA³$yAžŸ&AŸWÒAÃñAÉ,AÏ$ØAÔŸ
+AÚX2AßñÞAåAë%9AðŸåAöXAûò>B ÅõBÌB_¢B	,xB
+ùOBÆ%BûB_ÒB,šBù~B
+ÆUB+B"`B%,ØB'ù®B*Æ
+B-[B0`1B3-B5ùÞB8ÆŽB;B>`aBA-7BCú
+BFÆäBI»BL`BO-gBQú>BTÇBWêBZ`ÁB]-B_úmBbÇDBeBh`ñBk-ÇBmúBpÇtBsJBva By-÷B{úÍB|¿  ¿  ?¯xI@÷Ú@1Å<@^@
+° @°@²}b@Èä@ßJÃ@õ±tA
+A?lA
+rÄA'Š
+A2ÙuA>
+ÍAI@&ATs~A_Š×AjÚ/Av
+A pA:
+AÓÉAmvA"A ÐA¢:}A§Ô)A­mÖA³Až¡/AŸ:ÜAÃÔAÉn5AÏâAÔ¡AÚ;;AßÔéAånAëBAð¡îAö;AûÕHB ·zBPBQ'B	
+ýB
+êÓB·ªBBQVB
+-BëB
+·ÙB°B"QB%
+]B'ë3B*ž	B-ßB0Q¶B3
+B5ëbB8ž9B;
+B>QåBA
+ŒBCëBFžiBI
+?BLRBO
+ìBQëÂBTžBW
+oBZREB]
+B_ëòBbžÉBe
+BhRuBkLBmì"BpžøBs
+ÏBvR¥By{B{ìQB|?!G®?)Õ?®
+@$@0Ý@]ªé@
+<%@¢×@²	@Èp8@ÞÖé@õ=AÒ&A~A
+8×A'l/A2A=ÒàAI9AT9A_léAj BAuÓAyA
+&A¶ÒAPAê-AÙA¢
+A§·2A­PßA²êAž8AŸ
+åAÃ·AÉQ>AÎêëAÔAÚ
+EAß·òAåQAêëKAðøAö
+€AûžQB šÿBuÕBB«B	B
+ÜXB©.BvBBÛB±BÜB
+©^Bv5B"C
+B%áB'Ü·B*©B-vdB0C:B3B5ÜçB8©œB;vB>CkBAABCÝBF©îBIvÄBLCBOqBQÝGBTª
+BWvôBZCÊB]¡B_ÝwBbªMBew$BhCúBkÐBmÝ§Bpª}BswSBvD)By B{ÝÖ¿  ?b(?&6¬?¬¶@(p@/õÒ@\Ã4@ÈK@.ü@±­@Çü^@Þc@ôÉÀA9AËAþêA'2BA2eA=óAHÌKASÿ€A_2üAjfUAu­AfA 0AÝA3AÍ6AfâA¢ A§<A­3èA²ÍAžgBAŸ îAÃAÉ4IAÎÍõAÔg¢AÚNAßûAå4šAêÎTAðhAö®AûZB BgZB40B	B
+ÍÝB³BgB4`B6BÎ
+B
+ãBg¹B"4B%fB'Î<B*B-géB04¿B3B5ÎlB8CB;hB>4ïBAÆBCÎBFrBIhIBL5BOõBQÎÌBT¢BWhyBZ5OB]%B_ÎüBbÒBehšBh5BkUBmÏ+BpBshØBv5®By	j¿  ¿  ?ÃV?"×?ªæ°@@º@/
+@[Û~@Tp@»!@±!Ò@Ç@Ýï3@ôUäA^KA£AÄüA&øTA2+¬A=_AH]ASÅ¶A^ùAj,gAu_¿AIA
+ã9A|æAA°?AIìA¡ãA§}EA­òA²°AžJKAœãùAÃ}¥AÉRAÎ°þAÔJ«AÙäXAß~Aå±Aê±^AðK
+Aõä·Aû~eB BXÞB%µBòB
+¿aB8BYB%åBò»B¿B
+gBY>B"&B$òêB'¿ÁB*B-YmB0&DB2óB5¿ñB8ÇB;YB>&tB@óJBCÀ!BF÷BIYÍBL&€BNózBQÀQBT'BWYýBZ&ÔB\óªB_ÀBbWBeZ-Bh'BjóÙBmÀ°BpBsaB¿  ¿  ¿  ¿  ?$?
+ù?©F@Y@.&h@ZóÊ@à@GG@°­÷@Çš@Ý{Y@óâ
+A$^AW¶AA&ŸgA1ñ¿A=%AHXpASÉA^¿!AiòyAu%ÒA,A
+ÆCA_ïAùAHA,õA¡Æ¢A§`NA¬ùûA²©Až-UAœÇAÃ`¯AÈú[AÎAÔ-ŽAÙÇaAßaAäúºAêgAð.AõÇÁAûanB }BJcB9BäB
+°æB}œBJBiBä?B±B
+}ìBJÂB"B$äoB'±EB*~
+B-JóB0ÉB2äB5±vB8~LB;K"B>ùB@äÏBC±¥BF~|BIKRBL)BNäÿBQ±ÕBT~¬BWKBZXB\å/B_²Bb~ÛBeK±BhBjå^Bm¹¿  ¿  ¿  ¿  ¿  ¿  ?
+²?Z1?§GÝ@ qQ@->³@Z
+@l»@Ól@°:
+@Æ Î@Ý@ón0AêpA
+ÉAQ!A&zA1·ÒA<ë+AH
+ASQÛA^
+4AižAtëåAA
+©LABøAÜ¥AvRAþA¡©«A§CYA¬ÝA²v²Až_Aœª
+AÃCžAÈÝdAÎwAÔŸAÙªjAßDAäÝÅAêwqAð
+AõªÊAûDwB oB;èBŸBÕB
+¢kBoAB<BîBÕÄB¢B
+oqB<GB"	
+B$ÕôB'¢ËB*o¡B-<wB0	NB2Ö$B5¢úB8oÑB;<§B>	}B@ÖTBC£*BFpBI<×BL	­BNÖBQ£ZBTp0BW=BZ	ÝB\Ö³B_£Bbp`Be=6Bhò¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?æá?»X?¥xp?ÿ5@,Vý@Y$_@øà@_@¯ÆC@Æ,ó@Ü€@òúTA°AãÜA4A&JA1}åA<±=AGäASïA^KGAi~At±øAåQA
+UA&A¿®AY[Aó	A¡µA§&bA¬ÀA²Y»A·óhAœAÃ&ÁAÈÀnAÎZAÓóÇAÙuAß'!AäÀÎAêZzAïô'AõÔAû'B `B-mBúCBÇB
+ïB`ÆB-BúrBÇIBB
+`õB-ÌB!ú£B$ÇyB'OB*a&B--üB/úÒB2Ç©B5B8aUB;.,B=ûB@ÇÙBC¯BFa
+BI.\BKû2BNÈBQßBTaµBW.BYûaB\È8B_BbhÊ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+H?
+?£©?ýCÌ@+oI@X<ª@
+@ë·@¯Rh@Å¹@ÜÊ@òzAvA©ïAÝGA&A1CøA<wQAGª©ARÞA^ZAiD²Atx
+A«dA
+o^A	
+A¢¹A<eAÖA¡o¿A§	kA¬£A²<ÄA·ÖqAœp
+AÃ	ÊAÈ£wAÎ=%AÓÖÑAÙp~Aß
+*Aä£×Aê=Aï×0AõpÝAû
+B RB
+ñBëÇBžB
+
+tBRJB!Bë÷BžÍB
+€B
+R{BQB!ì'B$žþB'
+ÔB*RªB-B/ìWB2¹-B5B8RÚB;±B=ìB@¹]BC4BFS
+BIàBKì·BN¹BQcBTS9BW BYìæB\À¢¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?	©>?}¬?¡Ù?ût_@*@WTô@+@wÛ@®Þ@ÅE=@Û«î@òA<šAp A£YA%Ö²A1
+
+A<=bAGp»AR€A]×lAi
+ÄAt>
+AquA
+RhAìA
+ÁAnA¹A¡RÇAŠìsA¬ A²ÍA·¹yAœS&AÂìÔAÈAÎ -AÓ¹ÚAÙSAÞí3AäßAê Aïº9AõSåAúíB CBvBÝLBª"B
+vùBCÏB¥BÝ|BªSBw)B
+CÿBÖB!Ý¬B$ªB'wYB*D/B-B/ÝÜB2ª²B5wB8D_B;5B=Þ
+B@ªâBCwžBFDBIeBKÞ;BN«BQwèBTDŸBWz¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+k?
+ÞÚ? 
+2?ù€ö@)Þ@Vm@@Q@@®j²@ÄÑc@Û8@ñÅA»A6AilA%ÄA0Ð
+A<uAG6ÎARj&A]AhÐ×At/A7A
+5qAÏ
+AhÊAwA#A¡5ÐAŠÏ}A¬i)A²ÖA·Aœ60AÂÏÝAÈiAÎ6AÓãAÙ6AÞÐ<AäiéAêAïBAõ6ïAúÐB 5$BúBÎÑB§B
+h}B5TB+BÏB×Bh®B
+5BZB!Ï1B$B'hÝB*5ŽB-B/ÏaB27B5i
+B85äB;ºB=ÏB@gBCi=BF6BIéBKÏÀBNBQpR¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?k?	@?:Å?÷Õ@(ž(@U
+@)u@&@­ö×@Ä]@ÚÄ9@ñ*êAÈÎAü&A/A%b×A00A;ÉAFüáAR09A]cAhêAsÊBA~ýA
+zA²'AKÓAåA-A¡ÙAŠ²A¬L4A±åàA·Aœ:AÂ²æAÈLAÍæ?AÓìAÙAÞ³EAäLòAéæAïLAõùAú³¥B &©BóBÀUB,B
+ZB&ÙBó¯BÀB\BZ2B
+'	B
+óßB!ÀµB$B'ZbB*'9B,ôB/ÀåB2ŒB5ZB8'hB:ô?B=ÁB@ëBCZÁBF'BHônBKÈ*¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ý?¡/?k\?ö!@'Ðs@TÕ@µ@
+L@­ý@Ãé®@ÚP_@ð·AáAÂ9AõA%(êA0\CA;AFÂóAQöLA])€Ah\ýAsUA~Ã®AûA0A.ÝAÈAb6A ûäAŠA¬/=A±ÈêA·bAŒüCAÂïAÈ/AÍÉIAÓbõAØü¢AÞOAä/üAéÉ©AïcUAôýAú¯B -BåB±ÛB~±B
+KB^Bå4B²
+B~áBK·B
+B
+ådB!²:B$B'KçB*œB,åB/²jB2@B5LB8íB:åÃB=²B@pBCLFBF ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ö[ë?U?ï?ô6Ž@&èœ@S¶
+@AÀ@šq@­"@ÃuÓ@ÙÜ@ðC4ATóAKA»€A$îüA0"TA;U­AFAQŒ^A\ï¶Ah#AsVgA~ÀAÞAx9AæA«AE@A ÞíAŠxA¬FA±«óA·EAŒßLAÂxùAÈ¥AÍ¬RAÓEÿAØß¬AÞyYAäAé¬²AïF_Aôà
+AúyžB 	³BÖB£_Bp6B
+=
+B	âBÖ¹B£BpeB=<B
+
+B
+ÖéB!£¿B$pB'=lB*
+BB,×B/£ïB2pÅB5=B8
+qB:×HB=€
+B@wÚ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ï
+I>üÇ?Ì?ògK@&@RÎj@Ì@4@¬G@Ãù@Ùh©@ïÏZAAN^A¶A$µA/ègA;ÀAFOAQqA\µÉAgé!As
+zA~OÓAÁA[DAôðAA(JA ÁöAŠ[£A«õOA±üA·(©AŒÂUAÂ\AÇõ¯AÍ\AÓ)	AØÂ¶AÞ\bAãöAé»Aï)hAôÃAú\ÁAÿönBÈBäBaºB
+.B
+ûgBÈ=BBaêB.ÁBûB
+ÈmB!DB$bB'.ðB)ûÇB,ÈB/sB2bIB5/ B7ûöB:Ï²¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >çà¥>õc?ý
+?ðâ@%T@Qæ¶@~Ž@Àœ@¬'m@Â
+@ØôÏ@ï[AáAqAGÉA${"A/®zA:áÓAF+AQHA\{ÜAg¯5ArâA~çA€ A>MA×úAqŠA
+SA €ÿAŠ>¬A«ØYA±rA·
+²AŒ¥_AÂ?
+AÇØ¹AÍrfAÓ
+AØ¥¿AÞ?kAãÙAérÅAï
+qAôŠ
+Aú?ËAÿÙxB¹BiBS?B
+ B
+ììB¹ÂBBSoB EBí
+B
+¹òB!ÈB$SB' uB)íKB,º!B/øB2SÎB5'¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >à£>îK ?-¬?îÈq@$1@Pþý@}Ì_@Là@«³@ÂB@Øó@îç€A§*A
+ÚA
+ÛA$A4A/tA:§äAEÛ=AQA\AîAguFAršA}ÛøA©A!UA»AT®Aî[A AŠ!ŽA«»aA±UA¶î»AŒhAÂ"AÇ»ÁAÍUnAÒïAØÇAÞ"tAãŒ AéUÍAîïzAô&Aú"ÔAÿŒB«BwìBDÃB
+B
+ÞpB«FBx
+BDóBÉBÞB
+«vB!xLB$E"B'øB)ÞÏB,«¥B/a¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Ùe]>ç
+û?^C?ìù@#Iç@PH@|äª@Ù@«?·@ÁŠh@Ø
+@îsÊAm=A
+ AÓîA$FA/:A:møAE¡PAPÔšA\Ag;YArn²A}¢
+Aj²A^A
+A7žAÑdA kAŠŸA«kA±8A¶ÑÅAŒkqAÂ
+AÇÊAÍ8wAÒÒ$AØkÐAÞ}Aã*Aé8ÖAîÒAôl1AúÝAÿBBiqB6HB
+
+B
+ÏôBËBi¡B6wBNBÐ$B
+úB!iÐB$6§B'}B)×9¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Ò'»>ßÐY?Û?ë)@"b3@O/@{üö@e,@ªËÝ@Á2@×?@íÿïA3PA
+fšAA#ÍZA/ ²A:4
+AEgcAP»A[ÎAglAr4ÅA}h
+AM»AçhAAÁAŽnA NA¥çÈA«uA±!A¶ŽÎAŒNzAÁè'AÇÔAÍAÒµ-AØNÚAÝèAã4AéáAîµAôO:AùèæAÿB BZöB'ÌB
+ô£B
+ÁyBOB[&B'üBôÒBÁšB
+B![UB$/¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Êê>Øµ?¿r?éZ6@!z~@NGà@{A@ñR@ªX@ÀŸ³@×%d@íAùcA
+,ŒA`A#lA.ÆÅA9ú
+AE-vAP`ÎA['AfÇAqú×A}./A0ÄAÊqAd
+AýËAxA 1%A¥ÊÑA«d~A°þ*A¶×AŒ1AÁË0AÇdÝAÌþAÒ7AØ1äAÝËAãe=AèþêAîAô2CAùËðAÿeB€BL{BQB
+æ'B
+²þBÔBLªBBæWB³-B
+é¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Ã¬s>ÑTñ?ð?çÆ@ Å@M`'@z-@}u@©ä&@ÀJ×@Ö±@í9A¿uA
+òÍA&&A#Y~A.×A9À/ADóAP&àA[Z8AfAqÀéA|ôBAÎA­{AG(AàÕAzA .A¥­ÚA«GA°á4A¶zàAŒAÁ®:AÇGçAÌáAÒ{AAØíAÝ®AãHFAèáóAî{ AôLAù®ùAÿH¥Bq)B=ÿB
+ÖB
+×¬B
+€BqXB>/B
+BÞÁ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ŒnÐ>ÊN? ?å»\@«@Lxr@yEÔ@	@©pL@¿Öý@Ö=®@ì€_A
+A
+žàAì9A#A.RêA9BAD¹AOìòA[ KAfS€AqüA|ºUAöØA
+A*1AÃÞA]A÷7A¥äA«*A°Ä=A¶]êA»÷AÁDAÇ*ñAÌÄAÒ^JA×÷öAÝ£Aã+PAèÄüAî^©AóøVAùAÿ+¯Bb®B/BüZB
+É0B
+BbÝB6¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >µ1,>ÂÙª?Q/?ãëó@
+Ã\@KŸ@x^ @Á@šür@¿c#@ÕÉÔ@ì0
+AKA
+~óA²LA"å€A.üA9LTAD­AO³AZæ^Af·AqMA|iAÙáAsA
+:AŠçA@AÚ@A¥síA«
+A°§GA¶@ôA»Ú¡AÁtMAÇ
+úAÌ§ŠAÒASA×Û AÝt¬AãYAèšAîA²AóÛ`Aùu
+Aÿ·BT2B!BíßB
+ºµB
+q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >­ó>»?Æ?â
+@
+Ûš@J©
+@wvl@!ç@š@ŸïI@ÕUù@ëŒ«A®A
+EAx^A"«¶A-ßA9hADEÀAOyAZ¬qAeßÉAq"A|F|AŒêAVAðDAðA#AœJA¥V÷Aªð€A°QA¶#ýA»œªAÁWVAÆñAÌ°AÒ$\A×Ÿ	AÝW¶AâñbAèAî$œAóŸiAùXAþñÁBE·BBæI¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Šµå>Ž^C?²U?àM@
+óï@IÁQ@v³@®
+@š»@Ÿ{m@Ôâ
+@ëHÎA ×¿A
+
+A>pA"qÉA-¥!A8ØzAD
+ÒAO?*AZrAe¥ÜApÙ4A|
+AóA9AÓLAlùAŠA SA¥: AªÓ¬A°mYA¶A» ²AÁ:_AÆÔ
+AÌmžAÒeA×¡AÝ:¿AâÔlAènAîÅAó¡rAù;
+AþÔËB>!¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >xA>­ À?âô?Þ}¹@
+
+?@HÙ¡@u§@:3@§ ã@Ÿ@ÔnD@êÔöA ÓA
+Ñ,AA"7ÝA-k5A8ACÑæAO?AZ8AekïApGA{Ò¡AýA
+ªA¶WAPAé±A]A¥
+
+Aª¶¶A°PcAµêA»ŒAÁ
+iAÆ·AÌPÂAÑêpA×
+AÝ
+ÉAâ·vAèQ#AíêÏAó|Aù+ó¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >:>¥ã??Ü®P@$@Gñì@t¿N@ÆX@§-@œº@Óúk@êaA cæA
+?AÊA!ýïA-1HA8d¡ACùANËQAYþ©Ae2Ape[A{ŽAfAÿŽAaA3
+AÌºAffA¥ AªÀA°3lAµÍA»fÆAÁ rAÆ AÌ3ÍAÑÍyA×g&AÝ ÓAâAè4,AíÛ£¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >üú>¥x?D"?ÚÞç@<Ö@G
+8@s×@R~@Š¹/@œß@Ó@éíAA )ùA
+]QAªA!ÄA,÷[A8*³AC^
+ANdAYÄœAdøAp+nA{^ÇAIAâœA|jAA¯ÃAIpA€ã
+Aª|ÉA°vAµ°"A»IÐAÀã}AÆ})AÌÖAÑ°A×J/AÜãÜAâS¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >¿W>h?~é?Ù@U*@F"@rïí@Þ§@ŠEX@Œ¬	@Óº@éyk@ÿà
+A
+#gAV¿A!A,œpA7ðÈAC$!ANWyAYÒAdŸ*AoñA{$ÜA,AÅÈA_tAù!AÍA,zA€Æ'Aª_ÓA¯ùAµ.A»,ÚAÀÆAÆ`4AËùàAÑA×;¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >³>*q?{JÂ?×@%@mv@E:×@r9@jÍ@¥Ñ~@Œ8/@Òà@é@ÿlBA
+éyA
+ÒA!P*A,A7¶ÛABê4AN
+AYPäAd=Ao·AzêïA$AšÑAB}AÜ*Au×AA€©1AªBÞA¯ÜAµv7A»äAÀ©AÆC=AËêŽ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >v
+>ìÍ?w«ð?Õpœ@
+Á@DS#@q @öó@¥]€@»ÄU@Ò+@è¶@þøgA
+¯AâåA!=A,IA7|îAB°FAMãAYøAdJPAo}šAz±Aò-AÚA%A¿3AXáAòA€:Aª%çA¯¿AµY@AºòíAÀd¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >h
+×>¯j?t
+>?Ó¡d@@Ckv@p8Ø@
+@€éÎ@»P~@Ñ·/@è
+à@þA
+u¡AšúA ÜRA,ªA7CABv\AM©ŽAXÝ
+AdeAoCœAzwAÕ8AnäAA¢?A;ëAÕA€oEAªñA¯¢AµJ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Y>tã?pnm?ÑÑû@¶`@BÂ@oQ$@C@€uó@ºÜ¥@ÑCU@çª@þ·A
+;ŽAo
+A ¢eA+ÕŸA7	AB<nAMoÇAX£AcÖxAo	ÐAz=)AžBAQïAëA
+HA
+õAž¡A€RNA©ùÅ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >KJ>fhÆ?lÏ»?Ð¢@ÎŽ@A@niw@m@€
+@ºhÎ@ÐÏ@ç60@ýáA
+ÉA5"A hzA+ÒA6Ï+ABAM5ÜAXi4AcAnÏåAz?ALA4ùAÎŠAhRAÿA©v¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ><>Wí?i0è?Î39@ç @@Ža@mÃ@'@£C@¹ôô@Ð[¥@æÂV@ý)A	ÇÜAû4A .A+aåA6>AAÈALûïAX/GAcbAnøAyÉRA~VAA±¯AY&¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >.»>Ir7?e?ÌcÐ@ÿK@?Ì­@l@³ž@£i@¹@ÏçË@æN|@üµ-A	ïAÁGAô A+'øA6[QAA©ALÂAWõZAc(³An\
+AydAa_AÖ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >€s>:÷p?aóe?Êx@@>å @k²b@?â@¢Š@¹
+D@Ïsõ@åÚ¥@üAVA	TA\AºµA*î
+A6!eAATŸALAW»oAbîÇAn" Ayq¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >)/>,|,?^T?ÈÅ@/ê@=ýL@jÊ­@Ì@¢2¹@žj@Ï @åfË@ûÍ}A	AMoAÇA*Ž A5çyAAÑALN)AWAbÐo¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >­é>
+ æ?ZµÃ?ÆõŠ@H5@=@iâù@X.@¡Ÿß@ž%@Î@@äòò@ûY¢Aà)AAFÛA*z3A5­A@àäAL/Ñ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =èeE>?W?Å&M@`@<-ë@hûM@äW@¡K@·±º@Îj@ä@úåÌAŠ?AÙA
+ïA*@HA55¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =Ën¹>
+Ù?Sx@?ÃVä@xÕ@;F7@h@p~@ ×.@·=ß@Í€@ä
+A@úqòAlQAªA
+î¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =®x1=å *?OÙ?Á@
+(@:^@g+ì@ü§@ cX@¶Ê	@Í0º@ãk@ùþ
+AMû¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =€=È)?L:Œ?¿ž#@
+©t@9vÖ@fD8@Í@ï~@¶V/@ÌŒà@ãZº¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =i.=«3?Hë?œèº@
+ÁÀ@8"@e\@ó@{€@¶~¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =/)==?Dý9?Œa@
+Ú@7§u@dt×@ØF¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  <êwô=bì?A^h?ºIù@	ò_@7.¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  <m;Š=( Ü?=¿?¹W6¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  9°ç\=
+J¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ?!G®?Ð£×@(Qì@hQì@(ö@Ž(ö@Ô(ö@ô(öA
+{A{A*{A:{AJ{AZ{Aj{Az{A
+
+=A
+=A
+=A
+=A¥
+=A­
+=Aµ
+=Aœ
+=AÅ
+=AÍ
+=AÕ
+=AÝ
+=Aå
+=Aí
+=Aõ
+=Aý
+=B
+B
+B
+
+B
+B
+B
+B
+B
+
+B"
+B&
+B*
+B.
+B2
+B6
+B:
+B>
+BB
+BF
+BJ
+BN
+BR
+BV
+BZ
+B^
+Bb
+Bf
+Bj
+Bn
+Br
+Bv
+Bz
+B~
+?
+žR?Ï\)@'®@g®@×
+@³×
+@Ó×
+@ó×
+A	ë
+Aë
+A)ë
+A9ë
+AIë
+AYë
+Aië
+Ayë
+AõÃAõÃAõÃAõÃA€õÃA¬õÃAŽõÃAŒõÃAÄõÃAÌõÃAÔõÃAÜõÃAäõÃAìõÃAôõÃAüõÃBzáBzáB
+záBzáBzáBzáBzáB
+záB"záB&záB*záB.záB2záB6záB:záB>záBBzáBFzáBJzáBNzáBRzáBVzáBZzáB^záBbzáBfzáBjzáBnzáBrzáBvzáBzzáB~zá?
+(ö?Î{@'
+>@g
+>@
+@³
+@Ó
+@ó
+A	ÂAÂA)ÂA9ÂAIÂAYÂAiÂAyÂAáHAáHAáHAáHA€áHA¬áHAŽáHAŒáHAÄáHAÌáHAÔáHAÜáHAäáHAìáHAôáHAüáHBp€Bp€B
+p€Bp€Bp€Bp€Bp€B
+p€B"p€B&p€B*p€B.p€B2p€B6p€B:p€B>p€BBp€BFp€BJp€BNp€BRp€BVp€BZp€B^p€Bbp€Bfp€Bjp€Bnp€Brp€Bvp€Bzp€B~p€??ÌÌÍ@&ff@fff@33@³33@Ó33@ó33A	AA)A9AIAYAiAyAÌÍAÌÍAÌÍAÌÍA€ÌÍA¬ÌÍAŽÌÍAŒÌÍAÄÌÍAÌÌÍAÔÌÍAÜÌÍAäÌÍAìÌÍAôÌÍAüÌÍBffBffB
+ffBffBffBffBffB
+ffB"ffB&ffB*ffB.ffB2ffB6ffB:ffB>ffBBffBFffBJffBNffBRffBVffBZffB^ffBbffBfffBjffBnffBrffBvffBzffB~ff?
+=?Ë
+
+@%Â@eÂ@áH@²áH@ÒáH@òáHA	p€Ap€A)p€A9p€AIp€AYp€Aip€Ayp€AžRAžRAžRAžRA€žRA¬žRAŽžRAŒžRAÄžRAÌžRAÔžRAÜžRAäžRAìžRAôžRAüžRB\)B\)B
+\)B\)B\)B\)B\)B
+\)B"\)B&\)B*\)B.\)B2\)B6\)B:\)B>\)BB\)BF\)BJ\)BN\)BR\)BV\)BZ\)B^\)Bb\)Bf\)Bj\)Bn\)Br\)Bv\)Bz\)B~\)?zá?Ê=p@%
+ž@e
+ž@\@²\@Ò\@ò\A	G®AG®A)G®A9G®AIG®AYG®AiG®AyG®A£×A£×A£×A£×A€£×A¬£×AŽ£×AŒ£×AÄ£×AÌ£×AÔ£×AÜ£×Aä£×Aì£×Aô£×Aü£×BQìBQìB
+QìBQìBQìBQìBQìB
+QìB"QìB&QìB*QìB.QìB2QìB6QìB:QìB>QìBBQìBFQìBJQìBNQìBRQìBVQìBZQìB^QìBbQìBfQìBjQìBnQìBrQìBvQìBzQìB~Qì?ë
+?ÈõÂ@$zá@dzá@=q@²=q@Ò=q@ò=qA	
+žA
+žA)
+žA9
+žAI
+žAY
+žAi
+žAy
+žA\A\A\A\A€\A¬\AŽ\AŒ\AÄ\AÌ\AÔ\AÜ\Aä\Aì\Aô\Aü\BG®BG®B
+G®BG®BG®BG®BG®B
+G®B"G®B&G®B*G®B.G®B2G®B6G®B:G®B>G®BBG®BFG®BJG®BNG®BRG®BVG®BZG®B^G®BbG®BfG®BjG®BnG®BrG®BvG®BzG®B~G®?\)?Ç®@#×
+@c×
+@ë
+@±ë
+@Ñë
+@ñë
+AõÃAõÃA(õÃA8õÃAHõÃAXõÃAhõÃAxõÃAzáAzáAzáAzáA€záA¬záAŽzáAŒzáAÄzáAÌzáAÔzáAÜzáAäzáAìzáAôzáAüzáB=qB=qB
+=qB=qB=qB=qB=qB
+=qB"=qB&=qB*=qB.=qB2=qB6=qB:=qB>=qBB=qBF=qBJ=qBN=qBR=qBV=qBZ=qB^=qBb=qBf=qBj=qBn=qBr=qBv=qBz=qB~=q?
+ÌÍ?Æff@#33@c33@@±@Ñ@ñAÌÍAÌÍA(ÌÍA8ÌÍAHÌÍAXÌÍAhÌÍAxÌÍAffAffAffAffA€ffA¬ffAŽffAŒffAÄffAÌffAÔffAÜffAäffAìffAôffAüffB33B33B
+33B33B33B33B33B
+33B"33B&33B*33B.33B233B633B:33B>33BB33BF33BJ33BN33BR33BV33BZ33B^33Bb33Bf33Bj33Bn33Br33Bv33Bz33B~33?
+=q?Å
+ž@"\@b\@G®@±G®@ÑG®@ñG®A£×A£×A(£×A8£×AH£×AX£×Ah£×Ax£×AQìAQìAQìAQìA€QìA¬QìAŽQìAŒQìAÄQìAÌQìAÔQìAÜQìAäQìAìQìAôQìAüQìB(öB(öB
+(öB(öB(öB(öB(öB
+(öB"(öB&(öB*(öB.(öB2(öB6(öB:(öB>(öBB(öBF(öBJ(öBN(öBR(öBV(öBZ(öB^(öBb(öBf(öBj(öBn(öBr(öBv(öBz(öB~(ö?®?Ã×
+@!ë
+@aë
+@õÂ@°õÂ@ÐõÂ@ðõÂAzáAzáA(záA8záAHzáAXzáAhzáAxzáA=qA=qA=qA=qA€=qA¬=qAŽ=qAŒ=qAÄ=qAÌ=qAÔ=qAÜ=qAä=qAì=qAô=qAü=qB
+žB
+žB
+
+žB
+žB
+žB
+žB
+žB
+
+žB"
+žB&
+žB*
+žB.
+žB2
+žB6
+žB:
+žB>
+žBB
+žBF
+žBJ
+žBN
+žBR
+žBV
+žBZ
+žB^
+žBb
+žBf
+žBj
+žBn
+žBr
+žBv
+žBz
+žB~
+ž?
+ž?Â\@!G®@aG®@£×@°£×@Ð£×@ð£×AQìAQìA(QìA8QìAHQìAXQìAhQìAxQìA(öA(öA(öA(öA€(öA¬(öAŽ(öAŒ(öAÄ(öAÌ(öAÔ(öAÜ(öAä(öAì(öAô(öAü(öB{B{B
+{B{B{B{B{B
+{B"{B&{B*{B.{B2{B6{B:{B>{BB{BF{BJ{BN{BR{BV{BZ{B^{Bb{Bf{Bj{Bn{Br{Bv{Bz{B~{?\?ÁG®@ £×@`£×@Qì@°Qì@ÐQì@ðQìA(öA(öA((öA8(öAH(öAX(öAh(öAx(öA{A{A{A{A€{A¬{AŽ{AŒ{AÄ{AÌ{AÔ{AÜ{Aä{Aì{Aô{Aü{B
+=B
+=B
+
+=B
+=B
+=B
+=B
+=B
+
+=B"
+=B&
+=B*
+=B.
+=B2
+=B6
+=B:
+=B>
+=BB
+=BF
+=BJ
+=BN
+=BR
+=BV
+=BZ
+=B^
+=Bb
+=Bf
+=Bj
+=Bn
+=Br
+=Bv
+=Bz
+=B~
+=?   ?À  @   @`  @  @°  @Ð  @ð  A  A  A(  A8  AH  AX  Ah  Ax  A  A  A  A  A€  A¬  AŽ  AŒ  AÄ  AÌ  AÔ  AÜ  Aä  Aì  Aô  Aü  B  B  B
+  B  B  B  B  B
+  B"  B&  B*  B.  B2  B6  B:  B>  BB  BF  BJ  BN  BR  BV  BZ  B^  Bb  Bf  Bj  Bn  Br  Bv  Bz  B~  >úáH?ŸžR@\)@_\)@®@¯®@Ï®@ï®A×
+A×
+A'×
+A7×
+AG×
+AW×
+Ag×
+Aw×
+Aë
+Aë
+Aë
+Aë
+A£ë
+A«ë
+A³ë
+A»ë
+AÃë
+AËë
+AÓë
+AÛë
+Aãë
+Aëë
+Aóë
+Aûë
+BõÃBõÃB	õÃB
+õÃBõÃBõÃBõÃB
+õÃB!õÃB%õÃB)õÃB-õÃB1õÃB5õÃB9õÃB=õÃBAõÃBEõÃBIõÃBMõÃBQõÃBUõÃBYõÃB]õÃBaõÃBeõÃBiõÃBmõÃBqõÃBuõÃByõÃB}õÃ>õÂ?œp€@
+žR@^žR@\)@¯\)@Ï\)@ï\)A®A®A'®A7®AG®AW®Ag®Aw®A×
+A×
+A×
+A×
+A£×
+A«×
+A³×
+A»×
+AÃ×
+AË×
+AÓ×
+AÛ×
+Aã×
+Aë×
+Aó×
+Aû×
+Bë
+Bë
+B	ë
+B
+ë
+Bë
+Bë
+Bë
+B
+ë
+B!ë
+B%ë
+B)ë
+B-ë
+B1ë
+B5ë
+B9ë
+B=ë
+BAë
+BEë
+BIë
+BMë
+BQë
+BUë
+BYë
+B]ë
+Baë
+Beë
+Bië
+Bmë
+Bqë
+Buë
+Byë
+B}ë
+>ð£×?Œ(ö@
+{@^{@
+=@¯
+=@Ï
+=@ï
+=A
+A
+A'
+A7
+AG
+AW
+Ag
+Aw
+AÂAÂAÂAÂA£ÂA«ÂA³ÂA»ÂAÃÂAËÂAÓÂAÛÂAãÂAëÂAóÂAûÂBáHBáHB	áHB
+áHBáHBáHBáHB
+áHB!áHB%áHB)áHB-áHB1áHB5áHB9áHB=áHBAáHBEáHBIáHBMáHBQáHBUáHBYáHB]áHBaáHBeáHBiáHBmáHBqáHBuáHByáHB}áH>ë
+?ºáH@
+p€@]p€@žR@®žR@ÎžR@îžRA\)A\)A'\)A7\)AG\)AW\)Ag\)Aw\)A®A®A®A®A£®A«®A³®A»®AÃ®AË®AÓ®AÛ®Aã®Aë®Aó®Aû®B×
+B×
+B	×
+B
+×
+B×
+B×
+B×
+B
+×
+B!×
+B%×
+B)×
+B-×
+B1×
+B5×
+B9×
+B=×
+BA×
+BE×
+BI×
+BM×
+BQ×
+BU×
+BY×
+B]×
+Ba×
+Be×
+Bi×
+Bm×
+Bq×
+Bu×
+By×
+B}×
+>æff?¹@
+ÌÍ@\ÌÍ@ff@®ff@Îff@îffA33A33A'33A733AG33AW33Ag33Aw33AAAAA£A«A³A»AÃAËAÓAÛAãAëAóAûBÌÍBÌÍB	ÌÍB
+ÌÍBÌÍBÌÍBÌÍB
+ÌÍB!ÌÍB%ÌÍB)ÌÍB-ÌÍB1ÌÍB5ÌÍB9ÌÍB=ÌÍBAÌÍBEÌÍBIÌÍBMÌÍBQÌÍBUÌÍBYÌÍB]ÌÍBaÌÍBeÌÍBiÌÍBmÌÍBqÌÍBuÌÍByÌÍB}ÌÍ>áG®?žQì@
+(ö@\(ö@{@®{@Î{@î{A
+=A
+=A'
+=A7
+=AG
+=AW
+=Ag
+=Aw
+=A
+A
+A
+A
+A£
+A«
+A³
+A»
+AÃ
+AË
+AÓ
+AÛ
+Aã
+Aë
+Aó
+Aû
+BÂBÂB	ÂB
+ÂBÂBÂBÂB
+ÂB!ÂB%ÂB)ÂB-ÂB1ÂB5ÂB9ÂB=ÂBAÂBEÂBIÂBMÂBQÂBUÂBYÂB]ÂBaÂBeÂBiÂBmÂBqÂBuÂByÂB}Â>Ü(ö?·
+>@
+@[
+@Â@­Â@ÍÂ@íÂAáHAáHA&áHA6áHAFáHAVáHAfáHAváHAp€Ap€Ap€Ap€A£p€A«p€A³p€A»p€AÃp€AËp€AÓp€AÛp€Aãp€Aëp€Aóp€Aûp€BžRBžRB	žRB
+žRBžRBžRBžRB
+žRB!žRB%žRB)žRB-žRB1žRB5žRB9žRB=žRBAžRBEžRBIžRBMžRBQžRBUžRBYžRB]žRBažRBežRBižRBmžRBqžRBužRByžRB}žR>×
+=?µÂ@áH@ZáH@p€@­p€@Íp€@íp€AžRAžRA&žRA6žRAFžRAVžRAfžRAvžRA\)A\)A\)A\)A£\)A«\)A³\)A»\)AÃ\)AË\)AÓ\)AÛ\)Aã\)Aë\)Aó\)Aû\)B®B®B	®B
+®B®B®B®B
+®B!®B%®B)®B-®B1®B5®B9®B=®BA®BE®BI®BM®BQ®BU®BY®B]®Ba®Be®Bi®Bm®Bq®Bu®By®B}®>Ñë
+?Žzá@=q@Z=q@
+ž@­
+ž@Í
+ž@í
+žA\A\A&\A6\AF\AV\Af\Av\AG®AG®AG®AG®A£G®A«G®A³G®A»G®AÃG®AËG®AÓG®AÛG®AãG®AëG®AóG®AûG®B£×B£×B	£×B
+£×B£×B£×B£×B
+£×B!£×B%£×B)£×B-£×B1£×B5£×B9£×B=£×BA£×BE£×BI£×BM£×BQ£×BU£×BY£×B]£×Ba£×Be£×Bi£×Bm£×Bq£×Bu£×By£×B}£×>ÌÌÍ?³33@@Y@ÌÍ@¬ÌÍ@ÌÌÍ@ìÌÍAffAffA&ffA6ffAFffAVffAfffAvffA33A33A33A33A£33A«33A³33A»33AÃ33AË33AÓ33AÛ33Aã33Aë33Aó33Aû33BBB	B
+BBBB
+B!B%B)B-B1B5B9B=BABEBIBMBQBUBYB]BaBeBiBmBqBuByB}>Ç®?±ë
+@õÂ@XõÂ@zá@¬zá@Ìzá@ìzáA=qA=qA&=qA6=qAF=qAV=qAf=qAv=qA
+žA
+žA
+žA
+žA£
+žA«
+žA³
+žA»
+žAÃ
+žAË
+žAÓ
+žAÛ
+žAã
+žAë
+žAó
+žAû
+žB\B\B	\B
+\B\B\B\B
+\B!\B%\B)\B-\B1\B5\B9\B=\BA\BE\BI\BM\BQ\BU\BY\B]\Ba\Be\Bi\Bm\Bq\Bu\By\B}\>Â\?°£×@Qì@XQì@(ö@¬(ö@Ì(ö@ì(öA{A{A&{A6{AF{AV{Af{Av{A
+=A
+=A
+=A
+=A£
+=A«
+=A³
+=A»
+=AÃ
+=AË
+=AÓ
+=AÛ
+=Aã
+=Aë
+=Aó
+=Aû
+=B
+B
+B	
+B
+
+B
+B
+B
+B
+
+B!
+B%
+B)
+B-
+B1
+B5
+B9
+B=
+BA
+BE
+BI
+BM
+BQ
+BU
+BY
+B]
+Ba
+Be
+Bi
+Bm
+Bq
+Bu
+By
+B}
+>œp€?¯\)@®@W®@×
+@«×
+@Ë×
+@ë×
+Aë
+Aë
+A%ë
+A5ë
+AEë
+AUë
+Aeë
+Auë
+AõÃAõÃAõÃAõÃA¢õÃAªõÃA²õÃAºõÃAÂõÃAÊõÃAÒõÃAÚõÃAâõÃAêõÃAòõÃAúõÃBzáBzáB	záB
+záBzáBzáBzáB
+záB!záB%záB)záB-záB1záB5záB9záB=záBAzáBEzáBIzáBMzáBQzáBUzáBYzáB]záBazáBezáBizáBmzáBqzáBuzáByzáB}zá>žQì?®{@
+>@W
+>@
+@«
+@Ë
+@ë
+AÂAÂA%ÂA5ÂAEÂAUÂAeÂAuÂAáHAáHAáHAáHA¢áHAªáHA²áHAºáHAÂáHAÊáHAÒáHAÚáHAâáHAêáHAòáHAúáHBp€Bp€B	p€B
+p€Bp€Bp€Bp€B
+p€B!p€B%p€B)p€B-p€B1p€B5p€B9p€B=p€BAp€BEp€BIp€BMp€BQp€BUp€BYp€B]p€Bap€Bep€Bip€Bmp€Bqp€Bup€Byp€B}p€>³33?¬ÌÍ@ff@Vff@33@«33@Ë33@ë33AAA%A5AEAUAeAuAÌÍAÌÍAÌÍAÌÍA¢ÌÍAªÌÍA²ÌÍAºÌÍAÂÌÍAÊÌÍAÒÌÍAÚÌÍAâÌÍAêÌÍAòÌÍAúÌÍBffBffB	ffB
+ffBffBffBffB
+ffB!ffB%ffB)ffB-ffB1ffB5ffB9ffB=ffBAffBEffBIffBMffBQffBUffBYffB]ffBaffBeffBiffBmffBqffBuffByffB}ff>®{?«
+@Â@UÂ@áH@ªáH@ÊáH@êáHAp€Ap€A%p€A5p€AEp€AUp€Aep€Aup€AžRAžRAžRAžRA¢žRAªžRA²žRAºžRAÂžRAÊžRAÒžRAÚžRAâžRAêžRAòžRAúžRB\)B\)B	\)B
+\)B\)B\)B\)B
+\)B!\)B%\)B)\)B-\)B1\)B5\)B9\)B=\)BA\)BE\)BI\)BM\)BQ\)BU\)BY\)B]\)Ba\)Be\)Bi\)Bm\)Bq\)Bu\)By\)B}\)>šõÃ?ª=q@
+ž@U
+ž@\@ª\@Ê\@ê\AG®AG®A%G®A5G®AEG®AUG®AeG®AuG®A£×A£×A£×A£×A¢£×Aª£×A²£×Aº£×AÂ£×AÊ£×AÒ£×AÚ£×Aâ£×Aê£×Aò£×Aú£×BQìBQìB	QìB
+QìBQìBQìBQìB
+QìB!QìB%QìB)QìB-QìB1QìB5QìB9QìB=QìBAQìBEQìBIQìBMQìBQQìBUQìBYQìB]QìBaQìBeQìBiQìBmQìBqQìBuQìByQìB}Qì>£×
+?šõÂ@zá@Tzá@=q@ª=q@Ê=q@ê=qA
+žA
+žA%
+žA5
+žAE
+žAU
+žAe
+žAu
+žA\A\A\A\A¢\Aª\A²\Aº\AÂ\AÊ\AÒ\AÚ\Aâ\Aê\Aò\Aú\BG®BG®B	G®B
+G®BG®BG®BG®B
+G®B!G®B%G®B)G®B-G®B1G®B5G®B9G®B=G®BAG®BEG®BIG®BMG®BQG®BUG®BYG®B]G®BaG®BeG®BiG®BmG®BqG®BuG®ByG®B}G®>žR?§®@×
+@S×
+@ë
+@©ë
+@Éë
+@éë
+AõÃAõÃA$õÃA4õÃADõÃATõÃAdõÃAtõÃAzáAzáAzáAzáA¢záAªzáA²záAºzáAÂzáAÊzáAÒzáAÚzáAâzáAêzáAòzáAúzáB=qB=qB	=qB
+=qB=qB=qB=qB
+=qB!=qB%=qB)=qB-=qB1=qB5=qB9=qB==qBA=qBE=qBI=qBM=qBQ=qBU=qBY=qB]=qBa=qBe=qBi=qBm=qBq=qBu=qBy=qB}=q>?Šff@33@S33@@©@É@éAÌÍAÌÍA$ÌÍA4ÌÍADÌÍATÌÍAdÌÍAtÌÍAffAffAffAffA¢ffAªffA²ffAºffAÂffAÊffAÒffAÚffAâffAêffAòffAúffB33B33B	33B
+33B33B33B33B
+33B!33B%33B)33B-33B133B533B933B=33BA33BE33BI33BM33BQ33BU33BY33B]33Ba33Be33Bi33Bm33Bq33Bu33By33B}33>zá?¥
+ž@\@R\@G®@©G®@ÉG®@éG®A£×A£×A$£×A4£×AD£×AT£×Ad£×At£×AQìAQìAQìAQìA¢QìAªQìA²QìAºQìAÂQìAÊQìAÒQìAÚQìAâQìAêQìAòQìAúQìB(öB(öB	(öB
+(öB(öB(öB(öB
+(öB!(öB%(öB)(öB-(öB1(öB5(öB9(öB=(öBA(öBE(öBI(öBM(öBQ(öBU(öBY(öB](öBa(öBe(öBi(öBm(öBq(öBu(öBy(öB}(ö>\)?£×
+@ë
+@Që
+@õÃ@šõÃ@ÈõÃ@èõÃAzáAzáA$záA4záADzáATzáAdzáAtzáA=qA=qA=qA=qA¢=qAª=qA²=qAº=qAÂ=qAÊ=qAÒ=qAÚ=qAâ=qAê=qAò=qAú=qB
+žB
+žB	
+žB
+
+žB
+žB
+žB
+žB
+
+žB!
+žB%
+žB)
+žB-
+žB1
+žB5
+žB9
+žB=
+žBA
+žBE
+žBI
+žBM
+žBQ
+žBU
+žBY
+žB]
+žBa
+žBe
+žBi
+žBm
+žBq
+žBu
+žBy
+žB}
+ž>=q?¢\@G®@QG®@£×@š£×@È£×@è£×AQìAQìA$QìA4QìADQìATQìAdQìAtQìA(öA(öA(öA(öA¢(öAª(öA²(öAº(öAÂ(öAÊ(öAÒ(öAÚ(öAâ(öAê(öAò(öAú(öB{B{B	{B
+{B{B{B{B
+{B!{B%{B){B-{B1{B5{B9{B={BA{BE{BI{BM{BQ{BU{BY{B]{Ba{Be{Bi{Bm{Bq{Bu{By{B}{>
+
+ž?¡G®@£×@P£×@Qì@šQì@ÈQì@èQìA(öA(öA$(öA4(öAD(öAT(öAd(öAt(öA{A{A{A{A¢{Aª{A²{Aº{AÂ{AÊ{AÒ{AÚ{Aâ{Aê{Aò{Aú{B
+=B
+=B	
+=B
+=B
+=B
+=B
+=B
+
+=B!
+=B%
+=B)
+=B-
+=B1
+=B5
+=B9
+=B=
+=BA
+=BE
+=BI
+=BM
+=BQ
+=BU
+=BY
+=B]
+=Ba
+=Be
+=Bi
+=Bm
+=Bq
+=Bu
+=By
+=B}
+=>  ?   @  @P  @  @š  @È  @è  A  A  A$  A4  AD  AT  Ad  At  A  A  A  A  A¢  Aª  A²  Aº  AÂ  AÊ  AÒ  AÚ  Aâ  Aê  Aò  Aú  B  B  B	  B
+  B  B  B  B
+  B!  B%  B)  B-  B1  B5  B9  B=  BA  BE  BI  BM  BQ  BU  BY  B]  Ba  Be  Bi  Bm  Bq  Bu  By  B}  >uÂ?žR@\)@O\)@®@§®@Ç®@ç®A×
+A×
+A#×
+A3×
+AC×
+AS×
+Ac×
+As×
+Aë
+Aë
+Aë
+Aë
+A¡ë
+A©ë
+A±ë
+A¹ë
+AÁë
+AÉë
+AÑë
+AÙë
+Aáë
+Aéë
+Añë
+Aùë
+B õÃBõÃBõÃB
+õÃBõÃBõÃBõÃB
+õÃB õÃB$õÃB(õÃB,õÃB0õÃB4õÃB8õÃB<õÃB@õÃBDõÃBHõÃBLõÃBPõÃBTõÃBXõÃB\õÃB`õÃBdõÃBhõÃBlõÃBpõÃBtõÃBxõÃB|õÃ>k
+?p€@žR@NžR@\)@§\)@Ç\)@ç\)A®A®A#®A3®AC®AS®Ac®As®A×
+A×
+A×
+A×
+A¡×
+A©×
+A±×
+A¹×
+AÁ×
+AÉ×
+AÑ×
+AÙ×
+Aá×
+Aé×
+Añ×
+Aù×
+B ë
+Bë
+Bë
+B
+ë
+Bë
+Bë
+Bë
+B
+ë
+B ë
+B$ë
+B(ë
+B,ë
+B0ë
+B4ë
+B8ë
+B<ë
+B@ë
+BDë
+BHë
+BLë
+BPë
+BTë
+BXë
+B\ë
+B`ë
+Bdë
+Bhë
+Blë
+Bpë
+Btë
+Bxë
+B|ë
+>aG®?(ö@{@N{@
+=@§
+=@Ç
+=@ç
+=A
+A
+A#
+A3
+AC
+AS
+Ac
+As
+AÂAÂAÂAÂA¡ÂA©ÂA±ÂA¹ÂAÁÂAÉÂAÑÂAÙÂAáÂAéÂAñÂAùÂB áHBáHBáHB
+áHBáHBáHBáHB
+áHB áHB$áHB(áHB,áHB0áHB4áHB8áHB<áHB@áHBDáHBHáHBLáHBPáHBTáHBXáHB\áHB`áHBdáHBháHBláHBpáHBtáHBxáHB|áH>W
+=?áH@
+p€@Mp€@žR@ŠžR@ÆžR@æžRA\)A\)A#\)A3\)AC\)AS\)Ac\)As\)A®A®A®A®A¡®A©®A±®A¹®AÁ®AÉ®AÑ®AÙ®Aá®Aé®Añ®Aù®B ×
+B×
+B×
+B
+×
+B×
+B×
+B×
+B
+×
+B ×
+B$×
+B(×
+B,×
+B0×
+B4×
+B8×
+B<×
+B@×
+BD×
+BH×
+BL×
+BP×
+BT×
+BX×
+B\×
+B`×
+Bd×
+Bh×
+Bl×
+Bp×
+Bt×
+Bx×
+B|×
+>LÌÍ?@
+ÌÍ@LÌÍ@ff@Šff@Æff@æffA33A33A#33A333AC33AS33Ac33As33AAAAA¡A©A±A¹AÁAÉAÑAÙAáAéAñAùB ÌÍBÌÍBÌÍB
+ÌÍBÌÍBÌÍBÌÍB
+ÌÍB ÌÍB$ÌÍB(ÌÍB,ÌÍB0ÌÍB4ÌÍB8ÌÍB<ÌÍB@ÌÍBDÌÍBHÌÍBLÌÍBPÌÍBTÌÍBXÌÍB\ÌÍB`ÌÍBdÌÍBhÌÍBlÌÍBpÌÍBtÌÍBxÌÍB|ÌÍ>B\?Qì@
+(ö@L(ö@{@Š{@Æ{@æ{A
+=A
+=A#
+=A3
+=AC
+=AS
+=Ac
+=As
+=A
+A
+A
+A
+A¡
+A©
+A±
+A¹
+AÁ
+AÉ
+AÑ
+AÙ
+Aá
+Aé
+Añ
+Aù
+B ÂBÂBÂB
+ÂBÂBÂBÂB
+ÂB ÂB$ÂB(ÂB,ÂB0ÂB4ÂB8ÂB<ÂB@ÂBDÂBHÂBLÂBPÂBTÂBXÂB\ÂB`ÂBdÂBhÂBlÂBpÂBtÂBxÂB|Â>8Qì?
+>@
+
+@K
+@
+Â@¥Â@ÅÂ@åÂAáHAáHA"áHA2áHABáHARáHAbáHAráHAp€Ap€Ap€Ap€A¡p€A©p€A±p€A¹p€AÁp€AÉp€AÑp€AÙp€Aáp€Aép€Añp€Aùp€B žRBžRBžRB
+žRBžRBžRBžRB
+žRB žRB$žRB(žRB,žRB0žRB4žRB8žRB<žRB@žRBDžRBHžRBLžRBPžRBTžRBXžRB\žRB`žRBdžRBhžRBlžRBpžRBtžRBxžRB|žR>.{?Â@
+áH@JáH@
+p€@¥p€@Åp€@åp€AžRAžRA"žRA2žRABžRARžRAbžRAržRA\)A\)A\)A\)A¡\)A©\)A±\)A¹\)AÁ\)AÉ\)AÑ\)AÙ\)Aá\)Aé\)Añ\)Aù\)B ®B®B®B
+®B®B®B®B
+®B ®B$®B(®B,®B0®B4®B8®B<®B@®BD®BH®BL®BP®BT®BX®B\®B`®Bd®Bh®Bl®Bp®Bt®Bx®B|®>#×
+?zá@
+=q@J=q@
+
+ž@¥
+ž@Å
+ž@å
+žA\A\A"\A2\AB\AR\Ab\Ar\AG®AG®AG®AG®A¡G®A©G®A±G®A¹G®AÁG®AÉG®AÑG®AÙG®AáG®AéG®AñG®AùG®B £×B£×B£×B
+£×B£×B£×B£×B
+£×B £×B$£×B(£×B,£×B0£×B4£×B8£×B<£×B@£×BD£×BH£×BL£×BP£×BT£×BX£×B\£×B`£×Bd£×Bh£×Bl£×Bp£×Bt£×Bx£×B|£×>?33@	@I@ÌÍ@€ÌÍ@ÄÌÍ@äÌÍAffAffA"ffA2ffABffARffAbffArffA33A33A33A33A¡33A©33A±33A¹33AÁ33AÉ33AÑ33AÙ33Aá33Aé33Añ33Aù33B BBB
+BBBB
+B B$B(B,B0B4B8B<B@BDBHBLBPBTBXB\B`BdBhBlBpBtBxB|>\)?ë
+@õÃ@HõÃ@zá@€zá@Äzá@äzáA=qA=qA"=qA2=qAB=qAR=qAb=qAr=qA
+žA
+žA
+žA
+žA¡
+žA©
+žA±
+žA¹
+žAÁ
+žAÉ
+žAÑ
+žAÙ
+žAá
+žAé
+žAñ
+žAù
+žB \B\B\B
+\B\B\B\B
+\B \B$\B(\B,\B0\B4\B8\B<\B@\BD\BH\BL\BP\BT\BX\B\\B`\Bd\Bh\Bl\Bp\Bt\Bx\B|\>
+ž?£×@Qì@HQì@(ö@€(ö@Ä(ö@ä(öA{A{A"{A2{AB{AR{Ab{Ar{A
+=A
+=A
+=A
+=A¡
+=A©
+=A±
+=A¹
+=AÁ
+=AÉ
+=AÑ
+=AÙ
+=Aá
+=Aé
+=Añ
+=Aù
+=B 
+B
+B
+B
+
+B
+B
+B
+B
+
+B 
+B$
+B(
+B,
+B0
+B4
+B8
+B<
+B@
+BD
+BH
+BL
+BP
+BT
+BX
+B\
+B`
+Bd
+Bh
+Bl
+Bp
+Bt
+Bx
+B|
+=õÂ?\)@®@G®@×
+@£×
+@Ã×
+@ã×
+Aë
+Aë
+A!ë
+A1ë
+AAë
+AQë
+Aaë
+Aqë
+AõÃAõÃAõÃAõÃA õÃAšõÃA°õÃAžõÃAÀõÃAÈõÃAÐõÃAØõÃAàõÃAèõÃAðõÃAøõÃB záBzáBzáB
+záBzáBzáBzáB
+záB záB$záB(záB,záB0záB4záB8záB<záB@záBDzáBHzáBLzáBPzáBTzáBXzáB\záB`záBdzáBhzáBlzáBpzáBtzáBxzáB|zá=áG®?{@
+=@G
+=@
+@£
+@Ã
+@ã
+AÂAÂA!ÂA1ÂAAÂAQÂAaÂAqÂAáHAáHAáHAáHA áHAšáHA°áHAžáHAÀáHAÈáHAÐáHAØáHAàáHAèáHAðáHAøáHB p€Bp€Bp€B
+p€Bp€Bp€Bp€B
+p€B p€B$p€B(p€B,p€B0p€B4p€B8p€B<p€B@p€BDp€BHp€BLp€BPp€BTp€BXp€B\p€B`p€Bdp€Bhp€Blp€Bpp€Btp€Bxp€B|p€=ÌÌÍ?ÌÍ@ff@Fff@33@£33@Ã33@ã33AAA!A1AAAQAaAqAÌÍAÌÍAÌÍAÌÍA ÌÍAšÌÍA°ÌÍAžÌÍAÀÌÍAÈÌÍAÐÌÍAØÌÍAàÌÍAèÌÍAðÌÍAøÌÍB ffBffBffB
+ffBffBffBffB
+ffB ffB$ffB(ffB,ffB0ffB4ffB8ffB<ffB@ffBDffBHffBLffBPffBTffBXffB\ffB`ffBdffBhffBlffBpffBtffBxffB|ff=žQì?
+@Â@EÂ@áH@¢áH@ÂáH@âáHAp€Ap€A!p€A1p€AAp€AQp€Aap€Aqp€AžRAžRAžRAžRA žRAšžRA°žRAžžRAÀžRAÈžRAÐžRAØžRAàžRAèžRAðžRAøžRB \)B\)B\)B
+\)B\)B\)B\)B
+\)B \)B$\)B(\)B,\)B0\)B4\)B8\)B<\)B@\)BD\)BH\)BL\)BP\)BT\)BX\)B\\)B`\)Bd\)Bh\)Bl\)Bp\)Bt\)Bx\)B|\)=£×
+?=q@
+ž@E
+ž@\@¢\@Â\@â\AG®AG®A!G®A1G®AAG®AQG®AaG®AqG®A£×A£×A£×A£×A £×Aš£×A°£×Až£×AÀ£×AÈ£×AÐ£×AØ£×Aà£×Aè£×Að£×Aø£×B QìBQìBQìB
+QìBQìBQìBQìB
+QìB QìB$QìB(QìB,QìB0QìB4QìB8QìB<QìB@QìBDQìBHQìBLQìBPQìBTQìBXQìB\QìB`QìBdQìBhQìBlQìBpQìBtQìBxQìB|Qì=\)?õÃ@zá@Dzá@=q@¢=q@Â=q@â=qA
+žA
+žA!
+žA1
+žAA
+žAQ
+žAa
+žAq
+žA\A\A\A\A \Aš\A°\Až\AÀ\AÈ\AÐ\AØ\Aà\Aè\Að\Aø\B G®BG®BG®B
+G®BG®BG®BG®B
+G®B G®B$G®B(G®B,G®B0G®B4G®B8G®B<G®B@G®BDG®BHG®BLG®BPG®BTG®BXG®B\G®B`G®BdG®BhG®BlG®BpG®BtG®BxG®B|G®=uÂ?®@×
+@C×
+@ë
+@¡ë
+@Áë
+@áë
+A õÃAõÃA õÃA0õÃA@õÃAPõÃA`õÃApõÃAzáAzáAzáAzáA záAšzáA°záAžzáAÀzáAÈzáAÐzáAØzáAàzáAèzáAðzáAøzáB =qB=qB=qB
+=qB=qB=qB=qB
+=qB =qB$=qB(=qB,=qB0=qB4=qB8=qB<=qB@=qBD=qBH=qBL=qBP=qBT=qBX=qB\=qB`=qBd=qBh=qBl=qBp=qBt=qBx=qB|=q=LÌÍ?ff@33@C33@@¡@Á@áA ÌÍAÌÍA ÌÍA0ÌÍA@ÌÍAPÌÍA`ÌÍApÌÍAffAffAffAffA ffAšffA°ffAžffAÀffAÈffAÐffAØffAàffAèffAðffAøffB 33B33B33B
+33B33B33B33B
+33B 33B$33B(33B,33B033B433B833B<33B@33BD33BH33BL33BP33BT33BX33B\33B`33Bd33Bh33Bl33Bp33Bt33Bx33B|33=#×
+?
+
+ž@\@B\@G®@¡G®@ÁG®@áG®A £×A£×A £×A0£×A@£×AP£×A`£×Ap£×AQìAQìAQìAQìA QìAšQìA°QìAžQìAÀQìAÈQìAÐQìAØQìAàQìAèQìAðQìAøQìB (öB(öB(öB
+(öB(öB(öB(öB
+(öB (öB$(öB((öB,(öB0(öB4(öB8(öB<(öB@(öBD(öBH(öBL(öBP(öBT(öBX(öB\(öB`(öBd(öBh(öBl(öBp(öBt(öBx(öB|(ö<õÂ?×
+@ë
+@Aë
+@õÃ@ õÃ@ÀõÃ@àõÃA záAzáA záA0záA@záAPzáA`záApzáA=qA=qA=qA=qA =qAš=qA°=qAž=qAÀ=qAÈ=qAÐ=qAØ=qAà=qAè=qAð=qAø=qB 
+žB
+žB
+žB
+
+žB
+žB
+žB
+žB
+
+žB 
+žB$
+žB(
+žB,
+žB0
+žB4
+žB8
+žB<
+žB@
+žBD
+žBH
+žBL
+žBP
+žBT
+žBX
+žB\
+žB`
+žBd
+žBh
+žBl
+žBp
+žBt
+žBx
+žB|
+ž<£×
+?\@G®@AG®@£×@ £×@À£×@à£×A QìAQìA QìA0QìA@QìAPQìA`QìApQìA(öA(öA(öA(öA (öAš(öA°(öAž(öAÀ(öAÈ(öAÐ(öAØ(öAà(öAè(öAð(öAø(öB {B{B{B
+{B{B{B{B
+{B {B${B({B,{B0{B4{B8{B<{B@{BD{BH{BL{BP{BT{BX{B\{B`{Bd{Bh{Bl{Bp{Bt{Bx{B|{<#×
+?G®@ £×@@£×@Qì@ Qì@ÀQì@àQìA (öA(öA (öA0(öA@(öAP(öA`(öAp(öA{A{A{A{A {Aš{A°{Až{AÀ{AÈ{AÐ{AØ{Aà{Aè{Að{Aø{B 
+=B
+=B
+=B
+
+=B
+=B
+=B
+=B
+
+=B 
+=B$
+=B(
+=B,
+=B0
+=B4
+=B8
+=B<
+=B@
+=BD
+=BH
+=BL
+=BP
+=BT
+=BX
+=B\
+=B`
+=Bd
+=Bh
+=Bl
+=Bp
+=Bt
+=Bx
+=B|
+=    ?  @   @@  @  @   @À  @à  A   A  A   A0  A@  AP  A`  Ap  A  A  A  A  A   Aš  A°  Až  AÀ  AÈ  AÐ  AØ  Aà  Aè  Að  Aø  B   B  B  B
+  B  B  B  B
+  B   B$  B(  B,  B0  B4  B8  B<  B@  BD  BH  BL  BP  BT  BX  B\  B`  Bd  Bh  Bl  Bp  Bt  Bx  B|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?!1?)ì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+Æ?(þ?¯m®@ý¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?óô?$h,?­E@:@29Q@_¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?U"? É:?«ÎÌ@}@1Q@_«@]â@D¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?¶P?
+*h?©ÿb@ŽÈ@0ià@^
+ø@
+ê@Ä@³ @ÊB¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ??w?š/ê@Í
+@/#@]7;@
+v)@P¶@³+B@ÊÎ@ààZ@÷Œ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+x­?ì¥?Š`@ åX@.o@\O@
+O@ÜÜ@²·g@Éô@àl@÷G
+AÌAb|¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?ÙÚ?M³?€?ÿû6@-²²@[gÊ@q@hý@²C@É
+@ßø¡@öÓ.AÖÜAD"A
+±hA)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?;	?®á?¢Á?þ+Î@,Êþ@Z@@õ#@±Ï¯@Èª;@ßÈ@ö_TAðA
+5A
+wzA(äÀA4RA?£¶¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ? 7?
+? ò6?ü\e@+ãJ@Ya@Šœ@I@±[Õ@È6a@ßí@õëyAcAÐHA
+=A(ªÓA4A?
+^AJò€AVDT¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ùúÊ?q
+?"Ÿ?úì@*û@X°€@2Þ@
+j@°ç÷@ÇÂ@Þ@õwA)AYA
+A(päA3Þ*A?KoAJžŽAV%úAa@Aläð¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >òœ(?ÒL?SU?øœ@*Ù@WÈð@¿@@°t
+@ÇNš@Þ)5@õÁAï&A\lA
+É±A(6÷A3€<A?AJ~ÈAUì
+AaYRAlÆAx3ÞAÂÇ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ë? 3Z?Ü?öî
+@),
+@Vá4@K&@%³@° >@ÆÚÊ@ÝµV@ôâAµ7A"}A
+ÂA'ýA3jMA>×AJDØAU²
+AadAl©AwùîA³Aj=A¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >äAà>ù)?Žs?õ
+¢@(Dh@Uù@×L@±Ø@¯d@Æfñ@ÝA|@ô
+A{IAèA
+UÕA'ÃA30`A>ŠAJ
+ëAUx1A`åvAlRŒAwÀA€AMHAëAºAcf¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Ý<>ñë,?äú?óO)@'\¬@UÃ@cm@=ú@¯
+@Åó@ÜÍ@óš+AA[A® A
+åA'+A2öqA>c·AIÐüAU>BA`«AlÍAwAy­A0PAæóAAT:A
+ÜA£³µ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ÕÆ>ê­??ñÀ@&t÷@T*@ï@Ê@®€«@Å8@ÜYÃ@ó4PAnAt³AáùA'O>A2ŒA>)ÉAIAUUA`qAkÞàAwL%A\¶AYAÉýA A7CAíçA£€A©[,A¯¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Îõ>ão€?F?ï°G@%;@SBR@{µ@VA@®0Í@Å
+Y@Ûåå@òÀqAÍ~A:ÄAš
+A'OA2A=ïÚAI]ATÊeA`7«Ak€ñAw6A?ŸAöaA­AcšALAÐïA£A©>6A®ôÙAŽ«{AºTT¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ÇKQ>Ü2?v¯?íàÞ@$¥@RZ@Û@âg@­Œó@Ä@Ûr
+@òLAA ÖAn
+A&ÛbA2HšA=µíAI#3ATxA_ýœAkkAvØIA"ÈAÙkAAF±AýUA³øA£jA©!?A®×âAŽAºE)A¿ûËAÅ€€¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >À
+®>Ôô
+?§6?ìe@#œÊ@Qrá@'ù@n@­I@Ä#¡@Úþ-@ñØ¹AY¢AÆèA4-A&¡rA2žA={þAHéDATVA_ÃÏAk1AvYAÐAŒsAsA)ºAà]A A£M€A©GA®ºëAŽqAº(1A¿ÞÕAÅxAËLAÐôó¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >žÐ
+>Í¶z?×Î?êAü@"Ö@P-@~@E@ú®@¬Õ;@Ã¯Ç@ÚS@ñdßAµAúAú@A&gA1ÔËA=BAH¯VAT
+A_âAj÷'AvdmAèÚA}AV!A
+ÃAÃfAz
+A£0­AšçPA®ôAŽTAº
+;A¿ÁÞAÅxAË/%AÐåÈAÖjAÜEC¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >±f>Æx?U?èr@!îY@O£p@}X@Ð@¬a\@Ã;è@Úu@ðñAåÆAS
+AÀQA&-A1ÜA="AHugASâ¬A_OòAjœ8Av*~AËâAA9)AïÌAŠpA]A£µAšÊYA®üAŽ7A¹îCA¿€æAÅ[AË-AÐÈÐAÖtAÜ6Aáì¹Aç¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ªTÃ>¿:ó?8ì?æ£@!¥@N»»@|pÔ@ö@«í@ÂÈ@Ù¢@ð}&A«ÙAAdA%ó©A1`ïA<Î4AH;zASšÀA_AjJAuðA®ëAeA
+2AÒÖAyA@
+A¢öÀAš­bA®dAŽ©A¹ÑLA¿ïAÅ>AÊõ6AÐ«ÚAÖb}AÜ AáÏÄAçgAí=	Aòåâ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >£>·ý?is?äÓ¡@ 
+ç@MÓÿ@{@@«y€@ÂT0@Ù.Œ@ð	HAqéAß/ALuA%¹»A1' A<EAHASnÐA^ÜAjI\Au¶¡AôAHAÿ:AµÞAlA#%A¢ÙÈAškA®GA³ý±A¹ŽTA¿jøAÅ!AÊØ>AÐâAÖE
+AÛü)Aá²ÌAçioAí AòÖ¶AøXAþ61¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Ù|>°¿??ã@@77@LìN@z¡g@+@@«Ì@ÁàX@Øºä@ïpA7þA¥CAA%ÎA0íA<ZZAGÇAS4äA^¢*AjpAu|µAtýA+ AâDAçAOA.A¢ŒÑAšsuA®*A³à»A¹_A¿NAÅ€AÊ»HAÐqëAÖ(AÛß2AáÕAçLyAí
+Aò¹¿AøpcAþ'BîÕBÃA¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >×>©è?
+Ê©?á4×@
+O@L@y¹²@·f@ªñ@Ál~@ØG
+@ï!AþAkVAØA%EáA0³&A< lAG²ARúøA^h=AiÕAuBÈAXAªAÅMA{ðA2Aé7A¢ÚAšV~A®
+!A³ÃÅA¹zhA¿1
+AÄç¯AÊQAÐTôAÖ
+AÛÂ;AáxÞAç/Aìæ%AòÉAøSlAþ
+BàYB»«BýB
+ki¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >^4>¢DD?û@?ßen@
+gÎ@K
+å@xÑþ@C@ª
+@Àø€@×Ó/@î­ŒAÄ#A1iA®A%
+ôA0y:A;æAGSÄARÁ
+A^.PAiAuÛA;A
+ñŽAšWA^úAAÌ@A¢äAš9A­ð*A³ŠÎA¹]qA¿AÄÊžAÊ[AÐ7ÿAÕî¡AÛ¥DAá[èAçAìÉ.AòÒAø6uAýíBÑÞB­0BB
+cÓB
+?%B¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  > > ?+×?Ý@
+@J51@wêJ@Ï±@©ª=@ÀÉ@×_U@î9âA6A
+÷|AdÁA$ÒA0?LA;¬AGØAR
+A]ôbAiašAtÎîA
+A
+ÔœAaABAø§A¯JA¢eíAš
+A­Ó4A³×A¹@zAŸ÷
+AÄ­ÁAÊdeAÐAÕÑ«AÛOAá>ñAæõAì¬8AòbÛAø~AýÐ"BÃcBŽBzB
+UXB
+0©B
+ûBçMB»¹¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >}ÅØ>Èü?\n?ÛÆ@e@IM}@w@[×@©6c@Àï@Öë{@íÆAPIA
+œA*ÕA$A0_A;r¥AFßêARM0A]ºvAi'»At A#A
+·ÆAnjA%
+AÛ±ATA¢H÷A§ÿA­¶=A³làA¹#AŸÚ'AÄÊAÊGnAÏþAÕŽµAÛkXAá!ûAæØAìAAòEäA÷üAý³+BŽçB9BkB
+FÜB
+".BýBØÑBŽ#BuBcá¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >oJ>X?}
+?Ù÷3@°±@HeÈ@vá@çý@šÂ@¿@Öw¡@íR-A\A
+¡AðçA$^-A/ËsA;8žAF¥ýARCA]AhíÎAt[AÈYA
+ÐAQsAAŸºAu]A¢,A§â€A­GA³OêA¹AŸœ0AÄsÔAÊ*wAÏáAÕŸAÛNaAáAæ»šAìrKAò(ïA÷ßAý4BŠlBŸB]B
+8aB
+³BïBÊVB¥šBùB\KB
+7B!
+	¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >`ÏI>
+Mµ?y{8?Ø'Ë@Èý@G~@u3,@t"@šN®@¿);@ÖÆ@ìÞSAÜoA
+IµA¶úA$$?A/
+A:þËAFlAQÙVA]FAh³áAt!&AlA
+}ÙA4|Aë A¡ÃAXfA¢
+A§Å­A­|QA³2ôAžéAŸ :AÄVÝAÊ
+AÏÄ$AÕzÇAÛ1jAàèAæ±AìUUAò
+øA÷ÂAýy?BñBsBBNB
+)æB
+7BàB»ÛB,Br~BMÐB
+)!B!sB#ßÅB&Ž1¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >RT >|  ?uÜf?ÖXb@áH@F_@tKw@ H@§ÚÔ@Ÿµ`@Õì@ìjyA¢A
+ÇA}
+A#êSA/WA:ÄÝAF2#AQiA]
+¯AhyôAsç9ATA
+`ãAAÎ)AÌA;pA¡òA§š¶A­_ZA³ýAžÌ¡AŸDAÄ9çAÉðAÏ§-AÕ]ÐAÛtAàËAæºAì8^AñïA÷¥¥Aý\HBuBdÇB@B
+jB
+öŒBÒB­_B±BdB?TB
+ŠB õøB#ÑIB&¬B)íB,\Y¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >CØž>m€Ø?r=?Ôù@ù@E®«@scÃ@m@§fú@ŸA@Õ
+@ëöAhA
+ÕÚAC A#°eA/
+«A:ñAEø6AQe{A\ÒÁAh@As­MAA
+CìAúA±3AgÖA
+yA¡Õ
+A§ÀA­BcA²ùAž¯ªAŸfMAÄ
+ñAÉÓAÏ7AÕ@ÚAÚ÷}Aà® AædÄAìgAñÒ
+A÷®Aý?QBzúBVLB1B
+
+ïB
+èABÃBäBz6BUB0ÙB
+
++B ç|B#ÂÎB& B)yqB,TÃB/0B2¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >5]q>_)?nÃ?Ò¹@ß@DÆö@r|@@Šó@œÍ«@Ôš8@ëÄA.šA
+íA	3A#vxA.ãŸA:QAEŸIAQ+A\ÔAhAss_A~à¥A
+&öAÝA<AJàAA¡ž&A§nÉA­%lA²ÜAž³AŸIVAÃÿúAÉ¶AÏmAAÕ#äAÚÚAà*AæGÍAëþpAñµA÷k·Aý"ZBlBGÐB#"B	þtB
+ÙÅBµBiBkºBG
+B"^B
+ý¯B ÙB#ŽSB&€B)jöB,FHB/!B1üëB4Ø=B7¬©¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >&â)>P®?k ?Ðê/@*/@CßF@q^@€»@ŠG@œYÓ@Ô4_@ëëA ô»A
+bAÏGA#<A.©ÒA:AE]APñ¢A\^èAgÌ.As9sA~Š¹A
+
+ AÀ£AwGA-êAäA¡1A§QÔA­wA²¿AžuœAŸ,aAÃãAÉ§AÏPKAÕîAÚœAàt5Aæ*ØAëá{Añ
+A÷NÁAýeB^B9UB§B	ïøB
+ËJBŠBíB]?B8BâB
+ï4B ÊB#¥×B&)B)\{B,7ÌB/
+B1îpB4ÉÁB7¥B:eB=TÑ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >fâ>B3?ga
+?ÏŸ@Bv@B÷@p¬Š@0ß@Š
+k@Œå÷@ÓÀ@êA ºÍA
+(AXA#A.oäA9Ý)AEJoAP·ŽA\$úAg?Arÿ
+A~lÊAíA£¬AZOAòAÇA¡~9A§4ÜA¬ëA²¢#AžXÆAŸiAÃÆ
+AÉ|°AÏ3SAÔéöAÚ AàW=Aæ
+áAëÄAñ{'A÷1ÊAüèmBOB*ÚB,B	á}B
+ŒÏB BsrBNÄB*BgB
+à¹B Œ
+B#\B&r®B)MÿB,)QB/£B1ßôB4»FB7B:qéB=M;B@(BBüù¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >	ë>3·?cÂD?ÍKQ@ZÀ@B×@oÄï@œ@¥@Œr
+@ÓLš@ê'4A àA
+î%A[kA"È±A.5öA9£<AEAP}ÇA[ë
+AgXRArÅA~2ÝAÐAµA=XAóüAªA¡aBA§æA¬ÎA²
+,Až;ÐAœòsAÃ©AÉ_¹AÏ\AÔÍ AÚ£Aà:FAåðêAë§Añ^1A÷ÔAüËwBA
+B
+_B÷°B	ÓB
+®TB¥Bd÷B@HBBöìB
+Ò=B ­B#áB&d2B)?B,ÖB.ö'B1ÑyB4¬ËB7
+B:cnB=>ÀB@BBõcBEÐµBH¥!¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =öà©>%<3?`#k?Ë{ä@s	@A(!@nÝ9@I)@¥#Ž@»þ@@ÒØÍ@é³YA FòA
+Ž8A!}A"ÂA-üA9iNADÖAPCÙA[±Ag
+dArªA}øñA³
+AiŸA bA×AšA¡DLAŠúïA¬±A²h6Až
+ÙAœÕ|AÃ AÉBÃAÎùfAÔ°	AÚf¬Aà
+PAåÓóAëAñA:Aö÷ÝAü®B2B
+ãBé5B	ÄB
+ØB{*BV|B1ÍB
+BèpB
+ÃÂB B#zeB&U·B)1	B,
+ZB.ç¬B1ÂþB4OB7y¡B:TóB=0DB@
+BBæèBEÂ9BHBKxÝBNMI¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =Ùê>Àí?\?É¬{@U@@@l@mõ@ÕN@€¯Ú@»g@Òdò@é?~A 
+A
+zJAçA"TÖA-ÂA9/`ADŠAP	ìA[w1AfäwArQœA}¿A%ALÈAlAºAp²A¡'UAŠÝøA¬A²K?AžâAœžAÃo)AÉ%ÌAÎÜpAÔAÚI¶Aà YAå¶üAëm Añ$CAöÚæAüB$BÿhBÚºB	¶
+B
+]Bl¯BH B#RBþ€BÙõB
+µGB B#kêB&G<B)"B+ýßB.Ù1B1ŽB4ÔB7k&B:FwB=!ÉB?ýBBØlBE³ŸBHBKjaBNE³BQ!BSõq¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =Œó>E?XåÀ?ÇÝ@£@?X¶@m
+Î@as@€;ÿ@»@Ññ@èË€@ÿŠ0A
+@]A­¢A"èA-.A8õtADb¹AOÏþA[=DAfªArÏA}
+Ay.A/ÒAæuAASŒA¡
+^AŠÁA¬w¥A².HA·äìAœAÃR2AÉÖAÎ¿yAÔv
+AÚ,ÀAßãcAåAëP©AñLAöœðAütBBðíBÌ>B	§B
+âB^3B9
+B×Bð(BËzB
+ŠÌB 
+B#]oB&8ÀB)B+ïdB.ÊµB1ŠB4YB7\ªB:7üB=NB?îBBÉñBE¥CBHBK[æBN78BQBSíÛBVÉ-BY¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =ý=ó@?UFæ?Æ
+¡@»ç@>pÿ@l&@í@£È$@º¢°@Ñ}<@èWÈ@ÿ2SA
+oAsµA!àúA-N?A8»
+AD(ËAOA[VAfpAqÝáA}K'A\7AÚAÉ}A!A6ÄA ígAŠ€
+A¬Z­A²QA·ÇôAœ~AÃ5;AÈëÞAÎ¢AÔY%AÚÈAßÆkAå}Aë3²AðêUAö øAüWBBâpBœÂB	B
+teBO·B+	BZBá¬BŒþB
+OB s¡B#NóB&*DB)B+àçB.Œ9B1B4rÜB7N.B:)B=ÑB?à#BB»uBEÆBHrBKMjBN(»BQ
+BSß_BVº°BYB\qTB_EÀ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =t=Ö?Qš?Ä>6@Ô2@=I@k>a@yœ@£TH@º.Õ@Ñ	a@çãí@þŸyA
+ÌA9ÈA!§
+A-SA8ACîÝAO\#AZÉiAf6¯Aq£ôA}9A?@AõãA¬Ac*AÍA ÐqAŠA¬=·A±ô[A·ªýAœa¡AÃDAÈÎçAÎ
+AÔ<.AÙòÑAß©uAå`Aë»AðÍ_AöAü:¥B ø£BÓõB¯GB	B
+eêBA<B
+B÷ßBÓ1B®B
+ÔB e&B#@wB&ÉB(÷B+ÒlB.­ŸB1B4daB7?³B:B<öVB?ÑšBB¬ùBEKBHcBK>îBN@BPõBSÐãBV¬5BYB\bØB_>*Bb|Bdíè¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =LÍ=¹Šä?N	:?ÂnÌ@ì}@<¡@jV¬@â@¢ào@¹ºû@Ð@çp@þJA
+AÿÚA!m A,ÚfA8G«ACŽñAO"6AZ{AeüÁAqjA|×LA"IAØíAAF3Aü×A ³zAŠj
+A¬ ÁA±×dA·AœD«AÂûMAÈ±ñAÎhAÔ7AÙÕÛAß~AåC!AêùÅAð°hAög
+Aü
+¯B ê(BÅzB ÌB	|
+B
+WoB2ÀBBédBÄµB B
+{YB VªB#1üB&
+NB(èB+ÃñB.CB1zB4UæB717B:
+B<çÛB?Ã,BB~BEyÐBHU!BK0sBN
+ÅBPçBSÂhBVºBYy
+B\T]B_/¯Bb
+ BdæRBgÁ€Bj¿  ¿  ¿  ¿  ¿  ¿  =2³=°8?Jjd?À`@Ç@;¹ß@inö@@¢l@¹G@Ð!¬@æü8@ýÖÂA
+X§AÅíA!32A, wA8
+œAC{ANèHAZUAeÂÓAq0A|`ASA»öArA)=AßàA AŠM'A¬ÊA±ºmA·qAœ'ŽAÂÞWAÈûAÎKAÔAAÙžäAßoAå&+AêÜÎAðqAöJAü žB Û­B¶ÿBPB	m¢B
+HôB$EBÿBÚèB¶:BB
+lÝB H/B##B%þÒB(Ú$B+µvB.ÇB1lB4GkB7"ŒB9þB<Ù_B?Ž±BBBEkTBHFŠBK!øBMýIBPØBS³íBV>BYjB\EâB_!3Baü
+Bd××Bg³(BjzBmiÌBp>8¿  ¿  ¿  ¿  <°/=s4?FË?ŸÏø@
+
+@:Ò*@hB@
+-@¡ø¹@žÓE@Ï­Ñ@æ]@ýbèA
+
+¹AÿA ùEA,fA7ÓÐACAAN®[AZ¡AeæApö,A|csAè]A AU£A
+FAÂéA yAŠ00A«æÓA±wA·TAœ
+œAÂÁaAÈxAÎ.§AÓåKAÙíAßRAå	4Aê¿×Aðv{Aö-
+AûãÁB Í2BšBÕB	_'B
+:xBÊBñ
+BÌmB§¿BB
+^bB 9ŽB#B%ðWB(Ë©B+ŠúB.LB1]B48ïB7AB9ïB<ÊäB?Š6BBBE\ÙBH8+BK|BMîÎBPÊ BS¥qBVÃBY\B\7fB_žBaî
+BdÉ[Bg€­BjÿBm[PBp6¢BsôBuæ`¿  ¿  ;òÃë=E
+ê?C,œ?œ @
+5^@9êu@g@ªS@¡ß@ž_k@Ï9÷@æ@üïA	äÍARA ¿WA,,A7ãAC)ANtnAYá³AeNùApŒ?A|)
+AËfA	A8­AïPA¥óA \AŠ9A«ÉÝA±A·7#AŒíÇAÂ€jAÈ[
+AÎ±AÓÈTAÙ~÷Aß5Aäì=Aê¢áAðYAö'AûÆËB Ÿ·BBuZB	P«B
++ýBOBâ BœòBDBtB
+OçB +8B#B%áÜB(œ-B+B.sÑB1O"B4*tB7ÆB9áB<ŒiB?»BBs
+BEN^BH)¯BKBMàSBP»€BSöBVrHBYMB\(ëB_=BaßBdºàBg2BjqBmLÕBp('BsxBuÞÊBxº
+B{    =
+??è?»1"@
+Mš@9¿@f·×@6x@¡@·ë@ÎÆ
+@å š@ü{4A	ªàA%A 
+kA+ò°A7_õABÍ;AN:AY§ÇAe
+ApQA{ïA®oAeA¶AÒYAýA ? A¥öCA«¬æA±cA·-AŒÐÐAÂsAÈ>AÍôºAÓ«]AÙbAß€AäÏGAê
+ëAð<Aõó1Aû©ÔB °;BBfßB	B0B
+
+BøÓBÔ%B¯wBÈBfB
+AlB 
+œB"øB%Ó`B(®²B+B.eUB1@§B4ùB6÷JB9ÒB<­îB??BBdBE?ãBH4BJöBMÑ×BP­)BS{BVcÌBY?
+B\pB^õÁBaÑBd¬eBg¶BjcBm>ZBp«BrôýBuÐOBx« B{òB~bD¿  ?=š\?¹a·@
+eó@8
+@eÐ"@Â@ *@·w¶@ÎRB@å,Î@üZA	pòAÞ8A K~A+žÃA7&	ABNAN AYmÙAdÛApHeA{µ«AyAH
+Aþ¿AµcAlA "©A¥ÙMA«ðA±FA¶ý6AŒ³ÙAÂj}AÈ! AÍ×ÃAÓgAÙE
+AÞû­Aä²QAêhôAðAõÖ;AûÝB ¡ÀB}BXcB	3µB
+BêXBÅªB ûB|MBWB
+2ðB BB"éB%ÄåB( 7B+{B.VÚB12,B4
+}B6èÏB9Ä!B<rB?zÄBBVBE1gBH
+¹BJè
+BMÃ\BP®BSyÿBVUQBY0£B\
+ôB^çFBaÂBdéBgy;BjTBm/ÞBp
+0BræBuÁÓBx%B{xwB~SÈB~}¿  ¿  @	ì@73U@dèl@NÂ@ )N@·Û@ÍÞg@äžó@û~A	7A€JA A+~ÕA6ìABY`AMÆŠAY3ëAd¡0ApvA{{ŒAtA+$AáÈAkAOA ²A¥ŒUA«røA±)A¶à?AŒâAÂM
+AÈ(AÍºÌAÓqoAÙ(AÞÞ¶AäYAêKüAð Aõ¹CAûoæB EBnBIèB	%:B
+ BÛÝB·/BBmÒBI#B
+$uBÿÇB"ÛB%¶jB(ŒB+m
+B.H_B1#°B3ÿB6ÚTB9µ¥B<÷B?lIBBGBE"ìBGþ>BJÙBMŽáBP3BSkBVFÖBY"'B[ýyB^ØËBaŽ
+BdnBgjÀBjFBm!cBoüµBrØBu³XBxªB{iûB~EMB~o¿  ¿  ¿  ¿  @do
+@Úè@µt@¶ @Íj@äE@û£AýAj]A×£A+DèA6²-ABsAM¹AXùþAdgDAoÔA{AÏAWA.AÄÑA{tA2Aè»A¥^A«VA±
+¥A¶ÃHAŒyìAÂ0AÇç2AÍÕAÓTxAÙ
+
+AÞÁ¿AäxbAê/Aïå©AõLAûRðB ÉB`B;mB	ŸB
+òBÍbBš³BB_WB:šB
+úBñKB"ÌB%§ïB(@B+^B.9äB15B3ðB6ËØB9§*B<|B?]ÍBB9BEqBGïÂBJËBMŠfBP·BS]	BV8[BY¬B[îþB^ÊOBa¥¡BdóBg\DBj7BmèBoî9BrÉBu€ÝBx.B{[B~6ÒB~`¿  ¿  ¿  ¿  ¿  ¿  @xÂ@¶
+%@Ìö±@ãÑ=@ú«ÊAÃ*A0pAµA+
+ûA6xAAAåAMRËAXÀAd-WAoA{âA:Añ8A§ÛA^~A!AËÄA¥hA«9
+A°ï®A¶ŠRAŒ\õAÂAÇÊ<AÍßAÓ7AØî%AÞ€ÈAä[lAêAïÈ²AõVAû5ùB vNBQ B,ñB	CB
+ãBŸæB8BuBPÛB,-B
+BâÐB"Ÿ"B%sB(tÅB+PB.+hB1ºB3â
+B6œ]B9¯B<t B?ORBB*€BEõBGáGBJŒBMêBPs<BSNBV)ßBY1B[àB^»ÔBa&BdrwBgMÉBj)BmlBoßŸBr»BuaBxq³B{MB~(VB~R¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @Ìº @ã]c@ú7ïA=AöAcÈA*ÑA6>SAA«AMßAX$AcóiAo`¯AzÍõA
+AÔAAäAAAø+A®ÎA¥eqA«
+A°ÒžA¶[AŒ?þAÁö¢AÇ­EAÍcèAÓAØÑ/AÞÒAä>uAéõAï«ŒAõb_AûB gÓBC$B
+vBùÈB
+ÕB°kBœBgBB`B
+²B
+ùBÔUB"¯§B%øB(fJB+AB.
+íB0ø?B3ÓB6®âB94B<e
+B?@×BB
+(BD÷zBGÒÌBJ®
+BMoBPdÁBS@BVdBXö¶B[ÒB^­YBa«BdcüBg?NBjBlõñBoÑCBr¬BuæBxc8B{>B~ÛB~C¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @ùû<AOOAŒA)ÚA* A6eAAq«ALÞðAXL6Ac¹|Ao&ÁAzA §A·JAmîA$AÛ4AØA¥H{Aªÿ
+A°µÁA¶ldAŒ#AÁÙ«AÇNAÍFòAÒýAØŽ8AÞjÜAä!AéØ"AïÅAõEhAúü
+B YXB4ªBûBëLB
+ÆB¡ðB}ABXB3åB6B
+êBÅÚB"¡+B%|}B(WÏB+3 B.rB0éÃB3ÅB6 gB9{žB<W
+B?2\BB
+­BDèÿBGÄPBJ¢BMzôBPVEBS1BV
+éBXè:B[ÃB^ÞBaz/BdUBg0ÓBj
+$BlçvBoÂÇBrBuykBxTŒB{0B~
+`B~5 ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A<A
+ïíA*]3A5ÊxAA7ŸAL¥AXIAcAnìÔAzZAã°ATAP÷AAŸ>AtáA¥+Aªâ(A°ËA¶OnAŒAÁŒŽAÇsXAÍ)ûAÒàAØBAÞMåAäAé»,AïqÏAõ(rAúßB JÜB&.BBÜÒB
+ž#BtBnÆBJB%iB »B
+Ü
+B·^B"°B%nB(ISB+$¥B-ÿ÷B0ÛHB3¶B6ëB9m=B<HB?#àBAÿ2BDÚBGµÕBJ'BMlxBPGÊBS#
+BUþmBXÙ¿B[µB^bBakŽBdGBg"WBiý©BlØûBoŽLBrBujïBxFAB{!B}üäB~&¥¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A*>ÚA5A@ýÑALkAWØ\AcE¡An²çAz .AÆ¹A}]A4 Aê€A¡GAWêA¥AªÅ1A°{ÔA¶2xA»éAÁŸAÇVaAÍ
+AÒÃšAØzKAÞ0îAãçAé5AïTØAõ
+|AúÂB <aB³BóBÎVB
+©šBúB`KB;BîBò@B
+ÍBšãB"5B%_B(:ØB+*B-ñ{B0ÌÍB3šB6pB9^ÂB<:B?eBAð·BDÌBG§ZBJ«BM]ýBP9OBS BUïòBXËDB[ŠB^çBa]9Bd8BgÜBiï.BlÊBo¥ÑBr#Bu\tBx7ÆB{B}îiB~*¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A@ßwAL1(AWnAc
+³AnxùAyæ>A©ÃA`fAAÍ¬AOA:óA€ñAªš9A°^ÝA¶A»Ì#AÁÇAÇ9jAÌð
+AÒŠ°AØ]SAÞ÷AãÊAé=Aï7áAôîAú¥'B -äB	6BäB¿ÚB
+,Bv}BQÏB-!BrBãÃB
+¿BgB"užB%Q
+B(,\B+­B-âÿB0ŸQB3¢B6tôB9PFB<+B?éBAâ:BDœBGÞBJt/BMOBP*ÒBS$BUávBXŒÇB[B^skBaNŒBd*Bg`Bià±BlŒBoUBrrŠBuMøBx)JB{B}ßíB~	®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AWAbÑÆAn?
+Ay¬QAÌACoAúA°¶AgXA
+üA€ÔAªCA°AæAµøA»¯-AÁeÐAÇ
+sAÌÓAÒºAØ@]AÝ÷ Aã­£AédGAïêAôÑAú0B iBú»BÖ
+B±^B
+°BhBCTB
+¥Bù÷BÕIB
+°BëB"g=B%BB(
+àB*ù2B-ÔB0¯ÕB3'B6fyB9AÊB<
+
+B>ønBAÓ¿BD¯BGbBJeŽBMABP
+WBR÷©BUÒúBX®LB[B^dïBa@ABdBföäBiÒ6Bl­BoÙBrd+Bu?}BxÎBzö B}ÑrB}û3¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  An ²AyrdAoÕA&yAÝ
+A¿AJcAA€·šAªnLA°$ïAµÛA»6AÁHÙAÆÿ}AÌ¶ AÒlÃAØ#gAÝÚ
+Aã­AéGPAîýóAôŽAúk:B îBì?BÇB¢ãB
+~4BYB4ØB*Bë|BÆÍB
+¢B}qB"XÂB%4B(eB*ê·B-ÆB0¡ZB3|¬B6WýB93OB<¡B>éòBAÅDBD BG{çBJW9BM2BP
+ÜBRé.BUÄBXÑB[{"B^VtBa1ÆBd
+BfèiBiÃ»Bl
+Boz^BrU°Bu1Bx
+SBzç¥B}ÂöB}ìž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A`©A	AÀ%AvÉA-lAäA€³AªQVA°øAµŸA»u?AÁ+ãAÆâAÌ)AÒOÍAØpAÝœAãs·Aé*ZAîàýAô AúNCB sBÝÅB¹BgB
+o¹BK
+B&\B®BÝ BžRB
+€BnõB"JGB%%B( êB*Ü;B-·B0ßB3n0B6IB9$ÔB< %B>ÛwBA¶ÉBDBGmlBJHŸBM$BOÿaBRÚ²BU¶BXVB[l§B^GùBa#JBcþBfÙîBiµ?BlBokãBrG4Bu"BwýØBzÙ)B}Ž{B}Þ=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A°ùAYÒAuAÇA€}ŒAª4_A¯ëAµ¡ŠA»XHAÁìAÆÅAÌ|3AÒ2ÖA×éyAÝ 
+AãVÀAé
+cAîÄAôzªAú1MAÿçïBÏIBªB
+íB
+a>B<BáBó3BÎB©ÖB
+
+(B`zB";ÌB%
+B'òoB*ÍÁB-©B0cB3_µB6;B9XB;ñªB>ÌüBAšMBDBG^ñBJ:BBMBOðæBRÌ7BU§BXÚB[^,B^9~BaÏBcð!BfËrBiŠÄBlBo]gBr8¹Bu
+Bwï\BzÊ®B}Š B}ÏÁ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AIAª"A€`ÅAªiA¯Î
+Aµ¯A»;SAÀñöAÆšAÌ_<AÒßA×ÌAÝ&Aã9ÉAèðmAî§Aô]³AúWAÿÊøBÀÎB BwqB
+RÃB.B	fBä·BÀ	B[B
+v¬BQþB"-PB%¢B'ãôB*¿EB-B0uéB3Q:B6,B9ÝB;ã/B>ŸBAÒBDu$BGPuBJ+ÇBMBOâjBRœŒBUBXt_B[O±B^+BaTBcáŠBfŒ÷BiIBlsBoNìBr*>BuBwàáBzŒ3B}B}ÁF¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A€QA©úrA¯±Aµg¹A»
+\AÀÔÿAÆ£AÌBFAÑøèA×¯AÝf/Aã
+ÓAèÓvAîAô@œAù÷`Aÿ®B²SB€BhöB
+DHBBúëBÖ=B±BßB
+h1BCB"
+ÔB$ú&B'ÕxB*°ÊB-
+B0gmB3B¿B6
+B8ùbB;Ô³B>°BAWBDfšBGAúBJ
+LBLøBOÓïBR¯ABUBXeäB[A6B^
+B`÷ÙBcÓ*Bf®|BiÎBleBo@qBrÂBt÷BwÒfBz­·B}	B}²Ë¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A¯¡éAµJÂA»eAÀž	AÆn¬AÌ%OAÑÛóA×AÝI8AâÿÜAè¶Aîm#Aô#ÆAùÚiAÿ
+B£×B)BZ{B
+5ÌB
+BìpBÇÁB£B~eB
+Y¶B5B"YB$ë«B'ÆüB*¢NB-} B0XòB34DB6B8êçB;Æ9B>¡BA|ÛBDX-BG3BJÐBLê"BOÅtBR ÅBU|BXWiB[2ºB^
+B`é^BcÄ¯Bf Bi{RBlV€Bo1öBr
+GBtèBwÃêBz<B}zB}€O¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aºò9AÀAÆQµAÌYAÑŸüA×uAÝ,CAââæAèAîP,AôÏAùœsAÿtB\Bp®BKÿB
+'QB£BÝôB¹FBBoéB
+K;B&B"ÞB$Ý/B'žB*ÓB-o$B0JvB3%ÈB6B8ÜlB;·œB>BAnaBDI²BG%BJ UBLÛ§BO¶øBRJBUmBXHíB[$?B]ÿB`ÚâBc¶4BfBil×BlH)Bo#zBqþÌBtÚ
+BwµoBzÁB}lB}Ô¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÆBAËëbAÑ¢A×X©AÝLAâÅïAè|Aî36AóéØAù |AÿWBáBb3B=B
+ÖB
+ô'BÏyBªËB
+BanB
+<ÀBB!ócB$ÎµB'ªB*
+WB-`©B0;ûB3LB5òB8ÍðB;©BB>BA_åBD;7BGBIñÚBLÍ+BOš}BRÏBU_ BX:rB[ÄB]ñB`ÌgBc§¹Bf
+Bi^\Bl9®BoÿBqðQBtË¢BwŠôBzFB}]B}Y¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÑÙA×;²AÜòUAâšùAè_Aî?AóÌãAùAÿ:'BxfBS·B/	B
+
+[B
+å¬BÀþBOBw¡BRóB
+.DB	B!äèB$À9B'B*vÝB-R.B0-B3ÑB5ä#B8¿tB;ÆB>vBAQjBD,ŒBG
+BIã_BLŸ±BOBRuSBUP¥BX+÷B[HB]âB`œìBc=BftBiOáBl+2BoBqáÖBtœ'BwyBzsÊB}O
+B}xÞ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÜã)AâAèB¥AíùIAó¯ìAùfAÿ
+1BiêBE<B B
+ûßB
+×1B²BÔBi&BDwB
+ÉB
+ûB!ÖlB$±ŸB'B*haB-C³B0B2úVB5Õ§B8°ùB;KB>gBABîBD
+@BFùBIÔäBL°5BOBRfÙBUB*BX
+{BZøÍB]ÔB`¯pBcÂBffBiAeBl
+·Bnø	BqÓZBt®¬BwþBzeOB}@¡B}jb¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aè3yAíÜRAóõAùIAÿ ;B[oB6ÁBB
+ídB
+È¶B€BYBZ«B5üB
+NB
+ìB!ÇñB$£CB'~B*YæB-58B0B2ëÛB5Ç-B8¢~B;}ÏB>Y!BA4sBDÄBFëBIÆhBL¡ºBO}
+BRX]BU3¯BXBZêRB]Å£B` õBc|GBfWBi2êBl<BnéBqÄßBt 1Bw{BzVÔB}2&B}[ç¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AóÉAù,¢AþãDBLôB(EBB
+ÞéB
+º:BBpÞBL/B'B
+ÓB
+Þ$B!¹vB$ÇB'pB*KkB-&ŒB0B2Ý`B5ž±B8B;oUB>JŠBA%÷BDIBFÜBI·ìBL>BOnBRIâBU%4BX 
+BZÛ×B]·)B`zBcmËBfI
+Bi$oBkÿÀBnÛBq¶dBtµBwmBzHYB}#ªB}Ml¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AþÔB>xBÊBõ
+B
+ÐmB
+«¿BBbbB=ŽBBôWB
+Ï©B!ªûB$LB'aB*<ïB-AB/óB2ÎäB5ª6B8
+B;`ÙB><+BA}BCòÎBFÎBI©qBLÃBO`BR;fBUžBWò
+BZÍ\B]š­B`ÿBc_QBf:¢BióBkñEBnÌBq§èBt:Bw^Bz9ÝB}/B}>ñ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B4Bæ B
+ÁòB
+DBxBSçB/9B
+BåÜB
+Á.B!B$wÑB'S#B*.tB-	ÆB/åB2ÀiB5»B8w
+B;R^B>-°BA	BCäSBF¿¥BIöBLvGBOQBR,ëBU<BWãBZŸàB]2B`uBcPÕBf,'BiyBkâÊBnŸBqmBtt¿BwPBz+bB}ŽB}0u¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+º\B
+ÈBjBElB œBüB×aB
+²²B!B$iVB'D§B*ùB,ûKB/ÖB2±îB5?B8hB;CãB>4B@úBCÕØBF±)BI{BLgÍBOC
+BR
+oBTùÁBWÕBZ°dB]¶B`gBcBZBf
+¬BhøýBkÔOBn¯¡BqòBtfCBwABz
+çB|ø8B}!ú¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BbB6ïBABíBÈäB
+€6B!B$ZÙB'6+B*}B,ìÎB/È B2£rB5~ÃB8ZB;5fB>žB@ì
+BCÇ[BF¢­BI}ÿBLYPBO4¢BRôBTëEBWÆBZ¡èB]}:B`XBc3ÝBf/BhêBkÅÓBn¡$Bq|vBtWÈBw3BzjB|éŒB}¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+«BßBºiB
+»B!q
+B$L^B''°B*B,ÞSB/¹¥B2öB5pHB8KB;&ëB>=B@ÝBCžàBF2BIoBLJÕBO&'BRxBTÜÊBWž
+BZmB]nŸB`JBc%bBf ³BhÜBk·WBn©BqmûBtILBw$ByÿðB|ÛAB}¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B²ÓB
+?B!bB$=ãB'4B)ôB,ÏØB/«)B2{B5aÍB8=
+B;pB=óÂB@ÏBCªeBF
+¶BIaBL<ZBO«BQòýBTÎOBW© BZòB]`DB`;BcæBeò8BhÍBkšÛBn-Bq_Bt:ÑBw#ByñtB|ÌÆB|ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B!ZûB$/gB'
+¹B)æ
+B,Á\B/®B2x B5SQB8.£B;	õB=åFB@ÀBCêBFw;BIRBL-ÞBO	0BQäBT¿ÓBW%BZvwB]QÈB`-BclBeãœBh¿Bk`Bnu²BqQBt,UBw§ByâùB|ŸKB|è
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B'#B)×B,²áB/3B2iB5DÖB8 (B:ûyB=ÖËB@²
+BCnBFhÀBIDBLcBNúµBQÖBT±XBWªBZgûB]CMB`
+BbùðBeÕBBh°BkåBng6BqBBt
+ÚBvù+ByÔ}B|¯ÏB|Ù¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B,«JB/¶B2[B56ZB8«B:ìýB=ÈOB@£ BC~òBFZDBI5BLçBNì9BQÇBT¢ÜBW~-BZYB]4ÑB`"BbëtBeÆÆBh¢Bk}iBnX»Bq4
+Bt]Bvê¯ByÆB|¡RB|Ë¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B2SrB5'ÞB80B:ÞB=¹ÓB@%BCpwBFKÈBI'BLlBNÝœBQ¹BTaBWo²BZKB]&UB`§BbÜùBežJBhBknîBnJ?Bq%Bt ãBvÜ4By·
+B|×B|Œ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B7ûB:ÐB=«XB@ªBCaûBF=MBIBKóðBNÏBBQªBT
+åBWa7BZ<B]ÚB_ó,BbÎ}Be©ÏBh
+!Bk`rBn;ÄBqBsògBvÍ¹By©
+B|\B|®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B=£ÂB@x.BCSBF.ÒBI
+#BKåuBNÀÇBQBTwjBWRŒBZ.
+B]	_B_ä±BbÀBeTBhv¥BkQ÷Bn-IBqBsãìBv¿>ByB|uáB|¥¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BCKéBF UBHû§BKÖùBN²JBQBThîBWD?BZB\úãB_Ö4Bb±BeØBhh)BkC{Bn
+ÌBpú
+BsÕpBv°ÁByB|geB|)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BHôBKÈ}BN£ÏBQ!BTZrBW5ÄBZB\ìgB_Ç¹Bb£
+Be~\BhY®Bk5 BnQBpë£BsÆôBv¢FBy}B|XéB|®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BN9BQp¥BTK÷BW'IBZB\ÝìB_¹>BbBeoáBhK3Bk&BnÖBpÝ(BsžyBvËByo
+B|JnB|t3¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BTDaBWÍBYôB\ÏqB_ªÂBbBeafBh<·Bk	Bmó[BpÎ¬Bs©þBv
+PBy`¡B|;óB|e·¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BYìB\ÀôB_FBbwBeRéBh.;Bk	BmäÞBpÀ0BsBvvÓByR%B|-wB|W<¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B_°Bbi
+BeDnBhÀBjûBmÖcBp±µBsBvhXByCªB|
+ûB|HÁ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Be<ØBhDBjìBmÇèBp£9Bs~BvYÝBy5.B|B|:F¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bjå Bm¹lBpŸBspBvKaBy&³B|B|+Ê¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bp'BsaBv<åBy7B{óB|
+O¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bv5OBy	»B{å
+B|Ô¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B{ÝwB| X¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 <#×
+<£×
+<õÂ=#×
+=LÌÍ=uÂ=\)=£×
+=žQì=ÌÌÍ=áG®=õÂ>
+ž>\)>>#×
+>.{>8Qì>B\>LÌÍ>W
+=>aG®>k
+>uÂ>  >
+
+ž>=q>\)>zá>>žR>£×
+>šõÃ>®{>³33>žQì>œp€>Â\>Ç®>ÌÌÍ>Ñë
+>×
+=>Ü(ö>áG®>æff>ë
+>ð£×>õÂ>úáH?   ?\?
+ž?®?
+=q?
+ÌÍ?\)?ë
+?zá?
+=??
+(ö?
+žR?!G®?  ?G®?\?×
+?
+
+ž?ff?®?õÃ?=q?
+?ÌÍ?{?\)?£×?ë
+?33?zá?Â?
+>?Qì??áH?(ö?p€?žR?   ?¡G®?¢\?£×
+?¥
+ž?Šff?§®?šõÂ?ª=q?«
+?¬ÌÍ?®{?¯\)?°£×?±ë
+?³33?Žzá?µÂ?·
+>?žQì?¹?ºáH?Œ(ö?œp€?ŸžR?À  ?ÁG®?Â\?Ã×
+?Å
+ž?Æff?Ç®?ÈõÂ?Ê=p?Ë
+
+?ÌÌÍ?Î{?Ï\)?Ð£×@   @ £×@G®@ë
+@\@33@×
+@zá@
+ž@Â@ff@
+=@®@Qì@õÃ@	@
+=q@
+áH@
+
+@
+(ö@
+ÌÍ@
+p€@{@žR@\)@  @£×@G®@ë
+@\@33@×
+@zá@
+ž@Â@ff@
+>@®@Qì@õÂ@@=q@áH@
+@
+(ö@
+ÌÍ@
+p€@
+{@
+žR@\)@   @ £×@!G®@!ë
+@"\@#33@#×
+@$zá@%
+ž@%Â@&ff@'
+>@'®@(Qì@@  @@£×@AG®@Aë
+@B\@C33@C×
+@Dzá@E
+ž@EÂ@Fff@G
+=@G®@HQì@HõÃ@I@J=q@JáH@K
+@L(ö@LÌÍ@Mp€@N{@NžR@O\)@P  @P£×@QG®@Që
+@R\@S33@S×
+@Tzá@U
+ž@UÂ@Vff@W
+>@W®@XQì@XõÂ@Y@Z=q@ZáH@[
+@\(ö@\ÌÍ@]p€@^{@^žR@_\)@`  @`£×@aG®@aë
+@b\@c33@c×
+@dzá@e
+ž@eÂ@fff@g
+>@g®@hQì@  @Qì@£×@õÃ@G®@@ë
+@=q@\@áH@33@
+@×
+@(ö@zá@ÌÍ@
+
+ž@
+p€@
+Â@{@ff@žR@
+=@\)@®@  @Qì@£×@õÃ@G®@@ë
+@=q@\@áH@33@
+@×
+@(ö@zá@ÌÍ@
+ž@p€@Â@{@ff@žR@
+=@\)@®@  @Qì@£×@õÂ@G®@@ë
+@=q@\@áH@33@
+@×
+@(ö@   @ Qì@ £×@ õÃ@¡G®@¡@¡ë
+@¢=q@¢\@¢áH@£33@£
+@£×
+@€(ö@€zá@€ÌÍ@¥
+ž@¥p€@¥Â@Š{@Šff@ŠžR@§
+=@§\)@§®@š  @šQì@š£×@šõÃ@©G®@©@©ë
+@ª=q@ª\@ªáH@«33@«
+@«×
+@¬(ö@¬zá@¬ÌÍ@­
+ž@­p€@­Â@®{@®ff@®žR@¯
+=@¯\)@¯®@°  @°Qì@°£×@°õÂ@±G®@±@±ë
+@²=q@²\@²áH@³33@³
+@³×
+@Ž(ö@À  @ÀQì@À£×@ÀõÃ@ÁG®@Á@Áë
+@Â=q@Â\@ÂáH@Ã33@Ã
+@Ã×
+@Ä(ö@Äzá@ÄÌÍ@Å
+ž@Åp€@ÅÂ@Æ{@Æff@ÆžR@Ç
+=@Ç\)@Ç®@È  @ÈQì@È£×@ÈõÃ@ÉG®@É@Éë
+@Ê=q@Ê\@ÊáH@Ë33@Ë
+@Ë×
+@Ì(ö@Ìzá@ÌÌÍ@Í
+ž@Íp€@ÍÂ@Î{@Îff@ÎžR@Ï
+=@Ï\)@Ï®@Ð  @ÐQì@Ð£×@ÐõÂ@ÑG®@Ñ@Ñë
+@Ò=q@Ò\@ÒáH@Ó33@Ó
+@Ó×
+@Ô(ö@à  @àQì@à£×@àõÃ@áG®@á@áë
+@â=q@â\@âáH@ã33@ã
+@ã×
+@ä(ö@äzá@äÌÍ@å
+ž@åp€@åÂ@æ{@æff@æžR@ç
+=@ç\)@ç®@è  @èQì@è£×@èõÃ@éG®@é@éë
+@ê=q@ê\@êáH@ë33@ë
+@ë×
+@ì(ö@ìzá@ìÌÍ@í
+ž@íp€@íÂ@î{@îff@îžR@ï
+=@ï\)@ï®@ð  @ðQì@ð£×@ðõÂ@ñG®@ñ@ñë
+@ò=q@ò\@òáH@ó33@ó
+@ó×
+@ô(öA   A (öA QìA záA £×A ÌÍA õÃA
+žAG®Ap€AAÂAë
+A{A=qAffA\AžRAáHA
+=A33A\)A
+A®A×
+A  A(öAQìAzáA£×AÌÍAõÃA
+žAG®Ap€AAÂAë
+A{A=qAffA\AžRAáHA
+=A33A\)A
+A®A×
+A  A(öAQìAzáA£×AÌÍAõÃA	
+žA	G®A	p€A	A	ÂA	ë
+A
+{A  A(öAQìAzáA£×AÌÍAõÃA
+žAG®Ap€AAÂAë
+A{A=qAffA\AžRAáHA
+=A33A\)A
+A®A×
+A  A(öAQìAzáA£×AÌÍAõÃA
+žAG®Ap€AAÂAë
+A{A=qAffA\AžRAáHA
+=A33A\)A
+A®A×
+A  A(öAQìAzáA£×AÌÍAõÃA
+žAG®Ap€AAÂAë
+A{A   A (öA QìA záA £×A ÌÍA õÃA!
+žA!G®A!p€A!A!ÂA!ë
+A"{A"=qA"ffA"\A"žRA"áHA#
+=A#33A#\)A#
+A#®A#×
+A$  A$(öA$QìA$záA$£×A$ÌÍA$õÃA%
+žA%G®A%p€A%A%ÂA%ë
+A&{A&=qA&ffA&\A&žRA&áHA'
+=A'33A'\)A'
+A'®A'×
+A(  A((öA(QìA(záA(£×A(ÌÍA(õÃA)
+žA)G®A)p€A)A)ÂA)ë
+A*{A0  A0(öA0QìA0záA0£×A0ÌÍA0õÃA1
+žA1G®A1p€A1A1ÂA1ë
+A2{A2=qA2ffA2\A2žRA2áHA3
+=A333A3\)A3
+A3®A3×
+A4  A4(öA4QìA4záA4£×A4ÌÍA4õÃA5
+žA5G®A5p€A5A5ÂA5ë
+A6{A6=qA6ffA6\A6žRA6áHA7
+=A733A7\)A7
+A7®A7×
+A8  A8(öA8QìA8záA8£×A8ÌÍA8õÃA9
+žA9G®A9p€A9A9ÂA9ë
+A:{A@  A@(öA@QìA@záA@£×A@ÌÍA@õÃAA
+žAAG®AAp€AAAAÂAAë
+AB{AB=qABffAB\ABžRABáHAC
+=AC33AC\)AC
+AC®AC×
+AD  AD(öADQìADzáAD£×ADÌÍADõÃAE
+žAEG®AEp€AEAEÂAEë
+AF{AF=qAFffAF\AFžRAFáHAG
+=AG33AG\)AG
+AG®AG×
+AH  AH(öAHQìAHzáAH£×AHÌÍAHõÃAI
+žAIG®AIp€AIAIÂAIë
+AJ{AP  AP(öAPQìAPzáAP£×APÌÍAPõÃAQ
+žAQG®AQp€AQAQÂAQë
+AR{AR=qARffAR\ARžRARáHAS
+=AS33AS\)AS
+AS®AS×
+AT  AT(öATQìATzáAT£×ATÌÍATõÃAU
+žAUG®AUp€AUAUÂAUë
+AV{AV=qAVffAV\AVžRAVáHAW
+=AW33AW\)AW
+AW®AW×
+AX  AX(öAXQìAXzáAX£×AXÌÍAXõÃAY
+žAYG®AYp€AYAYÂAYë
+AZ{A`  A`(öA`QìA`záA`£×A`ÌÍA`õÃAa
+žAaG®Aap€AaAaÂAaë
+Ab{Ab=qAbffAb\AbžRAbáHAc
+=Ac33Ac\)Ac
+Ac®Ac×
+Ad  Ad(öAdQìAdzáAd£×AdÌÍAdõÃAe
+žAeG®Aep€AeAeÂAeë
+Af{Af=qAfffAf\AfžRAfáHAg
+=Ag33Ag\)Ag
+Ag®Ag×
+Ah  Ah(öAhQìAhzáAh£×AhÌÍAhõÃAi
+žAiG®Aip€AiAiÂAië
+Aj{Ap  Ap(öApQìApzáAp£×ApÌÍApõÃAq
+žAqG®Aqp€AqAqÂAqë
+Ar{Ar=qArffAr\AržRAráHAs
+=As33As\)As
+As®As×
+At  At(öAtQìAtzáAt£×AtÌÍAtõÃAu
+žAuG®Aup€AuAuÂAuë
+Av{Av=qAvffAv\AvžRAváHAw
+=Aw33Aw\)Aw
+Aw®Aw×
+Ax  Ax(öAxQìAxzáAx£×AxÌÍAxõÃAy
+žAyG®Ayp€AyAyÂAyë
+Az{A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+
+=A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A   A {A (öA =qA QìA ffA záA \A £×A žRA ÌÍA áHA õÃA¡
+=A¡
+žA¡33A¡G®A¡\)A¡p€A¡
+A¡A¡®A¡ÂA¡×
+A¡ë
+A¢  A¢{A¢(öA¢=qA¢QìA¢ffA¢záA¢\A¢£×A¢žRA¢ÌÍA¢áHA¢õÃA£
+=A£
+žA£33A£G®A£\)A£p€A£
+A£A£®A£ÂA£×
+A£ë
+A€  A€{A€(öA€=qA€QìA€ffA€záA€\A€£×A€žRA€ÌÍA€áHA€õÃA¥
+=Aš  Aš{Aš(öAš=qAšQìAšffAšzáAš\Aš£×AšžRAšÌÍAšáHAšõÃA©
+=A©
+žA©33A©G®A©\)A©p€A©
+A©A©®A©ÂA©×
+A©ë
+Aª  Aª{Aª(öAª=qAªQìAªffAªzáAª\Aª£×AªžRAªÌÍAªáHAªõÃA«
+=A«
+žA«33A«G®A«\)A«p€A«
+A«A«®A«ÂA«×
+A«ë
+A¬  A¬{A¬(öA¬=qA¬QìA¬ffA¬záA¬\A¬£×A¬žRA¬ÌÍA¬áHA¬õÃA­
+=A°  A°{A°(öA°=qA°QìA°ffA°záA°\A°£×A°žRA°ÌÍA°áHA°õÃA±
+=A±
+žA±33A±G®A±\)A±p€A±
+A±A±®A±ÂA±×
+A±ë
+A²  A²{A²(öA²=qA²QìA²ffA²záA²\A²£×A²žRA²ÌÍA²áHA²õÃA³
+=A³
+žA³33A³G®A³\)A³p€A³
+A³A³®A³ÂA³×
+A³ë
+AŽ  AŽ{AŽ(öAŽ=qAŽQìAŽffAŽzáAŽ\AŽ£×AŽžRAŽÌÍAŽáHAŽõÃAµ
+=Až  Až{Až(öAž=qAžQìAžffAžzáAž\Až£×AžžRAžÌÍAžáHAžõÃA¹
+=A¹
+žA¹33A¹G®A¹\)A¹p€A¹
+A¹A¹®A¹ÂA¹×
+A¹ë
+Aº  Aº{Aº(öAº=qAºQìAºffAºzáAº\Aº£×AºžRAºÌÍAºáHAºõÃA»
+=A»
+žA»33A»G®A»\)A»p€A»
+A»A»®A»ÂA»×
+A»ë
+AŒ  AŒ{AŒ(öAŒ=qAŒQìAŒffAŒzáAŒ\AŒ£×AŒžRAŒÌÍAŒáHAŒõÃAœ
+=AÀ  AÀ{AÀ(öAÀ=qAÀQìAÀffAÀzáAÀ\AÀ£×AÀžRAÀÌÍAÀáHAÀõÃAÁ
+=AÁ
+žAÁ33AÁG®AÁ\)AÁp€AÁ
+AÁAÁ®AÁÂAÁ×
+AÁë
+AÂ  AÂ{AÂ(öAÂ=qAÂQìAÂffAÂzáAÂ\AÂ£×AÂžRAÂÌÍAÂáHAÂõÃAÃ
+=AÃ
+žAÃ33AÃG®AÃ\)AÃp€AÃ
+AÃAÃ®AÃÂAÃ×
+AÃë
+AÄ  AÄ{AÄ(öAÄ=qAÄQìAÄffAÄzáAÄ\AÄ£×AÄžRAÄÌÍAÄáHAÄõÃAÅ
+=AÈ  AÈ{AÈ(öAÈ=qAÈQìAÈffAÈzáAÈ\AÈ£×AÈžRAÈÌÍAÈáHAÈõÃAÉ
+=AÉ
+žAÉ33AÉG®AÉ\)AÉp€AÉ
+AÉAÉ®AÉÂAÉ×
+AÉë
+AÊ  AÊ{AÊ(öAÊ=qAÊQìAÊffAÊzáAÊ\AÊ£×AÊžRAÊÌÍAÊáHAÊõÃAË
+=AË
+žAË33AËG®AË\)AËp€AË
+AËAË®AËÂAË×
+AËë
+AÌ  AÌ{AÌ(öAÌ=qAÌQìAÌffAÌzáAÌ\AÌ£×AÌžRAÌÌÍAÌáHAÌõÃAÍ
+=AÐ  AÐ{AÐ(öAÐ=qAÐQìAÐffAÐzáAÐ\AÐ£×AÐžRAÐÌÍAÐáHAÐõÃAÑ
+=AÑ
+žAÑ33AÑG®AÑ\)AÑp€AÑ
+AÑAÑ®AÑÂAÑ×
+AÑë
+AÒ  AÒ{AÒ(öAÒ=qAÒQìAÒffAÒzáAÒ\AÒ£×AÒžRAÒÌÍAÒáHAÒõÃAÓ
+=AÓ
+žAÓ33AÓG®AÓ\)AÓp€AÓ
+AÓAÓ®AÓÂAÓ×
+AÓë
+AÔ  AÔ{AÔ(öAÔ=qAÔQìAÔffAÔzáAÔ\AÔ£×AÔžRAÔÌÍAÔáHAÔõÃAÕ
+=AØ  AØ{AØ(öAØ=qAØQìAØffAØzáAØ\AØ£×AØžRAØÌÍAØáHAØõÃAÙ
+=AÙ
+žAÙ33AÙG®AÙ\)AÙp€AÙ
+AÙAÙ®AÙÂAÙ×
+AÙë
+AÚ  AÚ{AÚ(öAÚ=qAÚQìAÚffAÚzáAÚ\AÚ£×AÚžRAÚÌÍAÚáHAÚõÃAÛ
+=AÛ
+žAÛ33AÛG®AÛ\)AÛp€AÛ
+AÛAÛ®AÛÂAÛ×
+AÛë
+AÜ  AÜ{AÜ(öAÜ=qAÜQìAÜffAÜzáAÜ\AÜ£×AÜžRAÜÌÍAÜáHAÜõÃAÝ
+=Aà  Aà{Aà(öAà=qAàQìAàffAàzáAà\Aà£×AàžRAàÌÍAàáHAàõÃAá
+=Aá
+žAá33AáG®Aá\)Aáp€Aá
+AáAá®AáÂAá×
+Aáë
+Aâ  Aâ{Aâ(öAâ=qAâQìAâffAâzáAâ\Aâ£×AâžRAâÌÍAâáHAâõÃAã
+=Aã
+žAã33AãG®Aã\)Aãp€Aã
+AãAã®AãÂAã×
+Aãë
+Aä  Aä{Aä(öAä=qAäQìAäffAäzáAä\Aä£×AäžRAäÌÍAäáHAäõÃAå
+=Aè  Aè{Aè(öAè=qAèQìAèffAèzáAè\Aè£×AèžRAèÌÍAèáHAèõÃAé
+=Aé
+žAé33AéG®Aé\)Aép€Aé
+AéAé®AéÂAé×
+Aéë
+Aê  Aê{Aê(öAê=qAêQìAêffAêzáAê\Aê£×AêžRAêÌÍAêáHAêõÃAë
+=Aë
+žAë33AëG®Aë\)Aëp€Aë
+AëAë®AëÂAë×
+Aëë
+Aì  Aì{Aì(öAì=qAìQìAìffAìzáAì\Aì£×AìžRAìÌÍAìáHAìõÃAí
+=Að  Að{Að(öAð=qAðQìAðffAðzáAð\Að£×AðžRAðÌÍAðáHAðõÃAñ
+=Añ
+žAñ33AñG®Añ\)Añp€Añ
+AñAñ®AñÂAñ×
+Añë
+Aò  Aò{Aò(öAò=qAòQìAòffAòzáAò\Aò£×AòžRAòÌÍAòáHAòõÃAó
+=Aó
+žAó33AóG®Aó\)Aóp€Aó
+AóAó®AóÂAó×
+Aóë
+Aô  Aô{Aô(öAô=qAôQìAôffAôzáAô\Aô£×AôžRAôÌÍAôáHAôõÃAõ
+=Aø  Aø{Aø(öAø=qAøQìAøffAøzáAø\Aø£×AøžRAøÌÍAøáHAøõÃAù
+=Aù
+žAù33AùG®Aù\)Aùp€Aù
+AùAù®AùÂAù×
+Aùë
+Aú  Aú{Aú(öAú=qAúQìAúffAúzáAú\Aú£×AúžRAúÌÍAúáHAúõÃAû
+=Aû
+žAû33AûG®Aû\)Aûp€Aû
+AûAû®AûÂAû×
+Aûë
+Aü  Aü{Aü(öAü=qAüQìAüffAüzáAü\Aü£×AüžRAüÌÍAüáHAüõÃAý
+=B   B 
+=B {B 
+žB (öB 33B =qB G®B QìB \)B ffB p€B záB 
+B \B B £×B ®B žRB ÂB ÌÍB ×
+B áHB ë
+B õÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB	  B	
+=B	{B	
+žB	(öB	33B	=qB	G®B	QìB	\)B	ffB	p€B	záB	
+B	\B	B	£×B	®B	žRB	ÂB	ÌÍB	×
+B	áHB	ë
+B	õÃB
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+\B
+B
+£×B
+®B
+žRB
+ÂB
+ÌÍB
+×
+B
+áHB
+ë
+B
+õÃB
+  B
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+\B
+B
+£×B
+®B
+žRB
+ÂB
+ÌÍB
+×
+B
+áHB
+ë
+B
+õÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+\B
+B
+£×B
+®B
+žRB
+ÂB
+ÌÍB
+×
+B
+áHB
+ë
+B
+õÃB
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+\B
+B
+£×B
+®B
+žRB
+ÂB
+ÌÍB
+×
+B
+áHB
+ë
+B
+õÃB
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B   B 
+=B {B 
+žB (öB 33B =qB G®B QìB \)B ffB p€B záB 
+B \B B £×B ®B žRB ÂB ÌÍB ×
+B áHB ë
+B õÃB!  B!
+=B!{B!
+žB!(öB!33B!=qB!G®B!QìB!\)B!ffB!p€B!záB!
+B!\B!B!£×B!®B!žRB!ÂB!ÌÍB!×
+B!áHB!ë
+B!õÃB"  B"
+=B"{B"
+žB"(öB"33B"=qB"G®B"QìB"\)B"ffB"p€B"záB"
+B$  B$
+=B${B$
+žB$(öB$33B$=qB$G®B$QìB$\)B$ffB$p€B$záB$
+B$\B$B$£×B$®B$žRB$ÂB$ÌÍB$×
+B$áHB$ë
+B$õÃB%  B%
+=B%{B%
+žB%(öB%33B%=qB%G®B%QìB%\)B%ffB%p€B%záB%
+B%\B%B%£×B%®B%žRB%ÂB%ÌÍB%×
+B%áHB%ë
+B%õÃB&  B&
+=B&{B&
+žB&(öB&33B&=qB&G®B&QìB&\)B&ffB&p€B&záB&
+B(  B(
+=B({B(
+žB((öB(33B(=qB(G®B(QìB(\)B(ffB(p€B(záB(
+B(\B(B(£×B(®B(žRB(ÂB(ÌÍB(×
+B(áHB(ë
+B(õÃB)  B)
+=B){B)
+žB)(öB)33B)=qB)G®B)QìB)\)B)ffB)p€B)záB)
+B)\B)B)£×B)®B)žRB)ÂB)ÌÍB)×
+B)áHB)ë
+B)õÃB*  B*
+=B*{B*
+žB*(öB*33B*=qB*G®B*QìB*\)B*ffB*p€B*záB*
+B,  B,
+=B,{B,
+žB,(öB,33B,=qB,G®B,QìB,\)B,ffB,p€B,záB,
+B,\B,B,£×B,®B,žRB,ÂB,ÌÍB,×
+B,áHB,ë
+B,õÃB-  B-
+=B-{B-
+žB-(öB-33B-=qB-G®B-QìB-\)B-ffB-p€B-záB-
+B-\B-B-£×B-®B-žRB-ÂB-ÌÍB-×
+B-áHB-ë
+B-õÃB.  B.
+=B.{B.
+žB.(öB.33B.=qB.G®B.QìB.\)B.ffB.p€B.záB.
+B0  B0
+=B0{B0
+žB0(öB033B0=qB0G®B0QìB0\)B0ffB0p€B0záB0
+B0\B0B0£×B0®B0žRB0ÂB0ÌÍB0×
+B0áHB0ë
+B0õÃB1  B1
+=B1{B1
+žB1(öB133B1=qB1G®B1QìB1\)B1ffB1p€B1záB1
+B1\B1B1£×B1®B1žRB1ÂB1ÌÍB1×
+B1áHB1ë
+B1õÃB2  B2
+=B2{B2
+žB2(öB233B2=qB2G®B2QìB2\)B2ffB2p€B2záB2
+B4  B4
+=B4{B4
+žB4(öB433B4=qB4G®B4QìB4\)B4ffB4p€B4záB4
+B4\B4B4£×B4®B4žRB4ÂB4ÌÍB4×
+B4áHB4ë
+B4õÃB5  B5
+=B5{B5
+žB5(öB533B5=qB5G®B5QìB5\)B5ffB5p€B5záB5
+B5\B5B5£×B5®B5žRB5ÂB5ÌÍB5×
+B5áHB5ë
+B5õÃB6  B6
+=B6{B6
+žB6(öB633B6=qB6G®B6QìB6\)B6ffB6p€B6záB6
+B8  B8
+=B8{B8
+žB8(öB833B8=qB8G®B8QìB8\)B8ffB8p€B8záB8
+B8\B8B8£×B8®B8žRB8ÂB8ÌÍB8×
+B8áHB8ë
+B8õÃB9  B9
+=B9{B9
+žB9(öB933B9=qB9G®B9QìB9\)B9ffB9p€B9záB9
+B9\B9B9£×B9®B9žRB9ÂB9ÌÍB9×
+B9áHB9ë
+B9õÃB:  B:
+=B:{B:
+žB:(öB:33B:=qB:G®B:QìB:\)B:ffB:p€B:záB:
+B<  B<
+=B<{B<
+žB<(öB<33B<=qB<G®B<QìB<\)B<ffB<p€B<záB<
+B<\B<B<£×B<®B<žRB<ÂB<ÌÍB<×
+B<áHB<ë
+B<õÃB=  B=
+=B={B=
+žB=(öB=33B==qB=G®B=QìB=\)B=ffB=p€B=záB=
+B=\B=B=£×B=®B=žRB=ÂB=ÌÍB=×
+B=áHB=ë
+B=õÃB>  B>
+=B>{B>
+žB>(öB>33B>=qB>G®B>QìB>\)B>ffB>p€B>záB>
+B@  B@
+=B@{B@
+žB@(öB@33B@=qB@G®B@QìB@\)B@ffB@p€B@záB@
+B@\B@B@£×B@®B@žRB@ÂB@ÌÍB@×
+B@áHB@ë
+B@õÃBA  BA
+=BA{BA
+žBA(öBA33BA=qBAG®BAQìBA\)BAffBAp€BAzáBA
+BA\BABA£×BA®BAžRBAÂBAÌÍBA×
+BAáHBAë
+BAõÃBB  BB
+=BB{BB
+žBB(öBB33BB=qBBG®BBQìBB\)BBffBBp€BBzáBB
+BD  BD
+=BD{BD
+žBD(öBD33BD=qBDG®BDQìBD\)BDffBDp€BDzáBD
+BD\BDBD£×BD®BDžRBDÂBDÌÍBD×
+BDáHBDë
+BDõÃBE  BE
+=BE{BE
+žBE(öBE33BE=qBEG®BEQìBE\)BEffBEp€BEzáBE
+BE\BEBE£×BE®BEžRBEÂBEÌÍBE×
+BEáHBEë
+BEõÃBF  BF
+=BF{BF
+žBF(öBF33BF=qBFG®BFQìBF\)BFffBFp€BFzáBF
+BH  BH
+=BH{BH
+žBH(öBH33BH=qBHG®BHQìBH\)BHffBHp€BHzáBH
+BH\BHBH£×BH®BHžRBHÂBHÌÍBH×
+BHáHBHë
+BHõÃBI  BI
+=BI{BI
+žBI(öBI33BI=qBIG®BIQìBI\)BIffBIp€BIzáBI
+BI\BIBI£×BI®BIžRBIÂBIÌÍBI×
+BIáHBIë
+BIõÃBJ  BJ
+=BJ{BJ
+žBJ(öBJ33BJ=qBJG®BJQìBJ\)BJffBJp€BJzáBJ
+BL  BL
+=BL{BL
+žBL(öBL33BL=qBLG®BLQìBL\)BLffBLp€BLzáBL
+BL\BLBL£×BL®BLžRBLÂBLÌÍBL×
+BLáHBLë
+BLõÃBM  BM
+=BM{BM
+žBM(öBM33BM=qBMG®BMQìBM\)BMffBMp€BMzáBM
+BM\BMBM£×BM®BMžRBMÂBMÌÍBM×
+BMáHBMë
+BMõÃBN  BN
+=BN{BN
+žBN(öBN33BN=qBNG®BNQìBN\)BNffBNp€BNzáBN
+BP  BP
+=BP{BP
+žBP(öBP33BP=qBPG®BPQìBP\)BPffBPp€BPzáBP
+BP\BPBP£×BP®BPžRBPÂBPÌÍBP×
+BPáHBPë
+BPõÃBQ  BQ
+=BQ{BQ
+žBQ(öBQ33BQ=qBQG®BQQìBQ\)BQffBQp€BQzáBQ
+BQ\BQBQ£×BQ®BQžRBQÂBQÌÍBQ×
+BQáHBQë
+BQõÃBR  BR
+=BR{BR
+žBR(öBR33BR=qBRG®BRQìBR\)BRffBRp€BRzáBR
+BT  BT
+=BT{BT
+žBT(öBT33BT=qBTG®BTQìBT\)BTffBTp€BTzáBT
+BT\BTBT£×BT®BTžRBTÂBTÌÍBT×
+BTáHBTë
+BTõÃBU  BU
+=BU{BU
+žBU(öBU33BU=qBUG®BUQìBU\)BUffBUp€BUzáBU
+BU\BUBU£×BU®BUžRBUÂBUÌÍBU×
+BUáHBUë
+BUõÃBV  BV
+=BV{BV
+žBV(öBV33BV=qBVG®BVQìBV\)BVffBVp€BVzáBV
+BX  BX
+=BX{BX
+žBX(öBX33BX=qBXG®BXQìBX\)BXffBXp€BXzáBX
+BX\BXBX£×BX®BXžRBXÂBXÌÍBX×
+BXáHBXë
+BXõÃBY  BY
+=BY{BY
+žBY(öBY33BY=qBYG®BYQìBY\)BYffBYp€BYzáBY
+BY\BYBY£×BY®BYžRBYÂBYÌÍBY×
+BYáHBYë
+BYõÃBZ  BZ
+=BZ{BZ
+žBZ(öBZ33BZ=qBZG®BZQìBZ\)BZffBZp€BZzáBZ
+B\  B\
+=B\{B\
+žB\(öB\33B\=qB\G®B\QìB\\)B\ffB\p€B\záB\
+B\\B\B\£×B\®B\žRB\ÂB\ÌÍB\×
+B\áHB\ë
+B\õÃB]  B]
+=B]{B]
+žB](öB]33B]=qB]G®B]QìB]\)B]ffB]p€B]záB]
+B]\B]B]£×B]®B]žRB]ÂB]ÌÍB]×
+B]áHB]ë
+B]õÃB^  B^
+=B^{B^
+žB^(öB^33B^=qB^G®B^QìB^\)B^ffB^p€B^záB^
+B`  B`
+=B`{B`
+žB`(öB`33B`=qB`G®B`QìB`\)B`ffB`p€B`záB`
+B`\B`B`£×B`®B`žRB`ÂB`ÌÍB`×
+B`áHB`ë
+B`õÃBa  Ba
+=Ba{Ba
+žBa(öBa33Ba=qBaG®BaQìBa\)BaffBap€BazáBa
+Ba\BaBa£×Ba®BažRBaÂBaÌÍBa×
+BaáHBaë
+BaõÃBb  Bb
+=Bb{Bb
+žBb(öBb33Bb=qBbG®BbQìBb\)BbffBbp€BbzáBb
+Bd  Bd
+=Bd{Bd
+žBd(öBd33Bd=qBdG®BdQìBd\)BdffBdp€BdzáBd
+Bd\BdBd£×Bd®BdžRBdÂBdÌÍBd×
+BdáHBdë
+BdõÃBe  Be
+=Be{Be
+žBe(öBe33Be=qBeG®BeQìBe\)BeffBep€BezáBe
+Be\BeBe£×Be®BežRBeÂBeÌÍBe×
+BeáHBeë
+BeõÃBf  Bf
+=Bf{Bf
+žBf(öBf33Bf=qBfG®BfQìBf\)BfffBfp€BfzáBf
+Bh  Bh
+=Bh{Bh
+žBh(öBh33Bh=qBhG®BhQìBh\)BhffBhp€BhzáBh
+Bh\BhBh£×Bh®BhžRBhÂBhÌÍBh×
+BháHBhë
+BhõÃBi  Bi
+=Bi{Bi
+žBi(öBi33Bi=qBiG®BiQìBi\)BiffBip€BizáBi
+Bi\BiBi£×Bi®BižRBiÂBiÌÍBi×
+BiáHBië
+BiõÃBj  Bj
+=Bj{Bj
+žBj(öBj33Bj=qBjG®BjQìBj\)BjffBjp€BjzáBj
+Bl  Bl
+=Bl{Bl
+žBl(öBl33Bl=qBlG®BlQìBl\)BlffBlp€BlzáBl
+Bl\BlBl£×Bl®BlžRBlÂBlÌÍBl×
+BláHBlë
+BlõÃBm  Bm
+=Bm{Bm
+žBm(öBm33Bm=qBmG®BmQìBm\)BmffBmp€BmzáBm
+Bm\BmBm£×Bm®BmžRBmÂBmÌÍBm×
+BmáHBmë
+BmõÃBn  Bn
+=Bn{Bn
+žBn(öBn33Bn=qBnG®BnQìBn\)BnffBnp€BnzáBn
+Bp  Bp
+=Bp{Bp
+žBp(öBp33Bp=qBpG®BpQìBp\)BpffBpp€BpzáBp
+Bp\BpBp£×Bp®BpžRBpÂBpÌÍBp×
+BpáHBpë
+BpõÃBq  Bq
+=Bq{Bq
+žBq(öBq33Bq=qBqG®BqQìBq\)BqffBqp€BqzáBq
+Bq\BqBq£×Bq®BqžRBqÂBqÌÍBq×
+BqáHBqë
+BqõÃBr  Br
+=Br{Br
+žBr(öBr33Br=qBrG®BrQìBr\)BrffBrp€BrzáBr
+Bt  Bt
+=Bt{Bt
+žBt(öBt33Bt=qBtG®BtQìBt\)BtffBtp€BtzáBt
+Bt\BtBt£×Bt®BtžRBtÂBtÌÍBt×
+BtáHBtë
+BtõÃBu  Bu
+=Bu{Bu
+žBu(öBu33Bu=qBuG®BuQìBu\)BuffBup€BuzáBu
+Bu\BuBu£×Bu®BužRBuÂBuÌÍBu×
+BuáHBuë
+BuõÃBv  Bv
+=Bv{Bv
+žBv(öBv33Bv=qBvG®BvQìBv\)BvffBvp€BvzáBv
+Bx  Bx
+=Bx{Bx
+žBx(öBx33Bx=qBxG®BxQìBx\)BxffBxp€BxzáBx
+Bx\BxBx£×Bx®BxžRBxÂBxÌÍBx×
+BxáHBxë
+BxõÃBy  By
+=By{By
+žBy(öBy33By=qByG®ByQìBy\)ByffByp€ByzáBy
+By\ByBy£×By®ByžRByÂByÌÍBy×
+ByáHByë
+ByõÃBz  Bz
+=Bz{Bz
+žBz(öBz33Bz=qBzG®BzQìBz\)BzffBzp€BzzáBz
+B|  B|
+=B|{B|
+žB|(öB|33B|=qB|G®B|QìB|\)B|ffB|p€B|záB|
+B|\B|B|£×B|®B|žRB|ÂB|ÌÍB|×
+B|áHB|ë
+B|õÃB}  B}
+=B}{B}
+žB}(öB}33B}=qB}G®B}QìB}\)B}ffB}p€B}záB}
+B}\B}B}£×B}®B}žRB}ÂB}ÌÍB}×
+B}áHB}ë
+B}õÃB~  B~
+=B~{B~
+žB~(öB~33B~=qB~G®B~QìB~\)B~ffB~p€B~záB~
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =
+(Ð9±¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?¹V:?=œ =(a<m<{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @7-@	ñâ?ºHþ?A\r=bn|<êxs¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @Ø@dt\@7Šù@
+Ù?Œg?DûC=-Ë=/)S¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @¶<@{b@±@e\@8@
+Á;?œç°?HÔ=«"U=ig¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @ãZx@ÌŒ@¶Uí@ï<@@fCµ@9vR@
+šï?¿·?L8Š=Èâ=Á¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AMÚ@ùýÚ@ã)@Í0x@¶ÉÇ@ c@üf@g+i@:^@
+£?Á?O×x=åm=®xL¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+îxAAl3@úqµ@ä
+@Í€S@·=¢@ Öñ@p@@h
+@;Eº@xX?ÃUê?SvJ>ý=ËnÙ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A5A*@)A
+ÑAÙxAŠ @úå@ä~Þ@Î-@·±|@¡JË@ä@húÒ@<-o@`
+?Å%S?W>~C=èee¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AL/°A@àÃA5­kA*zAFºAaAà	@ûYa@äò°@Îÿ@ž%N@¡Ÿ@Wì@iâv@=@G°?Æô?Z³¬>
+ø>­÷¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AbÐNAWaALN	AA°A5çXA*³ÿA§AMNA	ö@ûÍ;@åf@ÎÿÙ@ž(@¢2w@ËÆ@jÊ*@=üÇ@/e?ÈÄ?^R~>,sÏ>)>¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AypìAn!ÿAbî§AW»NALöAATA6!EA*íìAºA<A	Sã@üA@åÚd@Ïs³@¹
+@¢ŠQ@?¡@k±ß@>ä|@?Ên?añO>:ï>€¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÆAaOAyEAn[ìAc(AWõ;ALÁãAAA6[2A+'ÚAôAÁ(A	Ð@üŽï@æN>@Ïç@¹Ý@£,@³z@l@?Ì1@þÎ?ÌbÖ?e!>Ij[>.Ì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AYA±AðA~DAyÉ.AnÕAcb}AX/$ALûÌAAÈtA6A+aÂA .jAûA	Ç¹@ý(Â@æÂ@Ð[`@¹ô®@£þ@'M@m8@@³Õ@æs?Î2?i.²>Wä£><¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A©dAíAh@AÎA4çA:AzAnÏÂAcjAXiAM5¹AB`A6ÏA+°A hWA4ÿA
+Š@ý@ç5ê@ÐÏ:@ºh@€Ø@'@nhì@A@Î'?Ð?lÍ
+>f_ê>KZ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A©ùŽA€R=AžA
+äA
+7AëAQÞAž1Az=Ao	°AcÖWAX¢þAMoŠAB<NA7õA+ÕA ¢DAnëA
+;@þv@ç©Å@ÑC@ºÜc@€u²@@oP¡@B>@µÛ?ÑÐñ?plW>tÛ1>Y¡¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AµJA¯¢AªàA€o4AÕA;ÚA¢.AAnÓAÕ'AzvõAoCAdDAXÜìAM©ABv;A7BâA,A Ü1AšÙA
+u@þP@è
+@Ñ¶î@»P=@€é@Û@p8U@Cjó@?Ó Z?t
+(>«<>h
+è¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÀTAºòÝAµY0A¯¿Aª%×A€*Aò~AXÑA¿#A%wAÊAò
+Az°âAo}AdJ1AYÙAMãAB°'A7|ÏA,IwA!AâÆA
+¯m@þø*@èy@Ò*È@»Ä@¥]f@ö¶@q 	@DR§@
+D?ÕoÃ?w©ú>èà>v/¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AËê¢AÆC+AÀ©~A»ÒAµv%A¯ÜxAªBÌA€©AqAuÅAÜABlAš¿AAzêËAo·sAdAYPÁAN
+iABêA7¶¹A,`A!PA
+¯A
+éV@ÿkü@éK@Ò@Œ7ê@¥Ñ8@j@r®@E:K@lè?×?
+?{H>&>»¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A×:òAÑ{AËùÎAÆ`"AÀÆuA»,ÈAµ
+A¯ùoAª_ÁA€ÆA,hAŒAùA_bAÅ¶A,	A{$žAoñ_AdŸAY¯ANWWAC#þA7ð¥A,œMA!ôAVA
+#D@ÿßÖ@éy&@Ót@Œ«Ä@ŠE@Þb@rïb@F" @T?Ùt?~ç]>c§>¿_¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AâBAÜãËA×J
+AÑ°rAÌÅAÆ}AÀãlA»I¿Aµ°A°eAª|žA€ã
+AI_A¯²AA|YAâ¬AI A{^ŠAp+MAd÷õAYÄANCAC]ëA8*A,÷:A!ÃâAA
+]0A )Ø@éí @ÓO@œ@Šží@R<@s×@G	Ž@<Q?ÚÝÝ?C>¡K>ý¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AíÛAè4AânAÝ ÂA×gAÑÍhAÌ3ŒAÆAÁ aA»fµAµÍA°3\Aª¯A¥ AfVAÌ©A2üAPAÿ£AeöA{Ape:Ae1áAYþANË0ACØA8dA-1'A!ýÎAÊvA
+
+A cÆ@ê`Ú@Óú)@œx@§,Ç@Æ@tŸÌ@Gñh@$?Ü­F?>¥Þî>:Š¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aù+âAókAíêŸAèQAâ·eAÝ
+žA×
+AÑê_AÌP±AÆ·AÁ
+XA»¬AµéÿA°PRAª¶ŠA¥
+ùALAé AOóA¶FA
+AìA{ÒAp'AekÎAZ8vAO
+ACÑÅA8lA-kA"7ŒAdA
+Ñ
+A ²@êÔŽ@Ôn@ŸR@§ ¢@9ñ@uŠ@HÙ
+@
+
+º?Þ|¯?áé>­
+>xJ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B>AþÔ¹Aù;
+Aó¡`Aî³AènAâÔZAÝ:­A× ÿAÒSAÌmŠAÆÓúAÁ:MA»  A¶ôA°mGAªÓA¥9îA AAAlçAÓ:A9AáA|
+hApÙAe¥žAZr_AO?AD
+®A8ØVA-€þA"q¥A>LA
+
+ôA ×@ëH@ÔáÖ@Ÿ{%@št@­Ã@v$@IÀÁ@
+ó_?àK÷?±2>ŽYµ>Šµí¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bæ@BBE®Aþñ¯AùXAóŸVAî$ªAèýAâñOAÝW£A×œöAÒ$JAÌAÆððAÁWDA»œA¶#êA°>AªðA¥VäAœ7A#AÝAð1AVAŒØA|FVAqýAeß€AZ¬LAOxôADEA9CA-ÞêA"«Ax9A
+DáA@ëŒa@ÕU°@Ÿîÿ@šN@!@wuÙ@Jšv@
+Û?â`?>»Y>­ó¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+hB
+º¬BíÖB! BT)AÿŠAùtúAóÛMAîAAè§óAãFAÝtA×ÚíAÒA@AÌ§AÇ
+çAÁt:A»ÚA¶@áA°§4A«
+A¥sÚAÚ-A@AŠÔA
+(As{AÙÎA|CAqLêAfAZæ:AO²áADA9L0A.×A"åA²'A
+~ÏAKv@ì0;@ÕÉ@¿bÙ@šü)@x@x]@K*@
+ÂÇ?ãêÊ?P>ÂÔü>µ15¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B6BbÔB
+þB
+É(BüQB/{Bb¥Aÿ+AùïAóøCAî^AèÄêAã+=AÝA×÷äAÒ^7AÌÄAÇ*ÞAÁ1A»÷A¶]×A°Ä*A«*}A¥ÑA÷$A]xAÃËA*
+ArAöÅA|º0AqØAfSA[ &AOìÎAD¹uA9
+A.RÅA#mAìA
+žŒA
+c@ì€@Ö=e@¿ÖŽ@©p@	R@yEB@Lwß@ª|?åº2?m>Ê¡>ŒnÙ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BÞžB
+üB>&BqPB
+€yB
+×£B
+ÍB=öBq AÿHAù®æAô:Aî{AèáàAãH4AÝ®AØÚAÒ{.AÌáAÇGÔAÁ®'AŒzA¶zÎA°á!A«GtA¥­ÈA AznAàÂAGA­hA»A|ô
+AqÀÄAflA[ZAP&»ADócA9À
+A.²A#YZA&A
+ò©A¿P@íð@Ö±?@ÀJ@©ãÝ@},@z,ö@M_@ 1?ç?îÖ>ÑPD>Ã¬|¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+ßB³#BæMBwBL BÊB
+²ôB
+æ
+BGBLqBAÿeAùËÛAô2.AîAèþÕAãe(AÝË|AØ1ÏAÒ"AÌþuAÇdÈAÁË
+AŒ1oA¶ÂA°þA«diA¥ÊŒA 1AcAý¶Ad	AÊ\A0°A}.Aqú­AfÇUA[ýAP`¥AE-LA9ùôA.ÆA#CA_êA
+,Aù:@íÂ@×%@ÀŸ`@ªW¯@ðþ@{@NG8@!yÕ?éXå?Ÿ>Øh>Êê ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B$/B![KB
+uBÁBôÈB'òB[
+BEB
+ÁoB
+ôB'ÂBZìBAÿAùèÒAôO%AîµxAéÌAãAÝèrAØNÅAÒµAÍlAÇ¿AÁèAŒNfA¶Ž¹A±
+A«`A¥ç³A NAŽYA¬A AçSAMŠA}góAr4AgCA[ÍêAPAEg9A:3áA/ A#Í0AØA
+fA3&@íÿ@×ë@Á2:@ªË@dÙ@{üO@O.ì@"a?ë(M?>ßË
+>Ò'Ä¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B)×/B'sB$6B!iÇB
+ðBÐBDB6mBiBÁB
+ÏêB
+B6>BigBAÿtAúÈAôl
+AîÒoAé8ÂAãAÞhAØkŒAÒÒAÍ8bAÇ¶AÂ	AŒk\A¶Ñ°A±8A«VAŠ©A jüAÑPA7£AöAJAjA}¡áArnAg;0A\×APÔAE¡&A:mÎA/:vA$
+AÓÄA
+ lAm@îsv@Ø
+Å@ÁŠ@«?c@Ø³@|ä@P @#I>?ì÷·?\ñ>ç¯>Ùeh¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B/WB,«B)ÞÅB'ïB$EB!xBB
+«lBÞB¿BDéBxB«<B
+ÞfB
+BD¹BwâB«
+AÿŒkAú"¿AôAîïeAéUžAãŒ
+AÞ"_AØ²AÒïAÍUYAÇ»¬AÂ" AŒSA¶îŠA±TùA«»LAŠ! A óAîFATAºíA!@AA}ÛÎAršuAgu
+A\AÄAQlAEÛA:§»A/tbA$A
+A
+²A
+ÚYA§@îçQ@Ø@Âï@«³>@L@}Ëž@PþV@$0ó?îÇ ?,Z>îFT>à£
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B5'B2SÃB/íB,ºB)í@B' jB$SB!œB
+¹çBíB :BSdBB¹·B
+ìáB
+ 
+BS4B^B¹AÿÙbAú?µAôŠAï
+\Aér¯AãÙAÞ?VAØ¥©AÓ
+üAÍrPAÇØ£AÂ>öAŒ¥IA·
+A±qðA«ØCAŠ>A €êA
+=AqA×äA>7A€A~»ArâbAg¯
+A\{²AQHYAF A:ášA/®PA$z÷AGAFAàî@ï[+@Øôz@ÂÉ@¬'@Àg@~³l@Qæ
+@%§?ð?ûÄ>õù>çà°¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B:ÏŠB7ûêB5/B2b>B/gB,ÈB)û»B'.äB$bB!8B
+ÈaBûB.µBaÞBBÈ1B
+û[B
+.
+Ba®BØBÈAÿöVAú\ªAôÂýAï)PAé€Aãõ÷AÞ\JAØÂAÓ(ñAÍDAÇõAÂ[êAŒÂ>A·(A±äA«õ8AŠ[A ÁÞA(2A
+AôØA[,AÁ~A~O£As
+LAgèóA\µAQBAFNêA;A/è9A$ŽàAAN/A×@ïÎý@ÙhL@Ã@¬ê@49@@RÍ¯@& L?òeÒ?Ë
+>üÁ
+>ï
+U¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B@wÎB=€B:×<B8
+fB5=B2p¹B/£ãB,×
+B*
+6B'=`B$pB!£³B
+ÖÝB
+
+B=0BpYB£BÖ­B	ÖB
+= Bp*B£SBÖ}B 	§Aúy AôßôAïFGAé¬AäîAÞyAAØßAÓEçAÍ¬:AÈAÂxáAŒß4A·EA±«ÛA¬.AŠxA ÞÕAE(A«|AÎAx"AÞuA~AsV8Ah"àA\ïAQŒ/AF×A;U~A0"&A$îÍA»uA
+ATÄ@ðB×@ÙÜ&@Ãuu@­Ä@š@Ac@Sµc@&è ?ô5;?u?ÿ`>ö[ø¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BFöBCL:B@dB=²B:å·B8áB5L
+B24B/²^B,åB*±B'KÛB$B!².B
+åXB
+BK«B~ÕB±þBå(BRB
+K{B~¥B±ÏBäøB !AúAôüêAïc>AéÉAä/äAÞ7AØüAÓbÞAÍÉ1AÈ/AÂØAŒü+A·b~A±ÈÒA¬/%AŠxA ûÌAb
+AÈrA.ÅAAûlA~Ã~As&Ah\ÍA])uAQö
+AFÂÄA;kA0\A%(»AõbAÂ	A±@ð¶±@ÚP @ÃéO@­@î@µ=@T@'Ïµ?ö€?iÞ?2>ý¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BKÈ
+BHôbBF'BCZ¶B@ßB=Á	B:ô3B8'\B5ZB2°B/ÀÙB,ôB*'-B'ZVB$B!À©B
+óÓB
+&ýBZ&BPBÀzBó£B&ÍB
+Y÷B BÀIBósB &Aú³AõáAï4AéæAäLÚAÞ³.AÙAÓÔAÍæ(AÈL{AÂ²ÎAœ"A·uA±åÈA¬L
+AŠ²nA¡ÂAAåhAKŒA²A
+bA~ýkAsÊAhºA]cbAR0	AFü±A;ÉYA0 A%b§A/OAû÷AÈ@ñ*@ÚÃÛ@Ä]*@­öy@È@)@UÌ@(·i?÷Ô
+?9G?	=?k ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BQpFBNBKÏŽBIÞBF6BCi1B@[B=ÏB;®B85ØB5iB2+B/ÏUB-~B*5šB'hÑB$ûB!Ï%BNB
+5xBh¢BËBÎõBB5HB
+hqBBÎÅBîB 5AúÐAõ6×Aï*Aê~AäiÑAÞÐ$AÙ6xAÓËAÎ
+AÈirAÂÏÅAœ6A·lA²ŸA¬iAŠÏeA¡5žA
+A_Ah²AÏA
+5YA7XAt AhÐ§A]OARi÷AG6A<EA0ÏíA%Ai<A5äA@ñf@Û7µ@ÄÑ@®jS@¢@ò@Vl@)
+?ù£v? °?
+ÛÖ?
+r¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BWmBTD±BQwÛBN«BKÞ.BIXBFDBCw«B@ªÕB=ÝÿB;(B8DRB5w|B2ª¥B/ÝÏB-øB*D"B'wLB$ªuB!ÝBÉB
+CòBw
+BªFBÝoBBCÂB
+vìBªBÝ?BiB CAúíxAõSÌAïºAê rAäÆAÞíAÙSlAÓ¹ÀAÎ AÈfAÂìºAœS
+A·¹`A²³A¬AŠìZA¡R­A¹ ATA
+§AëúA
+RNAqAAt=éAi
+A]×8AR£ßAGpA<=/A1	ÖA%Ö~A£%AoÍA<t@ò8@Û«@ÅDÖ@®Þ%@wt@Ä@WT%@*Â?ûrŸ?¡×ù?zg?	©D¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B\ÀBYìÙBW BTS-BQVBN¹BKìªBIÓBFRýBC'B@¹PB=ìzB;€B8RÍB5
+÷B2¹ B/ìJB-tB*RB'
+ÇB$žñB!ìBDB
+RnB
+BžÀBëêBBR=B
+
+gBžBë»B
+åB RAû
+oAõpÂAï×Aê=iAä£ŒAß
+AÙpcAÓÖ¶AÎ=
+AÈ£\AÃ	°AœpA·ÖVA²<ªA¬¢ýA§	PA¡o€AÕ÷A<JA¢AñA
+oDA«.AtwÖAiD}A^%ARÝÍAGªtA<w
+A1CÃA&kAÝA©ºAvb@ò@Üa@Åž°@¯R @ëO@@X;Ù@+nv?ýB'?£§b?:?
+H¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BbhœB_B\È+BYûUBW.~BTašBQÒBNÇûBKû%BI.OBFaxBC¢B@ÇÌB=úõB;.B8aHB5rB2ÇB/úÅB--ïB*aB'BB$ÇlB!úB-¿B
+`èBBÇ<BúeB-B`¹B
+ãBÇ
+Bú6B-`B `Aû'fAõ¹Aïô
+AêZ`AäÀ³Aß'AÙZAÓó¬AÎZ AÈÀSAÃ&ŠAœúA·óMA²Y A¬¿ôA§&GA¡AòîAYAA¿A%çA
+:AåAt±ÃAi~kA^KASºAGäaA<±	A1}°A&JXA Aã§A°N@òùì@Ü<@Æ,@¯ÅÚ@_)@øx@Y#@,V+?ÿ?¥vË?ž
+?æè¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BhåBe=)BbpSB_£}B\ÖŠBZ	ÐBW<úBTp#BQ£MBNÖwBL	 BI<ÊBFoôBC£
+B@ÖGB>	pB;<B8oÄB5¢íB2ÖB0	AB-<jB*oB'¢ŸB$ÕçB"	B<:B
+odB¢BÕ·BáB<
+Bo5B
+¢^BÕB²B;ÛB oAûD\Aõª°AðAêwVAäÝªAßCüAÙªPAÔ£AÎvöAÈÝJAÃCAœ©ðAžDA²vA¬ÜêA§C>A¡©AäAv7AÜABÞA
+©1AAtë°AižXA^ÿASQ§AH
+NA<êöA1·A&EAPìA
+Aê<@ómÇ@Ý@Æ e@°9Ž@Ó@lR@Z
+B@-=ß@ p|?§F3?VÝ?
+¹¿  ¿  ¿  ¿  ¿  ¿  Bm¹
+BjåQBh{BeK¥Bb~ÎB_±øB\å"BZKBWKuBT~BQ±ÈBNäòBL
+BIKEBF~oBC±B@äÂB>ìB;KB8~?B5±iB2äB0ŒB-JæB*~B'±8B$äbB"BJµB
+}ßB±	Bä3B]BJB}°B
+°ÚBäB,BJVB }AûaSAõÇŠAð-úAêLAäú Aß`óAÙÇFAÔ-AÎíAÈú@AÃ`AœÆçAž-:A²A¬ùáA§`4A¡ÆA,ÚA.AùA_ÔA
+Æ(A,{Au%AiòEA^ŸìASAHX<A=$ãA1ñA&Ÿ2AÚAWA$)@óá¡@Ýzð@Ç?@°­@FÞ@à-@Zòö@.%@X1?©?
+õ¯?$¿  ¿  ¿  ¿  Bsa4BpxBmÀ¢BjóÌBh&õBeZBbIB_ÀrB\óBZ&ÆBWYïBTBQÀCBNólBL&BIY¿BFéBCÀB@ó<B>&fB;YB8¹B5¿ãB2ó
+B0&6B-Y_B*B'¿³B$òÜB"&BY0B
+ZB¿Bò­B%×BYB*B
+¿SBò}B%§BXÐB úAû~HAõäAðJîAê±AAåAß}èAÙä;AÔJAÎ°âAÉ5AÃ}AœãÜAžJ/A²°A­ÕA§}(A¡ã|AIÏA°"AvA|ÉA
+ã
+AIpAu_Aj,.A^øÖASÅ}AH$A=^ÌA2+tA&øAÄÃAkA^@ôUs@ÝîÂ@Ç@±!a@º°@Sÿ@[Ú@/
+8@?Õ?ªäæ?"B?Ã^¿  ¿  By	\Bv5 BshÊBpôBmÏ
+BkGBh5qBehBbÄB_ÎîB]BZ5ABWhkBTBQÎŸBOçBL5BIh;BFdBCÎBAžB>4áB;h
+B85B5Î^B3B04±B-gÛB*B'Î.B%XB"4Bg¬B
+ÕBÍÿB)B4RBg{B¥B
+ÍÏB	 øB4"BgLB uAû>AöAðgäAêÎ8Aå4AßÞAÚ2AÔg
+AÎÍØAÉ4,AÃAŸ ÒAžg%A²ÍxA­3ÌA§A¢ rAfÆAÍA3lAÀA AffAutAjfA_2ÂASÿjAHÌA=¹A2eaA'2	Aþ°AËWAÿ@ôÉN@Þb@Çûì@±;@.@ÇÙ@\ÂO@/ôí@'?¬ŽO?&3?b/B|  B{ÝÈByòBvD
+BswEBpªoBmÝBkÂBhCìBewBbª?B_ÝiB]BZCŒBWvæBTªBQÝ9BOcBLCBIv¶BF©àBCÝ	BA3B>C]B;vB8©¯B5ÜÙB3B0C,B-vVB*©B'ÜªB%ÔB"BýBv'B
+©QBÜzB£BBÍBu÷B© B
+ÜJB	tBBBuÇB šñAûž4Aö
+AðÛAêë.AåQAß·ÕAÚ
+(AÔ|AÎêÏAÉQ"AÃ·uAŸ
+ÈAž
+A²êoA­PÂA§·A¢
+iAŒAêAPcA¶¶A
+	A\AuÓ`Aj A_l°AT9WAIÿA=Ò§A2NA'kõA
+8AEAÑí@õ=(@ÞÖw@ÈoÆ@²	@¢e@
+;³@]ª@0Ü¢@??®ž?)Ñå¿  B|B{ìDBymBvRBs
+ÁBpžêBmìBk>BhRgBe
+Bbž»B_ëäB]BZR7BW
+aBTžBQëŽBO
+ÞBLRBI
+1BFž[BCë
+BA
+®B>Q×B;
+B8ž+B5ëTB3
+~B0QšB-ÒB*·üB'ë%B%
+OB"QyB¢B
+·ËBêõB
+BQHBrB·B
+êÅB	
+ïBQBBB ·lAûÕ+Aö;~Að¡ÒAë%AånxAßÔÌAÚ;AÔ¡rAÏÅAÉnAÃÔlAŸ:¿Až¡A³fA­m¹A§Ô
+A¢:`A ³AAmYAÓ¬A: A SAv
+NAjÙõA_ŠATsEAI?ìA>
+A2Ù;A'¥ãA
+rA?2A
+Ù@õ±@ßJQ@Èã¡@²|ð@>@
+¯@^¹@1ÄV@öó?¯vw¿  ¿  B|B{ú¿By-éBvaBs<BpÇfBmúBk-¹Bh`ãBe
+BbÇ6B_ú_B]-BZ`³BWÜBTÇBQú0BO-YBL`BI­BFÆÖBCùÿBA-)B>`SB;|B8ÆŠB5ùÐB3,úB0`$B-MB*ÆwB'ù¡B%,ÊB"_óB
+B
+ÆGBùpB,B_ÄBíBÆB
+ùAB	,jB_BŸB ÅçAûò"AöXuAðŸÈAë%
+AåoAßñÂAÚXAÔŸhAÏ$ŒAÉAÃñbAŸW¶AžŸ	A³$\A­°A§ñA¢WVAœ©A#üAPAð£AVöAœJAvG;AkãA_àAT­1AIyÙA>FA3)A'ßÐA
+¬wAyAEÇ@ö$Ý@ßŸ,@ÉWz@²ðÊ@@#h@_yn@2=¶¿  ¿  ¿  ¿  B|$B|	:By<dBvoBs¢·BpÕáBn	
+Bk<4Bho^Be¢BbÕ±B`ÛB]<BZo.BW¢XBTÕBR«BO;ÕBLnþBI¢'BFÕQBD{BA;€B>nÎB;¡øB8Õ"B6LB3;uB0nB-¡ÉB*ÔòB(B%;EB"noB¡B
+ÔÂBìB;Bn?B¡iBÔB
+ŒB	:æBnB¡9B ÔbAüAöulAðÛ¿AëBAåšeAàžAÚu
+AÔÛ_AÏA²AÉšAÄYAŸt¬AžÛ A³ASA­§ŠAš
+ùA¢tLAÚ A@óA§FA
+AsíAÚ@Av(AkMÏA`wATçAI³ÇA>nA3MA(œA
+æeA³
+AŽ@ö·@à2@ÉËU@³d€@ýó@`¿  ¿  ¿  ¿  ¿  ¿  B|3B|¶ByJßBv~	Bs±3Bpä\BnBkJ¯Bh}ÙBe±Bbä,B`VB]JBZ}©BW°ÓBTãýBR&BOJOBL}yBI°£BFãÌBDöBAJ B>}JB;°tB8ãB6ÇB3IñB0}B-°CB*ãmB(B%IÀB"|êB°B
+ã=BgBIB|ºB¯äBãB
+7B	IaB|B¯ŽB âÞAü,AöbAðøµAë_AåÅ\Aà+¯AÚAÔøVAÏ^©AÉÄüAÄ+PAŸ£Až÷öA³^IA­ÄAš*ðA¢CA÷A]êAÄ=A*AäA÷7Av»AkœA`TeAU!
+AIí³A>º[A3A(SªA
+ RAìúA¹¡@÷
+@à¥à@Ê?/@³¡T¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|AB|&/ByYYBvBs¿¬BpòÕBn%ÿBkY)BhRBe¿|BbòŠB`%ÏB]XùBZ#BW¿LBTòuBR%BOXÉBLòBI¿
+BFòFBD%pBAXB>ÃB;ŸíB8òB6%@B3XiB0B-ŸœB*ñæB(%B%X:B"cBŸB
+ñ·B$àBX
+B4BŸ]BñB
+$°B	WÚBBŸ-B ñWAüIAö¯TAñšAë{ûAåâNAàH¢AÚ®õAÕHAÏ{AÉáïAÄHBAŸ®A¹èA³{<A­áAšGâA¢®6AAzÜAá0AGA­×A)AvôûAkÁ¢A`IAUZñAJ'A>ô@A3ÀèA(A
+Z7A&ÞAó@÷[@àâ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|OÿB|4ªBygÔBvýBsÎ'BqQBn4zBkg€BhÎBeÍ÷Bc!B`4KB]gtBZBWÍÇBU ñBR4BOgDBLnBIÍBG ÂBD3ëBAgB>?B;ÍhB9 B63»B3fåB0B-Í8B+ bB(3B%fµB"ßBÍB
+ 2B3\Bf
+B¯BÌØB B
+3,B	fUBBÌšB ÿÒAüeøAöÌKAñ2AëòAåÿEAàeAÚËìAÕ2?AÏAÉþåAÄe8AŸËA¹1ßA³2A­þAšdÙA¢Ë,A1AÓAþ'AdyAÊÌA1 Aw.çAkûA`È7AUÞAJaA?..A3úÕA(Ç|A
+$A`ÌAÞ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|^zB|C%ByvOBv©yBsÜ¢BqÌBnBöBkvBh©IBeÜsBcB`BÅB]uïBZ©BWÜBBUlBRBBOuÀBLšêBIÜBG=BDBgBAuB>š¹B;ÛãB9
+B6B6B3u`B0šB-Û³B+ÝB(BB%u0B"šZBÛB
+­BA×Bu Bš*BÛTB}B
+A§B	tÐB§úBÛ$BMAüîAöéBAñOAëµèAæ
+<AàAÚèâAÕO5AÏµAÊÜAÄ/AŸèA¹NÖA³µ)A®|AšÐA¢è#ANwAŽÉA
+ApAçÃANAwhÕAl5|Aa$AUÎÌAJsA?hA44ÂA)jA
+²|¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|lõB|Q¡ByÊBv·ôBsë
+Bq
+GBnQqBkBh·ÄBeêíBc
+B`QAB]jBZ·BWêŸBU
+èBRQBO;BL·eBIêBG
+žBDPáBA
+B>·5B;ê^B9
+B6P²B3ÛB0·B-ê/B+
+XB(PB%¬B"¶ÕBéÿB
+
+(BPRB|B¶¥BéÏB
+øB
+P"B	LB¶uBéB
+ÉAüåA÷8AñlAëÒßAæ92Aà
+AÛØAÕl,AÏÒAÊ8ÒAÄ&A¿yA¹kÌA³Ò A®8sAšÇA£AklAÑÀA8AfAºAk
+Aw¢ÂAlojAa<AVžAJÕ`A?¢A4S¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|{pB|`
+ByFBvÆoBsùBq,ÃBn_ìBkBhÆ?BeùiBc,B`_ŒB]æBZÆBWù:BU,cBR_BO·BLÅàBIù	BG,3BD_]BAB>Å°B;øÚB9,B6_-B3WB0ÅB-øªB++ÔB(^ýB%'B"ÅPBøzB
++€B^ÍB÷BÅ BøJB+tB
+^B	ÇBÄñBøB+DAüŒÜA÷#/AñAëïÕAæV(AàŒ|AÛ"ÏAÕ"AÏïvAÊUÉAÄŒ
+A¿"pA¹ÃA³ïA®UiAš»ŒA£"AcAî¶AU
+A»]A!°AAwÜ¯Al©VAauþAVBŠAJóž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ìB|nBy¡ÁBvÔëBtBq;=BnngBk¡BhÔºBfäBc;B`n8B]¡bBZÔBXµBU:ßBRnBO¡1BLÔ[BJ
+BG:®BDmØBA¡B>Ô+B<UB9:B6mšB3 ÒB0ÓüB.%B+:OB(mxB% ¢B"ÓÌB õB
+:BmHB rBÓBÅB9ïB
+mB	 BBÓlBB9¿AüÙÒA÷@%AñŠxAì
+ÌAæsAàÙrAÛ?ÆAÕŠAÐ
+lAÊrÀAÄÙA¿?gA¹¥¹AŽ
+
+A®r`AšØ³A£?A¥ZA
+­Ar AØTA>§A€úAxAlãDAaV¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|gB|}By°<BvãeBtBqI¹Bn|âBk°
+Bhã6Bf`BcIB`|³B]¯ÝBZãBX0BUIYBR|BO¯­BLâÖBJ BGI*BD|SBA¯}B>â§B<ÐB9HúB6|$B3¯MB0âwB. B+HÊB({ôB%¯
+B"âGB pB
+HB{ÄB®íBâBABHjB
+{B	®ŸBáçBBH;AüöÈA÷]
+AñÃoAì)ÂAæAàöiAÛ\ŒAÕÃAÐ)cAÊ·AÄö	A¿\\A¹Â°AŽ)A®VAšõªA£[ýAÂPA(€A÷AõKA[AÁñAx4ô¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ŠâB|ByŸ·BvñáBt%
+BqX4Bn^BkŸBhñ²Bf$ÛBcXB`/B]ŸXBZñBX$«BUWÕBRþBOŸ(BLñRBJ${BGW¥BDÏBAœøB>ñ"B<$LB9WuB6B3œÈB0ðòB.$
+B+WEB(oB%œB"ðÂB #ìB
+WB?BœiBðB#ŒBVæB
+B	œ9BðcB#BV¶Aý¿A÷zAñàfAìF¹Aæ­
+Aá`AÛy³AÕàAÐFYAÊ¬¬AÅ A¿ySA¹ßŠAŽEúA®¬MA© A£xôAßGAEA«îA@AjÉ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|µ]B|	ByÍ2Bw \Bt3Bqf°BnÚBkÍBi -Bf3WBcfB`©B]ÌÓBZÿýBX3&BUfPBRzBOÌ£BLÿÍBJ2÷BGf BDJBAÌtB>ÿB<2ÇB9eðB6B3ÌDB0ÿmB.2B+eÀB(êB%ÌB"ÿ=B 2gB
+eBºBËäBÿB27BeaB
+B	ËŽBþÞB2Be1Aý0¶A÷	Añý\Aìc°AæÊAá0WAÛ©AÕüüAÐcPAÊÉ£AÅ/öA¿JA¹üAŽbðA®ÉDA©/A£ëAü>AbA»¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ÃØB|šByÛ®BwØBtBBqu+BnšUBkÛBišBfAÑBctûB`š%B]ÛNB[xBXA¢BUtËBR§õBOÛBMHBJArBGtBD§ÅBAÚïB?B<ABB9tlB6§B3Ú¿B1
+èB.AB+t<B(§eB%ÚB#
+¹B @âB
+t
+B§6BÚ_B
+B@³BsÜB
+§B	Ú0B
+YB@Bs¬AýM¬A÷Ž AòSAì§AææùAáMLAÛ³ AÖóAÐFAÊæAÅLíA¿³@AºAŽçA®æ;A©LA£²àA
+i¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ÒTB|¶þByê(Bw
+QBtP{Bq¥Bn¶ÎBké÷Bi
+!BfPKBctB`¶B]éÈB[
+ñBXPBUEBR¶nBOéBM
+ÂBJOëBGBD¶>BAéhB?
+B<O»B9åB6¶B3é8B1
+bB.OB+µB(µßB%éB#
+2B O\B
+
+Bµ¯BèÙB
+BO,BVB
+µB	è©BÒBNüB&AýjA÷ÐóAò7EAìAçìAáj?AÛÐAÖ6æAÐ9AËAÅiàA¿Ð3Aº6AŽÚA¯,A©[µ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|àÐB|ÅyByø£Bw+ÍBt^öBqBnÅIBkøsBi+Bf^ÆBcðB`ÅB]øCB[+mBX^BUÀBRÄêBOøBM+=BJ^fBGBDÄºBA÷ãB?+
+B<^6B9`B6ÄB3÷³B1*ÝB.^B+0B(ÄZB%÷B#*­B ]×B
+BÄ*B÷TB*~B]§BÑB
+ÃúB	÷$B*NB]wB¡AýA÷íèAòT<AìºAç âAá6AÛíAÖSÜAÐº0AË AÅ×A¿í*AºS|AŽ¬¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ïKB|ÓõBz
+Bw:GBtmqBq BnÓÄBlîBi:BfmABc kB`ÓB^ŸB[9èBXmBU ;BRÓeBPBM9žBJlâBG 
+BDÓ5BB^B?9B<l²B9ÛB6ÓB4/B19XB.lB+¬B(ÒÕB&ÿB#9)B lRB
+|BÒŠBÏB8ùBl"BLB
+ÒvB
+B8ÉBkóB
+Aý€Aø
+ßAòq2Aì×Aç=ÙAá€,AÜ
+AÖpÓAÐ×'AË=zAÅ£ÌA¿üU¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ýÆB|âoBzBwHÃBt{ìBq¯Bnâ@BliBiHBf{œBc®æB`âB^:B[HcBX{BU®¶BRáàBP
+BMH3BJ{]BG®BDá°BBÚB?HB<{-B9®WB6áB4ªB1GÔB.zýB+®'B(áQB&zB#G€B zÎB
+­÷Bá!BJBGtBzB­ÇB
+àñB
+BGDBznB­AýÁAø'ÖAò)Aìô|AçZÐAáÁ#AÜ'wAÖÊAÐô
+AËL¥¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}
+AB|ðëBz$BwW>BthBqœBnð»Bl#åBiWBf8BcœbB`ðB^#µB[VÞBXBUœ2BRð[BP#
+BMV®BJØBGœBDð+BB#UB?VB<šB9ŒÒB6ïüB4#%B1VOB.yB+Œ¢B(ïÌB&"öB#VB IB
+ŒrBïB"ÆBUïBBŒCB
+ïlB
+"BUÀBéBŒAýÞyAøDÌAò« AísAçwÇAáÞAÜDlAÖõ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ŒB|ÿfBz2Bwe¹BtãBqÌ
+Bnÿ6Bl2`BieBf³BcËÝB`ÿB^20B[eZBXBUË­BRþÖBP2 BMe*BJSBGË}BDþ§BB1ÐB?dúB<$B9ËMB6þwB41¡B1dÊB.ôB+Ë
+B(þGB&1qB#dB ÄB
+ÊîBþB1ABdkBBÊŸB
+ýèB
+1Bd;BeBÊAýûpAøaÃAòÈAí.jAçŒAáíE¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B})8B}
+áBzA
+Bwt5Bt§^BqÚBo
+²Bl@ÛBitBf§.BcÚXBa
+B^@«B[sÕBXŠþBUÚ(BS
+RBP@{BMs¥BJŠÏBGÙøBE
+"BB@LB?suB<ŠB9ÙÉB7
+òB4@
+B1sFB.ŠoB+ÙB)
+ÂB&?ìB#sB Š?B
+ÙiB
+B?ŒBræBŠBÙ9B
+
+cB
+?Br¶B¥ßBÙ
+AþgAø~ºAòå
+Aí=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}7³B}
+]BzOBw°BtµÚBqéBo
+-BlOVBiBfµªBcèÓBaýB^O&B[PBXµzBUè£BSÍBPN÷BM BJµJBGètBEBBNÇB?ñB<µB9èDB7nB4NB1ÁB.ŽêB+èB)>B&NgB#B Ž»B
+çäBBN8BaBŽBçµB
+ÞB
+NB2BŽ[Bç
+Aþ5\Aøå¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}F.B}*ØBz^Bw+BtÄUBq÷~Bo*šBl]ÒBiûBfÄ%Bc÷NBa*xB^]¢B[ËBXÃõBU÷BS*HBP]rBMBJÃÅBGöïBE*BB]BB?lB<ÃB9ö¿B7)éB4]B1<B.ÃfB+öB))¹B&\ãB#
+B Ã6B
+ö`B)B\³BÝBÃBö/B
+)ZB
+\B­BÂ×Bï¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}TªB}9SBzl}BwŠBtÒÐBrúBo9#BllMBivBfÒ BdÊBa8óB^l
+B[GBXÒpBVBS8ÄBPkíBMBJÒABHjBE8BBkŸB?çB<ÒB::B78dB4kB1·B.ÑáB,
+B)84B&k^B#B Ñ±B
+ÛB8Bk.BWBÑB«B
+7ÕB
+jÿBC¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}c%B}GÌBzzöBw® BtáIBrsBoGBlzÆBi­ðBfáBdCBaGmB^zB[­ÀBXàêBVBSG=BPzgBM­BJàºBHäBEG
+BBz7B?­`B<àB:ŽB7FÝB4zB1­1B.àZB,B)F®B&y×B#­B à+B
+TBF}ByšB¬ÑBßûB%B
+?i¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}q B}VHBzqBwŒBtïÄBr"îBoVBlABiŒkBfïBd"ŸBaUèB^B[Œ;BXïeBV"BSUžBPâBMŒ
+BJï5BH"_BEUBB²B?»ÜB<ïB:"/B7UYB4B1»¬B.îÖB,!ÿB)U)B&SB#»|B î¥B
+!ÐBTùB#B»MBç¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}B}dÃBzìBwËBtþ@Br1iBodBlœBiÊæBfþBd1:BadcB^B[Ê·BXýàBV1
+BSd4BP]BMÊBJý°BH0ÚBEdBB-B?ÊWB<ýB:0ªB7cÔB4þB1Ê'B.ýQB,0{B)c€B&ÍB#ÉøB ý!B
+0KBcuB¹¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}B}s>BzŠhBwÙBu
+»Br?åBosBlŠ8BiÙbBg
+Bd?µBarßB^ŠB[Ù2BY
+\BV?
+BSr¯BP¥ØBMÙBK
+,BH?UBErBB¥©B?ØÒB=
+üB:?&B7rOB4¥yB1Ø£B/
+ÌB,>õB)r B&¥IB#ØsB!
+B
+7á¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}B}¹BzŽãBwè
+Bu6BrN`BoBlŽ³BiçÝBgBdN0BaZB^ŽB[ç­BY×BVN BS*BPŽTBMç}BK§BHMÑBEúBBŽ$B?çNB=wB:M¡B7ËB4³ôB1ç
+B/HB,MqB)B&³ÅB#à	¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}«B}5BzÃ^BwöBu)²Br\ÛBoBlÃ/BiöXBg)Bd\¬BaÕB^ÂÿB[ö(BY)RBV\|BS¥BPÂÏBMõùBK)"BH\LBEvBBÂB?õÉB=(óB:\
+B7EB4ÂpB1õB/(ÃB,[íB)1¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ºB}°BzÑÚBxBu8-BrkWBoBlÑªBjÔBg7ýBdk'BaPB^ÑzB\€BY7ÍBVj÷BS!BPÑJBNtBK7BHjÇBEñBBÑB@DB=7mB:jB7ÁB4ÐëB2B/0Y¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ÈB}­+BzàUBxBuFšBryÒBo¬üBlà%BjOBgFxBdy¢Ba¬ÌB^ßõB\BYFIBVyrBS¬BPßÆBNïBKFBHyCBE¬lBBßB@ÀB=EéB:yB7¬=B4Ø¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ÖÿB}»§BzîÐBx!úBuU$BrMBo»wBlî Bj!ÊBgTôBd
+Ba»GB^îqB\!BYTÄBVîBS»BPîABN!kBKTBHœBEºèBBîB@!;B=TeB:©¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}åzB}Ê"BzýLBx0uBucBrÈBoÉòBlý
+Bj0EBgcoBdBaÉÂB^üìB\0BYc?BViBSÉBPüŒBN/åBKcBH9BEÉcBBüB@(Ñ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}óöB}ØB{
+ÅBx>îBurBr¥BBoØkBm
+Bj>¿BgqèBd¥BaØ<B_
+eB\>BYq¹BV€âBSØ
+BQ
+6BN>_BKqBH€³BEÐ÷¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~qB}çB{@BxMjBuBr³œBoæçBmBjM:BgdBd³Baæ·B_áB\M
+BY3BV³^BSæBQ±BNLÛBKy¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~ìB}õB{(»Bx[åBuBrÂ8BoõbBm(Bj[µBgßBdÂ	Baõ2B_([B\[BY¯BVÁÙBSõBQ!G¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~gB~
+B{77Bxj`BuBrÐŽBpÝBm7Bjj1BgZBdÐBb®B_6×B\jBY+BVÉo¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~-ãB~B{E²BxxÜBu¬Brß/BpYBmEBjx«Bg«ÖBdÞÿBb)B_ESB\q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~<^B~!B{T-BxWBuºBríªBp ÓBmSþBj'BgºQBdí{Bb¿¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~JÙB~/B{b©BxÒBuÈûBrü&Bp/OBmbyBj£BgÁç¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~YUB~=úB{q#Bx€MBu×wBs
+¡Bp=ËBmj¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~gÏB~LuB{Bx²ÉBuåóBs7¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~vKB~ZñB{Bxº_¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~ÇB~b
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             B|  Bx  Bt  Bp  Bl  Bh  Bd  B`  B\  BX  BT  BP  BL  BH  BD  B@  B<  B8  B4  B0  B,  B(  B$  B   B
+  B  B  B  B
+  B  B  B   Aø  Að  Aè  Aà  AØ  AÐ  AÈ  AÀ  Až  A°  Aš  A   A  A  A  A  Ap  A`  AP  A@  A0  A   A  A   @à  @À  @   @  @@  @   ?      B|
+=Bx
+=Bt
+=Bp
+=Bl
+=Bh
+=Bd
+=B`
+=B\
+=BX
+=BT
+=BP
+=BL
+=BH
+=BD
+=B@
+=B<
+=B8
+=B4
+=B0
+=B,
+=B(
+=B$
+=B 
+=B
+
+=B
+=B
+=B
+=B
+
+=B
+=B
+=B 
+=Aø{Að{Aè{Aà{AØ{AÐ{AÈ{AÀ{Až{A°{Aš{A {A{A{A{A{Ap(öA`(öAP(öA@(öA0(öA (öA(öA (ö@àQì@ÀQì@ Qì@Qì@@£×@ £×?G®<#×
+B|{Bx{Bt{Bp{Bl{Bh{Bd{B`{B\{BX{BT{BP{BL{BH{BD{B@{B<{B8{B4{B0{B,{B({B${B {B
+{B{B{B{B
+{B{B{B {Aø(öAð(öAè(öAà(öAØ(öAÐ(öAÈ(öAÀ(öAž(öA°(öAš(öA (öA(öA(öA(öA(öApQìA`QìAPQìA@QìA0QìA QìAQìA Qì@à£×@À£×@ £×@£×@AG®@G®?\<£×
+B|
+žBx
+žBt
+žBp
+žBl
+žBh
+žBd
+žB`
+žB\
+žBX
+žBT
+žBP
+žBL
+žBH
+žBD
+žB@
+žB<
+žB8
+žB4
+žB0
+žB,
+žB(
+žB$
+žB 
+žB
+
+žB
+žB
+žB
+žB
+
+žB
+žB
+žB 
+žAø=qAð=qAè=qAà=qAØ=qAÐ=qAÈ=qAÀ=qAž=qA°=qAš=qA =qA=qA=qA=qA=qApzáA`záAPzáA@záA0záA záAzáA zá@àõÃ@ÀõÃ@ õÃ@õÃ@Aë
+@ë
+?×
+<õÂB|(öBx(öBt(öBp(öBl(öBh(öBd(öB`(öB\(öBX(öBT(öBP(öBL(öBH(öBD(öB@(öB<(öB8(öB4(öB0(öB,(öB((öB$(öB (öB
+(öB(öB(öB(öB
+(öB(öB(öB (öAøQìAðQìAèQìAàQìAØQìAÐQìAÈQìAÀQìAžQìA°QìAšQìA QìAQìAQìAQìAQìAp£×A`£×AP£×A@£×A0£×A £×A£×A £×@áG®@ÁG®@¡G®@G®@B\@\?
+
+ž=#×
+B|33Bx33Bt33Bp33Bl33Bh33Bd33B`33B\33BX33BT33BP33BL33BH33BD33B@33B<33B833B433B033B,33B(33B$33B 33B
+33B33B33B33B
+33B33B33B 33AøffAðffAèffAàffAØffAÐffAÈffAÀffAžffA°ffAšffA ffAffAffAffAffApÌÍA`ÌÍAPÌÍA@ÌÍA0ÌÍA ÌÍAÌÍA ÌÍ@á@Á@¡@@C33@33?ff=LÌÍB|=qBx=qBt=qBp=qBl=qBh=qBd=qB`=qB\=qBX=qBT=qBP=qBL=qBH=qBD=qB@=qB<=qB8=qB4=qB0=qB,=qB(=qB$=qB =qB
+=qB=qB=qB=qB
+=qB=qB=qB =qAøzáAðzáAèzáAàzáAØzáAÐzáAÈzáAÀzáAžzáA°záAšzáA záAzáAzáAzáAzáApõÃA`õÃAPõÃA@õÃA0õÃA õÃAõÃA õÃ@áë
+@Áë
+@¡ë
+@ë
+@C×
+@×
+?®=uÂB|G®BxG®BtG®BpG®BlG®BhG®BdG®B`G®B\G®BXG®BTG®BPG®BLG®BHG®BDG®B@G®B<G®B8G®B4G®B0G®B,G®B(G®B$G®B G®B
+G®BG®BG®BG®B
+G®BG®BG®B G®Aø\Að\Aè\Aà\AØ\AÐ\AÈ\AÀ\Až\A°\Aš\A \A\A\A\A\Aq
+žAa
+žAQ
+žAA
+žA1
+žA!
+žA
+žA
+ž@â=q@Â=q@¢=q@=q@Dzá@zá?õÃ=\)B|QìBxQìBtQìBpQìBlQìBhQìBdQìB`QìB\QìBXQìBTQìBPQìBLQìBHQìBDQìB@QìB<QìB8QìB4QìB0QìB,QìB(QìB$QìB QìB
+QìBQìBQìBQìB
+QìBQìBQìB QìAø£×Að£×Aè£×Aà£×AØ£×AÐ£×AÈ£×AÀ£×Až£×A°£×Aš£×A £×A£×A£×A£×A£×AqG®AaG®AQG®AAG®A1G®A!G®AG®AG®@â\@Â\@¢\@\@E
+ž@
+ž?=q=£×
+B|\)Bx\)Bt\)Bp\)Bl\)Bh\)Bd\)B`\)B\\)BX\)BT\)BP\)BL\)BH\)BD\)B@\)B<\)B8\)B4\)B0\)B,\)B(\)B$\)B \)B
+\)B\)B\)B\)B
+\)B\)B\)B \)AøžRAðžRAèžRAàžRAØžRAÐžRAÈžRAÀžRAžžRA°žRAšžRA žRAžRAžRAžRAžRAqp€Aap€AQp€AAp€A1p€A!p€Ap€Ap€@âáH@ÂáH@¢áH@áH@EÂ@Â?
+=žQìB|ffBxffBtffBpffBlffBhffBdffB`ffB\ffBXffBTffBPffBLffBHffBDffB@ffB<ffB8ffB4ffB0ffB,ffB(ffB$ffB ffB
+ffBffBffBffB
+ffBffBffB ffAøÌÍAðÌÍAèÌÍAàÌÍAØÌÍAÐÌÍAÈÌÍAÀÌÍAžÌÍA°ÌÍAšÌÍA ÌÍAÌÍAÌÍAÌÍAÌÍAqAaAQAAA1A!AA@ã33@Ã33@£33@33@Fff@ff?ÌÍ=ÌÌÍB|p€Bxp€Btp€Bpp€Blp€Bhp€Bdp€B`p€B\p€BXp€BTp€BPp€BLp€BHp€BDp€B@p€B<p€B8p€B4p€B0p€B,p€B(p€B$p€B p€B
+p€Bp€Bp€Bp€B
+p€Bp€Bp€B p€AøáHAðáHAèáHAàáHAØáHAÐáHAÈáHAÀáHAžáHA°áHAšáHA áHAáHAáHAáHAáHAqÂAaÂAQÂAAÂA1ÂA!ÂAÂAÂ@ã
+@Ã
+@£
+@
+@G
+=@
+=?{=áG®B|záBxzáBtzáBpzáBlzáBhzáBdzáB`záB\záBXzáBTzáBPzáBLzáBHzáBDzáB@záB<záB8záB4záB0záB,záB(záB$záB záB
+záBzáBzáBzáB
+záBzáBzáB záAøõÃAðõÃAèõÃAàõÃAØõÃAÐõÃAÈõÃAÀõÃAžõÃA°õÃAšõÃA õÃAõÃAõÃAõÃAõÃAqë
+Aaë
+AQë
+AAë
+A1ë
+A!ë
+Aë
+Aë
+@ã×
+@Ã×
+@£×
+@×
+@G®@®?\)=õÂB|
+Bx
+Bt
+Bp
+Bl
+Bh
+Bd
+B`
+B\
+BX
+BT
+BP
+BL
+BH
+BD
+B@
+B<
+B8
+B4
+B0
+B,
+B(
+B$
+B 
+B
+
+B
+B
+B
+B
+
+B
+B
+B 
+Aù
+=Añ
+=Aé
+=Aá
+=AÙ
+=AÑ
+=AÉ
+=AÁ
+=A¹
+=A±
+=A©
+=A¡
+=A
+=A
+=A
+=A
+=Ar{Ab{AR{AB{A2{A"{A{A{@ä(ö@Ä(ö@€(ö@(ö@HQì@Qì?£×>
+žB|\Bx\Bt\Bp\Bl\Bh\Bd\B`\B\\BX\BT\BP\BL\BH\BD\B@\B<\B8\B4\B0\B,\B(\B$\B \B
+\B\B\B\B
+\B\B\B \Aù
+žAñ
+žAé
+žAá
+žAÙ
+žAÑ
+žAÉ
+žAÁ
+žA¹
+žA±
+žA©
+žA¡
+žA
+žA
+žA
+žA
+žAr=qAb=qAR=qAB=qA2=qA"=qA=qA=q@äzá@Äzá@€zá@zá@HõÃ@õÃ?ë
+>\)B|BxBtBpBlBhBdB`B\BXBTBPBLBHBDB@B<B8B4B0B,B(B$B B
+BBBB
+BBB Aù33Añ33Aé33Aá33AÙ33AÑ33AÉ33AÁ33A¹33A±33A©33A¡33A33A33A33A33ArffAbffARffABffA2ffA"ffAffAff@äÌÍ@ÄÌÍ@€ÌÍ@ÌÍ@I@	?33>B|£×Bx£×Bt£×Bp£×Bl£×Bh£×Bd£×B`£×B\£×BX£×BT£×BP£×BL£×BH£×BD£×B@£×B<£×B8£×B4£×B0£×B,£×B(£×B$£×B £×B
+£×B£×B£×B£×B
+£×B£×B£×B £×AùG®AñG®AéG®AáG®AÙG®AÑG®AÉG®AÁG®A¹G®A±G®A©G®A¡G®AG®AG®AG®AG®Ar\Ab\AR\AB\A2\A"\A\A\@å
+ž@Å
+ž@¥
+ž@
+
+ž@J=q@
+=q?zá>#×
+B|®Bx®Bt®Bp®Bl®Bh®Bd®B`®B\®BX®BT®BP®BL®BH®BD®B@®B<®B8®B4®B0®B,®B(®B$®B ®B
+®B®B®B®B
+®B®B®B ®Aù\)Añ\)Aé\)Aá\)AÙ\)AÑ\)AÉ\)AÁ\)A¹\)A±\)A©\)A¡\)A\)A\)A\)A\)AržRAbžRARžRABžRA2žRA"žRAžRAžR@åp€@Åp€@¥p€@
+p€@JáH@
+áH?Â>.{B|žRBxžRBtžRBpžRBlžRBhžRBdžRB`žRB\žRBXžRBTžRBPžRBLžRBHžRBDžRB@žRB<žRB8žRB4žRB0žRB,žRB(žRB$žRB žRB
+žRBžRBžRBžRB
+žRBžRBžRB žRAùp€Añp€Aép€Aáp€AÙp€AÑp€AÉp€AÁp€A¹p€A±p€A©p€A¡p€Ap€Ap€Ap€Ap€AráHAbáHARáHABáHA2áHA"áHAáHAáH@åÂ@ÅÂ@¥Â@
+Â@K
+@
+
+?
+>>8QìB|ÂBxÂBtÂBpÂBlÂBhÂBdÂB`ÂB\ÂBXÂBTÂBPÂBLÂBHÂBDÂB@ÂB<ÂB8ÂB4ÂB0ÂB,ÂB(ÂB$ÂB ÂB
+ÂBÂBÂBÂB
+ÂBÂBÂB ÂAù
+Añ
+Aé
+Aá
+AÙ
+AÑ
+AÉ
+AÁ
+A¹
+A±
+A©
+A¡
+A
+A
+A
+A
+As
+=Ac
+=AS
+=AC
+=A3
+=A#
+=A
+=A
+=@æ{@Æ{@Š{@{@L(ö@
+(ö?Qì>B\B|ÌÍBxÌÍBtÌÍBpÌÍBlÌÍBhÌÍBdÌÍB`ÌÍB\ÌÍBXÌÍBTÌÍBPÌÍBLÌÍBHÌÍBDÌÍB@ÌÍB<ÌÍB8ÌÍB4ÌÍB0ÌÍB,ÌÍB(ÌÍB$ÌÍB ÌÍB
+ÌÍBÌÍBÌÍBÌÍB
+ÌÍBÌÍBÌÍB ÌÍAùAñAéAáAÙAÑAÉAÁA¹A±A©A¡AAAAAs33Ac33AS33AC33A333A#33A33A33@æff@Æff@Šff@ff@LÌÍ@
+ÌÍ?>LÌÍB|×
+Bx×
+Bt×
+Bp×
+Bl×
+Bh×
+Bd×
+B`×
+B\×
+BX×
+BT×
+BP×
+BL×
+BH×
+BD×
+B@×
+B<×
+B8×
+B4×
+B0×
+B,×
+B(×
+B$×
+B ×
+B
+×
+B×
+B×
+B×
+B
+×
+B×
+B×
+B ×
+Aù®Añ®Aé®Aá®AÙ®AÑ®AÉ®AÁ®A¹®A±®A©®A¡®A®A®A®A®As\)Ac\)AS\)AC\)A3\)A#\)A\)A\)@æžR@ÆžR@ŠžR@žR@Mp€@
+p€?áH>W
+=B|áHBxáHBtáHBpáHBláHBháHBdáHB`áHB\áHBXáHBTáHBPáHBLáHBHáHBDáHB@áHB<áHB8áHB4áHB0áHB,áHB(áHB$áHB áHB
+áHBáHBáHBáHB
+áHBáHBáHB áHAùÂAñÂAéÂAáÂAÙÂAÑÂAÉÂAÁÂA¹ÂA±ÂA©ÂA¡ÂAÂAÂAÂAÂAs
+Ac
+AS
+AC
+A3
+A#
+A
+A
+@ç
+=@Ç
+=@§
+=@
+=@N{@{?(ö>aG®B|ë
+Bxë
+Btë
+Bpë
+Blë
+Bhë
+Bdë
+B`ë
+B\ë
+BXë
+BTë
+BPë
+BLë
+BHë
+BDë
+B@ë
+B<ë
+B8ë
+B4ë
+B0ë
+B,ë
+B(ë
+B$ë
+B ë
+B
+ë
+Bë
+Bë
+Bë
+B
+ë
+Bë
+Bë
+B ë
+Aù×
+Añ×
+Aé×
+Aá×
+AÙ×
+AÑ×
+AÉ×
+AÁ×
+A¹×
+A±×
+A©×
+A¡×
+A×
+A×
+A×
+A×
+As®Ac®AS®AC®A3®A#®A®A®@ç\)@Ç\)@§\)@\)@NžR@žR?p€>k
+B|õÃBxõÃBtõÃBpõÃBlõÃBhõÃBdõÃB`õÃB\õÃBXõÃBTõÃBPõÃBLõÃBHõÃBDõÃB@õÃB<õÃB8õÃB4õÃB0õÃB,õÃB(õÃB$õÃB õÃB
+õÃBõÃBõÃBõÃB
+õÃBõÃBõÃB õÃAùë
+Añë
+Aéë
+Aáë
+AÙë
+AÑë
+AÉë
+AÁë
+A¹ë
+A±ë
+A©ë
+A¡ë
+Aë
+Aë
+Aë
+Aë
+As×
+Ac×
+AS×
+AC×
+A3×
+A#×
+A×
+A×
+@ç®@Ç®@§®@®@O\)@\)?žR>uÂB}  By  Bu  Bq  Bm  Bi  Be  Ba  B]  BY  BU  BQ  BM  BI  BE  BA  B=  B9  B5  B1  B-  B)  B%  B!  B
+  B  B  B  B
+  B	  B  B  Aú  Aò  Aê  Aâ  AÚ  AÒ  AÊ  AÂ  Aº  A²  Aª  A¢  A  A  A  A  At  Ad  AT  AD  A4  A$  A  A  @è  @È  @š  @  @P  @  ?   >  B}
+=By
+=Bu
+=Bq
+=Bm
+=Bi
+=Be
+=Ba
+=B]
+=BY
+=BU
+=BQ
+=BM
+=BI
+=BE
+=BA
+=B=
+=B9
+=B5
+=B1
+=B-
+=B)
+=B%
+=B!
+=B
+
+=B
+=B
+=B
+=B
+=B	
+=B
+=B
+=Aú{Aò{Aê{Aâ{AÚ{AÒ{AÊ{AÂ{Aº{A²{Aª{A¢{A{A{A{A{At(öAd(öAT(öAD(öA4(öA$(öA(öA(ö@èQì@ÈQì@šQì@Qì@P£×@£×?¡G®>
+
+žB}{By{Bu{Bq{Bm{Bi{Be{Ba{B]{BY{BU{BQ{BM{BI{BE{BA{B={B9{B5{B1{B-{B){B%{B!{B
+{B{B{B{B
+{B	{B{B{Aú(öAò(öAê(öAâ(öAÚ(öAÒ(öAÊ(öAÂ(öAº(öA²(öAª(öA¢(öA(öA(öA(öA(öAtQìAdQìATQìADQìA4QìA$QìAQìAQì@è£×@È£×@š£×@£×@QG®@G®?¢\>=qB}
+žBy
+žBu
+žBq
+žBm
+žBi
+žBe
+žBa
+žB]
+žBY
+žBU
+žBQ
+žBM
+žBI
+žBE
+žBA
+žB=
+žB9
+žB5
+žB1
+žB-
+žB)
+žB%
+žB!
+žB
+
+žB
+žB
+žB
+žB
+
+žB	
+žB
+žB
+žAú=qAò=qAê=qAâ=qAÚ=qAÒ=qAÊ=qAÂ=qAº=qA²=qAª=qA¢=qA=qA=qA=qA=qAtzáAdzáATzáADzáA4záA$záAzáAzá@èõÃ@ÈõÃ@šõÃ@õÃ@Që
+@ë
+?£×
+>\)B}(öBy(öBu(öBq(öBm(öBi(öBe(öBa(öB](öBY(öBU(öBQ(öBM(öBI(öBE(öBA(öB=(öB9(öB5(öB1(öB-(öB)(öB%(öB!(öB
+(öB(öB(öB(öB
+(öB	(öB(öB(öAúQìAòQìAêQìAâQìAÚQìAÒQìAÊQìAÂQìAºQìA²QìAªQìA¢QìAQìAQìAQìAQìAt£×Ad£×AT£×AD£×A4£×A$£×A£×A£×@éG®@ÉG®@©G®@G®@R\@\?¥
+ž>záB}33By33Bu33Bq33Bm33Bi33Be33Ba33B]33BY33BU33BQ33BM33BI33BE33BA33B=33B933B533B133B-33B)33B%33B!33B
+33B33B33B33B
+33B	33B33B33AúffAòffAêffAâffAÚffAÒffAÊffAÂffAºffA²ffAªffA¢ffAffAffAffAffAtÌÍAdÌÍATÌÍADÌÍA4ÌÍA$ÌÍAÌÍAÌÍ@é@É@©@@S33@33?Šff>B}=qBy=qBu=qBq=qBm=qBi=qBe=qBa=qB]=qBY=qBU=qBQ=qBM=qBI=qBE=qBA=qB==qB9=qB5=qB1=qB-=qB)=qB%=qB!=qB
+=qB=qB=qB=qB
+=qB	=qB=qB=qAúzáAòzáAêzáAâzáAÚzáAÒzáAÊzáAÂzáAºzáA²záAªzáA¢záAzáAzáAzáAzáAtõÃAdõÃATõÃADõÃA4õÃA$õÃAõÃAõÃ@éë
+@Éë
+@©ë
+@ë
+@S×
+@×
+?§®>žRB}G®ByG®BuG®BqG®BmG®BiG®BeG®BaG®B]G®BYG®BUG®BQG®BMG®BIG®BEG®BAG®B=G®B9G®B5G®B1G®B-G®B)G®B%G®B!G®B
+G®BG®BG®BG®B
+G®B	G®BG®BG®Aú\Aò\Aê\Aâ\AÚ\AÒ\AÊ\AÂ\Aº\A²\Aª\A¢\A\A\A\A\Au
+žAe
+žAU
+žAE
+žA5
+žA%
+žA
+žA
+ž@ê=q@Ê=q@ª=q@=q@Tzá@zá?šõÂ>£×
+B}QìByQìBuQìBqQìBmQìBiQìBeQìBaQìB]QìBYQìBUQìBQQìBMQìBIQìBEQìBAQìB=QìB9QìB5QìB1QìB-QìB)QìB%QìB!QìB
+QìBQìBQìBQìB
+QìB	QìBQìBQìAú£×Aò£×Aê£×Aâ£×AÚ£×AÒ£×AÊ£×AÂ£×Aº£×A²£×Aª£×A¢£×A£×A£×A£×A£×AuG®AeG®AUG®AEG®A5G®A%G®AG®AG®@ê\@Ê\@ª\@\@U
+ž@
+ž?ª=q>šõÃB}\)By\)Bu\)Bq\)Bm\)Bi\)Be\)Ba\)B]\)BY\)BU\)BQ\)BM\)BI\)BE\)BA\)B=\)B9\)B5\)B1\)B-\)B)\)B%\)B!\)B
+\)B\)B\)B\)B
+\)B	\)B\)B\)AúžRAòžRAêžRAâžRAÚžRAÒžRAÊžRAÂžRAºžRA²žRAªžRA¢žRAžRAžRAžRAžRAup€Aep€AUp€AEp€A5p€A%p€Ap€Ap€@êáH@ÊáH@ªáH@áH@UÂ@Â?«
+>®{B}ffByffBuffBqffBmffBiffBeffBaffB]ffBYffBUffBQffBMffBIffBEffBAffB=ffB9ffB5ffB1ffB-ffB)ffB%ffB!ffB
+ffBffBffBffB
+ffB	ffBffBffAúÌÍAòÌÍAêÌÍAâÌÍAÚÌÍAÒÌÍAÊÌÍAÂÌÍAºÌÍA²ÌÍAªÌÍA¢ÌÍAÌÍAÌÍAÌÍAÌÍAuAeAUAEA5A%AA@ë33@Ë33@«33@33@Vff@ff?¬ÌÍ>³33B}p€Byp€Bup€Bqp€Bmp€Bip€Bep€Bap€B]p€BYp€BUp€BQp€BMp€BIp€BEp€BAp€B=p€B9p€B5p€B1p€B-p€B)p€B%p€B!p€B
+p€Bp€Bp€Bp€B
+p€B	p€Bp€Bp€AúáHAòáHAêáHAâáHAÚáHAÒáHAÊáHAÂáHAºáHA²áHAªáHA¢áHAáHAáHAáHAáHAuÂAeÂAUÂAEÂA5ÂA%ÂAÂAÂ@ë
+@Ë
+@«
+@
+@W
+>@
+>?®{>žQìB}záByzáBuzáBqzáBmzáBizáBezáBazáB]záBYzáBUzáBQzáBMzáBIzáBEzáBAzáB=záB9záB5záB1záB-záB)záB%záB!záB
+záBzáBzáBzáB
+záB	záBzáBzáAúõÃAòõÃAêõÃAâõÃAÚõÃAÒõÃAÊõÃAÂõÃAºõÃA²õÃAªõÃA¢õÃAõÃAõÃAõÃAõÃAuë
+Aeë
+AUë
+AEë
+A5ë
+A%ë
+Aë
+Aë
+@ë×
+@Ë×
+@«×
+@×
+@W®@®?¯\)>œp€B}
+By
+Bu
+Bq
+Bm
+Bi
+Be
+Ba
+B]
+BY
+BU
+BQ
+BM
+BI
+BE
+BA
+B=
+B9
+B5
+B1
+B-
+B)
+B%
+B!
+B
+
+B
+B
+B
+B
+
+B	
+B
+B
+Aû
+=Aó
+=Aë
+=Aã
+=AÛ
+=AÓ
+=AË
+=AÃ
+=A»
+=A³
+=A«
+=A£
+=A
+=A
+=A
+=A
+=Av{Af{AV{AF{A6{A&{A{A{@ì(ö@Ì(ö@¬(ö@(ö@XQì@Qì?°£×>Â\B}\By\Bu\Bq\Bm\Bi\Be\Ba\B]\BY\BU\BQ\BM\BI\BE\BA\B=\B9\B5\B1\B-\B)\B%\B!\B
+\B\B\B\B
+\B	\B\B\Aû
+žAó
+žAë
+žAã
+žAÛ
+žAÓ
+žAË
+žAÃ
+žA»
+žA³
+žA«
+žA£
+žA
+žA
+žA
+žA
+žAv=qAf=qAV=qAF=qA6=qA&=qA=qA=q@ìzá@Ìzá@¬zá@zá@XõÂ@õÂ?±ë
+>Ç®B}ByBuBqBmBiBeBaB]BYBUBQBMBIBEBAB=B9B5B1B-B)B%B!B
+BBBB
+B	BBAû33Aó33Aë33Aã33AÛ33AÓ33AË33AÃ33A»33A³33A«33A£33A33A33A33A33AvffAfffAVffAFffA6ffA&ffAffAff@ìÌÍ@ÌÌÍ@¬ÌÍ@ÌÍ@Y@?³33>ÌÌÍB}£×By£×Bu£×Bq£×Bm£×Bi£×Be£×Ba£×B]£×BY£×BU£×BQ£×BM£×BI£×BE£×BA£×B=£×B9£×B5£×B1£×B-£×B)£×B%£×B!£×B
+£×B£×B£×B£×B
+£×B	£×B£×B£×AûG®AóG®AëG®AãG®AÛG®AÓG®AËG®AÃG®A»G®A³G®A«G®A£G®AG®AG®AG®AG®Av\Af\AV\AF\A6\A&\A\A\@í
+ž@Í
+ž@­
+ž@
+ž@Z=q@=q?Žzá>Ñë
+B}®By®Bu®Bq®Bm®Bi®Be®Ba®B]®BY®BU®BQ®BM®BI®BE®BA®B=®B9®B5®B1®B-®B)®B%®B!®B
+®B®B®B®B
+®B	®B®B®Aû\)Aó\)Aë\)Aã\)AÛ\)AÓ\)AË\)AÃ\)A»\)A³\)A«\)A£\)A\)A\)A\)A\)AvžRAfžRAVžRAFžRA6žRA&žRAžRAžR@íp€@Íp€@­p€@p€@ZáH@áH?µÂ>×
+=B}žRByžRBužRBqžRBmžRBižRBežRBažRB]žRBYžRBUžRBQžRBMžRBIžRBEžRBAžRB=žRB9žRB5žRB1žRB-žRB)žRB%žRB!žRB
+žRBžRBžRBžRB
+žRB	žRBžRBžRAûp€Aóp€Aëp€Aãp€AÛp€AÓp€AËp€AÃp€A»p€A³p€A«p€A£p€Ap€Ap€Ap€Ap€AváHAfáHAVáHAFáHA6áHA&áHAáHAáH@íÂ@ÍÂ@­Â@Â@[
+@
+?·
+>>Ü(öB}ÂByÂBuÂBqÂBmÂBiÂBeÂBaÂB]ÂBYÂBUÂBQÂBMÂBIÂBEÂBAÂB=ÂB9ÂB5ÂB1ÂB-ÂB)ÂB%ÂB!ÂB
+ÂBÂBÂBÂB
+ÂB	ÂBÂBÂAû
+Aó
+Aë
+Aã
+AÛ
+AÓ
+AË
+AÃ
+A»
+A³
+A«
+A£
+A
+A
+A
+A
+Aw
+=Ag
+=AW
+=AG
+=A7
+=A'
+=A
+=A
+=@î{@Î{@®{@{@\(ö@
+(ö?žQì>áG®B}ÌÍByÌÍBuÌÍBqÌÍBmÌÍBiÌÍBeÌÍBaÌÍB]ÌÍBYÌÍBUÌÍBQÌÍBMÌÍBIÌÍBEÌÍBAÌÍB=ÌÍB9ÌÍB5ÌÍB1ÌÍB-ÌÍB)ÌÍB%ÌÍB!ÌÍB
+ÌÍBÌÍBÌÍBÌÍB
+ÌÍB	ÌÍBÌÍBÌÍAûAóAëAãAÛAÓAËAÃA»A³A«A£AAAAAw33Ag33AW33AG33A733A'33A33A33@îff@Îff@®ff@ff@\ÌÍ@
+ÌÍ?¹>æffB}×
+By×
+Bu×
+Bq×
+Bm×
+Bi×
+Be×
+Ba×
+B]×
+BY×
+BU×
+BQ×
+BM×
+BI×
+BE×
+BA×
+B=×
+B9×
+B5×
+B1×
+B-×
+B)×
+B%×
+B!×
+B
+×
+B×
+B×
+B×
+B
+×
+B	×
+B×
+B×
+Aû®Aó®Aë®Aã®AÛ®AÓ®AË®AÃ®A»®A³®A«®A£®A®A®A®A®Aw\)Ag\)AW\)AG\)A7\)A'\)A\)A\)@îžR@ÎžR@®žR@žR@]p€@
+p€?ºáH>ë
+B}áHByáHBuáHBqáHBmáHBiáHBeáHBaáHB]áHBYáHBUáHBQáHBMáHBIáHBEáHBAáHB=áHB9áHB5áHB1áHB-áHB)áHB%áHB!áHB
+áHBáHBáHBáHB
+áHB	áHBáHBáHAûÂAóÂAëÂAãÂAÛÂAÓÂAËÂAÃÂA»ÂA³ÂA«ÂA£ÂAÂAÂAÂAÂAw
+Ag
+AW
+AG
+A7
+A'
+A
+A
+@ï
+=@Ï
+=@¯
+=@
+=@^{@
+{?Œ(ö>ð£×B}ë
+Byë
+Buë
+Bqë
+Bmë
+Bië
+Beë
+Baë
+B]ë
+BYë
+BUë
+BQë
+BMë
+BIë
+BEë
+BAë
+B=ë
+B9ë
+B5ë
+B1ë
+B-ë
+B)ë
+B%ë
+B!ë
+B
+ë
+Bë
+Bë
+Bë
+B
+ë
+B	ë
+Bë
+Bë
+Aû×
+Aó×
+Aë×
+Aã×
+AÛ×
+AÓ×
+AË×
+AÃ×
+A»×
+A³×
+A«×
+A£×
+A×
+A×
+A×
+A×
+Aw®Ag®AW®AG®A7®A'®A®A®@ï\)@Ï\)@¯\)@\)@^žR@
+žR?œp€>õÂB}õÃByõÃBuõÃBqõÃBmõÃBiõÃBeõÃBaõÃB]õÃBYõÃBUõÃBQõÃBMõÃBIõÃBEõÃBAõÃB=õÃB9õÃB5õÃB1õÃB-õÃB)õÃB%õÃB!õÃB
+õÃBõÃBõÃBõÃB
+õÃB	õÃBõÃBõÃAûë
+Aóë
+Aëë
+Aãë
+AÛë
+AÓë
+AËë
+AÃë
+A»ë
+A³ë
+A«ë
+A£ë
+Aë
+Aë
+Aë
+Aë
+Aw×
+Ag×
+AW×
+AG×
+A7×
+A'×
+A×
+A×
+@ï®@Ï®@¯®@®@_\)@\)?ŸžR>úáHB~  Bz  Bv  Br  Bn  Bj  Bf  Bb  B^  BZ  BV  BR  BN  BJ  BF  BB  B>  B:  B6  B2  B.  B*  B&  B"  B
+  B  B  B  B  B
+  B  B  Aü  Aô  Aì  Aä  AÜ  AÔ  AÌ  AÄ  AŒ  AŽ  A¬  A€  A  A  A  A  Ax  Ah  AX  AH  A8  A(  A  A  @ð  @Ð  @°  @  @`  @   ?À  ?   B~
+=Bz
+=Bv
+=Br
+=Bn
+=Bj
+=Bf
+=Bb
+=B^
+=BZ
+=BV
+=BR
+=BN
+=BJ
+=BF
+=BB
+=B>
+=B:
+=B6
+=B2
+=B.
+=B*
+=B&
+=B"
+=B
+
+=B
+=B
+=B
+=B
+=B
+
+=B
+=B
+=Aü{Aô{Aì{Aä{AÜ{AÔ{AÌ{AÄ{AŒ{AŽ{A¬{A€{A{A{A{A{Ax(öAh(öAX(öAH(öA8(öA((öA(öA(ö@ðQì@ÐQì@°Qì@Qì@`£×@ £×?ÁG®?\B~{Bz{Bv{Br{Bn{Bj{Bf{Bb{B^{BZ{BV{BR{BN{BJ{BF{BB{B>{B:{B6{B2{B.{B*{B&{B"{B
+{B{B{B{B{B
+{B{B{Aü(öAô(öAì(öAä(öAÜ(öAÔ(öAÌ(öAÄ(öAŒ(öAŽ(öA¬(öA€(öA(öA(öA(öA(öAxQìAhQìAXQìAHQìA8QìA(QìAQìAQì@ð£×@Ð£×@°£×@£×@aG®@!G®?Â\?
+žB~
+žBz
+žBv
+žBr
+žBn
+žBj
+žBf
+žBb
+žB^
+žBZ
+žBV
+žBR
+žBN
+žBJ
+žBF
+žBB
+žB>
+žB:
+žB6
+žB2
+žB.
+žB*
+žB&
+žB"
+žB
+
+žB
+žB
+žB
+žB
+žB
+
+žB
+žB
+žAü=qAô=qAì=qAä=qAÜ=qAÔ=qAÌ=qAÄ=qAŒ=qAŽ=qA¬=qA€=qA=qA=qA=qA=qAxzáAhzáAXzáAHzáA8záA(záAzáAzá@ðõÂ@ÐõÂ@°õÂ@õÂ@aë
+@!ë
+?Ã×
+?®B~(öBz(öBv(öBr(öBn(öBj(öBf(öBb(öB^(öBZ(öBV(öBR(öBN(öBJ(öBF(öBB(öB>(öB:(öB6(öB2(öB.(öB*(öB&(öB"(öB
+(öB(öB(öB(öB(öB
+(öB(öB(öAüQìAôQìAìQìAäQìAÜQìAÔQìAÌQìAÄQìAŒQìAŽQìA¬QìA€QìAQìAQìAQìAQìAx£×Ah£×AX£×AH£×A8£×A(£×A£×A£×@ñG®@ÑG®@±G®@G®@b\@"\?Å
+ž?
+=qB~33Bz33Bv33Br33Bn33Bj33Bf33Bb33B^33BZ33BV33BR33BN33BJ33BF33BB33B>33B:33B633B233B.33B*33B&33B"33B
+33B33B33B33B33B
+33B33B33AüffAôffAìffAäffAÜffAÔffAÌffAÄffAŒffAŽffA¬ffA€ffAffAffAffAffAxÌÍAhÌÍAXÌÍAHÌÍA8ÌÍA(ÌÍAÌÍAÌÍ@ñ@Ñ@±@@c33@#33?Æff?
+ÌÍB~=qBz=qBv=qBr=qBn=qBj=qBf=qBb=qB^=qBZ=qBV=qBR=qBN=qBJ=qBF=qBB=qB>=qB:=qB6=qB2=qB.=qB*=qB&=qB"=qB
+=qB=qB=qB=qB=qB
+=qB=qB=qAüzáAôzáAìzáAäzáAÜzáAÔzáAÌzáAÄzáAŒzáAŽzáA¬záA€záAzáAzáAzáAzáAxõÃAhõÃAXõÃAHõÃA8õÃA(õÃAõÃAõÃ@ñë
+@Ñë
+@±ë
+@ë
+@c×
+@#×
+?Ç®?\)B~G®BzG®BvG®BrG®BnG®BjG®BfG®BbG®B^G®BZG®BVG®BRG®BNG®BJG®BFG®BBG®B>G®B:G®B6G®B2G®B.G®B*G®B&G®B"G®B
+G®BG®BG®BG®BG®B
+G®BG®BG®Aü\Aô\Aì\Aä\AÜ\AÔ\AÌ\AÄ\AŒ\AŽ\A¬\A€\A\A\A\A\Ay
+žAi
+žAY
+žAI
+žA9
+žA)
+žA
+žA	
+ž@ò=q@Ò=q@²=q@=q@dzá@$zá?ÈõÂ?ë
+B~QìBzQìBvQìBrQìBnQìBjQìBfQìBbQìB^QìBZQìBVQìBRQìBNQìBJQìBFQìBBQìB>QìB:QìB6QìB2QìB.QìB*QìB&QìB"QìB
+QìBQìBQìBQìBQìB
+QìBQìBQìAü£×Aô£×Aì£×Aä£×AÜ£×AÔ£×AÌ£×AÄ£×AŒ£×AŽ£×A¬£×A€£×A£×A£×A£×A£×AyG®AiG®AYG®AIG®A9G®A)G®AG®A	G®@ò\@Ò\@²\@\@e
+ž@%
+ž?Ê=p?záB~\)Bz\)Bv\)Br\)Bn\)Bj\)Bf\)Bb\)B^\)BZ\)BV\)BR\)BN\)BJ\)BF\)BB\)B>\)B:\)B6\)B2\)B.\)B*\)B&\)B"\)B
+\)B\)B\)B\)B\)B
+\)B\)B\)AüžRAôžRAìžRAäžRAÜžRAÔžRAÌžRAÄžRAŒžRAŽžRA¬žRA€žRAžRAžRAžRAžRAyp€Aip€AYp€AIp€A9p€A)p€Ap€A	p€@òáH@ÒáH@²áH@áH@eÂ@%Â?Ë
+
+?
+=B~ffBzffBvffBrffBnffBjffBfffBbffB^ffBZffBVffBRffBNffBJffBFffBBffB>ffB:ffB6ffB2ffB.ffB*ffB&ffB"ffB
+ffBffBffBffBffB
+ffBffBffAüÌÍAôÌÍAìÌÍAäÌÍAÜÌÍAÔÌÍAÌÌÍAÄÌÍAŒÌÍAŽÌÍA¬ÌÍA€ÌÍAÌÍAÌÍAÌÍAÌÍAyAiAYAIA9A)AA	@ó33@Ó33@³33@33@fff@&ff?ÌÌÍ?B~p€Bzp€Bvp€Brp€Bnp€Bjp€Bfp€Bbp€B^p€BZp€BVp€BRp€BNp€BJp€BFp€BBp€B>p€B:p€B6p€B2p€B.p€B*p€B&p€B"p€B
+p€Bp€Bp€Bp€Bp€B
+p€Bp€Bp€AüáHAôáHAìáHAäáHAÜáHAÔáHAÌáHAÄáHAŒáHAŽáHA¬áHA€áHAáHAáHAáHAáHAyÂAiÂAYÂAIÂA9ÂA)ÂAÂA	Â@ó
+@Ó
+@³
+@
+@g
+>@'
+>?Î{?
+(öB~záBzzáBvzáBrzáBnzáBjzáBfzáBbzáB^záBZzáBVzáBRzáBNzáBJzáBFzáBBzáB>záB:záB6záB2záB.záB*záB&záB"záB
+záBzáBzáBzáBzáB
+záBzáBzáAüõÃAôõÃAìõÃAäõÃAÜõÃAÔõÃAÌõÃAÄõÃAŒõÃAŽõÃA¬õÃA€õÃAõÃAõÃAõÃAõÃAyë
+Aië
+AYë
+AIë
+A9ë
+A)ë
+Aë
+A	ë
+@ó×
+@Ó×
+@³×
+@×
+@g®@'®?Ï\)?
+žRB~
+Bz
+Bv
+Br
+Bn
+Bj
+Bf
+Bb
+B^
+BZ
+BV
+BR
+BN
+BJ
+BF
+BB
+B>
+B:
+B6
+B2
+B.
+B*
+B&
+B"
+B
+
+B
+B
+B
+B
+B
+
+B
+B
+Aý
+=Aõ
+=Aí
+=Aå
+=AÝ
+=AÕ
+=AÍ
+=AÅ
+=Aœ
+=Aµ
+=A­
+=A¥
+=A
+=A
+=A
+=A
+
+=Az{Aj{AZ{AJ{A:{A*{A{A
+{@ô(ö@Ô(ö@Ž(ö@(ö@hQì@(Qì?Ð£×?!G®                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B| XB{Ýf¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ÔB{äþBy	¬Bv5@¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|
+OB{óyBy(Bv<ÖBsaBp¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|+ÊB|õBy&£BvKQBsp Bp®Bm¹\Bjäð¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|:FB|pBy5
+BvYÍBs~{Bp£)BmÇ×BjìBh4Be<È¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|HÁB|
+ëByCBvhHBsöBp±¥BmÖSBjûBh¯BeD^Bbi
+B_ ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|W<B|-gByRBvvÃBsrBpÀ BmäÎBk	}Bh.+BeRÙBbwB_6B\ÀäBYìx¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|e·B|;âBy`Bv
+?Bs©íBpÎBmóJBkøBh<ŠBeaUBbB_ª±B\Ï_BYôBWŒBTDP¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|t3B|J]Byo
+BvºBsžhBpÝBnÅBk&sBhK"BeoÐBb~B_¹-B\ÝÛBZBW'7BTKæBQpBN(¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|®B|XØBy}Bv¢5BsÆãBpëBn@Bk4ïBhYBe~KBb¢úB_ÇšB\ìVBZBW5³BTZaBQBN£ŸBKÈlBHô ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|)B|gTByBv°°BsÕ_Bpú
+Bn
+»BkCjBhhBeÇBb±uB_Ö#B\úÒBZBWD.BThÝBQBN²9BKÖçBHûBF DBCKØ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|¥B|uÑByBv¿.BsãÜBqBn-9BkQçBhvBeDBb¿òB_ä¡B]	OBZ-ýBWR¬BTwZBQBNÀ·BKåeBI
+BF.ÁBCSpB@x
+B=£²¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|®B|LByšûBvÍ©BsòWBqBn;ŽBk`bBh
+Be©¿BbÎmB_ó
+B]ÊBZ<yBWa'BT
+ÕBQªBNÏ2BKóàBIBF==BCaëB@B=«HB:ÏöB7û¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ŒB|ÇBy·uBvÜ$Bt ÓBq%BnJ/BknÞBhBež:BbÜéB`B]&EBZJôBWo¢BTQBQžÿBNÝ­BL\BI'
+BFKžBCpgB@B=¹ÃB:ÞqB8 B5'ÎB2Sb¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ËB|¡BByÅñBvêBtMBq3üBnX«Bk}YBh¢BeÆ¶BbëdB`B]4ÁBZYoBW~
+BT¢ÌBQÇzBNì)BL×BI5
+BFZ4BC~âB@£B=È?B:ìíB8B56IB2ZøB/ŠB,«:¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ÙB|¯ŸByÔlBvùBt
+ÉBqBwBng%BkÔBh°BeÕ1BbùßB`
+B]C<BZgêBWBT±GBQÕõBNú€BLRBIDBFh¯BC]B@²
+B=ÖºB:ûhB8 B5DÅB2isB/!B,²ÐB)×~B'¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|è
+B|Ÿ9ByâçBwBt,DBqPòBnu¡BkOBhŸýBeã¬Bc[B`-	B]Q·BZvfBWBT¿ÂBQäqBO	BL-ÍBIR|BFw*BCÙB@ÀB=å5B;	äB8.B5S@B2wïB/B,ÁKB)åùB'
+šB$/VB!Zê¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|öB|ÌµByñcBwBt:¿Bq_nBn
+BkšÊBhÍyBeò'BcÕB`;B]`3BZáBW©BTÎ>BQòìBOBL<IBI`÷BF
+¥BCªTB@ÏB=ó±B;_B8=
+B5aŒB2jB/«B,ÏÇB)ôuB'#B$=ÑB!bB
+.B²Â¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}B|Û0ByÿÞBw$BtI;BqméBnBk·FBhÛôBf ¢Bc%QB`IÿB]n­BZ\BWž
+BTÜ¹BRgBO&BLJÄBIorBF!BCžÏB@Ý}B>,B;&ÚB8KB5p7B2åB/¹B,ÞBB*ðB''B$LMB!pûB
+©BºXBßB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}B|é«BzYBw3BtW¶Bq|eBn¡BkÅÁBhêoBf
+Bc3ÌB`XzB]})BZ¡×BWÆ
+BTë4BRãBO4BLY?BI}îBF¢BCÇJB@ëùB>§B;5UB8ZB5~²B2£aB/ÈB,ìœB*lB'6B$ZÈB!wB
+€%BÈÓBíB0B6ÞBbr¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}!úB|ø&Bz
+ÕBwABtf1BqàBn¯BkÔ=BhøëBf
+BcBGB`föB]€BZ°RBWÕBTù¯BR
+]BOC
+BLg»BIiBF±BCÕÆB@útB>"B;CÑB8hB5-B2±ÜB/ÖB,û9B*çB'DB$iDB!òB
+² B×OBûýB «BEYBjB
+¶B
+ºJ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}0uB}€Bz+RBwP Btt¯Bq]BnŸ
+BkâºBihBf,BcPÅB`usB]!BZŸÐBWã~BU,BR,ÛBOQBLv7BIæBF¿BCäCBAñB>- B;RNB8vüB5«B2ÀYB/åB-	¶B*.dB'SB$wÁB!oB
+Á
+BåÌB
+zB/)BS×Bx
+B
+3B
+ÁâBæB$¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}>ñB}Bz9ÍBw^|Bt*Bq§ØBnÌBkñ5BiãBf:Bc_@B`ïB]šBZÍKBWñùBUšBR;VBO`BL³BI©aBFÎBCòŸBAmB><B;`ÉB8
+xB5ª&B2ÎÔB/óB-1B*<ßB'aB$<B!ªëB
+ÏBôGBöB=€BbRBB
+«¯B
+Ð]Bõ
+BºB>hAþÓø¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}MlB}#BzHIBwl÷Bt¥Bq¶TBnÛBkÿ°Bi$_BfI
+Bcm»B`jB]·BZÛÇBX uBU%#BRIÑBOnBL.BI·ÜBFÜBD9BA%çB>JB;oEB8óB5ž¡B2ÝPB0þB-&¬B*K[B'p	B$·B!¹fB
+ÞB
+ÃB'qBLBpÎB|B
+º*B
+ÞÙBB(5BLãAþã#Aù,Aóš¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}[çB}2BzVÄBw{rBt !BqÄÏBné}Bl,Bi2ÚBfWBc|7B` åB]ÅBZêBBXðBU3BRXMBO|ûBL¡©BIÆXBFëBDŽBA4cB>YB;}¿B8¢nB5Ç
+B2ëËB0yB-5(B*YÖB'~B$£3B!ÇáB
+ìB
+>B5ìBZBIB£÷B
+ÈŠB
+íTBB6±B[_Aÿ AùIwAóÔAíÜ1Aè3X¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}jbB}@Bze?BwîBt®BqÓJBn÷ùBl
+§BiAUBffBc²B`¯`B]ÔBZøœBX
+kBUBBRfÈBOwBL°%BIÔÓBFùBD
+0BABÞB>gB;;B8°éB5ÕB2úFB0
+õB-C£B*hQB' B$±®B!Ö\B
+û
+B
+¹BDgBiBÄB²sB
+×!B
+ûÏB ~BE,BiÚAÿ
+AùfnAó¯ËAíù'AèBAâáAÜã¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}xÝB}O
+BzsºBwhBtœBqáÆBotBl+"BiOÑBftBc-B`œÜB]âB[8BX+çBUPBRuCBOòBLŸ BIãOBGýBD,«BAQYB>vB;¶B8¿dB5äB3ÁB0-oB-R
+B*vÍB'{B$À)B!äØB	B
+.4BRãBwB?BÀîB
+åB
+
+KB.ùBS§BxVAÿ:AùeAóÌÂAî
+Aè_{Aâš×AÜò4A×;AÑž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}YB}]Bz5BwŠäBtËBqð@BoïBl9Bi^LBfúBc§©B`ÌWB]ñB[ŽBX:bBU_BR¿BOšmBLÍBIñÊBGxBD;'BA_ÕB>B;©1B8ÍàB5òB3<B0;ëB-`B*
+GB'©öB$Î¥B!óSBB
+<°Ba^B
+Bª»BÏiB
+ôB
+ÆB=tBb#BÑAÿVÿAù [Aóé·Aî3Aè|rAâÅÎAÝ+A×XAÑ¡äAËëAAÆBh¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ÔB}lBz±Bwµ_BtÚ
+BqþŒBo#jBlHBilÇBfvBc¶$B`ÚÒB]ÿB[$/BXHÝBUmBR:BO¶èBLÛBJ EBG$óBDI¢BAnPB>ÿB;·­B8Ü[B6	B3%žB0JfB-oB*ÃB'žqB$ÝB"ÎB&}B
+K+BoÙBB¹6BÝäBB
+'ABKïBpBLAÿsõAùœQAô®AîP
+AègAââÅAÝ,"A×u~AÑŸÛAÌ7AÆQAÀñAºò¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}€OB}z~Bz,BwÃÚBtèBr
+7Bo1åBlVBi{BBfðBcÄB`éNB^
+üB[2ªBXWYBU|BR µBOÅdBLêBJÀBG3oBDX
+BA|ËB>¡zB;Æ(B8ê×B6
+B343B0XáB-}B*¢>B'ÆìB$ëB"IB4÷B
+YŠB~UB£BÇ±Bì`BB
+5ŒBZkBB£ÇAÿëAùÚHAô#¥AîmAè¶^Aâÿ»AÝIA×uAÑÛÒAÌ%.AÆnAÀ·çA»DAµJ¡A¯¡È¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}²ÊB}ùBz­§BwÒVBt÷Br²Bo@aBleBiœBf®lBcÓB`÷ÈB^
+wB[A&BXeÔBUBR¯1BOÓßBLøBJ
+<BGAêBDfBAGB>¯õB;Ô£B8ùRB6
+ B3B¯B0g]B-
+B*°¹B'ÕhB$úB"
+ÄBCsB
+h!BÏB±~BÖ-BúÛBB
+D8BhæBB²CAÿ­âAù÷?Aô@AîøAèÓUAã
+±AÝfA×¯kAÑøÇAÌB%AÆAÀÔÞA»
+;AµgA¯°ôA©úQA€Qx¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ÁFB}vBzŒ$BwàÓBuBr*0BoNÞBlsBi;BfŒéBcáBaFB^*ôB[O¢BXtQBU BRœ®BOâ\BM
+BJ+¹BGPgBDuBAÄB>ŸrB;ã!B9ÏB6,}B3Q,B0uÚB-B*¿7B'ãåB%B"-BBQðB
+vBMB¿ûBä©B	XB.B
+RµBwcBBÀÀAÿÊÜAú9Aô]AîŠóAèðOAã9¬AÝ	A×ÌeAÒÂAÌ_AÆš{AÀñÙA»;6AµA¯ÍïAªKA€`šAªA,¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ÏÁB}¥òBzÊ BwïNBuüBr8«Bo]YBlBiŠ¶BfËdBcðBaÁB^9oB[^
+BXÌBU§zBRÌ)BOðØBMBJ:4BG^ãBDBAš?B>ÌîB;ñB9JB6:ùB3_§B0UB-©B*Í²B'òaB%B";œB`kB
+
+B©ÈBÎvBó%BÓB<B
+a0B
+ßBªBÏ;AÿçÓAú10AôzAîÃéAé
+FAãV£AÝÿA×é\AÒ2¹AÌ|AÆÅrAÁÏA»X+Aµ¡A¯êæAª4BA€}AÆûAXAYµA°Ü¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}Þ=B}ŽmBzÙBwýÊBu"xBrG&BokÔBlBiµ1BfÙàBcþBa#<B^GëB[lBXGBUµöBRÚ€BOÿRBM$BJH°BGm^BD
+BA¶»B>ÛiB< B9$ÆB6ItB3n"B0ÑB-·B*Ü-B( ÜB%%B"J9BnçB
+BžCBÜòB B&NBJýB
+o«BYB¹BÝ·B eAúN&AôAîàßAé*=AãsAÝŒöAØSAÒO¯AÌ
+AÆâiAÁ+ÅA»u"AµŸA°ÛAªQ9A€AãòA-OAv«AÀA	eA`¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ìžB}ÂèBzçBx
+EBu0óBrU¢BozPBlþBiÃ¬Bfè[Bd
+	Ba1žB^VfB[{BXÃBUÄqBRéBP
+ÎBM2|BJW*BG{ÙBD BAÅ6B>éäB<B93AB6WïB3|B0¡LB-ÅúB*ê©B(WB%4B"XŽB}bB
+¢BÆ¿BëmBB4ÊBYxB
+~&B¢ÕBÇBì1B àAúk
+AôŽyAîýÖAéG3AãAÝÙíAØ#IAÒlŠAÌ¶AÆÿ_AÁHŒA»AµÛuA°$ÒAªn/A€·A éAJFA¢AÜÿA&[AožAyr)An y¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}û3B}ÑdBzöBxÀBu?oBrd
+BoËBl­zBiÒ(BföÖBdBa@3B^dáB[BX®>BUÒìBR÷BP
+IBM@÷BJeŠBGTBD¯BAÓ±B>ø`B<
+B9AŒB6fkB3B0¯ÇB-ÔvB*ù$B(
+ÒB%BB"g/BÝB
+°BÕ:BùéB
+BCEBgóB
+¢B±PBÕþBú­B [AúAôÑpAïÍAéd)Aã­AÝöãAØ@?AÒAÌÒùAÇ
+VAÁe³A»¯AµølA°AÉAª%A€ÔA
+ßAg;A°AùöACRA¯Ay¬An>ÑAbÑAWÛ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~	®B}ßßB{Bx)<BuMêBrrBoGBl»õBià£BgRBd* BaN®B^s\B[
+BXŒ¹BUáhBSBP*ÄBMOsBJt!BGÏBDœ~BAâ,B?ÚB<+B9P8B6tæB3B0ŸCB-âñB+B(,NB%PüB"uªBYB
+¿BãµBdB-BQÁBvoB
+
+B¿ËBäzB	(B -ÖAú¥
+AôîgAï7ÃAé AãÊ}AÞÙAØ]6AÒŠAÌïïAÇ9MAÁ©A»ÌA¶cA°^¿Aªš
+A€ñyA:ÕA2AÍAëA`IA©ŠAyæAnxŸAc
+yAW3AL0íA@ß=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~*B}îZB{Bx7·Bu\eBrBo¥ÂBlÊpBiïBgÍBd8{Ba]*B^ØB[ŠBXË4BUïãBSBP9@BM]îBJBG§KBDËùBAð§B?VB<:B9^²B6aB3šB0ÌŸB-ñlB+B(:ÉB%_wB"&BšÔB
+ÍBò1BßB;B`<BêB
+©BÎGBòõB£B <RAúÂAõ
+]AïTºAéAãçsAÞ0ÐAØz-AÒÃAÍ
+æAÇVCAÁA»èýA¶2YA°{¶AªÅA¥oAWÌA¡)Aê
+A3âA}?AÆAzñAn²«AcEeAWØ ALjÛA@ýA5OA*>¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~&¥B}üÕB{!BxF2BujàBrBoŽ=BlØìBiýBg"HBdF÷Bak¥B^SB[µBXÙ°BUþ^BS#
+BPG»BMliBJBGµÆBDÚtBAÿ#B?#ÑB<HB9m.B6ÜB3¶B0Û9B-ÿèB+$B(IDB%móB"¡B·OB
+ÛþB ¬B%ZBJ	Bn·BeB
+žBÜÂBpB&B JÍAúÞ÷Aõ(TAïq±Aé»
+AäjAÞMÇAØ#AÒàAÍ)ÝAÇs9AÁŒAŒóA¶OOA°­Aªâ	A¥+fAtÃAŸA|APÙA5AãAzYÞAnìAcSAX
+AL€ÇAA7A5Ê=A*\÷A
+ï±A¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~5 B~
+QB{/ÿBxT­Buy\Br
+BoÂžBlçgBj
+Bg0ÄBdUrBaz B^ÏB[Ã}BXè+BV
+ÚBS1BPV6BMzäBJBGÄABDèðBB
+B?2LB<VûB9{©B6 WB3ÅB0éŽB.bB+3B(WÀB%|nB"¡
+BÅËB
+êyB'B3ÖBXB}2B¡áB
+ÆBë=BìB4B YHAúûíAõEJAï§AéØAä!aAÞjœAØŽAÒýwAÍFÓAÇ0AÁÙAŒ"éA¶lFA°µ£AªþÿA¥H]A¹AÛA$sAmÏA·,A AzËAo&
+Ac¹@AXKúALÞµAAqoA6)A*äA)AŒYAO@ùúÆ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~CB~ÌB{>zBxc)Bu×Br¬
+BoÑ4BlõâBjBg??BdcíBaB^­JB[ÑøBXö§BVUBS@BPd²BM`BJ®BGÒŒBD÷kBB
+B?@ÈB<evB9$B6®ÓB3ÓB0ø/B.
+ÞB+AB(f:B%éB"¯BÔFB
+øôB
+£BBQBfÿB®B°\B
+Õ
+Bù¹B
+gBCB gÄAûäAõbAAï«AéôúAä>WAÞŽAØÑAÓmAÍcÊAÇ­'AÁöAŒ?àA¶=A°ÒA«öA¥eSA®¯Aø
+AAiAÆAÔ#A
+AzÍžAo`rAcó-AX
+çAM¢AA«\A6>A*ÐÑAcAöFA@ú7v@ã\ë@Ì¹¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~RB~(IB{LøBxqŠBuTBr»Boß±Bm_Bj)BgMŒBdrjBaB^»ÇB[àvBY$BV)ÒBSNBPs/BMÝBJŒBGá:BEèBB*B?OEB<sóB9¢B6œPB3áþB1­B.+[B+P	B(tžB%fB"ŸBâÃB
+rB, BPÎBu}B+BŸÙB
+ãB	6B,äBQB vAAû5ßAõ;AïÈAêõAä[QAÞ€®AØî
+AÓ7hAÍÅAÇÊ!AÂ~AŒ\ÛA¶Š7A°ïA«8ñA¥MAËªAA^cA§ÁAñ
+A:zA{­AohAd-"AX¿ÜAMRAAåQA6x
+A+
+ÆAA0;AÂõ@ú«a@ãÐÕ@ÌöJ@¶¿@x^¿  ¿  ¿  ¿  ¿  ¿  B~`B~6ÅB{[sBx!Bu€ÐBrÉ~Boî,BmÛBj7Bg\7BdæBa¥B^ÊBB[îñBYBV8NBS\üBPªBMŠYBJËBGïµBEdBB9B?]ÀB<nB9§
+B6ËËB3ðzB1(B.9ÖB+^
+B(3B%§áB"ÌBñ>B
+ìB:B_JBøBšŠBÍUB
+òB	±B;`B`B ŒAûRÕAõ2AïåAê.ëAäxHAÞÁ¥AÙ
+AÓT^AÍ»AÇçAÂ0uAŒyÑA¶Ã.A±
+A«UçA¥DAè¡A1ýA{ZAÄ·AAWqA{AAoÔUAdgAXùÊAMAB>A6±ùA+D³A×nAj(Aüã@û:@äD¯@Íj$@¶@µ@Ú@dnD¿  ¿  ¿  ¿  B~o
+B~E?B{iîBxBu³KBr×ùBoüšBm!VBjFBgj³BdaBaŽB^ØŸB[ýlBY"BVFÉBSkwBP&BMŽÔBJÙBGþ1BE"ßBBGB?l<B<êB9µB6ÚFB3þõB1#£B.HRB+m B(®B%¶]B"Û
+Bÿ¹B
+$hBIBmÄBsB·"BÛÐB
+ ~B	%-BIÛBnB 8AûoÌAõ¹)Að
+AêKâAä?AÞÞAÙ'øAÓqUAÍº±AÈAÂMkAŒÈA¶à%A±)A«rÞA¥Œ;A ANôAQAá­A+
+AtgA{{ApBAd üAY3·AMÆqABY,A6ëæA+~ A [A€A	6Ð@û@äž@ÍÝþ@·s@ (è@N]@dç€@72@	ëÊ¿  ¿  B~}B~S»B{xiBxBuÁÆBræuBp
+#Bm/ÑBjTBgy.BdÜBaÂB^ç9B\
+çBY0BVUDBSyòBP¡BMÃOBJçþBH
+¬BE1ZBBV	B?z·B<eB9ÄB6èÂB4
+pB12
+B.VÍB+{{B( *B%ÄØB"éB 5B
+2ãBWB|@B îBÅBêKB
+úB	3šBXVB}B ¡³AûÂAõÖAð|AêhÙAä²5AÞûAÙDïAÓKAÍ×šAÈ!AÂjaAŒ³ŸA¶ýA±FxA«ÕA¥Ù1A "AkëAµGAþ€AHA]A{µtApH/AdÚéAYm€AN ^ABA7%ÓA+žA KHAÞA	pœ@üï@å,d@ÎQÙ@·wM@ Â@Â7@eÏX@8A@
+e)?¹`%?=¥@B~
+B~b7B{äBx«BuÐABrôïBpBm>MBjbûBg©Bd¬XBaÑB^õŽB\cBY?BVc¿BSnBP­
+BMÑÊBJöyBH'BE?ÖBBdB?2B<­áB9ÒB6÷=B4ìB1@B.eHB+öB(®¥B%ÓSB"øB 
+°B
+A^Bf
+B»B¯iBÔBøÆB
+
+tB	B#BfÒBB °.Aû©¹AõóAð<rAê
+ÏAäÏ,AßAÙaåAÓ«BAÍôAÈ=ûAÂXAŒÐµA·A±cnA«¬ËA¥ö(A ?
+AáAÒ>AAd÷A®TA{ïaAp
+Ae×AY§AN:KABÍA7_ÀA+ò{A 
+5AðA	ªª@üzÉ@å >@ÎÅ³@·ë(@¡@6@f·
+@9õ@
+LÞ?»/??Ÿ=
+f$¿  B{{BxºBuÞŒBskBp(BmLÇBjqvBg%BdºÓBaßB_0B\(ÞBYMBVr;BSéBP»BMàFBKôBH)¢BENQBBrÿB?®B<Œ\B9á
+B7¹B4*gB1OB.sÄB+rB(œ B%áÎB#}B ++B
+OÚBtB6BœåBâBAB
++ðB	PBuLBûB ŸªAûÆ¯Aö
+AðYiAê¢ÅAäì"Aß5AÙ~ÜAÓÈ9AÎAÈZòAÂ€OAŒí«A·7A±eA«ÉÁAŠ
+A \{A¥ØAï5A8AîAËKA|)OApŒ	AeNÃAYá~ANt9ACóA7­A,,hA ¿"AQÝA	ä@üî£@æ@Ï9@ž_@¡w@©ì@gÁ@9é©@
+4?Œþö?C)=ES?;ò¿
+¿  ¿  BuæSBsçBp6Bm[CBjñBg€BdÉNBaíýB_«B\7YBY\BV¶BS¥dBPÊBMîÁBKoBH8
+BE\ÌBBzB?Š)B<Ê×B9ïB74B48âB1]B.?B+ŠíB(ËB%ðJB#øB 9ŠB
+^UBB§²BÌ`BñBœB
+:kB	_BÈBšvB Í$AûãŠAö-Aðv_Aê¿ŒAå	AßRuAÙÒAÓå/AÎ.AÈwéAÂÁEAœ
+¢A·SÿA±[A«æžAŠ0A yqAÂÎA
++AUAåAèAA|c<ApõöAe±AZkAN®%AC@àA7ÓA,fUA ùAÊA
+
+@ýb}@æò@Ï­g@žÒÜ@¡øQ@
+Æ@hu@:Ñ^@
+
+G?ŸÎ_?FÈa=@Y<°ø¿  ¿  ¿  ¿  Bp>,BmiÀBjmBg³
+Bd×ÊBaüxB_!'B\EÖBYjBV2BS³áBPØBMý=BK!ìBHFBEkHBB÷B?Ž¥B<ÙSB9þB7"°B4G_B1l
+B.»B+µjB(ÚB%þÆB##uB H#B
+lÑBB¶.BÚÜBÿB$9B
+HçB	mBDB¶òB Û¡Aü AöIûAðXAêÜµAå&AßonAÙžËAÔ'AÎKAÈáAÂÞ>Aœ'A·p÷A±ºTA¬±AŠM
+A jAßÇA)#ArA»ÝA:A|-Aq/çAeÂ¢AZU\ANèACzÑA8
+A, FA!3AÅ»A
+Xu@ýÖ_@æûÔ@Ð!I@¹FŸ@¢l3@š@in9@;¹"@
+?Àç?Jgr=º=2¿  ¿  ¿  ¿  ¿  ¿  BjBgÁBdæEBb
+ôB_/¢B\TPBYxÿBV®BSÂ\BPç
+BN
+¹BK0gBHUBEyÄBBrB?Ã B<çÏB:
+}B71+B4UÚB1zB.7B+ÃåB(èB&
+BB#1ðB VB
+{MBûBÄ©BéWBB2ŽB
+WcB	|B ¿BÅnB ê
+Aü
+AöfòAð°OAêù«AåCAßeAÙÕÁAÔ
+AÎh{AÈ±×AÂû4AœDA·îA±×KA¬ §AŠjA ³aAüœAFAwAØÓA"0A|×AqiÔAeüAZIAO"ACŽŸA8GyA,Ú3A!líAÿšA
+c@þJ:@ço¯@Ð#@¹º@¢à
+@@jUî@< Ö@ë¿?ÂmQ?ND=¹F=L1¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BdíÜBboB_>
+B\bÌBYzBV¬(BSÐ×BPõBN4BK>âBHcBE?BB¬íB?ÑB<öJB:øB7?§B4dUB1B.­²B+Ò`B(÷B&œB#@kB eB
+ÈB®vBÓ%B÷ÓB
+BA/B
+eÞB	B¯;BÓéB øAü:AöèAðÍEAë¢Aå_ÿAß©[AÙòžAÔ<AÎ
+qAÈÎÎAÃ+AœaA·ªäA±ôAA¬=AŠûA ÐWAŽAcA¬mAõÊA?'A}Aq£ÂAf6|AZÉ6AO[ðACî«A8fA- A!ŠÛA9A
+ÌO@þŸ@çã@Ñý@º.r@£Sç@y\@k=¢@=@Ós?Ä<¹?Q¥=Ö
+Ê=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B_EŽB\qGBYõBVº€BSßRBQ BN(¯BKM^BHr
+BEºBB»iB?àB=ÅB:)tB7N"B4rÐB1B.Œ-B+àÛB)B&*8B#NçB sB
+CBŒòBá BNB*ýBO«B
+tYB	Bœ¶BâdBAüWAö ßAðê;Aë3Aå|õAßÆRAÚ¯AÔY
+AÎ¢hAÈëÅAÃ5!Aœ~~A·ÇÛA²7A¬ZAŠ£ñA íNA6«AAÉdAÁA\
+A}JôAqÝ®AfpiA[$AOÞAD(A8»RA-N
+A!àÈAsA
+=@ÿ1î@èWc@Ñ|Ø@º¢L@£ÇÁ@í6@l%V@>p?@»(?Æ
+!?UCç=ó|V=ü§¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BYBVÉBSíÍBQ|BN7*BK[ØBHBE¥6BBÉäB?îB=AB:7ïB7\B4LB1¥úB.ÊšB+ïWB)B&8³B#]bB B
+Š¿BËmBðBÊB9xB^&B
+ÕB	§BÌ1BðßBAütyAöœÕAñ2AëPAåëAßãHAÚ,¥AÔvAÎ¿_AÉ»AÃRAœuA·äÑA²..A¬wAŠÀçA¡
+DAS¡AþAæ[A/·AyA}áArAfªVA[=AOÏËADbA8õ@A-úA"ŽA­oA
+@*@ÿ¥È@èË=@Ñð²@»'@€;@a@m
+
+@?Wô@¢Ü?ÇÛ?Xâž>9r=Œó5¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BSõeBQ øBNEŠBKjUBHBE³±BBØ`B?ýB=!œB:FkB7kB4ÈB1ŽvB.Ù%B+ýÓB)"B&G0B#kÞB B
+µ;BÙéBþB#FBGôBl£B
+QB	µÿBÚ®Bÿ\B$
+AüqAöÚÎAñ$+AëmAå¶äAà AAÚIAÔúAÎÜWAÉ%ŽAÃoAœžmAžÊA²K'A¬AŠÝàA¡'=ApA¹öASAL°A
+A}ŸÓArQAfäGA[wAP	ŒADvA9/1A-ÁìA"TŠAç`A
+zA 
+Õ@é?@Òd@»	@€¯~@Ôó@môÐ@@?ž@¡?É«?\Ê>µž=ÙéÁ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BNM=BKxÐBH~BEÂ-BBæÛB@
+B=08B:TçB7yB4CB1ÂòB.ç B,
+NB)0ýB&U«B#zYB B
+Ã¶BèdB
+B1ÁBVpB{
+B
+ÌB	Ä{Bé)B
+×B2Aü®hAö÷ÅAñA!Aë~AåÓÛAà
+7AÚfAÔ¯ñAÎùMAÉBªAÃAœÕdAž
+ÁA²h
+A¬±zAŠú×A¡D3AAÖíA IAiŠA³A}øÀArzAg
+5A[°ïAPC©ADÖdA9i
+A-ûØA"A!NA
+ŽA FÂ@é²ù@ÒØn@»ýã@¥#X@HÍ@nÜ@A'm@rV?Ëz|?` >%0þ=öàN¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BH¥BEÐšBBõVB@B=>³B:caB7B4¬¿B1ÑmB.öB,ÊB)?xB&d&B#ÕB ­B
+Ò1BöàBB@<BdëBB
+®HB	ÒöB÷€B
+SBAAüË_A÷ŒAñ^Aë§uAåðÑAà:.AÚAÔÌçAÏDAÉ_¡AÃšýAœòZAž;·A²
+A¬ÎqA§ÍA¡a*AªAóãA=@AAÏùA~2¬ArÅgAgX!A[êÜAP}AEQA9£
+A.5ÆA"ÈA[:A
+íõA °@ê&Ô@ÓLH@Œqœ@¥2@Œ§@oÄ8@B!@Z
+?ÍIå?c¿m>3¬E>	ëm¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BBüíB@(B=M.B:qÝB7B4»9B1ßèB/B,)EB)MóB&r¢B#PB »þB
+à­B[B*	BNžBsfBB
+ŒÃB	áqB B*ÎBO|AüèUA÷1±Añ{AëÄlAæ
+ÈAàW%AÚ AÔéÞAÏ3;AÉ|AÃÅôAŸQAžX­A²¢
+A¬ëgA§4ÄA¡~!AÇ}AÚAZ7A£AìðA~lArÿTAgA\$ÉAP·AEJ>A9ÜùA.o³A#mA(A
+'âA º@ê®@ÓÀ"@Œå@Š
+
+@0@p«í@BöÖ@AŸ?ÏN?g^>>B'>fŽ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B=TÅB:XB7¥B4ÉµB1îcB/B,7ÀB)\oB&
+B#¥ËB ÊzB
+ï(BÖB8
+B]3BáBŠB
+Ë>B	ïìBB9IB]øAýKA÷NšAñAëáaAæ*¿Aàt
+AÚœxAÕÕAÏP1AÉAÃâëAŸ,GAžu€A²¿A­]A§QºA¡AätA-ÑAw-AÀA
+	çA~ŠAs9AAgËüA\^¶APñqAE+A:åA.© A#<[AÏA
+aÏA ô@ë@Ô3ý@œYr@Š~æ@€\@q¡@CÞ@)s?Ðè·?jý>P¢Ó>&áû¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B7¬B4Ø1B1üßB/!B,F<B)jêB&B#ŽHB ØöB
+ý€B"SBGBk¯B^Bµ
+B
+ÙºB	þiB#BGÅBltAý"DA÷k¡AñŽýAëþZAæG·AàAÚÚqAÕ#ÎAÏm*AÉ¶AÃÿãAŸI@AžA²ÛùA­%VA§n³A¡žAlAJÉA&AÝA
+&ßA~àxAss2AhíA\§AQ+bAEŸ
+A:P×A.ãA#vKA	A
+ÁA.{@ëk@Ô§ß@œÍT@ŠòÉ@>@r{e@DÆO@7?Òž@?n#>_>5]C¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B2vB/0	B,T·B)yfB&B#ÂÂB çqB
+
+ B0ÎBU|Bz+BÙBÃB
+è6B
+
+äB1BVABzïAý?;A÷AñÑôAìQAæd­Aà®
+AÚ÷gAÕ@ÃAÏ!AÉÓ~AÄ
+ÚAŸf7Až¯A²øðA­BMA§©A¡ÕA
+cAg¿A±
+AúyA
+CÖAeAs­ Ah?ÚA\ÒAQeOAEø	A:ÄA/
+~A#°9ABóA
+Õ­Ahh@ëöE@Õº@ŸA/@§f£@@sc@E®@øì?Ô©?r:õ>mb>CØ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B,\NB)áB&¬B#Ñ>B õìB
+B?IBcøBŠB­TBÒB
+ö±B
+_B@BdŒBjAý\1A÷¥AñîëAì8GAæ€AàËAÛ]AÕ]ºAÏ§AÉðsAÄ9ÑAŸ-AžÌA³çA­_CA§š A¡ñýA;YA¶AÎAoA
+`ÌATSAsç
+AhyÇA]
+AQ<AF1öA:Ä±A/WkA#ê&A|àA
+A¢U@ìj@Õ@Ÿµ@§Ú~@ÿò@tJÎ@F·@à ?ÖW?uÙÅ>|€>RSÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B&Ž&B#ß¹B!gB
+)BMÄBrrB!B»ÐBà~B
+,B
+)ÛBNBs7BæAýy(A÷Â
+Aò
+áAìU>AæAàç÷AÛ1TAÕz±AÏÄ
+AÊ
+jAÄVÇAŸ #AžéA³2ÝA­|:A§ÅA¢óAXPA¡­Aë	A4fA
+}ÃA?At úAh³ŽA]FnAQÙ)AFkäA:þA/XA$$A¶ÍA
+IAÜB@ìÝù@Ön@¿(ã@šNX@sÌ@u2@G}k@ÈT?Ø&z?yx>
+Hv>`Ï¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B!
+þB
+7B\?BîB¥BÊJBîùB
+šB
+8VB]B³BŠaAý
+A÷ß{Aò(ØAìr5Aæ»AáîAÛNKAÕ§AÏáAÊ*aAÄsœAŸœA¹wA³OÓA­1A§âA¢+êAuGAŸ£A AQ]A
+¹AÈ,AtZçAhí¡A]\ARAF¥ÐA;8A/ËFA$^ AðºA
+uA/@íQÓ@ÖwH@¿œ@šÂ2@ç§@v7@He @°	?Ùõã?}i>>oJ\¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bc×BjBŽBØÇBýuB
+"#B
+FÒBkB/BŽÝAý³A÷üsAòEÐAì-AæØAá!çAÛkCAÕŽ AÏýýAÊGYAÄ¶AŸÚA¹#oA³lÌA­¶)A§ÿ
+A¢HãA?AÛA$ùAnUA
+·²AAtØAi'A]ºMARMAFßÂA;r|A06A$ñA*¬A
+œfAP @íÅµ@Öë+@À@©6@[@wü@ILä@Í?ÛÅl?[=>Ä>>}Å€¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B»¯BçBB
+ðB
+0B
+UMByûBªBÃYAýÐAøjAòbÇAì¬#AæõAá>ÝAÛ:AÕÑAÐóAÊdPAÄ­­AŸ÷	A¹@fA³ÃA­ÓAš
+|A¢eÙA¯5AøAAïALA
+Ô©A
+AtÎÅAiaA]ô:ARôAG¯A;¬iA0?$A$ÑÞAdA
+÷SA@î9@×_@Àz@©©ï@Ïc@wé°@J4@
+?ÝÕ?*Š>â> v¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BB
+?B
+cÈBwB­%BÑÓAýíAø6aAòœAìÉAçwAá[ÓAÛ¥0AÕîAÐ7êAÊGAÄÊ£A¿ A¹]]A³Š¹A­ðAš9sA¢ÏAÌ,AA^åAšCA
+ñA:üAu²AimA^.'ARÀáAGSA;æVA0yA%
+ËAA1@AÃú@î­j@×Òß@ÀøT@ª
+É@C>@xÑe@K
+M@
+g6?ßd=?ú>¢?
+>^¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+k_BòB» BàOAþ	ûAøSWAòŽAìæAç/mAáxÊAÛÂ'AÖ
+AÐTàAÊ=AÄçA¿0÷A¹zSA³Ã°A®
+
+AšViA¢ÆAé#A2A{ÜAÅ9AAWòAuBAiÕYA^hARúÏAGA< CA0²þA%EžAØsAk-Aýè@ï!D@ØF¹@Ál.@ª£@·@y¹@L@
+Nê?á3Š?
+Éx>©}*>œ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BÃ7BîÊAþ&ñAøpNAò¹«AíAçLdAáÁAÛß
+AÖ(zAÐq×AÊ»3AÅA¿MíA¹JA³à§A®*Ašs`A¢ŒœAAOvAÓAâ/A+AtéAu|AjGA^¢AS4»AGÇvA<Z1A0ìëA%¥A`A¥A7Õ@ï@Øº@Áà@«}@*ò@z Í@Lë¶@6?ã?á>°ºÍ>Ùb¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aþ6AøFAòÖ£Aí  Açi]Aá²¹AÛüAÖEsAÐÏAÊØ,AÅ!A¿jåA¹ŽBA³ýA®FüAšYA¢ÙµA#AloAµËAÿ(AH
+AáAu¶}AjI8A^ÛòASn­AHgA<!A1&ÜA%¹ALQAß
+AqÆ@ð	@Ù.u@ÂSë@«y_@Ô@{@MÓ{@ 
+c?äÒ?hk>·øñ>£¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AòåÏAí<öAçSAáÏ°AÜ
+AÖbiAÐ«ÆAÊõ#AÅ>A¿ÜA¹Ñ9AŽA®còAš­OA¢ö¬A@	AeAÒÂA
+Ae{A®ØAuðjAj%A_ßASšAH;TA<ÎA1`ÉA%óA>AùA«³@ð|Û@Ù¢P@ÂÇÅ@«í9@¯@|pG@N»/@!?æ¢?7Ó>¿6>ªT©¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AçAáìŠAÜ6AÖ`AÐÈœAËAÅ[vA¿€ÓA¹î/AŽ7A®éAšÊEA£¢A\ÿAŠ\Aï¹A9ArAËÏAv*XAjœA_OÌASâAHuAA=üA1¶A&-qAÀ+ARåAå @ððµ@Ú*@Ã;@¬a@@}Wú@O¢ä@!íÌ?èqj?<>Æt6>±J¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÜE/AÖVAÐå³AË/AÅxmA¿ÁÉAº
+&AŽTA®ßAšç<A£0AyõAÃRA
+¯AV
+AiAèÅAvdEAjöÿA_ºAT
+tAH¯.A=AéA1Ô£A&g^AúAÓA@ñd@Ú@Ã¯y@¬Ôî@úb@~?¯@P@"Õ?ê@Ó?Ö€>Í±Ú>žÏï¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÐôßAËLAÅcA¿ÞÀAº(
+AŽqyA®ºÖA©3A£MAìAàIA)¥AsAŒ_AŒAv2Ak0íA_Ã§ATVaAHé
+A={ÖA2A&¡KA4AÆÀAYz@ñØi@ÚýÞ@Ä#S@­HÈ@n=@'d@QrM@#œ6?ì<?Š
+>Ôï~>À
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÅ€A¿ûžAºEAŽrA®×ÏA©!+A£jA³åAýAAFAûAÙWA"ŽAvØ#AkjÝA_ýATSAI#
+A=µÇA2HA&Û<AmöA ±Ak@òLK@ÛqÁ@Ä5@­Œª@â@@RZ@$€ú?íßÅ?u>Ü-¢>ÇK5¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AºTAAŽ«hA®ôÅA©>"A£AÐÛA8AcA¬ñAöNA?«AwAk€ËA`7
+ATÊ?AI\úA=ïµA2oA')A§äA:AÍX@òÀ&@Ûå@Å
+@®0
+@Uù@{n@SAÆ@%®?ï¯.?Dÿ>ãkE>ÎÚ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A¯ñA©[A£€uAíÒA7/AAÉèAEA\¡AwKýAkÞžA`qsAU-AIçA>)¡A2Œ\A'OAáÑAtAF@ó4 @ÜYu@Å~ê@®€_@ÉÓ@ïI@T)z@&tc?ñ~?i>êšé>ÕÆ}¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A£³¡A
+ÈAT%AAæßA0;AyAw
+êAl¥A`«_AU>AIÐÕA>cA2öIA'A
+ŸA®yAA3@ó§Û@ÜÍO@ÅòÄ@¯9@=®@c#@U.@'\?óN ?ãÒ>ñæ>Ý!¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AcQAºxAÕAM2AAw¿ØAlRA`åLAUxAJ
+ÁA>|A307A'ÂñA
+U«AèeA{ @ôŽ@ÝA*@Æf@¯@±@Öý@Uøã@(CÌ?õ
+i?³:>ù$1>äAÅ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AAj*A³AwùÈAlAa>AU±øAJD²A>×mA3j'A'üâA
+A"WAµ@ô@Ýµ
+@ÆÚ@¯ÿö@%k@Jß@Và§@)+?öìò?Ã? 1*>ëi¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÂ³Ax3¶AlÆpAaY*AUëåAJ~ A?ZA3€A(6ÏA
+ÉA\DAîþ@õq@Þ(æ@ÇN[@°sÏ@D@Ÿº@WÈ\@*E?øŒ[?R,?Ïü>òœ
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AläÉAaAV%ÒAJžA?KGA3ÞA(pŒA
+vA1A(ë@õwK@ÞÀ@ÇÂ5@°çª@
+@2@X°@*úù?úÃ?!?nÍ>ùú®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AVD+AJòzA?
+4A4îA(ª©A
+=dAÐ
+AbØ@õë%@ß@È6@±[@ù@Šn@YÄ@+â­?ü[,? ðý?
+
+? )¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A?£A4QàA(äA
+wTA
+AÊ@ö_@ß}@È©ñ@±Ïg@ôÛ@P@Z@,Êr?þ*µ?¢À?¬°?:û¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A)óA
+±BACüAÖ¶@öÒâ@ßøW@É
+Ì@²CA@hµ@*@[g=@-²&?ÿú
+?€ï?K?ÙÌ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AbUA€@÷FŒ@àl1@ÉŠ@²·@Ü@
+@\Nò@.Ú@ äÃ?Š_X?êU?
+x¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @÷n@àà
+@Ê@³*õ@Pj@
+uß@]6Š@/@Ìx?š.Á?'?q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @ÊB2@³Ð@ÄD@
+é¹@^
+[@0iC@Ž,?©þ*?
+'ø?¶B¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @ þ@]@_@1Q@ñ?«Í³? Ç
+?U¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @_@28œ@¥?­
+?$eÝ?óç¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @ý	?¯l
+?(®?
+ž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?)ê;?!1¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             B~
+B~záB~p€B~ffB~\)B~QìB~G®B~=qB~33B~(öB~
+žB~{B~
+=B~  B}õÃB}ë
+B}áHB}×
+B}ÌÍB}ÂB}žRB}®B}£×B}B}\B}
+B}záB}p€B}ffB}\)B}QìB}G®B}=qB}33B}(öB}
+žB}{B}
+=B}  B|õÃB|ë
+B|áHB|×
+B|ÌÍB|ÂB|žRB|®B|£×B|B|\B|
+B|záB|p€B|ffB|\)B|QìB|G®B|=qB|33B|(öB|
+žB|{B|
+=B|  Bz
+BzzáBzp€BzffBz\)BzQìBzG®Bz=qBz33Bz(öBz
+žBz{Bz
+=Bz  ByõÃByë
+ByáHBy×
+ByÌÍByÂByžRBy®By£×ByBy\By
+ByzáByp€ByffBy\)ByQìByG®By=qBy33By(öBy
+žBy{By
+=By  BxõÃBxë
+BxáHBx×
+BxÌÍBxÂBxžRBx®Bx£×BxBx\Bx
+BxzáBxp€BxffBx\)BxQìBxG®Bx=qBx33Bx(öBx
+žBx{Bx
+=Bx  Bv
+BvzáBvp€BvffBv\)BvQìBvG®Bv=qBv33Bv(öBv
+žBv{Bv
+=Bv  BuõÃBuë
+BuáHBu×
+BuÌÍBuÂBužRBu®Bu£×BuBu\Bu
+BuzáBup€BuffBu\)BuQìBuG®Bu=qBu33Bu(öBu
+žBu{Bu
+=Bu  BtõÃBtë
+BtáHBt×
+BtÌÍBtÂBtžRBt®Bt£×BtBt\Bt
+BtzáBtp€BtffBt\)BtQìBtG®Bt=qBt33Bt(öBt
+žBt{Bt
+=Bt  Br
+BrzáBrp€BrffBr\)BrQìBrG®Br=qBr33Br(öBr
+žBr{Br
+=Br  BqõÃBqë
+BqáHBq×
+BqÌÍBqÂBqžRBq®Bq£×BqBq\Bq
+BqzáBqp€BqffBq\)BqQìBqG®Bq=qBq33Bq(öBq
+žBq{Bq
+=Bq  BpõÃBpë
+BpáHBp×
+BpÌÍBpÂBpžRBp®Bp£×BpBp\Bp
+BpzáBpp€BpffBp\)BpQìBpG®Bp=qBp33Bp(öBp
+žBp{Bp
+=Bp  Bn
+BnzáBnp€BnffBn\)BnQìBnG®Bn=qBn33Bn(öBn
+žBn{Bn
+=Bn  BmõÃBmë
+BmáHBm×
+BmÌÍBmÂBmžRBm®Bm£×BmBm\Bm
+BmzáBmp€BmffBm\)BmQìBmG®Bm=qBm33Bm(öBm
+žBm{Bm
+=Bm  BlõÃBlë
+BláHBl×
+BlÌÍBlÂBlžRBl®Bl£×BlBl\Bl
+BlzáBlp€BlffBl\)BlQìBlG®Bl=qBl33Bl(öBl
+žBl{Bl
+=Bl  Bj
+BjzáBjp€BjffBj\)BjQìBjG®Bj=qBj33Bj(öBj
+žBj{Bj
+=Bj  BiõÃBië
+BiáHBi×
+BiÌÍBiÂBižRBi®Bi£×BiBi\Bi
+BizáBip€BiffBi\)BiQìBiG®Bi=qBi33Bi(öBi
+žBi{Bi
+=Bi  BhõÃBhë
+BháHBh×
+BhÌÍBhÂBhžRBh®Bh£×BhBh\Bh
+BhzáBhp€BhffBh\)BhQìBhG®Bh=qBh33Bh(öBh
+žBh{Bh
+=Bh  Bf
+BfzáBfp€BfffBf\)BfQìBfG®Bf=qBf33Bf(öBf
+žBf{Bf
+=Bf  BeõÃBeë
+BeáHBe×
+BeÌÍBeÂBežRBe®Be£×BeBe\Be
+BezáBep€BeffBe\)BeQìBeG®Be=qBe33Be(öBe
+žBe{Be
+=Be  BdõÃBdë
+BdáHBd×
+BdÌÍBdÂBdžRBd®Bd£×BdBd\Bd
+BdzáBdp€BdffBd\)BdQìBdG®Bd=qBd33Bd(öBd
+žBd{Bd
+=Bd  Bb
+BbzáBbp€BbffBb\)BbQìBbG®Bb=qBb33Bb(öBb
+žBb{Bb
+=Bb  BaõÃBaë
+BaáHBa×
+BaÌÍBaÂBažRBa®Ba£×BaBa\Ba
+BazáBap€BaffBa\)BaQìBaG®Ba=qBa33Ba(öBa
+žBa{Ba
+=Ba  B`õÃB`ë
+B`áHB`×
+B`ÌÍB`ÂB`žRB`®B`£×B`B`\B`
+B`záB`p€B`ffB`\)B`QìB`G®B`=qB`33B`(öB`
+žB`{B`
+=B`  B^
+B^záB^p€B^ffB^\)B^QìB^G®B^=qB^33B^(öB^
+žB^{B^
+=B^  B]õÃB]ë
+B]áHB]×
+B]ÌÍB]ÂB]žRB]®B]£×B]B]\B]
+B]záB]p€B]ffB]\)B]QìB]G®B]=qB]33B](öB]
+žB]{B]
+=B]  B\õÃB\ë
+B\áHB\×
+B\ÌÍB\ÂB\žRB\®B\£×B\B\\B\
+B\záB\p€B\ffB\\)B\QìB\G®B\=qB\33B\(öB\
+žB\{B\
+=B\  BZ
+BZzáBZp€BZffBZ\)BZQìBZG®BZ=qBZ33BZ(öBZ
+žBZ{BZ
+=BZ  BYõÃBYë
+BYáHBY×
+BYÌÍBYÂBYžRBY®BY£×BYBY\BY
+BYzáBYp€BYffBY\)BYQìBYG®BY=qBY33BY(öBY
+žBY{BY
+=BY  BXõÃBXë
+BXáHBX×
+BXÌÍBXÂBXžRBX®BX£×BXBX\BX
+BXzáBXp€BXffBX\)BXQìBXG®BX=qBX33BX(öBX
+žBX{BX
+=BX  BV
+BVzáBVp€BVffBV\)BVQìBVG®BV=qBV33BV(öBV
+žBV{BV
+=BV  BUõÃBUë
+BUáHBU×
+BUÌÍBUÂBUžRBU®BU£×BUBU\BU
+BUzáBUp€BUffBU\)BUQìBUG®BU=qBU33BU(öBU
+žBU{BU
+=BU  BTõÃBTë
+BTáHBT×
+BTÌÍBTÂBTžRBT®BT£×BTBT\BT
+BTzáBTp€BTffBT\)BTQìBTG®BT=qBT33BT(öBT
+žBT{BT
+=BT  BR
+BRzáBRp€BRffBR\)BRQìBRG®BR=qBR33BR(öBR
+žBR{BR
+=BR  BQõÃBQë
+BQáHBQ×
+BQÌÍBQÂBQžRBQ®BQ£×BQBQ\BQ
+BQzáBQp€BQffBQ\)BQQìBQG®BQ=qBQ33BQ(öBQ
+žBQ{BQ
+=BQ  BPõÃBPë
+BPáHBP×
+BPÌÍBPÂBPžRBP®BP£×BPBP\BP
+BPzáBPp€BPffBP\)BPQìBPG®BP=qBP33BP(öBP
+žBP{BP
+=BP  BN
+BNzáBNp€BNffBN\)BNQìBNG®BN=qBN33BN(öBN
+žBN{BN
+=BN  BMõÃBMë
+BMáHBM×
+BMÌÍBMÂBMžRBM®BM£×BMBM\BM
+BMzáBMp€BMffBM\)BMQìBMG®BM=qBM33BM(öBM
+žBM{BM
+=BM  BLõÃBLë
+BLáHBL×
+BLÌÍBLÂBLžRBL®BL£×BLBL\BL
+BLzáBLp€BLffBL\)BLQìBLG®BL=qBL33BL(öBL
+žBL{BL
+=BL  BJ
+BJzáBJp€BJffBJ\)BJQìBJG®BJ=qBJ33BJ(öBJ
+žBJ{BJ
+=BJ  BIõÃBIë
+BIáHBI×
+BIÌÍBIÂBIžRBI®BI£×BIBI\BI
+BIzáBIp€BIffBI\)BIQìBIG®BI=qBI33BI(öBI
+žBI{BI
+=BI  BHõÃBHë
+BHáHBH×
+BHÌÍBHÂBHžRBH®BH£×BHBH\BH
+BHzáBHp€BHffBH\)BHQìBHG®BH=qBH33BH(öBH
+žBH{BH
+=BH  BF
+BFzáBFp€BFffBF\)BFQìBFG®BF=qBF33BF(öBF
+žBF{BF
+=BF  BEõÃBEë
+BEáHBE×
+BEÌÍBEÂBEžRBE®BE£×BEBE\BE
+BEzáBEp€BEffBE\)BEQìBEG®BE=qBE33BE(öBE
+žBE{BE
+=BE  BDõÃBDë
+BDáHBD×
+BDÌÍBDÂBDžRBD®BD£×BDBD\BD
+BDzáBDp€BDffBD\)BDQìBDG®BD=qBD33BD(öBD
+žBD{BD
+=BD  BB
+BBzáBBp€BBffBB\)BBQìBBG®BB=qBB33BB(öBB
+žBB{BB
+=BB  BAõÃBAë
+BAáHBA×
+BAÌÍBAÂBAžRBA®BA£×BABA\BA
+BAzáBAp€BAffBA\)BAQìBAG®BA=qBA33BA(öBA
+žBA{BA
+=BA  B@õÃB@ë
+B@áHB@×
+B@ÌÍB@ÂB@žRB@®B@£×B@B@\B@
+B@záB@p€B@ffB@\)B@QìB@G®B@=qB@33B@(öB@
+žB@{B@
+=B@  B>
+B>záB>p€B>ffB>\)B>QìB>G®B>=qB>33B>(öB>
+žB>{B>
+=B>  B=õÃB=ë
+B=áHB=×
+B=ÌÍB=ÂB=žRB=®B=£×B=B=\B=
+B=záB=p€B=ffB=\)B=QìB=G®B==qB=33B=(öB=
+žB={B=
+=B=  B<õÃB<ë
+B<áHB<×
+B<ÌÍB<ÂB<žRB<®B<£×B<B<\B<
+B<záB<p€B<ffB<\)B<QìB<G®B<=qB<33B<(öB<
+žB<{B<
+=B<  B:
+B:záB:p€B:ffB:\)B:QìB:G®B:=qB:33B:(öB:
+žB:{B:
+=B:  B9õÃB9ë
+B9áHB9×
+B9ÌÍB9ÂB9žRB9®B9£×B9B9\B9
+B9záB9p€B9ffB9\)B9QìB9G®B9=qB933B9(öB9
+žB9{B9
+=B9  B8õÃB8ë
+B8áHB8×
+B8ÌÍB8ÂB8žRB8®B8£×B8B8\B8
+B8záB8p€B8ffB8\)B8QìB8G®B8=qB833B8(öB8
+žB8{B8
+=B8  B6
+B6záB6p€B6ffB6\)B6QìB6G®B6=qB633B6(öB6
+žB6{B6
+=B6  B5õÃB5ë
+B5áHB5×
+B5ÌÍB5ÂB5žRB5®B5£×B5B5\B5
+B5záB5p€B5ffB5\)B5QìB5G®B5=qB533B5(öB5
+žB5{B5
+=B5  B4õÃB4ë
+B4áHB4×
+B4ÌÍB4ÂB4žRB4®B4£×B4B4\B4
+B4záB4p€B4ffB4\)B4QìB4G®B4=qB433B4(öB4
+žB4{B4
+=B4  B2
+B2záB2p€B2ffB2\)B2QìB2G®B2=qB233B2(öB2
+žB2{B2
+=B2  B1õÃB1ë
+B1áHB1×
+B1ÌÍB1ÂB1žRB1®B1£×B1B1\B1
+B1záB1p€B1ffB1\)B1QìB1G®B1=qB133B1(öB1
+žB1{B1
+=B1  B0õÃB0ë
+B0áHB0×
+B0ÌÍB0ÂB0žRB0®B0£×B0B0\B0
+B0záB0p€B0ffB0\)B0QìB0G®B0=qB033B0(öB0
+žB0{B0
+=B0  B.
+B.záB.p€B.ffB.\)B.QìB.G®B.=qB.33B.(öB.
+žB.{B.
+=B.  B-õÃB-ë
+B-áHB-×
+B-ÌÍB-ÂB-žRB-®B-£×B-B-\B-
+B-záB-p€B-ffB-\)B-QìB-G®B-=qB-33B-(öB-
+žB-{B-
+=B-  B,õÃB,ë
+B,áHB,×
+B,ÌÍB,ÂB,žRB,®B,£×B,B,\B,
+B,záB,p€B,ffB,\)B,QìB,G®B,=qB,33B,(öB,
+žB,{B,
+=B,  B*
+B*záB*p€B*ffB*\)B*QìB*G®B*=qB*33B*(öB*
+žB*{B*
+=B*  B)õÃB)ë
+B)áHB)×
+B)ÌÍB)ÂB)žRB)®B)£×B)B)\B)
+B)záB)p€B)ffB)\)B)QìB)G®B)=qB)33B)(öB)
+žB){B)
+=B)  B(õÃB(ë
+B(áHB(×
+B(ÌÍB(ÂB(žRB(®B(£×B(B(\B(
+B(záB(p€B(ffB(\)B(QìB(G®B(=qB(33B((öB(
+žB({B(
+=B(  B&
+B&záB&p€B&ffB&\)B&QìB&G®B&=qB&33B&(öB&
+žB&{B&
+=B&  B%õÃB%ë
+B%áHB%×
+B%ÌÍB%ÂB%žRB%®B%£×B%B%\B%
+B%záB%p€B%ffB%\)B%QìB%G®B%=qB%33B%(öB%
+žB%{B%
+=B%  B$õÃB$ë
+B$áHB$×
+B$ÌÍB$ÂB$žRB$®B$£×B$B$\B$
+B$záB$p€B$ffB$\)B$QìB$G®B$=qB$33B$(öB$
+žB${B$
+=B$  B"
+B"záB"p€B"ffB"\)B"QìB"G®B"=qB"33B"(öB"
+žB"{B"
+=B"  B!õÃB!ë
+B!áHB!×
+B!ÌÍB!ÂB!žRB!®B!£×B!B!\B!
+B!záB!p€B!ffB!\)B!QìB!G®B!=qB!33B!(öB!
+žB!{B!
+=B!  B õÃB ë
+B áHB ×
+B ÌÍB ÂB žRB ®B £×B B \B 
+B záB p€B ffB \)B QìB G®B =qB 33B (öB 
+žB {B 
+=B   B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B	õÃB	ë
+B	áHB	×
+B	ÌÍB	ÂB	žRB	®B	£×B	B	\B	
+B	záB	p€B	ffB	\)B	QìB	G®B	=qB	33B	(öB	
+žB	{B	
+=B	  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B õÃB ë
+B áHB ×
+B ÌÍB ÂB žRB ®B £×B B \B 
+B záB p€B ffB \)B QìB G®B =qB 33B (öB 
+žB {B 
+=B   Aý
+=AüõÃAüáHAüÌÍAüžRAü£×Aü\AüzáAüffAüQìAü=qAü(öAü{Aü  Aûë
+Aû×
+AûÂAû®AûAû
+Aûp€Aû\)AûG®Aû33Aû
+žAû
+=AúõÃAúáHAúÌÍAúžRAú£×Aú\AúzáAúffAúQìAú=qAú(öAú{Aú  Aùë
+Aù×
+AùÂAù®AùAù
+Aùp€Aù\)AùG®Aù33Aù
+žAù
+=AøõÃAøáHAøÌÍAøžRAø£×Aø\AøzáAøffAøQìAø=qAø(öAø{Aø  Aõ
+=AôõÃAôáHAôÌÍAôžRAô£×Aô\AôzáAôffAôQìAô=qAô(öAô{Aô  Aóë
+Aó×
+AóÂAó®AóAó
+Aóp€Aó\)AóG®Aó33Aó
+žAó
+=AòõÃAòáHAòÌÍAòžRAò£×Aò\AòzáAòffAòQìAò=qAò(öAò{Aò  Añë
+Añ×
+AñÂAñ®AñAñ
+Añp€Añ\)AñG®Añ33Añ
+žAñ
+=AðõÃAðáHAðÌÍAðžRAð£×Að\AðzáAðffAðQìAð=qAð(öAð{Að  Aí
+=AìõÃAìáHAìÌÍAìžRAì£×Aì\AìzáAìffAìQìAì=qAì(öAì{Aì  Aëë
+Aë×
+AëÂAë®AëAë
+Aëp€Aë\)AëG®Aë33Aë
+žAë
+=AêõÃAêáHAêÌÍAêžRAê£×Aê\AêzáAêffAêQìAê=qAê(öAê{Aê  Aéë
+Aé×
+AéÂAé®AéAé
+Aép€Aé\)AéG®Aé33Aé
+žAé
+=AèõÃAèáHAèÌÍAèžRAè£×Aè\AèzáAèffAèQìAè=qAè(öAè{Aè  Aå
+=AäõÃAäáHAäÌÍAäžRAä£×Aä\AäzáAäffAäQìAä=qAä(öAä{Aä  Aãë
+Aã×
+AãÂAã®AãAã
+Aãp€Aã\)AãG®Aã33Aã
+žAã
+=AâõÃAâáHAâÌÍAâžRAâ£×Aâ\AâzáAâffAâQìAâ=qAâ(öAâ{Aâ  Aáë
+Aá×
+AáÂAá®AáAá
+Aáp€Aá\)AáG®Aá33Aá
+žAá
+=AàõÃAàáHAàÌÍAàžRAà£×Aà\AàzáAàffAàQìAà=qAà(öAà{Aà  AÝ
+=AÜõÃAÜáHAÜÌÍAÜžRAÜ£×AÜ\AÜzáAÜffAÜQìAÜ=qAÜ(öAÜ{AÜ  AÛë
+AÛ×
+AÛÂAÛ®AÛAÛ
+AÛp€AÛ\)AÛG®AÛ33AÛ
+žAÛ
+=AÚõÃAÚáHAÚÌÍAÚžRAÚ£×AÚ\AÚzáAÚffAÚQìAÚ=qAÚ(öAÚ{AÚ  AÙë
+AÙ×
+AÙÂAÙ®AÙAÙ
+AÙp€AÙ\)AÙG®AÙ33AÙ
+žAÙ
+=AØõÃAØáHAØÌÍAØžRAØ£×AØ\AØzáAØffAØQìAØ=qAØ(öAØ{AØ  AÕ
+=AÔõÃAÔáHAÔÌÍAÔžRAÔ£×AÔ\AÔzáAÔffAÔQìAÔ=qAÔ(öAÔ{AÔ  AÓë
+AÓ×
+AÓÂAÓ®AÓAÓ
+AÓp€AÓ\)AÓG®AÓ33AÓ
+žAÓ
+=AÒõÃAÒáHAÒÌÍAÒžRAÒ£×AÒ\AÒzáAÒffAÒQìAÒ=qAÒ(öAÒ{AÒ  AÑë
+AÑ×
+AÑÂAÑ®AÑAÑ
+AÑp€AÑ\)AÑG®AÑ33AÑ
+žAÑ
+=AÐõÃAÐáHAÐÌÍAÐžRAÐ£×AÐ\AÐzáAÐffAÐQìAÐ=qAÐ(öAÐ{AÐ  AÍ
+=AÌõÃAÌáHAÌÌÍAÌžRAÌ£×AÌ\AÌzáAÌffAÌQìAÌ=qAÌ(öAÌ{AÌ  AËë
+AË×
+AËÂAË®AËAË
+AËp€AË\)AËG®AË33AË
+žAË
+=AÊõÃAÊáHAÊÌÍAÊžRAÊ£×AÊ\AÊzáAÊffAÊQìAÊ=qAÊ(öAÊ{AÊ  AÉë
+AÉ×
+AÉÂAÉ®AÉAÉ
+AÉp€AÉ\)AÉG®AÉ33AÉ
+žAÉ
+=AÈõÃAÈáHAÈÌÍAÈžRAÈ£×AÈ\AÈzáAÈffAÈQìAÈ=qAÈ(öAÈ{AÈ  AÅ
+=AÄõÃAÄáHAÄÌÍAÄžRAÄ£×AÄ\AÄzáAÄffAÄQìAÄ=qAÄ(öAÄ{AÄ  AÃë
+AÃ×
+AÃÂAÃ®AÃAÃ
+AÃp€AÃ\)AÃG®AÃ33AÃ
+žAÃ
+=AÂõÃAÂáHAÂÌÍAÂžRAÂ£×AÂ\AÂzáAÂffAÂQìAÂ=qAÂ(öAÂ{AÂ  AÁë
+AÁ×
+AÁÂAÁ®AÁAÁ
+AÁp€AÁ\)AÁG®AÁ33AÁ
+žAÁ
+=AÀõÃAÀáHAÀÌÍAÀžRAÀ£×AÀ\AÀzáAÀffAÀQìAÀ=qAÀ(öAÀ{AÀ  Aœ
+=AŒõÃAŒáHAŒÌÍAŒžRAŒ£×AŒ\AŒzáAŒffAŒQìAŒ=qAŒ(öAŒ{AŒ  A»ë
+A»×
+A»ÂA»®A»A»
+A»p€A»\)A»G®A»33A»
+žA»
+=AºõÃAºáHAºÌÍAºžRAº£×Aº\AºzáAºffAºQìAº=qAº(öAº{Aº  A¹ë
+A¹×
+A¹ÂA¹®A¹A¹
+A¹p€A¹\)A¹G®A¹33A¹
+žA¹
+=AžõÃAžáHAžÌÍAžžRAž£×Až\AžzáAžffAžQìAž=qAž(öAž{Až  Aµ
+=AŽõÃAŽáHAŽÌÍAŽžRAŽ£×AŽ\AŽzáAŽffAŽQìAŽ=qAŽ(öAŽ{AŽ  A³ë
+A³×
+A³ÂA³®A³A³
+A³p€A³\)A³G®A³33A³
+žA³
+=A²õÃA²áHA²ÌÍA²žRA²£×A²\A²záA²ffA²QìA²=qA²(öA²{A²  A±ë
+A±×
+A±ÂA±®A±A±
+A±p€A±\)A±G®A±33A±
+žA±
+=A°õÃA°áHA°ÌÍA°žRA°£×A°\A°záA°ffA°QìA°=qA°(öA°{A°  A­
+=A¬õÃA¬áHA¬ÌÍA¬žRA¬£×A¬\A¬záA¬ffA¬QìA¬=qA¬(öA¬{A¬  A«ë
+A«×
+A«ÂA«®A«A«
+A«p€A«\)A«G®A«33A«
+žA«
+=AªõÃAªáHAªÌÍAªžRAª£×Aª\AªzáAªffAªQìAª=qAª(öAª{Aª  A©ë
+A©×
+A©ÂA©®A©A©
+A©p€A©\)A©G®A©33A©
+žA©
+=AšõÃAšáHAšÌÍAšžRAš£×Aš\AšzáAšffAšQìAš=qAš(öAš{Aš  A¥
+=A€õÃA€áHA€ÌÍA€žRA€£×A€\A€záA€ffA€QìA€=qA€(öA€{A€  A£ë
+A£×
+A£ÂA£®A£A£
+A£p€A£\)A£G®A£33A£
+žA£
+=A¢õÃA¢áHA¢ÌÍA¢žRA¢£×A¢\A¢záA¢ffA¢QìA¢=qA¢(öA¢{A¢  A¡ë
+A¡×
+A¡ÂA¡®A¡A¡
+A¡p€A¡\)A¡G®A¡33A¡
+žA¡
+=A õÃA áHA ÌÍA žRA £×A \A záA ffA QìA =qA (öA {A   A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Az{Ayë
+AyÂAyAyp€AyG®Ay
+žAxõÃAxÌÍAx£×AxzáAxQìAx(öAx  Aw×
+Aw®Aw
+Aw\)Aw33Aw
+=AváHAvžRAv\AvffAv=qAv{Auë
+AuÂAuAup€AuG®Au
+žAtõÃAtÌÍAt£×AtzáAtQìAt(öAt  As×
+As®As
+As\)As33As
+=AráHAržRAr\ArffAr=qAr{Aqë
+AqÂAqAqp€AqG®Aq
+žApõÃApÌÍAp£×ApzáApQìAp(öAp  Aj{Aië
+AiÂAiAip€AiG®Ai
+žAhõÃAhÌÍAh£×AhzáAhQìAh(öAh  Ag×
+Ag®Ag
+Ag\)Ag33Ag
+=AfáHAfžRAf\AfffAf=qAf{Aeë
+AeÂAeAep€AeG®Ae
+žAdõÃAdÌÍAd£×AdzáAdQìAd(öAd  Ac×
+Ac®Ac
+Ac\)Ac33Ac
+=AbáHAbžRAb\AbffAb=qAb{Aaë
+AaÂAaAap€AaG®Aa
+žA`õÃA`ÌÍA`£×A`záA`QìA`(öA`  AZ{AYë
+AYÂAYAYp€AYG®AY
+žAXõÃAXÌÍAX£×AXzáAXQìAX(öAX  AW×
+AW®AW
+AW\)AW33AW
+=AVáHAVžRAV\AVffAV=qAV{AUë
+AUÂAUAUp€AUG®AU
+žATõÃATÌÍAT£×ATzáATQìAT(öAT  AS×
+AS®AS
+AS\)AS33AS
+=ARáHARžRAR\ARffAR=qAR{AQë
+AQÂAQAQp€AQG®AQ
+žAPõÃAPÌÍAP£×APzáAPQìAP(öAP  AJ{AIë
+AIÂAIAIp€AIG®AI
+žAHõÃAHÌÍAH£×AHzáAHQìAH(öAH  AG×
+AG®AG
+AG\)AG33AG
+=AFáHAFžRAF\AFffAF=qAF{AEë
+AEÂAEAEp€AEG®AE
+žADõÃADÌÍAD£×ADzáADQìAD(öAD  AC×
+AC®AC
+AC\)AC33AC
+=ABáHABžRAB\ABffAB=qAB{AAë
+AAÂAAAAp€AAG®AA
+žA@õÃA@ÌÍA@£×A@záA@QìA@(öA@  A:{A9ë
+A9ÂA9A9p€A9G®A9
+žA8õÃA8ÌÍA8£×A8záA8QìA8(öA8  A7×
+A7®A7
+A7\)A733A7
+=A6áHA6žRA6\A6ffA6=qA6{A5ë
+A5ÂA5A5p€A5G®A5
+žA4õÃA4ÌÍA4£×A4záA4QìA4(öA4  A3×
+A3®A3
+A3\)A333A3
+=A2áHA2žRA2\A2ffA2=qA2{A1ë
+A1ÂA1A1p€A1G®A1
+žA0õÃA0ÌÍA0£×A0záA0QìA0(öA0  A*{A)ë
+A)ÂA)A)p€A)G®A)
+žA(õÃA(ÌÍA(£×A(záA(QìA((öA(  A'×
+A'®A'
+A'\)A'33A'
+=A&áHA&žRA&\A&ffA&=qA&{A%ë
+A%ÂA%A%p€A%G®A%
+žA$õÃA$ÌÍA$£×A$záA$QìA$(öA$  A#×
+A#®A#
+A#\)A#33A#
+=A"áHA"žRA"\A"ffA"=qA"{A!ë
+A!ÂA!A!p€A!G®A!
+žA õÃA ÌÍA £×A záA QìA (öA   A{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A
+{A	ë
+A	ÂA	A	p€A	G®A	
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žA õÃA ÌÍA £×A záA QìA (öA   @ô(ö@ó×
+@ó
+@ó33@òáH@ò\@ò=q@ñë
+@ñ@ñG®@ðõÂ@ð£×@ðQì@ð  @ï®@ï\)@ï
+=@îžR@îff@î{@íÂ@íp€@í
+ž@ìÌÍ@ìzá@ì(ö@ë×
+@ë
+@ë33@êáH@ê\@ê=q@éë
+@é@éG®@èõÃ@è£×@èQì@è  @ç®@ç\)@ç
+=@æžR@æff@æ{@åÂ@åp€@å
+ž@äÌÍ@äzá@ä(ö@ã×
+@ã
+@ã33@âáH@â\@â=q@áë
+@á@áG®@àõÃ@à£×@àQì@à  @Ô(ö@Ó×
+@Ó
+@Ó33@ÒáH@Ò\@Ò=q@Ñë
+@Ñ@ÑG®@ÐõÂ@Ð£×@ÐQì@Ð  @Ï®@Ï\)@Ï
+=@ÎžR@Îff@Î{@ÍÂ@Íp€@Í
+ž@ÌÌÍ@Ìzá@Ì(ö@Ë×
+@Ë
+@Ë33@ÊáH@Ê\@Ê=q@Éë
+@É@ÉG®@ÈõÃ@È£×@ÈQì@È  @Ç®@Ç\)@Ç
+=@ÆžR@Æff@Æ{@ÅÂ@Åp€@Å
+ž@ÄÌÍ@Äzá@Ä(ö@Ã×
+@Ã
+@Ã33@ÂáH@Â\@Â=q@Áë
+@Á@ÁG®@ÀõÃ@À£×@ÀQì@À  @Ž(ö@³×
+@³
+@³33@²áH@²\@²=q@±ë
+@±@±G®@°õÂ@°£×@°Qì@°  @¯®@¯\)@¯
+=@®žR@®ff@®{@­Â@­p€@­
+ž@¬ÌÍ@¬zá@¬(ö@«×
+@«
+@«33@ªáH@ª\@ª=q@©ë
+@©@©G®@šõÃ@š£×@šQì@š  @§®@§\)@§
+=@ŠžR@Šff@Š{@¥Â@¥p€@¥
+ž@€ÌÍ@€zá@€(ö@£×
+@£
+@£33@¢áH@¢\@¢=q@¡ë
+@¡@¡G®@ õÃ@ £×@ Qì@   @(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÂ@£×@Qì@  @®@\)@
+=@žR@ff@{@Â@p€@
+ž@ÌÍ@zá@(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÃ@£×@Qì@  @®@\)@
+=@žR@ff@{@
+Â@
+p€@
+
+ž@ÌÍ@zá@(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÃ@£×@Qì@  @hQì@g®@g
+>@fff@eÂ@e
+ž@dzá@c×
+@c33@b\@aë
+@aG®@`£×@`  @_\)@^žR@^{@]p€@\ÌÍ@\(ö@[
+@ZáH@Z=q@Y@XõÂ@XQì@W®@W
+>@Vff@UÂ@U
+ž@Tzá@S×
+@S33@R\@Që
+@QG®@P£×@P  @O\)@NžR@N{@Mp€@LÌÍ@L(ö@K
+@JáH@J=q@I@HõÃ@HQì@G®@G
+=@Fff@EÂ@E
+ž@Dzá@C×
+@C33@B\@Aë
+@AG®@@£×@@  @(Qì@'®@'
+>@&ff@%Â@%
+ž@$zá@#×
+@#33@"\@!ë
+@!G®@ £×@   @\)@
+žR@
+{@
+p€@
+ÌÍ@
+(ö@
+@áH@=q@@õÂ@Qì@®@
+>@ff@Â@
+ž@zá@×
+@33@\@ë
+@G®@£×@  @\)@žR@{@
+p€@
+ÌÍ@
+(ö@
+
+@
+áH@
+=q@	@õÃ@Qì@®@
+=@ff@Â@
+ž@zá@×
+@33@\@ë
+@G®@ £×@   ?Ð£×?Ï\)?Î{?ÌÌÍ?Ë
+
+?Ê=p?ÈõÂ?Ç®?Æff?Å
+ž?Ã×
+?Â\?ÁG®?À  ?ŸžR?œp€?Œ(ö?ºáH?¹?žQì?·
+>?µÂ?Žzá?³33?±ë
+?°£×?¯\)?®{?¬ÌÍ?«
+?ª=q?šõÂ?§®?Šff?¥
+ž?£×
+?¢\?¡G®?   ?žR?p€?(ö?áH??Qì?
+>?Â?zá?33?ë
+?£×?\)?{?ÌÍ?
+?=q?õÃ?®?ff?
+
+ž?×
+?\?G®?  ?!G®?
+žR?
+(ö??
+=?zá?ë
+?\)?
+ÌÍ?
+=q?®?
+ž?\?   >úáH>õÂ>ð£×>ë
+>æff>áG®>Ü(ö>×
+=>Ñë
+>ÌÌÍ>Ç®>Â\>œp€>žQì>³33>®{>šõÃ>£×
+>žR>>zá>\)>=q>
+
+ž>  >uÂ>k
+>aG®>W
+=>LÌÍ>B\>8Qì>.{>#×
+>>\)>
+ž=õÂ=áG®=ÌÌÍ=žQì=£×
+=\)=uÂ=LÌÍ=#×
+<õÂ<£×
+<#×
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/verified/fOut.fits
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/verified/fOut.fits	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/verified/fOut.fits	(revision 22158)
@@ -0,0 +1,8424 @@
+SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             B~
+B~záB~p€B~ffB~\)B~QìB~G®B~=qB~33B~(öB~
+žB~{B~
+=B~  B}õÃB}ë
+B}áHB}×
+B}ÌÍB}ÂB}žRB}®B}£×B}B}\B}
+B}záB}p€B}ffB}\)B}QìB}G®B}=qB}33B}(öB}
+žB}{B}
+=B}  B|õÃB|ë
+B|áHB|×
+B|ÌÍB|ÂB|žRB|®B|£×B|B|\B|
+B|záB|p€B|ffB|\)B|QìB|G®B|=qB|33B|(öB|
+žB|{B|
+=B|  Bz
+BzzáBzp€BzffBz\)BzQìBzG®Bz=qBz33Bz(öBz
+žBz{Bz
+=Bz  ByõÃByë
+ByáHBy×
+ByÌÍByÂByžRBy®By£×ByBy\By
+ByzáByp€ByffBy\)ByQìByG®By=qBy33By(öBy
+žBy{By
+=By  BxõÃBxë
+BxáHBx×
+BxÌÍBxÂBxžRBx®Bx£×BxBx\Bx
+BxzáBxp€BxffBx\)BxQìBxG®Bx=qBx33Bx(öBx
+žBx{Bx
+=Bx  Bv
+BvzáBvp€BvffBv\)BvQìBvG®Bv=qBv33Bv(öBv
+žBv{Bv
+=Bv  BuõÃBuë
+BuáHBu×
+BuÌÍBuÂBužRBu®Bu£×BuBu\Bu
+BuzáBup€BuffBu\)BuQìBuG®Bu=qBu33Bu(öBu
+žBu{Bu
+=Bu  BtõÃBtë
+BtáHBt×
+BtÌÍBtÂBtžRBt®Bt£×BtBt\Bt
+BtzáBtp€BtffBt\)BtQìBtG®Bt=qBt33Bt(öBt
+žBt{Bt
+=Bt  Br
+BrzáBrp€BrffBr\)BrQìBrG®Br=qBr33Br(öBr
+žBr{Br
+=Br  BqõÃBqë
+BqáHBq×
+BqÌÍBqÂBqžRBq®Bq£×BqBq\Bq
+BqzáBqp€BqffBq\)BqQìBqG®Bq=qBq33Bq(öBq
+žBq{Bq
+=Bq  BpõÃBpë
+BpáHBp×
+BpÌÍBpÂBpžRBp®Bp£×BpBp\Bp
+BpzáBpp€BpffBp\)BpQìBpG®Bp=qBp33Bp(öBp
+žBp{Bp
+=Bp  Bn
+BnzáBnp€BnffBn\)BnQìBnG®Bn=qBn33Bn(öBn
+žBn{Bn
+=Bn  BmõÃBmë
+BmáHBm×
+BmÌÍBmÂBmžRBm®Bm£×BmBm\Bm
+BmzáBmp€BmffBm\)BmQìBmG®Bm=qBm33Bm(öBm
+žBm{Bm
+=Bm  BlõÃBlë
+BláHBl×
+BlÌÍBlÂBlžRBl®Bl£×BlBl\Bl
+BlzáBlp€BlffBl\)BlQìBlG®Bl=qBl33Bl(öBl
+žBl{Bl
+=Bl  Bj
+BjzáBjp€BjffBj\)BjQìBjG®Bj=qBj33Bj(öBj
+žBj{Bj
+=Bj  BiõÃBië
+BiáHBi×
+BiÌÍBiÂBižRBi®Bi£×BiBi\Bi
+BizáBip€BiffBi\)BiQìBiG®Bi=qBi33Bi(öBi
+žBi{Bi
+=Bi  BhõÃBhë
+BháHBh×
+BhÌÍBhÂBhžRBh®Bh£×BhBh\Bh
+BhzáBhp€BhffBh\)BhQìBhG®Bh=qBh33Bh(öBh
+žBh{Bh
+=Bh  Bf
+BfzáBfp€BfffBf\)BfQìBfG®Bf=qBf33Bf(öBf
+žBf{Bf
+=Bf  BeõÃBeë
+BeáHBe×
+BeÌÍBeÂBežRBe®Be£×BeBe\Be
+BezáBep€BeffBe\)BeQìBeG®Be=qBe33Be(öBe
+žBe{Be
+=Be  BdõÃBdë
+BdáHBd×
+BdÌÍBdÂBdžRBd®Bd£×BdBd\Bd
+BdzáBdp€BdffBd\)BdQìBdG®Bd=qBd33Bd(öBd
+žBd{Bd
+=Bd  Bb
+BbzáBbp€BbffBb\)BbQìBbG®Bb=qBb33Bb(öBb
+žBb{Bb
+=Bb  BaõÃBaë
+BaáHBa×
+BaÌÍBaÂBažRBa®Ba£×BaBa\Ba
+BazáBap€BaffBa\)BaQìBaG®Ba=qBa33Ba(öBa
+žBa{Ba
+=Ba  B`õÃB`ë
+B`áHB`×
+B`ÌÍB`ÂB`žRB`®B`£×B`B`\B`
+B`záB`p€B`ffB`\)B`QìB`G®B`=qB`33B`(öB`
+žB`{B`
+=B`  B^
+B^záB^p€B^ffB^\)B^QìB^G®B^=qB^33B^(öB^
+žB^{B^
+=B^  B]õÃB]ë
+B]áHB]×
+B]ÌÍB]ÂB]žRB]®B]£×B]B]\B]
+B]záB]p€B]ffB]\)B]QìB]G®B]=qB]33B](öB]
+žB]{B]
+=B]  B\õÃB\ë
+B\áHB\×
+B\ÌÍB\ÂB\žRB\®B\£×B\B\\B\
+B\záB\p€B\ffB\\)B\QìB\G®B\=qB\33B\(öB\
+žB\{B\
+=B\  BZ
+BZzáBZp€BZffBZ\)BZQìBZG®BZ=qBZ33BZ(öBZ
+žBZ{BZ
+=BZ  BYõÃBYë
+BYáHBY×
+BYÌÍBYÂBYžRBY®BY£×BYBY\BY
+BYzáBYp€BYffBY\)BYQìBYG®BY=qBY33BY(öBY
+žBY{BY
+=BY  BXõÃBXë
+BXáHBX×
+BXÌÍBXÂBXžRBX®BX£×BXBX\BX
+BXzáBXp€BXffBX\)BXQìBXG®BX=qBX33BX(öBX
+žBX{BX
+=BX  BV
+BVzáBVp€BVffBV\)BVQìBVG®BV=qBV33BV(öBV
+žBV{BV
+=BV  BUõÃBUë
+BUáHBU×
+BUÌÍBUÂBUžRBU®BU£×BUBU\BU
+BUzáBUp€BUffBU\)BUQìBUG®BU=qBU33BU(öBU
+žBU{BU
+=BU  BTõÃBTë
+BTáHBT×
+BTÌÍBTÂBTžRBT®BT£×BTBT\BT
+BTzáBTp€BTffBT\)BTQìBTG®BT=qBT33BT(öBT
+žBT{BT
+=BT  BR
+BRzáBRp€BRffBR\)BRQìBRG®BR=qBR33BR(öBR
+žBR{BR
+=BR  BQõÃBQë
+BQáHBQ×
+BQÌÍBQÂBQžRBQ®BQ£×BQBQ\BQ
+BQzáBQp€BQffBQ\)BQQìBQG®BQ=qBQ33BQ(öBQ
+žBQ{BQ
+=BQ  BPõÃBPë
+BPáHBP×
+BPÌÍBPÂBPžRBP®BP£×BPBP\BP
+BPzáBPp€BPffBP\)BPQìBPG®BP=qBP33BP(öBP
+žBP{BP
+=BP  BN
+BNzáBNp€BNffBN\)BNQìBNG®BN=qBN33BN(öBN
+žBN{BN
+=BN  BMõÃBMë
+BMáHBM×
+BMÌÍBMÂBMžRBM®BM£×BMBM\BM
+BMzáBMp€BMffBM\)BMQìBMG®BM=qBM33BM(öBM
+žBM{BM
+=BM  BLõÃBLë
+BLáHBL×
+BLÌÍBLÂBLžRBL®BL£×BLBL\BL
+BLzáBLp€BLffBL\)BLQìBLG®BL=qBL33BL(öBL
+žBL{BL
+=BL  BJ
+BJzáBJp€BJffBJ\)BJQìBJG®BJ=qBJ33BJ(öBJ
+žBJ{BJ
+=BJ  BIõÃBIë
+BIáHBI×
+BIÌÍBIÂBIžRBI®BI£×BIBI\BI
+BIzáBIp€BIffBI\)BIQìBIG®BI=qBI33BI(öBI
+žBI{BI
+=BI  BHõÃBHë
+BHáHBH×
+BHÌÍBHÂBHžRBH®BH£×BHBH\BH
+BHzáBHp€BHffBH\)BHQìBHG®BH=qBH33BH(öBH
+žBH{BH
+=BH  BF
+BFzáBFp€BFffBF\)BFQìBFG®BF=qBF33BF(öBF
+žBF{BF
+=BF  BEõÃBEë
+BEáHBE×
+BEÌÍBEÂBEžRBE®BE£×BEBE\BE
+BEzáBEp€BEffBE\)BEQìBEG®BE=qBE33BE(öBE
+žBE{BE
+=BE  BDõÃBDë
+BDáHBD×
+BDÌÍBDÂBDžRBD®BD£×BDBD\BD
+BDzáBDp€BDffBD\)BDQìBDG®BD=qBD33BD(öBD
+žBD{BD
+=BD  BB
+BBzáBBp€BBffBB\)BBQìBBG®BB=qBB33BB(öBB
+žBB{BB
+=BB  BAõÃBAë
+BAáHBA×
+BAÌÍBAÂBAžRBA®BA£×BABA\BA
+BAzáBAp€BAffBA\)BAQìBAG®BA=qBA33BA(öBA
+žBA{BA
+=BA  B@õÃB@ë
+B@áHB@×
+B@ÌÍB@ÂB@žRB@®B@£×B@B@\B@
+B@záB@p€B@ffB@\)B@QìB@G®B@=qB@33B@(öB@
+žB@{B@
+=B@  B>
+B>záB>p€B>ffB>\)B>QìB>G®B>=qB>33B>(öB>
+žB>{B>
+=B>  B=õÃB=ë
+B=áHB=×
+B=ÌÍB=ÂB=žRB=®B=£×B=B=\B=
+B=záB=p€B=ffB=\)B=QìB=G®B==qB=33B=(öB=
+žB={B=
+=B=  B<õÃB<ë
+B<áHB<×
+B<ÌÍB<ÂB<žRB<®B<£×B<B<\B<
+B<záB<p€B<ffB<\)B<QìB<G®B<=qB<33B<(öB<
+žB<{B<
+=B<  B:
+B:záB:p€B:ffB:\)B:QìB:G®B:=qB:33B:(öB:
+žB:{B:
+=B:  B9õÃB9ë
+B9áHB9×
+B9ÌÍB9ÂB9žRB9®B9£×B9B9\B9
+B9záB9p€B9ffB9\)B9QìB9G®B9=qB933B9(öB9
+žB9{B9
+=B9  B8õÃB8ë
+B8áHB8×
+B8ÌÍB8ÂB8žRB8®B8£×B8B8\B8
+B8záB8p€B8ffB8\)B8QìB8G®B8=qB833B8(öB8
+žB8{B8
+=B8  B6
+B6záB6p€B6ffB6\)B6QìB6G®B6=qB633B6(öB6
+žB6{B6
+=B6  B5õÃB5ë
+B5áHB5×
+B5ÌÍB5ÂB5žRB5®B5£×B5B5\B5
+B5záB5p€B5ffB5\)B5QìB5G®B5=qB533B5(öB5
+žB5{B5
+=B5  B4õÃB4ë
+B4áHB4×
+B4ÌÍB4ÂB4žRB4®B4£×B4B4\B4
+B4záB4p€B4ffB4\)B4QìB4G®B4=qB433B4(öB4
+žB4{B4
+=B4  B2
+B2záB2p€B2ffB2\)B2QìB2G®B2=qB233B2(öB2
+žB2{B2
+=B2  B1õÃB1ë
+B1áHB1×
+B1ÌÍB1ÂB1žRB1®B1£×B1B1\B1
+B1záB1p€B1ffB1\)B1QìB1G®B1=qB133B1(öB1
+žB1{B1
+=B1  B0õÃB0ë
+B0áHB0×
+B0ÌÍB0ÂB0žRB0®B0£×B0B0\B0
+B0záB0p€B0ffB0\)B0QìB0G®B0=qB033B0(öB0
+žB0{B0
+=B0  B.
+B.záB.p€B.ffB.\)B.QìB.G®B.=qB.33B.(öB.
+žB.{B.
+=B.  B-õÃB-ë
+B-áHB-×
+B-ÌÍB-ÂB-žRB-®B-£×B-B-\B-
+B-záB-p€B-ffB-\)B-QìB-G®B-=qB-33B-(öB-
+žB-{B-
+=B-  B,õÃB,ë
+B,áHB,×
+B,ÌÍB,ÂB,žRB,®B,£×B,B,\B,
+B,záB,p€B,ffB,\)B,QìB,G®B,=qB,33B,(öB,
+žB,{B,
+=B,  B*
+B*záB*p€B*ffB*\)B*QìB*G®B*=qB*33B*(öB*
+žB*{B*
+=B*  B)õÃB)ë
+B)áHB)×
+B)ÌÍB)ÂB)žRB)®B)£×B)B)\B)
+B)záB)p€B)ffB)\)B)QìB)G®B)=qB)33B)(öB)
+žB){B)
+=B)  B(õÃB(ë
+B(áHB(×
+B(ÌÍB(ÂB(žRB(®B(£×B(B(\B(
+B(záB(p€B(ffB(\)B(QìB(G®B(=qB(33B((öB(
+žB({B(
+=B(  B&
+B&záB&p€B&ffB&\)B&QìB&G®B&=qB&33B&(öB&
+žB&{B&
+=B&  B%õÃB%ë
+B%áHB%×
+B%ÌÍB%ÂB%žRB%®B%£×B%B%\B%
+B%záB%p€B%ffB%\)B%QìB%G®B%=qB%33B%(öB%
+žB%{B%
+=B%  B$õÃB$ë
+B$áHB$×
+B$ÌÍB$ÂB$žRB$®B$£×B$B$\B$
+B$záB$p€B$ffB$\)B$QìB$G®B$=qB$33B$(öB$
+žB${B$
+=B$  B"
+B"záB"p€B"ffB"\)B"QìB"G®B"=qB"33B"(öB"
+žB"{B"
+=B"  B!õÃB!ë
+B!áHB!×
+B!ÌÍB!ÂB!žRB!®B!£×B!B!\B!
+B!záB!p€B!ffB!\)B!QìB!G®B!=qB!33B!(öB!
+žB!{B!
+=B!  B õÃB ë
+B áHB ×
+B ÌÍB ÂB žRB ®B £×B B \B 
+B záB p€B ffB \)B QìB G®B =qB 33B (öB 
+žB {B 
+=B   B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B	õÃB	ë
+B	áHB	×
+B	ÌÍB	ÂB	žRB	®B	£×B	B	\B	
+B	záB	p€B	ffB	\)B	QìB	G®B	=qB	33B	(öB	
+žB	{B	
+=B	  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B õÃB ë
+B áHB ×
+B ÌÍB ÂB žRB ®B £×B B \B 
+B záB p€B ffB \)B QìB G®B =qB 33B (öB 
+žB {B 
+=B   Aý
+=AüõÃAüáHAüÌÍAüžRAü£×Aü\AüzáAüffAüQìAü=qAü(öAü{Aü  Aûë
+Aû×
+AûÂAû®AûAû
+Aûp€Aû\)AûG®Aû33Aû
+žAû
+=AúõÃAúáHAúÌÍAúžRAú£×Aú\AúzáAúffAúQìAú=qAú(öAú{Aú  Aùë
+Aù×
+AùÂAù®AùAù
+Aùp€Aù\)AùG®Aù33Aù
+žAù
+=AøõÃAøáHAøÌÍAøžRAø£×Aø\AøzáAøffAøQìAø=qAø(öAø{Aø  Aõ
+=AôõÃAôáHAôÌÍAôžRAô£×Aô\AôzáAôffAôQìAô=qAô(öAô{Aô  Aóë
+Aó×
+AóÂAó®AóAó
+Aóp€Aó\)AóG®Aó33Aó
+žAó
+=AòõÃAòáHAòÌÍAòžRAò£×Aò\AòzáAòffAòQìAò=qAò(öAò{Aò  Añë
+Añ×
+AñÂAñ®AñAñ
+Añp€Añ\)AñG®Añ33Añ
+žAñ
+=AðõÃAðáHAðÌÍAðžRAð£×Að\AðzáAðffAðQìAð=qAð(öAð{Að  Aí
+=AìõÃAìáHAìÌÍAìžRAì£×Aì\AìzáAìffAìQìAì=qAì(öAì{Aì  Aëë
+Aë×
+AëÂAë®AëAë
+Aëp€Aë\)AëG®Aë33Aë
+žAë
+=AêõÃAêáHAêÌÍAêžRAê£×Aê\AêzáAêffAêQìAê=qAê(öAê{Aê  Aéë
+Aé×
+AéÂAé®AéAé
+Aép€Aé\)AéG®Aé33Aé
+žAé
+=AèõÃAèáHAèÌÍAèžRAè£×Aè\AèzáAèffAèQìAè=qAè(öAè{Aè  Aå
+=AäõÃAäáHAäÌÍAäžRAä£×Aä\AäzáAäffAäQìAä=qAä(öAä{Aä  Aãë
+Aã×
+AãÂAã®AãAã
+Aãp€Aã\)AãG®Aã33Aã
+žAã
+=AâõÃAâáHAâÌÍAâžRAâ£×Aâ\AâzáAâffAâQìAâ=qAâ(öAâ{Aâ  Aáë
+Aá×
+AáÂAá®AáAá
+Aáp€Aá\)AáG®Aá33Aá
+žAá
+=AàõÃAàáHAàÌÍAàžRAà£×Aà\AàzáAàffAàQìAà=qAà(öAà{Aà  AÝ
+=AÜõÃAÜáHAÜÌÍAÜžRAÜ£×AÜ\AÜzáAÜffAÜQìAÜ=qAÜ(öAÜ{AÜ  AÛë
+AÛ×
+AÛÂAÛ®AÛAÛ
+AÛp€AÛ\)AÛG®AÛ33AÛ
+žAÛ
+=AÚõÃAÚáHAÚÌÍAÚžRAÚ£×AÚ\AÚzáAÚffAÚQìAÚ=qAÚ(öAÚ{AÚ  AÙë
+AÙ×
+AÙÂAÙ®AÙAÙ
+AÙp€AÙ\)AÙG®AÙ33AÙ
+žAÙ
+=AØõÃAØáHAØÌÍAØžRAØ£×AØ\AØzáAØffAØQìAØ=qAØ(öAØ{AØ  AÕ
+=AÔõÃAÔáHAÔÌÍAÔžRAÔ£×AÔ\AÔzáAÔffAÔQìAÔ=qAÔ(öAÔ{AÔ  AÓë
+AÓ×
+AÓÂAÓ®AÓAÓ
+AÓp€AÓ\)AÓG®AÓ33AÓ
+žAÓ
+=AÒõÃAÒáHAÒÌÍAÒžRAÒ£×AÒ\AÒzáAÒffAÒQìAÒ=qAÒ(öAÒ{AÒ  AÑë
+AÑ×
+AÑÂAÑ®AÑAÑ
+AÑp€AÑ\)AÑG®AÑ33AÑ
+žAÑ
+=AÐõÃAÐáHAÐÌÍAÐžRAÐ£×AÐ\AÐzáAÐffAÐQìAÐ=qAÐ(öAÐ{AÐ  AÍ
+=AÌõÃAÌáHAÌÌÍAÌžRAÌ£×AÌ\AÌzáAÌffAÌQìAÌ=qAÌ(öAÌ{AÌ  AËë
+AË×
+AËÂAË®AËAË
+AËp€AË\)AËG®AË33AË
+žAË
+=AÊõÃAÊáHAÊÌÍAÊžRAÊ£×AÊ\AÊzáAÊffAÊQìAÊ=qAÊ(öAÊ{AÊ  AÉë
+AÉ×
+AÉÂAÉ®AÉAÉ
+AÉp€AÉ\)AÉG®AÉ33AÉ
+žAÉ
+=AÈõÃAÈáHAÈÌÍAÈžRAÈ£×AÈ\AÈzáAÈffAÈQìAÈ=qAÈ(öAÈ{AÈ  AÅ
+=AÄõÃAÄáHAÄÌÍAÄžRAÄ£×AÄ\AÄzáAÄffAÄQìAÄ=qAÄ(öAÄ{AÄ  AÃë
+AÃ×
+AÃÂAÃ®AÃAÃ
+AÃp€AÃ\)AÃG®AÃ33AÃ
+žAÃ
+=AÂõÃAÂáHAÂÌÍAÂžRAÂ£×AÂ\AÂzáAÂffAÂQìAÂ=qAÂ(öAÂ{AÂ  AÁë
+AÁ×
+AÁÂAÁ®AÁAÁ
+AÁp€AÁ\)AÁG®AÁ33AÁ
+žAÁ
+=AÀõÃAÀáHAÀÌÍAÀžRAÀ£×AÀ\AÀzáAÀffAÀQìAÀ=qAÀ(öAÀ{AÀ  Aœ
+=AŒõÃAŒáHAŒÌÍAŒžRAŒ£×AŒ\AŒzáAŒffAŒQìAŒ=qAŒ(öAŒ{AŒ  A»ë
+A»×
+A»ÂA»®A»A»
+A»p€A»\)A»G®A»33A»
+žA»
+=AºõÃAºáHAºÌÍAºžRAº£×Aº\AºzáAºffAºQìAº=qAº(öAº{Aº  A¹ë
+A¹×
+A¹ÂA¹®A¹A¹
+A¹p€A¹\)A¹G®A¹33A¹
+žA¹
+=AžõÃAžáHAžÌÍAžžRAž£×Až\AžzáAžffAžQìAž=qAž(öAž{Až  Aµ
+=AŽõÃAŽáHAŽÌÍAŽžRAŽ£×AŽ\AŽzáAŽffAŽQìAŽ=qAŽ(öAŽ{AŽ  A³ë
+A³×
+A³ÂA³®A³A³
+A³p€A³\)A³G®A³33A³
+žA³
+=A²õÃA²áHA²ÌÍA²žRA²£×A²\A²záA²ffA²QìA²=qA²(öA²{A²  A±ë
+A±×
+A±ÂA±®A±A±
+A±p€A±\)A±G®A±33A±
+žA±
+=A°õÃA°áHA°ÌÍA°žRA°£×A°\A°záA°ffA°QìA°=qA°(öA°{A°  A­
+=A¬õÃA¬áHA¬ÌÍA¬žRA¬£×A¬\A¬záA¬ffA¬QìA¬=qA¬(öA¬{A¬  A«ë
+A«×
+A«ÂA«®A«A«
+A«p€A«\)A«G®A«33A«
+žA«
+=AªõÃAªáHAªÌÍAªžRAª£×Aª\AªzáAªffAªQìAª=qAª(öAª{Aª  A©ë
+A©×
+A©ÂA©®A©A©
+A©p€A©\)A©G®A©33A©
+žA©
+=AšõÃAšáHAšÌÍAšžRAš£×Aš\AšzáAšffAšQìAš=qAš(öAš{Aš  A¥
+=A€õÃA€áHA€ÌÍA€žRA€£×A€\A€záA€ffA€QìA€=qA€(öA€{A€  A£ë
+A£×
+A£ÂA£®A£A£
+A£p€A£\)A£G®A£33A£
+žA£
+=A¢õÃA¢áHA¢ÌÍA¢žRA¢£×A¢\A¢záA¢ffA¢QìA¢=qA¢(öA¢{A¢  A¡ë
+A¡×
+A¡ÂA¡®A¡A¡
+A¡p€A¡\)A¡G®A¡33A¡
+žA¡
+=A õÃA áHA ÌÍA žRA £×A \A záA ffA QìA =qA (öA {A   A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Az{Ayë
+AyÂAyAyp€AyG®Ay
+žAxõÃAxÌÍAx£×AxzáAxQìAx(öAx  Aw×
+Aw®Aw
+Aw\)Aw33Aw
+=AváHAvžRAv\AvffAv=qAv{Auë
+AuÂAuAup€AuG®Au
+žAtõÃAtÌÍAt£×AtzáAtQìAt(öAt  As×
+As®As
+As\)As33As
+=AráHAržRAr\ArffAr=qAr{Aqë
+AqÂAqAqp€AqG®Aq
+žApõÃApÌÍAp£×ApzáApQìAp(öAp  Aj{Aië
+AiÂAiAip€AiG®Ai
+žAhõÃAhÌÍAh£×AhzáAhQìAh(öAh  Ag×
+Ag®Ag
+Ag\)Ag33Ag
+=AfáHAfžRAf\AfffAf=qAf{Aeë
+AeÂAeAep€AeG®Ae
+žAdõÃAdÌÍAd£×AdzáAdQìAd(öAd  Ac×
+Ac®Ac
+Ac\)Ac33Ac
+=AbáHAbžRAb\AbffAb=qAb{Aaë
+AaÂAaAap€AaG®Aa
+žA`õÃA`ÌÍA`£×A`záA`QìA`(öA`  AZ{AYë
+AYÂAYAYp€AYG®AY
+žAXõÃAXÌÍAX£×AXzáAXQìAX(öAX  AW×
+AW®AW
+AW\)AW33AW
+=AVáHAVžRAV\AVffAV=qAV{AUë
+AUÂAUAUp€AUG®AU
+žATõÃATÌÍAT£×ATzáATQìAT(öAT  AS×
+AS®AS
+AS\)AS33AS
+=ARáHARžRAR\ARffAR=qAR{AQë
+AQÂAQAQp€AQG®AQ
+žAPõÃAPÌÍAP£×APzáAPQìAP(öAP  AJ{AIë
+AIÂAIAIp€AIG®AI
+žAHõÃAHÌÍAH£×AHzáAHQìAH(öAH  AG×
+AG®AG
+AG\)AG33AG
+=AFáHAFžRAF\AFffAF=qAF{AEë
+AEÂAEAEp€AEG®AE
+žADõÃADÌÍAD£×ADzáADQìAD(öAD  AC×
+AC®AC
+AC\)AC33AC
+=ABáHABžRAB\ABffAB=qAB{AAë
+AAÂAAAAp€AAG®AA
+žA@õÃA@ÌÍA@£×A@záA@QìA@(öA@  A:{A9ë
+A9ÂA9A9p€A9G®A9
+žA8õÃA8ÌÍA8£×A8záA8QìA8(öA8  A7×
+A7®A7
+A7\)A733A7
+=A6áHA6žRA6\A6ffA6=qA6{A5ë
+A5ÂA5A5p€A5G®A5
+žA4õÃA4ÌÍA4£×A4záA4QìA4(öA4  A3×
+A3®A3
+A3\)A333A3
+=A2áHA2žRA2\A2ffA2=qA2{A1ë
+A1ÂA1A1p€A1G®A1
+žA0õÃA0ÌÍA0£×A0záA0QìA0(öA0  A*{A)ë
+A)ÂA)A)p€A)G®A)
+žA(õÃA(ÌÍA(£×A(záA(QìA((öA(  A'×
+A'®A'
+A'\)A'33A'
+=A&áHA&žRA&\A&ffA&=qA&{A%ë
+A%ÂA%A%p€A%G®A%
+žA$õÃA$ÌÍA$£×A$záA$QìA$(öA$  A#×
+A#®A#
+A#\)A#33A#
+=A"áHA"žRA"\A"ffA"=qA"{A!ë
+A!ÂA!A!p€A!G®A!
+žA õÃA ÌÍA £×A záA QìA (öA   A{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A
+{A	ë
+A	ÂA	A	p€A	G®A	
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žA õÃA ÌÍA £×A záA QìA (öA   @ô(ö@ó×
+@ó
+@ó33@òáH@ò\@ò=q@ñë
+@ñ@ñG®@ðõÂ@ð£×@ðQì@ð  @ï®@ï\)@ï
+=@îžR@îff@î{@íÂ@íp€@í
+ž@ìÌÍ@ìzá@ì(ö@ë×
+@ë
+@ë33@êáH@ê\@ê=q@éë
+@é@éG®@èõÃ@è£×@èQì@è  @ç®@ç\)@ç
+=@æžR@æff@æ{@åÂ@åp€@å
+ž@äÌÍ@äzá@ä(ö@ã×
+@ã
+@ã33@âáH@â\@â=q@áë
+@á@áG®@àõÃ@à£×@àQì@à  @Ô(ö@Ó×
+@Ó
+@Ó33@ÒáH@Ò\@Ò=q@Ñë
+@Ñ@ÑG®@ÐõÂ@Ð£×@ÐQì@Ð  @Ï®@Ï\)@Ï
+=@ÎžR@Îff@Î{@ÍÂ@Íp€@Í
+ž@ÌÌÍ@Ìzá@Ì(ö@Ë×
+@Ë
+@Ë33@ÊáH@Ê\@Ê=q@Éë
+@É@ÉG®@ÈõÃ@È£×@ÈQì@È  @Ç®@Ç\)@Ç
+=@ÆžR@Æff@Æ{@ÅÂ@Åp€@Å
+ž@ÄÌÍ@Äzá@Ä(ö@Ã×
+@Ã
+@Ã33@ÂáH@Â\@Â=q@Áë
+@Á@ÁG®@ÀõÃ@À£×@ÀQì@À  @Ž(ö@³×
+@³
+@³33@²áH@²\@²=q@±ë
+@±@±G®@°õÂ@°£×@°Qì@°  @¯®@¯\)@¯
+=@®žR@®ff@®{@­Â@­p€@­
+ž@¬ÌÍ@¬zá@¬(ö@«×
+@«
+@«33@ªáH@ª\@ª=q@©ë
+@©@©G®@šõÃ@š£×@šQì@š  @§®@§\)@§
+=@ŠžR@Šff@Š{@¥Â@¥p€@¥
+ž@€ÌÍ@€zá@€(ö@£×
+@£
+@£33@¢áH@¢\@¢=q@¡ë
+@¡@¡G®@ õÃ@ £×@ Qì@   @(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÂ@£×@Qì@  @®@\)@
+=@žR@ff@{@Â@p€@
+ž@ÌÍ@zá@(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÃ@£×@Qì@  @®@\)@
+=@žR@ff@{@
+Â@
+p€@
+
+ž@ÌÍ@zá@(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÃ@£×@Qì@  @hQì@g®@g
+>@fff@eÂ@e
+ž@dzá@c×
+@c33@b\@aë
+@aG®@`£×@`  @_\)@^žR@^{@]p€@\ÌÍ@\(ö@[
+@ZáH@Z=q@Y@XõÂ@XQì@W®@W
+>@Vff@UÂ@U
+ž@Tzá@S×
+@S33@R\@Që
+@QG®@P£×@P  @O\)@NžR@N{@Mp€@LÌÍ@L(ö@K
+@JáH@J=q@I@HõÃ@HQì@G®@G
+=@Fff@EÂ@E
+ž@Dzá@C×
+@C33@B\@Aë
+@AG®@@£×@@  @(Qì@'®@'
+>@&ff@%Â@%
+ž@$zá@#×
+@#33@"\@!ë
+@!G®@ £×@   @\)@
+žR@
+{@
+p€@
+ÌÍ@
+(ö@
+@áH@=q@@õÂ@Qì@®@
+>@ff@Â@
+ž@zá@×
+@33@\@ë
+@G®@£×@  @\)@žR@{@
+p€@
+ÌÍ@
+(ö@
+
+@
+áH@
+=q@	@õÃ@Qì@®@
+=@ff@Â@
+ž@zá@×
+@33@\@ë
+@G®@ £×@   ?Ð£×?Ï\)?Î{?ÌÌÍ?Ë
+
+?Ê=p?ÈõÂ?Ç®?Æff?Å
+ž?Ã×
+?Â\?ÁG®?À  ?ŸžR?œp€?Œ(ö?ºáH?¹?žQì?·
+>?µÂ?Žzá?³33?±ë
+?°£×?¯\)?®{?¬ÌÍ?«
+?ª=q?šõÂ?§®?Šff?¥
+ž?£×
+?¢\?¡G®?   ?žR?p€?(ö?áH??Qì?
+>?Â?zá?33?ë
+?£×?\)?{?ÌÍ?
+?=q?õÃ?®?ff?
+
+ž?×
+?\?G®?  ?!G®?
+žR?
+(ö??
+=?zá?ë
+?\)?
+ÌÍ?
+=q?®?
+ž?\?   >úáH>õÂ>ð£×>ë
+>æff>áG®>Ü(ö>×
+=>Ñë
+>ÌÌÍ>Ç®>Â\>œp€>žQì>³33>®{>šõÃ>£×
+>žR>>zá>\)>=q>
+
+ž>  >uÂ>k
+>aG®>W
+=>LÌÍ>B\>8Qì>.{>#×
+>>\)>
+ž=õÂ=áG®=ÌÌÍ=žQì=£×
+=\)=uÂ=LÌÍ=#×
+<õÂ<£×
+<#×
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bz
+B~zá¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bv
+BzzáBzzáB~p€¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bn
+BrzáBvzáBzp€BzffB~\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bj
+BnzáBnzáBrp€BvffBz\)Bz\)B~Qì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bf
+BfzáBjzáBnp€BnffBr\)Bv\)BzQìBzG®B~G®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B^
+BbzáBfzáBfp€BjffBn\)Bn\)BrQìBvG®BzG®Bz=qB~33¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BZ
+BZzáB^záBbp€BfffBf\)Bj\)BnQìBnG®BrG®Bv=qBz33Bz(öB~(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BR
+BVzáBZzáBZp€B^ffBb\)Bf\)BfQìBjG®BnG®Bn=qBr33Bv(öBz(öBz
+žB~{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BN
+BRzáBRzáBVp€BZffBZ\)B^\)BbQìBfG®BfG®Bj=qBn33Bn(öBr(öBv
+žBz{Bz{B~
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BJ
+BJzáBNzáBRp€BRffBV\)BZ\)BZQìB^G®BbG®Bf=qBf33Bj(öBn(öBn
+žBr{Bv{Bz
+=Bz  B~  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BB
+BFzáBJzáBJp€BNffBR\)BR\)BVQìBZG®BZG®B^=qBb33Bf(öBf(öBj
+žBn{Bn{Br
+=Bv  Bz  ByõÃB}ë
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B>
+B>záBBzáBFp€BJffBJ\)BN\)BRQìBRG®BVG®BZ=qBZ33B^(öBb(öBf
+žBf{Bj{Bn
+=Bn  Br  BuõÃByë
+ByáHB}áH¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B6
+B:záB>záB>p€BBffBF\)BJ\)BJQìBNG®BRG®BR=qBV33BZ(öBZ(öB^
+žBb{Bf{Bf
+=Bj  Bn  BmõÃBqë
+BuáHByáHBy×
+B}ÌÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B2
+B6záB6záB:p€B>ffB>\)BB\)BFQìBJG®BJG®BN=qBR33BR(öBV(öBZ
+žBZ{B^{Bb
+=Bf  Bf  BiõÃBmë
+BmáHBqáHBu×
+ByÌÍByÌÍB}Â¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B*
+B.záB2záB6p€B6ffB:\)B>\)B>QìBBG®BFG®BJ=qBJ33BN(öBR(öBR
+žBV{BZ{BZ
+=B^  Bb  BeõÃBeë
+BiáHBmáHBm×
+BqÌÍBuÌÍByÂByžRB}®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B&
+B*záB*záB.p€B2ffB6\)B6\)B:QìB>G®B>G®BB=qBF33BJ(öBJ(öBN
+žBR{BR{BV
+=BZ  BZ  B]õÃBaë
+BeáHBeáHBi×
+BmÌÍBmÌÍBqÂBužRBy®By®B}£×¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B"
+B"záB&záB*p€B*ffB.\)B2\)B6QìB6G®B:G®B>=qB>33BB(öBF(öBJ
+žBJ{BN{BR
+=BR  BV  BYõÃBYë
+B]áHBaáHBe×
+BeÌÍBiÌÍBmÂBmžRBq®Bu®By£×ByB}¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+B
+záB"záB"p€B&ffB*\)B*\)B.QìB2G®B6G®B6=qB:33B>(öB>(öBB
+žBF{BJ{BJ
+=BN  BR  BQõÃBUë
+BYáHBYáHB]×
+BaÌÍBeÌÍBeÂBižRBm®Bm®Bq£×BuByBy\B}
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+BzáBzáB
+p€B"ffB"\)B&\)B*QìB*G®B.G®B2=qB633B6(öB:(öB>
+žB>{BB{BF
+=BJ  BJ  BMõÃBQë
+BQáHBUáHBY×
+BYÌÍB]ÌÍBaÂBežRBe®Bi®Bm£×BmBqBu\By
+By
+B}zá¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+BzáBzáBp€BffB
+\)B"\)B"QìB&G®B*G®B*=qB.33B2(öB6(öB6
+žB:{B>{B>
+=BB  BF  BIõÃBIë
+BMáHBQáHBQ×
+BUÌÍBYÌÍBYÂB]žRBa®Be®Be£×BiBmBm\Bq
+Bu
+ByzáByp€B}ff¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+
+BzáBzáBp€BffB\)B\)B
+QìB"G®B"G®B&=qB*33B*(öB.(öB2
+žB6{B6{B:
+=B>  B>  BAõÃBEë
+BIáHBIáHBM×
+BQÌÍBQÌÍBUÂBYžRBY®B]®Ba£×BeBeBi\Bm
+Bm
+BqzáBup€ByffByffB}\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+BzáB
+záBp€BffB\)B\)BQìBG®B
+G®B"=qB"33B&(öB*(öB*
+žB.{B2{B6
+=B6  B:  B=õÃB=ë
+BAáHBEáHBI×
+BIÌÍBMÌÍBQÂBQžRBU®BY®BY£×B]BaBe\Be
+Bi
+BmzáBmp€BqffBuffBy\)ByQìB}Qì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aý
+=BzáBzáBp€B
+ffB\)B\)BQìBG®BG®B=qB
+33B"(öB"(öB&
+žB*{B*{B.
+=B2  B6  B5õÃB9ë
+B=áHB=áHBA×
+BEÌÍBIÌÍBIÂBMžRBQ®BQ®BU£×BYBYB]\Ba
+Be
+BezáBip€BmffBmffBq\)BuQìByQìByG®B}=q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aõ
+=AôõÃAüõÃBp€BffB\)B
+\)BQìBG®BG®B=qB33B(öB
+(öB"
+žB"{B&{B*
+=B*  B.  B1õÃB5ë
+B5áHB9áHB=×
+B=ÌÍBAÌÍBEÂBIžRBI®BM®BQ£×BQBUBY\BY
+B]
+BazáBep€BeffBiffBm\)BmQìBqQìBuG®By=qBy33B}33¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aå
+=AìõÃAôõÃAôáHAüÌÍB\)B\)BQìB
+G®BG®B=qB33B(öB(öB
+žB
+{B"{B"
+=B&  B*  B)õÃB-ë
+B1áHB5áHB5×
+B9ÌÍB=ÌÍB=ÂBAžRBE®BI®BI£×BMBQBQ\BU
+BY
+BYzáB]p€BaffBeffBe\)BiQìBmQìBmG®Bq=qBu33By33By(öB}
+ž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÝ
+=AäõÃAäõÃAìáHAôÌÍAôžRAüžRBQìBG®BG®B
+=qB33B(öB(öB
+žB{B{B
+
+=B"  B"  B%õÃB)ë
+B)áHB-áHB1×
+B5ÌÍB5ÌÍB9ÂB=žRB=®BA®BE£×BIBIBM\BQ
+BQ
+BUzáBYp€BYffB]ffBa\)BeQìBeQìBiG®Bm=qBm33Bq33Bu(öBy
+žBy
+žB}{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÍ
+=AÔõÃAÜõÃAäáHAäÌÍAìžRAôžRAô£×Aü\BG®B=qB33B
+(öB(öB
+žB{B{B
+=B  B
+  B!õÃB!ë
+B%áHB)áHB)×
+B-ÌÍB1ÌÍB5ÂB5žRB9®B=®B=£×BABEBI\BI
+BM
+BQzáBQp€BUffBYffBY\)B]QìBaQìBeG®Be=qBi33Bm33Bm(öBq
+žBu
+žBy{By
+=B}  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÅ
+=AÌõÃAÌõÃAÔáHAÜÌÍAäžRAäžRAì£×Aô\Aô\AüzáB33B(öB(öB
+
+žB{B{B
+=B  B  BõÃB
+ë
+B!áHB!áHB%×
+B)ÌÍB)ÌÍB-ÂB1žRB5®B5®B9£×B=B=BA\BE
+BI
+BIzáBMp€BQffBQffBU\)BYQìBYQìB]G®Ba=qBe33Be33Bi(öBm
+žBm
+žBq{Bu
+=By  By  B|õÃ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aœ
+=AŒõÃAÄõÃAÌáHAÌÌÍAÔžRAÜžRAä£×Aä\Aì\AôzáAôffAüQìB(öB
+žB{B
+{B
+=B  B  BõÃBë
+BáHB
+áHB!×
+B!ÌÍB%ÌÍB)ÂB)žRB-®B1®B5£×B5B9B=\B=
+BA
+BEzáBIp€BIffBMffBQ\)BQQìBUQìBYG®BY=qB]33Ba33Be(öBe
+žBi
+žBm{Bm
+=Bq  Bu  BxõÃBxë
+B|ë
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A­
+=AŽõÃAŒõÃAŒáHAÄÌÍAÌžRAÌžRAÔ£×AÜ\Aä\AäzáAìffAôQìAôQìAü=qB{B{B
+=B
+  B  B
+õÃBë
+BáHBáHB×
+B
+ÌÍB!ÌÍB!ÂB%žRB)®B)®B-£×B1B5B5\B9
+B=
+B=záBAp€BEffBIffBI\)BMQìBQQìBQG®BU=qBY33BY33B](öBa
+žBe
+žBe{Bi
+=Bm  Bm  BpõÃBtë
+Bxë
+BxáHB|×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A¥
+=A¬õÃA¬õÃAŽáHAŒÌÍAŒžRAÄžRAÌ£×AÌ\AÔ\AÜzáAäffAäQìAìQìAô=qAô(öAü(öB
+=B  B  B	õÃB
+ë
+B
+áHBáHB×
+BÌÍBÌÍB
+ÂB!žRB!®B%®B)£×B)B-B1\B5
+B5
+B9záB=p€B=ffBAffBE\)BIQìBIQìBMG®BQ=qBQ33BU33BY(öBY
+žB]
+žBa{Be
+=Be  Bi  BlõÃBlë
+Bpë
+BtáHBx×
+Bx×
+B|ÌÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+=AõÃA€õÃA¬áHA¬ÌÍAŽžRAŒžRAŒ£×AÄ\AÌ\AÌzáAÔffAÜQìAäQìAä=qAì(öAô(öAô{Aü  B  BõÃBë
+B	áHB
+áHB
+×
+BÌÍBÌÍBÂBžRB
+®B!®B!£×B%B)B)\B-
+B1
+B5záB5p€B9ffB=ffB=\)BAQìBEQìBIG®BI=qBM33BQ33BQ(öBU
+žBY
+žBY{B]
+=Ba  Be  BdõÃBhë
+Blë
+BláHBp×
+Bt×
+BxÌÍBxÂB|žR¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+=AõÃAõÃAáHA€ÌÍA¬žRA¬žRAŽ£×AŒ\AŒ\AÄzáAÌffAÌQìAÔQìAÜ=qAä(öAä(öAì{Aô  Aô  Aûë
+Bë
+BáHBáHB	×
+B
+ÌÍB
+ÌÍBÂBžRB®B®B
+£×B!B!B%\B)
+B)
+B-záB1p€B5ffB5ffB9\)B=QìB=QìBAG®BE=qBI33BI33BM(öBQ
+žBQ
+žBU{BY
+=BY  B]  B`õÃBdë
+Bdë
+BháHBl×
+Bl×
+BpÌÍBtÂBxžRBxžRB|®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+
+=AõÃAõÃAáHAÌÍAžRA€žRA¬£×A¬\AŽ\AŒzáAŒffAÄQìAÌQìAÌ=qAÔ(öAÜ(öAä{Aä  Aì  Aóë
+Aó×
+AûÂBáHB×
+BÌÍB	ÌÍB
+ÂB
+žRB®B®B£×BB
+B!\B!
+B%
+B)záB)p€B-ffB1ffB5\)B5QìB9QìB=G®B==qBA33BE33BI(öBI
+žBM
+žBQ{BQ
+=BU  BY  BXõÃB\ë
+B`ë
+BdáHBd×
+Bh×
+BlÌÍBlÂBpžRBtžRBx®Bx£×B|£×¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aj{Ayë
+AõÃAáHAÌÍAžRAžRA£×A€\A¬\A¬záAŽffAŒQìAŒQìAÄ=qAÌ(öAÌ(öAÔ{AÜ  Aä  Aãë
+Aë×
+AóÂAóÂAû®BÌÍBÌÍBÂB	žRB
+®B
+®B£×BBB\B
+
+B!
+B!záB%p€B)ffB)ffB-\)B1QìB5QìB5G®B9=qB=33B=33BA(öBE
+žBI
+žBI{BM
+=BQ  BQ  BTõÃBXë
+BXë
+B\áHB`×
+Bd×
+BdÌÍBhÂBlžRBlžRBp®Bt£×Bx£×BxB|\¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AZ{AYë
+Aië
+AyÂAÌÍAžRAžRA£×A\A\A€záA¬ffA¬QìAŽQìAŒ=qAŒ(öAÄ(öAÌ{AÌ  AÔ  AÛë
+Aã×
+AãÂAëÂAó®AóAûBÂBžRB®B	®B
+£×B
+BB\B
+B
+B
+záB!p€B!ffB%ffB)\)B)QìB-QìB1G®B5=qB533B933B=(öB=
+žBA
+žBE{BI
+=BI  BM  BPõÃBPë
+BTë
+BXáHBX×
+B\×
+B`ÌÍBdÂBdžRBhžRBl®Bl£×Bp£×BtBx\Bx
+B|
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A:{AIë
+AYë
+AYÂAiAyp€AžRA£×A\A\AzáAffA€QìA¬QìA¬=qAŽ(öAŒ(öAŒ{AÄ  AÌ  AËë
+AÓ×
+AÛÂAãÂAã®AëAóAó
+Aûp€B®B®B£×B	B
+B
+\B
+B
+BzáBp€B
+ffB!ffB!\)B%QìB)QìB)G®B-=qB133B533B5(öB9
+žB=
+žB={BA
+=BE  BI  BHõÃBLë
+BPë
+BPáHBT×
+BX×
+BXÌÍB\ÂB`žRBdžRBd®Bh£×Bl£×BlBp\Bt
+Bx
+BxzáB|p€¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A*{A9ë
+A9ë
+AIÂAYAYp€Aip€AyG®A\A\AzáAffAQìAQìA€=qA¬(öA¬(öAŽ{AŒ  AŒ  AÃë
+AË×
+AËÂAÓÂAÛ®AãAãAë
+Aóp€Aó\)Aû\)B£×BBB	\B
+
+B
+
+BzáBp€BffBffB
+\)B!QìB!QìB%G®B)=qB)33B-33B1(öB5
+žB5
+žB9{B=
+=B=  BA  BDõÃBHë
+BHë
+BLáHBP×
+BP×
+BTÌÍBXÂBXžRB\žRB`®Bd£×Bd£×BhBl\Bl
+Bp
+BtzáBxp€Bxp€B|ff¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A{Aë
+A)ë
+A9ÂA9AIp€AYp€AYG®Ai
+žAy
+žAzáAffAQìAQìA=qA(öA€(öA¬{A¬  AŽ  A»ë
+A»×
+AÃÂAËÂAË®AÓAÛAã
+Aãp€Aë\)Aó\)AóG®Aû33BB\B
+B	
+B
+záB
+p€BffBffB\)BQìB
+QìB!G®B!=qB%33B)33B)(öB-
+žB1
+žB5{B5
+=B9  B=  B<õÃB@ë
+BDë
+BHáHBH×
+BL×
+BPÌÍBPÂBTžRBXžRBX®B\£×B`£×BdBd\Bh
+Bl
+BlzáBpp€Btp€BxffBx\)B|\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @ô(öA	ë
+Aë
+AÂA)A9p€A9p€AIG®AY
+žAY
+žAhõÃAxÌÍAQìAQìA=qA(öA(öA{A€  A¬  A«ë
+A³×
+A»ÂA»ÂAÃ®AËAËAÓ
+AÛp€Aã\)Aã\)AëG®Aó33Aó33Aû
+žB
+B
+BzáB	p€B
+ffB
+ffB\)BQìBQìBG®B
+=qB!33B!33B%(öB)
+žB)
+žB-{B1
+=B5  B5  B8õÃB<ë
+B<ë
+B@áHBD×
+BH×
+BHÌÍBLÂBPžRBPžRBT®BX£×BX£×B\B`\Bd
+Bd
+BhzáBlp€Blp€BpffBt\)Bx\)BxQìB|G®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @Ô(ö@Ó×
+@ó×
+A	ÂAAp€A)p€A9G®A9
+žAI
+žAXõÃAXÌÍAh£×Ax£×A=qA(öA(öA{A  A  A£ë
+A«×
+A«ÂA³ÂA»®A»AÃAË
+AËp€AÓ\)AÛ\)AãG®Aã33Aë33Aó
+žAó
+=Aû
+=BzáBp€BffB	ffB
+\)B
+QìBQìBG®B=qB33B
+33B!(öB!
+žB%
+žB){B)
+=B-  B1  B4õÃB4ë
+B8ë
+B<áHB<×
+B@×
+BDÌÍBHÂBHžRBLžRBP®BP£×BT£×BXBX\B\
+B`
+BdzáBdp€Bhp€BlffBl\)Bp\)BtQìBxG®Bx=qB|=q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @(ö@³×
+@Ó×
+@Ó
+@ó33A	p€Ap€AG®A)
+žA9
+žA8õÃAHÌÍAX£×AX£×AhzáAxQìA(öA{A  A  Aë
+A×
+A£ÂA«ÂA«®A³A»A»
+AÃp€AË\)AË\)AÓG®AÛ33Aã33Aã
+žAë
+=Aó
+=AòõÃAúáHBffBffB\)B	QìB
+QìB
+G®B=qB33B33B(öB
+
+žB!
+žB!{B%
+=B)  B)  B,õÃB0ë
+B4ë
+B4áHB8×
+B<×
+B<ÌÍB@ÂBDžRBHžRBH®BL£×BP£×BPBT\BX
+BX
+B\záB`p€Bdp€BdffBh\)Bl\)BlQìBpG®Bt=qBx=qBx33B|(ö¿  ¿  ¿  ¿  ¿  ¿  @hQì@×
+@×
+@³
+@Ó33@ÒáH@òáHA	G®A
+žA
+žA(õÃA8ÌÍA8£×AH£×AXzáAXQìAhQìAx(öA  A  Aë
+A×
+AÂAÂA£®A«A«A³
+A»p€A»\)AÃ\)AËG®AË33AÓ33AÛ
+žAã
+=Aã
+=AêõÃAòáHAòÌÍAúÌÍB\)BQìBQìB	G®B
+=qB
+33B33B(öB
+žB
+žB
+{B!
+=B!  B%  B(õÃB(ë
+B,ë
+B0áHB4×
+B4×
+B8ÌÍB<ÂB<žRB@žRBD®BH£×BH£×BLBP\BP
+BT
+BXzáBXp€B\p€B`ffBd\)Bd\)BhQìBlG®Bl=qBp=qBt33Bx(öBx(öB|
+ž¿  ¿  ¿  ¿  ?Ð£×@'®@g®@
+@33@²áH@ÒáH@Ò\@ò=qA	
+žAõÃAÌÍA(£×A8£×A8záAHQìAXQìAX(öAh  Ax  Aë
+A×
+AÂAÂA®AA£A«
+A«p€A³\)A»\)A»G®AÃ33AË33AË
+žAÓ
+=AÛ
+=AâõÃAâáHAêÌÍAòÌÍAòžRAú£×BQìBG®B=qB	33B
+33B
+(öB
+žB
+žB{B
+=B
+  B!  B õÃB$ë
+B(ë
+B(áHB,×
+B0×
+B4ÌÍB4ÂB8žRB<žRB<®B@£×BD£×BHBH\BL
+BP
+BPzáBTp€BXp€BXffB\\)B`\)BdQìBdG®Bh=qBl=qBl33Bp(öBt(öBx
+žBx{B|
+=¿  ¿  ?!G®?Ï\)?Ï\)@'
+>@fff@áH@áH@²\@Ò=q@Ò=q@ñë
+AÌÍA£×A£×A(záA8QìA8QìAH(öAX  AX  Ag×
+Aw®AÂAÂA®AAA
+A£p€A«\)A«\)A³G®A»33A»33AÃ
+žAË
+=AË
+=AÒõÃAÚáHAâÌÍAâÌÍAêžRAò£×Aò£×Aú\B=qB33B33B	(öB
+
+žB
+
+žB{B
+=B  B  B
+õÃB ë
+B ë
+B$áHB(×
+B(×
+B,ÌÍB0ÂB4žRB4žRB8®B<£×B<£×B@BD\BH
+BH
+BLzáBPp€BPp€BTffBX\)BX\)B\QìB`G®Bd=qBd=qBh33Bl(öBl(öBp
+žBt{Bx
+=Bx
+=B|  ¿  ¿  ?
+žR?Î{?ÌÌÍ@%Â@eÂ@\@=q@²=q@Ñë
+@Ñ@ñG®A£×AzáAQìA(QìA8(öA8  AH  AW×
+AW®Ag
+Aw
+A®AAA
+Ap€A\)A£\)A«G®A«33A³33A»
+žA»
+=AÃ
+=AÊõÃAÊáHAÒÌÍAÚÌÍAâžRAâ£×Aê£×Aò\AòzáAúffB33B(öB
+žB	
+žB
+{B
+=B  B  BõÃBë
+B
+ë
+B áHB ×
+B$×
+B(ÌÍB(ÂB,žRB0žRB4®B4£×B8£×B<B<\B@
+BD
+BHzáBHp€BLp€BPffBP\)BT\)BXQìBXG®B\=qB`=qBd33Bd(öBh(öBl
+žBl{Bp
+=Bt
+=Bx  ¿  ¿  ¿  ¿  ??Ë
+
+?Ë
+
+@%
+ž@dzá@=q@ë
+@±@ÑG®@ÑG®@ðõÂAQìAQìA(öA(  A8  A7×
+AG®AW
+AW
+Ag\)Aw33AA
+Ap€A\)A\)AG®A£33A«33A«
+žA³
+=A»
+=AºõÃAÂáHAÊÌÍAÊÌÍAÒžRAÚ£×Aâ£×Aâ\AêzáAòffAòffAúQìB
+žB
+žB{B	
+=B
+  B
+  BõÃBë
+Bë
+BáHB
+×
+B ×
+B ÌÍB$ÂB(žRB(žRB,®B0£×B4£×B4B8\B<
+B<
+B@záBDp€BHp€BHffBL\)BP\)BPQìBTG®BX=qBX=qB\33B`(öBd(öBd
+žBh{Bl
+=Bl
+=Bp  ¿  ¿  ¿  ¿  ¿  ¿  ?
+=?Ê=p?ÈõÂ@$zá@c×
+@@G®@±G®@ÐõÂ@Ð£×@ð£×A(öA  A  A'×
+A7®A7
+AG
+AW\)AW33Ag33Aw
+=Ap€A\)A\)AG®A33A33A£
+žA«
+=A«
+=A²õÃAºáHAºÌÍAÂÌÍAÊžRAÊ£×AÒ£×AÚ\AâzáAâffAêffAòQìAò=qAú=qB{B
+=B  B	  B
+õÃB
+ë
+Bë
+BáHB×
+B×
+B
+ÌÍB ÂB žRB$žRB(®B(£×B,£×B0B4\B4
+B8
+B<záB<p€B@p€BDffBH\)BH\)BLQìBPG®BP=qBT=qBX33BX(öB\(öB`
+žBd{Bd
+=Bh
+=Bl  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?ë
+?ÈõÂ?Ç®@#33@b\@G®@õÂ@°£×@Ð£×@ÐQì@ð  A  A×
+A®A'
+A7
+A7\)AG33AW33AW
+=AfáHAvžRA\)AG®A33A33A
+žA
+=A£
+=AªõÃAªáHA²ÌÍAºÌÍAºžRAÂ£×AÊ£×AÊ\AÒzáAÚffAâffAâQìAê=qAò=qAò(öAú{B  B  BõÃBë
+B
+ë
+B
+áHB×
+B×
+BÌÍBÂB
+žRB žRB ®B$£×B(£×B(B,\B0
+B4
+B4záB8p€B<p€B<ffB@\)BD\)BHQìBHG®BL=qBP=qBP33BT(öBX(öBX
+žB\{B`
+=Bd
+=Bd  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?\)?Æff?Å
+ž@"\@aë
+@£×@£×@°Qì@Ð  @Ð  @ï®A®A
+A
+A'\)A733A733AG
+=AVáHAVžRAfžRAv\A33A33A
+žA
+=A
+=AõÃA¢áHAªÌÍAªÌÍA²žRAº£×Aº£×AÂ\AÊzáAÊffAÒffAÚQìAâ=qAâ=qAê(öAò{Aò  Aú  B õÃBë
+Bë
+BáHB
+×
+B
+×
+BÌÍBÂBžRBžRB
+®B £×B £×B$B(\B(
+B,
+B0záB4p€B4p€B8ffB<\)B<\)B@QìBDG®BH=qBH=qBL33BP(öBP(öBT
+žBX{BX
+=B\
+=B`  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+=q?Å
+ž?Ã×
+@!G®@aG®@Qì@  @°  @Ï®@Ï\)@ï
+=A
+A\)A33A'33A7
+=A6áHAFžRAVžRAV\AfffAvffA
+žA
+=A
+=AõÃAáHAÌÍA¢ÌÍAªžRAª£×A²£×Aº\AºzáAÂffAÊffAÊQìAÒ=qAÚ=qAâ(öAâ{Aê  Aò  Añë
+Aù×
+B ë
+BáHB×
+B×
+B
+ÌÍB
+ÂBžRBžRB®B£×B
+£×B B \B$
+B(
+B(záB,p€B0p€B4ffB4\)B8\)B<QìB<G®B@=qBD=qBH33BH(öBL(öBP
+žBP{BT
+=BX
+=BX  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?®?Â\?Â\@ £×@`  @  @®@¯\)@Ï
+=@Ï
+=@îžRA33A33A
+=A&áHA6žRA6žRAF\AVffAVffAf=qAv{A
+=AõÃAáHAÌÍAÌÍAžRA¢£×Aª£×Aª\A²záAºffAºffAÂQìAÊ=qAÊ=qAÒ(öAÚ{Aâ  Aâ  Aéë
+Añ×
+Añ×
+AùÂB ×
+B×
+BÌÍBÂB
+žRB
+žRB®B£×B£×BB
+\B 
+B 
+B$záB(p€B(p€B,ffB0\)B4\)B4QìB8G®B<=qB<=qB@33BD(öBH(öBH
+žBL{BP
+=BP
+=BT  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+ž?ÁG®?À  @   @_\)@\)@
+=@¯
+=@ÎžR@Îff@îffA
+=AáHAžRA&žRA6\A6ffAFffAV=qAV{Af{Auë
+AáHAÌÍAÌÍAžRA£×A£×A¢\AªzáAªffA²ffAºQìAº=qAÂ=qAÊ(öAÊ{AÒ  AÚ  Aáë
+Aá×
+Aé×
+AñÂAñ®Aù®B ÌÍBÂBžRBžRB
+®B
+£×B£×BB\B
+B
+
+B záB p€B$p€B(ffB(\)B,\)B0QìB4G®B4=qB8=qB<33B<(öB@(öBD
+žBH{BH
+=BL
+=BP  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?   ?À  ?ŸžR@
+žR@^{@
+=@žR@®ff@Îff@Î{@íÂAžRAžRA\A&ffA6ffA6=qAF{AV{AUë
+AeÂAuAÌÍAžRA£×A£×A\AzáA¢ffAªffAªQìA²=qAº=qAº(öAÂ{AÊ  AÊ  AÑë
+AÙ×
+Aá×
+AáÂAé®Añ®AñAù
+B žRBžRB®B£×B
+£×B
+B\B
+B
+BzáB
+p€B p€B ffB$\)B(\)B(QìB,G®B0=qB4=qB433B8(öB<(öB<
+žB@{BD
+=BH
+=BH  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >úáH?œp€?Œ(ö@
+{@]p€@ff@ff@®{@ÍÂ@Íp€@íp€A\AffAffA&=qA6{A6{AEë
+AUÂAUAeAup€A£×A£×A\AzáAffAffA¢QìAª=qAª=qA²(öAº{Aº  AÂ  AÉë
+AÉ×
+AÑ×
+AÙÂAá®Aá®AéAñ
+Añp€Aùp€B ®B£×B£×BB
+\B
+
+B
+BzáBp€Bp€B
+ffB \)B \)B$QìB(G®B(=qB,=qB033B4(öB4(öB8
+žB<{B<
+=B@
+=BD  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ð£×?Œ(ö?ºáH@
+ÌÍ@\ÌÍ@{@Â@­p€@Íp€@Í
+ž@ìÌÍAffA=qA{A&{A5ë
+A5ÂAEAUAUp€AeG®AuG®A\AzáAffAffAQìA=qA¢=qAª(öAª{A²  Aº  A¹ë
+AÁ×
+AÉ×
+AÉÂAÑ®AÙ®AáAá
+Aép€Añp€Añ\)AùG®B £×BB\B
+B
+
+B
+záBp€Bp€BffB\)B
+\)B QìB G®B$=qB(=qB(33B,(öB0(öB4
+žB4{B8
+=B<
+=B<  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ë
+?¹?¹@
+(ö@[
+@p€@p€@­
+ž@ÌÌÍ@ÌÌÍ@ìzáA{A{Aë
+A%ÂA5A5AEp€AUG®AUG®Ae
+žAtõÃAffAffAQìA=qA=qA(öA¢{Aª  Aª  A±ë
+A¹×
+A¹×
+AÁÂAÉ®AÉ®AÑAÙ
+Aáp€Aáp€Aé\)AñG®AñG®Aù33B \B
+B
+BzáB
+p€B
+p€BffB\)B\)BQìB
+G®B =qB =qB$33B((öB((öB,
+žB0{B4
+=B4
+=B8  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >æff?žQì?·
+>@áH@ZáH@
+ž@ÌÍ@¬ÌÍ@Ìzá@Ì(ö@ì(öAë
+AÂAA%A5p€A5G®AEG®AU
+žATõÃAdÌÍAtÌÍAQìA=qA=qA(öA{A  A¢  A©ë
+A©×
+A±×
+A¹ÂA¹®AÁ®AÉAÉ
+AÑp€AÙp€Aá\)AáG®AéG®Añ33Añ
+žAù
+=B 
+BzáBp€Bp€B
+ffB
+\)B\)BQìBG®B=qB
+=qB 33B (öB$(öB(
+žB({B,
+=B0
+=B4  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Ü(ö?µÂ?µÂ@=q@Y@ÌÍ@zá@¬(ö@Ì(ö@Ë×
+@ë
+AAAp€A%G®A5G®A5
+žADõÃATÌÍATÌÍAd£×AtzáA=qA(öA{A  A  Aë
+A¡×
+A©×
+A©ÂA±®A¹®A¹AÁ
+AÉp€AÉp€AÑ\)AÙG®AáG®Aá33Aé
+žAñ
+=Añ
+=AøõÃB p€Bp€BffB\)B
+\)B
+QìBG®B=qB=qB33B
+(öB (öB 
+žB${B(
+=B(
+=B,  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >×
+=?Žzá?³33@@XõÂ@(ö@(ö@«×
+@Ë
+@Ë33@ë33Ap€AG®AG®A%
+žA4õÃA4ÌÍADÌÍAT£×ATzáAdzáAtQìA{A  A  Aë
+A×
+A×
+A¡ÂA©®A©®A±A¹
+A¹p€AÁp€AÉ\)AÉG®AÑG®AÙ33Aá
+žAá
+=Aé
+=AðõÃAðáHAøáHB ffB\)B\)BQìB
+G®B
+=qB=qB33B(öB(öB
+
+žB {B 
+=B$
+=B(  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ÌÌÍ?³33?±ë
+@Qì@XQì@×
+@
+@«33@Ë33@ÊáH@ê\AG®A
+žAõÃA$ÌÍA4ÌÍA4£×ADzáATzáATQìAd(öAt  A  Aë
+A×
+A×
+AÂA®A¡®A©A©
+A±p€A¹p€A¹\)AÁG®AÉG®AÉ33AÑ
+žAÙ
+=Aá
+=AàõÃAèáHAðáHAðÌÍAøžRB \)BQìBG®B=qB
+=qB
+33B(öB(öB
+žB{B
+
+=B 
+=B   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Ç®?°£×?°£×@®@W
+>@33@33@ªáH@Ê\@Ê\@ê=qAõÃAÌÍAÌÍA$£×A4záA4záADQìAT(öAT  Ad  As×
+A×
+A×
+AÂA®A®AA¡
+A©p€A©p€A±\)A¹G®A¹G®AÁ33AÉ
+žAÉ
+=AÑ
+=AØõÃAàáHAàáHAèÌÍAðžRAðžRAø£×B G®B=qB=qB33B
+(öB
+(öB
+žB{B
+=B
+=B
+  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Â\?¯\)?®{@ff@Vff@áH@\@ª\@Ê=q@Éë
+@éAÌÍA£×AzáA$záA4QìA4(öAD  AT  AS×
+Ac®As®AÂA®A®AA
+Ap€A¡p€A©\)A©G®A±G®A¹33A¹
+žAÁ
+=AÉ
+=AÈõÃAÐáHAØáHAàÌÍAàžRAèžRAð£×Að\AøzáB =qB33B(öB(öB
+
+žB
+{B
+=B
+=B  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >žQì?¬ÌÍ?¬ÌÍ@Â@U
+ž@\@=q@©ë
+@É@É@éG®AzáAzáAQìA$(öA4  A4  AC×
+AS®AS®Ac
+As\)A®AA
+Ap€Ap€A\)A¡G®A©G®A©33A±
+žA¹
+=A¹
+=AÀõÃAÈáHAÈáHAÐÌÍAØžRAàžRAà£×Aè\AðzáAðzáAøffB (öB(öB
+žB{B
+
+=B
+
+=B  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >³33?«
+?ª=q@
+ž@Tzá@ë
+@@©@ÉG®@ÈõÃ@èõÃAQìA(öA  A$  A3×
+A3®AC®AS
+AS\)Ac\)As33A
+Ap€Ap€A\)AG®AG®A¡33A©
+žA©
+=A±
+=AžõÃAžáHAÀáHAÈÌÍAÈžRAÐžRAØ£×Aà\AàzáAèzáAðffAðQìAøQìB 
+žB{B
+=B
+=B
+  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >šõÃ?ª=q?šõÂ@×
+@S33@@G®@šõÃ@ÈõÃ@È£×@èQìA  A  A×
+A#®A3®A3
+AC\)AS\)AS33Ac
+=AráHAp€A\)AG®AG®A33A
+žA¡
+=A©
+=AšõÃA°áHAžáHAžÌÍAÀžRAÈžRAÈ£×AÐ\AØzáAàzáAàffAèQìAðQìAð=qAø(öB 
+=B
+=B  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >£×
+?§®?Šff@33@R\@õÃ@õÃ@š£×@ÈQì@È  @è  A×
+A®A®A#
+A3\)A3\)AC33AS
+=ARáHAbáHAržRAG®AG®A33A
+žA
+=A
+=A õÃAšáHAšáHA°ÌÍAžžRAžžRAÀ£×AÈ\AÈzáAÐzáAØffAàQìAàQìAè=qAð(öAð{Aø{B   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >?Šff?¥
+ž@ë
+@Që
+@£×@Qì@š  @È  @Ç®@ç\)A®A
+A\)A#\)A333A3
+=ABáHARáHARžRAb\Ar\A33A
+žA
+=A
+=AõÃAáHA áHAšÌÍAšžRA°žRAž£×Až\AÀzáAÈzáAÈffAÐQìAØQìAà=qAà(öAè{Að{Að  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >zá?£×
+?£×
+@G®@P£×@  @  @§®@Ç\)@Ç\)@ç
+=A\)A\)A33A#
+=A2áHA2áHABžRAR\AR\AbffAr=qA
+=A
+=AõÃAáHAáHAÌÍA žRAšžRAš£×A°\AžzáAžzáAÀffAÈQìAÈQìAÐ=qAØ(öAà{Aà{Aè  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >\)?¢\?¡G®@  @P  @®@\)@§\)@Ç
+=@ÆžR@æžRA33A
+=AáHA"áHA2žRA2\AB\ARffAR=qAb{Ar{AõÃAáHAáHAÌÍAžRAžRA £×Aš\AšzáA°záAžffAžQìAÀQìAÈ=qAÈ(öAÐ{AØ{Aà  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >
+
+ž?   ?   @\)@NžR@\)@
+=@ŠžR@ÆžR@Æff@æ{AáHAáHAžRA"\A2\A2ffAB=qAR{AR{Aaë
+AqÂAáHAÌÍAžRAžRA£×A\A záAšzáAšffA°QìAžQìAž=qAÀ(öAÈ{AÈ{AÐ  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >  ?žR?p€@žR@N{@žR@žR@Šff@Æ{@ÅÂ@åÂAžRA\A\A"ffA2=qA2{AB{AQë
+AQÂAaÂAqAžRAžRA£×A\AzáAzáA ffAšQìAšQìA°=qAž(öAž{AÀ{AÈ  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >k
+?p€?(ö@
+p€@Mp€@ff@{@¥Â@ÅÂ@Åp€@å
+žA\AffA=qA"{A2{A1ë
+AAÂAQÂAQAap€Aqp€A£×A\AzáAzáAffAQìA QìAš=qAš(öA°{Až{Až  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >aG®?áH?áH@
+ÌÍ@L(ö@
+Â@
+Â@¥p€@Å
+ž@Å
+ž@äÌÍA=qA{A{A!ë
+A1ÂA1ÂAAAQp€AQp€AaG®Aq
+žAzáAzáAffAQìAQìA=qA (öAš{Aš{A°  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >W
+=??Qì@
+
+@K
+@
+p€@
+
+ž@¥
+ž@ÄÌÍ@Äzá@ä(öA{Aë
+AÂA!ÂA1A1p€AAp€AQG®AQ
+žA`õÃApõÃAffAQìAQìA=qA(öA{A {Aš  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >B\?
+>?
+>@
+áH@J=q@
+
+ž@ÌÍ@€zá@Ä(ö@Ä(ö@ã×
+AÂAÂAA!p€A1p€A1G®AA
+žAPõÃAPõÃA`ÌÍAp£×AQìA=qA(öA{A{A  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >8Qì?Â?zá@
+=q@I@zá@(ö@€(ö@Ã×
+@Ã
+@ã
+AAp€Ap€A!G®A1
+žA0õÃA@õÃAPÌÍAP£×A`£×ApzáA(öA{A{A  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >#×
+?zá?33@õÃ@HQì@(ö@×
+@£
+@Ã
+@Ã33@âáHAp€AG®A
+žA õÃA0õÃA0ÌÍA@£×AP£×APzáA`QìAp(öA{A  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >?ë
+?£×@Qì@G®@
+@
+@£33@ÂáH@ÂáH@â\A
+žAõÃAõÃA ÌÍA0£×A0£×A@záAPQìAP(öA`(öAp  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >
+ž?£×?\)@
+=@G
+=@33@áH@¢áH@Â\@Â=q@áë
+A õÃAÌÍA£×A £×A0záA0QìA@(öAP(öAP  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =õÂ?{?{@ff@EÂ@áH@\@¢=q@Áë
+@Áë
+@áA £×A£×AzáA QìA0(öA0(öA@  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =áG®?ÌÍ?
+@Â@E
+ž@=q@ë
+@¡ë
+@Á@ÁG®@áG®A záAQìA(öA (öA0  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =žQì?
+?=q@zá@C×
+@ë
+@@¡G®@ÁG®@ÀõÃ@à£×A (öA(öA  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =£×
+?õÃ?®@×
+@C33@G®@G®@ õÃ@À£×@ÀQì@àQìA   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =uÂ?®?ff@\@B\@õÃ@£×@ Qì@ÀQì@À  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =LÌÍ?
+
+ž?
+
+ž@ë
+@AG®@Qì@Qì@   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =#×
+?×
+?\@ £×@@£×@  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  <£×
+?G®?G®@   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  <#×
+?  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ?!G®?Ð£×@(Qì@hQì@(ö@Ž(ö@Ô(ö@ô(öA
+{A{A*{A:{AJ{AZ{Aj{Az{A
+
+=A
+=A
+=A
+=A¥
+=A­
+=Aµ
+=Aœ
+=AÅ
+=AÍ
+=AÕ
+=AÝ
+=Aå
+=Aí
+=Aõ
+=Aý
+=B
+B
+B
+
+B
+B
+B
+B
+B
+
+B"
+B&
+B*
+B.
+B2
+B6
+B:
+B>
+BB
+BF
+BJ
+BN
+BR
+BV
+BZ
+B^
+Bb
+Bf
+Bj
+Bn
+Br
+Bv
+Bz
+B~
+?
+žR?Ï\)@'®@g®@×
+@³×
+@Ó×
+@ó×
+A	ë
+Aë
+A)ë
+A9ë
+AIë
+AYë
+Aië
+Ayë
+AõÃAõÃAõÃAõÃA€õÃA¬õÃAŽõÃAŒõÃAÄõÃAÌõÃAÔõÃAÜõÃAäõÃAìõÃAôõÃAüõÃBzáBzáB
+záBzáBzáBzáBzáB
+záB"záB&záB*záB.záB2záB6záB:záB>záBBzáBFzáBJzáBNzáBRzáBVzáBZzáB^záBbzáBfzáBjzáBnzáBrzáBvzáBzzáB~zá?
+(ö?Î{@'
+>@g
+>@
+@³
+@Ó
+@ó
+A	ÂAÂA)ÂA9ÂAIÂAYÂAiÂAyÂAáHAáHAáHAáHA€áHA¬áHAŽáHAŒáHAÄáHAÌáHAÔáHAÜáHAäáHAìáHAôáHAüáHBp€Bp€B
+p€Bp€Bp€Bp€Bp€B
+p€B"p€B&p€B*p€B.p€B2p€B6p€B:p€B>p€BBp€BFp€BJp€BNp€BRp€BVp€BZp€B^p€Bbp€Bfp€Bjp€Bnp€Brp€Bvp€Bzp€B~p€??ÌÌÍ@&ff@fff@33@³33@Ó33@ó33A	AA)A9AIAYAiAyAÌÍAÌÍAÌÍAÌÍA€ÌÍA¬ÌÍAŽÌÍAŒÌÍAÄÌÍAÌÌÍAÔÌÍAÜÌÍAäÌÍAìÌÍAôÌÍAüÌÍBffBffB
+ffBffBffBffBffB
+ffB"ffB&ffB*ffB.ffB2ffB6ffB:ffB>ffBBffBFffBJffBNffBRffBVffBZffB^ffBbffBfffBjffBnffBrffBvffBzffB~ff?
+=?Ë
+
+@%Â@eÂ@áH@²áH@ÒáH@òáHA	p€Ap€A)p€A9p€AIp€AYp€Aip€Ayp€AžRAžRAžRAžRA€žRA¬žRAŽžRAŒžRAÄžRAÌžRAÔžRAÜžRAäžRAìžRAôžRAüžRB\)B\)B
+\)B\)B\)B\)B\)B
+\)B"\)B&\)B*\)B.\)B2\)B6\)B:\)B>\)BB\)BF\)BJ\)BN\)BR\)BV\)BZ\)B^\)Bb\)Bf\)Bj\)Bn\)Br\)Bv\)Bz\)B~\)?zá?Ê=p@%
+ž@e
+ž@\@²\@Ò\@ò\A	G®AG®A)G®A9G®AIG®AYG®AiG®AyG®A£×A£×A£×A£×A€£×A¬£×AŽ£×AŒ£×AÄ£×AÌ£×AÔ£×AÜ£×Aä£×Aì£×Aô£×Aü£×BQìBQìB
+QìBQìBQìBQìBQìB
+QìB"QìB&QìB*QìB.QìB2QìB6QìB:QìB>QìBBQìBFQìBJQìBNQìBRQìBVQìBZQìB^QìBbQìBfQìBjQìBnQìBrQìBvQìBzQìB~Qì?ë
+?ÈõÂ@$zá@dzá@=q@²=q@Ò=q@ò=qA	
+žA
+žA)
+žA9
+žAI
+žAY
+žAi
+žAy
+žA\A\A\A\A€\A¬\AŽ\AŒ\AÄ\AÌ\AÔ\AÜ\Aä\Aì\Aô\Aü\BG®BG®B
+G®BG®BG®BG®BG®B
+G®B"G®B&G®B*G®B.G®B2G®B6G®B:G®B>G®BBG®BFG®BJG®BNG®BRG®BVG®BZG®B^G®BbG®BfG®BjG®BnG®BrG®BvG®BzG®B~G®?\)?Ç®@#×
+@c×
+@ë
+@±ë
+@Ñë
+@ñë
+AõÃAõÃA(õÃA8õÃAHõÃAXõÃAhõÃAxõÃAzáAzáAzáAzáA€záA¬záAŽzáAŒzáAÄzáAÌzáAÔzáAÜzáAäzáAìzáAôzáAüzáB=qB=qB
+=qB=qB=qB=qB=qB
+=qB"=qB&=qB*=qB.=qB2=qB6=qB:=qB>=qBB=qBF=qBJ=qBN=qBR=qBV=qBZ=qB^=qBb=qBf=qBj=qBn=qBr=qBv=qBz=qB~=q?
+ÌÍ?Æff@#33@c33@@±@Ñ@ñAÌÍAÌÍA(ÌÍA8ÌÍAHÌÍAXÌÍAhÌÍAxÌÍAffAffAffAffA€ffA¬ffAŽffAŒffAÄffAÌffAÔffAÜffAäffAìffAôffAüffB33B33B
+33B33B33B33B33B
+33B"33B&33B*33B.33B233B633B:33B>33BB33BF33BJ33BN33BR33BV33BZ33B^33Bb33Bf33Bj33Bn33Br33Bv33Bz33B~33?
+=q?Å
+ž@"\@b\@G®@±G®@ÑG®@ñG®A£×A£×A(£×A8£×AH£×AX£×Ah£×Ax£×AQìAQìAQìAQìA€QìA¬QìAŽQìAŒQìAÄQìAÌQìAÔQìAÜQìAäQìAìQìAôQìAüQìB(öB(öB
+(öB(öB(öB(öB(öB
+(öB"(öB&(öB*(öB.(öB2(öB6(öB:(öB>(öBB(öBF(öBJ(öBN(öBR(öBV(öBZ(öB^(öBb(öBf(öBj(öBn(öBr(öBv(öBz(öB~(ö?®?Ã×
+@!ë
+@aë
+@õÂ@°õÂ@ÐõÂ@ðõÂAzáAzáA(záA8záAHzáAXzáAhzáAxzáA=qA=qA=qA=qA€=qA¬=qAŽ=qAŒ=qAÄ=qAÌ=qAÔ=qAÜ=qAä=qAì=qAô=qAü=qB
+žB
+žB
+
+žB
+žB
+žB
+žB
+žB
+
+žB"
+žB&
+žB*
+žB.
+žB2
+žB6
+žB:
+žB>
+žBB
+žBF
+žBJ
+žBN
+žBR
+žBV
+žBZ
+žB^
+žBb
+žBf
+žBj
+žBn
+žBr
+žBv
+žBz
+žB~
+ž?
+ž?Â\@!G®@aG®@£×@°£×@Ð£×@ð£×AQìAQìA(QìA8QìAHQìAXQìAhQìAxQìA(öA(öA(öA(öA€(öA¬(öAŽ(öAŒ(öAÄ(öAÌ(öAÔ(öAÜ(öAä(öAì(öAô(öAü(öB{B{B
+{B{B{B{B{B
+{B"{B&{B*{B.{B2{B6{B:{B>{BB{BF{BJ{BN{BR{BV{BZ{B^{Bb{Bf{Bj{Bn{Br{Bv{Bz{B~{?\?ÁG®@ £×@`£×@Qì@°Qì@ÐQì@ðQìA(öA(öA((öA8(öAH(öAX(öAh(öAx(öA{A{A{A{A€{A¬{AŽ{AŒ{AÄ{AÌ{AÔ{AÜ{Aä{Aì{Aô{Aü{B
+=B
+=B
+
+=B
+=B
+=B
+=B
+=B
+
+=B"
+=B&
+=B*
+=B.
+=B2
+=B6
+=B:
+=B>
+=BB
+=BF
+=BJ
+=BN
+=BR
+=BV
+=BZ
+=B^
+=Bb
+=Bf
+=Bj
+=Bn
+=Br
+=Bv
+=Bz
+=B~
+=?   ?À  @   @`  @  @°  @Ð  @ð  A  A  A(  A8  AH  AX  Ah  Ax  A  A  A  A  A€  A¬  AŽ  AŒ  AÄ  AÌ  AÔ  AÜ  Aä  Aì  Aô  Aü  B  B  B
+  B  B  B  B  B
+  B"  B&  B*  B.  B2  B6  B:  B>  BB  BF  BJ  BN  BR  BV  BZ  B^  Bb  Bf  Bj  Bn  Br  Bv  Bz  B~  >úáH?ŸžR@\)@_\)@®@¯®@Ï®@ï®A×
+A×
+A'×
+A7×
+AG×
+AW×
+Ag×
+Aw×
+Aë
+Aë
+Aë
+Aë
+A£ë
+A«ë
+A³ë
+A»ë
+AÃë
+AËë
+AÓë
+AÛë
+Aãë
+Aëë
+Aóë
+Aûë
+BõÃBõÃB	õÃB
+õÃBõÃBõÃBõÃB
+õÃB!õÃB%õÃB)õÃB-õÃB1õÃB5õÃB9õÃB=õÃBAõÃBEõÃBIõÃBMõÃBQõÃBUõÃBYõÃB]õÃBaõÃBeõÃBiõÃBmõÃBqõÃBuõÃByõÃB}õÃ>õÂ?œp€@
+žR@^žR@\)@¯\)@Ï\)@ï\)A®A®A'®A7®AG®AW®Ag®Aw®A×
+A×
+A×
+A×
+A£×
+A«×
+A³×
+A»×
+AÃ×
+AË×
+AÓ×
+AÛ×
+Aã×
+Aë×
+Aó×
+Aû×
+Bë
+Bë
+B	ë
+B
+ë
+Bë
+Bë
+Bë
+B
+ë
+B!ë
+B%ë
+B)ë
+B-ë
+B1ë
+B5ë
+B9ë
+B=ë
+BAë
+BEë
+BIë
+BMë
+BQë
+BUë
+BYë
+B]ë
+Baë
+Beë
+Bië
+Bmë
+Bqë
+Buë
+Byë
+B}ë
+>ð£×?Œ(ö@
+{@^{@
+=@¯
+=@Ï
+=@ï
+=A
+A
+A'
+A7
+AG
+AW
+Ag
+Aw
+AÂAÂAÂAÂA£ÂA«ÂA³ÂA»ÂAÃÂAËÂAÓÂAÛÂAãÂAëÂAóÂAûÂBáHBáHB	áHB
+áHBáHBáHBáHB
+áHB!áHB%áHB)áHB-áHB1áHB5áHB9áHB=áHBAáHBEáHBIáHBMáHBQáHBUáHBYáHB]áHBaáHBeáHBiáHBmáHBqáHBuáHByáHB}áH>ë
+?ºáH@
+p€@]p€@žR@®žR@ÎžR@îžRA\)A\)A'\)A7\)AG\)AW\)Ag\)Aw\)A®A®A®A®A£®A«®A³®A»®AÃ®AË®AÓ®AÛ®Aã®Aë®Aó®Aû®B×
+B×
+B	×
+B
+×
+B×
+B×
+B×
+B
+×
+B!×
+B%×
+B)×
+B-×
+B1×
+B5×
+B9×
+B=×
+BA×
+BE×
+BI×
+BM×
+BQ×
+BU×
+BY×
+B]×
+Ba×
+Be×
+Bi×
+Bm×
+Bq×
+Bu×
+By×
+B}×
+>æff?¹@
+ÌÍ@\ÌÍ@ff@®ff@Îff@îffA33A33A'33A733AG33AW33Ag33Aw33AAAAA£A«A³A»AÃAËAÓAÛAãAëAóAûBÌÍBÌÍB	ÌÍB
+ÌÍBÌÍBÌÍBÌÍB
+ÌÍB!ÌÍB%ÌÍB)ÌÍB-ÌÍB1ÌÍB5ÌÍB9ÌÍB=ÌÍBAÌÍBEÌÍBIÌÍBMÌÍBQÌÍBUÌÍBYÌÍB]ÌÍBaÌÍBeÌÍBiÌÍBmÌÍBqÌÍBuÌÍByÌÍB}ÌÍ>áG®?žQì@
+(ö@\(ö@{@®{@Î{@î{A
+=A
+=A'
+=A7
+=AG
+=AW
+=Ag
+=Aw
+=A
+A
+A
+A
+A£
+A«
+A³
+A»
+AÃ
+AË
+AÓ
+AÛ
+Aã
+Aë
+Aó
+Aû
+BÂBÂB	ÂB
+ÂBÂBÂBÂB
+ÂB!ÂB%ÂB)ÂB-ÂB1ÂB5ÂB9ÂB=ÂBAÂBEÂBIÂBMÂBQÂBUÂBYÂB]ÂBaÂBeÂBiÂBmÂBqÂBuÂByÂB}Â>Ü(ö?·
+>@
+@[
+@Â@­Â@ÍÂ@íÂAáHAáHA&áHA6áHAFáHAVáHAfáHAváHAp€Ap€Ap€Ap€A£p€A«p€A³p€A»p€AÃp€AËp€AÓp€AÛp€Aãp€Aëp€Aóp€Aûp€BžRBžRB	žRB
+žRBžRBžRBžRB
+žRB!žRB%žRB)žRB-žRB1žRB5žRB9žRB=žRBAžRBEžRBIžRBMžRBQžRBUžRBYžRB]žRBažRBežRBižRBmžRBqžRBužRByžRB}žR>×
+=?µÂ@áH@ZáH@p€@­p€@Íp€@íp€AžRAžRA&žRA6žRAFžRAVžRAfžRAvžRA\)A\)A\)A\)A£\)A«\)A³\)A»\)AÃ\)AË\)AÓ\)AÛ\)Aã\)Aë\)Aó\)Aû\)B®B®B	®B
+®B®B®B®B
+®B!®B%®B)®B-®B1®B5®B9®B=®BA®BE®BI®BM®BQ®BU®BY®B]®Ba®Be®Bi®Bm®Bq®Bu®By®B}®>Ñë
+?Žzá@=q@Z=q@
+ž@­
+ž@Í
+ž@í
+žA\A\A&\A6\AF\AV\Af\Av\AG®AG®AG®AG®A£G®A«G®A³G®A»G®AÃG®AËG®AÓG®AÛG®AãG®AëG®AóG®AûG®B£×B£×B	£×B
+£×B£×B£×B£×B
+£×B!£×B%£×B)£×B-£×B1£×B5£×B9£×B=£×BA£×BE£×BI£×BM£×BQ£×BU£×BY£×B]£×Ba£×Be£×Bi£×Bm£×Bq£×Bu£×By£×B}£×>ÌÌÍ?³33@@Y@ÌÍ@¬ÌÍ@ÌÌÍ@ìÌÍAffAffA&ffA6ffAFffAVffAfffAvffA33A33A33A33A£33A«33A³33A»33AÃ33AË33AÓ33AÛ33Aã33Aë33Aó33Aû33BBB	B
+BBBB
+B!B%B)B-B1B5B9B=BABEBIBMBQBUBYB]BaBeBiBmBqBuByB}>Ç®?±ë
+@õÂ@XõÂ@zá@¬zá@Ìzá@ìzáA=qA=qA&=qA6=qAF=qAV=qAf=qAv=qA
+žA
+žA
+žA
+žA£
+žA«
+žA³
+žA»
+žAÃ
+žAË
+žAÓ
+žAÛ
+žAã
+žAë
+žAó
+žAû
+žB\B\B	\B
+\B\B\B\B
+\B!\B%\B)\B-\B1\B5\B9\B=\BA\BE\BI\BM\BQ\BU\BY\B]\Ba\Be\Bi\Bm\Bq\Bu\By\B}\>Â\?°£×@Qì@XQì@(ö@¬(ö@Ì(ö@ì(öA{A{A&{A6{AF{AV{Af{Av{A
+=A
+=A
+=A
+=A£
+=A«
+=A³
+=A»
+=AÃ
+=AË
+=AÓ
+=AÛ
+=Aã
+=Aë
+=Aó
+=Aû
+=B
+B
+B	
+B
+
+B
+B
+B
+B
+
+B!
+B%
+B)
+B-
+B1
+B5
+B9
+B=
+BA
+BE
+BI
+BM
+BQ
+BU
+BY
+B]
+Ba
+Be
+Bi
+Bm
+Bq
+Bu
+By
+B}
+>œp€?¯\)@®@W®@×
+@«×
+@Ë×
+@ë×
+Aë
+Aë
+A%ë
+A5ë
+AEë
+AUë
+Aeë
+Auë
+AõÃAõÃAõÃAõÃA¢õÃAªõÃA²õÃAºõÃAÂõÃAÊõÃAÒõÃAÚõÃAâõÃAêõÃAòõÃAúõÃBzáBzáB	záB
+záBzáBzáBzáB
+záB!záB%záB)záB-záB1záB5záB9záB=záBAzáBEzáBIzáBMzáBQzáBUzáBYzáB]záBazáBezáBizáBmzáBqzáBuzáByzáB}zá>žQì?®{@
+>@W
+>@
+@«
+@Ë
+@ë
+AÂAÂA%ÂA5ÂAEÂAUÂAeÂAuÂAáHAáHAáHAáHA¢áHAªáHA²áHAºáHAÂáHAÊáHAÒáHAÚáHAâáHAêáHAòáHAúáHBp€Bp€B	p€B
+p€Bp€Bp€Bp€B
+p€B!p€B%p€B)p€B-p€B1p€B5p€B9p€B=p€BAp€BEp€BIp€BMp€BQp€BUp€BYp€B]p€Bap€Bep€Bip€Bmp€Bqp€Bup€Byp€B}p€>³33?¬ÌÍ@ff@Vff@33@«33@Ë33@ë33AAA%A5AEAUAeAuAÌÍAÌÍAÌÍAÌÍA¢ÌÍAªÌÍA²ÌÍAºÌÍAÂÌÍAÊÌÍAÒÌÍAÚÌÍAâÌÍAêÌÍAòÌÍAúÌÍBffBffB	ffB
+ffBffBffBffB
+ffB!ffB%ffB)ffB-ffB1ffB5ffB9ffB=ffBAffBEffBIffBMffBQffBUffBYffB]ffBaffBeffBiffBmffBqffBuffByffB}ff>®{?«
+@Â@UÂ@áH@ªáH@ÊáH@êáHAp€Ap€A%p€A5p€AEp€AUp€Aep€Aup€AžRAžRAžRAžRA¢žRAªžRA²žRAºžRAÂžRAÊžRAÒžRAÚžRAâžRAêžRAòžRAúžRB\)B\)B	\)B
+\)B\)B\)B\)B
+\)B!\)B%\)B)\)B-\)B1\)B5\)B9\)B=\)BA\)BE\)BI\)BM\)BQ\)BU\)BY\)B]\)Ba\)Be\)Bi\)Bm\)Bq\)Bu\)By\)B}\)>šõÃ?ª=q@
+ž@U
+ž@\@ª\@Ê\@ê\AG®AG®A%G®A5G®AEG®AUG®AeG®AuG®A£×A£×A£×A£×A¢£×Aª£×A²£×Aº£×AÂ£×AÊ£×AÒ£×AÚ£×Aâ£×Aê£×Aò£×Aú£×BQìBQìB	QìB
+QìBQìBQìBQìB
+QìB!QìB%QìB)QìB-QìB1QìB5QìB9QìB=QìBAQìBEQìBIQìBMQìBQQìBUQìBYQìB]QìBaQìBeQìBiQìBmQìBqQìBuQìByQìB}Qì>£×
+?šõÂ@zá@Tzá@=q@ª=q@Ê=q@ê=qA
+žA
+žA%
+žA5
+žAE
+žAU
+žAe
+žAu
+žA\A\A\A\A¢\Aª\A²\Aº\AÂ\AÊ\AÒ\AÚ\Aâ\Aê\Aò\Aú\BG®BG®B	G®B
+G®BG®BG®BG®B
+G®B!G®B%G®B)G®B-G®B1G®B5G®B9G®B=G®BAG®BEG®BIG®BMG®BQG®BUG®BYG®B]G®BaG®BeG®BiG®BmG®BqG®BuG®ByG®B}G®>žR?§®@×
+@S×
+@ë
+@©ë
+@Éë
+@éë
+AõÃAõÃA$õÃA4õÃADõÃATõÃAdõÃAtõÃAzáAzáAzáAzáA¢záAªzáA²záAºzáAÂzáAÊzáAÒzáAÚzáAâzáAêzáAòzáAúzáB=qB=qB	=qB
+=qB=qB=qB=qB
+=qB!=qB%=qB)=qB-=qB1=qB5=qB9=qB==qBA=qBE=qBI=qBM=qBQ=qBU=qBY=qB]=qBa=qBe=qBi=qBm=qBq=qBu=qBy=qB}=q>?Šff@33@S33@@©@É@éAÌÍAÌÍA$ÌÍA4ÌÍADÌÍATÌÍAdÌÍAtÌÍAffAffAffAffA¢ffAªffA²ffAºffAÂffAÊffAÒffAÚffAâffAêffAòffAúffB33B33B	33B
+33B33B33B33B
+33B!33B%33B)33B-33B133B533B933B=33BA33BE33BI33BM33BQ33BU33BY33B]33Ba33Be33Bi33Bm33Bq33Bu33By33B}33>zá?¥
+ž@\@R\@G®@©G®@ÉG®@éG®A£×A£×A$£×A4£×AD£×AT£×Ad£×At£×AQìAQìAQìAQìA¢QìAªQìA²QìAºQìAÂQìAÊQìAÒQìAÚQìAâQìAêQìAòQìAúQìB(öB(öB	(öB
+(öB(öB(öB(öB
+(öB!(öB%(öB)(öB-(öB1(öB5(öB9(öB=(öBA(öBE(öBI(öBM(öBQ(öBU(öBY(öB](öBa(öBe(öBi(öBm(öBq(öBu(öBy(öB}(ö>\)?£×
+@ë
+@Që
+@õÃ@šõÃ@ÈõÃ@èõÃAzáAzáA$záA4záADzáATzáAdzáAtzáA=qA=qA=qA=qA¢=qAª=qA²=qAº=qAÂ=qAÊ=qAÒ=qAÚ=qAâ=qAê=qAò=qAú=qB
+žB
+žB	
+žB
+
+žB
+žB
+žB
+žB
+
+žB!
+žB%
+žB)
+žB-
+žB1
+žB5
+žB9
+žB=
+žBA
+žBE
+žBI
+žBM
+žBQ
+žBU
+žBY
+žB]
+žBa
+žBe
+žBi
+žBm
+žBq
+žBu
+žBy
+žB}
+ž>=q?¢\@G®@QG®@£×@š£×@È£×@è£×AQìAQìA$QìA4QìADQìATQìAdQìAtQìA(öA(öA(öA(öA¢(öAª(öA²(öAº(öAÂ(öAÊ(öAÒ(öAÚ(öAâ(öAê(öAò(öAú(öB{B{B	{B
+{B{B{B{B
+{B!{B%{B){B-{B1{B5{B9{B={BA{BE{BI{BM{BQ{BU{BY{B]{Ba{Be{Bi{Bm{Bq{Bu{By{B}{>
+
+ž?¡G®@£×@P£×@Qì@šQì@ÈQì@èQìA(öA(öA$(öA4(öAD(öAT(öAd(öAt(öA{A{A{A{A¢{Aª{A²{Aº{AÂ{AÊ{AÒ{AÚ{Aâ{Aê{Aò{Aú{B
+=B
+=B	
+=B
+=B
+=B
+=B
+=B
+
+=B!
+=B%
+=B)
+=B-
+=B1
+=B5
+=B9
+=B=
+=BA
+=BE
+=BI
+=BM
+=BQ
+=BU
+=BY
+=B]
+=Ba
+=Be
+=Bi
+=Bm
+=Bq
+=Bu
+=By
+=B}
+=>  ?   @  @P  @  @š  @È  @è  A  A  A$  A4  AD  AT  Ad  At  A  A  A  A  A¢  Aª  A²  Aº  AÂ  AÊ  AÒ  AÚ  Aâ  Aê  Aò  Aú  B  B  B	  B
+  B  B  B  B
+  B!  B%  B)  B-  B1  B5  B9  B=  BA  BE  BI  BM  BQ  BU  BY  B]  Ba  Be  Bi  Bm  Bq  Bu  By  B}  >uÂ?žR@\)@O\)@®@§®@Ç®@ç®A×
+A×
+A#×
+A3×
+AC×
+AS×
+Ac×
+As×
+Aë
+Aë
+Aë
+Aë
+A¡ë
+A©ë
+A±ë
+A¹ë
+AÁë
+AÉë
+AÑë
+AÙë
+Aáë
+Aéë
+Añë
+Aùë
+B õÃBõÃBõÃB
+õÃBõÃBõÃBõÃB
+õÃB õÃB$õÃB(õÃB,õÃB0õÃB4õÃB8õÃB<õÃB@õÃBDõÃBHõÃBLõÃBPõÃBTõÃBXõÃB\õÃB`õÃBdõÃBhõÃBlõÃBpõÃBtõÃBxõÃB|õÃ>k
+?p€@žR@NžR@\)@§\)@Ç\)@ç\)A®A®A#®A3®AC®AS®Ac®As®A×
+A×
+A×
+A×
+A¡×
+A©×
+A±×
+A¹×
+AÁ×
+AÉ×
+AÑ×
+AÙ×
+Aá×
+Aé×
+Añ×
+Aù×
+B ë
+Bë
+Bë
+B
+ë
+Bë
+Bë
+Bë
+B
+ë
+B ë
+B$ë
+B(ë
+B,ë
+B0ë
+B4ë
+B8ë
+B<ë
+B@ë
+BDë
+BHë
+BLë
+BPë
+BTë
+BXë
+B\ë
+B`ë
+Bdë
+Bhë
+Blë
+Bpë
+Btë
+Bxë
+B|ë
+>aG®?(ö@{@N{@
+=@§
+=@Ç
+=@ç
+=A
+A
+A#
+A3
+AC
+AS
+Ac
+As
+AÂAÂAÂAÂA¡ÂA©ÂA±ÂA¹ÂAÁÂAÉÂAÑÂAÙÂAáÂAéÂAñÂAùÂB áHBáHBáHB
+áHBáHBáHBáHB
+áHB áHB$áHB(áHB,áHB0áHB4áHB8áHB<áHB@áHBDáHBHáHBLáHBPáHBTáHBXáHB\áHB`áHBdáHBháHBláHBpáHBtáHBxáHB|áH>W
+=?áH@
+p€@Mp€@žR@ŠžR@ÆžR@æžRA\)A\)A#\)A3\)AC\)AS\)Ac\)As\)A®A®A®A®A¡®A©®A±®A¹®AÁ®AÉ®AÑ®AÙ®Aá®Aé®Añ®Aù®B ×
+B×
+B×
+B
+×
+B×
+B×
+B×
+B
+×
+B ×
+B$×
+B(×
+B,×
+B0×
+B4×
+B8×
+B<×
+B@×
+BD×
+BH×
+BL×
+BP×
+BT×
+BX×
+B\×
+B`×
+Bd×
+Bh×
+Bl×
+Bp×
+Bt×
+Bx×
+B|×
+>LÌÍ?@
+ÌÍ@LÌÍ@ff@Šff@Æff@æffA33A33A#33A333AC33AS33Ac33As33AAAAA¡A©A±A¹AÁAÉAÑAÙAáAéAñAùB ÌÍBÌÍBÌÍB
+ÌÍBÌÍBÌÍBÌÍB
+ÌÍB ÌÍB$ÌÍB(ÌÍB,ÌÍB0ÌÍB4ÌÍB8ÌÍB<ÌÍB@ÌÍBDÌÍBHÌÍBLÌÍBPÌÍBTÌÍBXÌÍB\ÌÍB`ÌÍBdÌÍBhÌÍBlÌÍBpÌÍBtÌÍBxÌÍB|ÌÍ>B\?Qì@
+(ö@L(ö@{@Š{@Æ{@æ{A
+=A
+=A#
+=A3
+=AC
+=AS
+=Ac
+=As
+=A
+A
+A
+A
+A¡
+A©
+A±
+A¹
+AÁ
+AÉ
+AÑ
+AÙ
+Aá
+Aé
+Añ
+Aù
+B ÂBÂBÂB
+ÂBÂBÂBÂB
+ÂB ÂB$ÂB(ÂB,ÂB0ÂB4ÂB8ÂB<ÂB@ÂBDÂBHÂBLÂBPÂBTÂBXÂB\ÂB`ÂBdÂBhÂBlÂBpÂBtÂBxÂB|Â>8Qì?
+>@
+
+@K
+@
+Â@¥Â@ÅÂ@åÂAáHAáHA"áHA2áHABáHARáHAbáHAráHAp€Ap€Ap€Ap€A¡p€A©p€A±p€A¹p€AÁp€AÉp€AÑp€AÙp€Aáp€Aép€Añp€Aùp€B žRBžRBžRB
+žRBžRBžRBžRB
+žRB žRB$žRB(žRB,žRB0žRB4žRB8žRB<žRB@žRBDžRBHžRBLžRBPžRBTžRBXžRB\žRB`žRBdžRBhžRBlžRBpžRBtžRBxžRB|žR>.{?Â@
+áH@JáH@
+p€@¥p€@Åp€@åp€AžRAžRA"žRA2žRABžRARžRAbžRAržRA\)A\)A\)A\)A¡\)A©\)A±\)A¹\)AÁ\)AÉ\)AÑ\)AÙ\)Aá\)Aé\)Añ\)Aù\)B ®B®B®B
+®B®B®B®B
+®B ®B$®B(®B,®B0®B4®B8®B<®B@®BD®BH®BL®BP®BT®BX®B\®B`®Bd®Bh®Bl®Bp®Bt®Bx®B|®>#×
+?zá@
+=q@J=q@
+
+ž@¥
+ž@Å
+ž@å
+žA\A\A"\A2\AB\AR\Ab\Ar\AG®AG®AG®AG®A¡G®A©G®A±G®A¹G®AÁG®AÉG®AÑG®AÙG®AáG®AéG®AñG®AùG®B £×B£×B£×B
+£×B£×B£×B£×B
+£×B £×B$£×B(£×B,£×B0£×B4£×B8£×B<£×B@£×BD£×BH£×BL£×BP£×BT£×BX£×B\£×B`£×Bd£×Bh£×Bl£×Bp£×Bt£×Bx£×B|£×>?33@	@I@ÌÍ@€ÌÍ@ÄÌÍ@äÌÍAffAffA"ffA2ffABffARffAbffArffA33A33A33A33A¡33A©33A±33A¹33AÁ33AÉ33AÑ33AÙ33Aá33Aé33Añ33Aù33B BBB
+BBBB
+B B$B(B,B0B4B8B<B@BDBHBLBPBTBXB\B`BdBhBlBpBtBxB|>\)?ë
+@õÃ@HõÃ@zá@€zá@Äzá@äzáA=qA=qA"=qA2=qAB=qAR=qAb=qAr=qA
+žA
+žA
+žA
+žA¡
+žA©
+žA±
+žA¹
+žAÁ
+žAÉ
+žAÑ
+žAÙ
+žAá
+žAé
+žAñ
+žAù
+žB \B\B\B
+\B\B\B\B
+\B \B$\B(\B,\B0\B4\B8\B<\B@\BD\BH\BL\BP\BT\BX\B\\B`\Bd\Bh\Bl\Bp\Bt\Bx\B|\>
+ž?£×@Qì@HQì@(ö@€(ö@Ä(ö@ä(öA{A{A"{A2{AB{AR{Ab{Ar{A
+=A
+=A
+=A
+=A¡
+=A©
+=A±
+=A¹
+=AÁ
+=AÉ
+=AÑ
+=AÙ
+=Aá
+=Aé
+=Añ
+=Aù
+=B 
+B
+B
+B
+
+B
+B
+B
+B
+
+B 
+B$
+B(
+B,
+B0
+B4
+B8
+B<
+B@
+BD
+BH
+BL
+BP
+BT
+BX
+B\
+B`
+Bd
+Bh
+Bl
+Bp
+Bt
+Bx
+B|
+=õÂ?\)@®@G®@×
+@£×
+@Ã×
+@ã×
+Aë
+Aë
+A!ë
+A1ë
+AAë
+AQë
+Aaë
+Aqë
+AõÃAõÃAõÃAõÃA õÃAšõÃA°õÃAžõÃAÀõÃAÈõÃAÐõÃAØõÃAàõÃAèõÃAðõÃAøõÃB záBzáBzáB
+záBzáBzáBzáB
+záB záB$záB(záB,záB0záB4záB8záB<záB@záBDzáBHzáBLzáBPzáBTzáBXzáB\záB`záBdzáBhzáBlzáBpzáBtzáBxzáB|zá=áG®?{@
+=@G
+=@
+@£
+@Ã
+@ã
+AÂAÂA!ÂA1ÂAAÂAQÂAaÂAqÂAáHAáHAáHAáHA áHAšáHA°áHAžáHAÀáHAÈáHAÐáHAØáHAàáHAèáHAðáHAøáHB p€Bp€Bp€B
+p€Bp€Bp€Bp€B
+p€B p€B$p€B(p€B,p€B0p€B4p€B8p€B<p€B@p€BDp€BHp€BLp€BPp€BTp€BXp€B\p€B`p€Bdp€Bhp€Blp€Bpp€Btp€Bxp€B|p€=ÌÌÍ?ÌÍ@ff@Fff@33@£33@Ã33@ã33AAA!A1AAAQAaAqAÌÍAÌÍAÌÍAÌÍA ÌÍAšÌÍA°ÌÍAžÌÍAÀÌÍAÈÌÍAÐÌÍAØÌÍAàÌÍAèÌÍAðÌÍAøÌÍB ffBffBffB
+ffBffBffBffB
+ffB ffB$ffB(ffB,ffB0ffB4ffB8ffB<ffB@ffBDffBHffBLffBPffBTffBXffB\ffB`ffBdffBhffBlffBpffBtffBxffB|ff=žQì?
+@Â@EÂ@áH@¢áH@ÂáH@âáHAp€Ap€A!p€A1p€AAp€AQp€Aap€Aqp€AžRAžRAžRAžRA žRAšžRA°žRAžžRAÀžRAÈžRAÐžRAØžRAàžRAèžRAðžRAøžRB \)B\)B\)B
+\)B\)B\)B\)B
+\)B \)B$\)B(\)B,\)B0\)B4\)B8\)B<\)B@\)BD\)BH\)BL\)BP\)BT\)BX\)B\\)B`\)Bd\)Bh\)Bl\)Bp\)Bt\)Bx\)B|\)=£×
+?=q@
+ž@E
+ž@\@¢\@Â\@â\AG®AG®A!G®A1G®AAG®AQG®AaG®AqG®A£×A£×A£×A£×A £×Aš£×A°£×Až£×AÀ£×AÈ£×AÐ£×AØ£×Aà£×Aè£×Að£×Aø£×B QìBQìBQìB
+QìBQìBQìBQìB
+QìB QìB$QìB(QìB,QìB0QìB4QìB8QìB<QìB@QìBDQìBHQìBLQìBPQìBTQìBXQìB\QìB`QìBdQìBhQìBlQìBpQìBtQìBxQìB|Qì=\)?õÃ@zá@Dzá@=q@¢=q@Â=q@â=qA
+žA
+žA!
+žA1
+žAA
+žAQ
+žAa
+žAq
+žA\A\A\A\A \Aš\A°\Až\AÀ\AÈ\AÐ\AØ\Aà\Aè\Að\Aø\B G®BG®BG®B
+G®BG®BG®BG®B
+G®B G®B$G®B(G®B,G®B0G®B4G®B8G®B<G®B@G®BDG®BHG®BLG®BPG®BTG®BXG®B\G®B`G®BdG®BhG®BlG®BpG®BtG®BxG®B|G®=uÂ?®@×
+@C×
+@ë
+@¡ë
+@Áë
+@áë
+A õÃAõÃA õÃA0õÃA@õÃAPõÃA`õÃApõÃAzáAzáAzáAzáA záAšzáA°záAžzáAÀzáAÈzáAÐzáAØzáAàzáAèzáAðzáAøzáB =qB=qB=qB
+=qB=qB=qB=qB
+=qB =qB$=qB(=qB,=qB0=qB4=qB8=qB<=qB@=qBD=qBH=qBL=qBP=qBT=qBX=qB\=qB`=qBd=qBh=qBl=qBp=qBt=qBx=qB|=q=LÌÍ?ff@33@C33@@¡@Á@áA ÌÍAÌÍA ÌÍA0ÌÍA@ÌÍAPÌÍA`ÌÍApÌÍAffAffAffAffA ffAšffA°ffAžffAÀffAÈffAÐffAØffAàffAèffAðffAøffB 33B33B33B
+33B33B33B33B
+33B 33B$33B(33B,33B033B433B833B<33B@33BD33BH33BL33BP33BT33BX33B\33B`33Bd33Bh33Bl33Bp33Bt33Bx33B|33=#×
+?
+
+ž@\@B\@G®@¡G®@ÁG®@áG®A £×A£×A £×A0£×A@£×AP£×A`£×Ap£×AQìAQìAQìAQìA QìAšQìA°QìAžQìAÀQìAÈQìAÐQìAØQìAàQìAèQìAðQìAøQìB (öB(öB(öB
+(öB(öB(öB(öB
+(öB (öB$(öB((öB,(öB0(öB4(öB8(öB<(öB@(öBD(öBH(öBL(öBP(öBT(öBX(öB\(öB`(öBd(öBh(öBl(öBp(öBt(öBx(öB|(ö<õÂ?×
+@ë
+@Aë
+@õÃ@ õÃ@ÀõÃ@àõÃA záAzáA záA0záA@záAPzáA`záApzáA=qA=qA=qA=qA =qAš=qA°=qAž=qAÀ=qAÈ=qAÐ=qAØ=qAà=qAè=qAð=qAø=qB 
+žB
+žB
+žB
+
+žB
+žB
+žB
+žB
+
+žB 
+žB$
+žB(
+žB,
+žB0
+žB4
+žB8
+žB<
+žB@
+žBD
+žBH
+žBL
+žBP
+žBT
+žBX
+žB\
+žB`
+žBd
+žBh
+žBl
+žBp
+žBt
+žBx
+žB|
+ž<£×
+?\@G®@AG®@£×@ £×@À£×@à£×A QìAQìA QìA0QìA@QìAPQìA`QìApQìA(öA(öA(öA(öA (öAš(öA°(öAž(öAÀ(öAÈ(öAÐ(öAØ(öAà(öAè(öAð(öAø(öB {B{B{B
+{B{B{B{B
+{B {B${B({B,{B0{B4{B8{B<{B@{BD{BH{BL{BP{BT{BX{B\{B`{Bd{Bh{Bl{Bp{Bt{Bx{B|{<#×
+?G®@ £×@@£×@Qì@ Qì@ÀQì@àQìA (öA(öA (öA0(öA@(öAP(öA`(öAp(öA{A{A{A{A {Aš{A°{Až{AÀ{AÈ{AÐ{AØ{Aà{Aè{Að{Aø{B 
+=B
+=B
+=B
+
+=B
+=B
+=B
+=B
+
+=B 
+=B$
+=B(
+=B,
+=B0
+=B4
+=B8
+=B<
+=B@
+=BD
+=BH
+=BL
+=BP
+=BT
+=BX
+=B\
+=B`
+=Bd
+=Bh
+=Bl
+=Bp
+=Bt
+=Bx
+=B|
+=    ?  @   @@  @  @   @À  @à  A   A  A   A0  A@  AP  A`  Ap  A  A  A  A  A   Aš  A°  Až  AÀ  AÈ  AÐ  AØ  Aà  Aè  Að  Aø  B   B  B  B
+  B  B  B  B
+  B   B$  B(  B,  B0  B4  B8  B<  B@  BD  BH  BL  BP  BT  BX  B\  B`  Bd  Bh  Bl  Bp  Bt  Bx  B|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+žR?Ð£×¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+(ö?Ï\)?Ï\)@(Qì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+=?ÌÌÍ?Î{@'®@g®@(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?zá?Ë
+
+?Ë
+
+@&ff@g
+>@×
+@×
+@Ž(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?ë
+?ÈõÂ?Ê=p@%Â@eÂ@33@
+@³×
+@Ó×
+@Ô(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+ÌÍ?Ç®?ÈõÂ@$zá@e
+ž@áH@áH@³33@Ó
+@Ó×
+@ó×
+A
+{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+=q?Å
+ž?Æff@#×
+@dzá@=q@\@²áH@ÒáH@Ó33@ó
+A	ë
+Aë
+A{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?
+ž?Ã×
+?Å
+ž@"\@c33@ë
+@=q@²=q@Ò\@ÒáH@òáHA	AÂAë
+A)ë
+A:{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?\?Â\?Â\@!ë
+@b\@G®@@±ë
+@Ò=q@Ò=q@ò\A	p€Ap€AA)ÂA9ë
+A9ë
+AJ{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?   ?À  ?ÁG®@!G®@aG®@õÂ@G®@±G®@Ñ@Ñë
+@ò=qA	
+žAG®Ap€A)p€A9A9ÂAIë
+AYë
+AZ{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >õÂ?ŸžR?À  @   @`£×@£×@£×@°õÂ@ÑG®@ÑG®@ñAõÃA
+žA
+žA)G®A9p€A9p€AIAYÂAYë
+Aië
+Az{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ð£×?Œ(ö?œp€@\)@`  @  @Qì@°£×@Ð£×@ÐõÂ@ñG®A£×AÌÍAõÃA)
+žA9
+žA9G®AIp€AYp€AYAiÂAyë
+AõÃA
+
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >æff?ºáH?Œ(ö@
+{@^žR@®@  @°  @ÐQì@Ð£×@ð£×AzáA£×A£×A(ÌÍA8õÃA9
+žAI
+žAYG®AYp€Aip€AyAáHAõÃAõÃA
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >áG®?¹?¹@
+p€@^{@
+=@\)@¯®@Ð  @Ð  @ðQìAQìAQìAzáA(£×A8£×A8ÌÍAHõÃAY
+žAY
+žAiG®Ayp€AžRAÌÍAáHAõÃAõÃA
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >×
+=?·
+>?žQì@
+ÌÍ@\ÌÍ@žR@
+=@¯
+=@Ï\)@Ï®@ð  A  A(öAQìA(QìA8záA8£×AH£×AXÌÍAXõÃAi
+žAy
+žA£×AžRAžRAÌÍAáHAõÃA€õÃA­
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Ñë
+?µÂ?µÂ@
+@\(ö@ff@ff@®žR@Ï
+=@Ï
+=@ï\)A×
+A  A  A((öA8QìA8QìAHzáAX£×AX£×AhÌÍAxõÃA\A\A£×AžRAžRAÌÍA€áHA¬õÃA¬õÃAµ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >ÌÌÍ?³33?Žzá@áH@ZáH@Â@{@®ff@Îff@ÎžR@ï
+=A
+A®A×
+A(  A8  A8(öAHQìAXQìAXzáAh£×Ax£×AffAzáA\A\A£×AžRA€žRA¬ÌÍA¬áHAŽõÃAŒõÃAœ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >Â\?±ë
+?³33@@Z=q@p€@p€@­Â@Î{@Îff@îffA\)A
+A
+A'®A7×
+A8  AH  AX(öAXQìAhQìAxzáAQìAQìAffAzáA\A\A€£×A¬žRA¬žRAŽÌÍAŒáHAŒõÃAÄõÃAÍ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >œp€?°£×?°£×@õÂ@Y@ÌÍ@
+ž@­p€@Íp€@ÍÂ@î{A33A33A\)A'
+A7
+A7®AG×
+AX  AX  Ah(öAxQìA(öA=qAQìAQìAffAzáA€\A¬\A¬£×AŽžRAŒžRAŒÌÍAÄáHAÌõÃAÌõÃAÕ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >³33?®{?¯\)@Qì@XQì@zá@ÌÍ@¬ÌÍ@Í
+ž@Íp€@íp€AáHA
+=A33A'33A7\)A7
+AG
+AW®AW×
+Ah  Ax  A{A(öA(öA=qAQìAQìA€ffA¬záA¬\AŽ\AŒ£×AŒžRAÄžRAÌÌÍAÌáHAÔõÃAÜõÃAå
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >®{?¬ÌÍ?¬ÌÍ@
+>@W®@(ö@(ö@¬zá@ÌÌÍ@ÌÌÍ@í
+žAžRAžRAáHA'
+=A733A733AG\)AW
+AW
+Ag®Aw×
+A  A  A{A(öA(öA=qA€QìA¬QìA¬ffAŽzáAŒ\AŒ\AÄ£×AÌžRAÌžRAÔÌÍAÜáHAäõÃAäõÃAí
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >šõÃ?ª=q?«
+@ff@Vff@
+@×
+@¬(ö@Ì(ö@Ìzá@ìÌÍAffA\AžRA&žRA6áHA7
+=AG33AW33AW\)Ag
+Aw
+A×
+Aë
+A  A  A{A(öA€(öA¬=qA¬QìAŽQìAŒffAŒzáAÄ\AÌ\AÌ£×AÔžRAÜžRAäÌÍAäáHAìõÃAôõÃAõ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >žR?šõÂ?ª=q@
+ž@UÂ@33@33@«
+@Ë×
+@Ì(ö@ì(öA=qAffAffA&\A6žRA6žRAFáHAW
+=AW33Ag33Aw\)AÂAÂA×
+Aë
+A  A  A€{A¬(öA¬(öAŽ=qAŒQìAŒQìAÄffAÌzáAÌ\AÔ\AÜ£×AäžRAäžRAìÌÍAôáHAôõÃAüõÃB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >?Šff?§®@zá@U
+ž@\@áH@«33@Ë33@Ë
+@ë×
+A{A{A=qA&ffA6ffA6\AFžRAVžRAVáHAg
+=Aw33AA®AÂAÂA×
+Aë
+A€  A¬  A¬{AŽ(öAŒ(öAŒ=qAÄQìAÌQìAÌffAÔzáAÜ\Aä\Aä£×AìžRAôžRAôÌÍAüáHBzáBzáB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >\)?¥
+ž?Šff@33@S×
+@=q@\@ª\@ÊáH@Ë33@ë33AÂAë
+A{A&{A6=qA6ffAFffAV\AVžRAfžRAváHA
+AAA®AÂAÂA£×
+A«ë
+A¬  AŽ  AŒ{AŒ(öAÄ(öAÌ=qAÌQìAÔQìAÜffAäzáAä\Aì\Aô£×AôžRAüžRBffBp€BzáB
+záB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >=q?£×
+?£×
+@\@S33@@ë
+@ª=q@Ê\@Ê\@êáHAAAÂA%ë
+A6{A6{AF=qAVffAVffAf\AvžRA\)Ap€A
+AAA®A£ÂA«ÂA«×
+A³ë
+AŒ  AŒ  AÄ{AÌ(öAÌ(öAÔ=qAÜQìAäQìAäffAìzáAô\Aô\Aü£×B\)B\)BffB
+p€BzáBzáB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >  ?¡G®?¢\@ë
+@Që
+@G®@@©@Éë
+@Ê=q@ê\AG®Ap€AA%A5ÂA5ë
+AF{AV{AV=qAfffAvffAG®A\)A\)Ap€A
+AA£A«®A«ÂA³ÂA»×
+A»ë
+AÄ  AÌ  AÌ{AÔ(öAÜ(öAä=qAäQìAìQìAôffAôzáAü\BG®BQìB\)B
+\)BffBp€BzáBzáB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >uÂ?   ?   @£×@QG®@õÃ@õÃ@©G®@É@É@éë
+A
+žAG®AG®A%p€A5A5AEÂAUë
+AV{Af{Av=qA33A33AG®A\)A\)Ap€A£
+A«A«A³®A»ÂA»ÂAÃ×
+AËë
+AÌ  AÔ  AÜ{Aä(öAä(öAì=qAôQìAôQìAüffB=qBG®BG®B
+QìB\)B\)BffBp€BzáBzáB
+
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >k
+?p€?žR@  @P  @Qì@£×@šõÃ@ÈõÃ@ÉG®@éAÌÍAõÃA
+žA%G®A5G®A5p€AEAUAUÂAeë
+Av{A
+=A
+žA33A33AG®A\)A£\)A«p€A«
+A³A»A»®AÃÂAËÂAË×
+AÓë
+AÜ  Aä  Aä{Aì(öAô(öAô=qAüQìB(öB33B=qB
+G®BG®BQìB\)B\)BffBp€B
+záB"záB"
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >W
+=?(ö?p€@žR@O\)@  @  @šQì@È£×@ÈõÃ@èõÃA£×AÌÍAÌÍA$õÃA5
+žA5G®AEG®AUp€AUAeAuÂAõÃA
+=A
+=A
+žA33A33A£G®A«\)A«\)A³p€A»
+A»AÃAË®AËÂAÓÂAÛ×
+Aãë
+Aä  Aì  Aô{Aô(öAü(öB
+žB(öB(öB
+33B=qBG®BG®BQìB\)B\)B
+ffB"p€B"záB&záB*
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >LÌÍ?áH?áH@{@NžR@\)@®@š  @È  @ÈQì@è£×AzáAzáA£×A$ÌÍA4ÌÍA4õÃAE
+žAUG®AUG®Aep€AuAÌÍAáHAõÃA
+=A
+=A
+žA£33A«33A«G®A³\)A»\)A»p€AÃ
+AËAËAÓ®AÛÂAãÂAã×
+Aëë
+Aô  Aô  Aü{B{B{B
+žB
+(öB(öB33B=qBG®BG®BQìB
+\)B"\)B"ffB&p€B*záB*záB.
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >8Qì?Qì?@
+p€@Mp€@
+=@\)@§\)@Ç®@È  @è  A(öAQìAzáA$záA4£×A4ÌÍADÌÍATõÃAU
+žAeG®AuG®AžRAÌÍAÌÍAáHAõÃA
+=A£
+=A«
+žA«33A³33A»G®A»\)AÃ\)AËp€AË
+AÓAÛAã®AãÂAëÂAó×
+Aóë
+Aü  B  B
+=B{B
+{B
+žB(öB(öB33B=qBG®B
+G®B"QìB"\)B&\)B*ffB*p€B.záB2záB6
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >.{?
+>?
+>@
+(ö@LÌÍ@žR@žR@§
+=@Ç\)@Ç\)@ç®A  A  A(öA$QìA4záA4záAD£×ATÌÍATÌÍAdõÃAu
+žA£×A£×AžRAÌÍAÌÍAáHA¢õÃA«
+=A«
+=A³
+žA»33A»33AÃG®AË\)AË\)AÓp€AÛ
+AãAãAë®AóÂAóÂAû×
+BõÃB  B  B
+
+=B{B{B
+žB(öB(öB33B
+=qB"G®B"G®B&QìB*\)B*\)B.ffB2p€B6záB6záB:
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >#×
+?zá?Â@
+
+@K
+@{@ff@ŠžR@ÆžR@Ç
+=@ç\)A®A×
+A  A$  A4(öA4QìADzáATzáAT£×AdÌÍAtÌÍAzáA\A£×A£×AžRAÌÍA¢ÌÍAªáHAªõÃA³
+=A»
+=A»
+žAÃ33AË33AËG®AÓ\)AÛ\)Aãp€Aã
+AëAóAó®AûÂBáHBë
+BõÃB
+  B  B
+=B{B{B
+žB(öB
+(öB"33B"=qB&G®B*G®B*QìB.\)B2\)B6ffB6p€B:záB>záB>
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >\)?33?zá@
+=q@JáH@
+Â@
+Â@Š{@Æff@ÆžR@æžRA
+A®A®A#×
+A4  A4  AD(öATQìATzáAdzáAt£×AffAffAzáA\A£×A£×A¢žRAªÌÍAªÌÍA²áHAºõÃA»
+=AÃ
+=AË
+žAË33AÓ33AÛG®Aã\)Aã\)Aëp€Aó
+AóAûB×
+BáHBáHB	ë
+B
+õÃB  B  B
+=B{B{B
+
+žB"(öB"(öB&33B*=qB*G®B.G®B2QìB6\)B6\)B:ffB>p€B>záBBzáBF
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  >
+ž?£×?ë
+@	@J=q@
+
+ž@
+p€@¥Â@ÅÂ@Æ{@æffA\)A\)A
+A#®A3®A3×
+AD  AT  AT(öAdQìAtzáA=qAQìAffAffAzáA\A¢£×Aª£×AªžRA²ÌÍAºÌÍAºáHAÂõÃAË
+=AË
+=AÓ
+žAÛ33Aã33AãG®Aë\)Aó\)Aóp€Aû
+BÌÍBÌÍB×
+B	áHB
+áHB
+ë
+BõÃB  B  B
+=B
+{B"{B"
+žB&(öB*(öB*33B.=qB2G®B6G®B6QìB:\)B>\)B>ffBBp€BFzáBJzáBJ
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =áG®?\)?£×@Qì@HõÃ@ÌÍ@
+
+ž@¥
+ž@Åp€@ÅÂ@åÂA
+=A33A\)A#\)A3
+A3®AC®AS×
+AT  Ad  At(öA(öA=qA=qAQìAffAffA¢záAª\Aª£×A²£×AºžRAºÌÍAÂÌÍAÊáHAÊõÃAÓ
+=AÛ
+=Aã
+žAã33Aë33AóG®Aó\)Aû\)BžRBÂBÌÍB	ÌÍB
+×
+B
+áHBáHBë
+BõÃB  B
+  B"
+=B"{B&{B*
+žB*(öB.(öB233B6=qB6G®B:G®B>QìB>\)BB\)BFffBJp€BJzáBNzáBR
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =ÌÌÍ?{?{@®@HQì@(ö@zá@€ÌÍ@Å
+ž@Å
+ž@åp€AáHAáHA
+=A#33A3\)A3\)AC
+AS®AS®Ac×
+At  A  A{A(öA=qA=qAQìA¢ffAªffAªzáA²\Aº£×Aº£×AÂžRAÊÌÍAÊÌÍAÒáHAÚõÃAã
+=Aã
+=Aë
+žAó33Aó33AûG®B®B®BžRB	ÂB
+ÌÍB
+ÌÍB×
+BáHBáHBë
+B
+õÃB"  B"  B&
+=B*{B*{B.
+žB2(öB6(öB633B:=qB>G®B>G®BBQìBF\)BJ\)BJffBNp€BRzáBRzáBV
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =žQì?
+?ÌÍ@
+=@G
+=@×
+@(ö@€(ö@Äzá@ÄÌÍ@å
+žA\AžRAáHA"áHA3
+=A333AC\)AS\)AS
+Ac®As®Aë
+A  A  A{A(öA=qA¢=qAªQìAªffA²ffAºzáAº\AÂ£×AÊ£×AÊžRAÒÌÍAÚÌÍAâáHAâõÃAë
+=Aó
+=Aó
+žAû33BB£×B®B	®B
+žRB
+ÂBÌÍBÌÍB×
+BáHB
+áHB!ë
+B!õÃB&  B*  B*
+=B.{B2{B6
+žB6(öB:(öB>33B>=qBBG®BFG®BJQìBJ\)BN\)BRffBRp€BVzáBZzáBZ
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =\)?=q?
+@Â@Fff@
+@
+@£×
+@Ä(ö@Ä(ö@äzáAffA\A\A"žRA2áHA2áHAC
+=AS33AS\)Ac\)As
+A×
+A×
+Aë
+A  A  A{A¢(öAª=qAª=qA²QìAºffAºffAÂzáAÊ\AÊ£×AÒ£×AÚžRAâÌÍAâÌÍAêáHAòõÃAó
+=Aû
+=B\BBB	£×B
+®B
+®BžRBÂBÌÍBÌÍB
+×
+B!áHB!áHB%ë
+B)õÃB*  B.  B2
+=B6{B6{B:
+žB>(öB>(öBB33BF=qBJG®BJG®BNQìBR\)BR\)BVffBZp€BZzáB^záBb
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =uÂ?®?õÃ@
+ž@EÂ@áH@33@£
+@Ã
+@Ã×
+@ä(öA{A=qAffA"\A2\A2žRABáHARáHAS
+=Ac33As\)A®AÂA×
+A×
+Aë
+A  A¢  Aª{Aª(öA²=qAº=qAºQìAÂffAÊffAÊzáAÒ\AÚ£×Aâ£×AâžRAêÌÍAòÌÍAòáHAúõÃB
+B
+B\B	B
+B
+£×B®B®BžRBÂB
+ÌÍB!ÌÍB!×
+B%áHB)áHB)ë
+B-õÃB2  B6  B6
+=B:{B>{B>
+žBB(öBF(öBJ33BJ=qBNG®BRG®BRQìBV\)BZ\)BZffB^p€BbzáBfzáBf
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  =#×
+?ff?®@×
+@Dzá@\@áH@¢áH@Ã33@Ã
+@ã
+Aë
+A{A{A"=qA2ffA2\AB\ARžRARáHAbáHAs
+=AA®A®AÂA×
+A×
+A¡ë
+Aª  Aª  A²{Aº(öAº=qAÂ=qAÊQìAÊffAÒffAÚzáAâ\Aâ£×Aê£×AòžRAòÌÍAúÌÍBp€BzáB
+B	
+B
+\B
+BB£×B®B®B
+žRB!ÂB!ÌÍB%ÌÍB)×
+B)áHB-áHB1ë
+B5õÃB6  B:  B>
+=B>{BB{BF
+žBJ(öBJ(öBN33BR=qBRG®BVG®BZQìBZ\)B^\)BbffBfp€BfzáBjzáBn
+¿  ¿  ¿  ¿  ¿  ¿  <õÂ?
+
+ž?
+
+ž@33@C×
+@ë
+@=q@¢\@ÂáH@ÂáH@ã33AÂAÂAë
+A"{A2{A2=qABffAR\AR\AbžRAráHAp€A
+AA®A®AÂA¡×
+A©×
+A©ë
+A²  Aº  Aº{AÂ(öAÊ=qAÊ=qAÒQìAÚffAâffAâzáAê\Aò£×Aò£×AúžRBffBffBp€B	záB
+
+B
+
+B\BBB£×B
+®B!®B!žRB%ÂB)ÌÍB)ÌÍB-×
+B1áHB5áHB5ë
+B9õÃB>  B>  BB
+=BF{BJ{BJ
+žBN(öBR(öBR33BV=qBZG®BZG®B^QìBb\)Bf\)BfffBjp€BnzáBnzáBr
+¿  ¿  ¿  ¿  <#×
+?\?×
+@\@B\@@ë
+@¡ë
+@Â=q@Â\@âáHAp€AAÂA!ÂA1ë
+A2{AB{AR=qARffAb\Ar\A\)Ap€Ap€A
+AA®A¡®A©ÂA©×
+A±×
+A¹ë
+Aº  AÂ  AÊ{AÊ(öAÒ=qAÚ=qAâQìAâffAêffAòzáAò\Aú£×BQìB\)BffB	ffB
+p€B
+záB
+B
+B\BB
+B!£×B!®B%®B)žRB)ÂB-ÌÍB1ÌÍB5×
+B5áHB9áHB=ë
+B=õÃBB  BF  BJ
+=BJ{BN{BR
+žBR(öBV(öBZ33BZ=qB^G®BbG®BfQìBf\)Bj\)BnffBnp€BrzáBvzáBz
+¿  ¿      ?G®?G®@G®@Aë
+@G®@G®@¡@Áë
+@Áë
+@â=qAG®Ap€Ap€A!A1ÂA1ÂAAë
+AR{AR{Ab=qArffAG®AG®A\)Ap€Ap€A
+A¡A©®A©®A±ÂA¹×
+A¹×
+AÁë
+AÊ  AÊ  AÒ{AÚ(öAâ=qAâ=qAêQìAòffAòffAúzáBG®BQìBQìB	\)B
+ffB
+ffBp€BzáB
+B
+B
+\B!B!B%£×B)®B)®B-žRB1ÂB5ÌÍB5ÌÍB9×
+B=áHB=áHBAë
+BEõÃBJ  BJ  BN
+=BR{BR{BV
+žBZ(öBZ(öB^33Bb=qBfG®BfG®BjQìBn\)Bn\)BrffBvp€BzzáBzzáB~
+¿  ¿  ?  @ £×@@£×@£×@õÃ@¡G®@ÁG®@Á@áë
+A õÃA
+žAG®A!p€A1p€A1AAÂAQÂAQë
+Ab{Ar{A
+žA33AG®AG®A\)Ap€A¡p€A©
+A©A±®A¹®A¹ÂAÁ×
+AÉ×
+AÉë
+AÒ  AÚ  Aâ{Aâ(öAê=qAò=qAòQìAúffB33B=qBG®B	QìB
+QìB
+\)BffBffBp€BzáB
+
+B!
+B!\B%B)B)£×B-®B1®B5žRB5ÂB9ÌÍB=ÌÍB=×
+BAáHBEáHBIë
+BIõÃBN  BR  BR
+=BV{BZ{BZ
+žB^(öBb(öBf33Bf=qBjG®BnG®BnQìBr\)Bv\)BzffBzp€B~zá¿  ¿  ¿  ¿  @@  @Qì@Qì@ £×@ÀõÃ@ÁG®@áG®A ÌÍAõÃAõÃA!
+žA1G®A1p€AAp€AQAQÂAaÂAqë
+A
+=A
+=A
+žA33AG®AG®A¡\)A©p€A©p€A±
+A¹A¹®AÁ®AÉÂAÉ×
+AÑ×
+AÙë
+Aâ  Aâ  Aê{Aò(öAò=qAú=qB(öB33B33B	=qB
+G®B
+QìBQìB\)BffBffB
+p€B!záB!
+B%
+B)\B)B-B1£×B5®B5®B9žRB=ÂB=ÌÍBAÌÍBE×
+BIáHBIáHBMë
+BQõÃBR  BV  BZ
+=BZ{B^{Bb
+žBf(öBf(öBj33Bn=qBnG®BrG®BvQìBz\)Bz\)B~ff¿  ¿  ¿  ¿  ¿  ¿  @  @ Qì@ÀQì@À£×@àõÃA £×A£×AÌÍA õÃA0õÃA1
+žAAG®AQp€AQp€AaAqÂAáHAõÃA
+=A
+=A
+žA33A¡G®A©G®A©\)A±p€A¹p€A¹
+AÁAÉ®AÉ®AÑÂAÙ×
+Aá×
+Aáë
+Aê  Aò  Aò{Aú(öB
+žB
+žB(öB	33B
+33B
+=qBG®BQìBQìB\)B
+ffB!ffB!p€B%záB)
+B)
+B-\B1B5B5£×B9®B=®B=žRBAÂBEÌÍBIÌÍBI×
+BMáHBQáHBQë
+BUõÃBZ  BZ  B^
+=Bb{Bf{Bf
+žBj(öBn(öBn33Br=qBvG®BzG®BzQìB~\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @À  @ÀQì@àQìA QìAzáA£×A £×A0ÌÍA0õÃA@õÃAQ
+žAQG®Aap€Aqp€AÌÍAáHAáHAõÃA
+=A
+=A¡
+žA©33A©G®A±G®A¹\)A¹p€AÁp€AÉ
+AÉAÑ®AÙ®AáÂAá×
+Aé×
+Añë
+Aò  Aú  B
+=B{B
+žB	
+žB
+(öB
+33B33B=qBG®BQìB
+QìB!\)B!ffB%ffB)p€B)záB-
+B1
+B5\B5B9B=£×B=®BA®BEžRBIÂBIÌÍBMÌÍBQ×
+BQáHBUáHBYë
+BYõÃB^  Bb  Bf
+=Bf{Bj{Bn
+žBn(öBr(öBv33Bz=qBzG®B~G®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @à  A (öA(öAQìA záA0£×A0£×A@ÌÍAPõÃAPõÃAa
+žAqG®AžRAžRAÌÍAáHAáHAõÃA¡
+=A©
+=A©
+žA±33A¹G®A¹G®AÁ\)AÉp€AÉp€AÑ
+AÙAá®Aá®AéÂAñ×
+Añ×
+Aùë
+B  B  B
+=B	{B
+
+žB
+
+žB(öB33B33B=qB
+G®B!QìB!QìB%\)B)ffB)ffB-p€B1záB5
+B5
+B9\B=B=BA£×BE®BI®BIžRBMÂBQÌÍBQÌÍBU×
+BYáHBYáHB]ë
+BaõÃBf  Bf  Bj
+=Bn{Bn{Br
+žBv(öBz(öBz33B~=q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A  A(öA (öA0QìA0záA@£×AP£×APÌÍA`õÃApõÃA\A£×AžRAžRAÌÍAáHA áHAšõÃA©
+=A±
+=A¹
+žA¹33AÁG®AÉG®AÉ\)AÑp€AÙp€Aá
+AáAé®Añ®AñÂAù×
+B ë
+BõÃB  B	  B
+=B
+{B
+žB
+žB(öB33B
+33B!=qB!G®B%QìB)QìB)\)B-ffB1ffB5p€B5záB9
+B=
+B=\BABEBI£×BI®BM®BQžRBQÂBUÌÍBYÌÍBY×
+B]áHBaáHBeë
+BeõÃBj  Bn  Bn
+=Br{Bv{Bz
+žBz(öB~(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A   A0(öA0(öA@QìAPzáAP£×A`£×ApÌÍAzáAzáA\A£×AžRAžRA ÌÍAšáHAšáHA°õÃA¹
+=A¹
+=AÁ
+žAÉ33AÉG®AÑG®AÙ\)Aáp€Aáp€Aé
+AñAñ®Aù®B áHBë
+Bë
+BõÃB
+  B
+  B
+=B{B
+žB
+žB
+(öB!33B!33B%=qB)G®B)QìB-QìB1\)B5ffB5ffB9p€B=záB=
+BA
+BE\BIBIBM£×BQ®BQ®BUžRBYÂBYÌÍB]ÌÍBa×
+BeáHBeáHBië
+BmõÃBn  Br  Bv
+=Bz{Bz{B~
+ž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A0  A@(öAP(öAPQìA`záAp£×AQìAffAzáAzáA\A£×A žRAšžRAšÌÍA°áHAžáHAžõÃAÁ
+=AÉ
+=AÉ
+žAÑ33AÙG®AáG®Aá\)Aép€Añp€Añ
+AùB ×
+B×
+BáHBë
+B
+ë
+B
+õÃB  B  B
+=B{B
+
+žB!
+žB!(öB%33B)33B)=qB-G®B1QìB5QìB5\)B9ffB=ffB=p€BAzáBE
+BI
+BI\BMBQBQ£×BU®BY®BYžRB]ÂBaÌÍBeÌÍBe×
+BiáHBmáHBmë
+BqõÃBv  Bz  Bz
+=B~{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AP  AP(öA`(öApQìA=qAQìAQìAffAzáAzáA \Aš£×AšžRA°žRAžÌÍAžáHAÀáHAÈõÃAÉ
+=AÑ
+=AÙ
+žAá33AáG®AéG®Añ\)Añp€Aùp€B ÂBÌÍB×
+B×
+B
+áHB
+ë
+Bë
+BõÃB  B  B
+
+=B!{B!
+žB%
+žB)(öB)33B-33B1=qB5G®B5QìB9QìB=\)B=ffBAffBEp€BIzáBI
+BM
+BQ\BQBUBY£×BY®B]®BažRBeÂBeÌÍBiÌÍBm×
+BmáHBqáHBuë
+ByõÃBz  B~  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A`  Ap(öA{A(öA=qAQìAQìAffA záAšzáAš\A°£×AžžRAžžRAÀÌÍAÈáHAÈáHAÐõÃAÙ
+=Aá
+=Aá
+žAé33AñG®AñG®Aù\)B žRBžRBÂBÌÍB
+×
+B
+×
+BáHBë
+Bë
+BõÃB
+  B!  B!
+=B%{B)
+žB)
+žB-(öB133B533B5=qB9G®B=QìB=QìBA\)BEffBIffBIp€BMzáBQ
+BQ
+BU\BYBYB]£×Ba®Be®BežRBiÂBmÌÍBmÌÍBq×
+BuáHByáHByë
+B}õÃ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A  A{A{A(öA=qAQìA QìAšffAšzáA°záAž\Až£×AÀžRAÈžRAÈÌÍAÐáHAØáHAàõÃAá
+=Aé
+=Añ
+žAñ33AùG®B £×B®BžRBžRB
+ÂB
+ÌÍB×
+B×
+BáHBë
+B
+ë
+B õÃB!  B%  B)
+=B){B-
+žB1
+žB5(öB533B933B==qB=G®BAQìBEQìBI\)BIffBMffBQp€BQzáBU
+BY
+BY\B]BaBe£×Be®Bi®BmžRBmÂBqÌÍBuÌÍBy×
+ByáHB}áH¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A  A{A{A(öA =qAšQìAšQìA°ffAžzáAžzáAÀ\AÈ£×AÈžRAÐžRAØÌÍAàáHAàáHAèõÃAñ
+=Añ
+=Aù
+žB B£×B£×B®B
+žRB
+žRBÂBÌÍB×
+B×
+B
+áHB ë
+B ë
+B$õÃB)  B)  B-
+=B1{B5
+žB5
+žB9(öB=33B=33BA=qBEG®BIQìBIQìBM\)BQffBQffBUp€BYzáBY
+B]
+Ba\BeBeBi£×Bm®Bm®BqžRBuÂByÌÍByÌÍB}×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A  A{A {Aš(öAš=qA°QìAžQìAžffAÀzáAÈzáAÈ\AÐ£×AØžRAàžRAàÌÍAèáHAðáHAðõÃAù
+=B 
+B\BB£×B
+£×B
+®BžRBžRBÂBÌÍB
+×
+B ×
+B áHB$ë
+B(ë
+B(õÃB-  B1  B5
+=B5{B9
+žB=
+žB=(öBA33BE33BI=qBIG®BMQìBQQìBQ\)BUffBYffBYp€B]záBa
+Be
+Be\BiBmBm£×Bq®Bu®ByžRByÂB}ÌÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A   Aš{Aš{A°(öAž=qAžQìAÀQìAÈffAÈzáAÐzáAØ\Aà£×AàžRAèžRAðÌÍAðáHAøáHB záB
+B
+B\B
+B
+£×B£×B®BžRBžRB
+ÂB ÌÍB ×
+B$×
+B(áHB(ë
+B,ë
+B0õÃB5  B5  B9
+=B={B=
+žBA
+žBE(öBI33BI33BM=qBQG®BQQìBUQìBY\)BYffB]ffBap€BezáBe
+Bi
+Bm\BmBqBu£×By®By®B}žR¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aš  A°{Až{Až(öAÀ=qAÈQìAÈQìAÐffAØzáAàzáAà\Aè£×AðžRAðžRAøÌÍB p€Bp€BzáB
+B
+
+B
+\BB£×B£×B®B
+žRB žRB ÂB$ÌÍB(×
+B(×
+B,áHB0ë
+B4ë
+B4õÃB9  B=  B=
+=BA{BE
+žBI
+žBI(öBM33BQ33BQ=qBUG®BYQìBYQìB]\)BaffBeffBep€BizáBm
+Bm
+Bq\BuByBy£×B}®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Až  Až{AÀ{AÈ(öAÈ=qAÐQìAØQìAàffAàzáAèzáAð\Að£×AøžRB \)BffBp€Bp€B
+záB
+
+B
+B\BB£×B
+£×B ®B žRB$žRB(ÂB(ÌÍB,×
+B0×
+B4áHB4ë
+B8ë
+B<õÃB=  BA  BE
+=BI{BI
+žBM
+žBQ(öBQ33BU33BY=qBYG®B]QìBaQìBe\)BeffBiffBmp€BmzáBq
+Bu
+By\ByB}¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÀ  AÈ{AÈ{AÐ(öAØ=qAàQìAàQìAèffAðzáAðzáAø\B QìB\)B\)BffB
+p€B
+p€BzáB
+B
+B\B
+B £×B £×B$®B(žRB(žRB,ÂB0ÌÍB4×
+B4×
+B8áHB<ë
+B<ë
+B@õÃBE  BI  BI
+=BM{BQ
+žBQ
+žBU(öBY33BY33B]=qBaG®BeQìBeQìBi\)BmffBmffBqp€BuzáBy
+By
+B}\¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÈ  AÐ{AØ{Aà(öAà=qAèQìAðQìAðffAøzáB =qBG®BQìB\)B
+\)B
+ffBp€Bp€BzáB
+B
+
+B \B B$£×B(£×B(®B,žRB0žRB4ÂB4ÌÍB8×
+B<×
+B<áHB@ë
+BDë
+BHõÃBI  BM  BQ
+=BQ{BU
+žBY
+žBY(öB]33Ba33Be=qBeG®BiQìBmQìBm\)BqffBuffByp€ByzáB}
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AØ  Aà{Aà{Aè(öAð=qAðQìAøQìB 33B=qB=qBG®B
+QìB
+\)B\)BffBp€Bp€B
+záB 
+B 
+B$\B(B(£×B,£×B0®B4žRB4žRB8ÂB<ÌÍB<×
+B@×
+BDáHBHë
+BHë
+BLõÃBQ  BQ  BU
+=BY{BY
+žB]
+žBa(öBe33Be33Bi=qBmG®BmQìBqQìBu\)ByffByffB}p€¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aà  Aè{Að{Að(öAø=qB (öB(öB33B=qB
+=qB
+G®BQìB\)B\)BffB
+p€B p€B záB$
+B(
+B(\B,B0£×B4£×B4®B8žRB<žRB<ÂB@ÌÍBD×
+BH×
+BHáHBLë
+BPë
+BPõÃBU  BY  BY
+=B]{Ba
+žBe
+žBe(öBi33Bm33Bm=qBqG®BuQìByQìBy\)B}ff¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Að  Að{Aø{B {B
+žB(öB(öB
+33B
+=qB=qBG®BQìB\)B
+\)B ffB p€B$p€B(záB(
+B,
+B0\B4B4£×B8£×B<®B<žRB@žRBDÂBHÌÍBH×
+BL×
+BPáHBPë
+BTë
+BXõÃBY  B]  Ba
+=Be{Be
+žBi
+žBm(öBm33Bq33Bu=qByG®ByQìB}Qì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aø  B 
+=B
+=B{B
+žB
+(öB
+(öB33B=qB=qBG®B
+QìB \)B \)B$ffB(p€B(p€B,záB0
+B4
+B4\B8B<£×B<£×B@®BDžRBHžRBHÂBLÌÍBP×
+BP×
+BTáHBXë
+BXë
+B\õÃBa  Be  Be
+=Bi{Bm
+žBm
+žBq(öBu33By33By=qB}G®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B  B
+=B
+=B
+{B
+
+žB(öB(öB33B=qB
+=qB G®B QìB$\)B(\)B(ffB,p€B0p€B4záB4
+B8
+B<\B<B@£×BD£×BH®BHžRBLžRBPÂBPÌÍBT×
+BX×
+BXáHB\ë
+B`ë
+BdõÃBe  Bi  Bm
+=Bm{Bq
+žBu
+žBy(öBy33B}33¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B  B
+
+=B
+
+=B{B
+žB(öB(öB
+33B =qB =qB$G®B(QìB(\)B,\)B0ffB4p€B4p€B8záB<
+B<
+B@\BDBH£×BH£×BL®BPžRBPžRBTÂBXÌÍBX×
+B\×
+B`áHBdë
+Bdë
+BhõÃBm  Bm  Bq
+=Bu{By
+žBy
+žB}(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+  B
+=B
+=B{B
+žB
+(öB (öB 33B$=qB(=qB(G®B,QìB0\)B4\)B4ffB8p€B<p€B<záB@
+BD
+BH\BHBL£×BP£×BP®BTžRBXžRBXÂB\ÌÍB`×
+Bd×
+BdáHBhë
+Blë
+BlõÃBq  Bu  By
+=By{B}
+ž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B  B
+=B
+=B
+{B 
+žB (öB$(öB(33B(=qB,=qB0G®B4QìB4\)B8\)B<ffB<p€B@p€BDzáBH
+BH
+BL\BPBP£×BT£×BX®BXžRB\žRB`ÂBdÌÍBd×
+Bh×
+BláHBlë
+Bpë
+BtõÃBy  By  B}
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B  B
+
+=B 
+=B {B$
+žB((öB((öB,33B0=qB4=qB4G®B8QìB<\)B<\)B@ffBDp€BHp€BHzáBL
+BP
+BP\BTBX£×BX£×B\®B`žRBdžRBdÂBhÌÍBl×
+Bl×
+BpáHBtë
+Bxë
+BxõÃB}  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B   B 
+=B$
+=B({B(
+žB,(öB0(öB433B4=qB8=qB<G®B<QìB@\)BD\)BHffBHp€BLp€BPzáBP
+BT
+BX\BXB\£×B`£×Bd®BdžRBhžRBlÂBlÌÍBp×
+Bt×
+BxáHBxë
+B|ë
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B$  B(
+=B(
+=B,{B0
+žB4(öB4(öB833B<=qB<=qB@G®BDQìBH\)BH\)BLffBPp€BPp€BTzáBX
+BX
+B\\B`Bd£×Bd£×Bh®BlžRBlžRBpÂBtÌÍBx×
+Bx×
+B|áH¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B(  B,
+=B0
+=B4{B4
+žB8(öB<(öB<33B@=qBD=qBHG®BHQìBL\)BP\)BPffBTp€BXp€BXzáB\
+B`
+Bd\BdBh£×Bl£×Bl®BpžRBtžRBxÂBxÌÍB|×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B0  B4
+=B4
+=B8{B<
+žB<(öB@(öBD33BH=qBH=qBLG®BPQìBP\)BT\)BXffBXp€B\p€B`záBd
+Bd
+Bh\BlBl£×Bp£×Bt®BxžRBxžRB|Â¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B4  B8
+=B<
+=B<{B@
+žBD(öBH(öBH33BL=qBP=qBPG®BTQìBX\)BX\)B\ffB`p€Bdp€BdzáBh
+Bl
+Bl\BpBt£×Bx£×Bx®B|žR¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B<  B<
+=B@
+=BD{BH
+žBH(öBL(öBP33BP=qBT=qBXG®BXQìB\\)B`\)BdffBdp€Bhp€BlzáBl
+Bp
+Bt\BxBx£×B|£×¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B@  BD
+=BH
+=BH{BL
+žBP(öBP(öBT33BX=qBX=qB\G®B`QìBd\)Bd\)BhffBlp€Blp€BpzáBt
+Bx
+Bx\B|¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BH  BH
+=BL
+=BP{BP
+žBT(öBX(öBX33B\=qB`=qBdG®BdQìBh\)Bl\)BlffBpp€Btp€BxzáBx
+B|
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BL  BP
+=BP
+=BT{BX
+žBX(öB\(öB`33Bd=qBd=qBhG®BlQìBl\)Bp\)BtffBxp€Bxp€B|zá¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BP  BT
+=BX
+=BX{B\
+žB`(öBd(öBd33Bh=qBl=qBlG®BpQìBt\)Bx\)BxffB|p€¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BX  BX
+=B\
+=B`{Bd
+žBd(öBh(öBl33Bl=qBp=qBtG®BxQìBx\)B|\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B\  B`
+=Bd
+=Bd{Bh
+žBl(öBl(öBp33Bt=qBx=qBxG®B|Qì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bd  Bd
+=Bh
+=Bl{Bl
+žBp(öBt(öBx33Bx=qB|=q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bh  Bl
+=Bl
+=Bp{Bt
+žBx(öBx(öB|33¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bl  Bp
+=Bt
+=Bx{Bx
+žB|(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bt  Bx
+=Bx
+=B|{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bx  B|
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 <#×
+<£×
+<õÂ=#×
+=LÌÍ=uÂ=\)=£×
+=žQì=ÌÌÍ=áG®=õÂ>
+ž>\)>>#×
+>.{>8Qì>B\>LÌÍ>W
+=>aG®>k
+>uÂ>  >
+
+ž>=q>\)>zá>>žR>£×
+>šõÃ>®{>³33>žQì>œp€>Â\>Ç®>ÌÌÍ>Ñë
+>×
+=>Ü(ö>áG®>æff>ë
+>ð£×>õÂ>úáH?   ?\?
+ž?®?
+=q?
+ÌÍ?\)?ë
+?zá?
+=??
+(ö?
+žR?!G®?  ?G®?\?×
+?
+
+ž?ff?®?õÃ?=q?
+?ÌÍ?{?\)?£×?ë
+?33?zá?Â?
+>?Qì??áH?(ö?p€?žR?   ?¡G®?¢\?£×
+?¥
+ž?Šff?§®?šõÂ?ª=q?«
+?¬ÌÍ?®{?¯\)?°£×?±ë
+?³33?Žzá?µÂ?·
+>?žQì?¹?ºáH?Œ(ö?œp€?ŸžR?À  ?ÁG®?Â\?Ã×
+?Å
+ž?Æff?Ç®?ÈõÂ?Ê=p?Ë
+
+?ÌÌÍ?Î{?Ï\)?Ð£×@   @ £×@G®@ë
+@\@33@×
+@zá@
+ž@Â@ff@
+=@®@Qì@õÃ@	@
+=q@
+áH@
+
+@
+(ö@
+ÌÍ@
+p€@{@žR@\)@  @£×@G®@ë
+@\@33@×
+@zá@
+ž@Â@ff@
+>@®@Qì@õÂ@@=q@áH@
+@
+(ö@
+ÌÍ@
+p€@
+{@
+žR@\)@   @ £×@!G®@!ë
+@"\@#33@#×
+@$zá@%
+ž@%Â@&ff@'
+>@'®@(Qì@@  @@£×@AG®@Aë
+@B\@C33@C×
+@Dzá@E
+ž@EÂ@Fff@G
+=@G®@HQì@HõÃ@I@J=q@JáH@K
+@L(ö@LÌÍ@Mp€@N{@NžR@O\)@P  @P£×@QG®@Që
+@R\@S33@S×
+@Tzá@U
+ž@UÂ@Vff@W
+>@W®@XQì@XõÂ@Y@Z=q@ZáH@[
+@\(ö@\ÌÍ@]p€@^{@^žR@_\)@`  @`£×@aG®@aë
+@b\@c33@c×
+@dzá@e
+ž@eÂ@fff@g
+>@g®@hQì@  @Qì@£×@õÃ@G®@@ë
+@=q@\@áH@33@
+@×
+@(ö@zá@ÌÍ@
+
+ž@
+p€@
+Â@{@ff@žR@
+=@\)@®@  @Qì@£×@õÃ@G®@@ë
+@=q@\@áH@33@
+@×
+@(ö@zá@ÌÍ@
+ž@p€@Â@{@ff@žR@
+=@\)@®@  @Qì@£×@õÂ@G®@@ë
+@=q@\@áH@33@
+@×
+@(ö@   @ Qì@ £×@ õÃ@¡G®@¡@¡ë
+@¢=q@¢\@¢áH@£33@£
+@£×
+@€(ö@€zá@€ÌÍ@¥
+ž@¥p€@¥Â@Š{@Šff@ŠžR@§
+=@§\)@§®@š  @šQì@š£×@šõÃ@©G®@©@©ë
+@ª=q@ª\@ªáH@«33@«
+@«×
+@¬(ö@¬zá@¬ÌÍ@­
+ž@­p€@­Â@®{@®ff@®žR@¯
+=@¯\)@¯®@°  @°Qì@°£×@°õÂ@±G®@±@±ë
+@²=q@²\@²áH@³33@³
+@³×
+@Ž(ö@À  @ÀQì@À£×@ÀõÃ@ÁG®@Á@Áë
+@Â=q@Â\@ÂáH@Ã33@Ã
+@Ã×
+@Ä(ö@Äzá@ÄÌÍ@Å
+ž@Åp€@ÅÂ@Æ{@Æff@ÆžR@Ç
+=@Ç\)@Ç®@È  @ÈQì@È£×@ÈõÃ@ÉG®@É@Éë
+@Ê=q@Ê\@ÊáH@Ë33@Ë
+@Ë×
+@Ì(ö@Ìzá@ÌÌÍ@Í
+ž@Íp€@ÍÂ@Î{@Îff@ÎžR@Ï
+=@Ï\)@Ï®@Ð  @ÐQì@Ð£×@ÐõÂ@ÑG®@Ñ@Ñë
+@Ò=q@Ò\@ÒáH@Ó33@Ó
+@Ó×
+@Ô(ö@à  @àQì@à£×@àõÃ@áG®@á@áë
+@â=q@â\@âáH@ã33@ã
+@ã×
+@ä(ö@äzá@äÌÍ@å
+ž@åp€@åÂ@æ{@æff@æžR@ç
+=@ç\)@ç®@è  @èQì@è£×@èõÃ@éG®@é@éë
+@ê=q@ê\@êáH@ë33@ë
+@ë×
+@ì(ö@ìzá@ìÌÍ@í
+ž@íp€@íÂ@î{@îff@îžR@ï
+=@ï\)@ï®@ð  @ðQì@ð£×@ðõÂ@ñG®@ñ@ñë
+@ò=q@ò\@òáH@ó33@ó
+@ó×
+@ô(öA   A (öA QìA záA £×A ÌÍA õÃA
+žAG®Ap€AAÂAë
+A{A=qAffA\AžRAáHA
+=A33A\)A
+A®A×
+A  A(öAQìAzáA£×AÌÍAõÃA
+žAG®Ap€AAÂAë
+A{A=qAffA\AžRAáHA
+=A33A\)A
+A®A×
+A  A(öAQìAzáA£×AÌÍAõÃA	
+žA	G®A	p€A	A	ÂA	ë
+A
+{A  A(öAQìAzáA£×AÌÍAõÃA
+žAG®Ap€AAÂAë
+A{A=qAffA\AžRAáHA
+=A33A\)A
+A®A×
+A  A(öAQìAzáA£×AÌÍAõÃA
+žAG®Ap€AAÂAë
+A{A=qAffA\AžRAáHA
+=A33A\)A
+A®A×
+A  A(öAQìAzáA£×AÌÍAõÃA
+žAG®Ap€AAÂAë
+A{A   A (öA QìA záA £×A ÌÍA õÃA!
+žA!G®A!p€A!A!ÂA!ë
+A"{A"=qA"ffA"\A"žRA"áHA#
+=A#33A#\)A#
+A#®A#×
+A$  A$(öA$QìA$záA$£×A$ÌÍA$õÃA%
+žA%G®A%p€A%A%ÂA%ë
+A&{A&=qA&ffA&\A&žRA&áHA'
+=A'33A'\)A'
+A'®A'×
+A(  A((öA(QìA(záA(£×A(ÌÍA(õÃA)
+žA)G®A)p€A)A)ÂA)ë
+A*{A0  A0(öA0QìA0záA0£×A0ÌÍA0õÃA1
+žA1G®A1p€A1A1ÂA1ë
+A2{A2=qA2ffA2\A2žRA2áHA3
+=A333A3\)A3
+A3®A3×
+A4  A4(öA4QìA4záA4£×A4ÌÍA4õÃA5
+žA5G®A5p€A5A5ÂA5ë
+A6{A6=qA6ffA6\A6žRA6áHA7
+=A733A7\)A7
+A7®A7×
+A8  A8(öA8QìA8záA8£×A8ÌÍA8õÃA9
+žA9G®A9p€A9A9ÂA9ë
+A:{A@  A@(öA@QìA@záA@£×A@ÌÍA@õÃAA
+žAAG®AAp€AAAAÂAAë
+AB{AB=qABffAB\ABžRABáHAC
+=AC33AC\)AC
+AC®AC×
+AD  AD(öADQìADzáAD£×ADÌÍADõÃAE
+žAEG®AEp€AEAEÂAEë
+AF{AF=qAFffAF\AFžRAFáHAG
+=AG33AG\)AG
+AG®AG×
+AH  AH(öAHQìAHzáAH£×AHÌÍAHõÃAI
+žAIG®AIp€AIAIÂAIë
+AJ{AP  AP(öAPQìAPzáAP£×APÌÍAPõÃAQ
+žAQG®AQp€AQAQÂAQë
+AR{AR=qARffAR\ARžRARáHAS
+=AS33AS\)AS
+AS®AS×
+AT  AT(öATQìATzáAT£×ATÌÍATõÃAU
+žAUG®AUp€AUAUÂAUë
+AV{AV=qAVffAV\AVžRAVáHAW
+=AW33AW\)AW
+AW®AW×
+AX  AX(öAXQìAXzáAX£×AXÌÍAXõÃAY
+žAYG®AYp€AYAYÂAYë
+AZ{A`  A`(öA`QìA`záA`£×A`ÌÍA`õÃAa
+žAaG®Aap€AaAaÂAaë
+Ab{Ab=qAbffAb\AbžRAbáHAc
+=Ac33Ac\)Ac
+Ac®Ac×
+Ad  Ad(öAdQìAdzáAd£×AdÌÍAdõÃAe
+žAeG®Aep€AeAeÂAeë
+Af{Af=qAfffAf\AfžRAfáHAg
+=Ag33Ag\)Ag
+Ag®Ag×
+Ah  Ah(öAhQìAhzáAh£×AhÌÍAhõÃAi
+žAiG®Aip€AiAiÂAië
+Aj{Ap  Ap(öApQìApzáAp£×ApÌÍApõÃAq
+žAqG®Aqp€AqAqÂAqë
+Ar{Ar=qArffAr\AržRAráHAs
+=As33As\)As
+As®As×
+At  At(öAtQìAtzáAt£×AtÌÍAtõÃAu
+žAuG®Aup€AuAuÂAuë
+Av{Av=qAvffAv\AvžRAváHAw
+=Aw33Aw\)Aw
+Aw®Aw×
+Ax  Ax(öAxQìAxzáAx£×AxÌÍAxõÃAy
+žAyG®Ayp€AyAyÂAyë
+Az{A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+
+=A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A
+žA33AG®A\)Ap€A
+AA®AÂA×
+Aë
+A  A{A(öA=qAQìAffAzáA\A£×AžRAÌÍAáHAõÃA
+=A   A {A (öA =qA QìA ffA záA \A £×A žRA ÌÍA áHA õÃA¡
+=A¡
+žA¡33A¡G®A¡\)A¡p€A¡
+A¡A¡®A¡ÂA¡×
+A¡ë
+A¢  A¢{A¢(öA¢=qA¢QìA¢ffA¢záA¢\A¢£×A¢žRA¢ÌÍA¢áHA¢õÃA£
+=A£
+žA£33A£G®A£\)A£p€A£
+A£A£®A£ÂA£×
+A£ë
+A€  A€{A€(öA€=qA€QìA€ffA€záA€\A€£×A€žRA€ÌÍA€áHA€õÃA¥
+=Aš  Aš{Aš(öAš=qAšQìAšffAšzáAš\Aš£×AšžRAšÌÍAšáHAšõÃA©
+=A©
+žA©33A©G®A©\)A©p€A©
+A©A©®A©ÂA©×
+A©ë
+Aª  Aª{Aª(öAª=qAªQìAªffAªzáAª\Aª£×AªžRAªÌÍAªáHAªõÃA«
+=A«
+žA«33A«G®A«\)A«p€A«
+A«A«®A«ÂA«×
+A«ë
+A¬  A¬{A¬(öA¬=qA¬QìA¬ffA¬záA¬\A¬£×A¬žRA¬ÌÍA¬áHA¬õÃA­
+=A°  A°{A°(öA°=qA°QìA°ffA°záA°\A°£×A°žRA°ÌÍA°áHA°õÃA±
+=A±
+žA±33A±G®A±\)A±p€A±
+A±A±®A±ÂA±×
+A±ë
+A²  A²{A²(öA²=qA²QìA²ffA²záA²\A²£×A²žRA²ÌÍA²áHA²õÃA³
+=A³
+žA³33A³G®A³\)A³p€A³
+A³A³®A³ÂA³×
+A³ë
+AŽ  AŽ{AŽ(öAŽ=qAŽQìAŽffAŽzáAŽ\AŽ£×AŽžRAŽÌÍAŽáHAŽõÃAµ
+=Až  Až{Až(öAž=qAžQìAžffAžzáAž\Až£×AžžRAžÌÍAžáHAžõÃA¹
+=A¹
+žA¹33A¹G®A¹\)A¹p€A¹
+A¹A¹®A¹ÂA¹×
+A¹ë
+Aº  Aº{Aº(öAº=qAºQìAºffAºzáAº\Aº£×AºžRAºÌÍAºáHAºõÃA»
+=A»
+žA»33A»G®A»\)A»p€A»
+A»A»®A»ÂA»×
+A»ë
+AŒ  AŒ{AŒ(öAŒ=qAŒQìAŒffAŒzáAŒ\AŒ£×AŒžRAŒÌÍAŒáHAŒõÃAœ
+=AÀ  AÀ{AÀ(öAÀ=qAÀQìAÀffAÀzáAÀ\AÀ£×AÀžRAÀÌÍAÀáHAÀõÃAÁ
+=AÁ
+žAÁ33AÁG®AÁ\)AÁp€AÁ
+AÁAÁ®AÁÂAÁ×
+AÁë
+AÂ  AÂ{AÂ(öAÂ=qAÂQìAÂffAÂzáAÂ\AÂ£×AÂžRAÂÌÍAÂáHAÂõÃAÃ
+=AÃ
+žAÃ33AÃG®AÃ\)AÃp€AÃ
+AÃAÃ®AÃÂAÃ×
+AÃë
+AÄ  AÄ{AÄ(öAÄ=qAÄQìAÄffAÄzáAÄ\AÄ£×AÄžRAÄÌÍAÄáHAÄõÃAÅ
+=AÈ  AÈ{AÈ(öAÈ=qAÈQìAÈffAÈzáAÈ\AÈ£×AÈžRAÈÌÍAÈáHAÈõÃAÉ
+=AÉ
+žAÉ33AÉG®AÉ\)AÉp€AÉ
+AÉAÉ®AÉÂAÉ×
+AÉë
+AÊ  AÊ{AÊ(öAÊ=qAÊQìAÊffAÊzáAÊ\AÊ£×AÊžRAÊÌÍAÊáHAÊõÃAË
+=AË
+žAË33AËG®AË\)AËp€AË
+AËAË®AËÂAË×
+AËë
+AÌ  AÌ{AÌ(öAÌ=qAÌQìAÌffAÌzáAÌ\AÌ£×AÌžRAÌÌÍAÌáHAÌõÃAÍ
+=AÐ  AÐ{AÐ(öAÐ=qAÐQìAÐffAÐzáAÐ\AÐ£×AÐžRAÐÌÍAÐáHAÐõÃAÑ
+=AÑ
+žAÑ33AÑG®AÑ\)AÑp€AÑ
+AÑAÑ®AÑÂAÑ×
+AÑë
+AÒ  AÒ{AÒ(öAÒ=qAÒQìAÒffAÒzáAÒ\AÒ£×AÒžRAÒÌÍAÒáHAÒõÃAÓ
+=AÓ
+žAÓ33AÓG®AÓ\)AÓp€AÓ
+AÓAÓ®AÓÂAÓ×
+AÓë
+AÔ  AÔ{AÔ(öAÔ=qAÔQìAÔffAÔzáAÔ\AÔ£×AÔžRAÔÌÍAÔáHAÔõÃAÕ
+=AØ  AØ{AØ(öAØ=qAØQìAØffAØzáAØ\AØ£×AØžRAØÌÍAØáHAØõÃAÙ
+=AÙ
+žAÙ33AÙG®AÙ\)AÙp€AÙ
+AÙAÙ®AÙÂAÙ×
+AÙë
+AÚ  AÚ{AÚ(öAÚ=qAÚQìAÚffAÚzáAÚ\AÚ£×AÚžRAÚÌÍAÚáHAÚõÃAÛ
+=AÛ
+žAÛ33AÛG®AÛ\)AÛp€AÛ
+AÛAÛ®AÛÂAÛ×
+AÛë
+AÜ  AÜ{AÜ(öAÜ=qAÜQìAÜffAÜzáAÜ\AÜ£×AÜžRAÜÌÍAÜáHAÜõÃAÝ
+=Aà  Aà{Aà(öAà=qAàQìAàffAàzáAà\Aà£×AàžRAàÌÍAàáHAàõÃAá
+=Aá
+žAá33AáG®Aá\)Aáp€Aá
+AáAá®AáÂAá×
+Aáë
+Aâ  Aâ{Aâ(öAâ=qAâQìAâffAâzáAâ\Aâ£×AâžRAâÌÍAâáHAâõÃAã
+=Aã
+žAã33AãG®Aã\)Aãp€Aã
+AãAã®AãÂAã×
+Aãë
+Aä  Aä{Aä(öAä=qAäQìAäffAäzáAä\Aä£×AäžRAäÌÍAäáHAäõÃAå
+=Aè  Aè{Aè(öAè=qAèQìAèffAèzáAè\Aè£×AèžRAèÌÍAèáHAèõÃAé
+=Aé
+žAé33AéG®Aé\)Aép€Aé
+AéAé®AéÂAé×
+Aéë
+Aê  Aê{Aê(öAê=qAêQìAêffAêzáAê\Aê£×AêžRAêÌÍAêáHAêõÃAë
+=Aë
+žAë33AëG®Aë\)Aëp€Aë
+AëAë®AëÂAë×
+Aëë
+Aì  Aì{Aì(öAì=qAìQìAìffAìzáAì\Aì£×AìžRAìÌÍAìáHAìõÃAí
+=Að  Að{Að(öAð=qAðQìAðffAðzáAð\Að£×AðžRAðÌÍAðáHAðõÃAñ
+=Añ
+žAñ33AñG®Añ\)Añp€Añ
+AñAñ®AñÂAñ×
+Añë
+Aò  Aò{Aò(öAò=qAòQìAòffAòzáAò\Aò£×AòžRAòÌÍAòáHAòõÃAó
+=Aó
+žAó33AóG®Aó\)Aóp€Aó
+AóAó®AóÂAó×
+Aóë
+Aô  Aô{Aô(öAô=qAôQìAôffAôzáAô\Aô£×AôžRAôÌÍAôáHAôõÃAõ
+=Aø  Aø{Aø(öAø=qAøQìAøffAøzáAø\Aø£×AøžRAøÌÍAøáHAøõÃAù
+=Aù
+žAù33AùG®Aù\)Aùp€Aù
+AùAù®AùÂAù×
+Aùë
+Aú  Aú{Aú(öAú=qAúQìAúffAúzáAú\Aú£×AúžRAúÌÍAúáHAúõÃAû
+=Aû
+žAû33AûG®Aû\)Aûp€Aû
+AûAû®AûÂAû×
+Aûë
+Aü  Aü{Aü(öAü=qAüQìAüffAüzáAü\Aü£×AüžRAüÌÍAüáHAüõÃAý
+=B   B 
+=B {B 
+žB (öB 33B =qB G®B QìB \)B ffB p€B záB 
+B \B B £×B ®B žRB ÂB ÌÍB ×
+B áHB ë
+B õÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB	  B	
+=B	{B	
+žB	(öB	33B	=qB	G®B	QìB	\)B	ffB	p€B	záB	
+B	\B	B	£×B	®B	žRB	ÂB	ÌÍB	×
+B	áHB	ë
+B	õÃB
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+\B
+B
+£×B
+®B
+žRB
+ÂB
+ÌÍB
+×
+B
+áHB
+ë
+B
+õÃB
+  B
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+\B
+B
+£×B
+®B
+žRB
+ÂB
+ÌÍB
+×
+B
+áHB
+ë
+B
+õÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B\BB£×B®BžRBÂBÌÍB×
+BáHBë
+BõÃB  B
+=B{B
+žB(öB33B=qBG®BQìB\)BffBp€BzáB
+B
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+\B
+B
+£×B
+®B
+žRB
+ÂB
+ÌÍB
+×
+B
+áHB
+ë
+B
+õÃB
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B
+\B
+B
+£×B
+®B
+žRB
+ÂB
+ÌÍB
+×
+B
+áHB
+ë
+B
+õÃB
+  B
+
+=B
+{B
+
+žB
+(öB
+33B
+=qB
+G®B
+QìB
+\)B
+ffB
+p€B
+záB
+
+B   B 
+=B {B 
+žB (öB 33B =qB G®B QìB \)B ffB p€B záB 
+B \B B £×B ®B žRB ÂB ÌÍB ×
+B áHB ë
+B õÃB!  B!
+=B!{B!
+žB!(öB!33B!=qB!G®B!QìB!\)B!ffB!p€B!záB!
+B!\B!B!£×B!®B!žRB!ÂB!ÌÍB!×
+B!áHB!ë
+B!õÃB"  B"
+=B"{B"
+žB"(öB"33B"=qB"G®B"QìB"\)B"ffB"p€B"záB"
+B$  B$
+=B${B$
+žB$(öB$33B$=qB$G®B$QìB$\)B$ffB$p€B$záB$
+B$\B$B$£×B$®B$žRB$ÂB$ÌÍB$×
+B$áHB$ë
+B$õÃB%  B%
+=B%{B%
+žB%(öB%33B%=qB%G®B%QìB%\)B%ffB%p€B%záB%
+B%\B%B%£×B%®B%žRB%ÂB%ÌÍB%×
+B%áHB%ë
+B%õÃB&  B&
+=B&{B&
+žB&(öB&33B&=qB&G®B&QìB&\)B&ffB&p€B&záB&
+B(  B(
+=B({B(
+žB((öB(33B(=qB(G®B(QìB(\)B(ffB(p€B(záB(
+B(\B(B(£×B(®B(žRB(ÂB(ÌÍB(×
+B(áHB(ë
+B(õÃB)  B)
+=B){B)
+žB)(öB)33B)=qB)G®B)QìB)\)B)ffB)p€B)záB)
+B)\B)B)£×B)®B)žRB)ÂB)ÌÍB)×
+B)áHB)ë
+B)õÃB*  B*
+=B*{B*
+žB*(öB*33B*=qB*G®B*QìB*\)B*ffB*p€B*záB*
+B,  B,
+=B,{B,
+žB,(öB,33B,=qB,G®B,QìB,\)B,ffB,p€B,záB,
+B,\B,B,£×B,®B,žRB,ÂB,ÌÍB,×
+B,áHB,ë
+B,õÃB-  B-
+=B-{B-
+žB-(öB-33B-=qB-G®B-QìB-\)B-ffB-p€B-záB-
+B-\B-B-£×B-®B-žRB-ÂB-ÌÍB-×
+B-áHB-ë
+B-õÃB.  B.
+=B.{B.
+žB.(öB.33B.=qB.G®B.QìB.\)B.ffB.p€B.záB.
+B0  B0
+=B0{B0
+žB0(öB033B0=qB0G®B0QìB0\)B0ffB0p€B0záB0
+B0\B0B0£×B0®B0žRB0ÂB0ÌÍB0×
+B0áHB0ë
+B0õÃB1  B1
+=B1{B1
+žB1(öB133B1=qB1G®B1QìB1\)B1ffB1p€B1záB1
+B1\B1B1£×B1®B1žRB1ÂB1ÌÍB1×
+B1áHB1ë
+B1õÃB2  B2
+=B2{B2
+žB2(öB233B2=qB2G®B2QìB2\)B2ffB2p€B2záB2
+B4  B4
+=B4{B4
+žB4(öB433B4=qB4G®B4QìB4\)B4ffB4p€B4záB4
+B4\B4B4£×B4®B4žRB4ÂB4ÌÍB4×
+B4áHB4ë
+B4õÃB5  B5
+=B5{B5
+žB5(öB533B5=qB5G®B5QìB5\)B5ffB5p€B5záB5
+B5\B5B5£×B5®B5žRB5ÂB5ÌÍB5×
+B5áHB5ë
+B5õÃB6  B6
+=B6{B6
+žB6(öB633B6=qB6G®B6QìB6\)B6ffB6p€B6záB6
+B8  B8
+=B8{B8
+žB8(öB833B8=qB8G®B8QìB8\)B8ffB8p€B8záB8
+B8\B8B8£×B8®B8žRB8ÂB8ÌÍB8×
+B8áHB8ë
+B8õÃB9  B9
+=B9{B9
+žB9(öB933B9=qB9G®B9QìB9\)B9ffB9p€B9záB9
+B9\B9B9£×B9®B9žRB9ÂB9ÌÍB9×
+B9áHB9ë
+B9õÃB:  B:
+=B:{B:
+žB:(öB:33B:=qB:G®B:QìB:\)B:ffB:p€B:záB:
+B<  B<
+=B<{B<
+žB<(öB<33B<=qB<G®B<QìB<\)B<ffB<p€B<záB<
+B<\B<B<£×B<®B<žRB<ÂB<ÌÍB<×
+B<áHB<ë
+B<õÃB=  B=
+=B={B=
+žB=(öB=33B==qB=G®B=QìB=\)B=ffB=p€B=záB=
+B=\B=B=£×B=®B=žRB=ÂB=ÌÍB=×
+B=áHB=ë
+B=õÃB>  B>
+=B>{B>
+žB>(öB>33B>=qB>G®B>QìB>\)B>ffB>p€B>záB>
+B@  B@
+=B@{B@
+žB@(öB@33B@=qB@G®B@QìB@\)B@ffB@p€B@záB@
+B@\B@B@£×B@®B@žRB@ÂB@ÌÍB@×
+B@áHB@ë
+B@õÃBA  BA
+=BA{BA
+žBA(öBA33BA=qBAG®BAQìBA\)BAffBAp€BAzáBA
+BA\BABA£×BA®BAžRBAÂBAÌÍBA×
+BAáHBAë
+BAõÃBB  BB
+=BB{BB
+žBB(öBB33BB=qBBG®BBQìBB\)BBffBBp€BBzáBB
+BD  BD
+=BD{BD
+žBD(öBD33BD=qBDG®BDQìBD\)BDffBDp€BDzáBD
+BD\BDBD£×BD®BDžRBDÂBDÌÍBD×
+BDáHBDë
+BDõÃBE  BE
+=BE{BE
+žBE(öBE33BE=qBEG®BEQìBE\)BEffBEp€BEzáBE
+BE\BEBE£×BE®BEžRBEÂBEÌÍBE×
+BEáHBEë
+BEõÃBF  BF
+=BF{BF
+žBF(öBF33BF=qBFG®BFQìBF\)BFffBFp€BFzáBF
+BH  BH
+=BH{BH
+žBH(öBH33BH=qBHG®BHQìBH\)BHffBHp€BHzáBH
+BH\BHBH£×BH®BHžRBHÂBHÌÍBH×
+BHáHBHë
+BHõÃBI  BI
+=BI{BI
+žBI(öBI33BI=qBIG®BIQìBI\)BIffBIp€BIzáBI
+BI\BIBI£×BI®BIžRBIÂBIÌÍBI×
+BIáHBIë
+BIõÃBJ  BJ
+=BJ{BJ
+žBJ(öBJ33BJ=qBJG®BJQìBJ\)BJffBJp€BJzáBJ
+BL  BL
+=BL{BL
+žBL(öBL33BL=qBLG®BLQìBL\)BLffBLp€BLzáBL
+BL\BLBL£×BL®BLžRBLÂBLÌÍBL×
+BLáHBLë
+BLõÃBM  BM
+=BM{BM
+žBM(öBM33BM=qBMG®BMQìBM\)BMffBMp€BMzáBM
+BM\BMBM£×BM®BMžRBMÂBMÌÍBM×
+BMáHBMë
+BMõÃBN  BN
+=BN{BN
+žBN(öBN33BN=qBNG®BNQìBN\)BNffBNp€BNzáBN
+BP  BP
+=BP{BP
+žBP(öBP33BP=qBPG®BPQìBP\)BPffBPp€BPzáBP
+BP\BPBP£×BP®BPžRBPÂBPÌÍBP×
+BPáHBPë
+BPõÃBQ  BQ
+=BQ{BQ
+žBQ(öBQ33BQ=qBQG®BQQìBQ\)BQffBQp€BQzáBQ
+BQ\BQBQ£×BQ®BQžRBQÂBQÌÍBQ×
+BQáHBQë
+BQõÃBR  BR
+=BR{BR
+žBR(öBR33BR=qBRG®BRQìBR\)BRffBRp€BRzáBR
+BT  BT
+=BT{BT
+žBT(öBT33BT=qBTG®BTQìBT\)BTffBTp€BTzáBT
+BT\BTBT£×BT®BTžRBTÂBTÌÍBT×
+BTáHBTë
+BTõÃBU  BU
+=BU{BU
+žBU(öBU33BU=qBUG®BUQìBU\)BUffBUp€BUzáBU
+BU\BUBU£×BU®BUžRBUÂBUÌÍBU×
+BUáHBUë
+BUõÃBV  BV
+=BV{BV
+žBV(öBV33BV=qBVG®BVQìBV\)BVffBVp€BVzáBV
+BX  BX
+=BX{BX
+žBX(öBX33BX=qBXG®BXQìBX\)BXffBXp€BXzáBX
+BX\BXBX£×BX®BXžRBXÂBXÌÍBX×
+BXáHBXë
+BXõÃBY  BY
+=BY{BY
+žBY(öBY33BY=qBYG®BYQìBY\)BYffBYp€BYzáBY
+BY\BYBY£×BY®BYžRBYÂBYÌÍBY×
+BYáHBYë
+BYõÃBZ  BZ
+=BZ{BZ
+žBZ(öBZ33BZ=qBZG®BZQìBZ\)BZffBZp€BZzáBZ
+B\  B\
+=B\{B\
+žB\(öB\33B\=qB\G®B\QìB\\)B\ffB\p€B\záB\
+B\\B\B\£×B\®B\žRB\ÂB\ÌÍB\×
+B\áHB\ë
+B\õÃB]  B]
+=B]{B]
+žB](öB]33B]=qB]G®B]QìB]\)B]ffB]p€B]záB]
+B]\B]B]£×B]®B]žRB]ÂB]ÌÍB]×
+B]áHB]ë
+B]õÃB^  B^
+=B^{B^
+žB^(öB^33B^=qB^G®B^QìB^\)B^ffB^p€B^záB^
+B`  B`
+=B`{B`
+žB`(öB`33B`=qB`G®B`QìB`\)B`ffB`p€B`záB`
+B`\B`B`£×B`®B`žRB`ÂB`ÌÍB`×
+B`áHB`ë
+B`õÃBa  Ba
+=Ba{Ba
+žBa(öBa33Ba=qBaG®BaQìBa\)BaffBap€BazáBa
+Ba\BaBa£×Ba®BažRBaÂBaÌÍBa×
+BaáHBaë
+BaõÃBb  Bb
+=Bb{Bb
+žBb(öBb33Bb=qBbG®BbQìBb\)BbffBbp€BbzáBb
+Bd  Bd
+=Bd{Bd
+žBd(öBd33Bd=qBdG®BdQìBd\)BdffBdp€BdzáBd
+Bd\BdBd£×Bd®BdžRBdÂBdÌÍBd×
+BdáHBdë
+BdõÃBe  Be
+=Be{Be
+žBe(öBe33Be=qBeG®BeQìBe\)BeffBep€BezáBe
+Be\BeBe£×Be®BežRBeÂBeÌÍBe×
+BeáHBeë
+BeõÃBf  Bf
+=Bf{Bf
+žBf(öBf33Bf=qBfG®BfQìBf\)BfffBfp€BfzáBf
+Bh  Bh
+=Bh{Bh
+žBh(öBh33Bh=qBhG®BhQìBh\)BhffBhp€BhzáBh
+Bh\BhBh£×Bh®BhžRBhÂBhÌÍBh×
+BháHBhë
+BhõÃBi  Bi
+=Bi{Bi
+žBi(öBi33Bi=qBiG®BiQìBi\)BiffBip€BizáBi
+Bi\BiBi£×Bi®BižRBiÂBiÌÍBi×
+BiáHBië
+BiõÃBj  Bj
+=Bj{Bj
+žBj(öBj33Bj=qBjG®BjQìBj\)BjffBjp€BjzáBj
+Bl  Bl
+=Bl{Bl
+žBl(öBl33Bl=qBlG®BlQìBl\)BlffBlp€BlzáBl
+Bl\BlBl£×Bl®BlžRBlÂBlÌÍBl×
+BláHBlë
+BlõÃBm  Bm
+=Bm{Bm
+žBm(öBm33Bm=qBmG®BmQìBm\)BmffBmp€BmzáBm
+Bm\BmBm£×Bm®BmžRBmÂBmÌÍBm×
+BmáHBmë
+BmõÃBn  Bn
+=Bn{Bn
+žBn(öBn33Bn=qBnG®BnQìBn\)BnffBnp€BnzáBn
+Bp  Bp
+=Bp{Bp
+žBp(öBp33Bp=qBpG®BpQìBp\)BpffBpp€BpzáBp
+Bp\BpBp£×Bp®BpžRBpÂBpÌÍBp×
+BpáHBpë
+BpõÃBq  Bq
+=Bq{Bq
+žBq(öBq33Bq=qBqG®BqQìBq\)BqffBqp€BqzáBq
+Bq\BqBq£×Bq®BqžRBqÂBqÌÍBq×
+BqáHBqë
+BqõÃBr  Br
+=Br{Br
+žBr(öBr33Br=qBrG®BrQìBr\)BrffBrp€BrzáBr
+Bt  Bt
+=Bt{Bt
+žBt(öBt33Bt=qBtG®BtQìBt\)BtffBtp€BtzáBt
+Bt\BtBt£×Bt®BtžRBtÂBtÌÍBt×
+BtáHBtë
+BtõÃBu  Bu
+=Bu{Bu
+žBu(öBu33Bu=qBuG®BuQìBu\)BuffBup€BuzáBu
+Bu\BuBu£×Bu®BužRBuÂBuÌÍBu×
+BuáHBuë
+BuõÃBv  Bv
+=Bv{Bv
+žBv(öBv33Bv=qBvG®BvQìBv\)BvffBvp€BvzáBv
+Bx  Bx
+=Bx{Bx
+žBx(öBx33Bx=qBxG®BxQìBx\)BxffBxp€BxzáBx
+Bx\BxBx£×Bx®BxžRBxÂBxÌÍBx×
+BxáHBxë
+BxõÃBy  By
+=By{By
+žBy(öBy33By=qByG®ByQìBy\)ByffByp€ByzáBy
+By\ByBy£×By®ByžRByÂByÌÍBy×
+ByáHByë
+ByõÃBz  Bz
+=Bz{Bz
+žBz(öBz33Bz=qBzG®BzQìBz\)BzffBzp€BzzáBz
+B|  B|
+=B|{B|
+žB|(öB|33B|=qB|G®B|QìB|\)B|ffB|p€B|záB|
+B|\B|B|£×B|®B|žRB|ÂB|ÌÍB|×
+B|áHB|ë
+B|õÃB}  B}
+=B}{B}
+žB}(öB}33B}=qB}G®B}QìB}\)B}ffB}p€B}záB}
+B}\B}B}£×B}®B}žRB}ÂB}ÌÍB}×
+B}áHB}ë
+B}õÃB~  B~
+=B~{B~
+žB~(öB~33B~=qB~G®B~QìB~\)B~ffB~p€B~záB~
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?  <#×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @   ?G®?G®<£×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @  @@£×@ £×?\?×
+=#×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @   @Qì@Qì@AG®@ë
+?
+
+ž?
+
+ž=LÌÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @À  @ÀQì@ Qì@£×@õÃ@B\@\?ff?®=uÂ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A   @àQì@ÀQì@À£×@ õÃ@G®@G®@C33@×
+?®?õÃ=£×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A  A(öA (ö@à£×@ÀõÃ@ÁG®@¡G®@@ë
+@C×
+@zá?=q?
+=žQì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A0  A (öA(öAQìA zá@áG®@ÁG®@Á@¡ë
+@ë
+@=q@E
+ž@Â?
+?ÌÍ=áG®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A@  A0(öA0(öA QìAzáA£×A £×@á@Áë
+@Áë
+@¢=q@\@áH@EÂ@ff?{?{=õÂ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AP  AP(öA@(öA0QìA0záA £×A£×AÌÍA õÃ@áë
+@Â=q@Â\@¢áH@áH@33@G
+=@
+=?\)?£×>
+ž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Ap  A`(öAP(öAPQìA@záA0£×A0£×A ÌÍAõÃAõÃA
+ž@â\@ÂáH@ÂáH@£33@
+@
+@G®@Qì?£×?ë
+>¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A  A{Ap(öA`QìAPzáAP£×A@£×A0ÌÍA0õÃA õÃA
+žAG®Ap€@âáH@Ã33@Ã
+@£
+@×
+@(ö@HQì@õÃ?33?zá>#×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A  A{A{A(öApzáA`£×AP£×APÌÍA@õÃA0õÃA1
+žA!G®Ap€Ap€A@ã
+@Ã
+@Ã×
+@€(ö@(ö@zá@I@
+=q?zá?Â>8Qì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A  A{A{A(öA=qAQìAp£×A`ÌÍAPõÃAPõÃAA
+žA1G®A1p€A!p€AAÂAÂ@ã×
+@Ä(ö@Ä(ö@€zá@ÌÍ@
+
+ž@J=q@
+áH?
+>?
+>>B\¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aš  A {A{A(öA=qAQìAQìAffApõÃA`õÃAQ
+žAQG®AAp€A1p€A1A!ÂAÂAë
+A{@ä(ö@Äzá@ÄÌÍ@¥
+ž@
+
+ž@
+p€@K
+@
+
+?Qì?>W
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A°  Aš{Aš{A (öA=qAQìAQìAffAzáAzáAq
+žAaG®AQp€AQp€AAA1ÂA1ÂA!ë
+A{A{A=q@äÌÍ@Å
+ž@Å
+ž@¥p€@
+Â@
+Â@L(ö@
+ÌÍ?áH?áH>aG®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Až  Až{A°{Aš(öAš=qA QìAQìAffAzáAzáA\A£×Aqp€Aap€AQAQÂAAÂA1ë
+A2{A"{A=qAffA\@å
+ž@Åp€@ÅÂ@¥Â@{@ff@Mp€@
+p€?(ö?p€>k
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÈ  AÀ{Až{Až(öA°=qAšQìAšQìA ffAzáAzáA\A£×AžRAžRAqAaÂAQÂAQë
+AB{A2{A2=qA"ffA\A\AžR@åÂ@ÅÂ@Æ{@Šff@žR@žR@N{@žR?p€?žR>  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÐ  AÈ{AÈ{AÀ(öAž=qAžQìA°QìAšffAšzáA záA\A£×AžRAžRAÌÍAáHAqÂAaë
+AR{AR{AB=qA2ffA2\A"\AžRAáHAáH@æ{@Æff@ÆžR@ŠžR@
+=@\)@NžR@\)?   ?   >
+
+ž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aà  AØ{AÐ{AÈ(öAÈ=qAÀQìAžQìAžffA°záAšzáAš\A £×AžRAžRAÌÍAáHAáHAõÃAr{Ab{AR=qARffAB\A2\A2žRA"áHAáHA
+=A33@æžR@ÆžR@Ç
+=@§\)@\)@®@P  @  ?¡G®?¢\>\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aè  Aà{Aà{AØ(öAÐ=qAÈQìAÈQìAÀffAžzáAžzáA°\Aš£×AšžRA žRAÌÍAáHAáHAõÃA
+=A
+=Ar=qAbffAR\AR\ABžRA2áHA2áHA#
+=A33A\)A\)@ç
+=@Ç\)@Ç\)@§®@  @  @P£×@G®?£×
+?£×
+>zá¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Að  Að{Aè{Aà(öAà=qAØQìAÐQìAÈffAÈzáAÀzáAž\Až£×A°žRAšžRAšÌÍA áHAáHAõÃA
+=A
+=A
+žA33Ar\Ab\ARžRARáHABáHA3
+=A333A#\)A\)A
+A®@ç\)@Ç®@È  @š  @Qì@£×@Që
+@ë
+?¥
+ž?Šff>¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B   Aø{Að{Að(öAè=qAàQìAàQìAØffAÐzáAÈzáAÈ\AÀ£×AžžRAžžRA°ÌÍAšáHAšáHA õÃA
+=A
+=A
+žA33AG®AG®AržRAbáHARáHAS
+=AC33A3\)A3\)A#
+A®A®A×
+@è  @È  @ÈQì@š£×@õÃ@õÃ@R\@33?Šff?§®>£×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B  B
+=B 
+=Aø(öAð=qAðQìAèQìAàffAàzáAØzáAÐ\AÈ£×AÈžRAÀžRAžÌÍAžáHA°áHAšõÃA©
+=A¡
+=A
+žA33AG®AG®A\)Ap€AráHAc
+=AS33AS\)AC\)A3
+A3®A#®A×
+A  A  @èQì@È£×@ÈõÃ@šõÃ@G®@@S33@×
+?šõÂ?ª=q>šõÃ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+  B
+=B
+=B{B 
+žAøQìAðQìAðffAèzáAàzáAà\AØ£×AÐžRAÈžRAÈÌÍAÀáHAžáHAžõÃA±
+=A©
+=A©
+žA¡33AG®AG®A\)Ap€Ap€A
+As33Ac\)AS\)AS
+AC®A3®A3×
+A$  A  A(öAQì@èõÃ@ÈõÃ@ÉG®@©@@ë
+@Tzá@
+ž?ª=q?«
+>³33¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B  B
+
+=B
+
+=B{B
+žB(öB (öAøffAðzáAðzáAè\Aà£×AàžRAØžRAÐÌÍAÈáHAÈáHAÀõÃA¹
+=A¹
+=A±
+žA©33A©G®A¡G®A\)Ap€Ap€A
+AA®As\)Ac
+AS®AS®AC×
+A4  A4  A$(öAQìAzáAzá@éG®@É@É@©ë
+@=q@\@U
+ž@Â?¬ÌÍ?¬ÌÍ>žQì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B  B
+=B
+=B
+{B
+
+žB(öB(öB33B =qAøzáAð\Að£×AèžRAàžRAàÌÍAØáHAÐáHAÈõÃAÉ
+=AÁ
+=A¹
+žA¹33A±G®A©G®A©\)A¡p€Ap€A
+AA®A®AÂAs®Ac®AS×
+AT  AD  A4(öA4QìA$záAzáA£×AÌÍ@é@Éë
+@Ê=q@ª\@\@áH@Vff@ff?®{?¯\)>Â\¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+  B
+=B
+=B{B
+žB
+(öB
+(öB33B=qB=qB G®Aø£×AðžRAðžRAèÌÍAàáHAàáHAØõÃAÑ
+=AÉ
+=AÉ
+žAÁ33A¹G®A¹G®A±\)A©p€A©p€A¡
+AA®A®AÂA×
+A×
+As×
+Ad  AT  AT(öADQìA4záA4záA$£×AÌÍAÌÍAõÃ@ê=q@Ê\@Ê\@ªáH@33@33@W
+>@®?°£×?°£×>Ç®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B   B 
+=B
+
+=B{B
+žB(öB(öB
+33B
+=qB=qBG®BQìB \)AøžRAðÌÍAðáHAèáHAàõÃAá
+=AÙ
+=AÑ
+žAÉ33AÉG®AÁG®A¹\)A¹p€A±p€A©
+A©A¡®A®AÂA×
+A×
+Aë
+A  At  Ad(öATQìATzáADzáA4£×A4ÌÍA$ÌÍAõÃA
+žAG®@ê\@ÊáH@Ë33@«33@
+@×
+@XQì@Qì?±ë
+?³33>ÌÌÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B(  B$
+=B 
+=B {B
+
+žB(öB(öB33B=qB
+=qB
+G®BQìB\)B\)B ffAøáHAðáHAðõÃAé
+=Aá
+=Aá
+žAÙ33AÑG®AÉG®AÉ\)AÁp€A¹p€A¹
+A±A©®A©®A¡ÂA×
+A×
+Aë
+A  A  A{AtQìAdzáATzáAT£×ADÌÍA4ÌÍA4õÃA%
+žAG®AG®Ap€@ë33@Ë33@Ë
+@«×
+@(ö@(ö@XõÂ@?³33?Žzá>×
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B,  B(
+=B(
+=B${B 
+žB (öB
+(öB33B=qB=qBG®B
+QìB
+\)B\)BffBp€B p€AøõÃAñ
+=Añ
+=Aé
+žAá33AáG®AÙG®AÑ\)AÉp€AÉp€AÁ
+A¹A¹®A±®A©ÂA©×
+A¡×
+Aë
+A  A  A{A(öA=qAtzáAd£×ATÌÍATÌÍADõÃA5
+žA5G®A%G®Ap€AA@ë
+@Ë×
+@Ì(ö@¬(ö@zá@ÌÍ@Y@=q?µÂ?µÂ>Ü(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B4  B0
+=B,
+=B({B(
+žB$(öB (öB 33B
+=qB=qBG®BQìB\)B
+\)B
+ffBp€Bp€BzáB 
+Aù
+=Añ
+žAñ33AéG®AáG®Aá\)AÙp€AÑp€AÉ
+AÉAÁ®A¹®A¹ÂA±×
+A©×
+A©ë
+A¢  A  A{A(öA=qA=qAQìAtÌÍAdÌÍATõÃAU
+žAEG®A5G®A5p€A%AAÂAë
+@ì(ö@Ì(ö@Ìzá@¬ÌÍ@ÌÍ@
+ž@ZáH@áH?·
+>?žQì>æff¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B8  B4
+=B4
+=B0{B,
+žB((öB((öB$33B =qB =qB
+G®BQìB\)B\)BffB
+p€B
+p€BzáB
+B
+B \Aù33AñG®AñG®Aé\)Aáp€Aáp€AÙ
+AÑAÉ®AÉ®AÁÂA¹×
+A¹×
+A±ë
+Aª  Aª  A¢{A(öA=qA=qAQìAffAffAtõÃAe
+žAUG®AUG®AEp€A5A5A%ÂAë
+A{A{@ìzá@ÌÌÍ@ÌÌÍ@­
+ž@p€@p€@[
+@
+(ö?¹?¹>ë
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B<  B<
+=B8
+=B4{B4
+žB0(öB,(öB(33B(=qB$=qB G®B QìB
+\)B\)BffBp€Bp€B
+záB
+
+B
+B\BB £×AùG®Añ\)Añp€Aép€Aá
+AáAÙ®AÑ®AÉÂAÉ×
+AÁ×
+A¹ë
+Aº  A²  Aª{Aª(öA¢=qA=qAQìAffAffAzáA\AuG®AeG®AUp€AUAEA5ÂA5ë
+A&{A{A=qAff@ìÌÍ@Í
+ž@Íp€@­p€@Â@{@\ÌÍ@
+ÌÍ?ºáH?Œ(ö>ð£×¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BD  B@
+=B<
+=B<{B8
+žB4(öB4(öB033B,=qB(=qB(G®B$QìB \)B \)B
+ffBp€Bp€BzáB
+B
+
+B
+\BB£×B£×B ®Aùp€Añp€Añ
+AéAá®Aá®AÙÂAÑ×
+AÉ×
+AÉë
+AÂ  Aº  Aº{A²(öAª=qAª=qA¢QìAffAffAzáA\A£×A£×Aup€AeAUAUÂAEë
+A6{A6{A&=qAffAffA\@íp€@Íp€@ÍÂ@®{@ff@ff@]p€@
+{?Œ(ö?œp€>úáH¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BH  BH
+=BD
+=B@{B<
+žB<(öB8(öB433B4=qB0=qB,G®B(QìB(\)B$\)B ffB p€B
+p€BzáB
+B
+B\B
+B
+£×B£×B®BžRB žRAù
+AñAñ®Aé®AáÂAá×
+AÙ×
+AÑë
+AÊ  AÊ  AÂ{Aº(öAº=qA²=qAªQìAªffA¢ffAzáA\A£×A£×AžRAÌÍAuAeÂAUë
+AV{AF{A6=qA6ffA&ffA\AžRAžR@íÂ@Î{@Îff@®ff@žR@
+=@^{@
+žR?ŸžR?À  ?   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BP  BL
+=BH
+=BH{BD
+žB@(öB<(öB<33B8=qB4=qB4G®B0QìB,\)B(\)B(ffB$p€B p€B záB
+
+B
+B\BB£×B
+£×B
+®BžRBžRBÂB ÌÍAù®Añ®AñÂAé×
+Aá×
+Aáë
+AÚ  AÒ  AÊ{AÊ(öAÂ=qAº=qAºQìA²ffAªffAªzáA¢\A£×A£×AžRAÌÍAÌÍAáHAuë
+Af{AV{AV=qAFffA6ffA6\A&žRAžRAáHA
+=@îff@Îff@ÎžR@¯
+=@
+=@\)@_\)@   ?À  ?ÁG®?
+ž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BT  BP
+=BP
+=BL{BH
+žBH(öBD(öB@33B<=qB<=qB8G®B4QìB4\)B0\)B,ffB(p€B(p€B$záB 
+B 
+B
+\BB£×B£×B®B
+žRB
+žRBÂBÌÍB×
+B ×
+AùÂAñ×
+Añ×
+Aéë
+Aâ  Aâ  AÚ{AÒ(öAÊ=qAÊ=qAÂQìAºffAºffA²záAª\Aª£×A¢£×AžRAÌÍAÌÍAáHAõÃA
+=Av{Af=qAVffAVffAF\A6žRA6žRA&áHA
+=A33A33@îžR@Ï
+=@Ï
+=@¯\)@®@  @`  @ £×?Â\?Â\?®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BX  BX
+=BT
+=BP{BP
+žBL(öBH(öBH33BD=qB@=qB<G®B<QìB8\)B4\)B4ffB0p€B,p€B(záB(
+B$
+B \B B
+£×B£×B®BžRBžRB
+ÂB
+ÌÍB×
+B×
+BáHB ë
+Aù×
+Añë
+Aò  Aê  Aâ{Aâ(öAÚ=qAÒ=qAÊQìAÊffAÂffAºzáAº\A²£×Aª£×AªžRA¢ÌÍAÌÍAáHAõÃA
+=A
+=A
+žAvffAfffAV\AVžRAFžRA6áHA7
+=A'33A33A\)A
+@ï
+=@Ï\)@Ï®@°  @  @Qì@aG®@!G®?Ã×
+?Å
+ž?
+=q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B`  B\
+=BX
+=BX{BT
+žBP(öBP(öBL33BH=qBH=qBDG®B@QìB<\)B<\)B8ffB4p€B4p€B0záB,
+B(
+B(\B$B £×B £×B
+®BžRBžRBÂBÌÍB
+×
+B
+×
+BáHBë
+Bë
+B õÃAú  Aò  Aò{Aê(öAâ=qAâ=qAÚQìAÒffAÊffAÊzáAÂ\Aº£×Aº£×A²žRAªÌÍAªÌÍA¢áHAõÃA
+=A
+=A
+žA33A33Av\AfžRAVžRAVáHAG
+=A733A733A'\)A
+A
+A®@ï®@Ð  @Ð  @°Qì@£×@£×@aë
+@"\?Å
+ž?Æff?\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bd  Bd
+=B`
+=B\{BX
+žBX(öBT(öBP33BP=qBL=qBHG®BHQìBD\)B@\)B<ffB<p€B8p€B4záB4
+B0
+B,\B(B(£×B$£×B ®B žRB
+žRBÂBÌÍB×
+B×
+B
+áHB
+ë
+Bë
+BõÃB  B  Aú{Aò(öAò=qAê=qAâQìAâffAÚffAÒzáAÊ\AÊ£×AÂ£×AºžRAºÌÍA²ÌÍAªáHAªõÃA£
+=A
+=A
+žA33A33AG®A\)AvžRAfáHAW
+=AW33AG33A7\)A7
+A'
+A®A×
+A  @ð  @ÐQì@Ð£×@°£×@õÂ@G®@b\@#33?Ç®?ÈõÂ?ë
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bl  Bh
+=Bd
+=Bd{B`
+žB\(öBX(öBX33BT=qBP=qBPG®BLQìBH\)BH\)BDffB@p€B<p€B<záB8
+B4
+B4\B0B,£×B(£×B(®B$žRB žRB ÂB
+ÌÍB×
+B×
+BáHBë
+B
+ë
+B
+õÃB	  B  B
+=B{Aú=qAò=qAòQìAêffAâffAâzáAÚ\AÒ£×AÊ£×AÊžRAÂÌÍAºÌÍAºáHA²õÃA«
+=A«
+=A£
+žA33A33AG®A\)A\)Ap€Aw
+=Ag33AW33AW\)AG
+A7
+A7®A'×
+A  A  A(ö@ð£×@Ð£×@ÐõÂ@±G®@G®@@c×
+@$zá?ÈõÂ?Ê=p?
+=¿  ¿  ¿  ¿  ¿  ¿  Bp  Bl
+=Bl
+=Bh{Bd
+žBd(öB`(öB\33BX=qBX=qBTG®BPQìBP\)BL\)BHffBHp€BDp€B@záB<
+B<
+B8\B4B4£×B0£×B,®B(žRB(žRB$ÂB ÌÍB ×
+B
+×
+BáHBë
+Bë
+BõÃB
+  B
+  B	
+=B{B
+žB
+žAúQìAòffAòffAêzáAâ\Aâ£×AÚ£×AÒžRAÊÌÍAÊÌÍAÂáHAºõÃA»
+=A³
+=A«
+žA«33A£33AG®A\)A\)Ap€A
+AAw33Ag\)AW
+AW
+AG®A7×
+A8  A(  A(öAQìAQì@ðõÂ@ÑG®@ÑG®@±@ë
+@=q@dzá@%
+ž?Ë
+
+?Ë
+
+?¿  ¿  ¿  ¿  Bx  Bt
+=Bp
+=Bl{Bl
+žBh(öBd(öBd33B`=qB\=qBXG®BXQìBT\)BP\)BPffBLp€BHp€BHzáBD
+B@
+B<\B<B8£×B4£×B4®B0žRB,žRB(ÂB(ÌÍB$×
+B ×
+B áHB
+ë
+Bë
+BõÃB  B  B
+=B
+{B	
+žB
+žB(öB33AúffAòzáAò\Aê£×Aâ£×AâžRAÚÌÍAÒÌÍAÊáHAÊõÃAÃ
+=A»
+=A»
+žA³33A«33A«G®A£\)A\)Ap€A
+AAA®Aw
+Ag
+AW®AW×
+AH  A8  A8(öA(QìAQìAzáA£×@ñG®@Ñ@Ñë
+@²=q@=q@\@eÂ@%Â?ÌÌÍ?Î{?
+žR¿  ¿  B|  Bx
+=Bx
+=Bt{Bp
+žBl(öBl(öBh33Bd=qBd=qB`G®B\QìBX\)BX\)BTffBPp€BPp€BLzáBH
+BH
+BD\B@B<£×B<£×B8®B4žRB4žRB0ÂB,ÌÍB(×
+B(×
+B$áHB ë
+B ë
+B
+õÃB  B  B
+=B{B
+
+žB
+
+žB	(öB33B33B=qAú\Aò£×Aò£×AêžRAâÌÍAâÌÍAÚáHAÒõÃAË
+=AË
+=AÃ
+žA»33A»33A³G®A«\)A«\)A£p€A
+AAA®AÂAÂAw®Ag×
+AX  AX  AH(öA8QìA8QìA(záA£×A£×AÌÍ@ñë
+@Ò=q@Ò=q@²\@áH@áH@fff@'
+>?Ï\)?Ï\)?!G®¿  ¿  B|
+=Bx{Bx
+žBt(öBp(öBl33Bl=qBh=qBdG®BdQìB`\)B\\)BXffBXp€BTp€BPzáBP
+BL
+BH\BHBD£×B@£×B<®B<žRB8žRB4ÂB4ÌÍB0×
+B,×
+B(áHB(ë
+B$ë
+B õÃB!  B
+  B
+=B{B
+žB
+žB
+(öB
+33B	33B=qBG®BQìAú£×AòžRAòÌÍAêÌÍAâáHAâõÃAÛ
+=AÓ
+=AË
+žAË33AÃ33A»G®A»\)A³\)A«p€A«
+A£AA®AÂAÂA×
+Aë
+Ax  Ah  AX(öAXQìAHQìA8záA8£×A(£×AÌÍAõÃA	
+ž@ò=q@Ò\@ÒáH@²áH@33@
+@g®@'®?Ð£×¿  ¿  ¿  ¿  B|
+žBx(öBx(öBt33Bp=qBl=qBlG®BhQìBd\)Bd\)B`ffB\p€BXp€BXzáBT
+BP
+BP\BLBH£×BH£×BD®B@žRB<žRB<ÂB8ÌÍB4×
+B4×
+B0áHB,ë
+B(ë
+B(õÃB%  B!  B!
+=B
+{B
+žB
+žB(öB33B
+33B
+=qB	G®BQìBQìB\)AúÌÍAòÌÍAòáHAêõÃAã
+=Aã
+=AÛ
+žAÓ33AË33AËG®AÃ\)A»\)A»p€A³
+A«A«A£®AÂAÂA×
+Aë
+A  A  Ax(öAhQìAXQìAXzáAH£×A8£×A8ÌÍA(õÃA
+žA
+žA	G®@òáH@ÒáH@Ó33@³
+@×
+@×
+@hQì¿  ¿  ¿  ¿  ¿  ¿  B|(öBx33Bx=qBt=qBpG®BlQìBl\)Bh\)BdffBdp€B`p€B\záBX
+BX
+BT\BPBP£×BL£×BH®BHžRBDžRB@ÂB<ÌÍB<×
+B8×
+B4áHB4ë
+B0ë
+B,õÃB)  B)  B%
+=B!{B!
+žB
+
+žB(öB33B33B=qB
+G®B
+QìB	QìB\)BffBffAúáHAòõÃAó
+=Aë
+=Aã
+žAã33AÛ33AÓG®AË\)AË\)AÃp€A»
+A»A³A«®A«ÂA£ÂA×
+Aë
+A  A  A{A(öAxQìAhzáAX£×AX£×AHÌÍA8õÃA9
+žA)
+žAG®Ap€A	p€@ó33@Ó
+@Ó×
+@³×
+@(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|=qBx=qBxG®BtQìBp\)Bl\)BlffBhp€Bdp€BdzáB`
+B\
+BX\BXBT£×BP£×BP®BLžRBHžRBHÂBDÌÍB@×
+B<×
+B<áHB8ë
+B4ë
+B4õÃB1  B-  B)
+=B){B%
+žB!
+žB!(öB
+33B33B=qBG®BQìB
+QìB
+\)B	ffBffBp€BzáAû
+=Aó
+=Aó
+žAë33Aã33AãG®AÛ\)AÓ\)AËp€AË
+AÃA»A»®A³ÂA«ÂA«×
+A£ë
+A  A  A{A(öA(öA=qAx£×Ah£×AXÌÍAXõÃAI
+žA9
+žA9G®A)p€Ap€AA	Â@ó×
+@Ó×
+@Ô(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|G®BxQìBx\)Bt\)BpffBlp€Blp€BhzáBd
+Bd
+B`\B\BX£×BX£×BT®BPžRBPžRBLÂBHÌÍBH×
+BD×
+B@áHB<ë
+B<ë
+B8õÃB5  B5  B1
+=B-{B)
+žB)
+žB%(öB!33B!33B
+=qBG®BQìBQìB\)B
+ffB
+ffB	p€BzáB
+B
+Aû
+žAó33Aó33AëG®Aã\)Aã\)AÛp€AÓ
+AËAËAÃ®A»ÂA»ÂA³×
+A«ë
+A¬  A€  A{A(öA(öA=qAQìAQìAxÌÍAhõÃAY
+žAY
+žAIG®A9p€A9p€A)AÂAë
+A	ë
+@ô(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|\)Bx\)BxffBtp€Bpp€BlzáBl
+Bh
+Bd\BdB`£×B\£×BX®BXžRBTžRBPÂBPÌÍBL×
+BH×
+BHáHBDë
+B@ë
+B<õÃB=  B9  B5
+=B5{B1
+žB-
+žB)(öB)33B%33B!=qB!G®B
+QìBQìB\)BffBffB
+p€B
+záB	
+B
+B\BAû33AóG®Aó\)Aë\)Aãp€Aã
+AÛAÓAË®AËÂAÃÂA»×
+A»ë
+AŽ  A¬  A¬{A€(öA(öA=qAQìAQìAffAzáAy
+žAi
+žAYG®AYp€AIp€A9A9ÂA)ë
+Aë
+A{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ffBxp€Bxp€BtzáBp
+Bl
+Bl\BhBd£×Bd£×B`®B\žRBXžRBXÂBTÌÍBP×
+BP×
+BLáHBHë
+BHë
+BDõÃBA  B=  B=
+=B9{B5
+žB5
+žB1(öB-33B)33B)=qB%G®B!QìB!QìB
+\)BffBffBp€BzáB
+
+B
+
+B	\BBB£×Aû\)Aó\)Aóp€Aë
+AãAãAÛ®AÓÂAËÂAË×
+AÃë
+AŒ  AŒ  AŽ{A¬(öA¬(öA€=qAQìAQìAffAzáA\A\AyG®Aip€AYp€AYAIÂA9ë
+A9ë
+A*{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|p€BxzáBx
+Bt
+Bp\BlBl£×Bh£×Bd®BdžRB`žRB\ÂBXÌÍBX×
+BT×
+BPáHBPë
+BLë
+BHõÃBI  BE  BA
+=B={B=
+žB9
+žB5(öB533B133B-=qB)G®B)QìB%QìB!\)B!ffB
+ffBp€BzáB
+B
+B
+\B
+B	B£×B®B®Aûp€Aó
+AóAëAã®AãÂAÛÂAÓ×
+AËë
+AÌ  AÄ  AŒ{AŒ(öAŽ(öA¬=qA¬QìA€QìAffAzáA\A\A£×AžRAyp€AiAYÂAYë
+AIë
+A:{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|
+Bx
+Bx\BtBp£×Bl£×Bl®BhžRBdžRBdÂB`ÌÍB\×
+BX×
+BXáHBTë
+BPë
+BPõÃBM  BI  BI
+=BE{BA
+žB=
+žB=(öB933B533B5=qB1G®B-QìB)QìB)\)B%ffB!ffB!p€B
+záB
+B
+B\BB
+B
+£×B	®B®BžRBÂAûAóAó®AëÂAãÂAã×
+AÛë
+AÔ  AÌ  AÌ{AÄ(öAŒ(öAŒ=qAŽQìA¬QìA¬ffA€záA\A\A£×AžRAžRAÌÍAyÂAië
+AYë
+AZ{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|\BxBx£×Bt£×Bp®BlžRBlžRBhÂBdÌÍBd×
+B`×
+B\áHBXë
+BXë
+BTõÃBQ  BQ  BM
+=BI{BI
+žBE
+žBA(öB=33B=33B9=qB5G®B5QìB1QìB-\)B)ffB)ffB%p€B!záB!
+B
+
+B\BBB£×B
+®B
+®B	žRBÂBÌÍBÌÍAû®AóÂAóÂAë×
+Aãë
+Aä  AÜ  AÔ{AÌ(öAÌ(öAÄ=qAŒQìAŒQìAŽffA¬záA¬\A€\A£×AžRAžRAÌÍAáHAõÃAyë
+Aj{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|£×Bx£×Bx®BtžRBpžRBlÂBlÌÍBh×
+Bd×
+BdáHB`ë
+B\ë
+BXõÃBY  BU  BQ
+=BQ{BM
+žBI
+žBI(öBE33BA33B==qB=G®B9QìB5QìB5\)B1ffB-ffB)p€B)záB%
+B!
+B!\B
+BB£×B®B®B
+žRB
+ÂB	ÌÍBÌÍB×
+BáHAûÂAó×
+Aóë
+Aì  Aä  Aä{AÜ(öAÔ(öAÌ=qAÌQìAÄQìAŒffAŒzáAŽ\A¬\A¬£×A€žRAžRAÌÍAáHAõÃAõÃA
+
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|®BxžRBxžRBtÂBpÌÍBl×
+Bl×
+BháHBdë
+Bdë
+B`õÃB]  BY  BY
+=BU{BQ
+žBQ
+žBM(öBI33BI33BE=qBAG®B=QìB=QìB9\)B5ffB5ffB1p€B-záB)
+B)
+B%\B!B!B
+£×B®B®BžRBÂB
+ÌÍB
+ÌÍB	×
+BáHBáHBë
+Aûë
+Aô  Aô  Aì{Aä(öAä(öAÜ=qAÔQìAÌQìAÌffAÄzáAŒ\AŒ\AŽ£×A¬žRA¬žRA€ÌÍAáHAõÃAõÃA
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|žRBxÂBxÌÍBt×
+Bp×
+BláHBlë
+Bhë
+BdõÃBe  Ba  B]
+=BY{BY
+žBU
+žBQ(öBQ33BM33BI=qBIG®BEQìBAQìB=\)B=ffB9ffB5p€B5záB1
+B-
+B)\B)B%B!£×B!®B
+®BžRBÂBÌÍBÌÍB
+×
+B
+áHB	áHBë
+BõÃB  Aü  Aô{Aô(öAì(öAä=qAäQìAÜQìAÔffAÌzáAÌ\AÄ\AŒ£×AŒžRAŽžRA¬ÌÍA¬áHA€õÃAõÃA
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ÌÍBx×
+Bx×
+BtáHBpë
+Blë
+BlõÃBi  Be  Be
+=Ba{B]
+žBY
+žBY(öBU33BQ33BQ=qBMG®BIQìBIQìBE\)BAffB=ffB=p€B9záB5
+B5
+B1\B-B)B)£×B%®B!®B!žRB
+ÂBÌÍBÌÍB×
+BáHB
+áHB
+ë
+B	õÃB  B  B
+=Aü(öAô(öAô=qAìQìAäQìAäffAÜzáAÔ\AÌ\AÌ£×AÄžRAŒžRAŒÌÍAŽáHA¬õÃA¬õÃA¥
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|×
+BxáHBxë
+Btë
+BpõÃBm  Bm  Bi
+=Be{Be
+žBa
+žB](öBY33BY33BU=qBQG®BQQìBMQìBI\)BIffBEffBAp€B=záB=
+B9
+B5\B5B1B-£×B)®B)®B%žRB!ÂB!ÌÍB
+ÌÍB×
+BáHBáHBë
+B
+õÃB  B
+  B
+=B{B{Aü=qAôQìAôQìAìffAäzáAä\AÜ\AÔ£×AÌžRAÌžRAÄÌÍAŒáHAŒõÃAŽõÃA­
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ë
+Bxë
+BxõÃBu  Bq  Bm
+=Bm{Bi
+žBe
+žBe(öBa33B]33BY=qBYG®BUQìBQQìBQ\)BMffBIffBIp€BEzáBA
+B=
+B=\B9B5B5£×B1®B-®B)žRB)ÂB%ÌÍB!ÌÍB!×
+B
+áHBáHBë
+BõÃB  B  B
+=B
+{B{B
+žB(öAüQìAôffAôzáAì\Aä\Aä£×AÜžRAÔžRAÌÌÍAÌáHAÄõÃAŒõÃAœ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|õÃBy  By  Bu
+=Bq{Bm
+žBm
+žBi(öBe33Be33Ba=qB]G®BYQìBYQìBU\)BQffBQffBMp€BIzáBI
+BE
+BA\B=B=B9£×B5®B5®B1žRB-ÂB)ÌÍB)ÌÍB%×
+B!áHB!áHB
+ë
+BõÃB  B  B
+=B{B{B
+
+žB(öB(öB33AüzáAô\Aô\Aì£×AäžRAäžRAÜÌÍAÔáHAÌõÃAÌõÃAÅ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}  By
+=By{Bu
+žBq
+žBm(öBm33Bi33Be=qBeG®BaQìB]QìBY\)BYffBUffBQp€BQzáBM
+BI
+BI\BEBAB=£×B=®B9®B5žRB5ÂB1ÌÍB-ÌÍB)×
+B)áHB%áHB!ë
+B!õÃB
+  B  B
+=B{B{B
+žB(öB
+(öB33B=qBG®Aü\Aô£×AôžRAìžRAäÌÍAäáHAÜõÃAÔõÃAÍ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}{By
+žBy
+žBu(öBq33Bm33Bm=qBiG®BeQìBeQìBa\)B]ffBYffBYp€BUzáBQ
+BQ
+BM\BIBIBE£×BA®B=®B=žRB9ÂB5ÌÍB5ÌÍB1×
+B-áHB)áHB)ë
+B%õÃB"  B"  B
+
+=B{B{B
+žB(öB(öB33B
+=qBG®BG®BQìAüžRAôžRAôÌÍAìáHAäõÃAäõÃAÝ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}
+žBy(öBy33Bu33Bq=qBmG®BmQìBiQìBe\)BeffBaffB]p€BYzáBY
+BU
+BQ\BQBMBI£×BI®BE®BAžRB=ÂB=ÌÍB9ÌÍB5×
+B5áHB1áHB-ë
+B)õÃB*  B&  B"
+=B"{B
+{B
+žB(öB(öB33B=qBG®B
+G®BQìB\)B\)AüÌÍAôáHAôõÃAìõÃAå
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}33By33By=qBuG®BqQìBmQìBm\)BiffBeffBep€BazáB]
+BY
+BY\BUBQBQ£×BM®BI®BIžRBEÂBAÌÍB=ÌÍB=×
+B9áHB5áHB5ë
+B1õÃB.  B*  B*
+=B&{B"{B"
+žB
+(öB(öB33B=qBG®BG®BQìB
+\)B\)BffBp€AüõÃAôõÃAõ
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}=qByG®ByQìBuQìBq\)BmffBmffBip€BezáBe
+Ba
+B]\BYBYBU£×BQ®BQ®BMžRBIÂBIÌÍBEÌÍBA×
+B=áHB=áHB9ë
+B5õÃB6  B2  B.
+=B*{B*{B&
+žB"(öB"(öB
+33B=qBG®BG®BQìB\)B\)B
+ffBp€BzáBzáAý
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}QìByQìBy\)BuffBqffBmp€BmzáBi
+Be
+Be\BaB]BY£×BY®BU®BQžRBQÂBMÌÍBIÌÍBI×
+BEáHBAáHB=ë
+B=õÃB:  B6  B6
+=B2{B.{B*
+žB*(öB&(öB"33B"=qB
+G®BG®BQìB\)B\)BffBp€B
+záBzáB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}\)ByffByffBup€BqzáBm
+Bm
+Bi\BeBeBa£×B]®BY®BYžRBUÂBQÌÍBQÌÍBM×
+BIáHBIáHBEë
+BAõÃB>  B>  B:
+=B6{B6{B2
+žB.(öB*(öB*33B&=qB"G®B"G®B
+QìB\)B\)BffBp€BzáBzáB
+
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ffByp€ByzáBu
+Bq
+Bm\BmBiBe£×Be®Ba®B]žRBYÂBYÌÍBUÌÍBQ×
+BQáHBMáHBIë
+BIõÃBF  BB  B>
+=B>{B:{B6
+žB6(öB2(öB.33B*=qB*G®B&G®B"QìB"\)B
+\)BffBp€BzáBzáB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}záBy
+By
+Bu\BqBmBm£×Bi®Be®BežRBaÂB]ÌÍBYÌÍBY×
+BUáHBQáHBQë
+BMõÃBJ  BJ  BF
+=BB{B>{B>
+žB:(öB6(öB633B2=qB.G®B*G®B*QìB&\)B"\)B"ffB
+p€BzáBzáB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}
+By\ByBuBq£×Bm®Bm®BižRBeÂBeÌÍBaÌÍB]×
+BYáHBYáHBUë
+BQõÃBR  BN  BJ
+=BJ{BF{BB
+žB>(öB>(öB:33B6=qB6G®B2G®B.QìB*\)B*\)B&ffB"p€B"záB
+záB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ByBy£×Bu®Bq®BmžRBmÂBiÌÍBeÌÍBe×
+BaáHB]áHBYë
+BYõÃBV  BR  BR
+=BN{BJ{BJ
+žBF(öBB(öB>33B>=qB:G®B6G®B6QìB2\)B.\)B*ffB*p€B&záB"záB"
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}£×By®By®BužRBqÂBmÌÍBmÌÍBi×
+BeáHBeáHBaë
+B]õÃBZ  BZ  BV
+=BR{BR{BN
+žBJ(öBJ(öBF33BB=qB>G®B>G®B:QìB6\)B6\)B2ffB.p€B*záB*záB&
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}®ByžRByÂBuÌÍBqÌÍBm×
+BmáHBiáHBeë
+BeõÃBb  B^  BZ
+=BZ{BV{BR
+žBR(öBN(öBJ33BJ=qBFG®BBG®B>QìB>\)B:\)B6ffB6p€B2záB.záB*
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ÂByÌÍByÌÍBu×
+BqáHBmáHBmë
+BiõÃBf  Bf  Bb
+=B^{BZ{BZ
+žBV(öBR(öBR33BN=qBJG®BJG®BFQìBB\)B>\)B>ffB:p€B6záB6záB2
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ÌÍBy×
+ByáHBuáHBqë
+BmõÃBn  Bj  Bf
+=Bf{Bb{B^
+žBZ(öBZ(öBV33BR=qBRG®BNG®BJQìBJ\)BF\)BBffB>p€B>záB:záB6
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}áHByáHByë
+BuõÃBr  Bn  Bn
+=Bj{Bf{Bf
+žBb(öB^(öBZ33BZ=qBVG®BRG®BRQìBN\)BJ\)BJffBFp€BBzáB>záB>
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ë
+ByõÃBz  Bv  Br
+=Bn{Bn{Bj
+žBf(öBf(öBb33B^=qBZG®BZG®BVQìBR\)BR\)BNffBJp€BJzáBFzáBB
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~  Bz  Bz
+=Bv{Br{Bn
+žBn(öBj(öBf33Bf=qBbG®B^G®BZQìBZ\)BV\)BRffBRp€BNzáBJzáBJ
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~
+=Bz{Bz{Bv
+žBr(öBn(öBn33Bj=qBfG®BfG®BbQìB^\)BZ\)BZffBVp€BRzáBRzáBN
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~{Bz
+žBz(öBv(öBr33Bn=qBnG®BjG®BfQìBf\)Bb\)B^ffBZp€BZzáBVzáBR
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~(öBz(öBz33Bv=qBrG®BnG®BnQìBj\)Bf\)BfffBbp€B^záBZzáBZ
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~33Bz=qBzG®BvG®BrQìBn\)Bn\)BjffBfp€BfzáBbzáB^
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~G®BzG®BzQìBv\)Br\)BnffBnp€BjzáBfzáBf
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~QìBz\)Bz\)BvffBrp€BnzáBnzáBj
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~\)BzffBzp€BvzáBrzáBn
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~p€BzzáBzzáBv
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~záBz
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             B|  Bx  Bt  Bp  Bl  Bh  Bd  B`  B\  BX  BT  BP  BL  BH  BD  B@  B<  B8  B4  B0  B,  B(  B$  B   B
+  B  B  B  B
+  B  B  B   Aø  Að  Aè  Aà  AØ  AÐ  AÈ  AÀ  Až  A°  Aš  A   A  A  A  A  Ap  A`  AP  A@  A0  A   A  A   @à  @À  @   @  @@  @   ?      B|
+=Bx
+=Bt
+=Bp
+=Bl
+=Bh
+=Bd
+=B`
+=B\
+=BX
+=BT
+=BP
+=BL
+=BH
+=BD
+=B@
+=B<
+=B8
+=B4
+=B0
+=B,
+=B(
+=B$
+=B 
+=B
+
+=B
+=B
+=B
+=B
+
+=B
+=B
+=B 
+=Aø{Að{Aè{Aà{AØ{AÐ{AÈ{AÀ{Až{A°{Aš{A {A{A{A{A{Ap(öA`(öAP(öA@(öA0(öA (öA(öA (ö@àQì@ÀQì@ Qì@Qì@@£×@ £×?G®<#×
+B|{Bx{Bt{Bp{Bl{Bh{Bd{B`{B\{BX{BT{BP{BL{BH{BD{B@{B<{B8{B4{B0{B,{B({B${B {B
+{B{B{B{B
+{B{B{B {Aø(öAð(öAè(öAà(öAØ(öAÐ(öAÈ(öAÀ(öAž(öA°(öAš(öA (öA(öA(öA(öA(öApQìA`QìAPQìA@QìA0QìA QìAQìA Qì@à£×@À£×@ £×@£×@AG®@G®?\<£×
+B|
+žBx
+žBt
+žBp
+žBl
+žBh
+žBd
+žB`
+žB\
+žBX
+žBT
+žBP
+žBL
+žBH
+žBD
+žB@
+žB<
+žB8
+žB4
+žB0
+žB,
+žB(
+žB$
+žB 
+žB
+
+žB
+žB
+žB
+žB
+
+žB
+žB
+žB 
+žAø=qAð=qAè=qAà=qAØ=qAÐ=qAÈ=qAÀ=qAž=qA°=qAš=qA =qA=qA=qA=qA=qApzáA`záAPzáA@záA0záA záAzáA zá@àõÃ@ÀõÃ@ õÃ@õÃ@Aë
+@ë
+?×
+<õÂB|(öBx(öBt(öBp(öBl(öBh(öBd(öB`(öB\(öBX(öBT(öBP(öBL(öBH(öBD(öB@(öB<(öB8(öB4(öB0(öB,(öB((öB$(öB (öB
+(öB(öB(öB(öB
+(öB(öB(öB (öAøQìAðQìAèQìAàQìAØQìAÐQìAÈQìAÀQìAžQìA°QìAšQìA QìAQìAQìAQìAQìAp£×A`£×AP£×A@£×A0£×A £×A£×A £×@áG®@ÁG®@¡G®@G®@B\@\?
+
+ž=#×
+B|33Bx33Bt33Bp33Bl33Bh33Bd33B`33B\33BX33BT33BP33BL33BH33BD33B@33B<33B833B433B033B,33B(33B$33B 33B
+33B33B33B33B
+33B33B33B 33AøffAðffAèffAàffAØffAÐffAÈffAÀffAžffA°ffAšffA ffAffAffAffAffApÌÍA`ÌÍAPÌÍA@ÌÍA0ÌÍA ÌÍAÌÍA ÌÍ@á@Á@¡@@C33@33?ff=LÌÍB|=qBx=qBt=qBp=qBl=qBh=qBd=qB`=qB\=qBX=qBT=qBP=qBL=qBH=qBD=qB@=qB<=qB8=qB4=qB0=qB,=qB(=qB$=qB =qB
+=qB=qB=qB=qB
+=qB=qB=qB =qAøzáAðzáAèzáAàzáAØzáAÐzáAÈzáAÀzáAžzáA°záAšzáA záAzáAzáAzáAzáApõÃA`õÃAPõÃA@õÃA0õÃA õÃAõÃA õÃ@áë
+@Áë
+@¡ë
+@ë
+@C×
+@×
+?®=uÂB|G®BxG®BtG®BpG®BlG®BhG®BdG®B`G®B\G®BXG®BTG®BPG®BLG®BHG®BDG®B@G®B<G®B8G®B4G®B0G®B,G®B(G®B$G®B G®B
+G®BG®BG®BG®B
+G®BG®BG®B G®Aø\Að\Aè\Aà\AØ\AÐ\AÈ\AÀ\Až\A°\Aš\A \A\A\A\A\Aq
+žAa
+žAQ
+žAA
+žA1
+žA!
+žA
+žA
+ž@â=q@Â=q@¢=q@=q@Dzá@zá?õÃ=\)B|QìBxQìBtQìBpQìBlQìBhQìBdQìB`QìB\QìBXQìBTQìBPQìBLQìBHQìBDQìB@QìB<QìB8QìB4QìB0QìB,QìB(QìB$QìB QìB
+QìBQìBQìBQìB
+QìBQìBQìB QìAø£×Að£×Aè£×Aà£×AØ£×AÐ£×AÈ£×AÀ£×Až£×A°£×Aš£×A £×A£×A£×A£×A£×AqG®AaG®AQG®AAG®A1G®A!G®AG®AG®@â\@Â\@¢\@\@E
+ž@
+ž?=q=£×
+B|\)Bx\)Bt\)Bp\)Bl\)Bh\)Bd\)B`\)B\\)BX\)BT\)BP\)BL\)BH\)BD\)B@\)B<\)B8\)B4\)B0\)B,\)B(\)B$\)B \)B
+\)B\)B\)B\)B
+\)B\)B\)B \)AøžRAðžRAèžRAàžRAØžRAÐžRAÈžRAÀžRAžžRA°žRAšžRA žRAžRAžRAžRAžRAqp€Aap€AQp€AAp€A1p€A!p€Ap€Ap€@âáH@ÂáH@¢áH@áH@EÂ@Â?
+=žQìB|ffBxffBtffBpffBlffBhffBdffB`ffB\ffBXffBTffBPffBLffBHffBDffB@ffB<ffB8ffB4ffB0ffB,ffB(ffB$ffB ffB
+ffBffBffBffB
+ffBffBffB ffAøÌÍAðÌÍAèÌÍAàÌÍAØÌÍAÐÌÍAÈÌÍAÀÌÍAžÌÍA°ÌÍAšÌÍA ÌÍAÌÍAÌÍAÌÍAÌÍAqAaAQAAA1A!AA@ã33@Ã33@£33@33@Fff@ff?ÌÍ=ÌÌÍB|p€Bxp€Btp€Bpp€Blp€Bhp€Bdp€B`p€B\p€BXp€BTp€BPp€BLp€BHp€BDp€B@p€B<p€B8p€B4p€B0p€B,p€B(p€B$p€B p€B
+p€Bp€Bp€Bp€B
+p€Bp€Bp€B p€AøáHAðáHAèáHAàáHAØáHAÐáHAÈáHAÀáHAžáHA°áHAšáHA áHAáHAáHAáHAáHAqÂAaÂAQÂAAÂA1ÂA!ÂAÂAÂ@ã
+@Ã
+@£
+@
+@G
+=@
+=?{=áG®B|záBxzáBtzáBpzáBlzáBhzáBdzáB`záB\záBXzáBTzáBPzáBLzáBHzáBDzáB@záB<záB8záB4záB0záB,záB(záB$záB záB
+záBzáBzáBzáB
+záBzáBzáB záAøõÃAðõÃAèõÃAàõÃAØõÃAÐõÃAÈõÃAÀõÃAžõÃA°õÃAšõÃA õÃAõÃAõÃAõÃAõÃAqë
+Aaë
+AQë
+AAë
+A1ë
+A!ë
+Aë
+Aë
+@ã×
+@Ã×
+@£×
+@×
+@G®@®?\)=õÂB|
+Bx
+Bt
+Bp
+Bl
+Bh
+Bd
+B`
+B\
+BX
+BT
+BP
+BL
+BH
+BD
+B@
+B<
+B8
+B4
+B0
+B,
+B(
+B$
+B 
+B
+
+B
+B
+B
+B
+
+B
+B
+B 
+Aù
+=Añ
+=Aé
+=Aá
+=AÙ
+=AÑ
+=AÉ
+=AÁ
+=A¹
+=A±
+=A©
+=A¡
+=A
+=A
+=A
+=A
+=Ar{Ab{AR{AB{A2{A"{A{A{@ä(ö@Ä(ö@€(ö@(ö@HQì@Qì?£×>
+žB|\Bx\Bt\Bp\Bl\Bh\Bd\B`\B\\BX\BT\BP\BL\BH\BD\B@\B<\B8\B4\B0\B,\B(\B$\B \B
+\B\B\B\B
+\B\B\B \Aù
+žAñ
+žAé
+žAá
+žAÙ
+žAÑ
+žAÉ
+žAÁ
+žA¹
+žA±
+žA©
+žA¡
+žA
+žA
+žA
+žA
+žAr=qAb=qAR=qAB=qA2=qA"=qA=qA=q@äzá@Äzá@€zá@zá@HõÃ@õÃ?ë
+>\)B|BxBtBpBlBhBdB`B\BXBTBPBLBHBDB@B<B8B4B0B,B(B$B B
+BBBB
+BBB Aù33Añ33Aé33Aá33AÙ33AÑ33AÉ33AÁ33A¹33A±33A©33A¡33A33A33A33A33ArffAbffARffABffA2ffA"ffAffAff@äÌÍ@ÄÌÍ@€ÌÍ@ÌÍ@I@	?33>B|£×Bx£×Bt£×Bp£×Bl£×Bh£×Bd£×B`£×B\£×BX£×BT£×BP£×BL£×BH£×BD£×B@£×B<£×B8£×B4£×B0£×B,£×B(£×B$£×B £×B
+£×B£×B£×B£×B
+£×B£×B£×B £×AùG®AñG®AéG®AáG®AÙG®AÑG®AÉG®AÁG®A¹G®A±G®A©G®A¡G®AG®AG®AG®AG®Ar\Ab\AR\AB\A2\A"\A\A\@å
+ž@Å
+ž@¥
+ž@
+
+ž@J=q@
+=q?zá>#×
+B|®Bx®Bt®Bp®Bl®Bh®Bd®B`®B\®BX®BT®BP®BL®BH®BD®B@®B<®B8®B4®B0®B,®B(®B$®B ®B
+®B®B®B®B
+®B®B®B ®Aù\)Añ\)Aé\)Aá\)AÙ\)AÑ\)AÉ\)AÁ\)A¹\)A±\)A©\)A¡\)A\)A\)A\)A\)AržRAbžRARžRABžRA2žRA"žRAžRAžR@åp€@Åp€@¥p€@
+p€@JáH@
+áH?Â>.{B|žRBxžRBtžRBpžRBlžRBhžRBdžRB`žRB\žRBXžRBTžRBPžRBLžRBHžRBDžRB@žRB<žRB8žRB4žRB0žRB,žRB(žRB$žRB žRB
+žRBžRBžRBžRB
+žRBžRBžRB žRAùp€Añp€Aép€Aáp€AÙp€AÑp€AÉp€AÁp€A¹p€A±p€A©p€A¡p€Ap€Ap€Ap€Ap€AráHAbáHARáHABáHA2áHA"áHAáHAáH@åÂ@ÅÂ@¥Â@
+Â@K
+@
+
+?
+>>8QìB|ÂBxÂBtÂBpÂBlÂBhÂBdÂB`ÂB\ÂBXÂBTÂBPÂBLÂBHÂBDÂB@ÂB<ÂB8ÂB4ÂB0ÂB,ÂB(ÂB$ÂB ÂB
+ÂBÂBÂBÂB
+ÂBÂBÂB ÂAù
+Añ
+Aé
+Aá
+AÙ
+AÑ
+AÉ
+AÁ
+A¹
+A±
+A©
+A¡
+A
+A
+A
+A
+As
+=Ac
+=AS
+=AC
+=A3
+=A#
+=A
+=A
+=@æ{@Æ{@Š{@{@L(ö@
+(ö?Qì>B\B|ÌÍBxÌÍBtÌÍBpÌÍBlÌÍBhÌÍBdÌÍB`ÌÍB\ÌÍBXÌÍBTÌÍBPÌÍBLÌÍBHÌÍBDÌÍB@ÌÍB<ÌÍB8ÌÍB4ÌÍB0ÌÍB,ÌÍB(ÌÍB$ÌÍB ÌÍB
+ÌÍBÌÍBÌÍBÌÍB
+ÌÍBÌÍBÌÍB ÌÍAùAñAéAáAÙAÑAÉAÁA¹A±A©A¡AAAAAs33Ac33AS33AC33A333A#33A33A33@æff@Æff@Šff@ff@LÌÍ@
+ÌÍ?>LÌÍB|×
+Bx×
+Bt×
+Bp×
+Bl×
+Bh×
+Bd×
+B`×
+B\×
+BX×
+BT×
+BP×
+BL×
+BH×
+BD×
+B@×
+B<×
+B8×
+B4×
+B0×
+B,×
+B(×
+B$×
+B ×
+B
+×
+B×
+B×
+B×
+B
+×
+B×
+B×
+B ×
+Aù®Añ®Aé®Aá®AÙ®AÑ®AÉ®AÁ®A¹®A±®A©®A¡®A®A®A®A®As\)Ac\)AS\)AC\)A3\)A#\)A\)A\)@æžR@ÆžR@ŠžR@žR@Mp€@
+p€?áH>W
+=B|áHBxáHBtáHBpáHBláHBháHBdáHB`áHB\áHBXáHBTáHBPáHBLáHBHáHBDáHB@áHB<áHB8áHB4áHB0áHB,áHB(áHB$áHB áHB
+áHBáHBáHBáHB
+áHBáHBáHB áHAùÂAñÂAéÂAáÂAÙÂAÑÂAÉÂAÁÂA¹ÂA±ÂA©ÂA¡ÂAÂAÂAÂAÂAs
+Ac
+AS
+AC
+A3
+A#
+A
+A
+@ç
+=@Ç
+=@§
+=@
+=@N{@{?(ö>aG®B|ë
+Bxë
+Btë
+Bpë
+Blë
+Bhë
+Bdë
+B`ë
+B\ë
+BXë
+BTë
+BPë
+BLë
+BHë
+BDë
+B@ë
+B<ë
+B8ë
+B4ë
+B0ë
+B,ë
+B(ë
+B$ë
+B ë
+B
+ë
+Bë
+Bë
+Bë
+B
+ë
+Bë
+Bë
+B ë
+Aù×
+Añ×
+Aé×
+Aá×
+AÙ×
+AÑ×
+AÉ×
+AÁ×
+A¹×
+A±×
+A©×
+A¡×
+A×
+A×
+A×
+A×
+As®Ac®AS®AC®A3®A#®A®A®@ç\)@Ç\)@§\)@\)@NžR@žR?p€>k
+B|õÃBxõÃBtõÃBpõÃBlõÃBhõÃBdõÃB`õÃB\õÃBXõÃBTõÃBPõÃBLõÃBHõÃBDõÃB@õÃB<õÃB8õÃB4õÃB0õÃB,õÃB(õÃB$õÃB õÃB
+õÃBõÃBõÃBõÃB
+õÃBõÃBõÃB õÃAùë
+Añë
+Aéë
+Aáë
+AÙë
+AÑë
+AÉë
+AÁë
+A¹ë
+A±ë
+A©ë
+A¡ë
+Aë
+Aë
+Aë
+Aë
+As×
+Ac×
+AS×
+AC×
+A3×
+A#×
+A×
+A×
+@ç®@Ç®@§®@®@O\)@\)?žR>uÂB}  By  Bu  Bq  Bm  Bi  Be  Ba  B]  BY  BU  BQ  BM  BI  BE  BA  B=  B9  B5  B1  B-  B)  B%  B!  B
+  B  B  B  B
+  B	  B  B  Aú  Aò  Aê  Aâ  AÚ  AÒ  AÊ  AÂ  Aº  A²  Aª  A¢  A  A  A  A  At  Ad  AT  AD  A4  A$  A  A  @è  @È  @š  @  @P  @  ?   >  B}
+=By
+=Bu
+=Bq
+=Bm
+=Bi
+=Be
+=Ba
+=B]
+=BY
+=BU
+=BQ
+=BM
+=BI
+=BE
+=BA
+=B=
+=B9
+=B5
+=B1
+=B-
+=B)
+=B%
+=B!
+=B
+
+=B
+=B
+=B
+=B
+=B	
+=B
+=B
+=Aú{Aò{Aê{Aâ{AÚ{AÒ{AÊ{AÂ{Aº{A²{Aª{A¢{A{A{A{A{At(öAd(öAT(öAD(öA4(öA$(öA(öA(ö@èQì@ÈQì@šQì@Qì@P£×@£×?¡G®>
+
+žB}{By{Bu{Bq{Bm{Bi{Be{Ba{B]{BY{BU{BQ{BM{BI{BE{BA{B={B9{B5{B1{B-{B){B%{B!{B
+{B{B{B{B
+{B	{B{B{Aú(öAò(öAê(öAâ(öAÚ(öAÒ(öAÊ(öAÂ(öAº(öA²(öAª(öA¢(öA(öA(öA(öA(öAtQìAdQìATQìADQìA4QìA$QìAQìAQì@è£×@È£×@š£×@£×@QG®@G®?¢\>=qB}
+žBy
+žBu
+žBq
+žBm
+žBi
+žBe
+žBa
+žB]
+žBY
+žBU
+žBQ
+žBM
+žBI
+žBE
+žBA
+žB=
+žB9
+žB5
+žB1
+žB-
+žB)
+žB%
+žB!
+žB
+
+žB
+žB
+žB
+žB
+
+žB	
+žB
+žB
+žAú=qAò=qAê=qAâ=qAÚ=qAÒ=qAÊ=qAÂ=qAº=qA²=qAª=qA¢=qA=qA=qA=qA=qAtzáAdzáATzáADzáA4záA$záAzáAzá@èõÃ@ÈõÃ@šõÃ@õÃ@Që
+@ë
+?£×
+>\)B}(öBy(öBu(öBq(öBm(öBi(öBe(öBa(öB](öBY(öBU(öBQ(öBM(öBI(öBE(öBA(öB=(öB9(öB5(öB1(öB-(öB)(öB%(öB!(öB
+(öB(öB(öB(öB
+(öB	(öB(öB(öAúQìAòQìAêQìAâQìAÚQìAÒQìAÊQìAÂQìAºQìA²QìAªQìA¢QìAQìAQìAQìAQìAt£×Ad£×AT£×AD£×A4£×A$£×A£×A£×@éG®@ÉG®@©G®@G®@R\@\?¥
+ž>záB}33By33Bu33Bq33Bm33Bi33Be33Ba33B]33BY33BU33BQ33BM33BI33BE33BA33B=33B933B533B133B-33B)33B%33B!33B
+33B33B33B33B
+33B	33B33B33AúffAòffAêffAâffAÚffAÒffAÊffAÂffAºffA²ffAªffA¢ffAffAffAffAffAtÌÍAdÌÍATÌÍADÌÍA4ÌÍA$ÌÍAÌÍAÌÍ@é@É@©@@S33@33?Šff>B}=qBy=qBu=qBq=qBm=qBi=qBe=qBa=qB]=qBY=qBU=qBQ=qBM=qBI=qBE=qBA=qB==qB9=qB5=qB1=qB-=qB)=qB%=qB!=qB
+=qB=qB=qB=qB
+=qB	=qB=qB=qAúzáAòzáAêzáAâzáAÚzáAÒzáAÊzáAÂzáAºzáA²záAªzáA¢záAzáAzáAzáAzáAtõÃAdõÃATõÃADõÃA4õÃA$õÃAõÃAõÃ@éë
+@Éë
+@©ë
+@ë
+@S×
+@×
+?§®>žRB}G®ByG®BuG®BqG®BmG®BiG®BeG®BaG®B]G®BYG®BUG®BQG®BMG®BIG®BEG®BAG®B=G®B9G®B5G®B1G®B-G®B)G®B%G®B!G®B
+G®BG®BG®BG®B
+G®B	G®BG®BG®Aú\Aò\Aê\Aâ\AÚ\AÒ\AÊ\AÂ\Aº\A²\Aª\A¢\A\A\A\A\Au
+žAe
+žAU
+žAE
+žA5
+žA%
+žA
+žA
+ž@ê=q@Ê=q@ª=q@=q@Tzá@zá?šõÂ>£×
+B}QìByQìBuQìBqQìBmQìBiQìBeQìBaQìB]QìBYQìBUQìBQQìBMQìBIQìBEQìBAQìB=QìB9QìB5QìB1QìB-QìB)QìB%QìB!QìB
+QìBQìBQìBQìB
+QìB	QìBQìBQìAú£×Aò£×Aê£×Aâ£×AÚ£×AÒ£×AÊ£×AÂ£×Aº£×A²£×Aª£×A¢£×A£×A£×A£×A£×AuG®AeG®AUG®AEG®A5G®A%G®AG®AG®@ê\@Ê\@ª\@\@U
+ž@
+ž?ª=q>šõÃB}\)By\)Bu\)Bq\)Bm\)Bi\)Be\)Ba\)B]\)BY\)BU\)BQ\)BM\)BI\)BE\)BA\)B=\)B9\)B5\)B1\)B-\)B)\)B%\)B!\)B
+\)B\)B\)B\)B
+\)B	\)B\)B\)AúžRAòžRAêžRAâžRAÚžRAÒžRAÊžRAÂžRAºžRA²žRAªžRA¢žRAžRAžRAžRAžRAup€Aep€AUp€AEp€A5p€A%p€Ap€Ap€@êáH@ÊáH@ªáH@áH@UÂ@Â?«
+>®{B}ffByffBuffBqffBmffBiffBeffBaffB]ffBYffBUffBQffBMffBIffBEffBAffB=ffB9ffB5ffB1ffB-ffB)ffB%ffB!ffB
+ffBffBffBffB
+ffB	ffBffBffAúÌÍAòÌÍAêÌÍAâÌÍAÚÌÍAÒÌÍAÊÌÍAÂÌÍAºÌÍA²ÌÍAªÌÍA¢ÌÍAÌÍAÌÍAÌÍAÌÍAuAeAUAEA5A%AA@ë33@Ë33@«33@33@Vff@ff?¬ÌÍ>³33B}p€Byp€Bup€Bqp€Bmp€Bip€Bep€Bap€B]p€BYp€BUp€BQp€BMp€BIp€BEp€BAp€B=p€B9p€B5p€B1p€B-p€B)p€B%p€B!p€B
+p€Bp€Bp€Bp€B
+p€B	p€Bp€Bp€AúáHAòáHAêáHAâáHAÚáHAÒáHAÊáHAÂáHAºáHA²áHAªáHA¢áHAáHAáHAáHAáHAuÂAeÂAUÂAEÂA5ÂA%ÂAÂAÂ@ë
+@Ë
+@«
+@
+@W
+>@
+>?®{>žQìB}záByzáBuzáBqzáBmzáBizáBezáBazáB]záBYzáBUzáBQzáBMzáBIzáBEzáBAzáB=záB9záB5záB1záB-záB)záB%záB!záB
+záBzáBzáBzáB
+záB	záBzáBzáAúõÃAòõÃAêõÃAâõÃAÚõÃAÒõÃAÊõÃAÂõÃAºõÃA²õÃAªõÃA¢õÃAõÃAõÃAõÃAõÃAuë
+Aeë
+AUë
+AEë
+A5ë
+A%ë
+Aë
+Aë
+@ë×
+@Ë×
+@«×
+@×
+@W®@®?¯\)>œp€B}
+By
+Bu
+Bq
+Bm
+Bi
+Be
+Ba
+B]
+BY
+BU
+BQ
+BM
+BI
+BE
+BA
+B=
+B9
+B5
+B1
+B-
+B)
+B%
+B!
+B
+
+B
+B
+B
+B
+
+B	
+B
+B
+Aû
+=Aó
+=Aë
+=Aã
+=AÛ
+=AÓ
+=AË
+=AÃ
+=A»
+=A³
+=A«
+=A£
+=A
+=A
+=A
+=A
+=Av{Af{AV{AF{A6{A&{A{A{@ì(ö@Ì(ö@¬(ö@(ö@XQì@Qì?°£×>Â\B}\By\Bu\Bq\Bm\Bi\Be\Ba\B]\BY\BU\BQ\BM\BI\BE\BA\B=\B9\B5\B1\B-\B)\B%\B!\B
+\B\B\B\B
+\B	\B\B\Aû
+žAó
+žAë
+žAã
+žAÛ
+žAÓ
+žAË
+žAÃ
+žA»
+žA³
+žA«
+žA£
+žA
+žA
+žA
+žA
+žAv=qAf=qAV=qAF=qA6=qA&=qA=qA=q@ìzá@Ìzá@¬zá@zá@XõÂ@õÂ?±ë
+>Ç®B}ByBuBqBmBiBeBaB]BYBUBQBMBIBEBAB=B9B5B1B-B)B%B!B
+BBBB
+B	BBAû33Aó33Aë33Aã33AÛ33AÓ33AË33AÃ33A»33A³33A«33A£33A33A33A33A33AvffAfffAVffAFffA6ffA&ffAffAff@ìÌÍ@ÌÌÍ@¬ÌÍ@ÌÍ@Y@?³33>ÌÌÍB}£×By£×Bu£×Bq£×Bm£×Bi£×Be£×Ba£×B]£×BY£×BU£×BQ£×BM£×BI£×BE£×BA£×B=£×B9£×B5£×B1£×B-£×B)£×B%£×B!£×B
+£×B£×B£×B£×B
+£×B	£×B£×B£×AûG®AóG®AëG®AãG®AÛG®AÓG®AËG®AÃG®A»G®A³G®A«G®A£G®AG®AG®AG®AG®Av\Af\AV\AF\A6\A&\A\A\@í
+ž@Í
+ž@­
+ž@
+ž@Z=q@=q?Žzá>Ñë
+B}®By®Bu®Bq®Bm®Bi®Be®Ba®B]®BY®BU®BQ®BM®BI®BE®BA®B=®B9®B5®B1®B-®B)®B%®B!®B
+®B®B®B®B
+®B	®B®B®Aû\)Aó\)Aë\)Aã\)AÛ\)AÓ\)AË\)AÃ\)A»\)A³\)A«\)A£\)A\)A\)A\)A\)AvžRAfžRAVžRAFžRA6žRA&žRAžRAžR@íp€@Íp€@­p€@p€@ZáH@áH?µÂ>×
+=B}žRByžRBužRBqžRBmžRBižRBežRBažRB]žRBYžRBUžRBQžRBMžRBIžRBEžRBAžRB=žRB9žRB5žRB1žRB-žRB)žRB%žRB!žRB
+žRBžRBžRBžRB
+žRB	žRBžRBžRAûp€Aóp€Aëp€Aãp€AÛp€AÓp€AËp€AÃp€A»p€A³p€A«p€A£p€Ap€Ap€Ap€Ap€AváHAfáHAVáHAFáHA6áHA&áHAáHAáH@íÂ@ÍÂ@­Â@Â@[
+@
+?·
+>>Ü(öB}ÂByÂBuÂBqÂBmÂBiÂBeÂBaÂB]ÂBYÂBUÂBQÂBMÂBIÂBEÂBAÂB=ÂB9ÂB5ÂB1ÂB-ÂB)ÂB%ÂB!ÂB
+ÂBÂBÂBÂB
+ÂB	ÂBÂBÂAû
+Aó
+Aë
+Aã
+AÛ
+AÓ
+AË
+AÃ
+A»
+A³
+A«
+A£
+A
+A
+A
+A
+Aw
+=Ag
+=AW
+=AG
+=A7
+=A'
+=A
+=A
+=@î{@Î{@®{@{@\(ö@
+(ö?žQì>áG®B}ÌÍByÌÍBuÌÍBqÌÍBmÌÍBiÌÍBeÌÍBaÌÍB]ÌÍBYÌÍBUÌÍBQÌÍBMÌÍBIÌÍBEÌÍBAÌÍB=ÌÍB9ÌÍB5ÌÍB1ÌÍB-ÌÍB)ÌÍB%ÌÍB!ÌÍB
+ÌÍBÌÍBÌÍBÌÍB
+ÌÍB	ÌÍBÌÍBÌÍAûAóAëAãAÛAÓAËAÃA»A³A«A£AAAAAw33Ag33AW33AG33A733A'33A33A33@îff@Îff@®ff@ff@\ÌÍ@
+ÌÍ?¹>æffB}×
+By×
+Bu×
+Bq×
+Bm×
+Bi×
+Be×
+Ba×
+B]×
+BY×
+BU×
+BQ×
+BM×
+BI×
+BE×
+BA×
+B=×
+B9×
+B5×
+B1×
+B-×
+B)×
+B%×
+B!×
+B
+×
+B×
+B×
+B×
+B
+×
+B	×
+B×
+B×
+Aû®Aó®Aë®Aã®AÛ®AÓ®AË®AÃ®A»®A³®A«®A£®A®A®A®A®Aw\)Ag\)AW\)AG\)A7\)A'\)A\)A\)@îžR@ÎžR@®žR@žR@]p€@
+p€?ºáH>ë
+B}áHByáHBuáHBqáHBmáHBiáHBeáHBaáHB]áHBYáHBUáHBQáHBMáHBIáHBEáHBAáHB=áHB9áHB5áHB1áHB-áHB)áHB%áHB!áHB
+áHBáHBáHBáHB
+áHB	áHBáHBáHAûÂAóÂAëÂAãÂAÛÂAÓÂAËÂAÃÂA»ÂA³ÂA«ÂA£ÂAÂAÂAÂAÂAw
+Ag
+AW
+AG
+A7
+A'
+A
+A
+@ï
+=@Ï
+=@¯
+=@
+=@^{@
+{?Œ(ö>ð£×B}ë
+Byë
+Buë
+Bqë
+Bmë
+Bië
+Beë
+Baë
+B]ë
+BYë
+BUë
+BQë
+BMë
+BIë
+BEë
+BAë
+B=ë
+B9ë
+B5ë
+B1ë
+B-ë
+B)ë
+B%ë
+B!ë
+B
+ë
+Bë
+Bë
+Bë
+B
+ë
+B	ë
+Bë
+Bë
+Aû×
+Aó×
+Aë×
+Aã×
+AÛ×
+AÓ×
+AË×
+AÃ×
+A»×
+A³×
+A«×
+A£×
+A×
+A×
+A×
+A×
+Aw®Ag®AW®AG®A7®A'®A®A®@ï\)@Ï\)@¯\)@\)@^žR@
+žR?œp€>õÂB}õÃByõÃBuõÃBqõÃBmõÃBiõÃBeõÃBaõÃB]õÃBYõÃBUõÃBQõÃBMõÃBIõÃBEõÃBAõÃB=õÃB9õÃB5õÃB1õÃB-õÃB)õÃB%õÃB!õÃB
+õÃBõÃBõÃBõÃB
+õÃB	õÃBõÃBõÃAûë
+Aóë
+Aëë
+Aãë
+AÛë
+AÓë
+AËë
+AÃë
+A»ë
+A³ë
+A«ë
+A£ë
+Aë
+Aë
+Aë
+Aë
+Aw×
+Ag×
+AW×
+AG×
+A7×
+A'×
+A×
+A×
+@ï®@Ï®@¯®@®@_\)@\)?ŸžR>úáHB~  Bz  Bv  Br  Bn  Bj  Bf  Bb  B^  BZ  BV  BR  BN  BJ  BF  BB  B>  B:  B6  B2  B.  B*  B&  B"  B
+  B  B  B  B  B
+  B  B  Aü  Aô  Aì  Aä  AÜ  AÔ  AÌ  AÄ  AŒ  AŽ  A¬  A€  A  A  A  A  Ax  Ah  AX  AH  A8  A(  A  A  @ð  @Ð  @°  @  @`  @   ?À  ?   B~
+=Bz
+=Bv
+=Br
+=Bn
+=Bj
+=Bf
+=Bb
+=B^
+=BZ
+=BV
+=BR
+=BN
+=BJ
+=BF
+=BB
+=B>
+=B:
+=B6
+=B2
+=B.
+=B*
+=B&
+=B"
+=B
+
+=B
+=B
+=B
+=B
+=B
+
+=B
+=B
+=Aü{Aô{Aì{Aä{AÜ{AÔ{AÌ{AÄ{AŒ{AŽ{A¬{A€{A{A{A{A{Ax(öAh(öAX(öAH(öA8(öA((öA(öA(ö@ðQì@ÐQì@°Qì@Qì@`£×@ £×?ÁG®?\B~{Bz{Bv{Br{Bn{Bj{Bf{Bb{B^{BZ{BV{BR{BN{BJ{BF{BB{B>{B:{B6{B2{B.{B*{B&{B"{B
+{B{B{B{B{B
+{B{B{Aü(öAô(öAì(öAä(öAÜ(öAÔ(öAÌ(öAÄ(öAŒ(öAŽ(öA¬(öA€(öA(öA(öA(öA(öAxQìAhQìAXQìAHQìA8QìA(QìAQìAQì@ð£×@Ð£×@°£×@£×@aG®@!G®?Â\?
+žB~
+žBz
+žBv
+žBr
+žBn
+žBj
+žBf
+žBb
+žB^
+žBZ
+žBV
+žBR
+žBN
+žBJ
+žBF
+žBB
+žB>
+žB:
+žB6
+žB2
+žB.
+žB*
+žB&
+žB"
+žB
+
+žB
+žB
+žB
+žB
+žB
+
+žB
+žB
+žAü=qAô=qAì=qAä=qAÜ=qAÔ=qAÌ=qAÄ=qAŒ=qAŽ=qA¬=qA€=qA=qA=qA=qA=qAxzáAhzáAXzáAHzáA8záA(záAzáAzá@ðõÂ@ÐõÂ@°õÂ@õÂ@aë
+@!ë
+?Ã×
+?®B~(öBz(öBv(öBr(öBn(öBj(öBf(öBb(öB^(öBZ(öBV(öBR(öBN(öBJ(öBF(öBB(öB>(öB:(öB6(öB2(öB.(öB*(öB&(öB"(öB
+(öB(öB(öB(öB(öB
+(öB(öB(öAüQìAôQìAìQìAäQìAÜQìAÔQìAÌQìAÄQìAŒQìAŽQìA¬QìA€QìAQìAQìAQìAQìAx£×Ah£×AX£×AH£×A8£×A(£×A£×A£×@ñG®@ÑG®@±G®@G®@b\@"\?Å
+ž?
+=qB~33Bz33Bv33Br33Bn33Bj33Bf33Bb33B^33BZ33BV33BR33BN33BJ33BF33BB33B>33B:33B633B233B.33B*33B&33B"33B
+33B33B33B33B33B
+33B33B33AüffAôffAìffAäffAÜffAÔffAÌffAÄffAŒffAŽffA¬ffA€ffAffAffAffAffAxÌÍAhÌÍAXÌÍAHÌÍA8ÌÍA(ÌÍAÌÍAÌÍ@ñ@Ñ@±@@c33@#33?Æff?
+ÌÍB~=qBz=qBv=qBr=qBn=qBj=qBf=qBb=qB^=qBZ=qBV=qBR=qBN=qBJ=qBF=qBB=qB>=qB:=qB6=qB2=qB.=qB*=qB&=qB"=qB
+=qB=qB=qB=qB=qB
+=qB=qB=qAüzáAôzáAìzáAäzáAÜzáAÔzáAÌzáAÄzáAŒzáAŽzáA¬záA€záAzáAzáAzáAzáAxõÃAhõÃAXõÃAHõÃA8õÃA(õÃAõÃAõÃ@ñë
+@Ñë
+@±ë
+@ë
+@c×
+@#×
+?Ç®?\)B~G®BzG®BvG®BrG®BnG®BjG®BfG®BbG®B^G®BZG®BVG®BRG®BNG®BJG®BFG®BBG®B>G®B:G®B6G®B2G®B.G®B*G®B&G®B"G®B
+G®BG®BG®BG®BG®B
+G®BG®BG®Aü\Aô\Aì\Aä\AÜ\AÔ\AÌ\AÄ\AŒ\AŽ\A¬\A€\A\A\A\A\Ay
+žAi
+žAY
+žAI
+žA9
+žA)
+žA
+žA	
+ž@ò=q@Ò=q@²=q@=q@dzá@$zá?ÈõÂ?ë
+B~QìBzQìBvQìBrQìBnQìBjQìBfQìBbQìB^QìBZQìBVQìBRQìBNQìBJQìBFQìBBQìB>QìB:QìB6QìB2QìB.QìB*QìB&QìB"QìB
+QìBQìBQìBQìBQìB
+QìBQìBQìAü£×Aô£×Aì£×Aä£×AÜ£×AÔ£×AÌ£×AÄ£×AŒ£×AŽ£×A¬£×A€£×A£×A£×A£×A£×AyG®AiG®AYG®AIG®A9G®A)G®AG®A	G®@ò\@Ò\@²\@\@e
+ž@%
+ž?Ê=p?záB~\)Bz\)Bv\)Br\)Bn\)Bj\)Bf\)Bb\)B^\)BZ\)BV\)BR\)BN\)BJ\)BF\)BB\)B>\)B:\)B6\)B2\)B.\)B*\)B&\)B"\)B
+\)B\)B\)B\)B\)B
+\)B\)B\)AüžRAôžRAìžRAäžRAÜžRAÔžRAÌžRAÄžRAŒžRAŽžRA¬žRA€žRAžRAžRAžRAžRAyp€Aip€AYp€AIp€A9p€A)p€Ap€A	p€@òáH@ÒáH@²áH@áH@eÂ@%Â?Ë
+
+?
+=B~ffBzffBvffBrffBnffBjffBfffBbffB^ffBZffBVffBRffBNffBJffBFffBBffB>ffB:ffB6ffB2ffB.ffB*ffB&ffB"ffB
+ffBffBffBffBffB
+ffBffBffAüÌÍAôÌÍAìÌÍAäÌÍAÜÌÍAÔÌÍAÌÌÍAÄÌÍAŒÌÍAŽÌÍA¬ÌÍA€ÌÍAÌÍAÌÍAÌÍAÌÍAyAiAYAIA9A)AA	@ó33@Ó33@³33@33@fff@&ff?ÌÌÍ?B~p€Bzp€Bvp€Brp€Bnp€Bjp€Bfp€Bbp€B^p€BZp€BVp€BRp€BNp€BJp€BFp€BBp€B>p€B:p€B6p€B2p€B.p€B*p€B&p€B"p€B
+p€Bp€Bp€Bp€Bp€B
+p€Bp€Bp€AüáHAôáHAìáHAäáHAÜáHAÔáHAÌáHAÄáHAŒáHAŽáHA¬áHA€áHAáHAáHAáHAáHAyÂAiÂAYÂAIÂA9ÂA)ÂAÂA	Â@ó
+@Ó
+@³
+@
+@g
+>@'
+>?Î{?
+(öB~záBzzáBvzáBrzáBnzáBjzáBfzáBbzáB^záBZzáBVzáBRzáBNzáBJzáBFzáBBzáB>záB:záB6záB2záB.záB*záB&záB"záB
+záBzáBzáBzáBzáB
+záBzáBzáAüõÃAôõÃAìõÃAäõÃAÜõÃAÔõÃAÌõÃAÄõÃAŒõÃAŽõÃA¬õÃA€õÃAõÃAõÃAõÃAõÃAyë
+Aië
+AYë
+AIë
+A9ë
+A)ë
+Aë
+A	ë
+@ó×
+@Ó×
+@³×
+@×
+@g®@'®?Ï\)?
+žRB~
+Bz
+Bv
+Br
+Bn
+Bj
+Bf
+Bb
+B^
+BZ
+BV
+BR
+BN
+BJ
+BF
+BB
+B>
+B:
+B6
+B2
+B.
+B*
+B&
+B"
+B
+
+B
+B
+B
+B
+B
+
+B
+B
+Aý
+=Aõ
+=Aí
+=Aå
+=AÝ
+=AÕ
+=AÍ
+=AÅ
+=Aœ
+=Aµ
+=A­
+=A¥
+=A
+=A
+=A
+=A
+
+=Az{Aj{AZ{AJ{A:{A*{A{A
+{@ô(ö@Ô(ö@Ž(ö@(ö@hQì@(Qì?Ð£×?!G®                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|
+=Bx  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|{Bx
+=Bx
+=Bt  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|(öBx
+žBx{Bt
+=Bp
+=Bl  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|33Bx(öBx(öBt
+žBp{Bl
+=Bl
+=Bh  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|=qBx=qBx33Bt(öBp(öBl
+žBl{Bh
+=Bd
+=Bd  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|QìBxG®Bx=qBt=qBp33Bl(öBl(öBh
+žBd{Bd
+=B`
+=B\  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|\)Bx\)BxQìBtG®Bp=qBl=qBl33Bh(öBd(öBd
+žB`{B\
+=BX
+=BX  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|p€BxffBx\)Bt\)BpQìBlG®Bl=qBh=qBd33Bd(öB`(öB\
+žBX{BX
+=BT
+=BP  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|záBxp€Bxp€BtffBp\)Bl\)BlQìBhG®Bd=qBd=qB`33B\(öBX(öBX
+žBT{BP
+=BP
+=BL  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|
+Bx
+BxzáBtp€Bpp€BlffBl\)Bh\)BdQìBdG®B`=qB\=qBX33BX(öBT(öBP
+žBP{BL
+=BH
+=BH  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|Bx\Bx
+Bt
+BpzáBlp€Blp€BhffBd\)Bd\)B`QìB\G®BX=qBX=qBT33BP(öBP(öBL
+žBH{BH
+=BD
+=B@  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|£×Bx£×BxBt\Bp
+Bl
+BlzáBhp€Bdp€BdffB`\)B\\)BXQìBXG®BT=qBP=qBP33BL(öBH(öBH
+žBD{B@
+=B<
+=B<  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|žRBx®Bx£×Bt£×BpBl\Bl
+Bh
+BdzáBdp€B`p€B\ffBX\)BX\)BTQìBPG®BP=qBL=qBH33BH(öBD(öB@
+žB<{B<
+=B8
+=B4  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ÂBxžRBxžRBt®Bp£×Bl£×BlBh\Bd
+Bd
+B`záB\p€BXp€BXffBT\)BP\)BPQìBLG®BH=qBH=qBD33B@(öB<(öB<
+žB8{B4
+=B4
+=B0  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|×
+BxÌÍBxÂBtžRBpžRBl®Bl£×Bh£×BdBd\B`
+B\
+BXzáBXp€BTp€BPffBP\)BL\)BHQìBHG®BD=qB@=qB<33B<(öB8(öB4
+žB4{B0
+=B,
+=B(  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|áHBx×
+Bx×
+BtÌÍBpÂBlžRBlžRBh®Bd£×Bd£×B`B\\BX
+BX
+BTzáBPp€BPp€BLffBH\)BH\)BDQìB@G®B<=qB<=qB833B4(öB4(öB0
+žB,{B(
+=B(
+=B$  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B|ë
+Bxë
+BxáHBt×
+Bp×
+BlÌÍBlÂBhžRBdžRBd®B`£×B\£×BXBX\BT
+BP
+BPzáBLp€BHp€BHffBD\)B@\)B<QìB<G®B8=qB4=qB433B0(öB,(öB(
+žB({B$
+=B 
+=B   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}  BxõÃBxë
+Btë
+BpáHBl×
+Bl×
+BhÌÍBdÂBdžRB`žRB\®BX£×BX£×BTBP\BP
+BL
+BHzáBHp€BDp€B@ffB<\)B<\)B8QìB4G®B4=qB0=qB,33B((öB((öB$
+žB {B 
+=B
+
+=B  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}
+=By  By  BtõÃBpë
+Blë
+BláHBh×
+Bd×
+BdÌÍB`ÂB\žRBXžRBX®BT£×BP£×BPBL\BH
+BH
+BDzáB@p€B<p€B<ffB8\)B4\)B4QìB0G®B,=qB(=qB(33B$(öB (öB 
+žB
+{B
+=B
+=B  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}
+žBy{By
+=Bu  Bq  BlõÃBlë
+Bhë
+BdáHBd×
+B`×
+B\ÌÍBXÂBXžRBTžRBP®BP£×BL£×BHBH\BD
+B@
+B<záB<p€B8p€B4ffB4\)B0\)B,QìB(G®B(=qB$=qB 33B (öB
+(öB
+žB{B
+=B
+=B
+  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}(öBy
+žBy
+žBu{Bq
+=Bm  Bm  BhõÃBdë
+Bdë
+B`áHB\×
+BX×
+BXÌÍBTÂBPžRBPžRBL®BH£×BH£×BDB@\B<
+B<
+B8záB4p€B4p€B0ffB,\)B(\)B(QìB$G®B =qB =qB
+33B(öB(öB
+žB{B
+
+=B
+
+=B  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}33By33By(öBu
+žBq
+žBm{Bm
+=Bi  Be  BdõÃB`ë
+B\ë
+BXáHBX×
+BT×
+BPÌÍBPÂBLžRBHžRBH®BD£×B@£×B<B<\B8
+B4
+B4záB0p€B,p€B(ffB(\)B$\)B QìB G®B
+=qB=qB33B(öB(öB
+
+žB
+{B
+=B
+=B  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}G®By=qBy33Bu33Bq(öBm
+žBm
+žBi{Be
+=Be  Ba  B\õÃBXë
+BXë
+BTáHBP×
+BP×
+BLÌÍBHÂBHžRBDžRB@®B<£×B<£×B8B4\B4
+B0
+B,záB(p€B(p€B$ffB \)B \)B
+QìBG®B=qB=qB33B
+(öB
+(öB
+žB{B
+=B 
+=Aø  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}QìByQìByG®Bu=qBq33Bm33Bm(öBi
+žBe
+žBe{Ba
+=B]  BY  BXõÃBTë
+BPë
+BPáHBL×
+BH×
+BHÌÍBDÂB@žRB<žRB<®B8£×B4£×B4B0\B,
+B(
+B(záB$p€B p€B ffB
+\)B\)BQìBG®B=qB
+=qB
+33B(öB(öB
+žB {Aø{Að{Að  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ffBy\)ByQìBuQìBqG®Bm=qBm33Bi33Be(öBe
+žBa
+žB]{BY
+=BY  BU  BPõÃBPë
+BLë
+BHáHBH×
+BD×
+B@ÌÍB<ÂB<žRB8žRB4®B4£×B0£×B,B(\B(
+B$
+B záB p€B
+p€BffB\)B\)BQìB
+G®B
+=qB=qB33B(öB (öAø=qAð(öAð{Aè{Aà  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}p€ByffByffBu\)BqQìBmQìBmG®Bi=qBe33Be33Ba(öB]
+žBY
+žBY{BU
+=BQ  BQ  BLõÃBHë
+BHë
+BDáHB@×
+B<×
+B<ÌÍB8ÂB4žRB4žRB0®B,£×B(£×B(B$\B 
+B 
+B
+záBp€Bp€BffB\)B
+\)B
+QìBG®B=qB=qB 33AøQìAðQìAð=qAè(öAà{Aà{AØ  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}
+ByzáByp€BuffBqffBm\)BmQìBiQìBeG®Be=qBa33B]33BY(öBY
+žBU
+žBQ{BQ
+=BM  BI  BHõÃBDë
+B@ë
+B<áHB<×
+B8×
+B4ÌÍB4ÂB0žRB,žRB(®B(£×B$£×B B \B
+
+B
+BzáBp€Bp€B
+ffB
+\)B\)BQìBG®B =qAøzáAðffAðQìAèQìAà=qAà(öAØ{AÐ{AÈ  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}\By
+By
+BuzáBqp€BmffBmffBi\)BeQìBeQìBaG®B]=qBY33BY33BU(öBQ
+žBQ
+žBM{BI
+=BI  BE  B@õÃB<ë
+B<ë
+B8áHB4×
+B4×
+B0ÌÍB,ÂB(žRB(žRB$®B £×B £×B
+B\B
+B
+BzáB
+p€B
+p€BffB\)B\)B QìAø\AðzáAðzáAèffAàQìAàQìAØ=qAÐ(öAÈ{AÈ{AÀ  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ByBy\Bu
+Bq
+BmzáBmp€BiffBeffBe\)BaQìB]QìBYG®BY=qBU33BQ33BQ(öBM
+žBI
+žBI{BE
+=BA  B=  B<õÃB8ë
+B4ë
+B4áHB0×
+B,×
+B(ÌÍB(ÂB$žRB žRB ®B
+£×B£×BB\B
+B
+
+B
+záBp€Bp€BffB \)AøžRAð£×Að\AèzáAàzáAàffAØQìAÐQìAÈ=qAÈ(öAÀ{Až{Až  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}®By£×ByBuBq\Bm
+Bm
+BizáBep€BeffBaffB]\)BYQìBYQìBUG®BQ=qBQ33BM33BI(öBI
+žBE
+žBA{B=
+=B=  B9  B4õÃB4ë
+B0ë
+B,áHB(×
+B(×
+B$ÌÍB ÂB žRB
+žRB®B£×B£×BB
+\B
+
+B
+BzáBp€B p€AøÌÍAðžRAðžRAè£×Aà\AàzáAØzáAÐffAÈQìAÈQìAÀ=qAž(öAž{A°{Aš  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}žRBy®By®Bu£×BqBmBm\Bi
+Be
+BezáBap€B]ffBYffBY\)BUQìBQQìBQG®BM=qBI33BI33BE(öBA
+žB=
+žB={B9
+=B5  B5  B0õÃB,ë
+B(ë
+B(áHB$×
+B ×
+B ÌÍB
+ÂBžRBžRB®B£×B
+£×B
+B\B
+B
+B záAøáHAðáHAðÌÍAèžRAàžRAà£×AØ\AÐzáAÈzáAÈffAÀQìAžQìAž=qA°(öAš{Aš{A   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}ÌÍByÂByžRBu®Bq®Bm£×BmBiBe\Be
+Ba
+B]záBYp€BYffBUffBQ\)BQQìBMQìBIG®BI=qBE33BA33B=(öB=
+žB9
+žB5{B5
+=B1  B-  B(õÃB(ë
+B$ë
+B áHB ×
+B
+×
+BÌÍBÂBžRBžRB
+®B
+£×B£×BB\B 
+Aù
+=AðõÃAðáHAèáHAàÌÍAàžRAØžRAÐ£×AÈ\AÈzáAÀzáAžffAžQìA°QìAš=qAš(öA {A{A  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}×
+ByÌÍByÌÍBuÂBqžRBm®Bm®Bi£×BeBeBa\B]
+BY
+BYzáBUp€BQffBQffBM\)BIQìBIQìBEG®BA=qB=33B=33B9(öB5
+žB5
+žB1{B-
+=B)  B)  B$õÃB ë
+B ë
+B
+áHB×
+B×
+BÌÍBÂB
+žRB
+žRB®B£×B£×B Aù
+žAñ
+=Añ
+=AèõÃAàáHAàáHAØÌÍAÐžRAÈžRAÈ£×AÀ\AžzáAžzáA°ffAšQìAšQìA =qA(öA{A{A  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}áHByáHBy×
+BuÌÍBqÌÍBmÂBmžRBi®Be®Be£×BaB]BY\BY
+BU
+BQzáBQp€BMffBIffBI\)BEQìBAQìB=G®B==qB933B533B5(öB1
+žB-
+žB){B)
+=B%  B!  B õÃB
+ë
+Bë
+BáHB×
+B×
+B
+ÌÍB
+ÂBžRBžRB®B £×AùG®Añ33Añ
+žAé
+=Aá
+=AàõÃAØáHAÐáHAÈÌÍAÈžRAÀžRAž£×Až\A°záAšzáAšffA QìAQìA=qA(öA{A{A  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B}õÃByë
+ByáHBuáHBq×
+BmÌÍBmÌÍBiÂBežRBe®Ba®B]£×BYBYBU\BQ
+BQ
+BMzáBIp€BIffBEffBA\)B=QìB=QìB9G®B5=qB533B133B-(öB)
+žB)
+žB%{B!
+=B!  B
+  BõÃBë
+Bë
+BáHB
+×
+B
+×
+BÌÍBÂBžRB žRAù\)AñG®AñG®Aé33Aá
+žAá
+=AÙ
+=AÐõÃAÈáHAÈáHAÀÌÍAžžRAžžRA°£×Aš\AšzáA záAffAQìAQìA=qA(öA{Ap(öA`  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~  Bz  ByõÃBuë
+BqáHBmáHBm×
+BiÌÍBeÌÍBeÂBažRB]®BY®BY£×BUBQBQ\BM
+BI
+BIzáBEp€BAffB=ffB=\)B9QìB5QìB5G®B1=qB-33B)33B)(öB%
+žB!
+žB!{B
+
+=B  B  BõÃBë
+B
+ë
+B
+áHB×
+B×
+BÌÍB ÂAùp€Añp€Añ\)AéG®AáG®Aá33AÙ
+žAÑ
+=AÉ
+=AÈõÃAÀáHAžáHAžÌÍA°žRAšžRAš£×A \AzáAzáAffAQìAQìA=qApQìA`(öAP(öAP  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~{Bz
+=Bz  Bv  BqõÃBmë
+BmáHBiáHBe×
+BeÌÍBaÌÍB]ÂBYžRBY®BU®BQ£×BQBMBI\BI
+BE
+BAzáB=p€B=ffB9ffB5\)B5QìB1QìB-G®B)=qB)33B%33B!(öB!
+žB
+
+žB{B
+=B  B  B
+õÃB
+ë
+Bë
+BáHB×
+B ×
+AùAñ
+Añp€Aép€Aá\)AáG®AÙG®AÑ33AÉ
+žAÉ
+=AÁ
+=AžõÃAžáHA°áHAšÌÍAšžRA žRA£×A\AzáAzáAffAQìAp£×A`záAPQìAP(öA@(öA0  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~
+žBz{Bz{Bv
+=Br  Bn  BmõÃBië
+BeáHBeáHBa×
+B]ÌÍBYÌÍBYÂBUžRBQ®BQ®BM£×BIBIBE\BA
+B=
+B=záB9p€B5ffB5ffB1\)B-QìB)QìB)G®B%=qB!33B!33B
+(öB
+žB
+žB{B
+=B
+  B
+  BõÃBë
+Bë
+B áHAù®Añ®AñAé
+Aáp€Aáp€AÙ\)AÑG®AÉG®AÉ33AÁ
+žA¹
+=A¹
+=A°õÃAšáHAšáHA ÌÍAžRAžRA£×A\AzáAzáApÌÍA`£×AP£×APzáA@QìA0(öA0(öA   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~(öBz(öBz
+žBv{Br{Bn
+=Bn  Bj  BeõÃBeë
+BaáHB]áHBY×
+BYÌÍBUÌÍBQÂBQžRBM®BI®BI£×BEBAB=\B=
+B9
+B5záB5p€B1ffB-ffB)\)B)QìB%QìB!G®B!=qB
+33B33B(öB
+žB
+žB
+{B
+=B	  B  BõÃB ë
+Aù×
+AñÂAñ®Aé®AáAá
+AÙp€AÑp€AÉ\)AÉG®AÁG®A¹33A¹
+žA±
+=A©
+=AšõÃA áHAáHAÌÍAžRAžRA£×A\ApõÃA`õÃAPÌÍAP£×A@£×A0záA0QìA (öA(öA  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~=qBz33Bz(öBv(öBr
+žBn{Bn{Bj
+=Bf  Bf  BaõÃB]ë
+BYáHBYáHBU×
+BQÌÍBQÌÍBMÂBIžRBI®BE®BA£×B=B=B9\B5
+B5
+B1záB-p€B)ffB)ffB%\)B!QìB!QìB
+G®B=qB33B33B(öB
+
+žB
+
+žB	{B
+=B  B  Aùë
+Añ×
+Añ×
+AéÂAá®Aá®AÙAÑ
+AÉp€AÉp€AÁ\)A¹G®A¹G®A±33A©
+žA©
+=A¡
+=AõÃAáHAáHAÌÍAžRAžRAqG®Aa
+žAPõÃAPõÃA@ÌÍA0£×A0£×A záAQìA(öA (ö@à  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~G®BzG®Bz=qBv33Br(öBn(öBn
+žBj{Bf{Bf
+=Bb  B^  BYõÃBYë
+BUáHBQáHBQ×
+BMÌÍBIÌÍBIÂBEžRBA®B=®B=£×B9B5B5\B1
+B-
+B)záB)p€B%ffB!ffB!\)B
+QìBQìBG®B=qB33B
+33B
+(öB	
+žB
+žB{B
+=Aú  Aò  Añë
+Aé×
+Aá×
+AáÂAÙ®AÑ®AÉAÉ
+AÁp€A¹p€A¹\)A±G®A©G®A©33A¡
+žA
+=A
+=AõÃAáHAáHAÌÍAqp€Aap€AQG®AQ
+žA@õÃA0õÃA0ÌÍA £×A£×AzáA Qì@àQì@ÀQì@À  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B~\)BzQìBzG®BvG®Br=qBn33Bn(öBj(öBf
+žBf{Bb{B^
+=BZ  BZ  BUõÃBQë
+BQáHBMáHBI×
+BIÌÍBEÌÍBAÂB=žRB=®B9®B5£×B5B1B-\B)
+B)
+B%záB!p€B!ffB
+ffB\)BQìBQìBG®B
+=qB
+33B	33B(öB
+žB
+žAú(öAò{Aò  Aê  Aáë
+Aá×
+AÙ×
+AÑÂAÉ®AÉ®AÁA¹
+A¹p€A±p€A©\)A©G®A¡G®A33A
+žA
+=A
+=AõÃAáHAqÂAaAQp€AQp€AAG®A1
+žA0õÃA õÃAÌÍA£×A £×@àõÃ@À£×@ÀQì@ Qì@  ¿  ¿  ¿  ¿  ¿  ¿  B~ffBz\)Bz\)BvQìBrG®BnG®Bn=qBj33Bf(öBf(öBb
+žB^{BZ{BZ
+=BV  BR  BQõÃBMë
+BIáHBIáHBE×
+BAÌÍB=ÌÍB=ÂB9žRB5®B5®B1£×B-B)B)\B%
+B!
+B!záB
+p€BffBffB\)BQìB
+QìB
+G®B	=qB33B33B(öAú=qAò=qAò(öAê{Aâ  Aâ  AÙë
+AÑ×
+AÉ×
+AÉÂAÁ®A¹®A¹A±
+A©p€A©p€A¡\)AG®AG®A33A
+žA
+=A
+=Aqë
+AaÂAQÂAQAAp€A1p€A1G®A!
+žAõÃAõÃA ÌÍ@áG®@ÁG®@ÀõÃ@ £×@Qì@Qì@@  ¿  ¿  ¿  ¿  B~záBzp€BzffBv\)Br\)BnQìBnG®BjG®Bf=qBf33Bb(öB^(öBZ
+žBZ{BV{BR
+=BR  BN  BIõÃBIë
+BEáHBAáHB=×
+B=ÌÍB9ÌÍB5ÂB5žRB1®B-®B)£×B)B%B!\B!
+B
+
+BzáBp€BffBffB
+\)B
+QìB	QìBG®B=qB33AúffAòQìAò=qAê=qAâ(öAâ{AÚ  AÒ  AÉë
+AÉ×
+AÁ×
+A¹ÂA¹®A±®A©A©
+A¡p€Ap€A\)AG®AG®A33A
+žAr{Ab{AQë
+AQÂAAÂA1A1p€A!p€AG®A
+žA õÃ@áë
+@Á@ÁG®@¡G®@õÃ@£×@@£×@ £×?  ¿  ¿  B~
+BzzáBzzáBvp€BrffBn\)Bn\)BjQìBfG®BfG®Bb=qB^33BZ(öBZ(öBV
+žBR{BR{BN
+=BJ  BJ  BEõÃBAë
+B=áHB=áHB9×
+B5ÌÍB5ÌÍB1ÂB-žRB)®B)®B%£×B!B!B
+\B
+B
+BzáBp€B
+ffB
+ffB	\)BQìBQìBG®AúzáAòffAòffAêQìAâ=qAâ=qAÚ(öAÒ{AÊ  AÊ  AÁë
+A¹×
+A¹×
+A±ÂA©®A©®A¡A
+Ap€Ap€A\)AG®AG®ArffAb=qAR{AR{AAë
+A1ÂA1ÂA!Ap€Ap€AG®@â=q@Áë
+@Áë
+@¡@G®@G®@Aë
+@G®?G®?G®    ¿  ¿  Bz
+BvzáBrzáBnp€BnffBj\)Bf\)BfQìBbG®B^G®BZ=qBZ33BV(öBR(öBR
+žBN{BJ{BJ
+=BF  BB  B=õÃB=ë
+B9áHB5áHB5×
+B1ÌÍB-ÌÍB)ÂB)žRB%®B!®B!£×B
+BB\B
+B
+B
+záB
+p€B	ffBffB\)BQìAú£×Aò\AòzáAêffAâffAâQìAÚ=qAÒ=qAÊ(öAÊ{AÂ  Aº  A¹ë
+A±×
+A©×
+A©ÂA¡®A®AA
+Ap€Ap€A\)Ar\Ab\ARffAR=qAB{A2{A1ë
+A!ÂAÂAAp€@âáH@Â\@Â=q@¡ë
+@ë
+@@B\@\?×
+?\<#×
+¿  ¿  ¿  ¿  Br
+BnzáBnzáBjp€BfffBf\)Bb\)B^QìBZG®BZG®BV=qBR33BR(öBN(öBJ
+žBJ{BF{BB
+=B>  B>  B9õÃB5ë
+B5áHB1áHB-×
+B)ÌÍB)ÌÍB%ÂB!žRB!®B
+®B£×BBB\B
+
+B
+
+B	záBp€BffBffAúžRAò£×Aò£×Aê\AâzáAâffAÚffAÒQìAÊ=qAÊ=qAÂ(öAº{Aº  A²  A©ë
+A©×
+A¡×
+AÂA®A®AA
+Ap€AráHAbžRAR\AR\ABffA2=qA2{A"{Aë
+AÂAÂ@ã33@ÂáH@ÂáH@¢\@=q@ë
+@C×
+@33?
+
+ž?
+
+ž<õÂ¿  ¿  ¿  ¿  ¿  ¿  Bn
+BjzáBfzáBfp€BbffB^\)BZ\)BZQìBVG®BRG®BR=qBN33BJ(öBJ(öBF
+žBB{B>{B>
+=B:  B6  B5õÃB1ë
+B-áHB)áHB)×
+B%ÌÍB!ÌÍB!ÂB
+žRB®B®B£×BB
+B
+\B	
+B
+BzáBp€AúÌÍAòÌÍAòžRAê£×Aâ£×Aâ\AÚzáAÒffAÊffAÊQìAÂ=qAº=qAº(öA²{Aª  Aª  A¡ë
+A×
+A×
+AÂA®A®AAs
+=AbáHARáHARžRAB\A2\A2ffA"=qA{A{Aë
+@ã
+@Ã
+@Ã33@¢áH@áH@\@Dzá@×
+?®?ff=#×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bf
+BfzáBbzáB^p€BZffBZ\)BV\)BRQìBRG®BNG®BJ=qBJ33BF(öBB(öB>
+žB>{B:{B6
+=B6  B2  B-õÃB)ë
+B)áHB%áHB!×
+B!ÌÍB
+ÌÍBÂBžRB®B®B
+£×B
+B	B\B
+B
+AúõÃAòáHAòÌÍAêÌÍAâžRAâ£×AÚ£×AÒ\AÊzáAÊffAÂffAºQìAº=qA²=qAª(öAª{A¢  A  Aë
+A×
+A×
+AÂA®As\)Ac33AS
+=ARáHABáHA2žRA2\A"\AffA=qA{@ä(ö@Ã×
+@Ã
+@£
+@33@áH@EÂ@
+ž?õÃ?®=uÂ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Bb
+B^záBZzáBZp€BVffBR\)BR\)BNQìBJG®BJG®BF=qBB33B>(öB>(öB:
+žB6{B6{B2
+=B.  B*  B)õÃB%ë
+B!áHB!áHB
+×
+BÌÍBÌÍBÂBžRB
+®B
+®B	£×BBB\Aû
+=Aó
+=AòõÃAêáHAâÌÍAâÌÍAÚžRAÒ£×AÊ£×AÊ\AÂzáAºffAºffA²QìAª=qAª=qA¢(öA{A  A  Aë
+A×
+A×
+As
+Ac\)AS\)AS33AC
+=A2áHA2áHA"žRA\A\Aff@äzá@Ä(ö@Ä(ö@£×
+@
+@
+@Fff@Â?
+?=q=\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BZ
+BZzáBVzáBRp€BRffBN\)BJ\)BJQìBFG®BBG®B>=qB>33B:(öB6(öB6
+žB2{B.{B*
+=B*  B&  B!õÃB!ë
+B
+áHBáHB×
+BÌÍBÌÍB
+ÂB
+žRB	®B®B£×BAû33Aó
+žAó
+=Aë
+=AâõÃAâáHAÚÌÍAÒÌÍAÊžRAÊ£×AÂ£×Aº\AºzáA²ffAªffAªQìA¢=qA=qA(öA{A  A  Aë
+As®Ac®AS
+AS\)AC\)A333A3
+=A"áHAáHAžRA\@å
+ž@ÄÌÍ@Äzá@€(ö@(ö@×
+@G
+=@
+=?ÌÍ?
+=žQì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BV
+BRzáBRzáBNp€BJffBJ\)BF\)BBQìB>G®B>G®B:=qB633B6(öB2(öB.
+žB*{B*{B&
+=B"  B"  B
+õÃBë
+BáHBáHB×
+B
+ÌÍB
+ÌÍB	ÂBžRB®B®AûG®Aó33Aó33Aë
+žAã
+=Aã
+=AÚõÃAÒáHAÊÌÍAÊÌÍAÂžRAº£×Aº£×A²\AªzáAªffA¢ffAQìA=qA=qA(öA{A  At  Ac×
+AS®AS®AC
+A3\)A3\)A#33A
+=AáHAáH@åp€@Å
+ž@Å
+ž@€ÌÍ@zá@(ö@HQì@®?{?{=ÌÌÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BR
+BNzáBJzáBJp€BFffBB\)B>\)B>QìB:G®B6G®B6=qB233B.(öB*(öB*
+žB&{B"{B"
+=B
+  B  BõÃBë
+BáHB
+áHB
+×
+B	ÌÍBÌÍBÂBžRAû\)Aó\)AóG®Aë33Aã33Aã
+žAÛ
+=AÓ
+=AÊõÃAÊáHAÂÌÍAºÌÍAºžRA²£×Aª£×Aª\A¢záAffAffAQìA=qA=qA(öAt(öAd  AT  AS×
+AC®A3®A3
+A#\)A\)A33A
+=@åÂ@ÅÂ@Åp€@¥
+ž@
+
+ž@ÌÍ@HõÃ@Qì?£×?\)=áG®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BJ
+BJzáBFzáBBp€B>ffB>\)B:\)B6QìB6G®B2G®B.=qB*33B*(öB&(öB"
+žB"{B
+{B
+=B  B  BõÃB
+ë
+B
+áHB	áHB×
+BÌÍBÌÍAû
+Aóp€Aó\)Aë\)AãG®Aã33AÛ33AÓ
+žAË
+=AË
+=AÂõÃAºáHAºÌÍA²ÌÍAªžRAª£×A¢£×A\AzáAffAffAQìA=qAtzáAdQìAT(öAT  AD  A3×
+A3®A#®A
+A\)A\)@æff@Æ{@ÅÂ@¥Â@
+p€@
+
+ž@J=q@	?ë
+?£×>
+ž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  BF
+BBzáB>záB>p€B:ffB6\)B6\)B2QìB.G®B*G®B*=qB&33B"(öB"(öB
+
+žB{B{B
+=B  B  B
+õÃB	ë
+BáHBáHB×
+AûAóAó
+Aëp€Aã\)Aã\)AÛG®AÓ33AË33AË
+žAÃ
+=A»
+=AºõÃA²áHAªÌÍAªÌÍA¢žRA£×A£×A\AzáAffAffAt£×AdzáATzáATQìAD(öA4  A4  A#×
+A®A®A
+@æžR@ÆžR@Æff@Š{@
+Â@
+Â@JáH@
+=q?zá?33>\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B>
+B>záB:záB6p€B6ffB2\)B.\)B*QìB*G®B&G®B"=qB"33B
+(öB(öB
+žB{B{B
+=B  B
+  BõÃBë
+BáHAûÂAó®AóAëAã
+Aãp€AÛ\)AÓ\)AËG®AË33AÃ33A»
+žA»
+=A³
+=AªõÃAªáHA¢ÌÍAÌÍAžRA£×A£×A\AzáAtÌÍAdÌÍAT£×ATzáADzáA4QìA4(öA$  A  A×
+A®@ç\)@Ç
+=@ÆžR@ŠžR@ff@{@K
+@
+
+?Â?zá>#×
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B:
+B6záB6záB2p€B.ffB*\)B*\)B&QìB"G®B"G®B
+=qB33B(öB(öB
+žB{B{B
+
+=B  B  BõÃAû×
+AóÂAóÂAë®AãAãAÛ
+AÓp€AË\)AË\)AÃG®A»33A»33A³
+žA«
+=A«
+=A¢õÃAáHAÌÍAÌÍAžRA£×A£×Au
+žAdõÃATÌÍATÌÍAD£×A4záA4záA$QìA(öA  A  @ç®@Ç\)@Ç\)@§
+=@žR@žR@LÌÍ@
+(ö?
+>?
+>>.{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B6
+B2záB.záB*p€B*ffB&\)B"\)B"QìB
+G®BG®B=qB33B(öB(öB
+žB
+{B{B
+=B  Aü  Aóë
+Aó×
+AëÂAãÂAã®AÛAÓAË
+AËp€AÃ\)A»\)A»G®A³33A«33A«
+žA£
+=A
+=AõÃAáHAÌÍAÌÍAžRAuG®AeG®AU
+žATõÃADÌÍA4ÌÍA4£×A$záAzáAQìA(ö@è  @È  @Ç®@§\)@\)@
+=@Mp€@
+p€??Qì>8Qì¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B.
+B*záB*záB&p€B"ffB"\)B
+\)BQìBG®BG®B=qB33B(öB
+(öB
+žB{B{Aü{Aô  Aô  Aëë
+Aã×
+AãÂAÛÂAÓ®AËAËAÃ
+A»p€A»\)A³\)A«G®A«33A£33A
+žA
+=A
+=AõÃAáHAÌÍAuAep€AUG®AUG®AE
+žA4õÃA4ÌÍA$ÌÍA£×AzáAzá@è£×@ÈQì@È  @š  @®@\)@NžR@{?áH?áH>LÌÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B*
+B&záB"záB"p€B
+ffB\)B\)BQìBG®BG®B=qB
+33B(öB(öB
+žAü(öAô(öAô{Aì  Aä  Aãë
+AÛ×
+AÓÂAËÂAË®AÃA»A»
+A³p€A«\)A«\)A£G®A33A33A
+žA
+=A
+=AõÃAuÂAeAUAUp€AEG®A5G®A5
+žA$õÃAÌÍAÌÍA£×@èõÃ@ÈõÃ@È£×@šQì@  @  @O\)@žR?p€?(ö>W
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B"
+B"záB
+záBp€BffB\)B\)BQìBG®B
+G®B=qB33B(öAüQìAô=qAô(öAì(öAä{Aä  AÜ  AÓë
+AË×
+AËÂAÃÂA»®A»A³A«
+A«p€A£\)A\)AG®A33A33A
+žA
+=Av{Aeë
+AUÂAUAEA5p€A5G®A%G®A
+žAõÃAÌÍ@é@ÉG®@ÈõÃ@šõÃ@£×@Qì@P  @  ?žR?p€>k
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+
+BzáBzáBp€BffB\)B\)B
+QìBG®BG®B=qAüffAôQìAôQìAì=qAä(öAä(öAÜ{AÔ  AÌ  AËë
+AÃ×
+A»ÂA»ÂA³®A«A«A£
+Ap€A\)A\)AG®A33A33Av=qAf{AV{AUë
+AEÂA5A5A%p€AG®AG®A
+ž@éë
+@É@É@©G®@õÃ@õÃ@QG®@£×?   ?   >uÂ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+BzáBzáBp€BffB
+\)B\)BQìBG®Aü\AôzáAôffAìQìAäQìAä=qAÜ(öAÔ(öAÌ{AÌ  AÄ  A»ë
+A»×
+A³ÂA«ÂA«®A£AA
+Ap€A\)A\)AG®AvffAfffAV=qAV{AF{A5ë
+A5ÂA%AAp€AG®@ê\@Ê=q@Éë
+@©@@G®@Që
+@ë
+?¢\?¡G®>  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+BzáBzáB
+p€BffB\)B\)Aü£×Aô\Aô\AìzáAäffAäQìAÜQìAÔ=qAÌ(öAÌ(öAÄ{AŒ  AŒ  A³ë
+A«×
+A«ÂA£ÂA®AAA
+Ap€A\)AvžRAf\AVffAVffAF=qA6{A6{A%ë
+AÂAA@êáH@Ê\@Ê\@ª=q@ë
+@@S33@\?£×
+?£×
+>=q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+B
+záBzáBp€BffAüžRAôžRAô£×Aì\Aä\AäzáAÜffAÔQìAÌQìAÌ=qAÄ(öAŒ(öAŒ{AŽ  A¬  A«ë
+A£×
+AÂAÂA®AAA
+AváHAfžRAVžRAV\AFffA6ffA6=qA&{A{Aë
+AÂ@ë33@Ë33@ÊáH@ª\@\@=q@S×
+@33?Šff?¥
+ž>\)¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+BzáBzáAüáHAôÌÍAôžRAìžRAä£×Aä\AÜ\AÔzáAÌffAÌQìAÄQìAŒ=qAŒ(öAŽ(öA¬{A¬  A€  Aë
+A×
+AÂAÂA®AAw33Ag
+=AVáHAVžRAFžRA6\A6ffA&ffA=qA{A{@ë×
+@Ë
+@Ë33@«33@áH@\@U
+ž@zá?§®?Šff>¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  B
+AüõÃAôõÃAôáHAìÌÍAäžRAäžRAÜ£×AÔ\AÌ\AÌzáAÄffAŒQìAŒQìAŽ=qA¬(öA¬(öA€{A  A  Aë
+A×
+AÂAÂAw\)Ag33AW33AW
+=AFáHA6žRA6žRA&\AffAffA=q@ì(ö@Ì(ö@Ë×
+@«
+@33@33@UÂ@
+ž?ª=q?šõÂ>žR¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aõ
+=AôõÃAìõÃAäáHAäÌÍAÜžRAÔžRAÌ£×AÌ\AÄ\AŒzáAŒffAŽQìA¬QìA¬=qA€(öA(öA{A  A  Aë
+A×
+Aw
+Ag
+AW\)AW33AG33A7
+=A6áHA&žRAžRA\Aff@ìÌÍ@Ìzá@Ì(ö@¬(ö@×
+@
+@Vff@ff?«
+?ª=q>šõÃ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aí
+=AäõÃAäõÃAÜáHAÔÌÍAÌžRAÌžRAÄ£×AŒ\AŒ\AŽzáA¬ffA¬QìA€QìA=qA(öA(öA{A  A  Aw×
+Ag®AW
+AW
+AG\)A733A733A'
+=AáHAžRAžR@í
+ž@ÌÌÍ@ÌÌÍ@¬zá@(ö@(ö@W®@
+>?¬ÌÍ?¬ÌÍ>®{¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aå
+=AÜõÃAÔõÃAÌáHAÌÌÍAÄžRAŒžRAŒ£×AŽ\A¬\A¬záA€ffAQìAQìA=qA(öA(öA{Ax  Ah  AW×
+AW®AG
+A7
+A7\)A'33A33A
+=AáH@íp€@Íp€@Í
+ž@¬ÌÍ@ÌÍ@zá@XQì@Qì?¯\)?®{>³33¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÕ
+=AÌõÃAÌõÃAÄáHAŒÌÍAŒžRAŽžRA¬£×A¬\A€\AzáAffAQìAQìA=qA(öAxQìAh(öAX  AX  AG×
+A7®A7
+A'
+A\)A33A33@î{@ÍÂ@Íp€@­p€@
+ž@ÌÍ@Y@õÂ?°£×?°£×>œp€¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AÍ
+=AÄõÃAŒõÃAŒáHAŽÌÍA¬žRA¬žRA€£×A\A\AzáAffAQìAQìAxzáAhQìAXQìAX(öAH  A8  A7×
+A'®A
+A
+A\)@îff@Îff@Î{@­Â@p€@p€@Z=q@?³33?±ë
+>Â\¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aœ
+=AŒõÃAŽõÃA¬áHA¬ÌÍA€žRAžRA£×A\A\AzáAffAx£×Ah£×AXzáAXQìAHQìA8(öA8  A(  A×
+A®A
+@ï
+=@ÎžR@Îff@®ff@{@Â@ZáH@áH?Žzá?³33>ÌÌÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Aµ
+=A¬õÃA¬õÃA€áHAÌÍAžRAžRA£×A\A\AxõÃAhÌÍAX£×AX£×AHzáA8QìA8QìA((öA  A  A×
+@ï\)@Ï
+=@Ï
+=@®žR@ff@ff@\(ö@
+?µÂ?µÂ>Ñë
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A­
+=A€õÃAõÃAáHAÌÍAžRAžRA£×Ay
+žAi
+žAXõÃAXÌÍAH£×A8£×A8záA(QìAQìA(öA  @ð  @Ï®@Ï\)@¯
+=@
+=@žR@\ÌÍ@
+ÌÍ?žQì?·
+>>×
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+=AõÃAõÃAáHAÌÍAžRAyp€AiG®AY
+žAY
+žAHõÃA8ÌÍA8£×A(£×AzáAQìAQì@ðQì@Ð  @Ð  @¯®@\)@
+=@^{@
+p€?¹?¹>áG®¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+=AõÃAõÃAáHAyAip€AYp€AYG®AI
+žA9
+žA8õÃA(ÌÍA£×A£×Azá@ð£×@Ð£×@ÐQì@°  @  @®@^žR@
+{?Œ(ö?ºáH>æff¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+
+=AõÃAyë
+AiÂAYAYp€AIp€A9G®A9
+žA)
+žAõÃAÌÍA£×@ñG®@ÐõÂ@Ð£×@°£×@Qì@  @`  @\)?œp€?Œ(ö>ð£×¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  Az{Aië
+AYë
+AYÂAIA9p€A9p€A)G®A
+žA
+žAõÃ@ñ@ÑG®@ÑG®@°õÂ@£×@£×@`£×@   ?À  ?ŸžR>õÂ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AZ{AYë
+AIë
+A9ÂA9A)p€Ap€AG®A	
+ž@ò=q@Ñë
+@Ñ@±G®@G®@õÂ@aG®@!G®?ÁG®?À  ?   ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  AJ{A9ë
+A9ë
+A)ÂAAp€A	p€@ò\@Ò=q@Ò=q@±ë
+@@G®@b\@!ë
+?Â\?Â\?\¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A:{A)ë
+Aë
+AÂA	@òáH@ÒáH@Ò\@²=q@=q@ë
+@c33@"\?Å
+ž?Ã×
+?
+ž¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A{Aë
+A	ë
+@ó
+@Ó33@ÒáH@²áH@\@=q@dzá@#×
+?Æff?Å
+ž?
+=q¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  A
+{@ó×
+@Ó×
+@Ó
+@³33@áH@áH@e
+ž@$zá?ÈõÂ?Ç®?
+ÌÍ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @Ô(ö@Ó×
+@³×
+@
+@33@eÂ@%Â?Ê=p?ÈõÂ?ë
+¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @Ž(ö@×
+@×
+@g
+>@&ff?Ë
+
+?Ë
+
+?zá¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @(ö@g®@'®?Î{?ÌÌÍ?
+=¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  @(Qì?Ï\)?Ï\)?
+(ö¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ?Ð£×?
+žR¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿  ¿                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             B~
+B~záB~p€B~ffB~\)B~QìB~G®B~=qB~33B~(öB~
+žB~{B~
+=B~  B}õÃB}ë
+B}áHB}×
+B}ÌÍB}ÂB}žRB}®B}£×B}B}\B}
+B}záB}p€B}ffB}\)B}QìB}G®B}=qB}33B}(öB}
+žB}{B}
+=B}  B|õÃB|ë
+B|áHB|×
+B|ÌÍB|ÂB|žRB|®B|£×B|B|\B|
+B|záB|p€B|ffB|\)B|QìB|G®B|=qB|33B|(öB|
+žB|{B|
+=B|  Bz
+BzzáBzp€BzffBz\)BzQìBzG®Bz=qBz33Bz(öBz
+žBz{Bz
+=Bz  ByõÃByë
+ByáHBy×
+ByÌÍByÂByžRBy®By£×ByBy\By
+ByzáByp€ByffBy\)ByQìByG®By=qBy33By(öBy
+žBy{By
+=By  BxõÃBxë
+BxáHBx×
+BxÌÍBxÂBxžRBx®Bx£×BxBx\Bx
+BxzáBxp€BxffBx\)BxQìBxG®Bx=qBx33Bx(öBx
+žBx{Bx
+=Bx  Bv
+BvzáBvp€BvffBv\)BvQìBvG®Bv=qBv33Bv(öBv
+žBv{Bv
+=Bv  BuõÃBuë
+BuáHBu×
+BuÌÍBuÂBužRBu®Bu£×BuBu\Bu
+BuzáBup€BuffBu\)BuQìBuG®Bu=qBu33Bu(öBu
+žBu{Bu
+=Bu  BtõÃBtë
+BtáHBt×
+BtÌÍBtÂBtžRBt®Bt£×BtBt\Bt
+BtzáBtp€BtffBt\)BtQìBtG®Bt=qBt33Bt(öBt
+žBt{Bt
+=Bt  Br
+BrzáBrp€BrffBr\)BrQìBrG®Br=qBr33Br(öBr
+žBr{Br
+=Br  BqõÃBqë
+BqáHBq×
+BqÌÍBqÂBqžRBq®Bq£×BqBq\Bq
+BqzáBqp€BqffBq\)BqQìBqG®Bq=qBq33Bq(öBq
+žBq{Bq
+=Bq  BpõÃBpë
+BpáHBp×
+BpÌÍBpÂBpžRBp®Bp£×BpBp\Bp
+BpzáBpp€BpffBp\)BpQìBpG®Bp=qBp33Bp(öBp
+žBp{Bp
+=Bp  Bn
+BnzáBnp€BnffBn\)BnQìBnG®Bn=qBn33Bn(öBn
+žBn{Bn
+=Bn  BmõÃBmë
+BmáHBm×
+BmÌÍBmÂBmžRBm®Bm£×BmBm\Bm
+BmzáBmp€BmffBm\)BmQìBmG®Bm=qBm33Bm(öBm
+žBm{Bm
+=Bm  BlõÃBlë
+BláHBl×
+BlÌÍBlÂBlžRBl®Bl£×BlBl\Bl
+BlzáBlp€BlffBl\)BlQìBlG®Bl=qBl33Bl(öBl
+žBl{Bl
+=Bl  Bj
+BjzáBjp€BjffBj\)BjQìBjG®Bj=qBj33Bj(öBj
+žBj{Bj
+=Bj  BiõÃBië
+BiáHBi×
+BiÌÍBiÂBižRBi®Bi£×BiBi\Bi
+BizáBip€BiffBi\)BiQìBiG®Bi=qBi33Bi(öBi
+žBi{Bi
+=Bi  BhõÃBhë
+BháHBh×
+BhÌÍBhÂBhžRBh®Bh£×BhBh\Bh
+BhzáBhp€BhffBh\)BhQìBhG®Bh=qBh33Bh(öBh
+žBh{Bh
+=Bh  Bf
+BfzáBfp€BfffBf\)BfQìBfG®Bf=qBf33Bf(öBf
+žBf{Bf
+=Bf  BeõÃBeë
+BeáHBe×
+BeÌÍBeÂBežRBe®Be£×BeBe\Be
+BezáBep€BeffBe\)BeQìBeG®Be=qBe33Be(öBe
+žBe{Be
+=Be  BdõÃBdë
+BdáHBd×
+BdÌÍBdÂBdžRBd®Bd£×BdBd\Bd
+BdzáBdp€BdffBd\)BdQìBdG®Bd=qBd33Bd(öBd
+žBd{Bd
+=Bd  Bb
+BbzáBbp€BbffBb\)BbQìBbG®Bb=qBb33Bb(öBb
+žBb{Bb
+=Bb  BaõÃBaë
+BaáHBa×
+BaÌÍBaÂBažRBa®Ba£×BaBa\Ba
+BazáBap€BaffBa\)BaQìBaG®Ba=qBa33Ba(öBa
+žBa{Ba
+=Ba  B`õÃB`ë
+B`áHB`×
+B`ÌÍB`ÂB`žRB`®B`£×B`B`\B`
+B`záB`p€B`ffB`\)B`QìB`G®B`=qB`33B`(öB`
+žB`{B`
+=B`  B^
+B^záB^p€B^ffB^\)B^QìB^G®B^=qB^33B^(öB^
+žB^{B^
+=B^  B]õÃB]ë
+B]áHB]×
+B]ÌÍB]ÂB]žRB]®B]£×B]B]\B]
+B]záB]p€B]ffB]\)B]QìB]G®B]=qB]33B](öB]
+žB]{B]
+=B]  B\õÃB\ë
+B\áHB\×
+B\ÌÍB\ÂB\žRB\®B\£×B\B\\B\
+B\záB\p€B\ffB\\)B\QìB\G®B\=qB\33B\(öB\
+žB\{B\
+=B\  BZ
+BZzáBZp€BZffBZ\)BZQìBZG®BZ=qBZ33BZ(öBZ
+žBZ{BZ
+=BZ  BYõÃBYë
+BYáHBY×
+BYÌÍBYÂBYžRBY®BY£×BYBY\BY
+BYzáBYp€BYffBY\)BYQìBYG®BY=qBY33BY(öBY
+žBY{BY
+=BY  BXõÃBXë
+BXáHBX×
+BXÌÍBXÂBXžRBX®BX£×BXBX\BX
+BXzáBXp€BXffBX\)BXQìBXG®BX=qBX33BX(öBX
+žBX{BX
+=BX  BV
+BVzáBVp€BVffBV\)BVQìBVG®BV=qBV33BV(öBV
+žBV{BV
+=BV  BUõÃBUë
+BUáHBU×
+BUÌÍBUÂBUžRBU®BU£×BUBU\BU
+BUzáBUp€BUffBU\)BUQìBUG®BU=qBU33BU(öBU
+žBU{BU
+=BU  BTõÃBTë
+BTáHBT×
+BTÌÍBTÂBTžRBT®BT£×BTBT\BT
+BTzáBTp€BTffBT\)BTQìBTG®BT=qBT33BT(öBT
+žBT{BT
+=BT  BR
+BRzáBRp€BRffBR\)BRQìBRG®BR=qBR33BR(öBR
+žBR{BR
+=BR  BQõÃBQë
+BQáHBQ×
+BQÌÍBQÂBQžRBQ®BQ£×BQBQ\BQ
+BQzáBQp€BQffBQ\)BQQìBQG®BQ=qBQ33BQ(öBQ
+žBQ{BQ
+=BQ  BPõÃBPë
+BPáHBP×
+BPÌÍBPÂBPžRBP®BP£×BPBP\BP
+BPzáBPp€BPffBP\)BPQìBPG®BP=qBP33BP(öBP
+žBP{BP
+=BP  BN
+BNzáBNp€BNffBN\)BNQìBNG®BN=qBN33BN(öBN
+žBN{BN
+=BN  BMõÃBMë
+BMáHBM×
+BMÌÍBMÂBMžRBM®BM£×BMBM\BM
+BMzáBMp€BMffBM\)BMQìBMG®BM=qBM33BM(öBM
+žBM{BM
+=BM  BLõÃBLë
+BLáHBL×
+BLÌÍBLÂBLžRBL®BL£×BLBL\BL
+BLzáBLp€BLffBL\)BLQìBLG®BL=qBL33BL(öBL
+žBL{BL
+=BL  BJ
+BJzáBJp€BJffBJ\)BJQìBJG®BJ=qBJ33BJ(öBJ
+žBJ{BJ
+=BJ  BIõÃBIë
+BIáHBI×
+BIÌÍBIÂBIžRBI®BI£×BIBI\BI
+BIzáBIp€BIffBI\)BIQìBIG®BI=qBI33BI(öBI
+žBI{BI
+=BI  BHõÃBHë
+BHáHBH×
+BHÌÍBHÂBHžRBH®BH£×BHBH\BH
+BHzáBHp€BHffBH\)BHQìBHG®BH=qBH33BH(öBH
+žBH{BH
+=BH  BF
+BFzáBFp€BFffBF\)BFQìBFG®BF=qBF33BF(öBF
+žBF{BF
+=BF  BEõÃBEë
+BEáHBE×
+BEÌÍBEÂBEžRBE®BE£×BEBE\BE
+BEzáBEp€BEffBE\)BEQìBEG®BE=qBE33BE(öBE
+žBE{BE
+=BE  BDõÃBDë
+BDáHBD×
+BDÌÍBDÂBDžRBD®BD£×BDBD\BD
+BDzáBDp€BDffBD\)BDQìBDG®BD=qBD33BD(öBD
+žBD{BD
+=BD  BB
+BBzáBBp€BBffBB\)BBQìBBG®BB=qBB33BB(öBB
+žBB{BB
+=BB  BAõÃBAë
+BAáHBA×
+BAÌÍBAÂBAžRBA®BA£×BABA\BA
+BAzáBAp€BAffBA\)BAQìBAG®BA=qBA33BA(öBA
+žBA{BA
+=BA  B@õÃB@ë
+B@áHB@×
+B@ÌÍB@ÂB@žRB@®B@£×B@B@\B@
+B@záB@p€B@ffB@\)B@QìB@G®B@=qB@33B@(öB@
+žB@{B@
+=B@  B>
+B>záB>p€B>ffB>\)B>QìB>G®B>=qB>33B>(öB>
+žB>{B>
+=B>  B=õÃB=ë
+B=áHB=×
+B=ÌÍB=ÂB=žRB=®B=£×B=B=\B=
+B=záB=p€B=ffB=\)B=QìB=G®B==qB=33B=(öB=
+žB={B=
+=B=  B<õÃB<ë
+B<áHB<×
+B<ÌÍB<ÂB<žRB<®B<£×B<B<\B<
+B<záB<p€B<ffB<\)B<QìB<G®B<=qB<33B<(öB<
+žB<{B<
+=B<  B:
+B:záB:p€B:ffB:\)B:QìB:G®B:=qB:33B:(öB:
+žB:{B:
+=B:  B9õÃB9ë
+B9áHB9×
+B9ÌÍB9ÂB9žRB9®B9£×B9B9\B9
+B9záB9p€B9ffB9\)B9QìB9G®B9=qB933B9(öB9
+žB9{B9
+=B9  B8õÃB8ë
+B8áHB8×
+B8ÌÍB8ÂB8žRB8®B8£×B8B8\B8
+B8záB8p€B8ffB8\)B8QìB8G®B8=qB833B8(öB8
+žB8{B8
+=B8  B6
+B6záB6p€B6ffB6\)B6QìB6G®B6=qB633B6(öB6
+žB6{B6
+=B6  B5õÃB5ë
+B5áHB5×
+B5ÌÍB5ÂB5žRB5®B5£×B5B5\B5
+B5záB5p€B5ffB5\)B5QìB5G®B5=qB533B5(öB5
+žB5{B5
+=B5  B4õÃB4ë
+B4áHB4×
+B4ÌÍB4ÂB4žRB4®B4£×B4B4\B4
+B4záB4p€B4ffB4\)B4QìB4G®B4=qB433B4(öB4
+žB4{B4
+=B4  B2
+B2záB2p€B2ffB2\)B2QìB2G®B2=qB233B2(öB2
+žB2{B2
+=B2  B1õÃB1ë
+B1áHB1×
+B1ÌÍB1ÂB1žRB1®B1£×B1B1\B1
+B1záB1p€B1ffB1\)B1QìB1G®B1=qB133B1(öB1
+žB1{B1
+=B1  B0õÃB0ë
+B0áHB0×
+B0ÌÍB0ÂB0žRB0®B0£×B0B0\B0
+B0záB0p€B0ffB0\)B0QìB0G®B0=qB033B0(öB0
+žB0{B0
+=B0  B.
+B.záB.p€B.ffB.\)B.QìB.G®B.=qB.33B.(öB.
+žB.{B.
+=B.  B-õÃB-ë
+B-áHB-×
+B-ÌÍB-ÂB-žRB-®B-£×B-B-\B-
+B-záB-p€B-ffB-\)B-QìB-G®B-=qB-33B-(öB-
+žB-{B-
+=B-  B,õÃB,ë
+B,áHB,×
+B,ÌÍB,ÂB,žRB,®B,£×B,B,\B,
+B,záB,p€B,ffB,\)B,QìB,G®B,=qB,33B,(öB,
+žB,{B,
+=B,  B*
+B*záB*p€B*ffB*\)B*QìB*G®B*=qB*33B*(öB*
+žB*{B*
+=B*  B)õÃB)ë
+B)áHB)×
+B)ÌÍB)ÂB)žRB)®B)£×B)B)\B)
+B)záB)p€B)ffB)\)B)QìB)G®B)=qB)33B)(öB)
+žB){B)
+=B)  B(õÃB(ë
+B(áHB(×
+B(ÌÍB(ÂB(žRB(®B(£×B(B(\B(
+B(záB(p€B(ffB(\)B(QìB(G®B(=qB(33B((öB(
+žB({B(
+=B(  B&
+B&záB&p€B&ffB&\)B&QìB&G®B&=qB&33B&(öB&
+žB&{B&
+=B&  B%õÃB%ë
+B%áHB%×
+B%ÌÍB%ÂB%žRB%®B%£×B%B%\B%
+B%záB%p€B%ffB%\)B%QìB%G®B%=qB%33B%(öB%
+žB%{B%
+=B%  B$õÃB$ë
+B$áHB$×
+B$ÌÍB$ÂB$žRB$®B$£×B$B$\B$
+B$záB$p€B$ffB$\)B$QìB$G®B$=qB$33B$(öB$
+žB${B$
+=B$  B"
+B"záB"p€B"ffB"\)B"QìB"G®B"=qB"33B"(öB"
+žB"{B"
+=B"  B!õÃB!ë
+B!áHB!×
+B!ÌÍB!ÂB!žRB!®B!£×B!B!\B!
+B!záB!p€B!ffB!\)B!QìB!G®B!=qB!33B!(öB!
+žB!{B!
+=B!  B õÃB ë
+B áHB ×
+B ÌÍB ÂB žRB ®B £×B B \B 
+B záB p€B ffB \)B QìB G®B =qB 33B (öB 
+žB {B 
+=B   B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+=B
+  B
+õÃB
+ë
+B
+áHB
+×
+B
+ÌÍB
+ÂB
+žRB
+®B
+£×B
+B
+\B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B
+
+B
+záB
+p€B
+ffB
+\)B
+QìB
+G®B
+=qB
+33B
+(öB
+
+žB
+{B
+
+=B
+  B	õÃB	ë
+B	áHB	×
+B	ÌÍB	ÂB	žRB	®B	£×B	B	\B	
+B	záB	p€B	ffB	\)B	QìB	G®B	=qB	33B	(öB	
+žB	{B	
+=B	  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  BõÃBë
+BáHB×
+BÌÍBÂBžRB®B£×BB\B
+BzáBp€BffB\)BQìBG®B=qB33B(öB
+žB{B
+=B  B õÃB ë
+B áHB ×
+B ÌÍB ÂB žRB ®B £×B B \B 
+B záB p€B ffB \)B QìB G®B =qB 33B (öB 
+žB {B 
+=B   Aý
+=AüõÃAüáHAüÌÍAüžRAü£×Aü\AüzáAüffAüQìAü=qAü(öAü{Aü  Aûë
+Aû×
+AûÂAû®AûAû
+Aûp€Aû\)AûG®Aû33Aû
+žAû
+=AúõÃAúáHAúÌÍAúžRAú£×Aú\AúzáAúffAúQìAú=qAú(öAú{Aú  Aùë
+Aù×
+AùÂAù®AùAù
+Aùp€Aù\)AùG®Aù33Aù
+žAù
+=AøõÃAøáHAøÌÍAøžRAø£×Aø\AøzáAøffAøQìAø=qAø(öAø{Aø  Aõ
+=AôõÃAôáHAôÌÍAôžRAô£×Aô\AôzáAôffAôQìAô=qAô(öAô{Aô  Aóë
+Aó×
+AóÂAó®AóAó
+Aóp€Aó\)AóG®Aó33Aó
+žAó
+=AòõÃAòáHAòÌÍAòžRAò£×Aò\AòzáAòffAòQìAò=qAò(öAò{Aò  Añë
+Añ×
+AñÂAñ®AñAñ
+Añp€Añ\)AñG®Añ33Añ
+žAñ
+=AðõÃAðáHAðÌÍAðžRAð£×Að\AðzáAðffAðQìAð=qAð(öAð{Að  Aí
+=AìõÃAìáHAìÌÍAìžRAì£×Aì\AìzáAìffAìQìAì=qAì(öAì{Aì  Aëë
+Aë×
+AëÂAë®AëAë
+Aëp€Aë\)AëG®Aë33Aë
+žAë
+=AêõÃAêáHAêÌÍAêžRAê£×Aê\AêzáAêffAêQìAê=qAê(öAê{Aê  Aéë
+Aé×
+AéÂAé®AéAé
+Aép€Aé\)AéG®Aé33Aé
+žAé
+=AèõÃAèáHAèÌÍAèžRAè£×Aè\AèzáAèffAèQìAè=qAè(öAè{Aè  Aå
+=AäõÃAäáHAäÌÍAäžRAä£×Aä\AäzáAäffAäQìAä=qAä(öAä{Aä  Aãë
+Aã×
+AãÂAã®AãAã
+Aãp€Aã\)AãG®Aã33Aã
+žAã
+=AâõÃAâáHAâÌÍAâžRAâ£×Aâ\AâzáAâffAâQìAâ=qAâ(öAâ{Aâ  Aáë
+Aá×
+AáÂAá®AáAá
+Aáp€Aá\)AáG®Aá33Aá
+žAá
+=AàõÃAàáHAàÌÍAàžRAà£×Aà\AàzáAàffAàQìAà=qAà(öAà{Aà  AÝ
+=AÜõÃAÜáHAÜÌÍAÜžRAÜ£×AÜ\AÜzáAÜffAÜQìAÜ=qAÜ(öAÜ{AÜ  AÛë
+AÛ×
+AÛÂAÛ®AÛAÛ
+AÛp€AÛ\)AÛG®AÛ33AÛ
+žAÛ
+=AÚõÃAÚáHAÚÌÍAÚžRAÚ£×AÚ\AÚzáAÚffAÚQìAÚ=qAÚ(öAÚ{AÚ  AÙë
+AÙ×
+AÙÂAÙ®AÙAÙ
+AÙp€AÙ\)AÙG®AÙ33AÙ
+žAÙ
+=AØõÃAØáHAØÌÍAØžRAØ£×AØ\AØzáAØffAØQìAØ=qAØ(öAØ{AØ  AÕ
+=AÔõÃAÔáHAÔÌÍAÔžRAÔ£×AÔ\AÔzáAÔffAÔQìAÔ=qAÔ(öAÔ{AÔ  AÓë
+AÓ×
+AÓÂAÓ®AÓAÓ
+AÓp€AÓ\)AÓG®AÓ33AÓ
+žAÓ
+=AÒõÃAÒáHAÒÌÍAÒžRAÒ£×AÒ\AÒzáAÒffAÒQìAÒ=qAÒ(öAÒ{AÒ  AÑë
+AÑ×
+AÑÂAÑ®AÑAÑ
+AÑp€AÑ\)AÑG®AÑ33AÑ
+žAÑ
+=AÐõÃAÐáHAÐÌÍAÐžRAÐ£×AÐ\AÐzáAÐffAÐQìAÐ=qAÐ(öAÐ{AÐ  AÍ
+=AÌõÃAÌáHAÌÌÍAÌžRAÌ£×AÌ\AÌzáAÌffAÌQìAÌ=qAÌ(öAÌ{AÌ  AËë
+AË×
+AËÂAË®AËAË
+AËp€AË\)AËG®AË33AË
+žAË
+=AÊõÃAÊáHAÊÌÍAÊžRAÊ£×AÊ\AÊzáAÊffAÊQìAÊ=qAÊ(öAÊ{AÊ  AÉë
+AÉ×
+AÉÂAÉ®AÉAÉ
+AÉp€AÉ\)AÉG®AÉ33AÉ
+žAÉ
+=AÈõÃAÈáHAÈÌÍAÈžRAÈ£×AÈ\AÈzáAÈffAÈQìAÈ=qAÈ(öAÈ{AÈ  AÅ
+=AÄõÃAÄáHAÄÌÍAÄžRAÄ£×AÄ\AÄzáAÄffAÄQìAÄ=qAÄ(öAÄ{AÄ  AÃë
+AÃ×
+AÃÂAÃ®AÃAÃ
+AÃp€AÃ\)AÃG®AÃ33AÃ
+žAÃ
+=AÂõÃAÂáHAÂÌÍAÂžRAÂ£×AÂ\AÂzáAÂffAÂQìAÂ=qAÂ(öAÂ{AÂ  AÁë
+AÁ×
+AÁÂAÁ®AÁAÁ
+AÁp€AÁ\)AÁG®AÁ33AÁ
+žAÁ
+=AÀõÃAÀáHAÀÌÍAÀžRAÀ£×AÀ\AÀzáAÀffAÀQìAÀ=qAÀ(öAÀ{AÀ  Aœ
+=AŒõÃAŒáHAŒÌÍAŒžRAŒ£×AŒ\AŒzáAŒffAŒQìAŒ=qAŒ(öAŒ{AŒ  A»ë
+A»×
+A»ÂA»®A»A»
+A»p€A»\)A»G®A»33A»
+žA»
+=AºõÃAºáHAºÌÍAºžRAº£×Aº\AºzáAºffAºQìAº=qAº(öAº{Aº  A¹ë
+A¹×
+A¹ÂA¹®A¹A¹
+A¹p€A¹\)A¹G®A¹33A¹
+žA¹
+=AžõÃAžáHAžÌÍAžžRAž£×Až\AžzáAžffAžQìAž=qAž(öAž{Až  Aµ
+=AŽõÃAŽáHAŽÌÍAŽžRAŽ£×AŽ\AŽzáAŽffAŽQìAŽ=qAŽ(öAŽ{AŽ  A³ë
+A³×
+A³ÂA³®A³A³
+A³p€A³\)A³G®A³33A³
+žA³
+=A²õÃA²áHA²ÌÍA²žRA²£×A²\A²záA²ffA²QìA²=qA²(öA²{A²  A±ë
+A±×
+A±ÂA±®A±A±
+A±p€A±\)A±G®A±33A±
+žA±
+=A°õÃA°áHA°ÌÍA°žRA°£×A°\A°záA°ffA°QìA°=qA°(öA°{A°  A­
+=A¬õÃA¬áHA¬ÌÍA¬žRA¬£×A¬\A¬záA¬ffA¬QìA¬=qA¬(öA¬{A¬  A«ë
+A«×
+A«ÂA«®A«A«
+A«p€A«\)A«G®A«33A«
+žA«
+=AªõÃAªáHAªÌÍAªžRAª£×Aª\AªzáAªffAªQìAª=qAª(öAª{Aª  A©ë
+A©×
+A©ÂA©®A©A©
+A©p€A©\)A©G®A©33A©
+žA©
+=AšõÃAšáHAšÌÍAšžRAš£×Aš\AšzáAšffAšQìAš=qAš(öAš{Aš  A¥
+=A€õÃA€áHA€ÌÍA€žRA€£×A€\A€záA€ffA€QìA€=qA€(öA€{A€  A£ë
+A£×
+A£ÂA£®A£A£
+A£p€A£\)A£G®A£33A£
+žA£
+=A¢õÃA¢áHA¢ÌÍA¢žRA¢£×A¢\A¢záA¢ffA¢QìA¢=qA¢(öA¢{A¢  A¡ë
+A¡×
+A¡ÂA¡®A¡A¡
+A¡p€A¡\)A¡G®A¡33A¡
+žA¡
+=A õÃA áHA ÌÍA žRA £×A \A záA ffA QìA =qA (öA {A   A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  A
+
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Aë
+A×
+AÂA®AA
+Ap€A\)AG®A33A
+žA
+=AõÃAáHAÌÍAžRA£×A\AzáAffAQìA=qA(öA{A  Az{Ayë
+AyÂAyAyp€AyG®Ay
+žAxõÃAxÌÍAx£×AxzáAxQìAx(öAx  Aw×
+Aw®Aw
+Aw\)Aw33Aw
+=AváHAvžRAv\AvffAv=qAv{Auë
+AuÂAuAup€AuG®Au
+žAtõÃAtÌÍAt£×AtzáAtQìAt(öAt  As×
+As®As
+As\)As33As
+=AráHAržRAr\ArffAr=qAr{Aqë
+AqÂAqAqp€AqG®Aq
+žApõÃApÌÍAp£×ApzáApQìAp(öAp  Aj{Aië
+AiÂAiAip€AiG®Ai
+žAhõÃAhÌÍAh£×AhzáAhQìAh(öAh  Ag×
+Ag®Ag
+Ag\)Ag33Ag
+=AfáHAfžRAf\AfffAf=qAf{Aeë
+AeÂAeAep€AeG®Ae
+žAdõÃAdÌÍAd£×AdzáAdQìAd(öAd  Ac×
+Ac®Ac
+Ac\)Ac33Ac
+=AbáHAbžRAb\AbffAb=qAb{Aaë
+AaÂAaAap€AaG®Aa
+žA`õÃA`ÌÍA`£×A`záA`QìA`(öA`  AZ{AYë
+AYÂAYAYp€AYG®AY
+žAXõÃAXÌÍAX£×AXzáAXQìAX(öAX  AW×
+AW®AW
+AW\)AW33AW
+=AVáHAVžRAV\AVffAV=qAV{AUë
+AUÂAUAUp€AUG®AU
+žATõÃATÌÍAT£×ATzáATQìAT(öAT  AS×
+AS®AS
+AS\)AS33AS
+=ARáHARžRAR\ARffAR=qAR{AQë
+AQÂAQAQp€AQG®AQ
+žAPõÃAPÌÍAP£×APzáAPQìAP(öAP  AJ{AIë
+AIÂAIAIp€AIG®AI
+žAHõÃAHÌÍAH£×AHzáAHQìAH(öAH  AG×
+AG®AG
+AG\)AG33AG
+=AFáHAFžRAF\AFffAF=qAF{AEë
+AEÂAEAEp€AEG®AE
+žADõÃADÌÍAD£×ADzáADQìAD(öAD  AC×
+AC®AC
+AC\)AC33AC
+=ABáHABžRAB\ABffAB=qAB{AAë
+AAÂAAAAp€AAG®AA
+žA@õÃA@ÌÍA@£×A@záA@QìA@(öA@  A:{A9ë
+A9ÂA9A9p€A9G®A9
+žA8õÃA8ÌÍA8£×A8záA8QìA8(öA8  A7×
+A7®A7
+A7\)A733A7
+=A6áHA6žRA6\A6ffA6=qA6{A5ë
+A5ÂA5A5p€A5G®A5
+žA4õÃA4ÌÍA4£×A4záA4QìA4(öA4  A3×
+A3®A3
+A3\)A333A3
+=A2áHA2žRA2\A2ffA2=qA2{A1ë
+A1ÂA1A1p€A1G®A1
+žA0õÃA0ÌÍA0£×A0záA0QìA0(öA0  A*{A)ë
+A)ÂA)A)p€A)G®A)
+žA(õÃA(ÌÍA(£×A(záA(QìA((öA(  A'×
+A'®A'
+A'\)A'33A'
+=A&áHA&žRA&\A&ffA&=qA&{A%ë
+A%ÂA%A%p€A%G®A%
+žA$õÃA$ÌÍA$£×A$záA$QìA$(öA$  A#×
+A#®A#
+A#\)A#33A#
+=A"áHA"žRA"\A"ffA"=qA"{A!ë
+A!ÂA!A!p€A!G®A!
+žA õÃA ÌÍA £×A záA QìA (öA   A{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A
+{A	ë
+A	ÂA	A	p€A	G®A	
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žAõÃAÌÍA£×AzáAQìA(öA  A×
+A®A
+A\)A33A
+=AáHAžRA\AffA=qA{Aë
+AÂAAp€AG®A
+žA õÃA ÌÍA £×A záA QìA (öA   @ô(ö@ó×
+@ó
+@ó33@òáH@ò\@ò=q@ñë
+@ñ@ñG®@ðõÂ@ð£×@ðQì@ð  @ï®@ï\)@ï
+=@îžR@îff@î{@íÂ@íp€@í
+ž@ìÌÍ@ìzá@ì(ö@ë×
+@ë
+@ë33@êáH@ê\@ê=q@éë
+@é@éG®@èõÃ@è£×@èQì@è  @ç®@ç\)@ç
+=@æžR@æff@æ{@åÂ@åp€@å
+ž@äÌÍ@äzá@ä(ö@ã×
+@ã
+@ã33@âáH@â\@â=q@áë
+@á@áG®@àõÃ@à£×@àQì@à  @Ô(ö@Ó×
+@Ó
+@Ó33@ÒáH@Ò\@Ò=q@Ñë
+@Ñ@ÑG®@ÐõÂ@Ð£×@ÐQì@Ð  @Ï®@Ï\)@Ï
+=@ÎžR@Îff@Î{@ÍÂ@Íp€@Í
+ž@ÌÌÍ@Ìzá@Ì(ö@Ë×
+@Ë
+@Ë33@ÊáH@Ê\@Ê=q@Éë
+@É@ÉG®@ÈõÃ@È£×@ÈQì@È  @Ç®@Ç\)@Ç
+=@ÆžR@Æff@Æ{@ÅÂ@Åp€@Å
+ž@ÄÌÍ@Äzá@Ä(ö@Ã×
+@Ã
+@Ã33@ÂáH@Â\@Â=q@Áë
+@Á@ÁG®@ÀõÃ@À£×@ÀQì@À  @Ž(ö@³×
+@³
+@³33@²áH@²\@²=q@±ë
+@±@±G®@°õÂ@°£×@°Qì@°  @¯®@¯\)@¯
+=@®žR@®ff@®{@­Â@­p€@­
+ž@¬ÌÍ@¬zá@¬(ö@«×
+@«
+@«33@ªáH@ª\@ª=q@©ë
+@©@©G®@šõÃ@š£×@šQì@š  @§®@§\)@§
+=@ŠžR@Šff@Š{@¥Â@¥p€@¥
+ž@€ÌÍ@€zá@€(ö@£×
+@£
+@£33@¢áH@¢\@¢=q@¡ë
+@¡@¡G®@ õÃ@ £×@ Qì@   @(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÂ@£×@Qì@  @®@\)@
+=@žR@ff@{@Â@p€@
+ž@ÌÍ@zá@(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÃ@£×@Qì@  @®@\)@
+=@žR@ff@{@
+Â@
+p€@
+
+ž@ÌÍ@zá@(ö@×
+@
+@33@áH@\@=q@ë
+@@G®@õÃ@£×@Qì@  @hQì@g®@g
+>@fff@eÂ@e
+ž@dzá@c×
+@c33@b\@aë
+@aG®@`£×@`  @_\)@^žR@^{@]p€@\ÌÍ@\(ö@[
+@ZáH@Z=q@Y@XõÂ@XQì@W®@W
+>@Vff@UÂ@U
+ž@Tzá@S×
+@S33@R\@Që
+@QG®@P£×@P  @O\)@NžR@N{@Mp€@LÌÍ@L(ö@K
+@JáH@J=q@I@HõÃ@HQì@G®@G
+=@Fff@EÂ@E
+ž@Dzá@C×
+@C33@B\@Aë
+@AG®@@£×@@  @(Qì@'®@'
+>@&ff@%Â@%
+ž@$zá@#×
+@#33@"\@!ë
+@!G®@ £×@   @\)@
+žR@
+{@
+p€@
+ÌÍ@
+(ö@
+@áH@=q@@õÂ@Qì@®@
+>@ff@Â@
+ž@zá@×
+@33@\@ë
+@G®@£×@  @\)@žR@{@
+p€@
+ÌÍ@
+(ö@
+
+@
+áH@
+=q@	@õÃ@Qì@®@
+=@ff@Â@
+ž@zá@×
+@33@\@ë
+@G®@ £×@   ?Ð£×?Ï\)?Î{?ÌÌÍ?Ë
+
+?Ê=p?ÈõÂ?Ç®?Æff?Å
+ž?Ã×
+?Â\?ÁG®?À  ?ŸžR?œp€?Œ(ö?ºáH?¹?žQì?·
+>?µÂ?Žzá?³33?±ë
+?°£×?¯\)?®{?¬ÌÍ?«
+?ª=q?šõÂ?§®?Šff?¥
+ž?£×
+?¢\?¡G®?   ?žR?p€?(ö?áH??Qì?
+>?Â?zá?33?ë
+?£×?\)?{?ÌÍ?
+?=q?õÃ?®?ff?
+
+ž?×
+?\?G®?  ?!G®?
+žR?
+(ö??
+=?zá?ë
+?\)?
+ÌÍ?
+=q?®?
+ž?\?   >úáH>õÂ>ð£×>ë
+>æff>áG®>Ü(ö>×
+=>Ñë
+>ÌÌÍ>Ç®>Â\>œp€>žQì>³33>®{>šõÃ>£×
+>žR>>zá>\)>=q>
+
+ž>  >uÂ>k
+>aG®>W
+=>LÌÍ>B\>8Qì>.{>#×
+>>\)>
+ž=õÂ=áG®=ÌÌÍ=žQì=£×
+=\)=uÂ=LÌÍ=#×
+<õÂ<£×
+<#×
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/verified/sBiOut.fits
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/verified/sBiOut.fits	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/verified/sBiOut.fits	(revision 22158)
@@ -0,0 +1,1414 @@
+SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ; = ?ÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 : < >ÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ; =ÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 : <ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ;ÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 :ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9ÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6ÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - /ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , .ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + -ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * ,ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) +ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( *ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' )ÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & (ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % 'ÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ &ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # %ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! #ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   "ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  !ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+  ÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+ ÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+ÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+ÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+       ÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+       ÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+      ÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+      ÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+     ÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+     ÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+    ÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+    ÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+   ÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+   ÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+  ÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+  ÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+ ÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+ ÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+ÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+ÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	ÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ      ÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ    ÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ    ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ   ÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ                                                                                                                                                                                                                                                                                                                                                                                                                                                                  XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÁÿÂÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀÿÁÿÃÿÄÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿ÿ¿ÿÂÿÄÿÆÿÇÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿœÿŸÿÀÿÂÿÄÿÆÿÉÿÊÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŒÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¹ÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿžÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÕÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¶ÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿØÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿµÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ³ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ°ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿæÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿéÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ«ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ©ÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿšÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ§ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿ÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¥ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ      ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+      ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  !ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % &ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ & ( )ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ & ( + ,ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % ' ) + - /ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ & ( * , . 0 2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ & ( + - / 1 3 5ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % ' ) + - 0 2 4 6 7ÿÿÿÿÿÿÿÿÿ
+ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ & ( * , . 0 2 4 7 9 :ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ & ( + - / 1 3 5 7 9 < =ÿÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % ' ) + - 0 2 4 6 8 : < >ÿÿÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ & ( * , . 0 2 4 7 9 ; = >ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ & ( + - / 1 3 5 7 9 < <ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % ' ) + - 0 2 4 6 8 : ;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ & ( * , . 0 2 4 7 9 :ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ & ( + - / 1 3 5 7 8ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % ' ) + - 0 2 4 6 7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ & ( * , . 0 2 4 5ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ & ( + - / 1 3 4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % ' ) + - 0 2 2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ & ( * , . 0 1ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ & ( + - / 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % ' ) + - .ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŠÿ§ÿ©ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ & ( * , -ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ©ÿªÿ¬ÿ®ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ & ( + +ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬ÿ­ÿ¯ÿ±ÿ³ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % ' ) *ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ & ( )ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " $ & 'ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! # % &ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ·ÿžÿºÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+  ! $ $ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºÿ»ÿœÿ¿ÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+   " #ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿœÿŸÿÀÿÂÿÄÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+  ! !ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       
+ 
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅÿÆÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+        
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÿÉÿËÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËÿÌÿÎÿÐÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+       ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÎÿÏÿÑÿÓÿÕÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+       ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÐÿÒÿÔÿÖÿØÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+      ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖÿ×ÿÚÿÜÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙÿÚÿÜÿßÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÜÿÝÿßÿáÿãÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞÿàÿâÿäÿæÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿáÿãÿåÿçÿéÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿäÿæÿèÿêÿìÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 
+ 
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçÿèÿëÿíÿïÿñÿóÿõÿ÷ÿùÿüÿþ       	 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿêÿëÿíÿïÿòÿôÿöÿøÿúÿüÿþ       
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíÿîÿðÿòÿôÿ÷ÿùÿûÿýÿÿ      	 	ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïÿñÿóÿõÿ÷ÿùÿüÿþ       ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòÿôÿöÿøÿúÿüÿþ      ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõÿ÷ÿùÿûÿýÿÿ     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿùÿüÿþ     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûÿüÿþ    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ   ÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ     ÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ       ÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ         ÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	ÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+ÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+  ÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+    ÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+      ÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+        ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+          ÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+            ÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+              ÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+ ÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    !ÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " #ÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ %ÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & 'ÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( )ÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * +ÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , -ÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . /ÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1ÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3ÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7ÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9ÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ;ÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < =           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ?                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿ
+ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¥ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿªÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ­ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ°ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ³ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»ÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÁÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÄÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ¢ÿ£ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿŠÿ¥ÿŠÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÌÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ§ÿ§ÿ§ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÏÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿ©ÿšÿ©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÒÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ©ÿªÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÕÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿ¬ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ­ÿ¬ÿ­ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ®ÿ®ÿ®ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÝÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ±ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿ³ÿ²ÿ³ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿæÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿ³ÿŽÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿµÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿ·ÿ¶ÿ·ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿîÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿžÿžÿžÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿºÿ¹ÿºÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿºÿ»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷ÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿœÿÿÿÿÿÿÿÿÿÿÿÿÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿŸÿœÿŸÿÿÿÿÿÿÿÿÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿ¿ÿ¿ÿ¿ÿÿÿÿÿÿÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿÁ      ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÿ         ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÆÿÅÿÄÿÃÿÿÿÿ          ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÉÿÈÿÇÿÆÿÿÿÿÿÿÿÿ            ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿËÿËÿÊÿÉÿÿÿÿÿÿÿÿÿÿÿÿ              ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÎÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                  ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÑÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 	 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿ×ÿÖÿÕÿÔÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÚÿÙÿØÿ×ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÜÿÜÿÛÿÚÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+  
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿàÿßÿßÿÞÿÜÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿãÿâÿáÿáÿßÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ       
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿæÿåÿäÿãÿâÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ         
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿèÿçÿæÿåÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ           
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿëÿêÿéÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ             
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿîÿíÿíÿìÿëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ               
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿñÿðÿïÿïÿíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                 
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿôÿóÿòÿòÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                   
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿ÷ÿöÿõÿôÿóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                     
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿùÿøÿ÷ÿöÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+                     
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿüÿûÿúÿùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+ 
+ 	 	                 ÿÿÿþÿþÿýÿüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+  
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+ 
+ 	 	                 ÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+ 
+ 	 	            ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ! ! !     
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+ 
+ 	 	       ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ " # " ! !     
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+ 
+ 	 	   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ $ $ $ # " ! !     
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+ 
+ 	ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ % & % $ $ # " ! !     
+ 
+ 
+ 
+                     
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ & ' & & % $ $ # " ! !     
+ 
+ 
+ 
+                  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ( ( ( ' & & % $ $ # " ! !     
+ 
+ 
+ 
+              ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ) * ) ( ( ' & & % $ $ # " ! !     
+ 
+ 
+ 
+          ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ + + + * ) ( ( ' & & % $ $ # " ! !     
+ 
+ 
+ 
+      ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ , - , + + * ) ( ( ' & & % $ $ # " ! !     
+ 
+ 
+ 
+  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ - . - - , + + * ) ( ( ' & & % $ $ # " ! !     
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ / 0 / . - - , + + * ) ( ( ' & & % $ $ # " ! ! ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0 1 0 0 / . - - , + + * ) ( ( ' & & % $ $ "ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 2 2 2 1 0 0 / . - - , + + * ) ( ( ' & %ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 3 4 3 2 2 1 0 0 / . - - , + + * ) (ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 5 5 4 4 3 2 2 1 0 0 / . - - , +ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 6 7 6 5 4 4 3 2 2 1 0 0 / -ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 7 8 7 7 6 5 4 4 3 2 2 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 9 9 9 8 7 7 6 5 4 3ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ : ; : 9 9 8 7 6ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ < < < ; : 9ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ = > = <ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ > >ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿ   ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+    ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿ   ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿ     ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿ    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿ      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿ 
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿ 
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿ  
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿ  
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿ   
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿ   
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿ    
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿ    
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿ     
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿ     
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿ      
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿ      
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿ       
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿ       
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿ        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿ        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿ 
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿ 
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ   
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠ % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿš ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ© ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿª ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ« * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ® - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ° / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ± 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ² 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽ 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµ 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ· 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿž 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ 8 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿº 9 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ» : 8 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒ ; 9 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœ < : 8 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸ = ; 9 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ > < : 8 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀ ? = ; 9 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁ                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   ÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    ÿþÿüÿûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     ÿþÿüÿùÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     ÿÿÿýÿûÿùÿ÷ÿõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      ÿþÿüÿúÿøÿöÿôÿòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ       ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 	 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿçÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿäÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÜÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿÙÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ       
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÎÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ        
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÅÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ! !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿœÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ # "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿºÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ $ $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ·ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ & % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ' & $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ) ( & $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ * ) ' % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ¬ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ + + ( & $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿ©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ - , * ( & $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿŠÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ . - + ) ' % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0 / - + ( & $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 1 0 . , * ( & $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 2 2 0 - + ) ' % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 4 3 1 / - + ( & $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 5 4 2 0 . , * ( & $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 7 6 4 2 0 - + ) ' % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 8 7 5 3 1 / - + ( & $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ : 9 7 4 2 0 . , * ( & $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ; : 8 6 4 2 0 - + ) ' % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ < < 9 7 5 3 1 / - + ( & $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ > = ; 9 7 4 2 0 . , * ( & $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿ ? > < : 8 6 4 2 0 - + ) ' % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿÿÿ = < 9 7 5 3 1 / - + ( & $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ : 9 7 4 2 0 . , * ( & $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿ
+ÿÿÿÿÿÿÿÿ 7 6 4 2 0 - + ) ' % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 5 3 1 / - + ( & $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 2 0 . , * ( & $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ / - + ) ' % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ , + ( & $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ) ( & $ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ & % # !  
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ $ "   
+ 
+       
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ !  
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+        
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ        
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ       
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    
+ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 	      ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 	     ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     ÿþÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ¢ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   ÿÿÿýÿûÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  ÿþÿüÿúÿøÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ¥ÿ£ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿüÿùÿ÷ÿõÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúÿùÿ÷ÿôÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿšÿŠÿ¥ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷ÿöÿôÿòÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ©ÿ§ÿ§ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôÿóÿñÿïÿíÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿšÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòÿðÿîÿìÿêÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ¬ÿªÿ©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿ«ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìÿëÿèÿæÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ¯ÿ­ÿ¬ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿéÿèÿæÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ®ÿ®ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿæÿåÿãÿáÿßÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ²ÿ°ÿ¯ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿäÿâÿàÿÞÿÜÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿ³ÿ±ÿ°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿ¶ÿŽÿ³ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÚÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿµÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿØÿ×ÿÕÿÓÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿ¹ÿ·ÿ¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÕÿÔÿÒÿÐÿÎÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿºÿžÿžÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÓÿÑÿÏÿÍÿËÿÉÿÆÿÄÿÂÿÀÿŸÿŒÿºÿ¹ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿ¿ÿœÿ»ÿºÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿŒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÊÿÉÿÆÿÄÿÂÿÀÿŸÿœÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÇÿÆÿÄÿÂÿ¿ÿ¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÄÿÃÿÁÿÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÂÿÁÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              ? > = < ; : 9 8 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	           = < ; : 9 8 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþ ; : 9 8 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿü 9 8 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿú 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿø 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿö 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿô 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿò / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿð - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿî + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿì ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿê ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿè % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿä !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâ  
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿà 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞ               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜ             
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚ           
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØ         
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖ       
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔ     
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒ   
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐ 
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊ         ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈ       ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆ     ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄ   ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ > >ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ < = > =ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 9 : ; < < <ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 6 7 8 9 9 : ; :ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 3 4 5 6 7 7 8 9 9 9ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0 2 2 3 4 4 5 6 7 7 8 7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ - / 0 0 1 2 2 3 4 4 5 6 7 6ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ + , - - . / 0 0 1 2 2 3 4 4 5 5ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ( ) * + + , - - . / 0 0 1 2 2 3 4 3ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ % & ' ( ( ) * + + , - - . / 0 0 1 2 2 2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ " $ $ % & & ' ( ( ) * + + , - - . / 0 0 1 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  ! ! " # $ $ % & & ' ( ( ) * + + , - - . / 0 /ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+     ! ! " # $ $ % & & ' ( ( ) * + + , - - . -ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   
+ 
+ 
+ 
+     ! ! " # $ $ % & & ' ( ( ) * + + , - ,ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ       
+ 
+ 
+ 
+     ! ! " # $ $ % & & ' ( ( ) * + + +ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ           
+ 
+ 
+ 
+     ! ! " # $ $ % & & ' ( ( ) * )ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ               
+ 
+ 
+ 
+     ! ! " # $ $ % & & ' ( ( (ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                   
+ 
+ 
+ 
+     ! ! " # $ $ % & & ' &ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+                     
+ 
+ 
+ 
+     ! ! " # $ $ % & %ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 	 
+ 
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+     ! ! " # $ $ $ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    	 	 
+ 
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+     ! ! " # "ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ        	 	 
+ 
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+     ! ! !ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ             	 	 
+ 
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ                  	 	 
+ 
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+  
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+                     
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+                    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+                  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+                ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+              ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+            ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+          ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿåÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+        ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+      ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÜÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+  
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 
+ 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÔÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  	 	 	ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÑÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÎÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ                ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ              ÿÿÿÿÿÿÿÿÿÿÿÿÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ            ÿÿÿÿÿÿÿÿÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ          ÿÿÿÿÿÃÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ         ÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿþÿÿ    ÿÿÿÁÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿüÿýÿþÿÿÿÿÿÿÿ¿ÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿùÿúÿûÿüÿÿÿÿÿÿÿÿÿŸÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿöÿ÷ÿ÷ÿøÿùÿÿÿÿÿÿÿÿÿÿÿÿÿœÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿóÿôÿôÿõÿ÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»ÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿðÿñÿòÿòÿôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿíÿîÿïÿïÿñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿžÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿëÿìÿíÿîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ·ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿèÿéÿêÿëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿµÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿåÿæÿæÿçÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŽÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿãÿäÿæÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ³ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿßÿàÿáÿáÿãÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ±ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÜÿÝÿÞÿßÿàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ°ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÚÿÛÿÜÿÝÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿ×ÿØÿÙÿÚÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ­ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬ÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÕÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿªÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ©ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿËÿÌÿÍÿÎÿÏÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ§ÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÉÿÊÿËÿÌÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŠÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÆÿÇÿÈÿÉÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ£ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÂÿÂÿÄÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÁÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿºÿ»ÿŒÿœÿŸÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿ»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ¶ÿ¶ÿ·ÿžÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ¯ÿ°ÿ±ÿ±ÿ³ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ®ÿ°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿ©ÿªÿ«ÿ¬ÿ­ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ§ÿšÿ©ÿªÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ¥ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿ
+ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ; = ?ÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 : < >ÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ; =ÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 : <ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ;ÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 :ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9ÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6ÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - /ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , .ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + -ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * ,ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) +ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( *ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' )ÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & (ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % 'ÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ &ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # %ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! #ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   "ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  !ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+  ÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+ ÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+ÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+ÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+       ÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+       ÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+      ÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+      ÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+     ÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+     ÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+    ÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+    ÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+   ÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+   ÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+  ÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+  ÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+ ÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+ ÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+ÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+ÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	ÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ      ÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ    ÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ    ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ   ÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/verified/sOut.fits
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/verified/sOut.fits	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/imageops/verified/sOut.fits	(revision 22158)
@@ -0,0 +1,1450 @@
+SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ; = ?ÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 : < >ÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ; =ÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 : <ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ;ÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 :ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9ÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6ÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - /ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , .ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + -ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * ,ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) +ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( *ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' )ÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & (ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % 'ÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ &ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # %ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! #ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   "ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  !ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+  ÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+ ÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+ÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+ÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+       ÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+       ÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+      ÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+      ÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+     ÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+     ÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+    ÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+    ÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+   ÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+   ÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+  ÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+  ÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+ ÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+ ÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+ÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+ÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	ÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ      ÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ    ÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ    ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ   ÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ                                                                                                                                                                                                                                                                                                                                                                                                                                                                  XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀÿÃÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿ÿÂÿÂÿÅÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿœÿÀÿÁÿÄÿÆÿÉÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŒÿ¿ÿ¿ÿÂÿÅÿÈÿÈÿËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»ÿœÿŸÿÁÿÃÿÆÿÇÿÊÿÌÿÍÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¹ÿŒÿœÿ¿ÿÂÿÅÿÅÿÈÿËÿÌÿÎÿÑÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿžÿºÿ»ÿŸÿÁÿÃÿÄÿÇÿÉÿÊÿÍÿÐÿÒÿÓÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¶ÿ¹ÿºÿŒÿ¿ÿÂÿÃÿÅÿÈÿÉÿËÿÎÿÑÿÒÿÔÿ×ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿµÿžÿžÿ»ÿŸÿÀÿÁÿÄÿÇÿÇÿÊÿÍÿÏÿÐÿÓÿÖÿÖÿÙÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŽÿ¶ÿ·ÿºÿŒÿ¿ÿÀÿÂÿÅÿÆÿÉÿËÿÎÿÏÿÑÿÔÿÕÿØÿÚÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²ÿµÿ¶ÿžÿ»ÿŸÿŸÿÁÿÄÿÄÿÇÿÊÿÍÿÍÿÐÿÓÿÓÿÖÿÙÿÚÿÜÿßÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ±ÿ³ÿŽÿ·ÿºÿŒÿœÿÀÿÂÿÃÿÆÿÈÿËÿÌÿÏÿÑÿÒÿÕÿ×ÿØÿÛÿÞÿàÿáÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯ÿ²ÿ³ÿµÿžÿ»ÿŒÿŸÿÁÿÂÿÄÿÇÿÊÿÊÿÍÿÐÿÑÿÓÿÖÿ×ÿÙÿÜÿßÿàÿâÿåÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ÿ±ÿ±ÿŽÿ·ÿ¹ÿºÿœÿÀÿÀÿÃÿÆÿÈÿÉÿÌÿÎÿÏÿÒÿÕÿÕÿØÿÛÿÝÿÞÿáÿäÿäÿçÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬ÿ¯ÿ°ÿ³ÿµÿžÿ¹ÿ»ÿŸÿ¿ÿÂÿÄÿÇÿÈÿÊÿÍÿÎÿÐÿÓÿÔÿ×ÿÙÿÜÿÝÿßÿâÿãÿæÿèÿëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ«ÿ®ÿ®ÿ±ÿŽÿ·ÿ·ÿºÿœÿœÿÀÿÃÿÆÿÆÿÉÿÌÿÌÿÏÿÒÿÒÿÕÿØÿÛÿÛÿÞÿáÿáÿäÿçÿêÿêÿíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿªÿ¬ÿ­ÿ°ÿ²ÿµÿ¶ÿ¹ÿ»ÿŒÿ¿ÿÁÿÄÿÅÿÈÿÊÿËÿÎÿÐÿÑÿÔÿÖÿÙÿÚÿÝÿßÿàÿãÿåÿèÿéÿìÿîÿïÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿšÿ«ÿ¬ÿ®ÿ±ÿŽÿŽÿ·ÿºÿ»ÿœÿÀÿÃÿÃÿÆÿÉÿÊÿÌÿÏÿÐÿÒÿÕÿØÿØÿÛÿÞÿßÿáÿäÿçÿçÿêÿíÿîÿðÿóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ§ÿªÿªÿ­ÿ°ÿ²ÿ³ÿ¶ÿžÿ¹ÿŒÿ¿ÿÁÿÂÿÅÿÇÿÈÿËÿÎÿÎÿÑÿÔÿÖÿ×ÿÚÿÜÿÝÿàÿãÿåÿæÿéÿëÿìÿïÿòÿòÿõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¥ÿšÿ©ÿ¬ÿ®ÿ±ÿ²ÿŽÿ·ÿžÿºÿœÿÀÿÁÿÃÿÆÿÇÿÉÿÌÿÍÿÐÿÒÿÕÿÖÿØÿÛÿÜÿÞÿáÿäÿåÿçÿêÿëÿíÿðÿñÿôÿöÿùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿ§ÿ§ÿªÿ­ÿ°ÿ°ÿ³ÿ¶ÿ¶ÿ¹ÿŒÿŸÿ¿ÿÂÿÅÿÅÿÈÿËÿËÿÎÿÑÿÔÿÔÿ×ÿÚÿÚÿÝÿàÿâÿãÿæÿéÿéÿìÿïÿïÿòÿõÿøÿøÿûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ£ÿ¥ÿŠÿ©ÿ«ÿ®ÿ¯ÿ²ÿŽÿµÿžÿºÿœÿŸÿÀÿÃÿÄÿÇÿÉÿÊÿÍÿÏÿÒÿÓÿÖÿØÿÙÿÜÿÞÿáÿâÿäÿçÿèÿëÿíÿîÿñÿóÿöÿ÷ÿúÿüÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ€ÿ¥ÿ§ÿªÿ­ÿ­ÿ°ÿ³ÿŽÿ¶ÿ¹ÿŒÿŒÿ¿ÿÂÿÂÿÅÿÈÿÉÿËÿÎÿÑÿÑÿÔÿ×ÿØÿÚÿÝÿàÿàÿãÿæÿæÿéÿìÿíÿïÿòÿõÿõÿøÿûÿüÿþ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ£ÿŠÿ©ÿ«ÿ¬ÿ¯ÿ±ÿ²ÿµÿžÿºÿ»ÿŸÿÀÿÁÿÄÿÆÿÇÿÊÿÍÿÏÿÐÿÓÿÕÿÖÿÙÿÜÿÞÿßÿâÿäÿåÿèÿêÿëÿîÿñÿóÿôÿ÷ÿùÿúÿý    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ¢ÿ€ÿ§ÿªÿ«ÿ­ÿ°ÿ±ÿ³ÿ¶ÿ¹ÿºÿŒÿ¿ÿÀÿÂÿÅÿÆÿÈÿËÿÎÿÏÿÑÿÔÿÕÿ×ÿÚÿÝÿÞÿàÿãÿäÿæÿéÿêÿìÿïÿòÿóÿõÿøÿùÿûÿþ    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ£ÿŠÿšÿ©ÿ¬ÿ¯ÿ¯ÿ²ÿµÿ·ÿžÿ»ÿŸÿŸÿÁÿÄÿÄÿÇÿÊÿÌÿÍÿÐÿÓÿÓÿÖÿÙÿÛÿÜÿßÿâÿâÿåÿèÿèÿëÿîÿðÿñÿôÿ÷ÿ÷ÿúÿýÿÿ      	ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ€ÿ§ÿšÿªÿ­ÿ®ÿ±ÿ³ÿ¶ÿ·ÿ¹ÿŒÿœÿÀÿÂÿÃÿÆÿÈÿËÿÌÿÎÿÑÿÒÿÕÿ×ÿÚÿÛÿÝÿàÿáÿäÿæÿçÿêÿìÿïÿðÿòÿõÿöÿùÿûÿþÿÿ     
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ£ÿŠÿŠÿ©ÿ¬ÿ¬ÿ¯ÿ²ÿµÿµÿžÿ»ÿ»ÿŸÿÁÿÂÿÄÿÇÿÊÿÊÿÍÿÐÿÐÿÓÿÖÿÙÿÙÿÜÿßÿßÿâÿåÿæÿèÿëÿîÿîÿñÿôÿôÿ÷ÿúÿýÿý      	 
+ 
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ€ÿ¥ÿšÿªÿ«ÿ®ÿ°ÿ³ÿŽÿ·ÿ¹ÿºÿœÿ¿ÿÀÿÃÿÆÿÈÿÉÿÌÿÎÿÏÿÒÿÔÿ×ÿØÿÛÿÝÿÞÿáÿãÿäÿçÿêÿìÿíÿðÿòÿóÿöÿøÿûÿüÿÿ     
+ 
+   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ£ÿ£ÿŠÿ©ÿªÿ¬ÿ¯ÿ²ÿ²ÿµÿžÿ¹ÿ»ÿŸÿ¿ÿÁÿÄÿÇÿÈÿÊÿÍÿÎÿÐÿÓÿÖÿÖÿÙÿÜÿÝÿßÿâÿãÿåÿèÿëÿìÿîÿñÿòÿôÿ÷ÿúÿúÿý      	 	 
+    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ¢ÿ¥ÿ§ÿšÿ«ÿ®ÿ°ÿ±ÿŽÿ¶ÿ·ÿºÿœÿœÿÀÿÃÿÅÿÆÿÉÿÌÿÌÿÏÿÒÿÔÿÕÿØÿÚÿÛÿÞÿáÿáÿäÿçÿéÿêÿíÿðÿðÿóÿöÿøÿùÿüÿþÿÿ     
+ 
+     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ£ÿŠÿ§ÿ©ÿ¬ÿ¯ÿ°ÿ²ÿµÿ¶ÿžÿ»ÿŒÿ¿ÿÁÿÄÿÅÿÇÿÊÿËÿÎÿÐÿÓÿÔÿÖÿÙÿÚÿÜÿßÿàÿãÿåÿèÿéÿëÿîÿïÿòÿôÿ÷ÿøÿúÿýÿþ      	 
+ 
+      ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ¥ÿ¥ÿšÿ«ÿ­ÿ®ÿ±ÿŽÿŽÿ·ÿºÿºÿœÿÀÿÃÿÃÿÆÿÉÿÉÿÌÿÏÿÒÿÒÿÕÿØÿØÿÛÿÞÿÞÿáÿäÿçÿçÿêÿíÿíÿðÿóÿöÿöÿùÿüÿüÿÿ     
+ 
+        
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ€ÿ§ÿ©ÿ¬ÿ­ÿ¯ÿ²ÿ³ÿ¶ÿžÿ¹ÿŒÿŸÿÁÿÂÿÅÿÇÿÈÿËÿÍÿÐÿÑÿÔÿÖÿ×ÿÚÿÜÿÝÿàÿâÿåÿæÿéÿëÿìÿïÿñÿôÿõÿøÿúÿûÿþ      	 
+ 
+       
+ 
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ£ÿ¥ÿšÿ«ÿ«ÿ®ÿ±ÿ±ÿŽÿ·ÿžÿºÿœÿÀÿÀÿÃÿÆÿÇÿÉÿÌÿÏÿÏÿÒÿÕÿÖÿØÿÛÿÜÿÞÿáÿäÿäÿçÿêÿëÿíÿðÿóÿóÿöÿùÿúÿüÿÿ      
+        
+ 
+   #ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ€ÿ§ÿ©ÿªÿ­ÿ¯ÿ°ÿ³ÿµÿ¶ÿ¹ÿŒÿŸÿ¿ÿÂÿÄÿÅÿÈÿËÿÍÿÎÿÑÿÓÿÔÿ×ÿÚÿÚÿÝÿàÿâÿãÿæÿèÿéÿìÿïÿñÿòÿõÿ÷ÿøÿûÿþ       
+ 
+ 
+       
+  " $ %ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿšÿ©ÿ«ÿ®ÿ¯ÿ±ÿŽÿµÿ·ÿºÿœÿŸÿÀÿÃÿÄÿÆÿÉÿÌÿÍÿÏÿÒÿÓÿÕÿØÿÙÿÜÿÞÿáÿâÿäÿçÿèÿêÿíÿðÿñÿóÿöÿ÷ÿùÿüÿÿ       
+ 
+        
+   # $ & )ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ€ÿŠÿ§ÿªÿ­ÿ­ÿ°ÿ³ÿ³ÿ¶ÿ¹ÿ»ÿŒÿ¿ÿÂÿÂÿÅÿÈÿÊÿËÿÎÿÑÿÑÿÔÿ×ÿ×ÿÚÿÝÿàÿàÿãÿæÿæÿéÿìÿîÿïÿòÿõÿõÿøÿûÿýÿþ     
+ 
+ 
+       
+  ! " % ( ( +ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿŠÿšÿ«ÿ¬ÿ¯ÿ±ÿ²ÿµÿ·ÿºÿ»ÿœÿÀÿÁÿÄÿÆÿÉÿÊÿÌÿÏÿÐÿÓÿÕÿÖÿÙÿÛÿÞÿßÿâÿäÿåÿèÿêÿíÿîÿðÿóÿôÿ÷ÿùÿüÿýÿÿ     	 
+        
+   ! # & ' * , -ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ€ÿ€ÿ§ÿªÿªÿ­ÿ°ÿ±ÿ³ÿ¶ÿ¹ÿ¹ÿŒÿ¿ÿ¿ÿÂÿÅÿÈÿÈÿËÿÎÿÎÿÑÿÔÿÕÿ×ÿÚÿÝÿÝÿàÿãÿäÿæÿéÿìÿìÿïÿòÿòÿõÿøÿûÿûÿþ      
+ 
+       
+   " % % ( + , . 1ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ£ÿŠÿšÿ©ÿ¬ÿ®ÿ¯ÿ²ÿµÿ·ÿžÿ»ÿœÿŸÿÁÿÃÿÆÿÇÿÊÿÌÿÍÿÐÿÒÿÓÿÖÿÙÿÛÿÜÿßÿáÿâÿåÿèÿêÿëÿîÿðÿñÿôÿöÿùÿúÿýÿÿ      	 
+        
+ 
+ ! # $ ' ) * - 0 2 3ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ¡ÿ€ÿ§ÿšÿªÿ­ÿ®ÿ°ÿ³ÿ¶ÿ·ÿ¹ÿŒÿœÿ¿ÿÂÿÅÿÅÿÈÿËÿÌÿÎÿÑÿÒÿÔÿ×ÿÚÿÛÿÝÿàÿáÿãÿæÿéÿêÿìÿïÿðÿòÿõÿøÿøÿûÿþÿÿ     
+ 
+       
+ 
+  " # % ( ) + . 1 2 4 7ÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ£ÿ¥ÿŠÿ©ÿ¬ÿ¬ÿ¯ÿ²ÿŽÿµÿžÿ»ÿ»ÿŸÿÁÿÃÿÄÿÇÿÉÿÊÿÍÿÐÿÐÿÓÿÖÿØÿÙÿÜÿßÿßÿâÿåÿçÿèÿëÿîÿîÿñÿôÿöÿ÷ÿúÿüÿý      	 
+ 
+        
+   ! $ ' ' * - / 0 3 6 6 9ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ€ÿ¥ÿ§ÿªÿ«ÿ®ÿ°ÿ³ÿŽÿ¶ÿ¹ÿºÿœÿ¿ÿÂÿÃÿÅÿÈÿÉÿËÿÎÿÏÿÒÿÔÿ×ÿØÿÚÿÝÿÞÿáÿãÿæÿçÿéÿìÿíÿðÿòÿõÿöÿøÿûÿüÿþ     
+ 
+ 
+       
+    " % & ) + . / 1 4 5 8 : =ÿÿÿÿÿÿ
+ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿ ÿ£ÿ£ÿŠÿ©ÿ©ÿ¬ÿ¯ÿ²ÿ²ÿµÿžÿžÿ»ÿŸÿÁÿÁÿÄÿÇÿÇÿÊÿÍÿÍÿÐÿÓÿÖÿÖÿÙÿÜÿÜÿßÿâÿåÿåÿèÿëÿëÿîÿñÿôÿôÿ÷ÿúÿúÿý       	 	 
+        
+ 
+ ! $ $ ' * - - 0 3 3 6 9 < < ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ¢ÿ¥ÿ§ÿšÿ«ÿ­ÿ°ÿ±ÿŽÿ¶ÿ·ÿºÿŒÿ¿ÿÀÿÃÿÅÿÆÿÉÿËÿÌÿÏÿÑÿÔÿÕÿØÿÚÿÛÿÞÿàÿãÿäÿçÿéÿêÿíÿïÿòÿóÿöÿøÿùÿüÿþÿÿ     
+ 
+       
+ 
+   " # & ( + , / 1 2 5 7 : ; >ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ£ÿŠÿ§ÿ©ÿ¬ÿ¯ÿ¯ÿ²ÿµÿ¶ÿžÿ»ÿŸÿŸÿÁÿÄÿÅÿÇÿÊÿËÿÍÿÐÿÓÿÓÿÖÿÙÿÚÿÜÿßÿâÿâÿåÿèÿéÿëÿîÿñÿñÿôÿ÷ÿøÿúÿýÿþ      	 
+ 
+       
+ 
+ ! " $ ' * * - 0 1 3 6 9 9 <ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ¥ÿ¥ÿšÿ«ÿ­ÿ®ÿ±ÿ³ÿŽÿ·ÿºÿŒÿœÿÀÿÂÿÃÿÆÿÉÿÉÿÌÿÏÿÑÿÒÿÕÿ×ÿØÿÛÿÞÿàÿáÿäÿæÿçÿêÿíÿïÿðÿóÿõÿöÿùÿüÿüÿÿ     
+ 
+        
+     # & ( ) , . / 2 5 7 8 ;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ£ÿ€ÿ§ÿ©ÿ¬ÿ­ÿ¯ÿ²ÿ³ÿµÿžÿ»ÿŒÿŸÿÁÿÂÿÄÿÇÿÈÿËÿÍÿÐÿÑÿÓÿÖÿ×ÿÙÿÜÿßÿàÿâÿåÿæÿèÿëÿîÿïÿñÿôÿõÿ÷ÿúÿûÿþ      	 
+ 
+        
+  " $ ' ( * - . 0 3 6 7 9ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ¢ÿ¥ÿšÿ«ÿ«ÿ®ÿ±ÿ±ÿŽÿ·ÿ¹ÿºÿœÿÀÿÀÿÃÿÆÿÆÿÉÿÌÿÏÿÏÿÒÿÕÿÕÿØÿÛÿÝÿÞÿáÿäÿäÿçÿêÿìÿíÿðÿóÿóÿöÿùÿùÿüÿÿ      
+        
+ 
+   # & & ) , , / 2 4 5 8ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ€ÿŠÿ©ÿªÿ­ÿ¯ÿ°ÿ³ÿµÿžÿ¹ÿ»ÿŸÿ¿ÿÂÿÄÿÅÿÈÿÊÿÍÿÎÿÑÿÓÿÔÿ×ÿÙÿÜÿÝÿßÿâÿãÿæÿèÿëÿìÿîÿñÿòÿõÿ÷ÿøÿûÿý       
+ 
+        
+  ! $ % ( * + . 0 3 4 6ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¥ÿšÿšÿ«ÿ®ÿ¯ÿ±ÿŽÿ·ÿ·ÿºÿœÿœÿÀÿÃÿÄÿÆÿÉÿÌÿÌÿÏÿÒÿÓÿÕÿØÿÛÿÛÿÞÿáÿáÿäÿçÿêÿêÿíÿðÿðÿóÿöÿ÷ÿùÿüÿÿÿÿ     
+         
+   # # & ) * , / 2 2 5ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ€ÿŠÿ§ÿªÿ¬ÿ­ÿ°ÿ³ÿµÿ¶ÿ¹ÿ»ÿŒÿ¿ÿÁÿÂÿÅÿÈÿÊÿËÿÎÿÐÿÑÿÔÿ×ÿÙÿÚÿÝÿßÿàÿãÿåÿèÿéÿìÿîÿïÿòÿôÿõÿøÿûÿýÿþ     
+ 
+ 
+       
+  ! " % ' ( + . 0 1 4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ¥ÿŠÿšÿ«ÿ¬ÿ®ÿ±ÿŽÿµÿ·ÿºÿ»ÿœÿÀÿÁÿÃÿÆÿÉÿÊÿÌÿÏÿÐÿÒÿÕÿØÿÙÿÛÿÞÿßÿáÿäÿçÿçÿêÿíÿîÿðÿóÿôÿöÿùÿüÿýÿÿ     
+ 
+        
+   ! # & ' ) , / 0 2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ€ÿ§ÿªÿªÿ­ÿ°ÿ²ÿ³ÿ¶ÿ¹ÿ¹ÿŒÿ¿ÿ¿ÿÂÿÅÿÇÿÈÿËÿÎÿÎÿÑÿÔÿÖÿ×ÿÚÿÝÿÝÿàÿãÿåÿæÿéÿëÿìÿïÿòÿòÿõÿøÿúÿûÿþ     	 
+ 
+       
+ 
+  " % % ( + - . 1ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ£ÿ¥ÿšÿ©ÿ¬ÿ®ÿ±ÿ²ÿŽÿ·ÿžÿ»ÿœÿŸÿÁÿÃÿÆÿÇÿÉÿÌÿÍÿÐÿÒÿÕÿÖÿØÿÛÿÜÿßÿáÿäÿåÿçÿêÿëÿíÿðÿñÿôÿöÿùÿúÿüÿÿ      	 
+        
+ 
+   # $ ' ) , - /ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿ§ÿ§ÿªÿ­ÿ°ÿ°ÿ³ÿ¶ÿ¶ÿ¹ÿŒÿœÿ¿ÿÂÿÅÿÅÿÈÿËÿËÿÎÿÑÿÔÿÔÿ×ÿÚÿÚÿÝÿàÿãÿãÿæÿéÿéÿìÿïÿïÿòÿõÿøÿøÿûÿþÿþ     
+ 
+ 
+      
+ 
+  " " % ( + + .ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŠÿ©ÿ«ÿ®ÿ¯ÿ²ÿŽÿµÿžÿºÿ»ÿŸÿÁÿÃÿÄÿÇÿÉÿÊÿÍÿÏÿÒÿÓÿÖÿØÿÙÿÜÿÞÿáÿâÿåÿçÿèÿëÿíÿîÿñÿóÿöÿ÷ÿúÿüÿý      	 
+ 
+        
+   ! $ & ) * -ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿªÿ­ÿ­ÿ°ÿ³ÿŽÿ¶ÿ¹ÿºÿŒÿ¿ÿÂÿÃÿÅÿÈÿÉÿËÿÎÿÑÿÑÿÔÿ×ÿØÿÚÿÝÿàÿàÿãÿæÿçÿéÿìÿíÿïÿòÿõÿõÿøÿûÿüÿþ     
+ 
+ 
+       
+    " % ( ( +ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬ÿ¯ÿ±ÿ²ÿµÿžÿžÿ»ÿŸÿÀÿÁÿÄÿÇÿÇÿÊÿÍÿÏÿÐÿÓÿÕÿÖÿÙÿÜÿÞÿßÿâÿäÿåÿèÿëÿëÿîÿñÿóÿôÿ÷ÿùÿúÿý       	 
+        
+ 
+ ! $ & ' *ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ°ÿ±ÿ³ÿ¶ÿ·ÿºÿŒÿ¿ÿÀÿÂÿÅÿÆÿÉÿËÿÎÿÏÿÑÿÔÿÕÿ×ÿÚÿÝÿÞÿàÿãÿäÿæÿéÿêÿíÿïÿòÿóÿõÿøÿùÿûÿþ      
+ 
+       
+ 
+   " % & (ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²ÿµÿµÿžÿ»ÿŸÿŸÿÁÿÄÿÄÿÇÿÊÿÍÿÍÿÐÿÓÿÓÿÖÿÙÿÛÿÜÿßÿâÿâÿåÿèÿèÿëÿîÿñÿñÿôÿ÷ÿ÷ÿúÿýÿÿ      	 
+ 
+        
+ ! $ $ 'ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŽÿ·ÿ¹ÿŒÿœÿÀÿÂÿÃÿÆÿÈÿËÿÌÿÏÿÑÿÒÿÕÿ×ÿÚÿÛÿÝÿàÿáÿäÿæÿçÿêÿìÿïÿðÿóÿõÿöÿùÿûÿþÿÿ     
+ 
+        
+  " # &ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿžÿ»ÿ»ÿŸÿÁÿÂÿÄÿÇÿÊÿÊÿÍÿÐÿÑÿÓÿÖÿÙÿÙÿÜÿßÿßÿâÿåÿæÿèÿëÿîÿîÿñÿôÿõÿ÷ÿúÿýÿý      	 
+ 
+        
+ ! ! $ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºÿœÿ¿ÿÀÿÃÿÆÿÈÿÉÿÌÿÎÿÏÿÒÿÕÿ×ÿØÿÛÿÝÿÞÿáÿãÿäÿçÿêÿìÿíÿðÿòÿóÿöÿùÿûÿüÿÿ      
+        
+    #ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸÿ¿ÿÁÿÄÿÇÿÈÿÊÿÍÿÎÿÐÿÓÿÖÿ×ÿÙÿÜÿÝÿßÿâÿãÿåÿèÿëÿìÿîÿñÿòÿôÿ÷ÿúÿûÿý       	 
+        
+  !ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀÿÃÿÅÿÆÿÉÿÌÿÌÿÏÿÒÿÔÿÕÿØÿÛÿÛÿÞÿáÿáÿäÿçÿéÿêÿíÿðÿðÿóÿöÿøÿùÿüÿÿÿÿ     
+ 
+       
+ 
+  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÄÿÅÿÇÿÊÿËÿÎÿÐÿÓÿÔÿÖÿÙÿÚÿÝÿßÿàÿãÿåÿèÿéÿëÿîÿïÿòÿôÿ÷ÿøÿúÿýÿþ     	 
+ 
+       
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÆÿÉÿÉÿÌÿÏÿÒÿÒÿÕÿØÿØÿÛÿÞÿßÿáÿäÿçÿçÿêÿíÿíÿðÿóÿöÿöÿùÿüÿüÿÿ     
+ 
+        
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÿËÿÍÿÐÿÑÿÔÿÖÿ×ÿÚÿÜÿÝÿàÿãÿåÿæÿéÿëÿìÿïÿñÿôÿõÿøÿúÿûÿþ      	 
+ 
+       
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÌÿÏÿÏÿÒÿÕÿÖÿØÿÛÿÜÿÞÿáÿäÿåÿçÿêÿëÿíÿðÿóÿóÿöÿùÿúÿüÿÿ      	 
+       ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÎÿÑÿÓÿÔÿ×ÿÚÿÚÿÝÿàÿâÿãÿæÿéÿéÿìÿïÿñÿòÿõÿ÷ÿøÿûÿþÿþ     
+ 
+ 
+     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÒÿÓÿÕÿØÿÙÿÜÿÞÿáÿâÿäÿçÿèÿëÿíÿðÿñÿóÿöÿ÷ÿùÿüÿý       
+ 
+     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÔÿ×ÿ×ÿÚÿÝÿàÿàÿãÿæÿæÿéÿìÿïÿïÿòÿõÿõÿøÿûÿûÿþ     
+ 
+ 
+    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖÿÙÿÛÿÞÿßÿâÿäÿåÿèÿêÿíÿîÿñÿóÿôÿ÷ÿùÿúÿýÿÿ     	 
+    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÚÿÝÿÝÿàÿãÿäÿæÿéÿìÿìÿïÿòÿóÿõÿøÿùÿûÿþ      
+ 
+   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÜÿßÿáÿâÿåÿèÿêÿëÿîÿðÿñÿôÿ÷ÿ÷ÿúÿýÿÿ      	 
+   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàÿáÿãÿæÿéÿêÿìÿïÿðÿòÿõÿöÿùÿûÿþÿÿ     
+ 
+  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâÿåÿçÿèÿëÿîÿîÿñÿôÿôÿ÷ÿúÿýÿý      	 
+ 
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿæÿçÿéÿìÿíÿðÿòÿóÿöÿøÿûÿüÿÿ     
+ 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿëÿëÿîÿñÿòÿôÿ÷ÿúÿúÿý      	 	 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿêÿíÿïÿðÿóÿöÿøÿùÿüÿþÿÿ     
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿîÿïÿñÿôÿ÷ÿøÿúÿýÿþ      	ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿóÿõÿöÿùÿüÿüÿÿ    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôÿõÿ÷ÿúÿûÿþ     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöÿùÿùÿüÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿûÿý    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿÿÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÿÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÿÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿ ÿ¡ÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿ¢ÿ£ÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿ€ÿ¥ÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿŠÿ§ÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿšÿ©ÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿªÿ«ÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿ¬ÿ­ÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿ®ÿ¯ÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿ°ÿ±ÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿ²ÿ³ÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿŽÿµÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿ¶ÿ·ÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿžÿ¹ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿºÿ»ÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿŒÿœÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿŸÿ¿ÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿÀÿÁÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿÿÂÿÃÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ   ÿÄÿÅÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ     ÿÆÿÇÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ       ÿÈÿÉÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ         ÿÊÿËÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	ÿÌÿÍÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ÿÎÿÏÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+ÿÐÿÑÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+  ÿÒÿÓÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+    ÿÔÿÕÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+      ÿÖÿ×ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+        ÿØÿÙÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+          ÿÚÿÛÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+            ÿÜÿÝÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+              ÿÞÿßÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ÿàÿáÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+ ÿâÿãÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    !ÿäÿåÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " #ÿæÿçÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ %ÿèÿéÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & 'ÿêÿëÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( )ÿìÿíÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * +ÿîÿïÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , -ÿðÿñÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . /ÿòÿóÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1ÿôÿõÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3ÿöÿ÷ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5ÿøÿùÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7ÿúÿûÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9ÿüÿýÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ;ÿþÿÿ           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < =           	 
+ 
+ 
+ 
+               
+ 
+ 
+    ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ?                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ£ÿ¡ÿ ÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŠÿ¥ÿ£ÿ€ÿ£ÿ¢ÿ ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿšÿ§ÿ§ÿŠÿ¥ÿŠÿ€ÿ£ÿ¢ÿ¢ÿ¡ÿ ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬ÿ«ÿ©ÿšÿ©ÿšÿŠÿ§ÿŠÿ€ÿ£ÿ€ÿ£ÿ¡ÿ¢ÿ¡ÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ÿ­ÿ­ÿ¬ÿ«ÿªÿªÿ©ÿšÿšÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ£ÿ¢ÿ¡ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ°ÿ±ÿ¯ÿ®ÿ¯ÿ®ÿ¬ÿ«ÿ¬ÿªÿ©ÿªÿ©ÿ§ÿŠÿ§ÿ¥ÿ€ÿ¥ÿ£ÿ¢ÿ£ÿ¢ÿ ÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŽÿ³ÿ±ÿ²ÿ±ÿ°ÿ°ÿ¯ÿ®ÿ¬ÿ­ÿ¬ÿ«ÿ«ÿªÿ©ÿ§ÿšÿ§ÿ¥ÿŠÿ¥ÿ€ÿ€ÿ£ÿ¢ÿ ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¶ÿµÿµÿŽÿ³ÿŽÿ²ÿ±ÿ²ÿ°ÿ¯ÿ®ÿ¯ÿ­ÿ¬ÿ­ÿ«ÿªÿ©ÿ©ÿšÿ§ÿšÿŠÿ¥ÿŠÿ€ÿ£ÿ¢ÿ£ÿ¡ÿ ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºÿ¹ÿ·ÿ¶ÿ·ÿ¶ÿŽÿµÿŽÿ²ÿ³ÿ²ÿ±ÿ¯ÿ°ÿ¯ÿ­ÿ®ÿ­ÿ«ÿªÿ«ÿªÿšÿ©ÿšÿŠÿ§ÿŠÿ¥ÿ£ÿ€ÿ£ÿ¡ÿ¢ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŒÿ»ÿ»ÿºÿ¹ÿžÿžÿ·ÿ¶ÿ¶ÿµÿŽÿµÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ¯ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿªÿ©ÿšÿ©ÿ§ÿŠÿ¥ÿ¥ÿ€ÿ£ÿ£ÿ¢ÿ¡ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸÿ¿ÿœÿŒÿœÿŒÿºÿ¹ÿºÿžÿ·ÿžÿ·ÿµÿ¶ÿµÿ³ÿ²ÿ³ÿ±ÿ°ÿ±ÿ°ÿ®ÿ­ÿ®ÿ¬ÿ«ÿ¬ÿ«ÿ©ÿªÿ©ÿ§ÿŠÿ§ÿ¥ÿ€ÿ¥ÿ€ÿ¢ÿ¡ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÂÿÁÿ¿ÿÀÿ¿ÿŸÿŸÿœÿŒÿºÿ»ÿºÿ¹ÿ¹ÿžÿ·ÿ·ÿ¶ÿµÿ³ÿŽÿ³ÿ²ÿ²ÿ±ÿ°ÿ®ÿ¯ÿ®ÿ­ÿ­ÿ¬ÿ«ÿ«ÿªÿ©ÿ§ÿšÿ§ÿŠÿŠÿ¥ÿ€ÿ¢ÿ£ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÄÿÅÿÃÿÂÿÁÿÂÿÀÿ¿ÿÀÿŸÿœÿŒÿœÿ»ÿºÿ»ÿ¹ÿžÿ¹ÿ·ÿ¶ÿµÿ¶ÿŽÿ³ÿŽÿ²ÿ±ÿ°ÿ±ÿ¯ÿ®ÿ¯ÿ­ÿ¬ÿ­ÿ«ÿªÿ©ÿªÿšÿ§ÿšÿŠÿ¥ÿ€ÿ¥ÿ£ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÿÇÿÅÿÆÿÅÿÄÿÂÿÃÿÂÿÀÿÁÿÀÿ¿ÿœÿŸÿœÿ»ÿŒÿ»ÿ¹ÿºÿ¹ÿžÿ¶ÿ·ÿ¶ÿŽÿµÿŽÿ³ÿ±ÿ²ÿ±ÿ¯ÿ°ÿ¯ÿ­ÿ®ÿ­ÿ¬ÿªÿ«ÿªÿšÿ©ÿšÿ§ÿ¥ÿŠÿ¥ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÊÿÉÿÉÿÈÿÇÿÈÿÆÿÅÿÄÿÄÿÃÿÂÿÃÿÁÿÀÿ¿ÿ¿ÿŸÿœÿœÿŒÿ»ÿŒÿºÿ¹ÿžÿžÿ·ÿ¶ÿ·ÿµÿŽÿ³ÿ³ÿ²ÿ±ÿ±ÿ°ÿ¯ÿ°ÿ®ÿ­ÿ¬ÿ¬ÿ«ÿªÿ«ÿ©ÿšÿ§ÿ§ÿŠÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÎÿÍÿËÿÊÿËÿÊÿÈÿÉÿÈÿÆÿÅÿÆÿÅÿÃÿÄÿÃÿÁÿÀÿÁÿ¿ÿŸÿ¿ÿŸÿŒÿœÿŒÿºÿ¹ÿºÿ¹ÿ·ÿžÿ·ÿµÿŽÿµÿ³ÿ²ÿ³ÿ²ÿ°ÿ±ÿ°ÿ®ÿ­ÿ®ÿ­ÿ«ÿ¬ÿ«ÿ©ÿšÿ©ÿšÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÐÿÏÿÏÿÎÿÍÿÌÿÌÿËÿÊÿÊÿÉÿÈÿÇÿÇÿÆÿÅÿÅÿÄÿÃÿÁÿÂÿÁÿÀÿÀÿ¿ÿŸÿŸÿœÿŒÿ»ÿ»ÿºÿ¹ÿ¹ÿžÿ·ÿµÿ¶ÿµÿŽÿŽÿ³ÿ²ÿ²ÿ±ÿ°ÿ¯ÿ¯ÿ®ÿ­ÿ­ÿ¬ÿ«ÿªÿªÿ©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÒÿÓÿÑÿÐÿÑÿÐÿÎÿÍÿÎÿÌÿËÿÌÿËÿÉÿÈÿÉÿÇÿÆÿÇÿÅÿÄÿÃÿÄÿÂÿÁÿÂÿÀÿ¿ÿÀÿ¿ÿœÿŒÿœÿ»ÿºÿ»ÿ¹ÿžÿ·ÿžÿ¶ÿµÿ¶ÿŽÿ³ÿŽÿ³ÿ±ÿ°ÿ±ÿ¯ÿ®ÿ¯ÿ®ÿ¬ÿ«ÿ¬ÿªÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖÿÕÿÓÿÔÿÓÿÒÿÒÿÑÿÐÿÎÿÏÿÎÿÍÿÍÿÌÿËÿÉÿÊÿÉÿÇÿÈÿÇÿÆÿÄÿÅÿÄÿÂÿÃÿÂÿÁÿÁÿÀÿ¿ÿœÿŸÿœÿ»ÿŒÿ»ÿºÿžÿ¹ÿžÿ¶ÿ·ÿ¶ÿµÿµÿŽÿ³ÿ±ÿ²ÿ±ÿ°ÿ°ÿ¯ÿ®ÿ¬ÿ­ÿ¬ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿØÿ×ÿ×ÿÖÿÕÿÖÿÔÿÓÿÔÿÒÿÑÿÐÿÑÿÏÿÎÿÏÿÍÿÌÿËÿËÿÊÿÉÿÊÿÈÿÇÿÆÿÆÿÅÿÄÿÅÿÃÿÂÿÃÿÁÿÀÿ¿ÿ¿ÿŸÿœÿŸÿŒÿ»ÿºÿºÿ¹ÿžÿ¹ÿ·ÿ¶ÿ·ÿµÿŽÿ³ÿŽÿ²ÿ±ÿ²ÿ°ÿ¯ÿ®ÿ®ÿ­ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÜÿÛÿÙÿØÿÙÿØÿÖÿ×ÿÖÿÔÿÕÿÔÿÓÿÑÿÒÿÑÿÏÿÐÿÏÿÍÿÌÿÍÿÌÿÊÿËÿÊÿÈÿÇÿÈÿÇÿÅÿÆÿÅÿÃÿÄÿÃÿÁÿÀÿÁÿÀÿŸÿ¿ÿŸÿŒÿ»ÿŒÿ»ÿ¹ÿºÿ¹ÿ·ÿžÿ·ÿ¶ÿŽÿµÿŽÿ²ÿ³ÿ²ÿ°ÿ¯ÿ°ÿ¯ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞÿÝÿÝÿÜÿÛÿÚÿÚÿÙÿØÿØÿ×ÿÖÿ×ÿÕÿÔÿÓÿÓÿÒÿÑÿÑÿÐÿÏÿÎÿÎÿÍÿÌÿÌÿËÿÊÿÉÿÉÿÈÿÇÿÇÿÆÿÅÿÅÿÄÿÃÿÂÿÂÿÁÿÀÿÀÿ¿ÿŸÿœÿœÿŒÿ»ÿ»ÿºÿ¹ÿºÿžÿ·ÿ¶ÿ¶ÿµÿŽÿŽÿ³ÿ²ÿ±ÿ±ÿ°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàÿáÿßÿÞÿßÿÞÿÜÿÛÿÜÿÚÿÙÿÚÿÙÿ×ÿØÿ×ÿÕÿÔÿÕÿÓÿÒÿÓÿÒÿÐÿÏÿÐÿÎÿÍÿÎÿÍÿËÿÊÿËÿÉÿÈÿÉÿÇÿÆÿÇÿÆÿÄÿÃÿÄÿÂÿÁÿÂÿÁÿ¿ÿŸÿ¿ÿœÿŒÿœÿŒÿºÿ»ÿºÿžÿ·ÿžÿ¶ÿµÿ¶ÿµÿ³ÿ²ÿ³ÿ±ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿäÿãÿáÿâÿáÿàÿàÿßÿÞÿÜÿÝÿÜÿÛÿÛÿÚÿÙÿÙÿØÿ×ÿÕÿÖÿÕÿÔÿÔÿÓÿÒÿÐÿÑÿÐÿÏÿÏÿÎÿÍÿËÿÌÿËÿÉÿÊÿÉÿÈÿÈÿÇÿÆÿÄÿÅÿÄÿÃÿÃÿÂÿÁÿ¿ÿÀÿ¿ÿŸÿŸÿœÿŒÿŒÿ»ÿºÿžÿ¹ÿžÿ·ÿ·ÿ¶ÿµÿ³ÿŽÿ³ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿæÿçÿåÿäÿãÿäÿâÿáÿâÿàÿßÿÞÿßÿÝÿÜÿÝÿÛÿÚÿÛÿÙÿØÿ×ÿØÿÖÿÕÿÖÿÔÿÓÿÒÿÓÿÑÿÐÿÑÿÏÿÎÿÍÿÍÿÌÿËÿÌÿÊÿÉÿÊÿÈÿÇÿÆÿÇÿÅÿÄÿÅÿÃÿÂÿÁÿÂÿÀÿ¿ÿÀÿŸÿœÿŸÿŒÿ»ÿºÿ»ÿ¹ÿžÿ¹ÿ·ÿ¶ÿµÿ¶ÿŽÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿêÿéÿçÿèÿçÿæÿäÿåÿäÿâÿãÿâÿáÿßÿàÿßÿÝÿÞÿÝÿÛÿÜÿÛÿÚÿØÿÙÿØÿÖÿ×ÿÖÿÕÿÓÿÔÿÓÿÑÿÒÿÑÿÏÿÎÿÏÿÎÿÌÿÍÿÌÿÊÿËÿÊÿÉÿÇÿÈÿÇÿÅÿÆÿÅÿÄÿÂÿÃÿÂÿÀÿÁÿÀÿŸÿ¿ÿŸÿœÿ»ÿŒÿ»ÿ¹ÿºÿ¹ÿžÿ¶ÿ·ÿ¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìÿëÿëÿêÿéÿêÿèÿçÿæÿæÿåÿäÿåÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÞÿÜÿÛÿÚÿÚÿÙÿØÿÙÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÐÿÐÿÏÿÎÿÎÿÍÿÌÿÍÿËÿÊÿÉÿÉÿÈÿÇÿÈÿÆÿÅÿÄÿÄÿÃÿÂÿÂÿÁÿÀÿÁÿ¿ÿŸÿœÿœÿŒÿ»ÿŒÿºÿ¹ÿžÿžÿ·ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿîÿïÿíÿìÿíÿìÿêÿëÿêÿèÿçÿèÿçÿåÿæÿåÿãÿâÿãÿáÿàÿáÿàÿÞÿßÿÞÿÜÿÛÿÜÿÛÿÙÿÚÿÙÿ×ÿÖÿ×ÿÕÿÔÿÕÿÔÿÒÿÑÿÒÿÐÿÏÿÐÿÏÿÍÿÎÿÍÿËÿÊÿËÿÊÿÈÿÉÿÈÿÆÿÅÿÆÿÄÿÃÿÄÿÃÿÁÿÂÿÁÿ¿ÿŸÿ¿ÿŸÿŒÿœÿŒÿºÿ¹ÿºÿžÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòÿñÿïÿðÿïÿîÿîÿíÿìÿìÿëÿêÿéÿéÿèÿçÿçÿæÿåÿãÿäÿãÿâÿâÿáÿàÿàÿßÿÞÿÝÿÝÿÜÿÛÿÛÿÚÿÙÿ×ÿØÿ×ÿÖÿÖÿÕÿÔÿÒÿÓÿÒÿÑÿÑÿÐÿÏÿÏÿÎÿÍÿÌÿÌÿËÿÊÿÊÿÉÿÈÿÆÿÇÿÆÿÅÿÅÿÄÿÃÿÃÿÂÿÁÿÀÿÀÿ¿ÿŸÿŸÿœÿŒÿºÿ»ÿºÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôÿõÿóÿòÿñÿòÿðÿïÿðÿîÿíÿîÿíÿëÿêÿëÿéÿèÿéÿçÿæÿåÿæÿäÿãÿäÿâÿáÿâÿáÿßÿÞÿßÿÝÿÜÿÝÿÛÿÚÿÙÿÚÿØÿ×ÿØÿÖÿÕÿÔÿÕÿÓÿÒÿÓÿÑÿÐÿÑÿÐÿÎÿÍÿÎÿÌÿËÿÌÿÊÿÉÿÈÿÉÿÇÿÆÿÇÿÅÿÄÿÅÿÄÿÂÿÁÿÂÿÀÿ¿ÿÀÿŸÿœÿŒÿœÿ»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿ÷ÿõÿöÿõÿôÿòÿóÿòÿðÿñÿðÿïÿïÿîÿíÿëÿìÿëÿéÿêÿéÿèÿæÿçÿæÿäÿåÿäÿãÿãÿâÿáÿßÿàÿßÿÝÿÞÿÝÿÜÿÚÿÛÿÚÿØÿÙÿØÿ×ÿÕÿÖÿÕÿÓÿÔÿÓÿÒÿÒÿÑÿÐÿÎÿÏÿÎÿÌÿÍÿÌÿËÿÉÿÊÿÉÿÇÿÈÿÇÿÆÿÆÿÅÿÄÿÂÿÃÿÂÿÀÿÁÿÀÿ¿ÿœÿŸÿœÿÿÿÿÿÿÿÿÿÿÿÿÿúÿùÿùÿøÿ÷ÿøÿöÿõÿôÿôÿóÿòÿóÿñÿðÿñÿïÿîÿíÿíÿìÿëÿìÿêÿéÿèÿèÿçÿæÿçÿåÿäÿåÿãÿâÿáÿáÿàÿßÿàÿÞÿÝÿÜÿÜÿÛÿÚÿÛÿÙÿØÿ×ÿ×ÿÖÿÕÿÖÿÔÿÓÿÔÿÒÿÑÿÐÿÐÿÏÿÎÿÏÿÍÿÌÿËÿËÿÊÿÉÿÊÿÈÿÇÿÈÿÆÿÅÿÄÿÄÿÃÿÂÿÃÿÁÿÀÿ¿ÿ¿ÿŸÿÿÿÿÿÿÿÿÿþÿýÿûÿúÿûÿúÿøÿùÿøÿöÿõÿöÿõÿóÿôÿóÿñÿòÿñÿïÿîÿïÿîÿìÿíÿìÿêÿéÿêÿéÿçÿèÿçÿåÿæÿåÿãÿâÿãÿâÿàÿáÿàÿÞÿÝÿÞÿÝÿÛÿÜÿÛÿÙÿØÿÙÿØÿÖÿ×ÿÖÿÔÿÕÿÔÿÒÿÑÿÒÿÑÿÏÿÐÿÏÿÍÿÌÿÍÿÌÿÊÿËÿÊÿÈÿÉÿÈÿÆÿÅÿÆÿÅÿÃÿÄÿÃÿÁÿÀÿÁÿÀÿÿÿÿ  ÿÿÿÿÿþÿýÿüÿüÿûÿúÿúÿùÿøÿ÷ÿ÷ÿöÿõÿõÿôÿóÿóÿòÿñÿðÿðÿïÿîÿîÿíÿìÿëÿëÿêÿéÿéÿèÿçÿçÿæÿåÿäÿäÿãÿâÿâÿáÿàÿßÿßÿÞÿÝÿÝÿÜÿÛÿÚÿÚÿÙÿØÿØÿ×ÿÖÿÖÿÕÿÔÿÓÿÓÿÒÿÑÿÑÿÐÿÏÿÎÿÎÿÍÿÌÿÌÿËÿÊÿÊÿÉÿÈÿÇÿÇÿÆÿÅÿÅÿÄÿÃÿÂÿÂÿÁÿÿÿÿ      ÿþÿýÿþÿüÿûÿüÿûÿùÿøÿùÿ÷ÿöÿ÷ÿõÿôÿõÿôÿòÿñÿòÿðÿïÿðÿïÿíÿìÿíÿëÿêÿëÿéÿèÿéÿèÿæÿåÿæÿäÿãÿäÿãÿáÿàÿáÿßÿÞÿßÿÞÿÜÿÛÿÜÿÚÿÙÿÚÿØÿ×ÿØÿ×ÿÕÿÔÿÕÿÓÿÒÿÓÿÒÿÐÿÏÿÐÿÎÿÍÿÎÿÌÿËÿÌÿËÿÉÿÈÿÉÿÇÿÆÿÇÿÆÿÄÿÃÿÿÿÿÿÿÿÿ      ÿþÿÿÿþÿýÿýÿüÿûÿùÿúÿùÿ÷ÿøÿ÷ÿöÿöÿõÿôÿòÿóÿòÿñÿñÿðÿïÿíÿîÿíÿëÿìÿëÿêÿêÿéÿèÿæÿçÿæÿåÿåÿäÿãÿáÿâÿáÿàÿàÿßÿÞÿÜÿÝÿÜÿÚÿÛÿÚÿÙÿÙÿØÿ×ÿÕÿÖÿÕÿÔÿÔÿÓÿÒÿÐÿÑÿÐÿÎÿÏÿÎÿÍÿÍÿÌÿËÿÉÿÊÿÉÿÈÿÈÿÇÿÿÿÿÿÿÿÿÿÿÿÿ        ÿÿÿþÿÿÿýÿüÿûÿûÿúÿùÿúÿøÿ÷ÿøÿöÿõÿôÿõÿóÿòÿóÿñÿðÿïÿïÿîÿíÿîÿìÿëÿìÿêÿéÿèÿéÿçÿæÿçÿåÿäÿãÿäÿâÿáÿâÿàÿßÿÞÿÞÿÝÿÜÿÝÿÛÿÚÿÛÿÙÿØÿ×ÿØÿÖÿÕÿÖÿÔÿÓÿÒÿÒÿÑÿÐÿÑÿÏÿÎÿÏÿÍÿÌÿËÿÌÿÊÿÉÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ        ÿÿ  ÿÿÿýÿüÿýÿüÿúÿûÿúÿøÿùÿøÿ÷ÿõÿöÿõÿóÿôÿóÿñÿðÿñÿðÿîÿïÿîÿìÿíÿìÿëÿéÿêÿéÿçÿèÿçÿæÿäÿåÿäÿâÿãÿâÿàÿßÿàÿßÿÝÿÞÿÝÿÛÿÜÿÛÿÚÿØÿÙÿØÿÖÿ×ÿÖÿÔÿÓÿÔÿÓÿÑÿÒÿÑÿÏÿÐÿÏÿÎÿÌÿÍÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ            ÿÿÿþÿþÿýÿüÿüÿûÿúÿûÿùÿøÿ÷ÿ÷ÿöÿõÿõÿôÿóÿòÿòÿñÿðÿðÿïÿîÿïÿíÿìÿëÿëÿêÿéÿêÿèÿçÿæÿæÿåÿäÿäÿãÿâÿáÿáÿàÿßÿßÿÞÿÝÿÞÿÜÿÛÿÚÿÚÿÙÿØÿØÿ×ÿÖÿÕÿÕÿÔÿÓÿÓÿÒÿÑÿÒÿÐÿÏÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 	            ÿÿ  ÿþÿýÿþÿýÿûÿüÿûÿùÿøÿùÿ÷ÿöÿ÷ÿöÿôÿóÿôÿòÿñÿòÿñÿïÿðÿïÿíÿìÿíÿìÿêÿëÿêÿèÿçÿèÿæÿåÿæÿåÿãÿâÿãÿáÿàÿáÿàÿÞÿßÿÞÿÜÿÛÿÜÿÚÿÙÿÚÿÙÿ×ÿÖÿ×ÿÕÿÔÿÕÿÔÿÒÿÓÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 	 	              ÿÿÿÿÿþÿýÿýÿüÿûÿùÿúÿùÿøÿøÿ÷ÿöÿôÿõÿôÿóÿóÿòÿñÿñÿðÿïÿîÿîÿíÿìÿìÿëÿêÿèÿéÿèÿçÿçÿæÿåÿãÿäÿãÿâÿâÿáÿàÿàÿßÿÞÿÜÿÝÿÜÿÛÿÛÿÚÿÙÿ×ÿØÿ×ÿÖÿÖÿÕÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 
+ 	              ÿÿÿþÿÿÿýÿüÿûÿüÿúÿùÿúÿøÿ÷ÿöÿ÷ÿõÿôÿõÿóÿòÿóÿòÿðÿïÿðÿîÿíÿîÿìÿëÿêÿëÿéÿèÿéÿçÿæÿåÿæÿäÿãÿäÿâÿáÿâÿàÿßÿÞÿßÿÝÿÜÿÝÿÛÿÚÿÙÿÚÿØÿ×ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 
+ 
+ 
+  	           ÿÿ  ÿÿÿþÿüÿýÿüÿúÿûÿúÿùÿ÷ÿøÿ÷ÿõÿöÿõÿôÿôÿóÿòÿðÿñÿðÿîÿïÿîÿíÿëÿìÿëÿéÿêÿéÿèÿæÿçÿæÿäÿåÿäÿâÿãÿâÿáÿßÿàÿßÿÝÿÞÿÝÿÜÿÚÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+  
+ 
+ 
+ 
+ 	  	            ÿÿÿþÿþÿýÿüÿýÿûÿúÿùÿùÿøÿ÷ÿøÿöÿõÿöÿôÿóÿòÿòÿñÿðÿñÿïÿîÿíÿíÿìÿëÿìÿêÿéÿèÿèÿçÿæÿæÿåÿäÿåÿãÿâÿáÿáÿàÿßÿàÿÞÿÝÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     
+ 
+ 
+ 
+ 	 
+ 	            ÿÿ  ÿÿÿýÿþÿýÿûÿúÿûÿúÿøÿùÿøÿöÿ÷ÿöÿôÿóÿôÿóÿñÿòÿñÿïÿîÿïÿîÿìÿíÿìÿêÿéÿêÿèÿçÿèÿçÿåÿæÿåÿãÿâÿãÿâÿàÿáÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      
+ 
+ 
+ 
+ 
+ 
+ 	              ÿÿÿÿÿþÿýÿüÿüÿûÿúÿúÿùÿøÿøÿ÷ÿöÿõÿõÿôÿóÿóÿòÿñÿðÿðÿïÿîÿîÿíÿìÿêÿëÿêÿéÿéÿèÿçÿçÿæÿåÿäÿäÿãÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ        
+ 
+ 
+ 
+ 
+ 	 
+                ÿþÿýÿþÿüÿûÿüÿúÿùÿúÿùÿ÷ÿöÿ÷ÿõÿôÿõÿôÿòÿñÿòÿðÿïÿðÿîÿíÿìÿíÿëÿêÿëÿéÿèÿéÿèÿæÿåÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ         
+  
+ 
+ 
+ 
+ 
+  	             ÿþÿÿÿþÿüÿýÿüÿûÿûÿúÿùÿ÷ÿøÿ÷ÿöÿöÿõÿôÿòÿóÿòÿðÿñÿðÿïÿíÿîÿíÿëÿìÿëÿêÿêÿéÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ            
+ 
+ 
+ 
+ 
+ 
+ 	  	             ÿÿÿþÿÿÿýÿüÿýÿûÿúÿùÿúÿøÿ÷ÿøÿöÿõÿôÿôÿóÿòÿóÿñÿðÿïÿïÿîÿíÿîÿìÿëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ             
+  
+ 
+ 
+ 
+ 	 
+ 	           ÿÿ  ÿÿÿýÿþÿýÿüÿúÿûÿúÿøÿùÿøÿöÿõÿöÿõÿóÿôÿóÿñÿðÿñÿðÿîÿïÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                
+ 
+ 
+ 
+ 
+ 
+ 	              ÿÿ  ÿþÿýÿüÿüÿûÿúÿúÿùÿøÿ÷ÿ÷ÿöÿõÿõÿôÿóÿòÿòÿñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                   
+ 
+ 
+ 
+ 	 
+                ÿþÿýÿþÿüÿûÿüÿûÿùÿøÿùÿ÷ÿöÿ÷ÿöÿôÿóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                     
+ 
+ 
+ 
+ 
+ 	 	             ÿþÿÿÿþÿýÿýÿüÿûÿùÿúÿùÿøÿøÿ÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+  
+                   
+ 
+ 
+ 
+ 
+ 
+ 	              ÿÿÿþÿÿÿýÿüÿûÿüÿúÿùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 
+ 
+                   
+  
+ 
+ 
+ 
+ 
+  	           ÿÿ  ÿÿÿþÿüÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+  
+ 
+                     
+  
+ 
+ 
+ 
+ 	              ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ !     
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+ 	 
+ 	         ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ " ! !    
+ 
+ 
+ 
+ 
+                    
+ 
+ 
+ 
+ 
+ 
+ 	 	     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ # " # "      
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+ 
+ 
+ 
+  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ % $ $ # "   !   
+  
+ 
+  
+                   
+  
+ 
+ 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ & % & $ # " " !   !  
+ 
+ 
+ 
+  
+                   
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ( & ' & $ # $ # ! " !  
+  
+ 
+ 
+ 
+                ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ) ( ( ' & % % $ # # " !      
+ 
+ 
+ 
+ 
+            ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ * ) * ) ' & ' % $ % $ " ! "      
+ 
+ 
+ 
+         ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ , + + * ) ' ( ' & & % $ " # "   !     
+ 
+  
+    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ - , - + * ) * ( ' ( & % $ $ # " # !   !  
+ 
+ 
+ 
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ / - . - , * + * ( ) ( & % & % # $ # ! " !   
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0 / 0 . - , , + * * ) ( ' ' & % % $ # $ " !ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 2 0 1 0 . - . , + , + ) ( ) ' & ' & $ %ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 3 2 2 1 0 . / . - - , + ) * ) ( ( 'ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 4 3 4 2 1 0 1 / . / - , + , * )ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 6 4 5 4 3 1 2 1 / 0 / . , -ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 7 6 7 5 4 3 3 2 1 2 0 /ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 9 7 8 7 5 4 5 4 2 3ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ : 9 9 8 7 6 6 5ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ; : ; : 8 7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ = < < ;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ > =ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿ   ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+    ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿ   ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿ     ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿ    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿ      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿ 
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿÿ 
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿ  
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿÿ  
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿÿ   
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿÿ   
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿÿ    
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿÿ    
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿÿ     
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿÿ     
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿÿ      
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿÿ      
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿÿ       
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿÿ       
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿÿ        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿÿ        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿÿ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ ÿ 
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡ÿ 
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ÿ   
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ÿ¡   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ÿ¢ !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ÿ£ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠÿ€ # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ÿ¥ $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿšÿŠ % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ©ÿ§ & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿªÿš ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ«ÿ© ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ÿª ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ÿ« * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ®ÿ¬ + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ÿ­ , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ°ÿ® - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ±ÿ¯ . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ²ÿ° / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ÿ± 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽÿ² 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµÿ³ 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ÿŽ 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ·ÿµ 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿžÿ¶ 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ÿ· 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿºÿž 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ»ÿ¹ 8 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒÿº 9 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœÿ» : 8 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸÿŒ ; 9 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ÿœ < : 8 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀÿŸ = ; 9 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁÿ¿ > < : 8 6 4 2 0 . , * ( & $ "   
+ 
+        
+ 
+      ÿþÿüÿúÿøÿöÿôÿòÿðÿîÿìÿêÿèÿæÿäÿâÿàÿÞÿÜÿÚÿØÿÖÿÔÿÒÿÐÿÎÿÌÿÊÿÈÿÆÿÄÿÂÿÀ ? = ; 9 7 5 3 1 / - + ) ' % # !  
+        
+ 
+ 	    ÿÿÿýÿûÿùÿ÷ÿõÿóÿñÿïÿíÿëÿéÿçÿåÿãÿáÿßÿÝÿÛÿÙÿ×ÿÕÿÓÿÑÿÏÿÍÿËÿÉÿÇÿÅÿÃÿÁ                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    ÿýÿûÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   ÿÿÿüÿùÿùÿöÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     ÿþÿûÿúÿ÷ÿõÿôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    ÿÿÿüÿüÿùÿöÿõÿóÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 	     ÿþÿýÿúÿøÿ÷ÿôÿñÿïÿîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+    ÿÿÿþÿüÿùÿøÿöÿóÿðÿïÿíÿêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 	 	     ÿýÿúÿúÿ÷ÿôÿòÿñÿîÿëÿëÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 
+    ÿÿÿüÿûÿøÿöÿóÿòÿðÿíÿìÿéÿçÿæÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+ 
+ 	     ÿýÿýÿúÿ÷ÿôÿôÿñÿîÿîÿëÿèÿçÿåÿâÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   
+ 
+    ÿÿÿþÿûÿùÿöÿõÿòÿðÿïÿìÿêÿéÿæÿãÿáÿàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    
+ 	     ÿÿÿýÿúÿ÷ÿ÷ÿôÿñÿðÿîÿëÿêÿèÿåÿâÿáÿßÿÜÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    
+ 
+     ÿþÿûÿùÿøÿõÿóÿòÿïÿìÿìÿéÿæÿäÿãÿàÿÝÿÝÿÚÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     
+ 	    ÿÿÿýÿúÿùÿ÷ÿôÿóÿñÿîÿíÿêÿèÿåÿäÿâÿßÿÞÿÛÿÙÿÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     
+ 
+ 
+    ÿþÿûÿûÿøÿõÿõÿòÿïÿïÿìÿéÿæÿæÿãÿàÿàÿÝÿÚÿ×ÿ×ÿÔÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      
+ 
+      ÿýÿüÿùÿ÷ÿöÿóÿñÿðÿíÿëÿèÿçÿäÿâÿáÿÞÿÜÿÙÿØÿÕÿÓÿÒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      
+ 
+ 
+    ÿþÿþÿûÿøÿ÷ÿõÿòÿñÿïÿìÿéÿéÿæÿãÿâÿàÿÝÿÚÿÚÿ×ÿÔÿÓÿÑÿÎÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ        
+ 	     ÿÿÿüÿúÿùÿöÿóÿóÿðÿíÿëÿêÿçÿåÿäÿáÿÞÿÜÿÛÿØÿÖÿÕÿÒÿÏÿÏÿÌÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+       
+ 
+ 	     ÿþÿûÿúÿøÿõÿôÿñÿïÿìÿëÿéÿæÿåÿãÿàÿÝÿÜÿÚÿ×ÿÖÿÔÿÑÿÐÿÍÿËÿÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+        
+ 
+    ÿÿÿüÿüÿùÿöÿöÿóÿðÿíÿíÿêÿçÿçÿäÿáÿßÿÞÿÛÿØÿØÿÕÿÒÿÒÿÏÿÌÿÉÿÉÿÆÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+       
+ 
+ 	    ÿþÿýÿúÿøÿ÷ÿôÿòÿïÿîÿëÿéÿèÿåÿãÿàÿßÿÝÿÚÿÙÿÖÿÔÿÓÿÐÿÎÿËÿÊÿÇÿÅÿÄÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   
+ 
+       
+ 
+    ÿÿÿÿÿüÿùÿøÿöÿóÿðÿðÿíÿêÿéÿçÿäÿáÿáÿÞÿÛÿÛÿØÿÕÿÔÿÒÿÏÿÌÿÌÿÉÿÆÿÅÿÃÿÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ !  
+        
+ 	      ÿýÿûÿúÿ÷ÿôÿòÿñÿîÿìÿëÿèÿåÿãÿâÿßÿÝÿÜÿÙÿ×ÿÖÿÓÿÐÿÎÿÍÿÊÿÈÿÇÿÄÿÁÿ¿ÿŸÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ #    
+        
+     ÿÿÿüÿûÿùÿöÿóÿòÿðÿíÿìÿêÿçÿäÿãÿáÿÞÿÝÿÛÿØÿ×ÿÕÿÒÿÏÿÎÿÌÿÉÿÈÿÆÿÃÿÀÿ¿ÿœÿºÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ $ ! ! 
+        
+ 
+ 	     ÿýÿýÿúÿ÷ÿõÿôÿñÿîÿîÿëÿèÿæÿåÿâÿßÿßÿÜÿÙÿÙÿÖÿÓÿÑÿÐÿÍÿÊÿÊÿÇÿÄÿÂÿÁÿŸÿ»ÿ»ÿžÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ & # "  
+        
+ 
+    ÿÿÿþÿûÿùÿöÿõÿóÿðÿïÿìÿêÿçÿæÿäÿáÿàÿÝÿÛÿÚÿ×ÿÕÿÒÿÑÿÏÿÌÿËÿÈÿÆÿÃÿÂÿÀÿœÿŒÿ¹ÿ·ÿŽÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ' $ $ ! 
+        
+ 
+ 	     ÿÿÿýÿúÿ÷ÿ÷ÿôÿñÿñÿîÿëÿèÿèÿåÿâÿâÿßÿÜÿÛÿÙÿÖÿÓÿÓÿÐÿÍÿÍÿÊÿÇÿÄÿÄÿÁÿŸÿŸÿ»ÿžÿµÿµÿ²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ( & % "   
+ 
+       
+ 
+     ÿþÿûÿùÿøÿõÿóÿòÿïÿíÿêÿéÿæÿäÿãÿàÿÞÿÝÿÚÿ×ÿÕÿÔÿÑÿÏÿÎÿËÿÉÿÆÿÅÿÂÿÀÿ¿ÿŒÿºÿ·ÿ¶ÿ³ÿ±ÿ°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ * ' & $ ! 
+ 
+        
+ 	      ÿýÿúÿùÿ÷ÿôÿóÿñÿîÿëÿëÿèÿåÿäÿâÿßÿÞÿÜÿÙÿÖÿÕÿÓÿÐÿÏÿÍÿÊÿÇÿÇÿÄÿÁÿÀÿŸÿ»ÿžÿžÿµÿ²ÿ±ÿ¯ÿ¬ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ + ( ( % "    
+       
+ 
+ 
+    ÿþÿüÿûÿøÿõÿõÿòÿïÿíÿìÿéÿçÿæÿãÿàÿàÿÝÿÚÿØÿ×ÿÔÿÑÿÑÿÎÿËÿÉÿÈÿÅÿÃÿÂÿ¿ÿŒÿºÿ¹ÿ¶ÿŽÿ³ÿ°ÿ­ÿ­ÿªÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ - * ) & $ !   
+        
+ 
+ 	     ÿýÿüÿúÿ÷ÿöÿóÿñÿîÿíÿëÿèÿçÿåÿâÿáÿÞÿÜÿÙÿØÿÖÿÓÿÒÿÏÿÍÿÊÿÉÿÇÿÄÿÃÿÁÿŸÿ»ÿºÿžÿµÿŽÿ²ÿ¯ÿ®ÿ«ÿ©ÿŠÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ . + + ( % " "  
+ 
+      
+ 
+ 
+    ÿþÿþÿûÿøÿøÿõÿòÿïÿïÿìÿéÿéÿæÿãÿãÿàÿÝÿÚÿÚÿ×ÿÔÿÔÿÑÿÎÿËÿËÿÈÿÅÿÅÿÂÿ¿ÿœÿŒÿ¹ÿ¶ÿ¶ÿ³ÿ°ÿ°ÿ­ÿªÿ§ÿ§ÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ / - , ) ' $ #   
+ 
+        
+ 	     ÿÿÿüÿúÿùÿöÿôÿñÿðÿíÿëÿêÿçÿåÿäÿáÿßÿÜÿÛÿØÿÖÿÕÿÒÿÐÿÍÿÌÿÉÿÇÿÆÿÃÿÁÿŸÿœÿ»ÿžÿ·ÿŽÿ²ÿ±ÿ®ÿ¬ÿ©ÿšÿ¥ÿ£ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 1 . - + ( % % "  
+ 
+       
+ 
+ 	    ÿþÿûÿúÿøÿõÿòÿòÿïÿìÿëÿéÿæÿåÿãÿàÿÝÿÝÿÚÿ×ÿÖÿÔÿÑÿÎÿÎÿËÿÈÿÇÿÅÿÂÿ¿ÿ¿ÿŒÿ¹ÿ¹ÿ¶ÿ³ÿ²ÿ°ÿ­ÿªÿªÿ§ÿ€ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 2 0 / , ) ' & # !   
+        
+ 
+    ÿÿÿýÿüÿùÿöÿôÿóÿðÿîÿíÿêÿçÿçÿäÿáÿßÿÞÿÛÿÙÿØÿÕÿÒÿÐÿÏÿÌÿÊÿÉÿÆÿÃÿÁÿÀÿœÿ»ÿºÿ·ÿµÿŽÿ±ÿ®ÿ¬ÿ«ÿšÿŠÿ¥ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 4 1 0 . + ( ' % " !  
+       
+ 
+ 
+    ÿþÿýÿûÿøÿõÿôÿòÿïÿîÿìÿéÿèÿåÿãÿàÿßÿÝÿÚÿÙÿ×ÿÔÿÑÿÐÿÎÿËÿÊÿÈÿÅÿÂÿÁÿ¿ÿŒÿ»ÿ¹ÿ¶ÿµÿ³ÿ°ÿ­ÿ¬ÿªÿ§ÿŠÿ€ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 5 2 2 / , * ) & # #   
+         
+    ÿÿÿÿÿüÿùÿ÷ÿöÿóÿðÿðÿíÿêÿêÿçÿäÿáÿáÿÞÿÛÿÛÿØÿÕÿÓÿÒÿÏÿÌÿÌÿÉÿÆÿÄÿÃÿÀÿœÿœÿºÿ·ÿ·ÿŽÿ±ÿ¯ÿ®ÿ«ÿšÿšÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 6 4 3 0 . + * ( % $ !  
+        
+ 
+      ÿýÿûÿøÿ÷ÿõÿòÿñÿîÿìÿëÿèÿæÿãÿâÿßÿÝÿÜÿÙÿ×ÿÔÿÓÿÑÿÎÿÍÿÊÿÈÿÅÿÄÿÂÿ¿ÿŸÿ»ÿ¹ÿžÿµÿ³ÿ°ÿ¯ÿ­ÿªÿ©ÿŠÿ€ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 8 5 4 2 / , , ) & & #   
+ 
+        
+     ÿÿÿüÿùÿùÿöÿóÿóÿðÿíÿìÿêÿçÿäÿäÿáÿÞÿÝÿÛÿØÿÕÿÕÿÒÿÏÿÏÿÌÿÉÿÆÿÆÿÃÿÀÿÀÿœÿºÿ¹ÿ·ÿŽÿ±ÿ±ÿ®ÿ«ÿ«ÿšÿ¥ÿ¢ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 9 7 6 3 0 . - * ( ' $ "  
+        
+ 
+ 	     ÿþÿûÿúÿ÷ÿõÿôÿñÿïÿîÿëÿèÿæÿåÿâÿàÿßÿÜÿÙÿ×ÿÖÿÓÿÑÿÐÿÍÿËÿÈÿÇÿÄÿÂÿÁÿŸÿŒÿ»ÿžÿµÿ³ÿ²ÿ¯ÿ­ÿ¬ÿ©ÿ§ÿ€ÿ£ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ; 8 7 5 2 / . , ) ( & #     
+        
+ 
+    ÿÿÿüÿüÿùÿöÿõÿóÿðÿïÿíÿêÿçÿæÿäÿáÿàÿÞÿÛÿØÿ×ÿÕÿÒÿÑÿÏÿÌÿÉÿÉÿÆÿÃÿÂÿÀÿœÿŒÿºÿ·ÿŽÿ³ÿ±ÿ®ÿ­ÿ«ÿšÿ¥ÿ¥ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ < 9 9 6 3 1 0 - * * ' $ " ! 
+ 
+       
+ 
+ 	     ÿþÿýÿúÿøÿ÷ÿôÿñÿñÿîÿëÿéÿèÿåÿâÿâÿßÿÜÿÚÿÙÿÖÿÓÿÓÿÐÿÍÿËÿÊÿÇÿÅÿÄÿÁÿŸÿŸÿ»ÿžÿ¶ÿµÿ²ÿ¯ÿ¯ÿ¬ÿ©ÿ§ÿŠÿ£ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ > ; : 7 5 2 1 / , + ( & # "   
+ 
+       
+ 
+    ÿÿÿþÿüÿùÿøÿöÿóÿòÿïÿíÿêÿéÿçÿäÿãÿàÿÞÿÛÿÚÿØÿÕÿÔÿÑÿÏÿÌÿËÿÉÿÆÿÅÿÃÿÀÿ¿ÿŒÿºÿ·ÿ¶ÿŽÿ±ÿ°ÿ­ÿ«ÿšÿ§ÿ¥ÿ¢ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ? < < 9 6 3 3 0 - - * ' $ $ ! 
+ 
+        
+ 	 	      ÿýÿúÿúÿ÷ÿôÿôÿñÿîÿëÿëÿèÿåÿåÿâÿßÿÜÿÜÿÙÿÖÿÖÿÓÿÐÿÍÿÍÿÊÿÇÿÇÿÄÿÁÿÁÿŸÿ»ÿžÿžÿµÿ²ÿ²ÿ¯ÿ¬ÿ©ÿ©ÿŠÿ£ÿ£ÿ ÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿ
+ÿÿÿÿÿ = : 8 5 4 1 / . + ) & % "    
+       
+ 
+ 
+    ÿþÿüÿûÿøÿöÿõÿòÿðÿíÿìÿéÿçÿæÿãÿáÿÞÿÝÿÚÿØÿ×ÿÔÿÒÿÏÿÎÿËÿÉÿÈÿÅÿÃÿÂÿ¿ÿœÿºÿ¹ÿ¶ÿŽÿ³ÿ°ÿ®ÿ«ÿªÿ§ÿ¥ÿ€ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 9 6 6 3 0 / - * ' ' $ !   
+        
+ 
+ 	     ÿýÿüÿúÿ÷ÿöÿôÿñÿîÿîÿëÿèÿçÿåÿâÿßÿßÿÜÿÙÿØÿÖÿÓÿÐÿÐÿÍÿÊÿÉÿÇÿÄÿÃÿÁÿŸÿ»ÿ»ÿžÿµÿŽÿ²ÿ¯ÿ¬ÿ¬ÿ©ÿŠÿ¥ÿ£ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿ 7 4 2 1 . + ) ( % # "  
+ 
+       
+ 
+    ÿÿÿþÿûÿøÿøÿõÿòÿðÿïÿìÿêÿéÿæÿãÿáÿàÿÝÿÛÿÚÿ×ÿÔÿÒÿÑÿÎÿÌÿËÿÈÿÅÿÅÿÂÿ¿ÿœÿŒÿ¹ÿ·ÿ¶ÿ³ÿ°ÿ®ÿ­ÿªÿšÿ§ÿ€ÿ¡ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 3 2 0 - * ) ' $ # ! 
+ 
+        
+ 	     ÿÿÿýÿúÿùÿöÿôÿñÿðÿîÿëÿêÿèÿåÿâÿáÿßÿÜÿÛÿÙÿÖÿÓÿÒÿÐÿÍÿÌÿÊÿÇÿÆÿÃÿÁÿŸÿœÿ»ÿžÿ·ÿµÿ²ÿ¯ÿ®ÿ¬ÿ©ÿšÿŠÿ£ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 1 . , + ( % % "   
+       
+ 
+     ÿþÿûÿûÿøÿõÿòÿòÿïÿìÿìÿéÿæÿäÿãÿàÿÝÿÝÿÚÿ×ÿÕÿÔÿÑÿÎÿÎÿËÿÈÿÈÿÅÿÂÿ¿ÿ¿ÿŒÿ¹ÿ¹ÿ¶ÿ³ÿ±ÿ°ÿ­ÿªÿªÿ§ÿ€ÿ€ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ - , * ' & # !   
+        
+ 	    ÿÿÿýÿüÿùÿ÷ÿôÿóÿðÿîÿíÿêÿèÿåÿäÿâÿßÿÞÿÛÿÙÿÖÿÕÿÓÿÐÿÏÿÌÿÊÿÉÿÆÿÄÿÁÿÀÿœÿ»ÿºÿ·ÿµÿ²ÿ±ÿ¯ÿ¬ÿ«ÿšÿŠÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ + ( ( % " !  
+       
+ 
+ 
+    ÿþÿýÿûÿøÿõÿõÿòÿïÿîÿìÿéÿæÿæÿãÿàÿàÿÝÿÚÿ×ÿ×ÿÔÿÑÿÑÿÎÿËÿÊÿÈÿÅÿÂÿÂÿ¿ÿŒÿ»ÿ¹ÿ¶ÿ³ÿ³ÿ°ÿ­ÿ­ÿªÿ§ÿŠÿ€ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ) & $ #   
+        
+ 
+      ÿÿÿüÿùÿ÷ÿöÿóÿñÿðÿíÿêÿèÿçÿäÿâÿáÿÞÿÜÿÙÿØÿÕÿÓÿÒÿÏÿÍÿÌÿÉÿÆÿÄÿÃÿÀÿŸÿœÿºÿ·ÿµÿŽÿ±ÿ¯ÿ®ÿ«ÿ©ÿšÿ¥ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ % $ "  
+       
+ 
+ 
+      ÿþÿûÿøÿ÷ÿõÿòÿñÿïÿìÿéÿèÿæÿãÿâÿàÿÝÿÚÿÚÿ×ÿÔÿÓÿÑÿÎÿÍÿËÿÈÿÅÿÄÿÂÿ¿ÿŸÿŒÿ¹ÿ¶ÿµÿ³ÿ°ÿ¯ÿ­ÿªÿ©ÿ§ÿ€ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ #   
+ 
+        
+     ÿÿÿüÿúÿùÿöÿóÿóÿðÿíÿëÿêÿçÿäÿäÿáÿÞÿÜÿÛÿØÿÖÿÕÿÒÿÏÿÏÿÌÿÉÿÇÿÆÿÃÿÀÿÀÿœÿºÿžÿ·ÿŽÿ±ÿ±ÿ®ÿ«ÿ«ÿšÿ¥ÿ£ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+ 
+       
+ 
+ 	     ÿþÿûÿúÿøÿõÿôÿñÿïÿìÿëÿéÿæÿåÿâÿàÿÝÿÜÿÚÿ×ÿÖÿÔÿÑÿÐÿÍÿËÿÈÿÇÿÅÿÂÿÁÿŸÿŒÿ¹ÿžÿ¶ÿ³ÿ²ÿ¯ÿ­ÿ¬ÿ©ÿ§ÿ€ÿ£ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+        
+ 
+    ÿÿÿüÿüÿùÿöÿöÿóÿðÿíÿíÿêÿçÿçÿäÿáÿÞÿÞÿÛÿØÿØÿÕÿÒÿÒÿÏÿÌÿÉÿÉÿÆÿÃÿÃÿÀÿœÿºÿºÿ·ÿŽÿŽÿ±ÿ®ÿ­ÿ«ÿšÿ¥ÿ¥ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ       
+ 
+ 	     ÿþÿýÿúÿøÿ÷ÿôÿòÿïÿîÿëÿéÿèÿåÿãÿàÿßÿÜÿÚÿÙÿÖÿÔÿÓÿÐÿÎÿËÿÊÿÇÿÅÿÄÿÁÿ¿ÿŒÿ»ÿžÿ¶ÿµÿ²ÿ°ÿ¯ÿ¬ÿ©ÿ§ÿŠÿ£ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      
+ 
+    ÿÿÿþÿüÿùÿøÿöÿóÿðÿðÿíÿêÿéÿçÿäÿáÿáÿÞÿÛÿÚÿØÿÕÿÔÿÒÿÏÿÌÿÌÿÉÿÆÿÅÿÃÿÀÿœÿœÿºÿ·ÿ¶ÿŽÿ±ÿ°ÿ®ÿ«ÿšÿ§ÿ¥ÿ¢ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     
+ 	 	     ÿýÿúÿúÿ÷ÿôÿòÿñÿîÿìÿëÿèÿåÿãÿâÿßÿÝÿÜÿÙÿÖÿÖÿÓÿÐÿÎÿÍÿÊÿÈÿÇÿÄÿÁÿ¿ÿŸÿ»ÿ¹ÿžÿµÿ²ÿ²ÿ¯ÿ¬ÿªÿ©ÿŠÿ£ÿ£ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    
+ 
+    ÿÿÿüÿûÿøÿöÿóÿòÿðÿíÿìÿêÿçÿäÿãÿáÿÞÿÝÿÛÿØÿ×ÿÔÿÒÿÏÿÎÿÌÿÉÿÈÿÆÿÃÿÀÿ¿ÿœÿºÿ¹ÿ·ÿŽÿ³ÿ°ÿ®ÿ«ÿªÿšÿ¥ÿ€ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+ 
+ 	     ÿýÿýÿúÿ÷ÿôÿôÿñÿîÿîÿëÿèÿæÿåÿâÿßÿßÿÜÿÙÿÙÿÖÿÓÿÐÿÐÿÍÿÊÿÊÿÇÿÄÿÂÿÁÿŸÿ»ÿ»ÿžÿµÿµÿ²ÿ¯ÿ¬ÿ¬ÿ©ÿŠÿŠÿ£ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+    ÿÿÿþÿûÿùÿöÿõÿòÿðÿïÿìÿêÿçÿæÿäÿáÿàÿÝÿÛÿÚÿ×ÿÕÿÒÿÑÿÎÿÌÿËÿÈÿÆÿÃÿÂÿÀÿœÿŒÿ¹ÿ·ÿ¶ÿ³ÿ±ÿ®ÿ­ÿªÿšÿ§ÿ€ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 	     ÿÿÿýÿúÿ÷ÿ÷ÿôÿñÿðÿîÿëÿèÿèÿåÿâÿâÿßÿÜÿÛÿÙÿÖÿÓÿÓÿÐÿÍÿÌÿÊÿÇÿÄÿÄÿÁÿŸÿŸÿ»ÿžÿ·ÿµÿ²ÿ¯ÿ¯ÿ¬ÿ©ÿšÿŠÿ£ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    ÿþÿûÿùÿøÿõÿóÿòÿïÿìÿêÿéÿæÿäÿãÿàÿÞÿÝÿÚÿ×ÿÕÿÔÿÑÿÏÿÎÿËÿÈÿÆÿÅÿÂÿÀÿ¿ÿŒÿºÿ¹ÿ¶ÿ³ÿ±ÿ°ÿ­ÿ«ÿªÿ§ÿ€ÿ¢ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ    ÿýÿúÿùÿ÷ÿôÿóÿñÿîÿëÿêÿèÿåÿäÿâÿßÿÞÿÜÿÙÿÖÿÕÿÓÿÐÿÏÿÍÿÊÿÇÿÆÿÄÿÁÿÀÿŸÿ»ÿºÿžÿµÿ²ÿ±ÿ¯ÿ¬ÿ«ÿ©ÿŠÿ£ÿ¢ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿþÿüÿûÿøÿõÿõÿòÿïÿíÿìÿéÿæÿæÿãÿàÿàÿÝÿÚÿØÿ×ÿÔÿÑÿÑÿÎÿËÿÉÿÈÿÅÿÂÿÂÿ¿ÿŒÿŒÿ¹ÿ¶ÿŽÿ³ÿ°ÿ­ÿ­ÿªÿ§ÿ¥ÿ€ÿ¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿüÿúÿ÷ÿöÿóÿñÿîÿíÿëÿèÿçÿäÿâÿáÿÞÿÜÿÙÿØÿÖÿÓÿÒÿÏÿÍÿÊÿÉÿÇÿÄÿÃÿÀÿŸÿœÿºÿžÿµÿŽÿ²ÿ¯ÿ®ÿ«ÿ©ÿŠÿ¥ÿ£ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûÿøÿøÿõÿòÿïÿïÿìÿéÿéÿæÿãÿâÿàÿÝÿÚÿÚÿ×ÿÔÿÔÿÑÿÎÿËÿËÿÈÿÅÿÅÿÂÿ¿ÿŸÿŒÿ¹ÿ¶ÿ¶ÿ³ÿ°ÿ°ÿ­ÿªÿ§ÿ§ÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùÿöÿôÿñÿðÿíÿëÿêÿçÿåÿäÿáÿÞÿÜÿÛÿØÿÖÿÕÿÒÿÐÿÍÿÌÿÉÿÇÿÆÿÃÿÁÿÀÿœÿºÿžÿ·ÿŽÿ²ÿ±ÿ®ÿ¬ÿ©ÿšÿ¥ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõÿòÿòÿïÿìÿëÿéÿæÿåÿãÿàÿÝÿÜÿÚÿ×ÿÖÿÔÿÑÿÎÿÎÿËÿÈÿÇÿÅÿÂÿÁÿ¿ÿŒÿ¹ÿžÿ¶ÿ³ÿ²ÿ°ÿ­ÿªÿªÿ§ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÿðÿîÿíÿêÿçÿçÿäÿáÿßÿÞÿÛÿØÿØÿÕÿÒÿÐÿÏÿÌÿÊÿÉÿÆÿÃÿÃÿÀÿœÿ»ÿºÿ·ÿŽÿŽÿ±ÿ®ÿ¬ÿ«ÿšÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïÿîÿìÿéÿèÿåÿãÿàÿßÿÝÿÚÿÙÿÖÿÔÿÑÿÐÿÎÿËÿÊÿÈÿÅÿÄÿÁÿ¿ÿŒÿ»ÿ¹ÿ¶ÿµÿ²ÿ°ÿ­ÿ¬ÿªÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíÿêÿêÿçÿäÿáÿáÿÞÿÛÿÛÿØÿÕÿÒÿÒÿÏÿÌÿÌÿÉÿÆÿÆÿÃÿÀÿœÿœÿºÿ·ÿ·ÿŽÿ±ÿ®ÿ®ÿ«ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëÿèÿæÿãÿâÿßÿÝÿÜÿÙÿ×ÿÔÿÓÿÐÿÎÿÍÿÊÿÈÿÇÿÄÿÂÿ¿ÿŸÿ»ÿ¹ÿžÿµÿ³ÿ°ÿ¯ÿ¬ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçÿäÿäÿáÿÞÿÝÿÛÿØÿÕÿÕÿÒÿÏÿÎÿÌÿÉÿÈÿÆÿÃÿÀÿÀÿœÿºÿ¹ÿ·ÿŽÿ±ÿ±ÿ®ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿåÿâÿàÿßÿÜÿÙÿ×ÿÖÿÓÿÑÿÐÿÍÿÊÿÊÿÇÿÄÿÂÿÁÿŸÿŒÿ»ÿžÿµÿ³ÿ²ÿ¯ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿáÿàÿÞÿÛÿØÿ×ÿÕÿÒÿÑÿÏÿÌÿËÿÈÿÆÿÃÿÂÿÀÿœÿŒÿºÿ·ÿŽÿ³ÿ±ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßÿÜÿÚÿÙÿÖÿÓÿÓÿÐÿÍÿÍÿÊÿÇÿÄÿÄÿÁÿŸÿŸÿ»ÿžÿ¶ÿµÿ²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÚÿØÿÕÿÔÿÑÿÏÿÎÿËÿÉÿÆÿÅÿÂÿÀÿ¿ÿŒÿºÿ·ÿ¶ÿŽÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙÿÖÿÖÿÓÿÐÿÏÿÍÿÊÿÇÿÇÿÄÿÁÿÀÿŸÿ»ÿžÿžÿµÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ×ÿÔÿÒÿÑÿÎÿËÿÉÿÈÿÅÿÃÿÂÿ¿ÿŒÿºÿ¹ÿ¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÓÿÒÿÐÿÍÿÊÿÉÿÇÿÄÿÃÿÁÿŸÿ»ÿºÿžÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÑÿÎÿÌÿËÿÈÿÅÿÅÿÂÿ¿ÿœÿŒÿ¹ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍÿÌÿÊÿÇÿÆÿÃÿÁÿŸÿœÿ»ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËÿÈÿÈÿÅÿÂÿ¿ÿ¿ÿŒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÉÿÆÿÄÿÁÿÀÿœÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅÿÂÿÂÿ¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÃÿÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              ? > = < ; : 9 8 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	           = < ; : 9 8 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþ ; : 9 8 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿü 9 8 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿú 7 6 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿø 5 4 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿö 3 2 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿô 1 0 / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿò / . - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿð - , + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿî + * ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿì ) ( ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿê ' & % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿè % $ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæ # " !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿä !    
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâ  
+ 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿà 
+ 
+               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞ               
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜ             
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚ           
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØ         
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖ       
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔ     
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒ   
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐ 
+ 
+ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎ 
+ 
+ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌ 	          ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊ         ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈ       ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆ     ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄ   ÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÿÿþÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿýÿüÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿûÿúÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿùÿøÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ÷ÿöÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿõÿôÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿóÿòÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿñÿðÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿïÿîÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿíÿìÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿëÿêÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿéÿèÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿçÿæÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿåÿäÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿãÿâÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿáÿàÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿßÿÞÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÝÿÜÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÛÿÚÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÙÿØÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿ×ÿÖÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÕÿÔÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÓÿÒÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÑÿÐÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÏÿÎÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍÿÌÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËÿÊÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÉÿÈÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÇÿÆÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅÿÄÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÃÿÂÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿÿÁÿÀÿ¿ÿŸÿœÿŒÿ»ÿºÿ¹ÿžÿ·ÿ¶ÿµÿŽÿ³ÿ²ÿ±ÿ°ÿ¯ÿ®ÿ­ÿ¬ÿ«ÿªÿ©ÿšÿ§ÿŠÿ¥ÿ€ÿ£ÿ¢ÿ¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   91 / length of data axis 1                          NAXIS2  =                   91 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ = >ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ; < < =ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 7 8 : ; : ;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 5 6 6 7 8 9 9 :ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 3 2 4 5 4 5 7 8 7 9ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ / 0 2 1 2 3 3 4 5 7 6 7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ - , . / 0 / 1 2 1 3 4 5 4 6ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ) * , + , - / . / 1 0 1 2 4 3 4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ' ( ( ) * ) + , - - . / . 0 1 2 2 3ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ % $ & ' & ' ) ( ) + , + , . - . 0 1 0 2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ! " $ # $ % % & ' ' ( ) * * + , , - . 0 / 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+   ! " ! # $ # % & % & ( ) ( * + * , - . - /ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  
+ 
+ 
+ 
+  !   ! # " # $ $ % & ( ' ( * ) * + - , -ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ     
+  
+ 
+     !   " # " $ % & & ' ( ' ) * + + ,ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ          
+ 
+ 
+ 
+      " ! " $ % $ % ' & ' ) * ) *ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ             
+ 
+ 
+ 
+ 
+      ! " # # $ % % & ' ( ( )ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                 
+ 
+ 
+ 
+  
+  ! " ! # $ # $ & ' & (ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+                   
+  
+ 
+ 
+ 
+  !   ! " " # $ & % &ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
+ 
+ 
+ 
+  
+                   
+  
+ 
+  
+   !   " # $ $ %ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   
+ 
+ 
+ 
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+      " # " #ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ      	 	 
+ 
+ 
+ 
+ 
+ 
+                    
+ 
+ 
+ 
+ 
+    ! ! "ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ          	 
+ 	 
+ 
+ 
+ 
+                     
+ 
+ 
+ 
+     !ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ               	 
+ 
+ 
+ 
+  
+                     
+ 
+  
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿüÿþÿÿ  ÿÿ            	  
+ 
+ 
+ 
+ 
+  
+                   
+ 
+ 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùÿúÿüÿûÿüÿýÿÿÿþÿÿ               	 
+ 
+ 
+ 
+ 
+ 
+                   
+  
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷ÿøÿøÿùÿúÿùÿûÿüÿýÿýÿþÿÿÿþ              	 	 
+ 
+ 
+ 
+ 
+                    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÿôÿöÿ÷ÿöÿ÷ÿùÿøÿùÿûÿüÿûÿüÿþÿýÿþ                 
+ 	 
+ 
+ 
+ 
+                  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñÿòÿòÿóÿôÿõÿõÿöÿ÷ÿ÷ÿøÿùÿúÿúÿûÿüÿüÿýÿþ  ÿÿ               	 
+ 
+ 
+ 
+ 
+ 
+               ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïÿîÿðÿñÿðÿñÿóÿôÿóÿõÿöÿõÿöÿøÿùÿøÿúÿûÿúÿüÿýÿþÿýÿÿ  ÿÿ            	 
+ 	 
+ 
+ 
+ 
+  
+            ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëÿìÿîÿíÿîÿïÿïÿðÿñÿóÿòÿóÿôÿôÿõÿöÿøÿ÷ÿøÿúÿùÿúÿûÿýÿüÿýÿÿÿþÿÿ              	  	 
+ 
+ 
+ 
+ 
+ 
+           ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿéÿêÿêÿëÿìÿëÿíÿîÿíÿïÿðÿñÿðÿòÿóÿòÿôÿõÿöÿöÿ÷ÿøÿ÷ÿùÿúÿûÿûÿüÿýÿüÿþÿÿÿþ              	  
+ 
+ 
+ 
+ 
+  
+        ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿåÿæÿèÿéÿèÿéÿëÿêÿëÿíÿìÿíÿîÿðÿïÿðÿòÿñÿòÿôÿõÿôÿõÿ÷ÿöÿ÷ÿùÿúÿùÿúÿüÿûÿüÿþÿýÿþ                 
+ 	 
+ 
+ 
+ 
+ 
+       ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãÿäÿäÿåÿæÿçÿçÿèÿéÿéÿêÿëÿêÿìÿíÿîÿîÿïÿðÿðÿñÿòÿóÿóÿôÿõÿõÿöÿ÷ÿøÿøÿùÿúÿúÿûÿüÿüÿýÿþÿÿÿÿ               	 
+ 
+ 
+ 
+ 
+ 
+     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿáÿàÿâÿãÿâÿãÿåÿæÿåÿçÿèÿçÿèÿêÿéÿêÿìÿíÿìÿîÿïÿîÿïÿñÿòÿñÿóÿôÿóÿôÿöÿ÷ÿöÿøÿùÿøÿúÿûÿúÿûÿýÿþÿýÿÿ  ÿÿ             	 
+ 	 
+ 
+ 
+ 
+    ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÝÿÞÿàÿßÿàÿáÿáÿâÿãÿåÿäÿåÿæÿæÿçÿèÿèÿéÿêÿìÿëÿìÿíÿíÿîÿïÿñÿðÿñÿòÿòÿóÿôÿöÿõÿöÿøÿ÷ÿøÿùÿùÿúÿûÿýÿüÿýÿþÿþÿÿ             	  	 
+ 
+ 
+ 
+  
+ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÚÿÜÿÝÿÞÿÝÿßÿàÿßÿáÿâÿãÿâÿäÿåÿäÿæÿçÿæÿèÿéÿêÿéÿëÿìÿëÿíÿîÿïÿîÿðÿñÿðÿòÿóÿôÿôÿõÿöÿõÿ÷ÿøÿ÷ÿùÿúÿûÿúÿüÿýÿüÿþÿÿ  ÿÿ            	  
+ 
+ 
+ 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ×ÿØÿÚÿÙÿÚÿÛÿÝÿÜÿÝÿßÿÞÿßÿàÿâÿáÿâÿäÿãÿäÿæÿåÿæÿçÿéÿèÿéÿëÿêÿëÿìÿîÿíÿîÿðÿïÿðÿòÿóÿòÿóÿõÿôÿõÿ÷ÿöÿ÷ÿøÿúÿùÿúÿüÿûÿüÿýÿÿÿþÿÿ               	 
+ 
+ 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÕÿÖÿÖÿ×ÿØÿ×ÿÙÿÚÿÛÿÛÿÜÿÝÿÜÿÞÿßÿàÿàÿáÿâÿâÿãÿäÿãÿåÿæÿçÿçÿèÿéÿèÿêÿëÿìÿìÿíÿîÿîÿïÿðÿñÿñÿòÿóÿóÿôÿõÿôÿöÿ÷ÿøÿøÿùÿúÿùÿûÿüÿýÿýÿþÿÿÿÿ               	 	 
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÓÿÒÿÔÿÕÿÔÿÕÿ×ÿÖÿ×ÿÙÿÚÿÙÿÚÿÜÿÛÿÜÿÞÿßÿÞÿàÿáÿàÿáÿãÿâÿãÿåÿæÿåÿæÿèÿçÿèÿêÿëÿêÿìÿíÿìÿíÿïÿðÿïÿñÿòÿñÿòÿôÿóÿôÿöÿ÷ÿöÿ÷ÿùÿøÿùÿûÿüÿûÿýÿþÿýÿþ  ÿÿ             	ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÏÿÐÿÒÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿØÿØÿÙÿÚÿÚÿÛÿÜÿÞÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿäÿäÿåÿæÿæÿçÿèÿêÿéÿêÿëÿëÿìÿíÿïÿîÿïÿðÿðÿñÿòÿòÿóÿôÿõÿõÿöÿ÷ÿ÷ÿøÿùÿûÿúÿûÿüÿüÿýÿþÿþÿÿ            ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍÿÌÿÎÿÏÿÐÿÏÿÑÿÒÿÑÿÓÿÔÿÓÿÔÿÖÿ×ÿÖÿØÿÙÿØÿÚÿÛÿÜÿÛÿÝÿÞÿÝÿßÿàÿßÿàÿâÿãÿâÿäÿåÿäÿæÿçÿèÿçÿéÿêÿéÿëÿìÿíÿìÿîÿïÿîÿðÿñÿðÿñÿóÿôÿóÿõÿöÿõÿ÷ÿøÿùÿøÿúÿûÿúÿüÿýÿüÿýÿÿ  ÿÿ        ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÉÿÊÿÌÿËÿÌÿÍÿÏÿÎÿÏÿÑÿÐÿÑÿÒÿÒÿÓÿÔÿÖÿÕÿÖÿØÿ×ÿØÿÙÿÛÿÚÿÛÿÝÿÜÿÝÿÞÿÞÿßÿàÿâÿáÿâÿäÿãÿäÿåÿçÿæÿçÿéÿèÿéÿêÿìÿëÿìÿîÿíÿîÿïÿïÿðÿñÿóÿòÿóÿõÿôÿõÿöÿøÿ÷ÿøÿúÿùÿúÿûÿûÿüÿýÿÿÿþÿÿ        ÿÿÿÿÿÿÿÿÿÿÿÿÿÇÿÈÿÈÿÉÿÊÿÉÿËÿÌÿÍÿÍÿÎÿÏÿÎÿÐÿÑÿÐÿÒÿÓÿÔÿÔÿÕÿÖÿÕÿ×ÿØÿÙÿÙÿÚÿÛÿÚÿÜÿÝÿÜÿÞÿßÿàÿàÿáÿâÿáÿãÿäÿåÿåÿæÿçÿæÿèÿéÿêÿêÿëÿìÿëÿíÿîÿíÿïÿðÿñÿñÿòÿóÿòÿôÿõÿöÿöÿ÷ÿøÿ÷ÿùÿúÿùÿûÿüÿýÿýÿþÿÿÿþ      ÿÿÿÿÿÿÿÿÿÃÿÄÿÆÿÇÿÆÿÇÿÉÿÈÿÉÿËÿÌÿËÿÌÿÎÿÍÿÎÿÐÿÏÿÐÿÒÿÓÿÒÿÓÿÕÿÔÿÕÿ×ÿØÿ×ÿØÿÚÿÙÿÚÿÜÿÛÿÜÿÞÿßÿÞÿßÿáÿàÿáÿãÿäÿãÿäÿæÿåÿæÿèÿéÿèÿéÿëÿêÿëÿíÿìÿíÿïÿðÿïÿðÿòÿñÿòÿôÿõÿôÿõÿ÷ÿöÿ÷ÿùÿøÿùÿûÿüÿûÿüÿþÿýÿþ      ÿÿÿÿÿÁÿÂÿÂÿÃÿÄÿÅÿÅÿÆÿÇÿÇÿÈÿÉÿÊÿÊÿËÿÌÿÌÿÍÿÎÿÎÿÏÿÐÿÑÿÑÿÒÿÓÿÓÿÔÿÕÿÖÿÖÿ×ÿØÿØÿÙÿÚÿÚÿÛÿÜÿÝÿÝÿÞÿßÿßÿàÿáÿâÿâÿãÿäÿäÿåÿæÿçÿçÿèÿéÿéÿêÿëÿëÿìÿíÿîÿîÿïÿðÿðÿñÿòÿóÿóÿôÿõÿõÿöÿ÷ÿ÷ÿøÿùÿúÿúÿûÿüÿüÿýÿþÿÿÿÿ  ÿÿÿÿÿÀÿÁÿÀÿÁÿÃÿÄÿÃÿÅÿÆÿÅÿÆÿÈÿÉÿÈÿÊÿËÿÊÿÌÿÍÿÌÿÍÿÏÿÐÿÏÿÑÿÒÿÑÿÒÿÔÿÕÿÔÿÖÿ×ÿÖÿØÿÙÿØÿÙÿÛÿÜÿÛÿÝÿÞÿÝÿÞÿàÿáÿàÿâÿãÿâÿãÿåÿæÿåÿçÿèÿçÿéÿêÿéÿêÿìÿíÿìÿîÿïÿîÿïÿñÿòÿñÿóÿôÿóÿõÿöÿõÿöÿøÿùÿøÿúÿûÿúÿûÿýÿþÿÿÿÿÿÿÿÿÿŸÿ¿ÿ¿ÿÀÿÁÿÃÿÂÿÃÿÄÿÄÿÅÿÆÿÈÿÇÿÈÿÊÿÉÿÊÿËÿËÿÌÿÍÿÏÿÎÿÏÿÐÿÐÿÑÿÒÿÔÿÓÿÔÿÖÿÕÿÖÿ×ÿ×ÿØÿÙÿÛÿÚÿÛÿÜÿÜÿÝÿÞÿàÿßÿàÿáÿáÿâÿãÿåÿäÿåÿçÿæÿçÿèÿèÿéÿêÿìÿëÿìÿíÿíÿîÿïÿñÿðÿñÿóÿòÿóÿôÿôÿõÿöÿøÿ÷ÿøÿùÿùÿúÿÿÿÿÿÿÿÿÿÿÿÿÿœÿŸÿœÿ¿ÿÀÿÁÿÀÿÂÿÃÿÂÿÄÿÅÿÆÿÆÿÇÿÈÿÇÿÉÿÊÿÉÿËÿÌÿÍÿÌÿÎÿÏÿÎÿÐÿÑÿÒÿÒÿÓÿÔÿÓÿÕÿÖÿÕÿ×ÿØÿÙÿØÿÚÿÛÿÚÿÜÿÝÿÞÿÝÿßÿàÿßÿáÿâÿãÿãÿäÿåÿäÿæÿçÿæÿèÿéÿêÿéÿëÿìÿëÿíÿîÿïÿïÿðÿñÿðÿòÿóÿòÿôÿõÿöÿõÿ÷ÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»ÿœÿŒÿœÿŸÿÀÿ¿ÿÀÿÂÿÁÿÂÿÄÿÅÿÄÿÅÿÇÿÆÿÇÿÉÿÈÿÉÿÊÿÌÿËÿÌÿÎÿÍÿÎÿÐÿÑÿÐÿÑÿÓÿÒÿÓÿÕÿÔÿÕÿÖÿØÿ×ÿØÿÚÿÙÿÚÿÛÿÝÿÜÿÝÿßÿÞÿßÿáÿâÿáÿâÿäÿãÿäÿæÿåÿæÿçÿéÿèÿéÿëÿêÿëÿíÿîÿíÿîÿðÿïÿðÿòÿñÿòÿóÿõÿôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºÿ»ÿºÿŒÿœÿŸÿŸÿ¿ÿÀÿÀÿÁÿÂÿÃÿÃÿÄÿÅÿÅÿÆÿÇÿÆÿÈÿÉÿÊÿÊÿËÿÌÿÌÿÍÿÎÿÏÿÏÿÐÿÑÿÑÿÒÿÓÿÒÿÔÿÕÿÖÿÖÿ×ÿØÿ×ÿÙÿÚÿÛÿÛÿÜÿÝÿÝÿÞÿßÿàÿàÿáÿâÿâÿãÿäÿãÿåÿæÿçÿçÿèÿéÿéÿêÿëÿìÿìÿíÿîÿîÿïÿðÿïÿñÿòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿžÿºÿ¹ÿºÿŒÿœÿŒÿŸÿ¿ÿŸÿ¿ÿÁÿÂÿÁÿÃÿÄÿÃÿÄÿÆÿÅÿÆÿÈÿÉÿÈÿÊÿËÿÊÿËÿÍÿÎÿÍÿÏÿÐÿÏÿÐÿÒÿÑÿÒÿÔÿÕÿÔÿÕÿ×ÿÖÿ×ÿÙÿÚÿÙÿÛÿÜÿÛÿÜÿÞÿßÿÞÿàÿáÿàÿáÿãÿâÿãÿåÿæÿåÿçÿèÿçÿèÿêÿëÿêÿìÿíÿìÿíÿïÿîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ·ÿžÿžÿ¹ÿºÿŒÿ»ÿŒÿœÿœÿŸÿ¿ÿÁÿÀÿÁÿÂÿÂÿÃÿÄÿÄÿÅÿÆÿÈÿÇÿÈÿÉÿÉÿÊÿËÿÍÿÌÿÍÿÎÿÎÿÏÿÐÿÐÿÑÿÒÿÓÿÓÿÔÿÕÿÕÿÖÿ×ÿÙÿØÿÙÿÚÿÚÿÛÿÜÿÞÿÝÿÞÿßÿßÿàÿáÿáÿâÿãÿåÿäÿåÿæÿæÿçÿèÿêÿéÿêÿëÿëÿìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¶ÿ·ÿ¶ÿžÿ¹ÿºÿ¹ÿ»ÿŒÿ»ÿœÿŸÿ¿ÿŸÿÀÿÁÿÀÿÂÿÃÿÂÿÄÿÅÿÆÿÅÿÇÿÈÿÇÿÉÿÊÿËÿÊÿÌÿÍÿÌÿÎÿÏÿÎÿÏÿÑÿÒÿÑÿÓÿÔÿÓÿÕÿÖÿ×ÿÖÿØÿÙÿØÿÚÿÛÿÜÿÛÿÝÿÞÿÝÿßÿàÿßÿáÿâÿãÿâÿäÿåÿäÿæÿçÿèÿçÿéÿêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŽÿ¶ÿµÿ¶ÿ·ÿ¹ÿžÿ¹ÿ»ÿºÿ»ÿŒÿŸÿœÿŸÿÀÿ¿ÿÀÿÂÿÁÿÂÿÃÿÅÿÄÿÅÿÇÿÆÿÇÿÈÿÊÿÉÿÊÿÌÿËÿÌÿÍÿÍÿÎÿÏÿÑÿÐÿÑÿÓÿÒÿÓÿÔÿÖÿÕÿÖÿØÿ×ÿØÿÙÿÛÿÚÿÛÿÝÿÜÿÝÿßÿÞÿßÿàÿâÿáÿâÿäÿãÿäÿåÿçÿæÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ³ÿŽÿ³ÿµÿ¶ÿ·ÿ·ÿžÿ¹ÿžÿºÿ»ÿŒÿŒÿœÿŸÿŸÿ¿ÿÀÿ¿ÿÁÿÂÿÃÿÃÿÄÿÅÿÄÿÆÿÇÿÈÿÈÿÉÿÊÿÉÿËÿÌÿËÿÍÿÎÿÏÿÏÿÐÿÑÿÐÿÒÿÓÿÔÿÔÿÕÿÖÿÕÿ×ÿØÿÙÿÙÿÚÿÛÿÛÿÜÿÝÿÜÿÞÿßÿàÿàÿáÿâÿáÿãÿäÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ±ÿ³ÿ²ÿ³ÿµÿ¶ÿµÿ¶ÿžÿ·ÿžÿºÿ»ÿºÿŒÿœÿŒÿœÿ¿ÿŸÿ¿ÿÁÿÂÿÁÿÂÿÄÿÃÿÄÿÆÿÇÿÆÿÇÿÉÿÈÿÉÿËÿÊÿËÿÍÿÎÿÍÿÎÿÐÿÏÿÐÿÒÿÓÿÒÿÓÿÕÿÔÿÕÿ×ÿØÿ×ÿÙÿÚÿÙÿÚÿÜÿÛÿÜÿÞÿßÿÞÿßÿáÿàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ°ÿ±ÿ±ÿ²ÿ³ÿŽÿŽÿµÿ¶ÿ¶ÿ·ÿžÿºÿ¹ÿºÿ»ÿ»ÿŒÿœÿœÿŸÿ¿ÿÀÿÀÿÁÿÂÿÂÿÃÿÄÿÅÿÅÿÆÿÇÿÇÿÈÿÉÿÉÿÊÿËÿÌÿÌÿÍÿÎÿÎÿÏÿÐÿÑÿÑÿÒÿÓÿÓÿÔÿÕÿ×ÿÖÿ×ÿØÿØÿÙÿÚÿÚÿÛÿÜÿÝÿÝÿÞÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯ÿ°ÿ¯ÿ°ÿ²ÿ³ÿ²ÿŽÿµÿŽÿ¶ÿ·ÿžÿ·ÿ¹ÿºÿ¹ÿ»ÿŒÿ»ÿŒÿŸÿ¿ÿŸÿÀÿÁÿÀÿÁÿÃÿÄÿÃÿÅÿÆÿÅÿÇÿÈÿÇÿÈÿÊÿËÿÊÿÌÿÍÿÌÿÍÿÏÿÐÿÏÿÑÿÒÿÑÿÓÿÔÿÕÿÔÿÖÿ×ÿÖÿØÿÙÿØÿÙÿÛÿÜÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ­ÿ®ÿ®ÿ¯ÿ°ÿ²ÿ±ÿ²ÿŽÿ³ÿŽÿµÿ·ÿ¶ÿ·ÿ¹ÿžÿ¹ÿºÿºÿ»ÿŒÿŸÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÃÿÂÿÃÿÅÿÄÿÅÿÆÿÆÿÇÿÈÿÊÿÉÿÊÿËÿËÿÌÿÍÿÏÿÎÿÏÿÑÿÐÿÑÿÒÿÔÿÓÿÔÿÖÿÕÿÖÿ×ÿ×ÿØÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬ÿ­ÿ¬ÿ®ÿ¯ÿ°ÿ°ÿ±ÿ²ÿ±ÿ³ÿŽÿµÿµÿ¶ÿ·ÿ¶ÿžÿ¹ÿžÿºÿ»ÿŒÿ»ÿœÿŸÿœÿ¿ÿÀÿÁÿÁÿÂÿÃÿÂÿÄÿÅÿÄÿÆÿÇÿÈÿÇÿÉÿÊÿÉÿËÿÌÿÍÿÍÿÎÿÏÿÎÿÐÿÑÿÒÿÒÿÓÿÔÿÓÿÕÿÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿªÿ¬ÿ«ÿ¬ÿ®ÿ¯ÿ®ÿ¯ÿ±ÿ°ÿ±ÿ³ÿŽÿ³ÿŽÿ¶ÿµÿ¶ÿžÿ·ÿžÿ¹ÿ»ÿºÿ»ÿœÿŒÿœÿ¿ÿÀÿ¿ÿÀÿÂÿÁÿÂÿÄÿÃÿÄÿÅÿÇÿÆÿÇÿÉÿÈÿÉÿËÿÌÿËÿÌÿÎÿÍÿÎÿÐÿÑÿÐÿÑÿÓÿÒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ©ÿªÿªÿ«ÿ¬ÿ­ÿ­ÿ®ÿ¯ÿ¯ÿ°ÿ±ÿ²ÿ²ÿ³ÿŽÿŽÿµÿ¶ÿµÿ·ÿžÿ¹ÿ¹ÿºÿ»ÿ»ÿŒÿœÿŸÿŸÿ¿ÿÀÿÀÿÁÿÂÿÁÿÃÿÄÿÅÿÅÿÆÿÇÿÇÿÈÿÉÿÊÿÊÿËÿÌÿÌÿÍÿÎÿÏÿÏÿÐÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿšÿ©ÿšÿ©ÿ«ÿ¬ÿ«ÿ­ÿ®ÿ­ÿ®ÿ°ÿ±ÿ°ÿ²ÿ³ÿ²ÿ³ÿµÿŽÿµÿ·ÿžÿ·ÿ¹ÿºÿ¹ÿºÿŒÿœÿŒÿŸÿ¿ÿŸÿ¿ÿÁÿÀÿÁÿÃÿÄÿÃÿÅÿÆÿÅÿÆÿÈÿÉÿÈÿÊÿËÿÊÿËÿÍÿÎÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŠÿ§ÿ§ÿšÿ©ÿ«ÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ°ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿ³ÿŽÿµÿ·ÿ¶ÿ·ÿžÿžÿ¹ÿºÿŒÿ»ÿŒÿœÿœÿŸÿ¿ÿ¿ÿÀÿÁÿÃÿÂÿÃÿÄÿÄÿÅÿÆÿÈÿÇÿÈÿÉÿÉÿÊÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¥ÿŠÿ¥ÿ§ÿšÿ©ÿšÿªÿ«ÿªÿ¬ÿ­ÿ®ÿ­ÿ¯ÿ°ÿ¯ÿ±ÿ²ÿ±ÿ³ÿŽÿµÿŽÿ¶ÿ·ÿ¶ÿžÿ¹ÿºÿ¹ÿ»ÿŒÿ»ÿœÿŸÿœÿ¿ÿÀÿÁÿÀÿÂÿÃÿÂÿÄÿÅÿÆÿÅÿÇÿÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ£ÿ¥ÿ€ÿ¥ÿŠÿšÿ§ÿšÿªÿ©ÿªÿ«ÿ­ÿ¬ÿ­ÿ¯ÿ®ÿ¯ÿ±ÿ°ÿ±ÿ²ÿŽÿ³ÿŽÿ¶ÿµÿ¶ÿ·ÿ¹ÿžÿ¹ÿ»ÿºÿ»ÿœÿŒÿœÿŸÿÀÿ¿ÿÀÿÂÿÁÿÂÿÃÿÅÿÄÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ£ÿ¢ÿ€ÿ¥ÿŠÿŠÿ§ÿšÿ§ÿ©ÿªÿ«ÿ«ÿ¬ÿ­ÿ­ÿ®ÿ¯ÿ®ÿ°ÿ±ÿ²ÿ²ÿ³ÿŽÿ³ÿµÿ¶ÿ·ÿ·ÿžÿ¹ÿ¹ÿºÿ»ÿºÿŒÿœÿŸÿŸÿ¿ÿÀÿ¿ÿÁÿÂÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ¡ÿ¢ÿ€ÿ¥ÿ€ÿ¥ÿ§ÿŠÿ§ÿ©ÿªÿ©ÿ«ÿ¬ÿ«ÿ¬ÿ®ÿ­ÿ®ÿ°ÿ±ÿ°ÿ±ÿ³ÿ²ÿ³ÿµÿ¶ÿµÿ·ÿžÿ·ÿžÿºÿ¹ÿºÿŒÿœÿŒÿœÿ¿ÿŸÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿ¡ÿ¢ÿ£ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿ©ÿšÿ©ÿªÿªÿ«ÿ¬ÿ¬ÿ­ÿ®ÿ¯ÿ¯ÿ°ÿ±ÿ±ÿ²ÿ³ÿµÿŽÿµÿ¶ÿ¶ÿ·ÿžÿžÿ¹ÿºÿ»ÿ»ÿŒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ¢ÿ¡ÿ£ÿ€ÿ£ÿ¥ÿŠÿ§ÿŠÿšÿ©ÿšÿªÿ«ÿªÿ«ÿ­ÿ®ÿ­ÿ¯ÿ°ÿ¯ÿ±ÿ²ÿ³ÿ²ÿŽÿµÿŽÿ¶ÿ·ÿ¶ÿ·ÿ¹ÿºÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ ÿ¡ÿ£ÿ¢ÿ£ÿ€ÿŠÿ¥ÿŠÿšÿ§ÿšÿ©ÿ©ÿªÿ«ÿ­ÿ¬ÿ­ÿ¯ÿ®ÿ¯ÿ°ÿ²ÿ±ÿ²ÿŽÿ³ÿŽÿµÿµÿ¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ ÿ¢ÿ£ÿ€ÿ€ÿ¥ÿŠÿ¥ÿ§ÿšÿ§ÿ©ÿªÿ«ÿ«ÿ¬ÿ­ÿ¬ÿ®ÿ¯ÿ°ÿ°ÿ±ÿ²ÿ±ÿ³ÿŽÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ ÿ¢ÿ£ÿ¢ÿ£ÿ¥ÿ€ÿ¥ÿ§ÿŠÿ§ÿ©ÿªÿ©ÿªÿ¬ÿ«ÿ¬ÿ®ÿ¯ÿ®ÿ¯ÿ±ÿ°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ¡ÿ¢ÿ£ÿ£ÿ€ÿ¥ÿ¥ÿŠÿ§ÿšÿšÿ©ÿªÿªÿ«ÿ¬ÿ­ÿ­ÿ®ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ¡ÿ¢ÿ¡ÿ£ÿ€ÿ£ÿ€ÿŠÿ§ÿŠÿšÿ©ÿšÿ©ÿ«ÿ¬ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ ÿ¡ÿ¢ÿ¢ÿ£ÿ€ÿŠÿ¥ÿŠÿ§ÿ§ÿšÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¡ÿ ÿ¢ÿ£ÿ€ÿ£ÿ¥ÿŠÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ ÿ¡ÿ£ÿ¢ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    3 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          NAXIS2  =                   64 / length of data axis 2                          NAXIS3  =                    1 / length of data axis 3                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BZERO   =   0.000000000000E+00 / Pixel Value Offset                             BSCALE  =   1.000000000000E+00 / Pixel Value Scale                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ; = ?ÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 : < >ÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ; =ÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 : <ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9 ;ÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8 :ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7 9ÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6 8ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5 7ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4 6ÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3 5ÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2 4ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1 3ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0 2ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - / 1ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , . 0ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + - /ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * , .ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) + -ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( * ,ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' ) +ÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & ( *ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % ' )ÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ & (ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # % 'ÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ &ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! # %ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   " $ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  ! #ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+   "ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+  !ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+  ÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+ ÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ 
+ÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+        
+ÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+        
+ÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+       ÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+       ÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+      ÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+      ÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+     ÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+     ÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+    ÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+    ÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+   ÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+   ÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+  ÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+  ÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+ ÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+ ÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ 
+ÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ 
+ÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	 
+ÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ       
+ÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ     	ÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ      ÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ    ÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ    ÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ   ÿÿ
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿ£ÿ¥ÿ§ÿ©ÿ«ÿ­ÿ¯ÿ±ÿ³ÿµÿ·ÿ¹ÿ»ÿœÿ¿ÿÁÿÃÿÅÿÇÿÉÿËÿÍÿÏÿÑÿÓÿÕÿ×ÿÙÿÛÿÝÿßÿáÿãÿåÿçÿéÿëÿíÿïÿñÿóÿõÿ÷ÿùÿûÿýÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ¢ÿ€ÿŠÿšÿªÿ¬ÿ®ÿ°ÿ²ÿŽÿ¶ÿžÿºÿŒÿŸÿÀÿÂÿÄÿÆÿÈÿÊÿÌÿÎÿÐÿÒÿÔÿÖÿØÿÚÿÜÿÞÿàÿâÿäÿæÿèÿêÿìÿîÿðÿòÿôÿöÿøÿúÿüÿþ                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/jpeg/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/jpeg/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/jpeg/.cvsignore	(revision 22158)
@@ -0,0 +1,9 @@
+temp
+.deps
+.libs
+Makefile
+Makefile.in
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/jpeg/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/jpeg/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/jpeg/Makefile.am	(revision 22158)
@@ -0,0 +1,18 @@
+AM_CPPFLAGS = $(SRCINC) -I$(top_srcdir)/test/tap/src $(PSLIB_CFLAGS)
+AM_LDFLAGS = \
+	$(top_builddir)/src/libpslib.la  \
+	$(top_builddir)/test/tap/src/libtap.la \
+	$(PSLIB_LIBS)
+
+TEST_PROGS =
+
+if BUILD_TESTS
+bin_PROGRAMS = $(TEST_PROGS)
+TESTS = $(TEST_PROGS)
+else
+check_PROGRAMS = $(TEST_PROGS)
+endif
+
+CLEANFILES = $(check_DATA) core core.* *~ *.bb *.bbg *.da gmon.out
+
+test: check
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/.cvsignore	(revision 22158)
@@ -0,0 +1,54 @@
+temp
+.deps
+.libs
+Makefile
+Makefile.in
+seed_msglog1.txt
+seed_msglog2.txt
+*.bb
+*.bbg
+*.da
+gmon.out
+
+tap_psHist00
+tap_psHist01
+tap_psHist02
+tap_psHist03
+tap_psMD5
+tap_psMatrix01
+tap_psMatrix02
+tap_psMatrix03
+tap_psMatrix04
+tap_psMatrix05
+tap_psMatrix06
+tap_psMatrix07
+tap_psPolyFit1D
+tap_psPolyFit2D
+tap_psPolyFit3D
+tap_psPolyFit4D
+tap_psPolynomial
+tap_psPolynomialEval1D
+tap_psPolynomialEval2D
+tap_psPolynomialEval3D
+tap_psPolynomialEval4D
+tap_psPolynomialUtils_Derivatives
+tap_psSparse
+tap_psStats00
+tap_psStats01
+tap_psStats02
+tap_psStats03
+tap_psStats05
+tap_psStats06
+tap_psStats07
+tap_psStats08
+tap_psStats09
+tap_psStatsTiming
+tap_psStats_Sample_01
+tap_psFunc01
+tap_psHistogram
+tap_psMatrixVectorArithmetic01
+tap_psMatrixVectorArithmetic04
+tap_psMinimizePowell
+tap_psRandom
+tap_psSpline1D
+tap_psPolynomialMD
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/Makefile.am	(revision 22158)
@@ -0,0 +1,64 @@
+
+AM_CPPFLAGS = \
+	$(SRCINC) \
+	-I$(top_srcdir)/test/tap/src \
+	-I$(top_srcdir)/test/pstap/src \
+	$(PSLIB_CFLAGS)
+
+AM_LDFLAGS = \
+	$(top_builddir)/src/libpslib.la  \
+	$(top_builddir)/test/tap/src/libtap.la \
+	$(top_builddir)/test/pstap/src/libpstap.la \
+	$(PSLIB_LIBS)
+
+TEST_PROGS = \
+	tap_psHistogram \
+	tap_psMD5 \
+	tap_psMatrix01 \
+	tap_psMatrix02 \
+	tap_psMatrix03 \
+	tap_psMatrix04 \
+	tap_psMatrix05 \
+	tap_psMatrix06 \
+	tap_psMatrix07 \
+	tap_psPolyFit1D \
+	tap_psPolyFit2D \
+	tap_psPolyFit3D \
+	tap_psPolyFit4D \
+	tap_psPolynomial \
+	tap_psPolynomialEval1D \
+	tap_psPolynomialEval2D \
+	tap_psPolynomialEval3D \
+	tap_psPolynomialEval4D \
+	tap_psPolynomialUtils_Derivatives \
+	tap_psSparse \
+	tap_psStats00 \
+	tap_psStats01 \
+	tap_psStats02 \
+	tap_psStats03 \
+	tap_psStats05 \
+	tap_psStats06 \
+	tap_psStats07 \
+	tap_psStats08 \
+	tap_psStats09 \
+	tap_psStatsTiming \
+	tap_psFunc01 \
+	tap_psStats_Sample_01 \
+	tap_psMatrixVectorArithmetic01 \
+	tap_psMatrixVectorArithmetic04 \
+	tap_psRandom \
+	tap_psMinimizePowell \
+	tap_psSpline1D \
+	tap_psPolynomialMD
+
+if BUILD_TESTS
+bin_PROGRAMS = $(TEST_PROGS)
+TESTS = $(TEST_PROGS)
+else
+check_PROGRAMS = $(TEST_PROGS)
+endif
+
+CLEANFILES = $(check_DATA) temp/* core core.* *~ *.bb *.bbg *.da gmon.out
+
+test: check
+	$(top_srcdir)/test/test.pl
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psFunc01.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psFunc01.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psFunc01.c	(revision 22158)
@@ -0,0 +1,57 @@
+/*****************************************************************************
+    This routine must ensure that the psGaussian() shall evaluate a
+    specified Gaussian at some X.
+ 
+    It also tests the p_psGaussianDev() procedure.
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define MY_MEAN 5.0
+#define MY_STDEV 2.0
+#define TOLERANCE 0.01
+psF32 truth1[10] = {0.008764, 0.026995, 0.064759, 0.120985, 0.176033, 0.199471, 0.176033, 0.120985, 0.064759, 0.026995};
+psF32 truth2[10] = {0.043937, 0.135335, 0.324652, 0.606531, 0.882497, 1.000000, 0.882497, 0.606531, 0.324652, 0.135335};
+
+int main()
+{
+    psLogSetFormat("HLNM");
+    plan_tests(4);
+
+
+    // Test the psGaussian(): normalized version
+    {
+        psMemId id = psMemGetId();
+        bool errorFlag = false;
+        for (psS32 x = 0 ; x < (int) (MY_MEAN * 2.0) ; x++)
+        {
+            psF32 actual = psGaussian((psF32) x, MY_MEAN, MY_STDEV, true);
+            if (fabs(truth1[x] - actual) > TOLERANCE) {
+                diag("ERROR: the Gaussian at %.2f was %f, should be %f", (psF32) x, actual, truth1[x]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psGaussian() produced consistent results (normalized)");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test the psGaussian(): non-normalized version
+    {
+        psMemId id = psMemGetId();
+        bool errorFlag = false;
+        for (psS32 x = 0 ; x < (int) (MY_MEAN * 2.0) ; x++)
+        {
+            psF32 actual = psGaussian((psF32) x, MY_MEAN, MY_STDEV, false);
+            if (fabs(truth2[x] - actual) > TOLERANCE) {
+                diag("ERROR: the Gaussian at %.2f was %f, should be %f", (psF32) x, actual, truth1[x]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psGaussian() produced consistent results (non-normalized)");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psHistogram.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psHistogram.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psHistogram.c	(revision 22158)
@@ -0,0 +1,435 @@
+/*****************************************************************************
+We test:
+    psHistogramAlloc()
+    psHistogramAllocGeneric()
+    psVectorHistogram(): uniform histograms
+    psVectorHistogram(): generic histograms
+*****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#define ERROR_TOLERANCE 0.001
+#define NUM_DATA 10000
+
+void genericTestHistogramAlloc(psS32 numBins, psS32 lower, psS32 higher)
+{
+    // Allocate the psHistogram structure
+    {
+        psMemId id = psMemGetId();
+        psHistogram *myHist = psHistogramAlloc(lower, higher, numBins);
+        ok(myHist != NULL, "psHistogram allocated successfully");
+        skip_start(myHist == NULL, 7, "Skipping tests because psHistogramAlloc() failed");
+        ok(myHist->nums->n = numBins, "psHistogramAlloc() set the correct number of bins");
+        ok(myHist->bounds->n == numBins+1, "psHistogramAlloc() set the correct number of bounds");
+        ok(myHist->minNum == 0, "psHistogramAlloc() initialized minNum to 0.0");
+        ok(myHist->maxNum == 0, "psHistogramAlloc() initialized maxNum to 0.0");
+        ok(myHist->uniform == true, "psHistogramAlloc() initialized ->uniform to true");
+
+        bool errorFlag = false;
+        for (int i=0;i<numBins;i++)
+        {
+            if (myHist->nums->data.F32[i] != 0.0) {
+                diag("ERROR: myHist->nums->data.U32[%d] not initialized to 0.\n", i);
+                errorFlag = true;
+            }
+            myHist->nums->data.F32[i] = 0.0;
+        }
+        ok(!errorFlag, "psHistogramAlloc() initialized the data to 0.0");
+
+        errorFlag = false;
+        for (int i=0;i<numBins;i++)
+        {
+            psF32 expectedBound = (psF32) (i + 1);
+            if (fabs(expectedBound - myHist->bounds->data.F32[i]) > ERROR_TOLERANCE) {
+                diag("Bin number %d bounds: (%6.3f - %6.3f)\n", i,
+                     myHist->bounds->data.F32[i],
+                     myHist->bounds->data.F32[i+1]);
+                diag("Was %f, expected %f\n", myHist->bounds->data.F32[i], expectedBound);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psHistogramAlloc() set the histogram bounds correctly");
+
+        skip_end();
+        psFree(myHist);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
+
+void genericTestHistogramAllocGeneric(psS32 numBins, psS32 lower, psS32 higher)
+{
+    {
+        psMemId id = psMemGetId();
+        psVector *myBounds = psVectorAlloc(numBins+1, PS_TYPE_F32);
+        for (int i=0;i<numBins+1;i++) {
+            myBounds->data.F32[i] = lower + ((higher - lower) / (float) numBins) *
+		(float) i;
+        }
+        psHistogram *myHist = psHistogramAllocGeneric(myBounds);
+        ok(myHist != NULL, "psHistogram allocated successfully");
+        skip_start(myHist == NULL, 7, "Skipping tests because psHistogramAlloc() failed");
+        ok(myHist->nums->n = numBins, "psHistogramAllocGeneric() set the correct number of bins");
+        ok(myHist->bounds->n == numBins+1, "psHistogramAllocGeneric() set the correct number of bounds");
+        ok(myHist->minNum == 0, "psHistogramAllocGeneric() initialized minNum to 0.0");
+        ok(myHist->maxNum == 0, "psHistogramAllocGeneric() initialized maxNum to 0.0");
+        ok(myHist->uniform == false, "psHistogramAllocGeneric() initialized ->uniform to false");
+
+        bool errorFlag = false;
+        for (int i=0;i<numBins;i++) {
+            if (myHist->nums->data.F32[i] != 0.0) {
+                diag("ERROR: myHist->nums->data.F32[%d] not initialized to 0.\n", i);
+                errorFlag = false;
+            }
+        }
+        ok(!errorFlag, "psHistogramAllocGeneric() initialized the data to 0.0");
+
+        errorFlag = false;
+        for (int i=0;i<numBins;i++) {
+            psF32 expectedBound = (psF32) (i + 1);
+            if (fabs(expectedBound - myHist->bounds->data.F32[i]) > ERROR_TOLERANCE) {
+                diag("Bin number %d bounds: (%6.3f - %6.3f)\n", i,
+                     myHist->bounds->data.F32[i],
+                     myHist->bounds->data.F32[i+1]);
+                diag("Was %f, expected %f\n", myHist->bounds->data.F32[i], expectedBound);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psHistogramAlloc() set the histogram bounds correctly");
+
+        skip_end();
+        psFree(myHist);
+        psFree(myBounds);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+
+    }
+}
+
+
+void genericTestVectorHistogram1(psS32 numBins, psS32 lower, psS32 higher)
+{
+    if ((numBins%2) != 0) {
+        diag("Configuration error: must run this test with even number of bins");
+        return;
+    }
+    if ((NUM_DATA%numBins) != 0) {
+        diag("Configuration error: NUM_DATA must be an integer multiple of numBins");
+        return;
+    }
+
+    // Allocate the psHistogram structure, ensure that psVectorHistogram() sets
+    // the data correctly when called with a NULL mask.
+    {
+        psMemId id = psMemGetId();
+        psVector *myData = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        for (int i = 0;i < NUM_DATA;i++) {
+            myData->data.F32[i] = lower + ((higher - lower) / (float) NUM_DATA) * (float) i;
+        }
+
+        psHistogram *myHist = psHistogramAlloc(lower, higher, numBins);
+        bool rc = psVectorHistogram(myHist, myData, NULL, NULL, 0);
+        ok(rc == true, "psVectorHistogram() returned TRUE");
+        skip_start(myHist == NULL, 1, "Skipping tests because psVectorHistogram() returned NULL");
+
+        bool errorFlag = false;
+        for (int i = 0; i < numBins; i++) {
+
+	    // we need to explicitly count the number in each bin.  we can fool ourselves with
+	    // rounding otherwise
+	    int nValues = 0;
+	    for (int j = 0; j < myData->n; j++) {
+		// valid bin: bound[bin] <= value < bound[bin+1]
+		if (myData->data.F32[j] < myHist->bounds->data.F32[i]) continue;
+		if (myData->data.F32[j] >= myHist->bounds->data.F32[i+1]) continue;
+		nValues ++;
+	    }
+	    if (myHist->nums->data.F32[i] != nValues) {
+		diag("Bin number %d bounds: (%.2f - %.2f) data (%.2f) should be (%2d)\n",
+		     i,
+		     myHist->bounds->data.F32[i],
+		     myHist->bounds->data.F32[i+1],
+		     myHist->nums->data.F32[i], nValues);
+		errorFlag = true;
+	    }
+        }
+        ok(!errorFlag, "psVectorHistogram() correctly set the histogram");
+        skip_end();
+        psFree(myHist);
+        psFree(myData);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Allocate the psHistogram structure, ensure that psVectorHistogram() sets
+    // the data correctly when called with a mask.
+    {
+        psMemId id = psMemGetId();
+        psVector *myData = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        myData->n = myData->nalloc;
+        for (int i = 0;i < NUM_DATA;i++) {
+            myData->data.F32[i] = lower + ((higher - lower) / (float) NUM_DATA) * (float) i;
+        }
+
+        psVector *myMask = psVectorAlloc(NUM_DATA, PS_TYPE_U8);
+        myMask->n = myMask->nalloc;
+        for (int i = 0;i < NUM_DATA;i++) {
+            if (i >= (NUM_DATA / 2)) {
+                myMask->data.U8[i] = 1;
+            } else {
+                myMask->data.U8[i] = 0;
+            }
+        }
+        psHistogram *myHist = psHistogramAlloc(lower, higher, numBins);
+        bool rc = psVectorHistogram(myHist, myData, NULL, myMask, 1);
+        ok(rc == true, "psVectorHistogram() returned TRUE");
+        skip_start(myHist == NULL, 1, "Skipping tests because psVectorHistogram() returned NULL");
+
+        bool errorFlag = false;
+        for (int i = 0;i < numBins;i++) {
+
+	    // we need to explicitly count the number in each bin.  we can fool ourselves with
+	    // rounding otherwise
+	    int nValues = 0;
+	    for (int j = 0; j < myData->n; j++) {
+		// valid bin: bound[bin] <= value < bound[bin+1]
+		if (myMask->data.U8[j] == 1) continue;
+		if (myData->data.F32[j] < myHist->bounds->data.F32[i]) continue;
+		if (myData->data.F32[j] >= myHist->bounds->data.F32[i+1]) continue;
+		nValues ++;
+	    }
+	    if (myHist->nums->data.F32[i] != nValues) {
+		diag("Bin number %d bounds: (%6.3f - %6.3f) data (%f) should be (%.2f)\n", i,
+		     myHist->bounds->data.F32[i],
+		     myHist->bounds->data.F32[i + 1],
+		     myHist->nums->data.F32[i], (float) (NUM_DATA/numBins));
+		errorFlag = true;
+	    }
+        }
+        ok(!errorFlag, "psVectorHistogram() correctly set the histogram");
+        skip_end();
+        psFree(myHist);
+        psFree(myMask);
+        psFree(myData);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify the return value is NULL and program execution doesn't stop,
+    // if input psHistogram parameter is NULL.
+    {
+        psMemId id = psMemGetId();
+        psVector *myData = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        myData->n = myData->nalloc;
+        for (int i = 0;i < NUM_DATA;i++) {
+            myData->data.F32[i] = lower + ((higher - lower) / (float) NUM_DATA) * (float) i;
+        }
+        ok(false == psVectorHistogram(NULL, myData, NULL, NULL, 0),
+	   "psVectorHistogram() returned FALSE with a NULL psHistogram input");
+        psFree(myData);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify the return value is the same as the input parameter myHist and
+    // program execution doesn't stop, if the input parameter myArray is
+    // NULL.
+    {
+        psMemId id = psMemGetId();
+        psHistogram *myHist = psHistogramAlloc(lower, higher, numBins);
+        ok(true == psVectorHistogram(myHist, NULL, NULL, NULL, 0),
+	   "psVectorHistogram() returns TRUE with a NULL input array");
+        psFree(myHist);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify the return value is the same as the input parameter myHist and
+    // program execution doesn't stop, if the input parameter myArray has no
+    // elements.
+    {
+        psMemId id = psMemGetId();
+        psVector *myData = psVectorAlloc(0, PS_TYPE_F32);
+        psHistogram *myHist = psHistogramAlloc(lower, higher, numBins);
+        ok(true == psVectorHistogram(myHist, NULL, NULL, NULL, 0),
+	   "psVectorHistogram() returns TRUE with an empty input array");
+        psFree(myHist);
+        psFree(myData);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
+//#define NUM_DATA 20
+void genericTestVectorHistogram2(psS32 numBins, psS32 lower, psS32 higher)
+{
+    if (numBins > NUM_DATA) {
+        diag("Configuration error: NUM_DATA must be larger than numBins");
+        return;
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *myData = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        for (int i = 0;i < NUM_DATA;i++) {
+            myData->data.F32[ i ] = lower + ((higher-lower) / (float) NUM_DATA) * (float) i;
+        }
+
+        psVector *myBounds = psVectorAlloc(numBins+1, PS_TYPE_F32);
+        for (int i=0;i<numBins+1;i++) {
+            myBounds->data.F32[i] = lower + ((higher - lower) / (float) numBins) * (float) i;
+        }
+
+        psHistogram *myHist = psHistogramAllocGeneric(myBounds);
+        ok(myHist->nums->n == numBins, "psHistogramAllocGeneric() set correct number of bins");
+        ok(myHist->bounds->n == numBins+1, "psHistogramAllocGeneric() set correct number of bounds");
+        ok(myHist->minNum == 0, "psHistogramAlloc() initialized minNum to 0.0");
+        ok(myHist->maxNum == 0, "psHistogramAlloc() initialized maxNum to 0.0");
+        ok(myHist->uniform == false, "psHistogramAlloc() initialized ->uniform to false");
+
+        bool errorFlag = false;
+        for (int i=0;i<numBins;i++) {
+            if (fabs(myHist->nums->data.F32[i]) > ERROR_TOLERANCE) {
+                diag("ERROR: myHist->nums->data.F32[%d] not initialized to 0.\n", i);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psVectorHistogram() correctly initialized the bins");
+
+        bool rc = psVectorHistogram(myHist, myData, NULL, NULL, 0);
+        ok(rc == true, "psVectorHistogram() returned TRUE");
+        skip_start(rc == false, 1, "Skipping tests because psVectorHistogram() returned FALSE");
+        for (int i=0;i<numBins;i++) {
+
+	    // we need to explicitly count the number in each bin.  we can fool ourselves with
+	    // rounding otherwise
+	    int nValues = 0;
+	    for (int j = 0; j < myData->n; j++) {
+		// valid bin: bound[bin] <= value < bound[bin+1]
+		if (myData->data.F32[j] < myHist->bounds->data.F32[i]) continue;
+		if (myData->data.F32[j] >= myHist->bounds->data.F32[i+1]) continue;
+		nValues ++;
+	    }
+	    if (myHist->nums->data.F32[i] != nValues) {
+                diag("Bin number %d bounds: (%.2f - %.2f): data: (%.2f) should be (%.2f)\n", i,
+                     myHist->bounds->data.F32[i],
+                     myHist->bounds->data.F32[i+1],
+                     myHist->nums->data.F32[i], nValues);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psVectorHistogram() correctly set the bins");
+        skip_end();
+        psFree(myData);
+        psFree(myHist);
+        psFree(myBounds);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
+
+psS32 main()
+{
+    psLogSetLevel(PS_LOG_INFO);
+    psLogSetFormat("HLNM");
+    plan_tests(168);
+
+
+    // psHistogramAlloc() tests
+    // Call with lower bound larger than upper bound.  Should return NULL.
+    {
+        psMemId id = psMemGetId();
+        psHistogram *myHist = psHistogramAlloc(10, 5, 1);
+        ok(myHist == NULL, "psHistogramAlloc() returned NULL with lower bound larger than upper bound");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call with 0 numBins.  Should return NULL.
+    {
+        psMemId id = psMemGetId();
+        psHistogram *myHist = psHistogramAlloc(5, 10, 0);
+        ok(myHist == NULL, "psHistogramAlloc() returned NULL with 0 numBins");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psHistogramAlloc() tests
+    {
+        genericTestHistogramAlloc(1, 1, 2);
+        genericTestHistogramAlloc(2, 1, 3);
+        genericTestHistogramAlloc(10, 1, 11);
+        genericTestHistogramAlloc(20, 1, 21);
+    }
+
+
+    // psHistogramAllocGeneric() tests
+    // Use NULL psVector* bounds struct.
+    {
+        psMemId id = psMemGetId();
+        psHistogram *myHist = psHistogramAllocGeneric(NULL);
+        ok(myHist == NULL, "psHistogram() returned NULL with NULL psVector* bounds struct");
+        psFree(myHist);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Use unallowed type for bounds
+    {
+        psMemId id = psMemGetId();
+        psS32 numBins = 10;
+        psS32 lower = 5;
+        psS32 higher = 10;
+        psVector *myBounds = psVectorAlloc(numBins+1, PS_TYPE_F64);
+        for (int i=0;i<numBins+1;i++) {
+            myBounds->data.F64[i] = lower + ((higher - lower) / (float) numBins) * (float) i;
+        }
+        psHistogram *myHist = psHistogramAllocGeneric(myBounds);
+        ok(myHist == NULL, "psHistogram() returned NULL with unallowed type for psVector* bounds struct");
+        ok(myBounds != NULL, "psHistogram() did not free bounds");
+        psFree(myHist);
+        psFree(myBounds);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Use only a single bound
+    {
+        psMemId id = psMemGetId();
+        psVector *myBounds = psVectorAlloc(1, PS_TYPE_F32);
+        psHistogram *myHist = psHistogramAllocGeneric(myBounds);
+        ok(myHist == NULL, "psHistogram() returned NULL with only a single bound");
+        ok(myBounds != NULL, "psHistogram() did not free bounds");
+        psFree(myHist);
+        psFree(myBounds);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psHistogramAllocGeneric() tests
+    {
+        genericTestHistogramAllocGeneric(1, 1, 2);
+        genericTestHistogramAllocGeneric(2, 1, 3);
+        genericTestHistogramAllocGeneric(10, 1, 11);
+        genericTestHistogramAllocGeneric(20, 1, 21);
+    }
+
+
+    // psVectorHistogram() tests: uniform histograms
+    {
+        genericTestVectorHistogram1(2, 1, 3);
+        genericTestVectorHistogram1(10, 1, 11);
+        genericTestVectorHistogram1(20, 1, 21);
+        genericTestVectorHistogram1(500, 1, 501);
+    }
+
+
+    // psVectorHistogram() tests: generic histograms
+    {
+        genericTestVectorHistogram2(1, 1, 2);
+        genericTestVectorHistogram2(2, 1, 3);
+        genericTestVectorHistogram2(10, 1, 11);
+        genericTestVectorHistogram2(20, 1, 21);
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMD5.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMD5.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMD5.c	(revision 22158)
@@ -0,0 +1,142 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+// The official MD5 test cases
+#define NUM_TESTS 7
+static const struct
+{
+    const char *input;                  // The input string
+    const char result[16];              // The hash
+    const char string[34];              // The stringified hash
+}
+tests[] =
+    {
+        { "",
+          "\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42\x7e",
+          "d41d8cd98f00b204e9800998ecf8427e" },
+        { "a",
+          "\x0c\xc1\x75\xb9\xc0\xf1\xb6\xa8\x31\xc3\x99\xe2\x69\x77\x26\x61",
+          "0cc175b9c0f1b6a831c399e269772661" },
+        { "abc",
+          "\x90\x01\x50\x98\x3c\xd2\x4f\xb0\xd6\x96\x3f\x7d\x28\xe1\x7f\x72",
+          "900150983cd24fb0d6963f7d28e17f72" },
+        { "message digest",
+          "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d\x52\x5a\x2f\x31\xaa\xf1\x61\xd0",
+          "f96b697d7cb7938d525a2f31aaf161d0" },
+        { "abcdefghijklmnopqrstuvwxyz",
+          "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00\x7d\xfb\x49\x6c\xca\x67\xe1\x3b",
+          "c3fcd3d76192e4007dfb496cca67e13b" },
+        { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+          "\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f",
+          "d174ab98d277d9f5a5611c2c9f419d9f" },
+        { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+          "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55\xac\x49\xda\x2e\x21\x07\xb6\x7a",
+          "57edf4a22be3c955ac49da2e2107b67a" }
+    };
+
+
+int main(void)
+{
+    plan_tests(NUM_TESTS * 3 +          // Strings
+               NUM_TESTS * 2 +          // Vectors
+               (NUM_TESTS - 1) * 2 +    // Images (except the empty string test)
+               (NUM_TESTS - 2) * 3 +    // Sub-images (except the empty and "a" string test)
+               1                        // Memory leaks
+              );
+
+//    diag("psMD5 tests");
+
+    // Strings
+    for (int i = 0; i < NUM_TESTS; i++) {
+        psString string = psStringCopy(tests[i].input); // String to test
+        psVector *hash = psStringMD5(string); // The MD5 hash
+        ok(hash, "hash generated");
+
+        skip_start(!hash, 2, "Skipping tests because hash calculation failed");
+
+        ok(memcmp(hash->data.U8, tests[i].result, 16) == 0, "hash matches");
+
+        psString hashString = psMD5toString(hash); // String of the hash
+        ok(strcmp(hashString, tests[i].string) == 0, "hash string matches");
+        psFree(hashString);
+
+        skip_end();
+
+        psFree(hash);
+        psFree(string);
+    }
+
+    // Vectors
+    for (int i = 0; i < NUM_TESTS; i++) {
+        psVector *vector = psVectorAlloc(strlen(tests[i].input), PS_TYPE_U8); // Vector to test
+        memcpy(vector->data.U8, tests[i].input, strlen(tests[i].input));
+        psVector *hash = psVectorMD5(vector); // The MD5 hash
+        ok(hash, "hash generated");
+
+        skip_start(!hash, 1, "Skipping test because hash calculation failed");
+        ok(memcmp(hash->data.U8, tests[i].result, 16) == 0, "hash matches");
+        skip_end();
+
+        psFree(hash);
+        psFree(vector);
+    }
+
+    // Images
+    for (int i = 0; i < NUM_TESTS; i++) {
+        if (strlen(tests[i].input) == 0) {
+            // We don't like images with size = 0,0
+            continue;
+        }
+
+        psImage *image = psImageAlloc(1, strlen(tests[i].input), PS_TYPE_U8); // Image to test
+        for (int j = 0; j < strlen(tests[i].input); j++) {
+            image->data.U8[j][0] = tests[i].input[j];
+        }
+
+        {
+            psVector *hash = psImageMD5(image);
+            ok(hash, "hash generated");
+
+            skip_start(!hash, 1, "Skipping test because hash calculation failed");
+            ok(memcmp(hash->data.U8, tests[i].result, 16) == 0, "hash matches");
+            skip_end();
+
+            psFree(hash);
+        }
+
+        if (strlen(tests[i].input) > 1) {
+            // Generate a subImage (so the source can't assume that everything's contiguous)
+            psRegion region = { 0, 1, 1, image->numRows }; // Region of interest --- all but the first char
+            psImage *subImage = psImageSubset(image, region);
+
+            // We're going to test against something that we calculate ourselves.  Not the most robust of
+            // tests, but we've already verified psStringMD5, so we cross our fingers and hope.
+            psVector *reference = psStringMD5(tests[i].input + 1);
+            ok(reference, "reference hash generated");
+            skip_start(!reference, 2, "Skipping tests because hash calculation failed");
+
+            psVector *hash = psImageMD5(subImage);
+            ok(hash, "hash generated");
+
+            skip_start(!hash, 1, "Skipping test because hash calculation failed");
+            ok(memcmp(reference->data.U8, hash->data.U8, 16) == 0, "hash matches");
+            skip_end();
+
+            psFree(hash);
+
+            skip_end();
+
+            psFree(reference);
+
+            psFree(subImage);
+        }
+
+        psFree(image);
+    }
+
+    done();
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMathUtils.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMathUtils.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMathUtils.c	(revision 22158)
@@ -0,0 +1,222 @@
+/*****************************************************************************
+This routine contains code which tests the general math utility functions.
+ 
+XXX: This test never really was complete.  I simply converted the lates version
+to libtap format.  It really needs more work.
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define NUM_DATA 10
+#define VERBOSE 0
+#define EXTRA_VERBOSE 0
+#define TS00_X_F32  0x00000001
+#define TS00_X_F64  0x00000002
+#define TS00_X_NULL  0x00000004
+#define TS00_DOMAIN_F32  0x00000008
+#define TS00_DOMAIN_F64  0x00000010
+#define TS00_DOMAIN_NULL 0x00000020
+#define TS00_RANGE_F32  0x00000040
+#define TS00_RANGE_F64  0x00000080
+#define TS00_RANGE_NULL  0x00000200
+#define TOLERANCE 0.01
+
+psS32 genericInterpolateTest(
+    psU32 flags,
+    psS32 order,
+    psS32 numData,
+    psF64 xValue,
+    psBool expectedRC)
+{
+    psS32 testStatus = true;
+    psScalar *x = NULL;
+    psVector *domain = NULL;
+    psVector *range = NULL;
+    psScalar *out = NULL;
+
+    psMemId id = psMemGetId();
+    if (expectedRC == false && VERBOSE) {
+        printf("This test should generate an error message, and return NULL.\n");
+    }
+
+    if (flags & TS00_X_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL x scalar\n");
+    }
+
+    if (flags & TS00_X_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 x scalar\n");
+        x = psScalarAlloc((psF32) xValue, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_X_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 x scalar\n");
+        x = psScalarAlloc((psF64) xValue, PS_TYPE_F64);
+    }
+
+    if (flags & TS00_DOMAIN_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL domain vector\n");
+    }
+
+    if (flags & TS00_DOMAIN_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 domain vector\n");
+        domain = psVectorAlloc(numData, PS_TYPE_F32);
+        for (psS32 i=0;i<numData;i++) {
+            domain->data.F32[i] = (psF32) i;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                if (VERBOSE)
+                    printf("Original domain data %d: (%.1f)\n", i, domain->data.F32[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_DOMAIN_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 domain vector\n");
+        domain = psVectorAlloc(numData, PS_TYPE_F64);
+        for (psS64 i=0;i<numData;i++) {
+            domain->data.F64[i] = (psF64) i;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original domain data %d: (%.1f)\n", i, domain->data.F64[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_RANGE_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL range vector\n");
+    }
+
+    if (flags & TS00_RANGE_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 range vector\n");
+        range = psVectorAlloc(numData, PS_TYPE_F32);
+        for (psS32 i=0;i<numData;i++) {
+            range->data.F32[i] = (psF32) 2*i;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original range data %d: (%.1f)\n", i, range->data.F32[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_RANGE_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 range vector\n");
+        range = psVectorAlloc(numData, PS_TYPE_F64);
+        for (psS64 i=0;i<numData;i++) {
+            range->data.F64[i] = (psF64) 2*i;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original range data %d: (%.1f)\n", i, range->data.F64[i]);
+            }
+        }
+    }
+
+    out = p_psVectorInterpolate(NULL, domain, range, order, x);
+    if (out == NULL) {
+        if (expectedRC == true) {
+            diag("TEST ERROR: the p_psVectorInterpolate function returned NULL.\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            diag("TEST ERROR: the p_psVectorInterpolate function returned non-NULL.\n");
+            testStatus = false;
+        }
+
+        if (flags & TS00_X_F32) {
+            if ((out->data.F32 - (2.0 * x->data.F32)) > TOLERANCE) {
+                diag("The interpolated value was %.2f: should be %.2f\n", out->data.F32, 2.0 * x->data.F32);
+                testStatus = false;
+            }
+
+        } else if (flags & TS00_X_F64) {
+            if ((out->data.F64 - (2.0 * x->data.F64)) > TOLERANCE) {
+                diag("The interpolated value was %.2f: should be %.2f\n", out->data.F64, 2.0 * x->data.F64);
+                testStatus = false;
+            }
+        }
+
+        /*
+        if (0) {
+                if (flags & TS00_F_F32) {
+                    expectData = f->data.F32[i];
+                } else if (flags & TS00_F_F64) {
+                    expectData = (psF32) f->data.F64[i];
+                } else if (flags & TS00_F_S32) {
+                    expectData = (psF32) f->data.S32[i];
+                }
+         
+                    if (flags & TS00_X_F32) {
+                        xData = x->data.F32[i];
+                    } else if (flags & TS00_X_F64) {
+                        xData = (psF32) x->data.F64[i];
+                    } else if (flags & TS00_X_S32) {
+                        xData = (psF32) x->data.S32[i];
+                    } else if (flags & TS00_X_NULL) {
+                        if (flags & TS00_POLY_ORD) {
+                            xData = (psF32) i;
+                        } else if (flags & TS00_POLY_CHEB) {
+                            xData = ((2.0 / ((psF32) (numData - 1))) * ((psF32) i)) - 1.0;
+                        }
+                    }
+         
+                    psF32 actualData = psPolynomial1DEval(myPoly, xData);
+         
+                    if (fabs(actualData-expectData) > fabs(ERROR_TOLERANCE * expectData)) {
+                        printf("TEST ERROR: Fitted data %d: (%.1f %.1f), expected was (%.1f)\n",
+                               i, xData, actualData, expectData);
+                        testStatus = false;
+                     } else {
+                        if (VERBOSE) {
+                            printf("GOOD: Fitted data %d: (%.1f %.1f), expected was (%.1f)\n",
+                                     i, xData, actualData, expectData);
+                        }
+                    }
+                }
+        }
+        */
+    }
+
+    psFree(x);
+    psFree(out);
+    psFree(domain);
+    psFree(range);
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+
+    return (testStatus);
+}
+
+/*****************************************************************************
+ *****************************************************************************/
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    plan_tests(2);
+
+    //
+    // F32 tests:
+    //
+    // All Vectors non-NULL
+
+    ok(genericInterpolateTest(TS00_X_F32 | TS00_DOMAIN_F32 | TS00_RANGE_F32, 5, NUM_DATA, 5.5, true),
+       "p_psVectorInterpolate() worked");
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix01.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix01.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix01.c	(revision 22158)
@@ -0,0 +1,140 @@
+/** @file  tst_psMatrix_01.c
+*
+*  @brief Test driver for psMatrix transpose function
+*
+*  This test driver contains the following tests:
+*     Transpose input image into output image
+*     Transpose input image into auto allocated NULL output image
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2007-05-02 04:20:06 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define TOLERANCE 0.000001
+double truthMatrix[3][3] = {{1, 4, 7},
+                            {2, 5, 8},
+                            {3, 6, 9}};
+
+bool check_matrix(psImage *img)
+{
+    bool errorFlag = false;
+
+    for(psU32 i=0; i<img->numRows; i++) {
+        for(psU32 j=0; j<img->numCols; j++) {
+            if(img->type.type == PS_TYPE_F64) {
+                if(fabs(img->data.F64[i][j]-truthMatrix[i][j]) > TOLERANCE) {
+                    diag("Matrix values at element %d, %d don't agree %lf vs %lf\n", i, j,
+                         img->data.F64[i][j], truthMatrix[i][j]);
+                    errorFlag = true;
+                }
+            } else if(img->type.type == PS_TYPE_F32) {
+                if(fabs(img->data.F32[i][j]-truthMatrix[i][j]) > TOLERANCE) {
+                    diag("Matrix values at element %d, %d don't agree %f vs %lf\n", i, j,
+                         img->data.F32[i][j], truthMatrix[i][j]);
+                    errorFlag = true;
+                }
+            }
+        }
+    }
+    return(errorFlag);
+}
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    plan_tests(14);
+
+
+    // Verify with NULL input params
+    {
+        psMemId id = psMemGetId();
+        psImage *outImage = psMatrixTranspose(NULL, NULL);
+        ok(outImage == NULL, "psMatrixTranspose() returned NULL with NULL input params");
+        psFree(outImage);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify with incorrect input image type
+    {
+        psMemId id = psMemGetId();
+        psImage *inImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_S64);
+        psImage *outImage = psMatrixTranspose(NULL, inImage);
+        ok(outImage == NULL, "psMatrixTranspose() returned NULL with incorrect input image type");
+        psFree(inImage);
+        psFree(outImage);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    psImage *inImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    psImage *outImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    inImage->data.F64[0][0] = 1;
+    inImage->data.F64[0][1] = 2;
+    inImage->data.F64[0][2] = 3;
+    inImage->data.F64[1][0] = 4;
+    inImage->data.F64[1][1] = 5;
+    inImage->data.F64[1][2] = 6;
+    inImage->data.F64[2][0] = 7;
+    inImage->data.F64[2][1] = 8;
+    inImage->data.F64[2][2] = 9;
+    psImage *inImageF32 = (psImage*)psImageAlloc(3, 3, PS_TYPE_F32);
+    psImage *outImageF32 = (psImage*)psImageAlloc(3, 3, PS_TYPE_F32);
+    inImageF32->data.F32[0][0] = 1;
+    inImageF32->data.F32[0][1] = 2;
+    inImageF32->data.F32[0][2] = 3;
+    inImageF32->data.F32[1][0] = 4;
+    inImageF32->data.F32[1][1] = 5;
+    inImageF32->data.F32[1][2] = 6;
+    inImageF32->data.F32[2][0] = 7;
+    inImageF32->data.F32[2][1] = 8;
+    inImageF32->data.F32[2][2] = 9;
+
+    // Transpose input image into output image
+    {
+        psMemId id = psMemGetId();
+        psImage *tempImage = outImage;
+        outImage = psMatrixTranspose(outImage, inImage);
+        ok(outImage->type.dimen == PS_DIMEN_IMAGE, "psMatrixTranspose(): outImage has correct number of dimensions");
+        ok(outImage == tempImage, "psMatrixTranspose(): Return pointer equal to output argument pointer");
+        ok(!check_matrix(outImage), "Output image data set correctly");
+
+        tempImage = outImageF32;
+        outImageF32 = psMatrixTranspose(outImageF32, inImageF32);
+        ok(!check_matrix(outImageF32), "Output image data set correctly");
+        ok(outImageF32->type.dimen == PS_DIMEN_IMAGE, "psMatrixTranspose(): outImage has correct number of dimensions");
+        ok(outImageF32 == tempImage, "psMatrixTranspose(): Return pointer equal to output argument pointer");
+
+        psFree(outImage);
+        psFree(outImageF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Transpose input image into auto allocated NULL output image
+    {
+        psMemId id = psMemGetId();
+        psImage *outImageNull = psMatrixTranspose(NULL, inImage);
+        ok(!check_matrix(outImageNull), "Output image data set correctly");
+
+        psImage *outImageNullF32 = psMatrixTranspose(NULL, inImageF32);
+        check_matrix(outImageNullF32);
+        ok(!check_matrix(outImageNullF32), "Output image data set correctly");
+
+        psFree(outImageNull);
+        psFree(outImageNullF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    psFree(inImage);
+    psFree(inImageF32);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix02.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix02.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix02.c	(revision 22158)
@@ -0,0 +1,131 @@
+/** @file  tst_psMatrix_02.c
+ *
+ *  @brief Test driver for negative tests for psMatrix transpose function
+ *
+ *  This test driver contains the following tests for psMatrix test point 2:
+ *     A)  Input pointer same as output pointer
+ *     B)  Null input psImage
+ *     C)  Incorrect type for input pointer
+ *     D)  Incorrect type for output pointer
+ *     E)  Matrix not square for output pointer
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.4 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2008-05-07 23:12:13 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+int main(psS32 argc,
+         char* argv[])
+{
+    psLogSetFormat("HLNM");
+    plan_tests(23);
+
+    // Input pointer same as output pointer
+    // XXX: This results in a seg fault.  It's not clear that passing this test is
+    // a requirement.  However, we should probably fix the case where the input
+    // image equals the output image.
+     {
+        psMemId id = psMemGetId();
+        psImage *inImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+        ok(psMatrixTranspose(inImage, inImage) == NULL, "psMatrixTranspose(): inImage == outImage results in NULL");
+        psFree(inImage);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Null input psImage
+    // Merge with tap_psMatrix01.c, get rid of this test (redundant)
+    {
+        psMemId id = psMemGetId();
+        psImage *nullImage = NULL;
+        psImage *outImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+        ok(psMatrixTranspose(outImage, nullImage) == NULL, "psMatrixTranspose(): inImage = NULL results in NULL return");
+        psFree(outImage);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Incorrect type for input pointer
+    {
+        psMemId id = psMemGetId();
+        psImage *inImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_U8);
+        psImage *outImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+        ok(psMatrixTranspose(outImage, inImage) == NULL, "psMatrixTranspose(): inImage wrong type (U8) results in NULL return");
+        psFree(outImage);
+        psFree(inImage);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Incorrect type for input pointer
+    {
+        psMemId id = psMemGetId();
+        psImage *inImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_S32);
+        psImage *outImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+        ok(psMatrixTranspose(outImage, inImage) == NULL, "psMatrixTranspose(): inImage wrong type (S32) results in NULL return");
+        psFree(outImage);
+        psFree(inImage);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Incorrect type for output pointer
+    {
+        psMemId id = psMemGetId();
+        psImage *inImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+        psImage *outImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_U8);
+        outImage = psMatrixTranspose(outImage, inImage);
+        ok(outImage != NULL, "psMatrixTranspose() results in non-NULL return");
+
+        // check that the type was changed.
+        ok(outImage->type.type == PS_TYPE_F64, "the output type was changed to F64");
+        psFree(inImage);
+        psFree(outImage);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // output target matrix not square (Nx > Ny) for output pointer
+    {
+        psMemId id = psMemGetId();
+        psImage *inImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+        psImage *outImage = (psImage*)psImageAlloc(3, 2, PS_TYPE_F64);
+        ok(psMatrixTranspose(outImage, inImage) != NULL, "psMatrixTranspose(): non-square matrix results in non-NULL");
+        ok(outImage->numCols == 3, "psMatrixTranspose(): output matrix dimensions match input");
+        ok(outImage->numRows == 3, "psMatrixTranspose(): output matrix dimensions match input");
+        psFree(inImage);
+        psFree(outImage);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // input matrix not square (Nx < Ny) 
+    {
+        psMemId id = psMemGetId();
+        psImage *inImage = (psImage*)psImageAlloc(2, 3, PS_TYPE_F64);
+        psImage *outImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+        ok(psMatrixTranspose(outImage, inImage) != NULL, "psMatrixTranspose(): non-square matrix results in non-NULL");
+        ok(outImage->numCols == 3, "psMatrixTranspose(): output matrix dimensions match input");
+        ok(outImage->numRows == 2, "psMatrixTranspose(): output matrix dimensions match input");
+        psFree(inImage);
+        psFree(outImage);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // input matrix not square (Nx > Ny) 
+    {
+        psMemId id = psMemGetId();
+        psImage *inImage = (psImage*)psImageAlloc(3, 2, PS_TYPE_F64);
+        psImage *outImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+        ok(psMatrixTranspose(outImage, inImage) != NULL, "psMatrixTranspose(): non-square matrix results in non-NULL");
+        ok(outImage->numCols == 2, "psMatrixTranspose(): output matrix dimensions match input");
+        ok(outImage->numRows == 3, "psMatrixTranspose(): output matrix dimensions match input");
+        psFree(inImage);
+        psFree(outImage);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix03.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix03.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix03.c	(revision 22158)
@@ -0,0 +1,228 @@
+/** @file  tst_psMatrix_03.c
+ *
+ *  @brief Test driver for psMatrix LU functions
+ *
+ *  This test driver contains the following tests for psMatrix test point 3:
+ *     Create input and output images and vectors
+ *     Calculate LU matrix
+ *     Determine solution to matrix equation
+ *     Free input and output images and vectors
+ *     Attempt to use null image input argument
+ *     Attempt to use null input vector argument
+ *     Attempt to use null LU image argument
+ *
+ * XXX: Some tests should generate an error or warning, but we don't know how to test that.
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2007-05-02 04:14:33 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define TOLERANCE 0.000001
+double truthVector[3] = {4.000000, -2.000000, 3.000000};
+double truthMatrix[3][3] = {{4.000000,  5.000000,  6.000000},
+                            {0.750000, -2.750000, -6.500000},
+                            {0.500000, -0.545455, -0.545455}};
+
+psS32 checkMatrix(psImage *img)
+{
+    bool errorFlag = false;
+    for(psU32 i=0; i<img->numRows; i++) {
+        for(psU32 j=0; j<img->numCols; j++) {
+            if(img->type.type == PS_TYPE_F64) {
+                if(fabs(img->data.F64[i][j]-truthMatrix[i][j]) > TOLERANCE) {
+                    diag("Matrix values at element %d, %d don't agree %lf vs %lf\n", i, j,
+                         img->data.F64[i][j], truthMatrix[i][j]);
+                    errorFlag = true;
+                }
+            } else if(img->type.type == PS_TYPE_F32) {
+                if(fabs(img->data.F32[i][j]-truthMatrix[i][j]) > TOLERANCE) {
+                    diag("Matrix values at element %d, %d don't agree %f vs %lf\n", i, j,
+                         img->data.F32[i][j], truthMatrix[i][j]);
+                    errorFlag = true;
+                }
+            }
+        }
+    }
+    return(errorFlag);
+}
+
+
+psS32 checkVector(psVector *vector)
+{
+    bool errorFlag = false;
+    for(psU32 i=0; i<vector->n; i++) {
+        if(vector->type.type == PS_TYPE_F64) {
+            if(fabs(vector->data.F64[i]-truthVector[i]) > TOLERANCE) {
+                diag("Vector values at element %d don't agree %lf vs %lf\n", i,
+                     vector->data.F64[i], truthVector[i]);
+                errorFlag = true;
+            }
+        } else if(vector->type.type == PS_TYPE_F32) {
+            if(fabs(vector->data.F32[i]-truthVector[i]) > TOLERANCE) {
+                diag("Vector values at element %d don't agree %f vs %lf\n", i,
+                     vector->data.F32[i], truthVector[i]);
+                errorFlag = true;
+            }
+        }
+    }
+    return(errorFlag);
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    plan_tests(16);
+
+    // This test calculates the LU matrix and then solved the linear equations
+    // in F64 mode.
+    {
+        psMemId id = psMemGetId();
+        psImage *luImage = (psImage*) psImageAlloc(3, 3, PS_TYPE_F64);
+        psImage *tempImage = luImage;
+        psImage *inImage = (psImage*) psImageAlloc(3, 3, PS_TYPE_F64);
+        inImage->data.F64[0][0] =  2;
+        inImage->data.F64[0][1] =  4;
+        inImage->data.F64[0][2] =  6;
+        inImage->data.F64[1][0] =  4;
+        inImage->data.F64[1][1] =  5;
+        inImage->data.F64[1][2] =  6;
+        inImage->data.F64[2][0] =  3;
+        inImage->data.F64[2][1] =  1;
+        inImage->data.F64[2][2] = -2;
+        psVector *perm = (psVector*) psVectorAlloc(3, PS_TYPE_F64);
+        psVector *outVector = (psVector*) psVectorAlloc(3, PS_TYPE_F32);
+        psVector *tempVector = outVector;
+        psVector *inVector = (psVector*) psVectorAlloc(3, PS_TYPE_F64);
+
+        luImage = psMatrixLUD(luImage, &perm, inImage);
+        ok(luImage != NULL, "psMatrixLUD() produced a non-NULL LU matrix");
+        skip_start(luImage == NULL, 6, "Skipping tests because LU matrix was NULL");
+        ok(!checkMatrix(luImage), "psMatrixLUD() produced the correct LU matrix");
+        ok(luImage->type.dimen == PS_DIMEN_IMAGE, "The LU matrix has the correct ->dimen member");
+        ok(luImage == tempImage, "The LU matrix was not created from scratch");
+
+        // Determine solution to matrix equation
+        inVector->data.F64[0] = 18.0;
+        inVector->data.F64[1] = 24.0;
+        inVector->data.F64[2] =  4.0;
+        inVector->n = 3;
+
+        outVector = psMatrixLUSolve(outVector, luImage, inVector, perm);
+        ok(!checkVector(outVector), "psMatrixLUSolve() correctly solved the equations");
+        ok(outVector->type.dimen == PS_DIMEN_VECTOR, "The output vector hasthe correct ->dimen member");
+        ok(outVector == tempVector, "The output vector was not created from scratch");
+
+        skip_end();
+        psFree(inImage);
+        psFree(luImage);
+        psFree(perm);
+        psFree(outVector);
+        psFree(inVector);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // This test calculates the LU matrix and then solved the linear equations
+    // in F32 mode.
+    {
+        psMemId id = psMemGetId();
+        psImage *luImage32 = (psImage*)psImageAlloc(3, 3, PS_TYPE_F32);
+        psImage *tempImage32 = luImage32;
+        psImage *inImage32 = (psImage*)psImageAlloc(3, 3, PS_TYPE_F32);
+        inImage32->data.F32[0][0] =  2;
+        inImage32->data.F32[0][1] =  4;
+        inImage32->data.F32[0][2] =  6;
+        inImage32->data.F32[1][0] =  4;
+        inImage32->data.F32[1][1] =  5;
+        inImage32->data.F32[1][2] =  6;
+        inImage32->data.F32[2][0] =  3;
+        inImage32->data.F32[2][1] =  1;
+        inImage32->data.F32[2][2] = -2;
+        psVector *perm32 = NULL;
+        psVector *outVector32 = (psVector*)psVectorAlloc(3, PS_TYPE_F32);
+        psVector *tempVector32 = outVector32;
+        psVector *inVector32 = (psVector*)psVectorAlloc(3, PS_TYPE_F32);
+        inVector32->data.F32[0] = 18.0;
+        inVector32->data.F32[1] = 24.0;
+        inVector32->data.F32[2] =  4.0;
+        inVector32->n = 3;
+
+        luImage32 = psMatrixLUD(luImage32, &perm32, inImage32);
+        ok(luImage32 != NULL, "psMatrixLUD() produced a non-NULL LU matrix");
+        skip_start(luImage32 == NULL, 6, "Skipping tests because LU matrix was NULL");
+        ok(!checkMatrix(luImage32), "psMatrixLUD() produced the correct LU matrix");
+        ok(luImage32->type.dimen == PS_DIMEN_IMAGE, "The LU matrix has the correct ->dimen member");
+        ok(luImage32 == tempImage32, "The LU matrix was not created from scratch");
+
+        // Determine solution to matrix equation
+
+        outVector32 = psMatrixLUSolve(outVector32, luImage32, inVector32, perm32);
+        ok(!checkVector(outVector32), "psMatrixLUSolve() correctly solved the equations");
+        ok(outVector32->type.dimen == PS_DIMEN_VECTOR, "The output vector hasthe correct ->dimen member");
+        ok(outVector32 == tempVector32, "The output vector was not created from scratch");
+
+        skip_end();
+        psFree(inImage32);
+        psFree(luImage32);
+        psFree(perm32);
+        psFree(outVector32);
+        psFree(inVector32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to use null image input argument
+    // XXX: This test should generate an error or warning
+    // XXX: This seg-faults
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage *imageTest = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+        psMatrixLUD(imageTest, NULL, NULL);
+        psFree(imageTest);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to use null input vector argument
+    // XXX: This test should generate an error or warning
+    // XXX: This seg-faulta
+    if (0) {
+        psMemId id = psMemGetId();
+        psVector *vectorBad = NULL;
+        psVector *vectorBadOut = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+        psVector *permBad = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+        psImage *imageTest = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+        psMatrixLUSolve(vectorBadOut, imageTest, vectorBad, permBad);
+        psFree(vectorBadOut);
+        psFree(permBad);
+        psFree(imageTest);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to use null LU image argument
+    // XXX: This test should generate an error or warning, but we don't know how to test that.
+    // XXX: This seg-faulta
+    if (0) {
+        psMemId id = psMemGetId();
+        psVector *vectorBadOut = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+        psVector *vectorBad = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+        psVector *permBad = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+        psMatrixLUSolve(vectorBadOut, NULL, vectorBad, permBad);
+        psFree(vectorBadOut);
+        psFree(vectorBad);
+        psFree(permBad);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix04.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix04.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix04.c	(revision 22158)
@@ -0,0 +1,170 @@
+/** @file  tst_psMatrix_04.c
+ *
+ *  @brief Test driver for psMatrix invert function
+ *
+ *  This test driver contains the following tests for psMatrix test point 4:
+ *     Create input and output images
+ *     Invert matrix and calculate determinant
+ *     Calculate determinant only
+ *     Free input and output images
+ *     Attempt to use null input image argument
+ *     Attempt to use null input float argument
+ *
+ * Sme tests should generate an error/warning, but we don't know how to test that.
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.1 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2006-12-20 20:02:29 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#define TOLERANCE 0.000001
+double truthMatrix[3][3] = {{4.0000000, -4.333333, -2.333333},
+                            {-1.000000,  1.666667,  0.666667},
+                            {-1.000000,  0.666667,  0.666667}};
+double truthValue = 3.0;
+
+psS32 checkMatrix(psImage *img)
+{
+    bool errorFlag = false;
+    for(psU32 i=0; i<img->numRows; i++) {
+        for(psU32 j=0; j<img->numCols; j++) {
+            if(img->type.type == PS_TYPE_F64) {
+                if(fabs(img->data.F64[i][j]-truthMatrix[i][j]) > TOLERANCE) {
+                    diag("Matrix values at element %d, %d don't agree %lf vs %lf\n", i, j,
+                         img->data.F64[i][j], truthMatrix[i][j]);
+                    errorFlag = true;
+                }
+            } else if(img->type.type == PS_TYPE_F32) {
+                if(fabs(img->data.F32[i][j]-truthMatrix[i][j]) > TOLERANCE) {
+                    diag("Matrix values at element %d, %d don't agree %f vs %lf\n", i, j,
+                         img->data.F32[i][j], truthMatrix[i][j]);
+                    errorFlag = true;
+                }
+            }
+        }
+    }
+    return(errorFlag);
+}
+
+psS32 checkValue(psF64 value)
+{
+    if(fabs(value-truthValue) > TOLERANCE) {
+        diag("Values don't agree %lf vs %lf\n", value, truthValue);
+        return(true);
+    } else {
+        return(false);
+    }
+}
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    plan_tests(14);
+
+    // Invert matrix and calculate determinant: F64
+    {
+        psMemId id = psMemGetId();
+        float det = 0.0f;
+        float det2 = 0;
+        psImage *tempImage = NULL;
+        psImage *outImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+        psImage *inImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+        inImage->data.F64[0][0] =  2;
+        inImage->data.F64[0][1] =  4;
+        inImage->data.F64[0][2] =  3;
+        inImage->data.F64[1][0] =  0;
+        inImage->data.F64[1][1] =  1;
+        inImage->data.F64[1][2] = -1;
+        inImage->data.F64[2][0] =  3;
+        inImage->data.F64[2][1] =  5;
+        inImage->data.F64[2][2] =  7;
+
+        tempImage = outImage;
+        outImage = psMatrixInvert(outImage, inImage, &det);
+        ok(outImage != NULL, "psMatrixInvert() produced a non-NULL matrix");
+        skip_start(outImage == NULL, 4, "Skipping tests because the output matrix is NULL");
+        ok(!checkMatrix(outImage), "psMatrixInvert() produced the correct output matrix");
+        ok(!checkValue(det), "psMatrixInvert() produced the correct determinant");
+        ok(outImage->type.dimen == PS_DIMEN_IMAGE, "psMatrixInvert() produced the correct ->dimen member");
+        ok(outImage == tempImage, "psMatrixInvert() did not allocate a new output matrix");
+        det = 0.0f;
+
+        det2 = psMatrixDeterminant(inImage);
+        ok(!checkValue(det2), "psMatrixDeterminant() produced the correct determinant");
+
+        skip_end()
+        psFree(outImage);
+        psFree(inImage);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Invert matrix and calculate determinant: F32
+    {
+        psMemId id = psMemGetId();
+        float det = 0.0f;
+        float det2 = 0;
+        psImage *tempImage32 = NULL;
+        psImage *outImage32 = (psImage*)psImageAlloc(3, 3, PS_TYPE_F32);
+        psImage *inImage32 = (psImage*)psImageAlloc(3, 3, PS_TYPE_F32);
+        inImage32->data.F32[0][0] =  2;
+        inImage32->data.F32[0][1] =  4;
+        inImage32->data.F32[0][2] =  3;
+        inImage32->data.F32[1][0] =  0;
+        inImage32->data.F32[1][1] =  1;
+        inImage32->data.F32[1][2] = -1;
+        inImage32->data.F32[2][0] =  3;
+        inImage32->data.F32[2][1] =  5;
+        inImage32->data.F32[2][2] =  7;
+
+        tempImage32 = outImage32;
+        outImage32 = psMatrixInvert(outImage32, inImage32, &det);
+        ok(outImage32 != NULL, "psMatrixInvert() produced a non-NULL matrix");
+        skip_start(outImage32 == NULL, 4, "Skipping tests because the output matrix is NULL");
+        ok(!checkMatrix(outImage32), "psMatrixInvert() produced the correct output matrix");
+        ok(!checkValue(det), "psMatrixInvert() produced the correct determinant");
+        ok(outImage32->type.dimen == PS_DIMEN_IMAGE, "psMatrixInvert() produced the correct ->dimen member");
+        ok(outImage32 == tempImage32, "psMatrixInvert() did not allocate a new output matrix");
+
+        det2 = psMatrixDeterminant(inImage32);
+        ok(!checkValue(det2), "psMatrixDeterminant() produced the correct determinant");
+
+        skip_end()
+        psFree(outImage32);
+        psFree(inImage32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to use null input image argument
+    // XXX: This should generate an error/warning, but we don't know how to test that.
+    if (0) {
+        psMemId id = psMemGetId();
+        float det = 0.0f;
+        psImage *badOutImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+        psMatrixInvert(badOutImage, NULL, &det);
+        psFree(badOutImage);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to use null input float argument
+    // XXX: This should generate an error/warning, but we don't know how to test that.
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage *badInImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+        psImage *badOutImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+        psMatrixInvert(badOutImage, badInImage, NULL);
+        psFree(badInImage);
+        psFree(badOutImage);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix05.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix05.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix05.c	(revision 22158)
@@ -0,0 +1,120 @@
+/** @file  tst_psMatrix_05.c
+*
+*  @brief Test driver for psMatrix multiplication function
+*
+*  This test driver contains the following tests for psMatrix test point 5:
+*     A)  Create input and output images
+*     B)  Multiply images
+*     C)  Free input and output images
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.1 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2006-12-20 20:02:29 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#define TOLERANCE 0.000001
+double truthMatrix[3][3] = {{  0.0, 52.0},
+                            {-14.0, 51.0}};
+
+psS32 checkMatrix(psImage *img)
+{
+    bool errorFlag = false;
+    for(psU32 i=0; i<img->numRows; i++) {
+        for(psU32 j=0; j<img->numCols; j++) {
+            if(img->type.type == PS_TYPE_F64) {
+                if(fabs(img->data.F64[i][j]-truthMatrix[i][j]) > TOLERANCE) {
+                    diag("Matrix values at element %d, %d don't agree %lf vs %lf\n", i, j,
+                         img->data.F64[i][j], truthMatrix[i][j]);
+                    errorFlag = true;
+                }
+            } else if(img->type.type == PS_TYPE_F32) {
+                if(fabs(img->data.F32[i][j]-truthMatrix[i][j]) > TOLERANCE) {
+                    diag("Matrix values at element %d, %d don't agree %f vs %lf\n", i, j,
+                         img->data.F32[i][j], truthMatrix[i][j]);
+                    errorFlag = true;
+                }
+            }
+        }
+    }
+    return(errorFlag);
+}
+
+psS32 main(psS32 argc,
+           char* argv[])
+{
+    psLogSetFormat("HLNM");
+    plan_tests(6);
+
+    // Create input and output images, then multiple: F64 version
+    {
+        psMemId id = psMemGetId();
+        psImage * outImage = (psImage*) psImageAlloc(2, 2, PS_TYPE_F64);
+        psImage *inImage1 = (psImage*) psImageAlloc(3, 2, PS_TYPE_F64);
+        psImage *inImage2 = (psImage*) psImageAlloc(2, 3, PS_TYPE_F64);
+        inImage1->data.F64[0][0] = 2;
+        inImage1->data.F64[0][1] = 3;
+        inImage1->data.F64[0][2] = 4;
+        inImage1->data.F64[1][0] = -1;
+        inImage1->data.F64[1][1] = 2;
+        inImage1->data.F64[1][2] = 5;
+        inImage2->data.F64[0][0] = 4;
+        inImage2->data.F64[0][1] = 1;
+        inImage2->data.F64[1][0] = 0;
+        inImage2->data.F64[1][1] = 6;
+        inImage2->data.F64[2][0] = -2;
+        inImage2->data.F64[2][1] = 8;
+
+        // Test B - Multiply images
+        psMatrixMultiply(outImage, inImage1, inImage2);
+        ok(outImage != NULL, "psMatrixMultiply() produced a non-NULL output matrix");
+        ok(!checkMatrix(outImage), "psMatrixMultiply() produced the correct output matrix");
+
+        // Test C - Free input and output images
+        psFree(outImage);
+        psFree(inImage1);
+        psFree(inImage2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Create input and output images, then multiple: F32 version
+    {
+        psMemId id = psMemGetId();
+        psImage * outImage32 = NULL;
+        psImage *inImage132 = NULL;
+        psImage *inImage232 = NULL;
+        outImage32 = (psImage*)psImageAlloc(2, 2, PS_TYPE_F32);
+        inImage132 = (psImage*)psImageAlloc(3, 2, PS_TYPE_F32);
+        inImage232 = (psImage*)psImageAlloc(2, 3, PS_TYPE_F32);
+        inImage132->data.F32[0][0] = 2;
+        inImage132->data.F32[0][1] = 3;
+        inImage132->data.F32[0][2] = 4;
+        inImage132->data.F32[1][0] = -1;
+        inImage132->data.F32[1][1] = 2;
+        inImage132->data.F32[1][2] = 5;
+        inImage232->data.F32[0][0] = 4;
+        inImage232->data.F32[0][1] = 1;
+        inImage232->data.F32[1][0] = 0;
+        inImage232->data.F32[1][1] = 6;
+        inImage232->data.F32[2][0] = -2;
+        inImage232->data.F32[2][1] = 8;
+
+        // Test B - Multiply images
+        psMatrixMultiply(outImage32, inImage132, inImage232);
+        ok(outImage32 != NULL, "psMatrixMultiply() produced a non-NULL output matrix");
+        ok(!checkMatrix(outImage32), "psMatrixMultiply() produced the correct output matrix");
+
+        // Test C - Free input and output images
+        psFree(outImage32);
+        psFree(inImage132);
+        psFree(inImage232);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix06.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix06.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix06.c	(revision 22158)
@@ -0,0 +1,124 @@
+/** @file  tst_psMatrix_06.c
+*
+*  @brief Test driver for psMatrix Eigenvectors function
+*
+*  This test driver contains the following tests for psMatrix test point 6:
+*     A)  Create input and output images
+*     B)  Calculate Eigenvectors
+*     C)  Free input and output images
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.1 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2006-12-20 20:02:29 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#define TOLERANCE 0.000001
+double truthMatrix[4][4] = {{0.792608,  0.582076, -0.179186, -0.029193},
+                            {0.451923, -0.370502,  0.741918,  0.328712},
+                            {0.322416, -0.509579, -0.100228, -0.791411},
+                            {0.252161, -0.514048, -0.638283,  0.514553}};
+
+
+psS32 checkMatrix(psImage *img)
+{
+    bool errorFlag = false;
+    for(psU32 i=0; i<img->numRows; i++) {
+        for(psU32 j=0; j<img->numCols; j++) {
+            if(img->type.type == PS_TYPE_F64) {
+                if(fabs(img->data.F64[i][j]-truthMatrix[i][j]) > TOLERANCE) {
+                    diag("Matrix values at element %d, %d don't agree %lf vs %lf\n", i, j,
+                         img->data.F64[i][j], truthMatrix[i][j]);
+                    errorFlag = true;
+                }
+            } else if(img->type.type == PS_TYPE_F32) {
+                if(fabs(img->data.F32[i][j]-truthMatrix[i][j]) > TOLERANCE) {
+                    diag("Matrix values at element %d, %d don't agree %f vs %lf\n", i, j,
+                         img->data.F32[i][j], truthMatrix[i][j]);
+                    errorFlag = true;
+                }
+            }
+        }
+    }
+    return(errorFlag);
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    plan_tests(6);
+
+    // Create input and output images, then produce Eigen vectors: F64 version
+    {
+        psMemId id = psMemGetId();
+        psImage * outImage = (psImage*) psImageAlloc(4, 4, PS_TYPE_F64);
+        psImage *inImage = (psImage*)  psImageAlloc(4, 4, PS_TYPE_F64);
+        inImage->data.F64[0][0] = 1./1.;
+        inImage->data.F64[0][1] = 1./2.;
+        inImage->data.F64[0][2] = 1./3.;
+        inImage->data.F64[0][3] = 1./4.;
+        inImage->data.F64[1][0] = 1./2.;
+        inImage->data.F64[1][1] = 1./3.;
+        inImage->data.F64[1][2] = 1./4.;
+        inImage->data.F64[1][3] = 1./5.;
+        inImage->data.F64[2][0] = 1./3.;
+        inImage->data.F64[2][1] = 1./4.;
+        inImage->data.F64[2][2] = 1./5.;
+        inImage->data.F64[2][3] = 1./6.;
+        inImage->data.F64[3][0] = 1./4.;
+        inImage->data.F64[3][1] = 1./5.;
+        inImage->data.F64[3][2] = 1./6.;
+        inImage->data.F64[3][3] = 1./7.;
+
+        psMatrixEigenvectors(outImage, inImage);
+        ok(outImage != NULL, "psMatrixEigenvectors() produced a NULL output Matrix");
+        skip_start(outImage == NULL, 1, "Skipping tests because output matrix was NULL");
+        ok(!checkMatrix(outImage), "psMatrixEigenvectors() produced the correct Matrix");
+        psFree(outImage);
+        psFree(inImage);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Create input and output images, then produce Eigen vectors: F32 version
+    {
+        psMemId id = psMemGetId();
+        psImage * outImage32 = (psImage*) psImageAlloc(4, 4, PS_TYPE_F32);
+        psImage *inImage32 = (psImage*)  psImageAlloc(4, 4, PS_TYPE_F32);
+        inImage32->data.F32[0][0] = 1./1.;
+        inImage32->data.F32[0][1] = 1./2.;
+        inImage32->data.F32[0][2] = 1./3.;
+        inImage32->data.F32[0][3] = 1./4.;
+        inImage32->data.F32[1][0] = 1./2.;
+        inImage32->data.F32[1][1] = 1./3.;
+        inImage32->data.F32[1][2] = 1./4.;
+        inImage32->data.F32[1][3] = 1./5.;
+        inImage32->data.F32[2][0] = 1./3.;
+        inImage32->data.F32[2][1] = 1./4.;
+        inImage32->data.F32[2][2] = 1./5.;
+        inImage32->data.F32[2][3] = 1./6.;
+        inImage32->data.F32[3][0] = 1./4.;
+        inImage32->data.F32[3][1] = 1./5.;
+        inImage32->data.F32[3][2] = 1./6.;
+        inImage32->data.F32[3][3] = 1./7.;
+
+        psMatrixEigenvectors(outImage32, inImage32);
+        ok(outImage32 != NULL, "psMatrixEigenvectors() produced a NULL output Matrix");
+        skip_start(outImage32 == NULL, 1, "Skipping tests because output matrix was NULL");
+        ok(!checkMatrix(outImage32), "psMatrixEigenvectors() produced the correct Matrix");
+        psFree(outImage32);
+        psFree(inImage32);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix07.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix07.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrix07.c	(revision 22158)
@@ -0,0 +1,340 @@
+/** @file  tst_psMatrix_07.c
+ *
+ *  @brief Test driver for psMatrix vector conversion functions
+ *
+ *  This test driver contains the following tests for psMatrix test point 7:
+ *     Create input and output images and vectors
+ *     Convert matrix to PS_DIMEN_VECTOR vector
+ *     Attempt to use null image input argument
+ *     Convert matrix to PS_DIMEN_TRANSV vector
+ *     XXX: Improper image size (NOT TESTED)
+ *     Convert PS_DIMEN_VECTOR vector to matrix
+ *     XXX: Attempt to use null input vector argument (NOT TESTED)
+ *     Convert PS_DIMEN_TRANSV vector to matrix
+ *     Free input and output images and vectors
+ *
+ * XXX: This should produce an error; how can we test it?
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2007-02-07 22:50:18 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#define TOLERANCE 0.000001
+psF64 truthVector[3] = {0.0, 1.0, 2.0};
+psF32 truthVector_32[3] = {0.0, 1.0, 2.0};
+psF64 truthMatrix[3][1] = {{0.0}, {1.0}, {2.0}};
+psF32 truthMatrix_32[3][1] = {{0.0}, {1.0}, {2.0}};
+
+psS32 checkMatrix(psImage *img)
+{
+    bool errorFlag = false;
+    for(psU32 i=0; i<img->numRows; i++) {
+        for(psU32 j=0; j<img->numCols; j++) {
+            if(img->type.type == PS_TYPE_F64) {
+                if(fabs(img->data.F64[i][j]-truthMatrix[i][j]) > TOLERANCE) {
+                    diag("Matrix values at element %d, %d don't agree %lf vs %lf\n", i, j,
+                         img->data.F64[i][j], truthMatrix[i][j]);
+                    errorFlag = true;
+                }
+            } else if(img->type.type == PS_TYPE_F32) {
+                if(fabs(img->data.F32[i][j]-truthMatrix[i][j]) > TOLERANCE) {
+                    diag("Matrix values at element %d, %d don't agree %f vs %lf\n", i, j,
+                         img->data.F32[i][j], truthMatrix[i][j]);
+                    errorFlag = true;
+                }
+            }
+        }
+    }
+    return(errorFlag);
+}
+
+psS32 checkVector(psVector *vector)
+{
+    bool errorFlag = false;
+    for(psU32 i=0; i<vector->n; i++) {
+        if(vector->type.type == PS_TYPE_F64) {
+            if(fabs(vector->data.F64[i]-truthVector[i]) > TOLERANCE) {
+                diag("Vector values at element %d don't agree %lf vs %lf\n", i,
+                     vector->data.F64[i], truthVector[i]);
+                errorFlag = true;
+            }
+        } else if(vector->type.type == PS_TYPE_F32) {
+            if(fabs(vector->data.F32[i]-truthVector[i]) > TOLERANCE) {
+                diag("Vector values at element %d don't agree %f vs %lf\n", i,
+                     vector->data.F32[i], truthVector[i]);
+                errorFlag = true;
+            }
+        }
+    }
+    return(errorFlag);
+}
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    plan_tests(44);
+
+    // Convert matrix to PS_DIMEN_VECTOR vector: F64 version
+    {
+        psMemId id = psMemGetId();
+        psVector *v1 = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+        psImage *m1 = (psImage*)psImageAlloc(1, 3, PS_TYPE_F64);
+        m1->data.F64[0][0] = 0.0;
+        m1->data.F64[1][0] = 1.0;
+        m1->data.F64[2][0] = 2.0;
+        psVector *tempVector = v1;
+
+        v1 = psMatrixToVector(v1, m1);
+        ok(v1 != NULL, "psMatrixToVector() produced a non-NULL vector");
+        skip_start(v1 == NULL, 3, "Skipping tests because vector was NULL");
+        ok(!checkVector(v1), "psMatrixToVector() produced the correct vector");
+        ok(v1->type.dimen == PS_DIMEN_VECTOR, "psMatrixToVector() produced the correct ->dimen member");
+        ok(v1 == tempVector, "psMatrixToVector() did not allocate a new output vector");
+
+        skip_end();
+        psFree(m1);
+        psFree(v1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Convert matrix to PS_DIMEN_VECTOR vector: F32 version
+    {
+        psMemId id = psMemGetId();
+        psVector *v1_32 = (psVector*)psVectorAlloc(3, PS_TYPE_F32);
+        psImage *m1_32 = (psImage*)psImageAlloc(1,3,PS_TYPE_F32);
+        m1_32->data.F32[0][0] = 0.0;
+        m1_32->data.F32[1][0] = 1.0;
+        m1_32->data.F32[2][0] = 2.0;
+        psVector *tempVector_32 = v1_32;
+
+        v1_32 = psMatrixToVector(v1_32, m1_32);
+        ok(v1_32 != NULL, "psMatrixToVector() produced a non-NULL vector");
+        skip_start(v1_32 == NULL, 3, "Skipping tests because vector was NULL");
+        ok(!checkVector(v1_32), "psMatrixToVector() produced the correct vector");
+        ok(v1_32->type.dimen == PS_DIMEN_VECTOR, "psMatrixToVector() produced the correct ->dimen member");
+        ok(v1_32 == tempVector_32, "psMatrixToVector() did not allocate a new output vector");
+
+        skip_end();
+        psFree(m1_32);
+        psFree(v1_32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Attempt to use null image input argument: F64 version
+    {
+        psMemId id = psMemGetId();
+        psVector *v1 = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+        v1 = psMatrixToVector(v1, NULL);
+        ok(v1 == NULL, "psMatrixToVector() returned NULL with NULL matrix argument");
+        psFree(v1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Attempt to use null image input argument: F32 version
+    {
+        psMemId id = psMemGetId();
+        psVector *v1_32 = (psVector*)psVectorAlloc(3, PS_TYPE_F32);
+        v1_32 = psMatrixToVector(v1_32, NULL);
+        ok(v1_32 == NULL, "psMatrixToVector() returned NULL with NULL matrix argument");
+        psFree(v1_32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Convert matrix to PS_DIMEN_TRANSV vector: F64 version
+    {
+        psMemId id = psMemGetId();
+        psImage *m4 = (psImage*)psImageAlloc(3, 1, PS_TYPE_F64);
+        m4->data.F64[0][0] = 0.0;
+        m4->data.F64[0][1] = 1.0;
+        m4->data.F64[0][2] = 2.0;
+        psVector *v3 = psVectorAlloc(3, PS_TYPE_F64);
+        psVector *tempVector = v3;
+
+        v3->type.dimen = PS_DIMEN_TRANSV;
+        psMatrixToVector(v3, m4);
+        ok(v3 != NULL, "psMatrixToVector() produced non-NULL output VECTOR");
+        skip_start(v3 == NULL, 3, "Skipping tests because of non-NULL output VECTOR");
+        ok(!checkVector(v3), "psMatrixToVector() produced the correct vector");
+        ok(v3->type.dimen == PS_DIMEN_TRANSV, "psMatrixToVector() produced the correct ->dimen member");
+        ok(v3 == tempVector, "psMatrixToVector() did not allocate a new output vector");
+
+        skip_end();
+        psFree(m4);
+        psFree(v3);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Convert matrix to PS_DIMEN_TRANSV vector: F32 version
+    {
+        psMemId id = psMemGetId();
+        psImage *m4_32 = m4_32 = (psImage*)psImageAlloc(3,1,PS_TYPE_F32);
+        m4_32->data.F32[0][0] = 0.0;
+        m4_32->data.F32[0][1] = 1.0;
+        m4_32->data.F32[0][2] = 2.0;
+        psVector *v3_32 = psVectorAlloc(3, PS_TYPE_F32);
+        psVector *tempVector_32 = v3_32;
+
+        v3_32->type.dimen = PS_DIMEN_TRANSV;
+        psMatrixToVector(v3_32, m4_32);
+        ok(v3_32 != NULL, "psMatrixToVector() produced non-NULL output VECTOR");
+        skip_start(v3_32 == NULL, 3, "Skipping tests because of non-NULL output VECTOR");
+        ok(!checkVector(v3_32), "psMatrixToVector() produced the correct vector");
+        ok(v3_32->type.dimen == PS_DIMEN_TRANSV, "psMatrixToVector() produced the correct ->dimen member");
+        ok(v3_32 == tempVector_32, "psMatrixToVector() did not allocate a new output vector");
+
+        skip_end();
+        psFree(m4_32);
+        psFree(v3_32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Improper image size: F64 version
+    // XXX: This should produce an error; how can we test it?
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage *badImage = (psImage*)psImageAlloc(2, 2, PS_TYPE_F64);
+        psVector *v1 = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+        ok(psMatrixToVector(v1, badImage) == NULL, "psMatrixToVector() returned NULL with improper sizes");
+        psFree(badImage);
+        psFree(v1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Improper image size: F32 version
+    // XXX: This should produce an error; how can we test it?
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage *badImage_32 = (psImage*)psImageAlloc(2,2,PS_TYPE_F32);
+        psVector *v1_32 = (psVector*)psVectorAlloc(3, PS_TYPE_F32);
+        ok(psMatrixToVector(v1_32, badImage_32) == NULL, "psMatrixToVector() returned NULL with improper sizes");
+        psFree(badImage_32);
+        psFree(v1_32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Convert PS_DIMEN_VECTOR vector to matrix: F64 version
+    {
+        psMemId id = psMemGetId();
+        psImage *m2 = (psImage*)psImageAlloc(1, 3, PS_TYPE_F64);
+        psVector *v2 = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+        v2->data.F64[0] = 0.0;
+        v2->data.F64[1] = 1.0;
+        v2->data.F64[2] = 2.0;
+        v2->n = 3;
+
+        psImage *tempImage = m2;
+        m2 = psVectorToMatrix(m2, v2);
+        ok(m2 != NULL, "psVectorToMatrix() produced non-NULL output matrix");
+        skip_start(m2 == NULL, 3, "Skipping tests because of non-NULL output matrix");
+        ok(!checkMatrix(m2), "psVectorToMatrix() produced the correct vector");
+        ok(m2->type.dimen == PS_DIMEN_IMAGE, "psVectorToMatrix() produced the correct ->dimen member");
+        ok(m2 == tempImage, "psVectorToMatrix() did not allocate a new output matrix");
+
+        skip_end();
+        psFree(m2);
+        psFree(v2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Convert PS_DIMEN_VECTOR vector to matrix: F32 version
+    {
+        psMemId id = psMemGetId();
+        psImage *m2_32 = (psImage*)psImageAlloc(1,3,PS_TYPE_F32);
+        psVector *v2_32 = (psVector*)psVectorAlloc(3,PS_TYPE_F32);
+        v2_32->data.F32[0] = 0.0;
+        v2_32->data.F32[1] = 1.0;
+        v2_32->data.F32[2] = 2.0;
+        v2_32->n = 3;
+
+        psImage *tempImage_32 = m2_32;
+        m2_32 = psVectorToMatrix(m2_32, v2_32);
+        ok(m2_32 != NULL, "psVectorToMatrix() produced non-NULL output matrix");
+        skip_start(m2_32 == NULL, 3, "Skipping tests because of non-NULL output matrix");
+        ok(!checkMatrix(m2_32), "psVectorToMatrix() produced the correct vector");
+        ok(m2_32->type.dimen == PS_DIMEN_IMAGE, "psVectorToMatrix() produced the correct ->dimen member");
+        ok(m2_32 == tempImage_32, "psVectorToMatrix() did not allocate a new output matrix");
+
+        skip_end();
+        psFree(m2_32);
+        psFree(v2_32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Attempt to use null input vector argument: F64 version
+    // XXX: This should produce an error; how can we test it?
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage *m2 = (psImage*)psImageAlloc(1, 3, PS_TYPE_F64);
+        ok(psVectorToMatrix(m2, NULL) == NULL, "psVectorToMatrix() returned NULL with NULL input vector");
+        psFree(m2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Attempt to use null input vector argument: F32 version
+    // XXX: This should produce an error; how can we test it?
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage *m2_32 = (psImage*)psImageAlloc(1,3,PS_TYPE_F32);
+        ok(psVectorToMatrix(m2_32, NULL) == NULL, "psVectorToMatrix() returned NULL with NULL input vector");
+        psFree(m2_32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Convert PS_DIMEN_TRANSV vector to matrix: F64 version
+    {
+        psMemId id = psMemGetId();
+        psVector *v2 = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+        v2->data.F64[0] = 0.0;
+        v2->data.F64[1] = 1.0;
+        v2->data.F64[2] = 2.0;
+        v2->n = 3;
+        v2->type.dimen = PS_DIMEN_TRANSV;
+        psImage *m3 = (psImage*)psImageAlloc(3, 1, PS_TYPE_F64);
+        psImage *tempImage = m3;
+
+        psVectorToMatrix(m3, v2);
+        ok(m3 != NULL, "psVectorToMatrix() produced non-NULL output matrix");
+        skip_start(m3 == NULL, 3, "Skipping tests because of non-NULL output matrix");
+        ok(!checkMatrix(m3), "psVectorToMatrix() produced the correct vector");
+        ok(m3->type.dimen == PS_DIMEN_IMAGE, "psVectorToMatrix() produced the correct ->dimen member");
+        ok(m3 == tempImage, "psVectorToMatrix() did not allocate a new output matrix");
+
+        skip_end();
+        psFree(v2);
+        psFree(m3);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Convert PS_DIMEN_TRANSV vector to matrix: F32 version
+    {
+        psMemId id = psMemGetId();
+        psVector *v2_32 = (psVector*)psVectorAlloc(3,PS_TYPE_F32);
+        v2_32->data.F32[0] = 0.0;
+        v2_32->data.F32[1] = 1.0;
+        v2_32->data.F32[2] = 2.0;
+        v2_32->n = 3;
+        v2_32->type.dimen = PS_DIMEN_TRANSV;
+        psImage *m3_32 = (psImage*)psImageAlloc(3,1,PS_TYPE_F32);
+        psImage *tempImage_32 = m3_32;
+
+        psVectorToMatrix(m3_32, v2_32);
+        ok(m3_32 != NULL, "psVectorToMatrix() produced non-NULL output matrix");
+        skip_start(m3_32 == NULL, 3, "Skipping tests because of non-NULL output matrix");
+        ok(!checkMatrix(m3_32), "psVectorToMatrix() produced the correct vector");
+        ok(m3_32->type.dimen == PS_DIMEN_IMAGE, "psVectorToMatrix() produced the correct ->dimen member");
+        ok(m3_32 == tempImage_32, "psVectorToMatrix() did not allocate a new output matrix");
+
+        skip_end();
+        psFree(v2_32);
+        psFree(m3_32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrixVectorArithmetic01.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrixVectorArithmetic01.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrixVectorArithmetic01.c	(revision 22158)
@@ -0,0 +1,247 @@
+/** @file  tst_psMatrixVectorArithmetic01.c
+ *
+ *  @brief Test driver for psMatrixVector arithmetic functions
+ *
+ *  This test driver tests combinations of matrix, vector, and scalar binary operations including:
+ *     Matrix-matrix with +,-,*,/ with S32, F32, F64
+ *     Matrix-vector with +,-,*,/ with S32, F32, F64
+ *     Matrix-scalar with +,-,*,/ with S32, F32, F64
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2007-05-02 04:14:33 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#define VERBOSE 1
+
+#define CREATE_AND_SET_VECTOR(NAME,TYPE,VALUE,SIZE)                \
+psVector *NAME = (psVector*)psVectorAlloc(SIZE, PS_TYPE_##TYPE);   \
+{                                                                  \
+    ps##TYPE tmpScalar = VALUE;                                    \
+    for(psS32 i=0; i<SIZE; i++) {                                  \
+        NAME->data.TYPE[i] = tmpScalar;                            \
+        tmpScalar+= (ps##TYPE) 1;                                  \
+    }                                                              \
+}                                                                  \
+NAME->n = SIZE;
+
+
+#define CREATE_AND_SET_IMAGE(NAME,TYPE,VALUE,NROWS,NCOLS)          \
+psImage *NAME = (psImage*)psImageAlloc(NCOLS,NROWS,PS_TYPE_##TYPE);\
+{                                                                  \
+    ps##TYPE tmpScalar = VALUE;                                    \
+    for (psS32 i=0; i<NAME->numRows; i++) {                        \
+        for(psS32 j=0; j<NAME->numCols; j++) {                     \
+            NAME->data.TYPE[i][j] = tmpScalar;                     \
+            tmpScalar+= (ps##TYPE) 1;                              \
+        }                                                          \
+    }                                                              \
+}
+
+#define testBinaryOpMM(OP,TYPE,VALUE1,VALUE2,NROWS,NCOLS,ERRORFLAG,MEMORYFLAG) \
+{                                                                              \
+    psMemId id = psMemGetId();                                                 \
+    ERRORFLAG = false;                                                         \
+    MEMORYFLAG = false;                                                        \
+    CREATE_AND_SET_IMAGE(in1,TYPE,VALUE1,NROWS,NCOLS);                         \
+    CREATE_AND_SET_IMAGE(in2,TYPE,VALUE2,NROWS,NCOLS);                         \
+    psImage *out = (psImage*)psBinaryOp(NULL, in1, #OP, in2);                  \
+    for (psS32 i = 0 ; i < NROWS ; i++) {                                      \
+        for (psS32 j = 0 ; j < NCOLS ; j++) {                                  \
+            ps##TYPE expect = in1->data.TYPE[i][j] OP in2->data.TYPE[i][j];    \
+            if (fabs((psF32) (out->data.TYPE[i][j] - expect)) > 0.1) {         \
+                errorFlag = true;                                              \
+                if (VERBOSE) {                                                 \
+                    printf("TEST ERROR: outImage[%d][%d] is %f, should be %f\n", i, j, (psF32) out->data.TYPE[i][j], (psF32) expect); \
+                }                                                              \
+            }                                                                  \
+        }                                                                      \
+    }                                                                          \
+    psFree(in1);                                                               \
+    psFree(in2);                                                               \
+    psFree(out);                                                               \
+    MEMORYFLAG = psMemCheckLeaks(id, NULL, NULL, false);                       \
+}
+
+#define testBinaryOpMV(OP,TYPE,VALUE1,VALUE2,NROWS,NCOLS,ERRORFLAG,MEMORYFLAG) \
+{                                                                              \
+    psMemId id = psMemGetId();                                                 \
+    ERRORFLAG = false;                                                         \
+    MEMORYFLAG = false;                                                        \
+    CREATE_AND_SET_IMAGE(in,TYPE,VALUE1,NROWS,NCOLS);                          \
+    CREATE_AND_SET_VECTOR(inVector,TYPE,VALUE2,NROWS);                         \
+    psImage *out = (psImage*)psBinaryOp(NULL, in, #OP, inVector);              \
+    for (psS32 i = 0 ; i < NROWS ; i++) {                                      \
+        for (psS32 j = 0 ; j < NCOLS ; j++) {                                  \
+            ps##TYPE expect = in->data.TYPE[i][j] OP inVector->data.TYPE[i];   \
+            if (fabs((psF32) (out->data.TYPE[i][j] - expect)) > 0.1) {         \
+                errorFlag = true;                                              \
+                if (VERBOSE) {                                                 \
+                    printf("TEST ERROR: outImage[%d][%d] is %f, should be %f\n", i, j, (psF32) out->data.TYPE[i][j], (psF32) expect); \
+                }                                                              \
+            }                                                                  \
+        }                                                                      \
+    }                                                                          \
+    psFree(in);                                                                \
+    psFree(inVector);                                                          \
+    psFree(out);                                                               \
+    MEMORYFLAG = psMemCheckLeaks(id, NULL, NULL, false);                       \
+}
+
+#define testBinaryOpMS(OP,TYPE,VALUE1,VALUE2,NROWS,NCOLS,ERRORFLAG,MEMORYFLAG) \
+{                                                                              \
+    psMemId id = psMemGetId();                                                 \
+    ERRORFLAG = false;                                                         \
+    MEMORYFLAG = false;                                                        \
+    CREATE_AND_SET_IMAGE(in,TYPE,VALUE1,NROWS,NCOLS);                          \
+    psScalar *inScalar = (psScalar*)psScalarAlloc(VALUE2,PS_TYPE_##TYPE);      \
+    psImage *out = (psImage*)psBinaryOp(NULL, in, #OP, psScalarCopy(inScalar));\
+    for (psS32 i = 0 ; i < NROWS ; i++) {                                      \
+        for (psS32 j = 0 ; j < NCOLS ; j++) {                                  \
+            ps##TYPE expect = in->data.TYPE[i][j] OP inScalar->data.TYPE;      \
+            if (fabs((psF32) (out->data.TYPE[i][j] - expect)) > 0.1) {         \
+                errorFlag = true;                                              \
+                if (VERBOSE) {                                                 \
+                    printf("TEST ERROR: outImage[%d][%d] is %f, should be %f\n", i, j, (psF32) out->data.TYPE[i][j], (psF32) expect); \
+                }                                                              \
+            }                                                                  \
+        }                                                                      \
+    }                                                                          \
+    psFree(inScalar);                                                          \
+    psFree(in);                                                                \
+    psFree(out);                                                               \
+    MEMORYFLAG = psMemCheckLeaks(id, NULL, NULL, false);                       \
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    bool errorFlag = false;
+    bool memoryFlag = false;
+    plan_tests(72);
+
+    //Test matrix-matrix binary operations
+    testBinaryOpMM(+,S32,10,20,5,4,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-matrix, +, S32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMM(+,F32,10.0,10.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-matrix, +, F32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMM(+,F64,10.0,10.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-matrix, +, F64)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMM(-,S32,20,10,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-matrix, -, S32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMM(-,F32,20.0,10.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-matrix, -, F32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMM(-,F64,20.0,10.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-matrix, -, F64)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMM(*,S32,20,10,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-matrix, *, S32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMM(*,F32,20.0,10.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-matrix, *, F32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMM(*,F64,20.0,10.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-matrix, *, F64)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMM(/,S32,20,10,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-matrix, /, S32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMM(/,F32,20.0,10.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-matrix, /, F32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMM(/,F64,20.0,10.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-matrix, /, F64)");
+    ok(memoryFlag== false, "no memory leaks");
+
+    // Test Matrix-Vector binary operations
+    testBinaryOpMV(+,S32,10,5,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-vector, +, S32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMV(+,F32,10.0,5.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-vector, +, F32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMV(+,F64,10.0,5.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-vector, +, F64)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMV(-,S32,20,5,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-vector, -, S32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMV(-,F32,20.0,5.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-vector, -, F32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMV(-,F64,20.0,5.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-vector, -, F32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMV(*,S32,20,5,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-vector, *, S32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMV(*,F32,20.0,5.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-vector, *, F32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMV(*,F64,20.0,5.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-vector, *, F64)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMV(/,S32,20,5,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-vector, /, S32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMV(/,F32,20.0,5.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-vector, /, F32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMV(/,F64,20.0,5.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-vector, /, F64)");
+    ok(memoryFlag== false, "no memory leaks");
+
+    // Test Matrix-Scalar binary operations
+    testBinaryOpMS(+,S32,10,5,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-scalar, +, S32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMS(+,F32,10.0,5.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-scalar, +, F32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMS(+,F64,10.0,5.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-scalar, +, F64)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMS(-,S32,20,5,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-scalar, -, S32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMS(-,F32,20.0,5.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-scalar, -, F32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMS(-,F64,20.0,5.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-scalar, -, F64)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMS(*,S32,20,5,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-scalar, *, S32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMS(*,F32,20.0,5.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-scalar, *, F32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMS(*,F64,20.0,5.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-scalar, *, F64)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMS(/,S32,20,5,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-scalar, /, S32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMS(/,F32,20.0,5.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-scalar, /, F32)");
+    ok(memoryFlag== false, "no memory leaks");
+    testBinaryOpMS(/,F64,20.0,5.0,3,2,errorFlag,memoryFlag);
+    ok(errorFlag== false, "psBinaryOp(): was successful: (matrix-scalar, /, F64)");
+    ok(memoryFlag== false, "no memory leaks");
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrixVectorArithmetic02.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrixVectorArithmetic02.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrixVectorArithmetic02.c	(revision 22158)
@@ -0,0 +1,446 @@
+
+/** @file  tst_psMatrixVectorArithmetic02.c
+ *
+ *  @brief Test driver for psMatrixVector arithmetic functions
+ *
+ *  This test driver tests combinations of matrix, vector, and scalar unary operations including:
+ *     Matrix with all math operators with S32, F32, F64
+ *     Vector with all math operators with S32, F32, F64
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2007-05-02 04:14:33 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define CHECK_VECTOR(VECTOR,TYPE,TRUTH,ERRORFLAG)                                                                      \
+{ \
+    for(psS32 i=0; i<VECTOR->n; i++) {                                                                             \
+        if(cabs(VECTOR->data.TYPE[i])-cabs(TRUTH) > FLT_EPSILON){                                                \
+            ERRORFLAG = true; \
+            diag("ERROR:Truth and calculated values don't match for vector operation:\n");                     \
+            if(PS_IS_PSELEMTYPE_COMPLEX(VECTOR->type.type)) {                                                    \
+                diag("Truth: %.2f%+.2fi\n", creal(VECTOR->data.TYPE[i]), cimag(VECTOR->data.TYPE[i]));         \
+                diag("Calculated: %.2f%+.2fi\n", creal(TRUTH), cimag(TRUTH));                                  \
+            } else if(PS_IS_PSELEMTYPE_INT(VECTOR->type.type)) {                                                 \
+                diag("Truth: %d\n", (psS32)(VECTOR->data.TYPE[i]));                                              \
+                diag("Calculated: %d\n", (psS32)(TRUTH));                                                        \
+            } else {                                                                                             \
+                diag("Truth: %.2f\n", (double)(VECTOR->data.TYPE[i]));                                         \
+                diag("Calculated: %.2f\n", (double)(TRUTH));                                                   \
+            }                                                                                                    \
+            diag("\n"); \
+        }                                                                                                        \
+    }                                                                                                            \
+}
+
+#define CHECK_MATRIX(IMAGE,TYPE,TRUTH,ERRORFLAG)                                                                       \
+{ \
+    for(psS32 i=IMAGE->numRows-1; i>-1; i--) {                                                                     \
+        for(psS32 j=0; j<IMAGE->numCols; j++) {                                                                    \
+            if(cabs(IMAGE->data.TYPE[i][j])-cabs(TRUTH) > FLT_EPSILON){                                          \
+                ERRORFLAG = true; \
+                diag("ERROR:Truth and calculated values don't match for matrix operation:\n");                 \
+                if(PS_IS_PSELEMTYPE_COMPLEX(IMAGE->type.type)) {                                                 \
+                    diag("Truth: %.2f%+.2fi\n", creal(IMAGE->data.TYPE[i][j]), cimag(IMAGE->data.TYPE[i][j])); \
+                    diag("Calculated: %.2f%+.2fi\n", creal(TRUTH), cimag(TRUTH));                              \
+                } else if(PS_IS_PSELEMTYPE_INT(IMAGE->type.type)) {                                              \
+                    diag("Truth: %d\n", (psS32)(IMAGE->data.TYPE[i][j]));                                        \
+                    diag("Calculated: %d\n", (psS32)(TRUTH));                                                    \
+                } else {                                                                                         \
+                    diag("Truth: %.2f\n", (double)(IMAGE->data.TYPE[i][j]));                                   \
+                    diag("Calculated: %.2f\n", (double)(TRUTH));                                               \
+                }                                                                                                \
+                diag("\n");                                                                                            \
+                diag("\n");                                                                                            \
+            }                                                                                                    \
+        }                                                                                                        \
+    }                                                                                                            \
+}
+
+#define CREATE_AND_SET_VECTOR(NAME,TYPE,VALUE,SIZE)                                                          \
+psVector *NAME = (psVector*)psVectorAlloc(SIZE, PS_TYPE_##TYPE);                                             \
+for(psS32 i=0; i<SIZE; i++) {                                                                                  \
+    NAME->data.TYPE[i] = VALUE;                                                                              \
+}                                                                                                            \
+NAME->n = SIZE;
+
+
+#define CREATE_AND_SET_IMAGE(NAME,TYPE,VALUE,NROWS,NCOLS)                                                    \
+psImage *NAME = (psImage*)psImageAlloc(NCOLS,NROWS,PS_TYPE_##TYPE);                                          \
+for(psS32 i=0; i<NAME->numRows; i++) {                                                                         \
+    for(psS32 j=0; j<NAME->numCols; j++) {                                                                     \
+        NAME->data.TYPE[i][j] = VALUE;                                                                       \
+    }                                                                                                        \
+}
+
+
+#define CHECK_MEMORY \
+if( psMemCheckLeaks(0, NULL, stdout, false) != 0 ) {  \
+    psError(PS_ERR_UNKNOWN, true,"Memory leaks detected."); \
+    return 50; \
+} \
+psS32 nBad = psMemCheckCorruption(0); \
+if(nBad) { \
+    psError(PS_ERR_UNKNOWN, true,"ERROR: Found %d bad memory blocks\n", nBad); \
+    return 51; \
+}
+
+// Test matrix unary operations
+#define testUnaryOpM(OP,TYPE,VALUE1,VALUE2,NROWS,NCOLS,TRUTH,ERRORFLAG,MEMORYFLAG) \
+{                                                                                  \
+    psMemId id = psMemGetId();                                                     \
+    ERRORFLAG = false;                                                             \
+    MEMORYFLAG = false;                                                            \
+    CREATE_AND_SET_IMAGE(inImage,TYPE,VALUE1,NROWS,NCOLS);                         \
+    CREATE_AND_SET_IMAGE(outImage,TYPE,VALUE2,NROWS,NCOLS);                        \
+    outImage = (psImage*)psUnaryOp(outImage, inImage, #OP);                        \
+    CHECK_MATRIX(outImage,TYPE,TRUTH,ERRORFLAG);                                   \
+    psFree(inImage);                                                               \
+    psFree(outImage);                                                              \
+    MEMORYFLAG = psMemCheckLeaks(id, NULL, NULL, false);                           \
+}
+
+// Test vector unary operations
+#define testUnaryOpV(OP,TYPE,VALUE1,VALUE2,SIZE,TRUTH,ERRORFLAG,MEMORYFLAG)        \
+{                                                                                  \
+    psMemId id = psMemGetId();                                                     \
+    ERRORFLAG = false;                                                             \
+    MEMORYFLAG = false;                                                            \
+    CREATE_AND_SET_VECTOR(inVector,TYPE,VALUE1,SIZE);                              \
+    CREATE_AND_SET_VECTOR(outVector,TYPE,VALUE2,SIZE);                             \
+    outVector = (psVector*)psUnaryOp(outVector, inVector, #OP);                    \
+    CHECK_VECTOR(outVector,TYPE,TRUTH,ERRORFLAG);                                  \
+    psFree(inVector);                                                              \
+    psFree(outVector);                                                             \
+    MEMORYFLAG = psMemCheckLeaks (id, NULL, NULL, false);                          \
+}
+
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    plan_tests(272);
+    bool errorFlag = false;
+    bool memoryFlag = false;
+
+    testUnaryOpM( abs, S32, -10, 0, 3, 2, 10, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): abs was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( abs, F32, -10.0, 0.0, 3, 2, 10.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): abs was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( abs, F64, -10.0, 0.0, 3, 2, 10.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): abs was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( exp, S32, 10, 0, 3, 2, exp(10), errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): exp was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( exp, F32, 10.0, 0.0, 3, 2, cexp(10.0), errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): exp was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( exp, F64, 10.0, 0.0, 3, 2, cexp(10.0), errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): exp was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( ln, S32, 10, 0, 3, 2, clog(10), errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): ln was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( ln, F32, 10.0, 0.0, 3, 2, clog(10.0), errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): ln was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( ln, F64, 10.0, 0.0, 3, 2, clog(10.0), errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): ln was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( ten, S32, 3, 0, 3, 2, 1000, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): ten was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( ten, F32, 3.0, 0.0, 3, 2, 1000, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): ten was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( ten, F64, 3.0, 0.0, 3, 2, 1000, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): ten was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( log, S32, 1000, 0, 3, 2, 3, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): log was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( log, F32, 1000.0, 0.0, 3, 2, 3, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): log was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( log, F64, 1000.0, 0.0, 3, 2, 3, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): log was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( sin, S32, M_PI_2, 0, 3, 2, 1, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): sin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( sin, F32, M_PI_2, 0.0, 3, 2, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): sin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( sin, F64, M_PI_2, 0.0, 3, 2, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): sin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( dsin, S32, 90, 0, 3, 2 , 1, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dsin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( dsin, F32, 90.0, 0.0, 3, 2, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dsin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( dsin, F64, 90.0, 0.0, 3, 2, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dsin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( cos, S32, 0, 0, 3, 2, 1, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): cos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( cos, F32, 0.0, 0.0, 3, 2, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): cos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( cos, F64, 0.0, 0.0, 3, 2, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): cos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( dcos, S32, 0, 0, 3, 2, 1, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dcos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( dcos, F32, 0.0, 0.0, 3, 2, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dcos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( dcos, F64, 0.0, 0.0, 3, 2, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dcos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( tan, S32, M_PI_4, 0, 3, 2, 1, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): tan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( tan, F32, M_PI_4, 0.0, 3, 2, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): tan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( tan, F64, M_PI_4, 0.0, 3, 2, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): tan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( dtan, S32, 45, 0, 3, 2, 1, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dtan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( dtan, F32, 45.0, 0.0, 3, 2, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dtan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( dtan, F64, 45.0, 0.0, 3, 2, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dtan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( asin, S32, 1, 0, 3, 2, M_PI_2, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): asin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( asin, F32, 1.0, 0.0, 3, 2, M_PI_2 , errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): asin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( asin, F64, 1.0, 0.0, 3, 2, M_PI_2, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): asin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( dasin, S32, 1.0, 0, 3, 2, 90, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dasin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( dasin, F32, 1.0, 0.0, 3, 2, 90.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dasin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( dasin, F64, 1.0, 0.0, 3, 2, 90.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dasin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( acos, S32, 0, 0, 3, 2, M_PI_2, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): acos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( acos, F32, 0.0, 0.0, 3, 2, M_PI_2, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): acos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( acos, F64, 0.0, 0.0, 3, 2, M_PI_2, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): acos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( dacos, S32, 0, 0, 3, 2, 90, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dacos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( dacos, F32, 0.0, 0.0, 3, 2, 90.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dacos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( dacos, F64, 0.0, 0.0, 3, 2, 90.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dacos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( atan, S32, 1, 0, 3, 2, M_PI_4, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): atan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( atan, F32, 1.0, 0.0, 3, 2, M_PI_4, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): atan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( atan, F64, 1.0, 0.0, 3, 2, M_PI_4, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): atan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( datan, S32, 1, 0, 3, 2, 45, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): datan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( datan, F32, 1.0, 0.0, 3, 2, 45.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): datan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpM( datan, F64, 1.0, 0.0, 3, 2, 45.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): datan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+
+    testUnaryOpV( abs, S32, -10, 0, 3, 10, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): abs was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( abs, F32, -10.0, 0.0, 3, 10.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): abs was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( abs, F64, -10.0, 0.0, 3, 10.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): abs was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( exp, S32, 10, 0, 3, cexp(10), errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): exp was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( exp, F32, 10.0, 0.0, 3, cexp(10.0), errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): exp was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( exp, F64, 10.0, 0.0, 3, cexp(10.0), errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): exp was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( ln, S32, 10, 0, 3, clog(10), errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): ln was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( ln, F32, 10.0, 0.0, 3, clog(10.0), errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): ln was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( ln, F64, 10.0, 0.0, 3, clog(10.0), errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): ln was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( ten, S32, 3, 0, 3, 1000, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): ten was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( ten, F32, 3.0, 0.0, 3, 1000, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): ten was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( ten, F64, 3.0, 0.0, 3, 1000, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): ten was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( log, S32, 1000, 0, 3,  3, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): log was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( log, F32, 1000.0, 0.0, 3, 3, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): log was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( log, F64, 1000.0, 0.0, 3, 3, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): log was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( sin, S32, M_PI_2, 0, 3, 1, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): sin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( sin, F32, M_PI_2, 0.0, 3, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): sin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( sin, F64, M_PI_2, 0.0, 3, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): sin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( dsin, S32, 90, 0, 3, 1, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dsin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( dsin, F32, 90.0, 0.0, 3, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dsin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( dsin, F64, 90.0, 0.0, 3, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dsin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( cos, S32, 0, 0, 3, 1, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): cos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( cos, F32, 0.0, 0.0, 3, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): cos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( cos, F64, 0.0, 0.0, 3, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): cos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( dcos, S32, 0, 0, 3, 1, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dcos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( dcos, F32, 0.0, 0.0, 3, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dcos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( dcos, F64, 0.0, 0.0, 3, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dcos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( tan, S32, M_PI_4, 0, 3, 1, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): tan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( tan, F32, M_PI_4, 0.0, 3, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): tan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( tan, F64, M_PI_4, 0.0, 3, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): tan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( dtan, S32, 45, 0, 3, 1, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dtan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( dtan, F32, 45.0, 0.0, 3, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dtan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( dtan, F64, 45.0, 0.0, 3, 1.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dtan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( asin, S32, 1, 0, 3, M_PI_2, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): asin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( asin, F32, 1.0, 0.0, 3, M_PI_2 , errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): asin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( asin, F64, 1.0, 0.0, 3, M_PI_2, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): asin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( dasin, S32, 1.0, 0, 3, 90, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dasin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( dasin, F32, 1.0, 0.0, 3, 90.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dasin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( dasin, F64, 1.0, 0.0, 3, 90.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dasin was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( acos, S32, 0, 0, 3, M_PI_2, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): acos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( acos, F32, 0.0, 0.0, 3, M_PI_2, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): acos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( acos, F64, 0.0, 0.0, 3, M_PI_2, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): acos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( dacos, S32, 0, 0, 3, 90, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dacos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( dacos, F32, 0.0, 0.0, 3, 90.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dacos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( dacos, F64, 0.0, 0.0, 3, 90.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): dacos was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( atan, S32, 1, 0, 3, M_PI_4, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): atan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( atan, F32, 1.0, 0.0, 3, M_PI_4, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): atan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( atan, F64, 1.0, 0.0, 3, M_PI_4, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): atan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( datan, S32, 1, 0, 3, 45, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): datan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( datan, F32, 1.0, 0.0, 3, 45.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): datan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+    testUnaryOpV( datan, F64, 1.0, 0.0, 3, 45.0, errorFlag, memoryFlag);
+    ok(errorFlag== false, "psUnaryOp(): datan was successful");
+    ok(memoryFlag== false, "no memory leaks");
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrixVectorArithmetic03.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrixVectorArithmetic03.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrixVectorArithmetic03.c	(revision 22158)
@@ -0,0 +1,255 @@
+/** @file  tst_psMatrixVectorArithmetic03.c
+ *
+ *  @brief Test driver for psMatrixVector arithmetic functions
+ *
+ *  This test driver contains negative tests for psBinaryOp and psUanryOp:
+ *     Check for NULL arguments
+ *     Inconsistent element types
+ *     Inconsistent element count
+ *     Inconsistent dimensionality
+ *     Division by zero
+ *     Invalid operation
+ *
+ * XXX: Many of these tests are desinged to produce an error.  They are commented out.
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2007-05-02 04:14:33 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define CREATE_AND_SET_VECTOR(NAME,TYPE,VALUE,SIZE) \
+psVector *NAME = (psVector*)psVectorAlloc(SIZE, PS_TYPE_##TYPE); \
+for(psS32 i=0; i<SIZE; i++) { \
+    NAME->data.TYPE[i] = VALUE; \
+} \
+NAME->n = SIZE;
+
+
+#define CREATE_AND_SET_IMAGE(NAME,TYPE,VALUE,NROWS,NCOLS) \
+psImage *NAME = (psImage*)psImageAlloc(NCOLS,NROWS,PS_TYPE_##TYPE); \
+for(psS32 i=0; i<NAME->numRows; i++) { \
+    for(psS32 j=0; j<NAME->numCols; j++) { \
+        NAME->data.TYPE[i][j] = VALUE; \
+    } \
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    plan_tests(5);
+    psMemId idGlobal = psMemGetId();
+
+    CREATE_AND_SET_IMAGE(image1,F64,0,3,3);
+    CREATE_AND_SET_IMAGE(image2,F64,0,3,3);
+    CREATE_AND_SET_IMAGE(image3,F32,0,3,3);
+    CREATE_AND_SET_IMAGE(image4,F64,0,2,2);
+    CREATE_AND_SET_VECTOR(vector1,F64,0,2);
+    CREATE_AND_SET_VECTOR(vector2,F64,0,3);
+
+    // Check for NULL output argument
+    {
+        psMemId id = psMemGetId();
+        psImage* image6 = (psImage*)psBinaryOp(NULL, image1, "+", image2);
+        ok(image6 != NULL, "psBinaryOp() produced a non-NULL image given no output to recycle.");
+        psFree(image6);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Check for NULL input argument #1
+
+    if (1) {
+        psMemId id = psMemGetId();
+        psImage* image6 = (psImage*)psBinaryOp(image6, NULL, "+", image2);
+        ok(image6 == NULL, "psBinaryOp() returned a NULL result given a NULL first operand.");
+        psFree(image6);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Check for NULL input argument #2
+    // Following should generate an error message
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage* image6 = (psImage*)psBinaryOp(image6, image1, "+", NULL);
+        ok(image6 == NULL, "psBinaryOp() returned a NULL given a NULL second operand.");
+        psFree(image6);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Check for NULL operand
+    // Following should generate an error message
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage* image6 = (psImage*)psBinaryOp(image6, image1, NULL, image2);
+        ok(image6 == NULL, "psBinaryOp returned a NULL given a NULL operator.");
+        psFree(image6);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Check for null output
+    {
+        psMemId id = psMemGetId();
+        psImage* image6 = (psImage*)psUnaryOp(NULL, image1, "sin");
+        ok(image6 != NULL, "psUnaryOp produced an image given no output to recycle.");
+        psFree(image6);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Check for NULL input arg
+    // Following should generate an error message
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage* image6 = (psImage*)psUnaryOp(image6, NULL, "sin");
+        ok(image6 == NULL, "psUnaryOp returned a NULL given a NULL operand.");
+        psFree(image6);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Check for NULL operand
+    // Following should generate an error message
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage* image6 = (psImage*)psUnaryOp(image6, image1, NULL);
+        ok(image6 == NULL, "psUnaryOp returned a NULL operand.");
+        psFree(image6);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Inconsistent element types
+    // Following should generate an error message
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage* image6 = (psImage*)psBinaryOp(image6, image3, "+", image2);
+        ok(image6 == NULL, "psBinaryOp returned a NULL given operands of different types");
+        psFree(image6);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Check unary op to convert to correct type
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage* image6 = psImageCopy(image6,image2,PS_TYPE_F64);
+        image6 = (psImage*)psUnaryOp(image6, image3, "sin");
+        ok(!(image6 == NULL || image6->type.type != PS_TYPE_F32),
+           "psUnaryOp converted the type of the output.");
+        psFree(image6);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Inconsistent element count
+    // Following should generate an error message
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage* image6 = (psImage*)psBinaryOp(image6, image4, "+", image2);
+        ok(image6 == NULL, "psBinaryOp returned a NULL given operands of different sizes.");
+        psFree(image6);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Inconsistent element in input and output
+    // XXX: This fails, but should work.
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage* image6 = psImageCopy(image6,image2,PS_TYPE_F64);
+        image6 = (psImage*)psUnaryOp(image6, image4, "sin");
+        ok(!(image6 == NULL ||
+             image6->numCols != image6->numCols ||
+             image6->numRows != image6->numRows),"psUnaryOp resized the output.");
+        psFree(image6);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Inconsistent size of input 1 and input 2
+    // Following should generate an error message
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage* image6 = (psImage*)psBinaryOp(image6, vector1, "+", image2);
+        ok(image6 == NULL, "psBinaryOp returned a NULL given operands of different sizes.");
+        psFree(image6);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Inconsistent size of input 1 and input 2
+    // Following should generate an error message
+    if (0) {
+        psMemId id = psMemGetId();
+        vector1->type.dimen = PS_DIMEN_TRANSV;
+        psImage* image6 = (psImage*)psBinaryOp(image6, vector1, "+", image2);
+        ok(image6 == NULL, "psBinaryOp returned a NULL given operands of different sizes.");
+        psFree(image6);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Inconsistent dimensionality
+    // Following should generate an two error messages
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage* image6 = psImageCopy(image6,image2,PS_TYPE_F64);
+        image6 = (psImage*)psUnaryOp(image6, vector2, "sin");
+        ok(image6 == NULL, "psUnaryOp returned NULL given wrong type out parameter.");
+        psFree(image6);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Invalid operation
+    // Following should generate an error messgae
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage* image6 = (psImage*)psBinaryOp(image6, image1, "yarg", image2);
+        ok(image6 == NULL, "psBinaryOp returned NULL with invalid operator");
+        psFree(image6);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Following should generate an error message
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage* image6 = (psImage*)psUnaryOp(image6, image1, "yarg");
+        ok(image6 == NULL, "psUnaryOp returned NULL with invalid operator");
+        psFree(image6);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    CREATE_AND_SET_VECTOR(vector4,F64,0,3);
+    CREATE_AND_SET_VECTOR(vector5,F64,0,3);
+
+    // Input parameter with dimension of PS_DIMEN_OTHER
+    // Following should generate an error message
+    if (0) {
+        psMemId id = psMemGetId();
+        vector4->type.dimen = PS_DIMEN_OTHER;
+        ok(psBinaryOp(NULL,vector4,"+",vector5) == NULL, "psBinaryOp should return null when input dimen PS_DIMEN_OTHER.");
+        vector4->type.dimen = PS_DIMEN_VECTOR;
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Input parameter with dimension of PS_DIMEN_OTHER
+    // Following should generate an error message
+    if (0) {
+        psMemId id = psMemGetId();
+        vector4->type.dimen = PS_DIMEN_OTHER;
+        ok(psUnaryOp(NULL,vector4,"sin") == NULL, "psUnaryOp should return null when input dimen PS_DIMEN_OTHER");
+        vector4->type.dimen = PS_DIMEN_VECTOR;
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    psFree(vector4);
+    psFree(vector5);
+    psFree(image1);
+    psFree(image2);
+    psFree(image3);
+    psFree(image4);
+    psFree(vector1);
+    psFree(vector2);
+    ok(!psMemCheckLeaks (idGlobal, NULL, NULL, false), "no memory leaks");
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrixVectorArithmetic04.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrixVectorArithmetic04.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMatrixVectorArithmetic04.c	(revision 22158)
@@ -0,0 +1,234 @@
+/** @file  tst_psMatrixVectorArithmetic04.c
+ *
+ *  @brief Test driver for psBinary arithmetic operations with scalars
+ *
+ *  This test driver will test the following binary operation with scalar inputs
+ *        vector addition with scalar in first argument
+ *        image addition with scalar in second argument
+ *
+ * XXX: The scalar functions at the end are producing memory corruption errors
+ * when they shouldn't.
+ *
+ * @author  Eric Van Alst, MHPCC
+ *
+ * @version $Revision: 1.1 $  $Name: not supported by cvs2svn $
+ * @date  $Date: 2007-01-06 00:48:54 $
+ *
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+
+// Create vector
+#define CREATE_AND_SET_VECTOR(NAME,TYPE,VALUE,SIZE) \
+psVector *NAME = psVectorAlloc(SIZE,PS_TYPE_##TYPE); \
+for(psS32 i=0; i<SIZE; i++) { \
+    NAME->data.TYPE[i] = VALUE; \
+} \
+NAME->n = SIZE;
+
+// Create image
+#define CREATE_AND_SET_IMAGE(NAME,TYPE,VALUE,NROWS,NCOLS) \
+psImage *NAME = psImageAlloc(NCOLS,NROWS,PS_TYPE_##TYPE); \
+for(psS32 i=0; i<NAME->numRows; i++) { \
+    for(psS32 j=0; j<NAME->numCols; j++) { \
+        NAME->data.TYPE[i][j] = VALUE; \
+    } \
+}
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    plan_tests(12);
+
+    // testBinOpScalarFirst(void)
+    {
+        psMemId id = psMemGetId();
+        bool psErrorFlag = false;
+        CREATE_AND_SET_VECTOR(vector1,S8,1,5)
+        CREATE_AND_SET_VECTOR(vector2,S8,0,5)
+        psScalar* inScalar1 = psScalarAlloc(2,PS_TYPE_S8);
+
+        // Add vector and scalar
+        vector2 = (psVector*)psBinaryOp(vector2,inScalar1,"+",vector1);
+        // Verify the result vector
+        for(psS32 i=0; i<vector2->n; i++)
+        {
+            if(vector2->data.S8[i] != 3 ) {
+                psErrorFlag = true;
+                diag("Unexpected value in return vector[%d]",i);
+            }
+        }
+        ok(!psErrorFlag, "psBinaryOp() produced the correct vector");
+        psFree(vector1);
+        psFree(vector2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        bool psErrorFlag = false;
+        CREATE_AND_SET_VECTOR(vector3,S8,1,5);
+        CREATE_AND_SET_VECTOR(vector4,S8,0,3);
+
+        psScalar* inScalar2 = psScalarAlloc(2,PS_TYPE_S8);
+        vector4->type.dimen = PS_DIMEN_TRANSV;
+        vector4 = (psVector*)psBinaryOp(vector4,inScalar2,"+",vector3);
+        for(psS32 i=0; i<vector4->n; i++)
+        {
+            if(vector4->data.S8[i] != 3 ) {
+                psErrorFlag = true;
+                diag("Unexpected value in return vector[%d]",i);
+            }
+        }
+        ok(!psErrorFlag, "psBinaryOp() produced the correct vector");
+        psFree(vector3);
+        psFree(vector4);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        bool psErrorFlag = false;
+        CREATE_AND_SET_IMAGE(image1,S8,1,5,5)
+        psImage* image2 = NULL;
+        psScalar* inScalar3 = psScalarAlloc(2,PS_TYPE_S8);
+
+        image2 = (psImage*)psBinaryOp(image2,inScalar3,"+",image1);
+        for(psS32 i=0; i<image2->numRows; i++)
+        {
+            for(psS32 j=0; j<image2->numCols; j++) {
+                if(image2->data.S8[i][j] != 3 ) {
+                    psErrorFlag = true;
+                    diag("Unexpected value in return image[%d][%d]",i,j);
+                }
+            }
+        }
+        ok(!psErrorFlag, "psBinaryOp() produced the correct matrix");
+        psFree(image1);
+        psFree(image2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        bool psErrorFlag = false;
+        CREATE_AND_SET_VECTOR(vector1,S8,1,5)
+        CREATE_AND_SET_VECTOR(vector2,S8,0,5)
+        psScalar* inScalar1 = psScalarAlloc(2,PS_TYPE_S8);
+
+        vector2 = (psVector*)psBinaryOp(vector2,vector1,"+",inScalar1);
+        for(psS32 i=0; i<vector2->n; i++)
+        {
+            if(vector2->data.S8[i] != 3 ) {
+                psErrorFlag = true;
+                diag("Unexpected value in return vector[%d]",i);
+            }
+        }
+        ok(!psErrorFlag, "psBinaryOp() produced the correct vector");
+        psFree(vector1);
+        psFree(vector2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        bool psErrorFlag = false;
+        CREATE_AND_SET_VECTOR(vector3,S8,1,5);
+        CREATE_AND_SET_VECTOR(vector4,S8,0,3);
+        psScalar* inScalar2 = psScalarAlloc(2,PS_TYPE_S8);
+
+        vector4->type.dimen = PS_DIMEN_TRANSV;
+        vector4 = (psVector*)psBinaryOp(vector4,vector3,"+",inScalar2);
+        for(psS32 i=0; i<vector4->n; i++)
+        {
+            if(vector4->data.S8[i] != 3 ) {
+                psErrorFlag = true;
+                diag("Unexpected value in return vector[%d]",i);
+            }
+        }
+        ok(!psErrorFlag, "psBinaryOp() produced the correct vector");
+        psFree(vector3);
+        psFree(vector4);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    if (1) {
+        psMemId id = psMemGetId();
+        bool psErrorFlag = false;
+        CREATE_AND_SET_IMAGE(image1,S8,1,5,5);
+        psImage* image2 = NULL;
+        psScalar* inScalar3 = psScalarAlloc(2,PS_TYPE_S8);
+
+        image2 = (psImage*)psBinaryOp(image2,image1,"+",inScalar3);
+        for(psS32 i=0; i<image2->numRows; i++) {
+            for(psS32 j=0; j<image2->numCols; j++) {
+                if(image2->data.S8[i][j] != 3 ) {
+                    psErrorFlag = true;
+                    diag("Unexpected value in return image[%d][%d]",i,j);
+                }
+            }
+        }
+        ok(!psErrorFlag, "psBinaryOp() produced the correct matrix");
+        psFree(image1);
+        psFree(image2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testBinOpScalarBoth
+    // This test fails.  It shouldn't.
+    if (0) {
+        psMemId id = psMemGetId();
+        psScalar* inScalar1 = psScalarAlloc(1,PS_TYPE_S8);
+        psScalar* inScalar2 = psScalarAlloc(2,PS_TYPE_S8);
+        psScalar* outScalar = psScalarAlloc(4,PS_TYPE_S8);
+
+        outScalar = (psScalar*)psBinaryOp(outScalar,inScalar1,"+",inScalar2);
+        ok(outScalar->data.S8 == 3, "psBinaryOp() produced the correct result");
+        psFree(outScalar);
+        psFree(inScalar1);
+        psFree(inScalar2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // This test fails.  It shouldn't.
+    if (0) {
+        psMemId id = psMemGetId();
+        psScalar* inScalar3 = psScalarAlloc(10,PS_TYPE_S8);
+        psScalar* inScalar4 = psScalarAlloc(20,PS_TYPE_S8);
+        psScalar* outScalar1 = NULL;
+
+        outScalar1 = (psScalar*)psBinaryOp(outScalar1,inScalar3,"+",inScalar4);
+        ok(outScalar1->data.S8 == 30, "psBinaryOp() produced the correct result");
+        psFree(outScalar1);
+        psFree(inScalar3);
+        psFree(inScalar4);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // This test fails.  It shouldn't.
+    // testUnaryOpScalar
+    if (0) {
+        psMemId id = psMemGetId();
+        psScalar* inScalar = psScalarAlloc(-1,PS_TYPE_F32);
+        psScalar* outScalar = NULL;
+
+        outScalar = (psScalar*)psUnaryOp(outScalar,inScalar,"abs");
+        ok(outScalar->data.F32 == 1, "psUnaryOp() produced the correct result");
+        psFree(outScalar);
+        psFree(inScalar);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMinimizeLMM.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMinimizeLMM.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMinimizeLMM.c	(revision 22158)
@@ -0,0 +1,274 @@
+/*****************************************************************************
+    This routine must ensure that psMinimizeLM() works correctly.
+ 
+    XXX: This code needs a lot of additional test case work.  The minimization
+	 currently fails and we don't attempt to check the output values.
+    XXX: Add tests for
+	covar arg set to non-NULL
+	constraint set to non-NULL
+        Set x->vectors to NULL, or use wrong types
+        yWt (errors) vector set to incorrect size, type.
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define NUM_ITERATIONS 100
+#define ERR_TOL 1e-6
+#define NUM_DATA_POINTS 300
+#define NUM_PARAMS 3
+#define VERBOSE 0
+float expectedParm[NUM_PARAMS];
+
+// y = p2 + p0 * e^( x0^2 + x1^2 / (2 * p1^2) )
+float function(const psVector *params, const psVector *x)
+{
+    return params->data.F32[0] *
+           expf(- (PS_SQR(x->data.F32[0]) + PS_SQR(x->data.F32[1]) / 2.0 / PS_SQR(params->data.F32[1]))) +
+           params->data.F32[2];
+}
+
+void derivatives(psVector *deriv, const psVector *params, const psVector *x)
+{
+    deriv->data.F32[0] = expf(- (PS_SQR(x->data.F32[0]) + PS_SQR(x->data.F32[1]) / 2.0 / PS_SQR(params->data.F32[1])));
+    deriv->data.F32[1] = params->data.F32[0] * (PS_SQR(x->data.F32[0]) + PS_SQR(x->data.F32[1]) / 2.0 / PS_SQR(params->data.F32[1])) / params->data.F32[1] / params->data.F32[1] / params->data.F32[1] * expf(- (PS_SQR(x->data.F32[0]) + PS_SQR(x->data.F32[1]) / 2.0 / PS_SQR(params->data.F32[1])));
+    deriv->data.F32[2] = 1.0;
+}
+
+
+psF32 fitFunc(psVector *deriv,
+              psVector *params,
+              psVector *x)
+{
+    if ((deriv == NULL) || (params == NULL) || (x == NULL)) {
+        psError(PS_ERR_UNKNOWN, true, "deriv or params or x is NULL.\n");
+    }
+
+    derivatives(deriv, params, x);
+    return function(params, x);
+}
+
+
+#define NUM_ITER 10
+#define TOL  20.0
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(34);
+
+
+    // Test psMinimizationAlloc()
+    {
+        psMemId id = psMemGetId();
+        psMinimization *tmp = psMinimizationAlloc(NUM_ITER, TOL);
+        ok(tmp != NULL, "psMinimizationAlloc() returned non-NULL");
+        skip_start(tmp == NULL, 5, "Skipping tests because psMinimizationAlloc() failed");
+        ok(tmp->maxIter == NUM_ITER, "psMinimizationAlloc() properly set ->maxIter");
+        ok(tmp->tol == TOL, "psMinimizationAlloc() properly set ->tol");
+        ok(tmp->value == 0.0, "psMinimizationAlloc() properly set ->value");
+        ok(tmp->iter == 0, "psMinimizationAlloc() properly set ->iter (%d)", tmp->iter);
+        ok(isnan(tmp->lastDelta), "psMinimizationAlloc() properly set ->lastDelta (%f)", tmp->lastDelta);
+        skip_end();
+        psFree(tmp);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psMinConstraintAlloc()
+    {
+        psMemId id = psMemGetId();
+        psMinConstraint *tmp = psMinConstraintAlloc();
+        ok(tmp != NULL, "psMinConstraintAlloc() returned non-NULL");
+        skip_start(tmp == NULL, 2, "Skipping tests because psMinConstraintAlloc() failed");
+        ok(tmp->paramMask == NULL, "psMinConstraintAlloc() properly set ->paramMask");
+        ok(tmp->checkLimits == NULL, "psMinConstraintAlloc() properly set ->checkLimits");
+        psFree(tmp);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psMinimizeLMChi2(): unallowed input parameters.
+    {
+        psMemId id = psMemGetId();
+        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 1); // Random number generator; using known seed
+        psMinimization *min = psMinimizationAlloc(NUM_ITERATIONS, ERR_TOL);
+        psArray *ordinates = psArrayAlloc(NUM_DATA_POINTS);
+        psVector *coordinates = psVectorAlloc(NUM_DATA_POINTS, PS_TYPE_F32);
+        psVector *coordinatesF64 = psVectorAlloc(NUM_DATA_POINTS, PS_TYPE_F64);
+        psVector *errors = psVectorAlloc(NUM_DATA_POINTS, PS_TYPE_F32);
+        psVector *params = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+        psVector *paramsF64 = psVectorAlloc(NUM_PARAMS, PS_TYPE_F64);
+        psVector *trueParams = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+
+        // Test with psMinimization set to NULL
+        {
+            psMemId id = psMemGetId();
+            bool tmpBool = psMinimizeLMChi2(NULL, NULL, params, NULL, ordinates,
+                           coordinates, errors, (psMinimizeLMChi2Func)fitFunc);
+            ok(!tmpBool, "psMinimizeLMChi2() returned FALSE with NULL psMinimization");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Test with params set to NULL
+        {
+            psMemId id = psMemGetId();
+            bool tmpBool = psMinimizeLMChi2(min, NULL, NULL, NULL, ordinates,
+                           coordinates, errors, (psMinimizeLMChi2Func)fitFunc);
+            ok(!tmpBool, "psMinimizeLMChi2() returned FALSE with NULL params");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Test with params wrong type
+        {
+            psMemId id = psMemGetId();
+            bool tmpBool = psMinimizeLMChi2(min, NULL, paramsF64, NULL, ordinates,
+                           coordinates, errors, (psMinimizeLMChi2Func)fitFunc);
+            ok(!tmpBool, "psMinimizeLMChi2() returned FALSE with NULL params");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Test with ordinates (x) set to NULL
+        {
+            psMemId id = psMemGetId();
+            bool tmpBool = psMinimizeLMChi2(min, NULL, params, NULL, NULL,
+                           coordinates, errors, (psMinimizeLMChi2Func)fitFunc);
+            ok(!tmpBool, "psMinimizeLMChi2() returned FALSE with NULL ordinates (x)");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Test with coordinates (y) set to NULL
+        {
+            psMemId id = psMemGetId();
+            bool tmpBool = psMinimizeLMChi2(min, NULL, params, NULL, ordinates,
+                           NULL, errors, (psMinimizeLMChi2Func)fitFunc);
+            ok(!tmpBool, "psMinimizeLMChi2() returned FALSE with NULL coordinates (y)");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Test with coordinates (y) wrong type (F64)
+        {
+            psMemId id = psMemGetId();
+            bool tmpBool = psMinimizeLMChi2(min, NULL, params, NULL, ordinates,
+                           coordinatesF64, errors, (psMinimizeLMChi2Func)fitFunc);
+            ok(!tmpBool, "psMinimizeLMChi2() returned FALSE with coordinates (y) wrong type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Test with ordinates and coordinates wrong size
+        {
+            psMemId id = psMemGetId();
+            coordinates->n--;
+            bool tmpBool = psMinimizeLMChi2(min, NULL, params, NULL, ordinates,
+                           coordinates, errors, (psMinimizeLMChi2Func)fitFunc);
+            ok(!tmpBool, "psMinimizeLMChi2() returned FALSE with NULL psMinimization");
+            coordinates->n++;
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Test with function set to NULL
+        {
+            psMemId id = psMemGetId();
+            bool tmpBool = psMinimizeLMChi2(min, NULL, params, NULL, ordinates,
+                           coordinates, errors, NULL);
+            ok(!tmpBool, "psMinimizeLMChi2() returned FALSE with NULL fit function");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+        psFree(min);
+        psFree(params);
+        psFree(paramsF64);
+        psFree(trueParams);
+        psFree(ordinates);
+        psFree(coordinates);
+        psFree(coordinatesF64);
+        psFree(errors);
+        psFree(rng);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psMinimizeLMChi2() with legitimate input values
+    // Currently this fails, and we do not attempt to verify output
+    {
+        psMemId id = psMemGetId();
+        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 1); // Random number generator; using known seed
+        psMinimization *min = psMinimizationAlloc(NUM_ITERATIONS, ERR_TOL);
+        psArray *ordinates = psArrayAlloc(NUM_DATA_POINTS);
+        psVector *coordinates = psVectorAlloc(NUM_DATA_POINTS, PS_TYPE_F32);
+        psVector *errors = psVectorAlloc(NUM_DATA_POINTS, PS_TYPE_F32);
+        psVector *params = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+        psVector *trueParams = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+        bool tmpBool;
+        trueParams->data.F32[0] = 100.0;    // Normalisation
+        trueParams->data.F32[1] = 3.0;      // Width
+        trueParams->data.F32[2] = 10.0;     // Background
+
+        // Set parameters
+        for (long i = 0; i < NUM_PARAMS; i++)
+        {
+            // Ensure we're not starting right on the true value:
+            params->data.F32[i] = trueParams->data.F32[i] *
+                                  (1.0 - psRandomGaussian(rng) / 10.0);
+        }
+
+        for (long i = 0; i < NUM_DATA_POINTS; i++)
+        {
+            psVector *x = psVectorAlloc(2, PS_TYPE_F32);
+            x->data.F32[0] = 10.0 * psRandomUniform(rng) - 5.0;
+            x->data.F32[1] = 10.0 * psRandomUniform(rng) - 5.0;
+            ordinates->data[i] = x;
+            // Add some noise
+            coordinates->data.F32[i] = function(params, x) + 0.1 * (2.0 * psRandomGaussian(rng) - 1.0);
+            errors->data.F32[i] = 0.1;
+            if (VERBOSE) {
+                printf("Data %ld: (%f, %f) --> %f\n",
+                       i, x->data.F32[0], x->data.F32[1], coordinates->data.F32[i]);
+            }
+        }
+
+        tmpBool = psMinimizeLMChi2(min, NULL, params, NULL, ordinates, coordinates, errors,
+                                   (psMinimizeLMChi2Func)fitFunc);
+        ok(tmpBool, "psMinimizeLMChi2() suceeded");
+        skip_start(!tmpBool, 4, "Skipping tests because psMinimizeLMChi2() failed");
+
+        printf("Minimisation took %d iterations\n", min->iter);
+        printf("chi^2 at the minimum is %.3g\n", min->value);
+        for (long i = 0; i < NUM_PARAMS; i++)
+        {
+            printf("Parameter %ld at the minimum is %.3f, expected: %f\n", i,
+                   params->data.F32[i], trueParams->data.F32[i]);
+        }
+        float diff = 0.0;
+        for (long i = 0; i < NUM_DATA_POINTS; i++)
+        {
+            psVector *x = ordinates->data[i];
+            float fitted = function(trueParams, x);
+            float expected = function(params, x);
+            diff += (fitted - expected) / fabsf(expected);
+            if (VERBOSE) {
+                printf("Data point %ld: Fitted: %f, expected: %f\n", i, fitted, expected);
+            }
+        }
+        printf("Mean relative difference is %f\n", diff/(float)NUM_DATA_POINTS);
+        skip_end();
+        psFree(min);
+        psFree(params);
+        psFree(trueParams);
+        psFree(ordinates);
+        psFree(coordinates);
+        psFree(errors);
+        psFree(rng);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMinimizePowell.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMinimizePowell.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psMinimizePowell.c	(revision 22158)
@@ -0,0 +1,186 @@
+/*****************************************************************************
+    This routine must ensure that psMinimizePowell() works correctly.
+ 
+    XXX: This needs extensive work
+    XXX: We test with a NULL and non-NULL paramMask, however, the mask
+         has all zero values.
+    XXX: The tests that should generate errors are if'ed out.
+    XXX: psMinimizeChi2Powell() is untested.
+    XXX: Also, the test currently fails because of memory corruption in
+         psMinimizePowell().
+    XXX: The unallowed input parameter tests could be more extensive
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define N 5
+#define MIN_VALUE 20.0
+#define NUM_PARAMS 10
+#define ERROR_TOLERANCE 0.10
+float expectedParm[NUM_PARAMS];
+psS32 testStatus = true;
+
+/*****************************************************************************
+myFunc(): This routine subtracts the associate value in expectedParm[] from
+each parameter and then squares it, then sums that for all parameters, then
+adds MIN_VALUE to it.  The minimum for this function will be MIN_VALUE, and
+will occur when each parameter equals the associated value in expectedParm[].
+ 
+This procedure ignores the coordinates, other than to ensure that they were
+passed correctly from psMinimizePowell().
+ *****************************************************************************/
+float myFunc(psVector *myParams,
+             psArray *myCoords)
+{
+    float sum = 0.0;
+    float coordData = 0.0;
+    float expData = 0.0;
+    psS32 i;
+
+    //
+    // Simply ensure that the coordinate data was passed correctly.
+    //
+    for (i=0;i<N;i++) {
+        coordData = ((psVector *) (myCoords->data[i]))->data.F32[0];
+        expData = (float) (i+10);
+        if (fabs(coordData - expData) > FLT_EPSILON) {
+            printf("ERROR(1): coordinate data was incorrectly passed to myFunc()\n");
+            printf("ERROR(1): was (%f) should be (%f)\n", coordData, expData);
+            testStatus = false;
+        }
+        coordData = ((psVector *) (myCoords->data[i]))->data.F32[1];
+        expData = (float) (i+3);
+        if (fabs(coordData - expData) > FLT_EPSILON) {
+            printf("ERROR(2): coordinate data was incorrectly passed to myFunc()\n");
+            printf("ERROR(2): was (%f) should be (%f)\n", coordData, expData);
+            testStatus = false;
+        }
+    }
+
+
+    sum = 0.0;
+    for (i=0;i<NUM_PARAMS;i++) {
+        sum+= (myParams->data.F32[i] - expectedParm[i]) * (myParams->data.F32[i] - expectedParm[i]);
+    }
+    sum = MIN_VALUE + (sum * sum);
+
+    return(sum);
+}
+
+
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    plan_tests(8);
+
+    // Check for various errors on unallowed input parameters
+    {
+        psVector *myParams = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+        psVector *myParamMask = psVectorAlloc(NUM_PARAMS, PS_TYPE_U8);
+        psMinimization *min = psMinimizationAlloc(100, 0.01);
+        psArray *myCoords = psArrayAlloc(N);
+
+        // Following should generate error for NULL minimize
+        {
+            psMemId id = psMemGetId();
+            bool tmpBool = psMinimizePowell(NULL, myParams, myParamMask, myCoords,
+                                           (psMinimizePowellFunc) myFunc);
+            ok(!tmpBool, "psMinimizePowell() returned FALSE with NULL psMinimize param");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Following should generate error for NULL parameter vector
+        {
+            psMemId id = psMemGetId();
+            bool tmpBool = psMinimizePowell(min, NULL, myParamMask, myCoords,(psMinimizePowellFunc) myFunc);
+            ok(!tmpBool, "psMinimizePowell() returned FALSE with NULL parameter param");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Following should generate error for NULL coords
+        {
+            psMemId id = psMemGetId();
+            bool tmpBool = psMinimizePowell(min, myParams, myParamMask, NULL, (psMinimizePowellFunc) myFunc);
+            ok(!tmpBool, "psMinimizePowell() returned FALSE with NULL coords param");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Following should generate error for NULL function
+        {
+            psMemId id = psMemGetId();
+            bool tmpBool = psMinimizePowell(min, myParams, myParamMask, myCoords, NULL);
+            ok(!tmpBool, "psMinimizePowell() returned FALSE with NULL function param");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+        psFree(myParams);
+        psFree(myParamMask);
+        psFree(min);
+        psFree(myCoords);
+    }
+
+
+    // Powell minimize with parameter mask
+    // XXX: This function aborts with a memory corruption error at around line
+    // 60 of psMinimizePowell.c, at the psFree(v):
+    //    if (fabs(baseFuncVal - currFuncVal) <= min->tol) {
+    //        psFree(v);
+    //        psFree(pQP);
+    if (0) {
+        psMemId id = psMemGetId();
+        psVector *myParams = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+        psMinimization *min = psMinimizationAlloc(100, 0.01);
+        psArray *myCoords = psArrayAlloc(N);
+        psVector *myParamMask = psVectorAlloc(NUM_PARAMS, PS_TYPE_U8);
+
+        for (psS32 i=0;i<N;i++)
+        {
+            myCoords->data[i] = (psPtr *) psVectorAlloc(2, PS_TYPE_F32);
+            ((psVector *) (myCoords->data[i]))->data.F32[0] = (float) (i+10);
+            ((psVector *) (myCoords->data[i]))->data.F32[1] = (float) (i+3);
+        }
+        for (psS32 i=0;i<NUM_PARAMS;i++)
+        {
+            expectedParm[i] = 2.32 + (float) (2 * i);
+            myParams->data.F32[i] = 0.0;
+            myParams->data.F32[i] = (float) i;
+            myParamMask->data.U8[i] = 0;
+        }
+
+        bool tmpBool = psMinimizePowell(min, myParams, NULL, myCoords,
+                                        (psMinimizePowellFunc) myFunc);
+        ok(tmpBool, "psMinimizePowell() returned sucessfully");
+        skip_start(!tmpBool, 0, "Skipping tests because psMinimizePowell() failed");
+
+        printf("\nThe minimum is %f (expected: %f)\n", min->value, MIN_VALUE);
+        for (psS32 i=0;i<NUM_PARAMS;i++)
+        {
+            printf("Parameter %d at the minimum is %.1f (expected: %.1f)\n", i,
+                   myParams->data.F32[i], expectedParm[i]);
+
+            if (fabs(myParams->data.F32[i] - expectedParm[i]) > fabs(ERROR_TOLERANCE * expectedParm[i])) {
+                printf("ERROR: Parameter %d: (%.1f), expected was (%.1f)\n",
+                       i, myParams->data.F32[i], expectedParm[i]);
+                testStatus = false;
+            } else {
+                printf("Parameter %d: (%.1f), expected was (%.1f)\n",
+                       i, myParams->data.F32[i], expectedParm[i]);
+            }
+        }
+
+        psFree(myCoords);
+        psFree(myParams);
+        psFree(myParamMask);
+        psFree(min);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // XXX: Add tests with active parameter mask
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolyFit1D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolyFit1D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolyFit1D.c	(revision 22158)
@@ -0,0 +1,744 @@
+/*****************************************************************************
+This routine must ensure that various psLib functions which fit 1D polynomials
+to data work correctly.  There is a function genericTest() which creates
+vectors of data points (x and f), and populates them with the values from an
+arbitrary function setData().  It then calls appropriate 1D fitting function.
+It then evaluates the polynomial with the coefficients generated above and
+determines if they are within an error tolerance of the expected values.
+ 
+XXX: Try null stats.
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define NUM_DATA 100
+#define POLY_ORDER 5
+#define A 2.0
+#define B 3.0
+#define C 4.0
+#define D 5.0
+#define E 6.0
+#define ERROR_TOLERANCE 0.10
+#define YERR 10.0
+#define VERBOSE 0
+#define EXTRA_VERBOSE 0
+#define NUM_ITERATIONS 5
+#define CLIP_SIGMA 4.0
+#define OUTLIERS true
+#define MASK_VALUE 1
+
+#define TS00_F_NULL  0x00000001
+#define TS00_F_F32  0x00000002
+#define TS00_F_F64  0x00000004
+#define TS00_F_S32  0x00000008
+#define TS00_X_NULL  0x00000010
+#define TS00_X_F32  0x00000020
+#define TS00_X_F64  0x00000040
+#define TS00_X_S32  0x00000080
+#define TS00_FERR_NULL  0x00000100
+#define TS00_FERR_F32  0x00000200
+#define TS00_FERR_F64  0x00000400
+#define TS00_FERR_S32  0x00000800
+#define TS00_MASK_NULL  0x00001000
+#define TS00_MASK_U8  0x00002000
+#define TS00_MASK_S32  0x00004000
+#define TS00_POLY_ORD  0x00008000
+#define TS00_POLY_CHEB  0x00010000
+#define TS00_CLIP_FIT  0x00020000
+
+psF32 setData(psF32 x)
+{
+    return(A + (B * x) + (C * x * x) + (D * x * x * x) + (E * x * x * x * x));
+}
+
+bool genericTest(
+    psU32 flags,
+    psS32 polyOrder,
+    psS32 numData,
+    bool expectedRC)
+{
+    psS32 currentId = psMemGetId();
+    bool testStatus = true;
+    psS32 memLeaks = 0;
+    psPolynomial1D *myPoly = NULL;
+    psVector *x = NULL;
+    psVector *f = NULL;
+    psVector *mask = NULL;
+    psVector *fErr = NULL;
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    stats->clipSigma = CLIP_SIGMA;
+    stats->clipIter = NUM_ITERATIONS;
+    stats->options |= PS_STAT_SAMPLE_STDEV;
+
+    if (VERBOSE)
+        printf("psMinimize functions: 1D Polynomial Fitting Functions");
+
+    if (expectedRC == false && VERBOSE) {
+        printf("This test should generate an error message, and return NULL.\n");
+    }
+
+    if (VERBOSE) {
+        if (flags & TS00_CLIP_FIT) {
+            printf("        performing a clip-fit\n");
+        } else {
+            printf("        performing a non clip-fit\n");
+        }
+    }
+
+    if (flags & TS00_POLY_ORD) {
+        if (VERBOSE)
+            printf(" using ordinary polynomials\n");
+        myPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, polyOrder);
+    }
+
+    if (flags & TS00_POLY_CHEB) {
+        if (VERBOSE)
+            printf(" using chebyshev polynomials\n");
+        myPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_CHEB, polyOrder);
+    }
+
+    if (flags & TS00_X_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL x vector\n");
+        numData = 30;
+    }
+
+    psVector *xTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *fTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 1); // Using a known seed
+    for (int i = 0; i < numData; i++) {
+        xTruth->data.F64[i] = (flags & TS00_X_NULL) ? i : 2.0*psRandomUniform(rng) - 1.0;
+        fTruth->data.F64[i] = setData(xTruth->data.F64[i]);
+    }
+    if (flags & TS00_X_NULL && flags & TS00_POLY_CHEB) {
+        // Renormalise the indices
+        p_psNormalizeVectorRange(xTruth, -1.0, 1.0);
+    }
+    psFree(rng);
+    if (EXTRA_VERBOSE)
+        for (int i = 0; i < numData; i++) {
+            printf("Original %d: %f\t%f\n", i, xTruth->data.F64[i], fTruth->data.F64[i]);
+        }
+
+    if (flags & TS00_X_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F32);
+
+        #if 0
+
+        if (flags & TS00_POLY_CHEB) {
+            p_psNormalizeVectorRange(x, -1.0, 1.0);
+        }
+        #endif
+
+    }
+
+    if (flags & TS00_X_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_S32);
+
+        #if 0
+
+        if (flags & TS00_POLY_CHEB) {
+            p_psNormalizeVectorRange(x, -1, 1);
+        }
+        #endif
+
+    }
+
+    if (flags & TS00_X_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F64);
+
+        #if 0
+
+        if (flags & TS00_POLY_CHEB) {
+            p_psNormalizeVectorRange(x, -1.0, 1.0);
+        }
+        #endif
+
+    }
+
+    if (flags & TS00_F_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL f vector\n");
+    }
+
+    if (flags & TS00_F_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F32[numData/4]*= 2.0;
+            f->data.F32[numData/2]*= 2.0;
+            f->data.F32[3*numData/4]*= 2.0;
+        }
+    }
+
+    if (flags & TS00_F_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_S32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.S32[numData/4]*= 2.0;
+            f->data.S32[numData/2]*= 2.0;
+            f->data.S32[3*numData/4]*= 2.0;
+        }
+
+    }
+
+    if (flags & TS00_F_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F64);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F64[numData/4]*= 2.0;
+            f->data.F64[numData/2]*= 2.0;
+            f->data.F64[3*numData/4]*= 2.0;
+        }
+    }
+
+    if (flags & TS00_FERR_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL fErr vector\n");
+    }
+
+    if (flags & TS00_FERR_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F32[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_S32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.S32[i] = (psS32) YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F64);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F64[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_MASK_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL mask vector\n");
+    }
+
+    if (flags & TS00_MASK_U8) {
+        if (VERBOSE)
+            printf(" using a psU8 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_U8);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.U8[i] = 0;
+        }
+    }
+
+    if (flags & TS00_MASK_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_S32);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.S32[i] = 0;
+        }
+    }
+
+    bool rc = false;
+    if (flags & TS00_CLIP_FIT) {
+        rc = psVectorClipFitPolynomial1D(myPoly, stats, mask, MASK_VALUE, f, fErr, x);
+    } else {
+        rc = psVectorFitPolynomial1D(myPoly, mask, MASK_VALUE, f, fErr, x);
+    }
+
+    if (!rc) {
+        if (expectedRC == true) {
+            diag("TEST ERROR: the 1D polynomial fitting function returned NULL.\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            diag("TEST ERROR: the 1D polynomial fitting function returned non-NULL.\n");
+            testStatus = false;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<polyOrder+1;i++) {
+                printf("Polynomial coefficient %d is %0.1f\n", i, myPoly->coeff[i]);
+            }
+        }
+
+        psVector *result = psPolynomial1DEvalVector(myPoly, xTruth);
+        for (psS32 i=0; i<numData; i++) {
+            // Skip the outliers.
+            if ((i == numData/4) || (i == numData/2) || (i == 3*numData/4)) {
+                continue;
+            }
+            psF32 expectData = fTruth->data.F64[i];
+            psF32 actualData = result->data.F64[i];
+            if (fabs(actualData-expectData) > fabs(ERROR_TOLERANCE * expectData)) {
+                diag("TEST ERROR: Fitted data %d: %.1f --> %.1f vs %.1f\n",
+                     i, xTruth->data.F64[i], actualData, expectData);
+                testStatus = false;
+            } else {
+                if (EXTRA_VERBOSE) {
+                    printf("GOOD: Fitted data %d: %1.f --> %.1f vs %.1f\n",
+                           i, xTruth->data.F64[i], actualData, expectData);
+                }
+            }
+        }
+        psFree(result);
+    }
+
+    psMemCheckCorruption(stderr, false);
+    psFree(myPoly);
+    psFree(mask);
+    psFree(x);
+    psFree(f);
+    psFree(xTruth);
+    psFree(fTruth);
+    psFree(fErr);
+    psFree(stats);
+    psMemCheckCorruption(stderr, false);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    return (testStatus);
+}
+
+/*****************************************************************************
+We test a variety of polynomial fitting routines, types, and polynomial types
+here:
+    F32 tests: Ordinary polys, non-clip fit
+    F64 tests: Ordinary polys, non-clip fit
+    F32 tests: Chebyshev polys, non-clip fit
+    F64 tests: Chebyshev polys, non-clip fit
+    F32 tests: Ordinary polys, clip fit
+    F64 tests: Ordinary polys, clip fit
+    F32 tests: Chebyshev polys, clip fit
+    F64 tests: Chebyshev polys, clip fit
+ *****************************************************************************/
+int main()
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(104);
+
+
+    // psVectorFitPolynomial1D()
+    // Test various erroneous input paramater configurations
+    {
+        psMemId id = psMemGetId();
+        psPolynomial1D *myPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, POLY_ORDER);
+        psVector *x = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *xS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *f = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *fS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *mask = psVectorAlloc(NUM_DATA, PS_TYPE_U8);
+        psVector *maskS8 = psVectorAlloc(NUM_DATA, PS_TYPE_S8);
+        psVector *fErr = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *fErrS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+
+
+        // Set psPolynomial1D to NULL, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial1D(NULL, mask, MASK_VALUE, f, fErr, x);
+            ok(rc == false, "psVectorFitPolynomial1D() returned FALSE with NULL psPolynomial1D");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set mask to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial1D(myPoly, maskS8, MASK_VALUE, f, fErr, x);
+            ok(rc == false, "psVectorFitPolynomial1D() returned FALSE with mask set to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set f psVector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial1D(myPoly, mask, MASK_VALUE, fS32, fErr, x);
+            ok(rc == false, "psVectorFitPolynomial1D() returned FALSE: Set f psVector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set fError vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial1D(myPoly, mask, MASK_VALUE, f, fErrS32, x);
+            ok(rc == false, "psVectorFitPolynomial1D() returned FALSE: Set fError vector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set x vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial1D(myPoly, mask, MASK_VALUE, f, fErr, xS32);
+            ok(rc == false, "psVectorFitPolynomial1D() returned FALSE: Set x vector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect mask psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            mask->n++;
+            bool rc = psVectorFitPolynomial1D(myPoly, mask, MASK_VALUE, f, fErr, x);
+            mask->n--;
+            ok(rc == false, "psVectorFitPolynomial1D() returned FALSE: Incorrect mask psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect f psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            f->n++;
+            bool rc = psVectorFitPolynomial1D(myPoly, mask, MASK_VALUE, f, fErr, x);
+            f->n--;
+            ok(rc == false, "psVectorFitPolynomial1D() returned FALSE: Incorrect f psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect fErr psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            fErr->n++;
+            bool rc = psVectorFitPolynomial1D(myPoly, mask, MASK_VALUE, f, fErr, x);
+            fErr->n--;
+            ok(rc == false, "psVectorFitPolynomial1D() returned FALSE: Incorrect fErr psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect x psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            x->n++;
+            bool rc = psVectorFitPolynomial1D(myPoly, mask, MASK_VALUE, f, fErr, x);
+            x->n--;
+            ok(rc == false, "psVectorFitPolynomial1D() returned FALSE: Incorrect x psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+        psFree(myPoly);
+        psFree(x);
+        psFree(xS32);
+        psFree(f);
+        psFree(fS32);
+        psFree(mask);
+        psFree(maskS8);
+        psFree(fErr);
+        psFree(fErrS32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psVectorClipFitPolynomial1D()
+    // Test various erroneous input paramater configurations
+    {
+        psMemId id = psMemGetId();
+        psPolynomial1D *myPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, POLY_ORDER);
+        psVector *x = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *xS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *f = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *fS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *mask = psVectorAlloc(NUM_DATA, PS_TYPE_U8);
+        psVector *maskS8 = psVectorAlloc(NUM_DATA, PS_TYPE_S8);
+        psVector *fErr = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *fErrS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+
+
+        // Set psPolynomial1D to NULL, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial1D(NULL, stats, mask, MASK_VALUE, f, fErr, x);
+            ok(rc == false, "psVectorClipFitPolynomial1D() returned FALSE with NULL psPolynomial1D");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set psStats to NULL, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial1D(myPoly, NULL, mask, MASK_VALUE, f, fErr, x);
+            ok(rc == false, "psVectorClipFitPolynomial1D() returned FALSE with NULL psStats");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set mask to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial1D(myPoly, stats, maskS8, MASK_VALUE, f, fErr, x);
+            ok(rc == false, "psVectorClipFitPolynomial1D() returned FALSE with mask set to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set f psVector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial1D(myPoly, stats, mask, MASK_VALUE, fS32, fErr, x);
+            ok(rc == false, "psVectorClipFitPolynomial1D() returned FALSE: Set f psVector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set fError vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial1D(myPoly, stats, mask, MASK_VALUE, f, fErrS32, x);
+            ok(rc == false, "psVectorClipFitPolynomial1D() returned FALSE: Set fError vector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set x vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial1D(myPoly, stats, mask, MASK_VALUE, f, fErr, xS32);
+            ok(rc == false, "psVectorClipFitPolynomial1D() returned FALSE: Set x vector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect mask psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            mask->n++;
+            bool rc = psVectorClipFitPolynomial1D(myPoly, stats, mask, MASK_VALUE, f, fErr, x);
+            mask->n--;
+            ok(rc == false, "psVectorClipFitPolynomial1D() returned FALSE: Incorrect mask psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect f psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            f->n++;
+            bool rc = psVectorClipFitPolynomial1D(myPoly, stats, mask, MASK_VALUE, f, fErr, x);
+            f->n--;
+            ok(rc == false, "psVectorClipFitPolynomial1D() returned FALSE: Incorrect f psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect fErr psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            fErr->n++;
+            bool rc = psVectorClipFitPolynomial1D(myPoly, stats, mask, MASK_VALUE, f, fErr, x);
+            fErr->n--;
+            ok(rc == false, "psVectorClipFitPolynomial1D() returned FALSE: Incorrect fErr psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect x psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            x->n++;
+            bool rc = psVectorClipFitPolynomial1D(myPoly, stats, mask, MASK_VALUE, f, fErr, x);
+            x->n--;
+            ok(rc == false, "psVectorClipFitPolynomial1D() returned FALSE: Incorrect x psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+        psFree(myPoly);
+        psFree(x);
+        psFree(xS32);
+        psFree(f);
+        psFree(fS32);
+        psFree(mask);
+        psFree(maskS8);
+        psFree(fErr);
+        psFree(fErrS32);
+        psFree(stats);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    //
+    // F32 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit, Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit, Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit, Some Vectors NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_NULL | TS00_X_NULL | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit, Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit, F Vector NULL");
+    // Unallowable vector types
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit, Unallowable vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_S32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit, Unallowable vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_S32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit, Unallowable vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_S32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit, Unallowable vector types");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit, Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit, Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit, Mismatch vector types");
+
+    //
+    // F64 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit, Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit, Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit, Some Vectors NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_NULL | TS00_X_NULL | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit, Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit, F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit, Mismatch data type");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit, Mismatch data type");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit, Mismatch data type");
+
+
+    //
+    // F32 tests: Chebyshev polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, non-clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, non-clip fit.  Some Vectors NULL.");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, non-clip fit.  Some Vectors NULL.");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, non-clip fit.  Some Vectors NULL.");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_NULL | TS00_X_NULL | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, non-clip fit.  Some Vectors NULL.");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_NULL | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, false), "F32 tests: Chebyshev polys, non-clip fit.  F Vector NULL.");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, false), "F32 tests: Chebyshev polys, non-clip fit.  Mismatch vector types.");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, non-clip fit.  Mismatch vector types.");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, non-clip fit.  Mismatch vector types.");
+
+
+    //
+    // F64 tests: Chebyshev polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, non-clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_NULL | TS00_X_NULL | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, non-clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_NULL | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, false), "F64 tests: Chebyshev polys, non-clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, false), "F64 tests: Chebyshev polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, non-clip fit.  Mismatch vector types");
+
+    //
+    // F32 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit");
+    // Some Vectors NULL
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_NULL | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+
+    //
+    // F64 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD
+                   | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true),
+       "F64 tests: Ordinary polys, clip fit");
+    // Some Vectors NULL
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_NULL | TS00_POLY_ORD
+                   | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false),
+       "F64 tests: Ordinary polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+
+
+    //
+    // F32 tests: Chebyshev polys, clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, clip fit");
+    // Some Vectors NULL
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, clip fit.  Some Vectors NULL");
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, clip fit.  Some Vectors NULL");
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_NULL | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_NULL | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Chebyshev polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Chebyshev polys, clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Chebyshev polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Chebyshev polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Chebyshev polys, clip fit.  Mismatch vector types");
+
+
+    //
+    // F64 tests: Chebyshev polys, clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, clip fit");
+    // Some Vectors NULL
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, clip fit.  Some Vectors NULL");
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_F_F64 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_NULL | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F64 tests: Chebyshev polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F64 tests: Chebyshev polys, clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F64 tests: Chebyshev polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F64 tests: Chebyshev polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F64 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F64 tests: Chebyshev polys, clip fit.  Mismatch vector types");
+
+    // Note: memory leaks tests are performed in the genericTest() subroutine.
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolyFit2D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolyFit2D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolyFit2D.c	(revision 22158)
@@ -0,0 +1,713 @@
+/*****************************************************************************
+This routine must ensure that various psLib functions which fit 2D polynomials
+to data work correctly.  There is a function genericTest() which creates
+vectors of data points (x and f), and populates them with the values from an
+arbitrary function setData().  It then calls appropriate 2D fitting function.
+It then evaluates the polynomial with the coefficients generated above and
+determines if they are within an error tolerance of the expected values.
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define NUM_DATA 100
+#define POLY_ORDER_X 2
+#define POLY_ORDER_Y 2
+#define A 2.0
+#define B 3.0
+#define C 4.0
+#define D 5.0
+#define E 6.0
+#define F 4.0
+#define ERROR_TOLERANCE 0.10
+#define YERR 10.0
+#define VERBOSE 0
+#define EXTRA_VERBOSE 0
+#define NUM_ITERATIONS 5
+#define CLIP_SIGMA 4.0
+#define OUTLIERS true
+#define MASK_VALUE 1
+
+#define TS00_F_NULL  0x00000001
+#define TS00_F_F32  0x00000002
+#define TS00_F_F64  0x00000004
+#define TS00_F_S32  0x00000008
+#define TS00_X_NULL  0x00000010
+#define TS00_X_F32  0x00000020
+#define TS00_X_F64  0x00000040
+#define TS00_X_S32  0x00000080
+#define TS00_FERR_NULL  0x00000100
+#define TS00_FERR_F32  0x00000200
+#define TS00_FERR_F64  0x00000400
+#define TS00_FERR_S32  0x00000800
+#define TS00_MASK_NULL  0x00001000
+#define TS00_MASK_U8  0x00002000
+#define TS00_MASK_S32  0x00004000
+#define TS00_POLY_ORD  0x00008000
+#define TS00_POLY_CHEB  0x00010000
+#define TS00_CLIP_FIT  0x00020000
+#define TS00_Y_NULL  0x00100000
+#define TS00_Y_F32  0x00200000
+#define TS00_Y_F64  0x00400000
+#define TS00_Y_S32  0x00800000
+
+psF32 setData(psF32 x, psF32 y)
+{
+    return(A + (B * x) + (C * x * x) + (D * y) + (E * y * y) + (F * x * y));
+}
+
+psS32 genericTest(
+    psU32 flags,
+    psS32 polyOrderX,
+    psS32 polyOrderY,
+    psS32 numData,
+    bool expectedRC)
+{
+    psS32 currentId = psMemGetId();
+    psS32 testStatus = true;
+    psS32 memLeaks = 0;
+    psPolynomial2D *myPoly = NULL;
+    psVector *x = NULL;
+    psVector *y = NULL;
+    psVector *f = NULL;
+    psVector *mask = NULL;
+    psVector *fErr = NULL;
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    stats->clipSigma = CLIP_SIGMA;
+    stats->clipIter = NUM_ITERATIONS;
+    stats->options |= PS_STAT_SAMPLE_STDEV;
+
+    if (VERBOSE)
+        printf("psMinimize functions: 2D Polynomial Fitting Functions");
+
+    if (expectedRC == false && VERBOSE) {
+        printf("This test should generate an error message, and return NULL.\n");
+    }
+
+    if (VERBOSE) {
+        if (flags & TS00_CLIP_FIT) {
+            printf(" performing a clip-fit\n");
+        } else {
+            printf(" performing a non clip-fit\n");
+        }
+    }
+
+    if (flags & TS00_POLY_ORD) {
+        if (VERBOSE)
+            printf(" using ordinary polynomials\n");
+        myPoly = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, polyOrderX, polyOrderY);
+    }
+
+
+    psVector *xTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *yTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *fTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    xTruth->n = numData;
+    yTruth->n = numData;
+    fTruth->n = numData;
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 1); // Using an RNG with a known seed
+    for (int i = 0; i < numData; i++) {
+        xTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        yTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        fTruth->data.F64[i] = setData(xTruth->data.F64[i], yTruth->data.F64[i]);
+    }
+    psFree(rng);
+
+    if (flags & TS00_X_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL x vector\n");
+    }
+
+    if (flags & TS00_X_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_X_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_X_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F64);
+    }
+
+    if (flags & TS00_Y_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL y vector\n");
+    }
+
+    if (flags & TS00_Y_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_Y_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_Y_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_F64);
+    }
+
+    if (flags & TS00_F_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL f vector\n");
+    }
+
+    if (flags & TS00_F_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F32[numData/4]*= 2.0;
+            f->data.F32[numData/2]*= 2.0;
+            f->data.F32[3*numData/4]*= 2.0;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original data %d: (%.1f %.1f)\n", i, (psF32) i, f->data.F32[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_F_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_S32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.S32[numData/4]*= 2.0;
+            f->data.S32[numData/2]*= 2.0;
+            f->data.S32[3*numData/4]*= 2.0;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original data %d: (%.1f %d)\n", i, (psF32) i, f->data.S32[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_F_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F64);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F64[numData/4]*= 2.0;
+            f->data.F64[numData/2]*= 2.0;
+            f->data.F64[3*numData/4]*= 2.0;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original data %d: (%.1f %.1f)\n", i, (psF32) i, f->data.F64[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_FERR_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL fErr vector\n");
+    }
+
+    if (flags & TS00_FERR_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F32[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_S32);
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.S32[i] = (psS32) YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F64);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F64[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_MASK_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL mask vector\n");
+    }
+
+    if (flags & TS00_MASK_U8) {
+        if (VERBOSE)
+            printf(" using a psU8 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_U8);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.U8[i] = 0;
+        }
+    }
+
+    if (flags & TS00_MASK_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_S32);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.S32[i] = 0;
+        }
+    }
+
+    bool rc = false;
+    if (flags & TS00_CLIP_FIT) {
+        rc = psVectorClipFitPolynomial2D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y);
+    } else {
+        rc = psVectorFitPolynomial2D(myPoly, mask, MASK_VALUE, f, fErr, x, y);
+    }
+
+    if (!rc) {
+        if (expectedRC == true) {
+            diag("TEST ERROR: the 2D polynomial fitting function returned NULL.\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            diag("TEST ERROR: the 2D polynomial fitting function returned non-NULL.\n");
+            testStatus = false;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<polyOrderX+1;i++) {
+                for (psS32 j=0;j<polyOrderY+1;j++) {
+                    printf("Polynomial coefficient [%d][%d] is %0.1f\n", i, j, myPoly->coeff[i][j]);
+                }
+            }
+        }
+
+        psVector *result = psPolynomial2DEvalVector(myPoly, xTruth, yTruth);
+        for (psS32 i=0 ;i<numData; i++) {
+            // Skip the outliers.
+            if ((i == numData/4) || (i == numData/2) || (i == 3*numData/4)) {
+                continue;
+            }
+            psF64 actualData = result->data.F64[i];
+            psF64 expectData = fTruth->data.F64[i];
+
+            if (fabs(actualData-expectData) > fabs(ERROR_TOLERANCE * expectData)) {
+                diag("TEST ERROR: Fitted data %d: (%.1f), expected was (%.1f)\n",
+                     i, actualData, expectData);
+                testStatus = false;
+            } else {
+                if (EXTRA_VERBOSE) {
+                    printf("GOOD: Fitted data %d: (%.1f), expected was (%.1f)\n",
+                           i, actualData, expectData);
+                }
+            }
+        }
+        psFree(result);
+    }
+
+    psMemCheckCorruption(stderr, false);
+    psFree(myPoly);
+    psFree(mask);
+    psFree(xTruth);
+    psFree(yTruth);
+    psFree(fTruth);
+    psFree(x);
+    psFree(y);
+    psFree(f);
+    psFree(fErr);
+    psFree(stats);
+    psMemCheckCorruption(stderr, false);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    return (testStatus);
+}
+
+/*****************************************************************************
+We test a variety of polynomial fitting routines, types, and polynomial types
+here:
+    F32 tests: Ordinary polys, non-clip fit
+    F64 tests: Ordinary polys, non-clip fit
+    F32 tests: Chebyshev polys, non-clip fit
+    F64 tests: Chebyshev polys, non-clip fit
+    F32 tests: Ordinary polys, clip fit
+    F64 tests: Ordinary polys, clip fit
+    F32 tests: Chebyshev polys, clip fit
+    F64 tests: Chebyshev polys, clip fit
+ *****************************************************************************/
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(88);
+
+
+    // psVectorFitPolynomial2D()
+    // Test various erroneous input paramater configurations
+    {
+        psMemId id = psMemGetId();
+        psPolynomial2D *myPoly = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, POLY_ORDER_X, POLY_ORDER_Y);
+        psVector *x = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *xS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *y = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *yS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *f = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *fS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *mask = psVectorAlloc(NUM_DATA, PS_TYPE_U8);
+        psVector *maskS8 = psVectorAlloc(NUM_DATA, PS_TYPE_S8);
+        psVector *fErr = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *fErrS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+
+
+        // Set psPolynomial2D to NULL, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial2D(NULL, mask, MASK_VALUE, f, fErr, x, y);
+            ok(rc == false, "psVectorFitPolynomial2D() returned FALSE with NULL psPolynomial2D");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set mask to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial2D(myPoly, maskS8, MASK_VALUE, f, fErr, x, y);
+            ok(rc == false, "psVectorFitPolynomial2D() returned FALSE with mask set to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set f psVector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial2D(myPoly, mask, MASK_VALUE, fS32, fErr, x, y);
+            ok(rc == false, "psVectorFitPolynomial2D() returned FALSE: Set f psVector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set fError vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial2D(myPoly, mask, MASK_VALUE, f, fErrS32, x, y);
+            ok(rc == false, "psVectorFitPolynomial2D() returned FALSE: Set fError vector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set x vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial2D(myPoly, mask, MASK_VALUE, f, fErr, xS32, y);
+            ok(rc == true, "psVectorFitPolynomial2D() returned TRUE: x vector may be S32");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set y vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial2D(myPoly, mask, MASK_VALUE, f, fErr, x, yS32);
+            ok(rc == true, "psVectorFitPolynomial2D() returned TRUE: y vector may be S32");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect mask psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            mask->n++;
+            bool rc = psVectorFitPolynomial2D(myPoly, mask, MASK_VALUE, f, fErr, x, y);
+            mask->n--;
+            ok(rc == false, "psVectorFitPolynomial2D() returned FALSE: Incorrect mask psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect f psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            f->n++;
+            bool rc = psVectorFitPolynomial2D(myPoly, mask, MASK_VALUE, f, fErr, x, y);
+            f->n--;
+            ok(rc == false, "psVectorFitPolynomial2D() returned FALSE: Incorrect f psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect fErr psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            fErr->n++;
+            bool rc = psVectorFitPolynomial2D(myPoly, mask, MASK_VALUE, f, fErr, x, y);
+            fErr->n--;
+            ok(rc == false, "psVectorFitPolynomial2D() returned FALSE: Incorrect fErr psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect x psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            x->n++;
+            bool rc = psVectorFitPolynomial2D(myPoly, mask, MASK_VALUE, f, fErr, x, y);
+            x->n--;
+            ok(rc == false, "psVectorFitPolynomial2D() returned FALSE: Incorrect x psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+        psFree(myPoly);
+        psFree(x);
+        psFree(xS32);
+        psFree(y);
+        psFree(yS32);
+        psFree(f);
+        psFree(fS32);
+        psFree(mask);
+        psFree(maskS8);
+        psFree(fErr);
+        psFree(fErrS32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psVectorClipFitPolynomial2D()
+    // Test various erroneous input paramater configurations
+    {
+        psMemId id = psMemGetId();
+        psPolynomial2D *myPoly = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, POLY_ORDER_X, POLY_ORDER_Y);
+        psVector *x = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *xS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *y = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *yS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *f = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *fS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *mask = psVectorAlloc(NUM_DATA, PS_TYPE_U8);
+        psVector *maskS8 = psVectorAlloc(NUM_DATA, PS_TYPE_S8);
+        psVector *fErr = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *fErrS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+
+
+        // Set psPolynomial2D to NULL, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial2D(NULL, stats, mask, MASK_VALUE, f, fErr, x, y);
+            ok(rc == false, "psVectorClipFitPolynomial2D() returned FALSE with NULL psPolynomial2D");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set psStats to NULL, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial2D(myPoly, NULL, mask, MASK_VALUE, f, fErr, x, y);
+            ok(rc == false, "psVectorClipFitPolynomial2D() returned FALSE with NULL psStats");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set mask to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial2D(myPoly, stats, maskS8, MASK_VALUE, f, fErr, x, y);
+            ok(rc == false, "psVectorClipFitPolynomial2D() returned FALSE with mask set to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set f psVector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial2D(myPoly, stats, mask, MASK_VALUE, fS32, fErr, x, y);
+            ok(rc == false, "psVectorClipFitPolynomial2D() returned FALSE: Set f psVector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set fError vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial2D(myPoly, stats, mask, MASK_VALUE, f, fErrS32, x, y);
+            ok(rc == false, "psVectorClipFitPolynomial2D() returned FALSE: Set fError vector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set x vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial2D(myPoly, stats, mask, MASK_VALUE, f, fErr, xS32, y);
+            ok(rc == false, "psVectorClipFitPolynomial2D() returned FALSE: Set x vector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set y vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial2D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, yS32);
+            ok(rc == false, "psVectorClipFitPolynomial2D() returned FALSE: Set y vector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect mask psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            mask->n++;
+            bool rc = psVectorClipFitPolynomial2D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y);
+            mask->n--;
+            ok(rc == false, "psVectorClipFitPolynomial2D() returned FALSE: Incorrect mask psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect f psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            f->n++;
+            bool rc = psVectorClipFitPolynomial2D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y);
+            f->n--;
+            ok(rc == false, "psVectorClipFitPolynomial2D() returned FALSE: Incorrect f psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect fErr psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            fErr->n++;
+            bool rc = psVectorClipFitPolynomial2D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y);
+            fErr->n--;
+            ok(rc == false, "psVectorClipFitPolynomial2D() returned FALSE: Incorrect fErr psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect x psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            x->n++;
+            bool rc = psVectorClipFitPolynomial2D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y);
+            x->n--;
+            ok(rc == false, "psVectorClipFitPolynomial2D() returned FALSE: Incorrect x psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+        psFree(myPoly);
+        psFree(x);
+        psFree(xS32);
+        psFree(y);
+        psFree(yS32);
+        psFree(f);
+        psFree(fS32);
+        psFree(mask);
+        psFree(maskS8);
+        psFree(fErr);
+        psFree(fErrS32);
+        psFree(stats);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //
+    // F32 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+
+    //
+    // F64 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+
+    //
+    // F32 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+
+    //
+    // F64 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F64 tests: Ordinary polys, clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolyFit3D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolyFit3D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolyFit3D.c	(revision 22158)
@@ -0,0 +1,797 @@
+/*****************************************************************************
+This routine must ensure that various psLib functions which fit 3D polynomials
+to data work correctly.  There is a function genericTest() which creates
+vectors of data points (x and f), and populates them with the values from an
+arbitrary function setData().  It then calls appropriate 3D fitting function.
+It then evaluates the polynomial with the coefficients generated above and
+determines if they are within an error tolerance of the expected values.
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define NUM_DATA 100
+#define POLY_ORDER_X 2
+#define POLY_ORDER_Y 3
+#define POLY_ORDER_Z 2
+#define A 100.0
+#define B 2.0
+#define C 3.0
+#define D 4.0
+#define E 5.0
+#define F 4.0
+#define H 3.0
+#define J 3.0
+#define K 1.0
+#define L 5.0
+#define ERROR_TOLERANCE 0.10
+#define YERR 10.0
+#define VERBOSE 0
+#define EXTRA_VERBOSE 0
+#define NUM_ITERATIONS 5
+#define CLIP_SIGMA 4.0
+#define OUTLIERS true
+#define MASK_VALUE 1
+
+#define TS00_F_NULL  0x00000001
+#define TS00_F_F32  0x00000002
+#define TS00_F_F64  0x00000004
+#define TS00_F_S32  0x00000008
+#define TS00_X_NULL  0x00000010
+#define TS00_X_F32  0x00000020
+#define TS00_X_F64  0x00000040
+#define TS00_X_S32  0x00000080
+#define TS00_FERR_NULL  0x00000100
+#define TS00_FERR_F32  0x00000200
+#define TS00_FERR_F64  0x00000400
+#define TS00_FERR_S32  0x00000800
+#define TS00_MASK_NULL  0x00001000
+#define TS00_MASK_U8  0x00002000
+#define TS00_MASK_S32  0x00004000
+#define TS00_POLY_ORD  0x00008000
+#define TS00_POLY_CHEB  0x00010000
+#define TS00_CLIP_FIT  0x00020000
+#define TS00_Y_NULL  0x00100000
+#define TS00_Y_F32  0x00200000
+#define TS00_Y_F64  0x00400000
+#define TS00_Y_S32  0x00800000
+#define TS00_Z_NULL  0x01000000
+#define TS00_Z_F32  0x02000000
+#define TS00_Z_F64  0x04000000
+#define TS00_Z_S32  0x08000000
+
+psF32 setData(psF32 x, psF32 y, psF32 z)
+{
+    if (0) {
+        // Linear case, for testing.
+        return(A + (B * x) + (D * y) + (H * z));
+    } else {
+        return(A + (B * x) + (C * x * x) + (D * y) + (E * y * y) + (F * x * y) + (H * z) +
+               (J * z * z) + (K * x * z) + (L * y * z));
+    }
+}
+
+psS32 genericTest(
+    psU32 flags,
+    psS32 polyOrderX,
+    psS32 polyOrderY,
+    psS32 polyOrderZ,
+    psS32 numData,
+    bool expectedRC)
+{
+    psS32 currentId = psMemGetId();
+    psS32 testStatus = true;
+    psS32 memLeaks = 0;
+    psPolynomial3D *myPoly = NULL;
+    psVector *x = NULL;
+    psVector *y = NULL;
+    psVector *z = NULL;
+    psVector *f = NULL;
+    psVector *mask = NULL;
+    psVector *fErr = NULL;
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    stats->clipSigma = CLIP_SIGMA;
+    stats->clipIter = NUM_ITERATIONS;
+    stats->options |= PS_STAT_SAMPLE_STDEV;
+
+    if (VERBOSE)
+        printf("psMinimize functions: 3D Polynomial Fitting Functions");
+
+    psVector *xTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *yTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *zTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *fTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    xTruth->n = numData;
+    yTruth->n = numData;
+    zTruth->n = numData;
+    fTruth->n = numData;
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 1); // Using known seed
+    for (int i = 0; i < numData; i++) {
+        xTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        yTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        zTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        fTruth->data.F64[i] = setData(xTruth->data.F64[i], yTruth->data.F64[i], zTruth->data.F64[i]);
+    }
+    psFree(rng);
+
+    if (expectedRC == false && VERBOSE) {
+        printf("This test should generate an error message, and return NULL.\n");
+    }
+
+    if (VERBOSE) {
+        if (flags & TS00_CLIP_FIT) {
+            printf(" performing a clip-fit\n");
+        } else {
+            printf(" performing a non clip-fit\n");
+        }
+    }
+
+    if (flags & TS00_POLY_ORD) {
+        if (VERBOSE)
+            printf(" using ordinary polynomials\n");
+        myPoly = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, polyOrderX, polyOrderY, polyOrderZ);
+    }
+
+    if (flags & TS00_X_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL x vector\n");
+    }
+
+    if (flags & TS00_X_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_X_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_X_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F64);
+    }
+
+
+    if (flags & TS00_Y_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL y vector\n");
+    }
+
+    if (flags & TS00_Y_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_Y_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_Y_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_F64);
+    }
+
+    if (flags & TS00_Z_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL z vector\n");
+    }
+
+    if (flags & TS00_Z_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 z vector\n");
+        z = psVectorCopy(NULL, zTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_Z_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 z vector\n");
+        z = psVectorCopy(NULL, zTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_Z_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 z vector\n");
+        z = psVectorCopy(NULL, zTruth, PS_TYPE_F64);
+    }
+
+
+    if (flags & TS00_F_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL f vector\n");
+    }
+
+    if (flags & TS00_F_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F32[numData/4]*= 2.0;
+            f->data.F32[numData/2]*= 2.0;
+            f->data.F32[3*numData/4]*= 2.0;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original data %d: (%.1f)\n", i, f->data.F32[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_F_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_S32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.S32[numData/4]*= 2.0;
+            f->data.S32[numData/2]*= 2.0;
+            f->data.S32[3*numData/4]*= 2.0;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original data %d: (%d)\n", i, f->data.S32[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_F_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F64);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F64[numData/4]*= 2.0;
+            f->data.F64[numData/2]*= 2.0;
+            f->data.F64[3*numData/4]*= 2.0;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original data %d: (%.1f)\n", i, f->data.F64[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_FERR_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL fErr vector\n");
+    }
+
+    if (flags & TS00_FERR_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F32[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_S32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.S32[i] = (psS32) YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F64);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F64[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_MASK_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL mask vector\n");
+    }
+
+    if (flags & TS00_MASK_U8) {
+        if (VERBOSE)
+            printf(" using a psU8 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_U8);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.U8[i] = 0;
+        }
+    }
+
+    if (flags & TS00_MASK_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_S32);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.S32[i] = 0;
+        }
+    }
+
+    bool rc = false;
+    if (flags & TS00_CLIP_FIT) {
+        rc = psVectorClipFitPolynomial3D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y, z);
+    } else {
+        rc = psVectorFitPolynomial3D(myPoly, mask, MASK_VALUE, f, fErr, x, y, z);
+    }
+
+    if (!rc) {
+        if (expectedRC == true) {
+            diag("TEST ERROR: the 3D polynomial fitting function returned NULL.\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            diag("TEST ERROR: the 3D polynomial fitting function returned non-NULL.\n");
+            testStatus = false;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<polyOrderX+1;i++) {
+                for (psS32 j=0;j<polyOrderY+1;j++) {
+                    for (psS32 k=0;k<polyOrderZ+1;k++) {
+                        printf("Polynomial coefficient [%d][%d][%d] is %0.1f\n", i, j, k, myPoly->coeff[i][j][k]);
+                    }
+                }
+            }
+        }
+
+        psVector *result = psPolynomial3DEvalVector(myPoly, xTruth, yTruth, zTruth);
+        for (psS32 i=0 ;i<numData; i++) {
+            // Skip the outliers.
+            if ((i == numData/4) || (i == numData/2) || (i == 3*numData/4)) {
+                continue;
+            }
+            psF32 expectData = fTruth->data.F64[i];
+            psF32 actualData = result->data.F64[i];
+
+            if (fabs(actualData-expectData) > fabs(ERROR_TOLERANCE * expectData)) {
+                diag("TEST ERROR: Fitted data %d: (%.1f), expected was (%.1f)\n",
+                     i, actualData, expectData);
+                testStatus = false;
+            } else {
+                if (EXTRA_VERBOSE) {
+                    printf("GOOD: Fitted data %d: (%.1f), expected was (%.1f)\n",
+                           i, actualData, expectData);
+                }
+            }
+        }
+        psFree(result);
+    }
+
+    psMemCheckCorruption(stderr, false);
+    psFree(myPoly);
+    psFree(mask);
+    psFree(x);
+    psFree(y);
+    psFree(z);
+    psFree(f);
+    psFree(xTruth);
+    psFree(yTruth);
+    psFree(zTruth);
+    psFree(fTruth);
+    psFree(fErr);
+    psFree(stats);
+    psMemCheckCorruption(stderr, false);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    return (testStatus);
+}
+
+/*****************************************************************************
+We test a variety of polynomial fitting routines, types, and polynomial types
+here:
+    F32 tests: Ordinary polys, non-clip fit
+    F64 tests: Ordinary polys, non-clip fit
+    F32 tests: Chebyshev polys, non-clip fit
+    F64 tests: Chebyshev polys, non-clip fit
+    F32 tests: Ordinary polys, clip fit
+    F64 tests: Ordinary polys, clip fit
+    F32 tests: Chebyshev polys, clip fit
+    F64 tests: Chebyshev polys, clip fit
+ *****************************************************************************/
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(100);
+
+
+    // psVectorFitPolynomial3D()
+    // Test various erroneous input paramater configurations
+    {
+        psMemId id = psMemGetId();
+        psPolynomial3D *myPoly = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z);
+        psVector *x = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *xS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *y = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *yS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *z = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *zS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *f = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *fS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *mask = psVectorAlloc(NUM_DATA, PS_TYPE_U8);
+        psVector *maskS8 = psVectorAlloc(NUM_DATA, PS_TYPE_S8);
+        psVector *fErr = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *fErrS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+
+
+        // Set psPolynomial3D to NULL, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial3D(NULL, mask, MASK_VALUE, f, fErr, x, y, z);
+            ok(rc == false, "psVectorFitPolynomial3D() returned FALSE with NULL psPolynomial3D");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set mask to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial3D(myPoly, maskS8, MASK_VALUE, f, fErr, x, y, z);
+            ok(rc == false, "psVectorFitPolynomial3D() returned FALSE with mask set to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set f psVector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial3D(myPoly, mask, MASK_VALUE, fS32, fErr, x, y, z);
+            ok(rc == false, "psVectorFitPolynomial3D() returned FALSE: Set f psVector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set fError vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial3D(myPoly, mask, MASK_VALUE, f, fErrS32, x, y, z);
+            ok(rc == false, "psVectorFitPolynomial3D() returned FALSE: Set fError vector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set x vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial3D(myPoly, mask, MASK_VALUE, f, fErr, xS32, y, z);
+            ok(rc == true, "psVectorFitPolynomial3D() returned TRUE: x vector may be S32");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set y vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial3D(myPoly, mask, MASK_VALUE, f, fErr, x, yS32, z);
+            ok(rc == true, "psVectorFitPolynomial3D() returned TRUE: y vector may be S32");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set z vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial3D(myPoly, mask, MASK_VALUE, f, fErr, x, y, zS32);
+            ok(rc == true, "psVectorFitPolynomial3D() returned TRUE: z vector may be S32");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect mask psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            mask->n++;
+            bool rc = psVectorFitPolynomial3D(myPoly, mask, MASK_VALUE, f, fErr, x, y, z);
+            mask->n--;
+            ok(rc == false, "psVectorFitPolynomial3D() returned FALSE: Incorrect mask psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect f psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            f->n++;
+            bool rc = psVectorFitPolynomial3D(myPoly, mask, MASK_VALUE, f, fErr, x, y, z);
+            f->n--;
+            ok(rc == false, "psVectorFitPolynomial3D() returned FALSE: Incorrect f psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect fErr psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            fErr->n++;
+            bool rc = psVectorFitPolynomial3D(myPoly, mask, MASK_VALUE, f, fErr, x, y, z);
+            fErr->n--;
+            ok(rc == false, "psVectorFitPolynomial3D() returned FALSE: Incorrect fErr psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect x psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            x->n++;
+            bool rc = psVectorFitPolynomial3D(myPoly, mask, MASK_VALUE, f, fErr, x, y, z);
+            x->n--;
+            ok(rc == false, "psVectorFitPolynomial3D() returned FALSE: Incorrect x psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+        psFree(myPoly);
+        psFree(x);
+        psFree(xS32);
+        psFree(y);
+        psFree(yS32);
+        psFree(z);
+        psFree(zS32);
+        psFree(f);
+        psFree(fS32);
+        psFree(mask);
+        psFree(maskS8);
+        psFree(fErr);
+        psFree(fErrS32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psVectorClipFitPolynomial3D()
+    // Test various erroneous input paramater configurations
+    {
+        psMemId id = psMemGetId();
+        psPolynomial3D *myPoly = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z);
+        psVector *x = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *xS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *y = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *yS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *z = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *zS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *f = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *fS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *mask = psVectorAlloc(NUM_DATA, PS_TYPE_U8);
+        psVector *maskS8 = psVectorAlloc(NUM_DATA, PS_TYPE_S8);
+        psVector *fErr = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *fErrS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+
+
+        // Set psPolynomial3D to NULL, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial3D(NULL, stats, mask, MASK_VALUE, f, fErr, x, y, z);
+            ok(rc == false, "psVectorClipFitPolynomial3D() returned FALSE with NULL psPolynomial3D");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set psStats to NULL, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial3D(myPoly, NULL, mask, MASK_VALUE, f, fErr, x, y, z);
+            ok(rc == false, "psVectorClipFitPolynomial3D() returned FALSE with NULL psStats");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set mask to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial3D(myPoly, stats, maskS8, MASK_VALUE, f, fErr, x, y, z);
+            ok(rc == false, "psVectorClipFitPolynomial3D() returned FALSE with mask set to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set f psVector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial3D(myPoly, stats, mask, MASK_VALUE, fS32, fErr, x, y, z);
+            ok(rc == false, "psVectorClipFitPolynomial3D() returned FALSE: Set f psVector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set fError vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial3D(myPoly, stats, mask, MASK_VALUE, f, fErrS32, x, y, z);
+            ok(rc == false, "psVectorClipFitPolynomial3D() returned FALSE: Set fError vector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set x vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial3D(myPoly, stats, mask, MASK_VALUE, f, fErr, xS32, y, z);
+            ok(rc == false, "psVectorClipFitPolynomial3D() returned FALSE: Set x vector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set y vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial3D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, yS32, z);
+            ok(rc == false, "psVectorClipFitPolynomial3D() returned FALSE: Set y vector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set z vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial3D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y, zS32);
+            ok(rc == false, "psVectorClipFitPolynomial3D() returned FALSE: Set z vector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect mask psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            mask->n++;
+            bool rc = psVectorClipFitPolynomial3D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y, z);
+            mask->n--;
+            ok(rc == false, "psVectorClipFitPolynomial3D() returned FALSE: Incorrect mask psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect f psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            f->n++;
+            bool rc = psVectorClipFitPolynomial3D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y, z);
+            f->n--;
+            ok(rc == false, "psVectorClipFitPolynomial3D() returned FALSE: Incorrect f psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect fErr psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            fErr->n++;
+            bool rc = psVectorClipFitPolynomial3D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y, z);
+            fErr->n--;
+            ok(rc == false, "psVectorClipFitPolynomial3D() returned FALSE: Incorrect fErr psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect x psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            x->n++;
+            bool rc = psVectorClipFitPolynomial3D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y, z);
+            x->n--;
+            ok(rc == false, "psVectorClipFitPolynomial3D() returned FALSE: Incorrect x psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+        psFree(myPoly);
+        psFree(x);
+        psFree(xS32);
+        psFree(y);
+        psFree(yS32);
+        psFree(z);
+        psFree(zS32);
+        psFree(f);
+        psFree(fS32);
+        psFree(mask);
+        psFree(maskS8);
+        psFree(fErr);
+        psFree(fErrS32);
+        psFree(stats);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //
+    // F32 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+
+    //
+    // F64 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+
+    //
+    // F32 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_Z_NULL | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+
+    //
+    // F64 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_Z_NULL | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolyFit4D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolyFit4D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolyFit4D.c	(revision 22158)
@@ -0,0 +1,1020 @@
+/*****************************************************************************
+This routine must ensure that various psLib functions which fit 4D polynomials
+to data work correctly.  There is a function genericTest() which creates
+vectors of data points (x and f), and populates them with the values from an
+arbitrary function setData().  It then calls appropriate 4D fitting function.
+It then evaluates the polynomial with the coefficients generated above and
+determines if they are within an error tolerance of the expected values.
+ 
+XXX: A few tests which previously worked (2006/02) now fail (2006/12).  See
+XXX comment below.
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define NUM_DATA 200
+#define POLY_ORDER_X 1
+#define POLY_ORDER_Y 1
+#define POLY_ORDER_Z 1
+#define POLY_ORDER_T 1
+#define A 100.0
+#define B 2.0
+#define C 3.0
+#define D 4.0
+#define E 5.0
+#define F 6.0
+#define H 3.0
+#define J 3.0
+#define K 1.0
+#define L 5.0
+#define M 4.0
+#define N 3.0
+#define O 2.0
+#define P 1.0
+#define Q 5.0
+#define ERROR_TOLERANCE 0.05
+#define YERR 0.1
+#define VERBOSE 0
+#define EXTRA_VERBOSE 0
+#define NUM_ITERATIONS 5
+#define CLIP_SIGMA 3.0
+#define OUTLIERS true
+#define MASK_VALUE 1
+
+#define TS00_F_NULL  0x00000001
+#define TS00_F_F32  0x00000002
+#define TS00_F_F64  0x00000004
+#define TS00_F_S32  0x00000008
+#define TS00_X_NULL  0x00000010
+#define TS00_X_F32  0x00000020
+#define TS00_X_F64  0x00000040
+#define TS00_X_S32  0x00000080
+#define TS00_FERR_NULL  0x00000100
+#define TS00_FERR_F32  0x00000200
+#define TS00_FERR_F64  0x00000400
+#define TS00_FERR_S32  0x00000800
+#define TS00_MASK_NULL  0x00001000
+#define TS00_MASK_U8  0x00002000
+#define TS00_MASK_S32  0x00004000
+#define TS00_POLY_ORD  0x00008000
+#define TS00_POLY_CHEB  0x00010000
+#define TS00_CLIP_FIT  0x00020000
+#define TS00_Y_NULL  0x00100000
+#define TS00_Y_F32  0x00200000
+#define TS00_Y_F64  0x00400000
+#define TS00_Y_S32  0x00800000
+#define TS00_Z_NULL  0x01000000
+#define TS00_Z_F32  0x02000000
+#define TS00_Z_F64  0x04000000
+#define TS00_Z_S32  0x08000000
+#define TS00_T_NULL  0x10000000
+#define TS00_T_F32  0x20000000
+#define TS00_T_F64  0x40000000
+#define TS00_T_S32  0x80000000
+
+psF32 setData(psF32 x, psF32 y, psF32 z, psF32 t)
+{
+    if (0) {
+        // Linear case, for testing.
+        return(A + (B * x) + (C * y) + (D * z) + (E * t));
+    } else {
+        #if 0
+        return(A + (B * x) + (C * y) + (D * z) + (E * t) +
+               (F * x * x) + (H * y * y) + (J * z * z) + (K * t * t) +
+               (L * x * y) + (M * x * z) + (N * x * t) + (O * y * z) + (P * y * t) + (Q * z * t));
+        #else
+
+        return A + (B * x) + (C * y) + (D * z) + (E * t) + (F * x * y);
+        #endif
+
+    }
+}
+
+bool genericTest(
+    psU32 flags,
+    psS32 polyOrderX,
+    psS32 polyOrderY,
+    psS32 polyOrderZ,
+    psS32 polyOrderT,
+    psS32 numData,
+    bool expectedRC)
+{
+    psS32 currentId = psMemGetId();
+    bool testStatus = true;
+    psS32 memLeaks = 0;
+    psPolynomial4D *myPoly = NULL;
+    psVector *x = NULL;
+    psVector *y = NULL;
+    psVector *z = NULL;
+    psVector *t = NULL;
+    psVector *f = NULL;
+    psVector *mask = NULL;
+    psVector *fErr = NULL;
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    stats->clipSigma = CLIP_SIGMA;
+    stats->clipIter = NUM_ITERATIONS;
+    stats->options |= PS_STAT_SAMPLE_STDEV;
+
+    if (VERBOSE)
+        printf("psMinimize functions: 4D Polynomial Fitting Functions");
+
+    psVector *xTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *yTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *zTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *tTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *fTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    xTruth->n = numData;
+    yTruth->n = numData;
+    zTruth->n = numData;
+    tTruth->n = numData;
+    fTruth->n = numData;
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 1); // Using known seed
+    for (int i = 0; i < numData; i++) {
+        xTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        yTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        zTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        tTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        fTruth->data.F64[i] = setData(xTruth->data.F64[i], yTruth->data.F64[i],
+                                      zTruth->data.F64[i], tTruth->data.F64[i]);
+    }
+    psFree(rng);
+
+    if (expectedRC == false && VERBOSE) {
+        printf("This test should generate an error message, and return NULL.\n");
+    }
+    if (VERBOSE) {
+        if (flags & TS00_CLIP_FIT) {
+            printf(" performing a clip-fit\n");
+        } else {
+            printf(" performing a non clip-fit\n");
+        }
+    }
+
+    if (flags & TS00_POLY_ORD) {
+        if (VERBOSE)
+            printf(" using ordinary polynomials\n");
+        myPoly = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, polyOrderX, polyOrderY,
+                                     polyOrderZ, polyOrderT);
+
+        #if 1
+
+        for (int ix = 0; ix < polyOrderX + 1; ix++) {
+            for (int iy = 0; iy < polyOrderY + 1; iy++) {
+                for (int iz = 0; iz < polyOrderZ + 1; iz++) {
+                    for (int it = 0; it < polyOrderT + 1; it++) {
+                        myPoly->coeffMask[ix][iy][iz][it] = 0xff; // Mask it out
+                    }
+                }
+            }
+        }
+
+        // Put these back in
+        myPoly->coeffMask[0][0][0][0] = 0;   // A
+        myPoly->coeffMask[1][0][0][0] = 0;   // B * x
+        myPoly->coeffMask[0][1][0][0] = 0;   // C * y
+        myPoly->coeffMask[0][0][1][0] = 0;   // D * z
+        myPoly->coeffMask[0][0][0][1] = 0;   // E * t
+        myPoly->coeffMask[1][1][0][0] = 0;   // F * xy
+        #endif
+
+    }
+
+    if (flags & TS00_X_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL x vector\n");
+    }
+
+    if (flags & TS00_X_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_X_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_X_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F64);
+    }
+
+
+    if (flags & TS00_Y_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL y vector\n");
+    }
+
+    if (flags & TS00_Y_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_Y_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_Y_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_F64);
+    }
+
+    if (flags & TS00_Z_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL z vector\n");
+    }
+
+    if (flags & TS00_Z_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 z vector\n");
+        z = psVectorCopy(NULL, zTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_Z_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 z vector\n");
+        z = psVectorCopy(NULL, zTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_Z_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 z vector\n");
+        z = psVectorCopy(NULL, zTruth, PS_TYPE_F64);
+    }
+
+    if (flags & TS00_T_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL t vector\n");
+    }
+
+    if (flags & TS00_T_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 t vector\n");
+        t = psVectorCopy(NULL, tTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_T_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 t vector\n");
+        t = psVectorCopy(NULL, tTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_T_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 t vector\n");
+        t = psVectorCopy(NULL, tTruth, PS_TYPE_F64);
+    }
+
+
+    if (flags & TS00_F_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL f vector\n");
+    }
+
+    if (flags & TS00_F_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F32[numData/4] *= 2.0;
+            f->data.F32[numData/2] *= 2.0;
+            f->data.F32[3*numData/4] *= 2.0;
+        }
+    }
+
+    if (flags & TS00_F_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_S32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.S32[numData/4] *= 2.0;
+            f->data.S32[numData/2] *= 2.0;
+            f->data.S32[3*numData/4] *= 2.0;
+        }
+    }
+
+    if (flags & TS00_F_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F64);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F64[numData/4] *= 2.0;
+            f->data.F64[numData/2] *= 2.0;
+            f->data.F64[3*numData/4] *= 2.0;
+        }
+    }
+
+    if (flags & TS00_FERR_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL fErr vector\n");
+    }
+
+    if (flags & TS00_FERR_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F32[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_S32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.S32[i] = (psS32) YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F64);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F64[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_MASK_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL mask vector\n");
+    }
+
+    if (flags & TS00_MASK_U8) {
+        if (VERBOSE)
+            printf(" using a psU8 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_U8);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.U8[i] = 0;
+        }
+    }
+
+    if (flags & TS00_MASK_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_S32);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.S32[i] = 0;
+        }
+    }
+
+    bool rc = false;
+    if (flags & TS00_CLIP_FIT) {
+        rc = psVectorClipFitPolynomial4D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y, z, t);
+    } else {
+        rc = psVectorFitPolynomial4D(myPoly, mask, MASK_VALUE, f, fErr, x, y, z, t);
+    }
+
+    if (!rc) {
+        if (expectedRC == true) {
+            diag("TEST ERROR: the 4D polynomial fitting function returned NULL.\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            diag("TEST ERROR: the 4D polynomial fitting function returned non-NULL.\n");
+            testStatus = false;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<polyOrderX+1;i++) {
+                for (psS32 j=0;j<polyOrderY+1;j++) {
+                    for (psS32 k=0;k<polyOrderZ+1;k++) {
+                        for (psS32 l=0;l<polyOrderT+1;l++) {
+                            printf("Polynomial coefficient [%d][%d][%d][%d] is %0.1f\n",
+                                   i, j, k, l, myPoly->coeff[i][j][k][l]);
+                        }
+                    }
+                }
+            }
+        }
+
+        psVector *result = psPolynomial4DEvalVector(myPoly, xTruth, yTruth, zTruth, tTruth);
+        for (int i=0;i<numData; i++) {
+            // Skip the outliers.
+            if ((i == numData/4) || (i == numData/2) || (i == 3*numData/4)) {
+                continue;
+            }
+            psF32 expectData = fTruth->data.F64[i];
+            psF32 actualData = result->data.F64[i];
+
+            if (fabs(actualData-expectData) > fabs(ERROR_TOLERANCE * expectData)) {
+                diag("TEST ERROR: Fitted data %d: (%f), expected was (%f)\n",
+                     i, actualData, expectData);
+                testStatus = false;
+            } else {
+                if (EXTRA_VERBOSE) {
+                    printf("GOOD: Fitted data %d: (%.1f), expected was (%.1f)\n",
+                           i, actualData, expectData);
+                }
+            }
+        }
+        psFree(result);
+    }
+
+    psMemCheckCorruption(stderr, false);
+    psFree(myPoly);
+    psFree(mask);
+    psFree(x);
+    psFree(y);
+    psFree(z);
+    psFree(t);
+    psFree(f);
+    psFree(xTruth);
+    psFree(yTruth);
+    psFree(zTruth);
+    psFree(tTruth);
+    psFree(fTruth);
+    psFree(fErr);
+    psFree(stats);
+    psMemCheckCorruption(stderr, false);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    return (testStatus);
+}
+
+/*****************************************************************************
+We test a variety of polynomial fitting routines, types, and polynomial types
+here:
+    F32 tests: Ordinary polys, non-clip fit
+    F64 tests: Ordinary polys, non-clip fit
+    F32 tests: Chebyshev polys, non-clip fit
+    F64 tests: Chebyshev polys, non-clip fit
+    F32 tests: Ordinary polys, clip fit
+    F64 tests: Ordinary polys, clip fit
+    F32 tests: Chebyshev polys, clip fit
+    F64 tests: Chebyshev polys, clip fit
+ *****************************************************************************/
+int main()
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(112);
+
+
+    // psVectorFitPolynomial4D()
+    // Test various erroneous input paramater configurations
+    {
+        psMemId id = psMemGetId();
+        psPolynomial4D *myPoly = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, POLY_ORDER_T);
+        psVector *x = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *xS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *y = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *yS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *z = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *zS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *t = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *tS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *f = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *fS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *mask = psVectorAlloc(NUM_DATA, PS_TYPE_U8);
+        psVector *maskS8 = psVectorAlloc(NUM_DATA, PS_TYPE_S8);
+        psVector *fErr = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *fErrS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+
+
+        // Set psPolynomial4D to NULL, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial4D(NULL, mask, MASK_VALUE, f, fErr, x, y, z, t);
+            ok(rc == false, "psVectorFitPolynomial4D() returned FALSE with NULL psPolynomial4D");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set mask to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial4D(myPoly, maskS8, MASK_VALUE, f, fErr, x, y, z, t);
+            ok(rc == false, "psVectorFitPolynomial4D() returned FALSE with mask set to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set f psVector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial4D(myPoly, mask, MASK_VALUE, fS32, fErr, x, y, z, t);
+            ok(rc == false, "psVectorFitPolynomial4D() returned FALSE: Set f psVector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set fError vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial4D(myPoly, mask, MASK_VALUE, f, fErrS32, x, y, z, t);
+            ok(rc == false, "psVectorFitPolynomial4D() returned FALSE: Set fError vector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set x vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial4D(myPoly, mask, MASK_VALUE, f, fErr, xS32, y, z, t);
+            ok(rc == true, "psVectorFitPolynomial4D() returned TRUE: x vector may be S32");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set y vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial4D(myPoly, mask, MASK_VALUE, f, fErr, x, yS32, z, t);
+            ok(rc == true, "psVectorFitPolynomial4D() returned TRUE: y vector may be S32");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set z vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial4D(myPoly, mask, MASK_VALUE, f, fErr, x, y, zS32, t);
+            ok(rc == true, "psVectorFitPolynomial4D() returned TRUE: z vector may be S32");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set t vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorFitPolynomial4D(myPoly, mask, MASK_VALUE, f, fErr, x, y, z, tS32);
+            ok(rc == true, "psVectorFitPolynomial4D() returned TRUE: t vector may be S32");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect mask psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            mask->n++;
+            bool rc = psVectorFitPolynomial4D(myPoly, mask, MASK_VALUE, f, fErr, x, y, z, t);
+            mask->n--;
+            ok(rc == false, "psVectorFitPolynomial4D() returned FALSE: Incorrect mask psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect f psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            f->n++;
+            bool rc = psVectorFitPolynomial4D(myPoly, mask, MASK_VALUE, f, fErr, x, y, z, t);
+            f->n--;
+            ok(rc == false, "psVectorFitPolynomial4D() returned FALSE: Incorrect f psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect fErr psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            fErr->n++;
+            bool rc = psVectorFitPolynomial4D(myPoly, mask, MASK_VALUE, f, fErr, x, y, z, t);
+            fErr->n--;
+            ok(rc == false, "psVectorFitPolynomial4D() returned FALSE: Incorrect fErr psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect x psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            x->n++;
+            bool rc = psVectorFitPolynomial4D(myPoly, mask, MASK_VALUE, f, fErr, x, y, z, t);
+            x->n--;
+            ok(rc == false, "psVectorFitPolynomial4D() returned FALSE: Incorrect x psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+        psFree(myPoly);
+        psFree(x);
+        psFree(xS32);
+        psFree(y);
+        psFree(yS32);
+        psFree(z);
+        psFree(zS32);
+        psFree(t);
+        psFree(tS32);
+        psFree(f);
+        psFree(fS32);
+        psFree(mask);
+        psFree(maskS8);
+        psFree(fErr);
+        psFree(fErrS32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psVectorClipFitPolynomial4D()
+    // Test various erroneous input paramater configurations
+    {
+        psMemId id = psMemGetId();
+        psPolynomial4D *myPoly = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, POLY_ORDER_T);
+        psVector *x = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *xS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *y = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *yS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *z = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *zS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *t = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *tS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *f = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *fS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psVector *mask = psVectorAlloc(NUM_DATA, PS_TYPE_U8);
+        psVector *maskS8 = psVectorAlloc(NUM_DATA, PS_TYPE_S8);
+        psVector *fErr = psVectorAlloc(NUM_DATA, PS_TYPE_F32);
+        psVector *fErrS32 = psVectorAlloc(NUM_DATA, PS_TYPE_S32);
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+
+
+        // Set psPolynomial4D to NULL, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial4D(NULL, stats, mask, MASK_VALUE, f, fErr, x, y, z, t);
+            ok(rc == false, "psVectorClipFitPolynomial4D() returned FALSE with NULL psPolynomial4D");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set psStats to NULL, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial4D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y, z, t);
+            ok(rc == false, "psVectorClipFitPolynomial4D() returned FALSE with NULL psStats");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set mask to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial4D(myPoly, stats, maskS8, MASK_VALUE, f, fErr, x, y, z, t);
+            ok(rc == false, "psVectorClipFitPolynomial4D() returned FALSE with mask set to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set f psVector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial4D(myPoly, stats, mask, MASK_VALUE, fS32, fErr, x, y, z, t);
+            ok(rc == false, "psVectorClipFitPolynomial4D() returned FALSE: Set f psVector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set fError vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial4D(myPoly, stats, mask, MASK_VALUE, f, fErrS32, x, y, z, t);
+            ok(rc == false, "psVectorClipFitPolynomial4D() returned FALSE: Set fError vector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set x vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial4D(myPoly, stats, mask, MASK_VALUE, f, fErr, xS32, y, z, t);
+            ok(rc == false, "psVectorClipFitPolynomial4D() returned FALSE: Set x vector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set y vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial4D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, yS32, z, t);
+            ok(rc == false, "psVectorClipFitPolynomial4D() returned FALSE: Set y vector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set z vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial4D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y, zS32, t);
+            ok(rc == false, "psVectorClipFitPolynomial4D() returned FALSE: Set z vector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Set t vector to incorrect type, should cause error
+        {
+            psMemId id = psMemGetId();
+            bool rc = psVectorClipFitPolynomial4D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y, z, tS32);
+            ok(rc == false, "psVectorClipFitPolynomial4D() returned FALSE: Set t vector to incorrect type");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect mask psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            mask->n++;
+            bool rc = psVectorClipFitPolynomial4D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y, z, t);
+            mask->n--;
+            ok(rc == false, "psVectorClipFitPolynomial4D() returned FALSE: Incorrect mask psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect f psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            f->n++;
+            bool rc = psVectorClipFitPolynomial4D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y, z, t);
+            f->n--;
+            ok(rc == false, "psVectorClipFitPolynomial4D() returned FALSE: Incorrect f psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect fErr psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            fErr->n++;
+            bool rc = psVectorClipFitPolynomial4D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y, z, t);
+            fErr->n--;
+            ok(rc == false, "psVectorClipFitPolynomial4D() returned FALSE: Incorrect fErr psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Incorrect x psVector size, should cause error
+        {
+            psMemId id = psMemGetId();
+            x->n++;
+            bool rc = psVectorClipFitPolynomial4D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y, z, t);
+            x->n--;
+            ok(rc == false, "psVectorClipFitPolynomial4D() returned FALSE: Incorrect x psVector size");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+        psFree(myPoly);
+        psFree(x);
+        psFree(xS32);
+        psFree(y);
+        psFree(yS32);
+        psFree(z);
+        psFree(zS32);
+        psFree(t);
+        psFree(tS32);
+        psFree(f);
+        psFree(fS32);
+        psFree(mask);
+        psFree(maskS8);
+        psFree(fErr);
+        psFree(fErrS32);
+        psFree(stats);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    
+    //
+    // F32 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit");
+
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_NULL
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_NULL | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F64
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+
+    //
+    // F64 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_NULL
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_NULL | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F32
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+
+    //
+    // F32 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+
+    // XXX: These tests are failing; they shouldn't be.
+    /*
+        ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                                  | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                                  POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit");
+        // Some Vectors NULL
+        ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                                  | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                                  POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    */
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_NULL
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_NULL | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F64
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+
+    //
+    // F64 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_NULL
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_NULL | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F32
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+}
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomial.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomial.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomial.c	(revision 22158)
@@ -0,0 +1,358 @@
+/** tst_Func00.c
+*
+*    This routine must ensure that the psPolynomial structures are
+*    allocated and deallocated by the psPolynomialXXXlloc() procedures.
+*    It also calls the various psPolynomialXXXEval() procedures.
+*
+*    The F32 and F64 polynomials are tested for all orders (1 - 4) and for
+*    both ordinary and chebyshev polynomials.
+*
+*    NOTE: This test code requries the stdout file to verify that the results
+*    are good.
+*
+*    XXX: Modify these tests so that polynomials with a variety of different
+*    orders are created.
+* 
+*    XXX: Compare to FLT_EPSILON
+* 
+*    @version $Revision: 1.5 $  $Name: not supported by cvs2svn $
+*    @date $Date: 2008-05-05 00:09:04 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*
+*****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define ORDER    3
+#define VERBOSE  0
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(59);
+
+    // This test will allocate a 1D polynomial and verify the structure allocated
+    {
+        psMemId id = psMemGetId();
+        psPolynomial1D* my1DPoly  = NULL;
+
+        // Allocate polynomial
+        my1DPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, ORDER);
+        ok(my1DPoly != NULL, "1D polynomial allocated successfully");
+        skip_start(my1DPoly == NULL, 3, "Skipping tests because psPolynomial1DAlloc() failed");
+
+        // Verify polynomial structure members set properly
+        ok(my1DPoly->nX == ORDER, "psPolynomial1DAlloc(): Number of terms set correctly");
+        ok(my1DPoly->type == PS_POLYNOMIAL_ORD, "psPolynomial1DAlloc():  type set correctly");
+        bool errorFlag = false;
+        for(psS32 i = 0; i < ORDER+1; i++)
+        {
+            if (my1DPoly->coeff[i] != 0.0) {
+                diag("Coeff[%d] %lg not as expected %lg", i, my1DPoly->coeff[i], 0.0);
+                errorFlag = true;
+            }
+            if (my1DPoly->coeffErr[i] != 0.0) {
+                diag("CoeffErr[%d] %lg not as expected %lg", i, my1DPoly->coeffErr[i], 0.0);
+                errorFlag = true;
+            }
+            if (my1DPoly->coeffMask[i] != 0) {
+                diag("Mask[%d] %d not as expected %d", i, my1DPoly->coeffMask[i], 0);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial1D coefficients set correctly");
+
+        skip_end();
+        psFree(my1DPoly);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // This test will allocate a Chebyshev 1D polynomial and verify the structure allocated
+    {
+        psMemId id = psMemGetId();
+        psPolynomial1D* my1DPoly  = NULL;
+        my1DPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_CHEB, ORDER);
+        ok(my1DPoly != NULL, "Chebyshev 1D polynomial allocated successfully");
+        skip_start(my1DPoly == NULL, 1, "Skipping tests because psPolynomial1DAlloc() failed");
+        ok(my1DPoly->type == PS_POLYNOMIAL_CHEB, "psPolynomial1DAlloc(): Chebyshev  type set correctly");
+        skip_end();
+        psFree(my1DPoly);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to allocate with negative order
+    // Following should generate error msg for negative terms
+    if (1) {
+        psMemId id = psMemGetId();
+        ok(psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, -1) == NULL,
+          "psPolynomial1DAlloc() returned NULL with negative polynomial order");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Allocate polynomial with unallowable type
+    {
+        psMemId id = psMemGetId();
+        psPolynomial1D* polyOrd = psPolynomial1DAlloc(99, ORDER);
+        ok(polyOrd==NULL, "psPolynomial1DAlloc() returned NULL with unallowed type");
+        psFree(polyOrd);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // This test will allocate a 2D polynomial and verify the structure allocated
+    {
+        psMemId id = psMemGetId();
+        psPolynomial2D* my2DPoly = NULL;
+
+        // Allocate polynomial
+        my2DPoly = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, ORDER,ORDER+1);
+        ok(my2DPoly != NULL, "2D polynomial allocated successfully");
+        skip_start(my2DPoly == NULL, 4, "Skipping tests because psPolynomial2DAlloc() failed");
+
+        // Verify polynomial structure members set properly
+        ok(my2DPoly->nX == ORDER, "psPolynomial2DAlloc(): Number of terms (nX) set correctly");
+        ok(my2DPoly->nY == ORDER+1, "psPolynomial2DAlloc(): Number of terms (nY) set correctly");
+        ok(my2DPoly->type == PS_POLYNOMIAL_ORD, "psPolynomial2DAlloc(): type set correctly");
+
+        bool errorFlag = false;
+        for(psS32 i = 0; i < ORDER+1; i++)
+        {
+            for(psS32 j = 0; j < ORDER+2; j++) {
+                if (fabs(my2DPoly->coeff[i][j]) > FLT_EPSILON) {
+                    diag("Coeff[%d][%d] %lg not as expected %lg", i, j, my2DPoly->coeff[i][j], 0.0);
+                    errorFlag = true;
+                }
+                if (my2DPoly->coeffErr[i][j] != 0.0) {
+                    diag("CoeffErr[%d][%d] %lg not as expected %lg", i, j, my2DPoly->coeffErr[i][j], 0.0);
+                    errorFlag = true;
+                }
+                if (my2DPoly->coeffMask[i][j] != 0) {
+                    diag("Mask[%d][%d] %d not as expected %d", i, j, my2DPoly->coeffMask[i][j], 0);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psPolynomial2D coefficients set correctly");
+        skip_end();
+        psFree(my2DPoly);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // This test will allocate a Chebyshev 2D polynomial and verify the structure allocated
+    {
+        psMemId id = psMemGetId();
+        psPolynomial2D* my2DPoly = NULL;
+        my2DPoly = psPolynomial2DAlloc(PS_POLYNOMIAL_CHEB, ORDER,ORDER+1);
+        ok(my2DPoly != NULL, "Chebyshev 2D polynomial allocated successfully");
+        skip_start(my2DPoly == NULL, 1, "Skipping tests because psPolynomial2DAlloc() failed");
+        skip_end();
+        psFree(my2DPoly);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to allocate with negative order
+    // Following should generate error msg for negative terms
+    if (1) {
+        psMemId id = psMemGetId();
+        ok(psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, -1, 1) == NULL, 
+          "psPolynomial2DAlloc() returned NULL with negative polynomial order");
+        ok(psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 1, -1) == NULL,
+          "psPolynomial2DAlloc() returned NULL with negative polynomial order");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Allocate polynomial with unallowed type
+    {
+        psMemId id = psMemGetId();
+        psPolynomial2D* polyOrd = psPolynomial2DAlloc(99, ORDER, ORDER);
+        ok(polyOrd == NULL, "psPolynomial2DAlloc() returned NULL with unallowed tpye");
+        psFree(polyOrd);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // This test will allocate a 3D polynomial and verify the structure allocated
+    {
+        psMemId id = psMemGetId();
+        psPolynomial3D* my3DPoly = NULL;
+
+        // Allocate polynomial
+        my3DPoly = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, ORDER, ORDER+1, ORDER+2);
+        ok(my3DPoly != NULL, "3D polynomial allocated successfully");
+        skip_start(my3DPoly == NULL, 5, "Skipping tests because psPolynomial3DAlloc() failed");
+
+        // Verify polynomial structure members set properly
+        ok(my3DPoly->nX == ORDER, "psPolynomial3DAlloc(): Number of terms (nX) set correctly");
+        ok(my3DPoly->nY == ORDER+1, "psPolynomial3DAlloc(): Number of terms (nY) set correctly");
+        ok(my3DPoly->nZ == ORDER+2, "psPolynomial3DAlloc(): Number of terms (nZ) set correctly");
+        ok(my3DPoly->type == PS_POLYNOMIAL_ORD, "psPolynomial3DAlloc(): type set correctly");
+
+        bool errorFlag = false;
+        for(psS32 i = 0; i < ORDER+1; i++)
+        {
+            for(psS32 j = 0; j < ORDER+2; j++) {
+                for(psS32 k = 0; k < ORDER+3; k++) {
+                    if (my3DPoly->coeff[i][j][k] != 0.0) {
+                        diag("Coeff[%d][%d][%d] %lg not as expected %lg",
+                             i, j, k, my3DPoly->coeff[i][j][k], 0.0);
+                        errorFlag = true;
+                    }
+                    if (my3DPoly->coeffErr[i][j][k] != 0.0) {
+                        diag("CoeffErr[%d][%d][%d] %lg not as expected %lg",
+                             i, j, k, my3DPoly->coeffErr[i][j][k], 0.0);
+                        errorFlag = true;
+                    }
+                    if (my3DPoly->coeffMask[i][j][k] != 0) {
+                        diag("Mask[%d][%d][%d] %d not as expected %d",
+                             i, j, k, my3DPoly->coeffMask[i][j][k], 0);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+        ok(!errorFlag, "psPolynomial3D coefficients set correctly");
+        skip_end();
+        psFree(my3DPoly);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // This test will allocate a Chebyshev 3D polynomial and verify the structure allocated
+    {
+        psMemId id = psMemGetId();
+        psPolynomial3D* my3DPoly = NULL;
+        my3DPoly = psPolynomial3DAlloc(PS_POLYNOMIAL_CHEB, ORDER, ORDER+1, ORDER+2);
+        ok(my3DPoly != NULL, "Chebyshev 3D polynomial allocated successfully");
+        skip_start(my3DPoly == NULL, 1, "Skipping tests because psPolynomial2DAlloc() failed");
+        ok(my3DPoly->type == PS_POLYNOMIAL_CHEB, "psPolynomial3DAlloc(): Chebyshev type set correctly");
+        skip_end();
+        psFree(my3DPoly);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to allocate with negative order
+    // Following should generate error msg for negative terms
+    if (1) {
+        psMemId id = psMemGetId();
+        ok(psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, -1, 1, 1) == NULL, 
+          "psPolynomial3DAlloc() returned NULL with negative polynomial order");
+        ok(psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, 1, -1, 1) == NULL, 
+          "psPolynomial3DAlloc() returned NULL with negative polynomial order");
+        ok(psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, 1, 1, -1) == NULL,
+          "psPolynomial3DAlloc() returned NULL with negative polynomial order");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Allocate polynomial with unallowed type
+    {
+        psMemId id = psMemGetId();
+        psPolynomial3D* polyOrd = psPolynomial3DAlloc(99, ORDER, ORDER, ORDER);
+        ok(polyOrd == NULL, "psPolynomial3DAlloc() returned NULL with unallowed type");
+        psFree(polyOrd);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+
+    }
+
+
+    // This test will allocate a 4D polynomial and verify the structure allocated
+    {
+        psMemId id = psMemGetId();
+        psPolynomial4D* my4DPoly = NULL;
+
+        // Allocate polynomial
+        my4DPoly = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, ORDER,ORDER+1,ORDER+2,ORDER+3);
+        ok(my4DPoly != NULL, "4D polynomial allocated successfully");
+        skip_start(my4DPoly == NULL, 6, "Skipping tests because psPolynomial4DAlloc() failed");
+
+        // Verify polynomial structure members set properly
+        ok(my4DPoly->nX == ORDER, "psPolynomial4DAlloc(): Number of terms (nX) set correctly");
+        ok(my4DPoly->nY == ORDER+1, "psPolynomial4DAlloc(): Number of terms (nY) set correctly");
+        ok(my4DPoly->nZ == ORDER+2, "psPolynomial4DAlloc(): Number of terms (nZ) set correctly");
+        ok(my4DPoly->nT == ORDER+3, "psPolynomial4DAlloc(): Number of terms (nT) set correctly");
+        ok(my4DPoly->type == PS_POLYNOMIAL_ORD, "psPolynomial4D    Alloc(): type set correctly");
+
+        bool errorFlag = false;
+        for(psS32 i = 0; i < ORDER+1; i++)
+        {
+            for(psS32 j = 0; j < ORDER+2; j++) {
+                for(psS32 k = 0; k < ORDER+3; k++) {
+                    for(psS32 l = 0; l < ORDER+4; l++) {
+                        if (my4DPoly->coeff[i][j][k][l] != 0.0) {
+                            diag("Coeff[%d][%d][%d][%d] %lg not as expected %lg",
+                                 i, j, k, l, my4DPoly->coeff[i][j][k][l], 0.0);
+                            errorFlag = true;
+                        }
+                        if (my4DPoly->coeffErr[i][j][k][l] != 0.0) {
+                            diag("CoeffErr[%d][%d][%d][%d] %lg not as expected %lg",
+                                 i, j, k, l, my4DPoly->coeffErr[i][j][k][l], 0.0);
+                            errorFlag = true;
+                        }
+                        if (my4DPoly->coeffMask[i][j][k][l] != 0) {
+                            diag("Mask[%d][%d][%d][%d] %d not as expected %d",
+                                 i, j, k, l, my4DPoly->coeffMask[i][j][k][l], 0);
+                            errorFlag = true;
+                        }
+                    }
+                }
+            }
+        }
+        ok(!errorFlag, "psPolynomial4D coefficients set correctly");
+        skip_end();
+        psFree(my4DPoly);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // This test will allocate a Chebyshev 4D polynomial and verify the structure allocated
+    {
+        psMemId id = psMemGetId();
+        psPolynomial4D* my4DPoly = NULL;
+        my4DPoly = psPolynomial4DAlloc(PS_POLYNOMIAL_CHEB, ORDER,ORDER+1,ORDER+2,ORDER+3);
+        ok(my4DPoly != NULL, "Chebyshev 4D polynomial allocated successfully");
+        skip_start(my4DPoly == NULL, 1, "Skipping tests because psPolynomial4DAlloc() failed");
+        ok(my4DPoly->type == PS_POLYNOMIAL_CHEB, "psPolynomial4DAlloc(): Chebyshev type set correctly");
+        skip_end();
+        psFree(my4DPoly);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to allocate with negative order
+    // Following should generate error msg for negative terms
+    if (1) {
+        psMemId id = psMemGetId();
+        ok(psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, -1, 1, 1, 1) == NULL, 
+          "psPolynomial4DAlloc() returned NULL with negative polynomial order");
+        ok(psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, 1, -1, 1, 1) == NULL, 
+          "psPolynomial4DAlloc() returned NULL with negative polynomial order");
+        ok(psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, 1, 1, -1, 1) == NULL,
+          "psPolynomial4DAlloc() returned NULL with negative polynomial order");
+        ok(psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, 1, 1, 1, -1) == NULL,
+          "psPolynomial4DAlloc() returned NULL with negative polynomial order");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Allocate polynomial with unallowed type
+    {
+        psMemId id = psMemGetId();
+        psPolynomial4D* polyOrd = psPolynomial4DAlloc(99, ORDER, ORDER, ORDER, ORDER);
+        ok(polyOrd == NULL, "psPolynomial4DAlloc() returned NULL with unallowed type");
+        psFree(polyOrd);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomialEval1D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomialEval1D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomialEval1D.c	(revision 22158)
@@ -0,0 +1,246 @@
+/**
+*
+*  This test driver will exercise the psPolynomialXDEval functions for both
+*  ORD and CHEB type polynomials.
+*
+*  @version  $Revision: 1.10 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2008-05-05 00:09:04 $
+*
+*  XXX: Probably should test single- and multi-dimensional polynomials in
+*  which one diminsion is constant (n == 1).
+*
+*  XXX: define ORDERS, not TERMS
+*
+*
+* Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*
+***************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define TERMS        4
+#define TESTPOINTS   5
+#define ERROR_TOL    0.001
+
+psF32 poly1DCoeff[TERMS]        = { -4.3, 2.3, -3.2, 1.9};
+psF64 Dpoly1DCoeff[TERMS]        = { -4.3, 2.3, -3.2, 1.9};
+psF32 poly1DMask[TERMS]         = {    0,   0,    1,   0  };
+
+psF32 poly1DXValue[TESTPOINTS]   = { 2.550000,    -9.8000,   0.00134,   -12.2500,   0.000};
+psF64 Dpoly1DXValue[TESTPOINTS]  = { 2.550000,    -9.8000,   0.00134,   -12.2500,   0.000};
+psF32 poly1DXResult[TESTPOINTS]  = {33.069613, -1815.1048, -4.296918, -3525.1797, -4.3000};
+psF64 Dpoly1DXResult[TESTPOINTS] = {33.069613, -1815.1048, -4.296918, -3525.1797, -4.3000};
+
+psF32 poly1DXChebValue[TESTPOINTS]   = { -0.99,    -0.33,     0.125,    0.564,    0.875};
+psF64 Dpoly1DXChebValue[TESTPOINTS]  = { -0.99,    -0.33,     0.125,    0.564,    0.875};
+psF32 poly1DXChebResult[TESTPOINTS]  = { -1.401196, 1.016252, 0.257813, 0.089625, 1.429688};
+psF64 Dpoly1DXChebResult[TESTPOINTS] = { -1.401196, 1.016252, 0.257813, 0.089625, 1.429688};
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(28);
+
+
+    // Evaluate a NULL polynomial
+    {
+        psMemId id = psMemGetId();
+        psF64 result = psPolynomial1DEval(NULL, 0.0);
+        ok(isnan(result), "psPolynomial1DEval() returned NAN with NULL psPolynomial");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Allocate and evaluate an ordinary polynomial structure
+    {
+        psMemId id = psMemGetId();
+
+        // Allocate polynomial structure
+        psPolynomial1D* polyOrd = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, TERMS-1);
+        ok(polyOrd != NULL, "Ordinary psPolynomial1D successfully allocated");
+        skip_start(polyOrd == NULL, 1, "Skipping tests because psPolynomial1DAlloc() failed");
+
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++) {
+            polyOrd->coeff[i] = poly1DCoeff[i];
+            polyOrd->coeffMask[i]  = poly1DMask[i];
+        }
+
+        // Evaluate test points and verify results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++) {
+            psF64 result = psPolynomial1DEval(polyOrd,poly1DXValue[i]);
+            if (fabs(poly1DXResult[i]-result) > ERROR_TOL ) {
+                diag("Evaluated value %g not as expected %g", result, poly1DXResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial1DEval() successful (Ordinary)");
+        skip_end();
+        psFree(polyOrd);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Allocate Cheby polynomial structure
+    {
+        bool errorFlag = false;
+        psMemId id = psMemGetId();
+        psPolynomial1D*  polyCheb = psPolynomial1DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1);
+        ok(polyCheb != NULL, "Chebyshev psPolynomial1D successfully allocated");
+        skip_start(polyCheb == NULL, 1, "Skipping tests because psPolynomial1DAlloc() failed");
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            polyCheb->coeff[i] = 1.0;
+            polyCheb->coeffMask[i]  = poly1DMask[i];
+        }
+        // Evaluate test points and verify results
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            psF64 resultCheb = psPolynomial1DEval(polyCheb,poly1DXChebValue[i]);
+            if (fabs(poly1DXChebResult[i]-resultCheb) > ERROR_TOL ) {
+                diag("Evaluated value %g not as expected %g", resultCheb, poly1DXChebResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial1DEval() successful (Chebyshev)");
+        skip_end();
+        psFree(polyCheb);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Allocate polynomial, test the psPolynomial1DEvalVector() routines
+    {
+        psMemId id = psMemGetId();
+        // Create input vectors
+        psVector* inputOrd = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            inputOrd->data.F64[i] = poly1DXValue[i];
+            inputOrd->n++;
+        }
+
+        psPolynomial1D* polyOrd = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, TERMS-1);
+        ok(polyOrd != NULL, "Ordinary polynomial allocation successful");
+        skip_start(polyOrd == NULL, 6, "Skipping tests because psPolynomial1DAlloc() failed");
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            polyOrd->coeff[i] = poly1DCoeff[i];
+            polyOrd->coeffMask[i]  = poly1DMask[i];
+        }
+
+        // Evaluate the vectors
+        psVector* outputOrd = psPolynomial1DEvalVector(polyOrd, inputOrd);
+        ok(outputOrd != NULL, "psPolynomial1DEvalVector() generated non-NULL psVector");
+        ok(outputOrd->type.type == PS_TYPE_F64, "psPolynomial1DEvalVector() generated correct output type");
+
+        // Verify the results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            if (fabs(poly1DXResult[i]-outputOrd->data.F64[i]) > ERROR_TOL) {
+                diag("Result[%d] %lg not equal to expected %lg",
+                     i, outputOrd->data.F64[i], poly1DXResult[i]);
+                errorFlag = TRUE;
+            }
+        }
+        ok(!errorFlag, "psPolynomial1DEvalVector() produced the correct answers");
+
+        // Attempt to invoke function with NULL polynomial
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial1DEvalVector(NULL, inputOrd) == NULL, "psPolynomial1DEvalVector() produced NULL when called with NULL polynomial");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial1DEvalVector(polyOrd, NULL) == NULL, "psPolynomial1DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputOrd->type.type = PS_TYPE_U8;
+            ok(psPolynomial1DEvalVector(polyOrd,inputOrd) == NULL, "psPolynomial1DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+        psFree(outputOrd);
+        skip_end();
+        psFree(inputOrd);
+        psFree(polyOrd);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Allocate polynomial, test the psPolynomial1DEvalVector() routines (Chebyshev)
+    {
+        psMemId id = psMemGetId();
+        // Create input vectors
+        psVector* inputCheb = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            inputCheb->data.F64[i] = poly1DXChebValue[i];
+            inputCheb->n++;
+        }
+
+        psPolynomial1D* polyCheb = psPolynomial1DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1);
+        ok(polyCheb != NULL, "Ordinary polynomial allocation successful");
+        skip_start(polyCheb == NULL, 5, "Skipping tests because psPolynomial1DAlloc() failed");
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            polyCheb->coeff[i] = 1.0;
+            polyCheb->coeffMask[i]  = poly1DMask[i];
+        }
+
+        // Evaluate the vectors
+        psVector* outputCheb = psPolynomial1DEvalVector(polyCheb, inputCheb);
+        ok(outputCheb != NULL, "psPolynomial1DEvalVector() generated non-NULL psVector");
+        ok(outputCheb->type.type == PS_TYPE_F64, "psPolynomial1DEvalVector() generated correct output type");
+
+        // Verify the results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            if (fabs(poly1DXChebResult[i]-outputCheb->data.F64[i]) > ERROR_TOL) {
+                diag("ResultCheb[%d] %lg not equal to expected %lg",
+                     i, outputCheb->data.F64[i], poly1DXChebResult[i]);
+                errorFlag = TRUE;
+            }
+        }
+        ok(!errorFlag, "psPolynomial1DEvalVector() produced the correct answers");
+
+
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial1DEvalVector(polyCheb,NULL) == NULL, "psPolynomial1DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputCheb->type.type = PS_TYPE_U8;
+            ok(psPolynomial1DEvalVector(polyCheb,inputCheb) == NULL, "psPolynomial1DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        psFree(outputCheb);
+        skip_end();
+        psFree(inputCheb);
+        psFree(polyCheb);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    return exit_status();
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomialEval2D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomialEval2D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomialEval2D.c	(revision 22158)
@@ -0,0 +1,341 @@
+/** tap_psPolynomialEval2D.c
+*
+*  This test driver will exercise the psPolynomialXDEval functions for both
+*  ORD and CHEB type polynomials.
+*
+*  @version  $Revision: 1.8 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2008-05-05 00:09:04 $
+*
+* Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*
+***************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define  TERMS        4
+#define  TESTPOINTS   5
+#define  ERROR_TOL    0.001
+
+psF32 poly2DCoeff[TERMS][TERMS]   = {  { -4.3,  2.3, -3.2,  1.9},
+                                       {  1.2,  0.7, -0.3,  1.3},
+                                       {  0.4, -2.9,  0.8, -3.1},
+                                       { -1.1,  2.1,  1.9,  0.6}
+                                    };
+psF64 Dpoly2DCoeff[TERMS][TERMS]  = {  { -4.3,  2.3, -3.2,  1.9},
+                                       {  1.2,  0.7, -0.3,  1.3},
+                                       {  0.4, -2.9,  0.8, -3.1},
+                                       { -1.1,  2.1,  1.9,  0.6}
+                                    };
+psF32 poly2DMask[TERMS][TERMS]    = {  {  0,    0,    0,    1},
+                                       {  0,    0,    1,    0},
+                                       {  1,    0,    0,    0},
+                                       {  0,    0,    0,    1}
+                                    };
+
+psF32 poly2DXYValue[TESTPOINTS][2] = {  {  1.40,  0.55},
+                                        { -0.55,  1.40},
+                                        {  0.00,  2.34},
+                                        { -0.88,  0.00},
+                                        {  3.45, -0.78}
+                                     };
+psF32 Dpoly2DXYValue[TESTPOINTS][2] = {  {  1.40,  0.55},
+                                      { -0.55,  1.40},
+                                      {  0.00,  2.34},
+                                      { -0.88,  0.00},
+                                      {  3.45, -0.78}
+                                      };
+psF32 poly2DResult[TESTPOINTS] = {  -3.415938, -14.765687, -16.43992, -4.606381, -22.650702 };
+psF64 Dpoly2DResult[TESTPOINTS] = {  -3.415938, -14.765687, -16.43992, -4.606381, -22.650702 };
+
+psF32 poly2DXYChebValue[TESTPOINTS][2] = {  {  0.500,  0.500},
+        {  0.000,  0.250},
+        { -0.250,  0.000},
+        {  0.990,  0.150},
+        {  0.333, -0.666}
+                                         };
+psF32 Dpoly2DXYChebValue[TESTPOINTS][2] = {  {  0.500,  0.500},
+        {  0.000,  0.250},
+        { -0.250,  0.000},
+        {  0.990,  0.150},
+        {  0.333, -0.666}
+                                          };
+psF32 poly2DChebResult[TESTPOINTS] = {  0.750000, 1.687500, 0.625000, -0.113040, 0.386786 };
+psF32 Dpoly2DChebResult[TESTPOINTS] = {  0.750000, 1.687500, 0.625000, -0.113040, 0.386786 };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(38);
+
+
+    // Evaluate a NULL polynomial
+    {
+        psMemId id = psMemGetId();
+        psF64 result = psPolynomial2DEval(NULL, 0.0, 0.0);
+        ok(isnan(result), "psPolynomial2DEval() returned NAN with NULL psPolynomial");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Allocate and evaluate an ordinary polynomial structure
+    {
+        psMemId id = psMemGetId();
+
+        // Allocate polynomial structure
+        psPolynomial2D*  polyOrd = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, TERMS-1, TERMS-1);
+        ok(polyOrd != NULL, "Ordinary psPolynomial2D successfully allocated");
+        skip_start(polyOrd == NULL, 1, "Skipping tests because psPolynomial2DAlloc() failed");
+
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                polyOrd->coeff[i][j] = poly2DCoeff[i][j];
+                polyOrd->coeffMask[i][j]  = poly2DMask[i][j];
+            }
+        }
+
+        // Evaluate test points and verify results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            psF64 result = psPolynomial2DEval(polyOrd,Dpoly2DXYValue[i][0],Dpoly2DXYValue[i][1]);
+            if (fabs(Dpoly2DResult[i]-result) > ERROR_TOL ) {
+                diag("TEST ERROR: Evaluated value %f, should be %f\n", result, Dpoly2DResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial2DEval() successful (Ordinary)");
+        skip_end();
+        psFree(polyOrd);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Allocate and evaluate Cheby polynomial structure
+    {
+        psMemId id = psMemGetId();
+
+        // Allocate polynomial structure
+        psPolynomial2D*  polyCheb = psPolynomial2DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1, TERMS-1);
+        ok(polyCheb != NULL, "Cheby psPolynomial2D successfully allocated");
+        skip_start(polyCheb == NULL, 1, "Skipping tests because psPolynomial2DAlloc() failed");
+
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                polyCheb->coeff[i][j] = 1.0;
+                polyCheb->coeffMask[i][j]  = poly2DMask[i][j];
+            }
+        }
+
+        // Evaluate test points and verify results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            psF64 resultCheb = psPolynomial2DEval(polyCheb,Dpoly2DXYChebValue[i][0],Dpoly2DXYChebValue[i][1]);
+            if (fabs(Dpoly2DChebResult[i]-resultCheb) > ERROR_TOL ) {
+                diag("TEST ERROR: Evaluated value %f, should be %f\n", resultCheb, Dpoly2DChebResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial2DEval() successful (Chebyshev)");
+        skip_end();
+        psFree(polyCheb);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Allocate polynomial, test the psPolynomial2DEvalVector() routines
+    {
+        psMemId id = psMemGetId();
+        // Create input vectors
+        psVector* inputOrdX  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputOrdY  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            inputOrdX->data.F64[i]  = poly2DXYValue[i][0];
+            inputOrdY->data.F64[i]  = poly2DXYValue[i][1];
+            inputOrdX->n++;
+            inputOrdY->n++;
+        }
+
+        psPolynomial2D* polyOrd = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, TERMS-1, TERMS-1);
+        ok(polyOrd != NULL, "Ordinary polynomial allocation successful");
+        skip_start(polyOrd == NULL, 8, "Skipping tests because psPolynomial2DAlloc() failed");
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                polyOrd->coeff[i][j] = poly2DCoeff[i][j];
+                polyOrd->coeffMask[i][j]  = poly2DMask[i][j];
+            }
+        }
+
+        // Evaluate the vectors
+        psVector* outputOrd = psPolynomial2DEvalVector(polyOrd, inputOrdX, inputOrdY);
+        ok(outputOrd != NULL, "psPolynomial2DEvalVector() generated non-NULL psVector");
+        ok(outputOrd->type.type == PS_TYPE_F64, "psPolynomial2DEvalVector() generated correct type");
+
+        // Verify the results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            if (fabs(poly2DResult[i]-outputOrd->data.F64[i]) > ERROR_TOL) {
+                diag("TEST ERROR: Result[%d] %lg not equal to expected %lg.\n",
+                     i, outputOrd->data.F64[i], poly2DResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial2DEvalVector() produced the correct answers");
+
+
+        // Attempt to invoke function with NULL polynomial
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial2DEvalVector(NULL, inputOrdX, inputOrdY) == NULL, "psPolynomial2DEvalVector() produced NULL when called with NULL polynomial");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial2DEvalVector(polyOrd,NULL,inputOrdY) == NULL, "psPolynomial2DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+    
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial2DEvalVector(polyOrd,inputOrdX,NULL) == NULL, "psPolynomial2DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+    
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputOrdX->type.type = PS_TYPE_U8;
+            ok(psPolynomial2DEvalVector(polyOrd,inputOrdX,inputOrdY) == NULL, "psPolynomial2DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+        inputOrdX->type.type = PS_TYPE_F64;
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputOrdY->type.type = PS_TYPE_U8;
+            ok(psPolynomial2DEvalVector(polyOrd,inputOrdX, inputOrdY) == NULL, "psPolynomial2DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+        psFree(outputOrd);
+        skip_end();
+        psFree(inputOrdX);
+        psFree(inputOrdY);
+        psFree(polyOrd);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+
+    }
+
+
+    // Allocate polynomial, test the psPolynomial2DEvalVector() routines
+    {
+        psMemId id = psMemGetId();
+        // Create input vectors
+        psVector* inputChebX = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputChebY = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            inputChebX->data.F64[i] = poly2DXYChebValue[i][0];
+            inputChebY->data.F64[i] = poly2DXYChebValue[i][1];
+            inputChebX->n++;
+            inputChebY->n++;
+        }
+
+        psPolynomial2D* polyCheb = psPolynomial2DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1, TERMS-1);
+        ok(polyCheb != NULL, "Cheby polynomial allocation successful");
+        skip_start(polyCheb == NULL, 8, "Skipping tests because psPolynomial2DAlloc() failed");
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                polyCheb->coeff[i][j] = 1.0;
+                polyCheb->coeffMask[i][j]  = poly2DMask[i][j];
+            }
+        }
+
+        // Evaluate the vectors
+        psVector* outputCheb = psPolynomial2DEvalVector(polyCheb, inputChebX, inputChebY);
+        ok(outputCheb != NULL, "psPolynomial2DEvalVector() generated non-NULL psVector");
+        ok(outputCheb->type.type == PS_TYPE_F64, "psPolynomial2DEvalVector() generated correct type");
+
+
+        // Verify the results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            if (fabs(poly2DChebResult[i]-outputCheb->data.F64[i]) > ERROR_TOL) {
+                diag("TEST ERROR: ResultCheb[%d] %lg not equal to expected %lg.\n",
+                     i, outputCheb->data.F64[i], poly2DChebResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial2DEvalVector() produced the correct answers");
+
+        // Attempt to invoke function with NULL polynomial
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial2DEvalVector(NULL, inputChebX, inputChebY) == NULL, "psPolynomial2DEvalVector() produced NULL when called with NULL polynomial");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial2DEvalVector(polyCheb,NULL,inputChebY) == NULL, "psPolynomial2DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial2DEvalVector(polyCheb,inputChebX,NULL) == NULL, "psPolynomial2DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputChebX->type.type = PS_TYPE_U8;
+            ok(psPolynomial2DEvalVector(polyCheb,inputChebX,inputChebY) == NULL, "psPolynomial2DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        inputChebX->type.type = PS_TYPE_F64;
+
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputChebY->type.type = PS_TYPE_U8;
+            ok(psPolynomial2DEvalVector(polyCheb,inputChebX, inputChebY) == NULL, "psPolynomial2DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+        psFree(outputCheb);
+        skip_end();
+        psFree(inputChebX);
+        psFree(inputChebY);
+        psFree(polyCheb);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomialEval3D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomialEval3D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomialEval3D.c	(revision 22158)
@@ -0,0 +1,447 @@
+/** tap_psPolynomialEval3D.c
+*
+*  This test driver will exercise the psPolynomialXDEval functions for both
+*  ORD and CHEB type polynomials.
+*
+*  @version  $Revision: 1.9 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2008-05-05 00:09:04 $
+*
+* Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*
+***************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define  TERMS        4
+#define  TESTPOINTS   5
+#define  ERROR_TOL    0.001
+
+psF32 poly3DCoeff[TERMS][TERMS][TERMS] = {  { { -1.1,  1.2, -1.3,  1.4},
+        {  1.5, -1.6,  1.7, -1.8},
+        {  0.1, -0.2,  0.3, -0.4},
+        { -0.5,  0.6, -0.7,  0.8}
+                                            },
+        { { -2.1,  2.2, -2.3,  2.4},
+          {  2.5, -2.6,  2.7, -2.8},
+          {  3.1, -3.2,  3.3, -3.4},
+          { -3.5,  3.6, -3.7,  3.8}
+        },
+        { { -4.1,  4.2, -4.3,  4.4},
+          {  4.5, -4.6,  4.7, -4.8},
+          {  5.1, -5.2,  5.3, -5.4},
+          { -5.5,  5.6, -5.7,  5.8}
+        },
+        { { -6.1,  6.2, -6.3,  6.4},
+          {  6.5, -6.6,  6.7, -6.8},
+          {  7.1, -7.2,  7.3, -7.4},
+          { -7.5,  7.6, -7.7,  7.8}
+        }
+                                         };
+psF64 Dpoly3DCoeff[TERMS][TERMS][TERMS] = {  { { -1.1,  1.2, -1.3,  1.4},
+        {  1.5, -1.6,  1.7, -1.8},
+        {  0.1, -0.2,  0.3, -0.4},
+        { -0.5,  0.6, -0.7,  0.8}
+                                             },
+        { { -2.1,  2.2, -2.3,  2.4},
+          {  2.5, -2.6,  2.7, -2.8},
+          {  3.1, -3.2,  3.3, -3.4},
+          { -3.5,  3.6, -3.7,  3.8}
+        },
+        { { -4.1,  4.2, -4.3,  4.4},
+          {  4.5, -4.6,  4.7, -4.8},
+          {  5.1, -5.2,  5.3, -5.4},
+          { -5.5,  5.6, -5.7,  5.8}
+        },
+        { { -6.1,  6.2, -6.3,  6.4},
+          {  6.5, -6.6,  6.7, -6.8},
+          {  7.1, -7.2,  7.3, -7.4},
+          { -7.5,  7.6, -7.7,  7.8}
+        }
+                                          };
+
+
+psF32 poly3DMask[TERMS][TERMS][TERMS]    = { {  {  0,    0,    0,    1},
+        {  0,    0,    1,    0},
+        {  1,    0,    0,    0},
+        {  0,    0,    0,    1}
+                                             },
+        {  {  1,    0,    0,    0},
+           {  1,    0,    0,    0},
+           {  1,    0,    0,    0},
+           {  1,    0,    0,    0}
+        },
+        {  {  0,    1,    0,    0},
+           {  0,    0,    1,    0},
+           {  0,    1,    0,    0},
+           {  0,    0,    1,    0}
+        },
+        {  {  1,    0,    0,    0},
+           {  0,    0,    0,    1},
+           {  1,    0,    0,    0},
+           {  0,    0,    0,    1}
+        },
+                                           };
+
+psF32 poly3DXYZValue[TESTPOINTS][3] = {  {  0.450, -0.780,  0.500},
+                                      {  0.297,  0.153, -0.354},
+                                      {  0.000,  0.153, -0.354},
+                                      {  0.297,  0.000, -0.354},
+                                      {  0.297,  0.153,  0.000}
+                                      };
+psF64 Dpoly3DXYZValue[TESTPOINTS][3] = {  {  0.450, -0.780,  0.500},
+                                       {  0.297,  0.153, -0.354},
+                                       {  0.000,  0.153, -0.354},
+                                       {  0.297,  0.000, -0.354},
+                                       {  0.297,  0.153,  0.000}
+                                       };
+psF32 poly3DResult[TESTPOINTS]  = { -1.298691, -2.011591, -1.359247, -2.548266, -1.139072};
+psF64 Dpoly3DResult[TESTPOINTS] = { -1.298691, -2.011591, -1.359247, -2.548266, -1.139072};
+
+
+psF32 poly3DXYZChebValue[TESTPOINTS][3] = {  {  0.000,  0.250, -0.250},
+        { -0.250,  0.000,  0.250},
+        {  0.250, -0.250,  0.000},
+        {  0.100, -0.300, -0.400},
+        {  0.990, -0.010,  0.500}
+                                          };
+psF64 Dpoly3DXYZChebValue[TESTPOINTS][3] = {  {  0.000,  0.250, -0.250},
+        { -0.250,  0.000,  0.250},
+        {  0.250, -0.250,  0.000},
+        {  0.100, -0.300, -0.400},
+        {  0.990, -0.010,  0.500}
+                                           };
+psF32 poly3DChebResult[TESTPOINTS]  = {  1.230469, 1.687500, 0.187500, -1.452707, 2.032344 };
+psF64 Dpoly3DChebResult[TESTPOINTS] = {  1.230469, 1.687500, 0.187500, -1.452707, 2.032344 };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(46);
+
+
+    // Evaluate NULL polynomial
+    {
+        psMemId id = psMemGetId();
+        psF64 result = psPolynomial3DEval(NULL, 0.0, 0.0, 0.0);
+        ok(isnan(result), "psPolynomial3DEval() returned NAN with NULL polynomial");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+
+    }
+
+
+    // Allocate and evaluate an ordinary polynomial structure
+    {
+        psMemId id = psMemGetId();
+
+        // Allocate polynomial structure
+        psPolynomial3D*  polyOrd = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, TERMS-1, TERMS-1, TERMS-1);
+        ok(polyOrd != NULL, "Ordinary psPolynomial3D successfully allocated");
+        skip_start(polyOrd == NULL, 1, "Skipping tests because psPolynomial3DAlloc() failed");
+
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                for(psS32 k = 0; k < TERMS; k++) {
+                    polyOrd->coeff[i][j][k] = Dpoly3DCoeff[i][j][k];
+                    polyOrd->coeffMask[i][j][k]  = poly3DMask[i][j][k];
+                }
+            }
+        }
+
+        // Evaluate test points and verify results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            psF64 result = psPolynomial3DEval(polyOrd,Dpoly3DXYZValue[i][0],Dpoly3DXYZValue[i][1],
+                                              Dpoly3DXYZValue[i][2]);
+            if (fabs(Dpoly3DResult[i]-result) > ERROR_TOL ) {
+                diag("TEST ERROR: Evaluated value %lg not as expected %lg.\n",
+                     result, Dpoly3DResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial3DEval() successful (Ordinary)");
+
+        psFree(polyOrd);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Allocate and evaluate Cheby polynomial structure
+    {
+        psMemId id = psMemGetId();
+
+        // Allocate polynomial structure
+        psPolynomial3D*  polyCheb = psPolynomial3DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1, TERMS-1, TERMS-1);
+        ok(polyCheb != NULL, "Ordinary psPolynomial3D successfully allocated");
+        skip_start(polyCheb == NULL, 1, "Skipping tests because psPolynomial3DAlloc() failed");
+
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                for(psS32 k = 0; k < TERMS; k++) {
+                    polyCheb->coeff[i][j][k] = 1.0;
+                    polyCheb->coeffMask[i][j][k]  = poly3DMask[i][j][k];
+                }
+            }
+        }
+
+        // Evaluate test points and verify results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            psF64 resultCheb = psPolynomial3DEval(polyCheb,Dpoly3DXYZChebValue[i][0],Dpoly3DXYZChebValue[i][1],
+                                                  Dpoly3DXYZChebValue[i][2]);
+            if (fabs(Dpoly3DChebResult[i]-resultCheb) > ERROR_TOL ) {
+                diag("TEST ERROR: Evaluated Chebyshev value %lg not as expected %lg.\n",
+                     resultCheb, Dpoly3DChebResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial3DEval() successful (Cheby)");
+
+        psFree(polyCheb);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Allocate polynomial, test the psPolynomial3DEvalVector() routines
+    {
+        psMemId id = psMemGetId();
+        // Create input vectors
+        psVector* inputOrdX  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputOrdY  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputOrdZ  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            inputOrdX->data.F64[i]  = Dpoly3DXYZValue[i][0];
+            inputOrdY->data.F64[i]  = Dpoly3DXYZValue[i][1];
+            inputOrdZ->data.F64[i]  = Dpoly3DXYZValue[i][2];
+            inputOrdX->n++;
+            inputOrdY->n++;
+            inputOrdZ->n++;
+        }
+
+        psPolynomial3D* polyOrd = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, TERMS-1, TERMS-1, TERMS-1);
+        ok(polyOrd != NULL, "Ordinary polynomial allocation successful");
+        skip_start(polyOrd == NULL, 10, "Skipping tests because psPolynomial3DAlloc() failed");
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                for(psS32 k = 0; k < TERMS; k++) {
+                    polyOrd->coeff[i][j][k] = Dpoly3DCoeff[i][j][k];
+                    polyOrd->coeffMask[i][j][k]  = poly3DMask[i][j][k];
+                }
+            }
+        }
+
+        // Evaluate the vectors
+        psVector* outputOrd = psPolynomial3DEvalVector(polyOrd,inputOrdX,inputOrdY,inputOrdZ);
+        ok(outputOrd != NULL, "psPolynomial3DEvalVector() generated non-NULL psVector");
+        ok(outputOrd->type.type == PS_TYPE_F64, "psPolynomial3DEvalVector() generated correct type");
+
+        // Verify the results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            if (fabs(Dpoly3DResult[i]-outputOrd->data.F64[i]) > ERROR_TOL) {
+                diag("TEST ERROR: Result[%d] %lg not equal to expected %lg.\n",
+                     i, outputOrd->data.F64[i], Dpoly3DResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial3DEvalVector() produced the correct answers");
+
+
+        // Attempt to invoke function with NULL polynomial
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial3DEvalVector(NULL,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with NULL polynomial");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial3DEvalVector(polyOrd,NULL,inputOrdY,inputOrdZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+    
+
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial3DEvalVector(polyOrd,inputOrdX,NULL,inputOrdZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial3DEvalVector(polyOrd,inputOrdX,inputOrdY,NULL) == NULL, "psPolynomial3DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputOrdX->type.type = PS_TYPE_U8;
+            ok(psPolynomial3DEvalVector(polyOrd,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+        inputOrdX->type.type = PS_TYPE_F64;
+
+
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputOrdY->type.type = PS_TYPE_U8;
+            ok(psPolynomial3DEvalVector(polyOrd,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+        inputOrdY->type.type = PS_TYPE_F64;
+
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputOrdZ->type.type = PS_TYPE_U8;
+            ok(psPolynomial3DEvalVector(polyOrd,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+        psFree(outputOrd);
+        skip_end();
+        psFree(inputOrdX);
+        psFree(inputOrdY);
+        psFree(inputOrdZ);
+        psFree(polyOrd);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Allocate polynomial, test the psPolynomial3DEvalVector() routines
+    {
+        psMemId id = psMemGetId();
+        // Create input vectors
+        psVector* inputChebX = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputChebY = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputChebZ = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            inputChebX->data.F64[i] = Dpoly3DXYZChebValue[i][0];
+            inputChebY->data.F64[i] = Dpoly3DXYZChebValue[i][1];
+            inputChebZ->data.F64[i] = Dpoly3DXYZChebValue[i][2];
+            inputChebX->n++;
+            inputChebY->n++;
+            inputChebZ->n++;
+        }
+        psPolynomial3D* polyCheb = psPolynomial3DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1, TERMS-1, TERMS-1);
+        ok(polyCheb != NULL, "Ordinary polynomial allocation successful");
+        skip_start(polyCheb == NULL, 10, "Skipping tests because psPolynomial3DAlloc() failed");
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                for(psS32 k = 0; k < TERMS; k++) {
+                    polyCheb->coeff[i][j][k] = 1.0;
+                    polyCheb->coeffMask[i][j][k]  = poly3DMask[i][j][k];
+                }
+            }
+        }
+
+        // Evaluate the vectors
+        psVector* outputCheb = psPolynomial3DEvalVector(polyCheb,inputChebX,inputChebY,inputChebZ);
+        ok(outputCheb != NULL, "psPolynomial3DEvalVector() generated non-NULL psVector");
+        ok(outputCheb->type.type == PS_TYPE_F64, "psPolynomial3DEvalVector() generated correct type");
+
+        // Verify the results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            if (fabs(Dpoly3DChebResult[i]-outputCheb->data.F64[i]) > ERROR_TOL) {
+                diag("TEST ERROR: ResultCheb[%d] %lg not equal to expected %lg.\n",
+                     i, outputCheb->data.F64[i], Dpoly3DChebResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial3DEvalVector() produced the correct answers");
+
+        // Attempt to invoke function with NULL polynomial
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial3DEvalVector(NULL,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with NULL polynomial");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial3DEvalVector(polyCheb,NULL,inputChebY,inputChebZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial3DEvalVector(polyCheb,inputChebX,NULL,inputChebZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial3DEvalVector(polyCheb,inputChebX,inputChebY,NULL) == NULL, "psPolynomial3DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputChebX->type.type = PS_TYPE_U8;
+            ok(psPolynomial3DEvalVector(polyCheb,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+        inputChebX->type.type = PS_TYPE_F64;
+
+
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputChebY->type.type = PS_TYPE_U8;
+            ok(psPolynomial3DEvalVector(polyCheb,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+        inputChebY->type.type = PS_TYPE_F64;
+
+
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputChebZ->type.type = PS_TYPE_U8;
+            ok(psPolynomial3DEvalVector(polyCheb,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+        psFree(outputCheb);
+        skip_end();
+        psFree(inputChebX);
+        psFree(inputChebY);
+        psFree(inputChebZ);
+        psFree(polyCheb);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomialEval4D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomialEval4D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomialEval4D.c	(revision 22158)
@@ -0,0 +1,742 @@
+/** tst_psFunc11.c
+*
+*  This test driver will exercise the psPolynomialXDEval functions for both
+*  ORD and CHEB type polynomials.
+*
+*  @version  $Revision: 1.7 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2008-05-05 00:09:04 $
+*
+* Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*
+***************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define  TERMS        4
+#define  TESTPOINTS   5
+#define  ERROR_TOL    0.001
+
+psF32 poly4DCoeff[TERMS][TERMS][TERMS][TERMS] = {
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            },
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            },
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            },
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            }
+        };
+psF64 Dpoly4DCoeff[TERMS][TERMS][TERMS][TERMS] = {
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            },
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            },
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            },
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            }
+        };
+
+psF32 poly4DMask[TERMS][TERMS][TERMS][TERMS]    = {
+            {
+                {
+                    {  0,    0,    0,    1},
+                    {  0,    0,    1,    0},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0}
+                },
+                {
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0},
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                }
+            },
+            {
+                {
+                    {  0,    0,    0,    1},
+                    {  0,    0,    1,    0},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0}
+                },
+                {
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0},
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                }
+            },
+            {
+                {
+                    {  0,    0,    0,    1},
+                    {  0,    0,    1,    0},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0}
+                },
+                {
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0},
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                }
+            },
+            {
+                {
+                    {  0,    0,    0,    1},
+                    {  0,    0,    1,    0},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0}
+                },
+                {
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0},
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                }
+            }
+        };
+
+psF32 poly4DWXYZValue[TESTPOINTS][4] = {
+                                           {  0.450, -0.780,  0.500, -0.123},
+                                           {  0.297,  0.153, -0.354,  0.000},
+                                           {  0.000,  0.153, -0.354,  0.321},
+                                           {  0.297,  0.000, -0.354,  0.321},
+                                           {  0.297,  0.153,  0.000,  0.321}
+                                       };
+psF64 Dpoly4DWXYZValue[TESTPOINTS][4] = {
+                                            {  0.450, -0.780,  0.500, -0.123},
+                                            {  0.297,  0.153, -0.354,  0.000},
+                                            {  0.000,  0.153, -0.354,  0.321},
+                                            {  0.297,  0.000, -0.354,  0.321},
+                                            {  0.297,  0.153,  0.000,  0.321}
+                                        };
+
+psF32 poly4DResult[TESTPOINTS]  = { -3.588753, -2.439566, -1.175955, -1.645497, -1.216915};
+psF64 Dpoly4DResult[TESTPOINTS]  = { -3.588753, -2.439566, -1.175955, -1.645497, -1.216915};
+
+psF32 poly4DWXYZChebValue[TESTPOINTS][4] = {
+            {  0.100,  0.000,  0.250, -0.250},
+            {  0.100, -0.250,  0.000,  0.250},
+            {  0.100,  0.250, -0.250,  0.000},
+            {  0.300,  0.200, -0.300, -0.400},
+            { -0.780,  0.990, -0.010,  0.500}
+        };
+psF64 Dpoly4DWXYZChebValue[TESTPOINTS][4] = {
+            {  0.100,  0.000,  0.250, -0.250},
+            {  0.100, -0.250,  0.000,  0.250},
+            {  0.100,  0.250, -0.250,  0.000},
+            {  0.300,  0.200, -0.300, -0.400},
+            { -0.780,  0.990, -0.010,  0.500}
+        };
+psF32 poly4DChebResult[TESTPOINTS]   = { -0.216563, -0.297000, -0.033000, 0.432198, 1.785601 };
+psF64 Dpoly4DChebResult[TESTPOINTS]  = { -0.216563, -0.297000, -0.033000, 0.432198, 1.785601 };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(54);
+
+
+    // Evaluate NULL polynomial
+    {
+        psMemId id = psMemGetId();
+        psF64 result = psPolynomial4DEval(NULL, 0.0, 0.0, 0.0, 0.0);
+        ok(isnan(result), "psPolynomial4DEval() returned NAN with unallowed type");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Allocate and evaluate an ordinary polynomial structure
+    {
+        psMemId id = psMemGetId();
+        // Allocate polynomial structure
+        psPolynomial4D*  polyOrd = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, TERMS-1, TERMS-1, TERMS-1, TERMS-1);
+        ok(polyOrd != NULL, "Ordinary psPolynomial4D successfully allocated");
+        skip_start(polyOrd == NULL, 1, "Skipping tests because psPolynomial4DAlloc() failed");
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                for(psS32 k = 0; k < TERMS; k++) {
+                    for(psS32 l = 0; l < TERMS; l++) {
+                        polyOrd->coeff[i][j][k][l] = Dpoly4DCoeff[i][j][k][l];
+                        polyOrd->coeffMask[i][j][k][l]  = poly4DMask[i][j][k][l];
+                    }
+                }
+            }
+        }
+
+        // Evaluate test points and verify results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            psF64 result = psPolynomial4DEval(polyOrd, Dpoly4DWXYZValue[i][0], Dpoly4DWXYZValue[i][1],
+                                              Dpoly4DWXYZValue[i][2], Dpoly4DWXYZValue[i][3]);
+            if (fabs(Dpoly4DResult[i]-result) > ERROR_TOL ) {
+                diag("TEST ERROR: Evaluated value %lg not as expected %lg.\n",
+                     result, Dpoly4DResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial3DEval() successful (Ordinary)");
+
+        psFree(polyOrd);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Allocate and evaluate an ordinary polynomial structure
+    {
+        psMemId id = psMemGetId();
+        // Allocate polynomial structure
+        psPolynomial4D*  polyCheb = psPolynomial4DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1, TERMS-1, TERMS-1, TERMS-1);
+        ok(polyCheb != NULL, "Ordinary psPolynomial4D successfully allocated");
+        skip_start(polyCheb == NULL, 1, "Skipping tests because psPolynomial4DAlloc() failed");
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                for(psS32 k = 0; k < TERMS; k++) {
+                    for(psS32 l = 0; l < TERMS; l++) {
+                        polyCheb->coeff[i][j][k][l] = 1.0;
+                        polyCheb->coeffMask[i][j][k][l]  = poly4DMask[i][j][k][l];
+                    }
+                }
+            }
+        }
+
+        // Evaluate test points and verify results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            psF64 resultCheb = psPolynomial4DEval(polyCheb, Dpoly4DWXYZChebValue[i][0], Dpoly4DWXYZChebValue[i][1],
+                                                  Dpoly4DWXYZChebValue[i][2], Dpoly4DWXYZChebValue[i][3]);
+            if (fabs(Dpoly4DChebResult[i]-resultCheb) > ERROR_TOL ) {
+                diag("TEST ERROR: Evaluated Chebyshev value %lg not as expected %lg.\n",
+                     resultCheb, Dpoly4DChebResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial3DEval() successful (Ordinary)");
+
+        psFree(polyCheb);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Allocate polynomial, test the psPolynomial4DEvalVector() routines
+    {
+        psMemId id = psMemGetId();
+        // Create input vectors
+        psVector* inputOrdW  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputOrdX  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputOrdY  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputOrdZ  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            inputOrdW->data.F64[i]  = Dpoly4DWXYZValue[i][0];
+            inputOrdX->data.F64[i]  = Dpoly4DWXYZValue[i][1];
+            inputOrdY->data.F64[i]  = Dpoly4DWXYZValue[i][2];
+            inputOrdZ->data.F64[i]  = Dpoly4DWXYZValue[i][3];
+            inputOrdW->n++;
+            inputOrdX->n++;
+            inputOrdY->n++;
+            inputOrdZ->n++;
+        }
+
+        // Allocate polynomial
+        psPolynomial4D* polyOrd = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, TERMS-1, TERMS-1, TERMS-1, TERMS-1);
+        ok(polyOrd != NULL, "Ordinary polynomial allocation successful");
+        skip_start(polyOrd == NULL, 12, "Skipping tests because psPolynomial4DAlloc() failed");
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                for(psS32 k = 0; k < TERMS; k++) {
+                    for(psS32 l = 0; l < TERMS; l++) {
+                        polyOrd->coeff[i][j][k][l] = Dpoly4DCoeff[i][j][k][l];
+                        polyOrd->coeffMask[i][j][k][l]  = poly4DMask[i][j][k][l];
+                    }
+                }
+            }
+        }
+
+        // Evaluate the vectors
+        psVector* outputOrd = psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,inputOrdY,inputOrdZ);
+        ok(outputOrd != NULL, "psPolynomial4DEvalVector() generated non-NULL psVector");
+        ok(outputOrd->type.type == PS_TYPE_F64, "psPolynomial4DEvalVector() generated correct type");
+
+        // Verify the results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            if (fabs(Dpoly4DResult[i]-outputOrd->data.F64[i]) > ERROR_TOL) {
+                diag("TEST ERROR: Result[%d] %lg not equal to expected %lg",
+                     i, outputOrd->data.F64[i], Dpoly4DResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial4DEvalVector() produced the correct answers");
+
+
+        // Attempt to invoke function with NULL polynomial
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial4DEvalVector(NULL,inputOrdW,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL polynomial");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial4DEvalVector(polyOrd,NULL,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial4DEvalVector(polyOrd,inputOrdW,NULL,inputOrdY,inputOrdZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,NULL,inputOrdZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,inputOrdY,NULL) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputOrdX->type.type = PS_TYPE_U8;
+            ok(psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+        inputOrdX->type.type = PS_TYPE_F64;
+
+
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputOrdY->type.type = PS_TYPE_U8;
+            ok(psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+        inputOrdY->type.type = PS_TYPE_F64;
+
+
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputOrdZ->type.type = PS_TYPE_U8;
+            ok(psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+        inputOrdZ->type.type = PS_TYPE_F64;
+
+
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputOrdW->type.type = PS_TYPE_U8;
+            ok(psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+        inputOrdW->type.type = PS_TYPE_F64;
+        psFree(outputOrd);
+        skip_end();
+        psFree(inputOrdX);
+        psFree(inputOrdY);
+        psFree(inputOrdZ);
+        psFree(inputOrdW);
+        psFree(polyOrd);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Allocate polynomial, test the psPolynomial4DEvalVector() routines
+    {
+        psMemId id = psMemGetId();
+        // Create input vectors
+        psVector* inputChebW = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputChebX = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputChebY = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputChebZ = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            inputChebW->data.F64[i] = Dpoly4DWXYZChebValue[i][0];
+            inputChebX->data.F64[i] = Dpoly4DWXYZChebValue[i][1];
+            inputChebY->data.F64[i] = Dpoly4DWXYZChebValue[i][2];
+            inputChebZ->data.F64[i] = Dpoly4DWXYZChebValue[i][3];
+            inputChebW->n++;
+            inputChebX->n++;
+            inputChebY->n++;
+            inputChebZ->n++;
+        }
+
+        // Allocate polynomial
+        psPolynomial4D* polyCheb = psPolynomial4DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1, TERMS-1, TERMS-1, TERMS-1);
+        ok(polyCheb != NULL, "Ordinary polynomial allocation successful");
+        skip_start(polyCheb == NULL, 12, "Skipping tests because psPolynomial4DAlloc() failed");
+
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                for(psS32 k = 0; k < TERMS; k++) {
+                    for(psS32 l = 0; l < TERMS; l++) {
+                        polyCheb->coeff[i][j][k][l] = 1.0;
+                        polyCheb->coeffMask[i][j][k][l]  = poly4DMask[i][j][k][l];
+                    }
+                }
+            }
+        }
+
+        // Evaluate the vectors
+        psVector* outputCheb = psPolynomial4DEvalVector(polyCheb,inputChebW,inputChebX,inputChebY,inputChebZ);
+        ok(outputCheb != NULL, "psPolynomial4DEvalVector() generated non-NULL psVector");
+        ok(outputCheb->type.type == PS_TYPE_F64, "psPolynomial4DEvalVector() generated correct type");
+
+        // Verify the results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            if (fabs(Dpoly4DChebResult[i]-outputCheb->data.F64[i]) > ERROR_TOL) {
+                diag("TEST ERROR: ResultCheb[%d] %lg not equal to expected %lg",
+                     i, outputCheb->data.F64[i], Dpoly4DChebResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial4DEvalVector() produced the correct answers");
+
+
+        // Attempt to invoke function with NULL polynomial
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial4DEvalVector(NULL,inputChebW,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL polynomial");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial4DEvalVector(polyCheb,NULL,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial4DEvalVector(polyCheb,inputChebW,NULL,inputChebY,inputChebZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial4DEvalVector(polyCheb,inputChebW,inputChebX,NULL,inputChebZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with NULL input vector
+        {
+            psMemId id = psMemGetId();
+            ok(psPolynomial4DEvalVector(polyCheb,inputChebW,inputChebX,inputChebY,NULL) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputChebX->type.type = PS_TYPE_U8;
+            ok(psPolynomial4DEvalVector(polyCheb,inputChebW,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+        inputChebX->type.type = PS_TYPE_F64;
+
+
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputChebY->type.type = PS_TYPE_U8;
+            ok(psPolynomial4DEvalVector(polyCheb,inputChebW,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+        inputChebY->type.type = PS_TYPE_F64;
+
+
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputChebZ->type.type = PS_TYPE_U8;
+            ok(psPolynomial4DEvalVector(polyCheb,inputChebW,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+        inputChebZ->type.type = PS_TYPE_F64;
+
+
+        // Attempt to invoke function with a non F64 type input vector
+        {
+            psMemId id = psMemGetId();
+            inputChebW->type.type = PS_TYPE_U8;
+            ok(psPolynomial4DEvalVector(polyCheb,inputChebW,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with non F64 input vector");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+        inputChebW->type.type = PS_TYPE_F64;
+        psFree(outputCheb);
+        skip_end();
+        psFree(inputChebW);
+        psFree(inputChebX);
+        psFree(inputChebY);
+        psFree(inputChebZ);
+        psFree(polyCheb);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomialMD.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomialMD.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomialMD.c	(revision 22158)
@@ -0,0 +1,97 @@
+#include <stdio.h>
+#include <pslib.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+#define XORDER 3
+#define YORDER 2
+static float constant = 1.0;
+static float xCoeff[XORDER] = { 5.0, -3.0, 2.0 };
+static float yCoeff[YORDER] = { -6.0, 4.0 };
+#define XNUM 10
+#define YNUM 10
+#define NUM ((XNUM)*(YNUM))
+#define TOL 1.0e-8
+
+int main(int argc, char *argv[])
+{
+    plan_tests(2 * (1 + (1 + XORDER + YORDER)) + 1);
+
+    {
+        psMemId id = psMemGetId();
+
+        psArray *ordinates = psArrayAlloc(NUM);
+        psVector *values = psVectorAlloc(NUM, PS_TYPE_F32);
+
+        for (int i = 0, index = 0; i < XNUM; i++) {
+            int x = i - XNUM/2;
+            for (int j = 0; j < YNUM; j++, index++) {
+                int y = j - YNUM/2;
+
+                float value = constant;
+                for (int k = 0; k < XORDER; k++) {
+                    value += xCoeff[k] * powf(x, k+1);
+                }
+                for (int k = 0; k < YORDER; k++) {
+                    value += yCoeff[k] * powf(y, k+1);
+                }
+
+                values->data.F32[index] = value;
+                psVector *ord = psVectorAlloc(2, PS_TYPE_F32);
+                ord->data.F32[0] = x;
+                ord->data.F32[1] = y;
+                ordinates->data[index] = ord;
+            }
+        }
+
+        psVector *orders = psVectorAlloc(2, PS_TYPE_S32);
+        orders->data.S32[0] = XORDER;
+        orders->data.S32[1] = YORDER;
+
+        {
+            psPolynomialMD *poly = psPolynomialMDAlloc(orders);
+            bool polyOK = psPolynomialMDFit(poly, values, NULL, NULL, 0, ordinates);
+            ok(polyOK, "Fit polynomial");
+            skip_start(!polyOK, 1+XORDER+YORDER, "Skipping coefficient checks since fit failed.");
+            int index = 0;
+            is_double_tol(poly->coeff->data.F64[index], constant, TOL, "Coefficient %d", index);
+            index++;
+            for (int i = 0; i < XORDER; i++, index++) {
+                is_double_tol(poly->coeff->data.F64[index], xCoeff[i], TOL, "Coefficient %d", index);
+            }
+            for (int i = 0; i < YORDER; i++, index++) {
+                is_double_tol(poly->coeff->data.F64[index], yCoeff[i], TOL, "Coefficient %d", index);
+            }
+            skip_end();
+            psFree(poly);
+        }
+
+        {
+            psPolynomialMD *poly = psPolynomialMDAlloc(orders);
+            values->data.F32[NUM/2] *= 10;
+            bool polyOK = psPolynomialMDClipFit(poly, values, NULL, NULL, 0, ordinates, 1, 3.0);
+            ok(polyOK, "Clip-fit polynomial");
+            skip_start(!polyOK, 1+XORDER+YORDER, "Skipping coefficient checks since clip-fit failed.");
+            int index = 0;
+            is_double_tol(poly->coeff->data.F64[index], constant, TOL, "Coefficient %d", index);
+            index++;
+            for (int i = 0; i < XORDER; i++, index++) {
+                is_double_tol(poly->coeff->data.F64[index], xCoeff[i], TOL, "Coefficient %d", index);
+            }
+            for (int i = 0; i < YORDER; i++, index++) {
+                is_double_tol(poly->coeff->data.F64[index], yCoeff[i], TOL, "Coefficient %d", index);
+            }
+            skip_end();
+            psFree(poly);
+        }
+
+        psFree(orders);
+        psFree(values);
+        psFree(ordinates);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    exit(EXIT_SUCCESS);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomialUtils_Derivatives.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomialUtils_Derivatives.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psPolynomialUtils_Derivatives.c	(revision 22158)
@@ -0,0 +1,276 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+int main (void)
+{
+    plan_tests(54);
+
+    note("psPolynomial2D Derivative tests");
+
+    // test psPolynomial2D_dX (no supplied output)
+    {
+        psMemId id = psMemGetId();
+
+        note ("test psPolynomial2D_dX (no supplied output)");
+
+        psPolynomial2D *poly = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 2, 2);
+        ok(poly != NULL, "psPolynomial2D successfully allocated");
+        skip_start(poly == NULL, 5, "Skipping tests because psPolynomial2DAlloc() failed");
+
+        // build sample polynomial (upper-left elements only)
+        // z = 5 + 2x + 3y - 3x^2 + 4xy - 2y^2
+        // dz/dx = 2 - 6x + 4y
+        poly->coeff[0][0] = 5.0;
+        poly->coeff[1][0] = 2.0;
+        poly->coeff[0][1] = 3.0;
+        poly->coeff[2][0] = -3.0;
+        poly->coeff[1][1] = 4.0;
+        poly->coeff[0][2] = -2.0;
+
+        // mask remaining elements
+        poly->coeffMask[2][1] = 1;
+        poly->coeffMask[1][2] = 1;
+        poly->coeffMask[2][2] = 1;
+
+        psPolynomial2D *dX = psPolynomial2D_dX (NULL, poly);
+
+        ok(dX->nX == 1, "new x order is %d", dX->nX);
+        ok(dX->nY == 2, "new y order is %d", dX->nY);
+
+        is_float(dX->coeff[0][0], +2.0, "x^0 y^0 coeff is %f", dX->coeff[0][0]);
+        is_float(dX->coeff[1][0], -6.0, "x^1 y^0 coeff is %f", dX->coeff[1][0]);
+        is_float(dX->coeff[0][1], +4.0, "x^0 y^1 coeff is %f", dX->coeff[0][1]);
+
+        ok(!dX->coeffMask[0][0], "x^0 y^0 coeff is unmasked");
+        ok(!dX->coeffMask[1][0], "x^1 y^0 coeff is unmasked");
+        ok(!dX->coeffMask[0][1], "x^0 y^1 coeff is unmasked");
+
+        ok(dX->coeffMask[1][1], "x^1 y^1 coeff is masked");
+        ok(dX->coeffMask[1][2], "x^1 y^2 coeff is masked");
+
+        psFree (dX);
+        psFree (poly);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test psPolynomial2D_dX (supplied output)
+    {
+        psMemId id = psMemGetId();
+
+        note ("test psPolynomial2D_dX (supplied output)");
+
+        psPolynomial2D *poly = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 2, 2);
+        ok(poly != NULL, "psPolynomial2D successfully allocated");
+        skip_start(poly == NULL, 5, "Skipping tests because psPolynomial2DAlloc() failed");
+
+        // build sample polynomial (upper-left elements only)
+        // z = 5 + 2x + 3y - 3x^2 + 4xy - 2y^2
+        // dz/dx = 2 - 6x + 4y
+        poly->coeff[0][0] = 5.0;
+        poly->coeff[1][0] = 2.0;
+        poly->coeff[0][1] = 3.0;
+        poly->coeff[2][0] = -3.0;
+        poly->coeff[1][1] = 4.0;
+        poly->coeff[0][2] = -2.0;
+
+        // mask remaining elements
+        poly->coeffMask[2][1] = 1;
+        poly->coeffMask[1][2] = 1;
+        poly->coeffMask[2][2] = 1;
+
+        psPolynomial2D *dX = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 2, 2);
+        psPolynomial2D_dX (dX, poly);
+
+        ok(dX->nX == 1, "new x order is %d", dX->nX);
+        ok(dX->nY == 2, "new y order is %d", dX->nY);
+
+        is_float(dX->coeff[0][0], +2.0, "x^0 y^0 coeff is %f", dX->coeff[0][0]);
+        is_float(dX->coeff[1][0], -6.0, "x^1 y^0 coeff is %f", dX->coeff[1][0]);
+        is_float(dX->coeff[0][1], +4.0, "x^0 y^1 coeff is %f", dX->coeff[0][1]);
+
+        ok(!dX->coeffMask[0][0], "x^0 y^0 coeff is unmasked");
+        ok(!dX->coeffMask[1][0], "x^1 y^0 coeff is unmasked");
+        ok(!dX->coeffMask[0][1], "x^0 y^1 coeff is unmasked");
+
+        ok(dX->coeffMask[1][1], "x^1 y^1 coeff is masked");
+        ok(dX->coeffMask[1][2], "x^1 y^2 coeff is masked");
+
+        psFree (dX);
+        psFree (poly);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test psPolynomial2D_dX (inPlace: supplied output == supplied input)
+    {
+        psMemId id = psMemGetId();
+
+        note ("test psPolynomial2D_dX (supplied output)");
+
+        psPolynomial2D *poly = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 2, 2);
+        ok(poly != NULL, "psPolynomial2D successfully allocated");
+        skip_start(poly == NULL, 5, "Skipping tests because psPolynomial2DAlloc() failed");
+
+        // build sample polynomial (upper-left elements only)
+        // z = 5 + 2x + 3y - 3x^2 + 4xy - 2y^2
+        // dz/dx = 2 - 6x + 4y
+        poly->coeff[0][0] = 5.0;
+        poly->coeff[1][0] = 2.0;
+        poly->coeff[0][1] = 3.0;
+        poly->coeff[2][0] = -3.0;
+        poly->coeff[1][1] = 4.0;
+        poly->coeff[0][2] = -2.0;
+
+        // mask remaining elements
+        poly->coeffMask[2][1] = 1;
+        poly->coeffMask[1][2] = 1;
+        poly->coeffMask[2][2] = 1;
+
+        psPolynomial2D *result = psPolynomial2D_dX (poly, poly);
+        ok (result == NULL, "psPolynomial2D_dX failed as expected: cannot assign output to input");
+
+        psFree (poly);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test psPolynomial2D_dY (no supplied output)
+    {
+        psMemId id = psMemGetId();
+
+        note ("test psPolynomial2D_dY (no supplied output)");
+
+        psPolynomial2D *poly = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 2, 2);
+        ok(poly != NULL, "psPolynomial2D successfully allocated");
+        skip_start(poly == NULL, 5, "Skipping tests because psPolynomial2DAlloc() failed");
+
+        // build sample polynomial (upper-left elements only)
+        // z = 5 + 2x + 3y - 3x^2 + 4xy - 2y^2
+        // dz/dy = 3 + 4x - 4y
+        poly->coeff[0][0] = 5.0;
+        poly->coeff[1][0] = 2.0;
+        poly->coeff[0][1] = 3.0;
+        poly->coeff[2][0] = -3.0;
+        poly->coeff[1][1] = 4.0;
+        poly->coeff[0][2] = -2.0;
+
+        // mask remaining elements
+        poly->coeffMask[2][1] = 1;
+        poly->coeffMask[1][2] = 1;
+        poly->coeffMask[2][2] = 1;
+
+        psPolynomial2D *dY = psPolynomial2D_dY (NULL, poly);
+
+        ok(dY->nX == 2, "new x order is %d", dY->nX);
+        ok(dY->nY == 1, "new y order is %d", dY->nY);
+
+        is_float(dY->coeff[0][0], +3.0, "x^0 y^0 coeff is %f", dY->coeff[0][0]);
+        is_float(dY->coeff[1][0], +4.0, "x^1 y^0 coeff is %f", dY->coeff[1][0]);
+        is_float(dY->coeff[0][1], -4.0, "x^0 y^1 coeff is %f", dY->coeff[0][1]);
+
+        ok(!dY->coeffMask[0][0], "x^0 y^0 coeff is unmasked");
+        ok(!dY->coeffMask[1][0], "x^1 y^0 coeff is unmasked");
+        ok(!dY->coeffMask[0][1], "x^0 y^1 coeff is unmasked");
+
+        ok(dY->coeffMask[1][1], "x^1 y^1 coeff is masked");
+        ok(dY->coeffMask[1][2], "x^1 y^2 coeff is masked");
+
+        psFree (dY);
+        psFree (poly);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test psPolynomial2D_dY (supplied output)
+    {
+        psMemId id = psMemGetId();
+
+        note ("test psPolynomial2D_dY (supplied output)");
+
+        psPolynomial2D *poly = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 2, 2);
+        ok(poly != NULL, "psPolynomial2D successfully allocated");
+        skip_start(poly == NULL, 5, "Skipping tests because psPolynomial2DAlloc() failed");
+
+        // build sample polynomial (upper-left elements only)
+        // z = 5 + 2x + 3y - 3x^2 + 4xy - 2y^2
+        // dz/dy = 3 + 4x - 4y
+        poly->coeff[0][0] = 5.0;
+        poly->coeff[1][0] = 2.0;
+        poly->coeff[0][1] = 3.0;
+        poly->coeff[2][0] = -3.0;
+        poly->coeff[1][1] = 4.0;
+        poly->coeff[0][2] = -2.0;
+
+        // mask remaining elements
+        poly->coeffMask[2][1] = 1;
+        poly->coeffMask[1][2] = 1;
+        poly->coeffMask[2][2] = 1;
+
+        psPolynomial2D *dY = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 2, 2);
+        psPolynomial2D_dY (dY, poly);
+
+        ok(dY->nX == 2, "new x order is %d", dY->nX);
+        ok(dY->nY == 1, "new y order is %d", dY->nY);
+
+        is_float(dY->coeff[0][0], +3.0, "x^0 y^0 coeff is %f", dY->coeff[0][0]);
+        is_float(dY->coeff[1][0], +4.0, "x^1 y^0 coeff is %f", dY->coeff[1][0]);
+        is_float(dY->coeff[0][1], -4.0, "x^0 y^1 coeff is %f", dY->coeff[0][1]);
+
+        ok(!dY->coeffMask[0][0], "x^0 y^0 coeff is unmasked");
+        ok(!dY->coeffMask[1][0], "x^1 y^0 coeff is unmasked");
+        ok(!dY->coeffMask[0][1], "x^0 y^1 coeff is unmasked");
+
+        ok(dY->coeffMask[1][1], "x^1 y^1 coeff is masked");
+        ok(dY->coeffMask[1][2], "x^1 y^2 coeff is masked");
+
+        psFree (dY);
+        psFree (poly);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test psPolynomial2D_dY (supplied output)
+    {
+        psMemId id = psMemGetId();
+
+        note ("test psPolynomial2D_dY (supplied output)");
+
+        psPolynomial2D *poly = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 2, 2);
+        ok(poly != NULL, "psPolynomial2D successfully allocated");
+        skip_start(poly == NULL, 5, "Skipping tests because psPolynomial2DAlloc() failed");
+
+        // build sample polynomial (upper-left elements only)
+        // z = 5 + 2x + 3y - 3x^2 + 4xy - 2y^2
+        // dz/dy = 3 + 4x - 4y
+        poly->coeff[0][0] = 5.0;
+        poly->coeff[1][0] = 2.0;
+        poly->coeff[0][1] = 3.0;
+        poly->coeff[2][0] = -3.0;
+        poly->coeff[1][1] = 4.0;
+        poly->coeff[0][2] = -2.0;
+
+        // mask remaining elements
+        poly->coeffMask[2][1] = 1;
+        poly->coeffMask[1][2] = 1;
+        poly->coeffMask[2][2] = 1;
+
+        psPolynomial2D *result = psPolynomial2D_dY (poly, poly);
+        ok (result == NULL, "psPolynomial2D_dY failed as expected: cannot assign output to input");
+
+        psFree (poly);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    return exit_status();
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psRandom.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psRandom.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psRandom.c	(revision 22158)
@@ -0,0 +1,363 @@
+/*****************************************************************************
+This routine must ensure that the various random number generator functions
+work properly.
+ 
+    ensure that psRandom structs are properly allocated by psRandomAlloc().
+    ensure that psRandomUniform() produces a sequence of numbers with
+        proper mean and stdev.
+    ensure that psRandomGaussian() produces a sequence of numbers with
+        proper mean and stdev.
+    ensure that psRandomPoisson() produces a sequence of numbers with
+        proper mean and stdev.
+    ensure that psRandomReset() properly seeds the random number
+        generator for psRandomUniform().
+    ensure that psRandomReset() properly seeds the random number
+        generator for psRandomGaussian().
+    ensure that psRandomReset() properly seeds the random number
+        generator for psRandomPoisson().
+ 
+XXX: I removed a test that generated error output.  How should we test that?
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#include <math.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#define NUM_DATA 10000
+#define SEED 54321
+#define SEED2 345
+#define UNIFORM_MEAN 0.5
+#define UNIFORM_STDEV 0.3
+#define GAUSSIAN_MEAN 0.0
+#define GAUSSIAN_STDEV 1.0
+#define POISSON_MEAN 15.0
+#define POISSON_STDEV (POISSON_MEAN / 4)
+#define ERROR_TOLERANCE 0.2
+#define VERBOSE 0
+# define is_float_tol_per(VALUE,EXPECT,TOL,COMMENT, ...)\
+ok((fabs((VALUE)-(EXPECT)) < (TOL)), COMMENT, ## __VA_ARGS__);
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    plan_tests(34);
+
+    // ensure that psRandom structs are properly allocated by psRandomAlloc()
+    {
+        psMemId id = psMemGetId();
+        // Valid type allocation
+        psRandom *myRNG = psRandomAlloc(PS_RANDOM_TAUS, SEED);
+        ok(myRNG != NULL, "psRandom struct was allocated properly");
+        skip_start(myRNG == NULL, 1, "Skipping tests because psRandomAlloc() failed");
+        ok(myRNG->type == PS_RANDOM_TAUS, "psRandomAlloc() set type properly");
+        psFree(myRNG);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Unallowed type allocation
+    {
+        psMemId id = psMemGetId();
+        psRandom *myRNG = psRandomAlloc(100,SEED);
+        ok(myRNG == NULL, "psRandomAlloc() refused to generate psRandom with unallowed type");
+        psFree(myRNG);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Negative seed value
+    {
+        psMemId id = psMemGetId();
+        psRandom *myRNG = psRandomAlloc(PS_RANDOM_TAUS,-5);
+        ok(myRNG != NULL, "psRandomAlloc() allows negative seed");
+        psFree(myRNG);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // testRandomUniform(void)
+    {
+        // testRandomUniform()
+        psMemId id = psMemGetId();
+        psVector *rans = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+        rans->n = rans->nalloc;
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        psRandom *myRNG = psRandomAlloc(PS_RANDOM_TAUS, SEED);
+        ok(myRNG != NULL, "psRandom struct was allocated properly");
+        skip_start(myRNG == NULL, 2, "Skipping tests because psRandomAlloc() failed");
+
+        // Initialize vector data with random number
+        for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+            rans->data.F64[i] = psRandomUniform(myRNG);
+        }
+
+        // Perform vector stats on random data (mean, stdev)
+        psVectorStats(stats, rans, NULL, NULL, 0);
+        stats->options = PS_STAT_SAMPLE_STDEV;
+        psVectorStats(stats, rans, NULL, NULL, 0);
+
+        // Verify mean and stdev
+        is_float_tol_per(stats->sampleMean, UNIFORM_MEAN, ERROR_TOLERANCE, "Mean is within expected range");
+        is_float_tol_per(stats->sampleStdev, UNIFORM_STDEV, ERROR_TOLERANCE, "StDev is within expected range");
+
+        skip_end();
+
+        psFree(myRNG);
+        psFree(rans);
+        psFree(stats);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Ensure psRandomUniform() returns 0 for NULL psRandom struct
+    {
+        psMemId id = psMemGetId();
+        ok(psRandomUniform(NULL) == 0, "Ensure psRandomUniform() returns 0 for NULL psRandom struct");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // testRandomGaussian(void)
+    {
+        diag("testRandomGaussian()");
+        psMemId id = psMemGetId();
+        psVector *rans = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+        rans->n = rans->nalloc;
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        psRandom *myRNG = psRandomAlloc(PS_RANDOM_TAUS, SEED);
+        ok(myRNG != NULL, "psRandom struct was allocated properly");
+        skip_start(myRNG == NULL, 2, "Skipping tests because psRandomAlloc() failed");
+
+        // Initialize vector with random data
+        for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+            rans->data.F64[i] = psRandomGaussian(myRNG);
+        }
+
+        // Perform vector stats on data (mean, stdev)
+        psVectorStats(stats, rans, NULL, NULL, 0);
+        stats->options = PS_STAT_SAMPLE_STDEV;
+        psVectorStats(stats, rans, NULL, NULL, 0);
+
+        // Verify mean and stdev
+        is_float_tol_per(stats->sampleMean, GAUSSIAN_MEAN, ERROR_TOLERANCE, "Mean is within expected range");
+        is_float_tol_per(stats->sampleStdev, GAUSSIAN_STDEV, ERROR_TOLERANCE, "StDev is within expected range");
+
+        skip_end();
+
+        psFree(myRNG);
+        psFree(rans);
+        psFree(stats);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Ensure psRandomGaussian() returns 0 for NULL psRandom struct
+    {
+        psMemId id = psMemGetId();
+        ok(psRandomGaussian(NULL) == 0, "Ensure psRandomGaussian() returns 0 for NULL psRandom struct");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testRandomPoisson(void)
+    {
+        diag("testRandomPoisson()");
+        psMemId id = psMemGetId();
+        psVector *rans = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+        rans->n = rans->nalloc;
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        psRandom *myRNG = psRandomAlloc(PS_RANDOM_TAUS, SEED);
+        ok(myRNG != NULL, "psRandom struct was allocated properly");
+        skip_start(myRNG == NULL, 2, "Skipping tests because psRandomAlloc() failed");
+
+        // Initialize vector with random data
+        for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+            rans->data.F64[i] = psRandomPoisson(myRNG, POISSON_MEAN);
+        }
+
+        // Perform vector stats on random data (mean, stdev)
+        psVectorStats(stats, rans, NULL, NULL, 0);
+        stats->options = PS_STAT_SAMPLE_STDEV;
+        psVectorStats(stats, rans, NULL, NULL, 0);
+        // Verify mean and stdev
+        is_float_tol_per(stats->sampleMean, POISSON_MEAN, ERROR_TOLERANCE, "Mean is within expected range");
+        is_float_tol_per(stats->sampleStdev, POISSON_STDEV, ERROR_TOLERANCE, "StDev is within expected range");
+
+        skip_end();
+
+        psFree(myRNG);
+        psFree(rans);
+        psFree(stats);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Ensure psRandomPoisson() returns 0 for NULL psRandom struct
+    {
+        psMemId id = psMemGetId();
+        ok(psRandomPoisson(NULL, POISSON_MEAN) == 0, "Ensure psRandomPoisson() returns 0 for NULL psRandom struct");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // testRandomResetUniform(void)
+    {
+        diag("testRandomUniform(): ensure the seed resets properly");
+        psMemId id = psMemGetId();
+        psVector *rans00 = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+        rans00->n = rans00->nalloc;
+        psVector *rans01 = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+        rans01->n = rans01->nalloc;
+        psVector *rans02 = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+        rans02->n = rans02->nalloc;
+
+        psRandom *myRNG = psRandomAlloc(PS_RANDOM_TAUS, SEED);
+        ok(myRNG != NULL, "psRandom struct was allocated properly");
+        skip_start(myRNG == NULL, 1, "Skipping tests because psRandomAlloc() failed");
+
+
+        // Random reset
+        psRandomReset(myRNG, SEED);
+        for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+            rans00->data.F64[i] = psRandomUniform(myRNG);
+        }
+        psRandomReset(myRNG, SEED2);
+        for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+            rans01->data.F64[i] = psRandomUniform(myRNG);
+        }
+        psRandomReset(myRNG, SEED);
+        for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+            rans02->data.F64[i] = psRandomUniform(myRNG);
+        }
+
+        // Verify reset to original seed produces same results
+        psBool errorFlag = false;
+        for (psS32 i = 0 ; i < NUM_DATA ; i++)
+        {
+            if (rans00->data.F64[i] != rans02->data.F64[i]) {
+                if (VERBOSE) {
+                    psError(PS_ERR_UNKNOWN,true,"psRandomUniform did not produce the same results with the same seed");
+                }
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psRandomUniform() produced the same results with the same seed");
+        skip_end();
+        psFree(myRNG);
+        psFree(rans00);
+        psFree(rans01);
+        psFree(rans02);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // XXX: How to test the proper generation of error messages?
+    if (0) {
+        psRandom *myRNG1 = NULL;
+        myRNG1 = psRandomAlloc(PS_RANDOM_TAUS, SEED);
+        //    psLogSetDestination("dest:stderr");
+        psLogSetDestination(0);
+        psRandomReset(myRNG1,0);
+        //    psLogSetDestination("dest:stderr");
+        psLogSetDestination(2);
+        psFree(myRNG1);
+
+        // Reset a NULL psRandom variable, should generate an error message
+        psRandomReset(NULL,SEED);
+    }
+
+    // testRandomResetGaussian(void)
+    {
+        // testRandomGaussian(): ensure the seed resets properly
+        psMemId id = psMemGetId();
+        psVector *rans00 = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+        rans00->n = rans00->nalloc;
+        psVector *rans01 = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+        rans01->n = rans01->nalloc;
+        psVector *rans02 = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+        rans02->n = rans02->nalloc;
+
+        psRandom *myRNG = psRandomAlloc(PS_RANDOM_TAUS, SEED);
+        ok(myRNG != NULL, "psRandom struct was allocated properly");
+        skip_start(myRNG == NULL, 1, "Skipping tests because psRandomAlloc() failed");
+
+
+        // Initialize random data in vectors
+        psRandomReset(myRNG, SEED);
+        for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+            rans00->data.F64[i] = psRandomGaussian(myRNG);
+        }
+        psRandomReset(myRNG, SEED2);
+        for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+            rans01->data.F64[i] = psRandomGaussian(myRNG);
+        }
+        psRandomReset(myRNG, SEED);
+        for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+            rans02->data.F64[i] = psRandomGaussian(myRNG);
+        }
+
+        // Verify data from original seed produces same data after reset
+        psBool errorFlag = false;
+        for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+            if (rans00->data.F64[i] != rans02->data.F64[i]) {
+                if (VERBOSE) {
+                    psError(PS_ERR_UNKNOWN,true,"psRandomGaussian did not produce the same results with the same seed");
+                }
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psRandomGaussian() produced the same results with the same seed");
+        skip_end();
+        psFree(myRNG);
+        psFree(rans00);
+        psFree(rans01);
+        psFree(rans02);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testRandomResetPoisson(void)
+    {
+        diag("testRandomPoisson(): ensure the seed resets properly");
+        psMemId id = psMemGetId();
+        psVector *rans00 = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+        rans00->n = rans00->nalloc;
+        psVector *rans01 = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+        rans01->n = rans01->nalloc;
+        psVector *rans02 = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+        rans02->n = rans02->nalloc;
+
+        psRandom *myRNG = psRandomAlloc(PS_RANDOM_TAUS, SEED);
+        ok(myRNG != NULL, "psRandom struct was allocated properly");
+        skip_start(myRNG == NULL, 1, "Skipping tests because psRandomAlloc() failed");
+
+        // Initialize vectors with random data
+        psRandomReset(myRNG, SEED);
+        for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+            rans00->data.F64[i] = psRandomPoisson(myRNG, POISSON_MEAN);
+        }
+        psRandomReset(myRNG, SEED2);
+        for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+            rans01->data.F64[i] = psRandomPoisson(myRNG, POISSON_MEAN);
+        }
+        psRandomReset(myRNG, SEED);
+        for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+            rans02->data.F64[i] = psRandomPoisson(myRNG, POISSON_MEAN);
+        }
+
+        // Verify the original seed produces same data after reset
+        psBool errorFlag = false;
+        for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+            if (rans00->data.F64[i] != rans02->data.F64[i]) {
+                if (VERBOSE) {
+                    psError(PS_ERR_UNKNOWN,true,"psRandomPoisson did not produce the same results with the same seed");
+                }
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psRandomPoisson() produced the same results with the same seed");
+        skip_end();
+        psFree(myRNG);
+        psFree(rans00);
+        psFree(rans01);
+        psFree(rans02);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psSparse.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psSparse.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psSparse.c	(revision 22158)
@@ -0,0 +1,397 @@
+    #include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(40);
+
+
+    // test psSparseAlloc()
+    {
+        psMemId id = psMemGetId();
+        psSparse *matrix = psSparseAlloc(10, 20);
+        ok(matrix != NULL, "psSparse successfully allocated");
+        skip_start(matrix == NULL, 12, "skipping tests because psSparseAlloc() returned NULL");
+        ok(matrix->Aij != NULL, "psSparseAlloc() set ->Aij correctly");
+        ok(matrix->Aij->n == 0, "psSparseAlloc() set ->Aij->n correctly");
+        ok(matrix->Si != NULL, "psSparseAlloc() set ->Si correctly");
+        ok(matrix->Si->n == 0, "psSparseAlloc() set ->Si->n correctly");
+        ok(matrix->Sj != NULL, "psSparseAlloc() set ->Sj correctly");
+        ok(matrix->Sj->n == 0, "psSparseAlloc() set ->Sj->n correctly");
+        ok(matrix->Bfj != NULL, "psSparseAlloc() set ->Bfj correctly");
+        ok(matrix->Bfj->n == 10, "psSparseAlloc() set ->Bfj->n correctly");
+        ok(matrix->Qii != NULL, "psSparseAlloc() set ->Qii correctly");
+        ok(matrix->Qii->n == 10, "psSparseAlloc() set ->Qii->n correctly");
+        ok(matrix->Nelem == 0, "psSparseAlloc() set ->Nelem correctly");
+        ok(matrix->Nrows == 10, "psSparseAlloc() set ->Nrows correctly");
+        skip_end();
+        psFree(matrix);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // test psSparseSolve for a simple normal example matrix
+    {
+        psMemId id = psMemGetId();
+        // the basic equation is Ax = b
+
+        // create a matrix A with diagonals of 1 and a small number of off diagonal elements.
+        // construct a vector x, construct the corresponding vector b by multiplication. solve
+        // Ax = b for x using psSparseSolve.  compare with the input values for x.
+
+        psSparse *matrix = psSparseAlloc(100, 100);
+        ok(matrix != NULL, "psSparse successfully allocated");
+        skip_start(matrix == NULL, 5, "Skipping tests because psSparseAlloc() failed");
+
+        for(int i = 0; i < 100; i++) {
+            psSparseMatrixElement(matrix, i, i, 1.0);
+            if (i + 1 < 100) {
+                psSparseMatrixElement(matrix, i + 1, i, 0.1);
+            }
+        }
+
+        // incoming matrix elements do not need to be in order; sort before
+        // applying sparse matrix
+        psSparseResort(matrix);
+
+        psVector *xRef = psVectorAlloc(100, PS_TYPE_F32);
+        for (int i = 0; i < 100; i++) {
+            xRef->data.F32[i] = 1.0;
+        }
+
+        psVector *bVec = psSparseMatrixTimesVector(NULL, matrix, xRef);
+
+        for (int i = 0; i < 100; i++) {
+            psSparseVectorElement(matrix, i, bVec->data.F32[i]);
+        }
+
+        psSparseConstraint constraint;
+        constraint.paramMin   = 0.0;
+        constraint.paramMax   = 1e8;
+        constraint.paramDelta = 1e8;
+
+        // solve for normalization terms (need include local sky?)
+        psVector *xFit = psSparseSolve(NULL, constraint, matrix, 4);
+
+        // measure stdev between xFit and xRes
+        float dS = 0;
+        float dS2 = 0;
+        for (int i = 0; i < 100; i++) {
+            float dX = xRef->data.F32[i] - xFit->data.F32[i];
+            // fprintf(stderr, "%5.3f %5.3f %5.3f %5.3f\n", bVec->data.F32[i], xRef->data.F32[i], xFit->data.F32[i], dX);
+            dS2 += PS_SQR(dX);
+            dS += dX;
+        }
+        dS /= 100.0;
+        dS2 = sqrt(dS2/100.0 - dS*dS);
+
+        is_float_tol(dS2, 0.0, 1e-4, "scatter: %.20f", dS2);
+
+        psFree(matrix);
+        psFree(xRef);
+        psFree(bVec);
+        psFree(xFit);
+
+        skip_end();
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test psSparseSolve for a simple non-normal example matrix
+    {
+        psMemId id = psMemGetId();
+        // the basic equation is Ax = b
+
+        // create a matrix A with diagonals of 1 and a small number of off diagonal elements.
+        // construct a vector x, construct the corresponding vector b by multiplication. solve
+        // Ax = b for x using psSparseSolve.  compare with the input values for x.
+
+        psSparse *matrix = psSparseAlloc(100, 100);
+        ok(matrix != NULL, "psSparse successfully allocated");
+        skip_start(matrix == NULL, 5, "Skipping tests because psSparseAlloc() failed");
+
+        for (int i = 0; i < 100; i++) {
+            psSparseMatrixElement(matrix, i, i, 5.0);
+            if (i + 1 < 100) {
+                psSparseMatrixElement(matrix, i + 1, i, 0.1);
+            }
+        }
+
+        // incoming matrix elements do not need to be in order; sort before
+        // applying sparse matrix
+        psSparseResort(matrix);
+
+        psVector *xRef = psVectorAlloc(100, PS_TYPE_F32);
+        for (int i = 0; i < 100; i++) {
+            xRef->data.F32[i] = 1.0;
+        }
+
+        psVector *bVec = psSparseMatrixTimesVector(NULL, matrix, xRef);
+
+        for (int i = 0; i < 100; i++) {
+            psSparseVectorElement(matrix, i, bVec->data.F32[i]);
+        }
+
+        psSparseConstraint constraint;
+        constraint.paramMin   = 0.0;
+        constraint.paramMax   = 1e8;
+        constraint.paramDelta = 1e8;
+
+        // solve for normalization terms(need include local sky?)
+        psVector *xFit = psSparseSolve(NULL, constraint, matrix, 4);
+
+        // measure stdev between xFit and xRes
+        float dS = 0;
+        float dS2 = 0;
+        for (int i = 0; i < 100; i++) {
+            float dX = xRef->data.F32[i] - xFit->data.F32[i];
+            // fprintf(stderr, "%5.3f %5.3f %5.3f %5.3f\n", bVec->data.F32[i], xRef->data.F32[i], xFit->data.F32[i], dX);
+            dS2 += PS_SQR(dX);
+            dS += dX;
+        }
+        dS /= 100.0;
+        dS2 = sqrt(dS2/100.0 - dS*dS);
+
+        is_float_tol(dS2, 0.0, 1e-4, "scatter: %.20f", dS2);
+
+        psFree(matrix);
+        psFree(xRef);
+        psFree(bVec);
+        psFree(xFit);
+
+        skip_end();
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    /* sample matrix equation:
+
+    1.0 0.1 0.1 | 1.0 |   |1.15|
+    0.1 1.0 0.2 | 1.0 | = |1.20|
+    0.1 0.2 0.5 | 0.5 |   |0.55|
+
+    lower product : 1.0*0.1 + 1.0*0.2 = 0.3
+    upper product : 0.1*0.5 = 0.05
+              : 0.2*0.5 = 0.10
+    */
+
+    // test psSparseBorderMultiply
+    {
+        psMemId id = psMemGetId();
+        // the basic equation(Ax = b) is:
+        // |S B'||x| = |f|
+        // |B Q ||y| = |g|
+
+        // construct a matrix S with diagonals of 1 and a small number of off diagonal elements.
+        // construct a border with finite values and a corresponding Q matrix
+        // construct a vector x, construct the corresponding vector b by multiplication. solve
+        // Ax = b for x using psSparseSolve.  compare with the input values for x.
+
+        int Nrows = 2;
+        int Nborder = 1;
+
+        // construct the sparse matrix
+        psSparse *matrix = psSparseAlloc(Nrows, Nrows);
+        ok(matrix != NULL, "psSparse successfully allocated");
+        skip_start(matrix == NULL, 5, "Skipping tests because psSparseAlloc() failed");
+
+        psSparseMatrixElement(matrix, 0, 0, 1.0);
+        psSparseMatrixElement(matrix, 1, 1, 1.0);
+        psSparseMatrixElement(matrix, 1, 0, 0.1);
+        psSparseResort(matrix);
+
+        // border region has a width of 1:
+        psSparseBorder *border = psSparseBorderAlloc(matrix, Nborder);
+
+        // construct the B component:
+        psSparseBorderElementB(border, 0, 0, 0.1);
+        psSparseBorderElementB(border, 1, 0, 0.2);
+
+        // construct the T component:
+        psSparseBorderElementT(border, 0, 0, 0.5);
+
+        // construct the X and Y vectors:
+        psVector *xRef = psVectorAlloc(Nrows, PS_TYPE_F32);
+        xRef->data.F32[0] = 1.0;
+        xRef->data.F32[1] = 1.0;
+        psVector *yRef = psVectorAlloc(Nborder, PS_TYPE_F32);
+        yRef->data.F32[0] = 0.5;
+
+        // construct the f and g vectors by multiplication:
+        psVector *fVec;
+
+        // test the support functions: LowerProduct
+        fVec = psSparseBorderLowerProduct(NULL, border, xRef);
+        is_float(fVec->n, 1.0, "f dimen: %d", fVec->n);
+        is_float(fVec->data.F32[0], 0.3, "f(0): %f", fVec->data.F32[0]);
+        psFree(fVec);
+
+        // test the support functions: Upper Product
+        fVec = psSparseBorderUpperProduct(NULL, border, yRef);
+        is_float(fVec->n, 2.0, "f dimen: %d", fVec->n);
+        is_float(fVec->data.F32[0], 0.05, "f(0): %f", fVec->data.F32[0]);
+        is_float(fVec->data.F32[1], 0.10, "f(0): %f", fVec->data.F32[1]);
+        psFree(fVec);
+
+        // test the support functions: Square Product
+        fVec = psSparseBorderSquareProduct(NULL, border, yRef);
+        is_float(fVec->n, 1.0, "f dimen: %d", fVec->n);
+        is_float(fVec->data.F32[0], 0.25, "f(0): %f", fVec->data.F32[0]);
+        psFree(fVec);
+
+        fVec = NULL;
+        psVector *gVec = NULL;
+        psSparseBorderMultiply(&fVec, &gVec, border, xRef, yRef);
+        is_float(fVec->data.F32[0], 1.15, "f(0): %f", fVec->data.F32[0]);
+        is_float(fVec->data.F32[1], 1.20, "f(1): %f", fVec->data.F32[1]);
+        is_float(gVec->data.F32[0], 0.55, "g(0): %f", gVec->data.F32[0]);
+
+        // supply the fVec and gVec data to the border
+        for (int i = 0; i < Nrows; i++) {
+            psSparseVectorElement(border->sparse, i, fVec->data.F32[i]);
+        }
+        for (int i = 0; i < Nborder; i++) {
+            psSparseBorderElementG(border, i, gVec->data.F32[i]);
+        }
+
+        // solve the border equation
+        psSparseConstraint constraint;
+        constraint.paramMin   = 0.0;
+        constraint.paramMax   = 1e8;
+        constraint.paramDelta = 1e8;
+
+        // solve for normalization terms (need include local sky?)
+        psVector *xFit = NULL;
+        psVector *yFit = NULL;
+        psSparseBorderSolve(&xFit, &yFit, constraint, border, 4);
+        is_float_tol(xFit->data.F32[0], 1.0, 1e-4, "f(0): %f", xFit->data.F32[0]);
+        is_float_tol(xFit->data.F32[1], 1.0, 1e-4, "f(1): %f", xFit->data.F32[1]);
+        is_float_tol(yFit->data.F32[0], 0.5, 1e-4, "g(0): %f", yFit->data.F32[0]);
+
+        psFree(xFit);
+        psFree(yFit);
+        psFree(fVec);
+        psFree(gVec);
+        psFree(xRef);
+        psFree(yRef);
+        psFree(border);
+        psFree(matrix);
+        skip_end();
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test psSparseBorderSolve for a simple example matrix
+    {
+        psMemId id = psMemGetId();
+        // the basic equation(Ax = b) is:
+        // |S B'||x| = |f|
+        // |B Q ||y| = |g|
+
+        // construct a matrix S with diagonals of 1 and a small number of off diagonal elements.
+        // construct a border with finite values and a corresponding Q matrix
+        // construct a vector x, construct the corresponding vector b by multiplication. solve
+        // Ax = b for x using psSparseSolve.  compare with the input values for x.
+
+        int Nrows = 10;
+        int Nborder = 1;
+
+        // construct the sparse matrix
+        psSparse *matrix = psSparseAlloc(Nrows, Nrows);
+        ok(matrix != NULL, "psSparse successfully allocated");
+        skip_start(matrix == NULL, 5, "Skipping tests because psSparseAlloc() failed");
+
+        for (int i = 0; i < Nrows; i++) {
+            psSparseMatrixElement(matrix, i, i, 1.0);
+            if (i + 1 < Nrows) {
+                psSparseMatrixElement(matrix, i + 1, i, 0.1);
+            }
+        }
+        psSparseResort(matrix);
+
+        // border region has a width of 1:
+        psSparseBorder *border = psSparseBorderAlloc(matrix, Nborder);
+
+        // construct the B component:
+        for (int i = 0; i < Nrows; i++) {
+            for (int j = 0; j < Nborder; j++) {
+                psSparseBorderElementB(border, i, j, 0.1);
+            }
+        }
+        is_float(border->Bij->data.F32[0][0], 0.1, "set matrix element %d,%d", 0, 0);
+
+        // construct the Q component:
+        for (int i = 0; i < Nborder; i++) {
+            for (int j = 0; j < Nborder; j++) {
+                psSparseBorderElementT(border, i, j, i+j+2);
+            }
+        }
+
+        // construct the X and Y vectors:
+        psVector *xRef = psVectorAlloc(Nrows, PS_TYPE_F32);
+        for (int i = 0; i < Nrows; i++) {
+            xRef->data.F32[i] = 1.0;
+        }
+        psVector *yRef = psVectorAlloc(Nborder, PS_TYPE_F32);
+        for (int i = 0; i < Nborder; i++) {
+            yRef->data.F32[i] = 1.0;
+        }
+
+        // construct the f and g vectors by multiplication:
+        psVector *fVec = NULL;
+        psVector *gVec = NULL;
+        psSparseBorderMultiply(&fVec, &gVec, border, xRef, yRef);
+
+        // supply the fVec and gVec data to the border
+        for (int i = 0; i < Nrows; i++) {
+            psSparseVectorElement(border->sparse, i, fVec->data.F32[i]);
+        }
+        for (int i = 0; i < Nborder; i++) {
+            psSparseBorderElementG(border, i, gVec->data.F32[i]);
+        }
+
+        // solve the border equation
+        psSparseConstraint constraint;
+        constraint.paramMin   = 0.0;
+        constraint.paramMax   = 1e8;
+        constraint.paramDelta = 1e8;
+
+        // solve for normalization terms(need include local sky?)
+        psVector *xFit = NULL;
+        psVector *yFit = NULL;
+        psSparseBorderSolve(&xFit, &yFit, constraint, border, 4);
+
+        // measure stdev between xFit and xRef
+        float dS = 0;
+        float dS2 = 0;
+        for (int i = 0; i < Nrows; i++) {
+            float dX = xRef->data.F32[i] - xFit->data.F32[i];
+            // fprintf(stderr, "%5.3f %5.3f %5.3f %5.3f\n", fVec->data.F32[i], xRef->data.F32[i], xFit->data.F32[i], dX);
+            dS2 += PS_SQR(dX);
+            dS += dX;
+        }
+        dS /= Nrows;
+        dS2 = sqrt(dS2/Nrows - dS*dS);
+        is_float_tol(dS2, 0.0, 1e-4, "scatter: %.20f", dS2);
+
+        // measure stdev between yFit and yRef
+        float dY = yRef->data.F32[0] - yFit->data.F32[0];
+        // fprintf(stderr, "%5.3f %5.3f %5.3f %5.3f\n", gVec->data.F32[0], yRef->data.F32[0], yFit->data.F32[0], dS);
+        is_float_tol(dY, 0.0, 2e-4, "scatter: %.20f", dY);
+
+        psFree(xRef);
+        psFree(yRef);
+        psFree(xFit);
+        psFree(yFit);
+        psFree(fVec);
+        psFree(gVec);
+        psFree(matrix);
+        psFree(border);
+
+        skip_end();
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psSpline1D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psSpline1D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psSpline1D.c	(revision 22158)
@@ -0,0 +1,336 @@
+/* @file  tst_psImageManip.c
+*
+*  @brief This file will contain tests for all of the public psLib functions
+*         that implement 1-D spline functionality:
+* psSpline1DAlloc()
+* psSpline1DEval()
+* psSpline1DEvalVector()
+* psVectorFitSpline1D()
+*
+*         This file is composed of the tests formerly in tst_psFunc02.c,
+*         tst_psFunc03.c, tst_psFunc04.c, tst_psFunc05.c, and tst_psFunc07.c.
+*
+*  @author GLG, MHPCC
+*
+*  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-05-02 04:20:06 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define ERROR_TOLERANCE_PERCENT    1.00
+#define VERBOSE 0
+/*********************************************************************************
+CheckErrorF32(psF32 actual, psF32 expect): this routine returns FALSE if the
+actual and expect arguments are with ERROR_TOLERANCE_PERCENT of each other,
+otherwise it returns TRUE.
+ ********************************************************************************/
+psBool CheckErrorF32(
+    psF32 actual,
+    psF32 expect)
+{
+    if ((fabs(actual - expect) / fabs(expect)) > ERROR_TOLERANCE_PERCENT) {
+        return(true);
+    } else {
+        return(false);
+    }
+}
+/*********************************************************************************
+CheckErrorF64(psF64 actual, psF64 expect): this routine returns FALSE if the
+actual and expect arguments are with ERROR_TOLERANCE_PERCENT of each other,
+otherwise it returns TRUE.
+ ********************************************************************************/
+psBool CheckErrorF64(
+    psF64 actual,
+    psF64 expect)
+{
+    if ((fabs(actual - expect) / fabs(expect)) > ERROR_TOLERANCE_PERCENT) {
+        return(true);
+    } else {
+        return(false);
+    }
+}
+
+psF32 myFunc00(psF32 x)
+{
+    return(x);
+}
+
+psF64 myFunc00_F64(psF64 x)
+{
+    return(x);
+}
+
+#define A 4.0
+#define B -3.0
+#define C 0.2
+#define D 0.1
+psF32 myFunc01(psF32 x)
+{
+    return(A + x * (B + x * (C + x * (D))));
+}
+psF64 myFunc01_F64(psF64 x)
+{
+    return(A + x * (B + x * (C + x * (D))));
+}
+
+typedef psF32 (*mappingFuncF32)(psF32 x);
+typedef psF64 (*mappingFuncF64)(psF64 x);
+
+bool genericF32Test(psS32 NumSplines, mappingFuncF32 func, bool xNull)
+{
+    // We test the psVectorFitSpline1D, psSpline1DEval() functions.  F32 version.
+    bool testStatus = true;
+    {
+        psMemId id = psMemGetId();
+        psVector *xF32 = psVectorAlloc(NumSplines+1, PS_TYPE_F32);
+        psVector *yF32 = psVectorAlloc(NumSplines+1, PS_TYPE_F32);
+        for (psS32 i=0;i<NumSplines+1;i++) {
+            xF32->data.F32[i] = (psF32) i;
+            yF32->data.F32[i] = (psF32) func((psF32) i);
+        }
+
+        psSpline1D *tmpSpline = NULL;
+        if (!xNull) {
+            tmpSpline = psVectorFitSpline1D(xF32, yF32);
+        } else {
+            tmpSpline = psVectorFitSpline1D(NULL, yF32);
+        }
+        if(tmpSpline == NULL) {
+            diag("psVectorFitSpline1D() returned NULL");
+            testStatus = false;
+        } else {
+            if (tmpSpline->n != NumSplines) {
+                diag("psVectorFitSpline1D() did not properly set the psSpline1D->n member");
+                testStatus = false;
+            }
+            if(tmpSpline->spline == NULL) {
+                diag("psVectorFitSpline1D() returned a NULL psSpline1D->spline member.");
+                testStatus = false;
+            }
+            for (psS32 i = 0 ; i < NumSplines ; i++) {
+                if (tmpSpline->spline[i] == NULL) {
+                    diag("psVectorFitSpline1D() returned a NULL psSpline1D->spline[%d] member.", i);
+                    testStatus = false;
+                }
+            }
+            if (tmpSpline->knots == NULL) {
+                diag("psVectorFitSpline1D() returned a NULL psSpline1D->knots member");
+                testStatus = false;
+            }
+            if (tmpSpline->p_psDeriv2 == NULL) {
+                diag("psVectorFitSpline1D()returned a NULL psSpline1D->p_psDeriv2 member");
+                testStatus = false;
+            }
+
+            // Test psSpline1DEval()
+            for (psS32 i=0;i<NumSplines;i++) {
+                psF32 x = 0.5 + (float) i;
+                psF32 y = psSpline1DEval(tmpSpline, x);
+                if (CheckErrorF32(y, func(x))) {
+                    testStatus = false;
+                    diag("TEST ERROR: f(%f) is %f, should be %f", x, y, myFunc00(x));
+                }
+            }
+
+            // Test psSpline1DEvalVector()
+            psVector *yF32Test = psSpline1DEvalVector(tmpSpline, xF32);
+            if (yF32Test == NULL) {
+                testStatus = false;
+                diag("TEST ERROR: psSpline1DEvalVector() returned NULL");
+            } else {
+                for (psS32 i=0;i<NumSplines;i++) {
+                    if (CheckErrorF32(yF32Test->data.F32[i], func(xF32->data.F32[i]))) {
+                        testStatus = false;
+                        diag("TEST ERROR: f(%f) is %f, should be %f", xF32->data.F32[i],
+                             yF32Test->data.F32[i], myFunc00(xF32->data.F32[i]));
+                    }
+                }
+                psFree(yF32Test);
+            }
+        }
+
+        psFree(tmpSpline);
+        psFree(xF32);
+        psFree(yF32);
+        if (psMemCheckLeaks (id, NULL, NULL, false)) {
+            diag("TEST ERROR: memory leaks");
+            testStatus = false;
+        }
+    }
+    return(testStatus);
+}
+
+
+// This is a duplicate cut-n-paste of the F32 function
+bool genericF64Test(psS32 NumSplines, mappingFuncF64 func, bool xNull)
+{
+    // We test the psVectorFitSpline1D, psSpline1DEval() functions.  F64 version.
+    bool testStatus = true;
+    {
+        psMemId id = psMemGetId();
+        psVector *xF64 = psVectorAlloc(NumSplines+1, PS_TYPE_F64);
+        psVector *yF64 = psVectorAlloc(NumSplines+1, PS_TYPE_F64);
+        for (psS32 i=0;i<NumSplines+1;i++) {
+            xF64->data.F64[i] = (psF64) i;
+            yF64->data.F64[i] = (psF64) func((psF64) i);
+        }
+
+        psSpline1D *tmpSpline = NULL;
+        if (!xNull) {
+            tmpSpline = psVectorFitSpline1D(xF64, yF64);
+        } else {
+            tmpSpline = psVectorFitSpline1D(NULL, yF64);
+        }
+        if(tmpSpline == NULL) {
+            diag("psVectorFitSpline1D() returned NULL");
+            testStatus = false;
+        } else {
+            if (tmpSpline->n != NumSplines) {
+                diag("psVectorFitSpline1D() did not properly set the psSpline1D->n member");
+                testStatus = false;
+            }
+            if(tmpSpline->spline == NULL) {
+                diag("psVectorFitSpline1D() returned a NULL psSpline1D->spline member.");
+                testStatus = false;
+            }
+            for (psS32 i = 0 ; i < NumSplines ; i++) {
+                if (tmpSpline->spline[i] == NULL) {
+                    diag("psVectorFitSpline1D() returned a NULL psSpline1D->spline[%d] member.", i);
+                    testStatus = false;
+                }
+            }
+            if (tmpSpline->knots == NULL) {
+                diag("psVectorFitSpline1D() returned a NULL psSpline1D->knots member");
+                testStatus = false;
+            }
+            if (tmpSpline->p_psDeriv2 == NULL) {
+                diag("psVectorFitSpline1D()returned a NULL psSpline1D->p_psDeriv2 member");
+                testStatus = false;
+            }
+
+            // Test psSpline1DEval()
+            for (psS32 i=0;i<NumSplines;i++) {
+                psF64 x = 0.5 + (float) i;
+                psF64 y = psSpline1DEval(tmpSpline, x);
+                if (CheckErrorF64(y, func(x))) {
+                    testStatus = false;
+                    diag("TEST ERROR psSpline1DEval(): f(%f) is %f, should be %f", x, y, myFunc00(x));
+                }
+            }
+
+            // Test psSpline1DEvalVector()
+            psVector *yF64Test = psSpline1DEvalVector(tmpSpline, xF64);
+            if (yF64Test == NULL) {
+                testStatus = false;
+                diag("TEST ERROR: psSpline1DEvalVector() returned NULL");
+            } else {
+                for (psS32 i=0;i<NumSplines;i++) {
+                    if (CheckErrorF64((psF64)yF64Test->data.F32[i], func(xF64->data.F64[i]))) {
+                        testStatus = false;
+                        diag("TEST ERROR psSpline1DEvalVector(): f(%f) is %f, should be %f", xF64->data.F64[i],
+                             yF64Test->data.F32[i], myFunc00(xF64->data.F64[i]));
+                    }
+                }
+                psFree(yF64Test);
+            }
+        }
+
+        psFree(tmpSpline);
+        psFree(xF64);
+        psFree(yF64);
+        if (psMemCheckLeaks (id, NULL, NULL, false)) {
+            diag("TEST ERROR: memory leaks");
+            testStatus = false;
+        }
+    }
+    return(testStatus);
+}
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel( PS_LOG_INFO );
+    plan_tests(28);
+
+    // psSplineAllocTest()
+    {
+        psMemId id = psMemGetId();
+        psSpline1D *tmpSpline = psSpline1DAlloc();
+        ok(tmpSpline != NULL, "psSpline1DAlloc() returned non-NULL");
+        skip_start(tmpSpline == NULL, 4, "Skipping tests because psSpline1DAlloc() failed");
+        ok(tmpSpline->n == 0, "psSpline1DAlloc() properly set the psSpline1D->n member");
+        ok(tmpSpline->spline == NULL, "psSpline1DAlloc() properly set the psSpline1D->spline member");
+        ok(tmpSpline->knots == NULL, "psSpline1DAlloc() properly set the psSpline1D->knots member");
+        ok(tmpSpline->p_psDeriv2 == NULL, "psSpline1DAlloc() properly set the psSpline1D->p_psDeriv2 member");
+        psFree(tmpSpline);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psSplineEvalTest_sub(): Call psVectorFitSpline1D with NULL arguments.
+    {
+        psMemId id = psMemGetId();
+        psSpline1D *tmpSpline = psVectorFitSpline1D(NULL, NULL);
+        ok(tmpSpline == NULL, "psVectorFitSpline1D() returns NULL with NULL arguments");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Verify psSpline1DEval() for NULL input
+    // Verify with spline->n==0, and spline->knots PS_TYPE_F64
+    {
+        psMemId id = psMemGetId();
+        float y = psSpline1DEval(NULL, 0.0);
+        ok(isnan(y), "psSpline1DEval() returned NAN will NULL input spline");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify psSpline1DEvalVector() for NULL input spline
+    {
+        psMemId id = psMemGetId();
+        psVector *x = psVectorAlloc(10, PS_TYPE_F32);
+        psVector *y = psSpline1DEvalVector(NULL, x);
+        ok(y == NULL, "psSpline1DEvalVector() returned NAN will NULL input spline");
+        psFree(x);
+        psFree(y);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify psSpline1DEvalVector() for NULL input vector
+    // XXX: Move this where we have a good spline.  It currently fails because
+    // were calling it with an un-fully-allocated one.
+    if (0) {
+        psMemId id = psMemGetId();
+        psSpline1D *tmpSpline = psSpline1DAlloc();
+        psVector *y = psSpline1DEvalVector(tmpSpline, NULL);
+        ok(y == NULL, "psSpline1DEvalVector() returned NAN will NULL input vector");
+        psFree(tmpSpline);
+        psFree(y);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    ok(genericF32Test(1, myFunc00, false), "Generic, simple mapping, F32 test. 1 spline");
+    ok(genericF32Test(95, myFunc00, false), "Generic, simple mapping, F32 test. 95 splines");
+    ok(genericF32Test(1, myFunc01, false), "Generic, simple mapping, F32 test. 1 spline");
+    ok(genericF32Test(95, myFunc01, false), "Generic, simple mapping, F32 test. 95 splines");
+    ok(genericF32Test(1, myFunc00, true), "Generic, simple mapping, F32 test. 1 spline");
+    ok(genericF32Test(95, myFunc00, true), "Generic, simple mapping, F32 test. 95 splines");
+    ok(genericF32Test(1, myFunc01, true), "Generic, simple mapping, F32 test. 1 spline");
+    ok(genericF32Test(95, myFunc01, true), "Generic, simple mapping, F32 test. 95 splines");
+    ok(genericF64Test(1, myFunc00_F64, false), "Generic, simple mapping, F64 test. 1 spline");
+    ok(genericF64Test(95, myFunc00_F64, false), "Generic, simple mapping, F64 test. 95 splines");
+    ok(genericF64Test(1, myFunc01_F64, false), "Generic, simple mapping, F64 test. 1 spline");
+    ok(genericF64Test(95, myFunc01_F64, false), "Generic, simple mapping, F64 test. 95 splines");
+    ok(genericF64Test(1, myFunc00_F64, true), "Generic, simple mapping, F64 test. 1 spline");
+    ok(genericF64Test(95, myFunc00_F64, true), "Generic, simple mapping, F64 test. 95 splines");
+    ok(genericF64Test(1, myFunc01_F64, true), "Generic, simple mapping, F64 test. 1 spline");
+    ok(genericF64Test(95, myFunc01_F64, true), "Generic, simple mapping, F64 test. 95 splines");
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats00.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats00.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats00.c	(revision 22158)
@@ -0,0 +1,292 @@
+/** @file  tst_psStats00.c
+ *
+ *  @brief Contains tests for psVectorStats with sample mean calculations
+ *
+ 
+ *  We extensively test the code with data type PS_TYPE_F32.  If these pass, we do a much
+ *  simpler test with data type PS_TYPE_U8, PS_TYPE_U16, PS_TYPE_F64.
+ *
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-05-08 06:21:16 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define N 15
+
+static psF32 samplesF32[N] =
+    {
+        1.1, 2.2, -3.3, 4.4, 5.5, -6.6, 7.7, 8.8, -9.9, 10.0,
+        11.01, -12.02, 13.03, 14.04, -15.05
+    };
+static psS8  samplesS8[N]  =
+    {
+        1, 2, -3, 4, 5, -6, 7, 8, -9, 10, 11, -12, 13, 14, -15
+    };
+static psU16 samplesU16[N] =
+    {
+        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+    };
+static psF64 samplesF64[N] =
+    {
+        1.1, 2.2, -3.3, 4.4, 5.5, -6.6, 7.7, 8.8, -9.9, 10.0,
+        11.01, -12.02, 13.03, 14.04, -15.05
+    };
+static psF32 errorsF32[N] =
+    {
+        -0.10,  0.11, -0.12,  0.13, -0.14,  0.15, -0.16,  0.17,
+        -0.18,  0.19, -0.20,  0.21, -0.22,  0.23, -0.24
+    };
+
+static psF64 expectedMeanNoMaskF32              =  2.060667;
+static psF64 expectedMeanWithMaskF32            =  2.123846;
+static psF64 expectedMeanNoMaskS8               =  2.000000;
+static psF64 expectedMeanNoMaskU16              =  8.000000;
+static psF64 expectedMeanNoMaskF64              =  2.060667;
+static psF64 expectedMeanRangeNoMaskF32         =  0.137500;
+static psF64 expectedMeanRangeWithMaskF32       = -0.366667;
+static psF64 expectedWeightMeanNoMaskF32        =  2.020035;
+static psF64 expectedWeightMeanWithMaskF32      =  2.036018;
+static psF64 expectedWeightMeanNoMaskRangeF32   = -0.650684;
+static psF64 expectedWeightMeanWithMaskRangeF32 = -1.046423;
+
+#include <unistd.h>
+psS32 main(psS32 argc, char* argv[] )
+{
+    psMemId idGlobal = psMemGetId();
+    psLogSetFormat("HLNM");
+    plan_tests(60);
+
+    // Allocate data vectors for F32 tests
+    psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    psVector *myVector = psVectorAlloc(N, PS_TYPE_F32);
+    psVector *myErrors = psVectorAlloc(N, PS_TYPE_F32);
+    psVector *maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    // Set the appropriate values for the vector data.
+    for (long i = 0; i < N; i++) {
+        myVector->data.F32[i] =  samplesF32[i];
+        myErrors->data.F32[i] =  errorsF32[i];
+        if (i > 1) {
+            maskVector->data.U8[i] = 0;
+        } else {
+            maskVector->data.U8[i] = 1;
+        }
+    }
+
+    // Call psVectorStats() with no vector mask.
+    {
+        psMemId id = psMemGetId();
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(result, "psVectorStats suceeded (F32: no mask vector, no error vector)");
+        ok(!isnan(myStats->sampleMean), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleMean, expectedMeanNoMaskF32, 1e-4,
+                     "The mean was %f, should be %f", myStats->sampleMean, expectedMeanNoMaskF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Invoke psVectorStats with no vector mask and error vector
+    {
+        psMemId id = psMemGetId();
+        bool result = psVectorStats(myStats, myVector, myErrors, NULL, 0);
+        ok(result, "psVectorStats suceeded (F32: no mask vector, with error vector)");
+        ok(!isnan(myStats->sampleMean), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleMean, expectedWeightMeanNoMaskF32, 1e-4, "The mean was %f, should be %f", myStats->sampleMean, expectedWeightMeanNoMaskF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Invoke psVectorStats with no vector mask and data range
+    {
+        psMemId id = psMemGetId();
+        myStats->options = PS_STAT_SAMPLE_MEAN | PS_STAT_USE_RANGE;
+        myStats->min = -10.0;
+        myStats->max =   8.0;
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(result, "psVectorStats suceeded (F32, no mask, no errors, with data range)");
+        ok(!isnan(myStats->sampleMean), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleMean, expectedMeanRangeNoMaskF32, 1e-4, "The mean was %f, should be %f", myStats->sampleMean, expectedMeanRangeNoMaskF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Invoke psVectorStats with no vector mask, errors and data range
+    {
+        psMemId id = psMemGetId();
+        myStats->options = PS_STAT_SAMPLE_MEAN | PS_STAT_USE_RANGE;
+        bool result = psVectorStats(myStats, myVector, myErrors, NULL, 0);
+        ok(result, "psVectorStats suceeded (F32, no mask, with errors and data range)");
+        ok(!isnan(myStats->sampleMean), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleMean, expectedWeightMeanNoMaskRangeF32, 1e-4, "The mean was %f, should be %f", myStats->sampleMean, expectedWeightMeanNoMaskRangeF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Call psVectorStats() with vector mask=1
+    {
+        psMemId id = psMemGetId();
+        myStats->options = PS_STAT_SAMPLE_MEAN;
+        bool result = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+        ok(result, "psVectorStats suceeded (F32, with mask, no errors)");
+        ok(!isnan(myStats->sampleMean), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleMean, expectedMeanWithMaskF32, 1e-4, "The mean was %f, should be %f", myStats->sampleMean, expectedMeanWithMaskF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Invoke psVectorStats with vector mask and error vector
+    {
+        psMemId id = psMemGetId();
+        bool result = psVectorStats(myStats, myVector, myErrors, maskVector, 1);
+        ok(result, "psVectorStats suceeded (F32, with mask and errors)");
+        ok(!isnan(myStats->sampleMean), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleMean, expectedWeightMeanWithMaskF32, 1e-4, "The mean was %f, should be %f", myStats->sampleMean, expectedWeightMeanWithMaskF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Invoke psVectorStats with vector mask and data range
+    {
+        psMemId id = psMemGetId();
+        myStats->options = PS_STAT_SAMPLE_MEAN | PS_STAT_USE_RANGE;
+        bool result = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+        ok(result, "psVectorStats suceeded (F32, with mask and data range)");
+        ok(!isnan(myStats->sampleMean), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleMean, expectedMeanRangeWithMaskF32, 1e-4, "The mean was %f, should be %f", myStats->sampleMean, expectedMeanRangeWithMaskF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Invoke psVectorStats with vector mask, errors, and data range
+    {
+        psMemId id = psMemGetId();
+        bool result = psVectorStats(myStats, myVector, myErrors, maskVector, 1);
+        ok(result, "psVectorStats suceeded (F32, withmask, errors, and data range)");
+        ok(!isnan(myStats->sampleMean), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleMean, expectedWeightMeanWithMaskRangeF32, 1e-4, "The mean was %f, should be %f", myStats->sampleMean, expectedWeightMeanWithMaskRangeF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Call psVectorStats() with vector mask=2.
+    {
+        psMemId id = psMemGetId();
+        myStats->options = PS_STAT_SAMPLE_MEAN;
+        for (psS32 i = 0; i < N; i++) {
+            if (maskVector->data.U8[i] == 1) {
+                maskVector->data.U8[i] = 2;
+            }
+        }
+        bool result = psVectorStats(myStats, myVector, NULL, maskVector, 2);
+        ok(result, "psVectorStats suceeded (F32, with mask = 2, no errors)");
+        ok(!isnan(myStats->sampleMean), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleMean, expectedMeanWithMaskF32, 1e-4, "The mean was %f, should be %f", myStats->sampleMean, expectedMeanWithMaskF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Call psVectorStats() with vector mask=3.
+    {
+        psMemId id = psMemGetId();
+        for (psS32 i = 0; i < N; i++)
+        {
+            if (maskVector->data.U8[i] == 2) {
+                maskVector->data.U8[i] = 3;
+            }
+        }
+        bool result = psVectorStats(myStats, myVector, NULL, maskVector, 4);
+        ok(result, "psVectorStats suceeded (F32, with mask = 3, no errors)");
+        ok(!isnan(myStats->sampleMean), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleMean, expectedMeanNoMaskF32, 1e-4, "The mean was %f, should be %f", myStats->sampleMean, expectedMeanNoMaskF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Mask all values and verify return is FALSE
+    {
+        psMemId id = psMemGetId();
+        for(psS32 i = 0; i < N; i++)
+        {
+            maskVector->data.U8[i] = 1;
+        }
+        bool result = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+        ok(result == true, "psVectorStats() returned TRUE (All values masked)");
+        ok(isnan(myStats->sampleMean), "psVectorStats() returned NAN");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Call psVectorStats() with NULL inputs.
+    {
+        psMemId id = psMemGetId();
+        ok(!psVectorStats(myStats, NULL, NULL, NULL, 0), "psVectorStats() returned false with NULL inputs");
+        ok(!psVectorStats(NULL, myVector, NULL, NULL, 0), "psVectorStats() returned false with NULL inputs");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    psFree(myStats);
+    psFree(myVector);
+    psFree(myErrors);
+    psFree(maskVector);
+    ok(!psMemCheckLeaks (idGlobal, NULL, NULL, false), "no memory leaks");
+    ok(!psMemCheckLeaks (idGlobal, NULL, NULL, false), "no memory leaks");
+
+
+    // Test SampleMean: S8
+    {
+        psMemId id = psMemGetId();
+        psStats* myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        psVector* myVector = psVectorAlloc(N, PS_TYPE_S8);
+        for (psS32 i = 0; i < N; i++)
+        {
+            myVector->data.S8[i] =  samplesS8[i];
+        }
+
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(result, "psVectorStats suceeded (S8, no mask, no errors)");
+        ok(!isnan(myStats->sampleMean), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleMean, expectedMeanNoMaskS8, 1e-4, "The mean was %f, should be %f", myStats->sampleMean, expectedMeanNoMaskS8);
+        psFree(myStats);
+        psFree(myVector);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test SampleMean: U16
+    {
+        psMemId id = psMemGetId();
+        psStats* myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        psVector* myVector = psVectorAlloc(N, PS_TYPE_U16);
+        myVector->n = N;
+        for (psS32 i = 0; i < N; i++)
+        {
+            myVector->data.U16[i] =  samplesU16[i];
+        }
+
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(result, "psVectorStats suceeded (U16, no mask, no errors)");
+        ok(!isnan(myStats->sampleMean), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleMean, expectedMeanNoMaskU16, 1e-4, "The mean was %f, should be %f", myStats->sampleMean, expectedMeanNoMaskU16);
+        psFree(myStats);
+        psFree(myVector);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test SampleMean: F64
+    {
+        psMemId id = psMemGetId();
+        psStats* myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        psVector* myVector = psVectorAlloc(N, PS_TYPE_F64);
+        myVector->n = N;
+        for (psS32 i = 0; i < N; i++)
+        {
+            myVector->data.F64[i] =  samplesF64[i];
+        }
+
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(result, "psVectorStats suceeded (F64, no mask, no errors)");
+        ok(!isnan(myStats->sampleMean), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleMean, expectedMeanNoMaskF64, 1e-4, "The mean was %f, should be %f", myStats->sampleMean, expectedMeanNoMaskF64);
+        psFree(myStats);
+        psFree(myVector);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats01.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats01.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats01.c	(revision 22158)
@@ -0,0 +1,187 @@
+/** @file  tst_psStats01.c
+*
+*  @brief Contains tests for psVectorStats with max calculations.
+*
+*  We extensively test the code with data type PS_TYPE_F32.  If these pass, we
+*  do a much simpler test with data types PS_TYPE_U8, PS_TYPE_U16, PS_TYPE_F64.
+*
+*  @author GLG, MHPCC
+*
+*  @version $Revision: 1.4 $  $Name: not supported by cvs2svn $
+*  @date $Date: 2007-03-27 22:52:03 $
+*
+* Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define N 15
+
+static psF32 samplesF32[N] = { 1.1, 2.2, -3.3, 4.4, 5.5, -6.6, 7.7, 8.8, -9.9, 10.0,
+                               11.01, -12.02, 13.03, 14.04, -15.05 };
+static psS8  samplesS8[N]  = {1, 2, -3, 4, 5, -6, 7, 8, -9, 10, 11, -12, 13, 14, -15};
+static psU16 samplesU16[N] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+static psF64 samplesF64[N] = { 1.1, 2.2, -3.3, 4.4, 5.5, -6.6, 7.7, 8.8, -9.9, 10.0,
+                               11.01, -12.02, 13.03, 14.04, -15.05 };
+
+static psF64 expectedMaxNoMaskF32                = 14.04;
+static psF64 expectedMaxNoMaskS8                 = 14.00;
+static psF64 expectedMaxNoMaskU16                = 15.00;
+static psF64 expectedMaxNoMaskF64                = 14.04;
+
+static psF64 expectedMaxWithMaskF32              = 13.03;
+static psF64 expectedMaxRangeNoMaskF32           = 10.00;
+static psF64 expectedMaxRangeWithMaskF32         = 13.03;
+
+psS32 main(psS32 argc, char* argv[] )
+{
+    psMemId idGlobal = psMemGetId();
+    psLogSetFormat("HLNM");
+    plan_tests(32);
+
+    psStats* myStats = psStatsAlloc(PS_STAT_MAX);
+    psVector* myVector =  psVectorAlloc(N, PS_TYPE_F32);
+    myVector->n = N;
+    psVector* maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    maskVector->n = N;
+    for (psS32 i = 0; i < N; i++) {
+        myVector->data.F32[i] = samplesF32[i];
+        if (i < 13) {
+            maskVector->data.U8[i] = 0;
+        } else {
+            maskVector->data.U8[i] = 1;
+        }
+    }
+
+    // Call psVectorStats() with no vector mask
+    {
+        psMemId id = psMemGetId();
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(result, "psVectorStats suceeded");
+        ok(!isnan(myStats->max), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->max, expectedMaxNoMaskF32, 1e-4,
+                     "The max was %f, should be %f", myStats->max, expectedMaxNoMaskF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Call psVectorStats() with vector mask
+    {
+        psMemId id = psMemGetId();
+        bool result = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+        ok(result, "psVectorStats suceeded");
+        ok(!isnan(myStats->max), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->max, expectedMaxWithMaskF32, 1e-4,
+                     "The max was %f, should be %f", myStats->max, expectedMaxWithMaskF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Invoke function with data range with no mask
+    {
+        psMemId id = psMemGetId();
+        myStats->options = PS_STAT_MAX | PS_STAT_USE_RANGE;
+        myStats->max = 10.2;
+        myStats->min = 0.0;
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(result, "psVectorStats suceeded");
+        ok(!isnan(myStats->max), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->max, expectedMaxRangeNoMaskF32, 1e-4,
+                     "The max was %f, should be %f", myStats->max, expectedMaxRangeNoMaskF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Invoke function with data range and mask
+    {
+        psMemId id = psMemGetId();
+        myStats->max = 14.0;
+        myStats->min = 0.0;
+        bool result = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+        ok(result, "psVectorStats suceeded");
+        ok(!isnan(myStats->max), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->max, expectedMaxRangeWithMaskF32, 1e-4,
+                     "The max was %f, should be %f", myStats->max, expectedMaxRangeWithMaskF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Invoke function with data range with no valid data
+    {
+        psMemId id = psMemGetId();
+        myStats->max = 100.00;
+        myStats->min = 90.00;
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(!result, "psVectorStats failed as expected");
+        ok(isnan(myStats->max), "psVectorStats() returned NAN");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    psFree(myStats);
+    psFree(myVector);
+    psFree(maskVector);
+    ok(!psMemCheckLeaks (idGlobal, NULL, NULL, false), "no memory leaks");
+
+    // Test StatsMax: S8
+    {
+        psMemId id = psMemGetId();
+        psStats* myStats = psStatsAlloc(PS_STAT_MAX);
+        psVector* myVector = psVectorAlloc(N, PS_TYPE_S8);
+        myVector->n = N;
+        for (psS32 i = 0; i < N; i++)
+        {
+            myVector->data.S8[i] = samplesS8[i];
+        }
+
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(result, "psVectorStats suceeded");
+        ok(!isnan(myStats->max), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->max, expectedMaxNoMaskS8, 1e-4,
+                     "The max was %f, should be %f", myStats->max, expectedMaxNoMaskS8);
+        psFree(myStats);
+        psFree(myVector);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test StatsMax: U16
+    {
+        psMemId id = psMemGetId();
+        psStats* myStats = psStatsAlloc(PS_STAT_MAX);
+        psVector* myVector = psVectorAlloc(N, PS_TYPE_U16);
+        myVector->n = N;
+        for (psS32 i = 0; i < N; i++)
+        {
+            myVector->data.U16[i] = samplesU16[i];
+        }
+
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(result, "psVectorStats suceeded");
+        ok(!isnan(myStats->max), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->max, expectedMaxNoMaskU16, 1e-4,
+                     "The max was %f, should be %f", myStats->max, expectedMaxNoMaskU16);
+        psFree(myStats);
+        psFree(myVector);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test StatsMax: F64
+    {
+        psMemId id = psMemGetId();
+        psStats* myStats = psStatsAlloc(PS_STAT_MAX);
+        psVector* myVector = psVectorAlloc(N, PS_TYPE_F64);
+        myVector->n = N;
+        for (psS32 i = 0; i < N; i++)
+        {
+            myVector->data.F64[i] = samplesF64[i];
+        }
+
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(result, "psVectorStats suceeded");
+        ok(!isnan(myStats->max), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->max, expectedMaxNoMaskF64, 1e-4,
+                     "The max was %f, should be %f", myStats->max, expectedMaxNoMaskF64);
+        psFree(myStats);
+        psFree(myVector);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats02.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats02.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats02.c	(revision 22158)
@@ -0,0 +1,193 @@
+/** @file  tst_psStats02.c
+*
+*  @brief Contains tests for psVectorStats with min calculations
+*
+*  We extensively test the code with data type PS_TYPE_F32.  If these pass, we
+*  do a much simpler test with data types PS_TYPE_U8, PS_TYPE_U16, PS_TYPE_F64.
+*
+*  If the psStats,c code every changes such that vectors of different type
+*  are handled by different routines, then these tests must be extended.
+*
+*  @author GLG, MHPCC
+*
+*  @version $Revision: 1.4 $  $Name: not supported by cvs2svn $
+*  @date $Date: 2007-03-27 22:52:03 $
+*
+* Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#define N 15
+
+static psF32 samplesF32[N] = { 1.1, 2.2, -3.3, 4.4, 5.5, -6.6, 7.7, 8.8, -9.9, 10.0,
+                               11.01, -12.02, 13.03, 14.04, -15.05 };
+static psS8  samplesS8[N]  = {1, 2, -3, 4, 5, -6, 7, 8, -9, 10, 11, -12, 13, 14, -15};
+static psU16 samplesU16[N] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+static psF64 samplesF64[N] = { 1.1, 2.2, -3.3, 4.4, 5.5, -6.6, 7.7, 8.8, -9.9, 10.0,
+                               11.01, -12.02, 13.03, 14.04, -15.05 };
+
+static psF64 expectedMinNoMaskF32                = -15.05;
+static psF64 expectedMinNoMaskS8                 = -15.00;
+static psF64 expectedMinNoMaskU16                = 1.00;
+static psF64 expectedMinNoMaskF64                = -15.05;
+
+static psF64 expectedMinWithMaskF32              = -12.02;
+static psF64 expectedMinRangeNoMaskF32           =   1.10;
+static psF64 expectedMinRangeWithMaskF32         = -12.02;
+
+psS32 main(psS32 argc, char* argv[] )
+{
+    psMemId idGlobal = psMemGetId();
+    psLogSetFormat("HLNM");
+    plan_tests(32);
+
+    psStats* myStats = psStatsAlloc(PS_STAT_MIN);
+    psVector* myVector = psVectorAlloc(N, PS_TYPE_F32);
+    myVector->n = N;
+    psVector* maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    maskVector->n = N;
+    for (psS32 i = 0; i < N; i++) {
+        myVector->data.F32[i] = samplesF32[i];
+        if (i < 13) {
+            maskVector->data.U8[i] = 0;
+        } else {
+            maskVector->data.U8[i] = 1;
+        }
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    {
+        psMemId id = psMemGetId();
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(result, "psVectorStats suceeded");
+        ok(!isnan(myStats->min), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->min, expectedMinNoMaskF32, 1e-4,
+                     "The min was %f, should be %f", myStats->min, expectedMinNoMaskF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask.                       */
+    /*************************************************************************/
+    {
+        psMemId id = psMemGetId();
+        bool result = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+        ok(result, "psVectorStats suceeded");
+        ok(!isnan(myStats->min), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->min, expectedMinWithMaskF32, 1e-4,
+                     "The min was %f, should be %f", myStats->min, expectedMinWithMaskF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Invoke function with data range with no mask
+    {
+        psMemId id = psMemGetId();
+        myStats->options = PS_STAT_MIN | PS_STAT_USE_RANGE;
+        myStats->max = 10.2;
+        myStats->min = 0.0;
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(result, "psVectorStats suceeded");
+        ok(!isnan(myStats->min), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->min, expectedMinRangeNoMaskF32, 1e-4,
+                     "The min was %f, should be %f", myStats->min, expectedMinRangeNoMaskF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Invoke function with data range and mask
+    {
+        psMemId id = psMemGetId();
+        myStats->max = 10.1;
+        myStats->min = -15.00;
+        bool result = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+        ok(result, "psVectorStats succeeded");
+        ok(!isnan(myStats->min), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->min, expectedMinRangeWithMaskF32, 1e-4,
+                     "The min was %f, should be %f", myStats->min, expectedMinRangeWithMaskF32);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Invoke function with data range with no valid data
+    {
+        psMemId id = psMemGetId();
+        myStats->max = 100.00;
+        myStats->min = 90.00;
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(!result, "psVectorStats failed as expected");
+        ok(isnan(myStats->min), "psVectorStats() returned NAN");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    psFree(myStats);
+    psFree(myVector);
+    psFree(maskVector);
+    ok(!psMemCheckLeaks (idGlobal, NULL, NULL, false), "no memory leaks");
+
+
+    // Test StatsMin: S8
+    {
+        psMemId id = psMemGetId();
+        psStats* myStats = psStatsAlloc(PS_STAT_MIN);
+        psVector* myVector = psVectorAlloc(N, PS_TYPE_S8);
+        myVector->n = N;
+        for (psS32 i = 0; i < N; i++)
+        {
+            myVector->data.S8[i] = samplesS8[i];
+        }
+
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(result, "psVectorStats succeeded");
+        ok(!isnan(myStats->min), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->min, expectedMinNoMaskS8, 1e-4,
+                     "The min was %f, should be %f", myStats->min, expectedMinNoMaskS8);
+        psFree(myStats);
+        psFree(myVector);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test StatsMin: U16
+    {
+        psMemId id = psMemGetId();
+        psStats* myStats = psStatsAlloc(PS_STAT_MAX);
+        psVector* myVector = psVectorAlloc(N, PS_TYPE_U16);
+        myVector->n = N;
+        for (psS32 i = 0; i < N; i++)
+        {
+            myVector->data.U16[i] = samplesU16[i];
+        }
+
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(result, "psVectorStats succeeded");
+        ok(!isnan(myStats->min), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->min, expectedMinNoMaskU16, 1e-4,
+                     "The min was %f, should be %f", myStats->min, expectedMinNoMaskU16);
+        psFree(myStats);
+        psFree(myVector);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test StatsMin: F64
+    {
+        psMemId id = psMemGetId();
+        psStats* myStats = psStatsAlloc(PS_STAT_MIN);
+        psVector* myVector = psVectorAlloc(N, PS_TYPE_F64);
+        myVector->n = N;
+        for (psS32 i = 0; i < N; i++)
+        {
+            myVector->data.F64[i] = samplesF64[i];
+        }
+
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(result, "psVectorStats succeeded");
+        ok(!isnan(myStats->min), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->min, expectedMinNoMaskF64, 1e-4,
+                     "The min was %f, should be %f", myStats->min, expectedMinNoMaskF64);
+        psFree(myStats);
+        psFree(myVector);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats03.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats03.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats03.c	(revision 22158)
@@ -0,0 +1,66 @@
+/*****************************************************************************
+    This routine must ensure that PS_STAT_SAMPLE_MEDIAN is correctly computed
+    by the procedure psVectorStats().
+ 
+    XXX: Must add tests for various data types, other than psF32.  Copy code
+    from tst_psStats00.c-tst_psStats02.c.
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define N1 1029   // This should be an odd number.
+#define N ((4 * N1) + 1)
+float realMedianWithMask = (float) (N-3)/4;
+float realMedianNoMask = (float) (N-1)/2;
+
+psS32 main()
+{
+    psMemId idGlobal = psMemGetId();
+    psLogSetFormat("HLNM");
+    plan_tests(9);
+
+    psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_MEDIAN);
+    psVector *myVector = psVectorAlloc(N, PS_TYPE_F32);
+    myVector->n = N;
+    psVector *maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    maskVector->n = N;
+    // Set the appropriate values for the vector data.
+    for (int i=0;i<N;i++) {
+        myVector->data.F32[i] = (float) i;
+        if (i < (N/2)) {
+            maskVector->data.U8[i] = 0;
+        } else {
+            maskVector->data.U8[i] = 1;
+        }
+    }
+
+    // Call psVectorStats() with no vector mask
+    {
+        psMemId id = psMemGetId();
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(result, "psVectorStats succeeded");
+        ok(!isnan(myStats->sampleMedian), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleMedian, realMedianNoMask, 1e-4,
+                     "The sample median was %f, should be %f", myStats->sampleMedian, realMedianNoMask);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Call psVectorStats() with vector mask
+    {
+        psMemId id = psMemGetId();
+        bool result = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+        ok(result, "psVectorStats succeeded");
+        ok(!isnan(myStats->sampleMedian), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleMedian, realMedianWithMask, 1e-4,
+                     "The sample median was %f, should be %f", myStats->sampleMedian, realMedianWithMask);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    psFree(myStats);
+    psFree(myVector);
+    psFree(maskVector);
+    ok(!psMemCheckLeaks (idGlobal, NULL, NULL, false), "no memory leaks");
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats05.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats05.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats05.c	(revision 22158)
@@ -0,0 +1,49 @@
+/*****************************************************************************
+    This routine must ensure that the psStats structure is correctly
+    allocated and deallocated by the procedure psStatsAlloc().
+ 
+    XXX: This should be test 00.  It should be merged into other tests
+         since it's so trivial.
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#define MISC_FLOAT_NUMBER 342.0
+
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    plan_tests(1);
+
+    {
+        psMemId id = psMemGetId();
+        psStats *myStats =psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        myStats->sampleMean = MISC_FLOAT_NUMBER;
+        myStats->sampleMedian = MISC_FLOAT_NUMBER;
+        myStats->sampleStdev = MISC_FLOAT_NUMBER;
+        myStats->sampleUQ = MISC_FLOAT_NUMBER;
+        myStats->sampleLQ = MISC_FLOAT_NUMBER;
+        myStats->robustMedian = MISC_FLOAT_NUMBER;
+        myStats->robustStdev = MISC_FLOAT_NUMBER;
+        myStats->robustUQ = MISC_FLOAT_NUMBER;
+        myStats->robustLQ = MISC_FLOAT_NUMBER;
+        myStats->robustN50 = MISC_FLOAT_NUMBER;
+        myStats->fittedMean = MISC_FLOAT_NUMBER;
+        myStats->fittedStdev = MISC_FLOAT_NUMBER;
+        myStats->fittedNfit = MISC_FLOAT_NUMBER;
+        myStats->clippedMean = MISC_FLOAT_NUMBER;
+        myStats->clippedStdev = MISC_FLOAT_NUMBER;
+        myStats->clippedNvalues = MISC_FLOAT_NUMBER;
+        myStats->clipSigma = MISC_FLOAT_NUMBER;
+        myStats->clipIter = MISC_FLOAT_NUMBER;
+        myStats->min = MISC_FLOAT_NUMBER;
+        myStats->max = MISC_FLOAT_NUMBER;
+        myStats->binsize = MISC_FLOAT_NUMBER;
+        myStats->nSubsample = MISC_FLOAT_NUMBER;
+        myStats->options = 0x0;
+        psFree(myStats);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats06.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats06.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats06.c	(revision 22158)
@@ -0,0 +1,67 @@
+/*****************************************************************************
+    This routine must ensure that PS_STAT_SAMPLE_STDEV is correctly computed
+    by the procedure psArrayStats().
+ 
+    XXX: Must add tests for various data types, other than psF32.  Copy code
+    from tst_psStats00.c-tst_psStats02.c.
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+//#include "float.h"
+//#include <math.h>
+#define N 15
+float realStdevNoMask = 4.472136;
+float realStdevWithMask = 2.160247;
+
+psS32 main()
+{
+    psMemId idGlobal = psMemGetId();
+    psLogSetFormat("HLNM");
+    plan_tests(9);
+
+    psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_STDEV);
+    psVector *myVector = psVectorAlloc(N, PS_TYPE_F32);
+    myVector->n = N;
+    psVector *maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    maskVector->n = N;
+    psS32 count           = 0;
+    for (int i=0;i<N;i++) {
+        myVector->data.F32[i] = (float) i;
+        if (i < (N/2)) {
+            maskVector->data.U8[i] = 0;
+            count++;
+        } else {
+            maskVector->data.U8[i] = 1;
+        }
+    }
+
+    // Call psVectorStats() with no vector mask
+    {
+        psMemId id = psMemGetId();
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(result, "psVectorStats succeeded");
+        ok(!isnan(myStats->sampleStdev), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleStdev, realStdevNoMask, 1e-4,
+                     "The mean was %f, should be %f", myStats->sampleStdev, realStdevNoMask);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Call psVectorStats() with vector mask
+    {
+        psMemId id = psMemGetId();
+        bool result = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+        ok(result, "psVectorStats succeeded");
+        ok(!isnan(myStats->sampleStdev), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleStdev, realStdevWithMask, 1e-4,
+                     "The mean was %f, should be %f", myStats->sampleStdev, realStdevWithMask);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    psFree(myStats);
+    psFree(myVector);
+    psFree(maskVector);
+    ok(!psMemCheckLeaks (idGlobal, NULL, NULL, false), "no memory leaks");
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats07.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats07.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats07.c	(revision 22158)
@@ -0,0 +1,514 @@
+/*****************************************************************************
+   This routine must ensure that PS_STAT_ROBUST_QUARTILE is correctly computed
+   by the procedure psArrayStats().
+ 
+   XXX: Must add tests for various data types, other than psF32.  Copy code
+   from tst_psStats00.c-tst_psStats02.c.
+
+   XXX: This basically works.  Must add bad paramater tests, and test other
+   data types, different vector sizes, etc.
+*****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define NUM_DATA 1000
+#define MEAN 32.0
+#define STDEV 2.0
+#define PERCENT_OUTLIERS 1
+#define OUTLIER_MAGNITUDE (NUM_DATA * 10)
+#define ERROR_TOLERANCE .10
+#define ERRORS 1000.0
+#define SEED 1995
+#define VERBOSE 0
+#define EXTRA_VERBOSE 0
+
+#define TST_IN_NULL             0x00000001
+#define TST_IN_F32              0x00000002
+#define TST_IN_F64              0x00000004
+#define TST_IN_S8               0x00000008
+#define TST_IN_U16              0x00000010
+#define TST_IN_S32              0x00000020
+#define TST_ERRORS_NULL         0x00000040
+#define TST_ERRORS_F32          0x00000080
+#define TST_ERRORS_F64          0x00000100
+#define TST_ERRORS_S8           0x00000200
+#define TST_ERRORS_U16          0x00000400
+#define TST_ERRORS_S32          0x00000800
+#define TST_MASK_NULL           0x00001000
+#define TST_MASK_U8             0x00002000
+#define TST_MASK_S32            0x00004000
+
+/*****************************************************************************
+    p_psGaussianDev()
+ This private routine (formerly a psLib API routine) creates a psVector of the
+ specified size and type F32 and fills it with a random Gaussian distribution
+ of numbers with the specified mean and sigma.
+ 
+XXX: It's possible to have a different seed everytime.  However, for now,
+for testability, we use a common seed.
+ *****************************************************************************/
+#define PS_XXX_GAUSSIAN_SEED 1995
+psVector* p_psGaussianDev(psF32 mean,
+                          psF32 sigma,
+                          unsigned int Npts)
+{
+    PS_ASSERT_INT_NONNEGATIVE(Npts, NULL);
+
+    //    psRandom *r = psRandomAlloc(PS_RANDOM_TAUS, p_psRandomGetSystemSeed());
+    psRandom *r = psRandomAlloc(PS_RANDOM_TAUS, PS_XXX_GAUSSIAN_SEED);
+    psVector* gauss = psVectorAlloc(Npts, PS_TYPE_F32);
+    for (unsigned int i = 0; i < Npts; i++) {
+        gauss->data.F32[i] = mean + p_psRandomGaussian(r, sigma);
+        gauss->n++;
+    }
+    psFree(r);
+
+    return(gauss);
+}
+
+psBool genericRobustStatsTest(
+    unsigned int flags,
+    psS32 numData,
+    psU32 maskValue,
+    psBool expectedRC)
+{
+    psS32 currentId = psMemGetId();
+    psBool testStatus = true;
+    psS32 memLeaks = 0;
+    psVector *in = NULL;
+    psVector *errors = NULL;
+    psVector *mask = NULL;
+    srand(SEED);
+
+    if (expectedRC == true) {
+        if (VERBOSE)
+            printf("This test should not generate any errors.\n");
+    }
+    if (expectedRC == false) {
+        if (VERBOSE)
+            printf("This test should generate an error message, and return NULL.\n");
+    }
+    psVector *gaussVector = p_psGaussianDev(MEAN, STDEV, numData);
+
+
+    if (flags & TST_IN_NULL) {
+        if (VERBOSE)
+            printf("        using a NULL in vector\n");
+    }
+
+    if (flags & TST_IN_F32) {
+        if (VERBOSE)
+            printf("        using a psF32 in vector\n");
+        in = psVectorAlloc(numData, PS_TYPE_F32);
+        for (psS32 i=0;i<numData;i++) {
+            in->data.F32[i] = gaussVector->data.F32[i];
+//            in->n++;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%.1f)\n", i, in->data.F32[i]);
+            }
+        }
+    }
+
+    if (flags & TST_IN_F64) {
+        if (VERBOSE)
+            printf("        using a psF64 in vector\n");
+        in = psVectorAlloc(numData, PS_TYPE_F64);
+        for (psS32 i=0;i<numData;i++) {
+            in->data.F64[i] = (psF64) gaussVector->data.F32[i];
+//            in->n++;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%.1f)\n", i, in->data.F64[i]);
+            }
+        }
+    }
+
+    if (flags & TST_IN_S8) {
+        if (VERBOSE)
+            printf("        using a psS8 in vector\n");
+        in = psVectorAlloc(numData, PS_TYPE_S8);
+        for (psS32 i=0;i<numData;i++) {
+            in->data.S8[i] = (psS8) gaussVector->data.F32[i];
+//            in->n++;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%d)\n", i, in->data.S8[i]);
+            }
+        }
+    }
+
+    if (flags & TST_IN_U16) {
+        if (VERBOSE)
+            printf("        using a psU16 in vector\n");
+        in = psVectorAlloc(numData, PS_TYPE_U16);
+        for (psS32 i=0;i<numData;i++) {
+            in->data.U16[i] = (psU16) gaussVector->data.F32[i];
+//            in->n++;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%d)\n", i, in->data.U16[i]);
+            }
+        }
+    }
+
+    if (flags & TST_IN_S32) {
+        if (VERBOSE)
+            printf("        using a psS32 in vector\n");
+        in = psVectorAlloc(numData, PS_TYPE_S32);
+        for (psS32 i=0;i<numData;i++) {
+            in->data.S32[i] = (psS32) gaussVector->data.F32[i];
+//            in->n++;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%d)\n", i, in->data.S32[i]);
+            }
+        }
+    }
+    psFree(gaussVector);
+
+    //    in->n = in->nalloc;
+    if (flags & TST_ERRORS_NULL) {
+        if (VERBOSE)
+            printf("        using a NULL errors vector\n");
+    }
+
+    if (flags & TST_ERRORS_F32) {
+        if (VERBOSE)
+            printf("        using a psF32 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_F32);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.F32[i] = ERRORS;
+//            errors->n++;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original errors data %d: (%.1f)\n", i, errors->data.F32[i]);
+            }
+        }
+    }
+
+    if (flags & TST_ERRORS_F64) {
+        if (VERBOSE)
+            printf("        using a psF64 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_F64);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.F64[i] = ERRORS;
+//            errors->n++;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original errors data %d: (%.1f)\n", i, errors->data.F64[i]);
+            }
+        }
+    }
+
+    if (flags & TST_ERRORS_S8) {
+        if (VERBOSE)
+            printf("        using a psS8 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_S8);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.S8[i] = (psS8) ERRORS;
+//            errors->n++;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original errors data %d: (%d)\n", i, errors->data.S8[i]);
+            }
+        }
+    }
+
+    if (flags & TST_ERRORS_U16) {
+        if (VERBOSE)
+            printf("        using a psU16 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_U16);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.U16[i] = (psU16) ERRORS;
+//            errors->n++;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original errors data %d: (%d)\n", i, errors->data.U16[i]);
+            }
+        }
+    }
+
+    if (flags & TST_ERRORS_S32) {
+        if (VERBOSE)
+            printf("        using a psS32 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_S32);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.S32[i] = (psS32) ERRORS;
+//            errors->n++;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original errors data %d: (%d)\n", i, errors->data.S32[i]);
+            }
+        }
+    }
+
+
+    if (flags & TST_MASK_NULL) {
+        if (VERBOSE)
+            printf("        using a NULL mask vector\n");
+    }
+
+    if (flags & TST_MASK_U8) {
+        if (VERBOSE)
+            printf("        using a psU8 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_U8);
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.U8[i] = (psU8) 0;
+//            mask->n++;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original mask data %d: (%d)\n", i, mask->data.U8[i]);
+            }
+        }
+    }
+
+    if (flags & TST_MASK_S32) {
+        if (VERBOSE)
+            printf("        using a psS32 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_S32);
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.S32[i] = (psS32) 0;
+//            mask->n++;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original mask data %d: (%d)\n", i, mask->data.S32[i]);
+            }
+        }
+    }
+
+
+    //
+    // We calculate the sample mean and stdev without and outliers in the data.
+    // We will use this later in determining if the clipped stats are correct.
+    //
+    psF32 sampleMean=0.0;
+    psF32 sampleStdev=0.0;
+    psF32 sampleMedian=0.0;
+    psF32 sampleLQ=0.0;
+    psF32 sampleUQ=0.0;
+    if (expectedRC == true) {
+        psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV | PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_QUARTILE);
+        bool rc = psVectorStats(myStats, in, NULL, NULL, maskValue);
+        if (rc == false) {
+            diag("TEST ERROR: the psVectorStats() function returned NULL.\n");
+            testStatus = false;
+        } else {
+            sampleMean = myStats->sampleMean;
+            sampleStdev = myStats->sampleStdev;
+            sampleMedian = myStats->sampleMedian;
+            sampleLQ = myStats->sampleLQ;
+            sampleUQ = myStats->sampleUQ;
+        }
+        psFree(myStats);
+    }
+
+    //
+    // We add a few outliers to the input data.
+    //
+    if (flags & TST_IN_F32) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.F32[i] = (psF32) OUTLIER_MAGNITUDE;
+            }
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%.1f)\n", i, in->data.F32[i]);
+            }
+        }
+    }
+    if (flags & TST_IN_F64) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.F64[i] = (psF64) OUTLIER_MAGNITUDE;
+            }
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%.1f)\n", i, in->data.F64[i]);
+            }
+        }
+    }
+    if (flags & TST_IN_S8) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.S8[i] = (psS8) OUTLIER_MAGNITUDE;
+            }
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%d)\n", i, in->data.S8[i]);
+            }
+        }
+    }
+    if (flags & TST_IN_U16) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.U16[i] = (psU16) OUTLIER_MAGNITUDE;
+            }
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%d)\n", i, in->data.U16[i]);
+            }
+        }
+    }
+    if (flags & TST_IN_S32) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.S32[i] = (psS32) OUTLIER_MAGNITUDE;
+            }
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%d)\n", i, in->data.S32[i]);
+            }
+        }
+    }
+
+    //
+    // We call psVectorStats() and calculate the clipped stats.
+    //
+    psStats *myStats = psStatsAlloc(
+                           PS_STAT_ROBUST_MEDIAN |
+                           PS_STAT_ROBUST_STDEV |
+                           PS_STAT_ROBUST_QUARTILE |
+                           PS_STAT_FITTED_MEAN |
+                           PS_STAT_FITTED_STDEV);
+    bool rc = psVectorStats(myStats, in, errors, mask, maskValue);
+
+    if (rc == false) {
+        if (expectedRC == true) {
+            diag("TEST ERROR: the psVectorStats() function returned NULL.\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            diag("TEST ERROR: the psVectorStats() function returned non-NULL.\n");
+            testStatus = false;
+        }
+
+        //
+        // Fitted Mean
+        //
+        if (fabs(myStats->fittedMean - sampleMean) > (ERROR_TOLERANCE * sampleMean)) {
+            diag("TEST ERROR: the fitted mean was %.2f, should have been %.2f\n", myStats->fittedMean, sampleMean);
+            testStatus = false;
+        } else if (EXTRA_VERBOSE) {
+            printf("GOOD: the fitted mean was %.2f, should have been %.2f\n", myStats->fittedMean, sampleMean);
+        }
+
+        //
+        // Fitted Stdev
+        //
+        if (fabs(myStats->fittedStdev - sampleStdev) > (ERROR_TOLERANCE * sampleStdev)) {
+            diag("TEST ERROR: the fitted stdev was %.2f, should have been %.2f\n", myStats->fittedStdev, sampleStdev);
+            testStatus = false;
+        } else if (EXTRA_VERBOSE) {
+            printf("GOOD: the fitted stdev was %.2f, should have been %.2f\n", myStats->fittedStdev, sampleStdev);
+        }
+
+        //
+        // Robust Stdev
+        //
+        if (fabs(myStats->robustStdev - sampleStdev) > (ERROR_TOLERANCE * sampleStdev)) {
+            diag("TEST ERROR: the robust stdev was %.2f, should have been %.2f\n", myStats->robustStdev, sampleStdev);
+            testStatus = false;
+        } else if (EXTRA_VERBOSE) {
+            printf("GOOD: the robust stdev was %.2f, should have been %.2f\n", myStats->robustStdev, sampleStdev);
+        }
+
+        //
+        // Robust Median
+        //
+        if (fabs(myStats->robustMedian - sampleMedian) > (ERROR_TOLERANCE * sampleMedian)) {
+            diag("TEST ERROR: the robust median was %.2f, should have been %.2f\n", myStats->robustMedian, sampleMedian);
+            testStatus = false;
+        } else if (EXTRA_VERBOSE) {
+            printf("GOOD: the robust median was %.2f, should have been %.2f\n", myStats->robustMedian, sampleMedian);
+        }
+
+        //
+        // Robust LQ
+        //
+        if (fabs(myStats->robustLQ - sampleLQ) > (ERROR_TOLERANCE * sampleLQ)) {
+            diag("TEST ERROR: the robust LQ was %.2f, should have been %.2f\n", myStats->robustLQ, sampleLQ);
+            testStatus = false;
+        } else if (EXTRA_VERBOSE) {
+            printf("GOOD: the robust LQ was %.2f, should have been %.2f\n", myStats->robustLQ, sampleLQ);
+        }
+
+        //
+        // Robust UQ
+        //
+        if (fabs(myStats->robustUQ - sampleUQ) > (ERROR_TOLERANCE * sampleUQ)) {
+            diag("TEST ERROR: the robust UQ was %.2f, should have been %.2f\n", myStats->robustUQ, sampleUQ);
+            testStatus = false;
+        } else if (EXTRA_VERBOSE) {
+            printf("GOOD: the robust UQ was %.2f, should have been %.2f\n", myStats->robustUQ, sampleUQ);
+        }
+    }
+
+    psFree(myStats);
+    psFree(in);
+    psFree(errors);
+    psFree(mask);
+    psMemCheckCorruption(stderr, false);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    return(testStatus);
+}
+
+
+psS32 main()
+{
+    psMemId id = psMemGetId();
+    psLogSetFormat("HLNM");
+    plan_tests(4);
+
+    ok(genericRobustStatsTest(TST_IN_F32 | TST_ERRORS_NULL | TST_MASK_NULL,
+       NUM_DATA, 1, true), "RobustStatsTest() F32 data, NULL errors, NULL mask");
+    ok(genericRobustStatsTest(TST_IN_F32 | TST_ERRORS_NULL | TST_MASK_U8, 
+       NUM_DATA, 1, true), "RobustStatsTest() F32 data, non-NULL errors and mask vector");
+    ok(genericRobustStatsTest(TST_IN_F32 | TST_ERRORS_F32 | TST_MASK_U8,
+        NUM_DATA, 1, true), "RobustStatsTest() F32 data, non-NULL errors and mask vector");
+
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats08.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats08.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats08.c	(revision 22158)
@@ -0,0 +1,92 @@
+/*****************************************************************************
+    This routine must ensure that PS_STAT_SAMPLE_QUARTILE is correctly computed
+    by the procedure psArrayStats().
+ 
+    XXX: Must add tests for various data types, other than psF32.  Copy code
+    from tst_psStats00.c-tst_psStats02.c.
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#define N1 25
+#define N (8 * N1) // Don't change this (N must be a multiple of 8)
+float realLQNoMask   = N/4.0;
+float realUQNoMask   = 3.0 * (N/4.0);
+float realLQWithMask   = N/8.0;
+float realUQWithMask   = 3.0 * (N/8.0);
+
+psS32 main()
+{
+    psMemId idGlobal = psMemGetId();
+    psLogSetFormat("HLNM");
+    plan_tests(18);
+
+    psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_QUARTILE);
+    psVector *myVector = psVectorAlloc(N, PS_TYPE_F32);
+    myVector->n = N;
+    psVector *maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    maskVector->n = N;
+    for (int i=0;i<N;i++) {
+        myVector->data.F32[i] = (float) i;
+        if (i < (N/2)) {
+            maskVector->data.U8[i] = 0;
+        } else {
+            maskVector->data.U8[i] = 1;
+        }
+    }
+
+
+    // Call psVectorStats() with no vector mask; test sampleLQ
+    {
+        psMemId id = psMemGetId();
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(result, "psVectorStats succeeded");
+        ok(!isnan(myStats->sampleLQ), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleLQ, realLQNoMask, 1e-4,
+                     "The sampleLQ was %f, should be %f", myStats->sampleLQ, realLQNoMask);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Call psVectorStats() with no vector mask; test sampleUQ
+    {
+        psMemId id = psMemGetId();
+        bool result = psVectorStats(myStats, myVector, NULL, NULL, 0);
+        ok(result, "psVectorStats succeeded");
+        ok(!isnan(myStats->sampleUQ), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleUQ, realUQNoMask, 1e-4,
+                     "The sampleUQ was %f, should be %f", myStats->sampleUQ, realUQNoMask);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Call psVectorStats() with vector mask; test sampleLQ
+    {
+        psMemId id = psMemGetId();
+        bool result = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+        ok(result, "psVectorStats succeeded");
+        ok(!isnan(myStats->sampleLQ), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleLQ, realLQWithMask, 1e-4,
+                     "The sampleLQ was %f, should be %f", myStats->sampleLQ,
+                     realLQWithMask);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Call psVectorStats() with vector mask; test sampleUQ
+    {
+        psMemId id = psMemGetId();
+        bool result = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+        ok(result, "psVectorStats succeeded");
+        ok(!isnan(myStats->sampleUQ), "psVectorStats() returned non-NAN");
+        is_float_tol(myStats->sampleUQ, realUQWithMask, 1e-4,
+                     "The sampleUQ was %f, should be %f", myStats->sampleUQ,
+                     realUQWithMask);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    psFree(myStats);
+    psFree(myVector);
+    psFree(maskVector);
+    ok(!psMemCheckLeaks (idGlobal, NULL, NULL, false), "no memory leaks");
+    ok(!psMemCheckLeaks (idGlobal, NULL, NULL, false), "no memory leaks");
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats09.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats09.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats09.c	(revision 22158)
@@ -0,0 +1,365 @@
+/*****************************************************************************
+    This routine must ensure that PS_STAT_CLIPPED_MEAN and
+    PS_STAT_CLIPPED_STDEV is calculate correctly by the procedure
+    psVectorStats().
+ 
+    XXX: The capability is here to test a wide variety of input parameters.
+    We must do this, later.
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define NUM_DATA 1000
+#define VERBOSE 0
+#define EXTRA_VERBOSE 0
+#define PERCENT_OUTLIERS 2
+#define ERROR_TOLERANCE .10
+#define ERRORS 1.0
+#define SEED 1995
+
+#define TST_IN_NULL  0x00000001
+#define TST_IN_F32  0x00000002
+#define TST_IN_F64  0x00000004
+#define TST_IN_S8  0x00000008
+#define TST_IN_U16  0x00000010
+#define TST_IN_S32  0x00000020
+#define TST_ERRORS_NULL  0x00000040
+#define TST_ERRORS_F32  0x00000080
+#define TST_ERRORS_F64  0x00000100
+#define TST_ERRORS_S8  0x00000200
+#define TST_ERRORS_U16  0x00000400
+#define TST_ERRORS_S32  0x00000800
+#define TST_MASK_NULL  0x00001000
+#define TST_MASK_U8  0x00002000
+#define TST_MASK_S32  0x00004000
+
+
+psBool genericClippedStatsTest(
+    unsigned int flags,
+    psS32 numData,
+    psU32 maskValue,
+    psBool expectedRC)
+{
+    psS32 currentId = psMemGetId();
+    psBool testStatus = true;
+    psS32 memLeaks = 0;
+    psVector *in = NULL;
+    psVector *errors = NULL;
+    psVector *mask = NULL;
+    srand(SEED);
+
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 1); // Random number generator; using known seed
+    psVector *truth = psVectorAlloc(numData, PS_TYPE_F64);
+    for (long i = 0; i < numData; i++) {
+        truth->data.F64[i] = psRandomGaussian(rng);
+    }
+    psFree(rng);
+
+    if (expectedRC == true) {
+        if (VERBOSE)
+            printf("This test should not generate any errors.\n");
+    }
+    if (expectedRC == false) {
+        if (VERBOSE)
+            printf("This test should generate an error message, and return NULL.\n");
+    }
+
+    if (flags & TST_IN_NULL) {
+        if (VERBOSE)
+            printf("        using a NULL in vector\n");
+    }
+
+    if (flags & TST_IN_F32) {
+        if (VERBOSE)
+            printf("        using a psF32 in vector\n");
+        in = psVectorCopy(in, truth, PS_TYPE_F32);
+    }
+
+    if (flags & TST_IN_F64) {
+        if (VERBOSE)
+            printf("        using a psF64 in vector\n");
+        in = psVectorCopy(in, truth, PS_TYPE_F64);
+    }
+
+    if (flags & TST_IN_S8) {
+        if (VERBOSE)
+            printf("        using a psS8 in vector\n");
+        in = psVectorCopy(in, truth, PS_TYPE_S8);
+    }
+
+    if (flags & TST_IN_U16) {
+        if (VERBOSE)
+            printf("        using a psU16 in vector\n");
+        in = psVectorCopy(in, truth, PS_TYPE_U16);
+    }
+
+    if (flags & TST_IN_S32) {
+        if (VERBOSE)
+            printf("        using a psS32 in vector\n");
+        in = psVectorCopy(in, truth, PS_TYPE_S32);
+    }
+
+    if (flags & TST_ERRORS_NULL) {
+        if (VERBOSE)
+            printf("        using a NULL errors vector\n");
+    }
+
+    if (flags & TST_ERRORS_F32) {
+        if (VERBOSE)
+            printf("        using a psF32 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_F32);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.F32[i] = ERRORS;
+        }
+    }
+
+    if (flags & TST_ERRORS_F64) {
+        if (VERBOSE)
+            printf("        using a psF64 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_F64);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.F64[i] = ERRORS;
+        }
+    }
+
+    if (flags & TST_ERRORS_S8) {
+        if (VERBOSE)
+            printf("        using a psS8 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_S8);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.S8[i] = (psS8) ERRORS;
+        }
+    }
+
+    if (flags & TST_ERRORS_U16) {
+        if (VERBOSE)
+            printf("        using a psU16 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_U16);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.U16[i] = (psU16) ERRORS;
+        }
+    }
+
+    if (flags & TST_ERRORS_S32) {
+        if (VERBOSE)
+            printf("        using a psS32 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_S32);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.S32[i] = (psS32) ERRORS;
+        }
+    }
+
+
+    if (flags & TST_MASK_NULL) {
+        if (VERBOSE)
+            printf("        using a NULL mask vector\n");
+    }
+
+    if (flags & TST_MASK_U8) {
+        if (VERBOSE)
+            printf("        using a psU8 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_U8);
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.U8[i] = (psU8) 0;
+        }
+    }
+
+    if (flags & TST_MASK_S32) {
+        if (VERBOSE)
+            printf("        using a psS32 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_S32);
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.S32[i] = (psS32) 0;
+        }
+    }
+
+
+    //
+    // We add a few outliers to the input data.
+    //
+    psVector *outliers = psVectorAlloc(numData, PS_TYPE_U8);
+    psVectorInit(outliers, 0);
+    long numOutliers = 0;
+    if (flags & TST_IN_F32) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.F32[i] = 100.0;
+                outliers->data.U8[i] = 1;
+                numOutliers++;
+            }
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Data %d: (%f)\n", i, in->data.F32[i]);
+            }
+        }
+    }
+    if (flags & TST_IN_F64) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.F64[i] = 100.0;
+                outliers->data.U8[i] = 1;
+                numOutliers++;
+            }
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Data %d: (%f)\n", i, in->data.F64[i]);
+            }
+        }
+    }
+    if (flags & TST_IN_S8) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.S8[i] = 100;
+                outliers->data.U8[i] = 1;
+                numOutliers++;
+            }
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Data %d: (%d)\n", i, in->data.S8[i]);
+            }
+        }
+    }
+    if (flags & TST_IN_U16) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.U16[i] = 100;
+                outliers->data.U8[i] = 1;
+                numOutliers++;
+            }
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Data %d: (%d)\n", i, in->data.U16[i]);
+            }
+        }
+    }
+    if (flags & TST_IN_S32) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.S32[i] = 100;
+                outliers->data.U8[i] = 1;
+                numOutliers++;
+            }
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Data %d: (%d)\n", i, in->data.S32[i]);
+            }
+        }
+    }
+
+    if (VERBOSE)
+        printf("%ld outliers.\n", numOutliers);
+
+    //
+    // We calculate the sample mean and stdev without and outliers in the data.
+    // We will use this later in determining if the clipped stats are correct.
+    //
+    psF32 sampleMean=0.0;
+    psF32 sampleStdev=0.0;
+    if (expectedRC == true) {
+        psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
+        bool rc = psVectorStats(myStats, in, errors, outliers, 1);
+        if (rc == false) {
+            diag("TEST ERROR: the psVectorStats() function returned NULL (a).\n");
+            testStatus = false;
+        } else {
+            sampleMean = myStats->sampleMean;
+            sampleStdev = myStats->sampleStdev;
+        }
+        psFree(myStats);
+    }
+    psFree(outliers);
+
+    //
+    // We call psVectorStats() and calculate the clipped stats.
+    //
+    psStats *myStats = psStatsAlloc(PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV);
+    myStats->clipSigma = 5.0;
+    myStats->clipIter = 2;
+    bool rc = psVectorStats(myStats, in, errors, mask, maskValue);
+    if (rc == false) {
+        if (expectedRC == true) {
+            diag("TEST ERROR: the psVectorStats() function returned NULL (b).\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            diag("TEST ERROR: the psVectorStats() function returned non-NULL.\n");
+            testStatus = false;
+        }
+
+        if (VERBOSE)
+            printf("Used %ld data points after clipping %ld.\n", myStats->clippedNvalues,
+                   in->n - myStats->clippedNvalues);
+
+        if (fabs(myStats->clippedMean - sampleMean) > (ERROR_TOLERANCE * sampleMean)) {
+            diag("TEST ERROR: the clipped mean was %f, should have been %f\n", myStats->clippedMean, sampleMean);
+            testStatus = false;
+        } else if (EXTRA_VERBOSE) {
+            printf("GOOD: the clipped mean was %f, should have been %f\n", myStats->clippedMean, sampleMean);
+        }
+
+        if (fabs(myStats->clippedStdev - sampleStdev) > (ERROR_TOLERANCE * sampleStdev)) {
+            diag("TEST ERROR: the clipped stdev was %f, should have been %f\n", myStats->clippedStdev, sampleStdev);
+            testStatus = false;
+        } else if (EXTRA_VERBOSE) {
+            printf("GOOD: the clipped stdev was %f, should have been %f\n", myStats->clippedStdev, sampleStdev);
+        }
+
+    }
+
+    psFree(myStats);
+    psFree(truth);
+    psFree(in);
+    psFree(errors);
+    psFree(mask);
+    psMemCheckCorruption(stderr, false);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    return(testStatus);
+}
+
+#define TRACE_LEVEL 0
+psS32 main()
+{
+    psMemId id = psMemGetId();
+    psLogSetFormat("HLNM");
+    plan_tests(6);
+
+    //
+    // We list pertinent psStats.c functions here for debugging ease.
+    //
+    psTraceSetLevel(".", TRACE_LEVEL);
+    psTraceSetLevel("p_psVectorSampleMean", TRACE_LEVEL);
+    psTraceSetLevel("p_psVectorMax", TRACE_LEVEL);
+    psTraceSetLevel("p_psVectorMin", TRACE_LEVEL);
+    psTraceSetLevel("p_psVectorCheckNonEmpty", TRACE_LEVEL);
+    psTraceSetLevel("p_psVectorNValues", TRACE_LEVEL);
+    psTraceSetLevel("p_psVectorClippedStats", TRACE_LEVEL);
+    psTraceSetLevel("p_psNormalizeVectorRange", TRACE_LEVEL);
+    psTraceSetLevel("psStatsAlloc", TRACE_LEVEL);
+    psTraceSetLevel("p_psConvertToF32", TRACE_LEVEL);
+    psTraceSetLevel("psVectorStats", TRACE_LEVEL);
+
+    ok(genericClippedStatsTest(TST_IN_NULL | TST_ERRORS_NULL | TST_MASK_NULL, NUM_DATA, 1, false), "GenericClippedStatsTest(): NULL data");
+    ok(genericClippedStatsTest(TST_IN_F32 | TST_ERRORS_NULL | TST_MASK_NULL, NUM_DATA, 1, true), "GenericClippedStatsTest(): F32 data");
+    ok(genericClippedStatsTest(TST_IN_F64 | TST_ERRORS_NULL | TST_MASK_NULL, NUM_DATA, 1, true), "GenericClippedStatsTest(): F64 data");
+    ok(genericClippedStatsTest(TST_IN_F32 | TST_ERRORS_F32 | TST_MASK_NULL, NUM_DATA, 1, true), "GenericClippedStatsTest(): non-NULL error vector");
+    ok(genericClippedStatsTest(TST_IN_F32 | TST_ERRORS_NULL | TST_MASK_U8, NUM_DATA, 1, true), "GenericClippedStatsTest(): non-NULL mask vector");
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStatsTiming.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStatsTiming.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStatsTiming.c	(revision 22158)
@@ -0,0 +1,828 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+// example tap lines:
+// ok(condition, "condition succeeded");
+// skip_start(condition, Nskip, "Skipping tests because of failure");
+
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+struct timeval start, mark;
+
+int main (void)
+{
+    plan_tests(68);
+
+//    diag("psStats timing tests");
+
+    // build a gauss-deviate vector (mean = 0.0, sigma = 1.0) for tests
+    psRandom *seed = psRandomAlloc (PS_RANDOM_TAUS, 0);
+    psVector *rnd = psVectorAlloc (1000, PS_TYPE_F32);
+    for (int i = 0; i < rnd->n; i++) {
+        rnd->data.F32[i] = psRandomGaussian (seed);
+    }
+
+//    diag ("timing for sample mean");
+    /********** SAMPLE MEAN ***********/
+    // test stat sample mean (no mask, no range)
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEAN);
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 10000; i++)
+        {
+            psVectorStats (stats, rnd, NULL, NULL, 0);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.1, "sample mean %f (mask: 0, range: 0): %.3f sec", stats->sampleMean, delta);
+        psFree (stats);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test stat sample mean (mask, no range)
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEAN);
+        psVector *mask = psVectorAlloc (1000, PS_TYPE_U8);
+        psVectorInit (mask, 0);
+        mask->data.U8[100] = 1;
+        mask->data.U8[200] = 1;
+        mask->data.U8[300] = 1;
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 10000; i++)
+        {
+            psVectorStats (stats, rnd, NULL, mask, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.12, "sample mean %f (mask: 1, range: 0): %.3f sec", stats->sampleMean, delta);
+        psFree (stats);
+        psFree (mask);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test stat sample mean (no mask, range)
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEAN | PS_STAT_USE_RANGE);
+        stats->min = -10;
+        stats->max = +10;
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 10000; i++)
+        {
+            psVectorStats (stats, rnd, NULL, NULL, 0);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.18, "sample mean %f (mask: 0, range: 1): %.3f sec", stats->sampleMean, delta);
+        psFree (stats);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test stat sample mean (mask, range)
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEAN | PS_STAT_USE_RANGE);
+        stats->min = -10;
+        stats->max = +10;
+        psVector *mask = psVectorAlloc (1000, PS_TYPE_U8);
+        psVectorInit (mask, 0);
+        mask->data.U8[100] = 1;
+        mask->data.U8[200] = 1;
+        mask->data.U8[300] = 1;
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 10000; i++)
+        {
+            psVectorStats (stats, rnd, NULL, mask, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.2, "sample mean %f (mask: 1, range: 1): %.3f sec", stats->sampleMean, delta);
+        psFree (stats);
+        psFree (mask);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test stat sample mean (mask, range : small sample)
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEAN | PS_STAT_USE_RANGE);
+        stats->min = -10;
+        stats->max = +10;
+        psVector *mask = psVectorAlloc (10, PS_TYPE_U8);
+        psVectorInit (mask, 0);
+        mask->data.U8[3] = 1;
+        int nOld = rnd->n;
+
+        rnd->n = 10;
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 1000000; i++)
+        {
+            psVectorStats (stats, rnd, NULL, mask, 1);
+        }
+        gettimeofday (&mark, NULL);
+        rnd->n = nOld;
+
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.2, "sample mean %f (mask: 1, range: 1): %.3f sec", stats->sampleMean, delta);
+        psFree (stats);
+        psFree (mask);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+//    diag ("timing for sample median");
+    /********** SAMPLE MEDIAN ***********/
+    // test stat sample median (no mask, no range)
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 10000; i++)
+        {
+            psVectorStats (stats, rnd, NULL, NULL, 0);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 2.8, "sample median %f (mask: 0, range: 0): %.3f sec", stats->sampleMedian, delta);
+        psFree (stats);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test stat sample median (mask, no range)
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+        psVector *mask = psVectorAlloc (1000, PS_TYPE_U8);
+        psVectorInit (mask, 0);
+        mask->data.U8[100] = 1;
+        mask->data.U8[200] = 1;
+        mask->data.U8[300] = 1;
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 10000; i++)
+        {
+            psVectorStats (stats, rnd, NULL, mask, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 2.8, "sample median %f (mask: 1, range: 0): %.3f sec", stats->sampleMedian, delta);
+        psFree (stats);
+        psFree (mask);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test stat sample median (no mask, range)
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_USE_RANGE);
+        stats->min = -10;
+        stats->max = +10;
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 10000; i++)
+        {
+            psVectorStats (stats, rnd, NULL, NULL, 0);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 2.8, "sample median %f (mask: 0, range: 1): %.3f sec", stats->sampleMedian, delta);
+        psFree (stats);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test stat sample median (mask, range)
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_USE_RANGE);
+        stats->min = -10;
+        stats->max = +10;
+        psVector *mask = psVectorAlloc (1000, PS_TYPE_U8);
+        psVectorInit (mask, 0);
+        mask->data.U8[100] = 1;
+        mask->data.U8[200] = 1;
+        mask->data.U8[300] = 1;
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 10000; i++)
+        {
+            psVectorStats (stats, rnd, NULL, mask, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 2.8, "sample median %f (mask: 1, range: 1): %.3f sec", stats->sampleMedian, delta);
+        psFree (stats);
+        psFree (mask);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+//    diag ("timing for sample stdev");
+    /********** SAMPLE STDEV ***********/
+    // test stat sample stdev (no mask, no range)
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_STDEV);
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 10000; i++)
+        {
+            psVectorStats (stats, rnd, NULL, NULL, 0);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.2, "sample stdev %f (mask: 0, range: 0): %.3f sec", stats->sampleStdev, delta);
+        psFree (stats);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test stat sample stdev (mask, no range)
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_STDEV);
+        psVector *mask = psVectorAlloc (1000, PS_TYPE_U8);
+        psVectorInit (mask, 0);
+        mask->data.U8[100] = 1;
+        mask->data.U8[200] = 1;
+        mask->data.U8[300] = 1;
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 10000; i++)
+        {
+            psVectorStats (stats, rnd, NULL, mask, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.27, "sample stdev %f (mask: 1, range: 0): %.3f sec", stats->sampleStdev, delta);
+        psFree (stats);
+        psFree (mask);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test stat sample stdev (no mask, range)
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_STDEV | PS_STAT_USE_RANGE);
+        stats->min = -10;
+        stats->max = +10;
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 10000; i++)
+        {
+            psVectorStats (stats, rnd, NULL, NULL, 0);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.36, "sample stdev %f (mask: 0, range: 1): %.3f sec", stats->sampleStdev, delta);
+        psFree (stats);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test stat sample stdev (mask, range)
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_STDEV | PS_STAT_USE_RANGE);
+        stats->min = -10;
+        stats->max = +10;
+        psVector *mask = psVectorAlloc (1000, PS_TYPE_U8);
+        psVectorInit (mask, 0);
+        mask->data.U8[100] = 1;
+        mask->data.U8[200] = 1;
+        mask->data.U8[300] = 1;
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 10000; i++)
+        {
+            psVectorStats (stats, rnd, NULL, mask, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.42, "sample stdev %f (mask: 1, range: 1): %.3f sec", stats->sampleStdev, delta);
+        psFree (stats);
+        psFree (mask);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test stat sample stdev (mask, range)
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_STDEV | PS_STAT_USE_RANGE);
+        stats->min = -10;
+        stats->max = +10;
+        psVector *mask = psVectorAlloc (10, PS_TYPE_U8);
+        psVectorInit (mask, 0);
+        mask->data.U8[1] = 1;
+        int nOld = rnd->n;
+
+        rnd->n = 10;
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 1000000; i++)
+        {
+            psVectorStats (stats, rnd, NULL, mask, 1);
+        }
+        gettimeofday (&mark, NULL);
+        rnd->n = nOld;
+
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.42, "sample stdev %f (mask: 1, range: 1): %.3f sec", stats->sampleStdev, delta);
+        psFree (stats);
+        psFree (mask);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+//    diag ("timing for sample min,max");
+    /*************** MIN,MAX ******************/
+    // test stat min,max (no mask, no range)
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_MIN | PS_STAT_MAX);
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 10000; i++)
+        {
+            psVectorStats (stats, rnd, NULL, NULL, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.17, "sample min,max %f,%f (mask: 0, range: 0): %.3f sec", stats->min, stats->max, delta);
+        psFree (stats);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    // test stat min,max (no mask, no range)
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_MIN | PS_STAT_MAX);
+        psVector *mask = psVectorAlloc (1000, PS_TYPE_U8);
+        psVectorInit (mask, 0);
+        mask->data.U8[100] = 1;
+        mask->data.U8[200] = 1;
+        mask->data.U8[300] = 1;
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 10000; i++)
+        {
+            psVectorStats (stats, rnd, NULL, mask, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.18, "sample min,max %f,%f (mask: 1, range: 0): %.3f sec", stats->min, stats->max, delta);
+        psFree (stats);
+        psFree (mask);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    // test stat min,max (no mask, no range)
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_MIN | PS_STAT_MAX | PS_STAT_USE_RANGE);
+        stats->min = -10;
+        stats->max = +10;
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 10000; i++)
+        {
+            psVectorStats (stats, rnd, NULL, NULL, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.22, "sample min,max %f,%f (mask: 0, range: 1): %.3f sec", stats->min, stats->max, delta);
+        psFree (stats);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    // test stat min,max (no mask, no range)
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_MIN | PS_STAT_MAX | PS_STAT_USE_RANGE);
+        stats->min = -10;
+        stats->max = +10;
+        psVector *mask = psVectorAlloc (1000, PS_TYPE_U8);
+        psVectorInit (mask, 0);
+        mask->data.U8[100] = 1;
+        mask->data.U8[200] = 1;
+        mask->data.U8[300] = 1;
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 10000; i++)
+        {
+            psVectorStats (stats, rnd, NULL, mask, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.26, "sample min,max %f,%f (mask: 1, range: 1): %.3f sec", stats->min, stats->max, delta);
+        psFree (stats);
+        psFree (mask);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+//    diag ("timing for clipped stats");
+    /********** CLIPPED STATS ***********/
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV);
+        psVector *rnd2 = psVectorAlloc (1000, PS_TYPE_F32);
+        for (int i = 0; i < rnd2->n; i++)
+        {
+            rnd2->data.F32[i] = psRandomGaussian (seed);
+        }
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 1000; i++)
+        {
+            psVectorStats (stats, rnd2, NULL, NULL, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.3, "clipped mean %f, stdev %f (mask: 0, range: 0): %.3f sec (1000 pts / 1000 loops)", stats->clippedMean, stats->clippedStdev, delta);
+        psFree (stats);
+        psFree (rnd2);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV);
+        psVector *rnd2 = psVectorAlloc (3000, PS_TYPE_F32);
+        for (int i = 0; i < rnd2->n; i++)
+        {
+            rnd2->data.F32[i] = psRandomGaussian (seed);
+        }
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 1000; i++)
+        {
+            psVectorStats (stats, rnd2, NULL, NULL, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.5, "clipped mean %f, stdev %f (mask: 0, range: 0): %.3f sec (3000 pts / 1000 loops)", stats->clippedMean, stats->clippedStdev, delta);
+        psFree (stats);
+        psFree (rnd2);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV);
+        psVector *rnd2 = psVectorAlloc (10000, PS_TYPE_F32);
+        for (int i = 0; i < rnd2->n; i++)
+        {
+            rnd2->data.F32[i] = psRandomGaussian (seed);
+        }
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 1000; i++)
+        {
+            psVectorStats (stats, rnd2, NULL, NULL, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 1.2, "clipped mean %f, stdev %f (mask: 0, range: 0): %.3f sec (10000 pts / 1000 loops)", stats->clippedMean, stats->clippedStdev, delta);
+        psFree (stats);
+        psFree (rnd2);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+//    diag ("timing for robust stats");
+    /********** ROBUST STATS ***********/
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV | PS_STAT_ROBUST_QUARTILE);
+        psVector *rnd2 = psVectorAlloc (1000, PS_TYPE_F32);
+        for (int i = 0; i < rnd2->n; i++)
+        {
+            rnd2->data.F32[i] = psRandomGaussian (seed);
+        }
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 1000; i++)
+        {
+            psVectorStats (stats, rnd2, NULL, NULL, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.3, "robust mean %f, stdev %f (mask: 0, range: 0): %.3f sec (1000 pts / 1000 loops)", stats->robustMedian, stats->robustStdev, delta);
+        psFree (stats);
+        psFree (rnd2);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV | PS_STAT_ROBUST_QUARTILE);
+        psVector *rnd2 = psVectorAlloc (3000, PS_TYPE_F32);
+        for (int i = 0; i < rnd2->n; i++)
+        {
+            rnd2->data.F32[i] = psRandomGaussian (seed);
+        }
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 1000; i++)
+        {
+            psVectorStats (stats, rnd2, NULL, NULL, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.5, "robust mean %f, stdev %f (mask: 0, range: 0): %.3f sec (3000 pts / 1000 loops)", stats->robustMedian, stats->robustStdev, delta);
+        psFree (stats);
+        psFree (rnd2);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV | PS_STAT_ROBUST_QUARTILE);
+        psVector *rnd2 = psVectorAlloc (10000, PS_TYPE_F32);
+        for (int i = 0; i < rnd2->n; i++)
+        {
+            rnd2->data.F32[i] = psRandomGaussian (seed);
+        }
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 1000; i++)
+        {
+            psVectorStats (stats, rnd2, NULL, NULL, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 1.2, "robust mean %f, stdev %f (mask: 0, range: 0): %.3f sec (10000 pts / 1000 loops)", stats->robustMedian, stats->robustStdev, delta);
+        psFree (stats);
+        psFree (rnd2);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+//    diag ("timing for fitted stats");
+    /********** FITTED TIMING ***********/
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_FITTED_MEAN | PS_STAT_FITTED_STDEV);
+        psVector *rnd2 = psVectorAlloc (1000, PS_TYPE_F32);
+        for (int i = 0; i < rnd2->n; i++)
+        {
+            rnd2->data.F32[i] = psRandomGaussian (seed);
+        }
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 1000; i++)
+        {
+            psVectorStats (stats, rnd2, NULL, NULL, 1);
+
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.7, "fitted mean %f, stdev %f (mask: 0, range: 0): %.3f sec (1000 pts / 1000 loops)", stats->fittedMean, stats->fittedStdev, delta);
+        psFree (stats);
+        psFree (rnd2);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_FITTED_MEAN | PS_STAT_FITTED_STDEV);
+        psVector *rnd2 = psVectorAlloc (3000, PS_TYPE_F32);
+        for (int i = 0; i < rnd2->n; i++)
+        {
+            rnd2->data.F32[i] = psRandomGaussian (seed);
+        }
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 1000; i++)
+        {
+            psVectorStats (stats, rnd2, NULL, NULL, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.8, "fitted mean %f, stdev %f (mask: 0, range: 0): %.3f sec (3000 pts / 1000 loops)", stats->fittedMean, stats->fittedStdev, delta);
+        psFree (stats);
+        psFree (rnd2);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_FITTED_MEAN | PS_STAT_FITTED_STDEV);
+        psVector *rnd2 = psVectorAlloc (10000, PS_TYPE_F32);
+        for (int i = 0; i < rnd2->n; i++)
+        {
+            rnd2->data.F32[i] = psRandomGaussian (seed);
+        }
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 1000; i++)
+        {
+            psVectorStats (stats, rnd2, NULL, NULL, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 2.2, "fitted mean %f, stdev %f (mask: 0, range: 0): %.3f sec (10000 pts / 1000 loops)", stats->fittedMean, stats->fittedStdev, delta);
+        psFree (stats);
+        psFree (rnd2);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+//    diag ("timing for fitted (v2) stats");
+    /********** FITTED (v2) TIMING ***********/
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_FITTED_MEAN_V2 | PS_STAT_FITTED_STDEV_V2);
+        psVector *rnd2 = psVectorAlloc (1000, PS_TYPE_F32);
+        for (int i = 0; i < rnd2->n; i++)
+        {
+            rnd2->data.F32[i] = psRandomGaussian (seed);
+        }
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 1000; i++)
+        {
+            psVectorStats (stats, rnd2, NULL, NULL, 1);
+
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.7, "fitted mean %f, stdev %f (mask: 0, range: 0): %.3f sec (1000 pts / 1000 loops)", stats->fittedMean, stats->fittedStdev, delta);
+        psFree (stats);
+        psFree (rnd2);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_FITTED_MEAN_V2 | PS_STAT_FITTED_STDEV_V2);
+        psVector *rnd2 = psVectorAlloc (3000, PS_TYPE_F32);
+        for (int i = 0; i < rnd2->n; i++)
+        {
+            rnd2->data.F32[i] = psRandomGaussian (seed);
+        }
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 1000; i++)
+        {
+            psVectorStats (stats, rnd2, NULL, NULL, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 0.8, "fitted mean %f, stdev %f (mask: 0, range: 0): %.3f sec (3000 pts / 1000 loops)", stats->fittedMean, stats->fittedStdev, delta);
+        psFree (stats);
+        psFree (rnd2);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_FITTED_MEAN_V2 | PS_STAT_FITTED_STDEV_V2);
+        psVector *rnd2 = psVectorAlloc (10000, PS_TYPE_F32);
+        for (int i = 0; i < rnd2->n; i++)
+        {
+            rnd2->data.F32[i] = psRandomGaussian (seed);
+        }
+
+        gettimeofday (&start, NULL);
+        for (int i = 0; i < 1000; i++)
+        {
+            psVectorStats (stats, rnd2, NULL, NULL, 1);
+        }
+        gettimeofday (&mark, NULL);
+        psF64 delta = DTIME(mark, start);
+        ok (delta < 2.2, "fitted mean %f, stdev %f (mask: 0, range: 0): %.3f sec (10000 pts / 1000 loops)", stats->fittedMean, stats->fittedStdev, delta);
+        psFree (stats);
+        psFree (rnd2);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+//    diag ("compare sample, robust, and fitted mean and stdev to theoretical");
+    // compare SAMPLE, FITTED, ROBUST mean to theoretical
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV | PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV | PS_STAT_FITTED_MEAN | PS_STAT_FITTED_STDEV);
+        psVector *sample = psVectorAlloc (1000, PS_TYPE_F32);
+        psVector *robust = psVectorAlloc (1000, PS_TYPE_F32);
+        psVector *fitted = psVectorAlloc (1000, PS_TYPE_F32);
+
+        for (int i = 0; i < 1000; i++)
+        {
+            // generate a new sample
+            for (int j = 0; j < rnd->n; j++) {
+                rnd->data.F32[j] = psRandomGaussian (seed);
+            }
+            // measure the stats
+            psVectorStats (stats, rnd, NULL, NULL, 1);
+            sample->data.F32[i] = stats->sampleMean;
+            robust->data.F32[i] = stats->robustMedian;
+            fitted->data.F32[i] = stats->fittedMean;
+        }
+        psFree (stats);
+
+        stats = psStatsAlloc (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
+        psVectorStats (stats, sample, NULL, NULL, 1);
+        ok (stats->sampleStdev < 2/sqrt(1000), "sample mean %f, stdev %f (1000 tries)", stats->sampleMean, stats->sampleStdev);
+        psVectorStats (stats, robust, NULL, NULL, 1);
+        ok (stats->sampleStdev < 2/sqrt(1000), "robust mean %f, stdev %f (1000 tries)", stats->sampleMean, stats->sampleStdev);
+        psVectorStats (stats, fitted, NULL, NULL, 1);
+        ok (stats->sampleStdev < 2/sqrt(1000), "fitted mean %f, stdev %f (1000 tries)", stats->sampleMean, stats->sampleStdev);
+        psFree (stats);
+        psFree (sample);
+        psFree (robust);
+        psFree (fitted);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+//    diag ("compare sample, robust, and fitted mean and stdev to theoretical");
+    // compare SAMPLE, FITTED_V2, ROBUST mean to theoretical
+    {
+        psMemId id = psMemGetId();
+
+        psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV | PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV | PS_STAT_FITTED_MEAN_V2 | PS_STAT_FITTED_STDEV_V2);
+        psVector *sample = psVectorAlloc (1000, PS_TYPE_F32);
+        psVector *robust = psVectorAlloc (1000, PS_TYPE_F32);
+        psVector *fitted = psVectorAlloc (1000, PS_TYPE_F32);
+
+        for (int i = 0; i < 1000; i++)
+        {
+            // generate a new sample
+            for (int j = 0; j < rnd->n; j++) {
+                rnd->data.F32[j] = psRandomGaussian (seed);
+            }
+            // measure the stats
+            psVectorStats (stats, rnd, NULL, NULL, 1);
+            sample->data.F32[i] = stats->sampleMean;
+            robust->data.F32[i] = stats->robustMedian;
+            fitted->data.F32[i] = stats->fittedMean;
+        }
+        psFree (stats);
+
+        stats = psStatsAlloc (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
+        psVectorStats (stats, sample, NULL, NULL, 1);
+        ok (stats->sampleStdev < 2/sqrt(1000), "sample mean %f, stdev %f (1000 tries)", stats->sampleMean, stats->sampleStdev);
+        psVectorStats (stats, robust, NULL, NULL, 1);
+        ok (stats->sampleStdev < 2/sqrt(1000), "robust mean %f, stdev %f (1000 tries)", stats->sampleMean, stats->sampleStdev);
+        psVectorStats (stats, fitted, NULL, NULL, 1);
+        ok (stats->sampleStdev < 2/sqrt(1000), "fitted mean %f, stdev %f (1000 tries)", stats->sampleMean, stats->sampleStdev);
+        psFree (stats);
+        psFree (sample);
+        psFree (robust);
+        psFree (fitted);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    return exit_status();
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStatsTiming.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStatsTiming.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStatsTiming.txt	(revision 22158)
@@ -0,0 +1,47 @@
+
+Running tap_psStatsTiming on alala (dual AMD Opteron, 64bit, 2.2GHz)
+yields the following timing results:
+
+# timing for sample mean (1000 loops of 10000 pts)
+ok 1 - sample mean 0.009719 (mask: 0, range: 0): 0.072 sec
+ok 3 - sample mean 0.011060 (mask: 1, range: 0): 0.119 sec
+ok 5 - sample mean 0.009719 (mask: 0, range: 1): 0.170 sec
+ok 7 - sample mean 0.011060 (mask: 1, range: 1): 0.198 sec
+
+# timing for sample median (1000 loops of 10000 pts)
+ok 9 - sample median 0.021781 (mask: 0, range: 0): 2.625 sec
+ok 11 - sample median 0.023795 (mask: 1, range: 0): 2.646 sec
+ok 13 - sample median 0.021781 (mask: 0, range: 1): 2.703 sec
+ok 15 - sample median 0.023795 (mask: 1, range: 1): 2.716 sec
+
+# timing for sample stdev (1000 loops of 10000 pts)
+ok 17 - sample stdev 0.964753 (mask: 0, range: 0): 0.193 sec
+ok 19 - sample stdev 0.965887 (mask: 1, range: 0): 0.257 sec
+ok 21 - sample stdev 0.964753 (mask: 0, range: 1): 0.353 sec
+ok 23 - sample stdev 0.965887 (mask: 1, range: 1): 0.401 sec
+
+# timing for sample min,max (1000 loops of 10000 pts)
+ok 25 - sample min,max -3.205688,2.706797 (mask: 0, range: 0): 0.125 sec
+ok 27 - sample min,max -3.205688,2.706797 (mask: 1, range: 0): 0.152 sec
+ok 29 - sample min,max -3.205688,2.706797 (mask: 0, range: 1): 0.201 sec
+ok 31 - sample min,max -3.205688,2.706797 (mask: 1, range: 1): 0.238 sec
+
+# timing for clipped stats
+not ok 33 - clipped mean -0.047714, stdev 0.991979 (mask: 0, range: 0): 0.369 sec (1000 pts / 1000 loops)
+not ok 35 - clipped mean 0.023963, stdev 0.972186 (mask: 0, range: 0): 1.219 sec (3000 pts / 1000 loops)
+not ok 37 - clipped mean -0.007020, stdev 0.985410 (mask: 0, range: 0): 4.883 sec (10000 pts / 1000 loops)
+
+NOTE: these fail because they are being compared to the 'robust' stats
+limits below.  The clipped mean algorithm should not be so slow (and
+apparently non-linear in npts).
+
+# timing for robust stats
+ok 39 - robust mean 0.123348, stdev 1.014896 (mask: 0, range: 0): 0.187 sec (1000 pts / 1000 loops)
+ok 41 - robust mean -0.006812, stdev 0.974468 (mask: 0, range: 0): 0.382 sec (3000 pts / 1000 loops)
+ok 43 - robust mean -0.013591, stdev 1.001539 (mask: 0, range: 0): 1.076 sec (10000 pts / 1000 loops)
+
+# timing for fitted stats
+ok 45 - fitted mean -0.029859, stdev 0.982947 (mask: 0, range: 0): 0.381 sec (1000 pts / 1000 loops)
+ok 47 - fitted mean 0.014660, stdev 0.956168 (mask: 0, range: 0): 0.727 sec (3000 pts / 1000 loops)
+ok 49 - fitted mean -0.008402, stdev 1.001366 (mask: 0, range: 0): 1.914 sec (10000 pts / 1000 loops)
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats_Sample_01.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats_Sample_01.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tap_psStats_Sample_01.c	(revision 22158)
@@ -0,0 +1,608 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+// example tap lines:
+// ok(condition, "condition succeeded");
+// skip_start(condition, Nskip, "Skipping tests because of failure");
+
+static float yraw_01[] = {
+                             11, 16, 13, 17, 17, 17, 23, 14, 18, 15,
+                             16, 13, 12, 17, 19, 15, 21, 18, 18, 17,
+                             15, 20, 26, 14, 12, 13, 19, 16, 14, 21,
+                             16, 12, 18, 14, 18, 25, 20, 16, 19, 16,
+                             14, 12, 20, 13, 12, 21, 16, 18, 11, 22,
+                             16, 23, 20, 21, 54, 12, 12, 16, 17, 14,
+                             18, 21, 19, 18, 16, 19, 18, 23, 21, 20,
+                             20, 22, 15, 13, 14, 15, 19, 16, 15, 23,
+                             14, 25, 18, 16, 20, 20, 19, 16, 22, 11,
+                             19, 12, 14, 21, 19, 15, 16, 35, 20, 18,
+                             14, 13, 18, 18, 19, 23, 19, 19, 13, 288,
+                             19, 17, 17, 19, 12, 18, 15, 14, 13, 16,
+                             10, 12, 22, 15, 13, 14, 15, 22, 16, 18,
+                             13, 19, 17, 17, 17, 16, 16, 15, 15, 24,
+                             25, 45, 23, 19, 18, 23, 12, 18, 20, 11,
+                             25, 16, 15, 15, 200, 16, 13, 19, 11, 16,
+                             19, 16, 13, 14, 12, 10, 17, 20, 25, 17,
+                             14, 13, 20, 9, 17, 13, 19, 16, 27, 19,
+                             20, 16, 15, 17, 15, 18, 20, 17, 19, 13,
+                             21, 11, 20, 19, 12, 17, 23, 8, 17, 13,
+                             11, 16, 29, 16, 16, 20, 13, 19, 20, 19,
+                             18, 22, 21, 20, 15, 11, 17, 17, 15, 17,
+                             13, 16, 19, 20, 21, 20, 18, 17, 99, 14,
+                             13, 20, 16, 18, 12, 15, 21, 17, 18, 20,
+                             19, 12, 9, 24, 10, 13, 18, 16, 15, 19,
+                             13, 19, 12, 22, 22, 20, 17, 13, 14, 14,
+                             20, 10, 19, 19, 18, 20, 15, 14, 13, 20,
+                             13, 14, 17, 19, 16, 25, 17, 15, 11, 19,
+                             19, 14, 15, 15, 12, 14, 16, 13, 20, 16,
+                             10, 15, 20, 21, 19, 17, 12, 18, 17, 17,
+                             20, 14, 19, 17, 19, 7, 12, 17, 24, 18,
+                             17, 13, 14, 16, 20, 15, 10, 18, 13, 18,
+                             17, 16, 13, 13, 21, 13, 15, 11, 15, 16,
+                             18, 13, 11, 18, 13, 12, 15, 17, 16, 19,
+                             12, 14, 20, 13, 26, 16, 20, 14, 12, 18,
+                             15, 24, 14, 12, 19, 19, 12, 15, 18, 20,
+                             16, 17625, 17, 17, 14, 22, 15, 17, 19, 17,
+                             15, 16, 13, 14, 18, 16, 11, 20, 20, 14,
+                             19, 16, 11, 12, 18, 13, 8, 20, 10, 17,
+                             18, 17, 21, 16, 18, 16, 16, 22, 19, 12,
+                             15, 14, 21, 13, 16, 11, 17, 12, 19, 18,
+                             18, 15, 18, 12, 17, 24, 12, 20, 21, 14,
+                             21, 14, 21, 11, 19, 13, 22, 15, 17, 21,
+                             21, 22, 16, 14, 21, 26, 17, 21, 20, 11,
+                             12, 15, 21, 19, 19, 17, 22, 16, 17, 18,
+                             13, 12, 13, 88, 14, 14, 9, 19, 18, 12,
+                             20, 16, 16, 14, 17, 19, 19, 6, 16, 15,
+                             20, 17, 10, 19, 15, 21, 20, 9, 14, 17,
+                             10, 27, 22, 18, 11, 19, 15, 15, 19, 13,
+                             15, 24, 22, 20, 19, 14, 16, 17, 12, 15,
+                             22, 12, 18, 19, 22, 18, 23, 19, 15, 15,
+                             8, 13, 24, 15, 12, 30, 16, 18, 15, 21,
+                             18, 14, 18, 20, 17, 12, 20, 19, 12, 17,
+                             13, 18, 20, 16, 23, 12, 17, 9, 18, 13,
+                             11, 15, 14, 20, 19, 16, 12, 19, 19, 18,
+                             22, 23, 18, 23, 18, 17, 19, 22, 15, 11,
+                             17, 20, 13, 19, 18, 17, 18, 20, 13, 14,
+                             14, 10, 22, 21, 13, 19, 14, 16, 14, 17,
+                             19, 14, 14, 26, 21, 18, 20, 11, 18, 19,
+                             20, 18, 15, 15, 19, 18, 15, 17, 12, 15,
+                             20, 18, 14, 22, 12, 13, 23, 22, 17, 10,
+                             15, 19, 18, 18, 17, 16, 19, 13, 19, 23,
+                             15, 13, 10, 14, 16, 14, 17, 15, 16, 20,
+                             17, 12, 20, 11, 19, 11, 20, 9, 27, 23,
+                             17, 18, 18, 19, 20, 15, 15, 18, 13, 13,
+                             21, 15, 18, 13, 19, 23, 19, 8, 21, 19,
+                             9, 22, 15, 14, 24, 17, 19, 15, 22, 19,
+                             18, 13, 11, 18, 13, 21, 17, 12, 13, 18,
+                             11, 16, 19, 16, 19, 24, 15, 16, 17, 18,
+                             19, 17, 19, 20, 18, 14, 16, 15, 20, 13,
+                             13, 16, 10, 15, 29, 13, 22, 18, 11, 13,
+                             18, 23, 13, 11, 19, 25, 18, 17, 17, 20,
+                             16, 16, 22, 12, 20, 39, 14, 21, 19, 10,
+                             61, 18, 24, 16, 14, 20, 20, 19, 16, 18,
+                             11, 16, 16, 20, 16, 7, 16, 14, 12, 24,
+                             20, 16, 17, 15, 11, 20, 13, 12, 25, 15,
+                             13, 15, 18, 12, 6, 18, 15, 24, 11, 15,
+                             14, 12, 14, 15, 15, 17, 20, 14, 21, 17,
+                             14, 19, 22, 13, 15, 12, 17, 19, 23, 15,
+                             17, 25, 15, 14, 23, 6, 17, 9, 10, 16,
+                             17, 17, 16, 18, 26, 15, 17, 23, 14, 11,
+                             22, 19, 21, 16, 15, 21, 15, 10, 22, 14,
+                             23, 12, 16, 20, 13, 16, 11, 19, 12, 19,
+                             16, 15, 43, 18, 16, 13, 27, 12, 13, 14,
+                             18, 15, 14, 18, 19, 14, 15, 21, 15, 20,
+                             13, 21, 19, 21, 18, 21, 13, 24, 22, 14,
+                             22, 14, 17, 21, 15, 17, 14, 16, 21, 11,
+                             17, 21, 26, 9, 12, 17, 15, 13, 13, 16,
+                             25, 23, 17, 13, 20, 16, 19, 17, 18, 19,
+                             17, 17, 20, 17, 17, 15, 20, 15, 10, 13,
+                             11, 18, 9, 19, 18, 28, 18, 19, 18, 15,
+                             22, 16, 16, 17, 15, 24, 19, 16, 10, 18,
+                             16, 15, 32, 17, 15, 17, 18, 11, 25, 15,
+                             19, 11, 20, 17, 17, 20, 18, 18, 16, 22,
+                             19, 15, 22, 16, 14, 21, 14, 14, 13, 14,
+                             14, 19, 21, 18, 18, 19, 12, 13, 19, 19,
+                             19, 16, 18, 16, 13, 17, 25, 17, 18, 16,
+                             25, 25, 19, 20, 13, 23, 13, 14, 18, 18,
+                             20, 27, 15, 23, 23, 17, 25, 13, 12, 19,
+                             17, 13, 25, 18, 13, 12, 15, 18, 16, 12,
+                         };
+
+static float yraw_02[] = {
+                             428, 405, 820, 581, 629, 396, 383, 400, 631, 413,
+                             614, 379, 646, 1629, 353, 2748, 400, 654, 1242, 556,
+                             1423, 524, 7261, 1997, 697, 1389, 818, 26580, 495, 26915,
+                             320, 1242, 592, 490, 580, 651, 421, 487, 1644, 1909,
+                             2791, 551, 386, 426, 504, 995, 598, 1235, 481, 589,
+                             619, 1608, 385, 687, 1119, 463, 1803, 338, 427, 2509,
+                             503, 426, 1305, 425, 394, 1173, 772, 672, 2239, 1171,
+                             1117, 583, 1028, 1837, 2287, 413, 762, 2109, 955, 959,
+                             1682, 1682, 1555, 481, 663, 987, 415, 668, 417, 1045,
+                             2094, 464, 3437, 1566, 487, 1067, 975, 1217, 6089, 383,
+                             394, 415, 1117, 522, 673, 1567, 559, 15690, 325, 591,
+                             607, 634, 966, 293, 1178, 334, 526, 552, 994, 1852,
+                             2689, 1175, 1221, 410, 933, 1106, 1094, 7888, 461, 2142,
+                             600, 395, 1963, 663, 882, 582, 456, 715, 459, 1527,
+                             1948, 1074, 1035, 556, 519, 624, 728, 415, 735, 414,
+                             392, 586, 745, 624, 588, 912, 1550, 2030, 451, 25635,
+                             774, 395, 452, 593, 644, 1807, 442, 33256, 1916, 1804,
+                             13222, 538, 1054, 433, 2055, 832, 545, 924, 2808, 597,
+                             456, 833, 812, 780, 422, 1189, 617, 1613, 1349, 30099,
+                             561, 2128, 1225, 1100, 415, 950, 403, 34824, 496, 388,
+                             670, 372, 503, 363, 604, 405, 1239, 612, 300, 17802,
+                             1560, 1123, 380, 2398, 1156, 1007, 1795, 311, 370, 1905,
+                             845, 1298, 1711, 1962, 408, 1421, 638, 657, 2339, 2242,
+                             3202, 2687, 1478, 618, 19826, 1263, 359, 888, 346, 673,
+                             487, 500, 2167, 1441, 382, 574, 360, 859, 2557, 441,
+                             1870, 361, 524, 864, 1910, 1993, 831, 542, 815, 677,
+                             321, 1018, 655, 1076, 680, 779, 518, 19929, 429, 514,
+                             972, 946, 388, 508, 1019, 316, 17112, 640, 2896, 1328,
+                             805, 432, 345, 858, 596, 488, 2105, 427, 1761, 711,
+                             689, 1003, 454, 427, 499, 468, 922, 394, 400, 2056,
+                             431, 433, 327, 1635, 438, 462, 602, 973, 761, 363,
+                             2206, 2335, 2451, 332, 1927, 1495, 649, 1112, 1036, 1360,
+                             539, 931, 1396, 408, 332, 871, 449, 508, 368, 1213,
+                             400, 479, 402, 1787, 426, 720, 846, 869, 650, 414,
+                             413, 19125, 385, 967, 1109, 22290, 918, 1752, 567, 1766,
+                             386, 1170, 619, 1963, 743, 605, 740, 517, 623, 631,
+                             430, 776, 750, 649, 778, 922, 1194, 868, 489, 770,
+                             387, 406, 545, 563, 1633, 469, 3058, 1600, 918, 1546,
+                             1969, 1611, 806, 699, 583, 581, 803, 657, 394, 1205,
+                             388, 709, 1174, 1849, 1571, 1051, 487, 1301, 1189, 1626,
+                             578, 398, 1514, 350, 501, 535, 1079, 1743, 1426, 1074,
+                             669, 3664, 757, 517, 1027, 1097, 1264, 2322, 359, 527,
+                             664, 560, 558, 22642, 331, 896, 1470, 934, 467, 1019,
+                             727, 424, 353, 601, 1097, 832, 510, 520, 1185, 1420,
+                             363, 965, 619, 2322, 4277, 20030, 2087, 2823, 560, 19312,
+                             1973, 770, 356, 832, 2467, 342, 660, 18751, 1706, 313,
+                             1069, 2490, 1238, 1013, 1471, 3348, 760, 871, 723, 397,
+                             1104, 371, 2382, 27958, 621, 339, 465, 616, 2282, 524,
+                             601, 379, 587, 534, 1408, 1260, 717, 1709, 965, 434,
+                             611, 1344, 387, 1660, 539, 831, 401, 842, 864, 1453,
+                             1746, 468, 391, 398, 376, 932, 342, 483, 824, 384,
+                             991, 591, 443, 419, 1112, 598, 379, 549, 511, 1626,
+                             1221, 14651, 2117, 1570, 899, 1063, 994, 2198, 424, 380,
+                             2611, 3374, 533, 565, 1098, 300, 857, 1517, 720, 1785,
+                             659, 9076, 1145, 476, 1588, 729, 551, 667, 1041, 364,
+                             447, 406, 1271, 1515, 345, 343, 577, 449, 571, 1066,
+                             1161, 1251, 332, 1669, 393, 5503, 466, 481, 18535, 420,
+                             1910, 1093, 4162, 448, 660, 395, 485, 450, 520, 461,
+                             406, 2414, 1150, 714, 411, 18470, 1054, 401, 582, 318,
+                             404, 434, 517, 3252, 1714, 997, 481, 833, 504, 407,
+                             490, 1942, 439, 3112, 910, 605, 727, 1347, 954, 565,
+                             493, 551, 535, 416, 393, 629, 4489, 395, 18156, 487,
+                             504, 618, 438, 1001, 21729, 644, 1340, 390, 355, 716,
+                             911, 575, 541, 2158, 8211, 959, 1004, 1370, 335, 611,
+                             385, 1382, 788, 1135, 929, 2275, 653, 549, 549, 1980,
+                             390, 556, 765, 1185, 1038, 493, 476, 387, 1980, 3695,
+                             808, 297, 1124, 829, 378, 835, 3024, 1273, 613, 1330,
+                             473, 15685, 3112, 628, 358, 1317, 607, 2270, 538, 808,
+                             1083, 287, 1598, 617, 438, 398, 435, 464, 476, 554,
+                             519, 507, 1171, 886, 717, 545, 1698, 1063, 533, 903,
+                             464, 2416, 1608, 18915, 337, 1222, 323, 981, 408, 1482,
+                             1268, 1413, 967, 392, 1373, 19138, 1133, 867, 1661, 2124,
+                             508, 304, 503, 406, 14095, 1091, 370, 435, 1231, 764,
+                             499, 2387, 3092, 361, 530, 945, 878, 1965, 5488, 1967,
+                             1148, 484, 565, 490, 995, 1807, 733, 331, 1273, 1231,
+                             459, 14455, 1510, 555, 7084, 841, 1024, 3561, 792, 440,
+                             1821, 574, 429, 1085, 691, 791, 667, 1684, 622, 1019,
+                             1704, 1105, 899, 307, 1987, 352, 639, 416, 428, 2525,
+                             312, 888, 444, 542, 364, 327, 400, 1629, 28582, 628,
+                             332, 513, 452, 361, 967, 21400, 544, 1103, 1134, 29599,
+                             638, 16500, 1148, 572, 364, 776, 794, 1967, 447, 1015,
+                             433, 619, 417, 897, 3099, 1957, 809, 401, 442, 529,
+                             433, 350, 895, 18687, 390, 553, 565, 1259, 21421, 1340,
+                             306, 2057, 473, 338, 889, 320, 974, 620, 1074, 1048,
+                             325, 300, 1867, 415, 358, 1721, 362, 436, 435, 484,
+                             1478, 1907, 590, 2146, 7816, 583, 381, 1610, 544, 376,
+                             2144, 589, 952, 389, 1145, 483, 958, 854, 814, 588,
+                             25947, 659, 830, 1045, 408, 880, 2352, 1651, 1288, 1022,
+                             1976, 1292, 838, 411, 796, 375, 879, 2339, 1047, 945,
+                             1922, 1322, 455, 358, 677, 25142, 977, 344, 1305, 421,
+                             1119, 682, 823, 1054, 554, 485, 1732, 1980, 326, 444,
+                             1762, 738, 15028, 413, 349, 2474, 2837, 1074, 763, 1400,
+                             686, 1184, 491, 6502, 399, 2194, 384, 968, 403, 462,
+                             499, 555, 1361, 568, 1315, 3912, 514, 514, 1066, 519,
+                             1024, 1307, 1056, 402, 914, 513, 444, 347, 406, 506,
+                             442, 614, 356, 1222, 597, 1162, 515, 22060, 2408, 2930,
+                             5935, 1057, 747, 1396, 400, 1576, 1212, 8900, 318, 688,
+                             2122, 1771, 316, 758, 445, 381, 1115, 394, 2284, 1515,
+                             1877, 637, 1279, 2291,
+                         };
+
+static float yraw_03[] = {
+                             183.6000061, 171.3600006, 182.5800018, 178.5, 176.4600067,
+                             176.4600067, 171.3600006, 178.5, 183.6000061, 175.4400024,
+                             159.1199951, 180.5399933, 183.6000061, 187.6799927, 175.4400024,
+                             181.5599976, 174.4199982, 179.5200043, 180.5399933, 187.6799927,
+                             183.6000061, 171.3600006, 177.4799957, 192.7799988, 184.6199951,
+                             176.4600067, 178.5, 182.5800018, 173.3999939, 191.7599945,
+                             202.9799957, 167.2799988, 181.5599976, 185.6399994, 173.3999939,
+                             159.1199951, 178.5, 188.6999969, 179.5200043, 178.5,
+                             184.6199951, 175.4400024, 186.6600037, 179.5200043, 183.6000061,
+                             182.5800018, 173.3999939, 181.5599976, 184.6199951, 177.4799957,
+                             162.1799927, 186.6600037, 163.1999969, 199.9199982, 173.3999939,
+                             170.3399963, 184.6199951, 190.7400055, 173.3999939, 178.5,
+                             189.7200012, 192.7799988, 166.2599945, 187.6799927, 174.4199982,
+                             176.4600067, 181.5599976, 199.9199982, 193.8000031, 170.3399963,
+                             182.5800018, 199.9199982, 183.6000061, 160.1399994, 184.6199951,
+                             195.8399963, 173.3999939, 189.7200012, 192.7799988, 162.1799927,
+                             174.4199982, 190.7400055, 175.4400024, 192.7799988, 181.5599976,
+                             185.6399994, 184.6199951, 166.2599945, 189.7200012, 192.7799988,
+                             183.6000061, 190.7400055, 188.6999969, 174.4199982, 184.6199951,
+                             186.6600037, 182.5800018, 173.3999939, 171.3600006, 166.2599945,
+                             166.2599945, 176.4600067, 147.8999939, 187.6799927, 166.2599945,
+                             173.3999939, 179.5200043, 166.2599945, 169.3200073, 172.3800049,
+                             174.4199982, 195.8399963, 192.7799988, 177.4799957, 181.5599976,
+                             163.1999969, 171.3600006, 194.8200073, 159.1199951, 173.3999939,
+                             182.5800018, 178.5, 179.5200043, 184.6199951, 179.5200043,
+                             164.2200012, 191.7599945, 177.4799957, 186.6600037, 168.3000031,
+                             168.3000031, 168.3000031, 180.5399933, 179.5200043, 175.4400024,
+                             174.4199982, 184.6199951, 186.6600037, 164.2200012, 169.3200073,
+                             187.6799927, 189.7200012, 166.2599945, 169.3200073, 187.6799927,
+                             172.3800049, 204, 194.8200073, 177.4799957, 188.6999969,
+                             171.3600006, 184.6199951, 182.5800018, 184.6199951, 176.4600067,
+                             186.6600037, 170.3399963, 170.3399963, 182.5800018, 184.6199951,
+                             168.3000031, 175.4400024, 176.4600067, 164.2200012, 183.6000061,
+                             161.1600037, 175.4400024, 167.2799988, 179.5200043, 176.4600067,
+                             175.4400024, 179.5200043, 158.1000061, 168.3000031, 168.3000031,
+                             179.5200043, 192.7799988, 190.7400055, 178.5, 173.3999939,
+                             180.5399933, 179.5200043, 191.7599945, 184.6199951, 177.4799957,
+                             182.5800018, 188.6999969, 169.3200073, 162.1799927, 172.3800049,
+                             160.1399994, 177.4799957, 176.4600067, 180.5399933, 170.3399963,
+                             168.3000031, 171.3600006, 180.5399933, 162.1799927, 163.1999969,
+                             170.3399963, 180.5399933, 164.2200012, 183.6000061, 178.5,
+                             193.8000031, 177.4799957, 178.5, 183.6000061, 192.7799988,
+                             157.0800018, 176.4600067, 190.7400055, 179.5200043, 157.0800018,
+                             178.5, 165.2400055, 195.8399963, 177.4799957, 166.2599945,
+                             172.3800049, 182.5800018, 175.4400024, 187.6799927, 164.2200012,
+                             178.5, 173.3999939, 173.3999939, 173.3999939, 172.3800049,
+                             183.6000061, 181.5599976, 163.1999969, 179.5200043, 193.8000031,
+                             172.3800049, 158.1000061, 171.3600006, 165.2400055, 183.6000061,
+                             187.6799927, 158.1000061, 171.3600006, 168.3000031, 166.2599945,
+                             166.2599945, 178.5, 179.5200043, 165.2400055, 176.4600067,
+                             160.1399994, 193.8000031, 170.3399963, 162.1799927, 180.5399933,
+                             159.1199951, 189.7200012, 160.1399994, 196.8600006, 173.3999939,
+                             170.3399963, 165.2400055, 193.8000031, 192.7799988, 184.6199951,
+                             151.9799957, 167.2799988, 162.1799927, 183.6000061, 166.2599945,
+                             177.4799957, 168.3000031, 191.7599945, 181.5599976, 166.2599945,
+                             171.3600006, 188.6999969, 172.3800049, 195.8399963, 189.7200012,
+                             177.4799957, 167.2799988, 191.7599945, 169.3200073, 181.5599976,
+                             180.5399933, 162.1799927, 171.3600006, 162.1799927, 171.3600006,
+                             177.4799957, 167.2799988, 180.5399933, 182.5800018, 187.6799927,
+                             175.4400024, 193.8000031, 174.4199982, 183.6000061, 179.5200043,
+                             164.2200012, 162.1799927, 186.6600037, 189.7200012, 186.6600037,
+                             171.3600006, 187.6799927, 189.7200012, 175.4400024, 184.6199951,
+                             172.3800049, 177.4799957, 183.6000061, 176.4600067, 171.3600006,
+                             172.3800049, 181.5599976, 175.4400024, 170.3399963, 196.8600006,
+                             201.9600067, 180.5399933, 176.4600067, 183.6000061, 175.4400024,
+                             184.6199951, 163.1999969, 177.4799957, 176.4600067, 175.4400024,
+                             192.7799988, 167.2799988, 176.4600067, 184.6199951, 184.6199951,
+                             177.4799957, 185.6399994, 196.8600006, 186.6600037, 184.6199951,
+                             169.3200073, 164.2200012, 185.6399994, 168.3000031, 186.6600037,
+                             180.5399933, 177.4799957, 177.4799957, 186.6600037, 191.7599945,
+                             177.4799957, 181.5599976, 166.2599945, 179.5200043, 184.6199951,
+                             178.5, 171.3600006, 184.6199951, 192.7799988, 182.5800018,
+                             186.6600037, 175.4400024, 182.5800018, 173.3999939, 186.6600037,
+                             162.1799927, 175.4400024, 196.8600006, 166.2599945, 189.7200012,
+                             189.7200012, 182.5800018, 172.3800049, 165.2400055, 191.7599945,
+                             174.4199982, 173.3999939, 178.5, 171.3600006, 157.0800018,
+                             182.5800018, 161.1600037, 195.8399963, 186.6600037, 167.2799988,
+                             166.2599945, 182.5800018, 178.5, 176.4600067, 181.5599976,
+                             184.6199951, 183.6000061, 179.5200043, 174.4199982, 167.2799988,
+                             187.6799927, 176.4600067, 165.2400055, 179.5200043, 157.0800018,
+                             171.3600006, 170.3399963, 175.4400024, 161.1600037, 185.6399994,
+                             169.3200073, 192.7799988, 175.4400024, 172.3800049, 180.5399933,
+                             183.6000061, 174.4199982, 176.4600067, 164.2200012, 183.6000061,
+                             179.5200043, 165.2400055, 169.3200073, 172.3800049, 149.9400024,
+                             175.4400024, 188.6999969, 190.7400055, 171.3600006, 172.3800049,
+                             183.6000061, 178.5, 165.2400055, 176.4600067, 177.4799957,
+                             188.6999969, 192.7799988, 183.6000061, 163.1999969, 186.6600037,
+                             183.6000061, 160.1399994, 167.2799988, 172.3800049, 179.5200043,
+                             189.7200012, 172.3800049, 177.4799957, 161.1600037, 174.4199982,
+                             190.7400055, 181.5599976, 187.6799927, 176.4600067, 176.4600067,
+                             183.6000061, 176.4600067, 188.6999969, 174.4199982, 170.3399963,
+                             185.6399994, 177.4799957, 172.3800049, 179.5200043, 175.4400024,
+                             170.3399963, 169.3200073, 176.4600067, 177.4799957, 169.3200073,
+                             199.9199982, 171.3600006, 194.8200073, 188.6999969, 193.8000031,
+                             182.5800018, 171.3600006, 177.4799957, 175.4400024, 172.3800049,
+                             166.2599945, 183.6000061, 157.0800018, 177.4799957, 193.8000031,
+                             168.3000031, 175.4400024, 175.4400024, 170.3399963, 191.7599945,
+                             189.7200012, 182.5800018, 177.4799957, 157.0800018, 174.4199982,
+                             189.7200012, 162.1799927, 184.6199951, 164.2200012, 157.0800018,
+                             197.8800049, 175.4400024, 184.6199951, 202.9799957, 190.7400055,
+                             171.3600006, 160.1399994, 162.1799927, 176.4600067, 180.5399933,
+                             206.0399933, 189.7200012, 170.3399963, 175.4400024, 175.4400024,
+                             185.6399994, 187.6799927, 168.3000031, 176.4600067, 177.4799957,
+                             185.6399994, 167.2799988, 178.5, 182.5800018, 179.5200043,
+                             173.3999939, 185.6399994, 196.8600006, 183.6000061, 162.1799927,
+                             176.4600067, 189.7200012, 208.0800018, 177.4799957, 163.1999969,
+                             187.6799927, 196.8600006, 180.5399933, 188.6999969, 163.1999969,
+                             187.6799927, 168.3000031, 182.5800018, 181.5599976, 174.4199982,
+                             181.5599976, 161.1600037, 163.1999969, 184.6199951, 190.7400055,
+                             181.5599976, 185.6399994, 186.6600037, 173.3999939, 172.3800049,
+                             179.5200043, 187.6799927, 191.7599945, 190.7400055, 183.6000061,
+                             166.2599945, 196.8600006, 172.3800049, 174.4199982, 181.5599976,
+                             177.4799957, 176.4600067, 188.6999969, 184.6199951, 169.3200073,
+                             178.5, 186.6600037, 174.4199982, 185.6399994, 201.9600067,
+                             171.3600006, 177.4799957, 183.6000061, 165.2400055, 189.7200012,
+                             188.6999969, 178.5, 163.1999969, 169.3200073, 178.5,
+                             182.5800018, 173.3999939, 177.4799957, 165.2400055, 163.1999969,
+                             175.4400024, 184.6199951, 189.7200012, 186.6600037, 188.6999969,
+                             163.1999969, 158.1000061, 172.3800049, 186.6600037, 173.3999939,
+                             157.0800018, 158.1000061, 172.3800049, 197.8800049, 171.3600006,
+                             172.3800049, 184.6199951, 173.3999939, 174.4199982, 175.4400024,
+                             166.2599945, 166.2599945, 172.3800049, 171.3600006, 181.5599976,
+                             181.5599976, 187.6799927, 180.5399933, 169.3200073, 182.5800018,
+                             178.5, 179.5200043, 184.6199951, 175.4400024, 175.4400024,
+                             158.1000061, 182.5800018, 196.8600006, 167.2799988, 178.5,
+                             174.4199982, 180.5399933, 195.8399963, 183.6000061, 200.9400024,
+                             189.7200012, 186.6600037, 173.3999939, 173.3999939, 180.5399933,
+                             172.3800049, 157.0800018, 163.1999969, 171.3600006, 190.7400055,
+                             196.8600006, 179.5200043, 175.4400024, 169.3200073, 158.1000061,
+                             157.0800018, 180.5399933, 173.3999939, 170.3399963, 175.4400024,
+                             193.8000031, 170.3399963, 164.2200012, 174.4199982, 185.6399994,
+                             178.5, 176.4600067, 176.4600067, 179.5200043, 176.4600067,
+                             171.3600006, 205.0200043, 184.6199951, 180.5399933, 165.2400055,
+                             167.2799988, 162.1799927, 165.2400055, 180.5399933, 169.3200073,
+                             176.4600067, 182.5800018, 182.5800018, 175.4400024, 186.6600037,
+                             182.5800018, 183.6000061, 163.1999969, 161.1600037, 189.7200012,
+                             181.5599976, 187.6799927, 173.3999939, 173.3999939, 177.4799957,
+                             179.5200043, 198.8999939, 177.4799957, 183.6000061, 154.0200043,
+                             188.6999969, 181.5599976, 177.4799957, 174.4199982, 202.9799957,
+                             168.3000031, 164.2200012, 187.6799927, 171.3600006, 189.7200012,
+                             185.6399994, 187.6799927, 157.0800018, 193.8000031, 160.1399994,
+                             166.2599945, 193.8000031, 166.2599945, 168.3000031, 179.5200043,
+                             181.5599976, 172.3800049, 183.6000061, 184.6199951, 180.5399933,
+                             177.4799957, 192.7799988, 171.3600006, 197.8800049, 190.7400055,
+                             182.5800018, 178.5, 189.7200012, 172.3800049, 199.9199982,
+                             183.6000061, 179.5200043, 170.3399963, 179.5200043, 181.5599976,
+                             178.5, 186.6600037, 177.4799957, 160.1399994, 176.4600067,
+                             173.3999939, 168.3000031, 180.5399933, 179.5200043, 175.4400024,
+                             188.6999969, 175.4400024, 178.5, 161.1600037, 181.5599976,
+                             184.6199951, 169.3200073, 187.6799927, 164.2200012, 176.4600067,
+                             176.4600067, 174.4199982, 189.7200012, 192.7799988, 181.5599976,
+                             165.2400055, 173.3999939, 184.6199951, 164.2200012, 181.5599976,
+                             167.2799988, 157.0800018, 175.4400024, 172.3800049, 172.3800049,
+                             170.3399963, 166.2599945, 185.6399994, 175.4400024, 184.6199951,
+                             179.5200043, 198.8999939, 189.7200012, 164.2200012, 198.8999939,
+                             169.3200073, 183.6000061, 191.7599945, 168.3000031, 178.5,
+                             172.3800049, 169.3200073, 196.8600006, 170.3399963, 192.7799988,
+                             183.6000061, 186.6600037, 181.5599976, 187.6799927, 198.8999939,
+                             167.2799988, 177.4799957, 165.2400055, 173.3999939, 182.5800018,
+                             190.7400055, 167.2799988, 184.6199951, 180.5399933, 165.2400055,
+                             166.2599945, 162.1799927, 175.4400024, 169.3200073, 187.6799927,
+                             155.0399933, 173.3999939, 165.2400055, 174.4199982, 183.6000061,
+                             167.2799988, 186.6600037, 175.4400024, 173.3999939, 177.4799957,
+                             192.7799988, 180.5399933, 191.7599945, 185.6399994, 194.8200073,
+                             201.9600067, 166.2599945, 171.3600006, 177.4799957, 194.8200073,
+                             191.7599945, 177.4799957, 167.2799988, 188.6999969, 172.3800049,
+                             162.1799927, 169.3200073, 198.8999939, 183.6000061, 170.3399963,
+                             190.7400055, 170.3399963, 169.3200073, 185.6399994, 181.5599976,
+                             166.2599945, 187.6799927, 169.3200073, 157.0800018, 165.2400055,
+                             176.4600067, 174.4199982, 166.2599945, 177.4799957, 195.8399963,
+                             187.6799927, 186.6600037, 194.8200073, 181.5599976, 172.3800049,
+                             166.2599945, 168.3000031, 183.6000061, 168.3000031, 174.4199982,
+                             185.6399994, 180.5399933, 181.5599976, 189.7200012, 172.3800049,
+                             183.6000061, 187.6799927, 183.6000061, 200.9400024, 184.6199951,
+                             173.3999939, 176.4600067, 172.3800049, 169.3200073, 166.2599945,
+                             186.6600037, 181.5599976, 161.1600037, 182.5800018, 179.5200043,
+                             178.5, 174.4199982, 170.3399963, 179.5200043, 193.8000031,
+                             188.6999969, 146.8800049, 192.7799988, 171.3600006, 178.5,
+                             177.4799957, 184.6199951, 180.5399933, 163.1999969, 159.1199951,
+                             160.1399994, 178.5, 176.4600067, 176.4600067, 192.7799988,
+                             161.1600037, 166.2599945, 162.1799927, 172.3800049, 175.4400024,
+                             168.3000031, 201.9600067, 188.6999969, 185.6399994, 175.4400024,
+                             175.4400024, 182.5800018, 182.5800018, 172.3800049, 175.4400024,
+                             179.5200043, 184.6199951, 163.1999969, 195.8399963, 180.5399933,
+                             170.3399963, 212.1600037, 166.2599945, 187.6799927, 179.5200043,
+                             178.5, 176.4600067, 172.3800049, 183.6000061, 179.5200043,
+                             176.4600067, 185.6399994, 161.1600037, 187.6799927, 167.2799988,
+                             187.6799927, 199.9199982, 187.6799927, 169.3200073, 158.1000061,
+                             200.9400024, 191.7599945, 179.5200043, 170.3399963, 186.6600037,
+                             170.3399963, 184.6199951, 189.7200012, 197.8800049, 186.6600037,
+                             171.3600006, 164.2200012, 183.6000061, 180.5399933, 165.2400055,
+                             160.1399994, 183.6000061, 166.2599945, 183.6000061, 196.8600006,
+                             175.4400024, 172.3800049, 172.3800049, 181.5599976, 177.4799957,
+                             173.3999939, 176.4600067, 180.5399933, 176.4600067, 178.5,
+                             163.1999969, 189.7200012, 175.4400024, 174.4199982, 185.6399994,
+                             182.5800018, 169.3200073, 194.8200073, 192.7799988, 188.6999969,
+                             193.8000031, 175.4400024, 165.2400055, 180.5399933, 184.6199951,
+                             176.4600067, 171.3600006, 188.6999969, 199.9199982, 183.6000061,
+                             169.3200073, 175.4400024, 180.5399933, 174.4199982, 167.2799988,
+                             184.6199951, 177.4799957, 180.5399933, 180.5399933, 184.6199951,
+                             178.5, 186.6600037, 161.1600037, 183.6000061, 168.3000031,
+                             188.6999969, 184.6199951, 171.3600006, 185.6399994, 167.2799988,
+                             162.1799927, 186.6600037, 175.4400024, 166.2599945, 182.5800018,
+                             171.3600006, 176.4600067, 192.7799988, 178.5, 168.3000031,
+                             182.5800018, 184.6199951, 148.9199982, 172.3800049, 168.3000031,
+                             181.5599976, 154.0200043, 166.2599945, 174.4199982, 166.2599945,
+                             178.5, 184.6199951, 176.4600067, 171.3600006, 188.6999969,
+                             177.4799957, 172.3800049, 176.4600067, 179.5200043, 176.4600067,
+                             161.1600037, 166.2599945, 181.5599976, 170.3399963, 176.4600067,
+                             163.1999969, 183.6000061, 206.0399933, 171.3600006, 186.6600037,
+                             176.4600067, 163.1999969, 179.5200043, 176.4600067, 182.5800018,
+                             167.2799988, 174.4199982, 188.6999969, 177.4799957, 190.7400055,
+                             176.4600067, 175.4400024, 174.4199982, 179.5200043, 182.5800018,
+                             182.5800018, 175.4400024, 165.2400055, 180.5399933, 178.5,
+                             176.4600067, 191.7599945, 173.3999939, 186.6600037, 165.2400055,
+                             173.3999939, 188.6999969, 172.3800049, 168.3000031, 193.8000031,
+                             180.5399933, 172.3800049, 180.5399933, 189.7200012, 170.3399963,
+                             170.3399963, 195.8399963, 173.3999939, 187.6799927, 165.2400055,
+                             147.8999939, 173.3999939, 184.6199951, 171.3600006, 178.5,
+                             163.1999969, 171.3600006, 190.7400055, 180.5399933, 156.0599976,
+                             164.2200012, 172.3800049, 202.9799957, 201.9600067, 175.4400024,
+                             193.8000031, 176.4600067, 182.5800018, 184.6199951, 178.5,
+                             169.3200073, 166.2599945, 173.3999939, 182.5800018, 171.3600006,
+                             167.2799988, 185.6399994, 179.5200043, 188.6999969, 194.8200073,
+                             177.4799957, 177.4799957, 164.2200012, 189.7200012, 193.8000031,
+                             173.3999939, 178.5, 184.6199951, 191.7599945, 191.7599945,
+                             162.1799927, 171.3600006, 165.2400055, 197.8800049, 169.3200073,
+                             178.5, 174.4199982, 183.6000061, 189.7200012, 181.5599976,
+                             185.6399994, 179.5200043, 181.5599976, 161.1600037, 173.3999939,
+                             187.6799927, 177.4799957, 182.5800018, 171.3600006, 188.6999969,
+                             194.8200073, 176.4600067, 182.5800018, 157.0800018, 169.3200073,
+                             170.3399963, 168.3000031, 190.7400055, 170.3399963, 185.6399994,
+                             195.8399963, 172.3800049, 213.1799927, 187.6799927, 187.6799927,
+                             178.5, 181.5599976, 183.6000061, 163.1999969, 169.3200073,
+                             180.5399933, 204, 175.4400024, 158.1000061, 174.4199982,
+                             183.6000061, 181.5599976, 181.5599976, 180.5399933, 172.3800049,
+                             188.6999969, 166.2599945, 196.8600006, 187.6799927, 196.8600006,
+                             164.2200012, 160.1399994, 165.2400055, 172.3800049, 177.4799957,
+                             173.3999939, 168.3000031, 181.5599976, 164.2200012, 177.4799957,
+                             182.5800018, 162.1799927, 168.3000031, 181.5599976, 179.5200043,
+                             171.3600006, 173.3999939, 176.4600067, 197.8800049, 172.3800049,
+                             189.7200012, 172.3800049, 161.1600037, 183.6000061, 173.3999939,
+                             188.6999969, 161.1600037, 180.5399933, 160.1399994, 166.2599945,
+                             164.2200012, 182.5800018, 169.3200073, 176.4600067, 186.6600037,
+                             192.7799988, 163.1999969, 153, 182.5800018, 184.6199951,
+                             166.2599945, 167.2799988, 186.6600037, 177.4799957, 174.4199982,
+                             175.4400024, 164.2200012, 180.5399933, 178.5, 176.4600067,
+                             164.2200012, 160.1399994, 178.5, 176.4600067, 180.5399933,
+                             182.5800018, 179.5200043, 169.3200073, 178.5, 172.3800049,
+                             171.3600006, 178.5, 166.2599945, 171.3600006, 181.5599976,
+                             162.1799927, 157.0800018, 189.7200012, 177.4799957, 164.2200012,
+                             179.5200043, 187.6799927, 172.3800049, 158.1000061, 164.2200012,
+                             177.4799957, 165.2400055, 185.6399994, 174.4199982, 188.6999969,
+                             173.3999939, 168.3000031, 164.2200012, 187.6799927, 209.1000061,
+                             172.3800049, 177.4799957, 170.3399963, 172.3800049, 164.2200012,
+                             190.7400055, 177.4799957, 165.2400055, 168.3000031, 173.3999939,
+                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                         };
+
+int main (void)
+{
+    plan_tests(21);
+
+//    diag("psStats Tests with sample SDSS data from RHL and Megacam from EAM");
+//    diag("this file does not yet define a specific test");
+//    diag("the fitted mean is currently wrong for these two data sets");
+
+    {
+        psMemId id = psMemGetId();
+
+//        diag("sample 1 : problem with integer-binned data driven to tiny sigma values");
+        psStats *stats = psStatsAlloc (PS_STAT_FITTED_MEAN | PS_STAT_FITTED_STDEV |
+                                       PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV |
+                                       PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV |
+                                       PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN |
+                                       PS_STAT_SAMPLE_STDEV | PS_STAT_USE_BINSIZE);
+        stats->binsize = 1.0;
+
+
+        // copy data in static array
+        int nPts = sizeof(yraw_01) / sizeof (float);
+        psVector *y = psVectorAlloc (nPts, PS_TYPE_F32);
+        for (int i = 0; i < y->n; i++) {
+            y->data.F32[i] = yraw_01[i];
+        }
+
+        psVectorStats (stats, y, NULL, NULL, 1);
+        ok (1, "sample  mean    %f, stdev %f", stats->sampleMean,   stats->sampleStdev);
+        ok (1, "sample  median  %f, stdev %f", stats->sampleMedian, stats->sampleStdev);
+        ok (1, "clipped mean    %f, stdev %f", stats->clippedMean,  stats->clippedStdev);
+        ok (1, "robust  median  %f, stdev %f", stats->robustMedian, stats->robustStdev);
+        ok (1, "fitted  mean    %f, stdev %f", stats->fittedMean,   stats->fittedStdev);
+        psFree (stats);
+
+        stats = psStatsAlloc (PS_STAT_FITTED_MEAN_V2 | PS_STAT_FITTED_STDEV_V2 | PS_STAT_USE_BINSIZE);
+        stats->binsize = 1.0;
+        psVectorStats (stats, y, NULL, NULL, 1);
+        ok (1, "fitted  mean v2 %f, stdev %f", stats->fittedMean,   stats->fittedStdev);
+        psFree (stats);
+
+        psFree (y);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+
+//        diag("sample 2");
+        psStats *stats = psStatsAlloc (PS_STAT_FITTED_MEAN | PS_STAT_FITTED_STDEV |
+                                       PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV |
+                                       PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV |
+                                       PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN |
+                                       PS_STAT_SAMPLE_STDEV);
+
+        // copy data in static array
+        int nPts = sizeof(yraw_02) / sizeof (float);
+        psVector *y = psVectorAlloc (nPts, PS_TYPE_F32);
+        for (int i = 0; i < y->n; i++) {
+            y->data.F32[i] = yraw_02[i];
+        }
+
+        psVectorStats (stats, y, NULL, NULL, 1);
+        ok (1, "sample  mean   %f, stdev %f", stats->sampleMean,   stats->sampleStdev);
+        ok (1, "sample  median %f, stdev %f", stats->sampleMedian, stats->sampleStdev);
+        ok (1, "clipped mean   %f, stdev %f", stats->clippedMean,  stats->clippedStdev);
+        ok (1, "robust  median %f, stdev %f", stats->robustMedian, stats->robustStdev);
+        ok (1, "fitted  mean   %f, stdev %f", stats->fittedMean,   stats->fittedStdev);
+        psFree (stats);
+
+        stats = psStatsAlloc (PS_STAT_FITTED_MEAN_V2 | PS_STAT_FITTED_STDEV_V2 | PS_STAT_USE_BINSIZE);
+        stats->binsize = 1.0;
+        psVectorStats (stats, y, NULL, NULL, 1);
+        ok (1, "fitted  mean v2 %f, stdev %f", stats->fittedMean,   stats->fittedStdev);
+        psFree (stats);
+
+        psFree (y);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    {
+        psMemId id = psMemGetId();
+
+//        diag("sample 3");
+        psStats *stats = psStatsAlloc (PS_STAT_FITTED_MEAN | PS_STAT_FITTED_STDEV |
+                                       PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV |
+                                       PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV |
+                                       PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN |
+                                       PS_STAT_SAMPLE_STDEV | PS_STAT_USE_BINSIZE);
+        stats->binsize = 1.0;
+
+
+        // copy data in static array
+        int nPts = sizeof(yraw_03) / sizeof (float);
+        psVector *y = psVectorAlloc (nPts, PS_TYPE_F32);
+        for (int i = 0; i < y->n; i++) {
+            y->data.F32[i] = yraw_03[i];
+        }
+
+        psVectorStats (stats, y, NULL, NULL, 1);
+        ok (1, "sample  mean   %f, stdev %f", stats->sampleMean,   stats->sampleStdev);
+        ok (1, "sample  median %f, stdev %f", stats->sampleMedian, stats->sampleStdev);
+        ok (1, "clipped mean   %f, stdev %f", stats->clippedMean,  stats->clippedStdev);
+        ok (1, "robust  median %f, stdev %f", stats->robustMedian, stats->robustStdev);
+        ok (1, "fitted  mean   %f, stdev %f", stats->fittedMean,   stats->fittedStdev);
+        psFree (stats);
+
+        stats = psStatsAlloc (PS_STAT_FITTED_MEAN_V2 | PS_STAT_FITTED_STDEV_V2 | PS_STAT_USE_BINSIZE);
+        stats->binsize = 1.0;
+        psVectorStats (stats, y, NULL, NULL, 1);
+        ok (1, "fitted  mean v2 %f, stdev %f", stats->fittedMean,   stats->fittedStdev);
+        psFree (stats);
+
+        psFree (y);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    return exit_status();
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psFunc01.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psFunc01.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psFunc01.c	(revision 22158)
@@ -0,0 +1,77 @@
+/*****************************************************************************
+    This routine must ensure that the psGaussian() shall evaluate a
+    specified Gaussian at some X.
+ 
+    It also tests the p_psGaussianDev() procedure.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+#include "psMemory.h"
+#include "psPolynomial.h"
+#define MY_MEAN 30.0
+#define MY_STDEV 2.0
+#define N 30
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    psS32 testStatus = true;
+    float x = 0.0;
+    psS32  memLeaks;
+    psS32  currentId = psMemGetId();
+    psVector *myGaussData = NULL;
+    printPositiveTestHeader(stdout,
+                            "psPolynomial functions",
+                            "psGaussian()");
+
+
+    for (x = 0.0 ; x < (MY_MEAN * 2.0) ; x+= 1.0) {
+        printf("normal psGaussian(%f) is %f\n", x, psGaussian(x, MY_MEAN, MY_STDEV, true));
+        x = x + 1.0;
+    }
+
+    for (x = 0.0 ; x < (MY_MEAN * 2.0) ; x+= 1.0) {
+        printf("NON-normal psGaussian(%f) is %f\n", x, psGaussian(x, MY_MEAN, MY_STDEV, false));
+        x = x + 1.0;
+    }
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    printFooter(stdout,
+                "psPolynomial functions",
+                "psGaussian()",
+                testStatus);
+
+
+    printPositiveTestHeader(stdout,
+                            "psPolynomial functions",
+                            "p_psGaussianDev()");
+
+    myGaussData = p_psGaussianDev(MY_MEAN, MY_STDEV, N);
+    for (psS32 i = 0; i < N ; i++) {
+        printf("Gaussian Deviate [%d] is %f\n", i, myGaussData->data.F32[i]);
+    }
+
+    if ( myGaussData->type.type != PS_TYPE_F32) {
+        psAbort("p_psGaussianDev did not return a vector of type F32");
+    }
+
+    psFree(myGaussData);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    printFooter(stdout,
+                "psPolynomial functions",
+                "p_psGaussianDev()",
+                testStatus);
+
+    return (!testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psHist00.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psHist00.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psHist00.c	(revision 22158)
@@ -0,0 +1,135 @@
+/*****************************************************************************
+    This routine must ensure that the psHistogram structure is correctly
+    allocated and deallocated by the procedure psHistogramAlloc().
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+#include "psMemory.h"
+#define LOWER 20.0
+#define UPPER 30.0
+
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    //
+    // We list pertinent psStats.c functions here for debugging ease.
+    //
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("p_psVectorBinDisect", 0);
+    psTraceSetLevel("psHistogramAlloc", 0);
+    psTraceSetLevel("psHistogramAllocGeneric", 0);
+    psTraceSetLevel("UpdateHistogramBins", 0);
+    psTraceSetLevel("psVectorHistogram", 0);
+    psHistogram *myHist = NULL;
+    psS32 testStatus      = true;
+    psS32 memLeaks        = 0;
+    psS32 i               = 0;
+    psS32 nb              = 0;
+    psS32 numBins         = 0;
+    psS32 currentId       = 0;
+
+    currentId       = psMemGetId();
+    for (nb=0;nb<4;nb++) {
+        if (nb == 0)
+            numBins = 1;
+        if (nb == 1)
+            numBins = 2;
+        if (nb == 2)
+            numBins = 10;
+        if (nb == 3)
+            numBins = 20;
+        /*********************************************************************/
+        /*  Allocate and initialize data structures                          */
+        /*********************************************************************/
+        printPositiveTestHeader(stdout,
+                                "psStats functions",
+                                "Allocate the psHistogram structure.");
+
+        myHist = psHistogramAlloc(LOWER, UPPER, numBins);
+
+        if (myHist->nums->n != numBins) {
+            printf("ERROR: myHist->nums->n is wrong size (%ld)\n", myHist->nums->n);
+            testStatus = false;
+        }
+
+        if (myHist->bounds->n != numBins+1) {
+            printf("ERROR: myHist->bounds->n is wrong size (%ld)\n", myHist->bounds->n);
+            testStatus = false;
+        }
+
+        for (i=0;i<numBins;i++) {
+            if (myHist->nums->data.F32[i] != 0.0) {
+                printf("ERROR: myHist->nums->data.U32[%d] not initialized to 0.\n", i);
+                testStatus = false;
+            }
+            myHist->nums->data.F32[i] = 0.0;
+        }
+
+        if (myHist->minNum != 0) {
+            printf("ERROR: myHist->minNum is %d\n", myHist->minNum);
+            testStatus = false;
+        }
+
+        if (myHist->maxNum != 0) {
+            printf("myHist->maxNum is %d\n", myHist->maxNum);
+            testStatus = false;
+        }
+
+        if (myHist->uniform != true) {
+            printf("ERROR: myHist->uniform is %d\n", myHist->uniform);
+            testStatus = false;
+        }
+
+        for (i=0;i<numBins;i++) {
+            printf("Bin number %d bounds: (%6.3f - %6.3f)\n", i,
+                   myHist->bounds->data.F32[i],
+                   myHist->bounds->data.F32[i+1]);
+        }
+
+        psMemCheckCorruption(1);
+        psFree(myHist);
+        psMemCheckCorruption(1);
+
+        printFooter(stdout,
+                    "psStats functions",
+                    "Allocate the psHistogram structure.",
+                    testStatus);
+    }
+
+
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "Allocate the psHistogram structure. (UPPER<LOWER)");
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message.");
+    myHist = psHistogramAlloc(UPPER, LOWER, numBins);
+    if (myHist != NULL) {
+        printf("ERROR: myHist != NULL\n");
+    }
+    printFooter(stdout,
+                "psStats functions",
+                "Allocate the psHistogram structure. (UPPER<LOWER)",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "Deallocate the psHistogram structure.");
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    psMemCheckCorruption(1);
+
+    printFooter(stdout,
+                "psStats functions",
+                "Deallocate the psHistogram structure.",
+                testStatus);
+
+    return (!testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psHist01.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psHist01.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psHist01.c	(revision 22158)
@@ -0,0 +1,124 @@
+/*****************************************************************************
+    This routine must ensure that the psHistogram structure is correctly
+    allocated and deallocated by the procedure psHistogramAllocGeneric().
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+#include "psMemory.h"
+#define LOWER 20.0
+#define UPPER 30.0
+
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    //
+    // We list pertinent psStats.c functions here for debugging ease.
+    //
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("p_psVectorBinDisect", 0);
+    psTraceSetLevel("psHistogramAlloc", 0);
+    psTraceSetLevel("psHistogramAllocGeneric", 0);
+    psTraceSetLevel("UpdateHistogramBins", 0);
+    psTraceSetLevel("psVectorHistogram", 0);
+    psHistogram *myHist = NULL;
+    psVector *myBounds  = NULL;
+    psS32 testStatus      = true;
+    psS32 memLeaks        = 0;
+    psS32 i               = 0;
+    psS32 nb              = 0;
+    psS32 numBins         = 0;
+    psS32 currentId       = 0;
+
+    currentId       = psMemGetId();
+    for (nb=0;nb<4;nb++) {
+        if (nb == 0)
+            numBins = 1;
+        if (nb == 1)
+            numBins = 2;
+        if (nb == 2)
+            numBins = 10;
+        if (nb == 3)
+            numBins = 20;
+        /*********************************************************************/
+        /*  Allocate and initialize data structures                          */
+        /*********************************************************************/
+        printPositiveTestHeader(stdout,
+                                "psStats functions",
+                                "Allocate the psHistogram structure.");
+        myBounds = psVectorAlloc(numBins+1, PS_TYPE_F32);
+        myBounds->n = myBounds->nalloc;
+        for (i=0;i<numBins+1;i++) {
+            myBounds->data.F32[i] = LOWER + ((UPPER - LOWER) / (float) numBins) *
+                                    (float) i;
+        }
+        myHist = psHistogramAllocGeneric(myBounds);
+
+        if (myHist->nums->n != numBins) {
+            printf("ERROR: myHist->nums->n is wrong size (%ld)\n", myHist->nums->n);
+            testStatus = false;
+        }
+
+        if (myHist->bounds->n != numBins+1) {
+            printf("ERROR: myHist->bounds->n is wrong size (%ld)\n", myHist->bounds->n);
+            testStatus = false;
+        }
+
+        for (i=0;i<numBins;i++) {
+            if (myHist->nums->data.F32[i] != 0.0) {
+                printf("ERROR: myHist->nums->data.F32[%d] not initialized to 0.\n", i);
+                testStatus = false;
+            }
+            myHist->nums->data.F32[i] = 0.0;
+        }
+
+        if (myHist->minNum != 0) {
+            printf("ERROR: myHist->minNum is %d\n", myHist->minNum);
+            testStatus = false;
+        }
+
+        if (myHist->maxNum != 0) {
+            printf("myHist->maxNum is %d\n", myHist->maxNum);
+            testStatus = false;
+        }
+
+        if (myHist->uniform != false) {
+            printf("ERROR: myHist->uniform is %d\n", myHist->uniform);
+            testStatus = false;
+        }
+
+        for (i=0;i<numBins;i++) {
+            printf("Bin number %d bounds: (%6.3f - %6.3f)\n", i,
+                   myHist->bounds->data.F32[i],
+                   myHist->bounds->data.F32[i+1]);
+        }
+        psMemCheckCorruption(1);
+        psFree(myHist);
+        psMemCheckCorruption(1);
+        psFree(myBounds);
+
+        printFooter(stdout,
+                    "psStats functions",
+                    "Allocate the psHistogram structure.",
+                    testStatus);
+    }
+    /*************************************************************************/
+    /*  Deallocate data structures                                           */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "Deallocate the psHistogram structure.");
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    psMemCheckCorruption(1);
+
+    printFooter(stdout,
+                "psStats functions",
+                "Deallocate the psHistogram structure.",
+                testStatus);
+
+    return (!testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psHist02.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psHist02.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psHist02.c	(revision 22158)
@@ -0,0 +1,191 @@
+/*****************************************************************************
+   This routine must ensure that the psHistogram structure is correctly
+   populated by the procedure psGetArrayHistogram().
+ 
+*****************************************************************************/
+#include <stdio.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+#include "psMemory.h"
+#define MISC_FLOAT_NUMBER 345.0
+#define MISC_INT_NUMBER 345
+#define LOWER 20.0
+#define UPPER 30.0
+#define NUM_DATA 10000
+
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    psHistogram * myHist = NULL;
+    psHistogram *myHist2 = NULL;
+    psVector *myData = NULL;
+    psVector *myMask = NULL;
+    psS32 testStatus = true;
+    psS32 memLeaks = 0;
+    psS32 nb = 0;
+    psS32 numBins = 0;
+    psS32 i = 0;
+    psS32 currentId = 0;
+
+    currentId = psMemGetId();
+
+    /*********************************************************************/
+    /*  Allocate and initialize data structures                          */
+    /*********************************************************************/
+    myData = psVectorAlloc( NUM_DATA, PS_TYPE_F32 );
+    myData->n = myData->nalloc;
+    for ( i = 0;i < NUM_DATA;i++ ) {
+        myData->data.F32[ i ] = LOWER + ( ( UPPER - LOWER ) / ( float ) NUM_DATA ) * ( float ) i;
+    }
+
+    myMask = psVectorAlloc( NUM_DATA, PS_TYPE_U8 );
+    myMask->n = myMask->nalloc;
+    for ( i = 0;i < NUM_DATA;i++ ) {
+        if ( i >= ( NUM_DATA / 2 ) ) {
+            myMask->data.U8[ i ] = 1;
+        } else {
+            myMask->data.U8[ i ] = 0;
+        }
+    }
+
+    for ( nb = 0;nb < 4;nb++ ) {
+        if ( nb == 0 )
+            numBins = 1;
+        if ( nb == 1 )
+            numBins = 2;
+        if ( nb == 2 )
+            numBins = 10;
+        if ( nb == 3 )
+            numBins = 20;
+
+        /*********************************************************************/
+        /*  Allocate and Perform Histogram, no mask                          */
+        /*********************************************************************/
+        printPositiveTestHeader( stdout,
+                                 "psStats functions",
+                                 "Allocate and Perform Histogram, no mask" );
+
+        myHist = psHistogramAlloc( LOWER, UPPER, numBins );
+        myHist = psVectorHistogram( myHist, myData, NULL, NULL, 0 );
+
+        for ( i = 0;i < numBins;i++ ) {
+            printf( "Bin number %d bounds: (%.2f - %.2f) data (%f)\n", i,
+                    myHist->bounds->data.F32[ i ],
+                    myHist->bounds->data.F32[ i + 1 ],
+                    myHist->nums->data.F32[ i ] );
+        }
+        psMemCheckCorruption( 1 );
+        psFree( myHist );
+        psMemCheckCorruption( 1 );
+
+        printFooter( stdout,
+                     "psStats functions",
+                     "Allocate and Perform Histogram, no mask",
+                     testStatus );
+
+        /*********************************************************************/
+        /*  Allocate and Perform Histogram with mask                         */
+        /*********************************************************************/
+        printPositiveTestHeader( stdout,
+                                 "psStats functions",
+                                 "Allocate and Perform Histogram with mask" );
+
+        myHist = psHistogramAlloc( LOWER, UPPER, numBins );
+        myHist = psVectorHistogram( myHist, myData, NULL, myMask, 1 );
+
+        for ( i = 0;i < numBins;i++ ) {
+            printf( "Bin number %d bounds: (%6.3f - %6.3f) data (%f)\n", i,
+                    myHist->bounds->data.F32[ i ],
+                    myHist->bounds->data.F32[ i + 1 ],
+                    myHist->nums->data.F32[ i ] );
+        }
+        psMemCheckCorruption( 1 );
+        psFree( myHist );
+        psMemCheckCorruption( 1 );
+
+        printFooter( stdout,
+                     "psStats functions",
+                     "Allocate and Perform Histogram with mask",
+                     testStatus );
+    }
+    psFree( myMask );
+
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "Calling psVectorHistogram() with various NULL inputs." );
+
+
+
+    // ********************************************************************
+    // Verify the return value is null and program execution doesn't stop,
+    // if input parameter myHist is null.
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message.");
+    myHist2 = psVectorHistogram( NULL, myData, NULL, NULL, 0 );
+    if ( myHist2 != NULL ) {
+        printf( "ERROR: myHist2!=NULL\n" );
+        testStatus = false;
+    }
+    psFree( myData );
+
+
+    // ********************************************************************
+    // Verify the return value is the same as the input parameter myHist and
+    // program execution doesn't stop, if the input parameter myArray is
+    // null.
+
+    myHist = psHistogramAlloc( LOWER, UPPER, numBins );
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message.");
+    myHist = psVectorHistogram( myHist, NULL, NULL, NULL, 0 );
+    if ( myHist == NULL ) {
+        printf( "ERROR: myHist==NULL\n" );
+        testStatus = false;
+    }
+    psFree( myHist );
+
+
+    //    exit(0);
+    // ********************************************************************
+    // Verify the return value is the same as the input parameter myHist and
+    // program execution doesn't stop, if the input parameter myArray has no
+    // elements.
+    // NOTE: This code segment is commented out because psVectorAlloc returns
+    // NULL if called with an N element data.
+    /*
+    myData = psVectorAlloc(0, PS_TYPE_F32);
+    myData->n = myData->nalloc;
+    myHist = psHistogramAlloc(LOWER, UPPER, numBins);
+    myHist = psVectorHistogram(myHist, NULL, NULL, NULL, 0);
+    if (myHist == NULL) {
+        printf("ERROR: myHist==NULL\n");
+        testStatus = false;
+    }
+    psFree(myHist);
+    psFree(myData);
+    */
+    printFooter( stdout,
+                 "psStats functions",
+                 "Calling psVectorHistogram() with various NULL inputs.",
+                 testStatus );
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+    printPositiveTestHeader( stdout,
+                             "psStats functions",
+                             "Deallocate the psHistogram structure." );
+
+    psMemCheckCorruption( 1 );
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if ( 0 != memLeaks ) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks );
+    }
+    psMemCheckCorruption( 1 );
+
+    printFooter( stdout,
+                 "psStats functions",
+                 "Deallocate the psHistogram structure.",
+                 testStatus );
+
+    return ( !testStatus );
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psHist03.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psHist03.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psHist03.c	(revision 22158)
@@ -0,0 +1,138 @@
+/*****************************************************************************
+    This routine must ensure that the psHistogram structure is correctly
+    allocated and deallocated by the procedure psHistogramAllocGeneric() and
+    that it can be populated correctly by psVectorHistogram().
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+#include "psMemory.h"
+#define LOWER 20.0
+#define UPPER 30.0
+#define NUM_DATA 20
+
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    //
+    // We list pertinent psStats.c functions here for debugging ease.
+    //
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("p_psVectorBinDisect", 0);
+    psTraceSetLevel("psHistogramAlloc", 0);
+    psTraceSetLevel("psHistogramAllocGeneric", 0);
+    psTraceSetLevel("UpdateHistogramBins", 0);
+    psTraceSetLevel("psVectorHistogram", 0);
+    psHistogram *myHist = NULL;
+    psVector *myBounds  = NULL;
+    psVector *myData = psVectorAlloc( NUM_DATA, PS_TYPE_F32 );
+    psS32 testStatus      = true;
+    psS32 memLeaks        = 0;
+    psS32 i               = 0;
+    psS32 nb              = 0;
+    psS32 numBins         = 0;
+    psS32 currentId       = 0;
+
+    currentId       = psMemGetId();
+
+    psTraceSetLevel(".psLib", 0);
+
+    myData->n = myData->nalloc;
+    for ( i = 0;i < NUM_DATA;i++ ) {
+        myData->data.F32[ i ] = LOWER + ( ( UPPER - LOWER ) / ( float ) NUM_DATA ) * ( float ) i;
+    }
+
+    for (nb=0;nb<4;nb++) {
+        if (nb == 0)
+            numBins = 1;
+        if (nb == 1)
+            numBins = 2;
+        if (nb == 2)
+            numBins = 10;
+        if (nb == 3)
+            numBins = 20;
+        /*********************************************************************/
+        /*  Allocate and initialize data structures                          */
+        /*********************************************************************/
+        printPositiveTestHeader(stdout,
+                                "psStats functions",
+                                "Allocate the psHistogram structure.");
+        myBounds = psVectorAlloc(numBins+1, PS_TYPE_F32);
+        myBounds->n = myBounds->nalloc;
+        for (i=0;i<numBins+1;i++) {
+            myBounds->data.F32[i] = LOWER + ((UPPER - LOWER) / (float) numBins) *
+                                    (float) i;
+        }
+        myHist = psHistogramAllocGeneric(myBounds);
+
+        if (myHist->nums->n != numBins) {
+            printf("ERROR: myHist->nums->n is wrong size (%ld)\n", myHist->nums->n);
+            testStatus = false;
+        }
+
+        if (myHist->bounds->n != numBins+1) {
+            printf("ERROR: myHist->bounds->n is wrong size (%ld)\n", myHist->bounds->n);
+            testStatus = false;
+        }
+
+        for (i=0;i<numBins;i++) {
+            if (myHist->nums->data.F32[i] != 0.0) {
+                printf("ERROR: myHist->nums->data.F32[%d] not initialized to 0.\n", i);
+                testStatus = false;
+            }
+            myHist->nums->data.F32[i] = 0.0;
+        }
+
+        if (myHist->minNum != 0) {
+            printf("ERROR: myHist->minNum is %d\n", myHist->minNum);
+            testStatus = false;
+        }
+
+        if (myHist->maxNum != 0) {
+            printf("myHist->maxNum is %d\n", myHist->maxNum);
+            testStatus = false;
+        }
+
+        if (myHist->uniform != false) {
+            printf("ERROR: myHist->uniform is %d\n", myHist->uniform);
+            testStatus = false;
+        }
+
+        myHist = psVectorHistogram( myHist, myData, NULL, NULL, 0 );
+        for (i=0;i<numBins;i++) {
+            printf("Bin number %d bounds: (%6.3f - %6.3f): data: (%f)\n", i,
+                   myHist->bounds->data.F32[i],
+                   myHist->bounds->data.F32[i+1],
+                   myHist->nums->data.F32[i]);
+        }
+
+        psMemCheckCorruption(1);
+        psFree(myHist);
+        psMemCheckCorruption(1);
+        psFree(myBounds);
+
+        printFooter(stdout,
+                    "psStats functions",
+                    "Allocate the psHistogram structure.",
+                    testStatus);
+    }
+    /*************************************************************************/
+    /*  Deallocate data structures                                           */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "Deallocate the psHistogram structure.");
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,NULL,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    psMemCheckCorruption(1);
+
+    printFooter(stdout,
+                "psStats functions",
+                "Deallocate the psHistogram structure.",
+                testStatus);
+
+    return (!testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMathUtils.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMathUtils.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMathUtils.c	(revision 22158)
@@ -0,0 +1,214 @@
+/*****************************************************************************
+This routine contains code which tests the general math utility functions.
+ *****************************************************************************/
+#include <stdio.h>
+#include <math.h>
+#include "pslib.h"
+#include "psTest.h"
+#define NUM_DATA 10
+#define VERBOSE 0
+#define TS00_X_F32  0x00000001
+#define TS00_X_F64  0x00000002
+#define TS00_X_NULL  0x00000004
+#define TS00_DOMAIN_F32  0x00000008
+#define TS00_DOMAIN_F64  0x00000010
+#define TS00_DOMAIN_NULL 0x00000020
+#define TS00_RANGE_F32  0x00000040
+#define TS00_RANGE_F64  0x00000080
+#define TS00_RANGE_NULL  0x00000200
+
+psS32 genericInterpolateTest(
+    psU32 flags,
+    psS32 order,
+    psS32 numData,
+    psF64 xValue,
+    psBool expectedRC)
+{
+    psS32 currentId = psMemGetId();
+    psS32 testStatus = true;
+    psS32 memLeaks = 0;
+    psScalar *x = NULL;
+    psVector *domain = NULL;
+    psVector *range = NULL;
+    psScalar *out = NULL;
+
+    printPositiveTestHeader(stdout, "psMathUtils functions", "1D Interpolation routines");
+
+    if (expectedRC == false) {
+        printf("This test should generate an error message, and return NULL.\n");
+    }
+
+    if (flags & TS00_X_NULL) {
+        printf(" using a NULL x scalar\n");
+    }
+
+    if (flags & TS00_X_F32) {
+        printf(" using a psF32 x scalar\n");
+        x = psScalarAlloc((psF32) xValue, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_X_F64) {
+        printf(" using a psF64 x scalar\n");
+        x = psScalarAlloc((psF64) xValue, PS_TYPE_F64);
+    }
+
+    if (flags & TS00_DOMAIN_NULL) {
+        printf(" using a NULL domain vector\n");
+    }
+
+    if (flags & TS00_DOMAIN_F32) {
+        printf(" using a psF32 domain vector\n");
+        domain = psVectorAlloc(numData, PS_TYPE_F32);
+        for (psS32 i=0;i<numData;i++) {
+            domain->data.F32[i] = (psF32) i;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original domain data %d: (%.1f)\n", i, domain->data.F32[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_DOMAIN_F64) {
+        printf(" using a psF64 domain vector\n");
+        domain = psVectorAlloc(numData, PS_TYPE_F64);
+        for (psS64 i=0;i<numData;i++) {
+            domain->data.F64[i] = (psF64) i;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original domain data %d: (%.1f)\n", i, domain->data.F64[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_RANGE_NULL) {
+        printf(" using a NULL range vector\n");
+    }
+
+    if (flags & TS00_RANGE_F32) {
+        printf(" using a psF32 range vector\n");
+        range = psVectorAlloc(numData, PS_TYPE_F32);
+        for (psS32 i=0;i<numData;i++) {
+            range->data.F32[i] = (psF32) 2*i;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original range data %d: (%.1f)\n", i, range->data.F32[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_RANGE_F64) {
+        printf(" using a psF64 range vector\n");
+        range = psVectorAlloc(numData, PS_TYPE_F64);
+        for (psS64 i=0;i<numData;i++) {
+            range->data.F64[i] = (psF64) 2*i;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original range data %d: (%.1f)\n", i, range->data.F64[i]);
+            }
+        }
+    }
+
+
+    out = p_psVectorInterpolate(NULL, domain, range, order, x);
+
+    if (out == NULL) {
+        if (expectedRC == true) {
+            printf("TEST ERROR: the p_psVectorInterpolate function returned NULL.\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            printf("TEST ERROR: the p_psVectorInterpolate function returned non-NULL.\n");
+            testStatus = false;
+        }
+
+        if (flags & TS00_X_F32) {
+            printf("The interpolated value was %.2f: should be %.2f\n", out->data.F32, 2.0 * x->data.F32);
+        } else if (flags & TS00_X_F64) {
+            printf("The interpolated value was %.2f: should be %.2f\n", out->data.F64, 2.0 * x->data.F64);
+        }
+
+        /*
+        if (0) {
+                if (flags & TS00_F_F32) {
+                    expectData = f->data.F32[i];
+                } else if (flags & TS00_F_F64) {
+                    expectData = (psF32) f->data.F64[i];
+                } else if (flags & TS00_F_S32) {
+                    expectData = (psF32) f->data.S32[i];
+                }
+         
+                    if (flags & TS00_X_F32) {
+                        xData = x->data.F32[i];
+                    } else if (flags & TS00_X_F64) {
+                        xData = (psF32) x->data.F64[i];
+                    } else if (flags & TS00_X_S32) {
+                        xData = (psF32) x->data.S32[i];
+                    } else if (flags & TS00_X_NULL) {
+                        if (flags & TS00_POLY_ORD) {
+                            xData = (psF32) i;
+                        } else if (flags & TS00_POLY_CHEB) {
+                            xData = ((2.0 / ((psF32) (numData - 1))) * ((psF32) i)) - 1.0;
+                        }
+                    }
+         
+                    psF32 actualData = psPolynomial1DEval(myPoly, xData);
+         
+                    if (fabs(actualData-expectData) > fabs(ERROR_TOLERANCE * expectData)) {
+                        printf("TEST ERROR: Fitted data %d: (%.1f %.1f), expected was (%.1f)\n",
+                               i, xData, actualData, expectData);
+                        testStatus = false;
+                     } else {
+                        if (VERBOSE) {
+                            printf("GOOD: Fitted data %d: (%.1f %.1f), expected was (%.1f)\n",
+                                     i, xData, actualData, expectData);
+                        }
+                    }
+                }
+        }
+        */
+    }
+
+    psMemCheckCorruption(1);
+    psFree(x);
+    psFree(out);
+    psFree(domain);
+    psFree(range);
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    printFooter(stdout, "psMinimize functions", "1D Interpolation routines", testStatus);
+
+    return (testStatus);
+}
+
+/*****************************************************************************
+We test a variety of 
+ *****************************************************************************/
+psS32 main()
+{
+    psBool testStatus = true;
+    psLogSetFormat("HLNM");
+    psTraceSetLevel(".", 0);
+    printPositiveTestHeader(stdout, "psMathUtils functions: 1D Interpolation routines", "");
+
+    //
+    // F32 tests:
+    //
+    // All Vectors non-NULL
+
+    testStatus &= genericInterpolateTest(TS00_X_F32 | TS00_DOMAIN_F32 | TS00_RANGE_F32, 5, NUM_DATA, 5.5, true);
+
+    printFooter(stdout, "psMinimize functions: 1D Polynomial Fitting Functions", "", testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix01.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix01.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix01.c	(revision 22158)
@@ -0,0 +1,132 @@
+/** @file  tst_psMatrix_01.c
+*
+*  @brief Test driver for psMatrix transpose function
+*
+*  This test driver contains the following tests for psMatrix test point 1:
+*     A)  Create input and output images
+*     B)  Transpose input image into output image
+*     C)  Transpose input image into auto allocated NULL output image
+*     D)  Free images and check for leaks
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2005-08-24 01:24:24 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+#define TOLERANCE 0.000001
+
+#define CHECK_MATRIX(IMAGE)                                                                                  \
+for(psU32 i=0; i<IMAGE->numRows; i++) {                                                                  \
+    for(psU32 j=0; j<IMAGE->numCols; j++) {                                                              \
+        if(IMAGE->type.type == PS_TYPE_F64) {                                                            \
+            if(fabs(IMAGE->data.F64[i][j]-truthMatrix[i][j]) > TOLERANCE) {                              \
+                printf("Matrix values at element %d, %d don't agree %lf vs %lf\n", i, j,                 \
+                       IMAGE->data.F64[i][j], truthMatrix[i][j]);                                        \
+            }                                                                                            \
+        } else if(IMAGE->type.type == PS_TYPE_F32){                                                      \
+            if(fabs(IMAGE->data.F32[i][j]-truthMatrix[i][j]) > TOLERANCE) {                              \
+                printf("Matrix values at element %d, %d don't agree %f vs %lf\n", i, j,                  \
+                       IMAGE->data.F32[i][j], truthMatrix[i][j]);                                        \
+            }                                                                                            \
+        }                                                                                                \
+    }                                                                                                    \
+}
+
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    psImage * tempImage = NULL;
+
+    double truthMatrix[3][3] = {{1, 4, 7},
+                                {2, 5, 8},
+                                {3, 6, 9}};
+
+    // Test A - Create input and output images
+    printPositiveTestHeader(stdout, "psMatrix", "Create input and output images");
+    psImage *inImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    psImage *outImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    inImage->data.F64[0][0] = 1;
+    inImage->data.F64[0][1] = 2;
+    inImage->data.F64[0][2] = 3;
+    inImage->data.F64[1][0] = 4;
+    inImage->data.F64[1][1] = 5;
+    inImage->data.F64[1][2] = 6;
+    inImage->data.F64[2][0] = 7;
+    inImage->data.F64[2][1] = 8;
+    inImage->data.F64[2][2] = 9;
+    psImage *inImageF32 = (psImage*)psImageAlloc(3, 3, PS_TYPE_F32);
+    psImage *outImageF32 = (psImage*)psImageAlloc(3, 3, PS_TYPE_F32);
+    inImageF32->data.F32[0][0] = 1;
+    inImageF32->data.F32[0][1] = 2;
+    inImageF32->data.F32[0][2] = 3;
+    inImageF32->data.F32[1][0] = 4;
+    inImageF32->data.F32[1][1] = 5;
+    inImageF32->data.F32[1][2] = 6;
+    inImageF32->data.F32[2][0] = 7;
+    inImageF32->data.F32[2][1] = 8;
+    inImageF32->data.F32[2][2] = 9;
+    printFooter(stdout, "psMatrix", "Create input and output images", true);
+
+
+    // Test B - Transpose input image into output image
+    printPositiveTestHeader(stdout, "psMatrix", "Transpose input image into output image");
+    tempImage = outImage;
+    outImage = psMatrixTranspose(outImage, inImage);
+    CHECK_MATRIX(outImage);
+    if (outImage->type.dimen != PS_DIMEN_IMAGE) {
+        printf( "Error: Resulting image is not PS_DIMEN_IMAGE\n");
+    } else if (outImage != tempImage) {
+        printf("Error: Return pointer not equal to output argument pointer\n");
+    }
+
+    tempImage = outImageF32;
+    outImageF32 = psMatrixTranspose(outImageF32, inImageF32);
+    CHECK_MATRIX(outImageF32);
+    if (outImageF32->type.dimen != PS_DIMEN_IMAGE) {
+        printf("Error: Resulting image is not PS_DIMEN_IMAGE\n");
+    } else if (outImageF32 != tempImage) {
+        printf("Error: Return pointer not equal to output argument pointer\n");
+    }
+    printFooter(stdout, "psMatrix", "Transpose input image into output image", true);
+
+
+    // Test C - Transpose input image into auto allocated NULL output image
+    printPositiveTestHeader(stdout, "psMatrix", "Transpose input image into auto allocated NULL output image");
+    psImage *outImageNull = NULL;
+    outImageNull = psMatrixTranspose(outImageNull, inImage);
+    CHECK_MATRIX(outImageNull);
+
+    psImage *outImageNullF32 = NULL;
+    outImageNullF32 = psMatrixTranspose(outImageNullF32, inImageF32);
+    CHECK_MATRIX(outImageNullF32);
+    printFooter(stdout, "psMatrix", "Transpose input image into auto allocated NULL output image", true);
+
+
+    // Test D - Free images and check for leaks
+    printPositiveTestHeader(stdout, "psMatrix", "Free images and check for leaks");
+    psFree(inImage);
+    psFree(outImage);
+    psFree(outImageNull);
+    psFree(inImageF32);
+    psFree(outImageF32);
+    psFree(outImageNullF32);
+    psS32 nLeaks = psMemCheckLeaks(0, NULL, stdout, false);
+    if (nLeaks != 0) {
+        printf("ERROR: Found %d memory leaks\n", nLeaks);
+    }
+    psS32 nBad = psMemCheckCorruption(0);
+    if (nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMatrix" , "Free images and check for leaks", true);
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix02.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix02.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix02.c	(revision 22158)
@@ -0,0 +1,101 @@
+/** @file  tst_psMatrix_02.c
+ *
+ *  @brief Test driver for negative tests for psMatrix transpose function
+ *
+ *  This test driver contains the following tests for psMatrix test point 2:
+ *     A)  Input pointer same as output pointer
+ *     B)  Null input psImage
+ *     C)  Incorrect type for input pointer
+ *     D)  Incorrect type for output pointer
+ *     E)  Matrix not square for output pointer
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2005-08-24 01:24:24 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+psS32 main(psS32 argc,
+           char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psImage *nullImage = NULL;
+    psImage *inImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    psImage *outImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    psImage *badImage1 = (psImage*)psImageAlloc(3, 3, PS_TYPE_C32);
+    psImage *badImage2 = (psImage*)psImageAlloc(3, 2, PS_TYPE_F64);
+
+    // Test A - Input pointer same as output pointer
+    printPositiveTestHeader(stdout,"psMatrix", "Input pointer same as output pointer");
+    psMemIncrRefCounter(inImage);
+    if (psMatrixTranspose(inImage, inImage) != NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "inImage = outImage didn't results in NULL return");
+        return 1;
+    }
+    if (psMemGetRefCounter(inImage) != 1) {
+        psError(PS_ERR_UNKNOWN, true,
+                "the output image was not freed on an error.");
+        return 2;
+    }
+    printFooter(stdout, "psMatrix", "Input pointer same as output pointer", true);
+
+    // Test B - Null input psImage
+    printPositiveTestHeader(stdout,"psMatrix", "Null input psImage");
+    psMemIncrRefCounter(outImage);
+    if (psMatrixTranspose(outImage, nullImage) != NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "inImage = outImage didn't results in NULL return");
+        return 3;
+    }
+    if (psMemGetRefCounter(outImage) != 1) {
+        psError(PS_ERR_UNKNOWN, true,
+                "the output image was not freed on an error.");
+        return 4;
+    }
+    printFooter(stdout, "psMatrix", "Null input psImage", true);
+
+    // Test C - Incorrect type for input pointer
+    printPositiveTestHeader(stdout,"psMatrix", "Incorrect type for input pointer");
+    psMemIncrRefCounter(outImage);
+    if (psMatrixTranspose(outImage, badImage1) != NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "inImage = outImage didn't results in NULL return");
+        return 5;
+    }
+    if (psMemGetRefCounter(outImage) != 1) {
+        psError(PS_ERR_UNKNOWN, true,
+                "the output image was not freed on an error.");
+        return 6;
+    }
+    printFooter(stdout, "psMatrix", "Incorrect type for input pointer", true);
+
+    // Test D - Incorrect type for output pointer
+    printPositiveTestHeader(stdout,"psMatrix", "Incorrect type for output pointer");
+    badImage1 = psMatrixTranspose(badImage1, inImage);
+    if (badImage1 == NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "inImage = outImage didn't results in NULL return");
+        return 7;
+    }
+    // check that the type was changed.
+    if (badImage1->type.type != PS_TYPE_F64) {
+        psError(PS_ERR_UNKNOWN, true,
+                "the output image was not freed on an error.");
+        return 8;
+    }
+    printFooter(stdout, "psMatrix", "Incorrect type for output pointer", true);
+
+    // Test E - Matrix not square for output pointer
+    printPositiveTestHeader(stdout,"psMatrix", "Matrix not square for output pointer");
+    psMatrixTranspose(badImage2, inImage);
+    printFooter(stdout, "psMatrix", "Matrix not square for output pointer", true);
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix03.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix03.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix03.c	(revision 22158)
@@ -0,0 +1,235 @@
+/** @file  tst_psMatrix_03.c
+ *
+ *  @brief Test driver for psMatrix LU functions
+ *
+ *  This test driver contains the following tests for psMatrix test point 3:
+ *     A)  Create input and output images and vectors
+ *     B)  Calculate LU matrix
+ *     C)  Determine solution to matrix equation
+ *     D)  Free input and output images and vectors
+ *     E)  Attempt to use null image input argument
+ *     F)  Attempt to use null input vector argument
+ *     G)  ttempt to use null LU image argument
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2005-08-24 01:24:24 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+#define TOLERANCE 0.000001
+
+#define CHECK_MATRIX(IMAGE)                                                                                  \
+for(psU32 i=0; i<IMAGE->numRows; i++) {                                                                  \
+    for(psU32 j=0; j<IMAGE->numCols; j++) {                                                              \
+        if(IMAGE->type.type == PS_TYPE_F64) {                                                            \
+            if(fabs(IMAGE->data.F64[i][j]-truthMatrix[i][j]) > TOLERANCE) {                              \
+                printf("Matrix values at element %d, %d don't agree %lf vs %lf\n", i, j,                 \
+                       IMAGE->data.F64[i][j], truthMatrix[i][j]);                                        \
+            }                                                                                            \
+        } else if(IMAGE->type.type == PS_TYPE_F32){                                                      \
+            if(fabs(IMAGE->data.F32[i][j]-truthMatrix[i][j]) > TOLERANCE) {                              \
+                printf("Matrix values at element %d, %d don't agree %f vs %lf\n", i, j,                  \
+                       IMAGE->data.F32[i][j], truthMatrix[i][j]);                                        \
+            }                                                                                            \
+        }                                                                                                \
+    }                                                                                                    \
+}
+
+#define CHECK_VECTOR(VECTOR)                                                                                 \
+for(psU32 i=0; i<VECTOR->n; i++) {                                                                       \
+    if(VECTOR->type.type == PS_TYPE_F64) {                                                               \
+        if(fabs(VECTOR->data.F64[i]-truthVector[i]) > TOLERANCE) {                                       \
+            printf("Vector values at element %d don't agree %lf vs %lf\n", i,                            \
+                   VECTOR->data.F64[i], truthVector[i]);                                                 \
+        }                                                                                                \
+    } else if(VECTOR->type.type == PS_TYPE_F32){                                                         \
+        if(fabs(VECTOR->data.F32[i]-truthVector[i]) > TOLERANCE) {                                       \
+            printf("Vector values at element %d don't agree %f vs %lf\n", i,                             \
+                   VECTOR->data.F32[i], truthVector[i]);                                                 \
+        }                                                                                                \
+    }                                                                                                    \
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psImage *luImage = NULL;
+    psImage *inImage = NULL;
+    psImage *tempImage = NULL;
+    psVector *tempVector = NULL;
+    psVector *perm = NULL;
+    psVector *outVector = NULL;
+    psVector *inVector = NULL;
+    psImage *luImage32 = NULL;
+    psImage *inImage32 = NULL;
+    psImage *tempImage32 = NULL;
+    psVector *tempVector32 = NULL;
+    psVector *perm32 = NULL;
+    psVector *outVector32 = NULL;
+    psVector *inVector32 = NULL;
+
+    double truthVector[3] = {
+                                4.000000,
+                                -2.000000,
+                                3.000000
+                            };
+
+    double truthMatrix[3][3] = {{4.000000,  5.000000,  6.000000},
+                                {0.750000, -2.750000, -6.500000},
+                                {0.500000, -0.545455, -0.545455}};
+
+
+    // Test A - Create input and output images and vectors
+    printPositiveTestHeader(stdout, "psMatrix", "Create input and output images and vectors");
+    luImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    perm = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+    outVector = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+    inVector = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+    inImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    inImage->data.F64[0][0] =  2;
+    inImage->data.F64[0][1] =  4;
+    inImage->data.F64[0][2] =  6;
+    inImage->data.F64[1][0] =  4;
+    inImage->data.F64[1][1] =  5;
+    inImage->data.F64[1][2] =  6;
+    inImage->data.F64[2][0] =  3;
+    inImage->data.F64[2][1] =  1;
+    inImage->data.F64[2][2] = -2;
+    inVector->data.F64[0] = 18.0;
+    inVector->data.F64[1] = 24.0;
+    inVector->data.F64[2] =  4.0;
+    inVector->n = 3;
+    luImage32 = (psImage*)psImageAlloc(3, 3, PS_TYPE_F32);
+    outVector32 = (psVector*)psVectorAlloc(3, PS_TYPE_F32);
+    inVector32 = (psVector*)psVectorAlloc(3, PS_TYPE_F32);
+    inImage32 = (psImage*)psImageAlloc(3, 3, PS_TYPE_F32);
+    inImage32->data.F32[0][0] =  2;
+    inImage32->data.F32[0][1] =  4;
+    inImage32->data.F32[0][2] =  6;
+    inImage32->data.F32[1][0] =  4;
+    inImage32->data.F32[1][1] =  5;
+    inImage32->data.F32[1][2] =  6;
+    inImage32->data.F32[2][0] =  3;
+    inImage32->data.F32[2][1] =  1;
+    inImage32->data.F32[2][2] = -2;
+    inVector32->data.F32[0] = 18.0;
+    inVector32->data.F32[1] = 24.0;
+    inVector32->data.F32[2] =  4.0;
+    inVector32->n = 3;
+    printFooter(stdout, "psMatrix", "Create input and output images and vectors", true);
+
+
+    // Test B - Calculate LU matrix
+    printPositiveTestHeader(stdout, "psMatrix", "Calculate LU matrix");
+    tempImage = luImage;
+    luImage = psMatrixLUD(luImage, &perm, inImage);
+    CHECK_MATRIX(luImage);
+    if(luImage->type.dimen != PS_DIMEN_IMAGE) {
+        printf("Error: Resulting image is not PS_DIMEN_IMAGE\n");
+    } else if(luImage != tempImage) {
+        printf("Error: Return pointer not equal to output argument pointer\n");
+    }
+
+    tempImage32 = luImage32;
+    luImage32 = psMatrixLUD(luImage32, &perm32, inImage32);
+    CHECK_MATRIX(luImage32);
+    if(luImage32->type.dimen != PS_DIMEN_IMAGE) {
+        printf("Error: Resulting image is not PS_DIMEN_IMAGE\n");
+    } else if(luImage32 != tempImage32) {
+        printf("Error: Return pointer not equal to output argument pointer\n");
+    }
+    printFooter(stdout, "psMatrix", "Calculate LU matrix", true);
+
+    // Test C - Determine solution to matrix equation
+    printPositiveTestHeader(stdout, "psMatrix", "Determine solution to matrix equation");
+    tempVector = outVector;
+    outVector = psMatrixLUSolve(outVector, luImage, inVector, perm);
+    CHECK_VECTOR(outVector);
+    if(outVector->type.dimen != PS_DIMEN_VECTOR) {
+        printf("Error: Resulting image is not PS_DIMEN_VECTOR\n");
+    } else if(outVector != tempVector) {
+        printf("Error: Return pointer not equal to output argument pointer\n");
+    }
+
+    tempVector32 = outVector32;
+    outVector32 = psMatrixLUSolve(outVector32, luImage32, inVector32, perm32);
+    CHECK_VECTOR(outVector32);
+    if(outVector32->type.dimen != PS_DIMEN_VECTOR) {
+        printf("Error: Resulting image is not PS_DIMEN_VECTOR\n");
+    } else if(outVector32 != tempVector32) {
+        printf("Error: Return pointer not equal to output argument pointer\n");
+    }
+    printFooter(stdout, "psMatrix", "Determine solution to matrix equation", true);
+
+
+    // Test D - Free input and output images and vectors
+    printPositiveTestHeader(stdout, "psMatrix", "Free input and output images and vectors");
+    psFree(inImage);
+    psFree(luImage);
+    psFree(perm);
+    psFree(outVector);
+    psFree(inVector);
+    psFree(inImage32);
+    psFree(luImage32);
+    psFree(perm32);
+    psFree(outVector32);
+    psFree(inVector32);
+    if( psMemCheckLeaks(0, NULL, stdout, false) ) {
+        psError(PS_ERR_UNKNOWN,true,"Memory leaks detected");
+        return 10;
+    }
+    psS32 nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMatrix" ,"Free input and output images and vectors", true);
+
+
+    // Test E - Attempt to use null image input argument
+    printNegativeTestHeader(stdout,"psMatrix", "Attempt to use null image input argument",
+                            "Invalid operation: inImage or its data is NULL.", 0);
+    psImage *imageTest = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    psMatrixLUD(imageTest, NULL, NULL);
+    printFooter(stdout, "psMatrix", "Attempt to use null image input argument", true);
+
+
+    // Test F - Attempt to use null input vector argument
+    printNegativeTestHeader(stdout,"psMatrix", "Attempt to use null input vector argument",
+                            "Invalid operation: inVector or its data is NULL.", 0);
+    psVector *vectorBad = NULL;
+    psVector *vectorBadOut = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+    psVector *permBad = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+    imageTest = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    psMatrixLUSolve(vectorBadOut, imageTest, vectorBad, permBad);
+    printFooter(stdout, "psMatrix", "Attempt to use null input vector argument", true);
+
+
+    // Test G - Attempt to use null LU image argument
+    printNegativeTestHeader(stdout,"psMatrix", "Attempt to use null LU image argument",
+                            "Invalid operation: inImage or its data is NULL.", 0);
+    vectorBadOut = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+    psMatrixLUSolve(vectorBadOut, NULL, vectorBad, permBad);
+    printFooter(stdout, "psMatrix", "Attempt to use null LU image argument", true);
+
+    psFree(permBad);
+    psFree(imageTest);
+
+    if( psMemCheckLeaks(0, NULL, stdout, false) ) {
+        psError(PS_ERR_UNKNOWN,true,"Memory leaks detected");
+        return 10;
+    }
+    nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix04.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix04.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix04.c	(revision 22158)
@@ -0,0 +1,162 @@
+/** @file  tst_psMatrix_04.c
+ *
+ *  @brief Test driver for psMatrix invert function
+ *
+ *  This test driver contains the following tests for psMatrix test point 4:
+ *     A)  Create input and output images
+ *     B)  Invert matrix and calculate determinant
+ *     C)  Calculate determinant only
+ *     D)  Free input and output images
+ *     E)  Attempt to use null input image argument
+ *     F)  Attempt to use null input float argument
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2005-08-24 01:24:24 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+
+#define TOLERANCE 0.000001
+
+#define CHECK_MATRIX(IMAGE)                                                                                  \
+for(psU32 i=0; i<IMAGE->numRows; i++) {                                                                  \
+    for(psU32 j=0; j<IMAGE->numCols; j++) {                                                              \
+        if(IMAGE->type.type == PS_TYPE_F64) {                                                            \
+            if(fabs(IMAGE->data.F64[i][j]-truthMatrix[i][j]) > TOLERANCE) {                              \
+                printf("Matrix values at element %d, %d don't agree %lf vs %lf\n", i, j,                 \
+                       IMAGE->data.F64[i][j], truthMatrix[i][j]);                                        \
+            }                                                                                            \
+        } else if(IMAGE->type.type == PS_TYPE_F32){                                                      \
+            if(fabs(IMAGE->data.F32[i][j]-truthMatrix[i][j]) > TOLERANCE) {                              \
+                printf("Matrix values at element %d, %d don't agree %f vs %lf\n", i, j,                  \
+                       IMAGE->data.F32[i][j], truthMatrix[i][j]);                                        \
+            }                                                                                            \
+        }                                                                                                \
+    }                                                                                                    \
+}
+
+#define CHECK_VALUE(VALUE)                                                                                   \
+if(fabs(VALUE-truthValue) > TOLERANCE) {                                                                     \
+    printf("Values don't agree %lf vs %lf\n", VALUE, truthValue);                                            \
+}
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    float det = 0.0f;
+    float det2 = 0;
+    psImage *outImage = NULL;
+    psImage *inImage = NULL;
+    psImage *tempImage = NULL;
+    psImage *outImage32 = NULL;
+    psImage *inImage32 = NULL;
+    psImage *tempImage32 = NULL;
+
+    double truthMatrix[3][3] = {{4.0000000, -4.333333, -2.333333},
+                                {-1.000000,  1.666667,  0.666667},
+                                {-1.000000,  0.666667,  0.666667}};
+    double truthValue = 3.0;
+
+
+    // Test A - Create input and output images
+    printPositiveTestHeader(stdout, "psMatrix", "Create input and output images");
+    outImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    inImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    inImage->data.F64[0][0] =  2;
+    inImage->data.F64[0][1] =  4;
+    inImage->data.F64[0][2] =  3;
+    inImage->data.F64[1][0] =  0;
+    inImage->data.F64[1][1] =  1;
+    inImage->data.F64[1][2] = -1;
+    inImage->data.F64[2][0] =  3;
+    inImage->data.F64[2][1] =  5;
+    inImage->data.F64[2][2] =  7;
+
+    outImage32 = (psImage*)psImageAlloc(3, 3, PS_TYPE_F32);
+    inImage32 = (psImage*)psImageAlloc(3, 3, PS_TYPE_F32);
+    inImage32->data.F32[0][0] =  2;
+    inImage32->data.F32[0][1] =  4;
+    inImage32->data.F32[0][2] =  3;
+    inImage32->data.F32[1][0] =  0;
+    inImage32->data.F32[1][1] =  1;
+    inImage32->data.F32[1][2] = -1;
+    inImage32->data.F32[2][0] =  3;
+    inImage32->data.F32[2][1] =  5;
+    inImage32->data.F32[2][2] =  7;
+    printFooter(stdout, "psMatrix", "Create input and output images", true);
+
+
+    // Test B - Invert matrix and calculate determinant
+    printPositiveTestHeader(stdout, "psMatrix", "Invert matrix and calculate determinant");
+    tempImage = outImage;
+    outImage = psMatrixInvert(outImage, inImage, &det);
+    CHECK_MATRIX(outImage);
+    CHECK_VALUE(det);
+    if(outImage->type.dimen != PS_DIMEN_IMAGE) {
+        printf("Error: Resulting image is not PS_DIMEN_IMAGE\n");
+    } else if(outImage != tempImage) {
+        printf("Error: Return pointer not equal to output argument pointer\n");
+    }
+    det = 0.0f;
+    tempImage32 = outImage32;
+    outImage32 = psMatrixInvert(outImage32, inImage32, &det);
+    CHECK_MATRIX(outImage32);
+    CHECK_VALUE(det);
+    if(outImage32->type.dimen != PS_DIMEN_IMAGE) {
+        printf("Error: Resulting image is not PS_DIMEN_IMAGE\n");
+    } else if(outImage32 != tempImage32) {
+        printf("Error: Return pointer not equal to output argument pointer\n");
+    }
+    printFooter(stdout, "psMatrix", "Invert matrix and calculate determinant", true);
+
+
+    // Test C - Calculate determinant only
+    printPositiveTestHeader(stdout, "psMatrix", "Calculate determinant only");
+    det2 = psMatrixDeterminant(inImage);
+    CHECK_VALUE(det2);
+    det2 = psMatrixDeterminant(inImage32);
+    CHECK_VALUE(det2);
+    printFooter(stdout, "psMatrix", "Calculate determinant only", true);
+
+
+    // Test D - Free input and output images
+    printPositiveTestHeader(stdout, "psMatrix", "Free input and output images");
+    psFree(outImage);
+    psFree(inImage);
+    psFree(outImage32);
+    psFree(inImage32);
+    if(psMemCheckLeaks(0, NULL, stdout, false) != 0 ) {
+        psError(PS_ERR_UNKNOWN,true,"Memory leaks detected.");
+        return 10;
+    }
+    psS32 nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMatrix" ,"Free input and output images", true);
+
+
+    // Test E - Attempt to use null input image argument
+    printNegativeTestHeader(stdout,"psMatrix", "Attempt to use null input image argument",
+                            "Invalid operation: inImage or its data is NULL.", 0);
+    psImage *badOutImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    psMatrixInvert(badOutImage, NULL, &det);
+    printFooter(stdout, "psMatrix", "Attempt to use null input image argument", true);
+
+
+    // Test F - Attempt to use null input float argument
+    printNegativeTestHeader(stdout,"psMatrix", "Attempt to use null input float argument",
+                            "Invalid operation: determinant argument is NULL.", 0);
+    psImage *badInImage = (psImage*)psImageAlloc(3, 3, PS_TYPE_F64);
+    psMatrixInvert(badOutImage, badInImage, NULL);
+    printFooter(stdout, "psMatrix", "Attempt to use null input float argument", true);
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix05.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix05.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix05.c	(revision 22158)
@@ -0,0 +1,119 @@
+/** @file  tst_psMatrix_05.c
+*
+*  @brief Test driver for psMatrix multiplication function
+*
+*  This test driver contains the following tests for psMatrix test point 5:
+*     A)  Create input and output images
+*     B)  Multiply images
+*     C)  Free input and output images
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2005-08-24 01:24:24 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+#define TOLERANCE 0.000001
+
+#define CHECK_MATRIX(IMAGE)                                                                                  \
+for(psU32 i=0; i<IMAGE->numRows; i++) {                                                                  \
+    for(psU32 j=0; j<IMAGE->numCols; j++) {                                                              \
+        if(IMAGE->type.type == PS_TYPE_F64) {                                                            \
+            if(fabs(IMAGE->data.F64[i][j]-truthMatrix[i][j]) > TOLERANCE) {                              \
+                printf("Matrix values at element %d, %d don't agree %lf vs %lf\n", i, j,                 \
+                       IMAGE->data.F64[i][j], truthMatrix[i][j]);                                        \
+            }                                                                                            \
+        } else if(IMAGE->type.type == PS_TYPE_F32){                                                      \
+            if(fabs(IMAGE->data.F32[i][j]-truthMatrix[i][j]) > TOLERANCE) {                              \
+                printf("Matrix values at element %d, %d don't agree %f vs %lf\n", i, j,                  \
+                       IMAGE->data.F32[i][j], truthMatrix[i][j]);                                        \
+            }                                                                                            \
+        }                                                                                                \
+    }                                                                                                    \
+}
+
+
+psS32 main( psS32 argc,
+            char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    psImage * outImage = NULL;
+    psImage *inImage1 = NULL;
+    psImage *inImage2 = NULL;
+    psImage * outImage32 = NULL;
+    psImage *inImage132 = NULL;
+    psImage *inImage232 = NULL;
+
+    double truthMatrix[3][3] = {{  0.0, 52.0},
+                                {-14.0, 51.0}};
+
+    // Test A - Create input and output images
+    printPositiveTestHeader(stdout, "psMatrix", "Create input and output images");
+    outImage = (psImage*) psImageAlloc(2, 2, PS_TYPE_F64);
+    inImage1 = (psImage*) psImageAlloc(3, 2, PS_TYPE_F64);
+    inImage2 = (psImage*) psImageAlloc(2, 3, PS_TYPE_F64);
+    inImage1->data.F64[0][0] = 2;
+    inImage1->data.F64[0][1] = 3;
+    inImage1->data.F64[0][2] = 4;
+    inImage1->data.F64[1][0] = -1;
+    inImage1->data.F64[1][1] = 2;
+    inImage1->data.F64[1][2] = 5;
+    inImage2->data.F64[0][0] = 4;
+    inImage2->data.F64[0][1] = 1;
+    inImage2->data.F64[1][0] = 0;
+    inImage2->data.F64[1][1] = 6;
+    inImage2->data.F64[2][0] = -2;
+    inImage2->data.F64[2][1] = 8;
+    outImage32 = (psImage*)psImageAlloc(2, 2, PS_TYPE_F32);
+    inImage132 = (psImage*)psImageAlloc(3, 2, PS_TYPE_F32);
+    inImage232 = (psImage*)psImageAlloc(2, 3, PS_TYPE_F32);
+    inImage132->data.F32[0][0] = 2;
+    inImage132->data.F32[0][1] = 3;
+    inImage132->data.F32[0][2] = 4;
+    inImage132->data.F32[1][0] = -1;
+    inImage132->data.F32[1][1] = 2;
+    inImage132->data.F32[1][2] = 5;
+    inImage232->data.F32[0][0] = 4;
+    inImage232->data.F32[0][1] = 1;
+    inImage232->data.F32[1][0] = 0;
+    inImage232->data.F32[1][1] = 6;
+    inImage232->data.F32[2][0] = -2;
+    inImage232->data.F32[2][1] = 8;
+    printFooter( stdout, "psMatrix", "Create input and output images", true );
+
+
+    // Test B - Multiply images
+    printPositiveTestHeader(stdout, "psMatrix", "Multiply images");
+    psMatrixMultiply(outImage, inImage1, inImage2);
+    CHECK_MATRIX(outImage);
+    psMatrixMultiply(outImage32, inImage132, inImage232);
+    CHECK_MATRIX(outImage32);
+    printFooter(stdout, "psMatrix", "Multiply images", true);
+
+
+    // Test C - Free input and output images
+    printPositiveTestHeader( stdout, "psMatrix", "Free input and output images" );
+    psFree(outImage);
+    psFree(inImage1);
+    psFree(inImage2);
+    psFree(outImage32);
+    psFree(inImage132);
+    psFree(inImage232);
+    psS32 nLeaks = psMemCheckLeaks( 0, NULL, stdout, false );
+    if ( nLeaks != 0 ) {
+        printf( "ERROR: Found %d memory leaks\n", nLeaks );
+    }
+    psS32 nBad = psMemCheckCorruption( 0 );
+    if ( nBad ) {
+        printf( "ERROR: Found %d bad memory blocks\n", nBad );
+    }
+    printFooter( stdout, "psMatrix" , "Free input and output images", true );
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix06.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix06.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix06.c	(revision 22158)
@@ -0,0 +1,125 @@
+/** @file  tst_psMatrix_06.c
+*
+*  @brief Test driver for psMatrix Eigenvectors function
+*
+*  This test driver contains the following tests for psMatrix test point 6:
+*     A)  Create input and output images
+*     B)  Calculate Eigenvectors
+*     C)  Free input and output images
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2005-08-24 01:24:24 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+#define TOLERANCE 0.000001
+
+#define CHECK_MATRIX(IMAGE)                                                                                  \
+for(psU32 i=0; i<IMAGE->numRows; i++) {                                                                  \
+    for(psU32 j=0; j<IMAGE->numCols; j++) {                                                              \
+        if(IMAGE->type.type == PS_TYPE_F64) {                                                            \
+            if(fabs(IMAGE->data.F64[i][j]-truthMatrix[i][j]) > TOLERANCE) {                              \
+                printf("Matrix values at element %d, %d don't agree %lf vs %lf\n", i, j,                 \
+                       IMAGE->data.F64[i][j], truthMatrix[i][j]);                                        \
+            }                                                                                            \
+        } else if(IMAGE->type.type == PS_TYPE_F32){                                                      \
+            if(fabs(IMAGE->data.F32[i][j]-truthMatrix[i][j]) > TOLERANCE) {                              \
+                printf("Matrix values at element %d, %d don't agree %f vs %lf\n", i, j,                  \
+                       IMAGE->data.F32[i][j], truthMatrix[i][j]);                                        \
+            }                                                                                            \
+        }                                                                                                \
+    }                                                                                                    \
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psImage * outImage = NULL;
+    psImage *inImage = NULL;
+    psImage * outImage32 = NULL;
+    psImage *inImage32 = NULL;
+
+    double truthMatrix[4][4] = {{0.792608,  0.582076, -0.179186, -0.029193},
+                                {0.451923, -0.370502,  0.741918,  0.328712},
+                                {0.322416, -0.509579, -0.100228, -0.791411},
+                                {0.252161, -0.514048, -0.638283,  0.514553}};
+
+
+    // Test A - Create input and output images
+    printPositiveTestHeader( stdout, "psMatrix", "Create input and output images" );
+    outImage = (psImage*) psImageAlloc(4, 4, PS_TYPE_F64);
+    inImage = (psImage*)  psImageAlloc(4, 4, PS_TYPE_F64);
+
+    inImage->data.F64[0][0] = 1./1.;
+    inImage->data.F64[0][1] = 1./2.;
+    inImage->data.F64[0][2] = 1./3.;
+    inImage->data.F64[0][3] = 1./4.;
+    inImage->data.F64[1][0] = 1./2.;
+    inImage->data.F64[1][1] = 1./3.;
+    inImage->data.F64[1][2] = 1./4.;
+    inImage->data.F64[1][3] = 1./5.;
+    inImage->data.F64[2][0] = 1./3.;
+    inImage->data.F64[2][1] = 1./4.;
+    inImage->data.F64[2][2] = 1./5.;
+    inImage->data.F64[2][3] = 1./6.;
+    inImage->data.F64[3][0] = 1./4.;
+    inImage->data.F64[3][1] = 1./5.;
+    inImage->data.F64[3][2] = 1./6.;
+    inImage->data.F64[3][3] = 1./7.;
+
+    outImage32 = (psImage*) psImageAlloc(4, 4, PS_TYPE_F32);
+    inImage32 = (psImage*)  psImageAlloc(4, 4, PS_TYPE_F32);
+    inImage32->data.F32[0][0] = 1./1.;
+    inImage32->data.F32[0][1] = 1./2.;
+    inImage32->data.F32[0][2] = 1./3.;
+    inImage32->data.F32[0][3] = 1./4.;
+    inImage32->data.F32[1][0] = 1./2.;
+    inImage32->data.F32[1][1] = 1./3.;
+    inImage32->data.F32[1][2] = 1./4.;
+    inImage32->data.F32[1][3] = 1./5.;
+    inImage32->data.F32[2][0] = 1./3.;
+    inImage32->data.F32[2][1] = 1./4.;
+    inImage32->data.F32[2][2] = 1./5.;
+    inImage32->data.F32[2][3] = 1./6.;
+    inImage32->data.F32[3][0] = 1./4.;
+    inImage32->data.F32[3][1] = 1./5.;
+    inImage32->data.F32[3][2] = 1./6.;
+    inImage32->data.F32[3][3] = 1./7.;
+    printFooter(stdout, "psMatrix", "Create input and output images", true);
+
+
+    // Test B - Calculate Eigenvectors
+    printPositiveTestHeader(stdout, "psMatrix", "Calculate Eigenvectors");
+    psMatrixEigenvectors(outImage, inImage);
+    CHECK_MATRIX(outImage);
+    psMatrixEigenvectors(outImage32, inImage32);
+    CHECK_MATRIX(outImage32);
+    printFooter(stdout, "psMatrix", "Calculate Eigenvectors", true);
+
+
+    // Test C - Free input and output images
+    printPositiveTestHeader(stdout, "psMatrix", "Free input and output images");
+    psFree(outImage);
+    psFree(inImage);
+    psFree(outImage32);
+    psFree(inImage32);
+    psS32 nLeaks = psMemCheckLeaks(0, NULL, stdout, false);
+    if (nLeaks != 0) {
+        printf("ERROR: Found %d memory leaks\n", nLeaks);
+    }
+    psS32 nBad = psMemCheckCorruption(0);
+    if (nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMatrix" , "Free input and output images", true);
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix07.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix07.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrix07.c	(revision 22158)
@@ -0,0 +1,314 @@
+/** @file  tst_psMatrix_07.c
+ *
+ *  @brief Test driver for psMatrix vector conversion functions
+ *
+ *  This test driver contains the following tests for psMatrix test point 7:
+ *     A)  Create input and output images and vectors
+ *     B)  Convert matrix to PS_DIMEN_VECTOR vector
+ *     C)  Attempt to use null image input argument
+ *     D)  Convert matrix to PS_DIMEN_TRANSV vector
+ *     E)  Improper image size
+ *     F)  Convert PS_DIMEN_VECTOR vector to matrix
+ *     G)  Attempt to use null input vector argument
+ *     H)  Convert PS_DIMEN_TRANSV vector to matrix
+ *     I)  Free input and output images and vectors
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2005-08-24 01:24:24 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+
+#define TOLERANCE 0.000001
+
+#define CHECK_MATRIX(IMAGE,TRUTH)                                                                        \
+for(psU32 i=0; i<IMAGE->numRows; i++) {                                                                  \
+    for(psU32 j=0; j<IMAGE->numCols; j++) {                                                              \
+        if(IMAGE->type.type == PS_TYPE_F64) {                                                            \
+            if(fabs(IMAGE->data.F64[i][j]-TRUTH[i][j]) > TOLERANCE) {                                    \
+                printf("Matrix values at element %d, %d don't agree %lf vs %lf\n", i, j,                 \
+                       IMAGE->data.F64[i][j], TRUTH[i][j]);                                              \
+            }                                                                                            \
+        } else if(IMAGE->type.type == PS_TYPE_F32){                                                      \
+            if(fabs(IMAGE->data.F32[i][j]-TRUTH[i][j]) > TOLERANCE) {                                    \
+                printf("Matrix values at element %d, %d don't agree %f vs %f\n", i, j,                  \
+                       IMAGE->data.F32[i][j], TRUTH[i][j]);                                              \
+            }                                                                                            \
+        }                                                                                                \
+    }                                                                                                    \
+}
+
+#define CHECK_VECTOR(VECTOR)                                                                                 \
+for(psU32 i=0; i<VECTOR->n; i++) {                                                                       \
+    if(VECTOR->type.type == PS_TYPE_F64) {                                                               \
+        if(fabs(VECTOR->data.F64[i]-truthVector[i]) > TOLERANCE) {                                       \
+            printf("Vector values at element %d don't agree %lf vs %lf\n", i,                            \
+                   VECTOR->data.F64[i], truthVector[i]);                                                 \
+        }                                                                                                \
+    } else if(VECTOR->type.type == PS_TYPE_F32){                                                         \
+        if(fabs(VECTOR->data.F32[i]-truthVector_32[i]) > TOLERANCE) {                                       \
+            printf("Vector values at element %d don't agree %f vs %lf\n", i,                             \
+                   VECTOR->data.F32[i], truthVector[i]);                                                 \
+        }                                                                                                \
+    }                                                                                                    \
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psVector *v1 = NULL;
+    psVector *v1_32 = NULL;
+    psVector *tempVector = NULL;
+    psVector *tempVector_32 = NULL;
+    psImage *tempImage = NULL;
+    psImage *tempImage_32 = NULL;
+    psImage *m1 = NULL;
+    psImage *m1_32 = NULL;
+    psVector *v2 = NULL;
+    psVector *v2_32 = NULL;
+    psVector *v3 = NULL;
+    psVector *v3_32 = NULL;
+    psImage *m2 = NULL;
+    psImage *m2_32 = NULL;
+    psImage *m3 = NULL;
+    psImage *m3_32 = NULL;
+    psImage *m4 = NULL;
+    psImage *m4_32 = NULL;
+    psImage *badImage = NULL;
+    psImage *badImage_32 = NULL;
+
+    psF64 truthVector[3] = {0.0, 1.0, 2.0};
+    psF32 truthVector_32[3] = {0.0, 1.0, 2.0};
+    psF64 truthMatrix[3][1] = {{0.0}, {1.0}, {2.0}};
+    psF32 truthMatrix_32[3][1] = {{0.0}, {1.0}, {2.0}};
+
+    // Test A - Create input and output images
+    printPositiveTestHeader(stdout, "psMatrix", "Create input and output images and vectors");
+    v1 = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+    v1_32 = (psVector*)psVectorAlloc(3, PS_TYPE_F32);
+    m1 = (psImage*)psImageAlloc(1, 3, PS_TYPE_F64);
+    m1_32 = (psImage*)psImageAlloc(1,3,PS_TYPE_F32);
+    v2 = (psVector*)psVectorAlloc(3, PS_TYPE_F64);
+    v2_32 = (psVector*)psVectorAlloc(3,PS_TYPE_F32);
+    m2 = (psImage*)psImageAlloc(1, 3, PS_TYPE_F64);
+    m2_32 = (psImage*)psImageAlloc(1,3,PS_TYPE_F32);
+    m3 = (psImage*)psImageAlloc(3, 1, PS_TYPE_F64);
+    m3_32 = (psImage*)psImageAlloc(3,1,PS_TYPE_F32);
+    m4 = (psImage*)psImageAlloc(3, 1, PS_TYPE_F64);
+    m4_32 = (psImage*)psImageAlloc(3,1,PS_TYPE_F32);
+    badImage = (psImage*)psImageAlloc(2, 2, PS_TYPE_F64);
+    badImage_32 = (psImage*)psImageAlloc(2,2,PS_TYPE_F32);
+    m1->data.F64[0][0] = 0.0;
+    m1->data.F64[1][0] = 1.0;
+    m1->data.F64[2][0] = 2.0;
+    m1_32->data.F32[0][0] = 0.0;
+    m1_32->data.F32[1][0] = 1.0;
+    m1_32->data.F32[2][0] = 2.0;
+    v2->data.F64[0] = 0.0;
+    v2->data.F64[1] = 1.0;
+    v2->data.F64[2] = 2.0;
+    v2->n = 3;
+    v2_32->data.F32[0] = 0.0;
+    v2_32->data.F32[1] = 1.0;
+    v2_32->data.F32[2] = 2.0;
+    v2_32->n = 3;
+    m4->data.F64[0][0] = 0.0;
+    m4->data.F64[0][1] = 1.0;
+    m4->data.F64[0][2] = 2.0;
+    m4_32->data.F32[0][0] = 0.0;
+    m4_32->data.F32[0][1] = 1.0;
+    m4_32->data.F32[0][2] = 2.0;
+    printFooter(stdout, "psMatrix", "Create input and output images and vectors", true);
+
+    // Test B - Convert matrix to PS_DIMEN_VECTOR vector
+    printPositiveTestHeader(stdout, "psMatrix", "Convert matrix to PS_DIMEN_VECTOR vector");
+    tempVector = v1;
+    v1 = psMatrixToVector(v1, m1);
+    CHECK_VECTOR(v1);
+    if(v1->type.dimen != PS_DIMEN_VECTOR) {
+        psError(PS_ERR_UNKNOWN,true,"Resulting image is not PS_DIMEN_VECTOR");
+        return 1;
+    } else if(v1 != tempVector) {
+        psError(PS_ERR_UNKNOWN,true,"Return pointer not equal to output argument pointer");
+        return 2;
+    }
+    tempVector_32 = v1_32;
+    v1_32 = psMatrixToVector(v1_32, m1_32);
+    CHECK_VECTOR(v1_32);
+    if(v1_32->type.dimen != PS_DIMEN_VECTOR) {
+        psError(PS_ERR_UNKNOWN,true,"Resulting image is not PS_DIMEN_VECTOR");
+        return 1;
+    } else if(v1_32 != tempVector_32) {
+        psError(PS_ERR_UNKNOWN,true,"Return pointer not equal to output argument pointer");
+        return 2;
+    }
+    printFooter(stdout, "psMatrix", "Convert matrix to PS_DIMEN_VECTOR vector", true);
+
+
+    // Test C - Attempt to use null image input argument
+    printNegativeTestHeader(stdout,"psMatrix", "Attempt to use null image input argument",
+                            "Invalid operation: inImage or its data is NULL.", 0);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error.");
+    v1 = psMatrixToVector(v1, NULL);
+    if(v1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with NULL input");
+        return 3;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error.");
+    v1_32 = psMatrixToVector(v1_32, NULL);
+    if(v1_32 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with NULL input");
+        return 3;
+    }
+    printFooter(stdout, "psMatrix", "Attempt to use null image input argument", true);
+
+
+    // Test D - Convert matrix to PS_DIMEN_TRANSV vector
+    printPositiveTestHeader(stdout, "psMatrix", "Convert matrix to PS_DIMEN_TRANSV vector");
+    v3 = psVectorAlloc(3, PS_TYPE_F64);
+    tempVector = v3;
+    v3->type.dimen = PS_DIMEN_TRANSV;
+    psMatrixToVector(v3, m4);
+    CHECK_VECTOR(v3);
+    if(v3->type.dimen != PS_DIMEN_TRANSV) {
+        psError(PS_ERR_UNKNOWN,true,"Resulting image is not PS_DIMEN_TRANSV");
+        return 4;
+    } else if(v3 != tempVector) {
+        psError(PS_ERR_UNKNOWN,true,"Return pointer not equal to output argument pointer");
+        return 5;
+    }
+    v3_32 = psVectorAlloc(3, PS_TYPE_F32);
+    tempVector_32 = v3_32;
+    v3_32->type.dimen = PS_DIMEN_TRANSV;
+    psMatrixToVector(v3_32, m4_32);
+    CHECK_VECTOR(v3_32);
+    if(v3_32->type.dimen != PS_DIMEN_TRANSV) {
+        psError(PS_ERR_UNKNOWN,true,"Resulting image is not PS_DIMEN_TRANSV");
+        return 6;
+    } else if(v3_32 != tempVector_32) {
+        psError(PS_ERR_UNKNOWN,true,"Return pointer not equal to output argument pointer");
+        return 7;
+    }
+    printFooter(stdout, "psMatrix", "Convert matrix to PS_DIMEN_TRANSV vector", true);
+
+
+    // Test E - Improper image size
+    printNegativeTestHeader(stdout,"psMatrix", "Improper image size",
+                            "Image does not have dim with 1 col or 1 row: (2 x 2).", 0);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if(psMatrixToVector(v1, badImage) != NULL ) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with improper sizes");
+        return 8;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if(psMatrixToVector(v1_32, badImage_32) != NULL ) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with improper sizes");
+        return 9;
+    }
+    printFooter(stdout, "psMatrix", "Improper image size", true);
+
+
+    // Test F - Convert PS_DIMEN_VECTOR vector to matrix
+    printPositiveTestHeader(stdout, "psMatrix", "Convert PS_DIMEN_VECTOR vector to matrix");
+    tempImage = m2;
+    m2 = psVectorToMatrix(m2, v2);
+    CHECK_MATRIX(m2,truthMatrix);
+    if(m2->type.dimen != PS_DIMEN_IMAGE) {
+        psError(PS_ERR_UNKNOWN,true,"Resulting image is not PS_DIMEN_IMAGE");
+        return 10;
+    } else if(m2 != tempImage) {
+        psError(PS_ERR_UNKNOWN,true,"Return pointer not equal to output argument pointer");
+        return 11;
+    }
+    tempImage_32 = m2_32;
+    m2_32 = psVectorToMatrix(m2_32, v2_32);
+    CHECK_MATRIX(m2_32,truthMatrix_32);
+    if(m2_32->type.dimen != PS_DIMEN_IMAGE) {
+        psError(PS_ERR_UNKNOWN,true,"Resulting image is not PS_DIMEN_IMAGE");
+        return 10;
+    } else if(m2_32 != tempImage_32) {
+        psError(PS_ERR_UNKNOWN,true,"Return pointer not equal to output argument pointer");
+        return 11;
+    }
+    printFooter(stdout, "psMatrix", "Convert PS_DIMEN_VECTOR vector to matrix", true);
+
+
+    // Test G - Attempt to use null input vector argument
+    printNegativeTestHeader(stdout,"psMatrix", "Attempt to use null input vector argument",
+                            "Invalid operation: inVector or its data is NULL.", 0);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    if(psVectorToMatrix(m2, NULL) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return output image");
+        return 12;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    if(psVectorToMatrix(m2_32, NULL) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return output image");
+        return 13;
+    }
+    printFooter(stdout, "psMatrix", "Attempt to use null input vector argument", true);
+
+
+    // Test H - Convert PS_DIMEN_TRANSV vector to matrix
+    printPositiveTestHeader(stdout, "psMatrix", "Convert PS_DIMEN_TRANSV vector to matrix");
+    v2->type.dimen = PS_DIMEN_TRANSV;
+    tempImage = m3;
+    psVectorToMatrix(m3, v2);
+    CHECK_MATRIX(m3, truthMatrix);
+    if(m3->type.dimen != PS_DIMEN_IMAGE) {
+        psError(PS_ERR_UNKNOWN,true,"Resulting image is not PS_DIMEN_IMAGE");
+        return 14;
+    } else if(m3 != tempImage) {
+        psError(PS_ERR_UNKNOWN,true,"Return pointer not equal to output argument pointer");
+        return 15;
+    }
+    v2_32->type.dimen = PS_DIMEN_TRANSV;
+    tempImage_32 = m3_32;
+    psVectorToMatrix(m3_32, v2_32);
+    CHECK_MATRIX(m3_32, truthMatrix_32);
+    if(m3_32->type.dimen != PS_DIMEN_IMAGE) {
+        psError(PS_ERR_UNKNOWN,true,"Resulting image is not PS_DIMEN_IMAGE");
+        return 16;
+    } else if(m3_32 != tempImage_32) {
+        psError(PS_ERR_UNKNOWN,true,"Return pointer not equal to output argument pointer");
+        return 17;
+    }
+    printFooter(stdout, "psMatrix", "Convert PS_DIMEN_TRANSV vector to matrix", true);
+
+
+    // Test I - Free input and output images
+    printPositiveTestHeader(stdout, "psMatrix", "Free input and output images and vectors");
+    psFree(m1);
+    psFree(v1);
+    psFree(v2);
+    psFree(v3);
+    psFree(m3);
+    psFree(m4);
+    psFree(m1_32);
+    psFree(v1_32);
+    psFree(v2_32);
+    psFree(v3_32);
+    psFree(m3_32);
+    psFree(m4_32);
+    psFree(badImage);
+    psFree(badImage_32);
+    if( psMemCheckLeaks(0, NULL, stdout, false) != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Memory leaks detected.");
+        return 10;
+    }
+    psS32 nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMatrix" ,"Free input and output images and vectors", true);
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrixVectorArithmetic01.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrixVectorArithmetic01.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrixVectorArithmetic01.c	(revision 22158)
@@ -0,0 +1,206 @@
+/** @file  tst_psMatrixVectorArithmetic01.c
+ *
+ *  @brief Test driver for psMatrixVector arithmetic functions
+ *
+ *  This test driver tests combinations of matrix, vector, and scalar binary operations including:
+ *     Matrix-matrix with +,-,*,/ with S32, F32, F64, C32
+ *     Matrix-vector with +,-,*,/ with S32, F32, F64, C32
+ *     Matrix-scalar with +,-,*,/ with S32, F32, F64, C32
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2005-08-24 01:24:24 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+#define PRINT_SCALAR(SCALAR,TYPE)                                                                            \
+if(PS_IS_PSELEMTYPE_COMPLEX(SCALAR->type.type)) {                                                        \
+    printf("%f+%fi ", creal(SCALAR->data.TYPE), cimag(SCALAR->data.TYPE));                               \
+} else if(PS_IS_PSELEMTYPE_INT(SCALAR->type.type)) {                                                     \
+    printf("%d ", (psS32)SCALAR->data.TYPE);                                                               \
+} else {                                                                                                 \
+    printf("%f ", (double)SCALAR->data.TYPE);                                                            \
+}                                                                                                        \
+printf("\n\n");
+
+#define PRINT_VECTOR(VECTOR,TYPE)                                                                            \
+for(psS32 i=0; i<VECTOR->n; i++) {                                                                         \
+    if(PS_IS_PSELEMTYPE_COMPLEX(VECTOR->type.type)) {                                                    \
+        printf("%f+%fi ", creal(VECTOR->data.TYPE[i]), cimag(VECTOR->data.TYPE[i]));                     \
+    } else if(PS_IS_PSELEMTYPE_INT(VECTOR->type.type)) {                                                 \
+        printf("%d ", (psS32)VECTOR->data.TYPE[i]);                                                        \
+    } else {                                                                                             \
+        printf("%f ", (double)VECTOR->data.TYPE[i]);                                                     \
+    }                                                                                                    \
+}                                                                                                        \
+printf("\n\n");
+
+
+#define PRINT_MATRIX(IMAGE,TYPE)                                                                             \
+for(psS32 i=IMAGE->numRows-1; i>-1; i--) {                                                                 \
+    for(psS32 j=0; j<IMAGE->numCols; j++) {                                                                \
+        if(PS_IS_PSELEMTYPE_COMPLEX(IMAGE->type.type)) {                                                 \
+            printf("%f+%fi ", creal(IMAGE->data.TYPE[i][j]), cimag(IMAGE->data.TYPE[i][j]));             \
+        } else if(PS_IS_PSELEMTYPE_INT(IMAGE->type.type)) {                                              \
+            printf("%d ", (psS32)IMAGE->data.TYPE[i][j]);                                                  \
+        } else {                                                                                         \
+            printf("%f ", (double)IMAGE->data.TYPE[i][j]);                                               \
+        }                                                                                                \
+    }                                                                                                    \
+    printf("\n");                                                                                        \
+}                                                                                                        \
+printf("\n");
+
+
+#define CREATE_AND_SET_VECTOR(NAME,TYPE,VALUE,SIZE)                                                          \
+psVector *NAME = (psVector*)psVectorAlloc(SIZE, PS_TYPE_##TYPE);                                         \
+for(psS32 i=0; i<SIZE; i++) {                                                                              \
+    NAME->data.TYPE[i] = VALUE;                                                                          \
+}                                                                                                        \
+NAME->n = SIZE;
+
+
+#define CREATE_AND_SET_IMAGE(NAME,TYPE,VALUE,NROWS,NCOLS)                                                    \
+psImage *NAME = (psImage*)psImageAlloc(NCOLS,NROWS,PS_TYPE_##TYPE);                                      \
+for(psS32 i=0; i<NAME->numRows; i++) {                                                                     \
+    for(psS32 j=0; j<NAME->numCols; j++) {                                                                 \
+        NAME->data.TYPE[i][j] = VALUE;                                                                   \
+    }                                                                                                    \
+}
+
+
+#define CHECK_MEMORY                                                                                     \
+if(psMemCheckLeaks(0, NULL, stdout, false) != 0 ) {                                                             \
+    psError(PS_ERR_UNKNOWN,true,"Memory leaks detected.");                                                \
+    return 10;                                                                                            \
+}                                                                                                        \
+psS32 nBad = psMemCheckCorruption(0);                                                                    \
+if(nBad) {                                                                                               \
+    printf("ERROR: Found %d bad memory blocks\n", nBad);                                                 \
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+
+    // Test matrix-matrix binary operations
+    #define testBinaryOpMM(OP,TYPE,VALUE1,VALUE2,NROWS,NCOLS)                                                \
+    {                                                                                                        \
+        printPositiveTestHeader(stdout, "psMatrixVectorArithmetic", "Test matrix-matrix psBinaryOp");        \
+        printf("Operation: %s\n", #OP);                                                                      \
+        CREATE_AND_SET_IMAGE(inImage,TYPE,VALUE1,NROWS,NCOLS);                                               \
+        CREATE_AND_SET_IMAGE(outImage,TYPE,VALUE2,NROWS,NCOLS);                                              \
+        printf("Input:\n");                                                                                  \
+        PRINT_MATRIX(inImage,TYPE);                                                                          \
+        PRINT_MATRIX(outImage,TYPE);                                                                         \
+        outImage = (psImage*)psBinaryOp(outImage, inImage, #OP, outImage);                                   \
+        printf("Output:\n");                                                                                 \
+        PRINT_MATRIX(outImage,TYPE);                                                                         \
+        psFree(inImage);                                                                                     \
+        psFree(outImage);                                                                                    \
+        CHECK_MEMORY;                                                                                        \
+        printFooter(stdout, "psMatrixVectorArithmetic", "Test matrix-matrix psBinaryOp", true);              \
+    }
+
+    testBinaryOpMM(+,S32,10,10,3,2);
+    testBinaryOpMM(+,F32,10.0,10.0,3,2);
+    testBinaryOpMM(+,F64,10.0,10.0,3,2);
+    testBinaryOpMM(+,C32,10.0+10.0i,10.0+10.0i,3,2);
+    testBinaryOpMM(-,S32,20,10,3,2);
+    testBinaryOpMM(-,F32,20.0,10.0,3,2);
+    testBinaryOpMM(-,F64,20.0,10.0,3,2);
+    testBinaryOpMM(*,C32,20.0+20.0i,10.0+10.0i,3,2);
+    testBinaryOpMM(*,S32,20,10,3,2);
+    testBinaryOpMM(*,F32,20.0,10.0,3,2);
+    testBinaryOpMM(*,F64,20.0,10.0,3,2);
+    testBinaryOpMM(*,C32,20.0+20.0i,10.0+10.0i,3,2);
+    testBinaryOpMM(/,C32,20.0+20.0i,10.0+10.0i,3,2);
+    testBinaryOpMM(/,S32,20,10,3,2);
+    testBinaryOpMM(/,F32,20.0,10.0,3,2);
+    testBinaryOpMM(/,F64,20.0,10.0,3,2);
+    testBinaryOpMM(/,C32,20.0+20.0i,10.0+10.0i,3,2);
+
+    // Test Matrix-Vector binary operations
+    #define testBinaryOpMV(OP,TYPE,VALUE1,VALUE2,NROWS,NCOLS)                                                \
+    {                                                                                                        \
+        printPositiveTestHeader(stdout, "psMatrixVectorArithmetic", "Test matrix-vector psBinaryOp");        \
+        printf("Operation: %s\n", #OP);                                                                      \
+        CREATE_AND_SET_IMAGE(outImage,TYPE,VALUE1,NROWS,NCOLS);                                              \
+        CREATE_AND_SET_VECTOR(inVector,TYPE,VALUE2,NROWS);                                                   \
+        printf("Input:\n");                                                                                  \
+        PRINT_MATRIX(outImage,TYPE);                                                                         \
+        PRINT_VECTOR(inVector,TYPE);                                                                         \
+        outImage = (psImage*)psBinaryOp(outImage, outImage, #OP, inVector);                                  \
+        printf("Output:\n");                                                                                 \
+        PRINT_MATRIX(outImage,TYPE);                                                                         \
+        psFree(inVector);                                                                                    \
+        psFree(outImage);                                                                                    \
+        CHECK_MEMORY;                                                                                        \
+        printFooter(stdout, "psMatrixVectorArithmetic", "Test matrix-vector psBinaryOp", true);              \
+    }
+
+    testBinaryOpMV(+,S32,10,5,3,2);
+    testBinaryOpMV(+,F32,10.0,5.0,3,2);
+    testBinaryOpMV(+,F64,10.0,5.0,3,2);
+    testBinaryOpMV(+,C32,10.0+10.0i,5.0+5.0i,3,2);
+    testBinaryOpMV(-,S32,20,5,3,2);
+    testBinaryOpMV(-,F32,20.0,5.0,3,2);
+    testBinaryOpMV(-,F64,20.0,5.0,3,2);
+    testBinaryOpMV(*,C32,20.0+20.0i,5.0+5.0i,3,2);
+    testBinaryOpMV(*,S32,20,5,3,2);
+    testBinaryOpMV(*,F32,20.0,5.0,3,2);
+    testBinaryOpMV(*,F64,20.0,5.0,3,2);
+    testBinaryOpMV(*,C32,20.0+20.0i,5.0+5.0i,3,2);
+    testBinaryOpMV(/,C32,20.0+20.0i,5.0+5.0i,3,2);
+    testBinaryOpMV(/,S32,20,5,3,2);
+    testBinaryOpMV(/,F32,20.0,5.0,3,2);
+    testBinaryOpMV(/,F64,20.0,5.0,3,2);
+    testBinaryOpMV(/,C32,20.0+20.0i,5.0+5.0i,3,2);
+
+    // Test Matrix-Scalar binary operations
+    #define testBinaryOpMS(OP,TYPE,VALUE1,VALUE2,NROWS,NCOLS)                                                \
+    {                                                                                                        \
+        printPositiveTestHeader(stdout, "psMatrixVectorArithmetic", "Test matrix-scalar psBinaryOp");        \
+        printf("Operation: %s\n", #OP);                                                                      \
+        CREATE_AND_SET_IMAGE(outImage,TYPE,VALUE1,NROWS,NCOLS);                                              \
+        psScalar *inScalar = (psScalar*)psScalarAlloc(VALUE2,PS_TYPE_##TYPE);                                \
+        printf("Input:\n");                                                                                  \
+        PRINT_MATRIX(outImage,TYPE);                                                                         \
+        PRINT_SCALAR(inScalar,TYPE);                                                                         \
+        outImage = (psImage*)psBinaryOp(outImage, outImage, #OP, psScalarCopy(inScalar));                    \
+        printf("Output:\n");                                                                                 \
+        PRINT_MATRIX(outImage,TYPE);                                                                         \
+        psFree(inScalar);                                                                                    \
+        psFree(outImage);                                                                                    \
+        CHECK_MEMORY;                                                                                        \
+        printFooter(stdout, "psMatrixVectorArithmetic", "Test matrix-scalar psBinaryOp", true);              \
+    }
+
+    testBinaryOpMS(+,S32,10,5,3,2);
+    testBinaryOpMS(+,F32,10.0,5.0,3,2);
+    testBinaryOpMS(+,F64,10.0,5.0,3,2);
+    testBinaryOpMS(+,C32,10.0+10.0i,5.0+5.0i,3,2);
+    testBinaryOpMS(-,S32,20,5,3,2);
+    testBinaryOpMS(-,F32,20.0,5.0,3,2);
+    testBinaryOpMS(-,F64,20.0,5.0,3,2);
+    testBinaryOpMS(*,C32,20.0+20.0i,5.0+5.0i,3,2);
+    testBinaryOpMS(*,S32,20,5,3,2);
+    testBinaryOpMS(*,F32,20.0,5.0,3,2);
+    testBinaryOpMS(*,F64,20.0,5.0,3,2);
+    testBinaryOpMS(*,C32,20.0+20.0i,5.0+5.0i,3,2);
+    testBinaryOpMS(/,C32,20.0+20.0i,5.0+5.0i,3,2);
+    testBinaryOpMS(/,S32,20,5,3,2);
+    testBinaryOpMS(/,F32,20.0,5.0,3,2);
+    testBinaryOpMS(/,F64,20.0,5.0,3,2);
+    testBinaryOpMS(/,C32,20.0+20.0i,5.0+5.0i,3,2);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrixVectorArithmetic02.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrixVectorArithmetic02.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrixVectorArithmetic02.c	(revision 22158)
@@ -0,0 +1,269 @@
+
+/** @file  tst_psMatrixVectorArithmetic02.c
+ *
+ *  @brief Test driver for psMatrixVector arithmetic functions
+ *
+ *  This test driver tests combinations of matrix, vector, and scalar unary operations including:
+ *     Matrix with all math operators with S32, F32, F64, C32
+ *     Vector with all math operators with S32, F32, F64, C32
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2005-08-24 01:24:24 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+#include <math.h>
+
+
+#define CHECK_VECTOR(VECTOR,TYPE,TRUTH)                                                                      \
+for(psS32 i=0; i<VECTOR->n; i++) {                                                                             \
+    if(cabs(VECTOR->data.TYPE[i])-cabs(TRUTH) > FLT_EPSILON){                                                \
+        printf("ERROR:Truth and calculated values don't match for vector operation:\n");                     \
+        if(PS_IS_PSELEMTYPE_COMPLEX(VECTOR->type.type)) {                                                    \
+            printf("Truth: %.2f%+.2fi\n", creal(VECTOR->data.TYPE[i]), cimag(VECTOR->data.TYPE[i]));         \
+            printf("Calculated: %.2f%+.2fi\n", creal(TRUTH), cimag(TRUTH));                                  \
+        } else if(PS_IS_PSELEMTYPE_INT(VECTOR->type.type)) {                                                 \
+            printf("Truth: %d\n", (psS32)(VECTOR->data.TYPE[i]));                                              \
+            printf("Calculated: %d\n", (psS32)(TRUTH));                                                        \
+        } else {                                                                                             \
+            printf("Truth: %.2f\n", (double)(VECTOR->data.TYPE[i]));                                         \
+            printf("Calculated: %.2f\n", (double)(TRUTH));                                                   \
+        }                                                                                                    \
+    }                                                                                                        \
+}                                                                                                            \
+printf("\n");
+
+
+#define CHECK_MATRIX(IMAGE,TYPE,TRUTH)                                                                       \
+for(psS32 i=IMAGE->numRows-1; i>-1; i--) {                                                                     \
+    for(psS32 j=0; j<IMAGE->numCols; j++) {                                                                    \
+        if(cabs(IMAGE->data.TYPE[i][j])-cabs(TRUTH) > FLT_EPSILON){                                          \
+            printf("ERROR:Truth and calculated values don't match for matrix operation:\n");                 \
+            if(PS_IS_PSELEMTYPE_COMPLEX(IMAGE->type.type)) {                                                 \
+                printf("Truth: %.2f%+.2fi\n", creal(IMAGE->data.TYPE[i][j]), cimag(IMAGE->data.TYPE[i][j])); \
+                printf("Calculated: %.2f%+.2fi\n", creal(TRUTH), cimag(TRUTH));                              \
+            } else if(PS_IS_PSELEMTYPE_INT(IMAGE->type.type)) {                                              \
+                printf("Truth: %d\n", (psS32)(IMAGE->data.TYPE[i][j]));                                        \
+                printf("Calculated: %d\n", (psS32)(TRUTH));                                                    \
+            } else {                                                                                         \
+                printf("Truth: %.2f\n", (double)(IMAGE->data.TYPE[i][j]));                                   \
+                printf("Calculated: %.2f\n", (double)(TRUTH));                                               \
+            }                                                                                                \
+        }                                                                                                    \
+    }                                                                                                        \
+    printf("\n");                                                                                            \
+}                                                                                                            \
+printf("\n");
+
+
+#define CREATE_AND_SET_VECTOR(NAME,TYPE,VALUE,SIZE)                                                          \
+psVector *NAME = (psVector*)psVectorAlloc(SIZE, PS_TYPE_##TYPE);                                             \
+for(psS32 i=0; i<SIZE; i++) {                                                                                  \
+    NAME->data.TYPE[i] = VALUE;                                                                              \
+}                                                                                                            \
+NAME->n = SIZE;
+
+
+#define CREATE_AND_SET_IMAGE(NAME,TYPE,VALUE,NROWS,NCOLS)                                                    \
+psImage *NAME = (psImage*)psImageAlloc(NCOLS,NROWS,PS_TYPE_##TYPE);                                          \
+for(psS32 i=0; i<NAME->numRows; i++) {                                                                         \
+    for(psS32 j=0; j<NAME->numCols; j++) {                                                                     \
+        NAME->data.TYPE[i][j] = VALUE;                                                                       \
+    }                                                                                                        \
+}
+
+
+#define CHECK_MEMORY \
+if( psMemCheckLeaks(0, NULL, stdout, false) != 0 ) {  \
+    psError(PS_ERR_UNKNOWN, true,"Memory leaks detected."); \
+    return 50; \
+} \
+psS32 nBad = psMemCheckCorruption(0); \
+if(nBad) { \
+    psError(PS_ERR_UNKNOWN, true,"ERROR: Found %d bad memory blocks\n", nBad); \
+    return 51; \
+}
+
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    // Test matrix unary operations
+    #define testUnaryOpM(OP,TYPE,VALUE1,VALUE2,NROWS,NCOLS,TRUTH)                                            \
+    {                                                                                                        \
+        printPositiveTestHeader(stdout, "psMatrixVectorArithmetic", "Test matrix psUnaryOp");                \
+        printf("Operation: %s\n", #OP);                                                                      \
+        CREATE_AND_SET_IMAGE(inImage,TYPE,VALUE1,NROWS,NCOLS);                                               \
+        CREATE_AND_SET_IMAGE(outImage,TYPE,VALUE2,NROWS,NCOLS);                                              \
+        outImage = (psImage*)psUnaryOp(outImage, inImage, #OP);                                              \
+        CHECK_MATRIX(outImage,TYPE,TRUTH);                                                                   \
+        psFree(inImage);                                                                                     \
+        psFree(outImage);                                                                                    \
+        CHECK_MEMORY;                                                                                        \
+        printFooter(stdout, "psMatrixVectorArithmetic", "Test matrix psUnaryOp", true);                      \
+    }
+
+    testUnaryOpM( abs, S32, -10, 0, 3, 2, 10 );
+    testUnaryOpM( abs, F32, -10.0, 0.0, 3, 2, 10.0 );
+    testUnaryOpM( abs, F64, -10.0, 0.0, 3, 2, 10.0 );
+    testUnaryOpM( abs, C32, -10.0 - 10.0i, 0.0 + 0.0i, 3, 2,10+10i );
+    testUnaryOpM( exp, S32, 10, 0, 3, 2, cexp(10));
+    testUnaryOpM( exp, F32, 10.0, 0.0, 3, 2, cexp(10.0) );
+    testUnaryOpM( exp, F64, 10.0, 0.0, 3, 2, cexp(10.0) );
+    testUnaryOpM( exp, C32, 1.0 + 1.0i, 0.0 + 0.0i, 3, 2, cexp(1.0+1.0i) );
+    testUnaryOpM( ln, S32, 10, 0, 3, 2, clog(10) );
+    testUnaryOpM( ln, F32, 10.0, 0.0, 3, 2, clog(10.0) );
+    testUnaryOpM( ln, F64, 10.0, 0.0, 3, 2, clog(10.0) );
+    testUnaryOpM( ln, C32, 10.0 + 10.0i, 0.0 + 0.0i, 3, 2, clog(10.0+10.0i) );
+    testUnaryOpM( ten, S32, 3, 0, 3, 2, 1000 );
+    testUnaryOpM( ten, F32, 3.0, 0.0, 3, 2, 1000 );
+    testUnaryOpM( ten, F64, 3.0, 0.0, 3, 2, 1000 );
+    testUnaryOpM( ten, C32, 1.0 + 0.0i, 0.0 + 0.0i, 3, 2, 10.0 );
+    testUnaryOpM( log, S32, 1000, 0, 3, 2, 3 );
+    testUnaryOpM( log, F32, 1000.0, 0.0, 3, 2, 3 );
+    testUnaryOpM( log, F64, 1000.0, 0.0, 3, 2, 3 );
+    testUnaryOpM( log, C32, 1000.0 + 0.0i, 0.0 + 0.0i, 3, 2, 3 );
+    testUnaryOpM( sin, S32, M_PI_2, 0, 3, 2, 1 );
+    testUnaryOpM( sin, F32, M_PI_2, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( sin, F64, M_PI_2, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( sin, C32, M_PI_2 + 0.0i, 0.0 + 0.0i, 3, 2, 1.0 );
+    testUnaryOpM( dsin, S32, 90, 0, 3, 2 , 1);
+    testUnaryOpM( dsin, F32, 90.0, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( dsin, F64, 90.0, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( dsin, C32, 90.0 + 00.0i, 0.0 + 0.0i, 3, 2, 1.0 );
+    testUnaryOpM( cos, S32, 0, 0, 3, 2, 1 );
+    testUnaryOpM( cos, F32, 0.0, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( cos, F64, 0.0, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( cos, C32, 0.0 + 0.0i, 0.0 + 0.0i, 3, 2, 1.0 );
+    testUnaryOpM( dcos, S32, 0, 0, 3, 2, 1 );
+    testUnaryOpM( dcos, F32, 0.0, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( dcos, F64, 0.0, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( dcos, C32, 0.0 + 0.0i, 0.0 + 0.0i, 3, 2, 1.0 );
+    testUnaryOpM( tan, S32, M_PI_4, 0, 3, 2, 1);
+    testUnaryOpM( tan, F32, M_PI_4, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( tan, F64, M_PI_4, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( tan, C32, M_PI_4 + 0.0i, 0.0 + 0.0i, 3, 2, 1 );
+    testUnaryOpM( dtan, S32, 45, 0, 3, 2, 1 );
+    testUnaryOpM( dtan, F32, 45.0, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( dtan, F64, 45.0, 0.0, 3, 2, 1.0 );
+    testUnaryOpM( dtan, C32, 45.0 + 45.0i, 0.0 + 0.0i, 3, 2, 1.0 );
+    testUnaryOpM( asin, S32, 1, 0, 3, 2, M_PI_2);
+    testUnaryOpM( asin, F32, 1.0, 0.0, 3, 2, M_PI_2  );
+    testUnaryOpM( asin, F64, 1.0, 0.0, 3, 2, M_PI_2);
+    testUnaryOpM( asin, C32, 1.0 + 1.0i, 0.0 + 0.0i, 3, 2, M_PI_2);
+    testUnaryOpM( dasin, S32, 1.0, 0, 3, 2, 90 );
+    testUnaryOpM( dasin, F32, 1.0, 0.0, 3, 2, 90.0 );
+    testUnaryOpM( dasin, F64, 1.0, 0.0, 3, 2, 90.0 );
+    testUnaryOpM( dasin, C32, 1.0 + 1.0i, 0.0 + 0.0i, 3, 2, 90.0 );
+    testUnaryOpM( acos, S32, 0, 0, 3, 2, M_PI_2);
+    testUnaryOpM( acos, F32, 0.0, 0.0, 3, 2, M_PI_2 );
+    testUnaryOpM( acos, F64, 0.0, 0.0, 3, 2, M_PI_2 );
+    testUnaryOpM( acos, C32, 0.0 + 0.0i, 0.0 + 0.0i, 3, 2, M_PI_2 );
+    testUnaryOpM( dacos, S32, 0, 0, 3, 2, 90 );
+    testUnaryOpM( dacos, F32, 0.0, 0.0, 3, 2, 90.0 );
+    testUnaryOpM( dacos, F64, 0.0, 0.0, 3, 2, 90.0 );
+    testUnaryOpM( dacos, C32, 0.0 + 0.0i, 0.0 + 0.0i, 3, 2, 90.0 );
+    testUnaryOpM( atan, S32, 1, 0, 3, 2, M_PI_4);
+    testUnaryOpM( atan, F32, 1.0, 0.0, 3, 2, M_PI_4 );
+    testUnaryOpM( atan, F64, 1.0, 0.0, 3, 2, M_PI_4);
+    testUnaryOpM( atan, C32, 1.0 + 0.0i, 0.0 + 0.0i, 3, 2, M_PI_4);
+    testUnaryOpM( datan, S32, 1, 0, 3, 2, 45 );
+    testUnaryOpM( datan, F32, 1.0, 0.0, 3, 2, 45.0 );
+    testUnaryOpM( datan, F64, 1.0, 0.0, 3, 2, 45.0 );
+    testUnaryOpM( datan, C32, 1.0 + 0.0i, 0.0 + 0.0i, 3, 2, 45.0 );
+
+
+    // Test vector unary operations
+    #define testUnaryOpV(OP,TYPE,VALUE1,VALUE2,SIZE,TRUTH)                                                   \
+    {                                                                                                        \
+        printPositiveTestHeader(stdout, "psMatrixVectorArithmetic", "Test vector psUnaryOp");                \
+        printf("Operation: %s\n", #OP);                                                                      \
+        CREATE_AND_SET_VECTOR(inVector,TYPE,VALUE1,SIZE);                                                    \
+        CREATE_AND_SET_VECTOR(outVector,TYPE,VALUE2,SIZE);                                                   \
+        outVector = (psVector*)psUnaryOp(outVector, inVector, #OP);                                          \
+        CHECK_VECTOR(outVector,TYPE,TRUTH);                                                                  \
+        psFree(inVector);                                                                                    \
+        psFree(outVector);                                                                                   \
+        CHECK_MEMORY;                                                                                        \
+        printFooter(stdout, "psMatrixVectorArithmetic", "Test vector psUnaryOp", true);                      \
+    }
+
+    testUnaryOpV( abs, S32, -10, 0, 3, 10 );
+    testUnaryOpV( abs, F32, -10.0, 0.0, 3, 10.0 );
+    testUnaryOpV( abs, F64, -10.0, 0.0, 3, 10.0 );
+    testUnaryOpV( abs, C32, -10.0 - 10.0i, 0.0 + 0.0i, 3, 10+10i );
+    testUnaryOpV( exp, S32, 10, 0, 3, cexp(10));
+    testUnaryOpV( exp, F32, 10.0, 0.0, 3, cexp(10.0) );
+    testUnaryOpV( exp, F64, 10.0, 0.0, 3, cexp(10.0) );
+    testUnaryOpV( exp, C32, 1.0 + 1.0i, 0.0 + 0.0i, 3, cexp(1.0+1.0i) );
+    testUnaryOpV( ln, S32, 10, 0, 3, clog(10) );
+    testUnaryOpV( ln, F32, 10.0, 0.0, 3, clog(10.0) );
+    testUnaryOpV( ln, F64, 10.0, 0.0, 3, clog(10.0) );
+    testUnaryOpV( ln, C32, 10.0 + 10.0i, 0.0 + 0.0i, 3, clog(10.0+10.0i) );
+    testUnaryOpV( ten, S32, 3, 0, 3, 1000 );
+    testUnaryOpV( ten, F32, 3.0, 0.0, 3, 1000 );
+    testUnaryOpV( ten, F64, 3.0, 0.0, 3, 1000 );
+    testUnaryOpV( ten, C32, 1.0 + 0.0i, 0.0 + 0.0i, 3, 10.0 );
+    testUnaryOpV( log, S32, 1000, 0, 3,  3 );
+    testUnaryOpV( log, F32, 1000.0, 0.0, 3, 3 );
+    testUnaryOpV( log, F64, 1000.0, 0.0, 3, 3 );
+    testUnaryOpV( log, C32, 1000.0 + 0.0i, 0.0 + 0.0i, 3, 3 );
+    testUnaryOpV( sin, S32, M_PI_2, 0, 3, 1 );
+    testUnaryOpV( sin, F32, M_PI_2, 0.0, 3, 1.0 );
+    testUnaryOpV( sin, F64, M_PI_2, 0.0, 3, 1.0 );
+    testUnaryOpV( sin, C32, M_PI_2 + 0.0i, 0.0 + 0.0i, 3, 1.0 );
+    testUnaryOpV( dsin, S32, 90, 0, 3, 1);
+    testUnaryOpV( dsin, F32, 90.0, 0.0, 3, 1.0 );
+    testUnaryOpV( dsin, F64, 90.0, 0.0, 3, 1.0 );
+    testUnaryOpV( dsin, C32, 90.0 + 00.0i, 0.0 + 0.0i, 3, 1.0 );
+    testUnaryOpV( cos, S32, 0, 0, 3, 1 );
+    testUnaryOpV( cos, F32, 0.0, 0.0, 3, 1.0 );
+    testUnaryOpV( cos, F64, 0.0, 0.0, 3, 1.0 );
+    testUnaryOpV( cos, C32, 0.0 + 0.0i, 0.0 + 0.0i, 3, 1.0 );
+    testUnaryOpV( dcos, S32, 0, 0, 3, 1 );
+    testUnaryOpV( dcos, F32, 0.0, 0.0, 3, 1.0 );
+    testUnaryOpV( dcos, F64, 0.0, 0.0, 3, 1.0 );
+    testUnaryOpV( dcos, C32, 0.0 + 0.0i, 0.0 + 0.0i, 3, 1.0 );
+    testUnaryOpV( tan, S32, M_PI_4, 0, 3, 1);
+    testUnaryOpV( tan, F32, M_PI_4, 0.0, 3, 1.0 );
+    testUnaryOpV( tan, F64, M_PI_4, 0.0, 3, 1.0 );
+    testUnaryOpV( tan, C32, M_PI_4 + 0.0i, 0.0 + 0.0i, 3, 1 );
+    testUnaryOpV( dtan, S32, 45, 0, 3, 1 );
+    testUnaryOpV( dtan, F32, 45.0, 0.0, 3, 1.0 );
+    testUnaryOpV( dtan, F64, 45.0, 0.0, 3, 1.0 );
+    testUnaryOpV( dtan, C32, 45.0 + 45.0i, 0.0 + 0.0i, 3, 1.0 );
+    testUnaryOpV( asin, S32, 1, 0, 3, M_PI_2);
+    testUnaryOpV( asin, F32, 1.0, 0.0, 3, M_PI_2  );
+    testUnaryOpV( asin, F64, 1.0, 0.0, 3, M_PI_2);
+    testUnaryOpV( asin, C32, 1.0 + 1.0i, 0.0 + 0.0i, 3, M_PI_2);
+    testUnaryOpV( dasin, S32, 1.0, 0, 3, 90 );
+    testUnaryOpV( dasin, F32, 1.0, 0.0, 3, 90.0 );
+    testUnaryOpV( dasin, F64, 1.0, 0.0, 3, 90.0 );
+    testUnaryOpV( dasin, C32, 1.0 + 1.0i, 0.0 + 0.0i, 3, 90.0 );
+    testUnaryOpV( acos, S32, 0, 0, 3, M_PI_2);
+    testUnaryOpV( acos, F32, 0.0, 0.0, 3, M_PI_2 );
+    testUnaryOpV( acos, F64, 0.0, 0.0, 3, M_PI_2 );
+    testUnaryOpV( acos, C32, 0.0 + 0.0i, 0.0 + 0.0i, 3, M_PI_2 );
+    testUnaryOpV( dacos, S32, 0, 0, 3, 90 );
+    testUnaryOpV( dacos, F32, 0.0, 0.0, 3, 90.0 );
+    testUnaryOpV( dacos, F64, 0.0, 0.0, 3, 90.0 );
+    testUnaryOpV( dacos, C32, 0.0 + 0.0i, 0.0 + 0.0i, 3, 90.0 );
+    testUnaryOpV( atan, S32, 1, 0, 3, M_PI_4);
+    testUnaryOpV( atan, F32, 1.0, 0.0, 3, M_PI_4 );
+    testUnaryOpV( atan, F64, 1.0, 0.0, 3, M_PI_4);
+    testUnaryOpV( atan, C32, 1.0 + 0.0i, 0.0 + 0.0i, 3, M_PI_4);
+    testUnaryOpV( datan, S32, 1, 0, 3, 45 );
+    testUnaryOpV( datan, F32, 1.0, 0.0, 3, 45.0 );
+    testUnaryOpV( datan, F64, 1.0, 0.0, 3, 45.0 );
+    testUnaryOpV( datan, C32, 1.0 + 0.0i, 0.0 + 0.0i, 3, 45.0 );
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrixVectorArithmetic03.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrixVectorArithmetic03.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrixVectorArithmetic03.c	(revision 22158)
@@ -0,0 +1,315 @@
+/** @file  tst_psMatrixVectorArithmetic03.c
+ *
+ *  @brief Test driver for psMatrixVector arithmetic functions
+ *
+ *  This test driver contains negative tests for psBinaryOp and psUanryOp:
+ *     Check for NULL arguments
+ *     Inconsistent element types
+ *     Inconsistent element count
+ *     Inconsistent dimensionality
+ *     Division by zero
+ *     Attempt to use min with complex numbers
+ *     Attempt to use max with complex numbers
+ *     Invalid operation
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2005-08-24 01:24:24 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+#define PRINT_VECTOR(VECTOR,TYPE) \
+for(psS32 i=0; i<VECTOR->n; i++) { \
+    if(PS_IS_PSELEMTYPE_COMPLEX(VECTOR->type.type)) { \
+        printf("%f+%fi ", creal(VECTOR->data.TYPE[i]), cimag(VECTOR->data.TYPE[i])); \
+    } else if(PS_IS_PSELEMTYPE_INT(VECTOR->type.type)) { \
+        printf("%d ", (psS32)VECTOR->data.TYPE[i]); \
+    } else { \
+        printf("%f ", (double)VECTOR->data.TYPE[i]); \
+    } \
+} \
+printf("\n\n");
+
+#define PRINT_MATRIX(IMAGE,TYPE) \
+for(psS32 i=IMAGE->numRows-1; i>-1; i--) { \
+    for(psS32 j=0; j<IMAGE->numCols; j++) { \
+        if(PS_IS_PSELEMTYPE_COMPLEX(IMAGE->type.type)) { \
+            printf("%f+%fi ", creal(IMAGE->data.TYPE[i][j]), cimag(IMAGE->data.TYPE[i][j])); \
+        } else if(PS_IS_PSELEMTYPE_INT(IMAGE->type.type)) { \
+            printf("%d ", (psS32)IMAGE->data.TYPE[i][j]); \
+        } else { \
+            printf("%f ", (double)IMAGE->data.TYPE[i][j]); \
+        } \
+    } \
+    printf("\n"); \
+} \
+printf("\n");
+
+
+#define CREATE_AND_SET_VECTOR(NAME,TYPE,VALUE,SIZE) \
+psVector *NAME = (psVector*)psVectorAlloc(SIZE, PS_TYPE_##TYPE); \
+for(psS32 i=0; i<SIZE; i++) { \
+    NAME->data.TYPE[i] = VALUE; \
+} \
+NAME->n = SIZE;
+
+
+#define CREATE_AND_SET_IMAGE(NAME,TYPE,VALUE,NROWS,NCOLS) \
+psImage *NAME = (psImage*)psImageAlloc(NCOLS,NROWS,PS_TYPE_##TYPE); \
+for(psS32 i=0; i<NAME->numRows; i++) { \
+    for(psS32 j=0; j<NAME->numCols; j++) { \
+        NAME->data.TYPE[i][j] = VALUE; \
+    } \
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    CREATE_AND_SET_IMAGE(image1,F64,0,3,3);
+    CREATE_AND_SET_IMAGE(image2,F64,0,3,3);
+    CREATE_AND_SET_IMAGE(image3,F32,0,3,3);
+    CREATE_AND_SET_IMAGE(image4,F64,0,2,2);
+    CREATE_AND_SET_IMAGE(image5,C32,1+1i,3,3);
+    CREATE_AND_SET_VECTOR(vector1,F64,0,2);
+    CREATE_AND_SET_VECTOR(vector2,F64,0,3);
+
+    // Check for NULL output argument
+    printPositiveTestHeader(stdout,"psBinaryOp", "Check for output generated");
+    psImage* image6 = (psImage*)psBinaryOp(NULL, image1, "+", image2);
+    if (image6 == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,"psBinaryOp failed to make an image given no output to recycle.");
+        return 1;
+    }
+    printFooter(stdout,"psBinaryOp","Check for output generated",true);
+
+    // Check for NULL input argument #1
+    printPositiveTestHeader(stdout,"psBinaryOp","Check for null input arg 1");
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    image6 = (psImage*)psBinaryOp(image6, NULL, "+", image2);
+    if (image6 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,"psBinaryOp returned a result given a NULL first operand.");
+        return 2;
+    }
+    printFooter(stdout,"psBinaryOp","Check for null input arg 1",true);
+
+    // Check for NULL input argument #2
+    printPositiveTestHeader(stdout,"psBinaryOp","Check for null input arg 2");
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    image6 = (psImage*)psBinaryOp(image6, image1, "+", NULL);
+    if (image6 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,"psBinaryOp returned a result given a NULL second operand.");
+        return 3;
+    }
+    printFooter(stdout,"psBinaryOp","Check for null input arg 2",true);
+
+    // Check for NULL operand
+    printPositiveTestHeader(stdout,"psBinaryOp","Check for null operand");
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    image6 = (psImage*)psBinaryOp(image6, image1, NULL, image2);
+    if (image6 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,"psBinaryOp returned a result given a NULL operator.");
+        return 4;
+    }
+    printFooter(stdout,"psBinaryOp","Check for null operand",true);
+
+    // Check for null output
+    printPositiveTestHeader(stdout,"psUnaryOp","Check for null output");
+    image6 = (psImage*)psUnaryOp(NULL, image1, "sin");
+    if (image6 == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,"psUnaryOp failed to make an image given no output to recycle.");
+        return 5;
+    }
+    printFooter(stdout,"psUnaryOp","Check for null output",true);
+
+    // Check for NULL input arg
+    printPositiveTestHeader(stdout,"psUnaryOp","Check for null input");
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    image6 = (psImage*)psUnaryOp(image6, NULL, "sin");
+    if (image6 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,"psUnaryOp returned a result given a NULL operand.");
+        return 6;
+    }
+    printFooter(stdout,"psUnaryOp","Check for null input",true);
+
+    // Check for NULL operand
+    printPositiveTestHeader(stdout,"psUnaryOp","Check for null operator");
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    image6 = (psImage*)psUnaryOp(image6, image1, NULL);
+    if (image6 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,"psUnaryOp returned a result given a NULL operator.");
+        return 7;
+    }
+    printFooter(stdout,"psUnaryOp","Check for null operator",true);
+
+    // Inconsistent element types
+    printPositiveTestHeader(stdout,"psBinaryOp", "Inconsistent element types");
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    image6 = (psImage*)psBinaryOp(image6, image3, "+", image2);
+    if (image6 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,"psBinaryOp returned a result given operands of different types.");
+        return 8;
+    }
+    printFooter(stdout,"psBinaryOp","Inconsistent element types",true);
+
+    // Check unary op to convert to correct type
+    printPositiveTestHeader(stdout,"psUnaryOp","Check output type conversion");
+    image6 = psImageCopy(image6,image2,PS_TYPE_F64);
+    image6 = (psImage*)psUnaryOp(image6, image3, "sin");
+    if (image6 == NULL || image6->type.type != PS_TYPE_F32) {
+        psLogMsg(__func__,PS_LOG_ERROR,"psUnaryOp failed to convert the type of the output.");
+        return 9;
+    }
+    printFooter(stdout,"psUnaryOp","Check output type conversion",true);
+
+    // Inconsistent element count
+    printPositiveTestHeader(stdout,"psBinaryOp","Check for inconsistent elements");
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    image6 = (psImage*)psBinaryOp(image6, image4, "+", image2);
+    if (image6 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,"psBinaryOp returned a result given operands of different sizes.");
+        return 10;
+    }
+    printFooter(stdout,"psBinaryOp","Check for inconsistent elements",true);
+
+    // Inconsistent element in input and output
+    printPositiveTestHeader(stdout,"psUnaryOp","Check inconsistent elements in input and output");
+    image6 = psImageCopy(image6,image2,PS_TYPE_F64);
+    image6 = (psImage*)psUnaryOp(image6, image4, "sin");
+    if (image6 == NULL ||
+            image6->numCols != image6->numCols ||
+            image6->numRows != image6->numRows) {
+        psLogMsg(__func__,PS_LOG_ERROR,"psUnaryOp failed to resize the output.");
+        return 11;
+    }
+    printFooter(stdout,"psUnaryOp","Check inconsistent elements in input and output",true);
+
+    // Inconsistent size of input 1 and input 2
+    printPositiveTestHeader(stdout,"psBinaryOp","Check inconsistent size");
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    image6 = (psImage*)psBinaryOp(image6, vector1, "+", image2);
+    if (image6 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,"psBinaryOp returned a result given operands of different sizes.");
+        return 12;
+    }
+    printFooter(stdout,"psBinaryOp","Check inconsistent size",true);
+
+    // Inconsistent size of input 1 and input 2
+    printPositiveTestHeader(stdout,"psBinaryOp","Check inconsistent size");
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    vector1->type.dimen = PS_DIMEN_TRANSV;
+    image6 = (psImage*)psBinaryOp(image6, vector1, "+", image2);
+    if (image6 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,"psBinaryOp returned a result given operands of different sizes.");
+        return 13;
+    }
+    printFooter(stdout, "psBinaryOp", "Check inconsistent size", true);
+
+
+    // Inconsistent dimensionality
+    printPositiveTestHeader(stdout,"psUnaryOp","Check inconsistent dimensionality");
+    image6 = psImageCopy(image6,image2,PS_TYPE_F64);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an two error messages");
+    image6 = (psImage*)psUnaryOp(image6, vector2, "sin");
+    if (image6 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,"psUnaryOp returned result given wrong type out parameter.");
+        return 14;
+    }
+    printFooter(stdout,"psUnaryOp","Check inconsistent dimensionality",true);
+
+    // Attempt to use min with complex numbers
+    printPositiveTestHeader(stdout,"psBinaryOp","Attempt to use min with complex numbers");
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    image6 = (psImage*)psBinaryOp(image6, image5, "min", image5);
+    if(image6 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,"psUnaryOp returned result with min of complex numbers");
+        return 15;
+    }
+    printFooter(stdout, "psBinaryOp", "Attempt to use  min with complex numbers", true);
+
+
+    // Attempt to use max with complex numbers
+    printPositiveTestHeader(stdout,"psBinaryOp","Attempt to use max with complex numbers");
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    image6 = (psImage*)psBinaryOp(image6, image5, "max", image5);
+    if(image6 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,"psUnaryOp returned result with max of complex numbers");
+        return 16;
+    }
+    printFooter(stdout, "psBinaryOp", "Attempt to use max with complex numbers", true);
+
+
+    // Invalid operation
+    printPositiveTestHeader(stdout,"psBinary","Attempt to use invalid operator");
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error messgae");
+    image6 = (psImage*)psBinaryOp(image6, image1, "yarg", image2);
+    if(image6 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,"psBinaryOp returned result with invalid operator");
+        return 17;
+    }
+    printFooter(stdout,"psBinaryOp","Attempt to use invalid operator",true);
+
+    printPositiveTestHeader(stdout,"psUnaryOp","Attempt to use invalid operator");
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    image6 = (psImage*)psUnaryOp(image6, image1, "yarg");
+    if(image6 != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,"psUnaryOp returned result with invalid operator");
+        return 18;
+    }
+    printFooter(stdout, "psUnaryOp", "Attempt to use invalid operator", true);
+
+    CREATE_AND_SET_VECTOR(vector4,F64,0,3);
+    CREATE_AND_SET_VECTOR(vector5,F64,0,3);
+
+    // Input parameter with dimension of PS_DIMEN_OTHER
+    printPositiveTestHeader(stdout,"psBinaryOp","Attempt to use input with PS_DIMEN_OTHER");
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    vector4->type.dimen = PS_DIMEN_OTHER;
+    if ( psBinaryOp(NULL,vector4,"+",vector5) != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psBinaryOp should return null when input dimen PS_DIMEN_OTHER.");
+        return 19;
+    }
+    vector4->type.dimen = PS_DIMEN_VECTOR;
+    printFooter(stdout,"psBinaryOp","Attempt to use input with PS_DIMEN_OTHER",true);
+
+    // Input parameter with dimension of PS_DIMEN_OTHER
+    printPositiveTestHeader(stdout,"psUnaryOp","Attempt to use input with PS_DIMEN_OTHER");
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    vector4->type.dimen = PS_DIMEN_OTHER;
+    if ( psUnaryOp(NULL,vector4,"sin") != NULL ) {
+        psError(PS_ERR_UNKNOWN,true,"psUnaryOp should return null when input dimen PS_DIMEN_OTHER");
+        return 20;
+    }
+    vector4->type.dimen = PS_DIMEN_VECTOR;
+    printFooter(stdout,"psUnaryOp","Attempt to use input with PS_DIMEN_OTHER",true);
+
+    psFree(vector4);
+    psFree(vector5);
+    psFree(image1);
+    psFree(image2);
+    psFree(image3);
+    psFree(image4);
+    psFree(image5);
+    psFree(vector1);
+    psFree(vector2);
+
+    psS32 nLeaks = psMemCheckLeaks(0,NULL,stdout,false);
+    if(nLeaks != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Memory leaks detected");
+        return 50;
+    }
+    psS32 nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        psError(PS_ERR_UNKNOWN,true,"Memory corruption detected");
+        return 51;
+    }
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrixVectorArithmetic04.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrixVectorArithmetic04.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMatrixVectorArithmetic04.c	(revision 22158)
@@ -0,0 +1,213 @@
+/** @file  tst_psMatrixVectorArithmetic04.c
+ *
+ *  @brief Test driver for psBinary arithmetic operations with scalars
+ *
+ *  This test driver will test the following binary operation with scalar inputs
+ *        vector addition with scalar in first argument
+ *        image addition with scalar in second argument
+ *
+ * @author  Eric Van Alst, MHPCC
+ *
+ * @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ * @date  $Date: 2005-08-24 01:24:24 $
+ *
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+static psS32 testBinOpScalarFirst(void);
+static psS32 testBinOpScalarSecond(void);
+static psS32 testBinOpScalarBoth(void);
+static psS32 testUnaryOpScalar(void);
+
+testDescription testsBinary[] = {
+                                    {testBinOpScalarFirst,737,"psBinaryOp",0,false},
+                                    {testBinOpScalarSecond,737,"psBinaryOp",0,false},
+                                    {testBinOpScalarBoth,737,"psBinaryOp",0,false},
+                                    {NULL}
+                                };
+
+testDescription testUnary[] = {
+                                  {testUnaryOpScalar,737,"psUnaryOp",0,false},
+                                  {NULL}
+                              };
+
+// Create vector
+#define CREATE_AND_SET_VECTOR(NAME,TYPE,VALUE,SIZE) \
+psVector *NAME = psVectorAlloc(SIZE,PS_TYPE_##TYPE); \
+for(psS32 i=0; i<SIZE; i++) { \
+    NAME->data.TYPE[i] = VALUE; \
+} \
+NAME->n = SIZE;
+
+// Create image
+#define CREATE_AND_SET_IMAGE(NAME,TYPE,VALUE,NROWS,NCOLS) \
+psImage *NAME = psImageAlloc(NCOLS,NROWS,PS_TYPE_##TYPE); \
+for(psS32 i=0; i<NAME->numRows; i++) { \
+    for(psS32 j=0; j<NAME->numCols; j++) { \
+        NAME->data.TYPE[i][j] = VALUE; \
+    } \
+}
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+
+    runTestSuite(stderr,"psBinaryOp",testsBinary,argc,argv);
+    runTestSuite(stderr,"psUnaryOp",testUnary,argc,argv);
+
+    return 0;
+}
+
+psS32 testBinOpScalarFirst(void)
+{
+    CREATE_AND_SET_VECTOR(vector1,S8,1,5)
+    CREATE_AND_SET_VECTOR(vector2,S8,0,5)
+
+    psScalar* inScalar1 = psScalarAlloc(2,PS_TYPE_S8);
+
+    // Add vector and scalar
+    vector2 = (psVector*)psBinaryOp(vector2,inScalar1,"+",vector1);
+    // Verify the result vector
+    for(psS32 i=0; i<vector2->n; i++) {
+        if(vector2->data.S8[i] != 3 ) {
+            psError(PS_ERR_UNKNOWN,true,"Unexpected value in return vector[%d]",i);
+            return 1;
+        }
+    }
+    psFree(vector1);
+    psFree(vector2);
+
+    CREATE_AND_SET_VECTOR(vector3,S8,1,5);
+    CREATE_AND_SET_VECTOR(vector4,S8,0,3);
+
+    psScalar* inScalar2 = psScalarAlloc(2,PS_TYPE_S8);
+    vector4->type.dimen = PS_DIMEN_TRANSV;
+    vector4 = (psVector*)psBinaryOp(vector4,inScalar2,"+",vector3);
+    for(psS32 i=0; i<vector4->n; i++) {
+        if(vector4->data.S8[i] != 3 ) {
+            psError(PS_ERR_UNKNOWN,true,"Unexpected value in return vector[%d]",i);
+            return 2;
+        }
+    }
+    psFree(vector3);
+    psFree(vector4);
+
+    CREATE_AND_SET_IMAGE(image1,S8,1,5,5)
+    psImage* image2 = NULL;
+
+    psScalar* inScalar3 = psScalarAlloc(2,PS_TYPE_S8);
+
+    image2 = (psImage*)psBinaryOp(image2,inScalar3,"+",image1);
+    for(psS32 i=0; i<image2->numRows; i++) {
+        for(psS32 j=0; j<image2->numCols; j++) {
+            if(image2->data.S8[i][j] != 3 ) {
+                psError(PS_ERR_UNKNOWN,true,"Unexpected value in return image[%d][%d]",i,j);
+                return 10;
+            }
+        }
+    }
+    psFree(image1);
+    psFree(image2);
+
+    return 0;
+}
+
+psS32 testBinOpScalarSecond(void)
+{
+    CREATE_AND_SET_VECTOR(vector1,S8,1,5)
+    CREATE_AND_SET_VECTOR(vector2,S8,0,5)
+
+    psScalar* inScalar1 = psScalarAlloc(2,PS_TYPE_S8);
+
+    vector2 = (psVector*)psBinaryOp(vector2,vector1,"+",inScalar1);
+    for(psS32 i=0; i<vector2->n; i++) {
+        if(vector2->data.S8[i] != 3 ) {
+            psError(PS_ERR_UNKNOWN,true,"Unexpected value in return vector[%d]",i);
+            return 1;
+        }
+    }
+    psFree(vector1);
+    psFree(vector2);
+
+    CREATE_AND_SET_VECTOR(vector3,S8,1,5);
+    CREATE_AND_SET_VECTOR(vector4,S8,0,3);
+
+    psScalar* inScalar2 = psScalarAlloc(2,PS_TYPE_S8);
+    vector4->type.dimen = PS_DIMEN_TRANSV;
+    vector4 = (psVector*)psBinaryOp(vector4,vector3,"+",inScalar2);
+    for(psS32 i=0; i<vector4->n; i++) {
+        if(vector4->data.S8[i] != 3 ) {
+            psError(PS_ERR_UNKNOWN,true,"Unexpected value in return vector[%d]",i);
+            return 2;
+        }
+    }
+    psFree(vector3);
+    psFree(vector4);
+
+    CREATE_AND_SET_IMAGE(image1,S8,1,5,5);
+    psImage* image2 = NULL;
+
+    psScalar* inScalar3 = psScalarAlloc(2,PS_TYPE_S8);
+
+    image2 = (psImage*)psBinaryOp(image2,image1,"+",inScalar3);
+    for(psS32 i=0; i<image2->numRows; i++) {
+        for(psS32 j=0; j<image2->numCols; j++) {
+            if(image2->data.S8[i][j] != 3 ) {
+                psError(PS_ERR_UNKNOWN,true,"Unexpected value in return image[%d][%d]",i,j);
+                return 10;
+            }
+        }
+    }
+    psFree(image1);
+    psFree(image2);
+
+    return 0;
+}
+
+psS32 testBinOpScalarBoth(void)
+{
+    psScalar* inScalar1 = psScalarAlloc(1,PS_TYPE_S8);
+    psScalar* inScalar2 = psScalarAlloc(2,PS_TYPE_S8);
+    psScalar* outScalar = psScalarAlloc(4,PS_TYPE_S8);
+
+    outScalar = (psScalar*)psBinaryOp(outScalar,inScalar1,"+",inScalar2);
+    if(outScalar->data.S8 != 3) {
+        psError(PS_ERR_UNKNOWN,true,"Unexpected value in return scalar");
+        return 3;
+    }
+    psFree(outScalar);
+
+    psScalar* inScalar3 = psScalarAlloc(10,PS_TYPE_S8);
+    psScalar* inScalar4 = psScalarAlloc(20,PS_TYPE_S8);
+    psScalar* outScalar1 = NULL;
+
+    outScalar1 = (psScalar*)psBinaryOp(outScalar1,inScalar3,"+",inScalar4);
+    if(outScalar1->data.S8 != 30 ) {
+        psError(PS_ERR_UNKNOWN,true,"Unexpected value in return scalar");
+        return 4;
+    }
+    psFree(outScalar1);
+
+    return 0;
+}
+
+psS32 testUnaryOpScalar(void)
+{
+    psScalar* inScalar = psScalarAlloc(-1,PS_TYPE_F32);
+    psScalar* outScalar = NULL;
+
+    outScalar = (psScalar*)psUnaryOp(outScalar,inScalar,"abs");
+    if(outScalar->data.F32 != 1) {
+        psError(PS_ERR_UNKNOWN,true,"Unexpected value in return scalar = %d  in = %d",outScalar->data.F32,inScalar->data.F32);
+        return 5;
+    }
+    psFree(outScalar);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMinimizeLMM.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMinimizeLMM.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMinimizeLMM.c	(revision 22158)
@@ -0,0 +1,296 @@
+/*****************************************************************************
+    This routine must ensure that psMinimizeLM() works correctly.
+ 
+    XXX: This code needs a lot of additional test case work.
+    XXX: Use the tst_template.
+    XXX: Print headers and footers.
+    XXX: Why are we flushing stdout?
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+#include <math.h>
+#define NUM_ITERATIONS 100
+#define ERR_TOL 1e-6
+#define NUM_DATA_POINTS 300
+#define NUM_PARAMS 3
+#define VERBOSE 0
+float expectedParm[NUM_PARAMS];
+
+
+float function(const psVector *params,      // Paramters
+               const psVector *x            // Ordinate
+              )
+{
+    return params->data.F32[0] *
+           expf(- (PS_SQR(x->data.F32[0]) + PS_SQR(x->data.F32[1]) / 2.0 / PS_SQR(params->data.F32[1]))) +
+           params->data.F32[2];
+}
+
+void derivatives(psVector *deriv,       // Derivatives
+                 const psVector *params,      // Paramters
+                 const psVector *x            // Ordinate
+                )
+{
+    deriv->data.F32[0] = expf(- (PS_SQR(x->data.F32[0]) + PS_SQR(x->data.F32[1]) / 2.0 / PS_SQR(params->data.F32[1])));
+    deriv->data.F32[1] = params->data.F32[0] * (PS_SQR(x->data.F32[0]) + PS_SQR(x->data.F32[1]) / 2.0 / PS_SQR(params->data.F32[1])) / params->data.F32[1] / params->data.F32[1] / params->data.F32[1] * expf(- (PS_SQR(x->data.F32[0]) + PS_SQR(x->data.F32[1]) / 2.0 / PS_SQR(params->data.F32[1])));
+    deriv->data.F32[2] = 1.0;
+}
+
+
+
+/*****************************************************************************
+myFunc():
+    sum = param[0] * x[0] * x[1] +
+          param[1] * x[0] +
+          param[2] * x[0]^2 +
+          param[3] * x[1] +
+          param[4] * x[1]^2
+ 
+ *****************************************************************************/
+psF32 fitFunc(psVector *deriv,
+              psVector *params,
+              psVector *x)
+{
+    if ((deriv == NULL) || (params == NULL) || (x == NULL)) {
+        psError(PS_ERR_UNKNOWN, true, "deriv or params or x is NULL.\n");
+    }
+
+    derivatives(deriv, params, x);
+    return function(params, x);
+}
+
+psS32 t01()
+{
+    psS32 currentId = psMemGetId();
+    psBool testStatus = true;
+
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 1); // Random number generator; using known seed
+    psMinimization *min = psMinimizationAlloc(NUM_ITERATIONS, ERR_TOL);
+    psArray *ordinates = psArrayAlloc(NUM_DATA_POINTS);
+    psVector *coordinates = psVectorAlloc(NUM_DATA_POINTS, PS_TYPE_F32);
+    psVector *errors = psVectorAlloc(NUM_DATA_POINTS, PS_TYPE_F32);
+    ordinates->n = NUM_DATA_POINTS;
+    coordinates->n = NUM_DATA_POINTS;
+    errors->n = NUM_DATA_POINTS;
+    psVector *params = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+    params->n = NUM_PARAMS;
+    psVector *trueParams = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+    trueParams->n = NUM_PARAMS;
+
+    trueParams->data.F32[0] = 100.0;    // Normalisation
+    trueParams->data.F32[1] = 3.0;      // Width
+    trueParams->data.F32[2] = 10.0;     // Background
+
+    // Set parameters
+    for (long i = 0; i < NUM_PARAMS; i++) {
+        // So we're not starting right on the true value:
+        params->data.F32[i] = trueParams->data.F32[i] * (1.0 - psRandomGaussian(rng) / 10.0);
+    }
+
+    for (long i = 0; i < NUM_DATA_POINTS; i++) {
+        psVector *x = psVectorAlloc(2, PS_TYPE_F32);
+        x->data.F32[0] = 10.0 * psRandomUniform(rng) - 5.0;
+        x->data.F32[1] = 10.0 * psRandomUniform(rng) - 5.0;
+        ordinates->data[i] = x;
+        // Add some noise
+        coordinates->data.F32[i] = function(params, x) + 0.1 * (2.0 * psRandomGaussian(rng) - 1.0);
+        errors->data.F32[i] = 0.1;
+        if (VERBOSE) {
+            printf("Data %ld: (%f, %f) --> %f\n",
+                   i, x->data.F32[0], x->data.F32[1], coordinates->data.F32[i]);
+        }
+    }
+
+    if (!psMinimizeLMChi2(min, NULL, params, NULL, ordinates, coordinates, errors,
+                          (psMinimizeLMChi2Func)fitFunc)) {
+        printf("TEST ERROR: psMinimizeLMChi2() returned FALSE.\n");
+        fflush(stdout);
+        testStatus = false;
+    } else {
+        printf("Minimisation took %d iterations\n", min->iter);
+        printf("chi^2 at the minimum is %.3g\n", min->value);
+        for (long i = 0; i < NUM_PARAMS; i++) {
+            printf("Parameter %ld at the minimum is %.3f, expected: %f\n", i,
+                   params->data.F32[i], trueParams->data.F32[i]);
+            fflush(stdout);
+        }
+        float diff = 0.0;
+        for (long i = 0; i < NUM_DATA_POINTS; i++) {
+            psVector *x = ordinates->data[i];
+            float fitted = function(trueParams, x);
+            float expected = function(params, x);
+            diff += (fitted - expected) / fabsf(expected);
+            if (VERBOSE) {
+                printf("Data point %ld: Fitted: %f, expected: %f\n", i, fitted, expected);
+            }
+            fflush(stdout);
+        }
+        printf("Mean relative difference is %f\n", diff/(float)NUM_DATA_POINTS);
+
+    }
+
+    psFree(min);
+    psFree(params);
+    psFree(trueParams);
+    psFree(ordinates);
+    psFree(coordinates);
+    psFree(errors);
+    psFree(rng);
+    psMemCheckCorruption(1);
+    psS32 memLeaks = psMemCheckLeaks(currentId, NULL, NULL, false);
+    if (0 != memLeaks) {
+        printf("TEST ERROR: Memory Leaks! (%d leaks).\n", memLeaks);
+        fflush(stdout);
+        // XXX: This is causing a seg fault
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    return (testStatus);
+}
+
+#define NUM_ITER 10
+#define TOL  20.0
+psS32 tst_psMinimizationAlloc()
+{
+    psS32 currentId = psMemGetId();
+    psBool testStatus = true;
+
+    psMinimization *tmp = psMinimizationAlloc(NUM_ITER, TOL);
+    if (tmp == NULL) {
+        printf("TEST ERROR: psMinimizationAlloc() returned FALSE.\n");
+        testStatus = false;
+    } else {
+        if (tmp->maxIter != NUM_ITER) {
+            printf("TEST ERROR: psMinimizationAlloc() did not properly set ->maxIter.\n");
+            testStatus = false;
+        }
+
+        if (tmp->tol != TOL) {
+            printf("TEST ERROR: psMinimizationAlloc() did not properly set ->tol.\n");
+            testStatus = false;
+        }
+
+        if (tmp->value != 0.0) {
+            printf("TEST ERROR: psMinimizationAlloc() did not properly set ->value.\n");
+            testStatus = false;
+        }
+
+        if (tmp->iter != 0) {
+            printf("TEST ERROR: psMinimizationAlloc() did not properly set ->iter.\n");
+            testStatus = false;
+        }
+
+        if (!isnan(tmp->lastDelta)) {
+            printf("TEST ERROR: psMinimizationAlloc() did not properly set ->lastDelta.\n");
+            testStatus = false;
+        }
+        psFree(tmp);
+    }
+
+    psMemCheckCorruption(1);
+    psS32 memLeaks = psMemCheckLeaks(currentId, NULL, NULL, false);
+    if (0 != memLeaks) {
+        printf("TEST ERROR: Memory Leaks! (%d leaks).\n", memLeaks);
+        testStatus = false;
+    }
+
+    return(testStatus);
+}
+
+
+#define NUM_ITER 10
+#define TOL  20.0
+psS32 tst_psMinConstrainAlloc()
+{
+    psS32 currentId = psMemGetId();
+    psBool testStatus = true;
+
+    psMinConstrain *tmp = psMinConstrainAlloc(NUM_ITER, TOL);
+    if (tmp == NULL) {
+        printf("TEST ERROR: psMinConstrainAlloc() returned FALSE.\n");
+        testStatus = false;
+    } else {
+        if (tmp->paramMask != NULL) {
+            printf("TEST ERROR: psMinConstrainAlloc() did not properly set ->paramMask.\n");
+            testStatus = false;
+        }
+
+        if (tmp->paramMax != NULL) {
+            printf("TEST ERROR: psMinConstrainAlloc() did not properly set ->paramMax.\n");
+            testStatus = false;
+        }
+
+        if (tmp->paramMin != NULL) {
+            printf("TEST ERROR: psMinConstrainAlloc() did not properly set ->paramMin.\n");
+            testStatus = false;
+        }
+
+        if (tmp->paramDelta != NULL) {
+            printf("TEST ERROR: psMinConstrainAlloc() did not properly set ->paramDelta.\n");
+            testStatus = false;
+        }
+
+        psFree(tmp);
+    }
+
+    psMemCheckCorruption(1);
+    psS32 memLeaks = psMemCheckLeaks(currentId, NULL, NULL, false);
+    if (0 != memLeaks) {
+        printf("TEST ERROR: Memory Leaks! (%d leaks).\n", memLeaks);
+        testStatus = false;
+    }
+
+    return(testStatus);
+}
+
+
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    psTraceSetDestination(1);
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel(__func__, 0);
+    psTraceSetLevel("t01", 0);
+    psTraceSetLevel("psMinimizeLMChi2_OLD", 0);
+    psTraceSetLevel("psMinimizeLMChi2", 0);
+    psTraceSetLevel("psMinimizeGaussNewtonDelta", 0);
+    psTraceSetLevel("psMinimizeGaussNewtonDelta_EAM", 0);
+    psTraceSetLevel("p_psMinLM_GuessABP", 0);
+    psTraceSetLevel("p_psMinLM_GuessABP_EAM", 0);
+    psTraceSetLevel("p_psMinLM_SetABX", 0);
+    psTraceSetLevel("psGaussJordan", 0);
+    psTraceSetLevel("psMinimizationAlloc", 0);
+    psTraceSetLevel("psMinConstrainAlloc", 0);
+    psTraceSetLevel("psMemCheckMinimization", 0);
+    psTraceSetLevel("p_psDetermineBracket", 0);
+    psTraceSetLevel("p_psDetermineBracket2", 0);
+    psTraceSetLevel("p_psLineMin", 0);
+    psTraceSetLevel("psMinimizePowell", 0);
+    psTraceSetLevel("myPowellChi2Func", 0);
+    psTraceSetLevel("psMinimizeChi2Powell", 0);
+    psTraceSetLevel("BuildSums1D", 0);
+    psTraceSetLevel("BuildSums2D", 0);
+    psTraceSetLevel("Polynomial2DEvalVectorD", 0);
+    psTraceSetLevel("vectorFitPolynomial1DCheby", 0);
+    psTraceSetLevel("VectorFitPolynomial1DOrd", 0);
+    psTraceSetLevel("psVectorFitPolynomial1D", 0);
+    psTraceSetLevel("psVectorClipFitPolynomial1D", 0);
+
+    psTrace(__func__, 2, "Calling new psMinimize().\n");
+    psS32 testStatus = true;
+
+
+    testStatus &= t01();
+    testStatus &= tst_psMinimizationAlloc();
+    testStatus &= tst_psMinConstrainAlloc();
+    if (testStatus == true) {
+        printf("The LMM minimization tests PASSED.\n");
+    } else {
+        printf("The LMM minimization tests FAILED.\n");
+    }
+    printf("DONE\n");
+    fflush(stdout);
+}
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMinimizePowell.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMinimizePowell.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psMinimizePowell.c	(revision 22158)
@@ -0,0 +1,294 @@
+/*****************************************************************************
+    This routine must ensure that psMinimizePowell() works correctly.
+ 
+    We test with a NULL and non-NULL paramMask.
+ 
+    XXX: Must verify the stderr for the NULL parameter tests.
+    XXX: psMinimizeChi2Powell() is untested.
+ *****************************************************************************/
+#include <stdio.h>
+#include <math.h>
+#include "pslib.h"
+#include "psTest.h"
+#define N 5
+#define MIN_VALUE 20.0
+#define NUM_PARAMS 10
+#define ERROR_TOLERANCE 0.10
+float expectedParm[NUM_PARAMS];
+psS32 testStatus = true;
+
+/*****************************************************************************
+myFunc(): This routine subtracts the associate value in expectedParm[] from
+each parameter and then squares it, then sums that for all parameters, then
+adds MIN_VALUE to it.  The minimum for this function will be MIN_VALUE, and
+will occur when each parameter equals the associated value in expectedParm[].
+ 
+This procedure ignores the coordinates, other than to ensure that they were
+passed correctly from psMinimizePowell().
+ *****************************************************************************/
+float myFunc(psVector *myParams,
+             psArray *myCoords)
+{
+    float sum = 0.0;
+    float coordData = 0.0;
+    float expData = 0.0;
+    psS32 i;
+
+    //
+    // Simply ensure that the coordinate data was passed correctly.
+    //
+    for (i=0;i<N;i++) {
+        coordData = ((psVector *) (myCoords->data[i]))->data.F32[0];
+        expData = (float) (i+10);
+        if (fabs(coordData - expData) > FLT_EPSILON) {
+            printf("ERROR(1): coordinate data was incorrectly passed to myFunc()\n");
+            printf("ERROR(1): was (%f) should be (%f)\n", coordData, expData);
+            testStatus = false;
+        }
+        coordData = ((psVector *) (myCoords->data[i]))->data.F32[1];
+        expData = (float) (i+3);
+        if (fabs(coordData - expData) > FLT_EPSILON) {
+            printf("ERROR(2): coordinate data was incorrectly passed to myFunc()\n");
+            printf("ERROR(2): was (%f) should be (%f)\n", coordData, expData);
+            testStatus = false;
+        }
+    }
+
+
+    sum = 0.0;
+    for (i=0;i<NUM_PARAMS;i++) {
+        sum+= (myParams->data.F32[i] - expectedParm[i]) * (myParams->data.F32[i] - expectedParm[i]);
+    }
+    sum = MIN_VALUE + (sum * sum);
+
+    return(sum);
+}
+
+
+psS32 t00()
+{
+    psS32 currentId = psMemGetId();
+    psS32 memLeaks = 0;
+    psS32 i = 0;
+    psArray *myCoords;
+    psVector *myParams;
+    psVector *myParamMask;
+    psMinimization *min;
+
+    psTraceSetLevel(".psLib", 0);
+    /**************************************************************************
+     *************************************************************************/
+    myParams = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+    myParamMask = psVectorAlloc(NUM_PARAMS, PS_TYPE_U8);
+    myParams->n = NUM_PARAMS;
+    myParamMask->n = NUM_PARAMS;
+    min = psMinimizationAlloc(100, 0.01);
+
+    myCoords = psArrayAlloc(N);
+    myCoords->n = N;
+    for (i=0;i<N;i++) {
+        myCoords->data[i] = (psPtr *) psVectorAlloc(2, PS_TYPE_F32);
+        ((psVector *) (myCoords->data[i]))->data.F32[0] = (float) (i+10);
+        ((psVector *) (myCoords->data[i]))->data.F32[1] = (float) (i+3);
+    }
+    for (i=0;i<NUM_PARAMS;i++) {
+        expectedParm[i] = 2.32 + (float) (2 * i);
+        myParams->data.F32[i] = 0.0;
+        myParams->data.F32[i] = (float) i;
+        myParamMask->data.U8[i] = 0;
+    }
+
+    printPositiveTestHeader(stdout,
+                            "psMinimize functions",
+                            "psMinimizePowell()");
+
+    psMinimizePowell(min,
+                     myParams,
+                     myParamMask,
+                     myCoords,
+                     (psMinimizePowellFunc) myFunc);
+
+    printf("\nThe minimum is %f (expected: %f)\n", min->value, MIN_VALUE);
+
+    for (i=0;i<NUM_PARAMS;i++) {
+        printf("Parameter %d at the minimum is %.1f (expected: %.1f)\n", i,
+               myParams->data.F32[i], expectedParm[i]);
+
+        if (fabs(myParams->data.F32[i] - expectedParm[i]) > fabs(ERROR_TOLERANCE * expectedParm[i])) {
+            printf("ERROR: Parameter %d: (%.1f), expected was (%.1f)\n",
+                   i, myParams->data.F32[i], expectedParm[i]);
+            testStatus = false;
+        } else {
+            printf("Parameter %d: (%.1f), expected was (%.1f)\n",
+                   i, myParams->data.F32[i], expectedParm[i]);
+        }
+    }
+
+
+    psFree(myCoords);
+    psFree(myParams);
+    psFree(myParamMask);
+    psFree(min);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    printFooter(stdout,
+                "psMinimize functions",
+                "psMinimizePowell()",
+                testStatus);
+
+
+    return (!testStatus);
+}
+
+psS32 t01()
+{
+    psS32 currentId = psMemGetId();
+    psS32 memLeaks = 0;
+    psS32 i = 0;
+    psArray *myCoords;
+    psVector *myParams;
+    psMinimization *min;
+
+    psTraceSetLevel(".psLib", 0);
+    /**************************************************************************
+     *************************************************************************/
+    myParams = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+    min = psMinimizationAlloc(100, 0.01);
+
+    myCoords = psArrayAlloc(N);
+    myCoords->n = N;
+    for (i=0;i<N;i++) {
+        myCoords->data[i] = (psPtr *) psVectorAlloc(2, PS_TYPE_F32);
+        ((psVector *) (myCoords->data[i]))->data.F32[0] = (float) (i+10);
+        ((psVector *) (myCoords->data[i]))->data.F32[1] = (float) (i+3);
+        ((psVector *) (myCoords->data[i]))->n = 2;
+    }
+    for (i=0;i<NUM_PARAMS;i++) {
+        expectedParm[i] = 2.32 + (float) (2 * i);
+        myParams->data.F32[i] = 0.0;
+        myParams->data.F32[i] = (float) i;
+        myParams->n++;
+    }
+
+    printPositiveTestHeader(stdout,
+                            "psMinimize functions",
+                            "psMinimizePowell()");
+
+    psMinimizePowell(min,
+                     myParams,
+                     NULL,
+                     myCoords,
+                     (psMinimizePowellFunc) myFunc);
+
+    printf("\nThe minimum is %f (expected: %f)\n", min->value, MIN_VALUE);
+
+    for (i=0;i<NUM_PARAMS;i++) {
+        printf("Parameter %d at the minimum is %.1f (expected: %.1f)\n", i,
+               myParams->data.F32[i], expectedParm[i]);
+
+        if (fabs(myParams->data.F32[i] - expectedParm[i]) > fabs(ERROR_TOLERANCE * expectedParm[i])) {
+            printf("ERROR: Parameter %d: (%.1f), expected was (%.1f)\n",
+                   i, myParams->data.F32[i], expectedParm[i]);
+            testStatus = false;
+        } else {
+            printf("Parameter %d: (%.1f), expected was (%.1f)\n",
+                   i, myParams->data.F32[i], expectedParm[i]);
+        }
+    }
+
+
+    psFree(myCoords);
+    psFree(myParams);
+    psFree(min);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    printFooter(stdout,
+                "psMinimize functions",
+                "psMinimizePowell()",
+                testStatus);
+
+
+    return (!testStatus);
+}
+
+psS32 t02()
+{
+    psS32 currentId = psMemGetId();
+    psS32 memLeaks = 0;
+    psS32 i = 0;
+    psArray *myCoords;
+    psVector *myParams;
+    psVector *myParamMask;
+    psMinimization *min;
+
+    psTraceSetLevel(".psLib", 0);
+    /**************************************************************************
+     *************************************************************************/
+    myParams = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+    myParamMask = psVectorAlloc(NUM_PARAMS, PS_TYPE_U8);
+    min = psMinimizationAlloc(100, 0.01);
+
+    myCoords = psArrayAlloc(N);
+    myCoords->n = N;
+    for (i=0;i<N;i++) {
+        myCoords->data[i] = (psPtr *) psVectorAlloc(2, PS_TYPE_F32);
+        ((psVector *) (myCoords->data[i]))->data.F32[0] = (float) (i+10);
+        ((psVector *) (myCoords->data[i]))->data.F32[1] = (float) (i+3);
+        ((psVector *) (myCoords->data[i]))->n++;
+    }
+    for (i=0;i<NUM_PARAMS;i++) {
+        expectedParm[i] = 2.32 + (float) (2 * i);
+        myParams->data.F32[i] = 0.0;
+        myParams->data.F32[i] = (float) i;
+        myParamMask->data.U8[i] = 0;
+        myParams->n++;
+        myParamMask->n++;
+    }
+
+    printPositiveTestHeader(stdout,
+                            "psMinimize functions",
+                            "psMinimizePowell(): various NULL inputs");
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error for null minimize.");
+    psMinimizePowell(NULL, myParams, myParamMask, myCoords, (psMinimizePowellFunc) myFunc);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error for null parameter vector");
+    psMinimizePowell(min, NULL, myParamMask, myCoords,(psMinimizePowellFunc) myFunc);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error for null coords.");
+    psMinimizePowell(min, myParams, myParamMask, NULL, (psMinimizePowellFunc) myFunc);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error for null function");
+    psMinimizePowell(min, myParams, myParamMask, myCoords, NULL);
+
+    psFree(myCoords);
+    psFree(myParams);
+    psFree(myParamMask);
+    psFree(min);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    printFooter(stdout,
+                "psMinimize functions",
+                "psMinimizePowell(): various NULL inputs",
+                testStatus);
+
+
+    return (!testStatus);
+}
+
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    t00();
+    t01();
+    t02();
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolyFit1D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolyFit1D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolyFit1D.c	(revision 22158)
@@ -0,0 +1,493 @@
+/*****************************************************************************
+This routine must ensure that various psLib functions which fit 1D polynomials
+to data work correctly.  There is a function genericTest() which creates
+vectors of data points (x and f), and populates them with the values from an
+arbitrary function setData().  It then calls appropriate 1D fitting function.
+It then evaluates the polynomial with the coefficients generated above and
+determines if they are within an error tolerance of the expected values.
+ 
+XXX: Try null stats.
+ *****************************************************************************/
+#include <stdio.h>
+#include <math.h>
+#include "pslib.h"
+#include "psTest.h"
+#define NUM_DATA 100
+#define POLY_ORDER 5
+#define A 2.0
+#define B 3.0
+#define C 4.0
+#define D 5.0
+#define E 6.0
+#define ERROR_TOLERANCE 0.10
+#define YERR 10.0
+#define VERBOSE 0
+#define NUM_ITERATIONS 5
+#define CLIP_SIGMA 4.0
+#define OUTLIERS true
+#define MASK_VALUE 1
+
+#define TS00_F_NULL  0x00000001
+#define TS00_F_F32  0x00000002
+#define TS00_F_F64  0x00000004
+#define TS00_F_S32  0x00000008
+#define TS00_X_NULL  0x00000010
+#define TS00_X_F32  0x00000020
+#define TS00_X_F64  0x00000040
+#define TS00_X_S32  0x00000080
+#define TS00_FERR_NULL  0x00000100
+#define TS00_FERR_F32  0x00000200
+#define TS00_FERR_F64  0x00000400
+#define TS00_FERR_S32  0x00000800
+#define TS00_MASK_NULL  0x00001000
+#define TS00_MASK_U8  0x00002000
+#define TS00_MASK_S32  0x00004000
+#define TS00_POLY_ORD  0x00008000
+#define TS00_POLY_CHEB  0x00010000
+#define TS00_CLIP_FIT  0x00020000
+
+psF32 setData(psF32 x)
+{
+    return(A + (B * x) + (C * x * x) + (D * x * x * x) + (E * x * x * x * x));
+}
+
+bool genericTest(
+    psU32 flags,
+    psS32 polyOrder,
+    psS32 numData,
+    psBool expectedRC)
+{
+    psS32 currentId = psMemGetId();
+    bool testStatus = true;
+    psS32 memLeaks = 0;
+    psPolynomial1D *myPoly = NULL;
+    psVector *x = NULL;
+    psVector *f = NULL;
+    psVector *mask = NULL;
+    psVector *fErr = NULL;
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    stats->clipSigma = CLIP_SIGMA;
+    stats->clipIter = NUM_ITERATIONS;
+
+    printPositiveTestHeader(stdout, "psMinimize functions", "1D Polynomial Fitting Functions");
+
+    if (expectedRC == false) {
+        printf("This test should generate an error message, and return NULL.\n");
+    }
+
+    if (flags & TS00_CLIP_FIT) {
+        printf("        performing a clip-fit\n");
+    } else {
+        printf("        performing a non clip-fit\n");
+    }
+
+    if (flags & TS00_POLY_ORD) {
+        printf(" using ordinary polynomials\n");
+        myPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, polyOrder);
+    }
+
+    if (flags & TS00_POLY_CHEB) {
+        printf(" using chebyshev polynomials\n");
+        myPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_CHEB, polyOrder);
+    }
+
+    if (flags & TS00_X_NULL) {
+        printf(" using a NULL x vector\n");
+        numData = 30;
+    }
+
+    psVector *xTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *fTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    xTruth->n = numData;
+    fTruth->n = numData;
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 1); // Using a known seed
+    for (int i = 0; i < numData; i++) {
+        xTruth->data.F64[i] = (flags & TS00_X_NULL) ? i : 2.0*psRandomUniform(rng) - 1.0;
+        fTruth->data.F64[i] = setData(xTruth->data.F64[i]);
+    }
+    if (flags & TS00_X_NULL && flags & TS00_POLY_CHEB) {
+        // Renormalise the indices
+        p_psNormalizeVectorRange(xTruth, -1.0, 1.0);
+    }
+    psFree(rng);
+    #if VERBOSE
+
+    for (int i = 0; i < numData; i++) {
+        printf("Original %d: %f\t%f\n", i, xTruth->data.F64[i], fTruth->data.F64[i]);
+    }
+    #endif
+
+    if (flags & TS00_X_F32) {
+        printf(" using a psF32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F32);
+
+        #if 0
+
+        if (flags & TS00_POLY_CHEB) {
+            p_psNormalizeVectorRange(x, -1.0, 1.0);
+        }
+        #endif
+
+    }
+
+    if (flags & TS00_X_S32) {
+        printf(" using a psS32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_S32);
+
+        #if 0
+
+        if (flags & TS00_POLY_CHEB) {
+            p_psNormalizeVectorRange(x, -1, 1);
+        }
+        #endif
+
+    }
+
+    if (flags & TS00_X_F64) {
+        printf(" using a psF64 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F64);
+
+        #if 0
+
+        if (flags & TS00_POLY_CHEB) {
+            p_psNormalizeVectorRange(x, -1.0, 1.0);
+        }
+        #endif
+
+    }
+
+    if (flags & TS00_F_NULL) {
+        printf(" using a NULL f vector\n");
+    }
+
+    if (flags & TS00_F_F32) {
+        printf(" using a psF32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F32[numData/4]*= 2.0;
+            f->data.F32[numData/2]*= 2.0;
+            f->data.F32[3*numData/4]*= 2.0;
+        }
+    }
+
+    if (flags & TS00_F_S32) {
+        printf(" using a psS32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_S32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.S32[numData/4]*= 2.0;
+            f->data.S32[numData/2]*= 2.0;
+            f->data.S32[3*numData/4]*= 2.0;
+        }
+
+    }
+
+    if (flags & TS00_F_F64) {
+        printf(" using a psF64 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F64);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F64[numData/4]*= 2.0;
+            f->data.F64[numData/2]*= 2.0;
+            f->data.F64[3*numData/4]*= 2.0;
+        }
+    }
+
+    if (flags & TS00_FERR_NULL) {
+        printf(" using a NULL fErr vector\n");
+    }
+
+    if (flags & TS00_FERR_F32) {
+        printf(" using a psF32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F32[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_S32) {
+        printf(" using a psS32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_S32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.S32[i] = (psS32) YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_F64) {
+        printf(" using a psF64 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F64);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F64[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_MASK_NULL) {
+        printf(" using a NULL mask vector\n");
+    }
+
+    if (flags & TS00_MASK_U8) {
+        printf(" using a psU8 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_U8);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.U8[i] = 0;
+        }
+    }
+
+    if (flags & TS00_MASK_S32) {
+        printf(" using a psS32 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_S32);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.S32[i] = 0;
+        }
+    }
+
+    psPolynomial1D *rc = NULL;
+    if (flags & TS00_CLIP_FIT) {
+        rc = psVectorClipFitPolynomial1D(myPoly, stats, mask, MASK_VALUE, f, fErr, x);
+    } else {
+        rc = psVectorFitPolynomial1D(myPoly, mask, MASK_VALUE, f, fErr, x);
+    }
+
+    if (rc == NULL) {
+        if (expectedRC == true) {
+            printf("TEST ERROR: the 1D polynomial fitting function returned NULL.\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            printf("TEST ERROR: the 1D polynomial fitting function returned non-NULL.\n");
+            testStatus = false;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<polyOrder+1;i++) {
+                printf("Polynomial coefficient %d is %0.1f\n", i, myPoly->coeff[i]);
+            }
+        }
+
+        psVector *result = psPolynomial1DEvalVector(myPoly, xTruth);
+        for (psS32 i=0; i<numData; i++) {
+            // Skip the outliers.
+            if ((i == numData/4) || (i == numData/2) || (i == 3*numData/4)) {
+                continue;
+            }
+            psF32 expectData = fTruth->data.F64[i];
+            psF32 actualData = result->data.F64[i];
+            if (fabs(actualData-expectData) > fabs(ERROR_TOLERANCE * expectData)) {
+                printf("TEST ERROR: Fitted data %d: %.1f --> %.1f vs %.1f\n",
+                       i, xTruth->data.F64[i], actualData, expectData);
+                testStatus = false;
+            } else {
+                if (VERBOSE) {
+                    printf("GOOD: Fitted data %d: %1.f --> %.1f vs %.1f\n",
+                           i, xTruth->data.F64[i], actualData, expectData);
+                }
+            }
+        }
+        psFree(result);
+    }
+
+    psMemCheckCorruption(1);
+    psFree(myPoly);
+    psFree(mask);
+    psFree(x);
+    psFree(f);
+    psFree(xTruth);
+    psFree(fTruth);
+    psFree(fErr);
+    psFree(stats);
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    printFooter(stdout, "psMinimize functions", "1D Polynomial Fitting Functions", testStatus);
+
+    return (testStatus);
+}
+
+/*****************************************************************************
+We test a variety of polynomial fitting routines, types, and polynomial types
+here:
+    F32 tests: Ordinary polys, non-clip fit
+    F64 tests: Ordinary polys, non-clip fit
+    F32 tests: Chebyshev polys, non-clip fit
+    F64 tests: Chebyshev polys, non-clip fit
+    F32 tests: Ordinary polys, clip fit
+    F64 tests: Ordinary polys, clip fit
+    F32 tests: Chebyshev polys, clip fit
+    F64 tests: Chebyshev polys, clip fit
+ *****************************************************************************/
+int main()
+{
+    psBool testStatus = true;
+    psLogSetFormat("HLNM");
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("psVectorClipFitPolynomial1D", 0);
+    psTraceSetLevel("VectorFitPolynomial1DOrd", 0);
+    psTraceSetLevel("VectorFitPolynomial1DCheb", 0);
+    psTraceSetLevel("vectorFitPolynomial1DCheb", 0);
+    psTraceSetLevel("vectorFitPolynomial1DChebSlow", 0);
+    psTraceSetLevel("vectorFitPolynomial1DChebFast", 0);
+    psTraceSetLevel("psVectorFitPolynomial1D", 0);
+    psTraceSetLevel("p_psCreateChebyshevPolys", 0);
+
+    printPositiveTestHeader(stdout, "psMinimize functions: 1D Polynomial Fitting Functions", "");
+
+    //
+    // F32 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true);
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_NULL | TS00_X_NULL | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false);
+    // Unallowable vector types
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_S32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_S32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_S32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false);
+
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true);
+
+    //
+    // F64 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true);
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_NULL | TS00_X_NULL | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false);
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true);
+
+
+    //
+    // F32 tests: Chebyshev polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true);
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_NULL | TS00_X_NULL | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_NULL | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, false);
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true);
+
+
+    //
+    // F64 tests: Chebyshev polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true);
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_NULL | TS00_X_NULL | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_NULL | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, false);
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true);
+
+    //
+    // F32 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true);
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_NULL | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+
+
+    //
+    // F64 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true);
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+
+
+    //
+    // F32 tests: Chebyshev polys, clip fit
+    //
+    // All Vectors non-NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true);
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_NULL | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_NULL | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+
+
+    //
+    // F64 tests: Chebyshev polys, clip fit
+    //
+    // All Vectors non-NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true);
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_F_F64 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_NULL | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F64 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false);
+
+    printFooter(stdout, "psMinimize functions: 1D Polynomial Fitting Functions", "", testStatus);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolyFit2D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolyFit2D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolyFit2D.c	(revision 22158)
@@ -0,0 +1,426 @@
+/*****************************************************************************
+This routine must ensure that various psLib functions which fit 2D polynomials
+to data work correctly.  There is a function genericTest() which creates
+vectors of data points (x and f), and populates them with the values from an
+arbitrary function setData().  It then calls appropriate 2D fitting function.
+It then evaluates the polynomial with the coefficients generated above and
+determines if they are within an error tolerance of the expected values.
+ *****************************************************************************/
+#include <stdio.h>
+#include <math.h>
+#include "pslib.h"
+#include "psTest.h"
+#define NUM_DATA 100
+#define POLY_ORDER_X 2
+#define POLY_ORDER_Y 3
+#define A 2.0
+#define B 3.0
+#define C 4.0
+#define D 5.0
+#define E 6.0
+#define F 4.0
+#define ERROR_TOLERANCE 0.10
+#define YERR 10.0
+#define VERBOSE 0
+#define NUM_ITERATIONS 5
+#define CLIP_SIGMA 4.0
+#define OUTLIERS true
+#define MASK_VALUE 1
+
+#define TS00_F_NULL  0x00000001
+#define TS00_F_F32  0x00000002
+#define TS00_F_F64  0x00000004
+#define TS00_F_S32  0x00000008
+#define TS00_X_NULL  0x00000010
+#define TS00_X_F32  0x00000020
+#define TS00_X_F64  0x00000040
+#define TS00_X_S32  0x00000080
+#define TS00_FERR_NULL  0x00000100
+#define TS00_FERR_F32  0x00000200
+#define TS00_FERR_F64  0x00000400
+#define TS00_FERR_S32  0x00000800
+#define TS00_MASK_NULL  0x00001000
+#define TS00_MASK_U8  0x00002000
+#define TS00_MASK_S32  0x00004000
+#define TS00_POLY_ORD  0x00008000
+#define TS00_POLY_CHEB  0x00010000
+#define TS00_CLIP_FIT  0x00020000
+#define TS00_Y_NULL  0x00100000
+#define TS00_Y_F32  0x00200000
+#define TS00_Y_F64  0x00400000
+#define TS00_Y_S32  0x00800000
+
+psF32 setData(psF32 x, psF32 y)
+{
+    return(A + (B * x) + (C * x * x) + (D * y) + (E * y * y) + (F * x * y));
+}
+
+psS32 genericTest(
+    psU32 flags,
+    psS32 polyOrderX,
+    psS32 polyOrderY,
+    psS32 numData,
+    psBool expectedRC)
+{
+    psS32 currentId = psMemGetId();
+    psS32 testStatus = true;
+    psS32 memLeaks = 0;
+    psPolynomial2D *myPoly = NULL;
+    psVector *x = NULL;
+    psVector *y = NULL;
+    psVector *f = NULL;
+    psVector *mask = NULL;
+    psVector *fErr = NULL;
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    stats->clipSigma = CLIP_SIGMA;
+    stats->clipIter = NUM_ITERATIONS;
+
+    printPositiveTestHeader(stdout, "psMinimize functions", "2D Polynomial Fitting Functions");
+
+    if (expectedRC == false) {
+        printf("This test should generate an error message, and return NULL.\n");
+    }
+
+    if (flags & TS00_CLIP_FIT) {
+        printf(" performing a clip-fit\n");
+    } else {
+        printf(" performing a non clip-fit\n");
+    }
+
+    if (flags & TS00_POLY_ORD) {
+        printf(" using ordinary polynomials\n");
+        myPoly = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, polyOrderX, polyOrderY);
+    }
+
+
+    psVector *xTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *yTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *fTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    xTruth->n = numData;
+    yTruth->n = numData;
+    fTruth->n = numData;
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 1); // Using an RNG with a known seed
+    for (int i = 0; i < numData; i++) {
+        xTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        yTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        fTruth->data.F64[i] = setData(xTruth->data.F64[i], yTruth->data.F64[i]);
+    }
+    psFree(rng);
+
+    if (flags & TS00_X_NULL) {
+        printf(" using a NULL x vector\n");
+    }
+
+    if (flags & TS00_X_F32) {
+        printf(" using a psF32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_X_S32) {
+        printf(" using a psS32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_X_F64) {
+        printf(" using a psF64 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F64);
+    }
+
+    if (flags & TS00_Y_NULL) {
+        printf(" using a NULL y vector\n");
+    }
+
+    if (flags & TS00_Y_F32) {
+        printf(" using a psF32 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_Y_S32) {
+        printf(" using a psS32 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_Y_F64) {
+        printf(" using a psF64 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_F64);
+    }
+
+    if (flags & TS00_F_NULL) {
+        printf(" using a NULL f vector\n");
+    }
+
+    if (flags & TS00_F_F32) {
+        printf(" using a psF32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F32[numData/4]*= 2.0;
+            f->data.F32[numData/2]*= 2.0;
+            f->data.F32[3*numData/4]*= 2.0;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original data %d: (%.1f %.1f)\n", i, (psF32) i, f->data.F32[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_F_S32) {
+        printf(" using a psS32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_S32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.S32[numData/4]*= 2.0;
+            f->data.S32[numData/2]*= 2.0;
+            f->data.S32[3*numData/4]*= 2.0;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original data %d: (%.1f %d)\n", i, (psF32) i, f->data.S32[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_F_F64) {
+        printf(" using a psF64 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F64);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F64[numData/4]*= 2.0;
+            f->data.F64[numData/2]*= 2.0;
+            f->data.F64[3*numData/4]*= 2.0;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original data %d: (%.1f %.1f)\n", i, (psF32) i, f->data.F64[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_FERR_NULL) {
+        printf(" using a NULL fErr vector\n");
+    }
+
+    if (flags & TS00_FERR_F32) {
+        printf(" using a psF32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F32[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_S32) {
+        printf(" using a psS32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_S32);
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.S32[i] = (psS32) YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_F64) {
+        printf(" using a psF64 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F64);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F64[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_MASK_NULL) {
+        printf(" using a NULL mask vector\n");
+    }
+
+    if (flags & TS00_MASK_U8) {
+        printf(" using a psU8 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_U8);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.U8[i] = 0;
+        }
+    }
+
+    if (flags & TS00_MASK_S32) {
+        printf(" using a psS32 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_S32);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.S32[i] = 0;
+        }
+    }
+
+    psPolynomial2D *rc = NULL;
+    if (flags & TS00_CLIP_FIT) {
+        rc = psVectorClipFitPolynomial2D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y);
+    } else {
+        rc = psVectorFitPolynomial2D(myPoly, mask, MASK_VALUE, f, fErr, x, y);
+    }
+
+    if (rc == NULL) {
+        if (expectedRC == true) {
+            printf("TEST ERROR: the 2D polynomial fitting function returned NULL.\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            printf("TEST ERROR: the 2D polynomial fitting function returned non-NULL.\n");
+            testStatus = false;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<polyOrderX+1;i++) {
+                for (psS32 j=0;j<polyOrderY+1;j++) {
+                    printf("Polynomial coefficient [%d][%d] is %0.1f\n", i, j, myPoly->coeff[i][j]);
+                }
+            }
+        }
+
+        psVector *result = psPolynomial2DEvalVector(myPoly, xTruth, yTruth);
+        for (psS32 i=0 ;i<numData; i++) {
+            // Skip the outliers.
+            if ((i == numData/4) || (i == numData/2) || (i == 3*numData/4)) {
+                continue;
+            }
+            psF64 actualData = result->data.F64[i];
+            psF64 expectData = fTruth->data.F64[i];
+
+            if (fabs(actualData-expectData) > fabs(ERROR_TOLERANCE * expectData)) {
+                printf("TEST ERROR: Fitted data %d: (%.1f), expected was (%.1f)\n",
+                       i, actualData, expectData);
+                testStatus = false;
+            } else {
+                if (VERBOSE) {
+                    printf("GOOD: Fitted data %d: (%.1f), expected was (%.1f)\n",
+                           i, actualData, expectData);
+                }
+            }
+        }
+        psFree(result);
+    }
+
+    psMemCheckCorruption(1);
+    psFree(myPoly);
+    psFree(mask);
+    psFree(xTruth);
+    psFree(yTruth);
+    psFree(fTruth);
+    psFree(x);
+    psFree(y);
+    psFree(f);
+    psFree(fErr);
+    psFree(stats);
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    printFooter(stdout, "psMinimize functions", "2D Polynomial Fitting Functions", testStatus);
+
+    return (testStatus);
+}
+
+/*****************************************************************************
+We test a variety of polynomial fitting routines, types, and polynomial types
+here:
+    F32 tests: Ordinary polys, non-clip fit
+    F64 tests: Ordinary polys, non-clip fit
+    F32 tests: Chebyshev polys, non-clip fit
+    F64 tests: Chebyshev polys, non-clip fit
+    F32 tests: Ordinary polys, clip fit
+    F64 tests: Ordinary polys, clip fit
+    F32 tests: Chebyshev polys, clip fit
+    F64 tests: Chebyshev polys, clip fit
+ *****************************************************************************/
+psS32 main()
+{
+    psBool testStatus = true;
+    psLogSetFormat("HLNM");
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("psVectorClipFitPolynomial2D", 0);
+    psTraceSetLevel("VectorFitPolynomial2DOrd", 0);
+    psTraceSetLevel("psVectorFitPolynomial2D", 0);
+
+    printPositiveTestHeader(stdout, "psMinimize functions: 2D Polynomial Fitting Functions", "");
+
+    //
+    // F32 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true);
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true);
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+
+    //
+    // F64 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true);
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true);
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+
+    //
+    // F32 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true);
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+
+    //
+    // F64 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true);
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false);
+
+    printFooter(stdout, "psMinimize functions: 2D Polynomial Fitting Functions", "", testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolyFit3D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolyFit3D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolyFit3D.c	(revision 22158)
@@ -0,0 +1,479 @@
+/*****************************************************************************
+This routine must ensure that various psLib functions which fit 3D polynomials
+to data work correctly.  There is a function genericTest() which creates
+vectors of data points (x and f), and populates them with the values from an
+arbitrary function setData().  It then calls appropriate 3D fitting function.
+It then evaluates the polynomial with the coefficients generated above and
+determines if they are within an error tolerance of the expected values.
+ *****************************************************************************/
+#include <stdio.h>
+#include <math.h>
+#include "pslib.h"
+#include "psTest.h"
+#define NUM_DATA 100
+#define POLY_ORDER_X 2
+#define POLY_ORDER_Y 3
+#define POLY_ORDER_Z 2
+#define A 100.0
+#define B 2.0
+#define C 3.0
+#define D 4.0
+#define E 5.0
+#define F 4.0
+#define H 3.0
+#define J 3.0
+#define K 1.0
+#define L 5.0
+#define ERROR_TOLERANCE 0.10
+#define YERR 10.0
+#define VERBOSE 0
+#define NUM_ITERATIONS 5
+#define CLIP_SIGMA 4.0
+#define OUTLIERS true
+#define MASK_VALUE 1
+
+#define TS00_F_NULL  0x00000001
+#define TS00_F_F32  0x00000002
+#define TS00_F_F64  0x00000004
+#define TS00_F_S32  0x00000008
+#define TS00_X_NULL  0x00000010
+#define TS00_X_F32  0x00000020
+#define TS00_X_F64  0x00000040
+#define TS00_X_S32  0x00000080
+#define TS00_FERR_NULL  0x00000100
+#define TS00_FERR_F32  0x00000200
+#define TS00_FERR_F64  0x00000400
+#define TS00_FERR_S32  0x00000800
+#define TS00_MASK_NULL  0x00001000
+#define TS00_MASK_U8  0x00002000
+#define TS00_MASK_S32  0x00004000
+#define TS00_POLY_ORD  0x00008000
+#define TS00_POLY_CHEB  0x00010000
+#define TS00_CLIP_FIT  0x00020000
+#define TS00_Y_NULL  0x00100000
+#define TS00_Y_F32  0x00200000
+#define TS00_Y_F64  0x00400000
+#define TS00_Y_S32  0x00800000
+#define TS00_Z_NULL  0x01000000
+#define TS00_Z_F32  0x02000000
+#define TS00_Z_F64  0x04000000
+#define TS00_Z_S32  0x08000000
+
+psF32 setData(psF32 x, psF32 y, psF32 z)
+{
+    if (0) {
+        // Linear case, for testing.
+        return(A + (B * x) + (D * y) + (H * z));
+    } else {
+        return(A + (B * x) + (C * x * x) + (D * y) + (E * y * y) + (F * x * y) + (H * z) +
+               (J * z * z) + (K * x * z) + (L * y * z));
+    }
+}
+
+psS32 genericTest(
+    psU32 flags,
+    psS32 polyOrderX,
+    psS32 polyOrderY,
+    psS32 polyOrderZ,
+    psS32 numData,
+    psBool expectedRC)
+{
+    psS32 currentId = psMemGetId();
+    psS32 testStatus = true;
+    psS32 memLeaks = 0;
+    psPolynomial3D *myPoly = NULL;
+    psVector *x = NULL;
+    psVector *y = NULL;
+    psVector *z = NULL;
+    psVector *f = NULL;
+    psVector *mask = NULL;
+    psVector *fErr = NULL;
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    stats->clipSigma = CLIP_SIGMA;
+    stats->clipIter = NUM_ITERATIONS;
+
+    printPositiveTestHeader(stdout, "psMinimize functions", "3D Polynomial Fitting Functions");
+
+    psVector *xTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *yTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *zTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *fTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    xTruth->n = numData;
+    yTruth->n = numData;
+    zTruth->n = numData;
+    fTruth->n = numData;
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 1); // Using known seed
+    for (int i = 0; i < numData; i++) {
+        xTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        yTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        zTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        fTruth->data.F64[i] = setData(xTruth->data.F64[i], yTruth->data.F64[i], zTruth->data.F64[i]);
+    }
+    psFree(rng);
+
+    if (expectedRC == false) {
+        printf("This test should generate an error message, and return NULL.\n");
+    }
+
+    if (flags & TS00_CLIP_FIT) {
+        printf(" performing a clip-fit\n");
+    } else {
+        printf(" performing a non clip-fit\n");
+    }
+
+    if (flags & TS00_POLY_ORD) {
+        printf(" using ordinary polynomials\n");
+        myPoly = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, polyOrderX, polyOrderY, polyOrderZ);
+    }
+
+    if (flags & TS00_X_NULL) {
+        printf(" using a NULL x vector\n");
+    }
+
+    if (flags & TS00_X_F32) {
+        printf(" using a psF32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_X_S32) {
+        printf(" using a psS32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_X_F64) {
+        printf(" using a psF64 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F64);
+    }
+
+
+    if (flags & TS00_Y_NULL) {
+        printf(" using a NULL y vector\n");
+    }
+
+    if (flags & TS00_Y_F32) {
+        printf(" using a psF32 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_Y_S32) {
+        printf(" using a psS32 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_Y_F64) {
+        printf(" using a psF64 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_F64);
+    }
+
+    if (flags & TS00_Z_NULL) {
+        printf(" using a NULL z vector\n");
+    }
+
+    if (flags & TS00_Z_F32) {
+        printf(" using a psF32 z vector\n");
+        z = psVectorCopy(NULL, zTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_Z_S32) {
+        printf(" using a psS32 z vector\n");
+        z = psVectorCopy(NULL, zTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_Z_F64) {
+        printf(" using a psF64 z vector\n");
+        z = psVectorCopy(NULL, zTruth, PS_TYPE_F64);
+    }
+
+
+    if (flags & TS00_F_NULL) {
+        printf(" using a NULL f vector\n");
+    }
+
+    if (flags & TS00_F_F32) {
+        printf(" using a psF32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F32[numData/4]*= 2.0;
+            f->data.F32[numData/2]*= 2.0;
+            f->data.F32[3*numData/4]*= 2.0;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original data %d: (%.1f)\n", i, f->data.F32[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_F_S32) {
+        printf(" using a psS32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_S32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.S32[numData/4]*= 2.0;
+            f->data.S32[numData/2]*= 2.0;
+            f->data.S32[3*numData/4]*= 2.0;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original data %d: (%d)\n", i, f->data.S32[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_F_F64) {
+        printf(" using a psF64 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F64);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F64[numData/4]*= 2.0;
+            f->data.F64[numData/2]*= 2.0;
+            f->data.F64[3*numData/4]*= 2.0;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original data %d: (%.1f)\n", i, f->data.F64[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_FERR_NULL) {
+        printf(" using a NULL fErr vector\n");
+    }
+
+    if (flags & TS00_FERR_F32) {
+        printf(" using a psF32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F32[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_S32) {
+        printf(" using a psS32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_S32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.S32[i] = (psS32) YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_F64) {
+        printf(" using a psF64 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F64);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F64[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_MASK_NULL) {
+        printf(" using a NULL mask vector\n");
+    }
+
+    if (flags & TS00_MASK_U8) {
+        printf(" using a psU8 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_U8);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.U8[i] = 0;
+        }
+    }
+
+    if (flags & TS00_MASK_S32) {
+        printf(" using a psS32 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_S32);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.S32[i] = 0;
+        }
+    }
+
+    psPolynomial3D *rc = NULL;
+    if (flags & TS00_CLIP_FIT) {
+        rc = psVectorClipFitPolynomial3D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y, z);
+    } else {
+        rc = psVectorFitPolynomial3D(myPoly, mask, MASK_VALUE, f, fErr, x, y, z);
+    }
+
+    if (rc == NULL) {
+        if (expectedRC == true) {
+            printf("TEST ERROR: the 3D polynomial fitting function returned NULL.\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            printf("TEST ERROR: the 3D polynomial fitting function returned non-NULL.\n");
+            testStatus = false;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<polyOrderX+1;i++) {
+                for (psS32 j=0;j<polyOrderY+1;j++) {
+                    for (psS32 k=0;k<polyOrderZ+1;k++) {
+                        printf("Polynomial coefficient [%d][%d][%d] is %0.1f\n", i, j, k, myPoly->coeff[i][j][k]);
+                    }
+                }
+            }
+        }
+
+        psVector *result = psPolynomial3DEvalVector(myPoly, xTruth, yTruth, zTruth);
+        for (psS32 i=0 ;i<numData; i++) {
+            // Skip the outliers.
+            if ((i == numData/4) || (i == numData/2) || (i == 3*numData/4)) {
+                continue;
+            }
+            psF32 expectData = fTruth->data.F64[i];
+            psF32 actualData = result->data.F64[i];
+
+            if (fabs(actualData-expectData) > fabs(ERROR_TOLERANCE * expectData)) {
+                printf("TEST ERROR: Fitted data %d: (%.1f), expected was (%.1f)\n",
+                       i, actualData, expectData);
+                testStatus = false;
+            } else {
+                if (VERBOSE) {
+                    printf("GOOD: Fitted data %d: (%.1f), expected was (%.1f)\n",
+                           i, actualData, expectData);
+                }
+            }
+        }
+        psFree(result);
+    }
+
+    psMemCheckCorruption(1);
+    psFree(myPoly);
+    psFree(mask);
+    psFree(x);
+    psFree(y);
+    psFree(z);
+    psFree(f);
+    psFree(xTruth);
+    psFree(yTruth);
+    psFree(zTruth);
+    psFree(fTruth);
+    psFree(fErr);
+    psFree(stats);
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    printFooter(stdout, "psMinimize functions", "3D Polynomial Fitting Functions", testStatus);
+
+    return (testStatus);
+}
+
+/*****************************************************************************
+We test a variety of polynomial fitting routines, types, and polynomial types
+here:
+    F32 tests: Ordinary polys, non-clip fit
+    F64 tests: Ordinary polys, non-clip fit
+    F32 tests: Chebyshev polys, non-clip fit
+    F64 tests: Chebyshev polys, non-clip fit
+    F32 tests: Ordinary polys, clip fit
+    F64 tests: Ordinary polys, clip fit
+    F32 tests: Chebyshev polys, clip fit
+    F64 tests: Chebyshev polys, clip fit
+ *****************************************************************************/
+psS32 main()
+{
+    psBool testStatus = true;
+    psLogSetFormat("HLNM");
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("psVectorClipFitPolynomial3D", 0);
+    psTraceSetLevel("VectorFitPolynomial3DOrd", 0);
+    psTraceSetLevel("psVectorFitPolynomial3D", 0);
+
+    printPositiveTestHeader(stdout, "psMinimize functions: 3D Polynomial Fitting Functions", "");
+
+    //
+    // F32 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+
+    //
+    // F64 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+
+    //
+    // F32 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_Z_NULL | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+
+    //
+    // F64 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_Z_NULL | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false);
+
+    printFooter(stdout, "psMinimize functions: 3D Polynomial Fitting Functions", "", testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolyFit4D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolyFit4D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolyFit4D.c	(revision 22158)
@@ -0,0 +1,667 @@
+/*****************************************************************************
+This routine must ensure that various psLib functions which fit 4D polynomials
+to data work correctly.  There is a function genericTest() which creates
+vectors of data points (x and f), and populates them with the values from an
+arbitrary function setData().  It then calls appropriate 4D fitting function.
+It then evaluates the polynomial with the coefficients generated above and
+determines if they are within an error tolerance of the expected values.
+ *****************************************************************************/
+#include <stdio.h>
+#include <math.h>
+#include "pslib.h"
+#include "psTest.h"
+#define NUM_DATA 200
+#define POLY_ORDER_X 1
+#define POLY_ORDER_Y 1
+#define POLY_ORDER_Z 1
+#define POLY_ORDER_T 1
+#define A 100.0
+#define B 2.0
+#define C 3.0
+#define D 4.0
+#define E 5.0
+#define F 6.0
+#define H 3.0
+#define J 3.0
+#define K 1.0
+#define L 5.0
+#define M 4.0
+#define N 3.0
+#define O 2.0
+#define P 1.0
+#define Q 5.0
+#define ERROR_TOLERANCE 0.05
+#define YERR 0.1
+#define VERBOSE 0
+#define NUM_ITERATIONS 5
+#define CLIP_SIGMA 3.0
+#define OUTLIERS true
+#define MASK_VALUE 1
+
+#define TS00_F_NULL  0x00000001
+#define TS00_F_F32  0x00000002
+#define TS00_F_F64  0x00000004
+#define TS00_F_S32  0x00000008
+#define TS00_X_NULL  0x00000010
+#define TS00_X_F32  0x00000020
+#define TS00_X_F64  0x00000040
+#define TS00_X_S32  0x00000080
+#define TS00_FERR_NULL  0x00000100
+#define TS00_FERR_F32  0x00000200
+#define TS00_FERR_F64  0x00000400
+#define TS00_FERR_S32  0x00000800
+#define TS00_MASK_NULL  0x00001000
+#define TS00_MASK_U8  0x00002000
+#define TS00_MASK_S32  0x00004000
+#define TS00_POLY_ORD  0x00008000
+#define TS00_POLY_CHEB  0x00010000
+#define TS00_CLIP_FIT  0x00020000
+#define TS00_Y_NULL  0x00100000
+#define TS00_Y_F32  0x00200000
+#define TS00_Y_F64  0x00400000
+#define TS00_Y_S32  0x00800000
+#define TS00_Z_NULL  0x01000000
+#define TS00_Z_F32  0x02000000
+#define TS00_Z_F64  0x04000000
+#define TS00_Z_S32  0x08000000
+#define TS00_T_NULL  0x10000000
+#define TS00_T_F32  0x20000000
+#define TS00_T_F64  0x40000000
+#define TS00_T_S32  0x80000000
+
+psF32 setData(psF32 x, psF32 y, psF32 z, psF32 t)
+{
+    if (0) {
+        // Linear case, for testing.
+        return(A + (B * x) + (C * y) + (D * z) + (E * t));
+    } else {
+        #if 0
+        return(A + (B * x) + (C * y) + (D * z) + (E * t) +
+               (F * x * x) + (H * y * y) + (J * z * z) + (K * t * t) +
+               (L * x * y) + (M * x * z) + (N * x * t) + (O * y * z) + (P * y * t) + (Q * z * t));
+        #else
+
+        return A + (B * x) + (C * y) + (D * z) + (E * t) + (F * x * y);
+        #endif
+
+    }
+}
+
+bool genericTest(
+    psU32 flags,
+    psS32 polyOrderX,
+    psS32 polyOrderY,
+    psS32 polyOrderZ,
+    psS32 polyOrderT,
+    psS32 numData,
+    psBool expectedRC)
+{
+    psS32 currentId = psMemGetId();
+    bool testStatus = true;
+    psS32 memLeaks = 0;
+    psPolynomial4D *myPoly = NULL;
+    psVector *x = NULL;
+    psVector *y = NULL;
+    psVector *z = NULL;
+    psVector *t = NULL;
+    psVector *f = NULL;
+    psVector *mask = NULL;
+    psVector *fErr = NULL;
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    stats->clipSigma = CLIP_SIGMA;
+    stats->clipIter = NUM_ITERATIONS;
+
+    printPositiveTestHeader(stdout, "psMinimize functions", "4D Polynomial Fitting Functions");
+
+    psVector *xTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *yTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *zTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *tTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *fTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    xTruth->n = numData;
+    yTruth->n = numData;
+    zTruth->n = numData;
+    tTruth->n = numData;
+    fTruth->n = numData;
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 1); // Using known seed
+    for (int i = 0; i < numData; i++) {
+        xTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        yTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        zTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        tTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        fTruth->data.F64[i] = setData(xTruth->data.F64[i], yTruth->data.F64[i],
+                                      zTruth->data.F64[i], tTruth->data.F64[i]);
+    }
+    psFree(rng);
+
+    if (expectedRC == false) {
+        printf("This test should generate an error message, and return NULL.\n");
+    }
+
+    if (flags & TS00_CLIP_FIT) {
+        printf(" performing a clip-fit\n");
+    } else {
+        printf(" performing a non clip-fit\n");
+    }
+
+    if (flags & TS00_POLY_ORD) {
+        printf(" using ordinary polynomials\n");
+        myPoly = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, polyOrderX, polyOrderY,
+                                     polyOrderZ, polyOrderT);
+
+        #if 1
+
+        for (int ix = 0; ix < polyOrderX + 1; ix++) {
+            for (int iy = 0; iy < polyOrderY + 1; iy++) {
+                for (int iz = 0; iz < polyOrderZ + 1; iz++) {
+                    for (int it = 0; it < polyOrderT + 1; it++) {
+                        myPoly->mask[ix][iy][iz][it] = 0xff; // Mask it out
+                    }
+                }
+            }
+        }
+
+        // Put these back in
+        myPoly->mask[0][0][0][0] = 0;   // A
+        myPoly->mask[1][0][0][0] = 0;   // B * x
+        myPoly->mask[0][1][0][0] = 0;   // C * y
+        myPoly->mask[0][0][1][0] = 0;   // D * z
+        myPoly->mask[0][0][0][1] = 0;   // E * t
+        myPoly->mask[1][1][0][0] = 0;   // F * xy
+        #endif
+
+    }
+
+    if (flags & TS00_X_NULL) {
+        printf(" using a NULL x vector\n");
+    }
+
+    if (flags & TS00_X_F32) {
+        printf(" using a psF32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_X_S32) {
+        printf(" using a psS32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_X_F64) {
+        printf(" using a psF64 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F64);
+    }
+
+
+    if (flags & TS00_Y_NULL) {
+        printf(" using a NULL y vector\n");
+    }
+
+    if (flags & TS00_Y_F32) {
+        printf(" using a psF32 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_Y_S32) {
+        printf(" using a psS32 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_Y_F64) {
+        printf(" using a psF64 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_F64);
+    }
+
+    if (flags & TS00_Z_NULL) {
+        printf(" using a NULL z vector\n");
+    }
+
+    if (flags & TS00_Z_F32) {
+        printf(" using a psF32 z vector\n");
+        z = psVectorCopy(NULL, zTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_Z_S32) {
+        printf(" using a psS32 z vector\n");
+        z = psVectorCopy(NULL, zTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_Z_F64) {
+        printf(" using a psF64 z vector\n");
+        z = psVectorCopy(NULL, zTruth, PS_TYPE_F64);
+    }
+
+    if (flags & TS00_T_NULL) {
+        printf(" using a NULL t vector\n");
+    }
+
+    if (flags & TS00_T_F32) {
+        printf(" using a psF32 t vector\n");
+        t = psVectorCopy(NULL, tTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_T_S32) {
+        printf(" using a psS32 t vector\n");
+        t = psVectorCopy(NULL, tTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_T_F64) {
+        printf(" using a psF64 t vector\n");
+        t = psVectorCopy(NULL, tTruth, PS_TYPE_F64);
+    }
+
+
+    if (flags & TS00_F_NULL) {
+        printf(" using a NULL f vector\n");
+    }
+
+    if (flags & TS00_F_F32) {
+        printf(" using a psF32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F32[numData/4] *= 2.0;
+            f->data.F32[numData/2] *= 2.0;
+            f->data.F32[3*numData/4] *= 2.0;
+        }
+    }
+
+    if (flags & TS00_F_S32) {
+        printf(" using a psS32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_S32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.S32[numData/4] *= 2.0;
+            f->data.S32[numData/2] *= 2.0;
+            f->data.S32[3*numData/4] *= 2.0;
+        }
+    }
+
+    if (flags & TS00_F_F64) {
+        printf(" using a psF64 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F64);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F64[numData/4] *= 2.0;
+            f->data.F64[numData/2] *= 2.0;
+            f->data.F64[3*numData/4] *= 2.0;
+        }
+    }
+
+    if (flags & TS00_FERR_NULL) {
+        printf(" using a NULL fErr vector\n");
+    }
+
+    if (flags & TS00_FERR_F32) {
+        printf(" using a psF32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F32[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_S32) {
+        printf(" using a psS32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_S32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.S32[i] = (psS32) YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_F64) {
+        printf(" using a psF64 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F64);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F64[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_MASK_NULL) {
+        printf(" using a NULL mask vector\n");
+    }
+
+    if (flags & TS00_MASK_U8) {
+        printf(" using a psU8 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_U8);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.U8[i] = 0;
+        }
+    }
+
+    if (flags & TS00_MASK_S32) {
+        printf(" using a psS32 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_S32);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.S32[i] = 0;
+        }
+    }
+
+    psPolynomial4D *rc = NULL;
+    if (flags & TS00_CLIP_FIT) {
+        rc = psVectorClipFitPolynomial4D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y, z, t);
+    } else {
+        rc = psVectorFitPolynomial4D(myPoly, mask, MASK_VALUE, f, fErr, x, y, z, t);
+    }
+
+    if (rc == NULL) {
+        if (expectedRC == true) {
+            printf("TEST ERROR: the 4D polynomial fitting function returned NULL.\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            printf("TEST ERROR: the 4D polynomial fitting function returned non-NULL.\n");
+            testStatus = false;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<polyOrderX+1;i++) {
+                for (psS32 j=0;j<polyOrderY+1;j++) {
+                    for (psS32 k=0;k<polyOrderZ+1;k++) {
+                        for (psS32 l=0;l<polyOrderT+1;l++) {
+                            printf("Polynomial coefficient [%d][%d][%d][%d] is %0.1f\n",
+                                   i, j, k, l, myPoly->coeff[i][j][k][l]);
+                        }
+                    }
+                }
+            }
+        }
+
+        psVector *result = psPolynomial4DEvalVector(myPoly, xTruth, yTruth, zTruth, tTruth);
+        for (int i=0;i<numData; i++) {
+            // Skip the outliers.
+            if ((i == numData/4) || (i == numData/2) || (i == 3*numData/4)) {
+                continue;
+            }
+            psF32 expectData = fTruth->data.F64[i];
+            psF32 actualData = result->data.F64[i];
+
+            if (fabs(actualData-expectData) > fabs(ERROR_TOLERANCE * expectData)) {
+                printf("TEST ERROR: Fitted data %d: (%f), expected was (%f)\n",
+                       i, actualData, expectData);
+                testStatus = false;
+            } else {
+                if (VERBOSE) {
+                    printf("GOOD: Fitted data %d: (%.1f), expected was (%.1f)\n",
+                           i, actualData, expectData);
+                }
+            }
+        }
+        psFree(result);
+    }
+
+    psMemCheckCorruption(1);
+    psFree(myPoly);
+    psFree(mask);
+    psFree(x);
+    psFree(y);
+    psFree(z);
+    psFree(t);
+    psFree(f);
+    psFree(xTruth);
+    psFree(yTruth);
+    psFree(zTruth);
+    psFree(tTruth);
+    psFree(fTruth);
+    psFree(fErr);
+    psFree(stats);
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    printFooter(stdout, "psMinimize functions", "4D Polynomial Fitting Functions", testStatus);
+
+    return (testStatus);
+}
+
+/*****************************************************************************
+We test a variety of polynomial fitting routines, types, and polynomial types
+here:
+    F32 tests: Ordinary polys, non-clip fit
+    F64 tests: Ordinary polys, non-clip fit
+    F32 tests: Chebyshev polys, non-clip fit
+    F64 tests: Chebyshev polys, non-clip fit
+    F32 tests: Ordinary polys, clip fit
+    F64 tests: Ordinary polys, clip fit
+    F32 tests: Chebyshev polys, clip fit
+    F64 tests: Chebyshev polys, clip fit
+ *****************************************************************************/
+int main()
+{
+    psBool testStatus = true;
+    psLogSetFormat("HLNM");
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("psVectorClipFitPolynomial4D", 0);
+    psTraceSetLevel("VectorFitPolynomial4DOrd", 0);
+    psTraceSetLevel("psVectorFitPolynomial4D", 0);
+
+    printPositiveTestHeader(stdout, "psMinimize functions: 4D Polynomial Fitting Functions", "");
+
+    //
+    // F32 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, true);
+
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_NULL
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_NULL | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, true);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, true);
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F64
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, false);
+
+    //
+    // F64 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, true);
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_NULL
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_NULL | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, true);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, true);
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F32
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                              POLY_ORDER_T, NUM_DATA, false);
+
+    //
+    // F32 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, true);
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_NULL
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_NULL | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F64
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                              | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+
+    //
+    // F64 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, true);
+    // Some Vectors NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, true);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_NULL
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_NULL | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    // F-vector NULL
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    // Mismatch vector types
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F32
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+    testStatus &= genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                              | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                              POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false);
+
+    printf("Status: %x\n", testStatus);
+
+    printFooter(stdout, "psMinimize functions: 4D Polynomial Fitting Functions", "", testStatus);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolynomial.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolynomial.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolynomial.c	(revision 22158)
@@ -0,0 +1,353 @@
+/** tst_Func00.c
+*
+*    This routine must ensure that the psPolynomial structures are
+*    allocated and deallocated by the psPolynomialXXXlloc() procedures.
+*    It also calls the various psPolynomialXXXEval() procedures.
+*
+*    The F32 and F64 polynomials are tested for all orders (1 - 4) and for
+*    both ordinary and chebyshev polynomials.
+*
+*    NOTE: This test code requries the stdout file to verify that the results
+*    are good.
+*
+*    XXX: Modify these tests so that polynomials with a variety of different
+*    orders are created.
+* 
+*    XXX: Compare to FLT_EPSILON
+* 
+*    @version $Revision: 1.1 $  $Name: not supported by cvs2svn $
+*    @date $Date: 2006-02-02 21:05:51 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*
+*****************************************************************************/
+#include <stdio.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+
+// Defines
+#define ORDER    3
+
+static psS32 testPolynomial1DAlloc(void);
+static psS32 testPolynomial2DAlloc(void);
+static psS32 testPolynomial3DAlloc(void);
+static psS32 testPolynomial4DAlloc(void);
+
+testDescription tests[] = {
+                              {testPolynomial1DAlloc,578,"psPolynomial1DAlloc",0,false},
+                              {testPolynomial2DAlloc,578,"psPolynomial2DAlloc",0,false},
+                              {testPolynomial3DAlloc,578,"psPolynomial3DAlloc",0,false},
+                              {testPolynomial4DAlloc,578,"psPolynomial4DAlloc",0,false},
+                              {NULL}
+                          };
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+
+    return !runTestSuite(stderr,"psPolynomialXD", tests, argc, argv);
+}
+
+
+// This test will allocate a 1D polynomial and verify the structure allocated
+psS32 testPolynomial1DAlloc(void)
+{
+    psPolynomial1D*  my1DPoly  = NULL;
+
+    // Allocate polynomial
+    my1DPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, ORDER);
+    // Verify structure allocated
+    if(my1DPoly == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Returned NULL not expected");
+        return 1;
+    }
+    // Verify polynomial structure members set properly
+    if(my1DPoly->nX != ORDER) {
+        psError(PS_ERR_UNKNOWN,true,"Number of terms %d not as expected %d",
+                my1DPoly->nX, ORDER);
+        return 2;
+    }
+    if(my1DPoly->type != PS_POLYNOMIAL_ORD) {
+        psError(PS_ERR_UNKNOWN,true,"Type %d not as expected %d",
+                my1DPoly->type, PS_POLYNOMIAL_ORD);
+        return 3;
+    }
+    for(psS32 i = 0; i < ORDER+1; i++) {
+        if(my1DPoly->coeff[i] != 0.0) {
+            psError(PS_ERR_UNKNOWN,true,"Coeff[%d] %lg not as expected %lg",
+                    i, my1DPoly->coeff[i], 0.0);
+            return 4;
+        }
+        if(my1DPoly->coeffErr[i] != 0.0) {
+            psError(PS_ERR_UNKNOWN,true,"CoeffErr[%d] %lg not as expected %lg",
+                    i, my1DPoly->coeffErr[i], 0.0);
+            return 5;
+        }
+        if(my1DPoly->mask[i] != 0) {
+            psError(PS_ERR_UNKNOWN,true,"Mask[%d] %d not as expected %d",
+                    i, my1DPoly->mask[i], 0);
+            return 6;
+        }
+    }
+    psFree(my1DPoly);
+
+    if (0) {
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if(psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, -1) != NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Returned structure but expected NULL");
+            return 7;
+        }
+    }
+
+    return 0;
+}
+
+// This test will allocate a 2D polynomial and verify the structure allocated
+psS32 testPolynomial2DAlloc(void)
+{
+    psPolynomial2D* my2DPoly = NULL;
+
+    // Allocate polynomial
+    my2DPoly = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, ORDER,ORDER+1);
+    // Verify structure allocated
+    if(my2DPoly == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Returned NULL not expected");
+        return 1;
+    }
+    // Verify polynomial structure members set properly
+    if(my2DPoly->nX != ORDER) {
+        psError(PS_ERR_UNKNOWN,true,"Number of terms %d not as expected %d",
+                my2DPoly->nX, ORDER);
+        return 2;
+    }
+    // Verify polynomial structure members set properly
+    if(my2DPoly->nY != ORDER+1) {
+        psError(PS_ERR_UNKNOWN,true,"Number of terms %d not as expected %d",
+                my2DPoly->nY, ORDER+1);
+        return 3;
+    }
+    if(my2DPoly->type != PS_POLYNOMIAL_ORD) {
+        psError(PS_ERR_UNKNOWN,true,"Type %d not as expected %d",
+                my2DPoly->type, PS_POLYNOMIAL_ORD);
+        return 4;
+    }
+
+    for(psS32 i = 0; i < ORDER+1; i++) {
+        for(psS32 j = 0; j < ORDER+2; j++) {
+            if(fabs(my2DPoly->coeff[i][j]) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN,true,"Coeff[%d][%d] %lg not as expected %lg",
+                        i, j, my2DPoly->coeff[i][j], 0.0);
+                return 5;
+            }
+            if(my2DPoly->coeffErr[i][j] != 0.0) {
+                psError(PS_ERR_UNKNOWN,true,"CoeffErr[%d][%d] %lg not as expected %lg",
+                        i, j, my2DPoly->coeffErr[i][j], 0.0);
+                return 6;
+            }
+            if(my2DPoly->mask[i][j] != 0) {
+                psError(PS_ERR_UNKNOWN,true,"Mask[%d][%d] %d not as expected %d",
+                        i, j, my2DPoly->mask[i][j], 0);
+                return 7;
+            }
+        }
+    }
+    psFree(my2DPoly);
+
+    if (0) {
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if(psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, -1, 1) != NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Returned structure but expected NULL");
+            return 8;
+        }
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if(psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 1, -1) != NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Returned structure but expected NULL");
+            return 9;
+        }
+    }
+    return 0;
+}
+
+// This test will allocate a 3D polynomial and verify the structure allocated
+psS32 testPolynomial3DAlloc(void)
+{
+    psPolynomial3D* my3DPoly = NULL;
+
+    // Allocate polynomial
+    my3DPoly = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, ORDER, ORDER+1, ORDER+2);
+    // Verify structure allocated
+    if(my3DPoly == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Returned NULL not expected");
+        return 1;
+    }
+    // Verify polynomial structure members set properly
+    if(my3DPoly->nX != ORDER) {
+        psError(PS_ERR_UNKNOWN,true,"Number of terms %d not as expected %d",
+                my3DPoly->nX, ORDER);
+        return 2;
+    }
+    // Verify polynomial structure members set properly
+    if(my3DPoly->nY != ORDER+1) {
+        psError(PS_ERR_UNKNOWN,true,"Number of terms %d not as expected %d",
+                my3DPoly->nY, ORDER+1);
+        return 3;
+    }
+    // Verify polynomial structure members set properly
+    if(my3DPoly->nZ != ORDER+2) {
+        psError(PS_ERR_UNKNOWN,true,"Number of terms %d not as expected %d",
+                my3DPoly->nZ, ORDER+2);
+        return 4;
+    }
+    if(my3DPoly->type != PS_POLYNOMIAL_ORD) {
+        psError(PS_ERR_UNKNOWN,true,"Type %d not as expected %d",
+                my3DPoly->type, PS_POLYNOMIAL_ORD);
+        return 5;
+    }
+    for(psS32 i = 0; i < ORDER+1; i++) {
+        for(psS32 j = 0; j < ORDER+2; j++) {
+            for(psS32 k = 0; k < ORDER+3; k++) {
+                if(my3DPoly->coeff[i][j][k] != 0.0) {
+                    psError(PS_ERR_UNKNOWN,true,"Coeff[%d][%d][%d] %lg not as expected %lg",
+                            i, j, k, my3DPoly->coeff[i][j][k], 0.0);
+                    return 6;
+                }
+                if(my3DPoly->coeffErr[i][j][k] != 0.0) {
+                    psError(PS_ERR_UNKNOWN,true,"CoeffErr[%d][%d][%d] %lg not as expected %lg",
+                            i, j, k, my3DPoly->coeffErr[i][j][k], 0.0);
+                    return 7;
+                }
+                if(my3DPoly->mask[i][j][k] != 0) {
+                    psError(PS_ERR_UNKNOWN,true,"Mask[%d][%d] %d not as expected %d",
+                            i, j, k, my3DPoly->mask[i][j][k], 0);
+                    return 8;
+                }
+            }
+        }
+    }
+    psFree(my3DPoly);
+
+    if (0) {
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if(psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, -1, 1, 1) != NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Returned structure but expected NULL");
+            return 9;
+        }
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if(psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, 1, -1, 1) != NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Returned structure but expected NULL");
+            return 10;
+        }
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if(psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, 1, 1, -1) != NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Returned structure but expected NULL");
+            return 11;
+        }
+    }
+
+    return 0;
+}
+
+// This test will allocate a 4D polynomial and verify the structure allocated
+psS32 testPolynomial4DAlloc(void)
+{
+    psPolynomial4D* my4DPoly = NULL;
+
+    // Allocate polynomial
+    my4DPoly = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, ORDER,ORDER+1,ORDER+2,ORDER+3);
+    // Verify structure allocated
+    if(my4DPoly == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Returned NULL not expected");
+        return 1;
+    }
+    // Verify polynomial structure members set properly
+    if(my4DPoly->nX != ORDER) {
+        psError(PS_ERR_UNKNOWN,true,"Number of terms %d not as expected %d",
+                my4DPoly->nX, ORDER);
+        return 2;
+    }
+    // Verify polynomial structure members set properly
+    if(my4DPoly->nY != ORDER+1) {
+        psError(PS_ERR_UNKNOWN,true,"Number of terms %d not as expected %d",
+                my4DPoly->nX, ORDER+1);
+        return 3;
+    }
+    // Verify polynomial structure members set properly
+    if(my4DPoly->nZ != ORDER+2) {
+        psError(PS_ERR_UNKNOWN,true,"Number of terms %d not as expected %d",
+                my4DPoly->nZ, ORDER+2);
+        return 4;
+    }
+    // Verify polynomial structure members set properly
+    if(my4DPoly->nT != ORDER+3) {
+        psError(PS_ERR_UNKNOWN,true,"Number of terms %d not as expected %d",
+                my4DPoly->nT, ORDER+3);
+        return 5;
+    }
+    if(my4DPoly->type != PS_POLYNOMIAL_ORD) {
+        psError(PS_ERR_UNKNOWN,true,"Type %d not as expected %d",
+                my4DPoly->type, PS_POLYNOMIAL_ORD);
+        return 6;
+    }
+    for(psS32 i = 0; i < ORDER+1; i++) {
+        for(psS32 j = 0; j < ORDER+2; j++) {
+            for(psS32 k = 0; k < ORDER+3; k++) {
+                for(psS32 l = 0; l < ORDER+4; l++) {
+                    if(my4DPoly->coeff[i][j][k][l] != 0.0) {
+                        psError(PS_ERR_UNKNOWN,true,"Coeff[%d][%d][%d][%d] %lg not as expected %lg",
+                                i, j, k, l, my4DPoly->coeff[i][j][k][l], 0.0);
+                        return 7;
+                    }
+                    if(my4DPoly->coeffErr[i][j][k][l] != 0.0) {
+                        psError(PS_ERR_UNKNOWN,true,"CoeffErr[%d][%d][%d][l] %lg not as expected %lg",
+                                i, j, k, l, my4DPoly->coeffErr[i][j][k][l], 0.0);
+                        return 8;
+                    }
+                    if(my4DPoly->mask[i][j][k][l] != 0) {
+                        psError(PS_ERR_UNKNOWN,true,"Mask[%d][%d][%d][%d] %d not as expected %d",
+                                i, j, k, l, my4DPoly->mask[i][j][k][l], 0);
+                        return 9;
+                    }
+                }
+            }
+        }
+    }
+    psFree(my4DPoly);
+
+    if (0) {
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if(psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, -1, 1, 1, 1) != NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Returned structure but expected NULL");
+            return 10;
+        }
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if(psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, 1, -1, 1, 1) != NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Returned structure but expected NULL");
+            return 11;
+        }
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if(psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, 1, 1, -1, 1) != NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Returned structure but expected NULL");
+            return 12;
+        }
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if(psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, 1, 1, 1, -1) != NULL) {
+            psError(PS_ERR_UNKNOWN,true,"Returned structure but expected NULL");
+            return 13;
+        }
+    }
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolynomialEval1D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolynomialEval1D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolynomialEval1D.c	(revision 22158)
@@ -0,0 +1,197 @@
+/** tst_psFunc08.c
+*
+*  This test driver will exercise the psPolynomialXDEval functions for both
+*  ORD and CHEB type polynomials.
+*
+*  @version  $Revision: 1.2 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2006-02-24 23:43:15 $
+*
+*  XXX: Probably should test single- and multi-dimensional polynomials in
+*  which one diminsion is constant (n == 1).
+*
+*  XXX: define ORDERS, not TERMS
+*
+*
+* Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*
+***************************************************************************/
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+#define  TERMS        4
+#define  TESTPOINTS   5
+#define  ERROR_TOL    0.001
+
+static psS32 testPoly1DEval(void);
+static psS32 testPoly1DEvalVector(void);
+
+testDescription tests[] = {
+                              {testPoly1DEval,000,"psPolynomial1DEval",0,false},
+                              {testPoly1DEvalVector,000,"psPolynomial1DEvalVector",0,false},
+                              {NULL}
+                          };
+
+psF32 poly1DCoeff[TERMS]        = { -4.3, 2.3, -3.2, 1.9};
+psF64 Dpoly1DCoeff[TERMS]        = { -4.3, 2.3, -3.2, 1.9};
+psF32 poly1DMask[TERMS]         = {    0,   0,    1,   0  };
+
+psF32 poly1DXValue[TESTPOINTS]   = { 2.550000,    -9.8000,   0.00134,   -12.2500,   0.000};
+psF64 Dpoly1DXValue[TESTPOINTS]  = { 2.550000,    -9.8000,   0.00134,   -12.2500,   0.000};
+psF32 poly1DXResult[TESTPOINTS]  = {33.069613, -1815.1048, -4.296918, -3525.1797, -4.3000};
+psF64 Dpoly1DXResult[TESTPOINTS] = {33.069613, -1815.1048, -4.296918, -3525.1797, -4.3000};
+
+psF32 poly1DXChebValue[TESTPOINTS]   = { -0.99,    -0.33,     0.125,    0.564,    0.875};
+psF64 Dpoly1DXChebValue[TESTPOINTS]  = { -0.99,    -0.33,     0.125,    0.564,    0.875};
+psF32 poly1DXChebResult[TESTPOINTS]  = { -1.401196, 1.016252, 0.257813, 0.089625, 1.429688};
+psF64 Dpoly1DXChebResult[TESTPOINTS] = { -1.401196, 1.016252, 0.257813, 0.089625, 1.429688};
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+
+    return !runTestSuite(stderr,"psPolynomialXDEval", tests, argc, argv);
+}
+
+// This test will verify operation of 1D polynomial evaluation
+psS32 testPoly1DEval(void)
+{
+    psF64  result;
+    psF64  resultCheb;
+
+    // Allocate polynomial structure
+    psPolynomial1D*  polyOrd = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, TERMS-1);
+    psPolynomial1D*  polyCheb = psPolynomial1DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1);
+    // Set polynomial members
+    for(psS32 i = 0; i < TERMS; i++) {
+        polyOrd->coeff[i] = poly1DCoeff[i];
+        polyOrd->mask[i]  = poly1DMask[i];
+        polyCheb->coeff[i] = 1.0;
+        polyCheb->mask[i]  = poly1DMask[i];
+    }
+    // Evaluate test points and verify results
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+        result = psPolynomial1DEval(polyOrd,poly1DXValue[i]);
+        if(fabs(poly1DXResult[i]-result) > ERROR_TOL ) {
+            psError(PS_ERR_UNKNOWN,true,"Evaluated value %g not as expected %g",
+                    result, poly1DXResult[i]);
+            return i;
+        }
+        resultCheb = psPolynomial1DEval(polyCheb,poly1DXChebValue[i]);
+        if(fabs(poly1DXChebResult[i]-resultCheb) > ERROR_TOL ) {
+            psError(PS_ERR_UNKNOWN,true,"Evaluated Chebyshev value %lg not as expected %lg",
+                    resultCheb, poly1DXChebResult[i]);
+            return 5*i;
+        }
+    }
+    psFree(polyOrd);
+    psFree(polyCheb);
+
+    // Allocate polynomial with invalid type
+    polyOrd = psPolynomial1DAlloc(99, TERMS-1);
+    // Attempt to evaluation invalid polynomial type
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message invalid type");
+    result = psPolynomial1DEval(polyOrd,0.0);
+    if ( !isnan(result) ) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NAN for invalid polynomial type");
+        return 20;
+    }
+    psFree(polyOrd);
+
+    return 0;
+}
+
+
+psS32 testPoly1DEvalVector(void)
+{
+    // Allocate polynomial
+    psPolynomial1D* polyOrd = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, TERMS-1);
+    psPolynomial1D* polyCheb = psPolynomial1DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1);
+
+    // Set polynomial members
+    for(psS32 i = 0; i < TERMS; i++) {
+        polyOrd->coeff[i] = poly1DCoeff[i];
+        polyOrd->mask[i]  = poly1DMask[i];
+        polyCheb->coeff[i] = 1.0;
+        polyCheb->mask[i]  = poly1DMask[i];
+    }
+
+    // Create input vectors
+    psVector* inputOrd = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    psVector* inputCheb = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+        inputOrd->data.F64[i] = poly1DXValue[i];
+        inputCheb->data.F64[i] = poly1DXChebValue[i];
+        inputOrd->n++;
+        inputCheb->n++;
+    }
+
+    // Evaluate the vectors
+    psVector* outputOrd = psPolynomial1DEvalVector(polyOrd, inputOrd);
+    if(outputOrd == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Unexpected return of NULL.");
+        return 1;
+    }
+    if(outputOrd->type.type != PS_TYPE_F64) {
+        psError(PS_ERR_UNKNOWN,true,"Output vector of type %d expected %d",
+                outputOrd->type.type, PS_TYPE_F64);
+        return 2;
+    }
+    psVector* outputCheb = psPolynomial1DEvalVector(polyCheb, inputCheb);
+    if(outputCheb == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Unexpected return of NULL.");
+        return 1;
+    }
+    if(outputCheb->type.type != PS_TYPE_F64) {
+        psError(PS_ERR_UNKNOWN,true,"Output vector of type %d expected %d",
+                outputCheb->type.type, PS_TYPE_F64);
+        return 2;
+    }
+
+    // Verify the results
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+        if(fabs(poly1DXResult[i]-outputOrd->data.F64[i]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"Result[%d] %lg not equal to expected %lg",
+                    i, outputOrd->data.F64[i], poly1DXResult[i]);
+            return i*5;
+        }
+        if(fabs(poly1DXChebResult[i]-outputCheb->data.F64[i]) > ERROR_TOL) {
+            psError(PS_ERR_UNKNOWN,true,"ResultCheb[%d] %lg not equal to expected %lg",
+                    i, outputCheb->data.F64[i], poly1DXChebResult[i]);
+            return i*10;
+        }
+    }
+
+    // Attempt to invoke function with null polynomial
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL polynomial");
+    if(psPolynomial1DEvalVector(NULL, inputOrd) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Return of NULL expected for NULL polynomial");
+        return 60;
+    }
+
+    // Attempt to invoke function with null input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL input vector");
+    if(psPolynomial1DEvalVector(polyOrd,NULL) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Return of NULL expected for NULL input vector");
+        return 61;
+    }
+
+    // Attempt to invoke function with a non F64 type input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid input type");
+    inputOrd->type.type = PS_TYPE_U8;
+    if(psPolynomial1DEvalVector(polyOrd,inputOrd) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Return NULL expected for non-F64 input vector");
+        return 62;
+    }
+    inputOrd->type.type = PS_TYPE_F64;
+
+    psFree(inputOrd);
+    psFree(inputCheb);
+    psFree(outputOrd);
+    psFree(outputCheb);
+    psFree(polyOrd);
+    psFree(polyCheb);
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolynomialEval2D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolynomialEval2D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolynomialEval2D.c	(revision 22158)
@@ -0,0 +1,247 @@
+/** tst_psFunc09.c
+*
+*  This test driver will exercise the psPolynomialXDEval functions for both
+*  ORD and CHEB type polynomials.
+*
+*  @version  $Revision: 1.2 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2006-02-24 23:43:15 $
+*
+* Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*
+***************************************************************************/
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+#define  TERMS        4
+#define  TESTPOINTS   5
+#define  ERROR_TOL    0.001
+
+static psS32 testPoly2DEval(void);
+static psS32 testPoly2DEvalVector(void);
+
+testDescription tests[] = {
+                              {testPoly2DEval,583,"psPolynomial2DEval",true,false},
+                              {testPoly2DEvalVector,000,"psPolynomial2DEvalVector",true,false},
+                              {NULL}
+                          };
+
+psF32 poly2DCoeff[TERMS][TERMS]   = {  { -4.3,  2.3, -3.2,  1.9},
+                                       {  1.2,  0.7, -0.3,  1.3},
+                                       {  0.4, -2.9,  0.8, -3.1},
+                                       { -1.1,  2.1,  1.9,  0.6}
+                                    };
+psF64 Dpoly2DCoeff[TERMS][TERMS]  = {  { -4.3,  2.3, -3.2,  1.9},
+                                       {  1.2,  0.7, -0.3,  1.3},
+                                       {  0.4, -2.9,  0.8, -3.1},
+                                       { -1.1,  2.1,  1.9,  0.6}
+                                    };
+psF32 poly2DMask[TERMS][TERMS]    = {  {  0,    0,    0,    1},
+                                       {  0,    0,    1,    0},
+                                       {  1,    0,    0,    0},
+                                       {  0,    0,    0,    1}
+                                    };
+
+psF32 poly2DXYValue[TESTPOINTS][2] = {  {  1.40,  0.55},
+                                        { -0.55,  1.40},
+                                        {  0.00,  2.34},
+                                        { -0.88,  0.00},
+                                        {  3.45, -0.78}
+                                     };
+psF32 Dpoly2DXYValue[TESTPOINTS][2] = {  {  1.40,  0.55},
+                                      { -0.55,  1.40},
+                                      {  0.00,  2.34},
+                                      { -0.88,  0.00},
+                                      {  3.45, -0.78}
+                                      };
+psF32 poly2DResult[TESTPOINTS] = {  -3.415938, -14.765687, -16.43992, -4.606381, -22.650702 };
+psF64 Dpoly2DResult[TESTPOINTS] = {  -3.415938, -14.765687, -16.43992, -4.606381, -22.650702 };
+
+psF32 poly2DXYChebValue[TESTPOINTS][2] = {  {  0.500,  0.500},
+        {  0.000,  0.250},
+        { -0.250,  0.000},
+        {  0.990,  0.150},
+        {  0.333, -0.666}
+                                         };
+psF32 Dpoly2DXYChebValue[TESTPOINTS][2] = {  {  0.500,  0.500},
+        {  0.000,  0.250},
+        { -0.250,  0.000},
+        {  0.990,  0.150},
+        {  0.333, -0.666}
+                                          };
+psF32 poly2DChebResult[TESTPOINTS] = {  0.750000, 1.687500, 0.625000, -0.113040, 0.386786 };
+psF32 Dpoly2DChebResult[TESTPOINTS] = {  0.750000, 1.687500, 0.625000, -0.113040, 0.386786 };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+
+    return !runTestSuite(stderr,"psPolynomialXDEval", tests, argc, argv);
+}
+
+// This test will verify operation of 1D polynomial evaluation
+psS32 testPoly2DEval(void)
+{
+    psF64  result;
+    psF64  resultCheb;
+    psBool testStatus = true;
+
+    // Allocate polynomial structure
+    psPolynomial2D*  polyOrd = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, TERMS-1, TERMS-1);
+    psPolynomial2D*  polyCheb = psPolynomial2DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1, TERMS-1);
+    // Set polynomial members
+    for(psS32 i = 0; i < TERMS; i++) {
+        for(psS32 j = 0; j < TERMS; j++) {
+            polyOrd->coeff[i][j] = poly2DCoeff[i][j];
+            polyOrd->mask[i][j]  = poly2DMask[i][j];
+            polyCheb->coeff[i][j] = 1.0;
+            polyCheb->mask[i][j]  = poly2DMask[i][j];
+        }
+    }
+    // Evaluate test points and verify results
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+        result = psPolynomial2DEval(polyOrd,Dpoly2DXYValue[i][0],Dpoly2DXYValue[i][1]);
+        if(fabs(Dpoly2DResult[i]-result) > ERROR_TOL ) {
+            printf("TEST ERROR: Evaluated value %f, should be %f\n", result, Dpoly2DResult[i]);
+            testStatus = false;
+        }
+        resultCheb = psPolynomial2DEval(polyCheb,Dpoly2DXYChebValue[i][0],Dpoly2DXYChebValue[i][1]);
+        if(fabs(Dpoly2DChebResult[i]-resultCheb) > ERROR_TOL ) {
+            printf("TEST ERROR: Evaluated value %f, should be %f\n", resultCheb, Dpoly2DChebResult[i]);
+            testStatus = false;
+        }
+    }
+    psFree(polyOrd);
+    psFree(polyCheb);
+
+    // Allocate polynomial with invalid type
+    polyOrd = psPolynomial2DAlloc(99, TERMS-1, TERMS-1);
+    // Attempt to evaluation invalid polynomial type
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message invalid type");
+    result = psPolynomial2DEval(polyOrd,0.0, 0.0);
+    if ( !isnan(result) ) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NAN for invalid polynomial type");
+        testStatus = false;
+    }
+    psFree(polyOrd);
+
+    return(testStatus);
+}
+
+psS32 testPoly2DEvalVector(void)
+{
+    psBool testStatus = true;
+    // Allocate polynomial
+    psPolynomial2D* polyOrd = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, TERMS-1, TERMS-1);
+    psPolynomial2D* polyCheb = psPolynomial2DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1, TERMS-1);
+
+    // Set polynomial members
+    for(psS32 i = 0; i < TERMS; i++) {
+        for(psS32 j = 0; j < TERMS; j++) {
+            polyOrd->coeff[i][j] = poly2DCoeff[i][j];
+            polyOrd->mask[i][j]  = poly2DMask[i][j];
+            polyCheb->coeff[i][j] = 1.0;
+            polyCheb->mask[i][j]  = poly2DMask[i][j];
+        }
+    }
+
+    // Create input vectors
+    psVector* inputOrdX  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    psVector* inputOrdY  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    psVector* inputChebX = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    psVector* inputChebY = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+        inputOrdX->data.F64[i]  = poly2DXYValue[i][0];
+        inputOrdY->data.F64[i]  = poly2DXYValue[i][1];
+        inputChebX->data.F64[i] = poly2DXYChebValue[i][0];
+        inputChebY->data.F64[i] = poly2DXYChebValue[i][1];
+        inputOrdX->n++;
+        inputOrdY->n++;
+        inputChebX->n++;
+        inputChebY->n++;
+    }
+
+    // Evaluate the vectors
+    psVector* outputOrd = psPolynomial2DEvalVector(polyOrd, inputOrdX, inputOrdY);
+    if(outputOrd == NULL) {
+        printf("TEST ERROR: Unexpected return of NULL.\n");
+        testStatus = false;
+    }
+    if(outputOrd->type.type != PS_TYPE_F64) {
+        printf("TEST ERROR: Output vector of type %d expected %d\n", outputOrd->type.type, PS_TYPE_F64);
+        testStatus = false;
+    }
+    psVector* outputCheb = psPolynomial2DEvalVector(polyCheb, inputChebX, inputChebY);
+    if(outputCheb == NULL) {
+        printf("TEST ERROR: Unexpected return of NULL.\n");
+        testStatus = false;
+    }
+    if(outputCheb->type.type != PS_TYPE_F64) {
+        printf("TEST ERROR: Output vector of type %d expected %d.\n", outputCheb->type.type, PS_TYPE_F64);
+        testStatus = false;
+    }
+
+    // Verify the results
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+        if(fabs(poly2DResult[i]-outputOrd->data.F64[i]) > ERROR_TOL) {
+            printf("TEST ERROR: Result[%d] %lg not equal to expected %lg.\n",
+                   i, outputOrd->data.F64[i], poly2DResult[i]);
+            testStatus = false;
+        }
+        if(fabs(poly2DChebResult[i]-outputCheb->data.F64[i]) > ERROR_TOL) {
+            printf("TEST ERROR: ResultCheb[%d] %lg not equal to expected %lg.\n",
+                   i, outputCheb->data.F64[i], poly2DChebResult[i]);
+            testStatus = false;
+        }
+    }
+
+    // Attempt to invoke function with null polynomial
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL polynomial");
+    if(psPolynomial2DEvalVector(NULL, inputOrdX, inputOrdY) != NULL) {
+        printf("TEST ERROR: Return of NULL expected for NULL polynomial.\n");
+        testStatus = false;
+    }
+
+    // Attempt to invoke function with null input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL input vector");
+    if(psPolynomial2DEvalVector(polyOrd,NULL,inputOrdY) != NULL) {
+        printf("TEST ERROR: Return of NULL expected for NULL input vector.\n");
+        testStatus = false;
+    }
+    // Attempt to invoke function with null input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL input vector");
+    if(psPolynomial2DEvalVector(polyOrd,inputOrdX,NULL) != NULL) {
+        printf("TEST ERROR: Return of NULL expected for NULL input vector.\n");
+        testStatus = false;
+    }
+
+    // Attempt to invoke function with a non F64 type input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid input type");
+    inputOrdX->type.type = PS_TYPE_U8;
+    if(psPolynomial2DEvalVector(polyOrd,inputOrdX, inputOrdY) != NULL) {
+        printf("TEST ERROR: Return NULL expected for non-F64 input vector.\n");
+        testStatus = false;
+    }
+    inputOrdX->type.type = PS_TYPE_F64;
+    // Attempt to invoke function with a non F64 type input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid input type");
+    inputOrdY->type.type = PS_TYPE_U8;
+    if(psPolynomial2DEvalVector(polyOrd,inputOrdX, inputOrdY) != NULL) {
+        printf("TEST ERROR: Return NULL expected for non-F64 input vector.\n");
+        testStatus = false;
+    }
+    inputOrdY->type.type = PS_TYPE_F64;
+
+    psFree(inputOrdX);
+    psFree(inputOrdY);
+    psFree(inputChebX);
+    psFree(inputChebY);
+    psFree(outputOrd);
+    psFree(outputCheb);
+    psFree(polyOrd);
+    psFree(polyCheb);
+
+    return(testStatus);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolynomialEval3D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolynomialEval3D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolynomialEval3D.c	(revision 22158)
@@ -0,0 +1,330 @@
+/** tst_psFunc10.c
+*
+*  This test driver will exercise the psPolynomialXDEval functions for both
+*  ORD and CHEB type polynomials.
+*
+*  @version  $Revision: 1.2 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2006-02-24 23:43:15 $
+*
+* Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*
+***************************************************************************/
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+#define  TERMS        4
+#define  TESTPOINTS   5
+#define  ERROR_TOL    0.001
+
+static psS32 testPoly3DEval(void);
+static psS32 testPoly3DEvalVector(void);
+
+testDescription tests[] = {
+                              {testPoly3DEval,583,"psPolynomial3DEval",true,false},
+                              {testPoly3DEvalVector,000,"psPolynomial3DEvalVector",true,false},
+                              {NULL}
+                          };
+
+psF32 poly3DCoeff[TERMS][TERMS][TERMS] = {  { { -1.1,  1.2, -1.3,  1.4},
+        {  1.5, -1.6,  1.7, -1.8},
+        {  0.1, -0.2,  0.3, -0.4},
+        { -0.5,  0.6, -0.7,  0.8}
+                                            },
+        { { -2.1,  2.2, -2.3,  2.4},
+          {  2.5, -2.6,  2.7, -2.8},
+          {  3.1, -3.2,  3.3, -3.4},
+          { -3.5,  3.6, -3.7,  3.8}
+        },
+        { { -4.1,  4.2, -4.3,  4.4},
+          {  4.5, -4.6,  4.7, -4.8},
+          {  5.1, -5.2,  5.3, -5.4},
+          { -5.5,  5.6, -5.7,  5.8}
+        },
+        { { -6.1,  6.2, -6.3,  6.4},
+          {  6.5, -6.6,  6.7, -6.8},
+          {  7.1, -7.2,  7.3, -7.4},
+          { -7.5,  7.6, -7.7,  7.8}
+        }
+                                         };
+psF64 Dpoly3DCoeff[TERMS][TERMS][TERMS] = {  { { -1.1,  1.2, -1.3,  1.4},
+        {  1.5, -1.6,  1.7, -1.8},
+        {  0.1, -0.2,  0.3, -0.4},
+        { -0.5,  0.6, -0.7,  0.8}
+                                             },
+        { { -2.1,  2.2, -2.3,  2.4},
+          {  2.5, -2.6,  2.7, -2.8},
+          {  3.1, -3.2,  3.3, -3.4},
+          { -3.5,  3.6, -3.7,  3.8}
+        },
+        { { -4.1,  4.2, -4.3,  4.4},
+          {  4.5, -4.6,  4.7, -4.8},
+          {  5.1, -5.2,  5.3, -5.4},
+          { -5.5,  5.6, -5.7,  5.8}
+        },
+        { { -6.1,  6.2, -6.3,  6.4},
+          {  6.5, -6.6,  6.7, -6.8},
+          {  7.1, -7.2,  7.3, -7.4},
+          { -7.5,  7.6, -7.7,  7.8}
+        }
+                                          };
+
+
+psF32 poly3DMask[TERMS][TERMS][TERMS]    = { {  {  0,    0,    0,    1},
+        {  0,    0,    1,    0},
+        {  1,    0,    0,    0},
+        {  0,    0,    0,    1}
+                                             },
+        {  {  1,    0,    0,    0},
+           {  1,    0,    0,    0},
+           {  1,    0,    0,    0},
+           {  1,    0,    0,    0}
+        },
+        {  {  0,    1,    0,    0},
+           {  0,    0,    1,    0},
+           {  0,    1,    0,    0},
+           {  0,    0,    1,    0}
+        },
+        {  {  1,    0,    0,    0},
+           {  0,    0,    0,    1},
+           {  1,    0,    0,    0},
+           {  0,    0,    0,    1}
+        },
+                                           };
+
+psF32 poly3DXYZValue[TESTPOINTS][3] = {  {  0.450, -0.780,  0.500},
+                                      {  0.297,  0.153, -0.354},
+                                      {  0.000,  0.153, -0.354},
+                                      {  0.297,  0.000, -0.354},
+                                      {  0.297,  0.153,  0.000}
+                                      };
+psF64 Dpoly3DXYZValue[TESTPOINTS][3] = {  {  0.450, -0.780,  0.500},
+                                       {  0.297,  0.153, -0.354},
+                                       {  0.000,  0.153, -0.354},
+                                       {  0.297,  0.000, -0.354},
+                                       {  0.297,  0.153,  0.000}
+                                       };
+psF32 poly3DResult[TESTPOINTS]  = { -1.298691, -2.011591, -1.359247, -2.548266, -1.139072};
+psF64 Dpoly3DResult[TESTPOINTS] = { -1.298691, -2.011591, -1.359247, -2.548266, -1.139072};
+
+
+psF32 poly3DXYZChebValue[TESTPOINTS][3] = {  {  0.000,  0.250, -0.250},
+        { -0.250,  0.000,  0.250},
+        {  0.250, -0.250,  0.000},
+        {  0.100, -0.300, -0.400},
+        {  0.990, -0.010,  0.500}
+                                          };
+psF64 Dpoly3DXYZChebValue[TESTPOINTS][3] = {  {  0.000,  0.250, -0.250},
+        { -0.250,  0.000,  0.250},
+        {  0.250, -0.250,  0.000},
+        {  0.100, -0.300, -0.400},
+        {  0.990, -0.010,  0.500}
+                                           };
+psF32 poly3DChebResult[TESTPOINTS]  = {  1.230469, 1.687500, 0.187500, -1.452707, 2.032344 };
+psF64 Dpoly3DChebResult[TESTPOINTS] = {  1.230469, 1.687500, 0.187500, -1.452707, 2.032344 };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+
+    return !runTestSuite(stderr,"psPolynomialXDEval", tests, argc, argv);
+}
+
+// This test will verify operation of 1D polynomial evaluation
+psS32 testPoly3DEval(void)
+{
+    psF64  result;
+    psF64  resultCheb;
+    psBool testStatus = true;
+
+    // Allocate polynomial structure
+    psPolynomial3D*  polyOrd = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, TERMS-1, TERMS-1, TERMS-1);
+    psPolynomial3D*  polyCheb = psPolynomial3DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1, TERMS-1, TERMS-1);
+    // Set polynomial members
+    for(psS32 i = 0; i < TERMS; i++) {
+        for(psS32 j = 0; j < TERMS; j++) {
+            for(psS32 k = 0; k < TERMS; k++) {
+                polyOrd->coeff[i][j][k] = Dpoly3DCoeff[i][j][k];
+                polyOrd->mask[i][j][k]  = poly3DMask[i][j][k];
+                polyCheb->coeff[i][j][k] = 1.0;
+                polyCheb->mask[i][j][k]  = poly3DMask[i][j][k];
+            }
+        }
+    }
+    // Evaluate test points and verify results
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+        result = psPolynomial3DEval(polyOrd,Dpoly3DXYZValue[i][0],Dpoly3DXYZValue[i][1],
+                                    Dpoly3DXYZValue[i][2]);
+        if(fabs(Dpoly3DResult[i]-result) > ERROR_TOL ) {
+            printf("TEST ERROR: Evaluated value %lg not as expected %lg.\n",
+                   result, Dpoly3DResult[i]);
+            testStatus = false;
+        }
+        resultCheb = psPolynomial3DEval(polyCheb,Dpoly3DXYZChebValue[i][0],Dpoly3DXYZChebValue[i][1],
+                                        Dpoly3DXYZChebValue[i][2]);
+        if(fabs(Dpoly3DChebResult[i]-resultCheb) > ERROR_TOL ) {
+            printf("TEST ERROR: Evaluated Chebyshev value %lg not as expected %lg.\n",
+                   resultCheb, Dpoly3DChebResult[i]);
+            testStatus = false;
+        }
+    }
+    psFree(polyOrd);
+    psFree(polyCheb);
+
+    // Allocate polynomial with invalid type
+    polyOrd = psPolynomial3DAlloc(99, TERMS-1, TERMS-1, TERMS-1);
+    // Attempt to evaluation invalid polynomial type
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message invalid type");
+    result = psPolynomial3DEval(polyOrd,0.0, 0.0, 0.0);
+    if ( !isnan(result) ) {
+        printf("TEST ERROR: Did not return NAN for invalid polynomial type.\n");
+        testStatus = false;
+    }
+    psFree(polyOrd);
+
+    return(testStatus);
+}
+
+psS32 testPoly3DEvalVector(void)
+{
+    psBool testStatus = true;
+    // Allocate polynomial
+    psPolynomial3D* polyOrd = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, TERMS-1, TERMS-1, TERMS-1);
+    psPolynomial3D* polyCheb = psPolynomial3DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1, TERMS-1, TERMS-1);
+
+    // Set polynomial members
+    for(psS32 i = 0; i < TERMS; i++) {
+        for(psS32 j = 0; j < TERMS; j++) {
+            for(psS32 k = 0; k < TERMS; k++) {
+                polyOrd->coeff[i][j][k] = Dpoly3DCoeff[i][j][k];
+                polyOrd->mask[i][j][k]  = poly3DMask[i][j][k];
+                polyCheb->coeff[i][j][k] = 1.0;
+                polyCheb->mask[i][j][k]  = poly3DMask[i][j][k];
+            }
+        }
+    }
+
+    // Create input vectors
+    psVector* inputOrdX  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    psVector* inputOrdY  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    psVector* inputOrdZ  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    psVector* inputChebX = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    psVector* inputChebY = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    psVector* inputChebZ = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+        inputOrdX->data.F64[i]  = Dpoly3DXYZValue[i][0];
+        inputOrdY->data.F64[i]  = Dpoly3DXYZValue[i][1];
+        inputOrdZ->data.F64[i]  = Dpoly3DXYZValue[i][2];
+        inputChebX->data.F64[i] = Dpoly3DXYZChebValue[i][0];
+        inputChebY->data.F64[i] = Dpoly3DXYZChebValue[i][1];
+        inputChebZ->data.F64[i] = Dpoly3DXYZChebValue[i][2];
+        inputOrdX->n++;
+        inputOrdY->n++;
+        inputOrdZ->n++;
+        inputChebX->n++;
+        inputChebY->n++;
+        inputChebZ->n++;
+    }
+
+    // Evaluate the vectors
+    psVector* outputOrd = psPolynomial3DEvalVector(polyOrd,inputOrdX,inputOrdY,inputOrdZ);
+    if(outputOrd == NULL) {
+        printf("TEST ERROR: Unexpected return of NULL.\n");
+        testStatus = false;
+    }
+    if(outputOrd->type.type != PS_TYPE_F64) {
+        printf("TEST ERROR: Output vector of type %d expected %d.\n",
+               outputOrd->type.type, PS_TYPE_F64);
+        testStatus = false;
+    }
+    psVector* outputCheb = psPolynomial3DEvalVector(polyCheb,inputChebX,inputChebY,inputChebZ);
+    if(outputCheb == NULL) {
+        printf("TEST ERROR: Unexpected return of NULL.\n");
+        testStatus = false;
+    }
+    if(outputCheb->type.type != PS_TYPE_F64) {
+        printf("TEST ERROR: Output vector of type %d expected %d.\n",
+               outputCheb->type.type, PS_TYPE_F64);
+        testStatus = false;
+    }
+
+    // Verify the results
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+        if(fabs(Dpoly3DResult[i]-outputOrd->data.F64[i]) > ERROR_TOL) {
+            printf("TEST ERROR: Result[%d] %lg not equal to expected %lg.\n",
+                   i, outputOrd->data.F64[i], Dpoly3DResult[i]);
+            testStatus = false;
+        }
+        if(fabs(Dpoly3DChebResult[i]-outputCheb->data.F64[i]) > ERROR_TOL) {
+            printf("TEST ERROR: ResultCheb[%d] %lg not equal to expected %lg.\n",
+                   i, outputCheb->data.F64[i], Dpoly3DChebResult[i]);
+            testStatus = false;
+        }
+    }
+
+    // Attempt to invoke function with null polynomial
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL polynomial");
+    if(psPolynomial3DEvalVector(NULL,inputOrdX,inputOrdY,inputOrdZ) != NULL) {
+        printf("TEST ERROR: Return of NULL expected for NULL polynomial.\n");
+        testStatus = false;
+    }
+
+    // Attempt to invoke function with null input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL input vector");
+    if(psPolynomial3DEvalVector(polyOrd,NULL,inputOrdY,inputOrdZ) != NULL) {
+        printf("TEST ERROR: Return of NULL expected for NULL input vector.\n");
+        testStatus = false;
+    }
+    // Attempt to invoke function with null input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL input vector");
+    if(psPolynomial3DEvalVector(polyOrd,inputOrdX,NULL,inputOrdZ) != NULL) {
+        printf("TEST ERROR: Return of NULL expected for NULL input vector.\n");
+        testStatus = false;
+    }
+    // Attempt to invoke function with null input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL input vector");
+    if(psPolynomial3DEvalVector(polyOrd,inputOrdX,inputOrdY,NULL) != NULL) {
+        printf("TEST ERROR: Return of NULL expected for NULL input vector.\n");
+        testStatus = false;
+    }
+
+    // Attempt to invoke function with a non F64 type input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid input type");
+    inputOrdX->type.type = PS_TYPE_U8;
+    if(psPolynomial3DEvalVector(polyOrd,inputOrdX,inputOrdY,inputOrdZ) != NULL) {
+        printf("TEST ERROR: Return NULL expected for non-F64 input vector.\n");
+        testStatus = false;
+    }
+    inputOrdX->type.type = PS_TYPE_F64;
+    // Attempt to invoke function with a non F64 type input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid input type");
+    inputOrdY->type.type = PS_TYPE_U8;
+    if(psPolynomial3DEvalVector(polyOrd,inputOrdX,inputOrdY,inputOrdZ) != NULL) {
+        printf("TEST ERROR: Return NULL expected for non-F64 input vector.\n");
+        testStatus = false;
+    }
+    inputOrdY->type.type = PS_TYPE_F64;
+    // Attempt to invoke function with a non F64 type input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid input type");
+    inputOrdZ->type.type = PS_TYPE_U8;
+    if(psPolynomial3DEvalVector(polyOrd,inputOrdX,inputOrdY,inputOrdZ) != NULL) {
+        printf("TEST ERROR: Return NULL expected for non-F64 input vector.\n");
+        testStatus = false;
+    }
+    inputOrdZ->type.type = PS_TYPE_F64;
+
+    psFree(inputOrdX);
+    psFree(inputOrdY);
+    psFree(inputOrdZ);
+    psFree(inputChebX);
+    psFree(inputChebY);
+    psFree(inputChebZ);
+    psFree(outputOrd);
+    psFree(outputCheb);
+    psFree(polyOrd);
+    psFree(polyCheb);
+
+    return(testStatus);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolynomialEval4D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolynomialEval4D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psPolynomialEval4D.c	(revision 22158)
@@ -0,0 +1,598 @@
+/** tst_psFunc11.c
+*
+*  This test driver will exercise the psPolynomialXDEval functions for both
+*  ORD and CHEB type polynomials.
+*
+*  @version  $Revision: 1.2 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2006-02-24 23:43:15 $
+*
+* Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*
+***************************************************************************/
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+#define  TERMS        4
+#define  TESTPOINTS   5
+#define  ERROR_TOL    0.001
+
+static psS32 testPoly4DEval(void);
+static psS32 testPoly4DEvalVector(void);
+
+testDescription tests[] = {
+                              {testPoly4DEval,583,"psPolynomial4DEval",true,false},
+                              {testPoly4DEvalVector,000,"psPolynomial4DEvalVector",true,false},
+                              {NULL}
+                          };
+
+psF32 poly4DCoeff[TERMS][TERMS][TERMS][TERMS] = {
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            },
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            },
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            },
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            }
+        };
+psF64 Dpoly4DCoeff[TERMS][TERMS][TERMS][TERMS] = {
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            },
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            },
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            },
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            }
+        };
+
+psF32 poly4DMask[TERMS][TERMS][TERMS][TERMS]    = {
+            {
+                {
+                    {  0,    0,    0,    1},
+                    {  0,    0,    1,    0},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0}
+                },
+                {
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0},
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                }
+            },
+            {
+                {
+                    {  0,    0,    0,    1},
+                    {  0,    0,    1,    0},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0}
+                },
+                {
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0},
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                }
+            },
+            {
+                {
+                    {  0,    0,    0,    1},
+                    {  0,    0,    1,    0},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0}
+                },
+                {
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0},
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                }
+            },
+            {
+                {
+                    {  0,    0,    0,    1},
+                    {  0,    0,    1,    0},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0}
+                },
+                {
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0},
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                }
+            }
+        };
+
+psF32 poly4DWXYZValue[TESTPOINTS][4] = {
+                                           {  0.450, -0.780,  0.500, -0.123},
+                                           {  0.297,  0.153, -0.354,  0.000},
+                                           {  0.000,  0.153, -0.354,  0.321},
+                                           {  0.297,  0.000, -0.354,  0.321},
+                                           {  0.297,  0.153,  0.000,  0.321}
+                                       };
+psF64 Dpoly4DWXYZValue[TESTPOINTS][4] = {
+                                            {  0.450, -0.780,  0.500, -0.123},
+                                            {  0.297,  0.153, -0.354,  0.000},
+                                            {  0.000,  0.153, -0.354,  0.321},
+                                            {  0.297,  0.000, -0.354,  0.321},
+                                            {  0.297,  0.153,  0.000,  0.321}
+                                        };
+
+psF32 poly4DResult[TESTPOINTS]  = { -3.588753, -2.439566, -1.175955, -1.645497, -1.216915};
+psF64 Dpoly4DResult[TESTPOINTS]  = { -3.588753, -2.439566, -1.175955, -1.645497, -1.216915};
+
+psF32 poly4DWXYZChebValue[TESTPOINTS][4] = {
+            {  0.100,  0.000,  0.250, -0.250},
+            {  0.100, -0.250,  0.000,  0.250},
+            {  0.100,  0.250, -0.250,  0.000},
+            {  0.300,  0.200, -0.300, -0.400},
+            { -0.780,  0.990, -0.010,  0.500}
+        };
+psF64 Dpoly4DWXYZChebValue[TESTPOINTS][4] = {
+            {  0.100,  0.000,  0.250, -0.250},
+            {  0.100, -0.250,  0.000,  0.250},
+            {  0.100,  0.250, -0.250,  0.000},
+            {  0.300,  0.200, -0.300, -0.400},
+            { -0.780,  0.990, -0.010,  0.500}
+        };
+psF32 poly4DChebResult[TESTPOINTS]   = { -0.216563, -0.297000, -0.033000, 0.432198, 1.785601 };
+psF64 Dpoly4DChebResult[TESTPOINTS]  = { -0.216563, -0.297000, -0.033000, 0.432198, 1.785601 };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+
+    return !runTestSuite(stderr,"psPolynomialXDEval", tests, argc, argv);
+}
+
+// This test will verify operation of 4D polynomial evaluation
+psS32 testPoly4DEval(void)
+{
+    psBool testStatus = true;
+    // Allocate polynomial structure
+    psPolynomial4D*  polyOrd = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, TERMS-1, TERMS-1, TERMS-1, TERMS-1);
+    psPolynomial4D*  polyCheb = psPolynomial4DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1, TERMS-1, TERMS-1, TERMS-1);
+    // Set polynomial members
+    for(psS32 i = 0; i < TERMS; i++) {
+        for(psS32 j = 0; j < TERMS; j++) {
+            for(psS32 k = 0; k < TERMS; k++) {
+                for(psS32 l = 0; l < TERMS; l++) {
+                    polyOrd->coeff[i][j][k][l] = Dpoly4DCoeff[i][j][k][l];
+                    polyOrd->mask[i][j][k][l]  = poly4DMask[i][j][k][l];
+                    polyCheb->coeff[i][j][k][l] = 1.0;
+                    polyCheb->mask[i][j][k][l]  = poly4DMask[i][j][k][l];
+                }
+            }
+        }
+    }
+
+    // Evaluate test points and verify results
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+        psF64 result = psPolynomial4DEval(polyOrd, Dpoly4DWXYZValue[i][0], Dpoly4DWXYZValue[i][1],
+                                          Dpoly4DWXYZValue[i][2], Dpoly4DWXYZValue[i][3]);
+        if(fabs(Dpoly4DResult[i]-result) > ERROR_TOL ) {
+            printf("TEST ERROR: Evaluated value %lg not as expected %lg.\n",
+                   result, Dpoly4DResult[i]);
+            testStatus = false;
+        }
+
+        psF64 resultCheb = psPolynomial4DEval(polyCheb, Dpoly4DWXYZChebValue[i][0], Dpoly4DWXYZChebValue[i][1],
+                                              Dpoly4DWXYZChebValue[i][2], Dpoly4DWXYZChebValue[i][3]);
+        if(fabs(Dpoly4DChebResult[i]-resultCheb) > ERROR_TOL ) {
+            printf("TEST ERROR: Evaluated Chebyshev value %lg not as expected %lg.\n",
+                   resultCheb, Dpoly4DChebResult[i]);
+            testStatus = false;
+        }
+    }
+
+    psFree(polyOrd);
+    psFree(polyCheb);
+
+    // Allocate polynomial with invalid type
+    polyOrd = psPolynomial4DAlloc(99, TERMS-1, TERMS-1, TERMS-1, TERMS-1);
+    // Attempt to evaluation invalid polynomial type
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message invalid type");
+    psF64 result = psPolynomial4DEval(polyOrd,0.0, 0.0, 0.0, 0.0);
+    if ( !isnan(result) ) {
+        printf("TEST ERROR: Did not return NAN for invalid polynomial type");
+        testStatus = false;
+    }
+    psFree(polyOrd);
+
+    return(testStatus);
+}
+
+psS32 testPoly4DEvalVector(void)
+{
+    psBool testStatus = true;
+    // Allocate polynomial
+    psPolynomial4D* polyOrd = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, TERMS-1, TERMS-1, TERMS-1, TERMS-1);
+    psPolynomial4D* polyCheb = psPolynomial4DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1, TERMS-1, TERMS-1, TERMS-1);
+
+    // Set polynomial members
+    for(psS32 i = 0; i < TERMS; i++) {
+        for(psS32 j = 0; j < TERMS; j++) {
+            for(psS32 k = 0; k < TERMS; k++) {
+                for(psS32 l = 0; l < TERMS; l++) {
+                    polyOrd->coeff[i][j][k][l] = Dpoly4DCoeff[i][j][k][l];
+                    polyOrd->mask[i][j][k][l]  = poly4DMask[i][j][k][l];
+                    polyCheb->coeff[i][j][k][l] = 1.0;
+                    polyCheb->mask[i][j][k][l]  = poly4DMask[i][j][k][l];
+                }
+            }
+        }
+    }
+
+    // Create input vectors
+    psVector* inputOrdW  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    psVector* inputOrdX  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    psVector* inputOrdY  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    psVector* inputOrdZ  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    psVector* inputChebW = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    psVector* inputChebX = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    psVector* inputChebY = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    psVector* inputChebZ = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+        inputOrdW->data.F64[i]  = Dpoly4DWXYZValue[i][0];
+        inputOrdX->data.F64[i]  = Dpoly4DWXYZValue[i][1];
+        inputOrdY->data.F64[i]  = Dpoly4DWXYZValue[i][2];
+        inputOrdZ->data.F64[i]  = Dpoly4DWXYZValue[i][3];
+        inputChebW->data.F64[i] = Dpoly4DWXYZChebValue[i][0];
+        inputChebX->data.F64[i] = Dpoly4DWXYZChebValue[i][1];
+        inputChebY->data.F64[i] = Dpoly4DWXYZChebValue[i][2];
+        inputChebZ->data.F64[i] = Dpoly4DWXYZChebValue[i][3];
+        inputOrdW->n++;
+        inputOrdX->n++;
+        inputOrdY->n++;
+        inputOrdZ->n++;
+        inputChebW->n++;
+        inputChebX->n++;
+        inputChebY->n++;
+        inputChebZ->n++;
+    }
+
+    // Evaluate the vectors
+    psVector* outputOrd = psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,inputOrdY,inputOrdZ);
+    if(outputOrd == NULL) {
+        printf("TEST ERROR: Unexpected return of NULL.");
+        testStatus = false;
+    }
+    if(outputOrd->type.type != PS_TYPE_F64) {
+        printf("TEST ERROR: Output vector of type %d expected %d",
+               outputOrd->type.type, PS_TYPE_F64);
+        testStatus = false;
+    }
+
+    psVector* outputCheb = psPolynomial4DEvalVector(polyCheb,inputChebW,inputChebX,inputChebY,inputChebZ);
+    if(outputCheb == NULL) {
+        printf("TEST ERROR: Unexpected return of NULL.");
+        testStatus = false;
+    }
+    if(outputCheb->type.type != PS_TYPE_F64) {
+        printf("TEST ERROR: Output vector of type %d expected %d",
+               outputCheb->type.type, PS_TYPE_F64);
+        testStatus = false;
+    }
+
+    // Verify the results
+    for(psS32 i = 0; i < TESTPOINTS; i++) {
+        if(fabs(Dpoly4DResult[i]-outputOrd->data.F64[i]) > ERROR_TOL) {
+            printf("TEST ERROR: Result[%d] %lg not equal to expected %lg",
+                   i, outputOrd->data.F64[i], Dpoly4DResult[i]);
+            testStatus = false;
+        }
+        if(fabs(Dpoly4DChebResult[i]-outputCheb->data.F64[i]) > ERROR_TOL) {
+            printf("TEST ERROR: ResultCheb[%d] %lg not equal to expected %lg",
+                   i, outputCheb->data.F64[i], Dpoly4DChebResult[i]);
+            testStatus = false;
+        }
+    }
+
+    // Attempt to invoke function with null polynomial
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL polynomial");
+    if(psPolynomial4DEvalVector(NULL,inputOrdW,inputOrdX,inputOrdY,inputOrdZ) != NULL) {
+        printf("TEST ERROR: Return of NULL expected for NULL polynomial");
+        testStatus = false;
+    }
+
+    // Attempt to invoke function with null input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL input vector");
+    if(psPolynomial4DEvalVector(polyOrd,NULL,inputOrdX,inputOrdY,inputOrdZ) != NULL) {
+        printf("TEST ERROR: Return of NULL expected for NULL input vector");
+        testStatus = false;
+    }
+    // Attempt to invoke function with null input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL input vector");
+    if(psPolynomial4DEvalVector(polyOrd,inputOrdW,NULL,inputOrdY,inputOrdZ) != NULL) {
+        printf("TEST ERROR: Return of NULL expected for NULL input vector");
+        testStatus = false;
+    }
+    // Attempt to invoke function with null input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL input vector");
+    if(psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,NULL,inputOrdZ) != NULL) {
+        printf("TEST ERROR: Return of NULL expected for NULL input vector");
+        testStatus = false;
+    }
+    // Attempt to invoke function with null input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL input vector");
+    if(psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,inputOrdY,NULL) != NULL) {
+        printf("TEST ERROR: Return of NULL expected for NULL input vector");
+        testStatus = false;
+    }
+
+    // Attempt to invoke function with a non F64 type input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid input type");
+    inputOrdX->type.type = PS_TYPE_U8;
+    if(psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,inputOrdY,inputOrdZ) != NULL) {
+        printf("TEST ERROR: Return NULL expected for non-F64 input vector");
+        testStatus = false;
+    }
+    inputOrdX->type.type = PS_TYPE_F64;
+    // Attempt to invoke function with a non F64 type input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid input type");
+    inputOrdY->type.type = PS_TYPE_U8;
+    if(psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,inputOrdY,inputOrdZ) != NULL) {
+        printf("TEST ERROR: Return NULL expected for non-F64 input vector");
+        testStatus = false;
+    }
+    inputOrdY->type.type = PS_TYPE_F64;
+    // Attempt to invoke function with a non F64 type input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid input type");
+    inputOrdZ->type.type = PS_TYPE_U8;
+    if(psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,inputOrdY,inputOrdZ) != NULL) {
+        printf("TEST ERROR: Return NULL expected for non-F64 input vector");
+        testStatus = false;
+    }
+    inputOrdZ->type.type = PS_TYPE_F64;
+    // Attempt to invoke function with a non F64 type input vector
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid input type");
+    inputOrdW->type.type = PS_TYPE_U8;
+    if(psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,inputOrdY,inputOrdZ) != NULL) {
+        printf("TEST ERROR: Return NULL expected for non-F64 input vector");
+        testStatus = false;
+    }
+    inputOrdW->type.type = PS_TYPE_F64;
+
+    psFree(inputOrdX);
+    psFree(inputOrdY);
+    psFree(inputOrdZ);
+    psFree(inputOrdW);
+    psFree(inputChebW);
+    psFree(inputChebX);
+    psFree(inputChebY);
+    psFree(inputChebZ);
+    psFree(outputOrd);
+    psFree(outputCheb);
+    psFree(polyOrd);
+    psFree(polyCheb);
+
+    return(testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psRandom.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psRandom.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psRandom.c	(revision 22158)
@@ -0,0 +1,409 @@
+/*****************************************************************************
+This routine must ensure that the various random number generator functions
+work properly.
+ 
+    t00(): ensure that psRandom structs are properly allocated by psRandomAlloc().
+    t01(): ensure that psRandomUniform() produces a sequence of numbers with
+    proper mean and stdev.
+    t02(): ensure that psRandomGaussian() produces a sequence of numbers with
+    proper mean and stdev.
+    t03(): ensure that psRandomPoisson() produces a sequence of numbers with
+    proper mean and stdev.
+    t04(): ensure that psRandomReset() properly seeds the random number
+    generator for psRandomUniform().
+    t05(): ensure that psRandomReset() properly seeds the random number
+    generator for psRandomGaussian().
+    t06(): ensure that psRandomReset() properly seeds the random number
+    generator for psRandomPoisson().
+ *****************************************************************************/
+#include <stdio.h>
+#include <math.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+
+#define NUM_DATA 10000
+#define SEED 54321
+#define SEED2 345
+#define UNIFORM_MEAN 0.5
+#define UNIFORM_STDEV 0.3
+#define GAUSSIAN_MEAN 0.0
+#define GAUSSIAN_STDEV 1.0
+#define POISSON_MEAN 15.0
+#define POISSON_STDEV (POISSON_MEAN / 4)
+#define ERROR_TOLERANCE 0.1
+psS32 testStatus = true;
+
+static psS32 testRandomAlloc(void);
+static psS32 testRandomUniform(void);
+static psS32 testRandomGaussian(void);
+static psS32 testRandomPoisson(void);
+static psS32 testRandomResetUniform(void);
+static psS32 testRandomResetGaussian(void);
+static psS32 testRandomResetPoisson(void);
+
+testDescription tests[] = {
+                              {testRandomAlloc,000,"psRandomAlloc",0,false},
+                              {testRandomUniform,000,"psRandomUniform",0,false},
+                              {testRandomGaussian,000,"psRandomGaussian",0,false},
+                              {testRandomPoisson,000,"psRandomPoisson",0,false},
+                              {testRandomResetUniform,000,"psRandomReset",0,false},
+                              {testRandomResetGaussian,000,"psRandomReset",0,false},
+                              {testRandomResetPoisson,000,"psRandomReset",0,false},
+                              {NULL}
+                          };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    if(!runTestSuite(stderr,"psRandom",tests,argc,argv)) {
+        return 1;
+    }
+
+    return 0;
+}
+
+psS32 testRandomAlloc(void)
+{
+    psRandom *myRNG = NULL;
+
+    // Valid type allocation
+    myRNG = psRandomAlloc(PS_RANDOM_TAUS, SEED);
+    if (myRNG == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Could not allocate psRandom structure");
+        return 1;
+    }
+    if (myRNG->type != PS_RANDOM_TAUS) {
+        psError(PS_ERR_UNKNOWN,true,"Type %d not as expected %d",myRNG->type,PS_RANDOM_TAUS);
+        return 2;
+    }
+    psFree(myRNG);
+
+    // Valid type allocation with seed equal to zero
+    int fd1 = creat("seed_msglog1.txt", 0666);
+    //    psLogSetDestination("file:seed_msglog1.txt");
+    psLogSetDestination(fd1);
+    myRNG = psRandomAlloc(PS_RANDOM_TAUS, 0);
+    //    psLogSetDestination("dest:stderr");
+    psLogSetDestination(2);
+    if (myRNG == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Could not allocate psRandom structure");
+        return 3;
+    }
+    if (myRNG->type != PS_RANDOM_TAUS) {
+        psError(PS_ERR_UNKNOWN,true,"Type %d not as expected %d",myRNG->type,PS_RANDOM_TAUS);
+        return 4;
+    }
+    psFree(myRNG);
+
+    // Invalid type allocation
+    psLogMsg(__func__,PS_LOG_INFO,"Invalid type, should generate error message");
+    myRNG = psRandomAlloc(100,SEED);
+    if (myRNG != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL for invalid type");
+        return 5;
+    }
+
+    // Negative seed value
+    myRNG = psRandomAlloc(PS_RANDOM_TAUS,-5);
+    if(myRNG == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return allocated psRandom");
+        return 6;
+    }
+    close(fd1);
+    psFree(myRNG);
+
+    return 0;
+}
+
+psS32 testRandomUniform(void)
+{
+    psRandom *myRNG = NULL;
+    psVector *rans = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+    rans->n = rans->nalloc;
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+
+    myRNG = psRandomAlloc(PS_RANDOM_TAUS, SEED);
+    if (myRNG == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Could not allocate psRandom structure");
+        return 1;
+    }
+
+    // Initialize vector data with random number
+    for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+        rans->data.F64[i] = psRandomUniform(myRNG);
+    }
+    // Perform vector stats on random data (mean, stdev)
+    stats = psVectorStats(stats, rans, NULL, NULL, 0);
+    stats->options = PS_STAT_SAMPLE_STDEV;
+    stats = psVectorStats(stats, rans, NULL, NULL, 0);
+    // Verify mean and stdev
+    if ((fabs(stats->sampleMean - UNIFORM_MEAN) / UNIFORM_MEAN) > ERROR_TOLERANCE) {
+        psError(PS_ERR_UNKNOWN,true,"psRandomUniform mean is %.2f, should be %.2f",
+                stats->sampleMean, UNIFORM_MEAN);
+        return 2;
+    }
+    if ((fabs(stats->sampleStdev - UNIFORM_STDEV) / UNIFORM_STDEV) > ERROR_TOLERANCE) {
+        psError(PS_ERR_UNKNOWN,true,"psRandomUniform stdev is %.2f, should be %.2f",
+                stats->sampleStdev, UNIFORM_STDEV);
+        return 3;
+    }
+
+    psFree(myRNG);
+    psFree(rans);
+    psFree(stats);
+
+    psLogMsg(__func__,PS_LOG_INFO,"NULL psRandom variable, should generate error message");
+    if(psRandomUniform(NULL) != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return zero for null psRandom");
+        return 4;
+    }
+
+    return 0;
+}
+
+psS32 testRandomGaussian(void)
+{
+    psRandom *myRNG = NULL;
+    psVector *rans = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+    rans->n = rans->nalloc;
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+
+    myRNG = psRandomAlloc(PS_RANDOM_TAUS, SEED);
+    if (myRNG == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Could not allocate psRandom structure");
+        return 1;
+    }
+
+    // Initialize vector with random data
+    for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+        rans->data.F64[i] = psRandomGaussian(myRNG);
+    }
+
+    // Perform vector stats on data (mean, stdev)
+    stats = psVectorStats(stats, rans, NULL, NULL, 0);
+    stats->options = PS_STAT_SAMPLE_STDEV;
+    stats = psVectorStats(stats, rans, NULL, NULL, 0);
+
+    // Verify statistics
+    if ((fabs(stats->sampleMean - GAUSSIAN_MEAN) / 1.0) > ERROR_TOLERANCE) {
+        psError(PS_ERR_UNKNOWN,true,"psRandomGaussian mean is %.2f, should be %.2f",
+                stats->sampleMean, GAUSSIAN_MEAN);
+        return 2;
+    }
+    if ((fabs(stats->sampleStdev - GAUSSIAN_STDEV) / GAUSSIAN_STDEV) > ERROR_TOLERANCE) {
+        psError(PS_ERR_UNKNOWN,true,"psRandomGaussian stdev is %.2f, should be %.2f",
+                stats->sampleStdev, GAUSSIAN_STDEV);
+        return 3;
+    }
+
+    psFree(myRNG);
+    psFree(rans);
+    psFree(stats);
+
+    psLogMsg(__func__,PS_LOG_INFO,"NULL psRandom variable, should generate error message");
+    if(psRandomGaussian(NULL) != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return zero for null psRandom");
+        return 4;
+    }
+
+    return 0;
+}
+
+psS32 testRandomPoisson(void)
+{
+    psRandom *myRNG = NULL;
+    psVector *rans = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+    rans->n = rans->nalloc;
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+
+    myRNG = psRandomAlloc(PS_RANDOM_TAUS, SEED);
+    if (myRNG == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Could not allocate psRandom structure");
+        return 1;
+    }
+
+    // Initialize vector with random data
+    for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+        rans->data.F64[i] = psRandomPoisson(myRNG, POISSON_MEAN);
+    }
+
+    // Perform statistics on data
+    stats = psVectorStats(stats, rans, NULL, NULL, 0);
+    stats->options = PS_STAT_SAMPLE_STDEV;
+    stats = psVectorStats(stats, rans, NULL, NULL, 0);
+    if ((fabs(stats->sampleMean - POISSON_MEAN) / POISSON_MEAN) > ERROR_TOLERANCE) {
+        psError(PS_ERR_UNKNOWN,true,"psRandomPoisson mean is %.2f, should be %.2f",
+                stats->sampleMean, POISSON_MEAN);
+        return 2;
+    }
+    if ((fabs(stats->sampleStdev - POISSON_STDEV) / POISSON_STDEV) > ERROR_TOLERANCE) {
+        psError(PS_ERR_UNKNOWN,true,"psRandomPoisson stdev is %.2f, should be %.2f",
+                stats->sampleStdev, POISSON_STDEV);
+        return 3;
+    }
+
+    psFree(myRNG);
+    psFree(rans);
+    psFree(stats);
+
+    psLogMsg(__func__,PS_LOG_INFO,"NULL psRandom variable, should generate error message");
+    if(psRandomPoisson(NULL, POISSON_MEAN) != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return zero for null psRandom");
+        return 4;
+    }
+
+    return 0;
+}
+
+psS32 testRandomResetUniform(void)
+{
+    psRandom *myRNG = NULL;
+    psVector *rans00 = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+    rans00->n = rans00->nalloc;
+    psVector *rans01 = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+    rans01->n = rans01->nalloc;
+    psVector *rans02 = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+    rans02->n = rans02->nalloc;
+
+    myRNG = psRandomAlloc(PS_RANDOM_TAUS, SEED);
+    if (myRNG == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Could not allocate psRandom structure");
+        return 1;
+    }
+
+    // Random reset
+    psRandomReset(myRNG, SEED);
+    for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+        rans00->data.F64[i] = psRandomUniform(myRNG);
+    }
+    psRandomReset(myRNG, SEED2);
+    for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+        rans01->data.F64[i] = psRandomUniform(myRNG);
+    }
+    psRandomReset(myRNG, SEED);
+    for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+        rans02->data.F64[i] = psRandomUniform(myRNG);
+    }
+
+    // Verify reset to original seed produces same results
+    for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+        if (rans00->data.F64[i] != rans02->data.F64[i]) {
+            psError(PS_ERR_UNKNOWN,true,"psRandomUniform did not produce the same results with the same seed");
+            return i+1;
+        }
+    }
+
+    psFree(myRNG);
+    psFree(rans00);
+    psFree(rans01);
+    psFree(rans02);
+
+    psRandom *myRNG1 = NULL;
+    myRNG1 = psRandomAlloc(PS_RANDOM_TAUS, SEED);
+    //    psLogSetDestination("dest:stderr");
+    psLogSetDestination(0);
+    psRandomReset(myRNG1,0);
+    //    psLogSetDestination("dest:stderr");
+    psLogSetDestination(2);
+    psFree(myRNG1);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Reset a NULL psRandom variable, should generate an error message");
+    psRandomReset(NULL,SEED);
+
+    return 0;
+}
+
+psS32 testRandomResetGaussian(void)
+{
+    psRandom *myRNG = NULL;
+    psVector *rans00 = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+    rans00->n = rans00->nalloc;
+    psVector *rans01 = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+    rans01->n = rans01->nalloc;
+    psVector *rans02 = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+    rans02->n = rans02->nalloc;
+
+    myRNG = psRandomAlloc(PS_RANDOM_TAUS, SEED);
+    if (myRNG == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Could not allocate psRandom structure");
+        return 1;
+    }
+
+    // Initialize random data in vectors
+    psRandomReset(myRNG, SEED);
+    for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+        rans00->data.F64[i] = psRandomGaussian(myRNG);
+    }
+    psRandomReset(myRNG, SEED2);
+    for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+        rans01->data.F64[i] = psRandomGaussian(myRNG);
+    }
+    psRandomReset(myRNG, SEED);
+    for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+        rans02->data.F64[i] = psRandomGaussian(myRNG);
+    }
+
+    // Verify data from original seed produces same data after reset
+    for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+        if (rans00->data.F64[i] != rans02->data.F64[i]) {
+            psError(PS_ERR_UNKNOWN,true,"psRandomGaussian did not produce the same results with the same seed");
+            return 2;
+        }
+    }
+
+    psFree(myRNG);
+    psFree(rans00);
+    psFree(rans01);
+    psFree(rans02);
+
+    return 0;
+}
+
+psS32 testRandomResetPoisson(void)
+{
+    psRandom *myRNG = NULL;
+    psVector *rans00 = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+    rans00->n = rans00->nalloc;
+    psVector *rans01 = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+    rans01->n = rans01->nalloc;
+    psVector *rans02 = psVectorAlloc(NUM_DATA, PS_TYPE_F64);
+    rans02->n = rans02->nalloc;
+
+    myRNG = psRandomAlloc(PS_RANDOM_TAUS, SEED);
+    if (myRNG == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Could not allocate psRandom structure");
+        return 1;
+    }
+
+    // Initialize vectors with random data
+    psRandomReset(myRNG, SEED);
+    for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+        rans00->data.F64[i] = psRandomPoisson(myRNG, POISSON_MEAN);
+    }
+    psRandomReset(myRNG, SEED2);
+    for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+        rans01->data.F64[i] = psRandomPoisson(myRNG, POISSON_MEAN);
+    }
+    psRandomReset(myRNG, SEED);
+    for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+        rans02->data.F64[i] = psRandomPoisson(myRNG, POISSON_MEAN);
+    }
+
+    // Verify the original seed produces same data after reset
+    for (psS32 i = 0 ; i < NUM_DATA ; i++) {
+        if (rans00->data.F64[i] != rans02->data.F64[i]) {
+            psError(PS_ERR_UNKNOWN,true,"psRandomPoisson did not produce the same results with the same seed");
+            return 2;
+        }
+    }
+
+    psFree(myRNG);
+    psFree(rans00);
+    psFree(rans01);
+    psFree(rans02);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psSparse.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psSparse.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psSparse.c	(revision 22158)
@@ -0,0 +1,59 @@
+
+void psSparseMatrixTest ()
+{
+
+    // build a sparse matrix
+    psSparse *sparse = psSparseAlloc (3, 9);
+
+    psSparseMatrixElement (sparse, 0, 0, 3.0);
+    psSparseMatrixElement (sparse, 1, 1, 2.0);
+    psSparseMatrixElement (sparse, 2, 2, 1.0);
+
+    psSparseMatrixElement (sparse, 1, 0, 0.1);
+    psSparseMatrixElement (sparse, 2, 0, -0.1);
+
+    psSparseResort (sparse);
+    for (int i = 0; i < sparse->Nelem; i++) {
+        fprintf (stderr, "%d %d %f\n",
+                 sparse->Si->data.S32[i],
+                 sparse->Sj->data.S32[i],
+                 sparse->Aij->data.F32[i]);
+    }
+
+    psVector *x = psVectorAlloc (3, PS_DATA_F32);
+    x->data.F32[0] = 3;
+    x->data.F32[1] = 5;
+    x->data.F32[2] = 7;
+    x->n = 3;
+    fprintf (stderr, "x: %f %f %f\n", x->data.F32[0], x->data.F32[1], x->data.F32[2]);
+
+
+    psVector *B = psSparseMatrixTimesVector (NULL, sparse, x);
+    fprintf (stderr, "B: %f %f %f\n", B->data.F32[0], B->data.F32[1], B->data.F32[2]);
+
+    sparse->Bfj->data.F32[0] = B->data.F32[0];
+    sparse->Bfj->data.F32[1] = B->data.F32[1];
+    sparse->Bfj->data.F32[2] = B->data.F32[2];
+
+    psSparseConstraint constraint;
+    constraint.paramMin   = -1e8;
+    constraint.paramMax   = +1e8;
+    constraint.paramDelta = +1e8;
+
+    x = psSparseSolve (x, constraint, sparse, 0);
+    fprintf (stderr, "x: %f %f %f\n", x->data.F32[0], x->data.F32[1], x->data.F32[2]);
+
+    x = psSparseSolve (x, constraint, sparse, 1);
+    fprintf (stderr, "x: %f %f %f\n", x->data.F32[0], x->data.F32[1], x->data.F32[2]);
+
+    x = psSparseSolve (x, constraint, sparse, 2);
+    fprintf (stderr, "x: %f %f %f\n", x->data.F32[0], x->data.F32[1], x->data.F32[2]);
+
+    x = psSparseSolve (x, constraint, sparse, 3);
+    fprintf (stderr, "x: %f %f %f\n", x->data.F32[0], x->data.F32[1], x->data.F32[2]);
+
+    x = psSparseSolve (x, constraint, sparse, 4);
+    fprintf (stderr, "x: %f %f %f\n", x->data.F32[0], x->data.F32[1], x->data.F32[2]);
+    return;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psSpline1D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psSpline1D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psSpline1D.c	(revision 22158)
@@ -0,0 +1,892 @@
+/* @file  tst_psImageManip.c
+*
+*  @brief This file will contain tests for all of the public psLib functions
+*         that implement 1-D spline functionality:
+* psSpline1DAlloc()
+* psSpline1DEval()
+* psSpline1DEvalVector()
+* psVectorFitSpline1D()
+*
+*         This file is composed of the tests formerly in tst_psFunc02.c,
+*         tst_psFunc03.c, tst_psFunc04.c, tst_psFunc05.c, and tst_psFunc07.c.
+*
+*  @author GLG, MHPCC
+*
+*  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-02-07 23:52:54 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#include "psTest.h"
+#include "pslib_strict.h"
+
+static psS32 psSplineAllocTest( void );
+static psS32 psSplineEvalTest( void );
+static psS32 psSplineEvalVectorTest( void );
+
+// {testFunction, testpointNumber, description, expected rc, boolean-ignore this test}
+testDescription tests[] = {
+                              {psSplineAllocTest, 665, "(TEST A) psSplineAllocTest",true, false},
+                              {psSplineEvalTest, 666, "(TEST B) psSplineEvalTest",true, false},
+                              {psSplineEvalVectorTest,667,"(TEST C) psSplineEvalVectorTest",true,false},
+                              {NULL}
+                          };
+
+#define  ERROR_TOLERANCE_PERCENT    1.00
+/*********************************************************************************
+CheckErrorF32(psF32 actual, psF32 expect): this routine returns FALSE if the
+actual and expect arguments are with ERROR_TOLERANCE_PERCENT of each other,
+otherwise it returns TRUE.
+ ********************************************************************************/
+psBool CheckErrorF32(
+    psF32 actual,
+    psF32 expect)
+{
+    if ((fabs(actual - expect) / fabs(expect)) > ERROR_TOLERANCE_PERCENT) {
+        return(true);
+    } else {
+        return(false);
+    }
+}
+
+psS32 main(
+    psS32 argc,
+    char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel( PS_LOG_INFO );
+    //
+    // Set the following trace levels to track what is happening in the
+    // various functions in psSpline.c
+    //
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("spline1DFree", 0);
+    psTraceSetLevel("calculateSecondDerivs", 0);
+    psTraceSetLevel("vectorBinDisectF32", 0);
+    psTraceSetLevel("vectorBinDisectF64", 0);
+    psTraceSetLevel("p_psVectorBinDisect", 0);
+    psTraceSetLevel("psSpline1DAlloc", 0);
+    psTraceSetLevel("psVectorFitSpline1D", 0);
+    psTraceSetLevel("psSpline1DEval", 0);
+    psTraceSetLevel("psSpline1DEvalVector", 0);
+
+    return ( ! runTestSuite( stderr, "psSpline1D", tests, argc, argv ) );
+}
+
+psS32 psSplineAllocTest()
+{
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("spline1DFree", 0);
+    psTraceSetLevel("calculateSecondDerivs", 0);
+    psTraceSetLevel("vectorBinDisectF32", 0);
+    psTraceSetLevel("vectorBinDisectF64", 0);
+    psTraceSetLevel("p_psVectorBinDisect", 0);
+    psTraceSetLevel("psSpline1DAlloc", 0);
+    psTraceSetLevel("psVectorFitSpline1D", 0);
+    psTraceSetLevel("psSpline1DEval", 0);
+    psTraceSetLevel("psSpline1DEvalVector", 0);
+
+    psS32 testStatus = true;
+    psS32  currentId = psMemGetId();
+
+    psSpline1D *tmpSpline = psSpline1DAlloc();
+    if (tmpSpline == NULL) {
+        printf("TEST ERROR: Could not allocate psSpline1D data structure\n");
+        testStatus = false;
+    }
+
+    if (tmpSpline->n != 0) {
+        printf("TEST ERROR: psSpline1DAlloc() did not properly set the psSpline1D->n member.\n");
+        testStatus = false;
+    }
+
+    if (tmpSpline->spline != NULL) {
+        printf("TEST ERROR: psSpline1DAlloc() did not properly set the psSpline1D->spline member.\n");
+        testStatus = false;
+    }
+
+    if (tmpSpline->knots != NULL) {
+        printf("TEST ERROR: psSpline1DAlloc() did not properly set the psSpline1D->knots member.\n");
+        testStatus = false;
+    }
+
+    if (tmpSpline->p_psDeriv2 != NULL) {
+        printf("TEST ERROR: psSpline1DAlloc() did not properly set the psSpline1D->p_psDeriv2 member.\n");
+        testStatus = false;
+    }
+    /*
+     XXX: Must allocate these members.
+        tmpSline->spline = (psPolynomial1D **) psAlloc(numSplines * sizeof(psPolynomial1D *));
+        for (psS32 i=0;i<numSplines;i++) {
+            spline->spline[i] = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 3);
+        }
+    */
+
+    psFree(tmpSpline);
+    psMemCheckCorruption(1);
+    psS32 memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    return(testStatus);
+}
+
+
+/*********************************************************************************
+psSplineEvalTest_sub(): We psVectorFitSpline1D with NULL arguments. psSpline1DEval()
+ ********************************************************************************/
+psS32 psSplineEvalTest_sub(psS32 NumSplines)
+{
+    psS32 testStatus = true;
+    psS32 memLeaks=0;
+    psS32  currentId = psMemGetId();
+
+    printf("\n");
+    printf("Calling psVectorFitSpline1D() with NULL y-vector.  Should generate error.\n");
+    psSpline1D *tmpSpline = psVectorFitSpline1D(NULL, NULL);
+    if (tmpSpline != NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not return NULL.\n");
+        testStatus = false;
+        psFree(tmpSpline);
+    }
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    return (testStatus);
+}
+
+
+/*********************************************************************************
+psSplineEvalTest_sub00(): We test the psVectorFitSpline1D, psSpline1DEval()
+functions with a very simple x->y mapping (defined by myFunc00() below).  We
+do this for both F32 and F64 versions of the input x and y vectors.
+ ********************************************************************************/
+psF32 myFunc00(psF32 x)
+{
+    return(x);
+}
+
+psS32 psSplineEvalTest_sub00(psS32 NumSplines)
+{
+    psS32 testStatus = true;
+    psS32 memLeaks=0;
+    psF32 x;
+    psF32 y;
+    psS32  currentId = psMemGetId();
+    psVector *xF32 = NULL;
+    psVector *xF64 = NULL;
+    psVector *yF32 = NULL;
+    psVector *yF64 = NULL;
+    psSpline1D *tmpSpline = NULL;
+
+    printf("\n");
+    printf("psSplineEvalTest_sub00(): We test the psVectorFitSpline1D, psSpline1DEval() functions with a very\n");
+    printf("simple x->y mapping (defined by myFunc00()).  We do this for both F32\n");
+    printf("and F64 versions of the input x and y vectors.\n");
+    printf("    Number of splines: %d\n", NumSplines);
+    /****************************************************************************/
+    /*    PS_TYPE_F32, PS_TYPE_F32 test          */
+    /****************************************************************************/
+    printf("Performing the F32 test....\n");
+    xF32 = psVectorAlloc(NumSplines+1, PS_TYPE_F32);
+    xF64 = psVectorAlloc(NumSplines+1, PS_TYPE_F64);
+    yF32 = psVectorAlloc(NumSplines+1, PS_TYPE_F32);
+    yF64 = psVectorAlloc(NumSplines+1, PS_TYPE_F64);
+    xF32->n = NumSplines+1;
+    xF64->n = NumSplines+1;
+    yF32->n = NumSplines+1;
+    yF64->n = NumSplines+1;
+
+    for (psS32 i=0;i<NumSplines+1;i++) {
+        xF32->data.F32[i] = (psF32) i;
+        xF64->data.F64[i] = (psF64) i;
+        yF32->data.F32[i] = (psF32) myFunc00(xF32->data.F32[i]);
+        yF64->data.F64[i] = (psF64) myFunc00(xF32->data.F32[i]);
+    }
+
+    tmpSpline = psVectorFitSpline1D(xF32, yF32);
+    if (tmpSpline == NULL) {
+        printf("TEST ERROR: Could not allocate psSpline1D data structure (1)\n");
+        testStatus = false;
+    }
+
+    if (tmpSpline->n != NumSplines) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->n member.\n");
+        printf("            psSpline1D->NumSplines was %d, should be %d.\n", tmpSpline->n, NumSplines);
+        testStatus = false;
+    }
+
+    if (tmpSpline->spline == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->spline member.\n");
+        testStatus = false;
+    } else {
+        for (psS32 i = 0 ; i < NumSplines ; i++) {
+            if (tmpSpline->spline[i] == NULL) {
+                printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->spline[%d] member.\n", i);
+                testStatus = false;
+            } else {
+                if (psTraceGetLevel(__func__) >= 6) {
+                    PS_POLY_PRINT_1D(tmpSpline->spline[i]);
+                }
+            }
+        }
+    }
+
+    if (tmpSpline->knots == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->knots member.\n");
+        testStatus = false;
+    }
+
+    if (tmpSpline->p_psDeriv2 == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->p_psDeriv2 member.\n");
+        testStatus = false;
+    }
+
+    if (testStatus == true) {
+        for (psS32 i=0;i<NumSplines;i++) {
+            x = 0.5 + (float) i;
+            y = psSpline1DEval(tmpSpline, x);
+            if (CheckErrorF32(y, myFunc00(x))) {
+                printf("TEST ERROR: f(%f) is %f, should be %f\n", x, y, myFunc00(x));
+                testStatus = false;
+            }
+        }
+    }
+
+    psFree(tmpSpline);
+    psFree(xF32);
+    psFree(xF64);
+    psFree(yF32);
+    psFree(yF64);
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    /****************************************************************************/
+    /*    PS_TYPE_F64, PS_TYPE_F64 test          */
+    /****************************************************************************/
+    printf("Performing the F64 test....\n");
+    xF32 = psVectorAlloc(NumSplines+1, PS_TYPE_F32);
+    xF64 = psVectorAlloc(NumSplines+1, PS_TYPE_F64);
+    yF32 = psVectorAlloc(NumSplines+1, PS_TYPE_F32);
+    yF64 = psVectorAlloc(NumSplines+1, PS_TYPE_F64);
+    xF32->n = NumSplines+1;
+    xF64->n = NumSplines+1;
+    yF32->n = NumSplines+1;
+    yF64->n = NumSplines+1;
+
+    for (psS32 i=0;i<NumSplines+1;i++) {
+        xF32->data.F32[i] = (psF32) i;
+        xF64->data.F64[i] = (psF64) i;
+        yF32->data.F32[i] = (psF32) myFunc00(xF32->data.F32[i]);
+        yF64->data.F64[i] = (psF64) myFunc00(xF32->data.F32[i]);
+    }
+
+    tmpSpline = psVectorFitSpline1D(xF64, yF64);
+    if (tmpSpline == NULL) {
+        printf("TEST ERROR: Could not allocate psSpline1D data structure\n");
+        testStatus = false;
+    }
+
+    if (tmpSpline->n != NumSplines) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->n member.\n");
+        printf("            psSpline1D->NumSplines was %d, should be %d.\n", tmpSpline->n, NumSplines);
+        testStatus = false;
+    }
+
+    if (tmpSpline->spline == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->spline member.\n");
+        testStatus = false;
+    } else {
+        for (psS32 i = 0 ; i < NumSplines ; i++) {
+            if (tmpSpline->spline[i] == NULL) {
+                printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->spline[%d] member.\n", i);
+                testStatus = false;
+            } else {
+                if (psTraceGetLevel(__func__) >= 6) {
+                    PS_POLY_PRINT_1D(tmpSpline->spline[i]);
+                }
+            }
+        }
+    }
+
+    if (tmpSpline->knots == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->knots member.\n");
+        testStatus = false;
+    }
+
+    if (tmpSpline->p_psDeriv2 == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->p_psDeriv2 member.\n");
+        testStatus = false;
+    }
+
+    if (testStatus == true) {
+        for (psS32 i=0;i<NumSplines;i++) {
+            x = 0.5 + (float) i;
+            y = psSpline1DEval(tmpSpline, x);
+            if (CheckErrorF32(y, myFunc00(x))) {
+                printf("TEST ERROR: f(%f) is %f, should be %f\n", x, y, myFunc00(x));
+                testStatus = false;
+            }
+        }
+    }
+
+    psFree(tmpSpline);
+    psFree(xF32);
+    psFree(xF64);
+    psFree(yF32);
+    psFree(yF64);
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    return (testStatus);
+}
+
+/*********************************************************************************
+psSplineEvalTest_sub00b(): We test the psVectorFitSpline1D, psSpline1DEval()
+functions with a more complicated x->y mapping (defined by myFunc00b() below).
+We do this for both F32 and F64 versions of the input x and y vectors.
+ ********************************************************************************/
+#define A 4.0
+#define B -3.0
+#define C 0.2
+#define D 0.1
+psF32 myFunc00b(psF32 x)
+{
+    return(A + x * (B + x * (C + x * (D))));
+}
+
+psS32 psSplineEvalTest_sub00b(psS32 NumSplines)
+{
+    printf("\n");
+    printf("psSplineEvalTest_sub00b(): We test the psVectorFitSpline1D, psSpline1DEval() functions with a\n");
+    printf("more complicated x->y mapping (defined by myFunc00b()).  We do this for\n");
+    printf("both F32 and F64 versions of the input x and y vectors.\n");
+    printf("    Number of splines: %d\n", NumSplines);
+    psS32 testStatus = true;
+    psS32 memLeaks=0;
+    psF32 x;
+    psF32 y;
+    psS32  currentId = psMemGetId();
+    psVector *xF32 = NULL;
+    psVector *xF64 = NULL;
+    psVector *yF32 = NULL;
+    psVector *yF64 = NULL;
+    psSpline1D *tmpSpline = NULL;
+
+    /****************************************************************************/
+    /*    PS_TYPE_F32, PS_TYPE_F32 test          */
+    /****************************************************************************/
+    printf("Performing the F32 test....\n");
+    xF32 = psVectorAlloc(NumSplines+1, PS_TYPE_F32);
+    xF64 = psVectorAlloc(NumSplines+1, PS_TYPE_F64);
+    yF32 = psVectorAlloc(NumSplines+1, PS_TYPE_F32);
+    yF64 = psVectorAlloc(NumSplines+1, PS_TYPE_F64);
+    xF32->n = NumSplines+1;
+    xF64->n = NumSplines+1;
+    yF32->n = NumSplines+1;
+    yF64->n = NumSplines+1;
+
+    for (psS32 i=0;i<NumSplines+1;i++) {
+        xF32->data.F32[i] = (psF32) i;
+        xF64->data.F64[i] = (psF64) i;
+        yF32->data.F32[i] = (psF32) myFunc00b(xF32->data.F32[i]);
+        yF64->data.F64[i] = (psF64) myFunc00b(xF32->data.F32[i]);
+    }
+
+    tmpSpline = psVectorFitSpline1D(xF32, yF32);
+    if (tmpSpline == NULL) {
+        printf("TEST ERROR: Could not allocate psSpline1D data structure\n");
+        testStatus = false;
+    }
+
+    if (tmpSpline->n != NumSplines) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->n member.\n");
+        printf("            psSpline1D->NumSplines was %d, should be %d.\n", tmpSpline->n, NumSplines);
+        testStatus = false;
+    }
+
+    if (tmpSpline->spline == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->spline member.\n");
+        testStatus = false;
+    } else {
+        for (psS32 i = 0 ; i < NumSplines ; i++) {
+            if (tmpSpline->spline[i] == NULL) {
+                printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->spline[%d] member.\n", i);
+                testStatus = false;
+            } else {
+                if (psTraceGetLevel(__func__) >= 6) {
+                    PS_POLY_PRINT_1D(tmpSpline->spline[i]);
+                }
+            }
+        }
+    }
+
+    if (tmpSpline->knots == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->knots member.\n");
+        testStatus = false;
+    }
+
+    if (tmpSpline->p_psDeriv2 == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->p_psDeriv2 member.\n");
+        testStatus = false;
+    }
+
+    if (testStatus == true) {
+        for (psS32 i=0;i<NumSplines;i++) {
+            x = 0.5 + (float) i;
+            y = psSpline1DEval(tmpSpline, x);
+            if (CheckErrorF32(y, myFunc00b(x))) {
+                printf("TEST ERROR: f(%f) is %f, should be %f\n", x, y, myFunc00b(x));
+                testStatus = false;
+            }
+        }
+    }
+
+    psFree(tmpSpline);
+    psFree(xF32);
+    psFree(xF64);
+    psFree(yF32);
+    psFree(yF64);
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    /****************************************************************************/
+    /*    PS_TYPE_F64, PS_TYPE_F64 test          */
+    /****************************************************************************/
+    printf("Performing the F64 test....\n");
+    xF32 = psVectorAlloc(NumSplines+1, PS_TYPE_F32);
+    xF64 = psVectorAlloc(NumSplines+1, PS_TYPE_F64);
+    yF32 = psVectorAlloc(NumSplines+1, PS_TYPE_F32);
+    yF64 = psVectorAlloc(NumSplines+1, PS_TYPE_F64);
+    xF32->n = NumSplines+1;
+    xF64->n = NumSplines+1;
+    yF32->n = NumSplines+1;
+    yF64->n = NumSplines+1;
+
+    for (psS32 i=0;i<NumSplines+1;i++) {
+        xF32->data.F32[i] = (psF32) i;
+        xF64->data.F64[i] = (psF64) i;
+        yF32->data.F32[i] = (psF32) myFunc00b(xF32->data.F32[i]);
+        yF64->data.F64[i] = (psF64) myFunc00b(xF32->data.F32[i]);
+    }
+
+    tmpSpline = psVectorFitSpline1D(xF64, yF64);
+    if (tmpSpline == NULL) {
+        printf("TEST ERROR: Could not allocate psSpline1D data structure\n");
+        testStatus = false;
+    }
+
+    if (tmpSpline->n != NumSplines) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->n member.\n");
+        printf("            psSpline1D->NumSplines was %d, should be %d.\n", tmpSpline->n, NumSplines);
+        testStatus = false;
+    }
+
+    if (tmpSpline->spline == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->spline member.\n");
+        testStatus = false;
+    } else {
+        for (psS32 i = 0 ; i < NumSplines ; i++) {
+            if (tmpSpline->spline[i] == NULL) {
+                printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->spline[%d] member.\n", i);
+                testStatus = false;
+            } else {
+                if (psTraceGetLevel(__func__) >= 6) {
+                    PS_POLY_PRINT_1D(tmpSpline->spline[i]);
+                }
+            }
+        }
+    }
+
+    if (tmpSpline->knots == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->knots member.\n");
+        testStatus = false;
+    }
+
+    if (tmpSpline->p_psDeriv2 == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->p_psDeriv2 member.\n");
+        testStatus = false;
+    }
+
+    if (testStatus == true) {
+        for (psS32 i=0;i<NumSplines;i++) {
+            x = 0.5 + (float) i;
+            y = psSpline1DEval(tmpSpline, x);
+            if (CheckErrorF32(y, myFunc00b(x))) {
+                printf("TEST ERROR: f(%f) is %f, should be %f\n", x, y, myFunc00b(x));
+                testStatus = false;
+            }
+        }
+    }
+
+    psFree(tmpSpline);
+    psFree(xF32);
+    psFree(xF64);
+    psFree(yF32);
+    psFree(yF64);
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    return (testStatus);
+}
+
+
+/*********************************************************************************
+psSplineEvalTest_sub00b():  This is similar to psSplineEvalTest_sub00b()
+except that the x vector is NULL.
+ ********************************************************************************/
+psS32 psSplineEvalTest_sub00c(psS32 NumSplines)
+{
+    printf("\n");
+    printf("psSplineEvalTest_sub00c(): This is similar to psSplineEvalTest_sub00b()\n");
+    printf("except that the x vector is NULL.\n");
+    printf("    Number of splines: %d\n", NumSplines);
+    psS32 testStatus = true;
+    psS32 memLeaks=0;
+    psF32 x;
+    psF32 y;
+    psS32  currentId = psMemGetId();
+    psVector *xF32 = NULL;
+    psVector *xF64 = NULL;
+    psVector *yF32 = NULL;
+    psVector *yF64 = NULL;
+    psSpline1D *tmpSpline = NULL;
+
+    /****************************************************************************/
+    /*    PS_TYPE_F32, PS_TYPE_F32 test          */
+    /****************************************************************************/
+    printf("Performing the F32 test....\n");
+    xF32 = psVectorAlloc(NumSplines+1, PS_TYPE_F32);
+    xF64 = psVectorAlloc(NumSplines+1, PS_TYPE_F64);
+    yF32 = psVectorAlloc(NumSplines+1, PS_TYPE_F32);
+    yF64 = psVectorAlloc(NumSplines+1, PS_TYPE_F64);
+    xF32->n = NumSplines+1;
+    xF64->n = NumSplines+1;
+    yF32->n = NumSplines+1;
+    yF64->n = NumSplines+1;
+
+    for (psS32 i=0;i<NumSplines+1;i++) {
+        xF32->data.F32[i] = (psF32) i;
+        xF64->data.F64[i] = (psF64) i;
+        yF32->data.F32[i] = (psF32) myFunc00b(xF32->data.F32[i]);
+        yF64->data.F64[i] = (psF64) myFunc00b(xF32->data.F32[i]);
+    }
+
+    tmpSpline = psVectorFitSpline1D(NULL, yF32);
+    if (tmpSpline == NULL) {
+        printf("TEST ERROR: Could not allocate psSpline1D data structure\n");
+        testStatus = false;
+    }
+
+    if (tmpSpline->n != NumSplines) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->n member.\n");
+        printf("            psSpline1D->NumSplines was %d, should be %d.\n", tmpSpline->n, NumSplines);
+        testStatus = false;
+    }
+
+    if (tmpSpline->spline == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->spline member.\n");
+        testStatus = false;
+    } else {
+        for (psS32 i = 0 ; i < NumSplines ; i++) {
+            if (tmpSpline->spline[i] == NULL) {
+                printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->spline[%d] member.\n", i);
+                testStatus = false;
+            } else {
+                if (psTraceGetLevel(__func__) >= 6) {
+                    PS_POLY_PRINT_1D(tmpSpline->spline[i]);
+                }
+            }
+        }
+    }
+
+    if (tmpSpline->knots == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->knots member.\n");
+        testStatus = false;
+    }
+
+    if (tmpSpline->p_psDeriv2 == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->p_psDeriv2 member.\n");
+        testStatus = false;
+    }
+
+    if (testStatus == true) {
+        for (psS32 i=0;i<NumSplines;i++) {
+            x = 0.5 + (float) i;
+            y = psSpline1DEval(tmpSpline, x);
+            if (CheckErrorF32(y, myFunc00b(x))) {
+                printf("TEST ERROR: f(%f) is %f, should be %f\n", x, y, myFunc00b(x));
+                testStatus = false;
+            }
+        }
+    }
+
+    psFree(tmpSpline);
+    psFree(xF32);
+    psFree(xF64);
+    psFree(yF32);
+    psFree(yF64);
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    /****************************************************************************/
+    /*    PS_TYPE_F64, PS_TYPE_F64 test          */
+    /****************************************************************************/
+    printf("Performing the F64 test....\n");
+    xF32 = psVectorAlloc(NumSplines+1, PS_TYPE_F32);
+    xF64 = psVectorAlloc(NumSplines+1, PS_TYPE_F64);
+    yF32 = psVectorAlloc(NumSplines+1, PS_TYPE_F32);
+    yF64 = psVectorAlloc(NumSplines+1, PS_TYPE_F64);
+    xF32->n = NumSplines+1;
+    xF64->n = NumSplines+1;
+    yF32->n = NumSplines+1;
+    yF64->n = NumSplines+1;
+
+    for (psS32 i=0;i<NumSplines+1;i++) {
+        xF32->data.F32[i] = (psF32) i;
+        xF64->data.F64[i] = (psF64) i;
+        yF32->data.F32[i] = (psF32) myFunc00b(xF32->data.F32[i]);
+        yF64->data.F64[i] = (psF64) myFunc00b(xF32->data.F32[i]);
+    }
+
+    tmpSpline = psVectorFitSpline1D(NULL, yF64);
+    if (tmpSpline == NULL) {
+        printf("TEST ERROR: Could not allocate psSpline1D data structure\n");
+        testStatus = false;
+    }
+
+    if (tmpSpline->n != NumSplines) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->n member.\n");
+        printf("            psSpline1D->NumSplines was %d, should be %d.\n", tmpSpline->n, NumSplines);
+        testStatus = false;
+    }
+
+    if (tmpSpline->spline == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->spline member.\n");
+        testStatus = false;
+    } else {
+        for (psS32 i = 0 ; i < NumSplines ; i++) {
+            if (tmpSpline->spline[i] == NULL) {
+                printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->spline[%d] member.\n", i);
+                testStatus = false;
+            } else {
+                if (psTraceGetLevel(__func__) >= 6) {
+                    PS_POLY_PRINT_1D(tmpSpline->spline[i]);
+                }
+            }
+        }
+    }
+
+    if (tmpSpline->knots == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->knots member.\n");
+        testStatus = false;
+    }
+
+    if (tmpSpline->p_psDeriv2 == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->p_psDeriv2 member.\n");
+        testStatus = false;
+    }
+
+    if (testStatus == true) {
+        for (psS32 i=0;i<NumSplines;i++) {
+            x = 0.5 + (float) i;
+            y = psSpline1DEval(tmpSpline, x);
+            if (CheckErrorF32(y, myFunc00b(x))) {
+                printf("TEST ERROR: f(%f) is %f, should be %f\n", x, y, myFunc00b(x));
+                testStatus = false;
+            }
+        }
+    }
+
+    psFree(tmpSpline);
+    psFree(xF32);
+    psFree(xF64);
+    psFree(yF32);
+    psFree(yF64);
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    return (testStatus);
+}
+
+
+
+psS32 psSplineEvalTest()
+{
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("spline1DFree", 0);
+    psTraceSetLevel("calculateSecondDerivs", 0);
+    psTraceSetLevel("vectorBinDisectF32", 0);
+    psTraceSetLevel("vectorBinDisectF64", 0);
+    psTraceSetLevel("p_psVectorBinDisect", 0);
+    psTraceSetLevel("psSpline1DAlloc", 0);
+    psTraceSetLevel("psVectorFitSpline1D", 0);
+    psTraceSetLevel("psSpline1DEval", 0);
+    psTraceSetLevel("psSpline1DEvalVector", 0);
+
+    psS32 testStatus = psSplineEvalTest_sub(10);
+
+    // HEY: XXX: Test with empty psVectors.
+    //    testStatus |= psSplineEvalTest_sub00(0);
+    //    testStatus |= psSplineEvalTest_sub00b(0);
+    //    testStatus |= psSplineEvalTest_sub00c(0);
+
+    testStatus |= psSplineEvalTest_sub00(1);
+    testStatus |= psSplineEvalTest_sub00b(1);
+    testStatus |= psSplineEvalTest_sub00c(1);
+
+    testStatus |= psSplineEvalTest_sub00(95);
+    testStatus |= psSplineEvalTest_sub00b(95);
+    testStatus |= psSplineEvalTest_sub00c(95);
+
+    return(testStatus);
+}
+
+
+
+psS32 psSplineEvalVectorTest_sub00(psS32 NumSplines)
+{
+    psS32 testStatus = true;
+    psS32 memLeaks=0;
+
+    psS32  currentId = psMemGetId();
+    psVector *xF32 = NULL;
+    psVector *yF32 = NULL;
+    psSpline1D *tmpSpline = NULL;
+    /****************************************************************************/
+    /*    PS_TYPE_F32, PS_TYPE_F32 test          */
+    /****************************************************************************/
+    printf("Performing the F32 test....\n");
+    xF32 = psVectorAlloc(NumSplines+1, PS_TYPE_F32);
+    yF32 = psVectorAlloc(NumSplines+1, PS_TYPE_F32);
+    psVector *xF32Test = psVectorAlloc(NumSplines, PS_TYPE_F32);
+    psVector *yF32Test = NULL;
+    psVector *xF64Test = psVectorAlloc(NumSplines, PS_TYPE_F64);
+    xF32->n = NumSplines+1;
+    yF32->n = NumSplines+1;
+    xF32Test->n = NumSplines;
+    xF64Test->n = NumSplines;
+
+
+    for (psS32 i=0;i<NumSplines+1;i++) {
+        xF32->data.F32[i] = (psF32) i;
+        yF32->data.F32[i] = (psF32) i;
+    }
+
+    tmpSpline = psVectorFitSpline1D(xF32, yF32);
+    if (tmpSpline == NULL) {
+        printf("TEST ERROR: Could not allocate psSpline1D data structure\n");
+        testStatus = false;
+    }
+
+    if (tmpSpline->n != NumSplines) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->n member.\n");
+        printf("            psSpline1D->NumSplines was %d, should be %d.\n", tmpSpline->n, NumSplines);
+        testStatus = false;
+    }
+
+    if (tmpSpline->spline == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->spline member.\n");
+        testStatus = false;
+    } else {
+        for (psS32 i = 0 ; i < NumSplines ; i++) {
+            if (tmpSpline->spline[i] == NULL) {
+                printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->spline[%d] member.\n", i);
+                testStatus = false;
+            } else {
+                if (psTraceGetLevel(__func__) >= 6) {
+                    PS_POLY_PRINT_1D(tmpSpline->spline[i]);
+                }
+            }
+        }
+    }
+
+    if (tmpSpline->knots == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->knots member.\n");
+        testStatus = false;
+    }
+
+    if (tmpSpline->p_psDeriv2 == NULL) {
+        printf("TEST ERROR: psVectorFitSpline1D() did not properly set the psSpline1D->p_psDeriv2 member.\n");
+        testStatus = false;
+    }
+
+    printf("Testing psSpline1DEvalVector() with an F32 vector.\n");
+    if (testStatus == true) {
+        for (psS32 i=0;i<NumSplines;i++) {
+            xF32Test->data.F32[i] = 0.5 + (psF32) i;
+        }
+        yF32Test = psSpline1DEvalVector(tmpSpline, xF32Test);
+
+        for (psS32 i=0;i<NumSplines;i++) {
+            if (CheckErrorF32(yF32Test->data.F32[i], xF32Test->data.F32[i])) {
+                printf("TEST ERROR: f(%f) is %f\n", xF32Test->data.F32[i], yF32Test->data.F32[i]);
+                testStatus = false;
+            }
+        }
+        psFree(yF32Test);
+    }
+
+    printf("Testing psSpline1DEvalVector() with an F64 vector.\n");
+    if (testStatus == true) {
+        for (psS32 i=0;i<NumSplines;i++) {
+            xF64Test->data.F64[i] = 0.5 + (psF64) i;
+        }
+        yF32Test = psSpline1DEvalVector(tmpSpline, xF64Test);
+
+        for (psS32 i=0;i<NumSplines;i++) {
+            if (CheckErrorF32(yF32Test->data.F32[i], (psF32) xF64Test->data.F64[i])) {
+                printf("TEST ERROR: f(%f) is %f\n", (psF32) xF64Test->data.F64[i], yF32Test->data.F32[i]);
+                testStatus = false;
+            }
+        }
+    }
+
+    psFree(tmpSpline);
+    psFree(xF32);
+    psFree(yF32);
+    psFree(xF32Test);
+    psFree(yF32Test);
+    psFree(xF64Test);
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    return (testStatus);
+}
+
+psS32 psSplineEvalVectorTest()
+{
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("spline1DFree", 0);
+    psTraceSetLevel("calculateSecondDerivs", 0);
+    psTraceSetLevel("vectorBinDisectF32", 0);
+    psTraceSetLevel("vectorBinDisectF64", 0);
+    psTraceSetLevel("p_psVectorBinDisect", 0);
+    psTraceSetLevel("psSpline1DAlloc", 0);
+    psTraceSetLevel("psVectorFitSpline1D", 0);
+    psTraceSetLevel("psSpline1DEval", 0);
+    psTraceSetLevel("psSpline1DEvalVector", 0);
+
+    return(psSplineEvalVectorTest_sub00(10));
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats00.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats00.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats00.c	(revision 22158)
@@ -0,0 +1,435 @@
+/** @file  tst_psStats00.c
+*
+*  @brief Contains tests for psVectorStats with sample mean calculations
+*
+*  We extensively test the code with data type PS_TYPE_F32.  If these pass, we
+*  do a much simpler test with data type PS_TYPE_U8, PS_TYPE_U16, PS_TYPE_F64.
+*
+*  If the psStats,c code ever changes such that vectors of different type
+*  are handled by different routines, then these tests must be extended.
+*
+*  @author GLG, MHPCC
+*
+*  @version $Revision: 1.8 $  $Name: not supported by cvs2svn $
+*  @date $Date: 2006-07-28 00:44:05 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*/
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+#define ERROR_TOL  0.0001
+#define N 15
+#define VERBOSE 1
+static psS32 testStatsSampleMeanF32(void);
+static psS32 testStatsSampleMeanS8(void);
+static psS32 testStatsSampleMeanU16(void);
+static psS32 testStatsSampleMeanF64(void);
+
+testDescription tests[] = {
+                              {testStatsSampleMeanF32, 512, "psVectorStats",0,false},
+                              {testStatsSampleMeanS8, 512, "psVectorStats",0,false},
+                              {testStatsSampleMeanU16, 512, "psVectorStats",0,false},
+                              {testStatsSampleMeanF64, 512, "psVectorStats",0,false},
+                              {NULL}
+                          };
+
+static psF32 samplesF32[N] = { 1.1, 2.2, -3.3, 4.4, 5.5, -6.6, 7.7, 8.8, -9.9, 10.0,
+                               11.01, -12.02, 13.03, 14.04, -15.05 };
+static psS8  samplesS8[N]  = {1, 2, -3, 4, 5, -6, 7, 8, -9, 10, 11, -12, 13, 14, -15};
+static psU16 samplesU16[N] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+static psF64 samplesF64[N] = { 1.1, 2.2, -3.3, 4.4, 5.5, -6.6, 7.7, 8.8, -9.9, 10.0,
+                               11.01, -12.02, 13.03, 14.04, -15.05 };
+static psF32 errorsF32[N] = { -0.10,  0.11, -0.12,  0.13, -0.14,  0.15, -0.16,  0.17,
+                              -0.18,  0.19, -0.20,  0.21, -0.22,  0.23, -0.24 };
+
+static psF64 expectedMeanNoMaskF32              =  2.060667;
+static psF64 expectedMeanWithMaskF32            =  2.123846;
+static psF64 expectedMeanNoMaskS8               =  2.000000;
+static psF64 expectedMeanNoMaskU16              =  8.000000;
+static psF64 expectedMeanNoMaskF64              =  2.060667;
+static psF64 expectedMeanRangeNoMaskF32         =  0.137500;
+static psF64 expectedMeanRangeWithMaskF32       = -0.366667;
+static psF64 expectedWeightMeanNoMaskF32        =  1.807210;
+static psF64 expectedWeightMeanWithMaskF32      =  1.890217;
+static psF64 expectedWeightMeanNoMaskRangeF32   =  0.640952;
+static psF64 expectedWeightMeanWithMaskRangeF32 =  0.046574;
+
+psF64 rtc(void);
+psF64 sT, eT;
+psF64 diff;
+
+#include <unistd.h>
+psS32 main(psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    //
+    // We list pertinent psStats.c functions here for debugging ease.
+    //
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("p_psVectorSampleMean", 10);
+    psTraceSetLevel("p_psVectorMax", 0);
+    psTraceSetLevel("p_psVectorMin", 0);
+    psTraceSetLevel("p_psVectorNValues", 0);
+    psTraceSetLevel("p_psNormalizeVectorRange", 0);
+    psTraceSetLevel("psStatsAlloc", 0);
+    psTraceSetLevel("p_psConvertToF32", 0);
+    psTraceSetLevel("psVectorStats", 0);
+
+    return ( ! runTestSuite(stderr, "psVectorStats",tests,argc,argv) );
+}
+
+psS32 testStatsSampleMeanF32(void)
+{
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    psVector *myVector = psVectorAlloc(N, PS_TYPE_F32);
+    myVector->n = N;
+    psVector *myErrors = psVectorAlloc(N, PS_TYPE_F32);
+    myErrors->n = N;
+    psVector *maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    maskVector->n = N;
+
+    psF64 mean = 0.0;
+    // Set the appropriate values for the vector data.
+    for (long i = 0; i < N; i++) {
+        myVector->data.F32[i] =  samplesF32[i];
+        myErrors->data.F32[i] =  errorsF32[i];
+    }
+
+    // Set the mask vector and calculate the expected maximum.
+    for (psS32 i = 0; i < N; i++) {
+
+        if (i > 1) {
+            maskVector->data.U8[i] = 0;
+        } else {
+            maskVector->data.U8[i] = 1;
+        }
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+    mean = myStats->sampleMean;
+    // Verify return value is as expected
+    if (VERBOSE) {
+        printf("psVectorStats() returned %.2f: expected was %.2f\n", mean, expectedMeanNoMaskF32);
+    }
+    if (isnan(myStats->sampleMean) || (fabs(mean - expectedMeanNoMaskF32) > ERROR_TOL)) {
+        psError(PS_ERR_UNKNOWN,true,"Returned value %f not as expected %f",
+                mean, expectedMeanNoMaskF32);
+        return 1;
+    }
+
+    // Invoke psVectorStats with no vector mask and error vector
+    myStats = psVectorStats(myStats, myVector, myErrors, NULL, 0);
+    mean = myStats->sampleMean;
+    // Verify return value is as expected
+    if (VERBOSE) {
+        printf("psVectorStats() returned %.2f: expected was %.2f\n", mean, expectedWeightMeanNoMaskF32);
+    }
+    if (isnan(myStats->sampleMean) || (fabs(mean - expectedWeightMeanNoMaskF32) > ERROR_TOL)) {
+        psError(PS_ERR_UNKNOWN,true,"Returned value %f not as expected %f",
+                mean, expectedWeightMeanNoMaskF32);
+        return 10;
+    }
+
+    // Invoke psVectorStats with no vector mask and data range
+    myStats->min = -10.0;
+    myStats->max =   8.0;
+    myStats->options = PS_STAT_SAMPLE_MEAN | PS_STAT_USE_RANGE;
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+    mean = myStats->sampleMean;
+    // Verify return value is as expected
+    if (VERBOSE) {
+        printf("psVectorStats() returned %.2f: expected was %.2f\n", mean, expectedMeanRangeNoMaskF32);
+    }
+    if ( fabs(mean - expectedMeanRangeNoMaskF32) > ERROR_TOL ) {
+        psError(PS_ERR_UNKNOWN,true,"Return value %f not as expected %f",
+                mean, expectedMeanRangeNoMaskF32);
+        return 2;
+    }
+
+    // Invoke psVectorStats with no vector mask, errors and data range
+    myStats = psVectorStats(myStats, myVector, myErrors, NULL, 0);
+    mean = myStats->sampleMean;
+    // Verify return value is as expected
+    if (VERBOSE) {
+        printf("psVectorStats() returned %.2f: expected was %.2f\n", mean, expectedWeightMeanNoMaskRangeF32);
+    }
+    if ( fabs(mean - expectedWeightMeanNoMaskRangeF32) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Return value %f not as expected %f",
+                mean, expectedWeightMeanNoMaskRangeF32);
+        return 20;
+    }
+    myStats->options = PS_STAT_SAMPLE_MEAN;
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask=1.                             */
+    /*************************************************************************/
+    myStats = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+    mean = myStats->sampleMean;
+    if (VERBOSE) {
+        printf("psVectorStats() returned %.2f: expected was %.2f\n", mean, expectedMeanWithMaskF32);
+    }
+    if ( fabs(mean - expectedMeanWithMaskF32) > ERROR_TOL ) {
+        psError(PS_ERR_UNKNOWN,true,"Returned value %f not as expected %f",
+                mean, expectedMeanWithMaskF32);
+        return 3;
+    }
+
+    // Invoke psVectorStats with vector mask and error vector
+    myStats = psVectorStats(myStats, myVector, myErrors, maskVector, 1);
+    mean = myStats->sampleMean;
+    if (VERBOSE) {
+        printf("psVectorStats() returned %.2f: expected was %.2f\n", mean, expectedWeightMeanWithMaskF32);
+    }
+    if ( fabs(mean - expectedWeightMeanWithMaskF32) > ERROR_TOL ) {
+        psError(PS_ERR_UNKNOWN,true,"Returned value %f not as expected %f",
+                mean, expectedWeightMeanWithMaskF32);
+        return 30;
+    }
+
+    // Invoke psVectorStats with vector mask and data range
+    myStats->options = PS_STAT_SAMPLE_MEAN | PS_STAT_USE_RANGE;
+    myStats = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+    mean = myStats->sampleMean;
+    // Verify return value is as expected
+    if (VERBOSE) {
+        printf("psVectorStats() returned %.2f: expected was %.2f\n", mean, expectedMeanRangeWithMaskF32);
+    }
+    if ( fabs(mean - expectedMeanRangeWithMaskF32) > ERROR_TOL ) {
+        psError(PS_ERR_UNKNOWN,true,"Return value %f not as expected %f",
+                mean, expectedMeanRangeWithMaskF32);
+        return 4;
+    }
+
+    // Invoke psVectorStats with vector mask, errors, and data range
+    myStats = psVectorStats(myStats, myVector, myErrors, maskVector, 1);
+    mean = myStats->sampleMean;
+    // Verify return value is as expected
+    if (VERBOSE) {
+        printf("psVectorStats() returned %.2f: expected was %.2f\n", mean, expectedWeightMeanWithMaskRangeF32);
+    }
+    if ( fabs(mean - expectedWeightMeanWithMaskRangeF32) > ERROR_TOL ) {
+        psError(PS_ERR_UNKNOWN,true,"Return value %f not as expected %f",
+                mean, expectedWeightMeanWithMaskRangeF32);
+        return 40;
+    }
+    myStats->options = PS_STAT_SAMPLE_MEAN;
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask=2.                             */
+    /*************************************************************************/
+    // Set the mask vector and calculate the expected maximum.
+    // Set the mask vector.
+    for (psS32 i = 0; i < N; i++) {
+        if (maskVector->data.U8[i] == 1) {
+            maskVector->data.U8[i] = 2;
+        }
+    }
+    myStats = psVectorStats(myStats, myVector, NULL, maskVector, 2);
+    mean = myStats->sampleMean;
+    if (VERBOSE) {
+        printf("psVectorStats() returned %.2f: expected was %.2f\n", mean, expectedMeanWithMaskF32);
+    }
+    if (fabs(mean - expectedMeanWithMaskF32) > ERROR_TOL )  {
+        psError(PS_ERR_UNKNOWN,true,"Returned value %f not as expected %f",
+                mean,expectedMeanWithMaskF32);
+        return 5;
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask=3.                             */
+    /*************************************************************************/
+    // Set the mask vector and calculate the expected maximum.
+    // Set the mask vector.
+    for (psS32 i = 0; i < N; i++) {
+        if (maskVector->data.U8[i] == 2) {
+            maskVector->data.U8[i] = 3;
+        }
+    }
+    myStats = psVectorStats(myStats, myVector, NULL, maskVector, 4);
+    mean = myStats->sampleMean;
+    if (VERBOSE) {
+        printf("psVectorStats() returned %.2f: expected was %.2f\n", mean, expectedMeanNoMaskF32);
+    }
+    if (fabs(mean - expectedMeanNoMaskF32) > ERROR_TOL ) {
+        psError(PS_ERR_UNKNOWN,true,"Return value %f not as expected %f",
+                mean,expectedMeanNoMaskF32);
+        return 6;
+    }
+
+    // Mask all values and verify return is NAN
+    for(psS32 i = 0; i < N; i++) {
+        maskVector->data.U8[i] = 1;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate warning message");
+    myStats = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+    mean = myStats->sampleMean;
+    if( !isnan(mean) ) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NAN with all values masked");
+        return 7;
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with NULL inputs.                               */
+    /*************************************************************************/
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message.");
+    if( psVectorStats(myStats, NULL, NULL, NULL, 0) != NULL ) {
+        psError(PS_ERR_UNKNOWN,true,"psVectorStats did not return NULL");
+        return 8;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message.");
+    psStats *myStats2 = psVectorStats(NULL, myVector, NULL, NULL, 0);
+    if ( myStats2 != NULL ) {
+        psError(PS_ERR_UNKNOWN,true,"psVectorStats did not return NULL");
+        return 9;
+    }
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                           */
+    /*************************************************************************/
+    psFree(myStats);
+    psFree(myVector);
+    psFree(myErrors);
+    psFree(maskVector);
+    psFree(myStats2);
+
+    return 0;
+}
+
+psS32 testStatsSampleMeanS8(void)
+{
+    psStats*  myStats  = NULL;
+    psVector* myVector = NULL;
+    psF64     mean     = 0.0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    myVector = psVectorAlloc(N, PS_TYPE_S8);
+    myVector->n = N;
+
+    mean = 0.0;
+    // Set the appropriate values for the vector data.
+    for (psS32 i = 0; i < N; i++) {
+        myVector->data.S8[i] =  samplesS8[i];
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+    mean = myStats->sampleMean;
+    // Verify return value is as expected
+    if (VERBOSE) {
+        printf("psVectorStats() returned %.2f: expected was %.2f\n", mean, expectedMeanNoMaskS8);
+    }
+    if ( fabs(mean - expectedMeanNoMaskS8) > ERROR_TOL ) {
+        psError(PS_ERR_UNKNOWN,true,"Returned value %f not as expected %f",
+                mean, expectedMeanNoMaskS8);
+        return 1;
+    }
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                           */
+    /*************************************************************************/
+    psFree(myStats);
+    psFree(myVector);
+
+    return 0;
+}
+
+psS32 testStatsSampleMeanU16(void)
+{
+    psStats*  myStats  = NULL;
+    psVector* myVector = NULL;
+    psF64     mean     = 0.0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    myVector = psVectorAlloc(N, PS_TYPE_U16);
+    myVector->n = N;
+
+    mean = 0.0;
+    // Set the appropriate values for the vector data.
+    for (psS32 i = 0; i < N; i++) {
+        myVector->data.U16[i] =  samplesU16[i];
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+    mean = myStats->sampleMean;
+    // Verify return value is as expected
+    if (VERBOSE) {
+        printf("psVectorStats() returned %.2f: expected was %.2f\n", mean, expectedMeanNoMaskU16);
+    }
+    if ( fabs(mean - expectedMeanNoMaskU16) > ERROR_TOL ) {
+        psError(PS_ERR_UNKNOWN,true,"Returned value %f not as expected %f",
+                mean, expectedMeanNoMaskU16);
+        return 1;
+    }
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                           */
+    /*************************************************************************/
+    psFree(myStats);
+    psFree(myVector);
+
+    return 0;
+}
+
+psS32 testStatsSampleMeanF64(void)
+{
+    psStats*  myStats  = NULL;
+    psVector* myVector = NULL;
+    psF64     mean     = 0.0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    myVector = psVectorAlloc(N, PS_TYPE_F64);
+    myVector->n = N;
+
+    mean = 0.0;
+    // Set the appropriate values for the vector data.
+    for (psS32 i = 0; i < N; i++) {
+        myVector->data.F64[i] =  samplesF64[i];
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+    mean = myStats->sampleMean;
+    // Verify return value is as expected
+    if (VERBOSE) {
+        printf("psVectorStats() returned %.2f: expected was %.2f\n", mean, expectedMeanNoMaskF64);
+    }
+    if ( fabs(mean - expectedMeanNoMaskF64) > ERROR_TOL ) {
+        psError(PS_ERR_UNKNOWN,true,"Returned value %f not as expected %f",
+                mean, expectedMeanNoMaskF64);
+        return 1;
+    }
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                           */
+    /*************************************************************************/
+    psFree(myStats);
+    psFree(myVector);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats01.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats01.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats01.c	(revision 22158)
@@ -0,0 +1,276 @@
+/** @file  tst_psStats01.c
+*
+*  @brief Contains tests for psVectorStats with max calculations.
+*
+*  We extensively test the code with data type PS_TYPE_F32.  If these pass, we
+*  do a much simpler test with data types PS_TYPE_U8, PS_TYPE_U16, PS_TYPE_F64.
+*
+*  If the psStats,c code every changes such that vectors of different type
+*  are handled by different routines, then these tests must be extended.
+*
+*  @author GLG, MHPCC
+*
+*  @version $Revision: 1.4 $  $Name: not supported by cvs2svn $
+*  @date $Date: 2006-07-28 00:44:05 $
+*
+* Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*/
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+#define N 15
+#define ERROR_TOL  0.0001
+
+static psS32 testStatsMaxF32(void);
+static psS32 testStatsMaxS8(void);
+static psS32 testStatsMaxU16(void);
+static psS32 testStatsMaxF64(void);
+
+testDescription tests[] = {
+                              {testStatsMaxF32, 518, "psVectorStats", 0, false},
+                              {testStatsMaxS8, 518, "psVectorStats", 0, false},
+                              {testStatsMaxU16, 518, "psVectorStats", 0, false},
+                              {testStatsMaxF64, 518, "psVectorStats", 0, false},
+                              {NULL}
+                          };
+
+static psF32 samplesF32[N] = { 1.1, 2.2, -3.3, 4.4, 5.5, -6.6, 7.7, 8.8, -9.9, 10.0,
+                               11.01, -12.02, 13.03, 14.04, -15.05 };
+static psS8  samplesS8[N]  = {1, 2, -3, 4, 5, -6, 7, 8, -9, 10, 11, -12, 13, 14, -15};
+static psU16 samplesU16[N] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+static psF64 samplesF64[N] = { 1.1, 2.2, -3.3, 4.4, 5.5, -6.6, 7.7, 8.8, -9.9, 10.0,
+                               11.01, -12.02, 13.03, 14.04, -15.05 };
+
+static psF64 expectedMaxNoMaskF32                = 14.04;
+static psF64 expectedMaxNoMaskS8                 = 14.00;
+static psF64 expectedMaxNoMaskU16                = 15.00;
+static psF64 expectedMaxNoMaskF64                = 14.04;
+
+static psF64 expectedMaxWithMaskF32              = 13.03;
+static psF64 expectedMaxRangeNoMaskF32           = 10.00;
+static psF64 expectedMaxRangeWithMaskF32         = 13.03;
+
+psS32 main(psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    //
+    // We list pertinent psStats.c functions here for debugging ease.
+    //
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("p_psVectorMax", 0);
+    psTraceSetLevel("p_psVectorMin", 0);
+    psTraceSetLevel("p_psVectorCheckNonEmpty", 0);
+    psTraceSetLevel("p_psVectorNValues", 0);
+    psTraceSetLevel("psStatsAlloc", 0);
+    psTraceSetLevel("p_psConvertToF32", 0);
+    psTraceSetLevel("psVectorStats", 0);
+
+    return ( ! runTestSuite(stderr, "psVectorStats", tests, argc, argv) );
+}
+
+psS32 testStatsMaxF32(void)
+{
+    psStats*  myStats    = NULL;
+    psVector* myVector   = NULL;
+    psVector* maskVector = NULL;
+    psF64     max        = 0.0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_MAX);
+    myVector = psVectorAlloc(N, PS_TYPE_F32);
+    myVector->n = N;
+    maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    maskVector->n = N;
+
+    // Set the appropriate values for the vector data.
+    for (psS32 i = 0; i < N; i++) {
+        myVector->data.F32[i] = samplesF32[i];
+    }
+
+    // Set the mask vector and calculate the expected maximum.
+    for (psS32 i = 0; i < N; i++) {
+        if (i < 13) {
+            maskVector->data.U8[i] = 0;
+        } else {
+            maskVector->data.U8[i] = 1;
+        }
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+    max = myStats->max;
+
+    if (fabs(max - expectedMaxNoMaskF32) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Max no mask return value %lf not as expected %lf",
+                max, expectedMaxNoMaskF32);
+        return 1;
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask.                       */
+    /*************************************************************************/
+    myStats = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+    max = myStats->max;
+    if (fabs(max - expectedMaxWithMaskF32) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Max with mask return value %lf not as expected %lf",
+                max, expectedMaxWithMaskF32);
+        return 2;
+    }
+
+    // Invoke function with data range with no mask
+    myStats->options = PS_STAT_MAX | PS_STAT_USE_RANGE;
+    myStats->max = 10.1;
+    myStats->min = 0.0;
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+    max = myStats->max;
+
+    if(fabs(max - expectedMaxRangeNoMaskF32) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Max with range no mask %lf not as expected %lf",
+                max, expectedMaxRangeNoMaskF32);
+        return 3;
+    }
+
+    // Invoke function with data range and mask
+    myStats->max = 14.0;
+    myStats->min = 0.0;
+    myStats = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+    max = myStats->max;
+    if(fabs(max - expectedMaxRangeWithMaskF32) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Max with range with mask %lf not as expected %lf",
+                max, expectedMaxRangeWithMaskF32);
+        return 3;
+    }
+
+    // Invoke function with data range with no valid data
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    myStats->max = 100.00;
+    myStats->min = 90.00;
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+    max = myStats->max;
+
+    if(!isnan(max)) {
+        psError(PS_ERR_UNKNOWN,true,"Max with range with no valid elemenets did not return NAN");
+        return 4;
+    }
+
+    psFree(myStats);
+    psFree(myVector);
+    psFree(maskVector);
+
+    return 0;
+}
+
+psS32 testStatsMaxS8(void)
+{
+    psStats*  myStats    = NULL;
+    psVector* myVector   = NULL;
+    psF64     max        = 0.0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_MAX);
+    myVector = psVectorAlloc(N, PS_TYPE_S8);
+    myVector->n = N;
+
+    // Set the appropriate values for the vector data.
+    for (psS32 i = 0; i < N; i++) {
+        myVector->data.S8[i] = samplesS8[i];
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+    max = myStats->max;
+
+    if (fabs(max - expectedMaxNoMaskS8) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Max no mask return value %lf not as expected %lf",
+                max, expectedMaxNoMaskS8);
+        return 1;
+    }
+
+    psFree(myStats);
+    psFree(myVector);
+
+    return 0;
+}
+
+psS32 testStatsMaxU16(void)
+{
+    psStats*  myStats    = NULL;
+    psVector* myVector   = NULL;
+    psF64     max        = 0.0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_MAX);
+    myVector = psVectorAlloc(N, PS_TYPE_U16);
+    myVector->n = N;
+
+    // Set the appropriate values for the vector data.
+    for (psS32 i = 0; i < N; i++) {
+        myVector->data.U16[i] = samplesU16[i];
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+    max = myStats->max;
+
+    if (fabs(max - expectedMaxNoMaskU16) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Max no mask return value %lf not as expected %lf",
+                max, expectedMaxNoMaskU16);
+        return 1;
+    }
+
+    psFree(myStats);
+    psFree(myVector);
+
+    return 0;
+}
+
+psS32 testStatsMaxF64(void)
+{
+    psStats*  myStats    = NULL;
+    psVector* myVector   = NULL;
+    psF64     max        = 0.0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_MAX);
+    myVector = psVectorAlloc(N, PS_TYPE_F64);
+    myVector->n = N;
+
+    // Set the appropriate values for the vector data.
+    for (psS32 i = 0; i < N; i++) {
+        myVector->data.F64[i] = samplesF64[i];
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+    max = myStats->max;
+
+    if (fabs(max - expectedMaxNoMaskF64) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Max no mask return value %lf not as expected %lf",
+                max, expectedMaxNoMaskF64);
+        return 1;
+    }
+
+    psFree(myStats);
+    psFree(myVector);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats02.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats02.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats02.c	(revision 22158)
@@ -0,0 +1,277 @@
+/** @file  tst_psStats02.c
+*
+*  @brief Contains tests for psVectorStats with min calculations
+*
+*  We extensively test the code with data type PS_TYPE_F32.  If these pass, we
+*  do a much simpler test with data types PS_TYPE_U8, PS_TYPE_U16, PS_TYPE_F64.
+*
+*  If the psStats,c code every changes such that vectors of different type
+*  are handled by different routines, then these tests must be extended.
+*
+*  @author GLG, MHPCC
+*
+*  @version $Revision: 1.4 $  $Name: not supported by cvs2svn $
+*  @date $Date: 2006-07-28 00:44:05 $
+*
+* Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*/
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+#define N 15
+#define ERROR_TOL  0.0001
+
+static psS32 testStatsMinF32(void);
+static psS32 testStatsMinS8(void);
+static psS32 testStatsMinU16(void);
+static psS32 testStatsMinF64(void);
+
+testDescription tests[] = {
+                              {testStatsMinF32, 518, "psVectorStats", 0, false},
+                              {testStatsMinS8, 518, "psVectorStats", 0, false},
+                              {testStatsMinU16, 518, "psVectorStats", 0, false},
+                              {testStatsMinF64, 518, "psVectorStats", 0, false},
+                              {NULL}
+                          };
+
+static psF32 samplesF32[N] = { 1.1, 2.2, -3.3, 4.4, 5.5, -6.6, 7.7, 8.8, -9.9, 10.0,
+                               11.01, -12.02, 13.03, 14.04, -15.05 };
+static psS8  samplesS8[N]  = {1, 2, -3, 4, 5, -6, 7, 8, -9, 10, 11, -12, 13, 14, -15};
+static psU16 samplesU16[N] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+static psF64 samplesF64[N] = { 1.1, 2.2, -3.3, 4.4, 5.5, -6.6, 7.7, 8.8, -9.9, 10.0,
+                               11.01, -12.02, 13.03, 14.04, -15.05 };
+
+static psF64 expectedMinNoMaskF32                = -15.05;
+static psF64 expectedMinNoMaskS8                 = -15.00;
+static psF64 expectedMinNoMaskU16                = 1.00;
+static psF64 expectedMinNoMaskF64                = -15.05;
+
+static psF64 expectedMinWithMaskF32              = -12.02;
+static psF64 expectedMinRangeNoMaskF32           =   1.10;
+static psF64 expectedMinRangeWithMaskF32         = -12.02;
+
+psS32 main(psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    //
+    // We list pertinent psStats.c functions here for debugging ease.
+    //
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("p_psVectorMax", 0);
+    psTraceSetLevel("p_psVectorMin", 0);
+    psTraceSetLevel("p_psVectorCheckNonEmpty", 0);
+    psTraceSetLevel("p_psVectorNValues", 0);
+    psTraceSetLevel("p_psNormalizeVectorRange", 0);
+    psTraceSetLevel("psStatsAlloc", 0);
+    psTraceSetLevel("p_psConvertToF32", 0);
+    psTraceSetLevel("psVectorStats", 0);
+
+    return ( ! runTestSuite(stderr, "psVectorStats", tests, argc, argv) );
+}
+
+psS32 testStatsMinF32(void)
+{
+    psStats*  myStats    = NULL;
+    psVector* myVector   = NULL;
+    psVector* maskVector = NULL;
+    psF64     min        = 0.0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_MIN);
+    myVector = psVectorAlloc(N, PS_TYPE_F32);
+    myVector->n = N;
+    maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    maskVector->n = N;
+
+    // Set the appropriate values for the vector data.
+    for (psS32 i = 0; i < N; i++) {
+        myVector->data.F32[i] = samplesF32[i];
+    }
+
+    // Set the mask vector and calculate the expected maximum.
+    for (psS32 i = 0; i < N; i++) {
+        if (i < 13) {
+            maskVector->data.U8[i] = 0;
+        } else {
+            maskVector->data.U8[i] = 1;
+        }
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+    min = myStats->min;
+
+    if (fabs(min - expectedMinNoMaskF32) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Min no mask return value %lf not as expected %lf",
+                min, expectedMinNoMaskF32);
+        return 1;
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask.                       */
+    /*************************************************************************/
+    myStats = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+    min = myStats->min;
+    if (fabs(min - expectedMinWithMaskF32) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Min with mask return value %lf not as expected %lf",
+                min, expectedMinWithMaskF32);
+        return 2;
+    }
+
+    // Invoke function with data range with no mask
+    myStats->options = PS_STAT_MIN | PS_STAT_USE_RANGE;
+    myStats->max = 10.1;
+    myStats->min = 0.0;
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+    min = myStats->min;
+
+    if(fabs(min - expectedMinRangeNoMaskF32) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Min with range no mask %lf not as expected %lf",
+                min, expectedMinRangeNoMaskF32);
+        return 3;
+    }
+
+    // Invoke function with data range and mask
+    myStats->max = 10.1;
+    myStats->min = -15.00;
+    myStats = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+    min = myStats->min;
+    if(fabs(min - expectedMinRangeWithMaskF32) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Min with range with mask %lf not as expected %lf",
+                min, expectedMinRangeWithMaskF32);
+        return 3;
+    }
+
+    // Invoke function with data range with no valid data
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    myStats->max = 100.00;
+    myStats->min = 90.00;
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+    min = myStats->min;
+
+    if(!isnan(min)) {
+        psError(PS_ERR_UNKNOWN,true,"Min with range with no valid elemenets did not return NAN");
+        return 4;
+    }
+
+    psFree(myStats);
+    psFree(myVector);
+    psFree(maskVector);
+
+    return 0;
+}
+
+psS32 testStatsMinS8(void)
+{
+    psStats*  myStats    = NULL;
+    psVector* myVector   = NULL;
+    psF64     min        = 0.0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_MIN);
+    myVector = psVectorAlloc(N, PS_TYPE_S8);
+    myVector->n = N;
+
+    // Set the appropriate values for the vector data.
+    for (psS32 i = 0; i < N; i++) {
+        myVector->data.S8[i] = samplesS8[i];
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+    min = myStats->min;
+
+    if (fabs(min - expectedMinNoMaskS8) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Min no mask return value %lf not as expected %lf",
+                min, expectedMinNoMaskS8);
+        return 1;
+    }
+
+    psFree(myStats);
+    psFree(myVector);
+
+    return 0;
+}
+
+psS32 testStatsMinU16(void)
+{
+    psStats*  myStats    = NULL;
+    psVector* myVector   = NULL;
+    psF64     min        = 0.0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_MAX);
+    myVector = psVectorAlloc(N, PS_TYPE_U16);
+    myVector->n = N;
+
+    // Set the appropriate values for the vector data.
+    for (psS32 i = 0; i < N; i++) {
+        myVector->data.U16[i] = samplesU16[i];
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+    min = myStats->min;
+
+    if (fabs(min - expectedMinNoMaskU16) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Min no mask return value %lf not as expected %lf",
+                min, expectedMinNoMaskU16);
+        return 1;
+    }
+
+    psFree(myStats);
+    psFree(myVector);
+
+    return 0;
+}
+
+psS32 testStatsMinF64(void)
+{
+    psStats*  myStats    = NULL;
+    psVector* myVector   = NULL;
+    psF64     min        = 0.0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_MIN);
+    myVector = psVectorAlloc(N, PS_TYPE_F64);
+    myVector->n = N;
+
+    // Set the appropriate values for the vector data.
+    for (psS32 i = 0; i < N; i++) {
+        myVector->data.F64[i] = samplesF64[i];
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+    min = myStats->min;
+
+    if (fabs(min - expectedMinNoMaskF64) > ERROR_TOL) {
+        psError(PS_ERR_UNKNOWN,true,"Min no mask return value %lf not as expected %lf",
+                min, expectedMinNoMaskF64);
+        return 1;
+    }
+
+    psFree(myStats);
+    psFree(myVector);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats03.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats03.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats03.c	(revision 22158)
@@ -0,0 +1,136 @@
+/*****************************************************************************
+    This routine must ensure that PS_STAT_SAMPLE_MEDIAN is correctly computed
+    by the procedure psVectorStats().
+ 
+    XXX: Must add tests for various data types, other than psF32.  Copy code
+    from tst_psStats00.c-tst_psStats02.c.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+#define N1 1029   // This should be an odd number.
+#define N ((4 * N1) + 1)
+
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    //
+    // We list pertinent psStats.c functions here for debugging ease.
+    //
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("p_psVectorSampleMean", 0);
+    psTraceSetLevel("p_psVectorCheckNonEmpty", 0);
+    psTraceSetLevel("p_psVectorNValues", 0);
+    psTraceSetLevel("p_psVectorSampleMedian", 0);
+    psTraceSetLevel("psStatsAlloc", 0);
+    psTraceSetLevel("p_psConvertToF32", 0);
+    psTraceSetLevel("psVectorStats", 0);
+
+    psStats *myStats    = NULL;
+    psS32 testStatus      = true;
+    psS32 globalTestStatus = true;
+    psS32 i               = 0;
+    psVector *myVector  = NULL;
+    psVector *maskVector= NULL;
+    float median        = 1e99;
+    float realMedianWithMask = (float) (N-3)/4;
+    float realMedianNoMask = (float) (N-1)/2;
+    psS32 currentId       = psMemGetId();
+    psS32 memLeaks        = 0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_SAMPLE_MEDIAN);
+    myVector = psVectorAlloc(N, PS_TYPE_F32);
+    myVector->n = N;
+    maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    maskVector->n = N;
+
+    // Set the appropriate values for the vector data.
+    for (i=0;i<N;i++) {
+        myVector->data.F32[i] = (float) i;
+    }
+
+    // Set the mask vector and calculate the expected median.
+    for (i=0;i<N;i++) {
+        if (i < (N/2)) {
+            maskVector->data.U8[i] = 0;
+        } else {
+            maskVector->data.U8[i] = 1;
+        }
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_MEDIAN: no vector mask");
+
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+    median = myStats->sampleMedian;
+
+    printf("Called psVectorStats() on a vector with no elements masked.\n");
+    printf("The expected median was %f.  The calculated median was %f.\n",
+           realMedianNoMask, median);
+    if (median == realMedianNoMask) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+
+    printFooter(stdout,
+                "psStats functions",
+                "PS_STAT_SAMPLE_MEDIAN: no vector mask",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask.                       */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_MEDIAN: with vector mask");
+
+    myStats = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+    median = myStats->sampleMedian;
+    printf("Called psVectorStats() on a vector with last N/2 elements masked.\n");
+    printf("The expected median was %f.  The calculated median was %f.\n",
+           realMedianWithMask, median);
+    if (median == realMedianWithMask) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+
+    printFooter(stdout,
+                "psStats functions",
+                "PS_STAT_SAMPLE_MEDIAN: with vector mask",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "psStats(): deallocating memory");
+
+    psFree(myStats);
+    psFree(myVector);
+    psFree(maskVector);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    printFooter(stdout,
+                "psStats functions",
+                "psStats(): deallocating memory",
+                testStatus);
+
+    return (!globalTestStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats05.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats05.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats05.c	(revision 22158)
@@ -0,0 +1,86 @@
+/*****************************************************************************
+    This routine must ensure that the psStats structure is correctly
+    allocated and deallocated by the procedure psStatsAlloc().
+ 
+    XXX: This should be test 00.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+#define MISC_FLOAT_NUMBER 345.0
+
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    //
+    // We list pertinent psStats.c functions here for debugging ease.
+    //
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("psStatsAlloc", 0);
+
+    psStats *myStats    = NULL;
+    psS32 testStatus      = true;
+    psS32 currentId       = psMemGetId();
+    psS32 memLeaks        = 0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "Allocate the psStats structure.");
+
+    myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    myStats->sampleMean = MISC_FLOAT_NUMBER;
+    myStats->sampleMedian = MISC_FLOAT_NUMBER;
+    myStats->sampleStdev = MISC_FLOAT_NUMBER;
+    myStats->sampleUQ = MISC_FLOAT_NUMBER;
+    myStats->sampleLQ = MISC_FLOAT_NUMBER;
+    myStats->robustMedian = MISC_FLOAT_NUMBER;
+    myStats->robustStdev = MISC_FLOAT_NUMBER;
+    myStats->robustUQ = MISC_FLOAT_NUMBER;
+    myStats->robustLQ = MISC_FLOAT_NUMBER;
+    myStats->robustN50 = MISC_FLOAT_NUMBER;
+    myStats->fittedMean = MISC_FLOAT_NUMBER;
+    myStats->fittedStdev = MISC_FLOAT_NUMBER;
+    myStats->fittedNfit = MISC_FLOAT_NUMBER;
+    myStats->clippedMean = MISC_FLOAT_NUMBER;
+    myStats->clippedStdev = MISC_FLOAT_NUMBER;
+    myStats->clippedNvalues = MISC_FLOAT_NUMBER;
+    myStats->clipSigma = MISC_FLOAT_NUMBER;
+    myStats->clipIter = MISC_FLOAT_NUMBER;
+    myStats->min = MISC_FLOAT_NUMBER;
+    myStats->max = MISC_FLOAT_NUMBER;
+    myStats->binsize = MISC_FLOAT_NUMBER;
+    myStats->nSubsample = MISC_FLOAT_NUMBER;
+    myStats->options = 0x0;
+
+    psMemCheckCorruption(1);
+
+    printFooter(stdout,
+                "psStats functions",
+                "Allocate the psStats structure.",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "Deallocate the psStats structure.");
+    psFree(myStats);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    psMemCheckCorruption(1);
+
+    printFooter(stdout,
+                "psStats functions",
+                "Deallocate the psStats structure.",
+                testStatus);
+
+    return (!testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats06.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats06.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats06.c	(revision 22158)
@@ -0,0 +1,147 @@
+/*****************************************************************************
+    This routine must ensure that PS_STAT_SAMPLE_STDEV is correctly computed
+    by the procedure psArrayStats().
+ 
+    XXX: Must add tests for various data types, other than psF32.  Copy code
+    from tst_psStats00.c-tst_psStats02.c.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+#include "psTest.h"
+#include "float.h"
+#include <math.h>
+
+#define N 15
+
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    //
+    // We list pertinent psStats.c functions here for debugging ease.
+    //
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("p_psVectorSampleMean", 0);
+    psTraceSetLevel("p_psVectorMax", 0);
+    psTraceSetLevel("p_psVectorMin", 0);
+    psTraceSetLevel("p_psVectorCheckNonEmpty", 0);
+    psTraceSetLevel("p_psVectorNValues", 0);
+    psTraceSetLevel("p_psVectorSampleStdevOLD", 0);
+    psTraceSetLevel("p_psVectorSampleStdev", 0);
+    psTraceSetLevel("psStatsAlloc", 0);
+    psTraceSetLevel("p_psConvertToF32", 0);
+    psTraceSetLevel("psVectorStats", 0);
+
+    psStats *myStats    = NULL;
+    psS32 testStatus      = true;
+    psS32 globalTestStatus = true;
+    psS32 i               = 0;
+    psVector *myVector  = NULL;
+    psVector *maskVector= NULL;
+    float stdev         = 0.0;
+    // NOTE: These values were calculated by running the function on the data.
+    // A: They must be changed if we adjust the number of data points.
+    // B: We don't really know that they are correct.
+    float realStdevNoMask   = 4.472136;
+    float realStdevWithMask = 2.160247;
+    psS32 count           = 0;
+    psS32 currentId       = psMemGetId();
+    psS32 memLeaks        = 0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_SAMPLE_STDEV);
+    myVector = psVectorAlloc(N, PS_TYPE_F32);
+    myVector->n = N;
+    maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    maskVector->n = N;
+
+    stdev = 0.0;
+    // Set the appropriate values for the vector data.
+    for (i=0;i<N;i++) {
+        myVector->data.F32[i] = (float) i;
+    }
+
+    // Set the mask vector and calculate the expected maximum.
+    for (i=0;i<N;i++) {
+        if (i < (N/2)) {
+            maskVector->data.U8[i] = 0;
+            count++;
+        } else {
+            maskVector->data.U8[i] = 1;
+        }
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_STDEV: no vector mask");
+
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+    stdev = myStats->sampleStdev;
+
+    printf("Called psVectorStats() on a vector with no elements masked.\n");
+    printf("The expected stdev was %f; the calculated stdev was %f\n",
+           realStdevNoMask, stdev);
+    if (fabs(stdev - realStdevNoMask) <= 2.0 * FLT_EPSILON) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_SAMPLE_STDEV: no vector mask",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask.                       */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_STDEV: with vector mask");
+
+    myStats = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+    stdev = myStats->sampleStdev;
+    printf("Called psVectorStats() on a vector with last N/2 elements masked.\n");
+    printf("The expected stdev was %f; the calculated stdev was %f\n",
+           realStdevWithMask, stdev);
+    if (fabs(stdev - realStdevWithMask) <= 2.0 * FLT_EPSILON) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_SAMPLE_STDEV: with vector mask",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "psStats(): deallocating memory");
+
+    psFree(myStats);
+    psFree(myVector);
+    psFree(maskVector);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    printFooter(stdout,
+                "psVector functions",
+                "psStats(): deallocating memory",
+                testStatus);
+
+    return (!globalTestStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats07.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats07.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats07.c	(revision 22158)
@@ -0,0 +1,491 @@
+/*****************************************************************************
+   This routine must ensure that PS_STAT_ROBUST_QUARTILE is correctly computed
+   by the procedure psArrayStats().
+ 
+   XXX: Must add tests for various data types, other than psF32.  Copy code
+   from tst_psStats00.c-tst_psStats02.c.
+*****************************************************************************/
+#include <stdio.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+#include "psTest.h"
+#include "float.h"
+#include <math.h>
+
+#define NUM_DATA 1000
+#define MEAN 32.0
+#define STDEV 2.0
+#define PERCENT_OUTLIERS 1
+#define OUTLIER_MAGNITUDE (NUM_DATA * 10)
+#define ERROR_TOLERANCE .10
+#define ERRORS 1000.0
+#define SEED 1995
+#define VERBOSE 0
+
+#define TST_IN_NULL             0x00000001
+#define TST_IN_F32              0x00000002
+#define TST_IN_F64              0x00000004
+#define TST_IN_S8               0x00000008
+#define TST_IN_U16              0x00000010
+#define TST_IN_S32              0x00000020
+#define TST_ERRORS_NULL         0x00000040
+#define TST_ERRORS_F32          0x00000080
+#define TST_ERRORS_F64          0x00000100
+#define TST_ERRORS_S8           0x00000200
+#define TST_ERRORS_U16          0x00000400
+#define TST_ERRORS_S32          0x00000800
+#define TST_MASK_NULL           0x00001000
+#define TST_MASK_U8             0x00002000
+#define TST_MASK_S32            0x00004000
+
+psBool genericRobustStatsTest(
+    unsigned int flags,
+    psS32 numData,
+    psU32 maskValue,
+    psBool expectedRC)
+{
+    psS32 currentId = psMemGetId();
+    psBool testStatus = true;
+    psS32 memLeaks = 0;
+    psVector *in = NULL;
+    psVector *errors = NULL;
+    psVector *mask = NULL;
+    srand(SEED);
+    printPositiveTestHeader(stdout, "psMathUtils functions", "psVectorStats Robust Stats Routine");
+
+    if (expectedRC == true) {
+        printf("This test should not generate any errors.\n");
+    }
+    if (expectedRC == false) {
+        printf("This test should generate an error message, and return NULL.\n");
+    }
+    psVector *gaussVector = p_psGaussianDev(MEAN, STDEV, numData);
+
+
+    if (flags & TST_IN_NULL) {
+        printf("        using a NULL in vector\n");
+    }
+
+    if (flags & TST_IN_F32) {
+        printf("        using a psF32 in vector\n");
+        in = psVectorAlloc(numData, PS_TYPE_F32);
+        for (psS32 i=0;i<numData;i++) {
+            in->data.F32[i] = gaussVector->data.F32[i];
+            in->n++;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%.1f)\n", i, in->data.F32[i]);
+            }
+        }
+    }
+
+    if (flags & TST_IN_F64) {
+        printf("        using a psF64 in vector\n");
+        in = psVectorAlloc(numData, PS_TYPE_F64);
+        for (psS32 i=0;i<numData;i++) {
+            in->data.F64[i] = (psF64) gaussVector->data.F32[i];
+            in->n++;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%.1f)\n", i, in->data.F64[i]);
+            }
+        }
+    }
+
+    if (flags & TST_IN_S8) {
+        printf("        using a psS8 in vector\n");
+        in = psVectorAlloc(numData, PS_TYPE_S8);
+        for (psS32 i=0;i<numData;i++) {
+            in->data.S8[i] = (psS8) gaussVector->data.F32[i];
+            in->n++;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%d)\n", i, in->data.S8[i]);
+            }
+        }
+    }
+
+    if (flags & TST_IN_U16) {
+        printf("        using a psU16 in vector\n");
+        in = psVectorAlloc(numData, PS_TYPE_U16);
+        for (psS32 i=0;i<numData;i++) {
+            in->data.U16[i] = (psU16) gaussVector->data.F32[i];
+            in->n++;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%d)\n", i, in->data.U16[i]);
+            }
+        }
+    }
+
+    if (flags & TST_IN_S32) {
+        printf("        using a psS32 in vector\n");
+        in = psVectorAlloc(numData, PS_TYPE_S32);
+        for (psS32 i=0;i<numData;i++) {
+            in->data.S32[i] = (psS32) gaussVector->data.F32[i];
+            in->n++;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%d)\n", i, in->data.S32[i]);
+            }
+        }
+    }
+    psFree(gaussVector);
+
+    //    in->n = in->nalloc;
+    if (flags & TST_ERRORS_NULL) {
+        printf("        using a NULL errors vector\n");
+    }
+
+    if (flags & TST_ERRORS_F32) {
+        printf("        using a psF32 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_F32);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.F32[i] = ERRORS;
+            errors->n++;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original errors data %d: (%.1f)\n", i, errors->data.F32[i]);
+            }
+        }
+    }
+
+    if (flags & TST_ERRORS_F64) {
+        printf("        using a psF64 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_F64);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.F64[i] = ERRORS;
+            errors->n++;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original errors data %d: (%.1f)\n", i, errors->data.F64[i]);
+            }
+        }
+    }
+
+    if (flags & TST_ERRORS_S8) {
+        printf("        using a psS8 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_S8);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.S8[i] = (psS8) ERRORS;
+            errors->n++;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original errors data %d: (%d)\n", i, errors->data.S8[i]);
+            }
+        }
+    }
+
+    if (flags & TST_ERRORS_U16) {
+        printf("        using a psU16 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_U16);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.U16[i] = (psU16) ERRORS;
+            errors->n++;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original errors data %d: (%d)\n", i, errors->data.U16[i]);
+            }
+        }
+    }
+
+    if (flags & TST_ERRORS_S32) {
+        printf("        using a psS32 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_S32);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.S32[i] = (psS32) ERRORS;
+            errors->n++;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original errors data %d: (%d)\n", i, errors->data.S32[i]);
+            }
+        }
+    }
+
+
+    if (flags & TST_MASK_NULL) {
+        printf("        using a NULL mask vector\n");
+    }
+
+    if (flags & TST_MASK_U8) {
+        printf("        using a psU8 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_U8);
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.U8[i] = (psU8) 0;
+            mask->n++;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original mask data %d: (%d)\n", i, mask->data.U8[i]);
+            }
+        }
+    }
+
+    if (flags & TST_MASK_S32) {
+        printf("        using a psS32 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_S32);
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.S32[i] = (psS32) 0;
+            mask->n++;
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original mask data %d: (%d)\n", i, mask->data.S32[i]);
+            }
+        }
+    }
+
+
+    //
+    // We calculate the sample mean and stdev without and outliers in the data.
+    // We will use this later in determining if the clipped stats are correct.
+    //
+    psF32 sampleMean;
+    psF32 sampleStdev;
+    psF32 sampleMedian;
+    psF32 sampleLQ;
+    psF32 sampleUQ;
+    if (expectedRC == true) {
+        psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV | PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_QUARTILE);
+        psStats *rc = psVectorStats(myStats, in, NULL, NULL, maskValue);
+        if (rc == NULL) {
+            printf("TEST ERROR: the psVectorStats() function returned NULL.\n");
+            testStatus = false;
+        } else {
+            sampleMean = myStats->sampleMean;
+            sampleStdev = myStats->sampleStdev;
+            sampleMedian = myStats->sampleMedian;
+            sampleLQ = myStats->sampleLQ;
+            sampleUQ = myStats->sampleUQ;
+        }
+        psFree(myStats);
+    }
+
+    //
+    // We add a few outliers to the input data.
+    //
+    if (flags & TST_IN_F32) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.F32[i] = (psF32) OUTLIER_MAGNITUDE;
+            }
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%.1f)\n", i, in->data.F32[i]);
+            }
+        }
+    }
+    if (flags & TST_IN_F64) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.F64[i] = (psF64) OUTLIER_MAGNITUDE;
+            }
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%.1f)\n", i, in->data.F64[i]);
+            }
+        }
+    }
+    if (flags & TST_IN_S8) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.S8[i] = (psS8) OUTLIER_MAGNITUDE;
+            }
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%d)\n", i, in->data.S8[i]);
+            }
+        }
+    }
+    if (flags & TST_IN_U16) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.U16[i] = (psU16) OUTLIER_MAGNITUDE;
+            }
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%d)\n", i, in->data.U16[i]);
+            }
+        }
+    }
+    if (flags & TST_IN_S32) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.S32[i] = (psS32) OUTLIER_MAGNITUDE;
+            }
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original in data %d: (%d)\n", i, in->data.S32[i]);
+            }
+        }
+    }
+
+    //
+    // We call psVectorStats() and calculate the clipped stats.
+    //
+    psStats *myStats = psStatsAlloc(
+                           PS_STAT_ROBUST_MEDIAN |
+                           PS_STAT_ROBUST_STDEV |
+                           PS_STAT_ROBUST_QUARTILE |
+                           PS_STAT_FITTED_MEAN |
+                           PS_STAT_FITTED_STDEV);
+    psStats *rc = psVectorStats(myStats, in, errors, mask, maskValue);
+
+    if (rc == NULL) {
+        if (expectedRC == true) {
+            printf("TEST ERROR: the psVectorStats() function returned NULL.\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            printf("TEST ERROR: the psVectorStats() function returned non-NULL.\n");
+            testStatus = false;
+        }
+
+        //
+        // Fitted Mean
+        //
+        if (fabs(myStats->fittedMean - sampleMean) > (ERROR_TOLERANCE * sampleMean)) {
+            printf("TEST ERROR: the fitted mean was %.2f, should have been %.2f\n", myStats->fittedMean, sampleMean);
+            testStatus = false;
+        } else if (VERBOSE) {
+            printf("GOOD: the fitted mean was %.2f, should have been %.2f\n", myStats->fittedMean, sampleMean);
+        }
+
+        //
+        // Fitted Stdev
+        //
+        if (fabs(myStats->fittedStdev - sampleStdev) > (ERROR_TOLERANCE * sampleStdev)) {
+            printf("TEST ERROR: the fitted stdev was %.2f, should have been %.2f\n", myStats->fittedStdev, sampleStdev);
+            testStatus = false;
+        } else if (VERBOSE) {
+            printf("GOOD: the fitted stdev was %.2f, should have been %.2f\n", myStats->fittedStdev, sampleStdev);
+        }
+
+        //
+        // Robust Stdev
+        //
+        if (fabs(myStats->robustStdev - sampleStdev) > (ERROR_TOLERANCE * sampleStdev)) {
+            printf("TEST ERROR: the robust stdev was %.2f, should have been %.2f\n", myStats->robustStdev, sampleStdev);
+            testStatus = false;
+        } else if (VERBOSE) {
+            printf("GOOD: the robust stdev was %.2f, should have been %.2f\n", myStats->robustStdev, sampleStdev);
+        }
+
+        //
+        // Robust Median
+        //
+        if (fabs(myStats->robustMedian - sampleMedian) > (ERROR_TOLERANCE * sampleMedian)) {
+            printf("TEST ERROR: the robust median was %.2f, should have been %.2f\n", myStats->robustMedian, sampleMedian);
+            testStatus = false;
+        } else if (VERBOSE) {
+            printf("GOOD: the robust median was %.2f, should have been %.2f\n", myStats->robustMedian, sampleMedian);
+        }
+
+        //
+        // Robust LQ
+        //
+        if (fabs(myStats->robustLQ - sampleLQ) > (ERROR_TOLERANCE * sampleLQ)) {
+            printf("TEST ERROR: the robust LQ was %.2f, should have been %.2f\n", myStats->robustLQ, sampleLQ);
+            testStatus = false;
+        } else if (VERBOSE) {
+            printf("GOOD: the robust LQ was %.2f, should have been %.2f\n", myStats->robustLQ, sampleLQ);
+        }
+
+        //
+        // Robust UQ
+        //
+        if (fabs(myStats->robustUQ - sampleUQ) > (ERROR_TOLERANCE * sampleUQ)) {
+            printf("TEST ERROR: the robust UQ was %.2f, should have been %.2f\n", myStats->robustUQ, sampleUQ);
+            testStatus = false;
+        } else if (VERBOSE) {
+            printf("GOOD: the robust UQ was %.2f, should have been %.2f\n", myStats->robustUQ, sampleUQ);
+        }
+    }
+
+    psFree(myStats);
+    psFree(in);
+    psFree(errors);
+    psFree(mask);
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    return(testStatus);
+}
+
+
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psBool testStatus = true;
+    //
+    // We list pertinent psStats.c functions here for debugging ease.
+    //
+    #define TRACE_LEVEL 0
+
+    psTraceSetLevel(".", TRACE_LEVEL);
+    psTraceSetLevel("psGaussian", TRACE_LEVEL);
+    psTraceSetLevel("p_psVectorMax", TRACE_LEVEL);
+    psTraceSetLevel("p_psVectorMin", TRACE_LEVEL);
+    psTraceSetLevel("p_psVectorCheckNonEmpty", TRACE_LEVEL);
+    psTraceSetLevel("p_psNormalizeVectorRange", TRACE_LEVEL);
+    psTraceSetLevel("p_ps1DPolyMedian", TRACE_LEVEL);
+    psTraceSetLevel("fitQuadraticSearchForYThenReturnX", TRACE_LEVEL);
+    psTraceSetLevel("PsVectorDup", TRACE_LEVEL);
+    psTraceSetLevel("psMinimizeLMChi2Gauss1D", TRACE_LEVEL);
+    psTraceSetLevel("LinInterpolate", TRACE_LEVEL);
+    psTraceSetLevel("p_psVectorRobustStats", TRACE_LEVEL);
+    psTraceSetLevel("psStatsAlloc", TRACE_LEVEL);
+    psTraceSetLevel("psHistogramAlloc", TRACE_LEVEL);
+    psTraceSetLevel("psHistogramAllocGeneric", TRACE_LEVEL);
+    psTraceSetLevel("UpdateHistogramBins", TRACE_LEVEL);
+    psTraceSetLevel("psVectorHistogram", TRACE_LEVEL);
+    psTraceSetLevel("p_psConvertToF32", TRACE_LEVEL);
+    psTraceSetLevel("psVectorStats", TRACE_LEVEL);
+
+    testStatus &= genericRobustStatsTest(TST_IN_F32 | TST_ERRORS_NULL | TST_MASK_NULL, NUM_DATA, 1, true);
+    testStatus &= genericRobustStatsTest(TST_IN_F32 | TST_ERRORS_NULL | TST_MASK_U8, NUM_DATA, 1, true);
+
+    if (testStatus) {
+        printf("TEST PASSED.\n");
+    } else {
+        printf("TEST FAILED.\n");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats08.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats08.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats08.c	(revision 22158)
@@ -0,0 +1,190 @@
+/*****************************************************************************
+    This routine must ensure that PS_STAT_SAMPLE_QUARTILE is correctly computed
+    by the procedure psArrayStats().
+ 
+    XXX: Must add tests for various data types, other than psF32.  Copy code
+    from tst_psStats00.c-tst_psStats02.c.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+#include "psTest.h"
+#include "float.h"
+#include <math.h>
+
+#define N1 25  //
+#define N (8 * N1) // Don't change this (N must be a multiple of 8)
+
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    //
+    // We list pertinent psStats.c functions here for debugging ease.
+    //
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("p_psVectorMax", 0);
+    psTraceSetLevel("p_psVectorMin", 0);
+    psTraceSetLevel("p_psVectorCheckNonEmpty", 0);
+    psTraceSetLevel("p_psVectorNValues", 0);
+    psTraceSetLevel("p_psVectorSampleQuartiles", 0);
+    psTraceSetLevel("psStatsAlloc", 0);
+    psTraceSetLevel("p_psConvertToF32", 0);
+    psTraceSetLevel("psVectorStats", 0);
+
+
+    psStats *myStats    = NULL;
+    psS32 testStatus      = true;
+    psS32 globalTestStatus = true;
+    psS32 i               = 0;
+    psVector *myVector  = NULL;
+    psVector *maskVector= NULL;
+    // NOTE: These values were calculated by running the function on the data.
+    // A: They must be changed if we adjust the number of data points.
+    // B: We don't really know that they are correct.
+    float realLQNoMask   = N/4.0;
+    float realUQNoMask   = 3.0 * (N/4.0);
+    float realLQWithMask   = N/8.0;
+    float realUQWithMask   = 3.0 * (N/8.0);
+    psS32 count           = 0;
+    psS32 currentId       = psMemGetId();
+    psS32 memLeaks        = 0;
+
+    /*************************************************************************/
+    /*  Allocate and initialize data structures                      */
+    /*************************************************************************/
+    myStats = psStatsAlloc(PS_STAT_SAMPLE_QUARTILE);
+    myVector = psVectorAlloc(N, PS_TYPE_F32);
+    myVector->n = N;
+    maskVector = psVectorAlloc(N, PS_TYPE_U8);
+    maskVector->n = N;
+
+    // Set the appropriate values for the vector data.
+    for (i=0;i<N;i++) {
+        myVector->data.F32[i] = (float) i;
+    }
+
+    // Set the mask vector and calculate the expected maximum.
+    for (i=0;i<N;i++) {
+        if (i < (N/2)) {
+            maskVector->data.U8[i] = 0;
+            count++;
+        } else {
+            maskVector->data.U8[i] = 1;
+        }
+    }
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with no vector mask.                    */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_LQ: no vector mask");
+
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+
+    printf("Called psVectorStats() on a vector with no elements masked.\n");
+    printf("The expected sampleLQ was %f; the calculated sampleLQ was %f\n",
+           realLQNoMask, myStats->sampleLQ);
+    if (fabs(realLQNoMask - myStats->sampleLQ) <= 2.0 * FLT_EPSILON) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_SAMPLE_LQ: no vector mask",
+                testStatus);
+
+
+
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_UQ: no vector mask");
+
+    myStats = psVectorStats(myStats, myVector, NULL, NULL, 0);
+
+    printf("Called psVectorStats() on a vector with no elements masked.\n");
+    printf("The expected sampleUQ was %f; the calculated sampleUQ was %f\n",
+           realUQNoMask, myStats->sampleUQ);
+    if (fabs(realUQNoMask - myStats->sampleUQ) <= 2.0 * FLT_EPSILON) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_SAMPLE_UQ: no vector mask",
+                testStatus);
+
+    /*************************************************************************/
+    /*  Call psVectorStats() with vector mask.                       */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_LQ: with vector mask");
+
+    myStats = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+
+    printf("Called psVectorStats() on a vector with elements masked.\n");
+    printf("The expected sampleLQ was %f; the calculated sampleLQ was %f\n",
+           realLQWithMask, myStats->sampleLQ);
+    if (fabs(realLQWithMask - myStats->sampleLQ) <= 2.0 * FLT_EPSILON) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_SAMPLE_LQ: with vector mask",
+                testStatus);
+
+
+
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "PS_STAT_SAMPLE_UQ: with vector mask");
+
+    myStats = psVectorStats(myStats, myVector, NULL, maskVector, 1);
+
+    printf("Called psVectorStats() on a vector with elements masked.\n");
+    printf("The expected sampleUQ was %f; the calculated sampleUQ was %f\n",
+           realUQWithMask, myStats->sampleUQ);
+    if (fabs(realUQWithMask - myStats->sampleUQ) <= 2.0 * FLT_EPSILON) {
+        testStatus = true;
+    } else {
+        testStatus = false;
+        globalTestStatus = false;
+    }
+    printFooter(stdout,
+                "psVector functions",
+                "PS_STAT_SAMPLE_UQ: with vector mask",
+                testStatus);
+
+
+    /*************************************************************************/
+    /*  Deallocate data structures                                   */
+    /*************************************************************************/
+    printPositiveTestHeader(stdout,
+                            "psStats functions",
+                            "psStats(): deallocating memory");
+
+    psFree(myStats);
+    psFree(myVector);
+    psFree(maskVector);
+
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    printFooter(stdout,
+                "psVector functions",
+                "psStats(): deallocating memory",
+                testStatus);
+
+    return (!globalTestStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats09.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats09.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/math/tst_psStats09.c	(revision 22158)
@@ -0,0 +1,359 @@
+/*****************************************************************************
+    This routine must ensure that PS_STAT_CLIPPED_MEAN and
+    PS_STAT_CLIPPED_STDEV is calculate correctly by the procedure
+    psVectorStats().
+ 
+    XXX: The capability is here to test a wide variety of input parameters.
+    We must do this, later.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+#include "float.h"
+#include <math.h>
+
+#define NUM_DATA 1000
+#define VERBOSE 1
+#define PERCENT_OUTLIERS 2
+#define ERROR_TOLERANCE .10
+#define ERRORS 1.0
+#define SEED 1995
+
+#define TST_IN_NULL  0x00000001
+#define TST_IN_F32  0x00000002
+#define TST_IN_F64  0x00000004
+#define TST_IN_S8  0x00000008
+#define TST_IN_U16  0x00000010
+#define TST_IN_S32  0x00000020
+#define TST_ERRORS_NULL  0x00000040
+#define TST_ERRORS_F32  0x00000080
+#define TST_ERRORS_F64  0x00000100
+#define TST_ERRORS_S8  0x00000200
+#define TST_ERRORS_U16  0x00000400
+#define TST_ERRORS_S32  0x00000800
+#define TST_MASK_NULL  0x00001000
+#define TST_MASK_U8  0x00002000
+#define TST_MASK_S32  0x00004000
+
+
+psBool genericClippedStatsTest(
+    unsigned int flags,
+    psS32 numData,
+    psU32 maskValue,
+    psBool expectedRC)
+{
+    psS32 currentId = psMemGetId();
+    psBool testStatus = true;
+    psS32 memLeaks = 0;
+    psVector *in = NULL;
+    psVector *errors = NULL;
+    psVector *mask = NULL;
+    srand(SEED);
+    printPositiveTestHeader(stdout, "psMathUtils functions", "psVectorStats Clipped Stats Routine");
+
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 1); // Random number generator; using known seed
+    psVector *truth = psVectorAlloc(numData, PS_TYPE_F64);
+    truth->n = numData;
+    for (long i = 0; i < numData; i++) {
+        truth->data.F64[i] = psRandomGaussian(rng);
+    }
+    psFree(rng);
+
+    if (expectedRC == true) {
+        printf("This test should not generate any errors.\n");
+    }
+    if (expectedRC == false) {
+        printf("This test should generate an error message, and return NULL.\n");
+    }
+
+    if (flags & TST_IN_NULL) {
+        printf("        using a NULL in vector\n");
+    }
+
+    if (flags & TST_IN_F32) {
+        printf("        using a psF32 in vector\n");
+        in = psVectorCopy(in, truth, PS_TYPE_F32);
+    }
+
+    if (flags & TST_IN_F64) {
+        printf("        using a psF64 in vector\n");
+        in = psVectorCopy(in, truth, PS_TYPE_F64);
+    }
+
+    if (flags & TST_IN_S8) {
+        printf("        using a psS8 in vector\n");
+        in = psVectorCopy(in, truth, PS_TYPE_S8);
+    }
+
+    if (flags & TST_IN_U16) {
+        printf("        using a psU16 in vector\n");
+        in = psVectorCopy(in, truth, PS_TYPE_U16);
+    }
+
+    if (flags & TST_IN_S32) {
+        printf("        using a psS32 in vector\n");
+        in = psVectorCopy(in, truth, PS_TYPE_S32);
+    }
+
+    if (flags & TST_ERRORS_NULL) {
+        printf("        using a NULL errors vector\n");
+    }
+
+    if (flags & TST_ERRORS_F32) {
+        printf("        using a psF32 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_F32);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.F32[i] = ERRORS;
+            errors->n++;
+        }
+    }
+
+    if (flags & TST_ERRORS_F64) {
+        printf("        using a psF64 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_F64);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.F64[i] = ERRORS;
+            errors->n++;
+        }
+    }
+
+    if (flags & TST_ERRORS_S8) {
+        printf("        using a psS8 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_S8);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.S8[i] = (psS8) ERRORS;
+            errors->n++;
+        }
+    }
+
+    if (flags & TST_ERRORS_U16) {
+        printf("        using a psU16 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_U16);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.U16[i] = (psU16) ERRORS;
+            errors->n++;
+        }
+    }
+
+    if (flags & TST_ERRORS_S32) {
+        printf("        using a psS32 errors vector\n");
+        errors = psVectorAlloc(numData, PS_TYPE_S32);
+        for (psS32 i=0;i<numData;i++) {
+            errors->data.S32[i] = (psS32) ERRORS;
+            errors->n++;
+        }
+    }
+
+
+    if (flags & TST_MASK_NULL) {
+        printf("        using a NULL mask vector\n");
+    }
+
+    if (flags & TST_MASK_U8) {
+        printf("        using a psU8 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_U8);
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.U8[i] = (psU8) 0;
+            mask->n++;
+        }
+    }
+
+    if (flags & TST_MASK_S32) {
+        printf("        using a psS32 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_S32);
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.S32[i] = (psS32) 0;
+            mask->n++;
+        }
+    }
+
+
+    //
+    // We add a few outliers to the input data.
+    //
+    psVector *outliers = psVectorAlloc(numData, PS_TYPE_U8);
+    outliers->n = numData;
+    psVectorInit(outliers, 0);
+    long numOutliers = 0;
+    if (flags & TST_IN_F32) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.F32[i] = 100.0;
+                outliers->data.U8[i] = 1;
+                numOutliers++;
+            }
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Data %d: (%f)\n", i, in->data.F32[i]);
+            }
+        }
+    }
+    if (flags & TST_IN_F64) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.F64[i] = 100.0;
+                outliers->data.U8[i] = 1;
+                numOutliers++;
+            }
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Data %d: (%f)\n", i, in->data.F64[i]);
+            }
+        }
+    }
+    if (flags & TST_IN_S8) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.S8[i] = 100;
+                outliers->data.U8[i] = 1;
+                numOutliers++;
+            }
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Data %d: (%d)\n", i, in->data.S8[i]);
+            }
+        }
+    }
+    if (flags & TST_IN_U16) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.U16[i] = 100;
+                outliers->data.U8[i] = 1;
+                numOutliers++;
+            }
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Data %d: (%d)\n", i, in->data.U16[i]);
+            }
+        }
+    }
+    if (flags & TST_IN_S32) {
+        for (psS32 i=0;i<numData;i++) {
+            if (PERCENT_OUTLIERS > (random() % 100)) {
+                in->data.S32[i] = 100;
+                outliers->data.U8[i] = 1;
+                numOutliers++;
+            }
+        }
+
+        if (VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Data %d: (%d)\n", i, in->data.S32[i]);
+            }
+        }
+    }
+
+    printf("%ld outliers.\n", numOutliers);
+
+    //
+    // We calculate the sample mean and stdev without and outliers in the data.
+    // We will use this later in determining if the clipped stats are correct.
+    //
+    psF32 sampleMean;
+    psF32 sampleStdev;
+    if (expectedRC == true) {
+        psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
+        psStats *rc = psVectorStats(myStats, in, errors, outliers, 1);
+        if (rc == NULL) {
+            printf("TEST ERROR: the psVectorStats() function returned NULL.\n");
+            testStatus = false;
+        } else {
+            sampleMean = myStats->sampleMean;
+            sampleStdev = myStats->sampleStdev;
+        }
+        psFree(myStats);
+    }
+    psFree(outliers);
+
+    //
+    // We call psVectorStats() and calculate the clipped stats.
+    //
+    psStats *myStats = psStatsAlloc(PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV);
+    myStats->clipSigma = 5.0;
+    myStats->clipIter = 2;
+    psStats *rc = psVectorStats(myStats, in, errors, mask, maskValue);
+    if (rc == NULL) {
+        if (expectedRC == true) {
+            printf("TEST ERROR: the psVectorStats() function returned NULL.\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            printf("TEST ERROR: the psVectorStats() function returned non-NULL.\n");
+            testStatus = false;
+        }
+
+        printf("Used %ld data points after clipping %ld.\n", myStats->clippedNvalues,
+               in->n - myStats->clippedNvalues);
+
+        if (fabs(myStats->clippedMean - sampleMean) > (ERROR_TOLERANCE * sampleMean)) {
+            printf("TEST ERROR: the clipped mean was %f, should have been %f\n", myStats->clippedMean, sampleMean);
+            testStatus = false;
+        } else if (VERBOSE) {
+            printf("GOOD: the clipped mean was %f, should have been %f\n", myStats->clippedMean, sampleMean);
+        }
+
+        if (fabs(myStats->clippedStdev - sampleStdev) > (ERROR_TOLERANCE * sampleStdev)) {
+            printf("TEST ERROR: the clipped stdev was %f, should have been %f\n", myStats->clippedStdev, sampleStdev);
+            testStatus = false;
+        } else if (VERBOSE) {
+            printf("GOOD: the clipped stdev was %f, should have been %f\n", myStats->clippedStdev, sampleStdev);
+        }
+
+    }
+
+    psFree(myStats);
+    psFree(truth);
+    psFree(in);
+    psFree(errors);
+    psFree(mask);
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    return(testStatus);
+}
+
+#define TRACE_LEVEL 0
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    psBool testStatus = true;
+
+    //
+    // We list pertinent psStats.c functions here for debugging ease.
+    //
+    psTraceSetLevel(".", TRACE_LEVEL);
+    psTraceSetLevel("p_psVectorSampleMean", TRACE_LEVEL);
+    psTraceSetLevel("p_psVectorMax", TRACE_LEVEL);
+    psTraceSetLevel("p_psVectorMin", TRACE_LEVEL);
+    psTraceSetLevel("p_psVectorCheckNonEmpty", TRACE_LEVEL);
+    psTraceSetLevel("p_psVectorNValues", TRACE_LEVEL);
+    psTraceSetLevel("p_psVectorClippedStats", TRACE_LEVEL);
+    psTraceSetLevel("p_psNormalizeVectorRange", TRACE_LEVEL);
+    psTraceSetLevel("psStatsAlloc", TRACE_LEVEL);
+    psTraceSetLevel("p_psConvertToF32", TRACE_LEVEL);
+    psTraceSetLevel("psVectorStats", TRACE_LEVEL);
+
+    testStatus &= genericClippedStatsTest(TST_IN_NULL | TST_ERRORS_NULL | TST_MASK_NULL, NUM_DATA, 1, false);
+    testStatus &= genericClippedStatsTest(TST_IN_F32 | TST_ERRORS_NULL | TST_MASK_NULL, NUM_DATA, 1, true);
+    testStatus &= genericClippedStatsTest(TST_IN_F64 | TST_ERRORS_NULL | TST_MASK_NULL, NUM_DATA, 1, true);
+    testStatus &= genericClippedStatsTest(TST_IN_F32 | TST_ERRORS_F32 | TST_MASK_NULL, NUM_DATA, 1, true);
+    testStatus &= genericClippedStatsTest(TST_IN_F32 | TST_ERRORS_NULL | TST_MASK_U8, NUM_DATA, 1, true);
+
+    if (testStatus) {
+        printf("TEST PASSED\n");
+    } else {
+        printf("TEST FAILED\n");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/.cvsignore	(revision 22158)
@@ -0,0 +1,23 @@
+temp
+.deps
+.libs
+Makefile
+Makefile.in
+tst_psImage
+tst_psScalar
+tst_psVector
+tst_psVectorSort_01
+tst_psVectorSort_02
+tst_psVectorSort_03
+tst_psVectorSort_04
+tap_psVector
+*.bb
+*.bbg
+*.da
+gmon.out
+tap_psImageInterpolate
+tap_psImage
+tap_psScalar
+tap_psVectorSort
+tap_psVectorSortIndex
+tap_psVectorSelect
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/Makefile.am	(revision 22158)
@@ -0,0 +1,32 @@
+
+AM_CPPFLAGS = \
+	$(SRCINC) \
+	-I$(top_srcdir)/src/mathtypes \
+	-I$(top_srcdir)/test/tap/src \
+	-I$(top_srcdir)/test/pstap/src \
+	$(PSLIB_CFLAGS)
+
+AM_LDFLAGS = \
+	$(top_builddir)/src/libpslib.la  \
+	$(top_builddir)/test/tap/src/libtap.la \
+	$(top_builddir)/test/pstap/src/libpstap.la \
+	$(PSLIB_LIBS)
+
+TEST_PROGS = \
+	tap_psScalar \
+	tap_psImage \
+	tap_psVector \
+	tap_psVectorSort \
+	tap_psVectorSortIndex \
+	tap_psVectorSelect
+
+if BUILD_TESTS
+bin_PROGRAMS = $(TEST_PROGS)
+TESTS = $(TEST_PROGS)
+else
+check_PROGRAMS = $(TEST_PROGS)
+endif
+
+CLEANFILES = $(check_DATA) temp/* core core.* *~ *.bb *.bbg *.da gmon.out
+
+test: check
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psImage.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psImage.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psImage.c	(revision 22158)
@@ -0,0 +1,416 @@
+/** @file  tst_psImage.c
+ *
+ *  @brief Contains the tests for psImage.[ch]
+ *
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-05-05 00:09:04 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdlib.h>
+#include "pslib.h"
+#include "tap.h"
+#include "pstap.h"
+
+
+#define OK(exp) \
+exp ? setOkay(1) : setOkay(0)
+
+#define RET_OK          \
+if ( ! Okay ) {     \
+    psFree(image);  \
+    return;         \
+}
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(402);
+
+    // testImageAlloc()
+    {
+        psMemId id = psMemGetId();
+        psImage* image = NULL;
+        psU32 sizes = 6;
+        psU32 numCols[] = {0,1,1,100,100,150};
+        psU32 numRows[] = {0,1,100,1,150,100};
+        psU32 types = 12;
+        psElemType type[] = { PS_TYPE_S8, PS_TYPE_S16, PS_TYPE_S32, PS_TYPE_S64,
+                              PS_TYPE_U8, PS_TYPE_U16, PS_TYPE_U32, PS_TYPE_U64,
+                              PS_TYPE_F32, PS_TYPE_F64 };
+        for (psU32 t=0;t<types;t++) {
+            for (psU32 i=0;i<sizes;i++) {
+                // Following should be an error if numRows[i] == 0 || numCols[i]==0
+                image = psImageAlloc(numCols[i],numRows[i],type[t]);
+                if (image == NULL) {
+                    if (numRows[i] == 0 || numCols[i] == 0) {
+                        continue;
+                    }
+                    ok(0, "psImageAlloc returned NULL for type %x, size %dx%d.",
+                       type[t], numCols[i], numRows[i]);
+                    psFree(image);
+                }
+
+                ok(image->type.dimen==PS_DIMEN_IMAGE && image->type.type==type[t],
+                    "psImageAlloc allocated dimen/type (%d/%d), expecting "
+                    "PS_IMAGE_DIMEN/%d", image->type.dimen,
+                    image->type.type, type[t]);
+                ok(image->numCols == numCols[i] && image->numRows == numRows[i],
+                    "psImageAlloc allocated size %dx%d, expecting be %dx%d "
+                    "(type = %d)", image->numCols, image->numRows, numCols[i],
+                    numRows[i],type[t]);
+                ok(image->col0 == 0 && image->row0 == 0,
+                    "psImageAlloc returned row0/col0 of %d/%d.  Expected 0/0.",
+                    image->row0, image->row0);
+                ok(image->parent == NULL, "psImageAlloc returned NULL parent");
+                ok(image->children == NULL,
+                    "psImageAlloc returned NULL children array");
+
+
+                if (image->children != NULL) {
+                    psFree(image);
+                }
+
+                switch (type[t]) {
+                case PS_TYPE_U16: {
+                        psU32 rows = numRows[i];
+                        psU32 cols = numCols[i];
+    
+                        for (psS32 r=0;r<rows;r++) {
+                            for (psS32 c=0;c<cols;c++) {
+                                image->data.U16[r][c] = 2*c+r;
+                            }
+                        }
+                        bool errorFlag = false;
+                        for (psS32 r=0;r<rows;r++) {
+                            for (psS32 c=0;c<cols;c++) {
+                                if (image->data.U16[r][c] != 2*c+r) {
+                                    errorFlag = true;
+                                }
+                            }
+                        }
+                        ok(!errorFlag, "psImageAlloc() set data correctly (U16)");
+                    }
+                    break;
+                case PS_TYPE_F32: {
+                        psU32 rows = numRows[i];
+                        psU32 cols = numCols[i];
+    
+                        for (psS32 r=0;r<rows;r++) {
+                            for (psS32 c=0;c<cols;c++) {
+                                image->data.F32[r][c] = 2.0f*c+r;
+                            }
+                        }
+                        bool errorFlag = false;
+                        for (psS32 r=0;r<rows;r++) {
+                            for (psS32 c=0;c<cols;c++) {
+                                if (fabsf(image->data.F32[r][c] - (2.0f*c+r)) > FLT_EPSILON) {
+                                    errorFlag = true;
+                                }
+                            }
+                        }
+                        ok(!errorFlag, "psImageAlloc() set data correctly (F32)");
+                    }
+                    break;
+                case PS_TYPE_F64: {
+                        psU32 rows = numRows[i];
+                        psU32 cols = numCols[i];
+    
+                        for (psS32 r=0;r<rows;r++) {
+                            for (psS32 c=0;c<cols;c++) {
+                                image->data.F64[r][c] = 2.0f*c+r;
+                            }
+                        }
+                        bool errorFlag = false;
+                        for (psS32 r=0;r<rows;r++) {
+                            for (psS32 c=0;c<cols;c++) {
+                                if (fabs(image->data.F64[r][c] - (2.0f*c+r)) > DBL_EPSILON) {
+                                    errorFlag = true;
+                                }
+                            }
+                        }
+                        ok(!errorFlag, "psImageAlloc() set data correctly (F64)");
+                    }
+                    break;
+                default: {
+                        // ignore type and just use as byte bucket.
+                        psU32 rows = numRows[i];
+                        psU32 cols = numCols[i]*PSELEMTYPE_SIZEOF(type[t]);
+    
+                        for (psS32 r=0;r<rows;r++) {
+                            for (psS32 c=0;c<cols;c++) {
+                                image->data.U8[r][c] = (uint8_t)(r + c);
+                            }
+                        }
+                        bool errorFlag = false;
+                        for (psS32 r=0;r<rows;r++) {
+                            for (psS32 c=0;c<cols;c++) {
+                                if (image->data.U8[r][c] != (uint8_t)(r + c)) {
+                                    errorFlag = true;
+                                }
+                            }
+                        }
+                        ok(!errorFlag, "psImageAlloc() set data correctly (default)");
+                    }
+                }
+                psFree(image);
+            }
+        }
+
+        // #548: Verify no memory leaks or corruption are detected after a valid psImage structure with multiple
+        // children is freed.
+        image = psImageAlloc(100,100,PS_TYPE_F32);
+        psImageSubset(image,((psRegion) {50,0,70,20}));
+        psImageSubset(image,((psRegion) {70,20,90,40}));
+        psFree(image);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testRegion()
+    {
+        psMemId id = psMemGetId();
+        psRegion region = psRegionSet(1,2,3,4);
+        char *tmpStr = psRegionToString(region);
+        ok(!(region.x0 != 1 || region.x1 != 2 || region.y0 != 3 || region.y1 != 4),
+            "The region attributes are set to (%s)", tmpStr);
+        psFree(tmpStr);
+        region = psRegionFromString("[1:2,3:4]");
+        tmpStr = psRegionToString(region);
+        ok(!(region.x0 != 0 || region.x1 != 2 || region.y0 != 2 || region.y1 != 4),
+            "The region attributes are set to (%s)", tmpStr);
+        psFree(tmpStr);
+        region = psRegionFromString("[1:2,3:]");
+        ok(isnan(region.x0),
+            "psRegionFromString returned a NULL pointer given a malformed string.");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //psRegionForImage
+    {
+        psMemId id = psMemGetId();
+        psImage *in;
+        psRegion inReg;
+        psRegion out;
+        in = psImageAlloc(1, 1, PS_TYPE_S32);
+        inReg = psRegionSet(1, 2, 1, 2);
+        out = psRegionForImage(in,inReg);
+        psRegion inReg2;
+        psRegion out2;
+        inReg2 = psRegionSet(-1, 0, -2, -1);
+        out2 = psRegionForImage(in, inReg2);
+    
+        ok(!( out.x0 != 1 || out.x1 != 1 || out.y0 != 1 || out.y1 != 1 ),
+           "Region For Image returned correct values");
+    
+        ok(!( out2.x0 != 0 || out2.x1 != 1 || out2.y0 != 0 || out2.y1 != 0 ),
+           "Region For Image returned correct values");
+        psFree(in);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //psRegionForSquare//
+    {
+        psMemId id = psMemGetId();
+        float X = 1;
+        float Y = 1;
+        float RAD = 1;
+        psRegion out;
+        out = psRegionForSquare(X, Y, RAD);
+        ok(!(out.x0 != 0 || out.x1 != 3 || out.y0 != 0 || out.y1!= 3),
+            "Region For Square returned correct values");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Initialize an image with a given value.//
+    {
+        psMemId id = psMemGetId();
+        psImage *in1 = NULL;
+        psImage *in2 = NULL;
+        psImage *in3 = NULL;
+        psImage *in4 = NULL;
+        int nRow = 1;
+        int nCol = 1;
+        in1 = psImageAlloc(nRow, nCol, PS_TYPE_U8);
+        ok(psImageInit(in1, 5 ),
+             "ImageAlloc.  U8 Case - 1x1");
+        nRow = 5;
+        in2 = psImageAlloc(nRow, nCol, PS_TYPE_F32);
+        ok(psImageInit(in2, 3),
+             "ImageAlloc.  F32 Case - 5x1");
+    
+        nCol = 5;
+        in3 = psImageAlloc(nRow, nCol, PS_TYPE_F64);
+        ok(psImageInit(in3, 3.14),
+             "ImageAlloc.  F64 Case - 5x5");
+    
+        in4 = psImageAlloc(nRow, nCol, PS_TYPE_S32);
+        ok(psImageInit(in4, 3),
+             "ImageAlloc.  S32 Case - 5x5");
+        psFree(in1);
+        psFree(in2);
+        psFree(in3);
+        psFree(in4);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageSet()
+    {
+        psMemId id = psMemGetId();
+        psImage *image = NULL;
+        image = psImageAlloc(5, 4, PS_TYPE_S32);
+
+        //Set the position of the subimage relative to the parent.
+        P_PSIMAGE_SET_COL0(image, 10);
+        P_PSIMAGE_SET_ROW0(image, 10);
+        for (int i = 0; i < 4; i++) {
+            for (int j = 0; j < 5; j++) {
+                image->data.S32[i][j] = i+j;
+            }
+        }
+
+        //Attempt to set a position in a NULL psImage*
+        psImage *none = NULL;
+        ok(! psImageSet(none, 1, 1, 1),
+            "psImageSet returned non-null");
+
+        //Attempt to set a position in a psImage* with negative numCols, numRows
+        none = psImageAlloc(2, 2, PS_TYPE_S32);
+        *(int*)&none->numCols = -1;
+        ok(! psImageSet(none, 1, 1, 1),
+            "psImageSet return false when passed an image with negative numCols");
+
+        *(int*)&none->numCols = 2;
+        *(int*)&none->numRows = -1;
+        ok(!psImageSet(none, 1, 1, 1),
+             "psImageSet failed to return false when passed an image with negative numRows");
+
+        //Attempt to set a position in a psImage* with negative col0, row0
+        *(int*)&none->numRows = 2;
+        P_PSIMAGE_SET_ROW0(none, -1);
+        ok(!psImageSet(none, 1, 1, 1),
+             "psImageSet failed to return false when passed an image with negative col0");
+
+        P_PSIMAGE_SET_COL0(none, -1);
+        P_PSIMAGE_SET_ROW0(none, 0);
+        ok(!psImageSet(none, 1, 1, 1),
+             "psImageSet failed to return false when passed an image with negative col0");
+        psFree(none);
+
+        //Try to set a position inside of the subimage.
+        ok(psImageSet(image, 14, 12, 666),
+             "psImageSet failed to return true when passed valid parameters");
+
+        ok(image->data.S32[2][4] == 666,
+            "psImageSet set the data value. value=%d", image->data.S32[2][4]);
+
+        //Try to set a position inside of the subimage from the tail.
+        ok(psImageSet(image, -1, -1, 666),
+             "psImageSet return true when passed valid parameters");
+
+        ok(image->data.S32[3][4] == 666,
+            "psImageSet set (from the tail) the data values correctly");
+
+        //Try to set a position outside of the subimage but inside of the parent image.
+        ok(!psImageSet(image, 0, 0, 666),
+             "psImageSet return false when passed an invalid location");
+
+        ok(!psImageSet(image, 9, 10, 666),
+             "psImageSet return false when passed an invalid location");
+
+        //Try to set a position outside of the subimage.
+        ok(!psImageSet(image, 15, 14, 666),
+             "psImageSet return false when passed an invalid location");
+
+        //Try to set a position outside of the subimage, indexing from the tail.
+        ok(!psImageSet(image, -6, -1, 666),
+             "psImageSet return false when passed an invalid location");
+        psFree(image);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageGet()
+    {
+        psMemId id = psMemGetId();
+        psImage *image = NULL;
+        image = psImageAlloc(5, 3, PS_TYPE_S32);
+
+        //Set the position of the subimage relative to the parent.
+        P_PSIMAGE_SET_COL0(image, 10);
+        P_PSIMAGE_SET_ROW0(image, 10);
+        for (int i = 0; i < 3; i++) {
+            for (int j = 0; j < 5; j++) {
+                image->data.S32[i][j] = i+j;
+            }
+        }
+    
+        //Attempt to get a position in a NULL psImage*
+        psImage *none = NULL;
+        ok(isnan( psImageGet(none, 1, 1) ),
+             "psImageGet return false when passed a NULL image");
+    
+        //Attempt to get a position in a psImage* with negative numCols, numRows
+        none = psImageAlloc(2, 2, PS_TYPE_S32);
+        *(int*)&none->numCols = -1;
+        ok(isnan( psImageGet(none, 1, 1) ),
+             "psImageGet return false when passed an image with negative numCols");
+    
+        *(int*)&none->numCols = 2;
+        *(int*)&none->numRows = -1;
+        ok(isnan( psImageGet(none, 1, 1) ),
+             "psImageGet return false when passed an image with negative numRows");
+    
+        //Attempt to get a position in a psImage* with negative col0, row0
+        *(int*)&none->numRows = 2;
+        P_PSIMAGE_SET_ROW0(none, -1);
+        ok(isnan( psImageGet(none, 1, 1) ),
+             "psImageGet return false when passed an image with negative col0");
+    
+        P_PSIMAGE_SET_COL0(none, -1);
+        P_PSIMAGE_SET_ROW0(none, 0);
+        ok(isnan( psImageGet(none, 1, 1) ),
+             "psImageGet return false when passed an image with negative col0");
+    
+        psFree(none);
+    
+    
+        //Try to get a position inside of the subimage.
+        ok(psImageGet(image, 14, 12) == 6,
+             "psImageGet return the correct value");
+    
+        //Try to get a position inside of the subimage from the tail.
+        ok(psImageGet(image, -1, -1) == 6,
+             "psImageGet return the correct value");
+    
+        //Try to get a position outside of the subimage but inside of the parent image.
+        ok(isnan( psImageGet(image, 1, 1) ),
+             "psImageGet return NAN when passed an invalid location");
+    
+        ok(isnan( psImageGet(image, 9, 10) ),
+             "psImageGet return NAN when passed an invalid location");
+    
+        //Try to set a position outside of the subimage.
+        ok(isnan( psImageGet(image, 15, 14) ),
+             "psImageGet return NAN when passed an invalid location");
+    
+        //Try to set a position outside of the subimage, indexing from the tail.
+        ok(isnan( psImageGet(image, -6, -1) ),
+             "psImageGet failed to return NAN when passed an invalid location");
+        psFree(image);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psImageInterpolate.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psImageInterpolate.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psImageInterpolate.c	(revision 22158)
@@ -0,0 +1,264 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+int main (void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(47);
+
+    // very simple tests: no mask, bilinear mode, xramp image only
+    {
+        psMemId id = psMemGetId();
+        // generate simple image (x ramp)
+        psImage *image = psImageAlloc(32, 32, PS_TYPE_F32);
+        ok(image != NULL, "psImage successfully allocated");
+        skip_start(image == NULL, 5, "Skipping tests because psImageAlloc() failed");
+
+        image->data.F32[10][10] = 1;
+
+        // center of pixels is 0.5, 0.5
+        float value;
+
+        value = psImagePixelInterpolate (image, 10.5, 10.5, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
+        is_float (value, 1.0, "pixel center value - %f", value);
+
+        value = psImagePixelInterpolate (image, 10.9, 10.5, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
+        is_float_tol (value, 0.6, 4.0*FLT_EPSILON, "pixel value - %.20f", value);
+
+        value = psImagePixelInterpolate (image, 10.5, 10.9, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
+        is_float_tol (value, 0.6, 4.0*FLT_EPSILON, "pixel value - %.20f", value);
+
+        value = psImagePixelInterpolate (image, 10.1, 10.5, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
+        is_float_tol (value, 0.6, 4.0*FLT_EPSILON, "pixel value - %.20f", value);
+
+        skip_end();
+
+        psFree(image);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // very simple tests: no mask, bilinear mode, xramp image only
+    {
+        psMemId id = psMemGetId();
+        // generate simple image (x ramp)
+        psImage *image = psImageAlloc(32, 32, PS_TYPE_F32);
+        ok(image != NULL, "psImage successfully allocated");
+        skip_start(image == NULL, 5, "Skipping tests because psImageAlloc() failed");
+
+        for (int j = 0; j < image->numRows; j++)
+        {
+            for (int i = 0; i < image->numCols; i++) {
+                image->data.F32[j][i] = i + 0.5;
+            }
+        }
+
+        // center of pixels is 0.5, 0.5
+        float value;
+
+        value = psImagePixelInterpolate (image, 2.5, 2.5, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
+        is_float (value, 2.5, "pixel center value - %f", value);
+
+        value = psImagePixelInterpolate (image, 2.2, 2.5, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
+        is_float (value, 2.2, "coord: 2.2, 2.5, value: %f", value);
+
+        value = psImagePixelInterpolate (image, 2.8, 2.5, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
+        is_float (value, 2.8, "coord: 2.8, value: %f", value);
+
+        value = psImagePixelInterpolate (image, 2.8, 2.2, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
+        is_float (value, 2.8, "coord: 2.8, value: %f", value);
+
+        value = psImagePixelInterpolate (image, 2.8, 2.8, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
+        is_float (value, 2.8, "coord: 2.8, value: %f", value);
+
+        value = psImagePixelInterpolate (image, 0.8, 2.8, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
+        is_float (value, 0.8, "coord: 0.8, value: %f", value);
+
+        // no extrapolation
+        value = psImagePixelInterpolate (image, 0.3, 2.8, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
+        is_float (value, 0.5, "coord: 0.3, value: %f", value);
+
+        value = psImagePixelInterpolate (image, -0.2, 2.8, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
+        is_float (value, 0.5, "coord: -0.2, value: %f", value);
+
+        skip_end();
+
+        psFree(image);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // very simple tests: no mask, bilinear mode, yramp image only
+    {
+        psMemId id = psMemGetId();
+        // generate simple image (y ramp)
+        psImage *image = psImageAlloc(32, 32, PS_TYPE_F32);
+        ok(image != NULL, "psImage successfully allocated");
+        skip_start(image == NULL, 5, "Skipping tests because psImageAlloc() failed");
+
+        for (int j = 0; j < image->numRows; j++)
+        {
+            for (int i = 0; i < image->numCols; i++) {
+                image->data.F32[j][i] = j + 0.5;
+            }
+        }
+
+        // center of pixels is 0.5, 0.5
+        float value;
+
+        value = psImagePixelInterpolate (image, 2.5, 2.5, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
+        is_float (value, 2.5, "pixel center value - %f", value);
+
+        value = psImagePixelInterpolate (image, 2.2, 2.2, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
+        is_float (value, 2.2, "coord: 2.2, 2.5, value: %f", value);
+
+        value = psImagePixelInterpolate (image, 2.5, 2.8, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
+        is_float (value, 2.8, "coord: 2.8, value: %f", value);
+
+        value = psImagePixelInterpolate (image, 2.2, 2.8, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
+        is_float (value, 2.8, "coord: 2.8, value: %f", value);
+
+        value = psImagePixelInterpolate (image, 2.8, 2.8, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
+        is_float (value, 2.8, "coord: 2.8, value: %f", value);
+
+        skip_end();
+
+        psFree(image);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // very simple tests: no mask, bicube mode, xramp image only
+    {
+        psMemId id = psMemGetId();
+        // generate simple image (x ramp)
+        psImage *image = psImageAlloc(32, 32, PS_TYPE_F32);
+        ok(image != NULL, "psImage successfully allocated");
+        skip_start(image == NULL, 5, "Skipping tests because psImageAlloc() failed");
+
+        for (int j = 0; j < image->numRows; j++)
+        {
+            for (int i = 0; i < image->numCols; i++) {
+                image->data.F32[j][i] = i + 0.5;
+            }
+        }
+
+        // center of pixels is 0.5, 0.5
+        float value;
+
+        value = psImagePixelInterpolate (image, 2.5, 2.5, NULL, 0, 0.0, PS_INTERPOLATE_BICUBE);
+        is_float (value, 2.5, "coord; 2.5, 2.5, value - %f", value);
+
+        value = psImagePixelInterpolate (image, 2.2, 2.5, NULL, 0, 0.0, PS_INTERPOLATE_BICUBE);
+        is_float (value, 2.2, "coord: 2.2, 2.5, value: %f", value);
+
+        value = psImagePixelInterpolate (image, 2.8, 2.5, NULL, 0, 0.0, PS_INTERPOLATE_BICUBE);
+        is_float (value, 2.8, "coord: 2.8, 2.5, value: %f", value);
+
+        value = psImagePixelInterpolate (image, 2.8, 2.2, NULL, 0, 0.0, PS_INTERPOLATE_BICUBE);
+        is_float (value, 2.8, "coord: 2.8, 2.2, value: %f", value);
+
+        value = psImagePixelInterpolate (image, 2.8, 2.8, NULL, 0, 0.0, PS_INTERPOLATE_BICUBE);
+        is_float (value, 2.8, "coord: 2.8, 2.8, value: %f", value);
+
+        // no extrapolation: these return the 'uncover' value
+        value = psImagePixelInterpolate (image, 0.8, 2.8, NULL, 0, 0.0, PS_INTERPOLATE_BICUBE);
+        is_float (value, 0.0, "coord: 0.8, 2.8, value: %f", value);
+
+        value = psImagePixelInterpolate (image, 0.3, 2.8, NULL, 0, 0.0, PS_INTERPOLATE_BICUBE);
+        is_float (value, 0.0, "coord: 0.3, 2.8, value: %f", value);
+
+        value = psImagePixelInterpolate (image, -0.2, 2.8, NULL, 0, 0.0, PS_INTERPOLATE_BICUBE);
+        is_float (value, 0.0, "coord: -0.2, 2.8, value: %f", value);
+
+        skip_end();
+
+        psFree(image);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // very simple tests: no mask, bilinear mode, yramp image only
+    {
+        psMemId id = psMemGetId();
+        // generate simple image (y ramp)
+        psImage *image = psImageAlloc(32, 32, PS_TYPE_F32);
+        ok(image != NULL, "psImage successfully allocated");
+        skip_start(image == NULL, 5, "Skipping tests because psImageAlloc() failed");
+
+        for (int j = 0; j < image->numRows; j++)
+        {
+            for (int i = 0; i < image->numCols; i++) {
+                image->data.F32[j][i] = j + 0.5;
+            }
+        }
+
+        // center of pixels is 0.5, 0.5
+        float value;
+
+        value = psImagePixelInterpolate (image, 2.5, 2.5, NULL, 0, 0.0, PS_INTERPOLATE_BICUBE);
+        is_float (value, 2.5, "pixel center value - %f", value);
+
+        value = psImagePixelInterpolate (image, 2.2, 2.2, NULL, 0, 0.0, PS_INTERPOLATE_BICUBE);
+        is_float (value, 2.2, "coord: 2.2, 2.5, value: %f", value);
+
+        value = psImagePixelInterpolate (image, 2.5, 2.8, NULL, 0, 0.0, PS_INTERPOLATE_BICUBE);
+        is_float (value, 2.8, "coord: 2.8, value: %f", value);
+
+        value = psImagePixelInterpolate (image, 2.2, 2.8, NULL, 0, 0.0, PS_INTERPOLATE_BICUBE);
+        is_float (value, 2.8, "coord: 2.8, value: %f", value);
+
+        value = psImagePixelInterpolate (image, 2.8, 2.8, NULL, 0, 0.0, PS_INTERPOLATE_BICUBE);
+        is_float (value, 2.8, "coord: 2.8, value: %f", value);
+
+        skip_end();
+
+        psFree(image);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // very simple tests: no mask, bilinear mode, x,y 2nd order shape
+    {
+        psMemId id = psMemGetId();
+        // generate simple image (x ramp)
+        psImage *image = psImageAlloc(32, 32, PS_TYPE_F32);
+        ok(image != NULL, "psImage successfully allocated");
+        skip_start(image == NULL, 5, "Skipping tests because psImageAlloc() failed");
+
+        for (int j = 0; j < image->numRows; j++)
+        {
+            for (int i = 0; i < image->numCols; i++) {
+                image->data.F32[j][i] = 0.25*PS_SQR(i + 0.5) + j + 0.5;
+            }
+        }
+
+        // center of pixels is 0.5, 0.5
+        float value;
+
+        value = psImagePixelInterpolate (image, 2.5, 2.5, NULL, 0, 0.0, PS_INTERPOLATE_BICUBE);
+        is_float (value, 4.0625, "pixel center value - %f", value);
+
+        value = psImagePixelInterpolate (image, 2.2, 2.2, NULL, 0, 0.0, PS_INTERPOLATE_BICUBE);
+        is_float (value, 3.41, "coord: 2.2, 2.5, value: %f", value);
+
+        value = psImagePixelInterpolate (image, 2.5, 2.8, NULL, 0, 0.0, PS_INTERPOLATE_BICUBE);
+        is_float (value, 4.3625002, "coord: 2.5, 2.8, value: %f", value);
+
+        value = psImagePixelInterpolate (image, 2.2, 2.8, NULL, 0, 0.0, PS_INTERPOLATE_BICUBE);
+        is_float (value, 4.010000229, "coord: 2.2, 2.8, value: %f", value);
+
+        value = psImagePixelInterpolate (image, 2.8, 2.8, NULL, 0, 0.0, PS_INTERPOLATE_BICUBE);
+        is_float (value, 4.75999975, "coord: 2.8, 2.8, value: %f", value);
+
+        skip_end();
+
+        psFree(image);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psScalar.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psScalar.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psScalar.c	(revision 22158)
@@ -0,0 +1,110 @@
+/** @file  tst_psScalar.c
+ *
+ *  @brief Contains the tests for psScalar.[ch]
+ *
+ *  @author Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.5 $
+ *           $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-04-10 21:09:30 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+
+#define tstScalarAllocByType(datatype,value)            \
+{                                                       \
+    psScalar* scalar;                                   \
+    scalar = psScalarAlloc(value,PS_TYPE_##datatype);   \
+    ok(scalar != NULL, "psScalarAlloc successful");     \
+    skip_start(scalar==NULL,1,"Skipping 1 test because psScalarAlloc failed");\
+    ok(scalar->type.type==PS_TYPE_##datatype && scalar->data.datatype==value, \
+       "scalar datatype and value are legit" );        \
+    skip_end();                                         \
+    psFree(scalar);                                     \
+}
+
+
+#define tstScalarCopyByType(datatype,value)                 \
+{                                                           \
+    psScalar*  scalarOrig;                                  \
+    psScalar*  scalarCopy;                                  \
+    scalarOrig = psScalarAlloc(value,PS_TYPE_##datatype);   \
+    scalarCopy = psScalarCopy(scalarOrig);                  \
+    ok(scalarCopy != NULL, "psScalarCopy != NULL");         \
+    skip_start(scalarCopy==NULL,1,"Skipping 1 test since psScalarCopy failed");\
+    ok(scalarCopy->type.type == scalarOrig->type.type && scalarCopy->data.datatype == scalarOrig->data.datatype, "Scalar datatype and value legit"); \
+    skip_end();                                             \
+    psFree(scalarCopy);                                     \
+    psFree(scalarOrig);                                     \
+}
+
+
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(47);
+
+
+    // Verify return is null for invalid scalar type
+    {
+        psMemId id = psMemGetId();
+        psScalar* scalar = psScalarAlloc(true,PS_TYPE_BOOL);
+        ok(scalar == NULL, "psScalarAlloc returns null for invalid type");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Verify the proper allocation/deallocation of scalar objects of valid types
+    {
+        psMemId id = psMemGetId();
+        tstScalarAllocByType(S8,10);
+        tstScalarAllocByType(U8,12);
+        tstScalarAllocByType(S16,14);
+        tstScalarAllocByType(U16,16);
+        tstScalarAllocByType(S32,18);
+        tstScalarAllocByType(U32,20);
+        tstScalarAllocByType(S64,22);
+        tstScalarAllocByType(U64,24);
+        tstScalarAllocByType(F32,26);
+        tstScalarAllocByType(F64,28);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify the return is null for invalid scalar type in the original
+    {
+        psMemId id = psMemGetId();
+        psScalar* scalarOrig = psScalarAlloc(0,PS_TYPE_S8);
+        scalarOrig->type.type = PS_TYPE_BOOL;
+        psScalar* scalarCopy = psScalarCopy(scalarOrig);
+        ok(scalarCopy == NULL, "psScalarCopy returns NULL for invalid type");
+        scalarCopy = psScalarCopy(NULL);
+        ok(scalarCopy == NULL, "psScalarCopy returns NULL for NULL argument");
+        psFree(scalarOrig);
+        psFree(scalarCopy);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify the proper copying of scalar objects for all valid types
+    {
+        psMemId id = psMemGetId();
+        tstScalarCopyByType(S8,100);
+        tstScalarCopyByType(U8,110);
+        tstScalarCopyByType(S16,120);
+        tstScalarCopyByType(U16,130);
+        tstScalarCopyByType(S32,140);
+        tstScalarCopyByType(U32,150);
+        tstScalarCopyByType(S64,160);
+        tstScalarCopyByType(U64,170);
+        tstScalarCopyByType(F32,180);
+        tstScalarCopyByType(F64,190);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psVector.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psVector.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psVector.c	(revision 22158)
@@ -0,0 +1,787 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+int main (void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(294);
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *psVec = psVectorAlloc(5, PS_TYPE_S32);
+        ok(psVec != NULL, "psVector successfully allocated");
+        skip_start(psVec == NULL, 4, "Skipping 4 tests because psVectorAlloc() failed");
+        ok(psVec->nalloc == 5, "Vector size = %ld", psVec->nalloc);
+        ok(psVec->n == 5, "Vector population = %ld", psVec->n);
+        ok(psVec->type.type == PS_TYPE_S32, "Vector type = %d", psVec->type.type);
+        ok(psVec->type.dimen == PS_DIMEN_VECTOR, "Vector dimen = %d", psVec->type.dimen);
+        skip_end();
+        psFree(psVec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector* vecZero = psVectorAlloc(0, PS_TYPE_S32);
+        ok(vecZero != NULL, "zero-length vector allocated");
+        skip_start(vecZero == NULL, 2, "Skipping 2 tests because psVectorAlloc() failed");
+        ok(vecZero->nalloc == 0, "Vector size = %ld", vecZero->nalloc);
+        ok(vecZero->n == 0, "Vector population = %ld", vecZero->n);
+        skip_end();
+        psFree(vecZero);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector* vecBogus = psVectorAlloc(10, 0);
+        ok(vecBogus == NULL, "psVectorAlloc() doesn't not accept bogus type");
+        psErr *err = psErrorLast();
+        skip_start(err == NULL, 2, "Skipping 2 tests because psVectorAlloc() didn't fail as expect");
+        ok(strstr(err->name, "vectorAlloc"), "alloc failure - got error name %s", err->name);
+        ok(err->code == PS_ERR_BAD_PARAMETER_TYPE, "alloc failure - got error code %d", err->code);
+        skip_end();
+        psFree(vecBogus);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psVectorRealloc() tests
+    {
+        psMemId id = psMemGetId();
+        psVector *psVec = psVectorAlloc(5, PS_TYPE_S32);
+        ok(psVec->n == 5, "Vector population = %ld", psVec->n);
+
+        // generate first part of vector
+        for(psS32 i = 0; i < 5; i++) {
+            psVec->data.S32[i] = i*10;
+        }
+
+        // Test C - Reallocate S32 vector bigger
+        ok(psVec->n == 5, "Vector population = %ld, should be %ld", psVec->n, 5);
+        psVec = psVectorRealloc(psVec,10);
+        ok(psVec != NULL, "test vector reallocated to bigger size");
+        skip_start(psVec == NULL, 4, "Skipping 4 tests because psVectorRealloc() failed");
+        ok(psVec->nalloc == 10, "Vector size = %ld", psVec->nalloc);
+        ok(psVec->n == 5, "Vector population = %ld", psVec->n);
+        ok(psVec->type.type == PS_TYPE_S32, "Vector type = %d", psVec->type.type);
+        ok(psVec->type.dimen == PS_DIMEN_VECTOR, "Vector dimen = %d", psVec->type.dimen);
+        skip_end();
+
+        // generate test data values
+        for(psS32 i = 5; i < 10; i++) {
+            psVec->data.S32[i] = i*10;
+            psVec->n++;
+        }
+
+        // test data values
+        skip_start(psVec == NULL, 10, "Skipping 10 tests because psVectorRealloc() failed");
+        for(psS32 i = 0; i < 10; i++) {
+            ok (psVec->data.S32[i] == i*10, "Elem %d = %d, expected %d", i, psVec->data.S32[i], i*10);
+        }
+        skip_end();
+        psFree(psVec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test D - Reallocate S32 vector smaller
+    {
+        psMemId id = psMemGetId();
+        psVector *psVec = psVectorAlloc(5, PS_TYPE_S32);
+        // generate test data values
+        for(psS32 i = 0; i < 5; i++) {
+            psVec->data.S32[i] = i*10;
+            psVec->n++;
+        }
+        psVec = psVectorRealloc(psVec, 3);
+        ok(psVec != NULL, "test vector reallocated to smaller size");
+        skip_start(psVec == NULL, 5, "Skipping 6 tests because psVectorRealloc() failed");
+        ok(psVec->nalloc == 3, "Vector size = %ld", psVec->nalloc);
+        ok(psVec->n == 3, "Vector population = %ld", psVec->n);
+
+        // check that the test data values survived the realloc
+        for(psS32 i = 0; i < 3; i++) {
+            ok (psVec->data.S32[i] == i*10, "Elem %d = %d, expected %d", i, psVec->data.S32[i], i*10);
+        }
+        skip_end();
+        psFree(psVec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // reallocate to 0 length
+    {
+        psMemId id = psMemGetId();
+        psVector *psVec = psVectorAlloc(5, PS_TYPE_S32);
+        psVec = psVectorRealloc(psVec,0);
+
+        ok(psVec != NULL, "test vector reallocated to zero length");
+        skip_start(psVec == NULL, 2, "Skipping 2 tests because psVectorRealloc() failed");
+        ok(psVec->nalloc == 0, "Vector size = %ld", psVec->nalloc);
+        ok(psVec->n == 0, "Vector population = %ld", psVec->n);
+        skip_end();
+
+        // Test E - Free S32 vector
+        // XXX not really a test...
+        psFree(psVec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *vecBogus = psVectorRealloc(NULL, 6);
+        ok(vecBogus == NULL, "psVectorRealloc() doesn't not accept bogus type");
+        psErr *err = psErrorLast();
+        skip_start(err == NULL, 2, "Skipping 2 tests because psVectorRealloc() didn't fail as expect");
+        ok(strstr(err->name, "psVectorRealloc"), "alloc failure - got error name %s", err->name);
+        ok(err->code == PS_ERR_BAD_PARAMETER_NULL, "alloc failure - got error code %d", err->code);
+        skip_end();
+        psFree(vecBogus);
+        psFree(err);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psVectorExtend() tests
+    {
+        psMemId id = psMemGetId();
+        psVector *psVec = psVectorAlloc(5, PS_TYPE_S32);
+        psVec = psVectorExtend(psVec, 0, 2);
+        ok(psVec != NULL, "test vector extended");
+        skip_start(psVec == NULL, 2, "Skipping 2 tests because psVectorExtend() failed");
+        // Skipping this because it appears the psVectorExtend() changes since the test was written.
+        // ok(psVec->nalloc == 5, "Vector size = %ld", psVec->nalloc);
+        ok(psVec->n == 7, "Vector population = %ld", psVec->n);
+        skip_end();
+        psFree(psVec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *psVec = psVectorAlloc(5, PS_TYPE_S32);
+        psVec = psVectorExtend(psVec, 0, 2);
+        psVec = psVectorExtend(psVec, 0, 2);
+        ok(psVec != NULL, "test vector extended");
+        skip_start(psVec == NULL, 2, "Skipping 2 tests because psVectorExtend() failed");
+        // Skipping this because it appears the psVectorExtend() changes since the test was written.
+        //ok(psVec->nalloc == 15, "Vector size = %ld", psVec->nalloc);
+        ok(psVec->n == 9,"Vector population = %ld", psVec->n);
+        skip_end();
+        psFree(psVec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *psVec = psVectorAlloc(5, PS_TYPE_S32);
+        psVec = psVectorExtend(psVec, 0, 2);
+        psVec = psVectorExtend(psVec, 0, 2);
+        psVec = psVectorExtend(psVec, 0, -2);
+        ok(psVec != NULL, "test vector extended");
+        skip_start(psVec == NULL, 2, "Skipping 2 tests because psVectorExtend() failed");
+        // Skipping this because it appears the psVectorExtend() changes since the test was written.
+        // ok(psVec->nalloc == 15 ,"Vector size = %ld", psVec->nalloc);
+        ok(psVec->n == 7, "Vector population = %ld", psVec->n);
+        skip_end();
+        psFree(psVec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *psVec = psVectorAlloc(5, PS_TYPE_S32);
+        psVec = psVectorExtend(psVec, 0, 2);
+        psVec = psVectorExtend(psVec, 0, 2);
+        psVec = psVectorExtend(psVec, 0, -2);
+        psVec = psVectorExtend(psVec, 0, -20);
+        ok(psVec != NULL, "test vector extended");
+        skip_start(psVec == NULL, 2, "Skipping 2 tests because psVectorExtend() failed");
+        // Skipping this because it appears the psVectorExtend() changes since the test was written.
+        // ok(psVec->nalloc == 15, "Vector size = %ld", psVec->nalloc);
+        ok(psVec->n == 0, "Vector population = %ld", psVec->n);
+        skip_end();
+        psFree(psVec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psVectorInit() tests
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = psVectorAlloc(1, PS_TYPE_U8);
+        ok(psVectorInit(vec, 1 ), "U8 Case");
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = psVectorAlloc(1, PS_TYPE_U16);
+        ok(!psVectorInit(vec, PS_MAX_U64), "VectorInit failed.  U16 Case");
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = psVectorAlloc(1, PS_TYPE_U32);
+        ok(psVectorInit(vec, 10), "U32 Case");
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = psVectorAlloc(1, PS_TYPE_U64);
+        ok(psVectorInit(vec, PS_MIN_U64), "U64 Case");
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = psVectorAlloc(1, PS_TYPE_S8);
+        ok(!psVectorInit(vec, PS_MAX_S16), "VectorInit failed.  S8 Case");
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = psVectorAlloc(1, PS_TYPE_S16);
+        ok(psVectorInit(vec, -100), "S16 Case");
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = psVectorAlloc(1, PS_TYPE_S32);
+        ok(psVectorInit(vec, 1), "S32 Case");
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // XXX is this test ok?
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = psVectorAlloc(1, PS_TYPE_S64);
+        ok(psVectorInit(vec, PS_MAX_S64), "S64 Case");
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = psVectorAlloc(1, PS_TYPE_F32);
+        ok(psVectorInit(vec, 1.1), "F32 Case");
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = psVectorAlloc(1, PS_TYPE_F64);
+        ok(psVectorInit(vec, 1.4 ), "F64 Case");
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psVectorCreate() tests
+    {
+        psMemId id = psMemGetId();
+        psVector *test = psVectorCreate(NULL, 0.0, 10.0, 1.0, PS_TYPE_S8);
+        for (int i = 0; i < 10; i++) {
+            ok(test->data.S8[i] == i, "Vector data matches. i = %d, data=%d",
+               i, test->data.S8[i]);
+        }
+        psFree(test);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *test = psVectorCreate(NULL, 0.0, 10.0, 1.0, PS_TYPE_U8);
+        for (int i = 0; i < 10; i++) {
+            ok(test->data.U8[i] == i, "Vector data matches. i = %d, data=%d",
+               i, test->data.U8[i]);
+        }
+        psFree(test);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *test = psVectorCreate(NULL, 0.0, 10.0, 1.0, PS_TYPE_U32);
+        for (int i = 0; i < 10; i++) {
+            ok(test->data.U32[i] == i, "Vector data matches. i = %d, data=%d",
+               i, test->data.U32[i]);
+        }
+        psFree(test);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *test = psVectorCreate(NULL, 0.0, 10.0, 1.0, PS_TYPE_S32);
+        for (int i = 0; i < 10; i++) {
+            ok(test->data.S32[i] == i, "Vector data matches. i = %d, data=%d",
+               i, test->data.S32[i]);
+        }
+        psFree(test);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *input = psVectorAlloc(5, PS_TYPE_F32);
+        psVector *test = psVectorCreate(input, 0.0, 5.0, 0.5, PS_TYPE_F32);
+
+        for (int i = 0; i < 10; i++) {
+            ok(test->data.F32[i] == i * 0.5,
+               "Vector data matches. i = %d, data=%f", i, test->data.F32[i]);
+        }
+        psFree(input);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //  Test PS_TYPE_F64
+    //       PS_TYPE_S64
+    //       PS_TYPE_U64
+    {
+        psMemId id = psMemGetId();
+        psVector *test = psVectorCreate(NULL, 0.0, 10.0, 1.0, PS_TYPE_S64);
+        for (int i = 0; i < 10; i++)
+        {
+            ok(test->data.S64[i] == i,
+               "Vector data does not match. i = %d, data=%ld",
+               i, (long)test->data.S64[i]);
+        }
+        psFree(test);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *test = psVectorCreate(NULL, 0.0, 10.0, 1.0, PS_TYPE_U64);
+        for (int i = 0; i < 10; i++)
+        {
+            ok(test->data.U64[i] == i,
+               "Vector data does not match. i = %d, data=%ld",
+               i, (long)test->data.U64[i]);
+        }
+        psFree(test);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *input = psVectorAlloc(5, PS_TYPE_F64);
+        psVector *test = psVectorCreate(input, 0.0, 5.0, 0.5, PS_TYPE_F64);
+        for (int i = 0; i < 10; i++)
+        {
+            ok(test->data.F64[i] == i * 0.5,
+               "Vector data does not match. i = %d, data=%f",
+               i, test->data.F64[i]);
+        }
+        psFree(input);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //  Test PS_TYPE_U16
+    //       PS_TYPE_S16
+    {
+        psMemId id = psMemGetId();
+        psVector *test = psVectorCreate(NULL, 0.0, 10.0, 1.0, PS_TYPE_S16);
+        for (int i = 0; i < 10; i++)
+        {
+            ok(test->data.S16[i] == i, "Vector data matches. i = %d, data=%d",
+               i, test->data.S16[i]);
+        }
+        psFree(test);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *input = psVectorAlloc(5, PS_TYPE_U16);
+        psVector *test = psVectorCreate(input, 0.0, 20.0, 2.0, PS_TYPE_U16);
+        for (int i = 0; i < 10; i++)
+        {
+            ok(test->data.U16[i] == i * 2.0,
+               "Vector data matches. i = %d, data=%d", i, test->data.U16[i]);
+        }
+        psFree(input);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    #define TEST_VECTOR_TO_STRING(TYPE, SIZE, START, INC, EXPECTED)         \
+    {                                                                       \
+        psMemId id = psMemGetId(); \
+        const int asize = SIZE;  /* alloc size */                           \
+        const int osize = 100;   /* output size (max) */                    \
+        const char* const expected = EXPECTED;                              \
+        \
+        psVector *input = psVectorAlloc(asize, TYPE);                       \
+        psVector *test = psVectorCreate(input, START, START+asize*INC,      \
+                                        INC, TYPE);                                                     \
+        \
+        psString result = psVectorToString(test, osize);                    \
+        ok(strcmp(result, expected) == 0,                                   \
+           "psVectorToString expected:result = %s:%s", expected, result ); \
+        \
+        psFree(input);                                                      \
+        psFree(result);                                                      \
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); \
+    }
+
+    // psVectorToString() tests
+    TEST_VECTOR_TO_STRING(PS_TYPE_U8,  5, 1, 1, "[1,2,3,4,5]");
+    TEST_VECTOR_TO_STRING(PS_TYPE_U16, 5, 1, 1, "[1,2,3,4,5]");
+    TEST_VECTOR_TO_STRING(PS_TYPE_U32, 5, 1, 1, "[1,2,3,4,5]");
+    TEST_VECTOR_TO_STRING(PS_TYPE_U64, 5, 1, 1, "[1,2,3,4,5]");
+    TEST_VECTOR_TO_STRING(PS_TYPE_S8,  5, -100, 10,"[-100,-90,-80,-70,-60]");
+    TEST_VECTOR_TO_STRING(PS_TYPE_S16, 5, 0, -100, "[0,-100,-200,-300,-400]");
+    TEST_VECTOR_TO_STRING(PS_TYPE_S32, 5, 0, -100, "[0,-100,-200,-300,-400]");
+    TEST_VECTOR_TO_STRING(PS_TYPE_S64, 5, 0, -100, "[0,-100,-200,-300,-400]");
+    TEST_VECTOR_TO_STRING(PS_TYPE_F32,5,.123,1,"[0.123,1.123,2.123,3.123,4.123]");
+    TEST_VECTOR_TO_STRING(PS_TYPE_F64,5,.123,1,"[0.123,1.123,2.123,3.123,4.123]");
+
+
+    #define TEST_VECTOR_GET_ELEMENT_F64(ELEM_TYPE, SIZE, VALUE_TYPE,        \
+                                        INIT_VALUE )                                                        \
+    {                                                                       \
+        psMemId id = psMemGetId(); \
+        psVector *vec = psVectorAlloc(SIZE, ELEM_TYPE);                     \
+        vec->n = SIZE;                                                      \
+        VALUE_TYPE initValue = INIT_VALUE;                                  \
+        psVectorInit(vec, initValue);                                       \
+        psF64 result = p_psVectorGetElementF64(vec, 0);                     \
+        psF64 expected = (psF64)initValue;                                  \
+        ok(result == expected,                                              \
+           "p_psVectorGetElementF64 expected:result = %f:%f",expected,result);\
+        \
+        psFree(vec);                                                        \
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); \
+    }
+    // p_psVectorGetElementF64() tests
+    TEST_VECTOR_GET_ELEMENT_F64(PS_TYPE_U8, 1, psU8, 1);
+    TEST_VECTOR_GET_ELEMENT_F64(PS_TYPE_U16, 2, psU16, 2);
+    TEST_VECTOR_GET_ELEMENT_F64(PS_TYPE_U32, 3, psU32, 3);
+    TEST_VECTOR_GET_ELEMENT_F64(PS_TYPE_U64, 100, psU64, 999999);
+    TEST_VECTOR_GET_ELEMENT_F64(PS_TYPE_S8,  1, psS8, -1);
+    TEST_VECTOR_GET_ELEMENT_F64(PS_TYPE_S16, 2, psS16, -2);
+    TEST_VECTOR_GET_ELEMENT_F64(PS_TYPE_S32, 3, psS32, -3);
+    TEST_VECTOR_GET_ELEMENT_F64(PS_TYPE_S64, 100, psS64, -999999);
+    TEST_VECTOR_GET_ELEMENT_F64(PS_TYPE_F32,1, psF32, .123);
+    TEST_VECTOR_GET_ELEMENT_F64(PS_TYPE_F64,2, psF64, -123.123);
+
+
+    // XXX: Why are we testing private functions?
+    #define TEST_VECTOR_PRINT(ELEM_TYPE, SIZE, VALUE_TYPE, INIT_VALUE, FD,  \
+                              OUT_NAME, EXPECTED_RC )                                             \
+    {                                                                       \
+        psMemId id = psMemGetId(); \
+        psVector *vec = psVectorAlloc(SIZE, ELEM_TYPE);                     \
+        vec->n = SIZE;                                                      \
+        VALUE_TYPE initValue = INIT_VALUE;                                  \
+        psVectorInit(vec, initValue);                                       \
+        psBool result = p_psVectorPrint(FD, vec, OUT_NAME);                 \
+        ok(result == EXPECTED_RC,                                           \
+           "p_psVectorPrint expected:result = %d:%d",EXPECTED_RC,result);  \
+        \
+        psFree(vec);                                                        \
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); \
+    }
+    // p_psVectorPrint() tests
+    TEST_VECTOR_PRINT(PS_TYPE_U8, 1, psU8, 1, 1, "PS_TYPE_U8", TRUE);
+    TEST_VECTOR_PRINT(PS_TYPE_U16, 2, psU16, 2, 1, "PS_TYPE_U16", TRUE);
+    TEST_VECTOR_PRINT(PS_TYPE_U32, 3, psU32, 3, 1, "PS_TYPE_U32", TRUE);
+    TEST_VECTOR_PRINT(PS_TYPE_U64, 4, psU64, 999999, 1, "PS_TYPE_U64", TRUE);
+    TEST_VECTOR_PRINT(PS_TYPE_S8,  1, psS8, -1, 1, "PS_TYPE_S8", TRUE);
+    TEST_VECTOR_PRINT(PS_TYPE_S16, 2, psS16, -2, 1, "PS_TYPE_S16", TRUE);
+    TEST_VECTOR_PRINT(PS_TYPE_S32, 3, psS32, -3, 1, "PS_TYPE_S32", TRUE);
+    TEST_VECTOR_PRINT(PS_TYPE_S64, 4, psS64, -999999, 1, "PS_TYPE_S64", TRUE);
+    TEST_VECTOR_PRINT(PS_TYPE_F32,1, psF32, .123, 1, "PS_TYPE_F32", TRUE);
+    TEST_VECTOR_PRINT(PS_TYPE_F64,2, psF64, -123.123, 1, "PS_TYPE_F64", TRUE);
+
+    // psVectorSet() tests
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = psVectorAlloc(5, PS_TYPE_S32);
+        ok(psVectorSet(vec, 0, 10),
+           "VectorSet set S32 at position 0");
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = psVectorAlloc(5, PS_TYPE_S32);
+        ok(!psVectorSet(vec, 10, 10),
+           "VectorSet failes to set S32 at out of range position");
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = psVectorAlloc(5, PS_TYPE_S32);
+        ok(psVectorSet(vec, 1, 4) == true,
+           "VectorSet set S32 at position 1");
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psVectorGet() tests
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = psVectorAlloc(10, PS_TYPE_S32);
+        psVectorSet(vec, 0, 10);
+        ok((psS32)psVectorGet(vec, 0) == 10,
+           "VectorGet returned the correct S32 from position 0");
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = psVectorAlloc(5, PS_TYPE_S32);
+        psVectorSet(vec, -1, 4);
+        ok((psS32)psVectorGet(vec, -1) == 4,
+           "VectorGet returned the correct S32 from tail using -1");
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psVectorCountPixelMask() tests
+    // Ensure -1 return for NULL psVector input
+    {
+        psMemId id = psMemGetId();
+        ok(psVectorCountPixelMask(NULL, 1) == -1,
+           "psVectorCountPixelMask() returned -1 for NULL psVector input");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Ensure -1 return for incorrect TYPE psVector input
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = psVectorAlloc(5, PS_TYPE_S32);
+        vec->data.S32[0] = 0;
+        vec->data.S32[1] = 1;
+        vec->data.S32[2] = 0;
+        vec->data.S32[3] = 1;
+        vec->data.S32[4] = 0;
+        ok(psVectorCountPixelMask(vec, 1) == -1,
+           "psVectorCountPixelMask() returned -1 for incorrect TYPE psVector input");
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Use correct inputs
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = psVectorAlloc(5, PS_TYPE_U8);
+        vec->data.U8[0] = 0;
+        vec->data.U8[1] = 1;
+        vec->data.U8[2] = 0;
+        vec->data.U8[3] = 1;
+        vec->data.U8[4] = 0;
+        long numPix = psVectorCountPixelMask(vec, 1);
+        ok(numPix != -1, "psVectorCountPixelMask() did return -1 for correct psVector input");
+        ok(numPix == 2, "returned pixel count %d", numPix);
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Use correct inputs; psVector length of 0
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = psVectorAlloc(0, PS_TYPE_U8);
+        long numPix = psVectorCountPixelMask(vec, 1);
+        ok(numPix != -1, "psVectorCountPixelMask() did return -1 for correct psVector input (length 0)");
+        ok(numPix == 0, "returned pixel count %d", numPix);
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Use correct inputs; psVector length of 1
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = psVectorAlloc(1, PS_TYPE_U8);
+        vec->data.U8[0] = 0;
+        long numPix = psVectorCountPixelMask(vec, 1);
+        ok(numPix != -1, "psVectorCountPixelMask() did return -1 for correct psVector input (length 1)");
+        ok(numPix == 0, "returned pixel count %d", numPix);
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Use correct inputs; large psVector 
+    {
+        psMemId id = psMemGetId();
+        #define N 10
+        psVector *vec = psVectorAlloc(N, PS_TYPE_U8);
+        for (int i = 0 ; i < N ; i++) {
+            if (0 == i%2) {
+                vec->data.U8[i] = 0;
+            } else {
+                vec->data.U8[i] = 1;
+            }
+        }
+        long numPix = psVectorCountPixelMask(vec, 1);
+        ok(numPix != -1, "psVectorCountPixelMask() did return -1 for correct psVector input (length: %d)", N);
+        ok(numPix == N/2, "returned pixel count %d", numPix);
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psVectorLength() tests
+    {
+        psMemId id = psMemGetId();
+        psVector *vector = psVectorAlloc(5, PS_TYPE_F32);
+        ok(psVectorLength(vector) == 5,
+           "returned the correct length of vector (was %d, should be 5)", psVectorLength(vector));
+        psFree(vector);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *vector = psVectorAlloc(5, PS_TYPE_F32);
+        ok(psVectorLength(vector) == 5,
+           "returned the correct length of vector");
+        psFree(vector);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *vector = psVectorAlloc(6, PS_TYPE_F32);
+        ok(psVectorLength(vector) == 6,
+           "returned the correct length of vector");
+        psFree(vector);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        ok(psVectorLength(NULL) == -1, "returned -1 for a NULL input vector");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psArray *array = psArrayAlloc(5);
+        ok(psVectorLength((psVector*)array) == -1,
+           "returned -1 for an invalid input vector");
+        psFree(array);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psVectorCopy() tests
+    {
+        psMemId id = psMemGetId();
+        ok(psVectorCopy(NULL, NULL, PS_TYPE_F32) == NULL,
+           "returned a NULL vector for NULL input");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        psVector *in = psVectorAlloc(5, PS_TYPE_F32);
+        for (int i = 0; i < 5; i++) {
+            in->data.F32[i] = i;
+        }
+        //Try copy of different type
+        psVector *copy = psVectorCopy(NULL, in, PS_TYPE_F64);
+        ok(copy != NULL, "returned a non NULL vector for correct input");
+        skip_start(copy == NULL, 1, "Skipping 1 test because psVectorCopy() failed");
+        ok(copy->data.F64[2] == 2.0,
+           "copy->data.f64[2] = %lf, in->data.f32[2] = %f",
+           copy->data.F64[2], in->data.F32[2]);
+        skip_end();
+        psFree(in);
+        psFree(copy);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // XXX psVectorRecycle needs it's own tests
+    // copy = psVectorRecycle(copy, in->n + 2, PS_TYPE_F64);
+    {
+        psMemId id = psMemGetId();
+        // Try copy of same type and non-NULL outVector of different type and
+        // size.
+        psVector *in = psVectorAlloc(5, PS_TYPE_F32);
+        in->n = 5;
+        for (int i = 0; i < 5; i++)
+        {
+            in->data.F32[i] = i;
+        }
+        psVector *copy = psVectorAlloc(5, PS_TYPE_F64);
+        copy = psVectorCopy(copy, in, in->type.type);
+
+        ok(copy != NULL, "returned a NULL vector for correct input");
+        skip_start(copy == NULL, 2,
+                   "Skipping 1 test because psVectorCopy() failed");
+        ok(copy->type.type == PS_TYPE_F32, "copy has the correct data type");
+        ok(copy->data.F32[2] == 2.0, "copy has the correct data value");
+        skip_end();
+
+        psFree(in);
+        psFree(copy);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psVectorSelect.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psVectorSelect.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psVectorSelect.c	(revision 22158)
@@ -0,0 +1,97 @@
+#include <stdio.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define SIZE 1001                       // Size of vector
+#define NUM_NONZERO 50                  // Number of non-zero values
+
+// Test that results of psVectorSelect match what you'd get from psVectorSort
+// 2 tests
+static void testSelect(int size,        // Size of vector
+                       int numNonzero   // Number of non-zero values
+                       )
+{
+    psMemId id = psMemGetId();
+
+    psVector *vector = psVectorAlloc(size, PS_TYPE_F32);
+    psVectorInit(vector, 0.0);
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 12345);
+    for (long i = 0; i < numNonzero; i++) {
+        long index = psRandomUniform(rng) * size;
+        vector->data.F32[index] = psRandomUniform(rng);
+    }
+    psFree(rng);
+
+    psVector *sorted = psVectorSort(NULL, vector); // Sorted vector
+    psVector *select = NULL;        // Vector for selecting
+    bool match = true;              // Everything matches
+    for (long i = 0; i < size && match; i++) {
+        select = psVectorSelect(select, vector, i);
+        if (select->data.F32[i] != sorted->data.F32[i]) {
+            match = false;
+            diag("Rank %ld doesn't match: %f vs %f", i, select->data.F32[i], sorted->data.F32[i]);
+        }
+    }
+    psFree(sorted);
+    psFree(select);
+    psFree(vector);
+
+    ok(match, "All selections match, size=%d, number non-zero=%d.", size, numNonzero);
+    ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+}
+
+// Test that results of psVectorSelectInPlace match what you'd get from psVectorSort
+// 2 tests
+static void testSelectInPlace(int size,        // Size of vector
+                       int numNonzero   // Number of non-zero values
+                       )
+{
+    psMemId id = psMemGetId();
+
+    psVector *vector = psVectorAlloc(size, PS_TYPE_F32);
+    psVectorInit(vector, 0.0);
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 12345);
+    for (long i = 0; i < numNonzero; i++) {
+        long index = psRandomUniform(rng) * size;
+        vector->data.F32[index] = psRandomUniform(rng);
+    }
+    psFree(rng);
+
+    psVector *sorted = psVectorSort(NULL, vector); // Sorted vector
+    bool match = true;              // Everything matches
+    for (long i = 0; i < size && match; i++) {
+        psVectorSelectInPlace(vector, i);
+        if (vector->data.F32[i] != sorted->data.F32[i]) {
+            match = false;
+            diag("Rank %ld doesn't match: %f vs %f", i, vector->data.F32[i], sorted->data.F32[i]);
+        }
+    }
+    psFree(sorted);
+    psFree(vector);
+
+    ok(match, "All selections in-place match, size=%d, number non-zero=%d.", size, numNonzero);
+    ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+}
+
+
+int main(int argc, char *argv[])
+{
+    plan_tests(6 * 2 + 6 * 2);
+
+    testSelect(100, 0);
+    testSelect(100, 1);
+    testSelect(100, 10);
+    testSelect(100, 100);
+    testSelect(137, 13);
+    testSelect(137, 137);
+
+    testSelectInPlace(100, 0);
+    testSelectInPlace(100, 1);
+    testSelectInPlace(100, 10);
+    testSelectInPlace(100, 100);
+    testSelectInPlace(137, 13);
+    testSelectInPlace(137, 137);
+
+    return PS_EXIT_SUCCESS;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psVectorSort.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psVectorSort.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psVectorSort.c	(revision 22158)
@@ -0,0 +1,263 @@
+/** @file  tst_psVectorSort_01.c
+ *
+ *  @brief Test driver for psVectorSort functions
+ *
+ *  This file is amalgamated from: tst_psVectorSort_01.c, tst_psVectorSort_03.c
+ *  tst_psVectorSort_04.c
+ *
+ *  Attempt to sort NULL input vector
+ *  Attempt to sort vector with unallowed type (i.e. PS_TYPE_BOOL)
+ *  Sort input vector with zero items
+ *  Sort vector with one element
+ *  Verify the sort for all supported types.
+ *  Sort input vector into itself
+ *  Output vector is smaller than input vector
+ *  Output vector is different type from input vector
+ *
+ *  @author  Ross Harman, GLG, MHPCC
+ *
+ *  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2007-05-08 06:21:16 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#define VERBOSE 0
+
+#define tstVectorSortByType(datatype, boolOutNull, value) \
+{ \
+    psMemId id = psMemGetId(); \
+    psVector *out = NULL; \
+    psVector *in = psVectorAlloc(7, PS_TYPE_##datatype); \
+    if (boolOutNull) { \
+        out = NULL; \
+    } else { \
+        out = psVectorAlloc(7,PS_TYPE_##datatype); \
+    } \
+    in->data.datatype[0] = 7+value; \
+    in->data.datatype[1] = 9+value; \
+    in->data.datatype[2] = 3+value; \
+    in->data.datatype[3] = 1+value; \
+    in->data.datatype[4] = 5+value; \
+    in->data.datatype[5] = 5+value; \
+    in->data.datatype[6] = 0+value; \
+    psVector *tempVec = out; \
+    out = psVectorSort(out, in); \
+    if (!boolOutNull) { \
+        ok(tempVec == out, "Return value equal to orignal output argument passed to function"); \
+    } \
+    ok(out->type.type == PS_TYPE_##datatype, "psVectorSort() returned vector with correct type"); \
+    ok(out->n == 7, "psVectorSort() returned correct size vector"); \
+    skip_start(out == NULL, 7,"Skipping tests because psVectorSort() returned NULL."); \
+    ok(out->data.datatype[0] == in->data.datatype[6], "sort out[0] type %s",#datatype); \
+    ok(out->data.datatype[1] == in->data.datatype[3], "sort out[1] type %s",#datatype); \
+    ok(out->data.datatype[2] == in->data.datatype[2], "sort out[2] type %s",#datatype); \
+    ok(out->data.datatype[3] == in->data.datatype[4], "sort out[3] type %s",#datatype); \
+    ok(out->data.datatype[4] == in->data.datatype[5], "sort out[4] type %s",#datatype); \
+    ok(out->data.datatype[5] == in->data.datatype[0], "sort out[5] type %s",#datatype); \
+    ok(out->data.datatype[6] == in->data.datatype[1], "sort out[6] type %s",#datatype); \
+    skip_end(); \
+    psFree(in); \
+    psFree(out); \
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); \
+}
+
+
+psS32 main(psS32 argc,
+           char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(246);
+
+
+    // Attempt to sort NULL input vector
+    {
+        psMemId id = psMemGetId();
+        psVector *out = psVectorSort(NULL, NULL);
+        ok(out == NULL, "psVectorSort returned a NULL for NULL input vector" );
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to sort vector with unallowed type
+    {
+        psMemId id = psMemGetId();
+        psVector *in = psVectorAlloc(7, PS_TYPE_BOOL);
+        psVector *out = psVectorSort(NULL, in);
+        ok(out == NULL, "Did return NULL on error");
+        psFree(in);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Sort vector with zero elements
+    {
+        psMemId id = psMemGetId();
+        psVector *in = psVectorAlloc(0, PS_TYPE_F32);
+        psVector *out = psVectorSort(NULL, in);
+        ok(out != NULL, "psVectorSort returned a non-NULL vector" );
+        skip_start(out == NULL, 1, "psVectorSort returned a NULL vector" );
+        ok(out->n == 0, "psVectorSort correctly return a 0-length vector");
+        skip_end();
+        psFree(in);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Sort vector with one element
+    {
+        psMemId id = psMemGetId();
+        psVector *in = psVectorAlloc(1, PS_TYPE_F32);
+        psVector *out = psVectorSort(NULL, in);
+        ok(out != NULL, "psVectorSort returned a non-NULL vector" );
+        skip_start(out == NULL, 1, "psVectorSort returned a NULL vector" );
+        ok(out->n == 1, "psVectorSort correctly return a 1-length vector");
+        skip_end();
+        psFree(in);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify the sort for all supported types.
+    {
+        // At first we test with a NULL out vector.
+        tstVectorSortByType(S8, true, 0);
+        tstVectorSortByType(S16, true, 1);
+        tstVectorSortByType(S32, true, 2);
+        tstVectorSortByType(S64, true, 3);
+        tstVectorSortByType(U8, true, 4);
+        tstVectorSortByType(U16, true, 5);
+        tstVectorSortByType(U32, true, 6);
+        tstVectorSortByType(U64, true, 7);
+        tstVectorSortByType(F32, true, 8);
+        tstVectorSortByType(F64, true, 9);
+        // We test with a non-NULL out vector.
+        tstVectorSortByType(S8, false, 0);
+        tstVectorSortByType(S16, false, 1);
+        tstVectorSortByType(S32, false, 2);
+        tstVectorSortByType(S64, false, 3);
+        tstVectorSortByType(U8, false, 4);
+        tstVectorSortByType(U16, false, 5);
+        tstVectorSortByType(U32, false, 6);
+        tstVectorSortByType(U64, false, 7);
+        tstVectorSortByType(F32, false, 8);
+        tstVectorSortByType(F64, false, 9);
+    }
+
+
+    // Sort input vector into itself
+    {
+        psMemId id = psMemGetId();
+        psVector *in = psVectorAlloc(7, PS_TYPE_F32);
+        in->data.F32[0] = 0.7f;
+        in->data.F32[1] = 0.9f;
+        in->data.F32[2] = 0.3f;
+        in->data.F32[3] = 0.1f;
+        in->data.F32[4] = 0.5f;
+        in->data.F32[5] = 0.5f;
+        in->data.F32[6] = -2.0f;
+        in = psVectorSort(in, in);
+        skip_start(in == NULL,  7, "Skipping tests because psVectorSort() returned NULL.");
+        ok(in->data.F32[0] == -2.0f,"self sort in[0]");
+        ok(in->data.F32[1] == 0.1f,"self sort in[1]");
+        ok(in->data.F32[2] == 0.3f, "self sort in[2]");
+        ok(in->data.F32[3] == 0.5f, "self sort in[3]");
+        ok(in->data.F32[4] == 0.5f, "self sort in[4]");
+        ok(in->data.F32[5] == 0.7f, "self sort in[5]");
+        ok(in->data.F32[6] == 0.9f, "self sort in[6]");
+        skip_end();
+        psFree(in);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Output vector is smaller than input vector
+    {
+        psMemId id = psMemGetId();
+        psVector *in = psVectorAlloc(7, PS_TYPE_F32);
+        psVector *out = psVectorAlloc(3, PS_TYPE_F32);
+        in->data.F32[0] = 0.7f;
+        in->data.F32[1] = 0.9f;
+        in->data.F32[2] = 0.3f;
+        in->data.F32[3] = 0.1f;
+        in->data.F32[4] = 0.5f;
+        in->data.F32[5] = 0.5f;
+        in->data.F32[6] = -2.0f;
+        out = psVectorSort(out, in);
+        skip_start(out == NULL,  7, "Skipping tests because psVectorSort() returned NULL.");
+        ok(out->data.F32[0] == -2.0f,"Smaller out vector: in[0]");
+        ok(out->data.F32[1] == 0.1f,"Smaller out vector: in[1]");
+        ok(out->data.F32[2] == 0.3f, "Smaller out vector: in[2]");
+        ok(out->data.F32[3] == 0.5f, "Smaller out vector: in[3]");
+        ok(out->data.F32[4] == 0.5f, "Smaller out vector: in[4]");
+        ok(out->data.F32[5] == 0.7f, "Smaller out vector: in[5]");
+        ok(out->data.F32[6] == 0.9f, "Smaller out vector: in[6]");
+        skip_end();
+        psFree(in);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Output vector is different type from input vector
+    {
+        psMemId id = psMemGetId();
+        psVector *in = psVectorAlloc(7, PS_TYPE_F32);
+        psVector *out = psVectorAlloc(7, PS_TYPE_F64);
+        in->data.F32[0] = 0.7f;
+        in->data.F32[1] = 0.9f;
+        in->data.F32[2] = 0.3f;
+        in->data.F32[3] = 0.1f;
+        in->data.F32[4] = 0.5f;
+        in->data.F32[5] = 0.5f;
+        in->data.F32[6] = -2.0f;
+        out = psVectorSort(out, in);
+        skip_start(out == NULL,  7, "Skipping tests because psVectorSort() returned NULL.");
+        ok(out->data.F32[0] == -2.0f,"Smaller out vector: in[0]");
+        ok(out->data.F32[1] == 0.1f,"Smaller out vector: in[1]");
+        ok(out->data.F32[2] == 0.3f, "Smaller out vector: in[2]");
+        ok(out->data.F32[3] == 0.5f, "Smaller out vector: in[3]");
+        ok(out->data.F32[4] == 0.5f, "Smaller out vector: in[4]");
+        ok(out->data.F32[5] == 0.7f, "Smaller out vector: in[5]");
+        ok(out->data.F32[6] == 0.9f, "Smaller out vector: in[6]");
+        skip_end();
+        psFree(in);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Sort large input vector
+    {
+        #define N 1000000
+        psMemId id = psMemGetId();
+        psVector *in = psVectorAlloc(N, PS_TYPE_S32);
+        for (int i = 0 ; i < N ; i++) {
+            in->data.S32[N-i-1] = i;
+        }
+        psVector *out = psVectorSort(NULL, in);
+        skip_start(out == NULL,  7, "Skipping tests because psVectorSort() returned NULL.");
+        bool errorFlag = false;
+        for (int i = 0 ; i < N ; i++) {
+            if (out->data.S32[i] != i) {
+                if (VERBOSE) {
+                    diag("Test error: out[%d] is %d, should be %d\n", i, out->data.S32[i], i);
+                }
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psVectorSort() correctly sorted a large input vector");
+        skip_end();
+        psFree(in);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psVectorSortIndex.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psVectorSortIndex.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tap_psVectorSortIndex.c	(revision 22158)
@@ -0,0 +1,209 @@
+/** @file  tst_psVectorSort_02.c
+ *
+ *  @brief Test driver for psVectorSort functions
+ *
+ *  This test driver contains the following tests for psVectorSort test point 2:
+ *    Attempt to sort with null input vector
+ *    Attempt to sort input vector with unallowed type
+ *    Sort input vector with zero elements
+ *    Sort input vector with one element
+ *    Sort vectors by index for all types: first with a NULL output vector, then not.
+ *    Sort with output vector which needs to be resized
+ *    Sort with output vector with different type
+ *
+ *  @author  Ross Harman, GLG, MHPCC
+ *
+ *  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2007-11-29 02:51:08 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#define VERBOSE 0
+
+#define tstVectorSortIndexByType(datatype, boolOutNull, value) \
+{ \
+    psMemId id = psMemGetId(); \
+    psVector *out = NULL; \
+    psVector *in = psVectorAlloc(5, PS_TYPE_##datatype); \
+    in->data.datatype[0] = 7+value; \
+    in->data.datatype[1] = 9+value; \
+    in->data.datatype[2] = 5+value; \
+    in->data.datatype[3] = 1+value; \
+    in->data.datatype[4] = 5+value; \
+    if (boolOutNull) { \
+        out = NULL; \
+    } else { \
+        out = psVectorAlloc(5, PS_TYPE_##datatype); \
+    } \
+    psVector *tempVec = out; \
+    out = psVectorSortIndex(out, in); \
+    if (!boolOutNull) { \
+        ok(tempVec == out, "Return value equal to orignal output argument passed to function"); \
+    } \
+    skip_start(out == NULL, 6, "Skipping tests because psVectorSortIndex() returned NULL"); \
+    ok(out->type.type == PS_TYPE_S32, "Output vector is of type PS_TYPE_S32"); \
+    ok(out->n == 5, "psVectorSortIndex() returned correct size vector"); \
+    ok(out->data.U32[0] == 3, "index sort out[0] = %ld",out->data.U32[0]); \
+    ok(out->data.U32[1] == 2, "index sort out[1] = %ld",out->data.U32[1]); \
+    ok(out->data.U32[2] == 4, "index sort out[2] = %ld",out->data.U32[2]); \
+    ok(out->data.U32[3] == 0, "index sort out[3] = %ld",out->data.U32[3]); \
+    ok(out->data.U32[4] == 1, "index sort out[4] = %ld",out->data.U32[4]); \
+    skip_end(); \
+    psFree(in); \
+    psFree(out); \
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); \
+}\
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(196);
+
+
+    // Attempt to sort with null input vector
+    {
+        psMemId id = psMemGetId();
+        psVector *out = psVectorSortIndex(NULL, NULL);
+        ok(out == NULL, "psVectorSortIndex() return NULL with NULL input specified");
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to sort input vector with unallowed type
+    {
+        psMemId id = psMemGetId();
+        psVector *in = psVectorAlloc(5, PS_TYPE_BOOL);
+        psVector *out = psVectorSortIndex(NULL, in);
+        ok(out == NULL, "psVectorSortIndex() returned NULL with unallowed input vector type");
+        psFree(in);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Sort input vector with zero elements
+    {
+        psMemId id = psMemGetId();
+        psVector *in = psVectorAlloc(0, PS_TYPE_U8);
+        psVector *out = psVectorSortIndex(NULL, in);
+        ok(out != NULL, "psVectorSortIndex() returned non-NULL with size 0 input vector");
+        ok(out->n == 0, "psVectorSortIndex() returned correct size vector with size 0 input vector");
+        psFree(out);
+        psFree(in);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Sort input vector with one element
+    {
+        psMemId id = psMemGetId();
+        psVector *in = psVectorAlloc(1, PS_TYPE_U8);
+        psVector *out = psVectorSortIndex(NULL, in);
+        ok(out != NULL, "psVectorSortIndex() returned non-NULL with size 0 input vector");
+        ok(out->n == 1, "psVectorSortIndex() returned correct size vector with size 0 input vector");
+        psFree(out);
+        psFree(in);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Sort vectors by index for all types: first with a NULL output vector, then not.
+    {
+        tstVectorSortIndexByType(S8, true, 0)
+        tstVectorSortIndexByType(U8, true, 1)
+        tstVectorSortIndexByType(S16, true, 2)
+        tstVectorSortIndexByType(U16, true, 3)
+        tstVectorSortIndexByType(S32, true, 4)
+        tstVectorSortIndexByType(U32, true, 5)
+        tstVectorSortIndexByType(S64, true, 6)
+        tstVectorSortIndexByType(U64, true, 7)
+        tstVectorSortIndexByType(F32, true, 8)
+        tstVectorSortIndexByType(F64, true, 9)
+        tstVectorSortIndexByType(S8, false, 0)
+        tstVectorSortIndexByType(U8, false, 1)
+        tstVectorSortIndexByType(S16, false, 2)
+        tstVectorSortIndexByType(U16, false, 3)
+        tstVectorSortIndexByType(S32, false, 4)
+        tstVectorSortIndexByType(U32, false, 5)
+        tstVectorSortIndexByType(S64, false, 6)
+        tstVectorSortIndexByType(U64, false, 7)
+        tstVectorSortIndexByType(F32, false, 8)
+        tstVectorSortIndexByType(F64, false, 9)
+    }
+
+
+    // Sort with output vector which needs to be resized
+    {
+        psMemId id = psMemGetId();
+        psVector *in = psVectorAlloc(5, PS_TYPE_U8);
+        for(psS32 m=0; m<5; m++) {
+            in->data.U8[m]= 20-m;
+        }
+        psVector *out = psVectorAlloc(3,PS_TYPE_U32);
+        out = psVectorSortIndex(out,in);
+        ok(out->n == 5, "Did properly resize output vector...out->n=%d, in->n=%d", out->n, in->n);
+        ok(out->data.U32[0] == 4, "Did properly sort index out[0] = %d",out->data.U32[0]);
+        ok(out->data.U32[1] == 3, "Did properly sort index out[1] = %d",out->data.U32[1]);
+        ok(out->data.U32[2] == 2, "Did properly sort index out[2] = %d",out->data.U32[2]);
+        ok(out->data.U32[3] == 1, "Did properly sort index out[3] = %d",out->data.U32[3]);
+        ok(out->data.U32[4] == 0, "Did properly sort index out[4] = %d",out->data.U32[4]);
+        psFree(in);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Sort with output vector with different type
+    {
+        psMemId id = psMemGetId();
+        psVector *in = psVectorAlloc(5, PS_TYPE_U8);
+        for(psS32 m=0; m<5; m++) {
+            in->data.U8[m]= 20-m;
+        }
+        psVector *out = psVectorAlloc(3,PS_TYPE_F64);
+        out = psVectorSortIndex(out,in);
+        ok(out->n == 5, "Did properly resize output vector...out->n=%d, in->n=%d", out->n, in->n);
+        ok(out->data.U32[0] == 4, "Did properly sort index out[0] = %d",out->data.U32[0]);
+        ok(out->data.U32[1] == 3, "Did properly sort index out[1] = %d",out->data.U32[1]);
+        ok(out->data.U32[2] == 2, "Did properly sort index out[2] = %d",out->data.U32[2]);
+        ok(out->data.U32[3] == 1, "Did properly sort index out[3] = %d",out->data.U32[3]);
+        ok(out->data.U32[4] == 0, "Did properly sort index out[4] = %d",out->data.U32[4]);
+        psFree(in);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Sort large input vector
+    {
+        #define N 1000000
+        psMemId id = psMemGetId();
+        psVector *in = psVectorAlloc(N, PS_TYPE_S32);
+        for (int i = 0 ; i < N ; i++) {
+            in->data.S32[N-i-1] = i;
+        }
+        psVector *out = psVectorSortIndex(NULL, in);
+        skip_start(out == NULL,  7, "Skipping tests because psVectorSort() returned NULL.");
+        bool errorFlag = false;
+        for (int i = 0 ; i < N ; i++) {
+            if (out->data.U32[i] != N-i-1) {
+                if (VERBOSE) {
+                    diag("Test error: out[%d] is %d, should be %d\n", i, out->data.U32[i], i);
+                }
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psVectorSortIndex() correctly sorted a large input vector");
+        skip_end();
+        psFree(in);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tst_psImage.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tst_psImage.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tst_psImage.c	(revision 22158)
@@ -0,0 +1,583 @@
+/** @file  tst_psImage.c
+ *
+ *  @brief Contains the tests for psImage.[ch]
+ *
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-15 02:29:12 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "psTest.h"
+#include "pslib_strict.h"
+#include "psType.h"
+
+static psS32 testImageAlloc(void);
+static psS32 testRegion(void);
+static psS32 testRegion2(void);
+static psS32 testRegion3(void);
+static psS32 testImageInit(void);
+static psS32 testImageSet(void);
+static psS32 testImageGet(void);
+
+testDescription tests[] = {
+                              {testImageAlloc,546,"psImageAlloc",0,false},
+                              {testImageAlloc,548,"psImageFree",0,true},
+                              {testRegion,790,"psRegionSet",0,false},
+                              {testRegion,791,"psRegionFromString",0,true},
+                              {testRegion2,792,"psRegionForImage",0,false},
+                              {testRegion3,793,"psRegionForSquare",0,false},
+                              {testImageInit,794,"psImageInit",0,false},
+                              {testImageSet,795,"psImageSet",0,false},
+                              {testImageGet,666,"psImageGet",0,false},
+                              {NULL}
+                          };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    return ! runTestSuite(stderr,"psImage",tests,argc,argv);
+}
+
+psS32 testImageAlloc(void)
+{
+    psImage* image = NULL;
+    psU32 sizes = 6;
+    psU32 numCols[] = {
+                          0,1,1,100,100,150
+                      };
+    psU32 numRows[] = {
+                          0,1,100,1,150,100
+                      };
+    psU32 types = 12;
+    psElemType type[] = { PS_TYPE_S8, PS_TYPE_S16, PS_TYPE_S32, PS_TYPE_S64,
+                          PS_TYPE_U8, PS_TYPE_U16, PS_TYPE_U32, PS_TYPE_U64,
+                          PS_TYPE_F32, PS_TYPE_F64, PS_TYPE_C32, PS_TYPE_C64};
+
+    psLogMsg(__func__,PS_LOG_INFO,"#546 - psImageAlloc shall allocate memory for a psImage structure");
+
+    for (psU32 t=0;t<types;t++) {
+        psLogMsg(__func__,PS_LOG_INFO,"Testing psImage with type %xh",type[t]);
+
+        for (psU32 i=0;i<sizes;i++) {
+
+            if (numRows[i] == 0 || numCols[i] == 0) {
+                psLogMsg(__func__,PS_LOG_INFO,"Following should be an error.");
+            }
+
+            image = psImageAlloc(numCols[i],numRows[i],type[t]);
+
+            if (image == NULL) {
+                if (numRows[i] == 0 || numCols[i] == 0) {
+                    continue;
+                }
+                psError(PS_ERR_UNKNOWN, true,"psImageAlloc returned NULL for type %x, size %dx%d.",
+                        type[t], numCols[i], numRows[i]);
+                psFree(image);
+                return 1;
+            }
+
+            if (image->type.dimen != PS_DIMEN_IMAGE || image->type.type != type[t]) {
+                psError(PS_ERR_UNKNOWN, true,"psImageAlloc allocated wrong dimen/type (%d/%d), should be "
+                        "PS_IMAGE_DIMEN/%d", image->type.dimen, image->type.type, type[t]);
+                psFree(image);
+                return 2;
+            }
+
+            if (image->numCols != numCols[i] || image->numRows != numRows[i]) {
+                psError(PS_ERR_UNKNOWN, true,"psImageAlloc allocated wrong size %dx%d, should be %dx%d (type = %d)",
+                        image->numCols, image->numRows, numCols[i], numRows[i],type[t]);
+                psFree(image);
+                return 3;
+            }
+
+            if (image->col0 != 0 || image->row0 != 0) {
+                psError(PS_ERR_UNKNOWN, true,"psImageAlloc returned row0/col0 of %d/%d.  Should be 0/0.",
+                        image->row0, image->row0);
+                psFree(image);
+                return 4;
+            }
+
+            if (image->parent != NULL) {
+                psError(PS_ERR_UNKNOWN, true,"psImageAlloc returned non-NULL parent");
+                psFree(image);
+                return 5;
+            }
+
+            if (image->children != NULL) {
+                psError(PS_ERR_UNKNOWN, true,"psImageAlloc returned non-NULL children array");
+                psFree(image);
+                return 7;
+            }
+
+            switch (type[t]) {
+            case PS_TYPE_U16: {
+                    psU32 rows = numRows[i];
+                    psU32 cols = numCols[i];
+
+                    for (psS32 r=0;r<rows;r++) {
+                        for (psS32 c=0;c<cols;c++) {
+                            image->data.U16[r][c] = 2*c+r;
+                        }
+                    }
+                    for (psS32 r=0;r<rows;r++) {
+                        for (psS32 c=0;c<cols;c++) {
+                            if (image->data.U16[r][c] != 2*c+r) {
+                                psError(PS_ERR_UNKNOWN, true,"Could not set all pixels in uint16 image at (%d,%d)",c,r);
+                                psFree(image);
+                                return 8;
+                            }
+                        }
+                    }
+                }
+                break;
+            case PS_TYPE_F32: {
+                    psU32 rows = numRows[i];
+                    psU32 cols = numCols[i];
+
+                    for (psS32 r=0;r<rows;r++) {
+                        for (psS32 c=0;c<cols;c++) {
+                            image->data.F32[r][c] = 2.0f*c+r;
+                        }
+                    }
+                    for (psS32 r=0;r<rows;r++) {
+                        for (psS32 c=0;c<cols;c++) {
+                            if (fabsf(image->data.F32[r][c] - (2.0f*c+r)) > FLT_EPSILON) {
+                                psError(PS_ERR_UNKNOWN, true,"Could not set all pixels in float image at (%d,%d)",c,r);
+                                psFree(image);
+                                return 8;
+                            }
+                        }
+                    }
+                }
+                break;
+            case PS_TYPE_F64: {
+                    psU32 rows = numRows[i];
+                    psU32 cols = numCols[i];
+
+                    for (psS32 r=0;r<rows;r++) {
+                        for (psS32 c=0;c<cols;c++) {
+                            image->data.F64[r][c] = 2.0f*c+r;
+                        }
+                    }
+                    for (psS32 r=0;r<rows;r++) {
+                        for (psS32 c=0;c<cols;c++) {
+                            if (fabs(image->data.F64[r][c] - (2.0f*c+r)) > DBL_EPSILON) {
+                                psError(PS_ERR_UNKNOWN, true,"Could not set all pixels in double image at (%d,%d)",c,r);
+                                psFree(image);
+                                return 8;
+                            }
+                        }
+                    }
+                }
+                break;
+            case PS_TYPE_C32: {
+                    psU32 rows = numRows[i];
+                    psU32 cols = numCols[i];
+
+                    for (psS32 r=0;r<rows;r++) {
+                        for (psS32 c=0;c<cols;c++) {
+                            image->data.C32[r][c] = r + I * c;
+                        }
+                    }
+                    for (psS32 r=0;r<rows;r++) {
+                        for (psS32 c=0;c<cols;c++) {
+                            if (fabsf(crealf(image->data.C32[r][c]) - r) > FLT_EPSILON ||
+                                    fabsf(cimagf(image->data.C32[r][c]) - c) > FLT_EPSILON ) {
+                                psError(PS_ERR_UNKNOWN, true,"Could not set all pixels in complex image at (%d,%d)",c,r);
+                                psFree(image);
+                                return 8;
+                            }
+                        }
+                    }
+                }
+                break;
+            default: {
+                    // ignore type and just use as byte bucket.
+                    psU32 rows = numRows[i];
+                    psU32 cols = numCols[i]*PSELEMTYPE_SIZEOF(type[t]);
+
+                    for (psS32 r=0;r<rows;r++) {
+                        for (psS32 c=0;c<cols;c++) {
+                            image->data.U8[r][c] = (uint8_t)(r + c);
+                        }
+                    }
+                    for (psS32 r=0;r<rows;r++) {
+                        for (psS32 c=0;c<cols;c++) {
+                            if (image->data.U8[r][c] != (uint8_t)(r + c)) {
+                                psError(PS_ERR_UNKNOWN, true,"Could not set all pixels in image (type=%d) at (%d,%d)",
+                                        type[t],c,r);
+                                psFree(image);
+                                return 8;
+                            }
+                        }
+                    }
+                }
+            }
+            psFree(image);
+        }
+    }
+
+    // #548: Verify no memory leaks or corruption are detected after a valid psImage structure with multiple
+    // children is freed.
+    image = psImageAlloc(100,100,PS_TYPE_F32);
+    psImageSubset(image,(psRegion) {
+                      50,0,70,20
+                  }
+                 );
+    psImageSubset(image,(psRegion) {
+                      70,20,90,40
+                  }
+                 );
+
+    psFree(image);
+
+    return 0;
+}
+
+static psS32 testRegion(void)
+{
+    int testNum = 0;
+
+
+    // Testpoint #790
+
+    psRegion region = psRegionSet(1,2,3,4);
+
+    testNum++;
+    if (region.x0 != 1 || region.x1 != 2 || region.y0 != 3 || region.y1 != 4) {
+        psError(PS_ERR_UNKNOWN, false,
+                "The region attributes are not set properly (%s)",
+                psRegionToString(region));
+        return testNum;
+    }
+
+    // Testpoint #791
+
+    region = psRegionFromString("[1:2,3:4]");
+
+    testNum++;
+    if (region.x0 != 0 || region.x1 != 2 || region.y0 != 2 || region.y1 != 4) {
+        psError(PS_ERR_UNKNOWN, false,
+                "The region attributes are not set properly (%s)",
+                psRegionToString(region));
+        return testNum;
+    }
+
+    region = psRegionFromString("[1:2,3:]");
+
+    testNum++;
+    if (! isnan(region.x0)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "psRegionFromString returned a non-NULL pointer given a malformed string.");
+        return testNum;
+    }
+
+    return 0;
+}
+
+//psRegionForImage//
+static psS32 testRegion2(void)
+{
+    psImage *in;
+    psRegion inReg;
+    psRegion out;
+    in = psImageAlloc(1, 1, PS_TYPE_S32);
+    inReg = psRegionSet(1, 2, 1, 2);
+    out = psRegionForImage(in,inReg);
+    psRegion inReg2;
+    psRegion out2;
+    inReg2 = psRegionSet(-1, 0, -2, -1);
+    out2 = psRegionForImage(in, inReg2);
+
+    if( out.x0 != 1 || out.x1 != 1 || out.y0 != 1 || out.y1 != 1 ) {
+        psError(PS_ERR_UNKNOWN, true, "Error:  Region For Image returned incorrect values.\n");
+    }
+    if( out2.x0 != 0 || out2.x1 != 1 || out2.y0 != 0 || out2.y1 != 0 ) {
+        psError(PS_ERR_UNKNOWN, true, "Error:  Region For Image returned incorrect values.\n");
+    }
+
+    psFree(in);
+    return 0;
+}
+
+//psRegionForSquare//
+static psS32 testRegion3(void)
+{
+    float X = 1;
+    float Y = 1;
+    float RAD = 1;
+    psRegion out;
+    out = psRegionForSquare(X, Y, RAD);
+    if (out.x0 != 0 || out.x1 != 3 || out.y0 != 0 || out.y1!= 3)
+        psError(PS_ERR_UNKNOWN, true, "Error:  Region For Square returned incorrect values.\n");
+    return 0;
+}
+
+//Initialize an image with a given value.//
+static psS32 testImageInit(void)
+{
+    psImage *in1 = NULL;
+    psImage *in2 = NULL;
+    psImage *in3 = NULL;
+    psImage *in4 = NULL;
+    int nRow = 1;
+    int nCol = 1;
+    in1 = psImageAlloc(nRow, nCol, PS_TYPE_U8);
+    if ( !psImageInit(in1, -1 ) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "ImageInit failed.  U8 Case - 1x1\n");
+    }
+    nRow = 5;
+    in2 = psImageAlloc(nRow, nCol, PS_TYPE_F32);
+    if ( !psImageInit(in2, 3) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "ImageInit failed.  F32 Case - 5x1\n");
+    }
+    nCol = 5;
+    in3 = psImageAlloc(nRow, nCol, PS_TYPE_F64);
+    if ( !psImageInit(in3, 3.141) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "ImageInit failed.  F64 Case - 5x5\n");
+    }
+    in4 = psImageAlloc(nRow, nCol, PS_TYPE_S32);
+    if ( !psImageInit(in4, 3) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "ImageInit failed.  S32 Case - 5x5\n");
+    }
+    psFree(in1);
+    psFree(in2);
+    psFree(in3);
+    psFree(in4);
+    return 0;
+}
+
+static psS32 testImageSet(void)
+{
+    psImage *image = NULL;
+    image = psImageAlloc(5, 4, PS_TYPE_S32);
+
+    //Set the position of the subimage relative to the parent.
+    image->col0 = 10;
+    image->row0 = 10;
+    for (int i = 0; i < 4; i++) {
+        for (int j = 0; j < 5; j++) {
+            image->data.S32[i][j] = i+j;
+        }
+    }
+
+    //Attempt to set a position in a NULL psImage*
+    psImage *none = NULL;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psImageSet(none, 1, 1, 1) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImageSet failed to return false when passed a NULL image.\n");
+        return 1;
+    }
+
+    //Attempt to set a position in a psImage* with negative numCols, numRows
+    none = psImageAlloc(2, 2, PS_TYPE_S32);
+    *(int*)&none->numCols = -1;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psImageSet(none, 1, 1, 1) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImageSet failed to return false when passed an image with negative numCols.\n");
+        return 2;
+    }
+    *(int*)&none->numCols = 2;
+    *(int*)&none->numRows = -1;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psImageSet(none, 1, 1, 1) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImageSet failed to return false when passed an image with negative numRows.\n");
+        return 3;
+    }
+
+    //Attempt to set a position in a psImage* with negative col0, row0
+    *(int*)&none->numRows = 2;
+    none->row0 = -1;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psImageSet(none, 1, 1, 1) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImageSet failed to return false when passed an image with negative col0.\n");
+        return 4;
+    }
+    none->row0 = 0;
+    none->col0 = -1;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psImageSet(none, 1, 1, 1) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImageSet failed to return false when passed an image with negative col0.\n");
+        return 5;
+    }
+    psFree(none);
+
+    //Try to set a position inside of the subimage.
+    if ( !psImageSet(image, 14, 12, 666) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImageSet failed to return true when passed valid parameters.\n");
+        return 6;
+    }
+    if (image->data.S32[2][4] != 666) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImageSet failed to set the data values correctly. value=%d\n", image->data.S32[2][4]);
+        return 7;
+    }
+    //Try to set a position inside of the subimage from the tail.
+    if ( !psImageSet(image, -1, -1, 666) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImageSet failed to return true when passed valid parameters.\n");
+        return 8;
+    } else if  (image->data.S32[3][4] != 666) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImageSet failed to set (from the tail) the data values correctly.\n");
+        printf("\n value at 14,14 is %d\n", image->data.S32[3][4]);
+        return 9;
+    }
+
+    //Try to set a position outside of the subimage but inside of the parent image.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psImageSet(image, 0, 0, 666) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageSet failed to return false when passed an invalid location.\n");
+        return 10;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psImageSet(image, 9, 10, 666) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageSet failed to return false when passed an invalid location.\n");
+        return 11;
+    }
+
+    //Try to set a position outside of the subimage.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psImageSet(image, 15, 14, 666) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageSet failed to return false when passed an invalid location.\n");
+        return 12;
+    }
+    //Try to set a position outside of the subimage, indexing from the tail.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psImageSet(image, -6, -1, 666) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageSet failed to return false when passed an invalid location.\n");
+        return 13;
+    }
+
+
+    psFree(image);
+    return 0;
+}
+
+static psS32 testImageGet(void)
+{
+    psImage *image = NULL;
+    image = psImageAlloc(5, 3, PS_TYPE_S32);
+
+    //Set the position of the subimage relative to the parent.
+    image->col0 = 10;
+    image->row0 = 10;
+    for (int i = 0; i < 3; i++) {
+        for (int j = 0; j < 5; j++) {
+            image->data.S32[i][j] = i+j;
+        }
+    }
+
+    //Attempt to get a position in a NULL psImage*
+    psImage *none = NULL;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( !isnan( psImageGet(none, 1, 1) ) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImageGet failed to return false when passed a NULL image.\n");
+        return 1;
+    }
+
+    //Attempt to get a position in a psImage* with negative numCols, numRows
+    none = psImageAlloc(2, 2, PS_TYPE_S32);
+    *(int*)&none->numCols = -1;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( !isnan( psImageGet(none, 1, 1) ) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImageGet failed to return false when passed an image with negative numCols.\n");
+        return 2;
+    }
+    *(int*)&none->numCols = 2;
+    *(int*)&none->numRows = -1;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( !isnan( psImageGet(none, 1, 1) ) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImageGet failed to return false when passed an image with negative numRows.\n");
+        return 3;
+    }
+
+    //Attempt to get a position in a psImage* with negative col0, row0
+    *(int*)&none->numRows = 2;
+    none->row0 = -1;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( !isnan( psImageGet(none, 1, 1) ) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImageGet failed to return false when passed an image with negative col0.\n");
+        return 4;
+    }
+    none->row0 = 0;
+    none->col0 = -1;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( !isnan( psImageGet(none, 1, 1) ) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImageGet failed to return false when passed an image with negative col0.\n");
+        return 5;
+    }
+    psFree(none);
+
+    //Try to get a position inside of the subimage.
+    if ( psImageGet(image, 14, 12) != 6 ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImageGet failed to return the correct value.\n");
+        return 6;
+    }
+    //Try to get a position inside of the subimage from the tail.
+    if ( psImageGet(image, -1, -1) != 6 ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psImageGet failed to return the correct value.\n");
+        return 8;
+    }
+
+    //Try to get a position outside of the subimage but inside of the parent image.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( !isnan( psImageGet(image, 1, 1) ) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageGet failed to return NAN when passed an invalid location.\n");
+        return 10;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( !isnan( psImageGet(image, 9, 10) ) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageGet failed to return NAN when passed an invalid location.\n");
+        return 11;
+    }
+
+    //Try to set a position outside of the subimage.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( !isnan( psImageGet(image, 15, 14) ) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageGet failed to return NAN when passed an invalid location.\n");
+        return 12;
+    }
+    //Try to set a position outside of the subimage, indexing from the tail.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( !isnan( psImageGet(image, -6, -1) ) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psImageGet failed to return NAN when passed an invalid location.\n");
+        return 13;
+    }
+
+
+    psFree(image);
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tst_psScalar.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tst_psScalar.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tst_psScalar.c	(revision 22158)
@@ -0,0 +1,138 @@
+/** @file  tst_psScalar.c
+ *
+ *  @brief Contains the tests for psScalar.[ch]
+ *
+ *  @author Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.1 $
+ *           $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-07-13 02:47:00 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include "psTest.h"
+#include "pslib_strict.h"
+
+static psS32 testScalarAlloc(void);
+static psS32 testScalarCopy(void);
+
+#define tstScalarAllocByType(datatype,value)                                                                    \
+scalar = psScalarAlloc(value,PS_TYPE_##datatype);                                                               \
+if(scalar == NULL) {                                                                                            \
+    psError(PS_ERR_UNKNOWN,true,"psScalarAlloc returned NULL.");                                                \
+    return 1+value;                                                                                             \
+} else {                                                                                                        \
+    if( (scalar->type.type != PS_TYPE_##datatype) && (scalar->data.datatype != value) ) {                       \
+        psError(PS_ERR_UNKNOWN,true,"psScalarAlloc created object with unexpected type and/or value");          \
+        return 2+value;                                                                                         \
+    }                                                                                                           \
+}                                                                                                               \
+psFree(scalar);
+
+#define tstScalarCopyByType(datatype,value)                                                                               \
+scalarOrig = psScalarAlloc(value,PS_TYPE_##datatype);                                                                     \
+scalarCopy = psScalarCopy(scalarOrig);                                                                                    \
+if(scalarCopy == NULL) {                                                                                                  \
+    psError(PS_ERR_UNKNOWN,true,"psScalarCopy returned NULL.");                                                           \
+    return 3+value;                                                                                                       \
+} else {                                                                                                                  \
+    if( (scalarCopy->type.type != scalarOrig->type.type) || (scalarCopy->data.datatype != scalarOrig->data.datatype) ) {  \
+        psError(PS_ERR_UNKNOWN,true,"psScalarCopy did not copy the original scalar by type and/or value");                \
+        return 4+value;                                                                                                   \
+    }                                                                                                                     \
+}                                                                                                                         \
+psFree(scalarCopy);                                                                                                       \
+psFree(scalarOrig);
+
+testDescription tests[] = {
+                              {testScalarAlloc,783,"psScalarAlloc",0,false},
+                              {testScalarCopy,784,"psScalarCopy",0,false},
+                              {NULL}
+                          };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    if ( ! runTestSuite(stderr,"psScalar",tests,argc,argv) ) {
+        psError(PS_ERR_UNKNOWN,true,"One or more tests failed");
+        return 1;
+    }
+    return 0;
+}
+
+psS32 testScalarAlloc(void)
+{
+    psScalar* scalar;
+
+    psLogMsg(__func__,PS_LOG_INFO,"psScalarAlloc shall create scalar data objects");
+
+    // Verify the proper allocation/deallocation of scalar objects of valid types
+    tstScalarAllocByType(S8,10);
+    tstScalarAllocByType(U8,12);
+    tstScalarAllocByType(S16,14);
+    tstScalarAllocByType(U16,16);
+    tstScalarAllocByType(S32,18);
+    tstScalarAllocByType(U32,20);
+    tstScalarAllocByType(S64,22);
+    tstScalarAllocByType(U64,24);
+    tstScalarAllocByType(F32,26);
+    tstScalarAllocByType(F64,28);
+    tstScalarAllocByType(C32,30);
+    tstScalarAllocByType(C64,32);
+
+    // Verify return is null for invalid scalar type
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    scalar = psScalarAlloc(true,PS_TYPE_BOOL);
+    if(scalar != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psScalarAlloc did not return null for invalid type");
+        return 5;
+    }
+
+    return 0;
+}
+
+psS32 testScalarCopy(void)
+{
+    psScalar*  scalarOrig;
+    psScalar*  scalarCopy;
+
+    psLogMsg(__func__,PS_LOG_INFO,"psScalarCopy shall copy scalar objects");
+
+    // Verify the proper copying of scalar objects for all valid types
+    tstScalarCopyByType(S8,100);
+    tstScalarCopyByType(U8,110);
+    tstScalarCopyByType(S16,120);
+    tstScalarCopyByType(U16,130);
+    tstScalarCopyByType(S32,140);
+    tstScalarCopyByType(U32,150);
+    tstScalarCopyByType(S64,160);
+    tstScalarCopyByType(U64,170);
+    tstScalarCopyByType(F32,180);
+    tstScalarCopyByType(F64,190);
+    tstScalarCopyByType(C32,200);
+    tstScalarCopyByType(C64,210);
+
+    // Verify the return is null for invalid scalar type in the original
+    scalarOrig = psScalarAlloc(0,PS_TYPE_S8);
+    scalarOrig->type.type = PS_TYPE_BOOL;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    scalarCopy = psScalarCopy(scalarOrig);
+    if(scalarCopy != NULL ) {
+        psError(PS_ERR_UNKNOWN,true,"psScalarCopy did not return NULL for invalid type");
+        return 6;
+    }
+    psFree(scalarOrig);
+
+    // Verify the return is null for null original scalar value
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message");
+    scalarCopy = psScalarCopy(NULL);
+    if(scalarCopy != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psScalarCopy did not return NULL for NULL argument");
+        return 7;
+    }
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tst_psVector.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tst_psVector.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/mathtypes/tst_psVector.c	(revision 22158)
@@ -0,0 +1,648 @@
+/** @file  tst_psVector.c
+ *
+ *  @brief Test driver for psVector integer functions
+ *
+ *  This test driver contains the following tests for psVector test point 1:
+ *     A)  Create S32 vector
+ *     B)  Add data to S32 vector
+ *     C)  Reallocate S32 vector bigger
+ *     D)  Reallocate S32 vector smaller
+ *     E)  Free S32 vector
+ *     F)  Attempt to create a S32 vector with zero size
+ *     G)  Attempt to realloc a null S32 vector
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.12 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2006-05-02 22:35:52 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "psTest.h"
+#include "pslib_strict.h"
+
+static psS32 testVectorAlloc(void);
+static psS32 testVectorRealloc(void);
+static psS32 testVectorExtend(void);
+static psS32 testVectorInit(void);
+static psS32 testVectorCreate(void);
+static psS32 testVectorCreateA(void);
+static psS32 testVectorCreateB(void);
+static psS32 testVectorGetSet(void);
+static psS32 testVectorCountPixelMask(void);
+static psS32 testVectorLength(void);
+static psS32 testVectorCopy(void);
+
+testDescription tests[] = {
+                              {testVectorAlloc,-1,"psVectorAlloc",0,false},
+                              {testVectorRealloc,-2,"psVectorRealloc",0,false},
+                              {testVectorExtend,-3,"psVectorExtend",0,false},
+                              {testVectorInit,-4,"psVectorInit",0,false},
+                              {testVectorCreate,-5,"psVectorCreate",0,false},
+                              {testVectorCreateA,-6,"psVectorCreateA",0,false},
+                              {testVectorCreateB,-7,"psVectorCreateB",0,false},
+                              {testVectorGetSet,-8,"psVectorGet/Set",0,false},
+                              {testVectorCountPixelMask,-9,"psVectorCountPixelMask",0,false},
+                              {testVectorLength,666,"psVectorLength",0,false},
+                              {testVectorCopy,667,"psVectorCopy",0,false},
+                              {NULL}
+                          };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+    psLogSetFormat("HLNM");
+
+    if ( ! runTestSuite(stderr,"psVector",tests,argc,argv) ) {
+        return 1;
+    }
+    return 0;
+}
+
+psS32 testVectorAlloc(void)
+{
+    psVector *psVec = psVectorAlloc(5, PS_TYPE_S32);
+
+    if (psVec == NULL) {
+        fprintf(stderr,"ERROR: Return is NULL\n");
+        return 1;
+    }
+    if (psVec->nalloc != 5) {
+        fprintf(stderr,"Vector size = %ld\n", psVec->nalloc);
+        return 1;
+    }
+    if (psVec->n != 0) {
+        fprintf(stderr,"Vector population = %ld\n", psVec->n);
+        return 2;
+    }
+
+    if (psVec->type.type != PS_TYPE_S32) {
+        fprintf(stderr,"Vector type = %d\n", psVec->type.type);
+        return 3;
+    }
+    if (psVec->type.dimen != PS_DIMEN_VECTOR) {
+        fprintf(stderr,"Vector dimen = %d\n", psVec->type.dimen);
+        return 4;
+    }
+
+    // Test B - Add data to integer vector
+    for(psS32 i = 0; i < 5; i++) {
+        psVec->data.S32[i] = i*10;
+    }
+
+    psVector* vecZero = psVectorAlloc(0, PS_TYPE_S32);
+    if(vecZero == NULL) {
+        fprintf(stderr,"ERROR: Return is NULL\n");
+        return 5;
+    }
+    if (vecZero->nalloc != 0) {
+        fprintf(stderr,"Vector size = %ld\n", vecZero->nalloc);
+        return 6;
+    }
+    if (vecZero->n != vecZero->nalloc) {
+        fprintf(stderr,"Vector population = %ld\n", vecZero->n);
+        return 7;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO, "Following should be an error.");
+    psVector* vecBogus = psVectorAlloc(10, 0);
+    if (vecBogus != NULL) {
+        fprintf(stderr,"Huh!  bogus type generated a psVector?");
+        return 20;
+    }
+
+    psFree(psVec);
+    psFree(vecZero);
+
+    return 0;
+}
+
+psS32 testVectorRealloc(void)
+{
+    // create new psVector
+    psVector *psVec = psVectorAlloc(5, PS_TYPE_S32);
+    if (psVec == NULL) {
+        fprintf(stderr,"ERROR: Return is NULL\n");
+        return 30;
+    }
+    for(psS32 i = 0; i < 5; i++) {
+        psVec->data.S32[i] = i*10;
+        psVec->n++;
+    }
+
+    // Test C - Reallocate S32 vector bigger
+    psVec = psVectorRealloc(psVec,10);
+    if (psVec == NULL) {
+        fprintf(stderr,"ERROR: Return is NULL\n");
+        return 1;
+    }
+    if (psVec->nalloc != 10) {
+        fprintf(stderr,"Vector size = %ld\n", psVec->nalloc);
+        return 1;
+    }
+    if (psVec->n != 5) {
+        fprintf(stderr,"Vector population = %ld\n", psVec->n);
+        return 2;
+    }
+
+    if (psVec->type.type != PS_TYPE_S32) {
+        fprintf(stderr,"Vector type = %d\n", psVec->type.type);
+        return 3;
+    }
+    if (psVec->type.dimen != PS_DIMEN_VECTOR) {
+        fprintf(stderr,"Vector dimen = %d\n", psVec->type.dimen);
+        return 4;
+    }
+
+    for(psS32 i = 5; i < 10; i++) {
+        psVec->data.S32[i] = i*10;
+        psVec->n++;
+    }
+
+    for(psS32 i = 0; i < 10; i++) {
+        if (psVec->data.S32[i] != i*10) {
+            fprintf(stderr,"Elem %d = %d, expected %d\n", i,
+                    psVec->data.S32[i], i*10);
+            return 5;
+        }
+    }
+
+    // Test D - Reallocate S32 vector smaller
+    psVec = psVectorRealloc(psVec,3);
+    if (psVec == NULL) {
+        fprintf(stderr,"ERROR: Return is NULL\n");
+        return 9;
+    }
+    if (psVec->nalloc != 3) {
+        fprintf(stderr,"Vector size = %ld\n", psVec->nalloc);
+        return 10;
+    }
+    if (psVec->n != 3) {
+        fprintf(stderr,"Vector population = %ld\n", psVec->n);
+        return 11;
+    }
+
+    for(psS32 i = 0; i < 3; i++) {
+        if (psVec->data.S32[i] != i*10) {
+            fprintf(stderr,"Elem %d = %d, expected %d\n", i,
+                    psVec->data.S32[i], i*10);
+            return 12;
+        }
+    }
+
+    psVec = psVectorRealloc(psVec,0);
+    if (psVec == NULL) {
+        fprintf(stderr,"ERROR: Return is NULL\n");
+        return 20;
+    }
+    if (psVec->nalloc != 0) {
+        fprintf(stderr,"Vector size = %ld\n", psVec->nalloc);
+        return 21;
+    }
+    if (psVec->n != 0) {
+        fprintf(stderr,"Vector population = %ld\n", psVec->n);
+        return 22;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    psVector* vecBogus = psVectorRealloc(NULL, 6);
+    if (vecBogus != NULL) {
+        fprintf(stderr,"Huh!  bogus type generated a psVector?");
+        return 25;
+    }
+
+    // Test E - Free S32 vector
+    psFree(psVec);
+
+    return 0;
+}
+
+psS32 testVectorExtend(void)
+{
+    // create new psVector
+    psVector *psVec = psVectorAlloc(5, PS_TYPE_S32);
+    if (psVec == NULL) {
+        fprintf(stderr,"ERROR: Return is NULL\n");
+        return 1;
+    }
+
+    psVec->n = 0;
+
+    psVec = psVectorExtend(psVec, 0, 2);
+    if (psVec == NULL) {
+        fprintf(stderr,"ERROR: Return is NULL\n");
+        return 2;
+    }
+    if (psVec->nalloc != 5) { // no growth should occur
+        fprintf(stderr,"Vector size = %ld\n", psVec->nalloc);
+        return 3;
+    }
+    if (psVec->n != 2) {
+        fprintf(stderr,"Vector population = %ld\n", psVec->n);
+        return 4;
+    }
+
+    psVec = psVectorExtend(psVec, 0, 2);
+    if (psVec == NULL) {
+        fprintf(stderr,"ERROR: Return is NULL\n");
+        return 10;
+    }
+    if (psVec->nalloc != 15) { // growth should occur
+        fprintf(stderr,"Vector size = %ld\n", psVec->nalloc);
+        return 11;
+    }
+    if (psVec->n != 4) {
+        fprintf(stderr,"Vector population = %ld\n", psVec->n);
+        return 12;
+    }
+
+    psVec = psVectorExtend(psVec, 0, -2);
+    if (psVec == NULL) {
+        fprintf(stderr,"ERROR: Return is NULL\n");
+        return 20;
+    }
+    if (psVec->nalloc != 15) { // no growth
+        fprintf(stderr,"Vector size = %ld\n", psVec->nalloc);
+        return 21;
+    }
+    if (psVec->n != 2) {
+        fprintf(stderr,"Vector population = %ld\n", psVec->n);
+        return 22;
+    }
+
+    psVec = psVectorExtend(psVec, 0, -20);
+    if (psVec == NULL) {
+        fprintf(stderr,"ERROR: Return is NULL\n");
+        return 30;
+    }
+    if (psVec->nalloc != 15) { // no growth
+        fprintf(stderr,"Vector size = %ld\n", psVec->nalloc);
+        return 31;
+    }
+    if (psVec->n != 0) {
+        fprintf(stderr,"Vector population = %ld\n", psVec->n);
+        return 32;
+    }
+
+    psFree(psVec);
+
+    return 0;
+}
+
+psS32 testVectorInit(void)
+{
+    psVector *in1 = NULL;
+    psVector *in2 = NULL;
+    psVector *in3 = NULL;
+    psVector *in4 = NULL;
+    psVector *in5 = NULL;
+    psVector *in6 = NULL;
+    psVector *in7 = NULL;
+    psVector *in8 = NULL;
+    psVector *in9 = NULL;
+    psVector *in10 = NULL;
+    psVector *in11 = NULL;
+    psVector *in12 = NULL;
+    int nalloc = 1;
+    in1 = psVectorAlloc(nalloc, PS_TYPE_U8);
+    in2 = psVectorAlloc(nalloc, PS_TYPE_U16);
+    in3 = psVectorAlloc(nalloc, PS_TYPE_U32);
+    in4 = psVectorAlloc(nalloc, PS_TYPE_U64);
+    in5 = psVectorAlloc(nalloc, PS_TYPE_S8);
+    in6 = psVectorAlloc(nalloc, PS_TYPE_S16);
+    in7 = psVectorAlloc(nalloc, PS_TYPE_S32);
+    in8 = psVectorAlloc(nalloc, PS_TYPE_S64);
+    in9 = psVectorAlloc(nalloc, PS_TYPE_F32);
+    in10 = psVectorAlloc(nalloc, PS_TYPE_F64);
+    in11 = psVectorAlloc(nalloc, PS_TYPE_C32);
+    in12 = psVectorAlloc(nalloc, PS_TYPE_C64);
+    psC32 vC32;
+    psC64 vC64;
+
+    if ( !psVectorInit(in1, 1 ) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "VectorInit failed.  U8 Case \n");
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psVectorInit(in2, PS_MAX_U64) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "VectorInit failed.  U16 Case \n");
+    }
+    if ( !psVectorInit(in3, 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "VectorInit failed.  U32 Case \n");
+    }
+    if ( !psVectorInit(in4, -1) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "VectorInit failed.  U64 Case \n");
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psVectorInit(in5, PS_MAX_S16 ) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "VectorInit failed.  S8 Case \n");
+    }
+    if ( !psVectorInit(in6, -100 ) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "VectorInit failed.  S16 Case \n");
+    }
+    if ( !psVectorInit(in7, 1 ) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "VectorInit failed.  S32 Case \n");
+    }
+    if ( !psVectorInit(in8, PS_MAX_U64 ) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "VectorInit failed.  S64 Case \n");
+    }
+    if ( !psVectorInit(in9, 1.1 ) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "VectorInit failed.  F32 Case \n");
+    }
+    if ( !psVectorInit(in10, 1.4 ) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "VectorInit failed.  F64 Case \n");
+    }
+
+    vC32 = 1.23 + 1.19I;
+    vC64 = 2.13 + 2.31I;
+    if ( !psVectorInit(in11, vC32 ) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "VectorInit failed.  C32 Case \n");
+    }
+    if ( !psVectorInit(in12, vC64 ) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "VectorInit failed.  C64 Case \n");
+    }
+
+    psFree(in1);
+    psFree(in2);
+    psFree(in3);
+    psFree(in4);
+    psFree(in5);
+    psFree(in6);
+    psFree(in7);
+    psFree(in8);
+    psFree(in9);
+    psFree(in10);
+    psFree(in11);
+    psFree(in12);
+    return 0;
+}
+
+psS32 testVectorCreate(void)
+{
+    psVector *test = NULL;
+    psVector *test2 = NULL;
+    psVector *input = NULL;
+    psVector *input2 = psVectorAlloc(5, PS_TYPE_F32);
+
+    test = psVectorCreate(input, 0.0, 10.0, 1.0, PS_TYPE_S32);
+    test2 = psVectorCreate(input2, 0.0, 5.0, 0.5, PS_TYPE_F32);
+
+    for (int i = 0; i < 10; i++) {
+        if (test->data.S32[i] != i) {
+            fprintf(stderr, "Vector data does not match. i = %d, data=%d\n",
+                    i, test->data.S32[i]);
+            return 1;
+        }
+        if (test2->data.F32[i] != i*0.5) {
+            fprintf(stderr, "Vector data does not match. i = %d, data=%f\n",
+                    i, test->data.F32[i]);
+            return 1;
+        }
+    }
+    psFree(test);
+    psFree(test2);
+    return 0;
+}
+psS32 testVectorCreateA(void)
+{
+    //
+    //  Test PS_TYPE_F64
+    //       PS_TYPE_S64
+    //
+    psVector *test = NULL;
+    psVector *test2 = NULL;
+    psVector *input = NULL;
+    psVector *input2 = psVectorAlloc(5, PS_TYPE_F64);
+
+    test = psVectorCreate(input, 0.0, 10.0, 1.0, PS_TYPE_S64);
+    test2 = psVectorCreate(input2, 0.0, 5.0, 0.5, PS_TYPE_F64);
+
+    for (int i = 0; i < 10; i++) {
+        if (test->data.S64[i] != i) {
+            fprintf(stderr, "Vector data does not match. i = %d, data=%ld\n",
+                    i, (long)test->data.S64[i]);
+            return 1;
+        }
+        if (test2->data.F64[i] != i*0.5) {
+            fprintf(stderr, "Vector data does not match. i = %d, data=%f\n",
+                    i, test->data.F64[i]);
+            return 1;
+        }
+    }
+    psFree(test);
+    psFree(test2);
+    return 0;
+}
+psS32 testVectorCreateB(void)
+{
+    //
+    //  Test PS_TYPE_U16
+    //       PS_TYPE_S16
+    //
+    psVector *test = NULL;
+    psVector *test2 = NULL;
+    psVector *input = NULL;
+    psVector *input2 = psVectorAlloc(5, PS_TYPE_U16);
+
+    test = psVectorCreate(input, 0.0, 10.0, 1.0, PS_TYPE_S16);
+    test2 = psVectorCreate(input2, 0.0, 20.0, 2.0, PS_TYPE_U16);
+
+    for (int i = 0; i < 10; i++) {
+        if (test->data.S16[i] != i) {
+            fprintf(stderr, "Vector data does not match. i = %d, data=%d\n",
+                    i, test->data.S16[i]);
+            return 1;
+        }
+        if (test2->data.U16[i] != i*2.0) {
+            fprintf(stderr, "Vector data does not match. i = %d, data=%d\n",
+                    i, test->data.U16[i]);
+            return 1;
+        }
+    }
+    psFree(test);
+    psFree(test2);
+    return 0;
+}
+psS32 testVectorGetSet(void)
+{
+    psVector *vec = NULL;
+    vec = psVectorAlloc(5, PS_TYPE_S32);
+    vec->n = 0;
+
+    if ( !psVectorSet(vec, 0, 10) ) {
+        fprintf(stderr, "VectorSet failed to set S32 at position 0\n");
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psVectorSet(vec, 10, 10) ) {
+        fprintf(stderr, "VectorSet Improperly set S32 at out of range position\n");
+    }
+    if ( !psVectorSet(vec, 1, 4) ) {
+        fprintf(stderr, "VectorSet Failed to set S32 at position 1\n");
+    }
+    if ( (psS32)psVectorGet(vec, 0) != 10 ) {
+        fprintf(stderr,
+                "VectorGet Failed to return the correct S32 from position 0\n");
+    }
+    if ( (psS32)psVectorGet(vec, -1) != 4 ) {
+        fprintf(stderr,
+                "VectorGet Failed to return the correct S32 from tail using -1\n");
+    }
+
+    psFree(vec);
+    return 0;
+}
+
+psS32 testVectorCountPixelMask(void)
+{
+    long numPix = 0;
+    long numPix2 = 0;
+    psVector *vec = NULL;
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    numPix = psVectorCountPixelMask(vec, 1);
+    if (numPix != -1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psVectorCountPixelMask failed to return -1 for NULL Vector input.\n");
+        return 1;
+    }
+
+    numPix = 0;
+    vec = psVectorAlloc(5, PS_TYPE_S32);
+    psVector *vec2 = NULL;
+    vec2 = psVectorAlloc(5, PS_TYPE_U8);
+    vec->data.S32[0] = 0;
+    vec->data.S32[1] = 1;
+    vec->data.S32[2] = 0;
+    vec->data.S32[3] = 1;
+    vec->data.S32[4] = 0;
+    vec2->data.U8[0] = 0;
+    vec2->data.U8[1] = 1;
+    vec2->data.U8[2] = 0;
+    vec2->data.U8[3] = 1;
+    vec2->data.U8[4] = 0;
+    vec->n = 5;
+    vec2->n = 5;
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    numPix = psVectorCountPixelMask(vec, 1);
+    numPix2 = psVectorCountPixelMask(vec2, 1);
+
+    if (numPix != -1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psVectorCountPixelMask failed to return -1 for wrong type of Vector input.\n");
+        return 2;
+    }
+    if (numPix2 == -1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psVectorCountPixelMask returned -1 for correct Vector input\n");
+        return 3;
+    }
+    if (numPix2 != 2) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psVectorCountPixelMask returned incorrect pixel count %d\n", numPix2);
+        return 4;
+    }
+
+    psFree(vec);
+    psFree(vec2);
+    return 0;
+}
+
+psS32 testVectorLength( void )
+{
+    psVector *vector = psVectorAlloc(5, PS_TYPE_F32);
+
+    if (psVectorLength(vector) != 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psVectorLength failed to return the correct length of vector.\n");
+        return 1;
+    }
+    vector->n = 5;
+    if (psVectorLength(vector) != 5) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psVectorLength failed to return the correct length of vector.\n");
+        return 2;
+    }
+    vector->n++;
+    if (psVectorLength(vector) != 6) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psVectorLength failed to return the correct length of vector.\n");
+        return 3;
+    }
+    psFree(vector);
+
+    psVector *emptyVector = NULL;
+    psArray *array = psArrayAlloc(5);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if (psVectorLength(emptyVector) != -1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psVectorLength failed to return -1 for a NULL input vector.\n");
+        return 4;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if (psVectorLength((psVector*)array) != -1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psVectorLength failed to return -1 for an invalid input vector.\n");
+        return 5;
+    }
+    psFree(array);
+
+    return 0;
+}
+
+psS32 testVectorCopy(void)
+{
+
+    psVector *in = NULL;
+    psVector *copy = NULL;
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    copy = psVectorCopy(copy, in, PS_TYPE_F32);
+    if (copy != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "psVectorCopy failed to return a NULL vector for NULL input.\n");
+        return 1;
+    }
+
+    in = psVectorAlloc(5, PS_TYPE_F32);
+    in->n = 5;
+    for (int i = 0; i < 5; i++) {
+        in->data.F32[i] = i;
+    }
+    //Try copy of different type
+    copy = psVectorCopy(copy, in, PS_TYPE_F64);
+    if (copy == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "psVectorCopy returned a NULL vector for correct input.\n");
+        return 2;
+    } else if (copy->data.F64[2] != 2.0) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "psVectorCopy failed to return the correct data values.\n");
+        printf("\n copy->data.f64[2] = %lf, in->data.f32[2] = %f\n", copy->data.F64[2],
+               in->data.F32[2]);
+        return 3;
+    }
+
+    copy = psVectorRecycle(copy, in->n + 2, PS_TYPE_F64);
+    //Try copy of same type and non-NULL outVector of different type and size.
+    copy = psVectorCopy(copy, in, in->type.type);
+    if (copy == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "psVectorCopy returned a NULL vector for correct input.\n");
+        return 4;
+    } else if (copy->type.type != PS_TYPE_F32 || copy->data.F32[2] != 2.0) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "psVectorCopy failed to return the correct data values.\n");
+        return 5;
+    }
+
+
+    psFree(in);
+    psFree(copy);
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/notes.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/notes.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/notes.txt	(revision 22158)
@@ -0,0 +1,13 @@
+
+test directories which are currently (2008.05.04) working:
+
+types : OK
+sys : OK
+mathtypes : OK, but tap_psImageInterpolate does not build
+math : many problems
+jpeg : no tests
+imageops : many problems
+fits : many problems
+fft : OK
+db : probably needs a working db installation
+astro : many problems
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/pstap/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/pstap/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/pstap/.cvsignore	(revision 22158)
@@ -0,0 +1,3 @@
+Makefile
+Makefile.in
+.deps
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/pstap/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/pstap/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/pstap/Makefile.am	(revision 22158)
@@ -0,0 +1,1 @@
+SUBDIRS = src
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/pstap/src/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/pstap/src/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/pstap/src/.cvsignore	(revision 22158)
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+.deps
+.libs
+libpstap.la
+pstap.lo
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/pstap/src/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/pstap/src/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/pstap/src/Makefile.am	(revision 22158)
@@ -0,0 +1,12 @@
+AM_CPPFLAGS = $(SRCINC) -I$(top_srcdir)/test/tap/src $(PSLIB_CFLAGS)
+AM_LDFLAGS = \
+	$(top_builddir)/src/libpslib.la  \
+	$(top_builddir)/test/tap/src/libtap.la \
+	$(PSLIB_LIBS)
+
+TEST_LTLIBS = libpstap.la
+libpstap_la_SOURCES = pstap.c
+noinst_HEADERS = pstap.h
+
+noinst_LTLIBRARIES = $(TEST_LTLIBS)
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/pstap/src/pstap.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/pstap/src/pstap.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/pstap/src/pstap.c	(revision 22158)
@@ -0,0 +1,6 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <tap.h>
+#include <pslib.h>
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/pstap/src/pstap.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/pstap/src/pstap.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/pstap/src/pstap.h	(revision 22158)
@@ -0,0 +1,145 @@
+#include <math.h>
+
+
+#include <pslib.h>
+
+#include "tap.h"
+
+#define done() ok(psMemCheckLeaks(0, NULL, stdout, false) == 0, "Memory Leaks"); \
+return exit_status()
+
+# define mem() ok(psMemCheckLeaks(psMemGetLastId(), NULL, stdout, false) == 0, "Memory Leaks")
+
+# define checkLeaks false
+
+# define checkMem() if(checkLeaks) mem()
+
+// write a comment which is counted as a test (and swallowed by prove)
+# define note(...)\
+{ \
+    fprintf(stdout, __VA_ARGS__); \
+    fprintf(stdout, "\n[%s:%d in %s]\n", __FILE__, __LINE__, __func__); \
+}
+
+# define noted(...) _gen_result(1, __func__, __FILE__, __LINE__, __VA_ARGS__);
+
+// use to test the value of a float
+# define is_float(VALUE, EXPECT, ...) \
+{ \
+    bool status = false; \
+    if (isnan(EXPECT)) { \
+        status = isnan(VALUE); \
+    } else { \
+        status = (fabsf(VALUE - EXPECT) < FLT_EPSILON); \
+    } \
+    ok(status, __VA_ARGS__); \
+    if (!status) { \
+        diag("         got: '%f'", VALUE); \
+        diag("    expected: '%f'", EXPECT); \
+    } \
+}
+
+
+// use to test the value of a float within a defined tolerance
+# define is_float_tol(VALUE,EXPECT,TOL,...)\
+{ \
+    bool status = false; \
+    if (isnan(EXPECT)) { \
+        status = isnan(VALUE); \
+    } else { \
+        status = (fabsf((VALUE) - (EXPECT)) < (TOL)); \
+    } \
+    ok(status, __VA_ARGS__); \
+    if (!status) { \
+        diag("         got: '%f'", VALUE); \
+        diag("    expected: '%f' +/- %f", EXPECT, TOL); \
+    } \
+}
+
+
+// use to test the value of a double
+# define is_double(VALUE,EXPECT,...)\
+{ \
+    bool status = false; \
+    if (isnan(EXPECT)) { \
+        status = isnan(VALUE); \
+    } else { \
+        status = (fabs(VALUE - EXPECT) < DBL_EPSILON); \
+    } \
+    ok(status, __VA_ARGS__); \
+    if (!status) { \
+        diag("         got: '%.10f'", VALUE); \
+        diag("    expected: '%.10f'", EXPECT); \
+    } \
+}
+
+
+// use to test the value of a double
+# define is_double_tol(VALUE,EXPECT,TOL, ...)\
+{ \
+    bool status = false; \
+    if (isnan(EXPECT)) { \
+        status = isnan(VALUE); \
+    } else { \
+        status = (fabs((VALUE) - (EXPECT)) < (TOL)); \
+    } \
+    ok(status, __VA_ARGS__); \
+    if (!status) { \
+        diag("         got: '%.10f'", VALUE); \
+        diag("    expected: '%.10f' +/- %.10f", EXPECT, TOL); \
+    } \
+}
+
+
+# define is_str(VALUE, EXPECT, ...) \
+{ \
+    int cmp = (strcmp(VALUE, EXPECT) == 0); \
+    ok(cmp, __VA_ARGS__); \
+    if (!cmp) { \
+        diag("         got: '%s'", VALUE); \
+        diag("    expected: '%s'", EXPECT); \
+    } \
+}
+
+
+# define is_strn(VALUE, EXPECT, N, ...)\
+{ \
+    int cmp = (strncmp(VALUE, EXPECT, N) == 0); \
+    ok(cmp, __VA_ARGS__); \
+    if (!cmp) { \
+        diag("         got: '%s'", VALUE); \
+        diag("    expected: '%s'", EXPECT); \
+    } \
+}
+
+
+# define is_int(VALUE, EXPECT, ...)\
+{ \
+    int cmp = (VALUE == EXPECT); \
+    ok(cmp, __VA_ARGS__); \
+    if (!cmp) { \
+        diag("         got: '%d'", VALUE); \
+        diag("    expected: '%d'", EXPECT); \
+    } \
+}
+
+
+# define is_long(VALUE, EXPECT, ...)\
+{ \
+    int cmp = (VALUE == EXPECT); \
+    ok(cmp, __VA_ARGS__); \
+    if (!cmp) { \
+        diag("         got: '%ld'", VALUE); \
+        diag("    expected: '%ld'", EXPECT); \
+    } \
+}
+
+# define is_bool(VALUE, EXPECT, ...)\
+{ \
+    int cmp = (VALUE == EXPECT); \
+    ok(cmp, __VA_ARGS__); \
+    if (!cmp) { \
+        diag("         got: '%s'", VALUE ? "true" : "false"); \
+        diag("    expected: '%s'", EXPECT ? "true" : "false"); \
+    } \
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/sys/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/sys/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/sys/.cvsignore	(revision 22158)
@@ -0,0 +1,30 @@
+temp
+.deps
+.libs
+Makefile
+Makefile.in
+log.txt
+log2.txt
+tst_psAbort
+tst_psConfigure
+tst_psError
+tst_psLogMsg
+tst_psMemory
+tst_psString
+tst_psTrace
+tst_psTrace02_OUT
+test.fits
+core
+core.*
+tap_psStringSubstitute
+tst_psLine
+*.bb
+*.bbg
+*.da
+gmon.out
+tap_psConfigure
+tap_psError
+tap_psLine
+tap_psMemory
+tap_psString
+tap_psTrace
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/sys/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/sys/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/sys/Makefile.am	(revision 22158)
@@ -0,0 +1,31 @@
+AM_CPPFLAGS = \
+	$(SRCINC) \
+	-I$(top_srcdir)/test/tap/src \
+	-I$(top_srcdir)/test/pstap/src \
+	$(PSLIB_CFLAGS)
+AM_LDFLAGS = \
+	$(top_builddir)/src/libpslib.la  \
+	$(top_builddir)/test/tap/src/libtap.la \
+	$(top_builddir)/test/pstap/src/libpstap.la \
+	$(PSLIB_LIBS)
+
+TEST_PROGS = \
+	tap_psString \
+	tap_psTrace \
+	tap_psError \
+	tap_psMemory \
+	tap_psLine \
+	tap_psConfigure \
+	tap_psStringSubstitute
+
+if BUILD_TESTS
+bin_PROGRAMS = $(TEST_PROGS)
+TESTS = $(TEST_PROGS)
+else
+check_PROGRAMS = $(TEST_PROGS)
+endif
+
+CLEANFILES = $(check_DATA) temp/* log.txt log2.txt test.fits tst_psTrace02_OUT \
+	core core.* *~ *.bb *.bbg *.da gmon.out
+
+test: check
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/sys/table.fits
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/sys/table.fits	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/sys/table.fits	(revision 22158)
@@ -0,0 +1,1 @@
+END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tableF32.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tableF32.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tableF32.dat	(revision 22158)
@@ -0,0 +1,9 @@
+#  Table with valid types and index-values
+#
+#psF32     psU16    psU32     psU64    psS8    psS16    psS32    psS64    psU8   psF64
+-10.05    2        4         8        0       -2       -4       -8       5      -1.5
+ 1.009     4        8         16       -1      -4       -8       -16      0      -1.0
+23.45     6        12        24       -2      -6       -12      -24      5      -0.25
+3500.67   8        16        32       -3      -8       -16      -32      75     1.75
+   
+#
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psConfigure.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psConfigure.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psConfigure.c	(revision 22158)
@@ -0,0 +1,41 @@
+/** @file  tst_psConfigure.c
+ *
+ *  @brief Test driver for psconfigure functions
+ *
+ *  This test driver contains the following test points for psConfigure
+ *  functions.
+ *    1) Return current psLib version
+ *
+ *  Return:   Number of test points which failed
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2007-04-10 21:09:31 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "tap.h"
+#include "pstap.h"
+#include "string.h"
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    plan_tests(2);
+
+    // Simple test of psLibVersion()
+    // XX: Must somehow verify the output is correct.
+    {
+        psMemId id = psMemGetId();
+        char *stringVal = NULL;
+        stringVal = psLibVersion();
+        ok(stringVal != NULL && strlen(stringVal), "Version is cool");
+        psFree(stringVal);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psError.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psError.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psError.c	(revision 22158)
@@ -0,0 +1,382 @@
+/** @file  tst_psError.c
+ *
+ *  @brief Test driver for psError function
+ *
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.7 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2008-05-05 00:09:04 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include "pslib.h"
+#include "tap.h"
+#include "pstap.h"
+
+// XXX in this file, several operations are only validated by printing an output to the screen.   
+// we should define an output file and compare the contents of the output file to expectations.
+// I've commented out these features for now
+
+# if (0)
+// Function used in testError02 to verify the psErrorStackPrintV function
+static void myErrorStackPrint(
+    FILE *fd,
+    const char *fmt,
+    ...)
+{
+    va_list ap;
+
+    // Test whether psErrorStackPrintV() accept a va_list for output variables
+    va_start(ap, fmt);
+    psErrorStackPrintV(fd, fmt, ap);
+    va_end(ap);
+}
+# endif
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(60);
+
+
+    //psError() tests
+    {
+        psS32  intval=1;
+        psS64 longval = 2;
+        float floatval = 3.01;
+        char  charval = 'E';
+        char *stringval = "E R R O R";
+
+        // Multiple type values placed in the error string
+        // XX: The output is never verified
+        {
+            psMemId id = psMemGetId();
+            psError(PS_ERR_UNKNOWN, true,
+                    "ALL TYPES intval = %d longval = %"PRId64 " floatval = %f charval = %c strval = %s",
+                    intval,longval,floatval,charval,stringval);
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+    
+
+        // String values in error message
+        // XX: The output is never verified
+        {
+            psMemId id = psMemGetId();
+            psError(PS_ERR_UNKNOWN, true, "NO VALUES");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Empty strings in error message
+        // XX: The output is never verified
+        {
+            psMemId id = psMemGetId();
+            psError(PS_ERR_UNKNOWN, true, " ");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Verify the return value of psErrorMsg is the psErrorCode passed
+        {
+            psMemId id = psMemGetId();
+            psErrorCode code=PS_ERR_BAD_PARAMETER_VALUE;
+            ok(psError(code, true, "Error code = %d", code) == code, "Failed return value verify.");
+            // psErrorStackPrint(stderr,"ERROR STACK PRINT Test1A");
+            ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // test1B empty string in for name argument
+        {
+            psMemId id = psMemGetId();
+            psErrorCode code=PS_ERR_BAD_PARAMETER_VALUE;
+            ok(psError(code+1, true, "Error code = %d", code+1) == code+1,
+                 "Failed return with empty string.");
+            // psErrorStackPrint(stderr,"ERROR STACK PRINT Test1B");
+            ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // test1D undefined code
+        {
+            psMemId id = psMemGetId();
+            ok(psError(-1, true, "Error code = %d", -1) == -1,
+                 "Failed return with undefined code.");
+            // psErrorStackPrint(stderr,"ERROR STACK PRINT Test1D");
+            ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // test1E set psErrorMsg argument to false
+        {
+            psMemId id = psMemGetId();
+            psErrorCode code=PS_ERR_BAD_PARAMETER_VALUE;
+            ok(psError(code, false, "Error code = %d", code) == code,
+                "Failed return with false new arg.");
+            // psErrorStackPrint(stderr,"ERROR STACK PRINT Test1E");
+            ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // test1F psErrorMsg with a error code less then PS_ERR_BASE(256)
+        {
+            psMemId id = psMemGetId();
+            ok(psError(9, true, "Errno code = %d", 9) == 9, "Error Code" );
+            // psErrorStackPrint(stderr,"ERROR STACK PRINT Test1F");
+            ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+        }
+    }
+
+
+    //testError02()
+    {
+        // Generate error message and verify return value
+        {
+            psErrorCode code = PS_ERR_BAD_PARAMETER_VALUE;
+            psMemId id = psMemGetId();
+            ok(psError(code, true, "Error code = %d", code) == code,
+                "Failed return value verify.");
+            // myErrorStackPrint(stderr,"ERROR STACK PRINT Test%dA",2);
+            ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+        }
+    }
+
+
+    //psErrorGet(), psErrorLast()
+    {
+        // Attempt to get last error message with an empty stack verify 
+        // psErr with code PS_ERR_NONE
+        {
+            psMemId id = psMemGetId();
+            psErrorClear();
+            psErr *last = psErrorLast();
+            ok(last != NULL, "psErrorLast() returned non-NULL");
+            skip_start(last == NULL, 1, "Skipping tests because psErrorLast() returned NULL");
+            ok(last->code == PS_ERR_NONE,
+              "psErrorLast did return PS_ERR_NONE for empty stack(%d)", last->code);
+            skip_end();
+            psFree(last);
+            ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+        }
+
+        // Attempt to get specific error message with empty stack verify
+        // psErr with code PS_ERR_NONE
+        {
+            psMemId id = psMemGetId();
+            psErr *getErr= psErrorGet(2);
+            ok(getErr != NULL, "psErrorGet(2) returned non-NULL");
+            skip_start(getErr == NULL, 1, "Skipping tests because psErrorGet() returned NULL");
+            ok(getErr->code == PS_ERR_NONE,
+               "psErrorGet(2) did return PS_ERR_NONE for empty stack(%d)", getErr->code);
+            skip_end();
+            psFree(getErr);
+            ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Attempt to get error message with invalid index and an empty stack
+        {
+            psMemId id = psMemGetId();
+            psErr *getErr= psErrorGet(-1);
+            ok(getErr != NULL, "psErrorGet(-1) returned non-NULL");
+            skip_start(getErr == NULL, 1, "Skipping tests because psErrorGet(-1) returned NULL");
+            ok(getErr->code == PS_ERR_NONE, "psErrorGet with invalid index/empty stack");
+            skip_end();
+            psFree(getErr);
+            ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Generate three error messages, ensure they are correctly returned by psError()
+        {
+            psMemId id = psMemGetId();
+            psErrorCode code = PS_ERR_BAD_PARAMETER_VALUE;
+            ok(psError(code, true, "Error code = %d", code) ==  code,
+                "psError() returned correct error code (example 1)");
+            ok(psError((code+1), false, "Error code = %d", (code+1)) == (code+1),
+                "psError() returned correct error code (example 2)");
+            ok(psError((code+2), false, "Error code = %d", (code+2)) == (code+2),
+                "psError() returned correct error code (example 3)");
+    
+            psErr *last = psErrorLast();
+            psErr *getErr= psErrorGet(0);
+    
+            // Check that last and get with 0 index are equal
+            ok(last == getErr, "psErrorGet(0) equal to psErrorLast()");
+            psFree(last);
+
+            // Verify the last error message was returned
+            ok(getErr->code == (code+2), "psErrorLast() did retrieve last error");
+            psFree(getErr);
+            psErrorClear();
+            ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Verify the middle error message can be retrieved
+        {
+            psMemId id = psMemGetId();
+            psErrorCode code = PS_ERR_BAD_PARAMETER_VALUE;
+            psError(code, true, "Error code = %d", code);
+            psError((code+1), false, "Error code = %d", (code+1));
+            psError((code+2), false, "Error code = %d", (code+2));
+            psErr *getErr= psErrorGet(1);
+            ok(getErr->code == (code+1), "psErrorGet() did not retrieve proper error");
+            psFree(getErr);
+            psErrorClear();
+            ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+        }
+
+        // Verify the psErrorGet returns non-NULL PS_ERR_NONE if an invalid index
+        // is given with non-empty error stack
+        {
+            psMemId id = psMemGetId();
+            psErrorCode code = PS_ERR_BAD_PARAMETER_VALUE;
+            psError(code, true, "Error code = %d", code);
+            psError((code+1), false, "Error code = %d", (code+1));
+            psError((code+2), false, "Error code = %d", (code+2));
+            psErr *getErr= psErrorGet(-1);
+            ok(getErr->code == PS_ERR_NONE, "psErrorGet() did not return PS_ERR_NONE w/ invalid arg");
+            psFree(getErr);
+            psErrorClear();
+            ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+        }
+    }
+
+
+    // psErrorClear()
+    {
+        // With an attemp error stack call psErrorClear
+        {
+            psMemId id = psMemGetId();
+            psErrorClear();
+            // Get the last error message and verify PS_ERR_NONE (empty stack)
+            psErr *lastAfterClear = psErrorLast();
+            ok(lastAfterClear->code == PS_ERR_NONE, "psErrorLast return expected.");
+            psFree(lastAfterClear);
+            ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+        }
+
+
+        // Generate three error messages to have messages on error stack
+        {
+            psMemId id = psMemGetId();
+            psErrorCode code = PS_ERR_BAD_PARAMETER_VALUE;
+            ok(psError(code, true, "Error code = %d", code) == code,
+                "Failed return value verify.");
+            ok(psError((code+1), false, "Error code = %d", (code+1)) == (code+1),
+                "Failed return value verify.");
+            ok(psError((code+2), false, "Error code = %d", (code+2)) == (code+2),
+                "Failed return value verify.");
+            ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+        }
+
+        // Get the last error message and verify it has the expected code
+        {
+            psMemId id = psMemGetId();
+            psErrorCode code = PS_ERR_BAD_PARAMETER_VALUE;
+            psErr *last = psErrorLast();
+            ok(last->code == (code+2), "psErrorLast return expected.");
+            psFree(last);
+            ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+        }
+
+        // Clear the error stack
+        {
+            psMemId id = psMemGetId();
+            psErrorClear();
+            // Get the last error message after clear and verify is has PS_ERR_NONE code
+            psErr *lastAfterClear  = psErrorLast();
+            ok(lastAfterClear->code == PS_ERR_NONE, "psErrorLast return expected.");
+            psFree(lastAfterClear);
+            ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+        }
+    }
+
+
+    // psErrorCodeString()
+    {
+        // Verify the return value of psErrorCodeString
+        // psErrorCode code = PS_ERR_BAD_PARAMETER_VALUE;
+        // Verify the return value of psErrorCodeString if code is negative
+        ok( psErrorCodeString(-1) == NULL, "error string with neg. code");
+    }
+
+
+    //testErrorRegister()
+    {
+        psS32 numErr = 4;
+        psErrorDescription errDesc[] = { {PS_ERR_N_ERR_CLASSES+1,"first"},
+                                         {PS_ERR_N_ERR_CLASSES+2,"second"},
+                                         {PS_ERR_N_ERR_CLASSES+3,"third"},
+                                         {PS_ERR_N_ERR_CLASSES+4,"fourth"} };
+        /*
+            1. invoke psErrorRegister with a n>1 array of psErrorDescriptions. Verify that:
+                a. Each error description given is retrievable with psErrorCodeString.
+        */
+        psErrorRegister(errDesc,numErr);
+
+        for (psS32 i = 0; i < numErr; i++) {
+            const char* desc = psErrorCodeString(PS_ERR_N_ERR_CLASSES+1+i);
+            ok(desc != NULL,
+                "psErrorCode didn't find registered error code.");
+
+            ok(strcmp(desc,errDesc[i].description) == 0,
+                "psErrorCode didn't return the proper description.  Got '%s', expected '%s'.", desc,errDesc[i].description);
+        }
+
+        /*
+            2. invoke psErrorCodeString with a static/builtin psLib error code. Verify:
+                a. the result is correct.
+        */
+        const char* desc = psErrorCodeString(PS_ERR_N_ERR_CLASSES);
+        ok(desc != NULL, "psErrorCode didn't find static error code.");
+        ok(strcmp(desc,"error classes end marker") == 0,
+            "psErrorCode didn't return the proper description.  Got '%s', expected '%s'.",
+            desc,"error classes end marker");
+
+        desc = psErrorCodeString(PS_ERR_NONE);
+        ok(desc != NULL,
+            "psErrorCode didn't find static error code.");
+        ok(strcmp(desc,"not an error") == 0,
+            "psErrorCode didn't return the proper description.  Got '%s', expected '%s'.",
+            desc,"not an error");
+    
+        /*
+            3. invoke psErrorCodeString with an invalid code. Verify a NULL is returned.
+        */
+        desc = psErrorCodeString(PS_ERR_N_ERR_CLASSES+numErr+1);
+        ok(desc == NULL,
+            "psErrorCode didn't return a NULL with a bogus input code.");
+
+        /*
+            4. invoke psErrorRegister with a NULL psErrorDescription. Verify that:
+                a. the execution does not cease.
+                b. an appropriate error is generated.
+        */
+        // Following should be an error
+        psErrorClear();
+        psErrorRegister(NULL,1);
+        psErr* err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_NULL,
+        "psErrorCode didn't generate proper error code for NULL input.");
+
+        psFree(err);
+
+        /*
+            5. invoke psErrorRegister with nerror=0. Verify that no error occurs.
+        */
+        psErrorClear();
+        psErrorRegister(errDesc,0);
+        err = psErrorLast();
+        ok(err->code == PS_ERR_NONE,
+            "psErrorCode generated an error for nErrors = 0.");
+        psFree(err);
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psLine.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psLine.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psLine.c	(revision 22158)
@@ -0,0 +1,89 @@
+/** @file  tst_psLine.c
+ *
+ *  @brief Test driver for psLine functions
+ *
+ *  @author  dRob, MHPCC
+ *
+ *  @version $Revision: 1.4 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2007-04-10 21:09:31 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib.h"
+#include "tap.h"
+#include "pstap.h"
+#include "string.h"
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    plan_tests(16);
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+
+    //testLineAlloc()
+    {
+        psMemId id = psMemGetId();
+        psLine *lineline = NULL;
+        lineline = psLineAlloc(20);
+        ok(lineline->NLINE==20, "psLine set NLINE parameter during Allocation");
+        ok(lineline->Nline == 0, "psLine set Nline parameter during Allocation");
+        strncpy(lineline->line, "Hello World", 20);
+        ok(!strncmp(lineline->line, "Hello World", 20),
+            "psLine was stored a simple string!");
+        psFree(lineline);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // testLineInit()
+    {
+        psMemId id = psMemGetId();
+        psLine *line = NULL;
+        //Return false for NULL input
+        int okay = !psLineInit(line);
+        ok(okay, "psLineInit.  Expected false for NULL psLine input");
+        //Allocate a line and return true on Init
+        line = psLineAlloc(1);
+        okay = psLineInit(line);
+        ok(okay, "psLineInit.  Expected true for valid psLine input");
+        ok(line->NLINE == 1 && line->Nline == 0, "psLineInit returned line parameters.");
+        psFree(line);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testLineAdd()
+    {
+        psMemId id = psMemGetId();
+        psLine *line = NULL;
+        //Return false for NULL input
+        ok(!psLineAdd(line, "Hello World"),
+            "psLineAdd.  Expected false for NULL psLine input.");
+        //Allocate and return true for valid input.
+        line = psLineAlloc(20);
+        int okay = psLineAdd(line, "Hello %s", "World");
+        ok( okay, "psLineAdd.  Expected true for valid psLine input");
+        ok(line->NLINE == 20 && line->Nline == 11,
+            "psLineAdd failed to return the correct line parameters");
+        ok(!strncmp(line->line, "Hello World", 20),
+            "psLineAdd failed to store the correct line string.");
+        psFree(line);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testLineChk()
+    {
+        psMemId id = psMemGetId();
+        psLine *line = NULL;
+        //Return false for Null input line
+        ok(!psMemCheckLine(line),
+            "psMemCheckLine return false for NULL line input");
+        line = psLineAlloc(1);
+        ok(psMemCheckLine(line),
+            "psMemCheckLine return true for valid line input");
+        psFree(line);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psMemory.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psMemory.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psMemory.c	(revision 22158)
@@ -0,0 +1,621 @@
+/** @file  tst_psMemory.c
+*
+*  @brief Contains the tests for psMemory.[ch]
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-05-01 00:08:52 $
+*
+*  XXXX: Several tests fail with an Abort and are commented out.
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <stdlib.h>
+
+
+#include "pslib.h" // need to allow malloc for callback use
+#include "tap.h"
+#include "pstap.h"
+
+static psS32 problemCallbackCalled = 0;
+static psS32 allocCallbackCalled = 0;
+static psS32 freeCallbackCalled = 0;
+static psS32 exhaustedCallbackCalled = 0;
+
+psMemId memAllocCallback( const psMemBlock *ptr );
+psMemId memFreeCallback( const psMemBlock *ptr );
+psS32 memCheckTypes( void );
+void memProblemCallback( psMemBlock *ptr, const char *filename, unsigned int lineno );
+psPtr TPOutOfMemoryExhaustedCallback( size_t size );
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(46);
+
+    // TPFreeReferencedMemory()
+    {
+        psMemId id = psMemGetId();
+        psS32 *mem  = ( psS32* ) psAlloc( 100 * sizeof( psS32 ) );
+        psS32 ref = psMemGetRefCounter( mem );
+        ok(ref == 1, "buffer reference count %d.", ref );
+        skip_start ( ref != 1, 3, "buffer reference count %d.", ref );
+        psMemIncrRefCounter(mem);
+        psMemIncrRefCounter(mem);
+        psMemIncrRefCounter(mem);
+
+        ref = psMemGetRefCounter( mem );
+        ok(ref == 4, "buffer reference count was %d.", ref );
+        skip_start ( ref != 4, 2, "buffer reference count was %d.", ref );
+
+        psMemDecrRefCounter( mem );
+        psMemDecrRefCounter( mem );
+
+        ref = psMemGetRefCounter( mem );
+        ok(ref == 2, "Found buffer reference count to be %d.", ref );
+        skip_start ( ref != 2, 1, "Found buffer reference count to be %d.", ref );
+
+        psMemDecrRefCounter( mem );
+        ref = psMemGetRefCounter( mem );
+        ok(ref == 1, "Found buffer reference count to be %d.", ref );
+        skip_end();
+        skip_end();
+        skip_end();
+        psFree(mem);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Upon requesting more memory than is available, psalloc shall call
+    // the psMemExhaustedCallback.
+    // XXXX: Skipping TPOutOfMemory() because of test abort failure
+    if (0) {
+        psMemId id = psMemGetId();
+        psS32 *mem[ 100 ];
+        psMemExhaustedCallback cb;
+        for ( psS32 lcv = 0; lcv < 100; lcv++ ) {
+            mem[ lcv ] = NULL;
+        }
+        exhaustedCallbackCalled = 0;
+        cb = psMemExhaustedCallbackSet( TPOutOfMemoryExhaustedCallback );
+        #ifdef COMMENTED_OUT
+        // Don't include since intentionally aborts
+        for ( psS32 lcv = 0; lcv < 100; lcv++ ) {
+            mem[ lcv ] = ( psS32* ) psAlloc( SIZE_MAX/2 - 1000 );
+        }
+        psMemExhaustedCallbackSet( cb );
+        ok(exhaustedCallbackCalled != 0,
+             "Called psAlloc with HUGE memory requirement and survived!");
+        for ( psS32 lcv = 0; lcv < 100; lcv++ ) {
+            psFree( mem[ lcv ] );
+        }
+        #endif
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // Bug/Task #562 regression test.  Upon requesting more memory than is available,
+    // psRealloc shall call the psMemExhaustedCallback.
+    // XXXX: Skipping TPReallocOutOfMemory() because of test abort failure
+    if (0) {
+        psMemId id = psMemGetId();
+        psS32 *mem[ 100 ];
+        psMemExhaustedCallback cb;
+        for ( psS32 lcv = 0; lcv < 100; lcv++ ) {
+            mem[ lcv ] = NULL;
+        }
+        exhaustedCallbackCalled = 0;
+        cb = psMemExhaustedCallbackSet( TPOutOfMemoryExhaustedCallback );
+        for ( psS32 lcv = 0; lcv < 100; lcv++ ) {
+            mem[ lcv ] = ( psS32* ) psAlloc( 10 );
+        }
+        for ( psS32 lcv = 0; lcv < 100; lcv++ ) {
+            mem[ lcv ] = ( psS32* ) psRealloc( mem[ lcv ], SIZE_MAX/2 - 1000 );
+        }
+        psMemExhaustedCallbackSet( cb );
+        ok(exhaustedCallbackCalled != 0,
+             "Called psRealloc with HUGE memory requirement and survived in %s!", __func__ );
+        for ( psS32 lcv = 0; lcv < 100; lcv++ ) {
+            psFree( mem[ lcv ] );
+        }
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psAlloc shall allocate memory blocks writeable by caller.
+    {
+        psMemId id = psMemGetId();
+        const psS32 size = 100;
+        psS32 *mem = ( psS32* ) psAlloc( size * sizeof( psS32 ) );
+        ok(mem != NULL, "psAlloc returned non-NULL value" );
+        for ( psS32 index = 0;index < size;index++ ) {
+            mem[ index ] = index;
+        }
+        psS32 failed = 0;
+        for ( psS32 index = 0;index < size;index++ ) {
+            if ( mem[ index ] != index ) {
+                failed++;
+            }
+        }
+        ok(failed == 0, "mem legit" );
+        psFree( mem );
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psRealloc shall increase/decrease memory buffer while preserving contents
+    {
+        psMemId id = psMemGetId();
+        const psS32 initialSize = 100;
+        // allocate buffer with known values.
+        psS32 *mem1 = ( psS32* ) psAlloc( initialSize * sizeof( psS32 ) );
+        psS32 *mem2 = ( psS32* ) psAlloc( initialSize * sizeof( psS32 ) );
+        psS32 *mem3 = ( psS32* ) psAlloc( initialSize * sizeof( psS32 ) );
+        for ( psS32 lcv = 0;lcv < initialSize;lcv++ ) {
+            mem1[lcv] = mem2[lcv] = mem3[lcv] = lcv;
+        }
+        psMemCheckCorruption(stderr, false);
+        // realloc to 2x
+        mem1 = ( psS32* ) psRealloc( mem1, 2 * initialSize * sizeof( psS32 ) );
+        mem2 = ( psS32* ) psRealloc( mem2, 2 * initialSize * sizeof( psS32 ) );
+        mem3 = ( psS32* ) psRealloc( mem3, 2 * initialSize * sizeof( psS32 ) );
+        // check values of initial block
+        int error = 0;
+        for ( psS32 i = 0;i < initialSize;i++ ) {
+            if ( mem1[ i ] != i || mem2[ i ] != i || mem3[ i ] != i ) {
+                error = 1;
+                break;
+            }
+        }
+        ok(error==0, "Realloc preserve the contents with expanding buffer");
+        psMemCheckCorruption(stderr, false);
+        // realloc to 1/2 initial value.
+        mem1 = ( psS32* ) psRealloc( mem1, ( initialSize / 2 ) * sizeof( psS32 ) );
+        mem2 = ( psS32* ) psRealloc( mem2, ( initialSize / 2 ) * sizeof( psS32 ) );
+        mem3 = ( psS32* ) psRealloc( mem3, ( initialSize / 2 ) * sizeof( psS32 ) );
+        // check values of initial block
+        error = 0;
+        for ( psS32 i = 0;i < initialSize / 2;i++ ) {
+            if ( mem1[ i ] != i || mem2[ i ] != i || mem3[ i ] != i ) {
+                error = 1;
+                break;
+            }
+        }
+        ok(error==0, "Realloc preserved the contents with shrinking buffer");
+        psFree( mem1 );
+        psFree( mem2 );
+        psFree( mem3 );
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // TPallocCallback()
+    {
+        psMemId id = psMemGetId();
+        psS32 currentId = psMemGetId();
+        const psS32 initialSize = 100;
+        psS32 mark;
+        allocCallbackCalled = 0;
+        freeCallbackCalled = 0;
+        psMemAllocCallbackSet( memAllocCallback );
+        psMemFreeCallbackSet( memFreeCallback );
+        psMemAllocCallbackSetID( currentId + 1 );
+        psMemFreeCallbackSetID( currentId + 1 );
+        // allocate buffer with known values.
+        psS32 *mem1 = ( psS32* ) psAlloc( initialSize * sizeof( psS32 ) );
+        psS32 *mem2 = ( psS32* ) psAlloc( initialSize * sizeof( psS32 ) );
+        psS32 *mem3 = ( psS32* ) psAlloc( initialSize * sizeof( psS32 ) );
+        psFree(mem1);
+        psFree(mem2);
+        psFree(mem3);
+        ok(allocCallbackCalled == 2 && freeCallbackCalled == 2,
+            "alloc/free callbacks called the proper number of times" );
+        allocCallbackCalled = 0;
+        freeCallbackCalled = 0;
+        mark = psMemGetId();
+        mem1 = ( psS32* ) psAlloc( initialSize * sizeof( psS32 ) );
+        psMemAllocCallbackSetID( mark );
+        mem1 = ( psS32* ) psRealloc( mem1, initialSize * 2 * sizeof( psS32 ) );
+        psFree( mem1 );
+        ok(allocCallbackCalled == 2,
+             "realloc callbacks were called the proper number of times" );
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // TPcheckLeaks()
+    // XXXX: Skipping TPcheckLeaks() because of test abort failure
+    if (0) {
+        const psS32 numBuffers = 5;
+        psS32* buffers[ 5 ];
+        psS32 lcv;
+        psS32 currentId = psMemGetId();
+        psMemBlock** blks;
+        psS32 nLeaks = 0;
+        psS32 lineMark = 0;
+
+        for ( lcv = 0;lcv < numBuffers;lcv++ ) {
+            lineMark = __LINE__ + 1;
+            buffers[ lcv ] = psAlloc( sizeof( psS32 ) );
+        }
+        for ( lcv = 1;lcv < numBuffers;lcv++ ) {
+            psFree( buffers[ lcv ] );
+        }
+        nLeaks = psMemCheckLeaks( currentId, &blks, stderr, false );
+        ok(nLeaks == 1, "psMemCheckLeaks found %d leaks", nLeaks );
+        ok(blks[ 0 ] ->lineno == lineMark,
+             "psMemCheckLeaks found a leak other than the expected one (line %d vs %d)", lineMark, blks[ 0 ] ->lineno );
+        psFree( buffers[ 0 ] );
+        psFree( blks );
+        psMemCheckLeaks(currentId,NULL,stderr, false);
+        for ( lcv = 0;lcv < numBuffers;lcv++ ) {
+            lineMark = __LINE__ + 1;
+            buffers[ lcv ] = psAlloc( sizeof( psS32 ) );
+        }
+        for ( lcv = 0;lcv < numBuffers - 1;lcv++ ) {
+            psFree( buffers[ lcv ] );
+        }
+        nLeaks = psMemCheckLeaks( currentId, &blks, stderr, false );
+        ok(nLeaks == 1, "psMemCheckLeaks found %d leaks.", nLeaks );
+        ok(blks[ 0 ] ->lineno == lineMark, "psMemCheckLeaks found leaks");
+        psFree( buffers[ 4 ] );
+        psFree( blks );
+        for ( lcv = 0;lcv < numBuffers;lcv++ ) {
+            lineMark = __LINE__ + 1;
+            buffers[ lcv ] = psAlloc( sizeof( psS32 ) );
+        }
+        for ( lcv = 0;lcv < numBuffers;lcv++ ) {
+            if ( lcv % 2 == 0 ) {
+                psFree( buffers[ lcv ] );
+            }
+        }
+        nLeaks = psMemCheckLeaks( currentId, &blks, stderr, false );
+        ok(nLeaks == 2, "psMemCheckLeaks found %d leaks.", nLeaks);
+        ok(blks[ 0 ] ->lineno == lineMark,
+             "psMemCheckLeaks found a leak other than the expected." );
+        psFree(blks);
+        psFree(buffers[1]);
+        psFree(buffers[3]);
+    }
+
+
+    void TPmultipleFree( void );
+    // XXXX: Skipping TPmultipleFree() because of test abort failure
+    if (0) {
+        TPmultipleFree();
+    }
+
+    // memCheckTypes()
+    if (1) {
+        psMemId id = psMemGetId();
+        psArray *negative = psArrayAlloc(2);
+        psMetadata *neg = psMetadataAlloc();
+
+        psArray *array = psArrayAlloc(100);
+        int okay = psMemCheckType(PS_DATA_ARRAY,array);
+        if (!okay) {
+            psFree(array);
+        }
+        ok(okay, "psMemCheckArray in memCheckType");
+
+        ok(!psMemCheckType(PS_DATA_ARRAY, neg), "psMemCheckType with metadata input");
+        psFree(array);
+
+        psBitSet *bits;
+        bits = psBitSetAlloc(100);
+        okay = psMemCheckType(PS_DATA_BITSET, bits);
+        if (!okay )
+            psFree(bits);
+        ok(okay, "psMemCheckBitSet in memCheckType");
+        ok(!psMemCheckType(PS_DATA_BITSET, negative), "psMemCheckType on psArray");
+        psFree(bits);
+
+        psCube *cube;
+        cube = psCubeAlloc();
+        okay = psMemCheckType(PS_DATA_CUBE, cube);
+        if (!okay )
+            psFree(cube);
+        ok(okay, "psMemCheckCube in memCheckType");
+        psFree(cube);
+
+        psFits *fits;
+        fits = psFitsOpen("test.fits","w");
+        psImage* img = psImageAlloc(16,16,PS_TYPE_F32);
+        psFitsWriteImage(fits,NULL,img,1,NULL);
+        psFree(img);
+        okay = psMemCheckType(PS_DATA_FITS, fits);
+        if (!okay )
+            psFree(fits);
+        ok(okay, "psMemCheckFits in memCheckType");
+        psFitsClose(fits);
+
+        psHash *hash;
+        hash = psHashAlloc(100);
+        okay = psMemCheckType(PS_DATA_HASH, hash);
+        if (!okay )
+            psFree(hash);
+        ok(okay, "psMemCheckHash in memCheckType");
+        psFree(hash);
+
+        psHistogram *histogram;
+        histogram = psHistogramAlloc(1.1, 2.2, 2);
+        okay = psMemCheckType(PS_DATA_HISTOGRAM, histogram);
+        if (!okay )
+            psFree(histogram);
+        ok(okay, "psMemCheckHistogram in memCheckType");
+        psFree(histogram);
+
+        psImage *image;
+        image = psImageAlloc(5, 5, PS_TYPE_F32);
+        okay = psMemCheckType(PS_DATA_IMAGE, image);
+        if (!okay )
+            psFree(image);
+        ok(okay, "psMemCheckImage in memCheckType");
+        psFree(image);
+
+        psKernel *kernel;
+        kernel = psKernelAlloc(0, 1, 0, 1);
+        okay = psMemCheckType(PS_DATA_KERNEL, kernel);
+        if (!okay )
+            psFree(kernel);
+        ok(okay, "psMemCheckKernel in memCheckType");
+        psFree(kernel);
+
+        psList *list;
+        list = psListAlloc(NULL);
+        okay = psMemCheckType(PS_DATA_LIST, list);
+        if (!okay )
+            psFree(list);
+        ok(okay, "psMemCheckList in memCheckType");
+        psFree(list);
+
+        psLookupTable *lookup;
+        char *file = "tableF32.dat";
+        char *format = "\%f \%lf \%d \%ld";
+        lookup = psLookupTableAlloc(file, format, 10);
+        okay = psMemCheckType(PS_DATA_LOOKUPTABLE, lookup);
+        if (!okay )
+            psFree(lookup);
+        ok(okay, "psMemCheckLookupTable in memCheckType");
+        psFree(lookup);
+
+        psMetadata *metadata;
+        metadata = psMetadataAlloc();
+        okay = psMemCheckType(PS_DATA_METADATA, metadata);
+        if (!okay )
+            psFree(metadata);
+        ok(okay, "psMemCheckMetadata in memCheckType");
+        psFree(metadata);
+
+        psMetadataItem *metaItem;
+        metaItem = psMetadataItemAlloc("name", PS_DATA_S32, "COMMENT", 1);
+        okay = psMemCheckType(PS_DATA_METADATAITEM, metaItem);
+        if (!okay )
+            psFree(metaItem);
+        ok(okay, "psMemCheckMetadataItem in memCheckType");
+        psFree(metaItem);
+
+        psMinimization *min;
+        min = psMinimizationAlloc(3, 0.1);
+        okay = psMemCheckType(PS_DATA_MINIMIZATION, min);
+        if (!okay )
+            psFree(min);
+        ok(okay, "psMemCheckMinimization in memCheckType");
+        psFree(min);
+
+        psPixels *pixels;
+        pixels = psPixelsAlloc(100);
+        okay = psMemCheckType(PS_DATA_PIXELS, pixels);
+        if (!okay )
+            psFree(pixels);
+        ok(okay, "psMemCheckPixels in memCheckType");
+        psFree(pixels);
+
+        psPlane *plane;
+        plane = psPlaneAlloc();
+        okay = psMemCheckType(PS_DATA_PLANE, plane);
+        if (!okay )
+            psFree(plane);
+        ok(okay, "psMemCheckPlane in memCheckType.");
+        psFree(plane);
+
+        psPlaneDistort *planeDistort;
+        planeDistort = psPlaneDistortAlloc(1, 1, 1, 1);
+        okay =  psMemCheckType(PS_DATA_PLANEDISTORT, planeDistort);
+        if (!okay )
+            psFree(planeDistort);
+        ok(okay, "psMemCheckPlaneDistort in memCheckType.");
+        psFree(planeDistort);
+
+        psPlaneTransform *planeTransform;
+        planeTransform = psPlaneTransformAlloc(1, 1);
+        okay = psMemCheckType(PS_DATA_PLANETRANSFORM, planeTransform);
+        if (!okay )
+            psFree(planeTransform);
+        ok(okay, "psMemCheckPlaneTransform in memCheckType");
+        psFree(planeTransform);
+    
+        psPolynomial1D *poly1;
+        poly1 = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 2);
+        okay = psMemCheckType(PS_DATA_POLYNOMIAL1D, poly1);
+        if (!okay )
+            psFree(poly1);
+        ok(okay, "psMemCheckPolynomial1D in memCheckType");
+        psFree(poly1);
+    
+        psPolynomial2D *poly2;
+        poly2 = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 2, 1);
+        okay = psMemCheckType(PS_DATA_POLYNOMIAL2D, poly2);
+        if (!okay )
+            psFree(poly2);
+        ok(okay, "psMemCheckPolynomial2D in memCheckType");
+        psFree(poly2);
+    
+        psPolynomial3D *poly3;
+        poly3 = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, 2, 1, 1);
+        okay = psMemCheckType(PS_DATA_POLYNOMIAL3D, poly3);
+        if (!okay )
+            psFree(poly3);
+        ok(okay, "psMemCheckPolynomial3D in memCheckType");
+        psFree(poly3);
+    
+        psPolynomial4D *poly4;
+        poly4 = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, 2, 1, 2, 1);
+        okay = psMemCheckType(PS_DATA_POLYNOMIAL4D, poly4);
+        if (!okay )
+            psFree(poly4);
+        ok(okay, "psMemCheckPolynomial4D in memCheckType");
+        psFree(poly4);
+    
+        psProjection *proj;
+        proj = psProjectionAlloc(1, 1, 2.1, 2.1, PS_PROJ_TAN);
+        okay = psMemCheckType(PS_DATA_PROJECTION, proj);
+        if (!okay )
+            psFree(proj);
+        ok(okay, "psMemCheckProjection in memCheckType.");
+        psFree(proj);
+    
+        psScalar *scalar;
+        psF64 f64 = 1.1;
+        scalar = psScalarAlloc(f64, PS_TYPE_F64);
+        okay = psMemCheckType(PS_DATA_SCALAR, scalar);
+        if (!okay )
+            psFree(scalar);
+        ok(okay, "psMemCheckScalar in memCheckType");
+        psFree(scalar);
+    
+        psSphere *sphere;
+        sphere = psSphereAlloc();
+        okay = psMemCheckType(PS_DATA_SPHERE, sphere);
+        if (!okay )
+            psFree(sphere);
+        ok(okay, "psMemCheckSphere in memCheckType");
+        psFree(sphere);
+    
+        psSphereRot *sphereRot;
+        sphereRot = psSphereRotAlloc(0, 0, 20);
+        okay = psMemCheckType(PS_DATA_SPHEREROT, sphereRot);
+        if (!okay )
+            psFree(sphereRot);
+        ok(okay, "psMemCheckSphereRot in memCheckType");
+        psFree(sphereRot);
+    
+        psSpline1D *spline;
+        spline = psSpline1DAlloc(2, 1, 0, 2);
+        okay = psMemCheckType(PS_DATA_SPLINE1D, spline);
+        if (!okay )
+            psFree(spline);
+        ok(okay, "psMemCheckSpline1D in memCheckType");
+        psFree(spline);
+    
+        psStats *stats;
+        stats = psStatsAlloc(PS_STAT_MAX);
+        okay = psMemCheckType(PS_DATA_STATS, stats);
+        if (!okay )
+            psFree(stats);
+        ok(okay, "psMemCheckStats in memCheckType");
+        psFree(stats);
+    
+        psTime *time;
+        time = psTimeAlloc(PS_TIME_UT1);
+        okay = psMemCheckType(PS_DATA_TIME, time);
+        if (!okay )
+            psFree(time);
+        ok(okay, "psMemCheckTime in memCheckType");
+        psFree(time);
+    
+        psVector *vector;
+        vector = psVectorAlloc(100, PS_TYPE_F32);
+        okay = psMemCheckType(PS_DATA_VECTOR, vector);
+        ok(okay, "psMemCheckVector in memCheckType");
+        psFree(vector);
+        psFree(negative);
+        psFree(neg);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
+
+#if 0
+void TPmemCorruption( void )
+{
+    diag("TPmemCorruption");
+
+    psS32 * buffer = NULL;
+    psS32 oldValue = 0;
+    psS32 corruptions = 0;
+    psMemProblemCallback cb;
+
+    buffer = psAlloc( sizeof( psS32 ) );
+
+    // cause memory corruption via buffer underflow
+    *buffer = 1;
+    buffer--;
+    oldValue = *buffer;
+    *buffer = 2;
+
+    problemCallbackCalled = 0;
+    cb = psMemProblemCallbackSet( memProblemCallback );
+
+    corruptions = psMemCheckCorruption( 0 );
+
+    // restore the memory problem callback
+    psMemProblemCallbackSet( cb );
+
+    // restore the value, 'uncorrupting' the buffer
+    *buffer = oldValue;
+    buffer++;
+
+    psFree( buffer );
+
+    ok(corruptions == 1,
+         "Expected one memory corruption but found %d", corruptions );
+    ok(problemCallbackCalled == 1, "The memProblemCallback was invoked" );
+}
+#endif
+
+
+void memProblemCallback( psMemBlock *ptr, const char *file, unsigned int lineno )
+{
+    problemCallbackCalled++;
+}
+
+
+psMemId memAllocCallback( const psMemBlock *ptr )
+{
+    allocCallbackCalled++;
+    return 1;
+}
+
+psMemId memFreeCallback( const psMemBlock *ptr )
+{
+    freeCallbackCalled++;
+    return 1;
+}
+
+psPtr TPOutOfMemoryExhaustedCallback( size_t size )
+{
+    exhaustedCallbackCalled++;
+    return NULL;
+}
+
+void TPmultipleFree( void )
+{
+    psPtr buffer = psAlloc( 1024 );
+    psPtr buffer2 = buffer;
+
+    psFree( buffer );
+    psFree( buffer2 );
+}
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psString.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psString.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psString.c	(revision 22158)
@@ -0,0 +1,463 @@
+/** @file  tst_psString.c
+ *
+ * -*- mode: C; c-basic-indent: 4; tab-width: 8; indent-tabs-mode: nil -*-
+ * vim: set cindent ts=8 sw=4 expandtab:
+ *
+ *  @brief Test driver for psString functions
+ *
+ *  This test driver contains the following test points for psStringCopy
+ *  and psStringNCopy, and related string functions.
+ *    1) Verify string copy - psStringCopy
+ *    2) Verify empty string copy - psStringCopy
+ *    3) Verify string copy with length - psStringNCopy
+ *    4) Verify empty string copy with length - psStringNCopy
+ *    5) Copy string to larger string - psStringNCopy
+ *    6) Copy string with negative size - psStringNCopy
+ *    7) Verifiy creation of string literal - PS_STRING
+ *
+ *  Return:   Number of test points which failed
+ *
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.11 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2008-05-05 00:09:04 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <string.h>
+#include "pslib.h"
+#include "tap.h"
+#include "pstap.h"
+
+#define STR_0 "binky had a leeeetle lamb"
+
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(65);
+
+
+    //testStringCopy00()
+    {
+        psMemId id = psMemGetId();
+        char  stringval[20] = "E R R O R";
+        psS32   result = 0;
+        psS32   result1 = 0;
+        char  *strResult;
+
+        // Test point #1 Verify string copy - psStringCopy
+        strResult = psStringCopy(stringval);
+        // Perform string compare
+        result = strcmp(strResult, stringval);
+        // Modify original string
+        stringval[0]='G';
+        result1 = strcmp(strResult, stringval);
+        stringval[0]='E';
+        ok(( result == 0 ) && ( result1 != 0),
+             "Failed test point #1 strcmp result = %d expected 0",result);
+        // Free memory allocated
+        psFree(strResult);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testStringCopy01()
+    {
+        psMemId id = psMemGetId();
+        char  *emptyval = "";
+        psS32   result = 0;
+        char  *strResult;
+
+        // Test point #2 Verify empty string copy - psStringCopy
+        strResult = psStringCopy(emptyval);
+        // Perform string compare
+        result = strcmp(strResult, emptyval);
+        ok(result == 0,
+             "test point #2 strcmp result = %d expected 0",result);
+        // Free memory allocated
+        psFree(strResult);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testStringCopy02()
+    {
+        psMemId id = psMemGetId();
+        psS32   result = 0;
+        psS32   result1 = 0;
+        char  *strResult;
+        char  stringval1[20] = "e r r o r";
+        psS32   substringlen = 5;
+        char  *substringval = "e r r";
+
+        // Test point #3 Verify string copy with length - psStringNCopy
+        strResult = psStringNCopy(stringval1, substringlen);
+        // Perform string compare and get string length
+        result = strncmp(strResult, substringval, substringlen);
+        // Change original string
+        stringval1[0] = 'g';
+        result1 = strncmp(strResult, substringval, substringlen);
+        ok(( result == 0 ) && ( result1 == 0 ),
+             "Failed test point #3 strcmp result = %d expected 0",result);
+        psFree(strResult);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testStringCopy03()
+    {
+        psMemId id = psMemGetId();
+        psS32   result = 0;
+        psS32   result1 = 0;
+        char  *strResult;
+        char  *stringvalnocopy = "F A I L";
+
+        // Test point #4 Verify empty string copy with length - psStringNCopy
+        strResult = psStringNCopy(stringvalnocopy, 0);
+        // Perform string compare and get sting length
+        result = strcmp(strResult, stringvalnocopy);
+        result1 = strlen(strResult);
+        ok(result != 0,
+             "test point #4 strcmp result = %d didn't expected %d",result,0);
+        psFree(strResult);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testStringCopy04()
+    {
+        psMemId id = psMemGetId();
+        psS32   result = 0;
+        psS32   result1 = 0;
+        char  *strResult;
+        char  stringval[20] = "E R R O R";
+        psS32   increaseSize = 5;
+
+        // Test point #5 Copy string to larger string - psStringNCopy
+        strResult = psStringNCopy(stringval, (strlen(stringval) + increaseSize));
+        // Perform string compare and get string length
+        result = strcmp(strResult, stringval);
+        result1 = strlen(strResult);
+        // The strings should still compare
+        ok(result == 0 && result1 == strlen(stringval),
+             "test point #5 strcmp result = %d expected %d",result,0);
+        psFree(strResult);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+// XXX This test needs to be modified to check for maximum size
+//     This will require a mod to psStringNCopy source to check for maximum size
+//
+//psS32 testStringCopy05()
+//{
+//    char  *strResult;
+//    char  stringval[20] = "E R R O R";
+//    psS32   negativeSize = -5;
+//
+//    // Test point #6 Copy string with negative size - psStringNCopy
+//    strResult = psStringNCopy(stringval, negativeSize);
+//    if ( strResult != NULL ) {
+//        fprintf(stderr,"Failed test point #6 return value = %p expected NULL\n",
+//                strResult);
+//        return 1;
+//    }
+//    // Memory should not have been allocated
+//
+//    return 0;
+//}
+
+
+    // testStringCopy06()
+    {
+        psMemId id = psMemGetId();
+        char  *strResult;
+        char  stringval[20] = "E R R O R";
+        psS32   result = 0;
+
+        // Test point #7 Verify creation of string literal - PS_STRING
+        strResult = PS_STRING(E R R O R);
+        result = strcmp(strResult, stringval);
+        ok(result == 0,
+             "test point #7 strcmp result = %d expected %d",result,0);
+        // Memory should not have been allocated
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testStrAppend00()
+    {
+        psMemId id = psMemGetId();
+        char *str = psStringCopy("3.14159");
+        psStringAppend(&str, "%d%s", 2653589, "79323846");
+        // Test point: Verify string append
+        int result = strcmp(str, "3.14159265358979323846");
+        ok(result == 0, "Failed test point");
+        psFree(str);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+#if 0
+    // testStrAppend01()
+    {
+        psMemId id = psMemGetId();
+        char *str=NULL;
+        // test nonsensical invocations ...
+        ssize_t sz = psStringAppend(NULL, NULL);
+        ok(sz == 0, "Failed test point");
+        sz = psStringAppend(&str, NULL);
+        ok(sz == 0, "Failed test point");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+#endif
+
+    // testStrAppend02()
+    {
+        psMemId id = psMemGetId();
+        char *str=NULL;
+        // test string creation
+        psStringAppend(&str, "%s", "fubar");
+        int result = strcmp(str, "fubar");
+        ok(result == 0, "Failed test point");
+        psFree(str);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testStrAppend03()
+    {
+        psMemId id = psMemGetId();
+        char *str =psStringCopy(STR_0);
+        // test null-op
+        psStringAppend(&str, "%s", "");
+        is_str(str, STR_0, "Failed test point");
+        psFree(str);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testStrPrepend00()
+    {
+        psMemId id = psMemGetId();
+        char *str = psStringCopy("79323846");
+        psStringPrepend(&str, "%s%d","3.14159", 2653589 );
+        // Test point: Verify string append
+        int result = strcmp(str, "3.14159265358979323846");
+        ok(result == 0, "Failed test point");
+        psFree(str);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+#if 0
+    // testStrPrepend01()
+    {
+        psMemId id = psMemGetId();
+        char *str=NULL;
+        // test nonsensical invocations ...
+        ssize_t sz = psStringPrepend(NULL, NULL);
+        ok(sz == 0, "Failed test point");
+        sz = psStringPrepend(&str, NULL);
+        ok(sz == 0, "Failed test point");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+#endif
+
+    // testStrPrepend02()
+    {
+        psMemId id = psMemGetId();
+        char *str=NULL;
+        // test string creation
+        psStringPrepend(&str, "%s", "fubar");
+        int result = strcmp(str, "fubar");
+        ok(result == 0, "Failed test point");
+        psFree(str);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testStrPrepend03()
+    {
+        // test null-op
+        psMemId id = psMemGetId();
+        char *str =  psStringCopy(STR_0);
+        psStringPrepend(&str, "%s", "");
+        int result = strcmp(str, STR_0);
+        ok(result == 0, "test point str=[%s]", str);
+        psFree(str);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testStrSplit00()
+    {
+        psMemId id = psMemGetId();
+        psList *strList = NULL;
+        char str[35];
+        char split[5];
+        strncpy(str, "This is, a, test case, to check", 35);
+        strncpy(split, ",", 2);
+        psString psStr;
+        psString psSplit;
+        psStr = psStringCopy(str);
+        psSplit = psStringCopy(split);
+
+        //Return NULL for NULL inputs
+        strList = psStringSplit(NULL, NULL, true);
+        ok(!strList, "psStringSplit" );
+        psFree(strList);
+
+        strList = NULL;
+        //Return empty list for NULL string input
+        strList = psStringSplit(NULL, split, true);
+        ok(!psListLength(strList), "psListLength()" );
+        psFree(strList);
+
+        strList = NULL;
+        //Return NULL for NULL splitter input
+        strList = psStringSplit(str, NULL, true);
+        ok(!strList, "psStringSplit" );
+        psFree(strList);
+
+        strList = NULL;
+        //Return a psList* of psStrings
+        strList = psStringSplit(str, split, true);
+        ok(strList->n == 4,
+            "psStringSplit to return the correct number of strings");
+        ok(!strncmp((psString)(strList->head->data), "This is", 10),
+             "psStringSplit to return expected strings");
+        ok(!strncmp((psString)(strList->head->next->data), " a", 10),
+             "psStringSplit to return expected strings");
+        ok(!strncmp((psString)(strList->head->next->next->data), " test case",10),
+             "psStringSplit to return expected strings");
+        ok(!strncmp((psString)(strList->head->next->next->next->data), " to check", 10),
+             "psStringSplit failed to return expected strings");
+
+        psFree(strList);
+        //Return correct psList when using (psString, char*)
+        strList = psStringSplit(psStr, split, true);
+        ok(strList->n == 4,
+            "psStringSplit to return the correct number of strings");
+        ok(!strncmp((psString)(strList->head->data), "This is", 10),
+             "psStringSplit to return expected strings");
+        ok(!strncmp((psString)(strList->head->next->data), " a", 10),
+             "psStringSplit failed to return expected strings");
+        ok(!strncmp((psString)(strList->head->next->next->data), " test case",10),
+             "psStringSplit failed to return expected strings");
+        ok(!strncmp((psString)(strList->head->next->next->next->data), " to check", 10),
+             "psStringSplit to return expected strings");
+
+        psFree(strList);
+        //Return correct psList when using (char*, psString)
+        strList = psStringSplit(str, psSplit, true);
+        ok(strList->n == 4,
+            "psStringSplit to return the correct number of strings");
+        ok(!strncmp((psString)(strList->head->data), "This is", 10),
+             "psStringSplit to return expected strings");
+        ok(!strncmp((psString)(strList->head->next->data), " a", 10),
+             "psStringSplit to return expected strings");
+        ok(!strncmp((psString)(strList->head->next->next->data), " test case",10),
+             "psStringSplit to return expected strings");
+        ok(!strncmp((psString)(strList->head->next->next->next->data), " to check", 10),
+             "psStringSplit to return expected strings");
+
+        psFree(strList);
+        //Return correct psList when using (psString, psString)
+        strList = psStringSplit(psStr, psSplit, true);
+        ok(strList->n == 4,
+            "psStringSplit to return the correct number of strings");
+        ok(!strncmp((psString)(strList->head->data), "This is", 10),
+             "psStringSplit to return expected strings");
+        ok(!strncmp((psString)(strList->head->next->data), " a", 10),
+             "psStringSplit to return expected strings");
+        ok(!strncmp((psString)(strList->head->next->next->data), " test case",10),
+             "psStringSplit  to return expected strings");
+        ok(!strncmp((psString)(strList->head->next->next->next->data), " to check", 10),
+             "psStringSplit to return expected strings");
+
+        psFree(strList);
+        //Return correct psList output for string of zero length case
+        strncpy(str, "This is,, a,, test case,, to check", 35);
+        strList = psStringSplit(str, split, false);
+        ok(strList->n == 4,
+            "psStringSplit to return the correct number of strings");
+        ok(!strncmp((psString)(strList->head->data), "This is", 10),
+             "psStringSplit to return expected strings");
+        ok(!strncmp((psString)(strList->head->next->data), " a", 10),
+             "psStringSplit to return expected strings");
+        ok(!strncmp((psString)(strList->head->next->next->data), " test case",10),
+             "psStringSplit to return expected strings");
+        ok(!strncmp((psString)(strList->head->next->next->next->data), " to check", 10),
+             "psStringSplit to return expected strings");
+        psFree(strList);
+        psFree(psStr);
+        psFree(psSplit);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testNULLStrings()
+    {
+        psMemId id = psMemGetId();
+        psString nullTest = NULL;
+        psString output = NULL;
+        ssize_t outSize = 0;
+        char** nullDest = NULL;
+        char** test = NULL;
+        //psStringCopy should return NULL for NULL input string
+        // Following should generate error message
+        output = psStringCopy(nullTest);
+        ok(output == NULL, "psStringCopy to return NULL for NULL input string");
+
+        //psStringNCopy should return NULL for NULL input string
+        output = psStringNCopy(nullTest, 100);
+        ok(output == NULL, "psStringNCopy to return NULL for NULL input string");
+
+        //psStringAppend should return 0 for NULL input destination
+        outSize = psStringAppend(nullDest, "%s", "");
+        ok(outSize == 0, "psStringAppend to return 0 for NULL input destination");
+
+        //psStringAppend should return 0 for NULL input format
+        outSize = psStringAppend(test, nullTest);
+        ok(outSize == 0, "psStringAppend to return 0 for NULL input format");
+
+        //psStringPrepend should return 0 for NULL input destination
+        outSize = psStringPrepend(nullDest, " ");
+        ok(outSize == 0, "psStringPrepend to return 0 for NULL input destination");
+
+        //psStringPrepend should return 0 for NULL input format
+        outSize = psStringPrepend(test, nullTest);
+        ok(outSize == 0, "psStringPrepend to return 0 for NULL input format");
+
+        //psStringSplit should return empty list for NULL input string
+        psList *nullList = NULL;
+        nullList = psStringSplit(nullTest, ",", true);
+        ok(!psListLength(nullList), "psStringSplit to return NULL for NULL input string");
+        psFree(nullList);
+
+        nullList = NULL;
+        //psStringSplit should return NULL for NULL input splitter
+        nullList = psStringSplit("Hello World", nullTest, true);
+        ok(!nullList, "psStringSplit to return NULL for NULL input splitter");
+        psFree(nullList);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testStrCheck()
+    {
+        psMemId id = psMemGetId();
+        psString str = psStringAlloc(10);
+        strcpy(str, "Hello");
+        ok(psMemCheckString(str), "psString allocated!");
+        ok(psMemCheckType(PS_DATA_STRING, str), "psString allocated");
+        psFree(str);
+
+	// XXX EAM this function raises an abort since we are trying to test a non-psLib memory block
+        // char charStr[10];
+        // ok(!psMemCheckType(PS_DATA_STRING, charStr), "Input string is a psDataType");
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psStringSubstitute.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psStringSubstitute.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psStringSubstitute.c	(revision 22158)
@@ -0,0 +1,104 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+#define ORIGINAL "This is, a, test case, to check."
+#define CORRECTED "This is a test case to check."
+
+int main (void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(16);
+
+
+    // Return input for NULL key
+    {
+        psMemId id = psMemGetId();
+        psString input = psStringCopy(ORIGINAL);
+        psStringSubstitute(&input, ",", NULL);
+        ok(input && strcmp(input, ORIGINAL) == 0, "output = %s", input);
+        psFree(input);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return input for empty key
+    {
+        psMemId id = psMemGetId();
+        psString input = psStringCopy(ORIGINAL);
+        psStringSubstitute(&input, "XXX", "");
+        ok(input && strcmp(input, ORIGINAL) == 0, "output = %s", input);
+        psFree(input);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return corrected version for NULL replace
+    {
+        psMemId id = psMemGetId();
+        psString input = psStringCopy(ORIGINAL);
+        psStringSubstitute(&input, NULL, ",");
+        ok(input && strcmp(input, CORRECTED) == 0, "output = %s", input);
+        psFree(input);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return corrected version for empty replace
+    {
+        psMemId id = psMemGetId();
+        psString input = psStringCopy(ORIGINAL);
+        psStringSubstitute(&input, "", ",");
+        ok(input && strcmp(input, CORRECTED) == 0, "output = %s", input);
+        psFree(input);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return NULL for NULL input
+    {
+        psMemId id = psMemGetId();
+        int status = psStringSubstitute(NULL, "XXX", ",");
+        ok(status == 0, "status = %d", status);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return emptry string for empty input
+    {
+        psMemId id = psMemGetId();
+        psString input = psStringCopy("");
+        psStringSubstitute(&input, "XXX", ",");
+        ok(input && strcmp(input, "") == 0, "output = %s", input);
+        psFree(input);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Change commas to bangs
+    {
+        psMemId id = psMemGetId();
+        psString input = psStringCopy(ORIGINAL);
+        psStringSubstitute(&input, "!", ",");
+        ok(input && strcmp(input, "This is! a! test case! to check.") == 0, "output = %s", input);
+        psFree(input);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Long replacement text --- should allocate new space
+    {
+        psMemId id = psMemGetId();
+        psString input = psStringCopy(ORIGINAL);
+        psStringSubstitute(&input, "; This string is too long to fit in input(35 chars)", ".");
+        ok(input && strcmp(input, "This is, a, test case, to check; "
+                           "This string is too long to fit in input(35 chars)") == 0,
+           "output = %s", input);
+        psFree(input);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psTrace.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psTrace.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tap_psTrace.c	(revision 22158)
@@ -0,0 +1,302 @@
+/*****************************************************************************
+    This code will test whether trace levels can be set successfully.
+ 
+    XXX: For the last two testpoints, must verify that the results are
+    correct, and put that verification in the test as well.
+ *****************************************************************************/
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "pslib.h"
+#include "tap.h"
+#include "pstap.h"
+
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(54);
+
+# define DEBUG 1
+# if (DEBUG)
+    FILE *output = fopen ("/dev/null", "w");
+    int outFD = fileno (output);
+# else
+    int outFD = 2;
+# endif
+
+    // testTrace00()
+    {
+        psMemId id = psMemGetId();
+        psS32 lev = 0;
+        (void)psTraceSetDestination(outFD);
+        for (int i=0;i<10;i++) {
+            (void)psTraceSetLevel(".", i);
+            lev = psTraceGetLevel(".");
+            ok(lev == i, "trace level was %d, actual was %d", i, lev);
+        }
+
+        (void)psTraceSetLevel(".", 3);
+        for (int i=5;i<10;i++) {
+            (void)psTraceSetLevel(".NODE00", i);
+            lev = psTraceGetLevel(".NODE00");
+            ok (lev == i,"(.NODE00) expected trace level was %d, actual was %d",
+                i, lev);
+    
+            lev = psTraceGetLevel(".");
+            ok (lev == 3,
+                "expected trace level was %d, actual was %d", i, 3);
+        }
+    
+        (void)psTraceSetLevel(".NODE00.NODE01", 4);
+        for (int i=0;i<10;i++) {
+            (void)psTraceSetLevel(".NODE00.NODE01", i);
+            lev = psTraceGetLevel(".NODE00.NODE01");
+            ok (lev == i,
+                "(.NODE00.NODE01) expected trace level was %d, actual was %d",
+                i, lev);
+        }
+
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testTrace01()
+    {
+        psMemId id = psMemGetId();
+        (void)psTraceSetDestination(outFD);
+        (void)psTraceSetLevel(".A.B.C.D.E", 5);
+        psTrace(".A.C.D.C",1,"You should not see this");
+        psTrace(".A.B.C.D.E",2,"You should see this");
+        psTrace(".A.B.C.D.E.F",3,"You should see this too");
+        psTracePrintLevels();
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testTrace02()
+    {
+        psMemId id = psMemGetId();
+        psTraceReset();
+        (void)psTraceSetDestination(outFD);
+        (void)psTraceSetLevel(".A.B", 2);
+        (void)psTraceSetLevel(".A.B.C.D.E", 5);
+        psTracePrintLevels();
+        (void)psTraceSetLevel(".A.B", 10);
+        psTracePrintLevels();
+
+        ok (10 == psTraceGetLevel(".A.B.C"),
+            ".A.B.C did not dynamically inherit a trace level (%d)",
+            psTraceGetLevel(".A.B.C"));
+
+        ok (10 == psTraceGetLevel(".A.B.C.D"),
+            ".A.B.C.D did not dynamically inherit a trace level (%d)",
+            psTraceGetLevel(".A.B.C.D"));
+
+        ok (5 == psTraceGetLevel(".A.B.C.D.E"),
+            ".A.B.C.D.E did dynamically inherit a trace level (%d)",
+            psTraceGetLevel(".A.B.C.D.E"));
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testTrace03()
+    {
+        psMemId id = psMemGetId();
+        (void)psTraceSetDestination(outFD);
+
+        for (int i=0;i<10;i++) {
+            (void)psTraceSetLevel(".", i);
+            psTraceReset();
+            int lev = psTraceGetLevel(".");
+            ok (lev == PS_UNKNOWN_TRACE_LEVEL,
+                "expected trace level was %d, actual was %d",
+                PS_UNKNOWN_TRACE_LEVEL, lev);
+        }
+
+        (void)psTraceSetLevel(".", 5);
+        (void)psTraceSetLevel(".a", 4);
+        (void)psTraceSetLevel(".a.b", 3);
+        (void)psTraceSetLevel(".a.b.c", 2);
+        ok (!((5 != psTraceGetLevel(".")) ||
+              (4 != psTraceGetLevel(".a")) ||
+              (3 != psTraceGetLevel(".a.b")) ||
+              (2 != psTraceGetLevel(".a.b.c"))),
+            "trace successFlag = false;levels were not settable?");
+
+        psTraceReset();
+        ok (!((PS_UNKNOWN_TRACE_LEVEL != psTraceGetLevel(".")) ||
+              (PS_UNKNOWN_TRACE_LEVEL != psTraceGetLevel(".a")) ||
+              (PS_UNKNOWN_TRACE_LEVEL != psTraceGetLevel(".a.b")) ||
+              (PS_UNKNOWN_TRACE_LEVEL != psTraceGetLevel(".a.b.c"))),
+            "trace levels were not reset properly");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testTrace04()
+    {
+        psMemId id = psMemGetId();
+        int FD = creat("tst_psTrace02_OUT", 0666);
+        for (int nb = 0 ; nb<4;nb++) {
+            if (nb == 0)
+                (void)psTraceSetDestination(((outFD == 2) ? 1 : outFD));
+            if (nb == 1)
+                (void)psTraceSetDestination(((outFD == 2) ? 2 : outFD));
+            if (nb == 2)
+                (void)psTraceSetDestination(((outFD == 2) ? 0 : outFD));
+            if (nb == 3)
+                (void)psTraceSetDestination(FD);
+
+            (void)psTraceSetLevel(".", 4);
+            psTrace(".", 5, "(0) This message should not be displayed (%x)",
+                    0xbeefface);
+            (void)psTraceSetLevel(".", 7);
+            psTrace(".", 5, "(0) This message should be displayed (%x)",
+                    0xbeefface);
+
+            (void)psTraceSetLevel(".a", 4);
+            psTrace(".a", 5, "(1) This message should not be displayed (%x)",
+                    0xbeefface);
+            (void)psTraceSetLevel(".a", 7);
+            psTrace(".a", 5, "(1) This message should be displayed (%x)",
+                    0xbeefface);
+
+            (void)psTraceSetLevel(".a.b", 4);
+            psTrace(".a.b", 5, "(2) This message should not be displayed (%x)",
+                    0xbeefface);
+            (void)psTraceSetLevel(".a.b", 7);
+            psTrace(".a.b", 5, "(2) This message should be displayed (%x)",
+                    0xbeefface);
+            (void)psTraceSetLevel(".a.b.c", 12);
+            psTrace(".a.b.c", 11, "(3) This message should be displayed (%x)",
+                    0xbeefface);
+        }
+        close(FD);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testTrace05()
+    {
+        psMemId id = psMemGetId();
+        (void)psTraceSetDestination(outFD);
+        (void)psTraceSetLevel(".", 9);
+        (void)psTraceSetLevel(".a", 8);
+        (void)psTraceSetLevel(".b", 7);
+        (void)psTraceSetLevel(".c", 5);
+        (void)psTraceSetLevel(".a.a", 4);
+        (void)psTraceSetLevel(".a.b", 3);
+        (void)psTraceSetLevel(".b.a", 2);
+        (void)psTraceSetLevel(".b.b", 1);
+        (void)psTraceSetLevel(".c.a", 0);
+        (void)psTraceSetLevel(".c.b", 3);
+        (void)psTraceSetLevel(".c.c", 5);
+        psTracePrintLevels();
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testTrace05a()
+    {
+        psMemId id = psMemGetId();
+        (void)psTraceSetLevel(".", 9);
+        (void)psTraceSetLevel("a", 8);
+        (void)psTraceSetLevel("b", 7);
+        (void)psTraceSetLevel("c", 5);
+        (void)psTraceSetLevel("a.a", 4);
+        (void)psTraceSetLevel("a.b", 3);
+        (void)psTraceSetLevel("b.a", 2);
+        (void)psTraceSetLevel("b.b", 1);
+        (void)psTraceSetLevel("c.a", 0);
+        (void)psTraceSetLevel("c.b", 3);
+        (void)psTraceSetLevel("c.c", 5);
+        psTracePrintLevels();
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testTrace06()
+    {
+        psMemId id = psMemGetId();
+        (void)psTraceSetDestination(outFD);
+        (void)psTraceSetLevel(".", 9);
+        (void)psTraceSetLevel(".a", 8);
+        (void)psTraceSetLevel(".b", 7);
+        (void)psTraceSetLevel(".c", 5);
+        (void)psTraceSetLevel(".a.a", 4);
+        (void)psTraceSetLevel(".a.b", 3);
+        (void)psTraceSetLevel(".b.a", 2);
+        (void)psTraceSetLevel(".b.b", 1);
+        (void)psTraceSetLevel(".c.a", 0);
+        (void)psTraceSetLevel(".c.b", 3);
+        (void)psTraceSetLevel(".c.c", 5);
+        psTraceReset();
+
+        if ((psTraceGetLevel(".")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".a")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".b")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".c")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".a.a")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".a.b")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".b.a")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".b.b")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".c.a")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".c.b")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".c.c")!=PS_UNKNOWN_TRACE_LEVEL)) {
+            return 1;
+        }
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Ensure that the leading dot in the component names are optional.
+    // testTrace08()
+    {
+        psMemId id = psMemGetId();
+        psTraceReset();
+        (void)psTraceSetLevel(".", 9);
+        (void)psTraceSetLevel(".a", 8);
+        (void)psTraceSetLevel(".b", 7);
+        (void)psTraceSetLevel(".c", 5);
+        (void)psTraceSetLevel(".a.a", 4);
+        (void)psTraceSetLevel(".a.b", 3);
+        (void)psTraceSetLevel(".b.a", 2);
+        (void)psTraceSetLevel(".b.b", 1);
+        (void)psTraceSetLevel(".c.a", 0);
+        (void)psTraceSetLevel(".c.b", 3);
+        (void)psTraceSetLevel(".c.c", 5);
+        psTracePrintLevels();
+        if ((psTraceGetLevel(".")!=9) ||
+            (psTraceGetLevel("a")!=8) ||
+            (psTraceGetLevel("b")!=7) ||
+            (psTraceGetLevel("c")!=5) ||
+            (psTraceGetLevel("a.a")!=4) ||
+            (psTraceGetLevel("a.b")!=3) ||
+            (psTraceGetLevel("b.a")!=2) ||
+            (psTraceGetLevel("b.b")!=1) ||
+            (psTraceGetLevel("c.a")!=0) ||
+            (psTraceGetLevel("c.b")!=3) ||
+            (psTraceGetLevel("c.c")!=5)) {
+            printf("psTraceGetLevel(.) is %d", psTraceGetLevel("."));
+            printf("psTraceGetLevel(a) is %d", psTraceGetLevel("a"));
+            printf("psTraceGetLevel(b) is %d", psTraceGetLevel("b"));
+            printf("psTraceGetLevel(c) is %d", psTraceGetLevel("c"));
+            printf("psTraceGetLevel(a.a) is %d", psTraceGetLevel("a.a"));
+            printf("psTraceGetLevel(a.b) is %d", psTraceGetLevel("a.b"));
+            printf("psTraceGetLevel(b.a) is %d", psTraceGetLevel("b.a"));
+            printf("psTraceGetLevel(b.b) is %d", psTraceGetLevel("b.b"));
+            printf("psTraceGetLevel(c.a) is %d", psTraceGetLevel("c.a"));
+            printf("psTraceGetLevel(c.b) is %d", psTraceGetLevel("c.b"));
+            printf("psTraceGetLevel(c.c) is %d", psTraceGetLevel("c.c"));
+            return 1;
+        }
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+# if (DEBUG)
+    close (outFD);
+# endif
+
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psAbort.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psAbort.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psAbort.c	(revision 22158)
@@ -0,0 +1,76 @@
+/** @file  atst_psAbort_01.c
+ *
+ *  @brief Test driver for psAbort function
+ *
+ *  This test drivers contains the following test points for psAbort
+ *     1) Multiple type values in abort message
+ *
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.1 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2005-07-13 02:47:01 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+static psS32 testAbort00(void);
+static psS32 testAbort01(void);
+static psS32 testAbort02(void);
+
+testDescription tests[] = {
+                              {testAbort00, 0, "Multiple type values in abort message", -6, false},
+                              {testAbort01, 1, "String values in abort message", -6, false},
+                              {testAbort02, 2, "Empty strings in abort message", -6, false},
+                              {NULL}
+                          };
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetLevel( PS_LOG_INFO );
+
+    return ( ! runTestSuite( stderr, "psAbort", tests, argc, argv ) );
+}
+
+static psS32 testAbort00(void)
+{
+    psS32   intval = 1;
+    psS64  longval = 2;
+    float floatval = 3.01;
+    char  charval = 'E';
+    char  *stringval = "E R R O R";
+
+    // Test point #1 Multiple type values placed in the error string
+    psAbort(__func__,
+            "ALL TYPES intval = %d longval = %lld floatval = %f charval = %c strval = %s",
+            intval, longval, floatval, charval, stringval );
+
+    // Program execution should have ended before this statement but if it
+    // does not return a zero since the expected return value of this test
+    // is a non-zero value
+    return 0;
+}
+
+static psS32 testAbort01(void)
+{
+    // Test point #2 String values in abort message
+    psAbort(PS_STRING(__LINE__), "NO_VALUES");
+
+    // Program execution should have ended before this statement but if it
+    // does not return a zero since the expected return value of this test
+    // is a non-zero value
+    return 0;
+}
+
+static psS32 testAbort02(void)
+{
+    // Test point #2 String values in abort message
+    psAbort("","");
+
+    // Program execution should have ended before this statement but if it
+    // does not return a zero since the expected return value of this test
+    // is a non-zero value
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psConfigure.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psConfigure.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psConfigure.c	(revision 22158)
@@ -0,0 +1,52 @@
+/** @file  tst_psConfigure.c
+ *
+ *  @brief Test driver for psconfigure functions
+ *
+ *  This test driver contains the following test points for psConfigure
+ *  functions.
+ *    1) Return current psLib version
+ *
+ *  Return:   Number of test points which failed
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.1 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2005-07-13 02:47:01 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+
+static psS32 psLibVersion00(void);
+
+
+testDescription tests[] = {
+                              {psLibVersion00, 0, "Return current psLib version", 0, false},
+                              {NULL}
+                          };
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    return(!runTestSuite( stderr, "psConfigure", tests, argc, argv));
+}
+
+
+static psS32 psLibVersion00(void)
+{
+    char *stringVal = NULL;
+
+    stringVal = psLibVersion();
+    psLogMsg(__func__,PS_LOG_INFO,"Current psLib version is: %s", stringVal);
+    psFree(stringVal);
+
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psError.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psError.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psError.c	(revision 22158)
@@ -0,0 +1,394 @@
+/** @file  tst_psError.c
+ *
+ *  @brief Test driver for psError function
+ *
+ *  This test driver contains the following test points for psError
+ *     testError00 - psError()                          (Testpoint #486)
+ *     testError01 - psErrorMsg(), psErrorStackPrint()  (Testpoint #725)
+ *     testError02 - psErrorStackPrintV()               (Testpoint #726)
+ *     testError03 - psErrorGet(), psErrorLast()        (Testpoint #727)
+ *     testError04 - psErrorClear()                     (Testpoint #728)
+ *     testError05 - psErrorCodeString()                (Testpoint #729)
+ *
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2007-02-27 23:56:12 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+
+static psS32 testError00(void);
+static psS32 testError01(void);
+static psS32 testError02(void);
+static psS32 testError03(void);
+static psS32 testError04(void);
+static psS32 testError05(void);
+static psS32 testErrorRegister(void);
+
+// Function used in testError02 to verify the psErrorStackPrintV function
+static void myErrorStackPrint(FILE *fd,
+                              const char *fmt,
+                              ...)
+{
+    va_list ap;
+
+    // Test whether psErrorStackPrintV() accept a va_list for output variables
+    va_start(ap, fmt);
+    psErrorStackPrintV(fd, fmt, ap);
+    va_end(ap);
+}
+
+testDescription tests[] = {
+                              {testError00, 486, "psError()", 0, false},
+                              {testError01, 725, "psErrorMsg(),psErrorStackPrint()", 0, false},
+                              {testError02, 726, "psErrorStackPrintV()", 0, false},
+                              {testError03, 727, "psErrorGet(),psErrorLast()", 0, false},
+                              {testError04, 728, "psErrorClear()", 0, false},
+                              {testError05, 729, "psErrorCodeString()", 0, false},
+                              {testErrorRegister, 751, "psErrorRegister()", 0, false},
+                              {NULL}
+                          };
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetLevel( PS_LOG_INFO );
+
+//    return ( !runTestSuite(stderr, "psError", tests, argc, argv) );
+    testError03();
+}
+
+static psS32 testError05(void)
+{
+    psErrorCode code = PS_ERR_BAD_PARAMETER_VALUE;
+
+    // Verify the return value of psErrorCodeString
+    psLogMsg("tst_psError05", PS_LOG_INFO, psErrorCodeString(code));
+
+    // Verify the return value of psErrorCodeString if code is negative
+    if( psErrorCodeString(-1) != NULL) {
+        psLogMsg("tst_psError05", PS_LOG_INFO, "Failed error string with neg. code");
+        return 40;
+    }
+
+    return 0;
+}
+
+static psS32 testError04(void)
+{
+    psErrorCode code = PS_ERR_BAD_PARAMETER_VALUE;
+    psErr *last = NULL;
+    psErr *lastAfterClear = NULL;
+
+    // With an attemp error stack call psErrorClear
+    psErrorClear();
+
+    // Get the last error message and verify PS_ERR_NONE (empty stack)
+    lastAfterClear = psErrorLast();
+    if(lastAfterClear->code != PS_ERR_NONE) {
+        psLogMsg("tst_psError05", PS_LOG_ERROR, "psErrorLast did not return expected.");
+        return 30;
+    }
+    psFree(lastAfterClear);
+
+    // Generate three error messages to have messages on error stack
+    if (psError(code, true, "Error code = %d", code) !=  code) {
+        psLogMsg("tst_psError04", PS_LOG_ERROR, "Failed return value verify.");
+        return 31;
+    }
+    if (psError((code+1), false, "Error code = %d", (code+1)) != (code+1)) {
+        psLogMsg("tst_psError04", PS_LOG_ERROR, "Failed return value verify.");
+        return 32;
+    }
+    if (psError((code+2), false, "Error code = %d", (code+2)) != (code+2)) {
+        psLogMsg("tst_psError04", PS_LOG_ERROR, "Failed return value verify.");
+        return 33;
+    }
+
+    // Get the last error message and verify it has the expected code
+    last = psErrorLast();
+    if(last->code != (code+2)) {
+        psLogMsg("tst_psError04", PS_LOG_ERROR, "psErrorLast did not return expected.");
+        return 34;
+    }
+    psFree(last);
+
+    // Clear the error stack
+    psErrorClear();
+
+    // Get the last error message after clear and verify is has PS_ERR_NONE code
+    lastAfterClear = psErrorLast();
+    if(lastAfterClear->code != PS_ERR_NONE) {
+        psLogMsg("tst_psError05", PS_LOG_ERROR, "psErrorLast did not return expected.");
+        return 35;
+    }
+    psFree(lastAfterClear);
+
+    return 0;
+}
+
+static psS32 testError03(void)
+{
+    psErrorCode code = PS_ERR_BAD_PARAMETER_VALUE;
+    psErr *last = NULL;
+    psErr *getErr = NULL;
+
+    // Attempt to get last error message with an empty stack verify psErr with code PS_ERR_NONE
+    last = psErrorLast();
+    if(last->code != PS_ERR_NONE) {
+        psLogMsg("tst_psError03", PS_LOG_ERROR, "psErrorLast did return PS_ERR_NONE for empty stack");
+        return 20;
+    }
+    psFree(last);
+
+    // Attempt to get specific error message with empty stack verify psErr with code PS_ERR_NONE
+    getErr= psErrorGet(2);
+    if(getErr->code != PS_ERR_NONE) {
+        psLogMsg("tst_psError03", PS_LOG_ERROR, "psErrorGet did not return PS_ERR_NONE  for empty stack");
+        return 21;
+    }
+    psFree(getErr);
+
+    // Attempt to get error message with invalid index and an empty stack
+    getErr= psErrorGet(-1);
+    if(getErr->code != PS_ERR_NONE) {
+        psLogMsg("tst_psError03", PS_LOG_ERROR, "psErrorGet with invalid index/empty stack");
+        return 22;
+    }
+    psFree(getErr);
+
+    // Generate three error messages
+    if (psError(code, true, "Error code = %d", code) !=  code) {
+        psLogMsg("tst_psError03", PS_LOG_ERROR, "Failed return value verify.");
+        return 23;
+    }
+    if (psError((code+1), false, "Error code = %d", (code+1)) != (code+1)) {
+        psLogMsg("tst_psError03", PS_LOG_ERROR, "Failed return value verify.");
+        return 24;
+    }
+    if (psError((code+2), false, "Error code = %d", (code+2)) != (code+2)) {
+        psLogMsg("tst_psError03", PS_LOG_ERROR, "Failed return value verify.");
+        return 25;
+    }
+
+    last = psErrorLast();
+    getErr= psErrorGet(0);
+
+    // Check that last and get with 0 index are equal
+    if(last != getErr) {
+        psLogMsg("tst_psError03", PS_LOG_ERROR, "psErrorGet(0) not equal to psErrorLast");
+        return 26;
+    }
+    psFree(last);
+
+    // Verify the last error message was returned
+    if ( getErr->code != (code+2) ) {
+        psLogMsg("tst_psError03", PS_LOG_ERROR, "psErrorLast() did not retrieve last error");
+        return 27;
+    }
+    psFree(getErr);
+
+    // Verify the middle error message can be retrieved
+    getErr= psErrorGet(1);
+    if ( getErr->code != (code+1)) {
+        psLogMsg("tst_psError03", PS_LOG_ERROR, "psErrorGet() did not retrieve proper error");
+        return 28;
+    }
+    psFree(getErr);
+
+    // Verify the psErrorGet returns NULL if an invalid index is given
+    getErr= psErrorGet(-1);
+    if ( getErr->code != PS_ERR_NONE ) {
+        psLogMsg("tst_psError03", PS_LOG_ERROR, "psErrorGet() did not return PS_ERR_NONE w/ invalid arg");
+        return 29;
+    }
+    psFree(getErr);
+
+    return 0;
+}
+
+static psS32 testError02(void)
+{
+    psErrorCode code = PS_ERR_BAD_PARAMETER_VALUE;
+
+    // Generate error message and verify return value
+    if (psError(code, true, "Error code = %d", code) != code ) {
+        psLogMsg("tst_psError02", PS_LOG_ERROR, "Failed return value verify.");
+        return 10;
+    }
+    myErrorStackPrint(stderr,"ERROR STACK PRINT Test%dA",2);
+
+    return 0;
+}
+
+static psS32 testError01(void)
+{
+    psErrorCode code=PS_ERR_BAD_PARAMETER_VALUE;
+
+    // Verify the return value of psErrorMsg is the psErrorCode passed
+    if ( psError(code, true, "Error code = %d", code) != code) {
+        psLogMsg("tst_psError01", PS_LOG_ERROR, "Failed return value verify.");
+        return 1;
+    }
+    psErrorStackPrint(stderr,"ERROR STACK PRINT Test1A");
+
+    // test1B empty string in for name argument
+    if ( psError(code+1, true, "Error code = %d", code+1) != code+1) {
+        psLogMsg("tst_psError01", PS_LOG_ERROR, "Failed return with empty string.");
+        return 2;
+    }
+    psErrorStackPrint(stderr,"ERROR STACK PRINT Test1B");
+
+    // test1D undefined code
+    if ( psError(-1, true, "Error code = %d", -1) != -1) {
+        psLogMsg("test_psError01", PS_LOG_ERROR, "Failed return with undefined code.");
+        return 4;
+    }
+    psErrorStackPrint(stderr,"ERROR STACK PRINT Test1D");
+
+    // test1E set psErrorMsg argument to false
+    if( psError(code, false, "Error code = %d", code) != code) {
+        psLogMsg("test_psError01", PS_LOG_ERROR, "Failed return with false new arg.");
+        return 5;
+    }
+    psErrorStackPrint(stderr,"ERROR STACK PRINT Test1E");
+
+    // test1F psErrorMsg with a error code less then PS_ERR_BASE(256)
+    if( psError(9, true, "Errno code = %d", 9) != 9) {
+        psLogMsg("test_psError01", PS_LOG_ERROR, "Failed return with errno code.");
+        return 6;
+    }
+    psErrorStackPrint(stderr,"ERROR STACK PRINT Test1F");
+
+    return 0;
+}
+
+static psS32 testError00(void)
+{
+
+    psS32  intval=1;
+    psS64 longval = 2;
+    float floatval = 3.01;
+    char  charval = 'E';
+    char *stringval = "E R R O R";
+
+    // Test point #1 Multiple type values placed in the error string
+    psError(PS_ERR_UNKNOWN, true,
+            "ALL TYPES intval = %d longval = %lld floatval = %f charval = %c strval = %s",
+            intval,longval,floatval,charval,stringval);
+
+    // Test point #2 String values in error message
+    psError(PS_ERR_UNKNOWN, true, "NO VALUES");
+
+    // Test point #3 Empty strings in error message
+    psError(PS_ERR_UNKNOWN, true, "");
+
+    return 0;
+}
+
+static psS32 testErrorRegister(void)
+{
+
+    psS32 numErr = 4;
+    psErrorDescription errDesc[] = { {PS_ERR_N_ERR_CLASSES+1,"first"},
+                                     {PS_ERR_N_ERR_CLASSES+2,"second"},
+                                     {PS_ERR_N_ERR_CLASSES+3,"third"},
+                                     {PS_ERR_N_ERR_CLASSES+4,"fourth"} };
+    /*
+        1. invoke psErrorRegister with a n>1 array of psErrorDescriptions. Verify that:
+            a. Each error description given is retrievable with psErrorCodeString.
+    */
+    psErrorRegister(errDesc,numErr);
+
+    for (psS32 i = 0; i < numErr; i++) {
+        const char* desc = psErrorCodeString(PS_ERR_N_ERR_CLASSES+1+i);
+        if (desc == NULL) {
+            psLogMsg(__func__,PS_LOG_ERROR,
+                     "psErrorCode didn't find registered error code.");
+            return 1+i*10;
+        }
+        if (strcmp(desc,errDesc[i].description) != 0) {
+            psLogMsg(__func__,PS_LOG_ERROR,
+                     "psErrorCode didn't return the proper description.  Got '%s', expected '%s'.",
+                     desc,errDesc[i].description);
+            return 2+i*10;
+        }
+    }
+
+    /*
+        2. invoke psErrorCodeString with a static/builtin psLib error code. Verify:
+            a. the result is correct.
+    */
+    const char* desc = psErrorCodeString(PS_ERR_N_ERR_CLASSES);
+    if (desc == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psErrorCode didn't find static error code.");
+        return 40;
+    }
+    if (strcmp(desc,"error classes end marker") != 0) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psErrorCode didn't return the proper description.  Got '%s', expected '%s'.",
+                 desc,"error classes end marker");
+        return 41;
+    }
+
+    desc = psErrorCodeString(PS_ERR_NONE);
+    if (desc == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psErrorCode didn't find static error code.");
+        return 42;
+    }
+    if (strcmp(desc,"not an error") != 0) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psErrorCode didn't return the proper description.  Got '%s', expected '%s'.",
+                 desc,"not an error");
+        return 43;
+    }
+
+    /*
+        3. invoke psErrorCodeString with an invalid code. Verify a NULL is returned.
+    */
+    desc = psErrorCodeString(PS_ERR_N_ERR_CLASSES+numErr+1);
+    if (desc != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psErrorCode didn't return a NULL with a bogus input code.");
+        return 44;
+    }
+
+    /*
+        4. invoke psErrorRegister with a NULL psErrorDescription. Verify that:
+            a. the execution does not cease.
+            b. an appropriate error is generated.
+    */
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error.");
+    psErrorClear();
+    psErrorRegister(NULL,1);
+    psErr* err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psErrorCode didn't generate proper error code for NULL input.");
+        return 45;
+    }
+    psFree(err);
+
+    /*
+        5. invoke psErrorRegister with nerror=0. Verify that no error occurs.
+    */
+    psErrorClear();
+    psErrorRegister(errDesc,0);
+    err = psErrorLast();
+    if (err->code != PS_ERR_NONE) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psErrorCode generated an error for nErrors = 0.");
+        return 46;
+    }
+    psFree(err);
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psLine.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psLine.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psLine.c	(revision 22158)
@@ -0,0 +1,142 @@
+/** @file  tst_psLine.c
+ *
+ *  @brief Test driver for psLine functions
+ *
+ *  @author  dRob, MHPCC
+ *
+ *  @version $Revision: 1.1 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2006-07-14 02:26:25 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+static psS32 testLineAlloc(void);
+static psS32 testLineInit(void);
+static psS32 testLineAdd(void);
+static psS32 testLineChk(void);
+
+testDescription tests[] = {
+                              {testLineAlloc, 0, "Verify Line Alloc/Free", 0, false},
+                              {testLineInit, 1, "Verify Line Init", 0, false},
+                              {testLineAdd, 2, "Verify Line Add", 0, false},
+                              {testLineChk, 3, "Verify Line MemCheck", 0, false},
+                              {NULL}
+                          };
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetLevel( PS_LOG_INFO );
+
+    return ( ! runTestSuite( stderr, "psLine", tests, argc, argv ) );
+}
+
+psS32 testLineAlloc(void)
+{
+    psLine *lineline = NULL;
+    lineline = psLineAlloc(20);
+
+    if (lineline->NLINE != 20) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psLine set NLINE parameter incorrectly during Allocation!\n");
+        return 2;
+    }
+    if (lineline->Nline != 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psLine set Nline parameter incorrectly during Allocation!\n");
+        return 2;
+    }
+    strncpy(lineline->line, "Hello World", 20);
+    if (strncmp(lineline->line, "Hello World", 20)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psLine was unable to store a simple string!\n");
+        return 3;
+    }
+
+    psFree(lineline);
+
+    return 0;
+}
+
+psS32 testLineInit(void)
+{
+    psLine *line = NULL;
+    //Return false for NULL input
+    if (psLineInit(line) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psLineInit failed.  Expected false for NULL psLine input.\n");
+        return 1;
+    }
+    //Allocate a line and return true on Init
+    line = psLineAlloc(1);
+    if(!psLineInit(line) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psLineInit failed.  Expected true for valid psLine input.\n");
+        return 2;
+    }
+    if (line->NLINE != 1 || line->Nline != 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psLineInit failed to return the correct line parameters.\n");
+        return 3;
+    }
+
+    psFree(line);
+
+    return 0;
+}
+
+psS32 testLineAdd(void)
+{
+    psLine *line = NULL;
+    //Return false for NULL input
+    if (psLineAdd(line, "Hello World") ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psLineAdd failed.  Expected false for NULL psLine input.\n");
+        return 1;
+    }
+    //Allocate and return true for valid input.
+    line = psLineAlloc(20);
+    if (!psLineAdd(line, "Hello %s", "World") ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psLineAdd failed.  Expected true for valid psLine input.\n");
+        return 2;
+    }
+    if (line->NLINE != 20 || line->Nline != 11) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psLineAdd failed to return the correct line parameters.\n");
+        return 3;
+    }
+    if (strncmp(line->line, "Hello World", 20)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psLineAdd failed to store the correct line string.\n");
+        printf("\n  %s\n", line->line);
+        return 4;
+    }
+
+    psFree(line);
+
+    return 0;
+}
+
+psS32 testLineChk(void)
+{
+    psLine *line = NULL;
+    //Return false for Null input line
+    if (psMemCheckLine(line)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psMemCheckLine failed to return false for NULL line input.\n");
+        return 1;
+    }
+    line = psLineAlloc(1);
+    if (!psMemCheckLine(line)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psMemCheckLine failed to return true for valid line input.\n");
+        return 2;
+    }
+    psFree(line);
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psLogMsg.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psLogMsg.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psLogMsg.c	(revision 22158)
@@ -0,0 +1,308 @@
+/*****************************************************************************
+    This code will test whether trace levels can be set successfully.
+    This code will test whether trace messages can be displayed with printf
+    style string.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+#include <unistd.h>
+#include <fcntl.h>
+
+static psS32 testLogMsg00();
+static psS32 testLogMsg01();
+static psS32 testLogMsg02();
+static psS32 testLogMsg03();
+static psS32 testLogMsg04();
+static psS32 testLogMsg05();
+static psS32 testLogMsg06();
+
+testDescription tests[] = {
+                              {
+                                  testLogMsg00, 0, "default log levels, printf-style strings", 0, false
+                              },
+                              {
+                                  testLogMsg01, 1, "default log levels, psVLogMsg()", 0, false
+                              },
+                              {
+                                  testLogMsg02, 2, "psLogSet/GetLevel()", 0, false
+                              },
+                              {
+                                  testLogMsg03, 3, "psLogSetFormat()", 0, false
+                              },
+                              {
+                                  testLogMsg04, 4, "Output Format", 0, false
+                              },
+                              {
+                                  testLogMsg05, 5, "psLogSet/GetDestination()", 0, false
+                              },
+                              {
+                                  testLogMsg06, 6, "psMessageDestination()", 0, false
+                              },
+                              {
+                                  NULL
+                              }
+                          };
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetLevel( PS_LOG_INFO );
+
+    return ( ! runTestSuite( stderr, "psLogMsg", tests, argc, argv ) );
+}
+
+
+static void myLogMsg(const char *name,
+                     psS32 level,
+                     const char *fmt,
+                     ...)
+{
+    va_list ap;
+
+    // Test whether psLogMsgV() accept a va_list for output variables.
+    va_start(ap, fmt);
+    psLogMsgV(name, level, fmt, ap);
+    va_end(ap);
+}
+
+static psS32 testLogMsg00()
+{
+    psS32 i = 0;
+
+    // Send a log messages for levels 0:9.  Only the first four messages
+    // should actually be displayed.
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d %f %s\n", i,
+                 (float) i, "beep beep");
+    }
+
+    return 0;
+}
+
+static psS32 testLogMsg01()
+{
+    psS32 i = 0;
+
+    // Send a log messages for levels 0:9.  Only the first four messages
+    // should actually be displayed.
+    for (i=0;i<10;i++) {
+        myLogMsg(__func__, i, "Hello World!  My level is %d %f %s\n", i,
+                 (float) i, "beep beep");
+    }
+
+    return 0;
+}
+
+static psS32 testLogMsg02()
+{
+
+    psLogSetLevel(9);
+    // Send a log messages for levels 0:9.
+    for (psS32 i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    psLogSetLevel(5);
+    psLogMsg(__func__, 6, "This should not be displayed (level %d)\n", 6);
+    psLogSetLevel(4);
+    psLogMsg(__func__, 4, "This should  be displayed (level %d)\n", 4);
+    psLogMsg(__func__, 4, "This should display level 4 logging -> level %d\n", psLogGetLevel() );
+
+    return 0;
+}
+
+static psS32 testLogMsg03()
+{
+    psS32 i;
+
+    fprintf(stderr,"------------- psLogSetFormat() -------------\n");
+    psLogSetFormat("");
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    fprintf(stderr,"------------- psLogSetFormat(NULL) -------------\n");
+    psLogSetFormat(NULL);
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    fprintf(stderr,"------------- psLogSetFormat(T) -------------\n");
+    psLogSetFormat("T");
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    fprintf(stderr,"------------- psLogSetFormat(H) -------------\n");
+    psLogSetFormat("H");
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    fprintf(stderr,"------------- psLogSetFormat(L) -------------\n");
+    psLogSetFormat("L");
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    fprintf(stderr,"------------- psLogSetFormat(N) -------------\n");
+    psLogSetFormat("N");
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    fprintf(stderr,"------------- psLogSetFormat(M) -------------\n");
+    psLogSetFormat("M");
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    fprintf(stderr,"------------- psLogSetFormat(THLNM) -------------\n");
+    psLogSetFormat("THLNM");
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    return 0;
+}
+
+
+psS32 testLogMsg04()
+{
+    psLogMsg("Under 15 chars", 0, "Hello World!\n");
+    psLogMsg("This string is more than 15 chars", 0, "Hello World!\n");
+    psLogMsg(__func__, 0, "Line #1\n");
+    psLogMsg(__func__, 0, "Line #2\n");
+    psLogMsg(__func__, 0, "Line #3");
+    psLogMsg(__func__, 0, "Line #4");
+
+    return 0;
+}
+
+psS32 testLogMsg05()
+{
+    psS32 i = 0;
+    //    FILE* file;
+    int fd;
+    //    char line[256];
+
+    printf("--------------- psLogSetDestination(PS_LOG_NONE) ----------------\n");
+    //    psLogSetDestination("none");
+    psLogSetDestination(0);
+    printf("    File Descriptor = %d \n", psLogGetDestination() );
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    printf("------------- psLogSetDestination(PS_LOG_TO_STDERR) -------------\n");
+    //    psLogSetDestination("dest:stderr");
+    psLogSetDestination(2);
+    printf("    File Descriptor = %d \n", psLogGetDestination() );
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    printf("------------- psLogSetDestination(PS_LOG_TO_STDOUT) -------------\n");
+    //    psLogSetDestination("dest:stdout");
+    psLogSetDestination(1);
+    printf("    File Descriptor = %d \n", psLogGetDestination() );
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    printf("--------------- psLogSetDestination(""file:log.txt"") ---------------\n");
+    fd = creat("log.txt", 0666);
+    //    psLogSetDestination("file:log.txt");
+    psLogSetDestination(fd);
+    printf("    File Descriptor = %d \n", psLogGetDestination() );
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+
+    //    psLogSetDestination("none");
+    FILE *file;
+    char line[257];
+    //    psLogSetDestination(-1);
+    psLogSetDestination(0);
+    printf("--------------------- The Contents of log.txt -------------------\n");
+    file = fopen("log.txt","r");
+    while ( fgets(line,256,file) != NULL ) {
+        printf("%s",line);
+    }
+    fclose(file);
+    close(fd);
+
+    int fd2 = creat("eva/log.txt", 0666);
+    printf("--------------- psLogSetDestination(""file:eva/log.txt"") ----------\n");
+    //    psLogSetDestination("file:/eva/log.txt");
+    psLogSetDestination(fd2);
+    for ( i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World! My level is %d\n", i);
+    }
+    close(fd2);
+
+    return 0;
+}
+
+psS32 testLogMsg06()
+{
+    psS32 i = 0;
+    //    FILE* file;
+    int fd;
+    //    char line[256];
+
+    printf("--------------- psMessageDestination(PS_LOG_NONE) ----------------\n");
+    psMessageDestination("none");
+    //    psLogSetDestination(0);
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+    printf("------------- psMessageDestination(PS_LOG_TO_STDERR) -------------\n");
+    psMessageDestination("stderr");
+    //    psLogSetDestination(2);
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d - stderr\n", i);
+    }
+
+    printf("------------- psMessageDestination(PS_LOG_TO_STDOUT) -------------\n");
+    psMessageDestination("stdout");
+    //    psLogSetDestination(1);
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d - stdout\n", i);
+    }
+
+    printf("--------------- psMessageDestination(""file:log2.txt"") ---------------\n");
+    fd = creat("log2.txt", 0666);
+    psMessageDestination("file:log2.txt");
+    //    psLogSetDestination(fd);
+    for (i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World!  My level is %d\n", i);
+    }
+
+
+    psMessageDestination("none");
+    FILE *file;
+    char line[257];
+    //    psMessageDestination(-1);
+    //    psLogSetDestination(0);
+    printf("--------------------- The Contents of log2.txt -------------------\n");
+    file = fopen("log2.txt","r");
+    while ( fgets(line,256,file) != NULL ) {
+        printf("%s",line);
+    }
+    fclose(file);
+    close(fd);
+
+    int fd2 = creat("eva/log2.txt", 0666);
+    printf("--------------- psMessageDestination(""file:eva/log.txt"") ----------\n");
+    psMessageDestination("file:eva/log2.txt");
+    //    psLogSetDestination(fd2);
+    for ( i=0;i<10;i++) {
+        psLogMsg(__func__, i, "Hello World! My level is %d\n", i);
+    }
+    close(fd2);
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psMemory.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psMemory.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psMemory.c	(revision 22158)
@@ -0,0 +1,827 @@
+/** @file  tst_psMemory.c
+*
+*  @brief Contains the tests for psMemory.[ch]
+*
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2006-04-04 19:52:55 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <stdlib.h>
+
+
+#include "psTest.h"
+#include "pslib.h" // need to allow malloc for callback use
+
+static psS32 TPFreeReferencedMemory( void );
+static psS32 TPOutOfMemory( void );
+static psS32 TPReallocOutOfMemory( void );
+static psPtr TPOutOfMemoryExhaustedCallback( size_t size );
+static psS32 TPCheckBufferPositive( void );
+static psS32 TPrealloc( void );
+static psS32 TPallocCallback( void );
+static psMemId memAllocCallback( const psMemBlock *ptr );
+static psMemId memFreeCallback( const psMemBlock *ptr );
+static psS32 TPcheckLeaks( void );
+static psS32 TPmemCorruption( void );
+static psS32 TPmultipleFree( void );
+static psS32 memCheckTypes( void );
+void memProblemCallback( psMemBlock *ptr, const char *filename, unsigned int lineno );
+
+static psS32 problemCallbackCalled = 0;
+static psS32 allocCallbackCalled = 0;
+static psS32 freeCallbackCalled = 0;
+static psS32 exhaustedCallbackCalled = 0;
+
+testDescription tests[] = {
+                              {TPCheckBufferPositive, 449, "checkBufferPositive", 0, false},
+                              {TPOutOfMemory, 450, "outOfMemory", -6, false},
+                              {TPReallocOutOfMemory, 562, "reallocOutOfMemory", -6, false},
+                              {TPrealloc, 451, "psRealloc", 0, false},
+                              {TPallocCallback, 452, "allocCallback", 0, false},
+                              {TPallocCallback, 453, "allocCallback2", 0, true},
+                              {TPcheckLeaks, 454, "checkLeaks", 0, false},
+                              {TPmemCorruption, 455, "psMemCorruption", 0, false},
+                              {TPFreeReferencedMemory, 456, "freeReferencedMemory", 0, false},
+                              {TPmultipleFree, 699, "multipleFree", -6, false},
+                              {memCheckTypes, 700, "psMemCheckType", 0, false},
+                              {NULL}
+                          };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel( PS_LOG_INFO );
+
+    return ( ! runTestSuite( stderr, "psMemory", tests, argc, argv ) );
+}
+
+// Testpoint #449, psAlloc shall allocate memory blocks writeable by caller.
+psS32 TPCheckBufferPositive( void )
+{
+    psS32 * mem;
+    const psS32 size = 100;
+    psS32 failed = 0;
+
+    psLogMsg( __func__, PS_LOG_INFO, "psAlloc shall allocate memory blocks writeable by caller.\n" );
+
+    mem = ( psS32* ) psAlloc( size * sizeof( psS32 ) );
+    if ( mem == NULL ) {
+        psError(PS_ERR_UNKNOWN, true, "psAlloc returned a NULL value in %s!", __func__ );
+        return 1;
+    }
+
+    for ( psS32 index = 0;index < size;index++ ) {
+        mem[ index ] = index;
+    }
+
+    for ( psS32 index = 0;index < size;index++ ) {
+        if ( mem[ index ] != index ) {
+            failed++;
+        }
+    }
+
+    psFree( mem );
+
+    return failed;
+}
+
+psS32 TPFreeReferencedMemory( void )
+{
+    // create memory
+    psS32 * mem;
+    psS32 ref = 0;
+
+    psLogMsg( __func__, PS_LOG_INFO, "memory reference count shall be incrementable/decrementable" );
+
+    mem = ( psS32* ) psAlloc( 100 * sizeof( psS32 ) );
+
+    ref = psMemGetRefCounter( mem );
+    if ( ref != 1 ) {
+        psError(PS_ERR_UNKNOWN, true, "Expected to buffer reference count to be initially 1, but it was %d.", ref );
+        return 1;
+    }
+
+    psMemIncrRefCounter( mem );
+    psMemIncrRefCounter( mem );
+    psMemIncrRefCounter( mem );
+
+    ref = psMemGetRefCounter( mem );
+    if ( ref != 4 ) {
+        psError(PS_ERR_UNKNOWN, true, "Expected to find buffer reference count to be 4, but it was %d.", ref );
+        return 1;
+    }
+
+    psMemDecrRefCounter( mem );
+    psMemDecrRefCounter( mem );
+
+    ref = psMemGetRefCounter( mem );
+    if ( ref != 2 ) {
+        psError(PS_ERR_UNKNOWN, true, "Expected to find buffer reference count to be 2, but it was %d.", ref );
+        return 1;
+    }
+
+    psLogMsg( __func__, PS_LOG_INFO, "psFree shall be just decrement a multiple refererenced pointer." );
+
+    psMemDecrRefCounter( mem );
+
+    ref = psMemGetRefCounter( mem );
+    if ( ref != 1 ) {
+        psError(PS_ERR_UNKNOWN, true, "Expected to find buffer reference count to be 1, but it was %d.", ref );
+        return 1;
+    }
+
+    psFree( mem );
+
+    return 0;
+}
+
+// Bug/Task #562 regression test.  Upon requesting more memory than is available, psRealloc shall call
+// the psMemExhaustedCallback.
+psS32 TPReallocOutOfMemory( void )
+{
+    psS32 * mem[ 100 ];
+    psMemExhaustedCallback cb;
+
+    for ( psS32 lcv = 0; lcv < 100; lcv++ ) {
+        mem[ lcv ] = NULL;
+    }
+
+    psLogMsg( __func__, PS_LOG_INFO, "Upon requesting more memory than is available, psRealloc shall call "
+              "the psMemExhaustedCallback.\n" );
+
+    exhaustedCallbackCalled = 0;
+
+    cb = psMemExhaustedCallbackSet( TPOutOfMemoryExhaustedCallback );
+
+    for ( psS32 lcv = 0; lcv < 100; lcv++ ) {
+        mem[ lcv ] = ( psS32* ) psAlloc( 10 );
+    }
+
+    for ( psS32 lcv = 0; lcv < 100; lcv++ ) {
+        mem[ lcv ] = ( psS32* ) psRealloc( mem[ lcv ], SIZE_MAX/2 - 1000 );
+    }
+
+    psMemExhaustedCallbackSet( cb );
+
+    if ( exhaustedCallbackCalled == 0 ) {
+        psError(PS_ERR_UNKNOWN,true, "Called psRealloc with HUGE memory requirement and survived in %s!", __func__ );
+        return 1;
+    }
+
+    for ( psS32 lcv = 0; lcv < 100; lcv++ ) {
+        psFree( mem[ lcv ] );
+    }
+
+    return 0;
+}
+// Testpoint #450,  Upon requesting more memory than is available, psalloc shall call
+// the psMemExhaustedCallback.
+psS32 TPOutOfMemory( void )
+{
+    psS32 * mem[ 100 ];
+    psMemExhaustedCallback cb;
+
+    for ( psS32 lcv = 0; lcv < 100; lcv++ ) {
+        mem[ lcv ] = NULL;
+    }
+
+    psLogMsg( __func__, PS_LOG_INFO, "Upon requesting more memory than is available, psalloc shall call "
+              "the psMemExhaustedCallback.\n" );
+
+    exhaustedCallbackCalled = 0;
+
+    cb = psMemExhaustedCallbackSet( TPOutOfMemoryExhaustedCallback );
+
+    for ( psS32 lcv = 0; lcv < 100; lcv++ ) {
+        mem[ lcv ] = ( psS32* ) psAlloc( SIZE_MAX/2 - 1000 );
+    }
+
+    psMemExhaustedCallbackSet( cb );
+
+    if ( exhaustedCallbackCalled == 0 ) {
+        psError(PS_ERR_UNKNOWN,true, "Called psAlloc with HUGE memory requirement and survived in %s!", __func__ );
+        return 1;
+    }
+
+    for ( psS32 lcv = 0; lcv < 100; lcv++ ) {
+        psFree( mem[ lcv ] );
+    }
+
+    return 0;
+}
+
+// Testpoint #451,  psRealloc shall increase/decrease memory buffer while preserving contents
+psS32 TPrealloc( void )
+{
+    psS32 * mem1;
+    psS32* mem2;
+    psS32* mem3;
+    const psS32 initialSize = 100;
+
+    psLogMsg( __func__, PS_LOG_INFO, "psRealloc shall increase/decrease memory buffer while "
+              "preserving contents" );
+
+    // allocate buffer with known values.
+    mem1 = ( psS32* ) psAlloc( initialSize * sizeof( psS32 ) );
+    mem2 = ( psS32* ) psAlloc( initialSize * sizeof( psS32 ) );
+    mem3 = ( psS32* ) psAlloc( initialSize * sizeof( psS32 ) );
+    for ( psS32 lcv = 0;lcv < initialSize;lcv++ ) {
+        mem1[ lcv ] = mem2[ lcv ] = mem3[ lcv ] = lcv;
+    }
+
+    psMemCheckCorruption( 1 );
+    psLogMsg( __func__, PS_LOG_INFO, "Expanding memory buffer." );
+
+    // realloc to 2x
+    mem1 = ( psS32* ) psRealloc( mem1, 2 * initialSize * sizeof( psS32 ) );
+    mem2 = ( psS32* ) psRealloc( mem2, 2 * initialSize * sizeof( psS32 ) );
+    mem3 = ( psS32* ) psRealloc( mem3, 2 * initialSize * sizeof( psS32 ) );
+
+    // check values of initial block
+    for ( psS32 i = 0;i < initialSize;i++ ) {
+        if ( mem1[ i ] != i || mem2[ i ] != i || mem3[ i ] != i ) {
+            psError(PS_ERR_UNKNOWN,true, "Realloc didn't preserve the contents with expanding buffer in %s.",
+                    __func__ );
+            break;
+        }
+    }
+
+    psMemCheckCorruption( 1 );
+    psLogMsg( __func__, PS_LOG_INFO, "Shrinking memory buffer." );
+
+    // realloc to 1/2 initial value.
+    mem1 = ( psS32* ) psRealloc( mem1, ( initialSize / 2 ) * sizeof( psS32 ) );
+    mem2 = ( psS32* ) psRealloc( mem2, ( initialSize / 2 ) * sizeof( psS32 ) );
+    mem3 = ( psS32* ) psRealloc( mem3, ( initialSize / 2 ) * sizeof( psS32 ) );
+
+    // check values of initial block
+    for ( psS32 i = 0;i < initialSize / 2;i++ ) {
+        if ( mem1[ i ] != i || mem2[ i ] != i || mem3[ i ] != i ) {
+            psError(PS_ERR_UNKNOWN,true, "Realloc didn't preserve the contents with shrinking buffer in %s.",
+                    __func__ );
+            break;
+        }
+    }
+
+    psFree( mem1 );
+    psFree( mem2 );
+    psFree( mem3 );
+
+    return 0;
+}
+
+psS32 TPallocCallback( void )
+{
+    psS32 * mem1;
+    psS32* mem2;
+    psS32* mem3;
+    psS32 currentId = psMemGetId();
+    const psS32 initialSize = 100;
+    psS32 mark;
+
+    allocCallbackCalled = 0;
+    freeCallbackCalled = 0;
+    psMemAllocCallbackSet( memAllocCallback );
+    psMemFreeCallbackSet( memFreeCallback );
+
+    psMemAllocCallbackSetID( currentId + 1 );
+    psMemFreeCallbackSetID( currentId + 1 );
+
+    psLogMsg( __func__, PS_LOG_INFO, "call to psAlloc/psRealloc shall generate a callback if specified "
+              "memory ID is allocated." );
+
+    // allocate buffer with known values.
+    mem1 = ( psS32* ) psAlloc( initialSize * sizeof( psS32 ) );
+    mem2 = ( psS32* ) psAlloc( initialSize * sizeof( psS32 ) );
+    mem3 = ( psS32* ) psAlloc( initialSize * sizeof( psS32 ) );
+
+    psFree( mem1 );
+    psFree( mem2 );
+    psFree( mem3 );
+
+    if ( allocCallbackCalled != 2 || freeCallbackCalled != 2 ) {
+        psError(PS_ERR_UNKNOWN,true, "alloc/free callbacks were not called the proper number of times in %s",
+                __func__ );
+        return 1;
+    }
+
+    allocCallbackCalled = 0;
+    freeCallbackCalled = 0;
+
+    mark = psMemGetId();
+
+    mem1 = ( psS32* ) psAlloc( initialSize * sizeof( psS32 ) );
+
+    psMemAllocCallbackSetID( mark );
+
+    mem1 = ( psS32* ) psRealloc( mem1, initialSize * 2 * sizeof( psS32 ) );
+
+    psFree( mem1 );
+
+    if ( allocCallbackCalled != 2 ) {
+        psError(PS_ERR_UNKNOWN,true, "realloc callbacks were not called the proper number of times in %s",
+                __func__ );
+        return 1;
+    }
+
+    return 0;
+
+}
+
+psS32 TPcheckLeaks( void )
+{
+    const psS32 numBuffers = 5;
+    psS32* buffers[ 5 ];
+    psS32 lcv;
+    psS32 currentId = psMemGetId();
+    psMemBlock** blks;
+    psS32 nLeaks = 0;
+    psS32 lineMark = 0;
+
+    psLogMsg( __func__, PS_LOG_INFO, "psMemCheckLeaks shall return the number of blocks above an ID "
+              "that are still allocated" );
+
+    for ( lcv = 0;lcv < numBuffers;lcv++ ) {
+        lineMark = __LINE__ + 1;
+        buffers[ lcv ] = psAlloc( sizeof( psS32 ) );
+    }
+
+    for ( lcv = 1;lcv < numBuffers;lcv++ ) {
+        psFree( buffers[ lcv ] );
+    }
+
+    psLogMsg( __func__, PS_LOG_INFO, "following psMemCheckLeaks call should produce one instance." );
+
+    nLeaks = psMemCheckLeaks( currentId, &blks, stderr, false );
+
+    if ( nLeaks != 1 ) {
+        psError(PS_ERR_UNKNOWN,true, "psMemCheckLeaks should have found 1 leak, but found %d in %s.", nLeaks, __func__ );
+        return 1;
+    }
+
+    if ( blks[ 0 ] ->lineno != lineMark ) {
+        psError(PS_ERR_UNKNOWN,true, "psMemCheckLeaks found a leak other than the expected one (line %d vs %d) in %s.",
+                lineMark, blks[ 0 ] ->lineno, __func__ );
+        return 1;
+    }
+
+    psFree( buffers[ 0 ] );
+    psFree( blks );
+
+    psLogMsg( __func__, PS_LOG_INFO, "Testing psMemCheckLeaks again with a different leak location" );
+    psMemCheckLeaks(currentId,NULL,stderr, false);
+
+    for ( lcv = 0;lcv < numBuffers;lcv++ ) {
+        lineMark = __LINE__ + 1;
+        buffers[ lcv ] = psAlloc( sizeof( psS32 ) );
+    }
+
+    for ( lcv = 0;lcv < numBuffers - 1;lcv++ ) {
+        psFree( buffers[ lcv ] );
+    }
+
+    psLogMsg( __func__, PS_LOG_INFO, "following psMemCheckLeaks call should produce one error." );
+
+    nLeaks = psMemCheckLeaks( currentId, &blks, stderr, false );
+
+    if ( nLeaks != 1 ) {
+        psError(PS_ERR_UNKNOWN,true, "psMemCheckLeaks should have found 1 leak, but found %d in %s.", nLeaks, __func__ );
+        return 1;
+    }
+
+    if ( blks[ 0 ] ->lineno != lineMark ) {
+        psError(PS_ERR_UNKNOWN,true, "psMemCheckLeaks found a leak other than the expected one in %s.", __func__ );
+        return 1;
+    }
+
+    psFree( buffers[ 4 ] );
+    psFree( blks );
+
+    psLogMsg( __func__, PS_LOG_INFO, "Testing psMemCheckLeaks again with multiple leak locations." );
+
+    for ( lcv = 0;lcv < numBuffers;lcv++ ) {
+        lineMark = __LINE__ + 1;
+        buffers[ lcv ] = psAlloc( sizeof( psS32 ) );
+    }
+
+    for ( lcv = 0;lcv < numBuffers;lcv++ ) {
+        if ( lcv % 2 == 0 ) {
+            psFree( buffers[ lcv ] );
+        }
+    }
+
+    psLogMsg( __func__, PS_LOG_INFO, "following psMemCheckLeaks call should produce two errors." );
+
+    nLeaks = psMemCheckLeaks( currentId, &blks, stderr, false );
+
+    if ( nLeaks != 2 ) {
+        psError(PS_ERR_UNKNOWN,true, "psMemCheckLeaks should have found 1 leak, but found %d in %s.", nLeaks, __func__ );
+        return 1;
+    }
+
+    if ( blks[ 0 ] ->lineno != lineMark ) {
+        psError(PS_ERR_UNKNOWN,true, "psMemCheckLeaks found a leak other than the expected one in %s.", __func__ );
+        return 1;
+    }
+
+    psFree( blks );
+    psFree( buffers[ 1 ] );
+    psFree( buffers[ 3 ] );
+
+    return 0;
+}
+
+psS32 TPmemCorruption( void )
+{
+    psS32 * buffer = NULL;
+    psS32 oldValue = 0;
+    psS32 corruptions = 0;
+    psMemProblemCallback cb;
+
+    psLogMsg( __func__, PS_LOG_INFO, "psMemCheckCorruption shall detect memory corruptions" );
+
+    buffer = psAlloc( sizeof( psS32 ) );
+
+    // cause memory corruption via buffer underflow
+    *buffer = 1;
+    buffer--;
+    oldValue = *buffer;
+    *buffer = 2;
+
+    problemCallbackCalled = 0;
+    cb = psMemProblemCallbackSet( memProblemCallback );
+
+    psLogMsg( __func__, PS_LOG_INFO, "psMemCheckCorruption should output an error message and "
+              "memProblemCallback callback should be called." );
+
+    corruptions = psMemCheckCorruption( 0 );
+
+    // restore the memory problem callback
+    psMemProblemCallbackSet( cb );
+
+    // restore the value, 'uncorrupting' the buffer
+    *buffer = oldValue;
+    buffer++;
+
+    psFree( buffer );
+
+    if ( corruptions != 1 ) {
+        psError(PS_ERR_UNKNOWN,true, "Expected one memory corruption but found %d in %s.",
+                corruptions, __func__ );
+        return 1;
+    }
+
+    if ( problemCallbackCalled != 1 ) {
+        psError(PS_ERR_UNKNOWN,true, "The memProblemCallback was not invoked but should have been in %s",
+                __func__ );
+        return 1;
+    }
+
+    return 0;
+
+}
+
+void memProblemCallback( psMemBlock *ptr, const char *file, unsigned int lineno )
+{
+    psLogMsg( __func__, PS_LOG_INFO, "memory callback called for id %lu (%s:%d).",
+              ptr->id, file, lineno );
+    problemCallbackCalled++;
+    return ;
+}
+
+psMemId memAllocCallback( const psMemBlock *ptr )
+{
+    psLogMsg( __func__, PS_LOG_INFO, "block %lu was (re)allocated", ptr->id );
+    allocCallbackCalled++;
+    return 1;
+}
+
+psMemId memFreeCallback( const psMemBlock *ptr )
+{
+    psLogMsg( __func__, PS_LOG_INFO, "block %lu was freed", ptr->id );
+    freeCallbackCalled++;
+    return 1;
+}
+
+psPtr TPOutOfMemoryExhaustedCallback( size_t size )
+{
+    psLogMsg( __func__, PS_LOG_INFO, "Custom MemExhaustedCallback was invoked." );
+    exhaustedCallbackCalled++;
+    return NULL;
+}
+
+psS32 TPmultipleFree( void )
+{
+
+    psPtr buffer = psAlloc( 1024 );
+    psPtr buffer2 = buffer;
+
+    psFree( buffer );
+
+    psLogMsg( __func__, PS_LOG_INFO, "Next should abort due to multiple freeing." );
+    psFree( buffer2 );
+
+    psError(PS_ERR_UNKNOWN,true,
+            "Multiple psFree call survived");
+
+    return 0;
+}
+
+static psS32 memCheckTypes( void )
+{
+    psArray *negative;
+    negative = psArrayAlloc(2);
+    psMetadata *neg;
+    neg = psMetadataAlloc();
+
+    psArray *array;
+    array = psArrayAlloc(100);
+    if ( !psMemCheckType(PS_DATA_ARRAY, array) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckArray failed in memCheckType. \n");
+        psFree(array);
+        return 1;
+    }
+    psLogMsg( __func__, PS_LOG_INFO, "Next should error from invalid datatype." );
+    if ( !psMemCheckType(PS_DATA_ARRAY, neg) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckArray failed in memCheckType. \n");
+    }
+    psFree(array);
+
+    psBitSet *bits;
+    bits = psBitSetAlloc(100);
+    if ( !psMemCheckType(PS_DATA_BITSET, bits) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckBitSet failed in memCheckType. \n");
+        psFree(bits);
+        return 1;
+    }
+    psLogMsg( __func__, PS_LOG_INFO, "Next should error from invalid datatype." );
+    if ( !psMemCheckType(PS_DATA_BITSET, negative) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckBitSet failed in memCheckType. \n");
+    }
+    psFree(bits);
+
+    psCube *cube;
+    cube = psCubeAlloc();
+    if ( !psMemCheckType(PS_DATA_CUBE, cube) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckCube failed in memCheckType. \n");
+        psFree(cube);
+        return 1;
+    }
+    psFree(cube);
+
+    psFits *fits;
+    fits = psFitsOpen("test.fits","w");
+    psImage* img = psImageAlloc(16,16,PS_TYPE_F32);
+    psFitsWriteImage(fits,NULL,img,1,NULL);
+    psFree(img);
+    if ( !psMemCheckType(PS_DATA_FITS, fits) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckFits failed in memCheckType. \n");
+        psFree(fits);
+        return 1;
+    }
+    psFitsClose(fits);
+
+    psHash *hash;
+    hash = psHashAlloc(100);
+    if ( !psMemCheckType(PS_DATA_HASH, hash) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckHash failed in memCheckType. \n");
+        psFree(hash);
+        return 1;
+    }
+    psFree(hash);
+
+    psHistogram *histogram;
+    histogram = psHistogramAlloc(1.1, 2.2, 2);
+    if ( !psMemCheckType(PS_DATA_HISTOGRAM, histogram) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckHistogram failed in memCheckType. \n");
+        psFree(histogram);
+        return 1;
+    }
+    psFree(histogram);
+
+    psImage *image;
+    image = psImageAlloc(5, 5, PS_TYPE_F32);
+    if ( !psMemCheckType(PS_DATA_IMAGE, image) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckImage failed in memCheckType. \n");
+        psFree(image);
+        return 1;
+    }
+    psFree(image);
+
+    psKernel *kernel;
+    kernel = psKernelAlloc(0, 1, 0, 1);
+    if ( !psMemCheckType(PS_DATA_KERNEL, kernel) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckKernel failed in memCheckType. \n");
+        psFree(kernel);
+        return 1;
+    }
+    psFree(kernel);
+
+    psList *list;
+    list = psListAlloc(NULL);
+    if ( !psMemCheckType(PS_DATA_LIST, list) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckList failed in memCheckType. \n");
+        psFree(list);
+        return 1;
+    }
+    psFree(list);
+
+    psLookupTable *lookup;
+    char *file = "tableF32.dat";
+    char *format = "\%f \%lf \%d \%ld";
+    lookup = psLookupTableAlloc(file, format, 10);
+    if ( !psMemCheckType(PS_DATA_LOOKUPTABLE, lookup) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckLookupTable failed in memCheckType. \n");
+        psFree(lookup);
+        return 1;
+    }
+    psFree(lookup);
+
+    psMetadata *metadata;
+    metadata = psMetadataAlloc();
+    if ( !psMemCheckType(PS_DATA_METADATA, metadata) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckMetadata failed in memCheckType. \n");
+        psFree(metadata);
+        return 1;
+    }
+    psFree(metadata);
+
+    psMetadataItem *metaItem;
+    metaItem = psMetadataItemAlloc("name", PS_DATA_S32, "COMMENT", 1);
+    if ( !psMemCheckType(PS_DATA_METADATAITEM, metaItem) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckMetadataItem failed in memCheckType. \n");
+        psFree(metaItem);
+        return 1;
+    }
+    psFree(metaItem);
+
+    psMinimization *min;
+    min = psMinimizationAlloc(3, 0.1);
+    if ( !psMemCheckType(PS_DATA_MINIMIZATION, min) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckMinimization failed in memCheckType. \n");
+        psFree(min);
+        return 1;
+    }
+    psFree(min);
+
+    psPixels *pixels;
+    pixels = psPixelsAlloc(100);
+    if ( !psMemCheckType(PS_DATA_PIXELS, pixels) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckPixels failed in memCheckType. \n");
+        psFree(pixels);
+        return 1;
+    }
+    psFree(pixels);
+
+    psPlane *plane;
+    plane = psPlaneAlloc();
+    if ( !psMemCheckType(PS_DATA_PLANE, plane) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckPlane failed in memCheckType. \n");
+        psFree(plane);
+        return 1;
+    }
+    psFree(plane);
+
+    psPlaneDistort *planeDistort;
+    planeDistort = psPlaneDistortAlloc(1, 1, 1, 1);
+    if ( !psMemCheckType(PS_DATA_PLANEDISTORT, planeDistort) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckPlaneDistort failed in memCheckType. \n");
+        psFree(planeDistort);
+        return 1;
+    }
+    psFree(planeDistort);
+
+    psPlaneTransform *planeTransform;
+    planeTransform = psPlaneTransformAlloc(1, 1);
+    if ( !psMemCheckType(PS_DATA_PLANETRANSFORM, planeTransform) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckPlaneTransform failed in memCheckType. \n");
+        psFree(planeTransform);
+        return 1;
+    }
+    psFree(planeTransform);
+
+    psPolynomial1D *poly1;
+    poly1 = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 2);
+    if ( !psMemCheckType(PS_DATA_POLYNOMIAL1D, poly1) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckPolynomial1D failed in memCheckType. \n");
+        psFree(poly1);
+        return 1;
+    }
+    psFree(poly1);
+
+    psPolynomial2D *poly2;
+    poly2 = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 2, 1);
+    if ( !psMemCheckType(PS_DATA_POLYNOMIAL2D, poly2) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckPolynomial2D failed in memCheckType. \n");
+        psFree(poly2);
+        return 1;
+    }
+    psFree(poly2);
+
+    psPolynomial3D *poly3;
+    poly3 = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, 2, 1, 1);
+    if ( !psMemCheckType(PS_DATA_POLYNOMIAL3D, poly3) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckPolynomial3D failed in memCheckType. \n");
+        psFree(poly3);
+        return 1;
+    }
+    psFree(poly3);
+
+    psPolynomial4D *poly4;
+    poly4 = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, 2, 1, 2, 1);
+    if ( !psMemCheckType(PS_DATA_POLYNOMIAL4D, poly4) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckPolynomial4D failed in memCheckType. \n");
+        psFree(poly4);
+        return 1;
+    }
+    psFree(poly4);
+
+    psProjection *proj;
+    proj = psProjectionAlloc(1, 1, 2.1, 2.1, PS_PROJ_TAN);
+    if ( !psMemCheckType(PS_DATA_PROJECTION, proj) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckProjection failed in memCheckType. \n");
+        psFree(proj);
+        return 1;
+    }
+    psFree(proj);
+
+    psScalar *scalar;
+    psC64 c64 = 1.1 + 7I;
+    scalar = psScalarAlloc(c64, PS_TYPE_F64);
+    if ( !psMemCheckType(PS_DATA_SCALAR, scalar) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckScalar failed in memCheckType. \n");
+        psFree(scalar);
+        return 1;
+    }
+    psFree(scalar);
+
+    psSphere *sphere;
+    sphere = psSphereAlloc();
+    if ( !psMemCheckType(PS_DATA_SPHERE, sphere) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckSphere failed in memCheckType. \n");
+        psFree(sphere);
+        return 1;
+    }
+    psFree(sphere);
+
+    psSphereRot *sphereRot;
+    sphereRot = psSphereRotAlloc(0, 0, 20);
+    if ( !psMemCheckType(PS_DATA_SPHEREROT, sphereRot) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckSphereRot failed in memCheckType. \n");
+        psFree(sphereRot);
+        return 1;
+    }
+    psFree(sphereRot);
+
+    psSpline1D *spline;
+    spline = psSpline1DAlloc(2, 1, 0, 2);
+    if ( !psMemCheckType(PS_DATA_SPLINE1D, spline) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckSpline1D failed in memCheckType. \n");
+        psFree(spline);
+        return 1;
+    }
+    psFree(spline);
+
+    psStats *stats;
+    stats = psStatsAlloc(PS_STAT_MAX);
+    if ( !psMemCheckType(PS_DATA_STATS, stats) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckStats failed in memCheckType. \n");
+        psFree(stats);
+        return 1;
+    }
+    psFree(stats);
+
+    psTime *time;
+    time = psTimeAlloc(PS_TIME_UT1);
+    if ( !psMemCheckType(PS_DATA_TIME, time) )  {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckTime failed in memCheckType. \n");
+        psFree(time);
+        return 1;
+    }
+    psFree(time);
+
+    psVector *vector;
+    vector = psVectorAlloc(100, PS_TYPE_F32);
+    if ( !psMemCheckType(PS_DATA_VECTOR, vector) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psMemCheckVector failed in memCheckType. \n");
+        psFree(vector);
+        return 1;
+    }
+    psFree(vector);
+
+
+    psFree(negative);
+    psFree(neg);
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psString.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psString.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psString.c	(revision 22158)
@@ -0,0 +1,740 @@
+/** @file  tst_psString.c
+ *
+ * -*- mode: C; c-basic-indent: 4; tab-width: 8; indent-tabs-mode: nil -*-
+ * vim: set cindent ts=8 sw=4 expandtab:
+ *
+ *  @brief Test driver for psString functions
+ *
+ *  This test driver contains the following test points for psStringCopy
+ *  and psStringNCopy, and related string functions.
+ *    1) Verify string copy - psStringCopy
+ *    2) Verify empty string copy - psStringCopy
+ *    3) Verify string copy with length - psStringNCopy
+ *    4) Verify empty string copy with length - psStringNCopy
+ *    5) Copy string to larger string - psStringNCopy
+ *    6) Copy string with negative size - psStringNCopy
+ *    7) Verifiy creation of string literal - PS_STRING
+ *
+ *  Return:   Number of test points which failed
+ *
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.11 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2006-07-14 02:26:25 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include <string.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+
+#define STR_0 "binky had a leeeetle lamb"
+
+static psS32 testStringCopy00(void);
+static psS32 testStringCopy01(void);
+static psS32 testStringCopy02(void);
+static psS32 testStringCopy03(void);
+static psS32 testStringCopy04(void);
+//static psS32 testStringCopy05(void);
+static psS32 testStringCopy06(void);
+
+static psS32 testStrAppend00(void);
+static psS32 testStrAppend01(void);
+static psS32 testStrAppend02(void);
+static psS32 testStrAppend03(void);
+
+static psS32 testStrPrepend00(void);
+static psS32 testStrPrepend01(void);
+static psS32 testStrPrepend02(void);
+static psS32 testStrPrepend03(void);
+
+static psS32 testStrSplit00(void);
+static psS32 testNULLStrings(void);
+static psS32 testStrCheck(void);
+
+testDescription tests[] = {
+                              {testStringCopy00, 0, "Verify string copy", 0, false},
+                              {testStringCopy01, 1, "Verify empty string copy", 0, false},
+                              {testStringCopy02, 2, "Verify string copy with length", 0, false},
+                              {testStringCopy03, 3, "Verify empty string copy with length", 0, false},
+                              {testStringCopy04, 4, "Copy string to larger string", 0, false},
+                              //                              {testStringCopy05, 5, "Copy string with negative size", 0, false},
+                              {testStringCopy06, 6, "Verify creation of string literal", 0, false},
+
+                              {testStrAppend00,  7, "Verify generic string append", 0, false},
+                              {testStrAppend01,  8, "Test append NULL handling", 0, false},
+                              {testStrAppend02,  9, "Verify append string creation", 0, false},
+                              {testStrAppend03, 10, "Test append null-op", 0, false},
+
+                              {testStrPrepend00,11, "Verify generic string prepend", 0, false},
+                              {testStrPrepend01,12, "Test prepend NULL handling", 0, false},
+                              {testStrPrepend02,13, "Verify prepend string creation", 0, false},
+                              {testStrPrepend03,14, "Test prepend null-op", 0, false},
+                              {testStrSplit00,15, "Test String Splitting", 0, false},
+                              {testNULLStrings,666, "Test NULL String Error Handling", 0, false},
+                              {testStrCheck,16, "Test String Allocation and MemCheck", 0, false},
+                              {NULL}
+                          };
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetLevel( PS_LOG_INFO );
+
+    return ( ! runTestSuite( stderr, "psString", tests, argc, argv ) );
+}
+
+/*
+psS32 main( psS32 argc,
+          char * argv[] )
+{
+    psBool  tpResult = false;
+    char  stringval[20] = "E R R O R";
+    char  stringval1[20] = "e r r o r";
+    char  *stringvalnocopy = "F A I L";
+    char  *substringval = "e r r";
+    psS32   substringlen = 6;
+    char  *emptyval = "";
+    psS32   tpFails = 0;
+    char  *strResult;
+    psS32   increaseSize = 5;
+    psS32   negativeSize = -5;
+    psS32   result = 0;
+    psS32   result1 = 0;
+    psS32   memBlockAllocated = 0;
+    psMemBlock ***memBlockPtr = NULL;
+ 
+*/
+
+static psS32 testStringCopy00(void)
+{
+    char  stringval[20] = "E R R O R";
+    psS32   result = 0;
+    psS32   result1 = 0;
+    char  *strResult;
+
+    // Test point #1 Verify string copy - psStringCopy
+    strResult = psStringCopy(stringval);
+    // Perform string compare
+    result = strcmp(strResult, stringval);
+    // Modify original string
+    stringval[0]='G';
+    result1 = strcmp(strResult, stringval);
+    stringval[0]='E';
+    if ( ( result != 0 ) || ( result1 == 0) ) {
+        fprintf(stderr, "Failed test point #1 strcmp result = %d expected 0\n",result);
+        fprintf(stderr, "                               src = %s expected %s\n",
+                strResult, stringval);
+        fprintf(stderr, "             changed strcmp result = %d expected 1\n",result1);
+        fprintf(stderr, "             changed           src = %s expected %s\n",strResult,
+                stringval);
+        return 1;
+    }
+
+    // Free memory allocated
+    psFree(strResult);
+
+    return 0;
+}
+
+static psS32 testStringCopy01(void)
+{
+    char  *emptyval = "";
+    psS32   result = 0;
+    char  *strResult;
+
+    // Test point #2 Verify empty string copy - psStringCopy
+    strResult = psStringCopy(emptyval);
+    // Perform string compare
+    result = strcmp(strResult, emptyval);
+    if ( result != 0 ) {
+        fprintf(stderr,"Failed test point #2 strcmp result = %d expected 0\n",result);
+        fprintf(stderr,"                               src = %s expected %s\n",
+                strResult, emptyval);
+        return 1;
+    }
+
+    // Free memory allocated
+    psFree(strResult);
+
+    return 0;
+}
+
+static psS32 testStringCopy02(void)
+{
+    psS32   result = 0;
+    psS32   result1 = 0;
+    char  *strResult;
+    char  stringval1[20] = "e r r o r";
+    psS32   substringlen = 5;
+    char  *substringval = "e r r";
+
+    // Test point #3 Verify string copy with length - psStringNCopy
+    strResult = psStringNCopy(stringval1, substringlen);
+    // Perform string compare and get string length
+    result = strncmp(strResult, substringval, substringlen);
+    // Change original string
+    stringval1[0] = 'g';
+    result1 = strncmp(strResult, substringval, substringlen);
+    if ( ( result != 0 ) || ( result1 != 0 ) ) {
+        fprintf(stderr,"Failed test point #3 strcmp result = %d expected 0\n",result);
+        fprintf(stderr,"                               src = %s expected %s\n",
+                strResult, substringval);
+        fprintf(stderr,"             changed strcmp result = %d expected 0\n",result1);
+        fprintf(stderr,"                               src = %s expected %s\n",
+                strResult, substringval);
+        return 1;
+    }
+    // Free memory allocated
+    psFree(strResult);
+
+    return 0;
+}
+
+static psS32 testStringCopy03(void)
+{
+    psS32   result = 0;
+    psS32   result1 = 0;
+    char  *strResult;
+    char  *stringvalnocopy = "F A I L";
+
+    // Test point #4 Verify empty string copy with length - psStringNCopy
+    strResult = psStringNCopy(stringvalnocopy, 0);
+    // Perform string compare and get sting length
+    result = strcmp(strResult, stringvalnocopy);
+    result1 = strlen(strResult);
+    if ( result == 0 ) {
+        fprintf(stderr,"Failed test point #4 strcmp result = %d didn't expected %d\n",result,0);
+        fprintf(stderr,"                               src = %s didn't expected %s\n",
+                strResult, stringvalnocopy);
+        return 1;
+    }
+    // Free memory
+    psFree(strResult);
+
+    return 0;
+}
+
+static psS32 testStringCopy04(void)
+{
+    psS32   result = 0;
+    psS32   result1 = 0;
+    char  *strResult;
+    char  stringval[20] = "E R R O R";
+    psS32   increaseSize = 5;
+
+    // Test point #5 Copy string to larger string - psStringNCopy
+    strResult = psStringNCopy(stringval, (strlen(stringval) + increaseSize));
+    // Perform string compare and get string length
+    result = strcmp(strResult, stringval);
+    result1 = strlen(strResult);
+    // The strings should still compare
+    if ( ( result != 0 ) ||
+            ( result1 != strlen(stringval) ) ) {
+        fprintf(stderr,"Failed test point #5 strcmp result = %d expected %d\n",result,0);
+        fprintf(stderr,"                               src = %s expected %s\n",
+                strResult, stringval);
+        fprintf(stderr,"                     strlne result = %d expected %d\n",result1,
+                (psS32)strlen(stringval));
+        return 1;
+    }
+    // Free memory
+    psFree(strResult);
+
+    return 0;
+}
+
+// XXX This test needs to be modified to check for maximum size
+//     This will require a mod to psStringNCopy source to check for maximum size
+//
+//static psS32 testStringCopy05(void)
+//{
+//    char  *strResult;
+//    char  stringval[20] = "E R R O R";
+//    psS32   negativeSize = -5;
+//
+//    // Test point #6 Copy string with negative size - psStringNCopy
+//    strResult = psStringNCopy(stringval, negativeSize);
+//    if ( strResult != NULL ) {
+//        fprintf(stderr,"Failed test point #6 return value = %p expected NULL\n",
+//                strResult);
+//        return 1;
+//    }
+//    // Memory should not have been allocated
+//
+//    return 0;
+//}
+
+static psS32 testStringCopy06(void)
+{
+    char  *strResult;
+    char  stringval[20] = "E R R O R";
+    psS32   result = 0;
+
+    // Test point #7 Verify creation of string literal - PS_STRING
+    strResult = PS_STRING(E R R O R);
+    result = strcmp(strResult, stringval);
+    if ( result != 0 ) {
+        fprintf(stderr,"Failed test point #7 strcmp result = %d expected %d",result,0);
+        return 1;
+    }
+    // Memory should not have been allocated
+
+    return 0;
+}
+
+static psS32 testStrAppend00(void)
+{
+    char *str=NULL;
+    int result = 0;
+
+    str = psStringCopy("3.14159");
+
+    psStringAppend(&str, "%d%s", 2653589, "79323846");
+
+    // Test point: Verify string append
+    result = strcmp(str, "3.14159265358979323846");
+    if ( result != 0 ) {
+        fprintf(stderr,"%s","Failed test point\n");
+        return 1;
+    }
+
+    psFree(str);
+
+    return 0;
+}
+
+static psS32 testStrAppend01(void)
+{
+    ssize_t sz;
+    char *str=NULL;
+
+    // test nonsensical invocations ...
+    sz = psStringAppend(NULL, NULL);
+    if ( sz != 0 ) {
+        fprintf(stderr,"%s","Failed test point\n");
+        return 1;
+    }
+    sz = psStringAppend(&str, NULL);
+    if ( sz != 0 ) {
+        fprintf(stderr,"%s","Failed test point\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+static psS32 testStrAppend02(void)
+{
+    char *str=NULL;
+    int result;
+
+    // test string creation
+    psStringAppend(&str, "%s", "fubar");
+    result = strcmp(str, "fubar");
+    if ( result != 0 ) {
+        fprintf(stderr,"%s","Failed test point\n");
+        return 1;
+    }
+
+    psFree(str);
+
+    return 0;
+}
+
+static psS32 testStrAppend03(void)
+{
+    char *str=NULL;
+    int result;
+
+    str = psStringCopy(STR_0);
+
+    // test null-op
+    psStringAppend(&str, "");
+    result = strcmp(str, STR_0);
+    if ( result != 0 ) {
+        fprintf(stderr,"Failed test point str=[%s]\n", str);
+        return 1;
+    }
+
+    psFree(str);
+
+    return 0;
+}
+
+static psS32 testStrPrepend00(void)
+{
+    char *str=NULL;
+    int result = 0;
+
+    str = psStringCopy("79323846");
+
+    psStringPrepend(&str, "%s%d","3.14159", 2653589 );
+
+    // Test point: Verify string append
+    result = strcmp(str, "3.14159265358979323846");
+    if ( result != 0 ) {
+        fprintf(stderr,"%s","Failed test point\n");
+        return 1;
+    }
+
+    psFree(str);
+
+    return 0;
+}
+
+static psS32 testStrPrepend01(void)
+{
+    ssize_t sz;
+    char *str=NULL;
+
+    // test nonsensical invocations ...
+    sz = psStringPrepend(NULL, NULL);
+    if ( sz != 0 ) {
+        fprintf(stderr,"%s","Failed test point\n");
+        return 1;
+    }
+    sz = psStringPrepend(&str, NULL);
+    if ( sz != 0 ) {
+        fprintf(stderr,"%s","Failed test point\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+static psS32 testStrPrepend02(void)
+{
+    char *str=NULL;
+    int result;
+
+    // test string creation
+    psStringPrepend(&str, "%s", "fubar");
+    result = strcmp(str, "fubar");
+    if ( result != 0 ) {
+        fprintf(stderr,"%s","Failed test point\n");
+        return 1;
+    }
+
+    psFree(str);
+
+    return 0;
+}
+
+static psS32 testStrPrepend03(void)
+{
+    char *str=NULL;
+    int result;
+
+    str = psStringCopy(STR_0);
+
+    // test null-op
+    psStringPrepend(&str, "");
+    result = strcmp(str, STR_0);
+    if ( result != 0 ) {
+        fprintf(stderr,"Failed test point str=[%s]\n", str);
+        return 1;
+    }
+
+    psFree(str);
+
+    return 0;
+}
+
+static psS32 testStrSplit00(void)
+{
+    psList *strList = NULL;
+    char str[35];
+    char split[5];
+    strncpy(str, "This is, a, test case, to check.", 35);
+    strncpy(split, ",", 2);
+    psString psStr;
+    psString psSplit;
+    psStr = psStringCopy(str);
+    psSplit = psStringCopy(split);
+
+    //Return NULL for NULL inputs
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    strList = psStringSplit(NULL, NULL, true);
+    //    if (strList != NULL) {
+    if (strList) {
+        psFree(strList);
+        return 1;
+    }
+    psFree(strList);
+    strList = NULL;
+    //Return empty list for NULL string input
+    //psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    strList = psStringSplit(NULL, split, true);
+    //    if (strList != NULL) {
+    if ( psListLength(strList) ) {
+        psFree(strList);
+        return 2;
+    }
+    psFree(strList);
+    strList = NULL;
+    //Return NULL for NULL splitter input
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    strList = psStringSplit(str, NULL, true);
+    //    if (strList != NULL) {
+    if ( strList ) {
+        psFree(strList);
+        return 3;
+    }
+    psFree(strList);
+    strList = NULL;
+    //Return a psList* of psStrings
+    strList = psStringSplit(str, split, true);
+    if (strList->n != 4) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return the correct number of strings.\n");
+        return 4;
+    }
+    if ( strncmp((psString)(strList->head->data), "This is", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 5;
+    }
+    if ( strncmp((psString)(strList->head->next->data), " a", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 6;
+    }
+    if ( strncmp((psString)(strList->head->next->next->data), " test case", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 7;
+    }
+    if ( strncmp((psString)(strList->head->next->next->next->data), " to check.", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 8;
+    }
+    psFree(strList);
+    //Return correct psList when using (psString, char*)
+    strList = psStringSplit(psStr, split, true);
+    if (strList->n != 4) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return the correct number of strings.\n");
+        return 9;
+    }
+    if ( strncmp((psString)(strList->head->data), "This is", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 10;
+    }
+    if ( strncmp((psString)(strList->head->next->data), " a", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 11;
+    }
+    if ( strncmp((psString)(strList->head->next->next->data), " test case", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 12;
+    }
+    if ( strncmp((psString)(strList->head->next->next->next->data), " to check.", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 13;
+    }
+    psFree(strList);
+    //Return correct psList when using (char*, psString)
+    strList = psStringSplit(str, psSplit, true);
+    if (strList->n != 4) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return the correct number of strings.\n");
+        return 14;
+    }
+    if ( strncmp((psString)(strList->head->data), "This is", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 15;
+    }
+    if ( strncmp((psString)(strList->head->next->data), " a", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 16;
+    }
+    if ( strncmp((psString)(strList->head->next->next->data), " test case", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 17;
+    }
+    if ( strncmp((psString)(strList->head->next->next->next->data), " to check.", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 18;
+    }
+    psFree(strList);
+    //Return correct psList when using (psString, psString)
+    strList = psStringSplit(psStr, psSplit, true);
+    if (strList->n != 4) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return the correct number of strings.\n");
+        return 19;
+    }
+    if ( strncmp((psString)(strList->head->data), "This is", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 20;
+    }
+    if ( strncmp((psString)(strList->head->next->data), " a", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 21;
+    }
+    if ( strncmp((psString)(strList->head->next->next->data), " test case", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 22;
+    }
+    if ( strncmp((psString)(strList->head->next->next->next->data), " to check.", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 23;
+    }
+    psFree(strList);
+    //Return correct psList output for string of zero length case
+    strncpy(str, "This is,, a,, test case,, to check.", 35);
+    strList = psStringSplit(str, split, false);
+    if (strList->n != 4) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return the correct number of strings.\n");
+        return 24;
+    }
+    if ( strncmp((psString)(strList->head->data), "This is", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 25;
+    }
+    if ( strncmp((psString)(strList->head->next->data), " a", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 26;
+    }
+    if ( strncmp((psString)(strList->head->next->next->data), " test case", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 27;
+    }
+    if ( strncmp((psString)(strList->head->next->next->next->data), " to check.", 10) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psStringSplit failed to return expected strings.");
+        return 28;
+    }
+
+    psFree(strList);
+    psFree(psStr);
+    psFree(psSplit);
+    return 0;
+}
+
+static psS32 testNULLStrings(void)
+{
+    psString nullTest = NULL;
+    psString output = NULL;
+    ssize_t outSize = 0;
+    char** nullDest = NULL;
+    char** test;
+    //psStringCopy should return NULL for NULL input string
+    //    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    output = psStringCopy(nullTest);
+    if (output != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psStringCopy failed to return NULL for NULL input string.\n");
+        return 1;
+    }
+    //psStringNCopy should return NULL for NULL input string
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    output = psStringNCopy(nullTest, 100);
+    if (output != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psStringNCopy failed to return NULL for NULL input string.\n");
+        return 2;
+    }
+
+    //psStringAppend should return 0 for NULL input destination
+    outSize = psStringAppend(nullDest, "");
+    if (outSize != 0) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psStringAppend failed to return 0 for NULL input destination.\n");
+        return 3;
+    }
+    //psStringAppend should return 0 for NULL input format
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    outSize = psStringAppend(test, nullTest);
+    if (outSize != 0) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psStringAppend failed to return 0 for NULL input format.\n");
+        return 4;
+    }
+    //psStringPrepend should return 0 for NULL input destination
+    outSize = psStringPrepend(nullDest, " ");
+    if (outSize != 0) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psStringPrepend failed to return 0 for NULL input destination.\n");
+        return 3;
+    }
+    //psStringPrepend should return 0 for NULL input format
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    outSize = psStringPrepend(test, nullTest);
+    if (outSize != 0) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psStringPrepend failed to return 0 for NULL input format.\n");
+        return 4;
+    }
+    //psStringSplit should return empty list for NULL input string
+    psList *nullList = NULL;
+    // psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    nullList = psStringSplit(nullTest, ",", true);
+    //    if (nullList != NULL) {
+    if ( psListLength(nullList) ) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psStringSplit failed to return NULL for NULL input string.\n");
+        return 5;
+    }
+    psFree(nullList);
+    nullList = NULL;
+    //psStringSplit should return NULL for NULL input splitter
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    nullList = psStringSplit("Hello World", nullTest, true);
+    //    if (nullList != NULL) {
+    if ( nullList ) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psStringSplit failed to return NULL for NULL input splitter.\n");
+        return 6;
+    }
+    psFree(nullList);
+
+    return 0;
+}
+
+psS32 testStrCheck(void)
+{
+    psString str = NULL;
+    str = psStringAlloc(10);
+    strcpy(str, "Hello");
+    if (!psMemCheckString(str)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psString wasn't properly allocated!\n");
+        return 1;
+    }
+    if (!psMemCheckType(PS_DATA_STRING, str)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psString wasn't properly allocated!\n");
+        return 2;
+    }
+    psFree(str);
+
+    char charStr[10];
+    if (psMemCheckType(PS_DATA_STRING, charStr)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Input string is not a psDataType!!!  (Should have returned false)\n");
+        return 3;
+    }
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psTrace.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psTrace.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/sys/tst_psTrace.c	(revision 22158)
@@ -0,0 +1,381 @@
+/*****************************************************************************
+    This code will test whether trace levels can be set successfully.
+ 
+    XXX: For the last two testpoints, must verify that the results are
+    correct, and put that verification in the test as well.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+#include <fcntl.h>
+#include <unistd.h>
+
+
+static psS32 testTrace00(void);
+static psS32 testTrace01(void);
+static psS32 testTrace02(void);
+static psS32 testTrace03(void);
+static psS32 testTrace04(void);
+static psS32 testTrace05(void);
+static psS32 testTrace05a(void);
+static psS32 testTrace06(void);
+static psS32 testTrace08(void);
+
+testDescription tests[] = {
+                              {testTrace00, 0, "psTraceSetLevel() and psTraceGetLevel()", 0, false},
+                              {testTrace01, 1, "psTraceSetLevel(): set multiple components in one call", 0, false},
+                              {testTrace02, 2, "psTraceSetLevel(): test static/dynamic inheritance", 0, false},
+                              {testTrace03, 3, "psTraceReset()", 0, false},
+                              {testTrace04, 4, "psTrace()", 0, false},
+                              {testTrace05, 5, "psTracePrintLevels()", 0, false},
+                              {testTrace05a, 5, "optional leading dot and psTracePrintLevels()", 0, false},
+                              {testTrace06, 6, "Testing psTraceReset", 0, false},
+                              {testTrace08, 8, "Testing ", 0, false},
+                              {NULL}
+                          };
+
+testDescription tests2[] = {
+                               {testTrace08, 8, "Testing ", 0, false},
+                           };
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetLevel( PS_LOG_INFO );
+
+    return ( ! runTestSuite( stderr, "psTrace", tests, argc, argv ) );
+}
+
+static psS32 testTrace00(void)
+{
+    psS32 i;
+    psS32 lev = 0;
+
+    //    psTraceSetDestination(stderr);
+    psTraceSetDestination(2);
+
+    for (i=0;i<10;i++) {
+        (void)psTraceSetLevel(".", i);
+        lev = psTraceGetLevel(".");
+        if (lev != i) {
+            fprintf(stderr,"ERROR: (.) expected trace level was %d, actual was %d\n",
+                    i, lev);
+            return 1;
+        }
+    }
+    (void)psTraceSetLevel(".", 3);
+
+    for (i=5;i<10;i++) {
+        (void)psTraceSetLevel(".NODE00", i);
+        lev = psTraceGetLevel(".NODE00");
+        if (lev != i) {
+            fprintf(stderr,
+                    "ERROR: (.NODE00) expected trace level was %d, actual was %d\n",
+                    i, lev);
+            return 2;
+        }
+
+        lev = psTraceGetLevel(".");
+        if (lev != 3) {
+            fprintf(stderr,"ERROR: (.) expected trace level was %d, actual was %d\n",
+                    i, 3);
+            return 3;
+        }
+    }
+
+
+    (void)psTraceSetLevel(".NODE00.NODE01", 4);
+    for (i=0;i<10;i++) {
+        (void)psTraceSetLevel(".NODE00.NODE01", i);
+        lev = psTraceGetLevel(".NODE00.NODE01");
+        if (lev != i) {
+            fprintf(stderr,
+                    "ERROR: (.NODE00.NODE01) expected trace level was %d, actual was %d\n",
+                    i, lev);
+            return 4;
+        }
+    }
+
+    return 0;
+}
+
+static psS32 testTrace01(void)
+{
+    //    psTraceSetDestination(stderr);
+    psTraceSetDestination(2);
+    (void)psTraceSetLevel(".A.B.C.D.E", 5);
+
+    psTrace(".A.C.D.C",1,"You should not see this.\n");
+    psTrace(".A.B.C.D.E",2,"You should see this.\n");
+    psTrace(".A.B.C.D.E.F",3,"You should see this too.\n");
+
+    psTracePrintLevels();
+
+    return 0;
+}
+
+static psS32 testTrace02(void)
+{
+    psTraceReset();
+    //    psTraceSetDestination(stderr);
+    psTraceSetDestination(2);
+    psTraceSetLevel(".A.B", 2);
+    psTraceSetLevel(".A.B.C.D.E", 5);
+    psTracePrintLevels();
+    psTraceSetLevel(".A.B", 10);
+    psTracePrintLevels();
+
+    if (10 != psTraceGetLevel(".A.B.C")) {
+        fprintf(stderr,"ERROR: .A.B.C did not dynamically inherit a trace level (%d)\n",
+                psTraceGetLevel(".A.B.C"));
+        return 2;
+    }
+
+    if (10 != psTraceGetLevel(".A.B.C.D")) {
+        fprintf(stderr,"ERROR: .A.B.C.D did not dynamically inherit a trace level (%d)\n", psTraceGetLevel(".A.B.C.D"));
+        return 2;
+    }
+
+    if (5 != psTraceGetLevel(".A.B.C.D.E")) {
+        fprintf(stderr,"ERROR: .A.B.C.D.E did dynamically inherit a trace level (%d)\n", psTraceGetLevel(".A.B.C.D.E"));
+        return 2;
+    }
+
+    return 0;
+}
+
+static psS32 testTrace03(void)
+{
+    psS32 i = 0;
+    psS32 lev = 0;
+
+    //    psTraceSetDestination(stderr);
+    psTraceSetDestination(2);
+
+    for (i=0;i<10;i++) {
+        (void)psTraceSetLevel(".", i);
+        psTraceReset();
+
+        lev = psTraceGetLevel(".");
+        if (lev != PS_UNKNOWN_TRACE_LEVEL) {
+            fprintf(stderr,"ERROR: expected trace level was %d, actual was %d\n",
+                    PS_UNKNOWN_TRACE_LEVEL, lev);
+            return 1;
+        }
+    }
+    (void)psTraceSetLevel(".", 5);
+    (void)psTraceSetLevel(".a", 4);
+    (void)psTraceSetLevel(".a.b", 3);
+    (void)psTraceSetLevel(".a.b.c", 2);
+    if ((5 != psTraceGetLevel(".")) ||
+            (4 != psTraceGetLevel(".a")) ||
+            (3 != psTraceGetLevel(".a.b")) ||
+            (2 != psTraceGetLevel(".a.b.c"))) {
+        fprintf(stderr,"ERROR: trace successFlag = false;levels were not settable?\n");
+        return 2;
+    }
+
+    psTraceReset();
+    if ((PS_UNKNOWN_TRACE_LEVEL != psTraceGetLevel(".")) ||
+            (PS_UNKNOWN_TRACE_LEVEL != psTraceGetLevel(".a")) ||
+            (PS_UNKNOWN_TRACE_LEVEL != psTraceGetLevel(".a.b")) ||
+            (PS_UNKNOWN_TRACE_LEVEL != psTraceGetLevel(".a.b.c"))) {
+        fprintf(stderr,"ERROR: trace levels were not reset properly\n");
+        return 3;
+    }
+
+    return 0;
+}
+
+
+static psS32 testTrace04(void)
+{
+    int FD;
+    psS32 nb = 0;
+    FD = creat("tst_psTrace02_OUT", 0666);
+    //    printf("\nFD = %d\n", FD);
+    //    fp = fopen("tst_psTrace02_OUT", "w");
+    for (nb = 0 ; nb<4;nb++) {
+        if (nb == 0)
+            //            psTraceSetDestination(stdout);
+            psTraceSetDestination(1);
+        if (nb == 1)
+            //            psTraceSetDestination(stderr);
+            psTraceSetDestination(2);
+        if (nb == 2)
+            psTraceSetDestination(0); //NULL
+        if (nb == 3)
+            psTraceSetDestination(FD);
+
+        (void)psTraceSetLevel(".", 4);
+        psTrace(".", 5, "(0) This message should not be displayed (%x)\n",
+                0xbeefface);
+        (void)psTraceSetLevel(".", 7);
+        psTrace(".", 5, "(0) This message should be displayed (%x)\n",
+                0xbeefface);
+
+        (void)psTraceSetLevel(".a", 4);
+        psTrace(".a", 5, "(1) This message should not be displayed (%x)\n",
+                0xbeefface);
+        (void)psTraceSetLevel(".a", 7);
+        psTrace(".a", 5, "(1) This message should be displayed (%x)\n",
+                0xbeefface);
+
+
+        (void)psTraceSetLevel(".a.b", 4);
+        psTrace(".a.b", 5, "(2) This message should not be displayed (%x)\n",
+                0xbeefface);
+        (void)psTraceSetLevel(".a.b", 7);
+        psTrace(".a.b", 5, "(2) This message should be displayed (%x)\n",
+                0xbeefface);
+        (void)psTraceSetLevel(".a.b.c", 12);
+        psTrace(".a.b.c", 11, "(3) This message should be displayed (%x)\n",
+                0xbeefface);
+
+    }
+
+    close(FD);
+
+    return(0);
+}
+
+static psS32 testTrace05(void)
+{
+    //    psTraceSetDestination(stderr);
+    psTraceSetDestination(2);
+
+    (void)psTraceSetLevel(".", 9);
+
+    (void)psTraceSetLevel(".a", 8);
+    (void)psTraceSetLevel(".b", 7);
+    (void)psTraceSetLevel(".c", 5);
+
+    (void)psTraceSetLevel(".a.a", 4);
+    (void)psTraceSetLevel(".a.b", 3);
+
+    (void)psTraceSetLevel(".b.a", 2);
+    (void)psTraceSetLevel(".b.b", 1);
+
+    (void)psTraceSetLevel(".c.a", 0);
+    (void)psTraceSetLevel(".c.b", 3);
+    (void)psTraceSetLevel(".c.c", 5);
+
+    psTracePrintLevels();
+
+    return 0;
+
+}
+
+static psS32 testTrace05a(void)
+{
+    (void)psTraceSetLevel(".", 9);
+
+    (void)psTraceSetLevel("a", 8);
+    (void)psTraceSetLevel("b", 7);
+    (void)psTraceSetLevel("c", 5);
+
+    (void)psTraceSetLevel("a.a", 4);
+    (void)psTraceSetLevel("a.b", 3);
+
+    (void)psTraceSetLevel("b.a", 2);
+    (void)psTraceSetLevel("b.b", 1);
+
+    (void)psTraceSetLevel("c.a", 0);
+    (void)psTraceSetLevel("c.b", 3);
+    (void)psTraceSetLevel("c.c", 5);
+
+    psTracePrintLevels();
+
+    return 0;
+
+}
+
+static psS32 testTrace06(void)
+{
+    //    psTraceSetDestination(stderr);
+    psTraceSetDestination(2);
+
+    (void)psTraceSetLevel(".", 9);
+
+    (void)psTraceSetLevel(".a", 8);
+    (void)psTraceSetLevel(".b", 7);
+    (void)psTraceSetLevel(".c", 5);
+
+    (void)psTraceSetLevel(".a.a", 4);
+    (void)psTraceSetLevel(".a.b", 3);
+
+    (void)psTraceSetLevel(".b.a", 2);
+    (void)psTraceSetLevel(".b.b", 1);
+
+    (void)psTraceSetLevel(".c.a", 0);
+    (void)psTraceSetLevel(".c.b", 3);
+    (void)psTraceSetLevel(".c.c", 5);
+
+    psTraceReset();
+
+    if ((psTraceGetLevel(".")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".a")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".b")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".c")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".a.a")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".a.b")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".b.a")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".b.b")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".c.a")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".c.b")!=PS_UNKNOWN_TRACE_LEVEL) ||
+            (psTraceGetLevel(".c.c")!=PS_UNKNOWN_TRACE_LEVEL)) {
+        return 1;
+    }
+
+    return 0;
+}
+
+// Ensure that the leading dot in the component names are optional.
+static psS32 testTrace08(void)
+{
+    psTraceReset();
+    (void)psTraceSetLevel(".", 9);
+
+    (void)psTraceSetLevel(".a", 8);
+    (void)psTraceSetLevel(".b", 7);
+    (void)psTraceSetLevel(".c", 5);
+
+    (void)psTraceSetLevel(".a.a", 4);
+    (void)psTraceSetLevel(".a.b", 3);
+
+    (void)psTraceSetLevel(".b.a", 2);
+    (void)psTraceSetLevel(".b.b", 1);
+
+    (void)psTraceSetLevel(".c.a", 0);
+    (void)psTraceSetLevel(".c.b", 3);
+    (void)psTraceSetLevel(".c.c", 5);
+
+    psTracePrintLevels();
+
+    if ((psTraceGetLevel(".")!=9) ||
+            (psTraceGetLevel("a")!=8) ||
+            (psTraceGetLevel("b")!=7) ||
+            (psTraceGetLevel("c")!=5) ||
+            (psTraceGetLevel("a.a")!=4) ||
+            (psTraceGetLevel("a.b")!=3) ||
+            (psTraceGetLevel("b.a")!=2) ||
+            (psTraceGetLevel("b.b")!=1) ||
+            (psTraceGetLevel("c.a")!=0) ||
+            (psTraceGetLevel("c.b")!=3) ||
+            (psTraceGetLevel("c.c")!=5)) {
+        printf("psTraceGetLevel(.) is %d\n", psTraceGetLevel("."));
+        printf("psTraceGetLevel(a) is %d\n", psTraceGetLevel("a"));
+        printf("psTraceGetLevel(b) is %d\n", psTraceGetLevel("b"));
+        printf("psTraceGetLevel(c) is %d\n", psTraceGetLevel("c"));
+        printf("psTraceGetLevel(a.a) is %d\n", psTraceGetLevel("a.a"));
+        printf("psTraceGetLevel(a.b) is %d\n", psTraceGetLevel("a.b"));
+        printf("psTraceGetLevel(b.a) is %d\n", psTraceGetLevel("b.a"));
+        printf("psTraceGetLevel(b.b) is %d\n", psTraceGetLevel("b.b"));
+        printf("psTraceGetLevel(c.a) is %d\n", psTraceGetLevel("c.a"));
+        printf("psTraceGetLevel(c.b) is %d\n", psTraceGetLevel("c.b"));
+        printf("psTraceGetLevel(c.c) is %d\n", psTraceGetLevel("c.c"));
+
+        return 1;
+    }
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/.cvsignore	(revision 22158)
@@ -0,0 +1,13 @@
+.in
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+config.log
+config.status
+configure
+libtool
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/INSTALL
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/INSTALL	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/INSTALL	(revision 22158)
@@ -0,0 +1,8 @@
+Quick Installation
+
+    ./configure
+    make
+    make check
+    make install
+
+Run "configure --help" for additional options.
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/LICENSE
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/LICENSE	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/LICENSE	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/Makefile.am	(revision 22158)
@@ -0,0 +1,5 @@
+SUBDIRS  = src
+#SUBDIRS += tests
+
+prove:
+	prove -v -r
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/README
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/README	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/README	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/bootstrap.sh
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/bootstrap.sh	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/bootstrap.sh	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/compile
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/compile	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/compile	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/configure.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/configure.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/configure.in	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/src/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/src/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/src/.cvsignore	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/src/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/src/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/src/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/src/tap.3
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/src/tap.3	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/src/tap.3	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/src/tap.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/src/tap.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/src/tap.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/src/tap.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/src/tap.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/src/tap.h	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/.cvsignore	(revision 22158)
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/Makefile.am	(revision 22158)
@@ -0,0 +1,7 @@
+SUBDIRS=	diag
+SUBDIRS+=	fail
+SUBDIRS+=	ok
+SUBDIRS+=	pass
+SUBDIRS+=	plan
+SUBDIRS+=	skip
+SUBDIRS+=	todo
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/README
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/README	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/README	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/diag/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/diag/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/diag/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/diag/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/diag/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/diag/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/diag/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/diag/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/diag/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/diag/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/diag/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/diag/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/diag/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/diag/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/diag/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/fail/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/fail/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/fail/.cvsignore	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/fail/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/fail/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/fail/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/fail/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/fail/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/fail/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/fail/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/fail/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/fail/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/fail/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/fail/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/fail/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/.cvsignore	(revision 22158)
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/Makefile.am	(revision 22158)
@@ -0,0 +1,3 @@
+SUBDIRS  =	ok
+SUBDIRS +=	ok-hash
+SUBDIRS +=	ok-numeric
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-hash/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-hash/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-hash/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-hash/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-hash/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-hash/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-hash/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-hash/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-hash/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-hash/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-hash/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-hash/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-hash/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-hash/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-hash/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-numeric/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-numeric/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-numeric/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-numeric/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-numeric/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-numeric/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-numeric/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-numeric/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-numeric/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-numeric/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-numeric/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-numeric/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-numeric/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-numeric/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok-numeric/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/ok/ok/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/pass/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/pass/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/pass/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/pass/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/pass/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/pass/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/pass/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/pass/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/pass/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/pass/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/pass/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/pass/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/pass/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/pass/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/pass/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/.cvsignore	(revision 22158)
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no-tests/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no-tests/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no-tests/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no-tests/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no-tests/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no-tests/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no-tests/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no-tests/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no-tests/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no-tests/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no-tests/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no-tests/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no-tests/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no-tests/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no-tests/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no_plan/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no_plan/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no_plan/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no_plan/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no_plan/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no_plan/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no_plan/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no_plan/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no_plan/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no_plan/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no_plan/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no_plan/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no_plan/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no_plan/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/no_plan/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/not-enough-tests/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/not-enough-tests/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/not-enough-tests/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/not-enough-tests/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/not-enough-tests/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/not-enough-tests/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/not-enough-tests/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/not-enough-tests/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/not-enough-tests/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/not-enough-tests/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/not-enough-tests/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/not-enough-tests/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/not-enough-tests/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/not-enough-tests/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/not-enough-tests/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/sane/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/sane/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/sane/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/sane/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/sane/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/sane/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/sane/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/sane/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/sane/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/sane/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/sane/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/sane/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/sane/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/sane/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/sane/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/skip_all/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/skip_all/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/skip_all/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/skip_all/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/skip_all/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/skip_all/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/skip_all/plan.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/skip_all/plan.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/skip_all/plan.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/skip_all/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/skip_all/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/skip_all/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/skip_all/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/skip_all/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/skip_all/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/skip_all/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/skip_all/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/skip_all/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-plans/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-plans/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-plans/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-plans/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-plans/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-plans/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-plans/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-plans/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-plans/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-plans/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-plans/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-plans/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-plans/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-plans/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-plans/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-tests/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-tests/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-tests/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-tests/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-tests/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-tests/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-tests/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-tests/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-tests/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-tests/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-tests/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-tests/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-tests/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-tests/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/plan/too-many-tests/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/skip/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/skip/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/skip/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/skip/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/skip/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/skip/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/skip/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/skip/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/skip/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/skip/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/skip/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/skip/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/skip/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/skip/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/skip/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/todo/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/todo/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/todo/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/todo/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/todo/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/todo/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/todo/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/todo/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/todo/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/todo/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/todo/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/todo/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/todo/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/todo/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/tap/tests/todo/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psLib/test/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/test.pl	(revision 22158)
@@ -0,0 +1,31 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: test.pl,v 1.2 2006-09-12 20:27:07 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all);
+
+use vars qw($VERSION);
+$VERSION = '0.01';
+
+use File::Find::Rule;
+use Cwd;
+
+my $rule = File::Find::Rule->new;
+# ignore .lib directories
+$rule->or($rule->new
+        ->directory
+        ->name('.libs')
+        ->prune
+        ->discard,
+        $rule->new
+    );
+$rule->name(qr/^tap_[^.]*$/)
+        ->maxdepth(2)
+        ->relative;
+
+my @test_files = $rule->in(getcwd());
+
+system("prove @test_files");
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/.cvsignore	(revision 22158)
@@ -0,0 +1,79 @@
+temp
+.deps
+.libs
+Makefile
+Makefile.in
+header_1.fits
+header_2.fits
+mdcfgwrt.out
+table10.dat
+table2.dat
+table3.dat
+tableF32.dat
+tableS32.dat
+tableU8.dat
+test.config
+test1.config
+test2.config
+test3.config
+test4.config
+test5.config
+tst_psArray
+tst_psBitSet
+tst_psHash00
+tst_psHash01
+tst_psHash02
+tst_psHash03
+tst_psHash04
+tst_psHash05
+tst_psList
+tst_psLookupTable_01
+tst_psMetadataIO
+tst_psMetadata_01
+tst_psMetadata_02
+tst_psMetadata_03
+tst_psMetadata_04
+tst_psMetadata_05
+tst_psMetadata_06
+tst_psMetadata_07
+tst_psPixels
+MDCopy.in
+MDCopy.out
+tst_psArguments
+mdcfgwrt.verified
+
+tap_psListIterator
+tap_psMetadataIterator
+tap_psMetadataConfigParse
+tap_psMetadataConfigParse.config
+*.bb
+*.bbg
+*.da
+gmon.out
+
+tap_psArguments_all
+tap_psArray_all
+tap_psBitSet_all
+tap_psHash_845
+tap_psHash_all
+tap_psList_all
+tap_psLookupTable_all
+tap_psMetadataConfigFormat
+tap_psMetadataConfigParse_time
+tap_psMetadataConfigPrint
+tap_psMetadataConfigRead
+tap_psMetadataConfigWrite
+tap_psMetadataConfig_input
+tap_psMetadataConfig_output
+tap_psMetadataItemCompare
+tap_psMetadataItemParse
+tap_psMetadata_copying
+tap_psMetadata_creating
+tap_psMetadata_manip
+tap_psMetadata_polynomials
+tap_psMetadata_printing
+tap_psPixels_all
+
+tap_psMetadataUpdate
+tap_psMetadataOverlay
+tap_psTree
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/Makefile.am	(revision 22158)
@@ -0,0 +1,112 @@
+AM_CPPFLAGS = \
+	$(SRCINC) \
+	-I$(top_srcdir)/test/tap/src \
+	-I$(top_srcdir)/test/pstap/src \
+	$(PSLIB_CFLAGS)
+AM_LDFLAGS = \
+	$(top_builddir)/src/libpslib.la  \
+	$(top_builddir)/test/tap/src/libtap.la \
+	$(top_builddir)/test/pstap/src/libpstap.la \
+	$(PSLIB_LIBS)
+AM_CFLAGS = -DXML_CONFIG_FILE="\"$(top_srcdir)/etc/pslib/psTime.xml\""
+
+TEST_PROGS = \
+	tap_psMetadataIterator \
+	tap_psListIterator \
+	tap_psMetadataConfigRead \
+	tap_psMetadataConfigParse_time \
+	tap_psMetadataItemCompare \
+	tap_psMetadataItemParse \
+	tap_psMetadataUpdate \
+	tap_psMetadataOverlay \
+	tap_psMetadata_printing \
+	tap_psMetadata_copying \
+	tap_psMetadata_creating \
+	tap_psMetadata_manip   \
+	tap_psMetadata_polynomials \
+	tap_psArray_all \
+	tap_psArguments_all \
+	tap_psPixels_all \
+	tap_psHash_all \
+	tap_psBitSet_all \
+	tap_psList_all \
+	tap_psLookupTable_all \
+	tap_psMetadataConfigWrite \
+	tap_psMetadataConfigPrint \
+	tap_psMetadataConfigParse \
+	tap_psMetadataConfigFormat \
+	tap_psMetadataConfig_input \
+	tap_psHash_845	\
+	tap_psTree
+
+if BUILD_TESTS
+bin_PROGRAMS = $(TEST_PROGS)
+TESTS = $(TEST_PROGS)
+else
+check_PROGRAMS = $(TEST_PROGS)
+endif
+
+EXTRA_DIST = \
+	data/header_1.fits \
+	data/header_2.fits \
+	data/mdcfgwrt.verified \
+	data/test.config \
+	data/test1.config \
+	data/test2.config \
+	data/test3.config \
+	data/test4.config \
+	data/test5.config
+
+tmp_files = \
+	header_1.fits \
+	header_2.fits \
+	mdcfgwrt.verified \
+	test.config \
+	test1.config \
+	test2.config \
+	test3.config \
+	test4.config \
+	test5.config
+
+CLEANFILES = $(tmp_files) multi.fits table.fits temp/* MDCopy.in MDCopy.out mdcfgwrt.out \
+	core core.* *~ *.bb *.bbg *.da gmon.out
+
+tests: $(check_PROGRAMS)
+	$(top_srcdir)/test/test.pl
+
+# XXX what is the point of verbatim copying these files?
+
+%.dat: verified/%.dat
+	cp $? $@
+
+%.config: $(srcdir)/data/%.config
+	cp $? $@
+
+#test.config: $(srcdir)/data/test.config
+#	cp $? $@
+
+#test1.config: $(srcdir)/data/test1.config
+#	cp $? $@
+
+#test2.config: $(srcdir)/data/test2.config
+#	cp $? $@
+
+#test3.config: $(srcdir)/data/test3.config
+#	cp $? $@
+
+#test4.config: $(srcdir)/data/test4.config
+#	cp $? $@
+
+#test5.config: $(srcdir)/data/test5.config
+#	cp $? $@
+
+#header_1.fits: $(srcdir)/data/header_1.fits
+#	cp $? $@
+
+#header_2.fits: $(srcdir)/data/header_2.fits
+#	cp $? $@
+
+mdcfgwrt.verified: $(srcdir)/data/mdcfgwrt.verified
+	cp $? $@
+
+test: check
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/header_1.fits
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/header_1.fits	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/header_1.fits	(revision 22158)
@@ -0,0 +1,1 @@
+SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                    8 / number of bits per data pixel                  NAXIS   =                    0 / number of data axes                            HISTORY File modified by user 'harman' with fv  on 2004-08-04T11:11:18          END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/header_2.fits
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/header_2.fits	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/header_2.fits	(revision 22158)
@@ -0,0 +1,1 @@
+SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                  -64 / number of bits per data pixel                  NAXIS   =                    1 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -64 / number of bits per data pixel                  NAXIS   =                    1 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     BITPIX  =                  -64 / number of bits per data pixel                  EXTNAME = 'MY_DATA_1'                                                           HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:14:45          HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:15:29          HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:21:18          HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:21:46          END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -64 / number of bits per data pixel                  NAXIS   =                    1 / number of data axes                            NAXIS1  =                   64 / length of data axis 1                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     EXTNAME = 'MY_DATA_2'                                                           HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:22:12          HISTORY File modified by user 'harman' with fv  on 2004-08-04T13:22:52          END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/mdcfgwrt.verified
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/mdcfgwrt.verified	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/mdcfgwrt.verified	(revision 22158)
@@ -0,0 +1,18 @@
+item1 BOOL  TRUE #I am a boolean 
+item2 S32  55  
+item3 F32  3.14  
+item4 F64  6.28  
+item5 STR  GNIRTS  #I am a string 
+@vector6 S32 1 2 3 4 5  #I am a vector 
+time01 PS_TIME_TAI  1000, 25, T  #I am time 
+
+metadata7  METADATA  
+   ITEM01 S32  666  
+   META NEW  METADATA  
+      @VECTORNEW S32 1 2 3 4 5  #Newest VECTOR 
+      cell STR  pStArRs  #I am a p-Star 
+   END   #I AM Newest METADATA
+   ITEM02 F32  666.6  #I AM FLOAT 
+   ITEM03 F64  666.666  #I AM DOUBLE 
+END   #I am a metadata
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/test.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/test.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/test.config	(revision 22158)
@@ -0,0 +1,128 @@
+##########################################################################################################
+#  test.config
+#
+#  This is a sample metadata configuration file used to test the metadata configuration file parser. 
+#  It tests both positive and negative cases as described in the comments below.
+#
+#  author  Ross Harman, MHPCC
+#
+#  version $Revision: 1.1 $  $Name: not supported by cvs2svn $
+#  date  $Date: 2005-07-13 02:47:01 $
+#
+#  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+##########################################################################################################
+#
+#
+#
+########## Test 1 ##########
+# Lines beginning with # are comments. The line below, as well as those above are comments. They should be ignored by the parser.
+# I am a comment.
+#
+#
+#
+########## Test 2 ##########
+# The line below is a comment that begins with some whitespace. It should be ignored by the parser.
+      #        		Another comment
+#
+#
+#
+########## Test 3 ##########
+# The line below is completely blank except for a carriage return. It should be ignored by the parser.
+
+#
+#
+#
+########## Test 4 ##########
+# The line below consists of spaces and tabs (whitespace). It should be ignored by the parser.
+     	   			                    
+#
+#
+#
+########## Test 5 ##########
+# The line below consists of a variable name, type, value, and trailing comment. It should be read by the parser
+pi          F64         3.1415926535897932384626433832795029        # Definition of pi
+#
+#
+#
+########## Test 6 ##########
+# The line below consists of a variable name, type, and value, but without a trailing comment. It should be read by the parser.
+altitude          S32         10000   
+#
+#
+#
+########## Test 7 ##########
+# The lines below contain variations in name, type, value, trailing comment, and whitespace. They should all be read by the parser.
+   time F32 1234.5678 
+ myBool     BOOL            F           # F, f, 0, T, t, 1 are also acceptable
+title1  STR   Hello world #This is a comment for the string value
+    title2  STRING   Good bye world   #    STRING or STR may be used as the string type 
+#
+#
+#
+########## Test 8 ##########
+# The line below creates a vector. It should be read by the parser.
+@primes     S32     2, 3, 5, 7, 11, 13, 17   # These are prime numbers
+#
+#
+#
+########## Test 9 ##########
+# The line below creates a vector with commas mixed with spaces in the values. It should be read by the parser.
+@negatives  S32     -1,  -2 -3    -4, -5, -6,      -7
+#
+#
+#
+########## Test 10  ##########
+# The lines below should create a folder node with children that are strings. They should be read by the parser.
+comment *STR This
+comment *STR     is
+comment *STR         an
+comment *STR             ugly
+comment *STR                 comment
+comment *STR                         but
+comment *STR                             still
+comment *STR                                 valid
+#
+#
+#
+########## Test 11  ##########
+# The line below contains an incorrect value. It should produce an error.
+xPosition    F64          9876.54qqq32
+#
+#
+#
+########## Test 12  ##########
+# The line below contains no value. It should produce an error.
+yPosition    F64          
+#
+#
+#
+########## Test 13  ##########
+# The line below contains no type. It should produce an error.
+zPosition       99.999          
+#
+#
+#
+########## Test 14  ##########
+# The line below contains two * characters. It should produce an error.
+aPosition   **          
+#
+#
+#
+########## Test 15 ##########
+# The line below contains two @ characters. It should produce an error.
+@@bPosition     F64     22.33             
+#
+#
+#
+########## Test 16 ##########
+# The line below contains a ~ character used for special processing. It should produce an error.
+range     F64     140.0 ~             
+#
+#
+#
+########## Test 17 ##########
+# The variable name below is repeated. It should produce an error if the overwrite function argument is set to false.
+# If overwrite is true, then the last name and value will be stored and there will be no error.
+speed     F32     55.55
+speed     F32     66.66
+             
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/test1.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/test1.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/test1.config	(revision 22158)
@@ -0,0 +1,57 @@
+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 MULTI # 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
+
+boolean1  BOOL   F # The value of 'boolean' is 'false'
+
+@negprimes S8 -2, -3, -5, -7,-11,-13,-17,-19
+
+@vector1 U16  0, 1, 2, 4, 8
+@vector2 U32  0, 8, 16, 32, 64, 128
+@vector3 U64  0, 64, 256,
+
+@vector4 S16  -2 -1 0 1 2
+@vector5 S32  -4, -2, 0, 2, 4, 6
+@vector6 S64  -16, -4, 0, 4 16 36 64
+
+@vector7 F32  -1.03, 1.04, -1.05, 1.06
+@vector8 F64  -2.22, 2.21 -2.20, 2.19, -2.18
+
+TYPE	CELL	EXTNAME		BIASSEC		CHIP       #
+CELL.00	CELL	CCD00		BSEC-00		CHIP.00
+CELL.01	CELL	CCD01		BSEC-01		CHIP.00
+
+MYCELL  MULTI
+MYCELL    METADATA
+  EXTNAME   STR   CCD00
+  BIASSEC   STR   BSEC-00
+  CHIP      STR   CHIP.00
+  NCELL     S32   24
+END
+MYCELL S32 123 # A number
+
+cell  METADATA
+   foo   METADATA
+       bar     STR   BAZ
+       ping    STR   PONG
+   END
+
+   EXTNAME   STR CCD00
+   BIASSEC   STR BSEC-00
+   CHIP      STR CHIP.00
+   NCELL     S32 12
+END
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/test2.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/test2.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/test2.config	(revision 22158)
@@ -0,0 +1,44 @@
+ # This should generate error message
+boolean     BOOL    X # The value of 'boolean' is 'true'
+
+value1    S32  # No value
+
+# Invalid vector entries
+@vector  U8
+@vector1 U8  x,y,z
+@vector2
+@vector3 F8 ,,,
+
+# Multiple MULTI definitions
+comment MULTI
+comment MULTI
+
+# Type CELL not defined
+MYCELL CELL CCD00 BSEC-00 CHIP.00
+
+# Invalid value entries
+value1   F64   aabb
+value2   S32   ccdd
+
+# Repeated vector character
+@@vector4 U8 1 2 3 4 #
+
+# Invalid TYPE line
+TYPE
+
+# Duplicate TYPE
+TYPE CELL EXTNAME BIASSEC CHIP
+TYPE CELL EXTNAME BIASSEC CHIP
+
+# END with no matching METADATA
+END
+
+# Duplicate item names within metadata type specifier
+TYPE NEWCELL VALUE1 VALUE1 #
+
+# Not enough values in specified type
+OURCELL  CELL CCD00
+
+# Type with no item
+TYPE NEWCELL1
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/test3.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/test3.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/test3.config	(revision 22158)
@@ -0,0 +1,16 @@
+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 MULTI # 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: /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/test4.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/test4.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/test4.config	(revision 22158)
@@ -0,0 +1,161 @@
+#
+# This file contains examples from SDR-14 appendix A
+#
+CELL1 METADATA
+  EXTNAME  STR  CCD00
+  BIASSEC  STR  BSEC-00
+  CHIP     STR  CHIP.00
+  NCELL    S32  24
+END
+
+CELL2 METADATA
+   FOO METADATA
+       BAR   STR  BAZ
+       PING  STR  PONG
+   END
+
+   EXTNAME   STR  CCD00
+   BIASSEC   STR  BSEC-00
+   CHIP      STR  CHIP.00
+   NCELL     S32  24
+END
+
+FOO1 METADATA
+    FOO2 METADATA
+        FOO3 METADATA
+            FOO4 METADATA
+                FOO5 METADATA
+                    FOO6 METADATA
+                        BAR    STR   BAZ
+                        PING   STR   PONG
+                    END
+                    BAR   STR  BAZ
+                    PING  STR  PONG
+                END
+                BAR   STR  BAZ
+                PING  STR  PONG
+            END
+            BAR   STR   BAZ
+            PING  STR   PONG
+        END
+        BAR   STR  BAZ
+        PING  STR  PONG
+    END
+    BAR   STR  BAZ
+    PING  STR  PONG
+END
+
+FOO2 METADATA
+    BAR   STR  BAZ
+    PING  STR  PONG
+    FOO3 METADATA
+        BAR  STR  BAZ
+        PING STR  PONG
+        FOO4 METADATA
+            BAR  STR  BAZ
+            PING STR  PONG
+            FOO5 METADATA
+                BAR  STR BAZ
+                PING STR PONG
+                FOO6 METADATA
+                    BAR  STR  BAZ
+                    PING STR  PONG
+                    FOO7  METADATA
+                        BAR  STR BAZ
+                        PING STR PONG
+                    END
+                END
+            END
+        END
+    END
+END
+
+FOO3 METADATA
+    BAR  STR  BAZ
+    FOO4 METADATA
+        BAR  STR  BAZ
+        FOO5 METADATA
+            BAR  STR  BAZ
+            FOO6 METADATA
+                BAR   STR  BAZ
+                FOO7 METADATA
+                    BAR   STR   BAZ
+                    FOO8 METADATA
+                        BAR   STR  BAZ
+                        PING  STR  PONG
+                    END
+                    PING  STR  PONG
+                END
+                PING STR  PONG
+            END
+            PING STR  PONG
+        END
+        PING STR PONG
+    END
+    PING STR PONG
+END
+
+FOO4 METADATA
+    FOO5 METADATA
+        BAR  STR  BAZ
+        PING STR  PONG
+    END
+    FOO6 METADATA
+        BAR  STR  BAZ
+        PING STR  PONG
+    END
+END
+
+TYPE    CELL    EXTNAME   BIASSEC   CHIP
+CELL.00  CELL  CCD00  BSEC-00 CHIP.00
+CELL.01  CELL  CCD01  BSEC-01 CHIP.00
+FOO5 METADATA
+    TYPE CELL EXTNAME BIASSEC
+    CELL.00 CELL CCD00 BSEC-00
+    CELL.01 CELL CCD01 BSEC-01
+    FOO6 METADATA
+        TYPE CELL EXTNAME
+        CELL.00  CELL  CCD00
+        CELL.01  CELL  CCD01
+    END
+END
+
+foo MULTI
+foo S32   -1
+foo STR   bar baz
+foo BOOL  T
+
+foo1 MULTI        # foo
+foo1 S32  -1      # bar
+foo1 STR  bar baz # baz
+foo1 BOOL T       #
+
+foo2 MULTI
+foo2 S32 -1
+foo2 STR  bar baz
+foo2 BOOL  T
+bar1 METADATA
+    foo MULTI
+    foo S32  -1
+    foo STR  bar baz
+    foo BOOL T
+END
+
+foo3 MULTI
+foo3 METADATA
+    bar   BOOL T
+END
+foo3 METADATA
+    bar  BOOL T
+END
+
+foo4 MULTI
+TYPE bar a b c
+foo4 bar x y z
+foo4 bar x y z
+
+TYPE bar1 a b c
+foo5 MULTI
+foo5 bar1 x y z
+foo5 bar1 x y z
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/test5.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/test5.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/data/test5.config	(revision 22158)
@@ -0,0 +1,32 @@
+#
+# Examples from SDR-14 Appendix A which cause failures
+#
+TYPE  CELL1  EXTNAME  BIASSEC  CHIP
+FOO1 METADATA
+    CELL.00 CELL  CCD00  BSEC-00  CHIP.00
+END
+
+FOO2  METADATA
+    TYPE CELL2 EXTNAME BIASSEC CHIP
+END
+CELL.00 CELL2 CCD00 BSEC-00 CHIP.00
+
+FOO3 METADATA
+    TYPE CELL3 EXTNAME BIASSEC CHIP
+END
+BAR METADATA
+    CELL.00 CELL3 CCD00 BSEC-00 CHIP.00
+END
+
+TYPE CELL4 EXTNAME BIASSEC CHIP
+CELL.00 CELL4 CCD00 BSEC-00
+CELL.01 CELL4 CCD01 BSEC-01 CHIP.00
+
+TYPE CELL5 EXTNAME BIASSEC CHIP
+TYPE CELL5 EXTNAME BIASSEC CHIP
+CELL.02 CELL5 CCD00 BSEC-00 CHIP.00
+CELL.03 CELL5 CCD01 BSEC-01 CHIP.00
+
+CELL.04 CELL6 CCD00 BSEC-00 CHIP.00
+CELL.05 CELL6 CCD01 BSEC-01 CHIP.00
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/execute_tap
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/execute_tap	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/execute_tap	(revision 22158)
@@ -0,0 +1,21 @@
+make test
+./tap_psArray_all
+./tap_psListIterator
+./tap_psMetadataConfigParse_time
+./tap_psMetadataConfigRead
+./tap_psMetadata_copying
+./tap_psMetadata_creating
+./tap_psMetadataItemCompare
+./tap_psMetadataItemParse
+./tap_psMetadataIterator
+./tap_psMetadata_manip
+./tap_psMetadata_printing
+./tap_psMetadata_polynomials
+./tap_psArguments_all
+./tap_psPixels_all
+./tap_psHash_all
+./tap_psBitSet_all
+./tap_psList_all
+./tap_psLookupTable_all
+./tap_psMetadataConfig_output
+./tap_psMetadataConfig_input
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/metaconf.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/metaconf.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/metaconf.in	(revision 22158)
@@ -0,0 +1,90 @@
+#
+# Good lines
+#
+
+item1            BOOL      T                # I am a boolean
+item2            S32       55               # I am int
+item3            F32       3.14
+item4            F64       6.28             # I am float
+item5            STR       GNIRTS           # I am a string
+item7            S64       555
+item8            S8        3
+itemu1           U16       2
+itemu2           U32       55
+itemu3           U8        1
+itemu4           U64       1634
+item9            BOOL      F                # I am a boolean2
+item10           S16       16
+@vector1  S8  1 2 3 4 5   # I am a vector
+@vector2  S16 1 2 3 4 5
+@vector3  S32 1 2 3 4 5
+@vector4  S64 1 2 3 4 5
+@vector5  U8  1 2 3 4 5   # I am a vector
+@vector6  U16 1 2 3 4 5
+@vector7  U32 1 2 3 4 5
+@vector8  U64 1 1
+@vector9  F32 1.0 2.3 3.1 4.5 5.0   # I am a vector
+@vector10 F64 1.0 2.0 3.0 4.0 5.0
+time01           TT        1970-01-01T00:16:39Z  # I am time
+time02           UTC       NULL     # I am time2
+
+f32 MULTI
+f32              S32       666              # f32_1
+f32              S32       665              # f32_2
+
+f32 METADATA
+    newi S32 151
+END
+
+metanew MULTI
+meta1 METADATA
+    itemS32   S32       666              # f32_1
+END
+
+metadata7  METADATA
+   ITEM01           S32       666
+   META_NEW  METADATA
+      @VECTORNEW S32 1 2 3 4 5   # Newest VECTOR
+      cell             STR       pStArRs          # I am a p-Star
+   END  # I am a metadata
+   ITEM02           F32       666.6            # I AM FLOAT
+   ITEM03           F64       666.666          # I AM DOUBLE
+END
+#item11           C32       16+2i            # I am Complex
+
+TYPE PS_TYPE_DD D
+DD2     PS_TYPE_DD   ""
+     TYPE  C32  3
+newC32      C32 7i+5
+
+#
+# Bad lines : 28 (-1 for the GOOD line in meta1) & 3 valid duplicates
+#
+item1            BOOL      F                # duplicate
+item8            S8        5                # duplicate
+item4-1          F64       6.28 1           # I am float
+item6            S32       10 1
+item6-1          S32       ~
+item7-1          S64       555 x
+item8-1          S8        5 1
+itemu1-1         U16       2 1
+itemu2-1         U32       55 1
+itemu3-1         U8        1 2
+itemu4-1         U64       1634 1
+item10-1         S16       16 16
+@vector1-1 S8 % #
+@@@vector12 F64 1.0 2.0 3.0 4.0 5.0
+@vector11 C64 1.0 2.0 3.0 4.0 5.0
+meta1 METADATA                              # duplicate
+    M2   S32       666  # this line is "GOOD" but parsed in the top level
+END
+newDD   PS_TYPE_DD
+TYPE            1
+TYPE
+TYPE         #  # 1
+     TYPE  C32  3
+     TYPE PS_TYPE_C32 2                 #
+newC32      PS_TYPE_C32 7i+5        # duplicate but with borken type
+ps1  S32  NAN
+f32 MULTI
+\n
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/table.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/table.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/table.dat	(revision 22158)
@@ -0,0 +1,9 @@
+#  Table with valid types and index-values
+#
+#psF32     psU16    psU32     psU64    psS8    psS16    psS32    psS64    psU8   psF64
+-10.05    2        4         8        0       -2       -4       -8       5      -1.5
+ 1.009     4        8         16       -1      -4       -8       -16      0      -1.0
+23.45     6        12        24       -2      -6       -12      -24      5      -0.25
+3500.67   8        16        32       -3      -8       -16      -32      75     1.75
+   
+#
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/table2.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/table2.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/table2.dat	(revision 22158)
@@ -0,0 +1,9 @@
+#  Table with valid types and index-values
+#
+#psF32     psU16    psU32     psU64    psS8    psS16    psS32    psS64    psU8   psF64
+-10.05    2        4         8        0       -2        1       -8       5      -1.5
+ 1e-20     4        8         16       -1      -4       1       -16      0      -1.0
+2e-20     6        12        24       -2      -6        1       -24      5      -0.25
+3500.67   8        16        32       -3      -8        1      -32      75     1.75
+
+#
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/table3.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/table3.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/table3.dat	(revision 22158)
@@ -0,0 +1,9 @@
+#
+# This file is not valid metdataconfig syntax
+#
+#psF32     psU16    psU32     psU64    psS8    psS16    psS32    psS64    psU8   psF64
+-10.05    2        4         8        0       -2       -4       -8       5      -1.5
+ 1.009     4        8         16       -1      -4       -8       -16      0      -1.0
+23.45     6
+
+#
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tableF32_err.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tableF32_err.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tableF32_err.dat	(revision 22158)
@@ -0,0 +1,9 @@
+#  Table with valid types and index-values
+#
+#psF32     psU16    psU32     psU64    psS8    psS16    psS32    psS64    psU8   psF64
+-10.05    2        4         8        0       -2       -4       -8       5      -1.5
+ k.009     4        8         16       -1      -4       -8       -16      0      -1.0
+23.45     6        12        24       -2      -6       -12      -24      5      -0.25
+3500.67   8        16        32       -3      -8       -16      -32      75     1.75
+   
+#
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tableF64_err.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tableF64_err.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tableF64_err.dat	(revision 22158)
@@ -0,0 +1,9 @@
+#  Table with valid types and index-values
+#
+#psF32     psU16    psU32     psU64    psS8    psS16    psS32    psS64    psU8   psF64
+-10.05    2        4         8        0       -2       -4       -8       5      -1.5  #
+ 1.009     4        8         16       -1      -4       -8       -16      0      -1.k
+23.45     6        12        24       -2      -6       -12      -24      5      -0.25
+3500.67   8        16        32       -3      -8       -16      -32      75     1.75
+
+#
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tableS32_err.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tableS32_err.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tableS32_err.dat	(revision 22158)
@@ -0,0 +1,9 @@
+#  Table with valid types and index-values
+#
+#psF32     psU16    psU32     psU64    psS8    psS16    psS32    psS64    psU8   psF64
+-10.05    2        4         8        0       -2       -4       -8       5      -1.5
+ 1.009     4        8         16       -1      -4       -k8       -16      0      -1.0
+23.45     6        12        24       -2      -6       -12      -24      5      -0.25
+3500.67   8        16        32       -3      -8       -16      -32      75     1.75
+
+#
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tableS64_err.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tableS64_err.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tableS64_err.dat	(revision 22158)
@@ -0,0 +1,9 @@
+#  Table with valid types and index-values
+#
+#psF32     psU16    psU32     psU64    psS8    psS16    psS32    psS64    psU8   psF64
+-10.05    2        4         8        0       -2       -4       -8       5      -1.5
+ 1.009     4        8         16       -1      -4       -8       -k6      0      -1.0
+23.45     6        12        24       -2      -6       -12      -24      5      -0.25
+3500.67   8        16        32       -3      -8       -16      -32      75     1.75
+
+#
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psArguments_all.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psArguments_all.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psArguments_all.c	(revision 22158)
@@ -0,0 +1,494 @@
+/**
+ *  C Implementation: tap_psArguments_all
+ *
+ * Description:  Tests for psArgumentVerbosity, psArgumentGet, psArgumentRemove,
+ *               psArgumentParse, psArgumentHelp, psLogArguments, psTraceArguments
+ *
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+// tests which send output to the screen are silent unless DEBUG = 1
+#define DEBUG 0
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(30);
+
+    // test the failure cases for psArgumentGet, psArgumentRemove
+    {
+        psMemId id = psMemGetId();
+
+	// define a simple fake argument list : this is not modified
+        char *argv[5];
+        argv[0] = "./program";
+        argv[1] = "-string";
+        argv[2] = "new";
+        argv[3] = "-float";
+        argv[4] = "6.66";
+        int argc = 5;
+
+        // Try to get an argument's position
+        int i = psArgumentGet(argc, argv, "-float");
+        {
+            ok( i == 3,
+                "psArgumentGet:         return correct location of input argument.");
+        }
+
+        // Return 0 for attempting to get from a NULL input argument.
+        {
+            ok( psArgumentGet(argc, NULL, "-float") == 0,
+                "psArgumentGet:         return 0 for a NULL input argument.");
+        }
+
+        // Return 0 for attempting to find a NULL string
+        {
+            ok( psArgumentGet(argc, argv, NULL) == 0,
+                "psArgumentGet:         return 0 for a NULL input string.");
+        }
+
+        // Return 0 for attempting to find an empty string
+        {
+            ok( psArgumentGet(argc, argv, "") == 0,
+                "psArgumentGet:         return 0 for an empty input string.");
+        }
+
+        // Return 0 for attempting to get an argument that doesn't match
+        {
+            ok( psArgumentGet(argc, argv, "-xxx") == 0,
+                "psArgumentGet:         return 0 for an empty input string.");
+        }
+
+        // Return false for attempting to remove argnum = 0
+        {
+            ok( !psArgumentRemove(0, &argc, argv),
+                "psArgumentRemove:      return false for argnum = 0.");
+        }
+
+        // Return false for attempting to remove NULL argc
+        {
+            ok( !psArgumentRemove(0, NULL, argv),
+                "psArgumentRemove:      return false for NULL argc.");
+        }
+
+        // simple argument definitions for comparison
+        psMetadata *args = psMetadataAlloc();
+        psMetadataAdd(args, PS_LIST_TAIL, "-string", PS_DATA_STRING, "Test String", "SomeString");
+        psMetadataAdd(args, PS_LIST_TAIL, "-float", PS_DATA_F32, "Test Float", 0.666);
+        psMetadataAdd(args, PS_LIST_TAIL, "-double", PS_DATA_F64, "Test Double", 0.666);
+
+        // psArgumentParse tests
+        // Return false for NULL input arguments
+        {
+            ok( !psArgumentParse(NULL, &argc, argv),
+                "psArgumentParse:       return false for NULL argument metadata input.");
+        }
+
+        // Return false for NULL input argc
+        {
+            ok( !psArgumentParse(args, NULL, argv),
+                "psArgumentParse:       return false for NULL argc input.");
+        }
+
+        // Return false for NULL input argv
+        {
+            ok( !psArgumentParse(args, &argc, NULL),
+                "psArgumentParse:       return false for NULL argv input.");
+        }
+
+        // Return false for argc = 0
+        {
+            int tempc = 0;
+            ok( !psArgumentParse(args, &tempc, argv),
+                "psArgumentParse:       return false for argc = 1 input.");
+        }
+
+        // Return false for string not found in metadata arguments
+        {
+	    // define a simple fake argument list : this is not modified
+	    char *argvBad[5];
+	    argvBad[0] = "./program";
+	    argvBad[1] = "-string";
+	    argvBad[2] = "new";
+	    argvBad[3] = "-test";
+	    argvBad[4] = "6.66";
+	    int argcBad = 5;
+
+            ok( !psArgumentParse(args, &argcBad, argvBad),
+                "psArgumentParse:      return false for argv containing unspecified input.");
+        }
+
+        // Check for Memory leaks
+        {
+            psFree(args);
+            checkMem();
+        }
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // define a valid argument input set and definition set
+    // Return true for valid case
+    {
+        psMemId id = psMemGetId();
+
+	// define the sample arguments
+	char *argv[20];
+	argv[0] = "./program";
+	argv[1] = "-string";
+	argv[2] = "new";
+	argv[3] = "-float";
+	argv[4] = "6.66";
+	argv[5] = "-double";
+	argv[6] = "0.666";
+	argv[7] = "-int";
+	argv[8] = "8";
+	argv[9] = "16";
+	argv[10] = "32";
+	argv[11] = "64";
+	argv[12] = "-U8";
+	argv[13] = "1";
+	argv[14] = "-U16";
+	argv[15] = "666";
+	argv[16] = "-U32";
+	argv[17] = "666";
+	argv[18] = "-Bool";
+	argv[19] = "true";
+	int argc = 20;
+
+	// setup the argument definition
+	psMetadata *args = psMetadataAlloc();
+
+	// three simple types
+	psMetadataAdd(args, PS_LIST_TAIL, "-string", PS_DATA_STRING, "Test String", "SomeString");
+	psMetadataAdd(args, PS_LIST_TAIL, "-float", PS_DATA_F32, "Test Float", 0.666);
+	psMetadataAdd(args, PS_LIST_TAIL, "-double", PS_DATA_F64, "Test Double", 0.666);
+
+	// a multiple argument option : -int 1 2 3 4
+	psMetadata *ints = psMetadataAlloc();
+	psMetadataAdd(ints, PS_LIST_TAIL, "int1", PS_DATA_S8, "Int1", 8);
+	psMetadataAdd(ints, PS_LIST_TAIL, "int2", PS_DATA_S16, "Int2", 16);
+	psMetadataAdd(ints, PS_LIST_TAIL, "int3", PS_DATA_S32, "Int3", 32);
+	psMetadataAdd(ints, PS_LIST_TAIL, "int4", PS_DATA_S64, "Int4", 64);
+	psMetadataAdd(args, PS_LIST_TAIL, "-int", PS_DATA_METADATA, "Integers", ints);
+	psFree(ints);                  // Drop reference
+
+	// a multiple option example : -multi 1 -multi 2
+	psMetadataAddS32(args, PS_LIST_TAIL, "-multi", 0, "666", 2);
+	psMetadataAddS32(args, PS_LIST_TAIL, "-multi", PS_META_DUPLICATE_OK, "hello kitty", 1);
+
+	// simple psLib types
+	psMetadataAddU8(args, PS_LIST_TAIL, "-U8", 0, "U8", 1);
+	psMetadataAddU16(args, PS_LIST_TAIL, "-U16", 0, "U16", 666);
+	psMetadataAddU32(args, PS_LIST_TAIL, "-U32", 0, "U32", 666);
+	psMetadataAddU64(args, PS_LIST_TAIL, "-U64", 0, "U64", 666);
+	psMetadataAddBool(args, PS_LIST_TAIL, "-Bool", 0, "boolean", true);
+
+	// attempt to parse the above arguments using the above argument definition
+	ok( psArgumentParse(args, &argc, argv), "psArgumentParse:      return true for valid inputs.");
+
+        // Check for Memory leaks
+	psFree(args);
+	checkMem();
+
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+
+    }
+
+    // other basic tests
+    { 
+        psMemId id = psMemGetId();
+
+	// Return false for inconsistent argc in metadata
+	{
+	    psMetadata *tempArg = psMetadataAlloc();
+	    psMetadata *mdtemp = psMetadataAlloc();
+	    psMetadataAdd(mdtemp, PS_LIST_TAIL, "int1", PS_DATA_S8, "Int1", 8);
+	    psMetadataAdd(mdtemp, PS_LIST_TAIL, "int2", PS_DATA_S16, "Int2", 16);
+	    psMetadataAdd(mdtemp, PS_LIST_TAIL, "int3", PS_DATA_S32, "Int3", 32);
+	    psMetadataAdd(tempArg, PS_LIST_TAIL, "-int", PS_DATA_METADATA, "Integers", mdtemp);
+	    psFree(mdtemp);
+
+	    int argc = 2;
+	    char *argv[2];
+	    argv[0] = "./program";
+	    argv[1] = "-string";
+	    ok( !psArgumentParse(tempArg, &argc, argv),
+		"psArgumentParse:      return false for inconsistent argc.");
+	    psFree(tempArg);
+	}
+
+	// setup the argument definition
+	psMetadata *args = psMetadataAlloc();
+
+	// three simple types
+	psMetadataAdd(args, PS_LIST_TAIL, "-string", PS_DATA_STRING, "Test String", "SomeString");
+	psMetadataAddS32(args, PS_LIST_TAIL, "-multi", 0, "666", 2);
+	psMetadataAddS32(args, PS_LIST_TAIL, "-multi", PS_META_DUPLICATE_OK, "hello kitty", 1);
+
+	// Return false for argc = 1
+	{
+	    int argc = 2;
+	    char *argv[2];
+	    argv[0] = "./program";
+	    argv[1] = "-string";
+	    ok( !psArgumentParse(args, &argc, argv),
+		"psArgumentParse:      return false for incomplete string syntax.");
+	}
+
+	// Return true for an unfound MULTI match
+	{
+	    int argc = 3;
+	    char *argv[3];
+	    argv[0] = "./program";
+	    argv[1] = "-multi";
+	    argv[2] = "2";
+	    ok( psArgumentParse(args, &argc, argv),
+		"psArgumentParse:      return true for MULTI.");
+	}
+
+	// Check for Memory leaks
+	{
+	    psFree(args);
+	    checkMem();
+	}
+	ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test psArgumentVerbosity()
+    {
+	psMemId id = psMemGetId();
+	// Return 2 (default) for NULL input argument
+	{
+	    int argc = 1;
+	    ok( psArgumentVerbosity(&argc, NULL) == 2,
+		"psArgumentVerbosity:  return 2 for NULL argument input.");
+	}
+
+	// Return 2 for NULL argc input
+	{
+	    char *argv[1];
+	    argv[0] = "./program";
+	    ok( psArgumentVerbosity(NULL, argv) == 2,
+		"psArgumentVerbosity:  return 2 for NULL argument input.");
+	}
+
+	// Return 3 for "-v" option
+	{
+	    int argc = 2;
+	    char *argv[2];
+	    argv[0] = "./program";
+	    argv[1] = "-v";
+	    ok( psArgumentVerbosity(&argc, argv) == 3,
+		"psArgumentVerbosity:  return 3 for '-v' argument input.");
+	}
+
+	// Return 4 for "-vv" option
+	{
+	    int argc = 2;
+	    char *argv[2];
+	    argv[0] = "./program";
+	    argv[1] = "-vv";
+	    ok( psArgumentVerbosity(&argc, argv) == 4,
+		"psArgumentVerbosity:  return 4 for '-vv' argument input.");
+	}
+
+	// Return 5 for "-vvv" option
+	{
+	    int argc = 2;
+	    char *argv[2];
+	    argv[0] = "./program";
+	    argv[1] = "-vvv";
+	    ok( psArgumentVerbosity(&argc, argv) == 5,
+		"psArgumentVerbosity:  return 5 for '-vvv' argument input.");
+	}
+
+	// These routines should return 5 since that was the last level set above with -vvv
+	// Return 5 for "-logfmt" option
+	{
+	    int argc = 2;
+	    char *argv[2];
+	    argv[0] = "./program";
+	    argv[1] = "-logfmt";
+	    int rc = psArgumentVerbosity(&argc, argv);
+	    ok(rc == 5, "psArgumentVerbosity:  return 5 for '-logfmt' argument input (was %d)", rc);
+	}
+
+	// Return 5 for "-logfmt" option with "H"
+	{
+	    int argc = 3;
+	    char *argv[3];
+	    argv[0] = "./program";
+	    argv[1] = "-logfmt";
+	    argv[2] = "H";
+	    int rc = psArgumentVerbosity(&argc, argv);
+	    ok(rc == 5, "psArgumentVerbosity:  return 5 for '-logfmt H' argument inputs (was %d)", rc);
+	}
+
+	// Return 5 for "-trace" option
+	{
+	    int argc = 2;
+	    char *argv[2];
+	    argv[0] = "./program";
+	    argv[1] = "-trace";
+	    int rc = psArgumentVerbosity(&argc, argv);
+	    ok(rc == 5, "psArgumentVerbosity:  return 5 for '-trace' argument input (was %d)", rc);
+	}
+
+	// Return 5 for "-trace 1 2" option
+	{
+	    int argc = 4;
+	    char *argv[4];
+	    argv[0] = "./program";
+	    argv[1] = "-trace";
+	    argv[2] = "1";
+	    argv[3] = "2";
+	    // XXX EAM : we are getting unneeded output because of the verbosity set above.
+	    int rc = psArgumentVerbosity(&argc, argv);
+	    ok(rc == 5, "psArgumentVerbosity:  return 5 for '-trace 1 2' argument inputs (was %d", rc);
+	}
+
+	// Return 5 for "-trace-levels" option
+	{
+	    // this function sends output to the screen or /dev/null (i
+	    # if (!DEBUG)
+	    FILE *f = fopen ("/dev/null", "w");
+	    int fd = fileno(f);
+	    psTraceSetDestination (fd);
+	    # endif
+
+	    int argc = 2;
+	    char *argv[2];
+	    argv[0] = "./program";
+	    argv[1] = "-trace-levels";
+	    int rc = psArgumentVerbosity(&argc, argv);
+	    ok(rc == 5, "psArgumentVerbosity:  return 5 for '-trace-levels' argument input (was %d)", rc);
+	}
+	ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
+
+/* XXX: Why is this commented out?
+   void testLogTraceArguments(void)
+   {
+   note("  >>>Test 3:  psLogArguments & psTraceArguments Fxns");
+ 
+   // Return 2 (default) for NULL arguments input
+   {
+   int argc = 4;
+   ok( psLogArguments(&argc, NULL) == 2,
+   "psLogArguments:       return 2 for NULL argument input.");
+   }
+   // Return 2 (default) for NULL argc input
+   {
+   char *argv[1];
+   argv[0] = "./program";
+   ok( psLogArguments(NULL, argv) == 2,
+   "psLogArguments:       return 2 for NULL argc input.");
+   }
+   // Return 3 for "-v" option
+   {
+   int argc = 2;
+   char *argv[2];
+   argv[0] = "./program";
+   argv[1] = "-v";
+   ok( psLogArguments(&argc, argv) == 3,
+   "psLogArguments:       return 3 for '-v' argument input.");
+   }
+   // Return 4 for "-vv" option
+   {
+   int argc = 2;
+   char *argv[2];
+   argv[0] = "./program";
+   argv[1] = "-vv";
+   ok( psLogArguments(&argc, argv) == 4,
+   "psLogArguments:       return 4 for '-vv' argument input.");
+   }
+   // Return 5 for "-vvv" option
+   {
+   int argc = 2;
+   char *argv[2];
+   argv[0] = "./program";
+   argv[1] = "-vvv";
+   ok( psLogArguments(&argc, argv) == 5,
+   "psLogArguments:       return 5 for '-vvv' argument input.");
+   }
+   // Return 2 for "-logfmt" option
+   {
+   int argc = 2;
+   char *argv[2];
+   argv[0] = "./program";
+   argv[1] = "-logfmt";
+   ok( psLogArguments(&argc, argv) == 2,
+   "psLogArguments:       return 2 for '-logfmt' argument input.");
+   }
+   // Return 2 for "-logfmt" option with "H"
+   {
+   int argc = 3;
+   char *argv[3];
+   argv[0] = "./program";
+   argv[1] = "-logfmt";
+   argv[2] = "H";
+   ok( psLogArguments(&argc, argv) == 2,
+   "psLogArguments:       return 2 for '-logfmt H' argument inputs.");
+   }
+ 
+ 
+   // psTraceArguments Tests
+   // Return 0 (default) for NULL arguments input
+   {
+   int argc = 4;
+   ok( psTraceArguments(&argc, NULL) == 0,
+   "psTraceArguments:     return 0 for NULL argument input.");
+   }
+   // Return 0 (default) for NULL argc input
+   {
+   char *argv[1];
+   argv[0] = "./program";
+   ok( psTraceArguments(NULL, argv) == 0,
+   "psTraceArguments:     return 0 for NULL argc input.");
+   }
+   // Return 0 for "-trace" option
+   {
+   int argc = 2;
+   char *argv[2];
+   argv[0] = "./program";
+   argv[1] = "-trace";
+   ok( psTraceArguments(&argc, argv) == 0,
+   "psTraceArguments:     return 2 for '-trace' argument input.");
+   }
+   // Return 2 for "-trace 1 2" option
+   {
+   int argc = 4;
+   char *argv[4];
+   argv[0] = "./program";
+   argv[1] = "-trace";
+   argv[2] = "1";
+   argv[3] = "2";
+   ok( psTraceArguments(&argc, argv) == 1,
+   "psTraceArguments:     return 2 for '-trace 1 2' argument inputs.");
+   }
+   // Return 2 for "-trace-levels" option
+   {
+   int argc = 2;
+   char *argv[2];
+   argv[0] = "./program";
+   argv[1] = "-trace-levels";
+   ok( psTraceArguments(&argc, argv) == 0,
+   "psTraceArguments:     return 2 for '-trace-levels' argument input.");
+   }
+ 
+   // Check for Memory leaks
+   {
+   checkMem();
+   }
+   }
+*/
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psArray_all.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psArray_all.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psArray_all.c	(revision 22158)
@@ -0,0 +1,303 @@
+/**
+ *  C Implementation: tap_psArray_creating
+ *
+ * Description:  Tests for psArrayAlloc, psArrayRealloc, psMemCheckArray,
+ *               psArrayElementsFree, psArrayLength
+ *
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(31);
+
+    // testArrayAllocs()
+    {
+        psMemId id = psMemGetId();
+        psArray *a = NULL;
+
+        //Tests for psArrayAlloc
+        //Return NULL on attempting to allocate a negative size array
+        {
+            a = psArrayAlloc(-2);
+            ok( a == NULL,
+                "psArrayAlloc:           return NULL for negative array-size input.");
+        }
+        //Return NULL for negative array size - psArrayAllocEmpty
+        {
+            a = psArrayAllocEmpty(-2);
+            ok( a == NULL,
+                "psArrayAllocEmpty:      return NULL for negative array-size input.");
+        }
+        //Return properly allocated psArray
+        {
+            a = psArrayAlloc(0);
+            ok( a != NULL && psMemCheckArray(a),
+                "psArrayAlloc:           return properly allocated psArray.");
+        }
+
+        //Tests for psArrayRealloc
+        //Now try to reallocate the psArray - bigger
+        {
+            a = psArrayRealloc(a, 2);
+            ok ( psArrayLength(a) == 0 && a->nalloc == 2,
+                 "psArrayRealloc:         return properly reallocated psArray.");
+        }
+        //Return NULL when trying to reallocate a NULL psArray
+        {
+            psArray *temp = NULL;
+            temp = psArrayRealloc(temp, 1);
+            ok( temp == NULL,
+                "psArrayRealloc:         return NULL for NULL input psArray.");
+        }
+        //Attempt to reallocate the psArray - smaller
+        {
+            psS32 *s32 = (psS32*)psAlloc(sizeof(psS32));
+            *s32 = 1;
+            psS32 *s32_2 = (psS32*)psAlloc(sizeof(psS32));
+            *s32_2 = 2;
+            skip_start(  !psArraySet(a, 0, s32) || !psArraySet(a, 1, s32), 1,
+                         "Skipping 1 tests because psArraySet failed");
+            a = psArrayRealloc(a, 1);
+            *s32_2 = *((psS32*)(a->data[0]));
+            ok( a->n == 1 && a->nalloc == 1 && *s32_2 == 1,
+                "psArrayRealloc:         return properly reallocated psArray.");
+            skip_end();
+            psFree(s32);
+            psFree(s32_2);
+        }
+        //Attempt to reallocate the psArray to negative size
+        {
+            a = psArrayRealloc(a, -1);
+            psS32 *s32 = (psS32*)psAlloc(sizeof(psS32));
+            *s32 = 2;
+            *s32 = *((psS32*)(a->data[0]));
+            ok( a->n == 1 && a->nalloc == 1 && *s32 == 1,
+                "psArrayRealloc:         return same psArray for negative-size input.");
+            psFree(s32);
+        }
+
+        //Attempt to free a NULL psArray
+        psArrayElementsFree(NULL);
+        //Check the length of a NULL array
+        {
+            psArray *emptyArray = NULL;
+            ok( psArrayLength(emptyArray) == -1,
+                "psArrayLength:          return -1 for NULL input psArray.");
+        }
+        psFree(a);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testArrayAddRemove()
+    {
+        psMemId id = psMemGetId();
+        psArray *a = psArrayAlloc(0);
+        psS32 *s1 = (psS32*)psAlloc(sizeof(psS32));
+        *s1 = 2;
+        psS32 *s2 = (psS32*)psAlloc(sizeof(psS32));
+        psS32 *s3 = (psS32*)psAlloc(sizeof(psS32));
+
+        //Tests for psArrayAdd
+        //Attempt to add element to NULL psArray.
+        {
+            psArray *temp = NULL;
+            temp = psArrayAdd(temp, 1, (psPtr)s1);
+            *s3 = *((psS32*)(temp->data[0]));
+            ok( temp->n == 1 && temp->nalloc == 1 && *s3 == 2,
+                "psArrayAdd:             return array with newly added data.");
+            psFree(temp);
+        }
+        //Attempt to add an element to empty array.
+        {
+            a = psArrayAdd(a, 1, (psPtr)s1);
+            *s2 = 666;
+            *s3 = 212;
+            a = psArrayAdd(a, 1, s2);
+            a = psArrayAdd(a, 1, s3);
+            *s2 = *((psS32*)(a->data[0]));
+            ok ( a->n == 3 && a->nalloc == 3 && *s2 == 2,
+                 "psArrayAdd:            return array with newly added data.");
+        }
+
+        //Tests for psArrayRemoveData
+        //Setup array with 3 elements to test remove function
+        //Return false for attempting to remove from a NULL array
+        {
+            psArray *temp = NULL;
+            ok( !psArrayRemoveData(temp, s2),
+                "psArrayRemoveData:     return false for NULL input psArray.");
+        }
+        //Return true for successful removal
+        {
+            ok( psArrayRemoveData(a, s2) && a->n == 2,
+                "psArrayRemoveData:     return true for successful removal.");
+        }
+
+        //Tests for psArrayRemoveIndex
+        //Return false for NULL array input
+        {
+            ok( !psArrayRemoveIndex(NULL, 0),
+                "psArrayRemoveIndex:    return false for NULL input psArray.");
+        }
+        //Return false for out-of-range index
+        {
+            ok( !psArrayRemoveIndex(a, 5),
+                "psArrayRemoveIndex:    return false for out-of-range location.");
+        }
+        //Return true for successful removal
+        {
+            ok( psArrayRemoveIndex(a, 1) && a->n == 1,
+                "psArrayRemoveIndex:    return true for successful removal.");
+        }
+
+        psFree(s1);
+        psFree(s2);
+        psFree(s3);
+        psFree(a);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testArraySetGet()
+    {
+        psMemId id = psMemGetId();
+        psArray *a = NULL;
+        psArray *b = NULL;
+        psS32 *s1 = (psS32*)psAlloc(sizeof(psS32));
+        *s1 = 2;
+        psS32 *s2 = (psS32*)psAlloc(sizeof(psS32));
+        *s2 = 1;
+        psS32 *s3 = (psS32*)psAlloc(sizeof(psS32));
+        *s3 = 3;
+
+        //Tests for psArraySet
+        //Return false for trying to set a NULL psArray
+        {
+            ok( !psArraySet(a, 0, (psPtr)s1),
+                "psArraySet:            return false for NULL input psArray.");
+        }
+        //Return false for trying to set an invalid position
+        a = psArrayAlloc(1);
+        {
+            ok( !psArraySet(a, 2, (psPtr)s1),
+                "psArraySet:            return false for invalid input position.");
+        }
+        //Return false for trying to set nalloc position
+        psArraySet(a, 0, (psPtr)s1);
+        {
+            ok( !psArraySet(a, a->nalloc, (psPtr)s2),
+                "psArraySet:            return false for out-of-range position.");
+        }
+        //Return false for an invalid position (-2 = out-of-range neg. index)
+        {
+            ok( !psArraySet(a, -2, (psPtr)s2),
+                "psArraySet:            return false for out-of-range negative position.");
+        }
+        //Return true for set to a->n position (< nalloc)
+        a = psArrayRealloc(a, 10);
+        {
+            ok( psArraySet(a, a->n, (psPtr)s2)  && a->n == 2,
+                "psArraySet:            return true for valid input position.");
+        }
+        //Return true for a negative index input
+        {
+            ok( psArraySet(a, -2, (psPtr)s3) && a->n == 2 &&
+                *((psS32*)(a->data[0])) == 3,
+                "psArraySet:            return true for valid negative input position.");
+        }
+
+        //Tests for psArrayGet
+        //Return NULL for NULL array input
+        psS32 *s4 = NULL;
+        {
+            s4 = (psS32*)psArrayGet(b, 0);
+            ok( s4 == NULL,
+                "psArrayGet:            return NULL for NULL input psArray.");
+        }
+        //Return NULL for an out-of-range index
+        {
+            s4 = (psS32*)psArrayGet(a, a->n);
+            ok( s4 == NULL,
+                "psArrayGet:            return NULL for out-of-range position.");
+        }
+        //Return NULL for an out-of-range negative index
+        {
+            s4 = (psS32*)psArrayGet(a, -1-a->n);
+            ok( s4 == NULL,
+                "psArrayGet:            return NULL for out-of-range negative position.");
+        }
+        //Return valid case
+        {
+            s4 = (psS32*)psArrayGet(a, 1);
+            ok( *s4 == 1,
+                "psArrayGet:            return correct value for valid position.");
+        }
+
+        psFree(a);
+        psFree(s1);
+        psFree(s2);
+        psFree(s3);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testArraySort()
+    {
+        psMemId id = psMemGetId();
+        psArray *a = NULL;
+        a = psArrayAlloc(3);
+        a->n = 0;
+        psS32 *s1 = (psS32*)psAlloc(sizeof(psS32));
+        *s1 = 2;
+        psS32 *s2 = (psS32*)psAlloc(sizeof(psS32));
+        *s2 = 1;
+        psS32 *s3 = (psS32*)psAlloc(sizeof(psS32));
+        *s3 = 3;
+        psArraySet(a, a->n, (psPtr)s1);
+        psArraySet(a, a->n, (psPtr)s2);
+        psArraySet(a, a->n, (psPtr)s3);
+        psS32 *s4 = (psS32*)psAlloc(sizeof(psS32));
+        psS32 *s5 = (psS32*)psAlloc(sizeof(psS32));
+        psS32 *s6 = (psS32*)psAlloc(sizeof(psS32));
+
+        //Tests for psArraySort
+        //Return NULL for attempt to sort NULL psArray input.
+        {
+            psArray *temp = NULL;
+            temp = psArraySort(temp, (psComparePtrFunc)psCompareDescendingS32Ptr);
+            ok( temp == NULL,
+                "psArraySort:           return NULL for NULL input psArray.");
+        }
+        //Return properly sorted psArray with descending psS32 elements - 3,2,1
+        {
+            a = psArraySort(a, (psComparePtrFunc)psCompareDescendingS32Ptr);
+            *s4 = *((psS32*)(a->data[0]));
+            *s5 = *((psS32*)(a->data[1]));
+            *s6 = *((psS32*)(a->data[2]));
+            ok( *s4 == 3 && *s5 == 2 && *s6 == 1,
+                "psArraySort:           return properly sorted psArray.");
+        }
+
+        psFree(s1);
+        psFree(s2);
+        psFree(s3);
+        psFree(s4);
+        psFree(s5);
+        psFree(s6);
+        psFree(a);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psBitSet_all.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psBitSet_all.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psBitSet_all.c	(revision 22158)
@@ -0,0 +1,279 @@
+/**
+ *  C Implementation: tap_psBitSet_all
+ *
+ * Description:  Tests for psBitSetAlloc, psBitSetSet, psMemCheckBitSet, psBitSetClear,
+ *               psBitSetTest, psBitSetOp, psBitSetNot, psBitSetToString
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <pslib.h>
+#include <string.h>
+#include "tap.h"
+#include "pstap.h"
+
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(31);
+
+
+    // testBitSetBasics()
+    {
+        psMemId id = psMemGetId();
+        psBitSet *noBits = NULL;
+        psBitSet *bs = NULL;
+
+        //Return NULL for attempt to Allocate BitSet of negative size.
+        {
+            noBits = psBitSetAlloc(-1);
+            ok( noBits == NULL,
+                "psBitSetAlloc:         return NULL for negative BitSet-size input.");
+        }
+        //Return properly allocated 0-size psBitSet
+        {
+            bs = psBitSetAlloc(0);
+            ok( bs != NULL && psMemCheckBitSet(bs) && bs->n == 0,
+                "psBitSetAlloc:         return properly allocated psBitSet.");
+        }
+        //Return properly allocated psBitSet
+        {
+            psFree(bs);
+            bs = psBitSetAlloc(8);
+            ok( bs != NULL && psMemCheckBitSet(bs) && bs->n == 1,
+                "psBitSetAlloc:         return properly allocated psBitSet.");
+        }
+        //Make sure psMemCheckBitSet works correctly - return false
+        if (0) {
+            int j = 2;
+            ok( !psMemCheckBitSet(&j),
+                "psMemCheckBitSet:      return false for non-BitSet input.");
+        }
+
+        //BitSetSet Tests
+        //Return FALSE for NULL input psBitSet
+        {
+            bool rc = psBitSetSet(NULL, 0);
+            ok(rc == false,
+                "psBitSetSet:           return FALSE for NULL BitSet input.");
+        }
+        //Return FALSE for negative bit input
+        {
+            bool rc = psBitSetSet(bs, -1);
+            ok( rc == false,
+                "psBitSetSet:           return TRUE for negative bits input.");
+            noBits = NULL;
+        }
+        //Return FALSE for out-of-range bits
+        {
+            psFree(bs);
+            bs = psBitSetAlloc(8);
+            bool rc = psBitSetSet(bs, 8);
+            ok( rc == false,
+                "psBitSetSet:           return TRUE for out-of-range bits input.");
+            noBits = NULL;
+        }
+
+        //Return set BitSet for valid inputs
+        {
+            psBitSetSet(bs, 2);
+            ok( bs->bits[0] == 4,
+                "psBitSetSet:           return properly set BitSet for valid inputs.");
+        }
+
+        //BitSetClear Tests
+        //Return FALSE for NULL input psBitSet
+        {
+            bool rc = psBitSetClear(noBits, 0);
+            ok( rc == false,
+                "psBitSetClear:         return FALSE for NULL BitSet input.");
+        }
+        //Return FALSE for negative bit input
+        {
+            bool rc = psBitSetClear(bs, -1);
+            ok( rc == false,
+                "psBitSetClear:        return TRUE for negative bits input.");
+            noBits = NULL;
+        }
+        //Return FALSE for out-of-range bits
+        {
+            bool rc = psBitSetClear(bs, 8);
+            ok( rc == false,
+                "psBitSetClear:        return FALSE for out-of-range bits input.");
+            noBits = NULL;
+        }
+
+        //Return cleared BitSet for valid inputs
+        {
+            psBitSetClear(bs, 2);
+            ok( bs->bits[0] == 0,
+                "psBitSetClear:        return properly cleared BitSet for valid inputs.");
+        }
+
+        //BitSetTest Tests
+        //Return false for NULL input psBitSet
+        {
+            ok( !psBitSetTest(noBits, 0),
+                "psBitSetTest:         return false for NULL BitSet input.");
+        }
+        //Return false for negative bit input
+        {
+            ok( !psBitSetTest(bs, -1),
+                "psBitSetTest:         return false for negative bits input.");
+        }
+        //Return false for out-of-range bits
+        {
+            ok( !psBitSetTest(bs, 8),
+                "psBitSetTest:         return false for out-of-range bits input.");
+        }
+        //Return false for non-matching bit in BitSet
+        {
+            ok( !psBitSetTest(bs, 2),
+                "psBitSetTest:         return false for non-matching bit in BitSet.");
+        }
+        //Return false for non-matching bit in BitSet
+        {
+            psBitSetSet(bs, 2);
+            ok( psBitSetTest(bs, 2),
+                "psBitSetTest:         return true for matching bit in BitSet.");
+        }
+
+        psFree(bs);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testBitSetOps()
+    {
+        psMemId id = psMemGetId();
+        psBitSet *noBits = NULL;
+        psBitSet *bs = NULL;
+        bs = psBitSetAlloc(8);
+        psBitSetSet(bs, 2);  // 0000 0100 == 4
+        psBitSetSet(bs, 3);  // 0000 1100 == 12
+        psBitSetSet(bs, 4);  // 0001 1100 == 28
+        psBitSetSet(bs, 5);  // 0011 1100 == 60
+        psBitSetSet(bs, 6);  // 0111 1100 == 124
+        psBitSetSet(bs, 7);  // 1111 1100 == 252
+        psBitSet *out = NULL;
+
+        //psBitSetNot Tests
+        //Return NULL for NULL BitSet input
+        {
+            out = psBitSetNot(out, noBits);
+            ok( out == NULL,
+                "psBitSetNot:          return NULL for NULL BitSet input.");
+        }
+        //Return correct BitSet for valid BitSet input
+        {
+            out = psBitSetNot(out, bs);  //bs = 1111 1100  so out should = 0000 0011 = 3
+            ok( out->bits[0] == 3,
+                "psBitSetNot:          return correct BitSet for valid BitSet input.");
+        }
+
+        //psBitSetOp Tests   out = psBitSetOp(out, bs1, "op", bs2);
+        //Return NULL for NULL BitSet input
+        {
+            psFree(out);
+            out = NULL;
+            out = psBitSetOp(out, noBits, "op", noBits);
+            ok( out == NULL,
+                "psBitSetOp:           return NULL for NULL BitSet input.");
+        }
+        //Return NULL for NULL operator input
+        {
+            out = psBitSetOp(out, bs, NULL, noBits);
+            ok( out == NULL,
+                "psBitSetOp:           return NULL for NULL operator input.");
+        }
+        //Return NULL for invalid operator input
+        {
+            out = psBitSetOp(out, bs, "XAND", noBits);
+            ok( out == NULL,
+                "psBitSetOp:           return NULL for invalid operator input.");
+        }
+        //Return NULL for AND operator with NULL second BitSet input
+        {
+            out = psBitSetOp(out, bs, "AND", noBits);
+            ok( out == NULL,
+                "psBitSetOp:           return NULL for AND operator with NULL second BitSet input.");
+        }
+        //Return NULL for AND operator with BitSet inputs of differing size.
+        psBitSet *bs2 = psBitSetAlloc(16);
+        {
+            out = psBitSetOp(out, bs, "AND", bs2);
+            ok( out == NULL,
+                "psBitSetOp:           return NULL for AND operator with BitSet inputs of"
+                " differing size.");
+        }
+        psFree(bs);
+        bs = psBitSetAlloc(16);
+        psBitSetSet(bs, 1);     // 0000 0010 == 2
+        psBitSetSet(bs2, 2);   // 0000 0100 == 4
+        //Return correct psBitSet output for valid inputs with AND operator
+        {
+            out = psBitSetOp(out, bs, "AND", bs2);
+            ok( out->bits[0] == 0,
+                "psBitSetOp:           return correct psBitSet output for valid inputs"
+                " with AND operator.");
+        }
+        //Return correct psBitSet output for valid inputs with OR operator
+        {
+            out = psBitSetOp(out, bs, "OR", bs2);
+            ok( out->bits[0] == 6,
+                "psBitSetOp:           return correct psBitSet output for valid inputs"
+                " with OR operator.");
+        }
+        //Return correct psBitSet output for valid inputs with XOR operator
+        psBitSetSet(bs2, 1);     // 0000 0110 == 6
+        {
+            out = psBitSetOp(out, bs, "XOR", bs2);
+            ok( out->bits[0] == 4,
+                "psBitSetOp:           return correct psBitSet output for valid inputs"
+                " with XOR operator.");
+        }
+        //Return correct psBitSet output for valid inputs with NOT operator
+        {
+            psFree(out);
+            out = psBitSetAlloc(0);
+            psBitSetSet(bs, 2);  // 0000 0110 == 4
+            psBitSetSet(bs, 3);  // 0000 1110 == 12
+            psBitSetSet(bs, 4);  // 0001 1110 == 28
+            psBitSetSet(bs, 5);  // 0011 1110 == 60
+            psBitSetSet(bs, 6);  // 0111 1110 == 124
+            psBitSetSet(bs, 7);  // 1111 1110 == 252
+            out = psBitSetOp(out, bs, "NOT", bs2);
+            ok( out->bits[0] == 1,
+                "psBitSetOp:           return correct psBitSet output for valid inputs"
+                " with NOT operator.");
+        }
+
+        //psBitSetToString Tests
+        //Return NULL for NULL BitSet input
+        psString bitStr = NULL;
+        {
+            bitStr = psBitSetToString(noBits);
+            ok( bitStr == NULL,
+                "psBitSetToString:     return NULL for NULL BitSet input.");
+        }
+        //Return correct string for valid BitSet input
+        {
+            psFree(bs);
+            bs = psBitSetAlloc(8);
+            psBitSetSet(bs, 2);  // 0000 0100 == 4
+            bitStr = psBitSetToString(bs);
+            ok( !strncmp(bitStr, "00000100", 10),
+                "psBitSetToString:     return correct string for valid BitSet input.");
+        }
+
+        psFree(bitStr);
+        psFree(out);
+        psFree(bs);
+        psFree(bs2);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psHash_845.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psHash_845.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psHash_845.c	(revision 22158)
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include "pslib.h"
+#include "pstap.h"
+#define SIZE 128
+
+int main(int argc, char *argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(5);
+
+    // Very basic test: create a psHash, then add data to it.
+    // XXX: Remove this test, or mearge it with another file.
+    {
+        psMemId id = psMemGetId();
+        char *stuff1 = psAlloc(SIZE);       // Stuff to put on hash
+        char *stuff2 = psAlloc(SIZE);       // Stuff to put on hash
+
+        psHash *hash = psHashAlloc(16);     // Hash to test
+        ok(hash, "Hash allocated");
+        bool status1 = psHashAdd(hash, "stuff", stuff1);
+        ok(status1, "Added 1 to hash");
+        psFree(stuff1);                     // Drop reference
+        psMemId last = psMemGetId();        // Last memory I.D.
+        bool status2 = psHashAdd(hash, "stuff", stuff2);
+        ok(status2, "Added 2 to hash");
+        psFree(stuff2);                     // Drop reference
+        int numLeaks = psMemCheckLeaks(last, NULL, NULL, false); // Number of leaks
+        ok(numLeaks == 0, "No leaks.");
+        psFree(hash);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psHash_all.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psHash_all.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psHash_all.c	(revision 22158)
@@ -0,0 +1,252 @@
+/**
+ *  C Implementation: tap_psHash_all
+ *
+ * Description:  Tests for psHashAlloc, psHashAdd, psMemCheckHash, psHashLookup,
+ *               psHashRemove, psHashKeyList, psHashToArray
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+
+#include <pslib.h>
+#include <string.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+void testHashCreate(void);
+void testHashManip(void);
+void testHashConvert(void);
+
+int main(void)
+{
+    plan_tests(24);
+
+    note("Tests for psHash Functions");
+
+    testHashCreate();
+    testHashManip();
+    testHashConvert();
+
+    done();
+}
+
+void testHashCreate(void)
+{
+    note("  >>>Test 1:  psHash Creation Fxns");
+
+    psHash *h1 = NULL;
+    psHash *h2 = NULL;
+
+    //Return NULL on attempting to allocate a negative size hash
+    {
+        h1 = psHashAlloc(-2);
+        ok( h1 == NULL,
+            "psHashAlloc:          return NULL for negative array-size input.");
+    }
+    //Return properly allocated psHash of 0-length
+    {
+        h2 = psHashAlloc(0);
+        ok( h2 != NULL && psMemCheckHash(h2),//XXX: && h1->buckets == NULL,
+            "psHashAlloc:          return properly allocated psHash.");
+    }
+    //Return properly allocated psHash
+    {
+        h1 = psHashAlloc(3);
+        ok( h1 != NULL && psMemCheckHash(h1) && h1->buckets != NULL,
+            "psHashAlloc:          return properly allocated psHash.");
+    }
+    //Make sure psMemCheckHash works correctly - return false
+    if (0) {
+        int j = 2;
+        ok( !psMemCheckHash(&j),
+            "psMemCheckHash:       return false for non-Hash input.");
+    }
+    //Allocate a hashBucket by inserting a psHash entry - return true
+    psMetadataItem *itemBool = psMetadataItemAllocBool("itemBool", "", true);
+    {
+        ok( psHashAdd(h1, "h1-1", (psPtr)itemBool),
+            "psHashAlloc:          return properly allocated psHashBucket item.");
+    }
+    //Return false for trying to add to a NULL hash input
+    {
+        ok( !psHashAdd(NULL, "h1-2", (psPtr)itemBool),
+            "psHashAlloc:          return false for trying to add to a NULL hash input.");
+    }
+    //Return false for trying to add data with NULL key
+    {
+        ok( !psHashAdd(h1, NULL, (psPtr)itemBool),
+            "psHashAlloc:          return false for trying to add data with NULL key.");
+    }
+    //Return false for trying to add NULL data
+    {
+        ok( !psHashAdd(h1, "h1-2", NULL),
+            "psHashAlloc:          return false for trying to add NULL data.");
+    }
+    //Return false for trying to add data to empty hash
+    {
+        ok( !psHashAdd(h2, "h1-2", (psPtr)itemBool),
+            "psHashAlloc:          return false for trying to add data to empty table.");
+    }
+    //Return true for trying to add a duplicate hash entry - replaces
+    {
+        psHashAdd(h1, "h1-2", (psPtr)itemBool);
+        psHashAdd(h1, "h1-3", (psPtr)itemBool);
+        psHashAdd(h1, "h1-4", (psPtr)itemBool);
+        ok( psHashAdd(h1, "h1-3", (psPtr)itemBool),
+            "psHashAlloc:         return true when adding duplicate data entry.");
+    }
+
+
+    //Check for Memory leaks
+    {
+        psFree(itemBool);
+        psFree(h1);
+        psFree(h2);
+        checkMem();
+    }
+}
+
+void testHashManip(void)
+{
+    note("  >>>Test 2:  psHash Manipulation Fxns");
+
+    psHash *h1 = NULL;
+    h1 = psHashAlloc(2);
+    psMetadataItem *itemBool = psMetadataItemAllocBool("itemBool", "", true);
+    psMetadataItem *newBool = psMetadataItemAllocBool("newBool", "", true);
+    psHashAdd(h1, "h1-1", (psPtr)itemBool);
+    psHashAdd(h1, "h1-2", (psPtr)newBool);
+    psMetadataItem *data = NULL;
+
+    //psHashLookup Tests
+    //Return NULL for NULL hash input
+    {
+        data = (psMetadataItem*)psHashLookup(NULL, "h1-1");
+        ok( data == NULL,
+            "psHashLookup:        return NULL for NULL hash input.");
+    }
+    //Return NULL for NULL key input
+    {
+        data = (psMetadataItem*)psHashLookup(h1, NULL);
+        ok( data == NULL,
+            "psHashLookup:        return NULL for NULL key input.");
+    }
+    //Return NULL for no matching key
+    {
+        data = (psMetadataItem*)psHashLookup(h1, "h1-3");
+        ok( data == NULL,
+            "psHashLookup:        return NULL for invalid key input.");
+    }
+    //Return correct data for valid inputs
+    {
+        data = (psMetadataItem*)psHashLookup(h1, "h1-1");
+        ok( data != NULL && psMemCheckMetadataItem(data) && data->data.B,
+            "psHashLookup:        return correct data for valid inputs.");
+    }
+
+    //psHashRemove Tests
+    //Return false for NULL hash input
+    {
+        ok( !psHashRemove(NULL, "h1-1"),
+            "psHashRemove:        return false for NULL hash input.");
+    }
+    //Return false for NULL key input
+    {
+        ok( !psHashRemove(h1, NULL),
+            "psHashRemove:        return false for NULL key input.");
+    }
+    //Return false for no matching key
+    {
+        ok( !psHashRemove(h1, "h1-3"),
+            "psHashRemove:        return false for invalid key input.");
+    }
+    //Return true for properly removed hash entry
+    {
+        ok( psHashRemove(h1, "h1-1") && (psHashLookup(h1, "h1-1") == NULL),
+            "psHashRemove:        return true for properly removed hash entry.");
+    }
+
+    //Check for Memory leaks
+    {
+        psFree(h1);
+        psFree(itemBool);
+        psFree(newBool);
+        checkMem();
+    }
+}
+
+void testHashConvert(void)
+{
+    note("  >>>Test 3:  psHash Conversion/List Fxns");
+
+    psHash *h1 = NULL;
+    h1 = psHashAlloc(2);
+    psHash *h2 = psHashAlloc(0);
+    psMetadataItem *itemBool = psMetadataItemAllocBool("itemBool", "", true);
+    psMetadataItem *newBool = psMetadataItemAllocBool("newBool", "", true);
+    psHashAdd(h1, "h1-1", (psPtr)itemBool);
+    psHashAdd(h1, "h1-2", (psPtr)newBool);
+    psList *newList = NULL;
+    psArray *newArr = NULL;
+
+    //psHashKeyList Tests
+    //Return NULL for NULL hash input
+    {
+        newList = psHashKeyList(NULL);
+        ok( newList == NULL,
+            "psHashKeyList:       return NULL for NULL hash input.");
+    }
+    //Return empty list for empty hash input
+    {
+        newList = psHashKeyList(h2);
+        ok( newList != NULL && newList->n == 0,
+            "psHashKeyList:       return empty list for empty hash input.");
+        psFree(newList);
+        newList = NULL;
+    }
+    //Return correct list for valid, non-empty hash input
+    {
+        newList = psHashKeyList(h1);
+        ok( newList != NULL && !strncmp((char*)(newList->head->data), "h1-1", 10),
+            "psHashKeyList:       return correct list for valid hash input.");
+    }
+
+    //psHashToArray
+    //Return NULL for NULL hash input
+    {
+        newArr = psHashToArray(NULL);
+        ok( newArr == NULL,
+            "psHashToArray:       return NULL for NULL hash input.");
+    }
+    //Return empty array for empty hash input
+    {
+        newArr = psHashToArray(h2);
+        ok( newArr != NULL && newArr->n == 0,
+            "psHashToArray:       return empty array for empty hash input.");
+        psFree(newArr);
+        newArr = NULL;
+    }
+    //Return correct list for valid, non-empty hash input
+    {
+        newArr = psHashToArray(h1);
+        psMetadataItem *tempItem = (psMetadataItem*)psArrayGet(newArr, 0);
+        if (tempItem->type != PS_DATA_BOOL)
+            printf("\n not a bool - %s\n", tempItem->name);
+        ok( newArr != NULL,// && !strncmp(tempItem->name, "itemBool", 10),
+            "psHashToArray:       return correct array for valid hash input.");
+    }
+
+    //Check for Memory leaks
+    {
+        psFree(h1);
+        psFree(h2);
+        psFree(newList);
+        psFree(newArr);
+        psFree(itemBool);
+        psFree(newBool);
+        checkMem();
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psListIterator.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psListIterator.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psListIterator.c	(revision 22158)
@@ -0,0 +1,204 @@
+#include <stdio.h>
+#include <pslib.h>
+#include <string.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define STRING1 "This is string #1"
+#define STRING2 "String number 2"
+#define STRING3 "3 number string"
+#define STRING4 "four number string"
+#define STRING5 "number five string"
+#define STRING6 "#6 string"
+#define STRING7 "#7 $7r!Ng"
+
+
+// Generate a dummy list
+static psList *listGenerate(void)
+{
+    psList *list = psListAlloc(NULL);
+
+    // Generate the strings
+    psString string1 = psStringCopy(STRING1);
+    psString string2 = psStringCopy(STRING2);
+    psString string3 = psStringCopy(STRING3);
+    psString string4 = psStringCopy(STRING4);
+    psString string5 = psStringCopy(STRING5);
+    psString string6 = psStringCopy(STRING6);
+    psString string7 = psStringCopy(STRING7);
+
+    // Add the strings to the list
+    psListAdd(list, PS_LIST_TAIL, string1);
+    psListAdd(list, PS_LIST_TAIL, string2);
+    psListAdd(list, PS_LIST_TAIL, string3);
+    psListAdd(list, PS_LIST_TAIL, string4);
+    psListAdd(list, PS_LIST_TAIL, string5);
+    psListAdd(list, PS_LIST_TAIL, string6);
+    psListAdd(list, PS_LIST_TAIL, string7);
+
+    // Drop references
+    psFree(string1);
+    psFree(string2);
+    psFree(string3);
+    psFree(string4);
+    psFree(string5);
+    psFree(string6);
+    psFree(string7);
+
+    return list;
+}
+
+// Function to perform iteration
+typedef psString (*iterFunc)(psListIterator *iter);
+
+
+// Test the iteration by iterating once and checking the name, comment, and data
+static void testIteration(iterFunc function, // Function to use to iterate
+                          psListIterator *iterator, // The iterator
+                          const char *string // Expected string
+                         )
+{
+    psString output = function(iterator);
+    ok(output, "output = %x", output);
+    skip_start(!output, 1, "Skipping test because iteration failed");
+    ok(strcmp(output, string) == 0, "output = %s", output);
+    skip_end();
+
+    return;
+}
+
+
+int main (void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(72);
+
+    note("psListIterator tests");
+    // Forwards
+    {
+        psMemId id = psMemGetId();
+        psList *list = listGenerate();
+        psListIterator *iter = psListIteratorAlloc(list, PS_LIST_HEAD, false);
+        ok(iter, "iter = %x", iter);
+        skip_start(!iter, 14, "Skipping 14 tests because psMetadataIteratorAlloc failed");
+
+        testIteration((iterFunc)psListGetAndIncrement, iter, STRING1);
+        testIteration((iterFunc)psListGetAndIncrement, iter, STRING2);
+        testIteration((iterFunc)psListGetAndIncrement, iter, STRING3);
+        testIteration((iterFunc)psListGetAndIncrement, iter, STRING4);
+        testIteration((iterFunc)psListGetAndIncrement, iter, STRING5);
+        testIteration((iterFunc)psListGetAndIncrement, iter, STRING6);
+        testIteration((iterFunc)psListGetAndIncrement, iter, STRING7);
+
+        skip_end();
+        psFree(iter);
+        psFree(list);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Backwards
+    {
+        psMemId id = psMemGetId();
+        psList *list = listGenerate();
+        psListIterator *iter = psListIteratorAlloc(list, PS_LIST_TAIL, NULL);
+        ok(iter, "iter = %x", iter);
+        skip_start(!iter, 14, "Skipping 14 tests because psListIteratorAlloc failed");
+
+        testIteration((iterFunc)psListGetAndDecrement, iter, STRING7);
+        testIteration((iterFunc)psListGetAndDecrement, iter, STRING6);
+        testIteration((iterFunc)psListGetAndDecrement, iter, STRING5);
+        testIteration((iterFunc)psListGetAndDecrement, iter, STRING4);
+        testIteration((iterFunc)psListGetAndDecrement, iter, STRING3);
+        testIteration((iterFunc)psListGetAndDecrement, iter, STRING2);
+        testIteration((iterFunc)psListGetAndDecrement, iter, STRING1);
+
+        skip_end();
+        psFree(iter);
+        psFree(list);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Jumping in halfway through (using allocator), forwards
+    {
+        psMemId id = psMemGetId();
+        psList *list = listGenerate();
+        psListIterator *iter = psListIteratorAlloc(list, 3, NULL);
+        ok(iter, "iter = %x", iter);
+        skip_start(!iter, 8, "Skipping 8 tests because psListIteratorAlloc failed");
+
+        testIteration((iterFunc)psListGetAndIncrement, iter, STRING4);
+        testIteration((iterFunc)psListGetAndIncrement, iter, STRING5);
+        testIteration((iterFunc)psListGetAndIncrement, iter, STRING6);
+        testIteration((iterFunc)psListGetAndIncrement, iter, STRING7);
+
+        skip_end();
+        psFree(iter);
+        psFree(list);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Jumping in halfway through (using allocator), backwards
+    {
+        psMemId id = psMemGetId();
+        psList *list = listGenerate();
+        psListIterator *iter = psListIteratorAlloc(list, -4, NULL);
+        ok(iter, "iter = %x", iter);
+        skip_start(!iter, 8, "Skipping 8 tests because psListIteratorAlloc failed");
+
+        testIteration((iterFunc)psListGetAndDecrement, iter, STRING4);
+        testIteration((iterFunc)psListGetAndDecrement, iter, STRING3);
+        testIteration((iterFunc)psListGetAndDecrement, iter, STRING2);
+        testIteration((iterFunc)psListGetAndDecrement, iter, STRING1);
+
+        skip_end();
+        psFree(iter);
+        psFree(list);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Jumping in halfway through (using set), forwards
+    {
+        psMemId id = psMemGetId();
+        psList *list = listGenerate();
+        psListIterator *iter = psListIteratorAlloc(list, PS_LIST_HEAD, NULL);
+        ok(iter, "iter = %x", iter);
+        skip_start(!iter, 8, "Skipping 8 tests because psListIteratorAlloc failed");
+        psListIteratorSet(iter, 3);
+
+        testIteration((iterFunc)psListGetAndIncrement, iter, STRING4);
+        testIteration((iterFunc)psListGetAndIncrement, iter, STRING5);
+        testIteration((iterFunc)psListGetAndIncrement, iter, STRING6);
+        testIteration((iterFunc)psListGetAndIncrement, iter, STRING7);
+
+        skip_end();
+        psFree(iter);
+        psFree(list);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Jumping in halfway through (using set), backwards
+    {
+        psMemId id = psMemGetId();
+        psList *list = listGenerate();
+        psListIterator *iter = psListIteratorAlloc(list, PS_LIST_HEAD, NULL);
+        ok(iter, "iter = %x", iter);
+        skip_start(!iter, 8, "Skipping 8 tests because psListIteratorAlloc failed");
+        psListIteratorSet(iter, -4);
+
+        testIteration((iterFunc)psListGetAndDecrement, iter, STRING4);
+        testIteration((iterFunc)psListGetAndDecrement, iter, STRING3);
+        testIteration((iterFunc)psListGetAndDecrement, iter, STRING2);
+        testIteration((iterFunc)psListGetAndDecrement, iter, STRING1);
+
+        skip_end();
+        psFree(iter);
+        psFree(list);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psList_all.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psList_all.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psList_all.c	(revision 22158)
@@ -0,0 +1,511 @@
+/**
+ *  C Implementation: tap_psList_all
+ *
+ * Description:  Tests for psListAlloc, psListAdd, psMemCheckList, psListAddAfter,
+ *               psListAddBefore, psListRemove, psListRemoveData, psListGet,
+ *               psListIteratorAlloc, psListIteratorSet, psListGetAndIncrement,
+ *               psListGetAndDecrement, psListToArray, psArrayToList, psListSort,
+ *               psListLength
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <pslib.h>
+#include <string.h>
+#include "tap.h"
+#include "pstap.h"
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(61);
+
+    // Test 1:  psList Creation Fxns");
+    // testListCreate(void)
+    {
+        psMemId id = psMemGetId();
+        psList *noList = NULL;
+        psListIterator *noIter = NULL;
+        psList *list = psListAlloc(NULL);
+        psMetadata *md = psMetadataAlloc();
+        psListIterator *iter1 = NULL;
+        psListIterator *iter2 = NULL;
+
+        //Tests for psListAlloc & psMemCheckList
+        //Return empty list for NULL data input.
+        {
+            noList = psListAlloc(NULL);
+            ok( psListLength(noList) == 0 && psMemCheckList(noList),
+                "psListAlloc:             return empty list for NULL data input.");
+        }
+        //Return allocated list for non-NULL data input.
+        psFree(noList);
+        {
+            noList = psListAlloc(md);
+            ok( psListLength(noList) == 1,
+            "psListAlloc:             return correct list for non-NULL data input.");
+        }
+        //Make sure psMemCheckList works correctly - return false
+        if (0) {
+            int j = 2;
+            ok( !psMemCheckList(&j),
+                "psMemCheckList:          return false for non-List input.");
+        }
+
+        //Tests for ListIteratorAlloc
+        //Return NULL for attempt to allocate iterator with NULL list input
+        {
+            noIter = psListIteratorAlloc(NULL, 0, true);
+            ok( noIter == NULL,
+                "psListIteratorAlloc:     return false for NULL data input.");
+        }
+        //Attempt to Allocate a psListIterator with out-of-range location
+        {
+            iter1 = psListIteratorAlloc(noList, 10, false);
+            ok( iter1 == NULL,
+                "psListIteratorAlloc:     return NULL for out-of-range location.");
+        }
+        //Return valid iterator for valid inputs
+        {
+            iter1 = psListIteratorAlloc(noList, 0, true);
+            ok( iter1 != NULL,
+                "psListIteratorAlloc:     return valid iterator for valid inputs.");
+        }
+
+        //Tests For ListAdd Fxns
+        //Return false for NULL list input
+        {
+            ok( !psListAdd(NULL, 0, md),
+                "psListAdd:               return false for NULL list input.");
+        }
+        //Return false for NULL data input
+        {
+            ok( !psListAdd(list, 0, NULL),
+                "psListAdd:               return false for NULL data input.");
+        }
+        //Return false for list with NULL data
+        {
+            psFree(list->iterators->data[0]);
+            list->iterators->data[0] = NULL;
+            ok( !psListAdd(list, 0, md),
+                "psListAdd:               return false for list with NULL iterators.");
+            psFree(list);
+            list = psListAlloc(md);
+        }
+        //Return true for valid inputs - tail location
+        {
+            ok( psListAdd(list, 2, md),
+                "psListAdd:              return true for valid inputs - Tail Location.");
+        }
+        //Return true for valid inputs - head location
+        {
+            ok( psListAdd(list, 0, md),
+                "psListAdd:              return true for valid inputs - head Location.");
+        }
+
+        //psListAddAfter Tests
+        //psListAddAfter - Return false for NULL data input
+        {
+            ok( !psListAddAfter(iter1, NULL),
+                "psListAddAfter:         return false for NULL data input.");
+        }
+        //psListAddAfter - Return false for NULL iterator input
+        {
+            ok( !psListAddAfter(NULL, md),
+                "psListAddAfter:         return false for NULL iterator input.");
+        }
+        //psListAddAfter - Return false for non-mutable iterator input
+        {
+            iter1->mutable = false;
+            ok( !psListAddAfter(iter1, md),
+                "psListAddAfter:         return false for non-mutable iterator input.");
+            iter1->mutable = true;
+            psFree(iter1);
+        }
+        //psListAddAfter - Return false for iterator with NULL cursor
+        psList *newList = psListAlloc(md);
+        iter1 = psListIteratorAlloc(newList, 0, true);
+        psListElem *cursor = iter1->cursor;
+        {
+            iter1->cursor = NULL;
+            ok( !psListAddAfter(iter1, md),
+                "psListAddAfter:         return false for iterator with headptr but no cursor.");
+            iter1->cursor = cursor;
+        }
+        //Set the iterator to a middle element, then add after
+        {
+            iter2 = psListIteratorAlloc(list, 1, true);
+            ok( psListAddAfter(iter2, md),
+                "psListAddAfter:         return true for adding a list element to the middle.");
+        }
+        //Set the iterator to the head element, then add after a wrong index.  return true
+        {
+            if (!psListIteratorSet(iter2, PS_LIST_HEAD) )
+                printf("\nerror in set\n\n");
+            ((psListIterator*)(iter2->list->iterators->data[0]))->index = 10;
+            ok( psListAddAfter(iter2, md),
+                "psListAddAfter:         return true for adding a list element to the head.");
+        }
+        //Return true for adding to an empty list
+        psFree(noList);
+        noList = psListAlloc(NULL);
+        psListIterator *iter3 = psListIteratorAlloc(noList, 0, true);
+        {
+            ok( psListAddAfter(iter3, md),
+                "psListAddAfter:         return true for adding to an empty list.");
+        }
+
+        //psListAddBefore Tests
+        //psListAddBefore - Return false for NULL data input
+        {
+            ok( !psListAddBefore(iter1, NULL),
+                "psListAddBefore:        return false for NULL data input.");
+        }
+        //psListAddBefore - Return false for NULL iterator input
+        {
+            ok( !psListAddBefore(NULL, md),
+                "psListAddBefore:        return false for NULL iterator input.");
+        }
+        //psListAddBefore - Return false for non-mutable iterator input
+        {
+            iter1->mutable = false;
+            ok( !psListAddBefore(iter1, md),
+                "psListAddBefore:        return false for non-mutable iterator input.");
+            iter1->mutable = true;
+        }
+        {
+            cursor = iter1->cursor;
+            iter1->cursor = NULL;
+            ok( !psListAddBefore(iter1, md),
+                "psListAddBefore:        return false for iterator with headptr but no cursor.");
+            iter1->cursor = cursor;
+        }
+        //Add before a middle list element
+        {
+            psListIteratorSet(iter2, -2);
+            ok( psListAddBefore(iter2, md),
+                "psListAddBefore:        return true for adding a list element to the middle.");
+        }
+        //Set the iterator to the 2nd element, then add after a wrong index.  return true
+        {
+            skip_start(  !psListIteratorSet(iter2, 1), 1,
+                         "Skipping 1 tests because psListIteratorSet failed");
+            ((psListIterator*)(iter2->list->iterators->data[0]))->index = 10;
+            ok( psListAddBefore(iter2, md),
+                "psListAddBefore:        return true for adding a list element to the head.");
+            skip_end();
+        }
+        //Return true for adding to an empty list
+        {
+            psFree(noList);
+            noList = psListAlloc(NULL);
+            iter3 = psListIteratorAlloc(noList, 0, true);
+            psFree(iter3);
+            ok( psListAddBefore(iter3, md),
+                "psListAddBefore:        return true for adding to an empty list.");
+        }
+    
+        //Check the length of a NULL list
+        {
+            psList *emptyList = NULL;
+            ok( psListLength(emptyList) == -1,
+                "psListLength:           return -1 for NULL input psList.");
+        }
+    
+        psFree(iter2);
+        psFree(list);
+        psFree(iter1);
+        psFree(newList);
+        psFree(md);
+        psFree(noList);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testListManip()
+    // psList Manipulation Fxns");
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = psMetadataAlloc();
+        psList *emptyList = psListAlloc(NULL);
+        psList *list = psListAlloc(md);
+        psSphere *sphere = psSphereAlloc();
+        psCube *cube = psCubeAlloc();
+        psArray *array = psArrayAlloc(0);
+        psListAdd(list, PS_LIST_TAIL, sphere);
+        psListAdd(list, PS_LIST_TAIL, cube);
+        psListAdd(list, PS_LIST_TAIL, array);
+        psListIterator *emptyIter = psListIteratorAlloc(emptyList, 0, true);
+        psListIterator *iter1 = psListIteratorAlloc(list, PS_LIST_TAIL, true);
+    
+        //Tests for psListGet
+        //Return NULL for NULL list input
+        {
+            psMetadata *out = NULL;
+            out = (psMetadata*)psListGet(NULL, PS_LIST_HEAD);
+            ok( out == NULL,
+                "psListGet:              return NULL for NULL list input.");
+        }
+        //Return NULL for empty list
+        {
+            psMetadata *out = NULL;
+            out = (psMetadata*)psListGet(emptyList, PS_LIST_HEAD);
+            ok( out == NULL,
+                "psListGet:              return NULL for empty list.");
+        }
+        //Return NULL for out-of-range location
+        {
+            psMetadata *out = NULL;
+            out = (psMetadata*)psListGet(list, -10);
+            ok( out == NULL,
+                "psListGet:              return NULL for out-of-range location.");
+        }
+        //Return correct head item for valid inputs
+        {
+            psMetadata *out = NULL;
+            out = (psMetadata*)psListGet(list, PS_LIST_HEAD);
+            ok( out != NULL && psMemCheckMetadata(out),
+                "psListGet:              return correct head item for valid inputs.");
+        }
+    
+        //Tests for psListGetAndIncrement
+        //Return NULL for NULL iterator input
+        {
+            psMetadata *out = NULL;
+            out = (psMetadata*)psListGetAndIncrement(NULL);
+            ok( out == NULL,
+                "psListGetAndIncrement:  return NULL for NULL iterator input.");
+        }
+        //Return NULL for empty iterator with offend = false
+        {
+            psMetadata *out = NULL;
+            out = (psMetadata*)psListGetAndIncrement(emptyIter);
+            ok( out == NULL,
+                "psListGetAndIncrement:  return NULL for empty iterator input.");
+        }
+        //Return NULL for empty iterator with offend = true
+        {
+            emptyIter->offEnd = true;
+            psMetadata *out = NULL;
+            out = (psMetadata*)psListGetAndIncrement(emptyIter);
+            ok( out == NULL,
+                "psListGetAndIncrement:  return NULL for empty iterator input.");
+            emptyIter->offEnd = false;
+        }
+        //Return correct tail item for valid inputs
+        {
+            psArray *out = NULL;
+            out = (psArray*)psListGetAndIncrement(iter1);
+            ok( out != NULL && psMemCheckArray(out),
+                "psListGetAndIncrement:  return correct tail item for valid inputs.");
+        }
+    
+        //Tests for psListGetAndDecrement
+        //Return NULL for NULL iterator input
+        {
+            psMetadata *out = NULL;
+            out = (psMetadata*)psListGetAndDecrement(NULL);
+            ok( out == NULL,
+                "psListGetAndDecrement:  return NULL for NULL iterator input.");
+        }
+        //Return NULL for empty iterator with offend = false
+        {
+            psMetadata *out = NULL;
+            out = (psMetadata*)psListGetAndDecrement(emptyIter);
+            ok( out == NULL,
+                "psListGetAndDecrement:  return NULL for empty iterator input.");
+        }
+        //Return NULL for empty iterator with offend = true
+        {
+            emptyIter->offEnd = true;
+            psMetadata *out = NULL;
+            out = (psMetadata*)psListGetAndDecrement(emptyIter);
+            ok( out == NULL,
+                "psListGetAndDecrement:  return NULL for empty iterator input.");
+            emptyIter->offEnd = false;
+        }
+        //Return correct tail item for valid inputs
+        {
+            psArray *out = NULL;
+            skip_start(  !psListIteratorSet(iter1, PS_LIST_TAIL), 1,
+                         "Skipping 1 tests because psListIteratorSet failed");
+            out = (psArray*)psListGetAndDecrement(iter1);
+            ok( out != NULL && psMemCheckArray(out),
+                "psListGetAndDecrement:  return correct tail item for valid inputs.");
+            skip_end();
+        }
+    
+        //Tests for psListRemove
+        //Return false for NULL list input
+        {
+            ok( !psListRemove(NULL, PS_LIST_HEAD),
+                "psListRemove:           return false for NULL list input.");
+        }
+        //Return false for invalid location
+        {
+            ok( !psListRemove(list, -10),
+                "psListRemove:           return false for invalid location.");
+        }
+        //Return false for empty list
+        {
+            ok( !psListRemove(emptyList, PS_LIST_HEAD),
+                "psListRemove:           return false for remove from empty list.");
+        }
+        //Return true for remove from middle of list
+        {
+            ok( psListRemove(list, 2) && list->n == 3,
+                "psListRemove:           return true for remove from middle of list.");
+        }
+        //Return true for remove from head of list
+        {
+            ok( psListRemove(list, PS_LIST_HEAD) && list->n ==2,
+                "psListRemove:           return true for remove from head of list.");
+        }
+        //Return true for remove from tail of list
+        {
+            ok( psListRemove(list, PS_LIST_TAIL) && list->n == 1,
+                "psListRemove:           return true for remove from tail of list.");
+        }
+        //Tests for psListRemoveData
+        //Return false for NULL list input
+        {
+            ok( !psListRemoveData(NULL, md),
+                "psListRemoveData:       return false for NULL list input.");
+        }
+        //Return false for NULL data input
+        {
+            ok( !psListRemoveData(list, NULL),
+                "psListRemoveData:       return false for NULL data input.");
+        }
+        //Return false for non-matching data
+        {
+            ok( !psListRemoveData(list, md),
+                "psListRemoveData:       return false for non-matching data.");
+        }
+        //Return false for trying to remove from an empty list
+        {
+            ok( !psListRemoveData(emptyList, md),
+                "psListRemoveData:       return false for trying to remove from an empty list.");
+        }
+        //Return true for remove of valid data
+        psListAdd(list, PS_LIST_HEAD, cube);
+        psListAdd(list, PS_LIST_HEAD, array);
+        {
+            ok( psListRemoveData(list, sphere),
+                "psListRemoveData:       return true for remove of valid data.");
+        }
+    
+        psFree(md);
+        psFree(emptyList);
+        psFree(list);
+        psFree(sphere);
+        psFree(cube);
+        psFree(array);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testListConvertSort()
+    // psList Conversion and Sorting Fxns");
+    {
+        psMemId id = psMemGetId();
+        psList *emptyList = psListAlloc(NULL);
+        psS32 *s1 = (psS32*)psAlloc(sizeof(psS32));
+        *s1 = 2;
+        psS32 *s2 = (psS32*)psAlloc(sizeof(psS32));
+        *s2 = 3;
+        psS32 *s3 = (psS32*)psAlloc(sizeof(psS32));
+        *s3 = 1;
+        psList *list = psListAlloc(s1);
+        psListAdd(list, PS_LIST_TAIL, s2);
+        psListAdd(list, PS_LIST_TAIL, s3);
+        psArray *array = NULL;
+        psArray *emptyArray = psArrayAlloc(0);
+        psList *out = NULL;
+    
+        //Tests for psListToArray
+        //Return NULL for NULL list input
+        {
+            array = psListToArray(NULL);
+            ok( array == NULL,
+                "psListToArray:          return NULL for NULL list input.");
+        }
+        //Return empty array for empty list input
+        {
+            array = psListToArray(emptyList);
+            ok( array->n == 0 && psMemCheckArray(array),
+                "psListToArray:          return empty array for empty list input.");
+            psFree(array);
+            array = NULL;
+        }
+        //Return correct array for valid list input
+        {
+            array = psListToArray(list);
+            ok( array->n == 3 && *((psS32*)(array->data[0])) == 2,
+                "psListToArray:          return correct array for valid list input.");
+        }
+    
+        //Tests for psArrayToList
+        //Return NULL for NULL array input
+        {
+            out = psArrayToList(NULL);
+            ok( out == NULL,
+                "psArrayToList:          return NULL for NULL array input.");
+        }
+        //Return empty list for empty array input
+        {
+            out = psArrayToList(emptyArray);
+            ok( out->n == 0 && psMemCheckList(out),
+                "psArrayToList:          return empty list for empty array input.");
+            psFree(out);
+            out = NULL;
+        }
+        //Return correct list for valid array input
+        {
+            out = psArrayToList(array);
+            ok( out->n == 3 && *((psS32*)psListGet(out, PS_LIST_HEAD)) == 2,
+                "psArrayToList:          return correct list for valid array input.");
+        }
+    
+        //Tests for psListSort
+        //Return NULL for NULL list input
+        {
+            psList *none = NULL;
+            none = psListSort(none, (psComparePtrFunc)psCompareDescendingS32Ptr);
+            ok( none == NULL,
+                "psListSort:             return NULL for NULL list input.");
+        }
+        //Return empty list for empty list input
+        {
+            emptyList = psListSort(emptyList, (psComparePtrFunc)psCompareDescendingS32Ptr);
+            ok( emptyList != NULL,
+                "psListSort:             return empty list for empty list input.");
+        }
+        //Return properly sorted list for valid inputs
+        {
+            list = psListSort(list, (psComparePtrFunc)psCompareS32Ptr);
+            ok( *((psS32*)psListGet(list, 0)) == 1 &&  *((psS32*)psListGet(list, 1)) == 2,
+                "psListSort:             return properly sorted list for valid inputs.");
+        }
+        //Return unchanged list for NULL psComparePtrFunc
+        {
+            psList *tempList = NULL;
+            tempList = psListSort(list, NULL);
+            ok( tempList == NULL,
+                "psListSort:             return NULL for NULL psComparePtrFunc.");
+        }
+    
+        psFree(array);
+        psFree(out);
+        psFree(emptyArray);
+        psFree(emptyList);
+        psFree(list);
+        psFree(s1);
+        psFree(s2);
+        psFree(s3);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psLookupTable_all.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psLookupTable_all.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psLookupTable_all.c	(revision 22158)
@@ -0,0 +1,296 @@
+/**
+ *  C Implementation: tap_psLookupTable_all
+ *
+ * Description:  Tests for psLookupTableAlloc, psMemCheckLookupTable,
+ *               psVectorsReadFromFile, psLookupTableImport, psLookupTableRead,
+ *               psLookupTableInterpolate, psLookupTableInterpolateAll
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ *
+ * XXX: Must add correct build directories.  This file reads a file in the
+ * types/ subdirectory and will not execute directly if not run from psLib/test
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <pslib.h>
+#include <string.h>
+#include "tap.h"
+#include "pstap.h"
+
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(32);
+
+    // Tests for psLookupTable Functions
+
+
+    // testLookupTableAlloc()
+    // psLookupTableAlloc & psMemCheckLookupTable Fxns
+    {
+        psMemId id = psMemGetId();
+        psLookupTable *lt = NULL;
+        //Tests for psLookupTableAlloc
+        //Return NULL for NULL filename input
+        {
+            lt = psLookupTableAlloc(NULL, "\%f \%lf \%d \%ld", 10);
+            ok( lt == NULL,
+                "psLookupTableAlloc:               return NULL for NULL filename input.");
+        }
+        //Return NULL for NULL format input
+        {
+            lt = psLookupTableAlloc("table.dat", NULL, 10);
+            ok( lt == NULL,
+                "psLookupTableAlloc:               return NULL for NULL format input.");
+        }
+        //Return properly allocated lookupTable for valid inputs
+        {
+            lt = psLookupTableAlloc("table.dat", "\%f \%lf \%d \%ld", 10);
+            ok( lt != NULL && psMemCheckLookupTable(lt),
+                "psLookupTableAlloc:               "
+                "return properly allocated lookupTable for valid inputs.");
+        }
+
+        //Tests for psMemCheckArray
+        //Make sure psMemCheckArray works correctly - return false
+        if (0) {
+            int j = 2;
+            ok( !psMemCheckLookupTable(&j),
+                "psMemCheckLookupTable:            return false for non-LookupTable input.");
+        }
+
+        psFree(lt);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testLookupTableReadImport()
+    // psVectorsReadFromFile, psLookupTableImport, psLookupTableRead Fxns");
+    {
+        psMemId id = psMemGetId();
+        psArray *outVec = NULL;
+        psArray *vectors = NULL;
+        psLookupTable*  table1  = NULL;
+        long           numRows = 0;
+
+        //Tests for psVectorReadFromFile
+        // Attempt to read from NULL filename input
+        {
+            outVec = psVectorsReadFromFile(NULL,
+                                           "\%f \%d \%d \%ld \%d \%d \%d \%ld \%*d \%lf");
+            ok( outVec == NULL,
+                "psVectorsReadFromFile:            return NULL for NULL filename input.");
+        }
+        // Attempt to read from NULL format input
+        {
+            outVec = psVectorsReadFromFile("table.dat", NULL);
+            ok( outVec == NULL,
+                "psVectorsReadFromFile:            return NULL for NULL format input.");
+        }
+        // Attempt to read from invalid filename input
+        {
+            outVec = psVectorsReadFromFile("tableS32.dat",
+                                           "\%f \%d \%d \%ld \%d \%d \%d \%ld \%*d \%lf");
+            ok( outVec == NULL,
+                "psVectorsReadFromFile:            return NULL for invalid filename input.");
+        }
+        // Attempt to read from invalid format input
+        {
+            outVec = psVectorsReadFromFile("table.dat", "\%s");
+            ok( outVec == NULL,
+                "psVectorsReadFromFile:            return NULL for invalid format input.");
+        }
+        // Attempt to read from table containing invalid entry - F32
+        {
+            outVec = psVectorsReadFromFile("tableF32_err.dat",
+                                           "\%f \%d \%d \%ld \%d \%d \%d \%ld \%*d \%lf");
+            ok( outVec == NULL,
+                "psVectorsReadFromFile:            return NULL for table containing invalid entry.");
+        }
+        // Attempt to read from table containing invalid entry - F64
+        {
+            outVec = psVectorsReadFromFile("tableF64_err.dat",
+                                           "\%f \%d \%d \%ld \%d \%d \%d \%ld \%*d \%lf");
+            ok( outVec == NULL,
+                "psVectorsReadFromFile:           return NULL for table containing invalid entry.");
+        }
+        // Attempt to read from table containing invalid entry - S32
+        {
+            outVec = psVectorsReadFromFile("tableS32_err.dat",
+                                           "\%f \%d \%d \%ld \%d \%d \%d \%ld \%*d \%lf");
+            ok( outVec == NULL,
+                "psVectorsReadFromFile:           return NULL for table containing invalid entry.");
+        }
+        // Attempt to read from table containing invalid entry - S64
+        {
+            outVec = psVectorsReadFromFile("tableS64_err.dat",
+                                           "\%f \%d \%d \%ld \%d \%d \%d \%ld \%*d \%lf");
+            ok( outVec == NULL,
+                "psVectorsReadFromFile:           return NULL for table containing invalid entry.");
+        }
+        // Attempt to read from empty table
+        {
+            outVec = psVectorsReadFromFile("tableF32_2.dat",
+                                           "\%f \%d \%d \%ld \%d \%d \%d \%ld \%*d \%lf");
+            ok( outVec == NULL,
+                "psVectorsReadFromFile:           return NULL for empty table.");
+        }
+        // Attempt to read from file with partially constructed row
+        {
+            outVec = psVectorsReadFromFile("table3.dat",
+                                           "\%f \%d \%d \%ld \%d \%d \%d \%ld \%*d \%lf");
+            ok( outVec == NULL,
+                "psVectorsReadFromFile:           return NULL for table with partially"
+                " constructed row.");
+        }
+        // Attempt to read with valid inputs
+        {
+            outVec = psVectorsReadFromFile("table.dat",
+                                           "\%f \%d \%d \%ld \%d \%d \%d \%ld \%*d \%lf");
+            ok(outVec, "psVectorsReadFromFile:           read vectors from file");
+
+	    skip_start (!outVec, 2, "skipping tests using the invalid null array");
+	    ok(outVec->n == 9, "psVectorsReadFromFile:           read correct number of vectors");
+
+	    psVector *tmpVec = outVec->data[6];
+	    ok(tmpVec->data.S32[1] == -8, "psVectorsReadFromFile:           selected data element has correct value.");
+	    skip_end();
+        }
+
+        //Tests for psLookupTableRead
+        // Attempt to read table with NULL input table specified
+        numRows = psLookupTableRead(table1);
+        {
+            ok( numRows == 0,
+                "psLookupTableRead:               return NULL for NULL filename input.");
+        }
+        // Attempt to read table with bad filename specified
+        table1 = psLookupTableAlloc("psTable.dat", "\%f \%lf \%d \%ld", 10);
+        numRows = psLookupTableRead(table1);
+        {
+            ok( numRows == 0,
+                "psLookupTableRead:               return NULL for table with invalid filename.");
+        }
+
+        // Attempt to read valid table with wrong indexCol
+        psFree(table1);
+        table1 = psLookupTableAlloc("table.dat",
+                                "\%f \%d \%d \%ld \%d \%d \%d \%ld \%*d \%lf", 10);
+        numRows = psLookupTableRead(table1);
+        {
+            ok( numRows == 0,
+                "psLookupTableRead:               return correct number of rows for valid inputs.");
+        }
+        // Attempt to read valid table
+        psFree(table1);
+        table1 = psLookupTableAlloc("table.dat",
+                                    "\%f \%d \%d \%ld \%d \%d \%d \%ld \%*d \%lf", 0);
+        numRows = psLookupTableRead(table1);
+        {
+            ok( numRows == 4,
+                "psLookupTableRead:               return correct number of rows for valid inputs.");
+        }
+
+        //Tests for psLookupTableImport (remaining cases)
+        // Attempt to import table with negative indexCol
+        vectors = psVectorsReadFromFile(table1->filename, table1->format);
+        {
+            ok( !psLookupTableImport(table1, vectors, -1 ),
+                "psLookupTableImport:             return false for negative indexCol input.");
+        }
+        //Attempt to import table with unsorted array column
+        psFree(table1);
+        table1 = psLookupTableAlloc("table.dat",
+                                    "\%f \%d \%d \%ld \%d \%d \%d \%ld \%*d \%lf", 0);
+        {
+            ok( psLookupTableImport(table1, vectors, 7 ),
+                "psLookupTableImport:             return true for array with unsorted column");
+        }
+
+        psFree(vectors);
+        psFree(outVec);
+        psFree(table1);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testLookupTableInterpolates()
+    // psLookupTableInterpolate & psLookupTableInterpolateAll Fxns
+    {
+        psMemId id = psMemGetId();
+        psLookupTable *table1 = NULL;
+        psVector *vec = NULL;
+        // XXX: Remove the "types" path here
+        table1 = psLookupTableAlloc("table.dat",
+                                    "\%f \%d \%d \%ld \%d \%d \%d \%ld \%*d \%lf", 0);
+        psLookupTable *table2 = NULL;
+        // XXX: Remove the "types" path here
+        table2 = psLookupTableAlloc("table.dat",
+                                    "\%f \%d \%d \%ld \%d \%d \%d \%ld \%*d \%lf", 0);
+        psLookupTableRead(table2);
+    
+        //Tests for psLookupTableInterpolateAll
+        //Return NULL for NULL table input
+        {
+            vec = psLookupTableInterpolateAll(NULL, 0);
+            ok( vec == NULL,
+                "psLookupTableInterpolateAll:     return NULL for NULL table input.");
+        }
+        //Return NULL for NULL table values
+        {
+            vec = psLookupTableInterpolateAll(table1, 0);
+            ok( vec == NULL,
+                "psLookupTableInterpolateAll:     return NULL for NULL table values.");
+        }
+    
+        ok(table2->values != NULL, "table->values not NULL");
+	skip_start (!table2->values, 3, "skipping for failed table load");
+        //Return NULL for table with table->values->n == 0
+        {
+            long n = table2->values->n;
+            table2->values->n = 0;
+            vec = psLookupTableInterpolateAll(table2, 0);
+            ok( vec == NULL,
+                "psLookupTableInterpolateAll:     return NULL for table with no columns.");
+            table2->values->n = n;
+        }
+        //Return NULL for invalid index input
+        {
+            vec = psLookupTableInterpolateAll(table2, -10.5);
+            ok( vec == NULL,
+                "psLookupTableInterpolateAll:     return NULL for invalid index input.");
+        }
+        //Return correct vector output for valid inputs
+        {
+            vec = psLookupTableInterpolateAll(table2, 1);
+            skip_start(  vec == NULL, 1,
+                         "Skipping 1 tests because psLookupTableInterpolateAll failed");
+            is_double(vec->data.F64[0], 1.0,
+                      "psLookupTableInterpolateAll:     return correct output vector for valid inputs.");
+            skip_end();
+        }
+	skip_end();
+    
+        //Remaining tests for psLookupTableInterpolate
+        //Return NAN for invalid index - divide by zero error
+        psLookupTable *table3 = NULL;
+        table3 = psLookupTableAlloc("table2.dat",
+                                    "\%f \%d \%d \%ld \%d \%d \%d \%ld \%*d \%lf", 0);
+        psLookupTableRead(table3);
+        {
+            double retVal;
+            retVal = psLookupTableInterpolate(table3, 1.5e-20, 0);
+            ok( isnan(retVal),
+                "psLookupTableInterpolateAll:     return NAN for invalid index input.");
+        }
+    
+        psFree(table3);
+        psFree(vec);
+        psFree(table2);
+        psFree(table1);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfigFormat.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfigFormat.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfigFormat.c	(revision 22158)
@@ -0,0 +1,161 @@
+/**
+ *  C Implementation: tap_psMetadataConfigFormat.c
+ *
+ * Description:  Tests for psMetadataConfigFormat
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <pslib.h>
+#include <string.h>
+#include "tap.h"
+#include "pstap.h"
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(18);
+
+    psMetadata *md = NULL;
+    psString out = NULL;
+    //psString psMetadataConfigFormat(psMetadata *md);
+    //Return NULL for NULL metadata input
+    {
+        psMemId id = psMemGetId();
+        out = psMetadataConfigFormat(md);
+        ok( !out, "psMetadataConfigFormat:         return NULL for NULL metadata input.");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for empty metadata input
+    {
+        md = psMetadataAlloc();
+        out = psMetadataConfigFormat(md);
+        ok( out, "psMetadataConfigFormat:         return valid string for empty metadata input.");
+	skip_start (!out, 1, "failed to build valid string");
+        ok( *out == 0, "psMetadataConfigFormat:         return empty string for empty metadata input.");
+	psFree (out);
+	skip_end();
+    }
+
+
+    //Return NULL for metadata with missing hash table
+    {
+        psMetadataAddS32(md, PS_LIST_HEAD, "new_S32", 0, "", 666);
+        psMetadataAddS32(md, PS_LIST_HEAD, "new_S32", PS_META_DUPLICATE_OK, "", 665);
+        psHash *temp = md->hash;
+        md->hash = NULL;
+        out = psMetadataConfigFormat(md);
+        ok( out == NULL,
+            "psMetadataConfigFormat:         return NULL for metadata with missing "
+            "hash table.");
+        md->hash = temp;
+    }
+
+
+    //Return NULL for metadata containing a psList
+    {
+        psList *list = psListAlloc(NULL);
+        psMetadataAddList(md, PS_LIST_HEAD, "new_list", 0, "", list);
+        out = psMetadataConfigFormat(md);
+        ok( out == NULL,
+            "psMetadataConfigFormat:         return NULL for metadata containing a psList.");
+        psFree(list);
+        psFree(md);
+    }
+
+
+    //Return NULL for attempting to format psTime with type = -1
+    {
+        psMemId id = psMemGetId();
+        md = psMetadataAlloc();
+        psTime *time = psTimeAlloc(PS_TIME_TT);
+        time->type = -1;
+        psMetadataAddTime(md, PS_LIST_TAIL, "time", 0, "", time);
+        out = psMetadataConfigFormat(md);
+        ok( out == NULL,
+            "psMetadataConfigFormat:         return NULL for metadata containing a "
+            "invalid time type.");
+        psFree(time);
+        psFree(md);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return valid metadata for attempting to format NULL psTime metadataItem
+    {
+        psMemId id = psMemGetId();
+        md = psMetadataAlloc();
+        psTime *time = psTimeAlloc(PS_TIME_TT);
+        psMetadataAddTime(md, PS_LIST_HEAD, "time", 0, "", time);
+        psMetadataItem *item = psMetadataGet(md, PS_LIST_HEAD);
+        psFree(item->data.V);
+        item->data.V = NULL;
+        out = psMetadataConfigFormat(md);
+        ok( out != NULL,
+            "psMetadataConfigFormat:         return valid metadata for metadata "
+            "containing a NULL time.");
+        char configTest[32];
+        strncpy(configTest, "time             TAI       NULL", 31);
+        is_strn(configTest, out, 31,
+                "psMetadataConfigFormat:         return correct output string.");
+        psFree(time);
+        psFree(out);
+        out = NULL;
+        psFree(md);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return valid metadata for attempting to format NULL psTime metadataItem
+    {
+        psMemId id = psMemGetId();
+        md = psMetadataAlloc();
+        psMetadataAddS32(md, PS_LIST_HEAD, "new_S32", 0, NULL, 666);
+        psMetadataAddS32(md, PS_LIST_HEAD, "new_S32", PS_META_DUPLICATE_OK, NULL, 665);
+        out = psMetadataConfigFormat(md);
+        ok( out != NULL,
+            "psMetadataConfigFormat:         return valid metadata for metadata "
+            "containing a NULL time.");
+        char configTest[62];
+        strncpy(configTest, "new_S32 MULTI\nnew_S32          S32       666", 61);
+        is_strn(configTest, out, strlen(configTest),
+                "psMetadataConfigFormat:         return correct output string.");
+        psFree(out);
+        out = NULL;
+        psFree(md);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return valid metadata for attempting to format NULL psTime metadataItem
+    {
+        psMemId id = psMemGetId();
+        md = psMetadataAlloc();
+        psMetadataAddS32(md, PS_LIST_HEAD, "f32", 0, "f32_1", 666);
+        psMetadataAddS32(md, PS_LIST_TAIL, "f32", PS_META_DUPLICATE_OK, "f32_3", 666);
+        psMetadataAddS32(md, PS_LIST_TAIL, "f32", PS_META_DUPLICATE_OK, "f32_2", 665);
+        out = psMetadataConfigFormat(md);
+        ok( out != NULL,
+            "psMetadataConfigFormat:         return valid metadata for metadata "
+            "containing a NULL time.");
+        char configTest[201];
+        strncpy(configTest,
+                "f32 MULTI"
+                "\nf32              S32       666              # f32_1"
+                "\nf32              S32       666              # f32_3"
+                "\nf32              S32       665              # f32_2", 200);
+        is_strn(configTest, out, strlen(configTest),
+                "psMetadataConfigFormat:         return correct output string.");
+        psFree(out);
+        out = NULL;
+        psFree(md);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    done();
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfigParse.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfigParse.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfigParse.c	(revision 22158)
@@ -0,0 +1,154 @@
+/**
+ * tap_psMetdataConfigParse.c
+ *
+ * Description:  Tests for psMetadataConfigParse
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ * Author: Joshua Hoblitt, University of Hawaii, 2006
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <pslib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "tap.h"
+#include "pstap.h"
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(35);
+
+
+    // Return NULL for NULL string input
+    {
+        psMemId id = psMemGetId();
+        unsigned int nfail = 0;
+        psMetadata *md = psMetadataConfigParse(NULL, &nfail, NULL, false);
+
+        ok(md == NULL, "return NULL for NULL string input.");
+
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return empty metadata for incorrect string input
+    {
+        psMemId id = psMemGetId();
+        char *str = "-10.05    2        4";
+        psMetadata *md = psMetadataConfigParse(NULL, NULL, str, false);
+
+        ok(md == NULL, "return NULL for 1 invalid line");
+
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return correct metadata for correct string input - S32
+    {
+        psMemId id = psMemGetId();
+        char *str = "new S32       666";
+        psMetadata *md = psMetadataConfigParse(NULL, NULL, str, false);
+        psMetadataItem *item = psMetadataGet(md, PS_LIST_HEAD);
+
+        ok(md != NULL, "return correct metadata for 1 valid line");
+        skip_start(item == NULL, 2,
+                     "Skipping 1 tests because metadata container is empty!");
+        ok(item->type == PS_TYPE_S32, "return correcot metdataItem type");
+        is_int(item->data.S32, 666, "return correct metadataItem data");
+        is_str(item->name, "new", "return correct metadataItem name");
+        is_str(item->comment, "", "return correct metadataItem comment");
+        skip_end();
+
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return correct metadata for correct string input - F64
+    {
+        psMemId id = psMemGetId();
+        char *str = "item4            F64       6.28";
+        psMetadata *md = psMetadataConfigParse(NULL, NULL, str, false);
+        psMetadataItem *item = psMetadataGet(md, PS_LIST_HEAD);
+
+        ok(md != NULL, "return correct metadata for valid string input.");
+        ok(item != NULL, "return correct metadata for valid string input.");
+        skip_start(item == NULL, 2,
+                "Skipping 1 tests because metadata container is empty!");
+        ok(item->type == PS_DATA_F64, "return correct metadataItem type");
+        is_float(6.28, item->data.F64, "return correct metadataItem data");
+        is_str(item->name, "item4", "return correct metadataItem name");
+        is_str(item->comment, "", "return correct metadataItem comment");
+        skip_end();
+
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return correct metadata for string with duplicate entry - S8
+    {
+        psMemId id = psMemGetId();
+        char *str = "item8            S8        3\nitem8            S8        5";
+        unsigned int nfail = 0;
+        psMetadata *md = psMetadataConfigParse(NULL, &nfail, str, false);
+        psMetadataItem *item = psMetadataGet(md, PS_LIST_HEAD);
+
+        ok(md != NULL, "return metadata for 1 good & 1 duplicate (bad) line");
+        ok(item != NULL, "return non-empty metdata");
+        is_long(md->list->n, 1, "# of metdataItems");
+        is_int(nfail, 1, "number of parse failures");
+        skip_start(item == NULL, 2,
+                "Skipping 1 tests because metadata container is empty!");
+        ok(item->type == PS_TYPE_S8, "metdataItem type");
+        is_int(item->data.S8, 3, "metdataItem value");
+        is_str(item->name, "item8", "return correct metadataItem name");
+        is_str(item->comment, "", "return correct metadataItem comment");
+        skip_end();
+        psFree(md);
+
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return correct metadata for correct string input - Vector
+    {
+        psMemId id = psMemGetId();
+        char *str = "@vector6 U8 1 2 3 4 5   # I am a vector";
+        psMetadata *md = psMetadataConfigParse(NULL, NULL, str, true);
+        psMetadataItem *item = psMetadataGet(md, PS_LIST_HEAD);
+
+        ok(md != NULL, "return metadata for valid string input. (Vector)");
+        ok(item != NULL, "non-empty metadata");
+        skip_start(item == NULL, 2,
+                     "Skipping 1 tests because metadata container is empty!");
+        ok(item->type == PS_DATA_VECTOR, "metadataItem type");
+        is_int(((psVector*)(item->data.V))->data.U8[0], 1,
+                "return correct metadataItem data (Vector)");
+        is_str(item->name, "vector6",
+                "return correct metadataItem name (Vector)");
+        is_str(item->comment, "I am a vector", "return correct metadataItem comment");
+        skip_end();
+
+        psFree(md);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return empty metadata for incorrect string input
+    {
+        psMemId id = psMemGetId();
+        char *str = "END\n";
+        psMetadata *md = psMetadataConfigParse(NULL, NULL, str, false);
+
+        ok(md == NULL, "return NULL on 1 invalid line");
+
+        psFree(md);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfigParse_time.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfigParse_time.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfigParse_time.c	(revision 22158)
@@ -0,0 +1,157 @@
+#include <stdio.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+int main (void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(39 + 1);
+
+
+    {
+        psMemId id = psMemGetId();
+        char *testStr = "time    UTC     2005-03-18T16:05:00Z\n";
+        psU32 nBad = 0;
+        psMetadata *md = psMetadataConfigParse(NULL, &nBad, testStr, false);
+        psTime *time1 = psMetadataLookupTime(NULL, md, "time");
+        psTime *time2 = psTimeFromISO("2005-03-18T16:05:00Z", PS_TIME_UTC);
+        double delta = psTimeDelta(time1, time2);
+        psFree(time2);
+
+        ok(md, "md = %x", md);
+        ok(nBad == 0, "number of bad lines = %d", nBad); // One bad line from boolean
+        ok(md->list->n == 1, "number of items in metadata = %ld", md->list->n);
+        ok1(time1->type == PS_TIME_UTC);
+        ok(delta == 0.0, "reported time was off by %fs", delta);
+
+        psFree(md);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        char *testStr = "time    UT1     2005-03-18T16:05:00Z\n";
+        psU32 nBad = 0;
+        psMetadata *md = psMetadataConfigParse(NULL, &nBad, testStr, false);
+        psTime *time1 = psMetadataLookupTime(NULL, md, "time");
+        psTime *time2 = psTimeFromISO("2005-03-18T16:05:00Z", PS_TIME_UT1);
+        double delta = psTimeDelta(time1, time2);
+        psFree(time2);
+
+        ok(md, "md = %x", md);
+        ok(nBad == 0, "number of bad lines = %d", nBad);
+        ok(md->list->n == 1, "number of items in metadata = %ld", md->list->n);
+        ok1(time1->type == PS_TIME_UT1);
+        ok(delta == 0.0, "reported time was off by %fs", delta);
+
+        psFree(md);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        char *testStr = "time    TAI     2005-03-18T16:05:00Z\n";
+        psU32 nBad = 0;
+        psMetadata *md = psMetadataConfigParse(NULL, &nBad, testStr, false);
+        psTime *time1 = psMetadataLookupTime(NULL, md, "time");
+        psTime *time2 = psTimeFromISO("2005-03-18T16:05:00Z", PS_TIME_TAI);
+        double delta = psTimeDelta(time1, time2);
+        psFree(time2);
+
+        ok(md, "md = %x", md);
+        ok(nBad == 0, "number of bad lines = %d", nBad);
+        ok(md->list->n == 1, "number of items in metadata = %ld", md->list->n);
+        ok1(time1->type == PS_TIME_TAI);
+        ok(delta == 0.0, "reported time was off by %fs", delta);
+
+        psFree(md);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        char *testStr = "time    TT      2005-03-18T16:05:00Z";
+        psU32 nBad = 0;
+        psMetadata *md = psMetadataConfigParse(NULL, &nBad, testStr, false);
+        psTime *time1 = psMetadataLookupTime(NULL, md, "time");
+        psTime *time2 = psTimeFromISO("2005-03-18T16:05:00Z", PS_TIME_TT);
+        double delta = psTimeDelta(time1, time2);
+        psFree(time2);
+
+        ok(md, "md = %x", md);
+        ok(nBad == 0, "number of bad lines = %d", nBad);
+        ok(md->list->n == 1, "number of items in metadata = %ld", md->list->n);
+        ok1(time1->type == PS_TIME_TT);
+        ok(delta == 0.0, "reported time was off by %fs", delta);
+
+        psFree(md);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        // missing Z
+        char *testStr = "broken      UTC     2005-03-18T16:05:00";
+        psU32 nBad = 0;
+        psMetadata *md = psMetadataConfigParse(NULL, &nBad, testStr, false);
+
+        ok(md, "returned metdata");
+        is_int(nBad, 0, "number of bad lines");
+        is_long(psListLength(md->list), 1, "number of items in metadata");
+
+        psFree(md);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    {
+        psMemId id = psMemGetId();
+        // missing Z
+        char *testStr = "broken      UT1     2005-03-18T16:05:00";
+        psU32 nBad = 0;
+        psMetadata *md = psMetadataConfigParse(NULL, &nBad, testStr, false);
+
+        ok(md, "returned metdata");
+        is_int(nBad, 0, "number of bad lines");
+        is_long(psListLength(md->list), 1, "number of items in metadata");
+
+        psFree(md);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    {
+        psMemId id = psMemGetId();
+        // missing Z
+        char *testStr = "broken      TAI     2005-03-18T16:05:00";
+        psU32 nBad = 0;
+        psMetadata *md = psMetadataConfigParse(NULL, &nBad, testStr, false);
+
+        ok(md, "returned metdata");
+        is_int(nBad, 0, "number of bad lines");
+        is_long(psListLength(md->list), 1, "number of items in metadata");
+
+        psFree(md);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+        // missing Z
+        char *testStr = "broken      TT      2005-03-18T16:05:00";
+        psU32 nBad = 0;
+        psMetadata *md = psMetadataConfigParse(NULL, &nBad, testStr, false);
+
+        ok(md, "returned metdata");
+        is_int(nBad, 0, "number of bad lines");
+        is_long(psListLength(md->list), 1, "number of items in metadata");
+
+        psFree(md);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfigPrint.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfigPrint.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfigPrint.c	(revision 22158)
@@ -0,0 +1,115 @@
+/**
+ *  C Implementation: tap_psMetadataConfig_output
+ *
+ * Description:  Tests for psMetadataConfigPrint 
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <pslib.h>
+#include <string.h>
+#include "tap.h"
+#include "pstap.h"
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(11);
+
+
+    //Return false for NULL metadata input
+    {
+        psMemId id = psMemGetId();
+        FILE *openfile = fopen("mdcfg.prt", "w+");
+
+        ok(!psMetadataConfigPrint(openfile, NULL),
+           "return false for NULL metadata input.");
+
+        fclose(openfile);
+        remove("mdcfg.prt");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return true for empty metadata input (creates an empty file; is not an error)
+    {
+        psMemId id = psMemGetId();
+        FILE *openfile = fopen("mdcfg.prt", "w+");
+        psMetadata *md = psMetadataAlloc();
+
+        ok(psMetadataConfigPrint(openfile, md), "return true for empty metadata input.");
+
+        psFree(md);
+        fclose(openfile);
+        remove("mdcfg.prt");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return false for NULL file input
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = psMetadataAlloc();
+        psMetadataAddS32(md, PS_LIST_HEAD, "new S32", 0, "", 666);
+
+        ok(!psMetadataConfigPrint(NULL, md),
+           "return false for NULL FILE* input.");
+
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return false for read-only file input
+    {
+        psMemId id = psMemGetId();
+        // create an empty file to open read only later
+        {
+            FILE *openfile = fopen("mdcfg.prt", "w");
+            fclose(openfile);
+        }
+
+        FILE *openfile = fopen("mdcfg.prt", "r");
+        psMetadata *md = psMetadataAlloc();
+        psMetadataAddS32(md, PS_LIST_HEAD, "new S32", 0, "", 666);
+
+        ok(!psMetadataConfigPrint(openfile, md),
+           "return false for read-only FILE* input.");
+
+        psFree(md);
+        fclose(openfile);
+        remove("mdcfg.prt");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return true for valid inputs
+    {
+        psMemId id = psMemGetId();
+        FILE *openfile = fopen("mdcfg.prt", "w+");
+        psMetadata *md = psMetadataAlloc();
+        psMetadataAddS32(md, PS_LIST_HEAD, "new S32", 0, "", 666);
+
+        ok(psMetadataConfigPrint(openfile, md),
+           "return true for valid inputs.");
+
+        psFree(md);
+        fclose(openfile);
+
+        char fileStr2[62];
+        memset(fileStr2, '\0', 62);
+        FILE *mdcfg = fopen("mdcfg.prt", "r");
+
+        fread(fileStr2, 1, 31, mdcfg);
+
+        is_strn(fileStr2, "\nnew S32          S32       666 ", 30,
+                "return correct output.");
+
+        fclose(mdcfg);
+        remove("mdcfg.prt");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfigRead.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfigRead.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfigRead.c	(revision 22158)
@@ -0,0 +1,280 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <pslib.h>
+#include <string.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+#define FILENAME "tap_psMetadataConfigRead.config"
+
+#define STRING1 "# This is a comment that should be ignored\n"
+#define STRING2 "\t\t\tSomeString   STR    This is a string     # This is the comment    \n"
+#define STRING3 "      \t       vAlUes\t\t\t\tMETADATA\t\t\t\n"
+#define STRING3a "aFloat\tF32\t1.2345\t#A number with a decimal point\n"
+#define STRING3b "                                                anInt S32 98765\n"
+#define STRING3c "\t\t\t\t\t\t\t\t\t\t\t\t\tEND\n"
+#define STRING4 "Numbers\tMULTI\t\n"
+#define STRING5 "Numbers F32 1.23#Number one\n"
+#define STRING6 "        \t           \t                                \t              \n"
+#define STRING7 "Numbers\t\t\tSTR One point two three   #Number two\n"
+#define STRING8 "Numbers                                      BOOL 1#This is true\n"
+#define STRING9 "   \tboolean BOOL TRUEsomeTimesButFALSEatOthers#This should fail\n"
+#define STRING10 "SomeBoolean BOOL false\n"
+
+#define NAME2 "SomeString"
+#define TYPE2 PS_DATA_STRING
+#define MIX2 string
+#define VALUE2 "This is a string"
+#define COMMENT2 "This is the comment"
+
+#define NAME3 "vAlUes"
+#define TYPE3 PS_DATA_METADATA
+#define VALUE3 NULL                     // Not really, but serves as a placeholder
+#define COMMENT3 ""
+
+#define NAME3a "aFloat"
+#define TYPE3a PS_TYPE_F32
+#define MIX3a real
+#define VALUE3a 1.2345
+#define COMMENT3a "A number with a decimal point"
+
+#define NAME3b "anInt"
+#define TYPE3b PS_TYPE_S32
+#define MIX3b integer
+#define VALUE3b 98765
+#define COMMENT3b ""
+
+#define NAME5 "Numbers"
+#define TYPE5 PS_TYPE_F32
+#define MIX5 real
+#define VALUE5 1.23
+#define COMMENT5 "Number one"
+
+#define NAME7 "Numbers"
+#define TYPE7 PS_DATA_STRING
+#define MIX7 string
+#define VALUE7 "One point two three"
+#define COMMENT7 "Number two"
+
+#define NAME8 "Numbers"
+#define TYPE8 PS_TYPE_BOOL
+#define MIX8 boolean
+#define VALUE8 1
+#define COMMENT8 "This is true"
+
+#define NAME10 "SomeBoolean"
+#define TYPE10 PS_TYPE_BOOL
+#define MIX10 boolean
+#define VALUE10 0
+#define COMMENT10 ""
+
+#define MULTI_NAME "Numbers"
+
+#define BAD_NAME "boolean"
+
+typedef union {
+    const char *string;
+    float real;
+    int integer;
+    bool boolean;
+} mixedType;
+
+
+// Generate the metadata config file to be parsed
+static void generateMDConfig(void)
+{
+    FILE *fp = fopen(FILENAME, "w");    // Configuration file
+    fprintf(fp, "%s", STRING1);
+    fprintf(fp, "%s", STRING2);
+    fprintf(fp, "%s", STRING3);
+    fprintf(fp, "%s", STRING3a);
+    fprintf(fp, "%s", STRING3b);
+    fprintf(fp, "%s", STRING3c);
+    fprintf(fp, "%s", STRING4);
+    fprintf(fp, "%s", STRING5);
+    fprintf(fp, "%s", STRING6);
+    fprintf(fp, "%s", STRING7);
+    fprintf(fp, "%s", STRING8);
+    fprintf(fp, "%s", STRING9);
+    fprintf(fp, "%s", STRING10);
+    fclose(fp);
+}
+
+static void *testItem(const psMetadataItem *item, // Item to check
+                      const char *name, // Name of the item
+                      int type, // Type for item
+                      const char *comment, // Comment for the item
+                      mixedType value // Value for the item
+                     )
+{
+    psMemId id = psMemGetId();
+    skip_start(!item, 3, "Skipping 4 tests because !item");
+    ok(strcmp(item->name, name) == 0, "item->name = %s", item->name);
+    ok(strcmp(item->comment, comment) == 0, "item->comment = %s", item->comment);
+    ok(item->type == type, "item->type = %x", item->type);
+    skip_end();
+
+    if (item->type == PS_DATA_METADATA || item->type == PS_DATA_METADATA_MULTI) {
+        return item->data.V;
+    }
+
+    skip_start(item->type != type, 1, "Skipping 1 test because the item has incorrect type");
+    switch (item->type) {
+    case PS_DATA_STRING: {
+            ok(strcmp(item->data.V, value.string) == 0, "item->data.V = %s", item->data.V);
+            break;
+        }
+    case PS_TYPE_F32: {
+            ok(item->data.F32 == value.real, "item->data.F32 = %f", item->data.F32);
+            break;
+        }
+    case PS_TYPE_S32: {
+            ok(item->data.S32 == value.integer, "item->data.S32 = %d", item->data.S32);
+            break;
+        }
+    case PS_TYPE_BOOL: {
+            ok(item->data.B == value.boolean, "item->data.B = %d", item->data.B);
+            break;
+        }
+    default: {
+            ok(false, "Unknown item->type = %x", item->type);
+        }
+    }
+    skip_end();
+    ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    return NULL;
+}
+
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(62);
+
+    generateMDConfig();
+
+    unsigned int numBadLines = 0;            // Number of bad lines
+    psMetadata *md = psMetadataConfigRead(NULL, &numBadLines, FILENAME, false);
+    unlink (FILENAME);
+
+    ok(md, "md = %x", md);
+    is_int(numBadLines, 1, "number of bad lines"); // One bad line from boolean
+    skip_start(!md || numBadLines != 1, 0,
+               "Skipping 0 tests because psMetadataConfigRead failed.");
+    ok(psListLength(md->list) == 6, "size = %d", psListLength(md->list));
+
+    {
+        // Go through and make sure everything's there
+        psMetadataIterator *iterator = psMetadataIteratorAlloc(md, PS_LIST_HEAD, NULL); // Iterator
+
+        {
+            psMetadataItem *item = psMetadataGetAndIncrement(iterator);
+            mixedType value;
+            value.MIX2 = VALUE2;
+            testItem(item, NAME2, TYPE2, COMMENT2, value);
+        }
+
+        {
+            psMetadataItem *item = psMetadataGetAndIncrement(iterator);
+            mixedType value;            // Needed only to check the other stuff
+            psMetadata *nested = testItem(item, NAME3, TYPE3, COMMENT3, value);
+            ok(psListLength(nested->list) == 2, "size = %d", psListLength(nested->list));
+            skip_start(psListLength(nested->list) != 2, 8, "Skipping 8 tests because wrong size");
+            psMetadataIterator *nestedIter = psMetadataIteratorAlloc(nested, PS_LIST_HEAD, NULL);
+
+            {
+                psMetadataItem *item = psMetadataGetAndIncrement(nestedIter);
+                mixedType value;
+                value.MIX3a = VALUE3a;
+                testItem(item, NAME3a, TYPE3a, COMMENT3a, value);
+            }
+
+            {
+                psMetadataItem *item = psMetadataGetAndIncrement(nestedIter);
+                mixedType value;
+                value.MIX3b = VALUE3b;
+                testItem(item, NAME3b, TYPE3b, COMMENT3b, value);
+            }
+
+            psFree(nestedIter);
+            skip_end();
+        }
+
+        {
+            psMetadataItem *item = psMetadataGetAndIncrement(iterator);
+            mixedType value;
+            value.MIX5 = VALUE5;
+            testItem(item, NAME5, TYPE5, COMMENT5, value);
+        }
+
+        {
+            psMetadataItem *item = psMetadataGetAndIncrement(iterator);
+            mixedType value;
+            value.MIX7 = VALUE7;
+            testItem(item, NAME7, TYPE7, COMMENT7, value);
+        }
+
+        {
+            psMetadataItem *item = psMetadataGetAndIncrement(iterator);
+            mixedType value;
+            value.MIX8 = VALUE8;
+            testItem(item, NAME8, TYPE8, COMMENT8, value);
+        }
+
+        {
+            psMetadataItem *item = psMetadataGetAndIncrement(iterator);
+            mixedType value;
+            value.MIX10 = VALUE10;
+            testItem(item, NAME10, TYPE10, COMMENT10, value);
+        }
+
+        psFree(iterator);
+    }
+
+    {
+        // Check that the correct item is MULTI
+        psMetadataItem *item = psMetadataLookup(md, MULTI_NAME);
+        mixedType value;                // Needed only so we can test other stuff
+        psList *multi = testItem(item, MULTI_NAME, PS_DATA_METADATA_MULTI, "", value);
+        ok(psListLength(multi) == 3, "length = %d", psListLength(multi));
+        skip_start(psListLength(multi) != 3, 12, "Skipping 12 tests because MULTI failed.");
+        psListIterator *multiIter = psListIteratorAlloc(multi, PS_LIST_HEAD, false); // Iterator
+
+        {
+            psMetadataItem *item = psListGetAndIncrement(multiIter);
+            mixedType value;
+            value.MIX5 = VALUE5;
+            testItem(item, NAME5, TYPE5, COMMENT5, value);
+        }
+
+        {
+            psMetadataItem *item = psListGetAndIncrement(multiIter);
+            mixedType value;
+            value.MIX7 = VALUE7;
+            testItem(item, NAME7, TYPE7, COMMENT7, value);
+        }
+
+        {
+            psMetadataItem *item = psListGetAndIncrement(multiIter);
+            mixedType value;
+            value.MIX8 = VALUE8;
+            testItem(item, NAME8, TYPE8, COMMENT8, value);
+        }
+        psFree(multiIter);
+        skip_end();
+    }
+
+    {
+        // Check that the bad one isn't there
+        psMetadataItem *item = psMetadataLookup(md, BAD_NAME);
+        ok(!item, "item = %x", item);
+    }
+
+    skip_end();
+
+    psFree(md);
+
+    return exit_status();
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfigWrite.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfigWrite.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfigWrite.c	(revision 22158)
@@ -0,0 +1,86 @@
+/**
+ *  C Implementation: tap_psMetadataConfigWrite
+ *
+ * Description:  Tests for psMetadataConfigWrite
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <pslib.h>
+#include <string.h>
+#include "tap.h"
+#include "pstap.h"
+
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(11);
+
+
+    //Return false for NULL metadata input
+    {
+        psMemId id = psMemGetId();
+        ok( !psMetadataConfigWrite(NULL, "mdcfg.wrt"),
+            "return false for NULL metadata input.");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return false for NULL filename input
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = psMetadataAlloc();
+        ok( !psMetadataConfigWrite(md, NULL),
+            "return false for NULL filename input.");
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return false for invalid filename input
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = psMetadataAlloc();
+        ok( !psMetadataConfigWrite(md, "."),
+            "return false for invalid filename input.");
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return true for empty metadata input (creates an empty file)
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = psMetadataAlloc();
+        ok(psMetadataConfigWrite(md, "mdcfg.wrt"), "return false for empty metadata input.");
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return true for valid inputs
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = psMetadataAlloc();
+        psMetadataAddBool(md, PS_LIST_TAIL, "item1-1", 0, "I am a boolean", true);
+        ok( psMetadataConfigWrite(md, "mdcfg.wrt"),
+            "return true for valid inputs.");
+        char configTest[61];
+        char fileStr[62];
+        FILE *mdcfg = fopen("mdcfg.wrt", "r");
+        fgets(fileStr, 61, mdcfg);
+        strncpy(configTest,
+                "item1-1          BOOL      T                # I am a boolean", 60);
+        is_strn(configTest, fileStr, 60,
+                "return correct output.");
+        fclose(mdcfg);
+        remove
+            ("mdcfg.wrt");
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfig_input.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfig_input.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataConfig_input.c	(revision 22158)
@@ -0,0 +1,136 @@
+/**
+ * tap_psMetdataConfig_input.c
+ *
+ * Description:  Tests for psMetadataConfigRead
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ * Author: Joshua Hoblitt, University of Hawaii 2007
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <pslib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "tap.h"
+#include "pstap.h"
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(30);
+
+
+    // Return NULL for NULL filename input
+    {
+        psMemId id = psMemGetId();
+        unsigned int nfail = 0;
+        psMetadata *md = psMetadataConfigRead(NULL, &nfail, NULL, false);
+        ok(md == NULL, "return NULL for NULL filename input.");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return NULL for invalid filename input
+    {
+        psMemId id = psMemGetId();
+        unsigned int nfail = 0;
+        psMetadata *md = psMetadataConfigRead(NULL, &nfail, ".", false);
+        ok(md == NULL, "return NULL for invalid filename input.");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return NULL for missing file input
+    {
+        psMemId id = psMemGetId();
+        unsigned int nfail = 0;
+        psMetadata *md = psMetadataConfigRead(NULL, &nfail, "table4.dat", false);
+        ok(md == NULL, "return NULL for missing file input.");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return NULL for read-only file with comments, bad syntax, and no good
+    // lines
+    {
+        psMemId id = psMemGetId();
+        unsigned int nfail = 0;
+        psMetadata *md = psMetadataConfigRead(NULL, &nfail, "table3.dat", false);
+        ok(md == NULL, "return NULL for all bad syntax");
+        is_int(nfail, 0, "correct nfail");
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return true for valid inputs - overwrite = false
+    {
+        psMemId id = psMemGetId();
+        unsigned int nfail = 0;
+        psMetadata *md = psMetadataConfigRead(NULL, &nfail, "metaconf.in", false);
+
+        ok(md != NULL, "return metadata for valid input");
+        is_int(nfail, 27, "return correct nFail count");
+
+        skip_start(md == NULL, 8,
+                     "Skipping 1 tests because metadata container is empty!");
+
+        // look at the first item
+        psMetadataItem *item = psMetadataGet(md, PS_LIST_HEAD);
+        // XXX shouldn't assume item isn't NULL
+        is_str(item->name, "item1", "metadataItem name");
+        ok(item->type == PS_DATA_BOOL, "metadataItem type");
+        is_bool(item->data.B, true, "metdataItem value");
+        is_str(item->comment, "I am a boolean", "metadataItem comment.");
+
+        // look at the last item
+        item = psMetadataGet(md, PS_LIST_TAIL);
+        // XXX shouldn't assume item isn't NULL
+        is_str(item->name, "M2", "metadataItem name");
+        ok(item->type == PS_DATA_S32, "metdataItem type");
+        is_int(item->data.S32, 666, "metdataItem value");
+        is_str(item->comment, "this line is \"GOOD\" but parsed in the top level", "metadataItem comment.");
+        skip_end();
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return true for valid inputs - overwrite = true
+    {
+        psMemId id = psMemGetId();
+        unsigned int nfail = 0;
+        psMetadata *md = psMetadataConfigRead(NULL, &nfail, "metaconf.in", true);
+
+        ok(md != NULL, "return metadata for valid input");
+        is_int(nfail, 23, "return correct nFail count");
+
+        skip_start(md == NULL, 7,
+                     "Skipping 1 tests because metadata container is empty!");
+
+        // look at the first item
+        psMetadataItem *item = psMetadataGet(md, PS_LIST_HEAD);
+        // XXX shouldn't assume item isn't NULL
+        // note that item1 gets added to the "tail" of the metdata was it's
+        // replaced
+        is_str(item->name, "item2", "metadataItem name");
+        ok(item->type == PS_DATA_S32, "metdataItem type");
+        is_bool(item->data.S32, 55, "metadataItem value");
+        is_str(item->comment, "I am int", "metadataItem value");
+
+        // look at the last item
+        item = psMetadataGet(md, PS_LIST_TAIL);
+        // XXX shouldn't assume item isn't NULL
+        // meta1 is from "the bad section"
+        is_str(item->name, "meta1", "metadataItem name");
+        ok(item->type == PS_DATA_METADATA, "metadataItem type");
+
+        is_str(item->comment, "duplicate", "metadataItem comment");
+        skip_end();
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataItemCompare.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataItemCompare.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataItemCompare.c	(revision 22158)
@@ -0,0 +1,198 @@
+/**
+ *  C Implementation: tap_psMetadataItemCompare
+ *
+ * Description:  Tests for psMetadataItemCompare
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(22);
+
+    // psMetadataItemCompare() tests
+    {
+        psMemId id = psMemGetId();
+        psMetadataItem *compare = NULL;
+        psMetadataItem *template = NULL;
+        psMetadataItem *itemCopy = NULL;
+        psMetadataItem *item = psMetadataItemAlloc("Snickers", PS_DATA_BOOL, "No Comment", true)
+                               ;
+    
+        //Return false for NULL compare psMetadataItem
+        {
+            ok( !psMetadataItemCompare(compare, item),
+                "psMetadataItemCompare:      return false for NULL compare input." );
+        }
+        //Return false for NULL template psMetadataItem
+        {
+            ok( !psMetadataItemCompare(item, template),
+                "psMetadataItemCompare:      return false for NULL template input." );
+        }
+    
+        //Return false for psMetadataItem's with different names
+        {
+            template = psMetadataItemAlloc("Milky Way", PS_DATA_BOOL, "No Comment", true)
+                       ;
+            compare = psMetadataItemAlloc("Snickers", PS_DATA_S32, "No Comment", 1);
+            ok( !psMetadataItemCompare(template, item),
+                "psMetadataItemCompare:      return false for input with different names.");
+        }
+
+        //Return true for an exact match (copied psMetadataItem)
+        {
+            itemCopy = psMetadataItemCopy(item);
+            ok( psMetadataItemCompare(itemCopy, item),
+                "psMetadataItemCompare:      return true for comparison of identical psMetadataItem's.");
+        }
+    
+        //Return true for psMetadataItem's with different types but otherwise identical
+        {
+            ok( psMetadataItemCompare(compare, item),
+                "psMetadataItemCompare:      return true for valid compare of different type.");
+        }
+    
+        //Return true for comparing Bool with F64
+        {
+            psFree(compare);
+            compare = psMetadataItemAlloc("Snickers", PS_DATA_F64, "No Comment", 1.0000);
+            ok( psMetadataItemCompare(compare, item),
+                "psMetadataItemCompare:      return false for comparison of F64 to bool." );
+        }
+
+        //Return true for comparing F64 with Bool
+        {
+            ok( psMetadataItemCompare(item, compare),
+                "psMetadataItemCompare:      return false for comparison of bool to F64." );
+        }
+    
+        //Return true for comparing S32 with F32 of same value
+        {
+            psFree(template);
+            template = psMetadataItemAlloc("Snickers", PS_DATA_S32, "No Comment", 1);
+            psFree(compare);
+            compare = psMetadataItemAlloc("Snickers", PS_DATA_F32, "No Comment", 1.00);
+            ok( psMetadataItemCompare(compare, template),
+                "psMetadataItemCompare:      return true for comparison of S32 to F32." );
+        }
+
+        //Return true for comparing F32 with S32 of same value
+        {
+            ok( psMetadataItemCompare(template, compare),
+                "psMetadataItemCompare:      return true for comparison of F32 to S32." );
+        }
+    
+        //Return true for comparing U32 with S16 of same value
+        {
+            psFree(template);
+            template = psMetadataItemAlloc("Snickers", PS_DATA_S16, "No Comment", 1);
+            psFree(compare);
+            compare = psMetadataItemAlloc("Snickers", PS_DATA_U32, "No Comment", 1);
+            ok( psMetadataItemCompare(compare, template),
+                "psMetadataItemCompare:     return true for comparison of S16 to U32." );
+        }
+
+        //Return true for comparing S16 with U32 of same value
+        {
+            ok( psMetadataItemCompare(template, compare),
+                "psMetadataItemCompare:     return true for comparison of U32 to S16." );
+        }
+    
+        //Return true for comparing U8 with U16 of same value
+        {
+            psFree(template);
+            template = psMetadataItemAlloc("Snickers", PS_DATA_U8, "No Comment", 1);
+            psFree(compare);
+            compare = psMetadataItemAlloc("Snickers", PS_DATA_U16, "No Comment", 1);
+            ok( psMetadataItemCompare(compare, template),
+                "psMetadataItemCompare:     return true for comparison of U8 to U16." );
+        }
+
+        //Return true for comparing U16 with U8 of same value
+        {
+            ok( psMetadataItemCompare(template, compare),
+                "psMetadataItemCompare:     return true for comparison of U16 to U8." );
+        }
+    
+        //Return true for comparing U8 with S8 of same value
+        {
+            psFree(compare);
+            compare = psMetadataItemAlloc("Snickers", PS_DATA_S8, "No Comment", 1);
+            ok( psMetadataItemCompare(compare, template),
+                "psMetadataItemCompare:     return true for comparison of U8 to S8." );
+        }
+
+        //Return true for comparing S8 with U8 of same value
+        {
+            ok( psMetadataItemCompare(template, compare),
+               "psMetadataItemCompare:     return true for comparison of S8 to U8." );
+        }
+    
+        //Return false for comparing U8 with S64 of same value
+        {
+            psFree(compare);
+            compare = psMetadataItemAlloc("Snickers", PS_DATA_S64, "No Comment", 1);
+            ok( !psMetadataItemCompare(compare, template),
+                "psMetadataItemCompare:     return false for comparison of U8 to S64*.  "
+                "*not yet implemented" );
+        }
+
+        //Return false for comparing S64 with U8 of same value
+        {
+            ok( !psMetadataItemCompare(template, compare),
+                "psMetadataItemCompare:     return false for comparison of S64* to U8.  "
+                "*not yet implemented" );
+        }
+    
+        //Return false for comparing string of different value
+        {
+            psFree(compare);
+            compare = psMetadataItemAlloc("Snickers", PS_DATA_STRING, "No Comment",
+                                          "Not Going Anywhere?");
+            psFree(template);
+            template = psMetadataItemAlloc("Snickers", PS_DATA_STRING, "No Comment", "For a While?");
+            ok( !psMetadataItemCompare(compare, template),
+                "psMetadataItemCompare:     return false for comparison of different psString's.");
+        }
+    
+        //Return true for comparing string of same value
+        {
+            psFree(template);
+            template = psMetadataItemAlloc("Snickers", PS_DATA_STRING, "No Comment",
+                                           "Not Going Anywhere?");
+            ok( psMetadataItemCompare(compare, template),
+                "psMetadataItemCompare:     return true for comparison of identical psString's.");
+        }
+    
+        //Return false for comparing string with bool
+        {
+            psFree(template);
+            template = psMetadataItemAlloc("Snickers", PS_DATA_BOOL, "No Comment", false);
+            ok( !psMetadataItemCompare(compare, template),
+                "psMetadataItemCompare:     return false for comparison of psString with bool.");
+        }
+
+        //Return false for comparing bool with string
+        {
+            psFree(template);
+            template = psMetadataItemAlloc("Snickers", PS_DATA_BOOL, "No Comment", false);
+            ok( !psMetadataItemCompare(template, compare),
+                "psMetadataItemCompare:     return false for comparison of psString with bool.");
+        }
+    
+        psFree(compare);
+        psFree(template);
+        psFree(itemCopy);
+        psFree(item);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataItemParse.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataItemParse.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataItemParse.c	(revision 22158)
@@ -0,0 +1,519 @@
+/**
+ *  C Implementation: tap_psMetadataItemParse
+ *
+ * Description:  Tests for psMetadataItemParse
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <pslib.h>
+#include <string.h>
+#include "tap.h"
+#include "pstap.h"
+void testItemParse(void);
+
+int main (void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(112);
+
+    // psMetadataItemParse() tests
+    {
+        psMemId id = psMemGetId();
+        psMetadataItem *itemBool = psMetadataItemAlloc("bool", PS_DATA_BOOL, "No Comment", true);
+        psMetadataItem *itemF32 = psMetadataItemAlloc("f32", PS_DATA_F32, "No Comment", 0.00);
+        psMetadataItem *itemF64 = psMetadataItemAlloc("f64", PS_DATA_F64, "No Comment", 0.50);
+        psMetadataItem *itemS8 = psMetadataItemAlloc("s8", PS_DATA_S8, "No Comment", 1);
+        psMetadataItem *itemS16 = psMetadataItemAlloc("s16", PS_DATA_S16, "No Comment", 0);
+        psMetadataItem *itemS32 = psMetadataItemAlloc("s32", PS_DATA_S32, "No Comment", 1);
+        psMetadataItem *itemU8 = psMetadataItemAlloc("u8", PS_DATA_U8, "No Comment", 2);
+        psMetadataItem *itemU16 = psMetadataItemAlloc("u16", PS_DATA_U16, "No Comment", 0);
+        psMetadataItem *itemU32 = psMetadataItemAlloc("u32", PS_DATA_U32, "No Comment", 1);
+        psMetadataItem *itemString1 = psMetadataItemAlloc("String", PS_DATA_STRING, "", "true");
+        psMetadataItem *itemString2 = psMetadataItemAlloc("String", PS_DATA_STRING, "", "1.666");
+        psMetadataItem *itemString11 = psMetadataItemAlloc("String", PS_DATA_STRING, "", "false");
+        psMetadataItem *itemUnsupported = psMetadataItemAlloc("s64", PS_DATA_S64, "", 1);
+
+        //TESTS:  Bool, F32, F64, S8, S16, S32, U8, U16, U32, String
+        //BOOL Test
+        {
+            //Return false for NULL item
+            ok ( !psMetadataItemParseBool(NULL),
+                 "psMetadataItemParse:      return false in BOOL for NULL psMetadataItem "
+                 "input." );
+            //Return false for non-supported type S64
+            ok ( !psMetadataItemParseBool(itemUnsupported),
+                 "psMetadataItemParse:      return false in BOOL for S64 (unsupported) "
+                 "psMetadataItem input." );
+            //Return true for string with "true"
+            ok ( psMetadataItemParseBool(itemString1),
+                 "psMetadataItemParse:      return true in BOOL for string-item with "
+                 "value 'true'." );
+            //Return false for string with "false"
+            ok ( !psMetadataItemParseBool(itemString11),
+                 "psMetadataItemParse:      return false in BOOL for string-item with "
+                 "value 'false'." );
+            //Return false for F32 value 0.0
+            ok ( !psMetadataItemParseBool(itemF32),
+                 "psMetadataItemParse:      return false in BOOL for F32-item with "
+                 "value '0.0'." );
+            //Return true for F64 value 0.5
+            ok ( psMetadataItemParseBool(itemF64),
+                 "psMetadataItemParse:      return true in BOOL for F64-item with "
+                 "value '0.5'." );
+            //Return true for S8 value 1
+            ok ( psMetadataItemParseBool(itemS8),
+                 "psMetadataItemParse:      return true in BOOL for S8-item with "
+                 "value '1'." );
+            //Return false for S16 value 0
+            ok ( !psMetadataItemParseBool(itemS16),
+                 "psMetadataItemParse:      return false in BOOL for S16-item with "
+                 "value '0'." );
+            //Return true for S32 value 1
+            ok ( psMetadataItemParseBool(itemS32),
+                 "psMetadataItemParse:      return true in BOOL for S32-item with "
+                 "value '1'." );
+            //Return true for U8 value 2
+            ok ( psMetadataItemParseBool(itemU8),
+                 "psMetadataItemParse:     return true in BOOL for U8-item with "
+                 "value '2'." );
+            //Return false for U16 value 0
+            ok ( !psMetadataItemParseBool(itemU16),
+                 "psMetadataItemParse:     return false in BOOL for U16-item with "
+                 "value '0'." );
+            //Return true for U32 value 1
+            ok ( psMetadataItemParseBool(itemU32),
+                 "psMetadataItemParse:     return true in BOOL for U32-item with "
+                 "value '1'." );
+        }
+
+        //F32 Test
+        {
+            //Return NaN for NULL item
+            ok ( isnan(psMetadataItemParseF32(NULL)),
+                 "psMetadataItemParse:     return NaN for NULL psMetadataItem input." );
+            //Return NaN for non-supported type S64
+            ok ( isnan(psMetadataItemParseF32(itemUnsupported)),
+                 "psMetadataItemParse:     return NaN in F32 for S64 (unsupported) "
+                 "psMetadataItem input." );
+            //Return 1.666 for string with "1.666"
+            is_float( psMetadataItemParseF32(itemString2), 1.666,
+                      "psMetadataItemParse:     return 1.666 in F32 for string-item with "
+                      "value '1.666'." );
+            //Return 0.0 for F32 value 0.0
+            is_float( psMetadataItemParseF32(itemF32), 0.0,
+                      "psMetadataItemParse:     return 0.0 in F32 for F32-item with "
+                      "value '0.0'." );
+            //Return 0.5 for F64 value 0.5
+            is_float( psMetadataItemParseF32(itemF64), 0.5,
+                      "psMetadataItemParse:     return 0.5 in F32 for F64-item with "
+                      "value '0.5'." );
+            //Return 1.0 for S8 value 1
+            is_float( psMetadataItemParseF32(itemS8), 1.0,
+                      "psMetadataItemParse:     return 1.0 in F32 for S8-item with "
+                      "value '1'." );
+            //Return 0.0 for S16 value 0
+            is_float( psMetadataItemParseF32(itemS16), 0.0,
+                      "psMetadataItemParse:     return 0.0 in F32 for S16-item with "
+                      "value '0'." );
+            //Return 1.0 for S32 value 1
+            is_float( psMetadataItemParseF32(itemS32), 1.0,
+                      "psMetadataItemParse:     return 1.0 in F32 for S32-item with "
+                      "value '1'." );
+            //Return 2.0 for U8 value 2
+            is_float( psMetadataItemParseF32(itemU8), 2.0,
+                      "psMetadataItemParse:     return 2.0 in F32 for U8-item with "
+                      "value '2'." );
+            //Return 0.0 for U16 value 0
+            is_float( psMetadataItemParseF32(itemU16), 0.0,
+                      "psMetadataItemParse:     return 0.0 in F32 for U16-item with "
+                      "value '0'." );
+            //Return 1.0 for U32 value 1
+            is_float( psMetadataItemParseF32(itemU32), 1.0,
+                      "psMetadataItemParse:     return 1.0 in F32 for U32-item with "
+                      "value '1'." );
+        }
+
+        //F64 Test
+        {
+            //Return NaN for NULL item
+            ok ( isnan(psMetadataItemParseF64(NULL)),
+                 "psMetadataItemParse:     return NaN for NULL psMetadataItem input." );
+            //Return NaN for non-supported type S64
+            ok ( isnan(psMetadataItemParseF64(itemUnsupported)),
+                 "psMetadataItemParse:     return NaN in F64 for S64 (unsupported) "
+                 "psMetadataItem input." );
+            //Return 1.666 for string with "1.666"
+            is_double_tol( psMetadataItemParseF64(itemString2), 1.666, 0.00001,
+                           "psMetadataItemParse:     return 1.666 in F64 for string-item with "
+                           "value '1.666'." );
+            //Return 0.0 for F32 value 0.0
+            is_double( psMetadataItemParseF64(itemF32), 0.0,
+                       "psMetadataItemParse:     return 0.0 in F64 for F32-item with "
+                       "value '0.0'." );
+            //Return 0.5 for F64 value 0.5
+            is_double( psMetadataItemParseF64(itemF64), 0.5,
+                       "psMetadataItemParse:     return 0.5 in F64 for F64-item with "
+                       "value '0.5'." );
+            //Return 1.0 for S8 value 1
+            is_double( psMetadataItemParseF64(itemS8), 1.0,
+                       "psMetadataItemParse:     return 1.0 in F64 for S8-item with "
+                       "value '1'." );
+            //Return 0.0 for S16 value 0
+            is_double( psMetadataItemParseF64(itemS16), 0.0,
+                       "psMetadataItemParse:     return 0.0 in F64 for S16-item with "
+                       "value '0'." );
+            //Return 1.0 for S32 value 1
+            is_double( psMetadataItemParseF64(itemS32), 1.0,
+                       "psMetadataItemParse:     return 1.0 in F64 for S32-item with "
+                       "value '1'." );
+            //Return 2.0 for U8 value 2
+            is_double( psMetadataItemParseF64(itemU8), 2.0,
+                       "psMetadataItemParse:     return 2.0 in F64 for U8-item with "
+                       "value '2'." );
+            //Return 0.0 for U16 value 0
+            is_double( psMetadataItemParseF64(itemU16), 0.0,
+                       "psMetadataItemParse:     return 0.0 in F64 for U16-item with "
+                       "value '0'." );
+            //Return 1.0 for U32 value 1
+            is_double( psMetadataItemParseF64(itemU32), 1.0,
+                       "psMetadataItemParse:     return 1.0 in F64 for U32-item with "
+                       "value '1'." );
+        }
+
+        //S8 Test
+        {
+            //Return 0 for NULL item
+            ok ( psMetadataItemParseS8(NULL) == 0,
+                 "psMetadataItemParse:     return 0 for NULL psMetadataItem input." );
+            //Return 0 for non-supported type S64
+            ok ( psMetadataItemParseS8(itemUnsupported) == 0,
+                 "psMetadataItemParse:     return 0 in S8 for S64 (unsupported) "
+                 "psMetadataItem input." );
+            //Return 2 for string with "1.666"
+            ok ( psMetadataItemParseS8(itemString2) == 1,
+                 "psMetadataItemParse:     return 1 in S8 for string-item with "
+                 "value '1.666'." );
+            //Return 0 for F32 value 0.0
+            ok ( psMetadataItemParseS8(itemF32) == 0,
+                 "psMetadataItemParse:     return 0 in S8 for F32-item with "
+                 "value '0.0'." );
+            //Return 1 for F64 value 0.5
+            ok ( psMetadataItemParseS8(itemF64) == 0,
+                 "psMetadataItemParse:     return 0 in S8 for F64-item with "
+                 "value '0.5'." );
+            //Return 1 for S8 value 1
+            ok ( psMetadataItemParseS8(itemS8) == 1,
+                 "psMetadataItemParse:     return 1 in S8 for S8-item with "
+                 "value '1'." );
+            //Return 0 for S16 value 0
+            ok ( psMetadataItemParseS8(itemS16) == 0,
+                 "psMetadataItemParse:     return 0 in S8 for S16-item with "
+                 "value '0'." );
+            //Return 1 for S32 value 1
+            ok ( psMetadataItemParseS8(itemS32) == 1,
+                 "psMetadataItemParse:     return 1 in S8 for S32-item with "
+                 "value '1'." );
+            //Return 2 for U8 value 2
+            ok ( psMetadataItemParseS8(itemU8) == 2,
+                 "psMetadataItemParse:     return 2 in S8 for U8-item with "
+                 "value '2'." );
+            //Return 0 for U16 value 0
+            ok ( psMetadataItemParseS8(itemU16) == 0,
+                 "psMetadataItemParse:     return 0 in S8 for U16-item with "
+                 "value '0'." );
+            //Return 1 for U32 value 1
+            ok ( psMetadataItemParseS8(itemU32) == 1,
+                 "psMetadataItemParse:     return 1 in S8 for U32-item with "
+                 "value '1'." );
+        }
+
+        //S16 Test
+        {
+            //Return 0 for NULL item
+            ok ( psMetadataItemParseS16(NULL) == 0,
+                 "psMetadataItemParse:     return 0 for NULL psMetadataItem input." );
+            //Return 0 for non-supported type S64
+            ok ( psMetadataItemParseS16(itemUnsupported) == 0,
+                 "psMetadataItemParse:     return 0 in S16 for S64 (unsupported) "
+                 "psMetadataItem input." );
+            //Return 2 for string with "1.666"
+            ok ( psMetadataItemParseS16(itemString2) == 1,
+                 "psMetadataItemParse:     return 1 in S16 for string-item with "
+                 "value '1.666'." );
+            //Return 0 for F32 value 0.0
+            ok ( psMetadataItemParseS16(itemF32) == 0,
+                 "psMetadataItemParse:     return 0 in S16 for F32-item with value '0.0'." );
+            //Return 1 for F64 value 0.5
+            ok ( psMetadataItemParseS16(itemF64) == 0,
+                 "psMetadataItemParse:     return 0 in S16 for F64-item with value '0.5'." );
+            //Return 1 for S8 value 1
+            ok ( psMetadataItemParseS16(itemS8) == 1,
+                 "psMetadataItemParse:     return 1 in S16 for S8-item with value '1'." );
+            //Return 0 for S16 value 0
+            ok ( psMetadataItemParseS16(itemS16) == 0,
+                 "psMetadataItemParse:     return 0 in S16 for S16-item with value '0'." );
+            //Return 1 for S32 value 1
+            ok ( psMetadataItemParseS16(itemS32) == 1,
+                 "psMetadataItemParse:     return 1 in S16 for S32-item with value '1'." );
+            //Return 2 for U8 value 2
+            ok ( psMetadataItemParseS16(itemU8) == 2,
+                 "psMetadataItemParse:     return 2 in S16 for U8-item with value '2'." );
+            //Return 0 for U16 value 0
+            ok ( psMetadataItemParseS16(itemU16) == 0,
+                 "psMetadataItemParse:     return 0 in S16 for U16-item with value '0'." );
+            //Return 1 for U32 value 1
+            ok ( psMetadataItemParseS16(itemU32) == 1,
+                 "psMetadataItemParse:     return 1 in S16 for U32-item with value '1'." );
+        }
+
+        //S32 Test
+        {
+            //Return 0 for NULL item
+            ok ( psMetadataItemParseS32(NULL) == 0,
+                 "psMetadataItemParse:     return 0 for NULL psMetadataItem input." );
+            //Return 0 for non-supported type S64
+            ok ( psMetadataItemParseS32(itemUnsupported) == 0,
+                 "psMetadataItemParse:     return 0 in S32 for S64 (unsupported) "
+                 "psMetadataItem input." );
+            //Return 2 for string with "1.666"
+            ok ( psMetadataItemParseS32(itemString2) == 1,
+                 "psMetadataItemParse:     return 1 in S32 for string-item with "
+                 "value '1.666'." );
+            //Return 0 for F32 value 0.0
+            ok ( psMetadataItemParseS32(itemF32) == 0,
+                 "psMetadataItemParse:     return 0 in S32 for F32-item with value '0.0'." );
+            //Return 1 for F64 value 0.5
+            ok ( psMetadataItemParseS32(itemF64) == 0,
+                 "psMetadataItemParse:     return 0 in S32 for F64-item with value '0.5'." );
+            //Return 1 for S8 value 1
+            ok ( psMetadataItemParseS32(itemS8) == 1,
+                 "psMetadataItemParse:     return 1 in S32 for S8-item with value '1'." );
+            //Return 0 for S16 value 0
+            ok ( psMetadataItemParseS32(itemS16) == 0,
+                 "psMetadataItemParse:     return 0 in S32 for S16-item with value '0'." );
+            //Return 1 for S32 value 1
+            ok ( psMetadataItemParseS32(itemS32) == 1,
+                 "psMetadataItemParse:     return 1 in S32 for S32-item with value '1'." );
+            //Return 2 for U8 value 2
+            ok ( psMetadataItemParseS32(itemU8) == 2,
+                 "psMetadataItemParse:     return 2 in S32 for U8-item with value '2'." );
+            //Return 0 for U16 value 0
+            ok ( psMetadataItemParseS32(itemU16) == 0,
+                 "psMetadataItemParse:     return 0 in S32 for U16-item with value '0'." );
+            //Return 1 for U32 value 1
+            ok ( psMetadataItemParseS32(itemU32) == 1,
+                 "psMetadataItemParse:     return 1 in S32 for U32-item with value '1'." );
+        }
+
+        //U8 Test
+        {
+            //Return 0 for NULL item
+            ok ( psMetadataItemParseU8(NULL) == 0,
+                 "psMetadataItemParse:     return 0 for NULL psMetadataItem input." );
+            //Return 0 for non-supported type S64
+            ok ( psMetadataItemParseU8(itemUnsupported) == 0,
+                 "psMetadataItemParse:     return 0 in U8 for S64 (unsupported) "
+                 "psMetadataItem input." );
+            //Return 2 for string with "1.666"
+            ok ( psMetadataItemParseU8(itemString2) == 1,
+                 "psMetadataItemParse:     return 1 in U8 for string-item with "
+                 "value '1.666'." );
+            //Return 0 for F32 value 0.0
+            ok ( psMetadataItemParseU8(itemF32) == 0,
+                 "psMetadataItemParse:     return 0 in U8 for F32-item with value '0.0'." );
+            //Return 1 for F64 value 0.5
+            ok ( psMetadataItemParseU8(itemF64) == 0,
+                 "psMetadataItemParse:     return 0 in U8 for F64-item with value '0.5'." );
+            //Return 1 for S8 value 1
+            ok ( psMetadataItemParseU8(itemS8) == 1,
+                 "psMetadataItemParse:     return 1 in U8 for S8-item with value '1'." );
+            //Return 0 for S16 value 0
+            ok ( psMetadataItemParseU8(itemS16) == 0,
+                 "psMetadataItemParse:     return 0 in U8 for S16-item with value '0'." );
+            //Return 1 for S32 value 1
+            ok ( psMetadataItemParseU8(itemS32) == 1,
+                 "psMetadataItemParse:     return 1 in U8 for S32-item with value '1'." );
+            //Return 2 for U8 value 2
+            ok ( psMetadataItemParseU8(itemU8) == 2,
+                 "psMetadataItemParse:     return 2 in U8 for U8-item with value '2'." );
+            //Return 0 for U16 value 0
+            ok ( psMetadataItemParseU8(itemU16) == 0,
+                 "psMetadataItemParse:     return 0 in U8 for U16-item with value '0'." );
+            //Return 1 for U32 value 1
+            ok ( psMetadataItemParseU8(itemU32) == 1,
+                 "psMetadataItemParse:     return 1 in U8 for U32-item with value '1'." );
+        }
+
+        //U16 Test
+        {
+            //Return 0 for NULL item
+            ok ( psMetadataItemParseU16(NULL) == 0,
+                 "psMetadataItemParse:     return 0 for NULL psMetadataItem input." );
+            //Return 0 for non-supported type S64
+            ok ( psMetadataItemParseU16(itemUnsupported) == 0,
+                 "psMetadataItemParse:     return 0 in U16 for S64 (unsupported) "
+                 "psMetadataItem input." );
+            //Return 2 for string with "1.666"
+            ok ( psMetadataItemParseU16(itemString2) == 1,
+                 "psMetadataItemParse:     return 1 in U16 for string-item with "
+                 "value '1.666'." );
+            //Return 0 for F32 value 0.0
+            ok ( psMetadataItemParseU16(itemF32) == 0,
+                 "psMetadataItemParse:     return 0 in U16 for F32-item with value '0.0'." );
+            //Return 1 for F64 value 0.5
+            ok ( psMetadataItemParseU16(itemF64) == 0,
+                 "psMetadataItemParse:     return 0 in U16 for F64-item with value '0.5'." );
+            //Return 1 for S8 value 1
+            ok ( psMetadataItemParseU16(itemS8) == 1,
+                 "psMetadataItemParse:     return 1 in U16 for S8-item with value '1'." );
+            //Return 0 for S16 value 0
+            ok ( psMetadataItemParseU16(itemS16) == 0,
+                 "psMetadataItemParse:     return 0 in S8 for S16-item with value '0'." );
+            //Return 1 for S32 value 1
+            ok ( psMetadataItemParseU16(itemS32) == 1,
+                 "psMetadataItemParse:     return 1 in U16 for S32-item with value '1'." );
+            //Return 2 for U8 value 2
+            ok ( psMetadataItemParseU16(itemU8) == 2,
+                 "psMetadataItemParse:     return 2 in U16 for U8-item with value '2'." );
+            //Return 0 for U16 value 0
+            ok ( psMetadataItemParseU16(itemU16) == 0,
+                 "psMetadataItemParse:     return 0 in U16 for U16-item with value '0'." );
+            //Return 1 for U32 value 1
+            ok ( psMetadataItemParseU16(itemU32) == 1,
+                 "psMetadataItemParse:     return 1 in U16 for U32-item with value '1'." );
+        }
+
+        //U32 Test
+        {
+            //Return 0 for NULL item
+            ok ( psMetadataItemParseU32(NULL) == 0,
+                 "psMetadataItemParse:     return 0 for NULL psMetadataItem input." );
+            //Return 0 for non-supported type S64
+            ok ( psMetadataItemParseU32(itemUnsupported) == 0,
+                 "psMetadataItemParse:     return 0 in U32 for S64 (unsupported) "
+                 "psMetadataItem input." );
+            //Return 2 for string with "1.666"
+            ok ( psMetadataItemParseU32(itemString2) == 1,
+                 "psMetadataItemParse:     return 1 in U32 for string-item with "
+                 "value '1.666'." );
+            //Return 0 for F32 value 0.0
+            ok ( psMetadataItemParseU32(itemF32) == 0,
+                 "psMetadataItemParse:     return 0 in U32 for F32-item with value '0.0'." );
+            //Return 1 for F64 value 0.5
+            ok ( psMetadataItemParseU32(itemF64) == 0,
+                 "psMetadataItemParse:     return 0 in U32 for F64-item with value '0.5'." );
+            //Return 1 for S8 value 1
+            ok ( psMetadataItemParseU32(itemS8) == 1,
+                 "psMetadataItemParse:     return 1 in U32 for S8-item with value '1'." );
+            //Return 0 for S16 value 0
+            ok ( psMetadataItemParseU32(itemS16) == 0,
+                 "psMetadataItemParse:     return 0 in U32 for S16-item with value '0'." );
+            //Return 1 for S32 value 1
+            ok ( psMetadataItemParseU32(itemS32) == 1,
+                 "psMetadataItemParse:     return 1 in U32 for S32-item with value '1'." );
+            //Return 2 for U8 value 2
+            ok ( psMetadataItemParseU32(itemU8) == 2,
+                 "psMetadataItemParse:     return 2 in U32 for U8-item with value '2'." );
+            //Return 0 for U16 value 0
+            ok ( psMetadataItemParseU32(itemU16) == 0,
+                 "psMetadataItemParse:     return 0 in U32 for U16-item with value '0'." );
+            //Return 1 for U32 value 1
+            ok ( psMetadataItemParseU32(itemU32) == 1,
+                 "psMetadataItemParse:    return 1 in U32 for U32-item with value '1'." );
+        }
+
+        //STRING Test
+        {
+            //Return NULL for NULL item
+            ok ( psMetadataItemParseString(NULL) == NULL,
+                 "psMetadataItemParse:    return NULL for NULL STRING psMetadataItem "
+                 "input." );
+            //Return NULL for non-supported type S64
+            ok ( psMetadataItemParseString(itemUnsupported) == NULL,
+                 "psMetadataItemParse:    return NULL in STRING for S64 (unsupported)"
+                 " psMetadataItem input." );
+            //Return "true" for STRING of value "true"
+            psString tempString = psMetadataItemParseString(itemString1);
+            is_strn( tempString, "true", 6,
+                     "psMetadataItemParse:    return 'true' in STRING for STRING with "
+                     "value 'true'." );
+            psFree(tempString);
+    
+            //Return 0.000000 for F32 of value 0.000000
+            tempString = psMetadataItemParseString(itemF32);
+            is_strn( tempString, "0.000000", 4,
+                     "psMetadataItemParse:    return '0.000000' in STRING for F32 with "
+                     "value '0.000000'.   (actual result=%s)", tempString);
+            psFree(tempString);
+    
+            //Return 0.500000 for F64 value 0.5
+            tempString = psMetadataItemParseString(itemF64);
+            is_strn( tempString, "0.500000", 10,
+                     "psMetadataItemParse:    return '0.500000' in STRING for F64 with "
+                     "value '0.5'.   (actual result=%s)", tempString);
+            psFree(tempString);
+    
+            //Return 1 for S8 value 1
+            tempString = psMetadataItemParseString(itemS8);
+            is_strn( tempString, "1", 3,
+                     "psMetadataItemParse:    return '1' in STRING for S8 with "
+                     "value '1'.   (actual result=%s)", tempString);
+            psFree(tempString);
+    
+            //Return 0 for S16 value 0
+            tempString = psMetadataItemParseString(itemS16);
+            is_strn( tempString, "0", 3,
+                     "psMetadataItemParse:    return '0' in STRING for S8 with "
+                     "value '0'.   (actual result=%s)", tempString);
+            psFree(tempString);
+    
+            //Return 1 for S32 value 1
+            tempString = psMetadataItemParseString(itemS32);
+            is_strn( tempString, "1", 3,
+                     "psMetadataItemParse:    return '1' in STRING for S8 with "
+                     "value '1'.   (actual result=%s)", tempString);
+            psFree(tempString);
+    
+            //Return 2 for U8 value 2
+            tempString = psMetadataItemParseString(itemU8);
+            is_strn( tempString, "2", 3,
+                     "psMetadataItemParse:    return '2' in STRING for S8 with "
+                     "value '2'.   (actual result=%s)", tempString);
+            psFree(tempString);
+    
+            //Return 0 for U16 value 0
+            tempString = psMetadataItemParseString(itemU16);
+            is_strn( tempString, "0", 3,
+                     "psMetadataItemParse:    return '0' in STRING for S8 with "
+                     "value '0'.   (actual result=%s)", tempString);
+            psFree(tempString);
+    
+            //Return 1 for U32 value 1
+            tempString = psMetadataItemParseString(itemU32);
+            is_strn( tempString, "1", 3,
+                     "psMetadataItemParse:    return '1' in STRING for S8 with "
+                     "value '1'.   (actual result=%s)", tempString);
+            psFree(tempString);
+        }
+
+        psFree(itemBool);
+        psFree(itemF32);
+        psFree(itemF64);
+        psFree(itemS8);
+        psFree(itemS16);
+        psFree(itemS32);
+        psFree(itemU8);
+        psFree(itemU16);
+        psFree(itemU32);
+        psFree(itemString1);
+        psFree(itemString2);
+        psFree(itemString11);
+        psFree(itemUnsupported);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataIterator.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataIterator.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataIterator.c	(revision 22158)
@@ -0,0 +1,347 @@
+#include <stdio.h>
+#include <pslib.h>
+#include <string.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define NAME1 "SIMPLE"
+#define COMMENT1 "Basic FITS?"
+#define FLAG1 0
+#define VALUE1 "TRUE"
+
+#define NAME2 "COMMENT"
+#define COMMENT2 "This is a    "
+#define FLAG2 PS_META_DUPLICATE_OK
+#define VALUE2 "   comment."
+
+#define NAME3 "FILENAME"
+#define COMMENT3 "File name"
+#define FLAG3 0
+#define VALUE3 "abcdef123456.fits"
+
+#define NAME4 "COMMENT"
+#define COMMENT4 "   this IS a   "
+#define FLAG4 PS_META_DUPLICATE_OK
+#define VALUE4 "comment    too!"
+
+#define NAME5 "DATE-OBS"
+#define COMMENT5 "Observing date, UTC"
+#define FLAG5 0
+#define VALUE5 "1978-11-29"
+
+#define NAME6 "COMMENT"
+#define COMMENT6 "    another"
+#define FLAG6 PS_META_DUPLICATE_OK
+#define VALUE6 "comment     "
+
+#define NAME7 "COMMENT"
+#define COMMENT7 "This is another comment"
+#define FLAG7 PS_META_DUPLICATE_OK
+#define VALUE7 "Hello world"
+
+#define MULTI_NAME "COMMENT"
+#define MULTI_NAME1 NAME2
+#define MULTI_NAME2 NAME4
+#define MULTI_NAME3 NAME6
+#define MULTI_NAME4 NAME7
+#define MULTI_COMMENT1 COMMENT2
+#define MULTI_COMMENT2 COMMENT4
+#define MULTI_COMMENT3 COMMENT6
+#define MULTI_COMMENT4 COMMENT7
+#define MULTI_VALUE1 VALUE2
+#define MULTI_VALUE2 VALUE4
+#define MULTI_VALUE3 VALUE6
+#define MULTI_VALUE4 VALUE7
+
+// Generate a dummy metadata
+static psMetadata *mdGenerate(void)
+{
+    psMetadata *md = psMetadataAlloc();
+
+    // Something like a FITS header
+    psMetadataAddStr(md, PS_LIST_TAIL, NAME1, FLAG1, COMMENT1, VALUE1);
+    psMetadataAddStr(md, PS_LIST_TAIL, NAME2, FLAG2, COMMENT2, VALUE2);
+    psMetadataAddStr(md, PS_LIST_TAIL, NAME3, FLAG3, COMMENT3, VALUE3);
+    psMetadataAddStr(md, PS_LIST_TAIL, NAME4, FLAG4, COMMENT4, VALUE4);
+    psMetadataAddStr(md, PS_LIST_TAIL, NAME5, FLAG5, COMMENT5, VALUE5);
+    psMetadataAddStr(md, PS_LIST_TAIL, NAME6, FLAG6, COMMENT6, VALUE6);
+    psMetadataAddStr(md, PS_LIST_TAIL, NAME7, FLAG7, COMMENT7, VALUE7);
+
+    return md;
+}
+
+// Function to perform iteration
+typedef psMetadataItem *(*iterFunc)(psMetadataIterator *iter);
+
+
+// Test the iteration by iterating once and checking the name, comment, and data
+static void testIteration(iterFunc function, // Function to use to iterate
+                          psMetadataIterator *iterator, // The iterator
+                          const char *name, // Name of the item
+                          const char *comment, // Comment for the item
+                          const char *value // Value for the item
+                         )
+{
+    psMetadataItem *item = function(iterator);
+    ok(item, "item = %x", item);
+    skip_start(!item, 4, "Skipping 4 tests because iteration failed");
+    ok(strcmp(item->name, name) == 0, "item->name = %s", item->name);
+    ok(strcmp(item->comment, comment) == 0, "item->comment = %s", item->comment);
+    ok(item->type == PS_DATA_STRING, "item->type = %x", item->type);
+    skip_start(item->type != PS_DATA_STRING, 1, "Skipping 1 test because the item has incorrect type");
+    ok(strcmp(item->data.V, value) == 0, "item->data.V = %s", item->data.V);
+    skip_end();
+    skip_end();
+
+    return;
+}
+
+
+int main (void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(254);
+
+    // psMetadataIterator tests
+    // No regular expressions, forwards
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = mdGenerate();
+        psMetadataIterator *iter = psMetadataIteratorAlloc(md, PS_LIST_HEAD, NULL);
+        ok(iter, "iter = %x", iter);
+        skip_start(!iter, 35, "Skipping 35 tests because psMetadataIteratorAlloc failed");
+
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, NAME1, COMMENT1, VALUE1);
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, NAME2, COMMENT2, VALUE2);
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, NAME3, COMMENT3, VALUE3);
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, NAME4, COMMENT4, VALUE4);
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, NAME5, COMMENT5, VALUE5);
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, NAME6, COMMENT6, VALUE6);
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, NAME7, COMMENT7, VALUE7);
+
+        skip_end();
+        psFree(iter);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // No regular expressions, backwards
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = mdGenerate();
+        psMetadataIterator *iter = psMetadataIteratorAlloc(md, PS_LIST_TAIL, NULL);
+        ok(iter, "iter = %x", iter);
+        skip_start(!iter, 35, "Skipping 35 tests because psMetadataIteratorAlloc failed");
+
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, NAME7, COMMENT7, VALUE7);
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, NAME6, COMMENT6, VALUE6);
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, NAME5, COMMENT5, VALUE5);
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, NAME4, COMMENT4, VALUE4);
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, NAME3, COMMENT3, VALUE3);
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, NAME2, COMMENT2, VALUE2);
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, NAME1, COMMENT1, VALUE1);
+
+        skip_end();
+        psFree(iter);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // No regular expressions, jumping in halfway through (using allocator), forwards
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = mdGenerate();
+        psMetadataIterator *iter = psMetadataIteratorAlloc(md, 3, NULL);
+        ok(iter, "iter = %x", iter);
+        skip_start(!iter, 20, "Skipping 20 tests because psMetadataIteratorAlloc failed");
+
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, NAME4, COMMENT4, VALUE4);
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, NAME5, COMMENT5, VALUE5);
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, NAME6, COMMENT6, VALUE6);
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, NAME7, COMMENT7, VALUE7);
+
+        skip_end();
+        psFree(iter);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //  No regular expressions, jumping in halfway through (using allocator), backwards
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = mdGenerate();
+        psMetadataIterator *iter = psMetadataIteratorAlloc(md, -4, NULL);
+        ok(iter, "iter = %x", iter);
+        skip_start(!iter, 15, "Skipping 20 tests because psMetadataIteratorAlloc failed");
+
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, NAME4, COMMENT4, VALUE4);
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, NAME3, COMMENT3, VALUE3);
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, NAME2, COMMENT2, VALUE2);
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, NAME1, COMMENT1, VALUE1);
+
+        skip_end();
+        psFree(iter);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // No regular expressions, jumping in halfway through (using set), forwards");
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = mdGenerate();
+        psMetadataIterator *iter = psMetadataIteratorAlloc(md, PS_LIST_HEAD, NULL);
+        ok(iter, "iter = %x", iter);
+        skip_start(!iter, 20, "Skipping 20 tests because psMetadataIteratorAlloc failed");
+        psMetadataIteratorSet(iter, 3);
+
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, NAME4, COMMENT4, VALUE4);
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, NAME5, COMMENT5, VALUE5);
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, NAME6, COMMENT6, VALUE6);
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, NAME7, COMMENT7, VALUE7);
+
+        skip_end();
+        psFree(iter);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // No regular expressions, jumping in halfway through (using set), backwards");
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = mdGenerate();
+        psMetadataIterator *iter = psMetadataIteratorAlloc(md, PS_LIST_HEAD, NULL);
+        ok(iter, "iter = %x", iter);
+        skip_start(!iter, 15, "Skipping 20 tests because psMetadataIteratorAlloc failed");
+        psMetadataIteratorSet(iter, -4);
+
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, NAME4, COMMENT4, VALUE4);
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, NAME3, COMMENT3, VALUE3);
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, NAME2, COMMENT2, VALUE2);
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, NAME1, COMMENT1, VALUE1);
+
+        skip_end();
+        psFree(iter);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // With regular expressions, forwards");
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = mdGenerate();
+        psMetadataIterator *iter = psMetadataIteratorAlloc(md, PS_LIST_HEAD, "^" MULTI_NAME "$");
+        ok(iter, "iter = %x", iter);
+        skip_start(!iter, 20, "Skipping 20 tests because psMetadataIteratorAlloc failed");
+
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, MULTI_NAME1, MULTI_COMMENT1, MULTI_VALUE1);
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, MULTI_NAME2, MULTI_COMMENT2, MULTI_VALUE2);
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, MULTI_NAME3, MULTI_COMMENT3, MULTI_VALUE3);
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, MULTI_NAME4, MULTI_COMMENT4, MULTI_VALUE4);
+
+        skip_end();
+        psFree(iter);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // With regular expressions, backwards");
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = mdGenerate();
+        psMetadataIterator *iter = psMetadataIteratorAlloc(md, PS_LIST_TAIL, "^" MULTI_NAME "$");
+        ok(iter, "iter = %x", iter);
+        skip_start(!iter, 20, "Skipping 20 tests because psMetadataIteratorAlloc failed");
+
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, MULTI_NAME4, MULTI_COMMENT4, MULTI_VALUE4);
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, MULTI_NAME3, MULTI_COMMENT3, MULTI_VALUE3);
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, MULTI_NAME2, MULTI_COMMENT2, MULTI_VALUE2);
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, MULTI_NAME1, MULTI_COMMENT1, MULTI_VALUE1);
+
+        skip_end();
+        psFree(iter);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // With regular expressions, jumping in halfway through (using allocator), forwards");
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = mdGenerate();
+        psMetadataIterator *iter = psMetadataIteratorAlloc(md, 2, "^" MULTI_NAME "$");
+        ok(iter, "iter = %x", iter);
+        skip_start(!iter, 20, "Skipping 20 tests because psMetadataIteratorAlloc failed");
+
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, MULTI_NAME3, MULTI_COMMENT3, MULTI_VALUE3);
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, MULTI_NAME4, MULTI_COMMENT4, MULTI_VALUE4);
+
+        skip_end();
+        psFree(iter);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // With regular expressions, jumping in halfway through (using allocator), backwards");
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = mdGenerate();
+        psMetadataIterator *iter = psMetadataIteratorAlloc(md, -3, "^" MULTI_NAME "$");
+        ok(iter, "iter = %x", iter);
+        skip_start(!iter, 20, "Skipping 20 tests because psMetadataIteratorAlloc failed");
+
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, MULTI_NAME2, MULTI_COMMENT2, MULTI_VALUE2);
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, MULTI_NAME1, MULTI_COMMENT1, MULTI_VALUE1);
+
+        skip_end();
+        psFree(iter);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // With regular expressions, jumping in halfway through (using set), forwards");
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = mdGenerate();
+        psMetadataIterator *iter = psMetadataIteratorAlloc(md, PS_LIST_HEAD, "^" MULTI_NAME "$");
+        ok(iter, "iter = %x", iter);
+        skip_start(!iter, 20, "Skipping 20 tests because psMetadataIteratorAlloc failed");
+        psMetadataIteratorSet(iter, 2);
+
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, MULTI_NAME3, MULTI_COMMENT3, MULTI_VALUE3);
+        testIteration((iterFunc)psMetadataGetAndIncrement, iter, MULTI_NAME4, MULTI_COMMENT4, MULTI_VALUE4);
+
+        skip_end();
+        psFree(iter);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // With regular expressions, jumping in halfway through (using set), backwards");
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = mdGenerate();
+        psMetadataIterator *iter = psMetadataIteratorAlloc(md, PS_LIST_HEAD, "^" MULTI_NAME "$");
+        ok(iter, "iter = %x", iter);
+        skip_start(!iter, 20, "Skipping 20 tests because psMetadataIteratorAlloc failed");
+        psMetadataIteratorSet(iter, -3);
+
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, MULTI_NAME2, MULTI_COMMENT2, MULTI_VALUE2);
+        testIteration((iterFunc)psMetadataGetAndDecrement, iter, MULTI_NAME1, MULTI_COMMENT1, MULTI_VALUE1);
+
+        skip_end();
+        psFree(iter);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataOverlay.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataOverlay.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataOverlay.c	(revision 22158)
@@ -0,0 +1,290 @@
+/**
+*  C Implementation: tap_psMetadataOverlay
+*
+* Description: Tests for psMetadataOverlay
+*
+* Author: Eugene Magnier
+* Copyright: See COPYING file that comes with this distribution
+*
+*/
+#include <pslib.h>
+#include <string.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define DEBUG 0
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(14);
+    // psMetadataOverlay Tests
+
+    // overlay two metadatas : output should contain union of all entries
+    {
+        psMemId id = psMemGetId();
+	psMetadata *in = psMetadataAlloc();
+	psMetadata *out = psMetadataAlloc();
+
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN1", 0, "", 1);
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN2", 0, "", 2);
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN3", 0, "", 3);
+
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT1", 0, "", 1);
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT2", 0, "", 2);
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT3", 0, "", 3);
+
+	bool status = psMetadataOverlay (out, in);
+	if (DEBUG) psMetadataPrint (stderr, out, 1);
+
+	ok (status, "psMetadataOverlay : overlay two MDs");
+	psFree (in);
+	psFree (out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // overlay two metadatas, folder in output: output should contain union of all entries
+    {
+	psMemId id = psMemGetId();
+	psMetadata *in = psMetadataAlloc();
+	psMetadata *out = psMetadataAlloc();
+
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN1", 0, "", 1);
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN2", 0, "", 2);
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN3", 0, "", 3);
+
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT1", 0, "", 1);
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT2", 0, "", 2);
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT3", 0, "", 3);
+
+	psMetadata *sub = psMetadataAlloc();
+	psMetadataAddS32 (sub, PS_LIST_TAIL, "TEST.SUB1", 0, "", 1);
+	psMetadataAddS32 (sub, PS_LIST_TAIL, "TEST.SUB2", 0, "", 2);
+	psMetadataAddS32 (sub, PS_LIST_TAIL, "TEST.SUB3", 0, "", 3);
+
+	psMetadataAddMetadata (out, PS_LIST_TAIL, "SUB", 0, "", sub);
+
+	bool status = psMetadataOverlay (out, in);
+	if (DEBUG) psMetadataPrint (stderr, out, 1);
+
+	ok (status, "psMetadataOverlay : overlay two MDs");
+	psFree (in);
+	psFree (out);
+	psFree (sub);
+	ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // overlay two metadatas, folder in input: output should contain union of all entries
+    {
+	psMemId id = psMemGetId();
+	psMetadata *in = psMetadataAlloc();
+	psMetadata *out = psMetadataAlloc();
+
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN1", 0, "", 1);
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN2", 0, "", 2);
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN3", 0, "", 3);
+
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT1", 0, "", 1);
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT2", 0, "", 2);
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT3", 0, "", 3);
+
+	psMetadata *sub = psMetadataAlloc();
+	psMetadataAddS32 (sub, PS_LIST_TAIL, "TEST.SUB1", 0, "", 1);
+	psMetadataAddS32 (sub, PS_LIST_TAIL, "TEST.SUB2", 0, "", 2);
+	psMetadataAddS32 (sub, PS_LIST_TAIL, "TEST.SUB3", 0, "", 3);
+
+	psMetadataAddMetadata (in, PS_LIST_TAIL, "SUB", 0, "", sub);
+
+	bool status = psMetadataOverlay (out, in);
+	if (DEBUG) psMetadataPrint (stderr, out, 1);
+
+	ok (status, "psMetadataOverlay : overlay two MDs");
+	psFree (in);
+	psFree (out);
+	psFree (sub);
+	ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // overlay two metadatas, folder in input & output, no-matched elements
+    {
+	psMemId id = psMemGetId();
+	psMetadata *in = psMetadataAlloc();
+	psMetadata *out = psMetadataAlloc();
+
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN1", 0, "", 1);
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN2", 0, "", 2);
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN3", 0, "", 3);
+
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT1", 0, "", 1);
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT2", 0, "", 2);
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT3", 0, "", 3);
+
+	psMetadata *inSub = psMetadataAlloc();
+	psMetadataAddS32 (inSub, PS_LIST_TAIL, "TEST.INSUB1", 0, "", 1);
+	psMetadataAddS32 (inSub, PS_LIST_TAIL, "TEST.INSUB2", 0, "", 2);
+	psMetadataAddS32 (inSub, PS_LIST_TAIL, "TEST.INSUB3", 0, "", 3);
+	psMetadataAddMetadata (in, PS_LIST_TAIL, "SUB", 0, "", inSub);
+
+	psMetadata *outSub = psMetadataAlloc();
+	psMetadataAddS32 (outSub, PS_LIST_TAIL, "TEST.OUTSUB1", 0, "", 1);
+	psMetadataAddS32 (outSub, PS_LIST_TAIL, "TEST.OUTSUB2", 0, "", 2);
+	psMetadataAddS32 (outSub, PS_LIST_TAIL, "TEST.OUTSUB3", 0, "", 3);
+	psMetadataAddMetadata (out, PS_LIST_TAIL, "SUB", 0, "", outSub);
+
+	bool status = psMetadataOverlay (out, in);
+	if (DEBUG) psMetadataPrint (stderr, out, 1);
+
+	ok (status, "psMetadataOverlay : overlay two MDs");
+	psFree (in);
+	psFree (out);
+	psFree (inSub);
+	psFree (outSub);
+	ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // overlay two metadatas, folder and subfolders in input & output, no-matched elements
+    {
+	psMemId id = psMemGetId();
+	psMetadata *in = psMetadataAlloc();
+	psMetadata *out = psMetadataAlloc();
+
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN1", 0, "", 1);
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN2", 0, "", 2);
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN3", 0, "", 3);
+
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT1", 0, "", 1);
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT2", 0, "", 2);
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT3", 0, "", 3);
+
+	psMetadata *inSub = psMetadataAlloc();
+	psMetadataAddS32 (inSub, PS_LIST_TAIL, "TEST.INSUB1", 0, "", 1);
+	psMetadataAddS32 (inSub, PS_LIST_TAIL, "TEST.INSUB2", 0, "", 2);
+	psMetadataAddS32 (inSub, PS_LIST_TAIL, "TEST.INSUB3", 0, "", 3);
+
+	psMetadata *inSubSub = psMetadataAlloc();
+	psMetadataAddS32 (inSubSub, PS_LIST_TAIL, "TEST.INSUB1", 0, "", 1);
+	psMetadataAddS32 (inSubSub, PS_LIST_TAIL, "TEST.INSUB2", 0, "", 2);
+	psMetadataAddS32 (inSubSub, PS_LIST_TAIL, "TEST.INSUB3", 0, "", 3);
+	psMetadataAddMetadata (inSub, PS_LIST_TAIL, "SUB", 0, "", inSubSub);
+
+	psMetadataAddMetadata (in, PS_LIST_TAIL, "SUB", 0, "", inSub);
+
+	psMetadata *outSub = psMetadataAlloc();
+	psMetadataAddS32 (outSub, PS_LIST_TAIL, "TEST.OUTSUB1", 0, "", 1);
+	psMetadataAddS32 (outSub, PS_LIST_TAIL, "TEST.OUTSUB2", 0, "", 2);
+	psMetadataAddS32 (outSub, PS_LIST_TAIL, "TEST.OUTSUB3", 0, "", 3);
+
+	psMetadata *outSubSub = psMetadataAlloc();
+	psMetadataAddS32 (outSubSub, PS_LIST_TAIL, "TEST.OUTSUB1", 0, "", 1);
+	psMetadataAddS32 (outSubSub, PS_LIST_TAIL, "TEST.OUTSUB2", 0, "", 2);
+	psMetadataAddS32 (outSubSub, PS_LIST_TAIL, "TEST.OUTSUB3", 0, "", 3);
+	psMetadataAddMetadata (outSub, PS_LIST_TAIL, "SUB", 0, "", outSubSub);
+
+	psMetadataAddMetadata (out, PS_LIST_TAIL, "SUB", 0, "", outSub);
+
+	bool status = psMetadataOverlay (out, in);
+	if (DEBUG) psMetadataPrint (stderr, out, 1);
+
+	ok (status, "psMetadataOverlay : overlay two MDs");
+	psFree (in);
+	psFree (out);
+	psFree (inSub);
+	psFree (outSub);
+	psFree (inSubSub);
+	psFree (outSubSub);
+	ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // overlay two metadatas, folder in input & output, matched elements
+    {
+	psMemId id = psMemGetId();
+	psMetadata *in = psMetadataAlloc();
+	psMetadata *out = psMetadataAlloc();
+
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN1", 0, "", 1);
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN2", 0, "", 2);
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN3", 0, "", 3);
+
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT1", 0, "", 1);
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT2", 0, "", 2);
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT3", 0, "", 3);
+
+	psMetadata *inSub = psMetadataAlloc();
+	psMetadataAddS32 (inSub, PS_LIST_TAIL, "TEST.SUB1", 0, "", 1);
+	psMetadataAddS32 (inSub, PS_LIST_TAIL, "TEST.SUB2", 0, "", 2);
+	psMetadataAddS32 (inSub, PS_LIST_TAIL, "TEST.SUB3", 0, "", 3);
+	psMetadataAddMetadata (in, PS_LIST_TAIL, "SUB", 0, "", inSub);
+
+	psMetadata *outSub = psMetadataAlloc();
+	psMetadataAddS32 (outSub, PS_LIST_TAIL, "TEST.SUB1", 0, "", 4);
+	psMetadataAddS32 (outSub, PS_LIST_TAIL, "TEST.SUB2", 0, "", 5);
+	psMetadataAddS32 (outSub, PS_LIST_TAIL, "TEST.SUB3", 0, "", 6);
+	psMetadataAddMetadata (out, PS_LIST_TAIL, "SUB", 0, "", outSub);
+
+	bool status = psMetadataOverlay (out, in);
+	if (DEBUG) psMetadataPrint (stderr, out, 1);
+
+	ok (status, "psMetadataOverlay : overlay two MDs");
+	psFree (in);
+	psFree (out);
+	psFree (inSub);
+	psFree (outSub);
+	ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // overlay two metadatas, folder and subfolders in input & output, no-matched elements
+    {
+	psMemId id = psMemGetId();
+	psMetadata *in = psMetadataAlloc();
+	psMetadata *out = psMetadataAlloc();
+
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN1", 0, "", 1);
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN2", 0, "", 2);
+	psMetadataAddS32 (in, PS_LIST_TAIL, "TEST.IN3", 0, "", 3);
+
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT1", 0, "", 1);
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT2", 0, "", 2);
+	psMetadataAddS32 (out, PS_LIST_TAIL, "TEST.OUT3", 0, "", 3);
+
+	psMetadata *inSub = psMetadataAlloc();
+	psMetadataAddS32 (inSub, PS_LIST_TAIL, "TEST.SUB1", 0, "", 1);
+	psMetadataAddS32 (inSub, PS_LIST_TAIL, "TEST.SUB2", 0, "", 2);
+	psMetadataAddS32 (inSub, PS_LIST_TAIL, "TEST.SUB3", 0, "", 3);
+
+	psMetadata *inSubSub = psMetadataAlloc();
+	psMetadataAddS32 (inSubSub, PS_LIST_TAIL, "TEST.SUB1", 0, "", 1);
+	psMetadataAddS32 (inSubSub, PS_LIST_TAIL, "TEST.SUB2", 0, "", 2);
+	psMetadataAddS32 (inSubSub, PS_LIST_TAIL, "TEST.SUB3", 0, "", 3);
+	psMetadataAddMetadata (inSub, PS_LIST_TAIL, "SUB", 0, "", inSubSub);
+
+	psMetadataAddMetadata (in, PS_LIST_TAIL, "SUB", 0, "", inSub);
+
+	psMetadata *outSub = psMetadataAlloc();
+	psMetadataAddS32 (outSub, PS_LIST_TAIL, "TEST.SUB1", 0, "", 4);
+	psMetadataAddS32 (outSub, PS_LIST_TAIL, "TEST.SUB2", 0, "", 5);
+	psMetadataAddS32 (outSub, PS_LIST_TAIL, "TEST.SUB3", 0, "", 6);
+
+	psMetadata *outSubSub = psMetadataAlloc();
+	psMetadataAddS32 (outSubSub, PS_LIST_TAIL, "TEST.SUB1", 0, "", 4);
+	psMetadataAddS32 (outSubSub, PS_LIST_TAIL, "TEST.SUB2", 0, "", 5);
+	psMetadataAddS32 (outSubSub, PS_LIST_TAIL, "TEST.SUB3", 0, "", 6);
+	psMetadataAddMetadata (outSub, PS_LIST_TAIL, "SUB", 0, "", outSubSub);
+
+	psMetadataAddMetadata (out, PS_LIST_TAIL, "SUB", 0, "", outSub);
+
+	bool status = psMetadataOverlay (out, in);
+	if (DEBUG) psMetadataPrint (stderr, out, 1);
+
+	ok (status, "psMetadataOverlay : overlay two MDs");
+	psFree (in);
+	psFree (out);
+	psFree (inSub);
+	psFree (outSub);
+	psFree (inSubSub);
+	psFree (outSubSub);
+	ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataUpdate.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataUpdate.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadataUpdate.c	(revision 22158)
@@ -0,0 +1,137 @@
+/**
+*  C Implementation: tap_psMetadataUpdate
+*
+* Description: Tests for psMetadataUpdate, psMetadataItemAdd for PS_META_REQUIRE_ENTRY and
+* PS_META_REQUIRE_TYPE
+*
+* Author: Eugene Magnier
+* Copyright: See COPYING file that comes with this distribution
+*
+*/
+#include <pslib.h>
+#include <string.h>
+#include "tap.h"
+#include "pstap.h"
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(16);
+    // psMetadataUpdate Tests
+
+
+    {
+        psMemId id = psMemGetId();
+	psMetadata *md = psMetadataAlloc();
+	psMetadataAddS32 (md, PS_LIST_TAIL, "TEST1", 0, "", 1);
+	bool status = psMetadataAddF32 (md, PS_LIST_TAIL, "TEST1", PS_META_REPLACE | PS_META_REQUIRE_ENTRY, "", 1);
+	ok (status, "PS_META_REQUIRE_ENTRY : psMetadataAdd should not fail if item already exists");
+	psFree (md);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+	psMetadata *md = psMetadataAlloc();
+	psMetadataAddS32 (md, PS_LIST_TAIL, "TEST1", 0, "", 1);
+	bool status = psMetadataAddF32 (md, PS_LIST_TAIL, "TEST2", PS_META_REPLACE | PS_META_REQUIRE_ENTRY, "", 1);
+	ok (!status, "PS_META_REQUIRE_ENTRY : psMetadataAdd should fail if item does not already exist");
+	psFree (md);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+	psMetadata *md = psMetadataAlloc();
+	psMetadataAddS32 (md, PS_LIST_TAIL, "TEST1", 0, "", 1);
+	bool status = psMetadataAddF32 (md, PS_LIST_TAIL, "TEST2", PS_META_REPLACE | PS_META_REQUIRE_TYPE, "", 1);
+	ok (status, "PS_META_REQUIRE_TYPE : psMetadataAdd should not fail if item does not already exist");
+	psFree (md);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+	psMetadata *md = psMetadataAlloc();
+	psMetadataAddS32 (md, PS_LIST_TAIL, "TEST1", 0, "", 1);
+	bool status = psMetadataAddS32 (md, PS_LIST_TAIL, "TEST1", PS_META_REPLACE | PS_META_REQUIRE_TYPE, "", 1);
+	ok (status, "PS_META_REQUIRE_TYPE : psMetadataAdd should not fail if existing item has the same type");
+	psFree (md);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+	psMetadata *md = psMetadataAlloc();
+	psMetadataAddS32 (md, PS_LIST_TAIL, "TEST1", 0, "", 1);
+	bool status = psMetadataAddF32 (md, PS_LIST_TAIL, "TEST1", PS_META_REPLACE | PS_META_REQUIRE_TYPE, "", 1);
+	ok (!status, "PS_META_REQUIRE_TYPE : psMetadataAdd should fail if existing item does not match type");
+	psFree (md);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+	psMetadata *input = psMetadataAlloc();
+	psMetadata *output = psMetadataAlloc();
+
+	psMetadataAddS32 (input, PS_LIST_TAIL, "TEST1", 0, "", 2);
+	psMetadataAddS32 (input, PS_LIST_TAIL, "TEST2", 0, "", 2);
+	psMetadataAddS32 (input, PS_LIST_TAIL, "TEST3", 0, "", 2);
+	psMetadataAddS32 (output, PS_LIST_TAIL, "TEST1", 0, "", 1);
+	psMetadataAddS32 (output, PS_LIST_TAIL, "TEST2", 0, "", 1);
+	psMetadataAddS32 (output, PS_LIST_TAIL, "TEST3", 0, "", 1);
+
+	bool status = psMetadataUpdate (output, input);
+	ok (status, "psMetadataUpdate should not fail if items all exist and match type");
+	psFree (input);
+	psFree (output);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+	psMetadata *input = psMetadataAlloc();
+	psMetadata *output = psMetadataAlloc();
+
+	psMetadataAddS32 (input, PS_LIST_TAIL, "TEST1", 0, "", 2);
+	psMetadataAddS32 (input, PS_LIST_TAIL, "TEST2", 0, "", 2);
+	psMetadataAddS32 (input, PS_LIST_TAIL, "TEST3", 0, "", 2);
+	psMetadataAddS32 (output, PS_LIST_TAIL, "TEST1", 0, "", 1);
+	psMetadataAddS32 (output, PS_LIST_TAIL, "TEST3", 0, "", 1);
+
+	bool status = psMetadataUpdate (output, input);
+	ok (!status, "psMetadataUpdate should fail if any input items do not exist in output");
+	psFree (input);
+	psFree (output);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    {
+        psMemId id = psMemGetId();
+	psMetadata *input = psMetadataAlloc();
+	psMetadata *output = psMetadataAlloc();
+
+	psMetadataAddS32 (input, PS_LIST_TAIL, "TEST1", 0, "", 2);
+	psMetadataAddS32 (input, PS_LIST_TAIL, "TEST2", 0, "", 2);
+	psMetadataAddS32 (input, PS_LIST_TAIL, "TEST3", 0, "", 2);
+
+	psMetadataAddS32 (output, PS_LIST_TAIL, "TEST1", 0, "", 1);
+	psMetadataAddF32 (output, PS_LIST_TAIL, "TEST2", 0, "", 1);
+	psMetadataAddS32 (output, PS_LIST_TAIL, "TEST3", 0, "", 1);
+
+	bool status = psMetadataUpdate (output, input);
+	ok (!status, "psMetadataUpdate should fail if any input items do not match type in output");
+	psFree (input);
+	psFree (output);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadata_copying.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadata_copying.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadata_copying.c	(revision 22158)
@@ -0,0 +1,480 @@
+/**
+ *  C Implementation: tap_psMetadata_copying
+ *
+ * Description:  Tests for psMetadataCopy, psMetadataItemCopy, & psMetadataItemSupplement.
+ *
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <pslib.h>
+#include <string.h>
+#include "tap.h"
+#include "pstap.h"
+
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(41);
+
+
+    // testMetadataCopy()
+    {
+        psMemId id = psMemGetId();
+        psMetadata *in = NULL;
+        psMetadata *out = NULL;
+        psMetadataItem *tempItem = NULL;
+        psMetadataItem *outItem = NULL;
+        psMetadataItem *inItem = NULL;
+        psMetadata *outTest = NULL;
+    
+        //Return NULL for NULL psMetadata input
+        {
+            outTest = psMetadataCopy(out, NULL);
+            ok( outTest == NULL,
+                "psMetadataCopy:  return NULL for NULL input metadata.");
+        }
+        //Return allocated out for NULL psMetadata input (with allocated out)
+        {
+            out = psMetadataAlloc();
+            outTest = psMetadataCopy(out, NULL);
+            ok( outTest == NULL,
+                "psMetadataCopy:  return out for NULL input metadata.");
+            psFree(out);
+            out = NULL;
+        }
+        //Return NULL for attempt to copy item of unsupported data type - NULL out metadata
+        psMetadataItem *notype = NULL;
+        {
+            in = psMetadataAlloc();
+            psMetadataAddS32(in, PS_LIST_HEAD, "S32", 0, "", 1);
+            notype = psMetadataGet(in, PS_LIST_HEAD);
+            notype->type = -1;
+            outTest = psMetadataCopy(out, in);
+            ok( outTest == NULL,
+                "psMetadataCopy:  return NULL for metadata with item of bad type.");
+            psFree(out);
+            out = NULL;
+        }
+        //Return NULL for attempt to copy item of unsupported data type - allocated out metadata
+        {
+            out = psMetadataAlloc();
+            psMetadataAddS32(out, PS_LIST_TAIL, "S32", 0, "", 2);
+            outTest = psMetadataCopy(out, in);
+            ok( outTest == NULL,
+                "psMetadataCopy:  return NULL for metadata with item of bad type.");
+            notype->type = PS_DATA_S32;
+            psFree(out);
+            out = NULL;
+            psFree(in);
+            in = NULL;
+        }
+    
+        //Return NULL for NULL psMetadata input->list
+        in = psMetadataAlloc();
+        if (in->list != NULL) {
+            psFree(in->list);
+            in->list = NULL;
+        }
+        {
+            outTest = psMetadataCopy(out, in);
+            ok( outTest == NULL,
+                "psMetadataCopy:  return NULL for NULL metadata input->list.");
+        }
+        /*    //Return NULL for NULL psMetadata input->list (with allocated out)
+            {
+                out = psMetadataAlloc();
+                out = psMetadataCopy(out, in);
+                ok( out == NULL,
+                    "psMetadataCopy:  return NULL for NULL metadata input->list.");
+            }
+        */
+        //Return valid (but empty) metadata for NULL out input and empty input metadata.
+        in->list = psListAlloc(NULL);
+        psFree(in);
+        in = psMetadataAlloc();
+        if (out != NULL) {
+            psFree(out);
+            out = NULL;
+        }
+        outTest = psMetadataCopy(out, in);
+        tempItem = psMetadataGet(in, PS_LIST_HEAD);
+        {
+            ok( outTest != NULL && tempItem == NULL,
+                "psMetadataCopy:  return empty copy with no items for empty input metadata.");
+            psFree(out);
+            psFree(outTest);
+            out = NULL;
+            outTest = NULL;
+        }
+    
+        //Test case: multiCheckItem->type == PS_DATA_METADATA_MULTI
+        psMetadataAddS32(in, PS_LIST_HEAD, "S32", 0, "", 1);
+        psMetadataAddS32(in, PS_LIST_TAIL, "S32", PS_META_DUPLICATE_OK, "", 1);
+        outTest = psMetadataCopy(out, in);
+        tempItem = psMetadataGet(outTest, PS_LIST_HEAD);
+        {
+            ok( tempItem->type == PS_DATA_S32 && tempItem->data.S32 == 1,
+                "psMetadataCopy:  return valid copy for a PS_DATA_METADATA_MULTI entry.");
+            psFree(outTest);
+            outTest = NULL;
+        }
+    
+        //Test case:  !psMetadataAddItem(out, newItem, PS_LIST_TAIL, flag)
+        //XXX: doesn't seem to be easily reachable, certainly by the user...  Skipping.
+    
+        //Test case: simple valid test
+        psFree(in);
+        psFree(out);
+        out = NULL;
+        in = psMetadataAlloc();
+        psMetadataAddS32(in, PS_LIST_HEAD, "S32", 0, "", 666);
+        outTest = psMetadataCopy(out, in);
+        outItem = psMetadataGet(outTest, PS_LIST_HEAD);
+        inItem = psMetadataGet(in, PS_LIST_HEAD);
+        {
+            ok( outItem->type == PS_DATA_S32 && outItem->data.S32 == inItem->data.S32 &&
+                (strncmp(inItem->name, outItem->name, 10) == 0),
+                "psMetadataCopy:  return valid copy of metadata with 1 S32 entry.");
+        }
+        psFree(outTest);
+        psFree(in);
+        psFree(out);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testMetadataItemCopy()
+    {
+        psMemId id = psMemGetId();
+        //Return NULL for NULL input psMetadataItem
+        {
+            ok( psMetadataItemCopy(NULL) == NULL,
+                "psMetadataItemCopy:   return NULL for NULL input metadataItem.");
+        }
+    
+        //Test Simple types:  Bool, S8, S16, S32, S64, U8, U16, U32, U64, F32, F64, STRING
+        psMetadataItem *itemBool = psMetadataItemAlloc("itemBool", PS_DATA_BOOL, "", false);
+        psMetadataItem *itemS8  =  psMetadataItemAlloc("itemS8", PS_DATA_S8, "", 1);
+        psMetadataItem *itemS16 =  psMetadataItemAlloc("itemS16", PS_DATA_S16, "", 2);
+        psMetadataItem *itemS32 =  psMetadataItemAlloc("itemS32", PS_DATA_S32, "", 3);
+        psMetadataItem *itemS64 =  psMetadataItemAlloc("itemS64", PS_DATA_S64, "", (psS64)4);
+        psMetadataItem *itemU8  =  psMetadataItemAlloc("itemU8", PS_DATA_U8, "", 1);
+        psMetadataItem *itemU16 =  psMetadataItemAlloc("itemU16", PS_DATA_U16, "", 2);
+        psMetadataItem *itemU32 =  psMetadataItemAlloc("itemU32", PS_DATA_U32, "", 3);
+        psMetadataItem *itemU64 =  psMetadataItemAlloc("itemU64", PS_DATA_U64, "", 4);
+        psMetadataItem *itemF32 =  psMetadataItemAlloc("itemF32", PS_DATA_F32, "", 3.0);
+        psMetadataItem *itemF64 =  psMetadataItemAlloc("itemF64", PS_DATA_F64, "", 4.0);
+        psMetadataItem *itemString = psMetadataItemAlloc("itemString", PS_DATA_STRING, "", "I M STRiNG");
+        psMetadataItem *copy = NULL;
+        //Bool case
+        {
+            copy = psMetadataItemCopy(itemBool);
+            ok( (copy->type == PS_DATA_BOOL && (strncmp(copy->name, "itemBool", 10) == 0) &&
+                 !copy->data.B && strncmp(copy->comment, "", 2) == 0),
+                "psMetadataItemCopy:  return valid copy of BOOL item.");
+            psFree(copy);
+        }
+        //S8 case
+        {
+            copy = psMetadataItemCopy(itemS8);
+            ok( (copy->type == PS_DATA_S8 && (strncmp(copy->name, "itemS8", 10) == 0) &&
+                 copy->data.S8 == 1 && strncmp(copy->comment, "", 2) == 0),
+                "psMetadataItemCopy:  return valid copy of S8 item.");
+            psFree(copy);
+        }
+        //S16 case
+        {
+            copy = psMetadataItemCopy(itemS16);
+            ok( (copy->type == PS_DATA_S16 && (strncmp(copy->name, "itemS16", 10) == 0) &&
+                 copy->data.S16 == 2 && strncmp(copy->comment, "", 2) == 0),
+                "psMetadataItemCopy:  return valid copy of S16 item.");
+            psFree(copy);
+        }
+        //S32 case
+        {
+            copy = psMetadataItemCopy(itemS32);
+            ok( (copy->type == PS_DATA_S32 && (strncmp(copy->name, "itemS32", 10) == 0) &&
+                 copy->data.S32 == 3 && strncmp(copy->comment, "", 2) == 0),
+                "psMetadataItemCopy:  return valid copy of S32 item.");
+            psFree(copy);
+        }
+    
+        // S64 case
+        {
+            psMetadataItem *copy = psMetadataItemCopy(itemS64);
+    
+            ok(copy->type == PS_DATA_S64, "item type");
+            is_str(copy->name, "itemS64", "item name");
+            is_long(copy->data.S64, 4, "item data");
+            is_str(copy->comment, "", "item comment");
+    
+            psFree(copy);
+        }
+    
+        //U8 case
+        {
+            copy = psMetadataItemCopy(itemU8);
+            ok( (copy->type == PS_DATA_U8 && (strncmp(copy->name, "itemU8", 10) == 0) &&
+                 copy->data.U8 == 1 && strncmp(copy->comment, "", 2) == 0),
+                "psMetadataItemCopy:  return valid copy of U8 item.");
+            psFree(copy);
+        }
+        //U16 case
+        {
+            copy = psMetadataItemCopy(itemU16);
+            ok( (copy->type == PS_DATA_U16 && (strncmp(copy->name, "itemU16", 10) == 0) &&
+                 copy->data.U16 == 2 && strncmp(copy->comment, "", 2) == 0),
+                "psMetadataItemCopy:  return valid copy of U16 item.");
+            psFree(copy);
+        }
+        //U32 case
+        {
+            copy = psMetadataItemCopy(itemU32);
+            ok( (copy->type == PS_DATA_U32 && (strncmp(copy->name, "itemU32", 10) == 0) &&
+                 copy->data.U32 == 3 && strncmp(copy->comment, "", 2) == 0),
+                "psMetadataItemCopy:  return valid copy of U32 item.");
+            psFree(copy);
+        }
+        //U64 case
+        {
+            copy = psMetadataItemCopy(itemU64);
+            ok( (copy->type == PS_DATA_U64 && (strncmp(copy->name, "itemU64", 10) == 0) &&
+                 copy->data.U64 == 4 && strncmp(copy->comment, "", 2) == 0),
+                "psMetadataItemCopy:  return valid copy of U64 item.");
+            psFree(copy);
+        }
+        //F32 case
+        {
+            copy = psMetadataItemCopy(itemF32);
+            ok( (copy->type == PS_DATA_F32 && (strncmp(copy->name, "itemF32", 10) == 0) &&
+                 abs(copy->data.F32-3.0) < FLT_EPSILON && strncmp(copy->comment, "", 2) == 0),
+                "psMetadataItemCopy:  return valid copy of F32 item.");
+            psFree(copy);
+        }
+        //F64 case
+        {
+            copy = psMetadataItemCopy(itemF64);
+            ok( (copy->type == PS_DATA_F64 && (strncmp(copy->name, "itemF64", 10) == 0) &&
+                 abs(copy->data.F64-4.0) < DBL_EPSILON && strncmp(copy->comment, "", 2) == 0),
+                "psMetadataItemCopy:  return valid copy of F64 item.");
+            psFree(copy);
+        }
+        //STRING case
+        {
+            copy = psMetadataItemCopy(itemString);
+            ok( (copy->type == PS_DATA_STRING && (strncmp(copy->name, "itemString", 12) == 0) &&
+                 strncmp(copy->data.str,"I M STRiNG",12) == 0 && strncmp(copy->comment,"",2) == 0),
+                "psMetadataItemCopy:  return valid copy of STRING item.");
+            psFree(copy);
+        }
+    
+        //Test Remaining types:  Vector, Time, Metadata, Region
+        psVector *inV = psVectorAlloc(2, PS_TYPE_S32);
+        psVectorSet(inV, 0, 666);
+        psVectorSet(inV, 1, 667);
+        psMetadataItem *itemVector = psMetadataItemAlloc("itemVector", PS_DATA_VECTOR, "", inV);
+        psTime *teaTime = psTimeAlloc(PS_TIME_TAI);
+        teaTime->sec = 1;
+        teaTime->nsec = 0;
+        teaTime->leapsecond = true;
+        psMetadataItem *itemTime = psMetadataItemAlloc("itemTime", PS_DATA_TIME, "", teaTime);
+        psMetadata *md = psMetadataAlloc();
+        psMetadataAddS32(md, PS_LIST_HEAD, "mdS32", 0, "", 666);
+        psMetadataItem *itemMD = psMetadataItemAlloc("itemMD", PS_DATA_METADATA, "", md);
+        psRegion *reg = psRegionAlloc(0.0, 2.0, 1.0, 3.0);
+        psMetadataItem *itemRegion = psMetadataItemAlloc("itemRegion", PS_DATA_REGION, "", reg);
+        //Vector case
+        {
+            copy = psMetadataItemCopy(itemVector);
+            int int0 = ((psVector*)(copy->data.V))->data.S32[0];
+            int int1 = ((psVector*)(copy->data.V))->data.S32[1];
+            ok( (copy->type == PS_DATA_VECTOR && (strncmp(copy->name, "itemVector", 12) == 0)
+                 && int0 == 666 && int1 == 667 && strncmp(copy->comment,"",2) == 0),
+                "psMetadataItemCopy:  return valid copy of Vector item.");
+            psFree(copy);
+        }
+        //Vector case - invalid vector item
+        {
+            psFree(itemVector->data.V);
+            itemVector->data.V = NULL;
+            copy = psMetadataItemCopy(itemVector);
+            ok( copy == NULL, "psMetadataItemCopy:  return NULL for invalid vector item");
+            //        itemVector->data.V = psVectorAlloc(1, PS_TYPE_S32);
+        }
+        //Time case
+        {
+            copy = psMetadataItemCopy(itemTime);
+            int int0 = (int)((psTime*)(copy->data.V))->sec;
+            int int1 = (int)((psTime*)(copy->data.V))->nsec;
+            bool leap = ((psTime*)(copy->data.V))->leapsecond;
+            ok( (copy->type == PS_DATA_TIME && (strncmp(copy->name, "itemTime", 12) == 0)
+                 && int0 == 1 && int1 == 0 && strncmp(copy->comment,"",2) == 0) && leap,
+                "psMetadataItemCopy:  return valid copy of Time item.");
+            psFree(copy);
+        }
+        //Time case - invalid time item
+        {
+            psTime *t = psTimeAlloc(PS_TIME_TT);
+            t->type += 1;
+            psMetadataItem *itemTime2 = psMetadataItemAlloc("itemTime", PS_DATA_TIME, "", t);
+            copy = psMetadataItemCopy(itemTime2);
+            ok( copy != NULL && copy->data.V == NULL,
+                "psMetadataItemCopy:  return non-NULL item for invalid input time item");
+            psFree(t);
+            psFree(copy);
+            psFree(itemTime2);
+        }
+        //Time case - NULL time item
+        {
+            psFree(itemTime->data.V);
+            itemTime->data.V = NULL;
+            copy = psMetadataItemCopy(itemTime);
+            ok( copy != NULL && copy->data.V == NULL,
+                "psMetadataItemCopy:  return non-NULL item for NULL input time item");
+            //        (itemTime->data.V) = psTimeAlloc(PS_TIME_TAI);
+            psFree(copy);
+        }
+        //Metadata case
+        {
+            copy = psMetadataItemCopy(itemMD);
+            psMetadataItem *testItem = NULL;
+            testItem = psMetadataGet(((psMetadata*)(copy->data.V)), PS_LIST_HEAD);
+            if (testItem == NULL)
+                printf("\nError in psMetadataGet.\n");
+            ok( copy->type == PS_DATA_METADATA && strncmp(copy->name, "itemMD", 8) == 0
+                && (strncmp(copy->comment, "",2) == 0) && testItem->type == PS_DATA_S32
+                && (strncmp(testItem->name, "mdS32", 10) == 0) && testItem->data.S32 == 666
+                && (strncmp(testItem->comment,"",2) == 0),
+                "psMetadataItemCopy:  return valid copy of Metadata item.");
+            psFree(copy);
+        }
+        //Region case
+        {
+            copy = psMetadataItemCopy(itemRegion);
+            float x0 = ((psRegion*)(copy->data.V))->x0;
+            float x1 = ((psRegion*)(copy->data.V))->x1;
+            float y0 = ((psRegion*)(copy->data.V))->y0;
+            float y1 = ((psRegion*)(copy->data.V))->y1;
+            ok( (copy->type == PS_DATA_REGION && (strncmp(copy->name, "itemRegion", 12) == 0)
+                 && abs(x0-0.0) < FLT_EPSILON && abs(x1-2.0) < FLT_EPSILON
+                 && abs(y0-1.0) < FLT_EPSILON && abs(y1-3.0) < FLT_EPSILON
+                 && strncmp(copy->comment,"",2) == 0),
+                "psMetadataItemCopy:  return valid copy of Region item.");
+            psFree(copy);
+        }
+    
+        //Test Unsupported type - (sphere for example)
+        psSphere *sphere = psSphereAlloc();
+        sphere->r = 1.0;
+        sphere->d = 6.66;
+        psMetadataItem *itemSphere = psMetadataItemAlloc("itemSphere", PS_DATA_SPHERE, "", sphere);
+        psFree(sphere);
+        {
+            copy = psMetadataItemCopy(itemSphere);
+            float R = ((psSphere*)(copy->data.V))->r;
+            float D = ((psSphere*)(copy->data.V))->d;
+            ok( (copy->type == PS_DATA_SPHERE && (strncmp(copy->name, "itemSphere", 12) == 0) &&
+                 abs(R - 1.0) < FLT_EPSILON && abs(D - 6.66) < FLT_EPSILON &&
+                 strncmp(copy->comment,"",2) == 0),
+                "psMetadataItemCopy:  return valid copy of SPHERE item.");
+            psFree(copy);
+        }
+    
+        psFree(itemSphere);
+        psFree(inV);
+        psFree(teaTime);
+        psFree(md);
+        psFree(reg);
+        psFree(itemBool);
+        psFree(itemS8);
+        psFree(itemS16);
+        psFree(itemS32);
+        psFree(itemS64);
+        psFree(itemU8);
+        psFree(itemU16);
+        psFree(itemU32);
+        psFree(itemU64);
+        psFree(itemF32);
+        psFree(itemF64);
+        psFree(itemString);
+        psFree(itemVector);
+        psFree(itemTime);
+        psFree(itemMD);
+        psFree(itemRegion);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testMetadataItemTransfer()
+    {
+        psMemId id = psMemGetId();
+        psMetadata *out = psMetadataAlloc();
+        psMetadata *in = psMetadataAlloc();
+        psString key = psStringAlloc(30);
+        strncpy(key, "key", 4);
+    
+        //Return false for NULL in input
+        {
+            ok( !psMetadataItemSupplement(out, NULL, key),
+                "psMetadataItemSupplement:  return false for NULL in metadata.");
+        }
+        //Return false for NULL out input
+        {
+            ok( !psMetadataItemSupplement(NULL, in, key),
+                "psMetadataItemSupplement:  return false for NULL out metadata.");
+        }
+        //Return false for NULL key input
+        {
+            ok( !psMetadataItemSupplement(out, in, NULL),
+                "psMetadataItemSupplement:  return false for NULL key string.");
+        }
+        psMetadataAddS32(in, PS_LIST_HEAD, "key", PS_META_NO_REPLACE, "", 666);
+        psMetadataAddF32(out, PS_LIST_HEAD, "out", 0, "", 6.66);
+    
+        //Return true for valid inputs
+        {
+            bool transfered = psMetadataItemSupplement(out, in, key);
+            psMetadataItem *item = NULL;
+            if (transfered)
+                item = psMetadataGet(out, PS_LIST_TAIL);
+            ok(transfered && item->type == PS_DATA_S32 && strncmp(item->name, "key", 4) == 0
+               && item->data.S32 == 666 && strncmp(item->comment, "", 2) == 0,
+               "psMetadataItemSupplement:  return true for valid inputs.");
+        }
+        /*  Attempt here was to return false inside of ItemTransfer at psMetadataAddItem.
+        //Return false for duplicate entry with PS_META_DEFAULT (no duplicates)
+        {
+            psMetadataRemoveKey(out, key);
+            psMetadataItem *item = psMetadataGet(in, PS_LIST_HEAD);
+            psMetadataAddItem(out, item, PS_LIST_TAIL, PS_META_NO_REPLACE);
+            ok( !psMetadataItemSupplement(out, in, key),
+                "psMetadataItemSupplement:  return false for duplicate metadataItem.");
+        }
+        */
+        //Return false for invalid key
+        {
+            strncpy(key, "not MY key", 15);
+            ok( !psMetadataItemSupplement(out, in, key),
+                "psMetadataItemSupplement:  return false for invalid key.");
+        }
+        //Return false for invalid metadata
+        psMetadata *invalid = psMetadataAlloc();
+        psFree(invalid->hash);
+        invalid->hash = NULL;
+        {
+            ok( !psMetadataItemSupplement(invalid, in, "key"),
+                "psMetadataItemSupplement:  return false for invalid metadata.");
+        }
+        psFree(invalid);
+    
+        psFree(out);
+        psFree(in);
+        psFree(key);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadata_creating.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadata_creating.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadata_creating.c	(revision 22158)
@@ -0,0 +1,487 @@
+/**
+*  C Implementation: tap_psMetadata_creating
+*
+* Description:  Tests for psMetadataAlloc, psMetadataItemAlloc's (TYPEs),
+*               psMemCheckMetadata, psMemCheckMetadataItem, psMetadataAddItem,
+*               psMetadataIteratorAlloc
+*
+*
+* Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+*
+* Copyright: See COPYING file that comes with this distribution
+*
+*/
+#include <pslib.h>
+#include <string.h>
+#include "tap.h"
+#include "pstap.h"
+
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(42);
+    // psMetadata & psMetadataItem Creation Functions
+
+
+    // testItemAllocs(void)
+    // psMetadataItemAlloc Fxns
+    {
+        psMemId id = psMemGetId();
+        psMetadataItem *itemStr = psMetadataItemAllocStr("itemStr", "", "itemStr");
+        psMetadataItem *itemF32 = psMetadataItemAllocF32("itemF32", "", 6.66);
+        psMetadataItem *itemF64 = psMetadataItemAllocF64("itemF64", "", 0.666);
+        psMetadataItem *itemS8 = psMetadataItemAllocS8("itemS8", "", 0);
+        psMetadataItem *itemS16 = psMetadataItemAllocS16("itemS16", "", 1);
+        psMetadataItem *itemS32 = psMetadataItemAllocS32("itemS32", "", 2);
+        psMetadataItem *itemS64 = psMetadataItemAllocS64("itemS64", "", 3);
+        psMetadataItem *itemU8 = psMetadataItemAllocU8("itemU8", "", 0);
+        psMetadataItem *itemU16 = psMetadataItemAllocU16("itemU16", "", 1);
+        psMetadataItem *itemU32 = psMetadataItemAllocU32("itemU32", "", 2);
+        psMetadataItem *itemU64 = psMetadataItemAllocU64("itemU64", "", 3);
+        psMetadataItem *itemBool = psMetadataItemAllocBool("itemBool", "", true);
+    
+        //First try to free a NULL item
+        psMetadataItem *nullItem = NULL;
+        psFree(nullItem);
+        //Verify correct allocation
+        //String
+        {
+            skip_start(itemStr == NULL, 1,
+                       "Skipping 1 tests because psMetadataItemAllocStr() failed");
+            ok(itemStr->type == PS_DATA_STRING
+               && !strncmp(itemStr->name, "itemStr", 10)
+               && !strncmp(itemStr->data.V, "itemStr", 10)
+               && !strncmp(itemStr->comment, "", 2),
+               "psMetadataItemAllocStr:    create valid string item.");
+            skip_end();
+        }
+        //F32
+        {
+            skip_start(itemF32 == NULL, 1,
+                       "Skipping 1 tests because psMetadataItemAllocF32() failed");
+            ok(itemF32->type == PS_DATA_F32
+               && !strncmp(itemF32->name, "itemF32", 10)
+               && abs(itemF32->data.F32 - 6.66) < FLT_EPSILON
+               && !strncmp(itemF32->comment, "", 2),
+               "psMetadataItemAllocF32:    create valid F32 item.");
+            skip_end();
+        }
+        //F64
+        {
+            skip_start(itemF64 == NULL, 1,
+                       "Skipping 1 tests because psMetadataItemAllocF64() failed");
+            ok(itemF64->type == PS_DATA_F64
+               && !strncmp(itemF64->name, "itemF64", 10)
+               && abs(itemF64->data.F64 - 0.666) < DBL_EPSILON
+               && !strncmp(itemF64->comment, "", 2),
+               "psMetadataItemAllocF64:    create valid F64 item.");
+            skip_end();
+        }
+        //S8
+        {
+            skip_start(itemS8 == NULL, 1,
+                       "Skipping 1 tests because psMetadataItemAllocS8() failed");
+            ok(itemS8->type == PS_DATA_S8
+               && !strncmp(itemS8->name, "itemS8", 10)
+               && itemS8->data.S8 == 0
+               && !strncmp(itemS8->comment, "", 2),
+               "psMetadataItemAllocS8:     create valid S8 item.");
+            skip_end();
+        }
+        //S16
+        {
+            skip_start(itemS16 == NULL, 1,
+                       "Skipping 1 tests because psMetadataItemAllocS16() failed");
+            ok(itemS16->type == PS_DATA_S16
+               && !strncmp(itemS16->name, "itemS16", 10)
+               && itemS16->data.S16 == 1
+               && !strncmp(itemS16->comment, "", 2),
+               "psMetadataItemAllocS16:    create valid S16 item.");
+            skip_end();
+        }
+        //S32
+        {
+            skip_start(itemS32 == NULL, 1,
+                       "Skipping 1 tests because psMetadataItemAllocS32() failed");
+            ok(itemS32->type == PS_DATA_S32
+               && !strncmp(itemS32->name, "itemS32", 10)
+               && itemS32->data.S32 == 2
+               && !strncmp(itemS32->comment, "", 2),
+               "psMetadataItemAllocS32:    create valid S32 item.");
+            skip_end();
+        }
+        //S64
+        {
+            skip_start(itemS64 == NULL, 1,
+                       "Skipping 1 tests because psMetadataItemAllocS64() failed");
+            ok(itemS64->type == PS_DATA_S64
+               && !strncmp(itemS64->name, "itemS64", 10)
+               && itemS64->data.S64 == 3
+               && !strncmp(itemS64->comment, "", 2),
+               "psMetadataItemAllocS64:    create valid S64 item.");
+            skip_end();
+        }
+        //U8
+        {
+            skip_start(itemU8 == NULL, 1,
+                       "Skipping 1 tests because psMetadataItemAllocU8() failed");
+            ok(itemU8->type == PS_DATA_U8
+               && !strncmp(itemU8->name, "itemU8", 10)
+               && itemU8->data.U8 == 0
+               && !strncmp(itemU8->comment, "", 2),
+               "psMetadataItemAllocU8:     create valid U8 item.");
+            skip_end();
+        }
+        //U16
+        {
+            skip_start(itemU16 == NULL, 1,
+                       "Skipping 1 tests because psMetadataItemAllocU16() failed");
+            ok(itemU16->type == PS_DATA_U16
+               && !strncmp(itemU16->name, "itemU16", 10)
+               && itemU16->data.U16 == 1
+               && !strncmp(itemU16->comment, "", 2),
+               "psMetadataItemAllocU16:    create valid U16 item.");
+            skip_end();
+        }
+        //U32
+        {
+            skip_start(itemU32 == NULL, 1,
+                       "Skipping 1 tests because psMetadataItemAllocU32() failed");
+            ok(itemU32->type == PS_DATA_U32
+               && !strncmp(itemU32->name, "itemU32", 10)
+               && itemU32->data.U32 == 2
+               && !strncmp(itemU32->comment, "", 2),
+               "psMetadataItemAllocU32:   create valid U32 item.");
+            skip_end();
+        }
+        //U64
+        {
+            skip_start(itemU64 == NULL, 1,
+                       "Skipping 1 tests because psMetadataItemAllocU64() failed");
+            ok(itemU64->type == PS_DATA_U64
+               && !strncmp(itemU64->name, "itemU64", 10)
+               && itemU64->data.U64 == 3
+               && !strncmp(itemU64->comment, "", 2),
+               "psMetadataItemAllocU64:   create valid U64 item.");
+            skip_end();
+        }
+        //Bool
+        {
+            skip_start(itemBool == NULL, 1,
+                       "Skipping 1 tests because psMetadataItemAllocBool() failed");
+            ok(itemBool->type == PS_DATA_BOOL
+               && !strncmp(itemBool->name, "itemBool", 10)
+               && itemBool->data.B
+               && !strncmp(itemBool->comment, "", 2),
+               "psMetadataItemAllocBool:  create valid Bool item.");
+            skip_end();
+        }
+    
+        //Allocate a pointer.  Example= psSphere
+        {
+            psSphere *s = psSphereAlloc();
+            s->r = 1.1;
+            s->d = 2.1;
+            psMetadataItem *itemPtr = psMetadataItemAllocPtr("itemPtr", PS_DATA_SPHERE, "", s);
+            skip_start(itemPtr == NULL, 1,
+                       "Skipping 1 tests because psMetadataItemAllocPtr() failed");
+            float r = ((psSphere*)(itemPtr->data.V))->r;
+            float d = ((psSphere*)(itemPtr->data.V))->d;
+            ok( itemPtr->type == PS_DATA_SPHERE
+                && !strncmp(itemPtr->name, "itemPtr", 10)
+                && abs(r-1.1) < FLT_EPSILON && abs(d-2.1) < FLT_EPSILON
+                && !strncmp(itemPtr->comment, "", 2),
+                "psMetadataItemAllocPtr:   create valid ptr (psSphere) item.");
+            skip_end();
+            psFree(s);
+            psFree(itemPtr);
+        }
+    
+        //Try to Allocate an unsupported type with AllocV
+        {
+            psMetadataItem *itemNULL = NULL;
+            psLine *line = psLineAlloc(2);
+            itemNULL = psMetadataItemAlloc("itemNULL", PS_DATA_LINE, NULL, line);
+            ok( itemNULL == NULL,
+                "psMetadataItemAlloc:      return NULL for unsupported type.");
+            psFree(line);
+        }
+    
+        //Now Allocate the item with Alloc and test MemCheck for it's type.
+        {
+            psMetadataItem *itemAllocV = psMetadataItemAlloc("itemAllocV", PS_DATA_S32, NULL, 4);
+            skip_start(itemAllocV == NULL, 2,
+                       "Skipping 2 tests because psMetadataItemAllocV() failed");
+            ok (itemAllocV->type == PS_DATA_S32
+                && !strncmp(itemAllocV->name, "itemAllocV", 10)
+                && itemAllocV->data.S32 == 4
+                && !strncmp(itemAllocV->comment, "", 2),
+                "psMetadataItemAlloc:      create valid S32 item.");
+            ok ( psMemCheckMetadataItem(itemAllocV),
+                 "psMemCheckMetadataItem:   return true for valid MetadataItem.");
+            skip_end();
+            psFree(itemAllocV);
+        }
+    
+        //Make sure MemCheckItem worked.  Try primitive type.  Expect false.
+	// XXX EAM : disabled
+        if (0) {
+            int j = 2;
+            ok( !psMemCheckMetadataItem(&j),
+                "psMemCheckMetadataItem:   return false for non-MetadataItem input.");
+        }
+    
+        psFree(itemStr);
+        psFree(itemF32);
+        psFree(itemF64);
+        psFree(itemS8);
+        psFree(itemS16);
+        psFree(itemS32);
+        psFree(itemS64);
+        psFree(itemU8);
+        psFree(itemU16);
+        psFree(itemU32);
+        psFree(itemU64);
+        psFree(itemBool);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psMetadataAlloc & psMetadataAdd Fxns");
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = NULL;
+        md = psMetadataAlloc();
+        psMetadata *md1 = psMetadataAlloc();
+        psMetadata *md2 = psMetadataAlloc();
+        //test MemCheck for a valid psMetadata
+        {
+            ok( psMemCheckMetadata(md),
+                "psMemCheckMetadata:       return true for valid Metadata.");
+        }
+        //Make sure MemCheck worked.  Try primitive type.  Expect false.
+	// XXX EAM : disabled
+        if (0) {
+            int j = 2;
+            ok( !psMemCheckMetadata(&j),
+                "psMemCheckMetadata:       return false for non-Metadata input.");
+        }
+        //Return false for attempt to add a psMetadataItem with no name.
+        {
+            ok( !psMetadataAdd(md1, PS_LIST_HEAD, NULL, PS_DATA_S32, "", 1),
+                "psMetadataAdd:            return false for adding item with no name.");
+        }
+        psFree(md1);
+        md1 = psMetadataAlloc();
+    
+        //Return false for NULL metadata input
+        psMetadataItem *item = psMetadataItemAllocBool("item", "", true);
+        {
+            ok( !psMetadataAddItem(NULL, item, PS_LIST_HEAD, PS_META_DEFAULT),
+                "psMetadataAddItem:        return false for NULL metadata input.");
+        }
+        //Return false for metadata with NULL hash
+        psFree(md1->hash);
+        md1->hash = NULL;
+        {
+            ok( !psMetadataAddItem(md1, item, PS_LIST_HEAD, PS_META_DEFAULT),
+                "psMetadataAddItem:        return false for metadata with no hash.");
+        }
+        psFree(md1);
+        //Return false for metadata with NULL list
+        psFree(md2->list);
+        md2->list = NULL;
+        {
+            ok( !psMetadataAddItem(md2, item, PS_LIST_HEAD, PS_META_DEFAULT),
+                "psMetadataAddItem:        return false for metadata with no list.");
+        }
+        psFree(md2);
+        //Return false for NULL psMetadataItem input
+        {
+            ok( !psMetadataAddItem(md, NULL, PS_LIST_HEAD, PS_META_DEFAULT),
+                "psMetadataAddItem:        return false for NULL item input.");
+        }
+        //Return false for psMetadataItem with NULL name
+        psFree(item->name);
+        item->name = NULL;
+        {
+            ok( !psMetadataAddItem(md, item, PS_LIST_HEAD, PS_META_DEFAULT),
+                "psMetadataAddItem:        return false for item with no name.");
+        }
+        psFree(item);
+    
+        psMetadata *itemMD = psMetadataAlloc();
+        psMetadataAddS32(itemMD, PS_LIST_HEAD, "s", PS_META_DUPLICATE_OK, "", 2);
+        psMetadataItem *item2 = psMetadataItemAllocS32("s", "", 2);
+    
+        //Return true for addition of multi
+        {
+            ok( psMetadataAddItem(md, item2, PS_LIST_TAIL, PS_META_DUPLICATE_OK),
+                "psMetadataAddItem:        return true for addition of PS_DATA_METADATA_MULTI.");
+        }
+        psFree(item2);
+        psFree(itemMD);
+    
+        //Existing entry with duplicate key found.
+        psMetadataAddS32(md, PS_LIST_HEAD, "S32", 0, "", 1);
+        item2 = psMetadataItemAllocS32("S32", "", 1);
+        //FLAG = PS_META_REPLACE
+        {
+            ok( psMetadataAddItem(md, item2, PS_LIST_TAIL, PS_META_REPLACE),
+                "psMetadataAddItem:        return true for PS_META_REPLACE flag.");
+        }
+        //FLAG = PS_META_DUPLICATE_OK
+        {
+            ok( psMetadataAddItem(md, item2, PS_LIST_TAIL, PS_META_DUPLICATE_OK),
+                "psMetadataAddItem:        return true for PS_META_DUPLICATE_OK flag.");
+        }
+        /*        SEE BELOW.  TEST CASE REDONE b/c item2 in md was already a MULTI
+        //FLAG = PS_META_NO_REPLACE
+        {
+            ok( psMetadataAddItem(md, item2, PS_LIST_TAIL, PS_META_NO_REPLACE),
+                "psMetadataAddItem:        return true for PS_META_NO_REPLACE flag.");
+        }
+        */
+        //FLAG = PS_META_DEFAULT
+        {
+            ok( psMetadataAddItem(md, item2, PS_LIST_TAIL, PS_META_DEFAULT),
+                "psMetadataAddItem:        return false for PS_META_DEFAULT flag.");
+        }
+    
+        //Return false for attempting to add an element twice with flag NO_REPLACE
+        {
+            psMetadata *norep = psMetadataAlloc();
+            psMetadataAddS32(norep, PS_LIST_HEAD, "S32", 0, "", 1);
+            psMetadataItem *item666 = psMetadataItemAllocS32("S32", "", 1);
+            ok( psMetadataAddItem(norep, item666, PS_LIST_TAIL, PS_META_NO_REPLACE),
+                "psMetadataAddItem:        return true for PS_META_NO_REPLACE flag.");
+            psFree(item666);
+            psFree(norep);
+        }
+        //Return false for bad list location
+        {
+            psMetadata *emptymeta = psMetadataAlloc();
+            psMetadataItem *item666 = psMetadataItemAllocS32("S32", "", 1);
+            ok( !psMetadataAddItem(emptymeta, item666, -100, PS_META_NO_REPLACE),
+                "psMetadataAddItem:        return false for invalid list location.");
+            psFree(item666);
+            psFree(emptymeta);
+        }
+        //Return false for trying to add to MULTI with broken list element.
+        {
+            psMetadata *broken_list = psMetadataAlloc();
+            psMetadataAddS32(broken_list, PS_LIST_HEAD, "S32", 0, "", 1);
+            psMetadataAddS32(broken_list, PS_LIST_TAIL, "S32", PS_META_DUPLICATE_OK, "", 1);
+            psMetadataItem *brokenptr = psMetadataLookup(broken_list, "S32");
+            if (brokenptr->type != PS_DATA_METADATA_MULTI)
+                printf("\nError, Error\n");
+            else
+            {
+                psFree(brokenptr->data.list);
+                brokenptr->data.list = NULL;
+            }
+            psMetadataItem *item666 = psMetadataItemAllocS32("S32", "", 1);
+            ok( !psMetadataAddItem(broken_list, item666, PS_LIST_TAIL, PS_META_DUPLICATE_OK),
+                "psMetadataAddItem:        return false for MULTI with NULL list.");
+            psFree(item666);
+            psFree(broken_list);
+        }
+    
+        //Attempt to add a MULTI
+        psFree(item2);
+        item2 = NULL;
+        psMetadata *xxx = psMetadataAlloc();
+        psMetadataAddS32(xxx, PS_LIST_TAIL, "new S32", 0, "", 1);
+        item2 = psMetadataItemAllocS32("new S32", "", 1);
+        psMetadataAddItem(xxx, item2, PS_LIST_TAIL, PS_META_DUPLICATE_OK);
+        psFree(item2);
+        item2 = psMetadataLookup(xxx, "new S32");
+        {
+            ok( psMetadataAddItem(md, item2, PS_LIST_TAIL, PS_META_DUPLICATE_OK),
+                "psMetadataAddItem:        return true for new MULTI item");
+        }
+        //Attempt to add a 2nd reference of a MULTI to the originating metadata container
+        {
+            ok( !psMetadataAddItem(xxx, item2, PS_LIST_TAIL, PS_META_NO_REPLACE),
+                "psMetadataAddItem:        return false for attempt to add 2nd reference"
+                " of a MULTI");
+        }
+        psFree(xxx);
+    
+        //No existing entries or duplicates found
+        item2 = psMetadataItemAllocS32("new", "", 2);
+        {
+            ok( psMetadataAddItem(md, item2, PS_LIST_TAIL, PS_META_DUPLICATE_OK),
+                "psMetadataAddItem:        return true for new item.");
+        }
+    
+        psFree(item2);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+    
+
+    // psMetadataIteratorAlloc
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = psMetadataAlloc();
+        psMetadata *md2 = NULL;
+        psMetadataAddS32(md, PS_LIST_HEAD, "S32_1", PS_META_NO_REPLACE, "", 1);
+        psMetadataAddS32(md, PS_LIST_TAIL, "S32_2", PS_META_DEFAULT, "", 2);
+    
+        psMetadataIterator *iter = NULL;
+        //Return NULL for NULL metadata input
+        {
+            iter = psMetadataIteratorAlloc(md2, PS_LIST_HEAD, NULL);
+            ok( iter == NULL,
+                "psMetadataIteratorAlloc:  return NULL for NULL metadata input.");
+        }
+        //Return NULL for metadata with no List
+        md2 = psMetadataAlloc();
+        psFree(md2->list);
+        md2->list = NULL;
+        {
+            iter = psMetadataIteratorAlloc(md2, PS_LIST_HEAD, NULL);
+            ok( iter == NULL,
+                "psMetadataIteratorAlloc:  return NULL for metadata with no list.");
+        }
+        psFree(md2);
+    
+        //Return newly allocated MetadataIterator, regex=NULL
+        {
+            iter = psMetadataIteratorAlloc(md, PS_LIST_HEAD, NULL);
+            ok( iter != NULL,
+                "psMetadataIteratorAlloc:  return valid iterator for valid inputs, regex=NULL.");
+        }
+        //Return NULL for attempt to allocate an iterator with unfound regex.
+        psFree(iter);
+        iter = NULL;
+        {
+            iter = psMetadataIteratorAlloc(md, PS_LIST_HEAD, "IPP.machines.sky");
+            ok( iter == NULL,
+                "psMetadataIteratorAlloc:  return NULL for not-found regex input");
+        }
+        //Return NULL for invalid regex input.
+        {
+            iter = psMetadataIteratorAlloc(md, PS_LIST_HEAD, "IPP.machines.sky\\");
+            ok( iter == NULL,
+                "psMetadataIteratorAlloc:  return NULL for invalid regex input");
+        }
+        //Return properly allocated iterator for valid non-null regex input.
+        {
+            iter = psMetadataIteratorAlloc(md, PS_LIST_HEAD, "S32_");
+            ok( iter != NULL,
+                "psMetadataIteratorAlloc:  return valid iterator for valid regex input");
+        }
+    
+        //Check for Memory leaks
+        {
+            psFree(iter);
+            psFree(md);
+            checkMem();
+        }
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadata_manip.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadata_manip.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadata_manip.c	(revision 22158)
@@ -0,0 +1,460 @@
+/**
+ *  C Implementation: tap_psMetadata_manip
+ *
+ * Description:  Tests for psMetadataRemove's, psMetadataLookup's (TYPE),
+ *
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <pslib.h>
+#include <string.h>
+#include "tap.h"
+#include "pstap.h"
+
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_WARN);
+    plan_tests(50);
+    // psMetadataLookup, Remove, and Iterator Fxns
+
+
+    // psMetadataLookup Functions
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = psMetadataAlloc();
+        psMetadataAddStr(md, PS_LIST_TAIL, "itemStr", 0, "I am a string", "GNIRTS");
+        psMetadataAddBool(md, PS_LIST_TAIL, "itemBool", 0, "I am a boolean", true);
+        psMetadataAddS8(md, PS_LIST_TAIL, "itemS8", 0, "I am S8", 6);
+        psMetadataAddS16(md, PS_LIST_TAIL, "itemS16", 0, "I am S16", -666);
+        psMetadataAddS32(md, PS_LIST_TAIL, "itemS32", 0, "I am a integer", 55);
+        psMetadataAddS64(md, PS_LIST_TAIL, "itemS64", 0, "I am S64", 666);
+        psMetadataAddU8(md, PS_LIST_TAIL, "itemU8", 0, "I am U8", 6);
+        psMetadataAddU16(md, PS_LIST_TAIL, "itemU16", 0, "I am U16", 666);
+        psMetadataAddU32(md, PS_LIST_TAIL, "itemU32", 0, "I am U32", 666);
+        psMetadataAddU64(md, PS_LIST_TAIL, "itemU64", 0, "I am U64", 666);
+        psMetadataAddF32(md, PS_LIST_TAIL, "itemF32", 0, NULL, 3.14);
+        psMetadataAddF64(md, PS_LIST_TAIL, "itemF64", 0, "", 6.28);
+        psSphere *sphere = psSphereAlloc();
+        sphere->r = 6.66;
+        sphere->d = 666.666;
+        psMetadataAddPtr(md, PS_LIST_HEAD, "ptr", PS_DATA_SPHERE, "", sphere);
+        //    psMetadataAddPtr(md, PS_LIST_TAIL, "ptr", PS_DATA_METADATA_MULTI, "", sphere);
+        psTime *time;
+        time = psTimeAlloc(PS_TIME_TAI);
+        time->sec = 1000;
+        time->nsec = 25;
+        time->leapsecond = true;
+        psMetadataAddTime(md, PS_LIST_TAIL, "time01", 0, "I am time", time);
+        psMetadata *newMD = psMetadataAlloc();
+        psMetadataAddS32(newMD, PS_LIST_TAIL, "1", 0, "", 666);
+        psMetadataAddMetadata(md, PS_LIST_TAIL, "metadata7", 0, "I am a metadata", newMD);
+    
+        //Lookup Standard number-types (valid cases)
+        //U8
+        {
+            bool status = false;
+            psU8 u8 = 0;
+            u8 = psMetadataLookupU8(&status, md, "itemU8");
+            ok( status && u8 == 6,
+                "psMetadataLookupU8:     return correct U8 value on lookup.");
+        }
+        //U16
+        {
+            bool status = false;
+            psU16 u16 = 0;
+            u16 = psMetadataLookupU16(&status, md, "itemU16");
+            ok( status && u16 == 666,
+                "psMetadataLookupU16:    return correct U16 value on lookup.");
+        }
+        //U32
+        {
+            bool status = false;
+            psU32 u32 = 0;
+            u32 = psMetadataLookupU32(&status, md, "itemU32");
+            ok( status && u32 == 666,
+                "psMetadataLookupU32:    return correct U32 value on lookup.");
+        }
+        //U64
+        {
+            bool status = false;
+            psU64 u64 = 0;
+            u64 = psMetadataLookupU64(&status, md, "itemU64");
+            ok( status && u64 == 666,
+                "psMetadataLookupU64:    return correct U64 value on lookup.");
+        }
+        //S8
+        {
+            bool status = false;
+            psS8 s8 = 0;
+            s8 = psMetadataLookupS8(&status, md, "itemS8");
+            ok( status && s8 == 6,
+                "psMetadataLookupS8:     return correct S8 value on lookup.");
+        }
+        //S16
+        {
+            bool status = false;
+            psS16 s16 = 0;
+            s16 = psMetadataLookupS16(&status, md, "itemS16");
+            ok( status && s16 == -666,
+                "psMetadataLookupS16:    return correct S16 value on lookup.");
+        }
+        //S32
+        {
+            bool status = false;
+            psS32 s32 = 0;
+            s32 = psMetadataLookupS32(&status, md, "itemS32");
+            ok( status && s32 == 55,
+                "psMetadataLookupS32:    return correct S32 value on lookup.");
+        }
+        //S64
+        {
+            bool status = false;
+            psS64 s64 = 0;
+            s64 = psMetadataLookupS64(&status, md, "itemS64");
+            ok( status && s64 == 666,
+                "psMetadataLookupS64:    return correct S64 value on lookup.");
+        }
+        //F32
+        {
+            bool status = false;
+            psF32 f32 = 0;
+            f32 = psMetadataLookupF32(&status, md, "itemF32");
+            ok( status && abs(f32 - 3.14) < FLT_EPSILON,
+                "psMetadataLookupF32:    return correct F32 value on lookup.");
+        }
+        //F64
+        {
+            bool status = false;
+            psF64 f64 = 0;
+            f64 = psMetadataLookupF64(&status, md, "itemF64");
+            ok( status && abs(f64 - 6.28) < DBL_EPSILON,
+                "psMetadataLookupF64:    return correct F64 value on lookup.");
+        }
+        //Bool
+        {
+            bool status = false;
+            bool stat = false;
+            stat = psMetadataLookupBool(&status, md, "itemBool");
+            ok( status && stat,
+                "psMetadataLookupBool:   return correct Bool value on lookup.");
+        }
+        //String
+        {
+            bool status = false;
+            psString str = NULL;
+            str = psMetadataLookupStr(&status, md, "itemStr");
+            ok( status && !strncmp(str, "GNIRTS", 8),
+                "psMetadataLookupStr:   return correct String value on lookup.");
+        }
+        //Pointer
+        {
+            bool status = false;
+            psSphere *sph = NULL;
+            sph = (psSphere*)(psMetadataLookupPtr(&status, md, "ptr"));
+            ok( status && sph != NULL && abs(sph->r-6.66) < FLT_EPSILON,
+                "psMetadataLookupPtr:   return correct pointer value on lookup.");
+        }
+        //Time
+        {
+            bool status = false;
+            psTime *t = NULL;
+            t = psMetadataLookupTime(&status, md, "time01");
+            ok( status && t->sec == 1000,
+                "psMetadataLookupTime:  return correct time value on lookup.");
+        }
+        //Metadata
+        {
+            bool status = false;
+            psMetadata *mdtemp = NULL;
+            mdtemp = psMetadataLookupMetadata(&status, md, "metadata7");
+            psMetadataItem *itemtemp = psMetadataGet(mdtemp, PS_LIST_HEAD);
+            ok( status && itemtemp->type == PS_DATA_S32 && itemtemp->data.S32 == 666,
+                "psMetadataLookupMD:    return correct metadata value on lookup.");
+        }
+    
+        //Try Negatives and non-standard lookup cases
+        //String  - invalid key name
+        {
+            bool status = false;
+            psString str = NULL;
+            str = psMetadataLookupStr(&status, md, "item");
+            ok( !status && str == NULL,
+                "psMetadataLookupStr:   return NULL for incorrect key.");
+            str = NULL;
+            str = psMetadataLookupStr(NULL, md, "item");
+            ok( str == NULL,
+                "psMetadataLookupStr:   return NULL for incorrect key (& NULL status).");
+        }
+        //String - wrong key->  lookup s8 data
+        {
+            bool status = false;
+            psString str = NULL;
+            str = psMetadataLookupStr(&status, md, "itemS8");
+            ok( !status && str == NULL,
+                "psMetadataLookupStr:   return NULL for incorrect key .");
+            str = NULL;
+            str = psMetadataLookupStr(NULL, md, "itemS8");
+            ok( str == NULL,
+                "psMetadataLookupStr:   return NULL for incorrect key (& NULL status).");
+        }
+        //Pointer - invalid key name
+        {
+            bool status = false;
+            psSphere *sph = NULL;
+            sph = psMetadataLookupPtr(&status, md, "item");
+            ok( !status && sph == NULL,
+                "psMetadataLookupPtr:   return NULL for incorrect key.");
+        }
+        //Pointer - wrong key -> lookup s8 data
+        {
+            bool status = false;
+            psSphere *sph = NULL;
+            sph = psMetadataLookupPtr(&status, md, "itemS8");
+            ok( !status && sph == NULL,
+                "psMetadataLookupPtr:   return NULL for incorrect key.");
+        }
+    
+        //Pointer**  - lookup a PS_DATA_METADATA_MULTI
+        {
+            psMetadata *metadata = psMetadataAlloc();
+            psMetadataItem *multi = psMetadataItemAlloc("ptr", PS_DATA_METADATA_MULTI, "", NULL);
+            psMetadataAddItem(metadata, multi, PS_LIST_HEAD, PS_META_DUPLICATE_OK);
+            psMetadataAddPtr(metadata, PS_LIST_TAIL, "ptr",
+                             PS_DATA_SPHERE | PS_META_DUPLICATE_OK, "", sphere);
+            psSphere *s = psSphereAlloc();
+            s->r = 0.666;
+            psMetadataAddPtr(metadata, PS_LIST_TAIL, "ptr", PS_DATA_SPHERE | PS_META_DUPLICATE_OK, "", s);
+            psFree(s);
+            psMetadataItem *metadataItem = NULL;
+            metadataItem = psMetadataLookup(metadata, "ptr");
+            bool status = false;
+            psSphere *sph = NULL;
+            sph = (psSphere*)(psMetadataLookupPtr(&status, metadata, "ptr"));
+            ok( status && sph != NULL && fabs(sph->r - 6.66) < FLT_EPSILON,
+                "psMetadataLookupPtr:   return correct value on lookup of MULTI item.");
+            psFree(metadata);
+            psFree(multi);
+        }
+    
+        //Metadata - invalid key name
+        {
+            bool status = false;
+            psMetadata *met = NULL;
+            met = psMetadataLookupMetadata(&status, md, "item");
+            ok( !status && met == NULL,
+                "psMetadataLookupMD:   return NULL for incorrect key.");
+            met = NULL;
+            met = psMetadataLookupMetadata(NULL, md, "item");
+            ok( met == NULL,
+                "psMetadataLookupMD:   return NULL for incorrect key (& NULL status).");
+        }
+        //Metadata - wrong key -> lookup s8 data
+        {
+            bool status = false;
+            psMetadata *met = NULL;
+            met = psMetadataLookupMetadata(&status, md, "itemS8");
+            ok( !status && met == NULL,
+                "psMetadataLookupMD:   return NULL for incorrect key (& NULL status).");
+            met = NULL;
+            met = psMetadataLookupMetadata(NULL, md, "itemS8");
+            ok( met == NULL,
+                "psMetadataLookupMD:   return NULL for incorrect key.");
+        }
+        //Time - invalid key name
+        {
+            bool status = false;
+            psTime *time = NULL;
+            time = psMetadataLookupTime(&status, md, "item");
+            ok( !status && time == NULL,
+                "psMetadataLookupTime:   return NULL for incorrect key.");
+            time = NULL;
+            time = psMetadataLookupTime(NULL, md, "item");
+            ok( time == NULL,
+                "psMetadataLookupTime:   return NULL for incorrect key (& NULL status).");
+        }
+        //Time - wrong key -> lookup s8 data
+        {
+            bool status = false;
+            psTime *time = NULL;
+            time = psMetadataLookupTime(&status, md, "itemS8");
+            ok( !status && time == NULL,
+                "psMetadataLookupTime:   return NULL for incorrect key.");
+            time = NULL;
+            time = psMetadataLookupTime(NULL, md, "itemS8");
+            ok( time == NULL,
+                "psMetadataLookupTime:   return NULL for incorrect key (& NULL status).");
+        }
+    
+        psFree(sphere);
+        psFree(time);
+        psFree(newMD);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psMetadataRemove Functions
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = psMetadataAlloc();
+        psMetadataAddStr(md, PS_LIST_TAIL, "itemStr", 0, "I am a string", "GNIRTS");
+        psMetadataAddBool(md, PS_LIST_TAIL, "itemBool", 0, "I am a boolean", true);
+        psMetadataAddS8(md, PS_LIST_TAIL, "itemS8", 0, "I am S8", 6);
+        psMetadataAddS16(md, PS_LIST_TAIL, "itemS16", 0, "I am S16", -666);
+        psMetadataAddS32(md, PS_LIST_TAIL, "itemS32", 0, "I am a integer", 55);
+        psMetadataAddS64(md, PS_LIST_TAIL, "itemS64", PS_META_DUPLICATE_OK, "I am S64", 666);
+        psMetadataAddU8(md, PS_LIST_TAIL, "itemU8", 0, "I am U8", 6);
+    
+        //psMetadataRemoveKey
+        {
+            bool status = psMetadataRemoveKey(md, "itemU8");
+            psMetadataItem *temp = psMetadataGet(md, PS_LIST_TAIL);
+            ok( status && temp->type == PS_DATA_S64,
+                "psMetadataRemoveKey:    return true for valid case.");
+        }
+        //psMetadataRemoveIndex
+        {
+            bool status = psMetadataRemoveIndex(md, PS_LIST_HEAD);
+            psMetadataItem *temp = psMetadataGet(md, PS_LIST_HEAD);
+            ok( status && temp->type == PS_DATA_BOOL,
+                "psMetadataRemoveIndex:  return true for valid case.");
+        }
+        //Attempt to remove an incorrect key - Return false
+        {
+            ok( !psMetadataRemoveKey(md, "BigDog"),
+                "psMetadataRemoveKey:    return false for incorrect key.");
+        }
+        //Attempt to remove an out-of-range index - Return false
+        {
+            ok( !psMetadataRemoveIndex(md, 20),
+                "psMetadataRemoveIndex:  return false for incorrect index.");
+        }
+        //Attempt to remove an item with NULL name
+        {
+            psMetadataItem *temp = psMetadataGet(md, PS_LIST_HEAD);
+            psFree(temp->name);
+            temp->name = NULL;
+            ok( !psMetadataRemoveIndex(md, PS_LIST_HEAD),
+                "psMetadataRemoveIndex:  return false for item with no name.");
+        }
+        //Attempt to remove an item with wrong hash table
+        {
+            psMetadata *md2 = psMetadataAlloc();
+            psMetadataAddBool(md2, PS_LIST_TAIL, "Bool", 0, "I am a boolean", true);
+            psMetadataAddS8(md2, PS_LIST_TAIL, "S8", 0, "I am S8", 6);
+            psMetadataAddS16(md2, PS_LIST_TAIL, "S16", 0, "I am S16", -666);
+            psMetadataAddS32(md2, PS_LIST_TAIL, "S32", 0, "I am a integer", 55);
+            psMetadataAddS64(md2, PS_LIST_TAIL, "S64", 0, "I am S64", 666);
+    
+            psFree(md2->hash);
+            md2->hash = NULL;
+            md2->hash = md->hash;
+            ok( !psMetadataRemoveIndex(md2, PS_LIST_HEAD),
+                "psMetadataRemoveIndex:  return false for item with bad table.");
+            md2->hash = NULL;
+            psFree(md2);
+        }
+        //Attempt to remove a METADATA_MULTI item by key
+        {
+            psMetadataAddS64(md, PS_LIST_TAIL, "itemS64", PS_META_DUPLICATE_OK, "I am S64", 667);
+            psMetadataAddS64(md, PS_LIST_TAIL, "itemS64", PS_META_DUPLICATE_OK, "I am S64", 668);
+            bool status = psMetadataRemoveKey(md, "itemS64");
+            psMetadataItem *temp = psMetadataGet(md, PS_LIST_TAIL);
+            ok( status && temp->type == PS_DATA_S32,
+                "psMetadataRemoveKey:    return true for valid METADATA_MULTI case.");
+    
+        }
+        //Attempt to remove a METADATA_MULTI item by index
+        {
+            psMetadataAddS64(md, PS_LIST_TAIL, "itemS64", PS_META_DUPLICATE_OK, "I am S64", 667);
+            psMetadataAddS64(md, PS_LIST_TAIL, "itemS64", PS_META_DUPLICATE_OK, "I am S64", 668);
+            bool status = psMetadataRemoveIndex(md, PS_LIST_TAIL);
+            psMetadataItem *temp = psMetadataGet(md, PS_LIST_TAIL);
+            ok( status && temp->type == PS_DATA_S64,
+                "psMetadataRemoveIndex:  return true for valid METADATA_MULTI case.");
+        }
+    
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+    
+
+    // psMetadataIterator Functions
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = psMetadataAlloc();
+        psMetadataAddS32(md, PS_LIST_HEAD, "S32_1", PS_META_NO_REPLACE, "", 1);
+        psMetadataAddS32(md, PS_LIST_TAIL, "S32_2", PS_META_NO_REPLACE, "", 2);
+        psMetadataAddS32(md, PS_LIST_TAIL, "S32_3", PS_META_NO_REPLACE, "", 3);
+    
+        psMetadataIterator *iter = NULL;
+    
+        //Return NULL in psMetadataGetAnd(In/De)crement for NULL iterator input
+        {
+            ok( psMetadataGetAndIncrement(NULL) == NULL,
+                "psMetadataGetAndIncrement:  return NULL for NULL iterator input.");
+            ok( psMetadataGetAndDecrement(NULL) == NULL,
+                "psMetadataGetAndDecrement:  return NULL for NULL iterator input.");
+        }
+        //Return NULL in psMetadataGetAnd(In/De)crement for iterator with no list iterator
+        psMetadataIterator *iter2 = psMetadataIteratorAlloc(md, PS_LIST_HEAD, NULL);
+        psFree(iter2->iter);
+        iter2->iter = NULL;
+        {
+            ok( psMetadataGetAndIncrement(iter2) == NULL,
+                "psMetadataGetAndIncrement:  return NULL for iterator with no list iterator.");
+            ok( psMetadataGetAndDecrement(iter2) == NULL,
+                "psMetadataGetAndDecrement:  return NULL for iterator with no list iterator.");
+        }
+        psFree(iter2);
+    
+        //Return valid iterator for valid inputs, regex= NULL
+        psMetadataItem *item = NULL;
+        {
+            iter = psMetadataIteratorAlloc(md, PS_LIST_HEAD, NULL);
+            ok( iter != NULL,
+                "psMetadataIteratorAlloc:    return valid iterator for valid inputs, regex=NULL.");
+            skip_start(iter == NULL, 4,
+                       "Skipping 4 tests because psMetadataIteratorAlloc failed");
+    
+            item = psMetadataGetAndIncrement(iter);
+            ok( item != NULL,
+                "psMetadataGetAndIncrement:  return valid item for valid iterator input.");
+            skip_start(item == NULL, 1,
+                       "Skipping 1 tests because psMetadataGetAndIncrement failed");
+            ok(item->type == PS_DATA_S32
+               && !strncmp(item->name, "S32_1", 7)
+               && item->data.S32 == 1
+               && !strncmp(item->comment, "", 2),
+               "psMetadataGetAndIncrement:  retrieve correct item from valid iterator.");
+            skip_end();
+    
+            item = psMetadataGetAndDecrement(iter);
+            ok( item != NULL,
+                "psMetadataGetAndDecrement:  return valid item for valid iterator input.");
+            skip_start(item == NULL, 1,
+                       "Skipping 1 tests because psMetadataGetAndDecrement failed");
+            ok(item->type == PS_DATA_S32
+               && !strncmp(item->name, "S32_2", 7)
+               && item->data.S32 == 2
+               && !strncmp(item->comment, "", 2),
+               "psMetadataGetAndDecrement:  retrieve correct item from valid iterator.");
+            skip_end();
+    
+            skip_end();
+    
+        }
+    
+        psFree(iter);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
+    
+    
+                
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadata_polynomials.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadata_polynomials.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadata_polynomials.c	(revision 22158)
@@ -0,0 +1,828 @@
+/**
+ *  C Implementation: tap_psMetadata_polynomials
+ *
+ * Description:  Tests for psPolynomial(2,3,4)D(to/from)MD
+ *
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <pslib.h>
+#include <string.h>
+#include "tap.h"
+#include "pstap.h"
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(92);
+    // psPolynomial(1D, 2D, 3D, & 4D)(to/from)Metadata tests
+
+
+    // psPolynomial1DtoMetadata & psPolynomial1DfromMetadata functions
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = psMetadataAlloc();
+        psPolynomial1D *p1d = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 1);
+        p1d->coeff[0] = 1.1;
+        p1d->coeff[1] = 2.2;
+        p1d->coeffErr[0] = 0.1;
+        p1d->coeffErr[1] = 0.2;
+    
+        //psPolynomial1DtoMetadata
+        //Return a valid metadata containing a polynomial-metadata structure
+        {
+            note ("example of 1DtoMD using the names not the sequence");
+    
+            ok( psPolynomial1DtoMetadata(md, p1d, "polyMD"),
+                "psPolynomial1DtoMetadata:      return true for valid inputs.");
+            psMetadata *polyMDtemp = psMetadataLookupMetadata(NULL, md, "polyMD");
+            skip_start( polyMDtemp == NULL , 1,
+                        "Skipping 1 tests because psPolynomial1DtoMetadata has errors");
+    
+            bool status;
+            int nX = psMetadataLookupS32(&status, polyMDtemp, "NORDER_X");
+            ok(status,
+               "psPolynomial1DtoMetadata:      found NORDER_X");
+            ok(nX == 1,
+               "psPolynomial1DtoMetadata:      NORDER_X is 1");
+    
+            double val;
+            val = psMetadataLookupF64(&status, polyMDtemp, "VAL_X00");
+            ok(status,
+               "psPolynomial1DtoMetadata:      found VAL_X00");
+            is_double(val, 1.1,
+                      "psPolynomial1DtoMetadata:      VAL_X00 is %lf", val);
+    
+            val = psMetadataLookupF64(&status, polyMDtemp, "VAL_X01");
+            ok(status,
+               "psPolynomial1DtoMetadata:      found VAL_X01");
+            is_double(val, 2.2,
+                      "psPolynomial1DtoMetadata:      VAL_X01 is %lf", val);
+            skip_end();
+        }
+    
+        //Return false for no-name polynomial
+        {
+            ok( !psPolynomial1DtoMetadata(md, p1d, " "),
+                "psPolynomial1DtoMetadata:      return false for no-name.");
+        }
+        //Return false for NULL-name polynomial
+        {
+            ok( !psPolynomial1DtoMetadata(md, p1d, NULL),
+                "psPolynomial1DtoMetadata:      return false for NULL name input.");
+        }
+        //Return false for NULL metadata input
+        {
+            ok( !psPolynomial1DtoMetadata(NULL, p1d, "polyMD"),
+                "psPolynomial1DtoMetadata:     return false for NULL metadata input.");
+        }
+        //Return false for NULL polynomial input
+        {
+            ok( !psPolynomial1DtoMetadata(md, NULL, "polyMD"),
+                "psPolynomial1DtoMetadata:     return false for NULL polynomial input.");
+        }
+        //Return true for polynomial with 1 element, a constant
+        {
+            psPolynomial1D *constPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 0);
+            constPoly->coeff[0] = 6.66;
+            ok( psPolynomial1DtoMetadata(md, constPoly, "polyMD"),
+                "psPolynomial1DtoMetadata:     return true for constant polynomial (1 element != 0).");
+            psFree(constPoly);
+        }
+        //Return false for non-ordinary polynomial
+        {
+            psPolynomial1D *p1d1 = psPolynomial1DAlloc(PS_POLYNOMIAL_CHEB, 1);
+            p1d1->coeff[0] = 1.1;
+            ok( !psPolynomial1DtoMetadata(md, p1d1, "polyMD"),
+                "psPolynomial1DtoMetadata:     return false for chebyshev polynomial");
+            psFree(p1d1);
+        }
+    
+        //psPolynomial1DfromMetadata Tests
+        //Return NULL for NULL metadata input.
+        {
+            psPolynomial1D *emptyPoly1D = NULL;
+            emptyPoly1D = psPolynomial1DfromMetadata(NULL);
+            ok( emptyPoly1D == NULL,
+                "psPolynomial1DfromMetadata:   return NULL for NULL metadata input.");
+        }
+        //Get a polynomial from Metadata.
+        psPolynomial1D *outPoly = NULL;
+        psMetadata *polyMDtemp = psMetadataLookupMetadata(NULL, md, "polyMD");
+        outPoly = psPolynomial1DfromMetadata(polyMDtemp);
+        {
+            skip_start( outPoly == NULL, 1,
+                        "Skipping 1 tests because psPolynomial1DfromMetadata has errors.");
+            ok( outPoly->type == PS_POLYNOMIAL_ORD && outPoly->nX == 1 &&
+                abs(outPoly->coeff[0] - 1.1) < DBL_EPSILON,
+                "psPolynomial1DfromMetadata:   return correct polynomial from metadata");
+            skip_end();
+        }
+        //Get a polynomial from Metadata with mask[0] == 1.
+        psFree(outPoly);
+        outPoly = NULL;
+        psPolynomial1D *maskPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 0);
+        maskPoly->coeff[0] = 6.66;
+        maskPoly->coeffMask[0] = 1;
+        psMetadata *newmd = psMetadataAlloc();
+        psPolynomial1DtoMetadata(newmd, maskPoly, "polyMD");
+        psMetadata *polyMask = psMetadataLookupMetadata(NULL, newmd, "polyMD");
+        outPoly = psPolynomial1DfromMetadata(polyMask);
+        {
+            ok( outPoly->type == PS_POLYNOMIAL_ORD && outPoly->nX == 0 &&
+                outPoly->coeffMask[0] == 1,
+                "psPolynomial1DfromMetadata:   return correct polynomial (w/mask) from metadata");
+        }
+        psFree(maskPoly);
+        psFree(newmd);
+        //Return NULL for wrong NELEMENTS
+        psMetadataItem *nElementItem = psMetadataGet(polyMDtemp, PS_LIST_TAIL);
+        nElementItem->data.S32 -= 1;
+        psFree(outPoly);
+        outPoly = NULL;
+        outPoly = psPolynomial1DfromMetadata(polyMDtemp);
+        {
+            ok( outPoly == NULL,
+                "psPolynomial1DfromMetadata:   "
+                "return NULL for metadata-polynomial with wrong NELEMENTS");
+        }
+        //Return NULL for missing NELEMENTS
+        psMetadataRemoveIndex(polyMDtemp, PS_LIST_TAIL);
+        psFree(outPoly);
+        outPoly = NULL;
+        outPoly = psPolynomial1DfromMetadata(polyMDtemp);
+        {
+            ok( outPoly == NULL,
+                "psPolynomial1DfromMetadata:   "
+                "return NULL for metadata-polynomial with no NELEMENTS");
+        }
+    
+        //Return NULL for polynomial in metadata with no x-order
+        psMetadataRemoveKey(polyMDtemp, "NORDER_X");
+        psFree(outPoly);
+        outPoly = NULL;
+        outPoly = psPolynomial1DfromMetadata(polyMDtemp);
+        {
+            ok( outPoly == NULL,
+                "psPolynomial1DfromMetadata:   "
+                "return NULL for metadata-polynomial with no x-order");
+        }
+    
+        psFree(outPoly);
+        psFree(p1d);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psPolynomial2DtoMetadata & psPolynomial2DfromMetadata functions
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = psMetadataAlloc();
+        psPolynomial2D *p2d = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 1, 1);
+        p2d->coeff[0][0] = 1.1;
+        p2d->coeff[0][1] = 2.2;
+        p2d->coeff[1][0] = 3.3;
+        p2d->coeff[1][1] = 4.4;
+        p2d->coeffErr[0][0] = 0.1;
+        p2d->coeffErr[0][1] = 0.2;
+        p2d->coeffErr[1][0] = 0.3;
+        p2d->coeffErr[1][1] = 0.4;
+    
+        //psPolynomial2DtoMetadata
+        //Return a valid metadata containing a polynomial-metadata structure
+        {
+            ok( psPolynomial2DtoMetadata(md, p2d, "polyMD"),
+                "psPolynomial2DtoMetadata:     return true for valid inputs.");
+    
+            // psMetadataConfigWrite (md, "test.md");
+    
+            //XXX        ok (0, "these tests are relying on the ORDER of the MD components not the NAMES");
+            //XXX        ok (0, "these seem like irrelevant tests");
+            psMetadata *polyMDtemp = psMetadataLookupMetadata(NULL, md, "polyMD");
+            skip_start( polyMDtemp == NULL , 1,
+                        "Skipping 1 tests because psPolynomial2DtoMetadata has errors");
+            psMetadataItem *polyItem = psMetadataGet(polyMDtemp, 0);
+            skip_start( polyItem == NULL, 2,
+                        "Skipping 2 tests because psPolynomial2DtoMetadata has errors in order elements");
+            ok( !strncmp(polyItem->name, "NORDER_X", 10) && polyItem->data.S32 == 1,
+                "psPolynomial2DtoMetadata:     return correct number of x orders.");
+            polyItem = psMetadataGet(polyMDtemp, 1);
+            ok( !strncmp(polyItem->name, "NORDER_Y", 10) && polyItem->data.S32 == 1,
+                "psPolynomial2DtoMetadata:     return correct number of y orders.");
+            skip_end();
+            polyItem = psMetadataGet(polyMDtemp, 2);
+            skip_start( polyItem == NULL, 2,
+                        "Skipping 2 tests because psPolynomial2DtoMetadata has errors in coeff elements");
+            ok( !strncmp(polyItem->name, "VAL_X00_Y00", 14) &&
+                abs(polyItem->data.F64-1.1) < DBL_EPSILON,
+                "psPolynomial2DtoMetadata:     return correct first element.");
+            polyItem = psMetadataGet(polyMDtemp, PS_LIST_TAIL-1);
+            ok( !strncmp(polyItem->name, "ERR_X01_Y01", 14) &&
+                abs(polyItem->data.F64-0.4) < DBL_EPSILON,
+                "psPolynomial2DtoMetadata:     return correct last element.");
+            skip_end();
+            skip_end();
+        }
+    
+        //psPolynomial2DtoMetadata
+        //Return a valid metadata containing a polynomial-metadata structure
+        {
+            note ("example of 2DtoMD using the names not the sequence");
+    
+            ok( psPolynomial2DtoMetadata(md, p2d, "polyMD"),
+                "psPolynomial2DtoMetadata:     return true for valid inputs.");
+    
+            // psMetadataConfigWrite (md, "test.md");
+    
+            // of the components.  these seem like irrelevant tests.
+            psMetadata *polyMDtemp = psMetadataLookupMetadata(NULL, md, "polyMD");
+            skip_start( polyMDtemp == NULL , 1,
+                        "Skipping 1 tests because psPolynomial2DtoMetadata has errors");
+    
+            bool status;
+            int nX = psMetadataLookupS32(&status, polyMDtemp, "NORDER_X");
+            ok(status,
+               "psPolynomial2DtoMetadata:     found NORDER_X");
+            ok(nX == 1,
+               "psPolynomial2DtoMetadata:     NORDER_X is 1");
+    
+            int nY = psMetadataLookupS32(&status, polyMDtemp, "NORDER_Y");
+            ok(status,
+               "psPolynomial2DtoMetadata:     found NORDER_Y");
+            ok(nY == 1,
+               "psPolynomial2DtoMetadata:     NORDER_Y is 1");
+    
+            double val;
+            val = psMetadataLookupF64(&status, polyMDtemp, "VAL_X00_Y00");
+            ok(status,
+               "psPolynomial2DtoMetadata:     found VAL_X00_Y00");
+            is_double(val, 1.1,
+                      "psPolynomial2DtoMetadata:     VAL_X00_Y00 is %lf", val);
+    
+            val = psMetadataLookupF64(&status, polyMDtemp, "VAL_X01_Y01");
+            ok(status,
+               "psPolynomial2DtoMetadata:     found VAL_X01_Y01");
+            is_double(val, 4.4,
+                      "psPolynomial2DtoMetadata:     VAL_X01_Y01 is %lf", val);
+    
+            skip_end();
+        }
+    
+        //Return false for no-name polynomial
+        {
+            ok( !psPolynomial2DtoMetadata(md, p2d, " "),
+                "psPolynomial2DtoMetadata:     return false for no-name.");
+        }
+        //Return false for NULL-name polynomial
+        {
+            ok( !psPolynomial2DtoMetadata(md, p2d, NULL),
+                "psPolynomial2DtoMetadata:     return false for NULL name input.");
+        }
+        //Return false for NULL metadata input
+        {
+            ok( !psPolynomial2DtoMetadata(NULL, p2d, "polyMD"),
+                "psPolynomial2DtoMetadata:     return false for NULL metadata input.");
+        }
+        //Return false for NULL polynomial input
+        {
+            ok( !psPolynomial2DtoMetadata(md, NULL, "polyMD"),
+                "psPolynomial2DtoMetadata:     return false for NULL polynomial input.");
+        }
+        //Return true for polynomial with 1 element, a constant
+        {
+            psPolynomial2D *constPoly = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 0, 0);
+            constPoly->coeff[0][0] = 6.66;
+            ok( psPolynomial2DtoMetadata(md, constPoly, "polyMD"),
+                "psPolynomial2DtoMetadata:     return true for constant polynomial (1 element != 0).");
+            psFree(constPoly);
+        }
+        //Return false for non-ordinary polynomial
+        {
+            psPolynomial2D *p2d2 = psPolynomial2DAlloc(PS_POLYNOMIAL_CHEB, 1, 1);
+            p2d2->coeff[0][0] = 1.1;
+            ok( !psPolynomial2DtoMetadata(md, p2d2, "polyMD"),
+                "psPolynomial2DtoMetadata:     return false for chebyshev polynomial");
+            psFree(p2d2);
+        }
+    
+        //psPolynomial2DfromMetadata Tests
+        //Return NULL for NULL metadata input.
+        {
+            psPolynomial2D *emptyPoly2D = NULL;
+            emptyPoly2D = psPolynomial2DfromMetadata(NULL);
+            ok( emptyPoly2D == NULL,
+                "psPolynomial2DfromMetadata:   return NULL for NULL metadata input.");
+        }
+        //Get a polynomial from Metadata.
+        psPolynomial2D *outPoly = NULL;
+        psMetadata *polyMDtemp = psMetadataLookupMetadata(NULL, md, "polyMD");
+        outPoly = psPolynomial2DfromMetadata(polyMDtemp);
+        {
+            skip_start( outPoly == NULL, 1,
+                        "Skipping 1 tests because psPolynomial2DfromMetadata has errors.");
+            ok( outPoly->type == PS_POLYNOMIAL_ORD && outPoly->nX == 1 &&
+                outPoly->nY == 1 && abs(outPoly->coeff[0][0] - 1.1) < DBL_EPSILON,
+                "psPolynomial2DfromMetadata:   return correct polynomial from metadata");
+            skip_end();
+        }
+        //Get a polynomial from Metadata with mask[0][0] == 1.
+        psFree(outPoly);
+        outPoly = NULL;
+        psPolynomial2D *maskPoly = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 0, 0);
+        maskPoly->coeff[0][0] = 6.66;
+        maskPoly->coeffMask[0][0] = 1;
+        psMetadata *newmd = psMetadataAlloc();
+        psPolynomial2DtoMetadata(newmd, maskPoly, "polyMD");
+        psMetadata *polyMask = psMetadataLookupMetadata(NULL, newmd, "polyMD");
+        outPoly = psPolynomial2DfromMetadata(polyMask);
+        {
+            ok( outPoly->type == PS_POLYNOMIAL_ORD && outPoly->nX == 0 &&
+                outPoly->nY == 0 && outPoly->coeffMask[0][0] == 1,
+                "psPolynomial2DfromMetadata:   return correct polynomial (w/mask) from metadata");
+        }
+        psFree(maskPoly);
+        psFree(newmd);
+        //Return NULL for wrong NELEMENTS
+        psMetadataItem *nElementItem = psMetadataGet(polyMDtemp, PS_LIST_TAIL);
+        nElementItem->data.S32 -= 1;
+        psFree(outPoly);
+        outPoly = NULL;
+        outPoly = psPolynomial2DfromMetadata(polyMDtemp);
+        {
+            ok( outPoly == NULL,
+                "psPolynomial2DfromMetadata:   "
+                "return NULL for metadata-polynomial with wrong NELEMENTS");
+        }
+        //Return NULL for missing NELEMENTS
+        psMetadataRemoveIndex(polyMDtemp, PS_LIST_TAIL);
+        psFree(outPoly);
+        outPoly = NULL;
+        outPoly = psPolynomial2DfromMetadata(polyMDtemp);
+        {
+            ok( outPoly == NULL,
+                "psPolynomial2DfromMetadata:   "
+                "return NULL for metadata-polynomial with no NELEMENTS");
+        }
+    
+        //Return NULL for polynomial in metadata with no y-order
+        psMetadataRemoveKey(polyMDtemp, "NORDER_Y");
+        psFree(outPoly);
+        outPoly = NULL;
+        outPoly = psPolynomial2DfromMetadata(polyMDtemp);
+        {
+            ok( outPoly == NULL,
+                "psPolynomial2DfromMetadata:   "
+                "return NULL for metadata-polynomial with no y-order");
+        }
+        //Return NULL for polynomial in metadata with no x-order
+        psMetadataRemoveKey(polyMDtemp, "NORDER_X");
+        psFree(outPoly);
+        outPoly = NULL;
+        outPoly = psPolynomial2DfromMetadata(polyMDtemp);
+        {
+            ok( outPoly == NULL,
+                "psPolynomial2DfromMetadata:   "
+                "return NULL for metadata-polynomial with no x-order");
+        }
+
+        psFree(outPoly);
+        psFree(p2d);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psPolynomial3DtoMetadata & psPolynomial3DfromMetadata functions
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = psMetadataAlloc();
+        psPolynomial3D *p3d = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, 1, 1, 1);
+        p3d->coeff[0][0][0] = 1.1;
+        p3d->coeff[1][0][0] = 2.2;
+        p3d->coeff[0][1][0] = 3.3;
+        p3d->coeff[0][0][1] = 4.4;
+        p3d->coeff[1][1][0] = 5.5;
+        p3d->coeff[1][0][1] = 6.6;
+        p3d->coeff[0][1][1] = 7.7;
+        p3d->coeff[1][1][1] = 8.8;
+        p3d->coeffErr[0][0][0] = 0.1;
+        p3d->coeffErr[1][0][0] = 0.2;
+        p3d->coeffErr[0][1][0] = 0.3;
+        p3d->coeffErr[0][0][1] = 0.4;
+        p3d->coeffErr[1][1][0] = 0.5;
+        p3d->coeffErr[1][0][1] = 0.6;
+        p3d->coeffErr[0][1][1] = 0.7;
+        p3d->coeffErr[1][1][1] = 0.8;
+    
+        //psPolynomial3DtoMetadata
+        //Return a valid metadata containing a polynomial-metadata structure
+        {
+            ok( psPolynomial3DtoMetadata(md, p3d, "polyMD"),
+                "psPolynomial3DtoMetadata:     return true for valid inputs.");
+            psMetadata *polyMDtemp = psMetadataLookupMetadata(NULL, md, "polyMD");
+            skip_start( polyMDtemp == NULL , 1,
+                        "Skipping 1 tests because psPolynomial3DtoMetadata has errors");
+            psMetadataItem *polyItem = psMetadataGet(polyMDtemp, 0);
+            skip_start( polyItem == NULL, 2,
+                        "Skipping 3 tests because psPolynomial3DtoMetadata has errors in order elements");
+            ok( !strncmp(polyItem->name, "NORDER_X", 10) && polyItem->data.S32 == 1,
+                "psPolynomial3DtoMetadata:     return correct number of x orders.");
+            polyItem = psMetadataGet(polyMDtemp, 1);
+            ok( !strncmp(polyItem->name, "NORDER_Y", 10) && polyItem->data.S32 == 1,
+                "psPolynomial3DtoMetadata:     return correct number of y orders.");
+            polyItem = psMetadataGet(polyMDtemp, 2);
+            ok( !strncmp(polyItem->name, "NORDER_Z", 10) && polyItem->data.S32 == 1,
+                "psPolynomial3DtoMetadata:     return correct number of z orders.");
+            skip_end();
+            polyItem = psMetadataGet(polyMDtemp, 3);
+            skip_start( polyItem == NULL, 2,
+                        "Skipping 2 tests because psPolynomial3DtoMetadata has errors in coeff elements");
+            ok( !strncmp(polyItem->name, "VAL_X00_Y00_Z00", 14) &&
+                abs(polyItem->data.F64-1.1) < DBL_EPSILON,
+                "psPolynomial3DtoMetadata:     return correct first element.");
+            polyItem = psMetadataGet(polyMDtemp, PS_LIST_TAIL-1);
+            ok( !strncmp(polyItem->name, "ERR_X01_Y01_Z01", 14) &&
+                abs(polyItem->data.F64-0.8) < DBL_EPSILON,
+                "psPolynomial3DtoMetadata:     return correct last element.");
+            skip_end();
+            skip_end();
+        }
+        //Return false for no-name polynomial
+        {
+            ok( !psPolynomial3DtoMetadata(md, p3d, " "),
+                "psPolynomial3DtoMetadata:     return false for no-name.");
+        }
+        //Return false for NULL-name polynomial
+        {
+            ok( !psPolynomial3DtoMetadata(md, p3d, NULL),
+                "psPolynomial3DtoMetadata:     return false for NULL name input.");
+        }
+        //Return false for NULL metadata input
+        {
+            ok( !psPolynomial3DtoMetadata(NULL, p3d, "polyMD"),
+                "psPolynomial3DtoMetadata:     return false for NULL metadata input.");
+        }
+        //Return false for NULL polynomial input
+        {
+            ok( !psPolynomial3DtoMetadata(md, NULL, "polyMD"),
+                "psPolynomial3DtoMetadata:     return false for NULL polynomial input.");
+        }
+        /*    //Return false for empty polynomial
+            {
+                psPolynomial3D *emptyPoly = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, 0, 0, 0);
+                ok( !psPolynomial3DtoMetadata(md, emptyPoly, "polyMD"),
+                    "psPolynomial3DtoMetadata:     return false for empty polynomial input.");
+                psFree(emptyPoly);
+            }
+        */
+        //Return true for polynomial with 1 element, a constant
+        {
+            psPolynomial3D *constPoly = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, 0, 0, 0);
+            constPoly->coeff[0][0][0] = 6.66;
+            ok( psPolynomial3DtoMetadata(md, constPoly, "polyMD"),
+                "psPolynomial3DtoMetadata:     return true for constant polynomial (1 element != 0).");
+            psFree(constPoly);
+        }
+        //Return false for non-ordinary polynomial
+        {
+            psPolynomial3D *p3d2 = psPolynomial3DAlloc(PS_POLYNOMIAL_CHEB, 1, 1, 1);
+            p3d2->coeff[0][0][0] = 1.1;
+            ok( !psPolynomial3DtoMetadata(md, p3d2, "polyMD"),
+                "psPolynomial3DtoMetadata:     return false for chebyshev polynomial");
+            psFree(p3d2);
+        }
+    
+        //psPolynomial3DfromMetadata Tests
+        //Return NULL for NULL metadata input.
+        {
+            psPolynomial3D *emptyPoly2D = NULL;
+            emptyPoly2D = psPolynomial3DfromMetadata(NULL);
+            ok( emptyPoly2D == NULL,
+                "psPolynomial3DfromMetadata:   return NULL for NULL metadata input.");
+        }
+        //Get a polynomial from Metadata.
+        psPolynomial3D *outPoly = NULL;
+        psMetadata *polyMDtemp = psMetadataLookupMetadata(NULL, md, "polyMD");
+        outPoly = psPolynomial3DfromMetadata(polyMDtemp);
+        {
+            skip_start( outPoly == NULL, 1,
+                        "Skipping 1 tests because psPolynomial3DfromMetadata has errors.");
+            ok( outPoly->type == PS_POLYNOMIAL_ORD && outPoly->nX == 1 &&
+                outPoly->nY == 1 && outPoly->nZ == 1 &&
+                abs(outPoly->coeff[0][0][0] - 1.1) < DBL_EPSILON,
+                "psPolynomial3DfromMetadata:   return correct polynomial from metadata");
+            skip_end();
+        }
+    
+        //Get a polynomial from Metadata with mask[0][0][0] == 1.
+        psFree(outPoly);
+        outPoly = NULL;
+        psPolynomial3D *maskPoly = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, 0, 0, 0);
+        maskPoly->coeff[0][0][0] = 6.66;
+        maskPoly->coeffMask[0][0][0] = 1;
+        psMetadata *newmd = psMetadataAlloc();
+        psPolynomial3DtoMetadata(newmd, maskPoly, "polyMD");
+        psMetadata *polyMask = psMetadataLookupMetadata(NULL, newmd, "polyMD");
+        outPoly = psPolynomial3DfromMetadata(polyMask);
+        {
+            ok( outPoly->type == PS_POLYNOMIAL_ORD && outPoly->nX == 0 && outPoly->nY == 0
+                && outPoly->nZ == 0 && outPoly->coeffMask[0][0][0] == 1,
+                "psPolynomial3DfromMetadata:   return correct polynomial (w/mask) from metadata");
+        }
+        psFree(maskPoly);
+        psFree(newmd);
+        //Return NULL for wrong NELEMENTS
+        psMetadataItem *nElementItem = psMetadataGet(polyMDtemp, PS_LIST_TAIL);
+        nElementItem->data.S32 -= 1;
+        psFree(outPoly);
+        outPoly = NULL;
+        outPoly = psPolynomial3DfromMetadata(polyMDtemp);
+        {
+            ok( outPoly == NULL,
+                "psPolynomial3DfromMetadata:   "
+                "return NULL for metadata-polynomial with wrong NELEMENTS");
+        }
+        //Return NULL for missing NELEMENTS
+        psMetadataRemoveIndex(polyMDtemp, PS_LIST_TAIL);
+        psFree(outPoly);
+        outPoly = NULL;
+        outPoly = psPolynomial3DfromMetadata(polyMDtemp);
+        {
+            ok( outPoly == NULL,
+                "psPolynomial3DfromMetadata:   "
+                "return NULL for metadata-polynomial with no NELEMENTS");
+        }
+    
+        //Return NULL for polynomial in metadata with no z-order
+        psMetadataRemoveKey(polyMDtemp, "NORDER_Z");
+        psFree(outPoly);
+        outPoly = NULL;
+        outPoly = psPolynomial3DfromMetadata(polyMDtemp);
+        {
+            ok( outPoly == NULL,
+                "psPolynomial3DfromMetadata:   return NULL for metadata-polynomial with no z-order");
+        }
+        //Return NULL for polynomial in metadata with no y-order
+        psMetadataRemoveKey(polyMDtemp, "NORDER_Y");
+        psFree(outPoly);
+        outPoly = NULL;
+        outPoly = psPolynomial3DfromMetadata(polyMDtemp);
+        {
+            ok( outPoly == NULL,
+                "psPolynomial3DfromMetadata:   return NULL for metadata-polynomial with no y-order");
+        }
+        //Return NULL for polynomial in metadata with no x-order
+        psMetadataRemoveKey(polyMDtemp, "NORDER_X");
+        psFree(outPoly);
+        outPoly = NULL;
+        outPoly = psPolynomial3DfromMetadata(polyMDtemp);
+        {
+            ok( outPoly == NULL,
+                "psPolynomial3DfromMetadata:   return NULL for metadata-polynomial with no x-order");
+        }
+    
+        psFree(outPoly);
+        psFree(p3d);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psPolynomial4DtoMetadata & psPolynomial4DfromMetadata functions
+    {
+        psMemId id = psMemGetId();
+        psMetadata *md = psMetadataAlloc();
+        psPolynomial4D *p4d = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, 1, 1, 1, 1);
+        p4d->coeff[0][0][0][0] = 1.1;
+        p4d->coeff[0][0][0][1] = 2.2;
+        p4d->coeff[0][0][1][0] = 3.3;
+        p4d->coeff[0][1][0][0] = 4.4;
+        p4d->coeff[1][0][0][0] = 5.5;
+    
+        p4d->coeff[0][0][1][1] = 6.6;
+        p4d->coeff[0][1][0][1] = 7.7;
+        p4d->coeff[1][0][0][1] = 8.8;
+        p4d->coeff[0][1][1][0] = 9.9;
+        p4d->coeff[1][0][1][0] = 10.10;
+        p4d->coeff[1][1][0][0] = 11.11;
+    
+        p4d->coeff[0][1][1][1] = 12.12;
+        p4d->coeff[1][0][1][1] = 13.13;
+        p4d->coeff[1][1][0][1] = 14.14;
+        p4d->coeff[1][1][1][0] = 15.15;
+    
+        p4d->coeff[1][1][1][1] = 16.16;
+    
+        p4d->coeffErr[0][0][0][0] = 0.1;
+        p4d->coeffErr[0][0][0][1] = 0.2;
+        p4d->coeffErr[0][0][1][0] = 0.3;
+        p4d->coeffErr[0][1][0][0] = 0.4;
+        p4d->coeffErr[1][0][0][0] = 0.5;
+    
+        p4d->coeffErr[0][0][1][1] = 0.6;
+        p4d->coeffErr[0][1][0][1] = 0.7;
+        p4d->coeffErr[1][0][0][1] = 0.8;
+        p4d->coeffErr[0][1][1][0] = 0.9;
+        p4d->coeffErr[1][0][1][0] = 0.10;
+        p4d->coeffErr[1][1][0][0] = 0.11;
+    
+        p4d->coeffErr[0][1][1][1] = 0.12;
+        p4d->coeffErr[1][0][1][1] = 0.13;
+        p4d->coeffErr[1][1][0][1] = 0.14;
+        p4d->coeffErr[1][1][1][0] = 0.15;
+    
+        p4d->coeffErr[1][1][1][1] = 0.16;
+    
+        //psPolynomial4DtoMetadata
+        //Return a valid metadata containing a polynomial-metadata structure
+        {
+            ok( psPolynomial4DtoMetadata(md, p4d, "polyMD"),
+                "psPolynomial4DtoMetadata:     return true for valid inputs.");
+            psMetadata *polyMDtemp = psMetadataLookupMetadata(NULL, md, "polyMD");
+            skip_start( polyMDtemp == NULL , 1,
+                        "Skipping 1 tests because psPolynomial4DtoMetadata has errors");
+            psMetadataItem *polyItem = psMetadataGet(polyMDtemp, 0);
+            skip_start( polyItem == NULL, 2,
+                        "Skipping 4 tests because psPolynomial4DtoMetadata has errors in order elements");
+            ok( !strncmp(polyItem->name, "NORDER_X", 10) && polyItem->data.S32 == 1,
+                "psPolynomial4DtoMetadata:     return correct number of x orders.");
+            polyItem = psMetadataGet(polyMDtemp, 1);
+            ok( !strncmp(polyItem->name, "NORDER_Y", 10) && polyItem->data.S32 == 1,
+                "psPolynomial4DtoMetadata:     return correct number of y orders.");
+            polyItem = psMetadataGet(polyMDtemp, 2);
+            ok( !strncmp(polyItem->name, "NORDER_Z", 10) && polyItem->data.S32 == 1,
+                "psPolynomial4DtoMetadata:     return correct number of z orders.");
+            polyItem = psMetadataGet(polyMDtemp, 3);
+            ok( !strncmp(polyItem->name, "NORDER_T", 10) && polyItem->data.S32 == 1,
+                "psPolynomial4DtoMetadata:     return correct number of t orders.");
+            skip_end();
+            polyItem = psMetadataGet(polyMDtemp, 4);
+            skip_start( polyItem == NULL, 2,
+                        "Skipping 2 tests because psPolynomial4DtoMetadata has errors in coeff elements");
+            ok( !strncmp(polyItem->name, "VAL_X00_Y00_Z00_T00", 14) &&
+                abs(polyItem->data.F64-1.1) < DBL_EPSILON,
+                "psPolynomial4DtoMetadata:     return correct first element.");
+            polyItem = psMetadataGet(polyMDtemp, PS_LIST_TAIL-1);
+            ok( !strncmp(polyItem->name, "ERR_X01_Y01_Z01_T01", 14) &&
+                abs(polyItem->data.F64-0.16) < DBL_EPSILON,
+                "psPolynomial4DtoMetadata:     return correct last element.");
+            skip_end();
+            skip_end();
+        }
+        //Return false for no-name polynomial
+        {
+            ok( !psPolynomial4DtoMetadata(md, p4d, " "),
+                "psPolynomial4DtoMetadata:     return false for no-name.");
+        }
+        //Return false for NULL-name polynomial
+        {
+            ok( !psPolynomial4DtoMetadata(md, p4d, NULL),
+                "psPolynomial4DtoMetadata:     return false for NULL name input.");
+        }
+        //Return false for NULL metadata input
+        {
+            ok( !psPolynomial4DtoMetadata(NULL, p4d, "polyMD"),
+                "psPolynomial4DtoMetadata:     return false for NULL metadata input.");
+        }
+        //Return false for NULL polynomial input
+        {
+            ok( !psPolynomial4DtoMetadata(md, NULL, "polyMD"),
+                "psPolynomial4DtoMetadata:     return false for NULL polynomial input.");
+        }
+        /*    //Return false for empty polynomial
+            {
+                psPolynomial4D *emptyPoly = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, 0, 0, 0, 0);
+                ok( !psPolynomial4DtoMetadata(md, emptyPoly, "polyMD"),
+                    "psPolynomial4DtoMetadata:     return false for empty polynomial input.");
+                psFree(emptyPoly);
+            }
+        */
+        //Return true for polynomial with 1 element, a constant
+        {
+            psPolynomial4D *constPoly = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, 0, 0, 0, 0);
+            constPoly->coeff[0][0][0][0] = 6.66;
+            ok( psPolynomial4DtoMetadata(md, constPoly, "polyMD"),
+                "psPolynomial4DtoMetadata:     return true for constant polynomial (1 element != 0).");
+            psFree(constPoly);
+        }
+        //Return false for non-ordinary polynomial
+        {
+            psPolynomial4D *p4d2 = psPolynomial4DAlloc(PS_POLYNOMIAL_CHEB, 1, 1, 1, 1);
+            p4d2->coeff[0][0][0][0] = 1.1;
+            ok( !psPolynomial4DtoMetadata(md, p4d2, "polyMD"),
+                "psPolynomial4DtoMetadata:     return false for chebyshev polynomial");
+            psFree(p4d2);
+        }
+    
+        //psPolynomial4DfromMetadata Tests
+        //Return NULL for NULL metadata input.
+        {
+            psPolynomial4D *emptyPoly2D = NULL;
+            emptyPoly2D = psPolynomial4DfromMetadata(NULL);
+            ok( emptyPoly2D == NULL,
+                "psPolynomial4DfromMetadata:   return NULL for NULL metadata input.");
+        }
+        //Get a polynomial from Metadata.
+        psPolynomial4D *outPoly = NULL;
+        psMetadata *polyMDtemp = psMetadataLookupMetadata(NULL, md, "polyMD");
+        outPoly = psPolynomial4DfromMetadata(polyMDtemp);
+        {
+            skip_start( outPoly == NULL, 1,
+                        "Skipping 1 tests because psPolynomial4DfromMetadata has errors.");
+            ok( outPoly->type == PS_POLYNOMIAL_ORD && outPoly->nX == 1 &&
+                outPoly->nY == 1 && outPoly->nZ == 1 && outPoly->nT == 1 &&
+                abs(outPoly->coeff[0][0][0][0] - 1.1) < DBL_EPSILON,
+                "psPolynomial4DfromMetadata:   return correct polynomial from metadata");
+            skip_end();
+        }
+        //Get a polynomial from Metadata with mask[0][0][0][0] == 1.
+        psFree(outPoly);
+        outPoly = NULL;
+        psPolynomial4D *maskPoly = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, 0, 0, 0, 0);
+        maskPoly->coeff[0][0][0][0] = 6.66;
+        maskPoly->coeffMask[0][0][0][0] = 1;
+        psMetadata *newmd = psMetadataAlloc();
+        psPolynomial4DtoMetadata(newmd, maskPoly, "polyMD");
+        psMetadata *polyMask = psMetadataLookupMetadata(NULL, newmd, "polyMD");
+        outPoly = psPolynomial4DfromMetadata(polyMask);
+        {
+            ok( outPoly->type == PS_POLYNOMIAL_ORD && outPoly->nX == 0 && outPoly->nY == 0
+                && outPoly->nZ == 0 && outPoly->nT == 0 && outPoly->coeffMask[0][0][0][0] == 1,
+                "psPolynomial4DfromMetadata:   return correct polynomial (w/mask) from metadata");
+        }
+        psFree(maskPoly);
+        psFree(newmd);
+        //Return NULL for wrong NELEMENTS
+        psMetadataItem *nElementItem = psMetadataGet(polyMDtemp, PS_LIST_TAIL);
+        nElementItem->data.S32 -= 1;
+        psFree(outPoly);
+        outPoly = NULL;
+        outPoly = psPolynomial4DfromMetadata(polyMDtemp);
+        {
+            ok( outPoly == NULL,
+                "psPolynomial4DfromMetadata:   "
+                "return NULL for metadata-polynomial with wrong NELEMENTS");
+        }
+        //Return NULL for missing NELEMENTS
+        psMetadataRemoveIndex(polyMDtemp, PS_LIST_TAIL);
+        psFree(outPoly);
+        outPoly = NULL;
+        outPoly = psPolynomial4DfromMetadata(polyMDtemp);
+        {
+            ok( outPoly == NULL,
+                "psPolynomial4DfromMetadata:   "
+                "return NULL for metadata-polynomial with no NELEMENTS");
+        }
+    
+        //Return NULL for polynomial in metadata with no t-order
+        psMetadataRemoveKey(polyMDtemp, "NORDER_T");
+        psFree(outPoly);
+        outPoly = NULL;
+        outPoly = psPolynomial4DfromMetadata(polyMDtemp);
+        {
+            ok( outPoly == NULL,
+                "psPolynomial4DfromMetadata:   return NULL for metadata-polynomial with no t-order");
+        }
+        //Return NULL for polynomial in metadata with no z-order
+        psMetadataRemoveKey(polyMDtemp, "NORDER_Z");
+        psFree(outPoly);
+        outPoly = NULL;
+        outPoly = psPolynomial4DfromMetadata(polyMDtemp);
+        {
+            ok( outPoly == NULL,
+                "psPolynomial4DfromMetadata:   return NULL for metadata-polynomial with no z-order");
+        }
+        //Return NULL for polynomial in metadata with no y-order
+        psMetadataRemoveKey(polyMDtemp, "NORDER_Y");
+        psFree(outPoly);
+        outPoly = NULL;
+        outPoly = psPolynomial4DfromMetadata(polyMDtemp);
+        {
+            ok( outPoly == NULL,
+                "psPolynomial4DfromMetadata:   return NULL for metadata-polynomial with no y-order");
+        }
+        //Return NULL for polynomial in metadata with no x-order
+        psMetadataRemoveKey(polyMDtemp, "NORDER_X");
+        psFree(outPoly);
+        outPoly = NULL;
+        outPoly = psPolynomial4DfromMetadata(polyMDtemp);
+        {
+            ok( outPoly == NULL,
+                "psPolynomial4DfromMetadata:   return NULL for metadata-polynomial with no x-order");
+        }
+    
+        psFree(outPoly);
+        psFree(p4d);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
+    
+
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadata_printing.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadata_printing.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psMetadata_printing.c	(revision 22158)
@@ -0,0 +1,388 @@
+/**
+ *  C Implementation: tap_psMetadata_printing
+ *
+ * Description:  Tests for psMetadataPrint and psMetadataItemPrint.
+ *
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <fcntl.h>
+#include <unistd.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+static psMetadata *setupMeta(void)
+{
+    psMetadata *md = NULL;
+    psMetadata *newMD = NULL;
+    int i = 0;
+    md = psMetadataAlloc();
+    newMD = psMetadataAlloc();
+
+    psMetadataAddStr(md, PS_LIST_TAIL, "item5", 0, "I am a string", "GNIRTS");
+    psMetadataAddBool(md, PS_LIST_TAIL, "item1", 0, "I am a boolean", true);
+    psMetadataAddBool(md, PS_LIST_TAIL, "item11", 0, "I am a boolean", false);
+    psMetadataAddS8(md, PS_LIST_TAIL, "item6", 0, "I am S8", 6);
+    psMetadataAddS16(md, PS_LIST_TAIL, "item7", 0, "I am S16", -666);
+    psMetadataAddS32(md, PS_LIST_TAIL, "item2", 0, "I am a integer", 55);
+    psMetadataAddS64(md, PS_LIST_TAIL, "helloS64", 0, "I am S64", 666);
+    psMetadataAddU8(md, PS_LIST_TAIL, "item8", 0, "I am U8", 6);
+    psMetadataAddU16(md, PS_LIST_TAIL, "item9", 0, "I am U16", 666);
+    psMetadataAddU32(md, PS_LIST_TAIL, "item10", 0, "I am U32", 666);
+    psMetadataAddU64(md, PS_LIST_TAIL, "item12", 0, "I am U64", 666);
+    psMetadataAddF32(md, PS_LIST_TAIL, "item3", 0, NULL, 3.14);
+    psMetadataAddF64(md, PS_LIST_TAIL, "item4", 0, "", 6.28);
+
+    psMetadataAddS32(newMD, PS_LIST_TAIL, "ITEM01", 0, NULL, 666);
+    psMetadata *newestMD = NULL;
+    newestMD = psMetadataAlloc();
+    psVector *vec = NULL;
+    vec = psVectorAlloc(60, PS_DATA_S32);
+    for (i = 0; i < 5; i++) {
+        vec->data.S32[i] = i+1;
+    }
+    vec->n = 5;
+    psMetadataAddVector(newestMD, PS_LIST_TAIL, "VECTORNEW", 0, "Newest VECTOR", vec);
+    psMetadataAddStr(newestMD, PS_LIST_TAIL, "cell", 0, "I am a p-Star string", "pStArRs");
+    psMetadataAddMetadata(newMD, PS_LIST_TAIL, "META NEW", 0, "I AM Newest METADATA", newestMD);
+    psMetadataAddF32(newMD, PS_LIST_TAIL, "ITEM02", 0, "I AM FLOAT", 666.6);
+    psMetadataAddF64(newMD, PS_LIST_TAIL, "ITEM03", 0, "I AM DOUBLE", 666.666);
+    psMetadataAddS64(newMD, PS_LIST_TAIL, "item666", 0, "I am S64", 666);
+
+    psMetadataAddMetadata(md, PS_LIST_TAIL, "metadata7", 0, "I am a metadata", newMD);
+    psRegion *region = psRegionAlloc(0.0, 2.0, 0.0, 2.0);
+    psMetadataAddPtr(md, PS_LIST_TAIL, "region", PS_DATA_REGION, "I am a region", region);
+    psList *list = psListAlloc(NULL);
+    psMetadataAddList(md, PS_LIST_TAIL, "list01", 0, "I am a list", list);
+
+    psTime *time;
+    time = psTimeAlloc(PS_TIME_TAI);
+    time->sec = 1000;
+    time->nsec = 25;
+    time->leapsecond = true;
+    psMetadataAddTime(md, PS_LIST_TAIL, "time01", 0, "I am time", time);
+
+    psMetadataAddVector(md, PS_LIST_TAIL, "vector6", 0, "I am a vector", vec);
+    psFree(vec);
+    vec = psVectorAlloc(2, PS_DATA_U8);
+    vec->n = 2;
+    for (i = 0; i < 2; i++) {
+        vec->data.U8[i] = i+1;
+    }
+    psMetadataAddVector(md, PS_LIST_TAIL, "vector7", 0, "I am a U8-vector", vec);
+    psFree(vec);
+    vec = psVectorAlloc(2, PS_DATA_U16);
+    vec->n = 2;
+    for (i = 0; i < 2; i++) {
+        vec->data.U16[i] = i+1;
+    }
+    psMetadataAddVector(md, PS_LIST_TAIL, "vector8", 0, "I am a U16-vector", vec);
+    psFree(vec);
+    vec = psVectorAlloc(2, PS_DATA_U32);
+    vec->n = 2;
+    for (i = 0; i < 2; i++) {
+        vec->data.U32[i] = i+1;
+    }
+    psMetadataAddVector(md, PS_LIST_TAIL, "vector9", 0, "I am a U32-vector", vec);
+    psFree(vec);
+    vec = psVectorAlloc(2, PS_DATA_U64);
+    vec->n = 2;
+    for (i = 0; i < 2; i++) {
+        vec->data.U64[i] = i+1;
+    }
+    psMetadataAddVector(md, PS_LIST_TAIL, "vector10", 0, "I am a U64-vector", vec);
+    psFree(vec);
+    vec = psVectorAlloc(2, PS_DATA_S8);
+    vec->n = 2;
+    for (i = 0; i < 2; i++) {
+        vec->data.S8[i] = i+1;
+    }
+    psMetadataAddVector(md, PS_LIST_TAIL, "vector11", 0, "I am a S8-vector", vec);
+    psFree(vec);
+    vec = psVectorAlloc(2, PS_DATA_S16);
+    vec->n = 2;
+    for (i = 0; i < 2; i++) {
+        vec->data.S16[i] = i+1;
+    }
+    psMetadataAddVector(md, PS_LIST_TAIL, "vector12", 0, "I am a S16-vector", vec);
+    psFree(vec);
+    vec = psVectorAlloc(2, PS_DATA_S64);
+    vec->n = 2;
+    for (i = 0; i < 2; i++) {
+        vec->data.S64[i] = i+1;
+    }
+    psMetadataAddVector(md, PS_LIST_TAIL, "vector13", 0, "I am a S64-vector", vec);
+    psFree(vec);
+    vec = psVectorAlloc(2, PS_DATA_F32);
+    vec->n = 2;
+    for (i = 0; i < 2; i++) {
+        vec->data.F32[i] = i+1;
+    }
+    psMetadataAddVector(md, PS_LIST_TAIL, "vector14", 0, "I am a F32-vector", vec);
+    psFree(vec);
+    vec = psVectorAlloc(2, PS_DATA_F64);
+    vec->n = 2;
+    for (i = 0; i < 2; i++) {
+        vec->data.F64[i] = i+1;
+    }
+    psMetadataAddVector(md, PS_LIST_TAIL, "vector15", 0, "I am a F64-vector", vec);
+
+    /*    psImage *image = psImageAlloc(1, 1, PS_TYPE_S32);
+        psImageSet(image, 0, 0, 1);
+        psMetadataAddImage(md, PS_LIST_TAIL, "image1", 0, "I am an Image", image);
+
+        psHash *hash = psHashAlloc(1);
+        psHashAdd(hash, "hash", image);
+        psMetadataAddHash(md, PS_LIST_TAIL, "hash1", 0, "I am a Hash", hash);
+
+        psLookupTable *lookup = psLookupTableAlloc("table2.dat", "%s", 0);
+        psMetadataAddLookupTable(md, PS_LIST_TAIL, "lookup", 0, "I am a LookupTable", lookup);
+
+        psArray *array = psArrayAlloc(1);
+        psArraySet(array, 0, image);
+        psMetadataAddArray(md, PS_LIST_TAIL, "array", 0, "I am an Array", array);
+
+        psFree(array);
+        psFree(lookup);
+        psFree(image);
+        psFree(hash);
+    */
+    psFree(region);
+    psFree(list);
+    psFree(time);
+    psFree(newestMD);
+    psFree(vec);
+    psFree(newMD);
+    return md;
+}
+
+
+int main(void)
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(30);
+
+
+    // psMetadataPrint
+    {
+        psMemId id = psMemGetId();
+        FILE *fd = fopen("psMetadataPrint.out", "w+");
+        FILE *fd_read = fopen("Makefile", "r");
+        psMetadata *md = NULL;
+        psMetadata *md2 = NULL;
+        md = setupMeta();
+        md2 = psMetadataAlloc();
+        psSphere *sphere = psSphereAlloc();
+        psMetadataAddPtr(md2, PS_LIST_HEAD, "ptr", PS_DATA_SPHERE, "", sphere);
+        psMetadataAddUnknown(md2, PS_LIST_TAIL, "unknown", 0, "", sphere);
+    
+        psImage *image = psImageAlloc(1, 1, PS_TYPE_S32);
+        psImageSet(image, 0, 0, 1);
+        psMetadataAddImage(md2, PS_LIST_TAIL, "image1", 0, "I am an Image", image);
+    
+        psHash *hash = psHashAlloc(1);
+        psHashAdd(hash, "hash", image);
+        psMetadataAddHash(md2, PS_LIST_TAIL, "hash1", 0, "I am a Hash", hash);
+    
+        psLookupTable *lookup = psLookupTableAlloc("table2.dat", "%s", 0);
+        psMetadataAddLookupTable(md2, PS_LIST_TAIL, "lookup", 0, "I am a LookupTable", lookup);
+    
+        psArray *array = psArrayAlloc(1);
+        psArraySet(array, 0, image);
+        psMetadataAddArray(md2, PS_LIST_TAIL, "array", 0, "I am an Array", array);
+    
+        psFree(array);
+        psFree(lookup);
+        psFree(image);
+        psFree(hash);
+    
+        //Return false for NULL psMetadata input
+        {
+            ok( !psMetadataPrint(NULL, NULL, 0),
+                "psMetadataPrint:            return false for NULL psMetadata input.");
+        }
+        //Return false for read-only file descriptor
+        {
+            ok ( !psMetadataPrint(fd_read, md, 0),
+                 "psMetadataPrint:            return false for read-only file descriptor.");
+        }
+        fclose(fd_read);
+        //Error and then return true for unprintable datatype (sphere) and DATA_UNKNOWN
+        {
+            ok ( !psMetadataPrint(NULL, md2, 0),
+                 "psMetadataPrint:            return false for metadata with unknown datatype.");
+        }
+        psFree(md2);
+    
+        //Valid case where fd is NULL -> stdout
+        md2 = psMetadataAlloc();
+        psMetadataAddStr(md2, PS_LIST_HEAD,
+                         "  >>Hello Wally", 0, "My name is Bubbles", "Pet Me");
+        {
+            ok ( psMetadataPrint(NULL, md2, 0),
+                 "psMetadataPrint:            return true for NULL file pointer.");
+        }
+        psFree(md2);
+        //Valid case where fd is "psMetadataPrint.out"
+        {
+            ok ( psMetadataPrint(fd, md, 0),
+                 "psMetadataPrint:            return true for file='psMetadataPrint.out'.");
+        }
+    
+        //Check for Memory Leaks before exit
+        fclose(fd);
+        remove("psMetadataPrint.out");
+        psFree(sphere);
+        psFree(md);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psMetadataItemPrint
+    {
+        psMemId id = psMemGetId();
+        FILE *fd;
+        fd = fopen("psMetadataItemPrint.out", "w");
+        psMetadataItem *item1 = psMetadataItemAlloc("bool", PS_DATA_BOOL, "No Comment", true);
+        psMetadataItem *item2 = psMetadataItemAlloc("f32", PS_DATA_F32, "No Comment", 0.66601);
+        psMetadataItem *item3 = psMetadataItemAlloc("string", PS_DATA_STRING, "", "Can't touch this");
+        psMetadataItem *item4 = psMetadataItemAlloc("U16", PS_DATA_U16, "", 1);
+        psMetadataItem *item5 = psMetadataItemAlloc("string", PS_DATA_U8, "", "a");
+    
+        //Return false for NULL file-pointer
+        {
+            ok( !psMetadataItemPrint(NULL, "%s", item1),
+                "psMetadataItemPrint:        return false for NULL FILE*.");
+        }
+        //Return false for NULL format paramter
+        {
+            ok( !psMetadataItemPrint(fd, NULL, item1),
+                "psMetadataItemPrint:        return false for NULL format.");
+        }
+        //Return false for NULL metadataItem
+        {
+            ok( !psMetadataItemPrint(fd, "%s", NULL),
+                "psMetadataItemPrint:        return false for NULL psMetadataItem.");
+        }
+        //Return false for incorrect format parameter
+        {
+            ok( !psMetadataItemPrint(fd, "sos \n", item1),
+                "psMetadataItemPrint:       return false for incorrect format.");
+        }
+        //Return false for type that doesn't match format (ie, %s for f32 value)
+        {
+            ok( !psMetadataItemPrint(fd, "%s", item2),
+                "psMetadataItemPrint:       return false for item that doesn't match format.");
+        }
+    
+        //Return false for incorrect format parameter
+        {
+            ok( !psMetadataItemPrint(fd, "%z", item1),
+                "psMetadataItemPrint:       return false for incorrect format.");
+        }
+    
+    
+        //Return true for format parameter containing additional modifiers (F32)
+        {
+            ok( psMetadataItemPrint(fd, "%.3f\n", item2),
+                "psMetadataItemPrint:       return true for format with .3 modifier.");
+        }
+        //Return true for valid string input
+        {
+            ok( psMetadataItemPrint(fd, "%s\n", item3),
+                "psMetadataItemPrint:       return true for valid string case w/s.");
+        }
+        //Return true for valid ptr input
+        {
+            ok( psMetadataItemPrint(fd, "%p\n", item3),
+                "psMetadataItemPrint:       return true for valid ptr case w/p.");
+        }
+    
+        //Return true for format = %d, type = int
+        {
+            ok( psMetadataItemPrint(fd, "%d\n", item4),
+                "psMetadataItemPrint:       return true for valid case w/d.");
+        }
+        //Return true for format = %i, type = int
+        {
+            ok( psMetadataItemPrint(fd, "%i\n", item4),
+                "psMetadataItemPrint:       return true for valid case w/i.");
+        }
+        //Return true for format = %c, type = int
+        {
+            ok( psMetadataItemPrint(fd, "%c\n", item5),
+                "psMetadataItemPrint:       return true for valid case w/c.");
+        }
+        //Return true for format = %o, type = int
+        {
+            ok( psMetadataItemPrint(fd, "%o\n", item4),
+                "psMetadataItemPrint:       return true for valid case w/d.");
+        }
+        //Return true for format = %u, type = int
+        {
+            ok( psMetadataItemPrint(fd, "%u\n", item4),
+                "psMetadataItemPrint:       return true for valid case w/i.");
+        }
+        //Return true for format = %x, type = int
+        {
+            ok( psMetadataItemPrint(fd, "%x\n", item5),
+                "psMetadataItemPrint:       return true for valid case w/c.");
+        }
+        //Return true for format = %X, type = int
+        {
+            ok( psMetadataItemPrint(fd, "%X\n", item5),
+                "psMetadataItemPrint:       return true for valid case w/c.");
+        }
+    
+        //Return true for format = %e, type = int
+        {
+            ok( psMetadataItemPrint(fd, "%.1e\n", item2),
+                "psMetadataItemPrint:       return true for valid case w/e.");
+        }
+        //Return true for format = %E, type = int
+        {
+            ok( psMetadataItemPrint(fd, "%.2E\n", item2),
+                "psMetadataItemPrint:       return true for valid case w/E.");
+        }
+        //Return true for format = %F, type = int
+        {
+            ok( psMetadataItemPrint(fd, "%.3F\n", item2),
+                "psMetadataItemPrint:       return true for valid case w/F.");
+        }
+        //Return true for format = %g, type = int
+        {
+            ok( psMetadataItemPrint(fd, "%.3g\n", item2),
+                "psMetadataItemPrint:       return true for valid case w/g.");
+        }
+        //Return true for format = %G, type = int
+        {
+            ok( psMetadataItemPrint(fd, "%.4G\n", item2),
+                "psMetadataItemPrint:       return true for valid case w/G.");
+        }
+        //Return true for format = %a, type = int
+        {
+            ok( psMetadataItemPrint(fd, "%.4a\n", item2),
+                "psMetadataItemPrint:       return true for valid case w/a.");
+        }
+        //Return true for format = %A, type = int
+        {
+            ok( psMetadataItemPrint(fd, "%A\n", item2),
+                "psMetadataItemPrint:       return true for valid case w/A.");
+        }
+    
+        fclose(fd);
+        unlink ("psMetadataItemPrint.out");
+        psFree(item1);
+        psFree(item2);
+        psFree(item3);
+        psFree(item4);
+        psFree(item5);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psPixels_all.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psPixels_all.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psPixels_all.c	(revision 22158)
@@ -0,0 +1,394 @@
+/**
+ *  C Implementation: tap_psPixels_all
+ *
+ * Description:  Tests for psPixelsAlloc, psPixelsRealloc, psMemCheckPixels,
+ *               psPixelsCopy, psPixels(To/From)Mask, p_psPixelsAdd, psPixelsLength,
+ *               psPixels(Set/Get), psPixelsConcatenate
+ *
+ *
+ * Author: dRob <David.Robbins@mhpcc.hpc.mil>, (C) 2006
+ *
+ * Copyright: See COPYING file that comes with this distribution
+ *
+ */
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+void testPixelsCreate(void);
+void testPixelsManip(void);
+
+int main(void)
+{
+    plan_tests(48);
+
+    //Tests for psPixels Functions
+    testPixelsCreate();
+    testPixelsManip();
+
+    done();
+}
+
+void testPixelsCreate(void)
+{
+    //Test 1:  psPixels Creation Fxns
+    //Return allocated psPixels of length 0 with NULL data.
+    psPixels* p0 = psPixelsAlloc(0);
+    {
+        ok(p0 != NULL && p0->n == 0 && p0->nalloc == 0,
+           "psPixelsAlloc:         return newly allocated psPixels of 0 length.");
+    }
+    //Return properly allocated psPixels
+    psPixels* p1 = psPixelsAlloc(1);
+    {
+        ok(p1 != NULL && p1->n == 1 && p1->data != NULL && p1->nalloc == 1,
+           "psPixelsAlloc:         return newly allocated psPixels of 1 length.");
+    }
+    //Make sure psMemCheckPixels works correctly - return true
+    {
+        ok(psMemCheckPixels(p1),
+            "psMemCheckPixels:      return true for psPixels input.");
+    }
+    //Make sure psMemCheckPixels works correctly - return false
+    // XXX EAM : disabled -- failing test causes segfault  
+    if (0) {
+        int j = 2;
+        ok(!psMemCheckPixels(&j),
+            "psMemCheckPixels:      return false for non-psPixels input.");
+    }
+    //Return a 0-length allocated psPixels on Realloc with 0
+    {
+        psPixels *noPix = psPixelsAlloc(1);
+        noPix = psPixelsRealloc(noPix, 0);
+        ok(noPix->n == 0 && noPix->nalloc == 0,
+            "psPixelsRealloc:       return re-allocated psPixels of 0 length.");
+        psFree(noPix);
+    }
+    //Return a properly down-sized psPixels.
+    p0 = psPixelsAdd(p0, 1, 1.1, 1.2);
+    p0 = psPixelsAdd(p0, 1, 2.1, 2.2);
+    p0 = psPixelsAdd(p0, 1, 3.1, 3.2);
+    p0 = psPixelsAdd(p0, 0, 4.1, 4.2);
+    {
+        skip_start(  psPixelsLength(p0) != 4, 1,
+                     "Skipping 1 tests because psPixels input is of wrong size! =%ld", p0->n);
+        p0 = psPixelsRealloc(p0, 2);
+        ok(p0->n == 2 && fabs(p0->data[0].x - 1.1) < FLT_EPSILON && p0->nalloc == 2,
+            "psPixelsRealloc:       return properly down-sized psPixels.");
+        skip_end();
+    }
+    //Now see if we can create a valid psPixels copy of p0
+    {
+        psPixels *noPix = NULL;
+        noPix = psPixelsCopy(noPix, p0);
+        ok(noPix->n == 2 && fabs(noPix->data[0].x - 1.1) < FLT_EPSILON && noPix->nalloc == 2,
+            "psPixelsCopy:          return properly copied psPixels.");
+        psFree(noPix);
+    }
+    //Return NULL for attempting to create a psPixels copy of NULL input.
+    {
+        psPixels *noPix = NULL;
+        noPix = psPixelsCopy(noPix, NULL);
+        ok(noPix == NULL,
+            "psPixelsCopy:          return NULL for NULL psPixels input.");
+    }
+
+    //Check for Memory leaks
+    {
+        psFree(p1);
+        psFree(p0);
+        checkMem();
+    }
+}
+
+void testPixelsManip(void)
+{
+    //psPixels Manipulation Fxns
+    //Tests for psPixelsSet
+    psPixels *p0 = psPixelsAlloc(1);
+    psPixelCoord in;
+    in.x = 1.1;
+    in.y = 1.2;
+    //Return false for NULL pixels input
+    {
+        ok(!psPixelsSet(NULL, 0, in),
+            "psPixelsSet:          return false for NULL pixels input.");
+    }
+    //Return true for valid inputs
+    {
+        ok(psPixelsSet(p0, 0, in),
+            "psPixelsSet:          return true for valid inputs.");
+    }
+    //Return false for position == nalloc
+    {
+        ok(!psPixelsSet(p0, 1, in),
+            "psPixelsSet:          return false for position == nalloc.");
+    }
+    //Return false for out-of-range position
+    {
+        ok(!psPixelsSet(p0, 2, in),
+            "psPixelsSet:          return false for out-of-range position.");
+    }
+    //Return false for negative out-of-range position
+    {
+        ok(!psPixelsSet(p0, -2, in),
+            "psPixelsSet:          return false for negative out-of-range position.");
+    }
+    //Return true for valid negative position
+    {
+        ok(psPixelsSet(p0, -1, in),
+            "psPixelsSet:          return true for valid negative position.");
+    }
+
+    //Tests for psPixelsGet
+    psPixelCoord out;
+    //Return NAN's for NULL pixels input
+    {
+        out = psPixelsGet(NULL, 1);
+        ok(isnan(out.x) &&  isnan(out.y),
+            "psPixelsGet:          return NANs for NULL pixels input.");
+    }
+    //Return NAN's for out-of-range position
+    {
+        out = psPixelsGet(p0, 2);
+        ok(isnan(out.x) &&  isnan(out.y),
+            "psPixelsGet:          return NANs for out-of-range position.");
+    }
+    //Return NAN's for out-of-range negative position
+    {
+        out = psPixelsGet(p0, -2);
+        ok(isnan(out.x) &&  isnan(out.y),
+            "psPixelsGet:          return NANs for out-of-range negative position.");
+    }
+    //Return true for valid inputs
+    {
+        out = psPixelsGet(p0, 0);
+        ok(fabs(out.x - 1.1) < FLT_EPSILON &&  fabs(out.y - 1.2) < FLT_EPSILON,
+            "psPixelsGet:          return correct values for valid inputs.");
+    }
+    //Return true for valid negative position
+    {
+        out = psPixelsGet(p0, -1);
+        ok(fabs(out.x - 1.1) < FLT_EPSILON &&  fabs(out.y - 1.2) < FLT_EPSILON,
+            "psPixelsGet:          return correct values for valid negative position.");
+    }
+
+    //p_psPixelsPrint Tests
+    //Return true for valid inputs
+    {
+        FILE *newFD = fopen("psPixels.out", "w+");
+        ok(p_psPixelsPrint(newFD, p0, "PS-PIXELS"),
+             "p_psPixelsPrint:      return true for valid input.");
+        fflush(NULL);
+        fclose(newFD);
+    }
+    //Return false for invalid file
+    {
+        FILE *dummy = fopen("psPixels.out", "r");
+        ok(!p_psPixelsPrint(dummy, p0, "failed test"),
+             "p_psPixelsPrint:      return false for invalid file input.");
+        fclose(dummy);
+        remove
+            ("psPixels.out");
+    }
+    //Return false for NULL pixels and name inputs
+    {
+        ok(!p_psPixelsPrint(stdout, NULL, NULL),
+             "p_psPixelsPrint:      return false for NULL pixels and name inputs.");
+    }
+    //Return true for empty pixel data.
+    psPixels *p1 = psPixelsAlloc(0);
+    {
+        ok(p_psPixelsPrint(NULL, p1, "noPix"),
+             "p_psPixelsPrint:      return true for NULL file and empty pixel data inputs.");
+    }
+
+
+    //----------------------------------------------------------------------
+    //psPixelsToMask Tests
+    psImage *outImage = NULL;
+    psRegion region;
+    region.x0 = 1.0;
+    region.x1 = -2.0;
+    region.y0 = 1.0;
+    region.y1 = 5.0;
+    psMaskType maskVal = 1;
+    //Return NULL for NULL pixels input
+    {
+        psMemId id = psMemGetId();
+        outImage = psPixelsToMask(outImage, NULL, region, maskVal);
+        ok(outImage == NULL, "psPixelsToMask: return NULL for NULL pixels input.");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for empty pixel data
+    {
+        psMemId id = psMemGetId();
+        outImage = psPixelsToMask(outImage, p1, region, maskVal);
+        ok(outImage == NULL, "psPixelsToMask: return NULL for NULL pixels data input.");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for bad region input - negative value
+    {
+        psMemId id = psMemGetId();
+        outImage = psPixelsToMask(outImage, p0, region, maskVal);
+        ok(outImage == NULL, "psPixelsToMask: return NULL for negative value in region.");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for bad region input - upper bound less than lower bound
+    region.x0 = 3.0;
+    region.x1 = 1.0;
+    {
+        psMemId id = psMemGetId();
+        outImage = psPixelsToMask(outImage, p0, region, maskVal);
+        ok(outImage == NULL, "psPixelsToMask: return NULL for bad region input.");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return NULL for un-recyclable image - out->type.dimen != PS_DIMEN_IMAGE
+    region.x0 = 1.0;
+    region.x1 = 3.0;
+    outImage = psImageAlloc(1, 1, PS_TYPE_S32);
+    *(psDimen*)&(outImage->type.dimen) = PS_DIMEN_OTHER;
+    {
+        psMemId id = psMemGetId();
+        outImage = psPixelsToMask(outImage, p0, region, maskVal);
+        ok(outImage == NULL, "psPixelsToMask: return NULL for bad image input.");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return valid image for valid inputs
+    //XXX: Musr check pixel values
+    p0 = psPixelsAdd(p0, 1, 2.1, 2.2);
+    p0 = psPixelsAdd(p0, 1, 3.1, 3.2);
+    p0 = psPixelsAdd(p0, 1, 1.0, 1.0);
+    {
+        psMemId id = psMemGetId();
+        outImage = psPixelsToMask(outImage, p0, region, maskVal);
+        ok(outImage != NULL, "psPixelsToMask: return valid image for valid input.");
+        psFree(outImage);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //----------------------------------------------------------------------
+    //psPixelsFromMask Tests
+    outImage = psImageAlloc(31, 99, PS_TYPE_MASK);
+    for (int i = 0; i < outImage->numCols; i++) {
+        for (int j = 0; j < outImage->numRows; j++) {
+            outImage->data.PS_TYPE_MASK_DATA[i][j] = 1;
+        }
+    }
+    //Return valid psPixels for valid inputs
+    //XXX: We never check output psPixels
+    {
+        psMemId id = psMemGetId();
+        psPixels *outPixels = NULL;
+        outPixels = psPixelsFromMask(outPixels, outImage, maskVal);
+        ok(outPixels != NULL, "psPixelsFromMask: return valid pixels for valid input.");
+        psFree(outPixels);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return NULL for NULL image input
+    {
+        psMemId id = psMemGetId();
+        psPixels *outPixels = NULL;
+        outPixels = psPixelsFromMask(outPixels, NULL, maskVal);
+        ok(outPixels == NULL, "psPixelsFromMask: return NULL for NULL image input.");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Return NULL for image with wrong maskType
+    {
+        *(psElemType*)&(outImage->type.type) = PS_TYPE_U32;
+        psMemId id = psMemGetId();
+        psPixels *outPixels = NULL;
+        outPixels = psPixelsFromMask(outPixels, outImage, maskVal);
+        ok(outPixels == NULL, "psPixelsFromMask: return NULL for image with wrong maskType.");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    //----------------------------------------------------------------------
+    // psPixelsConcatenate Tests
+    // Return NULL for NULL pixels input
+    {
+        psMemId id = psMemGetId();
+        psPixels *outPixels = NULL;
+        outPixels = psPixelsConcatenate(outPixels, NULL);
+        ok(outPixels == NULL, "psPixelsConcatenate: return NULL for NULL pixels input.");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Return copy of input pixels for NULL out pixels
+    {
+        psMemId id = psMemGetId();
+        psPixels *outPixels = NULL;
+        outPixels = psPixelsFromMask(outPixels, outImage, maskVal);
+        outPixels = psPixelsConcatenate(outPixels, p0);
+        ok(outPixels->n == 4 && fabs(outPixels->data[0].x - 1.1) < FLT_EPSILON &&
+           fabs(outPixels->data[0].y - 1.2) < FLT_EPSILON ,
+          "psPixelsConcatenate:  return copy of input pixels for NULL out input.");
+        psFree(outPixels);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //test psPixelsConcatenate()
+    //Return properly concatenated psPixels list
+    {
+        psMemId id = psMemGetId();
+        psPixels *outPixels = psPixelsAlloc(5);
+        in.x = 1.0;
+        in.y = 1.0;
+        psPixelsSet(outPixels, 0, in);  //1, 1
+        psPixelsSet(outPixels, 1, in);  //1, 1
+        in.y = 2.0;
+        psPixelsSet(outPixels, 2, in);  //1, 2
+        in.y = 1.0;
+        psPixelsSet(outPixels, 3, in);  //1, 1
+        in.x = 2.0;
+        psPixelsSet(outPixels, 4, in);  //2, 1
+        psPixels *testPixels = psPixelsAlloc(6);
+        in.x = 1.0;
+        in.y = 1.0;
+        psPixelsSet(testPixels, 0, in);  //1, 1
+        in.y = 2.0;
+        psPixelsSet(testPixels, 1, in);  //1, 2
+        in.y = 1.0;
+        psPixelsSet(testPixels, 2, in);  //1, 1
+        in.x = 2.0;
+        psPixelsSet(testPixels, 3, in);  //2, 1
+        in.x = 1.0;
+        psPixelsSet(testPixels, 4, in);  //1, 1
+        in.x = 5.0;
+        in.y = 3.0;
+        psPixelsSet(testPixels, 5, in);  //5, 3
+        outPixels = psPixelsConcatenate(outPixels, testPixels);
+        ok(outPixels->n == 6, "psPixelsConcatenate:  return properly concatenate pixel list for valid inputs.");
+        psFree(testPixels);
+        psFree(outPixels);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Check for Memory leaks
+    //XXX: Remove this, add memory checks to individual blocks
+    {
+        psFree(outImage);
+        psFree(p1);
+        psFree(p0);
+        checkMem();
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psTree.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psTree.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tap_psTree.c	(revision 22158)
@@ -0,0 +1,72 @@
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define NUM 10000                       // Number of points
+
+int main(int argc, char *argv[])
+{
+    psLibInit(NULL);
+    plan_tests(6);
+
+    {
+        psMemId id = psMemGetId();
+
+        psVector *x = psVectorAlloc(NUM, PS_TYPE_F64);
+        psVector *y = psVectorAlloc(NUM, PS_TYPE_F64);
+
+        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+        for (int i = 0; i < NUM; i++) {
+            x->data.F64[i] = 2.0 * psRandomUniform(rng) - 1.0;
+            y->data.F64[i] = 2.0 * psRandomUniform(rng) - 1.0;
+        }
+        psFree(rng);
+
+        psTree *tree = psTreePlant(2, 2, x, y);
+
+        ok(tree, "Tree planted");
+        skip_start(!tree, 4, "tree died");
+        {
+            //            psTreePrint(stderr, tree);
+
+            psVector *coords = psVectorAlloc(2, PS_TYPE_F64);
+            psVectorInit(coords, 0);
+
+            long closeIndex = psTreeNearest(tree, coords);
+            psFree(coords);
+            ok(closeIndex >= 0 && closeIndex < tree->numNodes, "found point: %ld", closeIndex);
+
+            long bestIndex = -1;
+            double bestDist = INFINITY;
+            for (int i = 0; i < NUM; i++) {
+                double dist = PS_SQR(x->data.F64[i]) + PS_SQR(y->data.F64[i]);
+                if (dist < bestDist) {
+                    bestIndex = i;
+                    bestDist = dist;
+                }
+            }
+            ok(bestIndex == closeIndex, "correct point: %ld vs %ld", closeIndex, bestIndex);
+
+            psVector *closest = psTreeCoords(NULL, tree, closeIndex);
+            ok(closest, "got coords: %lf,%lf", closest->data.F64[0], closest->data.F64[1]);
+            ok(closest->data.F64[0] == x->data.F64[bestIndex] &&
+               closest->data.F64[1] == y->data.F64[bestIndex],
+               "correst coords: %lf,%lf(%lf) vs %lf,%lf(%lf)",
+               closest->data.F64[0], closest->data.F64[1],
+               sqrt(PS_SQR(closest->data.F64[0]) + PS_SQR(closest->data.F64[1])),
+               x->data.F64[bestIndex], y->data.F64[bestIndex],
+               sqrt(PS_SQR(x->data.F64[bestIndex]) + PS_SQR(y->data.F64[bestIndex])));
+            psFree(closest);
+        }
+        skip_end();
+
+        psFree(tree);
+        psFree(x);
+        psFree(y);
+
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    psLibFinalize();
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psArguments.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psArguments.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psArguments.c	(revision 22158)
@@ -0,0 +1,81 @@
+/** @file  tst_psArguments.c
+*
+*  @brief Test driver for psArguments functions
+*
+*  @author  David Robbins, MHPCC
+*
+*  @version $Revision: 1.4 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2006-09-13 02:20:15 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib.h"
+
+static psS32 testArgument(void);
+/*
+testDescription tests[] = {
+                              {testArgument, 666, "Test psArgument fxns", 0, false},
+                              {NULL}
+                          };
+*/
+int main(int argc, char* argv[])
+{
+    psLogSetLevel( PS_LOG_INFO );
+    testArgument();
+    //    if( !runTestSuite(stderr,"psArguments",tests,argc,argv)) {
+    //        return 1;
+    //    }
+    return 0;
+}
+
+psS32 testArgument(void)
+{
+    char *argv[6];
+    argv[0] = "./program";
+    argv[1] = "-string";
+    argv[2] = "new";
+    argv[3] = "-float";
+    argv[4] = "6.66";
+    argv[5] = "-vvv";
+    int argc = 6;
+
+    int i = psArgumentGet(argc, argv, "-float");
+    if ( i != 0 ) {
+        if ( !psArgumentRemove(i, &argc, argv) ) {
+            printf("\n Failed to remove float from argument list\n");
+        }
+    } else {
+        printf("\nFailed to find string in argument list\n");
+        return 1;
+    }
+    psArgumentRemove(i, &argc, argv);
+    printf("\n Argument %d has been removed", i);
+    int log = psArgumentVerbosity(&argc, argv);
+    printf("\nLog level = %d \n", log);
+
+    psMetadata *args = psMetadataAlloc();
+    psMetadataAdd(args, PS_LIST_TAIL, "-string", PS_DATA_STRING, "Test String", "SomeString");
+    psMetadataAdd(args, PS_LIST_TAIL, "-float", PS_DATA_F32, "Test Float", 0.0);
+    psMetadata *ints = psMetadataAlloc();
+    psMetadataAdd(ints, PS_LIST_TAIL, "int1", PS_DATA_S32, "Int1", 1);
+    psMetadataAdd(ints, PS_LIST_TAIL, "int2", PS_DATA_S32, "Int2", 2);
+    psMetadataAdd(args, PS_LIST_TAIL, "-int", PS_DATA_METADATA, "Integers", ints);
+    psFree(ints);                       // Drop reference
+
+    printf("\nThis Should print the Argument Help list.\n\n");
+    psArgumentHelp(args);
+
+    if ( !psArgumentParse(args, &argc, argv) || argc != 1 ) {
+        psArgumentHelp(args);
+        psFree(args);
+        return 2;
+    }
+
+    psMetadataPrint(NULL, args, 4);
+
+    psFree(args);
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psArray.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psArray.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psArray.c	(revision 22158)
@@ -0,0 +1,533 @@
+/** @file  tst_psArray.c
+ *
+ *  @brief Test driver for psArray integer functions
+ *
+ *  This test driver contains the following tests for psArray test point 1:
+ *     A)  Create void pointer array
+ *     B)  Add data to void pointer array
+ *     C)  Reallocate void pointer array bigger
+ *     D)  Reallocate void pointer array smaller
+ *     E)  Reallocate with null pointer
+ *     F)  Remove item from array
+ *     G)  Remove invalid item from array
+ *     H)  Remove item from null array
+ *     I)  Remove null item from array
+ *     J)  Free void pointer array
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.7 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2006-03-06 22:34:25 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include <math.h>
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+typedef struct
+{
+    psS32 x;
+    float y;
+}
+testStruct;
+
+static int testStructCompare(const void **a, const void **b)
+{
+    testStruct* first = (testStruct*)*a;
+    testStruct* second = (testStruct*)*b;
+
+    if(first->x < second->x)
+        return -1;
+    else if (first->x > second->x)
+        return 1;
+    else
+        return 0;
+}
+
+static psS32 testArray( void );
+static psS32 testArray01( void );
+static psS32 testArrayAdd( void );
+static psS32 testArrayGetSet( void );
+static psS32 testArrayLength( void );
+
+testDescription tests[] = {
+                              {testArray, 665, "psArray", 0, false},
+                              {testArray01, 666, "psArray01", 0, false},
+                              {testArrayAdd, 667, "psArrayAdd", 0, false},
+                              {testArrayGetSet, 668, "psArrayGetSet", 0, false},
+                              {testArrayLength, 669, "psArrayLength", 0, false},
+                              {NULL}
+                          };
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetLevel( PS_LOG_INFO );
+
+    return ( ! runTestSuite( stderr, "psArray", tests, argc, argv ) );
+}
+
+
+psS32 testArray(void)
+{
+    // Create array of pointers
+    testStruct *mySt[10];
+    psArray *psArr1 = NULL;
+
+    // Test A - Create void pointer array
+    printPositiveTestHeader(stderr,"psArray", "Create void pointer array");
+    psArray *psArr = psArrayAlloc(5);
+    if (psArr->nalloc != 5) {
+        psError(PS_ERR_UNKNOWN, true,"psArray didn't have proper number of elements.");
+        return 1;
+    }
+    printFooter(stderr, "psArray", "Create void pointer array", true);
+
+
+    // Test B - Add data to void pointer array
+    printPositiveTestHeader(stderr, "psArray", "Add data to void pointer array");
+    for(psS32 i = 0; i < 5; i++) {
+        testStruct *ts = psAlloc(sizeof(testStruct));
+        ts->x = 10*i;
+        ts->y = 10.1*i;
+        mySt[i] = ts;
+        //        psArr->data[i] = ts;
+        if (!psArraySet(psArr, psArr->n, (psPtr)ts) ) {
+            return 6;
+        }
+        psMemIncrRefCounter(ts);
+        psFree(ts);
+    }
+
+    for(psS32 i = 0; i < 5; i++) {
+        testStruct *ts = (testStruct*)psArr->data[i];
+        fprintf(stderr,"ts[%d].x = %d ts[%d].y = %.2f\n", i, ts->x, i, ts->y);
+        if (fabsf(ts->x - 10*i) > 0.01f || fabsf(ts->y - 10.1*i) > 0.01f) {
+            psError(PS_ERR_UNKNOWN, true,"Couldn't properly get elements from array.");
+            return 2;
+        }
+    }
+    fprintf(stderr,"array size = %ld\n", psArr->nalloc);
+    if (psArr->nalloc != 5) {
+        psError(PS_ERR_UNKNOWN, true,"Array Size wrong");
+        return 3;
+    }
+    fprintf(stderr,"array population = %ld\n", psArr->n);
+    if (psArr->n != 5) {
+        psError(PS_ERR_UNKNOWN, true,"Array population wrong");
+        return 4;
+    }
+    printFooter(stderr, "psArray", "Add data to void pointer array", true);
+
+
+    // Test C - Reallocate void pointer array bigger
+    printPositiveTestHeader(stderr,"psArray", "Reallocate void pointer array bigger");
+    psArr = psArrayRealloc(psArr,10);
+    fprintf(stderr,"Adding more elements to void pointer array...\n");
+    for(psS32 i = 5; i < 10; i++) {
+        testStruct *ts = psAlloc(sizeof(testStruct));
+        ts->x = 10*i;
+        ts->y = 10.1*i;
+        mySt[i] = ts;
+        psArr->data[i] = ts;
+        psArr->n++;
+        psMemIncrRefCounter(ts);
+    }
+    for(psS32 i = 0; i < 10; i++) {
+        testStruct *ts = (testStruct*)psArr->data[i];
+        fprintf(stderr,"ts[%d].x = %d ts[%d].y = %.2f\n", i, ts->x, i, ts->y);
+        if (fabsf(ts->x - 10*i) > 0.01f || fabsf(ts->y - 10.1*i) > 0.01f) {
+            psError(PS_ERR_UNKNOWN, true,"Couldn't properly get elements from array.");
+            return 5;
+        }
+    }
+    fprintf(stderr,"array size = %ld\n", psArr->nalloc);
+    if (psArr->nalloc != 10) {
+        psError(PS_ERR_UNKNOWN, true,"Array Size wrong");
+        return 6;
+    }
+    fprintf(stderr,"array population = %ld\n", psArr->n);
+    if (psArr->n != 10) {
+        psError(PS_ERR_UNKNOWN, true,"Array Population wrong");
+        return 7;
+    }
+    printFooter(stderr, "psArray", "Reallocate void pointer array bigger", true);
+
+    // Test D - Reallocate void pointer array smaller
+    printPositiveTestHeader(stderr,"psArray","Reallocate void pointer array smaller");
+    psArr = psArrayRealloc(psArr,3);
+    for(psS32 i = 0; i < 3; i++) {
+        testStruct *ts = (testStruct*)psArr->data[i];
+        fprintf(stderr,"ts[%d].x = %d ts[%d].y = %.2f\n", i, ts->x, i, ts->y);
+        if (fabsf(ts->x - 10*i) > 0.01f || fabsf(ts->y - 10.1*i) > 0.01f) {
+            psError(PS_ERR_UNKNOWN, true,"Couldn't properly get elements from array.");
+            return 8;
+        }
+    }
+    fprintf(stderr,"array size = %ld\n", psArr->nalloc);
+    if (psArr->nalloc != 3) {
+        psError(PS_ERR_UNKNOWN, true,"Array Size wrong");
+        return 9;
+    }
+    fprintf(stderr,"array population = %ld\n", psArr->n);
+    if (psArr->n != 3) {
+        psError(PS_ERR_UNKNOWN, true,"Array Population wrong");
+        return 10;
+    }
+    printFooter(stderr, "psArray", "Reallocate integer void pointer smaller", true);
+
+    // Test E - Reallocate with a null
+    printNegativeTestHeader(stderr,"psArray","Reallocate with a null array",
+                            "Error message generator", 0 );
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message.");
+    psArr1 = psArrayRealloc(NULL,5);
+    if ( psArr1 != NULL ) {
+        fprintf(stderr,"ERROR: Return is not NULL\n");
+    }
+    printFooter(stderr,"psArray","Reallocate with a null array",true);
+
+
+    // Test F - Remove item from array
+    printPositiveTestHeader(stderr, "psArray", "Remove valid item");
+    if( !psArrayRemove(psArr,mySt[0]) ) {
+        psError(PS_ERR_UNKNOWN,true,"Unable to remove valid item");
+        return 100;
+    }
+    fprintf(stderr,"Array size after removal = %ld\n",psArr->n);
+    if ( psArr->n != 2 ) {
+        psError(PS_ERR_UNKNOWN, true, "Items in array not decremented after removal");
+        return 101;
+    }
+    for(psS32 i = 0; i < psArr->n; i++) {
+        testStruct *ts = (testStruct*)psArr->data[i];
+        fprintf(stderr,"ts[%d].x = %d ts[%d].y = %.2f\n", i, ts->x, i, ts->y);
+        if(fabsf(ts->x - 10*(i+1)) > 0.01f || fabsf(ts->y - 10.1*(i+1)) > 0.01f) {
+            psError(PS_ERR_UNKNOWN, true, "Elements not as expected after remove.");
+            return 102;
+        }
+    }
+    printFooter(stderr,"psArray","Remove valid item", true);
+
+    // Test G - Remove invalid item from array
+    printPositiveTestHeader(stderr, "psArray", "Remove invalid item from array");
+    if( psArrayRemove(psArr,mySt[9]) ) {
+        psError(PS_ERR_UNKNOWN,true,"Removed invalid item from array");
+        return 103;
+    }
+    printFooter(stderr,"psArray","Remove invalid item from array",true);
+
+    // Test H - Remove item from null array
+    printPositiveTestHeader(stderr, "psArray", "Remove item from null array");
+    if ( psArrayRemove(NULL,mySt[1]) ) {
+        psError(PS_ERR_UNKNOWN,true,"Removed valid item from null array");
+        return 104;
+    }
+    printFooter(stderr,"psArray","Remove item from null array",true);
+
+    // Test I - Remove null item from array
+    printPositiveTestHeader(stderr, "psArray", "Remove null item from array");
+    if( psArrayRemove(psArr,NULL) ) {
+        psError(PS_ERR_UNKNOWN,true,"Remove null item from array",true);
+        return 105;
+    }
+    printFooter(stderr,"psArray","Remove null item from array",true);
+
+    // Test J - Free void pointer array
+    printPositiveTestHeader(stderr, "psArray", "Free void pointer array");
+    psFree(psArr);
+    for(psS32 i = 0; i < 10; i++) {
+        psFree(mySt[i]);
+    }
+
+    printFooter(stderr, "psArray" ,"Free void pointer array", true);
+
+    return 0;
+}
+
+psS32 testArray01(void)
+{
+    // Create array of pointers
+    testStruct *mySt[10];
+
+    // Test A - Create void pointer array
+    printPositiveTestHeader(stderr,"psArray", "Create void pointer array");
+    psArray *psArr = psArrayAlloc(10);
+    if (psArr->nalloc != 10) {
+        psError(PS_ERR_UNKNOWN, true,"psArray didn't have proper number of elements.");
+        return 1;
+    }
+    printFooter(stderr, "psArray", "Create void pointer array", true);
+
+    // Test B - Add data to void pointer array
+    printPositiveTestHeader(stderr, "psArray", "Add data to void pointer array");
+    for(psS32 i = 0; i < 10; i++) {
+        testStruct *ts = psAlloc(sizeof(testStruct));
+        ts->x = 10*(10-i);
+        ts->y = 10.1*(10-i);
+        mySt[i] = ts;
+        //        psArr->data[i] = ts;
+        if (!psArraySet(psArr, psArr->n, (psPtr)ts) ) {
+            return 6;
+        }
+        psMemIncrRefCounter(ts);
+        psFree(ts);
+    }
+
+    for(psS32 i = 0; i < 10; i++) {
+        testStruct *ts = (testStruct*)psArr->data[i];
+        fprintf(stderr,"ts[%d].x = %d ts[%d].y = %.2f\n", i, ts->x, i, ts->y);
+        if (fabsf(ts->x - 10*(10-i)) > 0.01f || fabsf(ts->y - 10.1*(10-i)) > 0.01f) {
+            psError(PS_ERR_UNKNOWN, true,"Couldn't properly get elements from array.");
+            return 2;
+        }
+    }
+    fprintf(stderr,"array size = %ld\n", psArr->nalloc);
+    if (psArr->nalloc != 10) {
+        psError(PS_ERR_UNKNOWN, true,"Array Size wrong");
+        return 3;
+    }
+    fprintf(stderr,"array population = %ld\n", psArr->n);
+    if (psArr->n != 10) {
+        psError(PS_ERR_UNKNOWN, true,"Array population wrong");
+        return 4;
+    }
+    printFooter(stderr, "psArray", "Add data to void pointer array", true);
+
+    // Test C - Sort data in array
+    printPositiveTestHeader(stderr,"psArray","Sort data in array");
+    psArr = psArraySort(psArr,testStructCompare);
+    for(psS32 i = 0; i < 10; i++) {
+        testStruct *ts = (testStruct*)psArr->data[i];
+        fprintf(stderr,"ts[%d].x = %d ts[%d].y = %.2f\n", i, ts->x, i, ts->y);
+        if (fabsf(ts->x - 10*(i+1)) > 0.01f || fabsf(ts->y - 10.1*(i+1)) > 0.01f) {
+            psError(PS_ERR_UNKNOWN, true,"Couldn't properly get elements from array.");
+            return 5;
+        }
+    }
+    printFooter(stderr,"psArray","Sort data in array",true);
+
+    // Test D - Attempt to sort null array
+    printPositiveTestHeader(stderr,"psArray","Attempt to sort array");
+    psArray* tempArr = psArraySort(NULL,testStructCompare);
+    if(tempArr != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Array sort did not return null when sorting null array");
+        return 6;
+    }
+    printFooter(stderr,"psArray","Attempt to sort array",true);
+
+    // Test E - Free void pointer array
+    printPositiveTestHeader(stderr, "psArray", "Free void pointer array");
+    psFree(psArr);
+    for(psS32 i = 0; i < 10; i++) {
+        psFree(mySt[i]);
+    }
+    if( psMemCheckLeaks(0, NULL, stderr, false) != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Memory leaks detected.");
+        return 110;
+    }
+    psS32 nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        fprintf(stderr,"ERROR: Found %d bad memory blocks\n", nBad);
+        return 111;
+    }
+    printFooter(stderr, "psArray" ,"Free void pointer array", true);
+
+    return 0;
+}
+
+psS32 testArrayAdd( void )
+{
+    int subtest = 0;
+    float* data;
+    int nalloc = 5;
+    int n = 0;
+    int delta = 5;
+
+    // allocate the array.
+    psArray* arr = psArrayAlloc(nalloc);
+    arr->n = n;
+
+    // test arrayAdd until n == nalloc
+    while (n < nalloc) {
+        data = psAlloc(sizeof(float));
+        arr = psArrayAdd(arr, delta*2, data); // make delta unique versus next delta used.
+
+        subtest++;
+        if (psMemGetRefCounter(data) != 2) {
+            // in response of Bug #302
+            psError(PS_ERR_UNKNOWN, true,
+                    "psArrayAdd did not increment the data reference count.");
+            return subtest;
+        }
+
+        subtest++;
+        if (arr->nalloc != nalloc) {
+            psError(PS_ERR_UNKNOWN,true,
+                    "psArrayAdd expanded the psArray unnecessarily.  n=%d",
+                    n);
+            return subtest;
+        }
+
+        subtest++;
+        if (arr->n != ++n) {
+            psError(PS_ERR_UNKNOWN,true,
+                    "psArrayAdd did not increment the size of the psArray. n=%d",
+                    n);
+            return subtest;
+        }
+
+        subtest++;
+        if (arr->data[n-1] != data) {
+            psError(PS_ERR_UNKNOWN,true,
+                    "psArrayAdd didn't set the element to data. n=%d",
+                    n);
+            return subtest;
+        }
+
+        psFree(data);
+    }
+
+    // now try to add an element when the array is full.
+    data = psAlloc(sizeof(float));
+    arr = psArrayAdd(arr, delta, data);
+
+    // make sure the array was expanded
+    subtest++;
+    if (arr->nalloc != nalloc+delta) {
+        psError(PS_ERR_UNKNOWN,true,
+                "psArrayAdd did not expand the psArray when it was already full."
+                " old nalloc=%d, nalloc=%d, delta=%d",
+                nalloc, arr->nalloc, delta);
+        return subtest;
+    }
+    nalloc = arr->nalloc;
+
+    subtest++;
+    if (arr->n != ++n) {
+        psError(PS_ERR_UNKNOWN,true,
+                "psArrayAdd did not increment psArray.n by 1 after expanding it.");
+        return subtest;
+    }
+
+    subtest++;
+    if (arr->data[n-1] != data) {
+        psError(PS_ERR_UNKNOWN,true,
+                "psArrayAdd didn't set the second element to data.");
+        return subtest;
+    }
+
+    psFree(data);
+
+    // make the array full again (operation tested already)
+    while (arr->n < arr->nalloc) {
+        data = psAlloc(sizeof(float));
+        arr = psArrayAdd(arr, 0, data);
+        psFree(data);
+    }
+    nalloc = arr->nalloc;
+    n = arr->n;
+
+    // now add to full array with delta = 0; verify that the array is
+    // expanded by 10
+    data = psAlloc(sizeof(float));
+    arr = psArrayAdd(arr, 0, data);
+    psFree(data);
+
+    subtest++;
+    if (arr->nalloc != nalloc+10) {
+        psError(PS_ERR_UNKNOWN,true,
+                "psArrayAdd did not expand the psArray by 10 when delta < 1."
+                " old nalloc=%d, nalloc=%d",
+                nalloc, arr->nalloc);
+        return subtest;
+    }
+
+    psFree(arr);
+
+    return 0;  // the value that indicates success is part of the testDescription
+}
+
+psS32 testArrayGetSet( void )
+{
+    psArray *test;
+    int *p1 = psAlloc(sizeof(int));
+    int *p2 = psAlloc(sizeof(int));
+    int *p3 = psAlloc(sizeof(int));
+    test = psArrayAlloc(5);
+    test->n = 0;
+    *p1 = 10;
+    *p2 = 4;
+    *p3 = 666;
+
+    if ( !psArraySet(test, 0, p1) )
+        fprintf(stderr, "ArraySet failed to set S32 at position 0\n");
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psArraySet(test, 10, p1) )
+        fprintf(stderr, "ArraySet Improperly set S32 at out of range position\n");
+    if ( !psArraySet(test, 1, p2) )
+        fprintf(stderr, "ArraySet Failed to set S32 at position 1\n");
+    if ( psArrayGet(test, 0) != p1 )
+        fprintf(stderr, "ArrayGet Failed to return the correct S32 from position 0\n");
+    if ( psArrayGet(test, -1) != p2)
+        fprintf(stderr, "ArrayGet Failed to return the correct S32 from tail using -1\n");
+    //    psFree(p1); // free ref from psArrayGet
+    //    psFree(p2); // free ref from psArrayGet
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psArraySet(test, -6, p3) )
+        fprintf(stderr, "ArraySet failed to fail using an out of range negative number\n");
+
+    psFree(test);
+    psFree(p1);
+    psFree(p2);
+    psFree(p3);
+
+    return 0;
+}
+
+psS32 testArrayLength( void )
+{
+    psArray *array = psArrayAlloc(5);
+
+    if (psArrayLength(array) != 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psArrayLength failed to return the correct length of array.\n");
+        return 1;
+    }
+    array->n = 5;
+    if (psArrayLength(array) != 5) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psArrayLength failed to return the correct length of array.\n");
+        return 2;
+    }
+    array->n++;
+    if (psArrayLength(array) != 6) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psArrayLength failed to return the correct length of array.\n");
+        return 3;
+    }
+    psFree(array);
+
+    psArray *emptyArray = NULL;
+    psVector *vector = psVectorAlloc(5, PS_TYPE_F32);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if (psArrayLength(emptyArray) != -1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psArrayLength failed to return -1 for a NULL input array.\n");
+        return 4;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if (psArrayLength((psArray*)vector) != -1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psArrayLength failed to return -1 for an invalid input array.\n");
+        return 5;
+    }
+    psFree(vector);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psBitSet.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psBitSet.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psBitSet.c	(revision 22158)
@@ -0,0 +1,681 @@
+/** @file  tst_psBitSet_01.c
+ *
+ *  @brief Test driver for psBitSet functions
+ *
+ *  This test driver contains the following tests for psBitSet test point 1:
+ *     A)  Create psBitSet
+ *     B)  Set bits
+ *     C)  Test bits
+ *     D)  Attempt to test negative bit
+ *     E)  Attempt to test bit to large
+ *     F)  Attempt to test bit in null BitSet
+ *     G)  Attempt to set negative bit
+ *     H)  Attempt to set bit to large
+ *     I)  Attempt to set bit in null BitSet
+ *     J)  Free psBitSet
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2007-02-07 23:52:54 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include "pslib_strict.h"
+#include "psTest.h"
+
+static psS32 testBitSet01a(void);
+static psS32 testBitSet01b(void);
+static psS32 testBitSet01c(void);
+static psS32 testBitSet02(void);
+static psS32 testBitSet03(void);
+static psS32 testBitSet04(void);
+static psS32 testBitSet05(void);
+static psS32 testBitSet06(void);
+
+testDescription tests[] = {
+                              {testBitSet01a, 1, "psBitSetAlloc", 0, false},
+                              {testBitSet01b, 2, "psBitSetSet/psBitSetClear", 0, false},
+                              {testBitSet01c, 3, "psBitSetTest", 0, false},
+                              {testBitSet06, 4, "psBitSetOp", 0, false},
+                              {testBitSet02, 5, "psBitSetOp AND Operator", 0, false},
+                              {testBitSet03, 6, "psBitSetOp OR Operator", 0, false},
+                              {testBitSet04, 7, "psBitSetOp XOR Operator", 0, false},
+                              {testBitSet05, 8, "psBitSetNot", 0, false},
+
+                              {NULL}
+                          };
+
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetLevel( PS_LOG_INFO );
+
+    return ( ! runTestSuite( stderr, "psBitSet", tests, argc, argv ) );
+}
+
+psS32 testBitSet01a(void)
+{
+    psErr* err;
+
+    // Test A - Create psBitSet
+    fprintf(stderr,"Creating psBitSet with 24 bits...\n");
+    psBitSet* bs = psBitSetAlloc(24);
+    if (bs == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Failed to create a psBitSet");
+        return 1;
+    }
+    if (bs->n != 3) {
+        psError(PS_ERR_UNKNOWN,true,"Number of bytes for psBitSet incorrect (%ld vs 3)",
+                bs->n);
+        return 2;
+    }
+    if (bs->bits[0] != 0 || bs->bits[1] != 0 || bs->bits[2] != 0) {
+        psError(PS_ERR_UNKNOWN,true,"psBitSetAlloc didn't clean ou the bits by default (%x%x%x).",
+                bs->bits[2],bs->bits[1],bs->bits[0]);
+        return 3;
+    }
+    psFree(bs);
+
+    // Test A - Create psBitSet
+    fprintf(stderr,"Creating psBitSet with 25 bits...\n");
+    bs = psBitSetAlloc(25);
+    if (bs == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Failed to create a psBitSet with 25 bits");
+        return 4;
+    }
+    if (bs->n != 4) {
+        psError(PS_ERR_UNKNOWN,true,"Number of bytes for psBitSet incorrect (%ld vs 4)",bs->n);
+        return 5;
+    }
+    psFree(bs);
+
+    psErrorClear();
+    psLogMsg(__func__,PS_LOG_INFO,"Following is an error.");
+    bs = psBitSetAlloc(-4);
+    if (bs != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psBitSetAlloc returned something in case of a negative size");
+        return 6;
+    }
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psErrorStackPrint(stderr,"Error Stack:");
+        psError(PS_ERR_UNKNOWN,true,"psBitSetAlloc didn't generate expected error with size = -4");
+        return 7;
+    }
+    psFree(err);
+
+    return 0;
+}
+
+psS32 testBitSet01b(void)
+{
+    char *binOut = NULL;
+    psBitSet *tempBs = NULL;
+    psErr* err = NULL;
+
+    psBitSet* bs = psBitSetAlloc(24);
+
+    if (psBitSetTest(bs,0) ||
+            psBitSetTest(bs,2) ||
+            psBitSetTest(bs,23) ) {
+
+        psAbort("psBitSetAlloc failed to clear all bits at allocation.");
+    }
+
+    // Test B - Set bits
+    tempBs = bs;
+    fprintf(stderr,"Setting first bit...\n");
+    bs = psBitSetSet(bs, 0);
+    fprintf(stderr,"Setting third bit...\n");
+    bs = psBitSetSet(bs, 2);
+    fprintf(stderr,"Setting last bit...\n");
+    bs = psBitSetSet(bs, 23);
+    if(bs != tempBs) {
+        psAbort(                "Return pointer not equal to output argument pointer.");
+    }
+    if(bs->bits[0] != 0x05) {
+        psAbort(                "Unexpected value for first byte (%d vs 5).",
+                bs->bits[0]);
+    }
+
+
+    binOut = psBitSetToString(bs);
+    fprintf(stderr,"%s\n\n", binOut);
+    psFree(binOut);
+
+    // Test C - Test bits
+    if (! psBitSetTest(bs,0) ||
+            ! psBitSetTest(bs,2) ||
+            ! psBitSetTest(bs,23) ) {
+
+        psAbort("Failed to set a bit.");
+    }
+
+    fprintf(stderr,"Clearing first bit...\n");
+    bs = psBitSetClear(bs, 0);
+    fprintf(stderr,"Clearing third bit...\n");
+    bs = psBitSetClear(bs, 2);
+    fprintf(stderr,"Clearing last bit...\n");
+    bs = psBitSetClear(bs, 23);
+
+    binOut = psBitSetToString(bs);
+    fprintf(stderr,"%s\n\n", binOut);
+    psFree(binOut);
+
+
+    if (psBitSetTest(bs,0) ||
+            psBitSetTest(bs,2) ||
+            psBitSetTest(bs,23) ) {
+
+        psAbort("Failed to clear a bit.");
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error");
+    if(psBitSetClear(NULL,2) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psBitSetClear did not return NULL with NULL bitset");
+        return 20;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error");
+    if(psBitSetClear(bs,-3) != bs) {
+        psError(PS_ERR_UNKNOWN,true,"psBitSetClear did not return original bitset");
+        return 21;
+    }
+
+    psLogMsg("testBitSet01b",PS_LOG_INFO,"Following should be an error");
+    psErrorClear();
+    psBitSetSet(bs, -4);
+
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psErrorStackPrint(stderr,"Error Stack:");
+        psAbort("psBitSetSet(bs, -4) didn't generate expected error.\n");
+    }
+    psFree(err);
+
+    psLogMsg("testBitSet01b",PS_LOG_INFO,"Following should be an error");
+    psErrorClear();
+    psBitSetSet(bs, 200);
+
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psErrorStackPrint(stderr,"Error Stack:");
+        psAbort("psBitSetSet(bs, 200) didn't generate expected error.\n");
+    }
+    psFree(err);
+
+    psLogMsg("testBitSet01b",PS_LOG_INFO,"Following should be an error");
+    psErrorClear();
+    psBitSetSet(NULL, 0);
+
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_NULL) {
+        psErrorStackPrint(stderr,"Error Stack:");
+        psAbort("psBitSetSet(NULL,0) didn't generate expected error.\n");
+    }
+    psFree(err);
+
+    psFree(bs);
+
+    return 0;
+}
+
+static psS32 testBitSet01c(void)
+{
+    psBitSet* bs = psBitSetAlloc(24);
+    psErr* err = NULL;
+
+    fprintf(stderr,"Setting first bit...\n");
+    bs = psBitSetSet(bs, 0);
+    fprintf(stderr,"Setting third bit...\n");
+    bs = psBitSetSet(bs, 2);
+    fprintf(stderr,"Setting last bit...\n");
+    bs = psBitSetSet(bs, 23);
+
+    if (! psBitSetTest(bs,0) ||
+            ! psBitSetTest(bs,2) ||
+            ! psBitSetTest(bs,23) ) {
+
+        psAbort("Set bits returned false.");
+    }
+
+    psLogMsg("testBitSet01c",PS_LOG_INFO,"Following should be an error");
+    psErrorClear();
+    if(psBitSetTest(bs, -4)) {
+        psAbort("psBitSetTest returned true with negative bit position.\n");
+    }
+
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psErrorStackPrint(stderr,"Error Stack:");
+        psAbort("psBitSetTest(bs, -4) didn't generate proper error.\n");
+    }
+    psFree(err);
+
+    psLogMsg("testBitSet01c",PS_LOG_INFO,"Following should be an error");
+    psErrorClear();
+    if(psBitSetTest(bs, 200)) {
+        psAbort("psBitSetTest returned true with too-large bit position.\n");
+    }
+
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psErrorStackPrint(stderr,"Error Stack:");
+        psAbort("psBitSetTest(bs, 200) didn't generate proper error.\n");
+    }
+    psFree(err);
+
+    psLogMsg("testBitSet01c",PS_LOG_INFO,"Following should be an error");
+    psErrorClear();
+    if (psBitSetTest(NULL, 0)) {
+        psAbort("psBitSetTest returned true with NULL psBitSet.\n");
+    }
+
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_NULL) {
+        psErrorStackPrint(stderr,"Error Stack:");
+        psAbort("psBitSetTest(NULL, 0) didn't generate proper error.\n");
+    }
+    psFree(err);
+
+    psFree(bs);
+
+    return 0;
+}
+
+psS32 testBitSet02()
+{
+    char *binOut1 = NULL;
+    char *binOut2 = NULL;
+    char *binOut3 = NULL;
+
+    psBitSet* bs1 = psBitSetAlloc(24);
+    psBitSet* bs2 = psBitSetAlloc(24);
+    psBitSet* and = psBitSetAlloc(24);
+    for(psS32 i=0; i<24; i++) {
+        if ((i & 2) == 0) {
+            bs1 = psBitSetSet(bs1, i);
+        }
+        if ((i & 1) == 0) {
+            bs2 = psBitSetSet(bs2, i);
+        }
+        if (((i & 1) == 0) && ((i & 2) == 0) ) {
+            and = psBitSetSet(and, i);
+        }
+    }
+    binOut1 = psBitSetToString(bs1);
+    binOut2 = psBitSetToString(bs2);
+    binOut3 = psBitSetToString(and);
+    fprintf(stderr,"psBitSetOp input is %s, %s.  Truth is %s.\n",
+            binOut1,binOut2,binOut3);
+    psFree(binOut1);
+    psFree(binOut2);
+    psFree(binOut3);
+
+    // Test B - Perform binary AND with psBitSets
+    psLogMsg(__func__,PS_LOG_INFO,"Perform binary AND with psBitSets");
+    psBitSet* outbs = psBitSetAlloc(24);
+    outbs = psBitSetOp(outbs, bs1, "AND", bs2);
+    if (outbs == NULL) {
+        psAbort("psBitSetOp returned a NULL result for AND operation");
+    }
+
+    for(psS32 i=0; i<24; i++) {
+        psBool truth = psBitSetTest(and,i);
+        psBool res = psBitSetTest(outbs,i);
+        if ( res != truth) {
+            binOut1 = psBitSetToString(bs1);
+            binOut2 = psBitSetToString(bs2);
+            binOut3 = psBitSetToString(outbs);
+            psAbort("psBitSetOp with AND operator failed.\nInput was %s, %s.  Output was %s",
+                    binOut1,binOut2,binOut3);
+        }
+    }
+    psFree(outbs);
+
+    // Test C - Perform binary AND and auto allocate output
+    psLogMsg(__func__,PS_LOG_INFO,"Perform binary AND and auto allocate output");
+    outbs = psBitSetOp(NULL, bs1, "AND", bs2);
+    if (outbs == NULL) {
+        psAbort("psBitSetOp failed to create a new psBitSet for the result");
+    }
+    for(psS32 i=0; i<24; i++) {
+        psBool truth = psBitSetTest(and,i);
+        psBool res = psBitSetTest(outbs,i);
+        if ( res != truth) {
+            binOut1 = psBitSetToString(bs1);
+            binOut2 = psBitSetToString(bs2);
+            binOut3 = psBitSetToString(outbs);
+            psAbort("psBitSetOp with AND operator failed.\nInput was %s, %s.  Output was %s",
+                    binOut1,binOut2,binOut3);
+        }
+    }
+    psFree(outbs);
+
+    psFree(bs1);
+    psFree(bs2);
+    psFree(and);
+
+    return 0;
+}
+
+static psS32 testBitSet03(void)
+{
+    char *binOut1 = NULL;
+    char *binOut2 = NULL;
+    char *binOut3 = NULL;
+
+    psBitSet* bs1 = psBitSetAlloc(24);
+    psBitSet* bs2 = psBitSetAlloc(24);
+    psBitSet* or = psBitSetAlloc(24);
+    for(psS32 i=0; i<24; i++) {
+        if ((i/2) % 2) {
+            bs1 = psBitSetSet(bs1, i);
+        }
+        if ((i) % 2) {
+            bs2 = psBitSetSet(bs2, i);
+        }
+        if ( ((i/2) % 2) || ((i) % 2) ) {
+            or = psBitSetSet(or, i);
+        }
+    }
+
+    binOut1 = psBitSetToString(bs1);
+    binOut2 = psBitSetToString(bs2);
+    binOut3 = psBitSetToString(or);
+    fprintf(stderr,"psBitSetOp input is %s, %s.  Truth is %s.\n",
+            binOut1,binOut2,binOut3);
+    psFree(binOut1);
+    psFree(binOut2);
+    psFree(binOut3);
+
+    // Test B - Perform binary AND with psBitSets
+    psLogMsg(__func__,PS_LOG_INFO,"Perform binary OR with psBitSets");
+    psBitSet* outbs = psBitSetAlloc(24);
+    outbs = psBitSetOp(outbs, bs1, "OR", bs2);
+    if (outbs == NULL) {
+        psAbort("psBitSetOp returned a NULL result for OR operation");
+    }
+
+    for(psS32 i=0; i<24; i++) {
+        psBool truth = psBitSetTest(or,i);
+        psBool res = psBitSetTest(outbs,i);
+        if ( res != truth) {
+            binOut1 = psBitSetToString(bs1);
+            binOut2 = psBitSetToString(bs2);
+            binOut3 = psBitSetToString(outbs);
+            psAbort("psBitSetOp with OR operator failed.\nInput was %s, %s.  Output was %s",
+                    binOut1,binOut2,binOut3);
+        }
+    }
+    psFree(outbs);
+
+    // Test C - Perform binary AND and auto allocate output
+    psLogMsg(__func__,PS_LOG_INFO,"Perform binary OR and auto allocate output");
+    outbs = psBitSetOp(NULL, bs1, "OR", bs2);
+    if (outbs == NULL) {
+        psAbort("psBitSetOp failed to create a new psBitSet for the result");
+    }
+    for(psS32 i=0; i<24; i++) {
+        psBool truth = psBitSetTest(or,i);
+        psBool res = psBitSetTest(outbs,i);
+        if ( res != truth) {
+            binOut1 = psBitSetToString(bs1);
+            binOut2 = psBitSetToString(bs2);
+            binOut3 = psBitSetToString(outbs);
+            psAbort("psBitSetOp with OR operator failed.\nInput was %s, %s.  Output was %s",
+                    binOut1,binOut2,binOut3);
+        }
+    }
+    psFree(outbs);
+    outbs = NULL;
+
+    psFree(bs1);
+    psFree(bs2);
+    psFree(or);
+
+    return 0;
+}
+
+static psS32 testBitSet04(void)
+{
+    char *binOut1 = NULL;
+    char *binOut2 = NULL;
+    char *binOut3 = NULL;
+
+    psBitSet* bs1 = psBitSetAlloc(24);
+    psBitSet* bs2 = psBitSetAlloc(24);
+    psBitSet* xor = psBitSetAlloc(24);
+    for(psS32 i=0; i<24; i++) {
+        if ((i/2) % 2) {
+            bs1 = psBitSetSet(bs1, i);
+        }
+        if ((i) % 2) {
+            bs2 = psBitSetSet(bs2, i);
+        }
+        if ( ((i/2) % 2) != ((i) % 2) ) {
+            xor = psBitSetSet(xor, i);
+        }
+    }
+
+    binOut1 = psBitSetToString(bs1);
+    binOut2 = psBitSetToString(bs2);
+    binOut3 = psBitSetToString(xor);
+    fprintf(stderr,"psBitSetOp input is %s, %s.  Truth is %s.\n",
+            binOut1,binOut2,binOut3);
+    psFree(binOut1);
+    psFree(binOut2);
+    psFree(binOut3);
+
+    // Test B - Perform binary AND with psBitSets
+    psLogMsg(__func__,PS_LOG_INFO,"Perform binary XOR with psBitSets");
+    psBitSet* outbs = psBitSetAlloc(24);
+    outbs = psBitSetOp(outbs, bs1, "XOR", bs2);
+    if (outbs == NULL) {
+        psAbort("psBitSetOp returned a NULL result for XOR operation");
+    }
+
+    for(psS32 i=0; i<24; i++) {
+        psBool truth = psBitSetTest(xor,i);
+        psBool res = psBitSetTest(outbs,i);
+        if ( res != truth) {
+            binOut1 = psBitSetToString(bs1);
+            binOut2 = psBitSetToString(bs2);
+            binOut3 = psBitSetToString(outbs);
+            psAbort("psBitSetOp with XOR operator failed.\nInput was %s, %s.  Output was %s",
+                    binOut1,binOut2,binOut3);
+        }
+    }
+    psFree(outbs);
+
+    // Test C - Perform binary AND and auto allocate output
+    psLogMsg(__func__,PS_LOG_INFO,"Perform binary XOR and auto allocate output");
+    outbs = psBitSetOp(NULL, bs1, "XOR", bs2);
+    if (outbs == NULL) {
+        psAbort("psBitSetOp failed to create a new psBitSet for the result");
+    }
+    for(psS32 i=0; i<24; i++) {
+        psBool truth = psBitSetTest(xor,i);
+        psBool res = psBitSetTest(outbs,i);
+        if ( res != truth) {
+            binOut1 = psBitSetToString(bs1);
+            binOut2 = psBitSetToString(bs2);
+            binOut3 = psBitSetToString(outbs);
+            psAbort("psBitSetOp with XOR operator failed.\nInput was %s, %s.  Output was %s",
+                    binOut1,binOut2,binOut3);
+        }
+    }
+    psFree(outbs);
+    outbs = NULL;
+
+    psFree(bs1);
+    psFree(bs2);
+    psFree(xor);
+
+    return 0;
+}
+
+static psS32 testBitSet05(void)
+{
+    char *binOut1 = NULL;
+    char *binOut2 = NULL;
+
+    psBitSet* bs1 = psBitSetAlloc(24);
+    psBitSet* not = psBitSetAlloc(24);
+    for(psS32 i=0; i<24; i++) {
+        if (i % 2) {
+            bs1 = psBitSetSet(bs1, i);
+        }
+        if (i % 2 == 0) {
+            not = psBitSetSet(not, i);
+        }
+    }
+
+    binOut1 = psBitSetToString(bs1);
+    binOut2 = psBitSetToString(not);
+    fprintf(stderr,"psBitSetOp input is %s.  Truth is %s.\n",
+            binOut1,binOut2);
+    psFree(binOut1);
+    psFree(binOut2);
+
+    // Test B - Perform binary AND with psBitSets
+    psLogMsg(__func__,PS_LOG_INFO,"Perform binary NOT with psBitSets");
+    psBitSet* outbs = psBitSetAlloc(24);
+    outbs = psBitSetNot(outbs, bs1);
+    if (outbs == NULL) {
+        psAbort("psBitSetOp returned a NULL result for NOT operation");
+    }
+
+    for(psS32 i=0; i<24; i++) {
+        psBool truth = psBitSetTest(not,i);
+        psBool res = psBitSetTest(outbs,i);
+        if ( res != truth) {
+            binOut1 = psBitSetToString(bs1);
+            binOut2 = psBitSetToString(outbs);
+            psAbort("psBitSetOp with NOT operator failed.\nInput was %s.  Output was %s",
+                    binOut1,binOut2);
+        }
+    }
+    psFree(outbs);
+
+    // Test C - Perform binary AND and auto allocate output
+    psLogMsg(__func__,PS_LOG_INFO,"Perform binary NOT and auto allocate output");
+    outbs = psBitSetNot(NULL, bs1);
+    if (outbs == NULL) {
+        psAbort("psBitSetOp failed to create a new psBitSet for the result");
+    }
+    for(psS32 i=0; i<24; i++) {
+        psBool truth = psBitSetTest(not,i);
+        psBool res = psBitSetTest(outbs,i);
+        if ( res != truth) {
+            binOut1 = psBitSetToString(bs1);
+            binOut2 = psBitSetToString(outbs);
+            psAbort("psBitSetOp with NOT operator failed.\nInput was %s.  Output was %s",
+                    binOut1,binOut2);
+        }
+    }
+    psFree(outbs);
+    outbs = NULL;
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error");
+    if(psBitSetNot(NULL,NULL) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psBitSetNot did not return NULL with NULL input");
+        return 30;
+    }
+
+    psFree(bs1);
+    psFree(not);
+
+    return 0;
+}
+
+static psS32 testBitSet06(void)
+{
+    psErr* err;
+
+    psBitSet* bs1 = psBitSetAlloc(24);
+    psBitSet* bs2 = psBitSetAlloc(40);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error");
+    psBitSet* outbs = psBitSetOp(NULL, bs1, "XOR", bs2);
+    if (outbs != NULL) {
+        psAbort("psBitSetOp did not return a NULL result when input sizes differ");
+    }
+
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_SIZE) {
+        psErrorStackPrint(stderr,"Error Stack:");
+        psAbort("psBitSetOp didn't generate expected error with operands' sizes differed.");
+    }
+    psFree(err);
+    psFree(bs1);
+    psFree(bs2);
+
+    bs1 = psBitSetAlloc(24);
+    bs2 = psBitSetAlloc(24);
+
+    outbs = psBitSetAlloc(40);
+    psBitSet* outbs2 = psBitSetOp(outbs, bs1, "XOR", bs2);
+    if (outbs2 == NULL) {
+        psAbort("psBitSetOp failed when input size and output size differed (a recoverable error).");
+    }
+    if (outbs2 != outbs) {
+        psAbort("psBitSetOp didn't reuse the given output struct.");
+    }
+    if (outbs2->n != bs1->n) {
+        psAbort("psBitSetOp did properly adjust the output psBitSet size.");
+    }
+
+    psErrorClear();
+    psLogMsg(__func__,PS_LOG_INFO,"Following is an error.");
+    outbs = psBitSetOp(outbs, bs1, "FOO", bs2);
+    if (outbs != NULL) {
+        psAbort("psBitSetOp returned something in case of a bogus operation.");
+    }
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psErrorStackPrint(stderr,"Error Stack:");
+        psAbort("psBitSetOp didn't generate expected error with bogus operator.");
+    }
+    psFree(err);
+
+
+    // try again, though give a valid output bitset -- should free the out upon error to avoid leak.
+    outbs = psBitSetAlloc(24);
+    psErrorClear();
+    psLogMsg(__func__,PS_LOG_INFO,"Following is an error.");
+    outbs = psBitSetOp(outbs, bs1, "FOO", bs2);
+
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psErrorStackPrint(stderr,"Error Stack:");
+        psAbort("psBitSetOp didn't generate expected error with bogus operator.");
+    }
+    psFree(err);
+
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error");
+    if(psBitSetOp(outbs,NULL,"AND",bs2) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psBitSetOp did not return NULL with NULL input 1 bit set");
+        return 40;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error");
+    if(psBitSetOp(outbs,bs1,NULL,bs2) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psBitSetOp did not return NULL with NULL operator");
+        return 41;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error");
+    if(psBitSetOp(outbs,bs1,"AND",NULL) != NULL)  {
+        psError(PS_ERR_UNKNOWN,true,"psBitSetOp did not return NULL with NULL input 2 bit set");
+        return 42;
+    }
+
+    psFree(bs1);
+    psFree(bs2);
+    psFree(outbs);
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psHash00.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psHash00.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psHash00.c	(revision 22158)
@@ -0,0 +1,64 @@
+/*****************************************************************************
+    This code will test whether a hash table can be allocated successfully,
+    then deallocated successfully.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+#include "psHash.h"
+#define NUM_HASH_TABLE_BUCKETS 10
+psS32 main()
+{
+    psHash *myHashTable = NULL;
+    psS32 testStatus      = true;
+    psS32 i               = 0;
+    psS32 currentId = psMemGetId();
+    psS32 memLeaks        = 0;
+    printPositiveTestHeader(stdout,
+                            "psHash functions",
+                            "psHashAlloc()");
+
+    myHashTable = psHashAlloc(NUM_HASH_TABLE_BUCKETS);
+
+    if (myHashTable == NULL) {
+        fprintf(stderr, "%s: could not allocate a hash table.", __func__);
+        testStatus = false;
+    }
+
+    if (myHashTable->n != NUM_HASH_TABLE_BUCKETS) {
+        fprintf(stderr, "%s: myHashTable->nbucket not set properly.\n",
+                __func__);
+        testStatus = false;
+
+    }
+
+    if (myHashTable->buckets == NULL) {
+        fprintf(stderr, "%s: myHashTable->buckets is NULL.\n",
+                __func__);
+        testStatus = false;
+
+    }
+
+    for (i=0;i<NUM_HASH_TABLE_BUCKETS;i++) {
+        if (myHashTable->buckets[i] != NULL) {
+            fprintf(stderr, "%s: hash table bucket[%d] not equal to NULL.\n",
+                    __func__, i);
+            testStatus = false;
+        }
+    }
+
+    printFooter(stdout,
+                "psHash functions",
+                "psHashAlloc()",
+                testStatus);
+
+    psFree(myHashTable);
+
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    psMemCheckCorruption(1);
+
+    return (!testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psHash01.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psHash01.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psHash01.c	(revision 22158)
@@ -0,0 +1,155 @@
+/*****************************************************************************
+    This code will test whether a hash table can be de-allocated successfully.
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+#include "psHash.h"
+#define NUM_HASH_TABLE_BUCKETS 100
+psS32 imGlobal = 0;
+
+typedef struct
+{
+    char *name;
+}
+ID;
+
+static void IdFree(ID *id);
+
+static ID *IdAlloc(const char *name)
+{
+    ID *id = psAlloc(sizeof(ID));
+    psMemSetDeallocator(id,(psFreeFunc)IdFree);
+    id->name = psStringCopy(name);
+
+    return id;
+}
+
+static void IdFree(ID *id)
+{
+    imGlobal++;
+    psFree(id->name);
+}
+
+psS32 main()
+{
+    psHash *myHashTable = NULL;
+    psS32 testStatus      = true;
+    psS32 currentId = psMemGetId();
+    ID* id = NULL;
+    ID* replaceId = NULL;
+    psS32 memLeaks        = 0;
+    psBool  retVal = false;
+
+    // Allocate memory for Hash Table
+    printPositiveTestHeader(stdout,"psHash functions","psHashAlloc");
+    myHashTable = psHashAlloc(NUM_HASH_TABLE_BUCKETS);
+    if(myHashTable == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Unable to allocate psHash table");
+        return 10;
+    }
+    printFooter(stdout,"psHash functions","psHashAlloc",true);
+
+    // Add items to Hash table
+    id = IdAlloc("IDA");
+    printPositiveTestHeader(stdout,"psHash functions","psHashAdd");
+    retVal = psHashAdd(myHashTable, "ENTRY00", id);
+    psFree(id);
+    if( !retVal) {
+        psError(PS_ERR_UNKNOWN, true, "psHashAdd unable to add ENTRY00");
+        return 1;
+    }
+
+    id = IdAlloc("IDB");
+    retVal = psHashAdd(myHashTable, "ENTRY01", id);
+    psFree(id);
+    if (!retVal) {
+        psError(PS_ERR_UNKNOWN, true, "psHashAdd unable to add ENTRY01");
+        return 2;
+    }
+
+    id = IdAlloc("IDC");
+    retVal = psHashAdd(myHashTable, "ENTRY02", id);
+    psFree(id);
+    if(!retVal) {
+        psError(PS_ERR_UNKNOWN,true,"psHashAdd unable to add ENTRY02");
+        return 3;
+    }
+
+    id = IdAlloc("IDD");
+    retVal =psHashAdd(myHashTable, "ENTRY03", id);
+    psFree(id);
+    if(!retVal) {
+        psError(PS_ERR_UNKNOWN,true,"psHashAdd unable to add ENTRY03");
+        return 4;
+    }
+    printFooter(stdout,"psHash functions","psHashAdd",true);
+
+    // Replace item with same key
+    printPositiveTestHeader(stdout,"psHash replace item","psHashAdd");
+    id = IdAlloc("IDE");
+    retVal = psHashAdd(myHashTable,"ENTRY02",id);
+    if(!retVal) {
+        psError(PS_ERR_UNKNOWN,true,"psHashAdd unable to replace ENTRY02");
+        return 5;
+    }
+    replaceId = psHashLookup(myHashTable,"ENTRY02");
+    if(strcmp(replaceId->name,"IDE") != 0) {
+        psError(PS_ERR_UNKNOWN,true,"psHashAdd did not replace ENTRY02 with correct item");
+        return 6;
+    }
+    printFooter(stdout,"psHash replace item","psHashAdd",true);
+
+    // Add with NULL hash table specified
+    printNegativeTestHeader(stdout,"psHashAdd","NULL hash table","Hash table can not be NULL.",0);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message: psHashAdd with null table");
+    retVal = psHashAdd(NULL,"ENTRY04",id);
+    if(retVal) {
+        psError(PS_ERR_UNKNOWN,true,"psHashAdd added entry to NULL hash table.");
+        return 20;
+    }
+    printFooter(stdout,"psHashAdd","NULL hash table",true);
+
+    // Add with key to valid hash table NULL
+    printNegativeTestHeader(stdout,"psHashAdd","NULL key","Hash key can not be NULL.",0);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message: psHashAdd with null key");
+    retVal = psHashAdd(myHashTable,NULL,id);
+    if(retVal) {
+        psError(PS_ERR_UNKNOWN,true,"psHashAdd added entry to hash table with NULL key.");
+        return 21;
+    }
+    printFooter(stdout,"psHashAdd","NULL hash key",true);
+
+    // Add NULL hash data to valid table and key
+    printNegativeTestHeader(stdout,"psHashAdd","NULL hash data","Hash data can not be NULL.",0);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message: psHashAdd with null data");
+    retVal = psHashAdd(myHashTable,"ENTRY04",NULL);
+    if(retVal) {
+        psError(PS_ERR_UNKNOWN,true,"psHashAdd added entry to hash table with NULL data.");
+        return 22;
+    }
+    printFooter(stdout,"psHashAdd","NULL hash data",true);
+
+    // Free hash table
+    printPositiveTestHeader(stdout,"psHash functions","psHashFree");
+    psFree(id);
+
+    psFree(myHashTable);
+
+    if (imGlobal != 5) {
+        fprintf(stderr, "%s: only (%d/4) entries were freed",
+                __func__, imGlobal);
+        testStatus = false;
+    }
+
+    printFooter(stdout,"psHash functions","psHashFree()",testStatus);
+
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (memLeaks != 0) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    psMemCheckCorruption(1);
+
+    return (!testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psHash02.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psHash02.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psHash02.c	(revision 22158)
@@ -0,0 +1,113 @@
+/*****************************************************************************
+    This code will test whether hash tables entries can be inserted correctly,
+    and retrieved correctly.
+ 
+    NOTE: Add code to test whether duplicates are handled correctly (use a
+    small hash table and lots of keys).
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+#include "psHash.h"
+#define NUM_HASH_TABLE_BUCKETS 100
+psS32 imGlobal = 0;
+
+typedef struct
+{
+    char *name;
+}
+ID;
+static void IdFree(ID *id);
+
+static ID *IdAlloc(const char *name)
+{
+    ID *id = psAlloc(sizeof(ID));
+    psMemSetDeallocator(id,(psFreeFunc)IdFree);
+    id->name = psStringCopy(name);
+
+    return id;
+}
+
+static void IdFree(ID *id)
+{
+    imGlobal++;
+    psFree(id->name);
+}
+
+psS32 main()
+{
+    psHash *myHashTable = NULL;
+    psS32 testStatus      = true;
+    psS32 i               = 0;
+    ID *id = NULL;
+    char *myKeys[] = {"ENTRY00", "ENTRY01", "ENTRY02", "ENTRY03", NULL
+                     };
+    char *myData[] = {"IDA", "IDB", "IDC", "IDD", NULL
+                     };
+    psS32 currentId = psMemGetId();
+    psS32 memLeaks        = 0;
+
+    printPositiveTestHeader(stdout,"psHash functions","psHashLookup");
+
+    myHashTable = psHashAlloc(NUM_HASH_TABLE_BUCKETS);
+    i = 0;
+    while (myKeys[i] != NULL) {
+        id = IdAlloc(myData[i]);
+        psHashAdd(myHashTable, myKeys[i], id);
+        psFree(id);
+        i++;
+    }
+
+    i = 0;
+    while (myKeys[i] != NULL) {
+        id = psHashLookup(myHashTable, myKeys[i]);
+        if (0 != strcmp(myData[i], id->name)) {
+            fprintf(stderr, "%s: Hash table entry for key %s was %s (should be %s).\n",
+                    __func__, myKeys[i], id->name, myData[i]);
+            return 1;
+        }
+        i++;
+    }
+    printFooter(stdout,"psHash functions","psHashLookup",true);
+
+    // Use an invalid key in the hash table: verify no item is returned
+    printNegativeTestHeader(stdout,"psHashLookup","Invalid key","Key is not found in the table",0);
+    id = psHashLookup(myHashTable, "BogusKey");
+    if (id != NULL) {
+        fprintf(stderr, "%s: Hash table entry for key %s was not NULL.\n",
+                __func__, "BogusKey");
+        return 2;
+    }
+    printFooter(stdout,"psHashLookup","Invalid key",true);
+
+    // Lookup with null table
+    printNegativeTestHeader(stdout,"psHashLookup","NULL table","Can not lookup with NULL table",0);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message: psHashLookup with null table");
+    id = psHashLookup(NULL,"ENTRY01");
+    if (id != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psHashLookup retrieved an entry from NULL hash table.");
+        return 3;
+    }
+    printFooter(stdout,"psHashLookup","NULL table",true);
+
+    // Lookup with null key
+    printNegativeTestHeader(stdout,"psHashLookup","NULL key","Can not lookup with NULL key.",0);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message: psHashLookup with null key");
+    id = psHashLookup(myHashTable,NULL);
+    if (id != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psHashLookup retrieved an entry with NULL key.");
+        return 4;
+    }
+    printFooter(stdout,"psHashLookup","NULL key",true);
+
+    psFree(myHashTable);
+
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    psMemCheckCorruption(1);
+
+    return (!testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psHash03.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psHash03.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psHash03.c	(revision 22158)
@@ -0,0 +1,142 @@
+/*****************************************************************************
+    This code will test whether hash tables entries can be removed correctly.
+ 
+    NOTE: Add code to test whether duplicates are handled correctly.
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+#include "psHash.h"
+#include "psMemory.h"
+#define NUM_HASH_TABLE_BUCKETS 100
+psS32 imGlobal = 0;
+psS32 currentId = 0;
+
+typedef struct
+{
+    char *name;
+}
+ID;
+static void IdFree(ID *id);
+
+static ID *IdAlloc(const char *name)
+{
+    ID *id = NULL;
+
+    id = psAlloc(sizeof(ID));
+    psMemSetDeallocator(id,(psFreeFunc)IdFree);
+
+    id->name = psStringCopy(name);
+
+    return id;
+}
+
+static void IdFree(ID *id)
+{
+    imGlobal++;
+    psFree(id->name);
+}
+
+psS32 main()
+{
+    psHash *myHashTable = NULL;
+    psS32 testStatus      = true;
+    psS32 i               = 0;
+    psS32 TotalKeys       = 0;
+    psBool retVal         = false;
+    ID *id = NULL;
+    ID *ids[4];
+    char *myKeys[] = {"ENTRY00", "ENTRY01", "ENTRY02", "ENTRY03", NULL
+                     };
+    char *myData[] = {"IDA", "IDB", "IDC", "IDD", NULL
+                     };
+    psS32 memLeaks        = 0;
+
+    currentId = psMemGetId();
+
+    printPositiveTestHeader(stdout,"psHash functions","psHashRemove");
+
+    // Add items to hash table
+    myHashTable = psHashAlloc(NUM_HASH_TABLE_BUCKETS);
+    i = 0;
+    while (myKeys[i] != NULL) {
+        ids[i] = IdAlloc(myData[i]);
+        psHashAdd(myHashTable, myKeys[i], ids[i]);
+        i++;
+    }
+    TotalKeys = i - 1;
+
+    // Verify items which were just add to hash table
+    i = TotalKeys;
+    while (i >= 0) {
+
+        id = psHashLookup(myHashTable, myKeys[i]);
+        if (0 != strcmp(myData[i], id->name)) {
+            fprintf(stderr, "%s: Hash table entry for key %s was %s (should be %s).\n",
+                    __func__, myKeys[i], id->name, myData[i]);
+            return 1;
+        }
+        i--;
+    }
+
+    // Remove each item from the table and verify item is no longer in the list
+    i = 0;
+    while (myKeys[i] != NULL) {
+        // The psHashRemove() procedure removes the entry from the hash
+        // table and deletes the data.
+        retVal = psHashRemove(myHashTable, myKeys[i]);
+        if (!retVal) {
+            fprintf(stderr,"%s: Hash table entry not removed.\n",__func__);
+            return 2;
+        }
+        id = psHashLookup(myHashTable, myKeys[i]);
+        if (id != NULL) {
+            fprintf(stderr, "%s: Hash table entry for key %s not removed.\n",
+                    __func__, "IDA");
+            return 3;
+        }
+        i++;
+    }
+    printFooter(stdout,"psHash functions","psHashRemove()",true);
+
+    // Use an invalid key in the hash table: verify false is returned
+    printNegativeTestHeader(stdout,"psHashRemove","Invalid key","Key is not found in table",0);
+    if (psHashRemove(myHashTable,"BogusKey") ) {
+        psError(PS_ERR_UNKNOWN,true,"psHashRemove removed an entry with a bogus key.");
+        return 4;
+    }
+    printFooter(stdout,"psHashRemove","Invalid key",true);
+
+    // Remove with null table
+    printNegativeTestHeader(stdout,"psHashRemove","NULL table","Can not remove with NULL table",0);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message: psHashRemove with null table");
+    retVal = psHashRemove(NULL,"ENTRY02");
+    if (retVal) {
+        psError(PS_ERR_UNKNOWN,true,"psHashRemove removed an entry from NULL hash table.");
+        return 5;
+    }
+    printFooter(stdout,"psHashRemove","NULL table",true);
+
+    // Remove with null key
+    printNegativeTestHeader(stdout,"psHashRemove","NULL key","Can not remove with NULL key",0);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message: psHashRemove with null key");
+    if (psHashRemove(myHashTable,NULL) ) {
+        psError(PS_ERR_UNKNOWN,true,"psHashRemove removed an entry from NULL key");
+        return 6;
+    }
+    printFooter(stdout,"psHashRemove","NULL key",true);
+
+    psFree(myHashTable);
+    for(i=0; i<(TotalKeys+1); i++) {
+        psFree(ids[i]);
+    }
+    memLeaks = psMemCheckLeaks(currentId,NULL,stdout,false);
+    if (memLeaks != 0) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    psMemCheckCorruption(true);
+
+    return (!testStatus);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psHash04.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psHash04.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psHash04.c	(revision 22158)
@@ -0,0 +1,84 @@
+/*****************************************************************************
+    This code will test whether the call psHashKeyList() function works.
+ *****************************************************************************/
+#include <stdio.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+#include "psHash.h"
+#define NUM_HASH_TABLE_BUCKETS 100
+psS32 imGlobal = 0;
+
+typedef struct
+{
+    char *name;
+}
+ID;
+static void IdFree(ID *id);
+
+static ID *IdAlloc(const char *name)
+{
+    ID *id = psAlloc(sizeof(ID));
+    psMemSetDeallocator(id,(psFreeFunc)IdFree);
+
+    id->name = psStringCopy(name);
+
+    return id;
+}
+
+static void IdFree(ID *id)
+{
+    imGlobal++;
+    psFree(id->name);
+}
+
+psS32 main()
+{
+    psHash *myHashTable = NULL;
+    psS32 testStatus      = true;
+    psS32 i               = 0;
+    char *myKeys[] = {"ENTRY00", "ENTRY01", "ENTRY02", "ENTRY03", NULL
+                     };
+    char *myData[] = {"IDA", "IDB", "IDC", "IDD", NULL
+                     };
+    psS32 currentId = psMemGetId();
+    psS32 memLeaks        = 0;
+    psList *myLinkList = NULL;
+    psListElem *tmp = NULL;
+    ID* id = NULL;
+
+    printPositiveTestHeader(stdout,"psHash functions","psHashKeyList()");
+    myHashTable = psHashAlloc(NUM_HASH_TABLE_BUCKETS);
+    i = 0;
+    while (myKeys[i] != NULL) {
+        id = IdAlloc(myData[i]);
+        psHashAdd(myHashTable, myKeys[i], id);
+        psFree(id);
+        i++;
+    }
+    myLinkList = psHashKeyList(myHashTable);
+    tmp = myLinkList->head;
+    while (tmp != NULL) {
+        printf("Linked List Entries: %s\n", (char *) tmp->data);
+        tmp = tmp->next;
+    }
+    printFooter(stdout,"psHash functions","psHashKeyList()",testStatus);
+    psFree(myLinkList);
+
+    printNegativeTestHeader(stdout,"psHashKeyList","NULL table","Can not lookup with NULL table",0);
+    myLinkList = psHashKeyList(NULL);
+    if(myLinkList != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psHashKeyList retrieved a key list from a NULL table.");
+        return 1;
+    }
+    printFooter(stdout,"psHashKeyList","NULL table",true);
+
+    psFree(myHashTable);
+
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (memLeaks != 0) {
+        psAbort("Memory Leaks! (%d leaks)", memLeaks);
+    }
+    psMemCheckCorruption(1);
+
+    return(!testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psHash05.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psHash05.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psHash05.c	(revision 22158)
@@ -0,0 +1,172 @@
+/** @file  tst_psHash05.c
+*
+*  @brief Contains the tests for psHash.[ch]
+*
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-07-13 02:47:01 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#include "psTest.h"
+#include "pslib_strict.h"
+
+static psS32 hashToArray( void );
+
+testDescription tests[] = {
+                              {hashToArray, 789, "psHashToArray", 0, false},
+                              {NULL}
+                          };
+
+static void printIntArray(char* name, psArray* arr)
+{
+    if (arr == NULL) {
+        printf("%s = NULL\n",name);
+        return;
+    }
+
+    printf("%s = {",name);
+    for (int i = 0; i < arr->n; i++) {
+        if (arr->data[i] == NULL) {
+            printf("NULL");
+        } else {
+            printf("%d",*(int*)arr->data[i]);
+        }
+        if (i != arr->n-1) {
+            printf(",");
+        }
+    }
+    printf("}");
+}
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetLevel( PS_LOG_INFO );
+
+    return ( ! runTestSuite( stderr, "psHash", tests, argc, argv ) );
+}
+
+psS32 hashToArray( void )
+{
+    int testNum = 0;
+    psArray* array;
+    #define BUCKETS 10
+
+    psHash* hash = psHashAlloc(BUCKETS);
+    char key[2] = "A";
+    bool found[BUCKETS];
+
+    for (int i = 0; i < BUCKETS; i++) {
+
+        array = psHashToArray(hash);
+
+        // return non-null?
+        testNum++;
+        if (array == NULL) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Failed to create an array from a psHash of %d elements.",
+                    i);
+            return testNum;
+        }
+
+        // the size correct
+        testNum++;
+        if (array->n != i) {
+            printIntArray("array",array);
+            psError(PS_ERR_UNKNOWN, false,
+                    "psHashToArray created a psArray of %d elements from a psHash of %d elements.",
+                    array->n, i);
+            return testNum;
+        }
+
+        // the values correct?
+
+        // zero out the found boolean vector
+        for (int j = 0; j < i; j++) {
+            found[j] = false;
+        }
+
+        // check if all the items in array are valid
+        for (int k = 0; k < array->n; k++) {
+            int* item = array->data[k];
+
+            testNum++;
+            if (item == NULL) {
+                printIntArray("array",array);
+                psError(PS_ERR_UNKNOWN, true,
+                        "The array position %d was NULL.",
+                        k);
+                return testNum;
+            }
+
+            testNum++;
+            if (*item < 0 || *item >= BUCKETS) {
+                printIntArray("array",array);
+                psError(PS_ERR_UNKNOWN, true,
+                        "The array position %d was invalid (%d).",
+                        k,*item);
+                return testNum;
+            }
+
+            testNum++;
+            if (found[*item]) {
+                printIntArray("array",array);
+                psError(PS_ERR_UNKNOWN, true,
+                        "The array position %d was a duplicate (%d).",
+                        k,*item);
+                return testNum;
+            }
+
+            testNum++;
+            if (psMemGetRefCounter(item) != 2) {
+                printIntArray("array",array);
+                psError(PS_ERR_UNKNOWN, true,
+                        "The array position %d was not properly reference counted (%d).",
+                        k,psMemGetRefCounter(item));
+                return testNum;
+            }
+
+            found[*item] = true;
+        }
+
+        // check that all the items in psHash was found
+        for (int j = 0; j < i; j++) {
+            testNum++;
+            if (! found[j]) {
+                printIntArray("array",array);
+                psError(PS_ERR_UNKNOWN, true,
+                        "Item %d not found in array.",
+                        j);
+                return testNum;
+            }
+        }
+
+        psFree(array);
+
+        // add one element
+        int* value = psAlloc(sizeof(int));
+        *value = i;
+        psHashAdd(hash, key, value);
+        *key += 1; // increment the key value
+
+        psFree(value);
+    }
+
+    psFree(hash);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error.");
+    array = psHashToArray(NULL);
+    testNum++;
+    if (array != NULL) {
+        printIntArray("array",array);
+        psError(PS_ERR_UNKNOWN, false,
+                "psHashToArray returned non-null psArray given a null psHash.");
+        return testNum;
+    }
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psList.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psList.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psList.c	(revision 22158)
@@ -0,0 +1,1320 @@
+/** @file  tst_psList.c
+ *
+ *  @brief Contains the tests for psList.[ch]
+ *
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-09-26 01:47:22 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include "psTest.h"
+#include "pslib_strict.h"
+
+void printListInt(psList* list);
+
+
+static psS32 testListAlloc(void);
+static psS32 testListAdd(void);
+static psS32 testListGet(void);
+static psS32 testListRemove(void);
+static psS32 testListConvert(void);
+static psS32 testListIterator(void);
+static psS32 testListFree(void);
+static psS32 testListSort(void);
+static psS32 testListAddAfter(void);
+static psS32 testListAddBefore(void);
+static psS32 testListLength(void);
+
+testDescription tests[] = {
+                              {testListAlloc,487,"psListAlloc",0,false},
+                              {testListAdd,488,"psListAdd",0,false},
+                              {testListGet,489,"psListGet",0,false},
+                              {testListRemove,490,"psListRemove",0,false},
+                              {testListConvert,491,"psListConvert",0,false},
+                              {testListIterator,494,"psListIterator",0,false},
+                              {testListFree,627,"psListFree",0,false},
+                              {testListSort,624,"psListSort",0,false},
+                              {testListAddAfter,811,"psListAddAfter",0,false},
+                              {testListAddBefore,811,"psListAddBefore",0,false},
+                              {testListLength,666,"testListLength",0,false},
+                              {NULL}
+                          };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    if (! runTestSuite(stderr,"psList",tests,argc,argv) ) {
+        psError(PS_ERR_UNKNOWN,true,"One or more tests failed");
+        return 1;
+    }
+    return 0;
+}
+
+psS32 testListAlloc(void)
+{
+    psList* list;
+    psS32 ref;
+    float* data;
+
+    psLogMsg(__func__,PS_LOG_INFO,"psListAlloc shall create a psList with either 0 or 1 element.");
+
+    data = psAlloc(sizeof(float));
+
+    // if psListAlloc is invoked with a NULL parameter, it shall return an
+    // empty psList struct with head=tail=NULL and n=0. Otherwise, it shall
+    // return a psList of one element (head=tail=data, n=1).
+    // Test requirement SDR-167
+    list = psListAlloc(NULL);
+    if (list == NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psListAlloc failed to return a list.");
+        return 1;
+    }
+    if (list->head != NULL || list->tail != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"head and/or tail was not NULL for empty list.");
+        return 2;
+    }
+    if (list->n != 0) {
+        psError(PS_ERR_UNKNOWN, true,"size of list wasn't zero for empty list.");
+        return 3;
+    }
+
+    psFree(list);
+
+    // Test requirement SDR-165
+    list = psListAlloc(data);
+    if (list == NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psListAlloc failed to return a list.");
+        return 4;
+    }
+
+    if (list->head == NULL || list->tail == NULL) {
+        psError(PS_ERR_UNKNOWN, true,"head and/or tail was NULL for one-element new list.");
+        return 5;
+    }
+
+    if (list->head->data != data || list->tail->data != data) {
+        psError(PS_ERR_UNKNOWN, true,"head and/or tail didn't point to data's node for one-element new list.");
+        return 6;
+    }
+
+    if (list->n != 1) {
+        psError(PS_ERR_UNKNOWN, true,"size of list wasn't correctly set for new, one-element list.");
+        return 7;
+    }
+
+    ref = psMemGetRefCounter(data);
+    if (ref != 2) {
+        psError(PS_ERR_UNKNOWN, true,"psList didn't increment reference count of data (%d.",ref);
+        return 8;
+    }
+
+    psFree(list);
+
+    psFree(data);
+
+    return 0;
+}
+
+psS32 testListAddAfter(void)
+{
+    psList* list = NULL;
+    psS32*  data = NULL;
+    psS32*  data1 = NULL;
+    psS32*  data2 = NULL;
+    psListIterator *currentIterator = NULL;
+
+    data = psAlloc(sizeof(psS32));
+    *data = 1;
+    data1 = psAlloc(sizeof(psS32));
+    *data1 = 2;
+    data2 = psAlloc(sizeof(psS32));
+    *data2 = 3;
+
+    list = psListAlloc(data);
+    currentIterator = psListIteratorAlloc(list,PS_LIST_HEAD,true);
+
+    // Add data after HEAD and verify data
+    // Test requirement SDR-755
+    if(!psListAddAfter(currentIterator,data1)) {
+        psError(PS_ERR_UNKNOWN,true,"psListAddAfter failed to add item");
+        return 1;
+    }
+    if(*(psS32*)list->head->next->data != 2) {
+        psError(PS_ERR_UNKNOWN,true,"psListAddAfter did not add the item properly");
+        return 2;
+    }
+    // Test requirement SDR-175
+    if (psMemGetRefCounter(data1) != 2) {
+        psError(PS_ERR_UNKNOWN, true,"psListAddAfter didn't increment the data reference count.");
+        return 20;
+    }
+    psFree(currentIterator);
+
+    currentIterator = psListIteratorAlloc(list,PS_LIST_TAIL,true);
+
+    // Add data after TAIL and verify data
+    if(!psListAddAfter(currentIterator,data2)) {
+        psError(PS_ERR_UNKNOWN,true,"psListAddAfter failed to add item");
+        return 3;
+    }
+    if(*(psS32*)list->tail->data != 3) {
+        psError(PS_ERR_UNKNOWN,true,"psListAddAfter did not add the item properly");
+        return 4;
+    }
+    // Test requirement SDR-175
+    if (psMemGetRefCounter(data2) != 2) {
+        psError(PS_ERR_UNKNOWN, true,"psListAddAfter didn't increment the data reference count.");
+        return 40;
+    }
+
+    // Verify error message generated with data pointer is NULL
+    psLogMsg(__func__,PS_LOG_INFO,"NULL data pointer should generate error message");
+    if(psListAddAfter(currentIterator,NULL)) {
+        psError(PS_ERR_UNKNOWN,true,"psListAddAfter should have generated error.");
+        return 5;
+    }
+
+    // Verify error message generated with iterator NULL
+    psLogMsg(__func__,PS_LOG_INFO,"NULL iterator should generate error message");
+    if(psListAddAfter(NULL,data2)) {
+        psError(PS_ERR_UNKNOWN,true,"psListAddAfter should have generated error.");
+        return 6;
+    }
+
+    // Verify error message is generate with non-mutable iterator
+    psLogMsg(__func__,PS_LOG_INFO,"Non-mutable list should generate error message");
+    currentIterator->mutable = false;
+    if(psListAddAfter(currentIterator,data2)) {
+        psError(PS_ERR_UNKNOWN,true,"psListAddAfter should have generated error for non-mutable list add");
+        return 7;
+    }
+    currentIterator->mutable = true;
+
+    psFree(data);
+    psFree(data1);
+    psFree(data2);
+    psFree(list);
+
+    return 0;
+}
+
+psS32 testListAddBefore(void)
+{
+    psList* list = NULL;
+    psS32*  data1 = NULL;
+    psS32*  data2 = NULL;
+    psListIterator *currentIterator = NULL;
+
+    data1 = psAlloc(sizeof(psS32));
+    *data1 = 2;
+    data2 = psAlloc(sizeof(psS32));
+    *data2 = 3;
+
+    list = psListAlloc(NULL);
+    currentIterator = psListIteratorAlloc(list,PS_LIST_HEAD,true);
+
+    // Add data before HEAD and verify data
+    // Test requirement SDR-756
+    if(!psListAddBefore(currentIterator,data1)) {
+        psError(PS_ERR_UNKNOWN,true,"psListAddBefore failed to add item");
+        return 1;
+    }
+    if(*(psS32*)list->head->data != 2) {
+        psError(PS_ERR_UNKNOWN,true,"psListAddBefore did not add the item properly");
+        return 2;
+    }
+    // Test requirement SDR-175
+    if (psMemGetRefCounter(data1) != 2) {
+        psError(PS_ERR_UNKNOWN, true,"psListAddBefore didn't increment the data reference count.");
+        return 20;
+    }
+    psFree(currentIterator);
+
+    currentIterator = psListIteratorAlloc(list,PS_LIST_TAIL,true);
+
+    // Add data after TAIL and verify data
+    if(!psListAddBefore(currentIterator,data2)) {
+        psError(PS_ERR_UNKNOWN,true,"psListAddBefore failed to add item");
+        return 3;
+    }
+    if(*(psS32*)list->tail->prev->data != 3) {
+        psError(PS_ERR_UNKNOWN,true,"psListAddBefore did not add the item properly");
+        return 4;
+    }
+    // Test requirement SDR-175
+    if (psMemGetRefCounter(data2) != 2) {
+        psError(PS_ERR_UNKNOWN, true,"psListAddBefore didn't increment the data reference count.");
+        return 40;
+    }
+
+    // Verify error message generated with data pointer is NULL
+    psLogMsg(__func__,PS_LOG_INFO,"NULL data pointer should generate error message");
+    if(psListAddBefore(currentIterator,NULL)) {
+        psError(PS_ERR_UNKNOWN,true,"psListAddBefore should have generated error.");
+        return 5;
+    }
+
+    // Verify error message generated with iterator NULL
+    psLogMsg(__func__,PS_LOG_INFO,"NULL iterator should generate error message");
+    if(psListAddBefore(NULL,data2)) {
+        psError(PS_ERR_UNKNOWN,true,"psListAddBefore should have generated error.");
+        return 6;
+    }
+
+    // Verify error message is generate with non-mutable iterator
+    psLogMsg(__func__,PS_LOG_INFO,"Non-mutable list should generate error message");
+    currentIterator->mutable = false;
+    if(psListAddBefore(currentIterator,data2)) {
+        psError(PS_ERR_UNKNOWN,true,"psListAddBefore should have generated error for non-mutable list add");
+        return 7;
+    }
+    currentIterator->mutable = true;
+
+    psFree(data1);
+    psFree(data2);
+    psFree(list);
+
+    return 0;
+}
+
+psS32 testListAdd(void)
+{
+    psList* list = NULL;
+    psS32* data = NULL;
+
+    psLogMsg(__func__,PS_LOG_INFO,"psListAdd shall add an element to list");
+
+    /*
+        psListAdd(list,data,where) should be tested in the instance where:
+
+        1. list is NULL (error)
+        2. data is NULL (error, list should not grow)
+        3. where is PS_LIST_HEAD or PS_LIST_TAIL
+        4. where is not PS_LIST_* but <0
+        5. where is >0
+    */
+
+    data = psAlloc(sizeof(psS32));
+    *data = 1;
+
+    //  1. list is NULL (error)
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for using NULL list.");
+    if (psListAdd(NULL,PS_LIST_HEAD,data)) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd was given a NULL list, but returned a true/success.");
+        return 1;
+    }
+
+    list = psListAlloc(data);
+    psFree(data);
+    if (list->n != 1) {
+        psError(PS_ERR_UNKNOWN, true,"psListAlloc didn't create a list properly.");
+        return 2;
+    }
+
+    //  2. data is NULL (error, list should not grow)
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error msg to add NULL data");
+    if (psListAdd(list, PS_LIST_HEAD,NULL)) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd successfully added a NULL data item?");
+        return 40;
+    }
+    if ( list->n != 1) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd with a NULL data element changed the list size or returned success.");
+        return 3;
+    }
+
+    //  3. where is PS_LIST_HEAD or PS_LIST_TAIL
+    data = psAlloc(sizeof(psS32));
+    *data = 2;
+    if ( ! psListAdd(list,PS_LIST_HEAD,data) ) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd failed to add a data item to head.");
+        return 21;
+    }
+    // Test requirement SDR-175
+    if (psMemGetRefCounter(data) != 2) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd didn't increment the data reference count.");
+        return 20;
+    }
+    psFree(data);
+
+    // verify that the size incremented
+    if (list->n != 2) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd didn't increment the size by one");
+        return 4;
+    }
+
+    // verify that the head is the inserted data item
+    if (*(psS32*)list->head->data != 2) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd with PS_LIST_HEAD didn't insert at the head.");
+        return 5;
+    }
+
+    data = psAlloc(sizeof(psS32));
+    *data = 3;
+    if ( ! psListAdd(list,PS_LIST_TAIL,data) ) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd failed to add a data item to tail.");
+        return 21;
+    }
+    // Test requirement SDR-175
+    if (psMemGetRefCounter(data) != 2) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd didn't increment the data reference count.");
+        return 22;
+    }
+    psFree(data);
+    // verify that the size incremented
+    if (list->n != 3) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd didn't increment the size by 1");
+        return 6;
+    }
+
+    // verify that the head is still the same
+    if (*(psS32*)list->head->data != 2) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd with PS_LIST_TAIL modified the head.");
+        return 7;
+    }
+
+    // verify that the tail is the data item inserted
+    if (*(psS32*)list->tail->data != 3) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd with PS_LIST_TAIL didn't insert at the tail.");
+        return 8;
+    }
+
+    // 4. where is not PS_LIST_* but <0
+
+    data = psAlloc(sizeof(psS32));
+    *data = 4;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should error with invalid insert location");
+
+    if ( psListAdd(list,-10,data) ) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd successfully added data to a -10 position?");
+        return 30;
+    }
+    // Test requirement SDR-175
+    if (psMemGetRefCounter(data) != 1) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd incremented the data reference count.");
+        return 24;
+    }
+    psFree(data);
+    // verify that the size wasn't incremented
+    if (list->n != 3) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"psListAdd didn't insert to head when where was invalid.");
+        return 9;
+    }
+
+    // 5. where is >0
+    data = psAlloc(sizeof(psS32));
+    *data = 5;
+
+    if ( ! psListAdd(list,1,data) ) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd failed to add data to 1 position.");
+        return 30;
+    }
+    // Test requirement SDR-175
+    if (psMemGetRefCounter(data) != 2) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd didn't increment the data reference count.");
+        return 25;
+    }
+    psFree(data);
+    // verify that the size incremented
+    if (list->n != 4 || *(psS32*)list->head->next->data != 5) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"psListAdd didn't insert to position #1.");
+        return 10;
+    }
+
+    data = psAlloc(sizeof(psS32));
+    *data = 6;
+    if ( ! psListAdd(list,3,data) ) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd failed to add data to 4 position.");
+        return 31;
+    }
+    // Test requirment SDR-175
+    if (psMemGetRefCounter(data) != 2) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd didn't increment the data reference count.");
+        return 26;
+    }
+    psFree(data);
+    // verify that the size incremented
+    if (list->n != 5  || *(psS32 *)list->head->next->next->next->data != 6) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"psListAdd didn't insert to position #4.");
+        return 50;
+    }
+
+    data = psAlloc(sizeof(psS32));
+    *data = 7;
+    // Test requirment SDR-169
+    if ( ! psListAdd(list,-2,data) ) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd failed to add data to 2 position.");
+        return 32;
+    }
+
+    // Test requirment SDR-175
+    if (psMemGetRefCounter(data) != 2) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd didn't increment the data reference count.");
+        return 28;
+    }
+    psFree(data);
+    // verify that the size incremented
+    if (list->n != 6  || *(psS32 *)list->tail->prev->prev->data != 7) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"psListAdd didn't insert to position #2.");
+        return 11;
+    }
+
+    // Test requirement SDR-757
+    data = psAlloc(sizeof(psS32));
+    *data = 8;
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be a warning.");
+
+    if ( ! psListAdd(list,9,data) ) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd failed to add data to a 9 position?");
+        return 30;
+    }
+    // Test requirment SDR-175
+    if (psMemGetRefCounter(data) != 2) {
+        psError(PS_ERR_UNKNOWN, true,"psListAdd didn't increment the data reference count.");
+        return 29;
+    }
+    if(list->n != 7 || *(psS32 *)list->tail->data != 8) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN,true,"psListAdd didn't place added item at tail.");
+        return 12;
+    }
+
+    psFree(data);
+
+    psFree(list);
+
+    return 0;
+}
+
+void printListInt(psList* list)
+{
+    psS32* data = NULL;
+    psBool first = true;
+
+    psListIterator* iter = psListIteratorAlloc(list,PS_LIST_HEAD,true);
+
+    while ( (data=(psS32*)psListGetAndIncrement(iter)) != NULL ) {
+        if (!first) {
+            printf(", %d",*(psS32*)data);
+        } else {
+            printf("%d",*(psS32*)data);
+            first = false;
+        }
+    }
+
+    printf(".\n");
+}
+
+
+psS32 testListGet(void)
+{
+    psList* list = NULL;
+    psS32* data;
+
+    /*
+     psListGet(list,which) shall be tested with the following instances
+
+        1. list is NULL.
+        2. which>0 and which<list.n.
+        3. which>list.n.
+        4. which=PS_LIST_HEAD
+        5. which=PS_LIST_NEXT
+        6. which=PS_LIST_TAIL
+        7. which=PS_LIST_PREV
+        8. which<0 and not any PS_LIST_* values
+    */
+
+    //  1. list is NULL.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error");
+    if (psListGet(list,PS_LIST_HEAD) != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psListGet didn't return NULL given a NULL list.");
+        return 1;
+    };
+
+    // create a list
+    data = psAlloc(sizeof(psS32));
+    *data = 0;
+    list = psListAlloc(data);
+    psFree(data);
+
+    data = psAlloc(sizeof(psS32));
+    *data = 1;
+    psListAdd(list,PS_LIST_TAIL,data);
+    psFree(data);
+
+    data = psAlloc(sizeof(psS32));
+    *data = 2;
+    psListAdd(list,PS_LIST_TAIL,data);
+    psFree(data);
+
+    data = psAlloc(sizeof(psS32));
+    *data = 3;
+    psListAdd(list,PS_LIST_TAIL,data);
+    psFree(data);
+
+    //  2. which>0 and which<list.n.
+    data = (psS32*)psListGet(list,3);
+    if (data == NULL || *data != 3) {
+        psError(PS_ERR_UNKNOWN, true,"psListGet failed with which=3");
+        return 2;
+    }
+    data = (psS32*)psListGet(list,1);
+    if (data == NULL || *data != 1) {
+        psError(PS_ERR_UNKNOWN, true,"psListGet failed with which=1");
+        return 3;
+    }
+
+    //  3. which>=list.n.
+    data = (psS32*)psListGet(list,5);
+    if (data != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psListGet failed with which=5");
+        return 4;
+    }
+    data = (psS32*)psListGet(list,4);
+    if (data != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psListGet failed with which=4");
+        return 5;
+    }
+
+    //  4. which=PS_LIST_HEAD
+    data = (psS32*)psListGet(list,PS_LIST_HEAD);
+    if (data == NULL || *data != 0) {
+        psError(PS_ERR_UNKNOWN, true,"psListGet failed with which=PS_LIST_HEAD");
+        return 6;
+    }
+
+    //  6. which=PS_LIST_TAIL
+    data = (psS32*)psListGet(list,PS_LIST_TAIL);
+    if (data == NULL || *data != 3) {
+        psError(PS_ERR_UNKNOWN, true,"psListGet failed with which=PS_LIST_TAIL");
+        return 8;
+    }
+
+    data = (psS32*)psListGet(list,-2);
+    if (data == NULL || *data !=2) {
+        psError(PS_ERR_UNKNOWN,true,"psListGet failed with location=-2");
+        return 9;
+    }
+
+    psFree(list);
+
+    return 0;
+}
+
+psS32 testListRemove(void)
+{
+    psList* list = NULL;
+    psS32* data;
+    int items = 15;
+
+    /*
+        psListRemove(list,data,which) should be tested under the following conditions:
+
+        1. list is NULL
+        2. which is PS_LIST_HEAD (remove first element of list)
+        3. which is PS_LIST_TAIL (remove last element of list)
+        4. which is PS_LIST_NEXT (element right of cursor [which should be head,tail, and neither])
+        5. which is PS_LIST_PREV (element left of cursor [which should be head,tail, and neither])
+        6. which is PS_LIST_UNKNOWN and data=NULL (error)
+        7. which is PS_LIST_UNKNOWN and data=[head,tail,other list items]
+        8. which is PS_LIST_UNKNOWN and data!=NULL and data!=any element in list
+
+        In all conditions that are not an error, list.n shall be decremented and only the specified element
+        shall be removed. After each step, list.n should be checked to verify that it is the true
+        number of elements in list.
+    */
+
+    //  1. list is NULL.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error");
+    if (psListRemove(list,PS_LIST_HEAD)) {
+        psError(PS_ERR_UNKNOWN, true,"psListRemove didn't return false given a NULL list.");
+        return 1;
+    };
+
+    // create a list
+    list = psListAlloc(NULL);
+
+    for (psS32 lcv=0;lcv<items;lcv++) {
+        data = psAlloc(sizeof(psS32));
+        *data = lcv;
+        psListAdd(list,PS_LIST_TAIL,data);
+        psMemDecrRefCounter(data);
+    }
+
+
+    // 2. which is PS_LIST_HEAD (remove first element of list)
+    psS32* data1 = (psS32 *)psListGet(list,PS_LIST_HEAD);
+    psMemIncrRefCounter(data1);
+    // Test requirement SDR-172, SDR-173
+    if ( (! psListRemove(list,PS_LIST_HEAD)) ||
+            (psListGet(list,PS_LIST_HEAD) == data) ) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"Failed to remove PS_LIST_HEAD");
+        return 1;
+    }
+
+    if (list->n != --items) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"Didn't decrement size properly to %d.",items);
+        return 1;
+    }
+    // Test requirement SDR-176
+    if (psMemGetRefCounter(data1) != 1) {
+        psError(PS_ERR_UNKNOWN, true,"psListRemove didn't decrement the data reference count.");
+        return 20;
+    }
+    psMemDecrRefCounter(data1);
+
+    // 3. which is PS_LIST_TAIL (remove last element of list)
+    data = psListGet(list,PS_LIST_TAIL);
+    // Test requirement SDR-173
+    if ( (! psListRemove(list,PS_LIST_TAIL)) ||
+            (psListGet(list,PS_LIST_TAIL) == data) ) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"Failed to remove PS_LIST_TAIL");
+        return 1;
+    }
+
+    if (list->n != --items) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"Didn't decrement size properly to %d.",items);
+        return 1;
+    }
+
+    data = psListGet(list,-2);
+    // Test requirement SDR-173
+    if ( (! psListRemove(list,-2)) ||
+            (psListGet(list,-2) == data) ) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"Failed to remove from location -2");
+        return 11;
+    }
+
+    if (list->n != --items) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"Didn't decrement size properly to %d.",items);
+        return 1;
+    }
+
+    // 6. psListRemoveData where data=NULL (error)
+    psLogMsg(__func__,PS_LOG_INFO,"Next message should be an error");
+    if (psListRemoveData(list,NULL)) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"removed something for PS_LIST_UNKNOWN with data=NULL");
+        return 1;
+    }
+
+    // 7. which is PS_LIST_UNKNOWN and data=[head,tail,other list items]
+    data = psListGet(list,PS_LIST_HEAD);
+    // Test requirement SDR-762
+    if ( (! psListRemoveData(list,data)) ||
+            (psListGet(list,PS_LIST_HEAD) == data) ) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"Failed to remove PS_LIST_UNKNOWN @ PS_LIST_HEAD");
+        return 1;
+    }
+
+    if (list->n != --items) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"Didn't decrement size properly to %d.",items);
+        return 1;
+    }
+
+    psS32* data2 = psListGet(list,PS_LIST_TAIL);
+    psMemIncrRefCounter(data2);
+    if ( (!psListRemoveData(list,data2)) ||
+            (psListGet(list,PS_LIST_TAIL) == data2) ) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"Failed to remove PS_LIST_UNKNOWN @ PS_LIST_TAIL");
+        return 1;
+    }
+
+    if (list->n != --items) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"Didn't decrement size properly to %d.",items);
+        return 1;
+    }
+    // Test requirement SDR-176
+    if (psMemGetRefCounter(data2) != 1) {
+        psError(PS_ERR_UNKNOWN, true,"psListRemoveData didn't decrement the data reference count.");
+        return 20;
+    }
+    psMemDecrRefCounter(data2);
+
+    data = psListGet(list,1);
+    if ( (! psListRemoveData(list,data))||
+            (psListGet(list,1) == data) ) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"Failed to remove data @ which=1");
+        return 1;
+    }
+
+    if (list->n != --items) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"Didn't decrement size properly to %d.",items);
+        return 1;
+    }
+
+    // 8. data!=NULL and data!=any element in list
+    psLogMsg(__func__,PS_LOG_INFO,"Next message should be an error");
+    // Test requirement SDR-764
+    if ( psListRemoveData(list,data) ) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"removed something for PS_LIST_UNKNOWN with previously removed item");
+        return 1;
+    }
+
+    if (list->n != items) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"size not %d, as expected.",items);
+        return 1;
+    }
+
+    // clear out the list
+    while (items > 1) {
+        psListRemove(list,PS_LIST_HEAD);
+        items--;
+    }
+
+    data = psListGet(list,PS_LIST_HEAD);
+    if ( (! psListRemove(list,PS_LIST_HEAD)) ||
+            (psListGet(list,PS_LIST_HEAD) == data) ) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"Failed to remove last element");
+        return 1;
+    }
+
+    if (list->n != 0) {
+        printListInt(list);
+        psError(PS_ERR_UNKNOWN, true,"Didn't remove all the elements.");
+        return 1;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"NULL list in psListRemoveData should generate error message.");
+    if(psListRemoveData(NULL,data)) {
+        psError(PS_ERR_UNKNOWN,true,"psListRemoveData should have generated an error with NULL list");
+        return 2;
+    }
+
+    psFree(list);
+
+    return 0;
+
+}
+
+psS32 testListConvert(void)
+{
+
+    psList* list = NULL;
+    psArray* arr = NULL;
+    psS32* data;
+
+    /*
+        array=psListToArray(list) shall take each element of the list, increment
+        their reference, and insert them into the returned fresh psPtr array.
+        The list shall not be changed, except for the element reference increment.
+    */
+
+    // test dlist -> array
+
+    // create a list
+    list = psListAlloc(NULL);
+    for (psS32 lcv=0;lcv<15;lcv++) {
+        data = psAlloc(sizeof(psS32));
+        *data = lcv;
+        psListAdd(list,PS_LIST_TAIL,data);
+        psMemDecrRefCounter(data);
+    }
+
+    arr = psListToArray(list);
+
+    if (arr->n != 15 || list->n != 15) {
+        psError(PS_ERR_UNKNOWN, true,"The created array didn't have the proper size");
+        return 1;
+    }
+    for (psS32 i=0;i<arr->n;i++) {
+        if (i != *(psS32*)arr->data[i]) {
+            psError(PS_ERR_UNKNOWN, true,"Element %d of array is incorrect (%d).",
+                    i,*(psS32*)arr->data[i]);
+            return 1;
+        }
+        if (i != *(psS32*)psListGet(list,i)) {
+            psError(PS_ERR_UNKNOWN, true,"Element %d of list is incorrect (%d).",
+                    i,*(psS32*)arr->data[i]);
+            return 1;
+        }
+        if (psMemGetRefCounter(arr->data[i]) != 2) {
+            psError(PS_ERR_UNKNOWN, true,"Element %d had wrong reference count (%ld).",
+                    i,psMemGetRefCounter(arr->data[i]));
+            return 1;
+        }
+    }
+
+    psFree(arr);
+    psFree(list);
+
+    // test array -> dlist
+
+    // create an array
+    arr = psArrayAlloc(15);
+    arr->n = arr->nalloc;
+    for (psS32 lcv=0;lcv<15;lcv++) {
+        data = psAlloc(sizeof(psS32));
+        *data = lcv;
+        arr->data[lcv] = data;
+    }
+
+    list = psArrayToList(arr);
+
+    if (arr->n != 15 || list->n != 15) {
+        psError(PS_ERR_UNKNOWN, true,"The created array didn't have the proper size");
+        return 1;
+    }
+    for (psS32 i=0;i<arr->n;i++) {
+        if (i != *(psS32*)arr->data[i]) {
+            psError(PS_ERR_UNKNOWN, true,"Element %d of array is incorrect (%d).",
+                    i,*(psS32*)arr->data[i]);
+            return 1;
+        }
+        if (i != *(psS32*)psListGet(list,i)) {
+            psError(PS_ERR_UNKNOWN, true,"Element %d of list is incorrect (%d).",
+                    i,*(psS32*)arr->data[i]);
+            return 1;
+        }
+        if (psMemGetRefCounter(arr->data[i]) != 2) {
+            psError(PS_ERR_UNKNOWN, true,"Element %d had wrong reference count (%ld).",
+                    i,psMemGetRefCounter(arr->data[i]));
+            return 1;
+        }
+    }
+
+    psFree(arr);
+    psFree(list);
+
+    // now, make sure if input array/list is NULL, output is NULL
+
+    arr = psListToArray(NULL);
+    if (arr != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psListToArray didn't return NULL when given NULL");
+        return 1;
+    }
+
+    list = psArrayToList(NULL);
+    if (list != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psArrayToList didn't return NULL when given NULL");
+        return 1;
+    }
+
+    // now, see what happens with a zero-size array/list
+    arr = psArrayAlloc(1);
+    arr->n = 0;
+    list = psArrayToList(arr);
+    if (list == NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psArrayToList didn't create an empty list from an "
+                "empty array.");
+        return 1;
+    }
+    psFree(arr);
+    psFree(list);
+
+    list = psListAlloc(NULL);
+    arr = psListToArray(list);
+    if (arr == NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psArrayToList didn't create an empty array from an "
+                "empty list.");
+        return 1;
+    }
+    psFree(arr);
+    psFree(list);
+
+    return 0;
+}
+
+psS32 testListIterator(void)
+{
+    psList* list = NULL;
+    psS32* data;
+
+    psLogMsg(__func__,PS_LOG_INFO," psListSetIterator/psListGetNext/psListGetPrev"
+             " shall move the list cursor to the specified location");
+
+    /*
+            psDlistSetIterator(list,where) shall:
+
+            1. output error message and do nothing if list=NULL
+            2. set list.cursor to list.head if where=PS_LIST_HEAD
+            3. set list.cursor to list.tail if where=PS_LIST_TAIL
+            4. set list.cursor to list.cursor->next if where=PS_LIST_NEXT
+            5. set list.cursor to list.cursor->prev if where=PS_LIST_PREV
+            6. leave list.cursor untouched if where=PS_LIST_UNKNOWN or PS_LIST_CURRENT
+
+            psDlistGetNext(list) shall be functionally equivalent to
+            psDlistSetIterator(list,PS_LIST_NEXT) but returns list.cursor.
+
+            psDlistGetPrev(list) shall be functionally equivalent to
+            psDlistSetIterator(list,PS_LIST_PREV) but returns list.cursor.
+    */
+
+    // create a list
+    list = psListAlloc(NULL);
+    for (psS32 lcv=0;lcv<15;lcv++) {
+        data = psAlloc(sizeof(psS32));
+        *data = lcv;
+        psListAdd(list,PS_LIST_TAIL,data);
+        psFree(data);
+    }
+
+    psListIterator* iter = psListIteratorAlloc(list,PS_LIST_HEAD,true);
+    if (iter == NULL) {
+        psError(PS_ERR_UNKNOWN, true,"Failed to make an iterator.");
+        return 22;
+    }
+
+    // 1. output error message and do nothing if iterator=NULL
+    psListIteratorSet(NULL,PS_LIST_HEAD);
+    if (psListIteratorSet(NULL,PS_LIST_HEAD)) {
+        psError(PS_ERR_UNKNOWN, true,"Success while setting position of a NULL iterator?");
+        return 23;
+    }
+
+    // Attempt to get next with NULL iterator
+    if ( psListGetAndIncrement(NULL) != NULL ) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL when NULL iterator specified");
+        return 24;
+    }
+
+    // Attempt to get previous with NULL iterator
+    if( psListGetAndDecrement(NULL) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL when NULL iterator specified");
+        return 25;
+    }
+
+    // 3. set list.cursor to list.tail if where=PS_LIST_TAIL
+
+    if (!psListIteratorSet(iter,PS_LIST_TAIL) ||
+            *(psS32*)iter->cursor->data != 14 ||
+            iter->index != 14) {
+        psError(PS_ERR_UNKNOWN, true,"Didn't successfully move cursor to tail.");
+        return 1;
+    }
+
+    // 2. set list.cursor to list.head if where=PS_LIST_HEAD
+    if (!psListIteratorSet(iter,PS_LIST_HEAD) ||
+            *(psS32*)iter->cursor->data != 0 ||
+            iter->index != 0) {
+        psError(PS_ERR_UNKNOWN, true,"Didn't successfully move cursor to head.");
+        return 2;
+    }
+
+    // test psListGetPrevious/Next
+    if (*(psS32*)psListGetAndIncrement(iter) != 0) {
+        psError(PS_ERR_UNKNOWN, true,"psListGetNext didn't move cursor to next.");
+        return 8;
+    }
+    if (*(psS32*)psListGetAndIncrement(iter) != 1) {
+        psError(PS_ERR_UNKNOWN, true,"psListGetNext didn't move cursor to next.");
+        return 9;
+    }
+    if (*(psS32*)psListGetAndIncrement(iter) != 2) {
+        psError(PS_ERR_UNKNOWN, true,"psListGetNext didn't move cursor to next.");
+        return 10;
+    }
+
+    if (*(psS32*)psListGetAndDecrement(iter) != 3) {
+        psError(PS_ERR_UNKNOWN, true,"psListGetPrevious didn't move cursor to previous.");
+        return 11;
+    }
+    if (*(psS32*)psListGetAndDecrement(iter) != 2) {
+        psError(PS_ERR_UNKNOWN, true,"psListGetPrevious didn't move cursor to previous.");
+        return 12;
+    }
+    if (*(psS32*)psListGetAndDecrement(iter) != 1) {
+        psError(PS_ERR_UNKNOWN, true,"psListGetPrevious didn't move cursor to previous..");
+        return 13;
+    }
+    if (*(psS32*)psListGetAndDecrement(iter) != 0) {
+        psError(PS_ERR_UNKNOWN, true,"psListGetPrevious didn't move cursor to previous..");
+        return 14;
+    }
+    if (psListGetAndDecrement(iter) != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psListGetPrevious moved cursor beyond head.");
+        return 15;
+    }
+    if (psListGetAndIncrement(iter) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psListGetNext should return NULL when above head");
+        return 22;
+    }
+    if (*(psS32*)psListGetAndIncrement(iter) != 0 ) {
+        psError(PS_ERR_UNKNOWN,true,"psListGetNext didn't move cursor to next.");
+        return 23;
+    }
+
+    psListIteratorSet(iter,PS_LIST_TAIL); // works according to an above test
+    if (*(psS32*)psListGetAndIncrement(iter) != 14) {
+        psError(PS_ERR_UNKNOWN, true,"psListGetNext moved cursor beyond tail.");
+        return 16;
+    }
+    if ((psListGetAndIncrement(iter) != NULL) || (!iter->offEnd)) {
+        psError(PS_ERR_UNKNOWN, true,"psListGetNext moved cursor beyond tail.");
+        return 17;
+    }
+    if(psListGetAndDecrement(iter) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"psListGetPrevious did not return NULL when offEnd is true");
+        return 18;
+    }
+    if(iter->offEnd) {
+        psError(PS_ERR_UNKNOWN,true,"psListGetPrevious did not move back onto the list.");
+        return 19;
+    }
+    if(*(psS32*)psListGetAndDecrement(iter) != 14) {
+        psError(PS_ERR_UNKNOWN,true,"psListGetPrevious did not return correct value of tail.");
+        return 20;
+    }
+
+    psFree(list);
+
+    return 0;
+}
+
+psS32 testListFree(void)
+{
+    float* data[15];
+    psList* list;
+
+    /*
+    Call psDlistAlloc to create a doubly linked list.
+
+    Create several data items and add them to the list.
+
+    Verify the data item's reference counter are incremented after adding to the list.
+    (not really needed, as psListAdd is tested elsewhere)
+    */
+
+    list = psListAlloc(NULL);
+    for (psS32 lcv=0;lcv<15;lcv++) {
+        data[lcv] = psAlloc(sizeof(psS32));
+        *data[lcv] = lcv;
+        psListAdd(list,PS_LIST_TAIL,data[lcv]);
+        if (psMemGetRefCounter(data[lcv]) != 2) {
+            psError(PS_ERR_UNKNOWN, true,"Reference counter for data was not incremented");
+            return 1;
+        }
+    }
+
+    /*
+    Verify items are within the list.
+    (not needed, as psListAdd is tested elsewhere, but check anyway.)
+    */
+    if (list->n != 15) {
+        psError(PS_ERR_UNKNOWN, true,"List wasn't populated as expected?");
+        return 2;
+    }
+
+    /*
+    Call psDlistFree with NULL specified as the elemFree function.
+    */
+
+    psFree(list);
+
+    /*
+    Verify the list is deallocated but not the data items.
+    (accomplished by checking for memory leaks)
+
+    Verify the data item's reference counters are decremented by one compared to when added to the list.
+    (technically, this could be accomplished by checking memory leaks too, but I checked anyway)
+    */
+
+    for (psS32 i=0;i<15;i++) {
+        if (psMemGetRefCounter(data[i]) != 1) {
+            psError(PS_ERR_UNKNOWN, true,"pslistFree didn't decrement the data item's reference counter");
+            return 3;
+        }
+        psFree(data[i]);
+    }
+
+    return 0;
+}
+
+psS32 testListSort(void)
+{
+    psList* list;
+    psListIterator* iter;
+    float* fValue;
+    psU32* uValue;
+
+    list = psListAlloc(NULL);
+
+    for (psS32 lcv=0;lcv<15;lcv++) {
+        float* data = psAlloc(sizeof(psS32));
+        if (lcv < 7) {
+            *data = 13-lcv*2;
+        } else {
+            *data = lcv*2-12;
+        }
+        psListAdd(list,PS_LIST_TAIL,data);
+        psFree(data);
+
+    }
+
+    printf("original list = [");
+    iter = psListIteratorAlloc(list,PS_LIST_HEAD,true);
+    while( (fValue=psListGetAndIncrement(iter)) != NULL ) {
+        printf(" %.1f",*fValue);
+    }
+    printf(" ]\n");
+
+    list = psListSort(list,psCompareF32Ptr);
+
+    printf("sorted list = [");
+    psListIteratorSet(iter,PS_LIST_HEAD);
+    while( (fValue=psListGetAndIncrement(iter)) != NULL ) {
+        printf(" %.1f",*fValue);
+    }
+    printf(" ]\n");
+
+    psListIteratorSet(iter,PS_LIST_HEAD);
+    float* prevFValue = psListGetAndIncrement(iter);
+    while( (fValue=psListGetAndIncrement(iter)) != NULL ) {
+        if (*prevFValue > *fValue) {
+            psError(PS_ERR_UNKNOWN, true,"Hey, the list wasn't sorted!?");
+            return 1;
+        }
+    }
+
+    list = psListSort(list,psCompareDescendingF32Ptr);
+
+    printf("descending sort list = [");
+    psListIteratorSet(iter,PS_LIST_HEAD);
+    while( (fValue=psListGetAndIncrement(iter)) != NULL ) {
+        printf(" %.1f",*fValue);
+    }
+    printf(" ]\n");
+
+    psListIteratorSet(iter,PS_LIST_HEAD);
+    prevFValue = psListGetAndIncrement(iter);
+    while( (fValue=psListGetAndIncrement(iter)) != NULL ) {
+        if (*prevFValue < *fValue) {
+            psError(PS_ERR_UNKNOWN, true,"Hey, the list wasn't sorted!?");
+            return 2;
+        }
+    }
+
+    psFree(list);
+
+    /********** OK, now do the same thing with ints. *************/
+
+    list = psListAlloc(NULL);
+
+    for (psS32 lcv=0;lcv<15;lcv++) {
+        psU32* data = psAlloc(sizeof(psS32));
+        if (lcv < 7) {
+            *data = 13-lcv*2;
+        } else {
+            *data = lcv*2-12;
+        }
+        psListAdd(list,PS_LIST_TAIL,data);
+        psFree(data);
+
+    }
+
+    printf("original list = [");
+    iter = psListIteratorAlloc(list,PS_LIST_HEAD,true);
+    while( (uValue=psListGetAndIncrement(iter)) != NULL ) {
+        printf(" %d",*uValue);
+    }
+    printf(" ]\n");
+
+    list = psListSort(list,psCompareU32Ptr);
+
+    printf("sorted list = [");
+    psListIteratorSet(iter,PS_LIST_HEAD);
+    while( (uValue=psListGetAndIncrement(iter)) != NULL ) {
+        printf(" %d",*uValue);
+    }
+    printf(" ]\n");
+
+    psListIteratorSet(iter,PS_LIST_HEAD);
+    psU32* prevUValue = psListGetAndIncrement(iter);
+    while( (uValue=psListGetAndIncrement(iter)) != NULL ) {
+        if (*prevUValue > *uValue) {
+            psError(PS_ERR_UNKNOWN, true,"Hey, the list wasn't sorted!?");
+            return 3;
+        }
+    }
+
+    list = psListSort(list,psCompareDescendingU32Ptr);
+
+    printf("descending sort list = [");
+    psListIteratorSet(iter,PS_LIST_HEAD);
+    while( (uValue=psListGetAndIncrement(iter)) != NULL ) {
+        printf(" %d",*uValue);
+    }
+    printf(" ]\n");
+
+    psListIteratorSet(iter,PS_LIST_HEAD);
+    prevUValue = psListGetAndIncrement(iter);
+    while( (uValue=psListGetAndIncrement(iter)) != NULL ) {
+        if (*prevUValue < *uValue) {
+            psError(PS_ERR_UNKNOWN, true,"Hey, the list wasn't sorted!?");
+            return 4;
+        }
+    }
+
+    psFree(list);
+
+    return 0;
+}
+
+psS32 testListLength( void )
+{
+    psArray *temp = psArrayAlloc(5);
+    psList *list = psListAlloc(temp);
+
+    if (psListLength(list) != 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psListLength failed to return the correct length of list.\n");
+        return 1;
+    }
+    list->n = 5;
+    if (psListLength(list) != 5) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psListLength failed to return the correct length of list.\n");
+        return 2;
+    }
+    list->n++;
+    if (psListLength(list) != 6) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psListLength failed to return the correct length of list.\n");
+        return 3;
+    }
+    psFree(temp);
+    psFree(list);
+
+    psList *emptyList = NULL;
+    psVector *vector = psVectorAlloc(5, PS_TYPE_F32);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if (psListLength(emptyList) != -1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psListLength failed to return -1 for a NULL input list.\n");
+        return 4;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if (psListLength((psList*)vector) != -1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psListLength failed to return -1 for an invalid input list.\n");
+        return 5;
+    }
+    psFree(vector);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psLookupTable_01.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psLookupTable_01.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psLookupTable_01.c	(revision 22158)
@@ -0,0 +1,855 @@
+/** @file  tst_psLookupTable_01.c
+*
+*  @brief Test driver for psLookupTable functions
+*
+*  This test driver contains the following tests for psLookupTable functions:
+*     testLookupAlloc - test allocation and freeing of psLookupTable
+*     testLookupRead - test different files and types within files
+*                      being read correctly and some failure cases
+*     testLookupTableInterpolate - test the interpolation function
+*     testLookupTableInterpolateAll - test interpolation of all row values
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.5 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2006-06-13 23:55:34 $
+*
+*  Copyright 2004-5 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include "pslib_strict.h"
+#include "psTest.h"
+#include <string.h>
+
+static psS32 testLookupTableAlloc(void);
+static psS32 testVectorsReadFromFile(void);
+static psS32 testLookupTableImport(void);
+static psS32 testLookupTableRead(void);
+static psS32 testLookupTableInterpolate(void);
+static psS32 testLookupTableInterpolateAll(void);
+
+const psF64 errorTol_psF64 = 1.0e-4;
+const psF64 tableU8_validFrom = 0;
+const psF64 tableU8_validTo = 3;
+const psS32 tableU8_size = 4;
+const char tableU8_format[] = "\%d \%d \%d \%ld \%d \%d \%d \%ld \%f \%lf";
+const char tableU8_filename[] = VERIFIED_DIR "/tableU8.dat";
+const psS32 tableU8_indexCol = 0;
+const psS32 tableU8_index[] =
+    {
+        0,   1,    2,   3
+    };
+const psU16 tableU8_val1[]  =
+    {
+        2,   4,    6,   8
+    };
+const psU32 tableU8_val2[]  =
+    {
+        4,   8,   12,  16
+    };
+const psU64 tableU8_val3[]  =
+    {
+        8,  16,   24,  32
+    };
+const psS8  tableU8_val4[]  =
+    {
+        0,  -1,   -2,  -3
+    };
+const psS16 tableU8_val5[]  =
+    {
+        -2,  -4,   -6,  -8
+    };
+const psS32 tableU8_val6[]  =
+    {
+        -4,  -8,  -12, -16
+    };
+const psS64 tableU8_val7[]  =
+    {
+        -8, -16,  -24, -32
+    };
+const psF32 tableU8_val8[]  =
+    {
+        -0.5, 0.0,  0.5,0.75
+    };
+const psF64 tableU8_val9[]  =
+    {
+        -1.5,-1.0,-0.25,1.75
+    };
+
+const psF64 tableF32_validFrom = -10.05;
+const psF64 tableF32_validTo = 3500.67;
+const psS32 tableF32_size = 4;
+const psS32 tableF32_cols = 9;
+const char tableF32_filename[] = VERIFIED_DIR "/tableF32.dat";
+const char tableF32_format[] = "\%f \%d \%d \%ld \%d \%d \%d \%ld \%d \%lf";
+const char tableF32_indexCol = 0;
+const psElemType tableF32_colType[] =
+    {
+        PS_TYPE_F32, PS_TYPE_S32, PS_TYPE_S32, PS_TYPE_S64,
+        PS_TYPE_S32, PS_TYPE_S32, PS_TYPE_S32, PS_TYPE_S64,
+        PS_TYPE_F64
+    };
+const psF32 tableF32_index[] =
+    {
+        -10.05,1.009,23.45,3500.67
+    };
+const psS32 tableF32_col1[] =
+    {
+        2, 4, 6, 8
+    };
+const psS32 tableF32_col2[] =
+    {
+        4, 8, 12, 16
+    };
+const psS64 tableF32_col3[] =
+    {
+        8, 16, 24, 32
+    };
+const psS32 tableF32_col4[] =
+    {
+        0, -1, -2, -3
+    };
+const psS32 tableF32_col5[] =
+    {
+        -2, -4, -6, -8
+    };
+const psS32 tableF32_col6[] =
+    {
+        -4, -8, -12, -16
+    };
+const psS64 tableF32_col7[] =
+    {
+        -8, -16, -24, -32
+    };
+const psF64 tableF32_col8[] =
+    {
+        -1.5, -1.0, -0.25, 1.75
+    };
+
+
+const psF64 table10_validFrom = 1;
+const psF64 table10_validTo   = 10;
+const psS32 table10_size      = 10;
+const char table10_format[] = "\%d \%d \%d \%ld \%d \%d \%d \%ld \%f \%lf";
+const char table10_filename[] = VERIFIED_DIR "/table10.dat";
+const psS32 table10_indexCol = 0;
+const psS32  table10_index[]   =
+    {
+        1,   2,    3,   4,    5,    6,    7,    8,   9,    10
+    };
+const psS32 table10_val1[]    =
+    {
+        4,   6,    8,  10,   12,   14,   16,   18,   20,   22
+    };
+const psS32 table10_val2[]    =
+    {
+        8,  12,   16,  20,   24,   28,   32,   36,   40,   44
+    };
+const psS64 table10_val3[]    =
+    {
+        16,  24,   32,  64,  128,  256,  512, 1024, 2048, 4096
+    };
+const psS32  table10_val4[]    =
+    {
+        -1,  -2,   -3,  -4,   -5,   -6,   -7,   -8,   -9,  -10
+    };
+const psS32 table10_val5[]    =
+    {
+        -4,  -6,   -8, -10,  -12,  -14,  -16,  -18,  -20,  -22
+    };
+const psS32 table10_val6[]    =
+    {
+        -8, -12,  -16, -20,  -24,  -28,  -32,  -36,  -40,  -44
+    };
+const psS64 table10_val7[]    =
+    {
+        -16, -24,  -32, -64, -128, -256, -512,-1024,-2048,-4096
+    };
+const psF32 table10_val8[]    =
+    {
+        -2.25,-1.5,-0.75, 0.0, 0.75, 1.50, 2.25, 3.00, 3.75, 4.50
+    };
+const psF64 table10_val9[]    =
+    {
+        -2.67,0.66, 3.99,7.32,10.65,13.98,17.31,20.64,23.97,27.30
+    };
+const psF64 interpolVal1[]    =
+    {
+        5.25, 12.5, 25, 160, -5.25, -12.5, -25, -160, 0.9375, 11.4825
+    };
+const psF64 interpolVal2[]    =
+    {
+        5, 12, 24, 128, -5, -12, -24, -128, 0.75, 10.65
+    };
+const psF64 interpolVal3[]    =
+    {
+        4, 8, 16, -1, -4, -8, -16, -2.25, -2.67
+    };
+
+testDescription tests[] = {
+                              {testLookupTableAlloc,817,"psLookupTableAlloc",0,false},
+                              {testVectorsReadFromFile,999,"psVectorsReadFromFile",0,false},
+                              {testLookupTableImport,666,"psLookupTableImport",0,false},
+                              {testLookupTableRead,998,"psLookupTableRead",0,false},
+                              {testLookupTableInterpolate,997,"psLookupTableInterpolate",0,false},
+                              {testLookupTableInterpolateAll,996,"psLookupTableInterpolateAll",0,false},
+                              {NULL}
+                          };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    if ( ! runTestSuite(stderr,"psLookupTable",tests,argc,argv)) {
+        return 1;
+    }
+    return 0;
+}
+
+psS32 testLookupTableAlloc(void)
+{
+    psLookupTable*  table1 = NULL;
+
+    // Allocate lookup table with valid parameters
+    table1 = psLookupTableAlloc("tableF32.dat","\%f \%lf \%d \%ld",10);
+    if(table1 == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Null lookup table generated from valid parameters");
+        return 1;
+    }
+    if(strcmp(table1->filename,"tableF32.dat") != 0) {
+        psError(PS_ERR_UNKNOWN,true,"File name not properly stored in psLookupTable structure.");
+        return 2;
+    }
+    if(strcmp(table1->format,"\%f \%lf \%d \%ld") != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Format string not properly storeed in psLookupTable structure.");
+        return 3;
+    }
+    if(table1->indexCol != 10) {
+        psError(PS_ERR_UNKNOWN,true,"Member indexCol not set properly");
+        return 3;
+    }
+    psFree(table1);
+
+    // Allocate lookup table with invalid filename
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid file name");
+    table1 = psLookupTableAlloc(NULL,"\%d",3);
+    if(table1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Null file name accepted by psLookupTableAlloc");
+        return 4;
+    }
+
+    // Allocate lookup table with invalid format
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid format string");
+    table1 = psLookupTableAlloc("tableF32.dat",NULL,3);
+    if(table1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Null format string accepted by psLookupTableAlloc");
+        return 5;
+    }
+
+    return 0;
+}
+
+psS32 testVectorsReadFromFile(void)
+{
+    psArray*   out        = NULL;
+    psVector*  tempVector = NULL;
+
+    // Read file and place into an array of vectors
+    out = psVectorsReadFromFile(VERIFIED_DIR "/tableF32.dat","\%f \%d \%d \%ld \%d \%d \%d \%ld \%*d \%lf");
+    if(out == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Unable to read file into array of vectors");
+        return 1;
+    }
+    // Verify the number of vectors in array is as expected
+    if(out->n != tableF32_cols) {
+        psError(PS_ERR_UNKNOWN,true,"Expected number of columns = %d not equal to actual = %d",
+                tableF32_cols, out->n);
+        return 2;
+    }
+    // Verify the number of entries in vectors is as expected
+    for(int i = 0; i < out->n; i++ ) {
+        tempVector = out->data[i];
+        if(tempVector->n != tableF32_size) {
+            psError(PS_ERR_UNKNOWN,true,"Col #%d Expected number of entries = %d  not equal to actual = %d",
+                    i,tableF32_size,tempVector->n);
+            return 3;
+        }
+    }
+    // Verify the vector types are as expected
+    for(int i = 0; i < out->n; i++) {
+        tempVector = out->data[i];
+        if(tempVector->type.type != tableF32_colType[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Col #%d Expected type = %d not equal to actual = %d",
+                    i,tableF32_colType[i],tempVector->type.type);
+            return 4;
+        }
+    }
+    // Verify the values in the vectors are as expected
+    tempVector = out->data[0];
+    for(int i = 0; i < tempVector->n; i++) {
+        if(tempVector->data.F32[i] != tableF32_index[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Col #0 Vector element[%d] expected = %f not equal to actual = %f",
+                    i, tableF32_index[i],tempVector->data.F32[i]);
+            return 5 + i;
+        }
+    }
+    // Verify the values in the vectors are as expected
+    tempVector = out->data[1];
+    for(int i = 0; i < tempVector->n; i++) {
+        if(tempVector->data.S32[i] != tableF32_col1[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Col #1 Vector element[%d] expected = %d not equal to actual = %d",
+                    i, tableF32_col1[i],tempVector->data.S32[i]);
+            return 10 + i;
+        }
+    }
+    // Verify the values in the vectors are as expected
+    tempVector = out->data[2];
+    for(int i = 0; i < tempVector->n; i++) {
+        if(tempVector->data.S32[i] != tableF32_col2[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Col #2 Vector element[%d] expected = %d not equal to actual = %d",
+                    i, tableF32_col2[i],tempVector->data.S32[i]);
+            return 15 + i;
+        }
+    }
+    // Verify the values in the vectors are as expected
+    tempVector = out->data[3];
+    for(int i = 0; i < tempVector->n; i++) {
+        if(tempVector->data.S64[i] != tableF32_col3[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Col #3 Vector element[%d] expected = %ld not equal to actual = %ld",
+                    i, tableF32_col3[i],tempVector->data.S64[i]);
+            return 20 + i;
+        }
+    }
+    // Verify the values in the vectors are as expected
+    tempVector = out->data[4];
+    for(int i = 0; i < tempVector->n; i++) {
+        if(tempVector->data.S32[i] != tableF32_col4[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Col #4 Vector element[%d] expected = %d not equal to actual = %d",
+                    i, tableF32_col4[i],tempVector->data.S32[i]);
+            return 25 + i;
+        }
+    }
+    // Verify the values in the vectors are as expected
+    tempVector = out->data[5];
+    for(int i = 0; i < tempVector->n; i++) {
+        if(tempVector->data.S32[i] != tableF32_col5[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Col #5 Vector element[%d] expected = %d not equal to actual = %d",
+                    i, tableF32_col5[i],tempVector->data.S32[i]);
+            return 30 + i;
+        }
+    }
+    // Verify the values in the vectors are as expected
+    tempVector = out->data[6];
+    for(int i = 0; i < tempVector->n; i++) {
+        if(tempVector->data.S32[i] != tableF32_col6[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Col #6 Vector element[%d] expected = %d not equal to actual = %d",
+                    i, tableF32_col6[i],tempVector->data.S32[i]);
+            return 35 + i;
+        }
+    }
+    // Verify the values in the vectors are as expected
+    tempVector = out->data[7];
+    for(int i = 0; i < tempVector->n; i++) {
+        if(tempVector->data.S64[i] != tableF32_col7[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Col #7 Vector element[%d] expected = %ld not equal to actual = %ld",
+                    i, tableF32_col7[i],tempVector->data.S64[i]);
+            return 40 + i;
+        }
+    }
+    // Verify the values in the vectors are as expected
+    tempVector = out->data[8];
+    for(int i = 0; i < tempVector->n; i++) {
+        if(tempVector->data.F64[i] != tableF32_col8[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Col #8 Vector element[%d] expected = %lf not equal to actual = %lf",
+                    i, tableF32_col8[i],tempVector->data.F64[i]);
+            return 45 + i;
+        }
+    }
+    psFree(out);
+
+    // Attempt to read vectors from valid file with invalid format
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL format");
+    out = psVectorsReadFromFile(VERIFIED_DIR "/tableF32.dat",NULL);
+    if(out != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with NULL format string");
+        return 50;
+    }
+
+    // Attempt to read vectors from invalid file with valid format
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL filename");
+    out = psVectorsReadFromFile(NULL,"%f %f");
+    if(out != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with NULL file name");
+        return 51;
+    }
+
+    // Attempt to read vectors from valid file with invalid format specifiers
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid format specifier");
+    out = psVectorsReadFromFile(VERIFIED_DIR "/tableF32.data","\%f \%c \%d");
+    if(out != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with invalid format specifier");
+        return 52;
+    }
+
+    // Attempt to read vectors from non-existant file
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for non-existant file");
+    out = psVectorsReadFromFile("nonexistant.dat","\%f \%d \%d");
+    if(out != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with non-existant file");
+        return 53;
+    }
+
+    // Attempt to read vectors from file with errors in the numbers
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for error is file");
+    out = psVectorsReadFromFile(VERIFIED_DIR "/tableF32_err.dat","\%f \%d \%d \%ld \%d \%d \%d \%ld \%d \%lf");
+    if(out != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with file with errors");
+        return 54;
+    }
+
+    return 0;
+}
+
+psS32 testLookupTableImport(void)
+{
+    psLookupTable*  outTable = NULL;
+    psLookupTable*  inTable  = NULL;
+    psArray*        vectors  = NULL;
+
+    // Attempt to import table with NULL table
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL table argument");
+    outTable = psLookupTableImport(NULL,vectors,1);
+    if(outTable != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with NULL input table");
+        return 1;
+    }
+
+    // Allocate valid table, format string and index column
+    inTable = psLookupTableAlloc(table10_filename,table10_format,table10_indexCol);
+
+    // Attempt to import table with NULL vector argument
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL vectors");
+    outTable = psLookupTableImport(inTable,vectors,table10_indexCol);
+    if(outTable != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with NULL input vectors");
+        return 2;
+    }
+
+    // Allocate valid array
+    vectors = psArrayAlloc(10);
+
+    // Attempt to import table with invalid index column
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid index column");
+    outTable = psLookupTableImport(inTable,vectors,-1);
+    if(outTable != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL with invalid index column specified");
+        return 3;
+    }
+    psFree(vectors);
+
+    // Attempt to import file with file with unsorted index vector
+    // Read vectors from file
+    vectors = psVectorsReadFromFile(table10_filename,table10_format);
+    outTable = psLookupTableImport(inTable,vectors,table10_indexCol);
+    if(outTable != inTable) {
+        psError(PS_ERR_UNKNOWN,true,"Did not set proper return value");
+        return 4;
+    }
+    // Verify the index column vector
+    psVector* indexVector = outTable->index;
+    for(int i = 0; i < indexVector->n; i++) {
+        if(indexVector->data.S32[i] != table10_index[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Index value[%d] = %d is not as expected %d",
+                    i,indexVector->data.S32[i],table10_index[i]);
+            return i*4;
+        }
+    }
+    // Verify the value array vectors
+    psVector* valueVector = outTable->values->data[1];
+    for(int i = 0; i < valueVector->n; i++) {
+        if(valueVector->data.S32[i] != table10_val1[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Value [%d] = %d is not as expected %d",
+                    i,valueVector->data.S32[i],table10_val1[i]);
+            return i*5;
+        }
+    }
+    valueVector = outTable->values->data[2];
+    for(int i = 0; i < valueVector->n; i++) {
+        if(valueVector->data.S32[i] != table10_val2[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Value [%d] = %d is not as expected %d",
+                    i,valueVector->data.S32[i],table10_val2[i]);
+            return i*6;
+        }
+    }
+    valueVector = outTable->values->data[3];
+    for(int i = 0; i < valueVector->n; i++) {
+        if(valueVector->data.S64[i] != table10_val3[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Value [%d] = %ld is not as expected %ld",
+                    i,valueVector->data.S64[i],table10_val3[i]);
+            return i*7;
+        }
+    }
+    valueVector = outTable->values->data[4];
+    for(int i = 0; i < valueVector->n; i++) {
+        if(valueVector->data.S32[i] != table10_val4[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Value [%d] = %d is not as expected %d",
+                    i,valueVector->data.S32[i],table10_val4[i]);
+            return i*8;
+        }
+    }
+    valueVector = outTable->values->data[5];
+    for(int i = 0; i < valueVector->n; i++) {
+        if(valueVector->data.S32[i] != table10_val5[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Value [%d] = %d is not as expected %d",
+                    i,valueVector->data.S32[i],table10_val5[i]);
+            return i*9;
+        }
+    }
+    valueVector = outTable->values->data[6];
+    for(int i = 0; i < valueVector->n; i++) {
+        if(valueVector->data.S32[i] != table10_val6[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Value [%d] = %d is not as expected %d",
+                    i,valueVector->data.S32[i],table10_val6[i]);
+            return i*10;
+        }
+    }
+    valueVector = outTable->values->data[7];
+    for(int i = 0; i < valueVector->n; i++) {
+        if(valueVector->data.S64[i] != table10_val7[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Value [%d] = %ld is not as expected %ld",
+                    i,valueVector->data.S64[i],table10_val7[i]);
+            return i*11;
+        }
+    }
+    valueVector = outTable->values->data[8];
+    for(int i = 0; i < valueVector->n; i++) {
+        if(valueVector->data.F32[i] != table10_val8[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Value [%d] = %f is not as expected %f",
+                    i,valueVector->data.F32[i],table10_val8[i]);
+            return i*12;
+        }
+    }
+    valueVector = outTable->values->data[9];
+    for(int i = 0; i < valueVector->n; i++) {
+        if(valueVector->data.F64[i] != table10_val9[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Value [%d] = %lf is not as expected %lf",
+                    i,valueVector->data.F64[i],table10_val9[i]);
+            return i*13;
+        }
+    }
+    // Verify the table members are set properly
+    if(outTable->indexCol != table10_indexCol) {
+        psError(PS_ERR_UNKNOWN,true,"Member indexCol = %d not as expected %d",
+                outTable->indexCol,table10_indexCol);
+        return 100;
+    }
+    if(outTable->validFrom != table10_validFrom) {
+        psError(PS_ERR_UNKNOWN,true,"Member validFrom = %d not as expected %d",
+                outTable->validFrom, table10_validFrom);
+        return 101;
+    }
+    if(outTable->validTo != table10_validTo) {
+        psError(PS_ERR_UNKNOWN,true,"Member validTo = %d not as expected %d",
+                outTable->validTo, table10_validTo);
+        return 102;
+    }
+    if(strcmp(outTable->filename,table10_filename) != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Member filename = %d not as expected %s",
+                outTable->filename,table10_filename);
+        return 103;
+    }
+    if(strcmp(outTable->format,table10_format) != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Member format = %d not as expected %s",
+                outTable->format,table10_format);
+        return 104;
+    }
+    psFree(vectors);
+    psFree(inTable);
+
+    // Attempt to import file with file with sorted index vector
+    // Read vectors from file
+    // Allocate valid table, format string and index column
+    inTable = psLookupTableAlloc(tableU8_filename,tableU8_format,tableU8_indexCol);
+    vectors = psVectorsReadFromFile(tableU8_filename,tableU8_format);
+    outTable = psLookupTableImport(inTable,vectors,tableU8_indexCol);
+    if(outTable != inTable) {
+        psError(PS_ERR_UNKNOWN,true,"Did not set proper return value");
+        return 4;
+    }
+    // Verify the index column vector
+    indexVector = outTable->index;
+    for(int i = 0; i < indexVector->n; i++) {
+        if(indexVector->data.S32[i] != tableU8_index[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Index value[%d] = %d is not as expected %d",
+                    i,indexVector->data.S32[i],tableU8_index[i]);
+        }
+    }
+    // Verify the table members are set properly
+    if(outTable->indexCol != tableU8_indexCol) {
+        psError(PS_ERR_UNKNOWN,true,"Member indexCol = %d not as expected %d",
+                outTable->indexCol,tableU8_indexCol);
+        return 100;
+    }
+    if(outTable->validFrom != tableU8_validFrom) {
+        psError(PS_ERR_UNKNOWN,true,"Member validFrom = %d not as expected %d",
+                outTable->validFrom, tableU8_validFrom);
+        return 101;
+    }
+    if(outTable->validTo != tableU8_validTo) {
+        psError(PS_ERR_UNKNOWN,true,"Member validTo = %d not as expected %d",
+                outTable->validTo, tableU8_validTo);
+        return 102;
+    }
+    if(strcmp(outTable->filename,tableU8_filename) != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Member filename = %d not as expected %s",
+                outTable->filename,tableU8_filename);
+        return 103;
+    }
+    if(strcmp(outTable->format,tableU8_format) != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Member format = %d not as expected %s",
+                outTable->format,tableU8_format);
+        return 104;
+    }
+    psFree(inTable);
+    psFree(vectors);
+
+    return 0;
+}
+
+psS32 testLookupTableRead(void)
+{
+    psLookupTable*  table1  = NULL;
+    long           numRows = 0;
+
+    // Attempt to read table with NULL input table specified
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL table");
+    numRows = psLookupTableRead(table1);
+    if(numRows != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return zero for NULL input table");
+        return 1;
+    }
+
+    // Set up valid table to read
+    table1 = psLookupTableAlloc(tableF32_filename,tableF32_format,tableF32_indexCol);
+    // Read table
+    numRows = psLookupTableRead(table1);
+    // Verify return value equals number of lines read
+    if(numRows != tableF32_size) {
+        psError(PS_ERR_UNKNOWN,true,"Return value %d not as expected %d",
+                numRows,tableF32_size);
+        return 1;
+    }
+    // Verify the members and values in table
+    if(fabs(table1->validFrom - tableF32_validFrom) > errorTol_psF64) {
+        psError(PS_ERR_UNKNOWN,true,"Member validFrom = %f not as expected %f",
+                table1->validFrom,tableF32_validFrom);
+        return 2;
+    }
+    if(fabs(table1->validTo - tableF32_validTo) > errorTol_psF64) {
+        psError(PS_ERR_UNKNOWN,true,"Member validTo = %f not as expected %f",
+                table1->validTo,tableF32_validTo);
+        return 3;
+    }
+    if(strcmp(table1->filename,tableF32_filename) != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Member filename %s not as expected %s",
+                table1->filename,tableF32_filename);
+        return 4;
+    }
+    if(strcmp(table1->format,tableF32_format) != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Member format %s not as expected %s",
+                table1->format,tableF32_format);
+        return 5;
+    }
+    if(table1->indexCol != tableF32_indexCol) {
+        psError(PS_ERR_UNKNOWN,true,"Member indexCol %d not as expected %d",
+                table1->indexCol,tableF32_indexCol);
+        return 6;
+    }
+    for(psS32 i = 0; i < table1->index->n; i++) {
+        if(fabs(table1->index->data.F32[i]-tableF32_index[i]) > errorTol_psF64) {
+            psError(PS_ERR_UNKNOWN,true,"Index column[%d] = %f not as expected %f",
+                    i,table1->index->data.F32[i],tableF32_index[i]);
+            return i*7;
+        }
+    }
+    psVector* tempVector = table1->values->data[1];
+    for(psS32 i = 0; i < tempVector->n; i++) {
+        if(tempVector->data.S32[i] != tableF32_col1[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Value column[%d] = %d not as expected %d",
+                    i,tempVector->data.S32[i],tableF32_col1[i]);
+            return i*8;
+        }
+    }
+    tempVector = table1->values->data[2];
+    for(psS32 i = 0; i < tempVector->n; i++) {
+        if(tempVector->data.S32[i] != tableF32_col2[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Value column[%d] = %d not as expected %d",
+                    i,tempVector->data.S32[i],tableF32_col2[i]);
+            return i*9;
+        }
+    }
+    tempVector = table1->values->data[3];
+    for(psS32 i = 0; i < tempVector->n; i++) {
+        if(tempVector->data.S64[i] != tableF32_col3[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Value column[%d] = %ld not as expected %ld",
+                    i,tempVector->data.S64[i],tableF32_col3[i]);
+            return i*10;
+        }
+    }
+    tempVector = table1->values->data[4];
+    for(psS32 i = 0; i < tempVector->n; i++) {
+        if(tempVector->data.S32[i] != tableF32_col4[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Value column[%d] = %d not as expected %d",
+                    i,tempVector->data.S32[i],tableF32_col4[i]);
+            return i*11;
+        }
+    }
+    tempVector = table1->values->data[5];
+    for(psS32 i = 0; i < tempVector->n; i++) {
+        if(tempVector->data.S32[i] != tableF32_col5[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Value column[%d] = %d not as expected %d",
+                    i,tempVector->data.S32[i],tableF32_col5[i]);
+            return i*12;
+        }
+    }
+    tempVector = table1->values->data[6];
+    for(psS32 i = 0; i < tempVector->n; i++) {
+        if(tempVector->data.S32[i] != tableF32_col6[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Value column[%d] = %d not as expected %d",
+                    i,tempVector->data.S32[i],tableF32_col6[i]);
+            return i*13;
+        }
+    }
+    tempVector = table1->values->data[7];
+    for(psS32 i = 0; i < tempVector->n; i++) {
+        if(tempVector->data.S64[i] != tableF32_col7[i]) {
+            psError(PS_ERR_UNKNOWN,true,"Value column[%d] = %ld not as expected %ld",
+                    i,tempVector->data.S64[i],tableF32_col7[i]);
+            return i*14;
+        }
+    }
+    psFree(table1);
+
+    // Set up invalid table to read
+    table1 = psLookupTableAlloc(tableF32_filename,tableF32_format,tableF32_indexCol);
+    table1->indexCol = -1;
+    // Read invalid table
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message invalid table indexCol");
+    numRows = psLookupTableRead(table1);
+    // Verify the num of rows read is zero
+    if(numRows != 0) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return 0 for line read for invalid table");
+        return 15;
+    }
+    psFree(table1);
+
+    return 0;
+}
+
+psS32 testLookupTableInterpolate(void)
+{
+    psLookupTable*  table1 = NULL;
+    psF64            out1 = 0.0;
+
+    // Attempt to perform interpolation with NULL table
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid table");
+    out1 = psLookupTableInterpolate(table1,0,0);
+    if( !isnan(out1) ) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NaN as expected");
+        return 1;
+    }
+
+    // Interpolate values within the list and verify return values
+    table1 = psLookupTableAlloc(table10_filename,table10_format,table10_indexCol);
+    psS32 numLines = psLookupTableRead(table1);
+    if(numLines != table10_size) {
+        psError(PS_ERR_UNKNOWN,true,"Line read %d not as expected %d",numLines,table10_size);
+        return 2;
+    }
+    for(psS32 i = 0; i < table1->values->n; i++ ) {
+        out1 = psLookupTableInterpolate(table1, 5.25, i);
+        if( fabs(out1-interpolVal1[i]) > errorTol_psF64) {
+            psError(PS_ERR_UNKNOWN,true,"Did not return expected value. %lg expected %lg",out1,interpolVal1[i]);
+            return 3*i;
+        }
+    }
+    for(psS32 i = 0; i < table1->values->n; i++ ) {
+        out1 = psLookupTableInterpolate(table1, 5.0, i);
+        if( fabs(out1-interpolVal2[i]) > errorTol_psF64) {
+            psError(PS_ERR_UNKNOWN,true,"Did not return expected value. %lg expected %lg",out1,interpolVal2[i]);
+            return 4*i;
+        }
+    }
+
+    // Interpolate value just below the lowest index value
+    out1 = psLookupTableInterpolate(table1,0,0);
+    if ( fabs(out1- NAN) > FLT_EPSILON ) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NAN returned %lf",out1);
+        return 5;
+    }
+
+    // Interpolate value just above the highest index value
+    out1 = psLookupTableInterpolate(table1,11,0);
+    if ( fabs(out1-NAN) > FLT_EPSILON ) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NAN returned %lf",out1);
+        return 7;
+    }
+
+    // Interpolate value with a column number greater than the table has
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error out of range.");
+    out1 = psLookupTableInterpolate(table1, 5, 100);
+    if ( fabs(out1-NAN) > FLT_EPSILON ) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NAN returned %lf",out1);
+        return 9;
+    }
+    psFree(table1);
+
+    return 0;
+}
+
+psS32 testLookupTableInterpolateAll(void)
+{
+    psLookupTable*  table1 = NULL;
+    psVector*        interpValues;
+
+    // Interpolate values with NULL table
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL table");
+    interpValues = psLookupTableInterpolateAll(table1,5);
+    if(interpValues != NULL ) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL for NULL table");
+        return 5;
+    }
+
+    // Interpolate values within the list and verify return values
+    table1 = psLookupTableAlloc(table10_filename,table10_format,table10_indexCol);
+    psS32 numLines = psLookupTableRead(table1);
+    if(numLines != table10_size) {
+        psError(PS_ERR_UNKNOWN,true,"Num lines read %d not as expected %d",numLines,table10_size);
+        return 6;
+    }
+    interpValues = psLookupTableInterpolateAll(table1,5.25);
+    if(interpValues == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Returned vector is NULL.");
+        return 1;
+    }
+    for(psS32 i = 0; i < table1->values->n; i++ ) {
+        if( fabs(interpValues->data.F64[i]-interpolVal1[i]) > errorTol_psF64) {
+            psError(PS_ERR_UNKNOWN,true,"Did not return expected value. %lg expected %lg",
+                    interpValues->data.F64[i],interpolVal1[i]);
+            return 2*i;
+        }
+    }
+    psFree(interpValues);
+
+    // Interpolate values with index outside table
+    interpValues = psLookupTableInterpolateAll(table1,0);
+    if(interpValues != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did return NULL");
+        return 4;
+    }
+    psFree(table1);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadataIO.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadataIO.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadataIO.c	(revision 22158)
@@ -0,0 +1,1021 @@
+/** @file  tst_psMetadataIO.c
+ *
+ *  @brief Test driver for psMetadataIO functions
+ *
+ *  This test driver contains the following tests for psMetadata:
+ *    Read config file with overwrite set true
+ *    Read config file with overwrite set false
+ *    Attempt to use null fileName argument
+ *    Attempt to open nonexistant file
+ *
+ *  @author  Ross Harman, MHPCC
+ *  @author  Robert DeSonia, MHPCC
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.7 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2006-06-07 01:39:17 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include <string.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+
+static psS32 testMetadataParseConfig(void);
+static psS32 testMetadataParseConfig1(void);
+static psS32 testMetadataParseConfig2(void);
+static psS32 testMetadataParseConfig3(void);
+static psS32 testMetadataParseConfig4(void);
+
+testDescription tests[] = {
+                              {testMetadataParseConfig,0,"psMetadataConfigParse",0,false},
+                              {testMetadataParseConfig1,1,"psMetadataConfigParse1",0,false},
+                              {testMetadataParseConfig2,2,"psMetadataConfigParse2",0,false},
+                              {testMetadataParseConfig3,3,"psMetadataConfigParse3",0,false},
+                              {testMetadataParseConfig4,4,"psMetadataConfigParse4",0,false},
+                              {NULL}
+                          };
+
+static void writeMetadataItem(psMetadataItem* metadataIem, char* indentStr);
+static void writeMetadata(psMetadata* metadata, char* indentStr);
+static void writeMetadataList(psList *metadataItemList, char* indentStr);
+
+static psBool checkFailedLines(psS32 failedLines, psS32 expectedFailedLines, char* configFile);
+static psBool checkNumberOfItems(psMetadata* md, psS32 expectedItems, char* configFile);
+static psBool checkItemName(psMetadataItem* mdItem, char* expectedName, char* configFile);
+static psBool checkItemType(psMetadataItem* mdItem, psS32 expectedType, char* configFile);
+static psBool checkItemComment(psMetadataItem* mdItem, char* expectedComment, char* configFile);
+
+#define ERROR_TOL  0.0001
+
+const char testConfig5[] = "test5.config";
+const psS32 testConfig5Fails = 7;
+
+const char testConfig4[] = "test4.config";
+const psS32 testConfig4Fails = 0;
+
+const char testConfig3[] = "test3.config";
+const psS32 testConfig3Fails = 1;
+
+const char testConfig2[] = "test2.config";
+const psS32 testConfig2Fails = 17;
+
+// SDR-14 test config file #1
+const char  testConfig1[] = "test1.config";
+const psS32 testConfig1FailsOverwrite = 0;
+const psS32 testConfig1Fails = 1;
+const psS32 testConfig1Items = 25;
+const char* testConfig1KeyOverwrite[] =
+    {
+        "Double","String","boolean","primes","comment",
+        "comment","comment","comment","comment","Float",
+        "boolean1","negprimes","vector1","vector2","vector3",
+        "vector4","vector5","vector6","vector7","vector8",
+        "CELL.00", "CELL.01","MYCELL","MYCELL","cell"
+    };
+const char* testConfig1CommentOverwrite[] =
+    {
+        "This is a comment","comment","The value of 'boolean' is 'true'","These are prime numbers",
+        "","","","","",
+        "This generates a warning, and, if 'overwrite' is 'false', is ignored","The value of 'boolean' is 'false'",
+        "","","","","",
+        "","","","",
+        "","","","A number",""
+    };
+const psDataType testConfig1TypeOverwrite[] =
+    {
+        PS_DATA_F64, PS_DATA_STRING, PS_DATA_BOOL, PS_DATA_VECTOR, PS_DATA_STRING,
+        PS_DATA_STRING, PS_DATA_STRING, PS_DATA_STRING, PS_DATA_STRING,  PS_DATA_F64,
+        PS_DATA_BOOL, PS_DATA_VECTOR, PS_DATA_VECTOR, PS_DATA_VECTOR, PS_DATA_VECTOR,
+        PS_DATA_VECTOR, PS_DATA_VECTOR, PS_DATA_VECTOR, PS_DATA_VECTOR, PS_DATA_VECTOR,
+        PS_DATA_METADATA, PS_DATA_METADATA, PS_DATA_METADATA, PS_DATA_S32, PS_DATA_METADATA
+    };
+const psS32 testConfig1ValueS32Overwrite[] =
+    {
+        0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0,
+        0, 0, 0, 123, 0
+    };
+const psF32 testConfig1ValueF32Overwrite[] =
+    {
+        0.0, 0.0, 0.0, 0.0, 0.0,
+        0.0, 0.0, 0.0, 0.0, 0.0,
+        0.0, 0.0, 0.0, 0.0, 0.0,
+        0.0, 0.0, 0.0, 0.0, 0.0,
+        0.0, 0.0, 0.0, 0.0, 0.0
+    };
+const psF64 testConfig1ValueF64Overwrite[] =
+    {
+        1.23456789, 0.0, 0.0, 0.0, 0.0,
+        0.0, 0.0, 0.0, 0.0, 1.23456,
+        0.0, 0.0, 0.0, 0.0, 0.0,
+        0.0, 0.0, 0.0, 0.0, 0.0,
+        0.0, 0.0, 0.0, 0.0, 0.0
+    };
+const psBool testConfig1ValueBoolOverwrite[] =
+    {
+        false, false, true, false, false,
+        false, false, false, false, false,
+        false, false, false, false, false,
+        false, false, false, false, false,
+        false, false, false, false, false
+    };
+const char* testConfig1ValueStrOverwrite[] =
+    {
+        "", "This is the string that forms the value","","","This",
+        "is","a","non-unique","key","",
+        "","","","","",
+        "","","","","",
+        "","","","",""
+    };
+const psS32 testConfig1ValueVecItemsU8 = 7;
+const psElemType testConfig1ValueVecTypeU8 = PS_TYPE_U8;
+const psU8 testConfig1ValueVecValueU8[] =
+    {
+        2, 3, 5, 7, 11, 13, 17
+    };
+const psS32 testConfig1ValueVecItemsS8 = 8;
+const psElemType testConfig1ValueVecTypeS8 = PS_TYPE_S8;
+const psS8 testConfig1ValueVecValueS8[] =
+    {
+        -2, -3, -5, -7, -11, -13, -17, -19
+    };
+const psS32 testConfig1ValueVecItemsU16 = 5;
+const psElemType testConfig1ValueVecTypeU16 = PS_TYPE_U16;
+const psU16 testConfig1ValueVecValueU16[] =
+    {
+        0, 1, 2, 4, 8
+    };
+const psS32 testConfig1ValueVecItemsU32 = 6;
+const psElemType testConfig1ValueVecTypeU32 = PS_TYPE_U32;
+const psU32 testConfig1ValueVecValueU32[] =
+    {
+        0, 8, 16, 32, 64, 128
+    };
+const psS32 testConfig1ValueVecItemsU64 = 3;
+const psElemType testConfig1ValueVecTypeU64 = PS_TYPE_U64;
+const psU64 testConfig1ValueVecValueU64[] =
+    {
+        0, 64, 256
+    };
+const psS32 testConfig1ValueVecItemsS16 = 5;
+const psElemType testConfig1ValueVecTypeS16 = PS_TYPE_S16;
+const psS16 testConfig1ValueVecValueS16[] =
+    {
+        -2, -1, 0, 1, 2
+    };
+const psS32 testConfig1ValueVecItemsS32 = 6;
+const psElemType testConfig1ValueVecTypeS32 = PS_TYPE_S32;
+const psS32 testConfig1ValueVecValueS32[] =
+    {
+        -4, -2, 0, 2, 4, 6
+    };
+const psS32 testConfig1ValueVecItemsS64 = 7;
+const psElemType testConfig1ValueVecTypeS64 = PS_TYPE_S64;
+const psS64 testConfig1ValueVecValueS64[] =
+    {
+        -16, -4, 0, 4, 16, 36, 64
+    };
+const psS32 testConfig1ValueVecItemsF32 = 4;
+const psElemType testConfig1ValueVecTypeF32 = PS_TYPE_F32;
+const psF32 testConfig1ValueVecValueF32[] =
+    {
+        -1.03, 1.04, -1.05, 1.06
+    };
+const psS32 testConfig1ValueVecItemsF64 = 5;
+const psElemType testConfig1ValueVecTypeF64 = PS_TYPE_F64;
+const psF64 testConfig1ValueVecValueF64[] =
+    {
+        -2.22, 2.21, -2.20, 2.19, -2.18
+    };
+const psS32 testConfig1ValueMetaItems1 = 3;
+const char* testConfig1ValueMetaNames1[] =
+    {
+        "EXTNAME","BIASSEC","CHIP"
+    };
+const psDataType testConfig1ValueMetaTypes1[] =
+    {
+        PS_DATA_STRING, PS_DATA_STRING, PS_DATA_STRING
+    };
+const char* testConfig1ValueMetaValue1[] =
+    {
+        "CCD00","BSEC-00","CHIP.00"
+    };
+const psS32 testConfig1ValueMetaItems2 = 3;
+const char* testConfig1ValueMetaNames2[] =
+    {
+        "EXTNAME","BIASSEC","CHIP"
+    };
+const psDataType testConfig1ValueMetaTypes2[] =
+    {
+        PS_DATA_STRING, PS_DATA_STRING, PS_DATA_STRING
+    };
+const char* testConfig1ValueMetaValue2[] =
+    {
+        "CCD01","BSEC-01","CHIP.00"
+    };
+const psS32 testConfig1ValueMetaItems3 = 4;
+const char* testConfig1ValueMetaNames3[] =
+    {
+        "EXTNAME","BIASSEC","CHIP","NCELL"
+    };
+const psDataType testConfig1ValueMetaTypes3[] =
+    {
+        PS_DATA_STRING, PS_DATA_STRING, PS_DATA_STRING, PS_DATA_S32
+    };
+const char* testConfig1ValueMetaValueStr3[] =
+    {
+        "CCD00","BSEC-00","CHIP.00",""
+    };
+const psS32 testConfig1ValueMetaValueS323[] =
+    {
+        0, 0, 0, 24
+    };
+
+static void writeMetadata(psMetadata* metadata, char* indentStr)
+{
+    writeMetadataList(metadata->list, indentStr);
+}
+
+static void writeMetadataList(psList* metadataItemList, char* indentStr)
+{
+    psMetadataItem* entryChild        = NULL;
+    psMetadataItem* searchChild       = NULL;
+    psArray*        nonUniqueKeyArray = NULL;
+    psBool          keyFound          = false;
+    char*           tempKey           = NULL;
+
+    // Allocate iterator for moving through metadata list
+    psListIterator* iter = psListIteratorAlloc(metadataItemList, PS_LIST_HEAD, true);
+    psListIterator* searchIter = psListIteratorAlloc(metadataItemList, PS_LIST_HEAD, true);
+
+    // Allocate array for nonUnique key names
+    nonUniqueKeyArray = psArrayAlloc(10);
+    nonUniqueKeyArray->n = 0;
+
+
+    // Loop through all items in the list
+    while ( (entryChild = psListGetAndIncrement(iter)) != NULL) {
+        // Search list for another entry with same key name
+        // Check if last entry
+        if(iter->index != metadataItemList->n) {
+            // Set search iterator to index
+            if(!psListIteratorSet(searchIter,iter->index) ) {
+                psError(PS_ERR_UNKNOWN,true,"Error searching list for multiple keys");
+                break;
+            }
+            keyFound = false;
+            while ( (searchChild = psListGetAndIncrement(searchIter)) != NULL) {
+                if(strcmp(entryChild->name,searchChild->name) == 0) {
+                    // Search nonUnique key array
+                    for(psS32 i = 0; i < nonUniqueKeyArray->n; i++) {
+                        if(strcmp(entryChild->name,nonUniqueKeyArray->data[i]) == 0) {
+                            keyFound = true;
+                        }
+                    }
+                    if(!keyFound) {
+                        // Add key to non-unique array
+                        tempKey = psStringCopy(entryChild->name);
+                        nonUniqueKeyArray = psArrayAdd(nonUniqueKeyArray,1,tempKey);
+                        psFree(tempKey);
+
+                        // Print MULTI line
+                        printf("%-25s MULTI\n",entryChild->name);
+
+                        // Break out of loop
+                        break;
+                    }
+                }
+            }
+        }
+        writeMetadataItem(entryChild,indentStr);
+    }
+
+    psFree(iter);
+    psFree(searchIter);
+    psFree(nonUniqueKeyArray);
+}
+
+char* vectorToConfigString(psVector* vector)
+{
+    psS32  maxLength = 256;
+
+    char* str = psAlloc(sizeof(char)*maxLength+1);
+
+    if (vector == NULL) {
+        snprintf(str,maxLength, "NULL");
+        return str;
+    }
+
+    int size = vector->n;
+
+    if (size == 0) {
+        snprintf(str,maxLength, " ");
+        return str;
+    }
+
+    char* tempStr = psAlloc(sizeof(char)*maxLength+1);
+    *str = '\0';
+    bool full = false;
+
+    #define APPEND_ELEMENTS_CASE(TYPE, NATIVE_TYPE, FORMAT) \
+case PS_TYPE_##TYPE: \
+    strcat(str,#TYPE); \
+    for(psS32 i = 0; i < (strlen(str)-6); i++) {  \
+        strcat(str," "); \
+    } \
+    for (lcv=0; lcv < size && ! full; lcv++) { \
+        snprintf(tempStr, maxLength, "%s" FORMAT, prefix, (NATIVE_TYPE) (vector->data.TYPE[lcv])); \
+        strncat(str,tempStr,maxLength); \
+        full = (strlen(str) > maxLength-2); \
+        prefix = ","; \
+    } \
+    break;
+
+    int lcv;
+    char* prefix = " ";
+    switch(vector->type.type) {
+        APPEND_ELEMENTS_CASE(S8,char,"%hd")
+        APPEND_ELEMENTS_CASE(S16,short int,"%hd")
+        APPEND_ELEMENTS_CASE(S32,int,"%d")
+        APPEND_ELEMENTS_CASE(S64,long,"%ld")
+        APPEND_ELEMENTS_CASE(U8,unsigned char,"%hu")
+        APPEND_ELEMENTS_CASE(U16,unsigned short,"%hu")
+        APPEND_ELEMENTS_CASE(U32,unsigned int, "%u")
+        APPEND_ELEMENTS_CASE(U64,unsigned long,"%lu")
+        APPEND_ELEMENTS_CASE(F32,double,"%g")
+        APPEND_ELEMENTS_CASE(F64,double,"%g")
+    default:
+        snprintf(str,maxLength,"INVALID TYPE");
+        break;
+    }
+
+    psFree(tempStr);
+
+    return str;
+}
+
+
+static void writeMetadataItem(psMetadataItem *metadataItem, char* indentStr)
+{
+    char*  vecStr;
+
+    switch(metadataItem->type) {
+    case PS_DATA_BOOL:
+        printf("%s%-25s BOOL  %40d",indentStr,metadataItem->name,metadataItem->data.B);
+        break;
+    case PS_DATA_S32:
+        printf("%s%-25s S32   %40d",indentStr,metadataItem->name,metadataItem->data.S32);
+        break;
+    case PS_DATA_F32:
+        printf("%s%-25s F32   %40f",indentStr,metadataItem->name,metadataItem->data.F32);
+        break;
+    case PS_DATA_F64:
+        printf("%s%-25s F64   %40lf",indentStr,metadataItem->name,metadataItem->data.F64);
+        break;
+    case PS_DATA_VECTOR:
+        vecStr = (char*)vectorToConfigString((psVector*)metadataItem->data.V);
+        printf("%s@%-24s %s",indentStr,metadataItem->name,vecStr);
+        psFree(vecStr);
+        break;
+    case PS_DATA_STRING:
+        printf("%s%-25s STR   %40s",indentStr,metadataItem->name,(char*)metadataItem->data.V);
+        break;
+    case PS_DATA_METADATA:
+        printf("%s%-25s METADATA\n",indentStr,metadataItem->name);
+        char nestedStr[256] = "    ";
+        strcat(nestedStr,indentStr);
+        writeMetadata((psMetadata*)metadataItem->data.md,nestedStr);
+        printf("%sEND",indentStr);
+        break;
+    default:
+        printf("#%s%-24s BAD TYPE=%d",indentStr,metadataItem->name,metadataItem->type);
+        break;
+    }
+    if(strlen(metadataItem->comment) > 0) {
+        printf("  # %-20s\n",metadataItem->comment);
+    } else {
+        printf("\n");
+    }
+}
+
+static psBool checkFailedLines(psS32 failedLines, psS32 expectedFailedLines, char* configFile)
+{
+    psBool     returnValue = true;
+
+    // Verify the expected number of failed lines
+    if(failedLines != expectedFailedLines) {
+        psError(PS_ERR_UNKNOWN,true,"File: %s : Number of failed lines = %d not as expected %d",
+                configFile,failedLines,expectedFailedLines);
+        returnValue = false;
+    }
+    return returnValue;
+}
+
+static psBool checkNumberOfItems(psMetadata* md, psS32 expectedItems, char* configFile)
+{
+    psBool     returnValue = true;
+
+    // Verify the number of items in metadata
+    if(md->list->n != expectedItems) {
+        psError(PS_ERR_UNKNOWN,true,"File: %s : Number of items = %d not as expected %d",
+                configFile,md->list->n, expectedItems);
+        returnValue = false;
+    }
+    return returnValue;
+}
+
+static psBool checkItemName(psMetadataItem* mdItem, char* expectedName, char* configFile)
+{
+    psBool    returnValue = true;
+
+    // Compare key names
+    if(strcmp(mdItem->name,expectedName) != 0) {
+        psError(PS_ERR_UNKNOWN,true,"File: %s : Key name %s not as expected %s",
+                configFile,mdItem->name,expectedName);
+        returnValue = false;
+    }
+
+    return returnValue;
+}
+
+static psBool checkItemType(psMetadataItem* mdItem, psS32 expectedType, char* configFile)
+{
+    psBool     returnValue = true;
+
+    // Compare types
+    if(mdItem->type != expectedType) {
+        psError(PS_ERR_UNKNOWN,true,"File: %s : Type %d not as expected %d",
+                configFile,mdItem->type,expectedType);
+        returnValue = false;
+    }
+    return returnValue;
+}
+
+static psBool checkItemComment(psMetadataItem* mdItem, char* expectedComment, char* configFile)
+{
+    psBool    returnValue = true;
+
+    // Compare comments
+    if(strcmp(mdItem->comment,expectedComment) != 0) {
+        psError(PS_ERR_UNKNOWN,true,"File: %s : Comment %s not as expected %s",
+                configFile,mdItem->comment,expectedComment);
+        returnValue = false;
+    }
+    return returnValue;
+}
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    if( !runTestSuite(stderr,"psMetadataConfigParse",tests,argc,argv)) {
+        return 1;
+    }
+
+    return 0;
+}
+
+psS32 testMetadataParseConfig(void)
+{
+    psMetadata*       metadata1      = NULL;
+    psMetadataItem*   entryChild     = NULL;
+    psU32             failedLines    = 0;
+    psListIterator*   iter           = NULL;
+    psListIterator*   mdIter         = NULL;
+    psMetadataItem*   mdChild        = NULL;
+    psS32             metaCounter    = 0;
+    psS32             mdCounter      = 0;
+
+    // Read config file test1.config with overwrite set true
+    metadata1 = psMetadataConfigParse(metadata1,&failedLines,testConfig1,true);
+    // Verify the expected number of failed lines
+    if(!checkFailedLines(failedLines,testConfig1FailsOverwrite,(char*)testConfig1)) {
+        return 1;
+    }
+    // Verify the number of items in metadata
+    if(!checkNumberOfItems(metadata1,testConfig1Items,(char*)testConfig1)) {
+        return 2;
+    }
+    // Verify metadata item quads
+    iter = psListIteratorAlloc(metadata1->list, PS_LIST_HEAD, true);
+    for(psS32 i = 0; i < testConfig1Items; i++) {
+        // Get list item
+        entryChild = psListGetAndIncrement(iter);
+
+        // Verify end of list not reached prematurely
+        if(entryChild == NULL) {
+            psError(PS_ERR_UNKNOWN,true,"End of list encountered at %d not as expected %d",
+                    i,testConfig1Items);
+            return i*10+1;
+        }
+        // Verify name
+        if(!checkItemName(entryChild,(char*)testConfig1KeyOverwrite[i],(char*)testConfig1)) {
+            return i*10+2;
+        }
+        // Verify type
+        if(!checkItemType(entryChild,testConfig1TypeOverwrite[i],(char*)testConfig1)) {
+            return i*10+3;
+        }
+        // Verify comment
+        if(!checkItemComment(entryChild,(char*)testConfig1CommentOverwrite[i],(char*)testConfig1)) {
+            return i*10+4;
+        }
+        // Compare values
+        switch(entryChild->type) {
+        case PS_DATA_S32:
+            if(entryChild->data.S32 != testConfig1ValueS32Overwrite[i]) {
+                psError(PS_ERR_UNKNOWN,true,"File: %s : Value %d not as expected %d",
+                        testConfig1,entryChild->data.S32, testConfig1ValueS32Overwrite[i]);
+                return i*10+5;
+            }
+            break;
+        case PS_DATA_F32:
+            if(fabs(entryChild->data.F32 - testConfig1ValueF32Overwrite[i]) > ERROR_TOL) {
+                psError(PS_ERR_UNKNOWN,true,"File: %s : Value %f not as expected %f",
+                        testConfig1,entryChild->data.F32, testConfig1ValueF32Overwrite[i]);
+                return i*10+5;
+            }
+            break;
+        case PS_DATA_F64:
+            if(fabs(entryChild->data.F64 - testConfig1ValueF64Overwrite[i]) > ERROR_TOL) {
+                psError(PS_ERR_UNKNOWN,true,"File: %s : Value %lf not as expected %lf",
+                        testConfig1,entryChild->data.F64, testConfig1ValueF64Overwrite[i]);
+                return i*10+5;
+            }
+            break;
+        case PS_DATA_BOOL:
+            if(entryChild->data.B != testConfig1ValueBoolOverwrite[i]) {
+                psError(PS_ERR_UNKNOWN,true,"File: %s : Value %d not as expected %d",
+                        testConfig1,entryChild->data.B,testConfig1ValueBoolOverwrite[i]);
+                return i*10+5;
+            }
+            break;
+        case PS_DATA_STRING:
+            if(strcmp(entryChild->data.V,testConfig1ValueStrOverwrite[i]) != 0) {
+                psError(PS_ERR_UNKNOWN,true,"File: %s : Value %s not as expected %s",
+                        testConfig1,entryChild->data.V,testConfig1ValueStrOverwrite[i]);
+                return i*10+5;
+            }
+            break;
+        case PS_DATA_VECTOR:
+            // Verify the correct number of entries
+            switch(((psVector*)(entryChild->data.V))->type.type) {
+            case PS_TYPE_U8:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsU8) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsU8);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeU8) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeU8);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsU8; j++) {
+                    if(((psVector*)entryChild->data.V)->data.U8[j] != testConfig1ValueVecValueU8[j]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %d not as expected %d",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.U8[j],
+                                testConfig1ValueVecValueU8[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            case PS_TYPE_U16:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsU16) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsU16);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeU16) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeU16);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsU16; j++) {
+                    if(((psVector*)entryChild->data.V)->data.U16[j] != testConfig1ValueVecValueU16[j]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %d not as expected %d",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.U16[j],
+                                testConfig1ValueVecValueU16[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            case PS_TYPE_U32:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsU32) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsU32);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeU32) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeU32);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsU32; j++) {
+                    if(((psVector*)entryChild->data.V)->data.U32[j] != testConfig1ValueVecValueU32[j]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %d not as expected %d",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.U32[j],
+                                testConfig1ValueVecValueU32[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            case PS_TYPE_U64:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsU64) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsU64);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeU64) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeU64);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsU64; j++) {
+                    if(((psVector*)entryChild->data.V)->data.U64[j] != testConfig1ValueVecValueU64[j]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %ld not as expected %ld",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.U64[j],
+                                testConfig1ValueVecValueU64[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            case PS_TYPE_S8:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsS8) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsS8);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeS8) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeS8);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsS8; j++) {
+                    if(((psVector*)entryChild->data.V)->data.S8[j] != testConfig1ValueVecValueS8[j]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %d not as expected %d",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.S8[j],
+                                testConfig1ValueVecValueS8[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            case PS_TYPE_S16:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsS16) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsS16);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeS16) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeS16);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsS16; j++) {
+                    if(((psVector*)entryChild->data.V)->data.S16[j] != testConfig1ValueVecValueS16[j]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %d not as expected %d",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.S16[j],
+                                testConfig1ValueVecValueS16[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            case PS_TYPE_S32:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsS32) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsS32);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeS32) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeS32);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsS32; j++) {
+                    if(((psVector*)entryChild->data.V)->data.S32[j] != testConfig1ValueVecValueS32[j]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %d not as expected %d",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.S32[j],
+                                testConfig1ValueVecValueS32[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            case PS_TYPE_S64:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsS64) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsS64);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeS64) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeS64);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsS64; j++) {
+                    if(((psVector*)entryChild->data.V)->data.S64[j] != testConfig1ValueVecValueS64[j]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %ld not as expected %ld",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.S64[j],
+                                testConfig1ValueVecValueS64[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            case PS_TYPE_F32:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsF32) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsF32);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeF32) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeF32);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsF32; j++) {
+                    if(fabs(((psVector*)entryChild->data.V)->data.F32[j]-testConfig1ValueVecValueF32[j])
+                            > ERROR_TOL) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %f not as expected %f",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.F32[j],
+                                testConfig1ValueVecValueF32[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            case PS_TYPE_F64:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsF64) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsF64);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeF64) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeF64);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsF64; j++) {
+                    if(fabs(((psVector*)entryChild->data.V)->data.F64[j]-testConfig1ValueVecValueF64[j])
+                            > ERROR_TOL) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %lf not as expected %lf",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.F64[j],
+                                testConfig1ValueVecValueF64[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            default:
+                break;
+            }
+            break;
+        case PS_DATA_METADATA:
+            if(metaCounter == 0) {
+                // Check if number of items is as expected
+                if(entryChild->data.md->list->n != testConfig1ValueMetaItems1) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 1 items %d not as expected %d",
+                            testConfig1,entryChild->data.md->list->n,testConfig1ValueMetaItems1);
+                    return i*10+6;
+                }
+                // Loop through metadata items
+                mdIter = psListIteratorAlloc(entryChild->data.md->list, PS_LIST_HEAD, true);
+                mdCounter = 0;
+                while ( (mdChild = psListGetAndIncrement(mdIter)) != NULL) {
+                    if(strcmp(mdChild->name,testConfig1ValueMetaNames1[mdCounter]) != 0) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 1 name[%d] %s not as expected %s",
+                                testConfig1,mdCounter,mdChild->name,testConfig1ValueMetaNames1[mdCounter]);
+                        return i*10+6*mdCounter;
+                    }
+                    if(mdChild->type != testConfig1ValueMetaTypes1[mdCounter]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 1 type[%d] %d not as expected %d",
+                                testConfig1,mdCounter,mdChild->type,testConfig1ValueMetaTypes1[mdCounter]);
+                        return i*10+6*mdCounter;
+                    }
+                    if(strcmp((char*)mdChild->data.V,testConfig1ValueMetaValue1[mdCounter]) != 0) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 1 value[%d] %s not as expected %s",
+                                testConfig1,mdCounter,(char*)mdChild->data.V,testConfig1ValueMetaValue1[mdCounter]);
+                        return i*10+6*mdCounter;
+                    }
+                    mdCounter++;
+                }
+                psFree(mdIter);
+            } else if(metaCounter == 1) {
+                // Check if number of items is as expected
+                if(entryChild->data.md->list->n != testConfig1ValueMetaItems2) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 2 items %d not as expected %d",
+                            testConfig1,entryChild->data.md->list->n,testConfig1ValueMetaItems2);
+                    return i*10+6;
+                }
+                // Loop through metadata items
+                mdIter = psListIteratorAlloc(entryChild->data.md->list, PS_LIST_HEAD, true);
+                mdCounter = 0;
+                while ( (mdChild = psListGetAndIncrement(mdIter)) != NULL) {
+                    if(strcmp(mdChild->name,testConfig1ValueMetaNames2[mdCounter]) != 0) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 2 name[%d] %s not as expected %s",
+                                testConfig1,mdCounter,mdChild->name,testConfig1ValueMetaNames2[mdCounter]);
+                        return i*10+6*mdCounter;
+                    }
+                    if(mdChild->type != testConfig1ValueMetaTypes2[mdCounter]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 2 type[%d] %d not as expected %d",
+                                testConfig1,mdCounter,mdChild->type,testConfig1ValueMetaTypes2[mdCounter]);
+                        return i*10+6*mdCounter;
+                    }
+                    if(strcmp((char*)mdChild->data.V,testConfig1ValueMetaValue2[mdCounter]) != 0) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 2 value[%d] %s not as expected %s",
+                                testConfig1,mdCounter,(char*)mdChild->data.V,testConfig1ValueMetaValue2[mdCounter]);
+                        return i*10+6*mdCounter;
+                    }
+                    mdCounter++;
+                }
+                psFree(mdIter);
+            } else if(metaCounter == 2) {
+                // Check if number of items is as expected
+                if(entryChild->data.md->list->n != testConfig1ValueMetaItems3) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 3 items %d not as expected %d",
+                            testConfig1,entryChild->data.md->list->n,testConfig1ValueMetaItems3);
+                    return i*10+6;
+                }
+                // Loop through metadata items
+                mdIter = psListIteratorAlloc(entryChild->data.md->list, PS_LIST_HEAD, true);
+                mdCounter = 0;
+                while ( (mdChild = psListGetAndIncrement(mdIter)) != NULL) {
+                    if(strcmp(mdChild->name,testConfig1ValueMetaNames3[mdCounter]) != 0) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 3 name[%d] %s not as expected %s",
+                                testConfig1,mdCounter,mdChild->name,testConfig1ValueMetaNames3[mdCounter]);
+                        return i*10+6*mdCounter;
+                    }
+                    if(mdChild->type != testConfig1ValueMetaTypes3[mdCounter]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 3 type[%d] %d not as expected %d",
+                                testConfig1,mdCounter,mdChild->type,testConfig1ValueMetaTypes3[mdCounter]);
+                        return i*10+6*mdCounter;
+                    }
+                    switch(mdChild->type) {
+                    case PS_DATA_STRING:
+                        if(strcmp((char*)mdChild->data.V,testConfig1ValueMetaValueStr3[mdCounter]) != 0) {
+                            psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 3 value[%d] %s not as expected %s",
+                                    testConfig1,mdCounter,(char*)mdChild->data.V,
+                                    testConfig1ValueMetaValueStr3[mdCounter]);
+                            return i*10+6*mdCounter;
+                        }
+                        break;
+                    case PS_DATA_S32:
+                        if(mdChild->data.S32 != testConfig1ValueMetaValueS323[mdCounter]) {
+                            psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 3 value[%d] %d not as expected %d",
+                                    testConfig1,mdCounter,mdChild->data.S32,
+                                    testConfig1ValueMetaValueS323[mdCounter]);
+                            return i*10+6*mdCounter;
+                        }
+                        break;
+                    default:
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 3 value[%d] unknown type",
+                                testConfig1,mdCounter);
+                        return i*10+6*mdCounter;
+                        break;
+                    }
+                    mdCounter++;
+                }
+                psFree(mdIter);
+            }
+            metaCounter++;
+            break;
+        default:
+            psError(PS_ERR_UNKNOWN,true,"Unexpected type %d encountered",entryChild->type);
+            return i*10+5;
+            break;
+        }
+    }
+
+    writeMetadata(metadata1,"");
+
+    psFree(metadata1);
+
+    return 0;
+}
+
+psS32 testMetadataParseConfig1(void)
+{
+    psMetadata*       metadata1      = NULL;
+    psU32             failedLines    = 0;
+
+    // Read config file test2.config with overwrite set true
+    // This file contains parse errors
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate parse error message");
+    metadata1 = psMetadataConfigParse(metadata1,&failedLines,testConfig2,true);
+    // Verify the expected number of failed lines
+    if(!checkFailedLines(failedLines,testConfig2Fails,(char*)testConfig2)) {
+        return 1;
+    }
+    // Verify return value is null
+    if(metadata1 == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expected a NULL return for failed parse");
+        return 2;
+    }
+    psFree(metadata1);
+
+    // Attempt parse a non-existant file
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    metadata1 = psMetadataConfigParse(metadata1,&failedLines,"ab.config",true);
+    if(metadata1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Expected a NULL return for non-existant file");
+        return 3;
+    }
+
+    // Attempt parse with NULL failed lines ptr
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL failed lines arg");
+    metadata1 = psMetadataConfigParse(metadata1,NULL,testConfig2,true);
+    if(metadata1 == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return for NULL failed lines argument");
+        return 4;
+    }
+    psFree(metadata1);
+    // Attempt parse with NULL file name
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL file name arg");
+    metadata1 = psMetadataConfigParse(metadata1,&failedLines,NULL,true);
+    if(metadata1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Expected a NULL return for NULL filename argument");
+        return 5;
+    }
+
+    psFree(metadata1);
+
+    return 0;
+}
+
+psS32 testMetadataParseConfig2(void)
+{
+    psMetadata*       metadata1      = NULL;
+    psU32             failedLines    = 0;
+
+    // Read config file test3.config with overwrite set false
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error of duplicate key names");
+    metadata1 = psMetadataConfigParse(metadata1,&failedLines,testConfig3,false);
+    // Verify the expected number of failed lines
+    if(!checkFailedLines(failedLines,testConfig3Fails,(char*)testConfig3)) {
+        return 1;
+    }
+    if(metadata1 == NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expected a NULL return for failed due to overwrite false");
+        return 2;
+    }
+    psFree(metadata1);
+
+    return 0;
+}
+
+psS32 testMetadataParseConfig3(void)
+{
+    psMetadata*       metadata1      = NULL;
+    psU32             failedLines    = 0;
+
+    // Read config file test4.config with overwrite set false
+    metadata1 = psMetadataConfigParse(metadata1,&failedLines,testConfig4,false);
+    // Verify the expected number of failed lines
+    if(!checkFailedLines(failedLines,testConfig4Fails,(char*)testConfig4)) {
+        return 1;
+    }
+    // Print out metadata items for comparison against STDERR verified file
+    writeMetadata(metadata1,"");
+
+    psFree(metadata1);
+
+    return 0;
+}
+
+psS32 testMetadataParseConfig4(void)
+{
+    psMetadata*       metadata1      = NULL;
+    psU32             failedLines    = 0;
+
+    // Read config file test4.config with overwrite set false
+    metadata1 = psMetadataConfigParse(metadata1,&failedLines,testConfig5,true);
+    // Verify the expected number of failed lines
+    if(!checkFailedLines(failedLines,testConfig5Fails,(char*)testConfig5)) {
+        return 1;
+    }
+    psFree(metadata1);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_01.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_01.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_01.c	(revision 22158)
@@ -0,0 +1,299 @@
+/** @file  tst_psMetadata_01.c
+*
+*  @brief Test driver for psMetadata functions
+*
+*  @author  dRob, MHPCC
+*
+*  @version $Revision: 1.12 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2006-08-09 00:06:26 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include <string.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+
+static psS32 testMetadataItemCopy(void);
+static psS32 testMetadataItemTransfer(void);
+static psS32 testMetadataPrint(void);
+static psS32 testMetadataItemCompare(void);
+static psS32 testMetadataItemParse(void);
+
+testDescription tests[] = {
+                              {testMetadataItemCopy, 666, "psMetadataItemCopy()", 0, false},
+                              {testMetadataItemTransfer, 1, "psMetadataItemTransfer()", 0, false},
+                              {testMetadataPrint,667,"psMetadataPrint",0,false},
+                              {testMetadataItemCompare,669,"psMetadataItemCompare",0,false},
+                              {testMetadataItemParse,665,"psMetadataItemParse",0,false},
+                              {NULL}
+                          };
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetLevel( PS_LOG_INFO );
+
+    return ( !runTestSuite(stderr,"psMetadata_01",tests,argc,argv) );
+
+}
+
+psS32 testMetadataItemCopy(void)
+{
+    psMetadataItem *item = psMetadataItemAlloc("metaITEM", PS_DATA_S32, "no Comment");
+    item->data.S32 = 666;
+    psMetadataItem *item2 = NULL;
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    item2 = psMetadataItemCopy(NULL);
+    if (item2 != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psMetadataItemCopy failed to return NULL for NULL input psMetadataItem.\n");
+        return 1;
+    }
+
+    //Simple copy of psS32 data
+    item2 = psMetadataItemCopy(item);
+    if (item2 == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psMetadataItemCopy incorrectly returned NULL for valid input psMetadataItem.\n");
+        return 2;
+    }
+    if ( strncmp(item2->name, item->name, 10) || item2->type != item->type ||
+            item2->data.S32 != item->data.S32 || strncmp(item2->comment, item->comment, 15) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psMetadataItemCopy returned an incorrect psMetadataItem (S32 test).\n");
+        return 3;
+    }
+    psFree(item2);
+    psFree(item);
+    item2 = NULL;
+
+    //Copy of MetadataItem containing a psMetadata
+    psMetadata* metadata = psMetadataAlloc();
+    psMetadataAddS32(metadata, PS_LIST_TAIL, "item01", 0, "", 55);
+    psMetadataAddF32(metadata, PS_LIST_TAIL, "item02", 0, NULL, 3.14);
+    item = psMetadataItemAlloc("metaItem2", PS_DATA_METADATA, "newMeta", metadata);
+    item2 = psMetadataItemCopy(item);
+    if (item2 == NULL || item2->data.md == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psMetadataItemCopy returned either a NULL item or NULL metadata data\n");
+        return 4;
+    }
+    if ( strncmp(item2->name, item->name, 11) || item2->type != item->type ||
+            strncmp(item2->comment, item->comment, 15) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psMetadataItemCopy returned an incorrect psMetadataItem (Metadata test).\n");
+        return 5;
+    }
+    psMetadataItem *temp1 = psMetadataGet(item->data.md, PS_LIST_HEAD);
+    psMetadataItem *temp2 = psMetadataGet(item2->data.md, PS_LIST_HEAD);
+    if ( strncmp(temp2->name, temp1->name, 10) || temp2->type != temp1->type ||
+            temp2->data.S32 != temp1->data.S32 || strncmp(temp2->comment, temp1->comment, 15) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psMetadataItemCopy incorrectly returned non-matching metadata data.\n");
+        return 6;
+    }
+
+    psFree(item2);
+    psFree(metadata);
+    psFree(item);
+    return 0;
+}
+
+psS32 testMetadataItemTransfer(void)
+{
+
+    psMetadata *md = psMetadataAlloc();
+    psMetadata *out = NULL;
+    psMetadataAddS32(md, PS_LIST_TAIL, "metaITEM", 0, "no Comment", 666);
+
+    //attempt transfer to NULL 'out' metadata.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psMetadataItemTransfer(out, md, "metaITEM") ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psMetadataItemTransfer failed to return false for NULL 'out' metadata.\n");
+        return 1;
+    }
+    out = psMetadataAlloc();
+    //attempt to transfer using a NULL key.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psMetadataItemTransfer(out, md, NULL) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psMetadataItemTransfer failed to return false for NULL key input.\n");
+        return 2;
+    }
+    //attempt transfer to NULL 'in' metadata.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psMetadataItemTransfer(out, NULL, "metaITEM") ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psMetadataItemTransfer failed to return false for NULL 'in' metadata.\n");
+        return 3;
+    }
+    //attempt to transfer using an allocated metadata and invalid key
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if (psMetadataItemTransfer(out, md, "metaITEM2") ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psMetadataItemTransfer failed to return false for invalid 'key'.\n");
+        return 4;
+    }
+    //attempt to transfer with all valid inputs.
+    psMetadataItem *item = NULL;
+    if ( !psMetadataItemTransfer(out, md, "metaITEM") ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psMetadataItemTransfer failed with valid inputs.\n");
+        return 7;
+    }
+    item = psMetadataGet(out, PS_LIST_HEAD);
+    if (item->data.S32 != 666 || strncmp(item->comment, "no Comment", 20)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psMetadataItemTransfer failed to correctly transfer item data.\n");
+        return 8;
+    }
+
+    psFree(out);
+    psFree(md);
+
+    return 0;
+}
+
+static psMetadata *setupMeta2(void)
+{
+    psMetadata *md = NULL;
+    psVector *vec = NULL;
+    psMetadata *newMD = NULL;
+    psTime *time;
+    int i = 0;
+    md = psMetadataAlloc();
+    newMD = psMetadataAlloc();
+    vec = psVectorAlloc(60, PS_DATA_S32);
+    time = psTimeAlloc(PS_TIME_TAI);
+    for (i = 0; i < 5; i++) {
+        vec->data.S32[i] = i+1;
+    }
+    vec->n = 5;
+    time->sec = 1000;
+    time->nsec = 25;
+    time->leapsecond = true;
+    psMetadataAddBool(md, PS_LIST_TAIL, "item1", 0, "I am a boolean", true);
+    psMetadataAddS32(md, PS_LIST_TAIL, "item2", 0, "I am a integer", 55);
+    psMetadataAddF32(md, PS_LIST_TAIL, "item3", 0, NULL, 3.14);
+    psMetadataAddF64(md, PS_LIST_TAIL, "item4", 0, "", 6.28);
+    psMetadataAddStr(md, PS_LIST_TAIL, "item5", 0, "I am a string", "GNIRTS");
+    psMetadataAddVector(md, PS_LIST_TAIL, "vector6", 0, "I am a vector", vec);
+    psMetadataAddTime(md, PS_LIST_TAIL, "time01", 0, "I am time", time);
+    psMetadataAddS8(md, PS_LIST_TAIL, "item6", 0, "I am S8", 6);
+    psMetadataAddS16(md, PS_LIST_TAIL, "item7", 0, "I am S16", -666);
+    psMetadataAddU8(md, PS_LIST_TAIL, "item8", 0, "I am U8", 6);
+    psMetadataAddU16(md, PS_LIST_TAIL, "item9", 0, "I am U16", 666);
+    psMetadataAddU32(md, PS_LIST_TAIL, "item10", 0, "I am U32", 666);
+    psMetadataAddS64(md, PS_LIST_TAIL, "item11", 0, "I am S64", 666);
+    psMetadataAddU64(md, PS_LIST_TAIL, "item12", 0, "I am U64", 666);
+
+    psMetadataAddS32(newMD, PS_LIST_TAIL, "ITEM01", 0, NULL, 666);
+    psMetadata *newestMD = NULL;
+    newestMD = psMetadataAlloc();
+    psMetadataAddVector(newestMD, PS_LIST_TAIL, "VECTORNEW", 0, "Newest VECTOR", vec);
+    psMetadataAddStr(newestMD, PS_LIST_TAIL, "cell", 0, "I am a p-Star", "pStArRs");
+    psMetadataAddMetadata(newMD, PS_LIST_TAIL, "META NEW", 0, "I AM Newest METADATA", newestMD);
+    psMetadataAddF32(newMD, PS_LIST_TAIL, "ITEM02", 0, "I AM FLOAT", 666.6);
+    psMetadataAddF64(newMD, PS_LIST_TAIL, "ITEM03", 0, "I AM DOUBLE", 666.666);
+
+    psMetadataAddMetadata(md, PS_LIST_TAIL, "metadata7", 0, "I am a metadata", newMD);
+    psFree(time);
+    psFree(newestMD);
+    psFree(vec);
+    psFree(newMD);
+    return md;
+}
+
+psS32 testMetadataPrint(void)
+{
+    psMetadata *meta = NULL;
+    meta = setupMeta2();
+    psMetadataPrint(NULL, meta, 0);
+    psFree(meta);
+    return 0;
+}
+
+psS32 testMetadataItemCompare(void)
+{
+    psMetadataItem *compare = NULL;
+    psMetadataItem *template = NULL;
+    psMetadataItem *itemCopy = NULL;
+    psMetadataItem *item = psMetadataItemAlloc("Snickers", PS_DATA_BOOL, "No Comment", true)
+                           ;
+    if (!item->data.B) {
+        return 1;
+    }
+
+    //compare = NULL
+    if ( psMetadataItemCompare(compare, item)) {
+        return 2;
+    }
+    //template = NULL
+    if ( psMetadataItemCompare(item, template)) {
+        return 3;
+    }
+
+    template = psMetadataItemAlloc("Milky Way", PS_DATA_BOOL, "No Comment", true)
+               ;
+    compare = psMetadataItemAlloc("Snickers", PS_DATA_S32, "No Comment", 1);
+    //template->name != item->name
+    if ( psMetadataItemCompare(template, item) ) {
+        return 4;
+    }
+    //compare->type != item->type
+    if ( psMetadataItemCompare(compare, item) ) {
+        printf("\ncompare == item b/c of type\n");
+        //        return 5;
+    }
+
+    //compare->type == F32  compare->data.F32 = 1.4
+    psFree(compare);
+    compare = psMetadataItemAlloc("Snickers", PS_DATA_F64, "No Comment", 1.00001);
+    if ( psMetadataItemCompare(compare, item) ) {
+        printf("\ncompare2 == item b/c of type\n");
+        //        return 5;
+    }
+    psFree(template)
+    ;
+    template = psMetadataItemAlloc("Snickers", PS_DATA_S32, "No Comment", 1)
+               ;
+    if ( psMetadataItemCompare(compare, template) ) {
+        printf("\ncompare3 == item b/c of type\n");
+        //        return 5;
+    }
+
+    psFree(template)
+    ;
+    template = psMetadataItemAlloc("Snickers", PS_DATA_F32, "No Comment", 1.00001)
+               ;
+    if ( psMetadataItemCompare(compare, template) ) {
+        printf("\ncompare4 == item b/c of type\n");
+        //        return 5;
+    }
+
+
+    //itemCopy == item
+    itemCopy = psMetadataItemCopy(item);
+    if ( !psMetadataItemCompare(itemCopy, item) ) {
+        return 7;
+    }
+
+    psFree(compare);
+    psFree(template)
+    ;
+    psFree(itemCopy);
+    psFree(item);
+
+    return 0;
+}
+
+psS32 testMetadataItemParse(void)
+{
+
+    return 0;
+}
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_02.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_02.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_02.c	(revision 22158)
@@ -0,0 +1,145 @@
+/** @file  tst_psMetadata_02.c
+ *
+ *  @brief Test driver for psMetadata functions
+ *
+ *  This test driver contains the following tests for psMetadata:
+ *     Test A - Allocate metadata items
+ *     Test B - Attempt to create metadata item with null name
+ *     Test C - Attempt to create metadata item with invalid type
+ *     Test D - Allocate metadata
+ *     Test E - Attempt to add metadata item to null metadata
+ *     Test F - Attempt to add null metadata item to metadata
+ *     Test G - Free psMetadata
+ *
+ *  @author  Ross Harman, MHPCC
+ *  @author  Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2005-09-26 21:13:33 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include <string.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+
+static void printMetadataItem(psMetadataItem *metadataItem)
+{
+    printf("Key Name: %8s  ", metadataItem->name);
+    printf("Key mdType: 0x%08x  ", metadataItem->type);
+
+    switch (metadataItem->type) {
+    case PS_DATA_METADATA_MULTI:
+        printf("Key Value: %17c", ' ');
+        break;
+    case PS_DATA_BOOL:
+        printf("Key Value: %15d  ", metadataItem->data.B);
+        break;
+    case PS_DATA_S32:
+        printf("Key Value: %15d  ", metadataItem->data.S32);
+        break;
+    case PS_DATA_F32:
+        printf("Key Value: %15.3f  ", metadataItem->data.F32);
+        break;
+    case PS_DATA_F64:
+        printf("Key Value: %15.3f  ", metadataItem->data.F64);
+        break;
+    case PS_DATA_STRING:
+        printf("Key Value: %15s  ", (char*)metadataItem->data.V);
+        break;
+    default:
+        printf("Bad type: %d ", metadataItem->type);
+    }
+    printf("Key Comment: %s\n", metadataItem->comment);
+}
+
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psMetadataItem *item1 = NULL;
+    psMetadata *metadata = NULL;
+    psMetadataItem *item2 = NULL;
+    psMetadataItem *item3 = NULL;
+    psMetadataItem *item4 = NULL;
+    psMetadataItem *item5 = NULL;
+    psMetadataItem *badItem = NULL;
+
+
+    // Test A - Allocate metadata items
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Allocate metadata items");
+    item1 = psMetadataItemAlloc("myItem1", PS_DATA_BOOL, "I am a boolean", true);
+    item2 = psMetadataItemAlloc("myItem2", PS_DATA_S32, "I am a signed integer", 111);
+    item3 = psMetadataItemAlloc("myItem3", PS_DATA_F32, "I am a single precision floating point", 222.222);
+    item4 = psMetadataItemAlloc("myItem4", PS_DATA_F64, "I am a double precision floating point", 333.333);
+    item5 = psMetadataItemAlloc("myItem5", PS_DATA_STRING, "I am a string", "HELLO WORLD");
+    printMetadataItem(item1);
+    printMetadataItem(item2);
+    printMetadataItem(item3);
+    printMetadataItem(item4);
+    printMetadataItem(item5);
+    printFooter(stdout, "psMetadata", "Test A - Allocate metadata items", true);
+
+
+    // Test B - Attempt to create metadata item with null name
+    printNegativeTestHeader(stdout,"psMetadata", "Test B - Attempt to create metadata item with null name",
+                            "Null value for name not allowed", 0);
+    psLogMsg(__func__,PS_LOG_INFO,"Following should produce error for null name.");
+    badItem = psMetadataItemAlloc(NULL, PS_DATA_STRING, "I am a string", "HELLO WORLD");
+    if (badItem != NULL) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataItemAlloc did not return null with null name item.");
+        return 10;
+    }
+    printFooter(stdout, "psMetadata", "Test B - Attempt to create metadata item with null name", true);
+
+
+    // Test C - Attempt to create metadata item with invalid type
+    printNegativeTestHeader(stdout,"psMetadata", "Test C - Attempt to create metadata item with invalid type",
+                            "Invalid psDataType: 6", 0);
+    badItem = psMetadataItemAlloc("badItem", -1, "I am bad", "Bad comment");
+    printFooter(stdout, "psMetadata", "Test C - Attempt to create metadata item with invalid type", true);
+
+
+    // Test D - Allocate metadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test D - Allocate metadata");
+    metadata = psMetadataAlloc();
+    printFooter(stdout, "psMetadata", "Test D - Allocate metadata", true);
+
+
+    // Test E - Attempt add metadata item to null metadata
+    printNegativeTestHeader(stdout,"psMetadata", "Test E - Attempt to add metadata item to null metadata",
+                            "Null metadata collection not allowed", 0);
+    psMetadataAddItem(NULL, item1, PS_LIST_HEAD, PS_META_DEFAULT);
+    printFooter(stdout, "psMetadata", "Test E - Attempt to add metadata item to null metadata", true);
+
+
+    // Test F - Attempt add null metadata item to metadata
+    printNegativeTestHeader(stdout,"psMetadata", "Test F - Attempt to add null metadata item to metadata",
+                            "Null metadata item not allowed", 0);
+    psMetadataAddItem(metadata, NULL, PS_LIST_HEAD, PS_META_DEFAULT);
+    printFooter(stdout, "psMetadata", "Test F - Attempt to add null metadata item to metadata", true);
+
+
+    // Test G - Free psMetadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test G - Free psMetadata");
+    psFree(item1);
+    psFree(item2);
+    psFree(item3);
+    psFree(item4);
+    psFree(item5);
+    psFree(badItem);
+    psFree(metadata);
+    if(psMemCheckLeaks(0, NULL, stdout,false) ) {
+        psError(PS_ERR_UNKNOWN,true,"Memory leaks detected.");
+        return 10;
+    }
+    psMemCheckCorruption(0);
+    psS32 nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMetadata", "Test G - Free psMetadata", true);
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_03.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_03.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_03.c	(revision 22158)
@@ -0,0 +1,241 @@
+/** @file  tst_psMetadata_03.c
+*
+*  @brief Test driver for psMetadata functions
+*
+*  This test driver contains the following tests for psMetadata:
+*     Test A - Allocate metadata and items
+*     Test B - Remove items from metadata by name
+*     Test C - Remove items from metadata by index
+*     Test D - Attempt to use null metadata
+*     Test E - Attempt to remove non-existant metadata item by name
+*     Test F - Attempt to remove non-existant metadata item by index
+*     Test G - Attempt to add item to an invalid metadata structure
+*     Test H - Attempt to add item to an invalid metadata structure
+*     Test I - Attempt to add item with a null name
+*     Test J - Attempt to add item to an invalid metadata structure
+*     Test K - Free psMetadata
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2005-09-26 21:13:33 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include <string.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+
+static void printMetadataItem(psMetadataItem *metadataItem)
+{
+    printf("Key Name: %8s  ", metadataItem->name);
+    printf("Key mdType: 0x%08x  ", metadataItem->type);
+
+    switch (metadataItem->type) {
+    case PS_DATA_METADATA_MULTI:
+        printf("Key Value: %17c", ' ');
+        break;
+    case PS_DATA_BOOL:
+        printf("Key Value: %15d  ", metadataItem->data.B);
+        break;
+    case PS_DATA_S32:
+        printf("Key Value: %15d  ", metadataItem->data.S32);
+        break;
+    case PS_DATA_F32:
+        printf("Key Value: %15.3f  ", metadataItem->data.F32);
+        break;
+    case PS_DATA_F64:
+        printf("Key Value: %15.3f  ", metadataItem->data.F64);
+        break;
+    case PS_DATA_STRING:
+        printf("Key Value: %15s  ", (char*)metadataItem->data.V);
+        break;
+    default:
+        printf("Bad type: %d ", metadataItem->type);
+    }
+    printf("Key Comment: %s\n", metadataItem->comment);
+}
+
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psMetadataItem *item1 = NULL;
+    psMetadataItem *item2 = NULL;
+    psMetadataItem *item3 = NULL;
+    psMetadataItem *item4 = NULL;
+    psMetadataItem *errItem = NULL;
+    psMetadata *metadata = NULL;
+    psMetadata *errMetadata = NULL;
+    psHash *mdTable = NULL;
+    psList *mdList = NULL;
+    char *errName = NULL;
+
+    // Test A - Allocate metadata and items
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Allocate metadata items");
+    metadata = psMetadataAlloc();
+    item1 = psMetadataItemAlloc("myItem1", PS_DATA_BOOL, "I am a boolean", true);
+    item2 = psMetadataItemAlloc("myItem2", PS_DATA_S32, "I am a integer", 55);
+    item3 = psMetadataItemAlloc("myItem3", PS_DATA_BOOL, "I am a boolean", false);
+    item4 = psMetadataItemAlloc("myItem4", PS_DATA_S32, "I am a integer", 66);
+    errItem = psMetadataItemAlloc("errItem", PS_DATA_S32, "I am a integer", 99);
+    printMetadataItem(item1);
+    printMetadataItem(item2);
+    printMetadataItem(item3);
+    printMetadataItem(item4);
+    printFooter(stdout, "psMetadata", "Test A - Allocate metadata items", true);
+
+
+    // Test B - Remove items from metadata by name
+    printPositiveTestHeader(stdout, "psMetadata", "Test B - Remove items from metadata by name");
+    if(!psMetadataAddItem(metadata, item1, PS_LIST_HEAD, PS_META_DEFAULT)) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return true when adding by name.");
+        return 10;
+    }
+    if(!psMetadataAdd(metadata,PS_LIST_HEAD,"myItem2", PS_DATA_S32, "I am S32 integer",77)) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return true when adding by name.");
+        return 11;
+    }
+    if (!psMetadataRemove(metadata, 0, "myItem1")) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataRemove did not return true when removing by name.");
+        return 12;
+    }
+    if (!psMetadataRemove(metadata, 0, "myItem2")) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataRemove did not return true when removing by name.");
+        return 13;
+    }
+    printFooter(stdout, "psMetadata", "Test B - Remove items from metadata by name", true);
+
+
+    // Test C - Remove items from metadata by index
+    printPositiveTestHeader(stdout, "psMetadata", "Test C - Remove items from metadata by index");
+    if ( ! psMetadataAddItem(metadata, item3, PS_LIST_HEAD, PS_META_DEFAULT) ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return true when adding by index.");
+        return 14;
+    }
+    if ( ! psMetadataAdd(metadata,PS_LIST_HEAD,"myItem4", PS_DATA_S32, "I am S32 integer",88) ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return true when adding by index.");
+        return 15;
+    }
+    if( ! psMetadataRemove(metadata, 0, NULL) ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataRemove did not return true when removing by index.");
+        return 16;
+    }
+    if ( ! psMetadataRemove(metadata, 0, NULL ) ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataRemove did not return true when removing by index.");
+        return 17;
+    }
+    printFooter(stdout, "psMetadata", "Test C - Remove items from metadata by index", true);
+
+
+    // Test D - Attempt to use null metadata
+    printNegativeTestHeader(stdout,"psMetadata", "Test D - Attempt to use null metadata",
+                            "Null metadata collection not allowed", 0);
+    if ( psMetadataRemove(NULL, 0, NULL) ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataRemove did not return false when removing from null metadata.");
+        return 18;
+    }
+    printFooter(stdout, "psMetadata", "Test D - Attempt to use null metadata", true);
+
+
+    // Test E - Attempt to remove non-existant metadata item by name
+    printNegativeTestHeader(stdout,"psMetadata", "Test E - Attempt to remove non-existant metadata item by name",
+                            "Couldn't find metadata item. Name: AARGH", 0);
+    if( psMetadataRemove(metadata, 0, "AARGH") ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataRemove did not return false when removing non-existant item.");
+        return 19;
+    }
+    printFooter(stdout, "psMetadata", "Test E - Attempt to remove non-existant metadata item by name", true);
+
+
+    // Test F - Attempt to remove non-existant metadata item by index
+    printNegativeTestHeader(stdout,"psMetadata", "Test E - Attempt to remove non-existant metadata item by index",
+                            "Couldn't find metadata item in list. Index: 22", 0);
+    if( psMetadataRemove(metadata, 22, NULL) ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataRemove did not return false when removing non-existant item.");
+        return 20;
+    }
+    printFooter(stdout, "psMetadata", "Test E - Attempt to remove non-existant metadata item by index", true);
+
+
+    // Test G - Attempt to add item to an invalid metadata structure
+    printNegativeTestHeader(stdout,"psMetadata","Test G - Attempt to add item to metadata w/o hash table",
+                            "Couldn't add item to invalid metadata structure.",0);
+    errMetadata = psMetadataAlloc();
+    mdTable = errMetadata->hash;
+    errMetadata->hash = NULL;
+    if ( psMetadataAddItem(errMetadata, item3, PS_LIST_HEAD, PS_META_DEFAULT) ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return false w/ invalid metadata struct w/o hash table.");
+        return 21;
+    }
+    if ( psMetadataRemove(errMetadata, PS_LIST_HEAD, "errItem") ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataRemove did not return false w/ invalid metadata struct w/o hash table.");
+        return 31;
+    }
+    errMetadata->hash = mdTable;
+    printFooter(stdout,"psMetadata","Test G - Attempt to add item to invalid metadata w/o hash table", true);
+
+    // Test H - Attempt to add item to an invalid metadata structure
+    printNegativeTestHeader(stdout,"psMetadata","Test H - Attempt to add item to metadata w/o link list",
+                            "Couldn't add item to invalid metadata structure.",0);
+    mdList = errMetadata->list;
+    errMetadata->list = NULL;
+    if ( psMetadataAddItem(errMetadata, item3, PS_LIST_HEAD, PS_META_DEFAULT) ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return false w/ invalid metadata struct w/o link list.");
+        return 22;
+    }
+    if ( psMetadataRemove(errMetadata, PS_LIST_HEAD, "errItem") ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataRemove did not return false w/ invalid metadata struct w/o link list.");
+        return 32;
+    }
+    errMetadata->list = mdList;
+    printFooter(stdout,"psMetadata","Test H - Attempt to add item to invalid metadata w/o link list", true);
+
+    // Test I - Attempt to add item with a null name
+    printNegativeTestHeader(stdout,"psMetadata","Test I - Attempt to add item with null name",
+                            "Couldn't add item with null name.",0);
+    errName = errItem->name;
+    errItem->name = NULL;
+    if ( psMetadataAddItem(errMetadata, errItem, PS_LIST_HEAD, PS_META_DEFAULT) ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return false with item with null name.");
+        return 23;
+    }
+    errItem->name = errName;
+    printFooter(stdout,"psMetadata","Test I - Attempt to add item with null name", true);
+
+    // Test J - Attempt to add item to an invalid metadata structure
+    printNegativeTestHeader(stdout,"psMetadata","Test J - Attempt to add item to metadata w/o hash table",
+                            "Couldn't add item to invalid metadata structure.",0);
+    mdTable = errMetadata->hash;
+    errMetadata->hash = NULL;
+    if (psMetadataAdd(errMetadata, PS_LIST_HEAD, "errItem", PS_DATA_S32, "Integer",22) ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return false w/ invalid metadata struct w/o hash table.");
+        return 24;
+    }
+    errMetadata->hash = mdTable;
+    printFooter(stdout,"psMetadata","Test J - Attempt to add item to invalid metadata w/o hash table", true);
+
+    // Test K - Free psMetadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test K - Free psMetadata");
+    psFree(metadata);
+    psFree(item1);
+    psFree(item2);
+    psFree(item3);
+    psFree(item4);
+    psFree(errItem);
+    psFree(errMetadata);
+    if( psMemCheckLeaks(0, NULL, stdout,false) != 0 ) {
+        psError(PS_ERR_UNKNOWN, true,"Memory leaks detected.");
+        return 25;
+    }
+    psMemCheckCorruption(0);
+    psS32 nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMetadata", "Test K - Free psMetadata", true);
+
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_04.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_04.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_04.c	(revision 22158)
@@ -0,0 +1,332 @@
+/** @file  tst_psMetadata_04.c
+ *
+ *  @brief Test driver for psMetadata functions
+ *
+ *  This test driver contains the following tests for psMetadata:
+ *     Test A - Allocate metadata and items
+ *     Test B - Lookup metadata item by name
+ *     Test C - Attempt to use null metadata
+ *     Test D - Attempt to use null key
+ *     Test E - Attempt to lookup non-existant metadata item
+ *     Test F - Lookup metadata item by index
+ *     Test G - Lookup metadata item and return psS32 value
+ *     Test H - Lookup metadata item and return psF64 value
+ *     Test I - Lookup metadata item and return psVector pointer
+ *     Test J - Lookup metadata item and return psMetadata pointer
+ *     Test K - Lookup metadata item and return psString value
+ *     Test L - Attempt to use null metadata
+ *     Test M - Attempt to get non-existant metadata item
+ *     Test N - Attempt to look up with an invalid metadata object
+ *     Test O - Attempt get item  with an invalid metadata object
+ *     Test P - Attempt get value of non-existant metadata item
+ *     Test Q - Free psMetadata
+ *
+ *  @author  Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.11 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2006-02-03 00:12:02 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include <string.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+
+static void printMetadataItem(psMetadataItem *metadataItem)
+{
+    printf("Key Name: %8s  ", metadataItem->name);
+    printf("Key mdType: 0x%08x  ", metadataItem->type);
+
+    switch (metadataItem->type) {
+    case PS_DATA_METADATA_MULTI:
+        printf("Key Value: %17c", ' ');
+        break;
+    case PS_DATA_BOOL:
+        printf("Key Value: %15d  ", metadataItem->data.B);
+        break;
+    case PS_DATA_S32:
+        printf("Key Value: %15d  ", metadataItem->data.S32);
+        break;
+    case PS_DATA_F32:
+        printf("Key Value: %15.3f  ", metadataItem->data.F32);
+        break;
+    case PS_DATA_F64:
+        printf("Key Value: %15.3f  ", metadataItem->data.F64);
+        break;
+    case PS_DATA_STRING:
+        printf("Key Value: %15s  ", (char*)metadataItem->data.V);
+        break;
+    default:
+        printf("Bad type: %d ", metadataItem->type);
+    }
+    printf("Key Comment: %s\n", metadataItem->comment);
+}
+
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psBool status = 0;
+    psMetadataItem *item1 = NULL;
+    psMetadataItem *item2 = NULL;
+    psMetadataItem *item3 = NULL;
+    psMetadataItem *item4 = NULL;
+    psMetadataItem *item5 = NULL;
+    psMetadataItem *item6 = NULL;
+    psMetadataItem *item7 = NULL;
+    psMetadataItem *item8 = NULL;
+    psMetadataItem *item = NULL;
+    psMetadata *metadata = NULL;
+    psMetadata *newMD = NULL;
+    char string[50];
+    psHash* tmpTable = NULL;
+    psList* tmpList = NULL;
+
+
+    // Test A - Allocate metadata and items
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Allocate metadata items");
+    psVector *vec = psVectorAlloc(5, PS_TYPE_S32);
+    metadata = psMetadataAlloc();
+    newMD = psMetadataAlloc();
+    strncpy(string, "String was here", 50);
+    psMetadataAddF64(newMD, PS_LIST_HEAD, "yourItem1", 0, "I am a psF64", 4.14);
+    item1 = psMetadataItemAlloc("myItem1", PS_DATA_BOOL, "I am a boolean", true);
+    item2 = psMetadataItemAlloc("myItem2", PS_DATA_S32, "I am a integer", 55);
+    item3 = psMetadataItemAlloc("myItem3", PS_DATA_BOOL, "I am a boolean", false);
+    item4 = psMetadataItemAlloc("myItem4", PS_DATA_S32, "I am a integer", 66);
+    item5 = psMetadataItemAlloc("myItem5", PS_DATA_F64, "I am a double", 3.14);
+    item6 = psMetadataItemAlloc("myItem6", PS_DATA_VECTOR, "I am a vector", vec);
+    item7 = psMetadataItemAlloc("myItem7", PS_DATA_METADATA, "I am a metadata", newMD);
+    item8 = psMetadataItemAlloc("myItem8", PS_DATA_STRING, "I am a string", string);
+    printMetadataItem(item1);
+    printMetadataItem(item2);
+    printMetadataItem(item3);
+    printMetadataItem(item4);
+    printMetadataItem(item5);
+    psMetadataAddItem(metadata, item1, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item2, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item3, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item4, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item5, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item6, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item7, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item8, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMemDecrRefCounter(vec); // vs. psFree, which now would set vec to NULL (want to keep it to comparison later)
+    printFooter(stdout, "psMetadata", "Test A - Allocate metadata items", true);
+
+
+    // Test B - Lookup metadata item by name
+    printPositiveTestHeader(stdout, "psMetadata", "Test B - Lookup metadata item by name");
+    item = psMetadataLookup(metadata, "myItem2");
+    printf("Found item named %s\n", item->name);
+    if(item == NULL) {
+        printf("ERROR: Item should not be null\n");
+        return 10;
+    }
+    printFooter(stdout, "psMetadata", "Test B - Lookup metadata item by name", true);
+
+
+    // Test C - Attempt to use null metadata
+    printNegativeTestHeader(stdout,"psMetadata", "Test C - Attempt to use null metadata",
+                            "Null metadata collection not allowed", 0);
+    if ( psMetadataLookup(NULL, "myItem2") != NULL ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataLookup did not return NULL with null metadata.");
+        return 11;
+    }
+    printFooter(stdout, "psMetadata", "Test C - Attempt to use null metadata", true);
+
+
+    // Test D - Attempt to use null key
+    printNegativeTestHeader(stdout,"psMetadata", "Test D - Attempt to use null key",
+                            "Null key name not allowed", 0);
+    if ( psMetadataLookup(metadata, NULL) != NULL ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadata did not return NULL with null key.");
+        return 12;
+    }
+    printFooter(stdout, "psMetadata", "Test D - Attempt to use null key", true);
+
+
+    // Test E - Attempt to lookup non-existant metadata item
+    printNegativeTestHeader(stdout,"psMetadata", "Test E - Attempt to lookup non-existant metadata item",
+                            "Couldn't find metadata item. Name: AARGH", 0);
+    if ( psMetadataLookup(metadata, "AARGH") != NULL ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadata did not return NULL with a non-existant item.");
+        return 13;
+    }
+    printFooter(stdout, "psMetadata", "Test E - Attempt to lookup non-existant metadata item", true);
+
+
+    // Test F - Lookup metadata item by index
+    printPositiveTestHeader(stdout, "psMetadata", "Test F - Lookup metadata item by index");
+    item = psMetadataGet(metadata, 0);
+    printf("Found item named %s\n", item->name);
+    if(item == NULL) {
+        printf("ERROR: Item should not be null\n");
+        return 14;
+    }
+    printFooter(stdout, "psMetadata", "Test F - Lookup metadata item by index", true);
+
+    // Test G - Lookup metadata item and return psS32 value
+    printPositiveTestHeader(stdout, "psMetadata", "Test G - Lookup metadata item and return psS32 value");
+    psS32 valueS32 = 0;
+    valueS32 = psMetadataLookupS32(&status, metadata, "myItem2");
+    if(valueS32 != 55) {
+        printf("ERROR: Bad value, %d, Expected 55\n", valueS32);
+        return 15;
+    } else if(! status) {
+        printf("ERROR: Bad status, %d\n", status);
+        return 15;
+    }
+    printFooter(stdout, "psMetadata", "Test G - Lookup metadata item and return psS32 value", true);
+
+    // Test H - Lookup metadata item and return psF64 value
+    printPositiveTestHeader(stdout, "psMetadata", "Test H - Lookup metadata item and return psF64 value");
+    psF64 valueF64 = 0.0;
+    valueF64 = psMetadataLookupF64(&status, metadata, "myItem5");
+    if(fabs(valueF64-3.14) > FLT_EPSILON) {
+        printf("ERROR: Bad value, %g, Expected 3.14\n", valueF64);
+        return 16;
+    } else if(! status) {
+        printf("ERROR: Bad status, %d\n", status);
+        return 16;
+    }
+    printFooter(stdout, "psMetadata", "Test H - Lookup metadata item and return psF64 value", true);
+
+    // Test I - Lookup metadata item and return psVector pointer
+    printPositiveTestHeader(stdout, "psMetadata", "Test I - Lookup metadata item and return psVector pointer");
+    psVector *valueVec = psMetadataLookupPtr(&status, metadata, "myItem6");
+    if(valueVec != vec) {
+        printf("ERROR: Bad vector pointer\n");
+        return 17;
+    } else if(! status) {
+        printf("ERROR: Bad status, %d\n", status);
+        return 17;
+    }
+    printFooter(stdout, "psMetadata", "Test I - Lookup metadata item and return psVector pointer", true);
+
+    // Test J - Lookup metadata item and return psMetadata pointer
+    printPositiveTestHeader(stdout, "psMetadata", "Test J - Lookup metadata item and return psMetadata pointer");
+    psMetadata *metaData = NULL;
+    metaData = psMetadataLookupMD(&status, metadata, "myItem7");
+    if(metaData != newMD) {
+        printf("ERROR: Bad metadata pointer\n");
+        return 25;
+    } else if(! status) {
+        printf("ERROR: Bad status, %d\n", status);
+        return 25;
+    }
+    printFooter(stdout, "psMetadata", "Test J - Lookup metadata item and return psMetadata pointer", true);
+
+    // Test K - Lookup metadata item and return psString value
+    printPositiveTestHeader(stdout, "psMetadata", "Test K - Lookup metadata item and return psString value");
+    psString newSTR;
+    newSTR = psMetadataLookupStr(&status, metadata, "myItem8");
+    if( strncmp(newSTR, string, 50) ) {
+        printf("ERROR: Bad string value \n");
+        return 26;
+    } else if(! status) {
+        printf("ERROR: Bad status, %d\n", status);
+        return 26;
+    }
+    printFooter(stdout, "psMetadata", "Test K - Lookup metadata item and return psString value", true);
+
+    // Test L - Attempt to use null metadata
+    printNegativeTestHeader(stdout,"psMetadata", "Test L - Attempt to use null metadata",
+                            "Null metadata collection not allowed", 0);
+    item = psMetadataGet(NULL, 0);
+    if ( item != NULL ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataGet did not return NULL with null metadata structure");
+        return 18;
+    }
+    printFooter(stdout, "psMetadata", "Test L - Attempt to use null metadata", true);
+
+
+    // Test M - Attempt to get non-existant metadata item
+    printNegativeTestHeader(stdout,"psMetadata", "Test M - Attempt to get non-existant metadata item",
+                            "Couldn't find metadata item with given index. Index: 22", 0);
+    if ( psMetadataGet(metadata, 22) != NULL ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataGet did not return NULL with non-existant metadata item");
+        return 19;
+    }
+    printFooter(stdout, "psMetadata", "Test M - Attempt to get non-existant metadata item", true);
+
+    // Test N - Attempt to look up with an invalid metadata object
+    printNegativeTestHeader(stdout,"psMetadata","Test N - Attemp to look up with an invalid metadata",
+                            "Lookup item with invalid metadata object.", 0 );
+    tmpTable = metadata->hash;
+    metadata->hash = NULL;
+    if ( psMetadataLookup(metadata,"myItem2") != NULL ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataLookup did not return null for invalid metadata object");
+        return 20;
+    }
+    metadata->hash = tmpTable;
+    printFooter(stdout, "psMetadata","Test N - Attempt to lookup an invalid metadata object.",true);
+
+    // Test O - Attempt get item with an invalid metadata object
+    printNegativeTestHeader(stdout,"psMetadata","Test O - Attempt to get item with an invalid metadata",
+                            "Get item with invalid metadata object.", 0 );
+    tmpList = metadata->list;
+    metadata->list = NULL;
+    if ( psMetadataGet(metadata,0) != NULL ) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataLookup did not return null for invalid metadata object");
+        return 21;
+    }
+    metadata->list = tmpList;
+    printFooter(stdout, "psMetadata","Test O - Attempt to get item with  invalid metadata object",true);
+
+    // Test P - Attempt get psS32 value of non-existant metadata item
+    printPositiveTestHeader(stdout, "psMetadata", "Test P - Attempt get psS32 value of non-existant metadata item");
+    valueS32 = psMetadataLookupS32(&status, metadata, "myItem22");
+    if(status) {
+        printf("ERROR: Bad status, %d, \n", status);
+        return 22;
+    }
+    printFooter(stdout, "psMetadata","Test P - Attempt get psS32 value of non-existant metadata item",true);
+
+    // Test P - Attempt get psF64 value of non-existant metadata item
+    printPositiveTestHeader(stdout, "psMetadata", "Test P - Attempt get psF64 value of non-existant metadata item");
+    valueF64 = psMetadataLookupF64(&status, metadata, "myItem22");
+    if(status) {
+        printf("ERROR: Bad status, %d, \n", status);
+        return 23;
+    }
+    printFooter(stdout, "psMetadata","Test P - Attempt get psF64 value of non-existant metadata item",true);
+
+    // Test P - Attempt get psVector value of non-existant metadata item
+    printPositiveTestHeader(stdout, "psMetadata", "Test P - Attempt get psVector value of non-existant metadata item");
+    valueVec = psMetadataLookupPtr(&status, metadata, "myItem22");
+    if(status) {
+        printf("ERROR: Bad status, %d, \n", status);
+        return 24;
+    }
+    printFooter(stdout, "psMetadata","Test P - Attempt get psVector value of non-existant metadata item",true);
+
+    // Test Q - Free psMetadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test Q - Free psMetadata");
+    //    psFree(string);
+    psFree(newMD);
+    psFree(item1);
+    psFree(item2);
+    psFree(item3);
+    psFree(item4);
+    psFree(item5);
+    psFree(item6);
+    psFree(item7);
+    psFree(item8);
+    psFree(metadata);
+    if ( psMemCheckLeaks(0, NULL, stdout,false) != 0 ) {
+        psError(PS_ERR_UNKNOWN, true,"memory leaks detected.");
+        return 23;
+    }
+    psMemCheckCorruption(0);
+    psS32 nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+        return 24;
+    }
+    printFooter(stdout, "psMetadata", "Test Q - Free psMetadata", true);
+
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_05.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_05.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_05.c	(revision 22158)
@@ -0,0 +1,342 @@
+
+
+/** @file  tst_psMetadata_05.c
+*
+*  @brief Test driver for psMetadata functions
+*
+*  This test driver contains the following tests for psMetadata:
+*     Test A - Allocate metadata and items
+*     Test B - Set iterator at second index
+*     Test C - Get next item at index
+*     Test D - Get next item at index and string
+*     Test E - Get previous item at index
+*     Test F - Write metadata item to file
+*     Test G - Attempt to use null metadata with setIterator
+*     Test H - Attempt to use null metadata with getNext
+*     Test I - Attempt to use null metadata with getPrevious
+*     Test J - Attempt to use null file with itemPrint
+*     Test K - Attempt to use null format with itemPrint
+*     Test L - Attempt to use null item with itemPrint
+*     Test M - Free psMetadata
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2005-09-26 21:13:33 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include <string.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+
+static void printMetadataItem(psMetadataItem *metadataItem)
+{
+    printf("Key Name: %8s  ", metadataItem->name);
+    printf("Key mdType: 0x%08x  ", metadataItem->type);
+
+    switch (metadataItem->type) {
+    case PS_DATA_METADATA_MULTI:
+        printf("Key Value: %17c", ' ');
+        break;
+    case PS_DATA_BOOL:
+        printf("Key Value: %15d  ", metadataItem->data.B);
+        break;
+    case PS_DATA_S32:
+        printf("Key Value: %15d  ", metadataItem->data.S32);
+        break;
+    case PS_DATA_F32:
+        printf("Key Value: %15.3f  ", metadataItem->data.F32);
+        break;
+    case PS_DATA_F64:
+        printf("Key Value: %15.3f  ", metadataItem->data.F64);
+        break;
+    case PS_DATA_STRING:
+        printf("Key Value: %15s  ", (char*)metadataItem->data.V);
+        break;
+    default:
+        printf("Bad type: %d ", metadataItem->type);
+    }
+    printf("Key Comment: %s\n", metadataItem->comment);
+}
+
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psMetadataItem *item1 = NULL;
+    psMetadataItem *item2 = NULL;
+    psMetadataItem *item3 = NULL;
+    psMetadataItem *item4 = NULL;
+    psMetadataItem *item5 = NULL;
+    psMetadataItem *item6 = NULL;
+    psMetadataItem *item7 = NULL;
+    //    psMetadataItem *item8 = NULL;
+    psMetadata *metadata = NULL;
+    FILE *fd = NULL;
+
+    // Test A - Allocate metadata and items
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Allocate metadata items");
+    metadata = psMetadataAlloc();
+    item1 = psMetadataItemAlloc("myItem1", PS_DATA_BOOL, "I am a boolean", true);
+    item2 = psMetadataItemAlloc("myItem2", PS_DATA_S32, "I am a integer", 55);
+    item3 = psMetadataItemAlloc("myItem3", PS_DATA_BOOL, "I am a boolean", false);
+    item4 = psMetadataItemAlloc("myItem4", PS_DATA_S32, "I am a integer", 66);
+    item5 = psMetadataItemAlloc("myItem5", PS_DATA_F32, "I am a float", 3.14);
+    item6 = psMetadataItemAlloc("myItem6", PS_DATA_F64,"I am a double", 6.28);
+    item7 = psMetadataItemAlloc("myItem7", PS_DATA_STRING, "I am a string", "GNIRTS");
+    //    item8 = psMetadataItemAlloc("myItem8", PS_TYPE_PTR, PS_META_UNKNOWN, "I am unknown");
+    printMetadataItem(item1);
+    printMetadataItem(item2);
+    printMetadataItem(item3);
+    printMetadataItem(item4);
+    psMetadataAddItem(metadata, item1, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item2, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item3, PS_LIST_HEAD, PS_META_DEFAULT);
+    psMetadataAddItem(metadata, item4, PS_LIST_HEAD, PS_META_DEFAULT);
+    printFooter(stdout, "psMetadata", "Test A - Allocate metadata items", true);
+
+    /*
+        // Test B - Set iterator at second index
+        printPositiveTestHeader(stdout, "psMetadata", "Test B - Set iterator at second index");
+        if (!psMetadataSetIterator(metadata, 2)) {
+            psError(PS_ERR_UNKNOWN,true,"Failed to set iterator");
+            return 100;
+        }
+        printFooter(stdout, "psMetadata", "Test B - Set iterator at second index", true);
+
+
+        // Test C - Get next item at index
+        printPositiveTestHeader(stdout, "psMetadata", "Test C - Get next item at index");
+        item = psMetadataGetNext(metadata, NULL, 2);
+        if(item == NULL) {
+            printf("ERROR: Item should not be null\n");
+        } else {
+            printf("Found item named %s\n", item->name);
+        }
+        printFooter(stdout, "psMetadata", "Test C - Get next item at index", true);
+
+
+        // Test D - Get next item at index and string
+        printPositiveTestHeader(stdout, "psMetadata", "Test D - Get next item at index and string");
+        item = psMetadataGetNext(metadata, "myItem1", 1);
+        if(item == NULL) {
+            printf("ERROR: Item should not be null\n");
+        } else {
+            printf("Found item named %s\n", item->name);
+        }
+        printFooter(stdout, "psMetadata", "Test D - Get next item at index and string", true);
+
+
+        // Test E - Get previous item at index
+        printPositiveTestHeader(stdout, "psMetadata", "Test E - Get previous item at index");
+        item = psMetadataGetPrevious(metadata, NULL, 1);
+        if(item == NULL) {
+            printf("ERROR: Item should not be null\n");
+        } else {
+            printf("Found item named %s\n", item->name);
+        }
+        if( psMetadataGetPrevious(metadata,"myItem3",1) == NULL) {
+            psError(PS_ERR_UNKNOWN, true,"psMetadataGetPrevious did not return an item from metadata.");
+            return 45;
+        }
+        tmpList = metadata->list;
+        metadata->list = NULL;
+        if ( psMetadataGetPrevious(metadata,NULL,1) != NULL) {
+            psError(PS_ERR_UNKNOWN, true,"psMetadataGetPrevious did not return null for invalid metadata.");
+            return 50;
+        }
+        metadata->list = tmpList;
+        printFooter(stdout, "psMetadata", "Test E - Get previous item at index", true);
+
+    */
+    // Test F - Write metadata item to file
+    printPositiveTestHeader(stdout, "psMetadata", "Test F - Write metadata item to file");
+    fd = fopen("temp/tst_psMetadata05_OUT", "w");
+    if(fd == NULL) {
+        printf("ERROR: Couldn't open file for writing\n");
+    }
+
+    if (psMetadataItemPrint(fd, "S32 = %ld\n", item2) == false) {
+        printf("ERROR: Return type should be true\n");
+        return 10;
+    }
+
+    if (psMetadataItemPrint(fd, "S32 = %+06.1f\n", item2) == false) {
+        printf("ERROR: Return type should be true\n");
+        return 10;
+    }
+
+    if (psMetadataItemPrint(fd, "BOL = %ld\n", item3) == false) {
+        printf("ERROR: Return type should be true\n");
+        return 11;
+    }
+
+    if (psMetadataItemPrint(fd, "F32 = %g\n", item5) == false) {
+        printf("ERROR: Return type should be true\n");
+        return 12;
+    }
+
+    if (psMetadataItemPrint(fd, "F32 = % #i\n", item5) == false) {
+        printf("ERROR: Return type should be true\n");
+        return 12;
+    }
+
+    if (psMetadataItemPrint(fd, "F64 = %g\n", item6) == false) {
+        printf("ERROR: Return type should be true\n");
+        return 13;
+    }
+
+    if (psMetadataItemPrint(fd, "STR = %s\n", item7) == false) {
+        printf("ERROR: Return type should be true\n");
+        return 14;
+    }
+    //    psLogMsg(__func__,PS_LOG_INFO,"Attempt to print item of invalid type, should generate error message");
+    //    if (psMetadataItemPrint(fd, "UNK = \n", item8) == true) {
+    //        printf("ERROR: Return type should be false\n");
+    //        fclose(fd);
+    //        return 15;
+    //    }
+    fclose(fd);
+
+    fd = fopen("temp/tst_psMetadata05_OUT", "r");
+    if(fd == NULL) {
+        printf("ERROR: Couldn't open file for reading\n");
+    }
+
+    char line[256];
+    char truth1[] = "S32 = 55";
+    fgets(line, 256, fd);
+    if(strncmp(line, truth1, 8)) {
+        printf("ERROR: Data in file is not as expected. Value: %s. Should be: %s\n", line, truth1);
+    }
+
+    char truth1b[] = "S32 = +055.0";
+    fgets(line, 256, fd);
+    if(strncmp(line, truth1b, 12)) {
+        printf("ERROR: Data in file is not as expected. Value: %s. Should be: %s\n", line, truth1b);
+    }
+
+    char truth2[] = "BOL = 0";
+    fgets(line, 256, fd);
+    if(strncmp(line, truth2, 7)) {
+        printf("ERROR: Data in file is not as expected. Value: %s. Should be: %s\n", line, truth2);
+    }
+
+    char truth3[] = "F32 = 3.14";
+    fgets(line, 256, fd);
+    if(strncmp(line, truth3, 10)) {
+        printf("ERROR: Data in file is not as expected. Value: %s. Should be: %s\n", line, truth3);
+    }
+
+    char truth3b[] = "F32 =  3";
+    fgets(line, 256, fd);
+    if(strncmp(line, truth3b, 8)) {
+        printf("ERROR: Data in file is not as expected. Value: %s. Should be: %s\n", line, truth3b);
+    }
+
+    char truth4[] = "F64 = 6.28";
+    fgets(line, 256, fd);
+    if(strncmp(line, truth4, 10)) {
+        printf("ERROR: Data in file is not as expected. Value: %s. Should be: %s\n", line, truth4);
+    }
+
+    char truth5[] = "STR = GNIRTS";
+    fgets(line, 256, fd);
+    if(strncmp(line, truth5, 12)) {
+        printf("ERROR: Data in file is not as expected. Value: %s. Should be: %s\n", line, truth5);
+    }
+
+    fclose(fd);
+    printFooter(stdout, "psMetadata", "Test F - Write metadata item to file", true);
+    /*
+        // Test G - Attempt to use null metadata with setIterator
+        printNegativeTestHeader(stdout,"psMetadata", "Test G - Attempt to use null metadata with setIterator",
+                                "Null metadata collection not allowed", 0);
+        if( psMetadataSetIterator(NULL, 0)) {
+            psError(PS_ERR_UNKNOWN,true,"Set iterator did not detect invalid parameter.");
+            return 101;
+        }
+        tmpList = metadata->list;
+        metadata->list = NULL;
+        if( psMetadataSetIterator(metadata,0)) {
+            psError(PS_ERR_UNKNOWN,true,"Set iterator did not detect null list.");
+            return 102;
+        }
+        metadata->list = tmpList;
+        printFooter(stdout, "psMetadata", "Test G - Attempt to use null metadata with setIterator", true);
+
+
+        // Test H - Attempt to use null metadata with getNext
+        printNegativeTestHeader(stdout,"psMetadata", "Test H - Attempt to use null metadata with getNext",
+                                "Null metadata collection not allowed", 0);
+        if( psMetadataGetNext(NULL, "myItem2", 0) != NULL ) {
+            psError(PS_ERR_UNKNOWN, true,"psMetadataGetNext did not return null for null metadata.");
+            return 40;
+        }
+        tmpList = metadata->list;
+        metadata->list = NULL;
+        if ( psMetadataGetNext(metadata, "myItem2", 0) != NULL ) {
+            psError(PS_ERR_UNKNOWN, true,"psMetadataGetNext did not return null for invalid metadata.");
+            return 41;
+        }
+        metadata->list = tmpList;
+
+        printFooter(stdout, "psMetadata", "Test H - Attempt to use null metadata with getNext", true);
+
+
+        // Test I - Attempt to use null metadata with getPrevious
+        printNegativeTestHeader(stdout,"psMetadata", "Test I - Attempt to use null metadata with getPrevious",
+                                "Null metadata collection not allowed", 0);
+        psMetadataGetPrevious(NULL, "myItem2", 0);
+        printFooter(stdout, "psMetadata", "Test I - Attempt to use null metadata with getPrevious", true);
+
+    */
+    // Test J - Attempt to use null file with itemPrint
+    printNegativeTestHeader(stdout,"psMetadata", "Test J - Attempt to use null file with itemPrint",
+                            "Null file descriptor not allowed", 0);
+    psMetadataItemPrint(NULL, "Item value: %ld", item2);
+    printFooter(stdout, "psMetadata", "Test J - Attempt to use null file with itemPrint", true);
+
+
+    // Test K - Attempt to use null format with itemPrint
+    printNegativeTestHeader(stdout,"psMetadata", "Test K - Attempt to use null format with itemPrint",
+                            "Null format not allowed", 0);
+    psMetadataItemPrint(fd, NULL, item2);
+    printFooter(stdout, "psMetadata", "Test K - Attempt to use null format with itemPrint", true);
+
+
+    // Test L - Attempt to use null item with itemPrint
+    printNegativeTestHeader(stdout,"psMetadata", "Test L - Attempt to use null item with itemPrint",
+                            "Null metadata not allowed", 0);
+    psMetadataItemPrint(fd, "Item value: %ld", NULL);
+    printFooter(stdout, "psMetadata", "Test L - Attempt to use null item with itemPrint", true);
+
+
+    // Test M - Free psMetadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test M - Free psMetadata");
+    psFree(metadata);
+    psFree(item1);
+    psFree(item2);
+    psFree(item3);
+    psFree(item4);
+    psFree(item5);
+    psFree(item6);
+    psFree(item7);
+    //    psFree(item8);
+    if ( psMemCheckLeaks(0, NULL, stdout, false) != 0 ) {
+        psError(PS_ERR_UNKNOWN, true,"Memory leaks detected.");
+        return 50;
+    }
+    psMemCheckCorruption(0);
+    psS32 nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+        return 51;
+    }
+    printFooter(stdout, "psMetadata", "Test M - Free psMetadata", true);
+
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_06.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_06.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_06.c	(revision 22158)
@@ -0,0 +1,166 @@
+
+/** @file  tst_psMetadata_06.c
+*
+*  @brief Test driver for psMetadata functions
+*
+*  This test driver contains the following tests for psMetadata:
+*     Test A - Allocate metadata and items
+*     Test B - Add leaf node on top of existing leaf node
+*     Test C - Add leaf node to existing folder node
+*     Test D - Add folder node on top of existing leaf node
+*     Test E - Free psMetadata
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2005-09-26 21:13:33 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include <string.h>
+#include "pslib_strict.h"
+#include "psTest.h"
+
+static void printMetadataItem(psMetadataItem *metadataItem)
+{
+    printf("Key Name: %8s  ", metadataItem->name);
+    printf("Key mdType: 0x%08x  ", metadataItem->type);
+
+    switch (metadataItem->type) {
+    case PS_DATA_METADATA_MULTI:
+        printf("Key Value: %17c", ' ');
+        break;
+    case PS_DATA_LIST:
+        printf("Key Value: %15s  ", "psList");
+        break;
+    case PS_DATA_BOOL:
+        printf("Key Value: %15d  ", metadataItem->data.B);
+        break;
+    case PS_DATA_S32:
+        printf("Key Value: %15d  ", metadataItem->data.S32);
+        break;
+    case PS_DATA_F32:
+        printf("Key Value: %15.3f  ", metadataItem->data.F32);
+        break;
+    case PS_DATA_F64:
+        printf("Key Value: %15.3f  ", metadataItem->data.F64);
+        break;
+    case PS_DATA_STRING:
+        printf("Key Value: %15s  ", (char*)metadataItem->data.V);
+        break;
+    default:
+        printf("Bad type: %d ", metadataItem->type);
+    }
+    printf("Key Comment: %s\n", metadataItem->comment);
+}
+
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psMetadataItem *item1a = NULL;
+    psMetadataItem *item1b = NULL;
+    psMetadataItem *item1c = NULL;
+    psMetadataItem *item2a = NULL;
+    psMetadataItem *item2b = NULL;
+    psMetadata *metadata = NULL;
+
+
+    // Test A - Allocate metadata and items
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Allocate metadata and items");
+    item1a = psMetadataItemAlloc("myItem1", PS_DATA_BOOL, "I am a boolean", true);
+    item1b = psMetadataItemAlloc("myItem1", PS_DATA_S32, "I am a signed integer", 111);
+    item1c = psMetadataItemAlloc("myItem1", PS_DATA_S32, "I am a signed integer", 222);
+    item2a = psMetadataItemAlloc("myItem2", PS_DATA_S32, "I am a signed integer", 333);
+    item2b = psMetadataItemAlloc("myItem2", PS_DATA_LIST, "I am a list", NULL);
+    metadata = psMetadataAlloc();
+    printMetadataItem(item1a);
+    printMetadataItem(item1b);
+    printMetadataItem(item1c);
+    printMetadataItem(item2a);
+    printMetadataItem(item2b);
+    printFooter(stdout, "psMetadata", "Test A - Allocate metadata and items", true);
+
+
+    // Test B - Add leaf node on top of existing leaf node
+    printPositiveTestHeader(stdout, "psMetadata", "Test B - replace an item in the metadata");
+    if(!psMetadataAddItem(metadata, item1a, PS_LIST_HEAD, PS_META_DEFAULT)) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem returned false for adding a node top.");
+        return 20;
+    }
+    psMetadataItem* tempItem = psMetadataLookup(metadata, item1a->name);
+    if (tempItem != item1a) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem didn't add the metadata entry.");
+        return 20;
+    }
+
+    if (!psMetadataAddItem(metadata, item1b, PS_LIST_HEAD, PS_META_REPLACE)) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem returned false for adding a node top.");
+        return 21;
+    }
+
+    tempItem = psMetadataLookup(metadata, item1a->name);
+    if (tempItem != item1b) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem didn't replace the metadata entry.");
+        return 21;
+    }
+
+    printFooter(stdout, "psMetadata", "Test B - replace an item in the metadata", true);
+
+
+    // Test C - Add leaf node to existing folder node
+    printPositiveTestHeader(stdout, "psMetadata", "Test C - add duplicate-key metadata item");
+    if (!psMetadataAddItem(metadata, item1c, PS_LIST_HEAD, PS_META_DUPLICATE_OK)) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem return false for adding a not to existing node.");
+        return 22;
+    }
+
+    tempItem = psMetadataLookup(metadata, item1a->name);
+    if (tempItem == NULL || tempItem->type != PS_DATA_METADATA_MULTI) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem didn't add additional metadata entry of same key.");
+        return 22;
+    }
+    printFooter(stdout, "psMetadata", "Test C - add duplicate-key metadata item", true);
+
+
+    // Test D - Add folder node on top of existing leaf node
+    printPositiveTestHeader(stdout, "psMetadata", "Test D - Add folder node on top of existing leaf node");
+    if (!psMetadataAddItem(metadata, item2a, PS_LIST_HEAD, PS_META_DEFAULT)) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem returned false for adding a node to existing leaf node.");
+        return 23;
+    }
+    if (!psMetadataAddItem(metadata, item2b, PS_LIST_HEAD, PS_META_DUPLICATE_OK)) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem returned false for adding a nod to existing leaf node.");
+        return 24;
+    }
+    printFooter(stdout, "psMetadata", "Test D - Add folder node on top of existing leaf node", true);
+    tempItem = psMetadataLookup(metadata, item1a->name);
+    if (tempItem == NULL || tempItem->type != PS_DATA_METADATA_MULTI) {
+        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem didn't add additional metadata entry of same key.");
+        return 24;
+    }
+
+
+    // Test E - Free psMetadata
+    printPositiveTestHeader(stdout, "psMetadata", "Test E - Free psMetadata");
+    psFree(item1a);
+    psFree(item1b);
+    psFree(item1c);
+    psFree(item2a);
+    psFree(item2b);
+    psFree(metadata);
+    if ( psMemCheckLeaks(0, NULL, stdout, false) != 0 ) {
+        psError(PS_ERR_UNKNOWN, true,"Memory leaks detected.");
+        return 25;
+    }
+    psMemCheckCorruption(0);
+    psS32 nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMetadata", "Test E - Free psMetadata", true);
+
+
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_07.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_07.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psMetadata_07.c	(revision 22158)
@@ -0,0 +1,362 @@
+/** @file  tst_psMetadata_07.c
+*
+*  @brief Test driver for psMetadataIterator functions
+*
+*  This test driver contains the following tests for psMetadata:
+*     Test A - Allocate a psMetadataIterator
+*     Test B - Set a psMetadataIterator
+*     Test C - Get and Increment a psMetadataIterator
+*     Test D - Get and Decrement a psMetadataIterator
+*     Test E - psMetadataConfigWrite (also tests psMetadataConfigFormat)
+*     Test F - psMetadataRemoveKey, RemoveIndex
+*     Test G - psMetadataAddPtr, psMetadataItemAllocPtr
+*     Test H - psMetadataCopy
+*     Test I - psArgument Functions
+*
+*  @author  David Robbins, MHPCC
+*
+*  @version $Revision: 1.22 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2006-05-03 01:10:09 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+#include "config.h"
+#include "pslib_strict.h"
+#include "psTest.h"
+//#include "psMetadata.h"
+
+static psS32 testMetaIter(void);
+static psS32 testMetaWrite(void);
+static psS32 testMetaRemove(void);
+static psS32 testMetaAddPtr(void);
+static psS32 testMetaCopy(void);
+
+testDescription tests[] = {
+                              {testMetaIter, 1, "Test psMetadataIterator fxns", 0, false},
+                              {testMetaWrite, 2, "Test psMetadataConfigWrite", 0, false},
+                              {testMetaRemove, 3, "Test psMetadataRemoveKey/Index", 0, false},
+                              {testMetaAddPtr, 4, "Test psMetadataAddPtr", 0, false},
+                              {testMetaCopy, 5, "Test psMetadataCopy", 0, false},
+                              {NULL}
+                          };
+
+static psMetadata *setupMeta(void);
+
+static psMetadata *setupMeta(void)
+{
+    psMetadata *md = NULL;
+    psVector *vec = NULL;
+    psMetadata *newMD = NULL;
+    psTime *time;
+    int i = 0;
+    md = psMetadataAlloc();
+    newMD = psMetadataAlloc();
+    vec = psVectorAlloc(60, PS_DATA_S32);
+    time = psTimeAlloc(PS_TIME_TAI);
+    for (i = 0; i < 5; i++) {
+        vec->data.S32[i] = i+1;
+    }
+    vec->n = 5;
+    time->sec = 1000;
+    time->nsec = 25;
+    time->leapsecond = true;
+    psMetadataAddBool(md, PS_LIST_TAIL, "item1", 0, "I am a boolean", true);
+    psMetadataAddS32(md, PS_LIST_TAIL, "item2", 0, "", 55);
+    psMetadataAddF32(md, PS_LIST_TAIL, "item3", 0, NULL, 3.14);
+    psMetadataAddF64(md, PS_LIST_TAIL, "item4", 0, "", 6.28);
+    psMetadataAddStr(md, PS_LIST_TAIL, "item5", 0, "I am a string", "GNIRTS");
+    psMetadataAddVector(md, PS_LIST_TAIL, "vector6", 0, "I am a vector", vec);
+    psMetadataAddTime(md, PS_LIST_TAIL, "time01", 0, "I am time", time);
+
+    psMetadataAddS32(newMD, PS_LIST_TAIL, "ITEM01", 0, NULL, 666);
+    psMetadata *newestMD = NULL;
+    newestMD = psMetadataAlloc();
+    psMetadataAddVector(newestMD, PS_LIST_TAIL, "VECTORNEW", 0, "Newest VECTOR", vec);
+    psMetadataAddStr(newestMD, PS_LIST_TAIL, "cell", 0, "I am a p-Star", "pStArRs");
+    psMetadataAddMetadata(newMD, PS_LIST_TAIL, "META NEW", 0, "I AM Newest METADATA", newestMD);
+    psMetadataAddF32(newMD, PS_LIST_TAIL, "ITEM02", 0, "I AM FLOAT", 666.6);
+    psMetadataAddF64(newMD, PS_LIST_TAIL, "ITEM03", 0, "I AM DOUBLE", 666.666);
+
+    psMetadataAddMetadata(md, PS_LIST_TAIL, "metadata7", 0, "I am a metadata", newMD);
+    psFree(time);
+    psFree(newestMD);
+    psFree(vec);
+    psFree(newMD);
+    return md;
+}
+
+int main(int argc, char* argv[])
+{
+    psLogSetLevel( PS_LOG_INFO );
+    if( !runTestSuite(stderr,"psMetadata_07",tests,argc,argv)) {
+        return 1;
+    }
+    return 0;
+}
+
+//Set a psMetadataIterator //
+static psS32 testMetaIter(void)
+{
+    psMetadata *metadata = NULL;
+    metadata = setupMeta();
+    psMetadataIterator *iter = NULL;
+    psMetadataItem *item1 = NULL;
+    psMetadataItem *item2 = NULL;
+    psMetadataItem *item3 = NULL;
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Allocate psMetadataIterator");
+    iter = psMetadataIteratorAlloc(metadata, PS_LIST_HEAD, NULL);
+    if (iter == NULL) {
+        fprintf(stderr, "Failed test point - Allocate a psMetadataIterator.  Iterator NULL. \n");
+    }
+    printFooter(stdout, "psMetadata", "Test A - Allocate psMetadataIterator", true);
+    printPositiveTestHeader(stdout, "psMetadata", "Test B - Set psMetadataIterator");
+    psMetadataIteratorSet(iter, 2);
+    item1 = psMetadataGetAndIncrement(iter);
+    if ( !strncmp(item1->name, "item2", 20) ) {
+        fprintf(stderr, "Failed test point - IteratorSet - Item names don't match. \n");
+    }
+    printFooter(stdout, "psMetadata", "Test B - Set psMetadataIterator", true);
+    printPositiveTestHeader(stdout, "psMetadata", "Test C - Get and Increment Iterator");
+    item2 = psMetadataGetAndDecrement(iter);
+    if ( !strncmp(item2->name, "item3", 20) ) {
+        fprintf(stderr, "Failed test point - GetAndIncrement - Item names don't match. \n");
+    }
+    printFooter(stdout, "psMetadata", "Test C - Get and Increment Iterator", true);
+    printPositiveTestHeader(stdout, "psMetadata", "Test D - Get and Decrement Iterator");
+    item3 = psMetadataGetAndDecrement(iter);
+    if ( !strncmp(item3->name, "item2", 20) ) {
+        fprintf(stderr, "Failed test point - GetAndDecrement - Item names don't match. \n");
+    }
+    printFooter(stdout, "psMetadata", "Test D - Get and Decrement Iterator", true);
+    psFree(iter);
+    psFree(metadata);
+    return 0;
+}
+
+static psS32 testMetaWrite(void)
+{
+    psMetadata *newMD = NULL;
+    //Return false for NULL input metadata
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if (psMetadataConfigWrite(newMD, "mdcfgwrt.out")) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psMetadataConfigWrite failed to return false for NULL input metadata.\n");
+        return 1;
+    }
+    newMD = setupMeta();
+    //Return false for NULL input filename
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if (psMetadataConfigWrite(newMD, NULL)) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psMetadataConfigWrite failed to return false for NULL input filename.\n");
+        return 2;
+    }
+    //Return false for bad input filename
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if (psMetadataConfigWrite(newMD, "temp")) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, false,
+                "psMetadataConfigWrite failed to return false for bad input filename.\n");
+        return 3;
+    }
+    //Return true for valid inputs
+    if ( !psMetadataConfigWrite(newMD, "mdcfgwrt.out") ) {
+        fprintf(stderr, "Failed test point E - Failed to write metadata to file. \n");
+        return 4;
+    }
+
+    //Make sure the output file matches the verified file output.
+    FILE *verified;
+    FILE *output;
+    verified = fopen("mdcfgwrt.verified", "r");
+    output = fopen("mdcfgwrt.out", "r");
+    char buffer1[100];
+    char buffer2[100];
+    while ( fscanf(verified, "%s", buffer1) != EOF ) {
+        if (fscanf(output, "%s", buffer2) == EOF) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, false,
+                    "Output file is smaller than the expected output file.\n");
+            return 5;
+        }
+        if (strncmp(buffer1, buffer2, 100) ) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                    "Output file contents do not match the expected output.\n");
+            return 6;
+        }
+    }
+    if (fscanf(output, "%s", buffer2) != EOF) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, false,
+                "Output file is larger than the expected output file.\n");
+        return 7;
+    }
+    fclose(verified);
+    fclose(output);
+
+    psFree(newMD);
+    return 0;
+}
+
+psS32 testMetaRemove(void)
+{
+    psMetadata *md = NULL;
+    md = setupMeta();
+    if ( !psMetadataRemoveKey(md, "item1") ) {
+        fprintf(stderr, "Failed to remove item1 from psMetadata.\n");
+        return 1;
+    }
+    if ( !psMetadataRemoveIndex(md, PS_LIST_HEAD) ) {
+        fprintf(stderr, "Failed to remove item2 from psMetadata.\n");
+        return 2;
+    }
+    psFree(md);
+    return 0;
+}
+
+psS32 testMetaAddPtr(void)
+{
+    bool status;
+    psVector *vecptr = NULL;
+    psVector *vecptr2 = NULL;
+    vecptr = psVectorAlloc(5, PS_TYPE_S32);
+    vecptr->data.S32[0] = 666;
+    psMetadata *md = NULL;
+    md = psMetadataAlloc();
+    psMetadataItem *item = NULL;
+    psMetadataItem *item2 = NULL;
+    item = psMetadataItemAllocPtr("itemptr", PS_DATA_STRING, "", "Devil String");
+    status = psMetadataAddPtr(md, PS_LIST_HEAD, "vecptr", PS_DATA_VECTOR,
+                              "this is a vector comment", vecptr);
+    if (!status) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "Unable to add psPtr (vector) to metadata.\n");
+        return 1;
+    }
+    status = false;
+    vecptr2 = (psVector*)psMetadataLookupPtr(&status, md, "vecptr");
+    if (!status) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "Unable to retrieve psPtr (vector) from metadata.\n");
+        return 2;
+    }
+    if (vecptr2->data.S32[0] != 666) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "Failed to retrieve correct psPtr (vector) from metadata.\n");
+        return 3;
+    }
+    status = false;
+    if (item == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "Unable to Alloc psPtr (string) metadata item .\n");
+        return 5;
+    }
+    if ( !psMetadataAddItem(md, item, PS_LIST_TAIL, 0) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "Unable to add psPtr (string) metadata item to metadata.\n");
+        return 6;
+    }
+    item2 = psMetadataGet(md, PS_LIST_TAIL);
+    if (item2 == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "Unable to retrieve psPtr (string) metadata item .\n");
+        return 7;
+    }
+    if ( strncmp((char*)item2->data.V, "Devil String", 20) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "Unable to retrieve correct psPtr (string) metadata item .\n");
+        printf("\n string = %s \n", (char*)item2->data.V);
+        return 8;
+    }
+
+    psMetadata *strtest = psMetadataAlloc();
+    //should return false for NULL input string
+    //    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( !psMetadataAddStr(strtest, PS_LIST_TAIL, "bar", 0, "baz", NULL) ) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true, "strtest failed for NULL.\n");
+        return 9;
+    }
+    psFree(strtest);
+
+    psFree(item);
+    psFree(vecptr);
+    psFree(md);
+    return 0;
+
+}
+
+psS32 testMetaCopy(void)
+{
+    psMetadata *test = NULL;
+    psMetadata *empty = NULL;
+    psMetadata *md = setupMeta();
+
+    //Return NULL for NULL input Metadata
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    test = psMetadataCopy(test, empty);
+    if (test != NULL) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psMetadataCopy failed to return NULL for NULL input metadata.\n");
+        psFree(md);
+        return 1;
+    }
+
+    //Return a copy in of md in test
+    test = psMetadataCopy(NULL, md);
+    //Check if contents are the same
+    psMetadataItem *testItem = NULL;
+    psMetadataItem *mdItem = NULL;
+    psMetadataIterator *testIterator = NULL;
+    psMetadataIterator *mdIterator = NULL;
+    testIterator = psMetadataIteratorAlloc(test, PS_LIST_HEAD, NULL);
+    mdIterator = psMetadataIteratorAlloc(md, PS_LIST_HEAD, NULL);
+    testItem = psMetadataGetAndIncrement(testIterator);
+    mdItem = psMetadataGetAndIncrement(mdIterator);
+    while (testItem != NULL || mdItem != NULL ) {
+        testItem = psMetadataGetAndIncrement(testIterator);
+        mdItem = psMetadataGetAndIncrement(mdIterator);
+    }
+
+    if (!psMetadataConfigWrite(md, "MDCopy.in") ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psMetadataConfigWrite failed to output original metadata contents.\n");
+        return 3;
+    }
+    if (!psMetadataConfigWrite(test, "MDCopy.out") ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psMetadataConfigWrite failed to output copied metadata contents.\n");
+        return 4;
+    }
+    FILE *verified;
+    FILE *output;
+    verified = fopen("MDCopy.in", "r");
+    output = fopen("MDCopy.out", "r");
+    char buffer1[100];
+    char buffer2[100];
+    while ( fscanf(verified, "%s", buffer1) != EOF ) {
+        if (fscanf(output, "%s", buffer2) == EOF) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, false,
+                    "Copied metadata is smaller than the original.\n");
+            return 5;
+        }
+        if (strncmp(buffer1, buffer2, 100) ) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                    "Copied metadata contents do not match original metadata contents.\n");
+            return 6;
+        }
+    }
+    if (fscanf(output, "%s", buffer2) != EOF) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, false,
+                "Copied metadata is larger than the original.\n");
+        return 7;
+    }
+    fclose(verified);
+    fclose(output);
+
+
+    psFree(testItem);
+    psFree(mdItem);
+    psFree(testIterator);
+    psFree(mdIterator);
+    psFree(test);
+    psFree(md);
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psPixels.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psPixels.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/types/tst_psPixels.c	(revision 22158)
@@ -0,0 +1,602 @@
+/** @file  tst_psPixels.c
+ *
+ *  @brief Contains the tests for psPixels.[ch]
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.5 $
+ *           $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-04-01 02:43:57 $
+ *
+ *  Copyright 2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include "psTest.h"
+#include "pslib_strict.h"
+
+static psS32 testPixelsAlloc(void);
+static psS32 testPixelsRealloc(void);
+static psS32 testPixelsCopy(void);
+static int testPixelsToMask(void);
+static int testPixelsFromMask(void);
+static int testPixelsConcatenate(void);
+static psS32 testPixelsGetSet(void);
+static psS32 testPixelsLength( void );
+
+testDescription tests[] = {
+                              {testPixelsAlloc,860,"psPixelsAlloc",0,false},
+                              {testPixelsRealloc,862,"psPixelsRealloc",0,false},
+                              {testPixelsCopy,863,"psPixelsCopy",0,false},
+                              {testPixelsToMask,864,"psPixelsToMask",0,false},
+                              {testPixelsFromMask,865,"psPixelsFromMask",0,false},
+                              {testPixelsConcatenate,866,"psPixelsConcatenate",0,false},
+                              {testPixelsGetSet,867,"psPixelsGet/Set",0,false},
+                              {testPixelsLength,666,"psPixelsLength",0,false},
+                              {NULL}
+                          };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    if ( ! runTestSuite(stderr,"psPixels",tests,argc,argv) ) {
+        psError(PS_ERR_UNKNOWN,true,"One or more tests failed");
+        return 1;
+    }
+    return 0;
+}
+
+psS32 testPixelsAlloc(void)
+{
+
+    psPixels* p0 = psPixelsAlloc(0);
+
+    if (p0 == NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsAlloc failed to allocate a zero-sized psPixels");
+        return 1;
+    }
+    if (p0->data != NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsAlloc failed to set data to NULL for a zero-sized psPixels");
+        return 2;
+    }
+    if (p0->n != p0->nalloc) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsAlloc failed to set n = 0");
+        return 3;
+    }
+    if (p0->nalloc != 0) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsAlloc failed to set nalloc = 0");
+        return 4;
+    }
+
+    psPixels* p1 = psPixelsAlloc(1);
+
+    if (p1 == NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsAlloc failed to allocate a one-sized psPixels");
+        return 11;
+    }
+    if (p1->data == NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsAlloc failed to allocate data for a one-sized psPixels");
+        return 12;
+    }
+    p1->data[0].x = 1;
+    p1->data[0].y = 2;
+    p1->n++;
+    if (p1->n != p1->nalloc) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsAlloc failed to set n = %ld", p1->nalloc);
+        return 13;
+    }
+    if (p1->nalloc != 1) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsAlloc failed to set nalloc = 1 (%ld)",
+                p1->nalloc);
+        return 14;
+    }
+
+    psPixels* p2 = psPixelsAlloc(10);
+
+    if (p2 == NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsAlloc failed to allocate a one-sized psPixels");
+        return 11;
+    }
+    if (p2->data == NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsAlloc failed to allocate data for a one-sized psPixels");
+        return 12;
+    }
+    for (int i = 0; i < 10; i++) {
+        p2->data[i].x = i;
+        p2->data[i].y = 100+i;
+        p2->n++;
+    }
+
+    if (p2->n != p2->nalloc) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsAlloc failed to set n = %ld", p2->nalloc);
+        return 13;
+    }
+    if (p2->nalloc != 10) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsAlloc failed to set nalloc = 1 (%ld)",
+                p2->nalloc);
+        return 14;
+    }
+
+
+    psFree(p2);
+    psFree(p1);
+    psFree(p0);
+
+    return 0;
+}
+
+psS32 testPixelsRealloc(void)
+{
+
+    // first, tests that reallocing a NULL just allocates
+    psPixels* p0 = psPixelsRealloc(NULL,10);
+    p0->n = 10;
+
+    if (p0 == NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsRealloc failed to allocate a zero-sized psPixels");
+        return 1;
+    }
+    if (p0->data == NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsRealloc failed to set data to NULL for a zero-sized psPixels");
+        return 2;
+    }
+    if (p0->n != p0->nalloc) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsRealloc failed to set n = 0");
+        return 3;
+    }
+    if (p0->nalloc != 10) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsRealloc failed to set nalloc = 10");
+        return 4;
+    }
+    for (int i = 0; i < 10; i++) {
+        p0->data[i].x = i;
+        p0->data[i].y = 100+i;
+    }
+    p0->n = 10;
+
+    psPixels* p1 = psPixelsRealloc(p0, 20);
+    //    p1->n = 20;
+
+    if (p1 != p0) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsRealloc failed to return a resized input psPixels");
+        return 11;
+    }
+    if (p1->data == NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsRealloc failed to set data to non-NULL");
+        return 12;
+    }
+    if (p1->n != 10) {
+        psError(PS_ERR_UNKNOWN, true,
+                "resizing up didn't preserve the size");
+        return 13;
+    }
+    if (p1->nalloc != 20) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsRealloc failed to set nalloc = 0");
+        return 14;
+    }
+    for (int i = 0; i < 10; i++) {
+        if (p0->data[i].x != i || p0->data[i].y != 100+i) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "The value of pixel %d was not preserved (%f,%f) vs (%d,%d).",
+                    i, p0->data[i].x, p0->data[i].y, i, 100+i);
+            return 15;
+        }
+    }
+    for (int i = 10; i < 20; i++) {
+        p1->data[i].x = i;
+        p1->data[i].y = 100+i;
+    }
+    p1->n = 20;
+
+
+    psPixels* p2 = psPixelsRealloc(p1,5);
+    p2->n = 5;
+    if (p2 != p1) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsRealloc didn't return input psPixels.");
+        return 21;
+    }
+    if (p2->data == NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsRealloc failed to allocate data");
+        return 22;
+    }
+
+    if (p2->n != 5) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsRealloc failed to set n=nalloc after shrinking");
+        return 23;
+    }
+    if (p2->nalloc != 5) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsRealloc failed to set nalloc properly");
+        return 24;
+    }
+
+    psPixels* p3 = psPixelsRealloc(p2,0);
+
+    if (p3 != p2) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsRealloc didn't return input psPixels.");
+        return 31;
+    }
+    if (p3->data != NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsRealloc failed to deallocate data when size=0");
+        return 32;
+    }
+
+    if (p3->n != 0) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsRealloc failed to set n=nalloc after shrinking");
+        return 33;
+    }
+    if (p3->nalloc != 0) {
+        psError(PS_ERR_UNKNOWN, true,
+                "psPixelsRealloc failed to set nalloc properly");
+        return 34;
+    }
+
+    psFree(p3);
+
+    return 0;
+}
+
+psS32 testPixelsCopy(void)
+{
+    psPixels* in1 = psPixelsAlloc(10);
+
+    for (int i = 0; i < 10; i++) {
+        in1->data[i].x = i;
+        in1->data[i].y = 100+i;
+    }
+    in1->n = 10;
+
+    psPixels* out1 = psPixelsCopy(NULL, in1);
+    if (out1 == in1) {
+        psError(PS_ERR_UNKNOWN, true,
+                "output == input?");
+        return 1;
+    }
+    if (out1 == NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "output == NULL?");
+        return 2;
+    }
+
+    if (out1->n != in1->n) {
+        psError(PS_ERR_UNKNOWN, true,
+                "out->n != in->n");
+        return 3;
+    }
+    for (long i = 0; i < out1->n; i++) {
+        if (out1->data[i].x != in1->data[i].x || out1->data[i].y != in1->data[i].y) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "failed to copy the values correctly at index %ld", i);
+            return 4;
+        }
+    }
+
+    // now test what happens when copying a 0-length list.
+    psPixels* in2 = psPixelsAlloc(0);
+    psPixels* out2 = psPixelsCopy(out1, in2);
+    if (out2 != out1) {
+        psError(PS_ERR_UNKNOWN, true,
+                "failed to recycle.");
+        return 10;
+    }
+    if (out2->n != in2->n) {
+        psError(PS_ERR_UNKNOWN, true,
+                "failed to set size when copying 0-length pixel list.");
+        return 11;
+    }
+
+    // Attempt to copy from NULL input
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL input");
+    out2 = psPixelsCopy(out2,NULL);
+    if (out2 != NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "Copying a NULL should create a NULL.");
+        return 20;
+    }
+
+    psFree(in1);
+    psFree(in2);
+
+    return 0;
+}
+
+int testPixelsToMask(void)
+{
+    // create a pixel list for
+    psPixels* pixels = psPixelsAlloc(10);
+    for (int i = 0; i < 10; i++) {
+        pixels->data[i].x = i;
+        pixels->data[i].y = i;
+    }
+    pixels->n = 10;
+
+    psImage* mask = psPixelsToMask(NULL,pixels, psRegionSet(0,10,0,10), 1);
+
+    if (mask == NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "Resulting mask was null.");
+        return 1;
+    }
+    if (mask->type.type != PS_TYPE_MASK) {
+        psError(PS_ERR_UNKNOWN, true,
+                "mask type was not PS_TYPE_MASK.");
+        return 2;
+    }
+
+    for (int row=0;row<10;row++) {
+        psMaskType* rowData = mask->data.PS_TYPE_MASK_DATA[row];
+        for (int col=0;col<10;col++) {
+            if ( (col==row && rowData[col] != 1) ||
+                    (col!=row && rowData[col] != 0) ) {
+                psError(PS_ERR_UNKNOWN,true,
+                        "Mask has unexpected value, %d, at (%d,%d)",
+                        rowData[col], col, row);
+                return 10;
+            }
+        }
+    }
+
+    // test when input psPixels is NULL.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for NULL pixels");
+    mask = psPixelsToMask(mask, NULL, psRegionSet(0,10,0,10), 1);
+    if (mask != NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "Resulting mask was not null though input psPixels was NULL.");
+        return 20;
+    }
+
+
+    // Test for invalid region
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for invalid range");
+    mask = psPixelsToMask(mask,pixels,psRegionSet(10,0,10,0),1);
+    if(mask != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL for invalid range");
+        return 21;
+    }
+    // Test for invalid region
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for invalid range");
+    mask = psPixelsToMask(mask,pixels,psRegionSet(0,-1,0,10),1);
+    if(mask != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL for invalid range");
+        return 22;
+    }
+
+    psFree(mask);
+    psFree(pixels);
+
+    return 0;
+}
+
+int testPixelsFromMask(void)
+{
+    const int numRows = 10;
+    const int numCols = 20;
+    psImage* mask = psImageAlloc(numCols,numRows,PS_TYPE_MASK);
+    for (int row=0;row<numRows;row++) {
+        for (int col=0;col<numCols;col++) {
+            mask->data.PS_TYPE_MASK_DATA[row][col] = (row*2 == col) ? 1 : 0;
+        }
+    }
+
+    psPixels* pixels = psPixelsFromMask(NULL, mask, 1);
+
+    if (pixels == NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "resulting psPixels was NULL?");
+        return 1;
+    }
+
+    if (pixels->n != numRows) {
+        psError(PS_ERR_UNKNOWN, false,
+                "wrong number of pixels in list.  Got %ld, should be %d.",
+                pixels->n, numRows);
+        return 2;
+    }
+
+    for (long i = 0; i < pixels->n; i++) {
+        if (mask->data.PS_TYPE_MASK_DATA[(int)pixels->data[i].y][(int)pixels->data[i].x] != 1) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Item in psPixels list (%f,%f) didn't coorespond to a masked value in image",
+                    pixels->data[i].x, pixels->data[i].y);
+            return 3;
+        }
+    }
+
+    // Attempt to create pixels from NULL mask
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error for NULL mask");
+    pixels = psPixelsFromMask(pixels, NULL, 1);
+
+    if (pixels != NULL) {
+        psError(PS_ERR_UNKNOWN, false,
+                "given a NULL image, got a non-NULL mask?");
+        return 4;
+    }
+
+    psFree(mask);
+
+    return 0;
+}
+
+int testPixelsConcatenate(void)
+{
+    // create a pixel list for
+    psPixels* pixels = psPixelsAlloc(10);
+    psPixels* pixels1 = psPixelsAlloc(10);
+    for (int i = 0; i < 10; i++) {
+        pixels->data[i].x = i;
+        pixels->data[i].y = i;
+        if (i%2) {
+            pixels1->data[i].x = -i;
+        } else {
+            pixels1->data[i].x = i;
+        }
+        pixels1->data[i].y = i;
+    }
+    pixels->n = 10;
+    pixels1->n = 10;
+    p_psPixelsPrint(stdout, pixels, "pixels");
+    p_psPixelsPrint(stdout, pixels1, "pixels1");
+
+    psPixels* pixels2 = psPixelsConcatenate(NULL, pixels);
+    p_psPixelsPrint(stdout, pixels2, "pixels2");
+    if (pixels2 == NULL) {
+        psError(PS_ERR_UNKNOWN, true,
+                "pixels2 == NULL?");
+        return 1;
+    }
+    if (pixels == pixels2) {
+        psError(PS_ERR_UNKNOWN, true,
+                "pixels == pixels2?  Should have made a copy.");
+        return 2;
+    }
+    if (pixels2->n != pixels->n) {
+        psError(PS_ERR_UNKNOWN, true,
+                "pixels2->n != pixels->n");
+        return 3;
+    }
+    for (long i = 0; i < pixels2->n; i++) {
+        if (pixels2->data[i].x != pixels->data[i].x || pixels2->data[i].y != pixels->data[i].y) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "failed to copy the values correctly at index %ld", i);
+            return 4;
+        }
+    }
+
+    // add pixels that are half unique.
+    psPixels* pixels3 = psPixelsConcatenate(pixels2, pixels1);
+    p_psPixelsPrint(stdout, pixels3, "pixels3");
+    if (pixels3 != pixels2) {
+        psError(PS_ERR_UNKNOWN, true,
+                "return expected to be the out parameter.");
+        return 10;
+    }
+    if (pixels3->n != 15) {
+        psError(PS_ERR_UNKNOWN, true,
+                "pixels3->n != 15, == %ld", pixels3->n);
+        return 11;
+    }
+
+    // Attempt to concatenate with NULL pixels
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL pixels");
+    if(psPixelsConcatenate(pixels2,NULL) != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not expect return to be non-NULL for NULL input pixels");
+        return 12;
+    }
+
+    psFree(pixels3);
+    psFree(pixels1);
+    psFree(pixels);
+
+    return 0;
+}
+
+psS32 testPixelsGetSet(void)
+{
+    psPixels *in = psPixelsAlloc(5);
+    in->n = 0;
+    psPixelCoord value;
+    psPixelCoord out;
+    value.x = 3;
+    value.y = 13;
+    if ( psPixelsSet(in, 2, value) ) {
+        psError(PS_ERR_LOCATION_INVALID, true, "psPixelSet set to Invalid location\n");
+        return 1;
+    }
+    if ( !psPixelsSet(in, 0, value) ) {
+        psError(PS_ERR_UNKNOWN, true, "psPixelsSet failed to set pixels at location 0\n");
+        return 2;
+    }
+    if ( !psPixelsSet(in, 1, value) ) {
+        psError(PS_ERR_UNKNOWN, true, "psPixelsSet failed to set pixels at location 0\n");
+        return 3;
+    }
+    out = psPixelsGet(in, 1);
+    if ( out.x != 3 || out.y != 13 ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psPixelsGet return incorrect values %f,%f",
+                out.x, out.y);
+        return 4;
+    }
+    value.x = 1;
+    value.y = 2;
+    if ( !psPixelsSet(in, 0, value) ) {
+        psError(PS_ERR_UNKNOWN, true, "psPixelsSet failed to set pixels at location 0\n");
+        return 5;
+    }
+    out = psPixelsGet(in, 0);
+    if (out.x != 1 || out.y != 2) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "psPixelsGet return incorrect values %f,%f",
+                out.x, out.y);
+        return 6;
+    }
+    psFree(in);
+    return 0;
+}
+
+psS32 testPixelsLength( void )
+{
+    psPixels *pixels = psPixelsAlloc(5);
+
+    if (psPixelsLength(pixels) != 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psPixelsLength failed to return the correct length of pixels.\n");
+        return 1;
+    }
+    pixels->n = 5;
+    if (psPixelsLength(pixels) != 5) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psPixelsLength failed to return the correct length of pixels.\n");
+        return 2;
+    }
+    pixels->n++;
+    if (psPixelsLength(pixels) != 6) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psPixelsLength failed to return the correct length of pixels.\n");
+        return 3;
+    }
+    psFree(pixels);
+
+    psPixels *emptyPixels = NULL;
+    psVector *vector = psVectorAlloc(5, PS_TYPE_F32);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if (psPixelsLength(emptyPixels) != -1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psPixelsLength failed to return -1 for a NULL input pixels.\n");
+        return 4;
+    }
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if (psPixelsLength((psPixels*)vector) != -1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "psPixelsLength failed to return -1 for an invalid input pixels.\n");
+        return 5;
+    }
+    psFree(vector);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/xml/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/xml/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/xml/.cvsignore	(revision 22158)
@@ -0,0 +1,15 @@
+temp
+.deps
+.libs
+Makefile
+Makefile.in
+psTest.xml
+psTest2.xml
+psTest3.xml
+psTest4.xml
+psTest5.xml
+tst_psXML
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/xml/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/xml/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/xml/Makefile.am	(revision 22158)
@@ -0,0 +1,21 @@
+AM_CPPFLAGS = $(SRCINC) -I$(top_srcdir)/test/tap/src $(PSLIB_CFLAGS)
+AM_LDFLAGS = \
+	$(top_builddir)/src/libpslib.la  \
+	$(top_builddir)/test/tap/src/libtap.la \
+	$(PSLIB_LIBS)
+
+TEST_PROGS = 
+
+if BUILD_TESTS
+bin_PROGRAMS = $(TEST_PROGS)
+TESTS = $(TEST_PROGS)
+else
+check_PROGRAMS = $(TEST_PROGS)
+endif
+
+EXTRA_DIST = psTime.xml psTime2.xml psTime3.xml psTime4.xml
+
+CLEANFILES = $(check_DATA) temp/* psTest5.xml psTest2.xml psTest.xml psTest3.xml psTest4.xml \
+	core core.* *~ *.bb *.bbg *.da gmon.out
+
+test: check
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/xml/psTime.xml
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/xml/psTime.xml	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/xml/psTime.xml	(revision 22158)
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+
+<!-- This configuration file specifies values required for time calculations by psLib -->
+<metadata>
+
+    <!-- Directory for time tables -->
+    <item name = "psLib.time.S32.value" psType = "S32" value = "20" />
+    <item name = "psLib.time.F32.value" psType = "F32" value = "50324.42145" />
+    <item name = "psLib.time.F64.value" psType = "F64" value = "80112.48952" />
+    <item name = "psLib.time.BOOL.value" psType = "BOOL" value = "TRUE" />
+    <item name = "psLib.time.BOOL.value2" psType = "BOOL" value = "false" />
+    <item name = "psLib.time.BOOL.value3" psType = "BOOL" value = "t" />
+    <item name = "psLib.time.BOOL.value4" psType = "BOOL" value = "F" />
+    <time name = "psLib.TIME.Magazine" psType = "PS_TIME_UTC" value = "1000, 25, F" />
+    <vector name = "psLib.time.Vector.S32" psType = "S32" value = "-4, -2, 506"/>
+    <vector name = "psLib.time.Vector.F32" psType = "F32" value = "-0.4944, -0.00023, 53262.0"/>
+    <vector name = "psLib.time.Vector.F64" psType = "F64" value = "-0.4944, -0.00023, 53262.0"/>
+    <metadata name ="cell" psType="METADATA">
+      <item name = "EXTNAME" psType="STR" value = "CCD00" />
+      <item name = "BIASSEC" psType="STR" value = "BSEC-00" />
+    </metadata>
+    <item name = "psLib.time.tables.dir" psType = "STR" value = "../../data" />
+</metadata>
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/xml/psTime2.xml
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/xml/psTime2.xml	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/xml/psTime2.xml	(revision 22158)
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+
+<!-- This configuration file specifies values required for time calculations by psLib -->
+<metadata>
+
+    <!-- Directory for time tables -->
+    <item name = "psLib.time.S32.value" psType = "U32" value = "20" />
+    <item name = "psLib.time.F32.value" psType = "F32" value = "50324.42145" />
+    <item name = "psLib.time.F64.value" psType = "F64" value = "80112.48952" />
+    <item name = "psLib.time.BOOL.value" psType = "BOOL" value = "TRUE" />
+    <item name = "psLib.time.BOOL.value2" psType = "BOOL" value = "false" />
+    <item name = "psLib.time.BOOL.value3" psType = "BOOL" value = "t" />
+    <item name = "psLib.time.BOOL.value4" psType = "BOOL" value = "F" />
+    <vector name = "psLib.time.Vector.S32" psType = "S32" value = "-4, -2, 506"/>
+    <vector name = "psLib.time.Vector.F32" psType = "F32" value = "-0.4944, -0.00023, 53262.0"/>
+    <vector name = "psLib.time.Vector.F64" psType = "F64" value = "-0.4944, -0.00023, 53262.0"/>
+    <metadata name ="cell" psType="METADATA">
+      <item name = "EXTNAME" psType="STR" value = "CCD00" />
+      <item name = "BIASSEC" psType="STR" value = "BSEC-00" />
+    </metadata>
+    <item name = "psLib.time.tables.dir" psType = "STR" value = "../../data" />
+</metadata>
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/xml/psTime3.xml
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/xml/psTime3.xml	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/xml/psTime3.xml	(revision 22158)
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+
+<!-- This configuration file specifies values required for time calculations by psLib -->
+<metadata>
+
+    <!-- Directory for time tables -->
+    <item name = "psLib.time.S32.value" psType = "S32" value = "20" />
+    <item name = "psLib.time.F32.value" psType = "F32" value = "50324.42145" />
+    <item name = "psLib.time.F64.value" psType = "F64" value = "80112.48952" />
+    <item name = "psLib.time.BOOL.value" psType = "BOOL" value = "right" />
+    <item name = "psLib.time.BOOL.value2" psType = "BOOL" value = "false" />
+    <item name = "psLib.time.BOOL.value3" psType = "BOOL" value = "t" />
+    <item name = "psLib.time.BOOL.value4" psType = "BOOL" value = "F" />
+    <vector name = "psLib.time.Vector.S32" psType = "S32" value = "-4, -2, 506"/>
+    <vector name = "psLib.time.Vector.F32" psType = "F32" value = "-0.4944, -0.00023, 53262.0"/>
+    <vector name = "psLib.time.Vector.F64" psType = "F64" value = "-0.4944, -0.00023, 53262.0"/>
+    <metadata name ="cell" psType="METADATA">
+      <item name = "EXTNAME" psType="STR" value = "CCD00" />
+      <item name = "BIASSEC" psType="STR" value = "BSEC-00" />
+    </metadata>
+    <item name = "psLib.time.tables.dir" psType = "STR" value = "../../data" />
+</metadata>
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/xml/psTime4.xml
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/xml/psTime4.xml	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/xml/psTime4.xml	(revision 22158)
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+
+<!-- This configuration file specifies values required for time calculations by psLib -->
+<meta>
+
+    <!-- Directory for time tables -->
+    <item name = "psLib.time.S32.value" psType = "S32" value = "20" />
+    <item name = "psLib.time.F32.value" psType = "F32" value = "50324.42145" />
+    <item name = "psLib.time.F64.value" psType = "F64" value = "80112.48952" />
+    <item name = "psLib.time.BOOL.value" psType = "BOOL" value = "TRUE" />
+    <item name = "psLib.time.BOOL.value2" psType = "BOOL" value = "false" />
+    <item name = "psLib.time.BOOL.value3" psType = "BOOL" value = "t" />
+    <item name = "psLib.time.BOOL.value4" psType = "BOOL" value = "F" />
+    <vector name = "psLib.time.Vector.S32" psType = "S32" value = "-4, -2, 506"/>
+    <vector name = "psLib.time.Vector.F32" psType = "F32" value = "-0.4944, -0.00023, 53262.0"/>
+    <vector name = "psLib.time.Vector.F64" psType = "F64" value = "-0.4944, -0.00023, 53262.0"/>
+    <metadata name ="cell" psType="METADATA">
+      <item name = "EXTNAME" psType="STR" value = "CCD00" />
+      <item name = "BIASSEC" psType="STR" value = "BSEC-00" />
+    </metadata>
+    <item name = "psLib.time.tables.dir" psType = "STR" value = "../../data" />
+</meta>
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/xml/tap_psXML.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/xml/tap_psXML.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/xml/tap_psXML.c	(revision 22158)
@@ -0,0 +1,315 @@
+/** @file  tst_psXML.c
+*
+*  @brief Test driver for psXML functions
+*
+*  This test driver contains the following tests for psXML:
+*     Test 1 - Parse an XML file
+*     Test 2 - Parse an XML memory block
+*     Test 3 - Parse an XML file descriptor
+*     Test 4 - Convert an XML doc to Metadata
+*     Test 5 - Convert Metadata to an XML doc
+*     Test 6 - Write an XML doc to file
+*     Test 7 - Write an XML doc to memory block
+*     Test 8 - Write an XML doc to file descriptor
+*
+*  @author  Dave Robbins, MHPCC
+*
+* XXXX: This doesn't even compile
+* XXXX: There are no data tests, he simple prints data to STDOUT
+*
+*  @version $Revision: 1.2 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2007-05-01 00:08:52 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+//static void writeMetadata(psMetadata* metadata, char* indentStr);
+
+// XXX: What should SRCDIR be?
+#define SRCDIR
+const char testFile1[] = SRCDIR "/psTime.xml";
+const char testFile2[] = SRCDIR "/psTime2.xml";
+const char testFile3[] = SRCDIR "/psTime3.xml";
+const char testFile4[] = SRCDIR "/psTime4.xml";
+//static void printMetadata(psMetadata *in);
+static void printMetadataItem(psMetadataItem *metadataItem, char *spaces);
+static void printMetadata(psMetadata *metadata);
+static void printMetadataList(psList *metadataItemList, char* spaces);
+static void printMetadataTable(psHash *mdTable);
+
+static void printMetadata(psMetadata *metadata)
+{
+    printf("Contents of metadata list:\n");
+    printMetadataList(metadata->list, " ");
+    printf("\nContents of metadata table:\n");
+    printMetadataTable(metadata->hash);
+}
+
+static void printMetadataList(psList *metadataItemList, char* spaces)
+{
+    psMetadataItem *entryChild = NULL;
+
+    psListIterator* iter = psListIteratorAlloc(metadataItemList, PS_LIST_HEAD, true);
+
+    while ( (entryChild=psListGetAndIncrement(iter)) != NULL) {
+        printMetadataItem(entryChild, spaces);
+    }
+
+    psFree(iter);
+}
+
+static void printMetadataTable(psHash *mdTable)
+{
+    psS32 i;
+    psHashBucket* ptr = NULL;
+    for(i=0; i<mdTable->n; i++) {
+        ptr = mdTable->buckets[i];
+        while (ptr != NULL) {
+            printMetadataItem(ptr->data, " ");
+            ptr = ptr->next;
+        }
+    }
+}
+
+static void printMetadataItem(psMetadataItem *metadataItem, char *spaces)
+{
+    int i = 0;
+    printf("%sKey Name: %25s  ", spaces, metadataItem->name);
+    //    printf("Key mdType: %d  ", (int)metadataItem->type);
+    //    printf("Key mdType: 0x%08x  ", metadataItem->type);
+    //    if ( metadataItem->type == PS_DATA_S32 )
+    //        printf("Key mdType: S32  " );
+
+    switch (metadataItem->type) {
+    case PS_DATA_BOOL:
+        printf("Key Type:  BOOL     Key Value: %15d  ", metadataItem->data.B);
+        break;
+    case PS_DATA_S32:
+        printf("Key Type:  S32      Key Value: %15d  ", metadataItem->data.S32);
+        break;
+    case PS_DATA_F32:
+        printf("Key Type:  F32      Key Value: %15.3f  ", metadataItem->data.F32);
+        break;
+    case PS_DATA_F64:
+        printf("Key Type:  F64      Key Value: %15.3f  ", metadataItem->data.F64);
+        break;
+    case PS_DATA_METADATA:
+        printf("Key Type:  METADATA    ");
+        break;
+    default:
+        printf("Key type:  psPtr    ");
+    }
+    if ( !strncmp(metadataItem->name, "psLib.time.Vector.S32", 256) ) {
+        printf("Key Values:   ");
+        while ( (int)((psVector*)(metadataItem->data.V))->data.S32[i] != 0 ) {
+            printf("%d  ", (int)((psVector*)(metadataItem->data.V))->data.S32[i] );
+            i++;
+        }
+        printf("\n");
+    } else if ( !strncmp(metadataItem->name, "psLib.time.tables.dir", 256) ) {
+        printf("Key Value:   ");
+        printf("%s", (char*)metadataItem->data.V );
+        printf("\n");
+    } else if ( !strncmp(metadataItem->name, "psLib.TIME.Magazine", 256) ) {
+        printf("Key Value:   ");
+        printf("%ld, ", (long)((psTime*)(metadataItem->data.V))->sec );
+        printf("%u, ", ((psTime*)(metadataItem->data.V))->nsec );
+        if( ((psTime*)(metadataItem->data.V))->leapsecond )
+            printf("TRUE  ");
+        else
+            printf("FALSE  ");
+        if( ((psTime*)(metadataItem->data.V))->type == PS_TIME_UTC )
+            printf("PS_TIME_UTC ");
+        else if( ((psTime*)(metadataItem->data.V))->type == PS_TIME_TAI )
+            printf("PS_TIME_TAI ");
+        else if( ((psTime*)(metadataItem->data.V))->type == PS_TIME_UT1 )
+            printf("PS_TIME_UT1 ");
+        else if( ((psTime*)(metadataItem->data.V))->type == PS_TIME_TT )
+            printf("PS_TIME_TT ");
+        printf("\n");
+    } else
+        printf("Key Comment: %s\n", metadataItem->comment);
+
+    //    if(metadataItem->data.V && metadataItem->type==PS_META_MULTI) {
+    //    if(metadataItem->data.V) {
+    //        printMetadataList(metadataItem->data.V, "    ");
+    //    }
+}
+
+typedef xmlDocPtr psXMLDoc;
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(24);
+
+    //Parses an XML file into memory.  Stores as a psXMLDoc//
+    // testXMLInput00
+    {
+        psMemId id = psMemGetId();
+        //psXMLParseFile should return a psXMLDoc* of testFile1//
+        psXMLDoc *newXML = NULL;
+        newXML = psXMLParseFile(testFile1);
+        ok(newXML != NULL, "psXMLParseFile() returned non-NULL");
+        psFree(newXML);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    //Parses an XML file from memory.  Stores as a psXMLDoc//
+    // testXMLInput01
+    {
+        psMemId id = psMemGetId();
+        psXMLDoc *newXML = NULL;
+        newXML = psXMLParseFile(testFile1);
+        char buffer[2048];
+        ok(psXMLDocToMem(newXML, buffer), "psXMLDocToMem() returned non-NULL");
+        psXMLDoc *newDoc = NULL;
+        newDoc = psXMLParseMem(buffer, strlen(buffer) );
+        ok(newDoc != NULL, "psXMLParseMem() returned non-NULL");
+        psFree(newDoc);
+        psFree(newXML);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Parses an XML file from a file descriptor.  Stores as a psXMLDoc//
+    // testXMLInput02
+    {
+        psMemId id = psMemGetId();
+        psXMLDoc *newXML = NULL;
+        newXML = psXMLParseFile(testFile1);
+        ok(newXML != NULL, "psXMLParseFile () returned non-NULL");
+        int fd = creat("psTest5.xml", 0644);
+        ok(psXMLDocToFD(newXML, fd), "psXMLDocToFD() returned TRUE");
+
+        psXMLDoc *newDoc = NULL;
+        fd = open("psTest5.xml", O_RDWR, 0);
+        newDoc = psXMLParseFD(fd);
+        ok(newDoc != NULL, "psXMLParseFD () returned non-NULL");
+        close(fd);
+        psFree(newXML);
+        psFree(newDoc);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Converts an existing psXMLDoc into psMetadata//
+    // testXMLConvert00
+    {
+        psMemId id = psMemGetId();
+        psXMLDoc *newXML = NULL;
+        newXML = psXMLParseFile(testFile1);
+        psMetadata *metaData = NULL;
+        metaData = psXMLDocToMetadata(newXML);
+        if (metaData == NULL)
+        {
+            ok(false, "psXMLDocToMetadata() returned non-NULL");
+        } else
+        {
+            ok(true, "psXMLDocToMetadata() returned non-NULL");
+            printMetadata(metaData);
+        }
+        psFree(newXML);
+        psFree(metaData);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Converts existing psMetadata into a psXMLDoc//
+    // testXMLConvert01
+    {
+        psMemId id = psMemGetId();
+        psXMLDoc *newXML = NULL;
+        newXML = psXMLParseFile(testFile1);
+        psMetadata *metaData = NULL;
+        metaData = psXMLDocToMetadata(newXML);
+        ok(metaData != NULL, "psXMLDocToMetadata() returned non-NULL");
+        psXMLDoc *XML2 = NULL;
+        XML2 = psMetadataToXMLDoc(metaData);
+        ok(psXMLDocToFile(XML2, "psTest2.xml"), "psMetadataToXMLDoc() returned TRUE");
+        psFree(newXML);
+        psFree(XML2);
+        psFree(metaData);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Writes a psXMLDoc to File//
+    // testXMLOutput00
+    {
+        psMemId id = psMemGetId();
+        psXMLDoc *newXML = NULL;
+        newXML = psXMLParseFile(testFile1);
+        ok(psXMLDocToFile(newXML, "psTest.xml"), "psXMLParseFile() returned TRUE");
+        psFree(newXML);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Writes a psXMLDoc to Memory//
+    // testXMLOutput01
+    {
+        psMemId id = psMemGetId();
+        psXMLDoc *newXML = NULL;
+        newXML = psXMLParseFile(testFile1);
+        char buffer[2048];
+        FILE *file;
+        file = fopen("psTest3.xml", "w");
+        ok(psXMLDocToMem(newXML, buffer), "fopen() successful");
+        fprintf(file, "%s", buffer);
+        fclose(file);
+        psFree(newXML);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Writes a psXMLDoc to a file descriptor//
+    // testXMLOutput02
+    {
+        psMemId id = psMemGetId();
+        psXMLDoc *newXML = NULL;
+        newXML = psXMLParseFile(testFile1);
+        int fd = creat("psTest4.xml", 0666);
+        ok(!psXMLDocToFD(newXML, fd), "psXMLDocToFD() returned TRUE");
+        close(fd);
+        psFree(newXML);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testXMLWrongInput
+    {
+        psMemId id = psMemGetId();
+        psXMLDoc *newXML = NULL;
+        newXML = psXMLParseFile(testFile2);
+        ok(newXML != NULL, "psXMLParseFile() returned non-NULL");
+        psMetadata *metaData = NULL;
+        metaData = psXMLDocToMetadata(newXML);
+        ok(metaData != NULL, "psXMLDocToMetadata() returned non-NULL");
+        psFree(newXML);
+        psFree(metaData);
+        psXMLDoc *newXML2 = NULL;
+        psMetadata *metaData2 = NULL;
+        newXML2 = psXMLParseFile(testFile3);
+        ok(newXML2 != NULL, "psXMLParseFile() returned non-NULL");
+        metaData2 = psXMLDocToMetadata(newXML2);
+        ok(metaData2 != NULL, "psXMLDocToMetadata() returned non-NULL");
+        psFree(newXML2);
+        psFree(metaData2);
+        psXMLDoc *newXML3 = NULL;
+        psMetadata *metaData3 = NULL;
+        newXML3 = psXMLParseFile(testFile4);
+        ok(newXML3 != NULL, "psXMLParseFile() returned non-NULL");
+        metaData3 = psXMLDocToMetadata(newXML3);
+        ok(metaData3 != NULL, "psXMLDocToMetadata() returned non-NULL");
+        psFree(newXML3);
+        psFree(metaData3);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/test/xml/tst_psXML.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/test/xml/tst_psXML.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/test/xml/tst_psXML.c	(revision 22158)
@@ -0,0 +1,357 @@
+/** @file  tst_psXML.c
+*
+*  @brief Test driver for psXML functions
+*
+*  This test driver contains the following tests for psXML:
+*     Test 1 - Parse an XML file
+*     Test 2 - Parse an XML memory block
+*     Test 3 - Parse an XML file descriptor
+*     Test 4 - Convert an XML doc to Metadata
+*     Test 5 - Convert Metadata to an XML doc
+*     Test 6 - Write an XML doc to file
+*     Test 7 - Write an XML doc to memory block
+*     Test 8 - Write an XML doc to file descriptor
+*
+*  @author  Dave Robbins, MHPCC
+*
+*  @version $Revision: 1.7 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2005-10-13 00:50:41 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+
+#include <string.h>
+#include "config.h"
+#include "pslib_strict.h"
+#include "psTest.h"
+#include <fcntl.h>
+#include <unistd.h>
+
+
+static psS32 testXMLInput00(void);
+static psS32 testXMLInput01(void);
+static psS32 testXMLInput02(void);
+static psS32 testXMLConvert00(void);
+static psS32 testXMLConvert01(void);
+static psS32 testXMLOutput00(void);
+static psS32 testXMLOutput01(void);
+static psS32 testXMLOutput02(void);
+static psS32 testXMLWrongInput(void);
+
+testDescription tests[] = {
+                              {testXMLInput00, 0, "Verify XML file parse", 0, false},
+                              {testXMLInput01, 1, "Verify XML memory parse", 0, false},
+                              {testXMLInput02, 2, "Verify XML file descriptor parse", 0, false},
+                              {testXMLConvert00, 3, "Verify XML to Metadata convert", 0, false},
+                              {testXMLConvert01, 4, "Verify Metadata to XML convert", 0, false},
+                              {testXMLOutput00, 5, "Verify XML file write", 0, false},
+                              {testXMLOutput01, 6, "Verify XML memory write", 0, false},
+                              {testXMLOutput02, 7, "Verify XML file descriptor write", 0, false},
+                              {testXMLWrongInput, 8, "Verify Incorrect XML Data", 0, false},
+                              {NULL}
+                          };
+
+//static void writeMetadata(psMetadata* metadata, char* indentStr);
+
+const char testFile1[] = SRCDIR "/psTime.xml";
+const char testFile2[] = SRCDIR "/psTime2.xml";
+const char testFile3[] = SRCDIR "/psTime3.xml";
+const char testFile4[] = SRCDIR "/psTime4.xml";
+//static void printMetadata(psMetadata *in);
+static void printMetadataItem(psMetadataItem *metadataItem, char *spaces);
+static void printMetadata(psMetadata *metadata);
+static void printMetadataList(psList *metadataItemList, char* spaces);
+static void printMetadataTable(psHash *mdTable);
+
+static void printMetadata(psMetadata *metadata)
+{
+    printf("Contents of metadata list:\n");
+    printMetadataList(metadata->list, " ");
+    printf("\nContents of metadata table:\n");
+    printMetadataTable(metadata->hash);
+}
+
+static void printMetadataList(psList *metadataItemList, char* spaces)
+{
+    psMetadataItem *entryChild = NULL;
+
+    psListIterator* iter = psListIteratorAlloc(metadataItemList, PS_LIST_HEAD, true);
+
+    while ( (entryChild=psListGetAndIncrement(iter)) != NULL) {
+        printMetadataItem(entryChild, spaces);
+    }
+
+    psFree(iter);
+}
+
+static void printMetadataTable(psHash *mdTable)
+{
+    psS32 i;
+    psHashBucket* ptr = NULL;
+    for(i=0; i<mdTable->n; i++) {
+        ptr = mdTable->buckets[i];
+        while (ptr != NULL) {
+            printMetadataItem(ptr->data, " ");
+            ptr = ptr->next;
+        }
+    }
+}
+
+static void printMetadataItem(psMetadataItem *metadataItem, char *spaces)
+{
+    int i = 0;
+    printf("%sKey Name: %25s  ", spaces, metadataItem->name);
+    //    printf("Key mdType: %d  ", (int)metadataItem->type);
+    //    printf("Key mdType: 0x%08x  ", metadataItem->type);
+    //    if ( metadataItem->type == PS_DATA_S32 )
+    //        printf("Key mdType: S32  " );
+
+    switch (metadataItem->type) {
+    case PS_DATA_BOOL:
+        printf("Key Type:  BOOL     Key Value: %15d  ", metadataItem->data.B);
+        break;
+    case PS_DATA_S32:
+        printf("Key Type:  S32      Key Value: %15d  ", metadataItem->data.S32);
+        break;
+    case PS_DATA_F32:
+        printf("Key Type:  F32      Key Value: %15.3f  ", metadataItem->data.F32);
+        break;
+    case PS_DATA_F64:
+        printf("Key Type:  F64      Key Value: %15.3f  ", metadataItem->data.F64);
+        break;
+    case PS_DATA_METADATA:
+        printf("Key Type:  METADATA    ");
+        break;
+    default:
+        printf("Key type:  psPtr    ");
+    }
+    if ( !strncmp(metadataItem->name, "psLib.time.Vector.S32", 256) ) {
+        printf("Key Values:   ");
+        while ( (int)((psVector*)(metadataItem->data.V))->data.S32[i] != 0 ) {
+            printf("%d  ", (int)((psVector*)(metadataItem->data.V))->data.S32[i] );
+            i++;
+        }
+        printf("\n");
+    } else if ( !strncmp(metadataItem->name, "psLib.time.tables.dir", 256) ) {
+        printf("Key Value:   ");
+        printf("%s", (char*)metadataItem->data.V );
+        printf("\n");
+    } else if ( !strncmp(metadataItem->name, "psLib.TIME.Magazine", 256) ) {
+        printf("Key Value:   ");
+        printf("%ld, ", (long)((psTime*)(metadataItem->data.V))->sec );
+        printf("%u, ", ((psTime*)(metadataItem->data.V))->nsec );
+        if( ((psTime*)(metadataItem->data.V))->leapsecond )
+            printf("TRUE  ");
+        else
+            printf("FALSE  ");
+        if( ((psTime*)(metadataItem->data.V))->type == PS_TIME_UTC )
+            printf("PS_TIME_UTC ");
+        else if( ((psTime*)(metadataItem->data.V))->type == PS_TIME_TAI )
+            printf("PS_TIME_TAI ");
+        else if( ((psTime*)(metadataItem->data.V))->type == PS_TIME_UT1 )
+            printf("PS_TIME_UT1 ");
+        else if( ((psTime*)(metadataItem->data.V))->type == PS_TIME_TT )
+            printf("PS_TIME_TT ");
+        printf("\n");
+    } else
+        printf("Key Comment: %s\n", metadataItem->comment);
+
+    //    if(metadataItem->data.V && metadataItem->type==PS_META_MULTI) {
+    //    if(metadataItem->data.V) {
+    //        printMetadataList(metadataItem->data.V, "    ");
+    //    }
+}
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetLevel( PS_LOG_INFO );
+
+    if( !runTestSuite(stderr,"psXML",tests,argc,argv)) {
+        return 1;
+    }
+
+    return 0;
+}
+
+//Parses an XML file into memory.  Stores as a psXMLDoc//
+psS32 testXMLInput00(void)
+{
+    //psXMLParseFile should return a psXMLDoc* of testFile1//
+    psXMLDoc *newXML = NULL;
+    newXML = psXMLParseFile(testFile1);
+    if (newXML == NULL ) {
+        fprintf(stderr, "Failed test point #1 xmlDocPtr is NULL \n");
+    }
+    psFree(newXML);
+    return 0;
+}
+
+//Parses an XML file from memory.  Stores as a psXMLDoc//
+psS32 testXMLInput01(void)
+{
+    psXMLDoc *newXML = NULL;
+    newXML = psXMLParseFile(testFile1);
+    char buffer[2048];
+    if (!psXMLDocToMem(newXML, buffer)) {
+        fprintf(stderr, "Failed test point #2 psXMLDocToMem not Working \n");
+    }
+    psXMLDoc *newDoc = NULL;
+    newDoc = psXMLParseMem(buffer, strlen(buffer) );
+    if (newDoc == NULL) {
+        fprintf(stderr, "Failed test point #2 xmlDocPtr is NULL \n");
+    }
+    psFree(newDoc);
+    psFree(newXML);
+    return 0;
+}
+
+//Parses an XML file from a file descriptor.  Stores as a psXMLDoc//
+psS32 testXMLInput02(void)
+{
+    psXMLDoc *newXML = NULL;
+    newXML = psXMLParseFile(testFile1);
+    if (newXML == NULL ) {
+        fprintf(stderr, "Failed test point #3 xmlDocPtr is NULL \n");
+    }
+    int fd = creat("psTest5.xml", 0666);
+
+    if ( !psXMLDocToFD(newXML, fd) ) {
+        fprintf(stderr, "Failed test point #3 psXMLDocToFD not Working \n");
+    }
+
+    psXMLDoc *newDoc = NULL;
+    fd = open("psTest5.xml", O_RDWR, 0);
+    newDoc = psXMLParseFD(fd);
+    if ( newDoc == NULL ) {
+        fprintf(stderr, "Failed test point #3 xmlDocPtr is NULL \n");
+    }
+
+    close(fd);
+    psFree(newXML);
+    psFree(newDoc);
+    return 0;
+}
+
+//Converts an existing psXMLDoc into psMetadata//
+psS32 testXMLConvert00(void)
+{
+    psXMLDoc *newXML = NULL;
+    newXML = psXMLParseFile(testFile1);
+    psMetadata *metaData = NULL;
+    metaData = psXMLDocToMetadata(newXML);
+    if (metaData == NULL) {
+        fprintf(stderr, "Failed test point #4 - Convert to Metadata \n");
+    } else {
+        printMetadata(metaData);
+    }
+    psFree(newXML);
+    psFree(metaData);
+    return 0;
+}
+
+//Converts existing psMetadata into a psXMLDoc//
+psS32 testXMLConvert01(void)
+{
+    psXMLDoc *newXML = NULL;
+    newXML = psXMLParseFile(testFile1);
+    psMetadata *metaData = NULL;
+    metaData = psXMLDocToMetadata(newXML);
+    if (metaData == NULL) {
+        fprintf(stderr, "Failed test point #5 - Convert from Metadata \n");
+    }
+    psXMLDoc *XML2 = NULL;
+    XML2 = psMetadataToXMLDoc(metaData);
+    if( !psXMLDocToFile(XML2, "psTest2.xml") ) {
+        fprintf(stderr, "Failed test point #5 - Write to File \n");
+    }
+    psFree(newXML);
+    psFree(XML2);
+    psFree(metaData);
+    return 0;
+}
+
+//Writes a psXMLDoc to File//
+psS32 testXMLOutput00(void)
+{
+    psXMLDoc *newXML = NULL;
+    newXML = psXMLParseFile(testFile1);
+    if( !psXMLDocToFile(newXML, "psTest.xml") ) {
+        fprintf(stderr, "Failed test point #6 - Write to File \n");
+    }
+    psFree(newXML);
+    return 0;
+}
+
+//Writes a psXMLDoc to Memory//
+psS32 testXMLOutput01(void)
+{
+    psXMLDoc *newXML = NULL;
+    newXML = psXMLParseFile(testFile1);
+    char buffer[2048];
+    FILE *file;
+    file = fopen("psTest3.xml", "w");
+    if( !psXMLDocToMem(newXML, buffer) ) {
+        fprintf(stderr, "Failed test point #7 - Write to Memory \n");
+    }
+    fprintf(file, "%s", buffer);
+    fclose(file);
+    psFree(newXML);
+    return 0;
+}
+
+//Writes a psXMLDoc to a file descriptor//
+psS32 testXMLOutput02(void)
+{
+    psXMLDoc *newXML = NULL;
+    newXML = psXMLParseFile(testFile1);
+    int fd = creat("psTest4.xml", 0666);
+
+    if( !psXMLDocToFD(newXML, fd) ) {
+        fprintf(stderr, "Failed test point #8 - Write to file descriptor \n");
+    }
+    close(fd);
+    psFree(newXML);
+    return 0;
+}
+
+psS32 testXMLWrongInput(void)
+{
+    psXMLDoc *newXML = NULL;
+    newXML = psXMLParseFile(testFile2);
+    if (newXML == NULL ) {
+        fprintf(stderr, "Failed to parse xml file.  Incorrect data\n");
+    }
+    psMetadata *metaData = NULL;
+    metaData = psXMLDocToMetadata(newXML);
+    if (metaData == NULL) {
+        fprintf(stderr, "Incorrect xml data for Metadata Conversion \n");
+    }
+    psFree(newXML);
+    psFree(metaData);
+    psXMLDoc *newXML2 = NULL;
+    psMetadata *metaData2 = NULL;
+    newXML2 = psXMLParseFile(testFile3);
+    if (newXML2 == NULL ) {
+        fprintf(stderr, "Failed to parse xml file.  Incorrect data\n");
+    }
+    metaData2 = psXMLDocToMetadata(newXML2);
+    if (metaData2 == NULL) {
+        fprintf(stderr, "Incorrect xml data for Metadata Conversion \n");
+    }
+    psFree(newXML2);
+    psFree(metaData2);
+    psXMLDoc *newXML3 = NULL;
+    psMetadata *metaData3 = NULL;
+    newXML3 = psXMLParseFile(testFile4);
+    if (newXML3 == NULL ) {
+        fprintf(stderr, "Failed to parse xml file.  Incorrect data\n");
+    }
+    metaData3 = psXMLDocToMetadata(newXML3);
+    if (metaData3 == NULL) {
+        fprintf(stderr, "Incorrect xml data for Metadata Conversion \n");
+    }
+    psFree(newXML3);
+    psFree(metaData3);
+    return 0;
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/utils/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/utils/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/utils/.cvsignore	(revision 22158)
@@ -0,0 +1,5 @@
+Makefile
+Makefile.in
+.deps
+.libs
+psTableParse
Index: /branches/eam_branches/eam_branch_20080719/psLib/utils/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/utils/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/utils/Makefile.am	(revision 22158)
@@ -0,0 +1,6 @@
+bin_SCRIPTS = psParsePrecessionTable psParseErrorCodes
+bin_PROGRAMS = psTableParse
+
+psTableParse_SOURCES = psTableParse.c
+
+EXTRA_DIST = psParsePrecessionTable psParseErrorCodes
Index: /branches/eam_branches/eam_branch_20080719/psLib/utils/psParseErrorCodes
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/utils/psParseErrorCodes	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/utils/psParseErrorCodes	(revision 22158)
@@ -0,0 +1,84 @@
+#!/usr/bin/env perl
+
+# Provides functions for handling long command line options
+use Getopt::Long;
+
+my @ErrorCodes        = ();
+my @ErrorDescriptions = ();
+
+my $data = "psErrorCodes.dat";
+my $outdir = ".";
+
+# Assign variables based on the presence of command line options to the script
+GetOptions(
+    "data=s"  => \$data,
+    "outdir=s" => \$outdir,
+    "verbose" => \$verbose,
+    "help"    => \$help
+);
+
+if ($help) {
+    print "Usage: parseErrorCodes ", "[--data=dataFile] ", "[--help] ",
+        "[--verbose] filename\n\n";
+    exit(0);
+}
+
+print "Using data file '$data'\n" if $verbose;
+unless ( open( DATAFILE, "<", $data ) ) {
+    die "Can not open data file $data.";
+}
+
+print "Datafile:\n" if $verbose;
+while (<DATAFILE>) {
+    chop;
+    if (/^\s*\#/) {
+        print "C $_\n" if $verbose;
+    }
+    else {
+        if (/^\s*(\w+)\s+([\%\w].*)/) {
+            my $ErrorCode        = $1;
+            my $ErrorDescription = $2;
+            print "  $ErrorCode: '$ErrorDescription'\n" if $verbose;
+            push( @ErrorCodes,        $ErrorCode );
+            push( @ErrorDescriptions, $ErrorDescription );
+        } else {
+            print "I $_\n" if $verbose;
+        }
+    }
+}
+close(DATAFILE);
+
+my $found = $#ErrorCodes + 1;
+print "\nFound $found error codes.\n" if $verbose;
+
+foreach (@ARGV) {
+    my $filename = $_.".in";
+    m/\/?([\w\.]+)$/;
+    my $output = "$outdir/$1";
+
+    die "Failed to open input file '$filename'"
+      if !open( INFILE, "<", $filename );
+    die "Failed to open output file '$output'"
+      if !open( OUTFILE, ">", $output );
+
+    print "\nOutput File: $output\n" if $verbose;
+    while (<INFILE>) {
+        if (/\${ErrorCode}/ || /\${ErrorDescription}/ || /\${n}/) {
+            $line = $_;
+            for ( $n = 0 ; $n < $found ; $n++ ) {
+                $_ = $line;
+                s/\${ErrorCode}/$ErrorCodes[$n]/g;
+                s/\${ErrorDescription}/$ErrorDescriptions[$n]/g;
+                s/\${n}/$n/g;
+                print OUTFILE;
+                print if $verbose;
+            }
+        } else {
+            print OUTFILE;
+            print if $verbose;
+        }
+    }
+
+    close(INFILE);
+    close(OUTFILE);
+}
Index: /branches/eam_branches/eam_branch_20080719/psLib/utils/psParsePrecessionTable
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/utils/psParsePrecessionTable	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/utils/psParsePrecessionTable	(revision 22158)
@@ -0,0 +1,149 @@
+#!/usr/bin/env perl
+
+# Provides functions for handling long command line options
+use Getopt::Long;
+
+# Assign variables based on the presence of command line options to the script
+GetOptions(
+    "verbose" => \$verbose,
+    "help"    => \$help
+);
+
+if ($help) {
+    print "Usage: psParsePrecessionTable ",
+        "[--help] ",
+        "[--verbose] ",
+        "tableFile.txt";
+    exit(0);
+}
+
+# Loop through the arguements passed to the script
+foreach (@ARGV) {
+    chomp;
+    $tableFile = $_;
+    s/\.txt$//;
+    $outputFile = $_ . ".dat";
+    $coeffFile = $_ . ".coeff";
+    print "Table output file is $outputFile\n",
+          "Coefficient output file is $coeffFile\n" if $verbose;
+
+    unless ( open( TABLEFILE, "<", $tableFile ) ) {
+        die "Can not open table file $tableFile.";
+    }
+
+    unless ( open( OUTPUTFILE, ">", $outputFile ) ) {
+        die "Can not create output file $outputFile.";
+    }
+
+    unless ( open( COEFFFILE, ">", $coeffFile ) ) {
+        die "Can not create coeff file $coeffFile.";
+    }
+
+    # Read Header and tranfer it to the output files
+    $found = 0;
+    while ($found < 2 && ($line=<TABLEFILE>)) {
+        print "# $line" if $verbose;
+        print COEFFFILE "# $line";
+        print OUTPUTFILE "# $line";
+        if ($line =~ /^----/) {
+            $found++;
+        }
+    }
+
+
+    die "Failed to parse the polynomials in $tableFile."
+        if &parsePolynomialCoefficients;
+
+    &parseTable;
+
+    close(TABLEFILE);
+    close(OUTPUTFILE);
+    close(COEFFFILE);
+}
+
+
+exit(0);
+
+sub parsePolynomialCoefficients {
+
+
+    print "Parsing table for polynomial values\n" if $verbose;
+
+    # find the polynomial part header
+    local $found = 0;
+    while (! $found && ($line=<TABLEFILE>)) {
+        if ($line =~ /^Polynomial part/) {
+            print COEFFFILE "# $line";
+            $found = 1;
+        }
+    }
+
+     if (! $found) {
+        print "Failed to find the coefficient section" if $verbose;
+        return 1;
+    }
+
+    print "Found proper polynomials section\n" if $verbose;
+
+    # find the line of coefficients
+    $found = 0;
+    while (! $found && ($line=<TABLEFILE>)) {
+        if ($line =~ /^\s*(\S+)\s+([\+-])\s*(\S+)\s+t\s+([\+-])\s*(\S+)\s+t\^2\s+([\+-])\s*(\S+)\s+t\^3\s+([\+-])\s*(\S+)\s+t\^4\s+([\+-])\s*(\S+)\s+t\^5/) {
+            $found = 1;
+            print COEFFFILE "$1 $2$3 $4$5 $6$7 $8$9 $10$11\n";
+            print "Coeff: $1 $2$3 $4$5 $6$7 $8$9 $10$11\n" if $verbose;
+        }
+        if ($line =~ /^\-\-\-\-\-\-\-/) {
+            $found = 2;
+        }
+    }
+
+    if ($found != 1) {
+        print "Failed to find the coefficients" if $verbose;
+        return 1;
+    }
+
+    return 0;
+}
+
+ sub parseTable {
+
+    print "Parsing table for non-polynomial values\n" if $verbose;
+
+    # find the non-polynomial part header
+    local $found = 0;
+    local $j = 0;
+    while (! $found && ($line=<TABLEFILE>)) {
+        if ($line =~ /^\s*j\s*=\s*(\d+)/) {
+            $j = $1;
+            print "Found data for j=$j\n" if $verbose;
+            $found = 1;
+        } else {
+            print OUTPUTFILE "# $line";
+        }
+    }
+
+     if (! $found) {
+        print "Failed to find the non-polynomial data" if $verbose;
+        return 1;
+    }
+
+    # find the line of coefficients
+    local $items = 0;
+    while ($line=<TABLEFILE>) {
+        if ($line =~ /^\s*j\s*=\s*(\d+)/) {
+            $j = $1;
+            print "Found data for j=$j\n" if $verbose;
+        } elsif ($line =~ /^\s*\d+\s(.+)/) {
+            print OUTPUTFILE "$j $1\n";
+            $items++;
+        }
+    }
+
+    print "Found $items data lines.\n" if $verbose;
+
+    return 0;
+}
+
+
+
Index: /branches/eam_branches/eam_branch_20080719/psLib/utils/psTableParse.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psLib/utils/psTableParse.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psLib/utils/psTableParse.c	(revision 22158)
@@ -0,0 +1,381 @@
+/** @file  psTableParse.c
+ *
+ *  @brief Parses input data tables (finals2000A.data) and outputs files for specified format
+ *
+ *  @ingroup psTableParse
+ *
+ *  @author Dave Robbins, MHPCC
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-09-23 03:03:14 $
+ *
+ *  Copyright 2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+//#include "pslib.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+static FILE *output = NULL;
+static FILE *input = NULL;
+
+static void printHeader(char *filename);
+
+int main(int argc, char *argv[])
+{
+    if (argc < 2) {
+        printf("\n Insufficient arguments.  Use [-h] for help.\n");
+        return 0;
+    }
+    if (!strncmp(argv[1], "-h", 2) ) {
+        printf("\n Usage:  psTableParse inputTable.data outputTable.dat <Sections>.\n");
+        printf(" i.e.    psTableParse finals.data finals.dat 1 3 4 8\n");
+        printf("\n Sections:\n 1)MJD Date       2)X (Bull A)     3)Y (Bull A)");
+        printf("\n 4)X (Bull B)     5)Y (Bull B)     6)dX (Bull A)");
+        printf("\n 7)dY (Bull A)    8)dX (Bull B)    9)dY (Bull B)");
+        printf("\n 10)UT1-UTC (Bull A)       11)UT1-UTC (Bull B)");
+        printf("\n 12)Error in X (Bull A)    13)Error in Y (Bull A)");
+        printf("\n 14)Error in dX (Bull A)   15)Error in dY (Bull A)    ");
+        printf("\n 16)Error in UT1-UTC (Bull A)\n\n");
+        return 0;
+    }
+    input = fopen(argv[1], "r");
+    output = fopen(argv[2], "w");
+    if (input == NULL) {
+        printf("\nERROR.  Could not open input file.\n");
+        return 0;
+    }
+    if (output == NULL) {
+        printf("\nERROR.  Could not open or create output file.\n");
+        return 0;
+    }
+    char data2[200];
+    printHeader(argv[1]);
+    fprintf(output, "#  ");
+    for (int i = 3; i < argc; i++) {
+        if(!strncmp(argv[i], "1", 2)) {
+            fprintf(output, "MJD       ");
+        }
+        if(!strncmp(argv[i], "2", 2)) {
+            fprintf(output, " X (A)     ");
+        }
+        if(!strncmp(argv[i], "3", 2)) {
+            fprintf(output, " Y (A)     ");
+        }
+        if(!strncmp(argv[i], "4", 2)) {
+            fprintf(output, " X (B)     ");
+        }
+        if(!strncmp(argv[i], "5", 2)) {
+            fprintf(output, "  Y (B)     ");
+        }
+        if(!strncmp(argv[i], "6", 2)) {
+            fprintf(output, " dX (A)     ");
+        }
+        if(!strncmp(argv[i], "7", 2)) {
+            fprintf(output, " dY (A)     ");
+        }
+        if(!strncmp(argv[i], "8", 2)) {
+            fprintf(output, " dX (B)     ");
+        }
+        if(!strncmp(argv[i], "9", 2)) {
+            fprintf(output, " dY (B)     ");
+        }
+        if(!strncmp(argv[i], "10", 2)) {
+            fprintf(output, "UT1-UTC (A)  ");
+        }
+        if(!strncmp(argv[i], "11", 2)) {
+            fprintf(output, "UT1-UTC (B)  ");
+        }
+        if(!strncmp(argv[i], "12", 2)) {
+            fprintf(output, " xErr (A)  ");
+        }
+        if(!strncmp(argv[i], "13", 2)) {
+            fprintf(output, " yErr (A)  ");
+        }
+        if(!strncmp(argv[i], "14", 2)) {
+            fprintf(output, " dXErr (A) ");
+        }
+        if(!strncmp(argv[i], "15", 2)) {
+            fprintf(output, " dYErr (A) ");
+        }
+        if(!strncmp(argv[i], "16", 2)) {
+            fprintf(output, "UT1-UTC Err");
+        }
+    }
+    fprintf(output, "\n#\n#\n");
+    int i;
+    while ( fscanf(input, "%188c", data2) != EOF) {
+
+        for(int j = 3; j < argc; j++) {
+            if(!strncmp(argv[j], "1", 2) ) {
+                for (i = 7; i <= 14; i++) {
+                    fprintf(output, "%c", data2[i]);
+                }
+            }
+            if(!strncmp(argv[j], "2", 2) ) {
+                if (data2[23] == ' ') {
+                    fprintf(output, "   0.000 ");
+                } else {
+                    for (i = 18; i <= 26; i++) {
+                        if (i == 18 && data2[i+1] == '-' && data2[i+2] == '.') {
+                            fprintf(output, "-0.");
+                            i = 21;
+                        }
+                        if (i == 19) {
+                            if (data2[i] == ' ' && data2[i+1] == '.') {
+                                fprintf(output, "0");
+                                i++;
+                            }
+                        }
+                        fprintf(output, "%c", data2[i]);
+                    }
+                }
+            }
+            if(!strncmp(argv[j], "3", 2) ) {
+                if (data2[42] == ' ') {
+                    fprintf(output, "   0.000 ");
+                } else {
+                    for (i = 37; i <= 45; i++) {
+                        if (i == 37 && data2[i+1] == '-' && data2[i+2] == '.') {
+                            fprintf(output, "-0.");
+                            i = 40;
+                        }
+                        if (i == 38) {
+                            if (data2[i] == ' ' && data2[i+1] == '.') {
+                                fprintf(output, "0");
+                                i++;
+                            }
+                        }
+                        fprintf(output, "%c", data2[i]);
+                    }
+                }
+            }
+            if(!strncmp(argv[j], "4", 2) ) {
+                if (data2[139] == ' ') {
+                    fprintf(output, "    0.000 ");
+                    //                    i = 144;
+                } else {
+                    for (i = 134; i <= 143; i++) {
+                        if (i == 135 && data2[i+1] == '-' && data2[i+2] == '.') {
+                            fprintf(output, "-0.");
+                            i = 138;
+                        }
+                        if (i == 136) {
+                            if (data2[i] == ' ' && data2[i+1] == '.') {
+                                fprintf(output, "0");
+                                i++;
+                            }
+                        }
+                        fprintf(output, "%c", data2[i]);
+                    }
+                }
+            }
+            if(!strncmp(argv[j], "5", 2) ) {
+                if (data2[149] == ' ') {
+                    fprintf(output, "    0.000 ");
+                } else {
+                    for (i = 144; i <= 153; i++) {
+                        if (i == 145 && data2[i+1] == '-' && data2[i+2] == '.') {
+                            fprintf(output, "-0.");
+                            i = 148;
+                        }
+                        if (i == 146) {
+                            if (data2[i] == ' ' && data2[i+1] == '.') {
+                                fprintf(output, "0");
+                                i++;
+                            }
+                        }
+                        fprintf(output, "%c", data2[i]);
+                    }
+                }
+            }
+            if(!strncmp(argv[j], "6", 2) ) {
+                if (data2[102] == ' ') {
+                    fprintf(output, "   0.000 ");
+                } else {
+                    for (i = 97; i <= 105; i++) {
+                        fprintf(output, "%c", data2[i]);
+                    }
+                }
+            }
+            if(!strncmp(argv[j], "7", 2) ) {
+                if (data2[121] == ' ') {
+                    fprintf(output, "   0.000 ");
+                } else {
+                    for (i = 116; i <= 124; i++) {
+                        fprintf(output, "%c", data2[i]);
+                    }
+                }
+            }
+            if(!strncmp(argv[j], "8", 2) ) {
+                if (data2[170] == ' ') {
+                    fprintf(output, "    0.000 ");
+                } else {
+                    for (i = 165; i <= 174; i++) {
+                        fprintf(output, "%c", data2[i]);
+                    }
+                }
+            }
+            if(!strncmp(argv[j], "9", 2) ) {
+                if (data2[180] == ' ') {
+                    fprintf(output, "    0.000 ");
+                } else {
+                    for (i = 175; i <= 184; i++) {
+                        fprintf(output, "%c", data2[i]);
+                    }
+                }
+            }
+            if(!strncmp(argv[j], "10", 2) ) {
+                if (data2[63] == ' ') {
+                    fprintf(output, "    0.000 ");
+                } else {
+                    for (i = 58; i <= 67; i++) {
+                        if (i == 58 && data2[i+1] == '-' && data2[i+2] == '.') {
+                            fprintf(output, "-0.");
+                            i = 61;
+                        }
+                        if (i == 59) {
+                            if (data2[i] == ' ' && data2[i+1] == '.') {
+                                fprintf(output, "0");
+                                i++;
+                            }
+                        }
+                        fprintf(output, "%c", data2[i]);
+                    }
+                }
+            }
+            if(!strncmp(argv[j], "11", 2) ) {
+                if (data2[159] == ' ') {
+                    fprintf(output, "     0.000 ");
+                } else {
+                    for (i = 154; i <= 164; i++) {
+                        if (i == 155 && data2[i+1] == '-' && data2[i+2] == '.') {
+                            fprintf(output, "-0.");
+                            i = 158;
+                        }
+                        if (i == 156) {
+                            if (data2[i] == ' ' && data2[i+1] == '.') {
+                                fprintf(output, "0");
+                                i++;
+                            }
+                        }
+                        fprintf(output, "%c", data2[i]);
+                    }
+                }
+            }
+            if(!strncmp(argv[j], "12", 2) ) {
+                if (data2[32] == ' ') {
+                    fprintf(output, "    0.000 ");
+                } else {
+                    for (i = 27; i <= 35; i++) {
+                        if (i == 27 && data2[i+1] == '-' && data2[i+2] == '.') {
+                            fprintf(output, "-0.");
+                            i = 30;
+                        }
+                        if (i == 28) {
+                            if (data2[i] == ' ' && data2[i+1] == '.') {
+                                fprintf(output, "0");
+                                i++;
+                            }
+                        }
+                        fprintf(output, "%c", data2[i]);
+                    }
+                }
+            }
+            if(!strncmp(argv[j], "13", 2) ) {
+                if (data2[51] == ' ') {
+                    fprintf(output, "     0.000 ");
+                } else {
+                    for (i = 46; i <= 54; i++) {
+                        if (i == 46 && data2[i+1] == '-' && data2[i+2] == '.') {
+                            fprintf(output, "-0.");
+                            i = 49;
+                        }
+                        if (i == 47) {
+                            if (data2[i] == ' ' && data2[i+1] == '.') {
+                                fprintf(output, "0");
+                                i++;
+                            }
+                        }
+                        fprintf(output, "%c", data2[i]);
+                    }
+                }
+            }
+            if(!strncmp(argv[j], "14", 2) ) {
+                if (data2[111] == ' ') {
+                    fprintf(output, "    0.000 ");
+                } else {
+                    for (i = 106; i <= 114; i++) {
+                        if (i == 106 && data2[i+1] == '-' && data2[i+2] == '.') {
+                            fprintf(output, "-0.");
+                            i = 109;
+                        }
+                        if (i == 107) {
+                            if (data2[i] == ' ' && data2[i+1] == '.') {
+                                fprintf(output, "0");
+                                i++;
+                            }
+                        }
+                        fprintf(output, "%c", data2[i]);
+                    }
+                }
+            }
+            if(!strncmp(argv[j], "15", 2) ) {
+                if (data2[131] == ' ') {
+                    fprintf(output, "     0.000 ");
+                } else {
+                    for (i = 125; i <= 133; i++) {
+                        if (i == 125 && data2[i+1] == '-' && data2[i+2] == '.') {
+                            fprintf(output, "-0.");
+                            i = 128;
+                        }
+                        if (i == 126) {
+                            if (data2[i] == ' ' && data2[i+1] == '.') {
+                                fprintf(output, "0");
+                                i++;
+                            }
+                        }
+                        fprintf(output, "%c", data2[i]);
+                    }
+                }
+            }
+            if(!strncmp(argv[j], "16", 2) ) {
+                if (data2[73] == ' ') {
+                    fprintf(output, "     0.000 ");
+                } else {
+                    for (i = 68; i <= 77; i++) {
+                        if (i == 155 && data2[i+1] == '-' && data2[i+2] == '.') {
+                            fprintf(output, "-0.");
+                            i = 71;
+                        }
+                        if (i == 69) {
+                            if (data2[i] == ' ' && data2[i+1] == '.') {
+                                fprintf(output, "0");
+                                i++;
+                            }
+                        }
+                        fprintf(output, "%c", data2[i]);
+                    }
+                }
+            }
+            fprintf(output, "  ");
+        }
+        fprintf(output, "\n");
+    }
+
+    fclose(input);
+    fclose(output);
+    return 0;
+}
+
+void printHeader(char *filename)
+{
+    if (output == NULL) {
+        printf("\n Unable to access output file.  Output is NULL.\n");
+    } else {
+        fprintf(output, "#\n#  Stripped version of %s file\n#\n#\n", filename);
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/.cvsignore	(revision 22158)
@@ -0,0 +1,29 @@
+autom4te.cache
+Makefile
+config.log
+config.status
+libtool
+Makefile.in
+aclocal.m4
+configure
+Doxyfile
+DoxygenLog
+docs
+man
+psmodules-config
+psmodules.pc
+bin
+include
+lib
+config.guess
+config.sub
+depcomp
+install-sh
+ltmain.sh
+missing
+psmodule.kdevelop.pcs
+psmodule-*.tar.gz
+psmodule-*.tar.bz2
+compile
+ChangeLog
+psmodules-*.tar.*
Index: /branches/eam_branches/eam_branch_20080719/psModules/AUTHORS
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/AUTHORS	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/AUTHORS	(revision 22158)
@@ -0,0 +1,1 @@
+Maui High Performance Computing Center, University of Hawai'i
Index: /branches/eam_branches/eam_branch_20080719/psModules/COPYING
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/COPYING	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/COPYING	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/Doxyfile.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/Doxyfile.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/Doxyfile.in	(revision 22158)
@@ -0,0 +1,1079 @@
+# Doxyfile 1.3.4
+
+# 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           = "Pan-STARRS Module Library"
+
+# 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         = @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.
+
+OUTPUT_DIRECTORY       = @builddir@/docs
+
+# 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, 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
+
+# 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    = YES
+
+# 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. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_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
+# explict @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = YES
+
+# 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         = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# reimplements.
+
+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
+
+# 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  = YES
+
+# 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            = NO
+
+#---------------------------------------------------------------------------
+# 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            = YES
+
+# 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  = 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 
+# 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
+
+# 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
+
+#---------------------------------------------------------------------------
+# 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
+
+# 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.
+
+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           = DoxygenLog
+
+#---------------------------------------------------------------------------
+# 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                  = 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
+
+FILE_PATTERNS          = *.h *.dox
+
+# 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       = *_wrap.c
+
+# 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.
+
+INPUT_FILTER           = 
+
+# 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.
+
+SOURCE_BROWSER         = YES
+
+# 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    = NO
+
+# 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     = YES
+
+# 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
+
+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 dir.
+
+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             = YES
+
+# 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   = 10
+
+# 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          = YES
+
+# 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             = letter
+
+# 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         = times
+
+# 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         = YES
+
+# 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           = YES
+
+# 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 optimised 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 assigments. 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              = YES
+
+#---------------------------------------------------------------------------
+# 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. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+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                = 
+
+#---------------------------------------------------------------------------
+# 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.
+
+PREDEFINED             = DOXYGEN
+
+# 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::addtions 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 superceded 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               = YES
+
+# 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 UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similiar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = YES
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = YES
+
+# 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
+
+# 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 on 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
+
+# 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::addtions 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: /branches/eam_branches/eam_branch_20080719/psModules/INSTALL
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/INSTALL	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/INSTALL	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/Makefile.am	(revision 22158)
@@ -0,0 +1,26 @@
+SUBDIRS = src test
+
+bin_SCRIPTS = psmodules-config
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA= psmodules.pc
+
+EXTRA_DIST = \
+	Doxyfile.in \
+	psmodules-config.in \
+	psmodules.pc.in \
+	autogen.sh
+
+if HAVE_DOXYGEN
+install-data-hook: doxygen
+	-$(mkdir_p) $(mandir)/man3
+	chmod 0755 $(mandir)/man3
+	-cp $(top_builddir)/docs/man/man3/* $(mandir)/man3
+
+doxygen:
+	$(DOXYGEN)
+endif
+
+CLEANFILES = $(prefix)/docs/psmodules/* *~
+
+test: check
Index: /branches/eam_branches/eam_branch_20080719/psModules/NEWS
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/NEWS	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/NEWS	(revision 22158)
@@ -0,0 +1,1 @@
+ 
Index: /branches/eam_branches/eam_branch_20080719/psModules/README
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/README	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/README	(revision 22158)
@@ -0,0 +1,1 @@
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/TODO
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/TODO	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/TODO	(revision 22158)
@@ -0,0 +1,1 @@
+ 
Index: /branches/eam_branches/eam_branch_20080719/psModules/autogen.sh
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/autogen.sh	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/autogen.sh	(revision 22158)
@@ -0,0 +1,114 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+PROJECT=psmodules
+TEST_TYPE=-f
+FILE=psmodules.pc.in
+
+DIE=0
+
+if [ "`which glibtoolize 2> /dev/null`" != "" ]
+ then LIBTOOLIZE=glibtoolize
+ else LIBTOOLIZE=libtoolize
+fi
+
+ACLOCAL="aclocal $ACLOCAL_FLAGS"
+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"
+
+# bypass taps bootstrap.sh
+cd ./test/tap
+$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: /branches/eam_branches/eam_branch_20080719/psModules/configure.ac
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/configure.ac	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/configure.ac	(revision 22158)
@@ -0,0 +1,348 @@
+AC_PREREQ(2.61)
+
+AC_INIT([psmodules],[1.1.0],[http://pan-starrs.ifa.hawaii.edu/bugzilla])
+AC_CONFIG_SRCDIR([psmodules.pc.in])
+
+dnl this enables the building of libtap
+AC_CONFIG_SUBDIRS([test/tap])
+
+AM_INIT_AUTOMAKE([1.7 foreign dist-bzip2])
+AM_CONFIG_HEADER([src/config.h])
+AM_MAINTAINER_MODE
+
+PSMODULES_LT_VERSION="1:1:0"
+AC_SUBST(PSMODULES_LT_VERSION,$PSMODULES_LT_VERSION)
+
+IPP_STDCFLAGS
+
+AC_LANG(C)
+AC_PROG_CC_C99
+AC_GNU_SOURCE
+AC_C_INLINE
+AC_C_CONST
+AC_PROG_INSTALL
+AM_PROG_LIBTOOL
+AC_SYS_LARGEFILE
+AC_FUNC_FSEEKO
+
+AC_PREFIX_DEFAULT([`pwd`])
+
+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)
+
+dnl ------------------- PERL options ---------------------
+  AC_ARG_WITH(perl,
+    [AS_HELP_STRING(--with-perl=FILE,Specify location of PERL executable.)],
+    [AC_CHECK_PROG(PERL, $withval, $withval)],
+    [AC_CHECK_PROG(PERL, perl, `which perl`)])
+    if test "$PERL" == ""
+    then
+      AC_MSG_ERROR([PERL is required.  Use --with-perl to specify its install location.])
+    fi
+    AC_SUBST(PERL,$PERL)
+
+SRCPATH='${top_srcdir}/src'
+SRCDIRS="extras config concepts camera astrom detrend imcombine objects"
+# escape two escapes at this level so \\ gets passed to the shell and \ to perl
+SRCINC=`echo "${SRCDIRS=}" | ${PERL} -pe "s|(\w+)|-I\\\\${SRCPATH=}/\1|g"`
+SRCINC="-I${SRCPATH=} ${SRCINC=}"
+SRCSUBLIBS=`echo "${SRCDIRS=}" | ${PERL} -pe "s|(\w+)|\1/libpsmodules\1.la|g"`
+AC_SUBST(SRCSUBLIBS,${SRCSUBLIBS=})
+AC_SUBST(SRCINC,${SRCINC=})
+AC_SUBST([SRCDIRS],${SRCDIRS=})
+
+dnl doxygen -------------------------------------------------------------------
+dnl doxygen doc generation is very, very slow so we're turing it off by default
+
+dnl save LIBS/CFLAGS/LDFLAGS
+TMP_LIBS=${LIBS}
+TMP_CFLAGS=${CFLAGS}
+TMP_LDFLAGS=${LDFLAGS}
+TMP_CPPFLAGS=${CPPFLAGS}
+
+AC_ARG_ENABLE(doxygen,
+  [AS_HELP_STRING(--enable-doxygen ,enable manpage generation)],
+  [AC_MSG_RESULT(doxygen enabled)
+    AC_PATH_PROG([DOXYGEN], [doxygen], [])
+  ],
+  [AC_MSG_RESULT([doxygen disabled])
+    doxygen=off
+  ]
+)
+AM_CONDITIONAL([HAVE_DOXYGEN], test -n "$DOXYGEN" -a "x$doxygen" != "xoff")
+
+dnl restore the CFLAGS/LDFLAGS
+LIBS=${TMP_LIBS}
+CFLAGS=${TMP_CFLAGS}
+LDFLAGS=${TMP_LDFLAGS}
+CPPFLAGS=${TMP_CPPFLAGS}
+
+dnl ------------------------------------------------------------
+
+AC_PATH_PROG([ERRORCODES], [psParseErrorCodes], [missing])
+if test "$ERRORCODES" = "missing" ; then
+  AC_MSG_ERROR([psParseErrorCodes is required])
+fi
+
+dnl ------------------ kapa,libkapa options -------------------------
+dnl -- libkapa implies the requirement for libpng, libjpeg as well --
+
+dnl save LIBS/CFLAGS/LDFLAGS
+TMP_LIBS=${LIBS}
+TMP_CFLAGS=${CFLAGS}
+TMP_LDFLAGS=${LDFLAGS}
+TMP_CPPFLAGS=${CPPFLAGS}
+
+dnl test for command-line options: use ohana-config if not supplied
+KAPA_CFLAGS_CONFIG="true"
+KAPA_LIBS_CONFIG="true"
+AC_ARG_WITH(kapa,
+[AS_HELP_STRING(--with-kapa=DIR,Specify location of libkapa)],
+[KAPA_CFLAGS="-I$withval/include" KAPA_LIBS="-L$withval/lib" 
+ KAPA_CFLAGS_CONFIG="false"       KAPA_LIBS_CONFIG="false"])
+AC_ARG_WITH(kapa-include,
+[AS_HELP_STRING(--with-kapa-include=DIR,Specify libkapa include directory.)],
+[KAPA_CFLAGS="-I$withval" KAPA_CFLAGS_CONFIG="false"])
+AC_ARG_WITH(kapa-lib,
+[AS_HELP_STRING(--with-kapa-lib=DIR,Specify libkapa library directory.)],
+[KAPA_LIBS="-L$withval" KAPA_LIBS_CONFIG="false"])
+
+echo "KAPA_CFLAGS_CONFIG: $KAPA_CFLAGS_CONFIG"
+echo "KAPA_LIBS_CONFIG: $KAPA_LIBS_CONFIG"
+echo "KAPA_CFLAGS: $KAPA_CFLAGS"
+echo "KAPA_LIBS: $KAPA_LIBS"
+
+dnl HAVE_KAPA is set to false if any of the tests fail
+HAVE_KAPA="true"
+AC_MSG_NOTICE([checking for libkapa])
+if test "$KAPA_CFLAGS_CONFIG" = "true" -o "$KAPA_LIBS_CONFIG" = "true"; then
+  AC_MSG_NOTICE([kapa info supplied by ohana-config])
+  KAPA_CONFIG=`which ohana-config`
+  AC_CHECK_FILE($KAPA_CONFIG,[],
+    [HAVE_KAPA="false"; AC_MSG_WARN([libkapa is not found: output plots disabled.  Obtain libkapa at http://kiawe.ifa.hawaii.edu/Elixir/Ohana or use --with-kapa to specify location])])
+  
+  echo "HAVE_KAPA: $HAVE_KAPA"
+  echo "KAPA_CFLAGS_CONFIG: $KAPA_CFLAGS_CONFIG"
+
+  if test "$HAVE_KAPA" = "true" -a "$KAPA_CFLAGS_CONFIG" = "true" ; then
+   AC_MSG_NOTICE([libkapa cflags info supplied by ohana-config])
+   AC_MSG_CHECKING([libkapa cflags])
+   KAPA_CFLAGS="`${KAPA_CONFIG} --cflags`"
+   AC_MSG_RESULT([${KAPA_CFLAGS}])
+  fi
+
+  if test "$HAVE_KAPA" = "true" -a "$KAPA_LIBS_CONFIG" = "true" ; then
+   AC_PATH_X
+   if test "$no_x" = "yes" ; then
+      AC_MSG_WARN([X11 not found: output plots using kapa disabled.  Use --x-includes and --x-libraries if required.])
+      HAVE_KAPA="false"
+   else
+      AC_MSG_NOTICE([libkapa ldflags info supplied by ohana-config])
+      AC_MSG_CHECKING([libkapa ldflags])
+      if test -n "$x_libraries" ; then
+            KAPA_LIBS="`${KAPA_CONFIG} --libs` -L$x_libraries -lX11"
+      else
+            KAPA_LIBS="`${KAPA_CONFIG} --libs` -lX11"
+      fi
+      if test -n "$x_includes" ; then
+            KAPA_CFLAGS="${KAPA_CFLAGS} -I$x_includes"
+      else
+            KAPA_CFLAGS="${KAPA_CFLAGS}"
+      fi
+      AC_MSG_RESULT([${KAPA_LIBS}])
+   fi
+  fi
+fi
+
+if test "$HAVE_KAPA" = "true" ; then
+ AC_MSG_NOTICE([libkapa supplied])
+ PSMODULES_CFLAGS="${PSMODULES_CFLAGS} ${KAPA_CFLAGS}"
+ PSMODULES_LIBS="${PSMODULES_LIBS} ${KAPA_LIBS}"
+else
+ AC_MSG_NOTICE([libkapa ignored])
+fi
+
+dnl HAVE_KAPA is set to false if any of the tests fail
+dnl HAVE_KAPA=true
+dnl AC_CHECK_HEADERS([kapa.h],
+dnl  [PSMODULES_CFLAGS="$PSMODULES_CFLAGS $KAPA_CFLAGS" AC_SUBST(KAPA_CFLAGS)],
+dnl  [HAVE_KAPA=false; AC_MSG_WARN([libkapa headers not found: output plots disabled.  Obtain libkapa at http://kiawe.ifa.hawaii.edu/Elixir/Ohana or use --with-kapa to specify location.])]
+dnl )
+dnl AC_CHECK_LIB(kapa,KapaInitGraph,
+dnl  [PSMODULES_LIBS="$PSMODULES_LIBS $JPEG_LDFLAGS -ljpeg"],  
+dnl  [HAVE_KAPA=false; AC_MSG_WARN([libkapa headers not found: output plots disabled.  Obtain libkapa at http://kiawe.ifa.hawaii.edu/Elixir/Ohana or use --with-kapa to specify location.])],[-lm]
+dnl )
+
+dnl restore the CFLAGS/LDFLAGS
+LIBS=${TMP_LIBS}
+CFLAGS=${TMP_CFLAGS}
+LDFLAGS=${TMP_LDFLAGS}
+CPPFLAGS=${TMP_CPPFLAGS}
+
+dnl ------------------ libjpeg options ---------------------
+
+dnl save LIBS/CFLAGS/LDFLAGS
+TMP_LIBS=${LIBS}
+TMP_CFLAGS=${CFLAGS}
+TMP_LDFLAGS=${LDFLAGS}
+TMP_CPPFLAGS=${CPPFLAGS}
+
+AC_ARG_WITH(jpeg,
+[AS_HELP_STRING(--with-jpeg=DIR,Specify location of libjpeg.)],
+[JPEG_CFLAGS="-I$withval/include"
+ JPEG_LDFLAGS="-L$withval/lib"])
+AC_ARG_WITH(jpeg-include,
+[AS_HELP_STRING(--with-jpeg-include=DIR,Specify libjpeg include directory.)],
+[JPEG_CFLAGS="-I$withval"])
+AC_ARG_WITH(jpeg-lib,
+[AS_HELP_STRING(--with-jpeg-lib=DIR,Specify libjpeg library directory.)],
+[JPEG_LDFLAGS="-L$withval"])
+
+CFLAGS="${CFLAGS} ${JPEG_CFLAGS}"
+CPPFLAGS=${CFLAGS}
+LDFLAGS="${LDFLAGS} ${JPEG_LDFLAGS}"
+
+AC_CHECK_HEADERS([jpeglib.h],
+  [PSMODULES_CFLAGS="$PSMODULES_CFLAGS $JPEG_CFLAGS" AC_SUBST(JPEG_CFLAGS)],
+  [HAVE_KAPA=false; AC_MSG_WARN([libjpeg headers not found: output plots disabled.  Obtain libjpeg from http://www.ijg.org/ or use --with-jpeg to specify location.])]
+)
+
+AC_CHECK_LIB(jpeg,jpeg_CreateCompress,
+  [PSMODULES_LIBS="$PSMODULES_LIBS $JPEG_LDFLAGS -ljpeg"],
+  [HAVE_KAPA=false; AC_MSG_WARN([libjpeg library not found: output plots disabled.  Obtain libjpeg from http://www.ijg.org/ or use --with-jpeg to specify location.])]
+)
+
+dnl restore the CFLAGS/LDFLAGS
+LIBS=${TMP_LIBS}
+CFLAGS=${TMP_CFLAGS}
+LDFLAGS=${TMP_LDFLAGS}
+CPPFLAGS=${TMP_CPPFLAGS}
+
+dnl ------------------ libpng options ---------------------
+
+dnl save LIBS/CFLAGS/LDFLAGS
+TMP_LIBS=${LIBS}
+TMP_CFLAGS=${CFLAGS}
+TMP_LDFLAGS=${LDFLAGS}
+TMP_CPPFLAGS=${CPPFLAGS}
+
+AC_ARG_WITH(png,
+[AS_HELP_STRING(--with-png=DIR,Specify location of libpng.)],
+[PNG_CFLAGS="-I$withval/include"
+ PNG_LDFLAGS="-L$withval/lib"])
+AC_ARG_WITH(png-include,
+[AS_HELP_STRING(--with-png-include=DIR,Specify libpng include directory.)],
+[PNG_CFLAGS="-I$withval"])
+AC_ARG_WITH(png-lib,
+[AS_HELP_STRING(--with-png-lib=DIR,Specify libpng library directory.)],
+[PNG_LDFLAGS="-L$withval"])
+
+CFLAGS="${CFLAGS} ${PNG_CFLAGS}"
+CPPFLAGS=${CFLAGS}
+LDFLAGS="${LDFLAGS} ${PNG_LDFLAGS}"
+
+AC_CHECK_HEADERS([png.h],
+  [PSMODULES_CFLAGS="$PSMODULES_CFLAGS $PNG_CFLAGS" AC_SUBST(PNG_CFLAGS)],
+  [HAVE_KAPA=false; AC_MSG_WARN([libpng headers not found: output plots disabled.  Obtain libpng from http://www.ijg.org/ or use --with-png to specify location.])]
+)
+
+AC_CHECK_LIB(png,png_init_io,
+  [PSMODULES_LIBS="$PSMODULES_LIBS $PNG_LDFLAGS -lpng"],
+  [HAVE_KAPA=false; AC_MSG_WARN([libpng library not found: output plots disabled.  Obtain libpng from http://www.ijg.org/ or use --with-png to specify location.])]
+)
+
+dnl restore the CFLAGS/LDFLAGS
+LIBS=${TMP_LIBS}
+CFLAGS=${TMP_CFLAGS}
+LDFLAGS=${TMP_LDFLAGS}
+CPPFLAGS=${TMP_CPPFLAGS}
+
+dnl ------------------ use kapa or not? ---------------------
+
+if test "$HAVE_KAPA" == "true" ; then
+  AC_MSG_RESULT([including plotting functions])
+  AC_DEFINE([HAVE_KAPA],[1],[enable use of libkapa])
+else
+  AC_MSG_RESULT([skipping plotting functions])
+  AC_DEFINE([HAVE_KAPA],[0],[disable use of libkapa])
+fi
+
+dnl pslib ---------------------------------------------------------------------
+AC_ARG_WITH(pslib-config,
+[  --with-pslib-config=FILE  Specify location of psLib-config script],
+[PSLIB_CONFIG=$withval])
+
+if test -z ${PSLIB_CONFIG} ; then
+  PKG_CHECK_MODULES([PSLIB], [pslib >= 0.12.0])
+else
+  AC_CHECK_FILE($PSLIB_CONFIG,[],
+    [AC_MSG_ERROR([psLib is required.  If not in path, use --with-pslib-config to specify pslib-config script location.])])
+  AC_MSG_CHECKING([PSLIB_CFLAGS])
+  PSLIB_CFLAGS="`${PSLIB_CONFIG} --cflags`"
+  AC_MSG_RESULT([${PSLIB_CFLAGS}])
+  AC_MSG_CHECKING([PSLIB_LIBS])
+  PSLIB_LIBS="`${PSLIB_CONFIG} --libs`"
+  AC_MSG_RESULT([${PSLIB_LIBS}])
+fi
+
+PSMODULES_CFLAGS="${PSMODULES_CFLAGS=} ${PSLIB_CFLAGS}"
+PSMODULES_LIBS="${PSMODULES_LIBS=} ${PSLIB_LIBS}"
+
+dnl nebclient -----------------------------------------------------------------
+
+PKG_CHECK_MODULES([NEBCLIENT], [nebclient >= 0.0.2],
+    [AC_DEFINE([HAVE_NEBCLIENT], 1, [Define to 1 if libnebclient is avaiable])],    [AC_MSG_RESULT([no])]
+)
+
+PSMODULES_CFLAGS="${PSMODULES_CFLAGS=} ${NEBCLIENT_CFLAGS}"
+PSMODULES_LIBS="${PSMODULES_LIBS=} ${NEBCLIENT_LIBS}"
+
+echo "PSMODULES_CFLAGS: $PSMODULES_CFLAGS"
+echo "PSMODULE_LIBS: $PSMODULES_LIBS"
+
+dnl ------- enable -Werror after all of the probes have run ---------
+IPP_STDOPTS
+
+CFLAGS="${CFLAGS} -Wall -Werror"
+dnl enable POSIX/XSI and C99 compliance
+CFLAGS="${CFLAGS=} -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L"
+
+dnl ---------------- export variables --------------------
+
+
+AC_SUBST([PSMODULES_CFLAGS])
+AC_SUBST([PSMODULES_LIBS])
+
+AC_CONFIG_FILES([
+  Makefile
+  src/Makefile
+  src/astrom/Makefile
+  src/camera/Makefile
+  src/config/Makefile
+  src/concepts/Makefile
+  src/detrend/Makefile
+  src/imcombine/Makefile
+  src/objects/Makefile
+  src/extras/Makefile
+  test/Makefile
+  test/astrom/Makefile
+  test/config/Makefile
+  test/camera/Makefile
+  test/concepts/Makefile
+  test/detrend/Makefile
+  test/extras/Makefile
+  test/imcombine/Makefile
+  test/objects/Makefile
+  test/pstap/Makefile
+  test/pstap/src/Makefile
+  Doxyfile
+  psmodules-config
+  psmodules.pc
+])
+
+AC_OUTPUT
Index: /branches/eam_branches/eam_branch_20080719/psModules/psmodules-config.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/psmodules-config.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/psmodules-config.in	(revision 22158)
@@ -0,0 +1,76 @@
+#! /bin/sh
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/@PACKAGE_NAME@
+
+usage()
+{
+    cat <<EOF
+Usage: pslib-config [OPTION]
+
+Known values for OPTION are:
+
+  --prefix		print psLib installation prefix
+  --libs		print library linking information
+  --cflags		print pre-processor and compiler flags
+  --help		display this help and exit
+  --version		output version information
+
+EOF
+
+    exit $1
+}
+
+if test $# -eq 0; then
+    usage 1
+fi
+
+cflags=false
+libs=false
+
+while test $# -gt 0; do
+    case "$1" in
+    -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+    *) optarg= ;;
+    esac
+
+    case "$1" in
+    --prefix=*)
+	prefix=$optarg
+	;;
+
+    --prefix)
+	echo $prefix
+	;;
+
+    --version)
+	echo @VERSION@
+	exit 0
+	;;
+
+    --help)
+	usage 0
+	;;
+
+    --cflags)
+       	echo -I${includedir} @PSMODULES_CFLAGS@
+       	;;
+
+    --libs)
+       	echo -L${libdir} -lpsmodules @PSMODULES_LIBS@
+       	;;
+
+    --deps)
+       	echo @LDFLAGS@
+       	;;
+    *)
+	usage
+	exit 1
+	;;
+    esac
+    shift
+done
+
+exit 0
Index: /branches/eam_branches/eam_branch_20080719/psModules/psmodules.pc.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/psmodules.pc.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/psmodules.pc.in	(revision 22158)
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/@PACKAGE_NAME@
+
+Name: @PACKAGE_NAME@
+Description: Pan-STARRS Module Library
+Version: @VERSION@
+Requires: pslib
+Libs: -L${libdir} -lpsmodules
+Libs.private: @PSMODULES_LIBS@
+Cflags: -I${includedir} @PSMODULES_CFLAGS@
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/.cvsignore	(revision 22158)
@@ -0,0 +1,9 @@
+.deps
+.libs
+Makefile
+config.h
+stamp-h1
+Makefile.in
+config.h.in
+*.la
+*.lo
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/Makefile.am	(revision 22158)
@@ -0,0 +1,13 @@
+SUBDIRS = $(SRCDIRS)
+lib_LTLIBRARIES = libpsmodules.la
+
+libpsmodules_la_CPPFLAGS = $(SRCINC)
+libpsmodules_la_LIBADD = $(SRCSUBLIBS) $(PSMODULES_LIBS)
+libpsmodules_la_DEPENDENCIES = $(SRCSUBLIBS)
+libpsmodules_la_SOURCES = 
+libpsmodules_la_LDFLAGS = -version-info $(PSMODULES_LT_VERSION)
+
+pkginclude_HEADERS = \
+	psmodules.h
+
+CLEANFILES = *~
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/.cvsignore	(revision 22158)
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/Makefile.am	(revision 22158)
@@ -0,0 +1,23 @@
+noinst_LTLIBRARIES = libpsmodulesastrom.la
+
+libpsmodulesastrom_la_CPPFLAGS = $(SRCINC) $(PSMODULES_CFLAGS) -I../pslib/
+libpsmodulesastrom_la_LDFLAGS  = -release $(PACKAGE_VERSION)
+libpsmodulesastrom_la_SOURCES  = \
+	pmAstrometryObjects.c \
+	pmAstrometryRegions.c \
+	pmAstrometryDistortion.c \
+	pmAstrometryUtils.c \
+	pmAstrometryModel.c \
+	pmAstrometryRefstars.c \
+	pmAstrometryWCS.c
+
+pkginclude_HEADERS = \
+	pmAstrometryObjects.h \
+	pmAstrometryRegions.h \
+	pmAstrometryDistortion.h \
+	pmAstrometryUtils.h \
+	pmAstrometryModel.h \
+	pmAstrometryRefstars.h \
+	pmAstrometryWCS.h
+
+CLEANFILES = *~
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryDistortion.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryDistortion.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryDistortion.c	(revision 22158)
@@ -0,0 +1,348 @@
+/** @file  pmAstrometryDistortion.c
+*
+*  @brief This file defines the basic types for measuring the focal-plane distortion.
+*
+*  @ingroup AstroImage
+*
+*  @author EAM, IfA
+*
+*  @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-11-12 21:58:17 $
+*
+*  Copyright 2006 Institute for Astronomy, University of Hawaii
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/******************************************************************************/
+/*  INCLUDE FILES                                                             */
+/******************************************************************************/
+
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPAExtent.h"
+#include "pmAstrometryObjects.h"
+#include "pmAstrometryRegions.h"
+#include "pmAstrometryDistortion.h"
+#include "pmKapaPlots.h"
+
+static void pmAstromGradientFree (pmAstromGradient *grad)
+{
+
+    if (grad == NULL)
+        return;
+
+    return;
+}
+
+pmAstromGradient *pmAstromGradientAlloc ()
+{
+
+    pmAstromGradient *gradient = psAlloc (sizeof(pmAstromGradient));
+    psMemSetDeallocator(gradient, (psFreeFunc) pmAstromGradientFree);
+
+    return (gradient);
+}
+
+psArray *pmAstromMeasureGradients(psArray *gradients, psArray *rawstars, psArray *refstars, psArray *matches, psRegion *region, int Nx, int Ny)
+{
+
+    if (gradients == NULL) {
+        gradients = psArrayAllocEmpty (100);
+    }
+
+    // NOTE: region specifies the FP region in pixels covered by the chip (NOT in FP units)
+    // determine range
+    int DX = (region->x1 - region->x0) / Nx;
+    int DY = (region->y1 - region->y0) / Ny;
+
+    psPolynomial2D *local = psPolynomial2DAlloc (PS_POLYNOMIAL_ORD, 1, 1);
+    local->coeffMask[1][1] = PS_POLY_MASK_SET;
+
+    // measure gradient for fractional chip regions
+    for (int nx = 0; nx < Nx; nx++) {
+        for (int ny = 0; ny < Ny; ny++) {
+            int Xmin = nx*DX;
+            int Xmax = Xmin + DX;
+            int Ymin = ny*DY;
+            int Ymax = Ymin + DY;
+
+            psStats *stats = NULL;
+            psVector *mask = NULL;
+            pmAstromGradient *grad = NULL;
+
+            psVector *L  = psVectorAllocEmpty (100, PS_TYPE_F32);
+            psVector *M  = psVectorAllocEmpty (100, PS_TYPE_F32);
+            psVector *dP = psVectorAllocEmpty (100, PS_TYPE_F32);
+            psVector *dQ = psVectorAllocEmpty (100, PS_TYPE_F32);
+
+            // XXX this is a bit inefficient: first sorting by X or Y could speed this up.
+            // XXX or assigning to a segment in a single pass first
+            // select the stars within this chip region
+            int Npts = 0;
+            for (int i = 0; i < matches->n; i++) {
+
+                pmAstromMatch *match = matches->data[i];
+
+                pmAstromObj *raw = rawstars->data[match->raw];
+
+                if (raw->chip->x < Xmin) continue;
+                if (raw->chip->x > Xmax) continue;
+                if (raw->chip->y < Ymin) continue;
+                if (raw->chip->y > Ymax) continue;
+
+                pmAstromObj *ref = refstars->data[match->ref];
+
+                L->data.F32[Npts] = ref->FP->x;
+                M->data.F32[Npts] = ref->FP->y;
+
+                // P,Q = L,M + terms of order epsilon.
+                // measuring the gradient constrains thos terms
+                dP->data.F32[Npts] = ref->TP->x - raw->FP->x;
+                dQ->data.F32[Npts] = ref->TP->y - raw->FP->y;
+
+                psVectorExtend (L, 100, 1);
+                psVectorExtend (M, 100, 1);
+                psVectorExtend (dP, 100, 1);
+                psVectorExtend (dQ, 100, 1);
+                Npts++;
+            }
+
+            psTrace ("psModules.astrom", 4, "Npts: %d (%d,%d) : (%d - %d),(%d - %d)\n", Npts, nx, ny, Xmin, Xmax, Ymin, Ymax);
+
+            if (Npts < 5)
+                goto skip;
+
+            // stats structure and mask for use in measuring the clipping statistic
+            // this analysis has too few data points to use the robust median method
+            stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
+            mask = psVectorAlloc (Npts, PS_TYPE_MASK);
+            psVectorInit (mask, 0);
+
+            grad = pmAstromGradientAlloc ();
+
+            // fit the collection of positions and offsets with a local 1st order gradient
+            // apply 3hi/3lo sigma clipping to the fitted data values
+            // the mask is used to mark the points which pass / fail the fit
+            if (!psVectorClipFitPolynomial2D (local, stats, mask, 0xff, dP, NULL, L, M)) {
+                goto skip;
+            }
+
+            grad->dTPdL.x = local->coeff[1][0];
+            grad->dTPdM.x = local->coeff[0][1];
+
+            // fit the collection of positions and offsets with a local 1st order gradient
+            // apply 3hi/3lo sigma clipping to the fitted data values
+            // the mask is used to mark the points which pass / fail the fit
+            if (!psVectorClipFitPolynomial2D (local, stats, mask, 0xff, dQ, NULL, L, M)) {
+                goto skip;
+            }
+
+            grad->dTPdL.y = local->coeff[1][0];
+            grad->dTPdM.y = local->coeff[0][1];
+
+            // also measure the L and M median positions as a representative coordinate
+            psVectorStats (stats, L, NULL, NULL, 0);
+            grad->FP.x = stats->sampleMedian;
+
+            psVectorStats (stats, M, NULL, NULL, 0);
+            grad->FP.y = stats->sampleMedian;
+
+            psArrayAdd (gradients, 100, grad);
+
+skip:
+            psFree (grad);
+            psFree (stats);
+            psFree (mask);
+            psFree (L);
+            psFree (M);
+            psFree (dP);
+            psFree (dQ);
+        }
+    }
+    psFree (local);
+    return gradients;
+}
+
+bool pmAstromFitDistortion(pmFPA *fpa, psArray *gradients, double pixelScale)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_ARRAY_NON_NULL(gradients, false);
+
+    psPolynomial2D *localX = NULL;
+    psPolynomial2D *localY = NULL;
+
+    // assign the gradient elements to psVectors for fitting
+    psVector *dPdL = psVectorAlloc (gradients->n, PS_TYPE_F32);
+    psVector *dQdL = psVectorAlloc (gradients->n, PS_TYPE_F32);
+    psVector *dPdM = psVectorAlloc (gradients->n, PS_TYPE_F32);
+    psVector *dQdM = psVectorAlloc (gradients->n, PS_TYPE_F32);
+    psVector *L = psVectorAlloc (gradients->n, PS_TYPE_F32);
+    psVector *M = psVectorAlloc (gradients->n, PS_TYPE_F32);
+
+    for (int i = 0; i < gradients->n; i++) {
+
+        pmAstromGradient *grad = gradients->data[i];
+
+        dPdL->data.F32[i] = grad->dTPdL.x;
+        dQdL->data.F32[i] = grad->dTPdL.y;
+
+        dPdM->data.F32[i] = grad->dTPdM.x;
+        dQdM->data.F32[i] = grad->dTPdM.y;
+
+        L->data.F32[i] = grad->FP.x;
+        M->data.F32[i] = grad->FP.y;
+    }
+
+    // mask and stats structure for measuring the clipping statistic
+    // this analysis has too few data points to use the robust median method
+    psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
+    psVector *mask = psVectorAlloc (gradients->n, PS_TYPE_MASK);
+    psVectorInit (mask, 0);
+
+    // the order of the gradient fits need to be 1 less than the distortion term
+    // determine the gradient order(s) from the fpa->toTP structure
+    localX = psPolynomial2DAlloc (PS_POLYNOMIAL_ORD, fpa->toTPA->x->nX-1, fpa->toTPA->x->nY);
+    localY = psPolynomial2DAlloc (PS_POLYNOMIAL_ORD, fpa->toTPA->x->nX,   fpa->toTPA->x->nY-1);
+
+    // set masks based on fpa->toTPA
+    for (int i = 0; i <= fpa->toTPA->x->nX; i++) {
+        for (int j = 0; j <= fpa->toTPA->x->nY; j++) {
+            if ((i > 0) && (i <= fpa->toTPA->x->nX)) {
+                localX->coeffMask[i-1][j] = fpa->toTPA->x->coeffMask[i][j];
+            }
+            if ((j > 0) && (j <= fpa->toTPA->x->nY)) {
+                localY->coeffMask[i][j-1] = fpa->toTPA->x->coeffMask[i][j];
+            }
+        }
+    }
+
+    // fit the local gradients in each direction
+    if (!psVectorClipFitPolynomial2D (localX, stats, mask, 0xff, dPdL, NULL, L, M)) {
+        psLogMsg ("psastro", 3, "failed to fit x-dir gradient\n");
+        psFree (localX);
+        psFree (localY);
+        goto escape;
+    }
+
+    if (!psVectorClipFitPolynomial2D (localY, stats, mask, 0xff, dPdM, NULL, L, M)) {
+        psLogMsg ("psastro", 3, "failed to fit y-dir gradient\n");
+        psFree (localX);
+        psFree (localY);
+        goto escape;
+    }
+
+    // update fpa->toTP distortion terms
+    fpa->toTPA->x->coeff[0][0] = 0;
+    for (int i = 1; i <= fpa->toTPA->x->nX; i++) {
+        if (fpa->toTPA->x->coeffMask[i][0] & PS_POLY_MASK_SET) {
+            continue;
+        }
+        fpa->toTPA->x->coeff[i][0] = localX->coeff[i-1][0] / i;
+    }
+    for (int j = 1; j <= fpa->toTPA->x->nY; j++) {
+        if (fpa->toTPA->x->coeffMask[0][j] & PS_POLY_MASK_SET) {
+            continue;
+        }
+        fpa->toTPA->x->coeff[0][j] = localY->coeff[0][j-1] / j;
+    }
+    for (int i = 1; i <= fpa->toTPA->x->nX; i++) {
+        for (int j = 1; j <= fpa->toTPA->x->nY; j++) {
+            if (fpa->toTPA->x->coeffMask[i][j] & PS_POLY_MASK_SET) {
+                continue;
+            }
+            fpa->toTPA->x->coeff[i][j] = 0.5*(localX->coeff[i-1][j] / i + localY->coeff[i][j-1] / j);
+        }
+    }
+    fpa->toTPA->x->coeff[1][0] += 1.0;
+    psFree (localX);
+    psFree (localY);
+
+    // the order of the gradient fits need to be 1 less than the distortion term
+    // determine the gradient order(s) from the fpa->toTP structure
+    localX = psPolynomial2DAlloc (PS_POLYNOMIAL_ORD, fpa->toTPA->y->nX-1, fpa->toTPA->y->nY);
+    localY = psPolynomial2DAlloc (PS_POLYNOMIAL_ORD, fpa->toTPA->y->nX,   fpa->toTPA->y->nY-1);
+
+    // set masks based on fpa->toTP
+    for (int i = 0; i < fpa->toTPA->y->nX; i++) {
+        for (int j = 0; j < fpa->toTPA->y->nY; j++) {
+            if ((i > 0) && (i <= fpa->toTPA->y->nX)) {
+                localX->coeffMask[i-1][j] = fpa->toTPA->y->coeffMask[i][j];
+            }
+            if ((j > 0) && (j <= fpa->toTPA->y->nY)) {
+                localY->coeffMask[i][j-1] = fpa->toTPA->y->coeffMask[i][j];
+            }
+        }
+    }
+
+    // fit the local gradients in each direction
+    psVectorClipFitPolynomial2D (localX, stats, mask, 0xff, dQdL, NULL, L, M);
+    psVectorClipFitPolynomial2D (localY, stats, mask, 0xff, dQdM, NULL, L, M);
+
+    // update fpa->toTP distortion terms
+    fpa->toTPA->y->coeff[0][0] = 0;
+    for (int i = 1; i <= fpa->toTPA->y->nX; i++) {
+        if (fpa->toTPA->y->coeffMask[i][0] & PS_POLY_MASK_SET) {
+            continue;
+        }
+        fpa->toTPA->y->coeff[i][0] = localX->coeff[i-1][0] / i;
+    }
+    for (int j = 1; j <= fpa->toTPA->y->nY; j++) {
+        if (fpa->toTPA->y->coeffMask[0][j] & PS_POLY_MASK_SET) {
+            continue;
+        }
+        fpa->toTPA->y->coeff[0][j] = localY->coeff[0][j-1] / j;
+    }
+    for (int i = 1; i <= fpa->toTPA->y->nX; i++) {
+        for (int j = 1; j <= fpa->toTPA->y->nY; j++) {
+            if (fpa->toTPA->y->coeffMask[i][j] & PS_POLY_MASK_SET) {
+                continue;
+            }
+            fpa->toTPA->y->coeff[i][j] = 0.5*(localX->coeff[i-1][j] / i + localY->coeff[i][j-1] / j);
+        }
+    }
+    fpa->toTPA->y->coeff[0][1] += 1.0;
+    psFree (localX);
+    psFree (localY);
+
+    // free unneeded structures
+    psFree (dPdL);
+    psFree (dPdM);
+    psFree (dQdL);
+    psFree (dQdM);
+    psFree (L);
+    psFree (M);
+    psFree (stats);
+    psFree (mask);
+
+    // reset the fromTPA terms here. choose an appropriate region based on the dimensions of
+    // the complete FPA
+    psRegion *region = pmAstromFPAExtent (fpa);
+
+    psFree (fpa->fromTPA);
+    fpa->fromTPA = psPlaneTransformInvert(NULL, fpa->toTPA, *region, 50);
+    psFree (region);
+
+    if (fpa->fromTPA == NULL) {
+        psError (PS_ERR_UNKNOWN, false, "failed to invert fpa->toTPA\n");
+        return false;
+    }
+
+    return true;
+
+escape:
+    // free unneeded structures
+    psFree (dPdL);
+    psFree (dPdM);
+    psFree (dQdL);
+    psFree (dQdM);
+    psFree (L);
+    psFree (M);
+    psFree (stats);
+    psFree (mask);
+    return false;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryDistortion.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryDistortion.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryDistortion.h	(revision 22158)
@@ -0,0 +1,59 @@
+/* @file  pmAstrometryDistortion.h
+ * @brief This file defines the basic types for measuring and fitting the focal-plane distortion.
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-03-18 22:07:17 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_ASTROMETRY_DISTORTION_H
+#define PM_ASTROMETRY_DISTORTION_H
+
+/// @addtogroup Astrometry
+/// @{
+
+/* The following data structure carries the information about the residual
+ * gradient of source positions in the tangent plane (pmAstromObj.TP) as a
+ * function of position in the focal plane (pmAstromObj.FP).
+ */
+typedef struct
+{
+    psPlane FP;
+    psPlane dTPdL;
+    psPlane dTPdM;
+}
+pmAstromGradient;
+
+pmAstromGradient *pmAstromGradientAlloc ();
+
+/* The following function determines the position residual, in the tangent
+ * plane, as a function of position in the focal plane, for a collection of raw
+ * measurements and matched reference stars. The configuration data must include
+ * the bin size over which the gradient is measured (keyword: ASTROM.GRAD.BOX).
+ * The function returns an array of pmAstromGradient structures, defined below.
+ */
+psArray *pmAstromMeasureGradients(
+    psArray *gradients,
+    psArray *rawstars,
+    psArray *refstars,
+    psArray *matches,
+    psRegion *region,
+    int Nx, int Ny
+);
+
+/* The gradient set measured above can be fitted with a pair of 2D
+ * polynomials. The resulting fits can then be related back to the implied
+ * polynomials which represent the distortion. The following function performs
+ * the fit and applies the result to the distortion transformation of the
+ * supplied pmFPA structure. The configuration variable supplies the polynomial
+ * order (keyword: ASTROM.DISTORT.ORDER).
+ */
+bool pmAstromFitDistortion(
+    pmFPA *fpa,
+    psArray *gradients,
+    double pixelScale);
+
+/// @}
+#endif // PM_ASTROMETRY_DISTORTION_H
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryModel.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryModel.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryModel.c	(revision 22158)
@@ -0,0 +1,766 @@
+/** @file  pmAstrometryModel.c
+ *
+ *  @brief Functions to read and write astrometric model
+ *
+ *  The generic model does not specify the location of the boresite on the sky, and it includes
+ *  a model for the rotator and motion of the boresite.
+ *
+ *  @ingroup AstroImage
+ *
+ *  @author EAM, IfA
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-17 22:38:15 $
+ *
+ *  Copyright 2007 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/******************************************************************************/
+/*  INCLUDE FILES                                                             */
+/******************************************************************************/
+#include <stdio.h>
+#include <strings.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include <unistd.h>   // for unlink
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+#include "pmFPAExtent.h"
+#include "pmFPAfileFitsIO.h"
+#include "pmAstrometryWCS.h"
+#include "pmAstrometryUtils.h"
+#include "pmAstrometryRegions.h"
+#include "pmAstrometryModel.h"
+
+# define REQUIRE(TEST,MESSAGE){ if (!(TEST)) { psAbort (MESSAGE); }}
+
+/********************* CheckDataStatus functions *****************************/
+
+bool pmAstromModelCheckDataStatusForView (const pmFPAview *view, pmFPAfile *file) {
+
+    pmFPA *fpa = file->fpa;
+
+    if (view->chip == -1) {
+        bool exists = pmAstromModelCheckDataStatusForFPA (fpa);
+        return exists;
+    }
+    if (view->chip >= fpa->chips->n) {
+        psError(PS_ERR_IO, true, "Requested chip == %d >= fpa->chips->n == %ld", view->chip, fpa->chips->n);
+        return false;
+    }
+    pmChip *chip = fpa->chips->data[view->chip];
+
+    if (view->cell == -1) {
+        bool exists = pmAstromModelCheckDataStatusForChip (chip);
+        return exists;
+    }
+    if (view->cell >= chip->cells->n) {
+        psError(PS_ERR_IO, true, "Requested cell == %d >= chip->cells->n == %ld", view->cell, chip->cells->n);
+        return false;
+    }
+    psError(PS_ERR_IO, false, "Astrometry only valid at the chip level");
+    return false;
+}
+
+bool pmAstromModelCheckDataStatusForFPA (const pmFPA *fpa) {
+
+    if (!fpa->toTPA) return false;
+    if (!fpa->fromTPA) return false;
+    if (!fpa->toSky) return false;
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        if (!chip) continue;
+        if (pmAstromModelCheckDataStatusForChip (chip)) return true;
+    }
+    return false;
+}
+
+bool pmAstromModelCheckDataStatusForChip (const pmChip *chip) {
+
+    if (!chip->toFPA) return false;
+    if (!chip->fromFPA) return false;  // XXX not strictly needed?
+    return true;
+}
+
+/********************* Write Data functions *****************************/
+
+bool pmAstromModelWriteForView (const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    // write the full model in one pass: require the level to be FPA
+    if (view->chip != -1) {
+        psError(PS_ERR_IO, false, "Astrometry must be written at the FPA level");
+        return false;
+    }
+
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, false); // Suitable FPA for writing
+
+    if (!pmAstromModelWriteFPA(file, fpa)) {
+        psError(PS_ERR_IO, false, "Failed to write Astrometry for fpa");
+        psFree(fpa);
+        return false;
+    }
+
+    psFree(fpa);
+
+    return true;
+}
+
+// write out all chip-level Astrometry data for this FPA
+bool pmAstromModelWriteFPA (pmFPAfile *file, const pmFPA *fpa)
+{
+
+
+    if (!pmAstromModelWritePHU (file, fpa)) {
+        psError(PS_ERR_IO, false, "Failed to write PHU for Astrometry model");
+        return false;
+    }
+
+    if (!pmAstromModelWriteChips (file)) {
+        psError(PS_ERR_IO, false, "Failed to write Astrometry for chips");
+        return false;
+    }
+
+    if (!pmAstromModelWriteFP (file)) {
+        psError(PS_ERR_IO, false, "Failed to write Sky for Astrometry model");
+        return false;
+    }
+
+    if (!pmAstromModelWriteTP (file)) {
+        psError(PS_ERR_IO, false, "Failed to write Sky for Astrometry model");
+        return false;
+    }
+
+    if (!pmAstromModelWriteSky (file)) {
+        psError(PS_ERR_IO, false, "Failed to write Sky for Astrometry model");
+        return false;
+    }
+
+    return true;
+}
+
+bool pmAstromModelWritePHU (pmFPAfile *file, const pmFPA *fpa) {
+    // Need to have an FPA suitable for writing, so that the headers are all kosher
+
+    // output header data
+    psMetadata *outhead = psMetadataAlloc();
+
+    // use the FPA phu to generate the PHU header
+    pmHDU *phu = fpa->hdu;
+
+    // if there is no FPA PHU, this is a single header+image (extension-less) file. This could be
+    // the case for an input SPLIT set of files being written out as a MEF.  if there is a PHU,
+    // write it out as a 'blank'
+    if (phu) {
+        psMetadataCopy (outhead, phu->header);
+    } else {
+        pmConfigConformHeader (outhead, file->format);
+    }
+
+    psMetadataAddBool (outhead, PS_LIST_TAIL, "EXTEND", PS_META_REPLACE, "this file has extensions", true);
+    psFitsWriteBlank (file->fits, outhead, "");
+    file->wrote_phu = true;
+
+    psTrace ("pmFPAfile", 5, "wrote phu %s (type: %d)\n", file->filename, file->type);
+    psFree (outhead);
+
+    return true;
+}
+
+// fourth layer holds the chips
+bool pmAstromModelWriteChips (pmFPAfile *file) {
+
+    psMetadata *header = psMetadataAlloc();
+    psMetadataAddStr(header, PS_LIST_TAIL, "COORD",    PS_META_REPLACE, "name of this layer",   "CHIPS");
+    psMetadataAddStr(header, PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "FOCAL_PLANE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "BOUNDARY", PS_META_REPLACE, "validity region",      "RECTANGLE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "TRANSFRM", PS_META_REPLACE, "mapping to parent",    "POLYNOMIAL");
+
+    psArray *model = psArrayAllocEmpty (1);
+
+    pmFPAview *view = pmFPAviewAlloc (0);
+
+    pmChip *chip = NULL;
+    while ((chip = pmFPAviewNextChip (view, file->fpa, 1)) != NULL) {
+
+        if (!chip->toFPA) continue;
+        assert (chip->toFPA->x);
+        assert (chip->toFPA->y);
+
+        psRegion *region = pmChipPixels (chip);
+
+        // set the chip name
+        char *chiprule = psStringCopy ("{CHIP.NAME}");
+        char *chipname = pmFPAfileNameFromRule (chiprule, file, view);
+
+        for (int i = 0; i <= chip->toFPA->x->nX; i++) {
+            for (int j = 0; j <= chip->toFPA->x->nY; j++) {
+                psMetadata *row = psMetadataAlloc ();
+
+                psMetadataAddStr(row,    PS_LIST_TAIL, "SEGMENT",  PS_META_REPLACE, "name of this segment", chipname);
+                psMetadataAddStr(row,    PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "FOCAL_PLANE");
+                psMetadataAddF32(row,    PS_LIST_TAIL, "MINX",     PS_META_REPLACE, "range", region->x0);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "MAXX",     PS_META_REPLACE, "range", region->x1);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "MINY",     PS_META_REPLACE, "range", region->y0);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "MAXY",     PS_META_REPLACE, "range", region->y1);
+
+                psMetadataAddS32(row,    PS_LIST_TAIL, "XORDER",   PS_META_REPLACE, "", i);
+                psMetadataAddS32(row,    PS_LIST_TAIL, "YORDER",   PS_META_REPLACE, "", j);
+                psMetadataAddS32(row,    PS_LIST_TAIL, "NXORDER",  PS_META_REPLACE, "", chip->toFPA->x->nX);
+                psMetadataAddS32(row,    PS_LIST_TAIL, "NYORDER",  PS_META_REPLACE, "", chip->toFPA->x->nY);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "POLY_X",   PS_META_REPLACE, "", chip->toFPA->x->coeff[i][j]);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "POLY_Y",   PS_META_REPLACE, "", chip->toFPA->y->coeff[i][j]);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "ERROR_X",  PS_META_REPLACE, "", chip->toFPA->x->coeffErr[i][j]);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "ERROR_Y",  PS_META_REPLACE, "", chip->toFPA->y->coeffErr[i][j]);
+                psMetadataAddU8 (row,    PS_LIST_TAIL, "MASK_X",   PS_META_REPLACE, "", chip->toFPA->x->coeffMask[i][j]);
+                psMetadataAddU8 (row,    PS_LIST_TAIL, "MASK_Y",   PS_META_REPLACE, "", chip->toFPA->y->coeffMask[i][j]);
+                psArrayAdd (model, 100, row);
+                psFree (row);
+            }
+        }
+        psFree (chiprule);
+        psFree (chipname);
+        psFree (region);
+    }
+
+    if (!psFitsWriteTable (file->fits, header, model, "CHIPS")) {
+        psError(PS_ERR_IO, false, "writing sky data\n");
+        psFree(model);
+        return false;
+    }
+
+    psFree (view);
+    psFree (model);
+    psFree (header);
+    return true;
+}
+
+// third layer is the focal plane
+bool pmAstromModelWriteFP (pmFPAfile *file) {
+
+    bool status;
+
+    psMetadata *header = psMetadataAlloc();
+    psMetadataAddStr(header, PS_LIST_TAIL, "COORD",    PS_META_REPLACE, "name of this layer",   "FOCAL_PLANE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "TANGENT_PLANE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "BOUNDARY", PS_META_REPLACE, "validity region",      "RECTANGLE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "TRANSFRM", PS_META_REPLACE, "mapping to parent",    "POLYNOMIAL");
+
+    psArray *model = psArrayAllocEmpty (1);
+
+    // XXX is this or the tpa region correct?
+    psRegion *region = pmAstromFPAExtent (file->fpa);
+
+    // rotate the toTPA to have 0.0 posangle
+    float posangle = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.POSANGLE");
+
+    // the to/from TPA transform currently has rotation of posangle; remove it & create the toTPA version
+    psPlaneTransform *fromTPA = psPlaneTransformRotate (NULL, file->fpa->fromTPA, -posangle);
+    psPlaneTransform *toTPA   = psPlaneTransformInvert(NULL, fromTPA, *region, 50);
+
+    for (int i = 0; i <= toTPA->x->nX; i++) {
+        for (int j = 0; j <= toTPA->x->nY; j++) {
+            psMetadata *row = psMetadataAlloc ();
+            psMetadataAddStr(row,    PS_LIST_TAIL, "SEGMENT",  PS_META_REPLACE, "name of this segment", "FOCAL_PLANE");
+            psMetadataAddStr(row,    PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "TANGENT_PLANE");
+            psMetadataAddF32(row,    PS_LIST_TAIL, "MINX",     PS_META_REPLACE, "range", region->x0);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "MAXX",     PS_META_REPLACE, "range", region->x1);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "MINY",     PS_META_REPLACE, "range", region->y0);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "MAXY",     PS_META_REPLACE, "range", region->y1);
+
+            psMetadataAddS32(row,    PS_LIST_TAIL, "XORDER",   PS_META_REPLACE, "", i);
+            psMetadataAddS32(row,    PS_LIST_TAIL, "YORDER",   PS_META_REPLACE, "", j);
+            psMetadataAddS32(row,    PS_LIST_TAIL, "NXORDER",  PS_META_REPLACE, "", toTPA->x->nX);
+            psMetadataAddS32(row,    PS_LIST_TAIL, "NYORDER",  PS_META_REPLACE, "", toTPA->x->nY);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "POLY_X",   PS_META_REPLACE, "", toTPA->x->coeff[i][j]);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "POLY_Y",   PS_META_REPLACE, "", toTPA->y->coeff[i][j]);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "ERROR_X",  PS_META_REPLACE, "", toTPA->x->coeffErr[i][j]);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "ERROR_Y",  PS_META_REPLACE, "", toTPA->y->coeffErr[i][j]);
+            psMetadataAddU8 (row,    PS_LIST_TAIL, "MASK_X",   PS_META_REPLACE, "", toTPA->x->coeffMask[i][j]);
+            psMetadataAddU8 (row,    PS_LIST_TAIL, "MASK_Y",   PS_META_REPLACE, "", toTPA->y->coeffMask[i][j]);
+
+            psArrayAdd (model, 100, row);
+            psFree (row);
+        }
+    }
+
+    if (!psFitsWriteTable (file->fits, header, model, "FP")) {
+        psError(PS_ERR_IO, false, "writing sky data\n");
+        psFree(model);
+        psFree (header);
+        psFree (region);
+        return false;
+    }
+
+    psFree (model);
+    psFree (header);
+    psFree (region);
+    return true;
+}
+
+// second layer is the tangent plane
+bool pmAstromModelWriteTP (pmFPAfile *file) {
+
+    bool status;
+
+    // get the boresite model parameters
+    float Xo = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.X0");
+    float Yo = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.Y0");
+    float RX = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.RX");
+    float RY = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.RY");
+    float To = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.T0");
+    float Po = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.P0");
+    float PosZero = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.POS_ZERO");  /// XXX be consistent with degrees v radians
+    char *refChip = psMetadataLookupStr (&status, file->fpa->concepts, "FPA.REF.CHIP");
+
+    psMetadata *header = psMetadataAlloc();
+    psMetadataAddStr(header, PS_LIST_TAIL, "COORD",    PS_META_REPLACE, "name of this layer",   "TANGENT_PLANE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "SKY");
+    psMetadataAddStr(header, PS_LIST_TAIL, "BOUNDARY", PS_META_REPLACE, "validity region",      "RECTANGLE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "TRANSFRM", PS_META_REPLACE, "mapping to parent",    "PROJECTION");
+
+    psArray *model = psArrayAllocEmpty (1);
+    psMetadata *row = psMetadataAlloc ();
+    psMetadataAddStr(row,    PS_LIST_TAIL, "SEGMENT",  PS_META_REPLACE, "name of this segment", "TANGENT_PLANE");
+    psMetadataAddStr(row,    PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "SKY");
+
+    psRegion *region = pmAstromFPAExtent (file->fpa);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "MINX",     PS_META_REPLACE, "range", region->x0);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "MAXX",     PS_META_REPLACE, "range", region->x1);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "MINY",     PS_META_REPLACE, "range", region->y0);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "MAXY",     PS_META_REPLACE, "range", region->y1);
+
+    // psMetadataAddF32(row,    PS_LIST_TAIL, "XREF",     PS_META_REPLACE, "", file->fpa->toSky->R  * PS_DEG_RAD);
+    // psMetadataAddF32(row,    PS_LIST_TAIL, "YREF",     PS_META_REPLACE, "", file->fpa->toSky->D  * PS_DEG_RAD);
+
+    psMetadataAddF32(row,    PS_LIST_TAIL, "XSCALE",   PS_META_REPLACE, "", file->fpa->toSky->Xs * PS_DEG_RAD);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "YSCALE",   PS_META_REPLACE, "", file->fpa->toSky->Ys * PS_DEG_RAD);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "BORE_X0",  PS_META_REPLACE, "boresite parameter", Xo);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "BORE_Y0",  PS_META_REPLACE, "boresite parameter", Yo);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "BORE_RX",  PS_META_REPLACE, "boresite parameter", RX);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "BORE_RY",  PS_META_REPLACE, "boresite parameter", RY);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "BORE_T0",  PS_META_REPLACE, "boresite parameter", To);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "BORE_P0",  PS_META_REPLACE, "boresite parameter", Po);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "POS_ZERO", PS_META_REPLACE, "boresite parameter", PosZero);
+    psMetadataAddStr(row,    PS_LIST_TAIL, "REF_CHIP", PS_META_REPLACE, "boresite parameter", refChip);
+
+    psArrayAdd (model, 100, row);
+    psFree (row);
+
+    if (!psFitsWriteTable (file->fits, header, model, "TP")) {
+        psError(PS_ERR_IO, false, "writing sky data\n");
+        psFree (region);
+        psFree (model);
+        psFree (header);
+        return false;
+    }
+
+    psFree (region);
+    psFree (model);
+    psFree (header);
+    return (true);
+}
+
+// first layer is the sky
+bool pmAstromModelWriteSky (pmFPAfile *file) {
+
+    psMetadata *header = psMetadataAlloc();
+    psMetadataAddStr(header, PS_LIST_TAIL, "COORD",    PS_META_REPLACE, "name of this layer",   "SKY");
+    psMetadataAddStr(header, PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "NONE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "BOUNDARY", PS_META_REPLACE, "validity region",      "NONE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "TRANSFRM", PS_META_REPLACE, "mapping to parent",    "NONE");
+
+    psArray *model = psArrayAllocEmpty (1);
+    psMetadata *row = psMetadataAlloc ();
+    psMetadataAddStr(row,    PS_LIST_TAIL, "SEGMENT",  PS_META_REPLACE, "name of this segment", "SKY");
+    psMetadataAddStr(row,    PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "NONE");
+
+    psArrayAdd (model, 100, row);
+    psFree (row);
+
+    if (!psFitsWriteTable (file->fits, header, model, "SKY")) {
+        psError(PS_ERR_IO, false, "writing sky data\n");
+        psFree(model);
+        return false;
+    }
+
+    psFree (model);
+    psFree (header);
+    return (true);
+}
+
+/********************* Read Data functions *****************************/
+
+bool pmAstromModelReadForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+    {
+
+        // write the full model in one pass: require the level to be FPA
+        if (view->chip != -1) {
+            psError(PS_ERR_IO, false, "Astrometry must be read at the FPA level");
+            return false;
+        }
+
+        if (!pmAstromModelReadFPA (file)) {
+            psError(PS_ERR_IO, false, "Failed to read Astrometry for fpa");
+            return false;
+        }
+        return true;
+    }
+
+// read out all chip-level Astrometry data for this FPA
+bool pmAstromModelReadFPA (pmFPAfile *file) {
+
+    if (!pmAstromModelReadPHU (file)) {
+        psError(PS_ERR_IO, false, "Failed to read PHU for Astrometry model");
+        return false;
+    }
+
+    if (!pmAstromModelReadChips (file)) {
+        psError(PS_ERR_IO, false, "Failed to read Astrometry for chips");
+        return false;
+    }
+
+    if (!pmAstromModelReadFP (file)) {
+        psError(PS_ERR_IO, false, "Failed to read Sky for Astrometry model");
+        return false;
+    }
+
+    // NOTE : TP must come after FP as it applies the POS, ROT boresite corrections to the
+    // transformation determined in FP
+    if (!pmAstromModelReadTP (file)) {
+        psError(PS_ERR_IO, false, "Failed to read Sky for Astrometry model");
+        return false;
+    }
+
+    if (!pmAstromModelReadSky (file)) {
+        psError(PS_ERR_IO, false, "Failed to read Sky for Astrometry model");
+        return false;
+    }
+
+    return true;
+}
+
+bool pmAstromModelReadPHU (pmFPAfile *file) {
+
+    fprintf (stderr, "not sure we need to read PHU\n");
+    return true;
+}
+
+int pmConceptsChipNumberFromName (pmFPA *fpa, char *name) {
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        if (!chip) continue;
+        char *thisone = psMetadataLookupStr (NULL, chip->concepts, "CHIP.NAME");
+        if (!thisone) continue;
+        if (!strcmp (name, thisone)) return (i);
+    }
+    return -1;
+}
+
+pmChip *pmConceptsChipFromName (pmFPA *fpa, char *name) {
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        if (!chip) continue;
+        char *thisone = psMetadataLookupStr (NULL, chip->concepts, "CHIP.NAME");
+        if (!thisone) continue;
+        if (!strcmp (name, thisone)) return (chip);
+    }
+    return NULL;
+}
+
+// first layer converts Chip to Focal Plane
+bool pmAstromModelReadChips (pmFPAfile *file) {
+
+    bool status;
+
+    // set FITS cursor
+    if (!psFitsMoveExtName (file->fits, "CHIPS")) {
+        psError(PS_ERR_IO, false, "missing CHIPS extension in astrometry model\n");
+        return false;
+    }
+
+    // free exising tranformations in prep for new alloc below
+    for (int i = 0; i < file->fpa->chips->n; i++) {
+        pmChip *chip = file->fpa->chips->data[i];
+        psFree (chip->toFPA);
+        chip->toFPA = NULL;
+    }
+
+    // XXX do I need anything from the header?
+    psMetadata *header = psFitsReadHeader(NULL, file->fits); // The FITS header
+    if (!header) psAbort("cannot read model header");
+
+    // load the full model in one shot
+    psArray *model = psFitsReadTable (file->fits);
+    if (!model) psAbort("cannot read model");
+    fprintf (stderr, "read %ld rows from FP\n", model->n);
+
+    // parse the model entries
+    for (int i = 0; i < model->n; i++) {
+        psMetadata *row = model->data[i];
+
+        // name of the chip for this row.
+        char *chipname = psMetadataLookupStr (&status, row, "SEGMENT");
+
+        // get chip from name
+        pmChip *chip = pmConceptsChipFromName (file->fpa, chipname);
+        REQUIRE (chip, "invalid chip name");
+
+        // define the toFPA transform if not already defined
+        int nX = psMetadataLookupS32(&status, row, "NXORDER"); REQUIRE (status, "missing NXORDER");
+        int nY = psMetadataLookupS32(&status, row, "NYORDER"); REQUIRE (status, "missing NYORDER");
+        if (chip->toFPA == NULL) {
+            chip->toFPA = psPlaneTransformAlloc(nX, nY);
+        } else {
+            REQUIRE (chip->toFPA->x->nX == nX, "mismatch in chip order");
+            REQUIRE (chip->toFPA->x->nY == nY, "mismatch in chip order");
+            REQUIRE (chip->toFPA->y->nX == nX, "mismatch in chip order");
+            REQUIRE (chip->toFPA->y->nY == nY, "mismatch in chip order");
+        }
+
+        int ix = psMetadataLookupS32(&status, row, "XORDER");  REQUIRE (status, "missing XORDER");
+        int iy = psMetadataLookupS32(&status, row, "YORDER");  REQUIRE (status, "missing YORDER");
+
+        // XXX do I need to use this or can i rely on the camera concepts?
+        // minX = psMetadataLookupF32(&status, row, "MINX");
+        // maxX = psMetadataLookupF32(&status, row, "MAXX");
+        // minY = psMetadataLookupF32(&status, row, "MINY");
+        // maxY = psMetadataLookupF32(&status, row, "MAXY");
+
+        // XXX need to include mask values
+        chip->toFPA->x->coeff[ix][iy]    = psMetadataLookupF32(&status, row, "POLY_X");
+        chip->toFPA->y->coeff[ix][iy]    = psMetadataLookupF32(&status, row, "POLY_Y");
+        chip->toFPA->x->coeffErr[ix][iy] = psMetadataLookupF32(&status, row, "ERROR_X");
+        chip->toFPA->y->coeffErr[ix][iy] = psMetadataLookupF32(&status, row, "ERROR_Y");
+        chip->toFPA->x->coeffMask[ix][iy] = psMetadataLookupU8(&status, row, "MASK_X");
+        chip->toFPA->y->coeffMask[ix][iy] = psMetadataLookupU8(&status, row, "MASK_Y");
+    }
+
+    // convert the toFPA transfomations to fromFPA transformations
+    for (int i = 0; i < file->fpa->chips->n; i++) {
+        pmChip *chip = file->fpa->chips->data[i];
+        if (!chip->toFPA) continue;
+        psRegion *region = pmChipPixels (chip);
+        psFree (chip->fromFPA);
+        chip->fromFPA = psPlaneTransformInvert(NULL, chip->toFPA, *region, 50);
+        psFree (region);
+    }
+
+    psFree (model);
+    psFree (header);
+    return true;
+}
+
+// second layer converts Focal Plane to Tangent Plane (unrotated)
+bool pmAstromModelReadFP (pmFPAfile *file) {
+
+    bool status;
+
+    if (!psFitsMoveExtName (file->fits, "FP")) {
+        psError(PS_ERR_IO, false, "missing FP extension in astrometry model\n");
+        return false;
+    }
+
+    psMetadata *header = psFitsReadHeader(NULL, file->fits); // The FITS header
+    if (!header) psAbort("cannot read model header");
+
+    // free the old
+    psFree (file->fpa->toTPA);
+    file->fpa->toTPA = NULL;
+
+    // read the complete model data at one shot
+    psArray *model = psFitsReadTable (file->fits);
+    fprintf (stderr, "read %ld rows from FP\n", model->n);
+
+    // parse the model
+    for (int i = 0; i < model->n; i++) {
+        psMetadata *row = model->data[i];
+
+        // there is only one transformation in this model; the order is defined in the header
+        int nX = psMetadataLookupS32(&status, row, "NXORDER"); REQUIRE (status, "missing NXORDER");
+        int nY = psMetadataLookupS32(&status, row, "NYORDER"); REQUIRE (status, "missing NYORDER");
+        if (file->fpa->toTPA == NULL) {
+            // allocate the new transformation
+            file->fpa->toTPA = psPlaneTransformAlloc(nX, nY);
+        } else {
+            REQUIRE (file->fpa->toTPA->x->nX == nX, "mismatch in chip order");
+            REQUIRE (file->fpa->toTPA->x->nY == nY, "mismatch in chip order");
+            REQUIRE (file->fpa->toTPA->y->nX == nX, "mismatch in chip order");
+            REQUIRE (file->fpa->toTPA->y->nY == nY, "mismatch in chip order");
+        }
+
+        int ix = psMetadataLookupS32(&status, row, "XORDER"); REQUIRE (status, "missing XORDER");
+        int iy = psMetadataLookupS32(&status, row, "YORDER"); REQUIRE (status, "missing YORDER");
+        file->fpa->toTPA->x->coeff[ix][iy]     = psMetadataLookupF32(&status, row, "POLY_X");  REQUIRE (status, "missing POLY_X");
+        file->fpa->toTPA->y->coeff[ix][iy]     = psMetadataLookupF32(&status, row, "POLY_Y");  REQUIRE (status, "missing POLY_Y");
+        file->fpa->toTPA->x->coeffErr[ix][iy]  = psMetadataLookupF32(&status, row, "ERROR_X"); REQUIRE (status, "missing ERROR_X");
+        file->fpa->toTPA->y->coeffErr[ix][iy]  = psMetadataLookupF32(&status, row, "ERROR_Y"); REQUIRE (status, "missing ERROR_Y");
+        file->fpa->toTPA->x->coeffMask[ix][iy] = psMetadataLookupU8 (&status, row, "MASK_X");  REQUIRE (status, "missing MASK_X");
+        file->fpa->toTPA->y->coeffMask[ix][iy] = psMetadataLookupU8 (&status, row, "MASK_Y");  REQUIRE (status, "missing MASK_Y");
+    }
+
+    psRegion *region = pmAstromFPAExtent (file->fpa);
+    psFree (file->fpa->fromTPA);
+    file->fpa->fromTPA = psPlaneTransformInvert(NULL, file->fpa->toTPA, *region, 50);
+
+    psFree (model);
+    psFree (header);
+    psFree (region);
+    return true;
+}
+
+# define TRANSFER(TO,FROM,NAME) { \
+    psMetadataItem *item = psMetadataLookup(FROM,NAME); \
+    if (!item) psAbort ("cannot find %s", NAME); \
+    psMetadataItem *newItem = psMetadataItemCopy(item); \
+    if (!psMetadataAddItem(TO, newItem, PS_LIST_TAIL, PS_META_REPLACE)) { \
+        psAbort ("cannot copy %s", NAME); \
+    } \
+    psFree (newItem); }
+
+// third layer applies boresite corrections and converts tangent plane to sky
+bool pmAstromModelReadTP (pmFPAfile *file) {
+
+    if (!psFitsMoveExtName (file->fits, "TP")) {
+        psError(PS_ERR_IO, false, "missing TP extension in astrometry model\n");
+        return false;
+    }
+
+    psMetadata *header = psFitsReadHeader(NULL, file->fits); // The FITS header
+    if (!header) psAbort("cannot read model header");
+
+    psArray *model = psFitsReadTable (file->fits);
+    fprintf (stderr, "read %ld rows from TP\n", model->n);
+    if (model->n != 1) psAbort("invalid number of rows in TP model (%ld)", model->n);
+
+    psMetadata *row = model->data[0];
+
+    // move needed items to the concepts
+    TRANSFER (file->fpa->concepts, row, "XSCALE");
+    TRANSFER (file->fpa->concepts, row, "XSCALE");
+    TRANSFER (file->fpa->concepts, row, "YSCALE");
+    TRANSFER (file->fpa->concepts, row, "BORE_X0");
+    TRANSFER (file->fpa->concepts, row, "BORE_Y0");
+    TRANSFER (file->fpa->concepts, row, "BORE_RX");
+    TRANSFER (file->fpa->concepts, row, "BORE_RY");
+    TRANSFER (file->fpa->concepts, row, "BORE_T0");
+    TRANSFER (file->fpa->concepts, row, "BORE_P0");
+    TRANSFER (file->fpa->concepts, row, "POS_ZERO");
+    TRANSFER (file->fpa->concepts, row, "REF_CHIP");
+
+    psFree (model);
+    psFree (header);
+    return (true);
+}
+
+// first layer is the sky
+bool pmAstromModelReadSky (pmFPAfile *file) {
+
+    if (!psFitsMoveExtName (file->fits, "SKY")) {
+        psError(PS_ERR_IO, false, "missing SKY extension in astrometry model\n");
+        return false;
+    }
+
+    psMetadata *header = psFitsReadHeader(NULL, file->fits); // The FITS header
+    if (!header) psAbort("cannot read model header");
+
+    psArray *model = psFitsReadTable (file->fits);
+    fprintf (stderr, "read %ld rows from SKY\n", model->n);
+    if (model->n != 1) psAbort("invalid number of rows in SKY model (%ld)", model->n);
+
+    // XXX not much information of interest in this table...
+
+    psFree (model);
+    psFree (header);
+    return (true);
+}
+
+// third layer applies boresite corrections and converts tangent plane to sky
+bool pmAstromModelSetTP (pmFPAfile *file, psMetadata *concepts) {
+
+    bool status;
+
+    // these externally supplied values are used to set the final transformation terms
+    double RA  = psMetadataLookupF64 (&status, concepts, "FPA.RA"); REQUIRE (status, "missing FPA.RA");
+    double DEC = psMetadataLookupF64 (&status, concepts, "FPA.DEC"); REQUIRE (status, "missing FPA.DEC");
+    double POS = PM_RAD_DEG * psMetadataLookupF64 (&status, concepts, "FPA.POSANGLE"); REQUIRE (status, "missing FPA.POSANGLE");
+    // double ROT = psMetadataLookupF64 (&status, concepts, "FPA.ROTANGLE"); REQUIRE (status, "missing FPA.ROTANGLE");
+
+    // get projection scale; center is supplied
+    float Xs = psMetadataLookupF32(&status, file->fpa->concepts, "XSCALE") * PM_RAD_DEG; REQUIRE (status, "missing XSCALE");
+    float Ys = psMetadataLookupF32(&status, file->fpa->concepts, "YSCALE") * PM_RAD_DEG; REQUIRE (status, "missing YSCALE");
+
+    // allocate a new toSky projection using the reported position
+    psFree (file->fpa->toSky);
+    file->fpa->toSky = psProjectionAlloc (RA, DEC, Xs, Ys, PS_PROJ_DIS);
+
+    // get boresite correction terms.  RX,RY,To,Po define an ellipse along which the boresite travels
+    double Xo = psMetadataLookupF32(&status, file->fpa->concepts, "BORE_X0"); REQUIRE (status, "missing ");
+    double Yo = psMetadataLookupF32(&status, file->fpa->concepts, "BORE_Y0"); REQUIRE (status, "missing ");
+    double RX = psMetadataLookupF32(&status, file->fpa->concepts, "BORE_RX"); REQUIRE (status, "missing ");
+    double RY = psMetadataLookupF32(&status, file->fpa->concepts, "BORE_RY"); REQUIRE (status, "missing ");
+    double To = psMetadataLookupF32(&status, file->fpa->concepts, "BORE_T0"); REQUIRE (status, "missing ");
+    double Po = psMetadataLookupF32(&status, file->fpa->concepts, "BORE_P0"); REQUIRE (status, "missing ");
+
+    // the true rotation of the instrument is POSANGLE - POS_ZERO
+    double PosZero = PM_RAD_DEG * psMetadataLookupF32(&status, file->fpa->concepts, "POS_ZERO"); REQUIRE (status, "missing POS_ZERO");
+    char *refChip  = psMetadataLookupStr(&status, file->fpa->concepts, "REF_CHIP"); REQUIRE (status, "missing REF_CHIP");
+
+    // apply true posangle = -(POS - POS_ZERO)
+    psPlaneTransform *fromTPA = psPlaneTransformRotate (NULL, file->fpa->fromTPA, (POS - PosZero));
+    psFree (file->fpa->fromTPA);
+    file->fpa->fromTPA = fromTPA;
+
+    psRegion *region = pmAstromFPAExtent (file->fpa);
+    psFree (file->fpa->toTPA);
+    file->fpa->toTPA = psPlaneTransformInvert(NULL, file->fpa->fromTPA, *region, 50);
+
+    // current position of the nominal boresite in refChip coordinates
+    double X = Xo + RX*cos(POS - To)*cos(Po) + RY*sin(POS - To)*sin(Po);
+    double Y = Yo + RY*sin(POS - To)*cos(Po) - RX*cos(POS - To)*sin(Po);
+
+    // get reference chip from name
+    pmChip *chip = pmConceptsChipFromName (file->fpa, refChip);
+    if (!chip) psAbort ("invalid chip name for reference");
+
+    psPlane *boreCH = psPlaneAlloc();
+    psPlane *boreFP = psPlaneAlloc();
+    psPlane *boreTP = psPlaneAlloc();
+    psSphere *boreSky = psSphereAlloc();
+
+    // find the true RA,DEC coord of the mirror of the reported boresite
+    boreCH->x = -X;
+    boreCH->y = -Y;
+    psPlaneTransformApply (boreFP, chip->toFPA, boreCH);
+    psPlaneTransformApply (boreTP, file->fpa->toTPA, boreFP);
+    psDeproject (boreSky, boreTP, file->fpa->toSky);
+
+    // modify the projection to account for offset between true and reported boresite
+    file->fpa->toSky->R = boreSky->r;
+    file->fpa->toSky->D = boreSky->d;
+
+    psTrace ("psModules.astrom", 5, "actual boresite coordinates: %lf, %lf\n", file->fpa->toSky->R*PS_DEG_RAD, file->fpa->toSky->D*PS_DEG_RAD);
+    psTrace ("psModules.astrom", 5, "plate scale used: %lf, %lf\n", file->fpa->toSky->Xs*PS_DEG_RAD*3600.0, file->fpa->toSky->Ys*PS_DEG_RAD*3600.0);
+
+    psFree (boreCH);
+    psFree (boreFP);
+    psFree (boreTP);
+    psFree (boreSky);
+
+    psFree (region);
+    return (true);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryModel.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryModel.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryModel.h	(revision 22158)
@@ -0,0 +1,43 @@
+/* @file  pmAstrometryModel.h
+ * @brief Astrometry model I/O functions
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-17 22:38:15 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_ASTROMETRY_MODEL_H
+#define PM_ASTROMETRY_MODEL_H
+
+/// @addtogroup Astrometry
+/// @{
+
+bool pmAstromModelCheckDataStatusForView (const pmFPAview *view, pmFPAfile *file);
+bool pmAstromModelCheckDataStatusForFPA (const pmFPA *fpa);
+bool pmAstromModelCheckDataStatusForChip (const pmChip *chip);
+
+bool pmAstromModelWriteForView (const pmFPAview *view, pmFPAfile *file, pmConfig *config);
+bool pmAstromModelWriteFPA (pmFPAfile *file, const pmFPA *fpa);
+bool pmAstromModelWritePHU (pmFPAfile *file, const pmFPA *fpa);
+bool pmAstromModelWriteSky (pmFPAfile *file);
+bool pmAstromModelWriteTP (pmFPAfile *file);
+bool pmAstromModelWriteFP (pmFPAfile *file);
+bool pmAstromModelWriteChips (pmFPAfile *file);
+
+int pmConceptsChipNumberFromName (pmFPA *fpa, char *name);
+pmChip *pmConceptsChipFromName (pmFPA *fpa, char *name);
+
+bool pmAstromModelReadForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmAstromModelReadFPA (pmFPAfile *file);
+bool pmAstromModelReadPHU (pmFPAfile *file);
+bool pmAstromModelReadChips (pmFPAfile *file);
+bool pmAstromModelReadFP (pmFPAfile *file);
+bool pmAstromModelReadTP (pmFPAfile *file);
+bool pmAstromModelReadSky (pmFPAfile *file);
+
+bool pmAstromModelSetTP (pmFPAfile *file, psMetadata *concepts);
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryObjects.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryObjects.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryObjects.c	(revision 22158)
@@ -0,0 +1,929 @@
+/** @file  pmAstrometryObjects.c
+*
+*  @brief This file defines the basic types for matching objects
+*  based on their astrometry.
+*
+*  @ingroup AstroImage
+*
+*  @author EAM, IfA
+*
+*  @version $Revision: 1.39 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2008-04-11 07:42:05 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/******************************************************************************/
+/*  INCLUDE FILES                                                             */
+/******************************************************************************/
+#include <stdio.h>
+#include <strings.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include <unistd.h>   // for unlink
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmAstrometryObjects.h"
+
+#define PM_ASTROMETRYOBJECTS_DEBUG 1
+/******************************************************************************
+pmAstromObjSortByMag(**a, **b): sort by mag (descending)
+
+Is this a private routine?
+Should we do the early asserts?
+ ******************************************************************************/
+int pmAstromObjSortByMag(
+    const void **a,
+    const void **b)
+{
+    if (PM_ASTROMETRYOBJECTS_DEBUG) {
+        PS_ASSERT_PTR_NON_NULL(a, 0);
+        PS_ASSERT_PTR_NON_NULL(*a, 0);
+        PS_ASSERT_PTR_NON_NULL(b, 0);
+        PS_ASSERT_PTR_NON_NULL(*b, 0);
+    }
+
+    pmAstromObj *A = *(pmAstromObj **)a;
+    pmAstromObj *B = *(pmAstromObj **)b;
+
+    psF32 diff = A->Mag - B->Mag;
+    if (diff > FLT_EPSILON) {
+        return (-1);
+    }
+
+    if (diff < FLT_EPSILON) {
+        return (+1);
+    }
+
+    return (0);
+}
+
+/************************************************************************************************************/
+/*
+ * Working routine to match two lists (where x[12] are sorted), given psVectors of their coordinates and the
+ * permutation used to sort in x
+ */
+static psArray *match_lists(const psVector *x1, const psVector *y1, // x/y coordinates of first set of objects
+                            const psVector *x2, const psVector *y2, // x/y   "    "    "  second "   "  "   "
+                            const psVector *sorted1, const psVector *sorted2, // mapping to original order
+                            const double RADIUS) // matching radius
+{
+    psArray *matches = psArrayAllocEmpty(x1->n);
+
+    const double RADIUS_SQR = PS_SQR(RADIUS);
+    double dX, dY, dR;
+
+    int jStart;
+    int i = 0, j = 0;
+    while (i < x1->n && j < x2->n) {
+        dX = x1->data.F64[i] - x2->data.F64[j];
+        if (dX <= -RADIUS) {
+            i++;
+            continue;
+        }
+        if (dX >= +RADIUS) {
+            j++;
+            continue;
+        }
+
+        jStart = j;
+        while (fabs(dX) < RADIUS && j < x2->n) {
+
+            dX = x1->data.F64[i] - x2->data.F64[j];
+            dY = y1->data.F64[i] - y2->data.F64[j];
+            dR = dX*dX + dY*dY;
+
+            if (dR > RADIUS_SQR) {
+                j++;
+                continue;
+            }
+
+            // got a match; add to output list
+            pmAstromMatch *match = pmAstromMatchAlloc (sorted1->data.S32[i], sorted2->data.S32[j]);
+            psArrayAdd (matches, 100, match);
+            psFree (match);
+
+            j++;
+        }
+        j = jStart;
+        i++;
+    }
+
+    return (matches);
+}
+
+/************************************************************************************************************/
+// macro to generate code for radius match function based on desired member
+// radius is in units of matching member (eg, pixels for chip, microns for FP, etc)
+#define MAKE_ASTROM_RADIUS(FUNC, MEMBER) \
+psArray *FUNC( \
+               const psArray *st1, \
+               const psArray *st2, \
+               double RADIUS) \
+{ \
+    PS_ASSERT_PTR_NON_NULL(st1, NULL); \
+    PS_ASSERT_PTR_NON_NULL(st2, NULL); \
+    \
+    assert(st1->n == 0 || pmAstromObjTest(st1->data[0])); \
+    assert(st2->n == 0 || pmAstromObjTest(st2->data[0])); \
+    \
+    /* sort both lists by X coord; st1 first */ \
+    psVector *x1 = psVectorAlloc(st1->n, PS_TYPE_F64); \
+    for (int i = 0; i < st1->n; i++) { \
+        x1->data.F64[i] = ((pmAstromObj *)st1->data[i])->MEMBER->x; \
+    } \
+    const psVector *sorted1 = psVectorSortIndex(NULL, x1); \
+    assert (sorted1->type.type == PS_TYPE_S32); \
+    \
+    psVector *y1 = psVectorAlloc(st1->n, PS_TYPE_F64); \
+    for (int i = 0; i < st1->n; i++) { \
+        x1->data.F64[i] = ((pmAstromObj *)st1->data[sorted1->data.S32[i]])->MEMBER->x; \
+        y1->data.F64[i] = ((pmAstromObj *)st1->data[sorted1->data.S32[i]])->MEMBER->y; \
+    } \
+    \
+    /* now st2 */ \
+    psVector *x2 = psVectorAlloc(st2->n, PS_TYPE_F64); \
+    for (int i = 0; i < st2->n; i++) { \
+        x2->data.F64[i] = ((pmAstromObj *)st2->data[i])->MEMBER->x; \
+    } \
+    const psVector *sorted2 = psVectorSortIndex(NULL, x2); \
+    \
+    psVector *y2 = psVectorAlloc(st2->n, PS_TYPE_F64); \
+    for (int i = 0; i < st2->n; i++) { \
+        x2->data.F64[i] = ((pmAstromObj *)st2->data[sorted2->data.S32[i]])->MEMBER->x; \
+        y2->data.F64[i] = ((pmAstromObj *)st2->data[sorted2->data.S32[i]])->MEMBER->y; \
+    } \
+    /* Do the work */ \
+    psArray *matches = match_lists(x1, y1, x2, y2, sorted1, sorted2, RADIUS); \
+    \
+    psFree((void *)sorted1); \
+    psFree((void *)sorted2); \
+    psFree(x1); \
+    psFree(y1); \
+    psFree(x2); \
+    psFree(y2); \
+    \
+    psLogMsg (__func__, 3, "radius match: %ld pairs (radius: %f)\n", matches->n, RADIUS); \
+    return (matches); \
+}
+
+/******************************************************************************/
+/*
+ * Match two lists of pmAstromObjs, based on the FP, TP, or chip coordinates
+ */
+MAKE_ASTROM_RADIUS(pmAstromRadiusMatch, FP)
+MAKE_ASTROM_RADIUS(pmAstromRadiusMatchFP, FP)
+MAKE_ASTROM_RADIUS(pmAstromRadiusMatchTP, TP)
+MAKE_ASTROM_RADIUS(pmAstromRadiusMatchChip, chip)
+
+/******************************************************************************
+pmAstromMatchFit(map, raw, ref, match, stats): take two matched star lists
+and fit a psPlaneTransform between them
+ ******************************************************************************/
+pmAstromFitResults *pmAstromMatchFit(
+    psPlaneTransform *map,
+    psArray *raw,
+    psArray *ref,
+    psArray *match,
+    psStats *stats)
+{
+    PS_ASSERT_PTR_NON_NULL(map, NULL);
+    PS_ASSERT_PTR_NON_NULL(raw, NULL);
+    PS_ASSERT_PTR_NON_NULL(ref, NULL);
+    PS_ASSERT_PTR_NON_NULL(match, NULL);
+    PS_ASSERT_PTR_NON_NULL(stats, NULL);
+
+    // reassign values for clip fit
+    // XXX set wt based on mag error?
+    psVector *X = psVectorAlloc (match->n, PS_TYPE_F32);
+    psVector *Y = psVectorAlloc (match->n, PS_TYPE_F32);
+    psVector *x = psVectorAlloc (match->n, PS_TYPE_F32);
+    psVector *y = psVectorAlloc (match->n, PS_TYPE_F32);
+    psVector *wt = psVectorAlloc (match->n, PS_TYPE_F32);
+    // take the matched stars, first fit
+    for (int i = 0; i < match->n; i++) {
+        pmAstromMatch *pair = match->data[i];
+        pmAstromObj *rawStar = raw->data[pair->raw];
+        pmAstromObj *refStar = ref->data[pair->ref];
+
+        X->data.F32[i] = rawStar->chip->x;
+        Y->data.F32[i] = rawStar->chip->y;
+
+        x->data.F32[i] = refStar->FP->x;
+        y->data.F32[i] = refStar->FP->y;
+
+        wt->data.F32[i] = 1.0;
+    }
+
+    // constant errors
+    psVector *mask = psVectorAlloc (match->n, PS_TYPE_U8);
+    psVectorInit (mask, 0);
+
+    // the stats options supplied are used to perform the clip fitting
+    pmAstromFitResults *results = pmAstromFitResultsAlloc();
+    results->xStats = psStatsAlloc (PS_STAT_NONE);
+    results->yStats = psStatsAlloc (PS_STAT_NONE);
+    *results->xStats = *stats;
+    *results->yStats = *stats;
+
+    int nIter = stats->clipIter;
+
+    results->xStats->clipIter = 1;
+    results->yStats->clipIter = 1;
+
+    // fit chip-to-FPA transformation
+    // we run 'clipIter' cycles clipping in each of x and y, with only one iteration each
+    // need to use the stats lookups functions to get the width and center
+    for (int i = 0; i < nIter; i++) {
+	if (!psVectorClipFitPolynomial2D (map->x, results->xStats, mask, 0xff, x, wt, X, Y)) {
+            psError(PS_ERR_UNKNOWN, false, "failure in clip-fitting for x\n");
+	    psFree (x);
+	    psFree (y);
+	    psFree (X);
+	    psFree (Y);
+	    psFree (wt);
+	    psFree (mask);
+
+	    return results;
+	}
+        psTrace ("psModules.astrom", 3, "x resid: %f +/- %f (%ld of %ld)\n", results->xStats->clippedMean, results->xStats->clippedStdev, results->xStats->clippedNvalues, x->n);
+
+        if (!psVectorClipFitPolynomial2D (map->y, results->yStats, mask, 0xff, y, wt, X, Y)) {
+            psError(PS_ERR_UNKNOWN, false, "failure in clip-fitting for y\n");
+	    psFree (x);
+	    psFree (y);
+	    psFree (X);
+	    psFree (Y);
+	    psFree (wt);
+	    psFree (mask);
+
+	    return results;
+	}
+        psTrace ("psModules.astrom", 3, "y resid: %f +/- %f (%ld of %ld)\n", results->yStats->clippedMean, results->yStats->clippedStdev, results->yStats->clippedNvalues, y->n);
+    }
+    results->xStats->clipIter = stats->clipIter;
+    results->yStats->clipIter = stats->clipIter;
+
+    psFree (x);
+    psFree (y);
+    psFree (X);
+    psFree (Y);
+    psFree (wt);
+    psFree (mask);
+
+    return (results);
+}
+
+
+/******************************************************************************
+pmAstromRotateObj(old, center, angle, angle): rotate & scale the focal-plane coordinates
+about the center coordinate angle specified in radians
+ ******************************************************************************/
+psArray *pmAstromRotateObj(
+    const psArray *old,
+    psPlane center,
+    double angle,
+    double scale)
+{
+    PS_ASSERT_PTR_NON_NULL(old, NULL);
+
+    double X, Y;
+    pmAstromObj *newObj;
+    const pmAstromObj *oldObj;
+
+    psArray *new = psArrayAlloc (old->n);
+    double cs = scale*cos(angle);
+    double sn = scale*sin(angle);
+    double xCenter = center.x;
+    double yCenter = center.y;
+
+    for (int i = 0; i < old->n; i++) {
+
+        oldObj = (pmAstromObj *)old->data[i];
+        newObj = pmAstromObjCopy (oldObj);
+
+        X = oldObj->FP->x - xCenter;
+        Y = oldObj->FP->y - yCenter;
+
+        newObj->FP->x = X*cs + Y*sn + xCenter;
+        newObj->FP->y = Y*cs - X*sn + yCenter;
+
+        new->data[i] = newObj;
+    }
+    return (new);
+}
+
+/******************************************************************************
+pmAstromStatsFree(stats)
+ ******************************************************************************/
+static void pmAstromStatsFree(pmAstromStats *stats)
+{
+    if (stats == NULL)
+        return;
+    return;
+}
+
+/******************************************************************************
+pmAstromStatsAlloc()
+ ******************************************************************************/
+pmAstromStats *pmAstromStatsAlloc(void)
+{
+    pmAstromStats *stats = psAlloc (sizeof(pmAstromStats));
+    psMemSetDeallocator (stats, (psFreeFunc)pmAstromStatsFree);
+
+    //    stats->center = {0, 0, 0, 0};
+    //    stats->offset = {0, 0, 0, 0};
+    stats->angle     = 0.0;
+    stats->scale     = 1.0;
+    stats->minMetric = 0.0;
+    stats->minVar    = 0.0;
+    stats->nMatch    = 0;
+    stats->nTest     = 0;
+    stats->nSigma    = 0;
+
+    return (stats);
+}
+
+/******************************************************************************
+pmAstromFitResultsFree(stats)
+ ******************************************************************************/
+static void pmAstromFitResultsFree(pmAstromFitResults *results)
+{
+    if (results == NULL)
+        return;
+    psFree (results->xStats);
+    psFree (results->yStats);
+    return;
+}
+
+/******************************************************************************
+pmAstromFitResultsAlloc()
+ ******************************************************************************/
+pmAstromFitResults *pmAstromFitResultsAlloc(void)
+{
+    pmAstromFitResults *results = psAlloc (sizeof(pmAstromFitResults));
+    psMemSetDeallocator (results, (psFreeFunc)pmAstromFitResultsFree);
+
+    results->xStats    = NULL;
+    results->yStats    = NULL;
+    results->nMatch    = 0;
+    results->nSigma    = 0;
+
+    return (results);
+}
+
+/******************************************************************************
+astromObjFree(obj)
+ ******************************************************************************/
+static void astromObjFree(pmAstromObj *obj)
+{
+    if (obj == NULL) {
+        return;
+    }
+
+    psFree(obj->pix);
+    psFree(obj->cell);
+    psFree(obj->chip);
+    psFree(obj->FP);
+    psFree(obj->TP);
+    psFree(obj->sky);
+
+    return;
+}
+
+
+/******************************************************************************
+pmAstromObjAlloc()
+ ******************************************************************************/
+pmAstromObj *pmAstromObjAlloc(void)
+{
+    pmAstromObj *obj = psAlloc (sizeof(pmAstromObj));
+    psMemSetDeallocator (obj, (psFreeFunc)astromObjFree);
+
+    obj->pix  = psPlaneAlloc();
+    obj->cell = psPlaneAlloc();
+    obj->chip = psPlaneAlloc();
+    obj->FP   = psPlaneAlloc();
+    obj->TP   = psPlaneAlloc();
+    obj->sky  = psSphereAlloc();
+    obj->Mag  = 0;
+    obj->dMag = 0;
+
+    return (obj);
+}
+
+bool pmAstromObjTest(const psPtr ptr)
+{
+    return (psMemGetDeallocator(ptr) == (psFreeFunc)astromObjFree);
+}
+
+
+
+/******************************************************************************
+pmAstromObjCopy(old)
+ ******************************************************************************/
+pmAstromObj *pmAstromObjCopy(const pmAstromObj *old)
+{
+    PS_ASSERT_PTR_NON_NULL(old, NULL);
+    pmAstromObj *obj = pmAstromObjAlloc();
+
+    *obj->pix  = *old->pix;
+    *obj->cell = *old->cell;
+    *obj->chip = *old->chip;
+    *obj->FP   = *old->FP;
+    *obj->TP   = *old->TP;
+    *obj->sky  = *old->sky;
+    obj->Mag   =  old->Mag;
+    obj->dMag  =  old->dMag;
+
+    return(obj);
+}
+
+
+/******************************************************************************
+ ******************************************************************************/
+static void pmAstromMatchFree (pmAstromMatch *match)
+{
+    if (match == NULL)
+        return;
+    return;
+}
+
+
+/******************************************************************************
+ ******************************************************************************/
+pmAstromMatch *pmAstromMatchAlloc(
+    int raw,
+    int ref)
+{
+    pmAstromMatch *match = psAlloc (sizeof(pmAstromMatch));
+    psMemSetDeallocator(match, (psFreeFunc) pmAstromMatchFree);
+
+    match->raw = raw;
+    match->ref = ref;
+
+    return (match);
+}
+
+
+static double maxOffpix;                // maximum allowed offset between lists, in raw pixels
+static double Scale;                    // grid pixel scale static
+double Offset;                          // deltas to pixels
+/******************************************************************************
+AstromGridBin(*dx, *dy, dX, dY): local function to convert x,y coords to grid
+bins it requires the globals defined above.
+
+ ******************************************************************************/
+static bool AstromGridBin(
+    int *dx,
+    int *dy,
+    double dX,
+    double dY)
+{
+    if (PM_ASTROMETRYOBJECTS_DEBUG) {
+        PS_ASSERT_PTR_NON_NULL(dx, false);
+        PS_ASSERT_PTR_NON_NULL(dy, false);
+    }
+
+    if (!isfinite(dX)) return false;
+    if (!isfinite(dY)) return false;
+
+    if (fabs(dX) > maxOffpix) return false;
+    if (fabs(dY) > maxOffpix) return false;
+
+    *dx = dX / Scale + Offset;
+    *dy = dY / Scale + Offset;
+    return true;
+}
+
+
+/******************************************************************************
+pmAstromGridAngle(raw, ref, config): match the two lists using the binned
+delta-delta max.
+ ******************************************************************************/
+pmAstromStats *pmAstromGridAngle(
+    const psArray *raw,
+    const psArray *ref,
+    const psMetadata *config)
+{
+    PS_ASSERT_PTR_NON_NULL(raw, NULL);
+    PS_ASSERT_PTR_NON_NULL(ref, NULL);
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    bool status;
+    int nPix;       // size of matching grid
+    int nPixHalf;   // half-size of matching grid
+    double dX, dY;  // offset between a possible matched pair
+    int iX, iY;     // corresponding grid bin
+
+    const pmAstromObj *ob1, *ob2; // short-cut pointers to the objects
+
+    pmAstromStats *stats = pmAstromStatsAlloc();    // output match statistics
+
+    // max allowed offset in either X or Y directions
+    double gridOffset = psMetadataLookupF32 (&status, config, "PSASTRO.GRID.OFFSET");
+
+    // sampling scale of the grid
+    double gridScale  = psMetadataLookupF32 (&status, config, "PSASTRO.GRID.SCALE");
+
+    // set the static scaling factors
+    nPixHalf = (int)(gridOffset / gridScale + 0.5);  // half-grid
+    nPix = 2*nPixHalf + 1;                           // full grid width
+
+    // these are globals used by p_pmAstromGridBin
+    maxOffpix = gridScale * (nPixHalf + 0.5);            // max offset from true center
+    Offset    = maxOffpix / gridScale;
+    Scale     = gridScale;
+
+    // images used as accumulators for the loop below
+    psImage *gridNP = psImageAlloc (nPix, nPix, PS_TYPE_U32);
+    psImage *gridDX = psImageAlloc (nPix, nPix, PS_TYPE_F32);
+    psImage *gridDY = psImageAlloc (nPix, nPix, PS_TYPE_F32);
+    psImage *gridD2 = psImageAlloc (nPix, nPix, PS_TYPE_F32);
+    psImageInit (gridNP, 0);
+    psImageInit (gridDX, 0);
+    psImageInit (gridDY, 0);
+    psImageInit (gridD2, 0);
+
+    // short-cut names for grid images
+    psU32 **NP = gridNP->data.U32;
+    psF32 **DX = gridDX->data.F32;
+    psF32 **DY = gridDY->data.F32;
+    psF32 **D2 = gridD2->data.F32;
+
+    // accumulate grids for focal plane (L,M) matches
+    for (int i = 0; i < raw->n; i++) {
+        ob1 = (pmAstromObj *)raw->data[i];
+        for (int j = 0; j < ref->n; j++) {
+            ob2 = (pmAstromObj *)ref->data[j];
+            dX = ob1->FP->x - ob2->FP->x;
+            dY = ob1->FP->y - ob2->FP->y;
+
+            // fprintf (f, "dX,dY: %8.2f %8.2f : %8.2f %8.2f : %8.2f %8.2f\n", dX, dY, ob1->FP->x, ob2->FP->x, ob1->FP->y, ob2->FP->y);
+            // find bin coordinates for this delta-delta
+            if (!AstromGridBin (&iX, &iY, dX, dY)) {
+                continue; // matched pair is too far offset
+            }
+
+            // accumulate bin stats
+            NP[iY][iX] ++;
+            DX[iY][iX] += dX;
+            DY[iY][iX] += dY;
+            D2[iY][iX] += PS_SQR(dX) + PS_SQR(dY);
+        }
+    }
+
+    // now assess the grid images
+    {
+        double minMetric = 1e10;
+        double minVar = 1e10;
+        int minX = -1;
+        int minY = -1;
+        double metric, var;
+
+        // find the max pixel
+        psStats *imStats = psStatsAlloc (PS_STAT_MAX | PS_STAT_MAX | PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
+        if (!psImageStats(imStats, gridNP, NULL, 0)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to get image statistics.\n");
+            psFree(imStats);
+            psFree(gridNP);
+            psFree(gridDX);
+            psFree(gridDY);
+            psFree(gridD2);
+            psFree(stats);
+            return NULL;
+        }
+
+        # if 0
+        char line[16];
+        psFits *fits = psFitsOpen ("grid.image.fits", "w");
+        psFitsWriteImage (fits, NULL, gridNP, 0, NULL);
+        psFitsClose (fits);
+        fprintf (stderr, "wrote grid image, press return to continue\n");
+        fgets (line, 15, stdin);
+        # endif
+
+        // only check bins with at least 1/2 of max bin
+        // XXX requiring at least 3 matches in bin
+        int minNpts = PS_MAX (0.5*imStats->max, 5);
+        psTrace("psModule.astrom", 5, "minNpts: %d, min: %d, max: %d, median: %f, stdev: %f", minNpts, (int)(imStats->min), (int)(imStats->max), imStats->sampleMedian, imStats->sampleStdev);
+
+        // find the 'best' bin
+        for (int j = 0; j < gridNP->numRows; j++) {
+            for (int i = 0; i < gridNP->numCols; i++) {
+                if (NP[j][i] < minNpts) continue;
+
+                // this metric emphasizes a narrow peak with lots of sources over one with few.
+                var = fabs((D2[j][i]/NP[j][i]) - PS_SQR(DX[j][i]/NP[j][i]) - PS_SQR(DY[j][i]/NP[j][i]));
+                metric = var / PS_SQR(NP[j][i]) / PS_SQR(NP[j][i]);
+
+                // fprintf (stderr, "try : %f %f (%d pts, %f var, %f met)\n", DX[j][i]/NP[j][i], DY[j][i]/NP[j][i], NP[j][i], var, metric);
+
+                if (metric < minMetric) {
+                    minMetric = metric;
+                    minVar    = var;
+                    minX      = i;
+                    minY      = j;
+                }
+            }
+        }
+
+        // convert the bin to delta-delta
+        if ((minX < 0) || (minY < 0))
+        {
+            // no valid matches found
+            stats->offset.x   = 0;
+            stats->offset.y   = 0;
+            stats->minMetric  = minMetric;
+            stats->minVar     = minVar;
+            stats->nMatch     = 0;
+        } else
+        {
+            stats->offset.x  = DX[minY][minX] / NP[minY][minX];
+            stats->offset.y  = DY[minY][minX] / NP[minY][minX];
+            stats->minMetric = minMetric;
+            stats->minVar    = minVar;
+            stats->nMatch    = NP[minY][minX];
+        }
+
+        psFree (imStats);
+        // XXX EAM : This routine, and pmAstromGridMatch, need to handle failure cases better
+    }
+
+    // sort the NP values and choose
+    psVector *listNP = psVectorAlloc (nPix*nPix, PS_TYPE_U32);
+    int n = 0;
+    for (int i = 0; i < nPix; i++) {
+        for (int j = 0; j < nPix; j++) {
+            listNP->data.U32[n] = gridNP->data.U32[j][i];
+            n++;
+        }
+    }
+    psVector *sort = psVectorSort (NULL, listNP);
+    stats->nTest = sort->data.U32[sort->n - 5];
+    stats->nSigma = (stats->nMatch - stats->nTest) / sqrt(stats->nTest);
+    // XXX this needs a better analysis of the image histogram..
+    // fprintf (stderr, "sigma: nMatch: %d, nTest: %d, nTen: %d\n", stats->nMatch, stats->nTest, sort->data.U32[sort->n - 10]);
+
+    psFree (sort);
+    psFree (listNP);
+    psFree (gridNP);
+    psFree (gridDX);
+    psFree (gridDY);
+    psFree (gridD2);
+    return (stats);
+}
+
+
+
+/******************************************************************************
+pmAstromGridMatch(*raw, *ref, *config): match two star lists.
+ ******************************************************************************/
+
+pmAstromStats *pmAstromGridMatch(const psArray *raw,
+                                 const psArray *ref,
+                                 const psMetadata *config)
+{
+    PS_ASSERT_PTR_NON_NULL(raw, NULL);
+    PS_ASSERT_PTR_NON_NULL(ref, NULL);
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    bool status;
+    double xMin, xMax, yMin, yMax;
+    const pmAstromObj *obj;
+    psArray *rot;
+
+    pmAstromStats *minStat = pmAstromStatsAlloc ();
+    pmAstromStats *newStat = NULL;
+
+    psPlane center;
+
+    // find center of the raw field (focal-plane coords)
+    xMin = yMin = +1e10;
+    xMax = yMax = -1e10;
+    for (int i = 0; i < raw->n; i++) {
+        obj = (pmAstromObj *)raw->data[i];
+        xMin = PS_MIN (obj->FP->x, xMin);
+        xMax = PS_MAX (obj->FP->x, xMax);
+        yMin = PS_MIN (obj->FP->y, yMin);
+        yMax = PS_MAX (obj->FP->y, yMax);
+    }
+    center.x = 0.5*(xMin + xMax);
+    center.y = 0.5*(yMin + yMax);
+
+    double minScale = psMetadataLookupF32 (&status, config, "PSASTRO.GRID.MIN.SCALE");
+    double maxScale = psMetadataLookupF32 (&status, config, "PSASTRO.GRID.MAX.SCALE");
+    double delScale = psMetadataLookupF32 (&status, config, "PSASTRO.GRID.DEL.SCALE");
+
+    double minAngle = PS_RAD_DEG*psMetadataLookupF32 (&status, config, "PSASTRO.GRID.MIN.ANGLE");
+    double maxAngle = PS_RAD_DEG*psMetadataLookupF32 (&status, config, "PSASTRO.GRID.MAX.ANGLE");
+    double delAngle = PS_RAD_DEG*psMetadataLookupF32 (&status, config, "PSASTRO.GRID.DEL.ANGLE");
+    double minSigma = psMetadataLookupF32 (&status, config, "PSASTRO.GRID.MIN.SIGMA");
+
+    minStat->minMetric = 1e10;
+    for (double scale = minScale; scale <= maxScale; scale += delScale) {
+	for (double angle = minAngle; angle <= maxAngle; angle += delAngle) {
+	    rot = pmAstromRotateObj (raw, center, angle, scale);
+
+# if 0
+	    FILE *f1 = fopen ("raw.dat", "w");
+	    for (int i = 0; i < rot->n; i++) {
+		pmAstromObj *obj = rot->data[i];
+		fprintf (f1, "%8.2f %8.2f   %6.2f\n", obj->FP->x, obj->FP->y, obj->Mag);
+	    }
+	    fclose (f1);
+	    FILE *f2 = fopen ("ref.dat", "w");
+	    for (int i = 0; i < ref->n; i++) {
+		pmAstromObj *obj = ref->data[i];
+		fprintf (f2, "%8.2f %8.2f   %6.2f\n", obj->FP->x, obj->FP->y, obj->Mag);
+	    }
+	    fclose (f2);
+	    fprintf (stderr, "type return");
+	    char c;
+	    fscanf (stdin, "%c", &c);
+# endif
+
+	    newStat = pmAstromGridAngle (rot, ref, config);
+	    newStat->angle  = angle;
+	    newStat->scale  = scale;
+	    newStat->center = center;
+
+	    if (isfinite(newStat->minMetric) && (newStat->minMetric > 0.0) && (newStat->minMetric < minStat->minMetric)) {
+		*minStat = *newStat;
+		psLogMsg ("psModule.astrom", 4, "grid test - offset: %7.2f,%7.2f @ %6.1f deg x %7.3f (%4d pts, %5.1f sig, %5.1f var, %6.3f log metric) *",
+			  minStat->offset.x, minStat->offset.y, PS_DEG_RAD*minStat->angle, minStat->scale, minStat->nMatch, minStat->nSigma, minStat->minVar, log10(minStat->minMetric));
+	    } else {
+		psLogMsg ("psModule.astrom", 4, "grid test - offset: %7.2f,%7.2f @ %6.1f deg x %7.3f (%4d pts, %5.1f sig, %5.1f var, %6.3f log metric)",
+			  newStat->offset.x, newStat->offset.y, PS_DEG_RAD*newStat->angle, newStat->scale, newStat->nMatch, newStat->nSigma, newStat->minVar, log10(newStat->minMetric));
+
+	    }
+	    psFree (newStat);
+	    psFree (rot);
+	}
+    }
+    psLogMsg ("psModule.astrom.grid.match", 4, "grid best - offset: %7.2f,%7.2f @ %6.1f deg x %7.3f (%4d pts, %5.1f sig, %5.1f var, %6.3f log metric)",
+              minStat->offset.x, minStat->offset.y, PS_DEG_RAD*minStat->angle, minStat->scale, minStat->nMatch, minStat->nSigma, minStat->minVar, log10(minStat->minMetric));
+
+    // I need to decide if a solution is likely to be a good solution or just a mis-match
+    // one posibility: how significant is the peak relative to the 4th or 5th most significant pixel?
+
+    if (minStat->nSigma < minSigma) {
+        psError(PS_ERR_UNKNOWN, true, "Failed to find a valid match (%f sigma for best)", minStat->nSigma);
+        psFree (minStat);
+        return NULL;
+    }
+    return (minStat);
+}
+
+/******************************************************************************
+pmAstromGridTweak(*raw, *ref, *recipe, stats): improve match for two star lists.
+ ******************************************************************************/
+pmAstromStats *pmAstromGridTweak(
+    psArray *raw,
+    psArray *ref,
+    psMetadata *recipe,
+    pmAstromStats *stats)
+{
+    bool status;
+    pmAstromObj *ob1, *ob2;  // short-cut pointers to the objects
+    double dX, dY;   // offset between a possible matched pair
+    psArray *rot;
+    int nBin, xBin, yBin;
+
+    rot = pmAstromRotateObj (raw, stats->center, stats->angle, stats->scale);
+
+    // sampling scale of the grid
+    double tweakScale  = psMetadataLookupF32 (&status, recipe, "PSASTRO.TWEAK.SCALE");
+    double tweakRange  = psMetadataLookupF32 (&status, recipe, "PSASTRO.TWEAK.RANGE");
+    double tweakSmooth = psMetadataLookupF32 (&status, recipe, "PSASTRO.TWEAK.SMOOTH");
+    double tweakNsigma = psMetadataLookupF32 (&status, recipe, "PSASTRO.TWEAK.NSIGMA");
+
+    nBin = 2*tweakRange / tweakScale;
+    psVector *xHist = psVectorAlloc (nBin, PS_TYPE_F32);
+    psVector *yHist = psVectorAlloc (nBin, PS_TYPE_F32);
+    psVectorInit (xHist, 0);
+    psVectorInit (yHist, 0);
+
+    // accumulate grids for focal plane (L,M) matches
+    for (int i = 0; i < rot->n; i++) {
+        ob1 = (pmAstromObj *)rot->data[i];
+        for (int j = 0; j < ref->n; j++) {
+            ob2 = (pmAstromObj *)ref->data[j];
+            dX = ob1->FP->x - ob2->FP->x - stats->offset.x;
+            dY = ob1->FP->y - ob2->FP->y - stats->offset.y;
+
+            xBin = (dX + tweakRange) / tweakScale;
+            yBin = (dY + tweakRange) / tweakScale;
+
+            if (xBin < 0)
+                continue;
+            if (yBin < 0)
+                continue;
+            if (xBin >= nBin)
+                continue;
+            if (yBin >= nBin)
+                continue;
+
+            xHist->data.F32[xBin] += 1.0;
+            yHist->data.F32[yBin] += 1.0;
+        }
+    }
+
+    // smooth histgram vector with gaussian of 1sigma = radius
+    psVector *xHistNew = psVectorSmooth(NULL, xHist, tweakSmooth, tweakNsigma);
+    psVector *yHistNew = psVectorSmooth(NULL, yHist, tweakSmooth, tweakNsigma);
+    psFree(xHist);
+    psFree(yHist);
+    xHist = xHistNew;
+    yHist = yHistNew;
+
+    // select peak in x and in y
+    xBin = yBin = 0;
+    double xMax = 0;
+    double yMax = 0;
+    for (int i = 0; i < nBin; i++) {
+        if (xHist->data.F32[i] > xMax) {
+            xBin = i;
+            xMax = xHist->data.F32[i];
+        }
+        if (yHist->data.F32[i] > yMax) {
+            yBin = i;
+            yMax = yHist->data.F32[i];
+        }
+    }
+    double xPeak = xBin*tweakScale - tweakRange;
+    double yPeak = yBin*tweakScale - tweakRange;
+    psLogMsg (__func__, 3, "tweak peak by %f,%f\n", xPeak, yPeak);
+
+    // adjust offset by peak center
+    pmAstromStats *tweak = pmAstromStatsAlloc();
+    *tweak = *stats;
+    tweak->offset.x += xPeak;
+    tweak->offset.y += yPeak;
+
+    psFree (rot);
+    psFree (xHist);
+    psFree (yHist);
+
+    return tweak;
+}
+
+/******************************************************************************
+pmAstromGridApply(*map, stat): apply the measured FPA offset and rotation
+(stat) to the fpa astrom structures.
+ ******************************************************************************/
+psPlaneTransform *pmAstromGridApply(
+    psPlaneTransform *map,
+    pmAstromStats *stat)
+{
+    PS_ASSERT_PTR_NON_NULL(map, NULL);
+    PS_ASSERT_POLY_NON_NULL(map->x, NULL);
+    PS_ASSERT_POLY_NON_NULL(map->y, NULL);
+
+    double cs = stat->scale * cos (stat->angle);
+    double sn = stat->scale * sin (stat->angle);
+
+    double dx = (map->x->coeff[0][0] - stat->center.x);
+    double dy = (map->y->coeff[0][0] - stat->center.y);
+
+    // new offset
+    map->x->coeff[0][0] =  cs*dx + sn*dy - stat->offset.x + stat->center.x;
+    map->y->coeff[0][0] = -sn*dx + cs*dy - stat->offset.y + stat->center.y;
+
+    // original rotation matrix
+    double pc1_1 = map->x->coeff[1][0];
+    double pc1_2 = map->x->coeff[0][1];
+    double pc2_1 = map->y->coeff[1][0];
+    double pc2_2 = map->y->coeff[0][1];
+
+    // new rotation matrix
+    map->x->coeff[1][0] = +cs*pc1_1 + sn*pc2_1;
+    map->x->coeff[0][1] = +cs*pc1_2 + sn*pc2_2;
+    map->y->coeff[1][0] = -sn*pc1_1 + cs*pc2_1;
+    map->y->coeff[0][1] = -sn*pc1_2 + cs*pc2_2;
+
+    return (map);
+}
+
+/* Illustration of the grid bins
+   dX        bin
+   -35:-25 -> 0     bin = dX / Scale + Offset
+   -25:-15 -> 1     Scale = 10
+   -15:-05 -> 2     Offset = 3.5
+   -05:+05 -> 3     nPix = 3 (maxOffset = 35 = (nPix + 0.5)*dXix
+   +05:+15 -> 4     dPix = 10
+   +15:+25 -> 5
+   +25:+35 -> 6
+
+   maxOffsetRequest = 30
+   nPix = (int) (maxOffset / dPix + 0.5);
+   maxOffset = (nPix + 0.5)*Scale;
+*/
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryObjects.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryObjects.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryObjects.h	(revision 22158)
@@ -0,0 +1,348 @@
+/* @file  pmAstrometryObjects.h
+ * @brief basic matching of objects based on their astrometry.
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.17 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-21 07:02:55 $
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PM_ASTROMETRY_OBJECTS_H
+#define PM_ASTROMETRY_OBJECTS_H
+
+/// @addtogroup Astrometry
+/// @{
+
+/*
+ *
+ * This structure specifies the coordinate of the detection in each of the
+ * four necessary coordinate frames: pix defines the position in the psReadout
+ * frame, FP defines the position in the Focal Plane frame, TP defines the
+ * position in the Tangent Plane frame, sky defines the position on the Celestial
+ * Sphere. In addition, a measurement of the brightness is given by the element
+ * Mag. Such a data structure should be used for both the raw and the reference
+ * stars. In astrometric processing, the raw detections will be projected using
+ * the best available information to each of these coordinate frames from the pix
+ * coordinates, while the reference detections will be projected to the other
+ * frames from the sky coordinates.
+ *
+ * XXX: There are more members here than in the SDRS.
+ *
+ */
+typedef struct
+{
+    psPlane *pix;   ///< the position in the pmReadout frame
+    psPlane *cell;   ///< the position in the pmCell frame
+    psPlane *chip;   ///< the position in the pmChip frame
+    psPlane *FP;   ///< the position in the pmFPA frame
+    psPlane *TP;   ///< the position in the tangent plane
+    psSphere *sky;        ///< the position on the Celestial Sphere.
+    double Mag;                         ///< object magnitude XXX what filter?
+    double dMag;                        ///< error on object magnitude
+}
+pmAstromObj;
+
+/*
+ *
+ * The pmAstromMatch structure defines the cross-correlation between two
+ * arrays. A single such data item specifies that item number pmAstromMatch.idx1
+ * in the first list corresponds to pmAstromMatch.idx2 in the second list.
+ *
+ */
+typedef struct
+{
+    int raw;                             ///< What is this?
+    int ref;                             ///< What is this?
+}
+pmAstromMatch;
+
+
+/*
+ *
+ * XXX: Not in SDRS.
+ *
+ */
+typedef struct
+{
+    psPlane center;                     ///<
+    psPlane offset;                     ///<
+    double  scale;                      ///<
+    double  angle;                      ///<
+    double  minMetric;                  ///<
+    double  minVar;                     ///<
+    int     nMatch;                     ///<
+    int     nTest;                      ///<
+    double  nSigma;                     ///<
+}
+pmAstromStats;
+
+typedef struct
+{
+    psStats *xStats;
+    psStats *yStats;
+    int     nMatch;                     ///<
+    double  nSigma;                     ///<
+}
+pmAstromFitResults;
+
+/*
+ *
+ * If the two sets of coordinates are expected to agree very well (ie, the current best-guess
+ * astrometric solution is quite close to reality), perform a match based on a simple radius
+ * test. The following functions accept two sets of pmAstromObj sources and determines the
+ * matched objects between the two lists using coordinates of the desired depth (depending on
+ * the function). The input and reference sources must have been projected to the desired depth
+ * (eg, for Focal Plane coordinates, to pmAstromObj.FP).  The specified radius must be in the
+ * units for the matching depth (chip: pixels, focal plane: microns, tangent plane:
+ * degrees. The output consists an array of pmAstromMatch values, defined above.
+ *
+ */
+psArray *pmAstromRadiusMatch(
+    const psArray *st1,
+    const psArray *st2,
+    double RADIUS
+);
+psArray *pmAstromRadiusMatchFP(
+    const psArray *st1,
+    const psArray *st2,
+    double RADIUS
+);
+psArray *pmAstromRadiusMatchTP(
+    const psArray *st1,
+    const psArray *st2,
+    double RADIUS
+);
+psArray *pmAstromRadiusMatchChip(
+    const psArray *st1,
+    const psArray *st2,
+    double RADIUS
+);
+
+
+pmAstromStats *pmAstromStatsAlloc(void);
+
+/*
+ *
+ * This function accepts an array of pmAstromObj objects and rotates them by
+ * the given angle about the given center coordinate pCenter,qCenter in the Focal
+ * Plane Array coordinates.
+ *
+ * XXX: This differs from the SDRS
+ *
+ */
+/* SDRS
+psArray *pmAstromRotateObj(
+    psArray *old,
+    double angle,
+    double pCenter,
+    double qCenter
+);
+*/
+psArray *pmAstromRotateObj(
+    const psArray *old,
+    psPlane center,
+    double angle,
+    double scale
+);
+
+
+/*
+ *
+ * If the two sets of coordinates are not known to agree well, but the
+ * relative scale and approximate relative rotation is known, then a much faster
+ * match can be found using pair-pair displacements. In such a case, the two
+ * lists can be considered as having the same coordinate system, with an unknown
+ * relative displacement. In this algorithm, all possible pair-wise differences
+ * between the source positions in the two lists are constructed and accumulated
+ * in a grid of possible offset values. The resulting grid is searched for a
+ * cluster representing the offset between the two input lists. This algorithm
+ * can only tolerate a small error in the relative scale or the relative rotation
+ * of the two coordinate lists. However, this process is naturally O(N2), and is
+ * thus advantageous over triangle matching in some circumstances. This process
+ * can be extended to allow a larger uncertainty in the relative rotation by
+ * allowing the procedure to scan over a range of rotations. We define the
+ * following function to apply this matching algorithm:
+ *
+ * XXX: In the SDRS, this function is a pointer.
+ *
+ */
+pmAstromStats *pmAstromGridMatch(
+    const psArray *st1,
+    const psArray *st2,
+    const psMetadata *config
+);
+
+/******************************************************************************
+pmAstromGridTweak(*raw, *ref, *recipe, stats): improve match for two star lists.
+ ******************************************************************************/
+pmAstromStats *pmAstromGridTweak(
+    psArray *raw,
+    psArray *ref,
+    psMetadata *recipe,
+    pmAstromStats *stats);
+
+/*
+ *
+ * The result of a pmAstromGridMatch may be used to modify the astrometry
+ * transformation information for a pmFPA image hierarchy structure. The result
+ * of pmAstromGridMatch defines the adjustments which should be made to the
+ * reference coordinate of the projection (pmFPA.projection.R,D) and the
+ * effective rotation of the Focal Plane.  The rotation implies modification of
+ * the linear terms of the pmFPA.toTangentPlane transformation. These two
+ * adjustments are made using the function:
+ *
+ * XXX: This function name is different in the SDRS.
+ *
+ */
+psPlaneTransform *pmAstromGridApply(
+    psPlaneTransform *map,
+    pmAstromStats *stat
+);
+
+
+/*
+ *
+ * This function is identical to pmAstromGridMatch, but is valid for only a
+ * single relative rotation. The input config information need not contain any of
+ * the GRID.*.ANGLE entries (they will be ignored).
+ *
+ * XXX: This function name is different in the SDRS.
+ *
+ */
+/* in pmAstromGrid.c */
+pmAstromStats *pmAstromGridAngle(
+    const psArray *st1,
+    const psArray *st2,
+    const psMetadata *config);
+
+
+
+/*
+ *
+ * This function accepts the raw and reference source lists and the list of
+ * matched entries. It uses the matched list to determine a polynomial
+ * transformation between the two coordinate systems. The fitting uses clipping
+ * to exclude outliers, likely representing poor matches. The config element must
+ * contain the information ASTROM.NSIGMA (specifying the number of sigma used in
+ * the clipping) and ASTROM.NCLIP (specifying the number of clipping iterations
+ * must be performed). The config element must also specify the order of the
+ * polynomial fit (keyword: ASTROM.ORDER). The result of this fit is a set of
+ * modifications of the components of the pmFPA.toTangentPlane transformation,
+ * and the modifications of the reference coordinate of the projection
+ * (pmFPA.projection.R,D) and the projection scale (pmFPA.projection.Xs,Ys). The
+ * modifications to pmFPA.toTangentPlane incorporate the rotation component of
+ * the linear terms and the higher-order terms of the polynomial fits.
+ *
+ * XXX: No prototype code.
+ *
+ */
+bool pmAstromFitFPA(
+    pmFPA *fpa,
+    psArray *st1,
+    psArray *st2,
+    psArray *match,
+    psMetadata *config
+);
+
+
+
+/*
+ *
+ * This function accepts the raw and reference source lists for a single chip
+ * and the list of matched entries. It uses the matched list to determine a
+ * polynomial transformation between the two coordinate systems. The fitting
+ * uses clipping to exclude outliers, likely representing poor matches. The
+ * config element must contain the information ASTROM.NSIGMA
+ *(specifying the number of sigma used in the clipping) and ASTROM.NCLIP
+ *(specifying the number of clipping iterations must be performed). The config
+ *element must also specify the order of the polynomial fit (keyword:
+ *ASTROM.ORDER).  The result of this fit is a set of modifications of the
+ *components of the pmChip.toFPA transformation.
+ *
+ * XXX: No prototype code.
+ *
+ */
+bool pmAstromFitChip(
+    pmFPA *fpa,
+    psArray *st1,
+    psArray *st2,
+    psArray *match,
+    psMetadata *config
+);
+
+
+/*******************************************************************************
+ The following functions and structs were in the prototype code, but not the
+ SDRS.
+ ******************************************************************************/
+/*
+ *
+ *
+ *
+ *
+ */
+
+pmAstromFitResults *pmAstromFitResultsAlloc(void);
+
+/*
+ *
+ * Allocates a pmAstromObj struct.
+ *
+ */
+pmAstromObj *pmAstromObjAlloc (void);
+/*
+ * Is a given pointer a pmAstromObj?
+ */
+bool pmAstromObjTest(const psPtr ptr);
+
+
+/*
+ *
+ * Copies a pmAstromObj struct.
+ *
+ */
+pmAstromObj *pmAstromObjCopy(
+    const pmAstromObj *old
+);
+
+
+
+/*
+ *
+ *
+ *
+ */
+pmAstromMatch *pmAstromMatchAlloc(
+    int i1,
+    int i2
+);
+
+
+
+
+/*
+ *
+ *
+ *
+ */
+pmAstromFitResults *pmAstromMatchFit(
+    psPlaneTransform *map,
+    psArray *raw,
+    psArray *ref,
+    psArray *match,
+    psStats *stats
+);
+
+/*
+ *
+ *
+ *
+ */
+int pmAstromObjSortByMag(
+    const void **a,
+    const void **b
+);
+
+/// @}
+#endif // PM_ASTROMETRY_OBJECTS_H
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryRefstars.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryRefstars.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryRefstars.c	(revision 22158)
@@ -0,0 +1,299 @@
+/* @file  pmAstrometryRefstars.c
+ * @brief Functions to write (and read?) astrometric reference stars
+ *
+ * @ingroup AstroImage
+ *
+ * @author EAM, IfA
+ * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-17 22:38:15 $
+ * Copyright 2008 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/******************************************************************************/
+/*  INCLUDE FILES                                                             */
+/******************************************************************************/
+#include <stdio.h>
+#include <strings.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include <unistd.h>   // for unlink
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+#include "pmFPAfileFitsIO.h"
+#include "pmAstrometryObjects.h"
+#include "pmAstrometryRefstars.h"
+
+/********************* CheckDataStatus functions *****************************/
+
+bool pmAstromRefstarsCheckDataStatusForView (const pmFPAview *view, pmFPAfile *file) {
+
+    pmFPA *fpa = file->fpa;
+
+    if (view->chip == -1) {
+        bool exists = pmAstromRefstarsCheckDataStatusForFPA (fpa);
+        return exists;
+    }
+    if (view->chip >= fpa->chips->n) {
+        psError(PS_ERR_IO, true, "Requested chip == %d >= fpa->chips->n == %ld", view->chip, fpa->chips->n);
+        return false;
+    }
+    pmChip *chip = fpa->chips->data[view->chip];
+
+    if (view->cell == -1) {
+        bool exists = pmAstromRefstarsCheckDataStatusForChip (chip);
+        return exists;
+    }
+    if (view->cell >= chip->cells->n) {
+        psError(PS_ERR_IO, true, "Requested cell == %d >= chip->cells->n == %ld", view->cell, chip->cells->n);
+        return false;
+    }
+    psError(PS_ERR_IO, false, "Astrometry only valid at the chip level");
+    return false;
+}
+
+// return true if data exists for any chip
+bool pmAstromRefstarsCheckDataStatusForFPA (const pmFPA *fpa) {
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        if (!chip) continue;
+        if (pmAstromRefstarsCheckDataStatusForChip (chip)) return true;
+    }
+    return false;
+}
+
+// return true if data exists for any cell
+bool pmAstromRefstarsCheckDataStatusForChip (const pmChip *chip) {
+
+    for (int i = 0; i < chip->cells->n; i++) {
+      pmCell *cell = chip->cells->data[i];
+        if (!cell) continue;
+        if (pmAstromRefstarsCheckDataStatusForCell (cell)) return true;
+    }
+    return false;
+}
+
+// return true if data exists for any readout
+bool pmAstromRefstarsCheckDataStatusForCell (const pmCell *cell) {
+
+    for (int i = 0; i < cell->readouts->n; i++) {
+      pmReadout *readout = cell->readouts->data[i];
+        if (!readout) continue;
+        if (pmAstromRefstarsCheckDataStatusForReadout (readout)) return true;
+    }
+    return false;
+}
+
+// check if refstars array exists
+bool pmAstromRefstarsCheckDataStatusForReadout (const pmReadout *readout) {
+
+  if (!readout->analysis) return false;
+
+  // select the raw objects for this readout
+  psArray *refstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.REFSTARS");
+  if (refstars == NULL) return false;
+
+  return true;
+}
+
+/********************* Write Data functions *****************************/
+
+bool pmAstromRefstarsWriteForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config) {
+
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+
+    pmFPA *fpa = file->fpa;
+
+    if (view->chip == -1) {
+        if (!pmAstromRefstarsWriteFPA (fpa, view, file, config)) {
+            psError(PS_ERR_IO, false, "Failed to write refstars for fpa");
+            return false;
+        }
+        return true;
+    }
+
+    if (view->chip >= fpa->chips->n) {
+        psError(PS_ERR_UNKNOWN, false, "Writing chip == %d (>= chips->n == %ld)", view->chip, fpa->chips->n);
+        return false;
+    }
+    pmChip *chip = fpa->chips->data[view->chip];
+
+    if (view->cell == -1) {
+        if (!pmAstromRefstarsWriteChip (chip, view, file, config)) {
+            psError(PS_ERR_IO, false, "Failed to write refstars for chip");
+            return false;
+        }
+        return true;
+    }
+
+    psError(PS_ERR_IO, false, "Astrometry must be written at the FPA level");
+    return false;
+}
+
+bool pmAstromRefstarsWritePHU (const pmFPAview *view, pmFPAfile *file, pmConfig *config) {
+
+    // output header data
+    psMetadata *outhead = psMetadataAlloc();
+
+    // use the FPA phu to generate the PHU header
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, false); // Suitable FPA for writing
+    pmHDU *phu = psMemIncrRefCounter(fpa->hdu);
+    psFree(fpa);
+
+    // if there is no FPA PHU, this is a single header+image (extension-less) file. This could be
+    // the case for an input SPLIT set of files being written out as a MEF.  if there is a PHU,
+    // write it out as a 'blank'
+    if (phu) {
+        psMetadataCopy (outhead, phu->header);
+    } else {
+        pmConfigConformHeader (outhead, file->format);
+    }
+    psFree(phu);
+
+    psMetadataAddBool (outhead, PS_LIST_TAIL, "EXTEND", PS_META_REPLACE, "this file has extensions", true);
+    psFitsWriteBlank (file->fits, outhead, "");
+    file->wrote_phu = true;
+
+    psTrace ("pmFPAfile", 5, "wrote phu %s (type: %d)\n", file->filename, file->type);
+    psFree (outhead);
+
+    return true;
+}
+
+// write out all chip-level Astrometry data for this FPA
+bool pmAstromRefstarsWriteFPA (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config) {
+
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(fpa->chips, false);
+
+    pmFPAview *thisView = pmFPAviewAlloc (view->nRows);
+    *thisView = *view;
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        thisView->chip = i;
+        if (!pmAstromRefstarsWriteChip (chip, thisView, file, config)) {
+            psError(PS_ERR_IO, false, "Failed to write %dth chip", i);
+            psFree (thisView);
+            return false;
+        }
+    }
+    psFree (thisView);
+    return true;
+}
+
+bool pmAstromRefstarsWriteChip (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config) {
+
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_PTR_NON_NULL(chip->cells, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    pmFPAview *thisView = pmFPAviewAlloc (view->nRows);
+    *thisView = *view;
+
+    for (int i = 0; i < chip->cells->n; i++) {
+        pmCell *cell = chip->cells->data[i];
+        thisView->cell = i;
+        if (!pmAstromRefstarsWriteCell (cell, thisView, file, config)) {
+            psError(PS_ERR_IO, false, "Failed to write %dth cell", i);
+            psFree (thisView);
+            return false;
+        }
+    }
+    psFree (thisView);
+    return true;
+}
+
+// read in all readout-level Objects files for this cell
+bool pmAstromRefstarsWriteCell (pmCell *cell, const pmFPAview *view, pmFPAfile *file, const pmConfig *config) {
+
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_PTR_NON_NULL(cell->readouts, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    pmFPAview *thisView = pmFPAviewAlloc (view->nRows);
+    *thisView = *view;
+
+    for (int i = 0; i < cell->readouts->n; i++) {
+        pmReadout *readout = cell->readouts->data[i];
+        thisView->readout = i;
+        if (!pmAstromRefstarsWriteReadout (readout, thisView, file, config)) {
+            psError(PS_ERR_IO, false, "Failed to write %dth readout", i);
+            psFree (thisView);
+            return false;
+        }
+    }
+    psFree (thisView);
+    return true;
+}
+
+// write out all refstars files for this readout
+bool pmAstromRefstarsWriteReadout (pmReadout *readout, const pmFPAview *view, pmFPAfile *file, const pmConfig *config) {
+
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_PTR_NON_NULL(readout->analysis, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    // select the raw objects for this readout
+    psArray *refstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.REFSTARS");
+    if (refstars == NULL) { return TRUE; }
+
+    psMetadata *header = psMetadataAlloc();
+
+    psArray *table = psArrayAllocEmpty (1);
+
+    // set the extname : we are really only allowed one entry per chip; check this here?
+    char *chiprule = psStringCopy ("{CHIP.NAME}");
+    char *chipname = pmFPAfileNameFromRule (chiprule, file, view);
+
+    for (int i = 0; i < refstars->n; i++) {
+      psMetadata *row = psMetadataAlloc ();
+
+      pmAstromObj *ref = refstars->data[i];
+
+      psMetadataAddF64(row,    PS_LIST_TAIL, "RA",      PS_META_REPLACE, "degrees", PS_DEG_RAD*ref->sky->r);
+      psMetadataAddF64(row,    PS_LIST_TAIL, "DEC",     PS_META_REPLACE, "degrees", PS_DEG_RAD*ref->sky->d);
+      psMetadataAddF32(row,    PS_LIST_TAIL, "TP_X",    PS_META_REPLACE, "microns", ref->TP->x);
+      psMetadataAddF32(row,    PS_LIST_TAIL, "TP_Y",    PS_META_REPLACE, "microns", ref->TP->y);
+      psMetadataAddF32(row,    PS_LIST_TAIL, "FP_X",    PS_META_REPLACE, "microns", ref->FP->x);
+      psMetadataAddF32(row,    PS_LIST_TAIL, "FP_Y",    PS_META_REPLACE, "microns", ref->FP->y);
+      psMetadataAddF32(row,    PS_LIST_TAIL, "CHIP_X",  PS_META_REPLACE, "microns", ref->chip->x);
+      psMetadataAddF32(row,    PS_LIST_TAIL, "CHIP_Y",  PS_META_REPLACE, "microns", ref->chip->y);
+      psMetadataAddF32(row,    PS_LIST_TAIL, "MAG",     PS_META_REPLACE, "microns", ref->Mag);
+      psMetadataAddF32(row,    PS_LIST_TAIL, "MAG_ERR", PS_META_REPLACE, "microns", ref->dMag);
+
+      psArrayAdd (table, 100, row);
+      psFree (row);
+    }
+    if (!psFitsWriteTable (file->fits, header, table, chipname)) {
+        psError(PS_ERR_IO, false, "writing refstars\n");
+        psFree (table);
+        psFree (header);
+        psFree (chiprule);
+        psFree (chipname);
+        return false;
+    }
+
+    psFree (chiprule);
+    psFree (chipname);
+    psFree (table);
+    psFree (header);
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryRefstars.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryRefstars.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryRefstars.h	(revision 22158)
@@ -0,0 +1,34 @@
+/* @file  pmAstrometryRefstars.h
+ * @brief Functions to write (and read?) astrometric reference stars
+ *
+ * @ingroup AstroImage
+ *
+ * @author EAM, IfA
+ * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-17 22:38:15 $
+ * Copyright 2008 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_ASTROMETRY_REFSTARS_H
+#define PM_ASTROMETRY_REFSTARS_H
+
+/// @addtogroup Astrometry
+/// @{
+
+bool pmAstromRefstarsCheckDataStatusForView (const pmFPAview *view, pmFPAfile *file);
+bool pmAstromRefstarsCheckDataStatusForFPA (const pmFPA *fpa);
+bool pmAstromRefstarsCheckDataStatusForChip (const pmChip *chip);
+bool pmAstromRefstarsCheckDataStatusForCell (const pmCell *cell);
+bool pmAstromRefstarsCheckDataStatusForReadout (const pmReadout *readout);
+
+bool pmAstromRefstarsWriteForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmAstromRefstarsWritePHU (const pmFPAview *view, pmFPAfile *file, pmConfig *config);
+
+bool pmAstromRefstarsWriteFPA (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmAstromRefstarsWriteChip (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmAstromRefstarsWriteCell (pmCell *cell, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmAstromRefstarsWriteReadout (pmReadout *readout, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryRegions.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryRegions.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryRegions.c	(revision 22158)
@@ -0,0 +1,170 @@
+/** @file  pmAstrometryRegions.c
+ *  @brief functions to define astrometry regions on FPA images
+ *  @ingroup Astrometry
+ *
+ *  @author EAM, IfA
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-12-22 17:51:48 $
+ *
+ *  Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPAExtent.h"
+#include "pmAstrometryRegions.h"
+
+// cell pixels corresponding to readout boundary
+psRegion *pmAstromReadoutInCell (pmReadout *readout) {
+
+    psRegion *region;
+    region = pmReadoutExtent (readout);
+    return (region);
+}
+
+// chip pixels corresponding to cell boundary
+psRegion *pmAstromCellInChip (pmCell *cell) {
+
+    psRegion *region;
+    region = pmCellExtent (cell);
+    return (region);
+}
+
+// FP pixels corresponding to chip boundary
+// since the chip may be rotated in the fpa, this region does not correspond 
+// exactly to the pixel grid of the chip
+psRegion *pmAstromChipInFP (pmChip *chip) {
+
+    PS_ASSERT_PTR_NON_NULL(chip, NULL);
+
+    // if we have not astrometry for this chip, just skip it silently (no error)
+    if (!chip->toFPA) return NULL;
+
+    // determine the bounding box of this chip in chip pixels
+    psRegion *chipExtent = pmChipPixels (chip);
+    if (!chipExtent) return NULL;
+
+    // apply chip-to-fpa astrometry to determine fpa coordinates 
+    psPlane *chPix = psPlaneAlloc ();
+    psPlane *fpPix = psPlaneAlloc ();
+    psRegion *chipRegion = psRegionAlloc(INFINITY, 0, INFINITY, 0); // Extent of chip
+
+    // determine the outer bounding box -- does not correspond to the same square region!
+    chPix->x = chipExtent->x0;
+    chPix->y = chipExtent->y0;
+    psPlaneTransformApply(fpPix, chip->toFPA, chPix); 
+    chipRegion->x0 = PS_MIN (chipRegion->x0, fpPix->x);
+    chipRegion->x1 = PS_MAX (chipRegion->x1, fpPix->x);
+    chipRegion->y0 = PS_MIN (chipRegion->y0, fpPix->y);
+    chipRegion->y1 = PS_MAX (chipRegion->y1, fpPix->y);
+
+    chPix->x = chipExtent->x1;
+    chPix->y = chipExtent->y0;
+    psPlaneTransformApply(fpPix, chip->toFPA, chPix); 
+    chipRegion->x0 = PS_MIN (chipRegion->x0, fpPix->x);
+    chipRegion->x1 = PS_MAX (chipRegion->x1, fpPix->x);
+    chipRegion->y0 = PS_MIN (chipRegion->y0, fpPix->y);
+    chipRegion->y1 = PS_MAX (chipRegion->y1, fpPix->y);
+
+    chPix->x = chipExtent->x1;
+    chPix->y = chipExtent->y1;
+    psPlaneTransformApply(fpPix, chip->toFPA, chPix); 
+    chipRegion->x0 = PS_MIN (chipRegion->x0, fpPix->x);
+    chipRegion->x1 = PS_MAX (chipRegion->x1, fpPix->x);
+    chipRegion->y0 = PS_MIN (chipRegion->y0, fpPix->y);
+    chipRegion->y1 = PS_MAX (chipRegion->y1, fpPix->y);
+
+    chPix->x = chipExtent->x0;
+    chPix->y = chipExtent->y1;
+    psPlaneTransformApply(fpPix, chip->toFPA, chPix); 
+    chipRegion->x0 = PS_MIN (chipRegion->x0, fpPix->x);
+    chipRegion->x1 = PS_MAX (chipRegion->x1, fpPix->x);
+    chipRegion->y0 = PS_MIN (chipRegion->y0, fpPix->y);
+    chipRegion->y1 = PS_MAX (chipRegion->y1, fpPix->y);
+
+    psFree (chPix);
+    psFree (fpPix);
+    psFree (chipExtent);
+    return (chipRegion);
+}
+
+// return FPA pixels included in all chips
+// this FPA grid has 0,0 at the mosaic center and is used for astrometric reference.
+psRegion *pmAstromFPAExtent(const pmFPA *fpa)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
+
+    psArray *chips = fpa->chips;       // Array of component chips
+    psRegion *fpaExtent = psRegionAlloc(INFINITY, 0, INFINITY, 0); // Extent of fpa
+    for (long i = 0; i < chips->n; i++) {
+        pmChip *chip = chips->data[i];  // Chip of interest
+        psRegion *chipExtent = pmAstromChipInFP(chip); // Extent of chip
+	if (!chipExtent) { continue; }
+        fpaExtent->x0 = PS_MIN(fpaExtent->x0, chipExtent->x0);
+        fpaExtent->x1 = PS_MAX(fpaExtent->x1, chipExtent->x1);
+        fpaExtent->y0 = PS_MIN(fpaExtent->y0, chipExtent->y0);
+        fpaExtent->y1 = PS_MAX(fpaExtent->y1, chipExtent->y1);
+        psFree(chipExtent);
+    }
+
+    return fpaExtent;
+}
+
+// TPA pixels corresponding to FPA boundary
+psRegion *pmAstromFPInTP (pmFPA *fpa) {
+
+    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
+    PS_ASSERT_PTR_NON_NULL(fpa->toTPA, NULL);
+
+    psRegion *fpaExtent = pmAstromFPAExtent (fpa);
+    if (!fpaExtent) return NULL;
+
+    // apply fpa-to-tpa astrometry to determine tpa coordinates 
+    psPlane *fpPix = psPlaneAlloc ();
+    psPlane *tpPix = psPlaneAlloc ();
+    psRegion *fpaRegion = psRegionAlloc(INFINITY, 0, INFINITY, 0); // Extent of fpa
+
+    // determine the outer bounding box -- does not correspond to the same square region!
+    fpPix->x = fpaExtent->x0;
+    fpPix->y = fpaExtent->y0;
+    psPlaneTransformApply(tpPix, fpa->toTPA, fpPix); 
+    fpaRegion->x0 = PS_MIN (fpaRegion->x0, tpPix->x);
+    fpaRegion->x1 = PS_MAX (fpaRegion->x1, tpPix->x);
+    fpaRegion->y0 = PS_MIN (fpaRegion->y0, tpPix->y);
+    fpaRegion->y1 = PS_MAX (fpaRegion->y1, tpPix->y);
+
+    fpPix->x = fpaExtent->x1;
+    fpPix->y = fpaExtent->y0;
+    psPlaneTransformApply(tpPix, fpa->toTPA, fpPix); 
+    fpaRegion->x0 = PS_MIN (fpaRegion->x0, tpPix->x);
+    fpaRegion->x1 = PS_MAX (fpaRegion->x1, tpPix->x);
+    fpaRegion->y0 = PS_MIN (fpaRegion->y0, tpPix->y);
+    fpaRegion->y1 = PS_MAX (fpaRegion->y1, tpPix->y);
+
+    fpPix->x = fpaExtent->x1;
+    fpPix->y = fpaExtent->y1;
+    psPlaneTransformApply(tpPix, fpa->toTPA, fpPix); 
+    fpaRegion->x0 = PS_MIN (fpaRegion->x0, tpPix->x);
+    fpaRegion->x1 = PS_MAX (fpaRegion->x1, tpPix->x);
+    fpaRegion->y0 = PS_MIN (fpaRegion->y0, tpPix->y);
+    fpaRegion->y1 = PS_MAX (fpaRegion->y1, tpPix->y);
+
+    fpPix->x = fpaExtent->x0;
+    fpPix->y = fpaExtent->y1;
+    psPlaneTransformApply(tpPix, fpa->toTPA, fpPix); 
+    fpaRegion->x0 = PS_MIN (fpaRegion->x0, tpPix->x);
+    fpaRegion->x1 = PS_MAX (fpaRegion->x1, tpPix->x);
+    fpaRegion->y0 = PS_MIN (fpaRegion->y0, tpPix->y);
+    fpaRegion->y1 = PS_MAX (fpaRegion->y1, tpPix->y);
+
+    psFree (fpPix);
+    psFree (tpPix);
+    psFree (fpaExtent);
+    return (fpaRegion);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryRegions.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryRegions.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryRegions.h	(revision 22158)
@@ -0,0 +1,35 @@
+/* @file  pmAstrometryRegion.h
+ * @brief functions to detemine fpa,chip,etc boundaries from astrometry
+ *
+ * @author EAM, IfA
+ * @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-03-21 21:59:57 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_ASTROMETRY_REGIONS_H
+#define PM_ASTROMETRY_REGIONS_H
+
+/// @addtogroup Astrometry
+/// @{
+
+// cell pixels corresponding to readout boundary
+psRegion *pmAstromReadoutInCell (pmReadout *readout);
+
+// chip pixels corresponding to cell boundary
+psRegion *pmAstromCellInChip (pmCell *cell);
+
+// FP pixels corresponding to chip boundary
+// since the chip may be rotated in the fpa, this region does not correspond 
+// exactly to the pixel grid of the chip
+psRegion *pmAstromChipInFP (pmChip *chip);
+
+// return FPA pixels included in all chips
+// this FPA grid has 0,0 at the mosaic center and is used for astrometric reference.
+psRegion *pmAstromFPAExtent(const pmFPA *fpa);
+
+// chip pixels corresponding to cell boundary
+psRegion *pmAstromFPInTP (pmFPA *fpa);
+
+/// @}
+#endif // PM_ASTROMETRY_DISTORTION_H
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryTable.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryTable.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryTable.c	(revision 22158)
@@ -0,0 +1,754 @@
+/** @file  pmAstrometryTable.c
+ *
+ *  @brief Functions to read and write astrometric information using the generic astrometry
+ *  model.
+ *
+ *  The generic model does not specify the location of the boresite on the sky, and it includes
+ *  a model for the rotator and motion of the boresite.
+ *
+ *  @ingroup AstroImage
+ *
+ *  @author EAM, IfA
+ *  @version $Revision: 1.9.14.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-25 02:00:01 $
+ *
+ *  Copyright 2007 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/******************************************************************************/
+/*  INCLUDE FILES                                                             */
+/******************************************************************************/
+#include <stdio.h>
+#include <strings.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include <unistd.h>   // for unlink
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+#include "pmFPAExtent.h"
+#include "pmAstrometryWCS.h"
+#include "pmAstrometryUtils.h"
+#include "pmAstrometryRegions.h"
+#include "pmAstrometryTable.h"
+
+# define REQUIRE(TEST,MESSAGE){ if (!(TEST)) { psAbort (MESSAGE); }}
+
+/********************* CheckDataStatus functions *****************************/
+
+bool pmAstromCheckDataStatusForView (const pmFPAview *view, pmFPAfile *file) {
+
+    pmFPA *fpa = file->fpa;
+
+    if (view->chip == -1) {
+        bool exists = pmAstromCheckDataStatusForFPA (fpa);
+        return exists;
+    }
+    if (view->chip >= fpa->chips->n) {
+        psError(PS_ERR_IO, true, "Requested chip == %d >= fpa->chips->n == %ld", view->chip, fpa->chips->n);
+        return false;
+    }
+    pmChip *chip = fpa->chips->data[view->chip];
+
+    if (view->cell == -1) {
+        bool exists = pmAstromCheckDataStatusForChip (chip);
+        return exists;
+    }
+    if (view->cell >= chip->cells->n) {
+        psError(PS_ERR_IO, true, "Requested cell == %d >= chip->cells->n == %ld", view->cell, chip->cells->n);
+        return false;
+    }
+    psError(PS_ERR_IO, false, "Astrometry only valid at the chip level");
+    return false;
+}
+
+bool pmAstromCheckDataStatusForFPA (const pmFPA *fpa) {
+
+    if (!fpa->toTPA) return false;
+    if (!fpa->fromTPA) return false;
+    if (!fpa->toSky) return false;
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        if (!chip) continue;
+        if (pmAstromCheckDataStatusForChip (chip)) return true;
+    }
+    return false;
+}
+
+bool pmAstromCheckDataStatusForChip (const pmChip *chip) {
+
+    if (!chip->toFPA) return false;
+    if (!chip->fromFPA) return false;  // XXX not strictly needed?
+    return true;
+}
+
+/********************* Write Data functions *****************************/
+
+bool pmAstromWriteForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config) {
+
+    // write the full table in one pass: require the level to be FPA
+    if (view->chip != -1) {
+        psError(PS_ERR_IO, false, "Astrometry must be written at the FPA level");
+        return false;
+    }
+
+    if (!pmAstromWriteFPA (file)) {
+        psError(PS_ERR_IO, false, "Failed to write Astrometry for fpa");
+        return false;
+    }
+    return true;
+}
+
+// write out all chip-level Astrometry data for this FPA
+bool pmAstromWriteFPA (pmFPAfile *file) {
+
+    if (!pmAstromWritePHU (file)) {
+        psError(PS_ERR_IO, false, "Failed to write PHU for Astrometry table");
+        return false;
+    }
+
+    if (!pmAstromWriteChips (file)) {
+        psError(PS_ERR_IO, false, "Failed to write Astrometry for chips");
+        return false;
+    }
+
+    if (!pmAstromWriteFP (file)) {
+        psError(PS_ERR_IO, false, "Failed to write Sky for Astrometry table");
+        return false;
+    }
+
+    if (!pmAstromWriteTP (file)) {
+        psError(PS_ERR_IO, false, "Failed to write Sky for Astrometry table");
+        return false;
+    }
+
+    if (!pmAstromWriteSky (file)) {
+        psError(PS_ERR_IO, false, "Failed to write Sky for Astrometry table");
+        return false;
+    }
+
+    return true;
+}
+
+bool pmAstromWritePHU (pmFPAfile *file) {
+
+    // output header data
+    psMetadata *outhead = psMetadataAlloc();
+
+    // use the FPA phu to generate the PHU header
+    pmHDU *phu = file->fpa->hdu;
+
+    // if there is no FPA PHU, this is a single header+image (extension-less) file. This could be
+    // the case for an input SPLIT set of files being written out as a MEF.  if there is a PHU,
+    // write it out as a 'blank'
+    if (phu) {
+        psMetadataCopy (outhead, phu->header);
+    } else {
+        pmConfigConformHeader (outhead, file->format);
+    }
+
+    psMetadataAddBool (outhead, PS_LIST_TAIL, "EXTEND", PS_META_REPLACE, "this file has extensions", true);
+    psFitsWriteBlank (file->fits, outhead, "");
+    file->wrote_phu = true;
+
+    psTrace ("pmFPAfile", 5, "wrote phu %s (type: %d)\n", file->filename, file->type);
+    psFree (outhead);
+
+    return true;
+}
+
+// fourth layer holds the chips
+bool pmAstromWriteChips (pmFPAfile *file) {
+
+    psMetadata *header = psMetadataAlloc();
+    psMetadataAddStr(header, PS_LIST_TAIL, "COORD",    PS_META_REPLACE, "name of this layer",   "CHIPS");
+    psMetadataAddStr(header, PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "FOCAL_PLANE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "BOUNDARY", PS_META_REPLACE, "validity region",      "RECTANGLE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "TRANSFRM", PS_META_REPLACE, "mapping to parent",    "POLYNOMIAL");
+
+    psArray *table = psArrayAllocEmpty (1);
+
+    pmFPAview *view = pmFPAviewAlloc (0);
+
+    pmChip *chip = NULL;
+    while ((chip = pmFPAviewNextChip (view, file->fpa, 1)) != NULL) {
+
+        if (!chip->toFPA) continue;
+        assert (chip->toFPA->x);
+        assert (chip->toFPA->y);
+
+        psRegion *region = pmChipPixels (chip);
+
+        // set the chip name
+        char *chiprule = psStringCopy ("{CHIP.NAME}");
+        char *chipname = pmFPAfileNameFromRule (chiprule, file, view);
+
+        for (int i = 0; i <= chip->toFPA->x->nX; i++) {
+            for (int j = 0; j <= chip->toFPA->x->nY; j++) {
+                psMetadata *row = psMetadataAlloc ();
+
+                psMetadataAddStr(row,    PS_LIST_TAIL, "SEGMENT",  PS_META_REPLACE, "name of this segment", chipname);
+                psMetadataAddStr(row,    PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "FOCAL_PLANE");
+                psMetadataAddF32(row,    PS_LIST_TAIL, "MINX",     PS_META_REPLACE, "range", region->x0);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "MAXX",     PS_META_REPLACE, "range", region->x1);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "MINY",     PS_META_REPLACE, "range", region->y0);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "MAXY",     PS_META_REPLACE, "range", region->y1);
+
+                psMetadataAddS32(row,    PS_LIST_TAIL, "XORDER",   PS_META_REPLACE, "", i);
+                psMetadataAddS32(row,    PS_LIST_TAIL, "YORDER",   PS_META_REPLACE, "", j);
+                psMetadataAddS32(row,    PS_LIST_TAIL, "NXORDER",  PS_META_REPLACE, "", chip->toFPA->x->nX);
+                psMetadataAddS32(row,    PS_LIST_TAIL, "NYORDER",  PS_META_REPLACE, "", chip->toFPA->x->nY);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "POLY_X",   PS_META_REPLACE, "", chip->toFPA->x->coeff[i][j]);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "POLY_Y",   PS_META_REPLACE, "", chip->toFPA->y->coeff[i][j]);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "ERROR_X",  PS_META_REPLACE, "", chip->toFPA->x->coeffErr[i][j]);
+                psMetadataAddF32(row,    PS_LIST_TAIL, "ERROR_Y",  PS_META_REPLACE, "", chip->toFPA->y->coeffErr[i][j]);
+                psMetadataAddU8 (row,    PS_LIST_TAIL, "MASK_X",   PS_META_REPLACE, "", chip->toFPA->x->coeffMask[i][j]);
+                psMetadataAddU8 (row,    PS_LIST_TAIL, "MASK_Y",   PS_META_REPLACE, "", chip->toFPA->y->coeffMask[i][j]);
+                psArrayAdd (table, 100, row);
+                psFree (row);
+            }
+        }
+        psFree (chiprule);
+        psFree (chipname);
+        psFree (region);
+    }
+
+    if (!psFitsWriteTable (file->fits, header, table, "CHIPS")) {
+        psError(PS_ERR_IO, false, "writing sky data\n");
+        psFree(table);
+        return false;
+    }
+
+    psFree (view);
+    psFree (table);
+    psFree (header);
+    return true;
+}
+
+// third layer is the focal plane
+bool pmAstromWriteFP (pmFPAfile *file) {
+
+    bool status;
+
+    psMetadata *header = psMetadataAlloc();
+    psMetadataAddStr(header, PS_LIST_TAIL, "COORD",    PS_META_REPLACE, "name of this layer",   "FOCAL_PLANE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "TANGENT_PLANE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "BOUNDARY", PS_META_REPLACE, "validity region",      "RECTANGLE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "TRANSFRM", PS_META_REPLACE, "mapping to parent",    "POLYNOMIAL");
+
+    psArray *table = psArrayAllocEmpty (1);
+
+    // XXX is this or the tpa region correct?
+    psRegion *region = pmAstromFPAExtent (file->fpa);
+
+    // rotate the toTPA to have 0.0 posangle
+    float posangle = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.POSANGLE");
+
+    // the to/from TPA transform currently has rotation of posangle; remove it & create the toTPA version
+    psPlaneTransform *fromTPA = psPlaneTransformRotate (NULL, file->fpa->fromTPA, -posangle);
+    psPlaneTransform *toTPA   = psPlaneTransformInvert(NULL, fromTPA, *region, 50);
+
+    for (int i = 0; i <= toTPA->x->nX; i++) {
+        for (int j = 0; j <= toTPA->x->nY; j++) {
+            psMetadata *row = psMetadataAlloc ();
+            psMetadataAddStr(row,    PS_LIST_TAIL, "SEGMENT",  PS_META_REPLACE, "name of this segment", "FOCAL_PLANE");
+            psMetadataAddStr(row,    PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "TANGENT_PLANE");
+            psMetadataAddF32(row,    PS_LIST_TAIL, "MINX",     PS_META_REPLACE, "range", region->x0);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "MAXX",     PS_META_REPLACE, "range", region->x1);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "MINY",     PS_META_REPLACE, "range", region->y0);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "MAXY",     PS_META_REPLACE, "range", region->y1);
+
+            psMetadataAddS32(row,    PS_LIST_TAIL, "XORDER",   PS_META_REPLACE, "", i);
+            psMetadataAddS32(row,    PS_LIST_TAIL, "YORDER",   PS_META_REPLACE, "", j);
+            psMetadataAddS32(row,    PS_LIST_TAIL, "NXORDER",  PS_META_REPLACE, "", toTPA->x->nX);
+            psMetadataAddS32(row,    PS_LIST_TAIL, "NYORDER",  PS_META_REPLACE, "", toTPA->x->nY);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "POLY_X",   PS_META_REPLACE, "", toTPA->x->coeff[i][j]);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "POLY_Y",   PS_META_REPLACE, "", toTPA->y->coeff[i][j]);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "ERROR_X",  PS_META_REPLACE, "", toTPA->x->coeffErr[i][j]);
+            psMetadataAddF32(row,    PS_LIST_TAIL, "ERROR_Y",  PS_META_REPLACE, "", toTPA->y->coeffErr[i][j]);
+            psMetadataAddU8 (row,    PS_LIST_TAIL, "MASK_X",   PS_META_REPLACE, "", toTPA->x->coeffMask[i][j]);
+            psMetadataAddU8 (row,    PS_LIST_TAIL, "MASK_Y",   PS_META_REPLACE, "", toTPA->y->coeffMask[i][j]);
+
+            psArrayAdd (table, 100, row);
+            psFree (row);
+        }
+    }
+
+    if (!psFitsWriteTable (file->fits, header, table, "FP")) {
+        psError(PS_ERR_IO, false, "writing sky data\n");
+        psFree(table);
+        psFree (header);
+        psFree (region);
+        return false;
+    }
+
+    psFree (table);
+    psFree (header);
+    psFree (region);
+    return true;
+}
+
+// second layer is the tangent plane
+bool pmAstromWriteTP (pmFPAfile *file) {
+
+    bool status;
+
+    // get the boresite model parameters
+    float Xo = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.X0");
+    float Yo = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.Y0");
+    float RX = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.RX");
+    float RY = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.RY");
+    float To = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.T0");
+    float Po = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.BORE.P0");
+    float PosZero = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.POS_ZERO");  /// XXX be consistent with degrees v radians
+    char *refChip = psMetadataLookupStr (&status, file->fpa->concepts, "FPA.REF.CHIP");
+
+    psMetadata *header = psMetadataAlloc();
+    psMetadataAddStr(header, PS_LIST_TAIL, "COORD",    PS_META_REPLACE, "name of this layer",   "TANGENT_PLANE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "SKY");
+    psMetadataAddStr(header, PS_LIST_TAIL, "BOUNDARY", PS_META_REPLACE, "validity region",      "RECTANGLE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "TRANSFRM", PS_META_REPLACE, "mapping to parent",    "PROJECTION");
+
+    psArray *table = psArrayAllocEmpty (1);
+    psMetadata *row = psMetadataAlloc ();
+    psMetadataAddStr(row,    PS_LIST_TAIL, "SEGMENT",  PS_META_REPLACE, "name of this segment", "TANGENT_PLANE");
+    psMetadataAddStr(row,    PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "SKY");
+
+    psRegion *region = pmAstromFPAExtent (file->fpa);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "MINX",     PS_META_REPLACE, "range", region->x0);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "MAXX",     PS_META_REPLACE, "range", region->x1);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "MINY",     PS_META_REPLACE, "range", region->y0);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "MAXY",     PS_META_REPLACE, "range", region->y1);
+
+    // psMetadataAddF32(row,    PS_LIST_TAIL, "XREF",     PS_META_REPLACE, "", file->fpa->toSky->R  * PM_DEG_RAD);
+    // psMetadataAddF32(row,    PS_LIST_TAIL, "YREF",     PS_META_REPLACE, "", file->fpa->toSky->D  * PM_DEG_RAD);
+
+    psMetadataAddF32(row,    PS_LIST_TAIL, "XSCALE",   PS_META_REPLACE, "", file->fpa->toSky->Xs * PM_DEG_RAD);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "YSCALE",   PS_META_REPLACE, "", file->fpa->toSky->Ys * PM_DEG_RAD);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "BORE_X0",  PS_META_REPLACE, "boresite parameter", Xo);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "BORE_Y0",  PS_META_REPLACE, "boresite parameter", Yo);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "BORE_RX",  PS_META_REPLACE, "boresite parameter", RX);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "BORE_RY",  PS_META_REPLACE, "boresite parameter", RY);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "BORE_T0",  PS_META_REPLACE, "boresite parameter", To);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "BORE_P0",  PS_META_REPLACE, "boresite parameter", Po);
+    psMetadataAddF32(row,    PS_LIST_TAIL, "POS_ZERO", PS_META_REPLACE, "boresite parameter", PosZero);
+    psMetadataAddStr(row,    PS_LIST_TAIL, "REF_CHIP", PS_META_REPLACE, "boresite parameter", refChip);
+
+    psArrayAdd (table, 100, row);
+    psFree (row);
+
+    if (!psFitsWriteTable (file->fits, header, table, "TP")) {
+        psError(PS_ERR_IO, false, "writing sky data\n");
+        psFree (region);
+        psFree (table);
+        psFree (header);
+        return false;
+    }
+
+    psFree (region);
+    psFree (table);
+    psFree (header);
+    return (true);
+}
+
+// first layer is the sky
+bool pmAstromWriteSky (pmFPAfile *file) {
+
+    psMetadata *header = psMetadataAlloc();
+    psMetadataAddStr(header, PS_LIST_TAIL, "COORD",    PS_META_REPLACE, "name of this layer",   "SKY");
+    psMetadataAddStr(header, PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "NONE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "BOUNDARY", PS_META_REPLACE, "validity region",      "NONE");
+    psMetadataAddStr(header, PS_LIST_TAIL, "TRANSFRM", PS_META_REPLACE, "mapping to parent",    "NONE");
+
+    psArray *table = psArrayAllocEmpty (1);
+    psMetadata *row = psMetadataAlloc ();
+    psMetadataAddStr(row,    PS_LIST_TAIL, "SEGMENT",  PS_META_REPLACE, "name of this segment", "SKY");
+    psMetadataAddStr(row,    PS_LIST_TAIL, "PARENT",   PS_META_REPLACE, "next layer up",        "NONE");
+
+    psArrayAdd (table, 100, row);
+    psFree (row);
+
+    if (!psFitsWriteTable (file->fits, header, table, "SKY")) {
+        psError(PS_ERR_IO, false, "writing sky data\n");
+        psFree(table);
+        return false;
+    }
+
+    psFree (table);
+    psFree (header);
+    return (true);
+}
+
+/********************* Read Data functions *****************************/
+
+bool pmAstromReadForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+    {
+
+        // write the full table in one pass: require the level to be FPA
+        if (view->chip != -1) {
+            psError(PS_ERR_IO, false, "Astrometry must be read at the FPA level");
+            return false;
+        }
+
+        if (!pmAstromReadFPA (file)) {
+            psError(PS_ERR_IO, false, "Failed to read Astrometry for fpa");
+            return false;
+        }
+        return true;
+    }
+
+// read out all chip-level Astrometry data for this FPA
+bool pmAstromReadFPA (pmFPAfile *file) {
+
+    if (!pmAstromReadPHU (file)) {
+        psError(PS_ERR_IO, false, "Failed to read PHU for Astrometry table");
+        return false;
+    }
+
+    if (!pmAstromReadChips (file)) {
+        psError(PS_ERR_IO, false, "Failed to read Astrometry for chips");
+        return false;
+    }
+
+    if (!pmAstromReadFP (file)) {
+        psError(PS_ERR_IO, false, "Failed to read Sky for Astrometry table");
+        return false;
+    }
+
+    // NOTE : TP must come after FP as it applies the POS, ROT boresite corrections to the
+    // transformation determined in FP
+    if (!pmAstromReadTP (file)) {
+        psError(PS_ERR_IO, false, "Failed to read Sky for Astrometry table");
+        return false;
+    }
+
+    if (!pmAstromReadSky (file)) {
+        psError(PS_ERR_IO, false, "Failed to read Sky for Astrometry table");
+        return false;
+    }
+
+    return true;
+}
+
+bool pmAstromReadPHU (pmFPAfile *file) {
+
+    fprintf (stderr, "not sure we need to read PHU\n");
+    return true;
+}
+
+int pmConceptsChipNumberFromName (pmFPA *fpa, char *name) {
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        if (!chip) continue;
+        char *thisone = psMetadataLookupStr (NULL, chip->concepts, "CHIP.NAME");
+        if (!thisone) continue;
+        if (!strcmp (name, thisone)) return (i);
+    }
+    return -1;
+}
+
+pmChip *pmConceptsChipFromName (pmFPA *fpa, char *name) {
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        if (!chip) continue;
+        char *thisone = psMetadataLookupStr (NULL, chip->concepts, "CHIP.NAME");
+        if (!thisone) continue;
+        if (!strcmp (name, thisone)) return (chip);
+    }
+    return NULL;
+}
+
+// first layer converts Chip to Focal Plane
+bool pmAstromReadChips (pmFPAfile *file) {
+
+    bool status;
+
+    // set FITS cursor
+    if (!psFitsMoveExtName (file->fits, "CHIPS")) {
+        psError(PS_ERR_IO, false, "missing CHIPS extension in astrometry table\n");
+        return false;
+    }
+
+    // free exising tranformations in prep for new alloc below
+    for (int i = 0; i < file->fpa->chips->n; i++) {
+        pmChip *chip = file->fpa->chips->data[i];
+        psFree (chip->toFPA);
+        chip->toFPA = NULL;
+    }
+
+    // XXX do I need anything from the header?
+    psMetadata *header = psFitsReadHeader(NULL, file->fits); // The FITS header
+    if (!header) psAbort("cannot read table header");
+
+    // load the full table in one shot
+    psArray *table = psFitsReadTable (file->fits);
+    if (!table) psAbort("cannot read table");
+    fprintf (stderr, "read %ld rows from FP\n", table->n);
+
+    // parse the table entries
+    for (int i = 0; i < table->n; i++) {
+        psMetadata *row = table->data[i];
+
+        // name of the chip for this row.
+        char *chipname = psMetadataLookupStr (&status, row, "SEGMENT");
+
+        // get chip from name
+        pmChip *chip = pmConceptsChipFromName (file->fpa, chipname);
+        REQUIRE (chip, "invalid chip name");
+
+        // define the toFPA transform if not already defined
+        int nX = psMetadataLookupS32(&status, row, "NXORDER"); REQUIRE (status, "missing NXORDER");
+        int nY = psMetadataLookupS32(&status, row, "NYORDER"); REQUIRE (status, "missing NYORDER");
+        if (chip->toFPA == NULL) {
+            chip->toFPA = psPlaneTransformAlloc(nX, nY);
+        } else {
+            REQUIRE (chip->toFPA->x->nX == nX, "mismatch in chip order");
+            REQUIRE (chip->toFPA->x->nY == nY, "mismatch in chip order");
+            REQUIRE (chip->toFPA->y->nX == nX, "mismatch in chip order");
+            REQUIRE (chip->toFPA->y->nY == nY, "mismatch in chip order");
+        }
+
+        int ix = psMetadataLookupS32(&status, row, "XORDER");  REQUIRE (status, "missing XORDER");
+        int iy = psMetadataLookupS32(&status, row, "YORDER");  REQUIRE (status, "missing YORDER");
+
+        // XXX do I need to use this or can i rely on the camera concepts?
+        // minX = psMetadataLookupF32(&status, row, "MINX");
+        // maxX = psMetadataLookupF32(&status, row, "MAXX");
+        // minY = psMetadataLookupF32(&status, row, "MINY");
+        // maxY = psMetadataLookupF32(&status, row, "MAXY");
+
+        // XXX need to include mask values
+        chip->toFPA->x->coeff[ix][iy]    = psMetadataLookupF32(&status, row, "POLY_X");
+        chip->toFPA->y->coeff[ix][iy]    = psMetadataLookupF32(&status, row, "POLY_Y");
+        chip->toFPA->x->coeffErr[ix][iy] = psMetadataLookupF32(&status, row, "ERROR_X");
+        chip->toFPA->y->coeffErr[ix][iy] = psMetadataLookupF32(&status, row, "ERROR_Y");
+        chip->toFPA->x->coeffMask[ix][iy] = psMetadataLookupU8(&status, row, "MASK_X");
+        chip->toFPA->y->coeffMask[ix][iy] = psMetadataLookupU8(&status, row, "MASK_Y");
+    }
+
+    // convert the toFPA transfomations to fromFPA transformations
+    for (int i = 0; i < file->fpa->chips->n; i++) {
+        pmChip *chip = file->fpa->chips->data[i];
+        if (!chip->toFPA) continue;
+        psRegion *region = pmChipPixels (chip);
+        psFree (chip->fromFPA);
+        chip->fromFPA = psPlaneTransformInvert(NULL, chip->toFPA, *region, 50);
+        psFree (region);
+    }
+
+    psFree (table);
+    psFree (header);
+    return true;
+}
+
+// second layer converts Focal Plane to Tangent Plane (unrotated)
+bool pmAstromReadFP (pmFPAfile *file) {
+
+    bool status;
+
+    if (!psFitsMoveExtName (file->fits, "FP")) {
+        psError(PS_ERR_IO, false, "missing FP extension in astrometry table\n");
+        return false;
+    }
+
+    psMetadata *header = psFitsReadHeader(NULL, file->fits); // The FITS header
+    if (!header) psAbort("cannot read table header");
+
+    // free the old
+    psFree (file->fpa->toTPA);
+    file->fpa->toTPA = NULL;
+
+    // read the complete table data at one shot
+    psArray *table = psFitsReadTable (file->fits);
+    fprintf (stderr, "read %ld rows from FP\n", table->n);
+
+    // parse the table
+    for (int i = 0; i < table->n; i++) {
+        psMetadata *row = table->data[i];
+
+        // there is only one transformation in this table; the order is defined in the header
+        int nX = psMetadataLookupS32(&status, row, "NXORDER"); REQUIRE (status, "missing NXORDER");
+        int nY = psMetadataLookupS32(&status, row, "NYORDER"); REQUIRE (status, "missing NYORDER");
+        if (file->fpa->toTPA == NULL) {
+            // allocate the new transformation
+            file->fpa->toTPA = psPlaneTransformAlloc(nX, nY);
+        } else {
+            REQUIRE (file->fpa->toTPA->x->nX == nX, "mismatch in chip order");
+            REQUIRE (file->fpa->toTPA->x->nY == nY, "mismatch in chip order");
+            REQUIRE (file->fpa->toTPA->y->nX == nX, "mismatch in chip order");
+            REQUIRE (file->fpa->toTPA->y->nY == nY, "mismatch in chip order");
+        }
+
+        int ix = psMetadataLookupS32(&status, row, "XORDER"); REQUIRE (status, "missing XORDER");
+        int iy = psMetadataLookupS32(&status, row, "YORDER"); REQUIRE (status, "missing YORDER");
+        file->fpa->toTPA->x->coeff[ix][iy]     = psMetadataLookupF32(&status, row, "POLY_X");  REQUIRE (status, "missing POLY_X");
+        file->fpa->toTPA->y->coeff[ix][iy]     = psMetadataLookupF32(&status, row, "POLY_Y");  REQUIRE (status, "missing POLY_Y");
+        file->fpa->toTPA->x->coeffErr[ix][iy]  = psMetadataLookupF32(&status, row, "ERROR_X"); REQUIRE (status, "missing ERROR_X");
+        file->fpa->toTPA->y->coeffErr[ix][iy]  = psMetadataLookupF32(&status, row, "ERROR_Y"); REQUIRE (status, "missing ERROR_Y");
+        file->fpa->toTPA->x->coeffMask[ix][iy] = psMetadataLookupU8 (&status, row, "MASK_X");  REQUIRE (status, "missing MASK_X");
+        file->fpa->toTPA->y->coeffMask[ix][iy] = psMetadataLookupU8 (&status, row, "MASK_Y");  REQUIRE (status, "missing MASK_Y");
+    }
+
+    psRegion *region = pmAstromFPAExtent (file->fpa);
+    psFree (file->fpa->fromTPA);
+    file->fpa->fromTPA = psPlaneTransformInvert(NULL, file->fpa->toTPA, *region, 50);
+
+    psFree (table);
+    psFree (header);
+    psFree (region);
+    return true;
+}
+
+# define TRANSFER(TO,FROM,NAME) { \
+    psMetadataItem *item = psMetadataLookup(FROM,NAME); \
+    if (!item) psAbort ("cannot find %s", NAME); \
+    psMetadataItem *newItem = psMetadataItemCopy(item); \
+    if (!psMetadataAddItem(TO, newItem, PS_LIST_TAIL, PS_META_REPLACE)) { \
+        psAbort ("cannot copy %s", NAME); \
+    } \
+    psFree (newItem); }
+
+// third layer applies boresite corrections and converts tangent plane to sky
+bool pmAstromReadTP (pmFPAfile *file) {
+
+    if (!psFitsMoveExtName (file->fits, "TP")) {
+        psError(PS_ERR_IO, false, "missing TP extension in astrometry table\n");
+        return false;
+    }
+
+    psMetadata *header = psFitsReadHeader(NULL, file->fits); // The FITS header
+    if (!header) psAbort("cannot read table header");
+
+    psArray *table = psFitsReadTable (file->fits);
+    fprintf (stderr, "read %ld rows from TP\n", table->n);
+    if (table->n != 1) psAbort("invalid number of rows in TP table (%ld)", table->n);
+
+    psMetadata *row = table->data[0];
+
+    // move needed items to the concepts
+    TRANSFER (file->fpa->concepts, row, "XSCALE");
+    TRANSFER (file->fpa->concepts, row, "XSCALE");
+    TRANSFER (file->fpa->concepts, row, "YSCALE");
+    TRANSFER (file->fpa->concepts, row, "BORE_X0");
+    TRANSFER (file->fpa->concepts, row, "BORE_Y0");
+    TRANSFER (file->fpa->concepts, row, "BORE_RX");
+    TRANSFER (file->fpa->concepts, row, "BORE_RY");
+    TRANSFER (file->fpa->concepts, row, "BORE_T0");
+    TRANSFER (file->fpa->concepts, row, "BORE_P0");
+    TRANSFER (file->fpa->concepts, row, "POS_ZERO");
+    TRANSFER (file->fpa->concepts, row, "REF_CHIP");
+
+    psFree (table);
+    psFree (header);
+    return (true);
+}
+
+// first layer is the sky
+bool pmAstromReadSky (pmFPAfile *file) {
+
+    if (!psFitsMoveExtName (file->fits, "SKY")) {
+        psError(PS_ERR_IO, false, "missing SKY extension in astrometry table\n");
+        return false;
+    }
+
+    psMetadata *header = psFitsReadHeader(NULL, file->fits); // The FITS header
+    if (!header) psAbort("cannot read table header");
+
+    psArray *table = psFitsReadTable (file->fits);
+    fprintf (stderr, "read %ld rows from SKY\n", table->n);
+    if (table->n != 1) psAbort("invalid number of rows in SKY table (%ld)", table->n);
+
+    // XXX not much information of interest in this table...
+
+    psFree (table);
+    psFree (header);
+    return (true);
+}
+
+// third layer applies boresite corrections and converts tangent plane to sky
+bool pmAstromSetTP (pmFPAfile *file, psMetadata *concepts) {
+
+    bool status;
+
+    // these externally supplied values are used to set the final transformation terms
+    double RA  = psMetadataLookupF64 (&status, concepts, "FPA.RA"); REQUIRE (status, "missing FPA.RA");
+    double DEC = psMetadataLookupF64 (&status, concepts, "FPA.DEC"); REQUIRE (status, "missing FPA.DEC");
+    double POS = PM_RAD_DEG * psMetadataLookupF64 (&status, concepts, "FPA.POSANGLE"); REQUIRE (status, "missing FPA.POSANGLE");
+    // double ROT = psMetadataLookupF64 (&status, concepts, "FPA.ROTANGLE"); REQUIRE (status, "missing FPA.ROTANGLE");
+
+    // get projection scale; center is supplied
+    float Xs = psMetadataLookupF32(&status, file->fpa->concepts, "XSCALE") * PM_RAD_DEG; REQUIRE (status, "missing XSCALE");
+    float Ys = psMetadataLookupF32(&status, file->fpa->concepts, "YSCALE") * PM_RAD_DEG; REQUIRE (status, "missing YSCALE");
+
+    // allocate a new toSky projection using the reported position
+    psFree (file->fpa->toSky);
+    file->fpa->toSky = psProjectionAlloc (RA, DEC, Xs, Ys, PS_PROJ_DIS);
+
+    // get boresite correction terms.  RX,RY,To,Po define an ellipse along which the boresite travels
+    double Xo = psMetadataLookupF32(&status, file->fpa->concepts, "BORE_X0"); REQUIRE (status, "missing ");
+    double Yo = psMetadataLookupF32(&status, file->fpa->concepts, "BORE_Y0"); REQUIRE (status, "missing ");
+    double RX = psMetadataLookupF32(&status, file->fpa->concepts, "BORE_RX"); REQUIRE (status, "missing ");
+    double RY = psMetadataLookupF32(&status, file->fpa->concepts, "BORE_RY"); REQUIRE (status, "missing ");
+    double To = psMetadataLookupF32(&status, file->fpa->concepts, "BORE_T0"); REQUIRE (status, "missing ");
+    double Po = psMetadataLookupF32(&status, file->fpa->concepts, "BORE_P0"); REQUIRE (status, "missing ");
+
+    // the true rotation of the instrument is POSANGLE - POS_ZERO
+    double PosZero = PM_RAD_DEG * psMetadataLookupF32(&status, file->fpa->concepts, "POS_ZERO"); REQUIRE (status, "missing POS_ZERO");
+    char *refChip  = psMetadataLookupStr(&status, file->fpa->concepts, "REF_CHIP"); REQUIRE (status, "missing REF_CHIP");
+
+    // apply true posangle = -(POS - POS_ZERO)
+    psPlaneTransform *fromTPA = psPlaneTransformRotate (NULL, file->fpa->fromTPA, (POS - PosZero));
+    psFree (file->fpa->fromTPA);
+    file->fpa->fromTPA = fromTPA;
+
+    psRegion *region = pmAstromFPAExtent (file->fpa);
+    psFree (file->fpa->toTPA);
+    file->fpa->toTPA = psPlaneTransformInvert(NULL, file->fpa->fromTPA, *region, 50);
+
+    // current position of the nominal boresite in refChip coordinates
+    double X = Xo + RX*cos(POS - To)*cos(Po) + RY*sin(POS - To)*sin(Po);
+    double Y = Yo + RY*sin(POS - To)*cos(Po) - RX*cos(POS - To)*sin(Po);
+
+    // get reference chip from name
+    pmChip *chip = pmConceptsChipFromName (file->fpa, refChip);
+    if (!chip) psAbort ("invalid chip name for reference");
+
+    psPlane *boreCH = psPlaneAlloc();
+    psPlane *boreFP = psPlaneAlloc();
+    psPlane *boreTP = psPlaneAlloc();
+    psSphere *boreSky = psSphereAlloc();
+
+    // find the true RA,DEC coord of the mirror of the reported boresite
+    boreCH->x = -X;
+    boreCH->y = -Y;
+    psPlaneTransformApply (boreFP, chip->toFPA, boreCH);
+    psPlaneTransformApply (boreTP, file->fpa->toTPA, boreFP);
+    psDeproject (boreSky, boreTP, file->fpa->toSky);
+
+    // modify the projection to account for offset between true and reported boresite
+    file->fpa->toSky->R = boreSky->r;
+    file->fpa->toSky->D = boreSky->d;
+
+    psFree (boreCH);
+    psFree (boreFP);
+    psFree (boreTP);
+    psFree (boreSky);
+
+    psFree (region);
+    return (true);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryTable.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryTable.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryTable.h	(revision 22158)
@@ -0,0 +1,43 @@
+/* @file  pmAstrometryTable.h
+ * @brief Astrometry table I/O functions
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-12-22 17:53:27 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_ASTROMETRY_TABLE_H
+#define PM_ASTROMETRY_TABLE_H
+
+/// @addtogroup Astrometry
+/// @{
+
+bool pmAstromCheckDataStatusForView (const pmFPAview *view, pmFPAfile *file);
+bool pmAstromCheckDataStatusForFPA (const pmFPA *fpa);
+bool pmAstromCheckDataStatusForChip (const pmChip *chip);
+
+bool pmAstromWriteForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmAstromWriteFPA (pmFPAfile *file);
+bool pmAstromWritePHU (pmFPAfile *file);
+bool pmAstromWriteSky (pmFPAfile *file);
+bool pmAstromWriteTP (pmFPAfile *file);
+bool pmAstromWriteFP (pmFPAfile *file);
+bool pmAstromWriteChips (pmFPAfile *file);
+
+int pmConceptsChipNumberFromName (pmFPA *fpa, char *name);
+pmChip *pmConceptsChipFromName (pmFPA *fpa, char *name);
+
+bool pmAstromReadForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmAstromReadFPA (pmFPAfile *file);
+bool pmAstromReadPHU (pmFPAfile *file);
+bool pmAstromReadChips (pmFPAfile *file);
+bool pmAstromReadFP (pmFPAfile *file);
+bool pmAstromReadTP (pmFPAfile *file);
+bool pmAstromReadSky (pmFPAfile *file);
+
+bool pmAstromSetTP (pmFPAfile *file, psMetadata *concepts);
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryUtils.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryUtils.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryUtils.c	(revision 22158)
@@ -0,0 +1,377 @@
+/** @file  pmAstrometryUtils.c
+ *
+ *  @brief utility functions for transform and distort functions
+ *
+ *  @ingroup Astrometry
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-12-22 17:52:21 $
+ *
+ *  Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmAstrometryUtils.h"
+
+// given a 2D transformation -- L(x,y),M(x,y) -- find the coordinates x,y
+// for which L,M = 0,0. tol is the allowed error on x,y.
+psPlane *psPlaneTransformGetCenter (psPlaneTransform *trans, double tol)
+{
+
+    // crpix1,2 = X,Y(crval1,2)
+    // start with linear solution for Xo,Yo:
+    double R  = (trans->x->coeff[1][0]*trans->y->coeff[0][1] - trans->x->coeff[0][1]*trans->y->coeff[1][0]);
+    double Xo = (trans->y->coeff[0][0]*trans->x->coeff[0][1] - trans->x->coeff[0][0]*trans->y->coeff[0][1])/R;
+    double Yo = (trans->x->coeff[0][0]*trans->y->coeff[1][0] - trans->y->coeff[0][0]*trans->x->coeff[1][0])/R;
+
+    // iterate to actual solution: requires small non-linear terms
+    if (trans->x->nX > 1) {
+        psPolynomial2D *XdX = psPolynomial2D_dX(NULL, trans->x);
+        psPolynomial2D *XdY = psPolynomial2D_dY(NULL, trans->x);
+
+        psPolynomial2D *YdX = psPolynomial2D_dX(NULL, trans->y);
+        psPolynomial2D *YdY = psPolynomial2D_dY(NULL, trans->y);
+
+        psImage *Alpha = psImageAlloc (2, 2, PS_DATA_F32);
+        psVector *Beta = psVectorAlloc (2, PS_DATA_F32);
+
+        /* this loop uses the Newton-Raphson method to solve for Xo,Yo
+        * it needs the high order terms to be small 
+        * Xo,Yo are in pixels;
+        */
+        double dPos = tol + 1;
+        for (int i = 0; (dPos > tol) && (i < 20); i++) {
+            // NOTE: order for Alpha is: [y][x]
+            Alpha->data.F32[0][0] = psPolynomial2DEval (XdX, Xo, Yo);
+            Alpha->data.F32[1][0] = psPolynomial2DEval (XdY, Xo, Yo);
+            Alpha->data.F32[0][1] = psPolynomial2DEval (YdX, Xo, Yo);
+            Alpha->data.F32[1][1] = psPolynomial2DEval (YdY, Xo, Yo);
+
+            Beta->data.F32[0] = psPolynomial2DEval (trans->x, Xo, Yo);
+            Beta->data.F32[1] = psPolynomial2DEval (trans->y, Xo, Yo);
+
+            psMatrixGJSolveF32 (Alpha, Beta);
+
+            Xo -= Beta->data.F32[0];
+            Yo -= Beta->data.F32[1];
+            dPos = hypot(Beta->data.F32[0], Beta->data.F32[1]);
+        }
+        psFree (Alpha);
+        psFree (Beta);
+        psFree (XdX);
+        psFree (XdY);
+        psFree (YdX);
+        psFree (YdY);
+    }
+    psPlane *center = psPlaneAlloc ();
+    center->x = Xo;
+    center->y = Yo;
+
+    return center;
+}
+
+// convert a transformation L(x,y) to L'(x-xo,y-yo)
+psPlaneTransform *psPlaneTransformSetCenter (psPlaneTransform *output, psPlaneTransform *input, double Xo, double Yo)
+{
+
+    // validate fit order
+
+    if (output == NULL) {
+        output = psPlaneTransformAlloc(input->x->nX, input->x->nY);
+    }
+
+    /* given two equivalent polynomial representations L(x,y) = \sum_i \sum_j A_{i,j} x^i y^j
+     * we can transform L(x,y) into L'(x-xo,y-yo) by taking the derivatives of both sides and 
+     * noting that the constant term in each is the coefficient in the case of L(x,y) and is the 
+     * value of L'(-xo,-yo) in the second case.
+     */
+
+    psPolynomial2D *tmp;
+
+    psPolynomial2D *xPx = psPolynomial2DCopy (NULL, input->x);
+    psPolynomial2D *yPx = psPolynomial2DCopy (NULL, input->y);
+
+    for (int i = 0; i <= input->x->nX; i++) {
+        psPolynomial2D *xPy = psPolynomial2DCopy (NULL, xPx);
+        psPolynomial2D *yPy = psPolynomial2DCopy (NULL, yPx);
+        for (int j = 0; j <= input->x->nY; j++) {
+            output->x->coeffMask[i][j] = input->x->coeffMask[i][j];
+            output->y->coeffMask[i][j] = input->y->coeffMask[i][j];
+            output->x->coeff[i][j] = (output->x->coeffMask[i][j] & PS_POLY_MASK_SET) ? 0 : psPolynomial2DEval (xPy, Xo, Yo) / tgamma(i+1) / tgamma(j+1);
+            output->y->coeff[i][j] = (output->y->coeffMask[i][j] & PS_POLY_MASK_SET) ? 0 : psPolynomial2DEval (yPy, Xo, Yo) / tgamma(i+1) / tgamma(j+1);
+
+            // take the next derivative wrt y, catch output (is NULL on last pass)
+            tmp = psPolynomial2D_dY(NULL, xPy);
+            psFree (xPy);
+            xPy = tmp;
+            tmp = psPolynomial2D_dY(NULL, yPy);
+            psFree (yPy);
+            yPy = tmp;
+        }
+        // take the next derivative wrt x, catch output (is NULL on last pass)
+        tmp = psPolynomial2D_dX(NULL, xPx);
+        psFree (xPx);
+        xPx = tmp;
+        tmp = psPolynomial2D_dX(NULL, yPx);
+        psFree (yPx);
+        yPx = tmp;
+    }
+    return output;
+}
+
+// rotate a transformation L(x,y) by theta
+psPlaneTransform *psPlaneTransformRotate (psPlaneTransform *output, psPlaneTransform *input, double theta)
+{
+    /* given the polynomial transformations:
+     *  L(x,y) = \sum_i \sum_j A_{i,j} x^i y^j and 
+     *  M(x,y) = \sum_i \sum_j B_{i,j} x^i y^j 
+     * we can rotate L,M to L',M' by applying the rotation matrix (c,s),(-s,c).
+     * the resulting terms of L and M are:
+     * A'_{i,j} = c A_{i,j} + s B_{i,j}
+     * B'_{i,j} = c B_{i,j} - s A_{i,j}
+     */
+
+    if (output == NULL) {
+        output = psPlaneTransformAlloc(input->x->nX, input->x->nY);
+    }
+
+    float cs = cos(theta);
+    float sn = sin(theta);
+
+    for (int i = 0; i <= input->x->nX; i++) {
+        for (int j = 0; j <= input->x->nY; j++) {
+	    // XXX what about inconsistent x and y masking?
+            output->x->coeffMask[i][j] = input->x->coeffMask[i][j];
+	    output->y->coeffMask[i][j] = input->y->coeffMask[i][j];
+	    if (output->x->coeffMask[i][j]) {
+		output->x->coeff[i][j] = 0.0;
+		output->y->coeff[i][j] = 0.0;
+	    } else {
+		output->x->coeff[i][j] = cs*input->x->coeff[i][j] + sn*input->y->coeff[i][j];
+		output->y->coeff[i][j] = cs*input->y->coeff[i][j] - sn*input->x->coeff[i][j];
+	    }
+        }
+    }
+    return output;
+}
+
+// construct a psPlaneTransform which is the identify transformation
+psPlaneTransform *psPlaneTransformIdentity (int order)
+{
+
+    psPlaneTransform *transform;
+
+    if (order < 1)
+        psAbort("invalid order");
+    if (order > 3)
+        psAbort("invalid order");
+
+    // all coeffs and masks initially set to 0
+    transform = psPlaneTransformAlloc (order, order);
+
+    for (int i = 0; i <= order; i++) {
+        for (int j = 0; j <= order; j++) {
+            if (i + j > order) {
+                transform->x->coeffMask [i][j] = PS_POLY_MASK_SET;
+                transform->y->coeffMask [i][j] = PS_POLY_MASK_SET;
+            }
+        }
+    }
+    transform->x->coeff[1][0] = 1;
+    transform->y->coeff[0][1] = 1;
+    transform->x->coeffMask[1][0] = PS_POLY_MASK_NONE;
+    transform->y->coeffMask[0][1] = PS_POLY_MASK_NONE;
+
+    return transform;
+}
+
+// check that the given psPlaneTransform is the identity * (Xs,Ys)
+bool psPlaneTransformIsDiagonal (psPlaneTransform *transform)
+{
+
+    int order;
+    bool status;
+
+    // we currently only support up to 3rd order polynomials
+    if (transform->x->nX < 1)
+        return false;
+    if (transform->x->nY < 1)
+        return false;
+    if (transform->y->nX < 1)
+        return false;
+    if (transform->y->nY < 1)
+        return false;
+
+    if (transform->x->nX != transform->x->nY)
+        return false;
+    if (transform->y->nX != transform->y->nY)
+        return false;
+
+    // these are not actually valid tests
+    if (transform->x->nX > 3)
+        return false;
+    if (transform->x->nY > 3)
+        return false;
+    if (transform->y->nX > 3)
+        return false;
+    if (transform->y->nY > 3)
+        return false;
+
+    status = true;
+    order = transform->x->nX;
+    for (int i = 0; i <= order; i++) {
+        for (int j = 0; j <= order; j++) {
+            if (i + j > order) {
+                // high-order cross terms must be masked (eg, x^3 y^2)
+                status &= (transform->x->coeffMask[i][j] & PS_POLY_MASK_SET);
+            } else {
+                status &= !(transform->x->coeffMask[i][j] & PS_POLY_MASK_SET);
+                if ((i == 1) && (i + j == 1)) {
+                    // linear, diagonal terms must be non-zero
+                    status &= (fabs(transform->x->coeff[i][j]) > FLT_EPSILON);
+                } else {
+                    // non-linear and off-diagonal terms must be 0 (eg, x^2, x y)
+                    status &= (fabs(transform->x->coeff[i][j]) < FLT_EPSILON);
+                }
+            }
+        }
+    }
+
+    order = transform->y->nX;
+    for (int i = 0; i <= order; i++) {
+        for (int j = 0; j <= order; j++) {
+            if (i + j > order) {
+                // high-order cross terms must be masked (eg, x^3 y^2)
+                status &= (transform->y->coeffMask[i][j] & PS_POLY_MASK_SET);
+            } else {
+                status &= !(transform->y->coeffMask[i][j] & PS_POLY_MASK_SET);
+                if ((j == 1) && (i + j == 1)) {
+                    // linear, diagonal terms must be 1.0
+                    status &= (fabs(transform->y->coeff[i][j]) > FLT_EPSILON);
+                } else {
+                    // non-linear and off-diagonal terms must be 0 (eg, x^2, x y)
+                    status &= (fabs(transform->y->coeff[i][j]) < FLT_EPSILON);
+                }
+            }
+        }
+    }
+    return status;
+}
+
+// construct a psPlaneDistort which is the identify transformation
+psPlaneDistort *psPlaneDistortIdentity (int order)
+{
+
+    psPlaneDistort *distort;
+
+    if (order < 1)
+        psAbort("invalid order");
+    if (order > 3)
+        psAbort("invalid order");
+
+    // all coeffs and masks initially set to 0
+    distort = psPlaneDistortAlloc (order, order, 0, 0);
+
+    for (int i = 0; i <= order; i++) {
+        for (int j = 0; j <= order; j++) {
+            if (i + j > order) {
+                distort->x->coeffMask [i][j][0][0] = PS_POLY_MASK_SET;
+                distort->y->coeffMask [i][j][0][0] = PS_POLY_MASK_SET;
+            }
+        }
+    }
+    distort->x->coeff[1][0][0][0] = 1;
+    distort->y->coeff[0][1][0][0] = 1;
+
+    return distort;
+}
+
+// check that the given psPlaneDistort is the identity * (Xs,Ys)
+bool psPlaneDistortIsDiagonal (psPlaneDistort *distort)
+{
+
+    int order;
+    bool status;
+
+    // we currently only support up to 3rd order polynomials
+    if (distort->x->nX < 1)
+        return false;
+    if (distort->x->nY < 1)
+        return false;
+    if (distort->y->nX < 1)
+        return false;
+    if (distort->y->nY < 1)
+        return false;
+
+    if (distort->x->nX > 3)
+        return false;
+    if (distort->x->nY > 3)
+        return false;
+    if (distort->y->nX > 3)
+        return false;
+    if (distort->y->nY > 3)
+        return false;
+
+    if (distort->x->nZ > 0)
+        return false;
+    if (distort->x->nT > 0)
+        return false;
+    if (distort->y->nZ > 0)
+        return false;
+    if (distort->y->nT > 0)
+        return false;
+
+    if (distort->x->nX != distort->x->nY)
+        return false;
+    if (distort->y->nX != distort->y->nY)
+        return false;
+
+    status = true;
+    order = distort->x->nX;
+    for (int i = 0; i <= order; i++) {
+        for (int j = 0; j <= order; j++) {
+            if (i + j > order) {
+                // high-order cross terms must be masked (eg, x^3 y^2)
+                status &= (distort->x->coeffMask[i][j][0][0] & PS_POLY_MASK_SET);
+            } else {
+                status &= !(distort->x->coeffMask[i][j][0][0] & PS_POLY_MASK_SET);
+                if ((i == 1) && (i + j == 1)) {
+                    // linear, diagonal terms must be 1.0
+                    status &= (fabs(distort->x->coeff[i][j][0][0]) > FLT_EPSILON);
+                } else {
+                    // non-linear and off-diagonal terms must be 0 (eg, x^2, x y)
+                    status &= (fabs(distort->x->coeff[i][j][0][0]) < FLT_EPSILON);
+                }
+            }
+        }
+    }
+
+    order = distort->y->nX;
+    for (int i = 0; i <= order; i++) {
+        for (int j = 0; j <= order; j++) {
+            if (i + j > order) {
+                // high-order cross terms must be masked (eg, x^3 y^2)
+                status &= (distort->y->coeffMask[i][j][0][0] & PS_POLY_MASK_SET);
+            } else {
+                status &= !(distort->y->coeffMask[i][j][0][0] & PS_POLY_MASK_SET);
+                if ((j == 1) && (i + j == 1)) {
+                    // linear, diagonal terms must be 1.0
+                    status &= (fabs(distort->y->coeff[i][j][0][0]) > FLT_EPSILON);
+                } else {
+                    // non-linear and off-diagonal terms must be 0 (eg, x^2, x y)
+                    status &= (fabs(distort->y->coeff[i][j][0][0]) < FLT_EPSILON);
+                }
+            }
+        }
+    }
+    return status;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryUtils.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryUtils.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryUtils.h	(revision 22158)
@@ -0,0 +1,28 @@
+/* @file  pmAstrometryUtils.h
+ * @brief utility functions for transform and distort functions
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-12-19 18:57:05 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_ASTROMETRY_UTILS_H
+#define PM_ASTROMETRY_UTILS_H
+
+/// @addtogroup Astrometry
+/// @{
+
+psPlane *psPlaneTransformGetCenter (psPlaneTransform *trans, double tol);
+psPlaneTransform *psPlaneTransformSetCenter (psPlaneTransform *output, psPlaneTransform *input, double Xo, double Yo);
+psPlaneTransform *psPlaneTransformRotate (psPlaneTransform *output, psPlaneTransform *input, double theta);
+
+psPlaneTransform *psPlaneTransformIdentity (int order);
+psPlaneDistort *psPlaneDistortIdentity (int order);
+
+bool psPlaneTransformIsDiagonal (psPlaneTransform *transform);
+bool psPlaneDistortIsDiagonal (psPlaneDistort *distort);
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryWCS.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryWCS.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryWCS.c	(revision 22158)
@@ -0,0 +1,798 @@
+/** @file  pmAstrometryWCS.c
+ *
+ *  @brief functions to convert FITS WCS keywords to / from pmFPA structures
+ *
+ *  @ingroup Astrometry
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.27 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-03-18 18:38:14 $
+ *
+ *  Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <strings.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPAExtent.h"
+#include "pmAstrometryWCS.h"
+#include "pmAstrometryUtils.h"
+#include "pmAstrometryRegions.h"
+
+// the following functions support coordinate transformations direcly related to the FITS WCS
+// keywords.  The FITS WCS allows for only a single level of transformation, thus it is not
+// appropriate for mosaic astrometry consisting of telescope distortion plus chip terms.
+// Below, we support the Elixir convention of using two connected FITS headers to define two
+// levels of coordinate transformation.  In the pmFPA structure, the projection, distortion,
+// and FPA-to-Chip transformations are carried independently.  NOTE: The FITS WCS keywords do
+// not represent a simple polynomial.  Instead, they have no constant term, and the coordinates
+// are corrected to a reference pixel before the polynomial transformation is applied.
+
+// interpret header WCS (only handles traditional WCS for the moment)
+// pixelScale is microns per pixel
+bool pmAstromReadWCS (pmFPA *fpa, pmChip *chip, const psMetadata *header, double pixelScale)
+{
+    pmAstromWCS *wcs = pmAstromWCSfromHeader (header);
+    if (!wcs) {
+        return false;
+    }
+
+    bool status = pmAstromWCStoFPA (fpa, chip, wcs, pixelScale);
+
+    psFree (wcs);
+    return status;
+}
+
+// convert toFPA / toSky components to pmAstromWCS
+// tolerance is convergence for inversion of non-linear terms in pixels
+bool pmAstromWriteWCS (psMetadata *header, const pmFPA *fpa, const pmChip *chip, double tol)
+{
+    pmAstromWCS *wcs = pmAstromWCSfromFPA(fpa, chip, tol);
+    if (!wcs) return false;
+
+    pmAstromWCStoHeader (header, wcs);
+
+    psFree (wcs);
+    return true;
+}
+
+// interpret chip header WCS as bilevel chip components
+bool pmAstromReadBilevelChip (pmChip *chip, const psMetadata *header)
+{
+    pmAstromWCS *wcs = pmAstromWCSfromHeader (header);
+    if (!wcs) {
+        return false;
+    }
+
+    bool status = pmAstromWCSBileveltoChip (chip, wcs);
+
+    psFree (wcs);
+    return status;
+}
+
+// convert toFPA / toSky components to traditional WCS
+// we require the header to have NAXIS1,NAXIS2, the field of the FPA 
+// the center of the TPA/Sky projection is 0.5*(NAXIS1,NAXIS2)
+bool pmAstromReadBilevelMosaic (pmFPA *fpa, const psMetadata *header)
+{
+    pmAstromWCS *wcs = pmAstromWCSfromHeader (header);
+    if (!wcs) {
+        psError(PS_ERR_UNKNOWN, false, "failure to determine WCS terms from header");
+        return false;
+    }
+
+    bool status1 = false;
+    bool status2 = false;
+    int Nx = psMetadataLookupS32 (&status1, header, "NAXIS1");
+    int Ny = psMetadataLookupS32 (&status2, header, "NAXIS2");
+    if (!status1 || !status2) {
+	psFree (wcs);
+        psError(PS_ERR_UNKNOWN, false, "missing required FPA size in header");
+        return false;
+    }
+
+    psRegion region = psRegionSet (-0.5*Nx, +0.5*Nx, -0.5*Ny, +0.5*Ny);
+    bool status = pmAstromWCSBileveltoFPA (fpa, wcs, region);
+
+    psFree (wcs);
+    return status;
+}
+
+// convert chip->toFPA components to bilevel WCS
+bool pmAstromWriteBilevelChip (psMetadata *header, const pmChip *chip, double tol)
+{
+    pmAstromWCS *wcs = pmAstromWCSBilevelChipFromFPA (chip, tol);
+    pmAstromWCStoHeader (header, wcs);
+
+    psFree (wcs);
+    return true;
+}
+
+
+// convert fpa->toTPA, fpa->toSky components to bilevel WCS
+bool pmAstromWriteBilevelMosaic (psMetadata *header, const pmFPA *fpa, double tol)
+{
+    pmAstromWCS *wcs = pmAstromWCSBilevelMosaicFromFPA (fpa, tol);
+
+    // we need to specify the dimensions of the FPA
+    // if we have chips defined, we can do
+    psRegion *region = pmAstromFPAExtent (fpa);
+    int Nx = region->x1 - region->x0;
+    int Ny = region->y1 - region->y0;
+    psMetadataAddS32 (header, PS_LIST_TAIL, "NAXIS1", PS_META_REPLACE, "Mosaic Dimensions", Nx);
+    psMetadataAddS32 (header, PS_LIST_TAIL, "NAXIS2", PS_META_REPLACE, "Mosaic Dimensions", Ny);
+
+    pmAstromWCStoHeader (header, wcs);
+
+    psFree (region);
+    psFree (wcs);
+    return true;
+}
+
+// convert coordinates from chip to sky using a pmAstromWCS structure
+bool pmAstromWCStoSky (psSphere *sky, pmAstromWCS *wcs, psPlane *chip)
+{
+
+    if (chip == NULL)
+        return false;
+    if (sky == NULL)
+        return false;
+    if (wcs == NULL)
+        return false;
+
+    psPlane *Chip = psPlaneAlloc();
+    psPlane *FP = psPlaneAlloc();
+
+    Chip->x = chip->x - wcs->crpix1;
+    Chip->y = chip->y - wcs->crpix2;
+
+    psPlaneTransformApply (FP, wcs->trans, Chip);
+    psDeproject (sky, FP, wcs->toSky); // find the RA,DEC coord of the focal-plane coordinate
+
+    psFree (Chip);
+    psFree (FP);
+    return true;
+}
+
+// convert coordinates from sky to chip using a pmAstromWCS structure
+bool pmAstromWCStoChip (psPlane *chip, pmAstromWCS *wcs, psSphere *sky)
+{
+
+    if (chip == NULL)
+        return false;
+    if (sky == NULL)
+        return false;
+    if (wcs == NULL)
+        return false;
+
+    psError(PS_ERR_UNKNOWN, true, "not yet implemented: needs to invert the transformation");
+    return false;
+
+    psPlane *Chip = psPlaneAlloc();
+    psPlane *FP = psPlaneAlloc();
+
+    psProject (FP, sky, wcs->toSky); // find the RA,DEC coord of the focal-plane coordinate
+
+    // XXX I actually need the inverse of wcs->transform at this point
+    psPlaneTransformApply (Chip, wcs->trans, FP);
+
+    chip->x = Chip->x + wcs->crpix1;
+    chip->y = Chip->y + wcs->crpix2;
+
+    psFree (Chip);
+    psFree (FP);
+    return true;
+}
+
+// interpret header WCS keywords (valid for bilevel and traditional WCS)
+pmAstromWCS *pmAstromWCSfromHeader (const psMetadata *header)
+{
+    psProjectionType type;
+    bool status, pcKeys, cdKeys, isPoly;
+    char name[16]; // used to store FITS keyword below (always < 8, so 16 should be safe!)
+
+    // interpret header data, convert to crval(i), etc
+    char *ctype = psMetadataLookupPtr (&status, header, "CTYPE2");
+    if (!status) {
+        psLogMsg ("psastro", 5, "warning: no WCS metadata in header\n");
+        return NULL;
+    }
+
+    // determine projection type
+    // XXX there are two indications for higher-order terms: the type (DIS,WRP,PLY,ZPL) and
+    // the value of NPLYTERM.
+    type = psProjectTypeFromString (ctype);
+    if (type == PS_PROJ_NTYPE) {
+        psLogMsg ("psastro", 2, "warning: unknown projection type %s\n", ctype);
+        return NULL;
+    }
+
+    // what type of WCS keywords are available?
+    // XXX add check for CROTA2
+    int fitOrder = psMetadataLookupS32 (&isPoly, header, "NPLYTERM");
+    psMetadataLookupF64 (&pcKeys, header, "PC001001");
+    psMetadataLookupF64 (&cdKeys, header, "CD1_1");
+
+    if (cdKeys && pcKeys) {
+        // XXX make this an option
+        psLogMsg ("psastro", 2, "warning: both CDi_j and PC00i00j defined in headers, using PC00i00j terms\n");
+    }
+    if (!cdKeys && !pcKeys) {
+        psError(PS_ERR_UNKNOWN, true, "missing both CDi_j and PC00i00j WCS terms");
+        // XXX we could default here to RA, DEC, ROTANGLE
+        return NULL;
+    }
+    if (isPoly) {
+        if (!pcKeys) {
+            psError(PS_ERR_UNKNOWN, true, "polynomial terms defined, but missing PC00i00j WCS terms");
+            return NULL;
+        }
+        if (fitOrder == 0)
+            fitOrder = 1;
+        if ((fitOrder > 3) || (fitOrder < 1)) {
+            psError(PS_ERR_UNKNOWN, true, "NPLYTERM value undefined: %d", fitOrder);
+            return NULL;
+        }
+    } else {
+        fitOrder = 1;
+    }
+
+    pmAstromWCS *wcs = pmAstromWCSAlloc (fitOrder, fitOrder);
+
+    // construct a transformation from X,Y in pixels to L,M in pixels
+    // NOTE that the WCS keywords convert X,Y to degrees first (using cdelt1,2)
+    // and then define a transformation from degrees to degrees
+
+    wcs->crval1 = psMetadataLookupF64 (&status, header, "CRVAL1");
+    wcs->crval2 = psMetadataLookupF64 (&status, header, "CRVAL2");
+    wcs->crpix1 = psMetadataLookupF64 (&status, header, "CRPIX1");
+    wcs->crpix2 = psMetadataLookupF64 (&status, header, "CRPIX2");
+    wcs->toSky = psProjectionAlloc (wcs->crval1*PM_RAD_DEG, wcs->crval2*PM_RAD_DEG, PM_RAD_DEG, PM_RAD_DEG, type);
+    // XXX I think this is wrong for linear proj
+
+    // test the CDELTi varient
+    if (pcKeys) {
+        wcs->cdelt1 = psMetadataLookupF64 (&status, header, "CDELT1");
+        wcs->cdelt2 = psMetadataLookupF64 (&status, header, "CDELT2");
+
+        // test the CROTAi varient:
+        // XXX double check lambda..
+        double rotate = psMetadataLookupF64 (&status, header, "CROTA2");
+        if (status) {
+            wcs->trans->x->coeff[1][0] = +wcs->cdelt1 * cos(rotate*PM_RAD_DEG); // == PC1_1
+            wcs->trans->x->coeff[0][1] = -wcs->cdelt2 * sin(rotate*PM_RAD_DEG); // == PC1_2
+            wcs->trans->y->coeff[1][0] = +wcs->cdelt1 * sin(rotate*PM_RAD_DEG); // == PC2_1
+            wcs->trans->y->coeff[0][1] = +wcs->cdelt2 * cos(rotate*PM_RAD_DEG); // == PC2_2
+            return wcs;
+        }
+
+        // FITS WCS PCi,j has units of unity
+        // wcs->trans has units of degrees/pixel
+        wcs->trans->x->coeff[1][0] = wcs->cdelt1 * psMetadataLookupF64 (&status, header, "PC001001"); // == PC1_1
+        wcs->trans->x->coeff[0][1] = wcs->cdelt2 * psMetadataLookupF64 (&status, header, "PC001002"); // == PC1_2
+        wcs->trans->y->coeff[1][0] = wcs->cdelt1 * psMetadataLookupF64 (&status, header, "PC002001"); // == PC2_1
+        wcs->trans->y->coeff[0][1] = wcs->cdelt2 * psMetadataLookupF64 (&status, header, "PC002002"); // == PC2_2
+
+        if (isPoly) {
+            // Elixir-style polynomial terms
+            // XXX currently, Elixir/DVO cannot accept mixed orders
+            for (int i = 0; i <= fitOrder; i++) {
+                for (int j = 0; j <= fitOrder; j++) {
+                    if (i + j < 2)
+                        continue;
+                    if (i + j > fitOrder) {
+                        wcs->trans->x->coeffMask[i][j] = PS_POLY_MASK_SET;
+                        wcs->trans->y->coeffMask[i][j] = PS_POLY_MASK_SET;
+                        continue;
+                    }
+                    sprintf (name, "PCA1X%1dY%1d", i, j);
+                    wcs->trans->x->coeff[i][j] = pow(wcs->cdelt1, i) * pow(wcs->cdelt2, j) * psMetadataLookupF64 (&status, header, name);
+                    sprintf (name, "PCA2X%1dY%1d", i, j);
+                    wcs->trans->y->coeff[i][j] = pow(wcs->cdelt1, i) * pow(wcs->cdelt2, j) * psMetadataLookupF64 (&status, header, name);
+                }
+            }
+        }
+        return wcs;
+    }
+
+    // test the CDi_j varient
+    if (cdKeys) {
+        wcs->trans->x->coeff[1][0] = psMetadataLookupF64 (&status, header, "CD1_1"); // == PC1_1
+        wcs->trans->x->coeff[0][1] = psMetadataLookupF64 (&status, header, "CD1_2"); // == PC1_2
+        wcs->trans->y->coeff[1][0] = psMetadataLookupF64 (&status, header, "CD2_1"); // == PC2_1
+        wcs->trans->y->coeff[0][1] = psMetadataLookupF64 (&status, header, "CD2_2"); // == PC2_2
+        wcs->cdelt1 = hypot (wcs->trans->x->coeff[1][0], wcs->trans->x->coeff[0][1]);
+        wcs->cdelt2 = hypot (wcs->trans->y->coeff[1][0], wcs->trans->y->coeff[0][1]);
+        return wcs;
+    }
+    psLogMsg ("psastro", 2, "warning: missing rotation matrix?\n");
+    psFree (wcs);
+    return NULL;
+}
+
+// convert wcs transformations into header WCS keywords (only handles traditional WCS for the moment)
+// wcs->trans defines the transformation from pixels to degrees.
+// wcs->cdelt1,2 carries the original pixels scale.
+// XXX force PC00i00j to be normalized, or use cdelt1,2 to set the scale?
+// here I've chosen to force the rotation matrix to be normalized
+bool pmAstromWCStoHeader (psMetadata *header, const pmAstromWCS *wcs)
+{
+    char name[16]; // used to store FITS keyword below (always < 8, so 16 should be safe!)
+    char *type;
+
+    if (!wcs) return false;
+
+    type = psProjectTypeToString (wcs->toSky->type, "RA--");
+    psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE1", PS_META_REPLACE, "", type);
+    psFree (type);
+
+    type = psProjectTypeToString (wcs->toSky->type, "DEC-");
+    psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE2", PS_META_REPLACE, "", type);
+    psFree (type);
+
+    psMetadataAddF64 (header, PS_LIST_TAIL, "CRVAL1", PS_META_REPLACE, "", wcs->toSky->R*PS_DEG_RAD);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "CRVAL2", PS_META_REPLACE, "", wcs->toSky->D*PS_DEG_RAD);
+
+    psMetadataAddF64 (header, PS_LIST_TAIL, "CRPIX1", PS_META_REPLACE, "", wcs->crpix1);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "CRPIX2", PS_META_REPLACE, "", wcs->crpix2);
+
+    // XXX make it optional to write out CDi_j terms, or other versions
+    // apply CDELT1,2 (degrees / pixel) to yield PCi,j terms of order unity
+    double cdelt1 = wcs->cdelt1;
+    double cdelt2 = wcs->cdelt2;
+    psMetadataAddF64 (header, PS_LIST_TAIL, "CDELT1", PS_META_REPLACE, "", cdelt1);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "CDELT2", PS_META_REPLACE, "", cdelt2);
+
+    // test the PC00i00j varient:
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PC001001", PS_META_REPLACE, "", wcs->trans->x->coeff[1][0] / cdelt1); // == PC1_1
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PC001002", PS_META_REPLACE, "", wcs->trans->x->coeff[0][1] / cdelt2); // == PC1_2
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PC002001", PS_META_REPLACE, "", wcs->trans->y->coeff[1][0] / cdelt1); // == PC2_1
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PC002002", PS_META_REPLACE, "", wcs->trans->y->coeff[0][1] / cdelt2); // == PC2_2
+
+    // Elixir-style polynomial terms
+    // XXX currently, Elixir/DVO cannot accept mixed orders
+    // XXX need to respect the masks
+    // XXX is wcs->cdelt1,2 always consistent?
+    int fitOrder = wcs->trans->x->nX;
+    if (fitOrder > 1) {
+        for (int i = 0; i <= fitOrder; i++) {
+            for (int j = 0; j <= fitOrder; j++) {
+                if (i + j < 2)
+                    continue;
+                if (i + j > fitOrder)
+                    continue;
+                sprintf (name, "PCA1X%1dY%1d", i, j);
+                psMetadataAddF64 (header, PS_LIST_TAIL, name, PS_META_REPLACE, "", wcs->trans->x->coeff[i][j] / pow(cdelt1, i) / pow(cdelt2, j));
+                sprintf (name, "PCA2X%1dY%1d", i, j);
+                psMetadataAddF64 (header, PS_LIST_TAIL, name, PS_META_REPLACE, "", wcs->trans->y->coeff[i][j] / pow(cdelt1, i) / pow(cdelt2, j));
+            }
+        }
+        psMetadataAddS32 (header, PS_LIST_TAIL, "NPLYTERM", PS_META_REPLACE, "", fitOrder);
+    }
+
+    return true;
+}
+
+// interpret header WCS (only handles traditional WCS for the moment)
+// pixelScale is the pixel size in microns/pixel
+bool pmAstromWCStoFPA (pmFPA *fpa, pmChip *chip, const pmAstromWCS *wcs, double pixelScale)
+{
+    psPlaneTransform *toFPA;
+
+    // create transformation with 0,0 reference pixel and units of degrees/pixel
+    toFPA = psPlaneTransformSetCenter (NULL, wcs->trans, -wcs->crpix1, -wcs->crpix2);
+
+    // modify scale of toFPA to have units of microns/pixel
+    // cdelt1,2 has units of degree/pixel
+    for (int i = 0; i <= toFPA->x->nX; i++) {
+        for (int j = 0; j <= toFPA->x->nX; j++) {
+            toFPA->x->coeff[i][j] *= pixelScale/wcs->cdelt1;
+            toFPA->y->coeff[i][j] *= pixelScale/wcs->cdelt2;
+        }
+    }
+
+    // pdelt1,2 has units of degree/micron
+    double pdelt1 = wcs->cdelt1 / pixelScale;
+    double pdelt2 = wcs->cdelt2 / pixelScale;
+
+    // projection from TPA (linear microns) to SKY (radians)
+    psProjection *toSky = psProjectionAlloc (wcs->toSky->R, wcs->toSky->D, PM_RAD_DEG*pdelt1, PM_RAD_DEG*pdelt2, wcs->toSky->type);
+
+    if (fpa->toSky == NULL) {
+        fpa->toTPA = psPlaneTransformIdentity (1);
+        fpa->fromTPA = psPlaneTransformIdentity (1);
+        fpa->toSky = toSky;
+    } else {
+
+        // this section allows the loaded chip to be included in an fpa structure in which
+        // other chips have already been loaded (ie, the fpa->toTPA, fpa->toSky components have
+        // already been defined).  we have to adjust to match the existing transformation.
+
+        if (fpa->toTPA == NULL)
+            psAbort("projection defined, tangent-plane not defined");
+        if (fpa->fromTPA == NULL)
+            psAbort("projection defined, tangent-plane not defined");
+
+        // convert from pixels on this chip to pixels on reference chip
+        // rX has units of refpixels / pixel
+        double rX = toSky->Xs / fpa->toSky->Xs;
+        double rY = toSky->Ys / fpa->toSky->Ys;
+
+        for (int i = 0; i <= toFPA->x->nX; i++) {
+            for (int j = 0; j <= toFPA->x->nY; j++) {
+                toFPA->x->coeff[i][j] *= rX;
+                toFPA->y->coeff[i][j] *= rY;
+            }
+        }
+
+	// apply the exiting fromTPA transformation to make the new toFPA consistent with the toTPA layter
+	// XXX this only works if toTPA is at most a linear transformation
+        psPlaneTransform *toFPAnew = psPlaneTransformAlloc(toFPA->x->nX, toFPA->x->nY);
+	for (int i = 0; i <= toFPA->x->nX; i++) {
+	  for (int j = 0; j <= toFPA->x->nY; j++) {
+	    double f1 = toFPA->x->coeffMask[i][j] ? 0.0 : fpa->fromTPA->x->coeff[1][0]*toFPA->x->coeff[i][j];
+	    double f2 = toFPA->y->coeffMask[i][j] ? 0.0 : fpa->fromTPA->x->coeff[0][1]*toFPA->y->coeff[i][j];
+	    toFPAnew->x->coeff[i][j] = f1 + f2;
+
+	    double g1 = toFPA->x->coeffMask[i][j] ? 0.0 : fpa->fromTPA->y->coeff[1][0]*toFPA->x->coeff[i][j];
+	    double g2 = toFPA->y->coeffMask[i][j] ? 0.0 : fpa->fromTPA->y->coeff[0][1]*toFPA->y->coeff[i][j];
+	    toFPAnew->y->coeff[i][j] = g1 + g2;
+	  }
+	}
+	toFPAnew->x->coeff[0][0] += fpa->fromTPA->x->coeff[0][0];
+	toFPAnew->y->coeff[0][0] += fpa->fromTPA->y->coeff[0][0];
+
+	psFree (toFPA);
+	toFPA = toFPAnew;
+
+        // adjust reference pixel for new toSky reference coordinate
+        // find the FPA coordinate of 0,0 for this chip.
+        psPlane *fpOld = psPlaneAlloc();
+        psPlane *fpNew = psPlaneAlloc();
+        psPlane *tp = psPlaneAlloc();
+        psSphere *sky = psSphereAlloc();
+
+	sky->r = toSky->R;
+	sky->d = toSky->D;
+        psProject (tp, sky, fpa->toSky); // find the focal-plane coord of this RA,DEC coord using the ref chip projection
+        psPlaneTransformApply (fpOld, fpa->fromTPA, tp);
+
+	sky->r = fpa->toSky->R;
+	sky->d = fpa->toSky->D;
+        psProject (tp, sky, fpa->toSky); // find the focal-plane coord of this RA,DEC coord using the ref chip projection
+        psPlaneTransformApply (fpNew, fpa->fromTPA, tp);
+
+        toFPA->x->coeff[0][0] -= fpNew->x - fpOld->x;
+        toFPA->y->coeff[0][0] -= fpNew->y - fpOld->y;
+
+        psFree (sky);
+        psFree (tp);
+        psFree (fpOld);
+        psFree (fpNew);
+
+        psFree (toSky);
+    }
+
+    // free an existing toFPA structure
+    psFree (chip->toFPA);
+    chip->toFPA = toFPA;
+
+    // determine the inverse transformation: we need the chip pixels covered by this transform
+    psRegion *region = pmChipPixels (chip);
+
+    psFree (chip->fromFPA);
+    chip->fromFPA = psPlaneTransformInvert(NULL, chip->toFPA, *region, 50);
+    psFree (region);
+
+    // this can take a very long time...
+    while (fpa->toSky->R < 0)
+        fpa->toSky->R += 2.0*M_PI;
+    while (fpa->toSky->R > 2.0*M_PI)
+        fpa->toSky->R -= 2.0*M_PI;
+
+    psTrace ("psastro", 5, "toFPA: %f %f  (%f,%f),(%f,%f)\n",
+             chip->toFPA->x->coeff[0][0], chip->toFPA->y->coeff[0][0],
+             chip->toFPA->x->coeff[1][0], chip->toFPA->x->coeff[0][1],
+             chip->toFPA->y->coeff[1][0], chip->toFPA->y->coeff[0][1]);
+
+    psTrace ("psastro", 5, "frFPA: %f %f  (%f,%f),(%f,%f)\n",
+             chip->fromFPA->x->coeff[0][0], chip->fromFPA->y->coeff[0][0],
+             chip->fromFPA->x->coeff[1][0], chip->fromFPA->x->coeff[0][1],
+             chip->fromFPA->y->coeff[1][0], chip->fromFPA->y->coeff[0][1]);
+
+    return true;
+}
+
+// convert a pmAstromWCS structure representing a bilevel chip into corresponding chip elements
+bool pmAstromWCSBileveltoChip (pmChip *chip, const pmAstromWCS *wcs)
+{
+    /* we convert wcs->trans to toFPA, which is different from wcs->trans in 3 important ways:
+     * 1) the output is in pixel (not degrees): divide by cdelt1,2 raised to an appropriate power
+     * 2) X,Y are applied directly, without an applied Xo,Yo offset
+     * 3) there is an allowed Lo,Mo term ([0][0] coefficients)
+     */
+
+    // create transformation with 0,0 reference pixel and units of microns/pixel
+    psFree (chip->toFPA);
+    chip->toFPA = psPlaneTransformSetCenter (NULL, wcs->trans, -wcs->crpix1, -wcs->crpix2);
+
+    // determine the inverse transformation: we need the chip pixels covered by this transform
+    psRegion *region = pmChipPixels (chip);
+
+    psFree (chip->fromFPA);
+    chip->fromFPA = psPlaneTransformInvert(NULL, chip->toFPA, *region, 50);
+    psFree (region);
+
+    return true;
+}
+
+// convert a pmAstromWCS structure representing a bilevel mosaic into corresponding fpa elements
+bool pmAstromWCSBileveltoFPA (pmFPA *fpa, const pmAstromWCS *wcs, psRegion region)
+{
+    // projection from TPA (microns) to SKY (radians)
+    // cdelt1,2 has units of degrees/micron
+    fpa->toSky = psProjectionAlloc (wcs->toSky->R, wcs->toSky->D, wcs->cdelt1*PM_RAD_DEG, wcs->cdelt2*PM_RAD_DEG, wcs->toSky->type);
+
+    // create transformation with 0,0 reference pixel
+    fpa->toTPA = psPlaneTransformSetCenter (NULL, wcs->trans, -wcs->crpix1, -wcs->crpix2);
+
+    // convert fpa->toTPA to units of unity (microns/micron)
+    for (int i = 0; i <= fpa->toTPA->x->nX; i++) {
+        for (int j = 0; j <= fpa->toTPA->x->nY; j++) {
+            fpa->toTPA->x->coeff[i][j] /= wcs->cdelt1;
+            fpa->toTPA->y->coeff[i][j] /= wcs->cdelt2;
+        }
+    }
+
+    // the transformation used the region to define the inversion grid
+    // the region defines the FPA pixels covered by the tranformation
+    psFree (fpa->fromTPA);
+    fpa->fromTPA = psPlaneTransformInvert(NULL, fpa->toTPA, region, 50);
+    return true;
+}
+
+// convert toFPA / toSky components to pmAstromWCS
+// tolerance is allowed error in center solution in pixels
+pmAstromWCS *pmAstromWCSfromFPA (const pmFPA *fpa, const pmChip *chip, double tol)
+{
+    // XXX require chip->toFPA->x->nX == chip->toFPA->x->nY
+    // XXX require chip->toFPA->y->nX == chip->toFPA->y->nY
+    // XXX require chip->toFPA->x->nX == chip->toFPA->y->nX
+    // XXX require chip->toFPA->nX == 1,2,3
+
+    // technically, we can have a plate scale here (fpa->toTPA:dx,dy != 1)
+    // XXX not really: toTPA needs to have unity scale for distortion fitting function
+    // if (!psPlaneTransformIsDiagonal (fpa->toTPA))
+    // psAbort("invalid TPA transformation");
+
+    // create a temporary transform which combines toTPA and toFPA.  allow toTPA to have 0th
+    // and 1st order terms
+    
+    // XXX require fpa->toTPA->x->nX == fpa->toTPA->x->nY
+    // XXX require fpa->toTPA->y->nX == fpa->toTPA->y->nY
+    // XXX require fpa->toTPA->x->nX == fpa->toTPA->y->nX
+    // XXX require fpa->toTPA->x->coeffMask[1][1]
+    // XXX require fpa->toTPA->y->coeffMask[1][1]
+    // XXX require fpa->toTPA->nX == 1
+
+    psPlaneTransform *toTPA = psPlaneTransformAlloc(chip->toFPA->x->nX, chip->toFPA->x->nY);
+
+    for (int i = 0; i <= toTPA->x->nX; i++) {
+	for (int j = 0; j <= toTPA->x->nY; j++) {
+	    double f1 = chip->toFPA->x->coeffMask[i][j] ? 0.0 : fpa->toTPA->x->coeff[1][0]*chip->toFPA->x->coeff[i][j];
+	    double f2 = chip->toFPA->y->coeffMask[i][j] ? 0.0 : fpa->toTPA->x->coeff[0][1]*chip->toFPA->y->coeff[i][j];
+	    toTPA->x->coeff[i][j] = f1 + f2;
+
+	    double g1 = chip->toFPA->x->coeffMask[i][j] ? 0.0 : fpa->toTPA->y->coeff[1][0]*chip->toFPA->x->coeff[i][j];
+	    double g2 = chip->toFPA->y->coeffMask[i][j] ? 0.0 : fpa->toTPA->y->coeff[0][1]*chip->toFPA->y->coeff[i][j];
+	    toTPA->y->coeff[i][j] = g1 + g2;
+	}
+    }
+    toTPA->x->coeff[0][0] += fpa->toTPA->x->coeff[0][0];
+    toTPA->y->coeff[0][0] += fpa->toTPA->y->coeff[0][0];
+
+    pmAstromWCS *wcs = pmAstromWCSAlloc(toTPA->x->nX, toTPA->x->nY);
+
+    // convert projection from FPA to SKY into wcs projection (degrees to radians)
+    wcs->toSky = psProjectionAlloc (fpa->toSky->R, fpa->toSky->D, PM_RAD_DEG, PM_RAD_DEG, fpa->toSky->type);
+    wcs->crval1 = fpa->toSky->R*PS_DEG_RAD;
+    wcs->crval2 = fpa->toSky->D*PS_DEG_RAD;
+
+    // given transformation, solve for coordinates which yields output coordinates of 0,0
+    psPlane *center = psPlaneTransformGetCenter (toTPA, tol);
+
+    // create wcs transform from toFPA, resulting transformation has units of microns/pixel
+    // adjust wcs transform to use center as reference coordinate
+    psPlaneTransformSetCenter (wcs->trans, toTPA, center->x, center->y);
+
+    // calculated center is crpix1,2
+    wcs->crpix1 = center->x;
+    wcs->crpix2 = center->y;
+    psFree (center);
+
+    // pdelt1,2 has units of degrees/micron
+    double pdelt1 = fpa->toSky->Xs * PS_DEG_RAD;
+    double pdelt2 = fpa->toSky->Ys * PS_DEG_RAD;
+
+    // convert wcs->trans to a matrix with units of degrees/pixel
+    for (int i = 0; i <= wcs->trans->x->nX; i++) {
+        for (int j = 0; j <= wcs->trans->x->nY; j++) {
+            wcs->trans->x->coeff[i][j] *= pdelt1;
+            wcs->trans->y->coeff[i][j] *= pdelt2;
+        }
+    }
+
+    // cdelt1,2 has units of degrees/pixel
+    wcs->cdelt1 = hypot (wcs->trans->x->coeff[1][0], wcs->trans->x->coeff[0][1]);
+    wcs->cdelt2 = hypot (wcs->trans->y->coeff[1][0], wcs->trans->y->coeff[0][1]);
+
+    psFree (toTPA);
+
+    return wcs;
+}
+
+/* the bilevel astrometry description consists of a polynomial warping from
+   chip coordinates to FPA coordinates (coords->ctype = LIN---WRP), followed
+   by a polynomial representation of the telescope distortion + the projection
+   (coords->ctype = RA---DIS).
+*/
+
+// convert the chip-level toFPA to a wcs polynomial transformation
+pmAstromWCS *pmAstromWCSBilevelChipFromFPA (const pmChip *chip, double tol)
+{
+    // XXX require chip->toFPA->x->nX == chip->toFPA->x->nY
+    // XXX require chip->toFPA->y->nX == chip->toFPA->y->nY
+    // XXX require chip->toFPA->x->nX == chip->toFPA->y->nX
+    // XXX require chip->toFPA->nX == 1,2,3
+
+    // convert chip->toFPA to wcs format (WRP)
+    pmAstromWCS *wcs = pmAstromWCSAlloc(chip->toFPA->x->nX, chip->toFPA->x->nY);
+
+    // Chip to FPA transformation is a Cartesian 'projection'
+    // reference pixel for FPA is 0.0, 0.0
+    wcs->toSky = psProjectionAlloc (0.0, 0.0, 1.0, 1.0, PS_PROJ_WRP);
+    wcs->crval1 = 0.0;
+    wcs->crval2 = 0.0;
+
+    // given transformation, solve for coordinates which yields output coordinates of 0,0
+    psPlane *center = psPlaneTransformGetCenter (chip->toFPA, tol);
+
+    // adjust wcs transform to use center as reference coordinate
+    // resulting transformation has units of microns/pixel
+    psPlaneTransformSetCenter (wcs->trans, chip->toFPA, center->x, center->y);
+
+    // calculated center is crpix1,2
+    wcs->crpix1 = center->x;
+    wcs->crpix2 = center->y;
+    psFree (center);
+
+    // output coordinates are in microns : CDELT1,2 has units of microns/pixel
+    wcs->cdelt1 = hypot (wcs->trans->x->coeff[1][0], wcs->trans->x->coeff[0][1]);
+    wcs->cdelt2 = hypot (wcs->trans->y->coeff[1][0], wcs->trans->y->coeff[0][1]);
+
+    return wcs;
+}
+
+// convert the fpa-level toTPA, toSky to a wcs polynomial transformation
+pmAstromWCS *pmAstromWCSBilevelMosaicFromFPA (const pmFPA *fpa, double tol)
+{
+    // XXX require fpa->toTPA->x->nX == fpa->toTPA->x->nY
+    // XXX require fpa->toTPA->y->nX == fpa->toTPA->y->nY
+    // XXX require fpa->toTPA->x->nX == fpa->toTPA->y->nX
+    // XXX require fpa->toTPA->nX == 1,2,3
+    // XXX require fpa->toSky->type == PS_PROJ_TAN
+
+    // convert fpa->toTPA + fpa->toSky to wcs format (DIS)
+    pmAstromWCS *wcs = pmAstromWCSAlloc(fpa->toTPA->x->nX, fpa->toTPA->x->nY);
+
+    // convert projection from TPA to SKY into wcs projection (degrees to radians)
+    wcs->toSky = psProjectionAlloc (fpa->toSky->R, fpa->toSky->D, PM_RAD_DEG, PM_RAD_DEG, PS_PROJ_DIS);
+    wcs->crval1 = fpa->toSky->R*PS_DEG_RAD;
+    wcs->crval2 = fpa->toSky->D*PS_DEG_RAD;
+
+    // given transformation, solve for coordinates which yields output coordinates of 0,0
+    psPlane *center = psPlaneTransformGetCenter (fpa->toTPA, tol);
+
+    // adjust wcs transform to use center as reference coordinate
+    // resulting transformation has units of unity (microns/micron)
+    psPlaneTransformSetCenter (wcs->trans, fpa->toTPA, center->x, center->y);
+
+    // calculated center is crpix1,2
+    wcs->crpix1 = center->x;
+    wcs->crpix2 = center->y;
+    psFree (center);
+
+    // pdelt1,2 has units of degrees/micron
+    double pdelt1 = fpa->toSky->Xs * PS_DEG_RAD;
+    double pdelt2 = fpa->toSky->Ys * PS_DEG_RAD;
+
+    // convert wcs->trans to units of degree/micron
+    for (int i = 0; i <= wcs->trans->x->nX; i++) {
+        for (int j = 0; j <= wcs->trans->x->nY; j++) {
+            wcs->trans->x->coeff[i][j] *= pdelt1;
+            wcs->trans->y->coeff[i][j] *= pdelt2;
+        }
+    }
+
+    // cdelt1,2 has units of degrees/micron
+    wcs->cdelt1 = hypot (wcs->trans->x->coeff[1][0], wcs->trans->x->coeff[0][1]);
+    wcs->cdelt2 = hypot (wcs->trans->y->coeff[1][0], wcs->trans->y->coeff[0][1]);
+
+    return wcs;
+}
+
+static void pmAstromWCSFree (pmAstromWCS *wcs)
+{
+
+    if (!wcs)
+        return;
+    psFree (wcs->trans);
+    psFree (wcs->toSky);
+}
+
+pmAstromWCS *pmAstromWCSAlloc (int nXorder, int nYorder)
+{
+
+    pmAstromWCS *wcs = (pmAstromWCS *) psAlloc(sizeof(pmAstromWCS));
+    psMemSetDeallocator(wcs, (psFreeFunc) pmAstromWCSFree);
+
+    wcs->trans = psPlaneTransformAlloc (nXorder, nYorder);
+    wcs->toSky = NULL;
+
+    memset (wcs->ctype1, 0, PM_ASTROM_WCS_TYPE_SIZE);
+    memset (wcs->ctype2, 0, PM_ASTROM_WCS_TYPE_SIZE);
+    return wcs;
+}
+
+/*****
+ 
+For mosaic astrometry, we need to have a starting set of projection terms in which the
+chip-to-FPA terms result in a fixed physical unit on the focal plane (eg, pixels or
+microns).  This set of projections, coupled with an identity toTPA (ie, no distortion) will
+result in substantial errors between the observed and predicted star positions on the focal
+plane: this is the measurement of the optical distortion in the camera.  At the same time,
+we need to carry around the transformations which allow us to make an accurate calculation
+of the position of the stars based on the input (per-chip) astrometry.  These
+transformations will allow us to match the raw and ref stars robustly.  To convert the
+per-chip astrometry (which may have been calculated with a different plate scale for each
+chip) to a collection of astrometry terms for chips in a single mosaic, we need to adjust
+the chip-to-FPA scaling (eg, pc11) to match the variations in the effective plate scale for
+each chip (eg, cdelt1).  Thus, we need to carry around both the
+ 
+*****/
+
+/* discussion of the coord transformations:
+   X,Y: coord on a chip in pixels
+   L,M: coord on the focal plane (pixels)
+   P,Q: coord in the tangent plane (microns or mm?)
+   R,D: coord on the sky 
+ 
+   this function creates WCS terms which convert directly from chip to sky.
+   this function requires a linear, unrotated toTPA distortion term
+   toTPA->x,y->coeff[1][0],[0][1] defines the detector scale (microns / pixel)
+   tpSky->Xs,Ys defines the plate scale (radians / micron)
+*/
+
+/* at this point, we have extracted from the header the WCS terms in the form of a polynomial,
+ * wcs->trans, which will convert X,Y in pixels to L,M in degrees.  we also have the following 
+ * elements defined:
+ * type (projection type)
+ * crval1,2 (in RA,DEC degrees)
+ * crpix1,2 
+ * cdelt1,2 (in degrees / pixel)
+ * pixelScale (microns / pixel)
+ * 
+ * now we convert wcs->trans to toFPA, which is different from wcs->trans in 3 important ways:
+ * 1) the output is in microns (not degrees): divide by cdelt1,2
+ * 2) X,Y are applied directly, without an applied Xo,Yo offset
+ * 3) there is an allowed Lo,Mo term ([0][0] coefficients)
+ */
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryWCS.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryWCS.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/astrom/pmAstrometryWCS.h	(revision 22158)
@@ -0,0 +1,77 @@
+/* @file  pmAstrometryDistortion.h
+ * @brief functions to convert FITS WCS keywords to / from pmFPA structures
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-03-21 22:00:49 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_ASTROMETRY_WCS_H
+#define PM_ASTROMETRY_WCS_H
+
+/// @addtogroup Astrometry
+/// @{
+
+#define PM_ASTROM_WCS_TYPE_SIZE 80
+typedef struct
+{
+    char ctype1[PM_ASTROM_WCS_TYPE_SIZE];
+    char ctype2[PM_ASTROM_WCS_TYPE_SIZE];
+    double crval1, crval2;
+    double crpix1, crpix2;
+    double cdelt1, cdelt2;
+    psProjection *toSky;
+    psPlaneTransform *trans;
+}
+pmAstromWCS;
+
+// support function for the pmAstromWCS representation
+pmAstromWCS *pmAstromWCSAlloc (int nXorder, int nYorder);
+bool pmAstromWCStoSky (psSphere *sky, pmAstromWCS *wcs, psPlane *chip);
+bool pmAstromWCStoChip (psPlane *chip, pmAstromWCS *wcs, psSphere *sky);
+
+// read and write the pmAstromWCS representation to the header
+bool pmAstromWCStoHeader (psMetadata *header, const pmAstromWCS *wcs);
+pmAstromWCS *pmAstromWCSfromHeader (const psMetadata *header);
+
+// convert from wcs terms to chip->toFPA, fpa->toSky,toTPA terms
+bool pmAstromWCSBileveltoChip (pmChip *chip, const pmAstromWCS *wcs);
+bool pmAstromWCSBileveltoFPA (pmFPA *fpa, const pmAstromWCS *wcs, psRegion region);
+
+// convert from chip->toFPA, fpa->toSky,toTPA terms to wcs terms
+pmAstromWCS *pmAstromWCSBilevelChipFromFPA (const pmChip *chip, double tol);
+pmAstromWCS *pmAstromWCSBilevelMosaicFromFPA (const pmFPA *fpa, double tol);
+
+// convert the pmAstromWCS representation to the FPA representation
+bool pmAstromWCStoFPA (pmFPA *fpa, pmChip *chip, const pmAstromWCS *wcs, double plateScale);
+pmAstromWCS *pmAstromWCSfromFPA (const pmFPA *fpa, const pmChip *chip, double tol);
+
+// read wcs terms from the supplied header into the fpa hierarchy components
+bool pmAstromReadWCS (pmFPA *fpa, pmChip *chip, const psMetadata *header, double plateScale);
+
+// write the wcs terms from the fpa hierarchy components into the supplied header
+// tol is the convergence tolerance for the non-linear solution to the reference pixel
+bool pmAstromWriteWCS (psMetadata *header, const pmFPA *fpa, const pmChip *chip, double tol);
+
+bool pmAstromReadBilevelChip (pmChip *chip, const psMetadata *header);
+bool pmAstromReadBilevelMosaic (pmFPA *fpa, const psMetadata *header);
+
+bool pmAstromWriteBilevelChip (psMetadata *header, const pmChip *chip, double tol);
+bool pmAstromWriteBilevelMosaic (psMetadata *header, const pmFPA *fpa, double tol);
+
+// move to pslib
+psPlaneDistort *psPlaneDistortIdentity (int order);
+bool psPlaneDistortIsDiagonal (psPlaneDistort *distort);
+
+# define PM_DEG_RAD 57.295779513082322
+# define PM_RAD_DEG  0.017453292519943
+
+/// @}
+#endif // PM_ASTROMETRY_WCS_H
+
+/*
+ * the wcs->trans component defines a polynomial which converts (x-crpix1),(y-crpix2) to
+ * L,M in degrees
+ */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/.cvsignore	(revision 22158)
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/Makefile.am	(revision 22158)
@@ -0,0 +1,59 @@
+noinst_LTLIBRARIES = libpsmodulescamera.la
+
+libpsmodulescamera_la_CPPFLAGS = $(SRCINC) $(PSMODULES_CFLAGS)
+libpsmodulescamera_la_LDFLAGS  = -release $(PACKAGE_VERSION)
+libpsmodulescamera_la_SOURCES  = \
+	pmFPA.c \
+	pmFPACalibration.c \
+	pmFPAConstruct.c \
+	pmFPACopy.c \
+	pmFPAHeader.c \
+	pmFPAMaskWeight.c \
+	pmFPAMosaic.c \
+	pmFPARead.c \
+	pmFPAUtils.c \
+	pmFPAWrite.c \
+	pmHDU.c \
+	pmHDUUtils.c \
+	pmHDUGenerate.c \
+	pmFPA_JPEG.c \
+	pmFPAview.c \
+	pmFPAfile.c \
+	pmFPAfileDefine.c \
+	pmFPAfileIO.c \
+	pmFPAfileFitsIO.c \
+	pmFPAFlags.c \
+	pmFPALevel.c \
+	pmFPAExtent.c \
+	pmCellSquish.c \
+	pmReadoutStack.c \
+	pmReadoutFake.c
+
+pkginclude_HEADERS = \
+	pmFPA.h \
+	pmFPACalibration.h \
+	pmFPAConstruct.h \
+	pmFPACopy.h \
+	pmFPAHeader.h \
+	pmFPAMaskWeight.h \
+	pmFPAMosaic.h \
+	pmFPARead.h \
+	pmFPAUtils.h \
+	pmFPAWrite.h \
+	pmHDU.h \
+	pmHDUUtils.h \
+	pmHDUGenerate.h \
+	pmFPA_JPEG.h \
+	pmFPAview.h \
+	pmFPAfile.h \
+	pmFPAfileDefine.h \
+	pmFPAfileIO.h \
+	pmFPAfileFitsIO.h \
+	pmFPAFlags.h \
+	pmFPALevel.h \
+	pmFPAExtent.h \
+	pmCellSquish.h \
+	pmReadoutStack.h \
+	pmReadoutFake.h
+
+CLEANFILES = *~
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmCellSquish.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmCellSquish.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmCellSquish.c	(revision 22158)
@@ -0,0 +1,176 @@
+#include <stdio.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmShifts.h"
+#include "pmCellSquish.h"
+
+// Comparing values to get ranges
+#define COMPARE_SMALLER(TARGET, SOURCE) if ((SOURCE) < (TARGET)) (TARGET) = (SOURCE);
+#define COMPARE_BIGGER(TARGET, SOURCE) if ((SOURCE) > (TARGET)) (TARGET) = (SOURCE);
+
+
+bool pmCellSquish(pmCell *cell, psMaskType maskVal, bool useShifts)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_ARRAY_NON_NULL(cell->readouts, false);
+    psArray *readouts = cell->readouts; // Array of readouts
+    long numReadouts = readouts->n; // Number of readouts
+
+    if (numReadouts <= 1) {
+        // We squished everything there was to squish
+        return true;
+    }
+
+    pmShifts *shifts = NULL;                   // Orthogonal transfer shifts
+    if (useShifts) {
+        bool mdok;                      // Status of MD lookup
+        shifts = psMetadataLookupPtr(&mdok, cell->analysis, PM_SHIFTS_TABLE_NAME);
+        if (!mdok || !shifts) {
+            psError(PS_ERR_UNEXPECTED_NULL, true, "Squishing with shifts requested, but no shifts found.");
+            return false;
+        }
+        if (shifts->num != numReadouts) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    "Number of shifts (%ld) does not match number of readouts (%ld).",
+                    shifts->num, numReadouts);
+            return false;
+        }
+    }
+
+    // First pass to get the bounds, make sure everything is legit.
+    int xMin = 0, xMax = 0, yMin = 0, yMax = 0; // Bounds of the squish
+    bool valid = false;                 // Do we have a valid readout?
+    int col0 = 0, row0 = 0, numCols = 0, numRows = 0;// Window parameters for the readouts
+    int xShift = 0, yShift = 0;         // Shift due to orthogonal transfer, to be applied
+    if (useShifts && shifts->xyRelative) {
+        // Correct for final shift, to put in correct frame for the image that is read out
+        xShift = - shifts->x->data.S32[shifts->num - 1];
+        yShift = - shifts->y->data.S32[shifts->num - 1];
+    }
+    for (long i = 0; i < numReadouts; i++) {
+        // Add in the shift
+        if (useShifts) {
+            if (shifts->xyRelative) {
+                // Need to accumulate shift
+                xShift += shifts->x->data.S32[i];
+                yShift += shifts->y->data.S32[i];
+            } else {
+                // Correct for final shift, to put in correct frame for the image that is read out
+                xShift = shifts->x->data.S32[i] - shifts->x->data.S32[shifts->num - 1];
+                yShift = shifts->y->data.S32[i] - shifts->y->data.S32[shifts->num - 1];
+            }
+        }
+
+        pmReadout *readout = readouts->data[i]; // Readout of interest
+        if (!readout || !readout->image) {
+            continue;
+        }
+
+        if (!valid) {
+            valid = true;
+
+            col0 = readout->col0;
+            row0 = readout->row0;
+            numCols = readout->image->numCols;
+            numRows = readout->image->numRows;
+
+            if (useShifts) {
+                xMin = col0;
+                xMax = col0 + numCols;
+                yMin = row0;
+                yMax = row0 + numRows;
+            }
+        } else {
+            if (readout->col0 != col0 || readout->row0 != row0 ||
+                readout->image->numCols != numCols || readout->image->numRows != numRows) {
+                // Everything should have the same window because we've read it in from an image cube
+                psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                        "Readout window [%d:%d,%d:%d] doesn't match canonical window [%d:%d,%d:%d]",
+                        readout->col0, readout->col0 + readout->image->numCols,
+                        readout->row0, readout->row0 + readout->image->numRows,
+                        col0, col0 + numCols, row0, row0 + numRows);
+                return false;
+            }
+
+            if (useShifts) {
+                // If there is shifting, the actual window may change
+                int xMinTest = readout->col0 + xShift; // Minimum x value
+                int xMaxTest = readout->col0 + readout->image->numCols + xShift; // Maximum x value
+                int yMinTest = readout->row0 + yShift; // Minimum y value
+                int yMaxTest = readout->row0 + readout->image->numRows + yShift; // Maximum y value
+                COMPARE_SMALLER(xMin, xMinTest);
+                COMPARE_BIGGER(xMax, xMaxTest);
+                COMPARE_SMALLER(yMin, yMinTest);
+                COMPARE_BIGGER(yMax, yMaxTest);
+            }
+        }
+    }
+
+    if (useShifts) {
+        // Size of combined image, after shifts applied
+        numCols = xMax - xMin + 1;
+        numRows = yMax - yMin + 1;
+    }
+    psImage *squishImage = psImageAlloc(numCols, numRows, PS_TYPE_F32); // Squished image
+    psImageInit(squishImage, 0.0);
+    psImage *squishMask = psImageAlloc(numCols, numRows, PS_TYPE_MASK); // Squished mask
+    psImageInit(squishMask, 0);
+
+    // Second pass to do the squish
+    xShift = yShift = 0;                // Reset the accumulated shifts
+    if (useShifts && shifts->xyRelative) {
+        // Correct for final shift, to put in correct frame for the image that is read out
+        xShift = - shifts->x->data.S32[shifts->num - 1];
+        yShift = - shifts->y->data.S32[shifts->num - 1];
+    }
+    for (long i = 0; i < numReadouts; i++) {
+        if (useShifts) {
+            if (shifts->xyRelative) {
+                // Need to accumulate shift
+                xShift += shifts->x->data.S32[i];
+                yShift += shifts->y->data.S32[i];
+            } else {
+                // Correct for final shift, to put in correct frame for the image that is read out
+                xShift = shifts->x->data.S32[i] - shifts->x->data.S32[shifts->num - 1];
+                yShift = shifts->y->data.S32[i] - shifts->y->data.S32[shifts->num - 1];
+            }
+        }
+
+        pmReadout *readout = readouts->data[i]; // Readout of interest
+        if (!readout || !readout->image) {
+            continue;
+        }
+
+        int xOffset = xMin - readout->col0; // Offset to squished readout in x
+        int yOffset = yMin - readout->row0; // Offset to squished readout in y
+        if (useShifts) {
+            xOffset += xShift;
+            yOffset += yShift;
+        }
+
+        psImage *image = readout->image; // The image of interest
+        psImage *mask = readout->mask; // The mask of interest
+        for (int y = 0; y < readout->image->numRows; y++) {
+            int ySquish = y + yOffset; // Position on squished readout in y
+            for (int x = 0; x < readout->image->numCols; x++) {
+                int xSquish = x + xOffset; // Position on squished readout in x
+                squishImage->data.F32[ySquish][xSquish] += image->data.F32[y][x];
+                if (mask) {
+                    squishMask->data.PS_TYPE_MASK_DATA[ySquish][xSquish] |= mask->data.U8[y][x] & maskVal;
+                }
+            }
+        }
+    }
+
+    pmCellFreeReadouts(cell);
+    pmReadout *squishRO = pmReadoutAlloc(cell); // New readout to hold squished image
+    squishRO->image = squishImage;
+    squishRO->mask = squishMask;
+    squishRO->row0 = yMin;
+    squishRO->col0 = xMin;
+    psFree(squishRO);               // Drop reference
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmCellSquish.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmCellSquish.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmCellSquish.h	(revision 22158)
@@ -0,0 +1,13 @@
+#ifndef PM_CELL_SQUISH_H
+#define PM_CELL_SQUISH_H
+
+/// Squish (combine all component readouts of) a cell
+///
+/// The component readouts are combined, optionally taking into account orthogonal transfer shifts (assumed to
+/// already have been read) and masks.
+bool pmCellSquish(pmCell *cell,         ///< Cell to have readouts combined
+                  psMaskType maskVal,   ///< Value to be masked
+                  bool useShifts        ///< Use the shifts when squishing?
+    );
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPA.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPA.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPA.c	(revision 22158)
@@ -0,0 +1,468 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <strings.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmConcepts.h"
+#include "pmMaskBadPixels.h"
+
+static void readoutFree(pmReadout *readout)
+{
+    // if this readout has a parent, drop that instance
+    if (readout->parent) {
+        psTrace("psModules.camera", 9, "Removing readout %zd from cell %zd...\n",
+                (size_t)readout, (size_t)readout->parent);
+        psArray *readouts = readout->parent->readouts;
+        for (int i = 0; i < readouts->n; i++) {
+            if (readouts->data[i] == readout) {
+                readouts->data[i] = NULL;
+            }
+        }
+    }
+    psTrace("psModules.camera", 9, "Freeing readout %zd\n", (size_t) readout);
+
+    psFree(readout->image);
+    psFree(readout->mask);
+    psFree(readout->weight);
+    psFree(readout->analysis);
+    psFree(readout->bias);
+}
+
+static void cellFree(pmCell *cell)
+{
+
+    // if this cell has a parent, drop that instance
+    if (cell->parent) {
+        psTrace("psModules.camera", 9, "Removing cell %zd from chip %zd...\n",
+                (size_t)cell, (size_t)cell->parent);
+        psArray *cells = cell->parent->cells;
+        for (int i = 0; i < cells->n; i++) {
+            if (cells->data[i] == cell) {
+                cells->data[i] = NULL;
+            }
+        }
+    }
+    psTrace("psModules.camera", 9, "Freeing cell %zd\n", (size_t)cell);
+    pmCellFreeReadouts(cell);
+    psFree(cell->readouts);
+
+    psFree(cell->concepts);
+    psFree(cell->analysis);
+    psFree(cell->config);
+    psFree(cell->hdu);
+}
+
+static void chipFree(pmChip* chip)
+{
+    // if this chip has a parent, drop that instance
+    if (chip->parent) {
+        psTrace("psModules.camera", 9, "Removing chip %zd from fpa %zd...\n",
+                (size_t)chip, (size_t)chip->parent);
+        psArray *chips = chip->parent->chips;
+        for (int i = 0; i < chips->n; i++) {
+            if (chips->data[i] == chip) {
+                chips->data[i] = NULL;
+            }
+        }
+    }
+
+    psTrace("psModules.camera", 9, "Freeing chip %zd\n", (size_t)chip);
+    pmChipFreeCells(chip);
+    psFree(chip->cells);
+
+    psFree(chip->concepts);
+    psFree(chip->analysis);
+    psFree(chip->hdu);
+
+    psFree(chip->toFPA);
+    psFree(chip->fromFPA);
+}
+
+
+static void FPAFree(pmFPA *fpa)
+{
+    psTrace("psModules.camera", 9, "Freeing fpa %zd\n", (size_t)fpa);
+
+    // NULL the parent pointers
+    psArray *chips = fpa->chips;
+    for (int i = 0 ; i < chips->n ; i++) {
+        pmChip *tmpChip = chips->data[i];
+        if (! tmpChip) {
+            continue;
+        }
+        tmpChip->parent = NULL;
+    }
+    psFree(fpa->chips);
+    psFree(fpa->concepts);
+    psFree(fpa->analysis);
+    psFree((void *)fpa->camera);
+    psFree(fpa->hdu);
+
+    psFree(fpa->fromTPA);
+    psFree(fpa->toTPA);
+    psFree(fpa->toSky);
+}
+
+void pmCellFreeReadouts(pmCell *cell)
+{
+    PS_ASSERT_PTR_NON_NULL(cell,);
+
+    //
+    // Set the parent to NULL in all cell->readouts before psFree(cell->readouts)
+    // in order to avoid memory reference counter problems.
+    //
+    psArray *readouts = cell->readouts;
+    for (psS32 i = 0 ; i < readouts->n ; i++) {
+        pmReadout *tmpReadout = readouts->data[i];
+        if (! tmpReadout) {
+            continue;
+        }
+        tmpReadout->parent = NULL;
+        psTrace("psModules.camera", 9, "Will now free readout %zd...\n", (size_t)tmpReadout);
+    }
+    cell->readouts = psArrayRealloc(cell->readouts, 0);
+    cell->readouts->n = 0;
+}
+
+
+void pmChipFreeCells(pmChip *chip)
+{
+    PS_ASSERT_PTR_NON_NULL(chip,);
+
+    //
+    // Set the parent to NULL in all chip->cells before psFree(chip->cells)
+    // in order to avoid memory reference counter problems.
+    //
+    psArray *cells = chip->cells;
+    for (int i = 0 ; i < cells->n ; i++) {
+        pmCell *tmpCell = cells->data[i];
+        if (! tmpCell) {
+            continue;
+        }
+        tmpCell->parent = NULL;
+        pmCellFreeReadouts(tmpCell);// Drop all readouts the cell holds
+    }
+    chip->cells = psArrayRealloc(chip->cells, 0);
+    chip->cells->n = 0;
+}
+
+void pmReadoutFreeData (pmReadout *readout)
+{
+    if (!readout) {
+        return;
+    }
+
+    psFree(readout->image);
+    psFree(readout->mask);
+    psFree(readout->weight);
+    psFree(readout->bias);
+
+    psTrace("psModules.camera", 3, "Freeing readout data for %zd\n", (size_t) readout);
+
+    readout->image = NULL;
+    readout->weight = NULL;
+    readout->mask = NULL;
+
+    readout->bias = psListAlloc(NULL);
+
+    readout->col0 = 0;
+    readout->row0 = 0;
+
+    readout->thisImageScan = 0;
+    readout->thisMaskScan = 0;
+    readout->thisWeightScan = 0;
+
+    readout->lastImageScan = 0;
+    readout->lastMaskScan = 0;
+    readout->lastWeightScan = 0;
+}
+
+void pmCellFreeData(pmCell *cell)
+{
+    if (!cell) {
+        return;
+    }
+
+    for (int i = 0; i < cell->readouts->n; i++) {
+        pmReadoutFreeData(cell->readouts->data[i]);
+    }
+    if (cell->hdu) {
+        psFree(cell->hdu->images);
+        psFree(cell->hdu->weights);
+        psFree(cell->hdu->masks);
+        // psFree(cell->hdu->header);
+
+        cell->hdu->images = NULL;
+        cell->hdu->weights = NULL;
+        cell->hdu->masks = NULL;
+        // cell->hdu->header = NULL;
+    }
+}
+
+void pmChipFreeData(pmChip *chip)
+{
+    if (!chip) {
+        return;
+    }
+
+    for (int i = 0; i < chip->cells->n; i++) {
+        pmCellFreeData(chip->cells->data[i]);
+    }
+    if (chip->hdu) {
+        psFree(chip->hdu->images);
+        psFree(chip->hdu->weights);
+        psFree(chip->hdu->masks);
+        // psFree(chip->hdu->header);
+
+        chip->hdu->images = NULL;
+        chip->hdu->weights = NULL;
+        chip->hdu->masks = NULL;
+        // chip->hdu->header = NULL;
+    }
+}
+
+void pmFPAFreeData(pmFPA *fpa)
+{
+    if (!fpa) {
+        return;
+    }
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChipFreeData(fpa->chips->data[i]);
+    }
+    if (fpa->hdu) {
+        psFree(fpa->hdu->images);
+        psFree(fpa->hdu->weights);
+        psFree(fpa->hdu->masks);
+        // psFree(fpa->hdu->header);
+
+        fpa->hdu->images = NULL;
+        fpa->hdu->weights = NULL;
+        fpa->hdu->masks = NULL;
+        // fpa->hdu->header = NULL;
+    }
+}
+
+pmReadout *pmReadoutAlloc(pmCell *cell)
+{
+    pmReadout *tmpReadout = (pmReadout *)psAlloc(sizeof(pmReadout));
+    psMemSetDeallocator(tmpReadout, (psFreeFunc) readoutFree);
+
+    tmpReadout->image = NULL;
+    tmpReadout->mask = NULL;
+    tmpReadout->weight = NULL;
+    tmpReadout->bias = psListAlloc(NULL);
+    tmpReadout->analysis = psMetadataAlloc();
+    tmpReadout->parent = cell;
+    if (cell) {
+        cell->readouts = psArrayAdd(cell->readouts, 1, (psPtr) tmpReadout);
+    }
+
+    tmpReadout->process = true;            // All cells are processed by default
+    tmpReadout->file_exists = false;       // file not yet identified
+    tmpReadout->data_exists = false;       // data yet read in
+
+    tmpReadout->row0 = 0;
+    tmpReadout->col0 = 0;
+
+    tmpReadout->thisImageScan = 0;
+    tmpReadout->thisMaskScan = 0;
+    tmpReadout->thisWeightScan = 0;
+
+    tmpReadout->lastImageScan = 0;
+    tmpReadout->lastMaskScan = 0;
+    tmpReadout->lastWeightScan = 0;
+
+    return(tmpReadout);
+}
+
+bool psMemCheckReadout(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) readoutFree);
+}
+
+
+pmCell *pmCellAlloc(
+    pmChip *chip,
+    const char *name)
+{
+    pmCell *tmpCell = (pmCell *) psAlloc(sizeof(pmCell));
+    psMemSetDeallocator(tmpCell, (psFreeFunc) cellFree);
+
+    tmpCell->config = NULL;
+    tmpCell->analysis = psMetadataAlloc();
+    tmpCell->readouts = psArrayAlloc(0);
+    tmpCell->parent = chip;
+    if (chip) {
+        chip->cells = psArrayAdd(chip->cells, 1, (psPtr) tmpCell);
+    }
+    tmpCell->hdu = NULL;
+    tmpCell->process = true;            // All cells are processed by default
+    tmpCell->file_exists = false;       // Not yet identified
+    tmpCell->data_exists = false;       // Not yet read in
+
+    tmpCell->concepts = psMetadataAlloc();
+    if (!psMetadataAddStr(tmpCell->concepts, PS_LIST_HEAD, "CELL.NAME", 0, NULL, name)) {
+        psErrorClear();
+        psWarning("Could not add CELL.NAME to metadata.");
+    }
+    tmpCell->conceptsRead = PM_CONCEPT_SOURCE_NONE;
+    // XXX does this work?  moved to conceptsRead... pmConceptsBlankCell(tmpCell);
+
+    return tmpCell;
+}
+
+bool psMemCheckCell(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) cellFree);
+}
+
+
+pmChip *pmChipAlloc(
+    pmFPA *fpa,
+    const char *name)
+{
+    pmChip *tmpChip = (pmChip*)psAlloc(sizeof(pmChip));
+    psMemSetDeallocator(tmpChip, (psFreeFunc) chipFree);
+
+    tmpChip->toFPA = NULL;
+    tmpChip->fromFPA = NULL;
+
+    tmpChip->analysis = psMetadataAlloc();
+    tmpChip->cells = psArrayAlloc(0);
+    tmpChip->parent = fpa;
+    if (fpa) {
+        psArrayAdd(fpa->chips, 1, (psPtr)tmpChip);
+    }
+    tmpChip->hdu = NULL;
+    tmpChip->process = true;            // Work on all chips, by default
+    tmpChip->file_exists = false;       // Not yet identified
+    tmpChip->data_exists = false;       // Not yet read in
+
+    tmpChip->concepts = psMetadataAlloc();
+    if (!psMetadataAddStr(tmpChip->concepts, PS_LIST_HEAD, "CHIP.NAME", 0, NULL, name)) {
+        psErrorClear();
+        psWarning("Could not add CHIP.NAME %s to concepts.", name);
+    }
+    tmpChip->conceptsRead = PM_CONCEPT_SOURCE_NONE;
+    // XXX does this work?  moved to conceptsRead... pmConceptsBlankChip(tmpChip);
+    return tmpChip;
+}
+
+bool psMemCheckChip(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) chipFree);
+}
+
+pmFPA *pmFPAAlloc(const psMetadata *camera, const char *cameraName)
+{
+    pmFPA *tmpFPA = (pmFPA *) psAlloc(sizeof(pmFPA));
+    psMemSetDeallocator(tmpFPA, (psFreeFunc) FPAFree);
+
+    tmpFPA->fromTPA = NULL;
+    tmpFPA->toTPA = NULL;
+    tmpFPA->toSky = NULL;
+
+    tmpFPA->analysis = psMetadataAlloc();
+    tmpFPA->camera = psMemIncrRefCounter((psPtr) camera);
+    tmpFPA->chips = psArrayAlloc(0);
+    tmpFPA->hdu = NULL;
+
+    tmpFPA->concepts = psMetadataAlloc();
+    if (!psMetadataAddStr(tmpFPA->concepts, PS_LIST_TAIL, "FPA.CAMERA", PS_META_REPLACE,
+                          "Camera name (according to configuration)", cameraName)) {
+        psErrorClear();
+        psWarning("Could not add FPA.CAMERA %s to concepts.", cameraName);
+    }
+    tmpFPA->conceptsRead = PM_CONCEPT_SOURCE_NONE;
+    // XXX does this work?  moved to conceptsRead... pmConceptsBlankFPA(tmpFPA);
+
+    // this may be somewhat pedantic, but it makes these things consistent
+    if (!psMetadataAddStr(tmpFPA->concepts, PS_LIST_TAIL, "FPA.NAME", PS_META_REPLACE,
+                          "name of FPA level", "fpa")) {
+        psErrorClear();
+        psWarning("Could not add FPA.NAME to concepts.");
+    }
+
+    return tmpFPA;
+}
+
+bool psMemCheckFPA(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) FPAFree);
+}
+
+
+// Check a cell to ensure that all component readouts have the parent pointer set correctly
+static bool cellCheckParents(pmCell *cell // Cell to check
+                            )
+{
+    PS_ASSERT_PTR_NON_NULL(cell, true);
+
+    bool flag = true;
+    for (long i = 0; i < cell->readouts->n ; i++) {
+        pmReadout *tmpReadout = (pmReadout *) cell->readouts->data[i];
+        if (!tmpReadout) {
+            continue;
+        }
+        if (tmpReadout->parent != cell) {
+            tmpReadout->parent = cell;
+            flag = false;
+        }
+    }
+    return flag;
+}
+
+// Check a chip to ensure that all component cells have the parent pointer set correctly
+static bool chipCheckParents(pmChip *chip // Chip to check
+                            )
+{
+    PS_ASSERT_PTR_NON_NULL(chip, true);
+
+    bool flag = true;
+    for (long i = 0; i < chip->cells->n ; i++) {
+        pmCell *tmpCell = (pmCell*)chip->cells->data[i];
+        if (!tmpCell) {
+            continue;
+        }
+        if (tmpCell->parent != chip) {
+            tmpCell->parent = chip;
+            flag = false;
+        }
+
+        flag &= cellCheckParents(tmpCell);
+    }
+    return flag;
+}
+
+psBool pmFPACheckParents(pmFPA *fpa)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+
+    bool flag = true;
+    for (long i = 0; i < fpa->chips->n ; i++) {
+        pmChip *tmpChip = (pmChip*)fpa->chips->data[i];
+        if (!tmpChip) {
+            continue;
+        }
+        if (tmpChip->parent != fpa) {
+            tmpChip->parent = fpa;
+            flag = false;
+        }
+
+        flag &= chipCheckParents(tmpChip);
+    }
+    return flag;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPA.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPA.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPA.h	(revision 22158)
@@ -0,0 +1,239 @@
+/* @file pmFPA.h
+ * @brief Defines the focal plane hierarchy, along with functions for interacting with it
+ *
+ * @author George Gusciora, MHPCC
+ * @author Paul Price, IfA
+ * @author Eugene Magnier, IfA
+ *
+ * @version $Revision: 1.22.14.1 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-29 21:39:55 $
+ * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FPA_H
+#define PM_FPA_H
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+// Return chip position, given FPA position; calculations are all done in pixel units
+#define PM_FPA_TO_CHIP(pos, chip0, chipParity) \
+    (((pos) - (chip0))*(chipParity))
+
+// Return cell position, given chip position; calculations are all done in pixel units
+#define PM_CHIP_TO_CELL(pos, cell0, cellParity, binning) \
+    (((pos) - (cell0))*(cellParity)/(binning))
+
+// Return chip position, given a cell position; calculations are all done in pixel units
+#define PM_CELL_TO_CHIP(pos, cell0, cellParity, binning) \
+    ((pos)*(binning)*(cellParity) + (cell0))
+
+// Return FPA position, given a chip position; calculations are all done in pixel units
+#define PM_CHIP_TO_FPA(pos, chip0, chipParity) \
+    ((pos)*(chipParity) + (chip0))
+
+/// Focal plane array (the entirety of the camera)
+///
+/// The FPA is the top-level camera structure, and consists of one or more chips.  It also contains the
+/// concepts metadata appropriate to this level, a summary of analysis tasks that have been performed, the
+/// camera configuration information, any HDU that corresponds to this level for the file of interest, and
+/// astrometric transformations.  The astrometric transformations encode how to transform from the tangent
+/// plane to the sky, and back.
+typedef struct {
+    // Astrometric transformations
+    psPlaneTransform *fromTPA;  ///< Transformation from tangent plane to focal plane, or NULL
+    psPlaneTransform *toTPA;  ///< Transformation from focal plane to tangent plane, or NULL
+    psProjection *toSky;         ///< Projection from tangent plane to sky, or NULL
+    // Information
+    psMetadata *concepts;               ///< FPA-level concepts
+    unsigned int conceptsRead;          ///< Which concepts have been read; see pmConceptsSource
+    psMetadata *analysis;               ///< FPA-level analysis metadata
+    const psMetadata *camera;           ///< Camera configuration
+    psArray *chips;                     ///< The component chips
+    pmHDU *hdu;                         ///< FITS header data unit of interest, or NULL
+} pmFPA;
+
+/// A chip (contiguous detector element)
+///
+/// The chip is the mid-level camera structure, being part of an FPA, and consisting of one or more cells
+/// (e.g., a CCD).  It also contains the concepts metadata appropriate to this level, a summary of analysis
+/// tasks that have been performed, status flags, any HDU that corresponds to this level for the file of
+/// interest, and astrometric transformations.  The astrometric transformations provide transforms between the
+/// chip and FPA coordinates and back.
+typedef struct {
+    // Astrometric transformations
+    psPlaneTransform *toFPA;            ///< Transformation from chip to FPA coordinates, or NULL
+    psPlaneTransform *fromFPA;          ///< Transformation from FPA to chip coordinates, or NULL
+    // Information
+    psMetadata *concepts;               ///< Chip-level concepts
+    unsigned int conceptsRead;          ///< Which concepts have been read; see pmConceptsSource
+    psMetadata *analysis;               ///< Chip-level analysis metadata
+    psArray *cells;                     ///< The component cells
+    pmFPA *parent;                      ///< Parent FPA
+    bool process;                       ///< Do we bother about reading and working with this chip?
+    bool file_exists;                   ///< Does the file for this chip exist (read case only)?
+    bool data_exists;                   ///< Does the data for this chip exist (read case only)?
+    pmHDU *hdu;                         ///< FITS header data unit of interest,
+} pmChip;
+
+/// A cell (smallest logical unit)
+///
+/// A cell is the lowest-level camera structure, being part of a chip (e.g., an amplifier).  It may consist of
+/// one or more readouts, which are individual reads of the cell.  It also contains the concepts metadata
+/// appropriate to this level, the cell configuration information (for convenience) from the camera
+/// configuration, a summary of analysis tasks that have been performed, status flags, and any HDU that
+/// corresponds to this level for the file of interest
+
+/** Cell data structure
+ *
+ *  A cell consists of one or more readouts.  It also contains a pointer to the
+ *  cell's metadata, and its parent chip.  On the astrometry side, it also
+ *  contains coordinate transforms from the cell to chip, from the cell to
+ *  focal-plane, as well as a "quick and dirty" tranform from the cell to
+ *  sky coordinates.
+ *
+ */
+typedef struct {
+    psMetadata *concepts;               ///< Cell-level concepts
+    unsigned int conceptsRead;          ///< Which concepts have been read; see pmConceptsSource
+    psMetadata *config;                 ///< Cell configuration information (from CELLS in the camera config)
+    psMetadata *analysis;               ///< Cell-level analysis metadata
+    psArray *readouts;                  ///< The component readouts
+    pmChip *parent;                     ///< Parent chip
+    bool process;                       ///< Do we bother about reading and working with this cell?
+    bool file_exists;                   ///< Does the file for this cell exist (read case only)?
+    bool data_exists;                   ///< Does the data for this cell exist (read case only)?
+    pmHDU *hdu;                         ///< FITS header data unit of interest
+} pmCell;
+
+/// A readout (individual read of a cell)
+///
+/// A readout corresponds to an individual read of a cell (e.g., a single image as part of a video sequence,
+/// or one of multiple coadds).  It contains the actual pixels used in analysis (along with mask and weight
+/// maps).  When reading from a FITS file, the images are subimages (from CELL.TRIMSEC) of the pixels read
+/// from the appropriate HDU (at the FPA, chip or cell level).  The readout also contains a list of bias
+/// sections (prescans or overscans, or otherwise), a summary of analysis tasks that have been performed,
+/// status flags, and the offsets used for reading a FITS file incrementally.
+typedef struct {
+    int col0;                           ///< Column offset; non-zero if reading in columns incrementally
+    int row0;                           ///< Row offset; non-zero if reading in rows incrementally
+    psImage *image;                     ///< Imaging area of readout (corresponds to CELL.TRIMSEC region)
+    psImage *mask;                      ///< Mask of input image (corresponds to CELL.TRIMSEC region)
+    psImage *weight;                    ///< Weight of input image (corresponds to CELL.TRIMSEC region)
+    psList *bias;                       ///< List of bias (prescan/overscan) images
+    psMetadata *analysis;               ///< Readout-level analysis metadata
+    pmCell *parent;                     ///< Parent cell
+    bool process;                       ///< Do we bother about reading and working with this readout?
+    bool file_exists;                   ///< Does the file for this readout exist (read case only)?
+    bool data_exists;                   ///< Does the data for this readout exist (read case only)?
+    int thisImageScan;			///< start scan for next/current read
+    int lastImageScan;			///< start scan of the last read
+    int thisMaskScan;			///< start scan for next/current read
+    int lastMaskScan;			///< start scan of the last read
+    int thisWeightScan;			///< start scan for next/current read
+    int lastWeightScan;			///< start scan of the last read
+} pmReadout;
+
+/// Free all readouts within a cell
+void pmCellFreeReadouts(pmCell *cell);    ///< Cell for which to free readouts
+
+/// Free all cells within a chip
+void pmChipFreeCells(pmChip *chip);       ///< Chip for which to free cells
+
+/// Free all data within a readout
+void pmReadoutFreeData(pmReadout *readout); ///< Readout for which to free data
+
+/// Free all data within a cell (all readouts as well as metadata)
+void pmCellFreeData(pmCell *cell);        ///< Cell for which to free data
+
+/// Free all data within a chip (all cells as well as metadata)
+void pmChipFreeData(pmChip *chip);        ///< Chip for which to free data
+
+/// Free all data within an FPA (all chips as well as metadata)
+void pmFPAFreeData(pmFPA *fpa);           ///< FPA for which to free data
+
+/// Allocate a readout associated with a cell
+pmReadout *pmReadoutAlloc(pmCell *cell);  ///< Parent cell, or NULL
+bool psMemCheckReadout(psPtr ptr);
+
+/// Allocate a cell associated with a chip
+///
+/// The name is used to set CELL.NAME within the concepts.
+pmCell *pmCellAlloc(pmChip *chip,       ///< Parent chip, or NULL
+                    const char *name);  ///< Name of cell, for CELL.NAME
+bool psMemCheckCell(psPtr ptr);
+
+
+/// Allocate a chip associated with an FPA
+///
+/// The name is used to set CHIP.NAME within the concepts
+pmChip *pmChipAlloc(pmFPA *fpa,         ///< Parent FPA, or NULL
+                    const char *name);  ///< Name of chip, for CHIP.NAME
+bool psMemCheckChip(psPtr ptr);
+
+
+/// Allocate an FPA
+pmFPA *pmFPAAlloc(const psMetadata *camera, ///< Camera configuration (to store in FPA)
+                  const char *cameraName ///< Name of camera (for FPA.CAMERA concept)
+    );
+bool psMemCheckFPA(psPtr ptr);
+
+/// Check parent links within an FPA
+///
+/// Iterates through the FPA to verify that the "parent" links in the chip, cell and readout are set
+/// correctly.  If there are any incorrect links, they are fixed, and the function returns false.
+bool pmFPACheckParents(pmFPA *fpa);     ///< FPA to check
+
+
+/// Assertions
+
+/// Check that the fundamentals of a readout are set
+#define PM_ASSERT_READOUT_NON_NULL(READOUT, RETVAL) { \
+    if (!(READOUT) || !(READOUT)->bias || !(READOUT)->analysis) { \
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Readout %s or one of its components is NULL.", #READOUT); \
+        return RETVAL; \
+    } \
+    int numCols = 0, numRows = 0; /* Size of readout images */ \
+    psImage *image = (READOUT)->image; /* Image pixels */ \
+    if (image) { \
+        PS_ASSERT_IMAGE_TYPE((READOUT)->image, PS_TYPE_F32, RETVAL); \
+        numCols = image->numCols; \
+        numRows = image->numRows; \
+    } \
+    psImage *mask = (READOUT)->mask; /* Mask pixels */ \
+    if (mask) { \
+        PS_ASSERT_IMAGE_NON_NULL((READOUT)->mask, RETVAL); \
+        if ((numCols != 0 || numRows != 0) && (mask->numCols != numCols || mask->numRows != numRows)) { \
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Mask in readout %s has wrong size (%dx%d vs %dx%d)", \
+                    #READOUT, mask->numCols, mask->numRows, numCols, numRows); \
+            return RETVAL; \
+        } else { \
+            numCols = mask->numCols; \
+            numRows = mask->numRows; \
+        } \
+    } \
+    psImage *weight = (READOUT)->weight; /* Weight map pixels */ \
+    if (weight) { \
+        PS_ASSERT_IMAGE_NON_NULL((READOUT)->weight, RETVAL); \
+        if ((numCols != 0 || numRows != 0) && (weight->numCols != numCols || weight->numRows != numRows)) { \
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Weight in readout %s has wrong size (%dx%d vs %dx%d)", \
+                    #READOUT, weight->numCols, weight->numRows, numCols, numRows); \
+            return RETVAL; \
+        } \
+    } \
+}
+
+/// Assert that a readout contains an image
+#define PM_ASSERT_READOUT_IMAGE(READOUT, RETVAL) \
+    PS_ASSERT_IMAGE_NON_NULL((READOUT)->image, RETVAL);
+
+/// Assert that a readout contains a mask
+#define PM_ASSERT_READOUT_MASK(READOUT, RETVAL) \
+    PS_ASSERT_IMAGE_NON_NULL((READOUT)->mask, RETVAL);
+
+/// Assert that a readout contains a weight map
+#define PM_ASSERT_READOUT_WEIGHT(READOUT, RETVAL) \
+    PS_ASSERT_IMAGE_NON_NULL((READOUT)->weight, RETVAL);
+
+/// @}
+#endif // #ifndef PM_FPA_H
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAAstrometry.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAAstrometry.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAAstrometry.c	(revision 22158)
@@ -0,0 +1,512 @@
+#include <stdio.h>
+#include "pslib.h"
+#include "pmFPAAstrometry.h"
+#include "pmFPA.h"
+
+
+/*****************************************************************************
+checkValidImageCoords(): this is a private function which simply determines if
+the supplied x,y coordinates are in the range for the supplied psImage.
+ 
+XXX: What about col0 and row0
+XXX: This should return a psBool.
+XXX: Macro this for speed.
+ *****************************************************************************/
+static psS32 checkValidImageCoords(
+    double x,
+    double y,
+    psImage* tmpImage)
+{
+    PS_ASSERT_IMAGE_NON_NULL(tmpImage, 0);
+
+    // The FLT_EPSILON is because -0.0 was failing this.
+    if (((x+FLT_EPSILON) < 0.0) || (x > (double)tmpImage->numCols) ||
+            ((y+FLT_EPSILON) < 0.0) || (y > (double)tmpImage->numRows)) {
+        return (0);
+    }
+
+    return (1);
+}
+
+/*****************************************************************************/
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+/*****************************************************************************/
+
+pmCell* pmCellInFPA(
+    const psPlane* fpaCoord,
+    const pmFPA* FPA)
+{
+    PS_ASSERT_PTR_NON_NULL(fpaCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(FPA, NULL);
+
+    pmChip* tmpChip = NULL;
+    psPlane chipCoord;
+    pmCell* outCell = NULL;
+
+    // Determine which chip contains the fpaCoords.
+    tmpChip = pmChipInFPA(fpaCoord, FPA);
+    if (tmpChip == NULL) {
+        return(NULL);
+    }
+
+    // Convert to those chip coordinates.
+    psPlane *rc = pmCoordFPAToChip(&chipCoord, fpaCoord, tmpChip);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine Chip coords.\n");
+        return(NULL);
+    }
+
+    // Determine which cell contains those chip coordinates.
+    outCell = pmCellInChip(&chipCoord, tmpChip);
+    if (outCell == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine the cell.\n");
+        return(NULL);
+    }
+
+    return (outCell);
+}
+
+pmChip* pmChipInFPA(
+    const psPlane* fpaCoord,
+    const pmFPA* FPA)
+{
+    PS_ASSERT_PTR_NON_NULL(fpaCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(FPA, NULL);
+    PS_ASSERT_PTR_NON_NULL(FPA->chips, NULL);
+
+    psArray* chips = FPA->chips;
+    psS32 nChips = chips->n;
+    psPlane chipCoord;
+    pmCell *tmpCell = NULL;
+
+    //
+    // Loop through every chip in this FPA.  Convert the original FPA
+    // coordinates to chip coordinates for that chip.  Then, determine if any
+    // cells in that chip contain those chip coordinates.
+    // XXX: Depending on the number of chips, and their topology, there may be
+    // a much more efficient way of doing this.
+    //
+    for (psS32 i = 0; i < nChips; i++) {
+        pmChip* tmpChip = chips->data[i];
+        PS_ASSERT_PTR_NON_NULL(tmpChip, NULL);
+        PS_ASSERT_PTR_NON_NULL(tmpChip->fromFPA, NULL);
+
+        psPlaneTransformApply(&chipCoord, tmpChip->fromFPA, fpaCoord);
+
+        tmpCell = pmCellInChip(&chipCoord, tmpChip);
+        if (tmpCell != NULL) {
+            return(tmpChip);
+        }
+    }
+
+    psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine the chip.\n");
+    return (NULL);
+}
+
+
+pmCell* pmCellInChip(
+    const psPlane* chipCoord,
+    const pmChip* chip)
+{
+    PS_ASSERT_PTR_NON_NULL(chipCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(chip, NULL);
+
+    psPlane cellCoord;
+    psArray* cells;
+
+    cells = chip->cells;
+    if (cells == NULL) {
+        return NULL;
+    }
+
+    //
+    // We loop over each cell in the chip.  We transform the chipCoord into
+    // a cellCoord for that cell and determine if that cellCoord is valid.
+    // If so, then we return that cell.
+    // XXX: Depending on the number of cells, and their topology, there may be
+    // a much more efficient way of doing this.
+    //
+    for (psS32 i = 0; i < cells->n; i++) {
+        pmCell* tmpCell = (pmCell* ) cells->data[i];
+        PS_ASSERT_PTR_NON_NULL(tmpCell, NULL);
+
+        psPlaneTransform *chipToCell = NULL;
+        if (true ==  p_psIsProjectionLinear(tmpCell->toChip)) {
+            chipToCell = p_psPlaneTransformLinearInvert(tmpCell->toChip);
+        } else {
+            psLogMsg(__func__, PS_LOG_WARN, "WARNING: non-linear cell->chip transforms are not yet implemented.\n");
+            //chipToCell = psPlaneTransformInvert(NULL, tmpCell->toChip, NULL, -1);
+            chipToCell = NULL;
+        }
+        if (chipToCell == NULL) {
+            psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not invert the Cell->toChip transform.\n");
+            return(NULL);
+        }
+        psArray* readouts = tmpCell->readouts;
+
+        if (readouts != NULL) {
+            for (psS32 j = 0; j < readouts->n; j++) {
+                pmReadout* tmpReadout = readouts->data[j];
+                PS_ASSERT_READOUT_NON_NULL(tmpReadout, NULL);
+
+                psPlaneTransformApply(&cellCoord,
+                                      chipToCell,
+                                      chipCoord);
+
+                if (checkValidImageCoords(cellCoord.x,
+                                          cellCoord.y,
+                                          tmpReadout->image)) {
+                    psFree(chipToCell);
+                    return (tmpCell);
+                }
+            }
+        }
+        psFree(chipToCell);
+    }
+
+    //psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine the cell.\n");
+    return (NULL);
+}
+
+
+psPlane* pmCoordCellToFPA(
+    psPlane* fpaCoord,
+    const psPlane* cellCoord,
+    const pmCell* cell)
+{
+    PS_ASSERT_PTR_NON_NULL(cellCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell, NULL);
+
+    psPlane *rc = psPlaneTransformApply(fpaCoord, cell->toFPA, cellCoord);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform cell coords to FPA coords.\n");
+    }
+    return(rc);
+}
+
+
+psPlane* pmCoordChipToFPA(
+    psPlane* outCoord,
+    const psPlane* inCoord,
+    const pmChip* chip)
+{
+    PS_ASSERT_PTR_NON_NULL(inCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(chip, NULL);
+
+    psPlane *rc = psPlaneTransformApply(outCoord, chip->toFPA, inCoord);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform chip coords to FPA coords.\n");
+    }
+    return(rc);
+}
+
+
+psPlane* pmCoordFPAToChip(
+    psPlane* chipCoord,
+    const psPlane* fpaCoord,
+    const pmChip* chip)
+{
+    PS_ASSERT_PTR_NON_NULL(fpaCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(chip, NULL);
+    PS_ASSERT_PTR_NON_NULL(chip->fromFPA, NULL);
+
+    psPlane *rc = psPlaneTransformApply(chipCoord, chip->fromFPA, fpaCoord);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform FPA coords to Chip coords.\n");
+    }
+    return(rc);
+}
+
+psPlane* pmCoordCellToChip(
+    psPlane* outCoord,
+    const psPlane* inCoord,
+    const pmCell* cell)
+{
+    PS_ASSERT_PTR_NON_NULL(inCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell, NULL);
+
+    psPlane *rc = psPlaneTransformApply(outCoord, cell->toChip, inCoord);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform Cell coords to Chip coords.\n");
+    }
+    return(rc);
+}
+
+psPlane* pmCoordChipToCell(
+    psPlane* cellCoord,
+    const psPlane* chipCoord,
+    const pmCell* cell)
+{
+    PS_ASSERT_PTR_NON_NULL(chipCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell->parent, NULL);
+
+    pmCell *tmpCell = pmCellInChip(chipCoord, cell->parent);
+    if (tmpCell == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine the proper cell.\n");
+        return(NULL);
+    }
+
+    psPlaneTransform *tmpChipToCell = NULL;
+    PS_ASSERT_PTR_NON_NULL(tmpCell->toChip, NULL);
+    if (true ==  p_psIsProjectionLinear(tmpCell->toChip)) {
+        tmpChipToCell = p_psPlaneTransformLinearInvert(tmpCell->toChip);
+    } else {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: non-linear cell->chip transforms are not yet implemented.\n");
+        // XXX: tmpChipToCell = psPlaneTransformInvert(NULL, tmpCell->toChip, NULL, -1);
+        tmpChipToCell = NULL;
+    }
+    if (tmpChipToCell == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not invert the Cell->toChip transform.\n");
+        return(NULL);
+    }
+
+    psPlane *rc = psPlaneTransformApply(cellCoord, tmpChipToCell, chipCoord);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform Chip coords to Cell coords.\n");
+    }
+    psFree(tmpChipToCell);
+    return(rc);
+}
+
+psPlane* pmCoordFPAToTP(
+    psPlane* outCoord,
+    const psPlane* inCoord,
+    double color,
+    double magnitude,
+    const pmFPA* fpa)
+{
+    PS_ASSERT_PTR_NON_NULL(inCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
+
+    psPlane *rc = psPlaneDistortApply(outCoord, fpa->toTangentPlane, inCoord, color, magnitude);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform FPA coords to tangent plane coords.\n");
+    }
+    return(rc);
+}
+
+psPlane* pmCoordTPToFPA(
+    psPlane* fpaCoord,
+    const psPlane* tpCoord,
+    double color,
+    double magnitude,
+    const pmFPA* fpa)
+{
+    PS_ASSERT_PTR_NON_NULL(tpCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
+    PS_ASSERT_PTR_NON_NULL(fpa->fromTangentPlane, NULL);
+
+    psPlane *rc = psPlaneDistortApply(fpaCoord, fpa->fromTangentPlane, tpCoord, color, magnitude);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform tangent plane coords to FPA coords.\n");
+    }
+    return(rc);
+}
+
+
+/*****************************************************************************
+XXXDeproject(outSphere, coord, projection): This private routine is a wrapper
+for p_psDeproject().  The reason: p_psDeproject() and p_psProject() combined
+do not seem to produce the original coordinates when they even though they
+should.  XXXDeproject() simply negates the ->r and ->d members of the output
+psSphere if the input ->y is larger than 0.0.  I don't know why it works.
+ 
+I'm guessing the p_psProject() and p_psDeproject() functions have bugs.
+ 
+XXX: It appears that p_psProject() and p_psDeproject() have been fixed.
+Remove this.
+ *****************************************************************************/
+psSphere* XXXDeproject(
+    psSphere *outSphere,
+    const psPlane* coord,
+    const psProjection* projection)
+{
+    psSphere *rc = p_psDeproject(outSphere, coord, projection);
+
+    if (coord->y >= 0.0) {
+        rc->d = -rc->d;
+        rc->r = -rc->r;
+    }
+
+    return(rc);
+}
+
+/*****************************************************************************
+  *****************************************************************************/
+psSphere* pmCoordTPToSky(
+    psSphere* outSphere,
+    const psPlane* tpCoord,
+    const psProjection *projection)
+{
+    PS_ASSERT_PTR_NON_NULL(tpCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(projection, NULL);
+
+    //    psSphere *rc = XXXDeproject(outSphere, tpCoord, projection);
+    psSphere *rc = p_psDeproject(outSphere, tpCoord, projection);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform tangent plane coords to sky coords.\n");
+    }
+    return(rc);
+}
+
+/*****************************************************************************
+ *****************************************************************************/
+psPlane* pmCoordSkyToTP(
+    psPlane* tpCoord,
+    const psSphere* in,
+    const psProjection *projection)
+{
+    PS_ASSERT_PTR_NON_NULL(in, NULL);
+    PS_ASSERT_PTR_NON_NULL(projection, NULL);
+
+    psPlane *rc = p_psProject(tpCoord, in, projection);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform sky to tangent plane coords.\n");
+    }
+    return(rc);
+}
+
+/*****************************************************************************
+ *****************************************************************************/
+psSphere* pmCoordCellToSky(
+    psSphere* skyCoord,
+    const psPlane* cellCoord,
+    double color,
+    double magnitude,
+    const pmCell* cell)
+{
+    PS_ASSERT_PTR_NON_NULL(cellCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell->toFPA, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell->parent, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell->parent->parent, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell->parent->parent->toTangentPlane, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell->parent->parent->projection, NULL);
+    psPlane fpaCoord;
+    psPlane tpCoord;
+    psPlane *rc;
+    pmFPA* parFPA = (cell->parent)->parent;
+
+    // Convert the input cell coordinates to FPA coordinates.
+    rc = psPlaneTransformApply(&fpaCoord, cell->toFPA, cellCoord);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could transform cell coords to FPA coords.\n");
+        return(NULL);
+    }
+
+    // Convert the FPA coordinates to tangent plane Coordinates.
+    rc = psPlaneDistortApply(&tpCoord, parFPA->toTangentPlane, &fpaCoord, color, magnitude);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could transform FPA coords to tangent plane coords.\n");
+        return(NULL);
+    }
+
+    // Convert the tangent plane Coordinates to sky coordinates.
+    psSphere *rc2 = pmCoordTPToSky(skyCoord, &tpCoord, parFPA->projection);
+    if (rc2 == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform cell coords to sky coords.\n");
+    }
+
+    return(rc2);
+}
+
+/*****************************************************************************
+ *****************************************************************************/
+psPlane* pmCoordSkyToCell(
+    psPlane* cellCoord,
+    const psSphere* skyCoord,
+    float color,
+    float magnitude,
+    const pmCell* cell)
+{
+    PS_ASSERT_PTR_NON_NULL(skyCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell->parent, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell->parent->parent, NULL);
+    pmChip *parChip = cell->parent;
+    pmFPA *parFPA = parChip->parent;
+    psPlane tpCoord;
+    psPlane fpaCoord;
+    psPlane chipCoord;
+    psPlane *rc;
+
+    // Convert the skyCoords to tangent plane coords.
+    rc = pmCoordSkyToTP(&tpCoord, skyCoord, parFPA->projection);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine tangent plane coords.\n");
+        return(NULL);
+    }
+
+    // Convert the tangent plane coords to FPA coords.
+    rc = pmCoordTPToFPA(&fpaCoord, &tpCoord, color, magnitude, parFPA);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine FPA coords.\n");
+        return(NULL);
+    }
+
+    // Convert the FPA coords to chip coords.
+    rc = pmCoordFPAToChip(&chipCoord, &fpaCoord, parChip);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine chip coords.\n");
+        return(NULL);
+    }
+
+    // Convert the chip coords to cell coords.
+    rc = pmCoordChipToCell(cellCoord, &chipCoord, cell);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine cell coords.\n");
+        return(NULL);
+    }
+
+    return (cellCoord);
+}
+
+/*****************************************************************************
+ *****************************************************************************/
+psSphere* pmCoordCellToSkyQuick(
+    psSphere* outSphere,
+    const psPlane* cellCoord,
+    const pmCell* cell)
+{
+    PS_ASSERT_PTR_NON_NULL(cellCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell->toSky, NULL);
+    psPlane outPlane;
+    psPlane *rc;
+    rc = psPlaneTransformApply(&outPlane, cell->toSky, cellCoord);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could transform cell coords to sky coords.\n");
+        return(NULL);
+    }
+
+    psSphere *out = outSphere;
+    if (out == NULL) {
+        out = psSphereAlloc();
+    }
+    out->r = outPlane.y;
+    out->d = outPlane.x;
+
+    return(out);
+}
+
+/*****************************************************************************
+ *****************************************************************************/
+psPlane* pmCoordSkyToCellQuick(
+    psPlane* cellCoord,
+    const psSphere* skyCoord,
+    const pmCell* cell)
+{
+    PS_ASSERT_PTR_NON_NULL(skyCoord, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell->toSky, NULL);
+    psPlane skyPlane;
+    skyPlane.y = skyCoord->r;
+    skyPlane.x = skyCoord->d;
+
+    psPlane *rc = psPlaneTransformApply(cellCoord, cell->toSky, &skyPlane);
+    if (rc == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform sky to cell coords.\n");
+    }
+    return(cellCoord);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAAstrometry.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAAstrometry.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAAstrometry.h	(revision 22158)
@@ -0,0 +1,188 @@
+#ifndef PM_FPA_ASTROMETRY_H
+#define PM_FPA_ASTROMETRY_H
+
+#include "pslib.h"
+#include "pmFPA.h"
+
+/** Find cooresponding cell for given FPA coordinate
+ *
+ *  @return pmCell*    the cell cooresponding to the coord in FPA
+ */
+pmCell* pmCellInFPA(
+    const psPlane* coord,              ///< the coordinate in FPA plane
+    const pmFPA* FPA                   ///< the FPA to search for the cell
+);
+
+
+/** Find cooresponding chip for given FPA coordinate
+ *
+ *  @return pmChip*    the chip cooresponding to coord
+ */
+pmChip* pmChipInFPA(
+    const psPlane* coord,              ///< the coordinate in FPA plane
+    const pmFPA* FPA                   ///< the FPA to search for the cell
+);
+
+
+/** Find cooresponding cell for given Chip coordinate
+ *
+ *  @return pmCell*    the cell cooresponding to coord
+ */
+pmCell* pmCellInChip(
+    const psPlane* coord,              ///< the coordinate in Chip plane
+    const pmChip* chip                 ///< the chip to search for the cell
+);
+
+
+/** Translate a cell coordinate into a chip coordinate
+ *
+ *  @return psPlane*    the resulting chip coordinate
+ */
+psPlane* pmCoordCellToChip(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                 ///< the coordinate within Cell
+    const pmCell* cell                 ///< the Cell in interest
+);
+
+
+/** Translate a chip coordinate into a FPA coordinate
+ *
+ *  @return psPlane*    the resulting FPA coordinate
+ */
+psPlane* pmCoordChipToFPA(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                 ///< the coordinate within Chip
+    const pmChip* chip                 ///< the chip in interest
+);
+
+
+/** Translate a FPA coordinate into a Tangent Plane coordinate
+ *
+ *  @return psPlane*    the resulting Tangent Plane coordinate
+ */
+psPlane* pmCoordFPAToTP(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                 ///< the coordinate within FPA
+    double color,                      ///< Color of source
+    double magnitude,                  ///< Magnitude of source
+    const pmFPA* fpa                   ///< the FPA in interest
+);
+
+
+/** Translate a Tangent Plane coordinate into a Sky coordinate
+ *
+ *  @return psSphere*    the resulting Sky coordinate
+ */
+psSphere* pmCoordTPToSky(
+    psSphere* out,                     ///< a sphere struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                ///< the coordinate within Tangent Plane
+    const psProjection *projection
+);
+
+/** Translate a cell coordinate into a FPA coordinate
+ *
+ *  @return psPlane*    the resulting FPA coordinate
+ */
+psPlane* pmCoordCellToFPA(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                 ///< the coordinate within cell
+    const pmCell* cell                 ///< the cell in interest
+);
+
+
+/** Translate a cell coordinate into a Sky coordinate
+ *
+ *  @return psSphere*    the resulting Sky coordinate
+ */
+psSphere* pmCoordCellToSky(
+    psSphere* out,                     ///< a sphere struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                 ///< the coordinate within cell
+    double color,                      ///< Color of source
+    double magnitude,                  ///< Magnitude of source
+    const pmCell* cell                 ///< the cell in interest
+);
+
+
+/** Translate a cell coordinate into a Sky coordinate using a 'quick and
+ *  dirty' method
+ *
+ *  @return psSphere*    the resulting Sky coordinate
+ */
+psSphere* pmCoordCellToSkyQuick(
+    psSphere* out,                     ///< a sphere struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                 ///< the coordinate within cell
+    const pmCell* cell                 ///< the cell in interest
+);
+
+
+/** Translate a Sky coordinate into a Tangent Plane coordinate
+ *
+ *  @return psPlane*    the resulting Tangent Plane coordinate
+ */
+psPlane* pmCoordSkyToTP(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psSphere* in,                ///< the sky coordinate
+    const psProjection *projection
+);
+
+/** Translate a Tangent Plane coordinate into a FPA coordinate
+ *
+ *  @return psPlane*    the resulting FPA coordinate
+ */
+psPlane* pmCoordTPToFPA(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                 ///< the coordinate within tangent plane
+    double color,                      ///< Color of source
+    double magnitude,                  ///< Magnitude of source
+    const pmFPA* fpa                   ///< the FPA of interest
+);
+
+
+/** Translate a FPA coordinate into a chip coordinate
+ *
+ *  @return psPlane*    the resulting chip coordinate
+ */
+psPlane* pmCoordFPAToChip(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                 ///< the FPA coordinate
+    const pmChip* chip                 ///< the chip of interest
+);
+
+
+/** Translate a chip coordinate into a cell coordinate
+ *
+ *  @return psPlane*    the resulting cell coordinate
+ */
+psPlane* pmCoordChipToCell(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psPlane* in,                 ///< the Chip coordinate
+    const pmCell* cell                 ///< the cell of interest
+);
+
+
+/** Translate a sky coordinate into a cell coordinate
+ *
+ *  @return psPlane*    the resulting cell coordinate
+ */
+psPlane* pmCoordSkyToCell(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psSphere* in,                ///< the Sky coordinate
+    float color,                       ///< Color of source
+    float magnitude,                   ///< Magnitude of source
+    const pmCell* cell                 ///< the cell of interest
+);
+
+
+/** Translate a sky coordinate into a cell coordinate using a 'quick and
+ *  dirty' method
+ *
+ *  @return psPlane*    the resulting cell coordinate
+ */
+psPlane* pmCoordSkyToCellQuick(
+    psPlane* out,                      ///< a plane struct to recycle. If NULL, a new struct is created
+    const psSphere* in,                ///< the Sky coordinate
+    const pmCell* cell                 ///< the cell of interest
+);
+
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPACalibration.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPACalibration.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPACalibration.c	(revision 22158)
@@ -0,0 +1,63 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+
+#include "pmFPACalibration.h"
+
+float pmFPADarkNorm(const pmFPA *fpa, const pmFPAview *view, float expTime)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, NAN);
+    PS_ASSERT_PTR_NON_NULL(view, NAN);
+
+    psMetadata *darkNorms = psMetadataLookupMetadata(NULL, fpa->camera, "DARK.NORM"); // Dark normalisations
+    if (!darkNorms) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to find DARK.NORM in camera configuration.");
+        return NAN;
+    }
+
+    const char *key = psMetadataLookupStr(NULL, fpa->camera, "DARK.NORM.KEY"); // Key for normalisation
+    if (!key || strlen(key) == 0) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to find DARK.NORM.KEY in camera configuration.");
+        return NAN;
+    }
+
+    psString keyResolved = pmFPANameFromRule(key, fpa, view); // Resolved version
+    if (!keyResolved || strlen(keyResolved) == 0) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to resolve DARK.NORM.KEY: %s", key);
+        return NAN;
+    }
+
+    psMetadata *polyMD = psMetadataLookupMetadata(NULL, darkNorms, keyResolved); // Metadata with polynomial
+    if (!polyMD) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to find %s polynomial in the DARK.NORM metadata", keyResolved);
+        psFree(keyResolved);
+        return NAN;
+    }
+
+    psPolynomial1D *poly = psPolynomial1DfromMetadata(polyMD); // Polynomial
+    if (!poly) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to determine polynomial from %s in the DARK.NORM metadata",
+                keyResolved);
+        psFree(keyResolved);
+        return NAN;
+    }
+    psFree(keyResolved);
+
+    float value = psPolynomial1DEval(poly, expTime);
+
+    psFree(poly);
+
+    return value;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPACalibration.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPACalibration.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPACalibration.h	(revision 22158)
@@ -0,0 +1,17 @@
+#ifndef PM_FPA_CALIBRATION_H
+#define PM_FPA_CALIBRATION_H
+
+/// Return the dark normalisation value
+///
+/// Unfortunately, dark current is not linear with the exposure time, but application of a polynomial
+/// correction to the exposure time should make it linear.  This function returns the appropriate value with
+/// which to normalise a dark frame.  The polynomial is obtained from DARK.NORM in the camera configuration.
+/// The specific polynomial metadata to use is provided by DARK.NORM.KEY, which is keyword expanded in the
+/// usual manner (e.g., try "{CHIP.NAME}").
+float pmFPADarkNorm(const pmFPA *fpa,   ///< FPA for which to get the normalisation
+                    const pmFPAview *view, ///< View to the FPA component of interest
+                    float expTime       ///< The nominal exposure time
+    );
+
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAConstruct.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAConstruct.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAConstruct.c	(revision 22158)
@@ -0,0 +1,1577 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <strings.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAFlags.h"
+#include "pmConcepts.h"
+#include "pmFPAConstruct.h"
+#include "pmFPAUtils.h"
+#include "pmHDUUtils.h"
+
+#define TABLE_OF_CONTENTS "CONTENTS"    // Name for camera format metadata containing the contents
+#define CHIP_TYPES "CHIPS"              // Name for camera format metadata containing the chip types
+#define CELL_TYPES "CELLS"              // Name for camera format metadata containing the cell types
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// File-static functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Read data for a particular cell from the camera format description
+static psMetadata *getCellData(const psMetadata *format, // The camera format description
+                               const char *cellName // The name of the cell
+                              )
+{
+    assert(format);
+    assert(cellName && strlen(cellName) > 0);
+
+    bool status = true;                 // Result of MD lookup
+    psMetadata *cells = psMetadataLookupMetadata(&status, format, CELL_TYPES); // The CELLS
+    if (!status || !cells) {
+        psError(PS_ERR_IO, true, "Unable to find %s in camera format.\n", CELL_TYPES);
+        return NULL;
+    }
+
+    psMetadata *cellData = psMetadataLookupMetadata(&status, cells, cellName); // The data for the particular cell
+    if (!status || !cellData) {
+        psWarning("Unable to find specs for cell %s: ignored\n", cellName);
+    }
+
+    return cellData;
+}
+
+// Parse a list of first:second:third pairs in a string
+static int parseContent(psArray **first, // Array of the first values
+                         psArray **second, // Array of the second values
+                         psArray **third, // Array of the third values
+                         const char *string // The string to parse
+                        )
+{
+    assert(string && strlen(string) > 0);
+    // Must populate 'first', 'second', 'third' in order.
+    assert(!second || first);
+    assert(!third || second);
+
+    int numArrays = third ? 3 : (second ? 2 : 1); // Number of arrays
+
+    psList *values = psStringSplit(string, " ,;", true); // List of the parts
+    int num = values->n; // number of parsed content elements
+
+    // extend the arrays if they exist, create new ones if they don't
+    if (first && !*first) {
+        *first = psArrayAllocEmpty(values->n);
+    }
+    if (second && !*second) {
+        *second = psArrayAllocEmpty(values->n);
+    }
+    if (third && !*third) {
+        *third = psArrayAllocEmpty(values->n);
+    }
+
+    psListIterator *valuesIter = psListIteratorAlloc(values, PS_LIST_HEAD, false); // Iterator for values
+    psString value = NULL;               // "first:second:third" string
+    while ((value = psListGetAndIncrement(valuesIter))) {
+        psArray *fst = psStringSplitArray(value, ":", true); // First, second, third
+        switch (numArrays) {
+          case 3:
+            psArrayAdd(*third, 8, fst->data[2]);
+          case 2:
+            psArrayAdd(*second, 8, fst->data[1]);
+          case 1:
+            psArrayAdd(*first, 8, fst->data[0]);
+            break;
+        default:
+          psAbort("Should never get here.");
+        }
+        psFree(fst);
+    }
+    psFree(valuesIter);
+    psFree(values);
+
+    return num;
+}
+
+// Get the name of a PHU chip or cell from the header
+static psString phuNameFromHeader(const char *name, // The name to lookup: "CELL.NAME" or "CHIP.NAME"
+                                  const psMetadata *fileInfo, // FILE within the camera format description
+                                  const psMetadata *header // Primary header
+                                 )
+{
+    assert(name && strlen(name) > 0);
+    assert(fileInfo);
+    assert(header);
+
+    bool mdok = true;                   // Result of MD lookup
+    psString keyword = psMetadataLookupStr(&mdok, fileInfo, name);
+    if (!mdok || strlen(keyword) == 0) {
+        return false;
+    }
+    psMetadataItem *resultItem = psMetadataLookup(header, keyword);
+    if (!resultItem) {
+        psError(PS_ERR_IO, true, "Unable to find %s in primary header to identify %s.\n", keyword, name);
+        return NULL;
+    }
+    return psMetadataItemParseString(resultItem);
+}
+
+// Add an HDU to the FPA
+static bool addHDUtoFPA(pmFPA *fpa,     // FPA to which to add
+                        pmHDU *hdu      // HDU to be added
+                       )
+{
+    assert(fpa);
+    assert(hdu);
+
+    if (fpa->hdu) {
+        // Something's already here
+        if (fpa->hdu != hdu) {
+            psError(PS_ERR_IO, true, "Unable to add HDU since FPA already has one.\n");
+        }
+        return false;
+    }
+    fpa->hdu = psMemIncrRefCounter(hdu);
+    pmFPASetFileStatus(fpa, true);
+
+    return true;
+}
+
+// Add an HDU to the chip
+static bool addHDUtoChip(pmChip *chip,  // Chip to which to add
+                         pmHDU *hdu     // HDU to be added
+                        )
+{
+    assert(chip);
+    assert(hdu);
+
+    if (chip->hdu) {
+        // Something's already here
+        if (chip->hdu != hdu) {
+            psError(PS_ERR_IO, true, "Unable to add HDU since chip already has one.\n");
+        }
+        return false;
+    }
+    chip->hdu = psMemIncrRefCounter(hdu);
+    pmChipSetFileStatus(chip, true);
+
+    return true;
+}
+
+// Add an HDU to the cell
+static bool addHDUtoCell(pmCell *cell,  // Cell to which to add
+                         pmHDU *hdu     // HDU to be added
+                        )
+{
+    assert(cell);
+    assert(hdu);
+
+    if (cell->hdu) {
+        // Something's already here
+        if (cell->hdu != hdu) {
+            psError(PS_ERR_IO, true, "Unable to add HDU since cell already has one.\n");
+        }
+        return false;
+    }
+    cell->hdu = psMemIncrRefCounter(hdu);
+    pmCellSetFileStatus(cell, true);
+
+    return true;
+}
+
+
+// Looks up the particular content, based on the chip and cell
+static const char *getContent(const psMetadata *fileInfo, // The FILE from the camera format configuration
+                              const psMetadata *header, // The FITS header
+                              const psMetadata *contents // The CONTENTS from the camera format configuration
+                             )
+{
+    assert(fileInfo);
+    assert(contents);
+    assert(header);
+
+    const char *contentHeader = psMetadataLookupStr(NULL, fileInfo, "CONTENT"); // Keyword to get contents
+    if (!contentHeader || strlen(contentHeader) == 0) {
+        psError(PS_ERR_UNEXPECTED_NULL, false,
+                "Unable to find CONTENT in FILE within camera format configuration.\n");
+        return NULL;
+    }
+
+    psMetadataItem *contentKey = psMetadataLookup(header, contentHeader); // Key to CONTENTS menu
+    if (!contentKey) {
+        psError(PS_ERR_UNEXPECTED_NULL, false,
+                "Unable to find %s in header to determine file content.", contentHeader);
+        return NULL;
+    }
+
+    psString contentKeyStr = psMetadataItemParseString(contentKey); // Key, as a string
+
+    psTrace("psModules.camera", 5, "Looking up %s in the CONTENTS.\n", contentKeyStr);
+    const char *content = psMetadataLookupStr(NULL, contents, contentKeyStr);
+    if (!content || strlen(content) == 0) {
+        psError(PS_ERR_IO, false, "Unable to find %s in the CONTENTS.\n", contentKeyStr);
+        return NULL;
+    }
+
+    psFree(contentKeyStr);
+
+    return content;
+}
+
+
+// Given a list of contents, put the HDU in the correct place and plug in the cell configuration information
+static bool processContents(pmFPA *fpa,  // The FPA
+                            pmChip *chip, // The chip
+                            pmHDU *hdu,  // The HDU to be added
+                            pmFPALevel level, // The level at which to add the HDU
+                            psArray *chipNames, // The chip names
+                            psArray *cellNames, // The cell names
+                            psArray *cellTypes, // The cell types
+                            const psMetadata *format // Camera format configuration
+                            )
+{
+    assert(fpa);
+    assert(cellTypes);
+    long num = cellTypes->n;            // Number of entries to add
+    assert(chip || (chipNames && chipNames->n == num));
+    assert(cellNames && cellNames->n == num);
+    assert(format);
+
+    if (hdu && level == PM_FPA_LEVEL_FPA) {
+        if (!addHDUtoFPA(fpa, hdu)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to add HDU to FPA");
+            return false;
+        }
+    }
+    // Load fpa-related concepts
+    if (!pmConceptsReadFPA(fpa, PM_CONCEPT_SOURCE_DEFAULTS, false, NULL)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read concepts from camera and defaults for fpa\n");
+        return false;
+    }
+
+    for (int i = 0; i < num; i++) {
+        psString cellType = cellTypes->data[i]; // The type of the cell
+
+        // Find the chip
+        pmChip *newChip;                // Chip of interest
+        if (chip) {
+            newChip = chip;
+        } else {
+            psString chipName = chipNames->data[i]; // The name of the chip
+            int chipNum = pmFPAFindChip(fpa, chipName); // The chip we're looking for
+            if (chipNum == -1) {
+                psError(PS_ERR_LOCATION_INVALID, false,
+                        "Unable to find chip %s in fpa --- ignored.\n", chipName);
+                return false;
+            }
+            newChip = fpa->chips->data[chipNum];
+        }
+
+        // Put in the HDU
+        if (hdu && level == PM_FPA_LEVEL_CHIP) {
+            addHDUtoChip(newChip, hdu);
+        }
+        // Load chip-related concepts
+        if (!pmConceptsReadChip(newChip, PM_CONCEPT_SOURCE_DEFAULTS, false, false, NULL)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to read concepts from camera and defaults for chip\n");
+            return false;
+        }
+
+        // Find the cell
+        pmCell *newCell;                // Cell of interest
+        psString cellName = cellNames->data[i]; // The name of the cell
+        int cellNum = pmChipFindCell(newChip, cellName); // The cell we're looking for
+        if (cellNum == -1) {
+            psError(PS_ERR_LOCATION_INVALID, false, "Unable to find cell %s in chip --- ignored.\n",
+                    cellName);
+            return false;
+        }
+        newCell = newChip->cells->data[cellNum];
+
+        psMetadata *cellData = getCellData(format, cellType); // Data for this cell
+
+        if (hdu && level == PM_FPA_LEVEL_CELL) {
+            addHDUtoCell(newCell, hdu);
+        }
+
+        // Put in the cell data
+        if (newCell->config) {
+            psWarning("Overwriting cell data in chip\n");
+            psFree(newCell->config); // Make way!
+        }
+        newCell->config = psMemIncrRefCounter(cellData);
+        if (!pmConceptsReadCell(newCell, PM_CONCEPT_SOURCE_CELLS | PM_CONCEPT_SOURCE_DEFAULTS,
+                                false, NULL)) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Unable to read concepts from camera and defaults for cell type %s", cellType);
+            return false;
+        }
+    }
+
+    return true;
+}
+
+#if 0
+// Return the level at which EXTENSIONS go, from the FILE metadata within the camera format
+static pmFPALevel hduLevel(const psMetadata *format // The camera format configuration
+                          )
+{
+    assert(format);
+
+    bool mdok = true;                   // Status of MD lookup
+    psMetadata *file = psMetadataLookupMetadata(&mdok, format, "FILE"); // File information
+    if (!mdok || !file) {
+        psError(PS_ERR_IO, true, "Unable to find FILE information in camera format configuration.\n");
+        return PM_FPA_LEVEL_NONE;
+    }
+    const char *extType = psMetadataLookupStr(&mdok, file, "EXTENSIONS");
+    if (!mdok || !extType || strlen(extType) == 0) {
+        psError(PS_ERR_IO, true, "Unable to find EXTENSIONS in the FILE information in the camera format"
+                " configuration.\n");
+        return PM_FPA_LEVEL_NONE;
+    }
+
+    // Where do we stick in the HDUs?
+    pmFPALevel level = PM_FPA_LEVEL_NONE; // Level for HDU insertion
+    if (strcasecmp(extType, "CHIP") == 0) {
+        level = PM_FPA_LEVEL_CHIP;
+    } else if (strcasecmp(extType, "CELL") == 0) {
+        level = PM_FPA_LEVEL_CELL;
+    } else if (strcasecmp(extType, "NONE") != 0) {
+        psError(PS_ERR_IO, true, "EXTENSIONS is not CHIP or CELL or NONE.\n");
+    }
+
+    return level;
+}
+#endif
+
+// Find the chip of interest within the FPA
+static bool whichChip(int *chipNum, // Chip number, modified
+                      psString *chipType, // Type of chip, modified
+                      const pmFPA *fpa, // FPA holding chip of interest
+                      const char *content // Content consisting of chipName:chipType
+                      )
+{
+    assert(chipType);
+    assert(fpa);
+    assert(content);
+
+    psArray *chipNames = NULL;
+    psArray *chipTypes = NULL;
+    if (parseContent(&chipNames, &chipTypes, NULL, content) != 1) {
+        psError(PS_ERR_UNKNOWN, false,
+                "Unable to parse chipName:chipType in %s in camera format",
+                TABLE_OF_CONTENTS);
+        return false;
+    }
+
+    psString chipName = psMemIncrRefCounter(chipNames->data[0]); // Name of chip
+    *chipType = psMemIncrRefCounter(chipTypes->data[0]); // Type of chip
+    psFree(chipNames);
+    psFree(chipTypes);
+
+    psTrace("psModules.camera", 5, "This is chip %s\n", chipName);
+
+    // Get the chip
+    *chipNum = pmFPAFindChip(fpa, chipName); // Chip number
+    if (*chipNum == -1) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find chip %s in FPA.\n", chipName);
+        psFree(chipName);
+        return false;
+    }
+    psFree(chipName);
+
+    return true;
+}
+
+
+// Process a chip, using the cellName:cellType pair
+static bool processChip(const psMetadata *format, // Camera format
+                        const psMetadataItem *chipContents, // Contents of chip, cellName:cellType pairs (either in a string or a metadata)
+                        pmFPA *fpa, // FPA of interest
+                        pmChip *chip, // Chip of interest
+                        pmFPALevel level, // Level for HDU to go
+                        pmHDU *hdu      // HDU to add
+    )
+{
+    assert(format);
+    assert(chipContents);
+    assert(fpa);
+
+    psMetadata *chips = psMetadataLookupMetadata(NULL, format, CHIP_TYPES); // The chip types
+    if (!chips) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find %s in camera format.", CHIP_TYPES);
+        return false;
+    }
+
+    psArray *cellNames = NULL;      // Cell names
+    psArray *cellTypes = NULL;      // Cell types
+
+    int nParsed = 0;
+
+    switch (chipContents->type) {
+      case PS_DATA_STRING: {
+          nParsed = parseContent(&cellNames, &cellTypes, NULL, chipContents->data.str);
+          break;
+      }
+      case PS_DATA_METADATA: {
+          psMetadataIterator *iter = psMetadataIteratorAlloc(chipContents->data.md, PS_LIST_HEAD, NULL); // Iterator
+          psMetadataItem *item;           // Item from iteration
+          while ((item = psMetadataGetAndIncrement(iter))) {
+              if (item->type != PS_DATA_STRING) {
+                  psWarning ("Item %s in camera format chip table is not of type STR.", item->name);
+                  continue;
+              }
+              nParsed += parseContent(&cellNames, &cellTypes, NULL, item->data.str);
+          }
+          psFree (iter);
+          break;
+      }
+      default:
+        psWarning ("Item %s in camera format chip table is not of type STR.", chipContents->name);
+        break;
+    }
+
+    if (nParsed == 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "Unable to parse chip contents (within %s in camera format) as cellName:cellType",
+                CHIP_TYPES);
+        psFree(cellNames);
+        psFree(cellTypes);
+        return false;
+    }
+
+    if (!processContents(fpa, chip, hdu, level, NULL, cellNames, cellTypes, format)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to set contents for chip from camera format.");
+        psFree(cellNames);
+        psFree(cellTypes);
+        return false;
+    }
+
+    psFree(cellNames);
+    psFree(cellTypes);
+
+    return true;
+}
+
+// Given a chip, find the corresponding type by searching through the contents, looking for a match to its
+// name
+psString findChipType(const pmChip *chip, // Chip of interest
+                      psMetadata *contents // Contents, from camera format
+                      )
+{
+    assert(chip);
+    assert(contents);
+
+    const char *chipName = psMetadataLookupStr(NULL, chip->concepts, "CHIP.NAME"); // Name of chip
+    assert(chipName);
+
+    psString chipType = NULL;           // Type of chip
+    psMetadataIterator *iter = psMetadataIteratorAlloc(contents, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *item;           // Item from iteration
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        if (item->type != PS_DATA_STRING) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Item %s within %s in camera format is not of type STR.", item->name, TABLE_OF_CONTENTS);
+            psFree(iter);
+            psFree(chipType);
+            return NULL;
+        }
+
+        psArray *chipNames = NULL;  // Chip names
+        psArray *chipTypes = NULL;  // Chip types
+        if (parseContent(&chipNames, &chipTypes, NULL, item->data.str) != 1) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                    "Unable to parse contents (within %s in camera format) as chipName:chipType",
+                    TABLE_OF_CONTENTS);
+            psFree(chipNames);
+            psFree(chipTypes);
+            psFree(iter);
+            psFree(chipType);
+            return NULL;
+        }
+
+        if (strcmp(chipName, chipNames->data[0]) == 0) {
+            if (chipType) {
+                if (strcmp(chipType, chipTypes->data[0]) != 0) {
+                    psError(PS_ERR_UNKNOWN, true,
+                            "Multiple instances of chip %s in contents, with differing chipType "
+                            "(%s vs %s)", chipName, chipType, (char*)chipTypes->data[0]);
+                    psFree(chipNames);
+                    psFree(chipTypes);
+                    psFree(iter);
+                    psFree(chipType);
+                    return NULL;
+                }
+            } else {
+                chipType = psMemIncrRefCounter(chipTypes->data[0]);
+            }
+        }
+        psFree(chipNames);
+        psFree(chipTypes);
+    }
+    psFree(iter);
+
+    if (!chipType) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to identify chip type for chip %s", chipName);
+        return NULL;
+    }
+
+    return chipType;
+}
+
+// PHU=FPA and EXTENSIONS=CHIP:
+// TABLE_OF_CONTENTS(METADATA) has a list of extensions, each with a chipName:chipType.
+// CHIP_TYPES(METADATA) has a list of chip types, each with cellName:cellType
+static bool addSource_FPA_CHIP(pmFPA *fpa, // FPA to which to add
+                               const psMetadata *format // The camera format
+                               )
+{
+    assert(fpa);
+    assert(format);
+
+    psMetadata *contents = psMetadataLookupMetadata(NULL, format, TABLE_OF_CONTENTS); // The contents
+    if (!contents) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find %s in camera format.", TABLE_OF_CONTENTS);
+        return false;
+    }
+
+    psMetadata *chips = psMetadataLookupMetadata(NULL, format, CHIP_TYPES); // The chip types
+    if (!chips) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find %s in camera format.", CHIP_TYPES);
+        return false;
+    }
+
+    // Iterate over all extensions
+    psMetadataIterator *contentsIter = psMetadataIteratorAlloc(contents, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *item;               // Item from iteration
+    while ((item = psMetadataGetAndIncrement(contentsIter))) {
+        if (item->type != PS_DATA_STRING) {
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    "Type for %s (%x) in %s METADATA in camera format is not STR",
+                    item->name, item->type, TABLE_OF_CONTENTS);
+            psFree(contentsIter);
+            return false;
+        }
+
+        const char *extname = item->name; // Extension name
+        pmHDU *hdu = pmHDUAlloc(extname); // HDU for this extension
+        // Casting to avoid "warning: passing arg 1 of `p_psMemIncrRefCounter' discards qualifiers from
+        // pointer target type"
+        hdu->format = psMemIncrRefCounter((const psPtr)format);
+
+        // What's in the extension?  It's specified by chipName:chipType
+        // Assume that an extension contains only a single chip, instead of multiple chips
+        psString chipType = NULL;       // Type of chip
+        int chipNum = -1;               // Chip number
+        if (!whichChip(&chipNum, &chipType, fpa, item->data.str)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to determine chip from contents");
+            return false;
+        }
+        pmChip *chip = fpa->chips->data[chipNum]; // Chip of interest
+
+        const psMetadataItem *chipContents = psMetadataLookup(chips, chipType); // Contents of chip
+        psFree(chipType);
+        if (!chipContents) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find chip type %s in %s.",
+                    chipType, CHIP_TYPES);
+            psFree(hdu);
+            psFree(contentsIter);
+            return false;
+        }
+
+        if (!processChip(format, chipContents, fpa, chip, PM_FPA_LEVEL_CHIP, hdu)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to process chip %d\n", chipNum);
+            psFree(hdu);
+            psFree(contentsIter);
+            return false;
+        }
+
+        psFree(hdu);                    // Drop reference
+    }
+    psFree(contentsIter);
+
+    return true;
+}
+
+// PHU=FPA and EXTENSIONS=CELL:
+// TABLE_OF_CONTENTS(METADATA) has a list of extensions, each with a chipName:cellName:cellType.
+static bool addSource_FPA_CELL(pmFPA *fpa, // FPA to which to add
+                               const psMetadata *format // The camera format
+                               )
+{
+    assert(fpa);
+    assert(format);
+
+    psMetadata *contents = psMetadataLookupMetadata(NULL, format, TABLE_OF_CONTENTS); // The contents
+    if (!contents) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find %s in camera format.", TABLE_OF_CONTENTS);
+        return false;
+    }
+
+    // Iterate over all extensions
+    psMetadataIterator *contentsIter = psMetadataIteratorAlloc(contents, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *item;               // Item from iteration
+    while ((item = psMetadataGetAndIncrement(contentsIter))) {
+        if (item->type != PS_DATA_STRING) {
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    "Type for %s (%x) in %s METADATA in camera format is not STR",
+                    item->name, item->type, TABLE_OF_CONTENTS);
+            psFree(contentsIter);
+            return false;
+        }
+
+        const char *extname = item->name; // Extension name
+        pmHDU *hdu = pmHDUAlloc(extname); // HDU for this extension
+        // Casting to avoid "warning: passing arg 1 of `p_psMemIncrRefCounter' discards qualifiers from
+        // pointer target type"
+        hdu->format = psMemIncrRefCounter((const psPtr)format);
+
+        // What's in the extension?  It's specified by (possibly multiple) chipName:cellName:cellType
+
+        psArray *chipNames = NULL;      // Chip names
+        psArray *cellNames = NULL;      // Cell names
+        psArray *cellTypes = NULL;      // Cell types
+        if (parseContent(&chipNames, &cellNames, &cellTypes, item->data.str) == 0) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                    "Unable to parse extension contents (within %s->%s in camera format) as "
+                    "chipName:cellName:cellType", TABLE_OF_CONTENTS, extname);
+            psFree(chipNames);
+            psFree(cellNames);
+            psFree(cellTypes);
+            psFree(hdu);
+            psFree(contentsIter);
+            return false;
+        }
+
+        if (!processContents(fpa, NULL, hdu, PM_FPA_LEVEL_CELL, chipNames, cellNames, cellTypes,
+                             format)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to set contents from camera format.");
+            psFree(chipNames);
+            psFree(cellNames);
+            psFree(cellTypes);
+            psFree(hdu);
+            psFree(contentsIter);
+            return false;
+        }
+
+        psFree(chipNames);
+        psFree(cellNames);
+        psFree(cellTypes);
+
+        psFree(hdu);                    // Drop reference
+    }
+    psFree(contentsIter);
+
+    return true;
+}
+
+// PHU=FPA and EXTENSIONS=NONE:
+// TABLE_OF_CONTENTS(STR) has a list of chipName:cellName:cellType.
+static bool addSource_FPA_NONE(pmFPA *fpa, // FPA to which to add
+                               const psMetadata *format // The camera format
+                               )
+{
+    assert(fpa);
+    assert(format);
+
+    psString contents = psMetadataLookupStr(NULL, format, TABLE_OF_CONTENTS); // The contents
+    if (!contents) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find %s in camera format.", TABLE_OF_CONTENTS);
+        return false;
+    }
+
+    // What's in the file?  It's specified by (possibly multiple) chipName:cellName:cellType
+
+    psArray *chipNames = NULL;          // Chip names
+    psArray *cellNames = NULL;          // Cell names
+    psArray *cellTypes = NULL;          // Cell types
+    if (parseContent(&chipNames, &cellNames, &cellTypes, contents) == 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "Unable to parse contents (within %s in camera format) as chipName:cellName:cellType",
+                TABLE_OF_CONTENTS);
+        psFree(chipNames);
+        psFree(cellNames);
+        psFree(cellTypes);
+        return false;
+    }
+
+    if (!processContents(fpa, NULL, NULL, PM_FPA_LEVEL_NONE, chipNames, cellNames, cellTypes,
+                         format)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to set contents from camera format.");
+        psFree(chipNames);
+        psFree(cellNames);
+        psFree(cellTypes);
+        return false;
+    }
+
+    psFree(chipNames);
+    psFree(cellNames);
+    psFree(cellTypes);
+
+    return true;
+}
+
+
+// PHU=CHIP and EXTENSIONS=CELL:
+// TABLE_OF_CONTENTS(METADATA) has a menu of contents, each with a chipName:chipType.
+// CHIP_TYPES(METADATA) has a list of chip types(METADATA), each with extension(STR) with cellName:cellType
+static bool addSource_CHIP_CELL(pmFPAview *view, // View for PHU, modified
+                                pmFPA *fpa, // FPA to which to add
+                                pmChip *chip, // Known chip to which to add, or NULL
+                                const psMetadata *format, // The camera format
+                                pmHDU *phdu, // The Primary HDU
+                                bool install // Install the HDUs?
+                                )
+{
+    assert(view);
+    assert(fpa);
+    assert(format);
+    assert(phdu);
+
+    psMetadata *contents = psMetadataLookupMetadata(NULL, format, TABLE_OF_CONTENTS); // The contents
+    if (!contents) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find %s in camera format.", TABLE_OF_CONTENTS);
+        return false;
+    }
+
+    psMetadata *chips = psMetadataLookupMetadata(NULL, format, CHIP_TYPES); // The chip types
+    if (!chips) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find %s in camera format.", CHIP_TYPES);
+        return false;
+    }
+
+    psMetadata *fileInfo = psMetadataLookupMetadata(NULL, format, "FILE"); // The file information
+    if (!fileInfo) {
+        psError(PS_ERR_IO, false, "Unable to find FILE in the camera format configuration.\n");
+        return false;
+    }
+
+
+    psString chipType = NULL;           // Type of chip
+    if (chip) {
+        // We're given the chip (adding source from view)
+        // Need to identify the chip type, which we will do by traversing the contents
+        chipType = findChipType(chip, contents);
+    } else {
+        // We're given a header, from which to identify what chip we've got, and its type
+        const char *content = getContent(fileInfo, phdu->header, contents); // The contents of this chip
+        if (!content) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to determine content of file.");
+            return false;
+        }
+
+        int chipNum = -1;               // Chip number
+        if (!whichChip(&chipNum, &chipType, fpa, content)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to determine chip from contents");
+            return false;
+        }
+        chip = fpa->chips->data[chipNum]; // Chip of interest
+        view->chip = chipNum;
+    }
+
+    if (!install) {
+        // Everything below is about installing the HDUs
+        psFree(chipType);
+        return true;
+    }
+
+    if (!addHDUtoChip(chip, phdu)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to add HDU to chip\n");
+        psFree(chipType);
+        return false;
+    }
+
+    psMetadata *chipContents = psMetadataLookupMetadata(NULL, chips, chipType); // Contents of chip
+    psFree(chipType);
+    if (!chipContents) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find chip type %s in %s.",
+                chipType, CHIP_TYPES);
+        return false;
+    }
+
+    psMetadataIterator *contentsIter = psMetadataIteratorAlloc(chipContents, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *contentItem;        // Content, from iteration
+    while ((contentItem = psMetadataGetAndIncrement(contentsIter))) {
+        pmHDU *hdu = pmHDUAlloc(contentItem->name); // HDU for this extension
+        // Casting to avoid "warning: passing arg 1 of `p_psMemIncrRefCounter' discards qualifiers from
+        // pointer target type"
+        hdu->format = psMemIncrRefCounter((const psPtr)format);
+
+        if (!processChip(format, contentItem, fpa, chip, PM_FPA_LEVEL_CELL, hdu)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to process chip\n");
+            psFree(hdu);
+            psFree(contentsIter);
+            return false;
+        }
+
+        psFree(hdu);                    // Drop reference
+    }
+    psFree(contentsIter);
+
+    if (!pmConceptsReadChip(chip, PM_CONCEPT_SOURCE_DEFAULTS | PM_CONCEPT_SOURCE_PHU, true, true, NULL)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read concepts for chip.");
+        return false;
+    }
+
+    return true;
+}
+
+// PHU=CHIP and EXTENSIONS=NONE:
+// TABLE_OF_CONTENTS(METADATA) has a menu of contents, each with a chipName:chipType.
+// CHIP_TYPES(METADATA) has a list of chip types, each with cellName:cellType
+static bool addSource_CHIP_NONE(pmFPAview *view, // View for PHU, modified
+                                pmFPA *fpa, // FPA to which to add
+                                pmChip *chip, // Known chip to which to add, or NULL
+                                const psMetadata *format, // The camera format
+                                pmHDU *phdu, // Primary HDU
+                                bool install // Install the HDUs?
+                                )
+{
+    assert(fpa);
+    assert(format);
+    assert(phdu);
+
+    psMetadata *contents = psMetadataLookupMetadata(NULL, format, TABLE_OF_CONTENTS); // The contents
+    if (!contents) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find %s in camera format.", TABLE_OF_CONTENTS);
+        return false;
+    }
+
+    psMetadata *chips = psMetadataLookupMetadata(NULL, format, CHIP_TYPES); // The chip types
+    if (!chips) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find %s in camera format.", CHIP_TYPES);
+        return false;
+    }
+
+    psMetadata *fileInfo = psMetadataLookupMetadata(NULL, format, "FILE"); // The file information
+    if (!fileInfo) {
+        psError(PS_ERR_IO, false, "Unable to find FILE in the camera format configuration.\n");
+        return false;
+    }
+
+    psString chipType = NULL;           // Type of chip
+    if (chip) {
+        // We're given the chip (adding source from view)
+        // Need to identify the chip type, which we will do by traversing the contents
+        chipType = findChipType(chip, contents);
+    } else {
+        const char *content = getContent(fileInfo, phdu->header, contents); // The chip type
+
+        int chipNum = -1;               // Chip number
+        if (!whichChip(&chipNum, &chipType, fpa, content)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to determine chip from contents");
+            return false;
+        }
+        chip = fpa->chips->data[chipNum]; // Chip of interest
+        view->chip = chipNum;
+    }
+
+    if (!install) {
+        // Everything below is about installing the HDU
+        psFree(chipType);
+        return true;
+    }
+
+    if (!addHDUtoChip(chip, phdu)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to add HDU to chip\n");
+        psFree(chipType);
+        return false;
+    }
+
+    // What's in the chip?
+    psMetadataItem *chipContents = psMetadataLookup(chips, chipType); // Contents of the chip
+    if (!chipContents) {
+        psError(PS_ERR_UNEXPECTED_NULL, false,
+                "Unable to find chip type %s in %s of camera format", chipType, CHIP_TYPES);
+        return false;
+    }
+    psFree(chipType);
+
+    if (!processChip(format, chipContents, fpa, chip, PM_FPA_LEVEL_NONE, NULL)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to process chip\n");
+        return false;
+    }
+
+    if (!pmConceptsReadChip(chip, PM_CONCEPT_SOURCE_DEFAULTS | PM_CONCEPT_SOURCE_PHU, true, true, NULL)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read concepts for chip.");
+        return false;
+    }
+
+    return true;
+}
+
+// PHU=CELL and EXTENSIONS=NONE:
+// TABLE_OF_CONTENTS(METADATA) has a menu of contents, each with a chipName:cellName:cellType
+static bool addSource_CELL_NONE(pmFPAview *view, // View for PHU, modified
+                                pmFPA *fpa, // FPA to which to add
+                                pmCell *cell, // Known cell to which to add, or NULL
+                                const psMetadata *format, // The camera format
+                                pmHDU *phdu, // The Primary HDU
+                                bool install // Install the HDUs?
+                                )
+{
+    assert(fpa);
+    assert(format);
+    assert(phdu);
+
+    psMetadata *contents = psMetadataLookupMetadata(NULL, format, TABLE_OF_CONTENTS); // The contents
+    if (!contents) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find %s in camera format.", TABLE_OF_CONTENTS);
+        return false;
+    }
+
+    psMetadata *fileInfo = psMetadataLookupMetadata(NULL, format, "FILE"); // The file information
+    if (!fileInfo) {
+        psError(PS_ERR_IO, false, "Unable to find FILE in the camera format configuration.\n");
+        return false;
+    }
+
+    psArray *chipNames = NULL;          // Chip names
+    psArray *cellNames = NULL;          // Cell names
+    psArray *cellTypes = NULL;          // Cell types
+    pmChip *chip = NULL;                // Chip of interest
+    if (cell) {
+        // We're given the chip and cell (adding source from view)
+        // Need to identify the cell type, which we will do by traversing the contents
+
+        chip = cell->parent;            // The chip of interest
+        psString cellType = NULL;       // Type of cell
+
+        // The below is very similar to findChipType(), but with modifications for finding the cellType
+        const char *chipName = psMetadataLookupStr(NULL, chip->concepts, "CHIP.NAME"); // Name of chip
+        assert(chipName);
+        const char *cellName = psMetadataLookupStr(NULL, cell->concepts, "CELL.NAME"); // Name of cell
+        assert(cellName);
+
+        psMetadataIterator *iter = psMetadataIteratorAlloc(contents, PS_LIST_HEAD, NULL); // Iterator
+        psMetadataItem *item;           // Item from iteration
+        while ((item = psMetadataGetAndIncrement(iter))) {
+            if (item->type != PS_DATA_STRING) {
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                        "Item %s within %s in camera format is not of type STR.",
+                        item->name, TABLE_OF_CONTENTS);
+                psFree(chipNames);
+                psFree(cellNames);
+                psFree(cellTypes);
+                psFree(iter);
+                psFree(cellType);
+                return false;
+            }
+
+            psArray *testChipNames = NULL; // Chip names
+            psArray *testCellNames = NULL; // Cell names
+            psArray *testCellTypes = NULL; // Cell types
+            if (parseContent(&testChipNames, &testCellTypes, &testCellTypes, item->data.str) != 1) {
+                psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                        "Unable to parse contents (within %s in camera format) as chipName:cellName:cellType",
+                        TABLE_OF_CONTENTS);
+                psFree(chipNames);
+                psFree(cellNames);
+                psFree(cellTypes);
+                psFree(testChipNames);
+                psFree(testCellNames);
+                psFree(testCellTypes);
+                psFree(iter);
+                psFree(cellType);
+                return false;
+            }
+
+            if (strcmp(chipName, chipNames->data[0]) == 0 && strcmp(cellName, cellNames->data[0]) == 0) {
+                if (cellType) {
+                    if (strcmp(cellType, cellTypes->data[0]) != 0) {
+                        psError(PS_ERR_UNKNOWN, true,
+                                "Multiple instances of chip %s cell %s in contents, with differing cellType "
+                                "(%s vs %s)", chipName, cellName, cellType, (char*)cellTypes->data[0]);
+                        psFree(chipNames);
+                        psFree(cellNames);
+                        psFree(cellTypes);
+                        psFree(testChipNames);
+                        psFree(testCellNames);
+                        psFree(testCellTypes);
+                        psFree(iter);
+                        psFree(cellType);
+                        return false;
+                    }
+                } else {
+                    cellType = psMemIncrRefCounter(cellTypes->data[0]);
+                    chipNames = psMemIncrRefCounter(testChipNames);
+                    cellNames = psMemIncrRefCounter(testCellNames);
+                    cellTypes = psMemIncrRefCounter(testCellTypes);
+                }
+            }
+            psFree(testChipNames);
+            psFree(testCellNames);
+            psFree(testCellTypes);
+        }
+        psFree(iter);
+
+        if (!cellType) {
+            psError(PS_ERR_UNKNOWN, true, "Unable to identify cell type for chip %s cell %s",
+                    chipName, cellName);
+            psFree(chipNames);
+            psFree(cellNames);
+            psFree(cellTypes);
+            return false;
+        }
+
+        // We don't really care about the cell type here --- it's taken care of by processContents
+        psFree(cellType);
+
+    } else {
+        const char *content = getContent(fileInfo, phdu->header, contents); // Content of cell
+
+        if (parseContent(&chipNames, &cellNames, &cellTypes, content) != 1) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                    "Unable to parse cell contents (%s) as cellName:cellType", content);
+            psFree(chipNames);
+            psFree(cellNames);
+            psFree(cellTypes);
+            return false;
+        }
+
+        int chipNum = pmFPAFindChip(fpa, chipNames->data[0]); // Chip number
+        if (chipNum == -1) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to find chip %s referred to in contents",
+                    (char*)chipNames->data[0]);
+            psFree(chipNames);
+            psFree(cellNames);
+            psFree(cellTypes);
+            return false;
+        }
+        chip = fpa->chips->data[chipNum];
+
+        int cellNum = pmChipFindCell(chip, cellNames->data[0]); // Cell number
+        if (cellNum == -1) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to find cell %s referred to in contents",
+                    (char*)cellNames->data[0]);
+            psFree(chipNames);
+            psFree(cellNames);
+            psFree(cellTypes);
+            return false;
+        }
+        cell = chip->cells->data[cellNum];
+
+        view->chip = chipNum;
+        view->cell = cellNum;
+
+        psFree(chipNames);
+        psFree(cellNames);
+        psFree(cellTypes);
+    }
+
+    if (!install) {
+        // Everything below is about installing the HDU
+        psFree(chipNames);
+        psFree(cellNames);
+        psFree(cellTypes);
+        return true;
+    }
+
+    if (!processContents(fpa, NULL, phdu, PM_FPA_LEVEL_NONE, chipNames, cellNames, cellTypes, format)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to set contents for cell from camera format.");
+        psFree(chipNames);
+        psFree(cellNames);
+        psFree(cellTypes);
+        return false;
+    }
+
+    psFree(chipNames);
+    psFree(cellNames);
+    psFree(cellTypes);
+
+    if (!pmConceptsReadCell(cell, PM_CONCEPT_SOURCE_DEFAULTS | PM_CONCEPT_SOURCE_PHU, true, NULL)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read concepts for cell.");
+        return false;
+    }
+
+    return true;
+}
+
+
+// This is the engine for the pmFPAAddSourceFrom{Header,View} functions.
+// It uses the camera format configuration information to determine where HDUs go in the FPA.
+// It returns a view corresponding to the PHU
+static pmFPAview *addSource(pmFPA *fpa,       // The FPA
+                            const char *fpaObs, // The desired FPA observation name
+                            const pmFPAview *phuView, // The view corresponding to the PHU, or NULL
+                            const psMetadata *header, // The PHU header, or NULL
+                            const psMetadata *format, // Format of file
+                            bool install // Install the provided header in the location that we find?
+                           )
+{
+    assert(fpa);
+    assert(phuView || header);
+    assert(format);
+
+    bool mdok;                          // Status of MD lookup
+
+    // If FPA.OBS is already defined, new name must match it; otherwise, warn the user that something
+    // potentially bad is happening.
+    if (fpaObs && install) {
+        const char *currentName = psMetadataLookupStr(&mdok, fpa->concepts, "FPA.OBS"); // Current name
+        if (mdok && currentName && strlen(currentName) > 0 && strcmp(currentName, fpaObs) != 0) {
+            psWarning("FPA.OBS for new source (%s) doesn't match FPA.OBS for current fpa (%s).",
+                      fpaObs, currentName);
+        }
+        psMetadataAddStr(fpa->concepts, PS_LIST_HEAD, "FPA.OBS", PS_META_REPLACE, "Observation identifier",
+                         fpaObs);
+    } else if (!psMetadataLookup(fpa->concepts, "FPA.OBS")) {
+        // Make sure there is an FPA.OBS
+        psMetadataAddStr(fpa->concepts, PS_LIST_HEAD, "FPA.OBS", 0, "Observation identifier", "UNKNOWN");
+    }
+
+    psMetadata *fileInfo = psMetadataLookupMetadata(&mdok, format, "FILE"); // The file information
+    if (!mdok || !fileInfo) {
+        psError(PS_ERR_IO, false, "Unable to find FILE in the camera format configuration.\n");
+        return NULL;
+    }
+
+    // At what level does the PHU go?
+    const char *phuType = psMetadataLookupStr(&mdok, fileInfo, "PHU"); // What is the PHU?
+    if (!mdok || strlen(phuType) == 0) {
+        psError(PS_ERR_IO, false, "Unable to find PHU in the format specification.\n");
+        return NULL;
+    }
+
+    // Prepare the PHU to be placed in the camera hierarchy
+    pmHDU *phdu = pmHDUAlloc(NULL);     // The primary header data unit
+    // Casting to psPtr to avoide "warning: passing arg 1 of `p_psMemIncrRefCounter' discards qualifiers from
+    // pointer target type"
+    phdu->header = psMemIncrRefCounter((const psPtr)header);
+    phdu->format = psMemIncrRefCounter((const psPtr)format);
+    pmFPAview *view = pmFPAviewAlloc(0); // View, to be returned
+    if (phuView) {
+        // Copy the view, for the case where we're given a view.
+        *view = *phuView;
+    }
+
+    // And at what level do the individual extensions go?
+    const char *extType = psMetadataLookupStr(&mdok, fileInfo, "EXTENSIONS"); // What's in the extns?
+    if (!mdok || strlen(extType) == 0) {
+        psError(PS_ERR_IO, false, "Unable to find EXTENSIONS in the format specification.\n");
+        psFree(view);
+        return NULL;
+    }
+
+    // Now, there are a few cases:
+
+    // Case    PHU     EXTENSIONS     Description
+    // ====    ===     ==========     ===========
+    // 1.      FPA     CHIP           CONTENTS(METADATA) has a list of extensions, each with chipName:chipType
+    //                                CHIPS(METADATA) has a list of chip types, each with cell:type
+    // 2.      FPA     CELL           CONTENTS(METADATA) has a list of extensions, each with chip:cell:type
+    //                                No need for CHIPS.
+    // 3.      FPA     NONE           CONTENTS(STRING) has a list of extensions, chip:cell:type
+    //                                No need for CHIPS
+    // 4.      CHIP    CELL           CONTENTS(METADATA) is a menu, each with a chipName:chipType
+    //                                CHIPS(METADATA) has a list of chip types(METADATA), containg a list of
+    //                                extensions.
+    // 5.      CHIP    NONE           CONTENTS(METADATA) is a menu, each with a chipName:chipType
+    //                                CHIPS(METADATA) has a list of chip types(STRING) with cell:type
+    // 6.      CELL    NONE           CONTENTS(METADATA) is a menu, each with a chipName:cellName:cellType.
+    //                                No need for CHIPS.
+
+
+    pmFPALevel phuLevel = pmFPALevelFromName(phuType); // Level for PHU
+    pmFPALevel extLevel = pmFPALevelFromName(extType); // Level for extensions
+
+    switch (phuLevel) {
+      case PM_FPA_LEVEL_FPA: {
+          // We don't have to work out where the PHU is --- there's only one FPA.
+          // 'view' already points to the FPA.
+          switch (extLevel) {
+            case PM_FPA_LEVEL_CHIP:
+              phdu->blankPHU = true;
+              if (install) {
+                  if (!addHDUtoFPA(fpa, phdu) || !addSource_FPA_CHIP(fpa, format) ||
+                      !pmConceptsReadFPA(fpa, PM_CONCEPT_SOURCE_DEFAULTS | PM_CONCEPT_SOURCE_PHU,
+                                         true, NULL)) {
+                      psError(PS_ERR_UNKNOWN, false, "Unable to add source.");
+                      psFree(phdu);
+                      psFree(view);
+                      return NULL;
+                  }
+              }
+              psFree(phdu);
+              return view;
+            case PM_FPA_LEVEL_CELL:
+              if (install) {
+                  phdu->blankPHU = true;
+                  if (!addHDUtoFPA(fpa, phdu) || !addSource_FPA_CELL(fpa, format) ||
+                      !pmConceptsReadFPA(fpa, PM_CONCEPT_SOURCE_DEFAULTS | PM_CONCEPT_SOURCE_PHU,
+                                         true, NULL)) {
+                      psError(PS_ERR_UNKNOWN, false, "Unable to add source.");
+                      psFree(phdu);
+                      psFree(view);
+                      return NULL;
+                  }
+              }
+              psFree(phdu);
+              return view;
+            case PM_FPA_LEVEL_NONE:
+              if (install) {
+                  phdu->blankPHU = false;
+                  if (!addHDUtoFPA(fpa, phdu) || !addSource_FPA_NONE(fpa, format) ||
+                      !pmConceptsReadFPA(fpa, PM_CONCEPT_SOURCE_DEFAULTS | PM_CONCEPT_SOURCE_PHU,
+                                         true, NULL)) {
+                      psError(PS_ERR_UNKNOWN, false, "Unable to add source.");
+                      psFree(phdu);
+                      psFree(view);
+                      return NULL;
+                  }
+              }
+              psFree(phdu);
+             return view;
+            default:
+              psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                      "EXTENSIONS level (%s) incompatible with PHU level (FPA)", extType);
+              psFree(phdu);
+              psFree(view);
+              return NULL;
+          }
+          break;
+      }
+      case PM_FPA_LEVEL_CHIP: {
+          pmChip *chip = NULL;          // Appropriate chip, if the view is specified
+          if (phuView) {
+              chip = fpa->chips->data[phuView->chip];
+          }
+          switch (extLevel) {
+            case PM_FPA_LEVEL_CELL:
+              phdu->blankPHU = true;
+              if (!addSource_CHIP_CELL(view, fpa, chip, format, phdu, install)) {
+                  psError(PS_ERR_UNKNOWN, false, "Unable to add source.");
+                  psFree(phdu);
+                  psFree(view);
+                  return NULL;
+              }
+              psFree(phdu);
+              return view;
+            case PM_FPA_LEVEL_NONE:
+              phdu->blankPHU = false;
+              if (!addSource_CHIP_NONE(view, fpa, chip, format, phdu, install)) {
+                  psError(PS_ERR_UNKNOWN, false, "Unable to add source.");
+                  psFree(phdu);
+                  psFree(view);
+                  return NULL;
+              }
+              psFree(phdu);
+              return view;
+            default:
+              psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                      "EXTENSIONS level (%s) incompatible with PHU level (CHIP)", extType);
+              return NULL;
+          }
+          break;
+      }
+      case PM_FPA_LEVEL_CELL: {
+          if (extLevel != PM_FPA_LEVEL_NONE) {
+              psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                      "EXTENSIONS level (%s) incompatible with PHU level (CELL)", extType);
+              return NULL;
+          }
+          pmChip *chip = NULL;          // Appropriate chip, if the view is specified
+          pmCell *cell = NULL;          // Appropriate cell, if the view is specified
+          if (phuView) {
+              chip = fpa->chips->data[phuView->chip];
+              cell = chip->cells->data[phuView->cell];
+          }
+          phdu->blankPHU = false;
+          if (!addSource_CELL_NONE(view, fpa, cell, format, phdu, install)) {
+              psError(PS_ERR_UNKNOWN, false, "Unable to add source.");
+              psFree(phdu);
+              psFree(view);
+              return NULL;
+          }
+          psFree(phdu);
+          return view;
+          break;
+      }
+      default:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Bad PHU level: %s", phuType);
+        return NULL;
+    }
+
+    return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+pmFPA *pmFPAConstruct(const psMetadata *camera, const char *cameraName)
+{
+    PS_ASSERT_PTR_NON_NULL(camera, NULL);
+
+    pmFPA *fpa = pmFPAAlloc(camera, cameraName);    // The FPA to fill out
+
+    bool mdok = true;                   // Status from MD lookups
+    psMetadata *components = psMetadataLookupMetadata(&mdok, camera, "FPA"); // FPA components
+    if (!mdok || !components) {
+        psError(PS_ERR_IO, true, "Failed to lookup \"FPA\"");
+        psFree(fpa);
+        return NULL;
+    }
+    psMetadataIterator *componentsIter = psMetadataIteratorAlloc(components, PS_LIST_HEAD, NULL);
+    psMetadataItem *componentsItem = NULL; // Item from components
+    while ((componentsItem = psMetadataGetAndIncrement(componentsIter))) {
+        const char *chipName = componentsItem->name; // Name of the chip
+        if (componentsItem->type != PS_DATA_STRING) {
+            psWarning("Element %s in FPA within the camera configuration is not of "
+                     "type STR (type=%x) --- ignored.\n", chipName, componentsItem->type);
+            continue;
+        }
+
+        pmChip *chip = pmChipAlloc(fpa, chipName); // The chip
+        psList *cellNames = psStringSplit(componentsItem->data.V, " ,;", true); // List of cell names
+        psListIterator *cellNamesIter = psListIteratorAlloc(cellNames, PS_LIST_HEAD, false); // Iterator
+
+        psString cellName = NULL;       // Name of cell
+        while ((cellName = psListGetAndIncrement(cellNamesIter))) {
+            pmCell *cell = pmCellAlloc(chip, cellName); // New cell
+            psFree(cell);               // Drop reference
+        }
+        psFree(chip);                   // Drop reference
+        psFree(cellNamesIter);
+        psFree(cellNames);
+    }
+    psFree(componentsIter);
+
+    return fpa;
+}
+
+bool pmFPAAddSourceFromFormat(pmFPA *fpa, const char *fpaObs, const psMetadata *format)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_METADATA_NON_NULL(format, false);
+
+    // Generate the correct structure
+    pmFPALevel phuLevel = pmFPAPHULevel(format); // Level at which PHU goes
+    pmFPAview *view = pmFPAviewAlloc(0);// View for current level
+    if (phuLevel == PM_FPA_LEVEL_FPA) {
+        if (!pmFPAAddSourceFromView(fpa, fpaObs, view, format)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to add PHU to FPA.");
+            psFree(view);
+            return false;
+        }
+    } else {
+        pmChip *chip;                       // Chip from FPA
+        while ((chip = pmFPAviewNextChip(view, fpa, 1))) {
+            if (phuLevel == PM_FPA_LEVEL_CHIP) {
+                if (!pmFPAAddSourceFromView(fpa, fpaObs, view, format)) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to add PHU to FPA.");
+                    psFree(view);
+                    return false;
+                }
+            } else {
+                pmCell *cell;                   // Cell from chip
+                while ((cell = pmFPAviewNextCell(view, fpa, 1))) {
+                    if (phuLevel == PM_FPA_LEVEL_CELL) {
+                        if (!pmFPAAddSourceFromView(fpa, fpaObs, view, format)) {
+                            psError(PS_ERR_UNKNOWN, false, "Unable to add PHU to FPA.");
+                            psFree(view);
+                            return false;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    psFree(view);
+
+    return true;
+}
+
+bool pmFPAAddSourceFromView(pmFPA *fpa, const char *fpaObs, const pmFPAview *phuView,
+                            const psMetadata *format)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(phuView, false);
+    PS_ASSERT_PTR_NON_NULL(format, false);
+
+    pmFPAview *view = addSource(fpa, fpaObs, phuView, NULL, format, true);
+    bool status = (view != NULL);
+    psFree(view);
+    return status;
+}
+
+pmFPAview *pmFPAAddSourceFromHeader(pmFPA *fpa, psMetadata *phu, const psMetadata *format)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
+    PS_ASSERT_PTR_NON_NULL(phu, NULL);
+    PS_ASSERT_PTR_NON_NULL(format, NULL);
+
+    bool mdok = true;                   // Status from metadata lookups
+    psMetadata *fileInfo = psMetadataLookupMetadata(&mdok, format, "FILE"); // The file information
+    if (!mdok || !fileInfo) {
+        psError(PS_ERR_IO, false, "Unable to find FILE in the camera format configuration.\n");
+        return NULL;
+    }
+
+    // Check the name of the FPA
+    psString fpaObs = phuNameFromHeader("FPA.OBS", fileInfo, phu); // New observation name for the FPA
+    if (!fpaObs || strlen(fpaObs) == 0) {
+        psWarning("Unable to determine FPA.OBS: check for FPA.OBS in FILE in camera format");
+    }
+
+    pmFPAview *view = addSource(fpa, fpaObs, NULL, phu, format, true); // View of PHU, to return
+    psFree(fpaObs);
+
+    return view;
+}
+
+
+pmFPAview *pmFPAIdentifySourceFromHeader(pmFPA *fpa, psMetadata *phu, const psMetadata *format)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
+    PS_ASSERT_PTR_NON_NULL(phu, NULL);
+    PS_ASSERT_PTR_NON_NULL(format, NULL);
+
+    return addSource(fpa, NULL, NULL, phu, format, false);
+}
+
+
+// Print spaces to indent
+#define INDENT(FILE, LEVEL) \
+{ \
+    for (int i = 0; i < (LEVEL); i++) { \
+        fprintf(FILE, " "); \
+    } \
+}
+
+void pmFPAPrint(FILE *fd, const pmFPA *fpa, bool header, bool concepts)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa,);
+
+    INDENT(fd, 1);
+    fprintf(fd, "FPA:\n");
+    if (fpa->hdu) {
+        pmHDUPrint(fd, fpa->hdu, 2, header);
+    }
+    if (concepts) {
+        psMetadataPrint(fd, fpa->concepts, 2);
+    }
+
+    psArray *chips = fpa->chips;        // Array of chips
+    // Iterate over the FPA
+    for (int i = 0; i < chips->n; i++) {
+        INDENT(fd, 3);
+        fprintf(fd, "Chip: %d\n", i);
+        pmChip *chip = chips->data[i]; // The chip
+        if (chip->hdu) {
+            pmHDUPrint(fd, chip->hdu, 4, header);
+        }
+        if (concepts) {
+            psMetadataPrint(fd, chip->concepts, 4);
+        }
+
+        // Iterate over the chip
+        psArray *cells = chip->cells;   // Array of cells
+        for (int j = 0; j < cells->n; j++) {
+            INDENT(fd, 5);
+            fprintf(fd, "Cell: %d\n", j);
+            pmCell *cell = cells->data[j]; // The cell
+            if (cell->hdu) {
+                pmHDUPrint(fd, cell->hdu, 6, header);
+            }
+            if (concepts) {
+                psMetadataPrint(fd, cell->concepts, 6);
+            }
+
+            psArray *readouts = cell->readouts; // Array of readouts
+            for (int k = 0; k < readouts->n; k++) {
+                pmReadout *readout = readouts->data[k]; // The readout
+                INDENT(fd, 6);
+                fprintf(fd, "Readout %d:\n", k);
+                INDENT(fd, 7);
+                fprintf(fd, "col0: %d\n", readout->col0);
+                INDENT(fd, 7);
+                fprintf(fd, "row0: %d\n", readout->row0);
+                psImage *image = readout->image; // The image
+                psImage *mask = readout->mask; // The mask
+                psImage *weight = readout->weight; // The weight
+                psList *bias = readout->bias; // The list of bias images
+                if (image) {
+                    INDENT(fd, 7);
+                    fprintf(fd, "Image: [%d:%d,%d:%d] (%dx%d)\n", image->col0, image->col0 +
+                            image->numCols, image->row0, image->row0 + image->numRows, image->numCols,
+                            image->numRows);
+                }
+                if (bias) {
+                    psListIterator *biasIter = psListIteratorAlloc(bias, PS_LIST_HEAD, false); // Iterator
+                    psImage *biasImage = NULL; // Bias image from iteration
+                    while ((biasImage = psListGetAndIncrement(biasIter))) {
+                        INDENT(fd, 7);
+                        fprintf(fd, "Bias:  [%d:%d,%d:%d] (%dx%d)\n", biasImage->col0,
+                                biasImage->col0 + biasImage->numCols, biasImage->row0,
+                                biasImage->row0 + biasImage->numRows, biasImage->numCols, biasImage->numRows);
+                    }
+                    psFree(biasIter);
+                }
+                if (mask) {
+                    INDENT(fd, 7);
+                    fprintf(fd, "Mask: [%d:%d,%d:%d] (%dx%d)\n", mask->col0, mask->col0 +
+                            mask->numCols, mask->row0, mask->row0 + mask->numRows, mask->numCols,
+                            mask->numRows);
+                }
+                if (weight) {
+                    INDENT(fd, 7);
+                    fprintf(fd, "Weight: [%d:%d,%d:%d] (%dx%d)\n", weight->col0, weight->col0 +
+                            weight->numCols, weight->row0, weight->row0 + weight->numRows, weight->numCols,
+                            weight->numRows);
+                }
+            } // Iterating over cell
+        } // Iterating over chip
+    } // Iterating over FPA
+
+}
+
+
+pmFPALevel pmFPAPHULevel(const psMetadata *format)
+{
+    PS_ASSERT_METADATA_NON_NULL(format, PM_FPA_LEVEL_NONE);
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *fileInfo = psMetadataLookupMetadata(&mdok, format, "FILE"); // Contents of FILE metadata
+    if (!mdok || !fileInfo) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find FILE in camera format configuration.\n");
+        return PM_FPA_LEVEL_NONE;
+    }
+    const char *phu = psMetadataLookupStr(&mdok, fileInfo, "PHU"); // PHU level
+    if (!mdok || !phu || strlen(phu) == 0) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find PHU in FILE in camera format configuration.\n");
+        return PM_FPA_LEVEL_NONE;
+    }
+
+    return pmFPALevelFromName(phu);
+}
+
+pmFPALevel pmFPAExtensionsLevel(const psMetadata *format)
+{
+    PS_ASSERT_METADATA_NON_NULL(format, PM_FPA_LEVEL_NONE);
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *fileInfo = psMetadataLookupMetadata(&mdok, format, "FILE"); // Contents of FILE metadata
+    if (!mdok || !fileInfo) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find FILE in camera format configuration.\n");
+        return PM_FPA_LEVEL_NONE;
+    }
+
+    const char *extensions = psMetadataLookupStr(&mdok, fileInfo, "EXTENSIONS"); // EXTENSIONS level
+    if (!mdok || !extensions || strlen(extensions) == 0) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find EXTENSIONS in FILE in camera format configuration.\n");
+        return PM_FPA_LEVEL_NONE;
+    }
+
+    return pmFPALevelFromName(extensions);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAConstruct.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAConstruct.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAConstruct.h	(revision 22158)
@@ -0,0 +1,78 @@
+/* @file pmFPAConstruct.h
+ * @brief Functions to create an FPA, and add data sources to it.
+ *
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-06-05 01:31:33 $
+ * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FPA_CONSTRUCT_H
+#define PM_FPA_CONSTRUCT_H
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+/// Construct an FPA instance on the basis of a camera configuration
+///
+/// This is the function that creates the FPA hierarchy on the basis of the camera configuration.  The "FPA"
+/// entry in the camera configuration specifies the chips (each of type STR) with their component cells listed
+/// as the corresponding values (whitespace separated).  The FPA hierarchy is created devoid of any
+/// input/output sources (i.e., HDUs).
+pmFPA *pmFPAConstruct(const psMetadata *camera, ///< The camera configuration
+                      const char *cameraName ///< Name of the camera (for FPA.CAMERA concept)
+                     );
+
+/// Add a source to the focal plane hierarchy, specified by a camera format
+///
+/// This is suitable for generating an output FPA given the desired format.
+bool pmFPAAddSourceFromFormat(pmFPA *fpa, ///< The FPA
+                              const char *fpaObs, ///< FPA.NAME for the source
+                              const psMetadata *format ///< Format of file
+    );
+
+/// Add an (input or output) source to the focal plane hierarchy, specified by a view
+///
+/// Given an FPA, add an HDU by specifying where it goes (i.e., by an FPAview).  The camera format
+/// configuration is required in order to describe how the FPA is laid out in terms of disk files.
+bool pmFPAAddSourceFromView(pmFPA *fpa,   ///< The FPA
+                            const char *fpaObs, ///< FPA.NAME for the source
+                            const pmFPAview *phuView, ///< The view, corresponding to the PHU
+                            const psMetadata *format ///< Format of file
+                           );
+
+/// Add an (input or output) source to the focal plane hierarchy, specified by a (primary) header
+///
+/// Given an FPA, add an HDU by specifying a primary header, which is used to determine the FITS file
+/// contents, and therefore the proper location for the HDU.  The camera format configuration is required in
+/// order to describe how the FPA is laid out in terms of disk files.
+pmFPAview *pmFPAAddSourceFromHeader(pmFPA *fpa, ///< The FPA
+                                    psMetadata *phu, ///< Primary header of file
+                                    const psMetadata *format ///< Format of file
+                                   );
+
+/// Identify a source in the focal plane hierarchy, specified by a (primary) header
+///
+/// This is the same as pmFPAAddSourceFromHeader, except the input is not added into the FPA hierarchy.
+/// This function serves only to identify where in the hierarchy it should go, not prepare for reading, etc.
+pmFPAview *pmFPAIdentifySourceFromHeader(pmFPA *fpa, psMetadata *phu, const psMetadata *format);
+
+/// Print a representation of the FPA, including its headers and concepts.
+///
+/// This function is intended for testing and development purposes.
+void pmFPAPrint(FILE *fd,               ///< File descriptor to which to print
+                const pmFPA *fpa,       ///< FPA to print
+                bool header,            ///< Print headers?
+                bool concepts           ///< Print concepts?
+               );
+
+/// Return the PHU level for an FPA, given the format
+pmFPALevel pmFPAPHULevel(const psMetadata *format);
+
+/// Return the Extensions level for an FPA, given the format
+pmFPALevel pmFPAExtensionsLevel(const psMetadata *format);
+
+/// @}
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPACopy.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPACopy.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPACopy.c	(revision 22158)
@@ -0,0 +1,618 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <strings.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPAUtils.h"
+#include "pmHDUUtils.h"
+#include "pmFPACopy.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// File-static functions and macros
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Copy the value for a concept
+#define COPY_CONCEPT(TARGET, SOURCE, NAME, TYPE) { \
+    psMetadataItem *targetItem = psMetadataLookup(TARGET, NAME); \
+    psMetadataItem *sourceItem = psMetadataLookup(SOURCE, NAME); \
+    targetItem->data.TYPE = sourceItem->data.TYPE; }
+
+// Find the blank (image-less) PHU, given a cell.
+static pmHDU *findBlankPHU(const pmCell *cell // The cell for which to find the PHU
+                          )
+{
+    assert(cell);
+
+    if (cell->hdu && cell->hdu->blankPHU) {
+        return cell->hdu;
+    }
+    pmChip *chip = cell->parent;        // The parent chip
+    if (chip->hdu && chip->hdu->blankPHU) {
+        return chip->hdu;
+    }
+    pmFPA *fpa = chip->parent;  // The parent FPA
+    if (fpa->hdu && fpa->hdu->blankPHU) {
+        return fpa->hdu;
+    }
+
+    return NULL;
+}
+
+// copy one of the psImage components of the readout
+static void readoutCopyComponent(psImage **target, // Image to which to copy
+                                 const psImage *source, // Image from which to copy
+                                 psImageBinning *binning, // New binning
+                                 bool xFlip, bool yFlip, // Flip in x or y?
+                                 bool pixels // Copy the pixels?
+                                 )
+{
+    if (!source) return;
+
+    if (*target) {
+        psFree(*target);
+    }
+    if (pixels) {
+        *target = psImageFlip(NULL, source, xFlip, yFlip);
+        return;
+    }
+
+    // I have the fine image size, I know the binning factor, determine the ruff image size
+    binning->nXfine = source->numCols;
+    binning->nYfine = source->numRows;
+    psImageBinningSetRuffSize(binning, PS_IMAGE_BINNING_CENTER);
+    *target = psImageAlloc(binning->nXruff, binning->nYruff, source->type.type);
+    return;
+}
+
+// Update the output analysis metadata, adding stuff in the input
+//
+// This is probably very similar to psMetadataCopy, but we want to explicitly deal with arrays (especially
+// since astronomical sources live in them)
+static psMetadata *updateAnalysis(psMetadata *out, psMetadata *in)
+{
+    psAssert(in, "Require input");
+    if (!out) {
+        out = psMetadataAlloc();
+    }
+
+    psMetadataIterator *iter = psMetadataIteratorAlloc(in, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *item;               // Item from iteration
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        psMetadataItem *original = psMetadataLookup(in, item->name); // Checking for MULTI
+        psMetadataItem *extant = psMetadataLookup(out, item->name); // Existing item?
+        if ((original && original->type == PS_DATA_METADATA_MULTI) ||
+            (extant && extant->type == PS_DATA_METADATA_MULTI)) {
+            psMetadataAddItem(out, item, PS_LIST_TAIL, PS_META_DUPLICATE_OK);
+            continue;
+        }
+
+        switch (item->type) {
+          case PS_DATA_ARRAY: {
+              // Concatenate arrays if they already exist
+              psMetadataItem *extant = psMetadataLookup(out, item->name); // Existing array?
+              if (extant && extant->type == PS_DATA_ARRAY) {
+                  psArray *new = item->data.V; // New array
+                  psArray *old = extant->data.V; // Old array
+                  long numNew = new->n, numOld = old->n; // Number of values in each
+                  extant->data.V = old = psArrayRealloc(old, old->n + numNew);
+                  for (long i = 0; i < numNew; i++) {
+                      old->data[numOld + i] = psMemIncrRefCounter(new->data[i]);
+                  }
+                  old->n = numOld + numNew;
+              } else {
+                  psMetadataAddItem(out, item, PS_LIST_TAIL, PS_META_REPLACE);
+              }
+              break;
+            default:
+              // If in doubt, there's not much we can do except replace
+              psMetadataAddItem(out, item, PS_LIST_TAIL, PS_META_REPLACE);
+              break;
+          }
+        }
+    }
+    psFree(iter);
+
+    return out;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// File-static engine functions --- these do all the work.  Actually, cellCopy does all the work; the others
+// merely iterate on the higher-level components.
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Common engine for pmCellCopy and pmCellCopyStructure
+// Does the actual splitting/splicing that's required to copy an FPA to a different representation.
+static bool cellCopy(pmCell *target,     // The target cell
+                     const pmCell *source, // The source cell, to be copied
+                     bool pixels,        // Copy the pixels?
+                     int xBin, int yBin  // (Relative) binning factors in x and y
+                    )
+{
+    assert(target);
+    assert(source);
+    assert(xBin > 0 && yBin > 0);
+
+    if (!source->data_exists) {
+        // Copied everything that exists
+        return true;
+    }
+
+    // XXX this is a programming / config error
+    if (pixels && (xBin != 1 || yBin != 1)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to copy pixels if binning is set\n");
+        return false;
+    }
+
+    // the binning structure carries the information on how to rebin the images if needed
+    psImageBinning *binning = psImageBinningAlloc();
+    binning->nXbin = xBin;
+    binning->nYbin = yBin;
+
+    psArray *sourceReadouts = source->readouts; // The source readouts
+    int numReadouts = sourceReadouts->n; // Number of readouts copied
+
+    // Need to check/change CELL.XPARITY and CELL.YPARITY
+    bool mdokS = true;                   // Status of MD lookup
+    bool mdokT = true;                   // Status of MD lookup
+    bool xFlip = false;                 // Switch parity in x?
+    bool yFlip = false;                 // Switch parity in y?
+
+    // enforce the following conditions:
+    // CELL.XPARITY is required for source
+    // CELL.XPARITY must be +/- 1
+    int xParitySource = psMetadataLookupS32(&mdokS, source->concepts, "CELL.XPARITY"); // Source parity
+    int xParityTarget = psMetadataLookupS32(&mdokT, target->concepts, "CELL.XPARITY"); // Target x parity
+    assert(mdokS && mdokT);
+    if (abs(xParitySource) != 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "CELL.XPARITY is not set for source (%d)",
+                xParitySource);
+        psFree(binning);
+        return false;
+    } else {
+        // Use the source parity
+        COPY_CONCEPT(target->concepts, source->concepts, "CELL.XPARITY", S32);
+        xParityTarget = xParitySource;
+    }
+    if (xParityTarget != xParitySource) {
+        xFlip = true;
+    }
+
+    int yParityTarget = psMetadataLookupS32(&mdokT, target->concepts, "CELL.YPARITY"); // Target y parity
+    int yParitySource = psMetadataLookupS32(&mdokS, source->concepts, "CELL.YPARITY"); // Source parity
+    assert(mdokS && mdokT);
+    if (abs(yParitySource) != 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "CELL.YPARITY is not set for source (%d)",
+                yParitySource);
+        psFree(binning);
+        return false;
+    } else {
+        // Use the source parity
+        COPY_CONCEPT(target->concepts, source->concepts, "CELL.YPARITY", S32);
+        yParityTarget = yParitySource;
+    }
+    if (yParityTarget != yParitySource) {
+        yFlip = true;
+    }
+    psTrace("psModules.camera", 3, "xFlip: %d; yFlip: %d\n", xFlip, yFlip);
+
+    // Perform deep copy of the images.  I would prefer *not* to do a deep copy, in the interests of speed (we
+    // still need to do another deep copy into the HDU for when we write out), but this is the only way I can
+    // think of to provide security against copying a cell and then unknowingly changing the source when
+    // manipulating the target.
+    for (int i = 0; i < numReadouts; i++) {
+        pmReadout *sourceReadout = sourceReadouts->data[i]; // The source readout
+        pmReadout *targetReadout = pmReadoutAlloc(target); // The target readout; this adds it to the cell
+
+        // Copy attributes
+        // XXX is this correct under binning?
+        targetReadout->col0 = sourceReadout->col0;
+        targetReadout->row0 = sourceReadout->row0;
+        targetReadout->process = sourceReadout->process;
+        targetReadout->file_exists = sourceReadout->file_exists;
+        targetReadout->data_exists = sourceReadout->data_exists;
+
+        // Copy all three image components (image, mask, weight)
+        readoutCopyComponent(&targetReadout->image,  sourceReadout->image,  binning, xFlip, yFlip, pixels);
+        readoutCopyComponent(&targetReadout->mask,   sourceReadout->mask,   binning, xFlip, yFlip, pixels);
+        readoutCopyComponent(&targetReadout->weight, sourceReadout->weight, binning, xFlip, yFlip, pixels);
+
+        // Copy bias
+        while (targetReadout->bias->n > 0) {
+            psListRemove(targetReadout->bias, PS_LIST_HEAD);
+        }
+
+        // Iterate over the biases
+        psListIterator *biasIter = psListIteratorAlloc(sourceReadout->bias, PS_LIST_HEAD, false);
+        psImage *bias = NULL;           // Bias image from iteration
+        while ((bias = psListGetAndIncrement(biasIter))) {
+            psImage *biasCopy = NULL;          // Copy of the bias
+            readoutCopyComponent (&biasCopy, bias, binning, xFlip, yFlip, pixels);
+            psListAdd(targetReadout->bias, PS_LIST_TAIL, biasCopy);
+            psFree(biasCopy);           // Drop reference
+        }
+        psFree(biasIter);
+
+        // Copy the analysis metadata
+        targetReadout->analysis = updateAnalysis(targetReadout->analysis, sourceReadout->analysis);
+
+        targetReadout->data_exists = true;
+        psFree(targetReadout);          // Drop reference
+    }
+
+    // Copy the remaining "concepts" over.  Don't copy the TRIMSEC or BIASSEC, since these will be created by
+    // pmHDUGenerate if they don't already exist in the target.  Don't copy the XPARITY or YPARITY, since
+    // we've used those to do the flips.  Don't copy the X0 and Y0 because they are updated below (and are
+    // dependent upon the flips we've done above).
+    psMetadataIterator *conceptsIter = psMetadataIteratorAlloc(source->concepts, PS_LIST_HEAD, NULL);
+    psMetadataItem *conceptItem = NULL; // Item from iteration
+    while ((conceptItem = psMetadataGetAndIncrement(conceptsIter))) {
+        psString name = conceptItem->name; // Name of concept
+        if (!strcmp(name, "CELL.TRIMSEC")) continue;
+        if (!strcmp(name, "CELL.BIASSEC")) continue;
+        if (!strcmp(name, "CELL.XPARITY")) continue;
+        if (!strcmp(name, "CELL.YPARITY")) continue;
+        if (!strcmp(name, "CELL.X0")) continue;
+        if (!strcmp(name, "CELL.Y0")) continue;
+
+        psMetadataItem *copy = psMetadataItemCopy(conceptItem); // Copy of the concept
+        psMetadataAddItem(target->concepts, copy, PS_LIST_TAIL, PS_META_REPLACE);
+        psFree(copy);               // Drop reference
+    }
+    psFree(conceptsIter);
+
+    // Need to update CELL.TRIMSEC and CELL.BIASSEC if we changed the binning and they exist already.
+    // XXX this code seems to be very similar to pmConceptsUpdate
+    if ((binning->nXbin != 1) || (binning->nYbin != 1)) {
+        bool mdok = false;
+        psRegion *trimsec = psMetadataLookupPtr(&mdok, target->concepts, "CELL.TRIMSEC"); // The trim section
+        if (mdok && trimsec && !psRegionIsNaN(*trimsec)) {
+            *trimsec = psImageBinningSetRuffRegion(binning, *trimsec);
+            // force integer pixels : truncate x0, roundup x1:
+            trimsec->x0 = (int)trimsec->x0;
+            if (trimsec->x1 > (int)trimsec->x1) {
+                trimsec->x1 = (int)trimsec->x1 + 1;
+            } else {
+                trimsec->x1 = (int)trimsec->x1;
+            }
+            trimsec->y0 = (int)trimsec->y0;
+            if (trimsec->y1 > (int)trimsec->y1) {
+                trimsec->y1 = (int)trimsec->y1 + 1;
+            } else {
+                trimsec->y1 = (int)trimsec->y1;
+            }
+        }
+        psList *biassecs = psMetadataLookupPtr(&mdok, target->concepts, "CELL.BIASSEC"); // The bias sections
+        if (mdok && biassecs && biassecs->n > 0) {
+            psListIterator *biassecsIter = psListIteratorAlloc(biassecs, PS_LIST_HEAD, true); // Iterator
+            psRegion *biassec = NULL;   // Bias section, from iteration
+            while ((biassec = psListGetAndIncrement(biassecsIter))) {
+                if (!psRegionIsNaN(*biassec)) {
+                    *biassec = psImageBinningSetRuffRegion(binning, *biassec);
+                    // force integer pixels : truncate x0, roundup x1:
+                    biassec->x0 = (int)biassec->x0;
+                    if (biassec->x1 > (int)biassec->x1) {
+                        biassec->x1 = (int)biassec->x1 + 1;
+                    } else {
+                        biassec->x1 = (int)biassec->x1;
+                    }
+                    biassec->y0 = (int)biassec->y0;
+                    if (biassec->y1 > (int)biassec->y1) {
+                        biassec->y1 = (int)biassec->y1 + 1;
+                    } else {
+                        biassec->y1 = (int)biassec->y1;
+                    }
+                }
+            }
+            psFree(biassecsIter);
+        }
+    }
+
+    // Need to update CELL.X0 and CELL.Y0 if we flipped
+    // XXX this section should probably use a common function consistent with psImageBinning
+    if (xFlip) {
+        int xZero = psMetadataLookupS32(NULL, source->concepts, "CELL.X0"); // CELL.X0 from source
+        int xParity = psMetadataLookupS32(NULL, source->concepts, "CELL.XPARITY"); // Parity in x
+        int sourceBin = psMetadataLookupS32(NULL, source->concepts, "CELL.XBIN"); // CELL.XBIN from source
+        int xSize = psMetadataLookupS32(NULL, source->concepts, "CELL.XSIZE"); // CELL.XSIZE of source
+
+        if (sourceBin == 0) {
+            // Don't know the binning; assume it is unity
+            sourceBin = binning->nXbin;
+        }
+
+        // XXX make sure this is consistent with the psImageBinning
+        psTrace("psModules.camera", 3, "CELL.X0: Before: %d After: %d\n", xZero, xZero + (xSize - 1) * xParity * sourceBin);
+        psTrace("psModules.camera", 9, "(xParity: %d xBin: %d numCols: %d)\n", xParity, sourceBin, xSize);
+
+        if (xParity == 0 || xSize == 0) {
+            psWarning("New CELL.X0 may be incorrect due to missing concepts (CELL.XPARITY, CELL.XSIZE)");
+        }
+
+        xZero += (xSize - 1) * xParity * sourceBin; // Change the parity on the X0 position
+        psMetadataItem *newItem = psMetadataLookup(target->concepts, "CELL.X0"); // CELL.X0 from target
+        newItem->data.S32 = xZero;
+    }
+    if (yFlip) {
+        int yZero = psMetadataLookupS32(NULL, source->concepts, "CELL.Y0"); // CELL.Y0 from source
+        int yParity = psMetadataLookupS32(NULL, source->concepts, "CELL.YPARITY"); // Parity in y
+        int sourceBin = psMetadataLookupS32(NULL, source->concepts, "CELL.YBIN"); // Binning in y
+        int ySize = psMetadataLookupS32(NULL, source->concepts, "CELL.YSIZE"); // CELL.YSIZE of source
+
+        if (sourceBin == 0) {
+            // Don't know the binning; assume it is unity
+            sourceBin = binning->nYbin;
+        }
+
+        psTrace("psModules.camera", 3, "CELL.Y0: Before: %d After: %d\n", yZero, yZero + (ySize - 1) * yParity * sourceBin);
+        psTrace("psModules.camera", 9, "(yParity: %d yBin: %d numRows: %d)\n", yParity, sourceBin, ySize);
+
+        if (yParity == 0 || ySize == 0) {
+            psWarning("New CELL.Y0 may be incorrect due to missing concepts "
+                      "(CELL.Y0, CELL.YPARITY, CELL.YBIN, CELL.YSIZE)");
+        }
+
+        yZero += (ySize - 1) * yParity * sourceBin; // Change the parity on the Y0 position
+        psMetadataItem *newItem = psMetadataLookup(target->concepts, "CELL.Y0"); // CELL.Y0 from target
+        newItem->data.S32 = yZero;
+    }
+
+    // Update the binning concepts
+    // XXX this should probably be done with a common function using psImageBinning
+    psMetadataItem *binItem = psMetadataLookup(target->concepts, "CELL.XBIN");
+    binItem->data.S32 *= xBin;
+    binItem = psMetadataLookup(target->concepts, "CELL.YBIN");
+    binItem->data.S32 *= yBin;
+
+    // Update the analysis metadata
+    target->analysis = updateAnalysis(target->analysis, source->analysis);
+
+    // Copy any headers
+    pmHDU *targetHDU = pmHDUFromCell(target); // The target HDU
+    if (targetHDU) {
+        pmHDU *sourceHDU = pmHDUFromCell(source); // The source HDU
+        if (!sourceHDU) {
+            psWarning("Unable to copy header: no source header.");
+        } else if (sourceHDU->header) {
+            targetHDU->header = psMetadataCopy(targetHDU->header, sourceHDU->header);
+        }
+    }
+
+    // Copy the PHU over as well, if required
+    pmHDU *targetPHU = findBlankPHU(target); // The target PHU
+    if (targetPHU && targetPHU != targetHDU) {
+        // pmHDU *sourcePHU = pmHDUGetHighest(source->parent->parent, source->parent, source); // A source HDU
+        pmHDU *sourcePHU = findBlankPHU(source); // The target PHU
+        if (sourcePHU && sourcePHU->header) {
+            targetPHU->header = psMetadataCopy(targetPHU->header, sourcePHU->header);
+        }
+    }
+
+    psFree (binning);
+    target->data_exists = true;
+    target->parent->data_exists = true;
+    return true;
+}
+
+// Common engine for pmChipCopy and pmChipCopyStructure
+// Iterate on the components
+static bool chipCopy(pmChip *target,          // The target chip
+                     const pmChip *source, // The source chip, to be copied
+                     bool pixels,             // Copy the pixels?
+                     int xBin, int yBin       // (Relative) binning factors in x and y
+                    )
+{
+    assert(target);
+    assert(source);
+    assert(xBin > 0);
+    assert(yBin > 0);
+
+    if (!source->data_exists) {
+        // Copied everything that exists
+        return true;
+    }
+
+    psArray *targetCells = target->cells; // The target cells
+    psArray *sourceCells = source->cells; // The source cells
+    if (targetCells->n != sourceCells->n) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Number of source cells (%ld) differs from the number of target cells (%ld)\n",
+                sourceCells->n, targetCells->n);
+        return false;
+    }
+
+    bool status = true;                 // Status of copy
+    for (int i = 0; i < targetCells->n; i++) {
+        pmCell *targetCell = targetCells->data[i]; // The target cell
+        const char *cellName = psMetadataLookupStr(NULL, targetCell->concepts, "CELL.NAME"); // Name of cell
+        int cellNum = pmChipFindCell(source, cellName); // Number of cell with that name
+        if (cellNum >= 0) {
+            pmCell *sourceCell = sourceCells->data[cellNum]; // The source cell
+            status &= cellCopy(targetCell, sourceCell, pixels, xBin, yBin);
+        }
+    }
+
+    // Update the analysis metadata
+    target->analysis = updateAnalysis(target->analysis, source->analysis);
+
+    // Update the concepts
+    psMetadataItem *chipName = psMemIncrRefCounter(psMetadataLookup(target->concepts, "CHIP.NAME"));
+    psMetadataCopy(target->concepts, source->concepts);
+    psMetadataAddItem(target->concepts, chipName, PS_LIST_TAIL, PS_META_REPLACE);
+    psFree(chipName);
+    psMetadataCopy(target->parent->concepts, source->parent->concepts);
+
+    target->data_exists = true;
+    return status;
+}
+
+// create a new pmChip with the data derived from the supplied chip
+pmChip *pmChipDuplicate(pmFPA *fpa, const pmChip *sourceChip)
+{
+    assert(sourceChip);
+
+    bool status;
+    char *chipName = psMetadataLookupStr(&status, sourceChip->concepts, "CHIP.NAME");
+    pmChip *targetChip = pmChipAlloc (NULL, chipName);
+    targetChip->parent = fpa;
+
+    psArray *sourceCells = sourceChip->cells; // The source cells
+
+    for (int i = 0; i < sourceCells->n; i++) {
+        pmCell *sourceCell = sourceCells->data[i]; // The sources cell
+        const char *cellName = psMetadataLookupStr(NULL, sourceCell->concepts, "CELL.NAME"); // Name of cell
+        // XXX are there other concepts I need to copy first?
+        pmCell *targetCell = pmCellAlloc (targetChip, cellName);
+        int xParityTarget = psMetadataLookupS32(&status, sourceCell->concepts, "CELL.XPARITY"); // Target x parity
+        psMetadataAddS32 (targetCell->concepts, PS_LIST_TAIL, "CELL.XPARITY", PS_META_REPLACE, "", xParityTarget);
+        int yParityTarget = psMetadataLookupS32(&status, sourceCell->concepts, "CELL.YPARITY"); // Target y parity
+        psMetadataAddS32 (targetCell->concepts, PS_LIST_TAIL, "CELL.YPARITY", PS_META_REPLACE, "", yParityTarget);
+        if (!cellCopy(targetCell, sourceCell, true, 1, 1)) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false, "failed to duplicate chip\n");
+            return NULL;
+        }
+        // update the attributes
+        targetCell->file_exists = sourceCell->file_exists;
+        targetCell->data_exists = sourceCell->data_exists;
+        targetCell->process     = sourceCell->process;
+    }
+
+    // Update the analysis metadata
+    targetChip->analysis = updateAnalysis(targetChip->analysis, sourceChip->analysis);
+
+    // Update the concepts
+    psMetadataCopy(targetChip->concepts, sourceChip->concepts);
+
+    // update the attributes
+    targetChip->file_exists = sourceChip->file_exists;
+    targetChip->data_exists = sourceChip->data_exists;
+    targetChip->process     = sourceChip->process;
+
+    return targetChip;
+}
+
+// Common engine for pmFPACopy and pmFPACopyStructure.
+// Iterate on the components
+static bool fpaCopy(pmFPA *target,      // The target FPA
+                    const pmFPA *source, // The source FPA, to be copied
+                    bool pixels,        // Copy the pixels?
+                    int xBin, int yBin  // (Relative) binning factors in x and y
+                   )
+{
+    assert(target);
+    assert(source);
+    assert(xBin > 0);
+    assert(yBin > 0);
+
+    psArray *targetChips = target->chips; // The target chips
+    psArray *sourceChips = source->chips; // The source chips
+    if (targetChips->n != sourceChips->n) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Number of source chips (%ld) differs from the number of target chips (%ld)\n",
+                sourceChips->n, targetChips->n);
+        return false;
+    }
+
+    bool status = true;                 // Status of copy
+    for (int i = 0; i < targetChips->n; i++) {
+        pmChip *targetChip = targetChips->data[i]; // The target chip
+        const char *chipName = psMetadataLookupStr(NULL, targetChip->concepts, "CHIP.NAME"); // Name of chip
+        int chipNum = pmFPAFindChip(source, chipName); // Number of chip with that name
+        if (chipNum >= 0) {
+            pmChip *sourceChip = sourceChips->data[chipNum]; // The source chip
+            status &= chipCopy(targetChip, sourceChip, pixels, xBin, yBin);
+        }
+    }
+
+    // Update the analysis metadata
+    target->analysis = updateAnalysis(target->analysis, source->analysis);
+
+    // Update the concepts
+    psMetadataCopy(target->concepts, source->concepts);
+
+    return status;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool pmFPACopy(pmFPA *target, const pmFPA *source)
+{
+    PS_ASSERT_PTR_NON_NULL(target, false);
+    PS_ASSERT_PTR_NON_NULL(source, false);
+    if (target == source) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Can't copy FPA onto itself.");
+        return false;
+    }
+    return fpaCopy(target, source, true, 1, 1);
+}
+
+bool pmChipCopy(pmChip *target, const pmChip *source)
+{
+    PS_ASSERT_PTR_NON_NULL(target, false);
+    PS_ASSERT_PTR_NON_NULL(source, false);
+    if (target == source) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Can't copy chip onto itself.");
+        return false;
+    }
+    return chipCopy(target, source, true, 1, 1);
+}
+
+bool pmCellCopy(pmCell *target, const pmCell *source)
+{
+    PS_ASSERT_PTR_NON_NULL(target, false);
+    PS_ASSERT_PTR_NON_NULL(source, false);
+    if (target == source) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Can't copy cell onto itself.");
+        return false;
+    }
+    return cellCopy(target, source, true, 1, 1);
+}
+
+
+bool pmFPACopyStructure(pmFPA *target, const pmFPA *source, int xBin, int yBin)
+{
+    PS_ASSERT_PTR_NON_NULL(target, false);
+    PS_ASSERT_PTR_NON_NULL(source, false);
+    PS_ASSERT_INT_POSITIVE(xBin, false);
+    PS_ASSERT_INT_POSITIVE(yBin, false);
+    if (target == source) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Can't copy FPA onto itself.");
+        return false;
+    }
+    return fpaCopy(target, source, false, xBin, yBin);
+}
+
+bool pmChipCopyStructure(pmChip *target, const pmChip *source, int xBin, int yBin)
+{
+    PS_ASSERT_PTR_NON_NULL(target, false);
+    PS_ASSERT_PTR_NON_NULL(source, false);
+    PS_ASSERT_INT_POSITIVE(xBin, false);
+    PS_ASSERT_INT_POSITIVE(yBin, false);
+    if (target == source) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Can't copy chip onto itself.");
+        return false;
+    }
+    return chipCopy(target, source, false, xBin, yBin);
+}
+
+bool pmCellCopyStructure(pmCell *target, const pmCell *source, int xBin, int yBin)
+{
+    PS_ASSERT_PTR_NON_NULL(target, false);
+    PS_ASSERT_PTR_NON_NULL(source, false);
+    PS_ASSERT_INT_POSITIVE(xBin, false);
+    PS_ASSERT_INT_POSITIVE(yBin, false);
+    if (target == source) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Can't copy cell onto itself.");
+        return false;
+    }
+    return cellCopy(target, source, false, xBin, yBin);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPACopy.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPACopy.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPACopy.h	(revision 22158)
@@ -0,0 +1,78 @@
+/* @file pmFPACopy.h
+ * @brief Functions to copy FPA components.
+ *
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-04-12 02:51:44 $
+ * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FPA_COPY_H
+#define PM_FPA_COPY_H
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+/// Copy an FPA and components, including the pixels, to a different representation of the same camera
+///
+/// This function is useful for converting between different representations of the same camera.  For example,
+/// between Megacam "RAW" (one amp per extension) and Megacam "SPLICED" formats (two amps = 1 chip per
+/// extension, spliced together).  Components are spliced together as necessary.
+bool pmFPACopy(pmFPA *target,           ///< The target FPA
+               const pmFPA *source      ///< The source FPA, to be copied
+              );
+
+/// Copy a chip and components, including the pixels, to a different representation of the same camera
+///
+/// This function is useful for converting between different representations of the same camera.  For example,
+/// between Megacam "RAW" (one amp per extension) and Megacam "SPLICED" formats (two amps = 1 chip per
+/// extension, spliced together).  Components are spliced together as necessary.
+bool pmChipCopy(pmChip *target,         ///< The target chip
+                const pmChip *source    ///< The source chip, to be copied
+               );
+
+/// Copy a cell and components, including the pixels, to a different representation of the same camera
+///
+/// This function is useful for converting between different representations of the same camera.  For example,
+/// between Megacam "RAW" (one amp per extension) and Megacam "SPLICED" formats (two amps = 1 chip per
+/// extension, spliced together).  Components are spliced together as necessary.
+bool pmCellCopy(pmCell *target,         ///< The target cell
+                const pmCell *source    ///< The source cell, to be copied
+               );
+
+
+/// Copy an FPA, but not the pixels, to a different representation of the same camera
+///
+/// This function the same as pmFPACopy, except that the pixels are not copied (though images of sufficient
+/// size are allocated in the target).  Changes the CELL.XBIN and CELL.YBIN according to the provided binning
+/// factors.
+bool pmFPACopyStructure(pmFPA *target,   ///< The target FPA
+                        const pmFPA *source, ///< The source FPA, to be copied
+                        int xBin, int yBin ///< Binning factors in x and y
+                       );
+
+/// Copy a chip, but not the pixels, to a different representation of the same camera
+///
+/// This function the same as pmChipCopy, except that the pixels are not copied (though images of sufficient
+/// size are allocated in the target).  Changes the CELL.XBIN and CELL.YBIN according to the provided binning
+/// factors.
+bool pmChipCopyStructure(pmChip *target, ///< The target chip
+                         const pmChip *source, ///< The source chip, to be copied
+                         int xBin, int yBin ///< Binning factors in x and y
+                        );
+
+/// Copy a cell, but not the pixels, to a different representation of the same camera
+///
+/// This function the same as pmCellCopy, except that the pixels are not copied (though images of sufficient
+/// size are allocated in the target).  Changes the CELL.XBIN and CELL.YBIN according to the provided binning
+/// factors.
+bool pmCellCopyStructure(pmCell *target, ///< The target cell
+                         const pmCell *source, ///< The source cell, to be copied
+                         int xBin, int yBin ///< Binning factors in x and y
+                        );
+
+pmChip *pmChipDuplicate(pmFPA *fpa, const pmChip *source);
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAExtent.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAExtent.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAExtent.c	(revision 22158)
@@ -0,0 +1,155 @@
+#include <stdio.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmHDUUtils.h"
+
+// return cell pixels bounding the readout
+psRegion *pmReadoutExtent(const pmReadout *readout)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, NULL);
+
+    psImage *image = readout->image;    // Image from which to get dimensions
+    if (!image) {
+        image = readout->mask;
+    }
+    if (!image) {
+        image = readout->weight;
+    }
+
+    int xSize = 0;
+    int ySize = 0;
+
+    if (!image) {
+	pmHDU *hdu = pmHDUFromReadout (readout);
+	if (hdu && hdu->header) {
+	    xSize = psMetadataLookupS32(NULL, hdu->header, "NAXIS1");
+	    ySize = psMetadataLookupS32(NULL, hdu->header, "NAXIS2");
+	} else {
+        // Don't have anything to base the true extent on, so have to give the hardwired value (largest possible extent)
+	    xSize = psMetadataLookupS32(NULL, readout->parent->concepts, "CELL.XSIZE");
+	    ySize = psMetadataLookupS32(NULL, readout->parent->concepts, "CELL.YSIZE");
+	}
+        return psRegionAlloc(0, xSize, 0, ySize);
+    }
+
+    // Get the offset to the CCD window
+    int xWindow = psMetadataLookupS32(NULL, readout->parent->concepts, "CELL.XWINDOW");
+    int yWindow = psMetadataLookupS32(NULL, readout->parent->concepts, "CELL.YWINDOW");
+    return psRegionAlloc(xWindow, xWindow + image->numCols,
+                         yWindow, yWindow + image->numRows);
+}
+
+// return chip pixels bounding the cell (all readouts)
+psRegion *pmCellExtent(const pmCell *cell)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, NULL);
+
+    psArray *readouts = cell->readouts; // Array of component readouts
+    psRegion *cellExtent = psRegionAlloc(INFINITY, 0, INFINITY, 0); // Extent of cell
+    for (long i = 0; i < readouts->n; i++) {
+        pmReadout *readout = readouts->data[i]; // Readout of interest
+        psRegion *roExtent = pmReadoutExtent(readout); // Extent of readout
+        cellExtent->x0 = PS_MIN(cellExtent->x0, roExtent->x0);
+        cellExtent->x1 = PS_MAX(cellExtent->x1, roExtent->x1);
+        cellExtent->y0 = PS_MIN(cellExtent->y0, roExtent->y0);
+        cellExtent->y1 = PS_MAX(cellExtent->y1, roExtent->y1);
+        psFree(roExtent);
+    }
+
+    bool mdok;                          // Status of MD lookup
+    int x0 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.X0"); // Cell x offset
+    if (!mdok) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find CELL.X0.\n");
+        psFree(cellExtent);
+        return NULL;
+    }
+    int y0 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.Y0"); // Cell y offset
+    if (!mdok) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find CELL.Y0.\n");
+        psFree(cellExtent);
+        return NULL;
+    }
+
+    cellExtent->x0 += x0;
+    cellExtent->x1 += x0;
+    cellExtent->y0 += y0;
+    cellExtent->y1 += y0;
+
+    return cellExtent;
+}
+
+// return chip pixels included in all cells
+psRegion *pmChipPixels(const pmChip *chip)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, NULL);
+
+    psArray *cells = chip->cells;       // Array of component cells
+    psRegion *chipExtent = psRegionAlloc(INFINITY, 0, INFINITY, 0); // Extent of chip
+    for (long i = 0; i < cells->n; i++) {
+        pmCell *cell = cells->data[i];  // Cell of interest
+        psRegion *cellExtent = pmCellExtent(cell); // Extent of cell
+        chipExtent->x0 = PS_MIN(chipExtent->x0, cellExtent->x0);
+        chipExtent->x1 = PS_MAX(chipExtent->x1, cellExtent->x1);
+        chipExtent->y0 = PS_MIN(chipExtent->y0, cellExtent->y0);
+        chipExtent->y1 = PS_MAX(chipExtent->y1, cellExtent->y1);
+        psFree(cellExtent);
+    }
+
+    return chipExtent;
+}
+
+// return pixels in basic FPA grid bounded by chip
+// this FPA grid has 0,0 at the 0,0 corner of one chip, and is NOT the same
+// as the astrometry focal plane coordinate system
+psRegion *pmChipExtent(const pmChip *chip)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, NULL);
+
+    psRegion *chipExtent = pmChipPixels(chip);
+    if (!chipExtent) return NULL;
+
+    bool mdok;                          // Status of MD lookup
+    int x0 = psMetadataLookupS32(&mdok, chip->concepts, "CHIP.X0"); // Chip x offset
+    if (!mdok) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find CHIP.X0.\n");
+        psFree(chipExtent);
+        return NULL;
+    }
+    int y0 = psMetadataLookupS32(&mdok, chip->concepts, "CHIP.Y0"); // Chip y offset
+    if (!mdok) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find CHIP.Y0.\n");
+        psFree(chipExtent);
+        return NULL;
+    }
+
+    chipExtent->x0 += x0;
+    chipExtent->x1 += x0;
+    chipExtent->y0 += y0;
+    chipExtent->y1 += y0;
+
+    return chipExtent;
+}
+
+// return FPA pixels included in all chips
+// this FPA grid has 0,0 at the 0,0 corner of one chip, and is NOT the same
+// as the astrometry focal plane coordinate system
+psRegion *pmFPAPixels(const pmFPA *fpa)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
+
+    psArray *chips = fpa->chips;       // Array of component chips
+    psRegion *fpaExtent = psRegionAlloc(INFINITY, 0, INFINITY, 0); // Extent of fpa
+    for (long i = 0; i < chips->n; i++) {
+        pmChip *chip = chips->data[i];  // Chip of interest
+        psRegion *chipExtent = pmChipExtent(chip); // Extent of chip
+        fpaExtent->x0 = PS_MIN(fpaExtent->x0, chipExtent->x0);
+        fpaExtent->x1 = PS_MAX(fpaExtent->x1, chipExtent->x1);
+        fpaExtent->y0 = PS_MIN(fpaExtent->y0, chipExtent->y0);
+        fpaExtent->y1 = PS_MAX(fpaExtent->y1, chipExtent->y1);
+        psFree(chipExtent);
+    }
+
+    return fpaExtent;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAExtent.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAExtent.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAExtent.h	(revision 22158)
@@ -0,0 +1,49 @@
+/* @file  pmPFAExtent.h
+ *
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-03-21 22:01:32 $
+ * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FPA_EXTENT_H
+#define PM_FPA_EXTENT_H
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+/// Return the extent of a readout
+///
+/// The extent is determined from an image, if present, or the CELL.TRIMSEC otherwise.
+psRegion *pmReadoutExtent(const pmReadout *readout ///< The readout of interest
+                         );
+
+/// Return the extent of a cell
+///
+/// The extent is determined from the extent of the component readouts, plus CELL.X0,Y0
+psRegion *pmCellExtent(const pmCell *cell ///< The cell of interest
+                      );
+
+// return chip pixels included in all cells
+psRegion *pmChipPixels(const pmChip *chip);
+
+/// Return the extent of a chip
+///
+/// The extent is determined from the extent of the component cells, plus CHIP.X0,Y0
+psRegion *pmChipExtent(const pmChip *chip ///< The chip of interest
+                      );
+
+// return FPA pixels included in all chips
+// this FPA grid has 0,0 at the 0,0 corner of one chip, and is NOT the same
+// as the astrometry focal plane coordinate system
+psRegion *pmFPAPixels(const pmFPA *fpa);
+
+/// Return the extent of an FPA
+///
+/// The extent is determined from the extent of the component chips.
+psRegion *pmFPAExtent(const pmFPA *fpa ///< The FPA of interest
+                     );
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAFlags.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAFlags.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAFlags.c	(revision 22158)
@@ -0,0 +1,341 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAFlags.h"
+
+
+/** functions to turn on/off the file_exists flag **/
+bool pmFPASetFileStatus(pmFPA *fpa, bool status)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        pmChipSetFileStatus (chip, status);
+    }
+    return true;
+}
+
+bool pmChipSetFileStatus(pmChip *chip, bool status)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+
+    chip->file_exists = status;
+    for (int i = 0; i < chip->cells->n; i++) {
+        pmCell *cell = chip->cells->data[i];
+        pmCellSetFileStatus (cell, status);
+    }
+    return true;
+}
+
+bool pmCellSetFileStatus(pmCell *cell, bool status)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+
+    cell->file_exists = status;
+    for (int i = 0; i < cell->readouts->n; i++) {
+        pmReadout *readout = cell->readouts->data[i];
+        readout->file_exists = status;
+    }
+    return true;
+}
+
+bool pmFPACheckFileStatus(const pmFPA *fpa)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        if (!pmChipCheckFileStatus(chip)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool pmChipCheckFileStatus(const pmChip *chip)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    if (!chip->file_exists) {
+        return false;
+    }
+
+    for (int i = 0; i < chip->cells->n; i++) {
+        pmCell *cell = chip->cells->data[i];
+        if (!pmCellCheckFileStatus(cell)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool pmCellCheckFileStatus(const pmCell *cell)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    if (!cell->file_exists) {
+        return false;
+    }
+
+    for (int i = 0; i < cell->readouts->n; i++) {
+        pmReadout *readout = cell->readouts->data[i];
+        if (!readout->file_exists) {
+            return false;
+        }
+    }
+    return true;
+}
+
+/** functions to turn on/off the data_exists flag **/
+bool pmFPASetDataStatus(pmFPA *fpa, bool status)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        pmChipSetDataStatus (chip, status);
+    }
+    return true;
+}
+
+bool pmChipSetDataStatus(pmChip *chip, bool status)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+
+    chip->data_exists = status;
+    for (int i = 0; i < chip->cells->n; i++) {
+        pmCell *cell = chip->cells->data[i];
+        pmCellSetDataStatus (cell, status);
+    }
+    return true;
+}
+
+bool pmCellSetDataStatus (pmCell *cell, bool status)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+
+    cell->data_exists = status;
+    for (int i = 0; i < cell->readouts->n; i++) {
+        pmReadout *readout = cell->readouts->data[i];
+        readout->data_exists = status;
+    }
+    return true;
+}
+
+// pmFPA does not have its own data_exists flag; check its children
+bool pmFPACheckDataStatus (const pmFPA *fpa) {
+
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        if (chip == NULL) continue;
+        if (chip->data_exists) return true;
+    }
+    return false;
+}
+
+bool pmChipCheckDataStatus (const pmChip *chip) {
+
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+
+    return (chip->data_exists);
+}
+
+bool pmCellCheckDataStatus (const pmCell *cell) {
+
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+
+    return (cell->data_exists);
+}
+
+bool pmReadoutCheckDataStatus (const pmReadout *readout) {
+
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+
+    return (readout->data_exists);
+}
+
+bool pmFPAviewCheckDataStatus (const pmFPA *fpa, const pmFPAview *view) {
+
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    if (view->chip == -1) {
+        bool exists = pmFPACheckDataStatus (fpa);
+        return exists;
+    }
+
+    if (view->chip >= fpa->chips->n) {
+        psError(PS_ERR_IO, true, "Requested chip == %d >= fpa->chips->n == %ld", view->chip, fpa->chips->n);
+        return false;
+    }
+    pmChip *chip = fpa->chips->data[view->chip];
+
+    if (view->cell == -1) {
+        bool exists = pmChipCheckDataStatus (chip);
+        return exists;
+    }
+
+    if (view->cell >= chip->cells->n) {
+        psError(PS_ERR_IO, true, "Requested cell == %d >= chip->cells->n == %ld", view->cell, chip->cells->n);
+        return false;
+    }
+    pmCell *cell = chip->cells->data[view->cell];
+
+    if (view->readout == -1) {
+        bool exists = pmCellCheckDataStatus (cell);
+        return exists;
+    }
+
+    if (view->readout >= cell->readouts->n) {
+        psError(PS_ERR_IO, true, "Requested readout == %d >= cell->readouds->n == %ld", view->readout, cell->readouts->n);
+        return false;
+    }
+    pmReadout *readout = cell->readouts->data[view->readout];
+
+    bool exists = pmReadoutCheckDataStatus (readout);
+    return exists;
+}
+
+// Set cells within a chip to be processed or not
+static bool setCellsProcess(const pmChip *chip, // Chip of interest
+                            bool process  // Process this chip?
+                           )
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+
+    psArray *cells = chip->cells;       // Component cells
+    if (! cells) {
+        return false;
+    }
+    for (int i = 0; i < cells->n; i++) {
+        pmCell *tmpCell = cells->data[i]; // Cell of interest
+        if (tmpCell) {
+            tmpCell->process = process;
+        }
+    }
+
+    return true;
+}
+
+
+bool pmFPASelectChip(pmFPA *fpa, int chipNum, bool exclusive)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+
+    psArray *chips = fpa->chips;        // Component chips
+    if ((chips == NULL) || (chipNum >= chips->n)) {
+        return(false);
+    }
+
+    for (int i = 0 ; i < chips->n ; i++) {
+        pmChip *tmpChip = (pmChip *) chips->data[i];
+        if (tmpChip == NULL) {
+            continue;
+        }
+        if (i == chipNum) {
+            tmpChip->process = true;
+            setCellsProcess(tmpChip, true);
+        } else {
+            if (exclusive) {
+                tmpChip->process = false;
+                setCellsProcess(tmpChip, false);
+            }
+        }
+
+    }
+
+    return true;
+}
+
+// XXX this function should probably be re-defined to merge with 'setCellsProcess'
+bool pmChipSelectCell(pmChip *chip, int cellNum, bool exclusive)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+
+    psArray *cells = chip->cells;       // Component cells
+    if (!cells || cellNum > cells->n) {
+        return false;
+    }
+
+    for (int i = 0; i < cells->n; i++) {
+        pmCell *cell = cells->data[i];
+        if (!cell) {
+            continue;
+        }
+        if (i == cellNum) {
+            cell->process = true;
+        } else {
+            if (exclusive) {
+                cell->process = false;
+            }
+        }
+    }
+    return true;
+}
+
+
+int pmFPAExcludeChip(pmFPA *fpa, int chipNum)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, -1);
+
+    psArray *chips = fpa->chips;        // Component chips
+    if (chips == NULL) {
+        psWarning("WARNING: fpa->chips == NULL\n");
+        return(0);
+    }
+    if ((chipNum >= chips->n) || (NULL == (pmChip *) chips->data[chipNum])) {
+        psWarning("WARNING: the specified chip (%d) does not exist.\n", chipNum);
+        return(0);
+    }
+
+    int numChips = 0;                   // Number of chips to be processed
+    for (int i = 0 ; i < chips->n ; i++) {
+        pmChip *tmpChip = (pmChip *) chips->data[i]; // Chip of interest
+        if (tmpChip != NULL) {
+            if (i == chipNum) {
+                tmpChip->process = false;
+                setCellsProcess(tmpChip, false); // Wipe out the cell as well
+            } else if (tmpChip->process) {
+                numChips++;
+            }
+        }
+    }
+
+    return(numChips);
+}
+
+
+int pmChipExcludeCell(pmChip *chip, int cellNum)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, -1);
+
+    psArray *cells = chip->cells;       // The component cells
+    if (!cells || cellNum > cells->n) {
+        return 0;
+    }
+
+    int numCells = 0;                   // Number of cells to be processed
+    for (int i = 0; i < cells->n; i++) {
+        pmCell *cell = cells->data[i];
+        if (!cell) {
+            continue;
+        }
+        if (i == cellNum) {
+            cell->process = false;
+        } else {
+            numCells++;
+        }
+    }
+
+    return numCells;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAFlags.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAFlags.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAFlags.h	(revision 22158)
@@ -0,0 +1,122 @@
+/*  @file pmFPAFlags.h
+ *  @brief Functions for setting and checking the status flags within the FPA hierarchy
+ * 
+ *  @author George Gusciora, MHPCC
+ *  @author Paul Price, IfA
+ *  @author Eugene Magnier, IfA
+ * 
+ *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-05-03 20:04:01 $
+ *  Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FPA_FLAGS_H
+#define PM_FPA_FLAGS_H
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+// Functions to turn on/off the file_exists flags
+
+/// Set the file_exists flag for an FPA and components
+bool pmFPASetFileStatus(pmFPA *fpa,     ///< FPA for which to set status
+                        bool status     ///< Status to set
+                       );
+
+/// Set the file_exists flag for a chip and components
+bool pmChipSetFileStatus(pmChip *chip,  ///< Chip for which to set status
+                         bool status    ///< Status to set
+                        );
+
+/// Set the file_exists flag for a cell and components
+bool pmCellSetFileStatus(pmCell *cell,  ///< Cell for which to set status
+                         bool status    ///< Status to set
+                        );
+
+// Functions to check the file_exists flags
+
+/// Return the file_exists status for an FPA and components
+bool pmFPACheckFileStatus(const pmFPA *fpa ///< FPA for which to check status
+                         );
+
+/// Return the file_exists status for a chip and components
+bool pmChipCheckFileStatus(const pmChip *chip ///< Chip for which to check status
+                          );
+
+/// Return the file_exists status for a chip and components
+bool pmCellCheckFileStatus(const pmCell *cell ///< Cell for which to check status
+                          );
+
+// Functions to turn on/off the data_exists flags
+
+/// Set the data_exists flag for an FPA and components
+bool pmFPASetDataStatus(pmFPA *fpa,     ///< FPA for which to set status
+                        bool status     ///< Status to set
+                       );
+
+/// Set the data_exists flag for a chip and components
+bool pmChipSetDataStatus(pmChip *chip,  ///< Chip for which to set status
+                         bool status    ///< Status to set
+                        );
+
+/// Set the data_exists flag for a cell and components
+bool pmCellSetDataStatus(pmCell *cell,  ///< Cell for which to set status
+                         bool status    ///< Status to set
+                        );
+
+
+// Functions the check the data_exists flags
+
+/// Check data_exists for the element of this fpa at this view
+bool pmFPAviewCheckDataStatus (const pmFPA *fpa, ///< FPA to check
+			       const pmFPAview *view ///< check for this view 
+  );
+
+/// Check data_exists for this fpa
+bool pmFPACheckDataStatus (const pmFPA *fpa ///< FPA to check
+  );
+
+/// Check data_exists for this chip
+bool pmChipCheckDataStatus (const pmChip *chip ///< Chip to check
+);
+
+/// Check data_exists for this cell
+bool pmCellCheckDataStatus (const pmCell *cell ///< Cell to check
+);
+
+/// Check data_exists for this readout
+bool pmReadoutCheckDataStatus (const pmReadout *readout ///< Readout to check
+);
+
+
+// Functions to set the process flags
+
+/// Select a chip within an FPA for processing
+///
+/// If exclusive is true, the specified chip is the only chip to be processed.  A negative value for chipNum
+/// is valid and, in combinations with exclusive, de-selects all chips.
+bool pmFPASelectChip(pmFPA *fpa,        ///< FPA containing the chip of interest
+                     int chipNum,       ///< Chip number to select
+                     bool exclusive     ///< Process this chip exclusive of the others?
+                    );
+
+/// Select a chip within a chip for processing
+///
+/// If exclusive is true, the specified cell is the only chip to be processed.  A negative value for cellNum
+/// is valid and, in combinations with exclusive, de-selects all chips.
+bool pmChipSelectCell(pmChip *chip,     ///< Chip containing the cell of interest
+                      int cellNum,      ///< Cell number to select
+                      bool exclusive    ///< Process this cell exclusive of the others?
+                     );
+
+/// Exclude a chip within an FPA from processing
+int pmFPAExcludeChip(pmFPA *fpa,        ///< FPA containing the chip of interest
+                     int chipNum        ///< Chip number to exclude
+                    );
+
+/// Exclude a cell within a chip from processing
+int pmChipExcludeCell(pmChip *chip,     ///< Chip containing the chip of interest
+                      int cellNum       ///< Cell number to exclude
+                     );
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAHeader.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAHeader.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAHeader.c	(revision 22158)
@@ -0,0 +1,77 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmConcepts.h"
+#include "pmFPAHeader.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool pmCellReadHeader(pmCell *cell, psFits *fits, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+
+    if (!cell->hdu) {
+        return pmChipReadHeader(cell->parent, fits, config);
+    }
+    if (!pmHDUReadHeader(cell->hdu, fits)) {
+        psError(PS_ERR_IO, false, "Unable to read header for cell.\n");
+        return false;
+    }
+
+    return pmConceptsReadCell(cell, PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_DATABASE, false, config);
+}
+
+
+bool pmChipReadHeader(pmChip *chip, psFits *fits, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+
+    if (!chip->hdu) {
+        return pmFPAReadHeader(chip->parent, fits, config);
+    }
+    if (!pmHDUReadHeader(chip->hdu, fits)) {
+        psError(PS_ERR_IO, false, "Unable to read header for cell.\n");
+        return false;
+    }
+
+    if (!pmConceptsReadChip(chip, PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_DATABASE, true, true, config)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read concepts for chip.\n");
+        return false;
+    }
+
+    return true;
+}
+
+
+bool pmFPAReadHeader(pmFPA *fpa, psFits *fits, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+
+    if (!fpa->hdu) {
+        return false;
+    }
+    if (!pmHDUReadHeader(fpa->hdu, fits)) {
+        psError(PS_ERR_IO, false, "Unable to read header for cell.\n");
+        return false;
+    }
+
+    if (!pmConceptsReadFPA(fpa, PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_DATABASE, true, config)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read concepts for FPA.\n");
+        return false;
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAHeader.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAHeader.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAHeader.h	(revision 22158)
@@ -0,0 +1,44 @@
+/*  @file pmFPAHeader.h
+ *  @brief Functions read FITS headers for FPA components
+ *
+ *  @author Paul Price, IfA
+ *
+ *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-06-17 22:16:38 $
+ *  Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FPA_HEADER_H
+#define PM_FPA_HEADER_H
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+/// Read the FITS header (and ingest concepts) for an FPA, if it exists at this level
+///
+/// Returns false if there was a problem.  Returns true if it successfully read the header, or if the header
+/// was already there.  No iteration to lower levels is performed.
+bool pmFPAReadHeader(pmFPA *fpa,        ///< FPA for which to read header
+                     psFits *fits,       ///< FITS file handle
+                     pmConfig *config   ///< Configuration
+                    );
+
+/// Read the FITS header (and ingest concepts) for a chip, if it exists at this level
+///
+/// Returns false if there was a problem.  Returns true if it successfully read the header, or if the header
+/// was already there.  No iteration to lower levels is performed.
+bool pmChipReadHeader(pmChip *chip,     ///< Chip for which to read header
+                      psFits *fits,      ///< FITS file handle
+                     pmConfig *config   ///< Configuration
+                     );
+
+/// Read the FITS header (and ingest concepts) for a cell, if it exists at this level
+///
+/// Returns false if there was a problem.  Returns true if it successfully read the header, or if the header
+/// was already there.  No iteration to lower levels is performed.
+bool pmCellReadHeader(pmCell *cell,     ///< Cell for which to read header
+                      psFits *fits,      ///< FITS file handle
+                     pmConfig *config   ///< Configuration
+                     );
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPALevel.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPALevel.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPALevel.c	(revision 22158)
@@ -0,0 +1,67 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <strings.h>
+#include <pslib.h>
+
+#include "pmFPALevel.h"
+
+static const char *nameNONE = "NONE";   ///< Name for PM_FPA_LEVEL_NONE
+static const char *nameFPA = "FPA";     ///< Name for PM_FPA_LEVEL_FPA
+static const char *nameCHIP = "CHIP";   ///< Name for PM_FPA_LEVEL_CHIP
+static const char *nameCELL = "CELL";   ///< Name for PM_FPA_LEVEL_CELL
+static const char *nameREADOUT = "READOUT"; ///< Name for PM_FPA_LEVEL_READOUT
+static const char *nameCHUNK = "CHUNK"; ///< Name for PM_FPA_LEVEL_CHUNK
+
+const char *pmFPALevelToName(pmFPALevel level)
+{
+    switch (level) {
+    case PM_FPA_LEVEL_NONE:
+        return nameNONE;
+    case PM_FPA_LEVEL_FPA:
+        return nameFPA;
+    case PM_FPA_LEVEL_CHIP:
+        return nameCHIP;
+    case PM_FPA_LEVEL_CELL:
+        return nameCELL;
+    case PM_FPA_LEVEL_READOUT:
+        return nameREADOUT;
+    case PM_FPA_LEVEL_CHUNK:
+        return nameCHUNK;
+    default:
+        psAbort("You can't get here; level = %d", level);
+    }
+    return NULL;
+}
+
+pmFPALevel pmFPALevelFromName(const char *name)
+{
+    if (name == NULL) {
+        return PM_FPA_LEVEL_NONE;
+    }
+    if (!strcasecmp(name, nameFPA)) {
+        return PM_FPA_LEVEL_FPA;
+    }
+    if (!strcasecmp(name, nameCHIP)) {
+        return PM_FPA_LEVEL_CHIP;
+    }
+    if (!strcasecmp(name, nameCELL)) {
+        return PM_FPA_LEVEL_CELL;
+    }
+    if (!strcasecmp(name, nameREADOUT)) {
+        return PM_FPA_LEVEL_READOUT;
+    }
+    if (!strcasecmp(name, nameCHUNK)) {
+        return PM_FPA_LEVEL_CHUNK;
+    }
+    if (!strcasecmp(name, nameNONE)) {
+        return PM_FPA_LEVEL_NONE;
+    }
+
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unrecognised FPA level name: %s", name);
+    return PM_FPA_LEVEL_NONE;
+}
+
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPALevel.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPALevel.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPALevel.h	(revision 22158)
@@ -0,0 +1,37 @@
+/* @file pmFPALevel.h
+ * @brief Defines enum and string representations for the FPA levels
+ *
+ * @author Eugene Magnier, IfA
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-02-07 00:10:08 $
+ * Copyright 2005-2008 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FPA_LEVEL_H
+#define PM_FPA_LEVEL_H
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+/// Specify the level of the FPA hierarchy
+typedef enum {
+    PM_FPA_LEVEL_NONE,                  ///< No particular level specified
+    PM_FPA_LEVEL_FPA,                   ///< Level corresponds to an FPA
+    PM_FPA_LEVEL_CHIP,                  ///< Level corresponds to a Chip
+    PM_FPA_LEVEL_CELL,                  ///< Level corresponds to a Cell
+    PM_FPA_LEVEL_READOUT,               ///< Level corresponds to a Readout
+    PM_FPA_LEVEL_CHUNK,                 ///< Level corresponds to a chunk
+} pmFPALevel;
+
+
+/// Return the string representation of the FPA level
+const char *pmFPALevelToName(pmFPALevel level ///< Level enum
+                            );
+
+/// Return the enum representation of the FPA level
+pmFPALevel pmFPALevelFromName(const char *name ///< Level name
+                             );
+/// @}
+#endif // #ifndef PM_FPA_LEVEL_H
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAMaskWeight.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAMaskWeight.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAMaskWeight.c	(revision 22158)
@@ -0,0 +1,432 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+
+#include <pslib.h>
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmHDUUtils.h"
+#include "pmHDUGenerate.h"
+#include "pmFPAMaskWeight.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// File-static (private) functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Create the parent mask images that reside in the HDU
+static void createParentMasks(pmHDU *hdu // The HDU for which to create
+                             )
+{
+    assert(hdu);
+    assert(hdu->images);
+
+    // Generate the parent mask images
+    psArray *images = hdu->images;      // Array of images
+    psArray *masks = hdu->masks;        // Array of masks
+    if (!masks) {
+        masks = psArrayAlloc(images->n);
+        hdu->masks = masks;
+    }
+
+    for (long i = 0; i < images->n; i++) {
+        psImage *image = images->data[i]; // The image for this readout
+        if (!image || masks->data[i]) {
+            continue;
+        }
+        masks->data[i] = psImageAlloc(image->numCols, image->numRows, PS_TYPE_U8);
+        psImageInit(masks->data[i], 0);
+    }
+
+    return;
+}
+
+// Create the parent weight images that reside in the HDU
+static void createParentWeights(pmHDU *hdu // The HDU for which to create
+                               )
+{
+    assert(hdu);
+    assert(hdu->images);
+
+    // Generate the parent mask images
+    psArray *images = hdu->images;      // Array of images
+    psArray *weights = hdu->weights;    // Array of weight images
+    if (!weights) {
+        weights = psArrayAlloc(images->n);
+        hdu->weights = weights;
+    }
+
+    for (long i = 0; i < images->n; i++) {
+        psImage *image = images->data[i]; // The image for this readout
+        if (!image || weights->data[i]) {
+            continue;
+        }
+        weights->data[i] = psImageAlloc(image->numCols, image->numRows, PS_TYPE_F32);
+    }
+
+    return;
+}
+
+// Identify a readout within the HDU, on the basis of the image pointer.
+// This is a little dirty, but hopefully should work....
+static long identifyReadout(pmHDU *hdu, // The HDU containing the readouts
+                            pmReadout *readout // The readout to be identified
+                           )
+{
+    assert(hdu);
+    assert(readout);
+
+    long index = -1;                    // Index of the readout
+    for (long i = 0; i < hdu->images->n && index == -1; i++) {
+        if (hdu->images->data[i] == readout->image->parent) {
+            index = i;
+        }
+    }
+
+    return index;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool pmReadoutSetMask(pmReadout *readout, psMaskType satMask, psMaskType badMask)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_IMAGE_NON_NULL(readout->image, false);
+
+    pmCell *cell = readout->parent;     // The parent cell
+    bool mdok = true;                   // Status of MD lookup
+
+    // Get the "concepts" of interest
+    float saturation = psMetadataLookupF32(&mdok, cell->concepts, "CELL.SATURATION"); // Saturation level
+    if (!mdok || isnan(saturation)) {
+        psError(PS_ERR_IO, true, "CELL.SATURATION is not set --- unable to set mask.\n");
+        return false;
+    }
+    float bad = psMetadataLookupF32(&mdok, cell->concepts, "CELL.BAD"); // Bad level
+    if (!mdok || isnan(bad)) {
+        psError(PS_ERR_IO, true, "CELL.BAD is not set --- unable to set mask.\n");
+        return false;
+    }
+    psTrace("psModules.camera", 5, "Saturation: %f, bad: %f\n", saturation, bad);
+
+
+    // Set up the mask
+    psImage *image = readout->image;    // The image pixels
+    if (!readout->mask) {
+        // Generate a (throwaway) mask image, if required
+        readout->mask = psImageAlloc(image->numCols, image->numRows, PS_TYPE_U8);
+    }
+    psImage *mask = readout->mask;      // The mask pixels
+    psImageInit(mask, 0);
+
+    // Dereference pointers for speed
+    psF32 **imageData = image->data.F32;// The image
+    psU8  **maskData  = mask->data.U8;  // The mask
+
+    for (int i = 0; i < image->numRows; i++) {
+        for (int j = 0; j < image->numCols; j++) {
+            if (imageData[i][j] >= saturation) {
+                maskData[i][j] |= satMask;
+            }
+            if (imageData[i][j] <= bad) {
+                maskData[i][j] |= badMask;
+            }
+            if (!isfinite(imageData[i][j])) {
+                maskData[i][j] |= badMask;
+            }
+        }
+    }
+
+    return true;
+}
+
+// XXX this function creates the mask pixels, or uses the existing mask
+// pixels.  currently, it will set mask bits if (value <= BAD) or (value >= SATURATION)
+// should we optionally ignore these tests?
+bool pmReadoutGenerateMask(pmReadout *readout, psMaskType satMask, psMaskType badMask)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+
+    pmCell *cell = readout->parent;     // The parent cell
+    bool mdok = true;                   // Status of MD lookup
+
+    // Create the mask image if required
+    if (!readout->mask) {
+        psRegion *trimsec = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.TRIMSEC"); // Trim section
+        if (!mdok || psRegionIsNaN(*trimsec)) {
+            psError(PS_ERR_IO, true, "CELL.TRIMSEC is not set --- unable to set mask.\n");
+            return false;
+        }
+
+        pmHDU *hdu = pmHDUFromCell(cell);   // The HDU containing the cell's pixels
+        PS_ASSERT_PTR_NON_NULL(hdu, false);
+        if (!hdu->images && !pmHDUGenerateForCell(cell)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to generate HDU for cell.\n");
+            return false;
+        }
+
+        createParentMasks(hdu);
+
+        // Need to identify which readout we're working with....
+        long index = identifyReadout(hdu, readout); // Index of the readout
+        if (index == -1) {
+            psError(PS_ERR_UNKNOWN, true, "Unable to identify readout image in HDU.\n");
+            return false;
+        }
+
+        psImage *mask = psImageSubset(hdu->masks->data[index], *trimsec); // The mask pixels
+        if (!mask) {
+            psString trimsecString = psRegionToString(*trimsec);
+            psError(PS_ERR_UNKNOWN, false, "Unable to set mask from HDU with trimsec: %s.\n", trimsecString);
+            psFree(trimsecString);
+            return false;
+        }
+        psImageInit(mask, 0);
+        assert (readout->mask == NULL); // or else this is a memory leak.
+        readout->mask = mask;
+    }
+
+    return pmReadoutSetMask(readout, satMask, badMask);
+}
+
+bool pmReadoutSetWeight(pmReadout *readout, bool poisson)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+
+    pmCell *cell = readout->parent;     // The parent cell
+    bool mdok = true;                   // Status of MD lookup
+
+    // Get the "concepts" of interest
+    float gain = psMetadataLookupF32(&mdok, cell->concepts, "CELL.GAIN"); // Cell gain
+    if (!mdok || isnan(gain)) {
+        psError(PS_ERR_IO, true, "CELL.GAIN is not set --- unable to set weight.\n");
+        return false;
+    }
+    float readnoise = psMetadataLookupF32(&mdok, cell->concepts, "CELL.READNOISE"); // Cell read noise
+    if (!mdok || isnan(readnoise)) {
+        psError(PS_ERR_IO, true, "CELL.READNOISE is not set --- unable to set weight.\n");
+        return false;
+    }
+
+    if (poisson) {
+        // Set weight image to the variance in ADU = f/g + rn^2
+        psImage *image = readout->image;    // The image pixels
+        readout->weight = (psImage*)psBinaryOp(readout->weight, image, "/", psScalarAlloc(gain, PS_TYPE_F32));
+
+        // a negative weight is non-sensical. if the image value drops below 1, the weight must be 1.
+        readout->weight = (psImage*)psUnaryOp(readout->weight, readout->weight, "abs");
+        readout->weight = (psImage*)psBinaryOp(readout->weight, readout->weight, "max",
+                                               psScalarAlloc(1, PS_TYPE_F32));
+    } else {
+        // Just use the read noise
+        if (!readout->weight) {
+            readout->weight = psImageAlloc(readout->image->numCols, readout->image->numRows, PS_TYPE_F32);
+        }
+        psImageInit(readout->weight, 0.0);
+    }
+
+    readout->weight = (psImage*)psBinaryOp(readout->weight, readout->weight, "+",
+                                           psScalarAlloc(readnoise*readnoise/gain/gain, PS_TYPE_F32));
+
+    return true;
+}
+
+// this function creates the weight pixels, or uses the existing weight pixels.  it will set
+// the noise pixel values only if the weight image is not supplied
+bool pmReadoutGenerateWeight(pmReadout *readout, bool poisson)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+
+    pmCell *cell = readout->parent;     // The parent cell
+    bool mdok = true;                   // Status of MD lookup
+
+    // Create the weight image if required
+    if (readout->weight)
+        return true;
+
+    psRegion *trimsec = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.TRIMSEC"); // Trim section
+    if (!mdok || psRegionIsNaN(*trimsec)) {
+        psError(PS_ERR_IO, true, "CELL.TRIMSEC is not set --- unable to set weight.\n");
+        return false;
+    }
+
+    pmHDU *hdu = pmHDUFromCell(cell);   // The HDU containing the cell's pixels
+    PS_ASSERT_PTR_NON_NULL(hdu, false);
+    if (!hdu->images && !pmHDUGenerateForCell(cell)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to generate HDU for cell.\n");
+        return false;
+    }
+
+    createParentWeights(hdu);
+
+    // Need to identify which readout we're working with....
+    long index = identifyReadout(hdu, readout); // Index of the readout
+    if (index == -1) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to identify readout image in HDU.\n");
+        return false;
+    }
+
+    psImage *weight = psImageSubset(hdu->weights->data[index], *trimsec); // The weight pixels
+    if (!weight) {
+        psString trimsecString = psRegionToString(*trimsec);
+        psError(PS_ERR_UNKNOWN, false, "Unable to set weight from HDU with trimsec: %s.\n",
+                trimsecString);
+        psFree(trimsecString);
+        return false;
+    }
+    psImageInit(weight, 0);
+    readout->weight = weight;
+
+    return pmReadoutSetWeight(readout, poisson);
+}
+
+bool pmReadoutGenerateMaskWeight(pmReadout *readout, psMaskType satMask, psMaskType badMask, bool poisson)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+
+    bool success = true;                // Was everything successful?
+
+    success &= pmReadoutGenerateMask(readout, satMask, badMask);
+    success &= pmReadoutGenerateWeight(readout, poisson);
+
+    return success;
+}
+
+bool pmCellGenerateMaskWeight(pmCell *cell, psMaskType satMask, psMaskType badMask, bool poisson)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+
+    bool success = true;                // Was everything successful?
+    psArray *readouts = cell->readouts; // Array of readouts
+    for (int i = 0; i < readouts->n; i++) {
+        pmReadout *readout = readouts->data[i]; // The readout
+        success &= pmReadoutGenerateMaskWeight(readout, poisson, satMask, badMask);
+    }
+
+    return success;
+}
+
+
+bool pmReadoutWeightRenorm(const pmReadout *readout, psMaskType maskVal, psStatsOptions meanStat,
+                           psStatsOptions stdevStat, int width, psRandom *rng)
+{
+    PM_ASSERT_READOUT_NON_NULL(readout, false);
+    PM_ASSERT_READOUT_IMAGE(readout, false);
+    PM_ASSERT_READOUT_WEIGHT(readout, false);
+    PS_ASSERT_INT_POSITIVE(width, false);
+
+    if (!psMemIncrRefCounter(rng)) {
+        rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+    }
+
+    psImage *image = readout->image, *mask = readout->mask, *weight = readout->weight; // Readout images
+    int numCols = image->numCols, numRows = image->numRows; // Size of images
+    int xNum = numCols / width + 1, yNum = numRows / width + 1; // Number of renormalisation regions
+    float xSize = numCols / (float)xNum, ySize = numRows / (float)yNum; // Size of renormalisation regions
+
+    psStats *meanStats = psStatsAlloc(meanStat), *stdevStats = psStatsAlloc(stdevStat); // Statistics
+    psVector *buffer = NULL;
+
+    for (int j = 0; j < yNum; j++) {
+        // Bounds in y
+        int yMin = j * ySize;
+        int yMax = (j + 1) * ySize;
+        for (int i = 0; i < xNum; i++) {
+            // Bounds in x
+            int xMin = i * xSize;
+            int xMax = (i + 1) * xSize;
+
+            psRegion region = psRegionSet(xMin, xMax, yMin, yMax); // Region of interest
+            psImage *subImage = psImageSubset(image, region); // Sub-image of the image pixels
+            psImage *subWeight = psImageSubset(weight, region); // Sub image of the weight pixels
+            psImage *subMask = mask ? psImageSubset(mask, region) : NULL; // Sub-image of the mask pixels
+
+            if (!psImageBackground(stdevStats, &buffer, subImage, subMask, maskVal, rng) ||
+                !psImageBackground(meanStats, &buffer, subWeight, subMask, maskVal, rng)) {
+                // Nothing we can do about it, but don't want to keel over and die, so do our best to flag it.
+                psString regionStr = psRegionToString(region); // String with region
+                psWarning("Unable to measure statistics over %s", regionStr);
+                psFree(regionStr);
+                psErrorClear();
+                psImageInit(subWeight, NAN);
+                if (subMask) {
+                    psImageInit(subMask, maskVal);
+                }
+            } else {
+                double meanVar = psStatsGetValue(meanStats, meanStat); // Mean of variance map
+                double stdev = psStatsGetValue(stdevStats, stdevStat); // Standard deviation of image
+                psTrace("psModules.camera", 3,
+                        "Region [%d:%d,%d:%d] has variance %lf, but mean of variance map is %lf\n",
+                        xMin, xMax, yMin, yMax, PS_SQR(stdev), meanVar);
+                psBinaryOp(subWeight, subWeight, "*", psScalarAlloc(PS_SQR(stdev) / meanVar, PS_TYPE_F32));
+            }
+
+            psFree(subImage);
+            psFree(subWeight);
+            psFree(subMask);
+        }
+    }
+    psFree(meanStats);
+    psFree(stdevStats);
+    psFree(rng);
+    psFree(buffer);
+
+    return true;
+}
+
+
+bool pmReadoutMaskNonfinite(pmReadout *readout, psMaskType maskVal)
+{
+    PM_ASSERT_READOUT_NON_NULL(readout, false);
+    PM_ASSERT_READOUT_IMAGE(readout, false);
+
+    psImage *image = readout->image;    // Readout's image
+    psImage *weight = readout->weight;  // Readout's weight
+    int numCols = image->numCols, numRows = image->numRows; // Size of image
+
+    if (!readout->mask) {
+        readout->mask = psImageAlloc(numCols, numRows, PS_TYPE_MASK);
+    }
+    psImage *mask = readout->mask;      // Readout's mask
+
+    for (int y = 0; y < numRows; y++) {
+        for (int x = 0; x < numCols; x++) {
+            if (!isfinite(image->data.F32[y][x]) || (weight && !isfinite(weight->data.F32[y][x]))) {
+                mask->data.PS_TYPE_MASK_DATA[y][x] |= maskVal;
+            }
+        }
+    }
+
+    return true;
+}
+
+
+
+bool pmReadoutMaskApply(pmReadout *readout, psMaskType maskVal)
+{
+    PM_ASSERT_READOUT_NON_NULL(readout, false);
+    PM_ASSERT_READOUT_IMAGE(readout, false);
+    PM_ASSERT_READOUT_MASK(readout, false);
+
+    int numCols = readout->image->numCols, numRows = readout->image->numRows; // Size of image
+    psMaskType **maskData = readout->mask->data.PS_TYPE_MASK_DATA; // Dereference mask
+    psF32 **imageData = readout->image->data.F32;// Dereference image
+    psF32 **weightData = readout->weight ? readout->weight->data.F32 : NULL; // Dereference weight map
+
+    for (int y = 0; y < numRows; y++) {
+        for (int x = 0; x < numCols; x++) {
+            if (maskData[y][x] & maskVal) {
+                imageData[y][x] = NAN;
+                if (weightData) {
+                    weightData[y][x] = NAN;
+                }
+            }
+        }
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAMaskWeight.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAMaskWeight.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAMaskWeight.h	(revision 22158)
@@ -0,0 +1,127 @@
+/* @file pmFPAHeader.h
+ * @brief Functions read FITS headers for FPA components
+ *
+ * @author Paul Price, IfA
+ * @author Eugene Magnier, IfA
+ *
+ * @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-15 20:25:00 $
+ * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FPA_MASK_WEIGHT_H
+#define PM_FPA_MASK_WEIGHT_H
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+#if 0
+/// Pixel mask values
+typedef enum {
+    PM_MASK_CLEAR    = 0x00,            ///< The pixel is not masked
+    PM_MASK_BLANK    = 0x01,            ///< The pixel is blank or has no (valid) data
+    PM_MASK_FLAT     = 0x02,            ///< The pixel is non-positive in the flat-field
+    PM_MASK_DETECTOR = 0x02,            ///< The detector pixel is bad (e.g., bad column, charge trap)
+    PM_MASK_SAT      = 0x04,            ///< The pixel is saturated in the image of interest
+    PM_MASK_BAD      = 0x04,            ///< The pixel is low in the image of interest
+    PM_MASK_RANGE    = 0x04,            ///< The pixel is out of range in the image of interest
+    PM_MASK_CR       = 0x08,            ///< The pixel is probably a CR
+    PM_MASK_SPARE1   = 0x10,            ///< Spare mask value
+    PM_MASK_SPARE2   = 0x20,            ///< Spare mask value
+    PM_MASK_SUSPECT  = 0x40,            ///< The pixel is suspected of being bad, but may not be
+    PM_MASK_MARK     = 0x80,            ///< The pixel is marked as temporarily ignored
+} pmMaskValue;
+#define PM_MASK_MARK 0x80            ///< The pixel is marked as temporarily ignored
+#define PM_MASK_SAT  0x04            ///< The pixel is saturated in the image of interest
+#endif
+
+/// Set a temporary readout mask using CELL.SATURATION and CELL.BAD
+///
+/// Identifies pixels that are saturated (>= CELL.SATURATION) or bad (<= CELL.BAD).  The mask that is produced
+/// within the readout is temporary --- it is not added to the HDU.  This is intended for when the user is
+/// iterating using pmReadoutReadNext, in which case the HDU can't be generated.
+bool pmReadoutSetMask(pmReadout *readout, ///< Readout for which to set mask
+                      psMaskType satMask, ///< Mask value to give saturated pixels
+                      psMaskType badMask  ///< Mask value to give bad (low) pixels
+    );
+
+
+/// Set a temporary readout weight map using CELL.GAIN and CELL.READNOISE
+///
+/// Calculates weights (actually variances) for each pixel using photon statistics and the cell gain
+/// (CELL.GAIN) and read noise (CELL.READNOISE).  The weight map that is produced within the readout is
+/// temporary --- it is not added to the HDU.  This is intended for when the user is iterating using
+/// pmReadoutReadNext, in which case the HDU can't be generated.
+bool pmReadoutSetWeight(pmReadout *readout, ///< Readout for which to set weight
+                        bool poisson    ///< Use poisson weights (in addition to read noise)?
+                       );
+
+/// Generate a readout mask (suitable for output) using CELL.SATURATION and CELL.BAD
+///
+/// Identifies pixels that are saturated (>= CELL.SATURATION) or bad (<= CELL.BAD).  The mask that is produced
+/// is suitable for output (complete with HDU entry).  This is intended for most operations.
+bool pmReadoutGenerateMask(pmReadout *readout, ///< Readout for which to generate mask
+                           psMaskType sat, ///< Mask value to give saturated pixels
+                           psMaskType bad ///< Mask value to give bad (low) pixels
+    );
+
+/// Generate a weight map (suitable for output) using CELL.GAIN and CELL.READNOISE
+///
+/// Calculates weights (actually variances) for each pixel using photon statistics and the cell gain
+/// (CELL.GAIN) and read noise (CELL.READNOISE).  The weight map that is produced within the readout is
+/// suitable for output (complete with HDU entry).  This is intended for most operations.
+bool pmReadoutGenerateWeight(pmReadout *readout, ///< Readout for which to generate weight
+                             bool poisson    ///< Use poisson weights (in addition to read noise)?
+                            );
+
+/// Generate mask and weight map for a readout
+///
+/// Calls pmReadoutGenerateMask and pmReadoutGenerateWeight for the readout
+bool pmReadoutGenerateMaskWeight(pmReadout *readout, ///< Readout for which to generate mask and weights
+                                 psMaskType sat, ///< Mask value to give saturated pixels
+                                 psMaskType bad, ///< Mask value to give bad (low) pixels
+                                 bool poisson ///< Use poisson weights (in addition to read noise)?
+                                );
+
+/// Generate mask and weight maps for all readouts within a cell
+///
+/// Calls pmReadoutGenerateMaskWeight for each readout within the cell.
+bool pmCellGenerateMaskWeight(pmCell *cell, ///< Cell for which to generate mask and weights
+                              psMaskType sat, ///< Mask value to give saturated pixels
+                              psMaskType bad, ///< Mask value to give bad (low) pixels
+                              bool poisson ///< Use poisson weights (in addition to read noise)?
+                             );
+
+/// Renormalise the weight map to match the actual variance
+///
+/// The variance in the image is measured in patches, and the variance map is adjusted so that the mean for
+/// that patch corresponds.
+bool pmReadoutWeightRenorm(const pmReadout *readout, // Readout to normalise
+                           psMaskType maskVal, // Value to mask
+                           psStatsOptions meanStat, // Statistic to measure the mean (of the variance map)
+                           psStatsOptions stdevStat, // Statistic to measure the stdev (of the image)
+                           int width,   // Width of patch (pixels)
+                           psRandom *rng // Random number generator (for sub-sampling images)
+    );
+
+/// Explicitly mask non-finite pixels
+///
+/// Since unmasked non-finite pixels can occur (e.g., by out-of-range in quantisation), it is sometimes
+/// necessary to mask them explicitly.  Non-finite pixels in the image or weight have their mask OR-ed with
+/// the provided value.
+bool pmReadoutMaskNonfinite(pmReadout *readout, ///< Readout to mask
+                            psMaskType maskVal ///< Mask value to give non-finite pixels
+    );
+
+/// Apply a mask to the image and weight map
+///
+/// Unfortunately, image subtraction may result in a bi-modal image in masked areas, which can upset image
+/// statistics (very important for quantising images so that a product can be written out!).  This function
+/// sets masked areas to NAN in the image and weight.
+bool pmReadoutMaskApply(pmReadout *readout, ///< Readout to mask
+                        psMaskType maskVal ///< Mask value for which to apply mask
+    );
+
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAMosaic.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAMosaic.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAMosaic.c	(revision 22158)
@@ -0,0 +1,1359 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAFlags.h"
+#include "pmConceptsAverage.h"
+#include "pmHDUUtils.h"
+#include "pmConfig.h"
+#include "pmAstrometryWCS.h"
+#include "pmFPAExtent.h"
+
+#include "pmFPAMosaic.h"
+
+
+#define CELL_LIST_BUFFER 10             // Buffer size for cell lists
+
+#define BLANK_VALUE 0.0                 // Value for pixels that are blank in the mosaicked image (e.g., //
+                                        // between cells).
+                                        // XXX This should ultimately be set to NAN, but psphot doesn't like
+                                        // that (masking needs to be more thorough).
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// File-static (private) functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Do two regions overlap?
+#define REGIONS_OVERLAP(region1, region2) \
+((region1->x0 > region2->x0 && region1->x0 < region2->x1) || \
+ (region1->x1 > region2->x0 && region1->x1 < region2->x1) || \
+ (region1->y0 > region2->y0 && region1->y0 < region2->y1) || \
+ (region1->y1 > region2->y0 && region1->y1 < region2->y1))
+
+// Compare a value with a maximum and minimum
+#define COMPARE(value,min,max) \
+if ((value) < (min)) { \
+    (min) = (value); \
+} \
+if ((value) > (max)) { \
+    (max) = (value); \
+}
+
+// Update a concept to the assumed value
+#define FIX_CONCEPT(SOURCE, NAME, TYPE, VALUE) \
+psMetadataItem *item = psMetadataLookup(SOURCE, NAME); \
+item->data.TYPE = VALUE;
+
+// Get the bounds for an chip's pixels on the HDU
+static bool chipBounds(psRegion *bounds, // The bounds for the chip
+                       const pmChip *chip // The chip to examine for contiguity
+                      )
+{
+    assert(chip);
+
+    psArray *cells = chip->cells;       // The array of cells
+    bool mdok = true;                   // Status of MD lookup
+    for (int i = 0; i < cells->n; i++) {
+        pmCell *cell = cells->data[i];  // Cell of interest
+        psRegion *trimsec = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.TRIMSEC"); // Trim section
+        if (!mdok || !trimsec || psRegionIsNaN(*trimsec)) {
+            psError(PS_ERR_UNKNOWN, true, "CELL.TRIMSEC hasn't been set for cell %d.\n", i);
+            return false;
+        }
+
+        if (trimsec->x0 < bounds->x0) {
+            bounds->x0 = trimsec->x0;
+        }
+        if (trimsec->x1 > bounds->x1) {
+            bounds->x1 = trimsec->x1;
+        }
+        if (trimsec->y0 < bounds->y0) {
+            bounds->y0 = trimsec->y0;
+        }
+        if (trimsec->y1 > bounds->y1) {
+            bounds->y1 = trimsec->y1;
+        }
+    }
+
+    return true;
+}
+
+// Make sure the TRIMSEC doesn't overlap with the established image bounds
+static bool chipContiguousTrimsec(psRegion *bounds, // The bounds of the image, altered if primary==true
+                                  const pmChip *chip // The chip to examine for contiguity
+                                 )
+{
+    assert(bounds);
+    assert(chip);
+
+    psArray *cells = chip->cells;       // The array of cells
+    bool mdok = true;                   // Status of MD lookup
+    for (int i = 0; i < cells->n; i++) {
+        pmCell *cell = cells->data[i];  // Cell of interest
+        psRegion *trimsec = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.TRIMSEC"); // Trim section
+        if (!mdok || !trimsec || psRegionIsNaN(*trimsec)) {
+            psError(PS_ERR_UNKNOWN, true, "CELL.TRIMSEC hasn't been set for cell %d.\n", i);
+            return false;
+        }
+
+        if (REGIONS_OVERLAP(trimsec, bounds)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+// Make sure the BIASSEC doesn't overlap with the established image bounds
+static bool chipContiguousBiassec(psRegion *bounds, // The bounds of the image, altered if primary==true
+                                  const pmChip *chip // The chip to examine for contiguity
+                                 )
+{
+    assert(bounds);
+    assert(chip);
+
+    // Check that the biases don't get in the way
+    psArray *cells = chip->cells;       // The array of cells
+    bool mdok = true;                   // Status of MD lookup
+    for (int i = 0; i < cells->n; i++) {
+        pmCell *cell = cells->data[i];  // Cell of interest
+        psList *biassecs = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.BIASSEC"); // Bias sections
+        if (!mdok || !biassecs) {
+            psError(PS_ERR_UNKNOWN, true, "CELL.BIASSEC hasn't been set for cell %d.\n", i);
+            return false;
+        }
+        if (biassecs->n == 0) {
+            // No point allocating an iterator if there's nothing there to iterate on
+            continue;
+        }
+        psListIterator *biassecsIter = psListIteratorAlloc(biassecs, PS_LIST_HEAD, false); // Iterator
+        psRegion *biassec = NULL;       // Bias section from iteration
+        while ((biassec = psListGetAndIncrement(biassecsIter))) {
+            if (psRegionIsNaN(*biassec)) {
+                continue;
+            }
+            if (REGIONS_OVERLAP(biassec, bounds)) {
+                psFree(biassecsIter);
+                return false;
+            }
+        }
+        psFree(biassecsIter);
+    }
+
+    // If we've gotten this far, everything is fine.
+    return true;
+}
+
+// Are the pixels for the FPA contiguous on the HDU?
+// Work this out by examining all the CELL.TRIMSEC and CELL.BIASSEC regions for the component cells
+static bool fpaContiguous(psRegion *bounds, // The bounds of the image, returned
+                          const pmFPA *fpa // The FPA to examine for contiguity
+                         )
+{
+    assert(bounds);
+    assert(fpa);
+
+    *bounds = psRegionSet(INFINITY, 0, INFINITY, 0);
+
+    // Get the size of the pixels on the HDU
+    psArray *chips = fpa->chips;        // The array of chips
+    for (int i = 0; i < chips->n; i++) {
+        pmChip *chip = chips->data[i];  // Chip of interest
+        if (!chipBounds(bounds, chip)) {
+            return false;
+        }
+    }
+
+    // Make sure the bias regions don't get in the way of the HDU
+    for (int i = 0; i < chips->n; i++) {
+        pmChip *chip = chips->data[i];  // Chip of interest
+        if (!chipContiguousBiassec(bounds, chip)) {
+            return false;
+        }
+    }
+
+    // If we got through it all, they must all be contiguous
+    return true;
+}
+
+
+
+// Check a cell for niceness in the parity and binning
+static bool niceCellParityBinning(int *xBin, int *yBin, // Binning for cell, to be returned
+                                  const pmCell *cell // Cell to check for niceness
+                                 )
+{
+    assert(xBin);
+    assert(yBin);
+    assert(cell);
+
+    // A "nice" cell must have only a single readout
+    if (cell->readouts->n != 1) {
+        return false;
+    }
+
+    // A "nice" cell must have parity == 1
+    bool mdok = true;                   // Status of MD lookup
+    int xParity = psMetadataLookupS32(&mdok, cell->concepts, "CELL.XPARITY"); // Parity in x
+    if (!mdok || xParity == 0) {
+        psError(PS_ERR_UNKNOWN, true, "CELL.XPARITY hasn't been set for cell.\n");
+        return false;
+    }
+    if (xParity != 1) {
+        return false;
+    }
+    int yParity = psMetadataLookupS32(&mdok, cell->concepts, "CELL.YPARITY"); // Parity in y
+    if (!mdok || yParity == 0) {
+        psError(PS_ERR_UNKNOWN, true, "CELL.YPARITY hasn't been set for cell.\n");
+        return false;
+    }
+    if (yParity != 1) {
+        return false;
+    }
+
+    // A "nice" cell must have consistent binning
+    int xBinCell = psMetadataLookupS32(&mdok, cell->concepts, "CELL.XBIN"); // Binning in x
+    if (!mdok || xBin <= 0) {
+        psError(PS_ERR_UNKNOWN, true, "CELL.XBIN hasn't been set for cell.\n");
+        return false;
+    }
+    int yBinCell = psMetadataLookupS32(&mdok, cell->concepts, "CELL.YBIN"); // Binning in y
+    if (!mdok || yBin <= 0) {
+        psError(PS_ERR_UNKNOWN, true, "CELL.YBIN hasn't been set for cell.\n");
+        return false;
+    }
+    if (*xBin == 0 || *yBin == 0) {
+        *xBin = xBinCell;
+        *yBin = yBinCell;
+    } else if (xBinCell != *xBin || yBinCell != *yBin) {
+        return false;
+    }
+
+    return true;
+}
+
+
+// Check a cell for niceness in the boundaries
+static bool niceCellBounds(const pmCell *cell, // Cell to check for niceness
+                           const psRegion *imageBounds // Bounds of the image on the HDU
+                          )
+{
+    // A "nice" cell must have the (0,0) pixel at CELL.X0,CELL.Y0
+    bool mdok = true;                   // Status of MD lookup
+    int x0 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.X0"); // Position of (0,0) on chip
+    if (!mdok) {
+        psError(PS_ERR_UNKNOWN, true, "CELL.X0 hasn't been set for cell.\n");
+        return false;
+    }
+    int y0 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.Y0"); // Position of (0,0) on chip
+    if (!mdok) {
+        psError(PS_ERR_UNKNOWN, true, "CELL.Y0 hasn't been set for cell.\n");
+        return false;
+    }
+    pmReadout *readout = cell->readouts->data[0]; // A representative readout
+    if (!readout) {
+        return false;                   // Nothing here
+    }
+    if (x0 != readout->col0 + readout->image->col0 - (int)imageBounds->x0 ||
+            y0 != readout->row0 + readout->image->row0 - (int)imageBounds->y0) {
+        psTrace("psModules.camera", 5, "CELL.X0,Y0 don't match: %d,%d vs %d,%d\n", x0, y0,
+                readout->col0 + readout->image->col0 - (int)imageBounds->x0,
+                readout->row0 + readout->image->row0 - (int)imageBounds->y0);
+        return false;
+    }
+
+    return true;
+}
+
+
+// Is the chip "nice"?  If so, return the region containing the chip pixels
+static psRegion *niceChip(int *xBinChip, int *yBinChip, // Binning for chip, to be returned
+                          const pmChip *chip // Chip to examine for "niceness".
+                         )
+{
+    assert(xBinChip);
+    assert(yBinChip);
+    assert(chip);
+
+    // Check that we've got the HDU in the chip or the FPA
+    if ((!chip->hdu || !chip->hdu->images) && (!chip->parent->hdu || !chip->parent->hdu->images)) {
+        return NULL;
+    }
+
+    // Check parity and binning for component cells
+    *xBinChip = 0;
+    *yBinChip = 0;
+    for (int i = 0; i < chip->cells->n; i++) {
+        pmCell *cell = chip->cells->data[i]; // The cell of interest
+        if (!niceCellParityBinning(xBinChip, yBinChip, cell)) {
+            return NULL;
+        }
+    }
+
+    // Now check that the pixels are all contiguous
+    psRegion *imageBounds = psRegionAlloc(INFINITY, 0, INFINITY, 0); // Bound of image on HDU
+    if (!chipBounds(imageBounds, chip) || !chipContiguousBiassec(imageBounds, chip)) {
+        psTrace("psModules.camera", 5, "Image isn't contiguous.\n");
+        psFree(imageBounds);
+        return NULL;
+    }
+
+    psString region = psRegionToString(*imageBounds);
+    psTrace("psModules.camera", 7, "Image bounds: %s\n", region);
+    psFree(region);
+
+    for (int i = 0; i < chip->cells->n; i++) {
+        pmCell *cell = chip->cells->data[i]; // The cell of interest
+        if (!niceCellBounds(cell, imageBounds)) {
+            psFree(imageBounds);
+            return NULL;
+        }
+    }
+
+    // Need to check all the other chips if the HDU is in the FPA
+    pmFPA *fpa = chip->parent;          // The parent FPA
+    if (fpa->hdu && fpa->hdu->images) {
+        psArray *chips = fpa->chips;    // Array of chips
+        for (int i = 0; i < chips->n; i++) {
+            pmChip *testChip = chips->data[i]; // The chip of interest
+            if (testChip == chip) {
+                // Already done this one
+                continue;
+            }
+            if (!chipContiguousTrimsec(imageBounds, testChip) ||
+                    !chipContiguousBiassec(imageBounds, testChip)) {
+                psTrace("psModules.camera", 5, "Image isn't contiguous.\n");
+                psFree(imageBounds);
+                return NULL;
+            }
+        }
+    }
+
+    return imageBounds;
+}
+
+// Is the FPA "nice"?  If so, return the region containing the FPA pixels
+static psRegion *niceFPA(int *xBinFPA, int *yBinFPA, // Binning for FPA, to be returned
+                         const pmFPA *fpa  // FPA to examine for "niceness".
+                        )
+{
+    assert(xBinFPA);
+    assert(yBinFPA);
+    assert(fpa);
+
+    // Check that we've got the HDU in the chip or the FPA
+    if (!fpa->hdu || !fpa->hdu->images) {
+        return NULL;
+    }
+
+    // Check parity and binning for component cells
+    *xBinFPA = 0;
+    *yBinFPA = 0;
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i]; // The chip of interest
+        for (int j = 0; i < chip->cells->n; i++) {
+            pmCell *cell = chip->cells->data[j]; // The cell of interest
+            if (!niceCellParityBinning(xBinFPA, yBinFPA, cell)) {
+                return NULL;
+            }
+        }
+    }
+
+    // Now check that the pixels are all contiguous
+    psRegion *imageBounds = psRegionAlloc(0, 0, 0, 0); // Bound of image on HDU
+    if (!fpaContiguous(imageBounds, fpa)) {
+        psTrace("psModules.camera", 5, "Image isn't contiguous.\n");
+        psFree(imageBounds);
+        return NULL;
+    }
+
+    psString region = psRegionToString(*imageBounds);
+    psTrace("psModules.camera", 7, "Image bounds: %s\n", region);
+    psFree(region);
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i]; // The chip of interest
+        for (int j = 0; i < chip->cells->n; i++) {
+            pmCell *cell = chip->cells->data[j]; // The cell of interest
+            if (!niceCellBounds(cell, imageBounds)) {
+                psFree(imageBounds);
+                return NULL;
+            }
+        }
+    }
+
+    return imageBounds;
+}
+
+// supporting macros used by imageMosaic()
+// copy pixels without binning
+#define COPY_WITH_PARITY_DIFFERENCE(TYPE) \
+        case PS_TYPE_##TYPE: { \
+                for (int y = 0; y < image->numRows; y++) { \
+                    int yTarget =  yTargetBase + yParity * y; \
+                    for (int x = 0; x < image->numCols; x++) { \
+                        int xTarget = xTargetBase + xParity * x; \
+                        mosaic->data.TYPE[yTarget][xTarget] = image->data.TYPE[y][x]; \
+                    } \
+                } \
+            } \
+            break;
+
+// In case the original image is binned but the mosaic is not, we need to fill in the values in
+// the mosaic.  this operation should be replaced with a call to one of the functions defined
+// in psImageBinning
+#define FILL_IN(TYPE) \
+        case PS_TYPE_##TYPE: \
+            for (int y = 0; y < image->numRows; y++) { \
+                float yTargetBinBase = yTargetBase + yParity * yBinSource->data.S32[i] * y / yBinTarget; \
+                for (int x = 0; x < image->numCols; x++) { \
+                    float xTargetBinBase = xTargetBase + xParity * xBinSource->data.S32[i] * x / xBinTarget; \
+                    for (int j = 0; j < yBinSource->data.S32[i]; j++) { \
+                        int yTarget = (int)(yTargetBinBase + yParity * (float)j / (float)yBinTarget); \
+                        for (int k = 0; k < xBinSource->data.S32[i]; k++) { \
+                            int xTarget = (int)(xTargetBinBase + xParity * (float)k / (float)xBinTarget); \
+                            mosaic->data.TYPE[yTarget][xTarget] = image->data.TYPE[y][x]; \
+                        } \
+                    } \
+                } \
+            } \
+            break;
+
+// Mosaic multiple images, with flips, binning and offsets
+static psImage *imageMosaic(const psArray *source, // Images to splice in
+                            const psVector *xFlip, const psVector *yFlip, // Need to flip x and y?
+                            const psVector *xBinSource, // Binning in x of source images
+                            const psVector *yBinSource, // Binning in y of source images
+                            int xBinTarget, int yBinTarget, // Binning in x and y of target images
+                            const psVector *x0, const psVector *y0, // Offsets for source images on target
+                            double unexposed // Value for unexposed pixels
+                           )
+{
+    assert(source);
+    assert(xFlip && xFlip->type.type == PS_TYPE_U8);
+    assert(yFlip && yFlip->type.type == PS_TYPE_U8);
+    assert(xBinSource && xBinSource->type.type == PS_TYPE_S32);
+    assert(yBinSource && yBinSource->type.type == PS_TYPE_S32);
+    assert(x0 && x0->type.type == PS_TYPE_S32);
+    assert(y0 && y0->type.type == PS_TYPE_S32);
+    assert(xFlip->n == source->n);
+    assert(yFlip->n == source->n);
+    assert(xBinSource->n == source->n);
+    assert(yBinSource->n == source->n);
+    assert(x0->n == source->n);
+    assert(y0->n == source->n);
+
+    if (source->n == 0) {
+        return NULL;
+    }
+
+    // Get the maximum extent of the mosaic image
+    int xMin = +INT_MAX;
+    int xMax = -INT_MAX;
+    int yMin = +INT_MAX;
+    int yMax = -INT_MAX;
+    psElemType type = 0;
+    int numImages = 0;                  // Number of images
+    psTrace("psModules.camera", 3, "Mosaicking %ld cells.\n", source->n);
+    for (int i = 0; i < source->n; i++) {
+        psImage *image = source->data[i]; // The image of interest
+        if (!image) {
+            continue;
+        }
+        numImages++;
+
+        // Only implemented for F32 and U8 images so far.
+        assert(image->type.type == PS_TYPE_F32 || image->type.type == PS_TYPE_U8);
+        // All input types must be the same
+        if (type == 0) {
+            type = image->type.type;
+        }
+        assert(type == image->type.type);
+
+        // Size of cell in x and y
+        int xParity = xFlip->data.U8[i] ? -1 : 1;
+        int yParity = yFlip->data.U8[i] ? -1 : 1;
+        psTrace("psModules.camera", 5, "Extent of cell %d: %d -> %d , %d -> %d\n", i, x0->data.S32[i],
+                x0->data.S32[i] + xParity * xBinSource->data.S32[i] * image->numCols, y0->data.S32[i],
+                y0->data.S32[i] + yParity * yBinSource->data.S32[i] * image->numRows);
+
+        COMPARE(x0->data.S32[i], xMin, xMax);
+        COMPARE(y0->data.S32[i], yMin, yMax);
+        // Subtract the parity to get the inclusive limit (not exclusive)
+        COMPARE(x0->data.S32[i] + xParity * xBinSource->data.S32[i] * image->numCols - xParity, xMin, xMax);
+        COMPARE(y0->data.S32[i] + yParity * yBinSource->data.S32[i] * image->numRows - yParity, yMin, yMax);
+    }
+    if (numImages == 0) {
+        return NULL;
+    }
+
+    // Set up the image
+    // Since both upper and lower values are inclusive, we need to add one to the size
+    float xSize = (float)(xMax - xMin + 1) / (float)xBinTarget;
+    if (xSize - (int)xSize > 0) {
+        xSize += 1;
+    }
+    float ySize = (float)(yMax - yMin + 1) / (float)yBinTarget;
+    if (ySize - (int)ySize > 0) {
+        ySize += 1;
+    }
+
+    psTrace("psModules.camera", 3, "Spliced image will be %dx%d\n", (int)xSize, (int)ySize);
+    psImage *mosaic = psImageAlloc((int)xSize, (int)ySize, type); // The mosaic image
+    psImageInit(mosaic, unexposed);
+
+    // Next pass through the images to do the mosaicking
+    // XXX this function uses summing for the output: is this the right choice?
+    for (int i = 0; i < source->n; i++) {
+        psImage *image = source->data[i]; // The image of interest
+        if (!image) {
+            continue;
+        }
+        int xParity = xFlip->data.U8[i] ? -1 : 1; // Parity difference, in x
+        int yParity = yFlip->data.U8[i] ? -1 : 1; // Parity difference, in y
+        int xTargetBase = (x0->data.S32[i] - xMin) / xBinTarget; // The base x position in the target frame
+        int yTargetBase = (y0->data.S32[i] - yMin) / yBinTarget; // The base y position in the target frame
+
+        // in the first case, we are just copy a section pixel-by-pixel
+        if ((xBinSource->data.S32[i] == xBinTarget) &&
+            (yBinSource->data.S32[i] == yBinTarget) &&
+            (xFlip->data.U8[i] == 0) &&
+            (yFlip->data.U8[i] == 0)) {
+            // Let someone else do the hard work
+            psImageOverlaySection(mosaic, image, xTargetBase, yTargetBase, "=");
+            continue;
+        }
+
+        // in the second case, there's a difference with the parities, but we don't have to
+        // worry about binning
+        if (xBinSource->data.S32[i] == xBinTarget && yBinSource->data.S32[i] == yBinTarget) {
+            switch (type) {
+                COPY_WITH_PARITY_DIFFERENCE(F32);
+                COPY_WITH_PARITY_DIFFERENCE(U8);
+              default:
+                psAbort("Should never get here.\n");
+            }
+            continue;
+        }
+
+        // In the third case, the images are flipped and have different binnnig.
+        // We have to do all of the hard work ourselves
+        switch (type) {
+            FILL_IN(F32);
+            FILL_IN(U8);
+          default:
+            psAbort("Should never get here.\n");
+        }
+    } // Iterating over images
+
+    return mosaic;
+}
+
+// Add a cell and its various properties to the arrays
+static bool addCell(psArray *images,    // Array of images
+                    psArray *masks,     // Array of masks
+                    psArray *weights,   // Array of weights
+                    psVector *x0,       // Array of X0
+                    psVector *y0,       // Array of Y0
+                    psVector *xBin,     // Array of XBIN
+                    psVector *yBin,     // Array of YBIN
+                    psVector *xFlip,    // Array indicating whether x axis should be flipped
+                    psVector *yFlip,    // Array indicating whether y axis should be flipped
+                    const pmCell *cell, // Cell to add
+                    int *xBinMin,       // The minimum x binning, returned
+                    int *yBinMin,       // The minimum y binning, returned
+                    bool chipStuff,      // Worry about chip stuff as well?
+                    int x0Target, int y0Target, // Target x0 and y0 offsets
+                    int xParityTarget, int yParityTarget // Target parities
+                   )
+{
+    if (!cell) {
+        return false;
+    }
+
+    if (cell->readouts->n > 1) {
+        psWarning("Cell contains more than one readout (%ld) --- skipping.\n", cell->readouts->n);
+	return true;
+    }
+
+    // Expand the arrays and vectors to handle new data
+    long index = images->n;               // The index to use
+    if (images->n == images->nalloc) {
+        images  = psArrayRealloc(images,  index + CELL_LIST_BUFFER);
+        masks   = psArrayRealloc(masks,   index + CELL_LIST_BUFFER);
+        weights = psArrayRealloc(weights, index + CELL_LIST_BUFFER);
+        x0    = psVectorRealloc(x0,    index+ CELL_LIST_BUFFER);
+        y0    = psVectorRealloc(y0,    index+ CELL_LIST_BUFFER);
+        xBin  = psVectorRealloc(xBin,  index+ CELL_LIST_BUFFER);
+        yBin  = psVectorRealloc(yBin,  index+ CELL_LIST_BUFFER);
+        xFlip = psVectorRealloc(xFlip, index+ CELL_LIST_BUFFER);
+        yFlip = psVectorRealloc(yFlip, index+ CELL_LIST_BUFFER);
+    }
+
+    images->n = index + 1;
+    masks->n = index + 1;
+    weights->n = index + 1;
+    x0->n = index + 1;
+    y0->n = index + 1;
+    xBin->n = index + 1;
+    yBin->n = index + 1;
+    xFlip->n = index + 1;
+    yFlip->n = index + 1;
+
+    bool mdok = true;                   // Status of MD lookup
+    bool good = true;                   // Is everything good?
+
+    // Offset of the cell on the chip
+    int x0Cell = psMetadataLookupS32(&mdok, cell->concepts, "CELL.X0");
+    if (!mdok) {
+        psError(PS_ERR_UNKNOWN, true, "CELL.X0 for cell is not set.\n");
+        good = false;
+    }
+    int y0Cell = psMetadataLookupS32(&mdok, cell->concepts, "CELL.Y0");
+    if (!mdok) {
+        psError(PS_ERR_UNKNOWN, true, "CELL.Y0 for cell is not set.\n");
+        good = false;
+    }
+    psTrace("psModules.camera", 5, "Cell %ld: x0=%d y0=%d\n", index, x0Cell, y0Cell);
+
+    // Offset of the chip on the FPA
+    int x0Chip = 0, y0Chip = 0;
+    if (chipStuff) {
+        pmChip *chip = cell->parent;    // The parent chip
+        if (!chip) {
+            psError(PS_ERR_UNKNOWN, true, "Cell has no parent chip --- can't find CHIP.X0 and CHIP.Y0\n");
+            good = false;
+        }
+        x0Chip = psMetadataLookupS32(&mdok, chip->concepts, "CHIP.X0");
+        if (!mdok) {
+            psError(PS_ERR_UNKNOWN, true, "CHIP.X0 for chip is not set.\n");
+            good = false;
+        }
+        y0Chip = psMetadataLookupS32(&mdok, chip->concepts, "CHIP.Y0");
+        if (!mdok) {
+            psError(PS_ERR_UNKNOWN, true, "CHIP.Y0 for chip is not set.\n");
+            good = false;
+        }
+    }
+
+    // Binning
+    xBin->data.S32[index] = psMetadataLookupS32(&mdok, cell->concepts, "CELL.XBIN");
+    if (!mdok || xBin->data.S32[index] == 0) {
+        psError(PS_ERR_UNKNOWN, true, "CELL.XBIN for cell is not set.\n");
+        return false;
+    } else if (xBin->data.S32[index] < *xBinMin) {
+        *xBinMin = xBin->data.S32[index];
+    }
+    yBin->data.S32[index] = psMetadataLookupS32(&mdok, cell->concepts, "CELL.YBIN");
+    if (!mdok || yBin->data.S32[index] == 0) {
+        psError(PS_ERR_UNKNOWN, true, "CELL.YBIN for cell is not set.\n");
+        return false;
+    } else if (yBin->data.S32[index] < *yBinMin) {
+        *yBinMin = yBin->data.S32[index];
+    }
+
+    // Do we need to flip?
+    int xParityCell = psMetadataLookupS32(&mdok, cell->concepts, "CELL.XPARITY");
+    if (!mdok || (xParityCell != 1 && xParityCell != -1)) {
+        psError(PS_ERR_UNKNOWN, true, "CELL.XPARITY for cell is not set.\n");
+        return false;
+    }
+    int yParityCell = psMetadataLookupS32(&mdok, cell->concepts, "CELL.YPARITY");
+    if (!mdok || (yParityCell != 1 && yParityCell != -1)) {
+        psError(PS_ERR_UNKNOWN, true, "CELL.YPARITY for cell is not set.\n");
+        return false;
+    }
+
+    // Parity of the chip on the FPA
+    int xParityChip = 1, yParityChip = 1;
+    if (chipStuff) {
+        pmChip *chip = cell->parent;    // The parent chip
+        xParityChip = psMetadataLookupS32(&mdok, chip->concepts, "CHIP.XPARITY");
+        if (!mdok || (xParityChip != 1 && xParityChip != -1)) {
+            psError(PS_ERR_UNKNOWN, true, "CHIP.XPARITY for chip is not set.\n");
+            return false;
+        }
+        yParityChip = psMetadataLookupS32(&mdok, chip->concepts, "CHIP.YPARITY");
+        if (!mdok || (yParityChip != 1 && yParityChip != -1)) {
+            psError(PS_ERR_UNKNOWN, true, "CHIP.YPARITY for chip is not set.\n");
+            return false;
+        }
+    }
+
+    // Set the flips on the basis of the parity
+    // XXX if (level == CHIP) : only apply Cell parity
+    // XXX if (level == FPA) : apply Chip & Cell parity
+    if (xParityCell * xParityChip == xParityTarget) {
+        xFlip->data.U8[index] = 0;
+    } else {
+        xFlip->data.U8[index] = 1;
+    }
+    if (yParityCell * yParityChip == yParityTarget) {
+        yFlip->data.U8[index] = 0;
+    } else {
+        yFlip->data.U8[index] = 1;
+    }
+
+    x0->data.S32[index] = x0Chip + x0Cell - x0Target;
+    y0->data.S32[index] = y0Chip + y0Cell - y0Target;
+
+    // Add the readout to the array of images to be mosaicked
+    psArray *readouts = cell->readouts; // The array of readouts
+    pmReadout *readout = readouts->data[0]; // The only readout we'll bother with
+
+    // The images to put into the mosaic
+    images->data[index]  = psMemIncrRefCounter(readout->image);
+    weights->data[index] = psMemIncrRefCounter(readout->weight);
+    masks->data[index]   = psMemIncrRefCounter(readout->mask);
+
+    psTrace("psModules.camera", 9, "Added cell (%p) %ld: %d,%d; %d,%d, %d,%d.\n", cell, index,
+            x0->data.S32[index], y0->data.S32[index], xBin->data.S32[index], yBin->data.S32[index],
+            xFlip->data.U8[index], yFlip->data.U8[index]);
+
+    return true;
+}
+
+
+// Mosaic together the cells in a chip
+static bool chipMosaic(psImage **mosaicImage, // The mosaic image, to be returned
+                       psImage **mosaicMask, // The mosaic mask, to be returned
+                       psImage **mosaicWeights, // The mosaic weights, to be returned
+                       int *xBinChip, int *yBinChip, // The binning in x and y, to be returned
+                       const pmChip *chip, // Chip to mosaic
+                       const pmCell *targetCell, // Cell to which to mosaic
+                       psMaskType blank // Mask value to give blank pixels
+                      )
+{
+    assert(mosaicImage);
+    assert(mosaicMask);
+    assert(mosaicWeights);
+    assert(xBinChip);
+    assert(yBinChip);
+    assert(chip);
+    assert(targetCell);
+
+    psArray *images = psArrayAlloc(0); // Array of images that will be mosaicked
+    psArray *weights = psArrayAlloc(0); // Array of weight images to be mosaicked
+    psArray *masks = psArrayAlloc(0); // Array of mask images to be mosaicked
+    psVector *x0 = psVectorAlloc(0, PS_TYPE_S32); // Origin x coordinates
+    psVector *y0 = psVectorAlloc(0, PS_TYPE_S32); // Origin y coordinates
+    psVector *xBin = psVectorAlloc(0, PS_TYPE_S32); // Binning in x
+    psVector *yBin = psVectorAlloc(0, PS_TYPE_S32); // Binning in y
+    psVector *xFlip = psVectorAlloc(0, PS_TYPE_U8); // Flip in x?
+    psVector *yFlip = psVectorAlloc(0, PS_TYPE_U8); // Flip in y?
+
+    // Get the target characteristics
+    bool mdok = true;                   // Status of MD lookup
+    int x0Target = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.X0");
+    if (!mdok) {
+        psWarning("CELL.X0 is not set for the target cell; assuming 0.\n");
+        FIX_CONCEPT(targetCell->concepts, "CELL.X0", S32, 0);
+    }
+    int y0Target = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.Y0");
+    if (!mdok) {
+        psWarning("CELL.Y0 is not set for the target cell; assuming 0.\n");
+        FIX_CONCEPT(targetCell->concepts, "CELL.Y0", S32, 0);
+    }
+    int xParityTarget = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.XPARITY");
+    if (!mdok || (xParityTarget != -1 && xParityTarget != 1)) {
+        psWarning("CELL.XPARITY is not set for the target cell; assuming 1.\n");
+        FIX_CONCEPT(targetCell->concepts, "CELL.XPARITY", S32, 1);
+        xParityTarget = 1;
+    }
+    int yParityTarget = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.YPARITY");
+    if (!mdok || (yParityTarget != -1 && yParityTarget != 1)) {
+        psWarning("CELL.YPARITY is not set for the target cell; assuming 1.\n");
+        FIX_CONCEPT(targetCell->concepts, "CELL.YPARITY", S32, 1);
+        yParityTarget = 1;
+    }
+
+    // Binning for the mosaicked chip is the minimum binning allowed by the cells
+    *xBinChip = INT_MAX;
+    *yBinChip = INT_MAX;
+
+    // Set up the required inputs
+    bool allGood = true;                // Is everything good, well-behaved?
+    psArray *cells = chip->cells;       // The array of cells
+    for (int i = 0; i < cells->n; i++) {
+        pmCell *cell = cells->data[i];  // The cell of interest
+        if (!cell || !cell->data_exists) {
+            continue;
+        }
+        allGood &= addCell(images, masks, weights, x0, y0, xBin, yBin, xFlip, yFlip,
+                           cell, xBinChip, yBinChip, false, x0Target, y0Target,
+                           xParityTarget, yParityTarget);
+    }
+
+    // Check to see if the target has a smaller binning in mind
+    int xBinTarget = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.XBIN");
+    if (!mdok || xBinTarget == 0) {
+        // CELL.XBIN is not set for the target cell --- assume it's the same as the source
+        FIX_CONCEPT(targetCell->concepts, "CELL.XBIN", S32, *xBinChip);
+    } else {
+        *xBinChip = xBinTarget;
+    }
+    int yBinTarget = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.YBIN");
+    if (!mdok || yBinTarget == 0) {
+        // CELL.YBIN is not set for the target cell --- assume it's the same as the source
+        FIX_CONCEPT(targetCell->concepts, "CELL.YBIN", S32, *yBinChip);
+    } else {
+        *yBinChip = yBinTarget;
+    }
+
+    // Mosaic the images together and we're done
+    if (allGood) {
+        *mosaicImage = imageMosaic(images, xFlip, yFlip, xBin, yBin, *xBinChip, *yBinChip, x0, y0, BLANK_VALUE);
+        *mosaicWeights = imageMosaic(weights, xFlip, yFlip, xBin, yBin, *xBinChip, *yBinChip, x0, y0, BLANK_VALUE);
+        *mosaicMask = imageMosaic(masks, xFlip, yFlip, xBin, yBin, *xBinChip, *yBinChip, x0, y0, blank);
+    }
+
+    // Clean up
+    psFree(images);
+    psFree(weights);
+    psFree(masks);
+    psFree(xFlip);
+    psFree(yFlip);
+    psFree(xBin);
+    psFree(yBin);
+    psFree(x0);
+    psFree(y0);
+
+    return allGood;
+}
+
+// Mosaic together the cells in a FPA
+static bool fpaMosaic(psImage **mosaicImage, // The mosaic image, to be returned
+                      psImage **mosaicMask, // The mosaic mask, to be returned
+                      psImage **mosaicWeights, // The mosaic weights, to be returned
+                      int *xBinFPA, int *yBinFPA, // The binning in x and y, to be returned
+                      const pmFPA *fpa,  // FPA to mosaic
+                      const pmChip *targetChip, // Chip to which to mosaic
+                      const pmCell *targetCell, // Cell to which to mosaic
+                      psMaskType blank  // Mask value to give blank pixels
+                     )
+{
+    assert(mosaicImage);
+    assert(mosaicMask);
+    assert(mosaicWeights);
+    assert(xBinFPA);
+    assert(yBinFPA);
+    assert(fpa);
+    assert(targetChip);
+    assert(targetCell);
+
+    psArray *images = psArrayAlloc(0); // Array of images that will be mosaicked
+    psArray *weights = psArrayAlloc(0); // Array of weight images to be mosaicked
+    psArray *masks = psArrayAlloc(0); // Array of mask images to be mosaicked
+    psVector *x0 = psVectorAlloc(0, PS_TYPE_S32); // Origin x coordinates
+    psVector *y0 = psVectorAlloc(0, PS_TYPE_S32); // Origin y coordinates
+    psVector *xBin = psVectorAlloc(0, PS_TYPE_S32); // Binning in x
+    psVector *yBin = psVectorAlloc(0, PS_TYPE_S32); // Binning in y
+    psVector *xFlip = psVectorAlloc(0, PS_TYPE_U8); // Flip in x?
+    psVector *yFlip = psVectorAlloc(0, PS_TYPE_U8); // Flip in y?
+
+    // Get the target characteristics
+    bool mdok = true;                   // Status of MD lookup
+    int x0Target = psMetadataLookupS32(&mdok, targetChip->concepts, "CHIP.X0");
+    if (!mdok) {
+        psWarning("CHIP.X0 is not set for the target chip; assuming 0.\n");
+        FIX_CONCEPT(targetChip->concepts, "CHIP.X0", S32, 0);
+    }
+    int y0Target = psMetadataLookupS32(&mdok, targetChip->concepts, "CHIP.Y0");
+    if (!mdok) {
+        psWarning("CHIP.Y0 is not set for the target chip; assuming 0.\n");
+        FIX_CONCEPT(targetChip->concepts, "CHIP.Y0", S32, 0);
+    }
+    x0Target += psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.X0");
+    if (!mdok) {
+        psWarning("CELL.X0 is not set for the target cell; assuming 0.\n");
+        FIX_CONCEPT(targetCell->concepts, "CELL.X0", S32, 0);
+    }
+    y0Target += psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.Y0");
+    if (!mdok) {
+        psWarning("CELL.Y0 is not set for the target cell; assuming 0.\n");
+        FIX_CONCEPT(targetCell->concepts, "CELL.Y0", S32, 0);
+    }
+    int xParityChipTarget = psMetadataLookupS32(&mdok, targetChip->concepts, "CHIP.XPARITY");
+    if (!mdok || (xParityChipTarget != -1 && xParityChipTarget != 1)) {
+        psWarning("CHIP.XPARITY is not set for the target chip; assuming 1.\n");
+        FIX_CONCEPT(targetChip->concepts, "CHIP.XPARITY", S32, 1);
+        xParityChipTarget = 1;
+    }
+    int yParityChipTarget = psMetadataLookupS32(&mdok, targetChip->concepts, "CHIP.YPARITY");
+    if (!mdok || (yParityChipTarget != -1 && yParityChipTarget != 1)) {
+        psWarning("CHIP.YPARITY is not set for the target chip; assuming 1.\n");
+        FIX_CONCEPT(targetChip->concepts, "CHIP.YPARITY", S32, 1);
+        yParityChipTarget = 1;
+    }
+    int xParityCellTarget = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.XPARITY");
+    if (!mdok || (xParityCellTarget != -1 && xParityCellTarget != 1)) {
+        psWarning("CELL.XPARITY is not set for the target cell; assuming 1.\n");
+        FIX_CONCEPT(targetCell->concepts, "CELL.XPARITY", S32, 1);
+        xParityCellTarget = 1;
+    }
+    int yParityCellTarget = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.YPARITY");
+    if (!mdok || (yParityCellTarget != -1 && yParityCellTarget != 1)) {
+        psWarning("CELL.YPARITY is not set for the target cell; assuming 1.\n");
+        FIX_CONCEPT(targetCell->concepts, "CELL.YPARITY", S32, 1);
+        yParityCellTarget = 1;
+    }
+    int xParityTarget = xParityChipTarget * xParityCellTarget;
+    int yParityTarget = yParityChipTarget * yParityCellTarget;
+
+    // Binning for the mosaicked chip is the minimum binning allowed by the cells
+    *xBinFPA = INT_MAX;
+    *yBinFPA = INT_MAX;
+
+    // Set up the required inputs
+    bool allGood = true;                // Is everything good, well-behaved?
+    psArray *chips = fpa->chips;        // Array of chips
+    for (int i = 0; i < chips->n; i++) {
+        pmChip *chip = chips->data[i];  // The chip of interest
+        if (!chip || !chip->data_exists) {
+            continue;
+        }
+        psArray *cells = chip->cells;   // The array of cells
+        for (int j = 0; j < cells->n; j++) {
+            pmCell *cell = cells->data[j];  // The cell of interest
+            if (!cell || !cell->data_exists) {
+                continue;
+            }
+            allGood |= addCell(images, masks, weights, x0, y0, xBin, yBin, xFlip, yFlip,
+                               cell, xBinFPA, yBinFPA, true, x0Target, y0Target,
+                               xParityTarget, yParityTarget);
+        }
+    }
+
+    // Check to see if the target has a smaller binning in mind
+    int xBinTarget = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.XBIN");
+    if (mdok && xBinTarget != 0) {
+        *xBinFPA = xBinTarget;
+    }
+    int yBinTarget = psMetadataLookupS32(&mdok, targetCell->concepts, "CELL.YBIN");
+    if (mdok && yBinTarget != 0) {
+        *yBinFPA = yBinTarget;
+    }
+
+    // Mosaic the images together and we're done
+    if (allGood) {
+        *mosaicImage = imageMosaic(images, xFlip, yFlip, xBin, yBin, *xBinFPA, *yBinFPA, x0, y0, BLANK_VALUE);
+        *mosaicWeights = imageMosaic(weights, xFlip, yFlip, xBin, yBin, *xBinFPA, *yBinFPA, x0, y0, BLANK_VALUE);
+        *mosaicMask = imageMosaic(masks, xFlip, yFlip, xBin, yBin, *xBinFPA, *yBinFPA, x0, y0, blank);
+    }
+
+    // Clean up
+    psFree(images);
+    psFree(weights);
+    psFree(masks);
+    psFree(xFlip);
+    psFree(yFlip);
+    psFree(xBin);
+    psFree(yBin);
+    psFree(x0);
+    psFree(y0);
+
+    return allGood;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Mosaic all the cells in a chip together.
+//
+// It is desirable to do this without using psImageOverlay (or similar) if it can be at all avoided (because
+// it's really really slow in that case).  There are therefore two cases:
+//
+// 1. The HDU is at the Chip or FPA level.  This is the fast case, and only works if the HDU is "nice", by
+// which I mean:
+//
+//    - the CELL.TRIMSECs are contiguous on the HDU image
+//    - the CELL.PARITYs are identically +1
+//    - the CELL.XBIN and CELL.YBIN are all identical
+//
+// Then we can just use psImageSubset to get the "mosaicked" chip.
+//
+//
+// 2. The HDU is at the cell level, or the above requirements are not met, in which case we mosaic the cells.
+// This is the slow case.  We need to:
+//
+//    - Throw away the bias regions
+//    - Convert all cells to common parity
+//    - Mosaic the cells into an HDU image using CELL.X0 and CELL.Y0
+//    - Update CELL.TRIMSECs
+//
+// Once the demands of case 1 have been met, or case 2 has been performed, then we can create a cell to hold
+// the mosaic image.
+
+bool pmChipMosaic(pmChip *target, const pmChip *source, bool deepCopy, psMaskType blank)
+{
+    // Target exists, and has only a single cell
+    PS_ASSERT_PTR_NON_NULL(target, false);
+    PS_ASSERT_PTR_NON_NULL(target->cells, false);
+    if (target->cells->n != 1) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Target chip for mosaicking must contain a single cell.\n");
+        return false;
+    }
+    pmCell *targetCell = target->cells->data[0]; // The target cell
+    PS_ASSERT_PTR_NON_NULL(targetCell, false);
+    // Source exists
+    PS_ASSERT_PTR_NON_NULL(source, false);
+
+
+    psImage *mosaicImage   = NULL;      // The mosaic image
+    psImage *mosaicMask    = NULL;      // The mosaic mask
+    psImage *mosaicWeights = NULL;      // The mosaic weights
+
+    // Find the HDU
+    psRegion *chipRegion = NULL;        // Region on the HDU that corresponds to the chip
+    int xBin = 0, yBin = 0;             // Binning for the chip mosaic
+    if (!deepCopy && (chipRegion = niceChip(&xBin, &yBin, source))) {
+        // Case 1 --- we need only cut out the region
+        psTrace("psModules.camera", 1, "Case 1 mosaicking: simple cut-out.\n");
+        pmHDU *hdu = source->hdu;       // The HDU that has the pixels
+        if (!hdu || !hdu->images) {
+            hdu = source->parent->hdu;
+        }
+        // force limits to land on chip
+        psRegion bounds = psRegionForImage (hdu->images->data[0], *chipRegion);
+        mosaicImage = psImageSubset(hdu->images->data[0], bounds);
+        if (!mosaicImage) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to select image pixels.\n");
+            return false;
+        }
+        if (hdu->masks) {
+            mosaicMask = psImageSubset(hdu->masks->data[0], bounds);
+            if (!mosaicMask) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to select mask pixels.\n");
+                return false;
+            }
+        }
+        if (hdu->weights) {
+            mosaicWeights = psImageSubset(hdu->weights->data[0], bounds);
+            if (!mosaicWeights) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to select weight pixels.\n");
+                return false;
+            }
+        }
+    } else {
+        // Case 2 --- we need to mosaic by cut and paste
+        psTrace("psModules.camera", 1, "Case 2 mosaicking: cut and paste.\n");
+        if (!chipMosaic(&mosaicImage, &mosaicMask, &mosaicWeights, &xBin, &yBin, source, targetCell, blank)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to mosaic cells.\n");
+            return false;
+        }
+        chipRegion = psRegionAlloc(0, 0, 0, 0); // We've cut and paste, so there's no valid trimsec
+        *chipRegion = psRegionForImage (mosaicImage, *chipRegion);
+    }
+    psTrace("psModules.camera", 1, "xBin,yBin: %d,%d\n", xBin, yBin);
+
+    // Set the concepts for the target cell
+    psList *sourceCells = psArrayToList(source->cells); // List of cells
+    pmConceptsAverageCells(targetCell, sourceCells, chipRegion, NULL, false);
+    {
+        psMetadataItem *item = psMetadataLookup(targetCell->concepts, "CELL.X0");
+        item->data.S32 = 0;
+        item = psMetadataLookup(targetCell->concepts, "CELL.Y0");
+        item->data.S32 = 0;
+        item = psMetadataLookup(targetCell->concepts, "CELL.XBIN");
+        item->data.S32 = xBin;
+        item = psMetadataLookup(targetCell->concepts, "CELL.YBIN");
+        item->data.S32 = yBin;
+    }
+    psFree(sourceCells);
+    psFree(chipRegion);
+
+    // Copy the concepts
+    target->concepts = psMetadataCopy(target->concepts, source->concepts); // Chip level
+    target->parent->concepts = psMetadataCopy(target->parent->concepts, source->parent->concepts); // FPA lvl
+
+    // Now make a new readout to go in the target cell
+    pmReadout *newReadout = pmReadoutAlloc(targetCell); // New readout
+    newReadout->image  = mosaicImage;
+    newReadout->mask   = mosaicMask;
+    newReadout->weight = mosaicWeights;
+    psFree(newReadout);                 // Drop reference
+
+    // Data now exists in the targets
+    pmChipSetDataStatus(target, true);
+    pmCellSetDataStatus(targetCell, true);
+    newReadout->data_exists = true;
+
+    // Update the headers
+    pmHDU *sourceHDU = pmHDUFromChip(source); // The HDU for the source
+    pmHDU *targetHDU = pmHDUFromChip(target); // The HDU for the target
+    targetHDU->header = psMetadataCopy(targetHDU->header, sourceHDU->header);
+    pmHDU *targetPHU = pmHDUGetHighest(target->parent, target, NULL);
+    pmHDU *sourcePHU = pmHDUGetHighest(source->parent, source, NULL);
+
+    // Need to update NAXIS1, NAXIS2 in the target header, so that when we write a CMF, it has the correct
+    // extent.  I'm not convinced that this is the best way to do this, but it should be, at worst, harmless,
+    // since NAXIS[12] will get overwritten for an image with the proper dimensions.
+    psRegion *naxis = pmChipExtent(target);
+    psMetadataAddS32(targetHDU->header, PS_LIST_TAIL, "NAXIS1", PS_META_REPLACE, "Size in x",
+                     naxis->x1 - naxis->x0);
+    psMetadataAddS32(targetHDU->header, PS_LIST_TAIL, "NAXIS2", PS_META_REPLACE, "Size in y",
+                     naxis->y1 - naxis->y0);
+    psFree(naxis);
+
+
+    if (!targetPHU) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find HDU after mosaicking.\n");
+        return false;
+    }
+    if (!targetPHU->header) {
+        // if we don't yet have a header, copy this one.
+        // XXX do we need to create an empty one if the levels do not match??
+        if (true) {
+            targetPHU->header = psMetadataCopy(targetPHU->header, sourcePHU->header);
+        } else {
+            targetPHU->header = psMetadataAlloc();
+        }
+    }
+
+    if (!pmConfigConformHeader(targetPHU->header, targetPHU->format)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to conform header after mosaicking.\n");
+        return false;
+    }
+
+    // If the cells contain the headers, we need to apply the WCS terms from (one of?) the cells
+    int xParityCellTarget = psMetadataLookupS32(NULL, targetCell->concepts, "CELL.XPARITY");
+    if (xParityCellTarget != -1 && xParityCellTarget != 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "CELL.XPARITY is not set for target.");
+        return false;
+    }
+    int xParityChipTarget = psMetadataLookupS32(NULL, target->concepts, "CHIP.XPARITY");
+    if (xParityChipTarget != -1 && xParityChipTarget != 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "CHIP.XPARITY is not set for target.");
+        return false;
+    }
+    int xParityTarget = xParityCellTarget * xParityChipTarget; // Target parity in x
+
+    int yParityCellTarget = psMetadataLookupS32(NULL, targetCell->concepts, "CELL.YPARITY");
+    if (yParityCellTarget != -1 && yParityCellTarget != 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "CELL.YPARITY is not set for target.");
+        return false;
+    }
+    int yParityChipTarget = psMetadataLookupS32(NULL, target->concepts, "CHIP.YPARITY");
+    if (yParityChipTarget != -1 && yParityChipTarget != 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "CHIP.YPARITY is not set for target.");
+        return false;
+    }
+    int yParityTarget = yParityCellTarget * yParityChipTarget; // Target parity in y
+
+    for (int i = 0; i < source->cells->n; i++) {
+        pmCell *cell = source->cells->data[i];
+        if (!cell || !cell->hdu || !cell->hdu->header) {
+            continue;
+        }
+
+        pmAstromWCS *wcs = pmAstromWCSfromHeader(cell->hdu->header); // WCS terms for this cell
+        if (!wcs) {
+            psTrace("psModules.camera", 1, "Unable to read cell WCS to generate chip WCS --- ignored.");
+            continue;
+        }
+
+        int xBinCell = psMetadataLookupS32(NULL, cell->concepts, "CELL.XBIN"); // Cell binning in x
+        if (xBinCell == 0) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "CELL.XBIN is not set.");
+            return false;
+        }
+        int xParitySource = psMetadataLookupS32(NULL, cell->concepts, "CELL.XPARITY") *
+            psMetadataLookupS32(NULL, source->concepts, "CHIP.XPARITY"); // Source parity in x
+        if (xParitySource != -1 && xParitySource != 1) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "CHIP.XPARITY or CELL.XPARITY is not set for source.");
+            return false;
+        }
+        bool xFlip = (xParitySource == xParityTarget ? false : true); // Flip the x sense of the WCS?
+        int x0Cell = psMetadataLookupS32(NULL, cell->concepts, "CELL.X0"); // Cell offset in x
+
+        // Modify the wcs terms for the cell offset, binning, and parity
+        float xBinRatio = (float)xBinCell / (float)xBin;
+        if (xFlip) {
+            wcs->crpix1 = x0Cell - wcs->crpix1 * xBinRatio;
+            wcs->cdelt1 *= -1;
+        } else {
+            wcs->crpix1 = x0Cell + wcs->crpix1 * xBinRatio;
+        }
+        wcs->cdelt1 *= xBinRatio;
+
+        int yBinCell = psMetadataLookupS32(NULL, cell->concepts, "CELL.YBIN"); // Cell binning in y
+        if (yBinCell == 0) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "CELL.YBIN is not set.");
+            return false;
+        }
+        int yParitySource = psMetadataLookupS32(NULL, cell->concepts, "CELL.YPARITY") *
+            psMetadataLookupS32(NULL, cell->parent->concepts, "CHIP.YPARITY"); // Source parity in y
+        if (yParitySource != -1 && yParitySource != 1) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "CHIP.YPARITY or CELL.YPARITY is not set for source.");
+            return false;
+        }
+        bool yFlip = (yParitySource == yParityTarget ? false : true); // Flip the y sense of the WCS?
+        int y0Cell = psMetadataLookupS32(NULL, cell->concepts, "CELL.Y0"); // Cell offset in y
+
+        float yBinRatio = (float)yBinCell / (float)yBin;
+        if (yFlip) {
+            wcs->crpix2 = y0Cell - wcs->crpix2 * yBinRatio;
+            wcs->cdelt2 *= -1;
+        } else {
+            wcs->crpix2 = y0Cell + wcs->crpix2 * yBinRatio;
+        }
+        wcs->cdelt2 *= yBinRatio;
+
+        if (!pmAstromWCStoHeader(targetHDU->header, wcs)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to generate chip WCS from cell WCS.");
+            psFree(wcs);
+            return false;
+        }
+        psFree(wcs);
+
+        // XXX rather than quitting at this point, we could save this wcs structure and compare
+        // its values to the equivalent version from one of the other cells.
+        break;
+    }
+
+    return true;
+}
+
+
+bool pmFPAMosaic(pmFPA *target, const pmFPA *source, bool deepCopy, psMaskType blank)
+{
+    // Target exists, and has only a single chip with single cell
+    PS_ASSERT_PTR_NON_NULL(target, false);
+    PS_ASSERT_PTR_NON_NULL(target->chips, false);
+    if (target->chips->n != 1) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Target FPA for mosaicking must contain a single chip.\n");
+        return false;
+    }
+    pmChip *targetChip = target->chips->data[0]; // The target chip
+    PS_ASSERT_PTR_NON_NULL(targetChip, false);
+    PS_ASSERT_PTR_NON_NULL(targetChip->cells, false);
+    if (target->chips->n != 1) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Target FPA for mosaicking must contain a single cell.\n");
+        return false;
+    }
+    pmCell *targetCell = targetChip->cells->data[0]; // The target cell
+    PS_ASSERT_PTR_NON_NULL(targetCell, false);
+    // Source exists
+    PS_ASSERT_PTR_NON_NULL(source, false);
+
+    psImage *mosaicImage   = NULL;      // The mosaic image
+    psImage *mosaicMask    = NULL;      // The mosaic mask
+    psImage *mosaicWeights = NULL;      // The mosaic weights
+
+    // Find the HDU
+    psRegion *fpaRegion = NULL;         // Region on the HDU that corresponds to the FPA
+    int xBin = 0, yBin = 0;             // Binning for the FPA mosaic
+    if (!deepCopy && (fpaRegion = niceFPA(&xBin, &yBin, source))) {
+        // Case 1 --- we need only cut out the region
+        psTrace("psModules.camera", 1, "Case 1 mosaicking: simple cut-out.\n");
+        pmHDU *hdu = source->hdu;         // The HDU that has the pixels
+        mosaicImage = psImageSubset(hdu->images->data[0], *fpaRegion);
+        if (hdu->masks) {
+            mosaicMask = psImageSubset(hdu->masks->data[0], *fpaRegion);
+        }
+        if (hdu->weights) {
+            mosaicWeights = psImageSubset(hdu->weights->data[0], *fpaRegion);
+        }
+    } else {
+        // Case 2 --- we need to mosaic by cut and paste
+        psTrace("psModules.camera", 1, "Case 2 mosaicking: cut and paste.\n");
+        if (!fpaMosaic(&mosaicImage, &mosaicMask, &mosaicWeights, &xBin, &yBin, source,
+                       targetChip, targetCell, blank)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to mosaic chips.\n");
+            return false;
+        }
+        fpaRegion = psRegionAlloc(NAN, NAN, NAN, NAN); // We've cut and paste, so there's no valid trimsec
+    }
+
+    // Set the concepts for the target cell, and add the mosaic in
+    // First we need a list of cells
+    psList *sourceCells = psListAlloc(NULL); // List of source cells
+    psArray *chips = source->chips;        // Array of chips
+    pmChip *firstSourceChip = NULL;     // The first chip in the source FPA; for headers
+    pmCell *firstSourceCell = NULL;     // The first cell in the source FPA; for headers
+    for (long i = 0; i < chips->n; i++) {
+        pmChip *chip = chips->data[i];  // Chip of interest
+        if (!chip || !chip->data_exists) {
+            continue;
+        }
+        psArray *cells = chip->cells;
+        for (long j = 0; j < cells->n; j++) {
+            pmCell *cell = cells->data[j]; // Cell of interest
+            if (!cell || !cell->data_exists) {
+                continue;
+            }
+            psListAdd(sourceCells, PS_LIST_TAIL, cell);
+
+            // These are valid chip and cell to use for the header; grab the first such
+            if (!firstSourceCell && !firstSourceChip) {
+                firstSourceCell = cell;
+                firstSourceChip = chip;
+            }
+        }
+    }
+    pmConceptsAverageCells(targetCell, sourceCells, fpaRegion, NULL, false);
+    {
+        psMetadataItem *item = psMetadataLookup(targetCell->concepts, "CELL.X0");
+        item->data.S32 = 0;
+        item = psMetadataLookup(targetCell->concepts, "CELL.Y0");
+        item->data.S32 = 0;
+        item = psMetadataLookup(targetCell->concepts, "CELL.XBIN");
+        item->data.S32 = xBin;
+        item = psMetadataLookup(targetCell->concepts, "CELL.YBIN");
+        item->data.S32 = yBin;
+    }
+    psFree(sourceCells);
+    psFree(fpaRegion);
+
+    // Currently, there's nothing interesting in the chip concepts that needs to be updated.
+
+    // Copy the concepts for the target FPA
+    target->concepts = psMetadataCopy(target->concepts, source->concepts);
+
+    // Now make a new readout to go in the new cell
+    pmReadout *newReadout = pmReadoutAlloc(targetCell); // New readout
+    newReadout->image  = mosaicImage;
+    newReadout->mask   = mosaicMask;
+    newReadout->weight = mosaicWeights;
+    psFree(newReadout);                 // Drop reference
+
+    // Data now exists in the targets
+    pmChipSetDataStatus(targetChip, true);
+    pmCellSetDataStatus(targetCell, true);
+    newReadout->data_exists = true;
+
+    // Update the headers
+    pmHDU *sourceHDU = pmHDUGetHighest(source, firstSourceChip, firstSourceCell); // The HDU for the source
+    if (!sourceHDU) {
+        psWarning("Unable to find HDU in source FPA; unable to copy headers.\n");
+        return false;
+    }
+    pmHDU *targetHDU = pmHDUGetHighest(target, targetChip, targetCell); // The HDU for the target
+    if (!targetHDU) {
+        psWarning("Unable to find HDU in target FPA; unable to copy headers.\n");
+        return false;
+    }
+
+    if (sourceHDU->header) {
+        targetHDU->header = psMetadataCopy(targetHDU->header, sourceHDU->header);
+    } else if (!targetHDU->header) {
+        targetHDU->header = psMetadataAlloc();
+    }
+
+    if (!pmConfigConformHeader(targetHDU->header, targetHDU->format)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to conform header after mosaicking.\n");
+        return false;
+    }
+
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAMosaic.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAMosaic.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAMosaic.h	(revision 22158)
@@ -0,0 +1,41 @@
+/* @file pmFPAMosaic.h
+ * @brief Functions to mosaic FPA components into a single entity
+ *
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-06-20 02:22:26 $
+ * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_CHIP_MOSAIC_H
+#define PM_CHIP_MOSAIC_H
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+/// Mosaic all cells within a chip
+///
+/// Mosaics all cells within the source into a single cell within the target (which must have only a single
+/// cell).  Cells are placed on the chip according to the CELL.X0 and CELL.Y0 offsets.  This is useful for
+/// getting an image of the chip on the sky.  The mosaicking is done so as to avoid performing a deep copy of
+/// the pixels, if possible.
+bool pmChipMosaic(pmChip *target,       ///< Target chip --- may contain only a single cell
+                  const pmChip *source, ///< Source chip whose cells will be mosaicked
+                  bool deepCopy,        ///< Require a deep copy (disregard 'nice' chip)
+                  psMaskType blank      ///< Mask value to give blank pixels
+    );
+
+/// Mosaic all cells within an FPA
+///
+/// Mosaics all cells within the source into a single chip with single cell within the target (which must have
+/// only a single chip with single cell).  Cells are placed on the FPA according to the CHIP.X0, CHIP.Y0,
+/// CELL.X0 and CELL.Y0 offsets.  This is useful for getting an image of the FPA on the sky.  The mosaicking
+/// is done so as to avoid performing a deep copy of the pixels, if possible.
+bool pmFPAMosaic(pmFPA *target, ///< Target FPA --- may contain only a single chip with a single cell
+                 const pmFPA *source,   ///< FPA whose chips and cells will be mosaicked
+                 bool deepCopy,         ///< Require a deep copy (disregard 'nice' chip)
+                 psMaskType blank       ///< Mask value to give blank pixels
+                );
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPARead.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPARead.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPARead.c	(revision 22158)
@@ -0,0 +1,1231 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <strings.h>
+#include <assert.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAFlags.h"
+#include "pmHDUUtils.h"
+#include "pmConcepts.h"
+#include "pmFPAHeader.h"
+
+#include "pmFPARead.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Definitions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Specify what to read
+typedef enum {
+    FPA_READ_TYPE_IMAGE,                // Read image
+    FPA_READ_TYPE_MASK,                 // Read mask
+    FPA_READ_TYPE_WEIGHT,               // Read weight map
+    FPA_READ_TYPE_HEADER                // Read header
+} fpaReadType;
+
+// Desired type for pixels; the index corresponds to the fpaReadType, above.
+static psElemType pixelTypes[] = {
+    PS_TYPE_F32,
+    PS_TYPE_MASK,
+    PS_TYPE_F32,
+    0
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// File-static functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Return pointer to appropriate value for tracking scans
+static int readoutGetThisScan(pmReadout *readout, // Readout of interest
+			      fpaReadType type // Type of image
+    )
+{
+    switch (type) {
+      case FPA_READ_TYPE_IMAGE:
+        return readout->thisImageScan;
+      case FPA_READ_TYPE_MASK:
+        return readout->thisMaskScan;
+      case FPA_READ_TYPE_WEIGHT:
+        return readout->thisWeightScan;
+      default:
+        psAbort("Unknown read type: %x\n", type);
+    }
+}
+
+// Return pointer to appropriate value for tracking scans
+static int readoutSetLastScan(pmReadout *readout, // Readout of interest
+			      fpaReadType type,	  // Type of image
+			      int numScans	  // requested number of scans
+    )
+{
+    switch (type) {
+      case FPA_READ_TYPE_IMAGE:
+        readout->lastImageScan = readout->thisImageScan + numScans;
+	return readout->lastImageScan;
+      case FPA_READ_TYPE_MASK:
+        readout->lastMaskScan = readout->thisMaskScan + numScans;
+	return readout->lastMaskScan;
+      case FPA_READ_TYPE_WEIGHT:
+        readout->lastWeightScan = readout->thisWeightScan + numScans;
+	return readout->lastWeightScan;
+      default:
+        psAbort("Unknown read type: %x\n", type);
+    }
+    return false;
+}
+
+// Return pointer to appropriate image
+static psImage **readoutImageByType(pmReadout *readout, // Readout of interest
+                                    fpaReadType type // Type of image
+    )
+{
+    switch (type) {
+      case FPA_READ_TYPE_IMAGE:
+        return &readout->image;
+      case FPA_READ_TYPE_MASK:
+        return &readout->mask;
+      case FPA_READ_TYPE_WEIGHT:
+        return &readout->weight;
+      default:
+        psAbort("Unknown read type: %x\n", type);
+    }
+}
+
+// Determine number of readouts in the FITS file
+// In the process, reads the header and concepts
+static bool cellNumReadouts(pmCell *cell,    // Cell of interest
+                            psFits *fits,    // FITS file
+                            pmConfig *config // Configuration
+    )
+{
+    assert(cell);
+    assert(fits);
+
+    // Get the HDU and read the header
+    pmHDU *hdu = pmHDUFromCell(cell);   // The HDU
+    if (!hdu || hdu->blankPHU) {
+        psError(PS_ERR_IO, true, "Unable to find HDU");
+        return false;
+    }
+    if (!pmCellReadHeader(cell, fits, config)) {
+        psError(PS_ERR_IO, false, "Unable to read header for cell!\n");
+        return false;
+    }
+    if (!pmConceptsReadCell(cell, PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_CELLS, true, NULL)) {
+        psError(PS_ERR_IO, false, "Failed to read concepts for cell.\n");
+        return false;
+    }
+
+    // Get the size of the third dimension
+    bool mdok;                          // Status of MD lookup
+    int naxis = psMetadataLookupS32(&mdok, hdu->header, "NAXIS"); // The number of axes
+    if (!mdok) {
+        psError(PS_ERR_IO, true, "Unable to find NAXIS in header for extension %s\n", hdu->extname);
+        return false;
+    }
+    if (naxis == 0) {
+        // No pixels to read
+        psError(PS_ERR_IO, true, "No pixels in extension %s.", hdu->extname);
+        return false;
+    }
+    if (naxis < 2 || naxis > 3) {
+        psError(PS_ERR_IO, true, "NAXIS in header of extension %s (= %d) is not valid.\n",
+                hdu->extname, naxis);
+        return false;
+    }
+    int naxis3;                     // Number of image planes
+    if (naxis == 3) {
+        naxis3 = psMetadataLookupS32(&mdok, hdu->header, "NAXIS3");
+        if (!mdok) {
+            psError(PS_ERR_IO, true, "Unable to find NAXIS3 in header for extension %s\n", hdu->extname);
+            return false;
+        }
+    } else {
+        naxis3 = 1;
+    }
+
+    return naxis3;
+}
+
+// Does the current readout, with scans set for a new read, represent any real data, or is it
+// beyond the end?  Requires that cellNumReadouts() has been called before (for header and
+// concepts to have been read) In the process, adjusts the TRIMSEC
+static bool readoutHaveMoreScans(bool *result,	 // true : more data to read 
+			     pmReadout *readout, // Readout of interest
+			     int numScans, // Number of scans to read at a time
+			     fpaReadType type, // Type of image
+			     pmConfig *config // Configuration
+    )
+{
+    assert(result);
+    assert(readout);
+
+    *result = false;
+
+    if (!pmConceptsReadCell(readout->parent, PM_CONCEPT_SOURCE_DEFAULTS | PM_CONCEPT_SOURCE_DATABASE,
+                            true, config)) {
+        psError(PS_ERR_IO, false, "Failed to read concepts for cell.");
+        return false;
+    }
+    // Header and concepts have been read by a call to cellNumReadouts(), so we can just assume they're there.
+
+    // Get the trim and bias sections
+    pmCell *cell = readout->parent;     // Parent cell
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    pmHDU *hdu = pmHDUFromCell(cell);   // HDU for data
+
+    bool mdok = true;                   // Status of MD lookup
+    psRegion *trimsec = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.TRIMSEC"); // Trim sections
+    if (!mdok || !trimsec || psRegionIsNaN(*trimsec)) {
+        psError(PS_ERR_IO, true, "CELL.TRIMSEC is not set.\n");
+        return false;
+    }
+    int readdir = psMetadataLookupS32(&mdok, cell->concepts, "CELL.READDIR"); // Read direction
+    if (!mdok || readdir == 0 || (readdir != 1 && readdir != 2)) {
+        psError(PS_ERR_IO, true, "CELL.READDIR is not set to -1 or +1.\n");
+        return false;
+    }
+
+    // Rationalize trimsec against naxis1, naxis2:  valid range for trimsec is 1-Nx,1-Ny
+    if (trimsec->x1 < 1) {
+        int naxis1 = psMetadataLookupS32(&mdok, hdu->header, "NAXIS1"); // The number of columns
+        if (!mdok) {
+            psError(PS_ERR_IO, true, "Unable to find NAXIS1 in header for extension %s\n", hdu->extname);
+            return false;
+        }
+        trimsec->x1 = naxis1 + trimsec->x1;
+    }
+    if (trimsec->y1 < 1) {
+        int naxis2 = psMetadataLookupS32(&mdok, hdu->header, "NAXIS2"); // The number of columns
+        if (!mdok) {
+            psError(PS_ERR_IO, true, "Unable to find NAXIS2 in header for extension %s\n", hdu->extname);
+            return false;
+        }
+        trimsec->y1 = naxis2 + trimsec->y1;
+    }
+
+    // Calculate the segment offset and upper limit
+    if (numScans == 0) {
+	// in the case of numScans == 0, we never call this funtion unless the data has not yet 
+	// been read.  thus, only if the delta is  should we return false (ie, trimsec defines an empty region)
+        int thisScan = (readdir == 1) ? trimsec->y0 : trimsec->x0;
+	int lastScan = (readdir == 1) ? trimsec->y1 : trimsec->x1;
+	*result = (lastScan > thisScan);
+	return true;
+    } 
+
+    // allow multiple threads to read different segments into different readouts
+    // this thread may not have read a segment yet; but others have.  trust readout->imageScan
+
+    // is the start scan of the read less than the last possible scan?
+    int thisScan = readoutGetThisScan(readout, type);
+    int lastScan = (readdir == 1) ? trimsec->y1 : trimsec->x1;
+
+    *result = (lastScan > thisScan);
+    return true;
+    // XXX fold this and the above case together
+}
+
+static bool readoutMore(pmReadout *readout, // Readout of interest
+                        psFits *fits,    // FITS file
+                        int z,          // Plane number
+                        int numScans,   // Number of scans to read at a time
+                        fpaReadType type, // Type of image
+                        pmConfig *config// Configuration
+    )
+{
+    assert(readout);
+    assert(fits);
+
+    psImage *image = *readoutImageByType(readout, type);
+
+    // XXX this may not be the valid test in a multithread environment. consider a fileGroup of
+    // N readouts, but numScans set to 0.  only the first should report that it requires data, 
+    // even if all readouts lack the image pointer.
+    if (!image) {
+        return true;
+    } 
+
+    // If we have already read an image, this result implies we are done (no more to read)
+    if (numScans == 0) {
+        return false;
+    }
+
+    pmCell *cell = readout->parent;     // Parent cell
+    if (!cell) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find parent cell.");
+        return false;
+    }
+    int naxis3 = cellNumReadouts(cell, fits, config); // Number of planes
+    if (z >= naxis3) {
+        // No more to read
+        return false;
+    }
+
+    bool haveData;
+    if (!readoutHaveMoreScans(&haveData, readout, numScans, type, config)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to determine readout properties.");
+        return false;
+    }
+
+    return haveData;
+}
+
+// Carve a readout from the image pixels
+static bool readoutCarve(pmReadout *readout, // Readout to be carved up
+                         psImage *image, // Image that will be carved
+                         const psRegion *trimsec, // Trim section
+                         const psList *biassecs, // Bias sections
+                         fpaReadType type // Type of image
+                        )
+{
+    assert(readout);
+    assert(image);
+    assert(trimsec);
+    assert(biassecs);
+
+    // The image corresponding to the trim region
+    if (psRegionIsNaN(*trimsec)) {
+        psString regionString = psRegionToString(*trimsec);
+        psError(PS_ERR_UNKNOWN, true, "Invalid trim section: %s\n", regionString);
+        psFree(regionString);
+        psFree(readout);
+        return false;
+    }
+    psRegion region = psRegionSet(PS_MAX(trimsec->x0 - readout->col0, 0), // x0
+                                  PS_MIN(trimsec->x1 - readout->col0, image->numCols), // x1
+                                  PS_MAX(trimsec->y0 - readout->row0, 0), // y0
+                                  PS_MIN(trimsec->y1 - readout->row0, image->numRows) // y1
+                                 );
+
+    // Place the image subset in the appropriate target location, freeing if needed
+    psImage **target = readoutImageByType(readout, type); // Target image
+    if (*target) {
+        psFree(*target);
+    }
+    *target = psImageSubset(image, region);
+
+    // Get the list of overscans: only for IMAGE types (no overscan for MASK and WEIGHT)
+    if (type == FPA_READ_TYPE_IMAGE) {
+        if (readout->bias->n != 0) {
+            // Make way!
+            psFree(readout->bias);
+            readout->bias = psListAlloc(NULL);
+        }
+        psListIterator *iter = psListIteratorAlloc((psList*)biassecs, PS_LIST_HEAD, false); // Iterator
+        psRegion *biassec = NULL;       // A BIASSEC region from the list
+        while ((biassec = psListGetAndIncrement(iter))) {
+            if (psRegionIsNaN(*biassec)) {
+                psString regionString = psRegionToString(*biassec);
+                psError(PS_ERR_IO, true, "Invalid bias section: %s\n", regionString);
+                psFree(regionString);
+                psFree(readout);
+                return false;
+            }
+            psRegion region = psRegionSet(PS_MAX(biassec->x0 - readout->col0, 0), // x0
+                                          PS_MIN(biassec->x1 - readout->col0, image->numCols), // x1
+                                          PS_MAX(biassec->y0 - readout->row0, 0), // y0
+                                          PS_MIN(biassec->y1 - readout->row0, image->numRows) // y1
+                );
+            psImage *overscan = psImageSubset(image, region);
+            psListAdd(readout->bias, PS_LIST_TAIL, overscan);
+            psFree(overscan);
+        }
+        psFree(iter);
+    }
+
+    return true;
+}
+
+// Read a component of a readout.  We read in only the rows from min to max for plane z, for
+// the full region requested.  if we request a range outside the region, we will pad to fill
+// out the edges of the region with 'bad' pixels.  The output image always has max-min rows.
+// The region represents the maximum bounds of the full image
+static psImage *readoutReadComponent(psImage *image, // Image into which to read
+                                     psFits *fits, // FITS file from which to read
+                                     const psRegion *fullImage, // full image region, read a subset
+                                     int readdir, // Read direction (1=rows, 2=cols)
+                                     int min,  // Minimum row/col number to read
+                                     int max,   // Maximum row/col number to read
+                                     int z,     // Image plane to read
+                                     float bad, // Bad value
+                                     psElemType type // Expected type for image
+    )
+{
+    assert(fits);
+    assert(fullImage);
+    assert((readdir == 1) || (readdir == 2));
+
+    int nRead = 0;                      // Number of scans read
+    int nScans = max - min;             // Number of scans desired
+    assert(nScans > 0);
+
+    psRegion toRead = *fullImage;  // full image region
+
+    int dX = 0, dY = 0;                 // Offset from image in FITS file to lower left corner of what's read
+    int nX = 0, nY = 0;                 // Size of region to read
+
+    if (readdir == 1) {
+        toRead.y0 = PS_MAX(toRead.y0, min);
+        toRead.y1 = PS_MIN(toRead.y1, max);
+        nRead = toRead.y1 - toRead.y0;
+        if (min < fullImage->y0) {
+            dY = toRead.y0;
+        }
+        nX = toRead.x1 - toRead.x0;
+        nY = nScans;
+    } else {
+        toRead.x0 = PS_MAX(toRead.x0, min);
+        toRead.x1 = PS_MIN(toRead.x1, max);
+        nRead = toRead.x1 - toRead.x0;
+        if (min < fullImage->x0) {
+            dX = toRead.x0;
+        }
+        nX = nScans;
+        nY = toRead.y1 - toRead.y0;
+    }
+
+    psTrace("psModules.camera", 5, "Reading section [%.0f:%.0f,%.0f:%.0f]\n",
+            toRead.x0, toRead.x1, toRead.y0, toRead.y1);
+    image = psFitsReadImageBuffer(image, fits, toRead, z); // Desired pixels
+    psTrace("psModules.camera", 7, "Image is %dx%d\n", image->numCols, image->numRows);
+
+    // Ensure the pixel type corresponds to what we desire
+    if (image->type.type != type) {
+        psImage *temp = psImageCopy(NULL, image, type);
+        psFree(image);
+        image = temp;
+    }
+
+    // Resize the image so that it matches the number of scans requested
+    // XXX this modification is not carried back up stream: it affects readout->row0,col0
+    //
+    // XXXXX Do we really want to do this???  Why???
+    if (nRead < nScans) {
+        // The region of interest is smaller than the number of pixels we want.
+        psTrace("psModules.camera", 5, "Resizing image to %d,%d\n", nX, nY);
+        psImage *temp = psImageAlloc(nX, nY, image->type.type);
+        psImageInit(temp, bad);
+        psImageOverlaySection(temp, image, dX, dY, "=");
+        psFree(image);
+        image = temp;
+    }
+
+    return image;
+}
+
+// Read a chunk of a readout (or the whole lot)
+static bool readoutReadChunk(pmReadout *readout, // Readout into which to read
+                             psFits *fits, // FITS file
+                             int z,     // Desired image plane
+                             int numScans, // Number of scans (row or col depends on CELL.READDIR); 0 for all
+                             int overlap, // Number of scans (row/col) to overlap between scans
+                             fpaReadType type, // Type of image
+                             pmConfig *config   // Configuration
+    )
+{
+    assert(readout);
+    assert(fits);
+    assert(z >= 0);
+    assert(numScans >= 0);
+    assert(overlap >= 0);
+
+    psImage **image = readoutImageByType(readout, type); // Pointer to the image of interest
+    if (*image && numScans == 0) {
+        psError(PS_ERR_UNKNOWN, true, "Already read entire image --- won't clobber.");
+        return false;
+    }
+
+    pmCell *cell = readout->parent;     // The parent cell
+    if (!cell) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find parent cell.");
+        return false;
+    }
+
+    int naxis3 = cellNumReadouts(cell, fits, config); // Number of image planes
+    if (z >= naxis3) {
+        psError(PS_ERR_IO, false, "Desired image plane (%d) exceeds available number (%d).",
+                z, naxis3);
+        return false;
+    }
+
+    bool haveData;
+    if (!readoutHaveMoreScans (&haveData, readout, type, numScans, config)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to determine readout properties.");
+        return false;
+    }
+    if (!haveData) {
+        psError(PS_ERR_IO, true, "No more of the readout to read.");
+        return false;
+    }
+
+
+    pmHDU *hdu = pmHDUFromCell(cell);   // The HDU
+    assert(hdu && !hdu->blankPHU);      // Checked by cellNumReadouts()
+
+    bool mdok;                          // Status of MD lookup
+    int readdir = psMetadataLookupS32(&mdok, cell->concepts, "CELL.READDIR"); // Read direction
+    if (!mdok || readdir == 0 || (readdir != 1 && readdir != 2)) {
+        psError(PS_ERR_IO, true, "CELL.READDIR is not set to -1 or +1.\n");
+        return false;
+    }
+
+    // XXX for IMAGE, we need the CELL.BAD value, but for MASK, we need the BAD mask value
+
+    float bad = 0;
+    if (type == FPA_READ_TYPE_MASK) {
+      bad = 1.0;
+    } else {
+      bad = psMetadataLookupF32(&mdok, cell->concepts, "CELL.BAD"); // Bad level
+    }
+
+    psRegion *trimsec = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.TRIMSEC"); // Trim sections
+    if (!mdok || !trimsec || psRegionIsNaN(*trimsec)) {
+        psError(PS_ERR_IO, true, "CELL.TRIMSEC is not set.\n");
+        return false;
+    }
+
+    // Check the third dimension
+    int naxis = psMetadataLookupS32(&mdok, hdu->header, "NAXIS"); // The number of axes
+    if (!mdok) {
+        psError(PS_ERR_IO, true, "Unable to find NAXIS in header for extension %s\n", hdu->extname);
+        return false;
+    }
+    if (naxis == 0) {
+        // No pixels to read
+        psError(PS_ERR_IO, true, "No pixels in extension %s.", hdu->extname);
+        return false;
+    }
+    if (naxis < 2 || naxis > 3) {
+        psError(PS_ERR_IO, true, "NAXIS in header of extension %s (= %d) is not valid.\n",
+                hdu->extname, naxis);
+        return false;
+    }
+
+    // Determine the numbe of scans to read
+    int thisScan = readoutGetThisScan(readout, type);
+    int lastScan = readoutSetLastScan (readout, type, numScans);
+    if (thisScan == 0) {
+        overlap = 0;
+    }
+    thisScan -= overlap;
+
+    // Calculate limits, adjust readout->row0,col0
+    // XXX Should row0,col0 be adjusted, since they are used for astrometry???
+    // Just moved to using the "scansTracker" for tracking position in chunk reads, so row0,col0 not required
+    if (readdir == 1) {
+        // Reading rows
+        readout->row0 = thisScan;
+        readout->col0 = trimsec->x0;
+        if (numScans == 0) {
+            numScans = trimsec->y1 - trimsec->y0;
+        }
+    } else {
+        // Reading cols
+        readout->col0 = thisScan;
+        readout->row0 = trimsec->y0;
+        if (numScans == 0) {
+            numScans = trimsec->x1 - trimsec->x0;
+        }
+    }
+
+    // Blow away existing data.
+    // Do this before returning, so that we're not returning data from a previous read
+    psFree(*image);
+    *image = NULL;
+    *image = readoutReadComponent(*image, fits, trimsec, readdir, thisScan, lastScan, z, bad, pixelTypes[type]);
+
+    // Read overscans only for "image" type --- weights and masks shouldn't record overscans
+    if (type == FPA_READ_TYPE_IMAGE) {
+        // Blow away existing data
+        while (readout->bias->n > 0) {
+            psListRemove(readout->bias, PS_LIST_HEAD);
+        }
+
+        // Get the new bias sections
+        psList *biassecs = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.BIASSEC"); // Bias sections
+        if (!mdok || !biassecs) {
+            psError(PS_ERR_IO, true, "CELL.BIASSEC is not set.\n");
+            return false;
+        }
+        psListIterator *biassecsIter = psListIteratorAlloc(biassecs, PS_LIST_HEAD, false); // Iterator
+        psRegion *biassec = NULL;           // Bias section from iteration
+        while ((biassec = psListGetAndIncrement(biassecsIter))) {
+            psImage *bias = readoutReadComponent(NULL, fits, biassec, readdir, thisScan, lastScan, z, bad, pixelTypes[type]); // The bias
+            psListAdd(readout->bias, PS_LIST_TAIL, bias);
+            psFree(bias);                   // Drop reference
+        }
+        psFree(biassecsIter);
+    }
+
+    return true;
+}
+
+// Read into an cell; this is the engine for pmCellRead, pmCellReadMask, pmCellReadWeight
+// Does most of the work for the reading --- reads the HDU, and portions the HDU into readouts.
+static bool cellRead(pmCell *cell,      // Cell into which to read
+                     psFits *fits,      // FITS file from which to read
+                     pmConfig *config,  // Configuration
+                     fpaReadType type   // Type to read
+                    )
+{
+    assert(cell);
+    assert(fits);
+
+    pmHDU *hdu = pmHDUFromCell(cell);   // The HDU
+    if (!hdu) {
+        return true;                    // We read everything we could
+    }
+
+    // check if we have read the desired data, read it if needed
+    bool (*hduReadFunc)(pmHDU*, psFits*) = NULL; // Function to use to read the HDU
+    void *dataPointer = NULL;           // pointer to location of desired data
+    switch (type) {
+      case FPA_READ_TYPE_IMAGE:
+        hduReadFunc = pmHDURead;
+        dataPointer = hdu->images;
+        break;
+      case FPA_READ_TYPE_HEADER:
+        hduReadFunc = pmHDUReadHeader;
+        dataPointer = hdu->header;
+        break;
+      case FPA_READ_TYPE_MASK:
+        hduReadFunc = pmHDUReadMask;
+        dataPointer = hdu->masks;
+        break;
+      case FPA_READ_TYPE_WEIGHT:
+        hduReadFunc = pmHDUReadWeight;
+        dataPointer = hdu->weights;
+        break;
+      default:
+        psAbort("Unknown read type: %x\n", type);
+    }
+
+    // do we have the data we want (image, header, or etc).
+    if (!dataPointer) {
+        // attempt to read in the desired data
+        if (!hduReadFunc(hdu, fits)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to read HDU for cell.\n");
+            return false;
+        }
+    }
+
+    // load in the concept information for this cell
+    if (!pmConceptsReadCell(cell, PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_DATABASE, true, config)) {
+        //psError(PS_ERR_UNKNOWN, false, "Failed to read concepts for cell");
+        //return false;
+        psWarning("Difficulty reading concepts for cell; attempting to proceed.");
+    }
+
+    // skip the image arrays completely for the header-only files
+    if (type == FPA_READ_TYPE_HEADER) {
+        pmCellSetDataStatus(cell, true);
+        return true;
+    }
+
+    // set up pointers for the different possible image arrays
+    psArray *imageArray = NULL; // Array of images in the HDU
+    psElemType imageType = pixelTypes[type]; // Expected type for image
+    switch (type) {
+      case FPA_READ_TYPE_IMAGE:
+        imageArray = hdu->images;
+        break;
+      case FPA_READ_TYPE_MASK:
+        imageArray = hdu->masks;
+        break;
+      case FPA_READ_TYPE_WEIGHT:
+        imageArray = hdu->weights;
+        break;
+      default:
+        psAbort("Unknown read type: %x\n", type);
+    }
+
+    // Having read the cell, we now have to cut it up
+    psRegion *trimsec = psMetadataLookupPtr(NULL, cell->concepts, "CELL.TRIMSEC");
+    psList *biassecs = psMetadataLookupPtr(NULL, cell->concepts, "CELL.BIASSEC");
+    if (psRegionIsNaN(*trimsec)) {
+        psError(PS_ERR_IO, false, "CELL.TRIMSEC is not set --- can't read cell.\n");
+        return false;
+    }
+
+    // Iterate over each of the image planes, converting type if necessary, and extracting the bits that
+    // matter (CELL.TRIMSEC, CELL.BIASSEC) into readouts with readoutCarve.
+    for (int i = 0; i < imageArray->n; i++) {
+        psImage *source = imageArray->data[i]; // Source image, from the i-th plane
+        PS_ASSERT_IMAGE_NON_NULL(source, false);
+
+        // Type conversion here to support the modules, which don't have multiple type support yet
+        if (source->type.type != imageType) {
+            psImage *temp = psImageCopy(NULL, source, imageType); // Temporary image
+            psFree(imageArray->data[i]);
+            imageArray->data[i] = temp;
+            source = temp;
+        }
+
+        pmReadout *readout;             // Readout into which to read
+        if (cell->readouts->n > i && cell->readouts->data[i]) {
+            readout = psMemIncrRefCounter(cell->readouts->data[i]);
+        } else {
+            readout = pmReadoutAlloc(cell);
+        }
+
+        if (!readoutCarve(readout, source, trimsec, biassecs, type)) {
+            psError(PS_ERR_UNEXPECTED_NULL, false,
+                    "Unable to carve readout into image and bias sections for %d the plane.", i);
+            return NULL;
+        }
+        psFree(readout);                // Drop reference
+    }
+
+    pmCellSetDataStatus(cell, true);
+    return true;
+}
+
+
+// Read into an chip; this is the engine for pmChipRead, pmChipReadMask, pmChipReadWeight
+// Iterates over component cells, reading each
+static bool chipRead(pmChip *chip,      // Chip into which to read
+                     psFits *fits,      // FITS file from which to read
+                     pmConfig *config,  // Configuration
+                     fpaReadType type   // Type to read
+                    )
+{
+    assert(chip);
+    assert(fits);
+
+    bool success = false;               // Were we able to read at least one HDU?
+    psArray *cells = chip->cells;       // Array of cells
+    for (int i = 0; i < cells->n; i++) {
+        pmCell *cell = cells->data[i];  // The cell of interest
+        success |= cellRead(cell, fits, config, type);
+    }
+    if (success) {
+        if (!pmConceptsReadChip(chip, PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_DATABASE,
+                                true, true, NULL)) {
+            psError(PS_ERR_IO, false, "Failed to read concepts for chip.\n");
+            return false;
+        }
+        // XXX probably could just use chip->data_exists
+        pmChipSetDataStatus(chip, true);
+    }
+
+    return success;
+}
+
+
+// Read into an FPA; this is the engine for pmFPARead, pmFPAReadMask, pmFPAReadWeight
+// Iterates over component chips, reading each
+static bool fpaRead(pmFPA *fpa,         // FPA into which to read
+                    psFits *fits,       // FITS file from which to read
+                    pmConfig *config,   // Configuration
+                    fpaReadType type    // Type to read
+                   )
+{
+    assert(fpa);
+    assert(fits);
+
+    bool success = false;               // Were we able to read at least one HDU?
+    psArray *chips = fpa->chips;        // Array of chips
+    for (int i = 0; i < chips->n; i++) {
+        pmChip *chip = chips->data[i];  // The cell of interest
+        success |= chipRead(chip, fits, config, type);
+    }
+    if (success) {
+        if (!pmConceptsReadFPA(fpa, PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_DATABASE, true, NULL)) {
+            psError(PS_ERR_IO, false, "Failed to read concepts for FPA.\n");
+            return false;
+        }
+    } else {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read any chips in FPA");
+    }
+
+    return success;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Reading images
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// pmReadoutReadNext is maintained here (for now) to maintain backwards compatibility.
+// pmReadoutReadNext has been replaced by pmReadoutRead, pmReadoutReadChunk, pmReadoutMore
+bool pmReadoutReadNext(bool *status, pmReadout *readout, psFits *fits, int z, int numScans, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    PS_ASSERT_INT_NONNEGATIVE(z, false);
+    PS_ASSERT_INT_NONNEGATIVE(numScans, false);
+
+    assert (numScans || !readout->image); // cannot have readout->image and !numScans
+
+    *status = false;
+
+    // Get the HDU and read the header
+    pmCell *cell = readout->parent;     // The parent cell
+
+    pmHDU *hdu = pmHDUFromCell(cell);   // The HDU
+    if (!hdu || hdu->blankPHU) {
+        // XXX is this an error condition?
+        *status = true;
+        return false;
+    }
+
+    if (!pmCellReadHeader(cell, fits, config)) {
+        psError(PS_ERR_IO, false, "Unable to read header for cell!\n");
+        return false;
+    }
+
+    // Make sure we have the information we need
+    if (!pmConceptsReadCell(cell, PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_CELLS |
+                            PM_CONCEPT_SOURCE_DEFAULTS | PM_CONCEPT_SOURCE_DATABASE, true, NULL)) {
+        psError(PS_ERR_IO, false, "Failed to read concepts for cell.\n");
+        return false;
+    }
+
+    // Get the trim and bias sections
+    bool mdok = true;                   // Status of MD lookup
+    psRegion *trimsec = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.TRIMSEC"); // Trim sections
+    if (!mdok || !trimsec || psRegionIsNaN(*trimsec)) {
+        psError(PS_ERR_IO, true, "CELL.TRIMSEC is not set.\n");
+        return false;
+    }
+    psList *biassecs = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.BIASSEC"); // Bias sections
+    if (!mdok || !biassecs) {
+        psError(PS_ERR_IO, true, "CELL.BIASSEC is not set.\n");
+        return false;
+    }
+    int readdir = psMetadataLookupS32(&mdok, cell->concepts, "CELL.READDIR"); // Read direction
+    if (!mdok || readdir == 0 || (readdir != 1 && readdir != 2)) {
+        psError(PS_ERR_IO, true, "CELL.READDIR is not set to -1 or +1.\n");
+        return false;
+    }
+    float bad = psMetadataLookupF32(&mdok, cell->concepts, "CELL.BAD"); // Bad level
+    if (!mdok) {
+        psLogMsg(__func__, PS_LOG_WARN, "CELL.BAD is not set --- assuming zero.\n");
+        bad = 0.0;
+    }
+
+    // Check the third dimension
+    int naxis = psMetadataLookupS32(&mdok, hdu->header, "NAXIS"); // The number of axes
+    if (!mdok) {
+        psError(PS_ERR_IO, true, "Unable to find NAXIS in header for extension %s\n", hdu->extname);
+        return false;
+    }
+    if (naxis == 0) {
+        // No pixels to read, as for a PHU.
+        *status = true;
+        return false;
+    }
+    if (naxis < 2 || naxis > 3) {
+        psError(PS_ERR_IO, true, "NAXIS in header of extension %s (= %d) is not valid.\n",
+                hdu->extname, naxis);
+        return false;
+    }
+    int naxis3 = 1;                     // The number of image planes
+    if (naxis == 3) {
+        naxis3 = psMetadataLookupS32(&mdok, hdu->header, "NAXIS3");
+        if (!mdok) {
+            psError(PS_ERR_IO, true, "Unable to find NAXIS3 in header for extension %s\n", hdu->extname);
+            return false;
+        }
+    }
+    if (z >= naxis3) {
+        // Nothing to see here.  Move along.
+        *status = true;
+        return false;
+    }
+
+    // Get the size of the image plane
+    int naxis1 = psMetadataLookupS32(&mdok, hdu->header, "NAXIS1"); // The number of columns
+    if (!mdok) {
+        psError(PS_ERR_IO, true, "Unable to find NAXIS1 in header for extension %s\n", hdu->extname);
+        return false;
+    }
+    int naxis2 = psMetadataLookupS32(&mdok, hdu->header, "NAXIS2"); // The number of columns
+    if (!mdok) {
+        psError(PS_ERR_IO, true, "Unable to find NAXIS2 in header for extension %s\n", hdu->extname);
+        return false;
+    }
+
+    // rationalize trimsec against naxis1, naxis2
+    // valid range for trimsec is 1-Nx,1-Ny
+    // if (trimsec->x0 == 0) trimsec->x0 = 1;
+    if (trimsec->x1 <  1)
+        trimsec->x1 = naxis1 + trimsec->x1;
+    // if (trimsec->y0 == 0) trimsec->y0 = 1;
+    if (trimsec->y1 <  1)
+        trimsec->y1 = naxis2 + trimsec->y1;
+
+    int maxSize;                        // Number of cols,rows in image
+    if (readdir == 1) {
+        maxSize = PS_MIN(naxis2, trimsec->y1 - trimsec->y0);
+    } else {
+        maxSize = PS_MIN(naxis1, trimsec->x1 - trimsec->x0);
+    }
+
+    int offset;                         // start of the segment
+    int upper;                          // end of the segment
+    int lastScan;                       // last possible scan
+
+    // Calculate the segment offset and upper limit, adjust readout->row0,col0
+    if (readdir == 1) {
+        // Reading rows
+        offset = (readout->image) ? readout->row0 + numScans : 0; // extend to next section or start at beginning?
+        offset = (numScans == 0) ? trimsec->x0 : offset; // full array ? read full trimsec : read section
+        readout->row0 = offset;
+        readout->col0 = trimsec->x0;
+        lastScan = trimsec->y1;
+    } else {
+        // Reading cols
+        offset = (readout->image) ? readout->col0 + numScans : 0;
+        offset = (numScans == 0) ? trimsec->y0 : offset; // full array ? read full trimsec : read section
+        readout->col0 = offset;
+        readout->row0 = trimsec->y0;
+        lastScan = trimsec->x1;
+    }
+    upper = offset + numScans;
+
+    // Blow away existing data.
+    // Do this before returning, so that we're not returning data from a previous read
+    psFree(readout->image);
+    readout->image = NULL;
+
+    while (readout->bias->n > 0) {
+        psListRemove(readout->bias, PS_LIST_HEAD);
+    }
+
+    if (offset >= lastScan) {
+        // We've read everything there is
+        psTrace("psModules.camera", 7, "Read everything.\n");
+        *status = true;
+        return false;
+    }
+
+    psTrace("psModules.camera", 7, "offset=%d, upper = %d, image is %dx%d, trimsec [%.0f:%.0f,%.0f:%.0f]\n",
+            offset, upper, naxis1, naxis2, trimsec->x0, trimsec->x1, trimsec->y0, trimsec->y1);
+
+    // Get the new the trim section
+    readout->image = readoutReadComponent(readout->image, fits, trimsec, readdir, offset, upper, z, bad,
+                                          PS_TYPE_F32); // The image
+
+    // Get the new bias sections
+    psListIterator *biassecsIter = psListIteratorAlloc(biassecs, PS_LIST_HEAD, false); // Iterator for BIASSEC
+    psRegion *biassec = NULL;           // Bias section from iteration
+    while ((biassec = psListGetAndIncrement(biassecsIter))) {
+        psImage *bias = readoutReadComponent(NULL, fits, biassec, readdir, offset, upper, z, bad,
+                                             PS_TYPE_F32); // The bias
+        psListAdd(readout->bias, PS_LIST_TAIL, bias);
+        psFree(bias);                   // Drop reference
+    }
+    psFree(biassecsIter);
+
+    *status = true;
+    return true;
+}
+
+
+
+bool pmReadoutMore(pmReadout *readout, psFits *fits, int z, int numScans, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    return readoutMore(readout, fits, z, numScans, FPA_READ_TYPE_IMAGE, config);
+}
+
+bool pmReadoutReadChunk(pmReadout *readout, psFits *fits, int z, int numScans, int overlap, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_INT_NONNEGATIVE(z, false);
+    PS_ASSERT_INT_NONNEGATIVE(numScans, false);
+
+    return readoutReadChunk(readout, fits, z, numScans, overlap, FPA_READ_TYPE_IMAGE, config);
+}
+
+bool pmReadoutRead(pmReadout *readout, psFits *fits, int z, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    return readoutReadChunk(readout, fits, z, 0, 0, FPA_READ_TYPE_IMAGE, config);
+}
+
+int pmCellNumReadouts(pmCell *cell, psFits *fits, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    return cellNumReadouts(cell, fits, config);
+}
+
+bool pmCellRead(pmCell *cell, psFits *fits, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    return cellRead(cell, fits, config, FPA_READ_TYPE_IMAGE);
+}
+
+bool pmChipRead(pmChip *chip, psFits *fits, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    return chipRead(chip, fits, config, FPA_READ_TYPE_IMAGE);
+}
+
+bool pmFPARead(pmFPA *fpa, psFits *fits, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    return fpaRead(fpa, fits, config, FPA_READ_TYPE_IMAGE);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Reading the mask
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool pmReadoutMoreMask(pmReadout *readout, psFits *fits, int z, int numScans, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    return readoutMore(readout, fits, z, numScans, FPA_READ_TYPE_MASK, config);
+}
+
+bool pmReadoutReadChunkMask(pmReadout *readout, psFits *fits, int z, int numScans, int overlap,
+                            pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_INT_NONNEGATIVE(z, false);
+    PS_ASSERT_INT_NONNEGATIVE(numScans, false);
+
+    return readoutReadChunk(readout, fits, z, numScans, overlap, FPA_READ_TYPE_MASK, config);
+}
+
+bool pmReadoutReadMask(pmReadout *readout, psFits *fits, int z, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    return readoutReadChunk(readout, fits, z, 0, 0, FPA_READ_TYPE_MASK, config);
+}
+
+bool pmCellReadMask(pmCell *cell, psFits *fits, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    return cellRead(cell, fits, config, FPA_READ_TYPE_MASK);
+}
+
+bool pmChipReadMask(pmChip *chip, psFits *fits, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    return chipRead(chip, fits, config, FPA_READ_TYPE_MASK);
+}
+
+bool pmFPAReadMask(pmFPA *fpa, psFits *fits, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    return fpaRead(fpa, fits, config, FPA_READ_TYPE_MASK);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Reading the weight map
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool pmReadoutMoreWeight(pmReadout *readout, psFits *fits, int z, int numScans, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    return readoutMore(readout, fits, z, numScans, FPA_READ_TYPE_WEIGHT, config);
+}
+
+bool pmReadoutReadChunkWeight(pmReadout *readout, psFits *fits, int z, int numScans, int overlap,
+                              pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_INT_NONNEGATIVE(z, false);
+    PS_ASSERT_INT_NONNEGATIVE(numScans, false);
+
+    return readoutReadChunk(readout, fits, z, numScans, overlap, FPA_READ_TYPE_WEIGHT, config);
+}
+
+bool pmReadoutReadWeight(pmReadout *readout, psFits *fits, int z, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    return readoutReadChunk(readout, fits, z, 0, 0, FPA_READ_TYPE_WEIGHT, config);
+}
+
+bool pmCellReadWeight(pmCell *cell, psFits *fits, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    return cellRead(cell, fits, config, FPA_READ_TYPE_WEIGHT);
+}
+
+bool pmChipReadWeight(pmChip *chip, psFits *fits, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    return chipRead(chip, fits, config, FPA_READ_TYPE_WEIGHT);
+}
+
+bool pmFPAReadWeight(pmFPA *fpa, psFits *fits, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    return fpaRead(fpa, fits, config, FPA_READ_TYPE_WEIGHT);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Reading the image header
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool pmCellReadHeaderSet(pmCell *cell, psFits *fits, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    return cellRead(cell, fits, config, FPA_READ_TYPE_HEADER);
+}
+
+bool pmChipReadHeaderSet(pmChip *chip, psFits *fits, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    return chipRead(chip, fits, config, FPA_READ_TYPE_HEADER);
+}
+
+bool pmFPAReadHeaderSet(pmFPA *fpa, psFits *fits, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    return fpaRead(fpa, fits, config, FPA_READ_TYPE_HEADER);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Reading FITS tables
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+int pmCellReadTable(pmCell *cell, psFits *fits, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, 0);
+    PS_ASSERT_FITS_NON_NULL(fits, 0);
+    PS_ASSERT_STRING_NON_EMPTY(name, 0);
+
+    const char *chipName = psMetadataLookupStr(NULL, cell->parent->concepts, "CHIP.NAME"); // Name of chip
+    const char *cellName = psMetadataLookupStr(NULL, cell->concepts, "CELL.NAME"); // Name of cell
+    psString extname = NULL;            // Extension name
+    psStringAppend(&extname, "%s_%s_%s", name, chipName, cellName);
+
+    // XXX Could do a table lookup from the camera format, in case the input file isn't laid out with
+    // NAME_CHIP_CELL extension names --- use these as keys, and the value as the proper extension name.
+    // Allow interpolation of concepts, e.g., "{CHIP.NAME}" --> "ccd13".
+
+    if (!psFitsMoveExtName(fits, extname)) {
+        psError(PS_ERR_IO, false, "Unable to move to extension %s\n", extname);
+        psFree(extname);
+        return 0;
+    }
+
+    psMetadata *header = psFitsReadHeader(NULL, fits); // The FITS header
+    if (!header) {
+        psError(PS_ERR_IO, false, "Unable to read header for extension %s\n", extname);
+        psFree(extname);
+        psFree(header);
+        return 0;
+    }
+
+    psString headerName = NULL;         // Name for header
+    psStringAppend(&headerName, "%s.HEADER", name);
+    if (!psMetadataAdd(cell->analysis, PS_LIST_TAIL, headerName, PS_DATA_METADATA,
+                       "FITS table header", header)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to add header from extension %s to analysis metadata "
+                "for chip %s, cell %s\n", extname, chipName, cellName);
+        psFree(headerName);
+        psFree(header);
+        psFree(extname);
+        return 0;
+    }
+    psFree(headerName);
+    psFree(header);
+
+    psArray *table = psFitsReadTable(fits); // The table
+    if (!psMetadataAdd(cell->analysis, PS_LIST_TAIL, name, PS_DATA_ARRAY, "FITS table", table)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to add table from extension %s to analysis metadata "
+                "for chip %s, cell %s\n", extname, chipName, cellName);
+        psFree(table);
+        psFree(extname);
+        return 0;
+    }
+
+    psFree(extname);
+    psFree(table);                      // Dropping reference
+
+    return 1;
+}
+
+
+int pmChipReadTable(pmChip *chip, psFits *fits, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, 0);
+    PS_ASSERT_FITS_NON_NULL(fits, 0);
+    PS_ASSERT_STRING_NON_EMPTY(name, 0);
+
+    int numRead = 0;                    // Number of reads
+    psArray *cells = chip->cells;       // Array of cells
+    for (int i = 0; i < cells->n; i++) {
+        pmCell *cell = cells->data[i];  // Cell of interest
+        numRead += pmCellReadTable(cell, fits, name);
+    }
+
+    return numRead;
+}
+
+
+int pmFPAReadTable(pmFPA *fpa, psFits *fits, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, 0);
+    PS_ASSERT_FITS_NON_NULL(fits, 0);
+    PS_ASSERT_STRING_NON_EMPTY(name, 0);
+
+    int numRead = 0;                    // Number of reads
+    psArray *chips = fpa->chips;        // Array of chips
+    for (int i = 0; i < chips->n; i++) {
+        pmChip *chip = chips->data[i];  // Chip of interest
+        numRead += pmChipReadTable(chip, fits, name);
+    }
+
+    return numRead;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPARead.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPARead.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPARead.h	(revision 22158)
@@ -0,0 +1,248 @@
+/* @file pmFPARead.h
+ * @brief Functions to read FPA components from a FITS file
+ *
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-06-17 22:16:38 $
+ * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FPA_READ_H
+#define PM_FPA_READ_H
+
+#include <pmConfig.h>
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+/// Check to see if there is more to read when reading a readout incrementally
+bool pmReadoutMore(pmReadout *readout,  ///< Readout of interest
+                   psFits *fits,        ///< FITS file from which to read
+                   int z,               ///< Readout number/plane; zero-offset indexing
+                   int numScans,        ///< Number of scans (rows/cols) to read
+                   pmConfig *config     ///< Configuration
+    );
+
+/// Read a chunk of a readout.
+///
+/// Allows reading the readout incrementally
+bool pmReadoutReadChunk(pmReadout *readout, ///< Readout of interest
+                        psFits *fits,   ///< FITS file from which to read
+                        int z,          ///< Readout number/plane; zero-offset indexing
+                        int numScans,   ///< Number of scans (rows/cols) to read
+                        int overlap,    ///< Overlap between consecutive reads
+                        pmConfig *config ///< Configuration
+    );
+
+/// Read the entire readout
+bool pmReadoutRead(pmReadout *readout,  ///< Readout of interest
+                   psFits *fits,        ///< FITS file from which to read
+                   int z,               ///< Readout number/plane; zero-offset indexing
+                   pmConfig *config     ///< Configuration
+    );
+
+/// Read a readout incrementally --- this is maintained temporarily only for backwards compatibility; it has
+/// been replaced by pmReadoutRead, pmReadoutReadChunk and pmReadoutMore.
+///
+/// Multiple calls to this function moves through a readout within a cell incrementally.  It is required to
+/// pass the readout previously acquired (or a newly-allocated one) in order to preserve state information
+/// (where the read is at).  Only a maximum of numRows rows are read at a time.  Returns true if pixels are
+/// read, and false otherwise.  To facilitate looping, no error is generated for reading a plane that doesn't
+/// exist.  Note that this function doesn't put pixels in the HDU.  It is therefore NOT COMPATIBLE with
+/// pmCellWrite, pmChipWrite, and pmFPAWrite (or any function that uses or creates an HDU for that matter).
+/// Use pmReadoutWriteNext to write the data that's read by this function.  This function is intended for
+/// reading in many readouts into memory at once (e.g., for stacking) where the input is not written out.
+bool pmReadoutReadNext(bool *status,    // non-error exit condition?
+                       pmReadout *readout, // Readout into which to read
+                       psFits *fits,    // FITS file from which to read
+                       int z,           // Readout number/plane; zero-offset indexing
+                       int numRows,      // The number of rows to read
+                       pmConfig *config
+                      );
+
+/// Return the number of readouts within a cell
+///
+/// This function is type-independent (doesn't matter if you are interested in the image/mask/weight).
+int pmCellNumReadouts(pmCell *cell, psFits *fits, pmConfig *config);
+
+/// Read an entire cell
+///
+/// Reads the appropriate HDU, ingests concepts from the header, and portions pixels into readouts.  Pixels
+/// are converted to F32.
+bool pmCellRead(pmCell *cell,           // Cell to read into
+                psFits *fits,           // FITS file from which to read
+                pmConfig *config        // Configuration
+               );
+
+/// Read a chip
+///
+/// Iterates over component cells, reading each with pmCellRead.
+bool pmChipRead(pmChip *chip,           // Chip to read into
+                psFits *fits,           // FITS file from which to read
+                pmConfig *config        // Configuration
+               );
+
+/// Read an FPA
+///
+/// Iterates over component chips, reading each with pmChipRead.
+bool pmFPARead(pmFPA *fpa,              // FPA to read into
+               psFits *fits,            // FITS file from which to read
+               pmConfig *config         // Configuration
+              );
+
+// Mask functions follow
+
+/// Check to see if there is more to read when reading a readout incrementally into the mask
+bool pmReadoutMoreMask(pmReadout *readout, ///< Readout of interest
+                       psFits *fits,    ///< FITS file from which to read
+                       int z,           ///< Readout number/plane; zero-offset indexing
+                       int numScans,    ///< Number of scans (rows/cols) to read
+                       pmConfig *config ///< Configuration
+    );
+
+/// Read a chunk of a readout into the mask
+///
+/// Allows reading the readout incrementally
+bool pmReadoutReadChunkMask(pmReadout *readout, ///< Readout of interest
+                            psFits *fits, ///< FITS file from which to read
+                            int z,      ///< Readout number/plane; zero-offset indexing
+                            int numScans, ///< Number of scans (rows/cols) to read
+                            int overlap, ///< Overlap between consecutive reads
+                            pmConfig *config ///< Configuration
+    );
+
+/// Read the entire readout into the mask
+bool pmReadoutReadMask(pmReadout *readout, ///< Readout of interest
+                       psFits *fits,    ///< FITS file from which to read
+                       int z,           ///< Readout number/plane; zero-offset indexing
+                       pmConfig *config ///< Configuration
+    );
+
+/// Read an entire cell into the mask
+///
+/// Same as pmCellRead, but reads into the mask element of the readouts.
+bool pmCellReadMask(pmCell *cell,       // Cell to read into
+                    psFits *fits,       // FITS file from which to read
+                    pmConfig *config    // Configuration
+                   );
+
+/// Read an entire chip into the mask
+///
+/// Same as pmChipRead, but reads into the mask element of the readouts.
+bool pmChipReadMask(pmChip *chip,       // Chip to read into
+                    psFits *fits,       // FITS file from which to read
+                    pmConfig *config    // Configuration
+                   );
+
+/// Read an entire FPA into the mask
+///
+/// Same as pmFPARead, but reads into the mask element of the readouts.
+bool pmFPAReadMask(pmFPA *fpa,          // FPA to read into
+                   psFits *fits,        // FITS file from which to read
+                   pmConfig *config     // Configuration
+                  );
+
+// Weight functions follow
+
+/// Check to see if there is more to read when reading a readout incrementally into the weight
+bool pmReadoutMoreWeight(pmReadout *readout, ///< Readout of interest
+                         psFits *fits,  ///< FITS file from which to read
+                         int z,         ///< Readout number/plane; zero-offset indexing
+                         int numScans,  ///< Number of scans (rows/cols) to read
+                         pmConfig *config ///< Configuration
+    );
+
+/// Read a chunk of a readout into the weight
+///
+/// Allows reading the readout incrementally
+bool pmReadoutReadChunkWeight(pmReadout *readout, ///< Readout of interest
+                              psFits *fits, ///< FITS file from which to read
+                              int z,    ///< Readout number/plane; zero-offset indexing
+                              int numScans, ///< Number of scans (rows/cols) to read
+                              int overlap, ///< Overlap between consecutive reads
+                              pmConfig *config ///< Configuration
+    );
+
+/// Read the entire readout into the weight
+bool pmReadoutReadWeight(pmReadout *readout, ///< Readout of interest
+                         psFits *fits,  ///< FITS file from which to read
+                         int z,         ///< Readout number/plane; zero-offset indexing
+                         pmConfig *config ///< Configuration
+    );
+
+/// Read an entire cell into the weight
+///
+/// Same as pmCellRead, but reads into the weight element of the readouts.
+bool pmCellReadWeight(pmCell *cell,     // Cell to read into
+                      psFits *fits,     // FITS file from which to read
+                      pmConfig *config  // Configuration
+                     );
+
+/// Read an entire chip into the weight
+///
+/// Same as pmChipRead, but reads into the weight element of the readouts.
+bool pmChipReadWeight(pmChip *chip,     // Chip to read into
+                      psFits *fits,     // FITS file from which to read
+                      pmConfig *config  // Configuration
+                     );
+
+/// Read an entire FPA into the weight
+///
+/// Same as pmFPARead, but reads into the weight element of the readouts.
+bool pmFPAReadWeight(pmFPA *fpa,        // FPA to read into
+                     psFits *fits,      // FITS file from which to read
+                     pmConfig *config   // Configuration
+                    );
+
+/// Read cell headers
+///
+/// Same as pmCellRead, but reads only the headers of the readouts.
+bool pmCellReadHeaderSet(pmCell *cell,  // Cell to read into
+                         psFits *fits,  // FITS file from which to read
+                         pmConfig *config // Configuration
+    );
+
+/// Read chip headers
+///
+/// Same as pmChipRead, but reads only the headers of the readouts.
+bool pmChipReadHeaderSet(pmChip *chip,  // Chip to read into
+                      psFits *fits,     // FITS file from which to read
+                      pmConfig *config  // Configuration
+                     );
+
+/// Read FPA headers
+///
+/// Same as pmFPARead, but reads only the headers of the readouts.
+bool pmFPAReadHeaderSet(pmFPA *fpa,     // FPA to read into
+                        psFits *fits,   // FITS file from which to read
+                        pmConfig *config // Configuration
+    );
+
+/// Read a FITS table into the cell
+///
+/// Given a name, which is combined with the chip and cell to identify the extension name ("NAME_CHIP_CELL"),
+/// read the FITS table into the cell analysis metadata (with key being the provided name).  The header is
+/// also read and included in the cell analysis metadata under "name.HEADER".
+int pmCellReadTable(pmCell *cell,       ///< Cell for which to read table
+                    psFits *fits,       ///< FITS file from which the table
+                    const char *name    ///< Specifies the extension name, and target in the analysis metadata
+                   );
+
+/// Read a FITS table into the component cells
+///
+/// Iterates over component cells, calling pmCellReadTable.
+int pmChipReadTable(pmChip *chip,       ///< Cell for which to read table
+                    psFits *fits,       ///< FITS file from which the table
+                    const char *name    ///< Specifies the extension name, and target in the analysis metadata
+                   );
+
+/// Read a FITS table into the component cells
+///
+/// Iterates over component chips, calling pmChipReadTable.
+int pmFPAReadTable(pmFPA *fpa,          ///< Cell for which to read table
+                   psFits *fits,        ///< FITS file from which the table
+                   const char *name     ///< Specifies the extension name, and target in the analysis metadata
+                  );
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAUtils.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAUtils.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAUtils.c	(revision 22158)
@@ -0,0 +1,55 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPAUtils.h"
+
+int pmFPAFindChip(const pmFPA *fpa, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, -1);
+    PS_ASSERT_PTR_NON_NULL(name, -1);
+    if (strlen(name) == 0) {
+        return -1;
+    }
+
+    psArray *chips = fpa->chips;        // Array of chips
+    for (int i = 0; i < chips->n; i++) {
+        pmChip *chip = chips->data[i]; // The chip of interest
+        psString testName = psMetadataLookupStr(NULL, chip->concepts, "CHIP.NAME"); // Name of this chip
+        if (strcmp(name, testName) == 0) {
+            return i;
+        }
+    }
+
+    psError(PS_ERR_IO, true, "Unable to find chip %s\n", name);
+    return -1;
+}
+
+
+int pmChipFindCell(const pmChip *chip, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, -1);
+    PS_ASSERT_PTR_NON_NULL(name, -1);
+    if (strlen(name) == 0) {
+        return -1;
+    }
+
+    psArray *cells = chip->cells;    // Array of cells
+    for (int i = 0; i < cells->n; i++) {
+        pmCell *cell = cells->data[i]; // The cell of interest
+        psString testName = psMetadataLookupStr(NULL, cell->concepts, "CELL.NAME"); // Name of this cell
+        if (strcmp(name, testName) == 0) {
+            return i;
+        }
+    }
+
+    psError(PS_ERR_IO, true, "Unable to find cell %s\n", name);
+    return -1;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAUtils.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAUtils.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAUtils.h	(revision 22158)
@@ -0,0 +1,33 @@
+/* @file pmFPAUtils.h
+ * @brief Utility functions for FPAs
+ *
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-03-30 21:12:56 $
+ * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FPA_UTILS_H
+#define PM_FPA_UTILS_H
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+/// Find a chip by name; return the index
+///
+/// Looks for a chip within the FPA with CHIP.NAME matching the provided name.  Returns the index of the chip,
+/// or -1 if it was not found.
+int pmFPAFindChip(const pmFPA *fpa,     ///< FPA in which to find the chip
+                  const char *name      ///< Name of the chip
+                 );
+
+/// Find a cell by name; return the index
+///
+/// Looks for a cell within the chip with CELL.NAME matching the provided name.  Returns the index of the
+/// cell, or -1 if it was not found.
+int pmChipFindCell(const pmChip *chip,  // Chip in which to find the cell
+                   const char *name     // Name of the cell
+                  );
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAWrite.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAWrite.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAWrite.c	(revision 22158)
@@ -0,0 +1,510 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <strings.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmDetrendDB.h"
+#include "pmFPAfile.h"
+#include "pmHDUUtils.h"
+#include "pmHDUGenerate.h"
+#include "pmConcepts.h"
+
+#include "pmFPAWrite.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Definitions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Specify what to read
+typedef enum {
+    FPA_WRITE_TYPE_IMAGE,               // Write image
+    FPA_WRITE_TYPE_MASK,                // Write mask
+    FPA_WRITE_TYPE_WEIGHT               // Write weight map
+} fpaWriteType;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// File-static (private) functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+// Update the FPA.OBS, CHIP.NAME and CELL.NAME in the FITS header, if required
+bool pmFPAUpdateNames(pmFPA *fpa, pmChip *chip, pmCell *cell)
+{
+    pmHDU *hdu = pmHDUGetHighest(fpa, chip, cell); // Highest HDU, i.e., the PHU
+    if (!hdu) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find HDU.\n");
+        return false;
+    }
+    if (!hdu->header) {
+        hdu->header = psMetadataAlloc();
+    }
+    bool mdok;                          // Status of MD lookup
+    psMetadata *fileData = psMetadataLookupMetadata(&mdok, hdu->format, "FILE"); // File information
+    if (!mdok || !fileData) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find FILE information in camera format.\n");
+        return false;
+    }
+    if (fpa) {
+        const char *fpaObsHdr = psMetadataLookupStr(&mdok, fileData, "FPA.OBS");
+        if (mdok && fpaObsHdr && strlen(fpaObsHdr) > 0) {
+            const char *fpaObs = psMetadataLookupStr(NULL, fpa->concepts, "FPA.OBS");
+            psMetadataAddStr(hdu->header, PS_LIST_TAIL, fpaObsHdr, PS_META_REPLACE,
+                             "Observation identifier", fpaObs);
+        }
+    }
+
+    if (fpa && !fpa->hdu && (chip || cell)) {
+        const char *rule = psMetadataLookupStr(NULL, fileData, "CONTENT.RULE"); // How to define the CONTENT
+        if (!rule) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to find CONTENT.RULE in FILE in camera format.");
+            return false;
+        }
+
+        pmFPAview *view = pmFPAviewGenerate(fpa, chip, cell, NULL); // View for fpa, chip, cell
+        psString content = pmFPANameFromRule(rule, fpa, view); // Content of this file, specified by the rule
+        psFree(view);
+
+        const char *contentKey = psMetadataLookupStr(NULL, fileData, "CONTENT"); // The CONTENT header keyword
+        if (!contentKey) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to find CONTENT in FILE in the camera format.");
+            psFree(content);
+            return false;
+        }
+
+        psMetadataAddStr(hdu->header, PS_LIST_TAIL, contentKey, PS_META_REPLACE, "Content of file", content);
+        psFree(content);                // Drop reference
+    }
+
+    return true;
+}
+
+// Return the appropriate image array for the given type
+static psArray **appropriateImageArray(pmHDU *hdu, // HDU containing the image arrays
+                                       fpaWriteType type // Type to write
+                                      )
+{
+    switch (type) {
+    case FPA_WRITE_TYPE_IMAGE:
+        return &hdu->images;
+    case FPA_WRITE_TYPE_MASK:
+        return &hdu->masks;
+    case FPA_WRITE_TYPE_WEIGHT:
+        return &hdu->weights;
+    default:
+        psAbort("Unknown write type: %x\n", type);
+    }
+    return NULL;
+}
+
+// Run the appropriate HDU write function
+static bool appropriateWriteFunc(pmHDU *hdu, // HDU to write
+                                 psFits *fits, // FITS file to which to write
+                                 fpaWriteType type // Type to write
+                                )
+{
+    switch (type) {
+    case FPA_WRITE_TYPE_IMAGE:
+        return pmHDUWrite(hdu, fits);
+    case FPA_WRITE_TYPE_MASK:
+        return pmHDUWriteMask(hdu, fits);
+    case FPA_WRITE_TYPE_WEIGHT:
+        return pmHDUWriteWeight(hdu, fits);
+    default:
+        psAbort("Unknown write type: %x\n", type);
+    }
+    return false;
+}
+
+// Write a cell image/mask/weight
+static bool cellWrite(pmCell *cell,     // Cell to write
+                      psFits *fits,     // FITS file to which to write
+                      pmConfig *config, // Configuration
+                      bool blank,       // Write a blank PHU?
+                      fpaWriteType type // Type to write
+                     )
+{
+    assert(cell);
+    assert(fits);
+
+    psTrace ("pmFPAWrite", 5, "writing to Cell (%d)\n", blank);
+
+    pmHDU *hdu = cell->hdu;             // The HDU
+    if (!hdu || !cell->data_exists) {
+        return true;                    // We wrote every HDU that exists
+    }
+
+    psArray **imageArray = appropriateImageArray(hdu, type); // Array of images in the HDU
+
+    // Generate the HDU if needed --- this is required after a pmFPACopy, or similar, which does not
+    // generate the HDU, but only copies the structure.
+    if (!blank && !hdu->blankPHU && !*imageArray && (!pmHDUGenerateForCell(cell) || !*imageArray)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to generate HDU for cell --- likely programming error.\n");
+        return false;
+    }
+
+    // We only write out a blank PHU if it's specifically requested.
+    bool writeBlank = blank && hdu->blankPHU && !*imageArray; // Write a blank PHU?
+    bool writeImage = !blank && !hdu->blankPHU && *imageArray; // Write an image?
+
+    if (writeBlank || writeImage) {
+
+        pmFPAUpdateNames(cell->parent->parent, cell->parent, cell);
+        pmConceptSource source = PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_CELLS |
+                                 PM_CONCEPT_SOURCE_DEFAULTS | PM_CONCEPT_SOURCE_DATABASE;
+        if (!pmConceptsWriteCell(cell, source, true, config)) {
+            psError(PS_ERR_IO, false, "Unable to write concepts for cell.\n");
+            return false;
+        }
+        if (!appropriateWriteFunc(hdu, fits, type)) {
+            psError(PS_ERR_IO, false, "Unable to write HDU for cell.\n");
+            return false;
+        }
+    }
+    // No lower levels to which to recurse
+
+    return true;
+}
+
+// Write a chip image/mask/weight
+static bool chipWrite(pmChip *chip,     // Chip to write
+                      psFits *fits,     // FITS file to which to write
+                      pmConfig *config, // Configuration
+                      bool blank,       // Write a blank PHU?
+                      bool recurse,     // Recurse to lower levels?
+                      fpaWriteType type // Type to write
+                     )
+{
+    assert(chip);
+    assert(fits);
+
+    pmHDU *hdu = chip->hdu;             // The HDU
+
+    psTrace ("pmFPAWrite", 5, "writing to Chip (%d, %d)\n", blank, recurse);
+
+    // If we have data at this level, try to write it out
+    if (hdu && chip->data_exists) {
+        psArray **imageArray = appropriateImageArray(hdu, type); // Array of images in HDU
+
+        // Generate the HDU if needed --- this is required after a pmFPACopy, or similar, which does not
+        // generate the HDU, but only copies the structure.
+        if (!blank && !hdu->blankPHU && !*imageArray && (!pmHDUGenerateForChip(chip) || !*imageArray)) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Unable to generate HDU for chip --- likely programming error.\n");
+            return false;
+        }
+
+        // We only write out a blank PHU if it's specifically requested.
+        bool writeBlank = blank && hdu->blankPHU && !*imageArray; // Write a blank HDU?
+        bool writeImage = !blank && !hdu->blankPHU && *imageArray; // Write an image?
+
+        if (writeBlank || writeImage) {
+            pmFPAUpdateNames(chip->parent, chip, NULL);
+            pmConceptSource source = PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_CELLS |
+                                     PM_CONCEPT_SOURCE_DEFAULTS | PM_CONCEPT_SOURCE_DATABASE;
+            if (!pmConceptsWriteChip(chip, source, true, true, config)) {
+                psError(PS_ERR_IO, false, "Unable to write concepts for chip.\n");
+                return false;
+            }
+            if (!appropriateWriteFunc(hdu, fits, type)) {
+                psError(PS_ERR_IO, false, "Unable to write HDU for chip.\n");
+                return false;
+            }
+        }
+    }
+
+    // Recurse to lower level if specifically requested.
+    // XXX recursion implies blank == false (must be called on correct level?)
+    if (recurse) {
+        psArray *cells = chip->cells;       // Array of cells
+        for (int i = 0; i < cells->n; i++) {
+            pmCell *cell = cells->data[i];  // The cell of interest
+            if (!cellWrite(cell, fits, config, false, type)) {
+                psError(PS_ERR_IO, false, "Unable to write Chip.\n");
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+
+// Write an FPA image/mask/weight
+static bool fpaWrite(pmFPA *fpa,        // FPA to write
+                     psFits *fits,      // FITS file to which to write
+                     pmConfig *config,  // Configuration
+                     bool blank,        // Write a blank PHU?
+                     bool recurse,      // Recurse to lower levels?
+                     fpaWriteType type  // Type to write
+                    )
+{
+    assert(fpa);
+    assert(fits);
+
+    pmHDU *hdu = fpa->hdu;              // The HDU
+
+    psTrace ("pmFPAWrite", 5, "writing to FPA (%d, %d)\n", blank, recurse);
+
+    // If we have data at this level, try to write it out
+    if (hdu) {
+        psArray **imageArray = appropriateImageArray(hdu, type); // Array of images in HDU
+
+        // Generate the HDU if needed --- this is required after a pmFPACopy, or similar, which does not
+        // generate the HDU, but only copies the structure.
+        if (!blank && !hdu->blankPHU && !*imageArray && (!pmHDUGenerateForFPA(fpa) || !*imageArray)) {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Unable to generate HDU for FPA --- likely programming error.\n");
+            return false;
+        }
+
+        // We only write out a blank PHU if it's specifically requested.
+        bool writeBlank = blank && hdu->blankPHU && !*imageArray; // Write a blank PHU?
+        bool writeImage = !blank && !hdu->blankPHU && *imageArray; // Write an image?
+
+        if (writeBlank || writeImage) {
+            pmFPAUpdateNames(fpa, NULL, NULL);
+            pmConceptSource source = PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_CELLS |
+                                     PM_CONCEPT_SOURCE_DEFAULTS | PM_CONCEPT_SOURCE_DATABASE;
+            if (!pmConceptsWriteFPA(fpa, source, true, config)) {
+                psError(PS_ERR_IO, false, "Unable to write concepts for FPA.\n");
+                return false;
+            }
+            if (!appropriateWriteFunc(hdu, fits, type))  {
+                psError(PS_ERR_IO, false, "Unable to write HDU for FPA.\n");
+                return false;
+            }
+        }
+    }
+
+    // Recurse to lower levels if requested
+    if (recurse) {
+        psArray *chips = fpa->chips;        // Array of chips
+        for (int i = 0; i < chips->n; i++) {
+            pmChip *chip = chips->data[i];  // The chip of interest
+            if (!chipWrite(chip, fits, config, false, true, type)) {
+                psError(PS_ERR_IO, false, "Unable to write FPA.\n");
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool pmReadoutWriteNext(pmReadout *readout, psFits *fits, int z)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+
+    pmHDU *hdu = pmHDUFromReadout(readout); // The HDU to which to write
+    if (!hdu) {
+        psError(PS_ERR_IO, false, "Unable to find HDU for readout.\n");
+        return false;
+    }
+    psMetadata *header = hdu->header;   // The FITS header
+    if (!header) {
+        psError(PS_ERR_IO, true, "No FITS header available in the HDU.\n");
+        return false;
+    }
+
+    // We have to rely to a great extent on the FITS header, because otherwise we simply don't know how many
+    // image planes there are (NAXIS3) or the size of the original image (NAXIS1, NAXIS2).
+    bool mdok = true;                   // Status of MD lookup
+    int naxis1 = psMetadataLookupS32(&mdok, header, "NAXIS1"); // Number of columns
+    if (!mdok || naxis1 <= 0) {
+        psError(PS_ERR_IO, true, "Can't find NAXIS1 in header.\n");
+        return false;
+    }
+    int naxis2 = psMetadataLookupS32(&mdok, header, "NAXIS2"); // Number of rows
+    if (!mdok || naxis2 <= 0) {
+        psError(PS_ERR_IO, true, "Can't find NAXIS2 in header.\n");
+        return false;
+    }
+    int naxis3 = psMetadataLookupS32(&mdok, header, "NAXIS3"); // Number of image planes
+    if (!mdok || naxis3 <= 0) {
+        naxis3 = 1;
+    }
+    if (z >= naxis3) {
+        psError(PS_ERR_IO, true, "Specified a plane number (%d) greater than NAXIS3 allows.\n", z);
+        return false;
+    }
+
+    if (!hdu->images) {
+        psError(PS_ERR_IO, true, "No images allocated in HDU.\n");
+        return false;
+    }
+    psImage *image = readout->image; // The image from the HDU to write
+    if (readout->row0 == 0 && readout->col0 == 0 && z == 0) {
+        // Then we can assume that nothing has been written to the FITS file for now
+        if (naxis1 == image->numCols && naxis2 == image->numRows) {
+            // We can write the whole lot at once
+            return psFitsWriteImage(fits, header, image, z, hdu->extname);
+        }
+        // Create a dummy image so we can write something larger than we actually have
+        psImage *dummy = psImageAlloc(naxis1, naxis2, image->type.type); // Dummy image
+        psImageInit(dummy, 0);
+        psImageOverlaySection(dummy, image, 0, 0, "=");
+        bool result = psFitsWriteImage(fits, header, dummy, z, hdu->extname);
+        psFree(dummy);
+        return result;
+    }
+
+    // We can simply update an existing HDU
+    if (hdu->blankPHU && !psFitsMoveExtNum(fits, 0, false)) {
+        psError(PS_ERR_IO, false, "Unable to move to PHU\n");
+        return false;
+    }
+    return psFitsUpdateImage(fits, image, readout->col0, readout->row0, z);
+}
+
+
+bool pmCellWrite(pmCell *cell, psFits *fits, pmConfig *config, bool blank)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    return cellWrite(cell, fits, config, blank, FPA_WRITE_TYPE_IMAGE);
+}
+
+bool pmChipWrite(pmChip *chip, psFits *fits, pmConfig *config, bool blank, bool recurse)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    return chipWrite(chip, fits, config, blank, recurse, FPA_WRITE_TYPE_IMAGE);
+}
+
+bool pmFPAWrite(pmFPA *fpa, psFits *fits, pmConfig *config, bool blank, bool recurse)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    return fpaWrite(fpa, fits, config, blank, recurse, FPA_WRITE_TYPE_IMAGE);
+}
+
+
+bool pmCellWriteMask(pmCell *cell, psFits *fits, pmConfig *config, bool blank)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    return cellWrite(cell, fits, config, blank, FPA_WRITE_TYPE_MASK);
+}
+
+bool pmChipWriteMask(pmChip *chip, psFits *fits, pmConfig *config, bool blank, bool recurse)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    return chipWrite(chip, fits, config, blank, recurse, FPA_WRITE_TYPE_MASK);
+}
+
+bool pmFPAWriteMask(pmFPA *fpa, psFits *fits, pmConfig *config, bool blank, bool recurse)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    return fpaWrite(fpa, fits, config, blank, recurse, FPA_WRITE_TYPE_MASK);
+}
+
+
+bool pmCellWriteWeight(pmCell *cell, psFits *fits, pmConfig *config, bool blank)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    return cellWrite(cell, fits, config, blank, FPA_WRITE_TYPE_WEIGHT);
+}
+
+bool pmChipWriteWeight(pmChip *chip, psFits *fits, pmConfig *config, bool blank, bool recurse)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    return chipWrite(chip, fits, config, blank, recurse, FPA_WRITE_TYPE_WEIGHT);
+}
+
+bool pmFPAWriteWeight(pmFPA *fpa, psFits *fits, pmConfig *config, bool blank, bool recurse)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    return fpaWrite(fpa, fits, config, blank, recurse, FPA_WRITE_TYPE_WEIGHT);
+}
+
+
+int pmCellWriteTable(psFits *fits, const pmCell *cell, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, 0);
+    PS_ASSERT_PTR_NON_NULL(fits, 0);
+    PS_ASSERT_STRING_NON_EMPTY(name, 0);
+
+    const char *chipName = psMetadataLookupStr(NULL, cell->parent->concepts, "CHIP.NAME"); // Name of chip
+    const char *cellName = psMetadataLookupStr(NULL, cell->concepts, "CELL.NAME"); // Name of cell
+
+    psArray *table = psMetadataLookupPtr(NULL, cell->analysis, name); // The FITS table
+    if (!table) {
+        // We wrote everything we could find
+        return 0;
+    }
+
+    psString headerName = NULL;         // Name for header in analysis metadata
+    psStringAppend(&headerName, "%s.HEADER", name);
+    psMetadata *header = psMetadataLookupMetadata(NULL, cell->analysis, headerName); // The FITS header
+    psFree(headerName);
+
+    psString extname = NULL;            // Extension name
+    psStringAppend(&extname, "%s_%s_%s", name, chipName, cellName);
+
+    // XXX Could do a table lookup from the camera format, in case the input file isn't laid out with
+    // NAME_CHIP_CELL extension names --- use these as keys, and the value as the proper extension name.
+    // Allow interpolation of concepts, e.g., "{CHIP.NAME}" --> "ccd13".
+
+    if (!psFitsWriteTable(fits, header, table, extname)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to write table from chip %s, cell %s to extension %s\n",
+                chipName, cellName, extname);
+        psFree(extname);
+        return 0;
+    }
+
+    psFree(extname);
+    return 1;
+}
+
+
+int pmChipWriteTable(psFits *fits, const pmChip *chip, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, 0);
+    PS_ASSERT_PTR_NON_NULL(fits, 0);
+    PS_ASSERT_STRING_NON_EMPTY(name, 0);
+
+    int numWrite = 0;                    // Number of reads
+    psArray *cells = chip->cells;       // Array of cells
+    for (int i = 0; i < cells->n; i++) {
+        pmCell *cell = cells->data[i];  // Cell of interest
+        numWrite += pmCellWriteTable(fits, cell, name);
+    }
+
+    return numWrite;
+}
+
+
+int pmFPAWriteTable(psFits *fits, const pmFPA *fpa, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, 0);
+    PS_ASSERT_PTR_NON_NULL(fits, 0);
+    PS_ASSERT_STRING_NON_EMPTY(name, 0);
+
+    int numWrite = 0;                    // Number of reads
+    psArray *chips = fpa->chips;        // Array of chips
+    for (int i = 0; i < chips->n; i++) {
+        pmChip *chip = chips->data[i];  // Chip of interest
+        numWrite += pmChipWriteTable(fits, chip, name);
+    }
+
+    return numWrite;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAWrite.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAWrite.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAWrite.h	(revision 22158)
@@ -0,0 +1,171 @@
+/* @file pmFPAWrite.h
+ * @brief Write FPA components to a FITS file
+ *
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-06-17 22:16:38 $
+ * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FPA_WRITE_H
+#define PM_FPA_WRITE_H
+
+#include <pmConfig.h>
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+/// Write a readout incrementally
+///
+/// Writes a readout to a FITS file, perhaps incrementally (if it has been read in using pmReadoutReadNext).
+/// Relies on the FITS header to specify how many image planes there are, and the width and height.
+bool pmReadoutWriteNext(pmReadout *readout, ///< Readout to write
+                        psFits *fits,   ///<  FITS file to which to write
+                        int z           ///<  Image plane to write
+                       );
+
+/// Write a cell to a FITS file
+///
+/// Generates CELL.TRIMSEC, CELL.BIASSEC and the HDU pixels if required.  A blank (i.e., image-less header) is
+/// written only if specifically requested.  Writes the concepts to the various locations, and then the HDU to
+/// the FITS file.  This function should be called at the beginning of the output cell loop with blank=true in
+/// order to produce the correct file structure.
+bool pmCellWrite(pmCell *cell,          ///<  Cell to write
+                 psFits *fits,          ///<  FITS file to which to write
+                 pmConfig *config,      ///<  Configuration
+                 bool blank             ///<  Write a blank PHU?
+                );
+
+/// Write a chip to a FITS file
+///
+/// Generates CELL.TRIMSEC, CELL.BIASSEC and the HDU pixels if required.  A blank (i.e., image-less header) is
+/// written only if specifically requested.  Writes the concepts to the various locations, and then the HDU to
+/// the FITS file, optionally recursing to lower levels.  This function should be called at the beginning of
+/// the output chip loop with blank=true and recurse=false in order to produce the correct file structure.
+bool pmChipWrite(pmChip *chip,          ///<  Chip to write
+                 psFits *fits,          ///<  FITS file to which to write
+                 pmConfig *config,      ///<  Configuration
+                 bool blank,            ///<  Write a blank PHU?
+                 bool recurse           ///<  Recurse to lower levels?
+                );
+
+/// Write an FPA to a FITS file
+///
+/// Generates CELL.TRIMSEC, CELL.BIASSEC and the HDU pixels if required.  A blank (i.e., image-less header) is
+/// written only if specifically requested.  Writes the concepts to the various locations, and then the HDU to
+/// the FITS file, optionally recursing to lower levels.  This function should be called at the beginning of
+/// the output FPA loop with blank=true and recurse=false in order to produce the correct file structure.
+bool pmFPAWrite(pmFPA *fpa,             ///<  FPA to write
+                psFits *fits,           ///<  FITS file to which to write
+                pmConfig *config,       ///<  Configuration
+                bool blank,             ///<  Write a blank PHU?
+                bool recurse            ///<  Recurse to lower levels?
+               );
+
+/// Write a cell mask to a FITS file
+///
+/// Generates CELL.TRIMSEC, CELL.BIASSEC and the HDU mask pixels if required.  A blank (i.e., image-less
+/// header) is written only if specifically requested.  Writes the concepts to the various locations, and then
+/// the HDU mask to the FITS file.  This function should be called at the beginning of the output cell loop
+/// with blank=true in order to produce the correct file structure.
+bool pmCellWriteMask(pmCell *cell,      ///<  Cell to write
+                     psFits *fits,      ///<  FITS file to which to write
+                     pmConfig *config,  ///<  Configuration
+                     bool blank         ///<  Write a blank PHU?
+                    );
+
+/// Write a chip mask to a FITS file
+///
+/// Generates CELL.TRIMSEC, CELL.BIASSEC and the HDU mask pixels if required.  A blank (i.e., image-less
+/// header) is written only if specifically requested.  Writes the concepts to the various locations, and then
+/// the HDU mask to the FITS file, optionally recursing to lower levels.  This function should be called at
+/// the beginning of the output chip loop with blank=true and recurse=false in order to produce the correct
+/// file structure.
+bool pmChipWriteMask(pmChip *chip,      ///<  Chip to write
+                     psFits *fits,      ///<  FITS file to which to write
+                     pmConfig *config,  ///<  Configuration
+                     bool blank,        ///<  Write a blank PHU?
+                     bool recurse       ///<  Recurse to lower levels?
+                    );
+
+/// Write an FPA mask to a FITS file
+///
+/// Generates CELL.TRIMSEC, CELL.BIASSEC and the HDU mask pixels if required.  A blank (i.e., image-less
+/// header) is written only if specifically requested.  Writes the concepts to the various locations, and then
+/// the HDU mask to the FITS file, optionally recursing to lower levels.  This function should be called at
+/// the beginning of the output FPA loop with blank=true and recurse=false in order to produce the correct
+/// file structure.
+bool pmFPAWriteMask(pmFPA *fpa,         ///<  FPA to write
+                    psFits *fits,       ///<  FITS file to which to write
+                    pmConfig *config,   ///<  Configuration
+                    bool blank,         ///<  Write a blank PHU?
+                    bool recurse        ///<  Recurse to lower levels?
+                   );
+
+/// Write a cell weight to a FITS file
+///
+/// Generates CELL.TRIMSEC, CELL.BIASSEC and the HDU weight pixels if required.  A blank (i.e., image-less
+/// header) is written only if specifically requested.  Writes the concepts to the various locations, and then
+/// the HDU weight to the FITS file.  This function should be called at the beginning of the output cell loop
+/// with blank=true in order to produce the correct file structure.
+bool pmCellWriteWeight(pmCell *cell,    ///<  Cell to write
+                       psFits *fits,    ///<  FITS file to which to write
+                       pmConfig *config, ///<  Configuration
+                       bool blank       ///<  Write a blank PHU?
+                      );
+
+/// Write a chip weight to a FITS file
+///
+/// Generates CELL.TRIMSEC, CELL.BIASSEC and the HDU weight pixels if required.  A blank (i.e., image-less
+/// header) is written only if specifically requested.  Writes the concepts to the various locations, and then
+/// the HDU weight to the FITS file, optionally recursing to lower levels.  This function should be called at
+/// the beginning of the output chip loop with blank=true and recurse=false in order to produce the correct
+/// file structure.
+bool pmChipWriteWeight(pmChip *chip,    ///<  Chip to write
+                       psFits *fits,    ///<  FITS file to which to write
+                       pmConfig *config, ///<  Configuration
+                       bool blank,      ///<  Write a blank PHU?
+                       bool recurse     ///<  Recurse to lower levels?
+                      );
+
+/// Write an FPA weight to a FITS file
+///
+/// Generates CELL.TRIMSEC, CELL.BIASSEC and the HDU weight pixels if required.  A blank (i.e., image-less
+/// header) is written only if specifically requested.  Writes the concepts to the various locations, and then
+/// the HDU weight to the FITS file, optionally recursing to lower levels.  This function should be called at
+/// the beginning of the output FPA loop with blank=true and recurse=false in order to produce the correct
+/// file structure.
+bool pmFPAWriteWeight(pmFPA *fpa,       ///<  FPA to write
+                      psFits *fits,     ///<  FITS file to which to write
+                      pmConfig *config, ///<  Configuration
+                      bool blank,       ///<  Write a blank PHU?
+                      bool recurse      ///<  Recurse to lower levels?
+                     );
+
+
+/// Write a FITS table from the cell's analysis metadata.
+///
+/// The FITS table (a psArray of psMetadatas) from the cell's analysis metadata (under "name") is written to
+/// the FITS file, at an extension specified by the name, chip name and cell name ("NAME_CHIP_CELL").  If a
+/// header is present in the analysis metadata ("name.HEADER"), then it is written also.
+int pmCellWriteTable(psFits *fits,      ///< FITS file to which to write
+                     const pmCell *cell, ///< Cell containing FITS table in the analysis metadata
+                     const char *name   ///< Name for the table data, and the extension name
+                    );
+
+int pmChipWriteTable(psFits *fits,      ///< FITS file to which to write
+                     const pmChip *chip, ///< Chip containing cells with tables to write
+                     const char *name   ///< Name for the table data, and the extension name
+                    );
+
+int pmFPAWriteTable(psFits *fits,       ///< FITS file to which to write
+                    const pmFPA *fpa,   ///< FPA containing cells with tables to write
+                    const char *name    ///< Name for the table data, and the extension name
+                   );
+
+// XXX better name, please
+bool pmFPAUpdateNames(pmFPA *fpa, pmChip *chip, pmCell *cell);
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPA_JPEG.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPA_JPEG.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPA_JPEG.c	(revision 22158)
@@ -0,0 +1,225 @@
+/** @file  pmFPA_JPEG.c
+ *
+ * This file contains functions to write JPEG images.
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.23 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-09-21 00:02:11 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/*****************************************************************************/
+/* INCLUDE FILES                                                             */
+/*****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>            /* for strn?casecmp */
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+#include "pmFPA_JPEG.h"
+
+
+bool pmFPAviewWriteJPEG(const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    pmFPA *fpa = file->fpa;
+
+    if (view->chip == -1) {
+        pmFPAWriteJPEG (fpa, view, file, config);
+        return true;
+    }
+
+    if (view->chip >= fpa->chips->n) {
+        return false;
+    }
+    pmChip *chip = fpa->chips->data[view->chip];
+
+    if (view->cell == -1) {
+        pmChipWriteJPEG (chip, view, file, config);
+        return true;
+    }
+
+    if (view->cell >= chip->cells->n) {
+        return false;
+    }
+    pmCell *cell = chip->cells->data[view->cell];
+
+    if (view->readout == -1) {
+        pmCellWriteJPEG (cell, view, file, config);
+        return true;
+    }
+
+    if (view->readout >= cell->readouts->n) {
+        return false;
+    }
+    pmReadout *readout = cell->readouts->data[view->readout];
+
+    pmReadoutWriteJPEG (readout, view, file, config);
+    return true;
+}
+
+// read in all chip-level JPEG files for this FPA
+bool pmFPAWriteJPEG (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+
+        pmChip *chip = fpa->chips->data[i];
+        pmChipWriteJPEG (chip, view, file, config);
+    }
+    return true;
+}
+
+// read in all cell-level JPEG files for this chip
+bool pmChipWriteJPEG (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    for (int i = 0; i < chip->cells->n; i++) {
+
+        pmCell *cell = chip->cells->data[i];
+        pmCellWriteJPEG (cell, view, file, config);
+    }
+    return true;
+}
+
+// read in all readout-level JPEG files for this cell
+bool pmCellWriteJPEG (pmCell *cell, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    for (int i = 0; i < cell->readouts->n; i++) {
+
+        pmReadout *readout = cell->readouts->data[i];
+        pmReadoutWriteJPEG (readout, view, file, config);
+    }
+    return true;
+}
+
+// write JPEG image for readout
+// note that this function will try as hard a possible to write out a jpeg.  it will not fail
+// just because the values are in a poor range.  it is more convenient to know you are getting
+// a jpeg which is weird than to fail to get the file at all.
+bool pmReadoutWriteJPEG (pmReadout *readout, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    bool status;
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    if (file->type != PM_FPA_FILE_JPEG) {
+        psError(PS_ERR_UNKNOWN, true, "warning: type mismatch");
+        return false;
+    }
+
+    psTrace("psModules.camera", 3, "writing jpeg for readout %zd\n", (size_t) readout);
+
+    psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, "PPIMAGE");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "missing recipe PPIMAGE in config data");
+        return false;
+    }
+
+    psMetadata *options = psMetadataLookupMetadata(&status, recipe, file->name);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "missing %s options in PPIMAGE recipe", file->name);
+        return false;
+    }
+
+    float min = 0;
+    float max = 0;                 // Minimum and maximum for stretch
+    float mean = 0;
+    float delta = 0;
+
+    // measure the image statistics for scaling
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+    psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN);
+    stats->nSubsample = 10000;
+    if (!psImageBackground(stats, NULL, readout->image, NULL, 0, rng)) {
+        psStats *statsAlt = psStatsAlloc(PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
+        stats->nSubsample = 10000;
+        if (!psImageBackground(stats, NULL, readout->image, NULL, 0, rng)) {
+            psLogMsg("jpeg", PS_LOG_WARN, "Unable to measure statistics for image, writing blank jpeg\n");
+            mean = 0;
+            delta = 1;
+        } else {
+            mean = statsAlt->sampleMean;
+            delta = 2*statsAlt->sampleStdev;
+        }
+        psFree(statsAlt);
+    } else {
+        mean = stats->robustMedian;
+        delta = stats->robustUQ - stats->robustLQ;
+    }
+    psFree(rng);
+    psFree(stats);
+
+    char *colormapName = psMemIncrRefCounter (psMetadataLookupStr (NULL, options, "COLORMAP"));
+    if (!colormapName)
+        colormapName = psStringCopy ("-greyscale");
+    char *mode = psMemIncrRefCounter (psMetadataLookupStr (NULL, options, "SCALE.MODE"));
+    if (!mode)
+        mode = psStringCopy ("RANGE");
+    float fmin = psMetadataLookupF32 (&status, options, "SCALE.MIN");
+    if (!status)
+        fmin = -3.0;
+    float fmax = psMetadataLookupF32 (&status, options, "SCALE.MAX");
+    if (!status)
+        fmax = +6.0;
+
+    if (!strcasecmp (mode, "RANGE")) {
+        min = mean + fmin*delta;
+        max = mean + fmax*delta;
+    }
+    if (!strcasecmp (mode, "FRACTION")) {
+        min = fmin*mean;
+        max = fmax*mean;
+    }
+    if (!strcasecmp (mode, "VALUE")) {
+        min = fmin;
+        max = fmax;
+    }
+
+    if (!isfinite(min) || !isfinite(max)) {
+        psLogMsg("jpeg", PS_LOG_WARN, "The stretch parameters are not both finite, writing blank jpeg\n");
+        min = 0;
+        max = 1;
+    }
+
+    psImageJpegColormap *map = psImageJpegColormapSet (NULL, colormapName);
+    if (!map) {
+        map = psImageJpegColormapSet (NULL, "-greyscale");
+    }
+
+    psImageJpeg (map, readout->image, file->filename, min, max);
+
+    psFree(map);
+    psFree(colormapName);
+    psFree(mode);
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPA_JPEG.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPA_JPEG.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPA_JPEG.h	(revision 22158)
@@ -0,0 +1,24 @@
+/* @file  pmFPAview.h
+ * @brief Tools to manipulate the FPA structure elements.
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-04-14 03:22:47 $
+ * Copyright 2004-2005 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FPA_JPEG_H
+#define PM_FPA_JPEG_H
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+bool pmFPAviewWriteJPEG (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmFPAWriteJPEG (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmChipWriteJPEG (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmCellWriteJPEG (pmCell *cell, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmReadoutWriteJPEG (pmReadout *readout, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+
+/// @}
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPA_MANAPLOT.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPA_MANAPLOT.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPA_MANAPLOT.c	(revision 22158)
@@ -0,0 +1,176 @@
+/** @file  pmFPA_MANAPLOT.c
+ *
+ * This file contains functions to write MANAPLOT images.
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-06-10 20:58:28 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/*****************************************************************************/
+/* INCLUDE FILES                                                             */
+/*****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPAfile.h"
+#include "pmFPAview.h"
+#include "pmFPA_MANAPLOT.h"
+
+
+bool pmFPAviewWriteMANAPLOT(const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    pmFPA *fpa = file->fpa;
+
+    if (view->chip == -1) {
+        pmFPAWriteMANAPLOT (fpa, view, file, config);
+        return true;
+    }
+
+    if (view->chip >= fpa->chips->n) {
+        return false;
+    }
+    pmChip *chip = fpa->chips->data[view->chip];
+
+    if (view->cell == -1) {
+        pmChipWriteMANAPLOT (chip, view, file, config);
+        return true;
+    }
+
+    if (view->cell >= chip->cells->n) {
+        return false;
+    }
+    pmCell *cell = chip->cells->data[view->cell];
+
+    if (view->readout == -1) {
+        pmCellWriteMANAPLOT (cell, view, file, config);
+        return true;
+    }
+
+    if (view->readout >= cell->readouts->n) {
+        return false;
+    }
+    pmReadout *readout = cell->readouts->data[view->readout];
+
+    pmReadoutWriteMANAPLOT (readout, view, file, config);
+    return true;
+}
+
+// read in all chip-level MANAPLOT files for this FPA
+bool pmFPAWriteMANAPLOT (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+
+        pmChip *chip = fpa->chips->data[i];
+        pmChipWriteMANAPLOT (chip, view, file, config);
+    }
+    return true;
+}
+
+// read in all cell-level MANAPLOT files for this chip
+bool pmChipWriteMANAPLOT (pmChip *chip, const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    for (int i = 0; i < chip->cells->n; i++) {
+
+        pmCell *cell = chip->cells->data[i];
+        pmCellWriteMANAPLOT (cell, view, file, config);
+    }
+    return true;
+}
+
+// read in all readout-level MANAPLOT files for this cell
+bool pmCellWriteMANAPLOT (pmCell *cell, const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    for (int i = 0; i < cell->readouts->n; i++) {
+
+        pmReadout *readout = cell->readouts->data[i];
+        pmReadoutWriteMANAPLOT (readout, view, file, config);
+    }
+    return true;
+}
+
+// read in all readout-level Objects files for this cell
+bool pmReadoutWriteMANAPLOT (pmReadout *readout, const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    if (file->type != PM_FPA_FILE_MANAPLOT) {
+        psError(PS_ERR_UNKNOWN, true, "warning: type mismatch");
+        return false;
+    }
+
+    // XXX does not have to be a mana script...
+    // this function will call a mana script of the form:
+    // scriptname (input) (output)
+    // scriptname : extname
+    // input : filextra
+    // output : filerule
+
+    bool create = file->mode == PM_FPA_MODE_WRITE ? true : false;
+
+    psString tmpName;
+    tmpName = pmFPAfileNameFromRule (file->filextra, file, view);
+    psString input = pmConfigConvertFilename (tmpName, config, create, false);
+    psFree (tmpName);
+
+    tmpName = pmFPAfileNameFromRule (file->filerule, file, view);
+    psString output = pmConfigConvertFilename (tmpName, config, create, false);
+    psFree (tmpName);
+
+    tmpName = pmFPAfileNameFromRule (file->extname, file, view);
+    psString script = pmConfigConvertFilename (tmpName, config, create, false);
+    psFree (tmpName);
+
+    psString line = NULL;
+    psStringAppend (&line, "%s %s %s", script, input, output);
+
+    // capture the stdout and stderr?
+    // XXX use psPipe instead?
+    int status = system (line);
+    if (status == -1) {
+        psError(PS_ERR_UNKNOWN, true, "fork failure: %s", script);
+        return false;
+    }
+    if (WEXITSTATUS(status) != 0) {
+        psError(PS_ERR_UNKNOWN, true, "error running: %s", script);
+        return false;
+    }
+
+    psFree(line);
+    psFree(input);
+    psFree(output);
+    psFree(script);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPA_MANAPLOT.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPA_MANAPLOT.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPA_MANAPLOT.h	(revision 22158)
@@ -0,0 +1,24 @@
+/* @file  pmFPAview.h
+ * @brief Tools to manipulate the FPA structure elements.
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-01-24 02:54:14 $
+ * Copyright 2004-2005 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FPA_MANAPLOT_H
+#define PM_FPA_MANAPLOT_H
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+bool pmFPAviewWriteMANAPLOT (const pmFPAview *view, pmFPAfile *file, pmConfig *config);
+bool pmFPAWriteMANAPLOT (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, pmConfig *config);
+bool pmChipWriteMANAPLOT (pmChip *chip, const pmFPAview *view, pmFPAfile *file, pmConfig *config);
+bool pmCellWriteMANAPLOT (pmCell *cell, const pmFPAview *view, pmFPAfile *file, pmConfig *config);
+bool pmReadoutWriteMANAPLOT (pmReadout *readout, const pmFPAview *view, pmFPAfile *file, pmConfig *config);
+
+/// @}
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfile.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfile.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfile.c	(revision 22158)
@@ -0,0 +1,565 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>            /* for strn?casecmp */
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+#include "pmFPACopy.h"
+#include "pmConcepts.h"
+
+static void pmFPAfileFree(pmFPAfile *file)
+{
+    if (!file) {
+	return;
+    }
+
+    psTrace ("pmFPAfileFree", 5, "freeing %s\n", file->name);
+    psFree (file->fpa);
+    psFree (file->src);
+    psFree (file->readout);
+    psFree (file->names);
+
+    psFree (file->camera);
+    psFree (file->cameraName);
+    psFree (file->format);
+    psFree (file->formatName);
+    psFree (file->name);
+
+    if (file->fits != NULL) {
+	psFitsClose (file->fits);
+    }
+    psFree(file->compression);
+    psFree(file->options);
+
+    psFree (file->filerule);
+
+    psFree (file->filesrc);
+    psFree (file->detrend);
+
+    psFree (file->filename);
+    psFree (file->extname);
+
+    return;
+}
+
+pmFPAfile *pmFPAfileAlloc()
+{
+    pmFPAfile *file = psAlloc(sizeof(pmFPAfile));
+    psMemSetDeallocator(file, (psFreeFunc) pmFPAfileFree);
+
+    file->wrote_phu = false;
+    file->readout = NULL;
+    file->header = NULL;
+
+    file->fileLevel = PM_FPA_LEVEL_NONE;
+    file->dataLevel = PM_FPA_LEVEL_NONE;
+    file->freeLevel = PM_FPA_LEVEL_NONE;
+    file->mosaicLevel = PM_FPA_LEVEL_NONE;
+
+    file->type = PM_FPA_FILE_NONE;
+    file->mode = PM_FPA_MODE_NONE;
+    file->state = PM_FPA_STATE_CLOSED;
+
+    file->fpa = NULL;
+    file->fits = NULL;
+    file->compression = NULL;
+    file->options = NULL;
+    file->names = psMetadataAlloc();
+
+    file->camera = NULL;
+    file->cameraName = NULL;
+    file->format = NULL;
+    file->formatName = NULL;
+    file->name = NULL;
+
+    file->filerule = NULL;
+
+    file->filename = NULL;
+    file->extname  = NULL;
+
+    file->filesrc = NULL;
+    file->detrend = NULL;
+
+    file->xBin = 1;
+    file->yBin = 1;
+    file->src = NULL;
+
+    file->save = false;
+
+    return file;
+}
+
+// select the readout from the named pmFPAfile; if the named file does not exist,
+pmReadout *pmFPAfileThisReadout (psMetadata *files, const pmFPAview *view, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(files, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(name, false);
+    PS_ASSERT_INT_POSITIVE(strlen(name), false);
+
+    bool status;
+
+    pmFPAfile *file = psMetadataLookupPtr (&status, files, name);
+    if (file == NULL) {
+	return NULL;
+    }
+
+    // internal files have the readout as a separate element:
+    if (file->mode == PM_FPA_MODE_INTERNAL) {
+	return file->readout;
+    }
+
+    pmReadout *readout = pmFPAviewThisReadout (view, file->fpa);
+    return readout;
+}
+
+// select the cell from the named pmFPAfile; if the named file does not exist,
+pmCell *pmFPAfileThisCell (psMetadata *files, const pmFPAview *view, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(files, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(name, false);
+    PS_ASSERT_INT_POSITIVE(strlen(name), false);
+
+    bool status;
+
+    pmFPAfile *file = psMetadataLookupPtr (&status, files, name);
+    if (file == NULL) {
+	return NULL;
+    }
+
+    // internal files have the readout as a separate element:
+    if (file->mode == PM_FPA_MODE_INTERNAL) {
+	return NULL;
+    }
+
+    pmCell *cell = pmFPAviewThisCell(view, file->fpa);
+    return cell;
+}
+
+// select the readout from the named pmFPAfile; if the named file does not exist,
+pmChip *pmFPAfileThisChip (psMetadata *files, const pmFPAview *view, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(files, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(name, false);
+    PS_ASSERT_INT_POSITIVE(strlen(name), false);
+
+    bool status;
+
+    pmFPAfile *file = psMetadataLookupPtr (&status, files, name);
+    if (file == NULL) {
+	return NULL;
+    }
+
+    // internal files have the readout as a separate element:
+    if (file->mode == PM_FPA_MODE_INTERNAL) {
+	return NULL;
+    }
+
+    pmChip *chip = pmFPAviewThisChip (view, file->fpa);
+    return chip;
+}
+
+psString pmFPANameFromRule(const char *rule, const pmFPA *fpa, const pmFPAview *view)
+{
+    PS_ASSERT_STRING_NON_EMPTY(rule, NULL);
+    PS_ASSERT_PTR_NON_NULL(view, NULL);
+    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
+
+    psString newName = NULL;            // New name, to be returned
+    newName = psStringCopy(rule);
+
+    if (strstr (newName, "{FPA.OBS}") != NULL) {
+	char *name = psMetadataLookupStr (NULL, fpa->concepts, "FPA.OBS");
+	if (name != NULL) {
+	    psStringSubstitute(&newName, name, "{FPA.OBS}");
+	}
+    }
+    if (strstr (newName, "{FPA.NAME}") != NULL) {
+	char *name = psMetadataLookupStr (NULL, fpa->concepts, "FPA.NAME");
+	if (name != NULL) {
+	    psStringSubstitute(&newName, name, "{FPA.NAME}");
+	}
+    }
+    if (strstr (newName, "{CHIP.NAME}") != NULL) {
+	pmChip *chip = pmFPAviewThisChip (view, fpa);
+	if (chip != NULL) {
+	    char *name = psMetadataLookupStr (NULL, chip->concepts, "CHIP.NAME");
+	    if (name != NULL) {
+		psStringSubstitute(&newName, name, "{CHIP.NAME}");
+	    }
+	}
+    }
+    if (strstr (newName, "{CHIP.ID}") != NULL) {
+	pmChip *chip = pmFPAviewThisChip (view, fpa);
+	if (chip != NULL) {
+	    char *name = psMetadataLookupStr (NULL, chip->concepts, "CHIP.ID");
+	    if (name != NULL) {
+		psStringSubstitute(&newName, name, "{CHIP.ID}");
+	    }
+	}
+    }
+    if (strstr (newName, "{CHIP.N}") != NULL) {
+	char *name = NULL;
+	if (view->chip < 0) {
+	    psStringAppend (&name, "XX");
+	} else {
+	    psStringAppend (&name, "%02d", view->chip);
+	}
+	psStringSubstitute(&newName, name, "{CHIP.N}");
+	psFree (name);
+    }
+    if (strstr (newName, "{CELL.NAME}") != NULL) {
+	pmCell *cell = pmFPAviewThisCell (view, fpa);
+	if (cell != NULL) {
+	    char *name = psMetadataLookupStr (NULL, cell->concepts, "CELL.NAME");
+	    if (name != NULL) {
+		psStringSubstitute(&newName, name, "{CELL.NAME}");
+	    }
+	}
+    }
+    if (strstr (newName, "{CELL.N}") != NULL) {
+	char *name = NULL;
+	if (view->cell < 0) {
+	    psStringAppend (&name, "XX");
+	} else {
+	    psStringAppend (&name, "%02d", view->cell);
+	}
+	psStringSubstitute(&newName, name, "{CELL.N}");
+    }
+    if (strstr (newName, "{EXTNAME}") != NULL) {
+	pmHDU *hdu = pmFPAviewThisHDU (view, fpa);
+	if (hdu->extname && *hdu->extname) {
+	    psStringSubstitute(&newName, hdu->extname, "{EXTNAME}");
+	}
+    }
+    if (strstr (newName, "{FILTER}") != NULL) {
+	if (fpa != NULL) {
+	    char *name = psMetadataLookupStr (NULL, fpa->concepts, "FPA.FILTER");
+	    if (name && *name) {
+		psStringSubstitute(&newName, name, "{FILTER}");
+	    }
+	}
+    }
+    if (strstr (newName, "{FILTER.ID}") != NULL) {
+	if (fpa != NULL) {
+	    char *name = psMetadataLookupStr (NULL, fpa->concepts, "FPA.FILTERID");
+	    if (name && *name) {
+		psStringSubstitute(&newName, name, "{FILTER.ID}");
+	    }
+	}
+    }
+    if (strstr (newName, "{CAMERA}") != NULL) {
+	if (fpa != NULL) {
+	    char *name = psMetadataLookupStr (NULL, fpa->concepts, "FPA.INSTRUMENT");
+	    if (name && *name) {
+		psStringSubstitute(&newName, name, "{CAMERA}");
+	    }
+	}
+    }
+    if (strstr (newName, "{INSTRUMENT}") != NULL) {
+	if (fpa != NULL) {
+	    char *name = psMetadataLookupStr (NULL, fpa->concepts, "FPA.INSTRUMENT");
+	    if (name && *name) {
+		psStringSubstitute(&newName, name, "{INSTRUMENT}");
+	    }
+	}
+    }
+    if (strstr (newName, "{DETECTOR}") != NULL) {
+	if (fpa != NULL) {
+	    char *name = psMetadataLookupStr (NULL, fpa->concepts, "FPA.DETECTOR");
+	    if (name && *name) {
+		psStringSubstitute(&newName, name, "{DETECTOR}");
+	    }
+	}
+    }
+    if (strstr (newName, "{TELESCOPE}") != NULL) {
+	if (fpa != NULL) {
+	    char *name = psMetadataLookupStr (NULL, fpa->concepts, "FPA.TELESCOPE");
+	    if (name && *name) {
+		psStringSubstitute(&newName, name, "{TELESCOPE}");
+	    }
+	}
+    }
+    return newName;
+}
+
+// select the rule from the camera configuration, perform substitutions as needed
+psString pmFPAfileNameFromRule(const char *rule, const pmFPAfile *file, const pmFPAview *view)
+{
+    PS_ASSERT_PTR_NON_NULL(rule, NULL);
+    PS_ASSERT_INT_POSITIVE(strlen(rule), NULL);
+    PS_ASSERT_PTR_NON_NULL(file, NULL);
+    PS_ASSERT_PTR_NON_NULL(view, NULL);
+
+    psString newRule = NULL;            // Rule to pass on to pmFPANameFromRule
+    newRule = psStringCopy(rule);
+
+    if (strstr(newRule, "{OUTPUT}") != NULL) {
+	char *name = psMetadataLookupStr(NULL, file->names, "OUTPUT");
+	if (name) {
+	    psStringSubstitute(&newRule, name, "{OUTPUT}");
+	}
+    }
+
+    psString newName = pmFPANameFromRule(newRule, file->fpa, view); // New name, to be returned
+    psFree(newRule);
+
+    return newName;
+}
+
+// given an already-opened fits file, write the components corresponding
+// to the specified view
+bool pmFPAfileCopyView (pmFPA *out, pmFPA *in, const pmFPAview *view)
+{
+    PS_ASSERT_PTR_NON_NULL(out, false);
+    PS_ASSERT_PTR_NON_NULL(in, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    // pmFPAWrite takes care of all PHUs as needed
+    if (view->chip == -1) {
+	pmFPACopy (out, in);
+	return true;
+    }
+    if (view->chip >= in->chips->n) {
+	psError(PS_ERR_IO, true, "Requested chip == %d >= in->chips->n == %ld", view->chip, in->chips->n);
+	return false;
+    }
+    pmChip *inChip = in->chips->data[view->chip];
+    pmChip *outChip = out->chips->data[view->chip];
+
+    if (view->cell == -1) {
+	pmChipCopy (outChip, inChip);
+	return true;
+    }
+    if (view->cell >= inChip->cells->n) {
+	psError(PS_ERR_IO, true, "Requested cell == %d>= inChip->cells->n == %ld",
+		view->cell, inChip->cells->n);
+	return false;
+    }
+    pmCell *inCell = inChip->cells->data[view->cell];
+    pmCell *outCell = outChip->cells->data[view->cell];
+
+    if (view->readout == -1) {
+	pmCellCopy (outCell, inCell);
+	return true;
+    }
+    psError(PS_ERR_UNKNOWN, true, "Returning false");
+    return false;
+
+    // XXX add readout / segment equivalents
+}
+
+// given an already-opened fits file, write the components corresponding
+// to the specified view
+bool pmFPAfileCopyStructureView (pmFPA *out, const pmFPA *in, int xBin, int yBin, const pmFPAview *view)
+{
+    bool status;
+    PS_ASSERT_PTR_NON_NULL(out, false);
+    PS_ASSERT_PTR_NON_NULL(in, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    // XXX this should be smarter (ie, only copy concepts from the current chips)
+    // but such a call is needed, so re-copy stuff rather than no copy
+    pmFPACopyConcepts (out, in);
+
+    // pmFPAWrite takes care of all PHUs as needed
+    if (view->chip == -1) {
+	status = pmFPACopyStructure (out, in, xBin, yBin);
+	return status;
+    }
+    if (view->chip >= in->chips->n) {
+	psError(PS_ERR_IO, true, "Requested chip == %d >= in->chips->n == %ld", view->chip, in->chips->n);
+	return false;
+    }
+    pmChip *inChip = in->chips->data[view->chip];
+    pmChip *outChip = out->chips->data[view->chip];
+
+    if (view->cell == -1) {
+	status = pmChipCopyStructure (outChip, inChip, xBin, yBin);
+	return status;
+    }
+    if (view->cell >= inChip->cells->n) {
+	psError(PS_ERR_IO, true, "Requested cell == %d>= inChip->cells->n == %ld",
+		view->cell, inChip->cells->n);
+	return false;
+    }
+    pmCell *inCell = inChip->cells->data[view->cell];
+    pmCell *outCell = outChip->cells->data[view->cell];
+
+    status = pmCellCopyStructure (outCell, inCell, xBin, yBin);
+    return status;
+}
+
+pmFPAfileType pmFPAfileTypeFromString(const char *type)
+{
+    PS_ASSERT_STRING_NON_EMPTY(type, PM_FPA_FILE_NONE);
+
+    if (!strcasecmp (type, "SX"))     {
+	return PM_FPA_FILE_SX;
+    }
+    if (!strcasecmp (type, "OBJ"))     {
+	return PM_FPA_FILE_OBJ;
+    }
+    if (!strcasecmp (type, "CMP"))     {
+	return PM_FPA_FILE_CMP;
+    }
+    if (!strcasecmp (type, "CMF"))     {
+	return PM_FPA_FILE_CMF;
+    }
+    if (!strcasecmp (type, "RAW"))     {
+	return PM_FPA_FILE_RAW;
+    }
+    if (!strcasecmp (type, "IMAGE"))     {
+	return PM_FPA_FILE_IMAGE;
+    }
+    if (!strcasecmp (type, "PSF"))     {
+	return PM_FPA_FILE_PSF;
+    }
+    if (!strcasecmp (type, "JPEG"))     {
+	return PM_FPA_FILE_JPEG;
+    }
+    if (!strcasecmp (type, "KAPA"))     {
+	return PM_FPA_FILE_KAPA;
+    }
+    if (!strcasecmp (type, "MASK"))     {
+	return PM_FPA_FILE_MASK;
+    }
+    if (!strcasecmp (type, "WEIGHT"))     {
+	return PM_FPA_FILE_WEIGHT;
+    }
+    if (!strcasecmp (type, "FRINGE")) {
+	return PM_FPA_FILE_FRINGE;
+    }
+    if (!strcasecmp (type, "DARK"))     {
+	return PM_FPA_FILE_DARK;
+    }
+    if (!strcasecmp (type, "HEADER"))     {
+	return PM_FPA_FILE_HEADER;
+    }
+    // deprecate this?
+    if (!strcasecmp (type, "ASTROM"))     {
+	return PM_FPA_FILE_ASTROM_MODEL;
+    }
+    if (!strcasecmp (type, "ASTROM.MODEL"))     {
+	return PM_FPA_FILE_ASTROM_MODEL;
+    }
+    if (!strcasecmp (type, "ASTROM.REFSTARS"))     {
+	return PM_FPA_FILE_ASTROM_REFSTARS;
+    }
+
+    return PM_FPA_FILE_NONE;
+}
+
+const char *pmFPAfileStringFromType(pmFPAfileType type)
+{
+    switch (type) {
+      case PM_FPA_FILE_SX:
+	return ("SX");
+      case PM_FPA_FILE_OBJ:
+	return ("OBJ");
+      case PM_FPA_FILE_CMP:
+	return ("CMP");
+      case PM_FPA_FILE_CMF:
+	return ("CMF");
+      case PM_FPA_FILE_RAW:
+	return ("RAW");
+      case PM_FPA_FILE_IMAGE:
+	return ("IMAGE");
+      case PM_FPA_FILE_PSF:
+	return ("PSF");
+      case PM_FPA_FILE_JPEG:
+	return ("JPEG");
+      case PM_FPA_FILE_KAPA:
+	return ("KAPA");
+      case PM_FPA_FILE_MASK:
+	return ("MASK");
+      case PM_FPA_FILE_WEIGHT:
+	return ("WEIGHT");
+      case PM_FPA_FILE_FRINGE:
+	return ("FRINGE");
+      case PM_FPA_FILE_DARK:
+	return("DARK");
+      case PM_FPA_FILE_HEADER:
+	return ("HEADER");
+      case PM_FPA_FILE_ASTROM_MODEL:
+	return ("ASTROM.MODEL");
+      case PM_FPA_FILE_ASTROM_REFSTARS:
+	return ("ASTROM.REFSTARS");
+      default:
+	return ("NONE");
+    }
+    return ("NONE");
+}
+
+
+psArray *pmFPAfileSelect(psMetadata *files, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(files, NULL);
+
+    psList *list = psListAlloc(NULL);   // List of files selected
+
+    psString regex = NULL;              // Regular expression
+    if (name) {
+        if (!psMetadataLookup(files, name)) {
+            psFree (list);
+            return NULL;
+        }
+        psStringAppend(&regex, "^%s$", name);
+    }
+    psMetadataIterator *iter = psMetadataIteratorAlloc(files, PS_LIST_HEAD, regex); // Iterator
+    psFree(regex);
+    psMetadataItem *item;               // Item from iteration
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        pmFPAfile *file = item->data.V; // File of iterest
+        psListAdd(list, PS_LIST_TAIL, file);
+    }
+    psFree(iter);
+
+    psArray *array = psListToArray(list); // Array generated from list
+    psFree(list);
+
+    return array;
+}
+
+pmFPAfile *pmFPAfileSelectSingle(psMetadata *files, const char *name, int num)
+{
+    PS_ASSERT_PTR_NON_NULL(files, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(num, NULL);
+
+    psString regex = NULL;              // Regular expression
+    if (name) {
+        if (!psMetadataLookup(files, name)) {
+            // No files
+            return NULL;
+        }
+        psStringAppend(&regex, "^%s$", name);
+    }
+
+    psMetadataIterator *iter = psMetadataIteratorAlloc(files, PS_LIST_HEAD, regex); // Iterator
+    psFree(regex);
+    psMetadataItem *item;               // Item from iteration
+    int i = 0;                          // Counter
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        if (i++ == num) {
+            psFree(iter);
+            return item->data.V;
+        }
+    }
+    psFree(iter);
+
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to find instance %d of file %s", num, name);
+    return NULL;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfile.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfile.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfile.h	(revision 22158)
@@ -0,0 +1,150 @@
+/* @file  pmFPAview.h
+ * @brief Tools to manipulate the FPA structure elements.
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.30 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-03-18 18:38:14 $
+ * Copyright 2004-2005 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FPA_FILE_H
+#define PM_FPA_FILE_H
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+typedef enum {
+    PM_FPA_BEFORE,
+    PM_FPA_AFTER,
+} pmFPAfilePlace;
+
+typedef enum {
+    PM_FPA_FILE_NONE,
+    PM_FPA_FILE_SX,
+    PM_FPA_FILE_OBJ,
+    PM_FPA_FILE_CMP,
+    PM_FPA_FILE_CMF,
+    PM_FPA_FILE_RAW,
+    PM_FPA_FILE_IMAGE,
+    PM_FPA_FILE_MASK,
+    PM_FPA_FILE_WEIGHT,
+    PM_FPA_FILE_FRINGE,
+    PM_FPA_FILE_DARK,
+    PM_FPA_FILE_PSF,
+    PM_FPA_FILE_JPEG,
+    PM_FPA_FILE_KAPA,
+    PM_FPA_FILE_HEADER,
+    PM_FPA_FILE_ASTROM_MODEL,
+    PM_FPA_FILE_ASTROM_REFSTARS,
+} pmFPAfileType;
+
+typedef enum {
+    PM_FPA_MODE_NONE,
+    PM_FPA_MODE_READ,
+    PM_FPA_MODE_WRITE,
+    PM_FPA_MODE_INTERNAL,
+    PM_FPA_MODE_REFERENCE,
+} pmFPAfileMode;
+
+typedef enum {
+    PM_FPA_STATE_OPEN     = 0x01,
+    PM_FPA_STATE_CLOSED   = 0x02,
+    PM_FPA_STATE_INACTIVE = 0x04,
+} pmFPAfileState;
+
+typedef struct {
+    pmFPAfileMode mode;                 // is this file read, written, or only used internally?
+    pmFPAfileType type;                 // what type of data is read from / written to disk?
+    pmFPAfileState state;               // have we opened the file, etc?
+
+    pmFPALevel fileLevel;               // what level in the FPA hierarchy represents a unique file?
+    pmFPALevel dataLevel;               // at what level do we read/write the data segment? (request by user)
+    pmFPALevel freeLevel;               // at what level do we free the data segment? (set by program)
+    pmFPALevel mosaicLevel;             // at what level is the mosaic?
+
+    pmFPA *fpa;                         // for I/O files, we carry a pointer to the complete fpa
+    psFits *fits;                       // for I/O files of fits type (IMAGE, CMP, CMF) we carry a file handle
+    psFitsCompression *compression;     // Compression for FITS images
+    psFitsOptions *options;             // FITS I/O options
+
+    bool wrote_phu;                     // have we written a PHU for this file?
+    psMetadata *header;                 // pointer (view) to the current hdu header
+
+    pmReadout *readout;                 // for internal files, we only carry a single readout
+
+    psMetadata *names;                  // filenames supplied by the cmdline or detdb are saved here
+
+    char *filerule;                     // rule for constructing a filename when needed
+    char *filesrc;                      // rule to find file in pmFPAfile->names list
+
+    char *name;                         // the name of the rule (useful for debugging / tracing)
+    char *filename;                     // the current name of an active file
+    char *extname;                      // the current name of an active file extension
+
+    pmDetrendSelectResults *detrend;    // Detrend information, from pmDetrendSelect
+
+    bool save;                          // Should the file be saved?
+
+    // the following elements are used for WRITE-mode IMAGE-type pmFPAfiles to inform
+    // the creation of a new image based on an existing image
+    pmFPA *src;                         // if an output FPA, inherit from this FPA
+    int xBin;                           // desired binning in x direction
+    int yBin;                           // desired binning in y direction
+
+    psMetadata *camera;                 // Camera configuration
+    psString cameraName;                // Name of the camera
+    psMetadata *format;                 // Camera format
+    psString formatName;                // name of the camera format
+} pmFPAfile;
+
+// allocate an empty pmFPAfile structure
+pmFPAfile *pmFPAfileAlloc ();
+
+// select the readout from the named pmFPAfile; if the named file does not exist,
+pmReadout *pmFPAfileThisReadout (psMetadata *files, const pmFPAview *view, const char *name);
+
+// select the cell from the named pmFPAfile; if the named file does not exist,
+pmCell *pmFPAfileThisCell (psMetadata *files, const pmFPAview *view, const char *name);
+
+// select the chip from the named pmFPAfile; if the named file does not exist,
+pmChip *pmFPAfileThisChip (psMetadata *files, const pmFPAview *view, const char *name);
+
+// add the specified filename info (value) to the files of the given mode using the given reference name
+bool pmFPAfileAddFileNames (psMetadata *files, char *name, char *value, int mode);
+
+// convert the rule to a name based on the current view
+psString pmFPANameFromRule(const char *rule, const pmFPA *fpa, const pmFPAview *view);
+
+// convert the rule to a name based on the current view
+psString pmFPAfileNameFromRule(const char *rule, const pmFPAfile *file, const pmFPAview *view);
+
+bool pmFPAfileCopyView (pmFPA *out, pmFPA *in, const pmFPAview *view);
+
+bool pmFPAfileCopyStructureView (pmFPA *out, const pmFPA *in, int xBin, int yBin, const pmFPAview *view);
+
+// Return the file type enum from a string
+pmFPAfileType pmFPAfileTypeFromString(const char *type);
+
+// Return the file type as a string
+const char *pmFPAfileStringFromType(pmFPAfileType type);
+
+/// Select files with the same name from the list of files
+///
+/// Returns all files if name is NULL.
+psArray *pmFPAfileSelect(psMetadata *files, ///< All files
+                         const char *name ///< Name of file(s) to return, or NULL for all
+    );
+
+/// Select a specific instance of a file from the list of files
+///
+/// Returns the num-th instance of all files if name is NULL.
+pmFPAfile *pmFPAfileSelectSingle(psMetadata *files, ///< All files
+                                 const char *name, ///< Name of file
+                                 int num ///< Instance number of specific instance
+    );
+
+
+
+/// @}
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfileDefine.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfileDefine.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfileDefine.c	(revision 22158)
@@ -0,0 +1,1429 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>            /* for strn?casecmp */
+#include <pslib.h>
+
+#include "pmErrorCodes.h"
+#include "pmConfig.h"
+#include "pmConfigMask.h"
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+#include "pmFPAfile.h"
+#include "pmFPAConstruct.h"
+
+#include "pmConcepts.h"
+
+# define FPA_TEST_ASSERT(A){ \
+	assert(A->format == NULL); \
+	assert(A->formatName == NULL); \
+	assert(A->filerule == NULL); \
+	assert(A->filesrc == NULL); }
+
+// Parse an option from a metadata, returning the appropriate integer value
+static int parseOptionInt(const psMetadata *md, // Metadata containing the option
+                          const char *name, // Option name
+                          const char *source, // Description of source, for warning messages
+                          int defaultValue // Default value
+                          )
+{
+    psMetadataItem *item = psMetadataLookup(md, name); // Item with the value of interest
+    if (!item) {
+        psWarning("Unable to find value for %s in %s --- set to %d.", name, source, defaultValue);
+        return defaultValue;
+    }
+    int value = psMetadataItemParseS32(item); // Value of interst
+    return value;
+}
+
+// Parse an option from a metadata, returning the appropriate float value
+static float parseOptionFloat(const psMetadata *md, // Metadata containing the option
+                              const char *name, // Option name
+                              const char *source // Description of source, for warning messages
+                              )
+{
+    psMetadataItem *item = psMetadataLookup(md, name); // Item with the value of interest
+    if (!item) {
+        psWarning("Unable to find value for %s in %s", name, source);
+        return NAN;
+    }
+    int value = psMetadataItemParseF32(item); // Value of interst
+    return value;
+}
+
+// Parse an option from a metadata, returning the appropriate double value
+static double parseOptionDouble(const psMetadata *md, // Metadata containing the option
+                                const char *name, // Option name
+                                const char *source // Description of source, for warning messages
+                                )
+{
+    psMetadataItem *item = psMetadataLookup(md, name); // Item with the value of interest
+    if (!item) {
+        psWarning("Unable to find value for %s in %s", name, source);
+        return NAN;
+    }
+    int value = psMetadataItemParseF64(item); // Value of interst
+    return value;
+}
+
+
+// define an input-type pmFPAfile, bind to the optional fpa if supplied
+pmFPAfile *pmFPAfileDefineInput(const pmConfig *config, pmFPA *fpa, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_PTR_NON_NULL(config->files, NULL);
+    PS_ASSERT_PTR_NON_NULL(config->camera, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(name, NULL);
+
+    bool status;
+    char *type;
+
+    const psMetadata *camera = (fpa ? fpa->camera : config->camera); // Camera configuration for this file
+    psMetadata *data = pmConfigFileRule(config, camera, name); // File rule
+    if (!data) {
+        psError(PS_ERR_IO, true, "Can't find file rule %s!", name);
+        return NULL;
+    }
+
+    pmFPAfile *file = pmFPAfileAlloc();
+
+    // save the name of this pmFPAfile
+    file->name = psStringCopy(name);
+
+    file->filerule = psMemIncrRefCounter(psMetadataLookupStr (&status, data, "FILENAME.RULE"));
+
+    type = psMetadataLookupStr(&status, data, "FILE.TYPE");
+    file->type = pmFPAfileTypeFromString(type);
+    if (file->type == PM_FPA_FILE_NONE) {
+        psError(PS_ERR_IO, true, "FILE.TYPE is not defined for %s\n", name);
+        psFree(file);
+        return NULL;
+    }
+
+    file->mode = PM_FPA_MODE_READ;
+    file->fileLevel = PM_FPA_LEVEL_NONE; // the fileLevel depends on the input data
+
+    file->dataLevel = pmFPALevelFromName(psMetadataLookupStr (&status, data, "DATA.LEVEL"));
+    if (file->dataLevel == PM_FPA_LEVEL_NONE) {
+        psError(PS_ERR_IO, true, "DATA.LEVEL is not set for %s\n", name);
+        psFree(file);
+        return NULL;
+    }
+    // default is to free the data after use (after written out)
+    // this can be overridden for pmFPAfiles used as carriers as well
+    file->freeLevel = file->dataLevel;
+
+    if (fpa) {
+        file->fpa = psMemIncrRefCounter(fpa);
+        file->camera = psMemIncrRefCounter((psMetadata *)fpa->camera);
+        file->cameraName = psMemIncrRefCounter(config->cameraName); // XXX Is this the correct thing to do?
+    } else {
+        file->camera = psMemIncrRefCounter(config->camera);
+        file->cameraName = psMemIncrRefCounter(config->cameraName);
+    }
+
+    // XXX ppImage and similar require the added file to be unique
+    // XXX ppFocus wants to override the selection with the new selection
+    // XXX require programs like ppFocus to remove existing files by hand
+    if (!psMetadataAddPtr(config->files, PS_LIST_TAIL, name,
+                          PS_DATA_UNKNOWN | PS_META_DUPLICATE_OK, "", file)) {
+        psError(PS_ERR_IO, false, "could not add %s to config files", name);
+        return NULL;
+    }
+    psFree(file);
+    return file;
+}
+
+// Define an output pmFPAfile
+pmFPAfile *pmFPAfileDefineOutputForFormat(const pmConfig *config, // Configuration
+                                          pmFPA *fpa, // Optional FPA to bind
+                                          const char *name, // Name of file rule
+                                          psString cameraName, // Name of camera configuration to use
+                                          psString formatName // Name of camera format to use
+    )
+{
+    bool status;
+
+    // Use the camera we were told to, the camera of the provided FPA, or default to the default camera
+    psMetadata *camera;                 // Camera configuration
+    if (!cameraName || strlen(cameraName) == 0) {
+        if (fpa && fpa->camera) {
+            camera = (psMetadata*)fpa->camera; // Casting away const, so I can put it in the file
+        } else {
+            camera = config->camera;
+            cameraName = config->cameraName;
+        }
+    } else {
+        bool mdok;                      // Status of MD lookup
+        psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->complete, "CAMERAS"); // Known cameras
+        if (!mdok || !cameras) {
+            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the system configuration.\n");
+            return NULL;
+        }
+        camera = psMetadataLookupMetadata(&mdok, cameras, cameraName); // Camera configuration of interest
+        if (!mdok || !camera) {
+            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find automatically generated "
+                    "camera configuration %s in system configuration.\n", cameraName);
+            return NULL;
+        }
+
+        if (fpa && fpa->camera && fpa->camera != camera) {
+            psAbort("Camera of bound FPA is not the requested camera --- there is an inconsistency!");
+        }
+    }
+
+    psMetadata *filerule = pmConfigFileRule(config, camera, name); // File rule
+    if (!filerule) {
+        psError(PS_ERR_IO, true, "Can't find file rule %s!", name);
+        return NULL;
+    }
+
+    pmFPAfile *file = pmFPAfileAlloc();
+
+    // save the name of this pmFPAfile
+    file->name = psStringCopy(name);
+
+    // this is the filename rule
+    file->filerule = psMemIncrRefCounter(psMetadataLookupStr(&status, filerule, "FILENAME.RULE"));
+
+    const char *type = psMetadataLookupStr(&status, filerule, "FILE.TYPE");
+    file->type = pmFPAfileTypeFromString(type);
+    if (file->type == PM_FPA_FILE_NONE) {
+        psError(PS_ERR_IO, true, "FILE.TYPE is not defined for %s\n", name);
+        psFree(file);
+        return NULL;
+    }
+
+    file->mode = PM_FPA_MODE_WRITE;
+    file->save = false;
+
+    file->camera = psMemIncrRefCounter(camera);
+    file->cameraName = psMemIncrRefCounter(cameraName);
+
+    // XXX this seems a bit of a hack: use the cameraName to determine the mosaic level...
+    # if (0)
+    if (cameraName) {
+        if (!strcmp(cameraName + strlen(cameraName) - 5, "-CHIP")) {
+            file->mosaicLevel = PM_FPA_LEVEL_CHIP;
+        }
+        if (!strcmp(cameraName + strlen(cameraName) - 5, "-FPA")) {
+            file->mosaicLevel = PM_FPA_LEVEL_FPA;
+        }
+    }
+    # endif
+
+    // Use the format we were told to, the format specified in the file rule, or default to the default format
+    if (!formatName || strlen(formatName) == 0) {
+        // select the format list from the selected camera
+        formatName = psMetadataLookupStr(&status, filerule, "FILE.FORMAT");
+        if (!formatName || strcmp(formatName, "NONE") == 0) {
+            // Try to get by with the default
+            formatName = config->formatName;
+        }
+    }
+    psMetadata *formats = psMetadataLookupMetadata(&status, file->camera, "FORMATS"); // List of formats
+    psMetadata *format = psMetadataLookupMetadata(&status, formats, formatName); // Camera format to use
+    if (!format) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to find format %s for file %s.\n",
+                formatName, file->name);
+        psFree(file);
+        return NULL;
+    }
+    file->format = psMemIncrRefCounter(format);
+    file->formatName = psStringCopy(formatName);
+
+    if (fpa) {
+        file->fpa = psMemIncrRefCounter(fpa);
+    } else {
+        file->fpa = pmFPAConstruct(file->camera, file->cameraName);
+    }
+
+    // Get FITS output scheme
+    const char *fitsType = psMetadataLookupStr(&status, filerule, "FITS.TYPE"); // Name of FITS scheme to use
+    if (fitsType && strcasecmp(fitsType, "NONE") != 0) {
+
+        // load the FITSTYPE scheme for this file
+        psMetadata *scheme = pmConfigFitsType(config, camera, fitsType); // File rule
+        if (!scheme) {
+            // XXX change to a config error?
+            psWarning("Unable to find %s in FITS in camera configuration --- will use defaults.", fitsType);
+            goto FITS_OPTIONS_DONE;
+        }
+
+        psString source = NULL;     // Source of options
+        psStringAppend(&source, "%s in FITS in camera configuration", fitsType);
+
+        psFitsOptions *options = file->options = psFitsOptionsAlloc(); // FITS I/O options
+
+        // Custom floating-point
+        bool mdok;                      // Status of MD lookup
+        const char *floatName = psMetadataLookupStr(&mdok, scheme, "FLOAT"); // Name of custom float
+        if (mdok && floatName) {
+            psString fullName = NULL;   // Full name of custom floating-point
+            psStringAppend(&fullName, "FLOAT_%s", floatName);
+            options->floatType = psFitsFloatTypeFromString(fullName);
+            psFree(fullName);
+        }
+
+        options->bitpix = parseOptionInt(scheme, "BITPIX", source, 0); // Bits per pixel
+
+        // Scaling options
+        const char *scalingString = psMetadataLookupStr(&mdok, scheme, "SCALING"); // Scaling name
+        if (scalingString) {
+            options->scaling = psFitsScalingFromString(scalingString); // Scaling method
+
+            switch (options->scaling) {
+              case PS_FITS_SCALE_NONE:
+              case PS_FITS_SCALE_RANGE:
+                // No options required
+                break;
+              case PS_FITS_SCALE_STDEV_POSITIVE:
+              case PS_FITS_SCALE_STDEV_NEGATIVE:
+                options->stdevNum = parseOptionFloat(scheme, "STDEV.NUM", source); // Padding to edge
+                if (!isfinite(options->stdevNum)) {
+                    psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Bad value for STDEV.NUM for %s", source);
+                    psFree(source);
+                    psFree(file);
+                    return NULL;
+                }
+                // Flow through
+              case PS_FITS_SCALE_STDEV_BOTH:
+                options->stdevBits = parseOptionInt(scheme, "STDEV.BITS", source, 0); // Bits for stdev
+                if (options->stdevBits <= 0) {
+                    psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Bad value for STDEV.BITS (%d) for %s",
+                            options->stdevBits, source);
+                    psFree(source);
+                    psFree(file);
+                    return NULL;
+                }
+                break;
+              case PS_FITS_SCALE_MANUAL:
+                options->bscale = parseOptionDouble(scheme, "BSCALE", source); // Scaling
+                options->bzero = parseOptionDouble(scheme, "BZERO", source); // Zero point
+                break;
+              default:
+                psAbort("Should never get here.");
+            }
+        }
+
+        // Compression options
+        const char *compressString = psMetadataLookupStr(&mdok, scheme, "COMPRESSION"); // Compression type
+        if (mdok && compressString) {
+            psFitsCompressionType type = psFitsCompressionTypeFromString(compressString); // Compression
+            psVector *tile = psVectorAlloc(3, PS_TYPE_S32); // Tile sizes
+            tile->data.S32[0] = parseOptionInt(scheme, "TILE.X", source, 0); // Tiling in x
+            tile->data.S32[1] = parseOptionInt(scheme, "TILE.Y", source, 1); // Tiling in y
+            tile->data.S32[2] = parseOptionInt(scheme, "TILE.Z", source, 1); // Tiling in z
+            int noise = parseOptionInt(scheme, "NOISE", source, 16); // Noise bits
+            int hscale = 0, hsmooth = 0;// Scaling and smoothing for HCOMPRESS
+            if (type == PS_FITS_COMPRESS_HCOMPRESS) {
+                hscale = parseOptionInt(scheme, "HSCALE", source, 0);
+                hsmooth = parseOptionInt(scheme, "HSMOOTH", source, 0);
+            }
+
+            file->compression = psFitsCompressionAlloc(type, tile, noise, hscale, hsmooth);
+            psFree(tile);
+        }
+
+        psFree(source);
+    }
+ FITS_OPTIONS_DONE:
+
+    file->fileLevel = pmFPAPHULevel(format);
+    if (file->fileLevel == PM_FPA_LEVEL_NONE) {
+        psError(PS_ERR_IO, true, "Unable to determine file level for %s\n", name);
+        psFree(file);
+        return NULL;
+    }
+
+    file->dataLevel = pmFPALevelFromName(psMetadataLookupStr(&status, filerule, "DATA.LEVEL"));
+    if (file->dataLevel == PM_FPA_LEVEL_NONE) {
+        psError(PS_ERR_IO, true, "DATA.LEVEL is not set for %s\n", name);
+        psFree(file);
+        return NULL;
+    }
+    // default is to free the data after use (after written out)
+    // this can be overridden for pmFPAfiles used as carriers as well
+    file->freeLevel = file->dataLevel;
+    file->fileLevel = PS_MIN (file->fileLevel, file->dataLevel);
+
+    // XXX the file/data/free level must be consistent with the reference fpa (but since we
+    // don't have access to its pmFPAfile, we cannot enforce this here...
+
+    pmFPALevel extLevel = pmFPAExtensionsLevel(format); // Level for extensions
+    if (extLevel != PM_FPA_LEVEL_NONE) {
+        if (extLevel < file->dataLevel) {
+            psWarning("Level for extensions is higher than desired data level --- adjusting.\n");
+            file->dataLevel = extLevel;
+        }
+        if (extLevel < file->freeLevel) {
+            psWarning("Level for extensions is higher than desired free level --- adjusting.\n");
+            file->freeLevel = extLevel;
+        }
+    } else {
+        // if we do not have extensions in the file, we are forced to write out at the file level
+        file->dataLevel = file->fileLevel;
+        file->freeLevel = file->fileLevel;
+    }
+
+    psTrace ("psModules.camera", 5, "file: %s, format: %s, fileLevel: %s, extLevel: %s, dataLevel: %s, freeLevel: %s\n",
+             file->name, file->formatName, pmFPALevelToName (file->fileLevel), pmFPALevelToName(extLevel), pmFPALevelToName (file->dataLevel), pmFPALevelToName (file->freeLevel));
+
+    // add argument-supplied OUTPUT name to this file
+    char *outname = psMetadataLookupStr(&status, config->arguments, "OUTPUT");
+    psMetadataAddStr(file->names, PS_LIST_TAIL, "OUTPUT", PS_META_NO_REPLACE, "", outname);
+
+    // place the resulting file in the config system
+    psMetadataAddPtr (config->files, PS_LIST_TAIL, name, PS_DATA_UNKNOWN, "", file);
+    psFree(file);                       // we free this copy of file, but 'files' still has a copy
+    return file;                        // the returned value is a view into the version on 'files'
+}
+
+// define a pmFPAfile, bind to the optional fpa if supplied
+pmFPAfile *pmFPAfileDefineOutput(const pmConfig *config, pmFPA *fpa, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_PTR_NON_NULL(config->files, NULL);
+    PS_ASSERT_PTR_NON_NULL(config->camera, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(name, NULL);
+
+    return pmFPAfileDefineOutputForFormat(config, fpa, name, NULL, NULL);
+}
+
+// define a pmFPAfile, bind to the optional file if supplied
+pmFPAfile *pmFPAfileDefineOutputFromFile(const pmConfig *config, pmFPAfile *file, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_PTR_NON_NULL(config->files, NULL);
+    PS_ASSERT_PTR_NON_NULL(config->camera, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(name, NULL);
+
+    char *cameraName = NULL, *formatName = NULL; // Name of camera and format
+    pmFPA *fpa = NULL;                  // FPA for file
+    if (file) {
+        cameraName = file->cameraName;
+        formatName = file->formatName;
+        fpa = file->fpa;
+    }
+
+    return pmFPAfileDefineOutputForFormat(config, fpa, name, cameraName, formatName);
+}
+
+// search for argname on the config->argument list
+// construct an FPA based on the files in this list (must represent a single FPA)
+// built the association between the FPA elements (CHIP/CELL) and the files
+// define the pmFPAfile filename and bind it to this FPA
+// save the pmFPAfile on config->files
+// return the pmFPAfile (a view to the one saved on config->files)
+pmFPAfile *pmFPAfileDefineFromArgs(bool *success, pmConfig *config, const char *filename, const char *argname)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(filename, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(argname, NULL);
+
+    bool status;
+    pmFPA *fpa = NULL;
+    psFits *fits = NULL;
+    pmFPAfile *file = NULL;
+    psMetadata *phu = NULL;
+    psMetadata *format = NULL;
+    psMetadata *camera = NULL;
+    psString formatName = NULL;
+
+    // use success to identify valid exit conditions (as opposed to 'argument not supplied')
+    if (success) {
+        *success = false;
+    }
+
+    // we search the argument data for the named fileset (argname)
+    psArray *infiles = psMetadataLookupPtr(&status, config->arguments, argname);
+    if (!status) {
+        if (success) {
+            *success = true;
+        }
+        return NULL;
+    }
+    if (infiles->n < 1) {
+        psError(PS_ERR_IO, false, "Found n == %ld files in %s in arguments\n", infiles->n, argname);
+        return NULL;
+    }
+
+    // this function is implicitly an INPUT operation: do not create the file
+    psString realName = pmConfigConvertFilename (infiles->data[0], config, false, false);
+    if (!realName) {
+        psError(PS_ERR_IO, false, "Failed to convert file name %s\n", (char *) infiles->data[0]);
+        return NULL;
+    }
+
+    // load the header of the first image
+    // EXTWORD (fits->extword) is not relevant to the PHU
+    fits = psFitsOpen (realName, "r");
+    if (!fits) {
+        psError(PS_ERR_IO, false, "Failed to open file %s\n", realName);
+        psFree (realName);
+        return NULL;
+    }
+    phu = psFitsReadHeader (NULL, fits);
+    if (!phu) {
+        psError(PS_ERR_IO, false, "Failed to read file header %s\n", realName);
+        psFree (realName);
+        return NULL;
+    }
+    psFitsClose(fits);
+
+    // Determine the current format from the header; Determine camera if not specified already.
+    // the returned pointers 'camera' and 'formatName' are allocated here
+    format = pmConfigCameraFormatFromHeader(&camera, &formatName, config, phu, true);
+    if (!format) {
+        psError(PS_ERR_IO, false, "Failed to read CCD format from %s\n", realName);
+        psFree(phu);
+	psFree(camera);
+	psFree(formatName);
+        psFree(realName);
+        return NULL;
+    }
+
+    // build the template fpa, set up the basic view
+    // XXX do we want this to be the baseCamera name or the metaCamera name?
+    fpa = pmFPAConstruct(camera, config->cameraName);
+    if (!fpa) {
+        psError(PS_ERR_IO, false, "Failed to construct FPA from %s", realName);
+        psFree(phu);
+	psFree(camera);
+	psFree(formatName);
+        psFree(realName);
+        psFree(format);
+        return NULL;
+    }
+    psFree (realName);
+    psFree (camera);
+
+    // load the given filerule (from config->camera) and bind it to the fpa
+    // the returned file is just a view to the entry on config->files
+    file = pmFPAfileDefineInput(config, fpa, filename);
+    if (!file) {
+        psError(PS_ERR_IO, false, "file %s not defined\n", filename);
+        psFree(phu);
+	psFree(formatName);
+        psFree(format);
+        psFree(fpa);
+        return NULL;
+    }
+    psFree (file->filerule); // this is set in pmFPAfileDefineInput 
+    file->format = format;
+    file->formatName = formatName;
+    file->filerule = psStringCopy("@FILES");
+    file->filesrc = psStringCopy("{CHIP.NAME}.{CELL.NAME}");
+    // we use the above rules to identify these files in the file->names data
+
+    file->fileLevel = pmFPAPHULevel(format);
+    if (file->fileLevel == PM_FPA_LEVEL_NONE) {
+        psError(PS_ERR_IO, true, "Unable to determine file level for %s\n", file->name);
+        psFree(phu);
+        psFree(fpa);
+        return NULL;
+    }
+
+    if (file->type == PM_FPA_FILE_MASK) {
+	if (!pmConfigMaskReadHeader (config, phu)) {
+	    psError(PS_ERR_IO, false, "error in mask bits");
+	    return NULL;
+	}
+    }
+
+    // examine the list of input files and validate their cameras
+    // associated each filename with an element of the FPA
+    // save the association on file->names
+    for (int i = 0; i < infiles->n; i++) {
+        if (i > 0) {
+            // this function is implicitly an INPUT operation: do not create the file
+            psString realName = pmConfigConvertFilename (infiles->data[i], config, false, false);
+            if (!realName) {
+                psError(PS_ERR_IO, false, "Failed to convert file name %s", (char *) infiles->data[i]);
+		psFree(phu);
+		psFree(fpa);
+                return NULL;
+            }
+            // EXTWORD (fits->extword) is not relevant to the PHU
+            fits = psFitsOpen (realName, "r");
+            if (!fits) {
+                psError(PS_ERR_IO, false, "Failed to open file %s\n", realName);
+                psFree(realName);
+		psFree(phu);
+		psFree(fpa);
+                return NULL;
+            }
+            phu = psFitsReadHeader (NULL, fits);
+            if (!phu) {
+                psError(PS_ERR_IO, false, "Failed to read file header %s", realName);
+                psFree(realName);
+                psFitsClose(fits);
+		psFree(phu);
+		psFree(fpa);
+                return NULL;
+            }
+            bool valid = false;
+            if (!pmConfigValidateCameraFormat (&valid, format, phu)) {
+                psError(PS_ERR_UNKNOWN, false, "Error in config scripts\n");
+                psFree(realName);
+                psFitsClose(fits);
+		psFree(phu);
+		psFree(fpa);
+                return NULL;
+            }
+            if (!valid) {
+                psError(PS_ERR_IO, false, "file %s is not from the required camera", realName);
+                psFree(realName);
+                psFitsClose(fits);
+		psFree(phu);
+		psFree(fpa);
+                return NULL;
+            }
+            psFree(realName);
+            psFitsClose(fits);
+        }
+
+        // set the view to the corresponding entry for this phu
+        pmFPAview *view = pmFPAAddSourceFromHeader (fpa, phu, format);
+        if (!view) {
+            psError(PS_ERR_IO, false, "Unable to determine source for %s", file->name);
+            psFree(phu);
+            psFree(fpa);
+            return NULL;
+        }
+
+        // associate the filename with the FPA element
+        char *name = pmFPAfileNameFromRule(file->filesrc, file, view);
+
+        // save the name association in the pmFPAfile structure
+        psMetadataAddStr(file->names, PS_LIST_TAIL, name, 0, "", infiles->data[i]);
+
+        psFree(view);
+        psFree(name);
+        psFree(phu);
+    }
+    psFree(fpa);
+    if (success) {
+        *success = true;
+    }
+
+    return file;
+}
+
+// search for argname on the config->argument list
+// construct an FPA based on the files in this list (must represent a single FPA)
+// built the association between the FPA elements (CHIP/CELL) and the files
+// define the pmFPAfile filename and bind it to this FPA
+// save the pmFPAfile on config->files
+// return the pmFPAfile (a view to the one saved on config->files)
+pmFPAfile *pmFPAfileBindFromArgs (bool *success, pmFPAfile *input, pmConfig *config, const char *filename, const char *argname)
+{
+    PS_ASSERT_PTR_NON_NULL(input, NULL);
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(filename, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(argname, NULL);
+
+    bool status;
+    psFits *fits = NULL;
+    pmFPAfile *file = NULL;
+    psMetadata *phu = NULL;
+
+    // use success to identify valid exit conditions (as opposed to 'argument not supplied')
+    if (success) {
+        *success = false;
+    }
+
+    // we search the argument data for the named fileset (argname)
+    psArray *infiles = psMetadataLookupPtr(&status, config->arguments, argname);
+    if (!status) {
+        // this is not an error: this just means no matching argument was supplied
+        if (success) {
+            *success = true;
+        }
+        return NULL;
+    }
+    if (infiles->n < 1) {
+        psError(PS_ERR_IO, false, "Found n == %ld files in %s in arguments\n", infiles->n, argname);
+        return NULL;
+    }
+
+    // load the given filerule (from config->camera) and bind it to the fpa
+    // the returned file is just a view to the entry on config->files
+    file = pmFPAfileDefineInput (config, input->fpa, filename);
+    if (!file) {
+        psError(PS_ERR_IO, false, "file %s not defined\n", filename);
+        psFree(phu);
+        return NULL;
+    }
+
+    // set derived values
+    file->fileLevel = input->fileLevel;
+
+
+    // define the rule to identify these files in the file->names data
+    psFree (file->filerule);
+    psFree (file->filesrc);
+    file->filerule = psStringCopy ("@FILES");
+    file->filesrc = psStringCopy ("{CHIP.NAME}.{CELL.NAME}");
+
+    // examine the list of input files and validate their cameras
+    // associated each filename with an element of the FPA
+    // save the association on file->names
+    psMetadata *format = NULL;
+    for (int i = 0; i < infiles->n; i++) {
+        // this function is implicitly an INPUT operation: do not create the file
+        psString realName = pmConfigConvertFilename (infiles->data[i], config, false, false);
+        if (!realName) {
+            psError(PS_ERR_IO, false, "Failed to convert file name %s", (char *) infiles->data[i]);
+            return NULL;
+        }
+        // EXTWORD (fits->extword) is not relevant to the PHU
+        fits = psFitsOpen (realName, "r");
+        if (!fits) {
+            psError(PS_ERR_IO, false, "Failed to open file %s\n", realName);
+            psFree(realName);
+            return NULL;
+        }
+        phu = psFitsReadHeader (NULL, fits);
+        if (!phu) {
+            psError(PS_ERR_IO, false, "Failed to read file header %s", realName);
+            psFree(realName);
+            psFitsClose(fits);
+            return NULL;
+        }
+
+        if (!format) {
+            format = pmConfigCameraFormatFromHeader(NULL, NULL, config, phu, true);
+            if (!format) {
+                psError(PS_ERR_IO, false, "Failed to read CCD format from %s\n", realName);
+                psFree(phu);
+                psFree(realName);
+                psFitsClose(fits);
+                return NULL;
+            }
+        } else {
+            bool valid = false;
+            if (!pmConfigValidateCameraFormat(&valid, format, phu)) {
+                psError(PS_ERR_UNKNOWN, false, "Error in config scripts\n");
+                psFree(realName);
+                psFitsClose(fits);
+                return NULL;
+            }
+            if (!valid) {
+                psError(PS_ERR_IO, false, "specified data file %s does not match format of supplied INPUT\n",
+                        realName);
+                psFree(realName);
+                psFitsClose(fits);
+                return NULL;
+            }
+        }
+
+        psFree(realName);
+        psFitsClose(fits);
+
+        // set the view to the corresponding entry for this phu
+        pmFPAview *view = pmFPAIdentifySourceFromHeader (input->fpa, phu, format);
+        if (!view) {
+            psError(PS_ERR_IO, false, "Unable to determine source for %s", file->name);
+            psFree(phu);
+            return NULL;
+        }
+
+        // associate the filename with the FPA element
+        char *name = pmFPAfileNameFromRule(file->filesrc, file, view);
+
+        // save the name association in the pmFPAfile structure
+        psMetadataAddStr (file->names, PS_LIST_TAIL, name, 0, "", infiles->data[i]);
+
+	if ((i == 0) && (file->type == PM_FPA_FILE_MASK)) {
+	    if (!pmConfigMaskReadHeader (config, phu)) {
+		psError(PS_ERR_IO, false, "error in mask bits");
+		return NULL;
+	    }
+	}
+
+        psFree(view);
+        psFree(name);
+        psFree(phu);
+    }
+    file->format = format;
+    file->formatName = psStringCopy(config->formatName);
+
+    if (success) {
+        *success = true;
+    }
+    return file;
+}
+
+// search for argname on the config->argument list
+// construct an FPA based on the files in this list (each represents the same FPA)
+// built the association between the FPA elements (CHIP/CELL) and the files
+// define the pmFPAfile filenames and bind them to the FPAs
+// save the pmFPAfiles on config->files
+// return the pmFPAfiles (a view to the one saved on config->files)
+pmFPAfile *pmFPAfileDefineSingleFromArgs (bool *success, pmConfig *config, const char *filename,
+        const char *argname, int entry)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(filename, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(argname, NULL);
+
+    bool status;
+    pmFPA *fpa = NULL;
+    psFits *fits = NULL;
+    pmFPAfile *file = NULL;
+    psMetadata *phu = NULL;
+    psMetadata *format = NULL;
+
+    if (success) {
+        *success = false;
+    }
+
+    // we search the argument data for the named fileset (argname)
+    psArray *infiles = psMetadataLookupPtr(&status, config->arguments, argname);
+    if (!status) {
+        psTrace("psModules.camera", 5, "Failed to find %s in argument list", argname);
+        if (success) {
+            *success = true;
+        }
+        return NULL;
+    }
+    if (infiles->n <= entry) {
+        psError(PS_ERR_IO, false, "only %ld files in %s in argument, entry %d requested\n",
+                infiles->n, argname, entry);
+        return NULL;
+    }
+
+    // examine the list of input files and validate their cameras
+    // associated each filename with an element of the FPA
+    // save the association on file->names
+    // EXTWORD (fits->extword) is not relevant to the PHU
+    fits = psFitsOpen (infiles->data[entry], "r");
+    phu = psFitsReadHeader (NULL, fits);
+    psFitsClose (fits);
+
+    // on first call to this function, config->camera is not set.
+    // later calls will give an error if the cameras do not match
+    psMetadata *camera = NULL;
+    psString formatName = NULL;
+    format = pmConfigCameraFormatFromHeader (&camera, &formatName, config, phu, true);
+    if (!format) {
+        psError(PS_ERR_IO, false, "Failed to read CCD format from %s\n", (char *)infiles->data[0]);
+        psFree(phu);
+	psFree(camera);
+	psFree(formatName);
+        return NULL;
+    }
+
+    // build the template fpa, set up the basic view
+    fpa = pmFPAConstruct (camera, config->cameraName);
+    if (!fpa) {
+        psError(PS_ERR_IO, false, "Failed to construct FPA from %s", (char *)infiles->data[0]);
+        psFree(phu);
+	psFree(camera);
+	psFree(formatName);
+        psFree(format);
+        return NULL;
+    }
+    psFree(camera);
+
+    // load the given filerule (from config->camera) and bind it to the fpa
+    // the returned file is just a view to the entry on config->files
+    // we need a variable name here... (but in filerule)
+    file = pmFPAfileDefineInput (config, fpa, filename);
+    if (!file) {
+        psError(PS_ERR_IO, false, "file %s not defined\n", filename);
+        psFree(phu);
+        psFree(fpa);
+        psFree(format);
+        return NULL;
+    }
+    FPA_TEST_ASSERT (file);
+    file->format = format;
+    file->formatName = formatName;
+    file->filerule = psStringCopy ("@FILES");
+    file->filesrc = psStringCopy ("{CHIP.NAME}.{CELL.NAME}");
+    // adjust the above rules to identify these files in the file->names data
+
+    file->fileLevel = pmFPAPHULevel(format);
+    if (file->fileLevel == PM_FPA_LEVEL_NONE) {
+        psError(PS_ERR_IO, true, "Unable to determine file level for %s\n", file->name);
+        psFree(phu);
+        psFree(fpa);
+        return NULL;
+    }
+
+    if (file->type == PM_FPA_FILE_MASK) {
+	if (!pmConfigMaskReadHeader (config, phu)) {
+	    psError(PS_ERR_IO, false, "error in mask bits");
+	    return NULL;
+	}
+    }
+
+    // set the view to the corresponding entry for this phu
+    pmFPAview *view = pmFPAAddSourceFromHeader (fpa, phu, format);
+    if (!view) {
+        psError(PS_ERR_IO, false, "Unable to determine source for %s", file->name);
+        psFree(phu);
+        psFree(fpa);
+        return NULL;
+    }
+
+    // associate the filename with the FPA element
+    char *name = pmFPAfileNameFromRule (file->filesrc, file, view);
+
+    // save the name association in the pmFPAfile structure
+    psMetadataAddStr (file->names, PS_LIST_TAIL, name, 0, "", infiles->data[entry]);
+
+    psFree(phu);
+    psFree(fpa);
+    psFree(view);
+    psFree(name);
+
+    if (success) {
+        *success = true;
+    }
+    return file;
+}
+
+// define the named pmFPAfile from the camera->config
+// only valid for pmFPAfile->mode = READ
+pmFPAfile *pmFPAfileDefineFromConf (bool *success, const pmConfig *config, const char *filename)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_STRING_NON_EMPTY(filename, NULL);
+
+    if (success) {
+        *success = false;
+    }
+
+    // a camera config is needed (as source of file rule)
+    if (config->camera == NULL) {
+        psError(PS_ERR_IO, true, "camera is not defined");
+        return NULL;
+    }
+
+    // build the template fpa, set up the basic view
+    pmFPA *fpa = pmFPAConstruct(config->camera, config->cameraName);
+    if (!fpa) {
+        psError(PS_ERR_IO, false, "Failed to construct FPA for %s", filename);
+        return NULL;
+    }
+
+    // load the given filerule (from config->camera) and bind it to the fpa
+    // the returned file is just a view to the entry on config->files
+    pmFPAfile *file = pmFPAfileDefineInput(config, fpa, filename);
+    psFree (fpa);
+    if (!file) {
+        psError(PS_ERR_IO, false, "file %s not defined\n", filename);
+        return NULL;
+    }
+
+    // image names may not come from file->names
+    if (!strcasecmp(file->filerule, "@FILES")) {
+        psError(PS_ERR_IO, true, "supplied filerule uses illegal value @FILES");
+        // XXX remove the file from config->files
+        return NULL;
+    }
+
+    // image names may come from the detrend database
+    if (!strcasecmp(file->filerule, "@DETDB")) {
+        psTrace ("pmFPAfile", 5, "requiring use of detrend database source\n");
+        // don't free the file here: it is left on config->files
+        // to be used optionally by pmFPAfileDefineFromDetDB (or others)
+        if (success) {
+            *success = true;
+        }
+        return NULL;
+    }
+
+    // Prepend the global path to the file rule
+    // this function is implicitly an INPUT operation: do not create the file
+    psString tmpName = pmConfigConvertFilename(file->filerule, config, false, false);
+    psFree (file->filerule);
+    file->filerule = tmpName;
+
+    if (success) {
+        *success = true;
+    }
+
+    return file;
+}
+
+// construct an FPA based on the supplied config->camera
+// built the association between the FPA elements (CHIP/CELL) and the files
+// define the pmFPAfile filename and bind it to this FPA
+// save the pmFPAfile on config->files
+// return the pmFPAfile (a view to the one saved on config->files)
+pmFPAfile *pmFPAfileDefineFromDetDB (bool *success, const pmConfig *config, const char *filename,
+                                     pmFPA *input, pmDetrendType type)
+{
+    PS_ASSERT_PTR_NON_NULL(input, NULL);
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_PTR_NON_NULL(config->camera, NULL);
+    PS_ASSERT_PTR_NON_NULL(config->files, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(filename, NULL);
+
+    bool status;
+    pmFPA *fpa = NULL;
+    pmFPAfile *file = NULL;
+
+    if (success) {
+        *success = false;
+    }
+
+    // a camera config is needed (as source of file rule)
+    if (config->camera == NULL) {
+        psError(PS_ERR_IO, true, "camera is not defined");
+        return NULL;
+    }
+    // a camera config is needed (as source of file rule)
+    if (config->cameraName == NULL) {
+        psAbort("camera defined but not cameraName!");
+    }
+
+    // find or define a pmFPAfile with this name
+    file = psMetadataLookupPtr (NULL, config->files, filename);
+    if (!file) {
+        // build the template fpa, set up the basic view
+        fpa = pmFPAConstruct(config->camera, config->cameraName);
+        if (!fpa) {
+            psError(PS_ERR_IO, false, "Failed to construct FPA for %s", filename);
+            return NULL;
+        }
+        // load the given filerule (from config->camera) and bind it to the fpa
+        // the returned file is just a view to the entry on config->files
+        file = pmFPAfileDefineInput (config, fpa, filename);
+        if (!file) {
+            psError(PS_ERR_IO, false, "file %s not defined\n", filename);
+            psFree(fpa);
+            return NULL;
+        }
+    }
+
+    // we are constructing a detselect command of the form:
+    //   detselect -search -inst (camera) -type (type) -time (time) [others]
+    // camera, type, and time are derived from pmFPA *input, other options are
+    // added if specified for the particular detrend type by the DETREND.CONSTRAINTS
+    // note that the filter-dependent choices are set for ppImage in ppImageParseCamera
+    // XXX make all of the detrend constraints explicit in DETREND.CONSTRAINTS?
+
+    // Get the time from FPA.TIME
+    psTime *time = psMetadataLookupPtr(NULL, input->concepts, "FPA.TIME");
+    if (time->sec == 0 && time->nsec == 0) {
+        psLogMsg ("psModules.camera", PS_LOG_WARN, "FPA.TIME has not been set.\n");
+    }
+
+    // XXX careful about this: is this set correctly in the camera.config files?
+    char *instrument = psMetadataLookupStr(NULL, input->concepts, "FPA.INSTRUMENT");
+    pmDetrendSelectOptions *options = pmDetrendSelectOptionsAlloc(instrument, *time, type);
+
+    // add additional constraints based on the type defined in the PPIMAGE recipe
+    // XXX use PPIMAGE or DETREND for the recipe name?
+    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, "PPIMAGE");
+    if (!status) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "PPIMAGE recipe not found.");
+        psFree(options);
+        psFree(fpa);
+        return false;
+    }
+    psMetadata *detConstraints = psMetadataLookupPtr (&status, recipe, "DETREND.CONSTRAINTS");
+    if (!status) {
+        psWarning("DETREND.CONSTRAINTS not found --- no constraints will be applied.");
+        goto DETREND_SELECT;
+    }
+
+    psString typeName = pmDetrendTypeToString (type);
+    psMetadata *constraints = psMetadataLookupPtr (&status, detConstraints, typeName);
+    if (!status) {
+        psWarning("DETREND.CONSTRAINTS for type %s not found --- no contraints will be applied.", typeName);
+        psFree(typeName);
+        goto DETREND_SELECT;
+    }
+    psFree(typeName);
+
+    // loop over the constraints and include in the detselect options
+    psMetadataIterator *iter = psMetadataIteratorAlloc (constraints, PS_LIST_HEAD, NULL);
+    psMetadataItem *item = NULL;
+    while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
+        if (item->type != PS_DATA_STRING) {
+            psWarning("Invalid type for DETREND.CONSTRAINT element %s --- ignoring constraint", item->name);
+            continue;
+        }
+        char *option  = item->name;     // item->name must correspond to a valid detselect option
+        char *concept = item->data.V;
+
+        // these items refer to the corresponding values for the input image
+        // (ie, -filter input:filter or -exptime input:exptime)
+        if (!strcasecmp (option, "filter")) {
+            options->filter = psMetadataLookupPtr (&status, input->concepts, concept);
+            psMemIncrRefCounter (options->filter);
+            if (!status)
+                psAbort("failed to find filter (concept %s)", concept);
+        } else if (!strcasecmp (option, "exptime")) {
+            options->exptime = psMetadataLookupF32 (&status, input->concepts, concept);
+            options->exptimeSet = true;
+            if (!status)
+                psAbort("exptime not found (concept %s)", concept);
+        } else if (!strcasecmp (option, "airmass")) {
+            options->airmass = psMetadataLookupF32 (&status, input->concepts, concept);
+            options->airmassSet = true;
+            if (!status)
+                psAbort("airmass not found (concept %s)", concept);
+        } else if (!strcasecmp (option, "dettemp")) {
+            options->dettemp = psMetadataLookupF32 (&status, input->concepts, concept);
+            options->dettempSet = true;
+            if (!status)
+                psAbort("dettemp not found (concept %s)", concept);
+        } else if (!strcasecmp (option, "twilight")) {
+            options->twilight = psMetadataLookupF32 (&status, input->concepts, concept);
+            options->twilightSet = true;
+            if (!status)
+                psAbort("twilight not found (concept %s)", concept);
+        }
+
+        // the version is applied literally
+        if (!strcasecmp (option, "version")) {
+            options->version = psMemIncrRefCounter (concept);
+        }
+        // we can override the detrend database dettype if desired
+        // ie, use DOMEFLAT for type FLAT
+        // the dettype string is applied literally
+        if (!strcasecmp (option, "dettype")) {
+            options->dettype = psMemIncrRefCounter (concept);
+        }
+    }
+    psFree(iter);
+
+DETREND_SELECT:
+    {
+        // search for existing detrend data (detID)
+        pmDetrendSelectResults *results = pmDetrendSelect (options, config);
+        if (!results) {
+            psError (PS_ERR_IO, false, "no matching detrend data");
+            return NULL;
+        }
+        file->detrend = results;
+        file->fileLevel = pmFPALevelFromName(results->level);
+        if (file->fileLevel == PM_FPA_LEVEL_NONE) {
+            psError (PS_ERR_IO, false, "invalid file level for selected detrend data");
+            return NULL;
+        }
+    }
+
+    psFree (options);
+
+    if (success) {
+        *success = true;
+    }
+    return file;
+}
+
+// create a new output pmFPAfile based on an existing FPA
+// only valid for pmFPAfile->mode == WRITE (or internal?)
+pmFPAfile *pmFPAfileDefineFromFPA (const pmConfig *config, pmFPA *src, int xBin, int yBin, const char *filename)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(src, false);
+    PS_ASSERT_STRING_NON_EMPTY(filename, NULL);
+
+    pmFPA *fpa = pmFPAConstruct(src->camera, psMetadataLookupStr(NULL, src->concepts, "FPA.CAMERA"));
+    // XXX should this use DefineOutputForFormat?
+    pmFPAfile *file = pmFPAfileDefineOutput (config, fpa, filename);
+    if (!file) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "file %s not defined\n", filename);
+        return NULL;
+    }
+    file->src = psMemIncrRefCounter(src); // inherit output elements from this source pmFPA
+    file->xBin = xBin;
+    file->yBin = yBin;
+    psFree (fpa);
+    return file;
+}
+
+pmFPAfile *pmFPAfileDefineFromFile(const pmConfig *config, pmFPAfile *src, int xBin, int yBin,
+                                   const char *filename)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(src, false);
+    PS_ASSERT_STRING_NON_EMPTY(filename, NULL);
+
+    pmFPAfile *file = pmFPAfileDefineOutputForFormat(config, NULL, filename, src->cameraName,
+                                                     src->formatName);
+    file->src = psMemIncrRefCounter(src->fpa); // inherit output elements from this source pmFPA
+    file->xBin = xBin;
+    file->yBin = yBin;
+
+    // inherit the concepts from the src fpa:
+    pmFPACopyConcepts(file->fpa, file->src);
+
+    return file;
+}
+
+// create a new output pmFPAfile based on an existing FPA
+// only valid for pmFPAfile->mode == WRITE (or internal?)
+pmFPAfile *pmFPAfileDefineNewCamera (const pmConfig *config, const char *filename)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_STRING_NON_EMPTY(filename, NULL);
+
+    pmFPAfile *file = pmFPAfileDefineOutput (config, NULL, filename);
+    if (!file) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "file %s not defined\n", filename);
+        return NULL;
+    }
+    if (!file->camera) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "file %s does not define a new camera\n", filename);
+        return NULL;
+    }
+    file->fpa = pmFPAConstruct(file->camera, file->cameraName);
+
+    return file;
+}
+
+pmFPAfile *pmFPAfileDefineSkycell(const pmConfig *config, pmFPA *fpa, const char *filename)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(filename, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(config->cameraName, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(config->formatName, NULL);
+
+    pmFPAfile *file;                    // The new file
+
+    if (config->cameraName[0] == '_' &&
+        strcmp(config->cameraName + strlen(config->cameraName) - 8, "-SKYCELL") == 0) {
+        // The input camera is already a skycell
+        file = pmFPAfileDefineOutputForFormat(config, fpa, filename, config->cameraName, "SKYCELL");
+    } else {
+        psString cameraName = NULL;         // Name of the old camera configuration
+        if (config->cameraName[0] == '_' &&
+            strcmp(config->cameraName + strlen(config->cameraName) - 5, "-CHIP") == 0) {
+            cameraName = psStringNCopy(config->cameraName + 1, strlen(config->cameraName) - 6);
+        } else if (config->cameraName[0] == '_' &&
+                   strcmp(config->cameraName + strlen(config->cameraName) - 4 , "-FPA") == 0) {
+            cameraName = psStringNCopy(config->cameraName + 1, strlen(config->cameraName) - 5);
+        } else {
+            cameraName = psMemIncrRefCounter(config->cameraName);
+        }
+        psString newCameraName = NULL;  // Name of the new (automatically-generated) camera configuration
+        psStringAppend(&newCameraName, "_%s-SKYCELL", cameraName);
+        file = pmFPAfileDefineOutputForFormat(config, fpa, filename, newCameraName, "SKYCELL");
+        psFree(cameraName);
+        psFree(newCameraName);
+    }
+    if (!file) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "file %s not defined\n", filename);
+        return NULL;
+    }
+
+    // Ensure everything is written out at the appropriate level
+    file->fileLevel = PM_FPA_LEVEL_FPA;
+    file->dataLevel = PM_FPA_LEVEL_FPA;
+    file->freeLevel = PM_FPA_LEVEL_FPA;
+
+    return file;
+}
+
+pmFPAfile *pmFPAfileDefineChipMosaic(const pmConfig *config, pmFPA *src, const char *filename)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_PTR_NON_NULL(src, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(filename, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(config->cameraName, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(config->formatName, NULL);
+
+    pmFPAfile *file;                    // The new file
+    if (config->cameraName[0] == '_' &&
+        (strcmp(config->cameraName + strlen(config->cameraName) - 5, "-CHIP") == 0 ||
+         strcmp(config->cameraName + strlen(config->cameraName) - 8, "-SKYCELL") == 0)) {
+        // The input camera has already been mosaicked to this level
+        file = pmFPAfileDefineOutputForFormat(config, NULL, filename, config->cameraName, config->formatName);
+    } else {
+        psString cameraName = NULL; // Name of the new (automatically-generated) camera configuration
+        if (config->cameraName[0] == '_' &&
+            strcmp(config->cameraName + strlen(config->cameraName) - 4 , "-FPA") == 0) {
+            cameraName = psStringNCopy(config->cameraName + 1, strlen(config->cameraName) - 5);
+        } else {
+            cameraName = psMemIncrRefCounter(config->cameraName);
+        }
+        psString newCameraName = NULL;  // Name of the new (automatically-generated) camera configuration
+        psStringAppend(&newCameraName, "_%s-CHIP", cameraName);
+
+        // Find the correct camera configuration
+        file = pmFPAfileDefineOutputForFormat(config, NULL, filename, newCameraName, config->formatName);
+        psFree(newCameraName);
+        psFree(cameraName);
+    }
+    if (!file) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "file %s not defined\n", filename);
+        return NULL;
+    }
+
+    file->src = psMemIncrRefCounter(src); // inherit output elements from this source pmFPA
+    if (src) {
+        if (!pmConceptsCopyFPA(file->fpa, src, true, false)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to copy concepts from source to new FPA");
+            return NULL;
+        }
+    }
+
+    file->mosaicLevel = PM_FPA_LEVEL_CHIP; // don't do any I/O on this at a lower level
+
+    return file;
+}
+
+pmFPAfile *pmFPAfileDefineFPAMosaic(const pmConfig *config, pmFPA *src, const char *filename)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_PTR_NON_NULL(src, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(filename, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(config->cameraName, NULL);
+
+    pmFPAfile *file;                    // The new file
+    if (config->cameraName[0] == '_' &&
+        (strcmp(config->cameraName + strlen(config->cameraName) - 4 , "-FPA") == 0 ||
+         strcmp(config->cameraName + strlen(config->cameraName) - 8, "-SKYCELL") == 0)) {
+        // The input camera has already been mosaicked to this level
+        file = pmFPAfileDefineOutputForFormat(config, NULL, filename, config->cameraName, config->formatName);
+    } else {
+
+        psString original = NULL;       // Name of the original camera configuration
+        if (config->cameraName[0] == '_' &&
+            strcmp(config->cameraName + strlen(config->cameraName) - 5 , "-CHIP") == 0) {
+            // It's a chip mosaic; we need to get the original name
+            original = psStringNCopy(config->cameraName + 1, strlen(config->cameraName) - 6);
+        } else if (config->cameraName[0] == '_' &&
+            strcmp(config->cameraName + strlen(config->cameraName) - 8, "-SKYCELL") == 0) {
+            original = psStringNCopy(config->cameraName + 1, strlen(config->cameraName) - 9);
+        } else {
+            original = psMemIncrRefCounter(config->cameraName);
+        }
+        psString cameraName = NULL;
+        psStringAppend(&cameraName, "_%s-FPA", original);
+        psFree(original);
+
+        file = pmFPAfileDefineOutputForFormat(config, NULL, filename, cameraName, config->formatName);
+        psFree(cameraName);
+    }
+    if (!file) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "file %s not defined\n", filename);
+        return NULL;
+    }
+
+    file->src = psMemIncrRefCounter(src); // inherit output elements from this source pmFPA
+    if (src) {
+        if (!pmConceptsCopyFPA(file->fpa, src, false, false)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to copy concepts from source to new FPA");
+            return NULL;
+        }
+    }
+
+    file->mosaicLevel = PM_FPA_LEVEL_FPA; // don't do any I/O on this at a lower level
+
+    return file;
+}
+
+// create a file with the given name, assign it type "INTERNAL", and supply it with an image
+// of the requested dimensions. (image only, mask and weight are ignored)
+pmReadout *pmFPAfileDefineInternal (psMetadata *files, const char *name, int Nx, int Ny, int type)
+{
+    PS_ASSERT_PTR_NON_NULL(files, false);
+    PS_ASSERT_STRING_NON_EMPTY(name, NULL);
+
+    pmReadout *readout = pmReadoutAlloc(NULL);
+    readout->image = psImageAlloc(Nx, Ny, type);
+
+    // I want an image from the
+    pmFPAfile *file = pmFPAfileAlloc();
+    file->mode = PM_FPA_MODE_INTERNAL;
+    file->name = psStringCopy (name);
+
+    file->readout = readout;
+    psMetadataAddPtr(files, PS_LIST_TAIL, name, PS_DATA_UNKNOWN, "", file);
+    psFree(file);
+    // we free this copy of file, but 'files' still has a copy
+
+    return readout;
+}
+
+bool pmFPAfileDropInternal(psMetadata *files, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(files, false);
+    PS_ASSERT_STRING_NON_EMPTY(name, NULL);
+
+    bool status = false;
+
+    pmFPAfile *file = psMetadataLookupPtr(&status, files, name);
+    if (!status) {
+        psTrace("psModules.camera", 6, "Internal File %s not in file list", name);
+        return true;
+    }
+    if (file == NULL) {
+        psError(PS_ERR_IO, true, "file %s is NULL", name);
+        return false;
+    }
+    if (file->mode != PM_FPA_MODE_INTERNAL) {
+        psTrace("psModules.camera", 6, "FPA File %s not Internal, not dropping", name);
+        return true;
+    }
+
+    psTrace("psModules.camera", 6, "dropping Internal FPA File %s", name);
+    psMetadataRemoveKey(files, name);
+    return true;
+}
+
+// Select or construct the requested readout.  If the named entry does not exist, generate it based
+// on the specified fpa and binning.  We have 4 possibilities: (INTERNAL or I/O file) and (exists or
+// not).  This call is used after all user-requested pmFPAfiles have been generated.  A missing
+// pmFPAfile is being used internally.
+pmReadout *pmFPAGenerateReadout(const pmConfig *config, // configuration information
+                                const pmFPAview *view, // select background for this entry
+                                const char *name, // name of internal/external file
+                                const pmFPA *fpa, // use this fpa to generate
+                                const psImageBinning *binning) {
+  pmReadout *readout = NULL;
+
+  bool status = true;
+  pmFPAfile *file = psMetadataLookupPtr(&status, config->files, name);
+
+  // if the file does not exist, it is not being used as an I/O file: define an internal version
+  if (file == NULL) {
+    readout = pmFPAfileDefineInternal (config->files, name, binning->nXruff, binning->nYruff, PS_TYPE_F32);
+    return readout;
+  }
+
+  // if the mode is INTERNAL, it has been defined in a previous call.  XXX This seems to require
+  // that the readout have the same dimensions for all entries.
+  if (file->mode == PM_FPA_MODE_INTERNAL) {
+    readout = file->readout;
+    return readout;
+  }
+
+  // we are using this pmFPAfile as an I/O file: select readout or create
+  readout = pmFPAviewThisReadout (view, file->fpa);
+  if (readout == NULL) {
+    // readout does not yet exist: create from input
+    // XXX we have an inconsistency in this calculation here and in pmFPACopy
+    // XXX use the psImageBinning functions to set the output image size
+    if (binning == NULL) {
+      pmFPAfileCopyStructureView (file->fpa, fpa, 1, 1, view);
+      readout = pmFPAviewThisReadout (view, file->fpa);
+    } else {
+      pmFPAfileCopyStructureView (file->fpa, fpa, binning->nXbin, binning->nYbin, view);
+      readout = pmFPAviewThisReadout (view, file->fpa);
+      PS_ASSERT (binning->nXruff == readout->image->numCols, false);
+      PS_ASSERT (binning->nYruff == readout->image->numRows, false);
+    }
+  }
+
+  return readout;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfileDefine.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfileDefine.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfileDefine.h	(revision 22158)
@@ -0,0 +1,156 @@
+/* @file  pmFPAview.h
+ * @brief Tools to manipulate the FPA structure elements.
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.17 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-05-12 21:41:55 $
+ * Copyright 2004-2005 Institute for Astronomy, University of Hawaii
+ */
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+#ifndef PM_FPA_FILE_DEFINE_H
+#define PM_FPA_FILE_DEFINE_H
+
+// load the pmFPAfile information from the camera configuration data
+//
+// Note that the returned pmFPAfile is a view only, so it should not be freed by the caller --- the only
+// reference count is held by the config->files metadata.  Multiple file rules of the same name are permitted
+// if multiple is true.
+pmFPAfile *pmFPAfileDefineInput (const pmConfig *config, pmFPA *fpa, const char *name);
+
+// load the pmFPAfile information from the camera configuration data
+//
+// Note that the returned pmFPAfile is a view only, so it should not be freed by the caller --- the only
+// reference count is held by the config->files metadata.
+// Define an output pmFPAfile
+pmFPAfile *pmFPAfileDefineOutput(const pmConfig *config, // Configuration
+                                 pmFPA *fpa, // Optional FPA to bind
+                                 const char *name // Name of file rule
+    );
+
+/// Same as pmFPAfileDefineOutput, but binds to the fpa in the provided file
+pmFPAfile *pmFPAfileDefineOutputFromFile(const pmConfig *config, // Configuration
+                                         pmFPAfile *file, // File to bind FPAs, or NULL
+                                         const char *name // Name of file rule
+    );
+
+/// Define the FPA file using the provided camera and format names.
+///
+/// Note that the returned pmFPAfile is a view only, so it should not be freed by the caller --- the only
+/// reference count is held by the config->files metadata.
+pmFPAfile *pmFPAfileDefineOutputForFormat(const pmConfig *config, // Configuration
+                                          pmFPA *fpa, // Optional FPA to bind
+                                          const char *name, // Name of file rule
+                                          psString cameraName, // Name of camera configuration to use
+                                          psString formatName // Name of camera format to use
+    );
+
+// look for the given argname on the argument list.  find the give filename from the file rules
+//
+// Note that the returned pmFPAfile is a view only, so it should not be freed by the caller --- the only
+// reference count is held by the config->files metadata.
+pmFPAfile *pmFPAfileDefineFromArgs (bool *found, pmConfig *config, const char *filename, const char *argname);
+
+// look for the given argname on the argument list; bind the associated files to the specified
+// fpa.  these are, eg, mask or weight images.
+// Note that the returned pmFPAfile is a view only, so it should not be freed by the caller --- the only
+// reference count is held by the config->files metadata.
+pmFPAfile *pmFPAfileBindFromArgs (bool *found, pmFPAfile *input, pmConfig *config, const char *filename, const char *argname);
+
+// look for the given argname on the argument list.  find the give filename from the file rules
+//
+// Note that the returned pmFPAfile is a view only, so it should not be freed by the caller --- the only
+// reference count is held by the config->files metadata.
+pmFPAfile *pmFPAfileDefineFromConf (bool *found, const pmConfig *config, const char *filename);
+
+// look for the given argname on the argument list.  find the give filename from the file rules
+//
+// Note that the returned pmFPAfile is a view only, so it should not be freed by the caller --- the only
+// reference count is held by the config->files metadata.
+pmFPAfile *pmFPAfileDefineFromDetDB (bool *found, const pmConfig *config, const char *filename,
+                                     pmFPA *input, pmDetrendType type);
+
+// create a new output pmFPAfile based on an existing FPA
+//
+// Note that the returned pmFPAfile is a view only, so it should not be freed by the caller --- the only
+// reference count is held by the config->files metadata.
+pmFPAfile *pmFPAfileDefineFromFPA (const pmConfig *config, pmFPA *src, int xBin, int yBin, const char *filename);
+
+/// Same as pmFPAfileDefineFromFPA, except it uses an FPA file instead of an FPA
+///
+/// The new pmFPAfile is inserted into the config->files metadata, freed and returned; so that the user does
+/// not have to (and should not!) free the result.
+pmFPAfile *pmFPAfileDefineFromFile(const pmConfig *config, // Configuration
+                                   pmFPAfile *src, // Source file for this file
+                                   int xBin, int yBin, // Binning for this file
+                                   const char *filename // Name of file rule
+    );
+
+
+// create a new output pmFPAfile based on an existing FPA
+// only valid for pmFPAfile->mode == WRITE (or internal?)
+//
+// Note that the returned pmFPAfile is a view only, so it should not be freed by the caller --- the only
+// reference count is held by the config->files metadata.
+pmFPAfile *pmFPAfileDefineNewCamera (const pmConfig *config, const char *filename);
+
+/// Create a new output pmFPAfile for a skycell of the default camera
+///
+/// The new pmFPAfile is inserted into the config->files metadata, freed and returned; so that the user does
+/// not have to (and should not!) free the result.
+pmFPAfile *pmFPAfileDefineSkycell(const pmConfig *config, ///< Configuration data
+                                  pmFPA *fpa, ///< FPA to which to bind
+                                  const char *filename ///< Output (root) filename
+    );
+
+
+/// Create a new output pmFPAfile based upon a chip mosaic of an existing FPA
+///
+/// The new pmFPAfile is inserted into the config->files metadata, freed and returned; so that the user does
+/// not have to (and should not!) free the result.
+pmFPAfile *pmFPAfileDefineChipMosaic(const pmConfig *config, ///< Configuration data
+                                     pmFPA *src, ///< Source FPA
+                                     const char *filename ///< Output (root) filename
+                                    );
+
+/// Create a new output pmFPAfile based upon an FPA mosaic of an existing FPA
+///
+/// The new pmFPAfile is inserted into the config->files metadata, freed and returned; so that the user does
+/// not have to (and should not!) free the result.
+pmFPAfile *pmFPAfileDefineFPAMosaic(const pmConfig *config, ///< Configuration data
+                                    pmFPA *src, ///< Source FPA
+                                    const char *filename ///< Output (root) filename
+                                   );
+
+// create a file with the given name, assign it type "INTERNAL", and supply it with an image
+// of the requested dimensions. (image only, mask and weight are ignored)
+///
+/// The new pmFPAfile is inserted into the config->files metadata, freed and returned; so that the user does
+/// not have to (and should not!) free the result.
+pmReadout *pmFPAfileDefineInternal(psMetadata *files, const char *name, int Nx, int Ny, int type);
+
+// delete the INTERNAL file of the given name (if it exists)
+bool pmFPAfileDropInternal(psMetadata *files, const char *name);
+
+// look for the given argname on the argument list.  find the give filename from the file rules
+//
+// Note that the returned pmFPAfile is a view only, so it should not be freed by the caller --- the only
+// reference count is held by the config->files metadata.
+pmFPAfile *pmFPAfileDefineSingleFromArgs(bool *found, pmConfig *config, const char *filename,
+                                         const char *argname, int entry);
+
+// Select or construct the requested readout.  If the named entry does not exist, generate it based
+// on the specified fpa and binning.  We have 4 possibilities: (INTERNAL or I/O file) and (exists or
+// not).  This call is used after all user-requested pmFPAfiles have been generated.  A missing
+// pmFPAfile is being used internally.
+pmReadout *pmFPAGenerateReadout(const pmConfig *config, // configuration information
+                                const pmFPAview *view, // select background for this entry
+                                const char *name, // name of internal/external file
+                                const pmFPA *fpa, // use this fpa to generate
+                                const psImageBinning *binning);
+
+/// @}
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfileFitsIO.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfileFitsIO.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfileFitsIO.c	(revision 22158)
@@ -0,0 +1,625 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmConfigMask.h"
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPARead.h"
+#include "pmFPAWrite.h"
+#include "pmFPAMaskWeight.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+#include "pmFPAfileFitsIO.h"
+#include "pmFPACopy.h"
+#include "pmFPAConstruct.h"
+#include "pmDark.h"
+#include "pmConcepts.h"
+
+// Get a suitable FPA for the file; generate it if necessary
+static pmFPA *suitableFPA(const pmFPAfile *file, // File for which to get FPA
+                          const pmFPAview *view, // View at which to produce the FPA
+                          pmConfig *config, // Configuration (for concepts update)
+                          bool pixels   // Worry about copying pixels?
+    )
+{
+    psAssert(file, "It's supposed to be here");
+    psAssert(view, "It's supposed to be here");
+    psAssert(config, "It's supposed to be here");
+
+    if (!file->format) {                // Working with the same output format as input format
+        return psMemIncrRefCounter(file->fpa);
+    }
+
+    // May need to change format
+    pmFPALevel level = pmFPAviewLevel(view); // Level for the view
+    if (level == PM_FPA_LEVEL_NONE || level == PM_FPA_LEVEL_READOUT) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "This function shouldn't be called at the readout (or unknown) level.");
+        return NULL;
+    }
+
+    // Does the HDU of interest conform to the desired format?
+    pmHDU *hdu = pmFPAviewThisHDU(view, file->fpa); // The HDU of interest
+    if (hdu && hdu->format == file->format) {
+        // No work required
+        return psMemIncrRefCounter(file->fpa);
+    }
+
+    // Otherwise, we have to generate a copy with the correct format
+
+    pmFPAview *phuView = pmFPAviewAlloc(0); // View corresponding to the PHU
+    *phuView = *view;               // Copy contents
+    pmFPALevel phuLevel = pmFPAPHULevel(file->format); // Level for the PHU
+    switch (phuLevel) {
+      case PM_FPA_LEVEL_FPA:
+        phuView->chip = -1;
+        // Flow through
+      case PM_FPA_LEVEL_CHIP:
+        phuView->cell = -1;
+        // Flow through
+      case PM_FPA_LEVEL_CELL:
+        phuView->readout = -1;
+        break;
+      case PM_FPA_LEVEL_READOUT:
+      case PM_FPA_LEVEL_NONE:
+      default:
+        psAbort("Should never get here: bad phu level.\n");
+    }
+
+    pmFPA *nameSource = file->src; // Source of FPA.OBS
+    if (!nameSource) {
+        nameSource = file->fpa;
+    }
+    bool mdok;                  // Status of MD lookup
+    const char *fpaObs = psMetadataLookupStr(&mdok, nameSource->concepts, "FPA.OBS"); // Observation id
+
+    pmFPA *copy = pmFPAConstruct(file->camera, file->cameraName);  // FPA to return
+    if (!pmFPAAddSourceFromView(copy, fpaObs, phuView, file->format)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to insert HDU into FPA for writing.\n");
+        psFree(copy);
+        psFree(phuView);
+        return NULL;
+    }
+    psFree(phuView);
+
+    switch (level) {
+      case PM_FPA_LEVEL_FPA:
+        if ((pixels && !pmFPACopy(copy, file->fpa)) ||
+            (!pixels && !pmFPACopyStructure(copy, file->fpa, 1, 1))) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to copy FPA for format conversion.\n");
+            return NULL;
+        }
+        return copy;
+      case PM_FPA_LEVEL_CHIP: {
+          pmChip *chip = pmFPAviewThisChip(view, copy); // Chip of interest
+          pmChip *srcChip = pmFPAviewThisChip(view, file->fpa); // Source chip
+          if ((pixels && !pmChipCopy(chip, srcChip)) ||
+              (!pixels && !pmChipCopyStructure(chip, srcChip, 1, 1))) {
+              psError(PS_ERR_UNKNOWN, false, "Unable to copy chip for format conversion.\n");
+              return false;
+          }
+          return copy;
+      }
+      case PM_FPA_LEVEL_CELL: {
+          pmCell *cell = pmFPAviewThisCell(view, copy); // Cell of interest
+          pmCell *srcCell = pmFPAviewThisCell(view, file->fpa); // Source cell
+          if ((pixels && !pmCellCopy(cell, srcCell)) ||
+              (!pixels && !pmCellCopyStructure(cell, srcCell, 1, 1))) {
+              psError(PS_ERR_UNKNOWN, false, "Unable to copy cell for format conversion.\n");
+              return false;
+          }
+          return copy;
+      }
+      case PM_FPA_LEVEL_READOUT:
+      case PM_FPA_LEVEL_NONE:
+      default:
+        psAbort("Should never get here: bad phu level.\n");
+    }
+
+    // Unreachable
+    return NULL;
+}
+
+
+pmFPA *pmFPAfileSuitableFPA(const pmFPAfile *file, const pmFPAview *view, pmConfig *config, bool pixels)
+{
+    PS_ASSERT_PTR_NON_NULL(file, NULL);
+    PS_ASSERT_PTR_NON_NULL(view, NULL);
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    pmFPA *fpa = suitableFPA(file, view, config, pixels); // A suitable FPA for writing
+    if (!fpa) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to produce suitable FPA.");
+        return NULL;
+    }
+
+    // Ensure headers and all are updated
+    // This is here so that the individual write functions (e.g., images, PSFs, sources, etc) don't have to
+    // take care of all this themselves (because they generally don't).
+    switch (file->type) {
+      case PM_FPA_FILE_IMAGE:
+      case PM_FPA_FILE_MASK:
+      case PM_FPA_FILE_WEIGHT:
+      case PM_FPA_FILE_HEADER:
+      case PM_FPA_FILE_FRINGE:
+      case PM_FPA_FILE_DARK:
+      case PM_FPA_FILE_CMP:
+      case PM_FPA_FILE_CMF:
+      case PM_FPA_FILE_PSF:
+      case PM_FPA_FILE_ASTROM_MODEL:
+      case PM_FPA_FILE_ASTROM_REFSTARS: {
+          pmHDU *hdu = pmFPAviewThisHDU(view, fpa);
+          if (hdu) {
+              if (!hdu->header) {
+                  hdu->header = psMetadataAlloc();
+              }
+              pmConfigConformHeader(hdu->header, file->format);
+
+              // whenever we write out a mask image, we should define the bits which represent mask concepts
+              if (file->type == PM_FPA_FILE_MASK) {
+                  assert (hdu->header);
+                  if (!pmConfigMaskWriteHeader(config, hdu->header)) {
+                      psError(PS_ERR_UNKNOWN, false,
+                              "failed to set the bitmask names in the PHU header for Image %s (%s)\n",
+                              file->filename, file->name);
+                      return false;
+                  }
+              }
+          }
+
+          pmChip *chip = pmFPAviewThisChip(view, fpa); // Chip of interest, or NULL
+          pmCell *cell = pmFPAviewThisCell(view, fpa); // Cell of interest, or NULL
+          if (!pmFPAUpdateNames(fpa, chip, cell)) {
+              psError(PS_ERR_UNKNOWN, false, "Unable to update names in header.");
+              return false;
+          }
+
+          pmConceptSource sources = PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_CELLS |
+              PM_CONCEPT_SOURCE_DEFAULTS | PM_CONCEPT_SOURCE_DATABASE; // Concept sources to write
+          if (cell) {
+              if (!pmConceptsWriteCell(cell, sources, true, config)) {
+                  psError(PS_ERR_IO, false, "Unable to write concepts for cell.\n");
+                  return false;
+              }
+          } else if (chip) {
+              if (!pmConceptsWriteChip(chip, sources, true, true, config)) {
+                  psError(PS_ERR_IO, false, "Unable to write concepts for chip.\n");
+                  return false;
+              }
+          } else if (!pmConceptsWriteFPA(fpa, sources, true, config)) {
+              psError(PS_ERR_IO, false, "Unable to write concepts for FPA.\n");
+              return false;
+          }
+          break;
+      }
+      default:
+        // No action
+        break;
+    }
+
+    return fpa;
+}
+
+// given an already-opened fits file, read the table corresponding to the specified view
+bool pmFPAviewReadFitsTable(const pmFPAview *view, pmFPAfile *file, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    pmFPA *fpa = file->fpa;             // FPA of interest
+    psFits *fits = file->fits;          // FITS file
+
+    if (view->chip == -1) {
+        return pmFPAReadTable(fpa, fits, name) > 0;
+    }
+
+    if (view->cell == -1) {
+        pmChip *chip = pmFPAviewThisChip(view, fpa); // Chip of interest
+        return pmChipReadTable(chip, fits, name) > 0;
+    }
+
+    pmCell *cell = pmFPAviewThisCell(view, fpa); // Cell of interest
+    return pmCellReadTable(cell, fits, name) > 0;
+}
+
+// given an already-opened fits file, write the table corresponding to the specified view
+bool pmFPAviewWriteFitsTable(const pmFPAview *view, pmFPAfile *file, const char *name, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, false); // FPA of interest
+    psFits *fits = file->fits;          // FITS file
+
+    if (view->chip == -1) {
+        return pmFPAWriteTable(fits, fpa, name) > 0;
+    }
+
+    if (view->cell == -1) {
+        pmChip *chip = pmFPAviewThisChip(view, fpa); // Chip of interest
+        return pmChipWriteTable(fits, chip, name) > 0;
+    }
+
+    pmCell *cell = pmFPAviewThisCell(view, fpa); // Cell of interest
+    return pmCellWriteTable(fits, cell, name) > 0;
+}
+
+
+// given an already-opened fits file, read the components corresponding to the specified view
+static bool fpaViewReadFitsImage(const pmFPAview *view, // FPA view, specifying the level of interest
+                                 pmFPAfile *file, // FPA file of interest
+                                 pmConfig *config, // Configuration
+                                 bool (*fpaReadFunc)(pmFPA*, psFits*, pmConfig*), // Function to read FPA
+                                 bool (*chipReadFunc)(pmChip*, psFits*, pmConfig*), // Function to read chip
+                                 bool (*cellReadFunc)(pmCell*, psFits*, pmConfig*) // Function to read cell
+                                )
+{
+    assert(view);
+    assert(file);
+
+    pmFPA *fpa = file->fpa;             // FPA of interest
+    psFits *fits = file->fits;          // FITS file from which to read
+
+    if (view->chip == -1) {
+        return fpaReadFunc(fpa, fits, config);
+    }
+
+    if (view->chip >= fpa->chips->n) {
+        psError(PS_ERR_IO, true, "Requested chip == %d >= fpa->chips->n == %ld", view->chip, fpa->chips->n);
+        return false;
+    }
+    pmChip *chip = fpa->chips->data[view->chip]; // Chip of interest
+
+    if (view->cell == -1) {
+        return chipReadFunc(chip, fits, config);
+    }
+
+    if (view->cell >= chip->cells->n) {
+        psError(PS_ERR_IO, true, "Requested cell == %d >= chip->cells->n == %ld", view->cell, chip->cells->n);
+        return false;
+    }
+    pmCell *cell = chip->cells->data[view->cell]; // Cell of interest
+
+    if (view->readout == -1) {
+        return cellReadFunc(cell, fits, config);
+    }
+    psError(PS_ERR_UNKNOWN, true, "Bad view: %d,%d", view->chip, view->cell);
+    return false;
+
+    // XXX pmReadoutRead, pmReadoutReadSegement disabled for now
+    #if 0
+
+    if (view->readout >= cell->readouts->n) {
+        psError(PS_ERR_IO, true, "Requested readout == %d >= cell->readouts->n == %d",
+                view->readout, cell->readouts->n);
+        return false;
+    }
+    pmReadout *readout = cell->readouts->data[view->readout];
+
+    if (view->nRows == 0) {
+        pmReadoutRead (readout, fits, config);
+    } else {
+        pmReadoutReadSegment (readout, fits, view->nRows, view->iRows, NULL, NULL);
+    }
+    return true;
+    #endif
+}
+
+
+bool pmFPAviewReadFitsImage(const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    return fpaViewReadFitsImage(view, file, config, pmFPARead, pmChipRead, pmCellRead);
+}
+
+bool pmFPAviewReadFitsMask(const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    return fpaViewReadFitsImage(view, file, config, pmFPAReadMask, pmChipReadMask, pmCellReadMask);
+}
+
+bool pmFPAviewReadFitsWeight(const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    return fpaViewReadFitsImage(view, file, config, pmFPAReadWeight, pmChipReadWeight, pmCellReadWeight);
+}
+
+bool pmFPAviewReadFitsDark(const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    return fpaViewReadFitsImage(view, file, config, pmFPAReadDark, pmChipReadDark, pmCellReadDark);
+}
+
+bool pmFPAviewReadFitsHeaderSet(const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    return fpaViewReadFitsImage(view, file, config, pmFPAReadHeaderSet, pmChipReadHeaderSet, pmCellReadHeaderSet);
+}
+
+// given an already-opened fits file, write the components corresponding
+// to the specified view. when the file was opened, pmFPA/Chip/CellWrite was
+// called on it with blank=true to write the (possible) blank PHU
+// do NOT call the functions below with blank=true or they will write
+// out data in an inconsistent fashion
+// the calls below should recurse down the element to write out all components.
+static bool fpaViewWriteFitsImage(const pmFPAview *view, // FPA view, specifying the level of interest
+                                  pmFPAfile *file, // FPA file of interest
+                                  pmConfig *config, // Configuration
+                                  bool (*fpaWriteFunc)(pmFPA*, psFits*, pmConfig*, bool, bool), // Func FPA
+                                  bool (*chipWriteFunc)(pmChip*, psFits*, pmConfig*, bool, bool),// Func chip
+                                  bool (*cellWriteFunc)(pmCell*, psFits*, pmConfig*, bool) // Func cell
+                                 )
+{
+    assert(view);
+    assert(file);
+
+    psFits *fits = file->fits;          // FITS file
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, true); // FPA to write
+
+    switch (pmFPAviewLevel(view)) {
+    case PM_FPA_LEVEL_FPA: {
+            bool success = fpaWriteFunc(fpa, fits, config, false, true);
+            psFree(fpa);
+            return success;
+        }
+    case PM_FPA_LEVEL_CHIP: {
+            pmChip *chip = pmFPAviewThisChip(view, fpa); // Chip of interest
+            bool success = chipWriteFunc(chip, fits, config, false, true);
+            psFree(fpa);
+            return success;
+        }
+    case PM_FPA_LEVEL_CELL: {
+            pmCell *cell = pmFPAviewThisCell(view, fpa); // Cell of interest
+            bool success = cellWriteFunc(cell, fits, config, false);
+            psFree(fpa);
+            return success;
+        }
+    case PM_FPA_LEVEL_READOUT:
+        #if 0 // XXX disable readout write for now
+
+        {
+            pmReadout *readout = pmFPAviewThisReadout(view, file->fpa); // Readout of interest
+            if (changeFormat)
+        {
+            // No copy function defined for readouts!
+            psError(PS_ERR_UNKNOWN, false, "Unable to copy readout for format conversion on write.\n");
+                return false;
+            }
+            if (view->nRows == 0)
+        {
+            return pmReadoutWrite(readout, fits, NULL, NULL);
+            } else
+            {
+                return pmReadoutWriteSegment(readout, fits, view->nRows, view->iRows, NULL, NULL);
+            }
+        }
+        #endif
+    case PM_FPA_LEVEL_NONE:
+    default:
+        psAbort("Should never reach here: invalid file level.");
+    }
+
+    return false;
+}
+
+bool pmFPAviewWriteFitsImage(const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    return fpaViewWriteFitsImage(view, file, config, pmFPAWrite, pmChipWrite, pmCellWrite);
+}
+
+bool pmFPAviewWriteFitsMask(const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    return fpaViewWriteFitsImage(view, file, config, pmFPAWriteMask, pmChipWriteMask, pmCellWriteMask);
+}
+
+bool pmFPAviewWriteFitsWeight(const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    return fpaViewWriteFitsImage(view, file, config, pmFPAWriteWeight, pmChipWriteWeight, pmCellWriteWeight);
+}
+
+bool pmFPAviewWriteFitsDark(const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    return fpaViewWriteFitsImage(view, file, config, pmFPAWriteDark, pmChipWriteDark, pmCellWriteDark);
+}
+
+// given an already-opened fits file, read the components corresponding
+// to the specified view
+bool pmFPAviewFreeData(const pmFPAview *view, pmFPAfile *file)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    pmFPA *fpa = file->fpa;
+
+    if (view->chip == -1) {
+        psTrace ("pmFPAfile", 5, "freeing fpa for %s\n", file->filename);
+        pmFPAFreeData (fpa);
+        // XXX drop me: file->fpa = NULL;
+        return true;
+    }
+
+    if (view->chip >= fpa->chips->n) {
+        psError(PS_ERR_IO, true, "Requested chip == %d >= fpa->chips->n == %ld", view->chip, fpa->chips->n);
+        return false;
+    }
+    pmChip *chip = fpa->chips->data[view->chip];
+
+    if (view->cell == -1) {
+        psTrace ("pmFPAfile", 5, "freeing chip %d for %s\n", view->chip, file->filename);
+        pmChipFreeData (chip);
+        return true;
+    }
+
+    if (view->cell >= chip->cells->n) {
+        psError(PS_ERR_IO, true, "Requested cell == %d >= chip->cells->n == %ld", view->cell, chip->cells->n);
+        return false;
+    }
+    pmCell *cell = chip->cells->data[view->cell];
+
+    if (view->readout == -1) {
+        psTrace ("pmFPAfile", 5, "freeing cell %d for %s\n", view->cell, file->filename);
+        pmCellFreeData (cell);
+        return true;
+    }
+    psError(PS_ERR_UNKNOWN, true, "Returning false");
+    return false;
+
+    // XXX pmReadoutRead, pmReadoutReadSegement disabled for now
+    #if 0
+
+    if (view->readout >= cell->readouts->n) {
+        psError(PS_ERR_IO, true, "Requested readout == %d >= cell->readouts->n == %d",
+                view->readout, cell->readouts->n);
+        return false;
+    }
+    pmReadout *readout = cell->readouts->data[view->readout];
+
+    if (view->nRows == 0) {
+        pmReadoutRead (readout, fits, NULL);
+    } else {
+        pmReadoutReadSegment (readout, fits, view->nRows, view->iRows, NULL, NULL);
+    }
+    return true;
+    #endif
+}
+
+#if 0
+// Shouldn't need this --- when we want to free fringe data, we want to free the whole level, not just the
+// table.
+
+// Free the table within a cell
+static void freeTable(pmCell *cell,     // Cell of interest
+                      const char *name  // Name of table to free
+                     )
+{
+    assert(cell);
+    assert(name && strlen(name) > 0);
+
+    psString headerName = NULL;         // Name of header
+    psStringAppend(&headerName, "%s.HEADER", name);
+    if (psMetadataLookup(cell->analysis, headerName)) {
+        psMetadataRemoveKey(cell->analysis, headerName);
+    }
+    psFree(headerName);
+
+    if (psMetadataLookup(cell->analysis, name)) {
+        psMetadataRemoveKey(cell->analysis, name);
+    }
+
+    return;
+}
+
+// given a file, free the components corresponding to the specified view
+bool pmFPAviewFreeFitsTable (const pmFPAview *view, pmFPAfile *file, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    pmFPA *fpa = file->fpa;
+
+    if (view->chip == -1) {
+        psArray *chips = fpa->chips;    // Array of chips
+        for (int i = 0; i < chips->n; i++) {
+            pmChip *chip = chips->data[i]; // Chip of interest
+            psArray *cells = chip->cells; // Array of cells
+            for (int j = 0; j < cells->n; j++) {
+                pmCell *cell = cells->data[j]; // Cell of interest
+                freeTable(cell, name);
+            }
+        }
+        return true;
+    }
+
+    if (view->cell == -1) {
+        pmChip *chip = pmFPAviewThisChip(view, fpa); // Chip of interest
+        psArray *cells = chip->cells;   // Array of cells
+        for (int i = 0; i < cells->n; i++) {
+            pmCell *cell = cells->data[i]; // Cell of interest
+            freeTable(cell, name);
+        }
+        return true;
+    }
+
+    pmCell *cell = pmFPAviewThisCell(view, fpa); // Cell of interest
+    freeTable(cell, name);
+    return true;
+}
+
+#endif
+
+bool pmFPAviewFitsWritePHU (const pmFPAview *view, pmFPAfile *file, pmConfig *config) {
+
+    bool status = false;
+
+    if (file->mode != PM_FPA_MODE_WRITE) return true;
+    if (file->wrote_phu) return true;
+
+    // select or generate the desired fpa in the correct output format
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, false);
+    pmHDU *phu = pmFPAviewThisHDU(view, fpa);
+    if (!phu || !phu->blankPHU) {
+        // No PHU to write!
+        psFree(fpa);
+        return true;
+    }
+
+    // whenever we write out a mask image, we should define the bits which represent mask concepts
+    if (file->type == PM_FPA_FILE_MASK) {
+        assert (phu->header);
+        if (!pmConfigMaskWriteHeader (config, phu->header)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to set the bitmask names in the PHU header for Image %s (%s)\n", file->filename, file->name);
+            return false;
+        }
+    }
+
+    switch (file->fileLevel) {
+      case PM_FPA_LEVEL_FPA:
+        status = pmFPAWrite(fpa, file->fits, config, true, false);
+        break;
+      case PM_FPA_LEVEL_CHIP: {
+          pmChip *chip = pmFPAviewThisChip(view, fpa);
+          status = pmChipWrite(chip, file->fits, config, true, false);
+          break;
+      }
+      case PM_FPA_LEVEL_CELL: {
+          pmCell *cell = pmFPAviewThisCell(view, fpa);
+          status = pmCellWrite(cell, file->fits, config, true);
+          break;
+      }
+      default:
+        psAbort("fileLevel not correctly set");
+        break;
+    }
+
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to write PHU for Image %s (%s)\n", file->filename, file->name);
+        return false;
+    }
+
+    psFree(fpa);
+    file->wrote_phu = true;
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfileFitsIO.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfileFitsIO.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfileFitsIO.h	(revision 22158)
@@ -0,0 +1,106 @@
+/* @file  pmFPAview.h
+ * @brief Tools to manipulate the FPA structure elements.
+ *
+ * @author EAM, IfA
+ * @author PAP, IfA
+ *
+ * @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-17 22:38:15 $
+ * Copyright 2004-2005 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FPA_FILE_FITS_IO_H
+#define PM_FPA_FILE_FITS_IO_H
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+/// Read an image into the current view
+bool pmFPAviewReadFitsImage(const pmFPAview *view, ///< View specifying level of interest
+                            pmFPAfile *file, ///< FPA file into which to read
+                            pmConfig *config
+                           );
+
+/// Read a mask into the current view
+bool pmFPAviewReadFitsMask(const pmFPAview *view, ///< View specifying level of interest
+                           pmFPAfile *file, ///< FPA file into which to read
+                            pmConfig *config
+                          );
+/// Read a weight map into the current view
+bool pmFPAviewReadFitsWeight(const pmFPAview *view,  ///< View specifying level of interest
+                             pmFPAfile *file, ///< FPA file into which to read
+                            pmConfig *config
+                            );
+
+/// Read a dark into the current view
+bool pmFPAviewReadFitsDark(const pmFPAview *view,  ///< View specifying level of interest
+                           pmFPAfile *file, ///< FPA file into which to read
+                            pmConfig *config
+    );
+
+/// Read an image header into the current view
+bool pmFPAviewReadFitsHeaderSet(const pmFPAview *view,  ///< View specifying level of interest
+                                pmFPAfile *file, ///< FPA file into which to read
+                            pmConfig *config
+    );
+
+/// Write the image for the specified view
+bool pmFPAviewWriteFitsImage(const pmFPAview *view, ///< View specifying level of interest
+                             pmFPAfile *file, ///< FPA file to write
+                             pmConfig *config ///< Configuration
+                            );
+
+/// Write the mask for the specified view
+bool pmFPAviewWriteFitsMask(const pmFPAview *view, ///< View specifying level of interest
+                            pmFPAfile *file, ///< FPA file to write
+                            pmConfig *config ///< Configuration
+                           );
+
+/// Write the weight map for the specified view
+bool pmFPAviewWriteFitsWeight(const pmFPAview *view, ///< View specifying level of interest
+                              pmFPAfile *file, ///< FPA file to write
+                              pmConfig *config ///< Configuration
+                             );
+
+/// Write the dark for the specified view
+bool pmFPAviewWriteFitsDark(const pmFPAview *view, ///< View specifying level of interest
+                            pmFPAfile *file, ///< FPA file to write
+                            pmConfig *config ///< Configuration
+    );
+
+/// Write a PHU for a fits image if needed
+bool pmFPAviewFitsWritePHU (const pmFPAview *view, pmFPAfile *file, pmConfig *config);
+
+/// Free the data for the specified view
+bool pmFPAviewFreeData(const pmFPAview *view, ///< View specifying level of interest
+                       pmFPAfile *file  ///< FPA file to free data
+                      );
+
+/// Read a table into the current view
+bool pmFPAviewReadFitsTable(const pmFPAview *view, ///<  View specifying level of interest
+                            pmFPAfile *file, ///< FPA file into which to read
+                            const char *name ///< Name of table
+                           );
+
+/// Write the table for the specified view
+bool pmFPAviewWriteFitsTable(const pmFPAview *view, ///<  View specifying level of interest
+                             pmFPAfile *file, ///< FPA file to write
+                             const char *name, ///< Name of table
+                             pmConfig *config ///< Configuration
+                            );
+
+/// Produce a suitable FPA for writing, on the basis of the input FPAfile
+///
+/// A new FPA with a changed format is generated if required (file->format is set and file->camera is equal to
+/// the default, indicating a change in the format without changing the camera --- changes to the camera are
+/// handled using other systems --- see pmFPAfileDefineChipMosaic, pmFPAfileDefineFPAMosaic).  Otherwise the
+/// file->fpa is returned (incremented).
+pmFPA *pmFPAfileSuitableFPA(const pmFPAfile *file,///< File containing the fpa
+                            const pmFPAview *view, ///< View at which to produce the fpa
+                            pmConfig *config, ///< Configuration
+                            bool pixels ///< Worry about copying the pixels?
+                           );
+
+/// @}
+
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfileIO.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfileIO.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfileIO.c	(revision 22158)
@@ -0,0 +1,978 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>            /* for strn?casecmp */
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmConfigMask.h"
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAMaskWeight.h"
+#include "pmFPAview.h"
+#include "pmFPAFlags.h"
+#include "pmFPAfile.h"
+#include "pmFPACopy.h"
+#include "pmFPARead.h"
+#include "pmFPAWrite.h"
+#include "pmFPAfileIO.h"
+#include "pmFPAfileFitsIO.h"
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmResiduals.h"
+#include "pmGrowthCurve.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmSourceIO.h"
+#include "pmResiduals.h"
+#include "pmPSF_IO.h"
+#include "pmAstrometryModel.h"
+#include "pmAstrometryRefstars.h"
+#include "pmFPA_JPEG.h"
+#include "pmSourcePlots.h"
+#include "pmFPAConstruct.h"
+#include "pmConcepts.h"
+
+// attempt create, read, write, close, or free pmFPAfiles available in files files are
+// automatically opened before they are read.  In the case of MEF files, the PHU is
+// read when the file is opened and written before the first extension is written.
+bool pmFPAfileIOChecks (pmConfig *config, const pmFPAview *view, pmFPAfilePlace place)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(config->files, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    psMetadata *files = config->files;
+
+    // attempt to perform all create, read, write, close operations
+    psMetadataItem *item = NULL;
+    psMetadataIterator *iter = psMetadataIteratorAlloc (files, PS_LIST_HEAD, NULL);
+    while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
+        pmFPAfile *file = item->data.V;
+
+        switch (place) {
+        case PM_FPA_BEFORE:
+            if (!pmFPAfileRead (file, view, config)) {
+                psError(PS_ERR_IO, false, "failed READ in FPA_BEFORE block for %s", file->name);
+                goto failure;
+            }
+            if (!pmFPAfileCreate(file, view, config)) {
+                psError(PS_ERR_IO, false, "failed CREATE in FPA_BEFORE block for %s", file->name);
+                goto failure;
+            }
+            break;
+        case PM_FPA_AFTER:
+            if (!pmFPAfileWrite (file, view, config)) {
+                psError(PS_ERR_IO, false, "failed WRITE in FPA_AFTER block for %s", file->name);
+                goto failure;
+            }
+            if (!pmFPAfileClose(file, view)) {
+                psError(PS_ERR_IO, false, "failed CLOSE in FPA_AFTER block for %s", file->name);
+                goto failure;
+            }
+            break;
+        default:
+            psAbort("You can't get here");
+        }
+    }
+
+    // attempt to free data that is no longer needed
+    psMetadataIteratorSet (iter, PS_LIST_HEAD);
+    while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
+        pmFPAfile *file = item->data.V;
+
+        switch (place) {
+        case PM_FPA_BEFORE:
+            break;
+        case PM_FPA_AFTER:
+            if (!pmFPAfileFreeData(file, view)) {
+                if (!psMetadataRemoveKey(files, file->name)) {
+                    psError(PS_ERR_IO, false, "failed to remove %s in FPA_AFTER block", file->name);
+                    goto failure;
+                }
+            }
+            break;
+        default:
+            psAbort("You can't get here");
+        }
+    }
+    psFree (iter);
+    return true;
+
+failure:
+    psFree (iter);
+    return false;
+}
+
+// read the file, if necessary and possible
+bool pmFPAfileRead(pmFPAfile *file, const pmFPAview *view, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    // an internal file should not be sent here (should not be left on config->files)
+    PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
+
+    // skip the following states
+    if (file->state & PM_FPA_STATE_INACTIVE) {
+        psTrace("psModules.camera", 6, "skip read for %s, file is inactive", file->name);
+        return true;
+    }
+    if (file->mode != PM_FPA_MODE_READ) {
+        psTrace("psModules.camera", 6, "skip read for %s, mode is not READ", file->name);
+        return true;
+    }
+
+    // get the current level
+    pmFPALevel level = pmFPAviewLevel (view);
+
+    // do we need to read this file? defer until we read the correct level
+    if (level != file->dataLevel) {
+        psTrace("psModules.camera", 6, "skip reading of %s at this level %s: dataLevel is %s",
+                file->name, pmFPALevelToName(level), pmFPALevelToName(file->dataLevel));
+        return true;
+    }
+
+    // do we need to open this file?
+    if (level >= file->fileLevel) {
+        // we are allowed to open a file at a level which is not the fileLevel, but we need to
+        // supply a view at the fileLevel for the file lookup functions below
+        pmFPAview *fileView = pmFPAviewForLevel (file->fileLevel, view);
+        if (!pmFPAfileOpen (file, fileView, config)) {
+            psError(PS_ERR_IO, false, "failed to open file %s (%s)", file->filename, file->name);
+            psFree (fileView);
+            return false;
+        }
+        psFree (fileView);
+    }
+
+    // We need to read it --- double-check it's open!
+    if (file->state == PM_FPA_STATE_CLOSED) {
+        psError(PS_ERR_IO, false, "failed to open file %s when attempting to read", file->name);
+        return false;
+    }
+
+    // select a reading method
+    bool status = true;
+    switch (file->type) {
+      case PM_FPA_FILE_IMAGE:
+        status = pmFPAviewReadFitsImage(view, file, config);
+        break;
+      case PM_FPA_FILE_MASK:
+        status = pmFPAviewReadFitsMask(view, file, config);
+        break;
+      case PM_FPA_FILE_WEIGHT:
+        status = pmFPAviewReadFitsWeight(view, file, config);
+        break;
+      case PM_FPA_FILE_HEADER:
+        status = pmFPAviewReadFitsHeaderSet(view, file, config);
+        break;
+      case PM_FPA_FILE_DARK:
+        status = pmFPAviewReadFitsDark(view, file, config);
+        break;
+      case PM_FPA_FILE_FRINGE:
+        status = pmFPAviewReadFitsImage(view, file, config);
+        if (status) {
+            if (!pmFPAviewReadFitsTable(view, file, "FRINGE")) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to read fringe data from %s.\n", file->filename);
+                return false;
+            }
+        }
+        break;
+      case PM_FPA_FILE_SX:
+      case PM_FPA_FILE_RAW:
+      case PM_FPA_FILE_OBJ:
+      case PM_FPA_FILE_CMP:
+      case PM_FPA_FILE_CMF:
+        status = pmFPAviewReadObjects (view, file, config);
+        break;
+      case PM_FPA_FILE_PSF:
+        status = pmPSFmodelReadForView (view, file, config);
+        break;
+      case PM_FPA_FILE_ASTROM_MODEL:
+        status = pmAstromModelReadForView (view, file, config);
+        break;
+      case PM_FPA_FILE_ASTROM_REFSTARS:
+      case PM_FPA_FILE_JPEG:
+      case PM_FPA_FILE_KAPA:
+        break;
+      default:
+        psError(PS_ERR_IO, true, "warning: type mismatch; saw type %d (%s)", file->type, file->name);
+        return false;
+    }
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to read %s (%s)\n", file->filename, file->name);
+        return false;
+    }
+    psTrace ("psModules.camera", 5, "read %s (%s) (%d:%d:%d)\n", file->filename, file->name, view->chip, view->cell, view->readout);
+    return true;
+}
+
+// create the data elements (headers, images) appropriate for this view
+bool pmFPAfileCreate (pmFPAfile *file, const pmFPAview *view, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    // these are not error conditions; these are state tests
+    if (file->state & PM_FPA_STATE_INACTIVE) {
+        psTrace("psModules.camera", 6, "skip create for inactive file %s", file->name);
+        return true;
+    }
+    if (file->mode != PM_FPA_MODE_WRITE) {
+        psTrace("psModules.camera", 6, "skip create for non-write file %s", file->name);
+        return true;
+    }
+
+    // an internal file should not be returned to here
+    PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
+
+    // get the current level
+    pmFPALevel level = pmFPAviewLevel (view);
+
+    // don't create the file if the src (FPA) is not defined
+    if (file->src == NULL) {
+        psTrace("psModules.camera", 6, "skip create for FPA without src FPA for %s", file->name);
+        return true;
+    }
+
+    // do we need to write this file?
+    if (level != file->fileLevel || file->mosaicLevel != PM_FPA_LEVEL_NONE) {
+        psTrace("psModules.camera", 6, "skip creation of %s at this level %s: fileLevel is %s",
+                file->name, pmFPALevelToName(level), pmFPALevelToName(file->fileLevel));
+        return true;
+    }
+
+    switch (file->type) {
+      case PM_FPA_FILE_IMAGE:
+      case PM_FPA_FILE_MASK:
+      case PM_FPA_FILE_WEIGHT:
+      case PM_FPA_FILE_FRINGE:
+      case PM_FPA_FILE_DARK: {
+            // create FPA structure component based on view
+            psMetadata *format = file->format; // Camera format configuration
+            if (!format) {
+                format = config->format;
+            }
+
+            pmFPA *nameSource = file->src; // Source of FPA.OBS
+            if (!nameSource) {
+                nameSource = file->fpa;
+            }
+            bool mdok;                  // Status of MD lookup
+            const char *fpaObs = psMetadataLookupStr(&mdok, nameSource->concepts, "FPA.OBS"); // Obs. id
+
+            pmFPAAddSourceFromView(file->fpa, fpaObs, view, format);
+            psTrace ("psModules.camera", 5, "created fpa data elements for %s (%s) (%d:%d:%d)\n",
+                     file->name, file->name, view->chip, view->cell, view->readout);
+            break;
+    }
+    case PM_FPA_FILE_HEADER:
+      psAbort ("Create not defined for HEADER");
+      break;
+    case PM_FPA_FILE_SX:
+    case PM_FPA_FILE_RAW:
+    case PM_FPA_FILE_OBJ:
+    case PM_FPA_FILE_CMP:
+    case PM_FPA_FILE_CMF:
+    case PM_FPA_FILE_PSF:
+    case PM_FPA_FILE_ASTROM_MODEL:
+    case PM_FPA_FILE_ASTROM_REFSTARS:
+    case PM_FPA_FILE_JPEG:
+    case PM_FPA_FILE_KAPA:
+        break;
+
+    default:
+        psError(PS_ERR_IO, true, "Unsupported type for %s: %d", file->name, file->type);
+        return false;
+    }
+    return true;
+}
+
+bool pmFPAfileWrite(pmFPAfile *file, const pmFPAview *view, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    if (file->state & PM_FPA_STATE_INACTIVE) {
+        psTrace("psModules.camera", 6, "skip write for %s, files is inactive", file->name);
+        return true;
+    }
+
+    if (file->mode != PM_FPA_MODE_WRITE) {
+        psTrace("psModules.camera", 6, "skip write for %s, mode is not WRITE", file->name);
+        return true;
+    }
+
+    // an internal file should not be returned to here
+    if (file->mode == PM_FPA_MODE_INTERNAL) {
+        psError(PS_ERR_IO, true, "File is mode PM_FPA_MODE_INTERNAL");
+        return false;
+    }
+
+    if (!file->save) {
+        psTrace("psModules.camera", 6, "skip write for %s, save is FALSE", file->name);
+        return true;
+    }
+
+    // get the current level
+    pmFPALevel level = pmFPAviewLevel (view);
+
+    // the effective dataLevel (for mosaics, we have preserved the original dataLevel)
+    pmFPALevel dataLevel = file->dataLevel;
+    if (file->mosaicLevel != PM_FPA_LEVEL_NONE && file->mosaicLevel < dataLevel) {
+        dataLevel = file->mosaicLevel;
+    }
+
+    // do we need to write this file?
+    if (level != dataLevel) {
+        psTrace("psModules.camera", 6, "skip writing of %s at this level %s: dataLevel is %s",
+                file->name, pmFPALevelToName(level), pmFPALevelToName(dataLevel));
+        return true;
+    }
+
+    // do we have data to write at this level?
+    if (!pmFPAviewCheckDataStatus (file->fpa, view)) {
+        psTrace("psModules.camera", 6, "skip write for %s, no data for this entry", file->name);
+        return true;
+    }
+
+    // note that for CMF and PSF, the test above is not sufficient to determine if there
+    // is actually any data to write out.  this is because these types of output files
+    // have their data stored on the readout->analysis metadata structure of another
+    // (existing) fpa
+    if (file->type == PM_FPA_FILE_CMF) {
+        if (!pmFPAviewCheckDataStatusForSources (view, file)) {
+        psTrace("psModules.camera", 6, "skip write for %s, no data for this entry", file->name);
+        return true;
+      }
+    }
+    if (file->type == PM_FPA_FILE_PSF) {
+      if (!pmPSFmodelCheckDataStatusForView (view, file)) {
+        psTrace("psModules.camera", 6, "skip write for %s, no data for this entry", file->name);
+        return true;
+      }
+    }
+    if (file->type == PM_FPA_FILE_ASTROM_MODEL) {
+      if (!pmAstromModelCheckDataStatusForView (view, file)) {
+        psTrace("psModules.camera", 6, "skip write for %s, no data for this entry", file->name);
+        return true;
+      }
+    }
+    if (file->type == PM_FPA_FILE_ASTROM_REFSTARS) {
+      if (!pmAstromRefstarsCheckDataStatusForView (view, file)) {
+        psTrace("psModules.camera", 6, "skip write for %s, no data for this entry", file->name);
+        return true;
+      }
+    }
+
+    // open the file if not yet opened
+    // XXX do we need to test mosaicLevel?
+    if (level >= file->fileLevel) {
+        // we are allowed to open a file at a level which is not the fileLevel, but
+        // we need to supply view at the fileLevel for the file lookup functions below
+        pmFPAview *fileView = pmFPAviewForLevel (file->fileLevel, view);
+        if (!pmFPAfileOpen (file, fileView, config)) {
+            psError(PS_ERR_IO, false, "failed to open %s (%s)", file->filename, file->name);
+            psFree (fileView);
+            return false;
+        }
+
+        // do we need to write out a PHU?
+        if (!pmFPAfileWritePHU(file, fileView, config)) {
+            psError(PS_ERR_IO, false, "failed to write phu for %s (%s)", file->filename, file->name);
+            return false;
+        }
+
+        psFree (fileView);
+    }
+
+    if (file->compression) {
+        psTrace("psModules.camera", 7, "Setting compression for %s (%s)\n", file->filename, file->name);
+        if (!psFitsCompressionApply(file->fits, file->compression)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to set compression options for %s (%s) (%d:%d:%d)\n",
+                    file->filename, file->name, view->chip, view->cell, view->readout);
+            return false;
+        }
+    }
+
+    // IMPORTANT: If adding a FITS-based file, make sure your write function uses an FPA produced by
+    // pmFPAfileSuitableFPA.  This ensures the HDUs are at the correct level for your output format, and sets
+    // the headers correctly.
+
+    // select a writing method
+    bool status = true;
+    switch (file->type) {
+      case PM_FPA_FILE_IMAGE:
+        status = pmFPAviewWriteFitsImage(view, file, config);
+        break;
+      case PM_FPA_FILE_MASK:
+        status = pmFPAviewWriteFitsMask(view, file, config);
+        break;
+      case PM_FPA_FILE_WEIGHT:
+        status = pmFPAviewWriteFitsWeight(view, file, config);
+        break;
+      case PM_FPA_FILE_HEADER:
+        psAbort ("no HEADER write functions defined");
+        break;
+      case PM_FPA_FILE_DARK:
+        status = pmFPAviewWriteFitsDark(view, file, config);
+        break;
+      case PM_FPA_FILE_FRINGE:
+        status = pmFPAviewWriteFitsImage (view, file, config);
+        if (status) {
+            if (!pmFPAviewWriteFitsTable(view, file, "FRINGE", config)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to write fringe data from %s.\n", file->filename);
+                return false;
+            }
+        }
+        break;
+      case PM_FPA_FILE_SX:
+      case PM_FPA_FILE_RAW:
+      case PM_FPA_FILE_OBJ:
+      case PM_FPA_FILE_CMP:
+      case PM_FPA_FILE_CMF:
+        status = pmFPAviewWriteObjects (view, file, config);
+        break;
+
+      case PM_FPA_FILE_PSF:
+        status = pmPSFmodelWriteForView (view, file, config);
+        break;
+
+      case PM_FPA_FILE_ASTROM_MODEL:
+        status = pmAstromModelWriteForView (view, file, config);
+        break;
+
+      case PM_FPA_FILE_ASTROM_REFSTARS:
+        status = pmAstromRefstarsWriteForView (view, file, config);
+        break;
+
+      case PM_FPA_FILE_JPEG:
+        status = pmFPAviewWriteJPEG (view, file, config);
+        break;
+
+      case PM_FPA_FILE_KAPA:
+        status = pmFPAviewWriteSourcePlot (view, file, config);
+        break;
+
+      default:
+        psError(PS_ERR_IO, true, "warning: type mismatch; saw type %d (%s)", file->type, file->name);
+        return false;
+    }
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to write %s (%s)\n", file->filename, file->name);
+        return false;
+    }
+    psTrace ("psModules.camera", 5, "wrote %s (%s) (%d:%d:%d)\n", file->filename, file->name, view->chip, view->cell, view->readout);
+    return true;
+}
+
+bool pmFPAfileClose (pmFPAfile *file, const pmFPAview *view)
+{
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    // an internal file should not be sent here (should not be left on config->files)
+    PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
+
+    // skip the following states
+    if (file->state & PM_FPA_STATE_INACTIVE) {
+        psTrace("psModules.camera", 6, "skip close for %s, files is inactive", file->name);
+        return true;
+    }
+    if (file->state == PM_FPA_STATE_CLOSED) {
+        psTrace("psModules.camera", 6, "skip close for %s, files is closed", file->name);
+        return true;
+    }
+
+    // is current level == open level?
+    pmFPALevel level = pmFPAviewLevel (view);
+    if (file->fileLevel != level) {
+        psTrace("psModules.camera", 6, "skip closing of %s at this level %s: fileLevel is %s",
+                file->name, pmFPALevelToName(level), pmFPALevelToName(file->fileLevel));
+        return true;
+    }
+
+    // check if we are actually open
+    bool status = true;
+    switch (file->type) {
+        // check the FITS types
+      case PM_FPA_FILE_IMAGE:
+      case PM_FPA_FILE_MASK:
+      case PM_FPA_FILE_WEIGHT:
+      case PM_FPA_FILE_HEADER:
+      case PM_FPA_FILE_FRINGE:
+      case PM_FPA_FILE_DARK:
+      case PM_FPA_FILE_CMF:
+      case PM_FPA_FILE_PSF:
+      case PM_FPA_FILE_ASTROM_MODEL:
+      case PM_FPA_FILE_ASTROM_REFSTARS:
+        psTrace ("psModules.camera", 5, "closing %s (%s) (%d:%d:%d)\n", file->filename, file->name, view->chip, view->cell, view->readout);
+        status = psFitsClose (file->fits);
+        file->fits = NULL;
+        file->header = NULL;
+        file->state = PM_FPA_STATE_CLOSED;
+        file->wrote_phu = false;
+        break;
+
+        // ignore the TEXT types
+      case PM_FPA_FILE_SX:
+      case PM_FPA_FILE_RAW:
+      case PM_FPA_FILE_OBJ:
+      case PM_FPA_FILE_CMP:
+      case PM_FPA_FILE_JPEG:
+      case PM_FPA_FILE_KAPA:
+        break;
+
+      default:
+        psError(PS_ERR_IO, true, "type mismatch: %d (%s)", file->type, file->name);
+        return false;
+    }
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to close %s (%s) (%d:%d:%d)\n", file->filename, file->name, view->chip, view->cell, view->readout);
+        return false;
+    }
+    return true;
+}
+
+bool pmFPAfileFreeData(pmFPAfile *file, const pmFPAview *view)
+{
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    // an internal file should not be sent here (should not be left on config->files)
+    PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
+
+    if (file->state & PM_FPA_STATE_INACTIVE) {
+        psTrace("psModules.camera", 6, "skip free for %s, files is inactive", file->name);
+        return true;
+    }
+
+    // get the current level
+    pmFPALevel level = pmFPAviewLevel (view);
+
+    // do we need to free this file?
+    if (level != file->freeLevel) {
+        psTrace("psModules.camera", 6, "skip free of %s at this level %s: freeLevel is %s",
+                file->name, pmFPALevelToName(level), pmFPALevelToName(file->freeLevel));
+        return true;
+    }
+
+    bool status = true;
+    switch (file->type) {
+      case PM_FPA_FILE_IMAGE:
+      case PM_FPA_FILE_MASK:
+      case PM_FPA_FILE_WEIGHT:
+      case PM_FPA_FILE_HEADER:
+      case PM_FPA_FILE_FRINGE:
+      case PM_FPA_FILE_DARK:
+        status = pmFPAviewFreeData(view, file);
+        break;
+      case PM_FPA_FILE_SX:
+      case PM_FPA_FILE_RAW:
+      case PM_FPA_FILE_OBJ:
+      case PM_FPA_FILE_CMP:
+      case PM_FPA_FILE_CMF:
+      case PM_FPA_FILE_PSF:
+      case PM_FPA_FILE_ASTROM_MODEL:
+      case PM_FPA_FILE_ASTROM_REFSTARS:
+        psTrace ("psModules.camera", 6, "NOT freeing %s (%s) : save for further analysis\n", file->filename, file->name);
+        return true;
+      case PM_FPA_FILE_JPEG:
+      case PM_FPA_FILE_KAPA:
+        psTrace ("psModules.camera", 5, "nothing to free for %s (%s)\n", file->filename, file->name);
+        return true;
+      default:
+        psError(PS_ERR_IO, true, "warning: type mismatch; saw type %d", file->type);
+        return false;
+    }
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to read %s (%s)\n", file->filename, file->name);
+        return false;
+    }
+    psTrace ("psModules.camera", 5, "freed %s (%s) (%d:%d:%d)\n", file->filename, file->name, view->chip, view->cell, view->readout);
+    return true;
+}
+
+// open file (if not already opened).
+// this function is only called only within pmFPAfileRead or pmFPAfileWrite.
+bool pmFPAfileOpen (pmFPAfile *file, const pmFPAview *view, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    bool status;
+    char *mode = NULL;
+    char *readMode = "r";
+    char *writeMode = "w";
+
+    if (file->state & PM_FPA_STATE_INACTIVE) {
+        psTrace("psModules.camera", 6, "skip open for %s, files is inactive", file->name);
+        return true;
+    }
+
+    if (file->state == PM_FPA_STATE_OPEN) {
+        return true;
+    }
+
+    // these are programming errors
+    PS_ASSERT(file->mode != PM_FPA_MODE_NONE, false);
+    PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
+
+    if (file->mode == PM_FPA_MODE_READ) {
+        mode = readMode;
+    }
+    if (file->mode == PM_FPA_MODE_WRITE) {
+        mode = writeMode;
+    }
+    if ((file->mode == PM_FPA_MODE_WRITE) && !file->save) {
+        psTrace("psModules.camera", 6, "skip open for %s, output file not requested", file->name);
+        return true;
+    }
+
+    // determine the file name, free a name allocated earlier
+    psFree (file->filename);
+    file->filename = pmFPAfileNameFromRule (file->filerule, file, view);
+    if (file->filename == NULL) {
+        psError(PS_ERR_IO, true, "Filename is NULL");
+        return false;
+    }
+
+    // indirect filenames: these come from a list on the command line or elsewhere
+    if (!strcasecmp (file->filename, "@FILES")) {
+        char *filesrc = pmFPAfileNameFromRule (file->filesrc, file, view);
+        if (filesrc == NULL) {
+            psError(PS_ERR_IO, false, "error converting filesrc to name %s\n", file->filesrc);
+            return false;
+        }
+
+        psFree (file->filename);
+        file->filename = psMetadataLookupStr (&status, file->names, filesrc);
+
+        if (file->filename == NULL) {
+            psError(PS_ERR_IO, true, "filename lookup error (@FILES) for %s : %s\n", file->filesrc, filesrc);
+            psFree (filesrc);
+            return false;
+        }
+        // psMetadataLookupStr just returns a view, file->filename must be protected
+        psMemIncrRefCounter (file->filename);
+        psFree (filesrc);
+    }
+
+    // get name from detrend database
+    // file->detrend->detID contains the desired -det_id detID -iteration iter string
+    if (!strcasecmp (file->filename, "@DETDB")) {
+        if (!file->detrend) {
+            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find information about selected detrend.");
+            return false;
+        }
+
+        psString classId = NULL;        // The class identifier, to pass to pmDetrendFile
+        psMetadata *menu = psMetadataLookupMetadata(&status, file->camera, "CLASSID"); // Menu of class IDs
+        if (!status || !menu) {
+            psError(PS_ERR_IO, false, "Unable to find CLASSID metadata in camera configuration");
+            return false;
+        }
+        const char *rule = psMetadataLookupStr(&status, menu, file->detrend->level); // Rule for class_id
+        if (!status || !rule || strlen(rule) == 0) {
+            psError(PS_ERR_IO, false, "Unable to find %s in CLASSID in camera configuration", file->detrend->level);
+            return false;
+        }
+        classId = pmFPAfileNameFromRule(rule, file, view);
+        if (!classId) {
+            psError(PS_ERR_IO, false, "error converting CLASSID rule to name: %s\n", rule);
+            return false;
+        }
+        psTrace ("psModules.camera", 6, "looking for detrend (%s, %s)\n", file->detrend->detID, classId);
+        psFree (file->filename);
+
+        file->filename = pmDetrendFile(file->detrend->detID, classId, config);
+        if (file->filename == NULL) {
+            psError(PS_ERR_IO, false, "failed to find a valid detrend image for detID %s : classID %s\n", file->detrend->detID, classId);
+            psFree (classId);
+            return false;
+        }
+
+        psTrace ("psModules.camera", 6, "got detrend file %s\n", file->filename);
+        psFree (classId);
+    }
+
+    // apply filename mangling rules (file://, path://, neb://)
+    bool create = file->mode == PM_FPA_MODE_WRITE ? true : false;
+    psString tmpName = pmConfigConvertFilename (file->filename, config, create, false);
+    psFree (file->filename);
+    file->filename = tmpName;
+
+    switch (file->type) {
+        // open the FITS types:
+      case PM_FPA_FILE_IMAGE:
+      case PM_FPA_FILE_MASK:
+      case PM_FPA_FILE_WEIGHT:
+      case PM_FPA_FILE_HEADER:
+      case PM_FPA_FILE_FRINGE:
+      case PM_FPA_FILE_DARK:
+      case PM_FPA_FILE_CMF:
+      case PM_FPA_FILE_PSF:
+      case PM_FPA_FILE_ASTROM_MODEL:
+      case PM_FPA_FILE_ASTROM_REFSTARS:
+        psTrace ("psModules.camera", 5, "opening %s (%s) (%d:%d:%d)\n",
+                 file->filename, file->name, view->chip, view->cell, view->readout);
+        file->fits = psFitsOpen (file->filename, mode);
+        if (file->fits == NULL) {
+            psError(PS_ERR_IO, false, "error opening file %s\n", file->filename);
+            return false;
+        }
+        file->state = PM_FPA_STATE_OPEN;
+
+        file->fits->options = psMemIncrRefCounter(file->options);
+
+        // in most cases, we have already open and read the phu and determined the format.
+        // in some cases, (eg DetDB images), we have only just determined the filename.
+        // we need to check the file format before we can work with the file
+        if (!file->format) {
+          psMetadata *phu = psFitsReadHeader (NULL, file->fits);
+          if (!phu) {
+            psError(PS_ERR_IO, false, "Failed to read file header %s\n", file->filename);
+            return false;
+          }
+
+          // XXX if we have a mask file, then we need to read the mask bit names
+          // defined for this file
+          if (file->type == PM_FPA_FILE_MASK) {
+            if (!pmConfigMaskReadHeader (config, phu)) {
+                psError(PS_ERR_IO, false, "error in mask bits");
+                return false;
+            }
+          }
+
+          // determine the current format from the header
+          // determine camera if not specified already
+          // XXX can I actually reach this with camera not specified??
+          file->format = pmConfigCameraFormatFromHeader (NULL, NULL, config, phu, true);
+          if (!file->format) {
+            psError(PS_ERR_IO, false, "Failed to read CCD format from %s\n", file->filename);
+            psFree(phu);
+            return false;
+          }
+          psFree(phu);
+        }
+
+        // if needed, set the optional EXTWORD field based on the camera value
+        psMetadata *fileMenu = psMetadataLookupMetadata (NULL, file->format, "FILE");
+        if (!fileMenu) {
+          psError (PS_ERR_IO, true, "FILE METADATA missing from camera format %s\n",
+                   config->formatName);
+          return false;
+        }
+        char *extword = psMetadataLookupStr (&status, fileMenu, "EXTWORD");
+        if (status) {
+          psFitsSetExtnameWord (file->fits, extword);
+        }
+
+        // XXX these are probably only needed for WRITE files
+        if (file->compression) {
+            psTrace("psModules.camera", 7, "Setting compression for %s (%s)\n", file->filename, file->name);
+            if (!psFitsCompressionApply(file->fits, file->compression)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to set compression options for %s (%s) (%d:%d:%d)\n",
+                        file->filename, file->name, view->chip, view->cell, view->readout);
+                return false;
+            }
+        }
+
+        // In some cases, we need to read the PHU after we've opened the file.  This happens for the images
+        // supplied by the detrend database, which are only identified here (pmConfigConvertFilename).
+        if (!pmFPAfileReadPHU (file, view, config)) {
+            psError (PS_ERR_IO, true, "error reading PHU for %s (%s) (%d:%d:%d)\n",
+                     file->filename, file->name, view->chip, view->cell, view->readout);
+            return false;
+        }
+        break;
+
+        // defer opening TEXT types:
+      case PM_FPA_FILE_SX:
+      case PM_FPA_FILE_OBJ:
+      case PM_FPA_FILE_CMP:
+      case PM_FPA_FILE_RAW:
+      case PM_FPA_FILE_JPEG:
+      case PM_FPA_FILE_KAPA:
+        psTrace ("psModules.camera", 5, "defer opening %s\n", file->filename);
+        break;
+
+      default:
+        psError(PS_ERR_IO, true, "type mismatch for %s : %d\n", file->filename, file->type);
+        return false;
+    }
+    return true;
+}
+
+// for this file and view, if we need to read a PHU, read it.  return true for any non-error
+// condition. this function should be called by pmFPAfileOpen.  this function is only called
+// for files for which the PHU is not already loaded (files passed via the db or files after
+// the first in a multifile dataset)
+bool pmFPAfileReadPHU (pmFPAfile *file, const pmFPAview *view, pmConfig *config)
+{
+    // required conditions
+    if (file->mode != PM_FPA_MODE_READ) return true;
+    if (file->state != PM_FPA_STATE_OPEN) psAbort ("pmFPAfileReadPHU called on unopened file");
+    if (file->fpa == NULL) psAbort ("pmFPAfileReadPHU called on file without an FPA");
+
+    // check if we need to read a PHU (if not, return true)
+    switch (file->fileLevel) {
+      case PM_FPA_LEVEL_FPA:
+        if (file->fpa->hdu) return true;
+        break;
+      case PM_FPA_LEVEL_CHIP: {
+          pmChip *chip = pmFPAviewThisChip(view, file->fpa);
+          if (!chip) psAbort ("inconsistent file/fpa: fileLevel is CHIP, view is FPA");
+          if (chip->hdu) return true;
+          break;
+      }
+      case PM_FPA_LEVEL_CELL: {
+          pmCell *cell = pmFPAviewThisCell(view, file->fpa);
+          if (!cell) psAbort ("inconsistent file/fpa: fileLevel is CELL, view is FPA");
+          if (cell->hdu) return true;
+          break;
+      }
+      case PM_FPA_LEVEL_NONE:
+        // Might get here immediately after opening a file selected from the detrend database.
+        break;
+      default:
+        psAbort("fileLevel not correctly set");
+        break;
+    }
+
+    // XXX do we need to advance to the first HDU?
+    psMetadata *phu = psFitsReadHeader (NULL, file->fits);
+    if (!file->format) {
+        // determine the format (camera is already known); do not load the recipe
+        file->format = pmConfigCameraFormatFromHeader (NULL, &file->formatName, config, phu, false);
+        if (!file->format) {
+            psError(PS_ERR_IO, false, "Failed to read CCD format from %s\n", file->filename);
+            psFree(phu);
+            return false;
+        }
+    } else {
+        bool valid;
+        if (!pmConfigValidateCameraFormat (&valid, file->format, phu)) {
+            psError (PS_ERR_UNKNOWN, false, "Error in camera configuration\n");
+            psFree (phu);
+            return false;
+        }
+        if (!valid) {
+            psError(PS_ERR_IO, false, "file %s is not from the required camera", file->filename);
+            psFree (phu);
+            return false;
+        }
+    }
+    pmFPAview *thisView = pmFPAAddSourceFromHeader (file->fpa, phu, file->format);
+    assert (thisView); // XXX we are having some trouble with input psf files not having the Cell and fpa names matching.
+    psFree (thisView);
+    psFree (phu);
+    // XXX we can check the output view to be sure it corresponds to our current view
+    return true;
+}
+
+// XXX this function is only called from pmFPAfileWrite
+// XXX for each data type, there should be a function which writes the PHU, if needed
+bool pmFPAfileWritePHU(pmFPAfile *file, const pmFPAview *view, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    if (file->wrote_phu) return true;
+
+    bool status = true;
+    switch (file->type) {
+      case PM_FPA_FILE_IMAGE:
+      case PM_FPA_FILE_MASK:
+      case PM_FPA_FILE_WEIGHT:
+      case PM_FPA_FILE_DARK:
+      case PM_FPA_FILE_FRINGE:
+        status = pmFPAviewFitsWritePHU (view, file, config);
+        break;
+      case PM_FPA_FILE_CMF:
+        status = pmSource_CMF_WritePHU (view, file, config);
+        break;
+      case PM_FPA_FILE_PSF:
+        status = pmPSFmodelWritePHU (view, file, config);
+        break;
+      case PM_FPA_FILE_ASTROM_REFSTARS:
+        status = pmAstromRefstarsWritePHU (view, file, config);
+        break;
+      case PM_FPA_FILE_ASTROM_MODEL:
+      case PM_FPA_FILE_SX:
+      case PM_FPA_FILE_RAW:
+      case PM_FPA_FILE_OBJ:
+      case PM_FPA_FILE_CMP:
+      case PM_FPA_FILE_JPEG:
+      case PM_FPA_FILE_KAPA:
+        break;
+      default:
+        fprintf (stderr, "warning: type mismatch\n");
+        return false;
+    }
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to write PHU for %s (%s)\n", file->filename, file->name);
+        return false;
+    }
+    // XXX this is also being set in the individual functions.  choose one or the other
+    file->wrote_phu = true;
+    return true;
+}
+
+
+// set the state of the specified pmFPAfile(s) to active (state == true) or inactive
+// if name is NULL, set the state for all pmFPAfiles
+bool pmFPAfileActivate(psMetadata *files, bool state, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(files, false);
+
+    // return false if the requested file is not in the list (not an error, but informational)
+    psArray *selected = pmFPAfileSelect(files, name);
+    if (!selected) {
+        return false;
+    }
+    for (int i = 0; i < selected->n; i++) {
+        pmFPAfile *file = selected->data[i]; // File of interest
+        if (!file) {
+            continue;
+        }
+        if (state) {
+            file->state &= PS_NOT_U8(PM_FPA_STATE_INACTIVE);
+        } else {
+            file->state |= PM_FPA_STATE_INACTIVE;
+        }
+    }
+    psFree(selected);
+
+    return true;
+}
+
+
+pmFPAfile *pmFPAfileActivateSingle(psMetadata *files, bool state, const char *name, int num)
+{
+    PS_ASSERT_PTR_NON_NULL(files, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(name, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(num, NULL);
+
+    pmFPAfile *file = pmFPAfileSelectSingle(files, name, num);
+    if (!file) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to select instance %d of file %s", num, name);
+        return NULL;
+    }
+    if (state) {
+        file->state &= PS_NOT_U8(PM_FPA_STATE_INACTIVE);
+    } else {
+        file->state |= PM_FPA_STATE_INACTIVE;
+    }
+
+    return file;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfileIO.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfileIO.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAfileIO.h	(revision 22158)
@@ -0,0 +1,55 @@
+/* @file  pmFPAview.h
+ * @brief Tools to manipulate the FPA structure elements.
+ *
+ * @author EAM, IfA
+ * @author PAP, IfA
+ *
+ * @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-06-30 00:53:45 $
+ * Copyright 2004-2005 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FPA_FILE_IO_H
+#define PM_FPA_FILE_IO_H
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+// open the real file corresponding to the given pmFPAfile appropriate to the current view
+bool pmFPAfileOpen (pmFPAfile *file, const pmFPAview *view, pmConfig *config);
+
+// read from the real file corresponding to the given pmFPAfile for the current view
+bool pmFPAfileRead (pmFPAfile *file, const pmFPAview *view, pmConfig *config);
+
+bool pmFPAfileCreate (pmFPAfile *file, const pmFPAview *view, const pmConfig *config);
+
+// write to the real file corresponding to the given pmFPAfile for the current view
+bool pmFPAfileWrite (pmFPAfile *file, const pmFPAview *view, pmConfig *config);
+
+// close the real file corresponding to the given pmFPAfile appropriate to the current view
+bool pmFPAfileClose (pmFPAfile *file, const pmFPAview *view);
+
+// free the data at this level
+bool pmFPAfileFreeData(pmFPAfile *file, const pmFPAview *view);
+
+// set the state of the specified pmFPAfile to active (state == true) or inactive
+// if name is NULL, set the state for all pmFPAfiles
+bool pmFPAfileActivate (psMetadata *files, bool state, const char *name);
+
+/// Set the state of a single pmFPAfile (in the case of multiple files with the same name)
+///
+/// Returns file activated
+pmFPAfile *pmFPAfileActivateSingle(psMetadata *files, ///< Files to activate
+                                   bool state, ///< State to set
+                                   const char *name, ///< Name of file to activate
+                                   int num    ///< Sequence numbner of file to activate
+    );
+
+// examine all pmFPAfiles listed in the files and perform the needed I/O operations (open,read,write,close)
+bool pmFPAfileIOChecks (pmConfig *config, const pmFPAview *view, pmFPAfilePlace place);
+
+bool pmFPAfileWritePHU(pmFPAfile *file, const pmFPAview *view, pmConfig *config);
+bool pmFPAfileReadPHU (pmFPAfile *file, const pmFPAview *view, pmConfig *config);
+
+/// @}
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAview.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAview.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAview.c	(revision 22158)
@@ -0,0 +1,375 @@
+/** @file  pmFPAview.c
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-01-02 20:33:14 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmHDUUtils.h"
+#include "pmFPAview.h"
+
+static void pmFPAviewFree(pmFPAview *view)
+{
+    // No reason to keep this function, apart from the fact that it allows us to type the memBlock
+    return;
+}
+
+pmFPAview *pmFPAviewAlloc(int nRows)
+{
+    pmFPAview *view = psAlloc(sizeof(pmFPAview));
+    psMemSetDeallocator(view, (psFreeFunc) pmFPAviewFree);
+
+    view->nRows = nRows;
+    pmFPAviewReset(view);
+    return view;
+}
+
+bool psMemCheckFPAview(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmFPAviewFree);
+}
+
+
+bool pmFPAviewReset(pmFPAview *view)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    view->chip    = -1;
+    view->cell    = -1;
+    view->readout = -1;
+    view->iRows   =  0;
+    return true;
+}
+
+// return a view restricted to the level (must be >= the input level)
+pmFPAview *pmFPAviewForLevel(pmFPALevel level, const pmFPAview *input)
+{
+    PS_ASSERT_PTR_NON_NULL(input, NULL);
+
+    pmFPAview *output = pmFPAviewAlloc (input->nRows);
+    *output = *input;
+
+    switch (level) {
+      case PM_FPA_LEVEL_FPA:
+        output->chip = -1;
+      case PM_FPA_LEVEL_CHIP:
+        output->cell = -1;
+      case PM_FPA_LEVEL_CELL:
+        output->readout = -1;
+        break;
+      default:
+        break;
+    }
+    return output;
+}
+
+pmFPALevel pmFPAviewLevel(const pmFPAview *view)
+{
+    PS_ASSERT_PTR_NON_NULL(view, PM_FPA_LEVEL_NONE);
+
+    if (view->chip < 0) {
+        return PM_FPA_LEVEL_FPA;
+    }
+    if (view->cell < 0) {
+        return PM_FPA_LEVEL_CHIP;
+    }
+    if (view->readout < 0) {
+        return PM_FPA_LEVEL_CELL;
+    }
+    return PM_FPA_LEVEL_READOUT;
+}
+
+pmChip *pmFPAviewThisChip(const pmFPAview *view, const pmFPA *fpa)
+{
+    PS_ASSERT_PTR_NON_NULL(view, NULL);
+    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
+    PS_ASSERT_PTR_NON_NULL(fpa->chips, NULL);
+
+    if (view->chip < 0) {
+        return NULL;
+    }
+
+    if (view->chip >= fpa->chips->n) {
+        return NULL;
+    }
+
+    pmChip *chip = fpa->chips->data[view->chip];
+    return chip;
+}
+
+pmChip *pmFPAviewNextChip(pmFPAview *view, const pmFPA *fpa, int nStep)
+{
+    PS_ASSERT_PTR_NON_NULL(view, NULL);
+    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
+
+    view->cell = -1;
+    view->readout = -1;
+    view->iRows = 0;
+
+    // if there are no available chips, return NULL
+    if (fpa->chips->n <= 0) {
+        view->chip = -1;
+        return NULL;
+    }
+
+    // clean up < -1 values
+    if (view->chip < -1) {
+        view->chip = -1;
+    }
+
+    // increment to the next chip
+    view->chip += nStep;
+
+    // if we are at the end of the stack, return NULL
+    if (view->chip >= fpa->chips->n) {
+        view->chip = -1;
+        return NULL;
+    }
+
+    // get the correct chip pointer
+    pmChip *chip = fpa->chips->data[view->chip];
+    return (chip);
+}
+
+pmCell *pmFPAviewThisCell(const pmFPAview *view, const pmFPA *fpa)
+{
+    PS_ASSERT_PTR_NON_NULL(view, NULL);
+    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
+    if (view->cell < 0) {
+        return NULL;
+    }
+    PS_ASSERT_PTR_NON_NULL(fpa->chips, NULL);
+
+    pmChip *chip = pmFPAviewThisChip (view, fpa);
+    PS_ASSERT_PTR_NON_NULL(chip, NULL);
+
+    if (view->cell >= chip->cells->n) {
+        return NULL;
+    }
+
+    pmCell *cell = chip->cells->data[view->cell];
+    return cell;
+}
+
+pmCell *pmFPAviewNextCell (pmFPAview *view, const pmFPA *fpa, int nStep)
+{
+    PS_ASSERT_PTR_NON_NULL(view, NULL);
+    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
+
+    pmChip *chip = pmFPAviewThisChip (view, fpa);
+    PS_ASSERT_PTR_NON_NULL(chip, NULL);
+
+    view->readout = -1;
+    view->iRows = 0;
+
+    // if there are no available cells, return NULL
+    if (chip->cells->n <= 0) {
+        view->cell = -1;
+        return NULL;
+    }
+
+    // clean up < -1 values
+    if (view->cell < -1) {
+        view->cell = -1;
+    }
+
+    // increment to the next cell
+    view->cell += nStep;
+
+    // if we are at the end of the stack, return NULL
+    if (view->cell >= chip->cells->n) {
+        view->cell = -1;
+        return NULL;
+    }
+
+    // get the correct cell pointer
+    pmCell *cell = chip->cells->data[view->cell];
+    return (cell);
+}
+
+pmReadout *pmFPAviewThisReadout (const pmFPAview *view, const pmFPA *fpa)
+{
+    PS_ASSERT_PTR_NON_NULL(view, NULL);
+    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
+
+    if (view->readout < 0) {
+        return NULL;
+    }
+
+    pmCell *cell = pmFPAviewThisCell (view, fpa);
+    PS_ASSERT_PTR_NON_NULL(cell, NULL);
+    PS_ASSERT_PTR_NON_NULL(cell->readouts, NULL);
+
+    if (view->readout >= cell->readouts->n) {
+        return NULL;
+    }
+
+    pmReadout *readout = cell->readouts->data[view->readout];
+    return readout;
+}
+
+pmReadout *pmFPAviewNextReadout (pmFPAview *view, const pmFPA *fpa, int nStep)
+{
+    PS_ASSERT_PTR_NON_NULL(view, NULL);
+    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
+
+    pmCell *cell = pmFPAviewThisCell (view, fpa);
+    PS_ASSERT_PTR_NON_NULL(cell, NULL);
+
+    view->iRows = 0;
+
+    // if there are no available cells, return NULL
+    if (cell->readouts->n <= 0) {
+        view->readout = -1;
+        return NULL;
+    }
+
+    // clean up < -1 values
+    if (view->readout < -1) {
+        view->readout = -1;
+    }
+
+    // increment to the next cell
+    view->readout += nStep;
+
+    // if we are at the end of the stack, return NULL
+    if (view->readout >= cell->readouts->n) {
+        view->readout = -1;
+        return NULL;
+    }
+
+    // get the correct cell pointer
+    pmReadout *readout = cell->readouts->data[view->readout];
+    return (readout);
+}
+
+pmHDU *pmFPAviewThisHDU(const pmFPAview *view, const pmFPA *fpa)
+{
+    PS_ASSERT_PTR_NON_NULL(view, NULL);
+    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
+
+    // the HDU is attached to a cell, chip or fpa
+    // if this view has a -1 for the level which contains the hdu,
+    // there is no unambiguous HDU
+
+    if (view->chip < 0) {
+        return pmHDUFromFPA (fpa);
+    }
+    if (view->cell < 0) {
+        return pmHDUFromChip (pmFPAviewThisChip (view, fpa));
+    }
+    if (view->readout < 0) {
+        return pmHDUFromCell (pmFPAviewThisCell (view, fpa));
+    }
+    return pmHDUFromReadout (pmFPAviewThisReadout (view, fpa));
+}
+
+pmHDU *pmFPAviewThisPHU(const pmFPAview *view, const pmFPA *fpa)
+{
+    PS_ASSERT_PTR_NON_NULL(view, NULL);
+    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
+
+    // select the HDU which corresponds to the PHU containing this view
+
+    pmHDU *hdu;
+    pmFPAview new;
+    pmChip *chip;
+    pmCell *cell;
+
+    new = *view;
+
+    if (view->chip < 0) {
+        hdu = pmHDUFromFPA (fpa);
+        if (!hdu)
+            return NULL;
+        if (hdu->blankPHU)
+            return hdu;
+        return NULL;
+    }
+    if (view->cell < 0) {
+        chip = pmFPAviewThisChip (view, fpa);
+        hdu  = pmHDUFromChip (chip);
+        if (!hdu)
+            return NULL;
+        if (hdu->blankPHU)
+            return hdu;
+        new.chip = -1;
+        hdu = pmFPAviewThisPHU (&new, fpa);
+        return hdu;
+    }
+    if (view->readout < 0) {
+        cell = pmFPAviewThisCell (view, fpa);
+        hdu  = pmHDUFromCell (cell);
+        if (!hdu) {
+            psAbort("a split readout is not covered by the current paradigm");
+        }
+        if (hdu->blankPHU)
+            return hdu;
+        new.cell = -1;
+        hdu = pmFPAviewThisPHU (&new, fpa);
+        return hdu;
+    }
+    return NULL;
+}
+
+pmFPAview *pmFPAviewGenerate(const pmFPA *fpa, const pmChip *chip, const pmCell *cell,
+                             const pmReadout *readout)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
+
+    pmFPAview *view = pmFPAviewAlloc(0);// View to return
+
+    if (!chip) {
+        return view;
+    }
+
+    for (view->chip = 0; view->chip < fpa->chips->n && fpa->chips->data[view->chip] != chip; view->chip++);
+    if (view->chip == fpa->chips->n) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find chip %p in fpa.", chip);
+        psFree(view);
+        return NULL;
+    }
+
+    if (!cell) {
+        return view;
+    }
+
+    for (view->cell = 0; view->cell < chip->cells->n && chip->cells->data[view->cell] != cell; view->cell++);
+    if (view->cell == chip->cells->n) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find cell %p in chip.", cell);
+        psFree(view);
+        return NULL;
+    }
+
+    if (!readout) {
+        return view;
+    }
+
+    for (view->readout = 0;
+         view->readout < cell->readouts->n && cell->readouts->data[view->readout] != readout;
+         view->readout++);
+    if (view->readout == cell->readouts->n) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find readout %p in cell.", readout);
+        psFree(view);
+        return NULL;
+    }
+
+    return view;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAview.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAview.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmFPAview.h	(revision 22158)
@@ -0,0 +1,127 @@
+/* @file pmFPA.h
+ * @brief Tools to manipulate the FPA structure elements.
+ *
+ * @author Eugene Magnier, IfA
+ *
+ * @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-01-02 20:33:14 $
+ * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FPA_VIEW_H
+#define PM_FPA_VIEW_H
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+// #include "pmFPA.h"
+// #include "pmFPALevel.h"
+
+/// Identifier for FPA components
+///
+/// This structure allows the identification of a single component of the focal plane hierarchy (or multiple,
+/// if we consider selecting all those components below the selected component).  Components are identified on
+/// the basis of their chip, cell, readout index.  An index of -1 means all components at that level.
+/// Additionally, since readouts may be read piecemeal, there are additional indices for these.
+typedef struct
+{
+    int chip;                           ///< Number of the chip, or -1 for all
+    int cell;                           ///< Number of the cell, or -1 for all
+    int readout;                        ///< Number of the readout, or -1 for all
+    int nRows;                          ///< Maximum number of rows per readout segment read, or 0 for all
+    int iRows;                          ///< Starting point for this read
+}
+pmFPAview;
+
+/// Allocator for pmFPAview
+pmFPAview *pmFPAviewAlloc(int nRows);   ///< Maximum number of rows per readout segment read, or 0 for all
+bool psMemCheckFPAview(psPtr ptr);
+
+/// Reset a view to select all components
+bool pmFPAviewReset(pmFPAview *view     ///< View to reset
+                   );
+
+// return a view restricted to the level (must be >= the input level)
+pmFPAview *pmFPAviewForLevel(pmFPALevel level, const pmFPAview *input);
+
+/// Determine the current view level
+///
+/// Returns the level appropriate for the view
+pmFPALevel pmFPAviewLevel(const pmFPAview *view ///< View to examine
+                         );
+
+// Lookups
+
+/// Return the currently selected chip for this view
+///
+/// Returns NULL if the selection is not specific or invalid
+pmChip *pmFPAviewThisChip(const pmFPAview *view, ///< Current view
+                          const pmFPA *fpa ///< FPA containing chip
+                         );
+
+/// Return the currently selected cell for this view
+///
+/// Returns NULL if the selection is not specific or invalid
+pmCell *pmFPAviewThisCell(const pmFPAview *view, ///< Current view
+                          const pmFPA *fpa ///< FPA containing cell
+                         );
+
+/// Return the currently selected readout for this view
+///
+/// Returns NULL if the selection is not specific or invalid
+pmReadout *pmFPAviewThisReadout(const pmFPAview *view, ///< Current view
+                                const pmFPA *fpa ///< FPA containing readout
+                               );
+
+// Incrementors
+
+/// Advance view to the next chip
+///
+/// Returns NULL if there is no next
+pmChip *pmFPAviewNextChip(pmFPAview *view, ///< Current view
+                          const pmFPA *fpa, ///< FPA containing chips
+                          int nStep     ///< Number of chips to increment
+                         );
+
+/// Advance view to the next cell
+///
+/// Returns NULL if there is no next
+pmCell *pmFPAviewNextCell(pmFPAview *view, ///< Current view
+                          const pmFPA *fpa, ///< FPA containing cells
+                          int nStep     ///< Number of cells to increment
+                         );
+
+/// Advance view to the next readout
+///
+/// Returns NULL if there is no next
+pmReadout *pmFPAviewNextReadout(pmFPAview *view, ///< Current view
+                                const pmFPA *fpa, ///< FPA containing readouts
+                                int nStep ///< Number of readouts to increment
+                               );
+
+/// Return the HDU corresponding to the current view
+///
+/// Uses the pmHDUFrom* functions, combined with the view.
+pmHDU *pmFPAviewThisHDU(const pmFPAview *view, ///< Current view
+                        const pmFPA *fpa ///< FPA for view
+                       );
+
+/// Return the blank Primary HDU corresponding to the current view, if any
+///
+/// Similar to pmFPAviewThisHDU, except returns NULL if no HDU is found, or the HDU is not a blank Primary HDU
+pmHDU *pmFPAviewThisPHU(const pmFPAview *view, ///< Current view
+                        const pmFPA *fpa ///< FPA for view
+                       );
+
+/// Generate a view, given a chip, cell, readout.
+///
+/// Uses the pointer value in the array of the parent to locate the child
+pmFPAview *pmFPAviewGenerate(const pmFPA *fpa, ///< FPA of interest
+                             const pmChip *chip, ///< Chip of interest, or NULL
+                             const pmCell *cell, ///< Cell of interest, or NULL
+                             const pmReadout *reaodut ///< Readout of interest, or NULL
+    );
+
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmHDU.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmHDU.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmHDU.c	(revision 22158)
@@ -0,0 +1,238 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmHDU.h"
+#include "pmFPA.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// File-static (private) functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Move to the appropriate extension in FITS file for HDU
+static bool hduMove(pmHDU *hdu,         // HDU with extname
+                    psFits *fits        // FITS file in which to move
+                   )
+{
+    // Deal with the PHU case
+    if (hdu->blankPHU || !hdu->extname) {
+        if (!psFitsMoveExtNum(fits, 0, false)) {
+            psError(PS_ERR_IO, false, "Unable to move to primary header!\n");
+            return false;
+        }
+        return true;
+    }
+
+    if (!psFitsMoveExtName(fits, hdu->extname)) {
+        psError(PS_ERR_IO, false, "Unable to move to extension %s\n", hdu->extname);
+        return false;
+    }
+
+    return true;
+}
+
+static void hduFree(pmHDU *hdu)
+{
+    psFree(hdu->extname);
+    psFree(hdu->format);
+    psFree(hdu->header);
+    psFree(hdu->images);
+    psFree(hdu->weights);
+    psFree(hdu->masks);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+pmHDU *pmHDUAlloc(const char *extname)
+{
+    pmHDU *hdu = psAlloc(sizeof(pmHDU));
+    psMemSetDeallocator(hdu, (psFreeFunc)hduFree);
+
+    if (!extname || strlen(extname) == 0) {
+        hdu->blankPHU = true;
+        hdu->extname = NULL;
+    } else {
+        hdu->blankPHU = false;
+        hdu->extname = psStringCopy(extname);
+    }
+    hdu->format  = NULL;
+    hdu->header  = NULL;
+    hdu->images  = NULL;
+    hdu->weights = NULL;
+    hdu->masks   = NULL;
+
+    return hdu;
+}
+
+bool psMemCheckHDU(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) hduFree);
+}
+
+
+bool pmHDUReadHeader(pmHDU *hdu, psFits *fits)
+{
+    PS_ASSERT_PTR_NON_NULL(hdu, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+
+    // Move to the appropriate extension
+    psTrace("psModules.camera", 5, "Moving to extension %s...\n", hdu->extname);
+    if (!hduMove(hdu, fits)) {
+        return false;
+    }
+
+    if (!hdu->header) {
+        psTrace("psModules.camera", 5, "Reading the header...\n");
+        hdu->header = psFitsReadHeader(hdu->header, fits);
+        if (! hdu->header) {
+            psError(PS_ERR_IO, false, "Unable to read header for extension %s\n", hdu->extname);
+            return false;
+        }
+    }
+
+    return true;
+}
+
+// Read an HDU from a FITS file
+// XXX: Add a region specifier?
+bool hduRead(pmHDU *hdu,                // HDU to write
+             psArray **images,          // Images into which to read
+             psFits *fits               // FITS file to read
+            )
+{
+    assert(hdu);
+    assert(images);
+    assert(fits);
+
+    // Read the header; includes the move
+    if (!pmHDUReadHeader(hdu, fits)) {
+        return false;
+    }
+
+    if (hdu->blankPHU) {
+        // Done already!
+        return true;
+    }
+
+    if (*images) {
+        psWarning("HDU %s has already been read --- overwriting.\n", hdu->extname);
+        psFree(*images);                // Blow away anything existing
+    }
+    psTrace("psModules.camera", 5, "Reading the pixels...\n");
+    *images = psFitsReadImageCube(fits, psRegionSet(0,0,0,0));
+    if (!*images) {
+        psError(PS_ERR_IO, false, "Unable to read pixels for extension %s\n", hdu->extname);
+        return false;
+    }
+    return true;
+}
+
+bool pmHDURead(pmHDU *hdu, psFits *fits)
+{
+    PS_ASSERT_PTR_NON_NULL(hdu, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+
+    return hduRead(hdu, &hdu->images, fits);
+}
+
+bool pmHDUReadMask(pmHDU *hdu, psFits *fits)
+{
+    PS_ASSERT_PTR_NON_NULL(hdu, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+
+    return hduRead(hdu, &hdu->masks, fits);
+}
+
+bool pmHDUReadWeight(pmHDU *hdu, psFits *fits)
+{
+    PS_ASSERT_PTR_NON_NULL(hdu, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+
+    return hduRead(hdu, &hdu->weights, fits);
+}
+
+// Write an HDU to a FITS file
+static bool hduWrite(pmHDU *hdu,        // HDU to write
+                     psArray *images,   // Images to write
+                     psFits *fits       // FITS file to which to write
+                    )
+{
+    assert(hdu);
+    assert(fits);
+
+    psTrace("psModules.camera", 7, "Writing HDU %s\n", hdu->extname);
+
+    if (!images && !hdu->header) {
+        psWarning("Nothing to write for HDU %s\n", hdu->extname);
+        return false;
+    }
+
+    // Preserve the extension name, if it's the PHU
+    char *extname = hdu->extname;       // The name of the extension
+    if (!extname && hdu->header) {
+        bool mdok = true;               // Status of MD lookup
+        extname = psMetadataLookupStr(&mdok, hdu->header, "EXTNAME");
+        if (!mdok || !extname || strlen(extname) == 0) {
+            extname = "";
+        }
+    }
+
+    // Make sure it's recognisable as what it's supposed to be
+    if (!hdu->header) {
+        hdu->header = psMetadataAlloc();
+    }
+    if (!pmConfigConformHeader(hdu->header, hdu->format)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to conform header to format.\n");
+        return false;
+    }
+
+    // Only a header
+    if (!images && !psFitsWriteBlank(fits, hdu->header, extname)) {
+        psError(PS_ERR_IO, false, "Unable to write header for extension %s\n", extname);
+        return false;
+    }
+
+    if (images) {
+        psTrace("psModules.camera", 9, "Writing pixels for %s\n", hdu->extname);
+        if (!psFitsWriteImageCube(fits, hdu->header, images, extname)) {
+            psError(PS_ERR_IO, false, "Unable to write image to extension %s\n", hdu->extname);
+            return false;
+        }
+    }
+    return true;
+}
+
+// XXX: Add a region specifier?
+bool pmHDUWrite(pmHDU *hdu, psFits *fits)
+{
+    PS_ASSERT_PTR_NON_NULL(hdu, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+
+    return hduWrite(hdu, hdu->images, fits);
+}
+
+bool pmHDUWriteMask(pmHDU *hdu, psFits *fits)
+{
+    PS_ASSERT_PTR_NON_NULL(hdu, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+
+    return hduWrite(hdu, hdu->masks, fits);
+}
+
+bool pmHDUWriteWeight(pmHDU *hdu, psFits *fits)
+{
+    PS_ASSERT_PTR_NON_NULL(hdu, false);
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+
+    return hduWrite(hdu, hdu->weights, fits);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmHDU.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmHDU.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmHDU.h	(revision 22158)
@@ -0,0 +1,82 @@
+/* @file pmHDU.h
+ * @brief Define a header data unit (from a FITS file), with functions to read and write
+ *
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-01-02 20:33:41 $
+ * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_HDU_H
+#define PM_HDU_H
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+/// An instance of the FITS Header Data Unit
+///
+/// Of course, it is not an exact replica of a FITS HDU --- they have no mask and weight data, but these are
+/// stored here for convenience --- it keeps all the relevant data about the image in one place.
+typedef struct
+{
+    psString extname;                   ///< The extension name
+    bool blankPHU;                      ///< Is this a blank FITS Primary Header Unit, i.e., no data?
+    psMetadata *format;                 ///< The camera format
+    psMetadata *header;                 ///< The FITS header, or NULL if primary for FITS; or section info
+    psArray *images;                    ///< The pixel data
+    psArray *weights;                   ///< The pixel data
+    psArray *masks;                     ///< The pixel data
+}
+pmHDU;
+
+
+/// Allocator for pmHDU
+pmHDU *pmHDUAlloc(const char *extname);   ///< Extension name, or NULL for PHU
+bool psMemCheckHDU(psPtr ptr);
+
+/// Read the HDU header only
+///
+/// Moves to the appropriate extension
+bool pmHDUReadHeader(pmHDU *hdu,        ///< HDU for which to read header
+                     psFits *fits       ///< FITS file from which to read
+                    );
+
+/// Read the HDU header and pixels
+///
+/// Moves to the appropriate extension
+bool pmHDURead(pmHDU *hdu,              ///< HDU to read
+               psFits *fits             ///< FITS file to read from
+              );
+
+/// Read the HDU header and mask
+///
+/// Moves to the appropriate extension
+bool pmHDUReadMask(pmHDU *hdu,          ///< HDU to read
+                   psFits *fits         ///< FITS file to read from
+                  );
+
+/// Read the HDU header and weight map
+///
+/// Moves to the appropriate extension
+bool pmHDUReadWeight(pmHDU *hdu,        ///< HDU to read
+                     psFits *fits       ///< FITS file to read from
+                    );
+
+/// Write the HDU header and pixels
+bool pmHDUWrite(pmHDU *hdu,             ///< HDU to write
+                psFits *fits            ///< FITS file to write to
+               );
+
+/// Write the HDU header and mask
+bool pmHDUWriteMask(pmHDU *hdu,         ///< HDU to write
+                    psFits *fits        ///< FITS file to write to
+                   );
+
+/// Write the HDU header and weight map
+bool pmHDUWriteWeight(pmHDU *hdu,       ///< HDU to write
+                      psFits *fits      ///< FITS file to write to
+                     );
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmHDUGenerate.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmHDUGenerate.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmHDUGenerate.c	(revision 22158)
@@ -0,0 +1,711 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <strings.h>            /* for strn?casecmp */
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmHDUUtils.h"
+#include "pmConcepts.h"
+#include "pmConceptsStandard.h"
+#include "pmHDUGenerate.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// File-static functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Add cells in a chip to a list
+static bool addCellsFromChip(psList *list, // List of cells
+                             const pmChip *chip // The chip from which to add cells
+                            )
+{
+    assert(list);
+    assert(chip);
+
+    psArray *cells = chip->cells;       // Array of cells
+    bool result = true;                 // Result of adding cells
+    for (int i = 0; i < cells->n; i++) {
+        pmCell *cell = cells->data[i];  // A cell
+        if (!cell->hdu) {               // Don't add cells that have their own HDU
+            result |= psListAdd(list, PS_LIST_TAIL, cell);
+        }
+    }
+
+    return result;
+}
+
+// Add cells in an FPA to a list
+static bool addCellsFromFPA(psList *list, // List of cells
+                            const pmFPA *fpa // The FPA from which to add cells
+                           )
+{
+    assert(list);
+    assert(fpa);
+
+    psArray *chips = fpa->chips;        // Array of chips
+    bool result = true;                 // Result of adding cells
+    for (int i = 0; i < chips->n; i++) {
+        pmChip *chip = chips->data[i];  // A chip
+        if (! chip->hdu) {              // Don't add chips that have their own HDU
+            result |= addCellsFromChip(list, chip);
+        }
+    }
+
+    return result;
+}
+
+// Get the maximum extent of the HDU from the trimsec and biassecs
+static bool sizeHDU(int *xSize, int *ySize, // Size of HDU
+                    psList *cells       // List of cells
+                   )
+{
+    psListIterator *cellsIter = psListIteratorAlloc(cells, PS_LIST_HEAD, false); // Iterator for cells
+    pmCell *cell = NULL;                // The cell from iteration
+    bool mdok = true;                   // Status of MD lookup
+    *xSize = 0;
+    *ySize = 0;
+    while ((cell = psListGetAndIncrement(cellsIter))) {
+        psRegion *trimsec = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.TRIMSEC"); // Trim section
+        if (mdok && trimsec && !psRegionIsNaN(*trimsec)) {
+            *xSize = PS_MAX(trimsec->x1, *xSize);
+            *ySize = PS_MAX(trimsec->y1, *ySize);
+        } else {
+            psFree(cellsIter);
+            return false;
+        }
+        psList *biassecs = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.BIASSEC"); // Bias sections
+        if (mdok && biassecs) {
+            psListIterator *biassecsIter = psListIteratorAlloc(biassecs, PS_LIST_HEAD, false); // Iterator
+            psRegion *biassec = NULL;   // The bias section
+            while ((biassec = psListGetAndIncrement(biassecsIter))) {
+                if (!psRegionIsNaN(*biassec)) {
+                    *xSize = PS_MAX(biassec->x1, *xSize);
+                    *ySize = PS_MAX(biassec->y1, *ySize);
+                } else {
+                    psFree(biassecsIter);
+                    psFree(cellsIter);
+                    return false;
+                }
+            }
+            psFree(biassecsIter);
+        }
+    }
+    psFree(cellsIter);
+
+    return (*xSize != 0 && *ySize != 0);
+}
+
+
+static psRegion *sectionForImage(int *position, // Position on the output image, updated
+                                 const psImage *image, // Image containing the sizes and offsets
+                                 int readdir // Read direction, 1=rows, 2=cols
+                                )
+{
+    psRegion *region = NULL;            // The region to return
+    switch (readdir) {
+    case 1:                           // Read direction is rows
+        region = psRegionAlloc(*position, *position + image->numCols, image->row0,
+                               image->row0 + image->numRows);
+        *position += image->numCols;
+        break;
+    case 2:                           // Read direction is columns
+        region = psRegionAlloc(image->col0, image->col0 + image->numCols, *position,
+                               *position + image->numRows);
+        *position += image->numRows;
+        break;
+    default:
+        psAbort("Shouldn't ever get here!\n");
+    }
+
+    return region;
+}
+
+static bool doBiasSections(int *position, // Position on the output image, updated
+                           int *readdir,// Read direction for cells
+                           pmCell *cell // Cell
+                          )
+{
+    psMetadataItem *biassecItem = psMetadataLookup(cell->concepts, "CELL.BIASSEC"); // Bias sections
+    if (!biassecItem) {
+        psWarning("CELL.BIASSEC has not been initialised in cell --- ignored.\n");
+        return false;
+    }
+    psFree(biassecItem->data.V);        // Blow away the old list
+    psList *biassecs = psListAlloc(NULL);
+    biassecItem->data.V = biassecs;
+
+    bool mdok = true;                   // Status of MD lookup
+    int cellreaddir = psMetadataLookupS32(&mdok, cell->concepts, "CELL.READDIR"); // Read direction
+    if (!mdok || (cellreaddir != 1 && cellreaddir != 2)) {
+        // Probably unnecessary, but just in case....
+        psWarning("CELL.READDIR is not set in cell --- ignored.\n");
+        return false;
+    }
+    if (*readdir == 0) {
+        *readdir = cellreaddir;
+    } else if (*readdir != cellreaddir) {
+        psWarning("CELL.READDIR does not match read direction for HDU --- ignored.\n");
+        return false;
+    }
+
+    pmReadout *readout = cell->readouts->data[0]; // The first readout, as representative
+    psList *biases = readout->bias; // The bias images from the readout
+
+    psListIterator *biasIter = psListIteratorAlloc(biases, PS_LIST_HEAD, true); // Iterator for biases
+    psImage *bias = NULL;       // Bias image from iteration
+    while ((bias = psListGetAndIncrement(biasIter))) {
+        // Construct a region
+        psRegion *biassec = sectionForImage(position, bias, *readdir);
+        psListAdd(biassecs, PS_LIST_TAIL, biassec);
+        psFree(biassec);        // Drop reference
+    }
+    psFree(biasIter);
+
+    return true;
+}
+
+// Attempt to read CELL.TRIMSEC and CELL.BIASSEC from the cell format if they are specified by VALUE
+static bool readTrimBias(psList *cells // List of cells below the HDU
+    )
+{
+    bool mdok;                          // Status of MD lookup
+    psListIterator *cellsIter = psListIteratorAlloc(cells, PS_LIST_HEAD, false); // Iterator for cells
+    pmCell *cell = NULL;                // Cell from iteration
+    bool allFixed = true;               // We're able to fix all TRIMSEC and BIASSEC
+    while ((cell = psListGetAndIncrement(cellsIter))) {
+        psMetadataItem *trimsecItem = psMetadataLookup(cell->concepts, "CELL.TRIMSEC"); // Item with trimsec
+        if (!trimsecItem || trimsecItem->type != PS_DATA_REGION) {
+            psWarning("CELL.TRIMSEC has not been initialised in cell --- ignored.\n");
+            return false;
+        }
+        psRegion *trimsec = trimsecItem->data.V; // Trim section
+        if (!trimsec || psRegionIsNaN(*trimsec)) {
+            const char *trimsecSource = psMetadataLookupStr(&mdok, cell->config, "CELL.TRIMSEC.SOURCE");
+            if (strcmp(trimsecSource, "VALUE") == 0) {
+
+                const char *trimsecStr = psMetadataLookupStr(&mdok, cell->config, "CELL.TRIMSEC");
+                if (!trimsec) {
+                    trimsec = trimsecItem->data.V = psRegionAlloc(NAN, NAN, NAN, NAN);
+                }
+                *trimsec = psRegionFromString(trimsecStr);
+            } else {
+                allFixed = false;
+            }
+        }
+
+        psMetadataItem *biassecItem = psMetadataLookup(cell->concepts, "CELL.BIASSEC"); // Bias sections
+        if (!biassecItem) {
+            psWarning("CELL.BIASSEC has not been initialised in cell --- ignored.\n");
+            return false;
+        }
+        psList *biassecs = biassecItem->data.V;
+        if (!biassecs || biassecs->n != 0) {
+            allFixed = false;
+            continue;
+        }
+
+        const char *biassecSource = psMetadataLookupStr(&mdok, cell->config, "CELL.BIASSEC.SOURCE");
+        if (biassecSource && strcmp(biassecSource, "VALUE") == 0) {
+            const char *biassecStr = psMetadataLookupStr(&mdok, cell->config, "CELL.BIASSEC");
+            psFree(biassecItem->data.V);
+            biassecItem->data.V = p_pmConceptParseRegions(biassecStr);
+        } else {
+            allFixed = false;
+        }
+    }
+    psFree(cellsIter);
+
+    return allFixed;
+}
+
+
+// Generate CELL.TRIMSEC and CELL.BIASSEC for the cells
+static bool generateTrimBias(psList *cells // List of cells below the HDU
+                            )
+{
+    pmCell *cell = NULL;                // Cell from iteration
+    int numCells = cells->n;            // Number of cells
+    int cellNum = 0;                    // The cell number
+    int position = 0;                   // Position on the image
+    bool mdok = true;                   // Status of MD lookup
+    int readdir = 0;                    // Read direction (1=rows, 2=cols)
+
+    // First run through to do the LHS biases
+    psListIterator *cellsIter = psListIteratorAlloc(cells, PS_LIST_HEAD, false); // Iterator for cells
+    bool done = false;                  // Done with iteration (due to being halfway through)?
+    while ((cell = psListGetAndIncrement(cellsIter)) && !done) {
+        if (cellNum <= numCells/2 - 1) {
+            doBiasSections(&position, &readdir, cell);
+            cellNum++;
+        } else {
+            done = true;
+        }
+    }
+
+    // Second run through to do the trim sections
+    psListIteratorSet(cellsIter, PS_LIST_HEAD);
+    while ((cell = psListGetAndIncrement(cellsIter))) {
+        psMetadataItem *trimsecItem = psMetadataLookup(cell->concepts, "CELL.TRIMSEC"); // Item with trimsec
+        if (!trimsecItem || trimsecItem->type != PS_DATA_REGION) {
+            psWarning("CELL.TRIMSEC has not been initialised in cell --- ignored.\n");
+            continue;
+        }
+        psRegion *trimsec = trimsecItem->data.V; // Trim section
+
+        int cellreaddir = psMetadataLookupS32(&mdok, cell->concepts, "CELL.READDIR"); // Read direction
+        if (!mdok || (cellreaddir != 1 && cellreaddir != 2)) {
+            // Probably unnecessary, but just in case....
+            psWarning("CELL.READDIR is not set in cell --- ignored.\n");
+            continue;
+        }
+        if (readdir == 0 && mdok && cellreaddir != 0) {
+            readdir = cellreaddir;
+        } else if (readdir != cellreaddir) {
+            psWarning("CELL.READDIR for cells within the HDU do not match!\n");
+            cellreaddir = readdir;
+        }
+
+        pmReadout *readout = cell->readouts->data[0]; // The first readout, as representative
+        // The proper image, used to get the size
+        psImage *image = readout->image ? readout->image : (readout->mask ? readout->mask : readout->weight);
+        if (!image) {
+            continue;
+        }
+        if (readout->mask &&
+                (readout->mask->numCols != image->numCols || readout->mask->numRows != image->numRows)) {
+            psWarning("Image and mask have different sizes (%dx%d vs %dx%d)!\n",
+                     image->numCols, image->numRows, readout->mask->numCols, readout->mask->numRows);
+        }
+        if (readout->weight &&
+                (readout->weight->numCols != image->numCols || readout->weight->numRows != image->numRows)) {
+            psWarning("Image and weight have different sizes (%dx%d vs %dx%d)!\n",
+                     image->numCols, image->numRows, readout->weight->numCols, readout->weight->numRows);
+        }
+        // New reference
+        trimsec = sectionForImage(&position, image, cellreaddir);
+        psFree(trimsecItem->data.V);
+        trimsecItem->data.V = trimsec;
+    }
+
+    // A final run through to do the RHS biases
+    psListIteratorSet(cellsIter, cellNum);
+    while ((cell = psListGetAndIncrement(cellsIter))) {
+        doBiasSections(&position, &readdir, cell);
+    }
+
+    // Clean up
+    psFree(cellsIter);
+
+    return (position > 0);
+}
+
+// Check the type for a current image against a previous type
+static psElemType checkTypes(psElemType previous, // Previously defined type, or 0
+                             psElemType current // Current type
+                            )
+{
+    if (previous == 0) {
+        return current;
+    }
+
+    if (previous != current) {
+        psWarning("Images within the HDU are of different types (%x vs %x) --- promoting\n",
+                  previous, current);
+        return PS_MAX(previous, current);
+    }
+
+    return previous;
+}
+
+
+// Paste the source image into the target, according to the provided region.  The source is then updated to
+// reference the region within the target.
+static psImage *pasteImage(psImage *target, // Target image, into which the paste is made
+                           psImage *source,// Source image, from which the paste is made, and then changed
+                           psRegion *region // Image section into which to paste
+                          )
+{
+    if (source->numCols != region->x1 - region->x0 || source->numRows != region->y1 - region->y0) {
+        psString regionString = psRegionToString(*region);
+        psWarning("Image size (%dx%d) does not match region (%s).\n",
+                 source->numCols, source->numRows, regionString);
+        psFree(regionString);
+    }
+    psImageOverlaySection(target, source, region->x0, region->y0, "=");
+
+    // Reference the HDU version, so that subsequent changes will touch the HDU
+    return psImageSubset(target, *region);
+}
+
+
+// Generate the HDU, given a list of cells below that HDU.  This is the main engine function, that does all
+// the work.
+static bool generateHDU(pmHDU *hdu,     // HDU to generate
+                        psList *cells   // List of cells
+                       )
+{
+    // Check the number of readouts is consistent within the HDU
+    int numReadouts = -1;               // Number of readouts
+    psElemType imageType = 0;           // Type of readout images
+    psElemType maskType = 0;            // Type of readout masks
+    psElemType weightType = 0;          // Type of readout weights
+    {
+        psListIterator *iter = psListIteratorAlloc(cells, PS_LIST_HEAD, false); // Iterator for cells
+        pmCell *cell = NULL;                // The cell from iteration
+        while ((cell = psListGetAndIncrement(iter)))
+        {
+            psArray *readouts = cell->readouts;
+            if (numReadouts == -1) {
+                numReadouts = readouts->n;
+            } else if (readouts->n != numReadouts) {
+                psError(PS_ERR_IO, true, "Number of readouts doesn't match: %ld vs %d\n", readouts->n,
+                        numReadouts);
+                return false;
+            }
+            for (int i = 0; i < numReadouts; i++) {
+                pmReadout *readout = readouts->data[i]; // The readout
+                if (!readout) {
+                    continue;
+                }
+
+                if (!hdu->images && readout->image) {
+                    imageType = checkTypes(imageType, readout->image->type.type);
+                }
+                if (!hdu->masks && readout->mask) {
+                    maskType = checkTypes(maskType, readout->mask->type.type);
+                }
+                if (!hdu->weights && readout->weight) {
+                    weightType = checkTypes(weightType, readout->weight->type.type);
+                }
+            }
+        }
+        psFree(iter);
+    }
+    if (numReadouts == 0 || (imageType == 0 && maskType == 0 && weightType == 0)) {
+        // Nothing from which to create an HDU
+        psFree(cells);
+        psError(PS_ERR_IO, true, "Nothing from which to create an HDU\n");
+        return false;
+    }
+
+    // Get the size of the HDU, either from existing trimsec and biassec, or generate these and try again
+    int xSize = 0, ySize = 0;           // Size of HDU
+    if (!sizeHDU(&xSize, &ySize, cells) &&
+        !(readTrimBias(cells) && sizeHDU(&xSize, &ySize, cells)) &&
+        !(generateTrimBias(cells) && sizeHDU(&xSize, &ySize, cells))) {
+        psError(PS_ERR_IO, true, "Unable to determine size of HDU!\n");
+        return false;
+    }
+
+    // Generate the HDU
+    if (imageType) {
+        hdu->images = psArrayAlloc(numReadouts);
+        for (int i = 0; i < numReadouts; i++) {
+            psImage *image = psImageAlloc(xSize, ySize, imageType);
+            psImageInit(image, 0.0);
+            hdu->images->data[i] = image;
+        }
+    }
+    if (maskType) {
+        hdu->masks = psArrayAlloc(numReadouts);
+        for (int i = 0; i < numReadouts; i++) {
+            psImage *mask = psImageAlloc(xSize, ySize, maskType);
+            psImageInit(mask, 0);
+            hdu->masks->data[i] = mask;
+        }
+    }
+    if (weightType) {
+        hdu->weights = psArrayAlloc(numReadouts);
+        for (int i = 0; i < numReadouts; i++) {
+            psImage *weight = psImageAlloc(xSize, ySize, weightType);
+            psImageInit(weight, 0.0);
+            hdu->weights->data[i] = weight;
+        }
+    }
+
+    // Insert the pixels into the HDU
+    {
+        psListIterator *iter = psListIteratorAlloc(cells, PS_LIST_HEAD, false); // Iterator for cells
+        pmCell *cell = NULL;           // The cell from iteration
+        bool mdok = true;               // Result of MD lookup
+        while ((cell = psListGetAndIncrement(iter)))
+        {
+            psRegion *trimsec = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.TRIMSEC"); // Trim section
+            if (!mdok || !trimsec) {
+                psAbort("Shouldn't ever get here --- CELL.TRIMSEC should have been set above.\n");
+            }
+            psList *biassecs = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.BIASSEC"); // Bias secionts
+            if (!mdok || !biassecs) {
+                psAbort("Shouldn't ever get here --- CELL.BIASSEC should have been set above.\n");
+            }
+            psListIterator *biassecsIter = psListIteratorAlloc(biassecs, PS_LIST_HEAD, false); // Iterator
+
+            psArray *readouts = cell->readouts; // Array of readouts
+            psArray *hduImages = hdu->images; // Array of images in the HDU
+            psArray *hduMasks = hdu->masks; // Array of masks in the HDU
+            psArray *hduWeights = hdu->weights; // Array of weights in the HDU
+            for (int i = 0; i < readouts->n; i++) {
+                pmReadout *readout = readouts->data[i]; // The readout of interest
+                if (!readout) {
+                    continue;
+                }
+
+                if (readout->image) {
+                    psImage *new = pasteImage(hduImages->data[i], readout->image, trimsec);
+                    psFree(readout->image);
+                    readout->image = new;
+                }
+                if (readout->mask) {
+                    psImage *new = pasteImage(hduMasks->data[i], readout->mask, trimsec);
+                    psFree(readout->mask);
+                    readout->mask = new;
+                }
+                if (readout->weight) {
+                    psImage *new = pasteImage(hduWeights->data[i], readout->weight, trimsec);
+                    psFree(readout->weight);
+                    readout->weight = new;
+                }
+
+                if (biassecs->n != readout->bias->n) {
+                    psWarning("Number of bias sections (%ld) and number of biases (%ld) do not match.\n",
+                              biassecs->n, readout->bias->n);
+                }
+                psListIterator *biasIter = psListIteratorAlloc(readout->bias, PS_LIST_HEAD, false); // Iteratr
+                psImage *bias = NULL;   // Bias image, from iteration
+                psListIteratorSet(biassecsIter, PS_LIST_HEAD);
+                psRegion *biassec = NULL; // Bias region, from iteration
+                psList *newBias = psListAlloc(NULL); // New list of bias images
+                while ((bias = psListGetAndIncrement(biasIter)) &&
+                        (biassec = psListGetAndIncrement(biassecsIter))) {
+                    psImage *new = pasteImage(hduImages->data[i], bias, biassec);
+                    psListAdd(newBias, PS_LIST_TAIL, new);
+                    psFree(new);        // Drop reference
+                }
+                psFree(biasIter);
+
+                // Add on the new list of bias images
+                psFree(readout->bias);
+                readout->bias = newBias;
+            }
+            psFree(biassecsIter);
+        } // Iterating over cells within the HDU
+        psFree(iter);
+    }
+    psFree(cells);
+
+    return true;
+}
+
+// Return the level that an extension applies to
+static pmFPALevel extensionLevel(pmHDU *hdu // HDU to check
+                                )
+{
+    if (!hdu->format) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "HDU does not have a camera format.\n");
+        return PM_FPA_LEVEL_NONE;
+    }
+    bool mdok = true;                   // Status of MD lookup
+    psMetadata *file = psMetadataLookupMetadata(&mdok, hdu->format, "FILE"); // File information for camera format
+    if (!mdok || !file) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Can't file FILE information for camera format "
+                "configuration.\n");
+        return PM_FPA_LEVEL_NONE;
+    }
+    psString extensions = psMetadataLookupStr(&mdok, file, "EXTENSIONS"); // Where the HDUs are
+    if (!mdok || !extensions || strlen(extensions) == 0) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Can't find EXTENSIONS in the FILE information of the camera "
+                "format configuration.\n");
+        return PM_FPA_LEVEL_NONE;
+    }
+    if (strcasecmp(extensions, "CELL") == 0) {
+        return PM_FPA_LEVEL_CELL;
+    }
+    if (strcasecmp(extensions, "CHIP") == 0) {
+        return PM_FPA_LEVEL_CHIP;
+    }
+    if (strcasecmp(extensions, "FPA") == 0) {
+        return PM_FPA_LEVEL_FPA;
+    }
+    if (strcasecmp(extensions, "NONE") == 0) {
+        return PM_FPA_LEVEL_NONE;
+    }
+    // No idea what it is
+    psError(PS_ERR_IO, true, "EXTENSIONS (%s) in FILE information is not FPA, CHIP, CELL or NONE.\n",
+            extensions);
+    return PM_FPA_LEVEL_NONE;
+}
+
+// Generate HDU for cells belonging to a chip --- just an iterator
+static bool generateForCells(pmChip *chip // Chip for which to generate HDUs
+                            )
+{
+    psArray *cells = chip->cells;       // Array of cells
+    bool status = true;                 // Status of HDU generation
+    for (long i = 0; i < cells->n; i++) {
+        status |= pmHDUGenerateForCell(cells->data[i]);
+    }
+    return status;
+}
+
+// Generate HDU for chips belonging to an FPA --- just an iterator
+static bool generateForChips(pmFPA *fpa // FPA for which to generate HDUs
+                            )
+{
+    psArray *chips = fpa->chips;        // Array of chips
+    bool status = true;                 // Status of HDU generation
+    for (long i = 0; i < chips->n; i++) {
+        status |= pmHDUGenerateForChip(chips->data[i]);
+    }
+    return status;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool pmHDUGenerateForCell(pmCell *cell)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+
+    // Get the HDU and a list of cells below it
+    pmHDU *hdu = pmHDUFromCell(cell); // The HDU in the cell
+    if (!hdu) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Can't find an HDU for cell.\n");
+        return false;
+    }
+    if (hdu->images && hdu->masks && hdu->weights) {
+        // It's already here!
+        return true;
+    }
+
+    pmFPALevel extLevel = extensionLevel(hdu);
+    switch (extLevel) {
+    case PM_FPA_LEVEL_NONE:
+    case PM_FPA_LEVEL_CELL: {
+            psList *cells = psListAlloc(NULL); // List of cells below the HDU
+
+            if (cell->hdu) {
+                psListAdd(cells, PS_LIST_TAIL, cell);
+            } else {
+                pmChip *chip = cell->parent;    // The parent chip
+                if (chip->hdu) {
+                    addCellsFromChip(cells, chip);
+                } else {
+                    pmFPA *fpa = chip->parent;  // The parent FPA
+                    if (fpa->hdu) {
+                        addCellsFromFPA(cells, fpa);
+                    }
+                }
+            }
+            if (cells->n == 0) {
+                // Nothing to do
+                return true;
+            }
+
+            return generateHDU(hdu, cells);
+        }
+    case PM_FPA_LEVEL_CHIP:
+    case PM_FPA_LEVEL_FPA:
+        return pmHDUGenerateForChip(cell->parent);
+    default:
+        psAbort("Shouldn't ever get here: check your camera format configuration.\n");
+    }
+    return false;
+}
+
+bool pmHDUGenerateForChip(pmChip *chip)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+
+    // Get the HDU and a list of cells below it
+    pmHDU *hdu = pmHDUFromChip(chip);   // The HDU in the chip
+    if (!hdu) {
+        // Nothing here; need to look further down
+        return generateForCells(chip);
+    }
+    if (hdu->images && hdu->masks && hdu->weights) {
+        // It's already here!
+        return true;
+    }
+
+    pmFPALevel extLevel = extensionLevel(hdu);
+    switch (extLevel) {
+    case PM_FPA_LEVEL_CELL:
+        // Work on lower levels
+        return generateForCells(chip);
+    case PM_FPA_LEVEL_NONE:
+    case PM_FPA_LEVEL_CHIP: {
+            // Work on this level
+            psList *cells = psListAlloc(NULL);  // List of cells below the HDU
+            if (chip->hdu) {
+                addCellsFromChip(cells, chip);
+            } else {
+                pmFPA *fpa = chip->parent;  // The parent FPA
+                if (fpa->hdu) {
+                    addCellsFromFPA(cells, fpa);
+                }
+            }
+            if (cells->n == 0) {
+                // Nothing to do
+                return true;
+            }
+
+            return generateHDU(hdu, cells);
+        }
+    case PM_FPA_LEVEL_FPA:
+        // Work on higher levels
+        return pmHDUGenerateForFPA(chip->parent);
+    default:
+        psAbort("Shouldn't ever get here: check your camera format configuration.\n");
+    }
+    return false;
+}
+
+
+bool pmHDUGenerateForFPA(pmFPA *fpa)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+
+    // Get the HDU and a list of cells below it
+    pmHDU *hdu = pmHDUFromFPA(fpa);     // The HDU in the FPA
+    if (!hdu) {
+        // Nothing here; need to look further down
+        return generateForChips(fpa);
+    }
+    if (hdu->images && hdu->masks && hdu->weights) {
+        // It's already here!
+        return true;
+    }
+
+    pmFPALevel extLevel = extensionLevel(hdu);
+    switch (extLevel) {
+    case PM_FPA_LEVEL_CELL:
+    case PM_FPA_LEVEL_CHIP:
+        // Work on lower levels
+        return generateForChips(fpa);
+    case PM_FPA_LEVEL_NONE:
+    case PM_FPA_LEVEL_FPA: {
+            // Work on this level
+            psList *cells = psListAlloc(NULL); // List of cells below the HDU
+            if (fpa->hdu) {
+                addCellsFromFPA(cells, fpa);
+            }
+            if (cells->n == 0) {
+                // Nothing to do
+                return true;
+            }
+
+            return generateHDU(hdu, cells);
+        }
+    default:
+        psAbort("Shouldn't ever get here: check your camera format configuration.\n");
+    }
+    return false;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmHDUGenerate.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmHDUGenerate.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmHDUGenerate.h	(revision 22158)
@@ -0,0 +1,53 @@
+/* @file pmHDUGenerate.h
+ * @brief Generate HDU pixels from FPA components that have pixels
+ *
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-03-30 21:12:56 $
+ * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_HDU_GENERATE_H
+#define PM_HDU_GENERATE_H
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+/// Generate an HDU (with CELL.TRIMSEC, CELL.BIASSEC and pixels) for a cell with pixels
+///
+/// The write functions for the FPA hierarchy use pmHDUWrite, which assumes that the images in the readouts
+/// are subimages of the pixels in the HDU structure.  If this is not the case, the HDU pixels can be
+/// generated using some simple assumptions.  Splices the images and overscans together without regard for
+/// CELL.X0 and CELL.Y0 (for a proper mosaic, see pmFPAMosaic), though it should respect CELL.READDIR (so that
+/// the bias and trim sections match properly).  A warning may be generated after running this function if the
+/// bias and trim sections are specified in the camera format by default values rather than in the header.
+/// Failure of this function is often due to a bad camera format file.
+bool pmHDUGenerateForCell(pmCell *cell  ///< The cell for which to generate an HDU
+                         );
+
+/// Generate an HDU (with CELL.TRIMSEC, CELL.BIASSEC and pixels) for a cell with pixels
+///
+/// The write functions for the FPA hierarchy use pmHDUWrite, which assumes that the images in the readouts
+/// are subimages of the pixels in the HDU structure.  If this is not the case, the HDU pixels can be
+/// generated using some simple assumptions.  Splices the images and overscans together without regard for
+/// CELL.X0 and CELL.Y0 (for a proper mosaic, see pmFPAMosaic), though it should respect CELL.READDIR (so that
+/// the bias and trim sections match properly).  A warning may be generated after running this function if the
+/// bias and trim sections are specified in the camera format by default values rather than in the header.
+/// Failure of this function is often due to a bad camera format file.
+bool pmHDUGenerateForChip(pmChip *chip  ///< The chip for which to generate an HDU
+                         );
+
+// Generate an HDU (with CELL.TRIMSEC, CELL.BIASSEC and pixels) from an FPA with pixels
+///
+/// The write functions for the FPA hierarchy use pmHDUWrite, which assumes that the images in the readouts
+/// are subimages of the pixels in the HDU structure.  If this is not the case, the HDU pixels can be
+/// generated using some simple assumptions.  Splices the images and overscans together without regard for
+/// CELL.X0 and CELL.Y0 (for a proper mosaic, see pmFPAMosaic), though it should respect CELL.READDIR (so that
+/// the bias and trim sections match properly).  A warning may be generated after running this function if the
+/// bias and trim sections are specified in the camera format by default values rather than in the header.
+/// Failure of this function is often due to a bad camera format file.
+bool pmHDUGenerateForFPA(pmFPA *fpa     ///< The fpa for which to generate an HDU
+                        );
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmHDUUtils.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmHDUUtils.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmHDUUtils.c	(revision 22158)
@@ -0,0 +1,172 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmHDUUtils.h"
+
+pmHDU *pmHDUGetFirst (const pmFPA *fpa) {
+
+    // XXX we probably should have an indicator in pmFPA about the depths.
+
+    if (!fpa) return NULL;
+    if (fpa->hdu) return fpa->hdu;
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+	pmChip *chip = fpa->chips->data[i];
+	if (!chip) continue;
+	if (chip->hdu) return chip->hdu;
+	if (!chip->cells) continue;
+	for (int j = 0; j < chip->cells->n; j++) {
+	    pmCell *cell = chip->cells->data[j];
+	    if (!cell) continue;
+	    if (cell->hdu) return cell->hdu;
+	}
+    }
+    return NULL;
+}
+
+pmHDU *pmHDUFromFPA(const pmFPA *fpa)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, NULL);
+    return fpa->hdu;
+}
+
+pmHDU *pmHDUFromChip(const pmChip *chip)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, NULL);
+
+    pmHDU *hdu = chip->hdu;             // The HDU information
+    if (!hdu) {
+        hdu = pmHDUFromFPA(chip->parent); // Grab HDU info from the FPA
+    }
+
+    return hdu;
+}
+
+pmHDU *pmHDUFromCell(const pmCell *cell)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, NULL);
+
+    pmHDU *hdu = cell->hdu;             // The HDU information
+    if (!hdu) {
+        hdu = pmHDUFromChip(cell->parent); // Grab HDU info from the chip
+    }
+
+    return hdu;
+}
+
+pmHDU *pmHDUFromReadout(const pmReadout *readout)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, NULL);
+
+    pmCell *cell = readout->parent; // cell containing this readout;
+    pmHDU *hdu = pmHDUFromCell(cell);
+    return hdu;
+}
+
+// Get the lowest HDU
+pmHDU *pmHDUGetLowest(const pmFPA *fpa, const pmChip *chip, const pmCell *cell)
+{
+    pmHDU *hdu = NULL;          // The HDU that's at the lowest level
+    if (cell) {
+        hdu = pmHDUFromCell(cell);
+    } else if (chip) {
+        hdu = pmHDUFromChip(chip);
+    } else if (fpa) {
+        hdu = pmHDUFromFPA(fpa);
+    }
+
+    return hdu;
+}
+
+// Get the highest HDU
+pmHDU *pmHDUGetHighest(const pmFPA *fpa, const pmChip *chip, const pmCell *cell)
+{
+    pmHDU *hdu = NULL;          // The HDU that's at the highest level
+    if (fpa) {
+        hdu = pmHDUFromFPA(fpa);
+    }
+    if (!hdu && chip) {
+        hdu = pmHDUFromChip(chip);
+    }
+    if (!hdu && cell) {
+        hdu = pmHDUFromCell(cell);
+    }
+
+    return hdu;
+}
+
+// Print spaces to indent
+#define INDENT(FILE, LEVEL) \
+{ \
+    for (int i = 0; i < (LEVEL); i++) { \
+        fprintf(FILE, " "); \
+    } \
+}
+
+void pmHDUPrint(FILE *fd, const pmHDU *hdu, int level, bool header)
+{
+    PS_ASSERT_PTR_NON_NULL(hdu,);
+
+    INDENT(fd, level);
+    if (hdu->blankPHU) {
+        fprintf(fd, "HDU: (PHU)\n");
+    } else {
+        fprintf(fd, "HDU: %s\n", hdu->extname);
+    }
+
+    INDENT(fd, level + 1);
+    fprintf(fd, "Format: %p\n", hdu->format);
+    if (header) {
+        INDENT(fd, level + 1);
+        if (hdu->header) {
+            fprintf(fd, "Header:\n");
+            psMetadataPrint(fd, hdu->header, level + 2);
+        } else {
+            fprintf(fd, "No header.\n");
+        }
+    }
+
+    INDENT(fd, level + 1);
+    if (hdu->images) {
+        fprintf(fd, "Images:\n");
+        for (long i = 0; i < hdu->images->n; i++) {
+            psImage *image = hdu->images->data[i]; // Image of interest
+            INDENT(fd, level + 2);
+            fprintf(fd, "%ld: %dx%d\n", i, image->numCols, image->numRows);
+        }
+    } else {
+        fprintf(fd, "NO images.\n");
+    }
+
+    INDENT(fd, level + 1);
+    if (hdu->masks) {
+        fprintf(fd, "Masks:\n");
+        for (long i = 0; i < hdu->masks->n; i++) {
+            psImage *mask = hdu->masks->data[i]; // Mask of interest
+            INDENT(fd, level + 2);
+            fprintf(fd, "%ld: %dx%d\n", i, mask->numCols, mask->numRows);
+        }
+    } else {
+        fprintf(fd, "NO masks.\n");
+    }
+
+    INDENT(fd, level + 1);
+    if (hdu->weights) {
+        fprintf(fd, "Weights:\n");
+        for (long i = 0; i < hdu->weights->n; i++) {
+            psImage *weight = hdu->weights->data[i]; // Weight image of interest
+            INDENT(fd, level + 2);
+            fprintf(fd, "%ld: %dx%d\n", i, weight->numCols, weight->numRows);
+        }
+    } else {
+        fprintf(fd, "NO weights.\n");
+    }
+
+    return;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmHDUUtils.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmHDUUtils.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmHDUUtils.h	(revision 22158)
@@ -0,0 +1,61 @@
+/* @file pmHDUUtils.h
+ * @brief Utility functions for working with an HDU
+ *
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-15 20:25:00 $
+ * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_HDU_UTILS_H
+#define PM_HDU_UTILS_H
+
+/// @addtogroup Camera Camera Layout
+/// @{
+
+/// Get the first HDU encountered in the hierarchy
+pmHDU *pmHDUGetFirst (const pmFPA *fpa);
+
+/// Get the lowest HDU in the hierarchy
+///
+/// The lowest HDU in the hierarchy will be the one with the actual pixels (if all levels are supplied).
+pmHDU *pmHDUGetLowest(const pmFPA *fpa, ///< The FPA
+                      const pmChip *chip, ///< The chip, or NULL
+                      const pmCell *cell ///< The cell, or NULL
+                     );
+
+/// Get the highest HDU in the hierarchy
+///
+/// The highest HDU in the hierarchy will be the PHU (might get NULL if not all levels are supplied)
+pmHDU *pmHDUGetHighest(const pmFPA *fpa, ///< The FPA
+                       const pmChip *chip, ///< The chip, or NULL
+                       const pmCell *cell ///< The cell, or NULL
+                      );
+
+/// Given an FPA, return the HDU (or NULL if all HDUs reside below the FPA)
+pmHDU *pmHDUFromFPA(const pmFPA *fpa    ///< FPA for which to find HDU
+                   );
+
+/// Given a chip, return the HDU (or NULL if it resides below the chip)
+pmHDU *pmHDUFromChip(const pmChip *chip ///< Chip for which to find HDU
+                    );
+
+/// Given a cell, return the HDU
+pmHDU *pmHDUFromCell(const pmCell *cell ///< Cell for which to find HDU
+                    );
+
+/// Given a readout, return the HDU
+pmHDU *pmHDUFromReadout(const pmReadout *readout ///< Readout for which to find HDU
+                       );
+
+/// Print details about an HDU
+///
+/// This is intended for testing or development use.
+void pmHDUPrint(FILE *fd,               ///< File descriptor to which to print
+                const pmHDU *hdu,       ///< HDU to print
+                int level,              ///< Level at which to print
+                bool header             ///< Print header?
+               );
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmReadoutFake.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmReadoutFake.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmReadoutFake.c	(revision 22158)
@@ -0,0 +1,156 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+
+#include "pmMoments.h"
+#include "pmResiduals.h"
+#include "pmGrowthCurve.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmModelClass.h"
+#include "pmPeaks.h"
+#include "pmSource.h"
+#include "pmSourceUtils.h"
+#include "pmModelUtils.h"
+
+#include "pmReadoutFake.h"
+
+#define MODEL_TYPE "PS_MODEL_RGAUSS"    // Type of model to use
+#define MAX_AXIS_RATIO 20.0             // Maximum axis ratio for PSF model
+#define SOURCE_MASK (PM_SOURCE_MODE_FAIL | PM_SOURCE_MODE_DEFECT | PM_SOURCE_MODE_SATURATED | \
+                     PM_SOURCE_MODE_CR_LIMIT) // Mask to apply to input sources
+
+
+// Given an object model, circularise it by setting the axes to be identical
+static bool circulariseModel(pmModel *model // Model to circularise
+    )
+{
+    assert(model);
+
+    psF32 *params = model->params->data.F32; // Model parameters
+    psEllipseAxes axes = pmPSF_ModelToAxes(params, MAX_AXIS_RATIO); // Ellipse axes
+    // Curiously, the minor axis can be larger than the major axis, so need to check.
+    if (axes.major >= axes.minor) {
+        axes.minor = axes.major;
+    } else {
+        axes.major = axes.minor;
+    }
+    return pmPSF_AxesToModel(params, axes);
+}
+
+bool pmReadoutFakeFromSources(pmReadout *readout, int numCols, int numRows, const psArray *sources,
+                              const psVector *xOffset, const psVector *yOffset, const pmPSF *psf,
+                              float minFlux, int radius, bool circularise)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_INT_LARGER_THAN(numCols, 0, false);
+    PS_ASSERT_INT_LARGER_THAN(numRows, 0, false);
+    PS_ASSERT_ARRAY_NON_NULL(sources, false);
+
+    if (xOffset || yOffset) {
+        PS_ASSERT_VECTOR_NON_NULL(xOffset, false);
+        PS_ASSERT_VECTOR_NON_NULL(yOffset, false);
+        PS_ASSERT_VECTORS_SIZE_EQUAL(xOffset, yOffset, false);
+        PS_ASSERT_VECTOR_TYPE(xOffset, PS_TYPE_S32, false);
+        PS_ASSERT_VECTOR_TYPE_EQUAL(xOffset, yOffset, false);
+        if (xOffset->n != sources->n) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    "Number of offset vectors (%ld) and sources (%ld) doesn't match",
+                    xOffset->n, sources->n);
+            return false;
+        }
+    }
+    PS_ASSERT_PTR_NON_NULL(psf, false);
+    if (radius > 0 && isfinite(minFlux) && minFlux > 0.0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Cannot define both minimum flux and fixed radius.");
+        return false;
+    }
+
+    readout->image = psImageRecycle(readout->image, numCols, numRows, PS_TYPE_F32);
+    psImageInit(readout->image, 0);
+
+    int numSources = sources->n;          // Number of stars
+
+    pmModel *fakeModel = pmModelFromPSFforXY(psf, (float)numCols / 2.0, (float)numRows / 2.0,
+                                             1.0); // Fake model, with central intensity of 1.0
+
+    float flux0 = fakeModel->modelFlux(fakeModel->params); // Flux for central intensity of 1.0
+
+    if (circularise && !circulariseModel(fakeModel)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to circularise PSF model.");
+        psFree(fakeModel);
+        return false;
+    }
+    psFree(fakeModel);
+
+    for (int i = 0; i < numSources; i++) {
+        pmSource *source = sources->data[i]; // Source of interest
+        if (source->mode & SOURCE_MASK) {
+            continue;
+        }
+        if (!isfinite(source->psfMag)) {
+            continue;
+        }
+        float x, y;                     // Coordinates of source
+        if (source->modelPSF) {
+            x = source->modelPSF->params->data.F32[PM_PAR_XPOS];
+            y = source->modelPSF->params->data.F32[PM_PAR_YPOS];
+        } else {
+            x = source->peak->xf;
+            y = source->peak->yf;
+        }
+
+        pmModel *fakeModel = pmModelFromPSFforXY(psf, x, y, powf(10.0, -0.4 * source->psfMag) / flux0);
+        if (!fakeModel) {
+            psErrorClear();
+            continue;
+        }
+        if (circularise && !circulariseModel(fakeModel)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to circularise PSF model.");
+            psFree(fakeModel);
+            return false;
+        }
+
+        psTrace("psModules.camera", 10, "Adding source at %f,%f with flux %f\n",
+                fakeModel->params->data.F32[PM_PAR_XPOS], fakeModel->params->data.F32[PM_PAR_YPOS],
+                fakeModel->params->data.F32[PM_PAR_I0]);
+
+        pmSource *fakeSource = pmSourceAlloc(); // Fake source to generate
+        fakeSource->peak = pmPeakAlloc(x, y, fakeModel->params->data.F32[PM_PAR_I0], PM_PEAK_LONE);
+        float fakeRadius = radius > 0 ? radius : fakeModel->modelRadius(fakeModel->params, minFlux); // Radius
+
+        if (xOffset) {
+            if (!pmSourceDefinePixels(fakeSource, readout, x + xOffset->data.S32[i],
+                                      y + yOffset->data.S32[i], fakeRadius)) {
+                psErrorClear();
+                continue;
+            }
+            if (!pmModelAddWithOffset(fakeSource->pixels, NULL, fakeModel, PM_MODEL_OP_FULL, 0,
+                                      - xOffset->data.S32[i], - yOffset->data.S32[i])) {
+                psErrorClear();
+                continue;
+            }
+        } else {
+            if (!pmSourceDefinePixels(fakeSource, readout, x, y, fakeRadius)) {
+                psErrorClear();
+                continue;
+            }
+            if (!pmModelAdd(fakeSource->pixels, NULL, fakeModel, PM_MODEL_OP_FULL, 0)) {
+                psErrorClear();
+                continue;
+            }
+        }
+        psFree(fakeSource);
+        psFree(fakeModel);
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmReadoutFake.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmReadoutFake.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmReadoutFake.h	(revision 22158)
@@ -0,0 +1,26 @@
+#ifndef PM_READOUT_FAKE_H
+#define PM_READOUT_FAKE_H
+
+#include <pslib.h>
+#include <pmHDU.h>
+#include <pmFPA.h>
+
+#include <pmMoments.h>
+#include <pmResiduals.h>
+#include <pmGrowthCurve.h>
+#include <pmTrend2D.h>
+#include <pmPSF.h>
+
+/// Generate a fake readout from an array of sources
+bool pmReadoutFakeFromSources(pmReadout *readout, ///< Output readout, or NULL
+                              int numCols, int numRows, ///< Dimension of image
+                              const psArray *sources, ///< Array of pmSource
+                              const psVector *xOffset, ///< x offsets for sources (source -> img), or NULL
+                              const psVector *yOffset, ///< y offsets for sources (source -> img), or NULL
+                              const pmPSF *psf, ///< PSF for sources
+                              float minFlux, ///< Minimum flux to bother about; for setting source radius
+                              int radius, ///< Fixed radius for sources
+                              bool circularise ///< Circularise PSF model?
+    );
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmReadoutStack.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmReadoutStack.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmReadoutStack.c	(revision 22158)
@@ -0,0 +1,305 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmReadoutStack.h"
+
+// generate the specified image
+// XXX should it be an error for the image to exist?
+psImage *pmReadoutSetAnalysisImage(pmReadout *readout, // Readout containing image
+				   const char *name, // Name of image in analysis metadata
+				   int numCols, int numRows, // Expected size of image
+				   psElemType type, // Expected type of image
+				   double init // Initial value
+    )
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_STRING_NON_EMPTY(name, false);
+
+    psImage *image = psImageAlloc(numCols, numRows, type);
+
+    if (!psMetadataAddImage(readout->analysis, PS_LIST_TAIL, name, 0, "Analysis image from " __FILE__, image)) {
+	psAbort ("analysis image already exists");
+    }
+    psImageInit(image, init);
+
+    psFree (image); // we still have a view on readout->analysis
+    return image;
+}
+
+// retrieve the specified image
+// XXX not sure why this should call psMemIncrRefCounter
+psImage *pmReadoutGetAnalysisImage(pmReadout *readout, // Readout containing image
+				   const char *name       // Name of image in analysis metadata
+    )
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_STRING_NON_EMPTY(name, false);
+
+    bool mdok;                          // Status of MD lookup
+    psImage *image = psMetadataLookupPtr(&mdok, readout->analysis, name);
+    return image;
+}
+
+psImage *pmReadoutAnalysisImage(pmReadout *readout, // Readout containing image
+                                const char *name, // Name of image in analysis metadata
+                                int numCols, int numRows, // Expected size of image
+                                psElemType type, // Expected type of image
+                                double init // Initial value
+    )
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_STRING_NON_EMPTY(name, false);
+
+    bool mdok;                          // Status of MD lookup
+    psImage *image = psMetadataLookupPtr(&mdok, readout->analysis, name);
+    if (!image) {
+        image = psImageAlloc(numCols, numRows, type);
+        psMetadataAddImage(readout->analysis, PS_LIST_TAIL, name, 0, "Analysis image from " __FILE__, image);
+        psImageInit(image, init);
+        return image;
+    }
+    if (image->numCols != numCols || image->numRows != numRows) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Analysis image %s has incorrect size (%dx%d vs %dx%d)",
+                name, image->numCols, image->numRows, numCols, numRows);
+        return NULL;
+    }
+    if (image->type.type != type) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Analysis image %s has incorrect type (%x vs %x)",
+                name, image->type.type, type);
+        return NULL;
+    }
+    return psMemIncrRefCounter(image);
+}
+
+// XXX for the moment, use col0, row0, numCols, numRows supplied from the outside
+bool pmReadoutStackDefineOutput(pmReadout *readout, int col0, int row0, int numCols, int numRows, bool mask, bool weight, psMaskType blank)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+
+    // XXX is this an error?
+    if (readout->image) return false;
+    readout->col0 = col0;
+    readout->row0 = row0;
+
+    // allocate the images
+    readout->image = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    psImageInit(readout->image, NAN);
+
+    if (mask) {
+	// XXX is this an error?
+        if (readout->mask) return false;
+	readout->mask = psImageAlloc(numCols, numRows, PS_TYPE_MASK);
+	psImageInit(readout->mask, blank);
+    }
+
+    if (weight) {
+	// XXX is this an error?
+        if (readout->weight) return false;
+	readout->weight = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+	psImageInit(readout->weight, NAN);
+    }
+
+    return true;
+}
+
+bool pmReadoutStackSetOutputSize(int *col0, int *row0, int *numCols, int *numRows, const psArray *inputs)
+{
+    PS_ASSERT_ARRAY_NON_NULL(inputs, false);
+    PS_ASSERT_PTR_NON_NULL(col0, false);
+    PS_ASSERT_PTR_NON_NULL(row0, false);
+    PS_ASSERT_PTR_NON_NULL(numCols, false);
+    PS_ASSERT_PTR_NON_NULL(numRows, false);
+
+    // Step through each readout in the input image list to determine how big of an output
+    // image is needed to combine these input images.
+
+    int xMin = INT_MAX;
+    int yMin = INT_MAX;
+    int xMax = 0;
+    int yMax = 0;
+    int xSize = 0;
+    int ySize = 0;           // The size of the output image
+
+    bool valid = false;                 // Do we have a single valid input?
+    for (long i = 0; i < inputs->n; i++) {
+        pmReadout *readout = inputs->data[i]; // Readout of interest
+
+        if (!readout) continue;
+
+        // use the trimsec to define the max full range of the output pixels
+        pmCell *cell = readout->parent; // The parent cell
+        bool mdok = true;       // Status of MD lookup
+        psRegion *trimsec = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.TRIMSEC"); // Trim section
+        if (!mdok || !trimsec || psRegionIsNaN(*trimsec)) {
+            psWarning("CELL.TRIMSEC is not set for readout %ld --- ignored.\n", i);
+        } else {
+            xSize = PS_MAX(xSize, trimsec->x1 - trimsec->x0);
+            ySize = PS_MAX(ySize, trimsec->y1 - trimsec->y0);
+            xMin  = PS_MIN(xMin,  trimsec->x0);
+            xMax  = PS_MAX(xMax,  trimsec->x1);
+            yMin  = PS_MIN(yMin,  trimsec->y0);
+            yMax  = PS_MAX(yMax,  trimsec->y1);
+        }
+        valid = true;
+        psTrace("psModules.camera", 7, "Readout %ld: trimsec: %f,%f - %f,%f\n", i, trimsec->x0, trimsec->y0, trimsec->x1, trimsec->y1);
+    }
+
+    *col0 = xMin;
+    *row0 = yMin;
+    *numCols = xSize;
+    *numRows = ySize;
+
+    if (!valid) {
+        psError(PS_ERR_UNKNOWN, false, "No valid input readouts.");
+    }
+    return valid;
+}
+
+bool pmReadoutUpdateSize(pmReadout *readout, int minCols, int minRows,
+                         int numCols, int numRows, bool mask, bool weight,
+                         psMaskType blank)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+
+    if (readout->image) {
+        readout->col0 = PS_MIN(minCols, readout->col0);
+        readout->row0 = PS_MIN(minRows, readout->row0);
+    } else {
+        readout->col0 = minCols;
+        readout->row0 = minRows;
+    }
+
+    // (reAllocate the images
+    if (!readout->image) {
+        readout->image = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+        psImageInit(readout->image, NAN);
+    }
+    if (readout->image->numCols < numCols || readout->image->numRows < numRows) {
+        // Generate the new output image by extending the current one, or making a whole new one
+        psImage *newImage = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+        psImageInit(newImage, NAN);
+        psImageOverlaySection(newImage, readout->image, readout->col0, readout->row0, "=");
+        psFree(readout->image);
+        readout->image = newImage;
+    }
+
+    if (mask) {
+        if (!readout->mask) {
+            readout->mask = psImageAlloc(numCols, numRows, PS_TYPE_MASK);
+            psImageInit(readout->mask, blank);
+        }
+        if (readout->mask->numCols < numCols || readout->mask->numRows < numRows) {
+            psImage *newMask = psImageAlloc(numCols, numRows, PS_TYPE_MASK);
+            psImageInit(newMask, blank);
+            psImageOverlaySection(newMask, readout->mask, readout->col0, readout->row0, "=");
+            psFree(readout->mask);
+            readout->mask = newMask;
+        }
+    }
+
+    if (weight) {
+        if (!readout->weight) {
+            readout->weight = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+            psImageInit(readout->weight, NAN);
+        }
+        if (readout->weight->numCols < numCols || readout->weight->numRows < numRows) {
+            psImage *newWeight = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+            psImageInit(newWeight, NAN);
+            psImageOverlaySection(newWeight, readout->weight, readout->col0, readout->row0, "=");
+            psFree(readout->weight);
+            readout->weight = newWeight;
+        }
+    }
+
+    return true;
+}
+
+bool pmReadoutStackValidate(int *minInputColsPtr, int *maxInputColsPtr, int *minInputRowsPtr,
+                            int *maxInputRowsPtr, int *numColsPtr, int *numRowsPtr,
+                            const psArray *inputs)
+{
+    PS_ASSERT_ARRAY_NON_NULL(inputs, false);
+    PS_ASSERT_PTR_NON_NULL(minInputColsPtr, false);
+    PS_ASSERT_PTR_NON_NULL(maxInputColsPtr, false);
+    PS_ASSERT_PTR_NON_NULL(minInputRowsPtr, false);
+    PS_ASSERT_PTR_NON_NULL(maxInputRowsPtr, false);
+    PS_ASSERT_PTR_NON_NULL(numColsPtr, false);
+    PS_ASSERT_PTR_NON_NULL(numRowsPtr, false);
+
+    // Step through each readout in the input image list to determine how big of an output image is needed to
+    // combine these input images.
+    int maxInputCols = 0;               // The largest input column value
+    int maxInputRows = 0;               // The largest input row value
+    int minInputCols = INT_MAX;         // The smallest input column value
+    int minInputRows = INT_MAX;         // The smallest input row value
+    int xSize = 0, ySize = 0;           // The size of the output image
+
+    int xMin = INT_MAX;
+    int yMin = INT_MAX;
+    int xMax = 0;
+    int yMax = 0;
+
+    bool valid = false;                 // Do we have a single valid input?
+    for (long i = 0; i < inputs->n; i++) {
+        pmReadout *readout = inputs->data[i]; // Readout of interest
+
+        if (!readout) {
+            continue;
+        }
+        if (!readout->image) {
+            psError(PS_ERR_UNEXPECTED_NULL, true, "Input readout %ld has NULL image.\n", i);
+            return false;
+        }
+
+        // use the trimsec to define the max full range of the output pixels
+        pmCell *cell = readout->parent; // The parent cell
+        bool mdok = true;       // Status of MD lookup
+        psRegion *trimsec = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.TRIMSEC"); // Trim section
+        if (!mdok || !trimsec || psRegionIsNaN(*trimsec)) {
+            psWarning("CELL.TRIMSEC is not set for readout %ld --- ignored.\n", i);
+        } else {
+            xSize = PS_MAX(xSize, trimsec->x1 - trimsec->x0);
+            ySize = PS_MAX(ySize, trimsec->y1 - trimsec->y0);
+            xMin  = PS_MIN(xMin,  trimsec->x0);
+            xMax  = PS_MAX(xMax,  trimsec->x1);
+            yMin  = PS_MIN(yMin,  trimsec->y0);
+            yMax  = PS_MAX(yMax,  trimsec->y1);
+        }
+
+        valid = true;
+
+        // Range of pixels on output images
+        minInputCols = PS_MAX(xMin, PS_MIN(minInputCols, readout->col0));
+        maxInputCols = PS_MIN(xMax, PS_MAX(maxInputCols, readout->col0 + readout->image->numCols));
+        minInputRows = PS_MAX(yMin, PS_MIN(minInputRows, readout->row0));
+        maxInputRows = PS_MIN(yMax, PS_MAX(maxInputRows, readout->row0 + readout->image->numRows));
+
+        psTrace("psModules.camera", 7, "Readout %ld: offset %d,%d; size %dx%d\n", i, readout->col0, readout->row0, readout->image->numCols, readout->image->numRows);
+    }
+
+    if (minInputColsPtr) {
+        *minInputColsPtr = minInputCols;
+    }
+    if (maxInputColsPtr) {
+        *maxInputColsPtr = maxInputCols;
+    }
+    if (minInputRowsPtr) {
+        *minInputRowsPtr = minInputRows;
+    }
+    if (maxInputRowsPtr) {
+        *maxInputRowsPtr = maxInputRows;
+    }
+    if (numColsPtr) {
+        *numColsPtr = xSize;
+    }
+    if (numRowsPtr) {
+        *numRowsPtr = ySize;
+    }
+
+    return valid;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmReadoutStack.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmReadoutStack.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/camera/pmReadoutStack.h	(revision 22158)
@@ -0,0 +1,53 @@
+#ifndef PM_READOUT_STACK_H
+#define PM_READOUT_STACK_H
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+
+#define PM_READOUT_STACK_ANALYSIS_COUNT "STACK.COUNT" // Name for count image in analysis metadata
+#define PM_READOUT_STACK_ANALYSIS_SIGMA "STACK.SIGMA" // Name for sigma image in analysis metadata
+
+/// Update an output readout (for a stack) with the correct col0,row0 and the image size
+bool pmReadoutUpdateSize(pmReadout *readout, ///< Readout which to update
+                         int minCols, int minRows, ///< Minimum coordinates
+                         int numCols, int numRows, ///< Size of images
+                         bool mask,     ///< Worry about the mask?
+                         bool weight,   ///< Worry about the weight?
+                         psMaskType blank ///< Mask value to give to blank pixels
+    );
+
+/// Determine how large an output image is needed to combine the input readouts
+bool pmReadoutStackValidate(int *minInputColsPtr, int *maxInputColsPtr, ///< Min and max size in x
+                            int *minInputRowsPtr, int *maxInputRowsPtr, ///< Min and max size in y
+                            int *numColsPtr, int *numRowsPtr, ///< Size of image
+                            const psArray *inputs ///< Array of pmReadouts
+    );
+
+psImage *pmReadoutSetAnalysisImage(pmReadout *readout, // Readout containing image
+				   const char *name, // Name of image in analysis metadata
+				   int numCols, int numRows, // Expected size of image
+				   psElemType type, // Expected type of image
+				   double init // Initial value
+    );
+
+// retrieve the specified image
+// XXX not sure why this should call psMemIncrRefCounter
+psImage *pmReadoutGetAnalysisImage(pmReadout *readout, // Readout containing image
+				   const char *name       // Name of image in analysis metadata
+    );
+
+
+/// Return an image from analysis metadata, produced while stacking
+psImage *pmReadoutAnalysisImage(pmReadout *readout, // Readout containing image
+                                const char *name, // Name of image in analysis metadata
+                                int numCols, int numRows, // Expected size of image
+                                psElemType type, // Expected type of image
+                                double init // Initial value
+    );
+
+// XXX for the moment, use col0, row0, numCols, numRows supplied from the outside
+bool pmReadoutStackDefineOutput(pmReadout *readout, int col0, int row0, int numCols, int numRows, bool mask, bool weight, psMaskType blank);
+
+bool pmReadoutStackSetOutputSize(int *col0, int *row0, int *numCols, int *numRows, const psArray *inputs);
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/.cvsignore	(revision 22158)
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/Makefile.am	(revision 22158)
@@ -0,0 +1,23 @@
+noinst_LTLIBRARIES = libpsmodulesconcepts.la
+
+libpsmodulesconcepts_la_CPPFLAGS = $(SRCINC) $(PSMODULES_CFLAGS)
+libpsmodulesconcepts_la_LDFLAGS  = -release $(PACKAGE_VERSION)
+libpsmodulesconcepts_la_SOURCES  = \
+	pmConcepts.c \
+	pmConceptsAverage.c \
+	pmConceptsRead.c \
+	pmConceptsWrite.c \
+	pmConceptsStandard.c \
+	pmConceptsPhotcode.c \
+	pmConceptsUpdate.c
+
+pkginclude_HEADERS = \
+	pmConcepts.h \
+	pmConceptsAverage.h \
+	pmConceptsRead.h \
+	pmConceptsWrite.h \
+	pmConceptsStandard.h \
+	pmConceptsPhotcode.h \
+	pmConceptsUpdate.h
+
+CLEANFILES = *~
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConcepts.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConcepts.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConcepts.c	(revision 22158)
@@ -0,0 +1,950 @@
+// XXX *REALLY* need generic "concept update" and "concept read" functions that handles the type transparently
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <pslib.h>
+#include <string.h>
+
+#include "pmConfig.h"
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmHDUUtils.h"
+#include "pmConcepts.h"
+#include "pmConceptsRead.h"
+#include "pmConceptsWrite.h"
+#include "pmConceptsStandard.h"
+#include "pmConceptsUpdate.h"
+
+static bool conceptsInitialised = false;// Have concepts been read?
+static psMetadata *conceptsFPA = NULL;  // Known concepts for FPA
+static psMetadata *conceptsChip = NULL; // Known concepts for chip
+static psMetadata *conceptsCell = NULL; // Known concepts for cell
+
+// Return the appropriate concepts metadata, given the level
+static psMetadata *conceptsFromLevel(pmFPALevel level)
+{
+    switch (level) {
+    case PM_FPA_LEVEL_FPA:
+        return conceptsFPA;
+    case PM_FPA_LEVEL_CHIP:
+        return conceptsChip;
+    case PM_FPA_LEVEL_CELL:
+        return conceptsCell;
+    default:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Invalid concept level provided: %d\n", level);
+        return NULL;
+    }
+}
+
+// Free a concept
+static void conceptSpecFree(pmConceptSpec *spec)
+{
+    psFree(spec->blank);
+}
+
+pmConceptSpec *pmConceptSpecAlloc(psMetadataItem *blank, pmConceptParseFunc parse,
+                                  pmConceptFormatFunc format, bool required)
+{
+    pmConceptSpec *spec = psAlloc(sizeof(pmConceptSpec));
+    psMemSetDeallocator(spec, (psFreeFunc)conceptSpecFree);
+
+    spec->blank = psMemIncrRefCounter(blank);
+    spec->parse = parse;
+    spec->format = format;
+    spec->required = required;
+
+    return spec;
+}
+
+psList *pmConceptsList(pmFPALevel level)
+{
+    if (!conceptsInitialised) {
+        pmConceptsInit();
+    }
+
+    // Get the appropriate concepts
+    psMetadata *concepts = conceptsFromLevel(level); // Metadata of concepts specs
+    if (!concepts) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Invalid concept level provided: %d\n", level);
+        return NULL;
+    }
+
+    // Pull out the names
+    psList *list = psListAlloc(NULL);   // List of concepts' names
+    psMetadataIterator *iter = psMetadataIteratorAlloc(concepts, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *item;               // Item from iteration
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        psListAdd(list, PS_LIST_TAIL, item->name);
+    }
+    psFree(iter);
+    return list;
+}
+
+bool pmConceptGetRequired(const char *name, pmFPALevel level)
+{
+    PS_ASSERT_STRING_NON_EMPTY(name, false);
+    if (!conceptsInitialised) {
+        pmConceptsInit();
+    }
+
+    psMetadata *concepts = conceptsFromLevel(level); // The metadata of known concepts
+
+    bool mdok;                          // Status of MD lookup
+    pmConceptSpec *spec = psMetadataLookupPtr(&mdok, concepts, name); // The specification
+    if (!spec) {
+        // Won't throw an error, because we can't distinguish an error from the desired result.
+        // However, that doesn't really matter, because if we can't find it, then it can't be required!
+        return false;
+    }
+
+    return spec->required;
+}
+
+bool pmConceptSetRequired(const char *name, pmFPALevel level, bool required)
+{
+    PS_ASSERT_STRING_NON_EMPTY(name, false);
+
+    if (!conceptsInitialised) {
+        pmConceptsInit();
+    }
+
+    psMetadata *concepts = conceptsFromLevel(level); // The metadata of known concepts
+
+    bool mdok;                          // Status of MD lookup
+    pmConceptSpec *spec = psMetadataLookupPtr(&mdok, concepts, name); // The specification
+    if (!spec) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to find defined concept %s in level %d.",
+                name, level);
+        return false;
+    }
+    spec->required = required;
+
+    return true;
+}
+
+bool pmConceptRegister(psMetadataItem *blank, pmConceptParseFunc parse,
+                        pmConceptFormatFunc format, bool required, pmFPALevel level)
+{
+    PS_ASSERT_PTR_NON_NULL(blank, false);
+
+    if (!conceptsInitialised) {
+        pmConceptsInit();
+    }
+
+    psMetadata *target = conceptsFromLevel(level); // The metadata of known concepts to write to
+    if (!target) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                "Unable to register concept at invalid concept level.");
+        return false;
+    }
+
+    pmConceptSpec *spec = pmConceptSpecAlloc(blank, parse, format, required); // The concept specification
+    psMetadataAdd(target, PS_LIST_TAIL, blank->name, PS_DATA_UNKNOWN | PS_META_REPLACE,
+                  "Concepts specification", spec);
+    psFree(spec);                       // Drop reference
+
+    return true;
+}
+
+
+// Set all registered concepts to blank value for the specified level
+static bool conceptsBlank(psMetadata **specs, // One of the concepts specifications
+                          psMetadata *target // Place to install the concepts
+                         )
+{
+    assert(specs);
+    assert(target);
+
+    if (!conceptsInitialised) {
+        pmConceptsInit();
+    }
+    psMetadataIterator *specsIter = psMetadataIteratorAlloc(*specs, PS_LIST_HEAD, NULL); // Iterator on specs
+    psMetadataItem *specItem = NULL;    // Item from the specs metadata
+    while ((specItem = psMetadataGetAndIncrement(specsIter))) {
+        psTrace("psModules.concepts", 9, "Blanking %s...\n", specItem->name);
+        pmConceptSpec *spec = specItem->data.V; // The specification
+        psMetadataItem *blank = spec->blank; // The concept
+        psMetadataItem *copy = NULL;    // Copy of the blank concept
+        // Trap the lists, which can't be copied in the ordinary way without a warning
+        if (blank->type == PS_DATA_LIST) {
+            copy = psMetadataItemAllocPtr(blank->name, PS_DATA_LIST, blank->comment, blank->data.V);
+        } else {
+            copy = psMetadataItemCopy(blank);
+        }
+        if (!psMetadataAddItem(target, copy, PS_LIST_TAIL, PS_META_REPLACE)) {
+            psLogMsg(__func__, PS_LOG_WARN, "Unable to add blank version of concept %s\n", blank->name);
+        }
+        psFree(copy);                   // Drop reference
+    }
+    psFree(specsIter);
+
+    return true;
+}
+
+
+
+// Read all registered concepts for the specified level
+static bool conceptsRead(psMetadata **specs, // One of the concepts specifications
+                         pmFPA *fpa,    // The FPA
+                         pmChip *chip,  // The chip
+                         pmCell *cell, // The cell
+                         unsigned int *read,     // What's already been read
+                         pmConceptSource source, // The source of the concepts to read
+                         pmConfig *config, // Configuration
+                         psMetadata *target // Place into which to read the concepts
+                        )
+{
+    assert(specs);
+    assert(read);
+    assert(target);
+
+    if (!conceptsInitialised) {
+        pmConceptsInit();
+    }
+
+    // At least one HDU is required for the reading functions
+    pmHDU *hduLow = pmHDUGetLowest(fpa, chip, cell); // Lowest HDU.
+    if (!hduLow) {
+        // Can't do anything --- don't record any success, but don't return an error either
+        return true;
+    }
+    pmHDU *hduHigh = pmHDUGetHighest(fpa, chip, cell); // Highest HDU
+
+    if (cell && (cell->conceptsRead == PM_CONCEPT_SOURCE_NONE)) {
+        pmConceptsBlankCell(cell);
+        cell->conceptsRead = PM_CONCEPT_SOURCE_BLANK;
+    }
+    if (chip && (chip->conceptsRead == PM_CONCEPT_SOURCE_NONE)) {
+        pmConceptsBlankChip(chip);
+        chip->conceptsRead = PM_CONCEPT_SOURCE_BLANK;
+    }
+    if (fpa && (fpa->conceptsRead == PM_CONCEPT_SOURCE_NONE)) {
+        pmConceptsBlankFPA(fpa);
+        fpa->conceptsRead = PM_CONCEPT_SOURCE_BLANK;
+    }
+
+    bool success = true;                // Success in reading concepts?
+    if (source & PM_CONCEPT_SOURCE_CELLS && !(*read & PM_CONCEPT_SOURCE_CELLS) && cell) {
+        if (p_pmConceptsReadFromCells(target, *specs, cell)) {
+            *read |= PM_CONCEPT_SOURCE_CELLS;
+        } else {
+            psError(PS_ERR_UNKNOWN, false, "Error reading concepts from camera configuration.\n");
+            success = false;
+        }
+    }
+
+    if (source & PM_CONCEPT_SOURCE_DEFAULTS && !(*read & PM_CONCEPT_SOURCE_DEFAULTS)) {
+        if (p_pmConceptsReadFromDefaults(target, *specs, fpa, chip, cell)) {
+            *read |= PM_CONCEPT_SOURCE_DEFAULTS;
+        } else {
+            psError(PS_ERR_UNKNOWN, false, "Error reading concepts from defaults.\n");
+            success = false;
+        }
+    }
+
+    if (source & PM_CONCEPT_SOURCE_PHU && !(*read & PM_CONCEPT_SOURCE_PHU) && hduHigh->header) {
+        if (p_pmConceptsReadFromHeader(target, *specs, fpa, chip, cell)) {
+            *read |= PM_CONCEPT_SOURCE_PHU;
+        } else {
+            psError(PS_ERR_UNKNOWN, false, "Error reading concepts from PHU.\n");
+            success = false;
+        }
+    }
+
+    // If there are multiple HDUs, then it may be that one of them hasn't been read yet (hdu->header not set)
+    if (source & PM_CONCEPT_SOURCE_HEADER && !(*read & PM_CONCEPT_SOURCE_HEADER) &&
+        hduLow != hduHigh && hduLow->header) {
+        if (p_pmConceptsReadFromHeader(target, *specs, fpa, chip, cell)) {
+            *read |= PM_CONCEPT_SOURCE_HEADER;
+        } else {
+            psError(PS_ERR_UNKNOWN, false, "Error reading concepts from header.\n");
+            success = false;
+        }
+    }
+
+    #ifdef HAVE_PSDB
+    if (source & PM_CONCEPT_SOURCE_DATABASE && !(*read & PM_CONCEPT_SOURCE_DATABASE)) {
+        if (p_pmConceptsReadFromDatabase(target, *specs, fpa, chip, cell, config)) {
+            *read |= PM_CONCEPT_SOURCE_DATABASE;
+        } else {
+            psError(PS_ERR_UNKNOWN, false, "Error reading concepts from database.\n");
+            success = false;
+        }
+    }
+    #endif
+
+    pmConceptsUpdate(fpa, chip, cell);
+
+    return success;
+}
+
+// Write all registered concepts for the specified level
+static bool conceptsWrite(psMetadata **specs, // One of the concepts specifications
+                          const pmFPA *fpa,   // The FPA
+                          const pmChip *chip, // The chip
+                          const pmCell *cell, // The cell
+                          pmConceptSource source, // The source of the concepts to write
+                          pmConfig *config, // Configuration
+                          const psMetadata *concepts // The concepts to write out
+                         )
+{
+    assert(specs);
+    assert(concepts);
+
+    if (!conceptsInitialised) {
+        pmConceptsInit();
+    }
+
+    psTrace("psModules.concepts", 3, "Writing concepts (%p %p %p): %d\n", fpa, chip, cell, source);
+
+    if (source & PM_CONCEPT_SOURCE_CELLS) {
+        p_pmConceptsWriteToCells(*specs, cell, concepts);
+    }
+    if (source & PM_CONCEPT_SOURCE_DEFAULTS) {
+        p_pmConceptsWriteToDefaults(*specs, fpa, chip, cell, concepts);
+    }
+    if (source & (PM_CONCEPT_SOURCE_PHU | PM_CONCEPT_SOURCE_HEADER)) {
+        p_pmConceptsWriteToHeader(*specs, fpa, chip, cell, concepts);
+    }
+    if (source & PM_CONCEPT_SOURCE_DATABASE) {
+        p_pmConceptsWriteToDatabase(*specs, fpa, chip, cell, config, concepts);
+    }
+
+    return true;
+}
+
+
+bool pmConceptsRead(pmFPA *fpa, pmChip *chip, pmCell *cell, pmConceptSource source, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    bool success = conceptsRead(&conceptsFPA, fpa, chip, cell, &fpa->conceptsRead, source,
+                                config, fpa->concepts);
+    if (chip) {
+        success &= conceptsRead(&conceptsChip, fpa, chip, cell, &chip->conceptsRead, source,
+                                config, chip->concepts);
+    }
+    if (cell) {
+        success &= conceptsRead(&conceptsCell, fpa, chip, cell, &cell->conceptsRead, source,
+                                config, cell->concepts);
+    }
+
+    return success;
+}
+
+
+bool pmConceptsBlankFPA(pmFPA *fpa)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    psTrace("psModules.concepts", 5, "Blanking FPA concepts: %p %p\n", conceptsFPA, fpa->concepts);
+    return conceptsBlank(&conceptsFPA, fpa->concepts);
+}
+
+
+bool pmConceptsReadFPA(pmFPA *fpa, pmConceptSource source, bool propagateDown, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    psTrace("psModules.concepts", 5, "Reading FPA concepts: %p %p\n", conceptsFPA, fpa->concepts);
+    bool success = conceptsRead(&conceptsFPA, fpa, NULL, NULL, &fpa->conceptsRead, source,
+                                config, fpa->concepts);
+    if (propagateDown) {
+        psArray *chips = fpa->chips;    // Array of chips
+        for (long i = 0; i < chips->n; i++) {
+            pmChip *chip = chips->data[i]; // Chip of interest
+            if (chip) {
+                success &= pmConceptsReadChip(chip, source, false, true, config);
+            }
+        }
+    }
+
+    return success;
+}
+
+bool pmConceptsWriteFPA(const pmFPA *fpa, pmConceptSource source, bool propagateDown, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    psTrace("psModules.concepts", 5, "Writing FPA concepts: %p %p\n", conceptsFPA, fpa->concepts);
+    bool success = conceptsWrite(&conceptsFPA, fpa, NULL, NULL, source, config, fpa->concepts);
+    if (propagateDown) {
+        psArray *chips = fpa->chips;        // Array of chips
+        for (long i = 0; i < chips->n; i++) {
+            pmChip *chip = chips->data[i];  // Chip of interest
+            if (chip && !chip->hdu) {
+                success &= pmConceptsWriteChip(chip, source, false, true, config);
+            }
+        }
+    }
+    return success;
+}
+
+bool pmConceptsBlankChip(pmChip *chip)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    psTrace("psModules.concepts", 5, "Blanking chip concepts: %p %p\n", conceptsChip, chip->concepts);
+    return conceptsBlank(&conceptsChip, chip->concepts);
+}
+
+bool pmConceptsReadChip(pmChip *chip, pmConceptSource source, bool propagateUp,
+                        bool propagateDown, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    psTrace("psModules.concepts", 5, "Reading chip concepts: %p %p\n", conceptsChip, chip->concepts);
+    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
+    bool success = conceptsRead(&conceptsChip, fpa, chip, NULL, &chip->conceptsRead, source, config,
+                                chip->concepts);
+    if (propagateUp) {
+        success &= conceptsRead(&conceptsFPA, fpa, chip, NULL, &fpa->conceptsRead, source,
+                                config, fpa->concepts);
+    }
+    if (propagateDown) {
+        psArray *cells = chip->cells;        // Array of cells
+        for (long i = 0; i < cells->n; i++) {
+            pmCell *cell = cells->data[i];  // Cell of interest
+            if (cell) {
+                success &= pmConceptsReadCell(cell, source, false, config);
+            }
+        }
+    }
+    return success;
+}
+
+bool pmConceptsWriteChip(const pmChip *chip, pmConceptSource source, bool propagateUp,
+                         bool propagateDown, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    psTrace("psModules.concepts", 5, "Writing chip concepts: %p %p\n", conceptsChip, chip->concepts);
+    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
+    bool success = conceptsWrite(&conceptsChip, fpa, chip, NULL, source, config, chip->concepts);
+    if (propagateUp && !fpa->hdu) {
+        success &= conceptsWrite(&conceptsFPA, fpa, chip, NULL, source, config, fpa->concepts);
+    }
+    if (propagateDown) {
+        psArray *cells = chip->cells;        // Array of cells
+        for (long i = 0; i < cells->n; i++) {
+            pmCell *cell = cells->data[i];  // Cell of interest
+            if (cell && !cell->hdu) {
+                success &= pmConceptsWriteCell(cell, source, false, config);
+            }
+        }
+    }
+    return success;
+}
+
+bool pmConceptsBlankCell(pmCell *cell)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    psTrace("psModules.concepts", 5, "Blanking cell concepts: %p %p\n", conceptsCell, cell->concepts);
+    return conceptsBlank(&conceptsCell, cell->concepts);
+}
+
+bool pmConceptsReadCell(pmCell *cell, pmConceptSource source, bool propagateUp, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    psTrace("psModules.concepts", 5, "Reading cell concepts: %p %p\n", conceptsCell, cell->concepts);
+    pmChip *chip = cell->parent;        // Chip to which the cell belongs
+    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
+
+    bool success = conceptsRead(&conceptsCell, fpa, chip, cell, &cell->conceptsRead, source, config,
+                                cell->concepts);
+    if (propagateUp) {
+        success &= conceptsRead(&conceptsChip, fpa, chip, cell, &chip->conceptsRead, source, config,
+                                chip->concepts);
+        success &= conceptsRead(&conceptsFPA, fpa, chip, cell, &fpa->conceptsRead, source, config,
+                                fpa->concepts);
+    }
+
+    return success;
+}
+
+bool pmConceptsWriteCell(const pmCell *cell, pmConceptSource source, bool propagateUp, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    psTrace("psModules.concepts", 5, "Writing cell concepts: %p %p\n", conceptsCell, cell->concepts);
+    pmChip *chip = cell->parent;        // Chip to which the cell belongs
+    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
+
+    bool success = conceptsWrite(&conceptsCell, fpa, chip, cell, source, config, cell->concepts);
+    if (propagateUp) {
+        if (!chip->hdu) {
+            success &= conceptsWrite(&conceptsChip, fpa, chip, cell, source, config, chip->concepts);
+            if (!fpa->hdu) {
+                success &= conceptsWrite(&conceptsFPA, fpa, chip, cell, source, config, fpa->concepts);
+            }
+        }
+    }
+
+    return success;
+}
+
+// Register a concept
+#define CONCEPT_REGISTER_FUNCTION(TYPENAME, SUFFIX, DEFAULT) \
+static void conceptRegister##SUFFIX(const char *name, /* Name of concept */ \
+                                    const char *comment, /* Comment for concept */ \
+                                    pmConceptParseFunc parse, /* Parsing function */ \
+                                    pmConceptFormatFunc format, /* Formatting function */ \
+                                    bool required, /* Required concept? */ \
+                                    pmFPALevel level /* Level at which concept applies */ \
+    ) \
+{ \
+    psMetadataItem *item = psMetadataItemAlloc##TYPENAME(name, comment, DEFAULT); /* Item to add */ \
+    pmConceptRegister(item, parse, format, required, level); \
+    psFree(item); \
+    return; \
+}
+
+CONCEPT_REGISTER_FUNCTION(Str, Str, "");
+CONCEPT_REGISTER_FUNCTION(F32, F32, NAN);
+CONCEPT_REGISTER_FUNCTION(F64, F64, NAN);
+CONCEPT_REGISTER_FUNCTION(S32, Enum, -1); // For enums: set default to -1
+CONCEPT_REGISTER_FUNCTION(S32, S32, 0); // For values: set default to 0
+
+static void conceptRegisterTime(const char *name, /* Name of concept */ \
+                                const char *comment, /* Comment for concept */ \
+                                bool required, /* Required concept? */ \
+                                pmFPALevel level /* Level at which concept applies */ \
+    )
+{
+    psTime *time = psTimeAlloc(PS_TIME_TAI); // Blank time
+    // Not particularly distinguishing, but should be good enough
+    time->sec = 0;
+    time->nsec = 0;
+    psMetadataItem *item = psMetadataItemAlloc(name, PS_DATA_TIME, comment, time);
+    psFree(time);
+    pmConceptRegister(item, p_pmConceptParse_TIME, p_pmConceptFormat_TIME, required, level);
+    psFree(item);
+}
+
+bool pmConceptsInit(void)
+{
+    conceptsInitialised = true;
+
+    p_psMemAllocatePersistent(true);
+
+    bool init = false;                  // Did we initialise anything?
+
+    if (! conceptsFPA) {
+        conceptsFPA = psMetadataAlloc();
+        init = true;
+
+        // Install the standard concepts
+        conceptRegisterStr("FPA.TELESCOPE", "Telescope of origin", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterStr("FPA.INSTRUMENT", "Instrument name (according to the instrument)", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterStr("FPA.DETECTOR", "Detector name", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterStr("FPA.COMMENT", "Observation comment", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.FOCUS", "Telescope focus", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.AIRMASS", "Airmass at boresight", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterStr("FPA.FILTERID", "Filter used (parsed, abstract name)", p_pmConceptParse_FPA_FILTER, p_pmConceptFormat_FPA_FILTER, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterStr("FPA.FILTER", "Filter used (instrument name)", false, NULL, NULL, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.POSANGLE", "Position angle of instrument", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterStr("FPA.RADECSYS", "Celestial coordinate system", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF64("FPA.RA", "Right Ascension of boresight", p_pmConceptParse_FPA_Coords, p_pmConceptFormat_FPA_Coords, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF64("FPA.DEC", "Declination of boresight", p_pmConceptParse_FPA_Coords, p_pmConceptFormat_FPA_Coords, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterStr("FPA.OBSTYPE", "Type of observation", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterStr("FPA.OBJECT", "Object of observation", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF64("FPA.ALT", "Altitude of boresight", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF64("FPA.AZ", "Azimuth of boresight", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterEnum("FPA.TIMESYS", "Time system", p_pmConceptParse_TIMESYS, p_pmConceptFormat_TIMESYS, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterTime("FPA.TIME", "Time of exposure", false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.TEMP", "Temperature of focal plane", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.M1X", "Primary Mirror X Position", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.M1Y", "Primary Mirror Y Position", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.M1Z", "Primary Mirror Z Position", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.M1TIP", "Primary Mirror TIP", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.M1TILT", "Primary Mirror TILT", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.M2X", "Primary Mirror X Position", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.M2Y", "Primary Mirror Y Position", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.M2Z", "Primary Mirror Z Position", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.M2TIP", "Primary Mirror TIP", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.M2TILT", "Primary Mirror TILT", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.ENV.TEMP", "Environment: Temperature", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.ENV.HUMID", "Environment: Humidity", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.ENV.WIND", "Environment: Wind speed", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.ENV.DIR", "Environment: Wind direction", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.TELTEMP.M1", "Telescope Temperatures: M1", p_pmConceptParse_TELTEMPS, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.TELTEMP.M1CELL", "Telescope Temperatures: M1 cell", p_pmConceptParse_TELTEMPS, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.TELTEMP.M2", "Telescope Temperatures: M2", p_pmConceptParse_TELTEMPS, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.TELTEMP.SPIDER", "Telescope Temperatures: spider", p_pmConceptParse_TELTEMPS, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.TELTEMP.TRUSS", "Telescope Temperatures: truss", p_pmConceptParse_TELTEMPS, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.TELTEMP.EXTRA", "Telescope Temperatures: extra", p_pmConceptParse_TELTEMPS, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.PON.TIME", "Power On Time", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.EXPOSURE", "Exposure time (sec)", NULL, NULL, false, PM_FPA_LEVEL_FPA);
+    }
+    if (! conceptsChip) {
+        conceptsChip = psMetadataAlloc();
+        init = true;
+
+        // Install the standard concepts
+        conceptRegisterS32("CHIP.XPARITY", "Orientation in x compared to the rest of the FPA", NULL, NULL, true, PM_FPA_LEVEL_CHIP);
+        conceptRegisterS32("CHIP.YPARITY", "Orientation in y compared to the rest of the FPA", NULL, NULL, true, PM_FPA_LEVEL_CHIP);
+        conceptRegisterS32("CHIP.X0", "Position of (0,0) on the FPA",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, true, PM_FPA_LEVEL_CHIP);
+        conceptRegisterS32("CHIP.Y0", "Position of (0,0) on the FPA",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, true, PM_FPA_LEVEL_CHIP);
+        conceptRegisterS32("CHIP.XSIZE", "Size of chip (pixels)", NULL, NULL, true, PM_FPA_LEVEL_CHIP);
+        conceptRegisterS32("CHIP.YSIZE", "Size of chip (pixels)", NULL, NULL, true, PM_FPA_LEVEL_CHIP);
+        conceptRegisterF32("CHIP.TEMP", "Temperature of chip", NULL, NULL, false, PM_FPA_LEVEL_CHIP);
+        conceptRegisterStr("CHIP.ID", "Chip identifier", NULL, NULL, false, PM_FPA_LEVEL_CHIP);
+    }
+
+    if (! conceptsCell) {
+        conceptsCell = psMetadataAlloc();
+        init = true;
+
+        // Install the standard concepts
+        conceptRegisterF32("CELL.GAIN", "CCD gain (e/count)", NULL, NULL, true, PM_FPA_LEVEL_CELL);
+        conceptRegisterF32("CELL.READNOISE", "CCD read noise (e)", NULL, NULL, true, PM_FPA_LEVEL_CELL);
+        conceptRegisterF32("CELL.SATURATION", "Saturation level (counts)", NULL, NULL, true, PM_FPA_LEVEL_CELL);
+        conceptRegisterF32("CELL.BAD", "Bad level (counts)", NULL, NULL, true, PM_FPA_LEVEL_CELL);
+        conceptRegisterS32("CELL.XPARITY", "Orientation in x compared to the rest of the chip", NULL, NULL, true, PM_FPA_LEVEL_CELL);
+        conceptRegisterS32("CELL.YPARITY", "Orientation in y compared to the rest of the chip", NULL, NULL, true, PM_FPA_LEVEL_CELL);
+        conceptRegisterS32("CELL.READDIR", "Read direction, rows=1, cols=2", NULL, NULL, true, PM_FPA_LEVEL_CELL);
+
+        // These (CELL.EXPOSURE and CELL.DARKTIME) used to be READOUT.EXPOSURE and READOUT.DARKTIME, but that
+        // doesn't really make sense at the moment.  Maybe we need to add a "parent" link to the readouts.
+        // But then how are the exposure times REALLY derived?  They're not in the FITS headers, because a
+        // readout is a plane in a 3D image.  We'll have to dream up some additional suffix to specify these,
+        // but for now....
+        conceptRegisterF32("CELL.EXPOSURE", "Exposure time (sec)", NULL, NULL, false, PM_FPA_LEVEL_CELL);
+        conceptRegisterF32("CELL.DARKTIME", "Time since flush (sec)", NULL, NULL, false, PM_FPA_LEVEL_CELL);
+
+        conceptRegisterS32("CELL.XBIN", "Binning in x", p_pmConceptParse_CELL_Binning,p_pmConceptFormat_CELL_XBIN, true, PM_FPA_LEVEL_CELL);
+        conceptRegisterS32("CELL.YBIN", "Binning in y",p_pmConceptParse_CELL_Binning,p_pmConceptFormat_CELL_YBIN, true, PM_FPA_LEVEL_CELL);
+        conceptRegisterEnum("CELL.TIMESYS", "Time system", p_pmConceptParse_TIMESYS,p_pmConceptFormat_TIMESYS, false, PM_FPA_LEVEL_CELL);
+        conceptRegisterTime("CELL.TIME", "Time of exposure", false, PM_FPA_LEVEL_CELL);
+        conceptRegisterS32("CELL.X0", "Position of (0,0) on the chip",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, true, PM_FPA_LEVEL_CELL);
+        conceptRegisterS32("CELL.Y0", "Position of (0,0) on the chip",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, true, PM_FPA_LEVEL_CELL);
+        conceptRegisterS32("CELL.XSIZE", "Size of cell (pixels)", NULL, NULL, true, PM_FPA_LEVEL_CELL);
+        conceptRegisterS32("CELL.YSIZE", "Size of cell (pixels)", NULL, NULL, true, PM_FPA_LEVEL_CELL);
+        conceptRegisterS32("CELL.XWINDOW", "Start of cell window (pixels)",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, true, PM_FPA_LEVEL_CELL);
+        conceptRegisterS32("CELL.YWINDOW", "Start of cell window (pixels)",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, true, PM_FPA_LEVEL_CELL);
+        conceptRegisterF32("CELL.VARFACTOR", "Variance factor for conversion from large to small scales", NULL, NULL, true, PM_FPA_LEVEL_CELL);
+
+        // CELL.TRIMSEC
+        {
+            psRegion *trimsec = psAlloc(sizeof(psRegion)); // Blank trimsec
+            trimsec->x0 = trimsec->y0 = trimsec->x1 = trimsec->y1 = NAN;
+            psMetadataItem *cellTrimsec = psMetadataItemAllocPtr("CELL.TRIMSEC", PS_DATA_REGION,
+                                          "Trim section", trimsec);
+            psFree(trimsec);
+            pmConceptRegister(cellTrimsec, p_pmConceptParse_CELL_TRIMSEC,p_pmConceptFormat_CELL_TRIMSEC, true, PM_FPA_LEVEL_CELL);
+            psFree(cellTrimsec);
+        }
+
+        // CELL.BIASSEC
+        {
+            psList *biassecs = psListAlloc(NULL); // Blank biassecs
+            psMetadataItem *cellBiassec = psMetadataItemAllocPtr("CELL.BIASSEC", PS_DATA_LIST,
+                                          "Bias sections", biassecs);
+            psFree(biassecs);
+            pmConceptRegister(cellBiassec, p_pmConceptParse_CELL_BIASSEC, p_pmConceptFormat_CELL_BIASSEC, true, PM_FPA_LEVEL_CELL);
+            psFree(cellBiassec);
+        }
+
+    }
+
+    p_psMemAllocatePersistent(false);
+
+    return init;
+}
+
+void pmConceptsDone(void)
+{
+    psFree(conceptsFPA);
+    conceptsFPA = NULL;
+    psFree(conceptsChip);
+    conceptsChip = NULL;
+    psFree(conceptsCell);
+    conceptsCell = NULL;
+
+    conceptsInitialised = false;
+}
+
+
+// List of concepts not to copy, for each level.
+// Must be NULL-terminated
+static const char *dontCopyConceptsFPA[] = { "FPA.OBS", "FPA.NAME", "FPA.CAMERA", 0 };
+static const char *dontCopyConceptsChip[] = { "CHIP.NAME", 0 };
+static const char *dontCopyConceptsCell[] = { "CELL.NAME", "CELL.TRIMSEC", "CELL.BIASSEC", 0 };
+
+// Copy concepts from a source container to a target container, avoiding certain entries
+static void copyConcepts(psMetadata *target, // Target metadata container
+                         psMetadata *source, // Source metadata container
+                         const char *dontCopyConcepts[] // Don't copy these concepts
+                         )
+{
+    assert(target);
+    assert(source);
+    assert(dontCopyConcepts);
+
+    psMetadataIterator *iter = psMetadataIteratorAlloc(source, PS_LIST_HEAD, NULL);
+    psMetadataItem *item;               // Item from iteration
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        const char *name = item->name;  // Name of concept
+        bool copyOK = true;            // OK to copy
+        for (int i = 0; dontCopyConcepts[i] && copyOK; i++) {
+            if (!strcmp(name, dontCopyConcepts[i])) {
+                copyOK = false;
+            }
+        }
+        if (!copyOK) {
+            continue;
+        }
+        psMetadataItem *new = psMetadataItemCopy(item); // New item, a copy of the old
+        psMetadataAddItem(target, new, PS_LIST_TAIL, PS_META_REPLACE);
+        psFree(new);                    // Drop reference
+    }
+    psFree(iter);
+
+    return;
+}
+
+
+bool pmFPACopyConcepts(pmFPA *target, const pmFPA *source)
+{
+    PS_ASSERT_PTR_NON_NULL(target, false);
+    PS_ASSERT_PTR_NON_NULL(source, false);
+
+    // Copy FPA concepts
+    copyConcepts(target->concepts, source->concepts, dontCopyConceptsFPA);
+
+    // Copy chip concepts
+    psArray *targetChips = target->chips; // Chips in target
+    psArray *sourceChips = source->chips; // Chips in source
+    if (targetChips->n != sourceChips->n) {
+        psError(PS_ERR_IO, true, "Number of chips in target (%ld) and source (%ld) differ --- unable to copy "
+                "concepts.\n", targetChips->n, sourceChips->n);
+        return false;
+    }
+    for (int i = 0; i < targetChips->n; i++) {
+        pmChip *targetChip = targetChips->data[i]; // Target chip of interest
+        pmChip *sourceChip = sourceChips->data[i]; // Source chip of interest
+        if (! targetChip || ! sourceChip) {
+            continue;
+        }
+
+        copyConcepts(targetChip->concepts, sourceChip->concepts, dontCopyConceptsChip);
+
+        // Copy cell concepts
+        psArray *targetCells = targetChip->cells; // Cells in target
+        psArray *sourceCells = sourceChip->cells; // Cells in source
+        if (targetCells->n != sourceCells->n) {
+            psError(PS_ERR_IO, true, "Number of cells in target (%ld) and source (%ld) differ for chip %d ---"
+                    " unable to copy concepts.\n", targetCells->n, sourceCells->n, i);
+            return false;
+        }
+        for (int j = 0; j < targetCells->n; j++) {
+            pmCell *targetCell = targetCells->data[j]; // Target chip of interest
+            pmCell *sourceCell = sourceCells->data[j]; // Source chip of interest
+            if (! targetCell || ! sourceCell) {
+                continue;
+            }
+
+            copyConcepts(targetCell->concepts, sourceCell->concepts, dontCopyConceptsCell);
+        }
+    }
+
+    return true;
+}
+
+
+bool pmConceptsCopyFPA(pmFPA *target, const pmFPA *source, bool chips, bool cells)
+{
+    PS_ASSERT_PTR_NON_NULL(target, false);
+    PS_ASSERT_PTR_NON_NULL(source, false);
+
+    // Copy FPA concepts
+    copyConcepts(target->concepts, source->concepts, dontCopyConceptsFPA);
+
+    // Copy chip concepts
+    bool status = true;                 // Status of chips
+    if (chips) {
+        psArray *targetChips = target->chips; // Chips in target
+        psArray *sourceChips = source->chips; // Chips in source
+        if (targetChips->n != sourceChips->n) {
+            psError(PS_ERR_IO, true,
+                    "Number of chips in target (%ld) and source (%ld) differ --- unable to copy concepts.",
+                    targetChips->n, sourceChips->n);
+            return false;
+        }
+        for (int i = 0; i < targetChips->n; i++) {
+            pmChip *targetChip = targetChips->data[i]; // Target chip of interest
+            pmChip *sourceChip = sourceChips->data[i]; // Source chip of interest
+            if (! targetChip || ! sourceChip) {
+                continue;
+            }
+
+            status &= pmConceptsCopyChip(targetChip, sourceChip, cells);
+        }
+    }
+
+    return status;
+}
+
+bool pmConceptsCopyChip(pmChip *target, const pmChip *source, bool cells)
+{
+    PS_ASSERT_PTR_NON_NULL(target, false);
+    PS_ASSERT_PTR_NON_NULL(source, false);
+
+    // Copy chip concepts
+    copyConcepts(target->concepts, source->concepts, dontCopyConceptsChip);
+
+    // Copy cell concepts
+    bool status = true;                 // Status of cells
+    if (cells) {
+        psArray *targetCells = target->cells; // Cells in target
+        psArray *sourceCells = source->cells; // Cells in source
+        if (targetCells->n != sourceCells->n) {
+            psError(PS_ERR_IO, true,
+                    "Number of cells in target (%ld) and source (%ld) differ --- unable to copy concepts.",
+                    targetCells->n, sourceCells->n);
+            return false;
+        }
+        for (int j = 0; j < targetCells->n; j++) {
+            pmCell *targetCell = targetCells->data[j]; // Target chip of interest
+            pmCell *sourceCell = sourceCells->data[j]; // Source chip of interest
+            if (! targetCell || ! sourceCell) {
+                continue;
+            }
+
+            status &= pmConceptsCopyCell(targetCell, sourceCell);
+        }
+    }
+
+    return status;
+}
+
+
+bool pmConceptsCopyCell(pmCell *target, const pmCell *source)
+{
+    PS_ASSERT_PTR_NON_NULL(target, false);
+    PS_ASSERT_PTR_NON_NULL(source, false);
+
+    copyConcepts(target->concepts, source->concepts, dontCopyConceptsCell);
+
+    return true;
+}
+
+
+// Interpolate the concept.  Generalises the FPA/Chip/Cell
+#define CONCEPT_INTERPOLATE(SOURCE, NAME) \
+    if (strncmp(concept, NAME, strlen(NAME)) == 0) { \
+        if (!(SOURCE)) { \
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Cannot interpolate %s because %s not provided", \
+                    concept, NAME); \
+            psFree(string); \
+            return NULL; \
+        } \
+        psMetadataItem *item = psMetadataLookup((SOURCE)->concepts, concept); /* Item with concept */ \
+        if (!item) { \
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Can't find concept %s in %s", concept, NAME); \
+            psFree(string); \
+            return NULL; \
+        } \
+        \
+        psString value = psMetadataItemParseString(item); /* Value of concept */ \
+        if (!value) { \
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s", concept); \
+            psFree(string); \
+            return NULL; \
+        } \
+        \
+        char replace[length + 2];       /* String to replace with value */ \
+        replace[0] = '{'; \
+        strcpy(replace + 1, concept); \
+        strcpy(replace + length, "}"); \
+        \
+        psTrace("psModules.concepts", 10, "Interpolating concept %s for %s", replace, value); \
+        \
+        if (!psStringSubstitute(&string, value, replace)) { \
+            psError(PS_ERR_UNKNOWN, false, "Unable to replace concept %s", concept); \
+            psFree(string); \
+            psFree(value); \
+            return NULL; \
+        } \
+        psFree(value); \
+        \
+        continue; \
+    }
+
+
+// XXX Could make the concept delimiters, currently '{' and '}', configurable
+psString pmConceptsInterpolate(const char *input,
+                               const pmFPA *fpa,
+                               const pmChip *chip,
+                               const pmCell *cell
+    )
+{
+    PS_ASSERT_STRING_NON_EMPTY(input, NULL);
+
+    psString string = psStringCopy(input); // Interpolated string, to return
+
+    char *start;                        // Start of a concept
+    while ((start = strchr(string, '{'))) {
+        char *stop = strchr(start, '}'); // End of a concept
+        int length = stop - start;      // Length of the concept name, including terminating \0
+        char concept[length];  // Name of concept
+        strncpy(concept, start + 1, length - 1);
+        concept[length - 1] = '\0';
+
+        psTrace("psModules.concepts", 7, "Interpolating concept %s", concept);
+
+        CONCEPT_INTERPOLATE(fpa,  "FPA");
+        CONCEPT_INTERPOLATE(chip, "CHIP");
+        CONCEPT_INTERPOLATE(cell, "CELL");
+
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unrecognised concept: %s", concept);
+        psFree(string);
+        return NULL;
+    }
+
+    return string;
+}
+
+
+psMetadataItem *p_pmConceptsDepend(const char *name, const psMetadata *menu, const psMetadata *source,
+                                   const pmFPA *fpa, const pmChip *chip, const pmCell *cell)
+{
+    psAssert(name && strlen(name) > 0, "Concept name is empty");
+    psAssert(menu, "Must have menu");
+    psAssert(source, "Must have source");
+
+    // Check for DEPEND
+    psString depend = NULL; // The CONCEPT.DEPEND
+    psStringAppend(&depend, "%s.DEPEND", name);
+    bool mdok;                          // Status of MD lookup
+    const char *dependConcept = psMetadataLookupStr(&mdok, source, depend); // The concept name
+    if (!mdok || !dependConcept || strlen(dependConcept) == 0) {
+        psError(PS_ERR_IO, true, "Unable to parse %s: couldn't find %s in DEFAULTS.\n", name, depend);
+        psFree(depend);
+        return NULL;
+    }
+    psFree(depend);
+    // Now look up the depend value
+    psMetadataItem *dependValue = NULL; // The value of the concept we're looking up
+    if (cell) {
+        dependValue = psMetadataLookup(cell->concepts, dependConcept);
+    }
+    if (chip && !dependValue) {
+        dependValue = psMetadataLookup(chip->concepts, dependConcept);
+    }
+    if (fpa && !dependValue) {
+        dependValue = psMetadataLookup(chip->concepts, dependConcept);
+    }
+    if (!dependValue) {
+        // Not an error --- it may be specified some other way
+        psTrace("psModules.concepts", 7, "Couldn't find DEPEND for %s", name);
+        return NULL;
+    }
+    if (dependValue->type != PS_DATA_STRING) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "%s is required to resolve %s in DEFAULTS, "
+                "but it is not of type STRING.\n", dependConcept, name);
+        return NULL;
+    }
+    const char *key = dependValue->data.V; // The key to the DEPEND menu
+    psTrace("psModules.concepts", 7, "%s.DEPEND resolves to %s....\n", name, key);
+
+    return psMetadataLookup(menu, key);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConcepts.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConcepts.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConcepts.h	(revision 22158)
@@ -0,0 +1,248 @@
+/* @file pmConcepts.h
+ * @brief Top-level functions for defining, registering, reading and writing concepts
+ *
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-06-30 00:53:45 $
+ * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_CONCEPTS_H
+#define PM_CONCEPTS_H
+
+#include <pmConfig.h>
+
+/// @addtogroup Concepts Data Abstraction Concepts
+/// @{
+
+/// Source for concepts when reading and writing.
+///
+/// Since some sources become available at different times from others, we need to provide some specificity to
+/// reading and writing concepts (or we're forced to wait until everything's available, which we don't want to
+/// do).  Concepts may be read from or written to multiple sources at once by OR-ing them.
+typedef enum {
+    PM_CONCEPT_SOURCE_NONE     = 0x00,  ///< No concepts
+    PM_CONCEPT_SOURCE_BLANK    = 0x01,  ///< Blank concepts defined, but not read
+    PM_CONCEPT_SOURCE_CELLS    = 0x02,  ///< Concept comes from the camera information
+    PM_CONCEPT_SOURCE_DEFAULTS = 0x04,  ///< Concept comes from defaults
+    PM_CONCEPT_SOURCE_PHU      = 0x08,  ///< Concept comes from PHU
+    PM_CONCEPT_SOURCE_HEADER   = 0x10,  ///< Concept comes from FITS header
+    PM_CONCEPT_SOURCE_DATABASE = 0x20,  ///< Concept comes from database
+    PM_CONCEPT_SOURCE_ALL      = 0xfe   ///< All concepts (exclude BLANK)
+} pmConceptSource;
+
+/// Function to call to parse a concept once it has been read
+typedef psMetadataItem* (*pmConceptParseFunc)(const psMetadataItem *concept, ///< Concept to parse
+        const psMetadataItem *pattern, ///< Pattern for parsing
+                                              pmConceptSource source, ///< Source of concept
+        const psMetadata *cameraFormat, ///< Camera format definition
+        const pmFPA *fpa, ///< FPA for concept, or NULL
+        const pmChip *chip, ///< Chip for concept, or NULL
+        const pmCell *cell ///< Cell for concept, or NULL
+                                             );
+
+/// Function to call to format a concept for writing
+typedef psMetadataItem* (*pmConceptFormatFunc)(const psMetadataItem *concept, ///< Concept to format
+                                               pmConceptSource source, ///< Source of concept
+        const psMetadata *cameraFormat, ///< Camera format definition
+        const pmFPA *fpa, ///< FPA for concept, or NULL
+        const pmChip *chip, ///< Chip for concept, or NULL
+        const pmCell *cell ///< Cell for concept, or NULL
+                                              );
+
+/// A "concept" specification
+///
+/// Defines the name, default comment, blank value, and functions to parse (after reading) and format (before
+/// writing) the concept.
+typedef struct
+{
+    psMetadataItem *blank;              ///< Blank value of concept; also contains the name and comment
+    pmConceptParseFunc parse;           ///< Function to call to read the concept
+    pmConceptFormatFunc format;         ///< Function to call to write the concept
+    bool required;                      ///< Is concept required (throw an error on problems)?
+}
+pmConceptSpec;
+
+/// Allocator for pmConceptSpec
+pmConceptSpec *pmConceptSpecAlloc(psMetadataItem *blank, ///< Blank value; contains the name
+                                  pmConceptParseFunc parse, ///< Function to call to parse the concept
+                                  pmConceptFormatFunc format, ///< Function to call to format the concept
+                                  bool required ///< Is concept required?
+                                 );
+
+/// Get whether a particular concept is required
+bool pmConceptGetRequired(const char *name, ///< Name of concept
+                          pmFPALevel level ///< Level at which concept resides
+    );
+
+/// Set whether a particular concept is required
+bool pmConceptSetRequired(const char *name, ///< Name of concept
+                          pmFPALevel level, ///< Level at which concept resides
+                          bool required ///< Whether concept is required or not
+    );
+
+/// Register a new concept for parsing and formatting
+///
+/// Defines a new concept, based on the blank value (with name and default comment), and functions to parse
+/// and format the concept.  The new concept is registered at the specified level (FPA, chip or cell).  If the
+/// parse function is NULL, then a default parse function is used, which performs minimal parsing.  Similarly
+/// for the format function.
+bool pmConceptRegister(psMetadataItem *blank, ///< Blank value; contains the name and default comment
+                       pmConceptParseFunc parse, ///< Function to call to parse the concept, or NULL
+                       pmConceptFormatFunc format, ///< Function to call to format the concept, or NULL
+                       bool required,   ///< Is concept required?
+                       pmFPALevel level ///< Level at which to store concept in the FPA hierarchy
+                      );
+
+/// Get a list of defined concepts for a particular level.
+psList *pmConceptsList(pmFPALevel level);
+
+/// Read the concepts for the given set of fpa, chip, cell
+///
+/// Attempts to read as many concepts as possible from the specified source for the specified FPA, chip and
+/// cell.  That is, it will read chip- and cell-level concepts in addition to fpa-level concepts, if the chip
+/// and cell are provided.
+bool pmConceptsRead(pmFPA *fpa,         ///< FPA for which to read concepts
+                    pmChip *chip,       ///< Chip for which to read concepts, or NULL
+                    pmCell *cell,       ///< Cell for which to read concepts, or NULL
+                    pmConceptSource source, ///< The source of the concepts to read
+                    pmConfig *config    ///< Configuration
+                   );
+
+/// Set the concepts within the FPA to the blank value
+bool pmConceptsBlankFPA(pmFPA *fpa      ///< FPA for which to set blank concepts
+                       );
+
+/// Read concepts for an FPA; optionally, read concepts at all lower levels.
+///
+/// Once concepts should be available for reading at the FPA-level, this function attempts to read the
+/// concepts from the specified source.  It also allows concepts to be read at lower levels by iterating over
+/// the components.
+bool pmConceptsReadFPA(pmFPA *fpa,      ///< FPA for which to read concepts
+                       pmConceptSource source, ///< Source for concepts
+                       bool propagateDown, ///< Propagate to lower levels?
+                       pmConfig *config         ///< Configuration
+                      );
+
+/// Write concepts for an FPA; optionally, write concepts at all lower levels.
+///
+/// This function writes all concepts for the FPA to the specified "source".  It also allows concepts to be
+/// written for all lower levels by iterating over the components.
+bool pmConceptsWriteFPA(const pmFPA *fpa,     ///< FPA for which to write concepts
+                        pmConceptSource source, ///< Source for concepts
+                        bool propagateDown, ///< Propagate to lower levels?
+                        pmConfig *config        ///< Configuration
+                       );
+
+/// Set the concepts within the chip to the blank value
+bool pmConceptsBlankChip(pmChip *chip   ///< FPA for which to set blank concepts
+                        );
+
+/// Read concepts for a chip; optionally, read concepts at the FPA and cell levels.
+///
+/// Once concepts should be available for reading at the FPA-level, this function attempts to read the
+/// concepts from the specified source.  It also allows concepts to be read at the fpa level (through the
+/// parent), and the cell level by iterating over the components.
+bool pmConceptsReadChip(pmChip *chip,   ///< Chip for which to read concepts
+                        pmConceptSource source, ///< Source for concepts
+                        bool propagateUp, ///< Propagate to higher levels?
+                        bool propagateDown, ///< Propagate to lower levels?
+                        pmConfig *config        ///< Configuration
+                       );
+
+/// Write concepts for a chip; optionally, write concepts at the FPA and cell levels.
+///
+/// This function writes all concepts for the chip to the specified "source".  It also allows concepts to be
+/// written for the FPA, and the cell level by iterating over the components.
+bool pmConceptsWriteChip(const pmChip *chip,  ///< Chip for which to write concepts
+                         pmConceptSource source, ///< Source for concepts
+                         bool propagateUp,///< Propagate to higher levels?
+                         bool propagateDown, ///< Propagate to lower levels?
+                         pmConfig *config       ///< Configuration
+                        );
+
+/// Set the concepts within the cell to the blank value
+bool pmConceptsBlankCell(pmCell *cell   ///< Cell for which to set blank concepts
+                        );
+
+/// Read concepts for a cell; optionally, read concepts for the parents.
+///
+/// Once concepts should be available for reading at the FPA-level, this function attempts to read the
+/// concepts from the specified source.  It also allows concepts to be read at upper levels through the
+/// parents (note, it would not read concepts for all chips, but only the parent of this cell).
+bool pmConceptsReadCell(pmCell *cell,   ///< Cell for which to read concepts
+                        pmConceptSource source, ///< Source for concepts
+                        bool propagateUp, ///< Propagate to higher levels?
+                        pmConfig *config        ///< Configuration
+                       );
+
+/// Write concepts for a cell; optionally, write concepts for the parents.
+///
+/// This function writes all concepts for the chip to the specified "source".  It also allows concepts to be
+/// written for the upper levels through the parents (note, it would not write concepts for all chips, but
+/// only the parent of this cell).
+bool pmConceptsWriteCell(const pmCell *cell,  ///< FPA for which to write concepts
+                         pmConceptSource source, ///< Source for concepts
+                         bool propagateUp, ///< Propagate to higher levels?
+                         pmConfig *config ///< Configuration
+                        );
+
+/// Initialise the concepts system.
+///
+/// Register the standard concepts, so that concepts may be read and written.  This function is called
+/// automatically the first time the concepts functions are used.
+bool pmConceptsInit(void);
+
+/// Signifies that the user is done with the concepts system.
+///
+/// Frees the registered concepts so there is no memory leak when the user checks "persistent" memory.
+void pmConceptsDone(void);
+
+/// Copy all the concepts within an FPA to another FPA
+///
+/// Iterates over all components of the FPA, and copies the concepts metadata from the source to the target.
+bool pmFPACopyConcepts(pmFPA *target,   ///< The target FPA
+                       const pmFPA *source    ///< The source FPA
+                      );
+
+/// Copy the concepts within an FPA to another FPA; optionally recurse to lower levels
+bool pmConceptsCopyFPA(pmFPA *target,   ///< Target FPA
+                       const pmFPA *source, ///< Source FPA
+                       bool chips,      ///< Recurse to chips level?
+                       bool cells       ///< Recurse to cells level?
+    );
+
+/// Copy the concepts within a chip to another chip; optionally recurse to lower level
+bool pmConceptsCopyChip(pmChip *target, ///< Target chip
+                        const pmChip *source, ///< Source chip
+                        bool cells      ///< Recurse to cells level?
+    );
+
+/// Copy the concepts within a cell to another cell
+bool pmConceptsCopyCell(pmCell *target, ///< Target cell
+                        const pmCell *source ///< Source cell
+    );
+
+/// Interpolate a concept name to the actual value
+///
+/// Concepts enclosed within braces {}, are replaced with the value of the concept
+psString pmConceptsInterpolate(const char *input, ///< Input string
+                               const pmFPA *fpa, ///< FPA with concept values, or NULL
+                               const pmChip *chip, ///< Chip with concept values, or NULL
+                               const pmCell *cell ///< Cell with concept values, or NULL
+    );
+
+/// Look up a dependency menu to get a concept's value
+///
+/// Returns a psMetadataItem with the concept value
+psMetadataItem *p_pmConceptsDepend(const char *name, ///< Name of concept for which to get dependent value
+                                   const psMetadata *menu, ///< Menu in which to look up key
+                                   const psMetadata *source, ///< Source metadata with CONCEPT.DEPEND
+                                   const pmFPA *fpa, ///< FPA for dependency
+                                   const pmChip *chip, ///< Chip for dependency
+                                   const pmCell *cell ///< Cell for dependency
+    );
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsAverage.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsAverage.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsAverage.c	(revision 22158)
@@ -0,0 +1,306 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+#include <string.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmConcepts.h"
+#include "pmConceptsAverage.h"
+
+// Update a metadata entry directly
+#define MD_UPDATE(MD, NAME, TYPE, VALUE) \
+{ \
+    psMetadataItem *item = psMetadataLookup(MD, NAME); \
+    item->data.TYPE = VALUE; \
+}
+
+// Update a metadata string entry directly
+#define MD_UPDATE_STR(MD, NAME, VALUE) \
+{ \
+    psMetadataItem *item = psMetadataLookup(MD, NAME); \
+    psFree(item->data.str); \
+    item->data.str = psStringCopy(VALUE); \
+}
+
+bool pmConceptsAverageFPAs(pmFPA *target, psList *sources)
+{
+    PS_ASSERT_PTR_NON_NULL(target, false);
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_INT_POSITIVE(sources->n, false);
+
+    double time      = 0.0;             // Time of observation
+    psTimeType timeSys = 0;             // Time system
+    char *filter     = NULL;            // Filter
+
+    int num = 0;                        // Number of FPAs
+    psListIterator *sourcesIter = psListIteratorAlloc(sources, PS_LIST_HEAD, false); // Iterator for sources
+    pmFPA *fpa = NULL;                  // Source FPA from iteration
+    while ((fpa = psListGetAndIncrement(sourcesIter))) {
+        if (!fpa) {
+            continue;
+        }
+
+        num++;
+
+        psTime *fpaTime = psMetadataLookupPtr(NULL, fpa->concepts, "FPA.TIME");
+        time       += psTimeToMJD(fpaTime);
+        if (num == 1) {
+            timeSys = psMetadataLookupS32(NULL, fpa->concepts, "FPA.TIMESYS");
+            filter = psMetadataLookupStr(NULL, fpa->concepts, "FPA.FILTER");
+        } else {
+            if (timeSys != psMetadataLookupS32(NULL, fpa->concepts, "FPA.TIMESYS")) {
+                psWarning("Differing FPA.TIMESYS in use: %d vs %d\n",
+                          timeSys, psMetadataLookupS32(NULL, fpa->concepts, "FPA.TIMESYS"));
+            }
+            if (strcmp(filter, psMetadataLookupStr(NULL, fpa->concepts, "FPA.FILTER")) != 0) {
+                psWarning("Differing FPA.FILTER in use: %s vs %s\n",
+                          filter, psMetadataLookupStr(NULL, fpa->concepts, "FPA.FILTER"));
+            }
+        }
+    }
+    psFree(sourcesIter);
+
+    time      /= (double)num;
+
+    MD_UPDATE(target->concepts, "FPA.TIMESYS", S32, timeSys);
+    MD_UPDATE_STR(target->concepts, "FPA.FILTER", filter);
+
+    // FPA.TIME needs special care
+    {
+        psMetadataItem *timeItem = psMetadataLookup(target->concepts, "FPA.TIME");
+        psFree(timeItem->data.V);
+        timeItem->data.V = psTimeFromMJD(time);
+    }
+
+    return true;
+}
+
+
+// Set a variety of concepts in a cell by averaging over several
+// XXX does not properly set XSIZE, YSIZE
+bool pmConceptsAverageCells(pmCell *target, psList *sources, psRegion *trimsec, psRegion *biassec, bool same)
+{
+    PS_ASSERT_PTR_NON_NULL(target, false);
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_INT_POSITIVE(sources->n, false);
+
+    float gain       = 0.0;             // Gain
+    float readnoise  = 0.0;             // Read noise
+    float saturation = INFINITY;        // Saturation level
+    float bad        = -INFINITY;       // Bad level
+    float exposure   = 0.0;             // Exposure time
+    float darktime   = 0.0;             // Dark time
+    double time      = 0.0;             // Time of observation
+    psTimeType timeSys = 0;             // Time system
+    int readdir      = 0;               // Cell read direction
+    int xBin = 0, yBin = 0;             // Binning
+    int x0 = 0, y0 = 0;                 // Offset
+    int xParity = 0, yParity = 0;       // Parity
+
+    int nCells = 0;                     // Number of cells;
+    psListIterator *sourcesIter = psListIteratorAlloc(sources, PS_LIST_HEAD, false); // Iterator for sources
+    pmCell *cell = NULL;                // Source cell from iteration
+    while ((cell = psListGetAndIncrement(sourcesIter))) {
+        if (!cell) {
+            continue;
+        }
+
+        nCells++;
+        gain       += psMetadataLookupF32(NULL, cell->concepts, "CELL.GAIN");
+        readnoise  += psMetadataLookupF32(NULL, cell->concepts, "CELL.READNOISE");
+        exposure   += psMetadataLookupF32(NULL, cell->concepts, "CELL.EXPOSURE");
+        darktime   += psMetadataLookupF32(NULL, cell->concepts, "CELL.DARKTIME");
+        psTime *cellTime = psMetadataLookupPtr(NULL, cell->concepts, "CELL.TIME");
+        time       += psTimeToMJD(cellTime);
+        if (nCells == 1) {
+            timeSys = psMetadataLookupS32(NULL, cell->concepts, "CELL.TIMESYS");
+            readdir = psMetadataLookupS32(NULL, cell->concepts, "CELL.READDIR");
+            xBin    = psMetadataLookupS32(NULL, cell->concepts, "CELL.XBIN");
+            yBin    = psMetadataLookupS32(NULL, cell->concepts, "CELL.YBIN");
+
+            if (same) {
+                // Only makes sense to update these if they are the same cell
+                x0 = psMetadataLookupS32(NULL, cell->concepts, "CELL.X0");
+                y0 = psMetadataLookupS32(NULL, cell->concepts, "CELL.Y0");
+                xParity = psMetadataLookupS32(NULL, cell->concepts, "CELL.XPARITY");
+                yParity = psMetadataLookupS32(NULL, cell->concepts, "CELL.YPARITY");
+            }
+        } else {
+            if (timeSys != psMetadataLookupS32(NULL, cell->concepts, "CELL.TIMESYS")) {
+                psWarning("Differing CELL.TIMESYS in use: %d vs %d\n",
+                          timeSys, psMetadataLookupS32(NULL, cell->concepts, "CELL.TIMESYS"));
+            }
+            if (readdir != psMetadataLookupS32(NULL, cell->concepts, "CELL.READDIR")) {
+                psWarning("Differing CELL.READDIR in use: %d vs %d\n",
+                          readdir, psMetadataLookupS32(NULL, cell->concepts, "CELL.READDIR"));
+            }
+            if (xBin != psMetadataLookupS32(NULL, cell->concepts, "CELL.XBIN")) {
+                psWarning("Differing CELL.XBIN in use: %d vs %d\n",
+                          xBin, psMetadataLookupS32(NULL, cell->concepts, "CELL.XBIN"));
+            }
+            if (yBin != psMetadataLookupS32(NULL, cell->concepts, "CELL.YBIN")) {
+                psWarning("Differing CELL.YBIN in use: %d vs %d\n",
+                          yBin, psMetadataLookupS32(NULL, cell->concepts, "CELL.YBIN"));
+            }
+            if (same) {
+                if (x0 != psMetadataLookupS32(NULL, cell->concepts, "CELL.X0")) {
+                    psWarning("Differing CELL.X0 in use: %d vs %d\n",
+                              x0, psMetadataLookupS32(NULL, cell->concepts, "CELL.X0"));
+                }
+                if (y0 != psMetadataLookupS32(NULL, cell->concepts, "CELL.Y0")) {
+                    psWarning("Differing CELL.Y0 in use: %d vs %d\n",
+                              y0, psMetadataLookupS32(NULL, cell->concepts, "CELL.Y0"));
+                }
+                if (xParity != psMetadataLookupS32(NULL, cell->concepts, "CELL.XPARITY")) {
+                    psWarning("Differing CELL.XPARITY in use: %d vs %d\n",
+                              xParity, psMetadataLookupS32(NULL, cell->concepts, "CELL.XPARITY"));
+                }
+                if (yParity != psMetadataLookupS32(NULL, cell->concepts, "CELL.YPARITY")) {
+                    psWarning("Differing CELL.YPARITY in use: %d vs %d\n",
+                              yParity, psMetadataLookupS32(NULL, cell->concepts, "CELL.YPARITY"));
+                }
+            }
+        }
+
+        float cellSaturation = psMetadataLookupF32(NULL, cell->concepts, "CELL.SATURATION");
+        if (cellSaturation < saturation) {
+            saturation = cellSaturation;
+        }
+        float cellBad = psMetadataLookupF32(NULL, cell->concepts, "CELL.BAD");
+        if (cellBad > bad) {
+            bad = cellBad;
+        }
+    }
+    psFree(sourcesIter);
+
+    gain      /= (float)nCells;
+    readnoise /= (float)nCells;
+    exposure  /= (float)nCells;
+    darktime  /= (float)nCells;
+    time      /= (double)nCells;
+
+    MD_UPDATE(target->concepts, "CELL.GAIN", F32, gain);
+    MD_UPDATE(target->concepts, "CELL.READNOISE", F32, readnoise);
+    MD_UPDATE(target->concepts, "CELL.SATURATION", F32, saturation);
+    MD_UPDATE(target->concepts, "CELL.BAD", F32, bad);
+    MD_UPDATE(target->concepts, "CELL.EXPOSURE", F32, exposure);
+    MD_UPDATE(target->concepts, "CELL.DARKTIME", F32, darktime);
+    MD_UPDATE(target->concepts, "CELL.TIMESYS", S32, timeSys);
+    MD_UPDATE(target->concepts, "CELL.READDIR", S32, readdir);
+    MD_UPDATE(target->concepts, "CELL.XBIN", S32, xBin);
+    MD_UPDATE(target->concepts, "CELL.YBIN", S32, yBin);
+    if (same) {
+        MD_UPDATE(target->concepts, "CELL.X0", S32, x0);
+        MD_UPDATE(target->concepts, "CELL.Y0", S32, y0);
+        MD_UPDATE(target->concepts, "CELL.XPARITY", S32, xParity);
+        MD_UPDATE(target->concepts, "CELL.YPARITY", S32, yParity);
+    }
+
+    // CELL.TIME needs special care
+    {
+        psMetadataItem *timeItem = psMetadataLookup(target->concepts, "CELL.TIME");
+        psFree(timeItem->data.V);
+        timeItem->data.V = psTimeFromMJD(time);
+    }
+
+    // CELL.TRIMSEC needs special care
+    if (trimsec) {
+        psMetadataItem *trimsecItem = psMetadataLookup(target->concepts, "CELL.TRIMSEC");
+        psFree(trimsecItem->data.V);
+        trimsecItem->data.V = psMemIncrRefCounter(trimsec);
+    }
+
+    // CELL.BIASSEC needs special care
+    if (biassec) {
+        psMetadataItem *biassecItem = psMetadataLookup(target->concepts, "CELL.BIASSEC");
+        psFree(biassecItem->data.V);
+        biassecItem->data.V = psMemIncrRefCounter(biassec);
+    }
+
+    return true;
+}
+
+bool pmConceptsAverageChips(pmChip *target, psList *sources, bool same)
+{
+    PS_ASSERT_PTR_NON_NULL(target, false);
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_INT_POSITIVE(sources->n, false);
+
+    float temp = 0.0;                   // Temperature
+    int x0 = 0, y0 = 0;                 // Offset
+    int xParity = 0, yParity = 0;       // Parity
+    int xSize = 0, ySize = 0;           // Size
+    psString id = NULL;                 // Identifier
+
+    int nChips = 0;                     // Number of chips;
+    psListIterator *sourcesIter = psListIteratorAlloc(sources, PS_LIST_HEAD, false); // Iterator for sources
+    pmChip *chip = NULL;                // Source chip from iteration
+    while ((chip = psListGetAndIncrement(sourcesIter))) {
+        if (!chip) {
+            continue;
+        }
+        temp += psMetadataLookupF32(NULL, chip->concepts, "CHIP.TEMP");
+        if (nChips == 0) {
+            xSize = psMetadataLookupS32(NULL, chip->concepts, "CHIP.XSIZE");
+            ySize = psMetadataLookupS32(NULL, chip->concepts, "CHIP.YSIZE");
+            xParity = psMetadataLookupS32(NULL, chip->concepts, "CHIP.XPARITY");
+            yParity = psMetadataLookupS32(NULL, chip->concepts, "CHIP.YPARITY");
+            x0 = psMetadataLookupS32(NULL, chip->concepts, "CHIP.X0");
+            y0 = psMetadataLookupS32(NULL, chip->concepts, "CHIP.Y0");
+            id = psMetadataLookupStr(NULL, chip->concepts, "CHIP.ID");
+        } else {
+            if (xSize != psMetadataLookupS32(NULL, chip->concepts, "CHIP.XSIZE")) {
+                psWarning("Differing CHIP.XSIZE in use: %d vs %d\n",
+                    xSize, psMetadataLookupS32(NULL, chip->concepts, "CHIP.XSIZE"));
+            }
+            if (ySize != psMetadataLookupS32(NULL, chip->concepts, "CHIP.YSIZE")) {
+                psWarning("Differing CHIP.YSIZE in use: %d vs %d\n",
+                    ySize, psMetadataLookupS32(NULL, chip->concepts, "CHIP.YSIZE"));
+            }
+            if (xParity != psMetadataLookupS32(NULL, chip->concepts, "CHIP.XPARITY")) {
+                psWarning("Differing CHIP.XPARITY in use: %d vs %d\n",
+                    xParity, psMetadataLookupS32(NULL, chip->concepts, "CHIP.XPARITY"));
+            }
+            if (yParity != psMetadataLookupS32(NULL, chip->concepts, "CHIP.YPARITY")) {
+                psWarning("Differing CHIP.YPARITY in use: %d vs %d\n",
+                    yParity, psMetadataLookupS32(NULL, chip->concepts, "CHIP.YPARITY"));
+            }
+            if (x0 != psMetadataLookupS32(NULL, chip->concepts, "CHIP.X0")) {
+                psWarning("Differing CHIP.X0 in use: %d vs %d\n",
+                    x0, psMetadataLookupS32(NULL, chip->concepts, "CHIP.X0"));
+            }
+            if (y0 != psMetadataLookupS32(NULL, chip->concepts, "CHIP.Y0")) {
+                psWarning("Differing CHIP.Y0 in use: %d vs %d\n",
+                    y0, psMetadataLookupS32(NULL, chip->concepts, "CHIP.Y0"));
+            }
+            psString newID = psMetadataLookupStr(NULL, chip->concepts, "CHIP.ID");
+            if (id && newID && strcmp(id, newID)) {
+                psWarning("Differing CHIP.ID in use: %s vs %s\n", id, newID);
+            }
+        }
+
+        nChips++;
+    }
+    psFree(sourcesIter);
+
+    temp /= (float)nChips;
+
+    MD_UPDATE(target->concepts, "CHIP.TEMP", F32, temp);
+    if (same) {
+        MD_UPDATE(target->concepts, "CHIP.X0", S32, x0);
+        MD_UPDATE(target->concepts, "CHIP.Y0", S32, y0);
+        MD_UPDATE(target->concepts, "CHIP.XSIZE", S32, xSize);
+        MD_UPDATE(target->concepts, "CHIP.YSIZE", S32, ySize);
+        MD_UPDATE(target->concepts, "CHIP.XPARITY", S32, xParity);
+        MD_UPDATE(target->concepts, "CHIP.YPARITY", S32, yParity);
+        MD_UPDATE_STR(target->concepts, "CHIP.ID", id);
+    }
+
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsAverage.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsAverage.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsAverage.h	(revision 22158)
@@ -0,0 +1,65 @@
+/* @file pmConceptsAverage.h
+ * @brief Average the values of multiple concepts
+ *
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-04-10 06:31:42 $
+ * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_CONCEPTS_AVERAGE_H
+#define PM_CONCEPTS_AVERAGE_H
+
+/// @addtogroup Concepts Data Abstraction Concepts
+/// @{
+
+/// Set a variety of concepts in an FPA by averaging over several
+///
+/// This function averages the values of the following concepts:
+/// FPA.TIME
+/// And ensure the following concepts are consistent:
+/// FPA.FILTER
+/// FPA.TIMESYS
+/// The following concepts could be of interest to the user, but are not treated:
+/// FPA.EXPOSURE
+bool pmConceptsAverageFPAs(pmFPA *target,///< Target FPA
+                           psList *sources ///< List of source FPAs
+    );
+
+/// Set a variety of concepts in a cell by averaging over several
+///
+/// In some instances, we want to combine the values of a concept for several cells into a single concept for
+/// a single cell (e.g., when mosaicking multiple cells into a chip with one "cell").  This function averages
+/// the values of various concepts:
+/// - CELL.GAIN
+/// - CELL.READNOISE
+/// - CELL.EXPOSURE
+/// - CELL.DARKTIME
+/// - CELL.TIME
+/// For other concepts, it ensures the values are consistent:
+/// - CELL.READDIR
+/// - CELL.TIMESYS
+/// - CELL.X0, CELL.Y0
+/// - CELL.XPARITY, CELL.YPARITY
+/// And for others, it takes the "worst" possible value:
+/// - CELL.SATURATION
+/// - CELL.BAD
+/// These concepts are only handled if the cells are all the same cell (mosaicking vs stacking):
+/// - CELL.X0, CELL.Y0
+/// - CELL.XPARITY, CELL.YPARITY
+bool pmConceptsAverageCells(pmCell *target,///< Target cell
+                            psList *sources, ///< List of source cells
+                            psRegion *trimsec, ///< The new trim section
+                            psRegion *biassec, ///< The new bias section
+                            bool same   ///< Are the cells the same cell from different chips?
+                           );
+
+/// Set a variety of concepts in a chip by averaging over several 
+bool pmConceptsAverageChips(pmChip *target,///< Target chip
+                            psList *sources, ///< List of source chips
+                            bool same   ///< Are the chips the same chip from different exposures?
+                           );
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsPhotcode.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsPhotcode.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsPhotcode.c	(revision 22158)
@@ -0,0 +1,49 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+#include "pmConceptsPhotcode.h"
+
+psString pmConceptsPhotcodeForView(pmConfig *config, pmFPAfile *file, const pmFPAview *view)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_PTR_NON_NULL(file, NULL);
+    PS_ASSERT_PTR_NON_NULL(view, NULL);
+
+    if (view->chip < -1) {
+        psError(PS_ERR_IO, true, "Photcodes undefined for FPA: defined by chip\n");
+        return NULL;
+    }
+
+    // select recipe options supplied on command line
+    bool mdok;                          // Status of MD lookup
+    psMetadata *recipe  = psMetadataLookupPtr(&mdok, config->recipes, "PPIMAGE");
+    if (!mdok || !recipe) {
+        psError(PS_ERR_IO, true, "Recipe PPIMAGE not found\n");
+        return NULL;
+    }
+
+    // select photcode rule from recipe
+    char *rule = psMetadataLookupStr(&mdok, recipe, "PHOTCODE.RULE");
+    if (!mdok || !rule || strlen(rule) == 0) {
+        psError(PS_ERR_IO, true, "PHOTCODE.RULE not found in PPIMAGE recipe\n");
+        return NULL;
+    }
+
+    // convert rule to real photcode
+    psString photcode = pmFPAfileNameFromRule(rule, file, view);
+
+    return photcode;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsPhotcode.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsPhotcode.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsPhotcode.h	(revision 22158)
@@ -0,0 +1,25 @@
+/* @file  pmConceptsPhotcode.h
+ * @brief Generate a photcode from the concepts
+ *
+ * @author Eugene Magnier, IfA
+ *
+ * @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-05-17 21:35:51 $
+ * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_CONCEPTS_PHOTCODE_H
+#define PM_CONCEPTS_PHOTCODE_H
+
+/// @addtogroup Concepts Data Abstraction Concepts
+/// @{
+
+/// Return the photcode based on the PHOTCODE.RULE in the PHASE2 recipe
+///
+/// A photometry code ("photcode") is a string that represents the combination of filter and detector (chip).
+/// This functions generates a photcode for a particular chip within the FPA, based on the PHOTCODE.RULE in
+/// the PHASE2 recipe.  Interpolation using the usual syntax (e.g., "{CHIP.NAME}") is permitted.
+psString pmConceptsPhotcodeForView(pmConfig *config, pmFPAfile *file, const pmFPAview *view);
+
+/// @}
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsRead.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsRead.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsRead.c	(revision 22158)
@@ -0,0 +1,459 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <strings.h>            /* for strn?casecmp */
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmHDUUtils.h"
+#include "pmConcepts.h"
+#include "pmConceptsRead.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// File-static functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// This function gets called for the really boring concepts --- where all you have to do is parse from a
+// header or database and you don't need to muck around with conversions.  There is no similar "formatPlain",
+// since the type is already known.
+static psMetadataItem *parsePlain(psMetadataItem *concept, // The concept to parse
+                                  const psMetadataItem *pattern // The concept pattern
+                                 )
+{
+    assert(concept);
+    assert(pattern);
+
+    switch (pattern->type) {
+    case PS_DATA_STRING: {
+            psString string = psMetadataItemParseString(concept); // Get the string, so I can free it after it
+            // goes on the MetadataItem
+            psMetadataItem *item = psMetadataItemAllocStr(pattern->name, pattern->comment, string);
+            psFree(string);
+            return item;
+        }
+    case PS_DATA_S32:
+        return psMetadataItemAllocS32(pattern->name, pattern->comment, psMetadataItemParseS32(concept));
+    case PS_DATA_F32:
+        return psMetadataItemAllocF32(pattern->name, pattern->comment, psMetadataItemParseF32(concept));
+    case PS_DATA_F64:
+        return psMetadataItemAllocF64(pattern->name, pattern->comment, psMetadataItemParseF64(concept));
+    default:
+        psWarning("Concept %s (%s) is not of a standard type (%x)\n",
+                 pattern->name, pattern->comment, pattern->type);
+        return NULL;
+    }
+}
+
+// Parse a single concept
+static bool conceptParse(pmConceptSpec *spec, // The concept specification
+                         psMetadataItem *concept, // The concept to parse
+                         pmConceptSource source, // The concept source
+                         psMetadata *cameraFormat, // The camera format
+                         psMetadata *target, // The target
+                         const pmFPA *fpa, // The FPA
+                         const pmChip *chip, // The chip
+                         const pmCell *cell // The cell
+                        )
+{
+    assert(spec);
+    assert(cameraFormat);
+    assert(target);
+
+    if (!concept) {
+        psError(PS_ERR_UNKNOWN, true, "Concept is NULL");
+        return false;
+    }
+
+    psMetadataItem *parsed = NULL;  // The parsed concept
+    if (spec->parse) {
+        parsed = spec->parse(concept, spec->blank, source, cameraFormat, fpa, chip, cell);
+    } else {
+        parsed = parsePlain(concept, spec->blank);
+    }
+    if (!parsed) {
+        if (spec->required) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s\n", spec->blank->name);
+            return false;
+        } else {
+            psWarning("Unable to parse concept %s, but concept not marked as required.\n", spec->blank->name);
+            psErrorClear();
+            return true; // XXX return?
+        }
+    }
+
+    psTrace ("psModules.concepts", 3, "parsing concept: %s\n", spec->blank->name);
+
+    // Plug the parsed concept into a new psMetadataItem, so each "concept" has its own version that can
+    // be altered without affecting the others.  Also, so that we maintain the template name and comment.
+    psMetadataItem *cleaned = NULL;     // Item that's been cleaned up --- correct name and comment
+    switch (spec->blank->type) {
+    case PS_DATA_STRING:
+        cleaned = psMetadataItemAllocStr(spec->blank->name, spec->blank->comment, parsed->data.V);
+        break;
+    case PS_DATA_S32:
+        cleaned = psMetadataItemAllocS32(spec->blank->name, spec->blank->comment, parsed->data.S32);
+        break;
+    case PS_DATA_F32:
+        cleaned = psMetadataItemAllocF32(spec->blank->name, spec->blank->comment, parsed->data.F32);
+        break;
+    case PS_DATA_F64:
+        cleaned = psMetadataItemAllocF64(spec->blank->name, spec->blank->comment, parsed->data.F64);
+        break;
+    default:
+        cleaned = psMetadataItemAlloc(spec->blank->name, parsed->type, spec->blank->comment,
+                                      parsed->data.V);
+    }
+    psFree(parsed);
+    psMetadataAddItem(target, cleaned, PS_LIST_TAIL, PS_META_REPLACE);
+    psFree(cleaned);                 // Drop reference
+    return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool p_pmConceptsReadFromCells(psMetadata *target, const psMetadata *specs, const pmCell *cell)
+{
+    PS_ASSERT_PTR_NON_NULL(specs, false);
+    PS_ASSERT_PTR_NON_NULL(target, false);
+    if (!cell) {
+        psError(PS_ERR_UNKNOWN, true, "cell is NULL");
+        return false;
+    }
+
+    pmHDU *hdu = pmHDUGetLowest(NULL, NULL, cell); // The HDU at the lowest level
+    if (!hdu) {
+        psError(PS_ERR_UNKNOWN, true, "Can't find HDU for cell");
+        return false;
+    }
+    psMetadata *cameraFormat = hdu->format; // The camera format
+    psMetadata *cellConfig = cell->config; // The camera configuration for this cell
+    psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *specItem = NULL;    // Item from the specs metadata
+    bool status = true;                 // Status of reading concepts
+    while ((specItem = psMetadataGetAndIncrement(specsIter))) {
+        pmConceptSpec *spec = specItem->data.V; // The specification
+        psString name = specItem->name; // The concept name
+        psMetadataItem *conceptItem = psMetadataLookup(cellConfig, name); // The concept, or NULL
+        psTrace("psModules.concepts", 10, "%s: %p\n", name, conceptItem);
+        if (conceptItem) {
+            if (conceptItem->type == PS_DATA_STRING) {
+                // Check the SOURCE
+                psString nameSource = NULL; // String with the concept name and ".SOURCE" added
+                psStringAppend(&nameSource, "%s.SOURCE", name);
+                bool mdok = true;       // Status of MD lookup
+                psString source = psMetadataLookupStr(&mdok, cell->config, nameSource); // The source
+                psFree(nameSource);
+                if (mdok && source && strlen(source) > 0 && strcasecmp(source, "VALUE") == 0) {
+                    if (!conceptParse(spec, conceptItem, PM_CONCEPT_SOURCE_CELLS,
+                                      cameraFormat, target, NULL, NULL, cell)) {
+                        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s from camera "
+                                "configuration\n", name);
+                        status = false;
+                    }
+                } else if (source && (strlen(source) == 0 || strcasecmp(source, "HEADER") != 0)) {
+                    // We leave "HEADER" to pmConceptsReadFromHeader
+                    psError(PS_ERR_IO, true, "%s isn't HEADER or VALUE --- can't read %s\n", source,
+                            name);
+                    continue;
+                }
+            } else {
+                // Another type --- should be OK
+                if (!conceptParse(spec, conceptItem, PM_CONCEPT_SOURCE_CELLS,
+                                  cameraFormat, target, NULL, NULL, cell)) {
+                    psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s from camera "
+                            "configuration.\n", name);
+                    status = false;
+                }
+            }
+        }
+    }
+    psFree(specsIter);
+    return status;
+}
+
+psMetadataItem *p_pmConceptsReadSingleFromDefaults(const char *name, const psMetadata *defaults,
+                                                  const pmFPA *fpa, const pmChip *chip, const pmCell *cell)
+{
+    PS_ASSERT_STRING_NON_EMPTY(name, NULL);
+    PS_ASSERT_METADATA_NON_NULL(defaults, NULL);
+
+    psMetadataItem *item = psMetadataLookup(defaults, name); // The concept, or NULL
+    psTrace("psModules.concepts", 10, "%s: %p\n", name, item);
+    if (item && item->type == PS_DATA_METADATA) {
+        // This is a menu
+        psTrace("psModules.concepts", 5, "%s is of type METADATA.\n", name);
+        item = p_pmConceptsDepend(name, item->data.md, defaults, fpa, chip, cell);
+    }
+    return item;
+}
+
+bool p_pmConceptsReadFromDefaults(psMetadata *target, const psMetadata *specs,
+                                  const pmFPA *fpa, const pmChip *chip, const pmCell *cell)
+{
+    PS_ASSERT_PTR_NON_NULL(specs, false);
+    PS_ASSERT_PTR_NON_NULL(target, false);
+
+    psTrace("psModules.concepts", 3, "Reading concepts from defaults...\n");
+
+    pmHDU *hdu = pmHDUGetLowest(fpa, chip, cell); // The HDU at the lowest level
+    if (!hdu) {
+        // We read the defaults for all the HDUs we could find
+        return true;
+    }
+    psMetadata *cameraFormat = hdu->format; // The camera format
+    bool mdok = true;                   // Status of MD lookup
+    psMetadata *defaults = psMetadataLookupMetadata(&mdok, cameraFormat, "DEFAULTS"); // The DEFAULTS spec
+    if (!mdok || !defaults) {
+        psError(PS_ERR_IO, true, "Failed to find \"DEFAULTS\"");
+        return false;
+    }
+    psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *specItem = NULL;    // Item from the specs metadata
+    bool status = true;                 // Status of reading concepts
+    psErrorClear();   // we're going to declare all errors "old" => won't clear stack
+    while ((specItem = psMetadataGetAndIncrement(specsIter))) {
+        pmConceptSpec *spec = specItem->data.V; // The specification
+        psString name = specItem->name; // The concept name
+        psMetadataItem *conceptItem = p_pmConceptsReadSingleFromDefaults(name, defaults, fpa, chip, cell);
+        if (conceptItem && !conceptParse(spec, conceptItem, PM_CONCEPT_SOURCE_DEFAULTS,
+                                         cameraFormat, target, fpa, chip, cell)) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s from DEFAULTS.\n", name);
+            status = false;
+        }
+    }
+    psFree(specsIter);
+    return status;
+}
+
+
+bool p_pmConceptsReadFromHeader(psMetadata *target, const psMetadata *specs,
+                                const pmFPA *fpa, const pmChip *chip, const pmCell *cell)
+{
+    PS_ASSERT_PTR_NON_NULL(specs, false);
+    PS_ASSERT_PTR_NON_NULL(target, false);
+
+    pmHDU *hduLow = pmHDUGetLowest(fpa, chip, cell); // The HDU at the lowest level
+    if (!hduLow) {
+        // We read the defaults for all the HDUs we could find
+        return true;
+    }
+    pmHDU *hduHigh = pmHDUGetHighest(fpa, chip, cell); // The HDU at the highest level
+    if (!hduHigh) {
+        psError(PS_ERR_UNKNOWN, true, "Can't find HDU at the highest level");
+        return false;
+    }
+    assert(hduLow->format == hduHigh->format); // Just in case....
+    psMetadata *cameraFormat = hduLow->format; // The camera format
+    bool mdok = true;                   // Status of MD lookup
+    psMetadata *transSpec = psMetadataLookupMetadata(&mdok, cameraFormat, "TRANSLATION"); // TRANSLATION spec
+    if (!mdok || !transSpec) {
+        psError(PS_ERR_IO, true, "Failed to find \"TRANSLATION\"");
+        return false;
+    }
+
+    psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *specItem = NULL;    // Item from the specs metadata
+    bool status = true;                 // Status of reading concepts
+    while ((specItem = psMetadataGetAndIncrement(specsIter))) {
+        pmConceptSpec *spec = specItem->data.V; // The specification
+        psString name = specItem->name; // The concept name
+        psMetadataItem *headerItem = NULL; // The value of the concept from the header
+
+        // First check the cell configuration
+        if (cell && cell->config) {
+            psMetadataItem *conceptItem = psMetadataLookup(cell->config, name); // The concept, or NULL
+            if (conceptItem) {
+                // Check the SOURCE
+                psString nameSource = NULL; // String with the concept name and ".SOURCE" added
+                psStringAppend(&nameSource, "%s.SOURCE", name);
+                psString source = psMetadataLookupStr(&mdok, cell->config, nameSource); // The source
+                psFree(nameSource);
+                if (mdok && strlen(source) && strcasecmp(source, "HEADER") == 0) {
+                    if (hduLow->header) {
+                        headerItem = psMetadataLookup(hduLow->header, conceptItem->data.V);
+                    }
+                    if (!headerItem && hduHigh != hduLow && hduHigh->header) {
+                        headerItem = psMetadataLookup(hduHigh->header, conceptItem->data.V);
+                    }
+                    psMemIncrRefCounter(headerItem);
+                }
+                // Leave the error handling to pmConceptsFromCamera, which should already have been called
+            }
+        }
+
+        if (!headerItem) {
+            psMetadataItem *formatItem = psMetadataLookup(transSpec, name); // Item with keyword
+            if (!formatItem) {
+                continue;
+            }
+            if (formatItem->type == PS_DATA_METADATA) {
+                // This is a menu
+                psTrace("psModules.concepts", 5, "%s is of type METADATA.\n", name);
+                formatItem = p_pmConceptsDepend(name, formatItem->data.md, transSpec, fpa, chip, cell);
+                if (!formatItem) {
+                    continue;
+                }
+            }
+            if (formatItem->type != PS_DATA_STRING) {
+                psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Type for concept %s in TRANSLATION is not STR",
+                        name);
+                psFree(specsIter);
+                return false;
+            }
+            psString keywords = formatItem->data.str; // The FITS keywords
+
+            // In case there are multiple headers
+            psList *keys = psStringSplit(keywords, " ,;", true); // List of keywords
+            if (keys->n == 1) {
+                // Only one key --- proceed as usual
+                if (hduLow->header) {
+                    headerItem = psMetadataLookup(hduLow->header, keywords);
+                }
+                if (!headerItem && hduHigh != hduLow && hduHigh->header) {
+                    headerItem = psMetadataLookup(hduHigh->header, keywords);
+                }
+                psMemIncrRefCounter(headerItem);
+            } else {
+                psListIterator *keysIter = psListIteratorAlloc(keys, PS_LIST_HEAD, false); // Iterator
+                psString key = NULL; // Item from iteration
+                psList *values = psListAlloc(NULL); // List containing the values
+                while ((key = psListGetAndIncrement(keysIter))) {
+                    psMetadataItem *value = NULL;
+                    if (hduLow->header) {
+                        value = psMetadataLookup(hduLow->header, key);
+                    }
+                    if (!value && hduHigh != hduLow && hduHigh->header) {
+                        value = psMetadataLookup(hduHigh->header, key);
+                    }
+                    if (value) {
+                        psListAdd(values, PS_LIST_TAIL, value);
+                    } else {
+                        psWarning("Unable to find header %s --- assuming value is NULL", key);
+                    }
+                }
+                psFree(keysIter);
+                headerItem = psMetadataItemAlloc(name, PS_DATA_LIST, specItem->comment, values);
+                psFree(values);
+            }
+            psFree(keys);
+        }
+
+        // This will also clean up the name
+        if (headerItem) {
+            if (!conceptParse(spec, headerItem, PM_CONCEPT_SOURCE_HEADER,
+                              cameraFormat, target, fpa, chip, cell)) {
+                psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s from header.\n", name);
+                status = false;
+            }
+        }
+        psTrace("psModules.concepts", 10, "%s: %p\n", name, headerItem);
+        psFree(headerItem);
+    }
+    psFree(specsIter);
+    return status;
+}
+
+psMetadataItem *p_pmConceptsReadSingleFromDatabase(const char *name, const psMetadata *database,
+                                                   pmConfig *config, const pmFPA *fpa, const pmChip *chip,
+                                                   const pmCell *cell)
+{
+    PS_ASSERT_STRING_NON_EMPTY(name, NULL);
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    psMetadataItem *item = psMetadataLookup(database, name); // Item to return
+    if (item && item->type == PS_DATA_METADATA) {
+        // This is a menu
+        psTrace("psModules.concepts", 5, "%s is of type METADATA.\n", name);
+        item = p_pmConceptsDepend(name, item->data.md, database, fpa, chip, cell);
+    }
+    if (!item) {
+        return NULL;
+    }
+    if (item->type != PS_DATA_STRING) {
+        psWarning("%s in DATABASE in camera format is not of type STR --- ignored.", name);
+        return NULL;
+    }
+
+    psDB *db = pmConfigDB(config);      // Database handle
+    if (!db) {
+        psErrorClear();
+        psWarning("Unable to initialise database to write concepts.");
+        return NULL;
+    }
+
+    psString sql = pmConceptsInterpolate(item->data.str, fpa, chip, cell);
+    if (!p_psDBRunQuery(config->database, sql)) {
+        psWarning("Unable to query database for concept %s --- ignored.", name);
+        psFree(sql);
+        return NULL;
+    }
+    psFree(sql);
+
+    psArray *rows = p_psDBFetchResult(config->database); // Rows returned from the query
+    if (rows->n == 0) {
+        psWarning("No rows returned from database query for concept %s --- ignored.", name);
+        return NULL;
+    }
+    if (rows->n > 1) {
+        psWarning("Multiple rows returned from database query for concept %s --- using the first", name);
+    }
+    psMetadata *row = rows->data[0]; // First (and only) row
+    if (row->list->n > 1) {
+        psWarning("Multiple columns returned from database query for concept %s --- using the first", name);
+    }
+
+    return psMetadataGet(row, PS_LIST_HEAD); // Item of interest
+}
+
+bool p_pmConceptsReadFromDatabase(psMetadata *target, const psMetadata *specs,
+                                  const pmFPA *fpa, const pmChip *chip, const pmCell *cell, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(specs, false);
+    PS_ASSERT_PTR_NON_NULL(target, false);
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+#ifndef HAVE_PSDB
+    return true;
+#else
+    pmHDU *hdu = pmHDUGetLowest(fpa, chip, cell); // The HDU at the lowest level
+    if (!hdu) {
+        // We read the database for all the HDUs we could find
+        return true;
+    }
+    psMetadata *cameraFormat = hdu->format; // The camera format
+    bool mdok = true;                   // Status of MD lookup
+    psMetadata *dbSpec = psMetadataLookupMetadata(&mdok, cameraFormat, "DATABASE"); // The DATABASE spec
+    if (!mdok || !dbSpec) {
+        return true;
+    }
+
+    psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *specItem = NULL;    // Item from the specs metadata
+    bool status = true;                 // Status of reading concepts
+    while ((specItem = psMetadataGetAndIncrement(specsIter))) {
+        pmConceptSpec *spec = specItem->data.V; // The specification
+        psString name = specItem->name; // The concept name
+        psMetadataItem *conceptItem = p_pmConceptsReadSingleFromDatabase(name, dbSpec, config,
+                                                                         fpa, chip, cell);
+        if (conceptItem && !conceptParse(spec, conceptItem, PM_CONCEPT_SOURCE_DATABASE,
+                                         cameraFormat, target, fpa, chip, cell)) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s from database.\n", name);
+            status = false;
+        }
+    } // Iterating through the concept specifications
+    psFree(specsIter);
+
+    return status;
+#endif
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsRead.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsRead.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsRead.h	(revision 22158)
@@ -0,0 +1,82 @@
+/* @file  pmConceptsRead.h
+ * @brief Reading concepts from a variety of sources.
+ *
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-06-17 22:16:38 $
+ * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_CONCEPTS_READ_H
+#define PM_CONCEPTS_READ_H
+
+/// Read concepts from the camera format file's CELLS.
+///
+/// Examines the CELLS metadata in the camera format file
+/// for the current type of cell, and sucks in the concepts defined there.
+/// This is a useful way of defining concepts that vary depending on the
+/// type of the cell.
+bool p_pmConceptsReadFromCells(psMetadata *target, ///< Place into which to read the concepts
+                               const psMetadata *specs, ///< The concept specifications
+                               const pmCell *cell ///< The cell
+                              );
+
+/// Read a single concept from the DEFAULTS in the camera format
+///
+/// The returned item is NOT parsed, but any interpolation for DEPEND is done.
+psMetadataItem *p_pmConceptsReadSingleFromDefaults(
+    const char *name,                   ///< Name of concept
+    const psMetadata *defaults,         ///< DEFAULTS specifications
+    const pmFPA *fpa,                   ///< The FPA
+    const pmChip *chip,                 ///< The chip, or NULL
+    const pmCell *cell                  ///< The cell, or NULL
+    );
+
+/// Read concepts from the DEFAULTS in the camera format file.
+///
+/// Examines the DEFAULTS metadata in the camera format file
+/// for concepts in the specs, and imports them into the target.
+bool p_pmConceptsReadFromDefaults(psMetadata *target, // Place into which to read the concepts
+                                  const psMetadata *specs, // The concept specifications
+                                  const pmFPA *fpa, // The FPA
+                                  const pmChip *chip, // The chip
+                                  const pmCell *cell // The cell
+                                 );
+
+/// Read concepts from the header TRANSLATION in the camera format file.
+///
+/// Examines the TRANSLATION metadata in the camera format file
+/// for concepts in the specs, and imports them into the target.
+bool p_pmConceptsReadFromHeader(psMetadata *target, // Place into which to read the concepts
+                                const psMetadata *specs, // The concept specifications
+                                const pmFPA *fpa, // The FPA
+                                const pmChip *chip, // The chip
+                                const pmCell *cell  // The cell
+                               );
+
+/// Read a single concept from the DATABASE specification in the camera format
+///
+/// The returned item is NOT parsed, but any interpolation for DEPEND is done.
+psMetadataItem *p_pmConceptsReadSingleFromDatabase(
+    const char *name,                   ///< Name of concept
+    const psMetadata *database,         ///< DATABASE specification
+    pmConfig *config,                   ///< Configuration
+    const pmFPA *fpa,                   ///< The FPA
+    const pmChip *chip,                 ///< The chip, or NULL
+    const pmCell *cell                  ///< The cell, or NULL
+    );
+
+/// Read concepts from the header DATABASE in the camera format file.
+///
+/// Examines the DATABASE metadata in the camera format file
+/// for concepts in the specs, and imports them into the target.
+bool p_pmConceptsReadFromDatabase(psMetadata *target, // Place into which to read the concepts
+                                  const psMetadata *specs, // The concept specifications
+                                  const pmFPA *fpa, // The FPA
+                                  const pmChip *chip, // The chip
+                                  const pmCell *cell,  // The cell
+                                  pmConfig *config // Configuration
+                                 );
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsStandard.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsStandard.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsStandard.c	(revision 22158)
@@ -0,0 +1,1238 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>            /* for strn?casecmp */
+#include <assert.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmConcepts.h"
+#include "pmConceptsRead.h"
+#include "pmConceptsWrite.h"
+#include "pmConceptsStandard.h"
+
+// The functions in this file are intended to be called solely within the psModules concepts code.  For this
+// reason, they use "assert" instead of the PS_ASSERT_WHATEVER functions --- if there's a problem, then
+// there's a BIG problem that affects all of the code.
+
+#define COMPARE_REGIONS(a,b) (((a)->x0 == (b)->x0 && \
+                               (a)->x1 == (b)->x1 && \
+                               (a)->y0 == (b)->y0 && \
+                               (a)->y1 == (b)->y1) ? true : false)
+
+#define TYPE_CASE(assign, item, TYPE) \
+case PS_TYPE_##TYPE: \
+assign = item->data.TYPE; \
+break;
+
+
+
+static double defaultCoordScaling(const psMetadataItem *pattern)
+{
+    if (strcmp(pattern->name, "FPA.RA") == 0) {
+        psWarning("Assuming format for %s is HOURS.\n", pattern->name);
+        return M_PI / 12.0;
+    }
+    if (strcmp(pattern->name, "FPA.DEC") == 0) {
+        psWarning("Assuming format for %s is DEGREES.\n", pattern->name);
+        return M_PI / 180.0;
+    }
+    psAbort("Should never ever get here.\n");
+    return NAN;
+}
+
+// TELTEMPS : parse a list of the form 'X1 X2 X3 X4 X5 ...' : for now use median
+psMetadataItem *p_pmConceptParse_TELTEMPS(const psMetadataItem *concept,
+                                          const psMetadataItem *pattern,
+                                          pmConceptSource source,
+                                          const psMetadata *cameraFormat,
+                                          const pmFPA *fpa,
+                                          const pmChip *chip,
+                                          const pmCell *cell)
+{
+    assert(concept);
+    assert(pattern);
+
+    double value = NAN;
+    switch (concept->type) {
+      case PS_TYPE_F32:
+        value = concept->data.F32;
+        break;
+      case PS_TYPE_F64:
+        value = concept->data.F64;
+        break;
+      case PS_DATA_STRING: {
+          // parse the list of values into an array of substrings
+          psArray *strValues = psStringSplitArray (concept->data.V, " ,;", false);
+          assert (strValues);
+
+          // convert the substrings into a vector
+          psVector *fltValues = psVectorAlloc (strValues->n, PS_DATA_F32);
+          for (int i = 0; i < strValues->n; i++) {
+              fltValues->data.F32[i] = atof(strValues->data[i]);
+          }
+
+          // take the (for now) MEDIAN of the data
+          psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+
+          if (!psVectorStats (stats, fltValues, NULL, NULL, 0)) {
+              psAbort ("how can this stats function fail?");
+          }
+
+          value = stats->sampleMedian;
+          psFree (stats);
+          psFree (fltValues);
+          psFree (strValues);
+          break;
+      }
+
+      default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Invalid type for %s (%x)\n", pattern->name, concept->type);
+        return NULL;
+    }
+
+    psMetadataItem *item = psMetadataItemAllocF32(pattern->name, pattern->comment, value);
+    return (item);
+}
+
+// FPA.FILTER
+psMetadataItem *p_pmConceptParse_FPA_FILTER(const psMetadataItem *concept,
+                                            const psMetadataItem *pattern,
+                                            pmConceptSource source,
+                                            const psMetadata *cameraFormat,
+                                            const pmFPA *fpa,
+                                            const pmChip *chip,
+                                            const pmCell *cell)
+{
+    assert(concept);
+    assert(pattern);
+    assert(fpa);
+    assert(fpa->camera);
+
+    if (concept->type != PS_DATA_STRING) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Type for %s (%x) is not STR\n",
+                pattern->name, concept->type);
+        return NULL;
+    }
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *filters = psMetadataLookupMetadata(&mdok, fpa->camera, "FILTER.ID");
+    if (!mdok || !filters) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find FILTER.ID in camera configuration.\n");
+        return NULL;
+    }
+
+    // the metadata is in the format (internal) STR (external)
+    // do a reverse lookup to get the internal name
+    psMetadataIterator *iter = psMetadataIteratorAlloc(filters, PS_LIST_HEAD, NULL); // Iterator for filters
+    psMetadataItem *item;               // Item from iteration
+    char *name = NULL;                  // The winning name
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        if (item->type != PS_DATA_STRING) {
+            psWarning("Type for %s (%x) in FILTER.ID in camera configuration is not STR\n",
+                      item->name, item->type);
+            continue;
+        }
+        if (strcmp(item->data.str, concept->data.str) == 0) {
+            name = item->name;
+            break;
+        }
+    }
+    psFree(iter);
+    if (!name) {
+        psError(PS_ERR_UNEXPECTED_NULL, false,
+                "Unable to find any filter matching %s in FILTER.ID in camera configuration.\n",
+                concept->data.str);
+        return NULL;
+    }
+
+    return psMetadataItemAllocStr(pattern->name, pattern->comment, name);
+}
+
+psMetadataItem *p_pmConceptFormat_FPA_FILTER(const psMetadataItem *concept,
+                                             pmConceptSource source,
+                                             const psMetadata *cameraFormat,
+                                             const pmFPA *fpa,
+                                             const pmChip *chip,
+                                             const pmCell *cell)
+{
+    assert(concept);
+    assert(fpa);
+    assert(fpa->camera);
+
+    if (concept->type != PS_DATA_STRING) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Type for %s (%x) is not STR\n",
+                concept->name, concept->type);
+        return NULL;
+    }
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *filters = psMetadataLookupMetadata(&mdok, fpa->camera, "FILTER.ID");
+    if (!mdok || !filters) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find FILTER.ID in camera configuration.\n");
+        return NULL;
+    }
+
+    const char *key = concept->data.str;        // The name to look up
+    if (!key || strlen(key) == 0) {
+        return psMetadataItemAllocStr(concept->name, concept->comment, NULL);
+    }
+
+    // the metadata is in the format (internal) STR (external)
+    // find the first internal name that matches
+    psMetadataItem *item = psMetadataLookup (filters, key);
+    if (!item) {
+        psError(PS_ERR_UNEXPECTED_NULL, true,
+                "Unable to find %s in FILTER.ID in camera configuration.\n", key);
+        return NULL;
+    }
+
+    if (item->type == PS_DATA_STRING) {
+        return psMetadataItemAllocStr(concept->name, concept->comment, item->data.V);
+    }
+
+    if (item->type == PS_DATA_METADATA_MULTI) {
+        psMetadataItem *entry = psListGet (item->data.list, PS_LIST_HEAD);
+        if (!entry) {
+            psError(PS_ERR_UNEXPECTED_NULL, true,
+                    "List for %s in FILTER.ID in camera configuration is empty.\n", key);
+            return NULL;
+        }
+        return psMetadataItemAllocStr(concept->name, concept->comment, entry->data.V);
+    }
+
+    psError(PS_ERR_UNEXPECTED_NULL, true,
+            "Unable to find %s in FILTER.ID in camera configuration.\n", key);
+    return NULL;
+}
+
+// FPA.RA and FPA.DEC
+psMetadataItem *p_pmConceptParse_FPA_Coords(const psMetadataItem *concept,
+                                            const psMetadataItem *pattern,
+                                            pmConceptSource source,
+                                            const psMetadata *cameraFormat,
+                                            const pmFPA *fpa,
+                                            const pmChip *chip,
+                                            const pmCell *cell)
+{
+    assert(concept);
+    assert(pattern);
+    assert(cameraFormat);
+
+    double coords = NAN;                // The coordinates
+    switch (concept->type) {
+      case PS_TYPE_F32:
+        coords = concept->data.F32;
+        break;
+      case PS_TYPE_F64:
+        coords = concept->data.F64;
+        break;
+      case PS_DATA_STRING:
+        // Sexagesimal format
+        {
+            int big, medium;
+            float small;
+            // XXX: Upgrade path is to allow dd:mm.mmm
+            if (sscanf(concept->data.V, "%d:%d:%f", &big, &medium, &small) != 3 &&
+                sscanf(concept->data.V, "%d %d %f", &big, &medium, &small) != 3)
+            {
+                psError(PS_ERR_UNKNOWN, true, "Cannot interpret %s: %s\n", pattern->name, concept->data.str);
+                break;
+            }
+            coords = abs(big) + (float)medium/60.0 + small/3600.0;
+            if (big < 0)
+            {
+                coords *= -1.0;
+            }
+        }
+        break;
+      default:
+        psError(PS_ERR_UNKNOWN, true, "%s concept is of an unexpected type: %x\n",
+                pattern->name, concept->type);
+        return NULL;
+    }
+
+    // How to interpret the coordinates
+    bool mdok = true;           // Status of MD lookup
+    psMetadata *formats = psMetadataLookupMetadata(&mdok, cameraFormat, "FORMATS");
+    if (mdok && formats) {
+        psString format = psMetadataLookupStr(&mdok, formats, pattern->name);
+        if (mdok && strlen(format) > 0) {
+            if (strcasecmp(format, "HOURS") == 0) {
+                coords *= M_PI / 12.0;
+            } else if (strcasecmp(format, "DEGREES") == 0) {
+                coords *= M_PI / 180.0;
+            } else if (strcasecmp(format, "RADIANS") == 0) {
+                // No action required
+            } else {
+                coords *= defaultCoordScaling(pattern);
+            }
+        } else {
+            coords *= defaultCoordScaling(pattern);
+        }
+    } else {
+        coords *= defaultCoordScaling(pattern);
+    }
+
+    return psMetadataItemAllocF64(pattern->name, pattern->comment, coords);
+}
+
+// FPA.RA and FPA.DEC
+psMetadataItem *p_pmConceptFormat_FPA_Coords(const psMetadataItem *concept,
+                                             pmConceptSource source,
+                                             const psMetadata *cameraFormat,
+                                             const pmFPA *fpa,
+                                             const pmChip *chip,
+                                             const pmCell *cell)
+{
+    assert(concept);
+    assert(cameraFormat);
+
+    double coords = concept->data.F64;  // The coordinates
+
+    if (!isfinite(coords)) {
+        return psMetadataItemAllocF32(concept->name, concept->comment, NAN);
+    }
+
+    // How to interpret the coordinates
+    bool mdok = true;                   // Status of MD lookup
+    psMetadata *formats = psMetadataLookupMetadata(&mdok,
+                                                   cameraFormat,
+                                                   "FORMATS");
+    if (mdok && formats) {
+        psString format = psMetadataLookupStr(&mdok,formats, concept->name);
+        if (mdok && strlen(format) > 0) {
+            if (strcasecmp(format, "HOURS") == 0) {
+                coords /= M_PI / 12.0;
+            } else if (strcasecmp(format, "DEGREES") == 0) {
+                coords /= M_PI / 180.0;
+            } else if (strcasecmp(format, "RADIANS") == 0) {
+                // No action required
+            } else {
+                coords /= defaultCoordScaling(concept);
+            }
+        } else {
+            coords /= defaultCoordScaling(concept);
+        }
+    } else {
+        coords /= defaultCoordScaling(concept);
+    }
+
+    // We choose to write sexagesimal format
+    int big, medium;                    // Degrees and minutes
+    float small;                        // Seconds
+    bool negative = (coords < 0);       // Are we working below zero?
+    coords = fabs(coords);
+    big = (int)abs(coords);
+    coords -= big;
+    medium = 60.0 * coords;
+    coords -= medium / 60.0;
+    small = 3600.0 * coords;
+    small = (float)((int)(small * 100.0)) / 100.0;
+    if (negative) {
+        big *= -1;
+    }
+    psString coordString = NULL;        // String with the coordinates in sexagesimal format
+    psStringAppend(&coordString, "%d:%02d:%05.2f", big, medium, small);
+    psMetadataItem *coordItem = psMetadataItemAllocStr(concept->name, concept->comment, coordString);
+    psFree(coordString);
+
+    return coordItem;
+}
+
+
+psMetadataItem *p_pmConceptParse_CELL_TRIMSEC(const psMetadataItem *concept,
+                                              const psMetadataItem *pattern,
+                                              pmConceptSource source,
+                                              const psMetadata *cameraFormat,
+                                              const pmFPA *fpa,
+                                              const pmChip *chip,
+                                              const pmCell *cell)
+{
+    assert(concept);
+    assert(cell);
+    assert(pattern);
+
+    int xParity = 0;
+    int yParity = 0;
+    psRegion *trimsec = psRegionAlloc(0, 0, 0, 0);
+
+    if (concept->type != PS_DATA_STRING) {
+        psError(PS_ERR_UNKNOWN, true, "CELL.TRIMSEC after read is not of type STR (%x)\n", concept->type);
+        psFree(trimsec);
+        return NULL;
+    } else {
+        // allow for x and y flips in regions
+        *trimsec = psRegionAndParityFromString(&xParity, &yParity, concept->data.V);
+    }
+
+    // Need to correct for binning when CELL.TRIMSEC are specified immutably in the CELLS
+    if (source == PM_CONCEPT_SOURCE_CELLS) {
+        psMetadataAddBool(cell->concepts, PS_LIST_TAIL, "CELL.TRIMSEC.UPDATE", PS_META_REPLACE,
+                          "Need to update CELL.TRIMSEC when the binning is available.",
+                          true);
+    }
+
+    psMetadataItem *item = psMetadataItemAllocPtr(pattern->name, PS_DATA_REGION, pattern->comment, trimsec);
+    psFree(trimsec);
+    return item;
+}
+
+
+psList *p_pmConceptParseRegions(const char *region)
+{
+    psList *list = psListAlloc(NULL);   // List of regions
+    if (!region || strlen(region) == 0) {
+        // Empty list
+        return list;
+    }
+
+    // a single BIASSEC is of the form [AAAA]
+    // we may have multiple BIASSEC entries separated by space, commas, or semicolons
+    int xParity = 0, yParity = 0;       // Parity of region
+    char *p = strchr (region, '[');
+    while (p) {
+        char *q = strchr (p, ']');
+        if (!q) {
+            break;
+        }
+        char *regionString = psStringAlloc(q - p + 2);
+        strncpy (regionString, p, q - p + 1);
+        regionString[q - p + 1] = 0;
+
+        psRegion *region = psAlloc(sizeof(psRegion)); // The region
+        *region = psRegionAndParityFromString(&xParity, &yParity, regionString);
+        psListAdd(list, PS_LIST_TAIL, region);
+        psFree(region);           // Drop reference
+        psFree(regionString);     // Drop reference
+
+        p = strchr (q, '[');
+    }
+
+    return list;
+}
+
+psMetadataItem *p_pmConceptParse_CELL_BIASSEC(const psMetadataItem *concept,
+                                              const psMetadataItem *pattern,
+                                              pmConceptSource source,
+                                              const psMetadata *cameraFormat,
+                                              const pmFPA *fpa,
+                                              const pmChip *chip,
+                                              const pmCell *cell)
+{
+    assert(concept);
+    assert(cell);
+    assert(pattern);
+
+    psList *biassecs = NULL; // List of bias sections
+
+    switch (concept->type) {
+      case PS_DATA_STRING: {
+          biassecs = p_pmConceptParseRegions(concept->data.V);
+          break;
+      }
+      case PS_DATA_LIST: {
+          biassecs = psListAlloc(NULL);
+          psList *regions = concept->data.V; // The list of regions
+          psListIterator *regionsIter = psListIteratorAlloc(regions, PS_LIST_HEAD, false); // Iterator
+          psMetadataItem *regionItem = NULL; // Item from list iteration
+          while ((regionItem = psListGetAndIncrement(regionsIter))) {
+              if (regionItem->type != PS_DATA_STRING) {
+                  psWarning("CELL.BIASSEC member is not of type STR --- ignored.\n");
+                  continue;
+              }
+              int xParity = 0;
+              int yParity = 0;
+              psRegion *region = psAlloc(sizeof(psRegion)); // The region
+              *region = psRegionAndParityFromString(&xParity, &yParity, regionItem->data.V);
+              psListAdd(biassecs, PS_LIST_TAIL, region);
+              psFree(region);           // Drop reference
+          }
+          psFree(regionsIter);
+          break;
+      }
+      default:
+        psError(PS_ERR_UNKNOWN, true, "CELL.BIASSEC after read is not of type STRING or LIST --- assuming "
+                "blank.\n");
+    }
+
+    // Need to correct for binning when CELL.BIASSEC are specified immutably in the CELLS
+    if (source == PM_CONCEPT_SOURCE_CELLS) {
+        psMetadataAddBool(cell->concepts, PS_LIST_TAIL, "CELL.BIASSEC.UPDATE", 0,
+                          "Need to update CELL.BIASSEC when the binning is available.",
+                          true);
+    }
+
+    psMetadataItem *item = psMetadataItemAllocPtr(pattern->name, PS_DATA_LIST, pattern->comment, biassecs);
+    psFree(biassecs);               // Drop reference
+    return item;
+}
+
+// CELL.XBIN and CELL.YBIN
+psMetadataItem *p_pmConceptParse_CELL_Binning(const psMetadataItem *concept,
+                                              const psMetadataItem *pattern,
+                                              pmConceptSource source,
+                                              const psMetadata *cameraFormat,
+                                              const pmFPA *fpa,
+                                              const pmChip *chip,
+                                              const pmCell *cell)
+{
+    assert(concept);
+    assert(pattern);
+
+    int binning = 1;                    // Binning factor in x
+    switch (concept->type) {
+      case PS_DATA_STRING: {
+          psString binString = concept->data.V; // The string containing the binning
+          if ((strcmp(pattern->name, "CELL.XBIN") == 0 && sscanf(binString, "%d %*d", &binning) != 1 &&
+               sscanf(binString, "%d,%*d", &binning) != 1) ||
+              (strcmp(pattern->name, "CELL.YBIN") == 0 && sscanf(binString, "%*d %d", &binning) != 1 &&
+               sscanf(binString, "%*d,%d", &binning) != 1)) {
+              psError(PS_ERR_UNKNOWN, true, "Unable to parse string to get %s: %s\n", pattern->name, binString);
+          }
+          break;
+      }
+        TYPE_CASE(binning, concept, U8);
+        TYPE_CASE(binning, concept, U16);
+        TYPE_CASE(binning, concept, U32);
+        TYPE_CASE(binning, concept, S8);
+        TYPE_CASE(binning, concept, S16);
+        TYPE_CASE(binning, concept, S32);
+      default:
+        psError(PS_ERR_UNKNOWN, true, "Note sure how to parse %s of type %x --- assuming 1.\n", pattern->name,
+                concept->type);
+    }
+
+    return psMetadataItemAllocS32(pattern->name, pattern->comment, binning);
+}
+
+
+psMetadataItem *p_pmConceptParse_TIMESYS(const psMetadataItem *concept,
+                                         const psMetadataItem *pattern,
+                                         pmConceptSource source,
+                                         const psMetadata *cameraFormat,
+                                         const pmFPA *fpa,
+                                         const pmChip *chip,
+                                         const pmCell *cell)
+{
+    assert(concept);
+    assert(pattern);
+
+    psTimeType timeSys = PS_TIME_UTC;   // The time system
+    psString sys = concept->data.V;     // The time system string
+    if (concept->type != PS_DATA_STRING || strlen(sys) <= 0) {
+        // XXX is this too low verbosity?
+        psLogMsg ("psModules.concepts", PS_LOG_DETAIL, "Can't interpret %s --- assuming UTC.\n", pattern->name);
+    } else if (strcasecmp(sys, "TAI") == 0) {
+        timeSys = PS_TIME_TAI;
+    } else if (strcasecmp(sys, "UTC") == 0) {
+        timeSys = PS_TIME_UTC;
+    } else if (strcasecmp(sys, "UT1") == 0) {
+        timeSys = PS_TIME_UT1;
+    } else if (strcasecmp(sys, "TT") == 0) {
+        timeSys = PS_TIME_TT;
+    } else {
+        // XXX is this too low verbosity?
+        psLogMsg ("psModules.concepts", PS_LOG_DETAIL, "Can't interpret %s --- assuming UTC.\n", pattern->name);
+    }
+
+    return psMetadataItemAllocS32(pattern->name, pattern->comment, timeSys);
+}
+
+psMetadataItem *p_pmConceptParse_TIME(const psMetadataItem *concept,
+                                      const psMetadataItem *pattern,
+                                      pmConceptSource source,
+                                      const psMetadata *cameraFormat,
+                                      const pmFPA *fpa,
+                                      const pmChip *chip,
+                                      const pmCell *cell)
+{
+    assert(concept);
+    assert(cameraFormat);
+
+    // Need TIMESYS first
+    psString timesysName = psStringCopy(pattern->name); // e.g., "CELL.TIME" --> "CELL.TIMESYS"
+    psStringSubstitute(&timesysName, "TIMESYS", "TIME");
+    bool mdok = false;                  // Result of MD lookup
+    psTimeType timeSys = PS_TIME_UTC; // The time system
+    if (cell) {
+        timeSys = psMetadataLookupS32(&mdok, cell->concepts, timesysName);
+    }
+    if (!mdok && chip) {
+        timeSys = psMetadataLookupS32(&mdok, chip->concepts, timesysName);
+    }
+    if (!mdok && fpa) {
+        timeSys = psMetadataLookupS32(&mdok, fpa->concepts, timesysName);
+    }
+    if (!mdok || (timeSys == 0xffffffff)) {
+        psWarning("Unable to find %s in concepts when parsing %s --- assuming UTC.\n",
+                  timesysName, pattern->name);
+        timeSys = PS_TIME_UTC;
+    }
+    psFree(timesysName);
+
+    // Work out how the time is represented
+    bool separateTime = false;
+    bool usaTime = false;               // Is the time specified in USA (MM-DD-YYYY) order?
+    bool backwardsTime = false;         // Is the time specified in backwards (DD-MM-YYYY) order?
+    bool yearFirst = false;            // Is the time specified in yearFirst (YYYY-MM-DD) order?
+    bool pre2000Time = false;           // Is the time specified pre-2000 (where the year only has two digits)
+    bool mjdTime = false;               // Is the time specified a MJD?
+    bool jdTime = false;                // Is the time specified a JD?
+
+    // Get format
+    psMetadata *formats = psMetadataLookupMetadata(&mdok, cameraFormat, "FORMATS");
+    if (!mdok || !formats) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find FORMATS in camera configuration.\n");
+        return NULL;
+    }
+
+    psString timeFormat = psMetadataLookupStr(&mdok, formats, pattern->name);
+    if (!mdok || strlen(timeFormat) == 0) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find %s in FORMATS.\n", pattern->name);
+        return NULL;
+    }
+
+    // Parse the time format
+    // why should more than one be allowed??
+    psList *timeFormats = psStringSplit(timeFormat, " ,;", false); // List of the format options
+    psListIterator *timeFormatsIter = psListIteratorAlloc(timeFormats, PS_LIST_HEAD, false); // Iter
+    while ((timeFormat = psListGetAndIncrement(timeFormatsIter))) {
+        if (strcasecmp(timeFormat, "SEPARATE") == 0) {
+            separateTime = true;
+        } else if (strcasecmp(timeFormat, "USA") == 0) {
+            usaTime = true;
+            backwardsTime = false;
+            yearFirst = false;
+            jdTime = false;
+            mjdTime = false;
+        } else if (strcasecmp(timeFormat, "BACKWARDS") == 0) {
+            backwardsTime = true;
+            usaTime = false;
+            yearFirst = false;
+            jdTime = false;
+            mjdTime = false;
+        } else if (strcasecmp(timeFormat, "YEAR.FIRST") == 0) {
+            yearFirst = true;
+            usaTime = false;
+            backwardsTime = false;
+            jdTime = false;
+            mjdTime = false;
+        } else if (strcasecmp(timeFormat, "PRE2000") == 0) {
+            pre2000Time = true;
+        } else if (strcasecmp(timeFormat, "MJD") == 0) {
+            mjdTime = true;
+            jdTime = false;
+            yearFirst = false;
+            backwardsTime = false;
+            usaTime = false;
+        } else if (strcasecmp(timeFormat, "JD") == 0) {
+            jdTime = true;
+            mjdTime = false;
+            yearFirst = false;
+            backwardsTime = false;
+            usaTime = false;
+        } else {
+            psError(PS_ERR_UNKNOWN, true, "Unrecognised FORMATS option for %s: %s --- "
+                    "ignored.\n", pattern->name, timeFormat);
+            psFree(timeFormatsIter);
+            psFree(timeFormats);
+            return NULL;
+        }
+    }
+    psFree(timeFormatsIter);
+    psFree(timeFormats);
+
+    psTime *time = NULL;                // The time
+    switch (concept->type) {
+      case PS_DATA_LIST: {
+          if (!separateTime) {
+              psWarning ("DATE and TIME stored separately, but not specified in format\n");
+          }
+          // The date and time are stored separately
+          // Assume the date is first and the time second
+          psList *dateTime = concept->data.V; // The list containing items for date and time
+          if (psListLength(dateTime) != 2) {
+              psError(PS_ERR_BAD_PARAMETER_SIZE, false,
+                      "Unable to parse %s: date and time are not both available.", pattern->name);
+              return NULL;
+          }
+          psMetadataItem *dateItem = psListGet(dateTime, PS_LIST_HEAD); // Item containing the date
+          if (!dateItem) {
+              psError(PS_ERR_UNKNOWN, true, "Date is not found.\n");
+              return NULL;
+          }
+          if (dateItem->type != PS_DATA_STRING) {
+              psError(PS_ERR_UNKNOWN, true, "Date is not of type STR.\n");
+              return NULL;
+          }
+          psString dateString = dateItem->data.V; // The string with the date
+          int day = 0, month = 0, year = 0;
+          if (sscanf(dateString, "%d-%d-%d", &year, &month, &day) != 3 &&
+              sscanf(dateString, "%d/%d/%d", &year, &month, &day) != 3) {
+              psError(PS_ERR_UNKNOWN, true, "Unable to read date: %s\n", dateString);
+              return NULL;
+          }
+          if (backwardsTime) {
+              // Need to switch days and years
+              int temp = day;
+              day = year;
+              year = temp;
+          }
+          if (usaTime) {
+              // Need to switch everything around.... Yanks!
+              int temp = day;
+              day = month;
+              month = year;
+              year = temp;
+          }
+          if (year < 100) {
+              if (pre2000Time) {
+                  year += 1900;
+              } else {
+                  year += 2000;
+              }
+          }
+          sprintf(dateString,"%04d-%02d-%02d", year, month, day);
+
+          psMetadataItem *timeItem = psListGet(dateTime, PS_LIST_HEAD + 1); // Item containing the time
+          if (!timeItem) {
+              psError(PS_ERR_UNKNOWN, true, "Time is not found.\n");
+              return NULL;
+          }
+          psString timeString = NULL; // The string with the time
+          if (timeItem->type == PS_DATA_STRING) {
+              timeString = timeItem->data.V;
+          } else {
+              // Assume that time is specified in Second of Day (!)
+              double seconds = NAN;
+              switch (timeItem->type) {
+                  TYPE_CASE(seconds, timeItem, U8);
+                  TYPE_CASE(seconds, timeItem, U16);
+                  TYPE_CASE(seconds, timeItem, U32);
+                  TYPE_CASE(seconds, timeItem, S8);
+                  TYPE_CASE(seconds, timeItem, S16);
+                  TYPE_CASE(seconds, timeItem, S32);
+                  TYPE_CASE(seconds, timeItem, F32);
+                  TYPE_CASE(seconds, timeItem, F64);
+                default:
+                  psError(PS_ERR_UNKNOWN, true, "Time is not of an expected type: %x\n", timeItem->type);
+                  return NULL;
+              }
+              // Now print to timeString as "hh:mm:ss.ss"
+              int hours = seconds / 3600;
+              seconds -= (double)hours * 3600.0;
+              int minutes = seconds / 60;
+              seconds -= (double)minutes * 60.0;
+              psStringAppend(&timeString, "%02d:%02d:%02f", hours, minutes, seconds);
+          }
+          psString dateTimeString = NULL;
+          psStringAppend(&dateTimeString, "%sT%s", dateString, timeString);
+          time = psTimeFromISO(dateTimeString, timeSys);
+          psFree(dateTimeString);
+          break;
+      }
+      case PS_DATA_STRING: {
+          psString timeString = concept->data.V;   // String with the time
+          if (jdTime) {
+              double timeValue = strtod (timeString, NULL);
+              time = psTimeFromJD(timeValue);
+          } else if (mjdTime) {
+              double timeValue = strtod (timeString, NULL);
+              time = psTimeFromMJD(timeValue);
+          } else {
+              // It's ISO
+              time = psTimeFromISO(timeString, timeSys);
+          } // Interpreting the time string
+          break;
+      }
+      case PS_TYPE_F32: {
+          double timeValue = (double)concept->data.F32;
+          if (jdTime) {
+              time = psTimeFromJD(timeValue);
+          } else if (mjdTime) {
+              time = psTimeFromMJD(timeValue);
+          } else {
+              psError(PS_ERR_UNKNOWN, true, "Not sure how to parse %s (%f) --- trying JD\n",
+                      pattern->name, timeValue);
+              time = psTimeFromJD(timeValue);
+          }
+          break;
+      }
+      case PS_TYPE_F64: {
+          double timeValue = (double)concept->data.F64;
+          if (jdTime) {
+              time = psTimeFromJD(timeValue);
+          } else if (mjdTime) {
+              time = psTimeFromMJD(timeValue);
+          } else {
+              psError(PS_ERR_UNKNOWN, true, "Not sure how to parse %s (%f) --- trying JD\n",
+                      pattern->name, timeValue);
+              time = psTimeFromJD(timeValue);
+          }
+          break;
+      }
+      default:
+        psError(PS_ERR_UNKNOWN, true, "Unable to parse %s.\n", pattern->name);
+        return NULL;
+    }
+
+    psMetadataItem *item = psMetadataItemAllocPtr(pattern->name, PS_DATA_TIME, pattern->comment, time);
+    psFree(time);                       // Drop reference
+    return item;
+}
+
+// Correct a position --- in case the user wants FORTRAN indexing (like the FITS standard...)
+static int fortranCorr(const psMetadata *cameraFormat, // The camera format description
+                       const char *name // Name of concept to check for FORTRAN indexing
+    )
+{
+    bool mdok = false;                  // Result of MD lookup
+    psMetadata *formats = psMetadataLookupMetadata(&mdok, cameraFormat, "FORMATS");
+    if (mdok && formats) {
+        psString format = psMetadataLookupStr(&mdok, formats, name);
+        if (mdok && strlen(format) > 0 && strcasecmp(format, "FORTRAN") == 0) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+psMetadataItem *p_pmConceptParse_Positions(const psMetadataItem *concept,
+                                           const psMetadataItem *pattern,
+                                           pmConceptSource source,
+                                           const psMetadata *cameraFormat,
+                                           const pmFPA *fpa,
+                                           const pmChip *chip,
+                                           const pmCell *cell)
+{
+    assert(concept);
+    assert(cameraFormat);
+
+    int offset = 0;                     // Offset of component (0,0) corner from the parent (0,0) corner
+
+    switch (concept->type) {
+        TYPE_CASE(offset, concept, U8);
+        TYPE_CASE(offset, concept, U16);
+        TYPE_CASE(offset, concept, U32);
+        TYPE_CASE(offset, concept, S8);
+        TYPE_CASE(offset, concept, S16);
+        TYPE_CASE(offset, concept, S32);
+#if 0
+
+      case PS_DATA_STRING: {
+          // Interpret as a region specifier [x0:x1,y0:y1]
+          int xParity = 0;
+          int yParity = 0;
+          psRegion region = psRegionAndParityFromString(&xParity, &yParity, concept->data.V);
+          if (strstr(pattern->name, ".X0")) {
+              offset = region.x0;
+          } else if (strstr(pattern->name, ".Y0")) {
+              offset = region.y0;
+          } else if (strstr(pattern->name, ".X1")) {
+              offset = region.x1;
+          } else if (strstr(pattern->name, ".Y1")) {
+              offset = region.y1;
+          } else {
+              psError(PS_ERR_UNKNOWN, true,
+                      "Unable to interpret %s because unable to determine if concept is X or Y.\n",
+                      pattern->name);
+              return NULL;
+          }
+          break;
+      }
+#endif
+      default:
+        if (concept->type == PS_TYPE_F32 && concept->data.F32 - (int)concept->data.F32 == 0) {
+            offset = concept->data.F32;
+        } else if (concept->type == PS_TYPE_F64 && concept->data.F64 - (int)concept->data.F64 == 0) {
+            offset = concept->data.F64;
+        } else {
+            psError(PS_ERR_UNKNOWN, true, "Concept %s is not of integer type, as expected.\n", pattern->name);
+            return NULL;
+        }
+    }
+    offset -= fortranCorr(cameraFormat, pattern->name);
+    return psMetadataItemAllocS32(pattern->name, pattern->comment, offset);
+}
+
+
+psMetadataItem *p_pmConceptFormat_CELL_TRIMSEC(const psMetadataItem *concept,
+                                               pmConceptSource source,
+                                               const psMetadata *cameraFormat,
+                                               const pmFPA *fpa,
+                                               const pmChip *chip,
+                                               const pmCell *cell)
+{
+    assert(concept);
+
+    psRegion *trimsec = psMemIncrRefCounter(concept->data.V); // The trimsec region
+    if (!trimsec) {
+        return psMetadataItemAllocStr(concept->name, concept->comment, NULL);
+    }
+
+    // Correct trim section for binning if it's specified explicitly (i.e., immutably) in the CELLS.
+    if (source == PM_CONCEPT_SOURCE_CELLS) {
+        bool xStatus, yStatus;          // Status of MD lookups
+        int xBin = psMetadataLookupS32(&xStatus, cell->concepts, "CELL.XBIN");
+        int yBin = psMetadataLookupS32(&yStatus, cell->concepts, "CELL.YBIN");
+        if (!xStatus || !yStatus || xBin == 0 || yBin == 0) {
+            psWarning("Unable to find CELL.XBIN and CELL.YBIN to correct CELL.TRIMSEC.\n");
+            psFree(trimsec);            // Drop reference
+            return psMemIncrRefCounter((psPtr)concept); // Casting away "const" to increment
+        }
+        psRegion *newTrimsec = psRegionAlloc(trimsec->x0 * xBin, trimsec->x1 * xBin,
+                                             trimsec->y0 * yBin, trimsec->y1 * yBin); // Adjusted for binning
+        psFree(trimsec);
+        trimsec = newTrimsec;
+    }
+
+    psString trimsecString = psRegionToString(*trimsec);
+    psFree(trimsec);
+    psMetadataItem *formatted = psMetadataItemAllocStr(concept->name, concept->comment,
+                                                       trimsecString);
+    psFree(trimsecString);
+    return formatted;
+}
+
+psMetadataItem *p_pmConceptFormat_CELL_BIASSEC(const psMetadataItem *concept,
+                                               pmConceptSource source,
+                                               const psMetadata *cameraFormat,
+                                               const pmFPA *fpa,
+                                               const pmChip *chip,
+                                               const pmCell *cell)
+{
+    // Return a metadata item containing a list of metadata items of region strings
+    psList *biassecs = concept->data.V; // The biassecs region list
+    psList *new = psListAlloc(NULL);    // New list containing metadatas
+    if (biassecs) {
+        psListIterator *biassecsIter = psListIteratorAlloc(biassecs, PS_LIST_HEAD, false); // Iterator
+        psRegion *region = NULL;            // Region from iteration
+        while ((region = psListGetAndIncrement(biassecsIter))) {
+            // Correct bias section for binning if it's specified explicitly (i.e., immutably) in the CELLS.
+            if (source == PM_CONCEPT_SOURCE_CELLS) {
+                bool xStatus, yStatus;          // Status of MD lookups
+                int xBin = psMetadataLookupS32(&xStatus, cell->concepts, "CELL.XBIN");
+                int yBin = psMetadataLookupS32(&yStatus, cell->concepts, "CELL.YBIN");
+                if (!xStatus || !yStatus || xBin == 0 || yBin == 0) {
+                    psWarning("Unable to find CELL.XBIN and CELL.YBIN to correct CELL.BIASSEC.\n");
+                } else {
+                    psRegion *newTrimsec = psRegionAlloc(region->x0 * xBin, region->x1 * xBin,
+                                                         region->y0 * yBin, region->y1 * yBin);
+                    region = newTrimsec;
+                }
+            } else {
+                psMemIncrRefCounter(region);
+            }
+
+            psString regionString = psRegionToString(*region); // The string region "[x0:x1,y0:y1]"
+            psFree(region);
+            psMetadataItem *item = psMetadataItemAllocStr(concept->name, concept->comment, regionString);
+            psFree(regionString);           // Drop reference
+            psListAdd(new, PS_LIST_TAIL, item);
+            psFree(item);                   // Drop reference
+        }
+        psFree(biassecsIter);
+    }
+
+    psMetadataItem *formatted = psMetadataItemAllocPtr(concept->name, PS_DATA_LIST, concept->comment, new);
+    psFree(new);                        // Drop reference
+    return formatted;
+}
+
+// This function actually does both CELL.XBIN and CELL.YBIN if CELL.XBIN and CELL.YBIN are specified by the
+// same header.
+psMetadataItem *p_pmConceptFormat_CELL_XBIN(const psMetadataItem *concept,
+                                            pmConceptSource source,
+                                            const psMetadata *cameraFormat,
+                                            const pmFPA *fpa,
+                                            const pmChip *chip,
+                                            const pmCell *cell)
+{
+    assert(concept);
+
+    psMetadata *translation = psMetadataLookupMetadata(NULL, cameraFormat, "TRANSLATION");
+    bool xBinOK = true, yBinOK = true;  // Status of MD lookups
+    psString xKeyword = psMetadataLookupStr(&xBinOK, translation, "CELL.XBIN");
+    psString yKeyword = psMetadataLookupStr(&yBinOK, translation, "CELL.YBIN");
+    if (xBinOK && yBinOK && strlen(xKeyword) > 0 && strlen(yKeyword) > 0 &&
+        strcasecmp(xKeyword, yKeyword) == 0) {
+        psMetadataItem *yBinItem = psMetadataLookup(cell->concepts, "CELL.YBIN"); // Binning factor in y
+        psString binString = NULL;
+        psStringAppend(&binString, "%d %d", concept->data.S32, yBinItem->data.S32);
+        psMetadataItem *binItem = psMetadataItemAllocStr(concept->name, concept->comment, binString);
+        psFree(binString);
+        return binItem;
+    }
+
+    // Otherwise, there's no formatting required
+    return psMetadataItemCopy(concept);
+}
+
+// Only need to format if both if CELL.XBIN and CELL.YBIN are not specified by the same header.
+psMetadataItem *p_pmConceptFormat_CELL_YBIN(const psMetadataItem *concept,
+                                            pmConceptSource source,
+                                            const psMetadata *cameraFormat,
+                                            const pmFPA *fpa,
+                                            const pmChip *chip,
+                                            const pmCell *cell)
+{
+    assert(concept);
+
+    psMetadata *translation = psMetadataLookupMetadata(NULL, cameraFormat, "TRANSLATION");
+    bool xBinOK = true, yBinOK = true;  // Status of MD lookups
+    psString xKeyword = psMetadataLookupStr(&xBinOK, translation, "CELL.XBIN");
+    psString yKeyword = psMetadataLookupStr(&yBinOK, translation, "CELL.YBIN");
+    if (xBinOK && yBinOK && strlen(xKeyword) > 0 && strlen(yKeyword) > 0 &&
+        strcasecmp(xKeyword, yKeyword) == 0) {
+        // Censor this --- it's already done (though no harm if it's done twice
+        return NULL;
+    }
+
+    // No formatting required
+    return psMetadataItemCopy(concept);
+}
+
+
+psMetadataItem *p_pmConceptFormat_TIMESYS(const psMetadataItem *concept,
+                                          pmConceptSource source,
+                                          const psMetadata *cameraFormat,
+                                          const pmFPA *fpa,
+                                          const pmChip *chip,
+                                          const pmCell *cell)
+{
+    psString sys = NULL;            // String to store
+    switch (concept->data.S32) {
+      case PS_TIME_TAI:
+        sys = psStringCopy("TAI");
+        break;
+      case PS_TIME_UTC:
+        sys = psStringCopy("UTC");
+        break;
+      case PS_TIME_UT1:
+        sys = psStringCopy("UT1");
+        break;
+      case PS_TIME_TT:
+        sys = psStringCopy("TT");
+        break;
+      default:
+        sys = psStringCopy("Unknown");
+    }
+    psMetadataItem *newItem = psMetadataItemAllocStr(concept->name, concept->comment, sys);
+    psFree(sys);
+
+    return newItem;
+}
+
+psMetadataItem *p_pmConceptFormat_TIME(const psMetadataItem *concept,
+                                       pmConceptSource source,
+                                       const psMetadata *cameraFormat,
+                                       const pmFPA *fpa,
+                                       const pmChip *chip,
+                                       const pmCell *cell)
+{
+    psTime *time = concept->data.V;     // The time
+
+    // Work out the format
+    bool separateTime = false;          // Are the date and time stored separately?
+    bool pre2000Time = false;           // Is the year in pre-2000 format (two digits only)?
+    bool backwardsTime = false;         // Is the date stored backwards (DD-MM-YYYY)?
+    bool usaTime = false;               // Is the date stored in USA order (MM-DD-YYYY)?
+    bool jdTime = false;                // Is the date stored as a JD?
+    bool mjdTime = false;               // Is the date stored as a MJD?
+    bool yearFirst = false;
+
+    bool mdok = true;                   // Status of MD lookup
+    psMetadata *formats = psMetadataLookupMetadata(&mdok, cameraFormat, "FORMATS"); // The formats
+    if (mdok && formats) {
+        psString format = psMetadataLookupStr(&mdok, formats, concept->name); // The formats for eg, CELL.TIME
+        if (mdok && format && strlen(format) > 0) {
+            psList *formatList = psStringSplit(format, " ,;", false); // List of formats specified
+            psListIterator *formatListIter = psListIteratorAlloc(formatList, PS_LIST_HEAD, false); // Iterator
+            while ((format = psListGetAndIncrement(formatListIter))) {
+                if (strcasecmp(format, "SEPARATE") == 0) {
+                    separateTime = true;
+                } else if (strcasecmp(format, "USA") == 0) {
+                    usaTime = true;
+                    backwardsTime = false;
+                    jdTime = false;
+                    mjdTime = false;
+                } else if (strcasecmp(format, "BACKWARDS") == 0) {
+                    backwardsTime = true;
+                    usaTime = false;
+                    mjdTime = false;
+                    jdTime = false;
+                } else if (strcasecmp(format, "YEAR.FIRST") == 0) {
+                    yearFirst = true;
+                    usaTime = false;
+                    backwardsTime = false;
+                    jdTime = false;
+                    mjdTime = false;
+                } else if (strcasecmp(format, "PRE2000") == 0) {
+                    pre2000Time = true;
+                } else if (strcasecmp(format, "MJD") == 0) {
+                    mjdTime = true;
+                    usaTime = false;
+                    backwardsTime = false;
+                    jdTime = false;
+                    separateTime = false;
+                } else if (strcasecmp(format, "JD") == 0) {
+                    jdTime = true;
+                    usaTime = false;
+                    backwardsTime = false;
+                    mjdTime = false;
+                    separateTime = false;
+                } else {
+                    psWarning("Unrecognised FORMATS option for %s: %s --- "
+                              "ignored.\n", concept->name, format);
+                }
+            }
+            psFree(formatListIter);
+            psFree(formatList);
+        }
+    }
+
+    if (separateTime) {
+        // We're working with two separate headers --- construct a list with the date and time separately
+        psString dateTimeString = psTimeToISO(time); // String representation
+        psList *dateTime = psStringSplit(dateTimeString, "T", true);
+        psFree(dateTimeString);
+        psString dateString = psListGet(dateTime, PS_LIST_HEAD); // The date string
+        psString timeString = psListGet(dateTime, PS_LIST_TAIL); // The time string
+
+        // Need to format the strings....
+        // XXX: Couldn't be bothered doing these right now
+        if (pre2000Time) {
+            psError(PS_ERR_UNKNOWN, true, "Don't you realise it's the twenty-first century?\n");
+            return NULL;
+        }
+        if (backwardsTime) {
+            int day, month, year;
+            psTrace ("psModules.concepts", 5, "ISO time has year first, convert to DD-MM-YYYY");
+            sscanf (dateString, "%d-%d-%d", &year, &month, &day);
+            sprintf (dateString, "%02d-%02d-%04d", day, month, year);
+            // XXX fix this for str length
+        }
+        if (usaTime) {
+            int day, month, year;
+            psTrace ("psModules.concepts", 5, "ISO time has year first, convert to MM-DD-YYYY");
+            sscanf (dateString, "%d-%d-%d", &year, &month, &day);
+            sprintf (dateString, "%02d-%02d-%04d", month, day, year);
+            // XXX fix this for str length
+        }
+        if (yearFirst) {
+            psTrace ("psModules.concepts", 5, "ISO time has year first, no adjustment needed");
+        }
+
+        psMetadataItem *dateItem = psMetadataItemAllocStr(concept->name, "The date of observation",
+                                                          dateString);
+        psMetadataItem *timeItem = psMetadataItemAllocStr(concept->name, "The time of observation",
+                                                          timeString);
+
+        psListRemove(dateTime, PS_LIST_HEAD);
+        psListRemove(dateTime, PS_LIST_HEAD);
+
+        psListAdd(dateTime, PS_LIST_HEAD, dateItem);
+        psListAdd(dateTime, PS_LIST_TAIL, timeItem);
+
+        psMetadataItem *item = psMetadataItemAllocPtr(concept->name, PS_DATA_LIST, concept->comment,
+                                                      dateTime);
+        psFree (dateItem);
+        psFree (timeItem);
+        psFree (dateTime);
+        return item;
+    }
+    if (jdTime) {
+        double jd = psTimeToMJD(time);
+        return psMetadataItemAllocF64(concept->name, concept->comment, jd);
+    }
+    if (mjdTime) {
+        double mjd = psTimeToMJD(time);
+        return psMetadataItemAllocF64(concept->name, concept->comment, mjd);
+    }
+
+    // If we've gotten this far, so it's straight ISO.
+    psString dateTimeString = psTimeToISO(time); // String representation
+    psMetadataItem *item = psMetadataItemAllocStr(concept->name, concept->comment, dateTimeString);
+    psFree(dateTimeString);
+    return item;
+}
+
+
+psMetadataItem *p_pmConceptFormat_Positions(const psMetadataItem *concept,
+                                            pmConceptSource source,
+                                            const psMetadata *cameraFormat,
+                                            const pmFPA *fpa,
+                                            const pmChip *chip,
+                                            const pmCell *cell)
+{
+    assert(concept);
+    assert(cameraFormat);
+
+    if (concept->type != PS_TYPE_S32) {
+        psError(PS_ERR_UNKNOWN, true, "Concept %s is not of type S32, as expected.\n", concept->name);
+        return NULL;
+    }
+
+#if 0
+    // If both the X0 and Y0 positions are specified by the same header keyword, write both together, as part
+    // of the call for the X0 position.
+    // This is a bit of a kludge --- we're going to write it out as [x0:0,y0:0].  This means that we will be
+    // able to read it back in, but we've destroyed the x1 and y1 if it was present.
+    // We *could* attempt to read the header, parse the region, and only update the ones that we're trying
+    // to update.  Consider this an upgrade option later.
+    // Alternatively, we could add X1 and Y1 concepts, and write the whole lot out together.
+    // But until we care about X1 and Y1, it doesn't really matter --- if you want X1 and Y1, look at X0 and
+    // Y0 and add NXAIS1 and NAXIS2, respectively....
+    if (strstr(concept->name, ".X0")) {
+        psString companion = psStringCopy(concept->name); // Companion entry: ".Y" where this one has ".X"
+        psStringSubstitute(&companion, ".Y0", ".X0");
+
+        // Look both up in the camera format config
+        psMetadata *translation = psMetadataLookupMetadata(NULL, cameraFormat, "TRANSLATION");
+        bool xFound = true, yFound = true;  // Status of MD lookups
+        psString xKeyword = psMetadataLookupStr(&xFound, translation, concept->name);
+        psString yKeyword = psMetadataLookupStr(&yFound, translation, companion);
+        if (xFound && yFound && strlen(xKeyword) > 0 && strlen(yKeyword) > 0 &&
+            strcasecmp(xKeyword, yKeyword) == 0) {
+            psMetadataItem *yItem = psMetadataLookup(cell->concepts, companion); // Corresponding y value
+
+            int x = concept->data.S32 + fortranCorr(cameraFormat, concept->name); // x value
+            int y = yItem->data.S32 + fortranCorr(cameraFormat, companion); // y value
+
+            psRegion region = psRegionSet(x, x, y, y);
+            psString string = psRegionToString(region);
+            psMetadataItem *binItem = psMetadataItemAllocStr(concept->name, concept->comment, string);
+            psFree(string);
+            psFree(companion);
+            return binItem;
+        }
+        psFree(companion);
+    } else if (strstr(concept->name, ".Y0")) {
+        psString companion = psStringCopy(concept->name); // Companion entry: ".Y" where this one has ".X"
+        psStringSubstitute(&companion, ".X0", ".Y0");
+
+        // Look both up in the camera format config
+        psMetadata *translation = psMetadataLookupMetadata(NULL, cameraFormat, "TRANSLATION");
+        bool xFound = true, yFound = true;  // Status of MD lookups
+        psString xKeyword = psMetadataLookupStr(&xFound, translation, concept->name);
+        psString yKeyword = psMetadataLookupStr(&yFound, translation, companion);
+        psFree(companion);
+        if (xFound && yFound && strlen(xKeyword) > 0 && strlen(yKeyword) > 0 &&
+            strcasecmp(xKeyword, yKeyword) == 0) {
+            return NULL;                // We did it with the X; don't do anything.
+        }
+    }
+#endif
+
+    int offset = concept->data.S32;
+    offset += fortranCorr(cameraFormat, concept->name);
+    return psMetadataItemAllocS32(concept->name, concept->comment, offset);
+}
+
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsStandard.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsStandard.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsStandard.h	(revision 22158)
@@ -0,0 +1,191 @@
+/* @file  pmConceptsStandard.h
+ * @brief Private functions for parsing and formatting standard concepts.
+ *
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-12-08 03:15:37 $
+ * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_CONCEPTS_STANDARD_H
+#define PM_CONCEPTS_STANDARD_H
+
+/// @addtogroup Concepts Data Abstraction Concepts
+/// @{
+
+/// Parse a list of region specifiers on a line
+psList *p_pmConceptParseRegions(const char *region ///< Regions, separated by whitespace
+    );
+
+// Parse the TELTEMPS concept : parse a list of the form 'X1 X2 X3 X4 X5 ...' : for now use median
+psMetadataItem *p_pmConceptParse_TELTEMPS(const psMetadataItem *concept,
+					  const psMetadataItem *pattern,
+					  pmConceptSource source,
+					  const psMetadata *cameraFormat,
+					  const pmFPA *fpa,
+					  const pmChip *chip,
+					  const pmCell *cell);
+
+/// Parse the FPA.FILTER concept to apply a lookup table
+psMetadataItem *p_pmConceptParse_FPA_FILTER(const psMetadataItem *concept, ///< Concept to parse
+        const psMetadataItem *pattern, ///< Pattern to use in parsing
+                                            pmConceptSource source, ///< Source for concept
+        const psMetadata *cameraFormat, ///< Camera format definition
+        const pmFPA *fpa, ///< FPA for concept, or NULL
+        const pmChip *chip, ///< Chip for concept, or NULL
+        const pmCell *cell ///< Cell for concept, or NULL
+                                           );
+
+/// Format the FPA.FILTER concept to (reverse-)apply a lookup table
+psMetadataItem *p_pmConceptFormat_FPA_FILTER(const psMetadataItem *concept, ///< Concept to format
+                                            pmConceptSource source, ///< Source for concept
+        const psMetadata *cameraFormat, ///< Camera format definition
+        const pmFPA *fpa, ///< FPA for concept, or NULL
+        const pmChip *chip, ///< Chip for concept, or NULL
+        const pmCell *cell ///< Cell for concept, or NULL
+                                            );
+
+/// Parse the coordinates concepts: FPA.RA and FPA.DEC
+psMetadataItem *p_pmConceptParse_FPA_Coords(const psMetadataItem *concept, ///< Concept to parse
+        const psMetadataItem *pattern, ///< Pattern to use in parsing
+                                            pmConceptSource source, ///< Source for concept
+        const psMetadata *cameraFormat, ///< Camera format definition
+        const pmFPA *fpa, ///< FPA for concept, or NULL
+        const pmChip *chip, ///< Chip for concept, or NULL
+        const pmCell *cell ///< Cell for concept, or NULL
+                                           );
+
+/// Format the coordinates concepts: FPA.RA and FPA.DEC
+psMetadataItem *p_pmConceptFormat_FPA_Coords(const psMetadataItem *concept, ///< Concept to format
+                                            pmConceptSource source, ///< Source for concept
+        const psMetadata *cameraFormat, ///< Camera format definition
+        const pmFPA *fpa, ///< FPA for concept, or NULL
+        const pmChip *chip, ///< Chip for concept, or NULL
+        const pmCell *cell ///< Cell for concept, or NULL
+                                            );
+
+/// Parse the CELL.TRIMSEC concept
+psMetadataItem *p_pmConceptParse_CELL_TRIMSEC(const psMetadataItem *concept, ///< Concept to parse
+        const psMetadataItem *pattern, ///< Pattern to use in parsing
+                                            pmConceptSource source, ///< Source for concept
+        const psMetadata *cameraFormat, ///< Camera format definition
+        const pmFPA *fpa, ///< FPA for concept, or NULL
+        const pmChip *chip, ///< Chip for concept, or NULL
+        const pmCell *cell ///< Cell for concept, or NULL
+                                             );
+
+/// Parse the CELL.BIASSEC concept
+psMetadataItem *p_pmConceptParse_CELL_BIASSEC(const psMetadataItem *concept, ///< Concept to parse
+        const psMetadataItem *pattern, ///< Pattern to use in parsing
+                                            pmConceptSource source, ///< Source for concept
+        const psMetadata *cameraFormat, ///< Camera format definition
+        const pmFPA *fpa, ///< FPA for concept, or NULL
+        const pmChip *chip, ///< Chip for concept, or NULL
+        const pmCell *cell ///< Cell for concept, or NULL
+                                             );
+
+/// Parse the cell binning concepts: CELL.XBIN, CELL.YBIN
+psMetadataItem *p_pmConceptParse_CELL_Binning(const psMetadataItem *concept, ///< Concept to parse
+        const psMetadataItem *pattern, ///< Pattern to use in parsing
+                                            pmConceptSource source, ///< Source for concept
+        const psMetadata *cameraFormat, ///< Camera format definition
+        const pmFPA *fpa, ///< FPA for concept, or NULL
+        const pmChip *chip, ///< Chip for concept, or NULL
+        const pmCell *cell ///< Cell for concept, or NULL
+                                             );
+
+/// Parse the time system concepts: FPA.TIMESYS and CELL.TIMESYS
+psMetadataItem *p_pmConceptParse_TIMESYS(const psMetadataItem *concept, ///< Concept to parse
+        const psMetadataItem *pattern, ///< Pattern to use in parsing
+                                            pmConceptSource source, ///< Source for concept
+        const psMetadata *cameraFormat, ///< Camera format definition
+        const pmFPA *fpa, ///< FPA for concept, or NULL
+        const pmChip *chip, ///< Chip for concept, or NULL
+        const pmCell *cell ///< Cell for concept, or NULL
+                                        );
+
+/// Parse the time concepts: FPA.TIME and CELL.TIME
+psMetadataItem *p_pmConceptParse_TIME(const psMetadataItem *concept, ///< Concept to parse
+                                      const psMetadataItem *pattern, ///< Pattern to use in parsing
+                                            pmConceptSource source, ///< Source for concept
+                                      const psMetadata *cameraFormat, ///< Camera format definition
+                                      const pmFPA *fpa, ///< FPA for concept, or NULL
+                                      const pmChip *chip, ///< Chip for concept, or NULL
+                                      const pmCell *cell ///< Cell for concept, or NULL
+                                     );
+
+/// Parse a cell position concept, e.g., CELL.X0
+psMetadataItem *p_pmConceptParse_Positions(const psMetadataItem *concept, ///< Concept to parse
+        const psMetadataItem *pattern, ///< Pattern to use in parsing
+                                            pmConceptSource source, ///< Source for concept
+       const psMetadata *cameraFormat, ///< Camera format definition
+        const pmFPA *fpa, ///< FPA for concept, or NULL
+        const pmChip *chip, ///< Chip for concept, or NULL
+        const pmCell *cell ///< Cell for concept, or NULL
+                                          );
+
+/// Format the CELL.TRIMSEC concept
+psMetadataItem *p_pmConceptFormat_CELL_TRIMSEC(const psMetadataItem *concept, ///< Concept to format
+                                            pmConceptSource source, ///< Source for concept
+        const psMetadata *cameraFormat, ///< Camera format definition
+        const pmFPA *fpa, ///< FPA for concept, or NULL
+        const pmChip *chip, ///< Chip for concept, or NULL
+        const pmCell *cell ///< Cell for concept, or NULL
+                                              );
+
+/// Format the CELL.BIASSEC concept
+psMetadataItem *p_pmConceptFormat_CELL_BIASSEC(const psMetadataItem *concept, ///< Concept to format
+                                            pmConceptSource source, ///< Source for concept
+        const psMetadata *cameraFormat, ///< Camera format definition
+        const pmFPA *fpa, ///< FPA for concept, or NULL
+        const pmChip *chip, ///< Chip for concept, or NULL
+        const pmCell *cell ///< Cell for concept, or NULL
+                                              );
+
+/// Format the CELL.XBIN concept
+psMetadataItem *p_pmConceptFormat_CELL_XBIN(const psMetadataItem *concept, ///< Concept to format
+                                            pmConceptSource source, ///< Source for concept
+        const psMetadata *cameraFormat, ///< Camera format definition
+        const pmFPA *fpa, ///< FPA for concept, or NULL
+        const pmChip *chip, ///< Chip for concept, or NULL
+        const pmCell *cell ///< Cell for concept, or NULL
+                                           );
+
+/// Format the CELL.YBIN concept
+psMetadataItem *p_pmConceptFormat_CELL_YBIN(const psMetadataItem *concept, ///< Concept to format
+                                            pmConceptSource source, ///< Source for concept
+        const psMetadata *cameraFormat, ///< Camera format definition
+        const pmFPA *fpa, ///< FPA for concept, or NULL
+        const pmChip *chip, ///< Chip for concept, or NULL
+        const pmCell *cell ///< Cell for concept, or NULL
+                                           );
+
+/// Format the time system concepts: FPA.TIMESYS and CELL.TIMESYS
+psMetadataItem *p_pmConceptFormat_TIMESYS(const psMetadataItem *concept, ///< Concept to format
+                                            pmConceptSource source, ///< Source for concept
+        const psMetadata *cameraFormat, ///< Camera format definition
+        const pmFPA *fpa, ///< FPA for concept, or NULL
+        const pmChip *chip, ///< Chip for concept, or NULL
+        const pmCell *cell ///< Cell for concept, or NULL
+                                         );
+
+/// Format the time concepts: FPA.TIME and CELL.TIME
+psMetadataItem *p_pmConceptFormat_TIME(const psMetadataItem *concept, ///< Concept to format
+                                            pmConceptSource source, ///< Source for concept
+                                       const psMetadata *cameraFormat, ///< Camera format definition
+                                       const pmFPA *fpa, ///< FPA for concept, or NULL
+                                       const pmChip *chip, ///< Chip for concept, or NULL
+                                       const pmCell *cell ///< Cell for concept, or NULL
+                                      );
+
+/// Format a cell position concept, e.g., CELL.X0
+psMetadataItem *p_pmConceptFormat_Positions(const psMetadataItem *concept, ///< Concept to format
+                                            pmConceptSource source, ///< Source for concept
+        const psMetadata *cameraFormat, ///< Camera format definition
+        const pmFPA *fpa, ///< FPA for concept, or NULL
+        const pmChip *chip, ///< Chip for concept, or NULL
+        const pmCell *cell ///< Cell for concept, or NULL
+                                           );
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsUpdate.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsUpdate.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsUpdate.c	(revision 22158)
@@ -0,0 +1,90 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmConceptsUpdate.h"
+
+bool pmConceptsUpdate(const pmFPA *fpa, const pmChip *chip, const pmCell *cell)
+{
+    if (fpa) {
+        // Check for FPA concepts updates
+    }
+
+    if (chip) {
+        // Check for chip concepts updates
+    }
+
+    if (cell) {
+        // Check for cell concepts updates
+
+	bool xStatus, yStatus; // Status of MD lookups
+	psImageBinning *binning = psImageBinningAlloc();
+	binning->nXbin = psMetadataLookupS32(&xStatus, cell->concepts, "CELL.XBIN");
+	binning->nYbin = psMetadataLookupS32(&yStatus, cell->concepts, "CELL.YBIN");
+	if (!xStatus || !yStatus) {
+	    // XXX should this be an error condition?
+	    psFree (binning);
+	    return true;
+	}
+	if (!binning->nXbin || !binning->nXbin) {
+	    // XXX should this be an error condition?
+	    psFree (binning);
+	    return true;
+	}
+
+        // CELL.TRIMSEC needs to be updated for the binning
+        if (psMetadataLookup(cell->concepts, "CELL.TRIMSEC.UPDATE")) {
+	    psRegion *trimsec = psMetadataLookupPtr(NULL, cell->concepts, "CELL.TRIMSEC"); // Trim section
+	    *trimsec = psImageBinningSetRuffRegion (binning, *trimsec);
+	    // force integer pixels : truncate x0, roundup x1:
+	    trimsec->x0 = (int)trimsec->x0;
+	    if (trimsec->x1 > (int)trimsec->x1) {
+		trimsec->x1 = (int)trimsec->x1 + 1;
+	    } else {
+		trimsec->x1 = (int)trimsec->x1;
+	    }		
+	    trimsec->y0 = (int)trimsec->y0;
+	    if (trimsec->y1 > (int)trimsec->y1) {
+		trimsec->y1 = (int)trimsec->y1 + 1;
+	    } else {
+		trimsec->y1 = (int)trimsec->y1;
+	    }		
+	    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC.UPDATE");
+        }
+
+        // CELL.BIASSEC needs to be updated for the binning
+        if (psMetadataLookup(cell->concepts, "CELL.BIASSEC.UPDATE")) {
+	    psList *biassecs = psMetadataLookupPtr(NULL, cell->concepts, "CELL.BIASSEC"); // Bias sections
+	    psListIterator *biassecsIter = psListIteratorAlloc(biassecs, PS_LIST_HEAD, true); // Iterator
+	    psRegion *biassec; // Bias region, from iteration
+	    while ((biassec = psListGetAndIncrement(biassecsIter))) {
+		*biassec = psImageBinningSetRuffRegion (binning, *biassec);
+		// force integer pixels : truncate x0, roundup x1:
+		biassec->x0 = (int)biassec->x0;
+		if (biassec->x1 > (int)biassec->x1) {
+		    biassec->x1 = (int)biassec->x1 + 1;
+		} else {
+		    biassec->x1 = (int)biassec->x1;
+		}		
+		biassec->y0 = (int)biassec->y0;
+		if (biassec->y1 > (int)biassec->y1) {
+		    biassec->y1 = (int)biassec->y1 + 1;
+		} else {
+		    biassec->y1 = (int)biassec->y1;
+		}		
+	    }
+	    psFree(biassecsIter);
+	    psMetadataRemoveKey(cell->concepts, "CELL.BIASSEC.UPDATE");
+        }
+	psFree (binning);
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsUpdate.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsUpdate.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsUpdate.h	(revision 22158)
@@ -0,0 +1,25 @@
+/* @file  pmConceptsUpdate.h
+ * @brief Function to update concepts.
+ *
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-03-30 21:12:56 $
+ * Copyright 2005-2007 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_CONCEPTS_UPDATE_H
+#define PM_CONCEPTS_UPDATE_H
+
+/// Check for concepts to update.
+///
+/// Updating concepts is necessary if one concept depends on the value of another.  In that case, a flag
+/// (e.g., CONCEPTNAME.UPDATE" in the concepts) can be set, and it can be updated once the required value is
+/// known.
+bool pmConceptsUpdate(const pmFPA *fpa,       ///< FPA for which to update concepts
+                      const pmChip *chip,     ///< Chip for which to update concepts
+                      const pmCell *cell      ///< Cell for which to update concepts
+    );
+
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsWrite.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsWrite.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsWrite.c	(revision 22158)
@@ -0,0 +1,487 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <strings.h>            /* for strn?casecmp */
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmHDUUtils.h"
+#include "pmConcepts.h"
+#include "pmConceptsRead.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// File-static functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static bool compareConcepts(const psMetadataItem *compare, // Item to compare
+                            const psMetadataItem *standard // Standard for comparison
+                           )
+{
+    // First order checks
+    if (! compare || ! standard) {
+        return false;
+    }
+    if (strcasecmp(compare->name, standard->name) != 0) {
+        return false;
+    }
+
+    // Special case: list
+    if (compare->type == PS_DATA_LIST) {
+        // "compare" contains a list of psMetadataItems
+        // "standard" likely contains just a string (but it might possibly be a list of strings)
+        psList *cList = compare->data.V; // The list from comparison item
+        psList *sList = NULL;         // The list from standard item
+        switch (standard->type) {
+        case PS_DATA_STRING:
+            sList = psStringSplit(standard->data.V, " ;", true);
+            break;
+        case PS_DATA_LIST:
+            sList = psMemIncrRefCounter(standard->data.V);
+            break;
+        default:
+            return false;
+        }
+        if (cList->n != sList->n) {
+            psFree(sList);
+            return false;
+        }
+        psVector *match = psVectorAlloc(cList->n, PS_TYPE_U8); // Array indicating which values match
+        psVectorInit(match, 0);
+        psListIterator *cIter = psListIteratorAlloc(cList, PS_LIST_HEAD, false); // compare iterator
+        psListIterator *sIter = psListIteratorAlloc(sList, PS_LIST_HEAD, false); // standard iterator
+        psMetadataItem *cItem = NULL; // Item from compare list
+        while ((cItem = psListGetAndIncrement(cIter))) {
+            if (cItem->type != PS_DATA_STRING) {
+                psWarning("psMetadataItem from list is of type %x instead of "
+                         "%x (PS_DATA_STRING) --- can't interpret.\n", cItem->type, PS_DATA_STRING);
+                psFree(cIter);
+                psFree(sIter);
+                psFree(match);
+                psFree(sList);
+                return false;
+            }
+            psString cString = cItem->data.V; // String from compare list
+            psListIteratorSet(sIter, PS_LIST_HEAD);
+            int index = 0;            // Index for list
+            bool found = false;       // Found a match?
+            for (psString sString = NULL; (sString = psListGetAndIncrement(sIter)) && !found; index++) {
+                if (strcasecmp(cString, sString) == 0) {
+                    match->data.U8[index]++;
+                    found = true;
+                }
+            }
+            if (! found) {
+                // Can give up immediately
+                psFree(cIter);
+                psFree(sIter);
+                psFree(match);
+                psFree(sList);
+                return false;
+            }
+        }
+        // Make sure we got 100% matches in both directions
+        bool allMatch = true;         // Did all of them match?
+        for (int i = 0; i < match->n && allMatch; i++) {
+            if (!match->data.U8[i]) {
+                allMatch = false;
+            }
+        }
+        psFree(cIter);
+        psFree(sIter);
+        psFree(sList);
+        psFree(match);
+        return allMatch;
+    }
+
+    return psMetadataItemCompare(compare, standard);
+
+}
+
+
+// Format a single concept
+static psMetadataItem *conceptFormat(const pmConceptSpec *spec, // The concept specification
+                                     const psMetadataItem *concept, // The concept to parse
+                                     pmConceptSource source, // The concept source
+                                     const psMetadata *cameraFormat, // The camera format
+                                     const pmFPA *fpa, // The FPA
+                                     const pmChip *chip, // The chip
+                                     const pmCell *cell // The cell
+                                    )
+{
+    assert(spec);
+    assert(cameraFormat);
+
+    if (concept) {
+        psMetadataItem *formatted = NULL;  // The formatted concept
+        if (spec->format) {
+            formatted = spec->format(concept, source, cameraFormat, fpa, chip, cell);
+        } else if (strcmp(concept->name, spec->blank->name) != 0) {
+            // Adjust so that the name is correct
+            formatted = psMetadataItemCopy(concept);
+            psFree(formatted->name);
+            formatted->name = psStringCopy(spec->blank->name);
+        } else {
+            // Can get away with merely incrementing the reference counter
+            formatted = psMemIncrRefCounter((const psPtr)concept);
+        }
+
+        return formatted;
+    }
+    return NULL;
+}
+
+// Write a single value to a header
+static bool writeSingleHeader(pmHDU *hdu, // HDU for which to add to the header
+                              const char *keyword, // Keyword to add
+                              const psMetadataItem *item // Item to add to the header; may be NULL
+                             )
+{
+    assert(hdu);
+    assert(keyword && strlen(keyword) > 0);
+
+    if (!hdu->header) {
+        hdu->header = psMetadataAlloc();
+    }
+    if (!item) {
+        psTrace("psModules.concepts", 9, "Writing header %s: <<<BLANK>>>\n", keyword);
+        // Assume it's a NULL string: it's most easily parsed.
+        return psMetadataAddStr(hdu->header, PS_LIST_TAIL, keyword, PS_META_REPLACE, NULL, NULL);
+    }
+    switch (item->type) {
+    case PS_DATA_STRING:
+        psTrace("psModules.concepts", 9, "Writing header %s: %s\n", keyword, item->data.str);
+        return psMetadataAddStr(hdu->header, PS_LIST_TAIL, keyword, PS_META_REPLACE, item->comment,
+                                item->data.V);
+    case PS_DATA_S32:
+        psTrace("psModules.concepts", 9, "Writing header %s: %d\n", keyword, item->data.S32);
+        return psMetadataAddS32(hdu->header, PS_LIST_TAIL, keyword, PS_META_REPLACE, item->comment,
+                                item->data.S32);
+    case PS_DATA_F32:
+        psTrace("psModules.concepts", 9, "Writing header %s: %f\n", keyword, item->data.F32);
+        return psMetadataAddF32(hdu->header, PS_LIST_TAIL, keyword, PS_META_REPLACE, item->comment,
+                                item->data.F32);
+    case PS_DATA_F64:
+        psTrace("psModules.concepts", 9, "Writing header %s: %f\n", keyword, item->data.F64);
+        return psMetadataAddF64(hdu->header, PS_LIST_TAIL, keyword, PS_META_REPLACE, item->comment,
+                                item->data.F64);
+    case PS_DATA_REGION: {
+            psString region = psRegionToString(*(psRegion*)item->data.V);
+            psTrace("psModules.concepts", 9, "Writing header %s: %s\n", keyword, region);
+            bool result = psMetadataAddStr(hdu->header, PS_LIST_TAIL, keyword, PS_META_REPLACE, item->comment,
+                                           region);
+            psFree(region);
+            return result;
+        }
+    default:
+        psWarning("Type of %s is not suitable for a FITS header --- not added.\n",
+                 item->name);
+        return false;
+    }
+}
+
+
+// Write potentially multiple values to a header
+static bool writeHeader(pmHDU *hdu,     // HDU for which to add to the header
+                        const char *keywords, // Keywords to add
+                        const psMetadataItem *item // Item to add to the header
+                       )
+{
+    assert(hdu);
+    assert(keywords);
+    assert(item);
+
+    bool status = true;                 // Status of writing headers, to be returned
+    if (item->type == PS_DATA_LIST) {
+        psList *values = item->data.V;  // List of outputs
+        psList *keys = psStringSplit(keywords, " ,;", true); // List of keywords
+        if (keys->n != values->n && values->n != 0) {
+            psError(PS_ERR_UNKNOWN, true, "Number of keywords (%ld) does not match number of "
+                    "values (%ld).\n", keys->n, values->n);
+            psFree(keys);
+            return false;
+        }
+        psListIterator *keysIter = psListIteratorAlloc(keys, PS_LIST_HEAD, false); // Iterator for keywords
+        psListIterator *valuesIter = psListIteratorAlloc(values, PS_LIST_HEAD, false); // Iterator for values
+        psString key = NULL;            // Keyword from iteration
+        while ((key = psListGetAndIncrement(keysIter))) {
+            psMetadataItem *value = psListGetAndIncrement(valuesIter); // Value from iteration; may be NULL
+            status &= writeSingleHeader(hdu, key, value);
+        }
+        psFree(keysIter);
+        psFree(valuesIter);
+        psFree(keys);
+    } else {
+        status = writeSingleHeader(hdu, keywords, item);
+    }
+    return status;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool p_pmConceptsWriteToCells(const psMetadata *specs, const pmCell *cell, const psMetadata *concepts)
+{
+    PS_ASSERT_PTR_NON_NULL(specs, false);
+    PS_ASSERT_PTR_NON_NULL(concepts, false);
+    if (!cell) {
+        return false;
+    }
+    if (!cell->config) {
+        return false;
+    }
+
+    pmHDU *hdu = pmHDUGetLowest(NULL, NULL, cell); // The HDU at the lowest level
+    if (!hdu) {
+        return false;
+    }
+    psMetadata *cameraFormat = hdu->format; // The camera format
+    psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *specItem = NULL;    // Item from the specs metadata
+    while ((specItem = psMetadataGetAndIncrement(specsIter))) {
+        pmConceptSpec *spec = specItem->data.V; // The specification
+        psString name = specItem->name; // The concept name
+        psMetadataItem *cameraItem = psMetadataLookup(cell->config, name); // The concept from the camera,
+        // or NULL
+        if (cameraItem) {
+            // Grab the concept
+            psMetadataItem *conceptItem = psMetadataLookup(concepts, name); // The concept
+
+            psString nameSource = NULL; // String with the concept name and ".SOURCE" added
+            psStringAppend(&nameSource, "%s.SOURCE", name);
+            bool mdok = true;       // Status of MD lookup
+            psString source = psMetadataLookupStr(&mdok, cell->config, nameSource); // The source
+            if (mdok && strlen(source) > 0) {
+                psTrace("psModules.concepts", 8, "%s is %s\n", nameSource, source);
+                if (strcasecmp(source, "HEADER") == 0) {
+                    if (cameraItem->type != PS_DATA_STRING) {
+                        psWarning("Concept %s is specified by header, but is not "
+                                 "of type STR --- ignored.\n", conceptItem->name);
+                        continue;
+                    }
+
+                    // Formatted version
+                    psMetadataItem *formatted = conceptFormat(spec, conceptItem, PM_CONCEPT_SOURCE_HEADER,
+                                                              cameraFormat, NULL, NULL, cell);
+                    if (!formatted) {
+                        continue;
+                    }
+
+                    psTrace("psModules.concepts", 8, "Writing %s to header %s\n", name, cameraItem->data.str);
+                    writeHeader(hdu, cameraItem->data.V, formatted);
+                    psFree(formatted);
+                } else if (strcasecmp(source, "VALUE") == 0) {
+                    // Formatted version
+                    psMetadataItem *formatted = conceptFormat(spec, conceptItem, PM_CONCEPT_SOURCE_CELLS,
+                                                              cameraFormat, NULL, NULL, cell);
+                    if (!formatted) {
+                        continue;
+                    }
+
+                    psTrace("psModules.concepts", 8, "Checking %s against camera format.\n", name);
+                    if (! compareConcepts(formatted, cameraItem)) {
+                        psWarning("Concept %s is specified by value in the camera "
+                                 "format, but the values don't match.\n", name);
+                    }
+                    psFree(formatted);
+                } else {
+                    psWarning("Concept source %s isn't HEADER or VALUE --- can't "
+                             "write\n", nameSource);
+                }
+            } else {
+                // Assume it's specified by value
+                psMetadataItem *formatted = conceptFormat(spec, conceptItem, PM_CONCEPT_SOURCE_CELLS,
+                                                          cameraFormat, NULL, NULL, cell);
+                if (!formatted) {
+                    continue;
+                }
+
+                if (! compareConcepts(formatted, cameraItem)) {
+                    psWarning("Concept %s is specified by value in the camera "
+                             "format, but the values don't match.\n", name);
+                }
+                psFree(formatted);
+            }
+            psFree(nameSource);
+        }
+
+    }
+    psFree(specsIter);
+    return true;
+}
+
+bool p_pmConceptsWriteToDefaults(const psMetadata *specs, const pmFPA *fpa, const pmChip *chip,
+                                 const pmCell *cell, psMetadata *concepts)
+{
+    PS_ASSERT_PTR_NON_NULL(specs, false);
+    PS_ASSERT_PTR_NON_NULL(concepts, false);
+
+    pmHDU *hdu = pmHDUGetLowest(fpa, chip, cell); // The HDU at the lowest level
+    if (!hdu) {
+        return false;
+    }
+    psMetadata *cameraFormat = hdu->format; // The camera format
+    bool mdok = true;                   // Status of MD lookup
+    psMetadata *defaults = psMetadataLookupMetadata(&mdok, cameraFormat, "DEFAULTS"); // The DEFAULTS spec
+    if (!mdok || !defaults) {
+        return false;
+    }
+
+    psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *specItem = NULL;    // Item from the specs metadata
+    while ((specItem = psMetadataGetAndIncrement(specsIter))) {
+        pmConceptSpec *spec = specItem->data.V; // The specification
+        psString name = specItem->name; // The concept name
+
+        psMetadataItem *defaultItem = p_pmConceptsReadSingleFromDefaults(name, defaults, fpa, chip, cell);
+        if (!defaultItem) {
+            continue;
+        }
+        psMetadataItem *conceptItem = psMetadataLookup(concepts, name); // The item from the concepts
+        psMetadataItem *formatted = conceptFormat(spec, conceptItem, PM_CONCEPT_SOURCE_DEFAULTS,
+                                                  cameraFormat, fpa, chip, cell);
+        if (!formatted) {
+            continue;
+        }
+
+        if (strcmp(defaultItem->name, name) != 0) {
+            // Correct the name to match the concept name
+            defaultItem = psMetadataItemCopy(defaultItem);
+            psFree(defaultItem->name);
+            defaultItem->name = psStringCopy(name);
+        } else {
+            psMemIncrRefCounter(defaultItem);
+        }
+
+        if (!compareConcepts(formatted, defaultItem)) {
+            psWarning("Concept %s is specified by the DEFAULTS in the camera "
+                      "format, but the values don't match.\n", name);
+        }
+        psFree(defaultItem);
+        psFree(formatted);
+    }
+    psFree(specsIter);
+    return true;
+}
+
+
+bool p_pmConceptsWriteToHeader(const psMetadata *specs, const pmFPA *fpa, const pmChip *chip,
+                               const pmCell *cell, const psMetadata *concepts)
+{
+    PS_ASSERT_PTR_NON_NULL(specs, false);
+    PS_ASSERT_PTR_NON_NULL(concepts, false);
+
+    pmHDU *hdu = pmHDUGetLowest(fpa, chip, cell); // The HDU at the lowest level
+    if (!hdu) {
+        return false;
+    }
+    psMetadata *cameraFormat = hdu->format; // The camera format
+    bool mdok = true;                   // Status of MD lookup
+    psMetadata *translation = psMetadataLookupMetadata(&mdok, cameraFormat, "TRANSLATION"); // The TRANSLATION spec
+    if (!mdok || !translation) {
+        return false;
+    }
+
+    psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *specItem = NULL;    // Item from the specs metadata
+    while ((specItem = psMetadataGetAndIncrement(specsIter))) {
+        pmConceptSpec *spec = specItem->data.V; // The specification
+        psString name = specItem->name; // The concept name
+        psMetadataItem *headerItem = psMetadataLookup(translation, name); // The item from the TRANSLATION
+        if (!headerItem) {
+            continue;
+        }
+        if (headerItem->type == PS_DATA_METADATA) {
+            // This is a menu
+            psTrace("psModules.concepts", 5, "%s is of type METADATA.\n", name);
+            headerItem = p_pmConceptsDepend(name, headerItem->data.md, translation, fpa, chip, cell);
+            if (!headerItem) {
+                continue;
+            }
+        }
+        if (headerItem->type != PS_DATA_STRING) {
+            psWarning("TRANSLATION keyword for concept %s isn't of type STR --- ignored.", name);
+            continue;
+        }
+        psTrace("psModules.concepts", 3, "Writing %s to header %s\n", name, headerItem->data.str);
+        psMetadataItem *conceptItem = psMetadataLookup(concepts, name); // The item from the concepts
+        psMetadataItem *formatted = conceptFormat(spec, conceptItem, PM_CONCEPT_SOURCE_HEADER,
+                                                  cameraFormat, fpa, chip, cell);
+        if (!formatted) {
+            continue;
+        }
+        writeHeader(hdu, headerItem->data.V, formatted);
+        psFree(formatted);
+    }
+    psFree(specsIter);
+    return true;
+}
+
+// XXX Warning: This code has not been tested at all
+bool p_pmConceptsWriteToDatabase(const psMetadata *specs, const pmFPA *fpa, const pmChip *chip,
+                                 const pmCell *cell, pmConfig *config, const psMetadata *concepts)
+{
+    PS_ASSERT_PTR_NON_NULL(specs, false);
+    PS_ASSERT_PTR_NON_NULL(concepts, false);
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    #ifndef HAVE_PSDB
+    return false;
+    #else
+
+    pmHDU *hdu = pmHDUGetLowest(fpa, chip, cell); // The HDU at the lowest level
+    if (!hdu) {
+        return false;
+    }
+    psMetadata *cameraFormat = hdu->format; // The camera format
+    bool mdok = true;                   // Status of MD lookup
+    psMetadata *database = psMetadataLookupMetadata(&mdok, cameraFormat, "DATABASE"); // The DATABASE spec
+    if (!mdok || !database) {
+        return false;
+    }
+    psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *specItem = NULL;    // Item from the specs metadata
+    while ((specItem = psMetadataGetAndIncrement(specsIter))) {
+        pmConceptSpec *spec = specItem->data.V; // The specification
+        psString name = specItem->name; // The concept name
+
+        psMetadataItem *dbItem = p_pmConceptsReadSingleFromDatabase(name, database, config, fpa, chip, cell);
+        if (!dbItem) {
+            continue;
+        }
+
+        psMetadataItem *conceptItem = psMetadataLookup(concepts, name); // The item from the concepts
+        psMetadataItem *formatted = conceptFormat(spec, conceptItem, PM_CONCEPT_SOURCE_DATABASE,
+                                                  cameraFormat, fpa, chip, cell);
+        if (!formatted) {
+            continue;
+        }
+
+        if (strcmp(dbItem->name, name) != 0) {
+            // Correct the name to match the concept name
+            dbItem = psMetadataItemCopy(dbItem);
+            psFree(dbItem->name);
+            dbItem->name = psStringCopy(name);
+        } else {
+            psMemIncrRefCounter(dbItem);
+        }
+
+        if (!compareConcepts(formatted, dbItem)) {
+            psWarning("Concept %s is specified by the DATABASE in the camera "
+                      "format, but the values don't match.\n", name);
+        }
+        psFree(dbItem);
+        psFree(formatted);
+    }
+    psFree(specsIter);
+    return true;
+    #endif
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsWrite.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsWrite.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/concepts/pmConceptsWrite.h	(revision 22158)
@@ -0,0 +1,61 @@
+/* @file  pmConceptsWrite.h
+ * @brief Writing concepts to a variety of sources.
+ *
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-06-17 22:16:38 $
+ * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_CONCEPTS_WRITE_H
+#define PM_CONCEPTS_WRITE_H
+
+/// @addtogroup Concepts Data Abstraction Concepts
+/// @{
+
+/// "Write" concepts to (actually, check against) the camera format file's CELLS.
+///
+/// Examines the CELLS metadata in the camera format file for the current type of cell, and checks that the
+/// concepts as defined there match the ones defined in the cell.  A warning is produced if the concepts do
+/// not match.
+bool p_pmConceptsWriteToCells(const psMetadata *specs, ///< The concept specifications
+                              const pmCell *cell, ///< The cell
+                              const psMetadata *concepts ///< The concepts
+                             );
+
+/// "Write" concepts to (actually, check against) the camera format file's DEFAULTS.
+///
+/// Examines the DEFAULTS metadata in the camera format file, and checks that the concepts as defined there
+/// match the ones defined in the cell.  A warning is produced if the concepts do not match.
+bool p_pmConceptsWriteToDefaults(const psMetadata *specs, ///< The concept specifications
+                                 const pmFPA *fpa, ///< The FPA
+                                 const pmChip *chip, ///< The chip
+                                 const pmCell *cell, ///< The cell
+                                 const psMetadata *concepts ///< The concepts
+                                );
+
+/// "Write" concepts to (actually, add to, pending a later write) the FITS header.
+///
+/// Examines the FITS header TRANSLATION metadata in the camera format file, and writes concepts to the
+/// appropriate FITS headers in the HDU, in preparation for a future write of the HDU.
+bool p_pmConceptsWriteToHeader(const psMetadata *specs, ///< The concept specifications
+                               const pmFPA *fpa, ///< The FPA
+                               const pmChip *chip, ///< The chip
+                               const pmCell *cell, ///< The cell
+                               const psMetadata *concepts ///< The concepts
+                              );
+
+/// Write concepts to the database.
+///
+/// Examines the DATABASE metadata in the camera format file, and writes concepts to the database.
+/// Warning: This function has not been tested; use at your own risk.
+bool p_pmConceptsWriteToDatabase(const psMetadata *specs, ///< The concept specifications
+                                 const pmFPA *fpa, ///< The FPA
+                                 const pmChip *chip, ///< The chip
+                                 const pmCell *cell, ///< The cell
+                                 pmConfig *config,///< Configuration
+                                 const psMetadata *concepts ///< The concepts
+                                );
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/config/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/config/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/config/.cvsignore	(revision 22158)
@@ -0,0 +1,8 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
+pmErrorCodes.c
+pmErrorCodes.h
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/config/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/config/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/config/Makefile.am	(revision 22158)
@@ -0,0 +1,33 @@
+noinst_LTLIBRARIES = libpsmodulesconfig.la
+
+libpsmodulesconfig_la_CPPFLAGS = $(SRCINC) $(PSMODULES_CFLAGS)
+libpsmodulesconfig_la_LDFLAGS  = -release $(PACKAGE_VERSION)
+libpsmodulesconfig_la_SOURCES  = \
+    pmConfig.c \
+    pmConfigRecipes.c \
+    pmConfigCamera.c \
+    pmConfigCommand.c \
+    pmConfigMask.c \
+    pmVersion.c \
+    pmErrorCodes.c
+
+pkginclude_HEADERS = \
+    pmConfig.h \
+    pmConfigRecipes.h \
+    pmConfigCamera.h \
+    pmConfigCommand.h \
+    pmConfigMask.h \
+    pmVersion.h \
+    pmErrorCodes.h
+
+# Error codes.
+BUILT_SOURCES = pmErrorCodes.h pmErrorCodes.c
+CLEANFILES = *~ pmErrorCodes.h pmErrorCodes.c
+
+pmErrorCodes.h : pmErrorCodes.dat pmErrorCodes.h.in
+	$(ERRORCODES) --data=pmErrorCodes.dat --outdir=. pmErrorCodes.h
+
+pmErrorCodes.c : pmErrorCodes.dat pmErrorCodes.c.in pmErrorCodes.h
+	$(ERRORCODES) --data=pmErrorCodes.dat --outdir=. pmErrorCodes.c
+
+EXTRA_DIST = pmErrorCodes.h.in pmErrorCodes.dat pmErrorCodes.c.in
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/config/notes.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/config/notes.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/config/notes.txt	(revision 22158)
@@ -0,0 +1,56 @@
+
+* current recipe load sequence:
+
+** load the basic config information.
+   (unless camera is explicitly specified, camera-specific recipes are not loaded)
+
+** save the generic command-line options (-D ..) on config->arguments:OPTIONS:(recipe)
+
+** supplement recipe with specific command-line options (-isdark...) to config->arguments:OPTIONS:(recipe)
+
+** SYSTEM
+** load all files from config->complete:RECIPES to config->recipes
+   (loadRecipeSystem)
+
+** CAMERA
+** load the recipes for the specified camera from the camera-specific
+   config file to config->recipes (overlay existing metadata)
+
+** CL:arguments
+** load recipe files defined on command line in the form -recipe-file (recipe) (filename)
+   from config->arguments:RECIPES
+   
+** CL:symbols
+** load symbolic recipes defined on command line in the form -recipe (recipe) (symbolic name)
+   from config->recipeSymbols
+
+** CL:options
+** load values defined on command line in the form -D key value
+   from config->arguments:OPTIONS:(recipe)
+
+---
+
+what we really want:
+
+** SYSTEM
+** load all files from config->complete:RECIPES to config->recipes
+   (loadRecipeSystem)
+
+** CAMERA
+** load the recipes for the specified camera from the camera-specific
+   config file to config->recipesCamera
+
+** CL:arguments
+** load recipe files defined on command line in the form -recipe-file (recipe) (filename)
+   from config->arguments:RECIPES
+   
+** CL:symbols
+** load symbolic recipes defined on command line in the form -recipe (recipe) (symbolic name)
+   from config->recipeSymbols
+
+** CL:options
+** load values defined on command line in the form -D key value
+   from config->arguments:OPTIONS:(recipe)
+
+metadata = psMetadataConfigRead (recipes/NAME.config)
+metadata = 
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfig.c	(revision 22158)
@@ -0,0 +1,1768 @@
+/** @file  pmConfig.h
+ *
+ *  @author PAP (IfA)
+ *  @author EAM (IfA)
+ *
+ *  Copyright 2007 Institute for Astronomy, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>            /* for strn?casecmp */
+#include <unistd.h>
+#include <libgen.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <glob.h>
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmErrorCodes.h"
+#include "pmFPALevel.h"
+#include "pmConfigRecipes.h"
+#include "pmConfigCamera.h"
+
+#ifdef HAVE_NEBCLIENT
+#include <nebclient.h>
+#endif // ifdef HAVE_NEBCLIENT
+
+#define IPPRC_ENV "IPPRC"        // Name of the environment variable containing the top-level config file
+#define IPPRC_FILE ".ipprc"      // Default top-level config file
+
+#define DEFAULT_LOG STDERR_FILENO       // Default file descriptor for log messages
+#define DEFAULT_TRACE STDERR_FILENO     // Default file descriptor for trace messages
+
+static bool readCameraConfig = true;    // Read the camera config on startup (with pmConfigRead)?
+static psArray *configPath = NULL;      // Search path for configuration files
+
+static bool checkPath(const char *filename, bool create, bool trunc);
+
+bool pmConfigReadParamsSet(bool newReadCameraConfig)
+{
+    bool oldReadCameraConfig = readCameraConfig;
+    readCameraConfig = newReadCameraConfig;
+    return oldReadCameraConfig;
+}
+
+static void configFree(pmConfig *config)
+{
+    psFree(config->user);
+    psFree(config->site);
+    psFree(config->system);
+    psFree(config->complete);
+    psFree(config->files);
+    psFree(config->camera);
+    psFree(config->cameraName);
+    psFree(config->format);
+    psFree(config->formatName);
+    psFree(config->recipes);
+    psFree(config->recipesCamera);
+    psFree(config->recipeSymbols);
+    psFree(config->arguments);
+    psFree(config->database);
+
+    // Close log and trace files
+    if (config->logFD != STDOUT_FILENO && config->logFD != STDERR_FILENO) {
+        close(config->logFD);
+    }
+    if (config->traceFD != STDOUT_FILENO && config->traceFD != STDERR_FILENO) {
+        close(config->traceFD);
+    }
+
+    return;
+}
+
+// Check the end of a string for a word; return the length of the string without the ending word
+// Used to identify the camera base name (e.g., "MEGACAM" out of "_MEGACAM-CHIP")
+int checkEndForWord(const char *line,   // String to check for ending word
+                    const char *word    // Ending word to check for
+                    )
+{
+    int wlen = strlen(word);            // Length of word
+    int nlen = strlen(line);            // Length of line
+    if (nlen < wlen) {
+        return 0;
+    }
+
+    char *ptr = (char *)line + nlen - wlen; // Expected position of ending word
+    if (strcasecmp(ptr, word)) {
+        return 0;
+    }
+
+    return (nlen - wlen);
+}
+
+// the camera name is of the form: BASE, BASE_CHIP, or BASE_FPA.  pull out BASE:
+char *cameraBaseName(const char *name   // Name of meta-camera
+                     )
+{
+    char *answer;
+
+    int N = checkEndForWord (name, "-CHIP");
+    if (N && name[0] == '_') {
+        psString answer = psStringNCopy(name + 1, N - 1);
+        return answer;
+    }
+
+    N = checkEndForWord(name, "-FPA");
+    if (N && name[0] == '_') {
+        psString answer = psStringNCopy(name + 1, N - 1);
+        return answer;
+    }
+
+    N = checkEndForWord(name, "-SKYCELL");
+    if (N && name[0] == '_') {
+        psString answer = psStringNCopy(name + 1, N - 1);
+        return answer;
+    }
+
+    answer = psStringCopy(name);
+    return answer;
+}
+
+
+pmConfig *pmConfigAlloc()
+{
+    pmConfig *config = psAlloc(sizeof(pmConfig));
+    (void)psMemSetDeallocator(config, (psFreeFunc)configFree);
+
+    // Initialise
+    config->user = NULL;
+    config->site = NULL;
+    config->system = NULL;
+    config->complete = NULL;
+    config->camera = NULL;
+    config->cameraName = NULL;
+    config->format = NULL;
+    config->formatName = NULL;
+    config->recipes = psMetadataAlloc();
+    config->recipesRead = PM_RECIPE_SOURCE_NONE;
+    config->recipesCamera = psMetadataAlloc();
+    config->recipeSymbols = psMetadataAlloc();
+    config->arguments = psMetadataAlloc();
+    config->database = NULL;
+    config->defaultRecipe = NULL;
+
+    config->traceFD = DEFAULT_TRACE;
+    config->logFD = DEFAULT_LOG;
+
+    // the file structure is used to carry pmFPAfiles
+    config->files = psMetadataAlloc ();
+    return config;
+}
+
+// Resolve environment variables within a directory name; returns the resolved directory string.
+// The returned string is likely a new pointer; the old pointer should be freed by psStringSubstitute.
+static psString resolveEnvVar(psString dir // Directory to check for environment variables
+                             )
+{
+    char *envStart;                     // Start of any environment variable
+    while ((envStart = strchr(dir, '$'))) {
+        char *envName = envStart + 1;   // Start of the environment variable name
+        if (envName[0] == '\0') {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Path %s contains a bad environment variable.\n", dir);
+            return NULL;
+        }
+        if (envName[0] == '{') {
+            envName++;
+            if (envName[0] == '\0') {
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                        "Path %s contains a bad environment variable.\n", dir);
+                return NULL;
+            }
+        }
+        char *envStop = strpbrk(envStart, "}/"); // End of the environment variable
+        ssize_t nameLength = envStop ? envStop - envName : strlen(envName); // Length of the name
+        psString name = psStringNCopy(envName, nameLength); // The environment variable name
+        char *value = getenv(name);     // Value of the environment variable
+        psFree(name);
+        psString valueSlash = NULL;    // Value with appended slash
+        psStringAppend(&valueSlash, "%s/", value);
+
+        ssize_t envvarLength = envStop ? envStop - envStart : strlen(envStart); // Length, w/o '}'
+        psString envvar = psStringNCopy(envStart, envvarLength + 1);  // Environment variable, with $, {, }
+
+        psTrace("psModules.config", 7, "Replacing %s with %s in directory %s\n", envvar, valueSlash, dir);
+        psStringSubstitute(&dir, valueSlash, envvar);
+        psFree(envvar);
+        psFree(valueSlash);
+    }
+
+    return dir;
+}
+
+
+void pmConfigSet(const char *path)
+{
+    PS_ASSERT_STRING_NON_EMPTY(path,);
+
+    assert (configPath == NULL);
+    // XXX why was this being called?  pmConfigSet should only be called once...
+    // pmConfigDone();
+
+    psList *list = psStringSplit(path, ":", false);
+    configPath = psListToArray(list);
+    // Resolve environment variables
+    for (long i = 0; i < configPath->n; i++) {
+        configPath->data[i] = resolveEnvVar(configPath->data[i]);
+        psTrace("psModules.config", 4, "Path %ld: %s\n", i, (char*)configPath->data[i]);
+    }
+    psFree(list);
+}
+
+void pmConfigDone(void)
+{
+    if (configPath) {
+        psFree(configPath);
+    }
+    configPath = NULL;
+
+    return;
+}
+
+bool pmConfigFileRead(psMetadata **config, const char *name, const char *description)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_STRING_NON_EMPTY(name, false);
+    PS_ASSERT_STRING_NON_EMPTY(description, false);
+
+    char *realName = NULL;
+    unsigned int numBadLines = 0;
+    struct stat filestat;
+
+    psTrace("psModules.config", 3, "Loading %s configuration from file %s\n",
+            description, name);
+
+    uid_t uid = getuid();
+    gid_t gid = getgid();
+
+    // we try: name, path[0]/name, path[1]/name, ...
+    // find the first existing entry in the path (starting with the bare name)
+    realName = psStringCopy (name);
+    psTrace ("psModules.config", 8, "trying %s\n", realName);
+
+    int status = stat (realName, &filestat);
+    if (status == 0) {
+        if ((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR)) {
+            goto found;
+        }
+        if ((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP)) {
+            goto found;
+        }
+        if (filestat.st_mode & S_IROTH) {
+            goto found;
+        }
+    }
+    psFree (realName);
+
+    if (configPath == NULL) {
+        psError(PS_ERR_IO, true, "Cannot find %s configuration file (%s) in path\n", description, name);
+        return false;
+    }
+
+    for (int i = 0; i < configPath->n; i++) {
+        realName = psStringCopy (configPath->data[i]);
+        psStringAppend (&realName, "/%s", name);
+        psTrace ("psModules.config", 8, "trying %s\n", realName);
+
+        status = stat (realName, &filestat);
+        if (status == 0) {
+            if ((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR)) {
+                goto found;
+            }
+            if ((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP)) {
+                goto found;
+            }
+            if (filestat.st_mode & S_IROTH) {
+                goto found;
+            }
+        }
+        psFree (realName);
+    }
+
+    psError(PS_ERR_IO, true, "Cannot find %s configuration file %s in path\n", description, name);
+    return false;
+
+found:
+    *config = psMetadataConfigRead(NULL, &numBadLines, realName, true);
+    if (numBadLines > 0) {
+        psError(PS_ERR_IO, false, "%d bad lines in %s configuration file (%s)",
+                numBadLines, description, realName);
+        psFree (realName);
+
+        return false;
+    }
+    if (!*config) {
+        psError(PS_ERR_IO, true, "Unable to read %s configuration from %s",
+                description, realName);
+        psFree (realName);
+        return false;
+    }
+
+    psFree (realName);
+    return true;
+}
+
+// Read a file into a metadataItem, if required
+static bool metadataItemReadFile(psMetadataItem *item, // Item into which to read file
+                                 const char *description // Description, for error messages
+    )
+{
+    assert(item);
+    assert(description);
+
+    if (item->type == PS_DATA_METADATA) {
+        return true;                    // We've already read it
+    }
+    if (item->type != PS_DATA_STRING) {
+        psTrace("config", 2, "Element %s in %s metadata is not of type STR.\n",
+                item->name, description);
+        return false;
+    }
+
+    psTrace("config", 2, "Reading %s %s: %s\n", description, item->name, item->data.str);
+    psMetadata *new = NULL;         // New metadata
+    if (!pmConfigFileRead(&new, item->data.str, item->name)) {
+        psError(PM_ERR_CONFIG, false, "Trouble reading reading %s %s.\n",
+                description, item->name);
+        psFree(new);
+        return false;
+    }
+
+    // Muck around under the hood to replace the filename with the metadata; don't try this at home, kids
+    item->type = PS_DATA_METADATA;
+    psFree(item->data.str);
+    item->data.md = new;
+
+    return true;
+}
+
+// Read metadata config files in a metadata
+// The metadata contains file names, which will be replaced with the metadata that are in the files.
+static bool metadataReadFiles(psMetadata *source, // Source metadata
+                              const char *description // Description, for error messages
+                             )
+{
+    assert(source);
+    psMetadataIterator *iter = psMetadataIteratorAlloc(source, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *item;               // Item from iteration
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        if (!metadataItemReadFile(item, description)) {
+            psError(PM_ERR_CONFIG, false, "Unable to read %s %s.", description, item->name);
+            psFree(iter);
+            return false;
+        }
+    }
+    psFree(iter);
+
+    return true;
+}
+
+// Read the formats for a camera
+static bool cameraReadFormats(psMetadata *camera, // Camera for which to read the formats
+                              const char *name // Name of the camera, for error messages
+                             )
+{
+    assert(camera);
+    assert(name);
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *formats = psMetadataLookupMetadata(&mdok, camera, "FORMATS"); // Formats
+    if (!mdok || !formats) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find FORMATS in camera configuration %s.\n", name);
+        return false;
+    }
+    if (!metadataReadFiles(formats, "camera format")) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read formats within camera configuration %s.\n", name);
+        return false;
+    }
+
+    return true;
+}
+
+// Read the calibrations for a camera
+static bool cameraReadCalibrations(psMetadata *camera, // Camera for which to read the formats
+                                   const char *cameraName // Name of the camera, for error messages
+    )
+{
+    assert(camera);
+    assert(cameraName);
+
+    psMetadataItem *darkNorm = psMetadataLookup(camera, "DARK.NORM"); // The dark normalisation calibration
+    if (darkNorm) {
+        if (darkNorm->type == PS_DATA_STRING) {
+            const char *darkNormName = darkNorm->data.str; // The file name
+            psTrace("config", 2, "Reading %s dark normalisation: %s\n", cameraName, darkNormName);
+            psMetadata *new = NULL;         // New metadata
+            if (!pmConfigFileRead(&new, darkNormName, "Dark normalisation")) {
+                psError(PM_ERR_CONFIG, false, "Trouble reading reading %s dark normalisation %s --- "
+                        "ignored.\n", cameraName, darkNormName);
+                psFree(new);
+                return false;
+            }
+
+            // Muck around under the hood to replace the filename with the metadata;
+            // don't try this at home, kids
+            darkNorm->type = PS_DATA_METADATA;
+            psFree(darkNorm->data.str);
+            darkNorm->data.md = new;
+        } else if (darkNorm->type != PS_DATA_METADATA) {
+            psWarning("DARK.NORM in camera %s is not of type STR or METADATA (%x)",
+                      cameraName, darkNorm->type);
+        }
+    } else {
+        // Add a dummy entry
+        psPolynomial1D *poly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 1); // Dummy polynomial
+        poly->coeff[0] = 0.0;
+        poly->coeff[1] = 1.0;
+        psMetadata *polyMD = psMetadataAlloc(); // Container for the polynomial
+        (void)psPolynomial1DtoMetadata(polyMD, poly, "_DEFAULT"); // Metadata to insert
+        psFree(poly);
+        psMetadataAddMetadata(camera, PS_LIST_TAIL, "DARK.NORM", 0, "Dark normalisation polynomial",
+                              polyMD);
+        psMetadataAddStr(camera, PS_LIST_TAIL, "DARK.NORM.KEY", 0, "Key for dark normalisation", "_DEFAULT");
+        psFree(polyMD);
+    }
+
+    return true;
+}
+
+pmConfig *pmConfigRead(int *argc, char **argv, const char *defaultRecipe)
+{
+    PS_ASSERT_PTR_NON_NULL(argc, NULL);
+    PS_ASSERT_INT_POSITIVE(*argc, NULL);
+    PS_ASSERT_PTR_NON_NULL(argv, NULL);
+
+    pmConfig *config = pmConfigAlloc(); // The configuration, containing site, camera and recipes
+    config->defaultRecipe = defaultRecipe;
+
+    // The following section of code attempts to determine which file to use as the
+    // top-level the configuration file.  At the end of this code block, the configFile
+    // variable will contain the name of the configuration file.
+
+    char *configFile = NULL;
+    //
+    // First, try command line
+    //
+    psS32 argNum = psArgumentGet(*argc, argv, "-ipprc");
+    if (argNum != 0) {
+        // remove the "-ipprc" argument from argv, check and remove filename
+        psArgumentRemove(argNum, argc, argv);
+        if (argNum >= *argc) {
+            psWarning("-ipprc command-line switch provided without the required filename --- ignored.\n");
+        } else {
+            configFile = psStringCopy(argv[argNum]);
+            psArgumentRemove(argNum, argc, argv);
+        }
+    }
+    //
+    // Next, try environment variable
+    //
+    if (!configFile) {
+        configFile = getenv(IPPRC_ENV);
+        if (configFile) {
+            configFile = psStringCopy (configFile);
+        }
+    }
+
+    //
+    // Last chance is ~/.ipprc
+    //
+    if (!configFile) {
+        char *home = getenv("HOME");
+        configFile = psStringCopy(home);
+        psStringAppend(&configFile, "/%s", IPPRC_FILE);
+    }
+
+    // We have the configuration filename; now we read and parse the config
+    // file and store in psMetadata struct user.
+    // XXX move this section to pmConfigReadUser.c ?
+
+    if (!pmConfigFileRead(&config->user, configFile, "user")) {
+        psFree(config);
+        psFree(configFile);
+        return NULL;
+    }
+    psFree(configFile);
+
+    // XXX why was this being called here?  Is someone calling pmConfigRead multiple times?
+    // pmConfigDone();
+    assert (configPath == NULL);
+
+    // define the config-file search path (configPath).
+    psString path = psMetadataLookupStr(NULL, config->user, "PATH");
+    pmConfigSet (path);
+
+    // read the SITE file
+    psString siteFile = psMetadataLookupStr(NULL, config->user, "SITE");
+    if (!pmConfigFileRead(&config->site, siteFile, "site")) {
+        psFree(config);
+        return NULL;
+    }
+
+    // load the SYSTEM file
+    psString systemFile = psMetadataLookupStr(NULL, config->user, "SYSTEM");
+    if (!pmConfigFileRead(&config->system, systemFile, "system")) {
+        psFree(config);
+        return NULL;
+    }
+
+    // interpolate USER, SITE and SYSTEM into the config->complete metadata
+    config->complete = psMetadataCopy (NULL,             config->user);
+    config->complete = psMetadataCopy (config->complete, config->site);
+    config->complete = psMetadataCopy (config->complete, config->system);
+
+    // Set LOG and TRACE options based on the user configuration.  These must be set AFTER
+    // the SITE and SYSTEM config files are read so path:// entries here can be resolved.
+    {
+        bool mdok = true;   // Status of MD lookup result
+
+        // Set logging level
+        int logLevel = psMetadataLookupS32(&mdok, config->user, "LOGLEVEL");
+        if (mdok && logLevel >= 0)
+        {
+            psTrace("psModules.config", 7, "Setting log level to %d\n", logLevel);
+            psLogSetLevel(logLevel);
+        }
+
+
+        // Set logging format
+        psString logFormat = psMetadataLookupStr(&mdok, config->user, "LOGFORMAT");
+        if (mdok && logFormat)
+        {
+            psTrace("psModules.config", 7, "Setting log format to %s\n", logFormat);
+            psLogSetFormat(logFormat);
+        }
+
+        // Set logging destination first from command line, second from user configuration
+        psString logDest = NULL;        // Logging destination
+        argNum = psArgumentGet(*argc, argv, "-log");
+        if (argNum > 0) {
+            psArgumentRemove(argNum, argc, argv);
+            if (argNum >= *argc) {
+                psWarning("-log command-line switch provided without the required log destination "
+                          "--- ignored.");
+            } else {
+                logDest = psStringCopy(argv[argNum]);
+                psArgumentRemove(argNum, argc, argv);
+            }
+        }
+        if (!logDest) {
+            logDest = psMemIncrRefCounter(psMetadataLookupStr(&mdok, config->user, "LOGDEST"));
+        }
+        if (logDest) {
+            psString resolved = pmConfigConvertFilename(logDest, config, true, false); // Resolved filename
+            if (!resolved || strlen(resolved) == 0) {
+                psWarning("Unable to resolve log destination: %s --- ignored", logDest);
+            } else {
+                config->logFD = psMessageDestination(resolved);
+            }
+            psFree(resolved);
+            psFree(logDest);
+        }
+        if (!psLogSetDestination(config->logFD)) {
+            psError(PS_ERR_IO, false, "Unable to set log destination to file number %d --- ignored",
+                    config->logFD);
+            psFree(config);
+            return NULL;
+        }
+
+        // Set trace levels
+        psMetadata *trace = psMetadataLookupMetadata(&mdok, config->user, "TRACE");
+        if (mdok && trace) {
+            psMetadataIterator *traceIter = psMetadataIteratorAlloc(trace, PS_LIST_HEAD, NULL); // Iterator
+            psMetadataItem *traceItem = NULL; // Item from MD iteration
+            while ((traceItem = psMetadataGetAndIncrement(traceIter))) {
+                if (traceItem->type != PS_DATA_S32) {
+                    psWarning("The level for trace component %s is not of type S32 (%x)\n",
+                             traceItem->name, traceItem->type);
+                    continue;
+                }
+                psTrace("psModules.config", 7, "Setting trace level for %s to %d\n",
+                        traceItem->name, traceItem->data.S32);
+                (void)psTraceSetLevel(traceItem->name, traceItem->data.S32);
+            }
+            psFree(traceIter);
+        }
+
+        // Set trace formats
+        psString traceFormat = psMetadataLookupStr(&mdok, config->user, "TRACEFORMAT");
+        if (mdok && traceFormat) {
+            psTrace("psModules.config", 7, "Setting trace format to %s\n", traceFormat);
+            (void)psTraceSetFormat(traceFormat);
+        }
+
+        // Set trace destinations
+        psString traceDest = NULL;      // Trace destination
+        argNum = psArgumentGet(*argc, argv, "-tracedest");
+        if (argNum > 0) {
+            psArgumentRemove(argNum, argc, argv);
+            if (argNum >= *argc) {
+                psWarning("-tracedest command-line switch provided without the required trace destination "
+                          "--- ignored.\n");
+            } else {
+                traceDest = psStringCopy(argv[argNum]);
+                psArgumentRemove(argNum, argc, argv);
+            }
+        }
+        if (!traceDest) {
+            traceDest = psMemIncrRefCounter(psMetadataLookupStr(&mdok, config->user, "TRACEDEST"));
+        }
+        if (traceDest) {
+            psString resolved = pmConfigConvertFilename(traceDest, config, true, false); // Resolved filename
+            if (!resolved || strlen(resolved) == 0) {
+                psWarning("Unable to resolve trace destination: %s --- ignored", traceDest);
+            } else {
+                config->traceFD = psMessageDestination(resolved);
+            }
+            psFree(resolved);
+            psFree(traceDest);
+        }
+        if (!psTraceSetDestination(config->traceFD)) {
+            psError(PS_ERR_IO, false, "Unable to set trace destination to file number %d --- ignored",
+                    config->traceFD);
+            psFree(config);
+            return NULL;
+        }
+
+        // Allow command line options to override defaults for logging.
+        // XXX: Is it appropriate to use the ArgVerbosity function for this?
+        //   A: it removes the options from the command line.
+        //   B: will the pmConfigRead function always be called on initialization.
+        //
+        psArgumentVerbosity(argc, argv);
+        // XXX: substitute the string for the default log level for "2".
+    }
+
+    // XXX read TIME from SITE (or system?)
+    {
+        bool mdok = true;
+
+        // Initialise the psLib time handling
+        // XXX is this still needed / desired?
+        psString timeName = psMetadataLookupStr(&mdok, config->complete, "TIME");
+        if (mdok && timeName)
+        {
+            psTrace("psModules.config", 7, "Initialising psTime with file %s\n", timeName);
+            psTimeInit(timeName);
+        }
+    }
+
+    // Next, we do a similar thing for the camera configuration file.  The
+    // file is read and parsed into psMetadata struct "camera".
+    argNum = psArgumentGet(*argc, argv, "-camera");
+    if (argNum > 0) {
+        psArgumentRemove(argNum, argc, argv);
+        if (argNum >= *argc) {
+            psWarning("-camera command-line switch provided without the required camera or filename --- "
+                      "ignored.\n");
+        } else {
+            bool mdok = true;           // Status of MD lookup
+            char *cameraName = argv[argNum]; // symbolic name of the camera
+
+            // look for the CAMERAS list in config->complete
+            psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->complete, "CAMERAS");
+            if (!cameras) {
+                psError(PS_ERR_IO, false, "Unable to find CAMERAS in site configuration.\n");
+                psFree(config);
+                return NULL;
+            }
+
+            // look for the symbolic camera name in the CAMERAS metadata
+            char *cameraFile = psMetadataLookupStr(&mdok, cameras, cameraName); // The filename
+            if (!cameraFile) {
+                psError(PS_ERR_IO, false, "%s is not listed in the site CAMERAS list\n", cameraName);
+                psFree(config);
+                return NULL;
+            }
+
+            // load this camera's configuration informatoin
+            if (!pmConfigFileRead(&config->camera, cameraFile, "camera")) {
+                psError(PM_ERR_CONFIG, false, "Problem reading %s", cameraName);
+                psFree(config);
+                return NULL;
+            }
+            // save the name for future uses
+            config->cameraName = psStringCopy (cameraName);
+
+            psArgumentRemove(argNum, argc, argv);
+
+            // Read in the formats
+            if (!cameraReadFormats(config->camera, cameraFile)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to read formats within camera configuration %s.\n",
+                        cameraFile);
+                psFree(config);
+                return NULL;
+            }
+
+            // Read in any camera-specific calibrations
+            if (!cameraReadCalibrations(config->camera, cameraName)) {
+                psError(PS_ERR_UNKNOWN, false,
+                        "Unable to read calibrations within camera configuration %s.\n",
+                        cameraName);
+                psFree(config);
+                return NULL;
+            }
+
+            psMetadataAddMetadata(cameras, PS_LIST_HEAD, cameraName, PS_META_REPLACE,
+                                  "Camera specified on command line", config->camera);
+
+            if (!pmConfigCameraSkycellVersion(config->complete, cameraName)) {
+                psError(PS_ERR_UNKNOWN, false,
+                        "Unable to generate skycell versions of specified camera %s.\n",
+                        cameraName);
+                psFree(config);
+                return NULL;
+            }
+
+            if (!pmConfigCameraMosaickedVersions(config->complete, cameraName)) {
+                psError(PS_ERR_UNKNOWN, false,
+                        "Unable to generate mosaicked versions of specified camera %s.\n",
+                        cameraName);
+                psFree(config);
+                return NULL;
+            }
+        }
+    }
+
+    // Read the camera configurations, if not already defined, and not turned off
+    if (!config->camera && readCameraConfig) {
+        bool mdok;                      // Status of MD lookup
+        psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->complete, "CAMERAS"); // List of cameras
+        if (!mdok || !cameras) {
+            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the system configuration.\n");
+            return false;
+        }
+
+        if (!metadataReadFiles(cameras, "camera configuration")) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to read cameras within system configuration.\n");
+            psFree(config);
+            return NULL;
+        }
+
+        // Now fill in the formats and calibrations
+        psMetadataIterator *iter = psMetadataIteratorAlloc(cameras, PS_LIST_HEAD, NULL); // Iterator
+        psMetadataItem *item;           // Item from iteration
+        while ((item = psMetadataGetAndIncrement(iter))) {
+            assert(item->type == PS_DATA_METADATA);
+            if (!cameraReadFormats(item->data.md, item->name)) {
+                psWarning("Unable to read formats for camera %s: removed.\n", item->name);
+                psErrorStackPrint(stderr, "errors from read failure\n");
+                psErrorClear();
+                psMetadataRemoveKey(cameras, item->name);
+                continue;
+            }
+            if (!cameraReadCalibrations(item->data.md, item->name)) {
+                psWarning("Unable to read calibrations for camera %s: removed.\n", item->name);
+                psErrorStackPrint(stderr, "errors from read failure\n");
+                psErrorClear();
+                psMetadataRemoveKey(cameras, item->name);
+                continue;
+            }
+        }
+        psFree(iter);
+
+        if (!pmConfigCameraSkycellVersionsAll(config->complete)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to generate skycell versions of cameras.\n");
+            psFree(config);
+            return NULL;
+        }
+        if (!pmConfigCameraMosaickedVersionsAll(config->complete)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to generate mosaicked versions of cameras.\n");
+            psFree(config);
+            return NULL;
+        }
+    }
+
+    // Load the recipes from the camera file, if appropriate
+    if(!pmConfigReadRecipes(config, PM_RECIPE_SOURCE_SYSTEM | PM_RECIPE_SOURCE_CAMERA)) {
+        psError(PS_ERR_IO, false, "Failed to read recipes from camera file");
+        psFree(config);
+        return NULL;
+    }
+
+    // load command-line options of the form -recipe NAME RECIPE
+    pmConfigLoadRecipeArguments(argc, argv, config);
+
+    // read in command-line options to specific recipe values
+    pmConfigLoadRecipeOptions(argc, argv, config, "-D");
+    pmConfigLoadRecipeOptions(argc, argv, config, "-Di");
+    pmConfigLoadRecipeOptions(argc, argv, config, "-Df");
+    pmConfigLoadRecipeOptions(argc, argv, config, "-Db");
+
+    // Look for command-line options for files to replace
+    argNum = psArgumentGet(*argc, argv, "-F");
+    if (argNum > 0) {
+        psArgumentRemove(argNum, argc, argv);
+        if (argNum + 1 >= *argc) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    "Filerule switch (-F) provided without old and new filerule.");
+            psFree(config);
+            return NULL;
+        }
+
+        const char *old = argv[argNum]; // The old file, to be replaced
+        psArgumentRemove(argNum, argc, argv);
+        const char *new = argv[argNum]; // The new file, the replacement
+        psArgumentRemove(argNum, argc, argv);
+
+        psMetadata *cameras = psMetadataLookupMetadata(NULL, config->complete, "CAMERAS"); // List of cameras
+        if (!cameras) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find CAMERAS in the site configuration.\n");
+            return false;
+        }
+
+        psMetadataIterator *camerasIter = psMetadataIteratorAlloc(cameras, PS_LIST_HEAD, NULL); // Iterator
+        psMetadataItem *cameraItem;     // Item from iteration
+        while ((cameraItem = psMetadataGetAndIncrement(camerasIter))) {
+            // Silently ignore problems --- they will be caught later, because if the user wants the nominated
+            // file and it's not available for that camera, then they will know.
+
+            if (cameraItem->type != PS_DATA_METADATA) {
+                psTrace("psModules.config", 2,
+                        "Entry %s in CAMERAS is not of type METADATA --- ignored.", cameraItem->name);
+                continue;
+            }
+            psMetadata *camera = cameraItem->data.md; // Camera configuration
+
+            psMetadata *newRule = pmConfigFileRule(config, camera, new); // The rule of interest
+            if (!newRule) {
+                psTrace("psModules.config", 2,
+                        "Unable to find filerule %s in camera %s --- ignored.", new, cameraItem->name);
+                continue;
+            }
+
+            // By calling pmConfigFileRule, we've assured that the FILERULES is now a metadata
+            psMetadata *filerules = psMetadataLookupMetadata(NULL, camera, "FILERULES"); // File rules
+            if (!filerules) {
+                psTrace("psModules.config", 2,
+                        "Can't find FILERULES of type METADATA in camera %s --- ignored.", cameraItem->name);
+                continue;
+            }
+
+            psMetadataAddMetadata(filerules, PS_LIST_TAIL, old, PS_META_REPLACE,
+                                  "Original replaced by -F option", newRule);
+        }
+        psFree(camerasIter);
+    }
+
+    // check for values that override DB* keywords
+    argNum = psArgumentGet(*argc, argv, "-dbserver");
+    if (argNum > 0) {
+        psArgumentRemove(argNum, argc, argv);
+        if (argNum >= *argc) {
+            psWarning("-dbserver command-line switch provided without the required server name --- ");
+        } else {
+            char *dbserver = argv[argNum]; // The camera configuration file to read
+            if (!psMetadataAddStr(config->complete, PS_LIST_TAIL, "DBSERVER", PS_META_REPLACE,
+                                  NULL, dbserver)) {
+                psWarning("Failed to overwrite .ipprc DBSERVER value");
+            }
+
+            psArgumentRemove(argNum, argc, argv);
+        }
+    }
+
+    argNum = psArgumentGet(*argc, argv, "-dbname");
+    if (argNum > 0) {
+        psArgumentRemove(argNum, argc, argv);
+        if (argNum >= *argc) {
+            psWarning("-dbname command-line switch provided without the required database name");
+        } else {
+            char *dbname = argv[argNum]; // The camera configuration file to read
+            if (!psMetadataAddStr(config->complete, PS_LIST_TAIL, "DBNAME", PS_META_REPLACE, NULL, dbname)) {
+                psWarning("Failed to overwrite .ipprc DBNAME value");
+            }
+
+            psArgumentRemove(argNum, argc, argv);
+        }
+    }
+
+    argNum = psArgumentGet(*argc, argv, "-dbuser");
+    if (argNum > 0) {
+        psArgumentRemove(argNum, argc, argv);
+        if (argNum >= *argc) {
+            psWarning("-dbuser command-line switch provided without the required database name");
+        } else {
+            char *dbuser = argv[argNum]; // The camera configuration file to read
+            if (!psMetadataAddStr(config->complete, PS_LIST_TAIL, "DBUSER", PS_META_REPLACE, NULL, dbuser)) {
+                psWarning("Failed to overwrite .ipprc DBUSER value");
+            }
+
+            psArgumentRemove(argNum, argc, argv);
+        }
+    }
+
+    argNum = psArgumentGet(*argc, argv, "-dbpassword");
+    if (argNum > 0) {
+        psArgumentRemove(argNum, argc, argv);
+        if (argNum >= *argc) {
+            psWarning("-dbpassword command-line switch provided without the required password");
+        } else {
+            char *dbpassword = argv[argNum]; // The camera configuration file to read
+            if (!psMetadataAddStr(config->complete, PS_LIST_TAIL, "DBPASSWORD", PS_META_REPLACE,
+                                  NULL, dbpassword)) {
+                psWarning("Failed to overwrite .ipprc DBPASSWORD value");
+            }
+
+            psArgumentRemove(argNum, argc, argv);
+        }
+    }
+
+    argNum = psArgumentGet(*argc, argv, "-dbport");
+    if (argNum > 0) {
+        psArgumentRemove(argNum, argc, argv);
+        if (argNum >= *argc) {
+            psWarning("-dbpport command-line switch provided without the required port number");
+        } else {
+            char *dbport = argv[argNum]; // The camera configuration file to read
+            if (!psMetadataAddS32(config->complete, PS_LIST_TAIL, "DBPORT", PS_META_REPLACE, NULL,
+                                  (psS32)atoi(dbport))) {
+                psWarning("Failed to overwrite .ipprc DBPORT value");
+            }
+
+            psArgumentRemove(argNum, argc, argv);
+        }
+    }
+
+    psErrorClear();   // we may have failed to find some items in the metadata
+
+    return config;
+}
+
+
+// does this header match the specified camera format?  answer is supplied to 'valid' the
+// return value defines the error condition. error only on config errors
+bool pmConfigValidateCameraFormat(bool *valid, const psMetadata *cameraFormat, const psMetadata *header)
+{
+    PS_ASSERT_PTR_NON_NULL(cameraFormat, false);
+    PS_ASSERT_PTR_NON_NULL(header, false);
+
+    // Read the rule for that camera format
+    bool mdStatus = true;
+
+    psMetadata *rule = psMetadataLookupMetadata(&mdStatus, cameraFormat, "RULE");
+    if (! mdStatus || ! rule) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read rule for camera.");
+        *valid = false;
+        return false;
+    }
+
+    // grab the metadata items in sequence by key so we get the MULTI entry
+    psList *keyList = psMetadataKeys (rule);
+    psArray *keys = psListToArray (keyList);
+    if (! keys) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read rule for camera.");
+        *valid = false;
+        return false;
+    }
+
+    *valid = true;
+    for (int i = 0; *valid && (i < keys->n); i++) {
+
+        // get the ruleItem for this key
+        psMetadataItem *ruleItem = psMetadataLookup(rule, keys->data[i]);
+
+        // Check for the existence of the rule in the header
+        psMetadataItem *headerItem = psMetadataLookup(header, ruleItem->name);
+        if (! headerItem) {
+            // rule item not found in header
+            psTrace("psModules.config.format", 5, "Can't find %s", ruleItem->name);
+            *valid = false;
+            continue;
+        }
+
+        // if the RULE type is a primitive type (int, float, etc) or string compare directly
+        if (PS_DATA_IS_PRIMITIVE (ruleItem->type) || (ruleItem->type == PS_DATA_STRING)) {
+            // Check to see if the rule works
+            if (!psMetadataItemCompare(headerItem, ruleItem)) {
+                psTrace("psModules.config.format", 5, "%s doesn't match.", ruleItem->name);
+                *valid = false;
+            }
+            continue;
+        }
+
+        // for MULTI, try each one & succeed if any match (valid = true is default state)
+        if (ruleItem->type == PS_DATA_METADATA_MULTI) {
+            bool found = false;
+            for (int j = 0; j < ruleItem->data.list->n; j++) {
+                psMetadataItem *entry = psListGet (ruleItem->data.list, j);
+                assert (entry);
+                if (psMetadataItemCompare(headerItem, entry)) {
+                    found = true;
+                    psTrace("psModules.config.format", 5, "%s in multi list matches.", ruleItem->name);
+                    break;
+                }
+            }
+            if (!found) {
+                *valid = false;
+                psTrace("psModules.config.format", 5, "%s doesn't match.", ruleItem->name);
+            }
+            continue;
+        }
+
+        psError(PS_ERR_UNKNOWN, false, "Invalid type for RULE %s.", ruleItem->name);
+        *valid = false;
+        psFree (keyList);
+        psFree (keys);
+        return false;
+    }
+
+    psFree (keyList);
+    psFree (keys);
+    return true;
+}
+
+// Given a camera and a header, see if any of the camera formats match the header
+// if so, return the winning format and the name of the winning format (both allocated here)
+static bool formatFromHeader(bool *status,
+                             psMetadata **format, // Format to return
+                             psString *name, // Name to return
+                             psMetadata *camera, // Camera configuration
+                             const psMetadata *header, // FITS header
+                             const char *cameraName // Name of camera
+                            )
+{
+    assert(format);
+    assert(camera);
+    assert(header);
+    assert(cameraName);
+    assert(*cameraName);
+
+    *status = true;                     // error status
+    bool result = false;                // Did we find the first match?
+
+    // Read the list of formats
+    bool mdok = true;                   // Status of MD lookup
+    psMetadata *formats = psMetadataLookupMetadata(&mdok, camera, "FORMATS"); // List of formats
+    if (!mdok || !formats) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to find list of FORMATS in camera %s", cameraName);
+        *status = false;
+        return false;
+    }
+
+    if (!metadataReadFiles(formats, "camera format")) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read cameras formats within camera configuration.\n");
+        *status = false;
+        return false;
+    }
+
+    // Iterate over the formats
+    psMetadataIterator *formatsIter = psMetadataIteratorAlloc(formats, PS_LIST_HEAD, NULL);
+    psMetadataItem *formatsItem = NULL; // Item from formats
+    while ((formatsItem = psMetadataGetAndIncrement(formatsIter))) {
+        assert(formatsItem->type == PS_DATA_METADATA); // Since we have just read it in or deleted it
+        psMetadata *testFormat = formatsItem->data.md; // Format to test against
+
+        psTrace("psModules.config.format", 5, "trying format %s", formatsItem->name);
+
+        bool valid = false;
+        if (!pmConfigValidateCameraFormat(&valid, testFormat, header)) {
+            psError (PS_ERR_UNKNOWN, false, "Error in config scripts for camera %s, format %s\n",
+                     cameraName, formatsItem->name);
+            *status = false;
+            return false;
+        }
+        if (valid) {
+            if (!*format) {
+                psLogMsg("psModules.config.format", PS_LOG_INFO, "Camera %s, format %s matches header.\n",
+                         cameraName, formatsItem->name);
+                *format = psMemIncrRefCounter(testFormat);
+                *name = psStringCopy(formatsItem->name);
+                result = true;
+            } else {
+                psWarning("Camera %s, format %s also matches header --- ignored.\n",
+                         cameraName, formatsItem->name);
+            }
+        }
+    }
+    psFree(formatsIter);
+    *status = true;
+    return result;
+}
+
+// determine the camera format based on the keywords in the header.  If we have already chosen
+// a camera, then we select the formats only from that camera, and the meta-cameras for that
+// camera.  If we are discovering the camera (config->camera == NULL), then we also load the
+// recipe files for the camera.
+psMetadata *pmConfigCameraFormatFromHeader(psMetadata **camera, psString *formatName, pmConfig *config,
+                                           const psMetadata *header, bool readRecipes)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_PTR_NON_NULL(header, NULL);
+
+    bool status = false;                // error status
+    psMetadata *format = NULL;          // The winning format
+    psString name = NULL;               // Name of the winning format
+
+    // If we don't know what sort of camera we have, we try all that we know
+    if (! config->camera) {
+        psAssert (!config->cameraName, "programming error: cameraName should be NULL if camera is undefined");
+        psAssert (!config->format,     "programming error: format should be NULL if camera is undefined");
+        psAssert (!config->formatName, "programming error: formatName should be NULL if camera is undefined");
+
+        bool mdok;                      // Metadata lookup status
+        psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->complete, "CAMERAS");
+        if (! mdok || !cameras) {
+            psError(PS_ERR_IO, true, "Unable to find CAMERAS in the configuration.");
+            return NULL;
+        }
+
+        if (!metadataReadFiles(cameras, "camera configuration")) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to read cameras within site configuration.\n");
+            return NULL;
+        }
+
+        // Iterate over the cameras
+        psMetadataIterator *camerasIter = psMetadataIteratorAlloc(cameras, PS_LIST_HEAD, NULL);
+        psMetadataItem *camerasItem = NULL; // Item from the metadata
+        while ((camerasItem = psMetadataGetAndIncrement(camerasIter))) {
+            // Open the camera information
+            psTrace("psModules.config.format", 3, "Inspecting camera %s (%s)\n", camerasItem->name,
+                    camerasItem->comment);
+            assert(camerasItem->type == PS_DATA_METADATA); // It should be because we've read it in or deleted
+            psMetadata *testCamera = camerasItem->data.md; // Camera to test against what we've got:
+            if (formatFromHeader(&status, &format, &name, testCamera, header, camerasItem->name)) {
+                config->camera = psMemIncrRefCounter(testCamera);
+                config->cameraName = psStringCopy(camerasItem->name);
+                config->formatName = name;
+                config->format = format;
+                if (camera) {
+                    *camera = psMemIncrRefCounter(testCamera);  // view on value saved on config
+                }
+                if (formatName) {
+                    *formatName = psMemIncrRefCounter(name);    // view on value saved on config
+                }
+            } else {
+                if (!status) {
+                    psError(PS_ERR_IO, false, "Error reading camera config data for %s", camerasItem->name);
+                    return NULL;
+                }
+            }
+        }
+        psFree(camerasIter);
+
+        // Done looking at all cameras
+        if (!config->camera) {
+            psError(PS_ERR_IO, false, "Unable to find a camera that matches input FITS header!");
+            return NULL;
+        }
+
+        // Now we have the camera, we can read the recipes
+        if (readRecipes && !pmConfigReadRecipes(config, PM_RECIPE_SOURCE_CAMERA | PM_RECIPE_SOURCE_CL)) {
+            psError(PS_ERR_IO, false, "Error reading recipes from camera config for %s", config->cameraName);
+            return NULL;
+        }
+        return psMemIncrRefCounter(format); // a second copy, since the first copy sits on config->format
+    }
+
+    // we have a config with a specified camera.  However, the supplied header may not
+    // correspond to this mosaic level for the camera.  We need to try the CHIP and FPA mosaic
+    // versions as well as the base version
+
+    psAssert (config->cameraName, "programming error: cameraName should not be NULL if camera is defined");
+    psAssert (config->format,     "programming error: format should not be NULL if camera is defined");
+    psAssert (config->formatName, "programming error: formatName should not be NULL if camera is defined");
+
+    // the camera name is of the form: BASE, BASE_CHIP, or BASE_FPA.  pull out BASE:
+    char *baseName = cameraBaseName (config->cameraName);
+
+    bool found = false;
+
+    psMetadata *testCamera = NULL;
+    char *testName = NULL;
+
+    psMetadata *cameras = psMetadataLookupMetadata (NULL, config->complete, "CAMERAS");
+    psAssert (cameras, "missing CAMERAS in complete metadata");
+
+    // try the FPA metaCamera
+    if (!found) {
+        testName = NULL;
+        psStringAppend (&testName, "_%s-FPA", baseName);
+
+        testCamera = psMetadataLookupMetadata (NULL, cameras, testName);
+        psAssert (testCamera, "missing %s in CAMERAS in complete metadata", testName);
+
+        bool status;
+        found = formatFromHeader(&status, &format, &name, testCamera, header, testName);
+        if (!found) psFree (testName);
+    }
+
+    // try the CHIP metaCamera
+    if (!found) {
+        testName = NULL;
+        psStringAppend (&testName, "_%s-CHIP", baseName);
+
+        testCamera = psMetadataLookupMetadata (NULL, cameras, testName);
+        psAssert (testCamera, "missing %s in CAMERAS in complete metadata", testName);
+
+        bool status;
+        found = formatFromHeader(&status, &format, &name, testCamera, header, testName);
+        if (!found) psFree (testName);
+    }
+
+    // try the SKYCELL metaCamera
+    if (!found) {
+        testName = NULL;
+        psStringAppend (&testName, "_%s-SKYCELL", baseName);
+
+        testCamera = psMetadataLookupMetadata (NULL, cameras, testName);
+        psAssert (testCamera, "missing %s in CAMERAS in complete metadata", testName);
+
+        bool status;
+        found = formatFromHeader(&status, &format, &name, testCamera, header, testName);
+        if (!found) psFree (testName);
+    }
+
+    // try the base name
+    if (!found) {
+        testName = psMemIncrRefCounter (baseName);
+
+        testCamera = psMetadataLookupMetadata (NULL, cameras, testName);
+        psAssert (testCamera, "missing %s in CAMERAS in complete metadata", testName);
+
+        bool status;
+        found = formatFromHeader(&status, &format, &name, testCamera, header, testName);
+    }
+
+    if (!found) {
+        psError(PS_ERR_IO, true, "Unable to find a format with the specified camera (%s) that matches the "
+                "given header.\n", baseName);
+        psFree (baseName);
+        return NULL;
+    }
+
+    psFree (name); // winning format name (for metaCamera) returned by formatFromHeader
+
+    psFree (baseName);
+    if (formatName) {
+        *formatName = testName;
+    } else {
+        psFree (testName);
+    }
+    if (camera) {
+        *camera = psMemIncrRefCounter(testCamera);
+    }
+    return format; // we do NOT need to incr ref counter: this is the only copy
+}
+
+// Return the requested camera configuration
+psMetadata *pmConfigCameraByName(pmConfig *config, const char *cameraName)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(cameraName, NULL);
+
+    psMetadata *cameras = psMetadataLookupMetadata(NULL, config->complete, "CAMERAS");
+    if (!cameras) {
+        psError(PS_ERR_IO, true, "Unable to find CAMERAS in the configuration.");
+        return NULL;
+    }
+
+    char *cameraPath = psMetadataLookupStr(NULL, cameras, cameraName);
+    if (!cameraPath) {
+        psError(PS_ERR_IO, true, "Unable to find requested CAMERA in the configuration.");
+        return NULL;
+    }
+
+    psMetadata *camera = NULL; // Camera to test against what we've got:
+
+    if (!pmConfigFileRead(&camera, cameraPath, cameraName)) {
+        psWarning("Trouble reading reading camera configuration %s", cameraName);
+        psFree(camera);
+        return NULL;
+    }
+
+    return camera;
+}
+
+psDB *pmConfigDB(pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_PTR_NON_NULL(config->complete, NULL);
+
+    #ifndef HAVE_PSDB
+
+    psError(PS_ERR_UNKNOWN, false,
+            "Cannot configure database: psModules was compiled without database support.");
+    return NULL;
+
+    #else
+
+    if (config->database) {
+        return config->database;
+    }
+
+    psBool mdStatus01 = false;
+    psBool mdStatus02 = false;
+    psBool mdStatus03 = false;
+    psBool mdStatus04 = false;
+    psBool mdStatus05 = false;
+
+    // XXX leaky strings
+    psString dbServer = psMetadataLookupStr(&mdStatus01, config->complete, "DBSERVER");
+    psString dbUsername = psMetadataLookupStr(&mdStatus02, config->complete, "DBUSER");
+    psString dbPassword = psMetadataLookupStr(&mdStatus03, config->complete, "DBPASSWORD");
+    psString dbName = psMetadataLookupStr(&mdStatus04, config->complete, "DBNAME");
+    psS32 dbPort = psMetadataLookupS32(&mdStatus05, config->complete, "DBPORT");
+    if (!mdStatus05) {
+        dbPort = 0;
+    }
+    if (!(mdStatus01 && mdStatus02 && mdStatus03 && mdStatus04)) {
+        psWarning("Could not determine database server, name, user, and password from site metadata.\n");
+        return NULL;
+    }
+
+    if (strcasecmp(dbName, "XXX") == 0 || strcasecmp(dbName, "NONE") == 0) {
+        psTrace("psModules.config", 1, "Database initialisation skipped: database is %s.", dbName);
+        return NULL;
+    }
+
+    config->database = psDBInit(dbServer, dbUsername, dbPassword, dbName, dbPort);
+    return config->database;
+    #endif
+}
+
+
+bool pmConfigConformHeader(psMetadata *header, const psMetadata *format)
+{
+    PS_ASSERT_PTR_NON_NULL(header, false);
+    PS_ASSERT_PTR_NON_NULL(format, false);
+
+    bool mdok = true;                   // Status of MD lookup
+    psMetadata *rules = psMetadataLookupMetadata(&mdok, format, "RULE"); // How to identify this format
+    if (!mdok || !rules) {
+        psError(PS_ERR_IO, true, "Unable to find RULE in camera format.\n");
+        return false;
+    }
+
+    psMetadataIterator *rulesIter = psMetadataIteratorAlloc(rules, PS_LIST_HEAD, NULL); // Iterator for rules
+    psMetadataItem *rulesItem = NULL;   // Item from iteration
+    while ((rulesItem = psMetadataGetAndIncrement(rulesIter))) {
+        // this will insert each of the MULTI entries, writing over the previous copies
+        if (PS_DATA_IS_PRIMITIVE (rulesItem->type) || (rulesItem->type == PS_DATA_STRING)) {
+            psMetadataItem *newItem = psMetadataItemCopy(rulesItem); // Copy of item
+            psMetadataAddItem(header, newItem, PS_LIST_TAIL, PS_META_REPLACE);
+            psFree(newItem);                // Drop reference
+            continue;
+        }
+
+        # if (0) // XXX not needed
+        // for MULTI entries, supply the first one
+        if (rulesItem->type == PS_DATA_METADATA_MULTI) {
+            psMetadataItem *entry = psListGet (rulesItem->data.list, PS_LIST_HEAD);
+            if (!entry) {
+                psError(PS_ERR_UNKNOWN, true, "No entries for MULTI RULE item.");
+                return false;
+            }
+            psMetadataItem *newItem = psMetadataItemCopy(entry); // Copy of item
+            psMetadataAddItem(header, newItem, PS_LIST_TAIL, PS_META_REPLACE);
+            psFree(newItem);                // Drop reference
+            continue;
+        }
+        # endif
+
+        psError(PS_ERR_UNKNOWN, false, "Invalid type for RULE %s.", rulesItem->name);
+        return false;
+    }
+    psFree(rulesIter);
+
+    return true;
+}
+
+psArray *pmConfigFileSets(int *argc, char **argv, const char *file, const char *list)
+{
+    PS_ASSERT_PTR_NON_NULL(argc, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(*argc, NULL);
+    PS_ASSERT_PTR_NON_NULL(argv, NULL);
+
+    int Narg;                           // Argument number
+
+    // we load all input files onto a psArray, to be parsed later
+    psArray *input = psArrayAllocEmpty(16);
+
+    // load the list of filenames the supplied file
+    // maybe a comma-separated list of words
+    // each word may be a glob: "file*.fits"
+    if (file && strlen(file) > 0 && (Narg = psArgumentGet (*argc, argv, file))) {
+
+        // select the word after 'file' and split by comma
+        psArgumentRemove (Narg, argc, argv);
+        psArray *words = psStringSplitArray (argv[Narg], ",", true);
+        psArgumentRemove (Narg, argc, argv);
+
+        // parse the word as a glob
+        glob_t globList;
+        for (int i = 0; i < words->n; i++) {
+            globList.gl_offs = 0;
+            glob (words->data[i], 0, NULL, &globList);
+
+            // if the glob does not match, save the literal word:
+            // otherwise save all glob matches
+            if (globList.gl_pathc == 0) {
+                psArrayAdd (input, 16, words->data[i]);
+            } else {
+                for (int j = 0; j < globList.gl_pathc; j++) {
+                    char *filename = psStringCopy (globList.gl_pathv[j]);
+                    psArrayAdd (input, 16, filename);
+                    psFree (filename);
+                }
+            }
+        }
+        psFree (words);
+    }
+
+    // load the list from the supplied text file
+    if (list && strlen(list) > 0 && (Narg = psArgumentGet(*argc, argv, list))) {
+        psArgumentRemove (Narg, argc, argv);
+        FILE *f = fopen(argv[Narg], "r");
+        if (!f) {
+            psError(PS_ERR_IO, true, "Unable to open specified list file");
+            psFree(input);
+            return NULL;
+        }
+
+        // XXX Reading the list should be reimplemented using psSlurp
+
+        char line[1024]; // XXX limits the list lines to 1024 chars
+        while (fgets(line, 1024, f) != NULL) {
+            char word[1024];
+            int nItems = sscanf(line, "%s", word);
+            switch (nItems) {
+              case 0:
+                break;
+              case 1: {
+                  psString filename = psStringCopy(word);
+                  psArrayAdd(input, 16, filename);
+                  psFree(filename);
+                  break;
+              }
+              default:
+                // rigid format, no comments allowed?
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to parse file list: spaces detected.");
+                psFree(input);
+                fclose(f);
+                return NULL;
+            }
+        }
+        psArgumentRemove(Narg, argc, argv);
+        fclose(f);
+    }
+
+    return input;
+}
+
+// XXX this is a prime example of the failing of our error-handling system.  this function has
+// three possible outcomes: the argument was found, it was not found, or we raised an error.
+// returning only the bool does not distinguish failure to find the argument from a deeper
+// error.  requiring the calling function to both test the bool AND trap the error stack is
+// fragile: the error stack may not have been cleared, or they may not do both.  in some
+// places, we solve this by returning two types of boolean status values.  a better option
+// might be to return a psErrorCode value (as RHL proposed), which would be 0 on success and
+// any of several options on failure.
+
+bool pmConfigFileSetsMD(psMetadata *metadata, int *argc, char **argv, const char *name,
+                        const char *file, const char *list)
+{
+    PS_ASSERT_PTR_NON_NULL(metadata, false);
+    PS_ASSERT_STRING_NON_EMPTY(name, NULL);
+
+    psErrorClear();   // pmConfigFileSets may or may not call psError, so
+    // if files->n == 0 we'll want to call psError(..., false, ...)
+    psArray *files = pmConfigFileSets(argc, argv, file, list);
+    if (!files) {
+        psAbort("error parsing argument list");
+        psError(PS_ERR_IO, false, "error parsing argument list");
+        psFree (files);
+        return false;
+    }
+
+    // no files found: this is not really an error
+    if (files->n == 0) {
+        psFree (files);
+        return false;
+    }
+
+    psMetadataAddPtr(metadata, PS_LIST_TAIL, name,  PS_DATA_ARRAY, "", files);
+    psFree (files);
+    return true;
+}
+
+// convert the supplied name, create a new output psString
+psString pmConfigConvertFilename(const char *filename, const pmConfig *config, bool create, bool trunc)
+{
+    PS_ASSERT_STRING_NON_EMPTY(filename, NULL);
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    // strip file:// from front of name
+    if (!strncasecmp(filename, "file:", strlen("file:"))) {
+        psString newName = psStringCopy(filename);
+
+        char *point = newName + strlen("file:");
+        while (*point == '/')
+            point ++;
+        char *tmpName = NULL;
+        psStringAppend (&tmpName, "/%s", point);
+        psFree (newName);
+        newName = tmpName;
+
+        if (!checkPath(newName, create, trunc)) {
+            // let checkPath()'s psError() call float up
+            psFree (newName);
+            return NULL;
+        }
+
+        return newName;
+    }
+
+    // replace path://PATH with matched datapath
+    if (!strncasecmp(filename, "path://", strlen("path://"))) {
+        PS_ASSERT_METADATA_NON_NULL(config->complete, NULL);
+
+        psString newName = psStringCopy(filename);
+
+        // filename should be of the form: path://PATH/rest/of/file
+        // replace PATH with matching name from config->complete:DATAPATH
+        psMetadata *datapath = psMetadataLookupPtr (NULL, config->complete, "DATAPATH");
+        if (datapath == NULL) {
+            psError(PS_ERR_UNKNOWN, true, "DATAPATH is not defined in config.site");
+            psFree (newName);
+            return NULL;
+        }
+
+        char *point = newName + strlen("path://");
+        char *mark = strchr (point, '/');
+        if (mark == NULL) {
+            psError(PS_ERR_UNKNOWN, true, "syntax error in PATH-style name %s", newName);
+            psFree (newName);
+            return false;
+        }
+
+        psString path = psStringNCopy (point, mark - point);
+        char *realpath = psMetadataLookupStr (NULL, datapath, path);
+        if (realpath == NULL) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "path (%s) not defined in config.site:DATAPATH for PATH-style name %s",
+                    path, newName);
+            psFree(newName);
+            psFree(path);
+            return false;
+        }
+        psFree(path);
+
+        char *tmpName = NULL;
+        psStringAppend(&tmpName, "%s/%s", realpath, mark + 1);
+        psFree(newName);
+        newName = tmpName;
+
+        if (!checkPath(newName, create, trunc)) {
+            // let checkPath()'s psError() call float up
+            psFree (newName);
+            return NULL;
+        }
+
+        return newName;
+    }
+
+    // substitute neb://name with matched nebulous name
+    if (!strncasecmp(filename, "neb://", strlen("neb://"))) {
+        #ifdef HAVE_NEBCLIENT
+
+        bool status = false;
+        psString neb_server = NULL;
+
+        // check the env first
+        neb_server = getenv("NEB_SERVER");
+
+        // if env isn't set, check the config system
+        if (!neb_server) {
+            neb_server = psMetadataLookupStr(&status, config->complete, "NEB_SERVER");
+            if (!status) {
+                psError(PM_ERR_CONFIG, true, "failed to lookup config value for NEB_SERVER.");
+                return NULL;
+            }
+        }
+
+        if (!neb_server) {
+            psError(PM_ERR_CONFIG, true, "Could not determine nebulous server URI.");
+            return NULL;
+        }
+
+        nebServer *server = nebServerAlloc(neb_server);
+        if (!server) {
+            psError(PM_ERR_SYS, true, "failed to create a nebServer object: %s", nebErr(server));
+            nebServerFree(server);
+            return NULL;
+        }
+
+        char *nebfile = NULL;
+        if (!(nebfile = nebFind(server, filename))) {
+            // object does not exist
+            if (create) {
+                nebfile = nebCreate(server, filename, NULL, NULL);
+                if (!nebfile) {
+                    psError(PM_ERR_SYS, true, "failed to create a new nebulous key: %s", nebErr(server));
+                    nebServerFree(server);
+                    return NULL;
+                }
+            } else {
+                // if the object does not exist and create isn't set, then we
+                // should puke
+                psError(PM_ERR_SYS, true, "Unable to access file %s", filename);
+                nebServerFree(server);
+                return NULL;
+            }
+        }
+
+        // convert nebfile into a psString
+        psString path = psStringCopy(nebfile);
+        nebFree(nebfile);
+        nebServerFree(server);
+
+        if (trunc) {
+            if(truncate(path, 0) != 0) {
+                psError(PS_ERR_IO, true, "Failed to truncate Nebulous file %s (real name %s)\n", filename, path);
+                return NULL;
+            }
+        }
+
+        return path;
+
+        #else // ifdef HAVE_NEBCLIENT
+
+        psError(PM_ERR_PROG, true, "psModules was compiled without nebulous support.");
+        return NULL;
+        #endif // ifdef HAVE_NEBCLIENT
+
+    }
+
+    // if we go this far, do nothing
+    return psStringCopy(filename);
+}
+
+psMetadata *pmConfigFileRule(const pmConfig *config, const psMetadata *camera, const char *name)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_METADATA_NON_NULL(camera, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(name, NULL);
+
+    psMetadataItem *item = psMetadataLookup(camera, "FILERULES"); // Item with the file rule of interest
+    if (!item) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find FILERULES in the camera configuration.");
+        return NULL;
+    }
+
+    if (!metadataItemReadFile(item, "file rules ")) {
+        psError(PM_ERR_CONFIG, false, "Unable to read file rules for camera.");
+        return NULL;
+    }
+
+    assert(item->type == PS_DATA_METADATA);
+    psMetadata *filerules = item->data.md; // File rules from the camera configuration
+
+    // select the name from the FILERULES
+    // check for alias name (type == STR, name is aliased name)
+    bool mdok;                          // Status of MD lookup
+    const char *realname = psMetadataLookupStr(&mdok, filerules, name); // Name of file rule to look up
+    if (!realname || strlen(realname) == 0) {
+        realname = name;
+    }
+
+    return psMetadataLookupMetadata(&mdok, filerules, realname);
+}
+
+psMetadata *pmConfigFitsType (const pmConfig *config, const psMetadata *camera, const char *fitsType)
+{
+    bool mdok;
+
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_METADATA_NON_NULL(camera, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(fitsType, NULL);
+
+    psMetadataItem *item = psMetadataLookup(camera, "FITSTYPES"); // Item with the file rule of interest
+    if (!item) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find FITSTYPES in the camera configuration.");
+        return NULL;
+    }
+
+    if (!metadataItemReadFile(item, "FITS Types")) {
+        psError(PM_ERR_CONFIG, false, "Unable to read fits types for camera.");
+        return NULL;
+    }
+
+    assert(item->type == PS_DATA_METADATA);
+    psMetadata *fitstypes = item->data.md; // FITS Types from the camera configuration
+
+    // select the name from the FITSTYPES
+    psMetadata *scheme = psMetadataLookupMetadata(&mdok, fitstypes, fitsType);
+    if (!scheme) {
+        psWarning("Unable to find specified FITS Type %s in camera configuration.", fitsType);
+        return NULL;
+    }
+
+    return scheme;
+}
+
+static bool checkPath(const char *filename, bool create, bool trunc)
+{
+    PS_ASSERT_PTR_NON_NULL(filename, false);
+
+    if (access(filename, R_OK) == 0) {
+        // file already exists
+        if (trunc) {
+            if(truncate(filename, 0) != 0) {
+                psError(PS_ERR_IO, true, "Failed to truncate file, %s\n", filename);
+                return false;
+            }
+        }
+    } else {
+        // file does not exist
+        if (create) {
+            int fd = open(filename, O_WRONLY|O_CREAT, 0666);
+            if (fd == 0) {
+                psError(PS_ERR_IO, true, "Failed to close file, %s\n", filename);
+                return false;
+            }
+            if (close(fd) != 0) {
+                psError(PS_ERR_IO, true, "Failed to close file, %s\n", filename);
+                return false;
+            }
+        } else {
+            // if the file does not exist and create isn't set, then we
+            // should puke
+            psError(PS_ERR_IO, true, "Unable to access file %s", filename);
+            return false;
+        }
+    }
+
+    return true;
+}
+
+
+#if 0
+bool pmConfigDump(const pmConfig *config, const pmFPA *source, const char *outroot)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_STRING_NON_EMPTY(outroot, false);
+
+    pmFPAview *view = source ? pmFPAviewTop(source) : pmFPAviewAlloc(0);// View to top level
+    if (!view) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to determine top view for FPA.");
+        return false;
+    }
+
+    psMetadata *dumpRules = psMetadataLookupMetadata(NULL, config->system, "CONFIG.RULES"); // Name rules
+    if (!dumpRules) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to find CONFIG.RULES in system configuration");
+        psFree(view);
+        return false;
+    }
+
+    const char *name =
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfig.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfig.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfig.h	(revision 22158)
@@ -0,0 +1,186 @@
+/*  @file pmConfig.h
+ *  @brief Configuration functions
+ *
+ *  @author Paul Price, IfA
+ *  @author Eugene Magnier, IfA
+ *
+ *  @version $Revision: 1.38 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-06-10 21:53:09 $
+ *  Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_CONFIG_H
+#define PM_CONFIG_H
+
+/// @addtogroup Config Configuration System
+/// @{
+
+/// Sources for recipes.
+///
+/// Defines what recipe sources have been read.  This allows us to read recipes from different sources as they
+/// become available.  For example, we may not have access to the camera configuration until we have read a
+/// FITS file.  We allow symbolic links, which means the user can specify on the command-line the name of a
+/// recipe that's defined elsewhere, instead of typing the entire filename.  This structure is private to
+/// psModules --- there is no need for the user to know about it.
+typedef enum {
+    PM_RECIPE_SOURCE_NONE        = 0x00, ///< None yet
+    PM_RECIPE_SOURCE_SYSTEM      = 0x01, ///< System configuration
+    PM_RECIPE_SOURCE_CAMERA      = 0x02, ///< Camera configuration
+    PM_RECIPE_SOURCE_CL          = 0x04, ///< Command-line
+    PM_RECIPE_SOURCE_SYMBOLIC    = 0x14, ///< Symbolic link, specified on command-line
+    PM_RECIPE_SOURCE_ALL         = 0xff  ///< All sources
+} pmRecipeSource;
+
+/// Configuration information
+///
+/// This structure stores the configuration information: user, site, system, camera and recipe configuration, the
+/// command-line arguments, the pmFPAfiles used, and the database handle.
+typedef struct {
+    psMetadata *user;                 	///< User configuration
+    psMetadata *site;                 	///< Site configuration
+    psMetadata *system;               	///< System configuration
+    psMetadata *complete;               ///< Full merged configuration
+    psMetadata *camera;                 ///< Camera specification
+    psString cameraName;                ///< Camera name
+    psMetadata *format;                 ///< Camera format description
+    psString formatName;                ///< Camera format name
+    psMetadata *recipes;                ///< Recipes for processing
+    psMetadata *recipesCamera;          ///< Recipes for processing
+    psMetadata *arguments;              ///< Processed command-line arguments
+    psMetadata *files;                  ///< pmFPAfiles used for analysis
+    psDB *database;                     ///< Database handle
+    const char *defaultRecipe;          ///< name of top-level recipe for this program
+    // Private members
+    pmRecipeSource recipesRead;         ///< Which recipe sources have been read
+    psMetadata *recipeSymbols;          ///< Where each recipe came from
+    int traceFD;                        ///< File descriptor for trace messages
+    int logFD;                          ///< File descriptor for log messages
+} pmConfig;
+
+/// Allocator for pmConfig
+pmConfig *pmConfigAlloc();
+
+/// Set static configuration information
+///
+/// The search path for the configuration files is a local static variable, set by this function.
+void pmConfigSet(const char *path ///< Search paths for configuration files; colon-delimited directories
+                );
+
+/// Free static memory used in the configuration system
+void pmConfigDone(void);
+
+/// Read configuration information from the command line.
+///
+/// pmConfigRead loads the user configuration (the file name is specified by "-ipprc FILE" on the
+/// command-line, the IPPRC environment variable, or it is $HOME/.ipprc).  The configuration search path is
+/// set. The camera configuration is loaded if it is specified on the command line ("-camera
+/// CAMERA_FILE"). Recipes specified on the command line ("-recipe RECIPE_NAME RECIPE_SOURCE") are also
+/// loaded.  These command-line arguments are removed from from the command-line, to simplify parsing.  The
+/// psLib log, trace and time setups are also performed if specified in the user configuration.
+pmConfig *pmConfigRead(int *argc,       ///< Number of command-line arguments
+                       char **argv, ///< Array of command-line arguments
+                       const char *defaultRecipe ///< name of top-level recipe for this program
+                      );
+
+/// Read a configuration file
+///
+/// Read a metadata configuration file into the supplied metadata.  Produce an error and return false if
+/// there's a problem.
+bool pmConfigFileRead(psMetadata **config, ///< Config to output
+                      const char *name, ///< Name of file
+                      const char *description ///< Description of file
+                     );
+
+/// Validate a header against the camera format
+///
+/// Given a FITS header (the PHU header), check it against the RULE metadata contained within the camera
+/// format; return found = true if it matches. return false on serious errors
+bool pmConfigValidateCameraFormat(bool *valid,
+                                  const psMetadata *cameraFormat, ///< Camera format containing the RULE
+                                  const psMetadata *header // FITS header for the PHU
+                                 );
+
+/// Determine the camera format (and camera if unknown) from examining the header
+///
+/// Given a FITS header, check it against all known cameras (unless we already know which camera, from
+/// pmConfigRead) and all known formats for those cameras in order to identify which is appropriate.  The
+/// first matching format is accepted; further matches produce warnings.  The accepted camera is saved in the
+/// configuration.  The accepted format is returned.
+psMetadata *pmConfigCameraFormatFromHeader(psMetadata **camera, // selected camera (or meta-camera)
+					   psString *formatName, // selected format name
+					   pmConfig *config, ///< The configuration
+                                           const psMetadata *header, ///< The FITS header
+                                           bool readRecipes ///< optionally read the recipes as well as the format
+    );
+
+/// Return the camera configuration specified by name
+///
+/// Given a camera name, returns the camera configuration metadata.
+psMetadata *pmConfigCameraByName(pmConfig *config, ///< The configuration
+                                 const char *cameraName ///< The camera name header
+                                );
+
+/// Setup the database
+///
+/// Initialise the database connection using the DBSERVER, DBNAME, DBUSER, DBPASSWORD values provided in the
+/// site configuration.  Stores the database handle in the configuration, and also returns it.
+psDB *pmConfigDB(pmConfig *config       ///< Configuration
+                );
+
+/// Make the supplied header conform to the nominated camera format.
+///
+/// Given a FITS header, make it conform to the RULE in the specified camera format.  This is useful for
+/// switching between formats, or generating fake data that must be recognised by
+/// pmConfigCameraFormatFromHeader.
+bool pmConfigConformHeader(psMetadata *header, ///< Header to conform
+                           const psMetadata *format ///< Camera format
+                          );
+
+/// Read the command-line for files (or a text file containing a list of files)
+///
+/// Given the 'file' and 'list' arguments (e.g., "-file" and "-list"), find the arguments associated with
+/// these words and interpret them as lists of files.  Return an array of the resulting filenames.
+psArray *pmConfigFileSets(int *argc,    ///< Number of arguments (I/O)
+                          char **argv,  ///< Array of arguments
+                          const char *file, ///< CL argument specifying a filename
+                          const char *list ///< CL argument specifying a text file with a list of filenames
+                         );
+
+/// Stuff associated files from the command-line into a metadata
+///
+/// Calls pmConfigFileSets to parse the command line for filenames (or a list which provides filenames), and
+/// stuffs the array of filenames into the metadata under "name".
+bool pmConfigFileSetsMD(psMetadata *metadata, ///< Metadata into which to stuff the array
+                        int *argc,    ///< Number of arguments (I/O)
+                        char **argv,  ///< Array of arguments
+                        const char *name, ///< Name for array in the metadata
+                        const char *file, ///< CL argument specifying a filename
+                        const char *list ///< CL argument specifying a text file with a list of filenames
+                       );
+
+/// Convert the supplied name, create a new output psString
+psString pmConfigConvertFilename(
+    const char *filename,               ///< file path/URI
+    const pmConfig *config,             ///< configuration
+    bool create,                        ///< create the file if it doesn't exist
+    bool trunc                          ///< truncate the file (if it exists)
+);
+
+/// Set whether all config parameters are read on startup
+bool pmConfigReadParamsSet(bool newReadCameraConfig // Desired mode for camera configuration reading
+                          );
+
+/// Get the file rule of interest
+///
+/// Look up the name of the set of file rules to use, get that set from the system configuration, and return the
+/// appropriate rule from the set.
+psMetadata *pmConfigFileRule(const pmConfig *config, ///< Configuration
+                             const psMetadata *camera, ///< Camera configuration of interest
+                             const char *name ///< Name of rule to read
+    );
+
+// look up the specified fitstype, interpolating the file if needed
+psMetadata *pmConfigFitsType (const pmConfig *config, const psMetadata *camera, const char *fitsType);
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigCamera.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigCamera.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigCamera.c	(revision 22158)
@@ -0,0 +1,843 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>            /* for strn?casecmp */
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmVersion.h"
+#include "pmConcepts.h"
+#include "pmConfigCamera.h"
+
+#define TABLE_OF_CONTENTS "CONTENTS"    // Name for camera format metadata containing the contents
+#define CHIP_TYPES "CHIPS"              // Name for camera format metadata containing the chip types
+#define CELL_TYPES "CELLS"              // Name for camera format metadata containing the cell types
+
+// local helper functions defined below
+static void removeCellConceptsSources(psMetadata *source);
+static void removeChipConceptsSources(psMetadata *source);
+
+// Generate the skycell version of a named camera configuration
+bool pmConfigCameraSkycellVersion(psMetadata *system, // The system configuration
+                                  const char *name // Name of the un-mosaicked camera
+                                  )
+{
+    PS_ASSERT_METADATA_NON_NULL(system, false);
+    PS_ASSERT_STRING_NON_EMPTY(name, false);
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *cameras = psMetadataLookupMetadata(&mdok, system, "CAMERAS"); // List of cameras
+    if (!mdok || !cameras) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the system configuration.\n");
+        return false;
+    }
+    if (!pmConfigGenerateSkycellVersion(cameras, cameras, name, system)) {
+        psError(PS_ERR_UNKNOWN, true, "Failed to build skycell camera description for %s\n", name);
+        return false;
+    }
+    return true;
+}
+
+
+bool pmConfigCameraSkycellVersionsAll(psMetadata *system)
+{
+    PS_ASSERT_METADATA_NON_NULL(system, false);
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *cameras = psMetadataLookupMetadata(&mdok, system, "CAMERAS"); // List of cameras
+    if (!mdok || !cameras) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the system configuration.\n");
+        return false;
+    }
+
+    psMetadataIterator *camerasIter = psMetadataIteratorAlloc(cameras, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *camerasItem = NULL; // Item from iteration
+    psMetadata *new = psMetadataAlloc();// New cameras to add
+    while ((camerasItem = psMetadataGetAndIncrement(camerasIter))) {
+        assert(camerasItem->type == PS_DATA_METADATA); // Only metadata are allowed here!
+        if (!pmConfigGenerateSkycellVersion(cameras, new, camerasItem->name, system)) {
+            psError(PS_ERR_UNKNOWN, true, "Failed to build skycell camera description for %s\n",
+                    camerasItem->name);
+            return false;
+        }
+    }
+    psFree(camerasIter);
+
+    // Now put the new cameras at the top of the list of cameras, so they get recognised first
+    // Note: going from the top, and putting everything to the top as we get there, so that the last one on
+    // goes to the top.  This preserves the original order of the cameras, putting the skycell versions
+    // before the originals.
+    camerasIter = psMetadataIteratorAlloc(new, PS_LIST_HEAD, NULL); // Iterator
+    while ((camerasItem = psMetadataGetAndIncrement(camerasIter))) {
+        psMetadataAddItem(cameras, camerasItem, PS_LIST_HEAD, 0);
+    }
+    psFree(camerasIter);
+    psFree(new);
+
+    return true;
+}
+
+// Don't update these skycell concepts; last one MUST be 0 (i.e., NULL).
+const static char *skycellConceptsCell[] = { "CELL.BIASSEC", "CELL.TRIMSEC", "CELL.READDIR", "CELL.XPARITY",
+                                             "CELL.YPARITY", "CELL.X0", "CELL.Y0", 0 };
+const static char *skycellConceptsChip[] = { "CHIP.XPARITY", "CHIP.YPARITY", 0 };
+const static char *skycellConceptsFPA[] = { 0 };
+
+// What do we call the skycell concept in the FITS header?
+static const char *skycellConceptName(const char *name, // Name of concept
+                                      const char **concepts, // List of concepts NOT to update
+                                      const psMetadata *system // System configuration
+                                      )
+{
+    for (int i = 0; concepts[i]; i++) {
+        if (strcmp(name, concepts[i]) == 0) {
+            return NULL;
+        }
+    }
+
+    if (!system) {
+        return name;
+    }
+    bool mdok;                          // Status of MD lookup
+    psMetadata *skycells = psMetadataLookupMetadata(&mdok, system, "SKYCELLS"); // Skycell concept headers
+    if (!skycells) {
+        return name;
+    }
+    const char *keyword = psMetadataLookupStr(&mdok, skycells, name); // Keyword to use for this concept
+    if (!mdok || !keyword || strlen(keyword) == 0) {
+        return name;
+    }
+    return keyword;
+}
+
+
+// Generate a skycell version of a camera configuration
+bool pmConfigGenerateSkycellVersion(psMetadata *oldCameras, // Old list of camera configurations
+                                    psMetadata *newCameras, // New list of camera configurations
+                                    const char *name, // Name of original camera configuration
+                                    const psMetadata *system // System configuration
+                                    )
+{
+    assert(oldCameras);
+    assert(newCameras);
+    assert(name);
+
+    // See if the old one is there
+    psMetadata *camera = psMetadataLookupMetadata(NULL, oldCameras, name); // The camera configuration
+    if (!camera) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Can't find camera to be skycelled in camera list.");
+        return false;
+    }
+
+    // See if the new one is already there
+    psString newName = NULL;       // Name of skycelled camera
+    psStringAppend(&newName, "_%s-SKYCELL", name);
+    if (psMetadataLookup(oldCameras, newName)) {
+        return true;
+    }
+
+    psMetadata *new = psMetadataCopy(NULL, camera); // Copy of the camera description
+
+    // Fix the FPA description to contain a single chip with single cell
+    {
+        psMetadata *fpa = psMetadataAlloc();// The FPA description
+        psMetadataAddStr(fpa, PS_LIST_HEAD, "SkyChip", 0, "Single chip with single cell", "SkyCell");
+        psMetadataAddMetadata(new, PS_LIST_TAIL, "FPA", PS_META_REPLACE, "Description of FPA hierarchy", fpa);
+        psFree(fpa);
+    }
+
+    // Clear out the formats, replace them with the One True Format
+    psMetadata *formats = psMetadataLookupMetadata(NULL, new, "FORMATS"); // The list of formats
+    if (!formats) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Can't find FORMATS within camera configuration.");
+        psFree(new);
+        return false;
+    }
+    while (psListLength(formats->list) > 0) {
+        psMetadataRemoveIndex(formats, PS_LIST_HEAD);
+    }
+    psMetadata *format = psMetadataAlloc(); // The One True Format
+
+    {
+        psMetadata *rule = psMetadataAlloc(); // The RULE --- how to recognise the camera
+        psMetadataAddStr(rule, PS_LIST_TAIL, "PSCAMERA", 0, "Camera name", name);
+        psMetadataAddStr(rule, PS_LIST_TAIL, "PSFORMAT", 0, "Camera format", "SKYCELL");
+        psMetadataAddMetadata(format, PS_LIST_TAIL, "RULE", 0, "How to recognise this type of file", rule);
+        psFree(rule);
+    }
+
+    {
+        psMetadata *file = psMetadataAlloc(); // The FILE --- how to read the data
+        psMetadataAddStr(file, PS_LIST_TAIL, "PHU", 0, "What level the FITS file represents", "FPA");
+        psMetadataAddStr(file, PS_LIST_TAIL, "EXTENSIONS", 0, "What level the extensions represent", "NONE");
+        psMetadataAddStr(file, PS_LIST_TAIL, "FPA.OBS", 0, "PHU keyword for unique identifier", "FPA.OBS");
+        psMetadataAddMetadata(format, PS_LIST_TAIL, "FILE", 0, "How to read this type of file", file);
+        psFree(file);
+    }
+
+    psMetadataAddStr(format, PS_LIST_TAIL, "CONTENTS", 0, "What's in this type of file",
+                     "SkyChip:SkyCell:_skycell");
+
+    {
+        psMetadata *cells = psMetadataAlloc(); // The CELLS --- how to read the cells
+        psMetadata *skycell = psMetadataAlloc(); // How to read the skycell
+        psMetadataAddStr(skycell, PS_LIST_TAIL, "CELL.TRIMSEC", 0, "Trim section", "CELL.TRIMSEC");
+        psMetadataAddStr(skycell, PS_LIST_TAIL, "CELL.BIASSEC", 0, "Bias section", "CELL.BIASSEC");
+        psMetadataAddStr(skycell, PS_LIST_TAIL, "CELL.TRIMSEC.SOURCE", 0, "Source for trim section",
+                         "HEADER");
+        psMetadataAddStr(skycell, PS_LIST_TAIL, "CELL.BIASSEC.SOURCE", 0, "Source for bias section",
+                         "HEADER");
+        psMetadataAddMetadata(cells, PS_LIST_TAIL, "_skycell", 0, "Skycell specification", skycell);
+        psFree(skycell);
+        psMetadataAddMetadata(format, PS_LIST_TAIL, "CELLS", 0, "How to read the cells", cells);
+        psFree(cells);
+    }
+
+    // Stuffing all concepts into the header, by their PS concept name (e.g., "FPA.AIRMASS").
+    // (HIERARCH will take care of the long names, implemented in psLib.)
+    // Some people may not like this, but it's quick and easy and will do for now.
+    // An alternative may be provided later.
+    {
+        psMetadata *translation = psMetadataAlloc(); // The TRANSLATION --- how to read the FITS headers
+
+        psList *concepts;               // List of concepts for each level
+        psListIterator *iter;           // Iterator for concepts
+        psString name;                  // Concept name, from iteration
+
+        concepts = pmConceptsList(PM_FPA_LEVEL_FPA); // FPA-level concepts
+        iter = psListIteratorAlloc(concepts, PS_LIST_HEAD, false);
+        while ((name = psListGetAndIncrement(iter))) {
+            const char *new = skycellConceptName(name, skycellConceptsFPA, system); // Name for skycell
+            if (new) {
+                psMetadataAddStr(translation, PS_LIST_TAIL, name, 0, NULL, new);
+            }
+        }
+        psFree(iter);
+        psFree(concepts);
+
+        concepts = pmConceptsList(PM_FPA_LEVEL_CHIP);
+        iter = psListIteratorAlloc(concepts, PS_LIST_HEAD, false);
+        while ((name = psListGetAndIncrement(iter))) {
+            const char *new = skycellConceptName(name, skycellConceptsChip, system); // Name for skycell
+            if (new) {
+                psMetadataAddStr(translation, PS_LIST_TAIL, name, 0, NULL, new);
+            }
+        }
+        psFree(iter);
+        psFree(concepts);
+
+        concepts = pmConceptsList(PM_FPA_LEVEL_CELL);
+        iter = psListIteratorAlloc(concepts, PS_LIST_HEAD, false);
+        while ((name = psListGetAndIncrement(iter))) {
+            const char *new = skycellConceptName(name, skycellConceptsCell, system); // Name for skycell
+            if (new) {
+                psMetadataAddStr(translation, PS_LIST_TAIL, name, 0, NULL, new);
+            }
+        }
+        psFree(iter);
+        psFree(concepts);
+
+        psMetadataAddMetadata(format, PS_LIST_TAIL, "TRANSLATION", 0, "How to translate the FITS headers",
+                              translation);
+        psFree(translation);
+    }
+
+    {
+        psMetadata *defaults = psMetadataAlloc(); // Default values for concepts
+
+        psMetadataAddS32(defaults, PS_LIST_TAIL, "CELL.XPARITY", 0, NULL, 1);
+        psMetadataAddS32(defaults, PS_LIST_TAIL, "CELL.YPARITY", 0, NULL, 1);
+        psMetadataAddS32(defaults, PS_LIST_TAIL, "CHIP.XPARITY", 0, NULL, 1);
+        psMetadataAddS32(defaults, PS_LIST_TAIL, "CHIP.YPARITY", 0, NULL, 1);
+        psMetadataAddS32(defaults, PS_LIST_TAIL, "CELL.Y0", 0, NULL, 0);
+        psMetadataAddS32(defaults, PS_LIST_TAIL, "CELL.X0", 0, NULL, 0);
+        psMetadataAddS32(defaults, PS_LIST_TAIL, "CHIP.Y0", 0, NULL, 0);
+        psMetadataAddS32(defaults, PS_LIST_TAIL, "CHIP.X0", 0, NULL, 0);
+        psMetadataAddS32(defaults, PS_LIST_TAIL, "CELL.READDIR", 0, "Read direction (rows)", 1);
+
+        psMetadataAddMetadata(format, PS_LIST_TAIL, "DEFAULTS", 0, "Default values for concepts", defaults);
+        psFree(defaults);
+
+    }
+
+    {
+        psMetadata *database = psMetadataAlloc(); // Database values for concepts
+        psMetadataAddMetadata(format, PS_LIST_TAIL, "DATABASE", 0, "Database values for concepts", database);
+        psFree(database);
+    }
+
+    {
+        psMetadata *conceptFormats = psMetadataAlloc(); // Format peculiarities for various concepts
+        // These are the only essential formats
+        psMetadataAddStr(conceptFormats, PS_LIST_TAIL, "FPA.RA", 0, "Units for RA", "HOURS");
+        psMetadataAddStr(conceptFormats, PS_LIST_TAIL, "FPA.DEC", 0, "Units for RA", "DEGREES");
+        psMetadataAddStr(conceptFormats, PS_LIST_TAIL, "FPA.TIME", 0, "Format for time", "MJD");
+        psMetadataAddStr(conceptFormats, PS_LIST_TAIL, "CELL.TIME", 0, "Format for time", "MJD");
+
+        psMetadataAddMetadata(format, PS_LIST_TAIL, "FORMATS", 0, "Formats for various concepts",
+                              conceptFormats);
+        psFree(conceptFormats);
+    }
+
+    psMetadataAddMetadata(formats, PS_LIST_TAIL, "SKYCELL", 0, "The One True Format for skycells", format);
+    psFree(format);
+
+    // New camera MUST go to the head of the metadata, so that it will be recognised first
+    // The old camera doesn't contain the PSCAMERA and PSFORMAT headers, so it will match anything!
+    psMetadataAddMetadata(newCameras, PS_LIST_HEAD, newName, PS_META_REPLACE,
+                          "Automatically generated", new);
+    psFree(newName);
+    psFree(new);
+
+    return true;
+}
+
+// Generate the Chip and FPA mosaicked version of a named camera configuration
+bool pmConfigCameraMosaickedVersions(psMetadata *system, // The system configuration
+                                     const char *name // Name of the un-mosaicked camera
+                                    )
+{
+    PS_ASSERT_METADATA_NON_NULL(system, false);
+    PS_ASSERT_STRING_NON_EMPTY(name, false);
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *cameras = psMetadataLookupMetadata(&mdok, system, "CAMERAS"); // List of cameras
+    if (!mdok || !cameras) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the system configuration.\n");
+        return false;
+    }
+    if (!pmConfigGenerateMosaickedVersion(cameras, cameras, name, PM_FPA_LEVEL_CHIP)) {
+        psError(PS_ERR_UNKNOWN, true, "Failed to build Chip mosaic camera description for %s\n", name);
+        return false;
+    }
+    if (!pmConfigGenerateMosaickedVersion(cameras, cameras, name, PM_FPA_LEVEL_FPA)) {
+        psError(PS_ERR_UNKNOWN, true, "Failed to build FPA mosaic camera description for %s\n", name);
+        return false;
+    }
+    return true;
+}
+
+// the operation putting the new entries first is now implemented in pmConfigGenerateMosaickedVersion
+// Generate the Chip and FPA mosaicked version of a named camera configuration
+bool pmConfigCameraMosaickedVersionsAll(psMetadata *system)
+{
+    PS_ASSERT_METADATA_NON_NULL(system, false);
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *cameras = psMetadataLookupMetadata(&mdok, system, "CAMERAS"); // List of cameras
+    if (!mdok || !cameras) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the system configuration.\n");
+        return false;
+    }
+
+    psMetadataIterator *camerasIter = psMetadataIteratorAlloc(cameras, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *camerasItem = NULL; // Item from iteration
+    psMetadata *new = psMetadataAlloc();// New cameras to add
+    while ((camerasItem = psMetadataGetAndIncrement(camerasIter))) {
+        assert(camerasItem->type == PS_DATA_METADATA); // Only metadata are allowed here!
+        if (!pmConfigGenerateMosaickedVersion(cameras, new, camerasItem->name, PM_FPA_LEVEL_CHIP)) {
+            psError(PS_ERR_UNKNOWN, true, "Failed to build Chip mosaic camera description for %s\n", camerasItem->name);
+            return false;
+        }
+        if (!pmConfigGenerateMosaickedVersion(cameras, new, camerasItem->name, PM_FPA_LEVEL_FPA)) {
+            psError(PS_ERR_UNKNOWN, true, "Failed to build FPA mosaic camera description for %s\n", camerasItem->name);
+            return false;
+        }
+    }
+    psFree(camerasIter);
+
+    // Now put the new cameras at the top of the list of cameras, so they get recognised first
+    // Note: going from the top, and putting everything to the top as we get there, so that the last one on
+    // goes to the top.  This preserves the original order of the cameras, putting the mosaicked versions
+    // before the originals.
+    camerasIter = psMetadataIteratorAlloc(new, PS_LIST_HEAD, NULL); // Iterator
+    while ((camerasItem = psMetadataGetAndIncrement(camerasIter))) {
+        psMetadataAddItem(cameras, camerasItem, PS_LIST_HEAD, 0);
+    }
+    psFree(camerasIter);
+    psFree(new);
+
+    return true;
+}
+
+// Generate a mosaicked version of a camera configuration
+bool pmConfigGenerateMosaickedVersion(psMetadata *oldCameras, // Old list of camera configurations
+                                      psMetadata *newCameras, // New list of camera configurations
+                                      const char *name, // Name of original camera configuration
+                                      pmFPALevel mosaicLevel // Level to which we are mosaicking
+    )
+{
+    assert(oldCameras);
+    assert(newCameras);
+    assert(name);
+    assert(mosaicLevel == PM_FPA_LEVEL_CHIP || mosaicLevel == PM_FPA_LEVEL_FPA);
+
+    // Don't generate a mosaicked version of a skycell
+    if (name[0] == '_' && strlen(name) > 9 && strcmp(name + strlen(name) - 8, "-SKYCELL") == 0) {
+        return true;
+    }
+
+    // See if the old one is there
+    psMetadata *camera = psMetadataLookupMetadata(NULL, oldCameras, name); // The camera configuration
+    if (!camera) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Can't find camera to be mosaicked in camera list.");
+        return false;
+    }
+
+    // See if the new one is already there
+    psString newName = NULL;       // Name of mosaicked camera
+    psStringAppend(&newName, "_%s-%s", name, mosaicLevel == PM_FPA_LEVEL_CHIP ? "CHIP" : "FPA");
+    if (psMetadataLookup(oldCameras, newName)) {
+        return true;
+    }
+
+    psMetadata *new = psMetadataCopy(NULL, camera); // Copy of the camera description
+    bool mdok;                          // Status of MD lookups
+
+    // ** Fix up the contents of the FPA description to match the mosaicked camera **
+    // select the FPA description
+    psMetadata *fpa = psMetadataLookupMetadata(NULL, new, "FPA"); // FPA in the camera configuration
+    if (!fpa) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Can't find FPA within camera configuration.");
+        psFree(new);
+        return false;
+    }
+    switch (mosaicLevel) {
+        // For CHIP mosaic, replace the contents of each chip with a single cell
+      case PM_FPA_LEVEL_CHIP: {
+          psMetadataIterator *fpaIter = psMetadataIteratorAlloc(fpa, PS_LIST_HEAD, NULL); // Iterator
+          psMetadataItem *fpaItem = NULL;     // Item from iteration
+          while ((fpaItem = psMetadataGetAndIncrement(fpaIter))) {
+              if (fpaItem->type != PS_DATA_STRING) {
+                  psError(PS_ERR_UNKNOWN, true,
+                          "Element %s within FPA in camera configuration is not of type STR.",
+                          fpaItem->name);
+                  psFree(new);
+                  return false;
+              }
+
+              psFree(fpaItem->data.str);
+              fpaItem->data.str = psStringCopy("MosaickedCell");
+              psFree(fpaItem->comment);
+              fpaItem->comment = psStringCopy("Mosaicked cell; automatically generated");
+          }
+          psFree(fpaIter);
+          break;
+      }
+        // For FPA mosaic, replace the contents of the FPA with a single chip containing a single cell
+      case PM_FPA_LEVEL_FPA: {
+          while (psListLength(fpa->list) > 0) {
+              psMetadataRemoveIndex(fpa, PS_LIST_TAIL);
+          }
+
+          psMetadataAddStr(fpa, PS_LIST_HEAD, "MosaickedChip", 0,
+                           "Mosaicked chip with mosaicked cell; automatically generated",
+                           "MosaickedCell");
+          break;
+      }
+    default:
+        psAbort("Should never get here.\n");
+    }
+
+    // ** Update the camera formats : add a new (mosaicked) format for each existing camera format **
+    // select the list of all camera formats
+    psMetadata *formats = psMetadataLookupMetadata(NULL, new, "FORMATS"); // FORMATS in the configuration
+    assert(formats);            // It had better be there --- we've already read them in
+    // loop over each of the formats
+    psMetadataIterator *formatsIter = psMetadataIteratorAlloc(formats, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *formatsItem = NULL; // Item from iteration
+    while ((formatsItem = psMetadataGetAndIncrement(formatsIter))) {
+        assert(formatsItem->type == PS_DATA_METADATA); // We should have read it by now!
+        psMetadata *format = formatsItem->data.md; // The camera format
+
+        // Add a new RULE which uniquely describes the mosaicked format.  this is needed so
+        // that when a mosaic is written to a FITS file, it can be recognised again when read.
+        psMetadata *rule = psMetadataLookupMetadata(NULL, format, "RULE"); // Way to identify format from PHU
+        if (!rule) {
+            // a camera format without a rule is not allowed.
+            psError(PS_ERR_UNKNOWN, false, "Camera format %s has no RULE", formatsItem->name);
+            return false;
+        }
+
+        // the new rule is supplemented by the mosaicLevel
+        switch (mosaicLevel) {
+        case PM_FPA_LEVEL_CHIP:
+            psMetadataAddStr(rule, PS_LIST_TAIL, "PSMOSAIC", 0, "Mosaicked level", "CHIP");
+            break;
+        case PM_FPA_LEVEL_FPA:
+            psMetadataAddStr(rule, PS_LIST_TAIL, "PSMOSAIC", 0, "Mosaicked level", "FPA");
+            break;
+        default:
+            psAbort("Should never get here.\n");
+        }
+
+        // Fix the FILE information: need to fix the levels for the PHU and EXTENSIONS.
+        // both of these elements are required in the format; we raise an error if they are not found
+        // If EXTENSIONS is NONE, then we need to change the CONTENT specifier to point to the chip name.
+        psMetadata *file = psMetadataLookupMetadata(NULL, format, "FILE"); // File information
+        if (!file) {
+            psError(PS_ERR_UNKNOWN, false, "Camera format %s has no FILE", formatsItem->name);
+            return false;
+        }
+        psMetadataItem *phuItem = psMetadataLookup(file, "PHU"); // PHU level
+        if (!phuItem || phuItem->type != PS_DATA_STRING) {
+            psError(PS_ERR_UNKNOWN, false, "Camera format %s is missing PHU in the FILE information", formatsItem->name);
+            return false;
+        }
+        psMetadataItem *extensionsItem = psMetadataLookup(file, "EXTENSIONS"); // Extensions level
+        if (!extensionsItem || extensionsItem->type != PS_DATA_STRING) {
+            psError(PS_ERR_UNKNOWN, false, "Camera format %s is missing EXTENSIONS in the FILE information", formatsItem->name);
+            return false;
+        }
+
+        // mosaicLevel == CHIP:
+        // Case    PHU     EXTENSIONS     Modifications
+        // ====    ===     ==========     ===========
+        // 1.      FPA     CHIP           NONE
+        // 2.      FPA     CELL           EXT->CHIP
+        // 3.      FPA     NONE           NONE
+        // 4.      CHIP    CELL           EXT->NONE
+        // 5.      CHIP    NONE           NONE
+        // 6.      CELL    NONE           PHU->CHIP
+        // possible outcomes:
+        //         FPA     CHIP
+        //         FPA     NONE
+        //         CHIP    NONE
+
+        // mosaicLevel == FPA:
+        // Case    PHU     EXTENSIONS     Modifications
+        // ====    ===     ==========     ===========
+        // 1.      FPA     CHIP           EXT->NONE
+        // 2.      FPA     CELL           EXT->NONE
+        // 3.      FPA     NONE           NONE
+        // 4.      CHIP    CELL           PHU->FPA, EXT->NONE
+        // 5.      CHIP    NONE           PHU->FPA
+        // 6.      CELL    NONE           PHU->FPA
+        // possible outcomes:
+        //         FPA     NONE
+
+        // modify the values of phuItem and extensionsItem
+        switch (mosaicLevel) {
+          case PM_FPA_LEVEL_CHIP:
+            if (!strcasecmp(phuItem->data.str, "FPA") && !strcasecmp(extensionsItem->data.str, "CHIP")) {
+                break;
+            }
+            if (!strcasecmp(phuItem->data.str, "FPA") && !strcasecmp(extensionsItem->data.str, "CELL")) {
+                psFree(extensionsItem->data.str);
+                extensionsItem->data.str = psStringCopy("CHIP");
+                break;
+            }
+            if (!strcasecmp(phuItem->data.str, "FPA") && !strcasecmp(extensionsItem->data.str, "NONE")) {
+                break;
+            }
+            if (!strcasecmp(phuItem->data.str, "CHIP") && !strcasecmp(extensionsItem->data.str, "CELL")) {
+                psFree(extensionsItem->data.str);
+                extensionsItem->data.str = psStringCopy("NONE");
+                break;
+            }
+            if (!strcasecmp(phuItem->data.str, "CHIP") && !strcasecmp(extensionsItem->data.str, "NONE")) {
+                break;
+            }
+            if (!strcasecmp(phuItem->data.str, "CELL") && !strcasecmp(extensionsItem->data.str, "NONE")) {
+                psFree(phuItem->data.str);
+                phuItem->data.str = psStringCopy("CHIP");
+                break;
+            }
+            psAbort ("should not reach here");
+
+          case PM_FPA_LEVEL_FPA:
+            if (!strcasecmp(phuItem->data.str, "FPA") && !strcasecmp(extensionsItem->data.str, "CHIP")) {
+                psFree(extensionsItem->data.str);
+                extensionsItem->data.str = psStringCopy("NONE");
+                break;
+            }
+            if (!strcasecmp(phuItem->data.str, "FPA") && !strcasecmp(extensionsItem->data.str, "CELL")) {
+                psFree(extensionsItem->data.str);
+                extensionsItem->data.str = psStringCopy("NONE");
+                break;
+            }
+            if (!strcasecmp(phuItem->data.str, "FPA") && !strcasecmp(extensionsItem->data.str, "NONE")) {
+                break;
+            }
+            if (!strcasecmp(phuItem->data.str, "CHIP") && !strcasecmp(extensionsItem->data.str, "CELL")) {
+                psFree(phuItem->data.str);
+                phuItem->data.str = psStringCopy("FPA");
+                psFree(extensionsItem->data.str);
+                extensionsItem->data.str = psStringCopy("NONE");
+                break;
+            }
+            if (!strcasecmp(phuItem->data.str, "CHIP") && !strcasecmp(extensionsItem->data.str, "NONE")) {
+                psFree(phuItem->data.str);
+                phuItem->data.str = psStringCopy("FPA");
+                break;
+            }
+            if (!strcasecmp(phuItem->data.str, "CELL") && !strcasecmp(extensionsItem->data.str, "NONE")) {
+                psFree(phuItem->data.str);
+                phuItem->data.str = psStringCopy("FPA");
+                break;
+            }
+            psAbort ("should not reach here");
+
+          default:
+            psAbort("Should never get here.\n");
+        }
+
+        // Fix up the CONTENTS to contain only the mosaicked cell for each chip
+        switch (mosaicLevel) {
+          case PM_FPA_LEVEL_FPA:
+            psMetadataAddStr(format, PS_LIST_TAIL, TABLE_OF_CONTENTS, PS_META_REPLACE, NULL,
+                             "MosaickedChip:MosaickedCell:_mosaic");
+            break;
+          case PM_FPA_LEVEL_CHIP:
+            if (!strcasecmp(phuItem->data.str, "FPA") && !strcasecmp(extensionsItem->data.str, "CHIP")) {
+                // ensure the value of CONTENT in the FILE section has the right value
+                psMetadataAddStr(file, PS_LIST_TAIL, "CONTENT", PS_META_REPLACE, "Key to CONTENTS menu",
+                                 "PS_CNTNT");
+                psMetadataAddStr(file, PS_LIST_TAIL, "CONTENT.RULE", PS_META_REPLACE,
+                                 "Rule to generate CONTENTS", "{CHIP.NAME}");
+
+                // List the chipName:chipType for each chip.
+                psMetadata *contents = psMetadataAlloc(); // List of contents, with chipName:chipType
+
+                // XXX this is using the fpaItem->name not the chipName
+                psMetadataIterator *fpaIter = psMetadataIteratorAlloc(fpa, PS_LIST_HEAD, NULL); // Iteratr
+                psMetadataItem *fpaItem;    // Item from iteration
+                while ((fpaItem = psMetadataGetAndIncrement(fpaIter))) {
+                    assert (fpaItem->type == PS_DATA_STRING);
+                    psString content = NULL; // Content to add
+                    psStringAppend(&content, "%s:_mosaicChip ", fpaItem->name);
+                    psMetadataAddStr(contents, PS_LIST_TAIL, fpaItem->name, 0, NULL, content);
+                    psFree(content);
+                }
+                psFree(fpaIter);
+                psMetadataAddMetadata(format, PS_LIST_TAIL, TABLE_OF_CONTENTS, PS_META_REPLACE,
+                                      "List of contents", contents);
+                psFree(contents);
+
+                psMetadata *chips = psMetadataAlloc(); // List of chip types, with cellName:cellType
+                psMetadataAddStr(chips, PS_LIST_TAIL, "_mosaicChip", 0, NULL,
+                                 "MosaickedCell:_mosaic");
+                psMetadataAddMetadata(format, PS_LIST_TAIL, CHIP_TYPES, PS_META_REPLACE,
+                                      "List of chip types", chips);
+                psFree(chips);
+                break;
+            }
+            if (!strcasecmp(phuItem->data.str, "FPA") && !strcasecmp(extensionsItem->data.str, "NONE")) {
+                // List the contents on a single line
+                psString contentsLine = NULL; // Contents of the PHU
+                psMetadataIterator *fpaIter = psMetadataIteratorAlloc(fpa, PS_LIST_HEAD, NULL); // Iteratr
+                psMetadataItem *fpaItem;    // Item from iteration
+                while ((fpaItem = psMetadataGetAndIncrement(fpaIter))) {
+                    assert (fpaItem->type == PS_DATA_STRING);
+                    psStringAppend(&contentsLine, "%s:MosaickedCell:_mosaic ", fpaItem->name);
+                }
+                psFree(fpaIter);
+                psMetadataAddStr(format, PS_LIST_TAIL, TABLE_OF_CONTENTS, PS_META_REPLACE,
+                                 NULL, contentsLine);
+                psFree(contentsLine);
+                break;
+            }
+            if (!strcasecmp(phuItem->data.str, "CHIP") && !strcasecmp(extensionsItem->data.str, "NONE")) {
+                // XXX recode this to match the structure above (FPA/CHIP)?
+                // select and remove the old contents
+                psMetadata *contents = psMetadataLookupMetadata(NULL, format, TABLE_OF_CONTENTS); // File contents
+                if (!contents) {
+                    psError(PS_ERR_UNKNOWN, false, "Couldn't find %s in the camera format %s.\n",
+                            TABLE_OF_CONTENTS, formatsItem->name);
+                    return false;
+                }
+
+                // replace chip type with _mosaicChip
+                psMetadataIterator *contentIter = psMetadataIteratorAlloc(contents, PS_LIST_HEAD, NULL); // Iterator
+                psMetadataItem *contentItem;    // Item from iteration
+                while ((contentItem = psMetadataGetAndIncrement(contentIter))) {
+                    assert (contentItem->type == PS_DATA_STRING);
+                    char *ptr = strchr (contentItem->data.str, ':');
+                    assert (ptr);
+                    psString content = psStringNCopy (contentItem->data.str, ptr - contentItem->data.str);
+                    psStringAppend(&content, ":_mosaicChip ");
+                    psFree (contentItem->data.str);
+                    contentItem->data.str = content;
+                }
+                psFree(contentIter);
+
+                # if (0)
+                while (psListLength(contents->list) > 0) {
+                    psMetadataRemoveIndex(contents, PS_LIST_TAIL);
+                }
+
+                // update with the new contents
+                psMetadataIterator *fpaIter = psMetadataIteratorAlloc(fpa, PS_LIST_HEAD, NULL); // Iterator
+                psMetadataItem *fpaItem;    // Item from iteration
+                while ((fpaItem = psMetadataGetAndIncrement(fpaIter))) {
+                    assert (fpaItem->type == PS_DATA_STRING);
+                    psString content = NULL; // Content to add
+                    psStringAppend(&content, "%s:_mosaicChip ", fpaItem->name);
+                    psMetadataAddStr(contents, PS_LIST_TAIL, fpaItem->name, 0, NULL, content);
+                    psFree(content);
+                }
+                psFree(fpaIter);
+                # endif
+
+                psMetadata *chips = psMetadataAlloc(); // List of chip types, with cellName:cellType
+                psMetadataAddStr(chips, PS_LIST_TAIL, "_mosaicChip", 0, NULL,
+                                 "MosaickedCell:_mosaic");
+                psMetadataAddMetadata(format, PS_LIST_TAIL, CHIP_TYPES, PS_META_REPLACE,
+                                      "List of chip types", chips);
+                psFree(chips);
+                break;
+            }
+        default:
+            psAbort("Should never get here.\n");
+        }
+
+        // Fix the cell type
+        psMetadata *cells = psMetadataLookupMetadata(NULL, format, CELL_TYPES); // CELLS information
+        if (!cells) {
+            psError(PS_ERR_UNKNOWN, false, "Couldn't find CELLS of type METADATA in the camera format %s.\n", formatsItem->name);
+            return false;
+        }
+        psMetadata *cell = psMetadataAlloc(); // Cell information
+        psMetadataAddStr(cell, PS_LIST_TAIL, "CELL.TRIMSEC", 0, "Trim section", "TRIMSEC");
+        psMetadataAddStr(cell, PS_LIST_TAIL, "CELL.BIASSEC", 0, "Bias section", "BIASSEC");
+        psMetadataAddStr(cell, PS_LIST_TAIL, "CELL.TRIMSEC.SOURCE", 0, "Trim section source", "HEADER");
+        psMetadataAddStr(cell, PS_LIST_TAIL, "CELL.BIASSEC.SOURCE", 0, "Bias section source", "HEADER");
+        psMetadataAddMetadata(cells, PS_LIST_HEAD, "_mosaic", PS_META_REPLACE, "Mosaic cell information", cell);
+        psFree(cell);                   // Drop reference
+
+        // Update the concepts, so that they are all stored in the FITS headers, under headers of the same
+        // name as the concept
+        psMetadata *database = psMetadataLookupMetadata(&mdok, format, "DATABASE"); // DATABASE concepts
+        psMetadata *defaults = psMetadataLookupMetadata(&mdok, format, "DEFAULTS"); // DEFAULTS concepts
+        if (!mdok || !defaults) {
+            psWarning("Couldn't find DEFAULTS of type METADATA in the camera format %s.\n",
+                      formatsItem->name);
+            continue;
+        }
+        psMetadata *translation = psMetadataLookupMetadata(&mdok, format, "TRANSLATION"); // TRANSLATION info
+        if (!mdok || !translation) {
+            psWarning("Couldn't find TRANSLATION of type METADATA in the camera format %s.\n",
+                      formatsItem->name);
+            continue;
+        }
+
+        removeCellConceptsSources(translation);
+        removeCellConceptsSources(database);
+        removeCellConceptsSources(defaults);
+
+        psMetadata *conceptFormats = psMetadataLookupMetadata(&mdok, format, "FORMATS"); // Concepts formats
+
+        // Add in the positioning concepts
+        psMetadataAddS32(defaults, PS_LIST_TAIL, "CELL.XPARITY", 0, NULL, 1);
+        psMetadataAddS32(defaults, PS_LIST_TAIL, "CELL.YPARITY", 0, NULL, 1);
+        psMetadataAddS32(defaults, PS_LIST_TAIL, "CELL.X0",      0, NULL, 0);
+        psMetadataAddS32(defaults, PS_LIST_TAIL, "CELL.Y0",      0, NULL, 0);
+        if (conceptFormats) {
+            if (psMetadataLookup(conceptFormats, "CELL.X0")) {
+                psMetadataRemoveKey(conceptFormats, "CELL.X0");
+            }
+            if (psMetadataLookup(conceptFormats, "CELL.Y0")) {
+                psMetadataRemoveKey(conceptFormats, "CELL.Y0");
+            }
+        }
+
+        if (mosaicLevel == PM_FPA_LEVEL_FPA) {
+            removeChipConceptsSources(translation);
+            removeChipConceptsSources(database);
+            removeChipConceptsSources(defaults);
+            psMetadataAddS32(defaults, PS_LIST_TAIL, "CHIP.XPARITY", 0, NULL, 1);
+            psMetadataAddS32(defaults, PS_LIST_TAIL, "CHIP.YPARITY", 0, NULL, 1);
+            psMetadataAddS32(defaults, PS_LIST_TAIL, "CHIP.X0", 0, NULL, 0);
+            psMetadataAddS32(defaults, PS_LIST_TAIL, "CHIP.Y0", 0, NULL, 0);
+            if (conceptFormats) {
+                if (psMetadataLookup(conceptFormats, "CHIP.X0")) {
+                    psMetadataRemoveKey(conceptFormats, "CHIP.X0");
+                }
+                if (psMetadataLookup(conceptFormats, "CHIP.Y0")) {
+                    psMetadataRemoveKey(conceptFormats, "CHIP.Y0");
+                }
+            }
+        }
+
+    }
+    psFree(formatsIter);
+
+    // New camera MUST go to the head of the metadata, so that it will be recognised first
+    // The old camera doesn't contain the PSMOSAIC header, so it will match anything!
+    psMetadataAddMetadata(newCameras, PS_LIST_HEAD, newName, PS_META_REPLACE,
+                          "Automatically generated", new);
+    psFree(newName);
+    psFree(new);
+
+    return true;
+}
+
+/*** Helper Functions ***/
+
+// Remove a concept from the list of sources.  Need to check to see if it exists first, to avoid a warning.
+static void removeConcept(psMetadata *source, // Source from which to remove concept
+                          const char *concept // Concept name to remove
+                         )
+{
+    assert(source);
+    assert(concept && strlen(concept) > 0);
+
+    if (psMetadataLookup(source, concept)) {
+        psMetadataRemoveKey(source, concept);
+    }
+
+    return;
+}
+
+// Remove certain concepts from the list of sources.  These concepts are important in the mosaicking process,
+// and are added explicitly to the defaults (elsewhere) so that the user can't get them wrong.
+static void removeCellConceptsSources(psMetadata *source // Source for concepts
+    )
+{
+    if (!source) {
+        return;
+    }
+
+    removeConcept(source, "CELL.BIASSEC");
+    removeConcept(source, "CELL.TRIMSEC");
+    removeConcept(source, "CELL.XPARITY");
+    removeConcept(source, "CELL.YPARITY");
+    removeConcept(source, "CELL.X0");
+    removeConcept(source, "CELL.Y0");
+
+    // For the sake of the defaults, include the .DEPEND
+    removeConcept(source, "CELL.XPARITY.DEPEND");
+    removeConcept(source, "CELL.YPARITY.DEPEND");
+    removeConcept(source, "CELL.X0.DEPEND");
+    removeConcept(source, "CELL.Y0.DEPEND");
+
+    return;
+}
+
+// Remove certain concepts from the list of sources.  These concepts are important in the mosaicking process,
+// and are added explicitly to the defaults (elsewhere) so that the user can't get them wrong.
+static void removeChipConceptsSources(psMetadata *source // Source for concepts
+    )
+{
+    if (!source) {
+        return;
+    }
+
+    removeConcept(source, "CHIP.XPARITY");
+    removeConcept(source, "CHIP.YPARITY");
+    removeConcept(source, "CHIP.X0");
+    removeConcept(source, "CHIP.Y0");
+
+    // For the sake of the defaults, include the .DEPEND
+    removeConcept(source, "CHIP.XPARITY.DEPEND");
+    removeConcept(source, "CHIP.YPARITY.DEPEND");
+    removeConcept(source, "CHIP.X0.DEPEND");
+    removeConcept(source, "CHIP.Y0.DEPEND");
+
+    return;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigCamera.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigCamera.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigCamera.h	(revision 22158)
@@ -0,0 +1,52 @@
+/*  @file pmConfigCamera.h
+ *  @brief Camera Configuration functions
+ *
+ *  @author Paul Price, IfA
+ *  @author Eugene Magnier, IfA
+ *
+ *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-08-14 00:17:40 $
+ *  Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_CONFIG_CAMERA_H
+#define PM_CONFIG_CAMERA_H
+
+/// @addtogroup Config Configuration System
+/// @{
+
+// Generate a skycell version of a camera configuration
+bool pmConfigGenerateSkycellVersion(psMetadata *oldCameras, // Old list of camera configurations
+                                    psMetadata *newCameras, // New list of camera configurations
+                                    const char *name, // Name of original camera configuration
+                                    const psMetadata *site // The site configuration
+    );
+
+/// Generate the skycell version of a particular camera configuration
+bool pmConfigCameraSkycellVersion(psMetadata *site, // The site configuration
+                                  const char *name // Name of the un-mosaicked camera
+    );
+
+
+/// Generate skycell versions of all the camera configurations
+bool pmConfigCameraSkycellVersionsAll(psMetadata *site // Site configuration
+    );
+
+// Generate a mosaicked version of a camera configuration
+bool pmConfigGenerateMosaickedVersion(psMetadata *oldCameras, // Old list of camera configurations
+                                      psMetadata *newCameras, // New list of camera configurations
+                                      const char *name, // Name of original camera configuration
+                                      pmFPALevel mosaicLevel // Level to which we are mosaicking
+    );
+
+/// Generate the chip mosaicked version of a particular camera configuration
+bool pmConfigCameraMosaickedVersions(psMetadata *site, // Site configuration
+                                     const char *name // Name of the un-mosaicked camera
+    );
+
+/// Generate chip- and fpa-mosaicked versions of all the camera configurations
+bool pmConfigCameraMosaickedVersionsAll(psMetadata *site // Site configuration
+    );
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigCommand.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigCommand.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigCommand.c	(revision 22158)
@@ -0,0 +1,61 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "pmConfig.h"
+#include "pmConfigCommand.h"
+
+bool pmConfigDatabaseCommand(psString *command, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(command, false);
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(config->complete, false);
+
+    bool mdok;                          // Status of MD lookup
+    const char *dbserver = psMetadataLookupStr(&mdok, config->complete, "DBSERVER"); // Database server
+    if (!mdok || strlen(dbserver) == 0) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find DBSERVER in site configuration.\n");
+        return false;
+    }
+    const char *dbname = psMetadataLookupStr(&mdok, config->complete, "DBNAME"); // Database name
+    if (!mdok || strlen(dbname) == 0) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find DBNAME in site configuration.\n");
+        return false;
+    }
+    const char *dbuser = psMetadataLookupStr(&mdok, config->complete, "DBUSER"); // Database user
+    if (!mdok || strlen(dbuser) == 0) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find DBUSER in site configuration.\n");
+        return false;
+    }
+    const char *dbpassword = psMetadataLookupStr(&mdok, config->complete, "DBPASSWORD"); // Database password
+    if (!mdok || strlen(dbpassword) == 0) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find DBPASSWORD in site configuration.\n");
+        return false;
+    }
+
+    psStringAppend(command, " -dbserver %s -dbname %s -dbuser %s -dbpassword %s",
+                   dbserver, dbname, dbuser, dbpassword);
+
+    return true;
+}
+
+
+bool pmConfigTraceCommand(psString *command)
+{
+    PS_ASSERT_PTR_NON_NULL(command, false);
+
+    psMetadata *levels = psTraceLevels(); // Metadata levels
+    psMetadataIterator *iter = psMetadataIteratorAlloc(levels, PS_LIST_HEAD, NULL); // Iterator for levels
+    psMetadataItem *item;               // Item from iteration
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        assert(item->type == PS_TYPE_S32);
+        psStringAppend(command, " -trace %s %d", item->name, item->data.S32);
+    }
+    psFree(iter);
+    psFree(levels);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigCommand.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigCommand.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigCommand.h	(revision 22158)
@@ -0,0 +1,16 @@
+#ifndef PM_CONFIG_COMMAND_H
+#define PM_CONFIG_COMMAND_H
+
+/// Extend a command-line to include the necessary database flags
+///
+/// The command-line is extended with -dbserver, -dbname, -dbuser, -dbpassword
+bool pmConfigDatabaseCommand(psString *command, ///< Command to extend
+                             const pmConfig *config ///< Configuration
+                            );
+
+/// Extend a command-line to propagate the trace flags
+///
+/// The command-line is extended with -trace
+bool pmConfigTraceCommand(psString *command ///< Command to extend
+                         );
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigMask.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigMask.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigMask.c	(revision 22158)
@@ -0,0 +1,319 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmConfigMask.h"
+
+psMaskType pmConfigMaskGet(const char *masks, const pmConfig *config)
+{
+    psAssert(config, "Require configuration");
+    PS_ASSERT_STRING_NON_EMPTY(masks, 0);
+
+    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe
+    if (!recipe) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");
+        return 0;
+    }
+
+    psMaskType mask = 0;                // Mask value, to return
+
+    psArray *names = psStringSplitArray(masks, " ,;", false); // Array of symbolic names
+    for (int i = 0; i < names->n; i++) {
+        const char *name = names->data[i]; // Symbolic name of interest
+        bool mdok;                      // Status of MD lookup
+        psMaskType value = psMetadataLookupU8(&mdok, recipe, name);
+        if (!mdok) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false,
+                    "Unable to find mask value for %s in MASK recipe", name);
+            psFree(names);
+            return 0;
+        }
+        mask |= value;
+    }
+    psFree(names);
+
+    return mask;
+}
+
+bool pmConfigMaskSet(const pmConfig *config, const char *maskName, psMaskType maskValue)
+{
+    psAssert(config, "Require configuration");
+    PS_ASSERT_STRING_NON_EMPTY(maskName, false);
+
+    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe
+    if (!recipe) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");
+        return false;
+    }
+
+    psMetadataAddU8 (recipe, PS_LIST_TAIL, maskName, PS_META_REPLACE, "user-defined mask", maskValue);
+
+    return true;
+}
+
+// replace the named masks in the recipe with values in the header:
+// replace only the names in the header in the recipe
+bool pmConfigMaskReadHeader(pmConfig *config, const psMetadata *header)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_METADATA_NON_NULL(header, false);
+
+    bool status = false;
+
+    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe
+    if (!recipe) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");
+        return false;
+    }
+
+    // MASK.VALUE and MARK.VALUE aren't usually set in the recipe, but may be set in the header: create fake
+    // versions so that it won't complain later
+    if (!psMetadataLookup(recipe, "MASK.VALUE")) {
+        psMetadataAddU8(recipe, PS_LIST_TAIL, "MASK.VALUE", 0, "Bits to mask", 0);
+    }
+    if (!psMetadataLookup(recipe, "MARK.VALUE")) {
+        psMetadataAddU8(recipe, PS_LIST_TAIL, "MARK.VALUE", 0, "Bits for marking", 0);
+    }
+
+    int nMask = psMetadataLookupS32(&status, header, "MSKNUM");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find MSKNUM in header.");
+        return false;
+    }
+
+    char namekey[80];                   // Keyword name for symbolic name of mask entry
+    char valuekey[80];                  // Keyword name for value of mask entry
+    for (int i = 0; i < nMask; i++) {
+        snprintf(namekey,  64, "MSKNAM%02d", i);
+        snprintf(valuekey, 64, "MSKVAL%02d", i);
+
+        char *name = psMetadataLookupStr(&status, header, namekey);
+        if (!status || !name) {
+            psWarning("Unable to find header keyword %s when parsing mask", namekey);
+            continue;
+        }
+        psU8 bit = psMetadataLookupU8(&status, header, valuekey);
+        if (!status) {
+            psWarning("Unable to find header keyword %s when parsing mask", namekey);
+            continue;
+        }
+
+        // XXX validate that bit is a 2^n value?
+
+        psString nameAlready = NULL;    // Name of key with ".ALREADY" added
+        psStringAppend(&nameAlready, "%s.ALREADY", name);
+        bool already = psMetadataLookupBool(&status, recipe, nameAlready); // Already read this one?
+
+        psMetadataItem *item = psMetadataLookup(recipe, name); // Item in recipe with current value
+        if (item->type != PS_TYPE_MASK) {
+            psWarning("Mask recipe entry is not of a mask type (%x)", item->type);
+            item->type = PS_TYPE_MASK;
+        }
+
+        if (already) {
+            if (item && item->data.U8 != bit) {
+                psWarning("New mask recipe entry doesn't match previously loaded entry: %x vs %x",
+                          bit, item->data.U8);
+            }
+        } else {
+            psMetadataAddBool(recipe, PS_LIST_TAIL, nameAlready, 0, "Already read this mask value", true);
+        }
+
+        if (!item) {
+            psWarning("Mask recipe entry %s not in recipe\n", name);
+            psMetadataAddU8(recipe, PS_LIST_TAIL, name, 0, "Bitmask bit value", bit);
+        } else {
+            item->data.U8 = bit;
+        }
+
+        psFree(nameAlready);
+    }
+
+
+    return true;
+}
+
+// Remove from the header keywords starting with the provided string
+static int maskRemoveHeader(psMetadata *header, // Header from which to remove keywords
+                            const char *start // Remove keywords that start with this string
+                            )
+{
+    psString regex = NULL;              // Regular expression for keywords
+    psStringAppend(&regex, "^%s[0-9][0-9]", start);
+    psMetadataIterator *iter = psMetadataIteratorAlloc(header, PS_LIST_HEAD, regex); // Iterator
+    psFree(regex);
+    psMetadataItem *item;               // Item from iteration
+    int num = 0;                        // Number of items removed
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        psMetadataRemoveKey(header, item->name);
+        num++;
+    }
+    psFree(iter);
+    return num;
+}
+
+
+// write the named mask bits to the header
+bool pmConfigMaskWriteHeader(const pmConfig *config, psMetadata *header)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_METADATA_NON_NULL(header, false);
+
+    maskRemoveHeader(header, "MSKNAM");
+    maskRemoveHeader(header, "MSKVAL");
+    if (psMetadataLookup(header, "MSKNUM")) {
+        psMetadataRemoveKey(header, "MSKNUM");
+    }
+
+    char namekey[80];
+    char valuekey[80];
+
+    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe
+    if (!recipe) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");
+        return false;
+    }
+
+    int nMask = 0;
+
+    psMetadataIterator *iter = psMetadataIteratorAlloc(recipe, PS_LIST_HEAD, NULL); // Iterator
+
+    psMetadataItem *item;               // Item from iteration
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        if (strcmp(item->name + strlen(item->name) - strlen(".ALREADY"), ".ALREADY") == 0) {
+            continue;
+        }
+
+        if (item->type != PS_DATA_U8) {
+            psWarning("mask recipe entry %s is not a bit value\n", item->name);
+            continue;
+        }
+
+        snprintf(namekey,  64, "MSKNAM%02d", nMask);
+        snprintf(valuekey, 64, "MSKVAL%02d", nMask);
+
+        psMetadataAddStr(header, PS_LIST_TAIL, namekey, 0, "Bitmask bit name", item->name);
+        psMetadataAddU8(header, PS_LIST_TAIL, valuekey, 0, "Bitmask bit value", item->data.U8);
+        nMask++;
+    }
+
+    psMetadataAddS32(header, PS_LIST_TAIL, "MSKNUM", 0, "Bitmask bit count", nMask);
+    return true;
+}
+
+// examine named mask values in mask recipe and set the bits for maskValue and markValue
+// this function sets an appropriate value for the following required named mask concepts:
+// FLAT (used to mark out-of-range corrections in the flat-fielding)
+// BLANK (used to mark non-existent pixels)
+// SAT (used to mark pixels with values out-of-range on the high end)
+// BAD (used to mark pixels with values out-of-range on the low end)
+// If there is no explicit value for the above, the 'DETECTOR' and 'RANGE' bits are used
+// If these latter do not exist, the value 0x01 is used.
+// The values actually used for these names are written back to the config file
+bool pmConfigMaskSetBits(psMaskType *outMaskValue, psMaskType *outMarkValue, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMaskType maskValue = 0;
+
+    // mask for generic detector defect
+    psMaskType detectorMask = pmConfigMaskGet("DETECTOR", config);
+    maskValue |= detectorMask;
+
+    // mask for dark structures
+    psMaskType darkMask = pmConfigMaskGet("DARK", config);
+    maskValue |= darkMask;
+
+    // mask for non-linear flat regions (default to DETECTOR if not defined)
+    psMaskType flatMask = pmConfigMaskGet("FLAT", config);
+    if (!flatMask) {
+        flatMask = detectorMask;
+        pmConfigMaskSet (config, "FLAT", flatMask);
+    }
+    if (!flatMask) {
+        flatMask = 0x01;
+        pmConfigMaskSet (config, "FLAT", flatMask);
+    }
+    maskValue |= flatMask;
+
+    // mask for non-existent data  (default to DETECTOR if not defined)
+    psMaskType blankMask = pmConfigMaskGet("BLANK", config);
+    if (!blankMask) {
+        blankMask = detectorMask;
+        pmConfigMaskSet (config, "BLANK", blankMask);
+    }
+    if (!blankMask) {
+        blankMask = 0x01;
+        pmConfigMaskSet (config, "BLANK", blankMask);
+    }
+    maskValue |= blankMask;
+
+    // mask for generic data range errors
+    psMaskType rangeMask = pmConfigMaskGet("RANGE", config);
+    maskValue |= rangeMask;
+
+    // mask for saturated data  (default to RANGE if not defined)
+    psMaskType satMask = pmConfigMaskGet("SAT", config);
+    if (!satMask) {
+        satMask = rangeMask;
+        pmConfigMaskSet (config, "SAT", satMask);
+    }
+    if (!satMask) {
+        satMask = 0x01;
+        pmConfigMaskSet (config, "SAT", satMask);
+    }
+    maskValue |= satMask;
+
+    // mask for below-range data  (default to RANGE if not defined)
+    psMaskType badMask = pmConfigMaskGet("BAD", config);
+    if (!badMask) {
+        badMask = rangeMask;
+        pmConfigMaskSet (config, "BAD", badMask);
+    }
+    if (!badMask) {
+        badMask = 0x01;
+        pmConfigMaskSet (config, "BAD", badMask);
+    }
+    maskValue |= badMask;
+
+    // XXX not sure what to do with these
+    psMaskType crMask = pmConfigMaskGet("CR", config);
+    maskValue |= crMask;
+
+    psMaskType ghostMask = pmConfigMaskGet("GHOST", config);
+    maskValue |= ghostMask;
+
+    // search for an unset bit to use for MARK:
+    psMaskType markValue = 0x80;
+
+    int nBits = sizeof(psMaskType) * 8;
+    for (int i = 0; !markValue && (i < nBits); i++) {
+        if (maskValue & markValue) {
+            markValue >>= 1;
+        } else {
+            markValue = markValue;
+        }
+    }
+    if (!markValue) {
+        psError (PS_ERR_UNKNOWN, true, "Unable to define the MARK bit mask: all bits taken!");
+        return false;
+    }
+
+
+    // update the config table
+    pmConfigMaskSet(config, "MASK.VALUE", maskValue);
+    pmConfigMaskSet(config, "MARK.VALUE", markValue);
+
+    if (outMaskValue) {
+        *outMaskValue = maskValue;
+    }
+    if (outMarkValue) {
+        *outMarkValue = markValue;
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigMask.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigMask.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigMask.h	(revision 22158)
@@ -0,0 +1,40 @@
+/*  @file pmConfigMask.h
+ *  @brief Mask configuration functions
+ *
+ *  @author Paul Price, IfA
+ *
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-17 20:37:20 $
+ *  Copyright 2007 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_CONFIG_MASK_H
+#define PM_CONFIG_MASK_H
+
+#include <pslib.h>
+#include <pmConfig.h>
+
+#define PM_MASKS_RECIPE "MASKS"
+
+/// @addtogroup Config Configuration System
+/// @{
+
+/// Return a mask value given a list of symbolic names
+///
+/// The mask values are derived from the MASKS recipe
+psMaskType pmConfigMaskGet(const char *masks, ///< List of symbolic names, space/comma delimited
+                           const pmConfig *config ///< Configuration
+    );
+
+bool pmConfigMaskSet(const pmConfig *config, const char *maskName, psMaskType maskValue);
+
+// replace the named masks in the recipe with values in the header:
+// replace only the names in the header in the recipe
+bool pmConfigMaskReadHeader(pmConfig *config, const psMetadata *header);
+
+// write the named mask bits to the header
+bool pmConfigMaskWriteHeader(const pmConfig *config, psMetadata *header);
+
+bool pmConfigMaskSetBits(psMaskType *outMaskValue, psMaskType *outMarkValue, const pmConfig *config);
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigRecipes.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigRecipes.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigRecipes.c	(revision 22158)
@@ -0,0 +1,628 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>            /* for strn?casecmp */
+#include <assert.h>
+#include <pslib.h>
+#include "pmConfig.h"
+#include "pmConfigRecipes.h"
+
+static bool loadRecipeSystem(bool *status, pmConfig *config, psMetadata *source);
+static bool loadRecipeCamera(bool *status, pmConfig *config, psMetadata *source);
+static bool loadRecipeSymbols(bool *status, pmConfig *config, pmRecipeSource source);
+static bool loadRecipeFromArguments(bool *status, pmConfig *config);
+static bool loadRecipeOptions(bool *status, pmConfig *config);
+static bool mergeRecipeCamera(bool *status, pmConfig *config);
+
+// use this function to select the options structure for the specified recipe
+// add additional command-line options to this metadata (before parsing the camera)
+psMetadata *pmConfigRecipeOptions (pmConfig *config, char *recipeName)
+{
+    bool success;
+
+    // select or create the OPTIONS folder
+    psMetadata *options = psMetadataLookupMetadata(&success, config->arguments, "OPTIONS");
+    if (!options) {
+        options = psMetadataAlloc ();
+        success = psMetadataAddPtr (config->arguments, PS_LIST_TAIL, "OPTIONS",  PS_DATA_METADATA, "", options);
+        assert (success); // type mismatch : OPTIONS already defined but wrong type
+        psFree (options); // drop extra reference
+    }
+
+    // look for the recipe defined in recipes
+    // if the recipe is already defined in config->arguments:OPTIONS, supplement
+    // save the recipe options onto config->arguments:RECIPES
+    psMetadata *recipe = psMetadataLookupMetadata(&success, options, recipeName);
+    if (!recipe) {
+        recipe = psMetadataAlloc();
+        success = psMetadataAddPtr(options, PS_LIST_TAIL, recipeName,  PS_DATA_METADATA, "", recipe);
+        assert (success); // type mismatch : OPTIONS already defined but wrong type
+        psFree (recipe);  // drop extra reference
+    }
+    return recipe;
+}
+
+// this function may be called several times.  it attempts to load the recipe data from one of three
+// locations: config->complete, config->camera, and argv.  We cannot read the recipes from
+// config->camera until a camera has been read BUT, the argv recipes must override the camera and
+// system recipes.  This command strips the argv elements it uses from the argv list.
+bool pmConfigReadRecipes(pmConfig *config, pmRecipeSource source)
+{
+    bool status;
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    if (!config->recipes) {
+        config->recipes = psMetadataAlloc();
+    }
+
+    // Read the recipe file names from the system configuration and camera configuration
+    // It is an error for config->complete:recipes not to exist.  all programs install their
+    // master recipe files in the system:recipe location when they are built.
+    psAssert (config->complete, "base config data defined");
+    if (source & PM_RECIPE_SOURCE_SYSTEM) {
+        if (!loadRecipeSystem(&status, config, config->complete)) {
+            psError(PS_ERR_IO, false, "Failed to read recipes from system config");
+            return false;
+        }
+        psTrace ("psModules.config", 3, "read recipes from system config");
+    }
+
+    // camera-specific recipes are not required : note the absence with a message
+    // camera-specific recipes may be read for a specified camera (in pmConfigRead) or
+    // for an identified camera (in pmConfigCameraFormatFromHeader).  the second
+    // set should not override the first set
+    if (config->camera && (source & PM_RECIPE_SOURCE_CAMERA) && !(config->recipesRead & PM_RECIPE_SOURCE_CAMERA)) {
+        if (!loadRecipeCamera(&status, config, config->camera)) {
+            psError(PS_ERR_IO, false, "Failed to read recipes from camera config");
+            return false;
+        }
+        if (status) {
+            psTrace ("psModules.config", 3, "read recipes from camera config");
+        } else {
+            psLogMsg ("psModules.config", PS_LOG_DETAIL, "no recipe supplied by camera config");
+        }
+    }
+
+    // merge camera and sytem recipes, apply recipes loaded into config->arguments based on command-line arguments
+    if (config->arguments && (source & PM_RECIPE_SOURCE_CL)) {
+
+	// update the system-level recipes with the symbolically-defined recipes 
+        if (!loadRecipeSymbols(&status, config, PM_RECIPE_SOURCE_SYSTEM)) {
+            psError(PS_ERR_IO, false, "Failed to read recipes from symbolic references");
+            return false;
+        }
+        if (status) {
+            psTrace ("psModules.config", 3, "read recipes from symbolic references");
+        } else {
+            psLogMsg ("psModules.config", PS_LOG_DETAIL, "no recipe supplied by symbolic reference");
+        }
+
+	// merge the SYSTEM and CAMERA recipes
+        if (!mergeRecipeCamera(&status, config)) {
+            psError(PS_ERR_IO, false, "Failed to read recipes from symbolic references");
+            return false;
+        }
+	psLogMsg ("psModules.config", PS_LOG_DETAIL, "merged camera recipes with system recipes");
+
+	// load recipe-files specified on the command line
+        if (!loadRecipeFromArguments(&status, config)) {
+            psError(PS_ERR_IO, false, "Failed to read recipes from command-line arguments");
+            return false;
+        }
+        if (status) {
+            psTrace ("psModules.config", 3, "read recipes from command-line arguments");
+        } else {
+            psLogMsg ("psModules.config", PS_LOG_DETAIL, "no recipe supplied on command-line arguments");
+        }
+
+	// update the system-level recipes with the symbolically-defined recipes 
+        if (!loadRecipeSymbols(&status, config, PM_RECIPE_SOURCE_CAMERA)) {
+            psError(PS_ERR_IO, false, "Failed to read recipes from symbolic references");
+            return false;
+        }
+        if (status) {
+            psTrace ("psModules.config", 3, "read recipes from symbolic references");
+        } else {
+            psLogMsg ("psModules.config", PS_LOG_DETAIL, "no recipe supplied by symbolic reference");
+        }
+
+	// override any specific values with values from the command line
+        if (!loadRecipeOptions(&status, config)) {
+            psError(PS_ERR_IO, false, "Failed to read recipes from symbolic references");
+            return false;
+        }
+        if (status) {
+            psTrace ("psModules.config", 3, "read recipes from command-line arguments");
+        } else {
+            psLogMsg ("psModules.config", PS_LOG_DETAIL, "no recipe supplied on command-line arguments");
+        }
+    }
+    return true;
+}
+
+// search for options of the form -D KEY VALUE or -D RECIPE:KEY VALUE
+bool pmConfigLoadRecipeOptions (int *argc, char **argv, pmConfig *config, char *flag)
+{
+    bool success;
+    int argNum;
+
+    // save the recipe options onto config->arguments:OPTIONS
+    // increment so we can free below (is a NOP if 'options' is NULL)
+    psMetadata *options = psMetadataLookupMetadata(&success, config->arguments, "OPTIONS");
+    if (!options) {
+        options = psMetadataAlloc();
+        success = psMetadataAddPtr(config->arguments, PS_LIST_TAIL, "OPTIONS",  PS_DATA_METADATA, "Command-line options specified with -D", options);
+        assert (success); // type mismatch : OPTIONS already defined but wrong type
+        psFree (options); // drop extra reference
+    }
+
+    // -D key value (all added as string)
+    while ((argNum = psArgumentGet (*argc, argv, flag))) {
+        psArgumentRemove (argNum, argc, argv);
+
+        // do we have enough arguments?
+        if (argNum + 1 >= *argc) {
+            psError(PS_ERR_IO, true, "insufficient parameters for command-line argument -D");
+            return false;
+        }
+
+        // is a target recipe specified?
+        const char *recipeName = NULL;
+        char *key;
+        psArray *words = psStringSplitArray(argv[argNum], ":", false);
+        switch (words->n) {
+        case 1:
+            recipeName = config->defaultRecipe;
+            if (!config->defaultRecipe) {
+                psError(PS_ERR_IO, true, "syntax error in parameter: no default recipe available; must specify recipe");
+                return false;
+            }
+            key = words->data[0];
+            break;
+        case 2:
+            recipeName = words->data[0];
+            key = words->data[1];
+            break;
+        default:
+            psError(PS_ERR_IO, true, "syntax error in parameter");
+            return false;
+        }
+
+        // if this recipe is already defined in options, supplement
+        psMetadata *recipe = psMetadataLookupMetadata(&success, options, recipeName);
+        if (!recipe) {
+            recipe = psMetadataAlloc();
+            success = psMetadataAddPtr(options, PS_LIST_TAIL, recipeName,  PS_DATA_METADATA, "", recipe);
+            assert (success); // type mismatch : recipe already defined but wrong type
+            psFree (recipe); // drop extra reference
+        }
+
+        bool valid = false;
+        if (!strcmp (flag, "-D")) {
+            psMetadataAddStr (recipe, PS_LIST_TAIL, key, PS_META_REPLACE, "", argv[argNum+1]);
+            valid = true;
+        }
+        if (!strcmp (flag, "-Di")) {
+            psMetadataAddS32 (recipe, PS_LIST_TAIL, key, PS_META_REPLACE, "", atoi(argv[argNum+1]));
+            valid = true;
+        }
+        if (!strcmp (flag, "-Df")) {
+            psMetadataAddF32 (recipe, PS_LIST_TAIL, key, PS_META_REPLACE, "", atof(argv[argNum+1]));
+            valid = true;
+        }
+        if (!strcmp (flag, "-Db")) {
+            if (!strcasecmp (argv[argNum+1], "true")) {
+                psMetadataAddBool (recipe, PS_LIST_TAIL, key, PS_META_REPLACE, "", true);
+            } else {
+                psMetadataAddBool (recipe, PS_LIST_TAIL, key, PS_META_REPLACE, "", false);
+            }
+            valid = true;
+        }
+        psFree (words);
+        assert (valid);  // flag may be: -D, -Df, -Di, -Db
+
+        psArgumentRemove (argNum, argc, argv);
+        psArgumentRemove (argNum, argc, argv);
+    }
+    return true;
+}
+
+// examine command-line arguments for -recipe RECIPE SYMBOLIC-NAME or -recipe-file RECIPE FILENAME
+// in the first case, the symbolic lookup is saved on config->recipeSymbols
+//   for later interpolation (pmConfigReadRecipes with option CL)
+// in the second case, read as metadata and save on config->arguments with name = KEY
+bool pmConfigLoadRecipeArguments (int *argc, char **argv, pmConfig *config)
+{
+    bool success;
+
+    psMetadata *recipes = psMetadataLookupMetadata(&success, config->arguments, "RECIPES");
+    if (!recipes) {
+        recipes = psMetadataAlloc();
+        success = psMetadataAddPtr (config->arguments, PS_LIST_TAIL, "RECIPES",  PS_DATA_METADATA, "", recipes);
+        assert (success);
+        psFree (recipes);
+    }
+
+    // Go through the command-line arguments
+    int argNum;                         // Argument number
+
+    // -recipe-file: read recipe from file
+    while ((argNum = psArgumentGet(*argc, argv, "-recipe-file")) > 0) {
+        psArgumentRemove(argNum, argc, argv);
+        if (argNum + 1 >= *argc) {
+            psError(PS_ERR_IO, false,
+                    "-recipe command-line switch provided without the required recipe and filename\n");
+            return false;
+        }
+
+        psString recipeName = psStringCopy(argv[argNum]); // Name of the recipe
+        psArgumentRemove(argNum, argc, argv);
+        psString filename = psStringCopy(argv[argNum]); // Filename for the recipe
+        psArgumentRemove(argNum, argc, argv);
+
+        psMetadata *recipe = NULL;      // Recipe from file
+        if (!pmConfigFileRead(&recipe, filename, "recipe")) {
+            psError(PS_ERR_IO, "Error reading config file %s\n", filename);
+            psFree(recipeName);
+            psFree(filename);
+            return false;
+        }
+
+        psString comment = NULL;
+        psStringAppend(&comment, "Recipe added at command line from file %s", filename);
+        psMetadataAdd(recipes, PS_LIST_TAIL, recipeName, PS_DATA_METADATA | PS_META_REPLACE,
+                      comment, recipe);
+        psFree(comment);
+        psFree(recipe);                 // Drop reference
+        psFree(recipeName);
+        psFree(filename);
+    }
+
+    // -recipe: read recipe from symbolic link
+    while ((argNum = psArgumentGet(*argc, argv, "-recipe")) > 0) {
+        psArgumentRemove(argNum, argc, argv);
+        if (argNum + 1 >= *argc) {
+            psError(PS_ERR_IO, false,
+                    "-recipe command-line switch provided without the required recipe and source\n");
+            return false;
+        }
+
+        char *recipeName = psStringCopy(argv[argNum]); // Name of the recipe
+        psArgumentRemove(argNum, argc, argv);
+        char *recipeSource = psStringCopy(argv[argNum]); // Source of the recipe
+        psArgumentRemove(argNum, argc, argv);
+
+        // Assume it's a symbolic reference to something that's not yet read in.
+        // it will be loaded later by pmConfigReadRecipes with option CL
+        psMetadataAddStr(config->recipeSymbols, PS_LIST_TAIL, recipeName, PS_META_REPLACE, NULL, recipeSource);
+
+        psTrace ("psModules.config", 3, "read recipe %s from %s", recipeName, recipeSource);
+        psFree(recipeName);
+        psFree(recipeSource);
+    }
+
+    return true;
+}
+
+// Load the recipe files for SYSTEM : REQUIRED
+static bool loadRecipeSystem(bool *status,
+                           pmConfig *config, // The configuration into which to read the recipes
+                           psMetadata *source // The source configuration, from which to read the filenames
+    )
+{
+    assert(status);
+    assert(config);
+    *status = false;
+
+    if (!source) {
+        psError(PS_ERR_IO, true, "The system configuration has not been read --- cannot read recipes from this location.\n");
+        config->recipesRead &= ~PM_RECIPE_SOURCE_SYSTEM;
+        return false;
+    }
+
+    psMetadata *recipes = psMetadataLookupMetadata(NULL, source, "RECIPES"); // The list of recipes
+    if (!recipes) {
+        psError(PS_ERR_IO, false, "RECIPES not found in the system configuration\n");
+        return false;
+    }
+
+    // Copy contents of the filenames to config->recipes from the "RECIPES" metadata in the source.
+    // We could use psMetadataCopy for this, but it's better to check that everything's of the correct type.
+    // If it's not of the correct type, we can tell the user which file it's in, so they can find it easier.
+    psMetadataIterator *recipesIter = psMetadataIteratorAlloc(recipes, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *fileItem = NULL;    // MD item containing the filename, from recipe iteration
+    while ((fileItem = psMetadataGetAndIncrement(recipesIter))) {
+        char *recipeName = fileItem->name;
+        char *recipeFile = fileItem->data.str;
+
+        // type mismatch is a serious error
+        if (fileItem->type != PS_DATA_STRING) {
+            psAbort("%s in system configuration RECIPES is not of type STR", recipeName);
+        }
+
+        // Read the recipe file. if we fail on a file, give a warning, but continue
+        psMetadata *recipe = NULL;
+        if (!pmConfigFileRead(&recipe, recipeFile, "recipe")) {
+            psError(PS_ERR_IO, false, "Failed to read recipe file %s listed in system configuration\n", recipeFile);
+            return false;
+        }
+
+        // and the contents of this recipe file to config->recipes
+        psMetadataAdd(config->recipes, PS_LIST_TAIL, fileItem->name, PS_DATA_METADATA | PS_META_REPLACE, fileItem->comment, recipe);
+        psFree(recipe);  // Drop reference
+    }
+    psFree(recipesIter);
+    config->recipesRead |= PM_RECIPE_SOURCE_SYSTEM;
+
+    *status = true;
+    return true;
+}
+
+// Load the recipe files for a specific CAMERA.  these are saved on recipesCamera
+static bool loadRecipeCamera(bool *status, // status variable
+                             pmConfig *config, // The configuration into which to read the recipes
+                             psMetadata *source // The source configuration, from which to read the filenames
+    )
+{
+    bool success;
+
+    assert(status);
+    assert(config);
+    *status = false;
+
+    if (!source) {
+        psError(PS_ERR_IO, true, "The camera configuration has not been read --- cannot read recipes from this location.\n");
+        config->recipesRead &= ~PM_RECIPE_SOURCE_CAMERA;
+        return false;
+    }
+
+    // it is not necessary to define any local recipes in the camera config; it this entry is missing,
+    // just return true
+    psMetadata *recipes = psMetadataLookupMetadata(&success, source, "RECIPES"); // The list of recipes
+    if (!recipes) {
+        psTrace ("psModules.config", 3, "RECIPES not found in the camera configuration\n");
+        return true;
+    }
+
+    // Copy contents of the filenames to config->recipes from the "RECIPES" metadata in the source.
+    // We could use psMetadataCopy for this, but it's better to check that everything's of the correct type.
+    // If it's not of the correct type, we can tell the user which file it's in, so they can find it easier.
+    psMetadataIterator *recipesIter = psMetadataIteratorAlloc(recipes, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *fileItem = NULL;    // MD item containing the filename, from recipe iteration
+    while ((fileItem = psMetadataGetAndIncrement(recipesIter))) {
+        char *recipeName = fileItem->name;
+        char *recipeFile = fileItem->data.str;
+
+        psTrace("psModules.config", 3, "loading %s from %s within camera configuration.\n", recipeName, recipeFile);
+
+        // type mismatch is a serious error
+        if (fileItem->type != PS_DATA_STRING) {
+            psAbort("%s in camera configuration RECIPES is not of type STR", recipeName);
+        }
+
+        // Read the recipe file. if we fail on a file, give a warning, but continue
+        psMetadata *recipe = NULL;
+        if (!pmConfigFileRead(&recipe, recipeFile, "recipe")) {
+            psError(PS_ERR_IO, false, "Failed to read recipe file %s listed in camera configuration\n", recipeFile);
+            return false;
+        }
+
+        // the named recipe must exist at the system level
+        psMetadata *current = psMetadataLookupMetadata(NULL, config->recipes, recipeName);
+        if (!current) {
+            psError(PS_ERR_IO, false, "Failed to find recipe for %s in master recipe list", recipeName);
+            psFree(recipe);  // Drop reference
+            return false;
+        }
+
+        // add the contents of this recipe file to config->recipesCamera
+        psMetadataAdd(config->recipesCamera, PS_LIST_TAIL, recipeName, PS_DATA_METADATA | PS_META_REPLACE, fileItem->comment, recipe);
+        psFree(recipe);  // Drop reference
+    }
+    psFree(recipesIter);
+    config->recipesRead |= PM_RECIPE_SOURCE_CAMERA;
+    *status = true;
+    return true;
+}
+
+// Merge the CAMERA recipes into the SYSTEM recipes
+static bool mergeRecipeCamera(bool *status, // status variable
+                             pmConfig *config // The configuration into which to read the recipes
+    )
+{
+    assert(status);
+    assert(config);
+    *status = false;
+
+    // Copy contents of config->recipesCamera to config->recipes
+    // We could use psMetadataCopy for this, but it's better to check that everything's of the correct type.
+    // If it's not of the correct type, we can tell the user which file it's in, so they can find it easier.
+    psMetadataIterator *recipesIter = psMetadataIteratorAlloc(config->recipesCamera, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *folderItem = NULL;    // MD item containing the filename, from recipe iteration
+    while ((folderItem = psMetadataGetAndIncrement(recipesIter))) {
+        char *recipeName = folderItem->name;
+        psMetadata *recipe = folderItem->data.md;
+
+        psTrace("psModules.config", 3, "merging %s from camera with system recipes.\n", recipeName);
+
+        // type mismatch is a serious error
+        if (folderItem->type != PS_DATA_METADATA) {
+            psAbort("%s not of type METADATA", recipeName);
+        }
+
+        // the select the named recipe from the system level
+        psMetadata *current = psMetadataLookupMetadata(NULL, config->recipes, recipeName);
+        psAssert (current, "Failed to find recipe for %s in system recipe list", recipeName);
+
+        // update the contents of this recipe from the one on config->recipesCamera
+	if (!psMetadataUpdate(current, recipe)) {
+	    psError(PS_ERR_IO, false, "Failed to update recipe for %s from camera recipe", recipeName);
+	    return false;
+	}
+    }
+    psFree(recipesIter);
+    *status = true;
+    return true;
+}
+
+// Load the recipes from config->arguments (CL)
+// Load the recipes: each time we load a specific recipe, it overrides the metadata
+// entries for an existing recipe metadata
+static bool loadRecipeFromArguments(bool *status,
+                                    pmConfig *config // The configuration into which to read the recipes
+    )
+{
+    assert(status);
+    assert(config);
+    *status = false;
+
+    if (!config->arguments) {
+        psTrace("psModules.config", 4, "no config->arguments metadata, nothing to read here");
+        return true;
+    }
+
+    psMetadata *recipes = psMetadataLookupMetadata(NULL, config->arguments, "RECIPES"); // The list of recipes
+    if (!recipes) {
+        psTrace("psModules.config", 4, "no RECIPES in config->arguments, nothing to read here");
+        return true;
+    }
+
+    // Copy the recipes from config->arguments:RECIPES to config->recipes.  supplement existing recipes.
+    psMetadataIterator *recipesIter = psMetadataIteratorAlloc(recipes, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *item = NULL;    // MD item containing the filename, from recipe iteration
+    while ((item = psMetadataGetAndIncrement(recipesIter))) {
+        // type mismatch is a serious error
+        if (item->type != PS_DATA_METADATA) {
+            psAbort("%s in config arguments RECIPES is not of type METADATA", item->name);
+        }
+        // increment the ref counter to protect the data
+
+        psMetadata *recipe = item->data.md; // Recipe of interest
+
+        // if this named recipe exists, supplement it
+        psMetadata *current = psMetadataLookupMetadata(NULL, config->recipes, item->name);
+        if (!current) {
+            psError(PS_ERR_IO, false, "Failed to find recipe for %s in master recipe list", item->name);
+            psFree(recipe);  // Drop reference
+            return false;
+        }
+        psTrace("psModules.config", 3, "Supplementing %s from arguments.\n", item->name);
+
+        if (!psMetadataUpdate (current, recipe)) {
+            psError(PS_ERR_IO, false, "Failed to update recipe for %s from camera recipe", item->name);
+            return false;
+        }
+    }
+    psFree(recipesIter);
+    *status = true;
+    return true;
+}
+
+// Load the recipes: each time we load a specific recipe, it overrides the metadata
+// entries for an existing recipe metadata
+// The configuration into which to read the recipes
+static bool loadRecipeSymbols(bool *status, pmConfig *config, pmRecipeSource source) {
+
+    bool found = false;
+
+    assert(status);
+    assert(config);
+    *status = false;
+
+    // check to see if any symbolic names need to be resolved
+    // each entry in recipeSymbols are of the form TARGET=SOURCE where TARGET is an existing
+    // recipe MD and REF is a MD to load over that recipe
+    psMetadataIterator *iter = psMetadataIteratorAlloc(config->recipeSymbols, PS_LIST_HEAD, NULL);
+    psMetadataItem *item = NULL;  // Item containing source, from iteration
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        assert(item->type == PS_DATA_STRING); // It should be this type: we put it in ourselves
+        const char *sourceName = item->data.str; // The name of the symbolic reference
+        const char *targetName = item->name;
+        psTrace("psModules.config", 3, "Supplementing %s from %s.\n", targetName, sourceName);
+
+        // the target recipe must exist; select it
+        psMetadata *targetMD = psMetadataLookupMetadata(&found, config->recipes, targetName);
+        if (!targetMD) {
+            psError(PS_ERR_IO, true, "Failed to find recipe for %s in master recipe list", targetName);
+            return false;
+        }
+
+        // search for sourceName in config->recipes (folder name is targetName)
+	psMetadata *folder = psMetadataLookupMetadata(&found, config->recipes, targetName);
+	psMetadata *sourceMD = psMetadataLookupMetadata(&found, folder, sourceName);
+
+	// if we find the desired symbolic name at this level, set the item comment to say "FOUND"
+        if (sourceMD) {
+	  if (!psMetadataUpdate(targetMD, sourceMD)) {
+            psError(PS_ERR_IO, false, "Failed to update recipe for %s from camera recipe", targetName);
+            return false;
+	  }
+	  psStringAppend (&item->comment, "(FOUND)");
+	}	  
+
+	// if we have not found it by the camera level, we have a problem
+	if (source == PM_RECIPE_SOURCE_CAMERA) {
+	  if (strstr (item->comment, "(FOUND)") == NULL) {
+	    psError(PS_ERR_IO, false, "Selected symbolic name %s does not exist in recipes", sourceName);
+	    return false;
+	  }
+	}
+    }
+    psFree(iter);
+    *status = true;
+    return true;
+}
+
+// Load the recipe options
+// Load the recipes: each time we load a specific recipe, it overrides the metadata
+// entries for an existing recipe metadata
+static bool loadRecipeOptions(bool *status,
+                              pmConfig *config // The configuration into which to read the recipes
+    )
+{
+    bool found;
+    assert(status);
+    assert(config);
+    *status = false;
+
+    if (!config->arguments) {
+        psTrace("psModules.config", 4, "no config->arguments metadata, nothing to read here");
+        return true;
+    }
+
+    psMetadata *recipes = psMetadataLookupMetadata(&found, config->arguments, "OPTIONS"); // The list of recipes
+    if (!recipes) {
+        psTrace("psModules.config", 4, "no OPTIONS in config->arguments, nothing to read here");
+        return true;
+    }
+
+    // Copy the recipes from config->arguments:OPTIONS to config->recipes.  supplement existing recipes.
+    psMetadataIterator *recipesIter = psMetadataIteratorAlloc(recipes, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataItem *item = NULL;    // MD item containing the filename, from recipe iteration
+    while ((item = psMetadataGetAndIncrement(recipesIter))) {
+        char *recipeName = item->name;
+        psMetadata *recipe = item->data.md;
+
+        // type mismatch is a serious error
+        if (item->type != PS_DATA_METADATA) {
+            psAbort("%s in config arguments OPTIONS is not of type METADATA", recipeName);
+        }
+
+        // if this named recipe exists, supplement it
+        psMetadata *current = psMetadataLookupMetadata(NULL, config->recipes, recipeName);
+        if (!current) {
+            psError(PS_ERR_IO, false, "Selected recipe %s is not found in camera recipe", recipeName);
+            return false;
+        }
+        if (!psMetadataUpdate (current, recipe)) {
+            psError(PS_ERR_IO, false, "Failed to update recipe for %s from camera recipe", recipeName);
+            return false;
+        }
+    }
+    psFree(recipesIter);
+    *status = true;
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigRecipes.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigRecipes.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmConfigRecipes.h	(revision 22158)
@@ -0,0 +1,33 @@
+/*  @file pmConfigRecipes.h
+ *  @brief Configuration Recipe functions
+ * 
+ *  @author ?, MHPCC
+ *  @author Paul Price, IfA
+ *  @author Eugene Magnier, IfA
+ * 
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-04-19 02:10:12 $
+ *  Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_CONFIG_RECIPES_H
+#define PM_CONFIG_RECIPES_H
+
+/// @addtogroup Config Configuration System
+/// @{
+
+/// Read recipes
+///
+/// Attempt to read recipes from the sources that are available but have not already been read.  Having read a
+/// recipe, attempt to resolve symbolic links that were specified on the command line.
+bool pmConfigReadRecipes(pmConfig *config, ///< Configuration
+                         pmRecipeSource source ///< desired sources for recipes
+                        );
+
+
+bool pmConfigLoadRecipeArguments (int *argc, char **argv, pmConfig *config);
+bool pmConfigLoadRecipeOptions (int *argc, char **argv, pmConfig *config, char *flag);
+psMetadata *pmConfigRecipeOptions (pmConfig *config, char *recipe);
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmErrorCodes.c.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmErrorCodes.c.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmErrorCodes.c.in	(revision 22158)
@@ -0,0 +1,25 @@
+/*
+ * The line
+    { PM_ERR_$X{ErrorCode}, "$X{ErrorDescription}"},
+ * (without the Xs)
+ * will be replaced by values from errorCodes.dat
+ */
+#include <pslib.h>
+#include "pmErrorCodes.h"
+
+void pmErrorRegister(void)
+{
+    static psErrorDescription errors[] = {
+       { PM_ERR_BASE, "First value we use; lower values belong to psLib" },
+       { PM_ERR_${ErrorCode}, "${ErrorDescription}"},
+    };
+    static int nerror = PM_ERR_NERROR - PM_ERR_BASE; // number of values in enum
+
+    for (int i = 0; i < nerror; i++) {
+       psErrorDescription *tmp = psAlloc(sizeof(psErrorDescription));
+       *tmp = errors[i];
+       psErrorRegister(tmp, 1);
+       psFree(tmp);			/* it's on the internal list */
+    }
+    nerror = 0;			                // don't register more than once
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmErrorCodes.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmErrorCodes.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmErrorCodes.dat	(revision 22158)
@@ -0,0 +1,18 @@
+#
+# This file is used to generate pmErrorCodes.h
+#
+UNKNOWN			Unknown psModules error code
+PHOTOM			Problem in photometry
+PSF			Problem in PSF
+ASTROM			Problem in astrometry
+CAMERA			Problem in camera
+CONCEPTS		Problem in concepts
+IMCOMBINE		Problem in imcombine
+OBJECTS			Problem in objects
+SKY			Problem in sky
+# these errors correspond to standard exit conditions
+ARGUMENTS               Incorrect arguments
+SYS                     System error
+CONFIG                  Problem in configure files
+PROG                    Programming error
+DATA                    invalid data
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmErrorCodes.h.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmErrorCodes.h.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmErrorCodes.h.in	(revision 22158)
@@ -0,0 +1,18 @@
+#if !defined(PM_ERROR_CODES_H)
+#define PM_ERROR_CODES_H
+/*
+ * The line
+ *  PM_ERR_$X{ErrorCode},
+ * (without the X)
+ *
+ * will be replaced by values from errorCodes.dat
+ */
+typedef enum {
+    PM_ERR_BASE = 1200,
+    PM_ERR_${ErrorCode},
+    PM_ERR_NERROR
+} pmErrorCode;
+
+void pmErrorRegister(void);
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmVersion.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmVersion.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmVersion.c	(revision 22158)
@@ -0,0 +1,28 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "pmVersion.h"
+
+static const char *cvsTag = "$Name: not supported by cvs2svn $";// CVS tag name
+
+psString psModulesVersion(void)
+{
+    psString version = NULL;            // Version, to return
+    psStringAppend(&version, "%s-%s",PACKAGE_NAME,PACKAGE_VERSION);
+    return version;
+}
+
+psString psModulesVersionLong(void)
+{
+    psString version = psModulesVersion(); // Version, to return
+    psString tag = psStringStripCVS(cvsTag, "Name"); // CVS tag
+
+    psStringAppend(&version, " (cvs tag %s) %s, %s", tag, __DATE__, __TIME__);
+
+    psFree(tag);
+    return version;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmVersion.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmVersion.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/config/pmVersion.h	(revision 22158)
@@ -0,0 +1,37 @@
+/*  @file pmVersion.h
+ *  @brief Version functions
+ * 
+ *  @author Paul Price, IfA
+ *  @author Eugene Magnier, IfA
+ * 
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-03-30 21:12:56 $
+ *  Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_VERSION_H
+#define PM_VERSION_H
+
+/// @addtogroup Config Configuration System
+/// @{
+
+/** Get current psModules version
+ *
+ *  Returns the current psModules version name as a string.
+ *
+ *  @return psString: String with version name.
+ */
+psString psModulesVersion(
+    void
+);
+
+/** Get current psModules version (full identification)
+ *
+ *  Returns the current psModules version name and other information identifying the compilation.
+ *
+ *  @return psString: String with identity.
+ */
+psString psModulesVersionLong(void);
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/.cvsignore	(revision 22158)
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/Makefile.am	(revision 22158)
@@ -0,0 +1,35 @@
+noinst_LTLIBRARIES = libpsmodulesdetrend.la
+
+libpsmodulesdetrend_la_CPPFLAGS = $(SRCINC) $(PSMODULES_CFLAGS)
+libpsmodulesdetrend_la_LDFLAGS  = -release $(PACKAGE_VERSION)
+libpsmodulesdetrend_la_SOURCES  = \
+	pmFlatField.c \
+	pmFlatNormalize.c \
+	pmFringeStats.c \
+	pmMaskBadPixels.c \
+	pmNonLinear.c \
+	pmBias.c \
+	pmOverscan.c \
+	pmDetrendDB.c \
+	pmShutterCorrection.c \
+	pmShifts.c \
+	pmDark.c
+
+#	pmSkySubtract.c
+
+pkginclude_HEADERS = \
+	pmFlatField.h \
+	pmFlatNormalize.h \
+	pmFringeStats.h \
+	pmMaskBadPixels.h \
+	pmNonLinear.h \
+	pmBias.h \
+	pmOverscan.h \
+	pmDetrendDB.h \
+	pmShutterCorrection.h \
+	pmShifts.h \
+	pmDark.h
+
+#	pmSkySubtract.h
+
+CLEANFILES = *~
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmBias.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmBias.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmBias.c	(revision 22158)
@@ -0,0 +1,194 @@
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmHDUUtils.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPACalibration.h"
+
+#include "pmOverscan.h"
+#include "pmBias.h"
+
+// pmBiasSubtractFrame(): this routine will take as input a readout for the input image and a readout for the bias
+// image.  The bias image is subtracted in place from the input image.
+bool pmBiasSubtractFrame(pmReadout *in, // Input readout
+                          const pmReadout *sub, // Readout to be subtracted from input
+                          float scale   // Scale to apply before subtracting
+                         )
+{
+    PS_ASSERT_PTR_NON_NULL(in, false);
+    PS_ASSERT_PTR_NON_NULL(in->image, false);
+    PS_ASSERT_IMAGE_TYPE(in->image, PS_TYPE_F32, false);
+    PS_ASSERT_IMAGE_NON_EMPTY(in->image, false);
+    PS_ASSERT_PTR_NON_NULL(sub, false);
+    PS_ASSERT_PTR_NON_NULL(sub->image, false);
+    PS_ASSERT_IMAGE_TYPE(sub->image, PS_TYPE_F32, false);
+    PS_ASSERT_IMAGE_NON_EMPTY(sub->image, false);
+    PS_ASSERT_IMAGES_SIZE_EQUAL(in->image, sub->image, false);
+
+    psImage *inImage  = in->image;      // The input image
+    psImage *inMask   = in->mask;       // The input mask
+    psImage *subImage = sub->image;     // The image to be subtracted
+    psImage *subMask  = sub->mask;      // The mask for the subtraction image
+
+    // Check parities
+    int xIpar = psMetadataLookupS32(NULL, in->parent->concepts, "CELL.XPARITY");
+    int xSpar = psMetadataLookupS32(NULL, sub->parent->concepts, "CELL.XPARITY");
+    if (xIpar != xSpar) {
+        psError(PS_ERR_UNKNOWN, true, "images for subtraction do not have the same "
+                "CELL.XPARITY (%d vs %d).\n    pmSubtractBias must be upgraded to handle this situation\n",
+                xIpar, xSpar);
+        return false;
+    }
+
+    int yIpar = psMetadataLookupS32(NULL, in->parent->concepts, "CELL.YPARITY");
+    int ySpar = psMetadataLookupS32(NULL, sub->parent->concepts, "CELL.YPARITY");
+    if (yIpar != ySpar) {
+        psError(PS_ERR_UNKNOWN, true, "images for subtraction do not have the same "
+                "CELL.YPARITY (%d vs %d).\n    pmSubtractBias must be upgraded to handle this situation\n",
+                xIpar, xSpar);
+        return false;
+    }
+
+    // Offsets of the cells
+    int x0in = psMetadataLookupS32(NULL, in->parent->concepts, "CELL.X0");
+    int y0in = psMetadataLookupS32(NULL, in->parent->concepts, "CELL.Y0");
+    int x0sub = psMetadataLookupS32(NULL, sub->parent->concepts, "CELL.X0");
+    int y0sub = psMetadataLookupS32(NULL, sub->parent->concepts, "CELL.Y0");
+
+    if ((inImage->numCols + x0in - x0sub) > subImage->numCols) {
+        psError(PS_ERR_UNKNOWN, true, "Image does not have enough columns for subtraction (%d vs %d).\n",
+                inImage->numCols + x0in - x0sub, subImage->numCols);
+        return false;
+    }
+    if ((inImage->numRows + y0in - y0sub) > subImage->numRows) {
+        psError(PS_ERR_UNKNOWN, true, "Image does not have enough rows for subtraction (%d vs %d).\n",
+                inImage->numRows + y0in - y0sub, subImage->numRows);
+        return false;
+    }
+
+    if (scale == 1.0) {
+        for (int i = 0; i < inImage->numRows; i++) {
+            for (int j = 0; j < inImage->numCols; j++) {
+                inImage->data.F32[i][j] -= subImage->data.F32[i+y0in-y0sub][j+x0in-x0sub];
+                if (inMask && subMask) {
+                    inMask->data.U8[i][j] |= subMask->data.U8[i+y0in-y0sub][j+x0in-x0sub];
+                }
+            }
+        }
+    } else {
+        for (int i = 0; i < inImage->numRows; i++) {
+            for (int j = 0; j < inImage->numCols; j++) {
+                inImage->data.F32[i][j] -= subImage->data.F32[i+y0in-y0sub][j+x0in-x0sub] * scale;
+                if (inMask && subMask) {
+                    inMask->data.U8[i][j] |= subMask->data.U8[i+y0in-y0sub][j+x0in-x0sub];
+                }
+            }
+        }
+    }
+
+    return true;
+}
+
+bool pmBiasSubtract(pmReadout *in, pmOverscanOptions *overscanOpts,
+                    const pmReadout *bias, const pmReadout *dark, const pmFPAview *view)
+{
+    psTrace("psModules.detrend", 4,
+            "---- pmBiasSubtract() begin ----\n");
+
+    PS_ASSERT_PTR_NON_NULL(in, false);
+    PS_ASSERT_IMAGE_NON_NULL(in->image, false);
+    PS_ASSERT_IMAGE_TYPE(in->image, PS_TYPE_F32, false);
+    if (bias) {
+        PS_ASSERT_IMAGE_NON_NULL(bias->image, false);
+        PS_ASSERT_IMAGE_TYPE(bias->image, PS_TYPE_F32, false);
+    }
+    if (dark) {
+        psWarning("Dark processing is now available using pmDark --- perhaps you should use that instead?");
+        PS_ASSERT_PTR_NON_NULL(view, false);
+        PS_ASSERT_IMAGE_NON_NULL(dark->image, false);
+        PS_ASSERT_IMAGE_TYPE(dark->image, PS_TYPE_F32, false);
+    }
+
+    pmHDU *hdu = pmHDUFromReadout(in);  // HDU of interest
+
+    if (!pmOverscanSubtract (in, overscanOpts)) {
+        return false;
+    }
+
+    // Bias frame subtraction
+    if (bias) {
+        psVector *md5 = psImageMD5(bias->image); // md5 hash
+        psString md5string = psMD5toString(md5); // String
+        psFree(md5);
+        psStringPrepend(&md5string, "BIAS image MD5: ");
+        psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK,
+                         md5string, "");
+        psFree(md5string);
+
+        if (!pmBiasSubtractFrame(in, bias, 1.0)) {
+            return false;
+        }
+    }
+
+    if (dark) {
+        // Get the scaling
+        float inTime = psMetadataLookupF32(NULL, in->parent->concepts, "CELL.DARKTIME");
+        float darkTime = psMetadataLookupF32(NULL, dark->parent->concepts, "CELL.DARKTIME");
+        if (isnan(inTime) || isnan(darkTime)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to determine dark scaling.");
+            return false;
+        }
+
+        float darkNorm = 1.0;
+        float inNorm = pmFPADarkNorm(in->parent->parent->parent, view, inTime);
+
+        // if we have a normalized dark exposure, we simply multiply the master by inNorm.  if
+        // we do not have a normalized exposure, we have to scale the master as well.  XXX do
+        // we need to explicitly identify the master as normalized?
+
+        if (darkTime != 1.0) {
+            darkNorm = pmFPADarkNorm(dark->parent->parent->parent, view, darkTime);
+        }
+
+        if (isnan(inNorm) || isnan(darkNorm)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to determine dark normalisations.");
+            return false;
+        }
+
+        float scale = inNorm / darkNorm;// Scaling to apply to dark exposure
+
+        psVector *md5 = psImageMD5(dark->image); // md5 hash
+        psString md5string = psMD5toString(md5); // String
+        psFree(md5);
+        psStringPrepend(&md5string, "DARK image (scale %.3f) MD5: ", scale);
+        psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK,
+                         md5string, "");
+        psFree(md5string);
+
+        if (!pmBiasSubtractFrame(in, dark, scale)) {
+            return false;
+        }
+    }
+
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now, used for reporting
+    psString timeString = psTimeToISO(time); // String with time
+    psFree(time);
+    psStringPrepend(&timeString, "Overscan/bias/dark processing completed at ");
+    psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK,
+                     timeString, "");
+    psFree(timeString);
+
+
+    return true;
+}
+
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmBias.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmBias.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmBias.h	(revision 22158)
@@ -0,0 +1,37 @@
+/* @file pmBias.h
+ * @brief Subtract the overscan, bias and dark
+ *
+ * @author George Gusciora, MHPCC
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-08-15 20:21:18 $
+ * Copyright 2004--2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_BIAS_H
+#define PM_BIAS_H
+
+/// @addtogroup detrend Detrend Creation and Application
+/// @{
+
+/// Subtract the overscan, bias and/or dark
+///
+/// Subtracts the overscan, as measured from the bias member of the input readout (if options are non-NULL),
+/// bias (if non-NULL) and dark (if non-NULL) scaled by the CELL.DARKTIME concept.
+bool pmBiasSubtract(pmReadout *in,      ///< Input readout, to be overscan/bias/dark corrected
+                    pmOverscanOptions *overscanOpts, ///< Options for overscan subtraction, or NULL
+                    const pmReadout *bias, ///< Bias to subtract, or NULL
+                    const pmReadout *dark, ///< Dark to scale and subtract, or NULL
+                    const pmFPAview *view ///< View for readout of interest
+                   );
+
+// pmBiasSubtractFrame(): this routine will take as input a readout for the input image and a readout for the bias
+// image.  The bias image is subtracted in place from the input image.
+bool pmBiasSubtractFrame(pmReadout *in, // Input readout
+                          const pmReadout *sub, // Readout to be subtracted from input
+                          float scale   // Scale to apply before subtracting
+    );
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmDark.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmDark.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmDark.c	(revision 22158)
@@ -0,0 +1,786 @@
+#include <stdio.h>
+#include <pslib.h>
+#include <string.h>
+
+#include "psPolynomialMD.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmHDUUtils.h"
+#include "pmFPARead.h"
+#include "pmFPAWrite.h"
+#include "pmReadoutStack.h"
+
+#include "pmDark.h"
+
+#define PM_DARK_FITS_EXTNAME "PS_DARK"  // FITS extension name for ordinates table
+#define PM_DARK_FITS_NAME    "NAME"     // Column name for concept name in ordinates table
+#define PM_DARK_FITS_ORDER   "ORDER"    // Column name for polynomial order in ordinates table
+#define PM_DARK_FITS_SCALE   "SCALE"    // Column name for scaling option in ordinates table
+#define PM_DARK_FITS_MIN     "MIN"      // Column name for minimum value in ordinates table
+#define PM_DARK_FITS_MAX     "MAX"      // Column name for maximum value in ordinates table
+
+
+
+// Look up the value of an ordinate in a readout
+static bool ordinateLookup(float *value, // Value of ordinate, to return
+                           bool *inRange, // is value within min : max range?
+                           const char *name, // Name of ordinate (concept name)
+                           bool scale,  // Scale the value?
+                           float min, float max, // Minimum and maximum values for scaling
+                           const pmReadout *ro // Readout of interest
+                           )
+{
+    assert(value);
+    assert(name);
+    assert(ro);
+
+    *inRange = true;
+
+    pmCell *cell = ro->parent; // Parent cell
+    if (!cell) {
+        return false;
+    }
+    psMetadataItem *item = psMetadataLookup(cell->concepts, name);
+    if (!item) {
+        pmChip *chip = cell->parent; // Parent chip
+        if (!chip) {
+            return false;
+        }
+        item = psMetadataLookup(chip->concepts, name);
+        if (!item) {
+            pmFPA *fpa = chip->parent; // Parent FPA
+            if (!fpa) {
+                return false;
+            }
+            item = psMetadataLookup(fpa->concepts, name);
+            if (!item) {
+                psWarning("Unable to find concept %s in readout", name);
+                return false;
+            }
+        }
+    }
+
+    *value = psMetadataItemParseF32(item); // Value of interest
+    if (!isfinite(*value)) {
+        psWarning("Non-finite value (%f) of concept %s in readout", *value, name);
+        return false;
+    }
+    if (scale) {
+        if (*value < min || *value > max) {
+            psWarning("Value of concept %s (%f) outside range (%f:%f)", name, *value, min, max);
+            *inRange = false;
+        }
+        *value = 2.0 * (*value - min) / (max - min) - 1.0;
+    }
+
+    return true;
+}
+
+static void darkOrdinateFree(pmDarkOrdinate *ord)
+{
+    psFree(ord->name);
+    return;
+}
+
+pmDarkOrdinate *pmDarkOrdinateAlloc(const char *name, int order)
+{
+    pmDarkOrdinate *ord = psAlloc(sizeof(pmDarkOrdinate)); // Ordinate data, to return
+    psMemSetDeallocator(ord, (psFreeFunc)darkOrdinateFree);
+
+    ord->name = psStringCopy(name);
+    ord->order = order;
+    ord->scale = false;
+    ord->min = NAN;
+    ord->max = NAN;
+
+    return ord;
+}
+
+
+bool pmDarkCombine(pmCell *output, const psArray *inputs, psArray *ordinates, const char *normConcept,
+                   int iter, float rej, psMaskType maskVal)
+{
+    PS_ASSERT_PTR_NON_NULL(output, false);
+    PS_ASSERT_ARRAY_NON_NULL(inputs, false);
+    PS_ASSERT_ARRAY_NON_NULL(ordinates, false);
+    PS_ASSERT_INT_NONNEGATIVE(iter, false);
+    PS_ASSERT_FLOAT_LARGER_THAN(rej, 0.0, false);
+
+    bool inRange = true;
+
+    // Extract fitting orders
+    int numOrdinates = ordinates->n;    // Number of ordinates
+    int numInputs = inputs->n;          // Number of inputs
+    int numBadInputs = 0;               // Number of bad inputs
+    psArray *values = psArrayAlloc(numInputs);
+    psVector *roMask = psVectorAlloc(numInputs, PS_TYPE_U8); // Mask for bad readouts
+    psVectorInit(roMask, 0);
+    psVector *norm = normConcept ? psVectorAlloc(numInputs, PS_TYPE_F32) : NULL; // Normalisations for each
+    for (int i = 0; i < numInputs; i++) {
+        values->data[i] = psVectorAlloc(numOrdinates, PS_TYPE_F32);
+        if (norm) {
+            pmReadout *ro = inputs->data[i]; // Readout of interest
+            float normValue;            // Normalisation value
+            if (!ordinateLookup(&normValue, &inRange, normConcept, false, NAN, NAN, ro)) {
+                psWarning("Unable to find value of %s for readout %d", normConcept, i);
+                roMask->data.U8[i] = 0xff;
+                norm->data.F32[i] = NAN;
+                numBadInputs++;
+                continue;
+            }
+            if (normValue == 0.0) {
+                psWarning("Normalisation value (%s) for readout %d is zero", normConcept, i);
+                roMask->data.U8[i] = 0xff;
+                norm->data.F32[i] = NAN;
+                numBadInputs++;
+                continue;
+            }
+            norm->data.F32[i] = 1.0 / normValue;
+        }
+    }
+    psVector *orders = psVectorAlloc(numOrdinates, PS_TYPE_U8); // Orders for each concept
+    for (int i = 0; i < numOrdinates; i++) {
+        pmDarkOrdinate *ord = ordinates->data[i]; // Ordinate information
+        if (ord->order <= 0) {
+            psError(PS_ERR_UNKNOWN, true, "Bad order for concept %s (%d) --- ignored", ord->name, ord->order);
+            psFree(values);
+            psFree(roMask);
+            psFree(orders);
+            return false;
+        }
+        orders->data.U8[i] = ord->order;
+
+        // Mask the readout and move on
+        #define MASK_READOUT_VALUE { \
+            roMask->data.U8[j] = 0xff; \
+            val->data.F32[i] = NAN; \
+            numBadInputs++; \
+            continue; \
+        }
+
+        for (int j = 0; j < numInputs; j++) {
+            psVector *val = values->data[j]; // Value vector for readout
+            if (roMask->data.U8[j]) {
+                val->data.F32[i] = NAN;
+                continue;
+            }
+
+            pmReadout *ro = inputs->data[j]; // Readout of interest
+            float value = NAN;          // Value of ordinate
+            if (!ordinateLookup(&value, &inRange, ord->name, ord->scale, ord->min, ord->max, ro)) {
+                roMask->data.U8[j] = 0xff;
+                val->data.F32[i] = NAN;
+                numBadInputs++;
+                continue;
+            }
+            if (!inRange) {
+                roMask->data.U8[j] = 0xff;
+                val->data.F32[i] = NAN;
+                numBadInputs++;
+                continue;
+            }
+            val->data.F32[i] = value;
+        }
+    }
+
+    if (psTraceGetLevel("psModules.detrend") > 9) {
+        for (int i = 0; i < numInputs; i++) {
+            psVector *val = values->data[i];
+            (void) val; // avoid unused variable message when tracing is compiled out
+            for (int j = 0; j < numOrdinates; j++) {
+                psTrace("psModules.detrend", 9, "Image %d, ordinate %d: %f\n", i, j, val->data.F32[j]);
+            }
+        }
+    }
+
+    psPolynomialMD *poly = psPolynomialMDAlloc(orders); // Polynomial for fitting
+    psFree(orders);
+    int numTerms = poly->coeff->n;      // Number of terms in polynomial
+    if (numTerms > numInputs - numBadInputs) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Insufficient inputs (%d) to fit polynomial terms (%d).",
+                numInputs - numBadInputs, numTerms);
+        psFree(values);
+        psFree(roMask);
+        psFree(norm);
+        return false;
+    }
+
+    // Set up output
+    int minInputCols, maxInputCols, minInputRows, maxInputRows; // Smallest and largest values to combine
+    int xSize, ySize;                   // Size of the output image
+    if (!pmReadoutStackValidate(&minInputCols, &maxInputCols, &minInputRows, &maxInputRows, &xSize, &ySize,
+                                inputs)) {
+        psError(PS_ERR_UNKNOWN, false, "No valid input readouts.");
+        psFree(values);
+        psFree(roMask);
+        psFree(norm);
+        return false;
+    }
+    if (output->readouts->n != numTerms) {
+        output->readouts = psArrayRealloc(output->readouts, numTerms);
+    }
+    int outRow0 = 0, outCol0 = 0;       // Output row0 and col0
+    for (int i = 0; i < numTerms; i++) {
+        pmReadout *ro = output->readouts->data[i]; // Readout to update
+        if (!ro) {
+            ro = output->readouts->data[i] = pmReadoutAlloc(output);
+        }
+
+        pmReadoutUpdateSize(ro, minInputCols, minInputRows, xSize, ySize, false, false, 0);
+        if (i == 0) {
+            outRow0 = ro->row0;
+            outCol0 = ro->col0;
+        } else {
+            assert(ro->row0 == outRow0);
+            assert(ro->col0 == outCol0);
+        }
+    }
+
+    psImage *counts = pmReadoutAnalysisImage(output->readouts->data[0], PM_READOUT_STACK_ANALYSIS_COUNT,
+                                             xSize, ySize, PS_TYPE_U16, 0);
+    if (!counts) {
+        return false;
+    }
+    psImage *sigma = pmReadoutAnalysisImage(output->readouts->data[0], PM_READOUT_STACK_ANALYSIS_SIGMA,
+                                            xSize, ySize, PS_TYPE_F32, NAN);
+    if (!sigma) {
+        psFree(counts);
+        return false;
+    }
+
+    // Iterate over pixels, fitting polynomial
+    psVector *pixels = psVectorAlloc(numInputs, PS_TYPE_F32); // Stack of pixels
+    psVector *mask   = psVectorAlloc(numInputs, PS_TYPE_MASK); // Mask for stack
+    for (int i = minInputRows; i < maxInputRows; i++) {
+        int yOut = i - outRow0; // y position on output readout
+#ifdef SHOW_BUSY
+        if (psTraceGetLevel("psModules.detrend") > 9) {
+            printf("Processing row %d\r", i);
+            fflush(stdout);
+        }
+#endif
+
+        for (int j = minInputCols; j < maxInputCols; j++) {
+            int xOut = j - outCol0; // x position on output readout
+
+            psVectorInit(mask, 0);
+            for (int r = 0; r < inputs->n; r++) {
+                if (roMask->data.U8[r]) {
+                    mask->data.PS_TYPE_MASK_DATA[r] = 0xff;
+                    continue;
+                }
+                pmReadout *readout = inputs->data[r]; // Input readout
+                int yIn = i - readout->row0; // y position on input readout
+                int xIn = j - readout->col0; // x position on input readout
+
+                pixels->data.F32[r] = readout->image->data.F32[yIn][xIn];
+                if (norm) {
+                    pixels->data.F32[r] *= norm->data.F32[r];
+                }
+                if (readout->mask) {
+                    mask->data.PS_TYPE_MASK_DATA[r] = readout->mask->data.PS_TYPE_MASK_DATA[yIn][xIn];
+                }
+
+            }
+
+            // XXX test
+            if (0 && (i == 377) && (j == 80)) {
+                FILE *f = fopen ("test.dat", "w");
+                for (int r = 0; r < inputs->n; r++) {
+                    fprintf (f, "%d %d  %d  ", i, j, mask->data.U8[r]);
+                    psVector *value = values->data[r];
+                    for (int tmpj = 0; tmpj < value->n; tmpj++) {
+                        fprintf (f, "%f ", value->data.F32[tmpj]);
+                    }
+                    fprintf (f, "%f\n", pixels->data.F32[r]);
+                }
+                fclose (f);
+            }
+
+            if (!psPolynomialMDClipFit(poly, pixels, NULL, mask, maskVal, values, iter, rej)) {
+                psErrorClear();         // Nothing we can do about it
+                psVectorInit(poly->coeff, NAN);
+            }
+            for (int k = 0; k < numTerms; k++) {
+                pmReadout *ro = output->readouts->data[k]; // Readout of interest
+                ro->image->data.F32[yOut][xOut] = poly->coeff->data.F64[k];
+            }
+            counts->data.U16[yOut][xOut] = poly->numFit;
+            sigma->data.F32[yOut][xOut] = poly->stdevFit;
+        }
+    }
+
+    psFree(norm);
+    psFree(roMask);
+    psFree(poly);
+    psFree(pixels);
+    psFree(mask);
+    psFree(values);
+
+    psMetadataAddPtr(output->analysis, PS_LIST_TAIL, PM_DARK_ANALYSIS_ORDINATES,
+                     PS_DATA_ARRAY | PS_META_REPLACE, "Dark ordinates", ordinates);
+    psMetadataAddStr(output->analysis, PS_LIST_TAIL, PM_DARK_ANALYSIS_NORM,
+                     PS_META_REPLACE, "Dark normalisation", normConcept);
+
+    for (int i = 0; i < numTerms; i++) {
+        pmReadout *ro = output->readouts->data[i]; // Readout to update
+        ro->data_exists = true;
+    }
+    output->data_exists = true;
+    output->parent->data_exists = true;
+
+    return true;
+}
+
+
+
+bool pmDarkApply(pmReadout *readout, const pmCell *dark, psMaskType bad)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_PTR_NON_NULL(dark, false);
+    PS_ASSERT_IMAGE_NON_NULL(readout->image, false);
+    PS_ASSERT_IMAGE_TYPE(readout->image, PS_TYPE_F32, false);
+    int numCols = readout->image->numCols, numRows = readout->image->numRows; // Size of image
+    if (readout->mask) {
+        PS_ASSERT_IMAGE_NON_NULL(readout->mask, false);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(readout->mask, readout->image, false);
+        PS_ASSERT_IMAGE_TYPE(readout->mask, PS_TYPE_MASK, false);
+    }
+    int numTerms = dark->readouts->n;   // Number of polynomial terms
+    for (int i = 0; i < numTerms; i++) {
+        pmReadout *ro = dark->readouts->data[i]; // Dark readout
+        PS_ASSERT_PTR_NON_NULL(ro, false);
+        PS_ASSERT_IMAGE_NON_NULL(ro->image, false);
+        PS_ASSERT_IMAGE_SIZE(ro->image, numCols, numRows, false);
+        PS_ASSERT_IMAGE_TYPE(ro->image, PS_TYPE_F32, false);
+    }
+    psArray *ordinates = psMetadataLookupPtr(NULL, dark->analysis, PM_DARK_ANALYSIS_ORDINATES); // Ordinates
+    if (!ordinates) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find dark ordinates.");
+        return false;
+    }
+    bool mdok;                          // Status of MD lookup
+    psString normConcept = psMetadataLookupStr(&mdok, dark->analysis, PM_DARK_ANALYSIS_NORM); // Normalisation
+    bool inRange = false;
+
+    int numOrdinates = ordinates->n;    // Number of ordinates
+    psVector *values = psVectorAlloc(numOrdinates, PS_TYPE_F32); // Values of ordinates
+    for (int i = 0; i < numOrdinates; i++) {
+        pmDarkOrdinate *ord = ordinates->data[i]; // Ordinate of interest
+        float value = NAN;              // Value for ordinate
+        if (!ordinateLookup(&value, &inRange, ord->name, ord->scale, ord->min, ord->max, readout)) {
+            psError(PS_ERR_UNKNOWN, true, "Unable to find value for %s", ord->name);
+            psFree(values);
+            return false;
+        }
+        values->data.F32[i] = value;
+    }
+    float norm = NAN;                   // Normalisation value
+    bool doNorm = false;                // Do normalisation?
+    if (normConcept && strlen(normConcept) > 0) {
+        if (!ordinateLookup(&norm, &inRange, normConcept, false, NAN, NAN, readout)) {
+            psError(PS_ERR_UNKNOWN, true, "Unable to find value for %s", normConcept);
+            psFree(values);
+            return false;
+        }
+        doNorm = true;
+    }
+
+    psVector *orders = psVectorAlloc(numOrdinates, PS_TYPE_U8); // Order for each polynomial
+    for (int i = 0; i < numOrdinates; i++) {
+        pmDarkOrdinate *ord = ordinates->data[i]; // Ordinate information
+        if (ord->order <= 0) {
+            psError(PS_ERR_UNKNOWN, true, "Bad order for concept %s (%d) --- ignored", ord->name, ord->order);
+            psFree(values);
+            psFree(orders);
+            return false;
+        }
+        orders->data.U8[i] = ord->order;
+    }
+
+    psPolynomialMD *poly = psPolynomialMDAlloc(orders); // Polynomial to apply
+    psFree(orders);
+
+    for (int y = 0; y < numRows; y++) {
+        for (int x = 0; x < numCols; x++) {
+            for (int i = 0; i < numTerms; i++) {
+                pmReadout *ro = dark->readouts->data[i]; // Dark readout
+                poly->coeff->data.F64[i] = ro->image->data.F32[y][x];
+            }
+            float value = psPolynomialMDEval(poly, values); // Value of dark current
+            if (doNorm) {
+                value *= norm;
+            }
+            readout->image->data.F32[y][x] -= value;
+            if (readout->mask && !isfinite(value)) {
+                readout->mask->data.PS_TYPE_MASK_DATA[y][x] = bad;
+            }
+        }
+    }
+
+    psFree(poly);
+    psFree(values);
+
+    return true;
+}
+
+bool pmFPAWriteDark(pmFPA *fpa, psFits *fits, pmConfig *config, bool blank, bool recurse)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    if (!pmFPAWrite(fpa, fits, config, blank, recurse)) {
+        psError(PS_ERR_IO, false, "Unable to write FPA dark images");
+        return false;
+    }
+
+    pmHDU *hdu = fpa->hdu;
+    if (blank || !hdu) {
+        // No more to do
+        return true;
+    }
+
+    psArray *ordinates = NULL;      // Dark ordinates, to write
+    const char *normConcept = NULL;     // Normalisation concept
+    psArray *chips = fpa->chips;    // Component chips
+    for (int i = 0; i < chips->n; i++) {
+        pmChip *chip = chips->data[i]; // Chip of interest
+        psArray *cells = chip->cells; // Component cells
+        for (int j = 0; j < cells->n; j++) {
+            pmCell *cell = cells->data[j]; // Cell of interest
+            bool mdok;              // Status of MD lookup
+            psArray *newOrd = psMetadataLookupPtr(&mdok, cell->analysis, PM_DARK_ANALYSIS_ORDINATES); // Ords
+            if (!mdok) {
+                continue;
+            }
+            psString newNorm = psMetadataLookupPtr(&mdok, cell->analysis, PM_DARK_ANALYSIS_NORM); // Norm
+            if (ordinates) {
+                if (newOrd != ordinates) {
+                    psError(PS_ERR_UNKNOWN, true, "Dark ordinates differ across cells.");
+                    return false;
+                }
+                if ((normConcept && (!newNorm || strcmp(normConcept, newNorm) != 0)) ||
+                    (!normConcept && newNorm)) {
+                    psError(PS_ERR_UNKNOWN, true, "Dark normalisations differ across cells.");
+                    return false;
+                }
+            } else {
+                ordinates = newOrd;
+                normConcept = newNorm;
+            }
+        }
+    }
+
+    if (!ordinates) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find dark ordinates.");
+        return false;
+    }
+
+    return pmDarkWrite(fits, hdu->header, ordinates, normConcept);
+}
+
+bool pmChipWriteDark(pmChip *chip, psFits *fits, pmConfig *config, bool blank, bool recurse)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    if (!pmChipWrite(chip, fits, config, blank, recurse)) {
+        psError(PS_ERR_IO, false, "Unable to write chip dark images");
+        return false;
+    }
+
+    pmHDU *hdu = pmHDUFromChip(chip);
+    if (blank || !hdu) {
+        // No more to do
+        return true;
+    }
+
+    psArray *ordinates = NULL;          // Dark ordinates, to write
+    const char *normConcept = NULL;     // Normalisation concept
+    psArray *cells = chip->cells;       // Component cells
+    for (int j = 0; j < cells->n; j++) {
+        pmCell *cell = cells->data[j]; // Cell of interest
+        bool mdok;                      // Status of MD lookup
+        psArray *newOrd = psMetadataLookupPtr(&mdok, cell->analysis, PM_DARK_ANALYSIS_ORDINATES); // Ordinates
+        if (!mdok) {
+            continue;
+        }
+        psString newNorm = psMetadataLookupPtr(&mdok, cell->analysis, PM_DARK_ANALYSIS_NORM); // Normalisation
+        if (ordinates) {
+            if (newOrd != ordinates) {
+                psError(PS_ERR_UNKNOWN, true, "Dark ordinates differ across cells.");
+                return false;
+            }
+            if ((normConcept && (!newNorm || strcmp(normConcept, newNorm) != 0)) ||
+                (!normConcept && newNorm)) {
+                psError(PS_ERR_UNKNOWN, true, "Dark normalisations differ across cells.");
+                return false;
+            }
+        } else {
+            ordinates = newOrd;
+            normConcept = newNorm;
+        }
+    }
+
+    if (!ordinates) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find dark ordinates.");
+        return false;
+    }
+
+    return pmDarkWrite(fits, hdu->header, ordinates, normConcept);
+}
+
+bool pmCellWriteDark(pmCell *cell, psFits *fits, pmConfig *config, bool blank)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    // Allow the usual pmFPAWrite functions to handle the heavy lifting for the images
+    if (!pmCellWrite(cell, fits, config, blank)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to write dark cell.");
+        return false;
+    }
+
+    pmHDU *hdu = pmHDUFromCell(cell);
+    if (blank || !hdu) {
+        // No more to do
+        return true;
+    }
+
+    psArray *ordinates = psMetadataLookupPtr(NULL, cell->analysis, PM_DARK_ANALYSIS_ORDINATES);
+    if (!ordinates) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find dark ordinates.");
+        return false;
+    }
+    bool mdok;                          // Status of MD lookup
+    psString normConcept = psMetadataLookupPtr(&mdok, cell->analysis, PM_DARK_ANALYSIS_NORM); // Normalisation
+
+    return pmDarkWrite(fits, hdu->header, ordinates, normConcept);
+}
+
+bool pmDarkWrite(psFits *fits, psMetadata *header, const psArray *ordinates, const char *normConcept)
+{
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+    PS_ASSERT_FITS_WRITABLE(fits, false);
+    PS_ASSERT_ARRAY_NON_NULL(ordinates, false);
+
+    // Only write table once per FITS file
+    bool write = false;             // Write table?
+    if (psFitsGetSize(fits) <= 1) {
+        write = true;
+    } else {
+        psMetadata *headers = psFitsReadHeaderSet(NULL, fits); // FITS headers
+        if (!psMetadataLookup(headers, PM_DARK_FITS_EXTNAME)) {
+            write = true;
+        }
+        psFree(headers);
+    }
+    if (!write) {
+        return true;
+    }
+
+    if (!psMemIncrRefCounter((psMetadata*)header)) {
+        header = psMetadataAlloc();
+    }
+    psMetadataAddStr(header, PS_LIST_TAIL, PM_DARK_HEADER_NORM, PS_META_REPLACE,
+                     "Dark normalisation concept", normConcept);
+
+    if (ordinates->n > 0) {
+        // Format ordinates into FITS table
+        int numOrdinates = ordinates->n;// Number of ordinates
+        psArray *table = psArrayAlloc(numOrdinates); // FITS table, constructed from ordinates
+        for (int i = 0; i < ordinates->n; i++) {
+            pmDarkOrdinate *ord = ordinates->data[i]; // Ordinate of interest
+            psMetadata *row = psMetadataAlloc(); // FITS table row
+            psMetadataAddStr(row, PS_LIST_TAIL, PM_DARK_FITS_NAME, 0, "Concept name", ord->name);
+            psMetadataAddS32(row, PS_LIST_TAIL, PM_DARK_FITS_ORDER, 0, "Polynomial order", ord->order);
+            psMetadataAddBool(row, PS_LIST_TAIL, PM_DARK_FITS_SCALE, 0, "Scale values?", ord->scale);
+            psMetadataAddF32(row, PS_LIST_TAIL, PM_DARK_FITS_MIN, 0, "Minimum value", ord->min);
+            psMetadataAddF32(row, PS_LIST_TAIL, PM_DARK_FITS_MAX, 0, "Maximum value", ord->max);
+            table->data[i] = row;
+        }
+
+        if (!psFitsWriteTable(fits, header, table, PM_DARK_FITS_EXTNAME)) {
+            psError(PS_ERR_IO, false, "Unable to write dark ordinates.");
+            psFree(table);
+            psFree(header);
+            return false;
+        }
+        psFree(table);
+    } else {
+        // No ordinates to write to a table, so write to a blank header.
+        if (!psFitsWriteBlank(fits, header, PM_DARK_FITS_EXTNAME)) {
+            psError(PS_ERR_IO, false, "Unable to write dark header.");
+            psFree(header);
+            return false;
+        }
+    }
+    psFree(header);
+
+    return true;
+}
+
+
+bool pmFPAReadDark(pmFPA *fpa, psFits *fits, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    if (!pmFPARead(fpa, fits, config)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read dark FPA.");
+        return false;
+    }
+
+    psString normConcept = NULL;        // Normalisation concept
+    psArray *ordinates = pmDarkRead(&normConcept, fits); // Dark ordinates
+    if (!ordinates) {
+        psError(PS_ERR_IO, false, "Unable to read dark ordinates.");
+        return false;
+    }
+
+    psArray *chips = fpa->chips;        // Component chips
+    for (int i = 0; i < chips->n; i++) {
+        pmChip *chip = chips->data[i];  // Chip of interest
+        psArray *cells = chip->cells;   // Component cells
+        for (int j = 0; j < cells->n; j++) {
+            pmCell *cell = cells->data[j]; // Cell of interest
+            psMetadataAddPtr(cell->analysis, PS_LIST_TAIL, PM_DARK_ANALYSIS_ORDINATES,
+                             PS_DATA_ARRAY | PS_META_REPLACE, "Dark ordinates", ordinates);
+            psMetadataAddStr(cell->analysis, PS_LIST_TAIL, PM_DARK_ANALYSIS_NORM, PS_META_REPLACE,
+                             "Dark normalisation", normConcept);
+        }
+    }
+    psFree(ordinates);
+    psFree(normConcept);
+
+    return true;
+}
+
+bool pmChipReadDark(pmChip *chip, psFits *fits, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    if (!pmChipRead(chip, fits, config)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read dark chip.");
+        return false;
+    }
+
+    psString normConcept = NULL;        // Normalisation concept
+    psArray *ordinates = pmDarkRead(&normConcept, fits); // Dark ordinates
+    if (!ordinates) {
+        psError(PS_ERR_IO, false, "Unable to read dark ordinates.");
+        return false;
+    }
+
+    psArray *cells = chip->cells;       // Component cells
+    for (int i = 0; i < cells->n; i++) {
+        pmCell *cell = cells->data[i];  // Cell of interest
+        psMetadataAddPtr(cell->analysis, PS_LIST_TAIL, PM_DARK_ANALYSIS_ORDINATES,
+                         PS_DATA_ARRAY | PS_META_REPLACE, "Dark ordinates", ordinates);
+        psMetadataAddStr(cell->analysis, PS_LIST_TAIL, PM_DARK_ANALYSIS_NORM, PS_META_REPLACE,
+                         "Dark normalisation", normConcept);
+    }
+    psFree(ordinates);
+    psFree(normConcept);
+
+    return true;
+}
+
+
+bool pmCellReadDark(pmCell *cell, psFits *fits, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    // Allow the usual pmFPARead functions to handle the heavy lifting for the images
+    if (!pmCellRead(cell, fits, config)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read dark cell.");
+        return false;
+    }
+
+    psString normConcept = NULL;        // Normalisation concept
+    psArray *ordinates = pmDarkRead(&normConcept, fits); // Dark ordinates
+    if (!ordinates) {
+        psError(PS_ERR_IO, false, "Unable to read dark ordinates.");
+        return false;
+    }
+    psMetadataAddPtr(cell->analysis, PS_LIST_TAIL, PM_DARK_ANALYSIS_ORDINATES,
+                     PS_DATA_ARRAY | PS_META_REPLACE, "Dark ordinates", ordinates);
+    psMetadataAddStr(cell->analysis, PS_LIST_TAIL, PM_DARK_ANALYSIS_NORM, PS_META_REPLACE,
+                     "Dark normalisation", normConcept);
+    psFree(ordinates);
+    psFree(normConcept);
+
+    return true;
+}
+
+psArray *pmDarkRead(psString *normConcept, psFits *fits)
+{
+    PS_ASSERT_PTR_NON_NULL(normConcept, NULL);
+    PS_ASSERT_PTR_NULL(*normConcept, NULL);
+    PS_ASSERT_FITS_NON_NULL(fits, NULL);
+
+    if (!psFitsMoveExtName(fits, PM_DARK_FITS_EXTNAME)) {
+        psError(PS_ERR_IO, false, "Unable to find extension with dark ordinates table (%s).",
+                PM_DARK_FITS_EXTNAME);
+        return false;
+    }
+
+    psMetadata *header = psFitsReadHeader(NULL, fits); // Header
+    bool mdok;                          // Status of MD lookup
+    *normConcept = psMemIncrRefCounter(psMetadataLookupStr(&mdok, header, PM_DARK_HEADER_NORM));
+
+    psArray *ordinates = NULL;          // Dark ordinates to return
+
+    psFitsType type = psFitsGetExtType(fits); // Type of FITS extension
+    switch (type) {
+      case PS_FITS_TYPE_IMAGE: {
+          // Check that it's of zero size; otherwise we might have some conflict
+          int numCols = psMetadataLookupS32(&mdok, header, "NAXIS1");
+          int numRows = psMetadataLookupS32(&mdok, header, "NAXIS2");
+          if (numCols != 0 || numRows != 0) {
+              psError(PS_ERR_UNKNOWN, true, "Extension %s is not a DARK table.", PM_DARK_FITS_EXTNAME);
+              psFree(header);
+              return NULL;
+          }
+          // No ordinates fit --- only a constant term
+          ordinates = psArrayAlloc(0);
+          break;
+      }
+      case PS_FITS_TYPE_BINARY_TABLE:
+      case PS_FITS_TYPE_ASCII_TABLE: {
+          psArray *table = psFitsReadTable(fits); // FITS Table with ordinates
+          int numOrdinates = table->n;        // Number of ordinates
+          ordinates = psArrayAlloc(numOrdinates);
+
+          for (int i = 0; i < numOrdinates; i++) {
+              psMetadata *row = table->data[i]; // Row of interest
+              const char *name = psMetadataLookupStr(NULL, row, PM_DARK_FITS_NAME); // Concept name
+              int order = psMetadataLookupS32(NULL, row, PM_DARK_FITS_ORDER); // Polynomial order
+              if (!name || order <= 0) {
+                  psError(PS_ERR_UNKNOWN, false, "Bad value reading dark ordinates table.");
+                  psFree(table);
+                  psFree(ordinates);
+                  return false;
+              }
+              pmDarkOrdinate *ord = pmDarkOrdinateAlloc(name, order); // Ordinate data
+              ord->scale = psMetadataLookupBool(NULL, row, PM_DARK_FITS_SCALE);
+              ord->min = psMetadataLookupF32(NULL, row, PM_DARK_FITS_MIN);
+              ord->max = psMetadataLookupF32(NULL, row, PM_DARK_FITS_MAX);
+
+              ordinates->data[i] = ord;
+          }
+          psFree(table);
+          break;
+      }
+      default:
+        psError(PS_ERR_UNKNOWN, true, "Unrecognised FITS extension type.");
+        return NULL;
+    }
+    psFree(header);
+
+    return ordinates;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmDark.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmDark.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmDark.h	(revision 22158)
@@ -0,0 +1,99 @@
+#ifndef PM_DARK_H
+#define PM_DARK_H
+
+#include <pslib.h>
+#include <pmHDU.h>
+#include <pmFPA.h>
+#include <pmConfig.h>
+
+#define PM_DARK_ANALYSIS_ORDINATES "DARK.ORDINATES" // Name for dark ordinates in the cell analysis metadata
+#define PM_DARK_ANALYSIS_NORM "DARK.NORM" // Name for dark normalisation concept in cell analysis metadata
+#define PM_DARK_HEADER_NORM "PSDRKNRM"  // Header keyword for dark normalisation concept
+
+// An ordinate for fitting darks
+typedef struct {
+    psString name;                      // Name of concept to fit
+    int order;                          // Polynomial order to fit
+    bool scale;                         // Rescale values?
+    float min, max;                     // Minimum and maximum values for rescaling
+} pmDarkOrdinate;
+
+// Allocator
+pmDarkOrdinate *pmDarkOrdinateAlloc(const char *name, // Name for ordinate
+                                    int order // Order for ordinate
+    );
+
+
+// Combine darks
+bool pmDarkCombine(pmCell *output,      // Output cell; readouts will be attached
+                   const psArray *inputs, // Input readouts for combination
+                   psArray *ordinates,  // Ordinates for fitting
+                   const char *normConcept, // Concept name to use to divide input pixel values
+                   int iter,            // Number of rejection iterations
+                   float rej,           // Rejection threshold (standard deviations)
+                   psMaskType maskVal   // Value to mask
+    );
+
+// Apply dark
+bool pmDarkApply(pmReadout *readout,    // Readout to which to apply dark
+                 const pmCell *dark,    // Dark to apply
+                 psMaskType bad         // Mask value to give bad pixels
+    );
+
+// I/O functions for darks
+
+// Write all darks within an FPA
+bool pmFPAWriteDark(pmFPA *fpa,         // FPA to write
+                    psFits *fits,       // FITS file to which to write
+                    pmConfig *config,   // Configuration
+                    bool blank,         // Write a blank only?
+                    bool recurse        // Recurse to lower levels?
+    );
+
+// Write all darks within a chip
+bool pmChipWriteDark(pmChip *chip,      // Chip to write
+                     psFits *fits,      // FITS file to which to write
+                     pmConfig *config,  // Configuration
+                     bool blank,        // Write a blank only?
+                     bool recurse       // Recurse to lower levels?
+    );
+
+// Write a dark to a FITS file
+bool pmCellWriteDark(pmCell *cell,      // Cell containing dark information
+                     psFits *fits,      // FITS file to which to write
+                     pmConfig *config,  // Configuration
+                     bool blank         // Write a blank only?
+    );
+
+// Read dark for all FPA from a FITS file
+bool pmFPAReadDark(pmFPA *fpa,          // FPA for which to read
+                   psFits *fits,        // FITS file to read
+                   pmConfig *config     // Configuration
+    );
+
+// Read dark for all chip from a FITS file
+bool pmChipReadDark(pmChip *chip,       // Chip for which to read
+                    psFits *fits,       // FITS file to read
+                    pmConfig *config    // Configuration
+    );
+
+// Read dark for a cell from a FITS file
+bool pmCellReadDark(pmCell *cell,       // Cell for which to read
+                    psFits *fits,       // FITS file to read
+                    pmConfig *config    // Configuration
+    );
+
+// Write dark table to FITS file
+bool pmDarkWrite(psFits *fits,          // FITS file to which to write
+                 psMetadata *header,    // Header to write
+                 const psArray *ordinates, // Dark ordinates to write
+                 const char *normConcept // Normalisation concept name
+    );
+
+// Read dark table from FITS file
+psArray *pmDarkRead(psString *normConcept, // Normalisation concept name
+                    psFits *fits        // FITS file to read
+    );
+
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmDetrendDB.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmDetrendDB.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmDetrendDB.c	(revision 22158)
@@ -0,0 +1,337 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmConfigCommand.h"
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmDetrendDB.h"
+#include "psPipe.h"
+#include "psIOBuffer.h"
+
+// ************* detrend select functions **************
+
+//
+static void pmDetrendSelectOptionsFree (pmDetrendSelectOptions *options)
+{
+
+    if (!options)
+        return;
+
+    psFree (options->camera);
+    psFree (options->filter);
+    psFree (options->dettype);
+    psFree (options->version);
+
+    return;
+}
+
+// define basic options for a new detrend database query
+pmDetrendSelectOptions *pmDetrendSelectOptionsAlloc(const char *camera, psTime time, pmDetrendType type)
+{
+
+    pmDetrendSelectOptions *options = psAlloc(sizeof(pmDetrendSelectOptions));
+    psMemSetDeallocator(options, (psFreeFunc) pmDetrendSelectOptionsFree);
+
+    // basic options required by every query
+    options->camera = psStringCopy (camera);
+    options->time   = time;
+    options->type   = type;
+
+    // these other options depend on the type of detrend data
+    options->filter   = NULL;
+    options->version  = NULL;
+    options->dettype  = NULL;
+    options->exptime  = 0.0;
+    options->airmass  = 0.0;
+    options->dettemp  = 0.0;
+    options->twilight = 0.0;
+
+    options->exptimeSet  = false; // not selected
+    options->airmassSet  = false; // not selected
+    options->dettempSet  = false; // not selected
+    options->twilightSet = false; // not selected
+
+    return options;
+}
+
+static void pmDetrendSelectResultsFree (pmDetrendSelectResults *results)
+{
+
+    if (!results)
+        return;
+
+    psFree (results->detID);
+    psFree(results->level);
+
+    return;
+}
+
+pmDetrendSelectResults *pmDetrendSelectResultsAlloc ()
+{
+
+    pmDetrendSelectResults *results = psAlloc(sizeof(pmDetrendSelectResults));
+    psMemSetDeallocator(results, (psFreeFunc) pmDetrendSelectResultsFree);
+
+    results->detID = NULL;
+    results->level = NULL;
+
+    return results;
+}
+
+psString pmDetrendTypeToString (pmDetrendType type)
+{
+
+    # define DETREND_STRING_CASE(TTT) \
+case PM_DETREND_TYPE_##TTT: \
+    return psStringCopy (#TTT);
+
+    switch (type) {
+        DETREND_STRING_CASE (MASK);
+        DETREND_STRING_CASE (BIAS);
+        DETREND_STRING_CASE (DARK);
+        DETREND_STRING_CASE (FLAT);
+        DETREND_STRING_CASE (FLAT_CORRECTION);
+        DETREND_STRING_CASE (SHUTTER);
+        DETREND_STRING_CASE (FRINGE);
+        DETREND_STRING_CASE (ASTROM);
+    default:
+        return NULL;
+    }
+    return NULL;
+}
+
+// detselect -camera (camera) -time (time) -type (type) [others]
+// returns: (type) (class) (exp_flag) DONE
+pmDetrendSelectResults *pmDetrendSelect (const pmDetrendSelectOptions *options,
+        const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(options, NULL);
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    int status, exit_status;
+    psString line = NULL;
+    psString time = psTimeToISO (&options->time);
+
+    char *type = NULL;
+    if (options->dettype) {
+        type = psMemIncrRefCounter (options->dettype);
+    } else {
+        type = pmDetrendTypeToString (options->type);
+    }
+    unsigned int nFail;
+
+    pmDetrendSelectResults *results = pmDetrendSelectResultsAlloc();
+    psStringAppend(&line, "detselect -search -inst %s -det_type %s -time %s", options->camera, type, time);
+
+    if (options->filter) {
+        psStringAppend(&line, " -filter %s", options->filter);
+    }
+    if (options->version) {
+        psStringAppend(&line, " -version %s", options->version);
+    }
+    if (options->exptimeSet) {
+        psStringAppend(&line, " -exp_time %f", options->exptime);
+    }
+    if (options->airmassSet) {
+        psStringAppend(&line, " -airmass %f", options->airmass);
+    }
+    if (options->dettempSet) {
+        psStringAppend(&line, " -airmass %f", options->dettemp);
+    }
+    if (options->twilightSet) {
+        psStringAppend(&line, " -airmass %f", options->twilight);
+    }
+
+    psIOBuffer *buffer = NULL;
+    psPipe *pipe = NULL;
+    psMetadata *answer = NULL;
+
+    if (!pmConfigDatabaseCommand(&line, config)) {
+        psError (PS_ERR_IO, false, "error building detrend command %s", line);
+        goto failure;
+    }
+
+    if (!pmConfigTraceCommand(&line)) {
+        psError (PS_ERR_IO, false, "error building detrend command %s", line);
+        goto failure;
+    }
+
+    psTrace("psModules.detrend", 5, "running %s", line);
+
+    // use psPipe to exec the command, wait for response
+    buffer = psIOBufferAlloc (512);
+    pipe = psPipeOpen (line);
+    if (!pipe) {
+        psError (PS_ERR_IO, false, "error calling command %s", line);
+        goto failure;
+    }
+
+    status = psIOBufferReadEmpty (buffer, 2000, pipe->fd_stdout);
+    if (!status) {
+        psError (PS_ERR_IO, false, "detselect is not responding");
+        psLogMsg ("psModule.detrend", PS_LOG_ERROR, "detselect command:\n %s\n", line);
+        goto failure;
+    }
+    exit_status = psPipeClose (pipe);
+    if (exit_status) {
+        psError (PS_ERR_IO, false, "error running detselect");
+        psLogMsg ("psModule.detrend", PS_LOG_ERROR, "detselect command:\n %s\n", line);
+        goto failure;
+    }
+
+    psTrace("psModules.detrend", 5, "got answer: %s\n", buffer->data);
+
+    nFail = 0;
+    answer = psMetadataConfigParse (NULL, &nFail, buffer->data, false);
+    if (!answer) {
+        psError(PS_ERR_IO, false, "failed to parse response from detselect\n");
+        psLogMsg ("psModule.detrend", PS_LOG_ERROR, "detselect response (%d bytes):\n %s\n", buffer->n, buffer->data);
+        psLogMsg ("psModule.detrend", PS_LOG_ERROR, "detselect command:\n %s\n", line);
+        goto failure;
+    }
+
+    psMetadata *md = psMetadataLookupPtr (NULL, answer, "detExp");
+    if (!md) {
+        psError(PS_ERR_IO, false, "detselect response is missing 'detExp' Metadata\n");
+        psLogMsg ("psModule.detrend", PS_LOG_ERROR, "detselect response:\n %s\n", buffer->data);
+        goto failure;
+    }
+
+    bool mdstatus;
+    int detID = psMetadataLookupS32 (&mdstatus, md, "det_id");
+    if (!mdstatus) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find det_id in output from detselect.");
+        psLogMsg ("psModule.detrend", PS_LOG_ERROR, "detselect response:\n %s\n", buffer->data);
+        goto failure;
+    }
+    int iteration  = psMetadataLookupS32 (&mdstatus, md, "iteration");
+    if (!mdstatus) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find iteration in output from detselect.");
+        psLogMsg ("psModule.detrend", PS_LOG_ERROR, "detselect response:\n %s\n", buffer->data);
+        goto failure;
+    }
+    psString fileLevel = psMetadataLookupStr(&mdstatus, md, "filelevel");
+    if (!mdstatus || !fileLevel || strlen(fileLevel) == 0) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find filelevel in output from detselect.");
+        psLogMsg ("psModule.detrend", PS_LOG_ERROR, "detselect response:\n %s\n", buffer->data);
+        goto failure;
+    }
+
+    results->detID = NULL; // it should be NULL already from the Alloc above
+    psStringAppend (&results->detID, " -det_id %d -iteration %d ", detID, iteration);
+    results->level = psMemIncrRefCounter(fileLevel);
+
+    psTrace("psModules.detrend", 5, "generated detID %s\n", results->detID);
+
+    psFree (answer);
+    psFree (buffer);
+    psFree (pipe);
+    psFree (line);
+    psFree (time);
+    psFree (type);
+    return results;
+
+failure:
+    psFree (answer);
+    psFree (results);
+    psFree (pipe);
+    psFree (buffer);
+    psFree (line);
+    psFree (type);
+    psFree (time);
+    return NULL;
+}
+
+// ************* detrend file functions **************
+
+// detselect -select -detID (detID) -classID (classID)
+// returns: (detID) (classID) (filename) DONE
+char *pmDetrendFile (const char *detID, const char *classID, const pmConfig *config)
+{
+    unsigned int nFail;
+
+    PS_ASSERT_PTR_NON_NULL(detID, NULL);
+
+    bool status;
+    psString line = NULL;
+    psArray *array = NULL;
+
+    // generate the detselect command
+    psStringAppend (&line, "detselect -select %s", detID);
+    if (classID && strlen(classID) > 0) {
+        psStringAppend(&line, " -class_id %s", classID);
+    }
+    pmConfigDatabaseCommand(&line, config);
+    pmConfigTraceCommand(&line);
+    psTrace("psModules.detrend", 5, "running %s", line);
+
+    // use psPipe to exec the command, wait for response
+    psIOBuffer *buffer = psIOBufferAlloc (512);
+    psPipe *pipe = psPipeOpen (line);
+    if (!pipe) {
+        psError (PS_ERR_IO, false, "error calling command %s", line);
+        goto failure;
+    }
+
+    // timeout somewhat longer than 2sec.  this could still be too short....
+    status = psIOBufferReadEmpty (buffer, 2000, pipe->fd_stdout);
+    if (!status) {
+        psError (PS_ERR_IO, false, "detselect is not responding");
+        goto failure;
+    }
+    status = psPipeClose (pipe);
+    if (status) {
+        psError (PS_ERR_IO, false, "error running detselect");
+        goto failure;
+    }
+
+    psTrace("psModules.detrend", 5, "got answer: %s\n", buffer->data);
+
+    if (!buffer->n) {
+        psLogMsg ("psModule.detrend", PS_LOG_ERROR, "detselect response (%d bytes):\n %s\n", buffer->n, buffer->data);
+        psError(PS_ERR_IO, true, "no matching detrend data in database\n");
+        goto failure;
+    }
+
+    psMetadata *answer = psMetadataConfigParse (NULL, &nFail, buffer->data, false);
+    if (!answer) {
+        psError(PS_ERR_IO, false, "failed to parse response from detselect\n");
+        psLogMsg ("psModule.detrend", PS_LOG_ERROR, "detselect response (%d bytes):\n %s\n", buffer->n, buffer->data);
+        goto failure;
+    }
+    psMetadataItem *item = psMetadataLookup (answer, "detNormalizedImfile");
+    if ((item->type == PS_DATA_METADATA_MULTI) && (item->data.list->n > 1)) {
+        psError(PS_ERR_IO, false, "detselect returned too many files\n");
+        goto failure;
+    }
+
+    psMetadata *md = psMetadataLookupPtr (NULL, answer, "detNormalizedImfile");
+    if (!md) {
+        psError(PS_ERR_IO, false, "detselect response is missing 'detNormalizedImfile' Metadata\n");
+        psLogMsg ("psModule.detrend", PS_LOG_ERROR, "detselect response:\n %s\n", buffer->data);
+        goto failure;
+    }
+
+    char *result = psStringCopy (psMetadataLookupStr (NULL, md, "uri"));
+    psTrace("psModules.detrend", 5, "detrend file: %s\n", result);
+
+    psFree (answer);
+    psFree (pipe);
+    psFree (buffer);
+    psFree (line);
+    return result;
+
+failure:
+    psFree (array);
+    psFree (pipe);
+    psFree (buffer);
+    psFree (line);
+    return NULL;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmDetrendDB.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmDetrendDB.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmDetrendDB.h	(revision 22158)
@@ -0,0 +1,65 @@
+/* @file  pmDetrendDB.h
+ * @brief Tools to query the detrend database system
+ *
+ * the functions in here do not perform the detrend database queries directly.  all interfaces
+ * to the detrend database go through the external dettools functions.  this allows the modules
+ * and directly dependent program to be sufficiently independent of the database schema that it
+ * can be used with any properly defined detrend database tables.
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
+ * Copyright 2004-2005 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_DETREND_DB_H
+#define PM_DETREND_DB_H
+
+/// @addtogroup detrend Detrend Creation and Application
+/// @{
+
+typedef enum {
+    PM_DETREND_TYPE_MASK,
+    PM_DETREND_TYPE_BIAS,
+    PM_DETREND_TYPE_DARK,
+    PM_DETREND_TYPE_FLAT,
+    PM_DETREND_TYPE_FLAT_CORRECTION,
+    PM_DETREND_TYPE_SHUTTER,
+    PM_DETREND_TYPE_FRINGE,
+    PM_DETREND_TYPE_BACKGROUND,
+    PM_DETREND_TYPE_ASTROM,
+} pmDetrendType;
+
+typedef struct {
+    char *camera;                       // name of camera
+    char *version;                      // optional version string
+    char *filter;                       // name of filter
+    char *dettype;                      // actual detrend type name
+    float exptime;                      // exposure time (for dark, maybe flat & fringe)
+    float airmass;                      // for fringe
+    float dettemp;                      // for fringe
+    float twilight;                     // hours (or seconds?) since/before nearest twilight
+    psTime time;                        // time of input data
+    pmDetrendType type;                 // type of detrend data
+
+    bool  exptimeSet;
+    bool  airmassSet;
+    bool  dettempSet;
+    bool  twilightSet;
+} pmDetrendSelectOptions;
+
+typedef struct {
+    char *detID;                        // identifier of detrend run
+    psString level;                     // level in FPA hierarchy of individual file
+} pmDetrendSelectResults;
+
+psString pmDetrendTypeToString (pmDetrendType type);
+
+pmDetrendSelectOptions *pmDetrendSelectOptionsAlloc(const char *camera, psTime time, pmDetrendType type);
+pmDetrendSelectResults *pmDetrendSelectResultsAlloc();
+pmDetrendSelectResults *pmDetrendSelect (const pmDetrendSelectOptions *options, const pmConfig *config);
+char *pmDetrendFile (const char *detID, const char *classID, const pmConfig *config);
+
+/// @}
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmFlatField.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmFlatField.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmFlatField.c	(revision 22158)
@@ -0,0 +1,119 @@
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmHDUUtils.h"
+#include "pmFPAMaskWeight.h"
+#include "pmFlatField.h"
+
+bool pmFlatField(pmReadout *in, const pmReadout *flat, psMaskType badFlat)
+{
+    PS_ASSERT_PTR_NON_NULL(in, false);
+    PS_ASSERT_PTR_NON_NULL(in->image, false);
+    PS_ASSERT_IMAGE_NON_EMPTY(in->image, false);
+    PS_ASSERT_PTR_NON_NULL(flat, false);
+    PS_ASSERT_PTR_NON_NULL(flat->image, false);
+    PS_ASSERT_IMAGE_NON_EMPTY(flat->image, false);
+    if (in->mask) {
+        PS_ASSERT_IMAGE_TYPE(in->mask, PS_TYPE_MASK, false);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(in->mask, in->image, false);
+    }
+    PS_ASSERT_IMAGE_TYPE(flat->image, in->image->type.type, false);
+    if (flat->mask) {
+        PS_ASSERT_IMAGE_TYPE(flat->mask, PS_TYPE_MASK, false);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(flat->mask, flat->image, false);
+    }
+
+    psImage *inImage   = in->image;     // Input image
+    psImage *inMask    = in->mask;      // Mask for input image
+    psImage *flatImage = flat->image;   // Flat-field image
+    psImage *flatMask  = flat->mask;    // Mask for flat-field image
+
+    // Add flat-field MD5 to header
+    pmHDU *hdu = pmHDUFromReadout(in);  // HDU of interest
+    psVector *md5 = psImageMD5(flat->image); // md5 hash
+    psString md5string = psMD5toString(md5); // String
+    psFree(md5);
+    psStringPrepend(&md5string, "FLAT image MD5: ");
+    psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK,
+                     md5string, "");
+    psFree(md5string);
+
+    // Check input image is not larger than flat image; mask is the same size as the input
+    if (inImage->numRows > flatImage->numRows || inImage->numCols > flatImage->numCols) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Input image (%dx%d) is larger than flat-field image "
+                "(%dx%d).\n", inImage->numCols, inImage->numRows, flatImage->numCols, flatImage->numRows);
+        return false;
+    }
+
+    // Offsets on the chip
+    int x0in = psMetadataLookupS32(NULL, in->parent->concepts, "CELL.X0");
+    int y0in = psMetadataLookupS32(NULL, in->parent->concepts, "CELL.Y0");
+    int x0flat = psMetadataLookupS32(NULL, flat->parent->concepts, "CELL.X0");
+    int y0flat = psMetadataLookupS32(NULL, flat->parent->concepts, "CELL.Y0");
+
+    // Determine offset based on image offset with chip offset: input frame to flat frame
+    int yOffset = in->row0 + y0in - flat->row0 - y0flat;
+    int xOffset = in->col0 + x0in - flat->col0 - x0flat;
+
+    // Check that offsets are within image limits
+    if (inImage->numRows + yOffset > flatImage->numRows ||
+            inImage->numCols + xOffset > flatImage->numCols) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Input image (%dx%d) with offsets (%d,%d) is larger than "
+                "flat-field image (%dx%d).\n", inImage->numCols, inImage->numRows, xOffset, yOffset,
+                flatImage->numCols, flatImage->numRows);
+        return false;
+    }
+
+    // Macro for all PS types
+    #define FLAT_DIVISION_CASE(TYPE, SPECIAL) \
+case PS_TYPE_##TYPE: \
+    for (int j = 0; j < inImage->numRows; j++) { \
+        for (int i = 0; i < inImage->numCols; i++) { \
+            ps##TYPE flatValue = flatImage->data.TYPE[j + yOffset][i + xOffset]; \
+            if (!isfinite(flatValue) || flatValue <= 0.0 || \
+                (flatMask && flatMask->data.U8[j + yOffset][i + xOffset])) { \
+                if (inMask) { \
+                    inMask->data.PS_TYPE_MASK_DATA[j][i] |= badFlat; \
+                } \
+                inImage->data.TYPE[j][i] = SPECIAL; \
+            } else { \
+                inImage->data.TYPE[j][i] /= flatValue; \
+            } \
+        } \
+    } \
+    break;
+
+    switch (inImage->type.type) {
+        FLAT_DIVISION_CASE(U8,  0);
+        FLAT_DIVISION_CASE(U16, 0);
+        FLAT_DIVISION_CASE(U32, 0);
+        FLAT_DIVISION_CASE(U64, 0);
+        FLAT_DIVISION_CASE(S8,  0);
+        FLAT_DIVISION_CASE(S16, 0);
+        FLAT_DIVISION_CASE(S32, 0);
+        FLAT_DIVISION_CASE(S64, 0);
+        FLAT_DIVISION_CASE(F32, NAN);
+        FLAT_DIVISION_CASE(F64, NAN);
+    default:
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Unsupported type for input image: %x\n",
+                inImage->type.type);
+        return false;
+    }
+
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now, used for reporting
+    psString timeString = psTimeToISO(time); // String with time
+    psFree(time);
+    psStringPrepend(&timeString, "Flat-field processing completed at ");
+    psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK,
+                     timeString, "");
+    psFree(timeString);
+
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmFlatField.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmFlatField.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmFlatField.h	(revision 22158)
@@ -0,0 +1,30 @@
+/* @file pmFlatField.h
+ * @brief Apply flat field calibration
+ *
+ * @author Ross Harman, MHPCC
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-06-02 03:51:03 $
+ * Copyright 2004-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FLAT_FIELD_H
+#define PM_FLAT_FIELD_H
+
+/// @addtogroup detrend Detrend Creation and Application
+/// @{
+
+/// Apply flat field calibration to a readout
+///
+/// This function applies the flat field calibration to the input readout.  Support is available for different
+/// image types, though the input and flat images must have the same type.  The relative offsets between the
+/// input and flat images is determined from the readout row0,col0 and the CELL.X0 and CELL.Y0 concepts.
+/// Normalisation of the flat is left as the responsibility of the caller.  Non-positive pixels in the flat
+/// are masked, if there is a mask present in the input readout.
+bool pmFlatField(pmReadout *in,         ///< Readout with input image
+                 const pmReadout *flat,  ///< Readout with flat image
+                 psMaskType badFlat     ///< Mask value to give bad flat pixels
+                );
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmFlatNormalize.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmFlatNormalize.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmFlatNormalize.c	(revision 22158)
@@ -0,0 +1,189 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <math.h>
+#include <pslib.h>
+
+#include "pmFlatNormalize.h"
+
+// I'm not sure that many many iterations are required, but rather suspect that the system converges within a
+// few with absolutely no trouble (it *is* over-constrained).  For this reason, I'm putting the maximum number
+// of iterations and tolerance as preset values.
+#define MAXITER 10                      // Maximum number of iterations
+#define TOLERANCE 1e-3                  // Minimum tolerance for convergance
+
+
+bool pmFlatNormalize(psVector **expFluxesPtr, psVector **chipGainsPtr, const psImage *bgMatrix)
+{
+    PS_ASSERT_PTR_NON_NULL(bgMatrix, false);
+    PS_ASSERT_IMAGE_NON_NULL(bgMatrix, false);
+
+    int numExps = bgMatrix->numRows; // Number of exposures
+    int numChips = bgMatrix->numCols; // Number of chips with which each exposure is made
+
+    psVector *expFluxes;                // Dereferenced version of expFluxesPtr
+    if (expFluxesPtr) {
+        if (*expFluxesPtr) {
+            PS_ASSERT_VECTOR_TYPE(*expFluxesPtr, PS_TYPE_F32, false);
+            PS_ASSERT_VECTOR_SIZE(*expFluxesPtr, (long)numExps, false);
+        } else {
+            *expFluxesPtr = psVectorAlloc(numExps, PS_TYPE_F32);
+        }
+        expFluxes = psMemIncrRefCounter(*expFluxesPtr);
+    } else {
+        expFluxes = psVectorAlloc(numExps, PS_TYPE_F32);
+    }
+
+    psVector *chipGains;                // Dereferenced version of chipGainsPtr
+    if (chipGainsPtr) {
+        if (*chipGainsPtr) {
+            PS_ASSERT_VECTOR_TYPE(*chipGainsPtr, PS_TYPE_F32, false);
+            PS_ASSERT_VECTOR_SIZE(*chipGainsPtr, (long)numChips, false);
+        } else {
+            *chipGainsPtr = psVectorAlloc(numChips, PS_TYPE_F32);
+            psVectorInit(*chipGainsPtr, 1.0);
+        }
+        chipGains = psMemIncrRefCounter(*chipGainsPtr);
+    } else {
+        chipGains = psVectorAlloc(numChips, PS_TYPE_F32);
+        psVectorInit(chipGains, 1.0);
+    }
+
+    // Take the logarithms
+    psImage *flux = psImageCopy(NULL, bgMatrix, PS_TYPE_F32); // Copy of the input flux levels matrix
+    psImage *fluxMask = psImageAlloc(numChips, numExps, PS_TYPE_U8); // Mask for bad measurements
+    psImageInit(fluxMask, 0);
+    psVector *gainMask = psVectorAlloc(numChips, PS_TYPE_U8); // Mask for bad gains
+    psVectorInit(gainMask, 0);
+    psVector *expMask = psVectorAlloc(numExps, PS_TYPE_U8); // Mask for bad exposures
+    psVectorInit(expMask, 0);
+    for (int i = 0; i < numChips; i++) {
+        // Note: the input gains are in e/ADU; we want to work with ADU/e (bg [ADU] = g [ADU/e] * f [e])
+        // Hence the minus sign
+        if (isfinite(chipGains->data.F32[i]) && chipGains->data.F32[i] > 0) {
+            chipGains->data.F32[i] = -logf(chipGains->data.F32[i]);
+        } else {
+            chipGains->data.F32[i] = 0.0; // Take a wild guess, gain ~ 1 e/ADU
+        }
+
+        for (int j = 0; j < numExps; j++) {
+            if (isfinite(flux->data.F32[j][i]) && flux->data.F32[j][i] > 0) {
+                flux->data.F32[j][i] = logf(flux->data.F32[j][i]);
+            } else {
+                // Blank out this measurement
+                fluxMask->data.U8[j][i] = 1;
+                flux->data.F32[j][i] = NAN;
+            }
+        }
+    }
+
+    // Not really sure that we need to iterate, but here we go anyway...
+
+    float diff = INFINITY;              // Difference from previous iteration
+    psVector *oldExpFluxes = NULL;      // The fluxes in the previous iteration
+    psVector *oldChipGains = NULL;      // Chip gains in the previous iteration
+    for (int iter = 0; iter < MAXITER && diff > TOLERANCE; iter++) {
+        // Improve on the exposure fluxes
+        int numFluxes = 0;              // Number of fluxes
+        for (int i = 0; i < numExps; i++) {
+            if (expMask->data.U8[i]) {
+                psTrace("psModules.detrend", 7, "Flux for exposure %d is masked.\n", i);
+                continue;
+            }
+            numFluxes++;
+            float sum = 0.0;            // Sum of F_ij - G_j
+            int number = 0;             // Number of chips contributing
+            for (int j = 0; j < numChips; j++) {
+                if (!gainMask->data.U8[j] && !fluxMask->data.U8[i][j]) {
+                    sum += flux->data.F32[i][j] - chipGains->data.F32[j];
+                    number++;
+                }
+            }
+            if (number > 0) {
+                expFluxes->data.F32[i] = sum / (float)number;
+            } else {
+                expMask->data.U8[i] = 1;
+                expFluxes->data.F32[i] = NAN;
+            }
+            psTrace("psModules.detrend", 7, "Flux for exposure %d is %lf\n", i, expf(expFluxes->data.F32[i]));
+        }
+
+        // Improve on the gains
+        float meanGain = 0.0;           // Mean gain
+        int numGains = 0;               // Number of gains
+        for (int i = 0; i < numChips; i++) {
+            if (gainMask->data.U8[i]) {
+                continue;
+            }
+            float sum = 0.0;           // Sum of F_ji - S_j
+            int number = 0;             // Numer of sources contributing
+            for (int j = 0; j < numExps; j++) {
+                if (!fluxMask->data.U8[j][i]) {
+                    sum += flux->data.F32[j][i] - expFluxes->data.F32[j];
+                    number++;
+                }
+            }
+            if (number > 0) {
+                chipGains->data.F32[i] = sum / (float)number;
+            } else {
+                gainMask->data.U8[i] = 1;
+                chipGains->data.F32[i] = NAN;
+            }
+            psTrace("psModules.detrend", 7, "Gain for chip %d is %lf\n", i, expf(-chipGains->data.F32[i]));
+            meanGain += expf(chipGains->data.F32[i]);
+            numGains++;
+        }
+
+        // Normalise the mean gain to unity, and measure the difference
+        meanGain /= (float)numGains;
+        meanGain = logf(meanGain);
+        if (iter > 0) {
+            diff = 0.0;
+            for (int i = 0; i < numChips; i++) {
+                if (gainMask->data.U8[i]) {
+                    continue;
+                }
+                chipGains->data.F32[i] -= meanGain;
+                diff += abs((chipGains->data.F32[i] - oldChipGains->data.F32[i]) / chipGains->data.F32[i]);
+            }
+            for (int i = 0; i < numExps; i++) {
+                if (expMask->data.U8[i]) {
+                    continue;
+                }
+                diff += abs((expFluxes->data.F32[i] - oldExpFluxes->data.F32[i]) / expFluxes->data.F32[i]);
+            }
+        }
+
+        psTrace("psModules.detrend", 2, "Iteration %d: difference is %e\n", iter, diff);
+
+        // Copy the new to the old
+        oldChipGains = psVectorCopy(oldChipGains, chipGains, PS_TYPE_F32);
+        oldExpFluxes = psVectorCopy(oldExpFluxes, expFluxes, PS_TYPE_F32);
+    }
+    psFree(flux);
+    psFree(fluxMask);
+    psFree(oldChipGains);
+    psFree(oldExpFluxes);
+
+    // Un-log the vectors
+    for (int i = 0; i < numChips; i++) {
+        if (!gainMask->data.U8[i]) {
+            chipGains->data.F32[i] = expf(chipGains->data.F32[i]);
+        }
+    }
+    for (int i = 0; i < numExps; i++) {
+        if (!expMask->data.U8[i]) {
+            expFluxes->data.F32[i] = expf(expFluxes->data.F32[i]);
+        }
+    }
+    psFree(gainMask);
+    psFree(expMask);
+
+    psFree(chipGains);
+    psFree(expFluxes);
+
+    return (diff < TOLERANCE); // Did we converge?
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmFlatNormalize.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmFlatNormalize.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmFlatNormalize.h	(revision 22158)
@@ -0,0 +1,31 @@
+/* @file pmFlatNormalize.h
+ * @brief Normalize flat-field measurements
+ *
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-03-30 21:12:56 $
+ * Copyright 2004-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FLAT_NORMALIZE_H
+#define PM_FLAT_NORMALIZE_H
+
+/// @addtogroup detrend Detrend Creation and Application
+/// @{
+
+/// Normalize flat-field measurements
+///
+/// We have f_ij = g_i s_j where f_ij is the flux recorded for chip i and integration j, g_i is the gain for
+/// the i-th chip, s_j is the flux of the source in the j-th integration.  An initial guess for the chip gains
+/// might be helpful, but is not necessary.  The matrix of background measurements contains the background for
+/// the flat fields used in the combination, as a function of exposure (rows) and chip (columns).  The
+/// exposure fluxes and chip gains are modified upon return with the solved values.  Returns true if the
+/// solution converged.
+bool pmFlatNormalize(psVector **expFluxesPtr, ///< Flux in each exposure, or NULL; modified
+                     psVector **chipGainsPtr, ///< Initial guess of the chip gains or NULL; modified
+                     const psImage *bgMatrix ///< Background measurements: rows are exposures, cols are chips
+                    );
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmFringeStats.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmFringeStats.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmFringeStats.c	(revision 22158)
@@ -0,0 +1,1071 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFringeStats.h"
+
+// Future optimisations for speed:
+//
+// 1. Clipping --- don't re-do the matrix setup again, but carry matrix and vector around, subtract
+// contributions from clipped data points.
+// 2. Faster psImageStats (use memcpy?)
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// pmFringeRegions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static void fringeRegionsFree(pmFringeRegions *fringe)
+{
+    psFree(fringe->x);
+    psFree(fringe->y);
+    psFree(fringe->mask);
+    return;
+}
+
+pmFringeRegions *pmFringeRegionsAlloc(int nPts, int dX, int dY, int nX, int nY)
+{
+    pmFringeRegions *fringe = psAlloc(sizeof(pmFringeRegions));
+    (void)psMemSetDeallocator(fringe, (psFreeFunc)fringeRegionsFree);
+
+    fringe->x = NULL;
+    fringe->y = NULL;
+    fringe->mask = NULL;
+
+    fringe->nRequested = nPts;
+    fringe->nAccepted = 0;
+
+    fringe->dX = dX;
+    fringe->dY = dY;
+    fringe->nX = nX;
+    fringe->nY = nY;
+
+    return fringe;
+}
+
+bool pmFringeRegionsCreatePoints(pmFringeRegions *fringe, const psImage *image, psRandom *random)
+{
+    PS_ASSERT_PTR_NON_NULL(fringe, false);
+    PS_ASSERT_PTR_NON_NULL(image, false);
+    PS_ASSERT_IMAGE_NON_EMPTY(image, false);
+
+    double frnd;
+    // create fringe->nRequested
+
+    psRandom *rng;
+    if (random) {
+        rng = psMemIncrRefCounter(random);
+    } else {
+        rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+    }
+
+    fringe->x = psVectorRecycle(fringe->x, fringe->nRequested, PS_TYPE_F32);
+    fringe->y = psVectorRecycle(fringe->y, fringe->nRequested, PS_TYPE_F32);
+    fringe->mask = psVectorRecycle(fringe->mask, fringe->nRequested, PS_TYPE_U8);
+    fringe->x->n = fringe->y->n = fringe->mask->n = fringe->nRequested;
+    psVectorInit(fringe->mask, 0);
+
+    int nX = image->numCols;
+    int nY = image->numRows;
+
+    psF32 *xPt = fringe->x->data.F32;
+    psF32 *yPt = fringe->y->data.F32;
+
+    int dX = fringe->dX;
+    int dY = fringe->dY;
+
+    // generate random points located within image bounds
+    for (int i = 0; i < fringe->nRequested; i++) {
+        frnd = psRandomUniform(rng);
+        xPt[i] = (nX - 2*dX)* frnd + dX;
+        frnd = psRandomUniform(rng);
+        yPt[i] = (nY - 2*dY)* frnd + dY;
+    }
+
+    psFree(rng);
+
+    return true;
+}
+
+bool pmFringeRegionsWriteFits(psFits *fits, psMetadata *header,
+                              const pmFringeRegions *regions, const char *extname)
+{
+    // Make sure the input is well-behaved
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    PS_ASSERT_PTR_NON_NULL(regions, false);
+    psVector *x = regions->x;           // The x positions
+    psVector *y = regions->y;           // The y positions
+    psVector *mask = regions->mask;     // The region mask
+    int numRows = regions->nRequested;  // Number of rows in the table
+    PS_ASSERT_INT_POSITIVE(numRows, false);
+    PS_ASSERT_VECTOR_NON_NULL(x, false);
+    PS_ASSERT_VECTOR_NON_NULL(y, false);
+    PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F32, false);
+    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, false);
+    PS_ASSERT_VECTOR_SIZE(x, (long)numRows, false);
+    PS_ASSERT_VECTOR_SIZE(y, (long)numRows, false);
+    if (mask) {
+        PS_ASSERT_VECTOR_NON_NULL(mask, false);
+        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
+        PS_ASSERT_VECTOR_SIZE(mask, (long)numRows, false);
+    }
+
+    // We need to write:
+    // Scalars: dX, dY, nX, nY
+    // Vectors: x, y, mask
+
+    psMetadata *scalars = psMemIncrRefCounter(header); // Metadata to hold the scalars; will be the header
+    if (!scalars) {
+        scalars = psMetadataAlloc();
+    }
+    psMetadataAddS32(scalars, PS_LIST_TAIL, "PSFRNGDX", PS_META_REPLACE, "Median box half-width",
+                     regions->dX);
+    psMetadataAddS32(scalars, PS_LIST_TAIL, "PSFRNGDY", PS_META_REPLACE, "Median box half-height",
+                     regions->dY);
+    psMetadataAddS32(scalars, PS_LIST_TAIL, "PSFRNGNX", PS_META_REPLACE, "Large-scale smoothing in x",
+                     regions->nX);
+    psMetadataAddS32(scalars, PS_LIST_TAIL, "PSFRNGNY", PS_META_REPLACE, "Large-scale smoothing in y",
+                     regions->nY);
+
+    psArray *table = psArrayAlloc(numRows); // The table
+    // Translate the vectors into the required format for psFitsWriteTable()
+    for (long i = 0; i < numRows; i++) {
+        psMetadata *row = psMetadataAlloc();
+        psMetadataAddF32(row, PS_LIST_TAIL, "x", PS_META_REPLACE, "Fringe position in x", x->data.F32[i]);
+        psMetadataAddF32(row, PS_LIST_TAIL, "y", PS_META_REPLACE, "Fringe position in y", y->data.F32[i]);
+        psU8 maskValue = 0;
+        if (mask && mask->data.U8[i]) {
+            maskValue = 0xff;
+        }
+        psMetadataAddU8(row, PS_LIST_TAIL, "mask", PS_META_REPLACE, "Mask", maskValue);
+        table->data[i] = row;
+    }
+
+    bool success;                       // Success of operation
+    if (!(success = psFitsWriteTable(fits, scalars, table, extname))) {
+        psError(PS_ERR_IO, false, "Unable to write fringe data to extension %s\n", extname);
+    }
+    psFree(scalars);
+    psFree(table);
+
+    return success;
+}
+
+pmFringeRegions *pmFringeRegionsReadFits(psMetadata *header, const psFits *fits, const char *extname)
+{
+    PS_ASSERT_PTR_NON_NULL(fits, NULL);
+
+    if (extname && strlen(extname) > 0) {
+        if (!psFitsMoveExtName(fits, extname)) {
+            psError(PS_ERR_IO, false, "Unable to move to extension %s\n", extname);
+            return NULL;
+        }
+    } else if (!psFitsMoveExtNum(fits, 0, false)) {
+        psError(PS_ERR_IO, false, "Unable to move to PHU\n");
+        return NULL;
+    }
+
+    psMetadata *headerCopy = psMemIncrRefCounter(header); // Copy of the header, or NULL
+
+    headerCopy = psFitsReadHeader(headerCopy, fits); // The FITS header
+    if (!headerCopy) {
+        psError(PS_ERR_IO, false, "Unable to read header for extension %s\n", extname);
+        psFree(header);
+        return NULL;
+    }
+
+    // Read the scalars from the header
+    #define READ_SCALAR(SCALAR, NAME) \
+    int SCALAR = psMetadataLookupS32(&mdok, headerCopy, NAME); \
+    if (!mdok || SCALAR <= 0) { \
+        psError(PS_ERR_IO, true, "Unable to find " NAME " in header of extension %s.\n", extname); \
+        psFree(headerCopy); \
+        return NULL; \
+    }
+
+    // Need to retrieve the scalars: dX, dY, nX, nY
+    bool mdok = true;                   // Status of MD lookup
+    READ_SCALAR(dX, "PSFRNGDX");
+    READ_SCALAR(dY, "PSFRNGDY");
+    READ_SCALAR(nX, "PSFRNGNX");
+    READ_SCALAR(nY, "PSFRNGNY");
+    psFree(headerCopy);
+
+    // Now the vectors: x, y, mask
+    psArray *table = psFitsReadTable(fits); // The table
+    long numRows = table->n;            // Number of rows
+
+    pmFringeRegions *regions = pmFringeRegionsAlloc(numRows, dX, dY, nX, nY); // The fringe regions
+    psVector *x = psVectorAlloc(numRows, PS_TYPE_F32); // x position
+    psVector *y = psVectorAlloc(numRows, PS_TYPE_F32); // y position
+    psVector *mask = psVectorAlloc(numRows, PS_TYPE_U8); // mask
+    regions->x = x;
+    regions->y = y;
+    regions->mask = mask;
+
+    #define READ_REGIONS_ROW(VECTOR, TYPE, NAME, DESCRIPTION) \
+    VECTOR->data.TYPE[i] = psMetadataLookup##TYPE(&mdok, row, NAME); \
+    if (!mdok) { \
+        psError(PS_ERR_IO, true, "Unable to find " #DESCRIPTION " .\n"); \
+        psFree(table); \
+        psFree(regions); \
+        return NULL; \
+    }
+
+    // Translate the table into vectors
+    for (long i = 0; i < numRows; i++) {
+        psMetadata *row = table->data[i]; // Table row
+        READ_REGIONS_ROW(x, F32, "x", "x position");
+        READ_REGIONS_ROW(y, F32, "y", "y position");
+        READ_REGIONS_ROW(mask, U8, "mask", "mask");
+    }
+    psFree(table);
+
+    return regions;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// pmFringeStats
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static void fringeStatsFree(pmFringeStats *stats)
+{
+    psFree(stats->regions);
+    psFree(stats->f);
+    psFree(stats->df);
+}
+
+pmFringeStats *pmFringeStatsAlloc(pmFringeRegions *regions)
+{
+    PS_ASSERT_PTR_NON_NULL(regions, false);
+
+    pmFringeStats *stats = psAlloc(sizeof(pmFringeStats));
+    (void)psMemSetDeallocator(stats, (psFreeFunc)fringeStatsFree);
+
+    int numRegions = regions->nRequested; // Number of regions
+    stats->regions = psMemIncrRefCounter(regions);
+    stats->f = psVectorAlloc(numRegions, PS_TYPE_F32);
+    stats->df = psVectorAlloc(numRegions, PS_TYPE_F32);
+
+    return stats;
+}
+
+pmFringeStats *pmFringeStatsMeasure(pmFringeRegions *fringe, const pmReadout *readout, psMaskType maskVal)
+{
+    PS_ASSERT_PTR_NON_NULL(fringe, NULL);
+    PS_ASSERT_PTR_NON_NULL(readout, NULL);
+    PS_ASSERT_PTR_NON_NULL(readout->image, NULL);
+    PS_ASSERT_IMAGE_NON_EMPTY(readout->image, NULL);
+
+    if (!fringe->x || !fringe->y) {
+        // create the fringe vectors for this image
+        pmFringeRegionsCreatePoints(fringe, readout->image, NULL);
+    }
+
+    PS_ASSERT_PTR_NON_NULL(fringe->x, false);
+    PS_ASSERT_PTR_NON_NULL(fringe->y, false);
+
+    pmFringeStats *measurements = pmFringeStatsAlloc(fringe);
+
+    psF32 *xPt = fringe->x->data.F32;
+    psF32 *yPt = fringe->y->data.F32;
+    psF32 *fPt = measurements->f->data.F32;
+    psF32 *dfPt = measurements->df->data.F32;
+
+    int dX = fringe->dX;
+    int dY = fringe->dY;
+
+    psImage *image = readout->image;
+    psImage *mask  = readout->mask;
+
+    psStats *median = psStatsAlloc(PS_STAT_SAMPLE_MEDIAN); // Median statistics only
+    psStats *medianSd = psStatsAlloc(PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV); // Median and SD
+
+    // Measure the sky in each smoothing box
+    psImage *sky = psImageAlloc(fringe->nX, fringe->nY, PS_TYPE_F32);
+    for (int i = 0; i < fringe->nY; i++) {
+        int y0 = image->row0 + (float)i * (float)image->numRows / (float)fringe->nY;
+        int y1 = image->row0 + (float)(i + 1) * (float)image->numRows / (float)fringe->nY;
+        for (int j = 0; j < fringe->nX; j++) {
+            int x0 = image->col0 + (float)j * (float)image->numCols / (float)fringe->nX;
+            int x1 = image->col0 + (float)(j + 1) * (float)image->numCols / (float)fringe->nX;
+            psRegion region = psRegionSet(x0, x1, y0, y1);
+            psImage *subImage = psImageSubset(image, region); // Subimage of the sky region
+            psImage *subMask = NULL;
+            if (mask) {
+                subMask = psImageSubset(mask, region); // Subimage of the sky region
+            }
+            psImageStats(median, subImage, subMask, maskVal);
+            sky->data.F32[i][j] = median->sampleMedian;
+            psFree(subImage);
+            psFree(subMask);
+        }
+    }
+
+    for (int i = 0; i < fringe->x->n; i++) {
+        psRegion region = psRegionSet(image->col0 + xPt[i] - dX,
+                                      image->col0 + xPt[i] + dX + 1,
+                                      image->row0 + yPt[i] - dY,
+                                      image->row0 + yPt[i] + dY + 1);
+        psImage *subImage = psImageSubset(image, region);
+        psImage *subMask = NULL;
+        if (mask) {
+            subMask = psImageSubset(mask, region);
+        }
+        psImageStats(medianSd, subImage, subMask, maskVal);
+        psFree(subImage);
+        psFree(subMask);
+
+        int xSky = xPt[i] / (float)image->numCols * (float)sky->numCols;
+        int ySky = yPt[i] / (float)image->numRows * (float)sky->numRows;
+
+        fPt[i] = medianSd->sampleMedian - sky->data.F32[ySky][xSky];
+        dfPt[i] = 1.0 / medianSd->sampleStdev;
+
+        psTrace("psModules.detrend", 7, "[%d:%d,%d:%d]: %f %f\n", (int)region.x0, (int)region.x1,
+                (int)region.y0, (int)region.y1, fPt[i], dfPt[i]);
+    }
+    psFree(sky);
+    psFree(median);
+    psFree(medianSd);
+
+    return measurements;
+}
+
+bool pmFringeStatsWriteFits(psFits *fits,
+                            psMetadata *header,
+                            const pmFringeStats *fringe,
+                            const char *extname
+                           )
+{
+    // Make sure the input is well-behaved
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    PS_ASSERT_PTR_NON_NULL(fringe, false);
+    pmFringeRegions *regions = fringe->regions; // The fringe regions
+    PS_ASSERT_PTR_NON_NULL(regions, false);
+    int numRows = regions->nRequested;  // Number of rows in the table
+    PS_ASSERT_INT_POSITIVE(numRows, false);
+    psVector *f = fringe->f;            // The fringe measurements
+    psVector *df = fringe->df;      // The fringe standard deviatiations
+    PS_ASSERT_VECTOR_NON_NULL(f, false);
+    PS_ASSERT_VECTOR_NON_NULL(df, false);
+    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, false);
+    PS_ASSERT_VECTOR_TYPE(df, PS_TYPE_F32, false);
+    PS_ASSERT_VECTOR_SIZE(f, (long)numRows, false);
+    PS_ASSERT_VECTOR_SIZE(df, (long)numRows, false);
+
+    // We need to write:
+    // Vectors: f, df
+    psArray *table = psArrayAlloc(numRows); // The table
+    // Translate the vectors into the required format for psFitsWriteTable()
+    for (long i = 0; i < numRows; i++) {
+        psMetadata *row = psMetadataAlloc();
+        psMetadataAddF32(row, PS_LIST_TAIL, "f", PS_META_REPLACE, "Fringe measurement", f->data.F32[i]);
+        psMetadataAddF32(row, PS_LIST_TAIL, "df", PS_META_REPLACE, "Fringe stdev", df->data.F32[i]);
+        table->data[i] = row;
+    }
+
+    if (!psFitsWriteTable(fits, header, table, extname)) {
+        psError(PS_ERR_IO, false, "Unable to write fringe data to extension %s\n", extname);
+        psFree(table);
+        return false;
+    }
+
+    psFree(table);
+    return true;
+}
+
+pmFringeStats *pmFringeStatsReadFits(psMetadata *header, const psFits *fits, const char *extname,
+                                     pmFringeRegions *regions)
+{
+    PS_ASSERT_PTR_NON_NULL(fits, NULL);
+    PS_ASSERT_PTR_NON_NULL(regions, NULL);
+    PS_ASSERT_INT_POSITIVE(regions->nRequested, NULL);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(regions->x, regions->y, NULL);
+    PS_ASSERT_VECTOR_SIZE(regions->x, (long)regions->nRequested, NULL);
+
+    if (extname && strlen(extname) > 0) {
+        if (!psFitsMoveExtName(fits, extname)) {
+            psError(PS_ERR_IO, false, "Unable to move to extension %s\n", extname);
+            return NULL;
+        }
+    } else if (!psFitsMoveExtNum(fits, 0, false)) {
+        psError(PS_ERR_IO, false, "Unable to move to PHU\n");
+        return NULL;
+    }
+
+    psMetadata *headerCopy = psMemIncrRefCounter(header); // Copy of the header, or NULL
+
+    headerCopy = psFitsReadHeader(headerCopy, fits); // The FITS header
+    if (!headerCopy) {
+        psError(PS_ERR_IO, false, "Unable to read header for extension %s\n", extname);
+        psFree(headerCopy);
+        return NULL;
+    }
+    psFree(headerCopy);
+
+    // Now the vectors: f, df
+    psArray *table = psFitsReadTable(fits); // The table
+    long numRows = table->n;            // Number of rows
+
+    pmFringeStats *fringes = pmFringeStatsAlloc(regions); // The fringe measurements
+    psVector *f = fringes->f;           // fringe measurement
+    psVector *df = fringes->df;         // fringe stdev
+
+    #define READ_STATS_ROW(VECTOR, TYPE, NAME, DESCRIPTION) \
+    VECTOR->data.TYPE[i] = psMetadataLookup##TYPE(&mdok, row, NAME); \
+    if (!mdok) { \
+        psError(PS_ERR_IO, true, "Unable to find " #DESCRIPTION " .\n"); \
+        psFree(table); \
+        psFree(fringes); \
+        return NULL; \
+    }
+
+    // Translate the table into vectors
+    bool mdok;                          // Status of MD lookup
+    for (long i = 0; i < numRows; i++) {
+        psMetadata *row = table->data[i]; // Table row
+        READ_STATS_ROW(f, F32, "f", "fringe measurement");
+        READ_STATS_ROW(df, F32, "df", "fringe standard deviation");
+    }
+    psFree(table);
+
+    return fringes;
+}
+
+
+pmFringeStats *pmFringeStatsConcatenate(const psArray *fringes, const psVector *x0, const psVector *y0)
+{
+    PS_ASSERT_PTR_NON_NULL(fringes, NULL);
+    PS_ASSERT_PTR_NON_NULL(fringes->data, NULL);
+    PS_ASSERT_INT_POSITIVE(fringes->n, NULL);
+    if (x0 && y0) {
+        PS_ASSERT_VECTOR_NON_NULL(x0, NULL);
+        PS_ASSERT_VECTOR_NON_NULL(y0, NULL);
+        PS_ASSERT_VECTOR_TYPE(x0, PS_TYPE_S32, NULL);
+        PS_ASSERT_VECTOR_TYPE(y0, PS_TYPE_S32, NULL);
+        PS_ASSERT_VECTORS_SIZE_EQUAL(x0, y0, NULL);
+        PS_ASSERT_VECTOR_SIZE(x0, fringes->n, NULL);
+        PS_ASSERT_VECTOR_SIZE(y0, fringes->n, NULL);
+    }
+
+    // Get the measurement parameters, and check they are consistent
+    int numPoints = 0;                  // Number of fringe points
+    int dX = 0, dY = 0;                 // Half-width and -height of fringe boxes
+    int nX = 0, nY = 0;                 // Smoothing scales
+    for (long i = 0; i < fringes->n; i++) {
+        pmFringeStats *fringe = fringes->data[i]; // The fringe of interest
+        pmFringeRegions *regions = fringe->regions; // The fringe regions
+        if (numPoints == 0) {
+            dX = regions->dX;
+            dY = regions->dY;
+            nX = regions->nX;
+            nY = regions->nY;
+        } else if (regions->dX != dX || regions->dY != dY || regions->nX != nX || regions->nY != nY) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Fringe %ld has different parameters (%d,%d,%d,%d) "
+                    "from the first (%d,%d,%d,%d).\n", i,
+                    regions->dX, regions->dY, regions->nX, regions->nY, dX, dY, nX, nY);
+            return NULL;
+        }
+        int num = regions->nRequested;  // Number of fringe points
+        if (regions->x->n != num || regions->y->n != num || regions->mask->n != num ||
+                fringe->f->n != num || fringe->df->n != num) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Length of region (%ld,%ld,%ld) and fringe vectors "
+                    "do not match (%ld,%ld) with the official value (%d).\n", regions->x->n, regions->y->n,
+                    regions->mask->n, fringe->f->n, fringe->df->n, num);
+            return NULL;
+        }
+        numPoints += regions->nRequested;
+    }
+
+    pmFringeRegions *newRegions = pmFringeRegionsAlloc(numPoints, dX, dY, nX, nY); // The new list of regions
+    newRegions->x = psVectorAlloc(numPoints, PS_TYPE_F32);
+    newRegions->y = psVectorAlloc(numPoints, PS_TYPE_F32);
+    newRegions->mask = psVectorAlloc(numPoints, PS_TYPE_U8);
+    pmFringeStats *newStats = pmFringeStatsAlloc(newRegions); // The new list of statistics
+
+    long offset = 0;                    // Offset from start of the list
+    for (long i = 0; i < fringes->n; i++) {
+        pmFringeStats *fringe = fringes->data[i]; // The fringe of interest
+        pmFringeRegions *regions = fringe->regions; // The fringe regions
+        // Copy the data over
+        memcpy(&newRegions->x->data.F32[offset], regions->x->data.F32, regions->x->n * sizeof(psF32));
+        memcpy(&newRegions->y->data.F32[offset], regions->y->data.F32, regions->y->n * sizeof(psF32));
+        memcpy(&newRegions->mask->data.U8[offset], regions->mask->data.U8, regions->mask->n * sizeof(psU8));
+        memcpy(&newStats->f->data.F32[offset], fringe->f->data.F32, fringe->f->n * sizeof(psF32));
+        memcpy(&newStats->df->data.F32[offset], fringe->df->data.F32, fringe->df->n * sizeof(psF32));
+        if (x0 && y0) {
+            for (long j = offset; j < offset + regions->x->n; j++) {
+                newRegions->x->data.F32[j] += x0->data.S32[i];
+                newRegions->y->data.F32[j] += y0->data.S32[i];
+            }
+        }
+        offset += regions->nRequested;
+    }
+
+    psFree(newRegions);                 // Drop reference
+    return newStats;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// pmFringeIO
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool pmFringesFormat(pmCell *cell, psMetadata *header, const psArray *fringes)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_ARRAY_NON_NULL(fringes, false);
+
+    // Check the regions are all identical
+    pmFringeRegions *regions = ((pmFringeStats*)fringes->data[0])->regions; // First region
+    for (int i = 1; i < fringes->n; i++) {
+        pmFringeStats *stats = fringes->data[i];
+        if (stats->regions != regions) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Regions for fringe statistics are not identical.\n");
+            return false;
+        }
+    }
+
+    // Ensure the region is legit
+    psVector *x = regions->x;           // The x positions
+    psVector *y = regions->y;           // The y positions
+    psVector *mask = regions->mask;     // The region mask
+    int numRows = regions->nRequested;  // Number of rows in the table
+    PS_ASSERT_INT_POSITIVE(numRows, false);
+    PS_ASSERT_VECTOR_NON_NULL(x, false);
+    PS_ASSERT_VECTOR_NON_NULL(y, false);
+    PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F32, false);
+    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, false);
+    PS_ASSERT_VECTOR_SIZE(x, (long)numRows, false);
+    PS_ASSERT_VECTOR_SIZE(y, (long)numRows, false);
+    if (mask) {
+        PS_ASSERT_VECTOR_NON_NULL(mask, false);
+        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
+        PS_ASSERT_VECTOR_SIZE(mask, (long)numRows, false);
+    }
+
+    // We need to write:
+    // Scalars: dX, dY, nX, nY
+    // Vectors: x, y, mask, f, df
+
+    psMetadata *scalars = psMemIncrRefCounter(header); // Metadata to hold the scalars; will be the header
+    if (!scalars) {
+        scalars = psMetadataAlloc();
+    }
+    psMetadataAddS32(scalars, PS_LIST_TAIL, "PSFRNGDX", PS_META_REPLACE, "Median box half-width",
+                     regions->dX);
+    psMetadataAddS32(scalars, PS_LIST_TAIL, "PSFRNGDY", PS_META_REPLACE, "Median box half-height",
+                     regions->dY);
+    psMetadataAddS32(scalars, PS_LIST_TAIL, "PSFRNGNX", PS_META_REPLACE, "Large-scale smoothing in x",
+                     regions->nX);
+    psMetadataAddS32(scalars, PS_LIST_TAIL, "PSFRNGNY", PS_META_REPLACE, "Large-scale smoothing in y",
+                     regions->nY);
+    psMetadataAdd(cell->analysis, PS_LIST_TAIL, "FRINGE.HEADER", PS_DATA_METADATA,
+                  "Header for fringe data", scalars);
+    psFree(scalars);
+
+
+    psArray *table = psArrayAlloc(numRows); // The table
+    // Translate the vectors into the required format for psFitsWriteTable()
+    for (long i = 0; i < numRows; i++) {
+        psMetadata *row = psMetadataAlloc();
+        psMetadataAddF32(row, PS_LIST_TAIL, "x", PS_META_REPLACE, "Fringe position in x", x->data.F32[i]);
+        psMetadataAddF32(row, PS_LIST_TAIL, "y", PS_META_REPLACE, "Fringe position in y", y->data.F32[i]);
+        psU8 maskValue = 0;             // Mask value
+        if (mask && mask->data.U8[i]) {
+            maskValue = 0xff;
+        }
+
+        psVector *f = psVectorAlloc(fringes->n, PS_TYPE_F32); // Measurements for each fringe component
+        psVector *df = psVectorAlloc(fringes->n, PS_TYPE_F32); // Errors in measurements
+        for (long j = 0; j < fringes->n; j++) {
+            pmFringeStats *stats = fringes->data[j]; // Fringe statistics of interest
+            f->data.F32[j] = stats->f->data.F32[i];
+            df->data.F32[j] = stats->df->data.F32[i];
+            if (!isfinite(f->data.F32[j]) || !isfinite(df->data.F32[j])) {
+                maskValue = 0xff;
+            }
+        }
+        psMetadataAdd(row, PS_LIST_TAIL, "f", PS_DATA_VECTOR | PS_META_REPLACE, "Fringe measurements", f);
+        psMetadataAdd(row, PS_LIST_TAIL, "df", PS_DATA_VECTOR | PS_META_REPLACE, "Fringe errors", df);
+        // Drop references
+        psFree(f);
+        psFree(df);
+
+        psMetadataAddU8(row, PS_LIST_TAIL, "mask", PS_META_REPLACE, "Mask", maskValue);
+        table->data[i] = row;
+    }
+
+    psMetadataAdd(cell->analysis, PS_LIST_TAIL, "FRINGE", PS_DATA_ARRAY, "Fringe data", table);
+
+    return true;
+}
+
+
+psArray *pmFringesParse(pmCell *cell)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, NULL);
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *header = psMetadataLookupMetadata(&mdok, cell->analysis, "FRINGE.HEADER"); // Header
+    if (!mdok || !header) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to find header for fringe data.\n");
+        return NULL;
+    }
+
+    psArray *table = psMetadataLookupPtr(NULL, cell->analysis, "FRINGE"); // FITS table
+    if (!table) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to find table for fringe data.\n");
+        return NULL;
+    }
+
+
+    // Read the scalars from the header
+    #define READ_FRINGES_SCALAR(SCALAR, NAME) \
+    int SCALAR = psMetadataLookupS32(&mdok, header, NAME); \
+    if (!mdok || SCALAR <= 0) { \
+        psError(PS_ERR_IO, true, "Unable to find " NAME " in fringe header.\n"); \
+        return NULL; \
+    }
+
+    // Need to retrieve the scalars: dX, dY, nX, nY
+    READ_FRINGES_SCALAR(dX, "PSFRNGDX");
+    READ_FRINGES_SCALAR(dY, "PSFRNGDY");
+    READ_FRINGES_SCALAR(nX, "PSFRNGNX");
+    READ_FRINGES_SCALAR(nY, "PSFRNGNY");
+
+    // Now the vectors: x, y, mask, f, df
+    long numRows = table->n;            // Number of rows
+    pmFringeRegions *regions = pmFringeRegionsAlloc(numRows, dX, dY, nX, nY); // The fringe regions
+    psVector *x = psVectorAlloc(numRows, PS_TYPE_F32); // x position
+    psVector *y = psVectorAlloc(numRows, PS_TYPE_F32); // y position
+    psVector *mask = psVectorAlloc(numRows, PS_TYPE_U8); // mask
+    regions->x = x;
+    regions->y = y;
+    regions->mask = mask;
+    psArray *f = psArrayAlloc(numRows); // Array of fringe measurements
+    psArray *df = psArrayAlloc(numRows);// Array of errors
+    psArray *fringes = NULL; // Array of fringes, to return
+
+    #define READ_FRINGES_VECTOR_ROW(VECTOR, TYPE, NAME, DESCRIPTION) \
+    { \
+        VECTOR->data.TYPE[i] = psMetadataLookup##TYPE(&mdok, row, NAME); \
+        if (!mdok) { \
+            psError(PS_ERR_IO, true, "Unable to find " #DESCRIPTION " for row %ld.\n", i); \
+            goto READ_FRINGES_DONE; \
+        } \
+    }
+
+    // Some values may be either a vector or a value --- need to check
+    #define READ_FRINGES_ARRAY_ROW(ARRAY, TYPE, NAME, DESCRIPTION) \
+    { \
+        psMetadataItem *item = psMetadataLookup(row, NAME); \
+        if (!item) { \
+            psError(PS_ERR_IO, true, "Unable to find " #DESCRIPTION " for row %ld.\n", i); \
+            goto READ_FRINGES_DONE; \
+        } \
+        if (item->type == PS_DATA_VECTOR) { \
+            ARRAY->data[i] = psMemIncrRefCounter(item->data.V); \
+        } else if (item->type == PS_TYPE_##TYPE) { \
+            psVector *vector = psVectorAlloc(1, PS_TYPE_##TYPE); \
+            vector->data.TYPE[0] = item->data.TYPE; \
+            ARRAY->data[i] = vector; \
+        } else { \
+            psError(PS_ERR_IO, true, "Found " #DESCRIPTION " for row %ld, but it's of an " \
+                    "unsupported type (%x).\n", i, item->type); \
+            goto READ_FRINGES_DONE; \
+        } \
+    }
+
+    // Translate the table into vectors
+    for (long i = 0; i < numRows; i++) {
+        psMetadata *row = table->data[i]; // Table row
+        READ_FRINGES_VECTOR_ROW(x, F32, "x", "x position");
+        READ_FRINGES_VECTOR_ROW(y, F32, "y", "y position");
+        READ_FRINGES_VECTOR_ROW(mask, U8, "mask", "mask");
+        READ_FRINGES_ARRAY_ROW(f, F32, "f", "fringe measurement");
+        READ_FRINGES_ARRAY_ROW(df, F32, "df", "fringe error");
+    }
+
+    // Get f,df into pmFringeStats
+    long numFringes = ((psVector*)(f->data[0]))->n; // Number of fringe components
+    fringes = psArrayAlloc(numFringes);
+    for (int j = 0; j < numFringes; j++) {
+        fringes->data[j] = pmFringeStatsAlloc(regions);
+    }
+
+    for (long i = 0; i < numRows; i++) {
+        psVector *measurements = f->data[i]; // Vector of measurements
+        psVector *errors = df->data[i]; // Vector of errors
+        for (int j = 0; j < numFringes; j++) {
+            pmFringeStats *fringe = fringes->data[j];
+            fringe->f->data.F32[i] = measurements->data.F32[j];
+            fringe->df->data.F32[i] = errors->data.F32[j];
+        }
+    }
+
+READ_FRINGES_DONE:
+    psFree(regions);
+    psFree(f);
+    psFree(df);
+
+    return fringes;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// pmFringeScale
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static void fringeScaleFree(pmFringeScale *scale)
+{
+    psFree(scale->coeff);
+    psFree(scale->coeffErr);
+    return;
+}
+
+pmFringeScale *pmFringeScaleAlloc(int nFringeFrames)
+{
+    pmFringeScale *scale = psAlloc(sizeof(pmFringeScale));
+    (void)psMemSetDeallocator(scale, (psFreeFunc)fringeScaleFree);
+
+    scale->nFringeFrames = nFringeFrames;
+    scale->coeff = psVectorAlloc(nFringeFrames + 1, PS_TYPE_F32);
+    scale->coeffErr = psVectorAlloc(nFringeFrames + 1, PS_TYPE_F32);
+
+    return scale;
+}
+
+// Determine the fringe scales through solving the least-squares problem
+static bool scaleMeasure(pmFringeScale *scale, // Scale to return
+                         pmFringeStats *science, // The fringe measurements for the science image
+                         psArray *fringes // Array of fringe measurements for the templates
+                        )
+{
+    assert(scale);
+    assert(science);
+    assert(fringes);
+    assert(scale->nFringeFrames == fringes->n);
+
+    psVector *mask = science->regions->mask; // The region mask
+
+    int numCoeffs = fringes->n + 1;     // Number of coefficients: scales for the templates plus a background
+    int numPoints = science->regions->nRequested; // Number of points (i.e., fringe measurements)
+
+    psImage *A = psImageAlloc(numCoeffs, numCoeffs, PS_TYPE_F64); // The least-squares matrix
+    psVector *B = psVectorAlloc(numCoeffs, PS_TYPE_F64); // The least-squares vector
+
+    // Generate the least-squares matrix and vector
+    for (int i = 0; i < numCoeffs; i++) {
+        psVector *fringe1 = NULL;       // A fringe measurement
+        if (i != 0) {
+            pmFringeStats *fringe = fringes->data[i - 1];
+            fringe1 = fringe->f;
+        }
+
+        // Fill in the upper part of the matrix
+        for (int j = i; j < numCoeffs; j++) {
+            psVector *fringe2 = NULL;   // Another fringe measurement
+            if (j != 0) {
+                pmFringeStats *fringe = fringes->data[j - 1];
+                fringe2 = fringe->f;
+            }
+
+            double matrix = 0.0;        // The matrix sum
+            for (int k = 0; k < numPoints; k++) {
+                if (!mask->data.U8[k]) {
+                    psF32 f1 = (fringe1) ? fringe1->data.F32[k] : 1.0; // Contribution from i fringe
+                    psF32 f2 = (fringe2) ? fringe2->data.F32[k] : 1.0; // Contribution from j fringe
+                    psF32 dsInv = science->df->data.F32[k]; // 1 / sigma
+                    matrix += f1 * f2 * dsInv * dsInv;
+                }
+            }
+            A->data.F64[i][j] = matrix;
+        }
+
+        // Use symmetry to fill in the lower part of the matrix
+        for (int j = 0; j < i; j++) {
+            A->data.F64[i][j] = A->data.F64[j][i];
+        }
+
+        double vector = 0.0;            // The vector sum
+        for (int k = 0; k < numPoints; k++) {
+            if (!mask->data.U8[k]) {
+                psF32 f1 = (fringe1) ? fringe1->data.F32[k] : 1.0; // Contribution from fringe 1
+                psF32 s = science->f->data.F32[k]; // Contribution from science measurement
+                psF32 dsInv = science->df->data.F32[k]; // 1 / sigma
+                vector += f1 * s * dsInv * dsInv;
+            }
+        }
+        B->data.F64[i] = vector;
+    }
+
+    if (psTraceGetLevel("psModules.detrend") >= 5) {
+        printf("From %d points:\n", numPoints);
+        for (int i = 0; i < numCoeffs; i++) {
+            for (int j = 0; j < numCoeffs; j++) {
+                printf("%.2e ", A->data.F64[i][j]);
+            }
+            printf("\n");
+        }
+    }
+
+    // Solve the least-squares equation
+    if (! psMatrixGJSolve(A, B)) {
+        psError(PS_ERR_UNKNOWN, false, "Could not solve linear equations.  Returning NULL.\n");
+        return false;
+    }
+
+    // Copy the results over
+    for (int i = 0; i < numCoeffs; i++) {
+        scale->coeff->data.F32[i] = B->data.F64[i];
+        scale->coeffErr->data.F32[i] = sqrt(A->data.F64[i][i]);
+    }
+
+    psFree(A);
+    psFree(B);
+
+    return true;
+}
+
+// Measure the fringe differences for each region
+static bool fringeScaleDiffs(psVector *diff, // Vector of differences
+                             pmFringeStats *science, // Science fringe measurements
+                             psArray *fringes, // Template fringe measurements
+                             pmFringeScale *scale // Fringe scales
+                            )
+{
+    assert(diff);
+    assert(diff->type.type == PS_TYPE_F32);
+    assert(science);
+    assert(fringes);
+    assert(scale);
+    assert(diff->n == science->regions->nRequested);
+    assert(fringes->n == scale->nFringeFrames);
+
+    psVector *mask = science->regions->mask; // The region mask
+
+    for (int i = 0; i < diff->n; i++) {
+        if (!mask->data.U8[i]) {
+            float difference = science->f->data.F32[i] - scale->coeff->data.F32[0];
+            for (int j = 0; j < fringes->n; j++) {
+                pmFringeStats *fringe = fringes->data[j]; // The fringe of interest
+                difference -= scale->coeff->data.F32[j + 1] * fringe->f->data.F32[i];
+            }
+            diff->data.F32[i] = difference * difference * science->df->data.F32[i] * science->df->data.F32[i];
+        }
+    }
+
+    return true;
+}
+
+// Clip regions based on the differences; return the number masked
+static int clipRegions(psVector *diffs, // Differences
+                       psVector *mask,  // Region mask
+                       float rej        // Rejection limit in standard deviations
+                      )
+{
+    assert(diffs);
+    assert(diffs->type.type == PS_TYPE_F32);
+    assert(mask);
+    assert(mask->type.type == PS_TYPE_U8);
+    assert(diffs->n == mask->n);
+
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_QUARTILE); // Statistics
+    psVectorStats(stats, diffs, NULL, mask, 1);
+    float middle = stats->sampleMedian; // The middle of the distribution
+    float thresh = rej * 0.74 * (stats->sampleUQ - stats->sampleLQ); // The rejection threshold
+    psFree(stats);
+
+    int numClipped = 0;                 // Number clipped
+    for (int i = 0; i < diffs->n; i++) {
+        psTrace("psModules.detrend", 10, "Region %d (%d): %f\n", i, mask->data.U8[i], diffs->data.F32[i]);
+        if (!mask->data.U8[i] && fabs(diffs->data.F32[i]) > middle + thresh) {
+            psTrace("psModules.detrend", 5, "Masking %d: %f\n", i, diffs->data.F32[i]);
+            mask->data.U8[i] = 1;
+            numClipped++;
+        }
+    }
+
+    return numClipped;
+}
+
+
+// XXX include the fringe error (fringe->df) in the fit?
+pmFringeScale *pmFringeScaleMeasure(pmFringeStats *science, psArray *fringes, float rej,
+                                    unsigned int nIter, float keepFrac)
+{
+    PS_ASSERT_PTR_NON_NULL(science, NULL);
+    PS_ASSERT_PTR_NON_NULL(fringes, NULL);
+    PS_ASSERT_INT_POSITIVE(fringes->n, NULL);
+    PS_ASSERT_INT_POSITIVE(nIter, NULL);
+
+    pmFringeRegions *regions = science->regions; // The fringe regions
+    int numRegions = regions->nRequested; // Number of regions
+
+    // Ensure we are dealing with the SAME fringe points for all the inputs.
+    // Otherwise, we're going to get crazy results.
+    for (long i = 0; i < numRegions; i++) {
+        float xScience = regions->x->data.F32[i]; // The x position for the science image
+        float yScience = regions->y->data.F32[i]; // The y position for the science image
+        for (long j = 0; j < fringes->n; j++) {
+            pmFringeStats *fringe = fringes->data[j]; // The fringe statistics from a fringe image
+            pmFringeRegions *fringeRegions = fringe->regions; // The fringe regions for that fringe image
+            if (fringeRegions->x->data.F32[i] != xScience ||
+                    fringeRegions->y->data.F32[i] != yScience) {
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Science and fringe measurement regions "
+                        "don't match.\n");
+                return NULL;
+            }
+        }
+    }
+
+    // Set up the mask
+    if (!regions->mask) {
+        regions->mask = psVectorAlloc(numRegions, PS_TYPE_U8);
+        psVectorInit(regions->mask, 0);
+    }
+    psVector *mask = regions->mask;     // The region mask
+    psStats *median = psStatsAlloc(PS_STAT_SAMPLE_MEDIAN); // Median statistics
+    unsigned int numClipped = 0;        // Total number clipped
+    psVector *diff = psVectorAlloc(numRegions, PS_TYPE_F32); // The differences between obs. and pred.
+
+    pmFringeScale *scale = pmFringeScaleAlloc(fringes->n); // The fringe scales
+
+    // Get rid of bad data points
+    for (int i = 0; i < fringes->n; i++) {
+        pmFringeStats *fringe = fringes->data[i]; // The fringe of interest
+        for (int j = 0; j < numRegions; j++) {
+            if (!isfinite(fringe->f->data.F32[j])) {
+                mask->data.U8[j] = 1;
+                psTrace("psModules.detrend", 9, "Masking region %d because not finite in fringe %d.\n", j, i);
+            }
+        }
+    }
+
+# if (0)
+    // Write fringe data to file for a test
+    FILE *f = fopen ("fringe.dat", "w");
+    for (int j = 0; j < numRegions; j++) {
+	if (mask->data.U8[j]) continue;
+	fprintf (f, "%d %f %f ", j, science->f->data.F32[j], science->df->data.F32[j]);
+	for (int i = 0; i < fringes->n; i++) {
+	    pmFringeStats *fringe = fringes->data[i]; // The fringe of interest
+            fprintf (f, "%f  ", fringe->f->data.F32[j]);
+        }
+	fprintf (f, "\n");
+    }
+    fclose (f);
+# endif
+
+    // Get rid of the extreme outliers by assuming most of the points are somewhat clustered
+    psVectorStats(median, science->f, NULL, NULL, 0);
+    scale->coeff->data.F32[0] = median->sampleMedian;
+    for (int i = 0; i < fringes->n; i++) {
+        pmFringeStats *fringe = fringes->data[i]; // The fringe of interest
+        psVectorStats(median, fringe->f, NULL, NULL, 0);
+        scale->coeff->data.F32[0] -= median->sampleMedian;
+        scale->coeff->data.F32[i] = 0.0;
+    }
+    psFree(median);
+    fringeScaleDiffs(diff, science, fringes, scale);
+    numClipped = clipRegions(diff, mask, 3.0*rej);
+    psTrace("psModules.detrend", 4, "%d regions clipped in initial pass.\n", numClipped);
+
+    unsigned int iter = 0;              // Iteration number
+    unsigned int iterClip = 0;          // Number clipped in this iteration
+    do {
+        iter++;
+        scaleMeasure(scale, science, fringes); // The scales
+        psTrace("psModules.detrend", 1, "Fringe scales after iteration %d:\n", iter);
+        psTrace("psModules.detrend", 1, "Background: %f %f\n", scale->coeff->data.F32[0],
+                scale->coeffErr->data.F32[0]);
+        for (int i = 0; i < scale->nFringeFrames; i++) {
+            psTrace("psModules.detrend", 1, "%d: %f %f\n", i, scale->coeff->data.F32[i + 1],
+                    scale->coeffErr->data.F32[i + 1]);
+        }
+
+        fringeScaleDiffs(diff, science, fringes, scale);
+        iterClip = clipRegions(diff, mask, rej); // Number clipped
+        numClipped += iterClip;
+        psTrace("psModules.detrend", 9, "Clipped: %d\tFrac: %f\n", iterClip,
+                (float)numClipped/(float)numRegions);
+    } while (iterClip > 0 && iter < nIter && (float)numClipped/(float)numRegions <= 1.0 - keepFrac);
+    psFree(diff);
+
+    // A final iteration with the last clipping
+    scaleMeasure(scale, science, fringes);
+
+    return scale;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Fringe correction
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// XXX note that this modifies the input fringe images
+psImage *pmFringeCorrect(pmReadout *readout, pmFringeRegions *fringes, psArray *fringeImages,
+                         psArray *fringeStats, psMaskType maskVal, float rej,
+                         unsigned int nIter, float keepFrac)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, NULL);
+    PS_ASSERT_PTR_NON_NULL(readout->image, NULL);
+    PS_ASSERT_IMAGE_NON_EMPTY(readout->image, NULL);
+    PS_ASSERT_PTR_NON_NULL(fringes, NULL);
+    PS_ASSERT_PTR_NON_NULL(fringeImages, NULL);
+    PS_ASSERT_PTR_NON_NULL(fringeStats, NULL);
+    PS_ASSERT_INT_EQUAL(fringeImages->n, fringeStats->n, NULL);
+    PS_ASSERT_INT_POSITIVE(nIter, NULL);
+
+    // measure the fringe stats for the science frame and solve for the scales
+    pmFringeStats *scienceStats = pmFringeStatsMeasure(fringes, readout, maskVal);
+
+    if (psTraceGetLevel("psModules.detrend") > 9) {
+        for (int i = 0; i < fringes->nRequested; i++) {
+            printf("%f", scienceStats->f->data.F32[i]);
+            for (int j = 0; j < fringeStats->n; j++) {
+                pmFringeStats *fringe = fringeStats->data[j];
+                printf("\t%f", fringe->f->data.F32[i]);
+            }
+            printf("\n");
+        }
+    }
+
+    pmFringeScale *scale = pmFringeScaleMeasure(scienceStats, fringeStats, rej, nIter, keepFrac);
+    psFree(scienceStats);
+
+    psTrace("psModules.detrend", 7, "Fringe solution:\n");
+    for (int i = 0; i < fringeImages->n + 1; i++) {
+        psTrace("psModules.detrend", 7, "%d: %f %f\n", i, scale->coeff->data.F32[i],
+                scale->coeffErr->data.F32[i]);
+    }
+
+    // build the fringe correction image
+    // XXX we could save data space by making the first image the output image
+    psImage *sumFringe = psImageAlloc(readout->image->numCols, readout->image->numRows, PS_TYPE_F32);
+    //psBinaryOp(sumFringe, sumFringe, "+", psScalarAlloc(scale->coeff->data.F32[0], PS_TYPE_F32));
+    for (int i = 0; i < fringeImages->n; i++) {
+
+        // rescale the fringe image
+        psBinaryOp(fringeImages->data[i], fringeImages->data[i], "*",
+                   psScalarAlloc(scale->coeff->data.F32[i+1], PS_TYPE_F32));
+
+        // sum together
+        sumFringe = (psImage*)psBinaryOp(sumFringe, sumFringe, "+", fringeImages->data[i]);
+    }
+    psFree(scale);
+
+    // subtract the resulting fringe frame
+    readout->image = (psImage*)psBinaryOp(readout->image, readout->image, "-", sumFringe);
+
+    return sumFringe;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmFringeStats.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmFringeStats.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmFringeStats.h	(revision 22158)
@@ -0,0 +1,214 @@
+/* @file pmFringeStats.h
+ * @brief Measure fringe statistics, and apply correction
+ *
+ * @author Eugene Magnier, IfA
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-01-24 02:54:15 $
+ * Copyright 2004-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FRINGE_STATS
+#define PM_FRINGE_STATS
+
+/// @addtogroup detrend Detrend Creation and Application
+/// @{
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// pmFringeRegions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/// Fringe measurement regions.
+///
+/// Fringes are measured within a box of size dX,dY.  A large scale smoothing is performed by subtracting the
+/// background within large divisions of the image.  The coordinates of the fringe points and the mask may be
+/// NULL, which means that they will be generated when required.
+typedef struct
+{
+    int nRequested;                     // Number of fringe points selected
+    int nAccepted;                      // Number of fringe points not masked
+    int dX;                             // Median box half-width
+    int dY;                             // Median box half-height
+    int nX;                             // Number of large-scale smoothing divisions in x (col)
+    int nY;                             // Number of large-scale smoothing divisions in y (row)
+    psVector *x;                        // Fringe point coordinates (col), or NULL
+    psVector *y;                        // Fringe point coordinates (row), or NULL
+    psVector *mask;                     // Fringe point on/off mask, or NULL
+}
+pmFringeRegions;
+
+/// Allocate fringe regions
+pmFringeRegions *pmFringeRegionsAlloc (int nPts, ///< Number of fringe points to create
+                                       int dX, ///< Half-width of fringe boxes
+                                       int dY, ///< Half-height of fringe boxes
+                                       int nX, ///< Smoothing scale in x
+                                       int nY ///< Smoothing scale in y
+                                      );
+
+/// Generate the fringe points
+///
+/// Fringe points are generated randomly over the image.  No effort is made to avoid masked regions (indeed,
+/// the function knows nothing about masks).  If the random number generator is NULL, then a new one will be
+/// used.
+bool pmFringeRegionsCreatePoints(pmFringeRegions *fringe, ///< Fringe regions to generate
+                                 const psImage *image, ///< Image for the regions (defines the size)
+                                 psRandom *random ///< Random number generator, or NULL
+                                );
+
+/// Write the regions to a FITS file
+///
+/// The fringe regions are written to the FITS file, with the given extension name.  The header is
+/// supplemented with scalar values dX, dY, nX and nY (as PSFRNGDX, PSFRNGDY, PSFRNGNX, PSFRNGNY) from the
+/// fringe regions, while the fringe coordinates and mask are written as a FITS table (as x, y, mask).
+bool pmFringeRegionsWriteFits(psFits *fits, ///< Output FITS file
+                              psMetadata *header, ///< Additional headers to write, or NULL
+                              const pmFringeRegions *regions, ///< Regions to write
+                              const char *extname ///< Extension name, or NULL
+                             );
+
+/// Read the regions from a FITS file
+///
+/// The fringe regions are read from the FITS file, at the given extension name.  The scalars are retrieved
+/// from the header, while the table provides the fringe coordinates and mask.
+pmFringeRegions *pmFringeRegionsReadFits(psMetadata *header, ///< Header to read, or NULL
+        const psFits *fits, ///< Input FITS file
+        const char *extname ///< Extension name, or NULL
+                                        );
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// pmFringeStats
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/// Fringe measurements for a particular image
+///
+/// Measurements of the median and stdev are made at each of the fringe regions.
+typedef struct
+{
+    pmFringeRegions *regions;           ///< Fringe regions
+    psVector *f;                        ///< Fringe point median
+    psVector *df;                       ///< Fringe point stdev
+}
+pmFringeStats;
+
+/// Allocate fringe statistics
+pmFringeStats *pmFringeStatsAlloc(pmFringeRegions *regions // The fringe regions which will be measured
+                                 );
+
+/// Measure the fringe statistics for an image
+///
+/// Given an input image and fringe regions at which to measure, measures the median and stdev at each of the
+/// fringe points.  If the fringe points are undefined, they are generated.
+pmFringeStats *pmFringeStatsMeasure(pmFringeRegions *fringe, ///< Fringe regions at which to measure
+                                    const pmReadout *readout, ///< Readout for which to measure
+                                    psMaskType maskVal ///< Mask value for image
+                                   );
+
+/// Write the fringe stats for an image to a FITS table
+///
+/// The fringe measurements are written to the FITS file with the given extension name.  The median and stdev
+/// measurements are written as a FITS table (as f and df).
+bool pmFringeStatsWriteFits(psFits *fits, ///< FITS file to which to write
+                            psMetadata *header, ///< Additional headers to write, or NULL
+                            const pmFringeStats *fringe, ///< Fringe statistics to be written
+                            const char *extname ///< Extension name for table
+                           );
+
+/// Read the fringe stats for an image from a FITS table
+///
+/// The fringe measurements are read from the FITS file, at the given extension name.  The table provides the
+/// median and stdev measurements.  It is assumed that the fringe measurements correspond to the regions
+/// provided.
+pmFringeStats *pmFringeStatsReadFits(psMetadata *header, ///< Header to read, or NULL
+                                     const psFits *fits, ///< FITS file from which to read
+                                     const char *extname, ///< Extension name to read
+                                     pmFringeRegions *regions ///< Corresponding regions
+                                    );
+
+/// Concatenate the fringe stats for several readouts into a single fringe stats.
+///
+/// Each readout of each chip must be measured separately (so as to avoid any gaps between the cells, as in
+/// the case for GPC).  But the fit must be performed with all the readouts belonging to a chip (in order to
+/// get a secure measurement of the fringe amplitudes).  To do so, we need to concatenate the fringe
+/// measurements for each of the chip components.  This function generates a new pmFringeStats from
+/// concatenating those in the array.  The corresponding pmFringeRegions is also generated.
+pmFringeStats *pmFringeStatsConcatenate(const psArray *fringes, ///< Array of pmFringeStats for the readouts
+                                        const psVector *x0, ///< Offset in x for the readout
+                                        const psVector *y0 ///< Offset in y for the readout
+                                       );
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Input/output for multiple pmFringeStats
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/// Write an array of fringes measurements to a FITS table.
+///
+/// Writes an array of fringe measurements for a cell as a FITS table in the analysis metadata.  The array of
+/// fringe statistics must all use the same fringe regions (or there is no point in storing them all
+/// together).  The header is supplemented with scalar values dX, dY, nX and nY (as PSFRNGDX, PSFRNGDY,
+/// PSFRNGNX, PSFRNGNY) from the fringe regions, while the fringe coordinates and mask are written as a FITS
+/// table (as x, y, mask, f, df; f and df are vectors).
+bool pmFringesFormat(pmCell *cell,   ///< Cell for which to write
+                     psMetadata *header, ///< Header, or NULL
+                     const psArray *fringes ///< Array of pmFringeStats, all for the same pmFringeRegion
+                    );
+
+/// Parses an array of fringes measurements from a FITS table.
+///
+/// The fringes for the cell are read from the FITS table in the analysis metadata.  The table provides the
+/// region and the (possibly multiple) fringe statistics for that region.  The current extension is used if
+/// the extension name is not provided.
+psArray *pmFringesParse(pmCell *cell ///< Cell for which to read fringes
+                       );
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// pmFringeScale
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/// The fringe correction solution
+typedef struct
+{
+    int nFringeFrames;                  ///< Number of fringe frames
+    psVector *coeff;                    ///< Fringe coefficients; size = nFringeFrames
+    psVector *coeffErr;                 ///< Error in fringe coefficients; size = nFringeFrames
+}
+pmFringeScale;
+
+/// Measure the scales for the fringe correction
+///
+/// Given a fringe measurement for a science image, and an array of template fringe measurements, this
+/// function measures the contribution of each of the templates to the input.  Rejection is performed on the
+/// fringe regions, to weed out stars etc.
+pmFringeScale *pmFringeScaleMeasure(pmFringeStats *science, ///< Fringe measurements from science image
+                                    psArray *fringes, ///< Array of fringe measurements from templates
+                                    float rej, ///< Rejection threshold (in standard deviations)
+                                    unsigned int nIter, ///< Maximum number of iterations
+                                    float keepFrac ///< Minimum fraction of regions to keep
+                                   );
+
+/// Allocate fringe scales
+pmFringeScale *pmFringeScaleAlloc(int nFringeFrames ///< Number of fringe frames
+                                 );
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Fringe correction
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/// Solve for and apply the fringe correction
+///
+/// This is a wrapper around each of the fringe correction components to measure the fringe points, solve for
+/// the fringe correction, and apply the fringe correction.  The input fringe images are modified (scaled by
+/// the solution coefficients in order to correct the science image).  Returns the summed fringe image.
+psImage *pmFringeCorrect(pmReadout *in, ///< Input science image
+                         pmFringeRegions *fringes, ///< The fringe regions used
+                         psArray *fringeImages, ///< Fringe template images to use in correction
+                         psArray *fringeStats, ///< Fringe stats (for templates) to use in correction
+                         psMaskType maskVal, ///< Value to mask for science image
+                         float rej,     ///< Rejection threshold, for pmFringeScaleMeasure
+                         unsigned int nIter, ///< Maximum number of iterations, for pmFringeScaleMeasure
+                         float keepFrac ///< Minimum fraction of regions to keep, for pmFringeScaleMeasure
+                        );
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmMaskBadPixels.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmMaskBadPixels.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmMaskBadPixels.c	(revision 22158)
@@ -0,0 +1,271 @@
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <strings.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmHDUUtils.h"
+#include "pmFPAMaskWeight.h"
+#include "pmMaskBadPixels.h"
+
+bool pmMaskBadPixels(pmReadout *input, const pmReadout *mask, psMaskType maskVal)
+{
+    PS_ASSERT_PTR_NON_NULL(input, false);
+    PS_ASSERT_PTR_NON_NULL(input->mask, false);
+    PS_ASSERT_IMAGE_TYPE(input->mask, PS_TYPE_MASK, false);
+
+    PS_ASSERT_PTR_NON_NULL(mask, false);
+    PS_ASSERT_PTR_NON_NULL(mask->mask, false);
+    PS_ASSERT_IMAGE_TYPE(mask->mask, PS_TYPE_MASK, false);
+
+    psImage *inMask = input->mask;
+    psImage *exMask = mask->mask;
+
+    // Add mask MD5 to header
+    pmHDU *hdu = pmHDUFromReadout(input);  // HDU of interest
+    psVector *md5 = psImageMD5(mask->mask); // md5 hash
+    psString md5string = psMD5toString(md5); // String
+    psFree(md5);
+    psStringPrepend(&md5string, "MASK image MD5: ");
+    psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK,
+                     md5string, "");
+    psFree(md5string);
+
+    int rowMax = input->row0 + inMask->numRows;
+    int colMax = input->col0 + inMask->numCols;
+
+    if (mask->row0 > input->row0 || mask->col0 > input->col0 ||
+            mask->row0 + exMask->numRows < rowMax || mask->col0 + exMask->numCols < colMax) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                "Input image size exceeds that of mask image: (%d, %d) vs (%d, %d)",
+                inMask->numRows, inMask->numCols, exMask->numRows, exMask->numCols);
+        return false;
+    }
+
+    // Determine total offset based on image offset with chip offset
+    // XXX if we choose to correct for the readout location, apply input->col0,row0 here
+    int offCol = input->col0 - mask->col0;
+    int offRow = input->row0 - mask->row0;
+
+    // masks are both of type PS_TYPE_MASK
+    psMaskType **exVal = exMask->data.U8;
+    psMaskType **inVal = inMask->data.U8;
+
+    // apply exMask values
+    if (maskVal) {
+        // set raised pixels in exMask which are selected by maskVal
+        for (int j = 0; j < inMask->numRows; j++) {
+            int xJ = j - offRow;
+            for (int i = 0; i < inMask->numCols; i++) {
+                int xI = i - offCol;
+                inVal[j][i] |= (maskVal & exVal[xJ][xI]);
+            }
+        }
+    }
+
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now, used for reporting
+    psString timeString = psTimeToISO(time); // String with time
+    psFree(time);
+    psStringPrepend(&timeString, "Static mask (selecting %x) applied at ", maskVal);
+    psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK,
+                     timeString, "");
+    psFree(timeString);
+
+    return true;
+}
+
+
+bool pmMaskFlagSuspectPixels(pmReadout *output, const pmReadout *readout, float median, float stdev,
+                             float rej, psMaskType maskVal)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_FLOAT_LARGER_THAN(rej, 0.0, false);
+    PS_ASSERT_IMAGE_NON_NULL(readout->image, false);
+    PS_ASSERT_IMAGE_NON_EMPTY(readout->image, false);
+    PS_ASSERT_IMAGE_TYPE(readout->image, PS_TYPE_F32, false);
+    if (readout->mask) {
+        PS_ASSERT_IMAGE_NON_EMPTY(readout->mask, false);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(readout->image, readout->mask, false);
+        PS_ASSERT_IMAGE_TYPE(readout->mask, PS_TYPE_MASK, false);
+    }
+    PS_ASSERT_PTR_NON_NULL(output, false);
+
+    bool mdok;                          // Status of MD lookup
+    psImage *suspect = psMetadataLookupPtr(&mdok, output->analysis, PM_MASK_ANALYSIS_SUSPECT); // Suspect img
+    if (suspect) {
+        PS_ASSERT_IMAGE_NON_EMPTY(suspect, false);
+        PS_ASSERT_IMAGE_TYPE(suspect, PS_TYPE_F32, false);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(readout->image, suspect, false);
+        psMemIncrRefCounter(suspect);
+    } else {
+        suspect = psImageAlloc(readout->image->numCols, readout->image->numRows, PS_TYPE_F32);
+        psImageInit(suspect, 0);
+        psMetadataAddImage(output->analysis, PS_LIST_TAIL, PM_MASK_ANALYSIS_SUSPECT, PS_META_REPLACE,
+                           "Suspect pixels", suspect);
+        psMetadataAddS32(output->analysis, PS_LIST_TAIL, PM_MASK_ANALYSIS_NUM, PS_META_REPLACE,
+                         "Number of input images", 0);
+    }
+
+    if (!isfinite(median) || !isfinite(stdev)) {
+        // If we get down here and the statistics are missing, then we should go and mask the entire image
+        psWarning("Missing statistics --- flagging entire image as suspect.");
+        return (psImage*)psBinaryOp(suspect, suspect, "+", psScalarAlloc(1.0, PS_TYPE_F32));
+    }
+
+    psImage *image = readout->image;    // Image of interest
+    psImage *mask = readout->mask;      // Corresponding mask
+
+    psTrace ("psModules.detrend", 3, "suspect: %f +/- %f\n", median, stdev);
+
+    // XXX this loop could result in pixels with suspect = 0.0 but no valid input pixels (all
+    // masked).  need to track the number of good as well as suspect pixels?
+    for (int y = 0; y < image->numRows; y++) {
+        for (int x = 0; x < image->numCols; x++) {
+            if (fabs((image->data.F32[y][x] - median) / stdev) < rej) continue;
+	    if (mask && (mask->data.PS_TYPE_MASK_DATA[y][x] & maskVal)) continue;
+	    suspect->data.F32[y][x] += 1.0;
+        }
+    }
+    psFree(suspect);                    // Drop reference
+
+    psMetadataItem *numItem = psMetadataLookup(output->analysis, PM_MASK_ANALYSIS_NUM); // Item with number
+    assert(numItem);
+    numItem->data.S32++;
+
+    return true;
+}
+
+// the maskVal supplied here is the value SET for this mask (ie, it is not used to avoid pixels)
+bool pmMaskIdentifyBadPixels(pmReadout *output, psMaskType maskVal, float thresh, pmMaskIdentifyMode mode)
+{
+    PS_ASSERT_PTR_NON_NULL(output, false);
+    psImage *suspects = psMetadataLookupPtr(NULL, output->analysis, PM_MASK_ANALYSIS_SUSPECT); // Suspect img
+    if (!suspects) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to find image with suspected bad pixels.");
+        return false;
+    }
+    PS_ASSERT_IMAGE_NON_EMPTY(suspects, false);
+    PS_ASSERT_IMAGE_TYPE(suspects, PS_TYPE_F32, false);
+    if (output->mask) {
+        PS_ASSERT_IMAGE_NON_EMPTY(output->mask, false);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(output->mask, suspects, false);
+        PS_ASSERT_IMAGE_TYPE(output->mask, PS_TYPE_MASK, false);
+    } else {
+        output->mask = psImageAlloc(suspects->numCols, suspects->numRows, PS_TYPE_MASK);
+    }
+    int num = psMetadataLookupS32(NULL, output->analysis, PM_MASK_ANALYSIS_NUM); // Number of inputs
+    PS_ASSERT_INT_POSITIVE(num, false);
+
+    float limit = NAN;                  // Limit for masking
+    switch (mode) {
+      case PM_MASK_ID_VALUE:
+        limit = thresh;
+        break;
+
+      case PM_MASK_ID_FRACTION:
+        limit = thresh * num;
+        break;
+
+      case PM_MASK_ID_SIGMA: {
+        psStats *stats = psStatsAlloc(PS_STAT_CLIPPED_STDEV); // Statistics
+        stats->clipSigma = 5.0;
+        stats->clipIter = 1;
+        if (!psImageStats(stats, suspects, NULL, 0) || !isfinite(stats->clippedStdev)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to perform statistics.\n");
+            psFree(stats);
+            return NULL;
+        }
+        limit = thresh * stats->clippedStdev;
+        psTrace ("psModules.detrend", 3, "bad: %f -> %f\n", stats->clippedStdev, limit);
+        psFree(stats);
+        break;
+      }
+
+      case PM_MASK_ID_POISSON: {
+        psStats *stats = psStatsAlloc(PS_STAT_MAX); // Statistics
+        if (!psImageStats(stats, suspects, NULL, 0)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to perform statistics.\n");
+            psFree(stats);
+            return NULL;
+        }
+        psHistogram *histo = psHistogramAlloc(-0.5, stats->max + 0.5, stats->max + 1);
+        psFree(stats);
+        if (!psImageHistogram(histo, suspects, NULL, 0)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to generate histogram.\n");
+            psFree(histo);
+            return NULL;
+        }
+
+        // Find the mode.  Since this is a Poisson distribution (more or less), this should also be the mean
+        // and variance.
+        int max = 0;                    // Index of the mode
+        for (int i = 0; i < histo->nums->n; i++) {
+            if (histo->nums->data.F32[i] > histo->nums->data.F32[max]) {
+                max = i;
+            }
+        }
+
+        // Since the mode is most likely zero, we add one to get something realistic.  Then "thresh" is
+        // negative, so we subtract instead of add.
+        limit = max + 1.0 - thresh * sqrtf((float)max + 1.0);
+
+        psTrace ("psModules.detrend", 3, "bad: mode: %d, stdev: %f, limit: %f\n",
+                 max, sqrtf((float)max + 1.0), limit);
+        break;
+      }
+      default:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Invalid mask identify mode");
+        return NULL;
+    }
+
+    if (psTraceGetLevel("psModules.detrend") > 9) {
+        psStats *stats = psStatsAlloc(PS_STAT_MIN | PS_STAT_MAX); // Statistics
+        psImageStats(stats, suspects, NULL, 0);
+        psHistogram *histo = psHistogramAlloc(-0.5, stats->max + 0.5, stats->max + 1);
+        psImageHistogram(histo, suspects, NULL, 0);
+        for (int i = 0; i < histo->nums->n; i++) {
+            printf("%f --> %f : %f\n", histo->bounds->data.F32[i], histo->bounds->data.F32[i + 1],
+                   histo->nums->data.F32[i]);
+        }
+        psFree(stats);
+        psFree(histo);
+        printf("Threshold: %f\n", limit);
+    }
+
+    psTrace ("psModules.detrend", 3, "bad pixel threshold: %f", limit);
+
+    psImage *badpix = output->mask;     // Bad pixel mask
+    psImageInit(badpix, 0);
+
+    for (int y = 0; y < suspects->numRows; y++) {
+        for (int x = 0; x < suspects->numCols; x++) {
+            if (suspects->data.F32[y][x] >= limit) {
+                badpix->data.PS_TYPE_MASK_DATA[y][x] = maskVal;
+            }
+        }
+    }
+
+    return true;
+}
+
+pmMaskIdentifyMode pmMaskIdentifyModeFromString (const char *string) {
+
+    if (!strcasecmp(string, "VALUE")) {
+      return PM_MASK_ID_VALUE;
+    }
+    if (!strcasecmp(string, "FRACTION")) {
+      return PM_MASK_ID_FRACTION;
+    }
+    if (!strcasecmp(string, "SIGMA")) {
+      return PM_MASK_ID_SIGMA;
+    }
+    if (!strcasecmp(string, "POISSON")) {
+      return PM_MASK_ID_POISSON;
+    }
+    return PM_MASK_ID_NONE;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmMaskBadPixels.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmMaskBadPixels.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmMaskBadPixels.h	(revision 22158)
@@ -0,0 +1,71 @@
+/* @file pmMaskBadPixels.h
+ * @brief Mask bad pixels
+ *
+ * @author Ross Harman, MHPCC
+ * @author Eugene Magnier, IfA
+ *
+ * @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-03-29 03:10:17 $
+ * Copyright 2004 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_MASK_BAD_PIXELS_H
+#define PM_MASK_BAD_PIXELS_H
+
+/// @addtogroup detrend Detrend Creation and Application
+/// @{
+
+#define PM_MASK_ANALYSIS_SUSPECT "MASK.SUSPECT" // Readout analysis metadata keyword for suspect image
+#define PM_MASK_ANALYSIS_NUM "MASK.NUM" // Readout analysis metadata keyword for number of inputs
+
+
+typedef enum {
+  PM_MASK_ID_NONE,
+  PM_MASK_ID_VALUE,
+  PM_MASK_ID_FRACTION,
+  PM_MASK_ID_SIGMA,
+  PM_MASK_ID_POISSON,
+} pmMaskIdentifyMode;
+
+pmMaskIdentifyMode pmMaskIdentifyModeFromString (const char *string);
+
+/// Applies the bad pixel mask to the input
+///
+/// Pixels marked as bad within the mask are marked as bad within the input image's mask.  If maskVal is
+/// non-zero, all pixels in the mask have any of the same bits sets as maskVal shall have the corresponding
+/// bits raised.  If maskVal is zero, any zero pixels in the mask are OR-ed with PM_MASK_BAD.  Position
+/// offsets (such as due to trimming) between the input and mask are applied so that the same pixels are
+/// referred to.  The science readout must already have a supplied mask element (use eg. pmReadoutSetMask).
+/// The supplied mask image must be of MASK type
+bool pmMaskBadPixels(pmReadout *input,  ///< Input science image
+                     const pmReadout *mask, ///< Mask image to apply
+                     psMaskType maskVal ///< Mask value to apply
+                    );
+
+/// Find pixels outlying from the background, flagging suspect pixels
+///
+/// Pixels more than "rej" standard deviations from the background level (in flat-fielded,
+/// background-subtracted images) have the corresponding pixel in the "suspect pixels" image
+/// incremented.  After accumulating over a suitable sample of images, bad pixels should have a
+/// high value in the suspect pixels image, allowing them to be identified.  The suspect pixels
+/// image is of type S32.  The relevant median and standard deviation must be supplied in the
+/// readout->analysis metadata as READOUT.MEDIAN, READOUT.STDEVe
+bool pmMaskFlagSuspectPixels(pmReadout *output, ///< Output readout, optionally with suspect pixels image
+                             const pmReadout *readout, ///< Readout to inspect
+                             float median, ///< Image median
+                             float stdev, ///< Image standard deviation
+                             float rej, ///< Rejection threshold (standard deviations)
+                             psMaskType maskVal ///< Mask value for statistics
+    );
+
+/// Identify bad pixels from the suspect pixels image
+///
+/// Bad pixels are identified from the suspect pixels image (accumulated over a large number of images),
+/// according to the chosen mode.
+bool pmMaskIdentifyBadPixels(pmReadout *output, ///< Output readout, with suspect pixels imageOut
+                             psMaskType maskVal, ///< Value to set for bad pixels
+                             float thresh, ///< Threshold for bad pixel
+                             pmMaskIdentifyMode mode ///< Mode for identifying bad pixels
+    );
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmNonLinear.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmNonLinear.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmNonLinear.c	(revision 22158)
@@ -0,0 +1,93 @@
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmNonLinear.h"
+
+pmReadout *pmNonLinearityPolynomial(pmReadout *inputReadout, const psPolynomial1D *input1DPoly)
+{
+    PS_ASSERT_PTR_NON_NULL(inputReadout, NULL);
+    PS_ASSERT_PTR_NON_NULL(inputReadout->image, NULL);
+    PS_ASSERT_IMAGE_TYPE(inputReadout->image, PS_TYPE_F32, NULL);
+    PS_ASSERT_PTR_NON_NULL(input1DPoly, NULL);
+
+    psImage *image = inputReadout->image; // Image to correct
+    for (int i = 0; i < image->numRows; i++) {
+        for (int j = 0; j < image->numCols; j++) {
+            image->data.F32[i][j] = psPolynomial1DEval(input1DPoly, image->data.F32[i][j]);
+        }
+    }
+    return inputReadout;
+}
+
+// set the bin closest to the corresponding value.  
+#define PS_BIN_FOR_VALUE(RESULT, VECTOR, VALUE) { \
+       	psVectorBinaryDisectResult result; \
+       	psScalar tmpScalar; \
+       	tmpScalar.type.type = PS_TYPE_F32; \
+	tmpScalar.data.F32 = (VALUE); \
+	RESULT = psVectorBinaryDisect (&result, VECTOR, &tmpScalar); \
+	switch (result) { \
+	  case PS_BINARY_DISECT_PASS: \
+            break; \
+	  case PS_BINARY_DISECT_OUTSIDE_RANGE: \
+            numPixels ++; \
+	    break; \
+	  case PS_BINARY_DISECT_INVALID_INPUT: \
+	  case PS_BINARY_DISECT_INVALID_TYPE: \
+	    psAbort ("programming error"); \
+	    break; \
+        } }
+
+pmReadout *pmNonLinearityLookup(pmReadout *inputReadout, const psVector *inFlux, const psVector *outFlux)
+{
+    PS_ASSERT_PTR_NON_NULL(inputReadout, NULL);
+    PS_ASSERT_PTR_NON_NULL(inputReadout->image, NULL);
+    PS_ASSERT_IMAGE_TYPE(inputReadout->image, PS_TYPE_F32, NULL);
+    PS_ASSERT_PTR_NON_NULL(inFlux, NULL);
+    if (inFlux->n < 2) {
+        psError(PS_ERR_UNKNOWN, true,
+                "pmNonLinearityLookup(): input vector less than 2 elements.  Returning inputReadout image.");
+        return(inputReadout);
+    }
+    PS_ASSERT_PTR_NON_NULL(outFlux,NULL);
+    psS32 tableSize = inFlux->n;
+    if (inFlux->n != outFlux->n) {
+        tableSize = PS_MIN(inFlux->n, outFlux->n);
+        psLogMsg(__func__, PS_LOG_WARN,
+                 "WARNING: pmNonLinear.c: pmNonLinearityLookup(): "
+                 "input vectors have different sizes (%ld, %ld)\n",
+                 inFlux->n, outFlux->n);
+    }
+    PS_ASSERT_VECTOR_TYPE(inFlux, PS_TYPE_F32, NULL);
+    PS_ASSERT_VECTOR_TYPE(outFlux, PS_TYPE_F32, NULL);
+
+    psImage *image = inputReadout->image; // Input image
+    int numPixels = 0;                  // Number of pixels outside the range
+    int binNum;
+
+    for (int i = 0; i < image->numRows; i++) {
+        for (int j = 0; j < image->numCols; j++) {
+	    float value = image->data.F32[i][j];
+            PS_BIN_FOR_VALUE(binNum, inFlux, value);
+
+	    // Perform linear interpolation.
+	    // XXX this will result in non-sensical results if inFlux contains equal-value
+	    // bins.  either enforce d(inFlux)/d(binNum) > 0 or see psStats.c PS_BIN_INTERPOLATE
+	    float slope = 
+		(outFlux->data.F32[binNum + 1] - outFlux->data.F32[binNum]) /
+		(inFlux->data.F32[binNum + 1] - inFlux->data.F32[binNum]);
+	    image->data.F32[i][j] = slope*(value - inFlux->data.F32[binNum]) + outFlux->data.F32[binNum];
+        }
+    }
+    if (numPixels > 0) {
+        psLogMsg(__func__, PS_LOG_WARN,
+                 "WARNING: pmNonLinear.c: pmNonLinearityLookup(): %d pixels outside table.", numPixels);
+    }
+    return inputReadout;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmNonLinear.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmNonLinear.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmNonLinear.h	(revision 22158)
@@ -0,0 +1,35 @@
+/* @file pmNonLinear.h
+ * @brief Perform non-linear correction through polynomial or table lookup
+ *
+ * @author George Gusciora, MHPCC
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-03-30 21:12:56 $
+ * Copyright 2004 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_NON_LINEAR_H
+#define PM_NON_LINEAR_H
+
+/// @addtogroup detrend Detrend Creation and Application
+/// @{
+
+/// Correct non-linearity through polynomial
+///
+/// Applies a polynomial to the flux of each pixel in the input image to determine the corrected flux.
+pmReadout *pmNonLinearityPolynomial(pmReadout *in, ///< Input image, to correct
+                                    const psPolynomial1D *coeff ///< Polynomial for non-linearity correction
+                                   );
+
+/// Correct non-linearity through table lookup
+///
+/// For each pixel in the input image, performs linear interpolation on the table (from the two vectors) to
+/// determine the corrected flux.
+pmReadout *pmNonLinearityLookup(pmReadout *in, ///< Input image, to correct
+                                const psVector *inFlux, ///< Table column with input fluxes
+                                const psVector *outFlux ///< Table column with output fluxes
+                               );
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmOverscan.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmOverscan.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmOverscan.c	(revision 22158)
@@ -0,0 +1,401 @@
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmHDUUtils.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPACalibration.h"
+
+#include "pmOverscan.h"
+
+#define SMOOTH_NSIGMA 4.0               // Number of Gaussian sigma the smoothing kernel extends
+
+static void pmOverscanOptionsFree(pmOverscanOptions *options)
+{
+    psFree(options->stat);
+    psFree(options->poly);
+    psFree(options->spline);
+}
+
+pmOverscanOptions *pmOverscanOptionsAlloc(bool single, pmFit fitType, unsigned int order, psStats *stat,
+                                          int boxcar, float gauss)
+{
+    pmOverscanOptions *opts = psAlloc(sizeof(pmOverscanOptions));
+    psMemSetDeallocator(opts, (psFreeFunc)pmOverscanOptionsFree);
+
+    // Inputs
+    opts->single = single;
+    opts->constant = false;
+    opts->fitType = fitType;
+    opts->order = order;
+    opts->stat = psMemIncrRefCounter(stat);
+
+    // Smoothing
+    opts->boxcar = boxcar;
+    opts->gauss = gauss;
+
+    // Outputs
+    opts->poly = NULL;
+    opts->spline = NULL;
+
+    return opts;
+}
+
+// Produce an overscan vector from an array of pixels
+psVector *pmOverscanVector(float *chi2, // chi^2 from fit
+			   pmOverscanOptions *overscanOpts, // Overscan options
+			   const psArray *pixels, // Array of vectors containing the pixel values
+			   psStats *myStats // Statistic to use in reducing the overscan
+    )
+{
+    assert(overscanOpts);
+    assert(pixels);
+    assert(myStats);
+
+    psStatsOptions statistic = psStatsSingleOption(myStats->options); // Statistic to use
+    assert(statistic != 0);
+
+    // Reduce the overscans
+    psVector *reduced = psVectorAlloc(pixels->n, PS_TYPE_F32); // Overscan for each row
+    psVector *ordinate = psVectorAlloc(pixels->n, PS_TYPE_F32); // Ordinate
+    psVector *mask = psVectorAlloc(pixels->n, PS_TYPE_U8); // Mask for fitting
+
+    for (int i = 0; i < pixels->n; i++) {
+        psVector *values = pixels->data[i]; // Vector with overscan values
+        if (values->n > 0) {
+            mask->data.U8[i] = 0;
+            ordinate->data.F32[i] = 2.0*(float)i/(float)pixels->n - 1.0; // Scale to [-1,1]
+            psVectorStats(myStats, values, NULL, NULL, 0);
+            reduced->data.F32[i] = psStatsGetValue(myStats, statistic);
+        } else if (overscanOpts->fitType == PM_FIT_NONE) {
+            psError(PS_ERR_UNKNOWN, true, "The overscan is not supplied for all points on the "
+                    "image, and no fit is requested.\n");
+            return NULL;
+        } else {
+            // We'll fit this one out
+            mask->data.U8[i] = 1;
+        }
+    }
+
+    // Smooth the reduced vector
+    if (overscanOpts->boxcar > 0) {
+        psVector *smoothed = psVectorBoxcar(NULL, reduced, overscanOpts->boxcar); // Smoothed vector
+        psFree(reduced);
+        reduced = smoothed;
+    }
+    if (isfinite(overscanOpts->gauss) && overscanOpts->gauss > 0) {
+        if (overscanOpts->boxcar > 0) {
+            psWarning("Gaussian smoothing the boxcar smoothed overscan --- you asked for it.");
+        }
+        psVector *smoothed = psVectorSmooth(NULL, reduced, overscanOpts->gauss, SMOOTH_NSIGMA);
+        psFree(reduced);
+        reduced = smoothed;
+    }
+
+    // Fit the overscan, if required
+    psVector *fitted;                   // Fitted overscan values
+    switch (overscanOpts->fitType) {
+      case PM_FIT_NONE:
+        // No fitting --- that's easy.
+        fitted = psMemIncrRefCounter(reduced);
+        break;
+      case PM_FIT_POLY_ORD:
+        if (overscanOpts->poly && (overscanOpts->poly->nX != overscanOpts->order ||
+                                   overscanOpts->poly->type != PS_POLYNOMIAL_ORD)) {
+            psFree(overscanOpts->poly);
+            overscanOpts->poly = NULL;
+        }
+        if (! overscanOpts->poly) {
+            overscanOpts->poly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, overscanOpts->order);
+        }
+        psVectorFitPolynomial1D(overscanOpts->poly, mask, 1, reduced, NULL, ordinate);
+        fitted = psPolynomial1DEvalVector(overscanOpts->poly, ordinate);
+        break;
+      case PM_FIT_POLY_CHEBY:
+        if (overscanOpts->poly && (overscanOpts->poly->nX != overscanOpts->order ||
+                                   overscanOpts->poly->type != PS_POLYNOMIAL_CHEB)) {
+            psFree(overscanOpts->poly);
+            overscanOpts->poly = NULL;
+        }
+        if (! overscanOpts->poly) {
+            overscanOpts->poly = psPolynomial1DAlloc(PS_POLYNOMIAL_CHEB, overscanOpts->order);
+        }
+        psVectorFitPolynomial1D(overscanOpts->poly, mask, 1, reduced, NULL, ordinate);
+        fitted = psPolynomial1DEvalVector(overscanOpts->poly, ordinate);
+        break;
+      case PM_FIT_SPLINE:
+        // XXX I don't think psSpline1D is up to scratch yet --- it has no mask, and requires an
+        // input spline
+        overscanOpts->spline = psVectorFitSpline1D(reduced, ordinate);
+        fitted = psSpline1DEvalVector(overscanOpts->spline, ordinate);
+        break;
+      default:
+        psError(PS_ERR_UNKNOWN, true, "Unknown value for the fitting type: %d\n", overscanOpts->fitType);
+        return NULL;
+        break;
+    }
+
+    if (chi2) {
+        *chi2 = 0.0;                    // chi^2 (sort of)
+        for (int i = 0; i < reduced->n; i++) {
+            *chi2 += PS_SQR(fitted->data.F32[i] - reduced->data.F32[i]);
+        }
+    }
+
+    psFree(reduced);
+    psFree(ordinate);
+    psFree(mask);
+
+    return fitted;
+}
+
+bool pmOverscanUpdateHeader (pmHDU *hdu, pmOverscanOptions *overscanOpts, float chi2) {
+
+    psString comment = NULL;    // Comment to add
+
+    switch (overscanOpts->fitType) {
+      case PM_FIT_POLY_ORD:
+      case PM_FIT_POLY_CHEBY: {
+	  psStringAppend(&comment, "Overscan fit (chi2: %.2f): ", chi2);
+	  psPolynomial1D *poly = overscanOpts->poly; // The polynomial
+	  for (int i = 0; i < poly->nX; i++) {
+	      psStringAppend(&comment, "%.1f ", poly->coeff[i]);
+	  }
+	  psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, comment, "");
+	  psFree(comment);
+	  comment = NULL;
+
+	  // write metadata header value
+	  psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_VAL", PS_META_REPLACE,
+			   "Overscan value", poly->coeff[0]);
+	  psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_SIG", PS_META_REPLACE,
+			   "Overscan stdev", poly->coeffErr[0]);
+	  break;
+      }
+      case PM_FIT_SPLINE: {
+	  psSpline1D *spline = overscanOpts->spline; // The spline
+	  for (int i = 0; i < spline->n; i++) {
+	      psStringAppend(&comment, "Overscan fit (chi2: %.2f) %d:", chi2, i);
+	      psPolynomial1D *poly = spline->spline[i]; // i-th polynomial
+	      for (int j = 0; j < poly->nX; j++) {
+		  psStringAppend(&comment, "%.1f ", poly->coeff[i]);
+	      }
+	      psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK,
+			       comment, "");
+	      psFree(comment);
+	      comment = NULL;
+	  }
+	  // write metadata header value
+	  psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_VAL", PS_META_REPLACE,
+			   "Overscan value", NAN);
+	  psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_SIG", PS_META_REPLACE,
+			   "Overscan stdev", NAN);
+	  break;
+      }
+      case PM_FIT_NONE:
+	break;
+      default:
+	psAbort("Should never get here!!!\n");
+    }
+    return true;
+}
+
+bool pmOverscanSubtract (pmReadout *input, pmOverscanOptions *overscanOpts) {
+
+    assert (input);
+
+    if (overscanOpts == NULL) return true; // no overscan subtraction requested
+
+    pmHDU *hdu = pmHDUFromReadout(input);  // HDU of interest
+    psImage *image = input->image;
+
+    // check for 'soft bias' (simple, fixed offset to be subtracted)
+    if (overscanOpts->constant) {
+	// write metadata header value
+	psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_VAL", PS_META_REPLACE, "Overscan value",
+			 overscanOpts->value);
+	psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_SIG", PS_META_REPLACE, "Overscan stdev", NAN);
+
+	(void)psBinaryOp(input->image, input->image, "-", psScalarAlloc((float)overscanOpts->value, PS_TYPE_F32));
+
+	return true;
+    }
+
+    // we are performing a statitical analysis of the overscan region
+
+    // Check for an unallowable pmFit.
+    if (overscanOpts->fitType != PM_FIT_NONE && overscanOpts->fitType != PM_FIT_POLY_ORD &&
+	overscanOpts->fitType != PM_FIT_POLY_CHEBY && overscanOpts->fitType != PM_FIT_SPLINE) {
+	psError(PS_ERR_UNKNOWN, true, "Invalid fit type (%d).  Returning original image.\n",
+		overscanOpts->fitType);
+	return false;
+    }
+
+    psList *overscans = input->bias; // List of the overscan images
+
+    psStatsOptions statistic = psStatsSingleOption(overscanOpts->stat->options); // Statistic to use
+    if (statistic == 0) {
+	psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Multiple or no statistics options set: %p\n",
+		overscanOpts->stat);
+	return false;
+    }
+    psStats *stats = psStatsAlloc(statistic); // A new psStats, to avoid clobbering original
+
+    psString comment = NULL;    // Comment to add
+    psStringAppend(&comment, "Subtracting overscan (stat %x; type %x; order %d)",
+		   statistic, overscanOpts->fitType, overscanOpts->order);
+    psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK,
+		     comment, "");
+    psFree(comment);
+
+    // Reduce all overscan pixels to a single value
+    if (overscanOpts->single) {
+	psVector *pixels = psVectorAlloc(0, PS_TYPE_F32);
+	psListIterator *iter = psListIteratorAlloc(overscans, PS_LIST_HEAD, false); // Iterator
+	psImage *overscan = NULL;   // Overscan image from iterator
+	while ((overscan = psListGetAndIncrement(iter))) {
+	    int index = pixels->n;  // Index
+	    pixels = psVectorRealloc(pixels, pixels->n + overscan->numRows * overscan->numCols);
+	    pixels->n += overscan->numRows * overscan->numCols;
+	    for (int i = 0; i < overscan->numRows; i++) {
+		memcpy(&pixels->data.F32[index], overscan->data.F32[i],
+		       overscan->numCols * sizeof(psF32));
+		index += overscan->numCols;
+	    }
+	}
+	psFree(iter);
+
+	(void)psVectorStats(stats, pixels, NULL, NULL, 0);
+	psFree(pixels);
+	double reduced = psStatsGetValue(stats, statistic); // Result of statistics
+
+	psString comment = NULL;    // Comment to add
+	psStringAppend(&comment, "Overscan value: %f", reduced);
+	psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, comment, "");
+	psFree(comment);
+
+	// write metadata header value
+	psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_VAL", PS_META_REPLACE, "Overscan value",
+			 reduced);
+	psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_SIG", PS_META_REPLACE, "Overscan stdev", NAN);
+
+	(void)psBinaryOp(image, image, "-", psScalarAlloc((float)reduced, PS_TYPE_F32));
+	psFree(stats);
+	return true;
+    } 
+
+    // We are performing a row-by-row overscan subtraction
+    bool readRows = psMetadataLookupBool(NULL, input->parent->concepts, "CELL.READDIR"); // Read direction
+    float chi2 = NAN;           // chi^2 from fit
+
+    // adjust operation depending on the read direction : need to re-org pixels for columns
+    if (readRows) {
+	// The read direction is rows
+	psArray *pixels = psArrayAlloc(image->numRows); // Array of vectors containing pixels
+	for (int i = 0; i < pixels->n; i++) {
+	    pixels->data[i] = psVectorAlloc(0, PS_TYPE_F32);
+	}
+
+	// Pull the pixels out into the vectors
+	psListIterator *iter = psListIteratorAlloc(overscans, PS_LIST_HEAD, false); // Iterator
+	psImage *overscan = NULL; // Overscan image from iterator
+	while ((overscan = psListGetAndIncrement(iter))) {
+	    // the overscan and image might not be aligned.  pixels->data represents
+	    // the image row pixels.
+	    int diff = overscan->row0 - image->row0; // Offset between the two regions
+	    for (int i = PS_MAX(0,diff); i < PS_MIN(image->numRows, overscan->numRows + diff); i++) {
+		int j = i - diff;
+		// i is row on image
+		// j is row on overscan
+		psVector *values = pixels->data[i];
+		int index = values->n; // Index in the vector
+		values = psVectorRealloc(values, values->n + overscan->numCols);
+		values->n += overscan->numCols;
+		memcpy(&values->data.F32[index], overscan->data.F32[j],
+		       overscan->numCols * PSELEMTYPE_SIZEOF(PS_TYPE_F32));
+		index += overscan->numCols;
+		pixels->data[i] = values; // Update the pointer in case it's moved
+	    }
+	}
+	psFree(iter);
+
+	// Reduce the overscans
+	psVector *reduced = pmOverscanVector(&chi2, overscanOpts, pixels, stats);
+	psFree(pixels);
+	if (! reduced) {
+	    psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to generate overscan vector.\n");
+	    psFree(stats);
+	    return false;
+	}
+
+	// Subtract row by row
+	for (int i = 0; i < image->numRows; i++) {
+	    for (int j = 0; j < image->numCols; j++) {
+		image->data.F32[i][j] -= reduced->data.F32[i];
+	    }
+	}
+	psFree(reduced);
+    } else {
+	// The read direction is columns
+	psArray *pixels = psArrayAlloc(image->numCols); // Array of vectors containing pixels
+	for (int i = 0; i < pixels->n; i++) {
+	    psVector *values = psVectorAlloc(0, PS_TYPE_F32);
+	    pixels->data[i] = values;
+	}
+
+	// Pull the pixels out into the vectors
+	psListIterator *iter = psListIteratorAlloc(overscans, PS_LIST_HEAD, false); // Iterator
+	psImage *overscan = NULL; // Overscan image from iterator
+	while ((overscan = psListGetAndIncrement(iter))) {
+	    // the overscan and image might not be aligned.  pixels->data represents
+	    // the image row pixels.
+	    int diff = overscan->col0 - image->col0; // Offset between the two regions
+	    for (int i = PS_MAX(0,diff); i < PS_MIN(image->numCols, overscan->numCols + diff); i++) {
+		int iFixed = i - diff;
+		// i is column on image
+		// iFixed is column on overscan
+		psVector *values = pixels->data[i];
+		int index = values->n; // Index in the vector
+		values = psVectorRealloc(values, values->n + overscan->numRows);
+		for (int j = 0; j < overscan->numRows; j++) {
+		    values->data.F32[index++] = overscan->data.F32[j][iFixed];
+		}
+		values->n += overscan->numRows;
+		pixels->data[i] = values; // Update the pointer in case it's moved
+	    }
+	}
+	psFree(iter);
+
+	// Reduce the overscans
+	psVector *reduced = pmOverscanVector(&chi2, overscanOpts, pixels, stats);
+	psFree(pixels);
+	if (! reduced) {
+	    psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to generate overscan vector.\n");
+	    psFree(stats);
+	    return false;
+	}
+
+	// Subtract column by column
+	for (int i = 0; i < image->numCols; i++) {
+	    for (int j = 0; j < image->numRows; j++) {
+		image->data.F32[j][i] -= reduced->data.F32[i];
+	    }
+	}
+	psFree(reduced);
+    }
+
+    pmOverscanUpdateHeader (hdu, overscanOpts, chi2);
+    psFree(stats);
+
+    return true;
+
+} // End of overscan subtraction
+    
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmOverscan.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmOverscan.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmOverscan.h	(revision 22158)
@@ -0,0 +1,72 @@
+/* @file pmOverscan.h
+ * @brief Functions to subtract the overscan, used by pmBiasSubtract
+ *
+ * @author George Gusciora, MHPCC
+ * @author Paul Price, IfA
+ * @author Eugene Magnier, IfA
+ *
+ * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-08-15 20:21:18 $
+ * Copyright 2004--2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_OVERSCAN_H
+#define PM_OVERSCAN_H
+
+/// @addtogroup detrend Detrend Creation and Application
+/// @{
+
+/// Type of fit to perform
+typedef enum {
+    PM_FIT_NONE,                        ///< No fit
+    PM_FIT_POLY_ORD,                    ///< Fit ordinary polynomial
+    PM_FIT_POLY_CHEBY,                  ///< Fit Chebyshev polynomial
+    PM_FIT_SPLINE                       ///< Fit cubic splines
+} pmFit;
+
+/// Options for overscan subtraction
+///
+/// The overscan subtraction may be performed by reducing all overscan regions to a single value (e.g., if
+/// there is no structure); or the overscan may be fit perpendicular to the read direction (usually the
+/// columns) with a particular functional form; or a single value may be subtracted for each read/scan without
+/// fitting (if the structure defies characterisation).  In any case, statistics are required to reduce
+/// multiple values to a single value (either for the scan, or for the entire overscan regions).
+typedef struct
+{
+    // Inputs
+    bool single;                        ///< Reduce all overscan regions to a single value?
+    bool constant;			///< use a supplied constant value (do not measure region)
+    float value;			///< supplied value if needed (per above)
+    pmFit fitType;                      ///< Type of fit to overscan
+    unsigned int order;                 ///< Order of polynomial, or number of spline pieces
+    psStats *stat;                      ///< Statistic to use when reducing the minor direction
+    int boxcar;                         ///< Boxcar smoothing radius
+    float gauss;                        ///< Gaussian smoothing sigma
+    // Outputs
+    psPolynomial1D *poly;               ///< Result of polynomial fit
+    psSpline1D *spline;                 ///< Result of spline fit
+}
+pmOverscanOptions;
+
+/// Allocator for overscan options
+pmOverscanOptions *pmOverscanOptionsAlloc(bool single, ///< Reduce all overscan regions to a single value?
+                                          pmFit fitType, ///< Type of fit to overscan
+                                          unsigned int order, ///< Order of polynomial, or number of splines
+                                          psStats *stat, ///< Statistic to use
+                                          int boxcar, ///< Boxcar smoothing radius
+                                          float gauss ///< Gaussian smoothing sigma
+                                         );
+
+psVector *pmOverscanVector(float *chi2, // chi^2 from fit
+			   pmOverscanOptions *overscanOpts, // Overscan options
+			   const psArray *pixels, // Array of vectors containing the pixel values
+			   psStats *myStats // Statistic to use in reducing the overscan
+    );
+
+bool pmOverscanUpdateHeader (pmHDU *hdu, pmOverscanOptions *overscanOpts, float chi2);
+
+bool pmOverscanSubtract (pmReadout *input, pmOverscanOptions *overscanOpts);
+
+/// @}
+#endif
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmShifts.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmShifts.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmShifts.c	(revision 22158)
@@ -0,0 +1,477 @@
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAUtils.h"
+#include "pmShifts.h"
+
+#define SHIFTS_BUFFER 100               // Buffer size for shifts
+#define TRACE "psModules.detrend"       // Trace facility
+#define FFT_SIZE 25                     // Size at which we use FFT instead of direct convolution
+
+// XXX To do:
+// * Make the table column names configurable, by having a SHIFTS metadata in the camera format, with entries
+//   specifying the column names.
+
+
+static void shiftsFree(pmShifts *shifts)
+{
+    psFree(shifts->x);
+    psFree(shifts->y);
+    psFree(shifts->t);
+    return;
+}
+
+pmShifts *pmShiftsAlloc(bool tRel, bool xyRel)
+{
+    pmShifts *shifts = psAlloc(sizeof(pmShifts));
+    psMemSetDeallocator(shifts, (psFreeFunc)shiftsFree);
+
+    shifts->x = psVectorAllocEmpty(SHIFTS_BUFFER, PS_TYPE_S32);
+    shifts->y = psVectorAllocEmpty(SHIFTS_BUFFER, PS_TYPE_S32);
+    shifts->t = psVectorAllocEmpty(SHIFTS_BUFFER, PS_TYPE_F32);
+    shifts->num = 0;
+
+    // Suitable defaults
+    shifts->tRelative = tRel;
+    shifts->xyRelative = xyRel;
+
+    return shifts;
+}
+
+// Look up the cell within a hash; supplement the hash with a new value if it doesn't exist
+static pmShifts *cellVectors(psHash *shifts, // Hash of shifts
+                             const char *cellName, // Key for hash
+                             bool tRel, bool xyRel // Are the shifts relative?
+    )
+{
+    assert(shifts);
+    assert(cellName);
+
+    // Find the appropriate cell
+    pmShifts *vectors = psHashLookup(shifts, cellName);
+    if (!vectors) {
+        vectors = pmShiftsAlloc(tRel, xyRel);
+        psHashAdd(shifts, cellName, vectors);
+        psFree(vectors);            // Drop reference
+    }
+    return vectors;
+}
+
+
+bool pmShiftsRead(const pmCell *cell, psFits *fits)
+{
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+
+    bool mdok;                          // Status of MD lookup
+    pmShifts *check = psMetadataLookupPtr(&mdok, cell->analysis, PM_SHIFTS_TABLE_NAME); // Table, or NULL
+    if (check) {
+        psTrace(TRACE, 2, "Cell already has OT kernel present.\n");
+        return true;                    // No error
+    }
+    psTrace(TRACE, 2, "Reading FITS file for OT kernels.\n");
+
+    // Determine camera layout
+    pmChip *chip = cell->parent;        // The parent chip
+    pmFPA *fpa = chip->parent;          // The parent FPA
+    pmHDU *phu = NULL;                  // The primary header
+    pmFPALevel phuLevel = PM_FPA_LEVEL_NONE; // Level of the PHU
+    long numChips = 0;                  // Number of chips below the PHU; for setting efficient hash size
+    long numCells = 0;                  // Number of cells below the PHU; for setting efficient hash size
+    if (fpa->hdu) {
+        phu = fpa->hdu;
+        // Count the cells
+        psArray *chips = fpa->chips;    // Array of chips
+        numChips = chips->n;
+        for (int i = 0; i < chips->n; i++) {
+            pmChip *chip = chips->data[i]; // Chip of interest
+            numCells += chip->cells->n;
+        }
+        numCells = (float)numCells / (float)numChips + 0.5; // Average number of cells per chip
+        phuLevel = PM_FPA_LEVEL_FPA;
+    }
+    if (!phu && chip->hdu) {
+        phu = chip->hdu;
+        numChips = 1;
+        numCells = chip->cells->n;
+        phuLevel = PM_FPA_LEVEL_CHIP;
+    }
+    if (!phu && cell->hdu) {
+        phu = cell->hdu;
+        numChips = 0;
+        numCells = 1;
+        phuLevel = PM_FPA_LEVEL_CELL;
+    }
+    if (!phu || phuLevel == PM_FPA_LEVEL_NONE) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Can't find the PHU.\n");
+        return false;
+    }
+
+
+    // Find out what to read
+    psMetadata *shiftsInfo = psMetadataLookupMetadata(&mdok, phu->format, "SHIFTS"); // Shifts information
+    if (!mdok || !shiftsInfo) {
+        // We have read all the shifts that we have been told about --- which is none.
+        return true;
+    }
+    const char *shiftsExt = psMetadataLookupStr(&mdok, shiftsInfo, "EXTENSION"); // Extension name for shifts
+    if (!mdok || !shiftsExt) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Can't find EXTENSION name in SHIFTS information from camera format.");
+        return false;
+    }
+    const char *chipCol = NULL;         // Column name for chip
+    if (phuLevel == PM_FPA_LEVEL_FPA) {
+        chipCol = psMetadataLookupStr(&mdok, shiftsInfo, "CHIP");
+        if (!mdok || !chipCol) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Can't find CHIP column name in SHIFTS information from camera format.");
+            return false;
+        }
+    }
+    const char *cellCol = NULL;         // Column name for cell
+    if (phuLevel <= PM_FPA_LEVEL_CHIP) {
+        cellCol = psMetadataLookupStr(&mdok, shiftsInfo, "CELL");
+        if (!mdok || !chipCol) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Can't find CELL column name in SHIFTS information from camera format.");
+            return false;
+        }
+    }
+    const char *tCol = psMetadataLookupStr(&mdok, shiftsInfo, "T");
+    if (!mdok || !tCol) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Can't find T column name in SHIFTS information from camera format.");
+        return false;
+    }
+    const char *xCol = psMetadataLookupStr(&mdok, shiftsInfo, "X");
+    if (!mdok || !xCol) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Can't find X column name in SHIFTS information from camera format.");
+        return false;
+    }
+    const char *yCol = psMetadataLookupStr(&mdok, shiftsInfo, "Y");
+    if (!mdok || !yCol) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Can't find Y column name in SHIFTS information from camera format.");
+        return false;
+    }
+
+    bool tRel = psMetadataLookupBool(&mdok, shiftsInfo, "TRELATIVE");
+    if (!mdok) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Can't find TRELATIVE in SHIFTS information from camera format.");
+        return false;
+    };
+    bool xyRel = psMetadataLookupStr(&mdok, shiftsInfo, "XYRELATIVE");
+    if (!mdok) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Can't find XYRELATIVE in SHIFTS information from camera format.");
+        return false;
+    };
+
+    // Read the FITS file
+    int origExt = psFitsGetExtNum(fits); // Original extension number; to preserve position
+    if (!psFitsMoveExtName(fits, shiftsExt)) {
+        psError(PS_ERR_IO, false, "Unable to move to shifts extension %s", shiftsExt);
+        return false;
+    }
+    psArray *table = psFitsReadTable(fits); // The table of shifts
+    if (!table) {
+        psError(PS_ERR_IO, false, "Unable to read shifts table.\n");
+        return false;
+    }
+
+    // More sensible storage
+    pmShifts *singleShifts = NULL;      // Shifts for a single cell
+    psHash *multipleShifts = NULL;      // Shifts for multiple cells, stored by cell name
+    switch (phuLevel) {
+      case PM_FPA_LEVEL_FPA:
+        multipleShifts = psHashAlloc(2 * numChips);
+        break;
+      case PM_FPA_LEVEL_CHIP:
+        multipleShifts = psHashAlloc(2 * numCells);
+        break;
+      case PM_FPA_LEVEL_CELL:
+        singleShifts = pmShiftsAlloc(tRel, xyRel);
+        break;
+      default:
+        psAbort("Should never get here.\n");
+    }
+
+    // Pull values out of the table into something a bit more sensible
+    for (int i = 0; i < table->n; i++) {
+        psMetadata *row = table->data[i]; // The row of interest
+
+        const char *chipName = NULL;    // Name of chip
+        if (phuLevel == PM_FPA_LEVEL_FPA) {
+            // Only care about the chip name if there's more than one chip
+            chipName = psMetadataLookupStr(&mdok, row, chipCol);
+            if (!mdok || !chipName) {
+                psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find column %s in row %d of shifts table\n",
+                        chipCol, i);
+                psFree(multipleShifts);
+                psFree(table);
+                return false;
+            }
+        }
+        const char *cellName = NULL;    // Name of cell
+        if (phuLevel <= PM_FPA_LEVEL_CHIP) {
+            // Only care about the cell name if there's a chip
+            cellName = psMetadataLookupStr(&mdok, row, cellCol);
+            if (!mdok || !cellName) {
+                psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find column %s in row %d of shifts table\n",
+                        cellCol, i);
+                psFree(multipleShifts);
+                psFree(table);
+                return false;
+            }
+        }
+        float x = psMetadataLookupS32(&mdok, row, xCol); // Shift in x
+        if (!mdok) {
+            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find column %s in row %d of shifts table\n",
+                    xCol, i);
+            psFree(multipleShifts);
+            psFree(table);
+            return false;
+        }
+        float y = psMetadataLookupF32(&mdok, row, yCol); // Shift in y
+        if (!mdok) {
+            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find column %s in row %d of shifts table\n",
+                    yCol, i);
+            psFree(multipleShifts);
+            psFree(table);
+            return false;
+        }
+        float t = psMetadataLookupF32(&mdok, row, tCol); // Time of shift
+        if (!mdok) {
+            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find column %s in row %d of shifts table\n",
+                    tCol, i);
+            psFree(multipleShifts);
+            psFree(table);
+            return false;
+        }
+
+        pmShifts *shifts = NULL;        // Shifts for the cell of interest
+        switch (phuLevel) {
+          case PM_FPA_LEVEL_FPA: {
+              psHash *cells = psHashLookup(multipleShifts, chipName); // Hash of cells
+              if (!cells) {
+                  cells = psHashAlloc(numCells);
+                  psHashAdd(multipleShifts, chipName, cells);
+                  psFree(cells);          // Drop reference
+              }
+              shifts = cellVectors(cells, cellName, tRel, xyRel);
+              break;
+          }
+          case PM_FPA_LEVEL_CHIP:
+            shifts = cellVectors(multipleShifts, cellName, tRel, xyRel);
+            break;
+          case PM_FPA_LEVEL_CELL:
+            shifts = singleShifts;
+            break;
+          default:
+            psAbort("Should never get here.\n");
+        }
+
+        // Add the shift
+        psVectorExtend(shifts->x, 1, SHIFTS_BUFFER);
+        psVectorExtend(shifts->y, 1, SHIFTS_BUFFER);
+        psVectorExtend(shifts->t, 1, SHIFTS_BUFFER);
+        shifts->x->data.S32[shifts->num] = (int)x;
+        shifts->y->data.S32[shifts->num] = (int)y;
+        shifts->t->data.F32[shifts->num] = t;
+        shifts->num++;
+    }
+    psFree(table);
+
+    // Put the kernels into their own cells
+    if (phuLevel == PM_FPA_LEVEL_CELL) {
+        // Only a single cell
+        psMetadataAddPtr(cell->analysis, PS_LIST_TAIL, PM_SHIFTS_TABLE_NAME, PS_DATA_KERNEL,
+                         "Orthogonal transfer shifts", singleShifts);
+        psFree(singleShifts);
+        return true;
+    } else {
+        psList *names = psHashKeyList(multipleShifts); // List of hash keys (chip/cell names)
+        psListIterator *namesIter = psListIteratorAlloc(names, PS_LIST_HEAD, false); // Iterator for names
+        const char *name;               // Name, from iteration
+        while ((name = psListGetAndIncrement(namesIter))) {
+            switch (phuLevel) {
+              case PM_FPA_LEVEL_FPA: {
+                  int chipNum = pmFPAFindChip(fpa, name); // Number of chip of interest
+                  if (chipNum < 0) {
+                      psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find chip %s", name);
+                      psFree(namesIter);
+                      psFree(names);
+                      psFree(multipleShifts);
+                      return false;
+                  }
+                  pmChip *chip = fpa->chips->data[chipNum]; // Chip of interest
+
+                  // Loop over component cells
+                  psHash *cells = psHashLookup(multipleShifts, name); // Hash of cells
+                  psList *cellNames = psHashKeyList(multipleShifts); // List of hash keys (cell names)
+                  psListIterator *cellNamesIter = psListIteratorAlloc(cellNames, PS_LIST_HEAD, false);
+                  const char *cellName;       // Cell name, from iteration
+                  while ((cellName = psListGetAndIncrement(cellNamesIter))) {
+                      int cellNum = pmChipFindCell(chip, cellName); // Number of cell of interest
+                      if (!cell) {
+                          psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find cell %s", cellName);
+                          psFree(cellNamesIter);
+                          psFree(cellNames);
+                          psFree(namesIter);
+                          psFree(names);
+                          psFree(multipleShifts);
+                          return false;
+                      }
+                      pmCell *cell = chip->cells->data[cellNum]; // Cell of interest
+                      if (psMetadataLookup(cell->analysis, PM_SHIFTS_TABLE_NAME)) {
+                          // Already has a shifts table, for some reason
+                          psWarning("Chip %s, cell %s already has a shifts table --- overwriting\n",
+                                    name, cellName);
+                      }
+
+                      pmShifts *vectors = psHashLookup(cells, cellName); // Shifts for the cell of interest
+                      psMetadataAddPtr(cell->analysis, PS_LIST_TAIL, PM_SHIFTS_TABLE_NAME,
+                                       PS_DATA_KERNEL | PS_META_REPLACE,
+                                       "Orthogonal transfer shifts", vectors);
+                  }
+                  psFree(cellNamesIter);
+                  psFree(cellNames);
+                  break;
+              }
+              case PM_FPA_LEVEL_CHIP: {
+                  int cellNum = pmChipFindCell(chip, name); // Number of cell of interest
+                  if (!cell) {
+                      psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find cell %s", name);
+                      psFree(namesIter);
+                      psFree(names);
+                      psFree(multipleShifts);
+                      return false;
+                  }
+                  pmCell *cell = chip->cells->data[cellNum]; // Cell of interest
+                  if (psMetadataLookup(cell->analysis, PM_SHIFTS_TABLE_NAME)) {
+                      // Already has a shifts table, for some reason
+                      psWarning("Cell %s already has a shifts table --- overwriting\n", name);
+                  }
+
+                  pmShifts *vectors = psHashLookup(multipleShifts, name); // Shifts for this cell
+                  psMetadataAddPtr(cell->analysis, PS_LIST_TAIL, PM_SHIFTS_TABLE_NAME,
+                                   PS_DATA_KERNEL | PS_META_REPLACE,
+                                   "Orthogonal transfer shifts", vectors);
+                  break;
+              }
+              default:
+                psAbort("Should never get here.\n");
+            }
+        }
+        psFree(namesIter);
+        psFree(names);
+        psFree(multipleShifts);
+    }
+
+    // Go back to the original position in the FITS file
+    return psFitsMoveExtNum(fits, origExt, false);
+}
+
+
+// Generate a kernel and stuff it on the cell metadata
+bool pmShiftsKernel(const pmCell *cell     // Cell to which the shifts belong
+    )
+{
+    PS_ASSERT_PTR(cell, false);
+
+    bool mdok;                          // Status of MD lookup
+    pmShifts *shifts = psMetadataLookupPtr(&mdok, cell->analysis, PM_SHIFTS_TABLE_NAME);
+    if (!shifts) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find shifts table for cell.\n");
+        return false;
+    }
+
+    psKernel *kernel = psKernelGenerate(shifts->t, shifts->x, shifts->y,
+                                        shifts->tRelative, shifts->xyRelative); // Shift kernel
+    if (!kernel) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to generate kernel from OT shifts");
+        return false;
+    }
+    psMetadataAddPtr(cell->analysis, PS_LIST_TAIL, PM_SHIFTS_KERNEL_NAME, PS_DATA_KERNEL,
+                     "Orthogonal transfer kernel, calculated from shifts", kernel);
+    psFree(kernel);
+
+    return true;
+}
+
+bool pmShiftsConvolve(pmReadout *detrend, const pmCell *source, psMaskType maskVal)
+{
+    PS_ASSERT_PTR(detrend, false);
+    PS_ASSERT_PTR(source, false);
+
+    bool mdok;                          // Status of MD lookup
+    psKernel *kernel = psMetadataLookupPtr(&mdok, source->analysis, PM_SHIFTS_KERNEL_NAME);
+    if (!kernel) {
+        // Maybe they just forgot to generate the kernel with pmShiftsKernel
+        if (psMetadataLookup(source->analysis, PM_SHIFTS_TABLE_NAME)) {
+            if (!pmShiftsKernel(source)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to generate shifts kernel.");
+                return false;
+            }
+            // Hopefully it's there now
+            kernel = psMetadataLookupPtr(&mdok, source->analysis, PM_SHIFTS_KERNEL_NAME);
+            if (!kernel) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to find shifts kernel.");
+                return false;
+            }
+        } else {
+            psError(PS_ERR_UNKNOWN, false, "Unable to find shifts kernel or shifts table.");
+            return false;
+        }
+    }
+
+    if (detrend->image) {
+#if 1
+        // Always do direct convolution (no fuss with edge effects)
+        psImage *convolved = psImageConvolveDirect(NULL, detrend->image, kernel);
+#else
+        // Kernel size-dependent convolution --- if it's big, use the FFT
+        int xSize = kernel->xMax - kernel->xMin; // Kernel size in x
+        int ySize = kernel->yMax - kernel->yMin; // Kernel size in y
+        psImage *convolved;
+        if (xSize * ySize < FFT_SIZE * FFT_SIZE) {
+            convolved = psImageConvolveDirect(NULL, detrend->image, kernel);
+        } else {
+            // This is a little dodgy --- making choices about parameters without the user's input
+            psStats *stats = psImageStats(PS_STAT_ROBUST_MEDIAN);
+            stats->nSubsample = 10000;
+            psImageBackground(stats, detrend->image, detrend->mask, maskVal, NULL);
+            convolved = psImageConvolveFFT(detrend->image, kernel, stats->robustMedian);
+        }
+#endif
+        if (!convolved) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to convolve detrend image.");
+            return false;
+        }
+        psFree(detrend->image);
+        detrend->image = convolved;
+    }
+
+    // Purposely ignoring the weight map --- don't care about the weight map for a detrend image
+
+    if (maskVal && detrend->mask && !psImageConvolveMaskDirect(detrend->mask, detrend->mask, maskVal, 0,
+                                                               kernel->xMin, kernel->xMax,
+                                                               kernel->yMin, kernel->yMax)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to convolve detrend mask.");
+        return false;
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmShifts.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmShifts.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmShifts.h	(revision 22158)
@@ -0,0 +1,51 @@
+#ifndef PM_SHIFTS_H
+#define PM_SHIFTS_H
+
+#define PM_SHIFTS_TABLE_NAME "SHIFTS.TABLE" ///< Name for table on the analysis metadata
+#define PM_SHIFTS_KERNEL_NAME "SHIFTS.KERNEL" ///< Name for kernel on the analysis metadata
+
+/// Shifts due to orthogonal transfer
+typedef struct {
+    psVector *x;                        ///< Shifts in x
+    psVector *y;                        ///< Shifts in y
+    psVector *t;                        ///< Times of shifts
+    long num;                           ///< Number of values
+    bool tRelative;                     ///< Are the time values relative (durations)?
+    bool xyRelative;                    ///< Are the shift (x,y) values relative to the previous position?
+} pmShifts;
+
+/// Allocator for pmShifts
+pmShifts *pmShiftsAlloc(bool tRel,      ///< Are the time values relative (durations)?
+                        bool xyRel      ///< Are the shift (x,y) values relative to the previous position?
+                        );
+
+/// Read orthogonal transfer shifts table for a cell
+///
+/// Given a cell, this function searches for the orthogonal transfer shifts for this cell in the supplied FITS
+/// file.  The FITS extension containing the shifts table is specified by the SHIFTS keyword within the FILE
+/// information in the camera format.  If the extension is found, the shifts table is read and translated into
+/// kernels which are placed in the analysis metadata of each cell.  Note that this operation is performed on
+/// all cells within the FITS file (or at least, those contained within the shifts table), not just the cell
+/// provided --- if we have to read the whole table, we may as well translate the whole lot.  If a kernel is
+/// already present in the cell analysis metadata, the function returns true without doing any work.
+bool pmShiftsRead(const pmCell *cell,         ///< Cell for which to search for shifts
+                  psFits *fits          ///< FITS file in which to search for OT shifts extension
+                  );
+
+
+/// Generate a kernel for the cell from the orthogonal transfer shifts
+///
+/// The kernel is saved in the analysis metadata
+bool pmShiftsKernel(const pmCell *cell   ///< Cell for which to generate kernel
+                    );
+
+/// Convolve a detrend with the appropriate orthogonal transfer convolution kernel from a science exposure.
+///
+/// The kernel is generated (with pmShiftsKernel) if required.  The image and mask are convolved with the
+/// kernel (specified maskVal is smeared).  The weight map is not convolved.
+bool pmShiftsConvolve(pmReadout *detrend, ///< Detrend readout to convolve
+                      const pmCell *source, ///< Science exposure, containing a shifts kernel
+                      psMaskType maskVal ///< Mask value to smear
+                      );
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmShutterCorrection.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmShutterCorrection.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmShutterCorrection.c	(revision 22158)
@@ -0,0 +1,1080 @@
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <strings.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmHDUUtils.h"
+#include "psVectorBracket.h"
+#include "pmConceptsAverage.h"
+#include "pmReadoutStack.h"
+
+#include "pmShutterCorrection.h"
+
+/// Measure shutter correction:
+///
+/// input  : collection of shutter correction exposures (pre-processed)
+/// output : a shutter correction image
+///
+/// The measurement could be performed on any focal-plane unit at a time. for GPC, the obvious scale is to
+/// measure the effect on the entire focal plane at once, with a single reference point in the field.  this is
+/// a little more complex than just measuring the effect for a single 2D image array.  the reference point and
+/// the detailed analysis points need to be defined for the entire hierarchy rather than just as coordinate
+/// pairs or regions.  a pmFPAview would be a natural element with which to define these points, but at the
+/// moment, the pmFPAview structure defines a band in the CCD, not a coordinate.  An option is to instead
+/// specify the reference locations as a pmFPAview coupled with a psRegion, though we need to be careful not
+/// to over-specify the pixels (ie, conflict between pmFPAview and psRegion).
+///
+/// At each point in an image with exposure time T, we measure f(k;T) = F(k;T) / F(0;T) where k is the
+/// coordinate of the point of interest, 0 is the reference coordinate, and F(k;T) is the measured number of
+/// counts at the point of interest in this image.  given a collection of f(k;T) values, we need to determine
+/// the model f(k;T) = A(k) (T + dTk) / (T + dTo) where dTk is the shutter error at the given position, dTo is
+/// the shutter error at the reference position, and A(k) is the scaling factor for the given position.
+///
+/// The process for generating a shutter correction is as follows:
+/// - for each image
+/// -- measure the reference point counts
+/// - for each analysis region:
+/// -- measure shutter parameters (dTo, dTk, A):
+/// --- for each image:
+/// ---- measure counts at the region
+/// ---- divide by the reference counts
+/// --- linear extrapolation to find f(inf) = A(k)
+/// --- linear extrapolation to find f(0) = A(k) dTk / dTo
+/// --- linear interpolation to find coordinate where f(dTo) = A (1 + dTk/dTo) / 2
+/// --- non-linear fit of T, f(T) to f(k;T) = A(k) (T + dTk) / (T + dTo)
+/// - use the collection of dTo values to choose a best value for dTo (median)
+/// - for each image pixel
+/// -- divide by the reference counts
+/// -- generate the vectors T, f(T)
+/// -- linear fit of T, f(T) to f(k;T) = A(k) (T + dTk) / (T + dTo) using dTo above
+/// -- save dTk, A(k) in output image pixels
+/// -- apply dTk, A(k) to measure residual images
+/// -- generate residual FITS/JPEG images
+
+
+#define MEASURE_SAMPLES 4               // Number of samples to make over the image.  This should only be
+                                        // changed with great caution, since assumptions on its value are in
+                                        // the code (see pmShutterCorrectionDataAlloc).
+
+
+static void pmShutterCorrectionFree(pmShutterCorrection *pars)
+{
+    // Nothing to free
+    return;
+}
+
+pmShutterCorrection *pmShutterCorrectionAlloc()
+{
+    pmShutterCorrection *corr = (pmShutterCorrection*)psAlloc(sizeof(pmShutterCorrection));
+    psMemSetDeallocator(corr, (psFreeFunc)pmShutterCorrectionFree);
+
+    corr->scale  = 0.0;
+    corr->offset = 0.0;
+    corr->offref = 0.0;
+    corr->num = 0;
+    corr->stdev = NAN;
+    corr->valid = true;
+
+    return corr;
+}
+
+pmShutterCorrection *pmShutterCorrectionGuess(const psVector *exptime, const psVector *counts)
+{
+    // NOTE: vectors must be sorted on input.  It is expensive to sort or check this here, but
+    // it is easy to arrange by sorting the images before generating these vectors.
+
+    PS_ASSERT_VECTOR_NON_NULL(exptime, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(counts, NULL);
+    PS_ASSERT_VECTOR_TYPE(exptime, PS_TYPE_F32, NULL);
+    PS_ASSERT_VECTOR_TYPE(counts, PS_TYPE_F32, NULL);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(exptime, counts, NULL);
+    if (exptime->n <= 2) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                "Require more than 2 exposures to guess shutter correction.\n");
+        return NULL;
+    }
+
+    long N = exptime->n;                // Number of exposures
+
+    // use interpolation to guess shutter correction parameters given a set of exposures times and normalized
+    // counts (divided by the reference counts for each image)
+
+    pmShutterCorrection *corr = pmShutterCorrectionAlloc(); // Shutter correction, to be returned
+    psPolynomial1D *line = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 1); // Straight line, for extrapolation
+
+    // choose the highest exptime point as the guess for the scale:
+    // XXX we could examine the top 2 or 3 values and decide if we
+    // extended exptime enough or median clip.
+    corr->scale = counts->data.F32[N-1];
+
+    // fit a line to the lowest three points and extrapolate to 0.0
+    psVector *tmpX = psVectorAlloc(2, PS_TYPE_F32);
+    psVector *tmpY = psVectorAlloc(2, PS_TYPE_F32);
+
+    long index;
+
+    // Iterate only
+    for (index = 0; !isfinite(exptime->data.F32[index]) && index < N - 1; index++); 
+
+    if (index == N - 1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Not enough good values to guess shutter correction.\n");
+        goto GUESS_ERROR;
+    }
+    tmpX->data.F32[0] = exptime->data.F32[index];
+    tmpY->data.F32[0] = counts->data.F32[index];
+
+    for (index++;
+            (!isfinite(exptime->data.F32[index]) || exptime->data.F32[index] == exptime->data.F32[0]) &&
+            index < N; index++)
+        ; // Iterate only
+    if (index == N) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Exposure times are all identical --- cannot guess shutter correction.\n");
+        goto GUESS_ERROR;
+    }
+    tmpY->data.F32[1] = counts->data.F32[index];
+    tmpX->data.F32[1] = exptime->data.F32[index];
+
+    // fit a line and extrapolate the fit to 0.0
+    if (!psVectorFitPolynomial1D(line, NULL, 0, tmpY, NULL, tmpX)) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to fit for the time offset.\n");
+        goto GUESS_ERROR;
+    }
+    float ratio = psPolynomial1DEval(line, 0.0) / corr->scale;
+
+    // XXX we need a sanity check:
+    // if the mean value of the three points is higher than corr->scale,
+    // then the slope should be negative.
+    // if the mean value of the three points is lower than corr->scale,
+    // then the slope should be positive.
+
+    // find two points bracketing the value counts = A (1 + dTk/dTo) / 2 = corr->scale (1 + ratio) / 2
+    float value = corr->scale * (1 + ratio) / 2.0;
+
+    int Np;                             // Index of the value above (positive side)
+    if (ratio < 1.0) {
+        Np = psVectorBracket(counts, value, true);
+    } else {
+        Np = psVectorBracketDescend(counts, value, true);
+    }
+    int Nm = (Np == 0) ? 1 : Np - 1;    // Index of the value below (negative side)
+
+    tmpX->data.F32[0] = counts->data.F32[Nm];
+    tmpX->data.F32[1] = counts->data.F32[Np];
+    tmpY->data.F32[0] = exptime->data.F32[Nm];
+    tmpY->data.F32[1] = exptime->data.F32[Np];
+
+    // fit a line and extrapolate the fit to counts = A (1 + dTk/dTo) : exptime = dTo
+    if (!psVectorFitPolynomial1D (line, NULL, 0, tmpY, NULL, tmpX)) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to fit for the reference offset.\n");
+        goto GUESS_ERROR;
+    }
+    corr->offref = psPolynomial1DEval(line, value);
+    corr->offset = ratio * corr->offref;
+
+    psFree(line);
+    psFree(tmpX);
+    psFree(tmpY);
+
+    return corr;
+
+GUESS_ERROR:
+    psFree(tmpX);
+    psFree(tmpY);
+    psFree(line);
+    psFree(corr);
+    return NULL;
+}
+
+// linear fit to the counts and exptime, given a value for offref
+pmShutterCorrection *pmShutterCorrectionLinFit(const psVector *exptime, const psVector *counts,
+                                               const psVector *cntError, const psVector *mask, float offref,
+                                               int nIter, float rej, psMaskType maskVal)
+{
+    PS_ASSERT_VECTOR_NON_NULL(exptime, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(counts, NULL);
+    PS_ASSERT_VECTOR_TYPE(exptime, PS_TYPE_F32, NULL);
+    PS_ASSERT_VECTOR_TYPE(counts, PS_TYPE_F32, NULL);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(exptime, counts, NULL);
+    if (exptime->n <= 2) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                "Require more than 2 exposures to guess shutter correction.\n");
+        return NULL;
+    }
+    if (cntError) {
+        PS_ASSERT_VECTOR_TYPE(cntError, PS_TYPE_F32, NULL);
+        PS_ASSERT_VECTORS_SIZE_EQUAL(counts, cntError, NULL);
+    }
+    PS_ASSERT_FLOAT_LARGER_THAN(offref, 0.0, NULL);
+
+    // this step is identical for all pixels: do it once and save?
+    psVector *x = psVectorAlloc(exptime->n, PS_TYPE_F32);
+    psVector *y = psVectorAlloc(exptime->n, PS_TYPE_F32);
+
+    for (long i = 0; i < exptime->n; i++) {
+        // Should be safe (if expensive) to stick NaNs in --- the fitter deals with them
+        float value = 1.0 / (exptime->data.F32[i] + offref);
+        x->data.F32[i] = exptime->data.F32[i] * value;
+        y->data.F32[i] = value;
+    }
+
+    psPolynomial2D *line = psPolynomial2DAlloc (PS_POLYNOMIAL_ORD, 1, 1);
+
+    // mask out the terms we will not fit
+    line->coeffMask[0][0] = PS_POLY_MASK_SET;
+    line->coeffMask[1][1] = PS_POLY_MASK_SET;
+    line->coeff[0][0] = 0;
+    line->coeff[1][1] = 0;
+
+    // the stats structure determines how the clipping statistic is measured
+    // too few points to use the robust analysis method
+    psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
+    stats->clipSigma = rej;
+    stats->clipIter = nIter;
+
+    if (!psVectorClipFitPolynomial2D(line, stats, mask, maskVal, counts, cntError, x, y)) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to fit shutter correction.\n");
+        psFree(stats);
+        psFree(x);
+        psFree(y);
+        psFree(line);
+        return NULL;
+    }
+
+    pmShutterCorrection *corr = pmShutterCorrectionAlloc();
+    corr->offref = offref;
+    corr->scale  = line->coeff[1][0];
+    corr->offset = line->coeff[0][1] / line->coeff[1][0];
+    corr->num = stats->clippedNvalues;
+    corr->stdev = stats->clippedStdev;
+
+    psFree(stats);
+    psFree(x);
+    psFree(y);
+    psFree(line);
+
+    return corr;
+}
+
+static psF32 pmShutterCorrectionModel(psVector *deriv, const psVector *params, const psVector *x)
+{
+    // This is in a tight loop, so we won't assert here.
+
+    psF32 A = params->data.F32[0];
+    psF32 p = x->data.F32[0] + params->data.F32[1];
+    psF32 q = 1.0 / (x->data.F32[0] + params->data.F32[2]);
+    psF32 f = A * p * q;
+
+    if (deriv) {
+        deriv->data.F32[0] = p * q;
+        deriv->data.F32[1] = A * q;
+        deriv->data.F32[2] = - f * q;
+    }
+    return f;
+}
+
+// non-linear fit to the counts and exptime, given a guess for the three parameters
+pmShutterCorrection *pmShutterCorrectionFullFit(const psVector *exptime, const psVector *counts,
+                                                const psVector *cntError, const pmShutterCorrection *guess)
+{
+    PS_ASSERT_VECTOR_NON_NULL(exptime, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(counts, NULL);
+    PS_ASSERT_VECTOR_TYPE(exptime, PS_TYPE_F32, NULL);
+    PS_ASSERT_VECTOR_TYPE(counts, PS_TYPE_F32, NULL);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(exptime, counts, NULL);
+    if (exptime->n <= 2) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                "Require more than 2 exposures to guess shutter correction.\n");
+        return NULL;
+    }
+    if (cntError) {
+        PS_ASSERT_VECTOR_TYPE(cntError, PS_TYPE_F32, NULL);
+        PS_ASSERT_VECTORS_SIZE_EQUAL(counts, cntError, NULL);
+    }
+    PS_ASSERT_PTR_NON_NULL(guess, NULL);
+
+    psMinimization *minInfo = psMinimizationAlloc(15, 0.1); // Minimization information
+
+    psVector *params = psVectorAlloc (3, PS_TYPE_F32); // Fitting parameters
+    params->data.F32[0] = guess->scale;
+    params->data.F32[1] = guess->offset;
+    params->data.F32[2] = guess->offref;
+
+    // XXX for the moment, don't set any constraints
+    // psMinConstraint *constraint = psMinConstraintAlloc();
+    // constrain->checkLimits = pmShutterParamLimits;
+    // constrain->paramMask   = NULL;
+    psMinConstraint *constraint = NULL;   // Constraints on the minimization
+
+    // XXX ignore covariance matrix for the moment
+    // psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F64);
+    psImage *covar = NULL;              // Covariance matrix
+
+    // construct the coordinate and value entries (y is counts)
+    psArray *x = psArrayAlloc(exptime->n); // Coordinates
+
+    for (long i = 0; i < exptime->n; i++) {
+        psVector *coord = psVectorAlloc(1, PS_TYPE_F32);
+        coord->data.F32[0] = exptime->data.F32[i];
+        x->data[i] = coord;
+    }
+
+    if (!psMinimizeLMChi2(minInfo, covar, params, constraint, x, counts, cntError, pmShutterCorrectionModel)) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to fit for shutter correction.\n");
+        psFree(x);
+        psFree(minInfo);
+        psFree(params);
+        return NULL;
+    }
+
+    pmShutterCorrection *corr = pmShutterCorrectionAlloc(); // Shutter correction
+    corr->scale  = params->data.F32[0];
+    corr->offset = params->data.F32[1];
+    corr->offref = params->data.F32[2];
+
+    // apply the correction and measure the residual scatter
+    psVector *resid = psVectorAlloc (exptime->n, PS_TYPE_F32);
+    for (int i = 0; i < exptime->n; i++) {
+	float fitCounts = corr->scale * (exptime->data.F32[i] + corr->offset) / (exptime->data.F32[i] + corr->offref);
+	resid->data.F32[i] = counts->data.F32[i] - fitCounts;
+    }
+    
+    psStats *rawStats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
+    psStats *resStats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
+    psVectorStats (rawStats, counts, NULL, NULL, 0);
+    psVectorStats (resStats, resid, NULL, NULL, 0);
+
+    // XXX temporary hard-wired minimum stdev improvement factor 
+    psTrace("psModules.detrend", 3, "raw scatter %f vs res scatter %f\n", rawStats->sampleStdev, resStats->sampleStdev);
+    if (rawStats->sampleStdev / resStats->sampleStdev < 1.5) corr->valid = false;
+
+    psFree (rawStats);
+    psFree (resStats);
+    psFree (resid);
+
+    psFree(minInfo);
+    psFree(params);
+    psFree(x);
+
+    return corr;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool pmShutterCorrectionMeasure(pmReadout *output, const psArray *readouts, int size, psStatsOptions meanStat,
+                                psStatsOptions stdevStat, int nIter, float rej, psMaskType maskVal)
+{
+    PS_ASSERT_ARRAY_NON_NULL(readouts, NULL);
+    PS_ASSERT_ARRAY_NON_EMPTY(readouts, NULL);
+    PS_ASSERT_INT_POSITIVE(size, NULL);
+
+    long num = readouts->n;             // Number of readouts
+    PS_ASSERT_INT_POSITIVE(nIter, NULL);
+    PS_ASSERT_FLOAT_LARGER_THAN(rej, 0.0, NULL);
+
+    psArray *images = psArrayAlloc(num);// Array of images
+    psArray *masks = NULL; // Array of masks
+    psArray *weights = NULL; // Array of weights
+    psVector *exptimes = psVectorAlloc(num, PS_TYPE_F32); // Vector of exposure times
+
+    {
+        pmReadout *readout = readouts->data[0]; // Representative readout
+        if (readout->mask)
+        {
+            masks = psArrayAlloc(num);
+        }
+        if (readout->weight)
+        {
+            weights = psArrayAlloc(num);
+        }
+    }
+
+    // Check input sizes, generate first-pass statistics
+    psRegion refRegion;                 // Reference region
+    psVector *refs = psVectorAlloc(num, PS_TYPE_F32); // Reference measurements
+    psVectorInit(refs, 0);
+    psArray *regions = psArrayAlloc(MEASURE_SAMPLES); // Array of sample regions, made on each image
+    psImage *samplesMean = psImageAlloc(num, MEASURE_SAMPLES, PS_TYPE_F32); // Measurements for each file
+    psImage *samplesStdev = psImageAlloc(num, MEASURE_SAMPLES, PS_TYPE_F32); // Errors for each file
+    psStats *stats = psStatsAlloc(meanStat | stdevStat);
+    int numRows = 0, numCols = 0; // Size of images
+    for (long i = 0; i < images->n; i++) {
+        pmReadout *readout = readouts->data[i]; // Readout of interest
+        if (!readout) {
+            continue;
+        }
+
+        bool mdok;                      // Status of MD lookup
+        float exptime = psMetadataLookupF32(&mdok, readout->parent->concepts, "CELL.EXPOSURE"); // Exp. time
+        if (!mdok || !isfinite(exptime)) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Exposure time for readout %ld is not set.\n", i);
+            goto MEASURE_ERROR;
+        }
+        exptimes->data.F32[i] = exptime;
+
+        psImage *image = readout->image; // Image of interest
+        if (!image) {
+            continue;
+        }
+        images->data[i] = psMemIncrRefCounter(image);
+        if (image->type.type != PS_TYPE_F32) {
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Bad type for image: %x\n", image->type.type);
+            goto MEASURE_ERROR;
+        }
+        if (numRows == 0 || numCols == 0) {
+            numRows = image->numRows;
+            numCols = image->numCols;
+	    // define the reference region : a box of size 'size' at the center
+            refRegion = psRegionForSquare(0.5 * numCols, 0.5 * numRows, size);
+            // Set up the sample regions : boxes of size 'size' at the 4 image corners
+            for (int j = 0; j < MEASURE_SAMPLES; j++) {
+                int x = (j % 2) ? size : image->numCols - size;
+                int y = (j > 1) ? size : image->numRows - size;
+                psRegion region = psRegionForSquare(x, y, size);
+                region = psRegionForImage(image, region);
+                regions->data[j] = psRegionAlloc(region.x0, region.x1, region.y0, region.y1);
+            }
+        } else if (numRows != image->numRows || numCols != image->numCols) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    "Image sizes don't match: %dx%d vs %dx%d\n", image->numCols, image->numRows,
+                    numCols, numRows);
+            goto MEASURE_ERROR;
+        }
+        psImage *mask = readout->mask; // Mask of interest
+        if (mask) {
+            if (!masks) {
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Not all readouts have masks.\n");
+                goto MEASURE_ERROR;
+            }
+            masks->data[i] = psMemIncrRefCounter(mask);
+
+            if (mask->type.type != PS_TYPE_U8) {
+                psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Bad type for mask: %x\n", mask->type.type);
+                goto MEASURE_ERROR;
+            }
+            if (mask->numRows != numRows || mask->numCols != numCols) {
+                psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                        "Mask sizes don't match: %dx%d vs %dx%d\n", mask->numCols, mask->numRows,
+                        numCols, numRows);
+                goto MEASURE_ERROR;
+            }
+        } else if (masks) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Not all readouts have masks.\n");
+            goto MEASURE_ERROR;
+        }
+
+        psImage *weight = readout->weight; // Weight map of interest
+        if (weight) {
+            if (!weights) {
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Not all readouts have weights.\n");
+                goto MEASURE_ERROR;
+            }
+            weights->data[i] = psMemIncrRefCounter(weight);
+
+            if (weight->type.type != PS_TYPE_F32) {
+                psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Bad type for weights: %x\n", weight->type.type);
+                goto MEASURE_ERROR;
+            }
+            if (weight->numRows != numRows || weight->numCols != numCols) {
+                psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                        "Weight sizes don't match: %dx%d vs %dx%d\n", weight->numCols, weight->numRows,
+                        numCols, numRows);
+                goto MEASURE_ERROR;
+            }
+        } else if (weights) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Not all readouts have weights.\n");
+            goto MEASURE_ERROR;
+        }
+
+
+        // Measure statistics
+        if (!psImageStats(stats, image, mask, maskVal)) {
+            psWarning("Unable to measure reference statistics.\n");
+        }
+        refs->data.F32[i] = psStatsGetValue(stats, meanStat);
+        psTrace("psModules.detrend", 3, "Reference value for image %ld = %f\n", i, refs->data.F32[i]);
+        if (refs->data.F32[i] <= 0.0) {
+            psError(PS_ERR_UNKNOWN, true, "Measured non-positive reference value.\n");
+            goto MEASURE_ERROR;
+        }
+        refs->data.F32[i] = 1.0 / refs->data.F32[i];
+        for (int j = 0; j < MEASURE_SAMPLES; j++) {
+            psRegion *region = regions->data[j]; // Region of interest
+            psImage *subImage = psImageSubset(image, *region); // Sub-image
+            psImage *subMask = NULL;
+            if (mask) {
+                subMask = psImageSubset(mask, *region);
+            }
+            if (!psImageStats(stats, subImage, subMask, maskVal)) {
+                psString regionString = psRegionToString(*region);
+                psWarning("Unable to measure sample statistics at %s in image %ld.\n",
+                          regionString, i);
+                psFree(regionString);
+            }
+            psFree(subImage);
+            samplesMean->data.F32[j][i] = psStatsGetValue(stats, meanStat) * refs->data.F32[i];
+            samplesStdev->data.F32[j][i] = psStatsGetValue(stats, stdevStat) * refs->data.F32[i];
+            psTrace("psModules.detrend", 5, "Image %ld, sample %d: %f +/- %f\n", i, j,
+                    samplesMean->data.F32[j][i], samplesStdev->data.F32[j][i]);
+        }
+    }
+    psFree(regions);
+    psFree(stats);
+
+    float meanRef = 0.0;                // Mean reference offset
+    int numGood = 0;                    // Number of good measurements
+    psVector *counts = psVectorAlloc(num, PS_TYPE_F32); // Mean for each image
+    psVector *errors = psVectorAlloc(num, PS_TYPE_F32); // Stdev for each image
+    for (int i = 0; i < MEASURE_SAMPLES; i++) {
+        counts = psImageRow(counts, samplesMean, i);
+        errors = psImageRow(errors, samplesStdev, i);
+        pmShutterCorrection *guess = pmShutterCorrectionGuess(exptimes, counts); // Guess at correction
+        pmShutterCorrection *corr = pmShutterCorrectionFullFit(exptimes, counts, errors, guess); // Correct'n
+        if (!corr) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to measure shutter reference correction.\n");
+            psFree(guess);
+            psFree(counts);
+            psFree(errors);
+            goto MEASURE_ERROR;
+        }
+        psTrace("psModules.detrend", 5, "Sample reference value: %f\n", corr->offref);
+        if (isfinite(corr->offref)) {
+            meanRef += corr->offref;
+            numGood++;
+        }
+        psFree(corr);
+        psFree(guess);
+    }
+    psFree(samplesMean);
+    psFree(samplesStdev);
+
+    if (numGood == 0) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to measure mean reference offset.\n");
+        psFree(counts);
+        psFree(errors);
+        goto MEASURE_ERROR;
+    }
+    meanRef /= (float)numGood;
+    psTrace("psModules.detrend", 3, "Mean reference value: %f\n", meanRef);
+
+    // Check the weights
+    if (weights && nIter > 1) {
+        for (int i = 0; i < weights->n && nIter > 1; i++) {
+            psImage *weight = weights->data[i]; // Weight image
+            if (!weight) {
+                // We don't have weights, so no realistic errors: turn off iteration
+                if (nIter > 0) {
+                    psWarning("Not all images have weights --- turning iteration off.\n");
+                }
+                nIter = 1;
+            }
+        }
+    }
+
+    psImage *shutter = psImageAlloc(numCols, numRows, PS_TYPE_F32); // Shutter correction image
+    psImage *pattern = psImageAlloc(numCols, numRows, PS_TYPE_F32); // Illumination pattern
+    psVector *mask = psVectorAlloc(num, PS_TYPE_U8); // Mask for each image
+    psVectorInit(mask, 0);
+    psTrace("psModules.detrend", 2, "Performing linear fit on individual pixels...\n");
+    for (int y = 0; y < numRows; y++) {
+        for (int x = 0; x < numCols; x++) {
+            for (int i = 0; i < num; i++) {
+                psImage *image = images->data[i]; // Image of interest
+                counts->data.F32[i] = image->data.F32[y][x] * refs->data.F32[i];
+                psImage *maskImage;     // Mask image
+                if (masks && (maskImage = masks->data[i])) {
+                    mask->data.U8[i] = maskImage->data.U8[y][x];
+                }
+                psImage *weight;        // Weight image
+                if (weights && (weight = weights->data[i])) {
+                    errors->data.F32[i] = sqrtf(weight->data.F32[y][x]) * refs->data.F32[i];
+                } else {
+                    errors->data.F32[i] = sqrtf(image->data.F32[y][x]) * refs->data.F32[i];
+                }
+            }
+
+            pmShutterCorrection *corr = pmShutterCorrectionLinFit(exptimes, counts, errors, mask, meanRef,
+                                        nIter, rej, maskVal);
+            shutter->data.F32[y][x] = corr->offset;
+            pattern->data.F32[y][x] = corr->scale;
+            psFree(corr);
+        }
+    }
+    psFree(mask);
+    psFree(counts);
+    psFree(errors);
+    psFree(refs);
+
+    if (psTraceGetLevel("psModules.detrend") > 5) {
+        psFits *fits = psFitsOpen("pattern.fits", "w");
+        psFitsWriteImage(fits, NULL, pattern, 0, NULL);
+        psFitsClose(fits);
+    }
+    psFree(pattern);
+
+    output->image = shutter;
+
+    // Update the "concepts"
+    psList *inputCells = psListAlloc(NULL); // List of cells
+    for (long i = 0; i < readouts->n; i++) {
+        pmReadout *readout = readouts->data[i]; // Readout of interest
+        psListAdd(inputCells, PS_LIST_TAIL, readout->parent);
+    }
+    bool success = pmConceptsAverageCells(output->parent, inputCells, NULL, NULL, true);
+    psFree(inputCells);
+
+    // Correct the exposure times --- they don't make sense any more.
+    psMetadataItem *item = psMetadataLookup(output->parent->concepts, "CELL.EXPOSURE");
+    item->data.F32 = NAN;
+    item = psMetadataLookup(output->parent->concepts, "CELL.DARKTIME");
+    item->data.F32 = NAN;
+
+    return success;
+
+
+MEASURE_ERROR:
+    // Clean up after error
+    psFree(exptimes);
+    psFree(images);
+    psFree(masks);
+    psFree(weights);
+    psFree(refs);
+    psFree(regions);
+    psFree(stats);
+    psFree(samplesMean);
+    psFree(samplesStdev);
+    return false;
+}
+
+
+bool pmShutterCorrectionApply(pmReadout *readout, const pmReadout *shutter, psMaskType blank)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_PTR_NON_NULL(shutter, false);
+    PS_ASSERT_IMAGE_NON_NULL(readout->image, false);
+    PS_ASSERT_IMAGE_NON_NULL(shutter->image, false);
+    PS_ASSERT_IMAGE_TYPE(readout->image, PS_TYPE_F32, false);
+    PS_ASSERT_IMAGE_TYPE(shutter->image, PS_TYPE_F32, false);
+
+    psRegion region = psRegionSet(readout->col0, readout->col0 + readout->image->numCols,
+                                  readout->row0, readout->row0 + readout->image->numRows); // Detector region
+
+    pmCell *cell = readout->parent;     // Parent cell
+    if (!cell) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "Parent cell is NULL --- unable to determine exposure time.\n");
+        return false;
+    }
+    float exptime = psMetadataLookupF32(NULL, cell->concepts, "CELL.EXPOSURE"); // Exposure time
+    if (!isfinite(exptime)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Bad exposure time: %f.\n", exptime);
+        return false;
+    }
+
+    pmHDU *hdu = pmHDUFromCell(cell);// HDU  of interest
+
+    psVector *md5 = psImageMD5(shutter->image); // md5 hash
+    psString md5string = psMD5toString(md5); // String
+    psFree(md5);
+    psStringPrepend(&md5string, "Shutter image MD5: ");
+    psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, md5string, "");
+    psFree(md5string);
+
+
+    psImage *shutterImage = psImageSubset(shutter->image, region); // Subimage with shutter
+    if (!shutterImage) {
+        psString regionString = psRegionToString(region);
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Size mismatch: %s vs %dx%d\n",
+                regionString, shutter->image->numCols, shutter->image->numRows);
+        psFree(regionString);
+        psFree(shutterImage);
+        return false;
+    }
+    psImage *image = readout->image;    // Image to correct
+    psImage *mask = readout->mask;      // Corresponding mask
+
+    if (exptime <= 0.0) {
+        // In the extreme case that we have exptime <= 0.0, we correct the image to
+        // counts-per-second, rather than counts in the nominal exposure time
+        for (int y = 0; y < image->numRows; y++) {
+            for (int x = 0; x < image->numCols; x++) {
+                if (mask && !isfinite(shutterImage->data.F32[y][x])) {
+                    mask->data.PS_TYPE_MASK_DATA[y][x] |= blank;
+                    image->data.F32[y][x] = NAN;
+                    continue;
+                }
+                image->data.F32[y][x] *= 1.0 / (exptime + shutterImage->data.F32[y][x]);
+            }
+        }
+        psMetadataAddF32 (cell->concepts, PS_LIST_TAIL, "CELL.EXPOSURE", PS_META_REPLACE, "exposure time re-normalized to 1.0", 1.0); // Exposure time
+        psString line = NULL;
+        psStringAppend (&line, "extreme exposure time %f, re-normalized to 1.0", exptime);
+        psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, line, "");
+        psFree (line);
+    } else {
+        for (int y = 0; y < image->numRows; y++) {
+            for (int x = 0; x < image->numCols; x++) {
+                if (mask && !isfinite(shutterImage->data.F32[y][x])) {
+                    mask->data.PS_TYPE_MASK_DATA[y][x] |= blank;
+                    image->data.F32[y][x] = NAN;
+                    continue;
+                }
+                image->data.F32[y][x] *= exptime / (exptime + shutterImage->data.F32[y][x]);
+            }
+        }
+    }
+    psFree(shutterImage);
+
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now, used for reporting
+    psString timeString = psTimeToISO(time); // String with time
+    psFree(time);
+    psStringPrepend(&timeString, "Shutter correction completed at ");
+    psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK,
+                     timeString, "");
+    psFree(timeString);
+
+
+    return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+#define IMAGES_BUFFER 10                // Allocate space for this many images at a time
+
+static void shutterCorrectionDataFree(pmShutterCorrectionData *data)
+{
+    psFree(data->regions);
+    psFree(data->mean);
+    psFree(data->stdev);
+
+    psFree(data->exptimes);
+    psFree(data->refs);
+
+    return;
+}
+
+pmShutterCorrectionData *pmShutterCorrectionDataAlloc(int numCols, int numRows, int size)
+{
+    pmShutterCorrectionData *data = psAlloc(sizeof(pmShutterCorrectionData));
+    psMemSetDeallocator(data, (psFreeFunc)shutterCorrectionDataFree);
+
+    data->num = 0;
+    data->numCols = 0;
+    data->numRows = 0;
+
+    data->regions = psArrayAlloc(MEASURE_SAMPLES);
+    for (int j = 0; j < MEASURE_SAMPLES; j++) {
+        int x = (j % 2) ? size : numCols - size - 1;
+        int y = (j > 1) ? size : numRows - size - 1;
+        psRegion region = psRegionForSquare(x, y, size);
+        data->regions->data[j] = psRegionAlloc(region.x0, region.x1, region.y0, region.y1);
+    }
+
+    data->mean = psArrayAlloc(MEASURE_SAMPLES);
+    data->stdev = psArrayAlloc(MEASURE_SAMPLES);
+    for (int i = 0; i < MEASURE_SAMPLES; i++) {
+        data->mean->data[i] = psVectorAllocEmpty(IMAGES_BUFFER, PS_TYPE_F32);
+        data->stdev->data[i] = psVectorAllocEmpty(IMAGES_BUFFER, PS_TYPE_F32);
+    }
+
+    data->exptimes = psVectorAllocEmpty(IMAGES_BUFFER, PS_TYPE_F32);
+    data->refs = psVectorAllocEmpty(IMAGES_BUFFER, PS_TYPE_F32);
+
+    return data;
+}
+
+bool pmShutterCorrectionAddReadout(pmShutterCorrectionData *data,
+                                   const pmReadout *readout, ///< Readout to add
+                                   psStatsOptions meanStat, ///< Statistic to use for mean
+                                   psStatsOptions stdevStat, ///< Statistic to use for stdev
+                                   psMaskType maskVal, ///< Mask value
+                                   psRandom *rng ///< Random number generator
+    )
+{
+    PS_ASSERT_PTR_NON_NULL(data, NULL);
+    PS_ASSERT_PTR_NON_NULL(readout, NULL);
+    PS_ASSERT_IMAGE_NON_NULL(readout->image, NULL);
+    PS_ASSERT_IMAGE_TYPE(readout->image, PS_TYPE_F32, NULL);
+    if (data->num == 0) {
+        data->numCols = readout->image->numCols;
+        data->numRows = readout->image->numRows;
+    } else {
+        PS_ASSERT_IMAGE_SIZE(readout->image, data->numCols, data->numRows, NULL);
+    }
+    if (readout->mask) {
+        PS_ASSERT_IMAGE_NON_NULL(readout->mask, NULL);
+        PS_ASSERT_IMAGE_TYPE(readout->mask, PS_TYPE_MASK, NULL);
+        PS_ASSERT_IMAGE_SIZE(readout->mask, data->numCols, data->numRows, NULL);
+    }
+    if (readout->weight) {
+        PS_ASSERT_IMAGE_NON_NULL(readout->weight, NULL);
+        PS_ASSERT_IMAGE_TYPE(readout->weight, PS_TYPE_F32, NULL);
+        PS_ASSERT_IMAGE_SIZE(readout->weight, data->numCols, data->numRows, NULL);
+    }
+
+    // Add the exposure time
+    float exptime = psMetadataLookupF32(NULL, readout->parent->concepts, "CELL.EXPOSURE"); // Exp. time
+    if (!isfinite(exptime)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Exposure time is not set.");
+        return false;
+    }
+    data->exptimes->data.F32[data->exptimes->n] = exptime;
+    data->exptimes = psVectorExtend(data->exptimes, IMAGES_BUFFER, 1);
+
+    // Add the statistics
+
+    // Add the reference value
+    psStats *stats = psStatsAlloc(meanStat | stdevStat); // Statistics to apply
+    if (!rng) {
+        rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+    } else {
+        psMemIncrRefCounter(rng);
+    }
+    if (!psImageBackground(stats, NULL, readout->image, readout->mask, maskVal, rng)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to measure reference statistics.\n");
+        psFree(stats);
+        psFree(rng);
+        return false;
+    }
+    psFree(rng);
+    float refValue = psStatsGetValue(stats, meanStat); // Reference value
+    psTrace("psModules.detrend", 3, "Reference value & exptime for shutter image : %f cnts %f sec\n", refValue, exptime);
+    if (refValue <= 0.0) {
+        psError(PS_ERR_UNKNOWN, true, "Measured non-positive reference value.\n");
+        psFree(stats);
+        return false;
+    }
+    refValue = 1.0 / refValue;
+    data->refs->data.F32[data->refs->n] = refValue;
+    data->refs = psVectorExtend(data->refs, IMAGES_BUFFER, 1);
+
+    // Add the region statistics
+    for (int j = 0; j < MEASURE_SAMPLES; j++) {
+        psRegion *region = data->regions->data[j]; // Region of interest
+        psRegion adjusted = *region;    // Adjusted region, compensating for offsets
+        adjusted.x0 += readout->image->col0;
+        adjusted.x1 += readout->image->col0;
+        adjusted.y0 += readout->image->row0;
+        adjusted.y1 += readout->image->row0;
+        psImage *subImage = psImageSubset(readout->image, adjusted); // Sub-image
+        psImage *subMask = NULL;        // Sub-image of mask
+        if (readout->mask) {
+            subMask = psImageSubset(readout->mask, adjusted);
+        }
+        if (!psImageStats(stats, subImage, subMask, maskVal)) {
+            psString regionString = psRegionToString(adjusted);
+            psWarning("Unable to measure sample statistics at %s in image.\n",
+                      regionString);
+            psFree(regionString);
+        }
+        psFree(subImage);
+        psFree(subMask);
+
+        psVector *mean = data->mean->data[j]; // Vector of means for this region
+        psVector *stdev = data->stdev->data[j]; // Vector of standard deviations for this region
+
+        mean->data.F32[mean->n] = psStatsGetValue(stats, meanStat) * refValue;
+        stdev->data.F32[stdev->n] = psStatsGetValue(stats, stdevStat) * refValue;
+
+	psTrace("psModules.detrend", 5, "input shutter image sample value %d: %f +/- %f  ->  %f +/- %f\n", j,
+		psStatsGetValue(stats, meanStat), psStatsGetValue(stats, stdevStat),
+		mean->data.F32[mean->n], stdev->data.F32[stdev->n]);
+
+        data->mean->data[j] = psVectorExtend(mean, IMAGES_BUFFER, 1);
+        data->stdev->data[j] = psVectorExtend(stdev, IMAGES_BUFFER, 1);
+    }
+
+    data->num++;
+
+    return true;
+}
+
+float pmShutterCorrectionReference(pmShutterCorrectionData *data)
+{
+    PS_ASSERT_PTR_NON_NULL(data, NAN);
+    PS_ASSERT_INT_POSITIVE(data->num, NAN);
+
+    // supply counts sorted by exptime
+
+    // generate the index for the exptimes vector
+    psVector *index = psVectorSortIndex (NULL, data->exptimes);
+    psVector *newtimes = psVectorAlloc (data->exptimes->n, PS_TYPE_F32);
+
+    // reshuffle exptimes to new sequence (this is only a local value)
+    for (int j = 0; j < newtimes->n; j++) {
+	newtimes->data.F32[j] = data->exptimes->data.F32[index->data.S32[j]];
+    }
+
+    float meanRef = 0.0;                // Mean reference offset
+    int numGood = 0;                    // Number of good measurements
+    for (int i = 0; i < MEASURE_SAMPLES; i++) {
+	psVector *newcounts = psVectorAlloc (data->exptimes->n, PS_TYPE_F32);
+	psVector *newerrors = psVectorAlloc (data->exptimes->n, PS_TYPE_F32);
+	psVector *counts = data->mean->data[i];
+	psVector *errors = data->stdev->data[i];
+
+	for (int j = 0; j < newcounts->n; j++) {
+	    newcounts->data.F32[j] = counts->data.F32[index->data.S32[j]];
+	    newerrors->data.F32[j] = errors->data.F32[index->data.S32[j]];
+	}
+
+	// use the sorted exptime, counts, and errors for the measurements
+        pmShutterCorrection *guess = pmShutterCorrectionGuess(newtimes, newcounts); // Guess at correction
+	psTrace("psModules.detrend", 5, "Shutter correction guess: scale: %f, offset: %f, offref: %f\n", guess->scale, guess->offset, guess->offref);
+
+        pmShutterCorrection *corr = pmShutterCorrectionFullFit(newtimes, newcounts, newerrors, guess); // The actual correction
+	psTrace("psModules.detrend", 5, "Shutter correction fit: scale: %f, offset: %f, offref: %f\n", corr->scale, corr->offset, corr->offref);
+
+        if (corr && isfinite(corr->offref) && corr->valid) {
+            psTrace("psModules.detrend", 5, "Sample reference value: %f\n", corr->offref);
+            meanRef += corr->offref;
+            numGood++;
+        }
+
+        psFree(corr);
+        psFree(guess);
+	psFree (newcounts);
+	psFree (newerrors);
+    }
+    psFree (newtimes);
+    psFree (index);
+
+    if (numGood == 0) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to measure mean reference offset.\n");
+        return false;
+    }
+    meanRef /= (float)numGood;
+    psTrace("psModules.detrend", 3, "Mean reference value: %f\n", meanRef);
+    return meanRef;
+}
+
+bool pmShutterCorrectionGenerate(pmReadout *shutter, pmReadout *pattern, const psArray *inputs,
+                                 float reference, const pmShutterCorrectionData *data,
+                                 int nIter, float rej, psMaskType maskVal)
+{
+    PS_ASSERT_PTR_NON_NULL(shutter, false);
+    PS_ASSERT_ARRAY_NON_NULL(inputs, false);
+    PS_ASSERT_INT_EQUAL(data->num, inputs->n, false);
+    PS_ASSERT_INT_NONNEGATIVE(nIter, false);
+    PS_ASSERT_FLOAT_LARGER_THAN(rej, 0.0, false);
+
+    int minInputCols, maxInputCols, minInputRows, maxInputRows; // Smallest and largest values to combine
+    int xSize, ySize;                   // Size of the output image
+    if (!pmReadoutStackValidate(&minInputCols, &maxInputCols, &minInputRows, &maxInputRows, &xSize, &ySize,
+                                inputs)) {
+        psError(PS_ERR_UNKNOWN, false, "No valid input readouts.");
+        return false;
+    }
+
+    pmReadoutUpdateSize(shutter, minInputCols, minInputRows, xSize, ySize, false, false, maskVal);
+    if (pattern) {
+        pmReadoutUpdateSize(pattern, minInputCols, minInputRows, xSize, ySize, false, false, maskVal);
+    }
+
+    psImage *nums = pmReadoutAnalysisImage(shutter, PM_READOUT_STACK_ANALYSIS_COUNT, xSize, ySize,
+                                           PS_TYPE_U16, 0); // Image with number fitted per pixel
+    if (!nums) {
+        return false;
+    }
+    psImage *sigma = pmReadoutAnalysisImage(shutter, PM_READOUT_STACK_ANALYSIS_SIGMA, xSize, ySize,
+                                            PS_TYPE_F32, NAN); // Image with stdev per pixel
+    if (!sigma) {
+        psFree(nums);
+        return false;
+    }
+
+    psImage *shutterImage = shutter->image; // Shutter correction image
+    psImage *patternImage; // Illumination pattern
+    if (pattern) {
+        patternImage = psMemIncrRefCounter(pattern->image);
+    } else {
+        patternImage = psImageAlloc(xSize, ySize, PS_TYPE_F32);
+    }
+
+    int num = data->num;                // Number of images
+    psVector *counts = psVectorAlloc(num, PS_TYPE_F32); // Counts in each image
+    psVector *errors = psVectorAlloc(num, PS_TYPE_F32); // Counts in each image
+    psVector *mask = psVectorAlloc(num, PS_TYPE_MASK); // Mask for each image
+    psTrace("psModules.detrend", 2, "Performing linear fit on individual pixels...\n");
+    for (int i = minInputRows; i < maxInputRows; i++) {
+        int yOut = i - shutter->row0; // y position on output readout
+        for (int j = minInputCols; j < maxInputCols; j++) {
+            int xOut = j - shutter->col0; // x position on output readout
+
+            psVectorInit(mask, 0);
+            for (int r = 0; r < num; r++) {
+                pmReadout *readout = inputs->data[r]; // Readout of interest
+                int yIn = i - readout->row0; // y position on input readout
+                int xIn = j - readout->col0; // x position on input readout
+                psImage *image = readout->image; // Image of interest
+                float ref = data->refs->data.F32[r]; // (Inverse) reference value
+                counts->data.F32[r] = image->data.F32[yIn][xIn] * ref;
+                if (readout->mask) {
+                    mask->data.PS_TYPE_MASK_DATA[r] = readout->mask->data.PS_TYPE_MASK_DATA[yIn][xIn];
+                }
+                if (readout->weight) {
+                    errors->data.F32[r] = sqrtf(readout->weight->data.F32[yIn][xIn]) * ref;
+                } else {
+                    errors->data.F32[r] = sqrtf(image->data.F32[yIn][xIn]) * ref;
+                }
+            }
+
+            pmShutterCorrection *corr = pmShutterCorrectionLinFit(data->exptimes, counts, errors, mask,
+                                                                  reference, nIter, rej, maskVal);
+            if (!corr) {
+                // Nothing we can do about it
+                psErrorClear();
+                shutterImage->data.F32[yOut][xOut] = NAN;
+                patternImage->data.F32[yOut][xOut] = NAN;
+                nums->data.U16[yOut][xOut] = 0;
+                sigma->data.F32[yOut][xOut] = NAN;
+                continue;
+            }
+            shutterImage->data.F32[yOut][xOut] = corr->offset;
+            patternImage->data.F32[yOut][xOut] = corr->scale;
+            nums->data.U16[yOut][xOut] = corr->num;
+            sigma->data.F32[yOut][xOut] = corr->stdev;
+            psFree(corr);
+        }
+    }
+    psFree(mask);
+    psFree(errors);
+    psFree(counts);
+    psFree(nums);
+    psFree(sigma);
+
+    // Update the "concepts"
+    psList *inputCells = psListAlloc(NULL); // List of cells
+    for (long i = 0; i < inputs->n; i++) {
+        pmReadout *readout = inputs->data[i]; // Readout of interest
+        psListAdd(inputCells, PS_LIST_TAIL, readout->parent);
+    }
+    bool success = pmConceptsAverageCells(shutter->parent, inputCells, NULL, NULL, true);
+    psFree(inputCells);
+
+    // Correct the exposure times --- they don't make sense any more.
+    psMetadataItem *item = psMetadataLookup(shutter->parent->concepts, "CELL.EXPOSURE");
+    item->data.F32 = NAN;
+    item = psMetadataLookup(shutter->parent->concepts, "CELL.DARKTIME");
+    item->data.F32 = NAN;
+
+    shutter->data_exists = true;
+    shutter->parent->data_exists = true;
+    shutter->parent->parent->data_exists = true;
+
+    if (pattern) {
+        pattern->data_exists = true;
+        pattern->parent->data_exists = true;
+        pattern->parent->parent->data_exists = true;
+    }
+
+    return success;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmShutterCorrection.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmShutterCorrection.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmShutterCorrection.h	(revision 22158)
@@ -0,0 +1,194 @@
+/* @file pmShutterCorrection.h
+ * @brief Functions to build and apply a shutter exposure-time correction.
+ *
+ * @author Eugene Magnier, IfA
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-06-09 00:39:37 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_SHUTTER_CORRECTION_H
+#define PM_SHUTTER_CORRECTION_H
+
+/// @addtogroup detrend Detrend Creation and Application
+/// @{
+
+/*  A mechanical shutter may not yield uniform exposure times as a function of position on the
+ *  detector.  The typical error consists of a constant exposure-time offset relative to the
+ *  requested value, ie exposure time is T_o + dT(x,y).  The exposure error, dT, may be
+ *  measured with the following scheme.  Obtain a set of exposures with different exposures
+ *  times taken of the same flat-field source; the source must be spatially stable between the
+ *  exposures, but need not have a stable amplitude.  For an illuminating flux of intensity
+ *  F(x,y) = F_o f(x,y), the signal recorded by any pixel in the detector is given by: S(t,x,y)
+ *  = F_o(t) f(x,y) (T_o + dT(x,y)) where F_o(t) is the (variable) overall intensity of the
+ *  illuminating source and f(x,y) is the spatial illumination pattern times the flat-field
+ *  response.  Choose a reference location in the image (eg, the detector center) and divide by
+ *  the value of that region (ie, mean or median):
+ *
+ *  s(t,x,y) = S(t,x,y) / S(t,0,0)
+ *  s(t,x,y) = F_o(t) f(x,y) (T_o + dT(x,y)) / F_o(t) f(0,0) (T_o + dT(0,0))
+ *  s(t,x,y) = f(x,y) (T_o + dT(x,y)) / f(0,0) (T_o + dT(0,0))
+ *
+ *  we can absorb the term f(0,0) into f(x,y) as we have no motivation for the scale of f(x,y)
+ *  -- a normalization for the flat-field is not specified here.  For any single pixel, over
+ *  the set of exposures, we thus need to solve for dT(x,y), dT(0,0), and f'(x,y) in the
+ *  equation: s(t,x,y) = f'(x,y) (T_o + dT(x,y)) / (T_o + dT(0,0))
+ *
+ *  we avoid directly fitting these values as the process would be a non-linear
+ *  least-squares problem for every pixel in the image, and thus very time
+ *  consuming.  There are linear options which may be used instead.
+ *  First, as T_o goes to a large value, s() approaches the value of f'(x,y).
+ *  Next, as T_o goes to a very small value, s() approaches the value of
+ *  f'(x,y)*dT(x,y)/dT(0,0).  Finally, when s() has the value of
+ *  f'(x,y)*(1 + dT(x,y)/dT(0,0))/2, T_o has the value of dT(0,0).  with data
+ *  points covering a reasonable dynamic range, we can solve for these three
+ *  values by interpolation and/or extrapolation.
+ *
+ *  To take the strategy one step further, we could use the above recipe to
+ *  obtain a guess for the three parameters and then apply non-linear fitting to
+ *  solve more accurately for the parameters.  If we limit this operation to a
+ *  handful of positions in the image (user defined, but the obvious choice would
+ *  be positions near the center, edges, and corners), then we may determine a
+ *  good value for dT(0,0).  Since there is only one dT(0,0) for the image, we
+ *  can apply the resulting measurement to the rest of the pixels in the image.
+ *  If dT(0,0) is not a free parameter, then the fitting process is linear in
+ *  terms of dT(x,y) and f'(x,y)
+ */
+
+/// Shutter correction parameters, applicable for a single pixel
+typedef struct {
+    double scale;                       ///< The normalisation for an exposure, A(k) or f'(x,y) 
+    double offset;                      ///< The time offset, dTk
+    double offref;                      ///< The reference time offset, dTo
+    int num;                            ///< Number of points used
+    float stdev;                        ///< Standard deviation
+    bool valid;				// is the fitted shutter correction valid (produce a significant improvement?)
+} pmShutterCorrection;
+
+/// Allocator for shutter correction parameters
+pmShutterCorrection *pmShutterCorrectionAlloc();
+
+/// Guess a shutter correction, based on plot of counts vs exposure time
+///
+/// This function is used before doing the full non-linear fit, to get parameters close to the true.  Assumes
+/// exptime vector is sorted (ascending order; longest is last) prior to input.
+pmShutterCorrection *pmShutterCorrectionGuess(
+    const psVector *exptime,            ///< Exposure times for each exposure
+    const psVector *counts              ///< Counts for each exposure
+    );
+
+/// Generate shutter correction based on a linear fit
+///
+/// Performs a linear fit to counts as a function of exposure time, with the reference time offset fixed (so
+/// that the system is linear).  Performs iterative clipping, if nIter > 1.
+pmShutterCorrection *pmShutterCorrectionLinFit(
+    const psVector *exptime,            ///< Exposure times for each exposure
+    const psVector *counts,             ///< Counts for each exposure
+    const psVector *cntError,           ///< Error in the counts
+    const psVector *mask,               ///< Mask for each exposure
+    float offref,                       ///< Reference time offset
+    int nIter,                          ///< Number of iterations
+    float rej,                          ///< Rejection threshold (sigma)
+    psMaskType maskVal                  ///< Mask value
+    );
+
+/// Generate shutter correction based on a full non-linear fit
+///
+/// Performs a full non-linear fit to counts as a function of exposure time.  The main purpose is to solve for
+/// the reference time offset, so that future fits may be performed using linear fitting with the reference
+/// time offset fixed.
+pmShutterCorrection *pmShutterCorrectionFullFit(
+    const psVector *exptime,            ///< Exposure times for each exposure
+    const psVector *counts,             ///< Counts for each exposure
+    const psVector *cntError,           ///< Error in the counts
+    const pmShutterCorrection *guess    ///< Initial guess
+    );
+
+/// Measure a shutter correction image from an array of images
+///
+/// Given an array of readouts (with known exposure times from the cell concepts), this function measures the
+/// shutter correction (our principal concern is for the time offset, rather than the normalisation) by
+/// measuring the reference time offset using the full non-linear fit for a small number of representative
+/// regions (middle and corners), and then using that to perform a linear fit to each pixel.
+bool pmShutterCorrectionMeasure(
+    pmReadout *output,                  ///< Output readout
+    const psArray *readouts,            ///< Array of readouts
+    int size,                           ///< Size of samples for statistics for non-linear fit
+    psStatsOptions meanStat,            ///< Statistic to use for mean
+    psStatsOptions stdevStat,           ///< Statistic to use for stdev
+    int nIter,                          ///< Number of iterations
+    float rej,                          ///< Rejection threshold (sigma)
+    psMaskType maskVal                  ///< Mask value
+    );
+
+/// Apply a shutter correction
+///
+/// Given a shutter correction (with dT for each pixel), applies this correction to an input image.
+bool pmShutterCorrectionApply(
+    pmReadout *readout,                 ///< Readout to which to apply shutter correction
+    const pmReadout *shutter,           ///< Shutter correction readout, with dT for each pixel
+    psMaskType blank                    ///< Value to give blank pixels
+    );
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Functions for doing the shutter correction piece-meal (don't have to read entire image stack into memory at
+// once).  A single read run through the stack is required, calling pmShutterCorrectionAddReadout on each.
+// Then pmShutterCorrectionReference provides the required reference shutter time, so that
+// pmShutterCorrectionGenerate can generate a shutter correction piece by piece as overlapping pixels from
+// each input are read in.
+
+
+/// Data for measuring the shutter correction
+typedef struct {
+    int num;                            ///< Number of images
+    int numCols, numRows;               ///< Size of images
+    psArray *regions;                   ///< Regions at which to measure statistics
+    psArray *mean;                      ///< Vector of means at each region
+    psArray *stdev;                     ///< Vector of standard deviations at each region
+    psVector *exptimes;                 ///< Exposure times for each image
+    psVector *refs;                     ///< Reference fluxes
+} pmShutterCorrectionData;
+
+/// Allocator for pmShutterCorrectionData
+pmShutterCorrectionData *pmShutterCorrectionDataAlloc(int numCols, int numRows, ///< Size of images
+                                                      int size ///< Size of regions
+    );
+
+/// Add a readout to the correction data
+///
+/// Performs statistics on the readout, recording the data
+bool pmShutterCorrectionAddReadout(
+    pmShutterCorrectionData *data,      ///< Correction data
+    const pmReadout *readout,           ///< Readout to add
+    psStatsOptions meanStat,            ///< Statistic to use for mean
+    psStatsOptions stdevStat,           ///< Statistic to use for stdev
+    psMaskType maskVal,                 ///< Mask value
+    psRandom *rng                       ///< Random number generator
+    );
+
+/// Calculate the reference shutter time from the correction data
+float pmShutterCorrectionReference(
+    pmShutterCorrectionData *data ///< Correction data
+    );
+
+/// Generate a shutter correction
+///
+/// Performs the linear fit to each pixel in the stack.
+bool pmShutterCorrectionGenerate(
+    pmReadout *shutter,                 ///< Shutter correction
+    pmReadout *pattern,                 ///< Background pattern (or NULL)
+    const psArray *inputs,              ///< Stack of input pmReadouts
+    float reference,                    ///< Reference shutter time (from pmShutterCorrectionRef)
+    const pmShutterCorrectionData *data, ///< Correction data
+    int nIter,                          ///< Number of iterations
+    float rej,                          ///< Rejection threshold (sigma)
+    psMaskType maskVal                  ///< Mask value
+    );
+
+
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmSkySubtract.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmSkySubtract.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmSkySubtract.c	(revision 22158)
@@ -0,0 +1,738 @@
+/** @file  pmSubtractSky.c
+ *
+ *  This file will contain a module which will create a model of the
+ *  background sky and subtract that from the input image.
+ *
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-04-04 22:42:48 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmSubtractSky.h"
+
+// XXX: Get rid of the.  Create pmUtils.h
+psImage *p_psDetermineTrimmedImage(
+    pmReadout *in
+);
+
+/******************************************************************************
+DetermineNumBits(data): This routine takes an enum psStatsOptions as an
+argument and returns the number of non-zero bits.
+
+XXX: This code is duplicated in the ReadoutCombine file.
+ *****************************************************************************/
+static psS32 DetermineNumBits(psStatsOptions data)
+{
+    psTrace("psModules.detrend", 4, "Calling DetermineNumBits(0x%x)\n", data);
+
+    psS32 i;
+    psU64 tmpData = data;
+    psS32 numBits = 0;
+
+    for (i=0;i<(8 * sizeof(psStatsOptions));i++) {
+        if (0x0001 & tmpData) {
+            numBits++;
+        }
+        tmpData = tmpData >> 1;
+    }
+
+    psTrace("psModules.detrend", 4,
+            "Calling DetermineNumBits(0x%x) -> %d\n", data, numBits);
+    return(numBits);
+}
+
+/******************************************************************************
+getHighestPriorityStatOption(statOptions): this routine takes as input a
+psStats->options with multiple options set and returns one with a single
+option set according to the precedence set in the SDRS.
+ *****************************************************************************/
+static psU64 getHighestPriorityStatOption(psU64 statOptions)
+{
+    psTrace("psModules.detrend", 4,
+            "Calling getHighestPriorityStatOption(0x%x)\n", statOptions);
+
+    if (statOptions & PS_STAT_SAMPLE_MEAN) {
+        return(PS_STAT_SAMPLE_MEAN);
+    } else if (statOptions & PS_STAT_SAMPLE_MEDIAN) {
+        return(PS_STAT_SAMPLE_MEDIAN);
+    } else if (statOptions & PS_STAT_CLIPPED_MEAN) {
+        return(PS_STAT_CLIPPED_MEAN);
+    } else if (statOptions & PS_STAT_FITTED_MEAN) {
+        return(PS_STAT_FITTED_MEAN);
+    } else if (statOptions & PS_STAT_ROBUST_MEDIAN) {
+        return(PS_STAT_ROBUST_MEDIAN);
+    }
+    psError(PS_ERR_UNKNOWN, true, "Unallowable option requested for statistically binning image pixels.\n");
+    return(-1);
+    // XXX
+    //else if (statOptions & PS_STAT_ROBUST_MODE) {
+    //    return(PS_STAT_ROBUST_MODE);
+    //}
+}
+
+/******************************************************************************
+psImage *binImage(origImage, binFactor, statOptions): This routine takes an
+input psImage and scales it smaller by a factor of binFactor.  The statistic
+used in combining input pixels is specified in statOptions.
+
+XXX: use static vectors for myStats, binVector and binMask.
+XXX: I coded this before I was aware of a psLib reBin function.  I don't
+use this function in this module.  I'm keeping it here in the event that
+requirements change and we might need a custom reBin function.
+ *****************************************************************************/
+#if 0
+static psImage *binImage(psImage *origImage,
+                         int binFactor,
+                         psStatsOptions statOptions)
+{
+    psTrace("psModules.detrend", 4, "Calling binImage(%d)\n", binFactor);
+
+    if (binFactor <= 0) {
+        psLogMsg(__func__, PS_LOG_WARN,
+                 "WARNING: binImage(): binFactor is %d\n", binFactor);
+        return(origImage);
+    }
+    if (binFactor == 1) {
+        return(origImage);
+    }
+
+    psVector *binVector = psVectorAlloc(binFactor * binFactor, PS_TYPE_F32);
+    psVector *binMask = psVectorAlloc(binFactor * binFactor, PS_TYPE_U8);
+    psStats *myStats = psStatsAlloc(statOptions);
+
+    for (psS32 row = 0; row < origImage->numRows ; row+=binFactor) {
+        for (psS32 col = 0; col < origImage->numCols ; col+=binFactor) {
+            psS32 count = 0;
+            for (psS32 binRow = 0; binRow <= binFactor ; binRow++) {
+                for (psS32 binCol = 0; binCol <= binFactor ; binCol++) {
+                    if (((row + binRow) < origImage->numRows) &&
+                            ((col + binCol) < origImage->numCols)) {
+                        binVector->data.F32[count] =
+                            origImage->data.F32[row + binRow][col + binCol];
+                        binMask->data.U8[count] = 0;
+                    } else {
+                        binVector->data.F32[count] = 0.0;
+                        binMask->data.U8[count] = 1;
+                    }
+                    count++;
+                }
+            }
+            psStats *rc1 = psVectorStats(myStats, binVector, NULL, binMask, 1);
+            if (rc1 == NULL) {
+                psError(PS_ERR_UNKNOWN, false, "psVectorStats(): could not perform requested statistical operation.  Returning in image.\n");
+                return(origImage);
+            }
+            psF64 statValue;
+            psBool rc = p_psGetStatValue(rc1, &statValue);
+
+            if (rc == true) {
+                origImage->data.F32[row][col] = (psF32) statValue;
+            } else {
+                origImage->data.F32[row][col] = 0.0;
+                psLogMsg(__func__, PS_LOG_WARN,
+                         "WARNING: pmSubtractSky(), binImage(): p_psGetStatValue() was FALSE\n");
+            }
+        }
+    }
+    psFree(binVector);
+    psFree(binMask);
+    psFree(myStats);
+
+    psTrace("psModules.detrend", 4, "Exiting binImage(%d)\n", binFactor);
+    return(origImage);
+}
+#endif
+
+/******************************************************************************
+CalculatePolyTerms(xOrder, yOrder): this routine will calculate the number of
+coefficients (or terms) in a 2-D polynomial of order (xOrder, yOrder).
+
+XXX: Use your brain and figure out the analytical expression.
+
+XXX: Why isn't it simply (xOrder+1) * (yOrder+1)?
+ *****************************************************************************/
+static psS32 CalculatePolyTerms(psS32 xOrder, psS32 yOrder)
+{
+    psTrace("psModules.detrend", 4,
+            "Calling CalculatePolyTerms(%d, %d)\n", xOrder, yOrder);
+
+    psS32 maxOrder = PS_MAX(xOrder, yOrder);
+    psS32 localPolyTerms = 0;
+    psS32 order = 0;
+    psS32 num=0;
+
+    for (order=0;order<=maxOrder;order++) {
+        for (num=0;num<=order;num++) {
+            if (((order-num) <= xOrder) && (num <= yOrder)) {
+                localPolyTerms++;
+            }
+        }
+    }
+    psTrace("psModules.detrend", 4,
+            "Exiting CalculatePolyTerms(%d, %d) -> %d\n", xOrder, yOrder, localPolyTerms);
+    return(localPolyTerms);
+
+    //    return((xOrder+1) * (yOrder+1));
+}
+
+/******************************************************************************
+buildPolyTerms(): this routine computes a 2-D array polyTerms[][] that holds
+terms for the polynomial that is used to model the sky background.  We use
+this array primarily for convenience in computations involving sky model
+polynomials.  It is defined as:
+    polyTerms[i][0] = the power to which X is raised in the i-th term of in an
+    poly-order sky background polynomial.
+
+    polyTerms[i][1] = the power to which Y is raised in the i-th term of in an
+    poly-order sky background polynomial.
+ *****************************************************************************/
+static psS32 **buildPolyTerms(psS32 xOrder, psS32 yOrder)
+{
+    psTrace("psModules.detrend", 4,
+            "Calling buildPolyTerms(%d, %d)\n", xOrder, yOrder);
+
+    psS32 i=0;
+    psS32 order = 0;
+    psS32 num=0;
+    psS32 localPolyTerms = CalculatePolyTerms(xOrder, yOrder);
+    psS32 maxOrder = PS_MAX(xOrder, yOrder);
+
+    // Create the data structure which we hold the xy order of each coeff.
+    psS32 **polyTerms = (psS32 **) psAlloc(localPolyTerms * sizeof(psS32 *));
+    for (i=0; i < localPolyTerms ; i++) {
+        polyTerms[i] = (psS32 *) psAlloc(2 * sizeof(psS32));
+    }
+
+    i=0;
+    // This code segment loops through each term i in the polynomial and
+    // calculates the power to which x/y are raised in that i-th term.
+    // We first do the 0-order terms, then the 1-order terms, etc.
+    for (order=0;order<=maxOrder;order++) {
+        for (num=0;num<=order;num++) {
+            if (((order-num) <= xOrder) && (num <= yOrder)) {
+                polyTerms[i][0] = order-num;
+                polyTerms[i][1] = num;
+                i++;
+            }
+        }
+    }
+
+    if (psTraceGetLevel("psModules.detrend") >= 10) {
+        for (i=0; i < localPolyTerms ; i++) {
+            printf("x^%d * y^%d\n", polyTerms[i][0], polyTerms[i][1]);
+        }
+    }
+
+    psTrace("psModules.detrend", 4,
+            "Exiting buildPolyTerms(%d, %d)\n", xOrder, yOrder);
+    return(polyTerms);
+}
+
+/******************************************************************************
+This procedure calculates various combinations of powers of x and y and stores
+them in the data structure p_psPolySums[][].  After it completes:
+
+    p_psPolySums[i][j] == x^i * y^j
+
+XXX: Use a psImage for the p_psPolySums data structure?
+XXX: p_psPolySums: should this be a global?  Did you get the storage classifier
+     and name correct?
+XXX: Use variable size arrays for p_psPolySums[][].
+XXX: Must initialize p_psPolySums[][]?
+ *****************************************************************************/
+#define PS_MAX_POLYNOMIAL_ORDER 20
+
+psF64 p_psPolySums[PS_MAX_POLYNOMIAL_ORDER+1][PS_MAX_POLYNOMIAL_ORDER+1];
+static void buildSums(psF64 x,
+                      psF64 y,
+                      psS32 xOrder,
+                      psS32 yOrder)
+{
+    psTrace("psModules.detrend", 4,
+            "Calling buildPolyTerms(%d, %d)\n", xOrder, yOrder);
+
+    psS32 i = 0;
+    psS32 j = 0;
+    psF64 xSum = 0.0;
+    psF64 ySum = 0.0;
+
+    xSum = 1.0;
+    ySum = 1.0;
+    for(i=0;i<=xOrder;i++) {
+        ySum = xSum;
+        for(j=0;j<=yOrder;j++) {
+            p_psPolySums[i][j] = ySum;
+            ySum*= y;
+        }
+        xSum*= x;
+    }
+    psTrace("psModules.detrend", 4,
+            "Exiting buildPolyTerms(%d, %d)\n", xOrder, yOrder);
+}
+
+/******************************************************************************
+ImageFitPolynomial(myPoly, dataImage, maskImage): this private routine takes
+an input image along with a mask and fits a polynomial to it.  The degree of
+the polynomial is specified by input parameter myPoly, and need not be
+symmetrical in orders of X and Y.  The polynomial must be type
+PS_POLYNOMIAL_ORD.  If there are not enough rows or columns in the input image
+for the order of the polynomial, then that order is reduced.  The algorithm
+used in this routine is based on that of the pilot project ADD, but is not
+documented anywhere.
+
+XXX: Different trace message facilities in use here.
+ *****************************************************************************/
+static psPolynomial2D *ImageFitPolynomial(
+    psPolynomial2D *myPoly,
+    psImage *dataImage,
+    psImage *maskImage)
+{
+    psTrace("psModules.detrend", 4,
+            "Calling ImageFitPolynomial()\n");
+    PS_ASSERT_POLY_NON_NULL(myPoly, NULL);
+    PS_ASSERT_POLY_TYPE(myPoly, PS_POLYNOMIAL_ORD, NULL);
+    PS_ASSERT_IMAGE_NON_NULL(dataImage, NULL);
+    PS_ASSERT_IMAGE_NON_EMPTY(dataImage, NULL);
+    PS_ASSERT_IMAGE_TYPE(dataImage, PS_TYPE_F32, NULL);
+    PS_ASSERT_IMAGE_NON_NULL(maskImage, NULL);
+    PS_ASSERT_IMAGE_NON_EMPTY(maskImage, NULL);
+    PS_ASSERT_IMAGE_TYPE(maskImage, PS_TYPE_U8, NULL);
+    PS_ASSERT_IMAGES_SIZE_EQUAL(dataImage, maskImage, NULL);
+    psS32 oldPolyX = -1;
+    psS32 oldPolyY = -1;
+
+    // The matrix equations become singular if there are more powers of X
+    // in myPoly then there are rows of the image.  I think.  Similarly for
+    // powers of Y and columns.  So.  Here we reduce the complexity of the
+    // polynomial if there are not enough rows/columns in the input image.
+
+    if ((myPoly->nX + 1) > dataImage->numRows) {
+        psLogMsg(__func__, PS_LOG_WARN,
+                 "WARNING: ImageFitPolynomial(): Reducing polynomial complexity in x-dimension.\n");
+        oldPolyX = myPoly->nX;
+        myPoly->nX = dataImage->numRows - 1;
+    }
+    if ((myPoly->nY + 1) > dataImage->numCols) {
+        psLogMsg(__func__, PS_LOG_WARN,
+                 "WARNING: ImageFitPolynomial(): Reducing polynomial complexity in y-dimension.\n");
+        oldPolyY = myPoly->nY;
+        myPoly->nY = dataImage->numCols - 1;
+    }
+    psS32 i;
+    psS32 j;
+    psS32 x;
+    psS32 y;
+    psS32 aRow;
+    psS32 aCol;
+    psS32 **polyTerms = buildPolyTerms(myPoly->nX, myPoly->nY);
+    // We determine how many coefficients will be in the polynomial that we
+    // are fitting to this image.
+    psS32 localPolyTerms = CalculatePolyTerms(myPoly->nX, myPoly->nY);
+    psImage *A = psImageAlloc(localPolyTerms, localPolyTerms, PS_TYPE_F64);
+    psImage *Aout = psImageAlloc(localPolyTerms, localPolyTerms, PS_TYPE_F64);
+    psVector *B = psVectorAlloc(localPolyTerms, PS_TYPE_F64);
+    psVector *outPerm = NULL;
+
+    //
+    // Initialize A matrix and B vector.
+    //
+    psImageInit(A, 0.0);
+    psVectorInit(B, 0.0);
+
+    //
+    // We build the A matrix and B vector.
+    //
+    for (x=0;x<dataImage->numRows;x++) {
+        for (y=0;y<dataImage->numCols;y++) {
+            if (maskImage->data.U8[x][y] == 0) {
+                buildSums((psF64) x, (psF64) y, myPoly->nX, myPoly->nY);
+
+                /************************************************************
+                This code dervies from equation (7) of the pilot ADD.  However,
+                it is not exactly the same in that the order of the polynomial
+                may be different in X And Y.
+
+                Equation (7) from the pilot ADD describes 16 linear equations.
+                The i-th equation is simply the partial derivative of the
+                sky background polynomial (1) w.r.t. to the i-th term in
+                that polynomial.  The i-th equation is stored in row i of
+                matrix A[][] (matrix A[][] has origin (1,1), not (0,0)).  To
+                compute A[i][j] we simply multiply the j-th term of the Sky
+                Background Polynomial (SBP) by the i-th term of SBP.
+                ************************************************************/
+                for (aRow=0;aRow<localPolyTerms;aRow++) {
+                    for (aCol=0;aCol<localPolyTerms;aCol++) {
+                        A->data.F64[aRow][aCol]+=
+                            (p_psPolySums[ polyTerms[aCol][0] ][ polyTerms[aCol][1] ] *
+                             p_psPolySums[ polyTerms[aRow][0] ][ polyTerms[aRow][1] ]);
+                    }
+                }
+                // Build the B[] vector, which is the right-hand side of (7).
+                for (i=0;i<localPolyTerms;i++) {
+                    B->data.F64[i]+= dataImage->data.F32[x][y] *
+                                     p_psPolySums[ polyTerms[i][0] ][ polyTerms[i][1] ];
+                }
+            }
+        }
+    }
+
+    if (psTraceGetLevel(".psModule.pmSubtractSky.ImageFitPolynomial") >= 8) {
+        for (aRow=0;aRow<localPolyTerms;aRow++) {
+            for (aCol=0;aCol<localPolyTerms;aCol++) {
+                printf("A[%d][%d] is %f\n", aRow, aCol,
+                       A->data.F64[aRow][aCol]);
+            }
+        }
+
+        for (i=0;i<=localPolyTerms;i++) {
+            printf("B[%d] is %f\n", i, B->data.F64[i]);
+        }
+    }
+
+    //
+    // Solve the matrix equations for the polynomial coefficients C.
+    // XXX: How do we know if these matrix operations were successful?
+    //
+    Aout = psMatrixLUD(Aout, &outPerm, A);
+    PS_ASSERT_IMAGE_NON_NULL(Aout, NULL);
+    PS_ASSERT_IMAGE_NON_EMPTY(Aout, NULL);
+    psVector *C = psVectorAlloc(localPolyTerms, PS_TYPE_F64);
+    psMatrixLUSolve(C, Aout, B, outPerm);
+
+    //
+    // Set the appropriate coefficients in the myPoly structure.
+    //
+    for (i=0;i<localPolyTerms;i++) {
+        myPoly->coeff[ polyTerms[i][0] ][ polyTerms[i][1] ] = C->data.F64[i];
+        psTrace("psModules.detrend", 6,
+                "myPoly->coeff[%d][%d] is %f\n", polyTerms[i][0], polyTerms[i][1], myPoly->coeff[ polyTerms[i][0] ][ polyTerms[i][1] ]);
+    }
+
+    //
+    // Free data structures that were allocated in this module.
+    //
+    for (i=0;i<localPolyTerms;i++) {
+        psFree(polyTerms[i]);
+    }
+    psFree(polyTerms);
+    psFree(A);
+    psFree(Aout);
+    psFree(B);
+    psFree(C);
+    psFree(outPerm);
+
+    //
+    // We restore the original size of the polynomial and set remaining
+    // coefficients to 0.0, if necessary.
+    //
+    // XXX: Verify this works after poly nOrder/nTerm change.
+    //
+    if (oldPolyX != -1) {
+        myPoly->nX = oldPolyX;
+        for (i=oldPolyX ; i < (1 + myPoly->nX) ; i++) {
+            for (j=0;j<(1 + myPoly->nY) ; j++) {
+                myPoly->coeff[i][j] = 0.0;
+            }
+        }
+    }
+    if (oldPolyY != -1) {
+        myPoly->nY = oldPolyY;
+        for (i=0 ; i < (1 + myPoly->nX) ; i++) {
+            for (j=oldPolyY;j < (1 + myPoly->nY) ; j++) {
+                myPoly->coeff[i][j] = 0.0;
+            }
+        }
+    }
+
+    psTrace("psModules.detrend", 4,
+            "Exiting ImageFitPolynomial()\n");
+    //    psTrace("psModules.detrend", 4,
+    //            "---- ImageFitPolynomial() end successfully ----\n");
+    return(myPoly);
+}
+
+
+/******************************************************************************
+pmReadout pmSubtractSky():
+
+XXX: use static vectors for myStats, and the binned image
+
+XXX: The SDR is silent about types.  PS_TYPE_F32 is implemented here.
+
+XXX: Sync the psTrace message facilities.
+ *****************************************************************************/
+pmReadout *pmSubtractSky(pmReadout *in,
+                         void *fitSpec,
+                         psFit fit,
+                         psS32 binFactor,
+                         psStats *stats,
+                         psF32 clipSD)
+{
+    PS_ASSERT_READOUT_NON_NULL(in, NULL);
+    PS_ASSERT_READOUT_NON_EMPTY(in, NULL);
+    PS_ASSERT_READOUT_TYPE(in, PS_TYPE_F32, NULL);
+    PS_WARN_PTR_NON_NULL(in->parent);
+    if (in->parent != NULL) {
+        PS_WARN_PTR_NON_NULL(in->parent->concepts);
+    }
+    psTrace("psModules.detrend", 4,
+            "---- pmSubtractSky() begin ----\n");
+
+    if ((fit != PM_FIT_NONE) &&
+            (fit != PM_FIT_POLYNOMIAL) &&
+            (fit != PM_FIT_SPLINE)) {
+        psError(PS_ERR_UNKNOWN, true, "psFit is unallowable (%d).  Returning in image.\n", fit);
+        return(in);
+    }
+
+    psStatsOptions statOptions = 0;
+
+    //
+    // Return the original input readout if the fit specs are poorly defined.
+    // No warning or error messages should be generated.
+    //
+    if ((fitSpec == NULL) ||
+            ((fit == PM_FIT_NONE) || (fit == PM_FIT_SPLINE))) {
+        //        psLogMsg(__func__, PS_LOG_WARN, "Fit specs are poorly defined.  Returning in image.\n");
+        return(in);
+    }
+
+    //
+    // Determine trimmed image from metadata.
+    //
+
+    psImage *trimmedImg = p_psDetermineTrimmedImage(in);
+    psImage *binnedImage = NULL;
+    psPolynomial2D *myPoly = NULL;
+    psImage *binnedMaskImage = NULL;
+    psU32 oldStatOptions = 0;
+
+    //
+    // Determine which statistic to use when binning pixels, if any.
+    //
+    if (stats != NULL) {
+        statOptions = stats->options;
+        if (1 < DetermineNumBits(statOptions)) {
+            psLogMsg(__func__, PS_LOG_WARN, "WARNING: Multiple statistical options have been requested.\n");
+            statOptions = getHighestPriorityStatOption(statOptions);
+            if (statOptions == -1) {
+                psError(PS_ERR_UNKNOWN, true, "Not allowable stats->option was specified.  Returning in image.\n");
+                return(in);
+            }
+            // Save old input "stats" parameter.
+            oldStatOptions = stats->options;
+            stats->options = statOptions;
+        }
+        if (0 == DetermineNumBits(statOptions)) {
+            psLogMsg(__func__, PS_LOG_WARN,
+                     "WARNING: pmSubtractSky(): no stats->options was requested\n");
+        }
+    }
+
+    //
+    // Generate required warning messages.
+    //
+    if (binFactor <= 0) {
+        psLogMsg(__func__, PS_LOG_WARN,
+                 "WARNING: pmSubtractSky(): binFactor is %d\n", binFactor);
+    }
+    if (stats == NULL) {
+        psLogMsg(__func__, PS_LOG_WARN,
+                 "WARNING: pmSubtractSky(): input parameter stats is NULL\n");
+    }
+
+    //
+    // Bin the input image according to input parameters.
+    // Create a new binned image mask.
+    //
+    if ((binFactor <= 1) || (stats == NULL) || (0 == DetermineNumBits(statOptions))) {
+        // No binning is required here.  Simply create a copy of the image
+        // and a mask.
+        binnedImage = psImageCopy(binnedImage, trimmedImg, PS_TYPE_F32);
+        if (binnedImage == NULL) {
+            psError(PS_ERR_UNKNOWN, false, "psImageCopy() returned NULL.  Returning in image.\n");
+            return(in);
+        }
+
+        if (in->mask != NULL) {
+            binnedMaskImage = psImageCopy(binnedMaskImage, in->mask, PS_TYPE_U8);
+            if (binnedMaskImage == NULL) {
+                psError(PS_ERR_UNKNOWN, false, "psImageCopy() returned NULL.  Returning in image.\n");
+                psFree(binnedImage);
+                return(in);
+            }
+        } else {
+            binnedMaskImage = psImageAlloc(binnedImage->numCols,
+                                           binnedImage->numRows,
+                                           PS_TYPE_U8);
+            psImageInit(binnedMaskImage, 0);
+        }
+    } else {
+        binnedImage = psImageRebin(NULL, trimmedImg, in->mask, 0, binFactor, stats);
+        if (binnedImage == NULL) {
+            psError(PS_ERR_UNKNOWN, false, "psImageRebin() returned NULL.  Returning in image.\n");
+            return(in);
+        }
+        binnedMaskImage = psImageAlloc(binnedImage->numCols,
+                                       binnedImage->numRows,
+                                       PS_TYPE_U8);
+        psImageInit(binnedMaskImage, 0);
+    }
+    psTrace("psModules.detrend", 4,
+            "binnedImage size is (%d, %d)\n", binnedImage->numRows, binnedImage->numCols);
+
+    //
+    // Clip pixels that are outside the acceptable range.
+    //
+    if (clipSD <= 0.0) {
+        psLogMsg(__func__, PS_LOG_WARN,
+                 "WARNING: pmSubtractSky(): clipSD is %f\n", clipSD);
+    } else {
+        // Determine the mean and standard deviation of the binned image.
+        psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
+        if (!psImageStats(myStats, binnedImage, NULL, 0)) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Couldn't get statistics for image.\n");
+            return NULL;
+        }
+        psF64 binnedMean = myStats->sampleMean;
+        psF64 binnedStdev = myStats->sampleStdev;
+        psFree(myStats);
+        psTrace("psModules.detrend", 6,
+                "binned StDev is %f\n", binnedStdev);
+
+        // Clip all pixels which are more than clipSD sigmas from the mean.
+        psTrace("psModules.detrend", 6,
+                "clipSD is %f\n", clipSD);
+
+        for (psS32 row = 0; row < binnedImage->numRows ; row++) {
+            for (psS32 col = 0; col < binnedImage->numCols ; col++) {
+                if (fabs(binnedImage->data.F32[row][col] - binnedMean) >
+                        (clipSD * binnedStdev)) {
+                    binnedMaskImage->data.U8[row][col] = 1;
+                }
+            }
+        }
+    }
+
+    //
+    // Fit the polynomial to the binned image
+    //
+    if (fit == PM_FIT_POLYNOMIAL) {
+        myPoly = (psPolynomial2D *) fitSpec;
+        PS_ASSERT_POLY_NON_NULL(myPoly, NULL);
+        PS_ASSERT_POLY_TYPE(myPoly, PS_POLYNOMIAL_ORD, NULL);
+
+        myPoly = ImageFitPolynomial(myPoly, binnedImage, binnedMaskImage);
+
+        if (myPoly != NULL) {
+            // Set the pixels in the binned image to that of the polynomial.
+            binnedImage = psImageEvalPolynomial(binnedImage, myPoly);
+            if (binnedImage == NULL) {
+                psError(PS_ERR_UNKNOWN, false, "psImageEvalPolynomial() returned NULL.  Returning in image.\n");
+                psFree(binnedMaskImage);
+                if (!((binFactor <= 1) || (stats == NULL))) {
+                    psFree(binnedImage);
+                }
+                if (oldStatOptions != 0) {
+                    stats->options = statOptions;
+                }
+                return(in);
+            }
+        } else {
+            psLogMsg(__func__, PS_LOG_WARN,
+                     "WARNING: pmSubtractSky(): could not model sky with a polynomial.\n");
+            psFree(binnedMaskImage);
+            if (!((binFactor <= 1) || (stats == NULL))) {
+                psFree(binnedImage);
+            }
+            if (oldStatOptions != 0) {
+                stats->options = statOptions;
+            }
+            return(in);
+        }
+    } else {
+        // We shouldn't get here since we check this above.
+        psError(PS_ERR_UNKNOWN, true, "Unallowable fit type.  Returning in image.\n");
+        psFree(binnedMaskImage);
+        if (!((binFactor <= 1) || (stats == NULL))) {
+            psFree(binnedImage);
+        }
+        if (oldStatOptions != 0) {
+            stats->options = statOptions;
+        }
+        return(in);
+    }
+
+    //
+    //Subtract the polynomially fitted image from the original image
+    //
+    if (binFactor <= 1) {
+        // The binned image is the same size as the original image.
+        for (psS32 row = 0; row < trimmedImg->numRows ; row++) {
+            for (psS32 col = 0; col < trimmedImg->numCols ; col++) {
+                trimmedImg->data.F32[row][col]-= binnedImage->data.F32[row][col];
+            }
+        }
+    } else {
+
+        psImageInterpolateOptions *interp = psImageInterpolateOptionsAlloc(PS_INTERPOLATE_BILINEAR,
+                                                                           binnedImage, NULL, NULL, 0,
+                                                                           0.0, 0.0, 0, 0, 0.0);
+
+        for (psS32 row = 0; row < trimmedImg->numRows ; row++) {
+            for (psS32 col = 0; col < trimmedImg->numCols ; col++) {
+                // We calculate the F32 value of the pixel coordinates in the
+                // binned image and then use a pixel interpolation routine to
+                // determine the value of the pixel at that location.
+                psF32 binRowF64 = ((psF32) row) / ((psF32) binFactor);
+                psF32 binColF64 = ((psF32) col) / ((psF32) binFactor);
+
+                // We add 0.5 to the pixel locations since the pixel
+                // interpolation routine defines the location of pixel
+                // (i, j) as (i+0.5, j+0.5).
+                binRowF64+= 0.5;
+                binColF64+= 0.5;
+
+                double binPixel;
+                if (!psImagePixelInterpolate(&binPixel, NULL, NULL, binColF64, binRowF64, interp)) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to interpolate image.");
+                    psFree(interp);
+                    psFree(binnedImage);
+                    return NULL;
+                }
+                trimmedImg->data.F32[row][col] -= binPixel;
+
+                psTrace("psModules.detrend", 8,
+                        "image[%d][%d] <--> binnedImage[%.2f][%.2f]: %lf\n",
+                        row, col, binRowF64-0.5, binColF64-0.5, binPixel);
+            }
+        }
+        psFree(interp);
+
+    }
+    psFree(binnedMaskImage);
+    psFree(binnedImage);
+    if (oldStatOptions != 0) {
+        stats->options = statOptions;
+    }
+
+    psTrace("psModules.detrend", 4,
+            "---- pmSubtractSky() exit successfully ----\n");
+    return(in);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmSkySubtract.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmSkySubtract.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/detrend/pmSkySubtract.h	(revision 22158)
@@ -0,0 +1,34 @@
+/* @file  pmSubtractSky.h
+ *
+ * This file will contain a module which will create a model of the
+ * background sky and subtract that from the input image.
+ *
+ * @author GLG, MHPCC
+ *
+ * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-03-30 21:12:56 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PM_SUBTRACT_SKY_H
+#define PM_SUBTRACT_SKY_H
+
+/// @addtogroup detrend Detrend Creation and Application
+/// @{
+
+// XXX: this is pmFit in pmSubtractBias.c, named psFit here.
+typedef enum {
+    PM_FIT_NONE,                              ///< No fit
+    PM_FIT_POLYNOMIAL,                        ///< Fit polynomial
+    PM_FIT_SPLINE                             ///< Fit cubic splines
+} psFit;
+
+pmReadout *pmSubtractSky(pmReadout *in,
+                         void *fitSpec,
+                         psFit fit,
+                         int binFactor,
+                         psStats *stats,
+                         float clipSD);
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/extras/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/extras/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/extras/.cvsignore	(revision 22158)
@@ -0,0 +1,9 @@
+.deps
+.libs
+Makefile
+Makefile.in
+libpsmodulesextras.la
+libpsmodulesextras_la-pmKapaPlots.lo
+libpsmodulesextras_la-psIOBuffer.lo
+libpsmodulesextras_la-psPipe.lo
+libpsmodulesextras_la-psVectorBracket.lo
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/extras/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/extras/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/extras/Makefile.am	(revision 22158)
@@ -0,0 +1,17 @@
+noinst_LTLIBRARIES = libpsmodulesextras.la
+
+libpsmodulesextras_la_CPPFLAGS = $(SRCINC) $(PSMODULES_CFLAGS) -I../pslib/
+libpsmodulesextras_la_LDFLAGS  = -release $(PACKAGE_VERSION)
+libpsmodulesextras_la_SOURCES  = \
+	psVectorBracket.c \
+	psPipe.c \
+	psIOBuffer.c \
+	pmKapaPlots.c
+
+pkginclude_HEADERS = \
+	psVectorBracket.h \
+	psPipe.h \
+	psIOBuffer.h \
+	pmKapaPlots.h
+
+CLEANFILES = *~
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/extras/pmKapaPlots.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/extras/pmKapaPlots.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/extras/pmKapaPlots.c	(revision 22158)
@@ -0,0 +1,234 @@
+/** @file  pmAstrometryWCS.c
+ *
+ *  @brief functions to convert FITS WCS keywords to / from pmFPA structures
+ *
+ *  @ingroup Astrometry
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-06-20 02:20:07 $
+ *
+ *  Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pslib.h>
+#include "pmKapaPlots.h"
+
+// the top portion of this file defines plotting functions which use kapa for plotting.
+// if kapa is not available, these functions are defined in the bottom portion as stubs
+// which perform NOP and return false (XXX should this be 'true' ??)
+
+# if (HAVE_KAPA)
+
+    // XXX not thread safe (perhaps not needed)
+    // to make this thread safe, we could check the thread ID and tie to it
+    static int kapa_fd = -1;
+
+int pmKapaOpen (bool showWindow)
+{
+    char kapa[64];
+
+    if (showWindow) {
+        strcpy (kapa, "kapa");
+    } else {
+        strcpy (kapa, "kapa -noX");
+    }
+
+    if (kapa_fd == -1) {
+        // kapa_fd = KapaOpen (kapa, "psphot");
+        kapa_fd = KapaOpenNamedSocket (kapa, "psphot");
+    }
+    return kapa_fd;
+}
+
+bool pmKapaClose ()
+{
+
+    if (kapa_fd == -1)
+        return true;
+    KapaClose (kapa_fd);
+    kapa_fd = -1;
+    return true;
+}
+
+bool pmKapaPlotVectorPair_AutoLimits_OpenGraph (int kapa, Graphdata *graphdata, psVector *xVec, psVector *yVec)
+{
+
+    // set limits based on data values
+    graphdata->xmin = +FLT_MAX;
+    graphdata->xmax = -FLT_MAX;
+    graphdata->ymin = +FLT_MAX;
+    graphdata->ymax = +FLT_MAX;
+    for (int i = 0; i < xVec->n; i++) {
+        graphdata->xmin = PS_MIN (graphdata->xmin, xVec->data.F32[i]);
+        graphdata->xmax = PS_MAX (graphdata->xmax, xVec->data.F32[i]);
+        graphdata->ymin = PS_MIN (graphdata->ymin, yVec->data.F32[i]);
+        graphdata->ymax = PS_MAX (graphdata->ymax, yVec->data.F32[i]);
+    }
+    // add 5% to range
+    float range;
+
+    range = graphdata->xmax - graphdata->xmin;
+    graphdata->xmax += 0.05*range;
+    graphdata->xmin -= 0.05*range;
+
+    range = graphdata->ymax - graphdata->ymin;
+    graphdata->ymax += 0.05*range;
+    graphdata->ymin -= 0.05*range;
+
+    KapaSetLimits (kapa, graphdata);
+    KapaSetFont (kapa, "helvetica", 14);
+    KapaBox (kapa, graphdata);
+
+    KapaPrepPlot (kapa, xVec->n, graphdata);
+    KapaPlotVector (kapa, xVec->n, xVec->data.F32, "x");
+    KapaPlotVector (kapa, yVec->n, yVec->data.F32, "y");
+    return true;
+}
+
+bool pmKapaPlotVectorPair (psVector *xVec, psVector *yVec)
+{
+
+    Graphdata graphdata;
+
+    int kapa = pmKapaOpen (true);
+    if (kapa == -1) {
+        psError(PS_ERR_UNKNOWN, true, "failure to open kapa");
+        return false;
+    }
+
+    if (xVec->n != yVec->n)
+        return false;
+
+    KapaInitGraph (&graphdata);
+    KapaClearPlots (kapa);
+
+    // set limits based on data values
+    graphdata.xmin = +FLT_MAX;
+    graphdata.xmax = -FLT_MAX;
+    graphdata.ymin = +FLT_MAX;
+    graphdata.ymax = -FLT_MAX;
+    for (int i = 0; i < xVec->n; i++) {
+        graphdata.xmin = PS_MIN (graphdata.xmin, xVec->data.F32[i]);
+        graphdata.xmax = PS_MAX (graphdata.xmax, xVec->data.F32[i]);
+        graphdata.ymin = PS_MIN (graphdata.ymin, yVec->data.F32[i]);
+        graphdata.ymax = PS_MAX (graphdata.ymax, yVec->data.F32[i]);
+    }
+    // add 5% to range
+    float range;
+
+    range = graphdata.xmax - graphdata.xmin;
+    graphdata.xmax += 0.05*range;
+    graphdata.xmin -= 0.05*range;
+
+    range = graphdata.ymax - graphdata.ymin;
+    graphdata.ymax += 0.05*range;
+    graphdata.ymin -= 0.05*range;
+
+    KapaSetLimits (kapa, &graphdata);
+    KapaSetFont (kapa, "helvetica", 14);
+    KapaBox (kapa, &graphdata);
+
+    graphdata.color = KapaColorByName ("black");
+    graphdata.ptype = 0;
+    graphdata.size = 0.5;
+    graphdata.style = 2;
+    KapaPrepPlot (kapa, xVec->n, &graphdata);
+    KapaPlotVector (kapa, xVec->n, xVec->data.F32, "x");
+    KapaPlotVector (kapa, yVec->n, yVec->data.F32, "y");
+
+    return true;
+}
+
+bool pmKapaPlotVectorTriple_AutoLimits_OpenGraph (int kapa, Graphdata *graphdata, psVector *xVec, psVector *yVec, psVector *zVec, bool increasing)
+{
+
+    // set limits based on data values
+    graphdata->xmin = +FLT_MAX;
+    graphdata->xmax = -FLT_MAX;
+    graphdata->ymin = +FLT_MAX;
+    graphdata->ymax = -FLT_MAX;
+    float zmin = +FLT_MAX;
+    float zmax = -FLT_MAX;
+    for (int i = 0; i < xVec->n; i++) {
+        graphdata->xmin = PS_MIN (graphdata->xmin, xVec->data.F32[i]);
+        graphdata->xmax = PS_MAX (graphdata->xmax, xVec->data.F32[i]);
+        graphdata->ymin = PS_MIN (graphdata->ymin, yVec->data.F32[i]);
+        graphdata->ymax = PS_MAX (graphdata->ymax, yVec->data.F32[i]);
+        zmin = PS_MIN (zmin, zVec->data.F32[i]);
+        zmax = PS_MAX (zmax, zVec->data.F32[i]);
+    }
+
+    // add 5% to range
+    float range;
+
+    psVector *zScale = psVectorAlloc (zVec->n, PS_DATA_F32);
+
+    range = zmax - zmin;
+    if (range == 0.0) {
+        psVectorInit (zScale, 1.0);
+    } else {
+        for (int i = 0; i < zVec->n; i++) {
+            if (increasing) {
+                zScale->data.F32[i] = PS_MIN (1.5, PS_MAX(0.05, 1.5*(zVec->data.F32[i] - zmin)/range));
+            } else {
+                zScale->data.F32[i] = PS_MIN (1.5, PS_MAX(0.05, 1.5*(zmax - zVec->data.F32[i])/range));
+            }
+        }
+    }
+
+    range = graphdata->xmax - graphdata->xmin;
+    graphdata->xmax += 0.05*range;
+    graphdata->xmin -= 0.05*range;
+
+    range = graphdata->ymax - graphdata->ymin;
+    graphdata->ymax += 0.05*range;
+    graphdata->ymin -= 0.05*range;
+
+    KapaSetLimits (kapa, graphdata);
+    KapaSetFont (kapa, "helvetica", 14);
+    KapaBox (kapa, graphdata);
+
+    // the point size will be scaled from the z vector
+    graphdata->size = -1;
+    KapaPrepPlot (kapa, xVec->n, graphdata);
+    KapaPlotVector (kapa, xVec->n, xVec->data.F32, "x");
+    KapaPlotVector (kapa, yVec->n, yVec->data.F32, "y");
+    KapaPlotVector (kapa, zVec->n, zScale->data.F32, "z");
+    psFree (zScale);
+    return true;
+}
+
+# else
+    # include "pmKapaPlots.h"
+
+    int pmKapaOpen (bool showWindow)
+{
+    return -1;
+}
+
+bool pmKapaClose ()
+{
+    return true;
+}
+
+bool pmKapaPlotVectorPair (psVector *xVec, psVector *yVec)
+{
+    return false;
+}
+
+bool pmKapaPlotVectorPair_AutoLimits_OpenGraph (int kapa, void *graphdata, psVector *xVec, psVector *yVec)
+{
+    return false;
+}
+
+bool pmKapaPlotVectorTriple_AutoLimits_OpenGraph (int kapa, void *graphdata, psVector *xVec, psVector *yVec, psVector *zVec, bool increasing)
+{
+    return false;
+}
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/extras/pmKapaPlots.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/extras/pmKapaPlots.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/extras/pmKapaPlots.h	(revision 22158)
@@ -0,0 +1,35 @@
+/* @file  pmKapaPlots.h
+ * @brief functions to make plots with the external program 'kapa' 
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-03-30 21:12:56 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_KAPA_PLOTS_H
+#define PM_KAPA_PLOTS_H
+
+/// @addtogroup Extras Miscellaneous Funtions
+/// @{
+
+// move to psLib or psModules
+int pmKapaOpen (bool showWindow);
+bool pmKapaClose ();
+bool pmKapaPlotVectorPair (psVector *xVec, psVector *yVec);
+
+# if (HAVE_KAPA)
+# include <kapa.h>
+
+// yes, this is an absurd name...
+bool pmKapaPlotVectorPair_AutoLimits_OpenGraph (int kapa, Graphdata *graphdata, psVector *xVec, psVector *yVec);
+bool pmKapaPlotVectorTriple_AutoLimits_OpenGraph (int kapa, Graphdata *graphdata, psVector *xVec, psVector *yVec, psVector *zVec, bool increasing);
+# else
+
+bool pmKapaPlotVectorPair_AutoLimits_OpenGraph (int kapa, void *graphdata, psVector *xVec, psVector *yVec);
+bool pmKapaPlotVectorTriple_AutoLimits_OpenGraph (int kapa, void *graphdata, psVector *xVec, psVector *yVec, psVector *zVec, bool increasing);
+# endif
+
+/// @}
+#endif // PM_KAPA_PLOTS_H
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/extras/psIOBuffer.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/extras/psIOBuffer.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/extras/psIOBuffer.c	(revision 22158)
@@ -0,0 +1,113 @@
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <pslib.h>
+#include "psIOBuffer.h"
+
+static void psIOBufferFree (psIOBuffer *buffer)
+{
+    if (buffer == NULL)
+        return;
+
+    psFree (buffer->data);
+    return;
+}
+
+psIOBuffer *psIOBufferAlloc (int nBuffer)
+{
+
+    psIOBuffer *buffer = (psIOBuffer *)psAlloc(sizeof(psIOBuffer));
+    psMemSetDeallocator(buffer, (psFreeFunc) psIOBufferFree);
+
+    buffer->data = (char *) psAlloc (nBuffer + 1);
+
+    buffer->nAlloc = nBuffer + 1;
+    buffer->nReset = nBuffer;
+    buffer->nBlock = nBuffer / 2;
+    buffer->n = 0;
+    return (buffer);
+}
+
+bool psIOBufferFlush (psIOBuffer *buffer)
+{
+
+    if (buffer == NULL)
+        return false;
+    buffer->n = 0;
+    buffer->nAlloc = buffer->nReset;
+    buffer->data = psRealloc (buffer->data, buffer->nAlloc);
+    memset(buffer->data, '\0', buffer->nAlloc);
+
+    return true;
+}
+
+int psIOBufferRead (psIOBuffer *buffer, int fd)
+{
+
+    int Nread, Nfree;
+
+    if (fd == 0) {
+        /* pipe is closed */
+        return (0);
+    }
+
+    Nfree = buffer->nAlloc - buffer->n - 1;
+
+    // extend the data block if needed
+    if (Nfree < buffer->nBlock) {
+        buffer->nAlloc += 2*buffer->nBlock + 1;
+        buffer->data = psRealloc (buffer->data, buffer->nAlloc);
+        Nfree = buffer->nAlloc - buffer->n;
+        memset(buffer->data + buffer->n, '\0', Nfree);
+    }
+
+    // attempt to read from the fd into the buffer
+    Nread = read (fd, &buffer->data[buffer->n], buffer->nBlock);
+
+    if (Nread >= 0) {
+        buffer->n += Nread;
+        buffer->data[buffer->n] = 0;
+        return (Nread);
+    }
+
+    // check on exit status (try again if waiting for non-blocking fd)
+    if (Nread == -1) {
+        switch (errno) {
+        case EAGAIN:
+        case EIO:
+            /** no data available in pipe **/
+            return (-1);
+        default:
+            /** error reading from pipe **/
+            psError (PS_ERR_IO, true, "error on psIOBufferRead");
+            return (-2);
+        }
+    }
+    return (Nread);
+}
+
+/* read until buffer is empty (Nmax retries) */
+int psIOBufferReadEmpty (psIOBuffer *buffer, int Nmax, int fd)
+{
+
+    int i, status;
+
+    status = -1;
+    for (i = 0; (status != 0) && (i < Nmax); i++) {
+        status = psIOBufferRead (buffer, fd);
+        if (status == -2)
+            return false;
+        if (status == -1)
+            usleep (10000);
+        if (status > 0)
+            i = 0;
+    }
+    if (status == -1)
+        return false;
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/extras/psIOBuffer.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/extras/psIOBuffer.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/extras/psIOBuffer.h	(revision 22158)
@@ -0,0 +1,34 @@
+/* @file  IOBuffer.h
+ * @brief input/output character buffer
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-01-24 02:54:15 $
+ * Copyright 2004-2005 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PS_IO_BUFFER_H
+#define PS_IO_BUFFER_H
+
+/// @addtogroup Extras Miscellaneous Funtions
+/// @{
+
+typedef struct
+{
+    char *data;
+    int nAlloc;    // current size of allocated buffer
+    int nReset;    // size to set buffer after flush
+    int nBlock;    // number of bytes to try to read at a time
+    int n;    // current size of filled data
+}
+psIOBuffer;
+
+// psIOBuffer functions
+psIOBuffer *psIOBufferAlloc (int nBuffer);
+bool psIOBufferFlush (psIOBuffer *buffer);
+int psIOBufferRead (psIOBuffer *buffer, int fd);
+int psIOBufferReadEmpty (psIOBuffer *buffer, int maxRetries, int fd);
+
+/// @}
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/extras/psPipe.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/extras/psPipe.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/extras/psPipe.c	(revision 22158)
@@ -0,0 +1,210 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <pslib.h>
+#include <psPipe.h>
+
+void closePipes (int *stdin_fd, int *stdout_fd, int *stderr_fd)
+{
+
+    if (stdin_fd[0]  != 0)
+        close (stdin_fd[0]);
+    if (stdin_fd[1]  != 0)
+        close (stdin_fd[0]);
+    if (stdout_fd[0] != 0)
+        close (stdout_fd[0]);
+    if (stdout_fd[1] != 0)
+        close (stdout_fd[1]);
+    if (stderr_fd[0] != 0)
+        close (stderr_fd[0]);
+    if (stderr_fd[1] != 0)
+        close (stderr_fd[1]);
+}
+
+static void psPipeFree (psPipe *pipe)
+{
+    return;
+}
+
+psPipe *psPipeAlloc ()
+{
+    psPipe *pipe = (psPipe *)psAlloc(sizeof(psPipe));
+    psMemSetDeallocator(pipe, (psFreeFunc) psPipeFree);
+
+    pipe->fd_stdin  = 0;
+    pipe->fd_stdout = 0;
+    pipe->fd_stderr = 0;
+    return (pipe);
+}
+
+psPipe *psPipeOpen (char *command)
+{
+
+    int stdin_fd[2], stdout_fd[2], stderr_fd[2], status;
+    pid_t pid;
+
+    memset(stdin_fd,  '\0', 2*sizeof(int));
+    memset(stdout_fd, '\0', 2*sizeof(int));
+    memset(stderr_fd, '\0', 2*sizeof(int));
+
+    if (pipe (stdin_fd)  < 0) {
+        psError (PS_ERR_UNKNOWN, true, "cannot create pipe file descriptor");
+        closePipes (stdin_fd, stdout_fd, stderr_fd);
+        return NULL;
+    }
+    if (pipe (stdout_fd) < 0) {
+        psError (PS_ERR_UNKNOWN, true, "cannot create pipe file descriptor");
+        closePipes (stdin_fd, stdout_fd, stderr_fd);
+        return NULL;
+    }
+    if (pipe (stderr_fd) < 0) {
+        psError (PS_ERR_UNKNOWN, true, "cannot create pipe file descriptor");
+        closePipes (stdin_fd, stdout_fd, stderr_fd);
+        return NULL;
+    }
+
+    psArray *cmd = psStringSplitArray (command, " ", false);
+    if (cmd->n <= 0) {
+        psError (PS_ERR_UNKNOWN, true, "empty command for pipe");
+        psFree (cmd);
+        closePipes (stdin_fd, stdout_fd, stderr_fd);
+        return NULL;
+    }
+
+    // create the command line array needed by execvp
+    char **argv = (char **)psAlloc((cmd->n+1)*sizeof(char *));
+    for (int i = 0; i < cmd->n; i++) {
+        argv[i] = cmd->data[i];
+    }
+    argv[cmd->n] = NULL;
+
+    pid = fork ();
+    if (!pid) { /* must be child process */
+        /* close the other ends of the pipes */
+        close (stdin_fd[1]);
+        close (stdout_fd[0]);
+        close (stderr_fd[0]);
+
+        /* tie our ends of the pipes to stdin, stdout, stderr */
+        dup2 (stdin_fd[0],  STDIN_FILENO);
+        dup2 (stdout_fd[1], STDOUT_FILENO);
+        dup2 (stderr_fd[1], STDERR_FILENO);
+
+        /* set all three unblocking */
+        setvbuf (stdin,  (char *) NULL, _IONBF, BUFSIZ);
+        setvbuf (stdout, (char *) NULL, _IONBF, BUFSIZ);
+        setvbuf (stderr, (char *) NULL, _IONBF, BUFSIZ);
+
+        status = execvp (argv[0], argv);
+
+        // this statement exits the child, not the parent, process
+        exit (1);
+    }
+    psFree (cmd);
+    psFree (argv);
+
+    if (pid == -1) {
+        psError (PS_ERR_UNKNOWN, true, "unable to create child process");
+        closePipes (stdin_fd, stdout_fd, stderr_fd);
+        return NULL;
+    }
+
+    /* close the other ends of the pipes */
+    close (stdin_fd[0]);
+    stdin_fd[0]  = 0;
+    close (stdout_fd[1]);
+    stdout_fd[1] = 0;
+    close (stderr_fd[1]);
+    stderr_fd[1] = 0;
+
+    /* make the pipes non-blocking */
+    fcntl (stdin_fd[1],  F_SETFL, O_NONBLOCK);
+    fcntl (stdout_fd[0], F_SETFL, O_NONBLOCK);
+    fcntl (stderr_fd[0], F_SETFL, O_NONBLOCK);
+
+    psPipe *pipe = psPipeAlloc();
+
+    pipe->pid    = pid;
+    pipe->fd_stdin  = stdin_fd[1];
+    pipe->fd_stdout = stdout_fd[0];
+    pipe->fd_stderr = stderr_fd[0];
+
+    return (pipe);
+}
+
+// this function returns the exit status of the called function
+// or a value > 255 on an error
+int psPipeClose (psPipe *pipe)
+{
+    int close_status;
+    int exit_status;
+    int wait_status;
+    int result;
+
+    PS_ASSERT_PTR_NON_NULL(pipe, false);
+
+    close_status = true;
+    if (close (pipe->fd_stdin) != 0) {
+        psError(PS_ERR_IO, true, "error closing the pipe stdin (pid %d, error %s)\n", pipe->pid, strerror(errno));
+        close_status = false;
+    }
+    if (close (pipe->fd_stdout) != 0) {
+        psError(PS_ERR_IO, true, "error closing the pipe stdout (pid %d, error %s)\n", pipe->pid, strerror(errno));
+        close_status = false;
+    }
+    if (close (pipe->fd_stderr) != 0) {
+        psError(PS_ERR_IO, true, "error closing the pipe sterr (pid %d, error %s)\n", pipe->pid, strerror(errno));
+        close_status = false;
+    }
+
+    // we expect the child process to have exited.
+    // wait for the exit condition, but no longer than 100ms
+    for (int i = 0; i < 10; i++) {
+        result = waitpid (pipe->pid, &wait_status, WNOHANG);
+        switch (result) {
+        case -1:   // error on waitpid
+            switch (errno) {
+            case ECHILD:
+                psError(PS_ERR_IO, true, "unknown PID, not a child process: %d\n", pipe->pid);
+                return 0x100;
+            default:
+                psAbort("unexpected response to waitpid: %d\n", result);
+            }
+            break;
+
+        case 0:   // child not yet exited
+            usleep (10000);
+            continue;
+
+        default:
+            if (result != pipe->pid) {
+                psAbort("waitpid error: mis-matched PID (%d vs %d).  programming error\n", result, pipe->pid);
+            }
+            if (WIFEXITED(wait_status)) {
+                exit_status = WEXITSTATUS(wait_status);
+                if (close_status) {
+                    return exit_status;
+                } else {
+                    return (0x100);
+                }
+            }
+            if (WIFSIGNALED(wait_status)) {
+                psError(PS_ERR_IO, true, "job %d exited on signal %d\n", pipe->pid, WTERMSIG(wait_status));
+                return (0x100 + WTERMSIG(wait_status));
+            }
+            if (WIFSTOPPED(wait_status)) {
+                psAbort("waitpid returns 'stopped' programming error\n");
+            }
+        }
+    }
+    psError(PS_ERR_IO, true, "child process pid %d did not exit\n", pipe->pid);
+    return 0x100;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/extras/psPipe.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/extras/psPipe.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/extras/psPipe.h	(revision 22158)
@@ -0,0 +1,33 @@
+/* @file  psPipe.h
+ * @brief 3-stream pipe 
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-01-24 02:54:15 $
+ * Copyright 2004-2005 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PS_PIPE_H
+#define PS_PIPE_H
+
+/// @addtogroup Extras Miscellaneous Funtions
+/// @{
+
+// move these to pslib??
+typedef struct
+{
+    int pid;
+    int fd_stdin;
+    int fd_stdout;
+    int fd_stderr;
+}
+psPipe;
+
+// psPipe functions
+psPipe *psPipeAlloc ();
+psPipe *psPipeOpen (char *command);
+int     psPipeClose (psPipe *pipe);
+
+/// @}
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/extras/psVectorBracket.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/extras/psVectorBracket.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/extras/psVectorBracket.c	(revision 22158)
@@ -0,0 +1,137 @@
+/** @file  psVectorBracket.c
+ *
+ *  Vector Bracketing tools
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-12-10 18:27:26 $
+ *
+ *  Copyright 2006 Institute for Astronomy, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pslib.h>
+#include "psVectorBracket.h"
+
+// return the last entry below or first entry above key value
+int psVectorBracket(const psVector *index, psF32 key, bool above)
+{
+
+    int N;
+    int Nlo = 0;
+    int Nhi = index->n;
+
+    if (above) {
+        while (Nhi - Nlo > 10) {
+            N = 0.5*(Nlo + Nhi);
+            if (index->data.F32[N] > key) {
+                Nhi = N;
+            } else {
+                Nlo = N - 1;
+            }
+        }
+        // at this point, index[Nhi] > key >= index[Nlo]
+        N = Nlo;
+        while ((index->data.F32[N] <= key) && (N < Nhi)) {
+            N++;
+        }
+        return (N);
+    }
+    while (Nhi - Nlo > 10) {
+        N = 0.5*(Nlo + Nhi);
+        if (index->data.F32[N] < key) {
+            Nlo = N;
+        } else {
+            Nhi = N + 1;
+        }
+    }
+    // at this point, index[Nhi] >= key > index[Nlo]
+    N = Nhi;
+    while ((index->data.F32[N] >= key) && (N > Nlo)) {
+        N--;
+    }
+    return (N);
+}
+
+// return the last entry below or first entry above key value (reverse sorted input)
+int psVectorBracketDescend(const psVector *index, psF32 key, bool above)
+{
+
+    int N;
+    int Nhi = 0;
+    int Nlo = index->n;
+
+    if (above) {
+        while (Nlo - Nhi > 10) {
+            N = 0.5*(Nhi + Nlo);
+            if (index->data.F32[N] < key) {
+                Nlo = N;
+            } else {
+                Nhi = N - 1;
+            }
+        }
+        // at this point, index[Nhi] >= key > index[Nlo]
+        N = Nhi;
+        while ((index->data.F32[N] >= key) && (N < Nlo)) {
+            N++;
+        }
+        return (N);
+    }
+    while (Nlo - Nhi > 10) {
+        N = 0.5*(Nhi + Nlo);
+        if (index->data.F32[N] > key) {
+            Nhi = N;
+        } else {
+            Nlo = N + 1;
+        }
+    }
+    // at this point, index[Nhi] > key >= index[Nlo]
+    N = Nlo;
+    while ((index->data.F32[N] <= key) && (N > Nhi)) {
+        N--;
+    }
+    return (N);
+}
+
+// search for the bins bounding key in index, interpolate the corresponding values
+psF32 psVectorInterpolate(const psVector *index, const psVector *value, psF32 key)
+{
+
+    int n0 = 0;
+    int n1 = 0;
+
+    // extrapolate at ends
+    if (key < index->data.F32[0]) {
+        n0 = 0;
+        n1 = 1;
+    }
+
+    // extrapolate at ends
+    if (key > index->data.F32[index->n-1]) {
+        n0 = index->n-2;
+        n1 = index->n-1;
+    }
+
+    if (n1 == 0) {
+        n0 = psVectorBracket (index, key, FALSE);
+        n1 = n0 + 1;
+    }
+
+    if (n0 == index->n-1) {
+        n1 = n0;
+        n0 = n1 - 1;
+    }
+
+    float dy = value->data.F32[n1] - value->data.F32[n0];
+    float dx = index->data.F32[n1] - index->data.F32[n0];
+    float dX = key - index->data.F32[n0];
+    float dY = dX * (dy/dx);
+    float result = value->data.F32[n0] + dY;
+    return result;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/extras/psVectorBracket.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/extras/psVectorBracket.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/extras/psVectorBracket.h	(revision 22158)
@@ -0,0 +1,22 @@
+/* @file  psVectorBracket.h
+ * @brief vector bracket functions
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-01-24 02:54:15 $
+ * Copyright 2004-2005 Institute for Astronomy, University of Hawaii
+ */
+
+# ifndef PS_VECTOR_BRACKET_H
+# define PS_VECTOR_BRACKET_H
+
+/// @addtogroup Extras Miscellaneous Funtions
+/// @{
+
+int psVectorBracket(const psVector *index, psF32 key, bool above);
+int psVectorBracketDescend(const psVector *index, psF32 key, bool above);
+psF32 psVectorInterpolate(const psVector *index, const psVector *value, psF32 key);
+
+/// @}
+# endif /* PS_VECTOR_BRACKET_H */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/.cvsignore	(revision 22158)
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/Makefile.am	(revision 22158)
@@ -0,0 +1,35 @@
+noinst_LTLIBRARIES = libpsmodulesimcombine.la
+
+libpsmodulesimcombine_la_CPPFLAGS = $(SRCINC) $(PSMODULES_CFLAGS)
+libpsmodulesimcombine_la_LDFLAGS  = -release $(PACKAGE_VERSION)
+
+libpsmodulesimcombine_la_SOURCES = \
+	pmReadoutCombine.c	\
+	pmStack.c		\
+	pmStackReject.c		\
+	pmSubtraction.c		\
+	pmSubtractionEquation.c	\
+	pmSubtractionIO.c	\
+	pmSubtractionKernels.c	\
+	pmSubtractionMask.c	\
+	pmSubtractionMatch.c	\
+	pmSubtractionParams.c	\
+	pmSubtractionStamps.c	\
+	pmPSFEnvelope.c
+
+pkginclude_HEADERS = \
+	pmImageCombine.h \
+	pmReadoutCombine.h	\
+	pmStack.h		\
+	pmStackReject.h		\
+	pmSubtraction.h		\
+	pmSubtractionEquation.h	\
+	pmSubtractionIO.h	\
+	pmSubtractionKernels.h	\
+	pmSubtractionMask.h	\
+	pmSubtractionMatch.h	\
+	pmSubtractionParams.h	\
+	pmSubtractionStamps.h	\
+	pmPSFEnvelope.h
+
+CLEANFILES = *~
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/demo_psftool.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/demo_psftool.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/demo_psftool.c	(revision 22158)
@@ -0,0 +1,194 @@
+// This is a very quick and dirty test program for pmPSFEnvelope
+//
+// gcc -g demo_psftool.c -o demo_psftool `psmodules-config --cflags --libs` --std=gnu99 -Wall
+//
+// ./demo_psftool test MOPS.skycell.0198767.wrp*.psf
+//
+
+#include <stdio.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+// Add a single filename to the arguments as an array, so that it can be used with pmFPAfileBindFromArgs, etc
+static void fileList(const char *file, // The symbolic name for the file
+                     const char *name, // The name of the file
+                     const char *comment, // Description of the file
+                     pmConfig *config // Configuration
+    )
+{
+    psArray *files = psArrayAlloc(1); // Array with file names
+    files->data[0] = psStringCopy(name);
+    psMetadataAddArray(config->arguments, PS_LIST_TAIL, file, 0, comment, files);
+    psFree(files);
+    return;
+}
+
+
+
+int main(int argc, char *argv[])
+{
+    psLibInit(NULL);
+    pmConfig *config = pmConfigRead(&argc, argv, "PSF");
+    if (!config) {
+        psErrorStackPrint(stderr, "Error reading configuration.");
+        exit(PS_EXIT_CONFIG_ERROR);
+    }
+
+    psTraceSetLevel("psModules.imcombine", 5);
+    psTraceSetLevel("psModules.objects", 0);
+    psTraceSetLevel("psLib.math", 0);
+
+    pmModelClassInit();
+
+    psMetadataAddStr(config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "Name of the output", argv[1]);
+
+    psArray *files = psArrayAlloc(argc - 2);
+    for (int i = 2; i < argc; i++) {
+        psString name = NULL;           // Name of file list
+        psStringAppend(&name, "INPUT_%d", i);
+
+        fileList(name, argv[i], "Input PSF", config);
+
+        pmFPAfile *file = pmFPAfileDefineFromArgs(NULL, config, "PSPHOT.PSF.LOAD", name);
+        psFree(name);
+        if (!file) {
+            psErrorStackPrint(stderr, "Can't define PSF file from %s --> %s", name, argv[i]);
+            psFree(files);
+            psFree(config);
+            exit(PS_EXIT_SYS_ERROR);
+        }
+
+        files->data[i - 2] = psMemIncrRefCounter(file);
+    }
+
+    pmFPAfile *outFile = pmFPAfileDefineOutput(config, NULL, "PSPHOT.PSF.SAVE");
+    if (!outFile) {
+        psErrorStackPrint(stderr, "Can't define output PSF file");
+        psFree(files);
+        psFree(config);
+        exit(PS_EXIT_SYS_ERROR);
+    }
+    outFile->save = true;
+
+    // XXX This is a bit dodgy; should be more rigorous for a real system
+    {
+        pmFPAview *phuView = pmFPAviewAlloc(0);
+        phuView->chip = 0;
+        if (!pmFPAAddSourceFromView(outFile->fpa, "Envelope PSF", phuView, outFile->format)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to add PHU to output.");
+            psFree(phuView);
+            return false;
+        }
+        psFree(phuView);
+    }
+
+    pmFPAview *view = pmFPAviewAlloc(0);
+
+    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+        psErrorStackPrint(stderr, "Problem in I/O");
+        psFree(view);
+        psFree(files);
+        psFree(config);
+        exit(PS_EXIT_SYS_ERROR);
+    }
+
+    pmChip *chip;
+    while ((chip = pmFPAviewNextChip(view, outFile->fpa, 1)) != NULL) {
+        if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+            psErrorStackPrint(stderr, "Problem in I/O");
+            psFree(view);
+            psFree(files);
+            psFree(config);
+            exit(PS_EXIT_SYS_ERROR);
+        }
+
+#if 0
+        pmFPAfileActivate(config->files, "PSPHOT.PSF.SAVE", false);
+        pmCell *cell;
+        while ((cell = pmFPAviewNextCell(view, outFile->fpa, 1)) != NULL) {
+            if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+                psErrorStackPrint(stderr, "Problem in I/O");
+                psFree(view);
+                psFree(files);
+                psFree(config);
+                exit(PS_EXIT_SYS_ERROR);
+            }
+        }
+#endif
+
+        psArray *inputs = psArrayAlloc(files->n);
+        int numCols = 4501, numRows = 4751;
+        for (int i = 0; i < files->n; i++) {
+            pmFPAfile *file = files->data[i];
+            pmChip *chip = pmFPAviewThisChip(view, file->fpa);
+
+            pmPSF *psf = psMetadataLookupPtr(NULL, chip->analysis, "PSPHOT.PSF");
+            if (!psf) {
+                psErrorStackPrint(stderr, "Can't find PSF in file %d", i);
+                psFree(inputs);
+                psFree(files);
+                psFree(config);
+                exit(PS_EXIT_PROG_ERROR);
+            }
+
+#if 0
+            pmHDU *hdu = pmHDUGetLowest(file->fpa, chip, NULL);
+            int imaxis1 = psMetadataLookupS32(NULL, hdu->header, "IMAXIS1");
+            int imaxis2 = psMetadataLookupS32(NULL, hdu->header, "IMAXIS2");
+            if (imaxis1 == 0 || imaxis2 == 0) {
+                psErrorStackPrint(stderr, "Size of image %d can't be determined.", i);
+                psFree(inputs);
+                psFree(files);
+                psFree(config);
+                exit(PS_EXIT_SYS_ERROR);
+            }
+            if (numCols == 0 && numRows == 0) {
+                numCols = imaxis1;
+                numRows = imaxis2;
+            } else if (imaxis1 != numCols || imaxis2 != numRows) {
+                psErrorStackPrint(stderr, "Image %d differs in size: %dx%d vs %dx%d",
+                                  i, imaxis1, imaxis2, numCols, numRows);
+                psFree(inputs);
+                psFree(files);
+                psFree(config);
+                exit(PS_EXIT_SYS_ERROR);
+            }
+#endif
+
+            inputs->data[i] = psMemIncrRefCounter(psf);
+        }
+
+        pmPSF *psf = pmPSFEnvelope(numCols, numRows, inputs, 5, 20, "PS_MODEL_RGAUSS", 3, 3);
+        psFree(inputs);
+        if (!psf) {
+            psErrorStackPrint(stderr, "Can't generate envelope PSF.");
+            psFree(config);
+            exit(PS_EXIT_SYS_ERROR);
+        }
+
+        psMetadataAddPtr(chip->analysis, PS_LIST_TAIL, "PSPHOT.PSF", PS_DATA_UNKNOWN, "Envelope PSF", psf);
+        psFree(psf);
+        chip->data_exists = true;
+
+        if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+            psErrorStackPrint(stderr, "Problem in I/O");
+            psFree(view);
+            psFree(files);
+            psFree(config);
+            exit(PS_EXIT_SYS_ERROR);
+            return false;
+        }
+    }
+
+    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+        psErrorStackPrint(stderr, "Problem in I/O");
+        psFree(view);
+        psFree(files);
+        psFree(config);
+        exit(PS_EXIT_SYS_ERROR);
+    }
+
+    psFree(config);
+
+    exit(PS_EXIT_SUCCESS);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmImageCombine.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmImageCombine.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmImageCombine.c	(revision 22158)
@@ -0,0 +1,683 @@
+/** @file  pmImageCombine.c
+ *
+ *  This file will perform image combination of several images of the
+ *  same field, produce a list of questionable pixels, then tag some
+ *  of those pixels as cosmic rays.
+ *
+ *  @author Paul Price, IfA (original prototype)
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-04-04 22:42:48 $
+ *
+ *  XXX: pmRejectPixels() has a known bug with the pmImageTransform() call.
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <config.h>
+#include <stdio.h>
+#include <math.h>
+#include "pslib.h"
+
+#define PIXEL_LIST_BUFFER 100           // Size of the pixel list buffer
+
+// Data structure for use as a buffer in combining pixels
+typedef struct
+{
+    psVector *pixels;                   // Pixel values
+    psVector *masks;                    // Pixel masks
+    psVector *errors;                   // Pixel errors
+    psStats *stats;                     // Statistics to use with combination
+}
+combineBuffer;
+
+void combineBufferFree(combineBuffer *buffer)
+{
+    psFree(buffer->pixels);
+    psFree(buffer->masks);
+    psFree(buffer->errors);
+    psFree(buffer->stats);
+}
+
+combineBuffer *combineBufferAlloc(long numImages // Number of images that will be combined
+                                 )
+{
+    combineBuffer *buffer = psAlloc(sizeof(combineBuffer));
+    psMemSetDeallocator(buffer, (psFreeFunc)combineBufferFree);
+
+    buffer->pixels = psVectorAlloc(numImages, PS_TYPE_F32);
+    buffer->masks = psVectorAlloc(numImages, PS_TYPE_MASK);
+    buffer->errors = psVectorAlloc(numImages, PS_TYPE_F32);
+    buffer->stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
+
+    return buffer;
+}
+
+
+static bool combinePixels(psImage *combine, // Combined image, for output
+                          psArray *questionablePixels, // Array of rejection masks
+                          int x, int y, // Position in the images
+                          const psArray *images, // Array of input images
+                          const psArray *errors, // Array of input error images
+                          const psArray *masks, // Array of input masks
+                          psU32 maskVal, // Mask value
+                          psS32 numIter, // Number of rejection iterations
+                          psF32 sigmaClip, // Number of standard deviations at which to reject
+                          combineBuffer *buffer // Buffer for combination; to avoid multiple allocations
+                         )
+{
+    assert(combine);
+    assert(x >= 0 && x < combine->numCols);
+    assert(y >= 0 && y < combine->numRows);
+    assert(images);
+    int numImages = images->n;          // Number of images to combine
+    if (masks) {
+        assert(masks->n == numImages);
+    }
+    if (errors) {
+        assert(errors->n == numImages);
+    }
+    assert(numIter >= 0);
+    assert(sigmaClip > 0);
+    assert(!questionablePixels || (questionablePixels && questionablePixels->n == numImages));
+
+    if (buffer) {
+        psMemIncrRefCounter(buffer);
+    } else {
+        buffer = combineBufferAlloc(numImages);
+    }
+
+    psVector *pixelData = buffer->pixels; // Values for the pixel of interest
+    psVector *pixelErrors = buffer->errors; // Errors for the pixel of interest
+    psVector *pixelMasks = buffer->masks; // Masks for the pixel of interest
+    psStats *stats = buffer->stats;     // Statistics for combination
+
+    //
+    // Loop through each image, extract the pixel/mask/error data into psVectors.
+    //
+    if (!masks) {
+        psVectorInit(pixelMasks, 0);
+    }
+    if (!errors) {
+        pixelErrors = NULL;
+    }
+    for (int i = 0; i < numImages; i++) {
+        // Set the pixel data
+        psImage *image = images->data[i]; // Image of interest
+        pixelData->data.F32[i] = image->data.F32[y][x];
+        // Set the pixel mask data, if necessary
+        if (masks) {
+            psImage *mask = masks->data[i]; // Mask of interest
+            pixelMasks->data.U8[i] = mask->data.U8[y][x];
+        }        // Set the pixel error data, if necessary
+        if (errors) {
+            psImage *error = errors->data[i]; // Error image of interest
+            pixelErrors->data.F32[i] = error->data.F32[y][x];
+        }
+    }
+
+    //
+    // Iterate on the pixels, rejecting outliers
+    //
+    for (int iter = 0; iter < numIter; iter++) {
+        // Combine all the pixels, using the specified stat.
+        if (!psVectorStats(stats, pixelData, pixelErrors, pixelMasks, maskVal)) {
+            combine->data.F32[y][x] = NAN;
+            psFree(buffer);
+            return false;
+        }
+        float combinedPixel = stats->sampleMean; // Value of the combination
+
+        if (iter == 0) {
+            // Save the value produced with no rejection, since it may be useful later
+            // (if the rejection turns out to be unnecessary)
+            combine->data.F32[y][x] = combinedPixel;
+        }
+
+        //
+        // Reject all pixels that lie more that sigmaClip standard deviations from
+        // the combined pixel value.
+        //
+        int numRejects = 0;     // Number of rejections
+        float stdev = stats->sampleStdev;
+        for (int i = 0; i < numImages; i++) {
+            if (!(pixelMasks->data.U8[i] & maskVal) &&
+                    fabs(pixelData->data.F32[i] - combinedPixel) > sigmaClip * stdev) {
+                // Reject pixel as questionable
+                numRejects++;
+                pixelMasks->data.U8[i] = maskVal;
+                if (questionablePixels) {
+                    // Mark the pixel as questionable
+                    psPixels *qp = questionablePixels->data[i]; // Questionable pixels for this image
+                    int qpNum = qp->n; // Number of QPs in the image of interest
+                    if (qpNum >= qp->nalloc) {
+                        // Grow dynamically, if required
+                        qp = psPixelsRealloc(qp, qp->nalloc + PIXEL_LIST_BUFFER);
+                        questionablePixels->data[i] = qp;
+                    }
+                    qp->data[qpNum].x = x;
+                    qp->data[qpNum].y = y;
+                    qp->n++;
+                }
+            }
+        }
+
+        //
+        // If the number of rejected pixels is zero, then there's no point continuing the loop.
+        //
+        if (numRejects == 0) {
+            break;
+        }
+
+        //
+        // XXX: Is it possible to have all pixels rejected?  If so, we should exit the loop.
+        //
+    }
+
+    psFree(buffer);
+    return true;
+}
+
+psImage *pmCombineImages(
+    psImage *combine,                   ///< Combined image (output)
+    psArray **questionablePixels,       ///< Array of rejection masks
+    const psArray *images,              ///< Array of input images
+    const psArray *errors,              ///< Array of input error images
+    const psArray *masks,               ///< Array of input masks
+    psU32 maskVal,                      ///< Mask value
+    const psPixels *pixels,             ///< Pixels to combine
+    psS32 numIter,                      ///< Number of rejection iterations
+    psF32 sigmaClip                     ///< Number of standard deviations at which to reject
+)
+{
+    psTrace("psModules.imcombine", 3, "Calling pmCombineImages(%ld)\n", images->n);
+
+    PS_ASSERT_ARRAY_NON_NULL(images, NULL);
+    PS_ASSERT_INT_POSITIVE(images->n, NULL);
+    long numImages = images->n;          // Number of images
+    int numCols = ((psImage*)images->data[0])->numCols; // Size in x
+    int numRows = ((psImage*)images->data[0])->numRows; // Size in y
+
+    if (combine) {
+        PS_ASSERT_IMAGE_NON_NULL(combine, NULL);
+        PS_ASSERT_IMAGE_SIZE(combine, numCols, numRows, NULL);
+    }
+    if (questionablePixels && !*questionablePixels) {
+        PS_ASSERT_ARRAY_NON_NULL(*questionablePixels, NULL);
+        PS_ASSERT_ARRAY_SIZE(*questionablePixels, numImages, 0);
+    }
+    for (int i = 1; i < images->n; i++) {
+        psImage *image = images->data[i]; // Image of interest
+        PS_ASSERT_IMAGE_TYPE(image, PS_TYPE_F32, NULL);
+        PS_ASSERT_IMAGE_SIZE(image, numCols, numRows, NULL);
+    }
+    if (errors) {
+        PS_ASSERT_ARRAYS_SIZE_EQUAL(images, errors, NULL);
+        for (int i = 0; i < images->n; i++) {
+            psImage *error = errors->data[i];
+            PS_ASSERT_IMAGE_SIZE(error, numCols, numRows, NULL);
+            PS_ASSERT_IMAGE_TYPE(error, PS_TYPE_F32, NULL);
+        }
+    }
+    if (masks) {
+        PS_ASSERT_ARRAYS_SIZE_EQUAL(images, masks, NULL);
+        for (int i = 0; i < images->n; i++) {
+            psImage *mask  = masks->data[i];
+            PS_ASSERT_IMAGE_SIZE(mask, numCols, numRows, NULL);
+            PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, NULL);
+        }
+    }
+    PS_ASSERT_INT_POSITIVE(numIter, NULL);
+    PS_ASSERT_FLOAT_LARGER_THAN(sigmaClip, 0.0, NULL);
+
+    // Allocate and initialize the combined image, if necessary.
+    if (!combine) {
+        combine = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+        if (pixels) {
+            // Set everything we're not working on to NAN
+            psImageInit(combine, NAN);
+        }
+    }
+
+    //
+    // Allocate the questionablePixels psArray, if necesssary, then create a psPixels
+    // struct for each image.
+    //
+    if (questionablePixels) {
+        if (*questionablePixels == NULL) {
+            *questionablePixels = psArrayAlloc(numImages);
+        } else if ((*questionablePixels)->n != numImages) {
+            *questionablePixels = psArrayRealloc(*questionablePixels, numImages);
+        }
+        for (int i = 0; i < numImages; i++) {
+            psFree((*questionablePixels)->data[i]);
+            (*questionablePixels)->data[i] = psPixelsAlloc(PIXEL_LIST_BUFFER);
+        }
+    }
+
+    combineBuffer *buffer = combineBufferAlloc(numImages); // Buffer for combination
+
+    if (pixels) {
+        // Only those specified pixels should be combined.
+
+        for (int p = 0; p < pixels->n; p++) {
+            int x = pixels->data[p].x; // Column of interest
+            int y = pixels->data[p].y; // Row of interest
+
+            if (!combinePixels(combine, questionablePixels ? *questionablePixels : NULL, x, y,
+                               images, errors, masks, maskVal, numIter, sigmaClip, buffer)) {
+                // Bad pixel --- no big deal
+                psErrorClear();
+            }
+        }
+    } else {
+        //
+        // We get here if there is a NULL list of pixels to combine.
+        // Therefore, we combine all pixels in all images.
+        //
+
+        //
+        // Loop over all pixels in all images, set the appropriate data, mask,
+        // error vectors, call psVectorStats(), and set the result in the
+        // combine image.
+        //
+        for (int y = 0; y < numRows; y++) {
+            for (int x = 0; x < numCols; x++) {
+                if (!combinePixels(combine, questionablePixels ? *questionablePixels : NULL, x, y,
+                                   images, errors, masks, maskVal, numIter, sigmaClip, buffer)) {
+                    // Bad pixel --- no big deal
+                    psErrorClear();
+                }
+            }
+        }
+    }
+
+    psFree(buffer);
+
+    psTrace("psModules.imcombine", 3, "Exiting pmCombineImages(%ld)\n", images->n);
+    return combine;
+}
+
+
+/******************************************************************************
+XXX: Directly from Paul Price
+ *****************************************************************************/
+static psF32 CalcGradient(
+    psImage *image,
+    psImage *imageMask,
+    psS32 x,
+    psS32 y
+)
+{
+    psTrace("psModules.imcombine", 4, "Calling CalcGradient(%d, %d)\n", x, y);
+    int num = 0;
+    psVector *pixels = psVectorAlloc(8, PS_TYPE_F32); // Array of pixels
+    psVector *mask = psVectorAlloc(8, PS_TYPE_U8); // Corresponding mask
+
+    // Get limits
+    int xMin = PS_MAX(x - 1, 0);
+    int xMax = PS_MIN(x + 1, image->numCols - 1);
+    int yMin = PS_MAX(y - 1, 0);
+    int yMax = PS_MIN(y + 1, image->numRows - 1);
+    if (imageMask != NULL) {
+        for (int j = yMin; j <= yMax; j++) {
+            for (int i = xMin; i <= xMax; i++) {
+                if ((i != x) && (j != y) && (0 == imageMask->data.U8[j][i])) {
+                    pixels->data.F32[num] = image->data.F32[j][i];
+                    mask->data.U8[num] = 0;
+                    num++;
+                } else {
+                    mask->data.U8[num] = 1;
+                }
+            }
+        }
+    } else {
+        //
+        // This code is simply the previous loop without the imageMask.
+        // XXX: Consider restructuring this.
+        //
+        for (int j = yMin; j <= yMax; j++) {
+            for (int i = xMin; i <= xMax; i++) {
+                if ((i != x) && (j != y)) {
+                    pixels->data.F32[num] = image->data.F32[j][i];
+                    mask->data.U8[num] = 0;
+                    num++;
+                } else {
+                    mask->data.U8[num] = 1;
+                }
+            }
+        }
+    }
+
+    pixels->n = num;
+    mask->n = num;
+
+    // Get the median
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEDIAN);
+    psVectorStats(stats, pixels, NULL, mask, 1);
+    float median = stats->sampleMedian;
+    psFree(stats);
+    psFree(pixels);
+    psFree(mask);
+
+    psTrace("psModules.imcombine", 4, "Exiting CalcGradient(%d, %d)\n", x, y);
+    return(median / image->data.F32[y][x]);
+}
+
+/******************************************************************************
+DetermineRegion(image, myOutToIn): for a psImage and a psPlaneTransform to that
+image, this routine determines the size of the input image which maps to that
+image, and returns the result in a psRegion struct.
+
+XXX: Basically, this routine is only guaranteed to work if the transform is
+linear.
+
+XXX: Shouldn't this functionality be part of psImageTransform()?
+ *****************************************************************************/
+static psRegion DetermineRegion(psImage *image,
+                                psPlaneTransform *myOutToIn)
+{
+    psTrace("psModules.imcombine", 4, "Calling DetermineRegion()\n");
+    psRegion myRegion;
+    myRegion.x0 = PS_MAX_F32;
+    myRegion.x1 = PS_MIN_F32;
+    myRegion.y0 = PS_MAX_F32;
+    myRegion.y1 = PS_MIN_F32;
+    psPlane in;
+    psPlane out;
+
+    in.x = 0.0;
+    in.y = 0.0;
+
+    psPlaneTransformApply(&out, myOutToIn, &in);
+    if (out.x < myRegion.x0) {
+        myRegion.x0 = out.x;
+    }
+    if (out.x > myRegion.x1) {
+        myRegion.x1 = out.x;
+    }
+    if (out.y < myRegion.y0) {
+        myRegion.y0 = out.y;
+    }
+    if (out.y > myRegion.y1) {
+        myRegion.y1 = out.y;
+    }
+
+    in.x = (psF32) (image->numCols);
+    in.y = 0.0;
+    psPlaneTransformApply(&out, myOutToIn, &in);
+    if (out.x < myRegion.x0) {
+        myRegion.x0 = out.x;
+    }
+    if (out.x > myRegion.x1) {
+        myRegion.x1 = out.x;
+    }
+    if (out.y < myRegion.y0) {
+        myRegion.y0 = out.y;
+    }
+    if (out.y > myRegion.y1) {
+        myRegion.y1 = out.y;
+    }
+
+    in.x = (psF32) (image->numCols);
+    ;
+    in.y = 0.0;
+    psPlaneTransformApply(&out, myOutToIn, &in);
+    if (out.x < myRegion.x0) {
+        myRegion.x0 = out.x;
+    }
+    if (out.x > myRegion.x1) {
+        myRegion.x1 = out.x;
+    }
+    if (out.y < myRegion.y0) {
+        myRegion.y0 = out.y;
+    }
+    if (out.y > myRegion.y1) {
+        myRegion.y1 = out.y;
+    }
+
+    in.x = (psF32) (image->numCols);
+    in.y = (psF32) (image->numRows);
+    psPlaneTransformApply(&out, myOutToIn, &in);
+    if (out.x < myRegion.x0) {
+        myRegion.x0 = out.x;
+    }
+    if (out.x > myRegion.x1) {
+        myRegion.x1 = out.x;
+    }
+    if (out.y < myRegion.y0) {
+        myRegion.y0 = out.y;
+    }
+    if (out.y > myRegion.y1) {
+        myRegion.y1 = out.y;
+    }
+
+    psTrace("psModules.imcombine", 4, "Exiting DetermineRegion()\n");
+    return(myRegion);
+}
+
+/******************************************************************************
+XXX: Don't we have a psLib function for this?
+ *****************************************************************************/
+static psImage *ImageConvertF32(psImage *image)
+{
+    psTrace("psModules.imcombine", 4, "Calling ImageConvertF32()\n");
+    psImage *imgF32 = psImageAlloc(image->numCols, image->numRows, PS_TYPE_F32);
+
+    for (psS32 i = 0 ; i < image->numRows ; i++) {
+        for (psS32 j = 0 ; j < image->numCols ; j++) {
+            imgF32->data.F32[i][j] = (psF32) image->data.U8[i][j];
+        }
+    }
+
+    psTrace("psModules.imcombine", 4, "Exiting ImageConvertF32()\n");
+    return(imgF32);
+}
+
+
+//
+// The following macros define how big the initial pixel list will be, and
+// how much it should be incremented when realloc'ed.
+//
+#define PS_REJECT_PIXEL_INITIAL_PIXEL_LIST_LENGTH 100
+#define PS_REJECT_PIXEL_INITIAL_PIXEL_LIST_LENGTH_INC 100
+/******************************************************************************
+pmRejectPixels(images, errors, inToOut, outToIn, rejThreshold,
+gradLimit)
+
+XXX: Optimization: we don't need to transform the entire mask image.
+XXX: The inToOut and outToIn transforms are confusing.  Verify that what
+     I think they mean syncs with PWP.
+ *****************************************************************************/
+psArray *pmRejectPixels(
+    const psArray *images,              ///< Array of input images
+    const psArray *masks,               ///< Array of input image masks
+    const psArray *errors,              ///< The pixels which were rejected in the combination
+    const psArray *inToOut,             ///< Transformation from input to output system
+    const psArray *outToIn,             ///< Transformation from output to input system
+    psF32 rejThreshold,                 ///< Rejection threshold
+    psF32 gradLimit                     ///< Gradient limit
+)
+{
+    psTrace("psModules.imcombine", 3, "Calling pmRejectPixels()\n");
+    PS_ASSERT_PTR_NON_NULL(images, NULL);
+    for (psS32 im = 0 ; im < images->n ; im++) {
+        psImage *tmpImage = (psImage *) images->data[im];
+        PS_ASSERT_IMAGE_NON_NULL(tmpImage, NULL);
+        PS_ASSERT_IMAGE_NON_EMPTY(tmpImage, NULL);
+        PS_ASSERT_IMAGE_TYPE(tmpImage, PS_TYPE_F32, NULL);
+        if (masks != NULL) {
+            PS_ASSERT_INT_EQUAL(images->n, masks->n, NULL);
+            psImage *tmpMask = (psImage *) masks->data[im];
+            PS_ASSERT_IMAGE_NON_NULL(tmpMask, NULL);
+            PS_ASSERT_IMAGE_NON_EMPTY(tmpMask, NULL);
+            PS_ASSERT_IMAGE_TYPE(tmpMask, PS_TYPE_F32, NULL);
+            PS_ASSERT_IMAGES_SIZE_EQUAL(tmpImage, tmpMask, NULL);
+        }
+        PS_ASSERT_IMAGES_SIZE_EQUAL(((psImage *) images->data[0]), tmpImage, NULL);
+    }
+    PS_ASSERT_PTR_NON_NULL(errors, NULL);
+    PS_ASSERT_PTR_NON_NULL(inToOut, NULL);
+    PS_ASSERT_PTR_NON_NULL(outToIn, NULL);
+    // Ensure that the psArray parameters have an element for each image.
+    psS32 numImages = images->n;
+    PS_ASSERT_INT_EQUAL(numImages, errors->n, NULL);
+    PS_ASSERT_INT_EQUAL(numImages, inToOut->n, NULL);
+    PS_ASSERT_INT_EQUAL(numImages, outToIn->n, NULL);
+
+    //
+    // Create the psArray of psPixelLists, one for each image, for rejected pixels.
+    //
+    psArray *rejects = psArrayAlloc(numImages);
+    for (psS32 im = 0 ; im < numImages ; im++) {
+        rejects->data[im] = (psPtr *) psPixelsAlloc(PS_REJECT_PIXEL_INITIAL_PIXEL_LIST_LENGTH);
+        ((psPixels *)(rejects->data[im]))->n = ((psPixels *)(rejects->data[im]))->nalloc;
+        psPixels *pixels = (psPixels *) rejects->data[im];
+        pixels->n = 0;
+    }
+    //
+    // rPtr is used to maintain a count of the questionable pixels for each image.
+    //
+    psVector *rPtr = psVectorAlloc(numImages, PS_TYPE_S32);
+    psVectorInit(rPtr, 0);
+
+    psS32 numCols = ((psImage *) images->data[0])->numCols;
+    psS32 numRows = ((psImage *) images->data[0])->numRows;
+    psRegion myRegion = psRegionSet(0, numCols-1, 0, numRows-1);
+    psU32 maskVal = 1;  // XXX: Is this appropriate?
+
+    psPlane *inCoords = psAlloc(sizeof(psPlane));
+    psPlane *outCoords = psAlloc(sizeof(psPlane));
+
+    for (psS32 im = 0 ; im < numImages ; im++) {
+        //
+        // Extract data from psArrays.
+        //
+        psPixels *pixelList = (psPixels *) errors->data[im];
+
+        psImage *currImage = (psImage *) images->data[im];
+        myRegion.x0 = 0;
+        myRegion.x1 = currImage->numCols;
+        myRegion.y0 = 0;
+        myRegion.y1 = currImage->numRows;
+        psPlaneTransform *myInToOut = (psPlaneTransform *) inToOut->data[im];
+        psPlaneTransform *myOutToIn = (psPlaneTransform *) outToIn->data[im];
+
+        //
+        // Create a psU8 mask image from the list of cosmic pixels.
+        //
+        psImage *maskImage = NULL;
+        maskImage = psPixelsToMask(maskImage, pixelList, myRegion, maskVal);
+        psImage *maskImageF32 = ImageConvertF32(maskImage);
+
+        //
+        // Transform that mask image into detector coordinate space
+        //
+        psRegion myRegionXForm = DetermineRegion(maskImageF32, myOutToIn);
+        psImage *transformedImage = psImageTransform(NULL, NULL, maskImageF32, NULL,
+                                    0, myOutToIn, myRegionXForm, NULL,
+                                    PS_INTERPOLATE_BILINEAR, 0);
+
+        //
+        // Loop over all cosmic pixels.  Transform their coords to detector space.
+        // If the value of the transformed mask is larger than rejThreshold, then
+        // this might be a cosmic ray pixel.  We then calculate the mean gradient
+        // in other images.
+        //
+
+        psImageInterpolateOptions *interp = psImageInterpolateOptionsAlloc(PS_INTERPOLATE_BILINEAR,
+                                                                           transformedImage, NULL, NULL,
+                                                                           0, 0.0, 0.0, 0, 0, 0.0);
+
+        for (psS32 p = 0 ; p < pixelList->n ; p++) {
+            inCoords->x = 0.5 + (psF32) (pixelList->data[p]).x;
+            inCoords->y = 0.5 + (psF32) (pixelList->data[p]).y;
+            psPlaneTransformApply(outCoords, myInToOut, inCoords);
+            double maskVal;
+            if (!psImageInterpolate(&maskVal, NULL, NULL, outCoords->x, outCoords->y, interp)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to interpolate image.");
+                psFree(interp);
+                psFree(maskImage);
+                psFree(maskImageF32);
+                psFree(transformedImage);
+                psFree(inCoords);
+                psFree(outCoords);
+                psFree(rejects);
+                return NULL;
+            }
+            if (maskVal > rejThreshold) {
+
+                // This is a possible cosmic array pixel.  We must calculate the gradient
+                // at this location in all input images.
+                psF32 meanGrads = 0.0;
+                psS32 numGrads = 0;
+                //
+                // Loop through all other images, calculate their mean gradient.
+                //
+                for (psS32 otherImg = 0 ; otherImg < numImages ; otherImg++) {
+                    if (im != otherImg) {
+                        // Map the outCoords to inCoords that for otherImg space.
+                        psImage *tmpMask = NULL;
+                        if (masks != NULL) {
+                            tmpMask = masks->data[otherImg];
+                        }
+                        psPlaneTransformApply(inCoords,
+                                              (psPlaneTransform * )outToIn->data[otherImg],
+                                              outCoords);
+                        psS32 xPix = (int)(inCoords->x + 0.5);
+                        psS32 yPix = (int)(inCoords->y + 0.5);
+                        if ((xPix >= 0) && (xPix <= ((psImage*)(images->data[otherImg]))->numCols - 1) &&
+                                (yPix >= 0) && (yPix <= ((psImage*)(images->data[otherImg]))->numRows - 1)) {
+                            meanGrads += CalcGradient(images->data[otherImg], tmpMask, xPix, yPix);
+                            numGrads++;
+                        }
+                    }
+                }
+                if (numGrads > 0) {
+                    meanGrads /= (psF32) numGrads;
+                } else {
+                    // XXX: my idea.  Verify with PWP:
+                    meanGrads = 1.0 + gradLimit;
+                }
+
+                // XXX: The SDRS and the prototype code differ significantly here:
+                // if (CalcGradient(inputs->data[i], pixelList->data.x, pixelList->data.y) < (gradLimit * meanGrads)) {
+                if (meanGrads < gradLimit) {
+                    //
+                    // Add this to the list of questionable pixels.  We must ensure that the
+                    // pixelList is large enough; if not, we realloc()
+                    //
+                    psS32 ptr = rPtr->data.S32[im];
+                    psPixels *pixelListPtr = (psPixels *) rejects->data[im];
+                    if (ptr >= pixelListPtr->nalloc) {
+                        rejects->data[im] = (psPtr *) psPixelsRealloc(((psPixels *) rejects->data[im]),
+                                            ((((psPixels *) rejects->data[im])->nalloc) + PS_REJECT_PIXEL_INITIAL_PIXEL_LIST_LENGTH_INC));
+                        // XXX: Can the realloc() fail?  Must we check for NULL?
+                    }
+
+                    ((psPixels *) rejects->data[im])->data[ptr].x = (pixelList->data[p]).x;
+                    ((psPixels *) rejects->data[im])->data[ptr].y = (pixelList->data[p]).y;
+                    (rPtr->data.S32[im])++;
+                    // XXX: this pixel ->n increment is wierd
+                    (((psPixels *) rejects->data[im])->n)++;
+                }
+            }
+        }
+
+        psFree(interp);
+        psFree(maskImage);
+        psFree(maskImageF32);
+        psFree(transformedImage);
+    }
+
+    psFree(inCoords);
+    psFree(outCoords);
+    psTrace("psModules.imcombine", 3, "Exiting pmRejectPixels()\n");
+    return(rejects);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmImageCombine.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmImageCombine.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmImageCombine.h	(revision 22158)
@@ -0,0 +1,44 @@
+/* @file  pmImageCombine.h
+ *
+ * This file will perform image combination of several images of the
+ * same field, produce a list of questionable pixels, then tag some
+ * of those pixels as cosmic rays.
+ *
+ * @author Paul Price, IfA (original prototype)
+ * @author GLG, MHPCC
+ *
+ * @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-03-30 21:12:56 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PM_IMAGE_COMBINE_H
+#define PM_IMAGE_COMBINE_H
+
+/// @addtogroup imcombine Image Combinations
+/// @{
+
+psImage *pmCombineImages(
+    psImage *combine,                   ///< Combined image (output)
+    psArray **questionablePixels,       ///< Array of rejection masks
+    const psArray *images,              ///< Array of input images
+    const psArray *errors,              ///< Array of input error images
+    const psArray *masks,               ///< Array of input masks
+    psU32 maskVal,                      ///< Mask value
+    const psPixels *pixels,             ///< Pixels to combine
+    psS32 numIter,                      ///< Number of rejection iterations
+    psF32 sigmaClip                     ///< Number of standard deviations at which to reject
+);
+
+psArray *pmRejectPixels(
+    const psArray *images,              ///< Array of input images
+    const psArray *masks,               ///< Array of input image masks
+    const psArray *errors,              ///< The pixels which were rejected in the combination
+    const psArray *inToOut,             ///< Transformation from input to output system
+    const psArray *outToIn,             ///< Transformation from output to input system
+    psF32 rejThreshold,                 ///< Rejection threshold
+    psF32 gradLimit                     ///< Gradient limit
+);
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmPSFEnvelope.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmPSFEnvelope.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmPSFEnvelope.c	(revision 22158)
@@ -0,0 +1,313 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmReadoutFake.h"
+
+#include "pmMoments.h"
+#include "pmResiduals.h"
+#include "pmGrowthCurve.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmModelClass.h"
+#include "pmModelUtils.h"
+#include "pmPeaks.h"
+#include "pmSource.h"
+#include "pmSourceUtils.h"
+#include "pmSourceFitModel.h"
+#include "pmPSFtry.h"
+
+
+#include "pmPSFEnvelope.h"
+
+
+
+//#define TESTING                         // Enable test output
+#define PEAK_FLUX 1.0e4                 // Peak flux for each source
+#define SKY_VALUE 0.0e0                 // Sky value for fake image
+#define WEIGHT_VAL 3.0                  // Weighting for image
+#define WEIGHT_FACTOR 10.0              // Factor to multiply image by to get weighting
+#define PSF_STATS PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV // Statistics options for measuring PSF
+
+
+
+// XXX To do:
+//
+// * PSF variation when only a portion of the image is present (e.g., the edge of an FPA overlapping a
+// skycell) may mean a disastrously weird PSF in the missing regions.  To counter this, get a region of
+// validity for each PSF (perhaps from an associated mask, or have the user work it out), and taper the PSF
+// when outside this region (perhaps multiply the peak flux by a Gaussian whose arguments are the distance
+// from the valid region, and a width that the user supplies).
+
+
+// We deliberately do not include the calculation of and storing of residuals (data - model) for the PSF
+// model, because (1) there is no code in psModules to do this, and we're not going to implement it here; and
+// (2) this is intended to generate "nice" or "ideal" PSFs to feed into pmSubtraction (PSF matching code), so
+// any residuals will hopefully be dealt with by that.
+
+
+pmPSF *pmPSFEnvelope(int numCols, int numRows, // Size of original image
+                     const psArray *inputs, // Input PSF models
+                     int instances, // Number of instances per dimension
+                     int radius,        // Radius of each PSF
+                     const char *modelName,// Name of PSF model to use
+                     int xOrder, int yOrder // Order for PSF variation fit
+                     )
+{
+    PS_ASSERT_INT_POSITIVE(numCols, NULL);
+    PS_ASSERT_INT_POSITIVE(numRows, NULL);
+    PS_ASSERT_ARRAY_NON_NULL(inputs, NULL);
+    PS_ASSERT_INT_POSITIVE(instances, NULL);
+    PS_ASSERT_INT_POSITIVE(radius, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(modelName, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(xOrder, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(yOrder, NULL);
+
+    float xOrigSpacing = (float)(numCols - 2 * radius) / (float)(instances - 1); // Spacing between instances
+    float yOrigSpacing = (float)(numRows - 2 * radius) / (float)(instances - 1); // Spacing between instances
+    int fakeSpacing = 2 * radius + 1;   // Spacing between instances (x and y) in the fake image
+    int fakeSize = instances * fakeSpacing; // Size of fake image
+
+    // Generate list of fake sources (instances of the PSF)
+    int numFakes = PS_SQR(instances);   // Number of fake sources
+    psArray *fakes = psArrayAlloc(numFakes); // Fake sources
+    psVector *xOffset = psVectorAlloc(numFakes, PS_TYPE_S32); // X offset from fake position to image
+    psVector *yOffset = psVectorAlloc(numFakes, PS_TYPE_S32); // Y offset from fake position to image
+    for (int j = 0, index = 0; j < instances; j++) {
+        float yOrig = j * yOrigSpacing + radius; // Source position in original image
+        float yFake = j * fakeSpacing + radius; // Position in fake image
+        int dy = yFake - yOrig;         // Difference between fake and original position
+
+        for (int i = 0; i < instances; i++, index++) {
+            float xOrig = i * xOrigSpacing + radius; // Source position in original image
+            float xFake = i * fakeSpacing + radius; // Position in fake image
+            int dx = xFake - xOrig;     // Difference between fake and original position
+
+            pmSource *fake = pmSourceAlloc(); // Fake source
+            fake->peak = pmPeakAlloc(xFake - dx, yFake - dy, PEAK_FLUX, PM_PEAK_LONE);
+            fake->type = PM_SOURCE_TYPE_STAR;
+            fake->psfMag = -2.5 * log10(PEAK_FLUX);
+
+            psTrace("psModules.imcombine", 5, "Source %d: %.2f,%.2f\n",
+                    index, xOrig, yOrig);
+
+            fakes->data[index] = fake;
+            xOffset->data.S32[index] = dx;
+            yOffset->data.S32[index] = dy;
+        }
+    }
+
+    // Generate fake images with each PSF, and take the envelope
+    psImage *envelope = psImageAlloc(fakeSize, fakeSize, PS_TYPE_F32); // Image with envelope of PSFs
+    psImageInit(envelope, SKY_VALUE);
+    pmReadout *fakeRO = pmReadoutAlloc(NULL); // Fake readout
+    for (int i = 0; i < inputs->n; i++) {
+        pmPSF *psf = inputs->data[i];   // PSF of interest
+        pmResiduals *resid = psf->residuals;// PSF residuals
+        psf->residuals = NULL;
+        if (!pmReadoutFakeFromSources(fakeRO, fakeSize, fakeSize, fakes, xOffset, yOffset, psf,
+                                      NAN, radius, true)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to generate fake readout.");
+            psFree(envelope);
+            psFree(yOffset);
+            psFree(xOffset);
+            psFree(fakes);
+            psf->residuals = resid;
+            return NULL;
+        }
+        psf->residuals = resid;
+
+        // Need to renormalise sources so they all have the same peak.  You would think they do have the same
+        // peak already, but it seems that the residual map messes things up by adding extra flux
+        for (int j = 0; j < numFakes; j++) {
+            pmSource *source = fakes->data[j]; // Fake source
+            float x = source->peak->xf + xOffset->data.S32[j]; // x coordinate of source
+            float y = source->peak->yf + yOffset->data.S32[j]; // y coordinate of source
+
+            double flux = fakeRO->image->data.F32[(int)y][(int)x];
+            float norm = PEAK_FLUX / flux; // Normalisation for source
+            psRegion region = psRegionSet(x - radius, x + radius, y - radius, y + radius); // PSF region
+            psImage *subImage = psImageSubset(fakeRO->image, region); // Subimage of fake PSF
+            psImage *subEnv = psImageSubset(envelope, region); // Subimage of envelope
+            psBinaryOp(subImage, subImage, "*", psScalarAlloc(norm, PS_TYPE_F32));
+            psBinaryOp(subEnv, subEnv, "MAX", subImage);
+            psFree(subImage);
+            psFree(subEnv);
+        }
+
+#ifdef TESTING
+        {
+            // Write out the PSF field
+            psString name = NULL;
+            psStringAppend(&name, "psf_field_%03d.fits", i);
+            psFits *fits = psFitsOpen(name, "w");
+            psFitsWriteImage(fits, NULL, fakeRO->image, 0, NULL);
+            psFitsClose(fits);
+            psFree(name);
+        }
+#endif
+
+    }
+    psFree(fakeRO);
+
+#ifdef TESTING
+    {
+        // Write out the envelope
+        psFits *fits = psFitsOpen("psf_field_envelope.fits", "w");
+        psFitsWriteImage(fits, NULL, envelope, 0, NULL);
+        psFitsClose(fits);
+    }
+#endif
+
+    // Put the fake sources onto a full-size image
+    pmReadout *readout = pmReadoutAlloc(NULL); // Readout to contain envelope pixels
+    readout->image = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    psImageInit(readout->image, 0.0);
+    for (int i = 0; i < numFakes; i++) {
+        pmSource *source = fakes->data[i]; // Fake source
+        // Position of source on fake image
+        int xFake = source->peak->x + xOffset->data.S32[i];
+        int yFake = source->peak->y + yOffset->data.S32[i];
+        psRegion region = psRegionSet(xFake - radius, xFake + radius,
+                                      yFake - radius, yFake + radius); // PSF region
+        psImage *subImage = psImageSubset(envelope, region); // Subimage of fake PSF
+
+        // Position of source on "real" image
+        int x0 = source->peak->x - radius;
+        int y0 = source->peak->y - radius;
+
+        if (!psImageOverlaySection(readout->image, subImage, x0, y0, "=")) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to overlay PSF");
+            psFree(subImage);
+            psFree(readout);
+            psFree(xOffset);
+            psFree(yOffset);
+            psFree(fakes);
+            return NULL;
+        }
+        psFree(subImage);
+    }
+    psFree(xOffset);
+    psFree(yOffset);
+    psFree(envelope);
+
+    // XXX Setting the weight seems to be an art
+    // Can't set it too high so that pixels are rejected as insignificant
+    // Can't set it too low so that it's hard to get to the minimum
+    // Have also tried:
+    // *** readout->weight = (psImage*)psBinaryOp(NULL, readout->image, "*", readout->image);
+    // *** readout->weight = (psImage*)psBinaryOp(NULL, readout->image, "*", psScalarAlloc(WEIGHT_FACTOR, PS_TYPE_F32));
+    readout->weight = (psImage*)psBinaryOp(NULL, readout->image, "+", psScalarAlloc(PS_SQR(WEIGHT_VAL), PS_TYPE_F32));
+    readout->mask = psImageAlloc(numCols, numRows, PS_TYPE_MASK);
+    psImageInit(readout->mask, 0);
+
+#ifdef TESTING
+    {
+        // Write out the envelope
+        psFits *fits = psFitsOpen("psf_field_full.fits", "w");
+        psFitsWriteImage(fits, NULL, readout->image, 0, NULL);
+        psFitsClose(fits);
+    }
+#endif
+
+    // Reset the sources to point to the new pixels, and measure the moments in preparation for PSF fitting
+    for (int i = 0; i < numFakes; i++) {
+        pmSource *source = fakes->data[i]; // Fake source
+        float x = source->peak->xf;     // x coordinates of source
+        float y = source->peak->yf;     // y coordinates of source
+
+        psFree(source->pixels);
+        psFree(source->weight);
+        psFree(source->maskView);
+        psFree(source->maskObj);
+        source->pixels = NULL;
+        source->weight = NULL;
+        source->maskView = NULL;
+        source->maskObj = NULL;
+
+        if (!pmSourceDefinePixels(source, readout, x, y, (float)radius)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to define pixels for source.");
+            psFree(readout);
+            psFree(fakes);
+            return NULL;
+        }
+
+        if (!pmSourceMoments(source, radius)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to measure moments for source.");
+            psFree(readout);
+            psFree(fakes);
+            return NULL;
+        }
+    }
+
+    // Don't assume Poisson errors
+    pmPSFOptions *options = pmPSFOptionsAlloc(); // Options for fitting a PSF
+    options->poissonErrorsPhotLMM = true;
+    options->poissonErrorsPhotLin = false;
+    options->poissonErrorsParams = true;
+    options->stats = psStatsAlloc(PSF_STATS);
+    options->radius = radius;
+    options->psfTrendMode = PM_TREND_MAP;
+    options->psfTrendNx = xOrder;
+    options->psfTrendNy = yOrder;
+    options->psfFieldNx = numCols;
+    options->psfFieldNy = numRows;
+    options->psfFieldXo = 0;
+    options->psfFieldYo = 0;
+
+    pmSourceFitModelInit(50, 0.01, WEIGHT_VAL, true);
+
+    pmPSFtry *try = pmPSFtryModel(fakes, modelName, options, 0, 0xff);
+    psFree(options);
+    if (!try) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to fit PSF model to PSF envelope.");
+        psFree(readout);
+        psFree(fakes);
+        return NULL;
+    }
+
+    pmPSF *psf = psMemIncrRefCounter(try->psf); // Output PSF
+    psFree(try);
+
+#ifdef TESTING
+    {
+        // Need to translate peak flux --> integrated flux
+        pmModel *fakeModel = pmModelFromPSFforXY(psf, (float)numCols / 2.0, (float)numRows / 2.0,
+                                                 1.0); // Fake model, with central intensity of 1.0
+        float flux0 = fakeModel->modelFlux(fakeModel->params); // Flux for central intensity of 1.0
+        for (int i = 0; i < numFakes; i++) {
+            pmSource *source = fakes->data[i]; // Fake source
+            source->psfMag -= 2.5 * log10(flux0);
+        }
+
+        pmReadout *generated = pmReadoutAlloc(NULL); // Generated image
+        pmReadoutFakeFromSources(generated, numCols, numRows, fakes, NULL, NULL, psf, NAN, radius,
+                                 false);
+        {
+            psFits *fits = psFitsOpen("psf_field_model.fits", "w");
+            psFitsWriteImage(fits, NULL, generated->image, 0, NULL);
+            psFitsClose(fits);
+        }
+        psBinaryOp(generated->image, generated->image, "-", readout->image);
+        {
+            psFits *fits = psFitsOpen("psf_field_resid.fits", "w");
+            psFitsWriteImage(fits, NULL, generated->image, 0, NULL);
+            psFitsClose(fits);
+        }
+        psFree(generated);
+    }
+#endif
+
+    psFree(fakes);
+    psFree(readout);
+
+    return psf;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmPSFEnvelope.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmPSFEnvelope.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmPSFEnvelope.h	(revision 22158)
@@ -0,0 +1,22 @@
+#ifndef PM_PSF_ENVELOPE_H
+#define PM_PSF_ENVELOPE_H
+
+#include <pslib.h>
+#include <pmMoments.h>
+#include <pmResiduals.h>
+#include <pmGrowthCurve.h>
+#include <pmTrend2D.h>
+#include <pmPSF.h>
+
+/// Generate a PSF which is the envelope of an array of PSFs
+///
+/// Generates multiple instances of the PSFs (distributed over an image)
+pmPSF *pmPSFEnvelope(int numCols, int numRows, // Size of original image
+                     const psArray *inputs, // Input PSF models
+                     int instances,     // Number of instances per dimension
+                     int radius,        // Radius of each PSF
+                     const char *modelName, // Name of PSF model to use
+                     int xOrder, int yOrder // Order for PSF variation
+    );
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmReadoutCombine.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmReadoutCombine.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmReadoutCombine.c	(revision 22158)
@@ -0,0 +1,417 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmHDUUtils.h"
+#include "pmFPAMaskWeight.h"
+#include "pmConceptsAverage.h"
+#include "pmReadoutStack.h"
+
+#include "pmReadoutCombine.h"
+
+//#define SHOW_BUSY 1                   // Show that the function is busy
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Allocator for pmCombineParams
+pmCombineParams *pmCombineParamsAlloc(psStatsOptions combine)
+{
+    pmCombineParams *params = psAlloc(sizeof(pmCombineParams));
+
+    params->combine = combine;
+    params->maskVal = 0;
+    params->blank = 0;
+    params->nKeep = 0;
+    params->fracHigh = 0.0;
+    params->fracHigh = 0.0;
+    params->iter = 1;
+    params->rej = INFINITY;
+    params->weights = false;
+
+    return params;
+}
+
+// check the input parameters and set up the output images
+bool pmReadoutCombinePrepare(pmReadout *output, const psArray *inputs, const pmCombineParams *params)
+{
+    // Check inputs
+    PS_ASSERT_PTR_NON_NULL(output, false);
+    PS_ASSERT_ARRAY_NON_NULL(inputs, false);
+    PS_ASSERT_PTR_NON_NULL(params, false);
+    PS_ASSERT_FLOAT_WITHIN_RANGE(params->fracLow, 0.0, 1.0, false);
+    PS_ASSERT_FLOAT_WITHIN_RANGE(params->fracHigh, 0.0, 1.0, false);
+
+    // valid combintion statistic?
+    bool valid = false;
+    valid |= (params->combine == PS_STAT_SAMPLE_MEAN);
+    valid |= (params->combine == PS_STAT_SAMPLE_MEDIAN);
+    valid |= (params->combine == PS_STAT_ROBUST_MEDIAN);
+    valid |= (params->combine == PS_STAT_FITTED_MEAN);
+    valid |= (params->combine == PS_STAT_CLIPPED_MEAN);
+    if (!valid) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Combination method is not SAMPLE_MEAN, SAMPLE_MEDIAN, "
+                "ROBUST_MEDIAN, FITTED_MEAN or CLIPPED_MEAN.\n");
+        return false;
+    }
+
+    // weights exist if weights desired?
+    for (int i = 0; i < inputs->n; i++) {
+        pmReadout *readout = inputs->data[i]; // Readout of interest
+        if (params->weights && !readout->weight) {
+            psError(PS_ERR_UNEXPECTED_NULL, true,
+                    "Rejection based on weights requested, but no weights supplied for image %d.\n", i);
+            return false;
+        }
+    }
+
+    pmHDU *hdu = pmHDUFromReadout(output); // Output HDU
+    if (!hdu) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find HDU for readout.\n");
+        return false;
+    }
+
+    //  set the output header metadata
+    psString comment = NULL;        // Comment to add to header
+    psStringAppend(&comment, "Combining using statistic: %x", params->combine);
+    if (!hdu->header) {
+	hdu->header = psMetadataAlloc();
+    }
+    psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, comment, "");
+    psFree(comment);
+
+    // note the clipping parameters, if used
+    if (params->combine == PS_STAT_CLIPPED_MEAN) {
+	psString comment = NULL;    // Comment to add to header
+	psStringAppend(&comment, "Combination clipping: %d iterations, rejection at %f sigma", params->iter, params->rej);
+	psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, comment, "");
+	psFree(comment);
+    }
+
+    // note the use of weights
+    if (params->weights) {
+        psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK,
+                         "Using input weights to combine images", "");
+    }
+
+    // note the rejection fraction
+    float keepFrac = 1.0 - params->fracLow - params->fracHigh; // Fraction of pixels to keep
+    if (keepFrac != 1.0) {
+        psString comment = NULL;        // Comment to add to header
+        psStringAppend(&comment, "Min/max rejection: %f high, %f low, keep %d",
+                       params->fracHigh, params->fracLow, params->nKeep);
+        psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, comment, "");
+        psFree(comment);
+    }
+
+    // note the mask value actually used
+    psMaskType maskVal = params->maskVal; // The mask value
+    if (maskVal) {
+        psString comment = NULL;        // Comment to add to header
+        psStringAppend(&comment, "Mask for combination: %x", maskVal);
+        psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, comment, "");
+        psFree(comment);
+    }
+
+    // determine the output image size based on the input images
+    int row0, col0, numCols, numRows;
+    if (!pmReadoutStackSetOutputSize(&col0, &row0, &numCols, &numRows, inputs)) {
+        psError(PS_ERR_UNKNOWN, false, "problem setting output readout size.");
+        return false;
+    }
+
+    // generate the required output images based on the specified sizes
+    pmReadoutStackDefineOutput(output, col0, row0, numCols, numRows, true, params->weights, params->blank);
+    psTrace("psModules.imcombine", 7, "Output minimum: %d,%d\n", output->col0, output->row0);
+
+    // these calls allocate and save the requested images on the output analysis metadata
+    psImage *counts = pmReadoutSetAnalysisImage(output, PM_READOUT_STACK_ANALYSIS_COUNT, numCols, numRows, PS_TYPE_U16, 0);
+    if (!counts) {
+        return false;
+    }
+    psImage *sigma = pmReadoutSetAnalysisImage(output, PM_READOUT_STACK_ANALYSIS_SIGMA, numCols, numRows, PS_TYPE_F32, NAN);
+    if (!sigma) {
+        return false;
+    }
+
+    // Update the "concepts"
+    psList *inputCells = psListAlloc(NULL); // List of cells
+    for (long i = 0; i < inputs->n; i++) {
+        pmReadout *readout = inputs->data[i]; // Readout of interest
+        psListAdd(inputCells, PS_LIST_TAIL, readout->parent);
+    }
+    bool success = pmConceptsAverageCells(output->parent, inputCells, NULL, NULL, true);
+    psFree(inputCells);
+
+    // set these even though the values are not yet set
+    output->data_exists = true;
+    output->parent->data_exists = true;
+    output->parent->parent->data_exists = true;
+
+    return success;
+}
+
+// XXX: Maybe add support for S16 and S32 types.  Currently, only F32 supported.
+bool pmReadoutCombine(pmReadout *output, const psArray *inputs, const psVector *zero, const psVector *scale,
+                      const pmCombineParams *params)
+{
+    // Check inputs
+    PS_ASSERT_PTR_NON_NULL(output, false);
+    PS_ASSERT_ARRAY_NON_NULL(inputs, false);
+    PS_ASSERT_PTR_NON_NULL(params, false);
+    if (zero) {
+        PS_ASSERT_VECTOR_TYPE(zero, PS_TYPE_F32, false);
+        PS_ASSERT_VECTOR_SIZE(zero, inputs->n, false);
+    }
+    if (scale) {
+        PS_ASSERT_VECTOR_TYPE(scale, PS_TYPE_F32, false);
+        PS_ASSERT_VECTOR_SIZE(scale, inputs->n, false);
+    }
+    PS_ASSERT_FLOAT_WITHIN_RANGE(params->fracLow, 0.0, 1.0, false);
+    PS_ASSERT_FLOAT_WITHIN_RANGE(params->fracHigh, 0.0, 1.0, false);
+
+    pmHDU *hdu = pmHDUFromReadout(output); // Output HDU
+    if (!hdu) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find HDU for readout.\n");
+        return false;
+    }
+
+    pthread_t id = pthread_self();
+    char name[64];
+    sprintf (name, "%x", (unsigned int) id);
+    psTimerStart (name);
+
+    psStatsOptions combineStdev = 0; // Statistics option for weights
+    switch (params->combine) {
+      case PS_STAT_SAMPLE_MEAN:
+      case PS_STAT_SAMPLE_MEDIAN:
+        combineStdev = PS_STAT_SAMPLE_STDEV;
+        break;
+      case PS_STAT_ROBUST_MEDIAN:
+        combineStdev = PS_STAT_ROBUST_STDEV;
+        break;
+      case PS_STAT_FITTED_MEAN:
+        combineStdev = PS_STAT_FITTED_STDEV;
+        break;
+      case PS_STAT_CLIPPED_MEAN:
+        combineStdev = PS_STAT_CLIPPED_STDEV;
+        break;
+      default:
+        psAbort("Should never get here --- checked params->combine before.\n");
+    }
+
+    psStats *stats = psStatsAlloc(params->combine | combineStdev); // The statistics to use in the combination
+    if (params->combine == PS_STAT_CLIPPED_MEAN) {
+        stats->clipSigma = params->rej;
+        stats->clipIter = params->iter;
+    }
+
+    psImage *counts = pmReadoutGetAnalysisImage(output, PM_READOUT_STACK_ANALYSIS_COUNT);
+    if (!counts) {
+        return false;
+    }
+    psImage *sigma = pmReadoutGetAnalysisImage(output, PM_READOUT_STACK_ANALYSIS_SIGMA);
+    if (!sigma) {
+        return false;
+    }
+
+    stats->options |= combineStdev;
+
+    int minInputCols, maxInputCols, minInputRows, maxInputRows; // Smallest and largest values to combine
+    int xSize, ySize;                   // Size of the output image
+    if (!pmReadoutStackValidate(&minInputCols, &maxInputCols, &minInputRows, &maxInputRows, &xSize, &ySize, inputs)) {
+        psError(PS_ERR_UNKNOWN, false, "No valid input readouts.");
+        return false;
+    }
+
+    // We loop through each pixel in the output image.  We loop through each input readout.  We determine if
+    // that output pixel is contained in the image from that readout.  If so, we save it in psVector pixels.
+    // If not, we set a mask for that element in pixels.  Then, we mask off pixels not between fracLow and
+    // fracHigh.  Then we call the vector stats routine on those pixels/mask.  Then we set the output pixel
+    // value to the result of the stats call.
+
+    psVector *pixels = psVectorAlloc(inputs->n, PS_TYPE_F32); // Stack of pixels
+    psF32 *pixelsData = pixels->data.F32; // Dereference pixels
+
+    psVector *mask   = psVectorAlloc(inputs->n, PS_TYPE_U8); // Mask for stack
+    psU8 *maskData = mask->data.U8;     // Dereference mask
+
+    psVector *weights = NULL;           // Stack of weights
+    psVector *errors = NULL;            // Stack of errors (sqrt of variance/weights), for psVectorStats
+    psF32 *weightsData = NULL;          // Dereference weights
+    if (params->weights) {
+        weights = psVectorAlloc(inputs->n, PS_TYPE_F32); // Stack of weights
+        weightsData = weights->data.F32;
+    }
+    psVector *index = NULL;             // The indices to sort the pixels
+
+    float keepFrac = 1.0 - params->fracLow - params->fracHigh; // Fraction of pixels to keep
+    psMaskType maskVal = params->maskVal; // The mask value
+
+    #ifndef PS_NO_TRACE
+    psTrace("psModules.imcombine", 3, "Iterating output: %d --> %d, %d --> %d\n",
+            minInputCols - output->col0, maxInputCols - output->col0,
+            minInputRows - output->row0, maxInputRows - output->row0);
+    if (psTraceGetLevel("psModules.imcombine") >= 3) {
+        for (int r = 0; r < inputs->n; r++) {
+            pmReadout *readout = inputs->data[r]; // Input readout
+            psTrace("psModules.imcombine", 3, "Iterating input %d: %d --> %d, %d --> %d\n", r,
+                    minInputCols - readout->col0, maxInputCols - readout->col0,
+                    minInputRows - readout->row0, maxInputRows - readout->row0);
+        }
+    }
+    #endif
+
+    // Dereference output products
+    psF32 **outputImage  = output->image->data.F32; // Output image
+    psU8  **outputMask   = output->mask->data.U8; // Output mask
+    psF32 **outputWeight = NULL; // Output weight map
+    if (output->weight) {
+        outputWeight = output->weight->data.F32;
+    }
+
+    psVector *invScale = NULL;          // Inverse scale; pre-calculated for efficiency
+    if (scale) {
+        invScale = (psVector*)psBinaryOp(NULL, psScalarAlloc(1.0, PS_TYPE_F32), "/", (const psPtr)scale);
+    }
+
+    for (int i = minInputRows; i < maxInputRows; i++) {
+        int yOut = i - output->row0; // y position on output readout
+        #ifdef SHOW_BUSY
+	
+        if (psTraceGetLevel("psModules.imcombine") > 9) {
+            printf("Processing row %d\r", i);
+            fflush(stdout);
+        }
+        #endif
+        for (int j = minInputCols; j < maxInputCols; j++) {
+            int xOut = j - output->col0; // x position on output readout
+
+            int numValid = 0;           // Number of valid pixels in the stack
+            memset(maskData, 0, mask->n * sizeof(psU8)); // Reset the mask
+            for (int r = 0; r < inputs->n; r++) {
+                pmReadout *readout = inputs->data[r]; // Input readout
+                int yIn = i - readout->row0; // y position on input readout
+                int xIn = j - readout->col0; // x position on input readout
+                psImage *image = readout->image; // The readout image
+
+                pixelsData[r] = image->data.F32[yIn][xIn];
+                if (!isfinite(pixelsData[r])) {
+                    maskData[r] = 1;
+                    continue;
+                }
+
+                // Check mask
+                psImage *roMask = readout->mask; // The mask image
+                if (roMask && roMask->data.U8[yIn][xIn] & maskVal) {
+                    maskData[r] = 1;
+                    continue;
+                }
+
+                if (params->weights) {
+                    weightsData[r] = readout->weight->data.F32[yIn][xIn];
+                }
+
+                if (zero) {
+                    pixelsData[r] -= zero->data.F32[r];
+                }
+                if (scale) {
+                    pixelsData[r] *= invScale->data.F32[r];
+                    if (params->weights) {
+                        weightsData[r] *= invScale->data.F32[r] * invScale->data.F32[r];
+                    }
+                }
+
+                numValid++;
+            }
+
+            if (numValid == 0) {
+                outputMask[yOut][xOut] = params->blank;
+                outputImage[yOut][xOut] = NAN;
+                counts->data.U16[yOut][xOut] = 0;
+                sigma->data.F32[yOut][xOut] = NAN;
+                continue;
+            }
+
+            // Apply fracLow,fracHigh if there are enough pixels
+            if (numValid * keepFrac >= params->nKeep && keepFrac != 1.0) {
+                index = psVectorSortIndex(index, pixels);
+                int numLow = numValid * params->fracLow; // Number of low pixels to clip
+                int numHigh = numValid * params->fracHigh; // Number of high pixels to clip
+                // Low pixels
+                psS32 *indexData = index->data.S32; // Dereference index
+                for (int k = 0, numMasked = 0; numMasked < numLow && k < index->n; k++) {
+                    // Don't count the ones that are already masked
+                    if (!maskData[indexData[k]]) {
+                        maskData[indexData[k]] = 1;
+                        numMasked++;
+                        numValid--;
+                    }
+                }
+                // High pixels
+                for (int k = pixels->n - 1, numMasked = 0; numMasked < numHigh && k >= 0; k--) {
+                    // Don't count the ones that are already masked
+                    if (!maskData[indexData[k]]) {
+                        maskData[indexData[k]] = 1;
+                        numMasked++;
+                        numValid--;
+                    }
+                }
+            }
+            counts->data.U16[yOut][xOut] = numValid;
+
+            // XXXXX this step probably is very expensive : convert errors to variance everywhere?
+            if (params->weights) {
+                errors = (psVector*)psUnaryOp(errors, weights, "sqrt");
+            }
+
+            // Combination
+            if (!psVectorStats(stats, pixels, errors, mask, 1)) {
+                // Can't do much about it, but it's not worth worrying about
+                psErrorClear();
+                outputImage[yOut][xOut] = NAN;
+                outputMask[yOut][xOut] = params->blank;
+                if (params->weights) {
+                    outputWeight[yOut][xOut] = NAN;
+                }
+                sigma->data.F32[yOut][xOut] = NAN;
+            } else {
+                outputImage[yOut][xOut] = psStatsGetValue(stats, params->combine);
+                outputMask[yOut][xOut] = isfinite(outputImage[yOut][xOut]) ? 0 : params->blank;
+                if (params->weights) {
+                    float stdev = psStatsGetValue(stats, combineStdev);
+                    outputWeight[yOut][xOut] = PS_SQR(stdev); // Variance
+                    // XXXX this is not the correct formal error.
+                    // also, the weighted mean is not obviously the correct thing here
+                }
+                sigma->data.F32[yOut][xOut] = psStatsGetValue(stats, combineStdev);
+            }
+        }
+    }
+    #ifdef SHOW_BUSY
+    if (psTraceGetLevel("psModules.imcombine") > 9) {
+        printf("\n");
+    }
+    #endif
+
+    psFree(index);
+    psFree(pixels);
+    psFree(mask);
+    psFree(weights);
+    psFree(errors);
+    psFree(stats);
+    psFree(invScale);
+
+    // fprintf (stderr, "done with combine %x : %f sec\n", (unsigned int) id, psTimerMark (name));
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmReadoutCombine.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmReadoutCombine.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmReadoutCombine.h	(revision 22158)
@@ -0,0 +1,50 @@
+/* @file  pmReadoutCombine.h
+ * @brief Combine multiple readouts
+ *
+ * @author George Gusciora, MHPCC
+ * @author Paul Price, IfA
+ *
+ * @version $Revision: 1.13.20.1 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-31 04:01:40 $
+ * Copyright 2004-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_READOUT_COMBINE_H
+#define PM_READOUT_COMBINE_H
+
+/// @addtogroup imcombine Image Combinations
+/// @{
+
+/// Combination parameters for pmReadoutCombine.
+///
+/// These values define how the combination is performed, and should not vary by detector, so that it can be
+/// re-used for multiple combinations.
+typedef struct {
+    psStatsOptions combine;             ///< Statistic to use when performing the combination
+    psMaskType maskVal;                 ///< Mask value
+    psMaskType blank;                   ///< Mask value to give blank (i.e., no data) pixels
+    int nKeep;                          ///< Mimimum number of pixels to keep
+    float fracHigh;                     ///< Fraction of high pixels to immediately throw
+    float fracLow;                      ///< Fraction of low pixels to immediately throw
+    int iter;                           ///< Number of iterations for clipping (for CLIPPED_MEAN only)
+    float rej;                          ///< Rejection threshould for clipping (for CLIPPED_MEAN only)
+    bool weights;                       ///< Use the supplied weights (instead of calculated stdev)?
+} pmCombineParams;
+
+// Allocator for pmCombineParams
+pmCombineParams *pmCombineParamsAlloc(psStatsOptions statsOptions ///< Statistic to use for combination
+                                     );
+
+// check the input parameters and set up the output images
+bool pmReadoutCombinePrepare(pmReadout *output, const psArray *inputs, const pmCombineParams *params);
+
+/// Combine multiple readouts, applying zero and scale, with optional minmax clipping
+bool pmReadoutCombine(pmReadout *output,///< Output readout; altered and returned
+                      const psArray *inputs,  ///< Array of input readouts (F32 image and weight, U8 mask)
+                      const psVector *zero, ///< Zero corrections to subtract from input, or NULL
+                      const psVector *scale, ///< Scale corrections to divide into input, or NULL
+                      const pmCombineParams *params ///< Combination parameters
+                     );
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmStack.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmStack.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmStack.c	(revision 22158)
@@ -0,0 +1,705 @@
+/** @file  pmStack.c
+ *
+ *  This file will perform image combination of several images of the
+ *  same field, produce a list of questionable pixels, then tag some
+ *  of those pixels as cosmic rays.
+ *
+ *  @author Paul Price, IfA
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.32 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-06-19 01:59:59 $
+ *  Copyright 2004-2007 Institute for Astronomy, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmReadoutStack.h"
+#include "pmConceptsAverage.h"
+
+#include "pmStack.h"
+
+#define PIXEL_LIST_BUFFER 100           // Number of entries to add to pixel list at a time
+#define PIXEL_MAP_BUFFER 2              // Number of entries to add to pixel map at a time
+
+// Internal values for masks
+#define MASK_BAD 0x01                   // Mask value for pixels that have formerly been masked as bad
+#define MASK_SUSPECT 0x02               // Mask value for pixels that are suspected bad (by pmStackCombine)
+
+#define NUM_DIRECT_STDEV 5              // For less than this number of values, measure stdev directly
+
+
+// Data structure for use as a buffer when combining pixels
+// Use of this structure means we don't have to do an allocation in the combination function for each pixel
+typedef struct {
+    psVector *pixels;                   // Pixel values
+    psVector *masks;                    // Pixel masks
+    psVector *variances;                // Pixel variances
+    psVector *weights;                  // Pixel weightings
+    psVector *sources;                  // Pixel sources (which image did they come from?)
+    psVector *sort;                     // Buffer for sorting (to get a robust estimator of the standard dev)
+} combineBuffer;
+
+static void combineBufferFree(combineBuffer *buffer)
+{
+    psFree(buffer->pixels);
+    psFree(buffer->masks);
+    psFree(buffer->variances);
+    psFree(buffer->weights);
+    psFree(buffer->sources);
+    psFree(buffer->sort);
+    return;
+}
+
+static combineBuffer *combineBufferAlloc(long numImages // Number of images that will be combined
+    )
+{
+    combineBuffer *buffer = psAlloc(sizeof(combineBuffer));
+    psMemSetDeallocator(buffer, (psFreeFunc)combineBufferFree);
+
+    buffer->pixels = psVectorAlloc(numImages, PS_TYPE_F32);
+    buffer->masks = psVectorAlloc(numImages, PS_TYPE_MASK);
+    buffer->variances = psVectorAlloc(numImages, PS_TYPE_F32);
+    buffer->weights = psVectorAlloc(numImages, PS_TYPE_F32);
+    buffer->sources = psVectorAlloc(numImages, PS_TYPE_U16);
+    buffer->sort = psVectorAlloc(numImages, PS_TYPE_F32);
+    return buffer;
+}
+
+
+// Deallocator for the stack data
+static void stackDataFree(pmStackData *data)
+{
+    psFree(data->readout);
+    psFree(data->reject);
+    psFree(data->inspect);
+    return;
+}
+
+
+// Determine a mean value and variance for the combination
+// Not using psVectorStats because it assumes that the "weights" are errors, and weights by 1/error^2
+static bool combinationMeanVariance(float *mean, // Mean value, to return
+                                    float *var, // Variance value, to return
+                                    const psVector *values, // Values to combine
+                                    const psVector *variances, // Pixel variances to combine
+                                    const psVector *weights // Weights to apply
+                                    )
+{
+    assert(mean);
+    assert(values && weights);
+    assert(values->n == weights->n);
+    assert((var && variances) || !var);
+    assert(!variances || variances->n == values->n);
+    assert(values->type.type == PS_TYPE_F32);
+    assert(!values || values->type.type == PS_TYPE_F32);
+    assert(weights->type.type == PS_TYPE_F32);
+
+    // We're not using the input pixel variances to generate a weighted average for the pixel flux (because
+    // that introduces systematic biases), so the variance of the output pixel value should simply be:
+    //     simga^2 = sum(weight_i^2 * sigma_i^2) / (sum(weight_i))^2
+    // This reduces, when the weights are all identically unity, to:
+    //     variance_combination = sum(variance_i) / N^2
+    // and if the variances are all equal:
+    //     variance_combination = variance_individual / N
+    // which makes sense --- the standard deviation of the combination is reduced by a factor of sqrt(N).
+
+    float sumValueWeight = 0.0;         // Sum of the value multiplied by the weight
+    float sumVarianceWeight = 0.0;     // Sum of the pixel variances multiplied by the global weights
+    float sumWeight = 0.0;              // Sum of the image weights
+    for (int i = 0; i < values->n; i++) {
+        sumValueWeight += values->data.F32[i] * weights->data.F32[i];
+        sumWeight += weights->data.F32[i];
+        if (variances) {
+            sumVarianceWeight += variances->data.F32[i] * PS_SQR(weights->data.F32[i]);
+        }
+    }
+
+    if (sumWeight <= 0) {
+        return false;
+    }
+
+    *mean = sumValueWeight / sumWeight;
+    if (var) {
+        *var = sumVarianceWeight / PS_SQR(sumWeight);
+    }
+    return true;
+}
+
+// Return the median and standard deviation for the pixels
+// Not using psVectorStats because it has additional allocations which slow things down
+static bool combinationMedianStdev(float *median, // Median value, to return
+                                   float *stdev, // Standard deviation value, to return
+                                   const psVector *values, // Values to combine
+                                   const psVector *masks, // Mask to apply
+                                   psVector *sortBuffer // Buffer for sorting
+                                   )
+{
+    assert(values);
+    assert(!masks || values->n == masks->n);
+    assert(values->type.type == PS_TYPE_F32);
+    assert(!masks || masks->type.type == PS_TYPE_MASK);
+    assert(sortBuffer && sortBuffer->nalloc >= values->n && sortBuffer->type.type == PS_TYPE_F32);
+
+    // Need to filter out clipped values
+    int num = 0;            // Number of valid values
+    for (int i = 0; i < values->n; i++) {
+        if (!masks || !masks->data.PS_TYPE_MASK_DATA[i]) {
+            sortBuffer->data.F32[num++] = values->data.F32[i];
+        }
+    }
+    sortBuffer->n = num;
+    if (!psVectorSortInPlace(sortBuffer)) {
+        return false;
+    }
+
+    if (num == 3) {
+        // Attempt to measure standard deviation with only three values (and one of those possibly corrupted)
+        *median = sortBuffer->data.F32[1];
+        if (stdev) {
+            float diff1 = sortBuffer->data.F32[0] - *median;
+            float diff2 = sortBuffer->data.F32[2] - *median;
+            // This factor of sqrt(2) might not be exact, but it's about right
+            *stdev = M_SQRT2 * PS_MIN(fabsf(diff1), fabsf(diff2));
+        }
+    } else {
+        *median = num % 2 ? sortBuffer->data.F32[num / 2] :
+            (sortBuffer->data.F32[num / 2 - 1] + sortBuffer->data.F32[num / 2]) / 2.0;
+        if (stdev) {
+            if (num <= NUM_DIRECT_STDEV) {
+                // If there are not many values, the direct standard deviation is better
+                double sum = 0.0;
+                for (int i = 0; i < num; i++) {
+                    sum += PS_SQR(sortBuffer->data.F32[i] - *median);
+                }
+                *stdev = sqrt(sum / (double)(num - 1));
+            } else {
+                // Standard deviation from the interquartile range
+                *stdev = 0.74 * (sortBuffer->data.F32[(int)(0.75 * num)] -
+                                 sortBuffer->data.F32[(int)(0.25 * num)]);
+            }
+        }
+    }
+
+    return true;
+}
+
+
+// Mark a pixel for inspection
+static inline void combineInspect(const psArray *inputs, // Stack data
+                                  int x, int y, // Pixel
+                                  int source // Source image index
+                                  )
+{
+    pmStackData *data = inputs->data[source]; // Stack data of interest
+    if (!data) {
+        psWarning("Can't find input data for source %d", source);
+        return;
+    }
+    data->inspect = psPixelsAdd(data->inspect, PIXEL_LIST_BUFFER, x, y);
+    return;
+}
+
+// Given a stack of images, combine with optional rejection.
+// Pixels in the stack that are rejected are marked for subsequent inspection
+static void combinePixels(psImage *image, // Combined image, for output
+                          psImage *mask, // Combined mask, for output
+                          psImage *variance, // Combined variance map, for output
+                          const psArray *inputs, // Stack data
+                          const psVector *weights, // Global (single value) weights for data, or NULL
+                          const psVector *varFactors, // Variance factors for data
+                          const psVector *reject, // Indices of pixels to reject, or NULL
+                          int x, int y, // Coordinates of interest; frame of output image
+                          psMaskType maskVal, // Value to mask
+                          psMaskType bad, // Value to give bad pixels
+                          int numIter, // Number of rejection iterations
+                          float rej, // Number of standard deviations at which to reject
+                          bool useVariance, // Use variance for rejection when combining?
+                          bool safe,    // Combine safely?
+                          combineBuffer *buffer // Buffer for combination; to avoid multiple allocations
+                         )
+{
+    // Rudimentary error checking
+    assert(image);
+    assert(mask);
+    assert(inputs);
+    assert(numIter >= 0);
+    assert(buffer);
+    assert(varFactors);
+    assert((useVariance && variance) || !useVariance);
+
+    psVector *pixelData = buffer->pixels; // Values for the pixel of interest
+    psVector *pixelMasks = buffer->masks; // Masks for the pixel of interest
+    psVector *pixelVariances = variance ? buffer->variances : NULL; // Variances for the pixel of interest
+    psVector *pixelWeights = buffer->weights; // Image weights for the pixel of interest
+    psVector *pixelSources = buffer->sources; // Sources for the pixel of interest
+    psVector *sort = buffer->sort;      // Sort buffer
+
+    // Extract the pixel and mask data
+    int num = 0;                        // Number of good images
+    for (int i = 0, j = 0; i < inputs->n; i++) {
+        // Check if this pixel has been rejected.  Assumes that the rejection pixel list is sorted --- it
+        // should be because of how pixelMapGenerate works
+        if (reject && reject->data.U16[j] == i) {
+            j++;
+            continue;
+        }
+
+        pmStackData *data = inputs->data[i]; // Stack data of interest
+        if (!data) {
+            continue;
+        }
+
+        int xIn = x - data->readout->col0, yIn = y - data->readout->row0; // Coordinates on input readout
+        psImage *mask = data->readout->mask; // Mask of interest
+        if (mask->data.PS_TYPE_MASK_DATA[yIn][xIn] & maskVal) {
+            continue;
+        }
+
+        psImage *image = data->readout->image; // Image of interest
+        psImage *variance = data->readout->weight; // Variance ("weight") map of interest
+        pixelData->data.F32[num] = image->data.F32[yIn][xIn];
+        if (variance) {
+            pixelVariances->data.F32[num] = variance->data.F32[yIn][xIn];
+        }
+        pixelWeights->data.F32[num] = data->weight;
+        pixelSources->data.U16[num] = i;
+        num++;
+    }
+    pixelData->n = num;
+    if (variance) {
+        pixelVariances->n = num;
+    }
+    pixelWeights->n = num;
+    pixelSources->n = num;
+
+
+    // The sensible thing to do varies according to how many good pixels there are.
+    // Default option is that the pixel is bad
+    float imageValue = NAN, varianceValue = NAN; // Value for combined image and variance map
+    psMaskType maskValue = bad;         // Value for combined mask
+    switch (num) {
+      case 0:
+        // Nothing to combine: it's bad
+        break;
+      case 1: {
+          // Accept the single pixel unless we have to be safe
+          if (!safe) {
+              imageValue = pixelData->data.F32[0];
+              if (variance) {
+                  varianceValue = pixelVariances->data.F32[0];
+              }
+              maskValue = 0;
+          }
+          break;
+      }
+      case 2: {
+          // Accept the mean of the pixels only if we're going to reject based on the variance, or we're not
+          // playing safe
+          if (useVariance || !safe) {
+              float mean, var;   // Mean and variance from combination
+              if (combinationMeanVariance(&mean, &var, pixelData, pixelVariances, pixelWeights)) {
+                  imageValue = mean;
+                  varianceValue = var;
+                  maskValue = 0;
+              }
+          }
+          if (useVariance && safe && numIter > 0) {
+              // Use variance to check that the two are consistent
+              float diff = pixelData->data.F32[0] - pixelData->data.F32[1];
+              float sigma = sqrtf(pixelVariances->data.F32[0] + pixelVariances->data.F32[1]);
+              if (fabs(diff) > rej * sigma) {
+                  // Not consistent: mark both for inspection
+                  combineInspect(inputs, x, y, pixelSources->data.U16[0]);
+                  combineInspect(inputs, x, y, pixelSources->data.U16[1]);
+              }
+          }
+          break;
+      }
+      default: {
+          // Record the value derived with no clipping, because pixels rejected using the harsh clipping
+          // applied in the first pass might later be accepted.
+          float mean, var;           // Mean and variance of the combination
+          if (!combinationMeanVariance(&mean, &var, pixelData, pixelVariances, pixelWeights)) {
+              break;
+          }
+          imageValue = mean;
+          varianceValue = var;
+          maskValue = 0;
+
+          // Prepare for clipping iteration
+          if (numIter > 0) {
+              pixelMasks->n = num;
+              psVectorInit(pixelMasks, 0);
+              if (useVariance) {
+                  // Convert to rejection limits --- saves doing it later.
+                  // Using squared rejection limit because it's cheaper than sqrts
+                  rej *= rej;
+                  for (int i = 0; i < num; i++) {
+                      pixelVariances->data.F32[i] = rej * pixelVariances->data.F32[i] *
+                          varFactors->data.F32[i];
+                  }
+              }
+          }
+
+          // The clipping that follows is solely to identify suspect pixels.
+          // These suspect pixels will be inspected in more detail by other functions.
+          int numClipped = INT_MAX;       // Number of pixels clipped per iteration
+          int totalClipped = 0;           // Total number of pixels clipped
+          for (int i = 0; i < numIter && numClipped > 0 && num - totalClipped > 2; i++) {
+              numClipped = 0;
+              float median, stdev;    // Median and stdev of the combination, for rejection
+
+              if (!combinationMedianStdev(&median, useVariance ? NULL : &stdev, pixelData, pixelMasks, sort)) {
+                  psWarning("Bad median/stdev at %d,%d", x, y);
+                  break;
+              }
+
+              float limit = NAN;        // Rejection limit, when rejecting based on data properties
+              if (!useVariance) {
+                  limit = rej * stdev;
+              }
+
+// Mask a pixel for inspection
+#define MASK_PIXEL_FOR_INSPECTION() \
+    pixelMasks->data.PS_TYPE_MASK_DATA[j] = 0xff; \
+    combineInspect(inputs, x, y, pixelSources->data.U16[j]); \
+    numClipped++; \
+    totalClipped++;
+
+              for (int j = 0; j < num; j++) {
+                  if (pixelMasks->data.PS_TYPE_MASK_DATA[j]) {
+                      continue;
+                  }
+                  float diff = fabsf(pixelData->data.F32[j] - median); // Difference from expected
+                  if (useVariance) {
+                      // Comparing squares --- cheaper than lots of sqrts
+                      if (PS_SQR(diff) > pixelVariances->data.F32[i]) {
+                          MASK_PIXEL_FOR_INSPECTION();
+                      }
+                  } else if (diff > limit) {
+                      MASK_PIXEL_FOR_INSPECTION();
+                  }
+              }
+          }
+          break;
+      }
+    }
+
+    image->data.F32[y][x] = imageValue;
+    mask->data.PS_TYPE_MASK_DATA[y][x] = maskValue;
+    if (variance) {
+        variance->data.F32[y][x] = varianceValue;
+    }
+
+    return;
+}
+
+
+// Ensure the input array of pmStackData is valid, and get some details out of it
+static bool validateInputData(bool *haveVariances, // Do we have variance maps in the sky images?
+                              bool *haveRejects, // Do we have lists of rejected pixels?
+                              int *num,    // Number of inputs
+                              int *numCols, int *numRows, // Size of (sky) images
+                              psArray *input // Input array of pmStackData to validate
+    )
+{
+    PS_ASSERT_ARRAY_NON_NULL(input, false);
+    *num = input->n;
+
+    pmStackData *data = NULL;           // First image off the rank, used as a template
+    for (int i = 0; !data && i < input->n; i++) {
+        data = input->data[i];
+    }
+    PS_ASSERT_PTR_NON_NULL(data, false);
+    assert(psMemGetDeallocator(data) == (psFreeFunc)stackDataFree); // Ensure it's the right type
+    *haveVariances = false;
+    PS_ASSERT_IMAGE_NON_NULL(data->readout->image, false);
+    PS_ASSERT_IMAGE_TYPE(data->readout->image, PS_TYPE_F32, false);
+    PS_ASSERT_IMAGE_NON_NULL(data->readout->mask, false);
+    PS_ASSERT_IMAGE_TYPE(data->readout->mask, PS_TYPE_MASK, false);
+    PS_ASSERT_IMAGES_SIZE_EQUAL(data->readout->image, data->readout->mask, false);
+    *numCols = data->readout->image->numCols;
+    *numRows = data->readout->image->numRows;
+    if (data->readout->weight) {
+        *haveVariances = true;
+        PS_ASSERT_IMAGE_NON_NULL(data->readout->weight, false);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(data->readout->image, data->readout->weight, false);
+        PS_ASSERT_IMAGE_TYPE(data->readout->weight, PS_TYPE_F32, false);
+    }
+    *haveRejects = (data->reject != NULL);
+
+    // Make sure the rest correspond with the first
+    for (int i = 1; i < *num; i++) {
+        pmStackData *data = input->data[i]; // Stack data for this input
+        if (!data) {
+            continue;
+        }
+        assert(psMemGetDeallocator(data) == (psFreeFunc)stackDataFree); // Ensure it's the right type
+        if (!data->readout) {
+            psError(PS_ERR_UNEXPECTED_NULL, true, "The readout is specified in some but not all inputs.");
+            return false;
+        }
+        if ((*haveRejects && !data->reject) || (data->reject && !*haveRejects)) {
+            psError(PS_ERR_UNEXPECTED_NULL, true,
+                    "The rejected pixels are specified in some but not all inputs.");
+            return false;
+        }
+        PS_ASSERT_IMAGE_NON_NULL(data->readout->image, false);
+        PS_ASSERT_IMAGE_NON_NULL(data->readout->mask, false);
+        PS_ASSERT_IMAGE_TYPE(data->readout->image, PS_TYPE_F32, false);
+        PS_ASSERT_IMAGE_TYPE(data->readout->mask, PS_TYPE_MASK, false);
+        PS_ASSERT_IMAGE_SIZE(data->readout->image, *numCols, *numRows, false);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(data->readout->image, data->readout->mask, false);
+        if (*haveVariances) {
+            PS_ASSERT_IMAGE_NON_NULL(data->readout->weight, false);
+            PS_ASSERT_IMAGES_SIZE_EQUAL(data->readout->image, data->readout->weight, false);
+            PS_ASSERT_IMAGE_TYPE(data->readout->weight, PS_TYPE_F32, false);
+        }
+    }
+
+    return true;
+}
+
+
+// Generate a "pixel map".
+//
+// A "pixel map" is an image-like structure containing a vector that contains the indices of images.  The idea
+// is to provide a reverse lookup for an array of pixel lists, so that the image for which a pixel is flagged
+// can be identified easily.
+static psArray *pixelMapGenerate(const psArray *input, // Data to stack
+                                 int numCols, int numRows // Size of (sky) images
+    )
+{
+    psArray *map = psArrayAlloc(numRows); // The pixel map
+    for (int y = 0; y < numRows; y++) {
+        map->data[y] = psArrayAlloc(numCols);
+    }
+
+    for (int i = 0; i < input->n; i++) {
+        pmStackData *data = input->data[i];
+        if (!data) {
+            continue;
+        }
+        assert(data->reject);
+        psPixels *pixels = data->reject; // The rejected pixels
+        for (int j = 0; j < pixels->n; j++) {
+            int x = pixels->data[j].x, y = pixels->data[j].y; // Coordinates of interest
+            if (x < 0 || x >= numCols || y < 0 || y >= numRows) {
+                //                psWarning("Bad pixel coordinate: %d,%d --- ignored.", x, y);
+                continue;
+            }
+            psArray *columns = map->data[y]; // The columns for that row
+            psVector *images = columns->data[x]; // The images for that column
+            if (!images) {
+                images = columns->data[x] = psVectorAllocEmpty(PIXEL_MAP_BUFFER, PS_TYPE_U16);
+            }
+            int size = images->n;       // Element number at which to add
+            columns->data[x] = psVectorExtend(images, PIXEL_MAP_BUFFER, 1);
+            images->data.U16[size] = i;
+        }
+    }
+
+    return map;
+}
+
+// Query a "pixel map", by returning the list of image indices for a particular pixel.
+static psVector *pixelMapQuery(const psArray *map, // Pixel map
+                               int x, int y // Coordinates of interest
+    )
+{
+    assert(y >= 0 && y < map->n);
+    psArray *colMap = map->data[y];     // Columns for that row
+    assert(x >= 0 && x < colMap->n);
+    return colMap->data[x];
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/// Constructor
+pmStackData *pmStackDataAlloc(pmReadout *readout, float weight)
+{
+    pmStackData *data = psAlloc(sizeof(pmStackData)); // Stack data, to return
+    psMemSetDeallocator(data, (psFreeFunc)stackDataFree);
+
+    data->readout = psMemIncrRefCounter(readout);
+    data->reject = NULL;
+    data->inspect = NULL;
+    data->weight = weight;
+
+    return data;
+}
+
+/// Stack input images
+bool pmStackCombine(pmReadout *combined, psArray *input, psMaskType maskVal, psMaskType bad,
+                    int kernelSize, int numIter, float rej, bool entire, bool useVariance, bool safe)
+{
+    PS_ASSERT_PTR_NON_NULL(combined, false);
+    bool haveVariances;                 // Do we have the variance maps?
+    bool haveRejects;                   // Do we have lists of rejected pixels?
+    int num;                            // Number of inputs
+    int numCols, numRows;               // Size of (sky) images
+    if (!validateInputData(&haveVariances, &haveRejects, &num, &numCols, &numRows, input)) {
+        return false;
+    }
+    PS_ASSERT_INT_NONNEGATIVE(kernelSize, false);
+    PS_ASSERT_INT_POSITIVE(bad, false);
+    PS_ASSERT_INT_NONNEGATIVE(numIter, false);
+    if (isnan(rej)) {
+        PS_ASSERT_INT_EQUAL(numIter, 0, false);
+    } else {
+        PS_ASSERT_FLOAT_LARGER_THAN(rej, 0.0, false);
+    }
+    if (haveRejects) {
+        // This is a subsequent combination, so expect that the image and mask already exist
+        PS_ASSERT_IMAGE_NON_NULL(combined->image, false);
+        PS_ASSERT_IMAGE_TYPE(combined->image, PS_TYPE_F32, false);
+        PS_ASSERT_IMAGE_NON_NULL(combined->mask, false);
+        PS_ASSERT_IMAGE_TYPE(combined->mask, PS_TYPE_MASK, false);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(combined->image, combined->mask, false);
+    }
+    if (useVariance && !haveVariances) {
+        psWarning("Unable to use variance in rejection if no variance maps supplied --- option turned off");
+        useVariance = false;
+    }
+
+    psVector *varFactors = psVectorAlloc(num, PS_TYPE_F32); // Variance factors for each image
+    psVector *weights = psVectorAlloc(num, PS_TYPE_F32); // Relative weighting for each image
+    psArray *stack = psArrayAlloc(num); // Stack of readouts
+    for (int i = 0; i < num; i++) {
+        pmStackData *data = input->data[i]; // Stack data for this input
+        if (!data) {
+            weights->data.F32[i] = 0.0;
+            continue;
+        }
+        weights->data.F32[i] = data->weight;
+        stack->data[i] = psMemIncrRefCounter(data->readout);
+        // Variance factor
+        float vf = psMetadataLookupF32(NULL, data->readout->parent->concepts, "CELL.VARFACTOR"); // Var factor
+        if (!isfinite(vf)) {
+            psWarning("Non-finite CELL.VARFACTOR for image %d --- setting to unity.", i);
+            vf = 1.0;
+        }
+        varFactors->data.F32[i] = vf;
+    }
+
+    int minInputCols, maxInputCols, minInputRows, maxInputRows; // Smallest and largest values to combine
+    int xSize, ySize;                   // Size of the output image
+    if (!pmReadoutStackValidate(&minInputCols, &maxInputCols, &minInputRows, &maxInputRows, &xSize, &ySize,
+                                stack)) {
+        psError(PS_ERR_UNKNOWN, false, "Input stack is not valid.");
+        psFree(stack);
+        return false;
+    }
+    psFree(stack);
+    pmReadoutUpdateSize(combined, minInputCols, minInputRows, xSize, ySize, true, true, bad);
+    psTrace("psModules.imcombine", 1, "Have for combination [%d:%d,%d:%d] (%dx%d)\n",
+            minInputCols, maxInputCols, minInputRows, maxInputRows, xSize, ySize);
+
+    // Reduce combination area by the size of the kernel
+    minInputCols += kernelSize;
+    maxInputCols -= kernelSize;
+    minInputRows += kernelSize;
+    maxInputRows -= kernelSize;
+    psTrace("psModules.imcombine", 1, "Combining on [%d:%d,%d:%d]\n",
+            minInputCols, maxInputCols, minInputRows, maxInputRows);
+
+
+    // Buffer for combination
+    combineBuffer *buffer = combineBufferAlloc(num);
+
+    if (haveRejects) {
+        psImage *combinedImage = combined->image; // Combined image
+        psImage *combinedMask = combined->mask; // Combined mask
+        psImage *combinedVariance = combined->weight; // Combined variance map
+
+        psArray *pixelMap = pixelMapGenerate(input, maxInputCols, maxInputRows); // Map of pixels to source
+        psPixels *pixels = NULL;            // Total list of pixels, with no duplicates
+        for (int i = 0; i < num; i++) {
+            pmStackData *data = input->data[i]; // Stacking data; contains the list of pixels
+            if (!data) {
+                continue;
+            }
+            pixels = psPixelsConcatenate(pixels, data->reject);
+        }
+
+        if (entire) {
+            // Combine entire image
+            for (int y = minInputRows; y < maxInputRows; y++) {
+                for (int x = minInputCols; x < maxInputCols; x++) {
+                    psVector *reject = pixelMapQuery(pixelMap, x, y); // Inspect these images closely
+                    combinePixels(combinedImage, combinedMask, combinedVariance, input, weights, varFactors,
+                                  reject, x, y, maskVal, bad, numIter, rej, useVariance, safe, buffer);
+                }
+            }
+        } else {
+            // Only combine previously rejected pixels
+            for (int i = 0; i < pixels->n; i++) {
+                // Pixel coordinates are in the frame of the original image
+                int x = pixels->data[i].x, y = pixels->data[i].y; // Coordinates of interest
+                if (x < minInputCols || x >= maxInputCols || y < minInputRows || y >= maxInputRows) {
+                    continue;
+                }
+                psVector *reject = pixelMapQuery(pixelMap, x, y); // Inspect these images closely
+                combinePixels(combinedImage, combinedMask, combinedVariance, input, weights, varFactors,
+                              reject, x, y, maskVal, bad, numIter, rej, useVariance, safe, buffer);
+            }
+        }
+        psFree(pixels);
+        psFree(pixelMap);
+    } else {
+        // Pull the products out, allocate if necessary
+        psImage *combinedImage = combined->image; // Combined image
+        if (!combinedImage) {
+            combined->image = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+            combinedImage = combined->image;
+        }
+        psImage *combinedMask = combined->mask; // Combined mask
+        if (!combinedMask) {
+            combined->mask = psImageAlloc(numCols, numRows, PS_TYPE_MASK);
+            combinedMask = combined->mask;
+        }
+
+        psImage *combinedVariance = combined->weight; // Combined variance map
+        if (haveVariances && !combinedVariance) {
+            combined->weight = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+            combinedVariance = combined->weight;
+        }
+
+        for (int y = minInputRows; y < maxInputRows; y++) {
+            for (int x = minInputCols; x < maxInputCols; x++) {
+                combinePixels(combinedImage, combinedMask, combinedVariance, input, weights, varFactors,
+                              NULL, x, y, maskVal, bad, numIter, rej, useVariance, safe, buffer);
+            }
+        }
+
+#ifndef PS_NO_TRACE
+        if (psTraceGetLevel("psModules.imcombine") >= 5) {
+            for (int i = 0; i < num; i++) {
+                pmStackData *data = input->data[i]; // Stack data for this input
+                if (!data || !data->inspect) {
+                    continue;
+                }
+                psTrace("psModules.imcombine", 5, "Image %d: %ld pixels to inspect.\n", i, data->inspect->n);
+            }
+        }
+#endif
+    }
+
+    psFree(weights);
+    psFree(buffer);
+
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmStack.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmStack.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmStack.h	(revision 22158)
@@ -0,0 +1,54 @@
+/* @file  pmStack.h
+ *
+ * This file will perform image combination of several images of the
+ * same field, produce a list of questionable pixels, then tag some
+ * of those pixels as defects.
+ *
+ * @author Paul Price, IfA
+ * @author GLG, MHPCC
+ *
+ * @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-03-17 21:38:43 $
+ *
+ * Copyright 2004-2007 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_STACK_H
+#define PM_STACK_H
+
+#include <pslib.h>
+#include <pmHDU.h>
+#include <pmFPA.h>
+
+/// @addtogroup imcombine Image Combinations
+/// @{
+
+
+/// Container for input image
+typedef struct {
+    pmReadout *readout;                 ///< Warped readout (sky cell)
+    psPixels *reject;                   ///< Pixels to reject
+    psPixels *inspect;                  ///< Pixels to inspect
+    float weight;                       ///< Relative weighting for image
+} pmStackData;
+
+/// Constructor
+pmStackData *pmStackDataAlloc(pmReadout *readout, ///< Warped readout (sky cell)
+                              float weight ///< Weight to apply
+    );
+
+/// Stack input images
+bool pmStackCombine(pmReadout *combined,///< Combined readout (output)
+                    psArray *input,     ///< Input array of pmStackData
+                    psMaskType maskVal, ///< Mask value of bad pixels
+                    psMaskType bad,     ///< Mask value to give rejected pixels
+                    int kernelSize,     ///< Half-size of the convolution kernel
+                    int numIter,        ///< Number of iterations
+                    float rej,          ///< Rejection limit (standard deviations)
+                    bool entire,        ///< Combine entire image even if rejection lists provided?
+                    bool useVariance,   ///< Use variance values for rejection?
+                    bool safe           ///< Play safe with small numbers of input pixels (mask if N <= 2)?
+    );
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmStackReject.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmStackReject.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmStackReject.c	(revision 22158)
@@ -0,0 +1,195 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+
+#include "pmSubtraction.h"
+#include "pmSubtractionKernels.h"
+
+#define PIXEL_LIST_BUFFER 100           // Number of pixels to add to list at a time
+
+//#define TESTING                         // Testing output
+
+
+psPixels *pmStackReject(const psPixels *in, const psRegion *valid, float threshold,
+                        const psArray *subRegions, const psArray *kernels)
+{
+    PS_ASSERT_PIXELS_NON_NULL(in, NULL);
+    PS_ASSERT_FLOAT_LARGER_THAN_OR_EQUAL(threshold, 0.0, NULL);
+    PS_ASSERT_FLOAT_LESS_THAN_OR_EQUAL(threshold, 1.0, NULL);
+    PS_ASSERT_ARRAY_NON_NULL(subRegions, NULL);
+    PS_ASSERT_ARRAY_NON_NULL(kernels, NULL);
+    PS_ASSERT_ARRAYS_SIZE_EQUAL(subRegions, kernels, NULL);
+
+    // Trivial case
+    if (in->n == 0) {
+        return psPixelsAllocEmpty(0);
+    }
+
+    // Get the original image size
+    int numRegions = subRegions->n;        // Number of regions
+    int numCols = 0, numRows = 0;       // Size of original image
+    int minCols = INT_MAX, minRows = INT_MAX; // Minimum coordinate for image
+    int size = 0;                       // Size of kernel
+    for (int i = 0; i < numRegions; i++) {
+        psRegion *subRegion = subRegions->data[i]; // Region of interest
+        if (subRegion->x0 < minCols) {
+            minCols = subRegion->x0;
+        }
+        if (subRegion->y0 < minRows) {
+            minRows = subRegion->y0;
+        }
+        if (subRegion->x1 > numCols) {
+            numCols = subRegion->x1;
+        }
+        if (subRegion->y1 > numRows) {
+            numRows = subRegion->y1;
+        }
+
+        pmSubtractionKernels *kernel = kernels->data[i]; // Kernel of interest
+        if (size == 0) {
+            size = kernel->size;
+        } else if (kernel->size != size) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Kernel sizes are not identical: %d vs %d",
+                    size, kernel->size);
+            return NULL;
+        }
+    }
+
+    // Adjust the size for the size of the subimage
+    if (valid) {
+        minCols = PS_MAX(valid->x0, minCols);
+        minRows = PS_MAX(valid->y0, minRows);
+        numCols = PS_MIN(valid->x1, numCols);
+        numRows = PS_MIN(valid->y1, numRows);
+    }
+    psTrace("psModules.imcombine", 1, "Rejecting [%d:%d,%d:%d]\n", minCols, numCols, minRows, numRows);
+
+    psImage *mask = psPixelsToMask(NULL, in, psRegionSet(minCols, numCols - 1, minRows, numRows - 1),
+                                   0x01); // Mask
+    psImage *image = psImageCopy(NULL, mask, PS_TYPE_F32); // Floating-point version, so we can convolve
+    psFree(mask);
+
+    // Convolve the image with the kernel --- we're basically applying a matched filter and then thresholding
+    pmReadout *convRO = pmReadoutAlloc(NULL); // Readout with convolved image
+    pmReadout *inRO = pmReadoutAlloc(NULL); // Readout with input image
+    inRO->image = image;
+    inRO->col0 = minCols;
+    inRO->row0 = minRows;
+    for (int i = 0; i < numRegions; i++) {
+        psRegion *region = subRegions->data[i]; // Region of interest
+        if (valid && (region->x0 > valid->x1 || region->x1 < valid->x0 ||
+                      region->y0 > valid->y1 || region->y1 < valid->y0)) {
+            // Region is outside of our sub-image
+            continue;
+        }
+        pmSubtractionKernels *kernel = kernels->data[i]; // Kernel of interest
+        if (!pmSubtractionConvolve(convRO, NULL, inRO, NULL, NULL, 0, region, kernel, false, true)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to convolve mask image in region %d.", i);
+            psFree(convRO);
+            psFree(inRO);
+            return NULL;
+        }
+
+        // Need to adjust the thresholding level for the normalisation of the kernel --- the application of
+        // the kernel may scale the unit level that we've inserted.
+
+        // Image of the kernel at the centre of the region
+        float xNorm = (region->x0 + 0.5 * (region->x1 - region->x0) - kernel->numCols/2.0) /
+            (float)kernel->numCols;
+        float yNorm = (region->y0 + 0.5 * (region->y1 - region->y0) - kernel->numRows/2.0) /
+            (float)kernel->numRows;
+        psImage *image = pmSubtractionKernelImage(kernel, xNorm, yNorm, false);
+        if (!image) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to generate kernel image.");
+            psFree(convRO);
+            psFree(inRO);
+            return NULL;
+        }
+        float sum = 0.0;
+        for (int y = 0; y < image->numRows; y++) {
+            for (int x = 0; x < image->numCols; x++) {
+                sum += image->data.F32[y][x];
+            }
+        }
+        psFree(image);
+
+        // Range for normalisation
+        int yMin = PS_MAX(minRows, region->y0) - inRO->row0;
+        int yMax = PS_MIN(numRows - 1, region->y1) - inRO->row0;
+        int xMin = PS_MAX(minCols, region->x0) - inRO->col0;
+        int xMax = PS_MIN(numCols - 1, region->x1) - inRO->col0;
+        psTrace("psModules.imcombine", 2, "Normalising convolved mask image by %f over %d:%d,%d:%d\n",
+                sum, xMin, xMax, yMin, yMax);
+        for (int y = yMin; y <= yMax; y++) {
+            for (int x = xMin; x <= xMax; x++) {
+                convRO->image->data.F32[y][x] /= sum;
+            }
+        }
+    }
+    psFree(inRO);
+    psImage *convolved = psMemIncrRefCounter(convRO->image);
+    psFree(convRO);
+
+#ifdef TESTING
+    {
+        static int seqNum = 0;          // Sequence number
+        psString name = NULL;           // Name of image
+        psStringAppend(&name, "inspect_conv_%02d.fits", seqNum);
+        seqNum++;
+        psFits *fits = psFitsOpen(name, "w"); // FITS file pointer
+        psFree(name);
+        psFitsWriteImage(fits, NULL, convolved, 0, NULL);
+        psFitsClose(fits);
+    }
+#endif
+
+    // Threshold the convolved image
+    psPixels *bad = psPixelsAllocEmpty(PIXEL_LIST_BUFFER); // List of pixels that should be masked
+    for (int y = size; y < convolved->numRows - size; y++) {
+        for (int x = size; x < convolved->numCols - size; x++) {
+            if (convolved->data.F32[y][x] > threshold) {
+                // Pixel coordinates in "bad" correspond to the full image
+                bad = psPixelsAdd(bad, PIXEL_LIST_BUFFER, x + minCols, y + minRows);
+            }
+        }
+    }
+    psFree(convolved);
+
+    // Now, grow the mask to include everything that touches a bad pixel in the convolution
+    int x0 = minCols, y0 = minRows;     // Offset for mask image
+    mask = psPixelsToMask(NULL, bad, psRegionSet(x0, numCols - 1, y0, numRows - 1), 0xff);
+    for (int i = 0; i < bad->n; i++) {
+        int xPix = bad->data[i].x - x0, yPix = bad->data[i].y - y0; // Coordinates in frame of mask image
+        // Convolution limits
+        int xMin = PS_MAX(xPix - size, 0);
+        int xMax = PS_MIN(xPix + size, mask->numCols - 1);
+        int yMin = PS_MAX(yPix - size, 0);
+        int yMax = PS_MIN(yPix + size, mask->numRows - 1);
+        for (int y = yMin; y <= yMax; y++) {
+            for (int x = xMin; x <= xMax; x++) {
+                assert(x < mask->numCols && y < mask->numRows);
+                mask->data.PS_TYPE_MASK_DATA[y][x] = 0xff;
+            }
+        }
+    }
+    bad = psPixelsFromMask(bad, mask, 0xff);
+    psFree(mask);
+
+    // Convert coordinates to frame of original image
+    for (int i = 0; i < bad->n; i++) {
+        int x = bad->data[i].x + x0;
+        int y = bad->data[i].y + y0;
+        if (x < 0 || x >= numCols || y < 0 || y >= numRows) {
+            psWarning("Bad pixel coordinate %d: %d,%d --- ignored.",
+                      i, x, y);
+            continue;
+        }
+        bad->data[i].x = x;
+        bad->data[i].y = y;
+    }
+
+    return bad;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmStackReject.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmStackReject.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmStackReject.h	(revision 22158)
@@ -0,0 +1,19 @@
+#ifndef PM_STACK_REJECT_H
+#define PM_STACK_REJECT_H
+
+#include <pslib.h>
+#include <pmSubtractionKernels.h>
+
+/// Given a list of pixels from the convolved image, find the corresponding (smaller subset of) pixels in the
+/// original image, and then convolve those to get the list of all pixels which should be rejected
+///
+/// We apply a matched filter to the corresponding mask image, and threshold to find the original pixels
+psPixels *pmStackReject(const psPixels *in, ///< List of pixels in the convolved image
+                        const psRegion *valid, ///< Valid region to consider
+                        float threshold, ///< Threshold on convolved image, 0..1
+                        const psArray *regions, ///< Array of image regions for image
+                        const psArray *kernels ///< Array of kernel parameters for each region
+    );
+
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtraction.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtraction.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtraction.c	(revision 22158)
@@ -0,0 +1,929 @@
+/** @file pmSubtraction.c
+ *
+ *  @author Paul Price, IfA
+ *  @author GLG, MHPCC
+ *
+ *  Copyright 2004-2007 Institute for Astronomy, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmHDU.h"                      // Required for pmFPA.h
+#include "pmFPA.h"
+#include "pmSubtractionStamps.h"
+#include "pmSubtractionEquation.h"
+
+#include "pmSubtraction.h"
+
+//#define TESTING
+
+#define PIXEL_LIST_BUFFER 100           // Number of entries to add to pixel list at a time
+#define MIN_SAMPLE_STATS    7           // Minimum number to use sample statistics; otherwise use quartiles
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Private (file-static) functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Generate the kernel to apply to the variance from the normal kernel
+static psKernel *varianceKernel(psKernel *out, // Output kernel
+                                psKernel *normalKernel // Normal kernel
+                                )
+{
+    // Kernel range
+    int xMin = normalKernel->xMin, xMax = normalKernel->xMax;
+    int yMin = normalKernel->yMin, yMax = normalKernel->yMax;
+
+    if (!out) {
+        out = psKernelAlloc(xMin, xMax, yMin, yMax);
+    }
+
+    // Take the square of the normal kernel
+    double sumNormal = 0.0, sumVariance = 0.0; // Sum of the normal and variance kernels
+    for (int v = yMin; v <= yMax; v++) {
+        for (int u = xMin; u <= xMax; u++) {
+            float value = normalKernel->kernel[v][u]; // Value of interest
+            float value2 = PS_SQR(value); // Value squared
+            sumNormal += value;
+            sumVariance += value2;
+            out->kernel[v][u] = value2;
+        }
+    }
+
+    // Normalise so that the sum of the variance kernel is the square of the sum of the normal kernel
+    // This is required to keep the relative scaling between the image and the weight map
+    psBinaryOp(out->image, out->image, "*", psScalarAlloc(PS_SQR(sumNormal) / sumVariance, PS_TYPE_F32));
+
+    return out;
+}
+
+// Generate an image of the solved kernel
+static psKernel *solvedKernel(psKernel *kernel, // Kernel, to return
+                              const pmSubtractionKernels *kernels, // Kernel basis functions
+                              const psImage *polyValues, // Spatial polynomial values
+                              bool wantDual // Want the dual (second) kernel?
+                              )
+{
+    assert(kernels);
+    assert(polyValues);
+
+    int numKernels = kernels->num;      // Number of kernel basis functions
+    int size = kernels->size;           // Kernel half-size
+    if (!kernel) {
+        kernel = psKernelAlloc(-size, size, -size, size);
+    }
+    psImageInit(kernel->image, 0.0);
+
+    for (int i = 0; i < numKernels; i++) {
+        double value = p_pmSubtractionSolutionCoeff(kernels, polyValues, i, wantDual); // Polynomial value
+
+        switch (kernels->type) {
+          case PM_SUBTRACTION_KERNEL_POIS: {
+              int u = kernels->u->data.S32[i]; // Offset in x
+              int v = kernels->v->data.S32[i]; // Offset in y
+              kernel->kernel[v][u] += value;
+              kernel->kernel[0][0] -= value;
+              break;
+          }
+          /* SPAM and FRIES use the same method */
+          case PM_SUBTRACTION_KERNEL_SPAM:
+          case PM_SUBTRACTION_KERNEL_FRIES: {
+              int uStart = kernels->u->data.S32[i];
+              int uStop = kernels->uStop->data.S32[i];
+              int vStart = kernels->v->data.S32[i];
+              int vStop = kernels->vStop->data.S32[i];
+
+              // Normalising sum of kernel component to unity
+              float norm = 1.0 / (float)((uStop - uStart + 1) * (vStop - vStart + 1));
+
+              for (int v = vStart; v <= vStop; v++) {
+                  for (int u = uStart; u <= uStop; u++) {
+                      kernel->kernel[v][u] += norm * value;
+                      kernel->kernel[0][0] -= value;
+                  }
+              }
+              break;
+          }
+          case PM_SUBTRACTION_KERNEL_GUNK: {
+              if (i < kernels->inner) {
+                  // Using pre-calculated function
+                  psKernel *preCalc = kernels->preCalc->data[i]; // Precalculated values
+                  // Iterating over the kernel
+                  for (int v = -size; v <= size; v++) {
+                      for (int u = -size; u <= size; u++) {
+                          kernel->kernel[v][u] += preCalc->kernel[v][u] * value;
+                          // Photometric scaling is built into the preCalc kernel --- no subtraction!
+                      }
+                  }
+              } else {
+                  // Using delta function
+                  int u = kernels->u->data.S32[i]; // Offset in x
+                  int v = kernels->v->data.S32[i]; // Offset in y
+                  kernel->kernel[v][u] += value;
+                  kernel->kernel[0][0] -= value;
+              }
+              break;
+          }
+          case PM_SUBTRACTION_KERNEL_ISIS: {
+              psKernel *preCalc = kernels->preCalc->data[i]; // Precalculated values
+              // Iterating over the kernel
+              for (int v = -size; v <= size; v++) {
+                  for (int u = -size; u <= size; u++) {
+                      kernel->kernel[v][u] += preCalc->kernel[v][u] * value;
+                      // Photometric scaling is built into the preCalc kernel --- no subtraction!
+                  }
+              }
+              break;
+          }
+          case PM_SUBTRACTION_KERNEL_RINGS: {
+              psArray *preCalc = kernels->preCalc->data[i]; // Precalculated data
+              psVector *uCoords = preCalc->data[0]; // u coordinates
+              psVector *vCoords = preCalc->data[1]; // v coordinates
+              psVector *poly = preCalc->data[2]; // Polynomial values
+              int num = uCoords->n;     // Number of pixels
+
+              for (int j = 0; j < num; j++) {
+                  int u = uCoords->data.S32[j], v = vCoords->data.S32[j]; // Kernel coordinates
+                  kernel->kernel[v][u] += poly->data.F32[j] * value;
+              }
+              // Photometric scaling is built into the kernel --- no subtraction!
+              break;
+          }
+          default:
+            psAbort("Should never get here.");
+        }
+    }
+
+    // Put in the normalisation component
+    kernel->kernel[0][0] += (wantDual ? 1.0 : p_pmSubtractionSolutionNorm(kernels));
+
+    return kernel;
+}
+
+// Subtract the (0,0) element to preserve photometric scaling
+static void convolveSub(psKernel *convolved, // Convolved image
+                        const psKernel *image, // Image being convolved
+                        int footprint  // Size of region of interest
+                        )
+{
+    // Can't use psBinaryOp because the images are of different size
+    for (int y = -footprint; y <= footprint; y++) {
+        for (int x = -footprint; x <= footprint; x++) {
+            convolved->kernel[y][x] -= image->kernel[y][x];
+        }
+    }
+    return;
+}
+
+// Generate the convolution given some offset
+static psKernel *convolveOffset(const psKernel *image, // Image to convolve (a kernel for convenience)
+                                int u, int v, // Offset to apply
+                                int footprint // Size of region of interest
+                                )
+{
+    psKernel *convolved = psKernelAlloc(-footprint, footprint, -footprint, footprint); // Convolved image
+    int numBytes = (2 * footprint + 1) * PSELEMTYPE_SIZEOF(PS_TYPE_F32); // Number of bytes to copy
+    for (int y = -footprint; y <= footprint; y++) {
+        // Convolution with a delta function is just the value specified by the offset
+        memcpy(&convolved->kernel[y][-footprint], &image->kernel[y - v][-footprint - u], numBytes);
+    }
+    return convolved;
+}
+
+
+// Convolve an image using FFT
+static void convolveFFT(psImage *target,// Place the result in here
+                        const psImage *image, // Image to convolve
+                        const psImage *mask, // Mask image
+                        psMaskType maskVal, // Value to mask
+                        const psKernel *kernel, // Kernel by which to convolve
+                        psRegion region,// Region of interest
+                        float background, // Background to add
+                        int size        // Size of (square) kernel
+                        )
+{
+    psRegion border = psRegionSet(region.x0 - size, region.x1 + size,
+                                  region.y0 - size, region.y1 + size); // Add a border
+
+    // Casting away const so psImageSubset can add the child
+    psImage *subImage = psImageSubset((psImage*)image, border); // Subimage to convolve
+    psImage *subMask = mask ? psImageSubset((psImage*)mask, border) : NULL; // Subimage mask
+    psImage *convolved = psImageConvolveFFT(NULL, subImage, subMask, maskVal, kernel); // Convolution
+    psFree(subImage);
+    psFree(subMask);
+
+    // Now, we have to chop off the borders, and stick it in where it belongs
+    psImage *subConv = psImageSubset(convolved, psRegionSet(size, -size, size, -size)); // Cut off the edges
+    psImage *subTarget = psImageSubset(target, region); // Target for this subregion
+    if (background != 0.0) {
+        psBinaryOp(subTarget, subConv, "+", psScalarAlloc(background, PS_TYPE_F32));
+    } else {
+        int numBytes = subTarget->numCols * PSELEMTYPE_SIZEOF(PS_TYPE_F32); // Number of bytes to copy
+        for (int y = 0; y < subTarget->numRows; y++) {
+            memcpy(subTarget->data.F32[y], subConv->data.F32[y], numBytes);
+        }
+    }
+    psFree(subConv);
+    psFree(convolved);
+    psFree(subTarget);
+    return;
+}
+
+// Convolve an image directly
+static void convolveDirect(psImage *target, // Put the result here
+                           const psImage *image, // Image to convolve
+                           const psKernel *kernel, // Kernel by which to convolve
+                           psRegion region,// Region of interest
+                           float background, // Background to add
+                           int size        // Size of (square) kernel
+                           )
+{
+    for (int y = region.y0; y < region.y1; y++) {
+        for (int x = region.x0; x < region.x1; x++) {
+            target->data.F32[y][x] = background;
+            for (int v = -size; v <= size; v++) {
+                for (int u = -size; u <= size; u++) {
+                    target->data.F32[y][x] += kernel->kernel[v][u] *
+                        image->data.F32[y - v][x - u];
+                }
+            }
+        }
+    }
+    return;
+}
+
+// Convolve a region of an image
+static inline void convolveRegion(psImage *convImage, // Convolved image (output)
+                                  psImage *convWeight, // Convolved weight map (output), or NULL
+                                  psKernel **kernelImage, // Convolution kernel for the image
+                                  psKernel **kernelWeight, // Convolution kernel for the weight map, or NULL
+                                  const psImage *image, // Image to convolve
+                                  const psImage *weight, // Weight map to convolve, or NULL
+                                  const psImage *subMask, // Subtraction mask
+                                  psMaskType maskVal, // Mask value to apply in convolution
+                                  const pmSubtractionKernels *kernels, // Kernels
+                                  psImage *polyValues, // Polynomial values
+                                  float background, // Background value to apply
+                                  psRegion region, // Region to convolve
+                                  bool useFFT,  // Use FFT to convolve?
+                                  bool wantDual // Want the dual convolution?
+    )
+{
+    *kernelImage = solvedKernel(*kernelImage, kernels, polyValues, wantDual);
+    if (weight) {
+        *kernelWeight = varianceKernel(*kernelWeight, *kernelImage);
+    }
+
+    if (useFFT) {
+        // Use Fast Fourier Transform to do the convolution
+        // This provides a big speed-up for large kernels
+        convolveFFT(convImage, image, subMask, maskVal, *kernelImage, region, background, kernels->size);
+        if (weight) {
+            convolveFFT(convWeight, weight, subMask, maskVal, *kernelWeight, region, 0.0, kernels->size);
+        }
+    } else {
+        convolveDirect(convImage, image, *kernelImage, region, background, kernels->size);
+        if (weight) {
+            convolveDirect(convWeight, weight, *kernelWeight, region, 0.0, kernels->size);
+        }
+    }
+
+    return;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Semi-public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+psKernel *p_pmSubtractionConvolveStampPrecalc(const psKernel *image, const psKernel *kernel)
+{
+    PS_ASSERT_KERNEL_NON_NULL(image, NULL);
+    PS_ASSERT_KERNEL_NON_NULL(kernel, NULL);
+
+    psImage *conv = psImageConvolveFFT(NULL, image->image, NULL, 0, kernel); // Convolved image
+    int x0 = - image->xMin, y0 = - image->yMin; // Position of centre of convolved image
+    psKernel *convolved = psKernelAllocFromImage(conv, x0, y0); // Kernel version
+    psFree(conv);
+    return convolved;
+}
+
+psImage *p_pmSubtractionPolynomial(psImage *output, int spatialOrder, float x, float y)
+{
+    assert(spatialOrder >= 0);
+    assert(x >= -1 && x <= 1);
+    assert(y >= -1 && y <= 1);
+
+    output = psImageRecycle(output, spatialOrder + 1, spatialOrder + 1, PS_TYPE_F64);
+    output->data.F64[0][0] = 1.0;
+
+    double value = 1.0;
+    for (int i = 1; i <= spatialOrder; i++) {
+        value *= x;
+        output->data.F64[0][i] = value;
+    }
+
+    value = 1.0;
+    for (int j = 1; j <= spatialOrder; j++) {
+        value *= y;
+        output->data.F64[j][0] = value;
+    }
+
+    for (int j = 1; j <= spatialOrder; j++) {
+        for (int i = 1; i <= spatialOrder - j; i++) {
+            output->data.F64[j][i] = output->data.F64[j][0] * output->data.F64[0][i];
+        }
+    }
+
+    return output;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+// Convolve a stamp by a single kernel basis function
+static psKernel *convolveStampSingle(const pmSubtractionKernels *kernels, // Kernel basis functions
+                                     int index, // Kernel basis function index
+                                     const psKernel *image, // Image to convolve (a kernel for convenience)
+                                     int footprint // Size of region of interest
+    )
+{
+#if 0
+    if (index == kernels->num) {
+        // Normalisation component
+        return convolveOffset(image, 0, 0, footprint);
+    }
+#endif
+
+    switch (kernels->type) {
+      case PM_SUBTRACTION_KERNEL_POIS: {
+          int u = kernels->u->data.S32[index]; // Offset in x
+          int v = kernels->v->data.S32[index]; // Offset in y
+          psKernel *convolved = convolveOffset(image, u, v, footprint); // Convolved image
+          convolveSub(convolved, image, footprint);
+          return convolved;
+      }
+        // Method for SPAM and FRIES is the same
+      case PM_SUBTRACTION_KERNEL_SPAM:
+      case PM_SUBTRACTION_KERNEL_FRIES: {
+          psKernel *convolved = psKernelAlloc(-footprint, footprint,
+                                              -footprint, footprint); // Convolved image
+          int uStart = kernels->u->data.S32[index];
+          int uStop = kernels->uStop->data.S32[index];
+          int vStart = kernels->v->data.S32[index];
+          int vStop = kernels->vStop->data.S32[index];
+          float norm = 1.0 / (uStop - uStart + 1) * (vStop - vStart + 1); // Normalisation
+          for (int y = -footprint; y <= footprint; y++) {
+              for (int x = -footprint; x <= footprint; x++) {
+                  double sum = 0.0;
+                  for (int v = vStart; v <= vStop; v++) {
+                      for (int u = uStart; u <= uStop; u++) {
+                          sum += image->kernel[y - v][x - u];
+                      }
+                  }
+                  convolved->kernel[y][x] = norm * sum;
+              }
+          }
+          convolveSub(convolved, image, footprint);
+          return convolved;
+      }
+      case PM_SUBTRACTION_KERNEL_GUNK: {
+          if (index < kernels->inner) {
+              // Photometric scaling is already built in to the precalculated kernel
+              return p_pmSubtractionConvolveStampPrecalc(image, kernels->preCalc->data[index]);
+          }
+          // Using delta function
+          int u = kernels->u->data.S32[index]; // Offset in x
+          int v = kernels->v->data.S32[index]; // Offset in y
+          psKernel *convolved = convolveOffset(image, u, v, footprint); // Convolved image
+          convolveSub(convolved, image, footprint);
+          return convolved;
+      }
+      case PM_SUBTRACTION_KERNEL_ISIS: {
+          // Photometric scaling is already built in to the precalculated kernel
+          return p_pmSubtractionConvolveStampPrecalc(image, kernels->preCalc->data[index]);
+      }
+      case PM_SUBTRACTION_KERNEL_RINGS: {
+          psKernel *convolved = psKernelAlloc(-footprint, footprint,
+                                              -footprint, footprint); // Convolved image
+          psArray *preCalc = kernels->preCalc->data[index]; // Precalculated data
+          psVector *uCoords = preCalc->data[0]; // u coordinates
+          psVector *vCoords = preCalc->data[1]; // v coordinates
+          psVector *poly = preCalc->data[2]; // Polynomial values
+          int num = uCoords->n;         // Number of pixels
+          for (int y = -footprint; y <= footprint; y++) {
+              for (int x = -footprint; x <= footprint; x++) {
+                  double sum = 0.0;             // Accumulated sum from convolution
+                  for (int j = 0; j < num; j++) {
+                      int u = uCoords->data.S32[j], v = vCoords->data.S32[j]; // Kernel coordinates
+                      sum += image->kernel[y - v][x - u] * poly->data.F32[j];
+                  }
+                  convolved->kernel[y][x] = sum;
+                  // Photometric scaling is built into the kernel --- no subtraction!
+              }
+          }
+          return convolved;
+      }
+      default:
+        psAbort("Should never get here.");
+    }
+    return NULL;
+}
+
+// Convolve the stamp by each of the kernel basis functions
+static psArray *convolveStamp(psArray *convolutions, // The convolutions
+                              const psKernel *image, // Image to convolve
+                              const pmSubtractionKernels *kernels, // Kernel basis functions
+                              int footprint // Stamp half-size
+    )
+{
+    assert(image);
+    assert(kernels);
+    assert(footprint >= 0);
+
+    if (convolutions) {
+        // Already done
+        return convolutions;
+    }
+
+    int numKernels = kernels->num;      // Number of kernels
+    convolutions = psArrayAlloc(numKernels);
+
+    for (int i = 0; i < numKernels; i++) {
+        convolutions->data[i] = convolveStampSingle(kernels, i, image, footprint);
+    }
+
+    return convolutions;
+}
+
+
+bool pmSubtractionConvolveStamp(pmSubtractionStamp *stamp, const pmSubtractionKernels *kernels, int footprint)
+{
+    PS_ASSERT_PTR_NON_NULL(stamp, false);
+    PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, false);
+    PS_ASSERT_INT_NONNEGATIVE(footprint, false);
+
+    if (stamp->status != PM_SUBTRACTION_STAMP_CALCULATE) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Stamp not marked for calculation.");
+        return false;
+    }
+
+    switch (kernels->mode) {
+      case PM_SUBTRACTION_MODE_1:
+        stamp->convolutions1 = convolveStamp(stamp->convolutions1, stamp->image1, kernels, footprint);
+        break;
+      case PM_SUBTRACTION_MODE_2:
+        stamp->convolutions2 = convolveStamp(stamp->convolutions2, stamp->image2, kernels, footprint);
+        break;
+      case PM_SUBTRACTION_MODE_UNSURE:
+      case PM_SUBTRACTION_MODE_DUAL:
+        stamp->convolutions1 = convolveStamp(stamp->convolutions1, stamp->image1, kernels, footprint);
+        stamp->convolutions2 = convolveStamp(stamp->convolutions2, stamp->image2, kernels, footprint);
+        break;
+      default:
+        psAbort("Unsupported subtraction mode: %x", kernels->mode);
+    }
+
+    return true;
+}
+
+
+
+
+int pmSubtractionRejectStamps(float *rmsPtr, int *numPtr, pmSubtractionStampList *stamps,
+                              const psVector *deviations, psImage *subMask, float sigmaRej,
+                              int footprint)
+{
+    PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, -1);
+    PS_ASSERT_VECTOR_NON_NULL(deviations, -1);
+    PS_ASSERT_VECTOR_TYPE(deviations, PS_TYPE_F32, -1);
+    PS_ASSERT_IMAGE_NON_EMPTY(subMask, -1);
+    PS_ASSERT_IMAGE_TYPE(subMask, PS_TYPE_MASK, -1);
+
+    // I used to measure the rms deviation about zero, and use that as the sigma against which to clip, but
+    // the distribution is actually something like a chi^2 or Student's t, both of which become Gaussian-like
+    // with large N.  Therefore, let's just treat this as a Gaussian distribution.
+
+    int numStamps = 0;                  // Number of used stamps
+    psVector *mask = psVectorAlloc(stamps->num, PS_TYPE_MASK); // Mask, for statistics
+    psVectorInit(mask, 0);
+    for (int i = 0; i < stamps->num; i++) {
+        pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest
+        if (stamp->status != PM_SUBTRACTION_STAMP_USED) {
+            mask->data.PS_TYPE_MASK_DATA[i] = 0xff;
+            continue;
+        }
+        numStamps++;
+    }
+    psTrace("psModules.imcombine", 1, "Number of good stamps: %d\n", numStamps);
+
+    if (numStamps == 0) {
+        psError(PS_ERR_UNKNOWN, true, "No good stamps found.");
+        psFree(mask);
+        return -1;
+    }
+
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV |
+                                  PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_QUARTILE); // Statistics for deviatns
+    if (!psVectorStats(stats, deviations, NULL, mask, 0xff)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to measure statistics for deviations.");
+        psFree(stats);
+        psFree(mask);
+        return -1;
+    }
+    psFree(mask);
+
+    double mean, rms;                 // Mean and RMS of deviations
+    if (numStamps < MIN_SAMPLE_STATS) {
+        mean = stats->sampleMean;
+        rms = stats->sampleStdev;
+    } else {
+        mean = stats->sampleMedian;
+        rms = 0.74 * (stats->sampleUQ - stats->sampleLQ);
+    }
+
+    psTrace("psModules.imcombine", 1, "Mean: %f\n", mean);
+    psTrace("psModules.imcombine", 1, "RMS deviation: %f\n", rms);
+
+    if (rmsPtr) {
+        *rmsPtr = rms;
+    }
+    if (numPtr) {
+        *numPtr = numStamps;
+    }
+
+    if (!isfinite(sigmaRej) || sigmaRej <= 0.0) {
+        // User just wanted to calculate and record the RMS for posterity
+        psLogMsg("psModules.imcombine", PS_LOG_INFO, "RMS deviation from %d stamps: %lf",
+                 numStamps, rms);
+        return 0;
+    }
+
+    float limit = sigmaRej * rms; // Limit on maximum deviation
+    psTrace("psModules.imcombine", 1, "Deviation limit: %f\n", limit);
+
+    int numRejected = 0;                // Number of stamps rejected
+    int numGood = 0;                    // Number of good stamps
+    double newMean = 0.0;               // New mean
+    for (int i = 0; i < stamps->num; i++) {
+        pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest
+        if (stamp->status == PM_SUBTRACTION_STAMP_USED) {
+            // Should we reject stars with low deviation?  Well, if this is really a Gaussian-like
+            // distribution and they're low, then we have the right to ask why.  Isn't it suspicious that
+            // they're anomalously low, compared to the rest of the population which (we hope) is indicative
+            // of normality?  Besides, the standard deviation is going to be blown up by stars that didn't
+            // subtract well, in which case very few (if any) stars will be legitimately rejected for being
+            // low.
+            if (deviations->data.F32[i] - mean > limit) {
+                // Mask out the stamp in the image so you it's not found again
+                psTrace("psModules.imcombine", 3, "Rejecting stamp %d (%d,%d)\n", i,
+                        (int)(stamp->x + 0.5), (int)(stamp->y + 0.5));
+                numRejected++;
+                for (int y = stamp->y - footprint; y <= stamp->y + footprint; y++) {
+                    for (int x = stamp->x - footprint; x <= stamp->x + footprint; x++) {
+                        subMask->data.PS_TYPE_MASK_DATA[y][x] |= PM_SUBTRACTION_MASK_REJ;
+                    }
+                }
+
+                // Set stamp for replacement
+                stamp->x = 0;
+                stamp->y = 0;
+                stamp->xNorm = NAN;
+                stamp->yNorm = NAN;
+                stamp->status = PM_SUBTRACTION_STAMP_REJECTED;
+                // Recalculate convolutions
+                psFree(stamp->convolutions1);
+                psFree(stamp->convolutions2);
+                stamp->convolutions1 = stamp->convolutions2 = NULL;
+                psFree(stamp->image1);
+                psFree(stamp->image2);
+                psFree(stamp->weight);
+                stamp->image1 = stamp->image2 = stamp->weight = NULL;
+                psFree(stamp->matrix1);
+                psFree(stamp->matrix2);
+                psFree(stamp->matrixX);
+                stamp->matrix1 = stamp->matrix2 = stamp->matrixX = NULL;
+                psFree(stamp->vector1);
+                psFree(stamp->vector2);
+                stamp->vector1 = stamp->vector2 = NULL;
+            } else {
+                numGood++;
+                newMean += deviations->data.F32[i];
+            }
+        }
+    }
+    newMean /= numGood;
+
+    if (numRejected > 0) {
+        psLogMsg("psModules.imcombine", PS_LOG_INFO,
+                 "%d good stamps; %d rejected.\nMean deviation: %lf --> %lf\n",
+                 numGood, numRejected, mean, newMean);
+    } else {
+        psLogMsg("psModules.imcombine", PS_LOG_INFO,
+                 "%d good stamps; 0 rejected.\nMean deviation: %lf\n",
+                 numGood, mean);
+    }
+
+    return numRejected;
+}
+
+psImage *pmSubtractionKernelImage(const pmSubtractionKernels *kernels, float x, float y, bool wantDual)
+{
+    PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, NULL);
+    PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(kernels, NULL);
+    PS_ASSERT_FLOAT_WITHIN_RANGE(x, -1.0, 1.0, NULL);
+    PS_ASSERT_FLOAT_WITHIN_RANGE(y, -1.0, 1.0, NULL);
+
+    // Precalulate polynomial values
+    psImage *polyValues = p_pmSubtractionPolynomial(NULL, kernels->spatialOrder, x, y);
+
+    // The appropriate kernel
+    psKernel *kernel = solvedKernel(NULL, kernels, polyValues, wantDual);
+
+    psFree(polyValues);
+
+    psImage *image = psMemIncrRefCounter(kernel->image); // Image of the kernel
+    psFree(kernel);
+
+    return image;
+}
+
+
+float pmSubtractionVarianceFactor(const pmSubtractionKernels *kernels, float x, float y, bool wantDual)
+{
+    PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, NAN);
+    PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(kernels, NAN);
+    PS_ASSERT_FLOAT_WITHIN_RANGE(x, -1.0, 1.0, NAN);
+    PS_ASSERT_FLOAT_WITHIN_RANGE(y, -1.0, 1.0, NAN);
+
+    // Precalulate polynomial values
+    psImage *polyValues = p_pmSubtractionPolynomial(NULL, kernels->spatialOrder, x, y);
+
+    psKernel *kernel = solvedKernel(NULL, kernels, polyValues, wantDual); // The appropriate kernel
+    psFree(polyValues);
+
+    double sumKernel2 = 0.0;            // Sum of the kernel squared
+    double sumKernel = 0.0;             // Sum of the kernel
+    for (int y = kernel->yMin; y <= kernel->yMax; y++) {
+        for (int x = kernel->xMin; x <= kernel->xMax; x++) {
+            sumKernel += kernel->kernel[y][x];
+            sumKernel2 += PS_SQR(kernel->kernel[y][x]);
+        }
+    }
+
+    psFree(kernel);
+
+    return sumKernel2 / PS_SQR(sumKernel);
+}
+
+#if 0
+psArray *pmSubtractionKernelSolutions(const pmSubtractionKernels *kernels, float x, float y, bool wantDual)
+{
+    PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, NULL);
+    PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(kernels, NULL);
+    PS_ASSERT_FLOAT_WITHIN_RANGE(x, -1.0, 1.0, NULL);
+    PS_ASSERT_FLOAT_WITHIN_RANGE(y, -1.0, 1.0, NULL);
+
+    psArray *images = psArrayAlloc(solution->n - 1); // Images of each kernel to return
+    psVector *fakeSolution = psVectorAlloc(solution->n, PS_TYPE_F64); // Fake solution vector
+    psVectorInit(fakeSolution, 0.0);
+
+    for (int i = 0; i < solution->n - 1; i++) {
+        fakeSolution->data.F64[i] = solution->data.F64[i];
+        images->data[i] = pmSubtractionKernelImage(kernels, x, y, wantDual);
+        fakeSolution->data.F64[i] = 0.0;
+    }
+
+    psFree(fakeSolution);
+
+    return images;
+}
+#endif
+
+
+
+bool pmSubtractionConvolve(pmReadout *out1, pmReadout *out2, const pmReadout *ro1, const pmReadout *ro2,
+                           const psImage *subMask, psMaskType blank, const psRegion *region,
+                           const pmSubtractionKernels *kernels, bool doBG, bool useFFT)
+{
+    int numCols = 0, numRows = 0;       // Image dimensions
+    int x0 = 0, y0 = 0;                 // Image offset
+    if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
+        PM_ASSERT_READOUT_NON_NULL(out1, false);
+        PM_ASSERT_READOUT_NON_NULL(ro1, false);
+        PM_ASSERT_READOUT_IMAGE(ro1, false);
+        numCols = ro1->image->numCols;
+        numRows = ro1->image->numRows;
+        x0 = ro1->col0;
+        y0 = ro1->row0;
+    }
+    if (kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
+        PM_ASSERT_READOUT_NON_NULL(out2, false);
+        PM_ASSERT_READOUT_NON_NULL(ro2, false);
+        PM_ASSERT_READOUT_IMAGE(ro2, false);
+        if (numCols == 0 && numRows == 0) {
+            numCols = ro2->image->numCols;
+            numRows = ro2->image->numRows;
+            x0 = ro2->col0;
+            y0 = ro2->row0;
+        }
+    }
+    if (kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
+        PS_ASSERT_IMAGES_SIZE_EQUAL(ro1->image, ro2->image, false);
+    }
+    PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, false);
+    PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(kernels, false);
+    if (subMask) {
+        PS_ASSERT_IMAGE_NON_NULL(subMask, false);
+        PS_ASSERT_IMAGE_TYPE(subMask, PS_TYPE_MASK, false);
+        PS_ASSERT_IMAGE_SIZE(subMask, numCols, numRows, false);
+    }
+    if (region && psRegionIsNaN(*region)) {
+        psString string = psRegionToString(*region);
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Input region (%s) contains NAN values", string);
+        psFree(string);
+        return false;
+    }
+
+    // Inputs
+    psImage *image1 = NULL, *weight1 = NULL; // Image and weight map from input 1
+    if (ro1) {
+        image1 = ro1->image;
+        weight1 = ro1->weight;
+    }
+    psImage *image2 = NULL, *weight2 = NULL; // Image and weight map from input 2
+    if (ro2) {
+        image2 = ro2->image;
+        weight2 = ro2->weight;
+    }
+
+    // Outputs
+    psImage *convImage1 = NULL, *convWeight1 = NULL; // Convolved image and weight from input 1
+    if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
+        convImage1 = out1->image;
+        if (!convImage1) {
+            convImage1 = out1->image = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+        }
+        if (weight1) {
+            if (!out1->weight) {
+                out1->weight = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+            }
+            convWeight1 = out1->weight;
+            psImageInit(convWeight1, 0.0);
+        }
+    }
+    psImage *convImage2 = NULL, *convWeight2 = NULL; // Convolved image and weight from input 2
+    if (kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
+        convImage2 = out2->image;
+        if (!convImage2) {
+            convImage2 = out2->image = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+        }
+        if (weight2) {
+            if (!out2->weight) {
+                out2->weight = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+            }
+            convWeight2 = out2->weight;
+            psImageInit(convWeight2, 0.0);
+        }
+    }
+    psImage *convMask = NULL;           // Convolved mask image (common to inputs 1 and 2)
+    if (subMask) {
+        if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
+            if (!out1->mask) {
+                out1->mask = psImageAlloc(numCols, numRows, PS_TYPE_MASK);
+            }
+            convMask = out1->mask;
+        }
+        if (kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
+            if (convMask) {
+                if (out2->mask) {
+                    psFree(out2->mask);
+                }
+                out2->mask = psMemIncrRefCounter(convMask);
+            } else {
+                if (!out2->mask) {
+                    out2->mask = psImageAlloc(numCols, numRows, PS_TYPE_MASK);
+                }
+                convMask = out2->mask;
+            }
+        }
+        psImageInit(convMask, 0);
+    }
+
+
+    int size = kernels->size;           // Half-size of kernel
+    int fullSize = 2 * size + 1;        // Full size of kernel
+
+    // Get region for convolution: [xMin:xMax,yMin:yMax]
+    int xMin = size, xMax = numCols - size;
+    int yMin = size, yMax = numRows - size;
+    if (region) {
+        xMin = PS_MAX(region->x0, xMin);
+        xMax = PS_MIN(region->x1, xMax);
+        yMin = PS_MAX(region->y0, yMin);
+        yMax = PS_MIN(region->y1, yMax);
+    }
+
+    // Size to use when calculating normalised coordinates (different from actual size when convolving
+    // subimage)
+    int xNormSize = (kernels->numCols > 0 ? kernels->numCols : numCols);
+    int yNormSize = (kernels->numRows > 0 ? kernels->numRows : numRows);
+
+    psMaskType maskSource;              // Mask these pixels when convolving
+    psMaskType maskTarget;              // Mark these pixels as bad when propagating the subtractionMask
+    switch (kernels->mode) {
+      case PM_SUBTRACTION_MODE_1:
+        maskSource = PM_SUBTRACTION_MASK_BAD_1;
+        maskTarget = PM_SUBTRACTION_MASK_BAD_2 | PM_SUBTRACTION_MASK_CONVOLVE_1;
+        break;
+      case PM_SUBTRACTION_MODE_2:
+        maskSource = PM_SUBTRACTION_MASK_BAD_2;
+        maskTarget = PM_SUBTRACTION_MASK_BAD_1 | PM_SUBTRACTION_MASK_CONVOLVE_2;
+        break;
+      case PM_SUBTRACTION_MODE_DUAL:
+        maskSource = PM_SUBTRACTION_MASK_BAD_1 | PM_SUBTRACTION_MASK_BAD_2;
+        maskTarget = PM_SUBTRACTION_MASK_CONVOLVE_1 | PM_SUBTRACTION_MASK_CONVOLVE_2;
+        break;
+      default:
+        psAbort("Unsupported subtraction mode: %x", kernels->mode);
+    }
+
+    psImage *polyValues = NULL;         // Pre-calculated polynomial values
+    psKernel *kernelImage = NULL;       // Kernel for the images
+    psKernel *kernelWeight = NULL;      // Kernel for the weight maps
+
+    for (int j = yMin; j < yMax; j += fullSize) {
+        int ySubMax = PS_MIN(j + fullSize, yMax); // Range for subregion of interest
+        float yNorm = 2.0 * (float)(j + y0 + size + 1 - yNormSize/2.0) /
+            (float)yNormSize; // Normalised coordinate
+        for (int i = xMin; i < xMax; i += fullSize) {
+            int xSubMax = PS_MIN(i + fullSize, xMax); // Range for subregion of interest
+            float xNorm = 2.0 * (float)(i + x0 + size + 1 - xNormSize/2.0) /
+                (float)xNormSize; // Normalised coordinate
+
+            // Only generate polynomial values every kernel footprint, since we have already assumed
+            // (with the stamps) that it does not vary rapidly on this scale.
+            polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, xNorm, yNorm);
+            float background = doBG ? p_pmSubtractionSolutionBackground(kernels, polyValues) :
+                0.0; // Background term
+            psRegion subRegion = psRegionSet(i, xSubMax, j, ySubMax); // Sub-region to convolve
+
+            if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
+                convolveRegion(convImage1, convWeight1, &kernelImage, &kernelWeight, image1, weight1,
+                               subMask, maskSource, kernels, polyValues, background, subRegion, useFFT,
+                               false);
+            }
+            if (kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
+                convolveRegion(convImage2, convWeight2, &kernelImage, &kernelWeight, image2, weight2,
+                               subMask, maskSource, kernels, polyValues, background, subRegion, useFFT,
+                               kernels->mode == PM_SUBTRACTION_MODE_DUAL);
+            }
+
+            // Propagate the mask
+            if (subMask) {
+                for (int y = j; y < ySubMax; y++) {
+                    for (int x = i; x < xSubMax; x++) {
+                        if (subMask->data.PS_TYPE_MASK_DATA[y][x] & maskTarget) {
+                            convMask->data.PS_TYPE_MASK_DATA[y][x] |= blank;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    psFree(kernelImage);
+    psFree(kernelWeight);
+    psFree(polyValues);
+
+    // Copy anything that wasn't convolved
+    switch (kernels->mode) {
+      case PM_SUBTRACTION_MODE_1:
+        if (out2) {
+            out2->image = psMemIncrRefCounter(ro2->image);
+            out2->weight = psMemIncrRefCounter(ro2->weight);
+            out2->mask = psMemIncrRefCounter(ro2->mask);
+        }
+        break;
+      case PM_SUBTRACTION_MODE_2:
+        if (out1) {
+            out1->image = psMemIncrRefCounter(ro1->image);
+            out1->weight = psMemIncrRefCounter(ro1->weight);
+            out1->mask = psMemIncrRefCounter(ro1->mask);
+        }
+        break;
+      case PM_SUBTRACTION_MODE_DUAL:
+        break;
+      default:
+        psAbort("Should never get here.");
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtraction.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtraction.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtraction.h	(revision 22158)
@@ -0,0 +1,123 @@
+/* @file pmSubtraction.h
+ *
+ * PSF-matched image subtraction, based on the Alard & Lupton (1998) and Alard (2000) methods.
+ *
+ * @author Paul Price, IfA
+ * @author GLG, MHPCC
+ *
+ * @version $Revision: 1.26 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-06-19 00:54:09 $
+ * Copyright 2004-207 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_SUBTRACTION_H
+#define PM_SUBTRACTION_H
+
+#include <pslib.h>
+
+#include <pmHDU.h>
+#include <pmFPA.h>
+#include <pmSubtractionKernels.h>
+#include <pmSubtractionStamps.h>
+
+/// @addtogroup imcombine Image Combinations
+/// @{
+
+/// Mask values for the subtraction mask
+typedef enum {
+    PM_SUBTRACTION_MASK_CLEAR       = 0x00, // No masking
+    PM_SUBTRACTION_MASK_BAD_1       = 0x01, // Image 1 is bad
+    PM_SUBTRACTION_MASK_BAD_2       = 0x02, // Image 2 is bad
+    PM_SUBTRACTION_MASK_CONVOLVE_1  = 0x04, // If image 1 is convolved, would be bad
+    PM_SUBTRACTION_MASK_CONVOLVE_2  = 0x08, // If image 2 is convolved, would be bad
+    PM_SUBTRACTION_MASK_FOOTPRINT_1 = 0x10, // Bad pixel within the stamp footprint of image 1
+    PM_SUBTRACTION_MASK_FOOTPRINT_2 = 0x20, // Bad pixel within the stamp footprint of image 2
+    PM_SUBTRACTION_MASK_BORDER      = 0x40, // Image border
+    PM_SUBTRACTION_MASK_REJ         = 0x80, // Previously tried as a stamp, and rejected
+} pmSubtractionMasks;
+
+
+/// Number of terms in a polynomial
+#define PM_SUBTRACTION_POLYTERMS(ORDER) (((ORDER) + 1) * ((ORDER) + 2) / 2)
+
+/// Set the indices for the normalisation and background terms
+#define PM_SUBTRACTION_INDICES(NORM,BG,KERNELS) { \
+    int numSpatial = PM_SUBTRACTION_POLYTERMS((KERNELS)->spatialOrder); /* Number of spatial terms */ \
+    NORM = (KERNELS)->num * numSpatial; \
+    BG = NORM + 1; \
+}
+
+/// Return the index for the start of the normalisation terms
+#define PM_SUBTRACTION_INDEX_NORM(KERNELS) \
+    ((KERNELS)->num * PM_SUBTRACTION_POLYTERMS((KERNELS)->spatialOrder))
+
+/// Return the index for the start of the background terms
+#define PM_SUBTRACTION_INDEX_BG(KERNELS) \
+    (((KERNELS)->num * PM_SUBTRACTION_POLYTERMS((KERNELS)->spatialOrder)) + 1)
+
+
+/// Convolve the reference stamp with the kernel components
+bool pmSubtractionConvolveStamp(pmSubtractionStamp *stamp, ///< Stamp to convolve
+                                const pmSubtractionKernels *kernels, ///< Kernel parameters
+                                int footprint ///< Half-size of region over which to calculate equation
+    );
+
+/// Reject stamps
+int pmSubtractionRejectStamps(float *rms, ///< RMS deviation, to return
+                              int *num, ///< Number of good stamps, to return
+                              pmSubtractionStampList *stamps, ///< Stamps
+                              const psVector *deviations, ///< Deviations for each stamp
+                              psImage *subMask, ///< Subtraction mask
+                              float sigmaRej, ///< Number of RMS deviations above zero at which to reject
+                              int footprint ///< Half-size of stamp
+    );
+
+/// Generate an image of the convolution kernel
+psImage *pmSubtractionKernelImage(const pmSubtractionKernels *kernels, ///< Kernel parameters
+                                  float x, float y,///< Normalised position [-1,1] for which to generate image
+                                  bool wantDual ///< Calculate for the dual kernel?
+                                  );
+
+/// Return the variance factor for a kernel
+///
+/// The variance factor allows conversion from the large-scale variance (which is what is calculated by
+/// pmSubtractionConvolve) and the small-scale (pixel-to-pixel) variance.
+float pmSubtractionVarianceFactor(const pmSubtractionKernels *kernels, ///< Kernel parameters
+                                  float x, float y, ///< Normalised position [-1,1]
+                                  bool wantDual ///< Calculate for the dual kernel?
+    );
+
+/// Generate images of the convolution kernel elements
+psArray *pmSubtractionKernelSolutions(const psVector *solution, ///< Solution vector
+                                      const pmSubtractionKernels *kernels, ///< Kernel parameters
+                                      float x, float y ///< Normalised position [-1,1] for images
+    );
+
+/// Convolve image in preparation for subtraction
+bool pmSubtractionConvolve(pmReadout *out1, ///< Output image 1
+                           pmReadout *out2, ///< Output image 2 (DUAL mode only)
+                           const pmReadout *ro1, // Input image 1
+                           const pmReadout *ro2, // Input image 2
+                           const psImage *subMask, ///< Subtraction mask (or NULL)
+                           psMaskType blank, ///< Mask value for blank regions
+                           const psRegion *region, ///< Region to convolve (or NULL)
+                           const pmSubtractionKernels *kernels, ///< Kernel parameters
+                           bool doBG,   ///< Apply background term?
+                           bool useFFT  ///< Use Fast Fourier Transform for the convolution?
+    );
+
+/// Generate the convolution of an image, given a precalculated kernel
+///
+/// The 'image' is a kernel for convenience --- intended to be a stamp
+psKernel *p_pmSubtractionConvolveStampPrecalc(const psKernel *image, ///< Image to convolve
+                                              const psKernel *kernel ///< Kernel by which to convolve
+    );
+
+/// Given (normalised) coordinates (x,y), generate a matrix where the elements (i,j) are x^i * y^j
+psImage *p_pmSubtractionPolynomial(psImage *output, ///< Output matrix, or NULL
+                                   int spatialOrder, ///< Maximum spatial polynomial order
+                                   float x, float y ///< Normalised position of interest, [-1,1]
+    );
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionEquation.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionEquation.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionEquation.c	(revision 22158)
@@ -0,0 +1,1083 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmSubtraction.h"
+#include "pmSubtractionKernels.h"
+#include "pmSubtractionStamps.h"
+
+#include "pmSubtractionEquation.h"
+
+
+//#define TESTING
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Private (file-static) functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Calculate the sum over a stamp product
+static inline double calculateSumProduct(const psKernel *image1, // First image in multiplication
+                                         const psKernel *image2, // Second image in multiplication
+                                         const psKernel *weight, // Weight image
+                                         int footprint // (Half-)Size of stamp
+    )
+{
+    double sum = 0.0;                   // Sum of the image products
+    for (int y = - footprint; y <= footprint; y++) {
+        for (int x = - footprint; x <= footprint; x++) {
+            sum += image1->kernel[y][x] * image2->kernel[y][x] / 1.0; // weight->kernel[y][x];
+        }
+    }
+    return sum;
+}
+
+// Calculate a single element of the least-squares matrix, with the polynomial expansions in one direction
+static inline bool calculateMatrixElement1(psImage *matrix, // Matrix to calculate
+                                           int i, int j, // Coordinates of element
+                                           const psKernel *image1, // First image in multiplication
+                                           const psKernel *image2, // Second image in multiplication
+                                           const psKernel *weight, // Weight image
+                                           const psImage *polyValues, // Spatial polynomial values
+                                           int numKernels, // Number of kernel basis functions
+                                           int footprint, // (Half-)Size of stamp
+                                           int spatialOrder, // Maximum order of spatial variation
+                                           bool symmetric // Is the matrix symmetric?
+    )
+{
+    double sum = calculateSumProduct(image1, image2, weight, footprint); // Sum of the image products
+    if (!isfinite(sum)) {
+        return false;
+    }
+
+    // Generate the pseudo-convolutions from the spatial polynomial terms
+    for (int iyOrder = 0, iIndex = i; iyOrder <= spatialOrder; iyOrder++) {
+        for (int ixOrder = 0; ixOrder <= spatialOrder - iyOrder; ixOrder++, iIndex += numKernels) {
+            double convPoly = sum * polyValues->data.F64[iyOrder][ixOrder];
+
+            assert(iIndex < matrix->numRows && j < matrix->numCols);
+
+            matrix->data.F64[iIndex][j] = convPoly;
+            if (symmetric) {
+
+                assert(iIndex < matrix->numCols && j < matrix->numRows);
+
+                matrix->data.F64[j][iIndex] = convPoly;
+            }
+        }
+    }
+    return true;
+}
+
+// Calculate a single element of the least-squares matrix, with the polynomial expansions in both directions
+static inline bool calculateMatrixElement2(psImage *matrix, // Matrix to calculate
+                                           int i, int j, // Coordinates of element
+                                           const psKernel *image1, // First image in multiplication
+                                           const psKernel *image2, // Second image in multiplication
+                                           const psKernel *weight, // Weight image
+                                           const psImage *polyValues, // Spatial polynomial values
+                                           int numKernels, // Number of kernel basis functions
+                                           int footprint, // (Half-)Size of stamp
+                                           int spatialOrder, // Maximum order of spatial variation
+                                           bool symmetric // Is the matrix symmetric?
+    )
+{
+    double sum = calculateSumProduct(image1, image2, weight, footprint); // Sum of the image products
+    if (!isfinite(sum)) {
+        return false;
+    }
+
+    // Generate the pseudo-convolutions from the spatial polynomial terms
+    for (int iyOrder = 0, iIndex = i; iyOrder <= spatialOrder; iyOrder++) {
+        for (int ixOrder = 0; ixOrder <= spatialOrder - iyOrder; ixOrder++, iIndex += numKernels) {
+            double iPoly = polyValues->data.F64[iyOrder][ixOrder]; // Value of polynomial
+            for (int jyOrder = 0, jIndex = j; jyOrder <= spatialOrder; jyOrder++) {
+                for (int jxOrder = 0; jxOrder <= spatialOrder - jyOrder; jxOrder++, jIndex += numKernels) {
+                    double convPoly = sum * iPoly * polyValues->data.F64[jyOrder][jxOrder];
+
+                    assert(iIndex < matrix->numRows && jIndex < matrix->numCols);
+
+                    matrix->data.F64[iIndex][jIndex] = convPoly;
+                    if (symmetric) {
+
+                        assert(iIndex < matrix->numCols && jIndex < matrix->numRows);
+
+                        matrix->data.F64[jIndex][iIndex] = convPoly;
+                    }
+                }
+            }
+        }
+    }
+    return true;
+}
+
+// Calculate the square part of the matrix derived from multiplying convolutions
+static bool calculateMatrixSquare(psImage *matrix, // Matrix to calculate
+                                  const psArray *convolutions1, // Convolutions for element 1
+                                  const psArray *convolutions2, // Convolutions for element 2
+                                  const psKernel *weight, // Weight image
+                                  const psImage *polyValues, // Polynomial values
+                                  int numKernels, // Number of kernel basis functions
+                                  int spatialOrder, // Order of spatial variation
+                                  int footprint // Half-size of stamp
+                                  )
+{
+    bool symmetric = (convolutions1 == convolutions2 ? true : false); // Is matrix symmetric?
+
+    for (int i = 0; i < numKernels; i++) {
+        psKernel *iConv = convolutions1->data[i]; // Convolution for i-th element
+
+        for (int j = (symmetric ? i : 0); j < numKernels; j++) {
+            psKernel *jConv = convolutions2->data[j]; // Convolution for j-th element
+
+            if (!calculateMatrixElement2(matrix, i, j, iConv, jConv, weight, polyValues, numKernels,
+                                         footprint, spatialOrder, symmetric)) {
+                psTrace("psModules.imcombine", 2, "Bad sumCC at %d, %d", i, j);
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+// Calculate least-squares matrix and vector
+static bool calculateMatrix(psImage *matrix, // Matrix to calculate
+                            const pmSubtractionKernels *kernels, // Kernel components
+                            const psArray *convolutions, // Convolutions of source with kernels
+                            const psKernel *input, // Input stamp, or NULL
+                            const psKernel *weight, // Weight stamp
+                            const psImage *polyValues, // Spatial polynomial values
+                            int footprint, // (Half-)Size of stamp
+                            bool normAndBG // Calculate normalisation and background terms?
+    )
+{
+    int numKernels = kernels->num;      // Number of kernel components
+    int spatialOrder = kernels->spatialOrder; // Maximum order of spatial variation
+    int numSpatial = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of spatial variation terms
+    int bgOrder = kernels->bgOrder;     // Maximum order of background fit
+    int numBackground = normAndBG ? PM_SUBTRACTION_POLYTERMS(bgOrder) : 0; // Number of background terms
+    int numTerms = numKernels * numSpatial + (normAndBG ? 1 + numBackground : 0); // Total number of terms
+    assert(matrix);
+    assert(matrix->numCols == matrix->numRows);
+    assert(matrix->numCols == numTerms);
+    assert(convolutions && convolutions->n == numKernels);
+    assert(polyValues);
+    assert(!normAndBG || input);        // If we want the normalisation and BG, then we need the input image
+
+    // Square part of the matrix (convolution-convolution products)
+    if (!calculateMatrixSquare(matrix, convolutions, convolutions, weight, polyValues, numKernels,
+                               spatialOrder, footprint)) {
+        return false;
+    }
+
+    // XXX To support higher-order background model than simply constant, the below code needs to be updated.
+    if (normAndBG) {
+        int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation
+        int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background
+
+        for (int i = 0; i < numKernels; i++) {
+            psKernel *conv = convolutions->data[i]; // Convolution for i-th element
+
+            // Normalisation-convolution terms
+            if (!calculateMatrixElement1(matrix, i, normIndex, conv, input, weight, polyValues, numKernels,
+                                         footprint, spatialOrder, true)) {
+                psTrace("psModules.imcombine", 2, "Bad sumIC at %d", i);
+                return false;
+            }
+
+            // Background-convolution terms
+            double sumC = 0.0;          // Sum of the convolution
+            for (int y = - footprint; y <= footprint; y++) {
+                for (int x = - footprint; x <= footprint; x++) {
+                    sumC += conv->kernel[y][x] / 1.0; // weight->kernel[y][x];
+                }
+            }
+            if (!isfinite(sumC)) {
+                psTrace("psModules.imcombine", 2, "Bad sumC at %d", i);
+                return false;
+            }
+
+            for (int yOrder = 0, index = i; yOrder <= spatialOrder; yOrder++) {
+                for (int xOrder = 0; xOrder <= spatialOrder - yOrder; xOrder++, index += numKernels) {
+                    double value = sumC * polyValues->data.F64[yOrder][xOrder];
+                    matrix->data.F64[index][bgIndex] = value;
+                    matrix->data.F64[bgIndex][index] = value;
+                }
+            }
+        }
+
+        // Background only, normalisation only, and background-normalisation terms
+        double sum1 = 0.0;              // Sum of the weighting
+        double sumI = 0.0;              // Sum of the input
+        double sumII = 0.0;             // Sum of the input squared
+        for (int y = - footprint; y <= footprint; y++) {
+            for (int x = - footprint; x <= footprint; x++) {
+                double invNoise2 = 1.0 / 1.0; // weight->kernel[y][x];
+                double value = input->kernel[y][x] * invNoise2;
+                sumI += value;
+                sumII += value * input->kernel[y][x];
+                sum1 += invNoise2;
+            }
+        }
+        if (!isfinite(sumI)) {
+            psTrace("psModules.imcombine", 2, "Bad sumI detected");
+            return false;
+        }
+        if (!isfinite(sumII)) {
+            psTrace("psModules.imcombine", 2, "Bad sumII detected");
+            return false;
+        }
+        if (!isfinite(sum1)) {
+            psTrace("psModules.imcombine", 2, "Bad sum1 detected");
+            return false;
+        }
+        matrix->data.F64[normIndex][normIndex] = sumII;
+        matrix->data.F64[bgIndex][bgIndex] = sum1;
+        matrix->data.F64[normIndex][bgIndex] = sumI;
+        matrix->data.F64[bgIndex][normIndex] = sumI;
+    }
+
+    return true;
+}
+
+
+// Calculate least-squares matrix and vector
+static bool calculateVector(psVector *vector, // Vector to calculate, or NULL
+                            const pmSubtractionKernels *kernels, // Kernel components
+                            const psArray *convolutions, // Convolutions of source with kernels
+                            const psKernel *input, // Input stamp, or NULL if !normAndBG
+                            const psKernel *target, // Target stamp
+                            const psKernel *weight, // Weight stamp
+                            const psImage *polyValues, // Spatial polynomial values
+                            int footprint, // (Half-)Size of stamp
+                            bool normAndBG // Calculate normalisation and background terms?
+    )
+{
+    int numKernels = kernels->num;      // Number of kernel components
+    int spatialOrder = kernels->spatialOrder; // Maximum order of spatial variation
+    int numSpatial = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of spatial variation terms
+    int bgOrder = kernels->bgOrder;     // Maximum order of background fit
+    int numBackground = normAndBG ? PM_SUBTRACTION_POLYTERMS(bgOrder) : 0; // Number of background terms
+    int numTerms = numKernels * numSpatial + (normAndBG ? 1 + numBackground : 0); // Total number of terms
+    assert(vector && vector->n == numTerms);
+    assert(convolutions && convolutions->n == numKernels);
+    assert(target);
+    assert(polyValues);
+    assert(!normAndBG || input);       // If we want the normalisation and BG, then we need the input image
+
+    // Convolution terms
+    for (int i = 0; i < numKernels; i++) {
+        psKernel *conv = convolutions->data[i]; // Convolution for i-th element
+        double sumTC = 0.0;          // Sum of the target and convolution
+        for (int y = - footprint; y <= footprint; y++) {
+            for (int x = - footprint; x <= footprint; x++) {
+                sumTC += target->kernel[y][x] * conv->kernel[y][x] / 1.0; // weight->kernel[y][x];
+            }
+        }
+        if (!isfinite(sumTC)) {
+            psTrace("psModules.imcombine", 2, "Bad sumTC at %d", i);
+            return false;
+        }
+        for (int yOrder = 0, index = i; yOrder <= spatialOrder; yOrder++) {
+            for (int xOrder = 0; xOrder <= spatialOrder - yOrder; xOrder++, index += numKernels) {
+                vector->data.F64[index] = sumTC * polyValues->data.F64[yOrder][xOrder];
+            }
+        }
+    }
+
+    if (normAndBG) {
+        // Background terms
+        double sumT = 0.0;              // Sum of the target
+        double sumIT = 0.0;             // Sum of the input-target product
+        for (int y = - footprint; y <= footprint; y++) {
+            for (int x = - footprint; x <= footprint; x++) {
+                float value = target->kernel[y][x] / 1.0; // weight->kernel[y][x];
+                sumIT += value * input->kernel[y][x];
+                sumT += value;
+            }
+        }
+        if (!isfinite(sumT)) {
+            psTrace("psModules.imcombine", 2, "Bad sumI detected");
+            return false;
+        }
+        if (!isfinite(sumIT)) {
+            psTrace("psModules.imcombine", 2, "Bad sumIT detected");
+            return false;
+        }
+
+        int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation term
+        vector->data.F64[normIndex] = sumIT;
+        int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index for background term
+        vector->data.F64[bgIndex] = sumT;
+    }
+
+    return true;
+}
+
+
+
+// Calculate the cross-matrix, composed of convolutions of each image
+// Note that the cross-matrix is NOT square
+static bool calculateMatrixCross(psImage *matrix, // Matrix to calculate
+                                 const pmSubtractionKernels *kernels, // Kernel components
+                                 const psArray *convolutions1, // Convolutions of image 1
+                                 const psArray *convolutions2, // Convolutions of image 2
+                                 const psKernel *image1, // Image 1 stamp
+                                 const psKernel *weight, // Weight stamp
+                                 const psImage *polyValues, // Spatial polynomial values
+                                 int footprint // (Half-)Size of stamp
+                                 )
+{
+    assert(matrix);
+    int numKernels = kernels->num;      // Number of kernel components
+    int spatialOrder = kernels->spatialOrder; // Maximum order of spatial variation
+    int numSpatial = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of spatial polynomial terms
+    int numBackground = PM_SUBTRACTION_POLYTERMS(kernels->bgOrder); // Number of background terms
+    int numCols = numKernels * numSpatial + 1 + numBackground; // Number of columns
+    int numRows = numKernels * numSpatial; // Number of rows
+    assert(matrix->numCols == numCols && matrix->numRows == numRows);
+    assert(convolutions1 && convolutions1->n == numKernels);
+    assert(convolutions2 && convolutions2->n == numKernels);
+
+    int normIndex, bgIndex;             // Indices in matrix for normalisation and background terms
+    PM_SUBTRACTION_INDICES(normIndex, bgIndex, kernels);
+
+    if (!calculateMatrixSquare(matrix, convolutions1, convolutions2, weight, polyValues, numKernels,
+                               spatialOrder, footprint)) {
+        return false;
+    }
+
+    for (int i = 0; i < numKernels; i++) {
+        // Normalisation
+        psKernel *conv = convolutions2->data[i]; // Convolution
+        if (!calculateMatrixElement1(matrix, i, normIndex, conv, image1, weight, polyValues, numKernels,
+                                     footprint, spatialOrder, false)) {
+            psTrace("psModules.imcombine", 2, "Bad sumIC at %d", i);
+            return false;
+        }
+
+        // Background
+        double sumC = 0.0;              // Sum of the weighting
+        for (int y = - footprint; y <= footprint; y++) {
+            for (int x = - footprint; x <= footprint; x++) {
+                sumC += conv->kernel[y][x] / 1.0; // weight->kernel[y][x];
+            }
+        }
+        if (!isfinite(sumC)) {
+            psTrace("psModules.imcombine", 2, "Bad sumC detected at %d", i);
+            return false;
+        }
+        for (int yOrder = 0, index = i; yOrder <= spatialOrder; yOrder++) {
+            for (int xOrder = 0; xOrder <= spatialOrder - yOrder; xOrder++, index += numKernels) {
+                matrix->data.F64[index][bgIndex] = sumC * polyValues->data.F64[yOrder][xOrder];
+            }
+        }
+    }
+
+    return true;
+}
+
+
+// Add in penalty term to least-squares vector
+static bool calculatePenalty(psVector *vector, // Vector to which to add in penalty term
+                             const pmSubtractionKernels *kernels // Kernel parameters
+    )
+{
+    if (kernels->penalty == 0.0) {
+        return true;
+    }
+
+    psVector *penalties = kernels->penalties; // Penalties for each kernel component
+    int spatialOrder = kernels->spatialOrder; // Order of spatial variations
+    int numKernels = kernels->num; // Number of kernel components
+    for (int i = 0; i < numKernels; i++) {
+        for (int yOrder = 0, index = i; yOrder <= spatialOrder; yOrder++) {
+            for (int xOrder = 0; xOrder <= spatialOrder - yOrder; xOrder++, index += numKernels) {
+                vector->data.F64[index] -= penalties->data.F32[i];
+            }
+        }
+    }
+
+    return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Semi-public functions
+// XXX We might like to define these functions as "extern inline" but gcc currently doesn't handle this in c99
+// mode.  See http://gcc.gnu.org/ml/gcc/2006-11/msg00006.html
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Calculate the value of a polynomial, specified by coefficients and polynomial values
+double p_pmSubtractionCalculatePolynomial(const psVector *coeff, // Coefficients
+                                                 const psImage *polyValues, // Polynomial values
+                                                 int order, // Order of polynomials
+                                                 int index, // Index at which to begin
+                                                 int step // Step between subsequent indices
+                                                 )
+{
+    double sum = 0.0;                   // Value of the polynomial sum
+    for (int yOrder = 0; yOrder <= order; yOrder++) {
+        for (int xOrder = 0; xOrder <= order - yOrder; xOrder++, index += step) {
+
+            assert(index < coeff->n);
+
+            sum += coeff->data.F64[index] * polyValues->data.F64[yOrder][xOrder];
+        }
+    }
+    return sum;
+}
+
+double p_pmSubtractionSolutionCoeff(const pmSubtractionKernels *kernels, const psImage *polyValues,
+                                           int index, bool wantDual)
+{
+#if 0
+    // This is probably in a tight loop, so don't check inputs
+    PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, NAN);
+    PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(kernels, NAN);
+    PS_ASSERT_IMAGE_NON_NULL(polyValues, NAN);
+    PS_ASSERT_INT_POSITIVE(index, NAN);
+#endif
+
+    psVector *solution = wantDual ? kernels->solution2 : kernels->solution1; // Solution vector
+    return p_pmSubtractionCalculatePolynomial(solution, polyValues, kernels->spatialOrder, index,
+                                              kernels->num);
+}
+
+double p_pmSubtractionSolutionNorm(const pmSubtractionKernels *kernels)
+{
+#if 0
+    // This is probably in a tight loop, so don't check inputs
+    PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, NAN);
+    PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(kernels, NAN);
+    PS_ASSERT_IMAGE_NON_NULL(polyValues, NAN);
+#endif
+
+    int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation
+    return kernels->solution1->data.F64[normIndex];
+}
+
+double p_pmSubtractionSolutionBackground(const pmSubtractionKernels *kernels,
+                                                const psImage *polyValues)
+{
+#if 0
+    // This is probably in a tight loop, so don't check inputs
+    PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, NAN);
+    PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(kernels, NAN);
+    PS_ASSERT_IMAGE_NON_NULL(polyValues, NAN);
+#endif
+
+    int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index for background
+    return p_pmSubtractionCalculatePolynomial(kernels->solution1, polyValues, kernels->bgOrder, bgIndex, 1);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool pmSubtractionCalculateEquation(pmSubtractionStampList *stamps, const pmSubtractionKernels *kernels)
+{
+    PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false);
+    PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, false);
+
+    int footprint = stamps->footprint;  // Half-size of stamps
+    int spatialOrder = kernels->spatialOrder; // Maximum order of spatial variation
+    int numKernels = kernels->num;      // Number of kernel basis functions
+    int numSpatial = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of spatial variations
+    int numBackground = PM_SUBTRACTION_POLYTERMS(kernels->bgOrder); // Number of background terms
+
+    // Total number of parameters to solve for: coefficient of each kernel basis function, multipled by the
+    // number of coefficients for the spatial polynomial, normalisation and a constant background offset.
+    int numParams = numKernels * numSpatial + 1 + numBackground;
+
+    psImage *polyValues = NULL;         // Polynomial terms
+
+    // We iterate over each stamp, allocate the matrix and vectors if
+    // necessary, and then calculate those matrix/vectors.
+    for (int i = 0; i < stamps->num; i++) {
+        pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest
+        if (stamp->status != PM_SUBTRACTION_STAMP_CALCULATE) {
+            continue;
+        }
+
+        // Generate convolutions
+        if (!pmSubtractionConvolveStamp(stamp, kernels, footprint)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to convolve stamp %d.", i);
+            psFree(polyValues);
+            return NULL;
+        }
+
+#ifdef TESTING
+        for (int j = 0; j < numKernels; j++) {
+            if (stamp->convolutions1) {
+                psString convName = NULL;
+                psStringAppend(&convName, "conv1_%03d_%03d.fits", i, j);
+                psFits *fits = psFitsOpen(convName, "w");
+                psFree(convName);
+                psKernel *conv = stamp->convolutions1->data[j];
+                psFitsWriteImage(fits, NULL, conv->image, 0, NULL);
+                psFitsClose(fits);
+            }
+
+            if (stamp->convolutions2) {
+                psString convName = NULL;
+                psStringAppend(&convName, "conv2_%03d_%03d.fits", i, j);
+                psFits *fits = psFitsOpen(convName, "w");
+                psFree(convName);
+                psKernel *conv = stamp->convolutions2->data[j];
+                psFitsWriteImage(fits, NULL, conv->image, 0, NULL);
+                psFitsClose(fits);
+            }
+        }
+#endif
+
+        polyValues = p_pmSubtractionPolynomial(polyValues, spatialOrder, stamp->xNorm, stamp->yNorm);
+
+
+            stamp->matrix1 = psImageAlloc(numParams, numParams, PS_TYPE_F64);
+            stamp->vector1 = psVectorAlloc(numParams, PS_TYPE_F64);
+#ifdef TESTING
+            psImageInit(stamp->matrix1, NAN);
+            psVectorInit(stamp->vector1, NAN);
+#endif
+
+        bool status;                    // Status of least-squares matrix/vector calculation
+        switch (kernels->mode) {
+          case PM_SUBTRACTION_MODE_1:
+            status = calculateMatrix(stamp->matrix1, kernels, stamp->convolutions1, stamp->image1,
+                                     stamp->weight, polyValues, footprint, true);
+            status &= calculateVector(stamp->vector1, kernels, stamp->convolutions1, stamp->image1,
+                                      stamp->image2, stamp->weight, polyValues, footprint, true);
+            break;
+          case PM_SUBTRACTION_MODE_2:
+            status = calculateMatrix(stamp->matrix1, kernels, stamp->convolutions2, stamp->image2,
+                                     stamp->weight, polyValues, footprint, true);
+            status &= calculateVector(stamp->vector1, kernels, stamp->convolutions2, stamp->image2,
+                                      stamp->image1, stamp->weight, polyValues, footprint, true);
+            break;
+          case PM_SUBTRACTION_MODE_DUAL:
+            stamp->matrix2 = psImageAlloc(numKernels * numSpatial, numKernels * numSpatial, PS_TYPE_F64);
+            stamp->matrixX = psImageAlloc(numParams, numKernels * numSpatial, PS_TYPE_F64);
+            stamp->vector2 = psVectorAlloc(numKernels * numSpatial, PS_TYPE_F64);
+#ifdef TESTING
+            psImageInit(stamp->matrix2, NAN);
+            psImageInit(stamp->matrixX, NAN);
+            psVectorInit(stamp->vector2, NAN);
+#endif
+            status  = calculateMatrix(stamp->matrix1, kernels, stamp->convolutions1, stamp->image1,
+                                      stamp->weight, polyValues, footprint, true);
+            status &= calculateMatrix(stamp->matrix2, kernels, stamp->convolutions2, NULL,
+                                      stamp->weight, polyValues, footprint, false);
+            status &= calculateMatrixCross(stamp->matrixX, kernels, stamp->convolutions1,
+                                           stamp->convolutions2, stamp->image1, stamp->weight, polyValues,
+                                           footprint);
+            status &= calculateVector(stamp->vector1, kernels, stamp->convolutions1, stamp->image1,
+                                      stamp->image2, stamp->weight, polyValues, footprint, true);
+            status &= calculateVector(stamp->vector2, kernels, stamp->convolutions2, NULL,
+                                      stamp->image2, stamp->weight, polyValues, footprint, false);
+            break;
+          default:
+            psAbort("Unsupported subtraction mode: %x", kernels->mode);
+        }
+
+        if (!status) {
+            stamp->status = PM_SUBTRACTION_STAMP_REJECTED;
+            psWarning("Rejecting stamp %d (%d,%d) because of bad equation",
+                      i, (int)(stamp->x + 0.5), (int)(stamp->y + 0.5));
+        } else {
+            stamp->status = PM_SUBTRACTION_STAMP_USED;
+        }
+
+#ifdef TESTING
+        if (psTraceGetLevel("psModules.imcombine.equation") >= 10) {
+            psString matrixName = NULL;
+            psStringAppend(&matrixName, "matrix1_%d.fits", i);
+            psFits *matrixFile = psFitsOpen(matrixName, "w");
+            psFree(matrixName);
+            psFitsWriteImage(matrixFile, NULL, stamp->matrix1, 0, NULL);
+            psFitsClose(matrixFile);
+
+            matrixName = NULL;
+            psStringAppend(&matrixName, "vector1_%d.fits", i);
+            psImage *dummy = psImageAlloc(stamp->vector1->n, 1, PS_TYPE_F64);
+            memcpy(dummy->data.F64[0], stamp->vector1->data.F64,
+                   PSELEMTYPE_SIZEOF(PS_TYPE_F64) * stamp->vector1->n);
+            matrixFile = psFitsOpen(matrixName, "w");
+            psFree(matrixName);
+            psFitsWriteImage(matrixFile, NULL, dummy, 0, NULL);
+            psFree(dummy);
+            psFitsClose(matrixFile);
+
+            if (stamp->vector2) {
+                matrixName = NULL;
+                psStringAppend(&matrixName, "vector2_%d.fits", i);
+                dummy = psImageAlloc(stamp->vector2->n, 1, PS_TYPE_F64);
+                memcpy(dummy->data.F64[0], stamp->vector2->data.F64,
+                       PSELEMTYPE_SIZEOF(PS_TYPE_F64) * stamp->vector2->n);
+                matrixFile = psFitsOpen(matrixName, "w");
+                psFree(matrixName);
+                psFitsWriteImage(matrixFile, NULL, dummy, 0, NULL);
+                psFree(dummy);
+                psFitsClose(matrixFile);
+            }
+
+            if (kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
+                matrixName = NULL;
+                psStringAppend(&matrixName, "matrix2_%d.fits", i);
+                matrixFile = psFitsOpen(matrixName, "w");
+                psFree(matrixName);
+                psFitsWriteImage(matrixFile, NULL, stamp->matrix2, 0, NULL);
+                psFitsClose(matrixFile);
+
+                matrixName = NULL;
+                psStringAppend(&matrixName, "matrixX_%d.fits", i);
+                matrixFile = psFitsOpen(matrixName, "w");
+                psFree(matrixName);
+                psFitsWriteImage(matrixFile, NULL, stamp->matrixX, 0, NULL);
+                psFitsClose(matrixFile);
+            }
+        }
+#endif
+
+    }
+    psFree(polyValues);
+
+    return true;
+}
+
+bool pmSubtractionSolveEquation(pmSubtractionKernels *kernels, const pmSubtractionStampList *stamps)
+{
+    PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, false);
+    PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false);
+
+    // Check inputs
+    int numParams = -1;                // Number of parameters
+    int numParams2 = 0;                // Number of parameters for part solution (DUAL mode)
+    for (int i = 0; i < stamps->num; i++) {
+        pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest
+        PS_ASSERT_PTR_NON_NULL(stamp, false);
+        if (stamp->status != PM_SUBTRACTION_STAMP_USED) {
+            continue;
+        }
+
+        PS_ASSERT_VECTOR_NON_NULL(stamp->vector1, false);
+        if (numParams == -1) {
+            numParams = stamp->vector1->n;
+        }
+        PS_ASSERT_VECTOR_SIZE(stamp->vector1, (long)numParams, false);
+        PS_ASSERT_VECTOR_TYPE(stamp->vector1, PS_TYPE_F64, false);
+        PS_ASSERT_IMAGE_NON_NULL(stamp->matrix1, false);
+        PS_ASSERT_IMAGE_SIZE(stamp->matrix1, numParams, numParams, false);
+        PS_ASSERT_IMAGE_TYPE(stamp->matrix1, PS_TYPE_F64, false);
+
+        if (kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
+            PS_ASSERT_IMAGE_NON_NULL(stamp->matrix2, false);
+            PS_ASSERT_IMAGE_NON_NULL(stamp->matrixX, false);
+            if (numParams2 == 0) {
+                numParams2 = stamp->matrix2->numCols;
+            }
+            PS_ASSERT_IMAGE_SIZE(stamp->matrix2, numParams2, numParams2, false);
+            PS_ASSERT_IMAGE_SIZE(stamp->matrixX, numParams, numParams2, false);
+            PS_ASSERT_IMAGE_TYPE(stamp->matrix2, PS_TYPE_F64, false);
+            PS_ASSERT_IMAGE_TYPE(stamp->matrixX, PS_TYPE_F64, false);
+            PS_ASSERT_VECTOR_NON_NULL(stamp->vector2, false);
+            PS_ASSERT_VECTOR_SIZE(stamp->vector2, (long)numParams2, false);
+            PS_ASSERT_VECTOR_TYPE(stamp->vector2, PS_TYPE_F64, false);
+        }
+    }
+    if (numParams == -1) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "No suitable stamps found.");
+        return NULL;
+    }
+
+    if (kernels->mode != PM_SUBTRACTION_MODE_DUAL) {
+        // Accumulate the least-squares matricies and vectors
+        psImage *sumMatrix = psImageAlloc(numParams, numParams, PS_TYPE_F64); // Combined matrix
+        psVector *sumVector = psVectorAlloc(numParams, PS_TYPE_F64); // Combined vector
+        psVectorInit(sumVector, 0.0);
+        psImageInit(sumMatrix, 0.0);
+        int numStamps = 0;              // Number of good stamps
+        for (int i = 0; i < stamps->num; i++) {
+            pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest
+            if (stamp->status == PM_SUBTRACTION_STAMP_USED) {
+                (void)psBinaryOp(sumMatrix, sumMatrix, "+", stamp->matrix1);
+                (void)psBinaryOp(sumVector, sumVector, "+", stamp->vector1);
+                numStamps++;
+            }
+        }
+        calculatePenalty(sumVector, kernels);
+
+        psVector *permutation = NULL;       // Permutation vector, required for LU decomposition
+        psImage *luMatrix = psMatrixLUD(NULL, &permutation, sumMatrix);
+        psFree(sumMatrix);
+        if (!luMatrix) {
+            psError(PS_ERR_UNKNOWN, true, "LU Decomposition of least-squares matrix failed.\n");
+            psFree(sumVector);
+            psFree(luMatrix);
+            psFree(permutation);
+            return NULL;
+        }
+        kernels->solution1 = psMatrixLUSolve(kernels->solution1, luMatrix, sumVector, permutation);
+        psFree(sumVector);
+        psFree(luMatrix);
+        psFree(permutation);
+        if (!kernels->solution1) {
+            psError(PS_ERR_UNKNOWN, true, "Failed to solve the least-squares system.\n");
+            return NULL;
+        }
+    } else {
+        // Dual convolution solution
+
+        // Accumulation of stamp matrices/vectors
+        psImage *sumMatrix1 = psImageAlloc(numParams, numParams, PS_TYPE_F64);
+        psImage *sumMatrix2 = psImageAlloc(numParams2, numParams2, PS_TYPE_F64);
+        psImage *sumMatrixX = psImageAlloc(numParams, numParams2, PS_TYPE_F64);
+        psVector *sumVector1 = psVectorAlloc(numParams, PS_TYPE_F64);
+        psVector *sumVector2 = psVectorAlloc(numParams, PS_TYPE_F64);
+        psImageInit(sumMatrix1, 0.0);
+        psImageInit(sumMatrix2, 0.0);
+        psImageInit(sumMatrixX, 0.0);
+        psVectorInit(sumVector1, 0.0);
+        psVectorInit(sumVector2, 0.0);
+
+        int numStamps = 0;              // Number of good stamps
+        for (int i = 0; i < stamps->num; i++) {
+            pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest
+            if (stamp->status == PM_SUBTRACTION_STAMP_USED) {
+                (void)psBinaryOp(sumMatrix1, sumMatrix1, "+", stamp->matrix1);
+                (void)psBinaryOp(sumMatrix2, sumMatrix2, "+", stamp->matrix2);
+                (void)psBinaryOp(sumMatrixX, sumMatrixX, "+", stamp->matrixX);
+                (void)psBinaryOp(sumVector1, sumVector1, "+", stamp->vector1);
+                (void)psBinaryOp(sumVector2, sumVector2, "+", stamp->vector2);
+                numStamps++;
+            }
+        }
+        calculatePenalty(sumVector1, kernels);
+        calculatePenalty(sumVector2, kernels);
+
+#if 0
+        // Apply weighting to maximise the difference between solution coefficients for the same functions
+        double fudge = PS_SQR(2 * stamps->footprint + 1); // Fudge factor
+        for (int i = 0; i < kernels->num; i++) {
+            sumMatrix1->data.F64[i][i] -= fudge;
+            sumMatrix2->data.F64[i][i] += fudge;
+        }
+#endif
+
+        // Pure matrix operations
+
+        // A * a = Ct * b + d
+        // C * a = B  * b + e
+        //
+        // a = (Ct * Bi * C - A)i (Ct * Bi * e - d)
+        // b = Bi * (C * a - e)
+        psVector *a = psVectorRecycle(kernels->solution1, numParams, PS_TYPE_F64);
+        psVector *b = psVectorRecycle(kernels->solution2, numParams2, PS_TYPE_F64);
+#ifdef TESTING
+        psVectorInit(a, NAN);
+        psVectorInit(b, NAN);
+#endif
+        psImage *A = sumMatrix1;
+        psImage *B = sumMatrix2;
+        psImage *C = sumMatrixX;
+        psVector *d = sumVector1;
+        psVector *e = sumVector2;
+
+        assert(a->n == numParams);
+        assert(b->n == numParams2);
+        assert(A->numRows == numParams && A->numCols == numParams);
+        assert(B->numRows == numParams2 && B->numCols == numParams2);
+        assert(C->numRows == numParams2 && C->numCols == numParams);
+        assert(d->n == numParams);
+        assert(e->n == numParams2);
+
+        psImage *Bi = psMatrixInvert(NULL, B, NULL);
+        assert(Bi->numRows == numParams2 && Bi->numCols == numParams2);
+        psImage *Ct = psMatrixTranspose(NULL, C);
+        assert(Ct->numRows == numParams && Ct->numCols == numParams2);
+
+        psImage *BiC = psMatrixMultiply(NULL, Bi, C);
+        assert(BiC->numRows == numParams2 && BiC->numCols == numParams);
+        psImage *CtBi = psMatrixMultiply(NULL, Ct, Bi);
+        assert(CtBi->numRows == numParams && CtBi->numCols == numParams2);
+
+        psImage *CtBiC = psMatrixMultiply(NULL, Ct, BiC);
+        assert(CtBiC->numRows == numParams && CtBiC->numCols == numParams);
+
+        psImage *F = (psImage*)psBinaryOp(NULL, CtBiC, "-", A);
+        assert(F->numRows == numParams && F->numCols == numParams);
+        float det = 0.0;
+        psImage *Fi = psMatrixInvert(NULL, F, &det);
+        assert(Fi->numRows == numParams && Fi->numCols == numParams);
+        psTrace("psModules.imcombine", 4, "Determinant of F: %f\n", det);
+
+        psVector *g = psVectorAlloc(numParams, PS_TYPE_F64);
+#ifdef TESTING
+        psVectorInit(g, NAN);
+#endif
+        assert(CtBi->numRows == numParams && CtBi->numCols == numParams2);
+        assert(e->n == numParams2);
+        assert(d->n == numParams);
+        for (int i = 0; i < numParams; i++) {
+            double value = 0.0;
+            for (int j = 0; j < numParams2; j++) {
+                value += CtBi->data.F64[i][j] * e->data.F64[j];
+            }
+            g->data.F64[i] = value - d->data.F64[i];
+        }
+
+        assert(Fi->numRows == numParams && Fi->numCols == numParams);
+        assert(g->n == numParams);
+        for (int i = 0; i < numParams; i++) {
+            double value = 0.0;
+            for (int j = 0; j < numParams; j++) {
+                value += Fi->data.F64[i][j] * g->data.F64[j];
+            }
+            a->data.F64[i] = value;
+        }
+
+        psVector *h = psVectorAlloc(numParams2, PS_TYPE_F64);
+#ifdef TESTING
+        psVectorInit(h, NAN);
+#endif
+        assert(C->numRows == numParams2 && C->numCols == numParams);
+        assert(a->n == numParams);
+        assert(e->n == numParams2);
+        for (int i = 0; i < numParams2; i++) {
+            double value = 0.0;
+            for (int j = 0; j < numParams; j++) {
+                value += C->data.F64[i][j] * a->data.F64[j];
+            }
+            h->data.F64[i] = value - e->data.F64[i];
+        }
+
+        assert(Bi->numRows == numParams2 && Bi->numCols == numParams2);
+        assert(h->n == numParams2);
+        for (int i = 0; i < numParams2; i++) {
+            double value = 0.0;
+            for (int j = 0; j < numParams2; j++) {
+                value += Bi->data.F64[i][j] * h->data.F64[j];
+            }
+            b->data.F64[i] = value;
+        }
+
+
+#if 0
+        for (int i = 0; i < numParams; i++) {
+            double aVal1 = 0.0, bVal1 = 0.0;
+            for (int j = 0; j < numParams2; j++) {
+                aVal1 += A->data.F64[i][j] * a->data.F64[j];
+                bVal1 += Ct->data.F64[i][j] * b->data.F64[j];
+            }
+            bVal1 += d->data.F64[i];
+            for (int j = numParams2; j < numParams; j++) {
+                aVal1 += A->data.F64[i][j] * a->data.F64[j];
+            }
+            printf("%d: %lf\n", i, aVal1 - bVal1);
+        }
+
+        for (int i = 0; i < numParams2; i++) {
+            double aVal2 = 0.0, bVal2 = 0.0;
+            for (int j = 0; j < numParams2; j++) {
+                aVal2 += C->data.F64[i][j] * a->data.F64[j];
+                bVal2 += B->data.F64[i][j] * b->data.F64[j];
+            }
+            bVal2 += e->data.F64[i];
+            for (int j = numParams2; j < numParams; j++) {
+                aVal2 += C->data.F64[i][j] * a->data.F64[j];
+            }
+            printf("%d: %lf\n", i, aVal2 - bVal2);
+        }
+#endif
+
+        {
+            psFits *fits = psFitsOpen("sumMatrix1.fits", "w");
+            psFitsWriteImage(fits, NULL, sumMatrix1, 0, NULL);
+            psFitsClose(fits);
+        }
+        {
+            psFits *fits = psFitsOpen("sumMatrix2.fits", "w");
+            psFitsWriteImage(fits, NULL, sumMatrix2, 0, NULL);
+            psFitsClose(fits);
+        }
+        {
+            psFits *fits = psFitsOpen("sumMatrixX.fits", "w");
+            psFitsWriteImage(fits, NULL, sumMatrixX, 0, NULL);
+            psFitsClose(fits);
+        }
+        {
+            psFits *fits = psFitsOpen("sumFinverse.fits", "w");
+            psFitsWriteImage(fits, NULL, Fi, 0, NULL);
+            psFitsClose(fits);
+        }
+
+
+        kernels->solution1 = a;
+        kernels->solution2 = b;
+
+        // XXXXX Free temporary matrices and vectors
+
+    }
+
+    if (psTraceGetLevel("psModules.imcombine") >= 7) {
+        for (int i = 0; i < kernels->solution1->n; i++) {
+            psTrace("psModules.imcombine", 7, "Solution 1 %d: %f\n", i, kernels->solution1->data.F64[i]);
+        }
+        if (kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
+            for (int i = 0; i < kernels->solution2->n; i++) {
+                psTrace("psModules.imcombine", 7, "Solution 2 %d: %f\n", i, kernels->solution2->data.F64[i]);
+            }
+        }
+     }
+
+    return true;
+}
+
+psVector *pmSubtractionCalculateDeviations(pmSubtractionStampList *stamps,
+                                           const pmSubtractionKernels *kernels)
+{
+    PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, NULL);
+    PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, NULL);
+    PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(kernels, NULL);
+
+    psVector *deviations = psVectorAlloc(stamps->num, PS_TYPE_F32); // Mean deviation for stamps
+    int footprint = stamps->footprint; // Half-size of stamps
+    long numPixels = PS_SQR(2 * footprint + 1); // Number of pixels in footprint
+    double devNorm = 1.0 / (double)numPixels; // Normalisation for deviations
+    int numKernels = kernels->num;      // Number of kernels
+
+    psImage *polyValues = NULL;         // Polynomial values
+    psKernel *residual = psKernelAlloc(-footprint, footprint, -footprint, footprint); // Residual image
+
+    for (int i = 0; i < stamps->num; i++) {
+        pmSubtractionStamp *stamp = stamps->stamps->data[i]; // The stamp of interest
+        if (stamp->status != PM_SUBTRACTION_STAMP_USED) {
+            deviations->data.F32[i] = NAN;
+            continue;
+        }
+
+        // Calculate coefficients of the kernel basis functions
+        polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, stamp->xNorm, stamp->yNorm);
+        double norm = p_pmSubtractionSolutionNorm(kernels); // Normalisation
+        double background = p_pmSubtractionSolutionBackground(kernels, polyValues);// Difference in background
+
+        // Calculate residuals
+        psKernel *weight = stamp->weight; // Weight postage stamp
+        psImageInit(residual->image, 0.0);
+        if (kernels->mode != PM_SUBTRACTION_MODE_DUAL) {
+            psKernel *target;           // Target postage stamp
+            psKernel *source;           // Source postage stamp
+            psArray *convolutions;      // Convolution postage stamps for each kernel basis function
+            switch (kernels->mode) {
+              case PM_SUBTRACTION_MODE_1:
+                target = stamp->image2;
+                source = stamp->image1;
+                convolutions = stamp->convolutions1;
+                break;
+              case PM_SUBTRACTION_MODE_2:
+                target = stamp->image1;
+                source = stamp->image2;
+                convolutions = stamp->convolutions2;
+                break;
+              default:
+                psAbort("Unsupported subtraction mode: %x", kernels->mode);
+            }
+
+            for (int j = 0; j < numKernels; j++) {
+                psKernel *convolution = convolutions->data[j]; // Convolution
+                double coefficient = p_pmSubtractionSolutionCoeff(kernels, polyValues, j,
+                                                                  false); // Coefficient
+                for (int y = - footprint; y <= footprint; y++) {
+                    for (int x = - footprint; x <= footprint; x++) {
+                        residual->kernel[y][x] -= convolution->kernel[y][x] * coefficient;
+                    }
+                }
+            }
+            for (int y = - footprint; y <= footprint; y++) {
+                for (int x = - footprint; x <= footprint; x++) {
+                    residual->kernel[y][x] += target->kernel[y][x] - background - source->kernel[y][x] * norm;
+                }
+            }
+        } else {
+            // Dual convolution
+            psArray *convolutions1 = stamp->convolutions1; // Convolutions of the first image
+            psArray *convolutions2 = stamp->convolutions2; // Convolutions of the second image
+            psKernel *image1 = stamp->image1; // The first image
+            psKernel *image2 = stamp->image2; // The second image
+
+            for (int j = 0; j < numKernels; j++) {
+                psKernel *conv1 = convolutions1->data[j]; // Convolution of first image
+                psKernel *conv2 = convolutions2->data[j]; // Convolution of second image
+                double coeff1 = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, false); // Coefficient 1
+                double coeff2 = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, true); // Coefficient 2
+
+                for (int y = - footprint; y <= footprint; y++) {
+                    for (int x = - footprint; x <= footprint; x++) {
+                        residual->kernel[y][x] += conv2->kernel[y][x] * coeff2 - conv1->kernel[y][x] * coeff1;
+                    }
+                }
+            }
+            for (int y = - footprint; y <= footprint; y++) {
+                for (int x = - footprint; x <= footprint; x++) {
+                    residual->kernel[y][x] += image2->kernel[y][x] - background - image1->kernel[y][x] * norm;
+                }
+            }
+        }
+
+        double deviation = 0.0;         // Sum of differences
+        for (int y = - footprint; y <= footprint; y++) {
+            for (int x = - footprint; x <= footprint; x++) {
+                double dev = PS_SQR(residual->kernel[y][x]) / weight->kernel[y][x];
+                deviation += dev;
+#ifdef TESTING
+                residual->kernel[y][x] = dev;
+#endif
+            }
+        }
+        deviations->data.F32[i] = sqrtf(devNorm * deviation);
+        psTrace("psModules.imcombine", 5, "Deviation for stamp %d (%d,%d): %f\n",
+                i, (int)(stamp->x + 0.5), (int)(stamp->y + 0.5), deviations->data.F32[i]);
+        if (!isfinite(deviations->data.F32[i])) {
+            stamp->status = PM_SUBTRACTION_STAMP_REJECTED;
+            psTrace("psModules.imcombine", 5,
+                    "Rejecting stamp %d (%d,%d) because of non-finite deviation\n",
+                    i, (int)(stamp->x + 0.5), (int)(stamp->y + 0.5));
+            continue;
+        }
+
+#ifdef TESTING
+        {
+            psString filename = NULL;
+            psStringAppend(&filename, "resid_%03d.fits", i);
+            psFits *fits = psFitsOpen(filename, "w");
+            psFree(filename);
+            psFitsWriteImage(fits, NULL, residual->image, 0, NULL);
+            psFitsClose(fits);
+        }
+        {
+            psString filename = NULL;
+            psStringAppend(&filename, "stamp_image_%03d.fits", i);
+            psFits *fits = psFitsOpen(filename, "w");
+            psFree(filename);
+            psFitsWriteImage(fits, NULL, stamp->image1->image, 0, NULL);
+            psFitsClose(fits);
+        }
+        {
+            psString filename = NULL;
+            psStringAppend(&filename, "stamp_weight_%03d.fits", i);
+            psFits *fits = psFitsOpen(filename, "w");
+            psFree(filename);
+            psFitsWriteImage(fits, NULL, stamp->weight->image, 0, NULL);
+            psFitsClose(fits);
+        }
+#endif
+
+    }
+    psFree(residual);
+    psFree(polyValues);
+
+    return deviations;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionEquation.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionEquation.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionEquation.h	(revision 22158)
@@ -0,0 +1,46 @@
+#ifndef PM_SUBTRACTION_EQUATION_H
+#define PM_SUBTRACTION_EQUATION_H
+
+#include "pmSubtractionStamps.h"
+#include "pmSubtractionKernels.h"
+
+/// Calculate the least-squares equation to match the image quality
+bool pmSubtractionCalculateEquation(pmSubtractionStampList *stamps, ///< Stamps
+                                    const pmSubtractionKernels *kernels ///< Kernel parameters
+                                    );
+
+/// Solve the least-squares equation to match the image quality
+bool pmSubtractionSolveEquation(pmSubtractionKernels *kernels, ///< Kernel parameters
+                                const pmSubtractionStampList *stamps ///< Stamps
+    );
+
+/// Calculate deviations
+psVector *pmSubtractionCalculateDeviations(pmSubtractionStampList *stamps, ///< Stamps
+                                           const pmSubtractionKernels *kernels ///< Kernel parameters
+    );
+
+/// Calculate the value of a polynomial, specified by coefficients and polynomial values
+double p_pmSubtractionCalculatePolynomial(const psVector *coeff, ///< Coefficients
+                                          const psImage *polyValues, ///< Polynomial values
+                                          int order, ///< Order of polynomials
+                                          int index, ///< Index at which to begin
+                                          int step ///< Step between subsequent indices
+    );
+
+/// Return the specified coefficient in the solution
+double p_pmSubtractionSolutionCoeff(const pmSubtractionKernels *kernels, ///< Kernel parameters
+                                    const psImage *polyValues, ///< Polynomial values
+                                    int index, ///< Coefficient index to calculate
+                                    bool wantDual ///< Calculate the coefficient for the dual solution?
+    );
+
+/// Return the normalisation in the solution
+double p_pmSubtractionSolutionNorm(const pmSubtractionKernels *kernels ///< Kernel parameters
+    );
+
+/// Return the background (difference) in the solution
+double p_pmSubtractionSolutionBackground(const pmSubtractionKernels *kernels, ///< Kernel parameters
+                                         const psImage *polyValues ///< Polynomial values
+    );
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionIO.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionIO.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionIO.c	(revision 22158)
@@ -0,0 +1,284 @@
+#include <stdio.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+
+#include "pmSubtraction.h"
+#include "pmSubtractionKernels.h"
+#include "pmSubtractionMatch.h"
+
+#define ARRAY_BUFFER 16                 // Number to add to array at a time
+
+// Names of FITS table columns
+#define NAME_XMIN "XMIN"                // Region of applicability: minimum x value
+#define NAME_XMAX "XMAX"                // Region of applicability: maximum x value
+#define NAME_YMIN "YMIN"                // Region of applicability: minimum y value
+#define NAME_YMAX "YMAX"                // Region of applicability: maximum y value
+#define NAME_KERNEL "KERNEL"            // Kernel description
+#define NAME_TYPE "TYPE"                // Kernel type
+#define NAME_SIZE "SIZE"                // Kernel half-size
+#define NAME_INNER "INNER"              // Size of inner region (only applicable for some kernel types)
+#define NAME_SPATIAL "SPATIAL_ORDER"    // Order of spatial polynomial
+#define NAME_BG "BG_ORDER"              // Order of background polynomial
+#define NAME_MODE "MODE"                // Matching mode
+#define NAME_COLS "COLUMNS"             // Number of columns
+#define NAME_ROWS "ROWS"                // Number of rows
+#define NAME_SOL1 "SOLUTION_1"          // Solution for convolving image 1
+#define NAME_SOL2 "SOLUTION_2"          // Solution for convolving image 2
+
+
+// Generate an extension name for the subtraction kernel
+static psString subtractionKernelExtname(const pmReadout *ro // Readout containing kernel
+                                         )
+{
+    psAssert(ro, "Required parameter");
+
+    psString extname = NULL;            // Name of FITS extension
+    pmCell *cell = ro->parent;     // Parent cell
+    if (cell && cell->parent) {
+        pmChip *chip = cell->parent;        // Parent chip
+        const char *chipName = psMetadataLookupStr(NULL, chip->concepts, "CHIP.NAME"); // Name of chip
+        const char *cellName = psMetadataLookupStr(NULL, cell->concepts, "CELL.NAME"); // Name of cell
+        psAssert(chipName && cellName, "Chip and cell names should be defined in concepts.");
+        int roNum = -1;                 // Index of readout
+        for (int i = 0; i < cell->readouts->n && roNum == -1; i++) {
+            if (cell->readouts->data[i] == ro) {
+                roNum = i;
+            }
+        }
+        if (roNum != -1) {
+            psStringAppend(&extname, "%s_%s_%d", chipName, cellName, roNum);
+        } else {
+            psWarning("Unable to find readout number");
+        }
+    }
+
+    if (!extname) {
+        extname = psStringCopy("SUBTRACTION_KERNEL");
+    }
+
+    return extname;
+}
+
+bool pmReadoutWriteSubtractionKernels(pmReadout *ro, psFits *fits)
+{
+    PM_ASSERT_READOUT_NON_NULL(ro, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+
+    // Extract the regions and solutions used in the image matching
+    psArray *regions = psArrayAllocEmpty(ARRAY_BUFFER); // Array of regions
+    {
+        psString regex = NULL;          // Regular expression
+        psStringAppend(&regex, "^%s$", PM_SUBTRACTION_ANALYSIS_REGION);
+        psMetadataIterator *iter = psMetadataIteratorAlloc(ro->analysis, PS_LIST_HEAD, regex); // Iterator
+        psFree(regex);
+        psMetadataItem *item = NULL;// Item from iteration
+        while ((item = psMetadataGetAndIncrement(iter))) {
+            assert(item->type == PS_DATA_REGION);
+            regions = psArrayAdd(regions, ARRAY_BUFFER, item->data.V);
+        }
+        psFree(iter);
+    }
+    if (regions->n == 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "No subtraction regions found.");
+        psFree(regions);
+        return false;
+    }
+
+    psArray *kernels = psArrayAllocEmpty(ARRAY_BUFFER); // Array of kernels
+    {
+        psString regex = NULL;          // Regular expression
+        psStringAppend(&regex, "^%s$", PM_SUBTRACTION_ANALYSIS_KERNEL);
+        psMetadataIterator *iter = psMetadataIteratorAlloc(ro->analysis, PS_LIST_HEAD, regex); // Iterator
+        psFree(regex);
+        psMetadataItem *item = NULL;// Item from iteration
+        while ((item = psMetadataGetAndIncrement(iter))) {
+            assert(item->type == PS_DATA_UNKNOWN);
+            // Set the normalisation dimensions, since these will be otherwise unavailable when reading the
+            // images by scans.
+            pmSubtractionKernels *kernel = item->data.V; // Kernel used in subtraction
+            kernel->numCols = ro->image->numCols;
+            kernel->numRows = ro->image->numRows;
+
+            kernels = psArrayAdd(kernels, ARRAY_BUFFER, kernel);
+        }
+        psFree(iter);
+    }
+
+    if (regions->n != kernels->n) {
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Number of regions (%ld) and kernels (%ld) don't match.\n",
+                regions->n, kernels->n);
+        psFree(regions);
+        psFree(kernels);
+        return false;
+    }
+
+    // Format for writing a table
+    int num = regions->n;              // Number of regions and kernels
+    psArray *rows = psArrayAlloc(num); // Array of FITS table rows
+    for (int i = 0; i < num; i++) {
+        psMetadata *row = psMetadataAlloc(); // Row of interest
+        rows->data[i] = psMemIncrRefCounter(row);
+
+        psRegion *region = regions->data[i]; // Region of interest
+        psMetadataAddS32(row, PS_LIST_TAIL, NAME_XMIN,  0, "Applicability minimum x", region->x0);
+        psMetadataAddS32(row, PS_LIST_TAIL, NAME_XMAX,  0, "Applicability maximum x", region->x1);
+        psMetadataAddS32(row, PS_LIST_TAIL, NAME_YMIN,  0, "Applicability minimum y", region->y0);
+        psMetadataAddS32(row, PS_LIST_TAIL, NAME_YMAX,  0, "Applicability maximum y", region->y1);
+
+        pmSubtractionKernels *kernel = kernels->data[i]; // Kernel
+        psMetadataAddStr(row, PS_LIST_TAIL, NAME_KERNEL, 0, "Kernel description", kernel->description);
+
+#if 0
+        psMetadataAddS32(row, PS_LIST_TAIL, NAME_TYPE,  0, "Kernel type (enum)", kernel->type);
+        psMetadataAddS32(row, PS_LIST_TAIL, NAME_SIZE,  0, "Kernel half-size", kernel->size);
+        psMetadataAddS32(row, PS_LIST_TAIL, NAME_INNER, 0, "Size of inner region", kernel->inner);
+        psMetadataAddS32(row, PS_LIST_TAIL, NAME_SPATIAL, 0, "Polynomial order for spatial variations",
+                         kernel->spatialOrder);
+#endif
+
+        psMetadataAddS32(row, PS_LIST_TAIL, NAME_BG,  0, "Polynomial order for background fitting",
+                         kernel->bgOrder);
+        psMetadataAddS32(row, PS_LIST_TAIL, NAME_MODE,  0, "Matching mode (enum)", kernel->mode);
+        psMetadataAddS32(row, PS_LIST_TAIL, NAME_COLS,  0, "Number of columns", kernel->numCols);
+        psMetadataAddS32(row, PS_LIST_TAIL, NAME_ROWS,  0, "Number of rows", kernel->numRows);
+        if (kernel->mode == PM_SUBTRACTION_MODE_1 || kernel->mode == PM_SUBTRACTION_MODE_DUAL) {
+            psMetadataAddVector(row, PS_LIST_TAIL, NAME_SOL1, 0, "Solution vector 1", kernel->solution1);
+        }
+        if (kernel->mode == PM_SUBTRACTION_MODE_2 || kernel->mode == PM_SUBTRACTION_MODE_DUAL) {
+            psMetadataAddVector(row, PS_LIST_TAIL, NAME_SOL2, 0, "Solution vector 2", kernel->solution2);
+        }
+    }
+    psFree(regions);
+    psFree(kernels);
+
+    psMetadata *header = psMetadataAlloc(); // Header for FITS file
+
+    // CVS tags, used to identify the version of this file (in case incompatibilities are introduced)
+    psString cvsFile = psStringCopy("$RCSfile: pmSubtractionIO.c,v $");
+    psString cvsRev  = psStringCopy("$Revision: 1.1 $");
+    psString cvsDate = psStringCopy("$Date: 2008-06-16 21:59:43 $");
+    psStringSubstitute(&cvsFile, NULL, "RCSfile: ");
+    psStringSubstitute(&cvsRev,  NULL, "Revision: ");
+    psStringSubstitute(&cvsDate, NULL, "Date: ");
+
+    psString version = NULL;            // Version information, for header
+    psStringAppend(&version, "%s %s %s", cvsFile, cvsRev, cvsDate);
+    psFree(cvsFile);
+    psFree(cvsRev);
+    psFree(cvsDate);
+    psStringSubstitute(&version, NULL, "$");
+    psMetadataAddStr(header, PS_LIST_TAIL, "PSVERSION", 0, "S/W version", version);
+    psFree(version);
+
+    psString extname = subtractionKernelExtname(ro); // Extension name
+
+    if (!psFitsWriteTable(fits, header, rows, extname)) {
+        psError(PS_ERR_IO, false, "Unable to write subtraction kernel to FITS table.");
+        psFree(header);
+        psFree(rows);
+        psFree(extname);
+        return false;
+    }
+
+    psFree(header);
+    psFree(rows);
+    psFree(extname);
+
+    return true;
+}
+
+
+bool pmReadoutReadSubtractionKernels(pmReadout *ro, psFits *fits)
+{
+    PM_ASSERT_READOUT_NON_NULL(ro, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    psString extname = subtractionKernelExtname(ro); // Extension name
+    if (!psFitsMoveExtName(fits, extname)) {
+        psError(PS_ERR_IO, false, "Unable to move to subtraction kernel table.");
+        psFree(extname);
+        return false;
+    }
+    psFree(extname);
+
+    psArray *table = psFitsReadTable(fits); // Table of interest
+    if (!table) {
+        psError(PS_ERR_IO, false, "Unable to read FITS table");
+        return false;
+    }
+
+    // Look up a column value for a row
+#define TABLE_LOOKUP(TYPE, SUFFIX, TARGET, NAME) \
+    TYPE TARGET; \
+    { \
+        bool mdok; \
+        TARGET = psMetadataLookup##SUFFIX(&mdok, row, NAME); \
+        if (!mdok) { \
+            psError(PS_ERR_UNKNOWN, false, "Unable to find column %s in subtraction kernel table.", NAME); \
+            psFree(table); \
+            return false; \
+        } \
+    }
+
+    for (int i = 0; i < table->n; i++) {
+        psMetadata *row = table->data[i]; // Table row
+
+        TABLE_LOOKUP(int, S32, xMin, NAME_XMIN);
+        TABLE_LOOKUP(int, S32, xMax, NAME_XMAX);
+        TABLE_LOOKUP(int, S32, yMin, NAME_YMIN);
+        TABLE_LOOKUP(int, S32, yMax, NAME_YMAX);
+
+        psRegion *region = psRegionAlloc(xMin, xMax, yMin, yMax); // Region of applicability
+        psMetadataAddPtr(ro->analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_REGION, PS_DATA_REGION,
+                         "Subtraction region", region);
+        psFree(region);
+
+        TABLE_LOOKUP(const char *, Str, description, NAME_KERNEL);
+        TABLE_LOOKUP(pmSubtractionMode, S32, mode,    NAME_MODE);
+
+#if 0
+        TABLE_LOOKUP(int, S32, size,    NAME_SIZE);
+        TABLE_LOOKUP(int, S32, inner,   NAME_INNER);
+        TABLE_LOOKUP(int, S32, spatial, NAME_SPATIAL);
+#endif
+
+        TABLE_LOOKUP(int, S32, bg,      NAME_BG);
+        TABLE_LOOKUP(int, S32, numCols, NAME_COLS);
+        TABLE_LOOKUP(int, S32, numRows, NAME_ROWS);
+
+        pmSubtractionKernels *kernels = pmSubtractionKernelsFromDescription(description, bg, mode);
+        kernels->numCols = numCols;
+        kernels->numRows = numRows;
+
+        bool mdok;                      // Status of MD lookup
+        if (mode == PM_SUBTRACTION_MODE_1 || mode == PM_SUBTRACTION_MODE_DUAL) {
+            kernels->solution1 = psMemIncrRefCounter(psMetadataLookupPtr(&mdok, row, NAME_SOL1));
+            if (!mdok) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to find column %s in subtraction kernel table.",
+                        NAME_SOL1);
+                psFree(kernels);
+                psFree(table);
+                return false;
+            }
+        }
+        if (mode == PM_SUBTRACTION_MODE_2 || mode == PM_SUBTRACTION_MODE_DUAL) {
+            kernels->solution2 = psMemIncrRefCounter(psMetadataLookupPtr(&mdok, row, NAME_SOL2));
+            if (!mdok) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to find column %s in subtraction kernel table.",
+                        NAME_SOL2);
+                psFree(kernels);
+                psFree(table);
+                return false;
+            }
+        }
+
+        psMetadataAddPtr(ro->analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_KERNEL, PS_DATA_UNKNOWN,
+                         "Subtraction kernels", kernels);
+        psFree(kernels);
+    }
+    psFree(table);
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionIO.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionIO.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionIO.h	(revision 22158)
@@ -0,0 +1,22 @@
+#ifndef PM_SUBTRACTION_IO_H
+#define PM_SUBTRACTION_IO_H
+
+#include <pslib.h>
+
+#include <pmHDU.h>
+#include <pmFPA.h>
+
+/// Write subtraction kernels within a readout to a FITS file
+bool pmReadoutWriteSubtractionKernels(
+    pmReadout *readout,                 ///< Readout for which to write subtraction kernels (in analysis MD)
+    psFits *fits                        ///< FITS file to which to write
+    );
+
+
+bool pmReadoutReadSubtractionKernels(
+    pmReadout *readout,                 ///< Readout for which to read subtraction kernels (into analysis MD)
+    psFits *fits                        ///< FITS file to which to write
+    );
+
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionKernels.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionKernels.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionKernels.c	(revision 22158)
@@ -0,0 +1,759 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <pslib.h>
+
+#include "pmSubtraction.h"
+#include "pmSubtractionKernels.h"
+
+#define RINGS_BUFFER 10                 // Buffer size for RINGS data
+
+
+// Free function for pmSubtractionKernels
+static void subtractionKernelsFree(pmSubtractionKernels *kernels)
+{
+    psFree(kernels->description);
+    psFree(kernels->u);
+    psFree(kernels->v);
+    psFree(kernels->widths);
+    psFree(kernels->uStop);
+    psFree(kernels->vStop);
+    psFree(kernels->preCalc);
+    psFree(kernels->penalties);
+    psFree(kernels->solution1);
+    psFree(kernels->solution2);
+}
+
+// Raise an integer to an integer power
+static inline long power(int value,     // Value
+                         int exp        // Exponent
+    )
+{
+    if (exp == 0) {
+        return 1.0;
+    }
+    long result = value;               // Result to return
+    for (int i = 2; i <= exp; i++) {
+        result *= value;
+    }
+    return result;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Semi-public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool p_pmSubtractionKernelsAddGrid(pmSubtractionKernels *kernels, int start, int size)
+{
+    PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, false);
+    PS_ASSERT_INT_NONNEGATIVE(start, false);
+    PS_ASSERT_INT_NONNEGATIVE(size, false);
+
+    int numNew = PS_SQR(2 * size + 1) - 1;  // Number of new kernel parameters to add
+
+    // Ensure the sizes match
+    kernels->widths = psVectorRealloc(kernels->widths, start + numNew);
+    kernels->u = psVectorRealloc(kernels->u, start + numNew);
+    kernels->v = psVectorRealloc(kernels->v, start + numNew);
+    kernels->preCalc = psArrayRealloc(kernels->preCalc, start + numNew);
+    kernels->penalties = psVectorRealloc(kernels->penalties, start + numNew);
+    kernels->inner = start;
+
+    // Generate a set of kernels for each (u,v)
+    for (int v = - size, index = start; v <= size; v++) {
+        for (int u = - size; u <= size; u++, index++) {
+            if (v == 0 && u == 0) {
+                // Skip normalisation component: added explicitly
+                index--;
+                continue;
+            }
+            kernels->widths->data.F32[index] = NAN;
+            kernels->u->data.S32[index] = u;
+            kernels->v->data.S32[index] = v;
+            kernels->preCalc->data[index] = NULL;
+            kernels->penalties->data.F32[index] = kernels->penalty * (PS_SQR(u) + PS_SQR(v));
+
+            psTrace("psModules.imcombine", 7, "Kernel %d: %d %d\n", index, u, v);
+        }
+    }
+
+    return true;
+}
+
+pmSubtractionKernels *p_pmSubtractionKernelsRawISIS(int size, int spatialOrder,
+                                                    const psVector *fwhms, const psVector *orders,
+                                                    float penalty, pmSubtractionMode mode)
+{
+    PS_ASSERT_VECTOR_NON_NULL(fwhms, NULL);
+    PS_ASSERT_VECTOR_TYPE(fwhms, PS_TYPE_F32, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(orders, NULL);
+    PS_ASSERT_VECTOR_TYPE(orders, PS_TYPE_S32, NULL);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(fwhms, orders, NULL);
+    PS_ASSERT_INT_POSITIVE(size, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(spatialOrder, NULL);
+
+    int numGaussians = fwhms->n;       // Number of Gaussians
+
+    int num = 0;                        // Number of basis functions
+    psString params = NULL;             // List of parameters
+    for (int i = 0; i < numGaussians; i++) {
+        int gaussOrder = orders->data.S32[i]; // Polynomial order to apply to Gaussian
+        psStringAppend(&params, "(%.1f,%d)", fwhms->data.F32[i], orders->data.S32[i]);
+        num += (gaussOrder + 1) * (gaussOrder + 2) / 2;
+    }
+
+    pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_ISIS, size,
+                                                              spatialOrder, penalty, mode); // The kernels
+    psStringAppend(&kernels->description, "ISIS(%d,%s,%d,%.2e)", size, params, spatialOrder, penalty);
+
+    psLogMsg("psModules.imcombine", PS_LOG_INFO, "ISIS kernel: %s,%d --> %d elements",
+             params, spatialOrder, num);
+    psFree(params);
+
+    // Set the kernel parameters
+    for (int i = 0, index = 0; i < numGaussians; i++) {
+        float sigma = fwhms->data.F32[i] / (2.0 * sqrtf(2.0 * logf(2.0))); // Gaussian sigma
+        float norm = 1.0 / (M_2_PI * sqrtf(sigma)); // Normalisation for Gaussian
+        // Iterate over (u,v) order
+        for (int uOrder = 0; uOrder <= orders->data.S32[i]; uOrder++) {
+            for (int vOrder = 0; vOrder <= orders->data.S32[i] - uOrder; vOrder++, index++) {
+                // Set the pre-calculated kernel
+                psKernel *preCalc = psKernelAlloc(-size, size, -size, size);
+                double sum = 0.0;       // Normalisation
+                double moment = 0.0;    // Moment, for penalty
+                for (int v = -size; v <= size; v++) {
+                    for (int u = -size; u <= size; u++) {
+                        sum += preCalc->kernel[v][u] = norm * power(u, uOrder) * power(v, vOrder) *
+                            expf(-0.5 * (PS_SQR(u) + PS_SQR(v)) / PS_SQR(sigma));
+                        moment += preCalc->kernel[v][u] * (PS_SQR(u) + PS_SQR(v));
+                    }
+                }
+
+                // Normalise sum of kernel component to unity for even functions
+                if (uOrder % 2 == 0 && vOrder % 2 == 0) {
+                    for (int v = -size; v <= size; v++) {
+                        for (int u = -size; u <= size; u++) {
+                            preCalc->kernel[v][u] = preCalc->kernel[v][u] / sum;
+                        }
+                    }
+                    preCalc->kernel[0][0] -= 1.0;
+                }
+
+                kernels->widths->data.F32[index] = fwhms->data.F32[i];
+                kernels->u->data.S32[index] = uOrder;
+                kernels->v->data.S32[index] = vOrder;
+                if (kernels->preCalc->data[index]) {
+                    psFree(kernels->preCalc->data[index]);
+                }
+                kernels->preCalc->data[index] = preCalc;
+                kernels->penalties->data.F32[index] = kernels->penalty * fabsf(moment);
+
+                psTrace("psModules.imcombine", 7, "Kernel %d: %f %d %d %f\n", index,
+                        fwhms->data.F32[i], uOrder, vOrder, fabsf(moment));
+            }
+        }
+    }
+
+    return kernels;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+pmSubtractionKernels *pmSubtractionKernelsAlloc(int numBasisFunctions, pmSubtractionKernelsType type,
+                                                int size, int spatialOrder, float penalty,
+                                                pmSubtractionMode mode)
+{
+    pmSubtractionKernels *kernels = psAlloc(sizeof(pmSubtractionKernels)); // Kernels, to return
+    psMemSetDeallocator(kernels, (psFreeFunc)subtractionKernelsFree);
+
+    kernels->type = type;
+    kernels->description = NULL;
+    kernels->num = numBasisFunctions;
+    kernels->u = psVectorAlloc(numBasisFunctions, PS_TYPE_S32);
+    kernels->v = psVectorAlloc(numBasisFunctions, PS_TYPE_S32);
+    kernels->widths = psVectorAlloc(numBasisFunctions, PS_TYPE_F32);
+    kernels->preCalc = psArrayAlloc(numBasisFunctions);
+    kernels->penalty = penalty;
+    kernels->penalties = psVectorAlloc(numBasisFunctions, PS_TYPE_F32);
+    kernels->uStop = NULL;
+    kernels->vStop = NULL;
+    kernels->size = size;
+    kernels->inner = 0;
+    kernels->spatialOrder = spatialOrder;
+    kernels->bgOrder = 0;
+    kernels->mode = mode;
+    kernels->numCols = 0;
+    kernels->numRows = 0;
+    kernels->solution1 = NULL;
+    kernels->solution2 = NULL;
+
+    return kernels;
+}
+
+pmSubtractionKernels *pmSubtractionKernelsPOIS(int size, int spatialOrder, float penalty,
+                                               pmSubtractionMode mode)
+{
+    PS_ASSERT_INT_POSITIVE(size, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(spatialOrder, NULL);
+
+    int num = PS_SQR(2 * size + 1) - 1; // Number of basis functions
+
+    pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_POIS, size,
+                                                              spatialOrder, penalty, mode); // The kernels
+    psStringAppend(&kernels->description, "POIS(%d,%d,%.2e)", size, spatialOrder, penalty);
+    psLogMsg("psModules.imcombine", PS_LOG_INFO, "POIS kernel: %d,%d --> %d elements",
+             size, spatialOrder, num);
+
+    if (!p_pmSubtractionKernelsAddGrid(kernels, 0, size)) {
+        psAbort("Should never get here.");
+    }
+
+    return kernels;
+}
+
+
+pmSubtractionKernels *pmSubtractionKernelsISIS(int size, int spatialOrder,
+                                               const psVector *fwhms, const psVector *orders,
+                                               float penalty, pmSubtractionMode mode)
+{
+    pmSubtractionKernels *kernels = p_pmSubtractionKernelsRawISIS(size, spatialOrder, fwhms, orders,
+                                                                  penalty, mode); // Kernels
+    if (!kernels) {
+        return NULL;
+    }
+
+    if (psTraceGetLevel("psModules.imcombine.kernel") >= 10) {
+        for (int i = 0; i < kernels->num; i++) {
+            psKernel *kernel = kernels->preCalc->data[i]; // Kernel of interest
+            psString kernelName = NULL;
+            psStringAppend(&kernelName, "kernel%03d.fits", i);
+            psFits *kernelFile = psFitsOpen(kernelName, "w");
+            psFree(kernelName);
+            psFitsWriteImage(kernelFile, NULL, kernel->image, 0, NULL);
+            psFitsClose(kernelFile);
+            double sum = 0.0;
+            for (int y = 0; y < kernel->image->numRows; y++) {
+                for (int x = 0; x < kernel->image->numCols; x++) {
+                    sum += kernel->image->data.F32[y][x];
+                }
+            }
+            psTrace("psModules.imcombine.kernel", 10, "Kernel %d sum: %le\n", i, sum);
+        }
+    }
+
+    return kernels;
+}
+
+pmSubtractionKernels *pmSubtractionKernelsSPAM(int size, int spatialOrder, int inner, int binning,
+                                               float penalty, pmSubtractionMode mode)
+{
+    PS_ASSERT_INT_POSITIVE(size, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(spatialOrder, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(inner, NULL);
+    PS_ASSERT_INT_LARGER_THAN(size, inner, NULL);
+    PS_ASSERT_INT_POSITIVE(binning, NULL);
+
+    // The outer region should be divisible by the "binning"; otherwise allocate remainder to the inner region
+    int numOuter = (size - inner) / binning; // Number of summed pixels in the outer region
+    int numInner = inner + (size - inner) % binning; // Number of pixels in the inner region
+    assert(numOuter * binning + numInner == size);
+    int numTotal = numOuter + numInner; // Total number of summed pixels
+
+    psTrace("psModules.imcombine", 3, "Inner: %d Outer: %d\n", numInner, numOuter);
+
+    int num = PS_SQR(2 * numTotal + 1) - 1; // Number of basis functions
+
+    psTrace("psModules.imcombine", 3, "Number of basis functions: %d\n", num);
+
+    pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_SPAM, size,
+                                                              spatialOrder, penalty, mode); // The kernels
+    psStringAppend(&kernels->description, "SPAM(%d,%d,%d,%d,%.2e)", size, inner, binning, spatialOrder,
+                   penalty);
+
+    psLogMsg("psModules.imcombine", PS_LOG_INFO, "SPAM kernel: %d,%d,%d,%d --> %d elements",
+             size, inner, binning, spatialOrder, num);
+
+    kernels->uStop = psVectorAlloc(num, PS_TYPE_S32);
+    kernels->vStop = psVectorAlloc(num, PS_TYPE_S32);
+
+    psVector *locations = psVectorAlloc(2 * numTotal + 1, PS_TYPE_S32); // Locations for each kernel element
+    psVector *widths = psVectorAlloc(2 * numTotal + 1, PS_TYPE_S32); // Widths for each kernel element
+    locations->data.S32[numTotal] = 0;
+    widths->data.S32[numTotal] = 0;
+    for (int i = 1; i <= numInner; i++) {
+        locations->data.S32[numTotal + i] = i;
+        widths->data.S32[numTotal + i] = 0;
+        locations->data.S32[numTotal - i] = - i;
+        widths->data.S32[numTotal - i] = 0;
+    }
+    for (int i = numInner + 1; i <= numTotal; i++) {
+        locations->data.S32[numTotal + i] = locations->data.S32[numTotal + i - 1] +
+            widths->data.S32[numTotal + i - 1] + 1;
+        widths->data.S32[numTotal + i] = binning - 1;
+        locations->data.S32[numTotal - i] = locations->data.S32[numTotal - i + 1] - binning;
+        widths->data.S32[numTotal - i] = binning - 1;
+    }
+
+    if (psTraceGetLevel("psModules.imcombine") >= 10) {
+        for (int i = 0; i < 2 * numTotal + 1; i++) {
+            psTrace("psModules.imcombine", 10, "%d: %d -> %d\n", i, locations->data.S32[i],
+                    locations->data.S32[i] + widths->data.S32[i]);
+        }
+    }
+
+    // Set the kernel parameters
+    for (int i = - numTotal, index = 0; i <= numTotal; i++) {
+        int u = locations->data.S32[numTotal + i]; // Location of pixel
+        int uStop = u + widths->data.S32[numTotal + i]; // Width of pixel
+
+        for (int j = - numTotal; j <= numTotal; j++, index++) {
+            if (i == 0 && j == 0) {
+                // Skip normalisation component: added explicitly
+                index--;
+                continue;
+            }
+            int v = locations->data.S32[numTotal + j]; // Location of pixel
+            int vStop = v + widths->data.S32[numTotal + j]; // Width of pixel
+
+            kernels->u->data.S32[index] = u;
+            kernels->v->data.S32[index] = v;
+            kernels->uStop->data.S32[index] = uStop;
+            kernels->vStop->data.S32[index] = vStop;
+
+            psTrace("psModules.imcombine", 7, "Kernel %d: %d %d %d %d\n", index,
+                    u, uStop, v, vStop);
+        }
+    }
+
+    psFree(locations);
+    psFree(widths);
+
+    psWarning("Kernel penalty for dual-convolution is not configured for SPAM kernels.");
+    psVectorInit(kernels->penalties, 0.0);
+
+    return kernels;
+}
+
+
+pmSubtractionKernels *pmSubtractionKernelsFRIES(int size, int spatialOrder, int inner, float penalty,
+                                                pmSubtractionMode mode)
+{
+    PS_ASSERT_INT_POSITIVE(size, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(spatialOrder, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(inner, NULL);
+    PS_ASSERT_INT_LARGER_THAN(size, inner, NULL);
+
+    int fibNum = 0;                     // Number of Fibonacci values
+    int fibLast = 1, fibTotal = 2;      // Fibonacci sequence
+    while (fibTotal < size - inner) {
+        int temp = fibTotal;
+        fibTotal += fibLast;
+        fibLast = temp;
+        fibNum++;
+    }
+
+    int numInner = inner;               // Number of pixels in the inner region
+    int numOuter = fibNum;              // Number of summed pixels in the outer region
+    int numTotal = numOuter + numInner; // Total number of summed pixels
+
+    psTrace("psModules.imcombine", 3, "Inner: %d Outer: %d\n", numInner, numOuter);
+
+    int num = PS_SQR(2 * numTotal + 1) - 1; // Number of basis functions
+
+    psTrace("psModules.imcombine", 3, "Number of basis functions: %d\n", num);
+
+    pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_FRIES, size,
+                                                              spatialOrder, penalty, mode); // The kernels
+    psStringAppend(&kernels->description, "FRIES(%d,%d,%d,%.2e)", size, inner, spatialOrder, penalty);
+
+    psLogMsg("psModules.imcombine", PS_LOG_INFO, "FRIES kernel: %d,%d,%d --> %d elements",
+             size, inner, spatialOrder, num);
+
+    kernels->uStop = psVectorAlloc(num, PS_TYPE_S32);
+    kernels->vStop = psVectorAlloc(num, PS_TYPE_S32);
+
+    psVector *start = psVectorAlloc(2 * numTotal + 1, PS_TYPE_S32);
+    psVector *stop = psVectorAlloc(2 * numTotal + 1, PS_TYPE_S32);
+    start->data.S32[numTotal] = 0;
+    stop->data.S32[numTotal] = 0;
+    for (int i = 1; i <= numInner; i++) {
+        start->data.S32[numTotal + i] = i;
+        stop->data.S32[numTotal + i] = i;
+        start->data.S32[numTotal - i] = -i;
+        stop->data.S32[numTotal - i] = -i;
+    }
+    for (int i = numInner + 1, fibLast = 1, fib = 2, temp; i <= numTotal;
+         i++, fib = (temp = fib) + fibLast, fibLast = temp) {
+        start->data.S32[numTotal + i] = stop->data.S32[numTotal + i - 1] + 1;
+        stop->data.S32[numTotal + i] = PS_MIN(start->data.S32[numTotal + i] + fib - 1, size);
+        start->data.S32[numTotal - i] = - stop->data.S32[numTotal + i];
+        stop->data.S32[numTotal - i] = - start->data.S32[numTotal + i];
+    }
+
+    if (psTraceGetLevel("psModules.imcombine") >= 10) {
+        for (int i = 0; i < 2 * numTotal + 1; i++) {
+            psTrace("psModules.imcombine", 10, "%d: %d -> %d\n", i, start->data.S32[i], stop->data.S32[i]);
+        }
+    }
+
+    // Set the kernel parameters
+    for (int i = - numTotal, index = 0; i <= numTotal; i++) {
+        int u = start->data.S32[numTotal + i]; // Location of pixel
+        int uStop = stop->data.S32[numTotal + i]; // Width of pixel
+        for (int j = - numTotal; j <= numTotal; j++, index++) {
+            if (i == 0 && j == 0) {
+                // Skip normalisation component: added explicitly
+                index--;
+                continue;
+            }
+            int v = start->data.S32[numTotal + j]; // Location of pixel
+            int vStop = stop->data.S32[numTotal + j]; // Width of pixel
+
+            kernels->u->data.S32[index] = u;
+            kernels->v->data.S32[index] = v;
+            kernels->uStop->data.S32[index] = uStop;
+            kernels->vStop->data.S32[index] = vStop;
+
+            psTrace("psModules.imcombine", 7, "Kernel %d: %d %d %d %d\n", index,
+                    u, uStop, v, vStop);
+        }
+    }
+
+    psFree(start);
+    psFree(stop);
+
+    psWarning("Kernel penalty for dual-convolution is not configured for FRIES kernels.");
+    psVectorInit(kernels->penalties, 0.0);
+
+    return kernels;
+}
+
+// Grid United with Normal Kernel
+pmSubtractionKernels *pmSubtractionKernelsGUNK(int size, int spatialOrder, const psVector *fwhms,
+                                               const psVector *orders, int inner, float penalty,
+                                               pmSubtractionMode mode)
+{
+    PS_ASSERT_INT_POSITIVE(size, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(spatialOrder, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(fwhms, NULL);
+    PS_ASSERT_VECTOR_TYPE(fwhms, PS_TYPE_F32, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(orders, NULL);
+    PS_ASSERT_VECTOR_TYPE(orders, PS_TYPE_S32, NULL);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(fwhms, orders, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(inner, NULL);
+    PS_ASSERT_INT_LESS_THAN(inner, size, NULL);
+
+    // XXX GUNK doesn't seem to work --- doesn't add the POIS components, or at least, they're not noticed
+
+    pmSubtractionKernels *kernels = p_pmSubtractionKernelsRawISIS(size, spatialOrder, fwhms, orders,
+                                                                  penalty, mode); // Kernels
+    psStringPrepend(&kernels->description, "GUNK=");
+    psStringAppend(&kernels->description, "+POIS(%d,%d)", inner, spatialOrder);
+
+    int numISIS = kernels->num;         // Number of ISIS kernels
+
+    if (!p_pmSubtractionKernelsAddGrid(kernels, numISIS, inner)) {
+        psAbort("Should never get here.");
+    }
+
+    return kernels;
+}
+
+// RINGS --- just what it says
+pmSubtractionKernels *pmSubtractionKernelsRINGS(int size, int spatialOrder, int inner, int ringsOrder,
+                                                float penalty, pmSubtractionMode mode)
+{
+    PS_ASSERT_INT_POSITIVE(size, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(spatialOrder, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(inner, NULL);
+    PS_ASSERT_INT_LESS_THAN_OR_EQUAL(inner, size, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(ringsOrder, NULL);
+
+    int fibNum = 0;                     // Number of Fibonacci values
+    {
+        int fibIndex = 1, fibIndexMinus1 = 0; // Fibonnacci parameters
+        int radius = inner;
+        while (radius + fibIndex < size) {
+            radius++;
+            int fibNew = fibIndex + fibIndexMinus1;
+            fibIndexMinus1 = fibIndex;
+            fibIndex = fibNew;
+            radius += fibIndex;
+            fibNum++;
+        }
+    }
+
+    int numInner = inner - 1;           // Number of pixels in the inner region
+    int numOuter = fibNum;              // Number of summed pixels in the outer region
+
+    int numRings = numOuter + numInner; // Number of rings (not including the central pixel)
+    int numPoly = PM_SUBTRACTION_POLYTERMS(ringsOrder); // Number of polynomial variants of each ring
+
+    int num = numRings * numPoly; // Total number of basis functions
+
+    pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_RINGS, size,
+                                                              spatialOrder, penalty, mode); // The kernels
+    psStringAppend(&kernels->description, "RINGS(%d,%d,%d,%d,%.2e)", size, inner, ringsOrder, spatialOrder,
+                   penalty);
+
+    psLogMsg("psModules.imcombine", PS_LOG_INFO, "RINGS kernel: %d,%d,%d,%d --> %d elements",
+             size, inner, ringsOrder, spatialOrder, num);
+
+    // Set the Gaussian kernel parameters
+    int fibIndex = 1, fibIndexMinus1 = 0; // Fibonnacci parameters
+    int radiusLast = 1;                 // Last radius
+    for (int i = 1, index = 0; i < numRings + 1; i++) {
+        float lower2;                   // Lower limit of radius^2
+        float upper2;                   // Upper limit of radius^2
+        if (i <= inner) {
+            // A ring every pixel width
+            float radius = i;
+            lower2 = PS_SQR(radius - 0.5);
+            upper2 = PS_SQR(radius + 0.5);
+            radiusLast = i;
+        } else {
+            // Rings Fibonacci distributed (2, 3, 5...)
+            int fibNew = fibIndex + fibIndexMinus1;
+            fibIndexMinus1 = fibIndex;
+            fibIndex = fibNew;
+
+            float radiusLower = radiusLast + 1;
+            radiusLast = radiusLower + fibIndex;
+            float radiusUpper = radiusLast;
+
+            lower2 = PS_SQR(radiusLower - 0.5);
+            upper2 = PS_SQR(radiusUpper + 0.5);
+        }
+
+        psTrace("psModules.imcombine", 8, "Radius limits: %f --> %f\n", sqrtf(lower2), sqrtf(upper2));
+
+        // Iterate over (u,v) order
+        for (int uOrder = 0; uOrder <= (i == 0 ? 0 : ringsOrder); uOrder++) {
+            for (int vOrder = 0; vOrder <= (i == 0 ? 0 : ringsOrder - uOrder); vOrder++, index++) {
+
+                psArray *data = psArrayAlloc(3); // Container for data
+                psVector *uCoords = data->data[0] = psVectorAllocEmpty(RINGS_BUFFER, PS_TYPE_S32); // u coords
+                psVector *vCoords = data->data[1] = psVectorAllocEmpty(RINGS_BUFFER, PS_TYPE_S32); // v coords
+                psVector *poly = data->data[2] = psVectorAllocEmpty(RINGS_BUFFER, PS_TYPE_F32); // Polynomial
+                double moment = 0.0;    // Moment, for penalty
+
+                if (i == 0) {
+                    // Central pixel is easy
+                    uCoords->data.S32[0] = vCoords->data.S32[0] = 0;
+                    poly->data.F32[0] = 1.0;
+                    uCoords->n = vCoords->n = poly->n = 1;
+                    radiusLast = 0;
+                    moment = 0.0;
+                } else {
+                    int j = 0;          // Index for data
+                    double norm = 0.0;  // Normalisation
+                    for (int v = -size; v <= size; v++) {
+                        int v2 = PS_SQR(v);   // Square of v
+                        float vPoly = powf(v/(float)size, vOrder); // Value of v^vOrder
+
+                        for (int u = -size; u <= size; u++) {
+                            int u2 = PS_SQR(u); // Square of u
+                            int distance2 = u2 + v2; // Distance from the centre
+                            if (distance2 > lower2 && distance2 < upper2) {
+                                float uPoly = powf(u/(float)size, uOrder); // Value of u^uOrder
+
+                                float polyVal = uPoly * vPoly; // Value of polynomial
+                                if (polyVal != 0) { // No point adding it otherwise
+                                    uCoords->data.S32[j] = u;
+                                    vCoords->data.S32[j] = v;
+                                    poly->data.F32[j] = polyVal;
+                                    norm += polyVal;
+                                    moment += polyVal * (PS_SQR(u) + PS_SQR(v));
+
+                                    psVectorExtend(uCoords, RINGS_BUFFER, 1);
+                                    psVectorExtend(vCoords, RINGS_BUFFER, 1);
+                                    psVectorExtend(poly, RINGS_BUFFER, 1);
+                                    psTrace("psModules.imcombine", 9, "u = %d, v = %d, poly = %f\n",
+                                            u, v, poly->data.F32[j]);
+                                    j++;
+                                }
+                            }
+                        }
+                    }
+                    // Normalise kernel component to unit sum
+                    if (uOrder % 2 == 0 && vOrder % 2 == 0) {
+                        psBinaryOp(poly, poly, "*", psScalarAlloc(1.0 / norm, PS_TYPE_F32));
+                        // Add subtraction of 0,0 component to preserve photometric scaling
+                        uCoords->data.S32[j] = 0;
+                        vCoords->data.S32[j] = 0;
+                        poly->data.F32[j] = -1.0;
+                        psVectorExtend(uCoords, RINGS_BUFFER, 1);
+                        psVectorExtend(vCoords, RINGS_BUFFER, 1);
+                        psVectorExtend(poly, RINGS_BUFFER, 1);
+                    } else {
+                        norm = powf(size, uOrder) * powf(size, vOrder);
+                        psBinaryOp(poly, poly, "*", psScalarAlloc(1.0 / norm, PS_TYPE_F32));
+                    }
+//                    moment /= norm;
+                }
+
+                psTrace("psModules.imcombine", 8, "%ld pixels in kernel\n", uCoords->n);
+
+                kernels->preCalc->data[index] = data;
+                kernels->u->data.S32[index] = uOrder;
+                kernels->v->data.S32[index] = vOrder;
+                kernels->penalties->data.F32[index] = kernels->penalty * fabsf(moment);
+
+                psTrace("psModules.imcombine", 7, "Kernel %d: %d %d %d\n", index,
+                        i, uOrder, vOrder);
+            }
+        }
+    }
+
+    return kernels;
+}
+
+pmSubtractionKernels *pmSubtractionKernelsGenerate(pmSubtractionKernelsType type, int size, int spatialOrder,
+                                                   const psVector *fwhms, const psVector *orders, int inner,
+                                                   int binning, int ringsOrder, float penalty,
+                                                   pmSubtractionMode mode)
+{
+    switch (type) {
+      case PM_SUBTRACTION_KERNEL_POIS:
+        return pmSubtractionKernelsPOIS(size, spatialOrder, penalty, mode);
+      case PM_SUBTRACTION_KERNEL_ISIS:
+        return pmSubtractionKernelsISIS(size, spatialOrder, fwhms, orders, penalty, mode);
+      case PM_SUBTRACTION_KERNEL_SPAM:
+        return pmSubtractionKernelsSPAM(size, spatialOrder, inner, binning, penalty, mode);
+      case PM_SUBTRACTION_KERNEL_FRIES:
+        return pmSubtractionKernelsFRIES(size, spatialOrder, inner, penalty, mode);
+      case PM_SUBTRACTION_KERNEL_GUNK:
+        return pmSubtractionKernelsGUNK(size, spatialOrder, fwhms, orders, inner, penalty, mode);
+      case PM_SUBTRACTION_KERNEL_RINGS:
+        return pmSubtractionKernelsRINGS(size, spatialOrder, inner, ringsOrder, penalty, mode);
+      default:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unknown kernel type: %x", type);
+        return NULL;
+    }
+}
+
+
+// Intermediate string parsing functions required because of different APIs for strtol and strtof
+static inline int parseStringInt(const char *string)
+{
+    return strtol(string, NULL, 10);
+}
+static inline float parseStringFloat(const char *string)
+{
+    return strtof(string, NULL);
+}
+
+
+// Parse a string of a number, up to some delimiter, and advance past the delimiter
+#define PARSE_STRING_NUMBER(TARGET, STRING, DELIM, PARSEFUNC) { \
+    char *start = STRING;               /* Start of string */ \
+    char *end = strchr(STRING, DELIM);  /* End of string */ \
+    if (!end) { \
+        psAbort("End of string encountered"); \
+    } \
+    int stringSize = end - STRING;      /* Size of string with value, NOT including \0 */ \
+    char value[stringSize + 1];         /* String to parse */ \
+    strncpy(value, start, stringSize); \
+    value[stringSize] = '\0'; \
+    TARGET = PARSEFUNC(value); \
+    STRING += stringSize + 1;           /* Advance past delimiter */ \
+}
+
+
+pmSubtractionKernels *pmSubtractionKernelsFromDescription(const char *description, int bgOrder,
+                                                          pmSubtractionMode mode)
+{
+    PS_ASSERT_STRING_NON_EMPTY(description, NULL);
+
+    if (bgOrder != 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Background order %d is not yet supported.", bgOrder);
+        return false;
+    }
+
+    pmSubtractionKernelsType type = PM_SUBTRACTION_KERNEL_NONE; // Type of kernel
+    int size = 0;                       // Half-size of kernel
+    int spatialOrder = 0;               // Order of spatial variations
+    const psVector *fwhms = NULL;       // FWHM of Gaussians
+    const psVector *orders = NULL;      // Polynomial order for each FWHM
+    int inner = 0;                      // Size of inner region
+    int binning = 0;                    // Binning to use
+    int ringsOrder = 0;                 // Polynomial order for rings
+    float penalty = 0.0;                // Penalty for wideness
+
+    if (strncmp(description, "ISIS", 4) == 0) {
+        // XXX Support for GUNK
+        if (strstr(description, "+POIS")) {
+            type = PM_SUBTRACTION_KERNEL_GUNK;
+            psAbort("Deciphering GUNK kernels (%s) is not currently supported.", description);
+        } else {
+            type = PM_SUBTRACTION_KERNEL_ISIS;
+            char *ptr = (char*)description + 5;    // Eat "ISIS("
+            PARSE_STRING_NUMBER(size, ptr, ',', parseStringInt);
+
+            // Count the number of Gaussians
+            int numGauss = 0;
+            for (char *string = ptr; string; string = strchr(string, '(')) {
+                numGauss++;
+            }
+
+            fwhms = psVectorAlloc(numGauss, PS_TYPE_F32);
+            orders = psVectorAlloc(numGauss, PS_TYPE_S32);
+
+            for (int i = 0; i < numGauss; i++) {
+                ptr++;                  // Eat the '('
+                PARSE_STRING_NUMBER(fwhms->data.F32[i], ptr, ',', parseStringFloat); // Eat "1.234,"
+                PARSE_STRING_NUMBER(orders->data.S32[i], ptr, ')', parseStringInt); // Eat "3)"
+            }
+
+            ptr++;                      // Eat ','
+            PARSE_STRING_NUMBER(spatialOrder, ptr, ',', parseStringInt);
+            penalty = parseStringFloat(ptr);
+        }
+    } else if (strncmp(description, "RINGS", 5) == 0) {
+        type = PM_SUBTRACTION_KERNEL_RINGS;
+        char *ptr = (char*)description + 6;
+        PARSE_STRING_NUMBER(size, ptr, ',', parseStringInt);
+        PARSE_STRING_NUMBER(inner, ptr, ',', parseStringInt);
+        PARSE_STRING_NUMBER(ringsOrder, ptr, ',', parseStringInt);
+        PARSE_STRING_NUMBER(spatialOrder, ptr, ',', parseStringInt);
+        PARSE_STRING_NUMBER(penalty, ptr, ')', parseStringInt);
+    } else {
+        psAbort("Deciphering kernels other than ISIS and RINGS is not currently supported.");
+    }
+
+
+    return pmSubtractionKernelsGenerate(type, size, spatialOrder, fwhms, orders,
+                                        inner, binning, ringsOrder, penalty, mode);
+}
+
+
+pmSubtractionKernelsType pmSubtractionKernelsTypeFromString(const char *type)
+{
+    if (strcasecmp(type, "POIS") == 0) {
+        return PM_SUBTRACTION_KERNEL_POIS;
+    }
+    if (strcasecmp(type, "ISIS") == 0) {
+        return PM_SUBTRACTION_KERNEL_ISIS;
+    }
+    if (strcasecmp(type, "SPAM") == 0) {
+        return PM_SUBTRACTION_KERNEL_SPAM;
+    }
+    if (strcasecmp(type, "FRIES") == 0) {
+        return PM_SUBTRACTION_KERNEL_FRIES;
+    }
+    if (strcasecmp(type, "GUNK") == 0) {
+        return PM_SUBTRACTION_KERNEL_GUNK;
+    }
+    if (strcasecmp(type, "RINGS") == 0) {
+        return PM_SUBTRACTION_KERNEL_RINGS;
+    }
+
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unrecognised kernel type: %s", type);
+    return PM_SUBTRACTION_KERNEL_NONE;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionKernels.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionKernels.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionKernels.h	(revision 22158)
@@ -0,0 +1,202 @@
+#ifndef PM_SUBTRACTION_KERNELS_H
+#define PM_SUBTRACTION_KERNELS_H
+
+#include <pslib.h>
+
+/// Type of subtraction kernel
+typedef enum {
+    PM_SUBTRACTION_KERNEL_NONE,         ///< Nothing --- an error
+    PM_SUBTRACTION_KERNEL_POIS,         ///< Pan-STARRS Optimal Image Subtraction --- delta functions
+    PM_SUBTRACTION_KERNEL_ISIS,         ///< Traditional kernel --- gaussians modified by polynomials
+    PM_SUBTRACTION_KERNEL_SPAM,         ///< Summed Pixels for Advanced Matching --- summed delta functions
+    PM_SUBTRACTION_KERNEL_FRIES,        ///< Fibonacci Radius Increases Excellence of Subtraction
+    PM_SUBTRACTION_KERNEL_GUNK,         ///< Grid United with Normal Kernel --- POIS and ISIS hybrid
+    PM_SUBTRACTION_KERNEL_RINGS,        ///< Rings Instead of the Normal Gaussian Subtraction
+} pmSubtractionKernelsType;
+
+/// Modes --- specifies which image to convolve
+typedef enum {
+    PM_SUBTRACTION_MODE_ERR,            // Error in the mode
+    PM_SUBTRACTION_MODE_1,              // Convolve image 1
+    PM_SUBTRACTION_MODE_2,              // Convolve image 2
+    PM_SUBTRACTION_MODE_UNSURE,         // Not sure yet which image to convolve so try to satisfy both
+    PM_SUBTRACTION_MODE_DUAL,           // Dual convolution
+} pmSubtractionMode;
+
+/// Kernels specification
+typedef struct {
+    pmSubtractionKernelsType type;      ///< Type of kernels --- allowing the use of multiple kernels
+    psString description;               ///< Description of the kernel parameters
+    long num;                           ///< Number of kernel components (not including the spatial ones)
+    psVector *u, *v;                    ///< Offset (for POIS) or polynomial order (for ISIS)
+    psVector *widths;                   ///< Gaussian FWHMs (ISIS)
+    psVector *uStop, *vStop;            ///< Width of kernel element (SPAM,FRIES only)
+    psArray *preCalc;                   ///< Array of images containing pre-calculated kernel (for ISIS)
+    float penalty;                      ///< Penalty for wideness
+    psVector *penalties;                ///< Penalty for each kernel component
+    int size;                           ///< The half-size of the kernel
+    int inner;                          ///< The size of an inner region
+    int spatialOrder;                   ///< The spatial order of the kernels
+    int bgOrder;                        ///< The order for the background fitting
+    pmSubtractionMode mode;             ///< Mode for subtraction
+    int numCols, numRows;               ///< Size of image (for normalisation), or zero to use image provided
+    psVector *solution1, *solution2;    ///< Solution for the PSF matching
+} pmSubtractionKernels;
+
+// Assertion to check pmSubtractionKernels
+#define PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(KERNELS, RETURNVALUE) { \
+    PS_ASSERT_PTR_NON_NULL(KERNELS, RETURNVALUE); \
+    PS_ASSERT_STRING_NON_EMPTY((KERNELS)->description, RETURNVALUE); \
+    PS_ASSERT_INT_POSITIVE((KERNELS)->num, RETURNVALUE); \
+    PS_ASSERT_VECTOR_NON_NULL((KERNELS)->u, RETURNVALUE); \
+    PS_ASSERT_VECTOR_NON_NULL((KERNELS)->v, RETURNVALUE); \
+    PS_ASSERT_VECTOR_TYPE((KERNELS)->u, PS_TYPE_S32, RETURNVALUE); \
+    PS_ASSERT_VECTOR_TYPE((KERNELS)->v, PS_TYPE_S32, RETURNVALUE); \
+    PS_ASSERT_VECTOR_SIZE((KERNELS)->u, (KERNELS)->num, RETURNVALUE); \
+    PS_ASSERT_VECTOR_SIZE((KERNELS)->v, (KERNELS)->num, RETURNVALUE); \
+    if ((KERNELS)->type == PM_SUBTRACTION_KERNEL_ISIS) { \
+        PS_ASSERT_VECTOR_NON_NULL((KERNELS)->widths, RETURNVALUE); \
+        PS_ASSERT_VECTOR_TYPE((KERNELS)->widths, PS_TYPE_F32, RETURNVALUE); \
+        PS_ASSERT_VECTOR_SIZE((KERNELS)->widths, (KERNELS)->num, RETURNVALUE); \
+    } \
+    if ((KERNELS)->uStop || (KERNELS)->vStop) { \
+        PS_ASSERT_VECTOR_NON_NULL((KERNELS)->uStop, RETURNVALUE); \
+        PS_ASSERT_VECTOR_NON_NULL((KERNELS)->vStop, RETURNVALUE); \
+        PS_ASSERT_VECTOR_TYPE((KERNELS)->uStop, PS_TYPE_S32, RETURNVALUE); \
+        PS_ASSERT_VECTOR_TYPE((KERNELS)->vStop, PS_TYPE_S32, RETURNVALUE); \
+        PS_ASSERT_VECTOR_SIZE((KERNELS)->uStop, (KERNELS)->num, RETURNVALUE); \
+        PS_ASSERT_VECTOR_SIZE((KERNELS)->vStop, (KERNELS)->num, RETURNVALUE); \
+    } \
+    if ((KERNELS)->preCalc) { \
+        PS_ASSERT_ARRAY_NON_NULL((KERNELS)->preCalc, RETURNVALUE); \
+        PS_ASSERT_ARRAY_SIZE((KERNELS)->preCalc, (KERNELS)->num, RETURNVALUE); \
+    } \
+    PS_ASSERT_INT_NONNEGATIVE((KERNELS)->size, RETURNVALUE); \
+    PS_ASSERT_INT_NONNEGATIVE((KERNELS)->inner, RETURNVALUE); \
+    PS_ASSERT_INT_NONNEGATIVE((KERNELS)->spatialOrder, RETURNVALUE); \
+    PS_ASSERT_INT_NONNEGATIVE((KERNELS)->bgOrder, RETURNVALUE); \
+}
+
+// Assertion to check that the solution is attached
+#define PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(KERNELS, RETURNVALUE) { \
+    PS_ASSERT_VECTOR_NON_NULL((KERNELS)->solution1, RETURNVALUE); \
+    PS_ASSERT_VECTOR_TYPE((KERNELS)->solution1, PS_TYPE_F64, RETURNVALUE); \
+    PS_ASSERT_VECTOR_SIZE((KERNELS)->solution1, \
+                          (KERNELS)->num * PM_SUBTRACTION_POLYTERMS((KERNELS)->spatialOrder) + 1 + \
+                              PM_SUBTRACTION_POLYTERMS((KERNELS)->bgOrder), \
+                          RETURNVALUE); \
+    if (kernels->mode == PM_SUBTRACTION_MODE_DUAL) { \
+        PS_ASSERT_VECTOR_NON_NULL(kernels->solution2, RETURNVALUE); \
+        PS_ASSERT_VECTOR_TYPE((KERNELS)->solution2, PS_TYPE_F64, RETURNVALUE); \
+        PS_ASSERT_VECTOR_SIZE((KERNELS)->solution2, \
+                              (KERNELS)->num * PM_SUBTRACTION_POLYTERMS((KERNELS)->spatialOrder), \
+                               RETURNVALUE); \
+    } \
+}
+
+/// Generate a delta-function grid for subtraction kernels (like the POIS kernel)
+bool p_pmSubtractionKernelsAddGrid(pmSubtractionKernels *kernels, ///< The subtraction kernels to append to
+                                   int start, ///< Index at which to start appending
+                                   int size ///< Half-size of the grid
+    );
+
+/// General allocator for pmSubtractionKernels
+///
+/// Unlike the functions for the specific kernel type, this function does not set up the basis functions, but
+/// merely allocates space for their storage.
+pmSubtractionKernels *pmSubtractionKernelsAlloc(int numBasisFunctions, ///< Number of basis functions
+                                                pmSubtractionKernelsType type, ///< Kernel type
+                                                int size, ///< Half-size of kernel
+                                                int spatialOrder, ///< Order of spatial variations
+                                                float penalty, ///< Penalty for wideness
+                                                pmSubtractionMode mode ///< Mode for subtraction
+    );
+
+/// Generate POIS kernels
+pmSubtractionKernels *pmSubtractionKernelsPOIS(int size, ///< Half-size of the kernel (in both dims)
+                                               int spatialOrder, ///< Order of spatial variations
+                                               float penalty, ///< Penalty for wideness
+                                               pmSubtractionMode mode ///< Mode for subtraction
+    );
+
+/// Generate ISIS kernels without the flux scaling built in
+pmSubtractionKernels *p_pmSubtractionKernelsRawISIS(int size, ///< Half-size of the kernel
+                                                    int spatialOrder, ///< Order of spatial variations
+                                                    const psVector *fwhms, ///< Gaussian FWHMs
+                                                    const psVector *orders, ///< Polynomial order of gaussians
+                                                    float penalty, ///< Penalty for wideness
+                                                    pmSubtractionMode mode ///< Mode for subtraction
+    );
+
+/// Generate ISIS kernels
+pmSubtractionKernels *pmSubtractionKernelsISIS(int size, ///< Half-size of the kernel
+                                               int spatialOrder, ///< Order of spatial variations
+                                               const psVector *fwhms, ///< Gaussian FWHMs
+                                               const psVector *orders, ///< Polynomial order of gaussians
+                                               float penalty, ///< Penalty for wideness
+                                               pmSubtractionMode mode ///< Mode for subtraction
+                                               );
+
+/// Generate SPAM kernels
+pmSubtractionKernels *pmSubtractionKernelsSPAM(int size, ///< Half-size of the kernel
+                                               int spatialOrder, ///< Order of spatial variations
+                                               int inner, ///< Inner radius to preserve unbinned
+                                               int binning, ///< Kernel binning factor
+                                               float penalty, ///< Penalty for wideness
+                                               pmSubtractionMode mode ///< Mode for subtraction
+    );
+
+/// Generate FRIES kernels
+pmSubtractionKernels *pmSubtractionKernelsFRIES(int size, ///< Half-size of the kernel
+                                                int spatialOrder, ///< Order of spatial variations
+                                                int inner, ///< Inner radius to preserve unbinned
+                                                float penalty, ///< Penalty for wideness
+                                                pmSubtractionMode mode ///< Mode for subtraction
+    );
+
+/// Generate GUNK kernels
+pmSubtractionKernels *pmSubtractionKernelsGUNK(int size, ///< Half-size of the kernel
+                                               int spatialOrder, ///< Order of spatial variations
+                                               const psVector *fwhms, ///< Gaussian FWHMs
+                                               const psVector *orders, ///< Polynomial order of gaussians
+                                               int inner, ///< Inner radius containing grid of delta functions
+                                               float penalty, ///< Penalty for wideness
+                                               pmSubtractionMode mode ///< Mode for subtraction
+    );
+
+/// Generate RINGS kernels
+pmSubtractionKernels *pmSubtractionKernelsRINGS(int size, ///< Half-size of the kernel
+                                                int spatialOrder, ///< Order of spatial variations
+                                                int inner, ///< Inner radius to preserve unbinned
+                                                int ringsOrder, ///< Polynomial order
+                                                float penalty, ///< Penalty for wideness
+                                                pmSubtractionMode mode ///< Mode for subtraction
+    );
+
+
+/// Generate a kernel of a specified type
+pmSubtractionKernels *pmSubtractionKernelsGenerate(pmSubtractionKernelsType type, ///< Kernel type
+                                                   int size, ///< Half-size of the kernel
+                                                   int spatialOrder, ///< Order of spatial variations
+                                                   const psVector *fwhms, ///< Gaussian FWHMs
+                                                   const psVector *orders, ///< Polynomial order of gaussians
+                                                   int inner, ///< Inner radius to preserve unbinned
+                                                   int binning, ///< Kernel binning factor
+                                                   int ringsOrder, ///< Polynomial order for RINGS
+                                                   float penalty, ///< Penalty for wideness
+                                                   pmSubtractionMode mode ///< Mode for subtraction
+    );
+
+/// Generate a kernel using the description
+pmSubtractionKernels *pmSubtractionKernelsFromDescription(
+    const char *description,            ///< Description of kernel
+    int bgOrder,                        ///< Polynomial order for background fitting
+    pmSubtractionMode mode              ///< Mode for subtraction
+    );
+
+/// Return the appropriate type from a string
+pmSubtractionKernelsType pmSubtractionKernelsTypeFromString(const char *string // String name for kernel type
+    );
+
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionMask.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionMask.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionMask.c	(revision 22158)
@@ -0,0 +1,259 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+
+#include "pmSubtraction.h"
+#include "pmSubtractionKernels.h"
+
+#include "pmSubtractionMask.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Private (file-static) functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Mark a pixel as blank in the image, mask and weight
+static inline void markBlank(psImage *image, // Image to mark as blank
+                             psImage *mask, // Mask to mark as blank (or NULL)
+                             psImage *weight, // Weight map to mark as blank (or NULL)
+                             int x, int y, // Coordinates to mark blank
+                             psMaskType blank // Blank mask value
+    )
+{
+    image->data.F32[y][x] = NAN;
+    if (mask) {
+        mask->data.PS_TYPE_MASK_DATA[y][x] |= blank;
+    }
+    if (weight) {
+        weight->data.F32[y][x] = NAN;
+    }
+    return;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+psImage *pmSubtractionMask(const psImage *mask1, const psImage *mask2, psMaskType maskVal,
+                           int size, int footprint, float badFrac, bool useFFT)
+{
+    PS_ASSERT_IMAGE_NON_NULL(mask1, NULL);
+    PS_ASSERT_IMAGE_TYPE(mask1, PS_TYPE_MASK, NULL);
+    if (mask2) {
+        PS_ASSERT_IMAGE_NON_NULL(mask2, NULL);
+        PS_ASSERT_IMAGE_TYPE(mask2, PS_TYPE_MASK, NULL);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(mask2, mask1, NULL);
+    }
+    PS_ASSERT_INT_NONNEGATIVE(size, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(footprint, NULL);
+    if (isfinite(badFrac)) {
+        PS_ASSERT_FLOAT_LARGER_THAN(badFrac, 0.0, NULL);
+        PS_ASSERT_FLOAT_LESS_THAN_OR_EQUAL(badFrac, 1.0, NULL);
+    }
+
+    int numCols = mask1->numCols, numRows = mask1->numRows; // Size of the images
+
+    // Dereference inputs for convenience
+    psMaskType **data1 = mask1->data.PS_TYPE_MASK_DATA;
+    psMaskType **data2 = NULL;
+    if (mask2) {
+        data2 = mask2->data.PS_TYPE_MASK_DATA;
+    }
+
+    // First, a pass through to determine the fraction of bad pixels
+    if (isfinite(badFrac) && badFrac != 1.0) {
+        int numBad = 0;                 // Number of bad pixels
+        for (int y = 0; y < numRows; y++) {
+            for (int x = 0; x < numCols; x++) {
+                if (data1[y][x] & maskVal) {
+                    numBad++;
+                    continue;
+                }
+                if (data2 && data2[y][x] & maskVal) {
+                    numBad++;
+                }
+            }
+        }
+        if (numBad > badFrac * numCols * numRows) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Fraction of bad pixels (%d/%d=%f) exceeds limit (%f)\n",
+                    numBad, numCols * numRows, (float)numBad/(float)(numCols * numRows), badFrac);
+            return NULL;
+        }
+    }
+
+    // Worried about the masks for bad pixels and bad stamps colliding, so make our own mask
+    psImage *mask = psImageAlloc(numCols, numRows, PS_TYPE_MASK); // The global mask
+    psImageInit(mask, 0);
+    psMaskType **maskData = mask->data.PS_TYPE_MASK_DATA; // Dereference for convenience
+
+    // Block out a border around the edge of the image
+
+    // Bottom stripe
+    for (int y = 0; y < PS_MIN(size + footprint, numRows); y++) {
+        for (int x = 0; x < numCols; x++) {
+            maskData[y][x] |= PM_SUBTRACTION_MASK_BORDER;
+        }
+    }
+    // Either side
+    for (int y = PS_MIN(size + footprint, numRows); y < numRows - size - footprint; y++) {
+        for (int x = 0; x < PS_MIN(size + footprint, numCols); x++) {
+            maskData[y][x] |= PM_SUBTRACTION_MASK_BORDER;
+        }
+        for (int x = PS_MAX(numCols - size - footprint, 0); x < numCols; x++) {
+            maskData[y][x] |= PM_SUBTRACTION_MASK_BORDER;
+        }
+    }
+    // Top stripe
+    for (int y = PS_MAX(numRows - size - footprint, 0); y < numRows; y++) {
+        for (int x = 0; x < numCols; x++) {
+            maskData[y][x] |= PM_SUBTRACTION_MASK_BORDER;
+        }
+    }
+
+    // XXX Could do something smarter here --- we will get images that are predominantly masked (where the
+    // skycell isn't overlapped by a large fraction by the observation), so that convolving around every bad
+    // pixel is wasting time.  As a first cut, I've put in a check on the fraction of bad pixels, but we could
+    // imagine looking for the edge of big regions and convolving just at the edge.  As a second cut, allow
+    // use of FFT convolution.
+
+    for (int y = 0; y < numRows; y++) {
+        for (int x = 0; x < numCols; x++) {
+            if (data1[y][x] & maskVal) {
+                maskData[y][x] |= PM_SUBTRACTION_MASK_BAD_1;
+            }
+            if (data2 && data2[y][x] & maskVal) {
+                maskData[y][x] |= PM_SUBTRACTION_MASK_BAD_2;
+            }
+        }
+    }
+
+    // Block out the entire stamp footprint around bad input pixels.
+
+    // We want to block out with the CONVOLVE mask anything that would be bad if we convolved with a bad
+    // reference pixel (within 'size').  Then we want to block out with the FOOTPRINT mask everything within a
+    // footprint's distance of those (within 'footprint').
+
+    if (!psImageConvolveMask(mask, mask, PM_SUBTRACTION_MASK_BAD_1,
+                             PM_SUBTRACTION_MASK_CONVOLVE_1 | PM_SUBTRACTION_MASK_FOOTPRINT_1,
+                             -size, size, -size, size)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to convolve bad pixels from mask 1.");
+        psFree(mask);
+        return NULL;
+    }
+    if (!psImageConvolveMask(mask, mask, PM_SUBTRACTION_MASK_BAD_2,
+                             PM_SUBTRACTION_MASK_CONVOLVE_2 | PM_SUBTRACTION_MASK_FOOTPRINT_2,
+                             -size, size, -size, size)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to convolve bad pixels from mask 2.");
+        psFree(mask);
+        return NULL;
+    }
+    if (!psImageConvolveMask(mask, mask, PM_SUBTRACTION_MASK_CONVOLVE_1,
+                             PM_SUBTRACTION_MASK_FOOTPRINT_1,
+                             -footprint, footprint, -footprint, footprint)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to reconvolve bad pixels from mask 1.");
+        psFree(mask);
+        return NULL;
+    }
+    if (!psImageConvolveMask(mask, mask, PM_SUBTRACTION_MASK_CONVOLVE_2,
+                             PM_SUBTRACTION_MASK_FOOTPRINT_2,
+                             -footprint, footprint, -footprint, footprint)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to reconvolve bad pixels from mask 2.");
+        psFree(mask);
+        return NULL;
+    }
+
+    return mask;
+}
+
+
+bool pmSubtractionBorder(psImage *image, psImage *weight, psImage *mask,
+                         int size, psMaskType blank)
+{
+    PS_ASSERT_IMAGE_NON_NULL(image, false);
+    PS_ASSERT_IMAGE_TYPE(image, PS_TYPE_F32, false);
+    if (mask) {
+        PS_ASSERT_IMAGE_NON_NULL(mask, false);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(mask, image, false);
+        PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, false);
+    }
+    if (weight) {
+        PS_ASSERT_IMAGE_NON_NULL(weight, false);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(weight, image, false);
+        PS_ASSERT_IMAGE_TYPE(weight, PS_TYPE_F32, false);
+    }
+
+    int numCols = image->numCols, numRows = image->numRows; // Image dimensions
+
+    for (int y = size; y < numRows - size; y++) {
+        for (int x = 0; x < size; x++) {
+            markBlank(image, mask, weight, x, y, blank);
+        }
+        for (int x = numCols - size; x < numCols; x++) {
+            markBlank(image, mask, weight, x, y, blank);
+        }
+    }
+    for (int y = 0; y < size; y++) {
+        for (int x = 0; x < numCols; x++) {
+            markBlank(image, mask, weight, x, y, blank);
+        }
+    }
+    for (int y = numRows - size; y < numRows; y++) {
+        for (int x = 0; x < numCols; x++) {
+            markBlank(image, mask, weight, x, y, blank);
+        }
+    }
+
+    return true;
+}
+
+
+bool pmSubtractionMaskApply(psImage *image, psImage *weight, const psImage *mask, pmSubtractionMode mode)
+{
+    PS_ASSERT_IMAGE_NON_NULL(image, false);
+    PS_ASSERT_IMAGE_TYPE(image, PS_TYPE_F32, false);
+    if (weight) {
+        PS_ASSERT_IMAGE_NON_NULL(weight, false);
+        PS_ASSERT_IMAGE_TYPE(weight, PS_TYPE_F32, false);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(weight, image, false);
+    }
+    PS_ASSERT_IMAGE_NON_NULL(mask, false);
+    PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, false);
+    PS_ASSERT_IMAGES_SIZE_EQUAL(mask, image, false);
+
+    bool maskVal = PM_SUBTRACTION_MASK_BORDER; // Value to mask
+    switch (mode) {
+      case PM_SUBTRACTION_MODE_1:
+        maskVal |= PM_SUBTRACTION_MASK_CONVOLVE_1;
+        break;
+      case PM_SUBTRACTION_MODE_2:
+        maskVal |= PM_SUBTRACTION_MASK_CONVOLVE_2;
+        break;
+      case PM_SUBTRACTION_MODE_DUAL:
+        maskVal |= PM_SUBTRACTION_MASK_CONVOLVE_2 | PM_SUBTRACTION_MASK_CONVOLVE_2;
+        break;
+      case PM_SUBTRACTION_MODE_ERR:
+      case PM_SUBTRACTION_MODE_UNSURE:
+      default:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unsuppored subtraction mode: %x", mode);
+        return false;
+    }
+
+    int numCols = image->numCols, numRows = image->numRows; // Size of image
+    psMaskType **maskData = mask->data.PS_TYPE_MASK_DATA; // Dereference mask
+
+    for (int y = 0; y < numRows; y++) {
+        for (int x = 0; x < numCols; x++) {
+            if (maskData[y][x] & maskVal) {
+                image->data.F32[y][x] = NAN;
+                if (weight) {
+                    weight->data.F32[y][x] = NAN;
+                }
+            }
+        }
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionMask.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionMask.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionMask.h	(revision 22158)
@@ -0,0 +1,36 @@
+#ifndef PM_SUBTRACTION_MASK_H
+#define PM_SUBTRACTION_MASK_H
+
+#include <pslib.h>
+
+/// Generate a mask for use in the subtraction process
+psImage *pmSubtractionMask(const psImage *refMask, ///< Mask for the reference image (will be convolved)
+                           const psImage *inMask, ///< Mask for the input image, or NULL
+                           psMaskType maskVal, ///< Value to mask out
+                           int size, ///< Half-size of the kernel (pmSubtractionKernels.size)
+                           int footprint, ///< Half-size of the kernel footprint
+                           float badFrac, ///< Maximum fraction of bad input pixels to accept
+                           bool useFFT  ///< Use FFT to do convolution?
+    );
+
+/// Mark the non-convolved part of the image as blank
+bool pmSubtractionBorder(psImage *image,///< Image
+                         psImage *weight, ///< Weight map (or NULL)
+                         psImage *mask, ///< Mask (or NULL)
+                         int size,      ///< Kernel half-size
+                         psMaskType blank ///< Mask value for blank regions
+    );
+
+/// Apply the subtraction mask to an image and weight.
+///
+/// Unfortunately, image subtraction may result in a bi-modal image in masked areas, which can upset image
+/// statistics (very important for quantising images so that a product can be written out!).  This function
+/// sets masked areas to NAN in the image and weight.
+bool pmSubtractionMaskApply(psImage *image, ///< Image to which to apply mask
+                            psImage *weight, ///< Weight map to which to apply mask (or NULL)
+                            const psImage *mask, ///< Subtraction mask
+                            pmSubtractionMode mode ///< Subtraction mode
+    );
+
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionMatch.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionMatch.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionMatch.c	(revision 22158)
@@ -0,0 +1,751 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmSubtractionParams.h"
+#include "pmSubtractionKernels.h"
+#include "pmSubtractionStamps.h"
+#include "pmSubtractionEquation.h"
+#include "pmSubtraction.h"
+#include "pmSubtractionMask.h"
+#include "pmSubtractionMatch.h"
+
+#define KERNEL_MOSAIC 2                 // Half-number of kernel instances in the mosaic image
+#define BG_STAT PS_STAT_ROBUST_MEDIAN   // Statistic to use for background
+
+static bool useFFT = true;              // Do convolutions using FFT
+
+
+//#define TESTING
+//#define TESTING_MEMORY
+
+// Output memory usage information
+static void memCheck(const char *where)
+{
+#ifdef TESTING_MEMORY
+    psMemBlock **leaks = NULL;
+    int numLeaks = psMemCheckLeaks(0, &leaks, NULL, true);
+    size_t largestSize = 0;
+    psMemId largest = 0;
+    size_t totalSize = 0;
+    for (int i = 0; i < numLeaks; i++) {
+        psMemBlock *mb = leaks[i];
+        totalSize += mb->userMemorySize;
+        if (mb->userMemorySize > largestSize) {
+            largestSize = mb->userMemorySize;
+            largest = mb->id;
+        }
+    }
+    psFree(leaks);
+    fprintf(stderr, "%s:\n", where);
+    fprintf(stderr, "    Memory in use: %zd\n", totalSize);
+    fprintf(stderr, "    Largest block: %ld\n", largest);
+    fprintf(stderr, "    sbrk(): %zd\n", (size_t)sbrk(0));
+#endif
+    return;
+}
+
+
+static bool getStamps(pmSubtractionStampList **stamps, // Stamps to read
+                      const pmReadout *ro1, // Readout 1
+                      const pmReadout *ro2, // Readout 2
+                      const psImage *subMask, // Mask for subtraction, or NULL
+                      psImage *weight,  // Weight map
+                      const psRegion *region, // Region of interest, or NULL
+                      float threshold,  // Threshold for stamp finding
+                      float stampSpacing, // Spacing between stamps
+                      int size,         // Kernel half-size
+                      int footprint,     // Convolution footprint for stamps
+                      pmSubtractionMode mode // Mode for subtraction
+    )
+{
+    psTrace("psModules.imcombine", 3, "Finding stamps...\n");
+    *stamps = pmSubtractionStampsFind(*stamps, ro1->image, subMask, region, threshold, footprint,
+                                      stampSpacing, mode);
+    if (!*stamps) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to find stamps.");
+        return false;
+    }
+
+    memCheck("  find stamps");
+
+    psTrace("psModules.imcombine", 3, "Extracting stamps...\n");
+    if (!pmSubtractionStampsExtract(*stamps, ro1->image, ro2 ? ro2->image : NULL, weight, size)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to extract stamps.");
+        return false;
+    }
+
+    memCheck("   extract stamps");
+
+    return true;
+}
+
+
+// Record the variance factor in a readout
+static bool recordVarianceFactor(pmReadout *ro, // Readout of interest
+                                 float varFactor, // Variance factor
+                                 const psRegion *region // Region of interest
+                                 )
+{
+    if (region) {
+        varFactor *= (region->x1 - region->x1 + 1) * (region->y1 * region->y1 + 1) /
+            (ro->image->numCols * ro->image->numRows);
+    }
+
+    psMetadataItem *vfItem = psMetadataLookup(ro->analysis, PM_SUBTRACTION_ANALYSIS_VARFACTOR);
+    if (vfItem) {
+        psAssert(vfItem->type == PS_TYPE_F32, "Should be the type we said.");
+        vfItem->data.F32 += varFactor;
+    } else {
+        psMetadataAddF32(ro->analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_VARFACTOR, 0,
+                         "Variance factor weighted by the area", varFactor);
+    }
+
+    return true;
+}
+
+bool pmSubtractionMatch(pmReadout *conv1, pmReadout *conv2, const pmReadout *ro1, const pmReadout *ro2,
+                        int footprint, float regionSize, float stampSpacing, float threshold,
+                        const psArray *sources, const char *stampsName,
+                        pmSubtractionKernelsType type, int size, int spatialOrder,
+                        const psVector *isisWidths, const psVector *isisOrders,
+                        int inner, int ringsOrder, int binning, float penalty,
+                        bool optimum, const psVector *optFWHMs, int optOrder, float optThreshold,
+                        int iter, float rej, psMaskType maskBad, psMaskType maskBlank,
+                        float badFrac, pmSubtractionMode mode)
+{
+    if (mode != PM_SUBTRACTION_MODE_2) {
+        PM_ASSERT_READOUT_NON_NULL(conv1, false);
+        if (conv1->image) {
+            psFree(conv1->image);
+            conv1->image = NULL;
+        }
+        if (conv1->mask) {
+            psFree(conv1->mask);
+            conv1->mask = NULL;
+        }
+        if (conv1->weight) {
+            psFree(conv1->weight);
+            conv1->weight = NULL;
+        }
+    }
+    if (mode != PM_SUBTRACTION_MODE_1) {
+        PM_ASSERT_READOUT_NON_NULL(conv2, false);
+        if (conv2->image) {
+            psFree(conv2->image);
+            conv2->image = NULL;
+        }
+        if (conv2->mask) {
+            psFree(conv2->mask);
+            conv2->mask = NULL;
+        }
+        if (conv2->weight) {
+            psFree(conv2->weight);
+            conv2->weight = NULL;
+        }
+    }
+
+    PM_ASSERT_READOUT_NON_NULL(ro1, false);
+    PM_ASSERT_READOUT_NON_NULL(ro2, false);
+    PM_ASSERT_READOUT_IMAGE(ro1, false);
+    PM_ASSERT_READOUT_IMAGE(ro2, false);
+    PS_ASSERT_IMAGES_SIZE_EQUAL(ro1->image, ro2->image, false);
+
+    PS_ASSERT_INT_NONNEGATIVE(footprint, false);
+    // regionSize can be just about anything (except maybe negative, but it can be NAN)
+    PS_ASSERT_FLOAT_LARGER_THAN(stampSpacing, 0.0, false);
+    // Don't care what threshold is
+    if (sources) {
+        PS_ASSERT_ARRAY_NON_NULL(sources, false);
+    }
+    // stampsName may be anything
+    // We'll check kernel type when we allocate the kernels
+    PS_ASSERT_INT_POSITIVE(size, false);
+    PS_ASSERT_INT_NONNEGATIVE(spatialOrder, false);
+    if (isisWidths || isisOrders) {
+        PS_ASSERT_VECTOR_NON_NULL(isisWidths, false);
+        PS_ASSERT_VECTOR_TYPE(isisWidths, PS_TYPE_F32, false);
+        PS_ASSERT_VECTOR_NON_NULL(isisOrders, false);
+        PS_ASSERT_VECTOR_TYPE(isisOrders, PS_TYPE_S32, false);
+        PS_ASSERT_VECTORS_SIZE_EQUAL(isisWidths, isisOrders, false);
+    }
+    PS_ASSERT_INT_NONNEGATIVE(inner, false);
+    PS_ASSERT_INT_NONNEGATIVE(ringsOrder, false);
+    PS_ASSERT_INT_POSITIVE(binning, false);
+    if (optimum) {
+        PS_ASSERT_VECTOR_NON_NULL(optFWHMs, false);
+        PS_ASSERT_INT_NONNEGATIVE(optOrder, false);
+        PS_ASSERT_FLOAT_LARGER_THAN(optThreshold, 0.0, false);
+        PS_ASSERT_FLOAT_LESS_THAN_OR_EQUAL(optThreshold, 1.0, false);
+    }
+    PS_ASSERT_INT_POSITIVE(iter, false);
+    PS_ASSERT_FLOAT_LARGER_THAN(rej, 0.0, false);
+    // Don't care about maskBad
+    // Don't care about maskBlank
+    if (isfinite(badFrac)) {
+        PS_ASSERT_FLOAT_LARGER_THAN(badFrac, 0.0, NULL);
+        PS_ASSERT_FLOAT_LESS_THAN_OR_EQUAL(badFrac, 1.0, NULL);
+    }
+
+    // If the stamp footprint is smaller than the kernel size, then we won't get much signal in the outer
+    // parts of the kernel, which can result in bad matching artifacts.
+    if (footprint < size) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Stamp footprint (%d) should be larger than or equal to the kernel size (%d)",
+                footprint, size);
+        return false;
+    }
+
+    // Where does our weight map come from?
+    // Getting the weight exactly right is not necessary --- it's just used for weighting.
+    psImage *weight = NULL;             // Weight image to use
+    if (ro1->weight && ro2->weight) {
+        weight = (psImage*)psBinaryOp(NULL, ro1->weight, "+", ro2->weight);
+    } else if (ro1->weight) {
+        weight = psMemIncrRefCounter(ro1->weight);
+    } else if (ro2->weight) {
+        weight = psMemIncrRefCounter(ro2->weight);
+    } else {
+        weight = (psImage*)psBinaryOp(NULL, ro1->image, "+", ro2->image);
+    }
+
+    // Putting important variable declarations here, since they are freed after a "goto" if there is an error.
+    psImage *subMask = NULL;            // Mask for subtraction
+    psRegion *region = NULL;            // Iso-kernel region
+    psString regionString = NULL;       // String for region
+    pmSubtractionStampList *stamps = NULL; // Stamps for matching PSF
+    pmSubtractionKernels *kernels = NULL; // Kernel basis functions
+
+    int numCols = ro1->image->numCols, numRows = ro1->image->numRows; // Image dimensions
+
+    memCheck("start");
+
+    subMask = pmSubtractionMask(ro1->mask, ro2 ? ro2->mask : NULL, maskBad, size, footprint,
+                                badFrac, useFFT);
+    if (!subMask) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to generate subtraction mask.");
+        psFree(weight);
+        return false;
+    }
+
+    memCheck("mask");
+
+    // Get region of interest
+    int xRegions = 1, yRegions = 1;     // Number of iso-kernel regions
+    float xRegionSize = 0, yRegionSize = 0; // Size of iso-kernel regions
+    if (isfinite(regionSize) && regionSize != 0.0) {
+        xRegions = numCols / regionSize + 1;
+        yRegions = numRows / regionSize + 1;
+        xRegionSize = (float)numCols / (float)xRegions;
+        yRegionSize = (float)numRows / (float)yRegions;
+        region = psRegionAlloc(NAN, NAN, NAN, NAN);
+    }
+
+    // Iterate over iso-kernel regions
+    for (int j = 0; j < yRegions; j++) {
+        for (int i = 0; i < xRegions; i++) {
+            psTrace("psModules.imcombine", 1, "Subtracting region %d of %d...\n",
+                    j * xRegions + i + 1, xRegions * yRegions);
+            if (region) {
+                *region = psRegionSet((int)(i * xRegionSize), (int)((i + 1) * xRegionSize),
+                                      (int)(j * yRegionSize), (int)((j + 1) * yRegionSize));
+                psFree(regionString);
+                regionString = psRegionToString(*region);
+                psTrace("psModules.imcombine", 3, "Iso-kernel region: %s out of %d,%d\n",
+                        regionString, numCols, numRows);
+            }
+
+            if (sources) {
+                stamps = pmSubtractionStampsSetFromSources(sources, subMask, region, footprint,
+                                                           stampSpacing, mode);
+            } else if (stampsName && strlen(stampsName) > 0) {
+                stamps = pmSubtractionStampsSetFromFile(stampsName, ro1->image, subMask, region, footprint,
+                                                        stampSpacing, mode);
+            }
+
+            // We get the stamps here; we will also attempt to get stamps at the first iteration, but it
+            // doesn't matter.
+            if (!getStamps(&stamps, ro1, ro2, subMask, weight, NULL, threshold, stampSpacing,
+                           size, footprint, mode)) {
+                goto MATCH_ERROR;
+            }
+
+            if (mode == PM_SUBTRACTION_MODE_UNSURE) {
+                // Get backgrounds
+                psStats *bgStats = psStatsAlloc(BG_STAT); // Statistics for background
+                psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0); // Random number generator
+                psVector *buffer = NULL;// Buffer for stats
+                if (!psImageBackground(bgStats, &buffer, ro1->image, ro1->mask, maskBad, rng)) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to measure background of image 1.");
+                    psFree(bgStats);
+                    psFree(rng);
+                    psFree(buffer);
+                    goto MATCH_ERROR;
+                }
+                float bg1 = psStatsGetValue(bgStats, BG_STAT); // Background for image 1
+                if (!psImageBackground(bgStats, &buffer, ro2->image, ro2->mask, maskBad, rng)) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to measure background of image 2.");
+                    psFree(bgStats);
+                    psFree(rng);
+                    psFree(buffer);
+                    goto MATCH_ERROR;
+                }
+                float bg2 = psStatsGetValue(bgStats, BG_STAT); // Background for image 2
+                psFree(bgStats);
+                psFree(rng);
+                psFree(buffer);
+
+                pmSubtractionMode newMode = pmSubtractionOrder(stamps, bg1, bg2); // Subtraction mode to use
+                switch (newMode) {
+                  case PM_SUBTRACTION_MODE_1:
+                    psLogMsg("psModules.imcombine", PS_LOG_INFO, "Convolving image 1 to match image 2.");
+                    break;
+                  case PM_SUBTRACTION_MODE_2:
+                    psLogMsg("psModules.imcombine", PS_LOG_INFO, "Convolving image 2 to match image 1.");
+                    break;
+                  default:
+                    psError(PS_ERR_UNKNOWN, false, "Unable to determine subtraction order.");
+                    goto MATCH_ERROR;
+                }
+                mode = newMode;
+            }
+
+            // Define kernel basis functions
+            if (optimum && (type == PM_SUBTRACTION_KERNEL_ISIS || type == PM_SUBTRACTION_KERNEL_GUNK)) {
+                kernels = pmSubtractionKernelsOptimumISIS(type, size, inner, spatialOrder, optFWHMs, optOrder,
+                                                          stamps, footprint, optThreshold, penalty, mode);
+                if (!kernels) {
+                    psErrorClear();
+                    psWarning("Unable to derive optimum ISIS kernel --- switching to default.");
+                }
+            }
+            if (kernels == NULL) {
+                // Not an ISIS/GUNK kernel, or the optimum kernel search failed
+                kernels = pmSubtractionKernelsGenerate(type, size, spatialOrder, isisWidths, isisOrders,
+                                                       inner, binning, ringsOrder, penalty, mode);
+            }
+
+            // Add analysis metadata
+            {
+                psRegion *subRegion;    // Region over which subtraction was performed
+                if (region) {
+                    subRegion = psMemIncrRefCounter(region);
+                } else {
+                    subRegion = psRegionAlloc(0, numCols, 0, numRows);
+                }
+
+                if (mode == PM_SUBTRACTION_MODE_1 || mode == PM_SUBTRACTION_MODE_DUAL) {
+                    psMetadataAddPtr(conv1->analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_KERNEL,
+                                     PS_DATA_UNKNOWN | PS_META_DUPLICATE_OK, "Subtraction kernels", kernels);
+                    psMetadataAddS32(conv1->analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_MODE,
+                                     PS_META_DUPLICATE_OK, "Subtraction kernels", mode);
+                    psMetadataAddPtr(conv1->analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_REGION,
+                                     PS_DATA_REGION | PS_META_DUPLICATE_OK,
+                                     "Region over which subtraction was performed", subRegion);
+                }
+                if (mode == PM_SUBTRACTION_MODE_2 || mode == PM_SUBTRACTION_MODE_DUAL) {
+                    psMetadataAddPtr(conv2->analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_KERNEL,
+                                     PS_DATA_UNKNOWN | PS_META_DUPLICATE_OK, "Subtraction kernels", kernels);
+                    psMetadataAddS32(conv2->analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_MODE,
+                                     PS_META_DUPLICATE_OK, "Subtraction kernels", mode);
+                    psMetadataAddPtr(conv2->analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_REGION,
+                                     PS_DATA_REGION | PS_META_DUPLICATE_OK,
+                                     "Region over which subtraction was performed", subRegion);
+                }
+                psFree(subRegion);
+            }
+
+            memCheck("kernels");
+
+            float rmsStamps = NAN;      // RMS for stamps
+            int numStamps = 0;          // Number of good stamps
+            int numRejected = -1;       // Number of rejected stamps in each iteration
+            for (int k = 0; k < iter && numRejected != 0; k++) {
+                psLogMsg("psModules.imcombine", PS_LOG_INFO, "Iteration %d.", k);
+
+                if (!getStamps(&stamps, ro1, ro2, subMask, weight, region, threshold, stampSpacing,
+                               size, footprint, mode)) {
+                    goto MATCH_ERROR;
+                }
+
+                psTrace("psModules.imcombine", 3, "Calculating equation...\n");
+                if (!pmSubtractionCalculateEquation(stamps, kernels)) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to calculate least-squares equation.");
+                    goto MATCH_ERROR;
+                }
+
+                memCheck("  calculate equation");
+
+                psTrace("psModules.imcombine", 3, "Solving equation...\n");
+
+                if (!pmSubtractionSolveEquation(kernels, stamps)) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to calculate least-squares equation.");
+                    goto MATCH_ERROR;
+                }
+
+                memCheck("  solve equation");
+
+                psVector *deviations = pmSubtractionCalculateDeviations(stamps, kernels); // Stamp deviations
+                if (!deviations) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to calculate deviations.");
+                    goto MATCH_ERROR;
+                }
+
+                memCheck("   calculate deviations");
+
+                psTrace("psModules.imcombine", 3, "Rejecting stamps...\n");
+                numRejected = pmSubtractionRejectStamps(&rmsStamps, &numStamps, stamps, deviations,
+                                                        subMask, rej, footprint);
+                if (numRejected < 0) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to reject stamps.");
+                    psFree(deviations);
+                    goto MATCH_ERROR;
+                }
+                psFree(deviations);
+
+                memCheck("  reject stamps");
+            }
+
+            if (numRejected > 0) {
+                psTrace("psModules.imcombine", 3, "Solving equation...\n");
+                if (!pmSubtractionSolveEquation(kernels, stamps)) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to calculate least-squares equation.");
+                    goto MATCH_ERROR;
+                }
+                psVector *deviations = pmSubtractionCalculateDeviations(stamps, kernels); // Stamp deviations
+                if (!deviations) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to calculate deviations.");
+                    goto MATCH_ERROR;
+                }
+                pmSubtractionRejectStamps(&rmsStamps, &numStamps, stamps, deviations,
+                                          subMask, NAN, footprint);
+                psFree(deviations);
+            }
+            psFree(stamps);
+            stamps = NULL;
+
+            if (mode == PM_SUBTRACTION_MODE_1 || mode == PM_SUBTRACTION_MODE_DUAL) {
+                psMetadataAddS32(conv1->analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_STAMPS_NUM,
+                                 PS_META_DUPLICATE_OK, "Number of good stamps", numStamps);
+                psMetadataAddF32(conv1->analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_STAMPS_RMS,
+                                 PS_META_DUPLICATE_OK, "RMS deviation of stamps", rmsStamps);
+            }
+            if (mode == PM_SUBTRACTION_MODE_2 || mode == PM_SUBTRACTION_MODE_DUAL) {
+                psMetadataAddS32(conv2->analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_STAMPS_NUM,
+                                 PS_META_DUPLICATE_OK, "Number of good stamps", numStamps);
+                psMetadataAddF32(conv2->analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_STAMPS_RMS,
+                                 PS_META_DUPLICATE_OK, "RMS deviation of stamps", rmsStamps);
+            }
+
+            memCheck("solution");
+
+            {
+                psTrace("psModules.imcombine", 2, "Generating diagnostics...\n");
+                // Generate image with convolution kernels
+                int fullSize = 2 * size + 1 + 1;    // Full size of kernel
+                int imageSize = (2 * KERNEL_MOSAIC + 1) * fullSize;
+                psImage *convKernels = psImageAlloc((mode == PM_SUBTRACTION_MODE_DUAL ? 2 : 1) *
+                                                    imageSize - 1 +
+                                                    (mode == PM_SUBTRACTION_MODE_DUAL ? 4 : 0),
+                                                    imageSize - 1, PS_TYPE_F32);
+                psImageInit(convKernels, NAN);
+                for (int j = -KERNEL_MOSAIC; j <= KERNEL_MOSAIC; j++) {
+                    for (int i = -KERNEL_MOSAIC; i <= KERNEL_MOSAIC; i++) {
+                        psImage *kernel = pmSubtractionKernelImage(kernels, (float)i / (float)KERNEL_MOSAIC,
+                                                                   (float)j / (float)KERNEL_MOSAIC,
+                                                                   false); // Image of the kernel
+                        if (!kernel) {
+                            psError(PS_ERR_UNKNOWN, false, "Unable to generate kernel image.");
+                            psFree(convKernels);
+                            goto MATCH_ERROR;
+                        }
+
+                        if (psImageOverlaySection(convKernels, kernel, (i + KERNEL_MOSAIC) * fullSize,
+                                                  (j + KERNEL_MOSAIC) * fullSize, "=") == 0) {
+                            psError(PS_ERR_UNKNOWN, false, "Unable to overlay kernel image.");
+                            psFree(kernel);
+                            psFree(convKernels);
+                            goto MATCH_ERROR;
+                        }
+                        psFree(kernel);
+
+                        if (mode == PM_SUBTRACTION_MODE_DUAL) {
+                            kernel = pmSubtractionKernelImage(kernels, (float)i / (float)KERNEL_MOSAIC,
+                                                              (float)j / (float)KERNEL_MOSAIC,
+                                                              true); // Image of the kernel
+                            if (!kernel) {
+                                psError(PS_ERR_UNKNOWN, false, "Unable to generate kernel image.");
+                                psFree(convKernels);
+                                goto MATCH_ERROR;
+                            }
+
+                            if (psImageOverlaySection(convKernels, kernel,
+                                                      (2 * KERNEL_MOSAIC + 1 + i + KERNEL_MOSAIC) * fullSize +
+                                                      4,
+                                                      (j + KERNEL_MOSAIC) * fullSize, "=") == 0) {
+                                psError(PS_ERR_UNKNOWN, false, "Unable to overlay kernel image.");
+                                psFree(kernel);
+                                psFree(convKernels);
+                                goto MATCH_ERROR;
+                            }
+                            psFree(kernel);
+                        }
+
+                    }
+                }
+
+                psString comment = NULL; // Comment for metadata
+                psStringAppend(&comment, "Subtraction kernel for region %s", regionString);
+                psMetadataAddImage(conv1->analysis, PS_LIST_TAIL, "SUBTRACTION.KERNEL.IMAGE",
+                                   PS_META_DUPLICATE_OK, comment, convKernels);
+                psFree(comment);
+                psFree(convKernels);
+            }
+
+#if 0
+            {
+                // Generate images of the kernel components
+                psMetadata *header = psMetadataAlloc(); // Header
+                for (int i = 0; i < solution->n; i++) {
+                    psString name = NULL;       // Header keyword
+                    psStringAppend(&name, "SOLN%04d", i);
+                    psMetadataAddF64(header, PS_LIST_TAIL, name, 0, NULL, solution->data.F64[i]);
+                    psFree(name);
+                }
+                psArray *kernelImages = pmSubtractionKernelSolutions(solution, kernels, 0.0, 0.0);
+                psFits *kernelFile = psFitsOpen("kernels.fits", "w");
+                (void)psFitsWriteImageCube(kernelFile, header, kernelImages, NULL);
+                psFitsClose(kernelFile);
+                psFree(kernelImages);
+                psFree(header);
+            }
+#endif
+
+            memCheck("diag outputs");
+
+            psTrace("psModules.imcombine", 2, "Convolving...\n");
+            if (!pmSubtractionConvolve(conv1, conv2, ro1, ro2, subMask, maskBlank, region, kernels,
+                                       true, useFFT)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to convolve image.");
+                goto MATCH_ERROR;
+            }
+
+            // Set the variance factors
+            switch (mode) {
+              case PM_SUBTRACTION_MODE_1: {
+                  recordVarianceFactor(conv1, pmSubtractionVarianceFactor(kernels, 0.5, 0.5, false),
+                                       region);
+                  break;
+              }
+              case PM_SUBTRACTION_MODE_2:
+                recordVarianceFactor(conv1, pmSubtractionVarianceFactor(kernels, 0.5, 0.5, false),
+                                     region);
+                break;
+              case PM_SUBTRACTION_MODE_DUAL:
+                recordVarianceFactor(conv1, pmSubtractionVarianceFactor(kernels, 0.5, 0.5, false),
+                                     region);
+                recordVarianceFactor(conv2, pmSubtractionVarianceFactor(kernels, 0.5, 0.5, true),
+                                     region);
+                break;
+              default:
+                psAbort("Should never reach here.");
+            }
+
+            psFree(kernels);
+            kernels = NULL;
+
+            // There is data in the readout now
+            if (mode == PM_SUBTRACTION_MODE_1 || mode == PM_SUBTRACTION_MODE_DUAL) {
+                conv1->data_exists = true;
+                if (conv1->parent) {
+                    conv1->parent->data_exists = true;
+                    conv1->parent->parent->data_exists = true;
+                }
+            }
+            if (mode == PM_SUBTRACTION_MODE_2 || mode == PM_SUBTRACTION_MODE_DUAL) {
+                conv2->data_exists = true;
+                if (conv2->parent) {
+                    conv2->parent->data_exists = true;
+                    conv2->parent->parent->data_exists = true;
+                }
+            }
+        }
+    }
+    psFree(region);
+    region = NULL;
+    psFree(regionString);
+    regionString = NULL;
+    psFree(subMask);
+    subMask = NULL;
+    psFree(weight);
+    weight = NULL;
+
+    if (!pmSubtractionBorder(conv1->image, conv1->weight, conv1->mask, size, maskBlank)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to set border of convolved image.");
+        goto MATCH_ERROR;
+    }
+
+    memCheck("convolution");
+
+
+#ifdef TESTING
+    {
+        if (mode == PM_SUBTRACTION_MODE_1 || mode == PM_SUBTRACTION_MODE_DUAL) {
+            psFits *fits = psFitsOpen("convolved1.fits", "w");
+            psFitsWriteImage(fits, NULL, conv1->image, 0, NULL);
+            psFitsClose(fits);
+        }
+
+        if (mode == PM_SUBTRACTION_MODE_2 || mode == PM_SUBTRACTION_MODE_DUAL) {
+            psFits *fits = psFitsOpen("convolved2.fits", "w");
+            psFitsWriteImage(fits, NULL, conv2->image, 0, NULL);
+            psFitsClose(fits);
+        }
+    }
+#endif
+
+    return true;
+
+MATCH_ERROR:
+    psFree(region);
+    psFree(regionString);
+    psFree(subMask);
+    psFree(kernels);
+    psFree(stamps);
+    psFree(weight);
+    return false;
+}
+
+
+// Determine a rough width (integer value) of the star in the image
+// XXX Could improve this by using a user-provided list of floating-point widths (or an end point and
+// increment).
+static int subtractionOrderWidth(const psKernel *kernel, // Image
+                                 float bg, // Background in image
+                                 int size, // Maximum size
+                                 psArray **models, // Buffer of models
+                                 psVector **modelSums // Buffer of model sums
+    )
+{
+    assert(kernel);
+    assert(models);
+    assert(modelSums);
+
+    int xMin = kernel->xMin, xMax = kernel->xMax; // Bounds in x
+    int yMin = kernel->yMin, yMax = kernel->yMax; // Bounds in y
+
+    // Generate models
+    if (!*models) {
+        assert(!*modelSums);
+        *models = psArrayAlloc(size);
+        *modelSums = psVectorAlloc(size, PS_TYPE_F64);
+        for (int sigma = 0; sigma < size; sigma++) {
+            psKernel *model = psKernelAlloc(xMin, xMax, yMin, yMax); // Gaussian model
+            float invSigma2 = 1.0 / (float)PS_SQR(1 + sigma); // Inverse sigma squared
+            double sumGG = 0.0;         // Sum of square of Gaussian
+            for (int y = yMin; y <= yMax; y++) {
+                int y2 = PS_SQR(y);     // y squared
+                for (int x = xMin; x <= xMax; x++) {
+                    float rad2 = PS_SQR(x) + y2; // Radius squared
+                    float value = expf(-rad2 * invSigma2); // Model value
+                    model->kernel[y][x] = value;
+                    sumGG += PS_SQR(value);
+                }
+            }
+            (*models)->data[sigma] = model;
+            (*modelSums)->data.F64[sigma] = sumGG;
+        }
+    }
+
+    // Fit gaussians of varying widths to the image, record the chi^2
+    psVector *chi2 = psVectorAlloc(size, PS_TYPE_F32); // chi^2 as a function of radius
+    for (int sigma = 0; sigma < size; sigma++) {
+        double sumFG = 0.0; // Sum for calculating the normalisation of the Gaussian
+        psKernel *model = (*models)->data[sigma]; // Model of interest
+        for (int y = yMin; y <= yMax; y++) {
+            for (int x = xMin; x <= xMax; x++) {
+                sumFG += model->kernel[y][x] * (kernel->kernel[y][x] - bg);
+            }
+        }
+        float norm = sumFG / (*modelSums)->data.F64[sigma]; // Normalisation for Gaussian
+        double sumDev2 = 0.0;           // Sum of square deviations
+        for (int y = yMin; y <= yMax; y++) {
+            for (int x = xMin; x <= xMax; x++) {
+                float dev = kernel->kernel[y][x] - bg - norm * model->kernel[y][x]; // Deviation
+                sumDev2 += PS_SQR(dev);
+            }
+        }
+        chi2->data.F32[sigma] = sumDev2;
+    }
+
+    // Find the minimum chi^2
+    int bestIndex = -1;                 // Index of best chi^2
+    float bestChi2 = INFINITY;          // Best chi^2
+    for (int i = 0; i < size; i++) {
+        if (chi2->data.F32[i] < bestChi2) {
+            bestChi2 = chi2->data.F32[i];
+            bestIndex = i;
+        }
+    }
+    psFree(chi2);
+
+    return bestIndex + 1;
+}
+
+pmSubtractionMode pmSubtractionOrder(pmSubtractionStampList *stamps, float bg1, float bg2)
+{
+    PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, PM_SUBTRACTION_MODE_ERR);
+
+    psVector *mask = psVectorAlloc(stamps->num, PS_TYPE_MASK); // Mask for stamps
+    psVector *ratios = psVectorAlloc(stamps->num, PS_TYPE_F32); // Ratios of widths
+    psArray *models = NULL;             // Gaussian models
+    psVector *modelSums = NULL;         // Gaussian model sums
+    for (int i = 0; i < stamps->num; i++) {
+        pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest
+        if (stamp->status != PM_SUBTRACTION_STAMP_CALCULATE && stamp->status != PM_SUBTRACTION_STAMP_USED) {
+            mask->data.PS_TYPE_MASK_DATA[i] = 0xff;
+            continue;
+        }
+
+        // Widths of stars
+        int width1 = subtractionOrderWidth(stamp->image1, bg1, stamps->footprint, &models, &modelSums);
+        int width2 = subtractionOrderWidth(stamp->image2, bg2, stamps->footprint, &models, &modelSums);
+
+        if (width1 == 0 || width2 == 0) {
+            ratios->data.F32[i] = NAN;
+            mask->data.PS_TYPE_MASK_DATA[i] = 0xff;
+        } else {
+            ratios->data.F32[i] = (float)width1 / (float)width2;
+            mask->data.PS_TYPE_MASK_DATA[i] = 0;
+        }
+    }
+    psFree(models);
+    psFree(modelSums);
+
+    psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN);
+    if (!psVectorStats(stats, ratios, NULL, mask, 0xff)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to calculate statistics for moments ratio.");
+        psFree(mask);
+        psFree(ratios);
+        psFree(stats);
+        return PM_SUBTRACTION_MODE_ERR;
+    }
+    psFree(ratios);
+    psFree(mask);
+
+    psLogMsg("psModules.imcombine", PS_LOG_INFO, "Median width ratio: %lf", stats->robustMedian);
+    pmSubtractionMode mode = (stats->robustMedian <= 1.0 ? PM_SUBTRACTION_MODE_1 : PM_SUBTRACTION_MODE_2);
+    psFree(stats);
+
+    return mode;
+}
+
+
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionMatch.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionMatch.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionMatch.h	(revision 22158)
@@ -0,0 +1,59 @@
+#ifndef PM_SUBTRACTION_MATCH_H
+#define PM_SUBTRACTION_MATCH_H
+
+#include <pslib.h>
+
+#include <pmHDU.h>
+#include <pmFPA.h>
+#include <pmSubtractionKernels.h>
+#include <pmSubtractionStamps.h>
+
+#define PM_SUBTRACTION_ANALYSIS_KERNEL "SUBTRACTION.KERNEL" // Name of kernel in the analysis metadata
+#define PM_SUBTRACTION_ANALYSIS_MODE "SUBTRACTION.MODE" // Name of subtraction mode in the analysis metadata
+#define PM_SUBTRACTION_ANALYSIS_REGION "SUBTRACTION.REGION" // Name of subtraction region in the analysis MD
+#define PM_SUBTRACTION_ANALYSIS_STAMPS_RMS "SUBTRACTION.RMS" // Name of stamp rms in the analysis metadata
+#define PM_SUBTRACTION_ANALYSIS_STAMPS_NUM "SUBTRACTION.NUM"// Name of the number of stamps in the analysis MD
+#define PM_SUBTRACTION_ANALYSIS_VARFACTOR "SUBTRACTION.VARFACTOR"// Name of variance factor in the analysis MD
+
+/// Match two images
+bool pmSubtractionMatch(pmReadout *conv1, ///< Output convolved data for image 1
+                        pmReadout *conv2, ///< Output convolved data for image 2
+                        const pmReadout *ro1, ///< Image 1
+                        const pmReadout *ro2, ///< Image 2
+                        // Stamp parameters
+                        int footprint,  ///< Stamp half-size
+                        float regionSize, ///< Typical size of iso-kernel regions
+                        float stampSpacing, ///< Typical spacing between stamps
+                        float threshold, ///< Threshold for stamps
+                        const psArray *sources, ///< Sources for stamps
+                        const char *stampsName, ///< Filename for stamps
+                        // Kernel parameters
+                        pmSubtractionKernelsType type, ///< Kernel type
+                        int size,       ///< Kernel half-size
+                        int order,      ///< Spatial polynomial order
+                        const psVector *widths, ///< ISIS Gaussian widths
+                        const psVector *orders, ///< ISIS Polynomial orders
+                        int inner,      ///< Inner radius for various kernel types
+                        int ringsOrder, ///< RINGS polynomial order
+                        int binning,    ///< SPAM kernel binning
+                        float penalty,  ///< Penalty for wideness
+                        bool optimum,   ///< Search for optimum ISIS kernel?
+                        const psVector *optFWHMs, ///< FWHMs for optimum search
+                        int optOrder,   ///< Maximum order for optimum search
+                        float optThreshold, ///< Threshold for optimum search (0..1)
+                        // Operational parameters
+                        int iter,       ///< Rejection iterations
+                        float rej,      ///< Rejection threshold
+                        psMaskType maskBad, ///< Value to mask
+                        psMaskType maskBlank, ///< Mask for blank region
+                        float badFrac,   ///< Maximum fraction of bad input pixels to accept
+                        pmSubtractionMode mode ///< Mode of subtraction; may be modified
+    );
+
+/// Determine which image to convolve
+pmSubtractionMode pmSubtractionOrder(pmSubtractionStampList *stamps, ///< Stamps that have been extracted
+                                     float bg1, float bg2 // Background for each image
+    );
+
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionParams.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionParams.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionParams.c	(revision 22158)
@@ -0,0 +1,510 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <pslib.h>
+
+#include "pmSubtractionStamps.h"
+#include "pmSubtraction.h"
+#include "pmSubtractionParams.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#if 0
+// Convolve the reference stamp by the kernel
+static psKernel *convolveStamp(const pmSubtractionStamp *stamp, // Stamp to be convolved
+                               const psKernel *kernel, // Kernel by which to convolve
+                               int footprint // Size of area to be convolved
+    )
+{
+    psKernel *convolution = psKernelAlloc(-footprint, footprint, -footprint, footprint); // Result
+    psKernel *reference = stamp->reference; // Reference stamp, to be convolved
+
+    // Range of kernel
+    int uMin = kernel->xMin;
+    int uMax = kernel->xMax;
+    int vMin = kernel->yMin;
+    int vMax = kernel->yMax;
+
+    for (int y = -footprint; y <= footprint; y++) {
+        psF32 *conv = &convolution->kernel[y][-footprint]; // Dereference convolution
+        for (int x = -footprint; x <= footprint; x++, conv++) {
+            *conv = 0.0;
+
+            int xStart = x + uMin;      // Start index for convolution
+            for (int v = vMin; v <= vMax; v++) {
+                psF32 *ref = &reference->kernel[y + v][xStart]; // Dereference reference image
+                psF32 *krnl = &kernel->kernel[v][uMin]; // Dereference kernel in x
+                for (int u = uMin; u <= uMax; u++, ref++, krnl++) {
+                    *conv += *ref * *krnl;
+                }
+            }
+        }
+    }
+
+    return convolution;
+}
+#endif
+
+/// Select the appropriate convolution, given the kernel basis function and subtraction mode
+static inline psKernel *selectConvolution(const pmSubtractionStamp *stamp, // Stamp
+                                          int kernelIndex, // Index for kernel component
+                                          pmSubtractionMode mode // Mode of subtraction
+    )
+{
+    switch (mode) {
+      case PM_SUBTRACTION_MODE_1:
+        return stamp->convolutions1->data[kernelIndex];
+      case PM_SUBTRACTION_MODE_2:
+        return stamp->convolutions2->data[kernelIndex];
+      default:
+        psAbort("Unsupported subtraction mode: %x", mode);
+    }
+    return NULL;                        // Unreached
+}
+
+// Accumulate cross-term sums for a stamp
+static void accumulateCross(double *sumI, // Sum of I(x)/sigma(x)^2
+                            double *sumII, // Sum of I(x)^2/sigma(x)^2
+                            double *sumIC, // Sum of I(x)conv(x)/sigma(x)^2
+                            const pmSubtractionStamp *stamp, // Stamp with weight
+                            const psKernel *target, // Target stamp
+                            int kernelIndex, // Index for kernel component
+                            int footprint, // Size of region of interest
+                            pmSubtractionMode mode // Mode of subtraction
+    )
+{
+    psKernel *weight = stamp->weight;   // Weight, sigma(x)^2
+    psKernel *convolution = selectConvolution(stamp, kernelIndex, mode); // Convolution of interest
+
+    for (int y = -footprint; y <= footprint; y++) {
+        psF32 *in = &target->kernel[y][-footprint]; // Dereference input
+        psF32 *wt = &weight->kernel[y][-footprint]; // Dereference weight
+        psF32 *conv = &convolution->kernel[y][-footprint]; // Dereference convolution
+        for (int x = -footprint; x <= footprint; x++, in++, wt++, conv++) {
+            double temp = *in / *wt; // Temporary product
+            *sumI += temp;
+            *sumII += *in * temp;
+            *sumIC += *conv * temp;
+        }
+    }
+    return;
+}
+
+// Accumulate convolution sums for a stamp
+static void accumulateConvolutions(double *sumC, // Sum of conv(x)/sigma(x)^2
+                                   double *sumCC, // Sum of conv(x)^2/sigma(x)^2
+                                   const pmSubtractionStamp *stamp, // Stamp with input and weight
+                                   int kernelIndex, // Index for kernel component
+                                   int footprint, // Size of region of interest
+                                   pmSubtractionMode mode // Mode of subtraction
+    )
+{
+    psKernel *weight = stamp->weight;   // Weight, sigma(x)^2
+    psKernel *convolution = selectConvolution(stamp, kernelIndex, mode); // Convolution of interest
+
+    for (int y = -footprint; y <= footprint; y++) {
+        psF32 *wt = &weight->kernel[y][-footprint]; // Dereference weight
+        psF32 *conv = &convolution->kernel[y][-footprint]; // Dereference convolution
+        for (int x = -footprint; x <= footprint; x++, wt++, conv++) {
+            double convNoise = *conv / *wt; // Temporary product
+            *sumC += convNoise;
+            *sumCC += *conv * convNoise;
+        }
+    }
+    return;
+}
+
+static double accumulateChi2(const psKernel *target, // Target stamp
+                             pmSubtractionStamp *stamp, // Stamp with weight
+                             int kernelIndex, // Index for kernel component
+                             double coeff, // Coefficient of convolution
+                             double bg,  // Background term
+                             int footprint, // Size of region of interest
+                             pmSubtractionMode mode // Mode of subtraction
+    )
+{
+    double chi2 = 0.0;
+    psKernel *weight = stamp->weight;   // Weight, sigma(x)^2
+    psKernel *convolution = selectConvolution(stamp, kernelIndex, mode); // Convolution of interest
+
+    for (int y = -footprint; y <= footprint; y++) {
+        psF32 *in = &target->kernel[y][-footprint]; // Dereference input
+        psF32 *wt = &weight->kernel[y][-footprint]; // Dereference weight
+        psF32 *conv = &convolution->kernel[y][-footprint]; // Dereference convolution
+        for (int x = -footprint; x <= footprint; x++, in++, wt++, conv++) {
+            chi2 += PS_SQR(*in - bg - coeff * *conv) / *wt;
+        }
+    }
+
+    return chi2;
+}
+
+// Return the initial value of chi^2
+static double initialChi2(const psKernel *target, // Target stamp
+                          const pmSubtractionStamp *stamp, // Stamp with weight
+                          int footprint, // Size of convolution
+                          pmSubtractionMode mode // Mode of subtraction
+    )
+{
+    psKernel *weight = stamp->weight;   // Weight map
+    psKernel *source;                   // Source stamp
+    switch (mode) {
+      case PM_SUBTRACTION_MODE_1:
+        source = stamp->image1;
+        break;
+      case PM_SUBTRACTION_MODE_2:
+        source = stamp->image2;
+        break;
+      default:
+        psAbort("Unsupported subtraction mode: %x", mode);
+    }
+
+    double chi2 = 0.0;                  // Chi^2
+    for (int y = -footprint; y <= footprint; y++) {
+        psF32 *in = &target->kernel[y][-footprint]; // Dereference input
+        psF32 *wt = &weight->kernel[y][-footprint]; // Dereference weight
+        psF32 *ref = &source->kernel[y][-footprint]; // Derference reference
+        for (int x = -footprint; x <= footprint; x++, in++, wt++, ref++) {
+            float diff = *in - *ref;    // Temporary value
+            chi2 += PS_SQR(diff) / *wt;
+        }
+    }
+
+    return chi2;
+}
+
+// Subtract a convolution from the input
+static void subtractConvolution(psKernel *target, // Target stamp
+                                const pmSubtractionStamp *stamp, // Stamp with weight
+                                int kernelIndex, // Index for kernel component
+                                float coeff, // Coefficient of subtraction
+                                float bg, // Background term
+                                int footprint, // Size of region of interest
+                                pmSubtractionMode mode // Mode of subtraction
+    )
+{
+    psKernel *convolution = selectConvolution(stamp, kernelIndex, mode); // Convolution of interest
+    for (int y = -footprint; y <= footprint; y++) {
+        psF32 *in = &target->kernel[y][-footprint]; // Dereference input
+        psF32 *conv = &convolution->kernel[y][-footprint]; // Dereference convolution
+        for (int x = -footprint; x <= footprint; x++, in++, conv++) {
+            *in -= *conv * coeff + bg;
+        }
+    }
+
+    return;
+}
+
+
+pmSubtractionKernels *pmSubtractionKernelsOptimumISIS(pmSubtractionKernelsType type, int size, int inner,
+                                                      int spatialOrder, const psVector *fwhms, int maxOrder,
+                                                      const pmSubtractionStampList *stamps, int footprint,
+                                                      float tolerance, float penalty, pmSubtractionMode mode)
+{
+    if (type != PM_SUBTRACTION_KERNEL_ISIS && type != PM_SUBTRACTION_KERNEL_GUNK) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Invalid kernel type: %x\n", type);
+        return NULL;
+    }
+    PS_ASSERT_INT_NONNEGATIVE(size, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(inner, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(spatialOrder, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(fwhms, NULL);
+    PS_ASSERT_VECTOR_TYPE(fwhms, PS_TYPE_F32, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(maxOrder, NULL);
+    PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, NULL);
+    PS_ASSERT_INT_NONNEGATIVE(footprint, NULL);
+    PS_ASSERT_FLOAT_LARGER_THAN(tolerance, 0.0, NULL);
+
+    // Generate the kernels to test
+    int numGaussians = fwhms->n;       // Number of Gaussians
+    int numKernels = numGaussians * (maxOrder + 1) * (maxOrder + 2) / 2; // Number of kernel components
+    psString params = NULL;             // Parameter, for description
+    for (int i = 0; i < numGaussians; i++) {
+        psStringAppend(&params, "%.2f,", fwhms->data.F32[i]);
+    }
+    params[strlen(params) - 1] = '\0';
+
+    psVector *orders = psVectorAlloc(numGaussians, PS_TYPE_S32); // Polynomial orders
+    psVectorInit(orders, maxOrder);
+    pmSubtractionKernels *kernels = p_pmSubtractionKernelsRawISIS(size, spatialOrder, fwhms, orders,
+                                                                  penalty, mode); // Kernels
+    psFree(orders);
+    psFree(kernels->description);
+    kernels->description = NULL;
+    psStringAppend(&kernels->description, "OptISIS(%d,(%s),%d)", size, params, spatialOrder);
+    psFree(params);
+
+    // Need to save the stamp inputs --- we're changing the values!
+    int numStamps = stamps->num;        // Number of stamps
+    psArray *targets = psArrayAlloc(numStamps); // Deep copies of the targets
+    psVector *badStamps = psVectorAlloc(numStamps, PS_TYPE_U8); // Mark the bad stamps
+    psVectorInit(badStamps, 0);
+    for (int i = 0; i < numStamps; i++) {
+        pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest
+        if (stamp->status != PM_SUBTRACTION_STAMP_CALCULATE && stamp->status != PM_SUBTRACTION_STAMP_USED) {
+            badStamps->data.U8[i] = 0xff;
+            continue;
+        }
+        psKernel *target;               // Target image of interest
+        switch (mode) {
+          case PM_SUBTRACTION_MODE_1:
+            target = stamp->image2;
+            break;
+          case PM_SUBTRACTION_MODE_2:
+            target = stamp->image1;
+            break;
+          default:
+            psAbort("Unsupported subtraction mode: %x", mode);
+        }
+        psImage *copy = psImageCopy(NULL, target->image, PS_TYPE_F32); // Copy of the image
+        targets->data[i] = psKernelAllocFromImage(copy, size + footprint, size + footprint);
+        psFree(copy);                   // Drop reference
+    }
+
+    // Generate the convolutions, accumulate sums, and measure initial chi^2
+    double sum1 = 0.0;                  // sum of 1/sigma(x,y)^2
+    psVector *sumC = psVectorAlloc(numKernels, PS_TYPE_F64); // sum of R(x)*k(u)/sigma(x)^2
+    psVector *sumCC = psVectorAlloc(numKernels, PS_TYPE_F64); // sum of [R(x)*k(u)]^2/sigma(x)^2
+    psVectorInit(sumC, 0.0);
+    psVectorInit(sumCC, 0.0);
+    double lastChi2 = 0.0;              // Chi^2 from last iteration
+    int numPixels = 0;                  // Number of pixels contributing to chi^2
+    for (int i = 0; i < numStamps; i++) {
+        pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest
+        if (badStamps->data.U8[i]) {
+            continue;
+        }
+        if (!pmSubtractionConvolveStamp(stamp, kernels, footprint)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to convolve stamp %d.", i);
+            psFree(targets);
+            psFree(kernels);
+            psFree(badStamps);
+            return NULL;
+        }
+
+        // This sum is invariant to the kernel
+        psKernel *weight = stamp->weight; // Weight map for stamp
+        for (int v = -footprint; v <= footprint; v++) {
+            psF32 *wt = &weight->kernel[v][-footprint]; // Dereference weight map
+            for (int u = -footprint; u <= footprint; u++, wt++) {
+                sum1 += 1.0 / *wt;
+            }
+        }
+        if (!isfinite(sum1)) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Sum of 1/sigma^2 is non-finite for stamp %d (%d,%d)\n",
+                    i, (int)stamp->x, (int)stamp->y);
+            psFree(targets);
+            psFree(kernels);
+            psFree(badStamps);
+            return NULL;
+        }
+
+        for (int j = 0; j < numKernels; j++) {
+            accumulateConvolutions(&sumC->data.F64[j], &sumCC->data.F64[j], stamp, j, footprint, mode);
+        }
+
+        lastChi2 += initialChi2(targets->data[i], stamp, footprint, mode);
+        numPixels += PS_SQR(2 * footprint + 1);
+    }
+    lastChi2 /= numPixels;
+
+    // Rank the kernel components
+    psVector *ranking = psVectorAlloc(numKernels, PS_TYPE_S32); // Ranking of the kernel components
+    psVectorInit(ranking, -1);
+    int cutIndex = -1;                  // Index at which to cut off kernels
+    for (int iter = 0; iter < numKernels; iter++) {
+        int bestIndex = -1;             // Index of best kernel component
+        double bestChi2 = INFINITY;     // Value of best chi^2
+        double bestCoeff = 0;           // Value of best coefficient
+        double bestBG = 0;              // Value of best background
+
+        for (int i = 0; i < numKernels; i++) {
+            if (ranking->data.S32[i] >= 0) {
+                continue;
+            }
+
+            double sumI = 0.0;          // sum of I(x)/sigma(x)^2
+            double sumII = 0.0;         // sum of I(x)^2/sigma(x)^2
+            double sumIC = 0.0;         // sum of I(x)C(x)/sigma(x)^2
+
+            for (int j = 0; j < numStamps; j++) {
+                if (badStamps->data.U8[j]) {
+                    continue;
+                }
+                pmSubtractionStamp *stamp = stamps->stamps->data[j]; // Stamp of interest
+                accumulateCross(&sumI, &sumII, &sumIC, stamp, targets->data[j], i, footprint, mode);
+            }
+
+            double invDet = 1.0 / (sum1 * sumCC->data.F64[i] - PS_SQR(sumC->data.F64[i])); // Determinant^-1
+            double coeff = invDet * (sum1 * sumIC - sumC->data.F64[i] * sumI); // Coefficient for kernel
+            double bg = invDet * (sumCC->data.F64[i] * sumI - sumC->data.F64[i] * sumIC); // Background
+
+            double chi2 = 0.0;          // Chi^2
+            for (int j = 0; j < numStamps; j++) {
+                if (badStamps->data.U8[j]) {
+                    continue;
+                }
+                pmSubtractionStamp *stamp = stamps->stamps->data[j]; // Stamp of interest
+                chi2 += accumulateChi2(targets->data[j], stamp, i, coeff, bg, footprint, mode);
+            }
+
+            if (chi2 < bestChi2) {
+                bestIndex = i;
+                bestCoeff = coeff;
+                bestChi2 = chi2;
+                bestBG = bg;
+            }
+
+            psTrace("psModules.imcombine", 8, "%d: %lf %lf %lf %lf %lf %lf\n", i, sum1, sumI, sumII, sumIC,
+                    sumC->data.F64[i], sumCC->data.F64[i]);
+            psTrace("psModules.imcombine", 6, "%d: %lf %lf %lf\n", i, coeff, bg, chi2);
+        }
+        bestChi2 /= numPixels;
+
+        if (bestIndex == -1) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to find best kernel component in round %d.", iter);
+            psFree(targets);
+            psFree(sumC);
+            psFree(sumCC);
+            psFree(ranking);
+            psFree(kernels);
+            psFree(badStamps);
+            return NULL;
+        }
+
+        // And the winner is....
+        ranking->data.S32[bestIndex] = iter;
+        // Remove its contribution, and don't include it in the future.
+        for (int j = 0; j < numStamps; j++) {
+            if (badStamps->data.U8[j]) {
+                continue;
+            }
+            pmSubtractionStamp *stamp = stamps->stamps->data[j]; // Stamp of interest
+            subtractConvolution(targets->data[j], stamp, bestIndex, bestCoeff, bestBG, footprint, mode);
+        }
+
+        double diff = lastChi2 - bestChi2; // Difference in chi^2 between iterations
+
+        psTrace("psModules.imcombine", 3, "The winner of round %d is %d (%f,%d,%d): %lf (%lf) --> %lf\n",
+                iter, bestIndex, kernels->widths->data.F32[bestIndex], kernels->u->data.S32[bestIndex],
+                kernels->v->data.S32[bestIndex], bestCoeff, diff, bestChi2);
+
+        if (fabsf(diff) < tolerance) {
+            cutIndex = iter;
+            break;
+        }
+
+        lastChi2 = bestChi2;
+    }
+    psFree(targets);
+    psFree(sumC);
+    psFree(sumCC);
+
+    if (cutIndex < 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to converge to tolerance %g\n", tolerance);
+        psFree(ranking);
+        psFree(kernels);
+        psFree(badStamps);
+        return NULL;
+    }
+
+    int newSize = cutIndex + 1;         // Size of new kernel basis set
+    psTrace("psModules.imcombine", 2, "Accepting %d kernels.\n", newSize);
+    psVector *uNew = psVectorAlloc(newSize, PS_TYPE_S32);
+    psVector *vNew = psVectorAlloc(newSize, PS_TYPE_S32);
+    psVector *widthsNew = psVectorAlloc(newSize, PS_TYPE_F32);
+    psArray *preCalcNew = psArrayAlloc(newSize);
+    psArray *convNew = psArrayAlloc(numStamps);
+    for (int i = 0; i < numStamps; i++) {
+        if (badStamps->data.U8[i]) {
+            continue;
+        }
+        convNew->data[i] = psArrayAlloc(newSize);
+    }
+
+    for (int i = 0; i < numKernels; i++) {
+        int rank = ranking->data.S32[i]; // This kernel component's ranking
+        if (rank >= 0 && rank < newSize) {
+            uNew->data.S32[rank] = kernels->u->data.S32[i];
+            vNew->data.S32[rank] = kernels->v->data.S32[i];
+            widthsNew->data.F32[rank] = kernels->widths->data.F32[i];
+            preCalcNew->data[rank] = psMemIncrRefCounter(kernels->preCalc->data[i]);
+
+            for (int j = 0; j < numStamps; j++) {
+                if (badStamps->data.U8[j]) {
+                    continue;
+                }
+                pmSubtractionStamp *stamp = stamps->stamps->data[j]; // Stamp of interest
+                psArray *convolutions = convNew->data[j]; // Convolutions for this stamp
+                convolutions->data[rank] = psMemIncrRefCounter(selectConvolution(stamp, i, mode));
+            }
+        }
+    }
+    psFree(kernels->u);
+    psFree(kernels->v);
+    psFree(kernels->widths);
+    psFree(kernels->preCalc);
+    kernels->u = uNew;
+    kernels->v = vNew;
+    kernels->widths = widthsNew;
+    kernels->preCalc = preCalcNew;
+    kernels->num = newSize;
+
+    for (int i = 0; i < numStamps; i++) {
+        if (badStamps->data.U8[i]) {
+            continue;
+        }
+        pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest
+        psFree(stamp->convolutions1);
+        psFree(stamp->convolutions2);
+        switch (mode) {
+          case PM_SUBTRACTION_MODE_1:
+            stamp->convolutions1 = convNew->data[i];
+            stamp->convolutions2 = NULL;
+            break;
+          case PM_SUBTRACTION_MODE_2:
+            stamp->convolutions1 = NULL;
+            stamp->convolutions2 = convNew->data[i];
+            break;
+          default:
+            psAbort("Unsupported subtraction mode: %x", mode);
+        }
+    }
+
+    psFree(badStamps);
+    psFree(ranking);
+
+    // Maintain photometric scaling
+    if (type == PM_SUBTRACTION_KERNEL_ISIS) {
+        psKernel *subtract = kernels->preCalc->data[0]; // Kernel to subtract from the rest
+        for (int i = 1; i < newSize; i++) {
+            if (kernels->u->data.S32[i] % 2 == 0 && kernels->v->data.S32[i] % 2 == 0) {
+                psKernel *kernel = kernels->preCalc->data[i]; // Kernel of interest
+                psBinaryOp(kernel->image, kernel->image, "-", subtract->image);
+            }
+        }
+    } else if (type == PM_SUBTRACTION_KERNEL_GUNK) {
+        psStringPrepend(&kernels->description, "GUNK=");
+        psStringAppend(&kernels->description, "+POIS(%d,%d)", inner, spatialOrder);
+
+        for (int i = 0; i < newSize; i++) {
+            if (kernels->u->data.S32[i] % 2 == 0 && kernels->v->data.S32[i] % 2 == 0) {
+                psKernel *kernel = kernels->preCalc->data[i]; // Kernel of interest
+                kernel->kernel[0][0] -= 1.0;
+            }
+        }
+
+        if (!p_pmSubtractionKernelsAddGrid(kernels, numGaussians, inner)) {
+            psAbort("Should never get here.");
+        }
+
+        kernels->type = PM_SUBTRACTION_KERNEL_GUNK;
+    }
+
+    return kernels;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionParams.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionParams.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionParams.h	(revision 22158)
@@ -0,0 +1,22 @@
+#ifndef PM_SUBTRACTION_PARAMS_H
+#define PM_SUBTRACTION_PARAMS_H
+
+#include <pslib.h>
+#include <pmSubtractionKernels.h>
+#include <pmSubtractionStamps.h>
+
+/// Generate a set of optimum kernels for ISIS (or GUNK)
+pmSubtractionKernels *pmSubtractionKernelsOptimumISIS(pmSubtractionKernelsType type, ///< Kernel type
+                                                      int size, ///< Half-size of kernel
+                                                      int inner, ///< Inner radius for GUNK
+                                                      int spatialOrder, ///< Spatial polynomial order
+                                                      const psVector *fwhms, ///< Gaussian FWHMs to try
+                                                      int maxOrder, ///< Maximum polynomial order
+                                                      const pmSubtractionStampList *stamps, ///< Stamps
+                                                      int footprint, ///< Convolution footprint for stamps
+                                                      float tolerance, ///< Maximum difference in chi^2
+                                                      float penalty, ///< Penalty for wideness
+                                                      pmSubtractionMode mode // Mode for subtraction
+    );
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionStamps.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionStamps.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionStamps.c	(revision 22158)
@@ -0,0 +1,603 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+// All these includes required to get stamps out of an array of pmSources
+#include "pmMoments.h"
+#include "pmPeaks.h"
+#include "pmResiduals.h"
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmGrowthCurve.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+
+
+#include "pmSubtraction.h"
+#include "pmSubtractionStamps.h"
+
+#define STAMP_LIST_BUFFER 20            // Number of stamps to add to list at a time
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Private (file-static) functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Free function for pmSubtractionStampList
+static void subtractionStampListFree(pmSubtractionStampList *list // Stamp list to free
+                                     )
+{
+    psFree(list->stamps);
+    psFree(list->regions);
+    psFree(list->x);
+    psFree(list->y);
+    psFree(list->flux);
+}
+
+// Free function for pmSubtractionStamp
+static void subtractionStampFree(pmSubtractionStamp *stamp // Stamp to free
+                                 )
+{
+    psFree(stamp->image1);
+    psFree(stamp->image2);
+    psFree(stamp->weight);
+    psFree(stamp->convolutions1);
+    psFree(stamp->convolutions2);
+
+    psFree(stamp->matrix1);
+    psFree(stamp->matrix2);
+    psFree(stamp->matrixX);
+    psFree(stamp->vector1);
+    psFree(stamp->vector2);
+
+}
+
+// Is this region OK?
+static bool checkStampRegion(int x, int y, // Coordinates of stamp
+                             const psRegion *region // Region of interest
+                             )
+{
+    if (!region) {
+        return true;
+    }
+    return (x < region->x0 || x > region->x1 || y < region->y0 || y > region->y1) ?
+        false : true;
+}
+
+// Is this position unmasked?
+static bool checkStampMask(int x, int y, // Coordinates of stamp
+                           const psImage *mask, // Mask
+                           pmSubtractionMode mode // Mode for subtraction
+                           )
+{
+    if (!mask) {
+        return true;
+    }
+    if (x < 0 || x >= mask->numCols || y < 0 || y >= mask->numRows) {
+        return false;
+    }
+
+    psMaskType maskVal = PM_SUBTRACTION_MASK_BORDER | PM_SUBTRACTION_MASK_REJ; // Mask value
+    switch (mode) {
+      case PM_SUBTRACTION_MODE_1:
+        maskVal |= PM_SUBTRACTION_MASK_FOOTPRINT_1;
+        break;
+      case PM_SUBTRACTION_MODE_2:
+        maskVal |= PM_SUBTRACTION_MASK_FOOTPRINT_2;
+        break;
+      case PM_SUBTRACTION_MODE_UNSURE:
+      case PM_SUBTRACTION_MODE_DUAL:
+        maskVal |= PM_SUBTRACTION_MASK_FOOTPRINT_1 | PM_SUBTRACTION_MASK_FOOTPRINT_2;
+        break;
+      default:
+        psAbort("Unsupported subtraction mode: %x", mode);
+    }
+
+    return (mask->data.PS_TYPE_MASK_DATA[y][x] & maskVal) ? false : true;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Public functions
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+pmSubtractionStampList *pmSubtractionStampListAlloc(int numCols, int numRows, const psRegion *region,
+                                                    int footprint, float spacing)
+{
+    pmSubtractionStampList *list = psAlloc(sizeof(pmSubtractionStampList)); // Stamp list to return
+    psMemSetDeallocator(list, (psFreeFunc)subtractionStampListFree);
+
+    // Get region in which to find stamps: [xMin:xMax,yMin:yMax]
+    int xMin = 0, xMax = numCols, yMin = 0, yMax = numRows;
+    if (region) {
+        xMin = PS_MAX(region->x0, xMin);
+        xMax = PS_MIN(region->x1, xMax);
+        yMin = PS_MAX(region->y0, yMin);
+        yMax = PS_MIN(region->y1, yMax);
+    }
+    int xSize = xMax - xMin, ySize = yMax - yMin; // Size of region of interest
+    int xStamps = (float)xSize / spacing + 1, yStamps = (float)ySize / spacing + 1; // Number of stamps
+
+    list->num = xStamps * yStamps;
+    list->stamps = psArrayAlloc(list->num);
+    list->regions = psArrayAlloc(list->num);
+
+    for (int y = 0, index = 0; y < yStamps; y++) {
+        int yStart = yMin + y * ((float)ySize / (float)(yStamps)); // Subregion starts here
+        int yStop = yMin + (y + 1) * ((float)ySize / (float)(yStamps)) - 1; // Subregion stops here
+        assert(yStart >= yMin && yStop < yMax);
+
+        for (int x = 0; x < xStamps; x++, index++) {
+            int xStart = xMin + x * ((float)xSize / (float)(xStamps)); // Subregion starts here
+            int xStop = xMin + (x + 1) * ((float)xSize / (float)(xStamps)) - 1; // Subregion stops here
+            assert(xStart >= xMin && xStop < xMax);
+
+            list->stamps->data[index] = pmSubtractionStampAlloc();
+            psTrace("psModules.imcombine", 6, "Stamp region %d: [%d:%d,%d:%d]\n",
+                    index, xStart, xStop, yStart, yStop);
+            list->regions->data[index] = psRegionAlloc(xStart, xStop, yStart, yStop);
+        }
+    }
+
+    list->x = NULL;
+    list->y = NULL;
+    list->flux = NULL;
+    list->footprint = footprint;
+
+    return list;
+}
+
+pmSubtractionStamp *pmSubtractionStampAlloc(void)
+{
+    pmSubtractionStamp *stamp = psAlloc(sizeof(pmSubtractionStamp)); // Stamp to return
+    psMemSetDeallocator(stamp, (psFreeFunc)subtractionStampFree);
+
+    stamp->x = NAN;
+    stamp->y = NAN;
+    stamp->flux = NAN;
+    stamp->xNorm = NAN;
+    stamp->yNorm = NAN;
+    stamp->status = PM_SUBTRACTION_STAMP_INIT;
+
+    stamp->image1 = NULL;
+    stamp->image2 = NULL;
+    stamp->weight = NULL;
+    stamp->convolutions1 = NULL;
+    stamp->convolutions2 = NULL;
+
+    stamp->matrix1 = NULL;
+    stamp->matrix2 = NULL;
+    stamp->matrixX = NULL;
+    stamp->vector1 = NULL;
+    stamp->vector2 = NULL;
+
+    return stamp;
+}
+
+
+pmSubtractionStampList *pmSubtractionStampsFind(pmSubtractionStampList *stamps, const psImage *image,
+                                                const psImage *subMask, const psRegion *region,
+                                                float threshold, int footprint, float spacing,
+                                                pmSubtractionMode mode)
+{
+    PS_ASSERT_IMAGE_NON_NULL(image, NULL);
+    PS_ASSERT_IMAGE_TYPE(image, PS_TYPE_F32, NULL);
+    if (subMask) {
+        PS_ASSERT_IMAGE_NON_NULL(subMask, NULL);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(image, subMask, NULL);
+        PS_ASSERT_IMAGE_TYPE(subMask, PS_TYPE_MASK, NULL);
+    }
+    PS_ASSERT_INT_NONNEGATIVE(footprint, NULL);
+    PS_ASSERT_FLOAT_LARGER_THAN(spacing, 0.0, NULL);
+    if (region) {
+        if (psRegionIsNaN(*region)) {
+            psString string = psRegionToString(*region);
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Input region (%s) contains NAN values", string);
+            psFree(string);
+            return false;
+        }
+        if (region->x0 < 0 || region->x1 > image->numCols ||
+            region->y0 < 0 || region->y1 > image->numRows) {
+            psString string = psRegionToString(*region);
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Input region (%s) does not fit in image (%dx%d)",
+                    string, image->numCols, image->numRows);
+            psFree(string);
+            return false;
+        }
+    }
+
+    int numRows = image->numRows, numCols = image->numCols; // Size of image
+
+    if (!stamps) {
+        stamps = pmSubtractionStampListAlloc(numCols, numRows, region, footprint, spacing);
+    }
+
+    int numStamps = stamps->num;        // Number of stamp regions
+    int numFound = 0;                   // Number of stamps found
+    int numValid = 0;                   // Number of valid regions
+    for (int i = 0; i < numStamps; i++) {
+        pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest
+
+        // Only find a new stamp if we need to
+        if (stamp->status != PM_SUBTRACTION_STAMP_REJECTED && stamp->status != PM_SUBTRACTION_STAMP_INIT) {
+            continue;
+        }
+        numValid++;
+
+        float xStamp = 0, yStamp = 0;   // Coordinates of stamp
+        float fluxStamp = NAN;          // Flux of stamp
+        bool goodStamp = false;         // Found a good stamp?
+
+        // A couple different ways of finding stamps:
+        if (stamps->x && stamps->y) {
+            // Get the next stamp from the list
+            psVector *xList = stamps->x->data[i], *yList = stamps->y->data[i]; // Coordinate lists
+            psVector *fluxList = stamps->flux->data[i]; // List of stamp fluxes
+
+            // Take stamp off the top of the (sorted) list
+            if (xList->n > 0) {
+                int index = xList->n - 1; // Index of new stamp
+                xStamp = xList->data.F32[index];
+                yStamp = yList->data.F32[index];
+                fluxStamp = fluxList->data.F32[index];
+
+                // Chop off the top of the list
+                xList->n = index;
+                yList->n = index;
+                fluxList->n = index;
+
+                goodStamp = true;
+            }
+        } else {
+            // Use a simple method of automatically finding stamps --- take the highest pixel in the subregion
+            fluxStamp = threshold;
+            psRegion *subRegion = stamps->regions->data[i]; // Sub-region of interest
+            for (int y = subRegion->y0; y <= subRegion->y1; y++) {
+                for (int x = subRegion->x0; x <= subRegion->x1; x++) {
+                    if (checkStampMask(x, y, subMask, mode) && image->data.F32[y][x] > fluxStamp) {
+                        fluxStamp = image->data.F32[y][x];
+                        xStamp = x;
+                        yStamp = y;
+                        goodStamp = true;
+                    }
+                }
+            }
+        }
+
+        if (goodStamp) {
+            stamp->x = xStamp;
+            stamp->y = yStamp;
+            stamp->flux = fluxStamp;
+
+            // Reset the postage stamps since we're making a new stamp
+            psFree(stamp->image1);
+            psFree(stamp->image2);
+            psFree(stamp->weight);
+            psFree(stamp->convolutions1);
+            psFree(stamp->convolutions2);
+            stamp->image1 = stamp->image2 = stamp->weight = NULL;
+            stamp->convolutions1 = stamp->convolutions2 = NULL;
+
+            stamp->status = PM_SUBTRACTION_STAMP_FOUND;
+            numFound++;
+            psTrace("psModules.imcombine", 5, "Found stamp in subregion %d: %d,%d\n",
+                    i, (int)stamp->x, (int)stamp->y);
+        } else {
+            stamp->status = PM_SUBTRACTION_STAMP_NONE;
+        }
+    }
+
+    if (numValid > 0) {
+        psLogMsg("psModules.imcombine", PS_LOG_INFO, "Found %d stamps", numFound);
+    }
+
+    return stamps;
+}
+
+
+pmSubtractionStampList *pmSubtractionStampsSet(const psVector *x, const psVector *y, const psVector *flux,
+                                               const psImage *image, const psImage *subMask,
+                                               const psRegion *region, int footprint, float spacing,
+                                               pmSubtractionMode mode)
+
+{
+    PS_ASSERT_VECTOR_NON_NULL(x, NULL);
+    PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F32, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
+    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, NULL);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(y, x, NULL);
+    if (flux) {
+        PS_ASSERT_VECTOR_NON_NULL(flux, NULL);
+        PS_ASSERT_VECTOR_TYPE(flux, PS_TYPE_F32, NULL);
+        PS_ASSERT_VECTORS_SIZE_EQUAL(flux, x, NULL);
+    } else {
+        PS_ASSERT_IMAGE_NON_NULL(image, NULL);
+    }
+    if (subMask) {
+        PS_ASSERT_IMAGE_NON_NULL(subMask, NULL);
+        PS_ASSERT_IMAGE_TYPE(subMask, PS_TYPE_MASK, NULL);
+        if (image) {
+            PS_ASSERT_IMAGE_NON_NULL(image, NULL);
+            PS_ASSERT_IMAGES_SIZE_EQUAL(image, subMask, NULL);
+        }
+    }
+    PS_ASSERT_FLOAT_LARGER_THAN(spacing, 0.0, NULL);
+
+    int numStars = x->n;                // Number of stars
+    pmSubtractionStampList *stamps = pmSubtractionStampListAlloc(subMask->numCols, subMask->numRows,
+                                                                 region, footprint, spacing); // Stamp list
+    int numStamps = stamps->num;        // Number of stamps
+
+    // Initialise the lists
+    stamps->x = psArrayAlloc(numStamps);
+    stamps->y = psArrayAlloc(numStamps);
+    stamps->flux = psArrayAlloc(numStamps);
+    for (int i = 0; i < numStamps; i++) {
+        stamps->x->data[i] = psVectorAllocEmpty(STAMP_LIST_BUFFER, PS_TYPE_F32);
+        stamps->y->data[i] = psVectorAllocEmpty(STAMP_LIST_BUFFER, PS_TYPE_F32);
+        stamps->flux->data[i] = psVectorAllocEmpty(STAMP_LIST_BUFFER, PS_TYPE_F32);
+    }
+
+    // Put the stars into their appropriate subregions
+    for (int i = 0; i < numStars; i++) {
+        float xStamp = x->data.F32[i], yStamp = y->data.F32[i]; // Coordinates of stamp
+        int xPix = xStamp + 0.5, yPix = yStamp + 0.5; // Pixel coordinate of stamp
+        if (!checkStampRegion(xPix, yPix, region)) {
+            // It's not in the big region
+            psTrace("psModules.imcombine", 9, "Rejecting input stamp (%d,%d) because outside region",
+                    xPix, yPix);
+            continue;
+        }
+        if (!checkStampMask(xPix, yPix, subMask, mode)) {
+            // Not a good stamp
+            psTrace("psModules.imcombine", 9, "Rejecting input stamp (%d,%d) because bad mask",
+                    xPix, yPix);
+            continue;
+        }
+
+        bool found = false;
+        for (int j = 0; j < numStamps && !found; j++) {
+            psRegion *subRegion = stamps->regions->data[j]; // Subregion of interest
+            if (checkStampRegion(xPix, yPix, subRegion)) {
+                psVector *xList = stamps->x->data[j], *yList = stamps->y->data[j]; // Pixel lists
+                psVector *fluxList = stamps->flux->data[j]; // Flux list
+
+                int index = xList->n;   // Index of new stamp candidate
+
+                psVectorExtend(xList, STAMP_LIST_BUFFER, 1);
+                psVectorExtend(yList, STAMP_LIST_BUFFER, 1);
+                psVectorExtend(fluxList, STAMP_LIST_BUFFER, 1);
+
+                xList->data.F32[index] = xStamp;
+                yList->data.F32[index] = yStamp;
+
+                if (flux) {
+                    fluxList->data.F32[index] = flux->data.F32[i];
+                } else {
+                    fluxList->data.F32[index] = image->data.F32[yPix][xPix];
+                }
+
+                found = true;
+                psTrace("psModules.imcombine", 9, "Putting input stamp (%d,%d) into subregion %d",
+                        xPix, yPix, j);
+            }
+        }
+
+        if (!found) {
+            psTrace("psModules.imcombine", 9, "Unable to find subregion for stamp (%d,%d)",
+                    xPix, yPix);
+        }
+    }
+
+    // Sort the list by flux, with the brightest last
+    for (int i = 0; i < numStamps; i++) {
+        psVector *xList = stamps->x->data[i], *yList = stamps->y->data[i]; // Pixel lists
+        psVector *fluxList = stamps->flux->data[i]; // Flux list
+
+        psVector *indexes = psVectorSortIndex(NULL, fluxList); // Indices to sort flux
+        int num = indexes->n;           // Number of candidate stamps in this subregion
+
+        psVector *xSorted = psVectorAlloc(num, PS_TYPE_F32); // Sorted version of x list
+        psVector *ySorted = psVectorAlloc(num, PS_TYPE_F32); // Sorted version of y list
+        psVector *fluxSorted = psVectorAlloc(num, PS_TYPE_F32); // Sorted version of flux list
+        for (int j = 0; j < num; j++) {
+            int k = indexes->data.S32[j]; // Sorted index
+            xSorted->data.F32[j] = xList->data.F32[k];
+            ySorted->data.F32[j] = yList->data.F32[k];
+            fluxSorted->data.F32[j] = fluxList->data.F32[k];
+        }
+        psFree(indexes);
+
+        psFree(stamps->x->data[i]);
+        psFree(stamps->y->data[i]);
+        psFree(stamps->flux->data[i]);
+
+        stamps->x->data[i] = xSorted;
+        stamps->y->data[i] = ySorted;
+        stamps->flux->data[i] = fluxSorted;
+    }
+
+
+    return stamps;
+}
+
+
+bool pmSubtractionStampsExtract(pmSubtractionStampList *stamps, psImage *image1, psImage *image2,
+                                psImage *weight, int kernelSize)
+{
+    PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false);
+    PS_ASSERT_IMAGE_NON_NULL(image1, false);
+    PS_ASSERT_IMAGE_TYPE(image1, PS_TYPE_F32, false);
+    if (image2) {
+        PS_ASSERT_IMAGE_NON_NULL(image2, false);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(image2, image1, false);
+        PS_ASSERT_IMAGE_TYPE(image2, PS_TYPE_F32, false);
+    }
+    PS_ASSERT_IMAGE_NON_NULL(weight, false);
+    PS_ASSERT_IMAGES_SIZE_EQUAL(weight, image1, false);
+    PS_ASSERT_IMAGE_TYPE(weight, PS_TYPE_F32, false);
+    PS_ASSERT_INT_NONNEGATIVE(kernelSize, false);
+
+    int numCols = image1->numCols, numRows = image1->numRows; // Size of images
+    int size = kernelSize + stamps->footprint; // Size of postage stamps
+
+    for (int i = 0; i < stamps->num; i++) {
+        pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest
+        if (!stamp || stamp->status != PM_SUBTRACTION_STAMP_FOUND) {
+            continue;
+        }
+
+        if (isnan(stamp->xNorm)) {
+            stamp->xNorm = 2.0 * (stamp->x - (float)numCols/2.0) / (float)numCols;
+        }
+        if (isnan(stamp->yNorm)) {
+            stamp->yNorm = 2.0 * (stamp->y - (float)numRows/2.0) / (float)numRows;
+        }
+
+        int x = stamp->x + 0.5, y = stamp->y + 0.5; // Stamp coordinates
+        if (x < size || x > numCols - size || y < size || y > numRows - size) {
+            psError(PS_ERR_UNKNOWN, false, "Stamp %d (%d,%d) is within the image border.\n", i, x, y);
+            return false;
+        }
+
+        // Catch memory leaks --- these should have been freed and NULLed before
+        assert(stamp->image1 == NULL);
+        assert(stamp->image2 == NULL);
+        assert(stamp->weight == NULL);
+
+        psRegion region = psRegionSet(x - size, x + size + 1, y - size, y + size + 1); // Region of interest
+
+        psImage *sub1 = psImageSubset(image1, region); // Subimage with stamp
+        stamp->image1 = psKernelAllocFromImage(sub1, size, size);
+        psFree(sub1);                   // Drop reference
+
+        if (image2) {
+            psImage *sub2 = psImageSubset(image2, region); // Subimage with stamp
+            stamp->image2 = psKernelAllocFromImage(sub2, size, size);
+            psFree(sub2);               // Drop reference
+        }
+
+        psImage *wtSub = psImageSubset(weight, region); // Subimage with stamp
+        stamp->weight = psKernelAllocFromImage(wtSub, size, size);
+        psFree(wtSub);                  // Drop reference
+
+        stamp->status = PM_SUBTRACTION_STAMP_CALCULATE;
+    }
+
+    return true;
+}
+
+#if 0
+bool pmSubtractionStampsGenerate(pmSubtractionStampList *stamps, float fwhm, int kernelSize)
+{
+    PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false);
+    PS_ASSERT_FLOAT_LARGER_THAN(fwhm, 0.0, false);
+    PS_ASSERT_INT_NONNEGATIVE(kernelSize, false);
+
+    int size = kernelSize + stamps->footprint; // Size of postage stamps
+    int num = stamps->num;              // Number of stamps
+    float sigma = fwhm / (2.0 * sqrtf(2.0 * log(2.0))); // Gaussian sigma
+
+    for (int i = 0; i < num; i++) {
+        pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest
+        if (!(stamp->status & PM_SUBTRACTION_STAMP_CALCULATE)) {
+            continue;
+        }
+
+        float x = stamp->x, y = stamp->y; // Coordinates of stamp
+        float flux = stamp->flux; // Flux of star
+        if (!isfinite(flux)) {
+            psWarning("Unable to generate PSF for stamp %d --- bad flux.", i);
+            stamp->status = PM_SUBTRACTION_STAMP_REJECTED;
+            continue;
+        }
+
+        float xStamp = x - (int)(x + 0.5); // x coordinate of star in stamp frame
+        float yStamp = y - (int)(y + 0.5); // y coordinate of star in stamp frame
+
+        psFree(stamp->image2);
+        stamp->image2 = psKernelAlloc(-size, size, -size, size);
+        psKernel *target = stamp->image2; // Target stamp
+
+        // Put in a Waussian, just for fun!
+        for (int v = -size; v <= size; v++) {
+            for (int u = -size; u <= size; u++) {
+                float z = (PS_SQR(u + xStamp) + PS_SQR(v + yStamp)) / (2.0 * PS_SQR(sigma));
+                target->kernel[v][u] = flux / sigma * 0.5 * M_2_SQRTPI * M_SQRT1_2 / (1.0 + z + PS_SQR(z));
+            }
+        }
+
+    }
+
+    return true;
+}
+#endif
+
+pmSubtractionStampList *pmSubtractionStampsSetFromSources(const psArray *sources, const psImage *subMask,
+                                                          const psRegion *region, int footprint,
+                                                          float spacing, pmSubtractionMode mode)
+{
+    PS_ASSERT_ARRAY_NON_NULL(sources, NULL);
+    // Let pmSubtractionStampsSet take care of the rest of the assertions
+
+    int numSources = sources->n;          // Number of stars
+
+    psVector *x = psVectorAlloc(numSources, PS_TYPE_F32); // x coordinates
+    psVector *y = psVectorAlloc(numSources, PS_TYPE_F32); // y coordinates
+    psVector *flux = psVectorAlloc(numSources, PS_TYPE_F32); // Fluxes
+
+    for (int i = 0; i < numSources; i++) {
+        pmSource *source = sources->data[i]; // Source of interest
+        if (source->modelPSF) {
+            x->data.F32[i] = source->modelPSF->params->data.F32[PM_PAR_XPOS];
+            y->data.F32[i] = source->modelPSF->params->data.F32[PM_PAR_YPOS];
+        } else {
+            x->data.F32[i] = source->peak->xf;
+            y->data.F32[i] = source->peak->yf;
+        }
+        flux->data.F32[i] = powf(10.0, -0.4 * source->psfMag);
+    }
+
+    pmSubtractionStampList *stamps = pmSubtractionStampsSet(x, y, flux, NULL, subMask, region,
+                                                            footprint, spacing, mode); // Stamps to return
+    psFree(x);
+    psFree(y);
+    psFree(flux);
+
+    if (!stamps) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to set stamps from sources.");
+    }
+
+    return stamps;
+}
+
+
+pmSubtractionStampList *pmSubtractionStampsSetFromFile(const char *filename, const psImage *image,
+                                                       const psImage *subMask, const psRegion *region,
+                                                       int footprint, float spacing, pmSubtractionMode mode)
+{
+    PS_ASSERT_STRING_NON_EMPTY(filename, NULL);
+    // Let pmSubtractionStampsSet take care of the rest of the assertions
+
+    psArray *data = psVectorsReadFromFile(filename, "%f %f");
+    if (!data) {
+        psError(PS_ERR_IO, false, "Unable to read stamps file %s", filename);
+        return NULL;
+    }
+    psVector *x = data->data[0], *y = data->data[1]; // Stamp positions
+
+    // Correct for IRAF/FITS (unit-offset) positions to C (zero-offset) positions
+    psBinaryOp(x, x, "-", psScalarAlloc(1.0, PS_TYPE_F32));
+    psBinaryOp(y, y, "-", psScalarAlloc(1.0, PS_TYPE_F32));
+
+    pmSubtractionStampList *stamps = pmSubtractionStampsSet(x, y, NULL, image, subMask, region, footprint,
+                                                            spacing, mode);
+    psFree(data);
+
+    return stamps;
+
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionStamps.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionStamps.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/imcombine/pmSubtractionStamps.h	(revision 22158)
@@ -0,0 +1,126 @@
+#ifndef PM_SUBTRACTION_STAMPS_H
+#define PM_SUBTRACTION_STAMPS_H
+
+#include <pslib.h>
+
+#include "pmSubtractionKernels.h"
+
+/// Status of stamp
+typedef enum {
+    PM_SUBTRACTION_STAMP_INIT,          ///< Initial state
+    PM_SUBTRACTION_STAMP_FOUND,         ///< Found a suitable source for this stamp
+    PM_SUBTRACTION_STAMP_CALCULATE,     ///< Calculate matrix and vector values for this stamp
+    PM_SUBTRACTION_STAMP_USED,          ///< Use this stamp
+    PM_SUBTRACTION_STAMP_REJECTED,      ///< This stamp has been rejected
+    PM_SUBTRACTION_STAMP_NONE           ///< No stamp in this region
+} pmSubtractionStampStatus;
+
+/// A list of stamps
+typedef struct {
+    long num;                           ///< Number of stamps
+    psArray *stamps;                    ///< The stamps
+    psArray *regions;                   ///< Regions for each stamp
+    psArray *x, *y;                     ///< Coordinates for possible stamps (or NULL)
+    psArray *flux;                      ///< Fluxes for possible stamps (or NULL)
+    int footprint;                      ///< Half-size of stamps
+} pmSubtractionStampList;
+
+/// Allocate a list of stamps
+pmSubtractionStampList *pmSubtractionStampListAlloc(int numCols, // Number of columns in image
+                                                    int numRows, // Number of rows in image
+                                                    const psRegion *region, // Region for stamps, or NULL
+                                                    int footprint, // Half-size of stamps
+                                                    float spacing // Rough average spacing between stamps
+    );
+
+/// Assertion for stamp list to be valid
+#define PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(LIST, RETURNVALUE) { \
+    PS_ASSERT_PTR_NON_NULL(LIST, RETURNVALUE); \
+    PS_ASSERT_ARRAY_NON_NULL((LIST)->stamps, RETURNVALUE); \
+    PS_ASSERT_ARRAY_NON_NULL((LIST)->regions, RETURNVALUE); \
+    PS_ASSERT_INT_POSITIVE((LIST)->num, RETURNVALUE); \
+    PS_ASSERT_ARRAY_SIZE((LIST)->stamps, (LIST)->num, RETURNVALUE); \
+    PS_ASSERT_ARRAY_SIZE((LIST)->regions, (LIST)->num, RETURNVALUE); \
+    PS_ASSERT_INT_NONNEGATIVE((LIST)->footprint, RETURNVALUE); \
+    if ((LIST)->x || (LIST)->y || (LIST)->flux) { \
+        PS_ASSERT_ARRAY_NON_NULL((LIST)->x, RETURNVALUE); \
+        PS_ASSERT_ARRAY_NON_NULL((LIST)->y, RETURNVALUE); \
+        PS_ASSERT_ARRAY_NON_NULL((LIST)->flux, RETURNVALUE); \
+        PS_ASSERT_ARRAY_SIZE((LIST)->x, (LIST)->num, RETURNVALUE); \
+        PS_ASSERT_ARRAY_SIZE((LIST)->y, (LIST)->num, RETURNVALUE); \
+        PS_ASSERT_ARRAY_SIZE((LIST)->flux, (LIST)->num, RETURNVALUE); \
+    } \
+}
+
+/// A stamp for image subtraction
+typedef struct {
+    float x, y;                         ///< Position
+    float flux;                         ///< Flux
+    float xNorm, yNorm;                 ///< Normalised position
+    psKernel *image1;                   ///< Reference image postage stamp
+    psKernel *image2;                   ///< Input image postage stamp
+    psKernel *weight;                   ///< Weight image postage stamp, or NULL
+    psArray *convolutions1;             ///< Convolutions of image 1 for each kernel component, or NULL
+    psArray *convolutions2;             ///< Convolutions of image 2 for each kernel component, or NULL
+    psImage *matrix1, *matrix2;         ///< Least-squares matrices for each image, or NULL
+    psImage *matrixX;                   ///< Cross-matrix (for mode DUAL), or NULL
+    psVector *vector1, *vector2;        ///< Least-squares vectors for each image, or NULL
+    pmSubtractionStampStatus status;    ///< Status of stamp
+} pmSubtractionStamp;
+
+/// Allocate a stamp
+pmSubtractionStamp *pmSubtractionStampAlloc(void);
+
+/// Find stamps on an image
+pmSubtractionStampList *pmSubtractionStampsFind(pmSubtractionStampList *stamps, ///< Output stamps, or NULL
+                                                const psImage *image, ///< Image for which to find stamps
+                                                const psImage *mask, ///< Mask, or NULL
+                                                const psRegion *region, ///< Region to search, or NULL
+                                                float threshold, ///< Threshold for stamps in the image
+                                                int footprint, ///< Half-size for stamps
+                                                float spacing, ///< Rough spacing for stamps
+                                                pmSubtractionMode mode ///< Mode for subtraction
+    );
+
+/// Set stamps based on a list of x,y
+pmSubtractionStampList *pmSubtractionStampsSet(const psVector *x, ///< x coordinates for each stamp
+                                               const psVector *y, ///< y coordinates for each stamp
+                                               const psVector *flux, ///< Flux for each stamp, or NULL
+                                               const psImage *image, ///< Image for flux of stamp
+                                               const psImage *mask, ///< Mask, or NULL
+                                               const psRegion *region, ///< Region to search, or NULL
+                                               int footprint, ///< Half-size for stamps
+                                               float spacing, ///< Rough spacing for stamps
+                                               pmSubtractionMode mode ///< Mode for subtraction
+    );
+
+/// Set stamps based on a list of sources
+pmSubtractionStampList *pmSubtractionStampsSetFromSources(
+    const psArray *sources,             ///< Sources for each stamp
+    const psImage *subMask,             ///< Mask, or NULL
+    const psRegion *region,             ///< Region to search, or NULL
+    int footprint,                      ///< Half-size for stamps
+    float spacing,                      ///< Rough spacing for stamps
+    pmSubtractionMode mode              ///< Mode for subtraction
+    );
+
+/// Set stamps based on values in a file
+pmSubtractionStampList *pmSubtractionStampsSetFromFile(
+    const char *filename,               ///< Filename of file containing x,y (or x,y,flux) on each line
+    const psImage *image,               ///< Image for flux of stamp
+    const psImage *subMask,             ///< Mask, or NULL
+    const psRegion *region,             ///< Region to search, or NULL
+    int footprint,                      ///< Half-size for stamps
+    float spacing,                      ///< Rough spacing for stamps
+    pmSubtractionMode mode              ///< Mode for subtraction
+    );
+
+/// Extract stamps from the images
+bool pmSubtractionStampsExtract(pmSubtractionStampList *stamps, ///< Stamps
+                                psImage *image1, ///< Reference image
+                                psImage *image2, ///< Input image (or NULL)
+                                psImage *weight, ///< Weight (variance) map
+                                int kernelSize ///< Kernel half-size
+    );
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/mainpage.dox
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/mainpage.dox	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/mainpage.dox	(revision 22158)
@@ -0,0 +1,127 @@
+/** @mainpage psModules Image Processing Library
+
+
+@section intro Introduction
+This library contains the Pan-STARRS Image Processing Pipeline (IPP) modules (psModules). These modules
+use the functionality of the Pan-STARRS Library (psLib) to perform more complex tasks associated with image
+processing. Modules were constructed to support each of the required processing stages and are listed according
+to the particular processing stage for which they will primarily be used. To preserve namespace, globally-visible
+structures and functions are prefixed with pm, an abbreviation for Pan-STARRS Modules.
+
+The capabilities provided by psModules are grouped into the following areas which are
+also reflected in the file system directory structure:
+ - Configuration
+ - Astrometry, Focal Plane
+ - Photometry
+ - Basic Image Detrending
+ - Object Detection and Classification
+ - Image Combination
+ - Image Subtraction
+
+The installed code for psModules consists of header files and a binary library.
+
+@section extinstall Required external Libraries
+
+Before building psLib from source, several external software libraries must
+be installed. These include:
+ - Pan-STARRS Library (psLib)
+     - Available from the Maui High Performance Computiong Center (MHPCC) at https://mhpcc.pan-starrs.org/code/releases
+     - Compatibility tested with rel5
+     - Note, psLib itself has many external library dependencies.
+ - Doxygen Documentation System
+     - Only needed if code documentation is to be made
+     - Available at http://www.doxygen.org
+     - Compatibility tested with version 1.3.6
+     - The optional companion package, GraphViz (a.k.a., the 'dot' command), is recommended to enable header-file dependency diagrams
+
+We recommend using the particular versions listed as compatibility tested, as
+that is the only versions of the external libraries tested to work well with psLib
+and psModules.  Though it is quite possible that later versions of the libraries
+listed will also work, care must be taken when upgrading these libraries to verify
+that its functionality is compatible with the tested version.
+
+@section install How to Build from Source
+
+Tested versions of psModules are put into a tar file and can be downloaded from:
+
+https://mhpcc.pan-starrs.org/code/releases
+
+If one has a login account on mhpcc.pan-starrs.org, direct CVS access is
+possible.  Example of the commands required for direct CVS retrieval are
+as follows:
+<pre>
+$ cvs -d:ext:USERNAME@mhpcc.pan-starrs.org:/data/panstarrs/cvsroot co -r RELEASEBRANCH psModule
+</pre>
+where:
+  - USERNAME is your login name on the server
+  - RELEASEBRANCH is the desired release branch, e.g. rel7.
+
+
+@section build How to Build and Test the psModules Library.
+
+The psModules library and associated tests are made via the GNU autoconf/automake system.
+
+The source should build using the configure script in the psModules directory.  The
+recommended steps are:
+<pre>
+$ cd psmodules
+$ ./configure
+$ make
+$ make check
+$ make install
+</pre>
+<i>Unless otherwise specified, the library is installed with PREFIX of the current directory.</i>
+
+If the code was retrieved from CVS, you will need to substitute 'autogen.sh' for 'configure' in
+above example.
+
+Other configuration options, such as location of external libraries, are also available.
+To get a list of options, type the following in the top psModules directory.
+<pre>
+$ configure --help
+</pre>
+A likely option needed is '--with-pslib-config', which specifies the location of
+the configuration script for psLib.  By default, configure searches for it using PATH, but that
+is not always sufficient.
+
+@section install How to Install
+
+To install the library using the prefix given in the configure step, execute in
+the top build directory:
+<pre>
+$ make install
+</pre>
+
+
+@section usage Building and Linking your code to the psModules library
+
+To assist the use of the library with your own code, a configuration tool is part
+of the psModules library package.  This tool, psmodules-config, is installed in the BIN
+directory, according to the options given to the configure script.
+
+The required CFLAG options for the compiler stage of code that uses psModules can be
+obtained via 'psmodules-config --cflags'.  This outputs the cc options that supplies
+include path(s) required to find the psModules headers.
+
+The required linking options, can be obtained via 'psmodules-config --libs'.  This
+outputs the ld options that supplies the library paths and files required to
+link to the psModules library.
+
+Note: psmodules-config usage above refers to the install locations of the library.  
+
+@section doc How to Create Code Documentation
+
+Both HTML and man page documentation may be generated from the inline
+documentation embedded in the code using the following commands:
+<pre>
+$ cd psmodules
+$ make docs
+</pre>
+<i>This places documentation in PREFIX/docs.</i>
+
+Also, a prebuilt set of code documentation for both the releases and last
+CVS snapshot can be found at:
+
+https://mhpcc.pan-starrs.org/docs/
+
+*/
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/.cvsignore	(revision 22158)
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/Makefile.am	(revision 22158)
@@ -0,0 +1,81 @@
+noinst_LTLIBRARIES = libpsmodulesobjects.la
+
+libpsmodulesobjects_la_CPPFLAGS = $(SRCINC) $(PSMODULES_CFLAGS) -I../pslib/
+libpsmodulesobjects_la_LDFLAGS  = -release $(PACKAGE_VERSION)
+libpsmodulesobjects_la_SOURCES  = \
+     pmDetections.c \
+     pmSpan.c \
+     pmFootprint.c \
+     pmFootprintArrayGrow.c \
+     pmFootprintArraysMerge.c \
+     pmFootprintAssignPeaks.c \
+     pmFootprintFind.c \
+     pmFootprintFindAtPoint.c \
+     pmFootprintIDs.c \
+     pmPeaks.c \
+     pmMoments.c \
+     pmModel.c \
+     pmModelClass.c \
+     pmModelUtils.c \
+     pmSource.c \
+     pmSourceExtendedPars.c \
+     pmSourceUtils.c \
+     pmSourceSky.c \
+     pmSourceContour.c \
+     pmSourceFitModel.c \
+     pmSourceFitSet.c \
+     pmSourcePhotometry.c \
+     pmSourceIO.c \
+     pmSourceIO_RAW.c \
+     pmSourceIO_OBJ.c \
+     pmSourceIO_SX.c \
+     pmSourceIO_CMP.c \
+     pmSourceIO_SMPDATA.c \
+     pmSourceIO_PS1_DEV_0.c \
+     pmSourceIO_PS1_DEV_1.c \
+     pmSourcePlots.c \
+     pmSourcePlotPSFModel.c \
+     pmSourcePlotMoments.c \
+     pmSourcePlotApResid.c \
+     pmResiduals.c \
+     pmPSF.c \
+     pmPSF_IO.c \
+     pmPSFtry.c \
+     pmTrend2D.c \
+     pmGrowthCurve.c
+
+EXTRA_DIST = \
+     models/pmModel_GAUSS.c \
+     models/pmModel_PGAUSS.c \
+     models/pmModel_QGAUSS.c \
+     models/pmModel_SGAUSS.c \
+     models/pmModel_RGAUSS.c \
+     models/pmModel_SERSIC.c
+
+pkginclude_HEADERS = \
+     pmDetections.h \
+     pmSpan.h \
+     pmFootprint.h \
+     pmPeaks.h \
+     pmMoments.h \
+     pmModel.h \
+     pmModelClass.h \
+     pmModelUtils.h \
+     pmSource.h \
+     pmSourceExtendedPars.h \
+     pmSourceUtils.h \
+     pmSourceSky.h \
+     pmSourceContour.h \
+     pmSourceFitModel.h \
+     pmSourceFitSet.h \
+     pmSourcePhotometry.h \
+     pmSourceIO.h \
+     pmSourcePlots.h \
+     pmResiduals.h \
+     pmPSF.h \
+     pmPSF_IO.h \
+     pmPSFtry.h \
+     pmTrend2D.h \
+     pmGrowthCurve.h
+
+CLEANFILES = *~
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_GAUSS.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_GAUSS.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_GAUSS.c	(revision 22158)
@@ -0,0 +1,396 @@
+/******************************************************************************
+ * this file defines the GAUSS source shape model.  Note that these model functions are loaded
+ * by pmModelGroup.c using 'include', and thus need no 'include' statements of their own.  The
+ * models use a psVector to represent the set of parameters, with the sequence used to specify
+ * the meaning of the parameter.  The meaning of the parameters may thus vary depending on the
+ * specifics of the model.  All models which are used a PSF representations share a few
+ * parameters, for which # define names are listed in pmModel.h:
+
+   pure Gaussian:
+   exp(-z)
+
+ * PM_PAR_SKY 0   - local sky : note that this is unused and may be dropped in the future
+ * PM_PAR_I0 1    - central intensity
+ * PM_PAR_XPOS 2  - X center of object
+ * PM_PAR_YPOS 3  - Y center of object
+ * PM_PAR_SXX 4   - X^2 term of elliptical contour (sqrt(2) * SigmaX)
+ * PM_PAR_SYY 5   - Y^2 term of elliptical contour (sqrt(2) * SigmaY)
+ * PM_PAR_SXY 6   - X*Y term of elliptical contour
+ *****************************************************************************/
+
+# define PM_MODEL_FUNC            pmModelFunc_GAUSS
+# define PM_MODEL_FLUX            pmModelFlux_GAUSS
+# define PM_MODEL_GUESS           pmModelGuess_GAUSS
+# define PM_MODEL_LIMITS          pmModelLimits_GAUSS
+# define PM_MODEL_RADIUS          pmModelRadius_GAUSS
+# define PM_MODEL_FROM_PSF        pmModelFromPSF_GAUSS
+# define PM_MODEL_PARAMS_FROM_PSF pmModelParamsFromPSF_GAUSS
+# define PM_MODEL_FIT_STATUS      pmModelFitStatus_GAUSS
+
+// the model is a function of the pixel coordinate (pixcoord[0,1] = x,y)
+psF32 PM_MODEL_FUNC(psVector *deriv,
+                    const psVector *params,
+                    const psVector *pixcoord)
+{
+    psF32 *PAR = params->data.F32;
+
+    psF32 X  = pixcoord->data.F32[0] - PAR[PM_PAR_XPOS];
+    psF32 Y  = pixcoord->data.F32[1] - PAR[PM_PAR_YPOS];
+    psF32 px = X / PAR[PM_PAR_SXX];
+    psF32 py = Y / PAR[PM_PAR_SYY];
+    psF32 z  = PS_SQR(px) + PS_SQR(py) + PAR[PM_PAR_SXY]*X*Y;
+    assert (z >= 0.0);
+
+    psF32 r  = exp(-z);
+    psF32 q  = PAR[PM_PAR_I0]*r;
+    psF32 f  = q + PAR[PM_PAR_SKY];
+
+    if (deriv != NULL) {
+        psF32 *dPAR = deriv->data.F32;
+        dPAR[PM_PAR_SKY]  = +1.0;
+        dPAR[PM_PAR_I0]   = +r;
+        dPAR[PM_PAR_XPOS] = q*(2*px/PAR[PM_PAR_SXX] + Y*PAR[PM_PAR_SXY]);
+        dPAR[PM_PAR_YPOS] = q*(2*py/PAR[PM_PAR_SYY] + X*PAR[PM_PAR_SXY]);
+        // the extra factor of 2 below is needed to avoid excessive swings
+        dPAR[PM_PAR_SXX]  = +4.0*q*px*px/PAR[PM_PAR_SXX];
+        dPAR[PM_PAR_SYY]  = +4.0*q*py*py/PAR[PM_PAR_SYY];
+        dPAR[PM_PAR_SXY]  = -q*X*Y;
+    }
+    return(f);
+}
+
+// define the parameter limits
+// AR_MAX is the maximum allowed axis ratio
+// AR_RATIO is ((1-R)/(1+R))^2 where R = AR_MAX^(-2)
+# define AR_MAX 20.0
+# define AR_RATIO 0.99
+
+bool PM_MODEL_LIMITS (psMinConstraintMode mode, int nParam, float *params, float *beta)
+{
+    float beta_lim = 0, params_min = 0, params_max = 0;
+    float f1 = 0, f2 = 0, q1 = 0, q2 = 0;
+
+    // we need to calculate the limits for SXY specially
+    if (nParam == PM_PAR_SXY) {
+        f1 = 1.0 / PS_SQR(params[PM_PAR_SYY]) + 1.0 / PS_SQR(params[PM_PAR_SXX]);
+        f2 = 1.0 / PS_SQR(params[PM_PAR_SYY]) - 1.0 / PS_SQR(params[PM_PAR_SXX]);
+        q1 = PS_SQR(f1)*AR_RATIO - PS_SQR(f2);
+        q1 = PS_MAX (0.0, q1);
+        // if q1 < 0.0, f2 ~ f1, we have a very large axis ratio near 45deg..  Saturate at that
+        // angle and let f2,f1 fight it out
+        q2  = 0.5*sqrt (q1);
+    }
+
+    switch (mode) {
+    case PS_MINIMIZE_BETA_LIMIT:
+        switch (nParam) {
+        case PM_PAR_SKY:
+            beta_lim = 1000;
+            break;
+        case PM_PAR_I0:
+            beta_lim = 3e6;
+            break;
+        case PM_PAR_XPOS:
+            beta_lim = 5;
+            break;
+        case PM_PAR_YPOS:
+            beta_lim = 5;
+            break;
+        case PM_PAR_SXX:
+            beta_lim = 2.0;
+            break;
+        case PM_PAR_SYY:
+            beta_lim = 2.0;
+            break;
+        case PM_PAR_SXY:
+            beta_lim =  0.5*q2;
+            break;
+        default:
+            psAbort("invalid parameter %d for beta test", nParam);
+        }
+        if (fabs(beta[nParam]) > fabs(beta_lim)) {
+            beta[nParam] = (beta[nParam] > 0) ? fabs(beta_lim) : -fabs(beta_lim);
+            psTrace ("psModules.objects", 5, "|beta[nParam==%d]| > |beta_lim|; %g v. %g",
+                     nParam, beta[nParam], beta_lim);
+            return false;
+        }
+        return true;
+    case PS_MINIMIZE_PARAM_MIN:
+        switch (nParam) {
+        case PM_PAR_SKY:
+            params_min = -1000;
+            break;
+        case PM_PAR_I0:
+            params_min =   0.01;
+            break;
+        case PM_PAR_XPOS:
+            params_min =  -100;
+            break;
+        case PM_PAR_YPOS:
+            params_min =  -100;
+            break;
+        case PM_PAR_SXX:
+            params_min =   0.5;
+            break;
+        case PM_PAR_SYY:
+            params_min =   0.5;
+            break;
+        case PM_PAR_SXY:
+            params_min =   -q2;
+            break;
+        default:
+            psAbort("invalid parameter %d for param min test", nParam);
+        }
+        if (params[nParam] < params_min) {
+            params[nParam] = params_min;
+            psTrace ("psModules.objects", 5, "params[nParam==%d] < params_min; %g v. %g",
+                     nParam, params[nParam], params_min);
+            return false;
+        }
+        return true;
+    case PS_MINIMIZE_PARAM_MAX:
+        switch (nParam) {
+        case PM_PAR_SKY:
+            params_max =   1e5;
+            break;
+        case PM_PAR_I0:
+            params_max =   1e8;
+            break;
+        case PM_PAR_XPOS:
+            params_max =   1e4;
+            break;
+        case PM_PAR_YPOS:
+            params_max =   1e4;
+            break;
+        case PM_PAR_SXX:
+            params_max =   100;
+            break;
+        case PM_PAR_SYY:
+            params_max =   100;
+            break;
+        case PM_PAR_SXY:
+            params_max =   +q2;
+            break;
+        default:
+            psAbort("invalid parameter %d for param max test", nParam);
+        }
+        if (params[nParam] > params_max) {
+            params[nParam] = params_max;
+            psTrace ("psModules.objects", 5, "params[nParam==%d] > params_max; %g v. %g",
+                     nParam, params[nParam], params_max);
+            return false;
+        }
+        return true;
+    default:
+        psAbort("invalid choice for limits");
+    }
+    psAbort("should not reach here");
+    return false;
+}
+
+// make an initial guess for parameters
+bool PM_MODEL_GUESS (pmModel *model, pmSource *source)
+{
+    pmMoments *moments = source->moments;
+    psF32     *PAR  = model->params->data.F32;
+
+    psEllipseMoments emoments;
+    emoments.x2 = moments->Sx;
+    emoments.y2 = moments->Sy;
+    emoments.xy = moments->Sxy;
+
+    // force the axis ratio to be < 20.0
+    psEllipseAxes axes = psEllipseMomentsToAxes (emoments, 20.0);
+    psEllipseShape shape = psEllipseAxesToShape (axes);
+
+    PAR[PM_PAR_SKY]  = moments->Sky;
+    PAR[PM_PAR_I0]   = moments->Peak - moments->Sky;
+    PAR[PM_PAR_XPOS] = moments->x;
+    PAR[PM_PAR_YPOS] = moments->y;
+    PAR[PM_PAR_SXX] = PS_MAX(0.5, M_SQRT2*shape.sx);
+    PAR[PM_PAR_SYY] = PS_MAX(0.5, M_SQRT2*shape.sy);
+    PAR[PM_PAR_SXY] = shape.sxy;
+    return(true);
+}
+
+psF64 PM_MODEL_FLUX (const psVector *params)
+{
+
+    psEllipseShape shape;
+
+    psF32 *PAR = params->data.F32;
+
+    shape.sx  = PAR[PM_PAR_SXX] / M_SQRT2;
+    shape.sy  = PAR[PM_PAR_SYY] / M_SQRT2;
+    shape.sxy = PAR[PM_PAR_SXY];
+
+    // Area is equivalent to 2 pi sigma^2
+    // axes ratio < 20
+    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
+    psF64 Area = 2.0 * M_PI * axes.major * axes.minor;
+
+    psF64 Flux = params->data.F32[PM_PAR_I0] * Area;
+
+    return(Flux);
+}
+
+// return the radius which yields the requested flux
+// this function is never allowed to return <= 0
+psF64 PM_MODEL_RADIUS (const psVector *params, psF64 flux)
+{
+    psEllipseShape shape;
+
+    psF32 *PAR = params->data.F32;
+
+    if (flux <= 0)
+        return (1.0);
+    if (PAR[PM_PAR_I0] <= 0)
+        return (1.0);
+    if (flux >= PAR[PM_PAR_I0])
+        return (1.0);
+
+    shape.sx  = PAR[PM_PAR_SXX] / M_SQRT2;
+    shape.sy  = PAR[PM_PAR_SYY] / M_SQRT2;
+    shape.sxy = PAR[PM_PAR_SXY];
+
+    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
+    psF64 radius = axes.major * sqrt (2.0 * log(PAR[PM_PAR_I0] / flux));
+    return (radius);
+}
+
+// construct the PSF model from the FLT model and the psf
+bool PM_MODEL_FROM_PSF (pmModel *modelPSF, pmModel *modelFLT, const pmPSF *psf)
+{
+    psF32 *out = modelPSF->params->data.F32;
+    psF32 *in  = modelFLT->params->data.F32;
+
+    // we require these two parameters to exist
+    assert (psf->params->n > PM_PAR_YPOS);
+    assert (psf->params->n > PM_PAR_XPOS);
+
+    // supply the model-fitted parameters, or copy from the input
+    for (int i = 0; i < psf->params->n; i++) {
+        if (psf->params->data[i] == NULL) {
+            out[i] = in[i];
+        } else {
+            pmTrend2D *trend = psf->params->data[i];
+            out[i] = pmTrend2DEval(trend, in[PM_PAR_XPOS], in[PM_PAR_YPOS]);
+        }
+    }
+
+    // the OLD 2D model for SXY actually fitted SXY / (SXX^-2 + SYY^-2); correct here
+    // out[PM_PAR_SXY] = pmPSF_SXYtoModel (out);
+
+    // the 2D PSF model fits polarization terms (E0,E1,E2)
+    // convert to shape terms (SXX,SYY,SXY)
+    // XXX user-defined value for limit?
+    if (!pmPSF_FitToModel (out, 0.1)) {
+        psError(PM_ERR_PSF, false, "Failed to fit object at (r,c) = (%.1f,%.1f)",
+                in[PM_PAR_YPOS], in[PM_PAR_XPOS]);
+        return false;
+    }
+
+    // apply the model limits here: this truncates excessive extrapolation
+    // XXX do we need to do this still?  should we put in asserts to test?
+    for (int i = 0; i < psf->params->n; i++) {
+        // apply the limits to all components or just the psf-model parameters?
+        if (psf->params->data[i] == NULL)
+            continue;
+
+        bool status = true;
+        status &= PM_MODEL_LIMITS (PS_MINIMIZE_PARAM_MIN, i, out, NULL);
+        status &= PM_MODEL_LIMITS (PS_MINIMIZE_PARAM_MAX, i, out, NULL);
+        if (!status) {
+            psTrace ("psModules.objects", 5, "Hitting parameter limits at (r,c) = (%.1f, %.1f)",
+                     in[PM_PAR_XPOS], in[PM_PAR_YPOS]);
+            modelPSF->flags |= PM_MODEL_STATUS_LIMITS;
+        }
+    }
+    return(true);
+}
+
+// construct the PSF model from the FLT model and the psf
+// XXX is this sufficiently general do be a global function, not a pmModelClass function?
+bool PM_MODEL_PARAMS_FROM_PSF (pmModel *model, const pmPSF *psf, float Xo, float Yo, float Io)
+{
+    psF32 *PAR = model->params->data.F32;
+
+    // we require these two parameters to exist
+    assert (psf->params->n > PM_PAR_YPOS);
+    assert (psf->params->n > PM_PAR_XPOS);
+
+    PAR[PM_PAR_SKY]  = 0.0;
+    PAR[PM_PAR_I0]   = Io;
+    PAR[PM_PAR_XPOS] = Xo;
+    PAR[PM_PAR_YPOS] = Yo;
+
+    // supply the model-fitted parameters, or copy from the input
+    for (int i = 0; i < psf->params->n; i++) {
+        if (i == PM_PAR_SKY) continue;
+        if (i == PM_PAR_I0) continue;
+        if (i == PM_PAR_XPOS) continue;
+        if (i == PM_PAR_YPOS) continue;
+        pmTrend2D *trend = psf->params->data[i];
+        PAR[i] = pmTrend2DEval(trend, Xo, Yo);
+    }
+
+    // the 2D PSF model fits polarization terms (E0,E1,E2)
+    // convert to shape terms (SXX,SYY,SXY)
+    // XXX user-defined value for limit?
+    if (!pmPSF_FitToModel (PAR, 0.1)) {
+        psError(PM_ERR_PSF, false, "Failed to fit object at (r,c) = (%.1f,%.1f)", Xo, Yo);
+        return false;
+    }
+
+    // apply the model limits here: this truncates excessive extrapolation
+    // XXX do we need to do this still?  should we put in asserts to test?
+    for (int i = 0; i < psf->params->n; i++) {
+        // apply the limits to all components or just the psf-model parameters?
+        if (psf->params->data[i] == NULL)
+            continue;
+
+        bool status = true;
+        status &= PM_MODEL_LIMITS (PS_MINIMIZE_PARAM_MIN, i, PAR, NULL);
+        status &= PM_MODEL_LIMITS (PS_MINIMIZE_PARAM_MAX, i, PAR, NULL);
+        if (!status) {
+            psTrace ("psModules.objects", 5, "Hitting parameter limits at (r,c) = (%.1f, %.1f)", Xo, Yo);
+            model->flags |= PM_MODEL_STATUS_LIMITS;
+        }
+    }
+    return(true);
+}
+
+// check the status of the fitted model
+// this test is invalid if the parameters are derived
+// from the PSF model
+bool PM_MODEL_FIT_STATUS (pmModel *model)
+{
+    psF32 dP;
+    bool  status;
+
+    psF32 *PAR  = model->params->data.F32;
+    psF32 *dPAR = model->dparams->data.F32;
+
+    dP = 0;
+    dP += PS_SQR(dPAR[PM_PAR_SXX] / PAR[PM_PAR_SXX]);
+    dP += PS_SQR(dPAR[PM_PAR_SYY] / PAR[PM_PAR_SYY]);
+    dP = sqrt (dP);
+
+    status = true;
+    status &= (dP < 0.5);
+    status &= (PAR[PM_PAR_I0] > 0);
+    status &= ((dPAR[PM_PAR_I0]/PAR[PM_PAR_I0]) < 0.5);
+
+    if (status)
+        return true;
+    return false;
+}
+
+# undef PM_MODEL_FUNC
+# undef PM_MODEL_FLUX
+# undef PM_MODEL_GUESS
+# undef PM_MODEL_LIMITS
+# undef PM_MODEL_RADIUS
+# undef PM_MODEL_FROM_PSF
+# undef PM_MODEL_PARAMS_FROM_PSF
+# undef PM_MODEL_FIT_STATUS
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_PGAUSS.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_PGAUSS.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_PGAUSS.c	(revision 22158)
@@ -0,0 +1,443 @@
+/******************************************************************************
+ * this file defines the PGAUSS source shape model.  Note that these model functions are loaded
+ * by pmModelGroup.c using 'include', and thus need no 'include' statements of their own.  The
+ * models use a psVector to represent the set of parameters, with the sequence used to specify
+ * the meaning of the parameter.  The meaning of the parameters may thus vary depending on the
+ * specifics of the model.  All models which are used a PSF representations share a few
+ * parameters, for which # define names are listed in pmModel.h:
+
+   Gaussian taylor expansion
+   1 / (1 + z + z^2/2 + z^3/6)
+
+ * PM_PAR_SKY 0   - local sky : note that this is unused and may be dropped in the future
+ * PM_PAR_I0 1    - central intensity
+ * PM_PAR_XPOS 2  - X center of object
+ * PM_PAR_YPOS 3  - Y center of object
+ * PM_PAR_SXX 4   - X^2 term of elliptical contour (sqrt(2) * SigmaX)
+ * PM_PAR_SYY 5   - Y^2 term of elliptical contour (sqrt(2) * SigmaY)
+ * PM_PAR_SXY 6   - X*Y term of elliptical contour
+ *****************************************************************************/
+
+# define PM_MODEL_FUNC            pmModelFunc_PGAUSS
+# define PM_MODEL_FLUX            pmModelFlux_PGAUSS
+# define PM_MODEL_GUESS           pmModelGuess_PGAUSS
+# define PM_MODEL_LIMITS          pmModelLimits_PGAUSS
+# define PM_MODEL_RADIUS          pmModelRadius_PGAUSS
+# define PM_MODEL_FROM_PSF        pmModelFromPSF_PGAUSS
+# define PM_MODEL_PARAMS_FROM_PSF pmModelParamsFromPSF_PGAUSS
+# define PM_MODEL_FIT_STATUS      pmModelFitStatus_PGAUSS
+
+// the model is a function of the pixel coordinate (pixcoord[0,1] = x,y)
+psF32 PM_MODEL_FUNC(psVector *deriv,
+                    const psVector *params,
+                    const psVector *pixcoord)
+{
+    psF32 *PAR = params->data.F32;
+
+    psF32 X  = pixcoord->data.F32[0] - PAR[PM_PAR_XPOS];
+    psF32 Y  = pixcoord->data.F32[1] - PAR[PM_PAR_YPOS];
+    psF32 px = X / PAR[PM_PAR_SXX];
+    psF32 py = Y / PAR[PM_PAR_SYY];
+    psF32 z  = PS_SQR(px) + PS_SQR(py) + PAR[PM_PAR_SXY]*X*Y;
+    assert (z >= 0.0);
+
+    psF32 t  = 1 + z + z*z/2.0;
+    psF32 r  = 1.0 / (t + z*z*z/6.0); /* exp (-Z) */
+    psF32 f  = PAR[PM_PAR_I0]*r + PAR[PM_PAR_SKY];
+
+    if (deriv != NULL) {
+        psF32 *dPAR = deriv->data.F32;
+        psF32 q = PAR[PM_PAR_I0]*r*r*t;
+        dPAR[PM_PAR_SKY] = +1.0;
+        dPAR[PM_PAR_I0] = +r;
+        dPAR[PM_PAR_XPOS] = q*(2.0*px/PAR[PM_PAR_SXX] + Y*PAR[PM_PAR_SXY]);
+        dPAR[PM_PAR_YPOS] = q*(2.0*py/PAR[PM_PAR_SYY] + X*PAR[PM_PAR_SXY]);
+        // the extra factor of 2 below is needed to avoid excessive swings
+        dPAR[PM_PAR_SXX] =  +4.0*q*px*px/PAR[PM_PAR_SXX];
+        dPAR[PM_PAR_SYY] =  +4.0*q*py*py/PAR[PM_PAR_SYY];
+        dPAR[PM_PAR_SXY] = -q*X*Y;
+    }
+    return(f);
+}
+
+// define the parameter limits
+// AR_MAX is the maximum allowed axis ratio
+// AR_RATIO is ((1-R)/(1+R))^2 where R = AR_MAX^(-2)
+# define AR_MAX 20.0
+# define AR_RATIO 0.99
+
+bool PM_MODEL_LIMITS (psMinConstraintMode mode, int nParam, float *params, float *beta)
+{
+    float beta_lim = 0, params_min = 0, params_max = 0;
+    float f1 = 0, f2 = 0, q1 = 0, q2 = 0;
+
+    // we need to calculate the limits for SXY specially
+    if (nParam == PM_PAR_SXY) {
+        f1 = 1.0 / PS_SQR(params[PM_PAR_SYY]) + 1.0 / PS_SQR(params[PM_PAR_SXX]);
+        f2 = 1.0 / PS_SQR(params[PM_PAR_SYY]) - 1.0 / PS_SQR(params[PM_PAR_SXX]);
+        q1 = PS_SQR(f1)*AR_RATIO - PS_SQR(f2);
+        q1 = PS_MAX (0.0, q1);
+        // if q1 < 0.0, f2 ~ f1, we have a very large axis ratio near 45deg..  Saturate at that
+        // angle and let f2,f1 fight it out
+        q2  = 0.5*sqrt (q1);
+    }
+
+    switch (mode) {
+    case PS_MINIMIZE_BETA_LIMIT:
+        switch (nParam) {
+        case PM_PAR_SKY:
+            beta_lim = 1000;
+            break;
+        case PM_PAR_I0:
+            beta_lim = 3e6;
+            break;
+        case PM_PAR_XPOS:
+            beta_lim = 5;
+            break;
+        case PM_PAR_YPOS:
+            beta_lim = 5;
+            break;
+        case PM_PAR_SXX:
+            beta_lim = 2.0;
+            break;
+        case PM_PAR_SYY:
+            beta_lim = 2.0;
+            break;
+        case PM_PAR_SXY:
+            beta_lim =  0.5*q2;
+            break;
+        default:
+            psAbort("invalid parameter %d for beta test", nParam);
+        }
+        if (fabs(beta[nParam]) > fabs(beta_lim)) {
+            beta[nParam] = (beta[nParam] > 0) ? fabs(beta_lim) : -fabs(beta_lim);
+            psTrace ("psModules.objects", 5, "|beta[nParam==%d]| > |beta_lim|; %g v. %g",
+                     nParam, beta[nParam], beta_lim);
+            return false;
+        }
+        return true;
+    case PS_MINIMIZE_PARAM_MIN:
+        switch (nParam) {
+        case PM_PAR_SKY:
+            params_min = -1000;
+            break;
+        case PM_PAR_I0:
+            params_min =  0.01;
+            break;
+        case PM_PAR_XPOS:
+            params_min =  -100;
+            break;
+        case PM_PAR_YPOS:
+            params_min =  -100;
+            break;
+        case PM_PAR_SXX:
+            params_min =   0.5;
+            break;
+        case PM_PAR_SYY:
+            params_min =   0.5;
+            break;
+        case PM_PAR_SXY:
+            params_min =   -q2;
+            break;
+        default:
+            psAbort("invalid parameter %d for param min test", nParam);
+        }
+        if (params[nParam] < params_min) {
+            params[nParam] = params_min;
+            psTrace ("psModules.objects", 5, "params[nParam==%d] < params_min; %g v. %g",
+                     nParam, params[nParam], params_min);
+            return false;
+        }
+        return true;
+    case PS_MINIMIZE_PARAM_MAX:
+        switch (nParam) {
+        case PM_PAR_SKY:
+            params_max =   1e5;
+            break;
+        case PM_PAR_I0:
+            params_max =   1e8;
+            break;
+        case PM_PAR_XPOS:
+            params_max =   1e4;
+            break;
+        case PM_PAR_YPOS:
+            params_max =   1e4;
+            break;
+        case PM_PAR_SXX:
+            params_max =   100;
+            break;
+        case PM_PAR_SYY:
+            params_max =   100;
+            break;
+        case PM_PAR_SXY:
+            params_max =   +q2;
+            break;
+        default:
+            psAbort("invalid parameter %d for param max test", nParam);
+        }
+        if (params[nParam] > params_max) {
+            params[nParam] = params_max;
+            psTrace ("psModules.objects", 5, "params[nParam==%d] > params_max; %g v. %g",
+                     nParam, params[nParam], params_max);
+            return false;
+        }
+        return true;
+    default:
+        psAbort("invalid choice for limits");
+    }
+    psAbort("should not reach here");
+    return false;
+}
+
+// make an initial guess for parameters
+bool PM_MODEL_GUESS (pmModel *model, pmSource *source)
+{
+    pmMoments *moments = source->moments;
+    psF32     *PAR     = model->params->data.F32;
+
+    psEllipseMoments emoments;
+    emoments.x2 = moments->Sx;
+    emoments.y2 = moments->Sx;
+    emoments.xy = moments->Sxy;
+
+    psEllipseAxes axes = psEllipseMomentsToAxes (emoments, 20.0);
+    psEllipseShape shape = psEllipseAxesToShape (axes);
+
+    PAR[PM_PAR_SKY]  = moments->Sky;
+    PAR[PM_PAR_I0]   = moments->Peak - moments->Sky;
+    PAR[PM_PAR_XPOS] = moments->x; // XXX use peak->xf, peak->yf?
+    PAR[PM_PAR_YPOS] = moments->y;
+    PAR[PM_PAR_SXX] = PS_MAX(0.5, M_SQRT2*shape.sx);
+    PAR[PM_PAR_SYY] = PS_MAX(0.5, M_SQRT2*shape.sy);
+    PAR[PM_PAR_SXY] = shape.sxy;
+    return(true);
+}
+
+psF64 PM_MODEL_FLUX(const psVector *params)
+{
+    float norm, z;
+    psEllipseShape shape;
+
+    psF32 *PAR = params->data.F32;
+
+    shape.sx  = PAR[PM_PAR_SXX] / M_SQRT2;
+    shape.sy  = PAR[PM_PAR_SYY] / M_SQRT2;
+    shape.sxy = PAR[PM_PAR_SXY];
+
+    // Area is equivalent to 2 pi sigma^2
+    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
+    psF64 Area = 2.0 * M_PI * axes.major * axes.minor;
+
+    // the area needs to be multiplied by the integral of f(z)
+    norm = 0.0;
+
+    # define DZ 0.25
+
+    float f0 = 1.0;
+    float f1, f2;
+    for (z = DZ; z < 50; z += DZ) {
+        f1 = 1.0 / (1 + z + z*z/2.0 + z*z*z/6.0);
+        z += DZ;
+        f2 = 1.0 / (1 + z + z*z/2.0 + z*z*z/6.0);
+        norm += f0 + 4*f1 + f2;
+        f0 = f2;
+    }
+    norm *= DZ / 3.0;
+
+    psF64 Flux = PAR[PM_PAR_I0] * Area * norm;
+
+    return(Flux);
+}
+
+// define this function so it never returns Inf or NaN
+// return the radius which yields the requested flux
+psF64 PM_MODEL_RADIUS (const psVector *params, psF64 flux)
+{
+    psF64 z, f;
+    int Nstep = 0;
+    psEllipseShape shape;
+
+    psF32 *PAR = params->data.F32;
+
+    if (flux <= 0)
+        return (1.0);
+    if (PAR[PM_PAR_I0] <= 0)
+        return (1.0);
+    if (flux >= PAR[PM_PAR_I0])
+        return (1.0);
+
+    shape.sx  = PAR[PM_PAR_SXX] / M_SQRT2;
+    shape.sy  = PAR[PM_PAR_SYY] / M_SQRT2;
+    shape.sxy = PAR[PM_PAR_SXY];
+
+    // this estimates the radius assuming f(z) is roughly exp(-z)
+    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
+    psF64 sigma = axes.major;
+
+    psF64 limit = flux / PAR[PM_PAR_I0];
+
+    // use the fact that f is monotonically decreasing
+    z = 0;
+    Nstep = 0;
+
+    // choose a z value guaranteed to be beyond our limit
+    float z0 = pow((1.0 / limit), (1.0 / 3.0));
+    float z1 = (1.0 / limit);
+    z1 = PS_MAX (z0, z1);
+    z0 = 0.0;
+
+    // perform a type of bisection to find the value
+    float f0 = 1.0 / (1 + z0 + z0*z0/2.0 + z0*z0*z0/6.0);
+    float f1 = 1.0 / (1 + z1 + z1*z1/2.0 + z1*z1*z1/6.0);
+    while ((Nstep < 10) && (fabs(z1 - z0) > 0.5)) {
+        z = 0.5*(z0 + z1);
+        f = 1.0 / (1 + z + z*z/2.0 + z*z*z/6.0);
+        if (f > limit) {
+            z0 = z;
+            f0 = f;
+        } else {
+            z1 = z;
+            f1 = f;
+        }
+        Nstep ++;
+    }
+    psF64 radius = sigma * sqrt (2.0 * z);
+
+    // psF64 radius = axes.major * sqrt (2.0 * log(PAR[PM_PAR_I0] / flux));
+
+    if (isnan(radius))
+        psAbort("error in code: radius is NaN");
+    if (radius < 0)
+        psAbort("error in code: radius is negative");
+
+    return (radius);
+}
+
+bool PM_MODEL_FROM_PSF (pmModel *modelPSF, pmModel *modelFLT, const pmPSF *psf)
+{
+    psF32 *out = modelPSF->params->data.F32;
+    psF32 *in  = modelFLT->params->data.F32;
+
+    // we require these two parameters to exist
+    assert (psf->params->n > PM_PAR_YPOS);
+    assert (psf->params->n > PM_PAR_XPOS);
+
+    for (int i = 0; i < psf->params->n; i++) {
+        if (psf->params->data[i] == NULL) {
+            out[i] = in[i];
+        } else {
+            pmTrend2D *trend = psf->params->data[i];
+            out[i] = pmTrend2DEval(trend, in[PM_PAR_XPOS], in[PM_PAR_YPOS]);
+        }
+    }
+
+    // the OLD 2D model for SXY actually fitted SXY / (SXX^-2 + SYY^-2); correct here
+    // out[PM_PAR_SXY] = pmPSF_SXYtoModel (out);
+
+    // the 2D PSF model fits polarization terms (E0,E1,E2)
+    // convert to shape terms (SXX,SYY,SXY)
+    if (!pmPSF_FitToModel (out, 0.1)) {
+        psError(PM_ERR_PSF, false, "Failed to fit object at (r,c) = (%.1f,%.1f)",
+                in[PM_PAR_YPOS], in[PM_PAR_XPOS]);
+        return false;
+    }
+
+    // apply the model limits here: this truncates excessive extrapolation
+    // XXX do we need to do this still?  should we put in asserts to test?
+    for (int i = 0; i < psf->params->n; i++) {
+        // apply the limits to all components or just the psf-model parameters?
+        if (psf->params->data[i] == NULL)
+            continue;
+
+        bool status = true;
+        status &= PM_MODEL_LIMITS (PS_MINIMIZE_PARAM_MIN, i, out, NULL);
+        status &= PM_MODEL_LIMITS (PS_MINIMIZE_PARAM_MAX, i, out, NULL);
+        if (!status) {
+            psTrace ("psModules.objects", 5, "Hitting parameter limits at (r,c) = (%.1f, %.1f)",
+                     in[PM_PAR_XPOS], in[PM_PAR_YPOS]);
+            modelPSF->flags |= PM_MODEL_STATUS_LIMITS;
+        }
+    }
+    return(true);
+}
+
+// construct the PSF model from the FLT model and the psf
+// XXX is this sufficiently general do be a global function, not a pmModelClass function?
+bool PM_MODEL_PARAMS_FROM_PSF (pmModel *model, const pmPSF *psf, float Xo, float Yo, float Io)
+{
+    psF32 *PAR = model->params->data.F32;
+
+    // we require these two parameters to exist
+    assert (psf->params->n > PM_PAR_YPOS);
+    assert (psf->params->n > PM_PAR_XPOS);
+
+    PAR[PM_PAR_SKY]  = 0.0;
+    PAR[PM_PAR_I0]   = Io;
+    PAR[PM_PAR_XPOS] = Xo;
+    PAR[PM_PAR_YPOS] = Yo;
+
+    // supply the model-fitted parameters, or copy from the input
+    for (int i = 0; i < psf->params->n; i++) {
+        if (i == PM_PAR_SKY) continue;
+        if (i == PM_PAR_I0) continue;
+        if (i == PM_PAR_XPOS) continue;
+        if (i == PM_PAR_YPOS) continue;
+        pmTrend2D *trend = psf->params->data[i];
+        PAR[i] = pmTrend2DEval(trend, Xo, Yo);
+    }
+
+    // the 2D PSF model fits polarization terms (E0,E1,E2)
+    // convert to shape terms (SXX,SYY,SXY)
+    // XXX user-defined value for limit?
+    if (!pmPSF_FitToModel (PAR, 0.1)) {
+        psError(PM_ERR_PSF, false, "Failed to fit object at (r,c) = (%.1f,%.1f)", Xo, Yo);
+        return false;
+    }
+
+    // apply the model limits here: this truncates excessive extrapolation
+    // XXX do we need to do this still?  should we put in asserts to test?
+    for (int i = 0; i < psf->params->n; i++) {
+        // apply the limits to all components or just the psf-model parameters?
+        if (psf->params->data[i] == NULL)
+            continue;
+
+        bool status = true;
+        status &= PM_MODEL_LIMITS (PS_MINIMIZE_PARAM_MIN, i, PAR, NULL);
+        status &= PM_MODEL_LIMITS (PS_MINIMIZE_PARAM_MAX, i, PAR, NULL);
+        if (!status) {
+            psTrace ("psModules.objects", 5, "Hitting parameter limits at (r,c) = (%.1f, %.1f)", Xo, Yo);
+            model->flags |= PM_MODEL_STATUS_LIMITS;
+        }
+    }
+    return(true);
+}
+
+bool PM_MODEL_FIT_STATUS (pmModel *model)
+{
+    psF32 dP;
+    bool  status;
+
+    psF32 *PAR  = model->params->data.F32;
+    psF32 *dPAR = model->dparams->data.F32;
+
+    dP = 0;
+    dP += PS_SQR(dPAR[PM_PAR_SXX] / PAR[PM_PAR_SXX]);
+    dP += PS_SQR(dPAR[PM_PAR_SYY] / PAR[PM_PAR_SYY]);
+    dP = sqrt (dP);
+
+    status = true;
+    status &= (dP < 0.5);
+    status &= (PAR[PM_PAR_I0] > 0);
+    status &= ((dPAR[PM_PAR_I0]/PAR[PM_PAR_I0]) < 0.5);
+
+    return status;
+}
+
+# undef PM_MODEL_FUNC
+# undef PM_MODEL_FLUX
+# undef PM_MODEL_GUESS
+# undef PM_MODEL_LIMITS
+# undef PM_MODEL_RADIUS
+# undef PM_MODEL_FROM_PSF
+# undef PM_MODEL_PARAMS_FROM_PSF
+# undef PM_MODEL_FIT_STATUS
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_QGAUSS.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_QGAUSS.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_QGAUSS.c	(revision 22158)
@@ -0,0 +1,474 @@
+/******************************************************************************
+ * this file defines the QGAUSS source shape model (XXX need a better name!).  Note that these
+ * model functions are loaded by pmModelGroup.c using 'include', and thus need no 'include'
+ * statements of their own.  The models use a psVector to represent the set of parameters, with
+ * the sequence used to specify the meaning of the parameter.  The meaning of the parameters
+ * may thus vary depending on the specifics of the model.  All models which are used a PSF
+ * representations share a few parameters, for which # define names are listed in pmModel.h:
+
+   power-law with fitted linear term
+   1 / (1 + kz + z^2.25)
+
+   * PM_PAR_SKY 0   - local sky : note that this is unused and may be dropped in the future
+   * PM_PAR_I0 1    - central intensity
+   * PM_PAR_XPOS 2  - X center of object
+   * PM_PAR_YPOS 3  - Y center of object
+   * PM_PAR_SXX 4   - X^2 term of elliptical contour (sqrt(2) / SigmaX)
+   * PM_PAR_SYY 5   - Y^2 term of elliptical contour (sqrt(2) / SigmaY)
+   * PM_PAR_SXY 6   - X*Y term of elliptical contour
+   * PM_PAR_7   7   - amplitude of the linear component (k)
+   *****************************************************************************/
+
+# define PM_MODEL_FUNC            pmModelFunc_QGAUSS
+# define PM_MODEL_FLUX            pmModelFlux_QGAUSS
+# define PM_MODEL_GUESS           pmModelGuess_QGAUSS
+# define PM_MODEL_LIMITS          pmModelLimits_QGAUSS
+# define PM_MODEL_RADIUS          pmModelRadius_QGAUSS
+# define PM_MODEL_FROM_PSF        pmModelFromPSF_QGAUSS
+# define PM_MODEL_PARAMS_FROM_PSF pmModelParamsFromPSF_QGAUSS
+# define PM_MODEL_FIT_STATUS      pmModelFitStatus_QGAUSS
+
+psF32 PM_MODEL_FUNC (psVector *deriv,
+                     const psVector *params,
+                     const psVector *pixcoord)
+{
+    psF32 *PAR = params->data.F32;
+
+    psF32 X  = pixcoord->data.F32[0] - PAR[PM_PAR_XPOS];
+    psF32 Y  = pixcoord->data.F32[1] - PAR[PM_PAR_YPOS];
+    psF32 px = X / PAR[PM_PAR_SXX];
+    psF32 py = Y / PAR[PM_PAR_SYY];
+    psF32 z  = PS_SQR(px) + PS_SQR(py) + PAR[PM_PAR_SXY]*X*Y;
+
+    // XXX if the elliptical contour is defined in valid way, this step should not be required.
+    // other models (like PGAUSS) don't use fractional powers, and thus do not have NaN values
+    // for negative values of z
+    // XXX use an assert here to force the elliptical parameters to be correctly determined
+    // if (z < 0) z = 0;
+    assert (z >= 0);
+
+    psF32 zp = pow(z,1.25);
+    psF32 r  = 1.0 / (1 + PAR[PM_PAR_7]*z + z*zp);
+
+    psF32 r1 = PAR[PM_PAR_I0]*r;
+    psF32 f  = r1 + PAR[PM_PAR_SKY];
+
+    if (deriv != NULL) {
+        psF32 *dPAR = deriv->data.F32;
+
+        // note difference from a pure gaussian: q = params->data.F32[PM_PAR_I0]*r
+        psF32 t = r1*r;
+        psF32 q = t*(PAR[PM_PAR_7] + 2.25*zp);
+
+        dPAR[PM_PAR_SKY]  = +1.0;
+        dPAR[PM_PAR_I0]   = +r;
+        dPAR[PM_PAR_XPOS] = q*(2.0*px/PAR[PM_PAR_SXX] + Y*PAR[PM_PAR_SXY]);
+        dPAR[PM_PAR_YPOS] = q*(2.0*py/PAR[PM_PAR_SYY] + X*PAR[PM_PAR_SXY]);
+        // the extra factor of 2 below is needed to avoid excessive swings
+        dPAR[PM_PAR_SXX]  = +4.0*q*px*px/PAR[PM_PAR_SXX];
+        dPAR[PM_PAR_SYY]  = +4.0*q*py*py/PAR[PM_PAR_SYY];
+        dPAR[PM_PAR_SXY]  = -q*X*Y;
+        dPAR[PM_PAR_7]    = -t*z;
+    }
+    return(f);
+}
+
+// define the parameter limits
+// AR_MAX is the maximum allowed axis ratio
+// AR_RATIO is ((1-R)/(1+R))^2 where R = AR_MAX^(-2)
+# define AR_MAX 20.0
+# define AR_RATIO 0.99
+bool PM_MODEL_LIMITS (psMinConstraintMode mode, int nParam, float *params, float *beta)
+{
+    float beta_lim = 0, params_min = 0, params_max = 0;
+    float f1 = 0, f2 = 0, q1 = 0, q2 = 0;
+
+    // we need to calculate the limits for SXY specially
+    if (nParam == PM_PAR_SXY) {
+        f1 = 1.0 / PS_SQR(params[PM_PAR_SYY]) + 1.0 / PS_SQR(params[PM_PAR_SXX]);
+        f2 = 1.0 / PS_SQR(params[PM_PAR_SYY]) - 1.0 / PS_SQR(params[PM_PAR_SXX]);
+        q1 = PS_SQR(f1)*AR_RATIO - PS_SQR(f2);
+        q1 = (q1 < 0.0) ? 0.0 : q1;
+        // if q1 < 0.0, f2 ~ f1, we have a very large axis ratio near 45deg..  Saturate at that
+        // angle and let f2,f1 fight it out
+        q2  = 0.5*sqrt (q1);
+    }
+
+    switch (mode) {
+    case PS_MINIMIZE_BETA_LIMIT:
+        switch (nParam) {
+        case PM_PAR_SKY:
+            beta_lim = 1000;
+            break;
+        case PM_PAR_I0:
+            beta_lim = 3e6;
+            break;
+        case PM_PAR_XPOS:
+            beta_lim = 5;
+            break;
+        case PM_PAR_YPOS:
+            beta_lim = 5;
+            break;
+        case PM_PAR_SXX:
+            beta_lim = 1.0;
+            break;
+        case PM_PAR_SYY:
+            beta_lim = 1.0;
+            break;
+        case PM_PAR_SXY:
+            beta_lim =  0.5*q2;
+            break;
+        case PM_PAR_7:
+            beta_lim = 2.0;
+            break;
+        default:
+            psAbort("invalid parameter %d for beta test", nParam);
+        }
+        if (fabs(beta[nParam]) > fabs(beta_lim)) {
+            beta[nParam] = (beta[nParam] > 0) ? fabs(beta_lim) : -fabs(beta_lim);
+            psTrace ("psModules.objects", 5, "|beta[nParam==%d]| > |beta_lim|; %g v. %g",
+                     nParam, beta[nParam], beta_lim);
+            return false;
+        }
+        return true;
+    case PS_MINIMIZE_PARAM_MIN:
+        switch (nParam) {
+        case PM_PAR_SKY:
+            params_min = -1000;
+            break;
+        case PM_PAR_I0:
+            params_min =   0.01;
+            break;
+        case PM_PAR_XPOS:
+            params_min =  -100;
+            break;
+        case PM_PAR_YPOS:
+            params_min =  -100;
+            break;
+        case PM_PAR_SXX:
+            params_min =   0.5;
+            break;
+        case PM_PAR_SYY:
+            params_min =   0.5;
+            break;
+        case PM_PAR_SXY:
+            params_min =  -q2;
+            break;
+        case PM_PAR_7:
+            params_min =   0.1;
+            break;
+        default:
+            psAbort("invalid parameter %d for param min test", nParam);
+        }
+        if (params[nParam] < params_min) {
+            params[nParam] = params_min;
+            psTrace ("psModules.objects", 5, "params[nParam==%d] < params_min; %g v. %g",
+                     nParam, params[nParam], params_min);
+            return false;
+        }
+        return true;
+    case PS_MINIMIZE_PARAM_MAX:
+        switch (nParam) {
+        case PM_PAR_SKY:
+            params_max =   1e5;
+            break;
+        case PM_PAR_I0:
+            params_max =   1e8;
+            break;
+        case PM_PAR_XPOS:
+            params_max =   1e4;
+            break;
+        case PM_PAR_YPOS:
+            params_max =   1e4;
+            break;
+        case PM_PAR_SXX:
+            params_max =   100;
+            break;
+        case PM_PAR_SYY:
+            params_max =   100;
+            break;
+        case PM_PAR_SXY:
+            params_max =  +q2;
+            break;
+        case PM_PAR_7:
+            params_max =  20.0;
+            break;
+        default:
+            psAbort("invalid parameter %d for param max test", nParam);
+        }
+        if (params[nParam] > params_max) {
+            params[nParam] = params_max;
+            psTrace ("psModules.objects", 5, "params[nParam==%d] > params_max; %g v. %g",
+                     nParam, params[nParam], params_max);
+            return false;
+        }
+        return true;
+    default:
+        psAbort("invalid choice for limits");
+    }
+    psAbort("should not reach here");
+    return false;
+}
+
+
+// make an initial guess for parameters
+bool PM_MODEL_GUESS (pmModel *model, pmSource *source)
+{
+    pmMoments *moments = source->moments;
+    pmPeak    *peak    = source->peak;
+    psF32     *PAR  = model->params->data.F32;
+
+    psEllipseMoments emoments;
+    emoments.x2 = moments->Sx;
+    emoments.y2 = moments->Sy;
+    emoments.xy = moments->Sxy;
+
+    // force the axis ratio to be < 20.0
+    psEllipseAxes axes = psEllipseMomentsToAxes (emoments, 20.0);
+
+    if (!isfinite(axes.major)) return false;
+    if (!isfinite(axes.minor)) return false;
+    if (!isfinite(axes.theta)) return false;
+
+    psEllipseShape shape = psEllipseAxesToShape (axes);
+
+    if (!isfinite(shape.sx))  return false;
+    if (!isfinite(shape.sy))  return false;
+    if (!isfinite(shape.sxy)) return false;
+
+    // XXX turn this off here for now PAR[PM_PAR_SKY]  = moments->Sky;
+    PAR[PM_PAR_SKY]  = 0.0;
+    PAR[PM_PAR_I0]   = moments->Peak;
+    PAR[PM_PAR_XPOS] = peak->x;
+    PAR[PM_PAR_YPOS] = peak->y;
+    PAR[PM_PAR_SXX]  = PS_MAX(0.5, M_SQRT2*shape.sx);
+    PAR[PM_PAR_SYY]  = PS_MAX(0.5, M_SQRT2*shape.sy);
+    PAR[PM_PAR_SXY]  = shape.sxy;
+    PAR[PM_PAR_7]    = 1.0;
+
+    return(true);
+}
+
+psF64 PM_MODEL_FLUX (const psVector *params)
+{
+    float z, norm;
+    psEllipseShape shape;
+
+    psF32 *PAR = params->data.F32;
+
+    shape.sx  = PAR[PM_PAR_SXX] / M_SQRT2;
+    shape.sy  = PAR[PM_PAR_SYY] / M_SQRT2;
+    shape.sxy = PAR[PM_PAR_SXY];
+
+    // Area is equivalent to 2 pi sigma^2
+    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
+    psF64 Area = 2.0 * M_PI * axes.major * axes.minor;
+
+    // the area needs to be multiplied by the integral of f(z)
+    norm = 0.0;
+
+    # define DZ 0.25
+
+    float f0 = 1.0;
+    float f1, f2;
+    for (z = DZ; z < 50; z += DZ) {
+        f1 = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, 2.25));
+        z += DZ;
+        f2 = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, 2.25));
+        norm += f0 + 4*f1 + f2;
+        f0 = f2;
+    }
+    norm *= DZ / 3.0;
+
+    psF64 Flux = PAR[PM_PAR_I0] * Area * norm;
+
+    return(Flux);
+}
+
+// define this function so it never returns Inf or NaN
+// return the radius which yields the requested flux
+psF64 PM_MODEL_RADIUS (const psVector *params, psF64 flux)
+{
+    psF64 z, f;
+    int Nstep = 0;
+    psEllipseShape shape;
+
+    psF32 *PAR = params->data.F32;
+
+    if (flux <= 0)
+        return (1.0);
+    if (PAR[PM_PAR_I0] <= 0)
+        return (1.0);
+    if (flux >= PAR[PM_PAR_I0])
+        return (1.0);
+
+    shape.sx  = PAR[PM_PAR_SXX] / M_SQRT2;
+    shape.sy  = PAR[PM_PAR_SYY] / M_SQRT2;
+    shape.sxy = PAR[PM_PAR_SXY];
+
+    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
+    psF64 sigma = axes.major;
+
+    psF64 limit = flux / PAR[PM_PAR_I0];
+
+    // use the fact that f is monotonically decreasing
+    z = 0;
+    Nstep = 0;
+
+    // choose a z value guaranteed to be beyond our limit
+    float z0 = pow((1.0 / limit), (1.0 / 2.25));
+    float z1 = (1.0 / limit) / PAR[PM_PAR_7];
+    z1 = PS_MAX (z0, z1);
+    z0 = 0.0;
+
+    // perform a type of bisection to find the value
+    float f0 = 1.0 / (1 + PAR[PM_PAR_7]*z0 + pow(z0, 2.25));
+    float f1 = 1.0 / (1 + PAR[PM_PAR_7]*z1 + pow(z1, 2.25));
+    while ((Nstep < 10) && (fabs(z1 - z0) > 0.5)) {
+        z = 0.5*(z0 + z1);
+        f = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, 2.25));
+        if (f > limit) {
+            z0 = z;
+            f0 = f;
+        } else {
+            z1 = z;
+            f1 = f;
+        }
+        Nstep ++;
+    }
+    psF64 radius = sigma * sqrt (2.0 * z);
+
+    if (isnan(radius))
+        psAbort("error in code: radius is NaN");
+
+    return (radius);
+}
+
+bool PM_MODEL_FROM_PSF (pmModel *modelPSF, pmModel *modelFLT, const pmPSF *psf)
+{
+
+    psF32 *out = modelPSF->params->data.F32;
+    psF32 *in  = modelFLT->params->data.F32;
+
+    // we require these two parameters to exist
+    assert (psf->params->n > PM_PAR_YPOS);
+    assert (psf->params->n > PM_PAR_XPOS);
+
+    for (int i = 0; i < psf->params->n; i++) {
+        if (psf->params->data[i] == NULL) {
+            out[i] = in[i];
+        } else {
+            pmTrend2D *trend = psf->params->data[i];
+            out[i] = pmTrend2DEval(trend, in[PM_PAR_XPOS], in[PM_PAR_YPOS]);
+        }
+    }
+
+    // the 2D PSF model fits polarization terms (E0,E1,E2)
+    // convert to shape terms (SXX,SYY,SXY)
+    if (!pmPSF_FitToModel (out, 0.1)) {
+        psError(PM_ERR_PSF, false, "Failed to fit object at (r,c) = (%.1f,%.1f)",
+                in[PM_PAR_YPOS], in[PM_PAR_XPOS]);
+        return false;
+    }
+
+    // apply the model limits here: this truncates excessive extrapolation
+    // XXX do we need to do this still?  should we put in asserts to test?
+    for (int i = 0; i < psf->params->n; i++) {
+        // apply the limits to all components or just the psf-model parameters?
+        if (psf->params->data[i] == NULL)
+            continue;
+
+        bool status = true;
+        status &= PM_MODEL_LIMITS(PS_MINIMIZE_PARAM_MIN, i, out, NULL);
+        status &= PM_MODEL_LIMITS(PS_MINIMIZE_PARAM_MAX, i, out, NULL);
+        if (!status) {
+            psTrace ("psModules.objects", 5, "Hitting parameter limits at (r,c) = (%.1f, %.1f)",
+                     in[PM_PAR_XPOS], in[PM_PAR_YPOS]);
+            modelPSF->flags |= PM_MODEL_STATUS_LIMITS;
+        }
+    }
+
+    return true;
+}
+
+// construct the PSF model from the FLT model and the psf
+// XXX is this sufficiently general do be a global function, not a pmModelClass function?
+bool PM_MODEL_PARAMS_FROM_PSF (pmModel *model, const pmPSF *psf, float Xo, float Yo, float Io)
+{
+    psF32 *PAR = model->params->data.F32;
+
+    // we require these two parameters to exist
+    assert (psf->params->n > PM_PAR_YPOS);
+    assert (psf->params->n > PM_PAR_XPOS);
+
+    PAR[PM_PAR_SKY]  = 0.0;
+    PAR[PM_PAR_I0]   = Io;
+    PAR[PM_PAR_XPOS] = Xo;
+    PAR[PM_PAR_YPOS] = Yo;
+
+    // supply the model-fitted parameters, or copy from the input
+    for (int i = 0; i < psf->params->n; i++) {
+        if (i == PM_PAR_SKY) continue;
+        if (i == PM_PAR_I0) continue;
+        if (i == PM_PAR_XPOS) continue;
+        if (i == PM_PAR_YPOS) continue;
+        pmTrend2D *trend = psf->params->data[i];
+        PAR[i] = pmTrend2DEval(trend, Xo, Yo);
+    }
+
+    // the 2D PSF model fits polarization terms (E0,E1,E2)
+    // convert to shape terms (SXX,SYY,SXY)
+    // XXX user-defined value for limit?
+    if (!pmPSF_FitToModel (PAR, 0.1)) {
+        psError(PM_ERR_PSF, false, "Failed to fit object at (r,c) = (%.1f,%.1f)", Xo, Yo);
+        return false;
+    }
+
+    // apply the model limits here: this truncates excessive extrapolation
+    // XXX do we need to do this still?  should we put in asserts to test?
+    for (int i = 0; i < psf->params->n; i++) {
+        // apply the limits to all components or just the psf-model parameters?
+        if (psf->params->data[i] == NULL)
+            continue;
+
+        bool status = true;
+        status &= PM_MODEL_LIMITS (PS_MINIMIZE_PARAM_MIN, i, PAR, NULL);
+        status &= PM_MODEL_LIMITS (PS_MINIMIZE_PARAM_MAX, i, PAR, NULL);
+        if (!status) {
+            psTrace ("psModules.objects", 5, "Hitting parameter limits at (r,c) = (%.1f, %.1f)", Xo, Yo);
+            model->flags |= PM_MODEL_STATUS_LIMITS;
+        }
+    }
+    return(true);
+}
+
+bool PM_MODEL_FIT_STATUS (pmModel *model)
+{
+
+    psF32 dP;
+    bool  status;
+
+    psF32 *PAR  = model->params->data.F32;
+    psF32 *dPAR = model->dparams->data.F32;
+
+    dP = 0;
+    dP += PS_SQR(dPAR[PM_PAR_SXX] / PAR[PM_PAR_SXX]);
+    dP += PS_SQR(dPAR[PM_PAR_SYY] / PAR[PM_PAR_SYY]);
+    dP = sqrt (dP);
+
+    status = true;
+//    status &= (dP < 0.5);
+    status &= (PAR[PM_PAR_I0] > 0);
+    status &= ((dPAR[PM_PAR_I0]/PAR[PM_PAR_I0]) < 0.5);
+
+    return status;
+}
+
+# undef PM_MODEL_FUNC
+# undef PM_MODEL_FLUX
+# undef PM_MODEL_GUESS
+# undef PM_MODEL_LIMITS
+# undef PM_MODEL_RADIUS
+# undef PM_MODEL_FROM_PSF
+# undef PM_MODEL_PARAMS_FROM_PSF
+# undef PM_MODEL_FIT_STATUS
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_RGAUSS.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_RGAUSS.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_RGAUSS.c	(revision 22158)
@@ -0,0 +1,466 @@
+/******************************************************************************
+ * this file defines the RGAUSS source shape model (XXX need a better name!).  Note that these
+ * model functions are loaded by pmModelGroup.c using 'include', and thus need no 'include'
+ * statements of their own.  The models use a psVector to represent the set of parameters, with
+ * the sequence used to specify the meaning of the parameter.  The meaning of the parameters
+ * may thus vary depending on the specifics of the model.  All models which are used a PSF
+ * representations share a few parameters, for which # define names are listed in pmModel.h:
+
+   power-law with fitted slope
+   1 / (1 + z + z^alpha)
+
+ * PM_PAR_SKY 0   - local sky : note that this is unused and may be dropped in the future
+ * PM_PAR_I0 1    - central intensity
+ * PM_PAR_XPOS 2  - X center of object
+ * PM_PAR_YPOS 3  - Y center of object
+ * PM_PAR_SXX 4   - X^2 term of elliptical contour (sqrt(2) / SigmaX)
+ * PM_PAR_SYY 5   - Y^2 term of elliptical contour (sqrt(2) / SigmaY)
+ * PM_PAR_SXY 6   - X*Y term of elliptical contour
+ * PM_PAR_7   7   - power-law slope (alpha)
+ *****************************************************************************/
+
+# define PM_MODEL_FUNC            pmModelFunc_RGAUSS
+# define PM_MODEL_FLUX            pmModelFlux_RGAUSS
+# define PM_MODEL_GUESS           pmModelGuess_RGAUSS
+# define PM_MODEL_LIMITS          pmModelLimits_RGAUSS
+# define PM_MODEL_RADIUS          pmModelRadius_RGAUSS
+# define PM_MODEL_FROM_PSF        pmModelFromPSF_RGAUSS
+# define PM_MODEL_PARAMS_FROM_PSF pmModelParamsFromPSF_RGAUSS
+# define PM_MODEL_FIT_STATUS      pmModelFitStatus_RGAUSS
+
+psF32 PM_MODEL_FUNC (psVector *deriv,
+                     const psVector *params,
+                     const psVector *pixcoord)
+{
+    psF32 *PAR = params->data.F32;
+
+    psF32 X  = pixcoord->data.F32[0] - PAR[PM_PAR_XPOS];
+    psF32 Y  = pixcoord->data.F32[1] - PAR[PM_PAR_YPOS];
+    psF32 px = X / PAR[PM_PAR_SXX];
+    psF32 py = Y / PAR[PM_PAR_SYY];
+    psF32 z  = PS_SQR(px) + PS_SQR(py) + X*Y*PAR[PM_PAR_SXY];
+
+    assert (z >= 0);
+
+    psF32 p  = pow(z, PAR[PM_PAR_7] - 1.0);
+    psF32 r  = 1.0 / (1 + z + z*p);
+    psF32 f  = PAR[PM_PAR_I0]*r + PAR[PM_PAR_SKY];
+
+    if (deriv != NULL) {
+        psF32 *dPAR = deriv->data.F32;
+
+        // note difference from a pure gaussian: q = params->data.F32[PM_PAR_I0]*r
+        psF32 t = PAR[PM_PAR_I0]*r*r;
+        psF32 q = t*(1 + PAR[PM_PAR_7]*p);
+
+        dPAR[PM_PAR_SKY] = +1.0;
+        dPAR[PM_PAR_I0] = +r;
+        dPAR[PM_PAR_XPOS] = q*(2.0*px/PAR[PM_PAR_SXX] + Y*PAR[PM_PAR_SXY]);
+        dPAR[PM_PAR_YPOS] = q*(2.0*py/PAR[PM_PAR_SYY] + X*PAR[PM_PAR_SXY]);
+        dPAR[PM_PAR_SXX] = +2.0*q*px*px/PAR[PM_PAR_SXX];
+        dPAR[PM_PAR_SYY] = +2.0*q*py*py/PAR[PM_PAR_SYY];
+        dPAR[PM_PAR_SXY] = -q*X*Y;
+
+        // this model derivative is undefined at z = 0.0, but is actually 0.0
+        dPAR[PM_PAR_7] = (z == 0.0) ? 0.0 : -5.0*t*log(z)*p*z;
+    }
+    return(f);
+}
+
+// define the parameter limits
+// AR_MAX is the maximum allowed axis ratio
+// AR_RATIO is ((1-R)/(1+R))^2 where R = AR_MAX^(-2)
+# define AR_MAX 20.0
+# define AR_RATIO 0.99
+bool PM_MODEL_LIMITS (psMinConstraintMode mode, int nParam, float *params, float *beta)
+{
+    float beta_lim = 0, params_min = 0, params_max = 0;
+    float f1 = 0, f2 = 0, q1 = 0, q2 = 0;
+
+    // we need to calculate the limits for SXY specially
+    if (nParam == PM_PAR_SXY) {
+        f1 = 1.0 / PS_SQR(params[PM_PAR_SYY]) + 1.0 / PS_SQR(params[PM_PAR_SXX]);
+        f2 = 1.0 / PS_SQR(params[PM_PAR_SYY]) - 1.0 / PS_SQR(params[PM_PAR_SXX]);
+        q1 = PS_SQR(f1)*AR_RATIO - PS_SQR(f2);
+        q1 = (q1 < 0.0) ? 0.0 : q1;
+        // if q1 < 0.0, f2 ~ f1, we have a very large axis ratio near 45deg..  Saturate at that
+        // angle and let f2,f1 fight it out
+        q2  = 0.5*sqrt (q1);
+    }
+
+    switch (mode) {
+    case PS_MINIMIZE_BETA_LIMIT:
+        switch (nParam) {
+        case PM_PAR_SKY:
+            beta_lim = 1000;
+            break;
+        case PM_PAR_I0:
+            beta_lim = 3e6;
+            break;
+        case PM_PAR_XPOS:
+            beta_lim = 5;
+            break;
+        case PM_PAR_YPOS:
+            beta_lim = 5;
+            break;
+        case PM_PAR_SXX:
+            beta_lim = 0.5;
+            break;
+        case PM_PAR_SYY:
+            beta_lim = 0.5;
+            break;
+        case PM_PAR_SXY:
+            beta_lim =  0.5*q2;
+            break;
+        case PM_PAR_7:
+            beta_lim = 0.5;
+            break;
+        default:
+            psAbort("invalid parameter %d for beta test", nParam);
+        }
+        if (fabs(beta[nParam]) > fabs(beta_lim)) {
+            beta[nParam] = (beta[nParam] > 0) ? fabs(beta_lim) : -fabs(beta_lim);
+            psTrace ("psModules.objects", 5, "|beta[nParam==%d]| > |beta_lim|; %g v. %g",
+                     nParam, beta[nParam], beta_lim);
+            return false;
+        }
+        return true;
+    case PS_MINIMIZE_PARAM_MIN:
+        switch (nParam) {
+        case PM_PAR_SKY:
+            params_min = -1000;
+            break;
+        case PM_PAR_I0:
+            params_min =   0.01;
+            break;
+        case PM_PAR_XPOS:
+            params_min =  -100;
+            break;
+        case PM_PAR_YPOS:
+            params_min =  -100;
+            break;
+        case PM_PAR_SXX:
+            params_min =   0.5;
+            break;
+        case PM_PAR_SYY:
+            params_min =   0.5;
+            break;
+        case PM_PAR_SXY:
+            params_min =  -q2;
+            break;
+        case PM_PAR_7:
+            params_min =   1.25;
+            break;
+        default:
+            psAbort("invalid parameter %d for param min test", nParam);
+        }
+        if (params[nParam] < params_min) {
+            params[nParam] = params_min;
+            psTrace ("psModules.objects", 5, "params[nParam==%d] < params_min; %g v. %g",
+                     nParam, params[nParam], params_min);
+            return false;
+        }
+        return true;
+    case PS_MINIMIZE_PARAM_MAX:
+        switch (nParam) {
+        case PM_PAR_SKY:
+            params_max =   1e5;
+            break;
+        case PM_PAR_I0:
+            params_max =   1e8;
+            break;
+        case PM_PAR_XPOS:
+            params_max =   1e4;
+            break;
+        case PM_PAR_YPOS:
+            params_max =   1e4;
+            break;
+        case PM_PAR_SXX:
+            params_max =   100;
+            break;
+        case PM_PAR_SYY:
+            params_max =   100;
+            break;
+        case PM_PAR_SXY:
+            params_max =  +q2;
+            break;
+        case PM_PAR_7:
+            params_max =  4.0;
+            break;
+        default:
+            psAbort("invalid parameter %d for param max test", nParam);
+        }
+        if (params[nParam] > params_max) {
+            params[nParam] = params_max;
+            psTrace ("psModules.objects", 5, "params[nParam==%d] > params_max; %g v. %g",
+                     nParam, params[nParam], params_max);
+            return false;
+        }
+        return true;
+    default:
+        psAbort("invalid choice for limits");
+    }
+    psAbort("should not reach here");
+    return false;
+}
+
+// make an initial guess for parameters
+bool PM_MODEL_GUESS (pmModel *model, pmSource *source)
+{
+    pmMoments *moments = source->moments;
+    pmPeak    *peak    = source->peak;
+    psF32     *PAR  = model->params->data.F32;
+
+    psEllipseMoments emoments;
+    emoments.x2 = moments->Sx;
+    emoments.y2 = moments->Sy;
+    emoments.xy = moments->Sxy;
+
+    // force the axis ratio to be < 20.0
+    psEllipseAxes axes = psEllipseMomentsToAxes (emoments, 20.0);
+
+    if (!isfinite(axes.major)) return false;
+    if (!isfinite(axes.minor)) return false;
+    if (!isfinite(axes.theta)) return false;
+
+    psEllipseShape shape = psEllipseAxesToShape (axes);
+
+    if (!isfinite(shape.sx))  return false;
+    if (!isfinite(shape.sy))  return false;
+    if (!isfinite(shape.sxy)) return false;
+
+    PAR[PM_PAR_SKY]  = moments->Sky;
+    PAR[PM_PAR_I0]   = moments->Peak - moments->Sky;
+    PAR[PM_PAR_XPOS] = peak->x;
+    PAR[PM_PAR_YPOS] = peak->y;
+    PAR[PM_PAR_SXX]  = PS_MAX(0.5, M_SQRT2*shape.sx);
+    PAR[PM_PAR_SYY]  = PS_MAX(0.5, M_SQRT2*shape.sy);
+    PAR[PM_PAR_SXY]  = shape.sxy;
+    PAR[PM_PAR_7]    = 2.25;
+
+    return(true);
+}
+
+psF64 PM_MODEL_FLUX (const psVector *params)
+{
+    float norm, z;
+    psEllipseShape shape;
+
+    psF32 *PAR = params->data.F32;
+
+    shape.sx  = PAR[PM_PAR_SXX] / M_SQRT2;
+    shape.sy  = PAR[PM_PAR_SYY] / M_SQRT2;
+    shape.sxy = PAR[PM_PAR_SXY];
+
+    // Area is equivalent to 2 pi sigma^2
+    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
+    psF64 Area = 2.0 * M_PI * axes.major * axes.minor;
+
+    // the area needs to be multiplied by the integral of f(z)
+    norm = 0.0;
+
+    # define DZ 0.25
+
+    float f0 = 1.0;
+    float f1, f2;
+    for (z = DZ; z < 50; z += DZ) {
+        f1 = 1.0 / (1 + z + pow(z, PAR[PM_PAR_7]));
+        z += DZ;
+        f2 = 1.0 / (1 + z + pow(z, PAR[PM_PAR_7]));
+        norm += f0 + 4*f1 + f2;
+        f0 = f2;
+    }
+    norm *= DZ / 3.0;
+
+    psF64 Flux = PAR[PM_PAR_I0] * Area * norm;
+
+    return(Flux);
+}
+
+// define this function so it never returns Inf or NaN
+// return the radius which yields the requested flux
+psF64 PM_MODEL_RADIUS (const psVector *params, psF64 flux)
+{
+    psF64 z, f;
+    int Nstep = 0;
+    psEllipseShape shape;
+
+    psF32 *PAR = params->data.F32;
+
+    if (flux <= 0)
+        return (1.0);
+    if (PAR[PM_PAR_I0] <= 0)
+        return (1.0);
+    if (flux >= PAR[PM_PAR_I0])
+        return (1.0);
+
+    shape.sx  = PAR[PM_PAR_SXX] / M_SQRT2;
+    shape.sy  = PAR[PM_PAR_SYY] / M_SQRT2;
+    shape.sxy = PAR[PM_PAR_SXY];
+
+    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
+    psF64 sigma = axes.major;
+
+    psF64 limit = flux / PAR[PM_PAR_I0];
+
+    // use the fact that f is monotonically decreasing
+    z = 0;
+    Nstep = 0;
+
+    // choose a z value guaranteed to be beyond our limit
+    float z0 = pow((1.0 / limit), (1.0 / PAR[PM_PAR_7]));
+    float z1 = (1.0 / limit);
+    z1 = PS_MAX (z0, z1);
+    z0 = 0.0;
+
+    // perform a type of bisection to find the value
+    float f0 = 1.0 / (1 + z0 + pow(z0, PAR[PM_PAR_7]));
+    float f1 = 1.0 / (1 + z1 + pow(z1, PAR[PM_PAR_7]));
+    while ((Nstep < 10) && (fabs(z1 - z0) > 0.5)) {
+        z = 0.5*(z0 + z1);
+        f = 1.0 / (1 + z + pow(z, PAR[PM_PAR_7]));
+        if (f > limit) {
+            z0 = z;
+            f0 = f;
+        } else {
+            z1 = z;
+            f1 = f;
+        }
+        Nstep ++;
+    }
+    psF64 radius = sigma * sqrt (2.0 * z);
+
+    if (isnan(radius))
+        psAbort("error in code: radius is NaN");
+
+    return (radius);
+}
+
+bool PM_MODEL_FROM_PSF (pmModel *modelPSF, pmModel *modelFLT, const pmPSF *psf)
+{
+
+    psF32 *out = modelPSF->params->data.F32;
+    psF32 *in  = modelFLT->params->data.F32;
+
+    // we require these two parameters to exist
+    assert (psf->params->n > PM_PAR_YPOS);
+    assert (psf->params->n > PM_PAR_XPOS);
+
+    for (int i = 0; i < psf->params->n; i++) {
+        if (psf->params->data[i] == NULL) {
+            out[i] = in[i];
+        } else {
+            pmTrend2D *trend = psf->params->data[i];
+            out[i] = pmTrend2DEval(trend, in[PM_PAR_XPOS], in[PM_PAR_YPOS]);
+        }
+    }
+
+    // the 2D PSF model fits polarization terms (E0,E1,E2)
+    // convert to shape terms (SXX,SYY,SXY)
+    if (!pmPSF_FitToModel (out, 0.1)) {
+        psError(PM_ERR_PSF, false, "Failed to fit object at (r,c) = (%.1f,%.1f)",
+                in[PM_PAR_YPOS], in[PM_PAR_XPOS]);
+        return false;
+    }
+
+    // apply the model limits here: this truncates excessive extrapolation
+    // XXX do we need to do this still?  should we put in asserts to test?
+    for (int i = 0; i < psf->params->n; i++) {
+        // apply the limits to all components or just the psf-model parameters?
+        if (psf->params->data[i] == NULL)
+            continue;
+
+        bool status = true;
+        status &= PM_MODEL_LIMITS(PS_MINIMIZE_PARAM_MIN, i, out, NULL);
+        status &= PM_MODEL_LIMITS(PS_MINIMIZE_PARAM_MAX, i, out, NULL);
+        if (!status) {
+            psTrace ("psModules.objects", 5, "Hitting parameter limits at (r,c) = (%.1f, %.1f)",
+                     in[PM_PAR_XPOS], in[PM_PAR_YPOS]);
+            modelPSF->flags |= PM_MODEL_STATUS_LIMITS;
+        }
+    }
+
+    return true;
+}
+
+// construct the PSF model from the FLT model and the psf
+// XXX is this sufficiently general do be a global function, not a pmModelClass function?
+bool PM_MODEL_PARAMS_FROM_PSF (pmModel *model, const pmPSF *psf, float Xo, float Yo, float Io)
+{
+    psF32 *PAR = model->params->data.F32;
+
+    // we require these two parameters to exist
+    assert (psf->params->n > PM_PAR_YPOS);
+    assert (psf->params->n > PM_PAR_XPOS);
+
+    PAR[PM_PAR_SKY]  = 0.0;
+    PAR[PM_PAR_I0]   = Io;
+    PAR[PM_PAR_XPOS] = Xo;
+    PAR[PM_PAR_YPOS] = Yo;
+
+    // supply the model-fitted parameters, or copy from the input
+    for (int i = 0; i < psf->params->n; i++) {
+        if (i == PM_PAR_SKY) continue;
+        if (i == PM_PAR_I0) continue;
+        if (i == PM_PAR_XPOS) continue;
+        if (i == PM_PAR_YPOS) continue;
+        pmTrend2D *trend = psf->params->data[i];
+        PAR[i] = pmTrend2DEval(trend, Xo, Yo);
+    }
+
+    // the 2D PSF model fits polarization terms (E0,E1,E2)
+    // convert to shape terms (SXX,SYY,SXY)
+    // XXX user-defined value for limit?
+    if (!pmPSF_FitToModel (PAR, 0.1)) {
+        psError(PM_ERR_PSF, false, "Failed to fit object at (r,c) = (%.1f,%.1f)", Xo, Yo);
+        return false;
+    }
+
+    // apply the model limits here: this truncates excessive extrapolation
+    // XXX do we need to do this still?  should we put in asserts to test?
+    for (int i = 0; i < psf->params->n; i++) {
+        // apply the limits to all components or just the psf-model parameters?
+        if (psf->params->data[i] == NULL)
+            continue;
+
+        bool status = true;
+        status &= PM_MODEL_LIMITS (PS_MINIMIZE_PARAM_MIN, i, PAR, NULL);
+        status &= PM_MODEL_LIMITS (PS_MINIMIZE_PARAM_MAX, i, PAR, NULL);
+        if (!status) {
+            psTrace ("psModules.objects", 5, "Hitting parameter limits at (r,c) = (%.1f, %.1f)", Xo, Yo);
+            model->flags |= PM_MODEL_STATUS_LIMITS;
+        }
+    }
+    return(true);
+}
+
+bool PM_MODEL_FIT_STATUS (pmModel *model)
+{
+
+    psF32 dP;
+    bool  status;
+
+    psF32 *PAR  = model->params->data.F32;
+    psF32 *dPAR = model->dparams->data.F32;
+
+    dP = 0;
+    dP += PS_SQR(dPAR[PM_PAR_SXX] / PAR[PM_PAR_SXX]);
+    dP += PS_SQR(dPAR[PM_PAR_SYY] / PAR[PM_PAR_SYY]);
+    dP = sqrt (dP);
+
+    status = true;
+    status &= (dP < 0.5);
+    status &= (PAR[PM_PAR_I0] > 0);
+    status &= ((dPAR[PM_PAR_I0]/PAR[PM_PAR_I0]) < 0.5);
+
+    return status;
+}
+
+# undef PM_MODEL_FUNC
+# undef PM_MODEL_FLUX
+# undef PM_MODEL_GUESS
+# undef PM_MODEL_LIMITS
+# undef PM_MODEL_RADIUS
+# undef PM_MODEL_FROM_PSF
+# undef PM_MODEL_PARAMS_FROM_PSF
+# undef PM_MODEL_FIT_STATUS
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_SERSIC.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_SERSIC.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_SERSIC.c	(revision 22158)
@@ -0,0 +1,462 @@
+/******************************************************************************
+ * this file defines the SERSIC source shape model.  Note that these model functions are loaded
+ * by pmModelGroup.c using 'include', and thus need no 'include' statements of their own.  The
+ * models use a psVector to represent the set of parameters, with the sequence used to specify
+ * the meaning of the parameter.  The meaning of the parameters may thus vary depending on the
+ * specifics of the model.  All models which are used a PSF representations share a few
+ * parameters, for which # define names are listed in pmModel.h:
+
+   f = exp(-z^n)
+
+   * PM_PAR_SKY 0   - local sky : note that this is unused and may be dropped in the future
+   * PM_PAR_I0 1    - central intensity
+   * PM_PAR_XPOS 2  - X center of object
+   * PM_PAR_YPOS 3  - Y center of object
+   * PM_PAR_SXX 4   - X^2 term of elliptical contour (sqrt(2) / SigmaX)
+   * PM_PAR_SYY 5   - Y^2 term of elliptical contour (sqrt(2) / SigmaY)
+   * PM_PAR_SXY 6   - X*Y term of elliptical contour
+   * PM_PAR_7   7   - normalized sersic parameter
+
+   note that a standard sersic model uses exp(-K*(z^(1/n) - 1).  the additional elements (K,
+   the -1 offset) are absorbed in this model by the normalization, the exponent, and the
+   radial scale.  We fit the elements in this form, then re-normalize them on output.
+   *****************************************************************************/
+
+# define PM_MODEL_FUNC            pmModelFunc_SERSIC
+# define PM_MODEL_FLUX            pmModelFlux_SERSIC
+# define PM_MODEL_GUESS           pmModelGuess_SERSIC
+# define PM_MODEL_LIMITS          pmModelLimits_SERSIC
+# define PM_MODEL_RADIUS          pmModelRadius_SERSIC
+# define PM_MODEL_FROM_PSF        pmModelFromPSF_SERSIC
+# define PM_MODEL_PARAMS_FROM_PSF pmModelParamsFromPSF_SERSIC
+# define PM_MODEL_FIT_STATUS      pmModelFitStatus_SERSIC
+
+psF32 PM_MODEL_FUNC (psVector *deriv,
+                     const psVector *params,
+                     const psVector *pixcoord)
+{
+    psF32 *PAR = params->data.F32;
+
+    psF32 X  = pixcoord->data.F32[0] - PAR[PM_PAR_XPOS];
+    psF32 Y  = pixcoord->data.F32[1] - PAR[PM_PAR_YPOS];
+    psF32 px = X / PAR[PM_PAR_SXX];
+    psF32 py = Y / PAR[PM_PAR_SYY];
+    psF32 z  = PS_SQR(px) + PS_SQR(py) + PAR[PM_PAR_SXY]*X*Y;
+
+    // XXX if the elliptical contour is defined in valid way, this step should not be required.
+    // other models (like PGAUSS) don't use fractional powers, and thus do not have NaN values
+    // for negative values of z
+    // XXX use an assert here to force the elliptical parameters to be correctly determined
+    // if (z < 0) z = 0;
+    assert (z >= 0);
+
+    psF32 f2 = pow(z,PAR[PM_PAR_7]);
+    psF32 f1 = exp(-f2);
+    psF32 z0 = PAR[PM_PAR_I0]*f1;
+    psF32 f0 = PAR[PM_PAR_SKY] + z0;
+
+    assert (isfinite(f2));
+    assert (isfinite(f1));
+    assert (isfinite(z0));
+    assert (isfinite(f0));
+
+    if (deriv != NULL) {
+        psF32 *dPAR = deriv->data.F32;
+
+        // gradient is infinite for z = 0; saturate at z = 0.01
+        psF32 z1 = (z < 0.01) ? z0*PAR[PM_PAR_7]*pow(0.01,PAR[PM_PAR_7] - 1.0) : z0*PAR[PM_PAR_7]*pow(z,PAR[PM_PAR_7] - 1.0);
+
+        dPAR[PM_PAR_SKY]  = +1.0;
+        dPAR[PM_PAR_I0]   = +f1;
+        dPAR[PM_PAR_7]    = (z == 0.0) ? 0.0 : -z0*f2*log(z);
+
+        assert (isfinite(z1));
+        assert (isfinite(dPAR[PM_PAR_7]));
+
+        dPAR[PM_PAR_XPOS] = +1.0*z1*(2.0*px/PAR[PM_PAR_SXX] + Y*PAR[PM_PAR_SXY]);
+        dPAR[PM_PAR_YPOS] = +1.0*z1*(2.0*py/PAR[PM_PAR_SYY] + X*PAR[PM_PAR_SXY]);
+        dPAR[PM_PAR_SXX]  = +2.0*z1*px*px/PAR[PM_PAR_SXX];
+        dPAR[PM_PAR_SYY]  = +2.0*z1*py*py/PAR[PM_PAR_SYY];
+        dPAR[PM_PAR_SXY]  = -1.0*z1*X*Y;
+        dPAR[PM_PAR_SXY]  = -1.0*z1*X*Y;
+    }
+    return (f0);
+}
+
+// define the parameter limits
+// AR_MAX is the maximum allowed axis ratio
+// AR_RATIO is ((1-R)/(1+R))^2 where R = AR_MAX^(-2)
+# define AR_MAX 20.0
+# define AR_RATIO 0.99
+bool PM_MODEL_LIMITS (psMinConstraintMode mode, int nParam, float *params, float *beta)
+{
+    float beta_lim = 0, params_min = 0, params_max = 0;
+    float f1 = 0, f2 = 0, q1 = 0, q2 = 0;
+
+    // we need to calculate the limits for SXY specially
+    if (nParam == PM_PAR_SXY) {
+        f1 = 1.0 / PS_SQR(params[PM_PAR_SYY]) + 1.0 / PS_SQR(params[PM_PAR_SXX]);
+        f2 = 1.0 / PS_SQR(params[PM_PAR_SYY]) - 1.0 / PS_SQR(params[PM_PAR_SXX]);
+        q1 = PS_SQR(f1)*AR_RATIO - PS_SQR(f2);
+        q1 = (q1 < 0.0) ? 0.0 : q1;
+        // if q1 < 0.0, f2 ~ f1, we have a very large axis ratio near 45deg..  Saturate at that
+        // angle and let f2,f1 fight it out
+        q2  = 0.5*sqrt (q1);
+    }
+
+    switch (mode) {
+    case PS_MINIMIZE_BETA_LIMIT:
+        switch (nParam) {
+        case PM_PAR_SKY:
+            beta_lim = 1000;
+            break;
+        case PM_PAR_I0:
+            beta_lim = 3e6;
+            break;
+        case PM_PAR_XPOS:
+            beta_lim = 5;
+            break;
+        case PM_PAR_YPOS:
+            beta_lim = 5;
+            break;
+        case PM_PAR_SXX:
+            beta_lim = 1.0;
+            break;
+        case PM_PAR_SYY:
+            beta_lim = 1.0;
+            break;
+        case PM_PAR_SXY:
+            beta_lim =  0.5*q2;
+            break;
+        case PM_PAR_7:
+            beta_lim = 2.0;
+            break;
+        default:
+            psAbort("invalid parameter %d for beta test", nParam);
+        }
+        if (fabs(beta[nParam]) > fabs(beta_lim)) {
+            beta[nParam] = (beta[nParam] > 0) ? fabs(beta_lim) : -fabs(beta_lim);
+            psTrace ("psModules.objects", 5, "|beta[nParam==%d]| > |beta_lim|; %g v. %g",
+                     nParam, beta[nParam], beta_lim);
+            return false;
+        }
+        return true;
+    case PS_MINIMIZE_PARAM_MIN:
+        switch (nParam) {
+        case PM_PAR_SKY:
+            params_min = -1000;
+            break;
+        case PM_PAR_I0:
+            params_min =     0.01;
+            break;
+        case PM_PAR_XPOS:
+            params_min =  -100;
+            break;
+        case PM_PAR_YPOS:
+            params_min =  -100;
+            break;
+        case PM_PAR_SXX:
+            params_min =   0.05;
+            break;
+        case PM_PAR_SYY:
+            params_min =   0.05;
+            break;
+        case PM_PAR_SXY:
+            params_min =  -q2;
+            break;
+        case PM_PAR_7:
+            params_min =   0.05;
+            break;
+        default:
+            psAbort("invalid parameter %d for param min test", nParam);
+        }
+        if (params[nParam] < params_min) {
+            params[nParam] = params_min;
+            psTrace ("psModules.objects", 5, "params[nParam==%d] < params_min; %g v. %g",
+                     nParam, params[nParam], params_min);
+            return false;
+        }
+        return true;
+    case PS_MINIMIZE_PARAM_MAX:
+        switch (nParam) {
+        case PM_PAR_SKY:
+            params_max =   1e5;
+            break;
+        case PM_PAR_I0:
+            params_max =   1e8;
+            break;
+        case PM_PAR_XPOS:
+            params_max =   1e4;
+            break;
+        case PM_PAR_YPOS:
+            params_max =   1e4;
+            break;
+        case PM_PAR_SXX:
+            params_max =   100;
+            break;
+        case PM_PAR_SYY:
+            params_max =   100;
+            break;
+        case PM_PAR_SXY:
+            params_max =  +q2;
+            break;
+        case PM_PAR_7:
+            params_max =   4.0;
+            break;
+        default:
+            psAbort("invalid parameter %d for param max test", nParam);
+        }
+        if (params[nParam] > params_max) {
+            params[nParam] = params_max;
+            psTrace ("psModules.objects", 5, "params[nParam==%d] > params_max; %g v. %g",
+                     nParam, params[nParam], params_max);
+            return false;
+        }
+        return true;
+    default:
+        psAbort("invalid choice for limits");
+    }
+    psAbort("should not reach here");
+    return false;
+}
+
+
+// make an initial guess for parameters
+bool PM_MODEL_GUESS (pmModel *model, pmSource *source)
+{
+    pmMoments *moments = source->moments;
+    pmPeak    *peak    = source->peak;
+    psF32     *PAR  = model->params->data.F32;
+
+    psEllipseMoments emoments;
+    emoments.x2 = moments->Sx;
+    emoments.y2 = moments->Sy;
+    emoments.xy = moments->Sxy;
+
+    // force the axis ratio to be < 20.0
+    psEllipseAxes axes = psEllipseMomentsToAxes (emoments, 20.0);
+
+    if (!isfinite(axes.major)) return false;
+    if (!isfinite(axes.minor)) return false;
+    if (!isfinite(axes.theta)) return false;
+
+    psEllipseShape shape = psEllipseAxesToShape (axes);
+
+    if (!isfinite(shape.sx))  return false;
+    if (!isfinite(shape.sy))  return false;
+    if (!isfinite(shape.sxy)) return false;
+
+    // XXX PAR[PM_PAR_SKY]  = moments->Sky;
+    PAR[PM_PAR_SKY]  = 0.0;
+    PAR[PM_PAR_I0]   = moments->Peak;
+    PAR[PM_PAR_XPOS] = peak->x;
+    PAR[PM_PAR_YPOS] = peak->y;
+    PAR[PM_PAR_SXX]  = PS_MAX(0.5, M_SQRT2*shape.sx);
+    PAR[PM_PAR_SYY]  = PS_MAX(0.5, M_SQRT2*shape.sy);
+    PAR[PM_PAR_SXY]  = shape.sxy;
+    PAR[PM_PAR_7]    = 0.5;
+
+    return(true);
+}
+
+psF64 PM_MODEL_FLUX (const psVector *params)
+{
+    float z, norm;
+    psEllipseShape shape;
+
+    psF32 *PAR = params->data.F32;
+
+    shape.sx  = PAR[PM_PAR_SXX] / M_SQRT2;
+    shape.sy  = PAR[PM_PAR_SYY] / M_SQRT2;
+    shape.sxy = PAR[PM_PAR_SXY];
+
+    // Area is equivalent to 2 pi sigma^2
+    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
+    psF64 Area = 2.0 * M_PI * axes.major * axes.minor;
+
+    // the area needs to be multiplied by the integral of f(z)
+    norm = 0.0;
+
+    # define DZ 0.25
+
+    float f0 = 1.0;
+    float f1, f2;
+    for (z = DZ; z < 50; z += DZ) {
+        f1 = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, 2.25));
+        z += DZ;
+        f2 = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, 2.25));
+        norm += f0 + 4*f1 + f2;
+        f0 = f2;
+    }
+    norm *= DZ / 3.0;
+
+    psF64 Flux = PAR[PM_PAR_I0] * Area * norm;
+
+    return(Flux);
+}
+
+// define this function so it never returns Inf or NaN
+// return the radius which yields the requested flux
+psF64 PM_MODEL_RADIUS (const psVector *params, psF64 flux)
+{
+    psEllipseShape shape;
+
+    psF32 *PAR = params->data.F32;
+
+    if (flux <= 0)
+        return (1.0);
+    if (PAR[PM_PAR_I0] <= 0)
+        return (1.0);
+    if (flux >= PAR[PM_PAR_I0])
+        return (1.0);
+
+    shape.sx  = PAR[PM_PAR_SXX] / M_SQRT2;
+    shape.sy  = PAR[PM_PAR_SYY] / M_SQRT2;
+    shape.sxy = PAR[PM_PAR_SXY];
+
+    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
+    psF64 sigma = axes.major;
+
+    psF64 limit = flux / PAR[PM_PAR_I0];
+
+    psF64 z = pow (-log(limit), (1.0 / PAR[PM_PAR_7]));
+
+    psF64 radius = sigma * sqrt (2.0 * z);
+
+    if (isnan(radius))
+        psAbort("error in code: radius is NaN");
+
+    return (radius);
+}
+
+bool PM_MODEL_FROM_PSF (pmModel *modelPSF, pmModel *modelFLT, const pmPSF *psf)
+{
+
+    psF32 *out = modelPSF->params->data.F32;
+    psF32 *in  = modelFLT->params->data.F32;
+
+    // we require these two parameters to exist
+    assert (psf->params->n > PM_PAR_YPOS);
+    assert (psf->params->n > PM_PAR_XPOS);
+
+    for (int i = 0; i < psf->params->n; i++) {
+        if (psf->params->data[i] == NULL) {
+            out[i] = in[i];
+        } else {
+            pmTrend2D *trend = psf->params->data[i];
+            out[i] = pmTrend2DEval(trend, in[PM_PAR_XPOS], in[PM_PAR_YPOS]);
+        }
+    }
+
+    // the 2D PSF model fits polarization terms (E0,E1,E2)
+    // convert to shape terms (SXX,SYY,SXY)
+    if (!pmPSF_FitToModel (out, 0.1)) {
+        psError(PM_ERR_PSF, false, "Failed to fit object at (r,c) = (%.1f,%.1f)",
+                in[PM_PAR_YPOS], in[PM_PAR_XPOS]);
+        return false;
+    }
+
+    // apply the model limits here: this truncates excessive extrapolation
+    // XXX do we need to do this still?  should we put in asserts to test?
+    for (int i = 0; i < psf->params->n; i++) {
+        // apply the limits to all components or just the psf-model parameters?
+        if (psf->params->data[i] == NULL)
+            continue;
+
+        bool status = true;
+        status &= PM_MODEL_LIMITS(PS_MINIMIZE_PARAM_MIN, i, out, NULL);
+        status &= PM_MODEL_LIMITS(PS_MINIMIZE_PARAM_MAX, i, out, NULL);
+        if (!status) {
+            psTrace ("psModules.objects", 5, "Hitting parameter limits at (r,c) = (%.1f, %.1f)",
+                     in[PM_PAR_XPOS], in[PM_PAR_YPOS]);
+            modelPSF->flags |= PM_MODEL_STATUS_LIMITS;
+        }
+    }
+
+    return true;
+}
+
+// construct the PSF model from the FLT model and the psf
+// XXX is this sufficiently general do be a global function, not a pmModelClass function?
+bool PM_MODEL_PARAMS_FROM_PSF (pmModel *model, const pmPSF *psf, float Xo, float Yo, float Io)
+{
+    psF32 *PAR = model->params->data.F32;
+
+    // we require these two parameters to exist
+    assert (psf->params->n > PM_PAR_YPOS);
+    assert (psf->params->n > PM_PAR_XPOS);
+
+    PAR[PM_PAR_SKY]  = 0.0;
+    PAR[PM_PAR_I0]   = Io;
+    PAR[PM_PAR_XPOS] = Xo;
+    PAR[PM_PAR_YPOS] = Yo;
+
+    // supply the model-fitted parameters, or copy from the input
+    for (int i = 0; i < psf->params->n; i++) {
+        if (i == PM_PAR_SKY) continue;
+        if (i == PM_PAR_I0) continue;
+        if (i == PM_PAR_XPOS) continue;
+        if (i == PM_PAR_YPOS) continue;
+        pmTrend2D *trend = psf->params->data[i];
+        PAR[i] = pmTrend2DEval(trend, Xo, Yo);
+    }
+
+    // the 2D PSF model fits polarization terms (E0,E1,E2)
+    // convert to shape terms (SXX,SYY,SXY)
+    // XXX user-defined value for limit?
+    if (!pmPSF_FitToModel (PAR, 0.1)) {
+        psError(PM_ERR_PSF, false, "Failed to fit object at (r,c) = (%.1f,%.1f)", Xo, Yo);
+        return false;
+    }
+
+    // apply the model limits here: this truncates excessive extrapolation
+    // XXX do we need to do this still?  should we put in asserts to test?
+    for (int i = 0; i < psf->params->n; i++) {
+        // apply the limits to all components or just the psf-model parameters?
+        if (psf->params->data[i] == NULL)
+            continue;
+
+        bool status = true;
+        status &= PM_MODEL_LIMITS (PS_MINIMIZE_PARAM_MIN, i, PAR, NULL);
+        status &= PM_MODEL_LIMITS (PS_MINIMIZE_PARAM_MAX, i, PAR, NULL);
+        if (!status) {
+            psTrace ("psModules.objects", 5, "Hitting parameter limits at (r,c) = (%.1f, %.1f)", Xo, Yo);
+            model->flags |= PM_MODEL_STATUS_LIMITS;
+        }
+    }
+    return(true);
+}
+
+bool PM_MODEL_FIT_STATUS (pmModel *model)
+{
+
+    psF32 dP;
+    bool  status;
+
+    psF32 *PAR  = model->params->data.F32;
+    psF32 *dPAR = model->dparams->data.F32;
+
+    dP = 0;
+    dP += PS_SQR(dPAR[PM_PAR_SXX] / PAR[PM_PAR_SXX]);
+    dP += PS_SQR(dPAR[PM_PAR_SYY] / PAR[PM_PAR_SYY]);
+    dP = sqrt (dP);
+
+    status = true;
+//    status &= (dP < 0.5);
+    status &= (PAR[PM_PAR_I0] > 0);
+    status &= ((dPAR[PM_PAR_I0]/PAR[PM_PAR_I0]) < 0.5);
+
+    fprintf (stderr, "SERSIC status pars: dP: %f, I0: %f, S/N: %f\n",
+	     dP, PAR[PM_PAR_I0], (dPAR[PM_PAR_I0]/PAR[PM_PAR_I0]));
+
+    return status;
+}
+
+# undef PM_MODEL_FUNC
+# undef PM_MODEL_FLUX
+# undef PM_MODEL_GUESS
+# undef PM_MODEL_LIMITS
+# undef PM_MODEL_RADIUS
+# undef PM_MODEL_FROM_PSF
+# undef PM_MODEL_PARAMS_FROM_PSF
+# undef PM_MODEL_FIT_STATUS
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_SGAUSS.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_SGAUSS.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_SGAUSS.c	(revision 22158)
@@ -0,0 +1,386 @@
+/******************************************************************************
+ * this file defines the SGAUSS source shape model (XXX need a better name!).  Note that these
+ * model functions are loaded by pmModelGroup.c using 'include', and thus need no 'include'
+ * statements of their own.  The models use a psVector to represent the set of parameters, with
+ * the sequence used to specify the meaning of the parameter.  The meaning of the parameters
+ * may thus vary depending on the specifics of the model.  All models which are used a PSF
+ * representations share a few parameters, for which # define names are listed in pmModel.h:
+
+   power-law with fitted slope and outer tidal radius
+   1 / (1 + z^N + kz^4)
+
+   * PM_PAR_SKY 0   - local sky : note that this is unused and may be dropped in the future
+   * PM_PAR_I0 1    - central intensity
+   * PM_PAR_XPOS 2  - X center of object
+   * PM_PAR_YPOS 3  - Y center of object
+   * PM_PAR_SXX 4   - X^2 term of elliptical contour (sqrt(2) / SigmaX)
+   * PM_PAR_SYY 5   - Y^2 term of elliptical contour (sqrt(2) / SigmaY)
+   * PM_PAR_SXY 6   - X*Y term of elliptical contour
+   * PM_PAR_7   7   - slope of power-law component (N)
+   * PM_PAR_8   8   - amplitude of the tidal cutoff (k)
+   *****************************************************************************/
+
+/***
+    XXXX the model in this file needs to be tested more carefully.
+    the code for guessing the power-law slope based on the radial profile
+    is either too slow or does not work well.
+    fix up the code to follow conventions in the other model function files.
+***/
+
+XXX broken code
+
+# define PM_MODEL_FUNC       pmModelFunc_SGAUSS
+# define PM_MODEL_FLUX       pmModelFlux_SGAUSS
+# define PM_MODEL_GUESS      pmModelGuess_SGAUSS
+# define PM_MODEL_LIMITS     pmModelLimits_SGAUSS
+# define PM_MODEL_RADIUS     pmModelRadius_SGAUSS
+# define PM_MODEL_FROM_PSF   pmModelFromPSF_SGAUSS
+# define PM_MODEL_FIT_STATUS pmModelFitStatus_SGAUSS
+
+psF64 psImageEllipseContour (psEllipseAxes axes, double xc, double yc, psImage *image);
+
+psF32 PM_MODEL_FUNC (psVector *deriv,
+                     const psVector *params,
+                     const psVector *x)
+{
+    psF32 *PAR = params->data.F32;
+
+    psF32 X  = x->data.F32[0] - PAR[2];
+    psF32 Y  = x->data.F32[1] - PAR[3];
+    psF32 px = PAR[4]*X;
+    psF32 py = PAR[5]*Y;
+    psF32 z  = PS_MAX((0.5*PS_SQR(px) + 0.5*PS_SQR(py) + PAR[6]*X*Y), 1e-8);
+    // note that if z -> 0, dPAR[7] -> -inf
+    // also z^(PAR[7]-1) -> Inf
+
+    psF32 pr = z*PAR[8];
+    psF32 pr3 = pr*pr*pr;
+    psF32 p  = pow(z, PAR[7] - 1.0);
+    psF32 r  = 1.0 / (1 + z*p + pr*pr3);
+    psF32 f  = PAR[1]*r + PAR[0];
+
+    if (deriv != NULL) {
+        // note difference from a pure gaussian: q = params->data.F32[1]*r
+        psF32 t = PAR[1]*r*r;
+        psF32 q = t*(PAR[7]*p + 4*PAR[8]*pr3);
+
+        deriv->data.F32[0] = +1.0;
+        deriv->data.F32[1] = +r;
+        deriv->data.F32[2] = q*(2.0*px*PAR[4] + PAR[6]*Y);
+        deriv->data.F32[3] = q*(2.0*py*PAR[5] + PAR[6]*X);
+        deriv->data.F32[4] = -2.0*q*px*X;
+        deriv->data.F32[5] = -2.0*q*py*Y;
+        deriv->data.F32[6] = -q*X*Y;
+        deriv->data.F32[7] = -2*t*log(z)*z*p;
+        deriv->data.F32[8] = -2*t*4*z*pr3;
+    }
+    return(f);
+}
+
+bool PM_MODEL_LIMITS  (psVector **beta_lim, psVector **params_min, psVector **params_max)
+{
+
+    *beta_lim   = psVectorAlloc (9, PS_TYPE_F32);
+    *params_min = psVectorAlloc (9, PS_TYPE_F32);
+    *params_max = psVectorAlloc (9, PS_TYPE_F32);
+
+    beta_lim[0][0].data.F32[0] = 1000;
+    beta_lim[0][0].data.F32[1] = 10000;
+    beta_lim[0][0].data.F32[2] = 5;
+    beta_lim[0][0].data.F32[3] = 5;
+    beta_lim[0][0].data.F32[4] = 0.5;
+    beta_lim[0][0].data.F32[5] = 0.5;
+    beta_lim[0][0].data.F32[6] = 0.5;
+    beta_lim[0][0].data.F32[7] = 0.5;
+    beta_lim[0][0].data.F32[8] = 0.05;
+
+    params_min[0][0].data.F32[0] = -1000;
+    params_min[0][0].data.F32[1] = 0;
+    params_min[0][0].data.F32[2] = -100;
+    params_min[0][0].data.F32[3] = -100;
+    params_min[0][0].data.F32[4] = 0.01;
+    params_min[0][0].data.F32[5] = 0.01;
+    params_min[0][0].data.F32[6] = -5.0;
+    params_min[0][0].data.F32[7] = 0.5;
+    params_min[0][0].data.F32[8] = 0.001;
+
+    params_max[0][0].data.F32[0] = 1e5;
+    params_max[0][0].data.F32[1] = 1e6;
+    params_max[0][0].data.F32[2] = 1e4;  // this should be set by image dimensions!
+    params_max[0][0].data.F32[3] = 1e4;  // this should be set by image dimensions!
+    params_max[0][0].data.F32[4] = 2.0;
+    params_max[0][0].data.F32[5] = 2.0;
+    params_max[0][0].data.F32[6] = +3.0;
+    params_max[0][0].data.F32[7] = 5.0;
+    params_max[0][0].data.F32[8] = 0.5;
+
+    return (TRUE);
+}
+
+bool PM_MODEL_GUESS  (pmModel *model, pmSource *source)
+{
+
+    pmMoments *sMoments = source->moments;
+    pmPeak    *peak     = source->peak;
+    psF32     *params   = model->params->data.F32;
+
+    psEllipseAxes axes;
+    psEllipseShape shape;
+    psEllipseMoments moments;
+
+    moments.x2 = PS_SQR(sMoments->Sx);
+    moments.y2 = PS_SQR(sMoments->Sy);
+    moments.xy = sMoments->Sxy;
+
+    // solve the math to go from Moments To Shape
+    axes = psEllipseMomentsToAxes(moments);
+    shape = psEllipseAxesToShape(axes);
+
+    params[0] = sMoments->Sky;
+    params[1] = sMoments->Peak - sMoments->Sky;
+    params[2] = peak->x;
+    params[3] = peak->y;
+    params[4] = 1.0 / shape.sx;
+    params[5] = 1.0 / shape.sy;
+    params[6] = shape.sxy;
+
+    # if (0)
+
+        f1 = psImageEllipseContour (axes, peak->x, peak->y, source->pixels);
+    axes.major *= 2.0;
+    axes.minor *= 2.0;
+    f2 = psImageEllipseContour (axes, peak->x, peak->y, source->pixels);
+
+    if (f1 > f2) {
+        params[7] = PS_MIN (3.0, PS_MAX (0.5, log(2.0*(f1/f2) - 1.0) / log(2.0)));
+    } else {
+        params[7] = 0.5;
+    }
+    # endif
+
+    params[7] = 1.8;
+    params[8] = 0.1;
+
+
+    return(true);
+}
+
+psF64 PM_MODEL_FLUX (const psVector *params)
+{
+    float f, norm, z;
+
+    psF32 *PAR = params->data.F32;
+
+    psF64 A1   = PS_SQR(PAR[4]);
+    psF64 A2   = PS_SQR(PAR[5]);
+    psF64 A3   = PS_SQR(PAR[6]);
+    psF64 Area = 2.0 * M_PI / sqrt(A1*A2 - A3);
+    // Area is equivalent to 2 pi sigma^2
+
+    // the area needs to be multiplied by the integral of f(z)
+    norm = 0.0;
+    for (z = 0.005; z < 50; z += 0.01) {
+        psF32 pr = PAR[8]*z;
+        f = 1.0 / (1 + pow(z, PAR[7]) + PS_SQR(PS_SQR(pr)));
+        norm += f;
+    }
+    norm *= 0.01;
+
+    psF64 Flux = PAR[1] * Area * norm;
+
+    return(Flux);
+}
+
+// XXX need to define the radius along the major axis
+// define this function so it never returns Inf or NaN
+// return the radius which yields the requested flux
+psF64 PM_MODEL_RADIUS   (const psVector *params, psF64 flux)
+{
+    psF64 r, z = 0.0, pr, f;
+    psF32 *PAR = params->data.F32;
+
+    psEllipseAxes axes;
+    psEllipseShape shape;
+
+    if (flux <= 0)
+        return (1.0);
+    if (PAR[1] <= 0)
+        return (1.0);
+    if (flux >= PAR[1])
+        return (1.0);
+
+    // convert Sx,Sy,Sxy to major/minor axes
+    shape.sx = 1.0 / PAR[4];
+    shape.sy = 1.0 / PAR[5];
+    shape.sxy = PAR[6];
+
+    axes = psEllipseShapeToAxes (shape);
+    psF64 dr = 1.0 / axes.major;
+    psF64 limit = flux / PAR[1];
+
+    // XXX : we can do this faster with an intelligent starting choice
+    for (r = 0.0; r < 20.0; r += dr) {
+        z = PS_SQR(r);
+        pr = PAR[8]*z;
+        f = 1.0 / (1 + pow(z, PAR[7]) + PS_SQR(PS_SQR(pr)));
+        if (f < limit)
+            break;
+    }
+    psF64 radius = 2.0 * axes.major * sqrt (z);
+    if (isnan(radius)) {
+        fprintf (stderr, "error in code\n");
+    }
+    return (radius);
+}
+
+bool PM_MODEL_FROM_PSF  (pmModel *modelPSF, pmModel *modelFLT, const pmPSF *psf)
+{
+
+    psF32 *out = modelPSF->params->data.F32;
+    psF32 *in  = modelFLT->params->data.F32;
+
+    out[0] = in[0];
+    out[1] = in[1];
+    out[2] = in[2];
+    out[3] = in[3];
+
+    for (int i = 4; i < 9; i++) {
+        psPolynomial2D *poly = psf->params->data[i-4];
+        // XXX: Verify this (from EAM change)
+        //out[i] = Polynomial2DEval_EAM(poly, out[2], out[3]);
+        out[i] = psPolynomial2DEval(poly, out[2], out[3]);
+    }
+    return(true);
+}
+
+bool PM_MODEL_FIT_STATUS  (pmModel *model)
+{
+
+    psF32 dP;
+    bool  status;
+    psEllipseAxes axes;
+    psEllipseShape shape;
+
+    psF32 *PAR  = model->params->data.F32;
+    psF32 *dPAR = model->dparams->data.F32;
+
+    shape.sx = 1.0 / PAR[4];
+    shape.sy = 1.0 / PAR[5];
+    shape.sxy = PAR[6];
+
+    axes = psEllipseShapeToAxes (shape);
+
+    dP = 0;
+    dP += PS_SQR(dPAR[4] / PAR[4]);
+    dP += PS_SQR(dPAR[5] / PAR[5]);
+    dP += PS_SQR(dPAR[7] / PAR[7]);
+    dP = sqrt (dP);
+
+    status = true;
+    status &= (dP < 0.5);
+    status &= (PAR[1] > 0);
+    status &= ((dPAR[1]/PAR[1]) < 0.5);
+    status &= (fabs(PAR[8]) < 0.5);
+    status &= (dPAR[8] < 0.1);
+    status &= (axes.major > 1.41);
+    status &= (axes.minor > 1.41);
+    status &= ((axes.major / axes.minor) < 5.0);
+    status &= (PAR[7] > 0.5);
+
+    if (status)
+        return true;
+    return false;
+}
+
+// measure the flux for the elliptical contour
+psF64 psImageEllipseContour (psEllipseAxes axes, double xc, double yc, psImage *image)
+{
+
+    double t, dt, ct, st, xo, yo, value;
+    int N, Nt, x, y;
+
+    // choose dt to uniformly divide contour, with ~1 pix spacing at most
+    dt = asin (1 / axes.minor);
+    Nt = (int)(2*M_PI / dt) + 1;
+    dt = 2*M_PI / Nt;
+
+    ct = cos(axes.theta);
+    st = sin(axes.theta);
+    xo = xc - image->col0;
+    yo = yc - image->row0;
+
+    psVector *contour = psVectorAlloc (Nt, PS_TYPE_F32);
+    contour->n = contour->nalloc;
+    for (t = 0, N = 0; (t < 2*M_PI) && (N < Nt); t += dt) {
+        x = ct*axes.major*cos(t) + st*axes.minor*sin(t) + xo;
+        y = ct*axes.minor*sin(t) + st*axes.major*cos(t) + yo;
+        value = p_psImageGetElementF64(image, x, y);
+        if (isfinite(value)) {
+            contour->data.F32[N] = value;
+            N++;
+        }
+    }
+    contour->n = N;
+    // accept every pixel: double counting is not so problematic here...
+
+    psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+    psVectorStats (stats, contour, NULL, NULL, 0);
+    value = stats->sampleMedian;
+
+    psFree (stats);
+    psFree (contour);
+
+    return (value);
+}
+
+// XXX EAM : test version using flux contours to guess slope
+bool PM_MODEL_GUESS_HARD (pmModel *model, pmSource *source)
+{
+
+    pmMoments *sMoments = source->moments;
+    pmPeak    *peak     = source->peak;
+    psF32     *params   = model->params->data.F32;
+    float f1, f2;
+
+    psEllipseAxes axes;
+    psEllipseShape shape;
+    psEllipseMoments moments;
+
+    moments.x2 = PS_SQR(sMoments->Sx);
+    moments.y2 = PS_SQR(sMoments->Sy);
+    moments.xy = sMoments->Sxy;
+
+    // solve the math to go from Moments To Shape
+    axes = psEllipseMomentsToAxes(moments);
+    shape = psEllipseAxesToShape(axes);
+
+    params[0] = sMoments->Sky;
+    params[1] = sMoments->Peak - sMoments->Sky;
+    params[2] = peak->x;
+    params[3] = peak->y;
+    params[4] = 1.0 / shape.sx;
+    params[5] = 1.0 / shape.sy;
+    params[6] = shape.sxy;
+
+    f1 = psImageEllipseContour (axes, peak->x, peak->y, source->pixels);
+    axes.major *= 2.0;
+    axes.minor *= 2.0;
+    f2 = psImageEllipseContour (axes, peak->x, peak->y, source->pixels);
+
+    if (f1 > f2) {
+        params[7] = PS_MIN (3.0, PS_MAX (0.5, log(2.0*(f1/f2) - 1.0) / log(2.0)));
+    } else {
+        params[7] = 0.5;
+    }
+    params[8] = 0.1;
+
+    return(true);
+}
+
+# undef PM_MODEL_FUNC
+# undef PM_MODEL_FLUX
+# undef PM_MODEL_GUESS
+# undef PM_MODEL_LIMITS
+# undef PM_MODEL_RADIUS
+# undef PM_MODEL_FROM_PSF
+# undef PM_MODEL_FIT_STATUS
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_TGAUSS.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_TGAUSS.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_TGAUSS.c	(revision 22158)
@@ -0,0 +1,202 @@
+/******************************************************************************
+ * this file defines the TGAUSS source shape model (XXX need a better name!).  Note that these
+ * model functions are loaded by pmModelGroup.c using 'include', and thus need no 'include'
+ * statements of their own.  The models use a psVector to represent the set of parameters, with
+ * the sequence used to specify the meaning of the parameter.  The meaning of the parameters
+ * may thus vary depending on the specifics of the model.  All models which are used a PSF
+ * representations share a few parameters, for which # define names are listed in pmModel.h:
+
+   power-law with fixed slope and fitted amplitude
+   1 / (1 + z + kz^2.2)
+
+   * PM_PAR_SKY 0   - local sky : note that this is unused and may be dropped in the future
+   * PM_PAR_I0 1    - central intensity
+   * PM_PAR_XPOS 2  - X center of object
+   * PM_PAR_YPOS 3  - Y center of object
+   * PM_PAR_SXX 4   - X^2 term of elliptical contour (sqrt(2) / SigmaX)
+   * PM_PAR_SYY 5   - Y^2 term of elliptical contour (sqrt(2) / SigmaY)
+   * PM_PAR_SXY 6   - X*Y term of elliptical contour
+   * PM_PAR_7   7   - amplitude of high-order component (k)
+   *****************************************************************************/
+
+/***
+    XXXX the model in this file needs to be tested more carefully.
+    fix up the code to follow conventions in the other model function files.
+***/
+
+XXX broken code
+
+# define PM_MODEL_FUNC       pmModelFunc_TGAUSS
+# define PM_MODEL_FLUX       pmModelFlux_TGAUSS
+# define PM_MODEL_GUESS      pmModelGuess_TGAUSS
+# define PM_MODEL_LIMITS     pmModelLimits_TGAUSS
+# define PM_MODEL_RADIUS     pmModelRadius_TGAUSS
+# define PM_MODEL_FROM_PSF   pmModelFromPSF_TGAUSS
+# define PM_MODEL_FIT_STATUS pmModelFitStatus_TGAUSS
+
+psF64 PS_MODEL_FUNC (psVector *deriv,
+                     const psVector *params,
+                     const psVector *x)
+{
+    psF32 *PAR = params->data.F32;
+
+    psF32 X  = x->data.F32[0] - PAR[2];
+    psF32 Y  = x->data.F32[1] - PAR[3];
+    psF32 px = PAR[4]*X;
+    psF32 py = PAR[5]*Y;
+    psF32 z  = 0.5*PS_SQR(px) + 0.5*PS_SQR(py) + PAR[6]*X*Y;
+
+    psF32 p  = pow(z, 1.2);
+    psF32 r  = 1.0 / (1 + z + PAR[7]*z*p);
+    psF32 f  = PAR[1]*r + PAR[0];
+
+    if (deriv != NULL) {
+        // note difference from a pure gaussian: q = params->data.F32[1]*r
+        psF32 t = PAR[1]*r*r;
+        psF32 q = t*(1 + PAR[7]*2.2*p);
+
+        deriv->data.F32[0] = +1.0;
+        deriv->data.F32[1] = +r;
+        deriv->data.F32[2] = q*(2.0*px*PAR[4] + PAR[6]*Y);
+        deriv->data.F32[3] = q*(2.0*py*PAR[5] + PAR[6]*X);
+        deriv->data.F32[4] = -2.0*q*px*X;
+        deriv->data.F32[5] = -2.0*q*py*Y;
+        deriv->data.F32[6] = -q*X*Y;
+        deriv->data.F32[7] = -t*z*p;
+    }
+    return(f);
+}
+
+bool PM_MODEL_LIMITS  (psVector **beta_lim, psVector **params_min, psVector **params_max)
+{
+
+    *beta_lim   = psVectorAlloc (8, PS_TYPE_F32);
+    *params_min = psVectorAlloc (8, PS_TYPE_F32);
+    *params_max = psVectorAlloc (8, PS_TYPE_F32);
+
+    beta_lim[0][0].data.F32[PM_PAR_SKY] = 1000;
+    beta_lim[0][0].data.F32[PM_PAR_I0] = 3e6;
+    beta_lim[0][0].data.F32[PM_PAR_XPOS] = 5;
+    beta_lim[0][0].data.F32[PM_PAR_YPOS] = 5;
+    beta_lim[0][0].data.F32[PM_PAR_SXX] = 0.5;
+    beta_lim[0][0].data.F32[PM_PAR_SYY] = 0.5;
+    beta_lim[0][0].data.F32[PM_PAR_SXY] = 0.5;
+    beta_lim[0][0].data.F32[PM_PAR_7] = 0.5;
+
+    params_min[0][0].data.F32[PM_PAR_SKY] = -1000;
+    params_min[0][0].data.F32[PM_PAR_I0] = 0;
+    params_min[0][0].data.F32[PM_PAR_XPOS] = -100;
+    params_min[0][0].data.F32[PM_PAR_YPOS] = -100;
+    params_min[0][0].data.F32[PM_PAR_SXX] = 0.5;
+    params_min[0][0].data.F32[PM_PAR_SYY] = 0.5;
+    params_min[0][0].data.F32[PM_PAR_SXY] = -5.0;
+    params_min[0][0].data.F32[PM_PAR_7] = 0.1;
+
+    params_max[0][0].data.F32[PM_PAR_SKY] = 1e5;
+    params_max[0][0].data.F32[PM_PAR_I0] = 1e8;
+    params_max[0][0].data.F32[PM_PAR_XPOS] = 1e4;  // this should be set by image dimensions!
+    params_max[0][0].data.F32[PM_PAR_YPOS] = 1e4;  // this should be set by image dimensions!
+    params_max[0][0].data.F32[PM_PAR_SXX] = 100.0;
+    params_max[0][0].data.F32[PM_PAR_SYY] = 100.0;
+    params_max[0][0].data.F32[PM_PAR_SXY] = +5.0;
+    params_max[0][0].data.F32[PM_PAR_7] = 10.0;
+
+    return (TRUE);
+}
+
+bool PS_MODEL_GUESS  (psModel *model, psSource *source)
+{
+
+    psVector *params = model->params;
+
+    params->data.F32[0] = source->moments->Sky;
+    params->data.F32[1] = source->peak->counts - source->moments->Sky;
+    params->data.F32[2] = source->moments->x;
+    params->data.F32[3] = source->moments->y;
+    params->data.F32[4] = 1.0/source->moments->Sx;
+    params->data.F32[5] = 1.0/source->moments->Sy;
+    // params->data.F32[6] = source->moments->Sxy;
+    params->data.F32[6] = 0.0;
+    params->data.F32[7] = 5.0;
+    return(true);
+}
+
+psF64 PS_MODEL_FLUX (const psVector *params)
+{
+    psF64 A1   = 1 / PS_SQR(params->data.F32[4]);
+    psF64 A2   = 1 / PS_SQR(params->data.F32[5]);
+    psF64 A3   = params->data.F32[6];
+    psF64 Area = 2.0 * M_PI / sqrt(A1*A2 - PS_SQR(A3));
+    // Area is equivalent to 2 pi sigma^2
+
+    psF64 Flux = params->data.F32[1] * Area;
+
+    return(Flux);
+}
+
+// define this function so it never returns Inf or NaN
+// return the radius which yields the requested flux
+psF64 PS_MODEL_RADIUS   (const psVector *params, psF64 flux)
+{
+    if (flux <= 0)
+        return (1.0);
+    if (params->data.F32[1] <= 0)
+        return (1.0);
+    if (flux >= params->data.F32[1])
+        return (1.0);
+
+    psF64 sigma  = sqrt(2.0) * hypot (1.0 / params->data.F32[4], 1.0 / params->data.F32[5]);
+    psF64 radius = sigma * sqrt (2.0 * log(params->data.F32[1] / flux));
+    if (isnan(radius)) {
+        fprintf (stderr, "error in code\n");
+    }
+    return (radius);
+}
+
+bool PS_MODEL_FROM_PSF  (psModel *modelPSF, psModel *modelFLT, const pmPSF *psf)
+{
+
+    psF32 *out = modelPSF->params->data.F32;
+    psF32 *in  = modelFLT->params->data.F32;
+
+    out[0] = in[0];
+    out[1] = in[1];
+    out[2] = in[2];
+    out[3] = in[3];
+
+    for (int i = 4; i < 8; i++) {
+        psPolynomial2D *poly = psf->params->data[i-4];
+        out[i] = Polynomial2DEval (poly, out[2], out[3]);
+    }
+    return(true);
+}
+
+bool PM_MODEL_FIT_STATUS (pmModel *model)
+{
+
+    psF32 dP;
+    bool  status;
+
+    psF32 *PAR  = model->params->data.F32;
+    psF32 *dPAR = model->dparams->data.F32;
+
+    dP = 0;
+    dP += PS_SQR(dPAR[PM_PAR_SXX] / PAR[PM_PAR_SXX]);
+    dP += PS_SQR(dPAR[PM_PAR_SYY] / PAR[PM_PAR_SYY]);
+    dP = sqrt (dP);
+
+    status = true;
+    status &= (dP < 0.5);
+    status &= (PAR[PM_PAR_I0] > 0);
+    status &= ((dPAR[PM_PAR_I0]/PAR[PM_PAR_I0]) < 0.5);
+
+    return status;
+}
+
+# undef PM_MODEL_FUNC
+# undef PM_MODEL_FLUX
+# undef PM_MODEL_GUESS
+# undef PM_MODEL_LIMITS
+# undef PM_MODEL_RADIUS
+# undef PM_MODEL_FROM_PSF
+# undef PM_MODEL_FIT_STATUS
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_WAUSS.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_WAUSS.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_WAUSS.c	(revision 22158)
@@ -0,0 +1,198 @@
+/******************************************************************************
+ * this file defines the WAUSS source shape model (XXX need a better name!).  Note that these
+ * model functions are loaded by pmModelGroup.c using 'include', and thus need no 'include'
+ * statements of their own.  The models use a psVector to represent the set of parameters, with
+ * the sequence used to specify the meaning of the parameter.  The meaning of the parameters
+ * may thus vary depending on the specifics of the model.  All models which are used a PSF
+ * representations share a few parameters, for which # define names are listed in pmModel.h:
+
+   power-law with fitted linear term
+   1 / (1 + Az + Bz^2 + z^3/6)
+
+   * PM_PAR_SKY 0   - local sky : note that this is unused and may be dropped in the future
+   * PM_PAR_I0 1    - central intensity
+   * PM_PAR_XPOS 2  - X center of object
+   * PM_PAR_YPOS 3  - Y center of object
+   * PM_PAR_SXX 4   - X^2 term of elliptical contour (SigmaX / sqrt(2))
+   * PM_PAR_SYY 5   - Y^2 term of elliptical contour (SigmaY / sqrt(2))
+   * PM_PAR_SXY 6   - X*Y term of elliptical contour
+   * PM_PAR_7   7   - amplitude of the linear component (A)
+   * PM_PAR_8   8   - amplitude of the quadratic component (B)
+   *****************************************************************************/
+
+/***
+    XXXX the model in this file needs to be tested more carefully.
+    fix up the code to follow conventions in the other model function files.
+***/
+
+XXX broken code
+
+# define PM_MODEL_FUNC       pmModelFunc_WAUSS
+# define PM_MODEL_FLUX       pmModelFlux_WAUSS
+# define PM_MODEL_GUESS      pmModelGuess_WAUSS
+# define PM_MODEL_LIMITS     pmModelLimits_WAUSS
+# define PM_MODEL_RADIUS     pmModelRadius_WAUSS
+# define PM_MODEL_FROM_PSF   pmModelFromPSF_WAUSS
+# define PM_MODEL_FIT_STATUS pmModelFitStatus_WAUSS
+
+psF64 PS_MODEL_FUNC (psVector *deriv,
+                     const psVector *params,
+                     const psVector *x)
+{
+    psF32 X = x->data.F32[0] - params->data.F32[2];
+    psF32 Y = x->data.F32[1] - params->data.F32[2];
+    psF32 px = params->data.F32[4]*X;
+    psF32 py = params->data.F32[5]*Y;
+    psF32 z = 0.5*PS_SQR(px) + 0.5*PS_SQR(py) + params->data.F32[6]*X*Y;
+    psF32 t = 0.5*z*z*(1.0 + params->data.F32[8]*z/3.0);
+    psF32 r = 1.0 / (1.0 + z + params->data.F32[7]*t); /* exp (-Z) */
+    psF32 f = params->data.F32[1]*r + params->data.F32[0];
+
+    if (deriv != NULL) {
+        // note difference from gaussian: q = params->data.F32[1]*r
+        psF32 q = params->data.F32[1]*r*r*(1.0 + params->data.F32[7]*z*(1.0 + params->data.F32[8]*z/2.0));
+        deriv->data.F32[0] = +1.0;
+        deriv->data.F32[1] = +r;
+        deriv->data.F32[2] = q*(2.0*px*params->data.F32[4] + params->data.F32[6]*Y);
+        deriv->data.F32[3] = q*(2.0*py*params->data.F32[5] + params->data.F32[6]*X);
+        deriv->data.F32[4] = -2.0*q*px*X;
+        deriv->data.F32[5] = -2.0*q*py*Y;
+        deriv->data.F32[6] = -q*X*Y;
+        deriv->data.F32[7] = -100.0*params->data.F32[1]*r*r*t;
+        deriv->data.F32[8] = -100.0*params->data.F32[1]*r*r*params->data.F32[7]*(z*z*z)/6.0;
+        // The values of 100 dampen the swing of params->data.F32[7,8] */
+    }
+    return(f);
+}
+
+bool PM_MODEL_LIMITS  (psVector **beta_lim, psVector **params_min, psVector **params_max)
+{
+
+    *beta_lim   = psVectorAlloc (8, PS_TYPE_F32);
+    *params_min = psVectorAlloc (8, PS_TYPE_F32);
+    *params_max = psVectorAlloc (8, PS_TYPE_F32);
+
+    beta_lim[0][0].data.F32[PM_PAR_SKY] = 1000;
+    beta_lim[0][0].data.F32[PM_PAR_I0] = 3e6;
+    beta_lim[0][0].data.F32[PM_PAR_XPOS] = 5;
+    beta_lim[0][0].data.F32[PM_PAR_YPOS] = 5;
+    beta_lim[0][0].data.F32[PM_PAR_SXX] = 0.5;
+    beta_lim[0][0].data.F32[PM_PAR_SYY] = 0.5;
+    beta_lim[0][0].data.F32[PM_PAR_SXY] = 0.5;
+    beta_lim[0][0].data.F32[PM_PAR_7] = 0.5;
+
+    params_min[0][0].data.F32[PM_PAR_SKY] = -1000;
+    params_min[0][0].data.F32[PM_PAR_I0] = 0;
+    params_min[0][0].data.F32[PM_PAR_XPOS] = -100;
+    params_min[0][0].data.F32[PM_PAR_YPOS] = -100;
+    params_min[0][0].data.F32[PM_PAR_SXX] = 0.5;
+    params_min[0][0].data.F32[PM_PAR_SYY] = 0.5;
+    params_min[0][0].data.F32[PM_PAR_SXY] = -5.0;
+    params_min[0][0].data.F32[PM_PAR_7] = 0.1;
+
+    params_max[0][0].data.F32[PM_PAR_SKY] = 1e5;
+    params_max[0][0].data.F32[PM_PAR_I0] = 1e8;
+    params_max[0][0].data.F32[PM_PAR_XPOS] = 1e4;  // this should be set by image dimensions!
+    params_max[0][0].data.F32[PM_PAR_YPOS] = 1e4;  // this should be set by image dimensions!
+    params_max[0][0].data.F32[PM_PAR_SXX] = 100.0;
+    params_max[0][0].data.F32[PM_PAR_SYY] = 100.0;
+    params_max[0][0].data.F32[PM_PAR_SXY] = +5.0;
+    params_max[0][0].data.F32[PM_PAR_7] = 10.0;
+
+    return (TRUE);
+}
+
+bool PS_MODEL_GUESS  (psModel *model, psSource *source)
+{
+
+    psVector *params = model->params;
+
+    params->data.F32[0] = source->moments->Sky;
+    params->data.F32[1] = source->peak->counts - source->moments->Sky;
+    params->data.F32[2] = source->moments->x;
+    params->data.F32[3] = source->moments->y;
+    params->data.F32[4] = sqrt(2.0) / source->moments->Sx;
+    params->data.F32[5] = sqrt(2.0) / source->moments->Sy;
+    params->data.F32[6] = source->moments->Sxy;
+    // XXX: What are these?
+    // params->data.F32[7] = B2;
+    // params->data.F32[8] = B3;
+    return(true);
+}
+
+// this is probably wrong since it uses the gauss integral 2 pi sigma^2
+psF64 PS_MODEL_FLUX (const psVector *params)
+{
+    psF64 A1   = 1 / PS_SQR(params->data.F32[4]);
+    psF64 A2   = 1 / PS_SQR(params->data.F32[5]);
+    psF64 A3   = params->data.F32[6];
+    psF64 Area = 2.0 * M_PI / sqrt(A1*A2 - PS_SQR(A3));
+    // Area is equivalent to 2 pi sigma^2
+
+    psF64 Flux = params->data.F32[1] * Area;
+
+    return(Flux);
+}
+
+// return the radius which yields the requested flux
+psF64 PS_MODEL_RADIUS   (const psVector *params, psF64 flux)
+{
+    if (flux <= 0)
+        return (1.0);
+    if (params->data.F32[1] <= 0)
+        return (1.0);
+    if (flux >= params->data.F32[1] <= 0)
+        return (1.0);
+
+    psF64 sigma  = sqrt(2.0) * hypot (1.0 / params->data.F32[4], 1.0 / params->data.F32[5]);
+    psF64 radius = sigma * sqrt (2.0 * log(params->data.F32[1] / flux));
+    return (radius);
+}
+
+bool PS_MODEL_FROM_PSF  (psModel *modelPSF, psModel *modelFLT, const pmPSF *psf)
+{
+
+    psF32 *out = modelPSF->params->data.F32;
+    psF32 *in  = modelFLT->params->data.F32;
+
+    out[0] = in[0];
+    out[1] = in[1];
+    out[2] = in[2];
+    out[3] = in[3];
+
+    for (int i = 4; i < 9; i++) {
+        psPolynomial2D *poly = psf->params->data[i-4];
+        out[i] = Polynomial2DEval (poly, out[2], out[3]);
+    }
+    return(true);
+}
+
+bool PM_MODEL_FIT_STATUS (pmModel *model)
+{
+
+    psF32 dP;
+    bool  status;
+
+    psF32 *PAR  = model->params->data.F32;
+    psF32 *dPAR = model->dparams->data.F32;
+
+    dP = 0;
+    dP += PS_SQR(dPAR[PM_PAR_SXX] / PAR[PM_PAR_SXX]);
+    dP += PS_SQR(dPAR[PM_PAR_SYY] / PAR[PM_PAR_SYY]);
+    dP = sqrt (dP);
+
+    status = true;
+    status &= (dP < 0.5);
+    status &= (PAR[PM_PAR_I0] > 0);
+    status &= ((dPAR[PM_PAR_I0]/PAR[PM_PAR_I0]) < 0.5);
+
+    return status;
+}
+
+# undef PM_MODEL_FUNC
+# undef PM_MODEL_FLUX
+# undef PM_MODEL_GUESS
+# undef PM_MODEL_LIMITS
+# undef PM_MODEL_RADIUS
+# undef PM_MODEL_FROM_PSF
+# undef PM_MODEL_FIT_STATUS
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_ZGAUSS.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_ZGAUSS.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/models/pmModel_ZGAUSS.c	(revision 22158)
@@ -0,0 +1,251 @@
+/******************************************************************************
+ * this file defines the ZGAUSS source shape model (XXX need a better name!).  Note that these
+ * model functions are loaded by pmModelGroup.c using 'include', and thus need no 'include'
+ * statements of their own.  The models use a psVector to represent the set of parameters, with
+ * the sequence used to specify the meaning of the parameter.  The meaning of the parameters
+ * may thus vary depending on the specifics of the model.  All models which are used a PSF
+ * representations share a few parameters, for which # define names are listed in pmModel.h:
+
+   power-law with fitted slope and tidal cutoff
+   1 / (1 + z^N + (Az)^4)
+
+   * PM_PAR_SKY 0   - local sky : note that this is unused and may be dropped in the future
+   * PM_PAR_I0 1    - central intensity
+   * PM_PAR_XPOS 2  - X center of object
+   * PM_PAR_YPOS 3  - Y center of object
+   * PM_PAR_SXX 4   - X^2 term of elliptical contour (sqrt(2) / SigmaX)
+   * PM_PAR_SYY 5   - Y^2 term of elliptical contour (sqrt(2) / SigmaY)
+   * PM_PAR_SXY 6   - X*Y term of elliptical contour
+   * PM_PAR_7   7   - slope of power-law component (N)
+   *****************************************************************************/
+
+/***
+    XXXX the model in this file needs to be tested more carefully.
+    fix up the code to follow conventions in the other model function files.
+***/
+
+XXX broken code
+
+# define PM_MODEL_FUNC       pmModelFunc_ZGAUSS
+# define PM_MODEL_FLUX       pmModelFlux_ZGAUSS
+# define PM_MODEL_GUESS      pmModelGuess_ZGAUSS
+# define PM_MODEL_LIMITS     pmModelLimits_ZGAUSS
+# define PM_MODEL_RADIUS     pmModelRadius_ZGAUSS
+# define PM_MODEL_FROM_PSF   pmModelFromPSF_ZGAUSS
+# define PM_MODEL_FIT_STATUS pmModelFitStatus_ZGAUSS
+
+# define PAR8 0.1
+
+psF64 PS_MODEL_FUNC (psVector *deriv,
+                     const psVector *params,
+                     const psVector *x)
+{
+    psF32 *PAR = params->data.F32;
+
+    psF32 X  = x->data.F32[0] - PAR[2];
+    psF32 Y  = x->data.F32[1] - PAR[3];
+    psF32 px = PAR[4]*X;
+    psF32 py = PAR[5]*Y;
+    psF32 z  = 0.5*PS_SQR(px) + 0.5*PS_SQR(py) + PAR[6]*X*Y;
+
+    psF32 pr = PAR8*z;
+    psF32 p  = pow(z, PAR[7] - 1.0);
+    psF32 r  = 1.0 / (1 + z*p + SQ(SQ(pr)));
+    psF32 f  = PAR[1]*r + PAR[0];
+
+    if (deriv != NULL) {
+        // note difference from a pure gaussian: q = params->data.F32[1]*r
+        psF32 t = PAR[1]*r*r;
+        psF32 q = t*(PAR[7]*p + 4*PAR8*pr*pr*pr);
+
+        deriv->data.F32[0] = +1.0;
+        deriv->data.F32[1] = +r;
+        deriv->data.F32[2] = q*(2.0*px*PAR[4] + PAR[6]*Y);
+        deriv->data.F32[3] = q*(2.0*py*PAR[5] + PAR[6]*X);
+        deriv->data.F32[4] = -q*px*X;
+        deriv->data.F32[5] = -q*py*Y;
+        deriv->data.F32[6] = -q*X*Y;
+        deriv->data.F32[7] = -t*log(z)*z*p;
+    }
+    return(f);
+}
+
+bool PM_MODEL_LIMITS  (psVector **beta_lim, psVector **params_min, psVector **params_max)
+{
+
+    *beta_lim   = psVectorAlloc (8, PS_TYPE_F32);
+    *params_min = psVectorAlloc (8, PS_TYPE_F32);
+    *params_max = psVectorAlloc (8, PS_TYPE_F32);
+
+    beta_lim[0][0].data.F32[PM_PAR_SKY] = 1000;
+    beta_lim[0][0].data.F32[PM_PAR_I0] = 3e6;
+    beta_lim[0][0].data.F32[PM_PAR_XPOS] = 5;
+    beta_lim[0][0].data.F32[PM_PAR_YPOS] = 5;
+    beta_lim[0][0].data.F32[PM_PAR_SXX] = 0.5;
+    beta_lim[0][0].data.F32[PM_PAR_SYY] = 0.5;
+    beta_lim[0][0].data.F32[PM_PAR_SXY] = 0.5;
+    beta_lim[0][0].data.F32[PM_PAR_7] = 0.5;
+
+    params_min[0][0].data.F32[PM_PAR_SKY] = -1000;
+    params_min[0][0].data.F32[PM_PAR_I0] = 0;
+    params_min[0][0].data.F32[PM_PAR_XPOS] = -100;
+    params_min[0][0].data.F32[PM_PAR_YPOS] = -100;
+    params_min[0][0].data.F32[PM_PAR_SXX] = 0.5;
+    params_min[0][0].data.F32[PM_PAR_SYY] = 0.5;
+    params_min[0][0].data.F32[PM_PAR_SXY] = -5.0;
+    params_min[0][0].data.F32[PM_PAR_7] = 0.1;
+
+    params_max[0][0].data.F32[PM_PAR_SKY] = 1e5;
+    params_max[0][0].data.F32[PM_PAR_I0] = 1e8;
+    params_max[0][0].data.F32[PM_PAR_XPOS] = 1e4;  // this should be set by image dimensions!
+    params_max[0][0].data.F32[PM_PAR_YPOS] = 1e4;  // this should be set by image dimensions!
+    params_max[0][0].data.F32[PM_PAR_SXX] = 100.0;
+    params_max[0][0].data.F32[PM_PAR_SYY] = 100.0;
+    params_max[0][0].data.F32[PM_PAR_SXY] = +5.0;
+    params_max[0][0].data.F32[PM_PAR_7] = 10.0;
+
+    return (TRUE);
+}
+
+bool PS_MODEL_GUESS  (psModel *model, psSource *source)
+{
+
+    psVector *params = model->params;
+
+    psEllipseAxes axes;
+    psEllipseShape shape;
+    psEllipseMoments moments;
+
+    moments.x2 = PS_SQR(source->moments->Sx);
+    moments.y2 = PS_SQR(source->moments->Sy);
+    moments.xy = source->moments->Sxy;
+
+    axes = psEllipseMomentsToAxes(moments);
+    shape = psEllipseAxesToShape(axes);
+
+    params->data.F32[0] = source->moments->Sky;
+    params->data.F32[1] = source->peak->counts - source->moments->Sky;
+    params->data.F32[2] = source->moments->x;
+    params->data.F32[3] = source->moments->y;
+    params->data.F32[4] = 1.0 / shape.sx;
+    params->data.F32[5] = 1.0 / shape.sy;
+    params->data.F32[6] = shape.sxy;
+    params->data.F32[7] = 1.9;
+    return(true);
+}
+
+psF64 PS_MODEL_FLUX (const psVector *params)
+{
+    float f, norm, z;
+
+    psF32 *PAR = params->data.F32;
+
+    psF64 A1   = PS_SQR(PAR[4]);
+    psF64 A2   = PS_SQR(PAR[5]);
+    psF64 A3   = PS_SQR(PAR[6]);
+    psF64 Area = 2.0 * M_PI / sqrt(A1*A2 - A3);
+    // Area is equivalent to 2 pi sigma^2
+
+    // the area needs to be multiplied by the integral of f(z)
+    norm = 0.0;
+    psF32 pr = PAR8*z;
+    for (z = 0.005; z < 50; z += 0.01) {
+        f = 1.0 / (1 + pow(z, PAR[7]) + SQ(SQ(pr)));
+        norm += f;
+    }
+    norm *= 0.01;
+
+    psF64 Flux = PAR[1] * Area * norm;
+
+    return(Flux);
+}
+
+// XXX need to define the radius along the major axis
+// define this function so it never returns Inf or NaN
+// return the radius which yields the requested flux
+psF64 PS_MODEL_RADIUS   (const psVector *params, psF64 flux)
+{
+    psF64 r, z, pr, f;
+    psF32 *PAR = params->data.F32;
+
+    psEllipseAxes axes;
+    psEllipseShape shape;
+
+    if (flux <= 0)
+        return (1.0);
+    if (PAR[1] <= 0)
+        return (1.0);
+    if (flux >= PAR[1])
+        return (1.0);
+
+    // convert Sx,Sy,Sxy to major/minor axes
+    shape.sx = 1.0 / PAR[4];
+    shape.sy = 1.0 / PAR[5];
+    shape.sxy = PAR[6];
+
+    axes = psEllipseShapeToAxes (shape);
+    psF64 dr = 1.0 / axes.major;
+    psF64 limit = flux / PAR[1];
+
+    // XXX : we can do this faster with an intelligent starting choice
+    for (r = 0.0; r < 20.0; r += dr) {
+        z = SQ(r);
+        pr = PAR8*z;
+        f = 1.0 / (1 + pow(z, PAR[7]) + SQ(SQ(pr)));
+        if (f < limit)
+            break;
+    }
+    psF64 radius = 2.0 * axes.major * sqrt (z);
+    if (isnan(radius)) {
+        fprintf (stderr, "error in code\n");
+    }
+    return (radius);
+}
+
+bool PS_MODEL_FROM_PSF  (psModel *modelPSF, psModel *modelFLT, const pmPSF *psf)
+{
+
+    psF32 *out = modelPSF->params->data.F32;
+    psF32 *in  = modelFLT->params->data.F32;
+
+    out[0] = in[0];
+    out[1] = in[1];
+    out[2] = in[2];
+    out[3] = in[3];
+
+    for (int i = 4; i < 8; i++) {
+        psPolynomial2D *poly = psf->params->data[i-4];
+        out[i] = Polynomial2DEval (poly, out[2], out[3]);
+    }
+    return(true);
+}
+
+bool PM_MODEL_FIT_STATUS (pmModel *model)
+{
+
+    psF32 dP;
+    bool  status;
+
+    psF32 *PAR  = model->params->data.F32;
+    psF32 *dPAR = model->dparams->data.F32;
+
+    dP = 0;
+    dP += PS_SQR(dPAR[PM_PAR_SXX] / PAR[PM_PAR_SXX]);
+    dP += PS_SQR(dPAR[PM_PAR_SYY] / PAR[PM_PAR_SYY]);
+    dP = sqrt (dP);
+
+    status = true;
+    status &= (dP < 0.5);
+    status &= (PAR[PM_PAR_I0] > 0);
+    status &= ((dPAR[PM_PAR_I0]/PAR[PM_PAR_I0]) < 0.5);
+
+    return status;
+}
+
+# undef PM_MODEL_FUNC
+# undef PM_MODEL_FLUX
+# undef PM_MODEL_GUESS
+# undef PM_MODEL_LIMITS
+# undef PM_MODEL_RADIUS
+# undef PM_MODEL_FROM_PSF
+# undef PM_MODEL_FIT_STATUS
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmDetections.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmDetections.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmDetections.c	(revision 22158)
@@ -0,0 +1,44 @@
+/* @file  pmDetections.c
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.1.2.1 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-20 23:08:03 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <strings.h>
+#include <pslib.h>
+#include "pmDetections.h"
+
+void pmDetectionsFree (pmDetections *detections) {
+
+  if (!detections) return;
+
+  psFree (detections->footprints);
+  psFree (detections->peaks);
+  psFree (detections->oldPeaks);
+  return;
+}
+
+// generate a pmDetections container with empty (allocated) footprints and peaks containers
+pmDetections *pmDetectionsAlloc() {
+
+    pmDetections *detections = (pmDetections *)psAlloc(sizeof(pmDetections));
+    psMemSetDeallocator(detections, (psFreeFunc) pmDetectionsFree);
+
+    detections->footprints = NULL;
+    detections->peaks      = NULL;
+    detections->oldPeaks   = NULL;
+    detections->last       = 0;
+
+    return (detections);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmDetections.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmDetections.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmDetections.h	(revision 22158)
@@ -0,0 +1,31 @@
+/* @file  pmDetections.h
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.1.2.1 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-20 23:08:03 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+# ifndef PM_DETECTIONS_H
+# define PM_DETECTIONS_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+/** pmDetections structure
+ *
+ * A strcture to carry the combined footprint and peak information
+ *
+ */
+typedef struct {
+  psArray *footprints;	      // collection of footprints in the image
+  psArray *peaks;	      // collection of all peaks contained by the footprints
+  psArray *oldPeaks;	      // collection of all peaks previously found
+  int last;
+} pmDetections;
+
+pmDetections *pmDetectionsAlloc ();
+
+/// @}
+# endif /* PM_DETECTIONS_H */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprint.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprint.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprint.c	(revision 22158)
@@ -0,0 +1,186 @@
+/* @file  pmFootprint.c
+ * low-level pmFootprint functions
+ *
+ * @author RHL, Princeton & IfA; EAM, IfA
+ *
+ * @version $Revision: 1.1.2.1 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-20 23:08:03 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <strings.h>
+#include <pslib.h>
+#include "pmPeaks.h"
+#include "pmSpan.h"
+#include "pmFootprint.h"
+
+static void footprintFree(pmFootprint *tmp)
+{
+   if (!tmp) {
+        return;
+   }
+
+   psTrace("psModules.objects", 5, "---- begin ----\n");
+
+   psFree(tmp->spans);
+   psFree(tmp->peaks);
+
+   psTrace("psModules.objects", 5, "---- end ----\n");
+}
+
+/*
+ * pmFootprintAlloc(): Allocate the pmFootprint structure to NULL.
+ */
+pmFootprint *pmFootprintAlloc(int nspan, // number of spans expected in footprint
+			      const psImage *image) // region footprint lives in
+{
+    psTrace("psModules.objects", 5, "---- begin ----\n");
+
+    static int id = 1;
+    pmFootprint *footprint = (pmFootprint *)psAlloc(sizeof(pmFootprint));
+    *(int *)&footprint->id = id++;
+    psMemSetDeallocator(footprint, (psFreeFunc) footprintFree);
+
+    footprint->normalized = false;
+
+    assert(nspan >= 0);
+    footprint->npix = 0;
+    footprint->spans = psArrayAllocEmpty(nspan);
+    footprint->peaks = psArrayAlloc(0);
+
+    footprint->bbox.x0 = footprint->bbox.y0 = 0;
+    footprint->bbox.x1 = footprint->bbox.y1 = -1;
+
+    if (image == NULL) {
+	footprint->region.x0 = footprint->region.y0 = 0;
+	footprint->region.x1 = footprint->region.y1 = -1;
+    } else {
+	footprint->region.x0 = image->col0;
+	footprint->region.x1 = image->col0 + image->numCols - 1;
+	footprint->region.y0 = image->row0;
+	footprint->region.y1 = image->row0 + image->numRows - 1;
+    }
+
+    psTrace("psModules.objects", 5, "---- end ----\n");
+    return(footprint);
+}
+
+bool pmFootprintTest(const psPtr ptr) {
+    return (psMemGetDeallocator(ptr) == (psFreeFunc)footprintFree);
+}
+
+pmFootprint *pmFootprintNormalize(pmFootprint *fp) {
+    if (fp != NULL && !fp->normalized) {
+	fp->peaks = psArraySort(fp->peaks, pmPeakSortBySN);
+	fp->normalized = true;
+    }
+
+    return fp;
+}
+
+//
+// Add a span to a footprint, returning the new span
+//
+pmSpan *pmFootprintAddSpan(pmFootprint *fp,	// the footprint to add to
+			   const int y, // row to add
+			   int x0,      // range of
+			   int x1) {    //          columns
+
+    if (x1 < x0) {
+	int tmp = x0;
+	x0 = x1;
+	x1 = tmp;
+    }
+
+    pmSpan *sp = pmSpanAlloc(y, x0, x1);
+    psArrayAdd(fp->spans, 1, sp);
+    psFree(sp);
+    
+    fp->npix += x1 - x0 + 1;
+
+    if (fp->spans->n == 1) {
+	fp->bbox.x0 = x0;
+	fp->bbox.x1 = x1;
+	fp->bbox.y0 = y;
+	fp->bbox.y1 = y;
+    } else {
+	if (x0 < fp->bbox.x0) fp->bbox.x0 = x0;
+	if (x1 > fp->bbox.x1) fp->bbox.x1 = x1;
+	if (y < fp->bbox.y0) fp->bbox.y0 = y;
+	if (y > fp->bbox.y1) fp->bbox.y1 = y;
+    }
+
+    return sp;
+}
+
+void pmFootprintSetBBox(pmFootprint *fp) {
+    assert (fp != NULL);
+    if (fp->spans->n == 0) {
+	return;
+    }
+    pmSpan *sp = fp->spans->data[0];
+    int x0 = sp->x0;
+    int x1 = sp->x1;
+    int y0 = sp->y;
+    int y1 = sp->y;
+
+    for (int i = 1; i < fp->spans->n; i++) {
+	sp = fp->spans->data[i];
+	
+	if (sp->x0 < x0) x0 = sp->x0;
+	if (sp->x1 > x1) x1 = sp->x1;
+	if (sp->y < y0) y0 = sp->y;
+	if (sp->y > y1) y1 = sp->y;
+    }
+
+    fp->bbox.x0 = x0;
+    fp->bbox.x1 = x1;
+    fp->bbox.y0 = y0;
+    fp->bbox.y1 = y1;
+}
+
+int pmFootprintSetNpix(pmFootprint *fp) {
+   assert (fp != NULL);
+   int npix = 0;
+   for (int i = 0; i < fp->spans->n; i++) {
+       pmSpan *span = fp->spans->data[i];
+       npix += span->x1 - span->x0 + 1;
+   }
+   fp->npix = npix;
+
+   return npix;
+}
+
+/*
+ * Extract the peaks in a psArray of pmFootprints, returning a psArray of pmPeaks
+ */
+psArray *pmFootprintArrayToPeaks(const psArray *footprints) {
+   assert(footprints != NULL);
+   assert(footprints->n == 0 || pmFootprintTest(footprints->data[0]));
+
+   int npeak = 0;
+   for (int i = 0; i < footprints->n; i++) {
+      const pmFootprint *fp = footprints->data[i];
+      npeak += fp->peaks->n;
+   }
+
+   psArray *peaks = psArrayAllocEmpty(npeak);
+   
+   for (int i = 0; i < footprints->n; i++) {
+      const pmFootprint *fp = footprints->data[i];
+      for (int j = 0; j < fp->peaks->n; j++) {
+	 psArrayAdd(peaks, 1, fp->peaks->data[j]);
+      }
+   }
+
+   return peaks;
+}
+
+/************************************************************************************************************/
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprint.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprint.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprint.h	(revision 22158)
@@ -0,0 +1,60 @@
+/* @file  pmFootprint.h
+ *
+ * @author RHL, Princeton & IfA; EAM, IfA
+ *
+ * @version $Revision: 1.1.2.1 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-20 23:08:03 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_FOOTPRINT_H
+#define PM_FOOTPRINT_H
+typedef struct {
+    const int id;                       //!< unique ID
+    int npix;                           //!< number of pixels in this pmFootprint
+    psArray *spans;                     //!< the pmSpans
+    psRegion bbox;                      //!< the pmFootprint's bounding box
+    psArray *peaks;                     //!< the peaks lying in this footprint
+    psRegion region;   //!< A region describing the psImage the footprints live in
+    bool normalized;                    //!< Are the spans sorted? 
+} pmFootprint;
+
+pmFootprint *pmFootprintAlloc(int nspan, const psImage *img);
+bool pmFootprintTest(const psPtr ptr);
+
+pmFootprint *pmFootprintNormalize(pmFootprint *fp);
+int pmFootprintSetNpix(pmFootprint *fp);
+void pmFootprintSetBBox(pmFootprint *fp);
+
+pmSpan *pmFootprintAddSpan(pmFootprint *fp,	// the footprint to add to
+			   const int y, // row to add
+			   int x0,      // range of
+			   int x1);    //          columns
+
+psArray *pmFootprintsFind(const psImage *img, const float threshold, const int npixMin);
+pmFootprint *pmFootprintsFindAtPoint(const psImage *img,
+                                    const float threshold,
+                                    const psArray *peaks,
+                                    int row, int col);
+
+psArray *pmFootprintArrayGrow(const psArray *footprints, int r);
+psArray *pmFootprintArraysMerge(const psArray *footprints1, const psArray *footprints2,
+                                const int includePeaks);
+
+psImage *pmSetFootprintArrayIDs(const psArray *footprints, const bool relativeIDs);
+psImage *pmSetFootprintID(psImage *idImage, const pmFootprint *fp, const int id);
+void pmSetFootprintArrayIDsForImage(psImage *idImage,
+				    const psArray *footprints, // the footprints to insert
+				    const bool relativeIDs); // show IDs starting at 0, not pmFootprint->id
+
+psErrorCode pmFootprintsAssignPeaks(psArray *footprints, const psArray *peaks);
+
+psErrorCode pmFootprintArrayCullPeaks(const psImage *img, const psImage *weight, psArray *footprints,
+                                 const float nsigma, const float threshold_min);
+psErrorCode pmFootprintCullPeaks(const psImage *img, const psImage *weight, pmFootprint *fp,
+                                 const float nsigma, const float threshold_min);
+
+psArray *pmFootprintArrayToPeaks(const psArray *footprints);
+
+/// @}
+# endif /* PM_FOOTPRINT_H */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprintArrayGrow.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprintArrayGrow.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprintArrayGrow.c	(revision 22158)
@@ -0,0 +1,92 @@
+/* @file  pmFootprintArrayGrow.c
+ *
+ * @author RHL, Princeton & IfA; EAM, IfA
+ *
+ * @version $Revision: 1.1.2.1 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-20 23:08:03 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <strings.h>
+#include <pslib.h>
+#include "pmSpan.h"
+#include "pmFootprint.h"
+
+# define USE_FFTS_TO_CONVOLVE 1
+
+/*
+ * Grow a psArray of pmFootprints isotropically by r pixels, returning a new psArray of new pmFootprints
+ */
+psArray *pmFootprintArrayGrow(const psArray *footprints, // footprints to grow
+			      int r) {	// how much to grow each footprint
+    assert (footprints->n == 0 || pmFootprintTest(footprints->data[0]));
+
+    psTimerStart ("grow");
+
+    if (footprints->n == 0) {		// we don't know the size of the footprint's region
+	return psArrayAlloc(0);
+    }
+    /*
+     * We'll insert the footprints into an image, then convolve with a disk,
+     * then extract a footprint from the result --- this is magically what we want.
+     */
+    psImage *idImage = pmSetFootprintArrayIDs(footprints, true);
+    psLogMsg ("psphot", PS_LOG_DETAIL, "set footprint array IDs: %f sec\n", psTimerMark ("grow"));
+
+    if (r <= 0) {
+	r = 1;				// r == 1 => no grow
+    }
+    psKernel *circle = psKernelAlloc(-r, r, -r, r);
+    assert (circle->image->numRows == 2*r + 1 && circle->image->numCols == circle->image->numRows);
+    for (int i = 0; i <= r; i++) {
+	for (int j = 0; j <= r; j++) {
+	    if (i*i + j*j <= r*r) {
+		circle->kernel[i][j] = 
+		    circle->kernel[i][-j] = 
+		    circle->kernel[-i][j] = 
+		    circle->kernel[-i][-j] = 1;
+	    }
+	}
+    }
+
+# if (USE_FFTS_TO_CONVOLVE)    
+    psImage *f32ImageIn = psImageCopy (NULL, idImage, PS_TYPE_F32);
+    psImage *f32ImageOut = psImageConvolveFFT(NULL, f32ImageIn, NULL, 0, circle);
+    psImage *grownIdImage = psImageCopy (NULL, f32ImageOut, PS_TYPE_S32);
+    psFree (f32ImageIn);
+    psFree (f32ImageOut);
+# else
+    psImage *grownIdImage = psImageConvolveDirect(NULL, idImage, circle); // Here's the actual grow step
+# endif
+
+    psLogMsg ("psphot", PS_LOG_DETAIL, "convolved with grow disc: %f sec\n", psTimerMark ("grow"));
+    psFree(circle);	
+
+    psArray *grown = pmFootprintsFind(grownIdImage, 0.5, 1); // and here we rebuild the grown footprints
+    psLogMsg ("psphot", PS_LOG_DETAIL, "found grown footprints: %f sec\n", psTimerMark ("grow"));
+
+    assert (grown != NULL);
+    psFree(idImage); 
+    psFree(grownIdImage);
+
+    /*
+     * Now assign the peaks appropriately.  We could do this more efficiently
+     * using grownIdImage (which we just freed), but this is easy and probably fast enough
+     */
+    psArray *peaks = pmFootprintArrayToPeaks(footprints);
+    pmFootprintsAssignPeaks(grown, peaks);
+    psFree(peaks);
+
+    psLogMsg ("psphot", PS_LOG_DETAIL, "finished grow: %f sec\n", psTimerMark ("grow"));
+
+    return grown;
+    
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprintArraysMerge.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprintArraysMerge.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprintArraysMerge.c	(revision 22158)
@@ -0,0 +1,87 @@
+/* @file  pmFootprintArraysMerge.c
+ *
+ * @author RHL, Princeton & IfA; EAM, IfA
+ *
+ * @version $Revision: 1.1.2.1 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-20 23:08:03 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <strings.h>
+#include <pslib.h>
+#include "pmSpan.h"
+#include "pmFootprint.h"
+
+/*
+ * Merge together two psArrays of pmFootprints neither of which is damaged.
+ *
+ * The returned psArray may contain elements of the inital psArrays (with
+ * their reference counters suitable incremented)
+ */
+psArray *pmFootprintArraysMerge(const psArray *footprints1, // one set of footprints
+				const psArray *footprints2, // the other set
+				const int includePeaks) { // which peaks to set? 0x1 => footprints1, 0x2 => 2
+    assert (footprints1->n == 0 || pmFootprintTest(footprints1->data[0]));
+    assert (footprints2->n == 0 || pmFootprintTest(footprints2->data[0]));
+
+    if (footprints1->n == 0 || footprints2->n == 0) {		// nothing to do but put copies on merged
+	const psArray *old = (footprints1->n == 0) ? footprints2 : footprints1;
+
+	psArray *merged = psArrayAllocEmpty(old->n);
+	for (int i = 0; i < old->n; i++) {
+	    psArrayAdd(merged, 1, old->data[i]);
+	}
+	
+	return merged;
+    }
+    /*
+     * We have real work to do as some pmFootprints in footprints2 may overlap
+     * with footprints1
+     */
+    {
+	pmFootprint *fp1 = footprints1->data[0];
+	pmFootprint *fp2 = footprints2->data[0];
+	if (fp1->region.x0 != fp2->region.x0 ||
+	    fp1->region.x1 != fp2->region.x1 ||
+	    fp1->region.y0 != fp2->region.y0 ||
+	    fp1->region.y1 != fp2->region.y1) {
+	    psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+		    "The two pmFootprint arrays correspnond to different-sized regions");
+	    return NULL;
+	}
+    }
+    /*
+     * We'll insert first one set of footprints then the other into an image, then
+     * extract a footprint from the result --- this is magically what we want.
+     */
+    psImage *idImage = pmSetFootprintArrayIDs(footprints1, true);
+    pmSetFootprintArrayIDsForImage(idImage, footprints2, true);
+
+    psArray *merged = pmFootprintsFind(idImage, 0.5, 1);
+    assert (merged != NULL);
+    psFree(idImage);
+    /*
+     * Now assign the peaks appropriately.  We could do this more efficiently
+     * using idImage (which we just freed), but this is easy and probably fast enough
+     */ 
+    if (includePeaks & 0x1) {
+	psArray *peaks = pmFootprintArrayToPeaks(footprints1);
+	pmFootprintsAssignPeaks(merged, peaks);
+	psFree(peaks);
+    }
+
+    if (includePeaks & 0x2) {
+	psArray *peaks = pmFootprintArrayToPeaks(footprints2);
+	pmFootprintsAssignPeaks(merged, peaks);
+	psFree(peaks);
+    }
+    
+    return merged;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprintAssignPeaks.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprintAssignPeaks.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprintAssignPeaks.c	(revision 22158)
@@ -0,0 +1,137 @@
+/* @file  pmFootprintAssignPeaks.c
+ *
+ * @author RHL, Princeton & IfA; EAM, IfA
+ *
+ * @version $Revision: 1.1.2.1 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-20 23:08:03 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <strings.h>
+#include <pslib.h>
+#include "pmPeaks.h"
+#include "pmSpan.h"
+#include "pmFootprint.h"
+
+/*
+ * Given a psArray of pmFootprints and another of pmPeaks, assign the peaks to the
+ * footprints in which that fall; if they _don't_ fall in a footprint, add a suitable
+ * one to the list.
+ */
+psErrorCode
+pmFootprintsAssignPeaks(psArray *footprints,	// the pmFootprints
+			const psArray *peaks) { // the pmPeaks
+    assert (footprints != NULL);
+    assert (footprints->n == 0 || pmFootprintTest(footprints->data[0]));
+    assert (peaks != NULL);
+    assert (peaks->n == 0 || psMemCheckPeak(peaks->data[0]));
+    
+    if (footprints->n == 0) {
+	if (peaks->n > 0) {
+	    return psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Your list of footprints is empty");
+	}
+	return PS_ERR_NONE;
+    }
+    /*
+     * Create an image filled with the object IDs, and use it to assign pmPeaks to the
+     * objects
+     */
+    psImage *ids = pmSetFootprintArrayIDs(footprints, true);
+    assert (ids != NULL);
+    assert (ids->type.type == PS_TYPE_S32);
+    const int row0 = ids->row0;
+    const int col0 = ids->col0;
+    const int numRows = ids->numRows;
+    const int numCols = ids->numCols;
+
+    for (int i = 0; i < peaks->n; i++) {
+	pmPeak *peak = peaks->data[i];
+	const int x = peak->x - col0;
+	const int y = peak->y - row0;
+	
+	assert (x >= 0 && x < numCols && y >= 0 && y < numRows);
+	int id = ids->data.S32[y][x - col0];
+
+	if (id == 0) {			// peak isn't in a footprint, so make one for it
+	    pmFootprint *nfp = pmFootprintAlloc(1, ids);
+	    pmFootprintAddSpan(nfp, y, x, x);
+	    psArrayAdd(footprints, 1, nfp);
+	    psFree(nfp);
+	    id = footprints->n;
+	}
+
+	assert (id >= 1 && id <= footprints->n);
+	pmFootprint *fp = footprints->data[id - 1];
+	psArrayAdd(fp->peaks, 5, peak);
+	peak->footprint = (struct pmFootprint *) fp; // reference to containing footprint
+    }
+    
+    psFree(ids);
+
+    // Make sure that peaks within each footprint are sorted and unique
+    for (int i = 0; i < footprints->n; i++) {
+	
+	pmFootprint *fp = footprints->data[i];
+
+	// XXX are we allowed to have peak-less footprints??
+	if (!fp->peaks->n) continue;
+
+        fp->peaks = psArraySort(fp->peaks, pmPeakSortBySN);
+
+	// XXX EAM : the algorithm below should be much faster than using psArrayRemove if
+	// the number of peaks in the footprint is large, or if there are no duplicates.
+	// if we have a lot of small-number peak arrays with duplicates, this may be
+	// slower.
+
+	// track the number of good peaks in the footprint
+	int nGood = 1;
+
+	// check for duplicates
+	// on first pass, we set the index to NULL if peak is a duplicate
+	// XXX EAM : this can leave behind duplicates of the same S/N
+	// (if sorted list has A, B, A, B ...)
+	for (int j = 1; j < fp->peaks->n; j++) { 
+	    if (fp->peaks->data[j] == fp->peaks->data[nGood]) {
+		// everything on the array has its own mem reference; free and drop this one
+		psFree (fp->peaks->data[j]);
+		fp->peaks->data[j] = NULL;
+	    } else {
+		nGood ++;
+	    }
+	}
+
+	// no deleted peaks, go to next footprint
+	if (nGood == fp->peaks->n) continue;
+
+	int nKeep = 0;
+
+	psArray *goodPeaks = psArrayAlloc (nGood);
+	// on second pass, save the good peaks
+	for (int j = 0; j < fp->peaks->n; j++) { // check for duplicates
+	    if (fp->peaks->data[j] == NULL) continue;
+	    // transfer the data (NULL to avoid double free)
+	    // this is only slightly sleazy
+	    goodPeaks->data[nKeep] = fp->peaks->data[j];
+	    fp->peaks->data[j] = NULL;
+	    nKeep ++;
+	}
+	psAssert (nGood == nKeep, "mis-counted nKeep or nGood");
+
+	// free the old (now NULL-filled) array
+	psFree (fp->peaks);
+	fp->peaks = goodPeaks;
+    }
+
+    // (void)psArrayRemoveIndex(fp->peaks, j);
+
+
+    return PS_ERR_NONE;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprintFind.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprintFind.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprintFind.c	(revision 22158)
@@ -0,0 +1,249 @@
+/* @file  pmFootprintFind.c
+ * find footprints in an image (fast on large scale images)
+ *
+ * @author RHL, Princeton & IfA; EAM, IfA
+ *
+ * @version $Revision: 1.1.2.1 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-20 23:08:03 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <strings.h>
+#include <pslib.h>
+#include "pmSpan.h"
+#include "pmFootprint.h"
+
+// ** this is not defined on all systems?
+void *memset (void *s, int c, size_t n);
+
+// XXX EAM : why use WSPAN in here rather than pmSpan?
+typedef struct {			/* run-length code for part of object*/
+   int id;				/* ID for object */
+   int y;				/* Row wherein WSPAN dwells */
+   int x0, x1;				/* inclusive range of columns */
+} WSPAN;
+
+/*
+ * comparison function for qsort; sort by ID then row
+ */
+static int
+compar(const void *va, const void *vb)
+{
+   const WSPAN *a = va;
+   const WSPAN *b = vb;
+
+   if(a->id < b->id) {
+      return(-1);
+   } else if(a->id > b->id) {
+      return(1);
+   } else {
+      return(a->y - b->y);
+   }
+}
+
+/*
+ * Follow a chain of aliases, returning the final resolved value.
+ */
+static int
+resolve_alias(const int *aliases,	/* list of aliases */
+	      int id)			/* alias to look up */
+{
+   int resolved = id;			/* resolved alias */
+
+   while(id != aliases[id]) {
+      resolved = id = aliases[id];
+   }
+
+   return(resolved);
+}
+
+/*
+ * Go through an image, finding sets of connected pixels above threshold
+ * and assembling them into pmFootprints;  the resulting set of objects
+ * is returned as a psArray
+ */
+psArray *
+pmFootprintsFind(const psImage *img,	// image to search
+		 const float threshold,	// Threshold
+		 const int npixMin)	// minimum number of pixels in an acceptable pmFootprint
+{
+   int i0;				/* initial value of i */
+   int id;				/* object ID */
+   int in_span;				/* object ID of current WSPAN */
+   int nspan = 0;			/* number of spans */
+   int nobj = 0;			/* number of objects found */
+   int x0 = 0;			        /* unpacked from a WSPAN */
+   int *tmp;				/* used in swapping idc/idp */
+
+   assert(img != NULL);
+
+   bool F32 = false;			// is this an F32 image?
+   if (img->type.type == PS_TYPE_F32) {
+       F32 = true;
+   } else if (img->type.type == PS_TYPE_S32) {
+       F32 = false;
+   } else {				// N.b. You can't trivially add more cases here; F32 is just a bool
+       psError(PS_ERR_UNKNOWN, true, "Unsupported psImage type: %d", img->type.type);
+       return NULL;
+   }
+   psF32 *imgRowF32 = NULL;		// row pointer if F32
+   psS32 *imgRowS32 = NULL;		//  "   "   "  "  !F32
+   
+   const int row0 = img->row0;
+   const int col0 = img->col0;
+   const int numRows = img->numRows;
+   const int numCols = img->numCols;
+/*
+ * Storage for arrays that identify objects by ID. We want to be able to
+ * refer to idp[-1] and idp[numCols], hence the (numCols + 2)
+ */
+   int *id_s = psAlloc(2*(numCols + 2)*sizeof(int));
+   memset(id_s, '\0', 2*(numCols + 2)*sizeof(int)); assert(id_s[0] == 0);
+   int *idc = id_s + 1;			// object IDs in current/
+   int *idp = idc + (numCols + 2);	//                       previous row
+
+   int size_aliases = 1 + numRows/20;	// size of aliases[] array
+   int *aliases = psAlloc(size_aliases*sizeof(int)); // aliases for object IDs
+
+   int size_spans = 1 + numRows/20;	// size of spans[] array
+   WSPAN *spans = psAlloc(size_spans*sizeof(WSPAN)); // row:x0,x1 for objects
+/*
+ * Go through image identifying objects
+ */
+   for (int i = 0; i < numRows; i++) {
+      int j;
+      tmp = idc; idc = idp; idp = tmp;	/* swap ID pointers */
+      memset(idc, '\0', numCols*sizeof(int));
+      
+      imgRowF32 = img->data.F32[i];	// only one of
+      imgRowS32 = img->data.S32[i];	//      these is valid!
+
+      in_span = 0;			/* not in a span */
+      for (j = 0; j < numCols; j++) {
+	 double pixVal = F32 ? imgRowF32[j] : imgRowS32[j];
+	 if (pixVal < threshold) {
+	    if (in_span) {
+	       if(nspan >= size_spans) {
+		  size_spans *= 2;
+		  spans = psRealloc(spans, size_spans*sizeof(WSPAN));
+	       }
+	       spans[nspan].id = in_span;
+	       spans[nspan].y = i;
+	       spans[nspan].x0 = x0;
+	       spans[nspan].x1 = j - 1;
+	       
+	       nspan++;
+
+	       in_span = 0;
+	    }
+	 } else {			/* a pixel to fix */
+	    if(idc[j - 1] != 0) {
+	       id = idc[j - 1];
+	    } else if(idp[j - 1] != 0) {
+	       id = idp[j - 1];
+	    } else if(idp[j] != 0) {
+	       id = idp[j];
+	    } else if(idp[j + 1] != 0) {
+	       id = idp[j + 1];
+	    } else {
+	       id = ++nobj;
+
+	       if(id >= size_aliases) {
+		  size_aliases *= 2;
+		  aliases = psRealloc(aliases, size_aliases*sizeof(int));
+	       }
+	       aliases[id] = id;
+	    }
+
+	    idc[j] = id;
+	    if(!in_span) {
+	       x0 = j; in_span = id;
+	    }
+/*
+ * Do we need to merge ID numbers? If so, make suitable entries in aliases[]
+ */
+	    if(idp[j + 1] != 0 && idp[j + 1] != id) {
+	       aliases[resolve_alias(aliases, idp[j + 1])] =
+						    resolve_alias(aliases, id);
+	       
+	       idc[j] = id = idp[j + 1];
+	    }
+	 }
+      }
+
+      if(in_span) {
+	 if(nspan >= size_spans) {
+	    size_spans *= 2;
+	    spans = psRealloc(spans, size_spans*sizeof(WSPAN));
+	 }
+
+	 assert(nspan < size_spans);	/* we checked for space above */
+	 spans[nspan].id = in_span;
+	 spans[nspan].y = i;
+	 spans[nspan].x0 = x0;
+	 spans[nspan].x1 = j - 1;
+	 
+	 nspan++;
+      }
+   }
+
+   psFree(id_s);
+/*
+ * Resolve aliases; first alias chains, then the IDs in the spans
+ */
+   for (int i = 0; i < nspan; i++) {
+      spans[i].id = resolve_alias(aliases, spans[i].id);
+   }
+
+   psFree(aliases);
+/*
+ * Sort spans by ID, so we can sweep through them once
+ * XXX replace with a psLib sort call
+ */
+   if(nspan > 0) {
+      qsort(spans, nspan, sizeof(WSPAN), compar);
+   }
+/*
+ * Build pmFootprints from the spans
+ */
+   psArray *footprints = psArrayAlloc(nobj);
+   int n = 0;			// number of pmFootprints
+
+   if(nspan > 0) {
+      id = spans[0].id;
+      i0 = 0;
+      for (int i = 0; i <= nspan; i++) {	/* nspan + 1 to catch last object */
+	 if(i == nspan || spans[i].id != id) {
+	    pmFootprint *fp = pmFootprintAlloc(i - i0, img);
+	    
+	    for(; i0 < i; i0++) {
+		pmFootprintAddSpan(fp, spans[i0].y + row0,
+				   spans[i0].x0 + col0, spans[i0].x1 + col0);
+	    }
+
+	    if (fp->npix < npixMin) {
+	       psFree(fp);
+	    } else {
+	       footprints->data[n++] = fp;
+	    }
+	 }
+	 
+	 id = spans[i].id;
+      }
+   }
+
+   footprints = psArrayRealloc(footprints, n);
+/*
+ * clean up
+ */
+   psFree(spans);
+
+   return footprints;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprintFindAtPoint.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprintFindAtPoint.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprintFindAtPoint.c	(revision 22158)
@@ -0,0 +1,409 @@
+/* @file  pmFootprintFindAtPoint.c
+ * find footprints in a small image relative to a reference point
+ *
+ * @author RHL, Princeton & IfA; EAM, IfA
+ *
+ * @version $Revision: 1.1.2.1 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-20 23:08:03 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <strings.h>
+#include <pslib.h>
+#include "pmPeaks.h"
+#include "pmSpan.h"
+#include "pmFootprint.h"
+
+/*
+ * A data structure to hold the starting point for a search for pixels above threshold,
+ * used by pmFootprintsFindAtPoint
+ *
+ * We don't want to find this span again --- it's already part of the footprint ---
+ * so we set appropriate mask bits
+ *
+ * EAM : these function were confusingly using "startspan" and "spartspan"  
+ * I've rationalized them all to 'startspan'
+ */
+
+//
+// An enum for what we should do with a Startspan
+//
+typedef enum {PM_SSPAN_DOWN = 0,	// scan down from this span
+	      PM_SSPAN_UP,		// scan up from this span
+	      PM_SSPAN_RESTART,		// restart scanning from this span
+	      PM_SSPAN_DONE		// this span is processed
+} PM_SSPAN_DIR;				// How to continue searching
+//
+// An enum for mask's pixel values.  We're looking for pixels that are above threshold, and
+// we keep extra book-keeping information in the PM_SSPAN_STOP plane.  It's simpler to be
+// able to check for 
+//
+enum {
+    PM_SSPAN_INITIAL = 0x0,		// initial state of pixels.
+    PM_SSPAN_DETECTED = 0x1,		// we've seen this pixel
+    PM_SSPAN_STOP = 0x2			// you may stop searching when you see this pixel
+};
+//
+// The struct that remembers how to [re-]start scanning the image for pixels
+//
+typedef struct {
+    const pmSpan *span;			// save the pixel range
+    PM_SSPAN_DIR direction;		// How to continue searching
+    bool stop;				// should we stop searching?
+} Startspan;
+
+static void startspanFree(Startspan *sspan) {
+    psFree((void *)sspan->span);
+}
+
+static Startspan *
+StartspanAlloc(const pmSpan *span,	// The span in question
+	       psImage *mask,		// Pixels that we've already detected
+	       const PM_SSPAN_DIR dir	// Should we continue searching towards the top of the image?
+    ) {
+    Startspan *sspan = psAlloc(sizeof(Startspan));
+    psMemSetDeallocator(sspan, (psFreeFunc)startspanFree);
+
+    sspan->span = psMemIncrRefCounter((void *)span);
+    sspan->direction = dir;
+    sspan->stop = false;
+    
+    if (mask != NULL) {			// remember that we've detected these pixels
+	psMaskType *mpix = &mask->data.PS_TYPE_MASK_DATA[span->y - mask->row0][span->x0 - mask->col0];
+
+	for (int i = 0; i <= span->x1 - span->x0; i++) {
+	    mpix[i] |= PM_SSPAN_DETECTED;
+	    if (mpix[i] & PM_SSPAN_STOP) {
+		sspan->stop = true;
+	    }
+	}
+    }
+    
+    return sspan;
+}
+
+//
+// Add a new Startspan to an array of Startspans.  Iff we see a stop bit, return true
+//
+static bool add_startspan(psArray *startspans, // the saved Startspans
+			  const pmSpan *sp, // the span in question
+			  psImage *mask, // mask of detected/stop pixels
+			  const PM_SSPAN_DIR dir) { // the desired direction to search
+    if (dir == PM_SSPAN_RESTART) {
+	if (add_startspan(startspans, sp, mask,  PM_SSPAN_UP) ||
+	    add_startspan(startspans, sp, NULL, PM_SSPAN_DOWN)) {
+	    return true;
+	}
+    } else {
+	Startspan *sspan = StartspanAlloc(sp, mask, dir);
+	if (sspan->stop) {		// we detected a stop bit
+	    psFree(sspan);		// don't allocate new span
+
+	    return true;
+	} else {
+	    psArrayAdd(startspans, 1, sspan);
+	    psFree(sspan);		// as it's now owned by startspans
+	}
+    }
+
+    return false;
+}
+
+/************************************************************************************************************/
+/*
+ * Search the image for pixels above threshold, starting at a single Startspan.
+ * We search the array looking for one to process; it'd be better to move the
+ * ones that we're done with to the end, but it probably isn't worth it for
+ * the anticipated uses of this routine.
+ *
+ * This is the guts of pmFootprintsFindAtPoint
+ */
+static bool do_startspan(pmFootprint *fp, // the footprint that we're building
+			 const psImage *img, // the psImage we're working on
+			 psImage *mask, // the associated masks
+			 const float threshold,	// Threshold
+			 psArray *startspans) {	// specify which span to process next
+    bool F32 = false;			// is this an F32 image?
+    if (img->type.type == PS_TYPE_F32) {
+	F32 = true;
+    } else if (img->type.type == PS_TYPE_S32) {
+	F32 = false;
+    } else {				// N.b. You can't trivially add more cases here; F32 is just a bool
+	psError(PS_ERR_UNKNOWN, true, "Unsupported psImage type: %d", img->type.type);
+	return NULL;
+    }
+
+    psF32 *imgRowF32 = NULL;		// row pointer if F32
+    psS32 *imgRowS32 = NULL;		//  "   "   "  "  !F32
+    psMaskType *maskRow = NULL;		//  masks's row pointer
+    
+    const int row0 = img->row0;
+    const int col0 = img->col0;
+    const int numRows = img->numRows;
+    const int numCols = img->numCols;
+    
+    /********************************************************************************************************/
+    
+    Startspan *sspan = NULL;
+    for (int i = 0; i < startspans->n; i++) {
+	sspan = startspans->data[i];
+	if (sspan->direction != PM_SSPAN_DONE) {
+	    break;
+	}
+	if (sspan->stop) {
+	    break;
+	}
+    }
+    if (sspan == NULL || sspan->direction == PM_SSPAN_DONE) { // no more Startspans to process
+	return false;
+    }
+    if (sspan->stop) {			// they don't want any more spans processed
+	return false;
+    }
+    /*
+     * Work
+     */
+    const PM_SSPAN_DIR dir = sspan->direction;
+    /*
+     * Set initial span to the startspan
+     */
+    int x0 = sspan->span->x0 - col0, x1 = sspan->span->x1 - col0;
+    /*
+     * Go through image identifying objects
+     */
+    int nx0, nx1 = -1;			// new values of x0, x1
+    const int di = (dir == PM_SSPAN_UP) ? 1 : -1; // how much i changes to get to the next row
+    bool stop = false;			// should I stop searching for spans?
+
+    for (int i = sspan->span->y -row0 + di; i < numRows && i >= 0; i += di) {
+	imgRowF32 = img->data.F32[i];	// only one of
+	imgRowS32 = img->data.S32[i];	//      these is valid!
+	maskRow = mask->data.PS_TYPE_MASK_DATA[i];
+	//
+	// Search left from the pixel diagonally to the left of (i - di, x0). If there's
+	// a connected span there it may need to grow up and/or down, so push it onto
+	// the stack for later consideration
+	//
+	nx0 = -1;
+	for (int j = x0 - 1; j >= -1; j--) {
+	    double pixVal = (j < 0) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]);
+	    if ((maskRow[j] & PM_SSPAN_DETECTED) || pixVal < threshold) {
+		if (j < x0 - 1) {	// we found some pixels above threshold
+		    nx0 = j + 1;
+		}
+		break;
+	    }
+	}
+
+	if (nx0 < 0) {			// no span to the left
+	    nx1 = x0 - 1;		// we're going to resume searching at nx1 + 1
+	} else {
+	    //
+	    // Search right in leftmost span
+	    //
+	    //nx1 = 0;			// make gcc happy
+	    for (int j = nx0 + 1; j <= numCols; j++) {
+		double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]);
+		if ((maskRow[j] & PM_SSPAN_DETECTED) || pixVal < threshold) {
+		    nx1 = j - 1;
+		    break;
+		}
+	    }
+	    
+	    const pmSpan *sp = pmFootprintAddSpan(fp, i + row0, nx0 + col0, nx1 + col0);
+	    
+	    if (add_startspan(startspans, sp, mask, PM_SSPAN_RESTART)) {
+		stop = true;
+		break;
+	    }
+	}
+	//
+	// Now look for spans connected to the old span.  The first of these we'll
+	// simply process, but others will have to be deferred for later consideration.
+	//
+	// In fact, if the span overhangs to the right we'll have to defer the overhang
+	// until later too, as it too can grow in both directions
+	//
+	// Note that column numCols exists virtually, and always ends the last span; this
+	// is why we claim below that sx1 is always set
+	//
+	bool first = false;		// is this the first new span detected?
+	for (int j = nx1 + 1; j <= x1 + 1; j++) {
+	    double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]);
+	    if (!(maskRow[j] & PM_SSPAN_DETECTED) && pixVal >= threshold) {
+		int sx0 = j++;		// span that we're working on is sx0:sx1
+		int sx1 = -1;		// We know that if we got here, we'll also set sx1
+		for (; j <= numCols; j++) {
+		    double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]);
+		    if ((maskRow[j] & PM_SSPAN_DETECTED) || pixVal < threshold) { // end of span
+			sx1 = j;
+			break;
+		    }
+		}
+		assert (sx1 >= 0);
+
+		const pmSpan *sp;
+		if (first) {
+		    if (sx1 <= x1) {
+			sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, sx1 + col0 - 1);
+			if (add_startspan(startspans, sp, mask, PM_SSPAN_DONE)) {
+			    stop = true;
+			    break;
+			}
+		    } else {		// overhangs to right
+			sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, x1 + col0);
+			if (add_startspan(startspans, sp, mask, PM_SSPAN_DONE)) {
+			    stop = true;
+			    break;
+			}
+			sp = pmFootprintAddSpan(fp, i + row0, x1 + 1 + col0, sx1 + col0 - 1);
+			if (add_startspan(startspans, sp, mask, PM_SSPAN_RESTART)) {
+			    stop = true;
+			    break;
+			}
+		    }
+		    first = false;
+		} else {
+		    sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, sx1 + col0 - 1);
+		    if (add_startspan(startspans, sp, mask, PM_SSPAN_RESTART)) {
+			stop = true;
+			break;
+		    }
+		}
+	    }
+	}
+
+	if (stop || first == false) {	// we're done
+	    break;
+	}
+
+	x0 = nx0; x1 = nx1;
+    }
+    /*
+     * Cleanup
+     */
+
+    sspan->direction = PM_SSPAN_DONE;
+    return stop ? false : true;
+}
+
+/*
+ * Go through an image, starting at (row, col) and assembling all the pixels
+ * that are connected to that point (in a chess kings-move sort of way) into
+ * a pmFootprint.
+ *
+ * This is much slower than pmFootprintsFind if you want to find lots of
+ * footprints, but if you only want a small region about a given point it
+ * can be much faster
+ *
+ * N.b. The returned pmFootprint is not in "normal form"; that is the pmSpans
+ * are not sorted by increasing y, x0, x1.  If this matters to you, call
+ * pmFootprintNormalize()
+ */
+pmFootprint *
+pmFootprintsFindAtPoint(const psImage *img,	// image to search
+		       const float threshold,	// Threshold
+		       const psArray *peaks, // array of peaks; finding one terminates search for footprint
+		       int row, int col) { // starting position (in img's parent's coordinate system)
+   assert(img != NULL);
+
+   bool F32 = false;			// is this an F32 image?
+   if (img->type.type == PS_TYPE_F32) {
+       F32 = true;
+   } else if (img->type.type == PS_TYPE_S32) {
+       F32 = false;
+   } else {				// N.b. You can't trivially add more cases here; F32 is just a bool
+       psError(PS_ERR_UNKNOWN, true, "Unsupported psImage type: %d", img->type.type);
+       return NULL;
+   }
+   psF32 *imgRowF32 = NULL;		// row pointer if F32
+   psS32 *imgRowS32 = NULL;		//  "   "   "  "  !F32
+   
+   const int row0 = img->row0;
+   const int col0 = img->col0;
+   const int numRows = img->numRows;
+   const int numCols = img->numCols;
+/*
+ * Is point in image, and above threshold?
+ */
+   row -= row0; col -= col0;
+   if (row < 0 || row >= numRows ||
+       col < 0 || col >= numCols) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "row/col == (%d, %d) are out of bounds [%d--%d, %d--%d]",
+		row + row0, col + col0, row0, row0 + numRows - 1, col0, col0 + numCols - 1);
+       return NULL;
+   }
+
+   double pixVal = F32 ? img->data.F32[row][col] : img->data.S32[row][col];
+   if (pixVal < threshold) {
+       return pmFootprintAlloc(0, img);
+   }
+   
+   pmFootprint *fp = pmFootprintAlloc(1 + img->numRows/10, img);
+/*
+ * We need a mask for two purposes; to indicate which pixels are already detected,
+ * and to store the "stop" pixels --- those that, once reached, should stop us
+ * looking for the rest of the pmFootprint.  These are generally set from peaks.
+ */
+   psImage *mask = psImageAlloc(numCols, numRows, PS_TYPE_MASK);
+   P_PSIMAGE_SET_ROW0(mask, row0);
+   P_PSIMAGE_SET_COL0(mask, col0);
+   psImageInit(mask, PM_SSPAN_INITIAL);
+   //
+   // Set stop bits from peaks list
+   //
+   assert (peaks == NULL || peaks->n == 0 || psMemCheckPeak(peaks->data[0]));
+   if (peaks != NULL) {
+       for (int i = 0; i < peaks->n; i++) {
+	   pmPeak *peak = peaks->data[i];
+	   mask->data.PS_TYPE_MASK_DATA[peak->y - mask->row0][peak->x - mask->col0] |= PM_SSPAN_STOP;
+       }
+   }
+/*
+ * Find starting span passing through (row, col)
+ */
+   psArray *startspans = psArrayAllocEmpty(1); // spans where we have to restart the search
+   
+   imgRowF32 = img->data.F32[row];	// only one of
+   imgRowS32 = img->data.S32[row];	//      these is valid!
+   psMaskType *maskRow = mask->data.PS_TYPE_MASK_DATA[row];
+   {
+       int i;
+       for (i = col; i >= 0; i--) {
+	   pixVal = F32 ? imgRowF32[i] : imgRowS32[i];
+	   if ((maskRow[i] & PM_SSPAN_DETECTED) || pixVal < threshold) {
+	       break;
+	   }
+       }
+       int i0 = i;
+       for (i = col; i < numCols; i++) {
+	   pixVal = F32 ? imgRowF32[i] : imgRowS32[i];
+	   if ((maskRow[i] & PM_SSPAN_DETECTED) || pixVal < threshold) {
+	       break;
+	   }
+       }
+       int i1 = i;
+       const pmSpan *sp = pmFootprintAddSpan(fp, row + row0, i0 + col0 + 1, i1 + col0 - 1);
+
+       (void)add_startspan(startspans, sp, mask, PM_SSPAN_RESTART);
+   }
+   /*
+    * Now workout from those Startspans, searching for pixels above threshold
+    */
+   while (do_startspan(fp, img, mask, threshold, startspans)) continue;
+   /*
+    * Cleanup
+    */
+   psFree(mask);
+   psFree(startspans);			// restores the image pixel
+
+   return fp;				// pmFootprint really
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprintIDs.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprintIDs.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmFootprintIDs.c	(revision 22158)
@@ -0,0 +1,121 @@
+/* @file  pmFootprintIDs.c
+ * functions to manipulate footprint IDs 
+ *
+ * @author RHL, Princeton & IfA; EAM, IfA
+ *
+ * @version $Revision: 1.1.2.1 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-20 23:08:03 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <strings.h>
+#include <pslib.h>
+#include "pmSpan.h"
+#include "pmFootprint.h"
+
+/*
+ * Worker routine for the pmSetFootprintArrayIDs/pmSetFootprintID (and pmMergeFootprintArrays)
+ */
+static void
+set_footprint_id(psImage *idImage,	// the image to set
+		 const pmFootprint *fp, // the footprint to insert
+		 const int id) {	// the desired ID
+   const int col0 = fp->region.x0;
+   const int row0 = fp->region.y0;
+
+   for (int j = 0; j < fp->spans->n; j++) {
+       const pmSpan *span = fp->spans->data[j];
+       psS32 *imgRow = idImage->data.S32[span->y - row0];
+       for(int k = span->x0 - col0; k <= span->x1 - col0; k++) {
+	   imgRow[k] += id;
+       }
+   }
+}
+
+void pmSetFootprintArrayIDsForImage(psImage *idImage,
+				    const psArray *footprints, // the footprints to insert
+				    const bool relativeIDs) { // show IDs starting at 0, not pmFootprint->id
+    int id = 0;				// first index will be 1
+    for (int i = 0; i < footprints->n; i++) {
+	const pmFootprint *fp = footprints->data[i];
+	if (relativeIDs) {
+	    id++;
+	} else {
+	    id = fp->id;
+	}
+       
+	set_footprint_id(idImage, fp, id);
+    }
+}
+
+/*
+ * Set an image to the value of footprint's ID whever they may fall
+ */
+psImage *pmSetFootprintArrayIDs(const psArray *footprints, // the footprints to insert
+				const bool relativeIDs) { // show IDs starting at 1, not pmFootprint->id
+   assert (footprints != NULL);
+
+   if (footprints->n == 0) {
+       psError(PS_ERR_BAD_PARAMETER_SIZE, true, "You didn't provide any footprints");
+       return NULL;
+   }
+   const pmFootprint *fp = footprints->data[0];
+   assert(pmFootprintTest((const psPtr)fp));
+   const int numCols = fp->region.x1 - fp->region.x0 + 1;
+   const int numRows = fp->region.y1 - fp->region.y0 + 1;
+   const int col0 = fp->region.x0;
+   const int row0 = fp->region.y0;
+   assert (numCols >= 0 && numRows >= 0);
+   
+   psImage *idImage = psImageAlloc(numCols, numRows, PS_TYPE_S32);
+   P_PSIMAGE_SET_ROW0(idImage, row0);
+   P_PSIMAGE_SET_COL0(idImage, col0);
+   psImageInit(idImage, 0);
+   /*
+    * do the work
+    */
+   pmSetFootprintArrayIDsForImage(idImage, footprints, relativeIDs);
+
+   return idImage;
+   
+}
+
+/*
+ * Set an image to the value of footprint's ID whever they may fall
+ */
+psImage *pmSetFootprintID(psImage *idImage,
+			  const pmFootprint *fp, // the footprint to insert
+			  const int id) {	// the desired ID
+   assert(fp != NULL && pmFootprintTest((const psPtr)fp));
+   const int numCols = fp->region.x1 - fp->region.x0 + 1;
+   const int numRows = fp->region.y1 - fp->region.y0 + 1;
+   const int col0 = fp->region.x0;
+   const int row0 = fp->region.y0;
+   assert (numCols >= 0 && numRows >= 0);
+   
+   if (idImage == NULL) {
+       idImage = psImageAlloc(numCols, numRows, PS_TYPE_S32);
+   } else {
+       assert (idImage->numCols == numCols);
+       assert (idImage->numRows == numRows);
+       // XXX assert on type (S32)
+   }
+   P_PSIMAGE_SET_ROW0(idImage, row0);
+   P_PSIMAGE_SET_COL0(idImage, col0);
+   psImageInit(idImage, 0);
+   /*
+    * do the work
+    */
+   set_footprint_id(idImage, fp, id);
+
+   return idImage;
+   
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmGrowthCurve.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmGrowthCurve.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmGrowthCurve.c	(revision 22158)
@@ -0,0 +1,72 @@
+/** @file  pmGrowthCurve.c
+ *
+ *  Measure the curve-of-growth for sources
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-10-03 00:42:40 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pslib.h>
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmResiduals.h"
+#include "pmGrowthCurve.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "psVectorBracket.h"
+
+static void pmGrowthCurveFree (pmGrowthCurve *growth)
+{
+    if (growth == NULL)
+        return;
+
+    psFree (growth->radius);
+    psFree (growth->apMag);
+    return;
+}
+
+bool psMemCheckGrowthCurve(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc)pmGrowthCurveFree );
+}
+
+pmGrowthCurve *pmGrowthCurveAlloc (psF32 minRadius, psF32 maxRadius, psF32 refRadius)
+{
+
+    pmGrowthCurve *growth = psAlloc (sizeof(pmGrowthCurve));
+    psMemSetDeallocator(growth, (psFreeFunc) pmGrowthCurveFree);
+
+    // fractional pixel radii are not well defined; use integer steps
+    growth->radius = psVectorCreate (NULL, minRadius, maxRadius, 1.0, PS_TYPE_F32);
+    growth->apMag  = psVectorAlloc (growth->radius->n, PS_TYPE_F32);
+
+    // XXX may want to extend this to allow for a different refRadius;
+    growth->refRadius = refRadius;
+    growth->maxRadius = maxRadius;
+    growth->apLoss = 0.0;
+    growth->fitMag = 0.0;
+    return growth;
+}
+
+psF32 pmGrowthCurveCorrect(pmGrowthCurve *growth, psF32 radius)
+{
+    PS_ASSERT_PTR_NON_NULL(growth, NAN);
+    float apRad = psVectorInterpolate (growth->radius, growth->apMag, radius);
+    float apCor = growth->apRef - apRad;
+    return apCor;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmGrowthCurve.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmGrowthCurve.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmGrowthCurve.h	(revision 22158)
@@ -0,0 +1,35 @@
+/* @file  pmGrowthCurve.h
+ * @brief functions to manipulate the curve-of-growth data
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+# ifndef PM_GROWTH_CURVE_H
+# define PM_GROWTH_CURVE_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+typedef struct
+{
+    psVector *radius;
+    psVector *apMag;
+    psF32 refRadius;
+    psF32 maxRadius;
+    psF32 fitMag;
+    psF32 apRef;   // apMag[refRadius]
+    psF32 apLoss;  // fitMag - apRef
+}
+pmGrowthCurve;
+
+bool psMemCheckGrowthCurve(psPtr ptr);
+
+pmGrowthCurve *pmGrowthCurveAlloc (psF32 minRadius, psF32 maxRadius, psF32 refRadius);
+psF32 pmGrowthCurveCorrect (pmGrowthCurve *growth, psF32 radius);
+
+/// @}
+# endif /* PM_GROWTH_CURVE_H */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModel.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModel.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModel.c	(revision 22158)
@@ -0,0 +1,412 @@
+/** @file  pmModel.c
+ *
+ *  Functions to define and manipulate object models
+ *
+ *  @author GLG, MHPCC
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.22 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-01-02 20:36:36 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmResiduals.h"
+#include "pmGrowthCurve.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmModelClass.h"
+
+static void modelFree(pmModel *tmp)
+{
+    psTrace("psModules.objects", 4, "---- %s() begin ----\n", __func__);
+    psFree(tmp->params);
+    psFree(tmp->dparams);
+    psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+}
+
+/******************************************************************************
+pmModelAlloc(): Allocate the pmModel structure, along with its parameters,
+and initialize the type member.  Initialize the params to 0.0.
+*****************************************************************************/
+pmModel *pmModelAlloc(pmModelType type)
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+
+    pmModelClass *class = pmModelClassSelect (type);
+    if (class == NULL) {
+        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
+        return(NULL);
+    }
+
+    pmModel *tmp = (pmModel *) psAlloc(sizeof(pmModel));
+    psMemSetDeallocator(tmp, (psFreeFunc) modelFree);
+
+    tmp->type = type;
+    tmp->chisq = 0.0;
+    tmp->chisqNorm = 0.0;
+    tmp->nDOF  = 0;
+    tmp->nIter = 0;
+    tmp->radiusFit = 0;
+    tmp->flags = PM_MODEL_STATUS_NONE;
+    tmp->residuals = NULL;              // XXX should the model own this memory?
+
+    psS32 Nparams = pmModelClassParameterCount(type);
+    assert (Nparams);
+
+    tmp->params  = psVectorAlloc(Nparams, PS_TYPE_F32);
+    tmp->dparams = psVectorAlloc(Nparams, PS_TYPE_F32);
+    assert (tmp->params);
+    assert (tmp->dparams);
+
+    for (psS32 i = 0; i < tmp->params->n; i++) {
+        tmp->params->data.F32[i] = 0.0;
+        tmp->dparams->data.F32[i] = 0.0;
+    }
+
+    tmp->modelFunc          = class->modelFunc;
+    tmp->modelFlux          = class->modelFlux;
+    tmp->modelRadius        = class->modelRadius;
+    tmp->modelLimits        = class->modelLimits;
+    tmp->modelGuess         = class->modelGuess;
+    tmp->modelFromPSF       = class->modelFromPSF;
+    tmp->modelParamsFromPSF = class->modelParamsFromPSF;
+    tmp->modelFitStatus     = class->modelFitStatus;
+
+    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    return(tmp);
+}
+
+bool psMemCheckModel(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) modelFree);
+}
+
+// copy model to a new structure
+pmModel *pmModelCopy (pmModel *model)
+{
+    PS_ASSERT_PTR_NON_NULL(model, NULL);
+
+    pmModel *new = pmModelAlloc (model->type);
+
+    new->chisq     = model->chisq;
+    new->nDOF      = model->nDOF;
+    new->nIter     = model->nIter;
+    new->flags     = model->flags;
+    new->radiusFit = model->radiusFit;
+
+    for (int i = 0; i < new->params->n; i++) {
+        new->params->data.F32[i]  = model->params->data.F32[i];
+        new->dparams->data.F32[i] = model->dparams->data.F32[i];
+    }
+
+    // note that model->residuals is just a reference
+    new->residuals = model->residuals;
+
+    return (new);
+}
+
+/******************************************************************************
+    pmModelEval(source, level, row): evaluates the model function at the specified coords.
+
+    NOTE: The coords are in subImage source->pixel coords, not image coords.
+
+    XXX: Use static vectors for x (NO: needs to be thread safe)
+*****************************************************************************/
+psF32 pmModelEval(pmModel *model, psImage *image, psS32 col, psS32 row)
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_PTR_NON_NULL(image, NAN);
+    PS_ASSERT_PTR_NON_NULL(model, NAN);
+    PS_ASSERT_PTR_NON_NULL(model->params, NAN);
+
+    // Allocate the x coordinate structure and convert row/col to image space.
+    //
+    psVector *x = psVectorAlloc(2, PS_TYPE_F32);
+    x->data.F32[0] = (psF32) (col + image->col0);
+    x->data.F32[1] = (psF32) (row + image->row0);
+    psF32 tmpF;
+
+    tmpF = model->modelFunc (NULL, model->params, x);
+    psFree(x);
+    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    return(tmpF);
+}
+
+psF32 pmModelEvalWithOffset(pmModel *model, psImage *image, psS32 col, psS32 row, int dx, int dy)
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_PTR_NON_NULL(image, false);
+    PS_ASSERT_PTR_NON_NULL(model, false);
+    PS_ASSERT_PTR_NON_NULL(model->params, false);
+
+    // Allocate the x coordinate structure and convert row/col to image space.
+    //
+    psVector *x = psVectorAlloc(2, PS_TYPE_F32);
+    x->data.F32[0] = (psF32) (col + image->col0 + dx);
+    x->data.F32[1] = (psF32) (row + image->row0 + dy);
+    psF32 tmpF;
+
+    tmpF = model->modelFunc (NULL, model->params, x);
+    psFree(x);
+    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    return(tmpF);
+}
+
+static bool AddOrSubModel(psImage *image,
+                          psImage *mask,
+                          pmModel *model,
+                          pmModelOpMode mode,
+                          bool add,
+                          psMaskType maskVal,
+                          int dx,
+                          int dy
+    )
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+
+    PS_ASSERT_PTR_NON_NULL(model, false);
+    PS_ASSERT_IMAGE_NON_NULL(image, false);
+    PS_ASSERT_IMAGE_TYPE(image, PS_TYPE_F32, false);
+
+    psVector *x = psVectorAlloc(2, PS_TYPE_F32);
+    psVector *params = model->params;
+
+    psS32 imageCol;
+    psS32 imageRow;
+    psF32 pixelValue;
+
+    // save original values; restore before returning
+    // use the true source position for the residual model
+    // the PSF model has presumably already been set for this coordinate
+    float xPos    = params->data.F32[PM_PAR_XPOS];
+    float yPos    = params->data.F32[PM_PAR_YPOS];
+    float IoSave  = params->data.F32[PM_PAR_I0];
+    float skySave = params->data.F32[PM_PAR_SKY];
+
+    if (mode & PM_MODEL_OP_NORM) {
+        params->data.F32[PM_PAR_I0] = 1.0;
+    }
+    if (!(mode & PM_MODEL_OP_SKY)) {
+        params->data.F32[PM_PAR_SKY] = 0.0;
+    }
+    if (mode & PM_MODEL_OP_CENTER) {
+        params->data.F32[PM_PAR_XPOS] = image->col0 + 0.5*image->numCols;
+        params->data.F32[PM_PAR_YPOS] = image->row0 + 0.5*image->numRows;
+    }
+
+    // use these values for this realization
+    float xCenter  = params->data.F32[PM_PAR_XPOS];
+    float yCenter  = params->data.F32[PM_PAR_YPOS];
+    float Io       = params->data.F32[PM_PAR_I0];
+
+    int xBin = 1;
+    int yBin = 1;
+    float xResidCenter = 0.0;
+    float yResidCenter = 0.0;
+
+    psImage *myRo = NULL;
+    psImage *myRx = NULL;
+    psImage *myRy = NULL;
+    psImageInterpolateOptions *Ro = NULL;
+    psImageInterpolateOptions *Rx = NULL;
+    psImageInterpolateOptions *Ry = NULL;
+    if (model->residuals && (mode & (PM_MODEL_OP_RES0 | PM_MODEL_OP_RES1))) {
+        // if the residual image and object image don't match,
+        // supply an appropriately overlapped residual image
+        psImage *inRo = model->residuals->Ro;
+        psImage *inRx = model->residuals->Rx;
+        psImage *inRy = model->residuals->Ry;
+        xBin = model->residuals->xBin;
+        yBin = model->residuals->yBin;
+        xResidCenter = model->residuals->xCenter;
+        yResidCenter = model->residuals->yCenter;
+        if ((image->numCols != inRo->numCols) ||
+            (image->numRows != inRo->numRows)) {
+            myRo = psImageAlloc (image->numCols, image->numRows, PS_TYPE_F32);
+            myRx = psImageAlloc (image->numCols, image->numRows, PS_TYPE_F32);
+            myRy = psImageAlloc (image->numCols, image->numRows, PS_TYPE_F32);
+            // Difference between input and desired centres
+            int xDiff = (int)(inRo->numCols / 2) - (xPos - image->col0);
+            int yDiff = (int)(inRo->numRows / 2) - (yPos - image->row0);
+            xResidCenter -= xDiff;
+            yResidCenter -= yDiff;
+            for (int iy = 0; iy < myRo->numRows; iy++) {
+                int jy = iy + yDiff;
+                if ((jy < 0) || (jy >= inRo->numRows)) {
+                    for (int ix = 0; ix < myRo->numCols; ix++) {
+                        myRo->data.F32[iy][ix] = 0.0;
+                        myRx->data.F32[iy][ix] = 0.0;
+                        myRy->data.F32[iy][ix] = 0.0;
+                    }
+                    continue;
+                }
+                for (int ix = 0; ix < myRo->numCols; ix++) {
+                    int jx = ix + xDiff;
+                    if ((jx < 0) || (jx >= inRo->numCols)) {
+                        myRo->data.F32[iy][ix] = 0.0;
+                        myRx->data.F32[iy][ix] = 0.0;
+                        myRy->data.F32[iy][ix] = 0.0;
+                    } else {
+                        myRo->data.F32[iy][ix] = inRo->data.F32[jy][jx];
+                        myRx->data.F32[iy][ix] = inRx->data.F32[jy][jx];
+                        myRy->data.F32[iy][ix] = inRy->data.F32[jy][jx];
+                    }
+                }
+            }
+        } else {
+            myRo = psMemIncrRefCounter (inRo);
+            myRx = psMemIncrRefCounter (inRx);
+            myRy = psMemIncrRefCounter (inRy);
+        }
+
+        Ro = psImageInterpolateOptionsAlloc(PS_INTERPOLATE_BILINEAR, myRo, NULL, mask, 0, 0.0, 0.0, 1, 0, 0.0);
+        Rx = psImageInterpolateOptionsAlloc(PS_INTERPOLATE_BILINEAR, myRx, NULL, NULL, 0, 0.0, 0.0, 1, 0, 0.0);
+        Ry = psImageInterpolateOptionsAlloc(PS_INTERPOLATE_BILINEAR, myRy, NULL, NULL, 0, 0.0, 0.0, 1, 0, 0.0);
+
+    }
+
+    for (psS32 iy = 0; iy < image->numRows; iy++) {
+        for (psS32 ix = 0; ix < image->numCols; ix++) {
+            if ((mask != NULL) && (mask->data.U8[iy][ix] & maskVal))
+                continue;
+
+            // Convert i/j to image coord space:
+            // XXX should we use using 0.5 pixel offset?
+            imageCol = ix + image->col0 + dx;
+            imageRow = iy + image->row0 + dy;
+
+            x->data.F32[0] = (float) imageCol;
+            x->data.F32[1] = (float) imageRow;
+
+            pixelValue = 0.0;
+
+            // add in the desired components for this coordinate
+            if (mode & PM_MODEL_OP_FUNC) {
+                pixelValue += model->modelFunc (NULL, params, x);
+            }
+
+            // get the contribution from the residual model
+            if (Ro) {
+                // fractional image position
+                float ox = xBin*(imageCol + 0.5 - xCenter) + xResidCenter;
+                float oy = yBin*(imageRow + 0.5 - yCenter) + yResidCenter;
+
+                psU8 mflux = 0;
+                if (mode & PM_MODEL_OP_RES0) {
+                    double Fo = 0.0;
+                    psImageInterpolate (&Fo, NULL, &mflux, ox, oy, Ro);
+                    if (!mflux && isfinite(Fo)) {
+                        pixelValue += Io*Fo;
+                    }
+                }
+                // skip Rx,Ry if Ro is masked
+                if (!mflux && (mode & PM_MODEL_OP_RES1)) {
+                    double Fx = 0.0;
+                    double Fy = 0.0;
+                    psImageInterpolate (&Fx, NULL, &mflux, ox, oy, Rx);
+                    psImageInterpolate (&Fy, NULL, &mflux, ox, oy, Ry);
+                    if (!mflux && isfinite(Fx) && isfinite(Fy)) {
+                        pixelValue += Io*(xPos*Fx + yPos*Fy);
+                    }
+                }
+            }
+
+            // add or subtract the value
+            if (add) {
+                image->data.F32[iy][ix] += pixelValue;
+            } else {
+                image->data.F32[iy][ix] -= pixelValue;
+            }
+        }
+    }
+
+    // restore original values
+    params->data.F32[PM_PAR_I0]   = IoSave;
+    params->data.F32[PM_PAR_SKY]  = skySave;
+    params->data.F32[PM_PAR_XPOS] = xPos;
+    params->data.F32[PM_PAR_YPOS] = yPos;
+
+    psFree(x);
+    psFree(Ro);
+    psFree(Rx);
+    psFree(Ry);
+    psFree(myRo);
+    psFree(myRx);
+    psFree(myRy);
+    psTrace("psModules.objects", 3, "---- %s(true) end ----\n", __func__);
+    return(true);
+}
+
+/******************************************************************************
+ *****************************************************************************/
+bool pmModelAdd(psImage *image,
+                psImage *mask,
+                pmModel *model,
+                pmModelOpMode mode,
+                psMaskType maskVal)
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psBool rc = AddOrSubModel(image, mask, model, mode, true, maskVal, 0.0, 0.0);
+    psTrace("psModules.objects", 3, "---- %s(%d) end ----\n", __func__, rc);
+    return(rc);
+}
+
+/******************************************************************************
+ *****************************************************************************/
+bool pmModelSub(psImage *image,
+                psImage *mask,
+                pmModel *model,
+                pmModelOpMode mode,
+                psMaskType maskVal)
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psBool rc = AddOrSubModel(image, mask, model, mode, false, maskVal, 0.0, 0.0);
+    psTrace("psModules.objects", 3, "---- %s(%d) end ----\n", __func__, rc);
+    return(rc);
+}
+
+/******************************************************************************
+ *****************************************************************************/
+bool pmModelAddWithOffset(psImage *image,
+                          psImage *mask,
+                          pmModel *model,
+                          pmModelOpMode mode,
+                          psMaskType maskVal,
+                          int dx,
+                          int dy)
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psBool rc = AddOrSubModel(image, mask, model, mode, true, maskVal, dx, dy);
+    psTrace("psModules.objects", 3, "---- %s(%d) end ----\n", __func__, rc);
+    return(rc);
+}
+
+/******************************************************************************
+ *****************************************************************************/
+bool pmModelSubWithOffset(psImage *image,
+                          psImage *mask,
+                          pmModel *model,
+                          pmModelOpMode mode,
+                          psMaskType maskVal,
+                          int dx,
+                          int dy)
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psBool rc = AddOrSubModel(image, mask, model, mode, false, maskVal, dx, dy);
+    psTrace("psModules.objects", 3, "---- %s(%d) end ----\n", __func__, rc);
+    return(rc);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModel.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModel.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModel.h	(revision 22158)
@@ -0,0 +1,201 @@
+/* @file  pmModel.h
+ * @brief Functions to define and manipulate object models
+ *
+ * @author GLG, MHPCC
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-04-08 18:33:16 $
+ *
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+# ifndef PM_MODEL_H
+# define PM_MODEL_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+/* pointers for the functions types below are supplied to each pmModel, and can be used by
+   the programmer without needing to know the model class */
+
+typedef enum {
+    PM_MODEL_STATUS_NONE         = 0x00, ///< model fit not yet attempted, no other info
+    PM_MODEL_STATUS_FITTED       = 0x01, ///< model fit completed
+    PM_MODEL_STATUS_NONCONVERGE  = 0x02, ///< model fit did not converge
+    PM_MODEL_STATUS_OFFIMAGE     = 0x04, ///< model fit drove out of range
+    PM_MODEL_STATUS_BADARGS      = 0x08, ///< model fit called with invalid args
+    PM_MODEL_STATUS_LIMITS       = 0x10  ///< model parameters hit limits
+} pmModelStatus;
+
+typedef enum {
+    PM_MODEL_OP_NONE    = 0x00,
+    PM_MODEL_OP_FUNC    = 0x01,
+    PM_MODEL_OP_RES0    = 0x02,
+    PM_MODEL_OP_RES1    = 0x04,
+    PM_MODEL_OP_FULL    = 0x07,
+    PM_MODEL_OP_SKY     = 0x08,
+    PM_MODEL_OP_CENTER  = 0x10,
+    PM_MODEL_OP_NORM    = 0x20,
+    PM_MODEL_OP_NOISE   = 0x40,
+} pmModelOpMode;
+
+typedef struct pmModel pmModel;
+typedef struct pmSource pmSource;
+
+//  This function is the model chi-square minimization function for this model.
+typedef psMinimizeLMChi2Func pmModelFunc;
+
+//  This function sets the parameter limits for this model.
+typedef psMinimizeLMLimitFunc pmModelLimits;
+
+// This function returns the integrated flux for the given model parameters.
+typedef psF64 (*pmModelFlux)(const psVector *params);
+
+// This function returns the radius at which the given model and parameters
+// achieves the given flux.
+typedef psF64 (*pmModelRadius)(const psVector *params, double flux);
+
+//  This function provides the model guess parameters based on the details of
+//  the given source.
+typedef bool (*pmModelGuessFunc)(pmModel *model, pmSource *source);
+
+//  This function constructs the PSF model for the given source based on the
+//  supplied psf and the EXT model for the object.
+typedef bool (*pmModelFromPSFFunc)(pmModel *modelPSF, pmModel *modelEXT, const pmPSF *psf);
+
+//  This function sets the model parameters based on the PSF for a given coordinate and central
+//  intensity
+typedef bool (*pmModelParamsFromPSF)(pmModel *model, const pmPSF *psf, float Xo, float Yo, float Io);
+
+//  This function returns the success / failure status of the given model fit
+typedef bool (*pmModelFitStatusFunc)(pmModel *model);
+
+/** pmModel data structure
+ *
+ * Every source may have two types of models: a PSF model and a EXT (extended-source)
+ * model. The PSF model represents the best fit of the image PSF to the specific
+ * object. In this case, the PSF-dependent parameters are specified for the
+ * object by the PSF, not by the fit. The EXT model represents the best fit of
+ * the given model to the object, with all shape parameters floating in the fit.
+ *
+ */
+struct pmModel {
+    pmModelType type;                   ///< Model to be used.
+    psVector *params;                   ///< Paramater values.
+    psVector *dparams;                  ///< Parameter errors.
+    float chisq;                        ///< Fit chi-squared.
+    float chisqNorm;                    ///< re-normalized fit chi-squared.
+    float mag;				///< integrated model magnitude 
+    float magErr;			///< integrated model magnitude error
+    int nDOF;                           ///< number of degrees of freedom
+    int nIter;                          ///< number of iterations to reach min
+    pmModelStatus flags;                ///< model status flags
+    float radiusFit;                    ///< fit radius actually used
+    pmResiduals *residuals;             ///< normalized PSF residuals
+
+    // functions for this model which depend on the model class
+    pmModelFunc          modelFunc;
+    pmModelFlux          modelFlux;
+    pmModelRadius        modelRadius;
+    pmModelLimits        modelLimits;
+    pmModelGuessFunc     modelGuess;
+    pmModelFromPSFFunc   modelFromPSF;
+    pmModelParamsFromPSF modelParamsFromPSF;
+    pmModelFitStatusFunc modelFitStatus;
+};
+
+/** Symbolic names for the elements of [d]params
+ * Note: these are #defines not enums as a given element of [d]params
+ * may/will correspond to different parameters in different contexts
+ */
+#define PM_PAR_SKY 0   ///< Sky
+#define PM_PAR_I0 1   ///< Central intensity
+#define PM_PAR_XPOS 2   ///< X centre of object
+#define PM_PAR_YPOS 3   ///< Y centre of object
+#define PM_PAR_SXX 4   ///< shape X^2 moment
+#define PM_PAR_SYY 5   ///< shape Y^2 moment
+#define PM_PAR_SXY 6   ///< shape XY moment
+#define PM_PAR_7 7   ///< ??? Unknown parameter
+#define PM_PAR_8 8   ///< ??? Unknown parameter
+
+/** pmModelAlloc()
+ *
+ */
+pmModel *pmModelAlloc(pmModelType type);
+bool psMemCheckModel(psPtr ptr);
+
+// copy model to a new structure
+pmModel *pmModelCopy (pmModel *model);
+
+psF32 pmModelEval(pmModel *model, psImage *image, psS32 col, psS32 row);
+psF32 pmModelEvalWithOffset(pmModel *model, psImage *image, psS32 col, psS32 row, int dx, int dy);
+
+/** pmModelAdd()
+ *
+ * Add the given source model flux to/from the provided image. The boolean
+ * option center selects if the source is re-centered to the image center or if
+ * it is placed at its centroid location. The boolean option sky selects if the
+ * background sky is applied (TRUE) or not. The pixel range in the target image
+ * is at most the pixel range specified by the source.pixels image. The success
+ * status is returned.
+ *
+ */
+bool pmModelAdd(
+    psImage *image,                     ///< The output image (float)
+    psImage *mask,                      ///< The image pixel mask (valid == 0)
+    pmModel *model,                     ///< The input pmModel
+    pmModelOpMode mode,                 ///< mode to control how the model is added into the image
+    psMaskType maskVal                  ///< Value to mask
+);
+
+/** pmModelSub()
+ *
+ * Subtract the given source model flux to/from the provided image. The
+ * boolean option center selects if the source is re-centered to the image center
+ * or if it is placed at its centroid location. The boolean option sky selects if
+ * the background sky is applied (TRUE) or not. The pixel range in the target
+ * image is at most the pixel range specified by the source.pixels image. The
+ * success status is returned.
+ *
+ */
+bool pmModelSub(
+    psImage *image,                     ///< The output image (float)
+    psImage *mask,                      ///< The image pixel mask (valid == 0)
+    pmModel *model,                     ///< The input pmModel
+    pmModelOpMode mode,                 ///< mode to control how the model is added into the image
+    psMaskType maskVal                  ///< Value to mask
+);
+
+bool pmModelAddWithOffset(psImage *image,
+                          psImage *mask,
+                          pmModel *model,
+                          pmModelOpMode mode,
+                          psMaskType maskVal,
+                          int dx,
+                          int dy);
+
+bool pmModelSubWithOffset(psImage *image,
+                          psImage *mask,
+                          pmModel *model,
+                          pmModelOpMode mode,
+                          psMaskType maskVal,
+                          int dx,
+                          int dy);
+
+/** pmModelFitStatus()
+ *
+ * This function wraps the call to the model-specific function returned by
+ * pmModelFitStatusFunc_GetFunction.  The model-specific function examines the
+ * model parameters, parameter errors, Chisq, S/N, and other parameters available
+ * from model to decide if the particular fit was successful or not.
+ *
+ * XXX: Must code this.
+ *
+ */
+bool pmModelFitStatus(
+    pmModel *model                      ///< Model to be used
+);
+
+/// @}
+# endif /* PM_MODEL_H */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModelClass.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModelClass.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModelClass.c	(revision 22158)
@@ -0,0 +1,165 @@
+/** @file  pmModelClass.c
+ *
+ *  Functions to define and manipulate object model attributes
+ *
+ *  @author GLG, MHPCC
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-27 03:14:57 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmResiduals.h"
+#include "pmGrowthCurve.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmModelClass.h"
+#include "pmErrorCodes.h"
+
+// XXX shouldn't these be defined for us in pslib.h ???
+double hypot(double x, double y);
+double sqrt (double x);
+
+# include "models/pmModel_GAUSS.c"
+# include "models/pmModel_PGAUSS.c"
+# include "models/pmModel_QGAUSS.c"
+# include "models/pmModel_RGAUSS.c"
+# include "models/pmModel_SERSIC.c"
+
+static pmModelClass defaultModels[] = {
+    {"PS_MODEL_GAUSS",        7, pmModelFunc_GAUSS,   pmModelFlux_GAUSS,   pmModelRadius_GAUSS,   pmModelLimits_GAUSS,   pmModelGuess_GAUSS,  pmModelFromPSF_GAUSS,  pmModelParamsFromPSF_GAUSS,  pmModelFitStatus_GAUSS},
+    {"PS_MODEL_PGAUSS",       7, pmModelFunc_PGAUSS,  pmModelFlux_PGAUSS,  pmModelRadius_PGAUSS,  pmModelLimits_PGAUSS,  pmModelGuess_PGAUSS, pmModelFromPSF_PGAUSS, pmModelParamsFromPSF_PGAUSS, pmModelFitStatus_PGAUSS},
+    {"PS_MODEL_QGAUSS",       8, pmModelFunc_QGAUSS,  pmModelFlux_QGAUSS,  pmModelRadius_QGAUSS,  pmModelLimits_QGAUSS,  pmModelGuess_QGAUSS, pmModelFromPSF_QGAUSS, pmModelParamsFromPSF_QGAUSS, pmModelFitStatus_QGAUSS},
+    {"PS_MODEL_RGAUSS",       8, pmModelFunc_RGAUSS,  pmModelFlux_RGAUSS,  pmModelRadius_RGAUSS,  pmModelLimits_RGAUSS,  pmModelGuess_RGAUSS, pmModelFromPSF_RGAUSS, pmModelParamsFromPSF_RGAUSS, pmModelFitStatus_RGAUSS},
+    {"PS_MODEL_SERSIC",       8, pmModelFunc_SERSIC,  pmModelFlux_SERSIC,  pmModelRadius_SERSIC,  pmModelLimits_SERSIC,  pmModelGuess_SERSIC, pmModelFromPSF_SERSIC, pmModelParamsFromPSF_SERSIC, pmModelFitStatus_SERSIC}
+};
+
+static pmModelClass *models = NULL;
+static int Nmodels = 0;
+
+static void ModelClassFree (pmModelClass *modelClass)
+{
+    if (modelClass == NULL)
+        return;
+    return;
+}
+
+pmModelClass *pmModelClassAlloc (int nModels)
+{
+    pmModelClass *modelClass = (pmModelClass *) psAlloc (nModels * sizeof(pmModelClass));
+    psMemSetDeallocator(modelClass, (psFreeFunc) ModelClassFree);
+    return (modelClass);
+}
+
+bool psMemCheckModelClass(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) ModelClassFree);
+}
+
+void pmModelClassAdd (pmModelClass *model)
+{
+    if (models == NULL) {
+        pmModelClassInit();
+    }
+
+    Nmodels ++;
+    models = (pmModelClass *) psRealloc (models, Nmodels*sizeof(pmModelClass));
+    models[Nmodels-1] = model[0];
+    return;
+}
+
+bool pmModelClassInit (void)
+{
+    // if we do not need to init, return false;
+    if (models != NULL) {
+        return false;
+    }
+
+    int Nnew = sizeof (defaultModels) / sizeof (pmModelClass);
+
+    models = pmModelClassAlloc (Nnew);
+    for (int i = 0; i < Nnew; i++) {
+        models[i] = defaultModels[i];
+    }
+    Nmodels = Nnew;
+    return true;
+}
+
+pmModelClass *pmModelClassSelect (pmModelType type)
+{
+    if (models == NULL) {
+        pmModelClassInit();
+    }
+
+    if ((type < 0) || (type >= Nmodels)) {
+        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
+        return (NULL);
+    }
+    return (&models[type]);
+}
+
+void pmModelClassCleanup (void)
+{
+    psFree (models);
+    models = NULL;
+    Nmodels = 0;
+    return;
+}
+
+psS32 pmModelClassParameterCount (pmModelType type)
+{
+    if (models == NULL) {
+        pmModelClassInit();
+    }
+
+    if ((type < 0) || (type >= Nmodels)) {
+        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
+        return (0);
+    }
+    return (models[type].nParams);
+}
+
+psS32 pmModelClassGetType (const char *name)
+{
+    if (models == NULL) {
+        pmModelClassInit();
+    }
+
+    for (int i = 0; i < Nmodels; i++) {
+        if (!strcmp(models[i].name, name)) {
+            return (i);
+        }
+    }
+    return (-1);
+}
+
+char *pmModelClassGetName (pmModelType type)
+{
+    if (models == NULL) {
+        pmModelClassInit();
+    }
+
+    if ((type < 0) || (type >= Nmodels)) {
+        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
+        return (NULL);
+    }
+    return (models[type].name);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModelClass.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModelClass.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModelClass.h	(revision 22158)
@@ -0,0 +1,76 @@
+/* @file  pmModelClass.h
+ *
+ * The object model function types are desined to allow for the flexible addition of new
+ * object models. Every object model, with parameters represented by pmModel, has an
+ * associated set of functions which provide necessary support operations.  A These
+ * functions allow the programmer to select the approriate function or property for a
+ * specific object model class.
+ *
+ * Every model instance belongs to a class of models, defined by the value of the
+ * pmModelType type entry. Various functions need access to information about each of the
+ * models. Some of this information varies from model to model, and may depend on the
+ * current parameter values or other data quantities. In order to keep the code from
+ * requiring the information about each model to be coded into the low-level fitting
+ * routines, we define a collection of functions which allow us to abstract this type of
+ * model-dependent information. These generic functions take the model type and return the
+ * corresponding function pointer for the specified model. Each model is defined by
+ * creating this collection of specific functions, and placing them in a single file for
+ * each model. We define the following structure to carry the collection of information
+ * about the models.
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-27 03:14:57 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+# ifndef PM_MODEL_CLASS_H
+# define PM_MODEL_CLASS_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+typedef struct
+{
+    char *name;
+    int nParams;
+    pmModelFunc          modelFunc;
+    pmModelFlux          modelFlux;
+    pmModelRadius        modelRadius;
+    pmModelLimits        modelLimits;
+    pmModelGuessFunc     modelGuess;
+    pmModelFromPSFFunc   modelFromPSF;
+    pmModelParamsFromPSF modelParamsFromPSF;
+    pmModelFitStatusFunc modelFitStatus;
+} pmModelClass;
+
+// allocate a pmModelClass to hold nModels entries
+pmModelClass *pmModelClassAlloc (int nModels);
+
+//
+bool psMemCheckModelClass(psPtr ptr);
+
+// initialize the internal (static) model class with the default models
+bool pmModelClassInit (void);
+
+// free the internal (static) model class
+void pmModelClassCleanup (void);
+
+// add a new model class to the collection of model classes
+void pmModelClassAdd (pmModelClass *modelClass);
+
+// get the specified model class
+pmModelClass *pmModelClassSelect (pmModelType type);
+
+// This function returns the number of parameters used by the listed function.
+int pmModelClassParameterCount (pmModelType type);
+
+// This function returns the user-space model names for the specified model type.
+char *pmModelClassGetName (pmModelType type);
+
+// This function returns the internal model type code for the user-space model names.
+pmModelType pmModelClassGetType (const char *name);
+
+/// @}
+# endif /* PM_MODEL_CLASS_H */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModelGroup.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModelGroup.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModelGroup.c	(revision 22158)
@@ -0,0 +1,202 @@
+/** @file  pmModelGroup.c
+ *
+ *  Functions to define and manipulate object model attributes
+ *
+ *  @author GLG, MHPCC
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmGrowthCurve.h"
+#include "pmResiduals.h"
+#include "pmModel.h"
+#include "pmModelGroup.h"
+#include "pmErrorCodes.h"
+
+// XXX shouldn't these be defined for us in pslib.h ???
+double hypot(double x, double y);
+double sqrt (double x);
+
+# include "models/pmModel_GAUSS.c"
+# include "models/pmModel_PGAUSS.c"
+# include "models/pmModel_QGAUSS.c"
+# include "models/pmModel_RGAUSS.c"
+# include "models/pmModel_SERSIC.c"
+
+static pmModelGroup defaultModels[] = {
+                                          {"PS_MODEL_GAUSS",        7, pmModelFunc_GAUSS,   pmModelFlux_GAUSS,   pmModelRadius_GAUSS,   pmModelLimits_GAUSS,   pmModelGuess_GAUSS,  pmModelFromPSF_GAUSS,  pmModelFitStatus_GAUSS},
+                                          {"PS_MODEL_PGAUSS",       7, pmModelFunc_PGAUSS,  pmModelFlux_PGAUSS,  pmModelRadius_PGAUSS,  pmModelLimits_PGAUSS,  pmModelGuess_PGAUSS, pmModelFromPSF_PGAUSS, pmModelFitStatus_PGAUSS},
+                                          {"PS_MODEL_QGAUSS",       8, pmModelFunc_QGAUSS,  pmModelFlux_QGAUSS,  pmModelRadius_QGAUSS,  pmModelLimits_QGAUSS,  pmModelGuess_QGAUSS, pmModelFromPSF_QGAUSS, pmModelFitStatus_QGAUSS},
+                                          {"PS_MODEL_RGAUSS",       8, pmModelFunc_RGAUSS,  pmModelFlux_RGAUSS,  pmModelRadius_RGAUSS,  pmModelLimits_RGAUSS,  pmModelGuess_RGAUSS, pmModelFromPSF_RGAUSS, pmModelFitStatus_RGAUSS},
+                                          {"PS_MODEL_SERSIC",       8, pmModelFunc_SERSIC,  pmModelFlux_SERSIC,  pmModelRadius_SERSIC,  pmModelLimits_SERSIC,  pmModelGuess_SERSIC, pmModelFromPSF_SERSIC, pmModelFitStatus_SERSIC}
+                                      };
+
+static pmModelGroup *models = NULL;
+static int Nmodels = 0;
+
+static void ModelGroupFree (pmModelGroup *modelGroup)
+{
+
+    if (modelGroup == NULL)
+        return;
+    return;
+}
+
+pmModelGroup *pmModelGroupAlloc (int nModels)
+{
+
+    pmModelGroup *modelGroup = (pmModelGroup *) psAlloc (nModels * sizeof(pmModelGroup));
+    psMemSetDeallocator(modelGroup, (psFreeFunc) ModelGroupFree);
+    return (modelGroup);
+}
+
+bool psMemCheckModelGroup(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) ModelGroupFree);
+}
+
+void pmModelGroupAdd (pmModelGroup *model)
+{
+
+    if (models == NULL) {
+        pmModelGroupInit ();
+    }
+
+    Nmodels ++;
+    models = (pmModelGroup *) psRealloc (models, Nmodels*sizeof(pmModelGroup));
+    models[Nmodels-1] = model[0];
+    return;
+}
+
+bool pmModelGroupInit (void)
+{
+
+    // if we do not need to init, return false;
+    if (models != NULL)
+        return false;
+
+    int Nnew = sizeof (defaultModels) / sizeof (pmModelGroup);
+
+    models = pmModelGroupAlloc (Nnew);
+    for (int i = 0; i < Nnew; i++) {
+        models[i] = defaultModels[i];
+    }
+    Nmodels = Nnew;
+    return true;
+}
+
+void pmModelGroupCleanup (void)
+{
+    psFree (models);
+    models = NULL;
+    return;
+}
+
+pmModelFunc pmModelFunc_GetFunction (pmModelType type)
+{
+    if ((type < 0) || (type >= Nmodels)) {
+        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
+        return (NULL);
+    }
+    return (models[type].modelFunc);
+}
+
+pmModelFlux pmModelFlux_GetFunction (pmModelType type)
+{
+    if ((type < 0) || (type >= Nmodels)) {
+        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
+        return (NULL);
+    }
+    return (models[type].modelFlux);
+}
+
+pmModelRadius pmModelRadius_GetFunction (pmModelType type)
+{
+    if ((type < 0) || (type >= Nmodels)) {
+        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
+        return (NULL);
+    }
+    return (models[type].modelRadius);
+}
+
+pmModelLimits pmModelLimits_GetFunction (pmModelType type)
+{
+    if ((type < 0) || (type >= Nmodels)) {
+        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
+        return (NULL);
+    }
+    return (models[type].modelLimits);
+}
+
+pmModelGuessFunc pmModelGuessFunc_GetFunction (pmModelType type)
+{
+    if ((type < 0) || (type >= Nmodels)) {
+        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
+        return (NULL);
+    }
+    return (models[type].modelGuessFunc);
+}
+
+pmModelFitStatusFunc pmModelFitStatusFunc_GetFunction (pmModelType type)
+{
+    if ((type < 0) || (type >= Nmodels)) {
+        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
+        return (NULL);
+    }
+    return (models[type].modelFitStatusFunc);
+}
+
+pmModelFromPSFFunc pmModelFromPSFFunc_GetFunction (pmModelType type)
+{
+    if ((type < 0) || (type >= Nmodels)) {
+        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
+        return (NULL);
+    }
+    return (models[type].modelFromPSFFunc);
+}
+
+psS32 pmModelParameterCount (pmModelType type)
+{
+    if ((type < 0) || (type >= Nmodels)) {
+        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
+        return (0);
+    }
+    return (models[type].nParams);
+}
+
+psS32 pmModelSetType (char *name)
+{
+    for (int i = 0; i < Nmodels; i++) {
+        if (!strcmp(models[i].name, name)) {
+            return (i);
+        }
+    }
+    return (-1);
+}
+
+char *pmModelGetType (pmModelType type)
+{
+    if ((type < 0) || (type >= Nmodels)) {
+        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
+        return (NULL);
+    }
+    return (models[type].name);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModelGroup.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModelGroup.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModelGroup.h	(revision 22158)
@@ -0,0 +1,201 @@
+/* @file  pmModelGroup.h
+ *
+ * The object model function types are desined to allow for the flexible addition of new object
+ * models. Every object model, with parameters represented by pmModel, has an associated set of
+ * functions which provide necessary support operations. A set of abstract functions allow the
+ * programmer to select the approriate function or property for a specific named object model.
+ *
+ * Every model instance belongs to a class of models, defined by the value of
+ * the pmModelType type entry. Various functions need access to information about
+ * each of the models. Some of this information varies from model to model, and
+ * may depend on the current parameter values or other data quantities. In order
+ * to keep the code from requiring the information about each model to be coded
+ * into the low-level fitting routines, we define a collection of functions which
+ * allow us to abstract this type of model-dependent information. These generic
+ * functions take the model type and return the corresponding function pointer
+ * for the specified model. Each model is defined by creating this collection of
+ * specific functions, and placing them in a single file for each model. We
+ * define the following structure to carry the collection of information about
+ * the models.
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+# ifndef PM_MODEL_GROUP_H
+# define PM_MODEL_GROUP_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+//  This function is the model chi-square minimization function for this model.
+typedef psMinimizeLMChi2Func pmModelFunc;
+
+//  This function sets the parameter limits for this model.
+typedef psMinimizeLMLimitFunc pmModelLimits;
+
+// This function returns the integrated flux for the given model parameters.
+typedef psF64 (*pmModelFlux)(const psVector *params);
+
+// This function returns the radius at which the given model and parameters
+// achieves the given flux.
+typedef psF64 (*pmModelRadius)(const psVector *params, double flux);
+
+//  This function provides the model guess parameters based on the details of
+//  the given source.
+typedef bool (*pmModelGuessFunc)(pmModel *model, pmSource *source);
+
+//  This function constructs the PSF model for the given source based on the
+//  supplied psf and the EXT model for the object.
+typedef bool (*pmModelFromPSFFunc)(pmModel *modelPSF, pmModel *modelEXT, pmPSF *psf);
+
+//  This function sets the model parameters based on the PSF for a given coordinate and central
+//  intensity
+typedef bool (*pmModelParamsFromPSF)(pmModel *model, pmPSF *psf, float Xo, float Yo, float Io);
+
+//  This function returns the success / failure status of the given model fit
+typedef bool (*pmModelFitStatusFunc)(pmModel *model);
+
+typedef struct
+{
+    char *name;
+    int nParams;
+    pmModelFunc          modelFunc;
+    pmModelFlux          modelFlux;
+    pmModelRadius        modelRadius;
+    pmModelLimits        modelLimits;
+    pmModelGuessFunc     modelGuessFunc;
+    pmModelFromPSFFunc   modelFromPSFFunc;
+    pmModelParamsFromPSF modelParamsFromPSF;
+    pmModelFitStatusFunc modelFitStatusFunc;
+}
+pmModelGroup;
+
+// allocate a pmModelGroup to hold nModels entries
+pmModelGroup *pmModelGroupAlloc (int nModels);
+
+bool psMemCheckModelGroup(psPtr ptr);
+
+// initialize the internal (static) model group with the default models
+bool pmModelGroupInit (void);
+
+// free the internal (static) model group
+void pmModelGroupCleanup (void);
+
+// add a new model to the internal (static) model group
+void pmModelGroupAdd (pmModelGroup *model);
+
+/* This function returns the number of parameters used by the listed function.
+ */
+int pmModelParameterCount(
+    pmModelType type                    ///< Add comment.
+);
+
+
+/* This function returns the user-space model names for the specified model type.
+ */
+char *pmModelGetType(
+    pmModelType type                    ///< Add comment.
+);
+
+
+/**
+ * 
+ * This function returns the internal model type code for the user-space model names.
+ * 
+ */
+pmModelType pmModelSetType(
+    char *name                          ///< Add comment.
+);
+
+/**
+ * 
+ *  Each of the function types above has a corresponding function which returns
+ *  the function given the model type:
+ * 
+ */
+
+/**
+ * 
+ * pmModelFunc is the function used to determine the value of the model at a
+ * specific coordinate, and is the one used by psMinimizeLMChi2.
+ * 
+ */
+pmModelFunc          pmModelFunc_GetFunction (pmModelType type);
+
+
+/**
+ * 
+ * pmModelFlux returns the total integrated flux for the given input parameters.
+ * 
+ */
+pmModelFlux          pmModelFlux_GetFunction (pmModelType type);
+
+
+/**
+ * 
+ * pmModelRadius returns the scaling radius at which the flux of the model
+ * matches the specified flux. This presumes that the model is a function of an
+ * elliptical contour.
+ * 
+ */
+pmModelRadius        pmModelRadius_GetFunction (pmModelType type);
+
+
+/**
+ * 
+ * pmModelLimits sets the parameter limit vectors for the function.
+ * 
+ */
+pmModelLimits        pmModelLimits_GetFunction (pmModelType type);
+
+
+/**
+ * 
+ * pmModelGuessFunc generates an initial guess for the model based on the
+ * provided source statistics (moments and pixel values as needed).
+ * 
+ */
+pmModelGuessFunc     pmModelGuessFunc_GetFunction (pmModelType type);
+
+
+/**
+ * 
+ * pmModelFromPSFFunc takes as input a representation of the psf and a value
+ * for the model and fills in the PSF parameters of the model. The input
+ * primarily relies upon the centroid coordinates of the input model, though the
+ * normalization may potentially be used.
+ * 
+ */
+pmModelFromPSFFunc   pmModelFromPSFFunc_GetFunction (pmModelType type);
+
+
+/**
+ * 
+ * pmModelFitStatusFunc returns a true or false values based on the success or
+ * failure of a model fit.  The success is determined by quantities such as the
+ * chisq or the signal-to-noise.
+ * 
+ */
+pmModelFitStatusFunc pmModelFitStatusFunc_GetFunction (pmModelType type);
+
+
+/** pmSourceModelGuess()
+ *
+ * Convert available data to an initial guess for the given model. This
+ * function allocates a pmModel entry for the pmSource structure based on the
+ * provided model selection. The method of defining the model parameter guesses
+ * are specified for each model below. The guess values are placed in the model
+ * parameters. The function returns TRUE on success or FALSE on failure.
+ *
+ */
+pmModel *pmSourceModelGuess(
+    pmSource *source,   ///< The input pmSource
+    pmModelType model   ///< The type of model to be created.
+);
+
+/// @}
+# endif /* PM_MODEL_GROUP_H */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModelUtils.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModelUtils.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModelUtils.c	(revision 22158)
@@ -0,0 +1,95 @@
+/** @file  pmModelUtils.c
+ *
+ *  Functions to manipulate object models
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-12-15 01:22:11 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmResiduals.h"
+#include "pmGrowthCurve.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmErrorCodes.h"
+#include "pmModelUtils.h"
+
+/*****************************************************************************
+pmModelFromPSF (*modelEXT, *psf):  use the model position parameters to
+construct a realization of the PSF model at the object coordinates
+ *****************************************************************************/
+pmModel *pmModelFromPSF (pmModel *modelEXT, const pmPSF *psf)
+{
+    PS_ASSERT_PTR_NON_NULL(psf, NULL);
+    PS_ASSERT_PTR_NON_NULL(modelEXT, NULL);
+
+    // allocate a new pmModel to hold the PSF version
+    pmModel *modelPSF = pmModelAlloc (psf->type);
+
+    // set model parameters for this source based on PSF information
+    if (!modelEXT->modelFromPSF (modelPSF, modelEXT, psf)) {
+        psError(PM_ERR_PSF, false, "Failed to set model params from PSF");
+        psFree(modelPSF);
+        return NULL;
+    }
+    // XXX note that model->residuals is just a reference
+    modelPSF->residuals = psf->residuals;
+
+    return (modelPSF);
+}
+
+// instantiate a model for the PSF at this location with peak flux
+// NOTE: psf and (Xo,Yo) are defined wrt chip coordinates
+pmModel *pmModelFromPSFforXY (const pmPSF *psf, float Xo, float Yo, float Io)
+{
+    PS_ASSERT_PTR_NON_NULL(psf, NULL);
+
+    // allocate a new pmModel to hold the PSF version
+    pmModel *modelPSF = pmModelAlloc (psf->type);
+
+    // set model parameters for this source based on PSF information
+    if (!modelPSF->modelParamsFromPSF (modelPSF, psf, Xo, Yo, Io)) {
+        psError(PM_ERR_PSF, false, "Failed to set model params from PSF");
+        psFree(modelPSF);
+        return NULL;
+    }
+
+    // XXX note that model->residuals is just a reference
+    modelPSF->residuals = psf->residuals;
+
+    return (modelPSF);
+}
+
+// set this model to have the requested flux
+bool pmModelSetFlux (pmModel *model, float flux) {
+    PS_ASSERT_PTR_NON_NULL(model, NULL);
+    PS_ASSERT_PTR_NON_NULL(model->params, NULL);
+
+    // set Io to be 1.0
+    model->params->data.F32[PM_PAR_I0] = 1.0;
+
+    // determine the normalized flux
+    float normFlux = model->modelFlux (model->params);
+    assert (isfinite(normFlux));
+    assert (normFlux > 0);
+
+    // set the desired normalization
+    model->params->data.F32[PM_PAR_I0] = flux / normFlux;
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModelUtils.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModelUtils.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmModelUtils.h	(revision 22158)
@@ -0,0 +1,47 @@
+/* @file  pmModelUtils.h
+ *
+ * Utility functions for working with pmSources
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-12-15 01:22:11 $
+ * Copyright 2007 IfA, University of Hawaii
+ */
+
+# ifndef PM_MODEL_UTILS_H
+# define PM_MODEL_UTILS_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+/**
+ *
+ * This function constructs a pmModel instance based on the pmPSF description
+ * of the PSF. The input is a pmModel with at least the values of the centroid
+ * coordinates (possibly normalization if this is needed) defined. The values of
+ * the PSF-dependent parameters are specified for the specific realization based
+ * on the coordinates of the object.
+ *
+ */
+pmModel *pmModelFromPSF(
+    pmModel *model,                     ///< Add comment
+    const pmPSF *psf                    ///< Add comment
+);
+
+pmModel *pmModelFromPSFforXY (
+    const pmPSF *psf,
+    float Xo,
+    float Yo,
+    float Io
+    );
+
+bool pmModelSetFlux (
+    pmModel *model,
+    float flux
+    );
+
+
+
+/// @}
+# endif /* PM_MODEL_UTILS_H */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmMoments.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmMoments.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmMoments.c	(revision 22158)
@@ -0,0 +1,44 @@
+/** @file  pmMoments.c
+ *
+ *  Functions defining the pmMoments structure
+ *
+ *  @author GLG, MHPCC
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-09-15 09:49:01 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+#include "pmMoments.h"
+
+/******************************************************************************
+pmMomentsAlloc(): Allocate the pmMoments structure and initialize the members
+to zero.
+*****************************************************************************/
+pmMoments *pmMomentsAlloc()
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    pmMoments *tmp = (pmMoments *) psAlloc(sizeof(pmMoments));
+    tmp->x = 0.0;
+    tmp->y = 0.0;
+    tmp->Sx = 0.0;
+    tmp->Sy = 0.0;
+    tmp->Sxy = 0.0;
+    tmp->Sum = 0.0;
+    tmp->Peak = 0.0;
+    tmp->Sky = 0.0;
+    tmp->nPixels = 0;
+
+    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    return(tmp);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmMoments.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmMoments.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmMoments.h	(revision 22158)
@@ -0,0 +1,46 @@
+/* @file  pmMoments.h
+ * @brief Definitions of the moments structure
+ *
+ * @author GLG, MHPCC
+ *
+ * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-01-24 02:54:15 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+# ifndef PM_MOMENTS_H
+# define PM_MOMENTS_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+/** pmMoments data structure
+ *
+ * One of the simplest measurements which can be made quickly for an object
+ * are the object moments. We specify a structure to carry the moment information
+ * for a specific source:
+ *
+ */
+typedef struct
+{
+    float x;     ///< X-coord of centroid.
+    float y;     ///< Y-coord of centroid.
+    float Sx;    ///< x-second moment.
+    float Sy;    ///< y-second moment.
+    float Sxy;   ///< xy cross moment.
+    float Sum;   ///< Pixel sum above sky (background).
+    float Peak;  ///< Peak counts above sky.
+    float Sky;   ///< Sky level (background).
+    float dSky;  ///< local Sky variance
+    float SN;    ///< approx signal-to-noise
+    int nPixels; ///< Number of pixels used.
+}
+pmMoments;
+
+/** pmMomentsAlloc()
+ *
+ */
+pmMoments *pmMomentsAlloc();
+
+/// @}
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmObjects.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmObjects.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmObjects.c	(revision 22158)
@@ -0,0 +1,25 @@
+/** @file  pmObjects.c
+ *
+ *  This file will ...
+ *
+ *  @author GLG, MHPCC
+ *  @author EAM, IfA: significant modifications.
+ *
+ *  @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-09-15 09:49:01 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+#include "pmObjects.h"
+#include "pmModelGroup.h"
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmObjects.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmObjects.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmObjects.h	(revision 22158)
@@ -0,0 +1,68 @@
+/* @file  pmObjects.h
+ *
+ * The process of finding, measuring, and classifying astronomical sources on
+ * images is one of the critical tasks of the IPP or any astronomical software
+ * system. This file will define structures and functions related to the task
+ * of source detection and measurement. The elements defined in this section
+ * are generally low-level components which can be connected together to
+ * construct a complete object measurement suite.
+ *
+ * @author GLG, MHPCC
+ *
+ * @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-01-24 02:54:15 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#ifndef PM_OBJECTS_H
+#define PM_OBJECTS_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+#include <stdio.h>
+#include <math.h>
+#include <pslib.h>
+
+/**
+ *
+ * This function converts the source classification into the closest available
+ * approximation to the Dophot classification scheme:
+ * XXX EAM : fix this to use current source classification scheme
+ *
+ * PM_SOURCE_DEFECT: 8
+ * PM_SOURCE_SATURATED: 8
+ * PM_SOURCE_SATSTAR: 10
+ * PM_SOURCE_PSFSTAR: 1
+ * PM_SOURCE_GOODSTAR: 1
+ * PM_SOURCE_POOR_FIT_PSF: 7
+ * PM_SOURCE_FAIL_FIT_PSF: 4
+ * PM_SOURCE_FAINTSTAR: 4
+ * PM_SOURCE_GALAXY: 2
+ * PM_SOURCE_FAINT_GALAXY: 2
+ * PM_SOURCE_DROP_GALAXY: 2
+ * PM_SOURCE_FAIL_FIT_GAL: 2
+ * PM_SOURCE_POOR_FIT_GAL: 2
+ * PM_SOURCE_OTHER: ?
+ *
+ */
+int pmSourceDophotType(
+    pmSource *source                    ///< Add comment.
+);
+
+
+/** pmSourceSextractType()
+ *
+ * This function converts the source classification into the closest available
+ * approximation to the Sextractor classification scheme. the correspondence is
+ * not yet defined (TBD) .
+ *
+ * XXX: Must code this.
+ *
+ */
+int pmSourceSextractType(
+    pmSource *source                    ///< Add comment.
+);
+
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSF.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSF.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSF.c	(revision 22158)
@@ -0,0 +1,505 @@
+/** @file  pmPSF.c
+ *
+ * This file contains typedefs for the Point-Spread Function and prototypes
+ * for functions that calculate the PSF.
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.36 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-15 20:25:00 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/*****************************************************************************/
+/* INCLUDE FILES                                                             */
+/*****************************************************************************/
+
+#include <strings.h>  // for strcasecmp
+#include <pslib.h>
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmResiduals.h"
+#include "pmGrowthCurve.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmModelClass.h"
+#include "pmModelUtils.h"
+#include "pmSourcePhotometry.h"
+#include "pmFPAMaskWeight.h"
+#include "psVectorBracket.h"
+#include "pmErrorCodes.h"
+
+/*****************************************************************************/
+/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
+/*****************************************************************************/
+
+static void pmPSFOptionsFree (pmPSFOptions *options) {
+
+    if (!options) return;
+
+    psFree (options->stats);
+    return;
+}
+
+pmPSFOptions *pmPSFOptionsAlloc () {
+
+    pmPSFOptions *options = (pmPSFOptions *) psAlloc(sizeof(pmPSFOptions));
+    psMemSetDeallocator(options, (psFreeFunc) pmPSFOptionsFree);
+
+    options->type          = 0;
+
+    options->stats         = NULL;
+
+    options->psfTrendMode  = PM_TREND_NONE;
+    options->psfTrendNx    = 0;
+    options->psfTrendNy    = 0;
+    options->psfFieldNx    = 0;
+    options->psfFieldNy    = 0;
+    options->psfFieldXo    = 0;
+    options->psfFieldYo    = 0;
+
+    options->poissonErrorsPhotLMM = true;
+    options->poissonErrorsPhotLin = false;
+    options->poissonErrorsParams  = true;
+
+    return options;
+}
+
+bool psMemCheckPSFOptions(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmPSFOptionsFree);
+}
+
+/*****************************************************************************
+pmPSFFree(psf): function to free a pmPSF structure
+ *****************************************************************************/
+static void pmPSFFree (pmPSF *psf)
+{
+    if (psf == NULL) {
+        return;
+    }
+
+    psFree (psf->ChiTrend);
+    psFree (psf->psfTrendStats);
+    psFree (psf->ApTrend);
+    psFree (psf->FluxScale);
+    psFree (psf->growth);
+    psFree (psf->params);
+    psFree (psf->residuals);
+    return;
+}
+
+/*****************************************************************************
+ pmPSFAlloc (type): allocate a pmPSF.
+
+ NOTE: PSF model parameters which are not modeled on an image are set to NULL
+ in psf->params.
+
+ These are normally:
+
+ X-center
+ Y-center
+ Sky background value
+ Object Normalization
+ *****************************************************************************/
+pmPSF *pmPSFAlloc (const pmPSFOptions *options)
+{
+    PS_ASSERT_PTR_NON_NULL(options, NULL);
+    int Nparams;
+
+    pmPSF *psf = (pmPSF *) psAlloc(sizeof(pmPSF));
+    psMemSetDeallocator(psf, (psFreeFunc) pmPSFFree);
+
+    psf->type     = options->type;
+    psf->chisq    = 0.0;
+    psf->ApResid  = 0.0;
+    psf->dApResid = 0.0;
+    psf->skyBias  = 0.0;
+    psf->skySat   = 0.0;
+    psf->nPSFstars  = 0;
+    psf->nApResid   = 0;
+
+    psf->poissonErrorsPhotLMM = options->poissonErrorsPhotLMM;
+    psf->poissonErrorsPhotLin = options->poissonErrorsPhotLin;
+    psf->poissonErrorsParams = options->poissonErrorsParams;
+
+    // the ApTrend components are (x, y).  It may be represented with a polynomial or with a
+    // psImageMap.  We set it initially to NULL. the user must allocate it before using.
+    // psf->ApTrend = pmTrend2DAlloc (PM_TREND_MAP, Nx, Ny, 1, 1, stats);
+    psf->ApTrend = NULL;
+
+    // the flux scale is the relationship between the integrated flux and the peak flux for a
+    // psf model.  this is a 2D function of position, and is modeled with pmTrend2D after the
+    // psf model is determined for an image.  until it is determined, the flux calculation
+    // integrates the sources
+    psf->FluxScale = NULL;
+
+    if (psf->poissonErrorsPhotLMM) {
+        psf->ChiTrend = psPolynomial1DAlloc (PS_POLYNOMIAL_ORD, 1);
+    } else {
+        psf->ChiTrend = psPolynomial1DAlloc (PS_POLYNOMIAL_ORD, 2);
+    }
+
+    // don't define a growth curve : user needs to choose radius bins
+    psf->growth = NULL;
+
+    // by default, we do not construct the residual image
+    psf->residuals = NULL;
+
+    Nparams = pmModelClassParameterCount (options->type);
+    if (!Nparams) {
+        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
+        return(NULL);
+    }
+    psf->params = psArrayAlloc(Nparams);
+
+    // save the trend stats on the psf for use in pmPSFFromPSFtry
+    psf->psfTrendStats = psMemIncrRefCounter (options->stats);
+
+    // the psf parameters may have 2D variations represented as either a polynomial (ordinary
+    // or chebychev) or as an image map.  The size of the image map is determined by pmPSFtry
+    // by minimizing the scatter in the fitted data and the rms error in the complete image
+    // map.  In this case, the user-supplied options of psfTrendNx and psfTrendNy are the
+    // maximum value used for these axes.  For the polynomial terms, the order is not currently
+    // set, dynamically.  The value of psfTrendNx and psfTrendNy are used.
+
+    psImageBinning *binning = psImageBinningAlloc();
+    binning->nXruff = options->psfTrendNx;
+    binning->nYruff = options->psfTrendNy;
+    binning->nXfine = options->psfFieldNx;
+    binning->nYfine = options->psfFieldNy;
+
+    // for polynomial representations, nXruff, nYruff are the order number, and may be 0.
+    // in this case, we cannot set the psImageBinning scale because 0 would be invalid.  these
+    // elements are only used by the image map representation
+    if (options->psfTrendMode == PM_TREND_MAP) {
+        psImageBinningSetScale (binning, PS_IMAGE_BINNING_CENTER);
+        psImageBinningSetSkipByOffset (binning, options->psfFieldXo, options->psfFieldYo);
+    }
+
+    // trendNx & trendNy are used in pmPSFtry as the max for these values
+    psf->psfTrendMode = options->psfTrendMode;
+    psf->trendNx      = options->psfTrendNx;
+    psf->trendNy      = options->psfTrendNy;
+    psf->fieldNx      = options->psfFieldNx;
+    psf->fieldNy      = options->psfFieldNy;
+    psf->fieldXo      = options->psfFieldXo;
+    psf->fieldYo      = options->psfFieldYo;
+
+    // define the parameter trends
+    if (options->psfTrendMode != PM_TREND_NONE) {
+        for (int i = 0; i < psf->params->n; i++) {
+            if (i == PM_PAR_SKY) continue;
+            if (i == PM_PAR_I0) continue;
+            if (i == PM_PAR_XPOS) continue;
+            if (i == PM_PAR_YPOS) continue;
+
+            psf->params->data[i] = pmTrend2DNoImageAlloc (options->psfTrendMode, binning, options->stats);
+        }
+    }
+    psFree (binning);
+    return psf;
+}
+
+bool psMemCheckPSF(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmPSFFree);
+}
+
+// the PSF models the \sigma_{xy} variation of the elliptical contour as a function of position in the image with a
+// polynomial.  an individual object has a contour of the form (x^2/2sx^2) + (y^2/2sy^2) + sxy*x*y
+// these are the values of the model->params.  the psf->params term for sxy is actually fitted
+// to sxy/(sxx^-2 + syy^-2)^2
+
+// XXX this is only an approximate solution.  A better solution would be to fit the second moment, Mxy. the
+// problem here is that converting from Mxy,SXX,SYY -> SXY is a third order problem:
+// Mxy = SXY * (SXX^-4 + SYY^-4 - 2 SXY ^2)
+
+// input: model->param, output: psf->param[PM_PAR_SXY]
+double pmPSF_SXYfromModel (psF32 *modelPar)
+{
+    PS_ASSERT_PTR_NON_NULL(modelPar, NAN);
+
+    double SXX = modelPar[PM_PAR_SXX];
+    double SYY = modelPar[PM_PAR_SYY];
+    double SXY = modelPar[PM_PAR_SXY];
+
+    double par = SXY / PS_SQR(1.0 / PS_SQR(SXX) + 1.0 / PS_SQR(SYY));
+    return (par);
+}
+
+// input: fitted psf->param, output: model->param[PM_PAR_SXY]
+double pmPSF_SXYtoModel (psF32 *fittedPar)
+{
+    PS_ASSERT_PTR_NON_NULL(fittedPar, NAN);
+
+    double SXX = fittedPar[PM_PAR_SXX];
+    double SYY = fittedPar[PM_PAR_SYY];
+    double fit = fittedPar[PM_PAR_SXY];
+
+    double SXY = fit * PS_SQR(1.0 / PS_SQR(SXX) + 1.0 / PS_SQR(SYY));
+
+    assert (!isnan(SXY));
+
+    return SXY;
+}
+
+// New Concept: the PSF modelling function fits the polarization terms e0, e1, e2:
+
+// convert the parameters used in the fitted source model
+// to the parameters used in the 2D PSF model
+bool pmPSF_FitToModel (psF32 *fittedPar, float minMinorAxis)
+{
+    PS_ASSERT_PTR_NON_NULL(fittedPar, false);
+
+    psEllipsePol pol;
+
+    pol.e0 = fittedPar[PM_PAR_E0];
+    pol.e1 = fittedPar[PM_PAR_E1];
+    pol.e2 = fittedPar[PM_PAR_E2];
+
+    psEllipseAxes axes;
+    if (psEllipsePolToAxes (pol, minMinorAxis, &axes) != PS_ERR_NONE) {
+        psError(PM_ERR_PSF, false, "Failed to convert e[012] (%g,%g,%g) to axes",
+                pol.e0, pol.e1, pol.e2);
+        return false;
+    }
+    psEllipseShape shape = psEllipseAxesToShape (axes);
+
+    fittedPar[PM_PAR_SXX] = shape.sx * M_SQRT2;
+    fittedPar[PM_PAR_SYY] = shape.sy * M_SQRT2;
+    fittedPar[PM_PAR_SXY] = shape.sxy;
+
+    return true;
+}
+
+// convert the PSF parameters used in the 2D PSF model fit into the
+// parameters used in the source model
+psEllipsePol pmPSF_ModelToFit (psF32 *modelPar)
+{
+    // must assert non-NULL input parameter
+    psEllipsePol pol;
+    pol.e0 = NAN;
+    pol.e1 = NAN;
+    pol.e2 = NAN;
+    PS_ASSERT_PTR_NON_NULL(modelPar, pol);
+
+    psEllipseShape shape;
+
+    shape.sx  = modelPar[PM_PAR_SXX] / M_SQRT2;
+    shape.sy  = modelPar[PM_PAR_SYY] / M_SQRT2;
+    shape.sxy = modelPar[PM_PAR_SXY];
+
+    pol = psEllipseShapeToPol (shape);
+
+    return pol;
+}
+
+// convert the parameters used in the fitted source model to the psEllipseAxes representation
+// (major,minor,theta)
+psEllipseAxes pmPSF_ModelToAxes (psF32 *modelPar, double maxAR)
+{
+    psEllipseShape shape;
+    psEllipseAxes axes;
+    axes.major = NAN;
+    axes.minor = NAN;
+    axes.theta = NAN;
+//   XXX: must assert non-NULL input parameter
+    PS_ASSERT_PTR_NON_NULL(modelPar, axes);
+
+    shape.sx  = modelPar[PM_PAR_SXX] / M_SQRT2;
+    shape.sy  = modelPar[PM_PAR_SYY] / M_SQRT2;
+    shape.sxy = modelPar[PM_PAR_SXY];
+
+    if ((shape.sx == 0) || (shape.sy == 0)) {
+        axes.major = 0.0;
+        axes.minor = 0.0;
+        axes.theta = 0.0;
+    } else {
+        // XXX this is not really consistent with the model fit range above
+        axes = psEllipseShapeToAxes (shape, maxAR);
+    }
+
+    return axes;
+}
+
+// convert the psEllipseAxes representation (major,minor,theta) to the parameters used in the
+// fitted source model
+bool pmPSF_AxesToModel (psF32 *modelPar, psEllipseAxes axes)
+{
+    PS_ASSERT_PTR_NON_NULL(modelPar, false);
+
+    if ((axes.major <= 0) || (axes.minor <= 0)) {
+        modelPar[PM_PAR_SXX] = 0.0;
+        modelPar[PM_PAR_SYY] = 0.0;
+        modelPar[PM_PAR_SXY] = 0.0;
+        return true;
+    }
+
+    psEllipseShape shape = psEllipseAxesToShape (axes);
+
+    modelPar[PM_PAR_SXX] = shape.sx * M_SQRT2;
+    modelPar[PM_PAR_SYY] = shape.sy * M_SQRT2;
+    modelPar[PM_PAR_SXY] = shape.sxy;
+
+    return true;
+}
+
+// generate a psf model of the requested type, with fixed shape
+pmPSF *pmPSFBuildSimple (char *typeName, float sxx, float syy, float sxy, ...)
+{
+
+    va_list ap;
+    va_start(ap, sxy);
+
+    pmPSFOptions *options = pmPSFOptionsAlloc ();
+    options->type = pmModelClassGetType (typeName);
+    options->psfTrendMode = PM_TREND_POLY_ORD;
+    options->psfTrendNx = 0;
+    options->psfTrendNy = 0;
+
+    pmPSF *psf = pmPSFAlloc (options);
+
+    psVector *par = psVectorAlloc (psf->params->n, PS_TYPE_F32);
+    par->data.F32[PM_PAR_SXX] = sxx;
+    par->data.F32[PM_PAR_SYY] = syy;
+    par->data.F32[PM_PAR_SXY] = sxy;
+
+    psEllipsePol pol = pmPSF_ModelToFit(par->data.F32);
+
+    pmTrend2D *trend = NULL;
+
+    // set the psf shape parameters
+    trend = psf->params->data[PM_PAR_E0];
+    trend->poly->coeff[0][0] = pol.e0;
+
+    trend = psf->params->data[PM_PAR_E1];
+    trend->poly->coeff[0][0] = pol.e1;
+
+    trend = psf->params->data[PM_PAR_E2];
+    trend->poly->coeff[0][0] = pol.e2;
+
+    for (int i = PM_PAR_SXY + 1; i < psf->params->n; i++) {
+        trend = psf->params->data[i];
+        trend->poly->coeff[0][0] = (psF32)va_arg(ap, psF64);
+    }
+    va_end(ap);
+
+    psFree (par);
+    psFree (options);
+    return psf;
+}
+
+// we generate the growth curve for the center of the image with the specified psf model
+bool pmGrowthCurveGenerate (pmReadout *readout, pmPSF *psf, bool ignore, psMaskType maskVal, psMaskType markVal)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_PTR_NON_NULL(readout->image, false);
+
+    // bool status;
+    float xc, yc, dx, dy;
+    float fitMag, apMag;
+    float radius;
+
+    // create template model
+    pmModel *modelRef = pmModelAlloc(psf->type);
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
+    // use the center of the center pixel of the image
+    xc = 0.5*readout->image->numCols + readout->image->col0 + 0.5;
+    yc = 0.5*readout->image->numRows + readout->image->row0 + 0.5;
+    dx = psf->growth->maxRadius + 1;
+    dy = psf->growth->maxRadius + 1;
+
+    // assign the x and y coords to the image center
+    // create an object with center intensity of 1000
+    modelRef->params->data.F32[PM_PAR_SKY] = 0;
+    modelRef->params->data.F32[PM_PAR_I0] = 1000;
+    modelRef->params->data.F32[PM_PAR_XPOS] = xc;
+    modelRef->params->data.F32[PM_PAR_YPOS] = yc;
+
+    // create modelPSF from this model
+    pmModel *model = pmModelFromPSF (modelRef, psf);
+
+    // measure the fitMag for this model
+    pmSourcePhotometryModel (&fitMag, model);
+    psf->growth->fitMag = fitMag;
+
+    // generate working image for this source
+    psRegion region = {xc - dx, xc + dx, yc - dy, yc + dy};
+
+    // force region to stop at dimensions of image
+    region = psRegionForImage (readout->image, region);
+
+    // the view, image, and mask retain col0,row0
+    psImage *view = psImageSubset (readout->image, region);
+    psImage *image = psImageCopy (NULL, view, PS_TYPE_F32);
+    psImage *mask = psImageCopy (NULL, view, PS_TYPE_U8);
+
+    psImageInit (image, 0.0);
+    psImageInit (mask, 0);
+
+    // place the reference object in the image center
+    // no need to mask the source here
+    // XXX should we measure this for the analytical model only or the full model?
+    pmModelAdd (image, NULL, model, PM_MODEL_OP_FULL, maskVal);
+
+    // loop over a range of source fluxes
+    // no need to interpolate since we have forced the object center
+    // to 0.5, 0.5 above
+    bool completeGrowthCurve = true;            // do we have a complete curve of growth?
+    for (int i = 0; i < psf->growth->radius->n; i++) {
+
+        radius = psf->growth->radius->data.F32[i];
+
+        // mask the given aperture and measure the apMag
+        psImageKeepCircle (mask, xc, yc, radius, "OR", markVal);
+        if (!pmSourcePhotometryAper (&apMag, model, image, mask, maskVal)) {
+            psError(PM_ERR_PHOTOM, false, "Measuring apMag for radius == %g", radius);
+            psErrorStackPrint (stderr, "failure to get growth curve");
+            psErrorClear();
+            completeGrowthCurve = false;
+            break;
+        }
+        psImageKeepCircle (mask, xc, yc, radius, "AND", PS_NOT_U8(markVal));
+
+        // the 'ignore' mode is for testing
+        if (ignore) {
+            psf->growth->apMag->data.F32[i] = fitMag;
+        } else {
+            psf->growth->apMag->data.F32[i] = apMag;
+        }
+    }
+
+    if (completeGrowthCurve) {
+        psf->growth->apRef = psVectorInterpolate (psf->growth->radius, psf->growth->apMag, psf->growth->refRadius);
+        psf->growth->apLoss = psf->growth->fitMag - psf->growth->apRef;
+    } else {
+        psf->growth->apRef = NAN;
+        psf->growth->apLoss = 0;
+    }
+
+    psLogMsg ("psphot.growth", 4, "GrowthCurve : apLoss : %f\n", psf->growth->apLoss);
+
+    psFree (view);
+    psFree (image);
+    psFree (mask);
+    psFree (model);
+    psFree (modelRef);
+
+    return completeGrowthCurve ? true : false;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSF.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSF.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSF.h	(revision 22158)
@@ -0,0 +1,108 @@
+/* @file  pmPSF.h
+ *
+ * This file contains typedefs for the Point-Spread Function and prototypes
+ * for functions that calculate the PSF.
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-27 03:14:57 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+# ifndef PM_PSF_H
+# define PM_PSF_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+// type of model carried by the pmModel structure
+typedef int pmModelType;
+
+/** pmPSF data structure
+ *
+ * It is useful to generate a model to define the point-spread-function which
+ * describes the flux distribution for unresolved sources in an image. In
+ * general, the PSF varies with position in the image. We allow any of the source
+ * models defined for the pmModel to represent the PSF. For a given source model,
+ * the 2D spatial variation of all of the source parameters, except the first
+ * four PSF-independent parameters, are represented as polynomial, stored in a
+ * psArray. The other elements of the structure define the quality of the PSF
+ * determination.
+ *
+ */
+typedef struct
+{
+    pmModelType type;                   ///< PSF Model in use
+    psArray *params;                    ///< Model parameters (psPolynomial2D)
+    psStats *psfTrendStats;             ///< psf parameter trend clipping stats
+    pmTrend2DMode psfTrendMode;
+    psPolynomial1D *ChiTrend;           ///< Chisq vs flux fit (correction for systematic errors)
+    pmTrend2D *ApTrend;                 ///< ApResid vs (x,y)
+    pmTrend2D *FluxScale;               ///< Flux for PSF at (x,y) for normalization = 1.0
+    float ApResid;                      ///< apMag - psfMag (for PSF stars)
+    float dApResid;                     ///< scatter of ApResid
+    float skyBias;                      ///< implied residual sky offset from ApResid fit
+    float skySat;                       ///< roll-over of ApResid fit
+    float chisq;                        ///< PSF goodness statistic (unused??)
+    int nPSFstars;                      ///< number of stars used to measure PSF
+    int nApResid;                       ///< number of stars used to measure ApResid
+    int trendNx;
+    int trendNy;
+    int fieldNx;
+    int fieldNy;
+    int fieldXo;
+    int fieldYo;
+    bool poissonErrorsPhotLMM;          ///< use poission errors for non-linear model fitting
+    bool poissonErrorsPhotLin;          ///< use poission errors for linear model fitting
+    bool poissonErrorsParams;           ///< use poission errors for model parameter fitting
+    pmGrowthCurve *growth;              ///< apMag vs Radius
+    pmResiduals *residuals;             ///< normalized residual image (no spatial variation)
+}
+pmPSF;
+
+typedef struct {
+    pmModelType   type;
+    psStats      *stats;                // psfTrend clipping stats
+    pmTrend2DMode psfTrendMode;
+    int           psfTrendNx;
+    int           psfTrendNy;
+    int           psfFieldNx;
+    int           psfFieldNy;
+    int           psfFieldXo;
+    int           psfFieldYo;
+    bool          poissonErrorsPhotLMM; ///< use poission errors for non-linear model fitting
+    bool          poissonErrorsPhotLin; ///< use poission errors for linear model fitting
+    bool          poissonErrorsParams; ///< use poission errors for model parameter fitting
+    float         radius;
+} pmPSFOptions;
+
+# define PM_PAR_E0 PM_PAR_SXX
+# define PM_PAR_E1 PM_PAR_SYY
+# define PM_PAR_E2 PM_PAR_SXY
+
+/**
+ *
+ * Allocator for the pmPSF structure.
+ *
+ */
+
+pmPSF *pmPSFAlloc (const pmPSFOptions *options);
+bool psMemCheckPSF(psPtr ptr);
+pmPSFOptions *pmPSFOptionsAlloc();
+bool psMemCheckPSFOptions(psPtr ptr);
+
+double pmPSF_SXYfromModel (psF32 *modelPar);
+double pmPSF_SXYtoModel (psF32 *fittedPar);
+
+bool pmGrowthCurveGenerate (pmReadout *readout, pmPSF *psf, bool ignore, psMaskType maskVal, psMaskType mark);
+pmPSF *pmPSFBuildSimple (char *typeName, float sxx, float syy, float sxy, ...);
+
+bool pmPSF_AxesToModel (psF32 *modelPar, psEllipseAxes axes);
+bool pmPSF_FitToModel (psF32 *fittedPar, float minMinorAxis);
+
+psEllipsePol pmPSF_ModelToFit (psF32 *modelPar);
+psEllipseAxes pmPSF_ModelToAxes (psF32 *modelPar, double maxAR);
+
+/// @}
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSF_IO.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSF_IO.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSF_IO.c	(revision 22158)
@@ -0,0 +1,820 @@
+/** @file  pmPSF_IO.c
+ *
+ * This file contains functions to read and write PSF models using the psMetadata Config file
+ * format.
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.34 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-17 22:38:15 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/*****************************************************************************/
+/* INCLUDE FILES                                                             */
+/*****************************************************************************/
+
+#include <string.h>
+#include <strings.h>            /* for strn?casecmp */
+
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+#include "pmFPAfileFitsIO.h"
+
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmGrowthCurve.h"
+#include "pmResiduals.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmPSF_IO.h"
+#include "pmSource.h"
+#include "pmModelClass.h"
+#include "pmSourceIO.h"
+
+bool pmPSFmodelCheckDataStatusForView (const pmFPAview *view, const pmFPAfile *file)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa->chips, false);
+    pmFPA *fpa = file->fpa;
+
+    if (view->chip == -1) {
+        bool exists = pmPSFmodelCheckDataStatusForFPA (fpa);
+        return exists;
+    }
+
+    if (view->chip >= fpa->chips->n) {
+        psError(PS_ERR_IO, true, "Requested chip == %d >= fpa->chips->n == %ld", view->chip, fpa->chips->n);
+        return false;
+    }
+
+    pmChip *chip = fpa->chips->data[view->chip];
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_PTR_NON_NULL(chip->cells, false);
+
+    if (view->cell == -1) {
+        bool exists = pmPSFmodelCheckDataStatusForChip (chip);
+        return exists;
+    }
+
+    if (view->cell >= chip->cells->n) {
+        psError(PS_ERR_IO, true, "Requested cell == %d >= chip->cells->n == %ld", view->cell, chip->cells->n);
+        return false;
+    }
+
+    psError(PS_ERR_IO, false, "PSF only valid at the chip level");
+    return false;
+}
+
+bool pmPSFmodelCheckDataStatusForFPA (const pmFPA *fpa) {
+
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(fpa->chips, false);
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        if (!chip) continue;
+        if (pmPSFmodelCheckDataStatusForChip (chip)) return true;
+    }
+    return false;
+}
+
+bool pmPSFmodelCheckDataStatusForChip (const pmChip *chip) {
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+
+    bool status;
+
+    // select the psf of interest
+    pmPSF *psf = psMetadataLookupPtr(&status, chip->analysis, "PSPHOT.PSF");
+    return psf ? true : false;
+}
+
+bool pmPSFmodelWriteForView (const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa->chips, false);
+
+    pmFPA *fpa = file->fpa;
+
+    if (view->chip == -1) {
+        if (!pmPSFmodelWriteFPA(fpa, view, file, config)) {
+            psError(PS_ERR_IO, false, "Failed to write PSF for fpa");
+            return false;
+        }
+        return true;
+    }
+
+    if (view->chip >= fpa->chips->n) {
+        return false;
+    }
+    pmChip *chip = fpa->chips->data[view->chip];
+
+    if (view->cell == -1) {
+        if (!pmPSFmodelWriteChip (chip, view, file, config)) {
+            psError(PS_ERR_IO, false, "Failed to write PSF for chip");
+            return false;
+        }
+        return true;
+    }
+
+    psError(PS_ERR_IO, false, "PSF must be written at the chip level");
+    return false;
+}
+
+// read in all chip-level PSFmodel files for this FPA
+bool pmPSFmodelWriteFPA (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(fpa->chips, false);
+    pmFPAview *thisView = pmFPAviewAlloc (view->nRows);
+    *thisView = *view;
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        thisView->chip = i;
+        if (!pmPSFmodelWriteChip (chip, thisView, file, config)) {
+            psError(PS_ERR_IO, false, "Failed to write PSF for %dth chip", i);
+            psFree(thisView);
+            return false;
+        }
+    }
+    psFree(thisView);
+    return true;
+}
+
+// read in all cell-level PSFmodel files for this chip
+bool pmPSFmodelWriteChip (pmChip *chip, const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+
+    if (!pmPSFmodelWrite (chip->analysis, view, file, config)) {
+        psError(PS_ERR_IO, false, "Failed to write PSF for chip");
+        return false;
+    }
+    return true;
+}
+
+// for a pmPSF supplied on the analysis metadata, we write out
+// if needed:
+//   - a PHU blank header
+// - image header        : FITS Image NAXIS = 0
+// if (trendMode == MAP)
+//   - psf resid (+header) : FITS Image
+// else
+//   - psf table (+header) : FITS Table
+bool pmPSFmodelWrite (psMetadata *analysis, const pmFPAview *view,
+                      pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+    bool status;
+    char *headName, *tableName, *residName;
+
+    if (!analysis) return false;
+
+    // select the current recipe
+    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, "PSPHOT");
+    if (!recipe) {
+        psError(PS_ERR_UNKNOWN, false, "missing recipe %s", "PSPHOT");
+        return false;
+    }
+
+    // write a PHU? (only if input image is MEF)
+    // write a header? (only if this is the first readout for cell)
+    //   note that the file->header is set to track the last hdu->header written
+    // write the data? (always?)
+
+    // get the current header
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, false); // Suitable FPA for writing
+    pmHDU *hdu = psMemIncrRefCounter(pmFPAviewThisHDU(view, fpa));
+    psFree(fpa);
+    if (!hdu) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to find HDU");
+        return false;
+    }
+
+    // if file does not yet have a PHU, attempt to write one to disk
+    // we only need a PHU if chips->n > 1 and file->fileLevel == FPA
+    // otherwise, the chip header fills the PHU location
+    // XXX this code could be placed in a 'pmPSF_WritePHU' function and called
+    // from pmFPAfileIO.c.
+
+    // define the EXTNAME values used for image header, table data, and residual image segments
+    {
+        // lookup the EXTNAME values used for table data and image header segments
+        char *rule = NULL;
+
+        // Menu of EXTNAME rules
+        psMetadata *menu = psMetadataLookupMetadata(&status, file->camera, "EXTNAME.RULES");
+        if (!menu) {
+            psError(PS_ERR_UNKNOWN, true, "missing EXTNAME.RULES in camera.config");
+            psFree(hdu);
+            return false;
+        }
+
+        // EXTNAME for image header
+        rule = psMetadataLookupStr(&status, menu, "PSF.HEAD");
+        if (!rule) {
+            psError(PS_ERR_UNKNOWN, false, "missing entry for PSF.HEAD in EXTNAME.RULES in camera.config");
+            psFree(hdu);
+            return false;
+        }
+        headName = pmFPAfileNameFromRule (rule, file, view);
+
+        // EXTNAME for table data
+        rule = psMetadataLookupStr(&status, menu, "PSF.TABLE");
+        if (!rule) {
+            psError(PS_ERR_UNKNOWN, false, "missing entry for PSF.TABLE in EXTNAME.RULES in camera.config");
+            psFree (headName);
+            psFree(hdu);
+            return false;
+        }
+        tableName = pmFPAfileNameFromRule (rule, file, view);
+
+        // EXTNAME for resid data
+        rule = psMetadataLookupStr(&status, menu, "PSF.RESID");
+        if (!rule) {
+            psError(PS_ERR_UNKNOWN, false, "missing entry for PSF.RESID in EXTNAME.RULES in camera.config");
+            psFree (headName);
+            psFree (tableName);
+            psFree(hdu);
+            return false;
+        }
+        residName = pmFPAfileNameFromRule (rule, file, view);
+    }
+
+    // write out the IMAGE header segment
+    // if this header block is new, write it to disk
+    if (hdu->header != file->header) {
+        // add EXTNAME, EXTHEAD, EXTTYPE to header
+        psMetadataAddStr (hdu->header, PS_LIST_TAIL, "EXTTABLE", PS_META_REPLACE, "name of table extension", tableName);
+        psMetadataAddStr (hdu->header, PS_LIST_TAIL, "EXTRESID", PS_META_REPLACE, "name of resid extension", residName);
+        psMetadataAddStr (hdu->header, PS_LIST_TAIL, "EXTTYPE", PS_META_REPLACE, "extension type", "IMAGE");
+        if (!file->wrote_phu) {
+            // this hdu->header acts as the PHU: set EXTEND to be true
+            psMetadataAddBool (hdu->header, PS_LIST_TAIL, "EXTEND", PS_META_REPLACE, "this file has extensions", true);
+            file->wrote_phu = true;
+        }
+
+        psFitsWriteBlank (file->fits, hdu->header, headName);
+        psTrace ("pmFPAfile", 5, "wrote ext head %s (type: %d)\n", file->filename, file->type);
+        file->header = hdu->header;
+        psFree (headName);
+    }
+    psFree(hdu);
+
+    // select the psf of interest
+    pmPSF *psf = psMetadataLookupPtr (&status, analysis, "PSPHOT.PSF");
+    if (!psf) {
+        psError(PS_ERR_UNKNOWN, true, "missing PSF for this analysis metadata");
+        psFree (tableName);
+        psFree (residName);
+        return false;
+    }
+
+    // write the PSF model parameters in a FITS table
+    {
+        // we need to write a header for the table,
+        psMetadata *header = psMetadataAlloc();
+
+        char *modelName = pmModelClassGetName (psf->type);
+        psMetadataAddStr (header, PS_LIST_TAIL, "PSF_NAME", 0, "PSF model name", modelName);
+
+        psMetadataAddBool (header, PS_LIST_TAIL, "ERR_LMM",  0, "Use Poisson errors in fits?", psf->poissonErrorsPhotLMM);
+        psMetadataAddBool (header, PS_LIST_TAIL, "ERR_LIN",  0, "Use Poisson errors in fits?", psf->poissonErrorsPhotLin);
+        psMetadataAddBool (header, PS_LIST_TAIL, "ERR_PAR",  0, "Use Poisson errors in fits?", psf->poissonErrorsParams);
+
+        int nPar = pmModelClassParameterCount (psf->type)    ;
+        psMetadataAdd (header, PS_LIST_TAIL, "PSF_NPAR", PS_DATA_S32, "PSF model parameter count", nPar);
+
+        psMetadataAddS32 (header, PS_LIST_TAIL, "IMAXIS1", 0, "Image X Size", psf->fieldNx);
+        psMetadataAddS32 (header, PS_LIST_TAIL, "IMAXIS2", 0, "Image Y Size", psf->fieldNy);
+        psMetadataAddS32 (header, PS_LIST_TAIL, "IMREF1",  0, "Image X Ref",  psf->fieldXo);
+        psMetadataAddS32 (header, PS_LIST_TAIL, "IMREF2",  0, "Image Y Ref",  psf->fieldYo);
+
+        // extract PSF Clump info
+        pmPSFClump psfClump;
+
+        psfClump.X  = psMetadataLookupF32 (&status, recipe, "PSF.CLUMP.X");   assert (status);
+        psfClump.Y  = psMetadataLookupF32 (&status, recipe, "PSF.CLUMP.Y");   assert (status);
+        psfClump.dX = psMetadataLookupF32 (&status, recipe, "PSF.CLUMP.DX");  assert (status);
+        psfClump.dY = psMetadataLookupF32 (&status, recipe, "PSF.CLUMP.DY");  assert (status);
+
+        psMetadataAddF32 (header, PS_LIST_TAIL, "PSF_CLX", 0, "psf clump center", psfClump.X);
+        psMetadataAddF32 (header, PS_LIST_TAIL, "PSF_CLY", 0, "psf clump center", psfClump.Y);
+        psMetadataAddF32 (header, PS_LIST_TAIL, "PSF_CLDX", 0, "psf clump size", psfClump.dX);
+        psMetadataAddF32 (header, PS_LIST_TAIL, "PSF_CLDY", 0, "psf clump size", psfClump.dY);
+
+        // save the dimensions of each parameter
+        for (int i = 0; i < nPar; i++) {
+            char name[9];
+            int nX, nY;
+
+            pmTrend2D *trend = psf->params->data[i];
+            if (trend == NULL) continue;
+
+            if (trend->mode == PM_TREND_MAP) {
+              nX = trend->map->map->numCols;
+              nY = trend->map->map->numRows;
+            } else {
+              nX = trend->poly->nX;
+              nY = trend->poly->nY;
+            }
+            snprintf (name, 9, "PAR%02d_NX", i);
+            psMetadataAddS32 (header, PS_LIST_TAIL, name, 0, "", nX);
+            snprintf (name, 9, "PAR%02d_NY", i);
+            psMetadataAddS32 (header, PS_LIST_TAIL, name, 0, "", nY);
+            snprintf (name, 9, "PAR%02d_MD", i);
+            char *modeName = pmTrend2DModeToString (trend->mode);
+            psMetadataAddStr (header, PS_LIST_TAIL, name, 0, "", modeName);
+            psFree (modeName);
+        }
+
+        // other required information describing the PSF
+        psMetadataAddF32 (header, PS_LIST_TAIL, "AP_RESID", 0, "aperture residual", psf->ApResid);
+        psMetadataAddF32 (header, PS_LIST_TAIL, "AP_ERROR", 0, "aperture residual scatter", psf->dApResid);
+        psMetadataAddF32 (header, PS_LIST_TAIL, "CHISQ",    0, "chi-square for fit", psf->chisq);
+        psMetadataAddS32 (header, PS_LIST_TAIL, "NSTARS",   0, "number of stars used to measure PSF", psf->nPSFstars);
+
+        // XXX can we drop this now?
+        psMetadataAddF32 (header, PS_LIST_TAIL, "SKY_BIAS", PS_DATA_F32, "sky bias level", psf->skyBias);
+
+        // build a FITS table of the PSF parameters
+        psArray *psfTable = psArrayAllocEmpty (100);
+        for (int i = 0; i < nPar; i++) {
+            pmTrend2D *trend = psf->params->data[i];
+            if (trend == NULL) continue; // skip unset parameters (eg, XPOS)
+
+            if (trend->mode == PM_TREND_MAP) {
+                // write the image components into a table: this is needed because they may each be a different size
+                psImageMap *map = trend->map;
+                for (int ix = 0; ix < map->map->numCols; ix++) {
+                    for (int iy = 0; iy < map->map->numRows; iy++) {
+                        psMetadata *row = psMetadataAlloc ();
+                        psMetadataAddS32 (row, PS_LIST_TAIL, "MODEL_TERM", 0, "", i);
+                        psMetadataAddS32 (row, PS_LIST_TAIL, "X_POWER",    0, "", ix);
+                        psMetadataAddS32 (row, PS_LIST_TAIL, "Y_POWER",    0, "", iy);
+                        psMetadataAddF32 (row, PS_LIST_TAIL, "VALUE",      0, "", map->map->data.F32[iy][ix]);
+                        psMetadataAddF32 (row, PS_LIST_TAIL, "ERROR",      0, "", map->error->data.F32[iy][ix]);
+                        psMetadataAddU8  (row, PS_LIST_TAIL, "MASK",       0, "", 0); // no cells are masked
+
+                        psArrayAdd (psfTable, 100, row);
+                        psFree (row);
+                    }
+                }
+            } else {
+                // write the polynomial components into a table
+                psPolynomial2D *poly = trend->poly;
+                for (int ix = 0; ix <= poly->nX; ix++) {
+                    for (int iy = 0; iy <= poly->nY; iy++) {
+                        psMetadata *row = psMetadataAlloc ();
+                        psMetadataAddS32 (row, PS_LIST_TAIL, "MODEL_TERM", 0, "", i);
+                        psMetadataAddS32 (row, PS_LIST_TAIL, "X_POWER",    0, "", ix);
+                        psMetadataAddS32 (row, PS_LIST_TAIL, "Y_POWER",    0, "", iy);
+                        psMetadataAddF32 (row, PS_LIST_TAIL, "VALUE",      0, "", poly->coeff[ix][iy]);
+                        psMetadataAddF32 (row, PS_LIST_TAIL, "ERROR",      0, "", poly->coeffErr[ix][iy]);
+                        psMetadataAddU8  (row, PS_LIST_TAIL, "MASK",       0, "", poly->coeffMask[ix][iy]);
+
+                        psArrayAdd (psfTable, 100, row);
+                        psFree (row);
+                    }
+                }
+            }
+        }
+
+        // write an empty FITS segment if we have no PSF information
+        if (psfTable->n == 0) {
+            // XXX this is probably an error (if we have a PSF, how do we have no data?)
+            psFitsWriteBlank (file->fits, header, tableName);
+        } else {
+            psTrace ("pmFPAfile", 5, "writing psf data %s\n", tableName);
+            if (!psFitsWriteTable (file->fits, header, psfTable, tableName)) {
+                psError(PS_ERR_IO, false, "writing psf table data %s\n", tableName);
+                psFree (tableName);
+                psFree (residName);
+                psFree (psfTable);
+                psFree (header);
+                return false;
+            }
+        }
+        psFree (tableName);
+        psFree (psfTable);
+        psFree (header);
+    }
+
+    // write the residual images (3D)
+    {
+        psMetadata *header = psMetadataAlloc ();
+        if (psf->residuals == NULL) {
+            // set some header keywords to make it clear there are no residuals?
+            psFitsWriteBlank (file->fits, header, residName);
+            psFree (residName);
+            psFree (header);
+            return true;
+        }
+
+        psMetadataAddS32 (header, PS_LIST_TAIL, "XBIN",    0, "", psf->residuals->xBin);
+        psMetadataAddS32 (header, PS_LIST_TAIL, "YBIN",    0, "", psf->residuals->yBin);
+        psMetadataAddS32 (header, PS_LIST_TAIL, "XCENTER", 0, "", psf->residuals->xCenter);
+        psMetadataAddS32 (header, PS_LIST_TAIL, "YCENTER", 0, "", psf->residuals->yCenter);
+
+        // write the residuals as three planes of the image
+        // this call creates an extension with NAXIS3 = 3
+        if (psf->residuals->Rx) {
+            // this call creates an extension with NAXIS3 = 3
+            psArray *images = psArrayAllocEmpty (3);
+            psArrayAdd (images, 1, psf->residuals->Ro);
+            psArrayAdd (images, 1, psf->residuals->Rx);
+            psArrayAdd (images, 1, psf->residuals->Ry);
+
+            psFitsWriteImageCube (file->fits, header, images, residName);
+            psFree (images);
+        } else {
+            // this call creates an extension with NAXIS3 = 1
+            psFitsWriteImage(file->fits, header, psf->residuals->Ro, 0, residName);
+        }
+        psFree (residName);
+        psFree (header);
+    }
+
+    return true;
+
+    // XXX save the growth curve
+    // XXX save ApTrend (as image?)
+    // XXX write the ApTrend with the same API as will be used for the PSF parameters above
+
+# if (0)
+    // build a FITS table of the fit to the Aperture Residuals
+    psArray *apresTable = psArrayAllocEmpty (100);
+    psPolynomial4D *poly = psf->ApTrend;
+    for (int ix = 0; ix < poly->nX; ix++) {
+        for (int iy = 0; iy < poly->nY; iy++) {
+
+            row = psMetadataAlloc ();
+            psMetadataAddS32 (row, PS_LIST_TAIL, "X_POWER",    0, "", ix);
+            psMetadataAddS32 (row, PS_LIST_TAIL, "Y_POWER",    0, "", iy);
+            psMetadataAddF32 (row, PS_LIST_TAIL, "VALUE",      0, "", poly->coeff[ix][iy]);
+            psMetadataAddF32 (row, PS_LIST_TAIL, "ERROR",      0, "", poly->coeffErr[ix][iy]);
+            psMetadataAddU8  (row, PS_LIST_TAIL, "MASK",       0, "", poly->mask[ix][iy]);
+
+            psArrayAdd (psfTable, 100, row);
+            psFree (row);
+        }
+    }
+# endif
+}
+
+// if this file needs to have a PHU written out, write one
+bool pmPSFmodelWritePHU (const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+    // not needed if already written
+    if (file->wrote_phu) return true;
+
+    // not needed if not FPA
+    // XXX this prevents us from defining a SPLIT/MEF CMF file...
+    if (file->fileLevel != PM_FPA_LEVEL_FPA) return true;
+
+    // not needed if only one chip
+    if (file->fpa->chips->n == 1) return true;
+
+
+    // find the FPA phu
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, false); // Suitable FPA for writing
+    pmHDU *phu = psMemIncrRefCounter(pmFPAviewThisPHU(view, fpa));
+    psFree(fpa);
+
+    // if there is no PHU, this is a single header+image (extension-less) file. This could be
+    // the case for an input SPLIT set of files being written out as a MEF.  if there is a PHU,
+    // write it out as a 'blank'
+    psMetadata *outhead = psMetadataAlloc();
+    if (phu) {
+        psMetadataCopy (outhead, phu->header);
+    } else {
+        pmConfigConformHeader (outhead, file->format);
+    }
+    psFree(phu);
+
+    psMetadataAddBool (outhead, PS_LIST_TAIL, "EXTEND", PS_META_REPLACE, "this file has extensions", true);
+    psFitsWriteBlank (file->fits, outhead, "");
+    file->wrote_phu = true;
+
+    psTrace ("pmFPAfile", 5, "wrote phu %s (type: %d)\n", file->filename, file->type);
+    psFree (outhead);
+
+    return true;
+}
+
+bool pmPSFmodelReadForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+
+    pmFPA *fpa = file->fpa;
+
+    if (view->chip == -1) {
+        return pmPSFmodelReadFPA(fpa, view, file, config);
+    }
+
+    if (view->chip >= fpa->chips->n) {
+        psAbort("Programming error: view does not apply to FPA.");
+    }
+    pmChip *chip = fpa->chips->data[view->chip];
+
+    if (view->cell == -1) {
+        return pmPSFmodelReadChip(chip, view, file, config);
+    }
+
+    psError(PS_ERR_IO, false, "PSF must be read at the chip level");
+    return false;
+}
+
+// read in all chip-level PSFmodel files for this FPA
+bool pmPSFmodelReadFPA (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+
+    bool success = true;                // Was everything successful?
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        success &= pmPSFmodelReadChip(chip, view, file, config);
+    }
+    return success;
+}
+
+// read in all cell-level PSFmodel files for this chip
+bool pmPSFmodelReadChip (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+
+    if (!pmPSFmodelRead (chip->analysis, view, file, config)) {
+        psError(PS_ERR_IO, false, "Failed to write PSF for chip");
+        return false;
+    }
+    return true;
+}
+
+// for each Readout (ie, analysed image), we write out: header + table with PSF model parameters,
+// and header + image for the PSF residual images
+bool pmPSFmodelRead (psMetadata *analysis, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+
+    bool status;
+    char *rule = NULL;
+    psMetadata *header = NULL;
+
+    psTrace ("psModules.objects", 5, "read psf model for %s\n", file->filename);
+
+    // select the current recipe
+    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, "PSPHOT");
+    if (!recipe) {
+        psError(PS_ERR_UNKNOWN, false, "missing recipe %s", "PSPHOT");
+        return false;
+    }
+
+    // Menu of EXTNAME rules
+    psMetadata *menu = psMetadataLookupMetadata(&status, file->camera, "EXTNAME.RULES");
+    if (!menu) {
+        psError(PS_ERR_UNKNOWN, true, "missing EXTNAME.RULES in camera.config");
+        return false;
+    }
+    // EXTNAME for table data
+    rule = psMetadataLookupStr(&status, menu, "PSF.TABLE");
+    if (!rule) {
+        psError(PS_ERR_UNKNOWN, true, "missing entry for PSF.TABLE in EXTNAME.RULES in camera.config");
+        return false;
+    }
+    char *tableName = pmFPAfileNameFromRule (rule, file, view);
+    // EXTNAME for residual images
+    rule = psMetadataLookupStr(&status, menu, "PSF.RESID");
+    if (!rule) {
+        psError(PS_ERR_UNKNOWN, true, "missing entry for PSF.RESID in EXTNAME.RULES in camera.config");
+        return false;
+    }
+    char *imageName = pmFPAfileNameFromRule (rule, file, view);
+
+    // move fits pointer to table and read header
+    // advance to the table data extension
+    // since we have read the IMAGE header, the TABLE header should exist
+    if (!psFitsMoveExtName (file->fits, tableName)) {
+        psAbort("cannot find data extension %s in %s", tableName, file->filename);
+    }
+
+    // load the PSF model table header
+    header = psFitsReadHeader (NULL, file->fits);
+    if (!header) psAbort("cannot read table header");
+
+    pmPSFOptions *options = pmPSFOptionsAlloc();
+
+    // load the PSF model parameters from the FITS table
+    char *modelName = psMetadataLookupStr (&status, header, "PSF_NAME");
+    options->type = pmModelClassGetType (modelName);
+    if (options->type == -1) {
+        psError(PS_ERR_UNKNOWN, true, "invalid model name %s in psf file %s", modelName, file->filename);
+        return false;
+    }
+
+    // psf clump data
+    pmPSFClump psfClump;
+
+    psfClump.X  = psMetadataLookupF32 (&status, header, "PSF_CLX" );  assert(status);
+    psfClump.Y  = psMetadataLookupF32 (&status, header, "PSF_CLY" );  assert(status);
+    psfClump.dX = psMetadataLookupF32 (&status, header, "PSF_CLDX");  assert(status);
+    psfClump.dY = psMetadataLookupF32 (&status, header, "PSF_CLDY");  assert(status);
+
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "PSF.CLUMP.X" , PS_META_REPLACE, "psf clump center", psfClump.X);
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "PSF.CLUMP.Y" , PS_META_REPLACE, "psf clump center", psfClump.Y);
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "PSF.CLUMP.DX", PS_META_REPLACE, "psf clump size",   psfClump.dX);
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump size",   psfClump.dY);
+
+    options->poissonErrorsPhotLMM = psMetadataLookupBool (&status, header, "ERR_LMM");
+    options->poissonErrorsPhotLin = psMetadataLookupBool (&status, header, "ERR_LIN");
+    options->poissonErrorsParams  = psMetadataLookupBool (&status, header, "ERR_PAR");
+
+    options->psfFieldNx = psMetadataLookupS32 (&status, header, "IMAXIS1");
+    options->psfFieldNy = psMetadataLookupS32 (&status, header, "IMAXIS2");
+    options->psfFieldXo = psMetadataLookupS32 (&status, header, "IMREF1");
+    options->psfFieldYo = psMetadataLookupS32 (&status, header, "IMREF2");
+
+    psImageBinning *binning = psImageBinningAlloc();
+    binning->nXfine = options->psfFieldNx;
+    binning->nYfine = options->psfFieldNy;
+
+    // we determine the PSF parameter polynomials from the MD-defined polynomials
+    pmPSF *psf = pmPSFAlloc (options);
+
+    // check the number of expected parameters
+    int nPar = psMetadataLookupS32 (&status, header, "PSF_NPAR");
+    if (nPar != pmModelClassParameterCount (psf->type))
+        psAbort("mismatch model par count");
+
+    // load the trend mode and dimensions of each parameter
+    for (int i = 0; i < nPar; i++) {
+        char name[9];
+        snprintf (name, 9, "PAR%02d_NX", i);
+        binning->nXruff = psMetadataLookupS32 (&status, header, name);
+        if (!status) continue;          // not all parameters are defined
+
+        snprintf (name, 9, "PAR%02d_NY", i);
+        binning->nYruff = psMetadataLookupS32 (&status, header, name);
+        if (!status) {
+            psError(PS_ERR_UNKNOWN, true, "inconsistent PSF header: NX defined for PAR %d, but not NY", i);
+            return false;
+        }
+
+        snprintf (name, 9, "PAR%02d_MD", i);
+        char *modeName = psMetadataLookupStr (&status, header, name);
+        if (!status) {
+            psError(PS_ERR_UNKNOWN, true, "inconsistent PSF header: NX & NY defined for PAR %d, but not MD", i);
+            return false;
+        }
+        pmTrend2DMode psfTrendMode = pmTrend2DModeFromString (modeName);
+        if (psfTrendMode == PM_TREND_NONE) {
+            psfTrendMode = PM_TREND_POLY_ORD;
+        }
+
+        // XXX Attempting to guard against failing assertions on nXruff and nYruff in psImageBinningSetScale.
+        // This replicates code in psphotCheckStarDistribution, where these values are generated.  Not sure
+        // it's correct, though.
+        if (psfTrendMode != PM_TREND_MAP) {
+            binning->nXruff++;
+            binning->nYruff++;
+        }
+
+        psImageBinningSetScale (binning, PS_IMAGE_BINNING_CENTER);
+        psImageBinningSetSkipByOffset (binning, options->psfFieldXo, options->psfFieldYo);
+        psf->params->data[i] = pmTrend2DNoImageAlloc (psfTrendMode, binning, NULL);
+    }
+    psFree (binning);
+    psFree(options);
+
+    // other required information describing the PSF
+    psf->ApResid   = psMetadataLookupF32 (&status, header, "AP_RESID");
+    psf->dApResid  = psMetadataLookupF32 (&status, header, "AP_ERROR");
+    psf->chisq     = psMetadataLookupF32 (&status, header, "CHISQ");
+    psf->nPSFstars = psMetadataLookupS32 (&status, header, "NSTARS");
+
+    // XXX can we drop this now?
+    psf->skyBias   = psMetadataLookupF32 (&status, header, "SKY_BIAS");
+
+    // read the raw table data
+    psArray *table = psFitsReadTable (file->fits);
+
+    // fill in the matching psf->params entries
+    for (int i = 0; i < table->n; i++) {
+        psMetadata *row = table->data[i];
+        int iPar = psMetadataLookupS32 (&status, row, "MODEL_TERM");
+        int xPow = psMetadataLookupS32 (&status, row, "X_POWER");
+        int yPow = psMetadataLookupS32 (&status, row, "Y_POWER");
+
+        pmTrend2D *trend = psf->params->data[iPar];
+        if (trend == NULL) {
+            psError(PS_ERR_UNKNOWN, true, "parameter %d not available", iPar);
+            return false;
+        }
+
+        if (trend->mode == PM_TREND_MAP) {
+            psImageMap *map = trend->map;
+            assert (map);
+            assert (map->map);
+            assert (map->error);
+            assert (xPow >= 0);
+            assert (yPow >= 0);
+            assert (xPow < map->map->numCols);
+            assert (yPow < map->map->numRows);
+            map->map->data.F32[yPow][xPow]    = psMetadataLookupF32 (&status, row, "VALUE");
+            map->error->data.F32[yPow][xPow]  = psMetadataLookupF32 (&status, row, "ERROR");
+        } else {
+            psPolynomial2D *poly = trend->poly;
+            assert (poly);
+            assert (xPow >= 0);
+            assert (yPow >= 0);
+            assert (xPow <= poly->nX);
+            assert (yPow <= poly->nY);
+            poly->coeff[xPow][yPow]     = psMetadataLookupF32 (&status, row, "VALUE");
+            poly->coeffErr[xPow][yPow]  = psMetadataLookupF32 (&status, row, "ERROR");
+            poly->coeffMask[xPow][yPow] = psMetadataLookupU8  (&status, row, "MASK");
+        }
+    }
+    psFree (header);
+    psFree (table);
+
+    // move fits pointer to residual image and read header
+    // advance to the table data extension
+    // since we have read the IMAGE header, the TABLE header should exist
+    if (!psFitsMoveExtName (file->fits, imageName)) {
+        psAbort("cannot find data extension %s in %s", imageName, file->filename);
+    }
+
+    header = psFitsReadHeader (NULL, file->fits);
+    int Naxis = psMetadataLookupS32 (&status, header, "NAXIS");
+    if (Naxis != 0) {
+
+        int Nx = psMetadataLookupS32 (&status, header, "NAXIS1");
+        int Ny = psMetadataLookupS32 (&status, header, "NAXIS2");
+        int Nz = psMetadataLookupS32 (&status, header, "NAXIS3");
+
+        int xBin  = psMetadataLookupS32 (&status, header, "XBIN");
+        int yBin  = psMetadataLookupS32 (&status, header, "YBIN");
+
+        int xSize = Nx / xBin;
+        int ySize = Ny / yBin;
+
+        psf->residuals = pmResidualsAlloc (xSize, ySize, xBin, yBin);
+
+        psf->residuals->xCenter = psMetadataLookupS32 (&status, header, "XCENTER");
+        psf->residuals->yCenter = psMetadataLookupS32 (&status, header, "YCENTER");
+
+        psRegion fullImage = {0, 0, 0, 0};
+        psFitsReadImageBuffer(psf->residuals->Ro, file->fits, fullImage, 0); // Desired pixels
+        if (Nz > 1) {
+            assert (Nz == 3);
+            psFitsReadImageBuffer(psf->residuals->Rx, file->fits, fullImage, 1); // Desired pixels
+            psFitsReadImageBuffer(psf->residuals->Ry, file->fits, fullImage, 2); // Desired pixels
+        }
+    }
+
+    psMetadataAdd (analysis, PS_LIST_TAIL, "PSPHOT.PSF",     PS_DATA_UNKNOWN,  "psphot psf", psf);
+    psFree (psf);
+
+    psFree (tableName);
+    psFree (imageName);
+    psFree (header);
+
+    return true;
+}
+
+// XXX pmPSF to/from Metadata functions were defined for 1.22 and earlier, but were dropped
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSF_IO.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSF_IO.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSF_IO.h	(revision 22158)
@@ -0,0 +1,36 @@
+/* @file  pmPSF.h
+ *
+ * This file contains typedefs for the Point-Spread Function and prototypes
+ * for functions that calculate the PSF.
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-17 22:38:15 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+# ifndef PM_PSF_IO_H
+# define PM_PSF_IO_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+bool pmPSFmodelWriteForView (const pmFPAview *view, pmFPAfile *file, pmConfig *config);
+bool pmPSFmodelWriteFPA (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, pmConfig *config);
+bool pmPSFmodelWriteChip (pmChip *chip, const pmFPAview *view, pmFPAfile *file, pmConfig *config);
+bool pmPSFmodelWrite (psMetadata *analysis, const pmFPAview *view, pmFPAfile *file, pmConfig *config);
+
+bool pmPSFmodelWritePHU (const pmFPAview *view, pmFPAfile *file, pmConfig *config);
+
+bool pmPSFmodelReadForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmPSFmodelReadFPA (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmPSFmodelReadChip (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmPSFmodelRead (psMetadata *analysis, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+
+bool pmPSFmodelCheckDataStatusForView (const pmFPAview *view, const pmFPAfile *file);
+bool pmPSFmodelCheckDataStatusForFPA (const pmFPA *fpa);
+bool pmPSFmodelCheckDataStatusForChip (const pmChip *chip);
+
+/// @}
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSFtoMetadata.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSFtoMetadata.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSFtoMetadata.c	(revision 22158)
@@ -0,0 +1,91 @@
+
+// create a psMetadata representation (human-readable) of a psf model
+psMetadata *pmPSFtoMetadata (psMetadata *metadata, pmPSF *psf)
+{
+
+    if (metadata == NULL) {
+        metadata = psMetadataAlloc ();
+    }
+
+    char *modelName = pmModelClassGetName (psf->type);
+    psMetadataAdd (metadata, PS_LIST_TAIL, "PSF_MODEL_NAME", PS_DATA_STRING, "PSF model name", modelName);
+
+    int nPar = pmModelClassParameterCount (psf->type)    ;
+    psMetadataAdd (metadata, PS_LIST_TAIL, "PSF_MODEL_NPAR", PS_DATA_S32, "PSF model parameter count", nPar);
+
+    for (int i = 0; i < nPar; i++) {
+        psPolynomial2D *poly = psf->params->data[i];
+        if (poly == NULL)
+            continue;
+        psPolynomial2DtoMetadata (metadata, poly, "PSF_PAR%02d", i);
+    }
+
+    // XXX fix this
+    psWarning ("APTREND is currently missing");
+    // psPolynomial4DtoMetadata (metadata, psf->ApTrend, "APTREND");
+
+    psMetadataAdd (metadata, PS_LIST_TAIL, "PSF_AP_RESID", PS_DATA_F32, "aperture residual", psf->ApResid);
+    psMetadataAdd (metadata, PS_LIST_TAIL, "PSF_dAP_RESID", PS_DATA_F32, "aperture residual scatter", psf->dApResid);
+    psMetadataAdd (metadata, PS_LIST_TAIL, "PSF_SKY_BIAS", PS_DATA_F32, "sky bias level", psf->skyBias);
+
+    psMetadataAdd (metadata, PS_LIST_TAIL, "PSF_CHISQ", PS_DATA_F32, "chi-square for fit", psf->chisq);
+    psMetadataAdd (metadata, PS_LIST_TAIL, "PSF_NSTARS", PS_DATA_S32, "number of stars used to measure PSF", psf->nPSFstars);
+    psMetadataAdd (metadata, PS_LIST_TAIL, "PSF_POISSON_ERRORS", PS_DATA_BOOL, "Poisson errors for fits", psf->poissonErrors);
+
+    return metadata;
+}
+
+// parse a psMetadata representation (human-readable) of a psf model
+pmPSF *pmPSFfromMetadata (psMetadata *metadata)
+{
+
+    bool status;
+    char keyword[80];
+
+    char *modelName = psMetadataLookupPtr (&status, metadata, "PSF_MODEL_NAME");
+    pmModelType type = pmModelClassGetType (modelName);
+
+    bool poissonErrors = psMetadataLookupPtr (&status, metadata, "PSF_POISSON_ERRORS");
+    if (!status)
+        poissonErrors = true;
+
+    // we determine the PSF parameter polynomials from the MD-defined polynomials
+    pmPSF *psf = pmPSFAlloc (type, poissonErrors, NULL);
+
+    int nPar = psMetadataLookupS32 (&status, metadata, "PSF_MODEL_NPAR");
+    if (nPar != pmModelClassParameterCount (psf->type))
+        psAbort("mismatch model par count");
+
+    // un-fitted terms, not in the Metadata, are left NULL
+    // XXX add a double-check of the expected number?
+    for (int i = 0; i < nPar; i++) {
+        sprintf (keyword, "PSF_PAR%02d", i);
+        psMetadata *folder = psMetadataLookupPtr (&status, metadata, keyword);
+        if (!status)
+            continue;
+        psPolynomial2D *poly = psPolynomial2DfromMetadata (folder);
+        psFree (psf->params->data[i]);
+        psf->params->data[i] = poly;
+    }
+
+    // load the APTREND data
+    // XXX fix this to work with pmTrend2D
+    psWarning ("APTREND is not being read");
+    # if (0)
+    sprintf (keyword, "APTREND");
+    psMetadata *folder = psMetadataLookupPtr (&status, metadata, keyword);
+    psPolynomial4D *poly = psPolynomial4DfromMetadata (folder);
+    psFree (psf->ApTrend);
+    psf->ApTrend = poly;
+    # endif
+
+    psf->ApResid = psMetadataLookupF32 (&status, metadata, "PSF_AP_RESID");
+    psf->dApResid = psMetadataLookupF32 (&status, metadata, "PSF_dAP_RESID");
+    psf->skyBias = psMetadataLookupF32 (&status, metadata, "PSF_SKY_BIAS");
+
+    psf->chisq = psMetadataLookupF32 (&status, metadata, "PSF_CHISQ");
+    psf->nPSFstars = psMetadataLookupS32 (&status, metadata, "PSF_NSTARS");
+
+    psFree (metadata);
+    return (psf);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSFtry.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSFtry.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSFtry.c	(revision 22158)
@@ -0,0 +1,852 @@
+/** @file  pmPSFtry.c
+ *
+ *  XXX: need description of file purpose
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.58 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-16 23:06:10 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+# include <pslib.h>
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPAMaskWeight.h"
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmResiduals.h"
+#include "pmGrowthCurve.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmSourceUtils.h"
+#include "pmPSFtry.h"
+#include "pmModelClass.h"
+#include "pmModelUtils.h"
+#include "pmSourceFitModel.h"
+#include "pmSourcePhotometry.h"
+
+// ********  pmPSFtry functions  **************************************************
+// * pmPSFtry holds a single pmPSF model test, with the input sources, the freely
+// * fitted version of the model, the pmPSF fit to the fitted model parameters,
+// * and the PSF fits to the source. It also includes the statistics from the
+// * fits, both the individual sources, and the collection
+
+// free a pmPSFtry structure
+static void pmPSFtryFree (pmPSFtry *test)
+{
+    if (test == NULL) return;
+
+    psFree (test->psf);
+    psFree (test->sources);
+    psFree (test->metric);
+    psFree (test->metricErr);
+    psFree (test->fitMag);
+    psFree (test->mask);
+    return;
+}
+
+// allocate a pmPSFtry based on the desired sources and the model (identified by name)
+pmPSFtry *pmPSFtryAlloc (const psArray *sources, const pmPSFOptions *options)
+{
+    pmPSFtry *test = (pmPSFtry *) psAlloc(sizeof(pmPSFtry));
+    psMemSetDeallocator(test, (psFreeFunc) pmPSFtryFree);
+
+    test->psf       = pmPSFAlloc (options);
+    test->metric    = psVectorAlloc (sources->n, PS_TYPE_F32);
+    test->metricErr = psVectorAlloc (sources->n, PS_TYPE_F32);
+    test->fitMag    = psVectorAlloc (sources->n, PS_TYPE_F32);
+    test->mask      = psVectorAlloc (sources->n, PS_TYPE_U8);
+
+    psVectorInit (test->mask,        0);
+    psVectorInit (test->metric,    0.0);
+    psVectorInit (test->metricErr, 0.0);
+    psVectorInit (test->fitMag,    0.0);
+
+    test->sources   = psArrayAlloc (sources->n);
+
+    for (int i = 0; i < sources->n; i++) {
+        test->sources->data[i] = pmSourceCopy (sources->data[i]);
+    }
+
+    return (test);
+}
+
+bool psMemCheckPSFtry(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmPSFtryFree);
+}
+
+
+// build a pmPSFtry for the given model:
+// - fit each source with the free-floating model
+// - construct the pmPSF from the collection of models
+// - fit each source with the PSF-parameter models
+// - measure the pmPSF quality metric (dApResid)
+
+// sources used in for pmPSFtry may be masked by the analysis
+// mask values indicate the reason the source was rejected:
+
+// generate a pmPSFtry with a copy of the test PSF sources
+pmPSFtry *pmPSFtryModel (const psArray *sources, const char *modelName, pmPSFOptions *options, psMaskType maskVal, psMaskType markVal)
+{
+    bool status;
+    int Next = 0;
+    int Npsf = 0;
+
+    // validate the requested model name
+    options->type = pmModelClassGetType (modelName);
+    if (options->type == -1) {
+        psError (PS_ERR_UNKNOWN, true, "invalid model name %s", modelName);
+        return NULL;
+    }
+
+    pmPSFtry *psfTry = pmPSFtryAlloc (sources, options);
+    if (psfTry == NULL) {
+        psError (PS_ERR_UNKNOWN, false, "failed to allocate psf model");
+        return NULL;
+    }
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
+    // stage 1:  fit an EXT model to all candidates PSF sources
+    psTimerStart ("fit");
+    for (int i = 0; i < psfTry->sources->n; i++) {
+
+        pmSource *source = psfTry->sources->data[i];
+        source->modelEXT = pmSourceModelGuess (source, psfTry->psf->type);
+        if (source->modelEXT == NULL) {
+            psError(PS_ERR_UNKNOWN, false, "failed to build model");
+            psFree(psfTry);
+            return NULL;
+        }
+
+        // set object mask to define valid pixels
+        psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, options->radius, "OR", markVal);
+
+        // fit model as EXT, not PSF
+        status = pmSourceFitModel (source, source->modelEXT, PM_SOURCE_FIT_EXT, maskVal);
+
+	// clear object mask to define valid pixels
+        psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, options->radius, "AND", PS_NOT_U8(markVal));
+
+        // exclude the poor fits
+        if (!status) {
+            psfTry->mask->data.U8[i] = PSFTRY_MASK_EXT_FAIL;
+            psTrace ("psModules.objects", 4, "masking %d (%d,%d) : status is poor\n", i, source->peak->x, source->peak->y);
+            continue;
+        }
+        Next ++;
+    }
+    psLogMsg ("psphot.psftry", 4, "fit ext:   %f sec for %d of %ld sources\n", psTimerMark ("fit"), Next, sources->n);
+    psTrace ("psphot.psftry", 3, "keeping %d of %ld PSF candidates (EXT)\n", Next, sources->n);
+
+    // stage 2: construct a psf (pmPSF) from this collection of model fits
+    if (!pmPSFFromPSFtry (psfTry)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to construct a psf model from collection of sources");
+        psFree(psfTry);
+        return NULL;
+    }
+
+    // stage 3: refit with fixed shape parameters
+    psTimerStart ("fit");
+    for (int i = 0; i < psfTry->sources->n; i++) {
+
+        pmSource *source = psfTry->sources->data[i];
+
+        // masked for: bad model fit, outlier in parameters
+        if (psfTry->mask->data.U8[i] & PSFTRY_MASK_ALL) {
+            psTrace ("psModules.objects", 4, "dropping %d (%d,%d) : source is masked\n", i, source->peak->x, source->peak->y);
+            continue;
+	}
+
+        // set shape for this model based on PSF
+        source->modelPSF = pmModelFromPSF (source->modelEXT, psfTry->psf);
+        if (source->modelPSF == NULL) {
+            psfTry->mask->data.U8[i] = PSFTRY_MASK_BAD_MODEL;
+            abort();
+            continue;
+        }
+        source->modelPSF->radiusFit = options->radius;
+
+        // set object mask to define valid pixels
+        psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, options->radius, "OR", markVal);
+
+        // fit the PSF model to the source
+        status = pmSourceFitModel (source, source->modelPSF, PM_SOURCE_FIT_PSF, maskVal);
+
+        // skip poor fits
+        if (!status) {
+	    psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, options->radius, "AND", PS_NOT_U8(markVal));
+            psfTry->mask->data.U8[i] = PSFTRY_MASK_PSF_FAIL;
+            psTrace ("psModules.objects", 4, "dropping %d (%d,%d) : failed PSF fit\n", i, source->peak->x, source->peak->y);
+            continue;
+        }
+
+        status = pmSourceMagnitudes (source, psfTry->psf, PM_SOURCE_PHOT_INTERP, maskVal);
+	if (!status || isnan(source->apMag)) {
+	    psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, options->radius, "AND", PS_NOT_U8(markVal));
+            psfTry->mask->data.U8[i] = PSFTRY_MASK_BAD_PHOT;
+            psTrace ("psModules.objects", 4, "dropping %d (%d,%d) : poor photometry\n", i, source->peak->x, source->peak->y);
+            continue;
+        }
+
+	// clear object mask to define valid pixels
+        psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, options->radius, "AND", PS_NOT_U8(markVal));
+
+        psfTry->fitMag->data.F32[i] = source->psfMag;
+        psfTry->metric->data.F32[i] = source->apMag - source->psfMag;
+        psfTry->metricErr->data.F32[i] = source->errMag;
+
+	psTrace ("psphot.psftry", 6, "keeping source %d (%d) of %ld\n", i, Npsf, psfTry->sources->n);
+        Npsf ++;
+    }
+    psfTry->psf->nPSFstars = Npsf;
+
+    psLogMsg ("psphot.psftry", 4, "fit psf:   %f sec for %d of %ld sources\n", psTimerMark ("fit"), Npsf, sources->n);
+    psTrace ("psphot.psftry", 3, "keeping %d of %ld PSF candidates (PSF)\n", Npsf, sources->n);
+
+    // measure the chi-square trend as a function of flux (PAR[PM_PAR_I0])
+    // this should be linear for Poisson errors and quadratic for constant sky errors
+    psVector *flux  = psVectorAlloc (psfTry->sources->n, PS_TYPE_F32);
+    psVector *chisq = psVectorAlloc (psfTry->sources->n, PS_TYPE_F32);
+    psVector *mask  = psVectorAlloc (psfTry->sources->n, PS_TYPE_MASK);
+
+    // generate the x and y vectors, and mask missing models
+    for (int i = 0; i < psfTry->sources->n; i++) {
+        pmSource *source = psfTry->sources->data[i];
+        if (source->modelPSF == NULL) {
+            flux->data.F32[i] = 0.0;
+            chisq->data.F32[i] = 0.0;
+            mask->data.U8[i] = 0xff;
+        } else {
+            flux->data.F32[i] = source->modelPSF->params->data.F32[PM_PAR_I0];
+            chisq->data.F32[i] = source->modelPSF->chisq / source->modelPSF->nDOF;
+            mask->data.U8[i] = 0;
+        }
+    }
+
+    // use 3hi/3lo sigma clipping on the chisq fit
+    psStats *stats = options->stats;
+
+    // linear clipped fit of chisq trend vs flux
+    bool result = psVectorClipFitPolynomial1D(psfTry->psf->ChiTrend, options->stats, mask,
+                                              0xff, chisq, NULL, flux);
+    psStatsOptions meanStat = psStatsMeanOption(options->stats->options); // Statistic for mean
+    psStatsOptions stdevStat = psStatsStdevOption(options->stats->options); // Statistic for stdev
+
+    psLogMsg ("pmPSFtry", 4, "chisq vs flux fit: %f +/- %f\n",
+              psStatsGetValue(stats, meanStat), psStatsGetValue(stats, stdevStat));
+
+    psFree(flux);
+    psFree(mask);
+    psFree(chisq);
+
+    if (!result) {
+        psError(PS_ERR_UNKNOWN, false, "Failed to fit psf->ChiTrend");
+        psFree(psfTry);
+        return NULL;
+    }
+
+    for (int i = 0; i < psfTry->psf->ChiTrend->nX + 1; i++) {
+        psLogMsg ("pmPSFtry", 4, "chisq vs flux fit term %d: %f +/- %f\n", i,
+                  psfTry->psf->ChiTrend->coeff[i]*pow(10000, i),
+                  psfTry->psf->ChiTrend->coeffErr[i]*pow(10000,i));
+    }
+
+    // XXX this function wants aperture radius for pmSourcePhotometry
+    if (!pmPSFtryMetric (psfTry, options)) {
+        psError(PS_ERR_UNKNOWN, false, "Attempt to fit PSF with model %s failed.", modelName);
+	psFree (psfTry);
+        return NULL;
+    }
+
+    psLogMsg ("psphot.pspsf", 3, "try model %s, ap-fit: %f +/- %f : sky bias: %f\n",
+              modelName, psfTry->psf->ApResid, psfTry->psf->dApResid, psfTry->psf->skyBias);
+
+    return (psfTry);
+}
+
+bool pmPSFtryMetric (pmPSFtry *psfTry, pmPSFOptions *options)
+{
+    PS_ASSERT_PTR_NON_NULL(psfTry, false);
+    PS_ASSERT_PTR_NON_NULL(options, false);
+    PS_ASSERT_PTR_NON_NULL(psfTry->sources, false);
+
+    float RADIUS = options->radius;
+
+    // the measured (aperture - fit) magnitudes (dA == psfTry->metric)
+    //   depend on both the true ap-fit (dAo) and the bias in the sky measurement:
+    //     dA = dAo + dsky/flux
+    //   where flux is the flux of the star
+    // we fit this trend to find the infinite flux aperture correction (dAo),
+    //   the nominal sky bias (dsky), and the error on dAo
+    // the values of dA are contaminated by stars with close neighbors in the aperture
+    //   we use an outlier rejection to avoid this bias
+
+    // r2rflux = radius^2 * ten(0.4*fitMag);
+    psVector *r2rflux = psVectorAlloc (psfTry->sources->n, PS_TYPE_F32);
+
+    for (int i = 0; i < psfTry->sources->n; i++) {
+        if (psfTry->mask->data.U8[i] & PSFTRY_MASK_ALL)
+            continue;
+        r2rflux->data.F32[i] = PS_SQR(RADIUS) * pow(10.0, 0.4*psfTry->fitMag->data.F32[i]);
+    }
+
+    // XXX test dump of aperture residual data
+    if (psTraceGetLevel("psModules.objects") >= 5) {
+        FILE *f = fopen ("apresid.dat", "w");
+        for (int i = 0; i < psfTry->sources->n; i++) {
+            int keep = (psfTry->mask->data.U8[i] & PSFTRY_MASK_ALL);
+
+            pmSource *source = psfTry->sources->data[i];
+            float x = source->peak->x;
+            float y = source->peak->y;
+
+            fprintf (f, "%d  %d, %f %f %f  %f %f %f \n",
+                     i, keep, x, y,
+                     psfTry->fitMag->data.F32[i],
+                     r2rflux->data.F32[i],
+                     psfTry->metric->data.F32[i],
+                     psfTry->metricErr->data.F32[i]);
+        }
+        fclose (f);
+    }
+
+    // This analysis of the apResid statistics is only approximate.  The fitted magnitudes
+    // measured at this point (in the PSF fit) use Poisson errors, and are thus biased as a
+    // function of magnitude.  We re-measure the apResid statistics later in psphot using the
+    // linear, constant-error fitting.  Do not reject outliers with excessive vigor here.
+
+    // fit ApTrend only to r2rflux, ignore x,y,flux variations for now
+    // linear clipped fit of ApResid to r2rflux
+    psPolynomial1D *poly = psPolynomial1DAlloc (PS_POLYNOMIAL_ORD, 1);
+    poly->coeffMask[1] = PS_POLY_MASK_SET; // fit only a constant offset (no SKYBIAS)
+
+    // XXX replace this with a psVectorStats call?  since we are not fitting the trend
+    bool result = psVectorClipFitPolynomial1D(poly, options->stats, psfTry->mask, PSFTRY_MASK_ALL,
+                                              psfTry->metric, psfTry->metricErr, r2rflux);
+    if (!result) {
+        psError(PS_ERR_UNKNOWN, false, "Failed to fit clipped poly");
+
+        psFree(poly);
+        psFree(r2rflux);
+
+        return false;
+    }
+    psStatsOptions stdevStat = psStatsStdevOption(options->stats->options); // Statistic for stdev
+    psLogMsg ("pmPSFtryMetric", 4, "apresid: %f +/- %f; from statistics of %ld psf stars\n", poly->coeff[0],
+              psStatsGetValue(options->stats, stdevStat), psfTry->sources->n);
+
+
+
+    // XXX test dump of fitted model (dump when tracing?)
+    if (psTraceGetLevel("psModules.objects") >= 4) {
+        FILE *f = fopen ("resid.dat", "w");
+        psVector *apfit = psPolynomial1DEvalVector (poly, r2rflux);
+        for (int i = 0; i < psfTry->sources->n; i++) {
+            int keep = (psfTry->mask->data.U8[i] & PSFTRY_MASK_ALL);
+
+            pmSource *source = psfTry->sources->data[i];
+            float x = source->peak->x;
+            float y = source->peak->y;
+
+            fprintf (f, "%d  %d, %f %f %f  %f %f %f  %f\n",
+                     i, keep, x, y,
+                     psfTry->fitMag->data.F32[i],
+                     r2rflux->data.F32[i],
+                     psfTry->metric->data.F32[i],
+                     psfTry->metricErr->data.F32[i],
+                     apfit->data.F32[i]);
+        }
+        fclose (f);
+        psFree (apfit);
+    }
+
+    // XXX drop the skyBias value, or include above??
+    psfTry->psf->skyBias  = poly->coeff[1];
+    psfTry->psf->ApResid  = poly->coeff[0];
+    psfTry->psf->dApResid = psStatsGetValue(options->stats, stdevStat);
+
+    psFree (r2rflux);
+    psFree (poly);
+
+    return true;
+}
+
+/*
+  (aprMag' - fitMag) = rflux*skyBias + ApTrend(x,y)
+  (aprMag - rflux*skyBias) - fitMag = ApTrend(x,y)
+  (aprMag - rflux*skyBias) = fitMag + ApTrend(x,y)
+*/
+
+/*****************************************************************************
+pmPSFFromPSFtry (psfTry): build a PSF model from a collection of
+source->modelEXT entries.  The PSF ignores the first 4 (independent) model
+parameters and constructs a polynomial fit to the remaining as a function of
+image coordinate.
+    input: psfTry with fitted source->modelEXT collection, pre-allocated psf
+Note: some of the array entries may be NULL (failed fits); ignore them.
+ *****************************************************************************/
+bool pmPSFFromPSFtry (pmPSFtry *psfTry)
+{
+    PS_ASSERT_PTR_NON_NULL(psfTry, false);
+    PS_ASSERT_PTR_NON_NULL(psfTry->sources, false);
+
+    pmPSF *psf = psfTry->psf;
+
+    // construct the fit vectors from the collection of objects
+    psVector *x  = psVectorAlloc (psfTry->sources->n, PS_TYPE_F32);
+    psVector *y  = psVectorAlloc (psfTry->sources->n, PS_TYPE_F32);
+    psVector *z  = psVectorAlloc (psfTry->sources->n, PS_TYPE_F32);
+
+    // construct the x,y terms
+    for (int i = 0; i < psfTry->sources->n; i++) {
+        pmSource *source = psfTry->sources->data[i];
+        if (source->modelEXT == NULL)
+            continue;
+
+        x->data.F32[i] = source->modelEXT->params->data.F32[PM_PAR_XPOS];
+        y->data.F32[i] = source->modelEXT->params->data.F32[PM_PAR_YPOS];
+    }
+
+    if (!pmPSFFitShapeParams (psf, psfTry->sources, x, y, psfTry->mask)) {
+        psFree(x);
+        psFree(y);
+        psFree(z);
+        return false;
+    }
+
+    // skip the unfitted parameters (X, Y, Io, Sky) and the shape parameters (SXX, SYY, SXY)
+    // apply the values of Nx, Ny determined above for E0,E1,E2 to the remaining parameters
+    for (int i = 0; i < psf->params->n; i++) {
+        switch (i) {
+          case PM_PAR_SKY:
+          case PM_PAR_I0:
+          case PM_PAR_XPOS:
+          case PM_PAR_YPOS:
+          case PM_PAR_SXX:
+          case PM_PAR_SYY:
+          case PM_PAR_SXY:
+            continue;
+          default:
+            break;
+        }
+
+        // select the per-object fitted data for this parameter
+        for (int j = 0; j < psfTry->sources->n; j++) {
+            pmSource *source = psfTry->sources->data[j];
+            if (source->modelEXT == NULL) continue;
+            z->data.F32[j] = source->modelEXT->params->data.F32[i];
+        }
+
+        psImageBinning *binning = psImageBinningAlloc();
+        binning->nXruff = psf->trendNx;
+        binning->nYruff = psf->trendNy;
+        binning->nXfine = psf->fieldNx;
+        binning->nYfine = psf->fieldNy;
+
+        if (psf->psfTrendMode == PM_TREND_MAP) {
+            psImageBinningSetScale (binning, PS_IMAGE_BINNING_CENTER);
+            psImageBinningSetSkipByOffset (binning, psf->fieldXo, psf->fieldYo);
+        }
+
+        // free existing trend, re-alloc
+        psFree (psf->params->data[i]);
+        psf->params->data[i] = pmTrend2DNoImageAlloc (psf->psfTrendMode, binning, psf->psfTrendStats);
+        psFree (binning);
+
+        // fit the collection of measured parameters to the PSF 2D model
+        // the mask is carried from previous steps and updated with this operation
+        // the weight is either the flux error or NULL, depending on 'psf->poissonErrorParams'
+        if (!pmTrend2DFit (psf->params->data[i], psfTry->mask, 0xff, x, y, z, NULL)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to build psf model for parameter %d", i);
+            psFree(x);
+            psFree(y);
+            psFree(z);
+            return false;
+        }
+    }
+
+    // test dump of star parameters vs position (compare with fitted values)
+    if (psTraceGetLevel("psModules.objects") >= 4) {
+        FILE *f = fopen ("params.dat", "w");
+
+        for (int j = 0; j < psfTry->sources->n; j++) {
+            pmSource *source = psfTry->sources->data[j];
+            if (source == NULL) continue;
+            if (source->modelEXT == NULL) continue;
+
+            pmModel *modelPSF = pmModelFromPSF (source->modelEXT, psf);
+
+            fprintf (f, "%f %f : ", source->modelEXT->params->data.F32[PM_PAR_XPOS], source->modelEXT->params->data.F32[PM_PAR_YPOS]);
+
+            for (int i = 0; i < psf->params->n; i++) {
+                if (psf->params->data[i] == NULL) continue;
+                fprintf (f, "%f %f : ", source->modelEXT->params->data.F32[i], modelPSF->params->data.F32[i]);
+            }
+            fprintf (f, "%f %d\n", source->modelEXT->chisq, source->modelEXT->nIter);
+
+            psFree(modelPSF);
+        }
+        fclose (f);
+    }
+
+    psFree (x);
+    psFree (y);
+    psFree (z);
+    return true;
+}
+
+
+bool pmPSFFitShapeParams (pmPSF *psf, psArray *sources, psVector *x, psVector *y, psVector *srcMask) {
+
+    // we are doing a robust fit.  after each pass, we drop points which are more deviant than
+    // three sigma.  mask is currently updated for each pass.
+
+    // The shape parameters (SXX, SXY, SYY) are strongly coupled.  We have to handle them very
+    // carefully.  First, we convert them to the Ellipse Polarization terms (E0, E1, E2) for
+    // each source and fit this set of parameters.  These values are less tightly coupled, but
+    // are still inter-related.  The fitted values do a good job of constraining the major axis
+    // and the position angle, but the minor axis is weakly measured.  When we apply the PSF
+    // model to construct a source model, we convert the fitted values of E0,E1,E2 to the shape
+    // parameters, with the constraint that the minor axis must be greater than a minimum
+    // threshold.
+
+    // convert the measured source shape paramters to polarization terms
+    psVector *e0   = psVectorAlloc (sources->n, PS_TYPE_F32);
+    psVector *e1   = psVectorAlloc (sources->n, PS_TYPE_F32);
+    psVector *e2   = psVectorAlloc (sources->n, PS_TYPE_F32);
+    psVector *mag  = psVectorAlloc (sources->n, PS_TYPE_F32);
+    for (int i = 0; i < sources->n; i++) {
+        pmSource *source = sources->data[i];
+        if (source->modelEXT == NULL) continue;
+        // XXX I am relying on the fact that none of the masked sources
+        // have modelEXT set here.  perhaps use the value of psfTry->mask instead?
+
+        psEllipsePol pol = pmPSF_ModelToFit (source->modelEXT->params->data.F32);
+
+        e0->data.F32[i] = pol.e0;
+        e1->data.F32[i] = pol.e1;
+        e2->data.F32[i] = pol.e2;
+
+        float flux = source->modelEXT->params->data.F32[PM_PAR_I0];
+        mag->data.F32[i] = (flux > 0.0) ? -2.5*log(flux) : -100.0;
+    }
+
+    if (psf->psfTrendMode == PM_TREND_MAP) {
+        float errorFloor = 0.0;
+        float errorTotal = 0.0;
+        float errorTotalMin = FLT_MAX;
+        int entryMin = -1;
+
+        psVector *dz = NULL;
+        psVector *mask = psVectorAlloc (sources->n, PS_TYPE_U8);
+
+        // check the fit residuals and increase Nx,Ny until the error is minimized
+        // pmPSFParamTrend increases the number along the longer of x or y
+        for (int i = 1; i < PS_MAX (psf->trendNx, psf->trendNy); i++) {
+
+            psVectorInit (mask, 0);
+            if (!pmPSFFitShapeParamsMap (psf, i, &errorFloor, &errorTotal, mask, x, y, mag, e0, e1, e2, dz)) {
+                break;
+            }
+
+            // we do not have a good model for the error distributions on e0, e1, e2.
+            // use the bright end scatter from the constant fit to set the scale for the
+            // versions with 2D variation.  potentially scale by poisson errors...
+            if (i == 1) {
+                // if (psf->poissonErrorsParams) do something else..
+                dz = psVectorAlloc (sources->n, PS_TYPE_F32);
+                for (int i = 0; i < sources->n; i++) {
+                    dz->data.F32[i] = errorFloor;
+                }
+            }
+
+            // store the resulting errorTotal values and the scales, redo the best
+            if (errorTotal < errorTotalMin) {
+                errorTotalMin = errorTotal;
+                entryMin = i;
+            }
+        }
+        if (entryMin == -1) {
+            psError (PS_ERR_UNKNOWN, true, "failed to find image map for shape params");
+            return false;
+        }
+
+        // XXX supply the resulting mask values back to srcMask
+        psVectorInit (mask, 0);
+        if (!pmPSFFitShapeParamsMap (psf, entryMin, &errorFloor, &errorTotal, mask, x, y, mag, e0, e1, e2, dz)) {
+            psAbort ("failed pmPSFFitShapeParamsMap on second pass?");
+        }
+
+        pmTrend2D *trend = psf->params->data[PM_PAR_E0];
+        psf->trendNx = trend->map->map->numCols;
+        psf->trendNy = trend->map->map->numRows;
+
+        psFree (mask);
+        psFree (dz);
+    } else {
+
+        // XXX iterate Nx, Ny based on scatter?
+        // XXX we force the x & y order to be the same
+        // modify the order to correspond to the actual number of matched stars:
+        int order = PS_MAX (psf->trendNx, psf->trendNy);
+        if ((sources->n < 15) && (order >= 3)) order = 2;
+        if ((sources->n < 11) && (order >= 2)) order = 1;
+        if ((sources->n <  8) && (order >= 1)) order = 0;
+        if ((sources->n <  3)) {
+            psError (PS_ERR_UNKNOWN, true, "failed to fit polynomial to shape params");
+            return false;
+        }
+        psf->trendNx = order;
+        psf->trendNy = order;
+
+        // we run 'clipIter' cycles clipping in each of x and y, with only one iteration each.
+        // This way, the parameters masked by one of the fits will be applied to the others
+        for (int i = 0; i < psf->psfTrendStats->clipIter; i++) {
+
+            // XXX we are using the same stats structure on each pass: do we need to re-init it?
+            bool status = true;
+            status &= pmTrend2DFit (psf->params->data[PM_PAR_E0], srcMask, 0xff, x, y, e0, NULL);
+            psTrace ("psModules.pmPSFtry", 4, "clipped E0 : keeping %ld of %ld\n", psf->psfTrendStats->clippedNvalues, e0->n);
+            status &= pmTrend2DFit (psf->params->data[PM_PAR_E1], srcMask, 0xff, x, y, e1, NULL);
+            psTrace ("psModules.pmPSFtry", 4, "clipped E1 : keeping %ld of %ld\n", psf->psfTrendStats->clippedNvalues, e1->n);
+            status &= pmTrend2DFit (psf->params->data[PM_PAR_E2], srcMask, 0xff, x, y, e2, NULL);
+            psTrace ("psModules.pmPSFtry", 4, "clipped E2 : keeping %ld of %ld\n", psf->psfTrendStats->clippedNvalues, e2->n);
+
+            if (!status) {
+                psError (PS_ERR_UNKNOWN, true, "failed to fit polynomial to shape params");
+                return false;
+            }
+        }
+    }
+
+    // test dump of the psf parameters
+    if (psTraceGetLevel("psModules.objects") >= 4) {
+        FILE *f = fopen ("pol.dat", "w");
+        fprintf (f, "# x y  :  e0obs e1obs e2obs  : e0fit e1fit e2fit : mask\n");
+        for (int i = 0; i < e0->n; i++) {
+            fprintf (f, "%f %f  :  %f %f %f  : %f %f %f  : %d\n",
+                     x->data.F32[i], y->data.F32[i],
+                     e0->data.F32[i], e1->data.F32[i], e2->data.F32[i],
+                     pmTrend2DEval (psf->params->data[PM_PAR_E0], x->data.F32[i], y->data.F32[i]),
+                     pmTrend2DEval (psf->params->data[PM_PAR_E1], x->data.F32[i], y->data.F32[i]),
+                     pmTrend2DEval (psf->params->data[PM_PAR_E2], x->data.F32[i], y->data.F32[i]),
+                     srcMask->data.U8[i]);
+        }
+        fclose (f);
+    }
+
+    psFree (e0);
+    psFree (e1);
+    psFree (e2);
+    psFree (mag);
+    return true;
+}
+
+// fit the shape variations as a psImageMap for the given scale factor
+bool pmPSFFitShapeParamsMap (pmPSF *psf, int scale, float *errorFloor, float *errorTotal, psVector *mask, psVector *x, psVector *y, psVector *mag, psVector *e0obs, psVector *e1obs, psVector *e2obs, psVector *dz) {
+
+    int Nx, Ny;
+
+    // set the map scale to match the aspect ratio
+    if (psf->fieldNx > psf->fieldNy) {
+        Nx = scale;
+        Ny = PS_MAX (1, Nx * (psf->fieldNy / psf->fieldNx));
+    } else {
+        Ny = scale;
+        Nx = PS_MAX (1, Ny * (psf->fieldNx / psf->fieldNy));
+    }
+
+    // do we have enough sources for this fine of a grid?
+    if (x->n < 3*Nx*Ny) {
+        return false;
+    }
+
+    // the mask marks the values not used to calculate the ApTrend
+    psVectorInit (mask, 0);
+
+    // XXX check this against the exising type
+    pmTrend2DMode psfTrendMode = PM_TREND_MAP;
+
+    psImageBinning *binning = psImageBinningAlloc();
+    binning->nXruff = Nx;
+    binning->nYruff = Ny;
+    binning->nXfine = psf->fieldNx;
+    binning->nYfine = psf->fieldNy;
+    psImageBinningSetScale (binning, PS_IMAGE_BINNING_CENTER);
+    psImageBinningSetSkipByOffset (binning, psf->fieldXo, psf->fieldYo);
+
+    psFree (psf->params->data[PM_PAR_E0]);
+    psFree (psf->params->data[PM_PAR_E1]);
+    psFree (psf->params->data[PM_PAR_E2]);
+
+    int nIter = psf->psfTrendStats->clipIter;
+    psf->psfTrendStats->clipIter = 1;
+    psf->params->data[PM_PAR_E0] = pmTrend2DNoImageAlloc (psfTrendMode, binning, psf->psfTrendStats);
+    psf->params->data[PM_PAR_E1] = pmTrend2DNoImageAlloc (psfTrendMode, binning, psf->psfTrendStats);
+    psf->params->data[PM_PAR_E2] = pmTrend2DNoImageAlloc (psfTrendMode, binning, psf->psfTrendStats);
+    psFree (binning);
+
+    // we run 'clipIter' cycles clipping in each of x and y, with only one iteration each.
+    // This way, the parameters masked by one of the fits will be applied to the others
+    for (int i = 0; i < nIter; i++) {
+        // XXX we are using the same stats structure on each pass: do we need to re-init it?
+        pmTrend2DFit (psf->params->data[PM_PAR_E0], mask, 0xff, x, y, e0obs, dz);
+        psTrace ("psModules.objects", 5, "clipped E0 : keeping %ld of %ld\n", psf->psfTrendStats->clippedNvalues, e0obs->n);
+        pmTrend2DFit (psf->params->data[PM_PAR_E1], mask, 0xff, x, y, e1obs, dz);
+        psTrace ("psModules.objects", 5, "clipped E1 : keeping %ld of %ld\n", psf->psfTrendStats->clippedNvalues, e1obs->n);
+        pmTrend2DFit (psf->params->data[PM_PAR_E2], mask, 0xff, x, y, e2obs, dz);
+        psTrace ("psModules.objects", 5, "clipped E2 : keeping %ld of %ld\n", psf->psfTrendStats->clippedNvalues, e2obs->n);
+    }
+    psf->psfTrendStats->clipIter = nIter; // restore default setting
+
+    // construct the fitted values and the residuals
+    psVector *e0fit = pmTrend2DEvalVector (psf->params->data[PM_PAR_E0], x, y);
+    psVector *e1fit = pmTrend2DEvalVector (psf->params->data[PM_PAR_E1], x, y);
+    psVector *e2fit = pmTrend2DEvalVector (psf->params->data[PM_PAR_E2], x, y);
+
+    psVector *e0res = (psVector *) psBinaryOp (NULL, (void *) e0obs, "-", (void *) e0fit);
+    psVector *e1res = (psVector *) psBinaryOp (NULL, (void *) e1obs, "-", (void *) e1fit);
+    psVector *e2res = (psVector *) psBinaryOp (NULL, (void *) e2obs, "-", (void *) e2fit);
+
+    // measure errors on the map pixels
+    pmTrend2D *trend;
+
+    trend = psf->params->data[PM_PAR_E0];
+    float mapErrorSum = 0.0;
+    float mapError = 0.0;
+    for (int iy = 0; iy < trend->map->error->numRows; iy++) {
+        for (int ix = 0; ix < trend->map->error->numCols; ix++) {
+            mapError += PS_SQR (trend->map->error->data.F32[iy][ix]);
+        }
+    }
+    psTrace ("psModules.objects", 4, "E0 error: %f\n", sqrt(mapError));
+    mapErrorSum += mapError;
+
+    trend = psf->params->data[PM_PAR_E1];
+    mapError = 0.0;
+    for (int iy = 0; iy < trend->map->error->numRows; iy++) {
+        for (int ix = 0; ix < trend->map->error->numCols; ix++) {
+            mapError += PS_SQR (trend->map->error->data.F32[iy][ix]);
+        }
+    }
+    psTrace ("psModules.objects", 4, "E1 error: %f\n", sqrt(mapError));
+    mapErrorSum += mapError;
+
+    trend = psf->params->data[PM_PAR_E2];
+    mapError = 0.0;
+    for (int iy = 0; iy < trend->map->error->numRows; iy++) {
+        for (int ix = 0; ix < trend->map->error->numCols; ix++) {
+            mapError += PS_SQR (trend->map->error->data.F32[iy][ix]);
+        }
+    }
+    psTrace ("psModules.objects", 4, "E2 error: %f\n", sqrt(mapError));
+    mapErrorSum += mapError;
+
+    psTrace ("psModules.objects", PS_LOG_INFO, "total map error: %f\n", sqrt(mapErrorSum));
+
+    // measure systematic errorFloor & systematic / photon scale factor
+    // XXX this is a bit arbitrary, but it forces ~3 stars from the bright bin per spatial bin
+    int nGroup = PS_MAX (3*Nx*Ny, 10);
+    pmPSFShapeParamsErrors (errorFloor, mag, e0res, e1res, e2res, mask, nGroup,
+                            psStatsStdevOption(psf->psfTrendStats->options));
+
+    *errorTotal = sqrt(PS_SQR(*errorFloor) + mapErrorSum);
+
+    psLogMsg ("psphot.psftry", PS_LOG_INFO, "result of %d x %d grid (%d stars per bin)\n", Nx, Ny, nGroup);
+    psLogMsg ("psphot.psftry", PS_LOG_INFO, "systematic scatter floor: %f, error map total: %f\n", *errorFloor, *errorTotal);
+
+    psFree (e0fit);
+    psFree (e1fit);
+    psFree (e2fit);
+
+    psFree (e0res);
+    psFree (e1res);
+    psFree (e2res);
+
+    return true;
+}
+
+// calculate the minimum scatter of the parameters
+bool pmPSFShapeParamsErrors(float *errorFloor, psVector *mag, psVector *e0res, psVector *e1res,
+                            psVector *e2res, psVector *mask, int nGroup, psStatsOptions stdevOpt)
+{
+
+    psStats *statsS = psStatsAlloc(stdevOpt);
+
+    // measure the trend in bins with 10 values each; if < 10 total, use them all
+    int nBin = PS_MAX (mag->n / nGroup, 1);
+
+    // output vectors for ApResid trend
+    psVector *dSo = psVectorAlloc (nBin, PS_TYPE_F32);
+
+    // use mag to group parameters in sequence
+    psVector *index = psVectorSortIndex (NULL, mag);
+
+    // subset vectors for mag and dap values within the given range
+    psVector *dE0subset = psVectorAllocEmpty (nGroup, PS_TYPE_F32);
+    psVector *dE1subset = psVectorAllocEmpty (nGroup, PS_TYPE_F32);
+    psVector *dE2subset = psVectorAllocEmpty (nGroup, PS_TYPE_F32);
+    psVector *mkSubset  = psVectorAllocEmpty (nGroup, PS_TYPE_U8);
+
+    int n = 0;
+    for (int i = 0; i < dSo->n; i++) {
+        int j;
+        for (j = 0; (j < nGroup) && (n < mag->n); j++, n++) {
+            int N = index->data.U32[n];
+            dE0subset->data.F32[j] = e0res->data.F32[N];
+            dE1subset->data.F32[j] = e1res->data.F32[N];
+            dE2subset->data.F32[j] = e2res->data.F32[N];
+
+            mkSubset->data.U8[j]   = mask->data.U8[N];
+        }
+        dE0subset->n = j;
+        dE1subset->n = j;
+        dE2subset->n = j;
+        mkSubset->n = j;
+
+        // calculate the root-mean-square of E0, E1, E2
+        float dEsquare = 0.0;
+        psStatsInit (statsS);
+        psVectorStats (statsS, dE0subset, NULL, mkSubset, 0xff);
+        dEsquare += PS_SQR(psStatsGetValue(statsS, stdevOpt));
+
+        psStatsInit (statsS);
+        psVectorStats (statsS, dE1subset, NULL, mkSubset, 0xff);
+        dEsquare += PS_SQR(psStatsGetValue(statsS, stdevOpt));
+
+        psStatsInit (statsS);
+        psVectorStats (statsS, dE2subset, NULL, mkSubset, 0xff);
+        dEsquare += PS_SQR(psStatsGetValue(statsS, stdevOpt));
+
+        dSo->data.F32[i] = sqrt(dEsquare);
+    }
+    psFree (dE0subset);
+    psFree (dE1subset);
+    psFree (dE2subset);
+    psFree (mkSubset);
+
+    psStats *minStats = psStatsAlloc(PS_STAT_MIN);
+    psVectorStats(minStats, dSo, NULL, NULL, 0);
+    *errorFloor = minStats->min;
+    psFree(minStats);
+
+    psFree(index);
+    psFree (dSo);
+
+    psFree (statsS);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSFtry.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSFtry.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPSFtry.h	(revision 22158)
@@ -0,0 +1,134 @@
+/* @file  pmPSFtry.h
+ *
+ * This file contains code that allows the user to try to fit several
+ * PSF models to an image.
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-12-15 01:23:18 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+# ifndef PM_PSF_TRY_H
+# define PM_PSF_TRY_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+/**
+ *
+ * This structure contains a pointer to the collection of sources which will
+ * be used to test the PSF model form. It lists the pmModelType type of model
+ * being tests, and contains an element to store the resulting psf
+ * representation. In addition, this structure carries the complete collection of
+ * EXT (floating parameter) and PSF (fixed parameter) model fits to each of the
+ * sources modelEXT and modelPSF. It also contains a mask which is set by the
+ * model fitting and psf fitting steps. For each model, the value of the quality
+ * metric is stored in the vector metric and the fitted instrumental magnitude is
+ * stored in fitMag. The quality metric for the PSF model is the aperture
+ * magnitude minus the fitted magnitude for each source. This collection of
+ * aperture residuals is examined in the analysis process, and a linear trend of
+ * the residual with the inverse object flux (ie, 100:4his structure contains a
+ * pointer to the collection of sources which will be used to test the PSF model
+ * form. It lists the pmModelType type of modmag) is fitted. The result of this
+ * fit is a measured sky bias (systematic error in the sky measured by the fits),
+ * an effective infinite-magnitude aperture correction (ApResid), and the scatter
+ * of the aperture correction for the ensemble of PSF stars (dApResid). The
+ * ultimate metric to intercompare multiple types of PSF models is the value of
+ * the aperture correction scatter.
+ *
+ * XXX: There are many more members in the SDRS then in the prototype code.
+ * I stuck with the prototype code.
+ *
+ *
+ */
+typedef struct
+{
+    pmPSF      *psf;                    ///< Add comment.
+    psArray    *sources;                ///< pointers to the original sources
+    psVector   *mask;                   ///< Add comment.
+    psVector   *metric;                 ///< Add comment.
+    psVector   *metricErr;              ///< Add comment.
+    psVector   *fitMag;                 ///< Add comment.
+}
+pmPSFtry;
+
+
+/** pmPSFtryMaskValues
+ *
+ * The following datatype defines the masks used by the pmPSFtry analysis to
+ * identify sources which should or should not be included in the analysis.
+ *
+ */
+typedef enum {
+    PSFTRY_MASK_CLEAR    = 0x00,        ///< Add comment.
+    PSFTRY_MASK_OUTLIER  = 0x01,        ///< 1: outlier in psf polynomial fit (provided by psPolynomials)
+    PSFTRY_MASK_EXT_FAIL = 0x02,        ///< 2: ext model failed to converge
+    PSFTRY_MASK_PSF_FAIL = 0x04,        ///< 3: psf model failed to converge
+    PSFTRY_MASK_BAD_PHOT = 0x08,        ///< 4: invalid source photometry
+    PSFTRY_MASK_BAD_MODEL= 0x10,        ///< 5: could not build PSF from EXT (!??)
+    PSFTRY_MASK_ALL      = 0x1f,        ///< Add comment.
+} pmPSFtryMaskValues;
+
+
+/** pmPSFtryAlloc()
+ *
+ * Allocate a pmPSFtry data structure.
+ *
+ */
+
+pmPSFtry *pmPSFtryAlloc (const psArray *sources, const pmPSFOptions *options);
+bool psMemCheckPSFtry(psPtr ptr);
+
+/** pmPSFtryModel()
+ *
+ * This function takes the input collection of sources and performs a complete
+ * analysis to determine a PSF model of the given type (specified by model name).
+ * The result is a pmPSFtry with the results of the analysis.
+ *
+ */
+pmPSFtry *pmPSFtryModel (const psArray *sources, const char *modelName, pmPSFOptions *options, psMaskType maskVal, psMaskType mark);
+
+/** pmPSFtryMetric()
+ *
+ * This function is used to measure the PSF model metric for the set of
+ * results contained in the pmPSFtry structure.
+ *
+ */
+bool pmPSFtryMetric(
+    pmPSFtry *psfTry,                  ///< Add comment.
+    pmPSFOptions *options              ///< PSF fitting options
+);
+
+/** pmPSFtryMetric_Alt()
+ *
+ * This function is used to measure the PSF model metric for the set of
+ * results contained in the pmPSFtry structure (alternative implementation).
+ *
+ */
+bool pmPSFtryMetric_Alt(
+    pmPSFtry *try,                      ///< Add comment.
+    float RADIUS                        ///< Add comment.
+);
+
+/**
+ *
+ * This function takes a collection of pmModel fitted models from across a
+ * single image and builds a pmPSF representation of the PSF. The input array of
+ * model fits may consist of entries to be ignored (noted by a non-zero mask
+ * entry). The analysis of the models fits a 2D polynomial for each parameter to
+ * the collection of model parameters as a function of position (and
+ * normalization?). In this process, some of the input models may be marked as
+ * outliers and excluded from the fit. These elements will be marked with a
+ * specific mask value (1 == PSFTRY_MASK_OUTLIER).
+ *
+ */
+bool pmPSFFromPSFtry (pmPSFtry *psfTry);
+
+bool pmPSFFitShapeParams (pmPSF *psf, psArray *sources, psVector *x, psVector *y, psVector *srcMask);
+bool pmPSFFitShapeParamsMap (pmPSF *psf, int scale, float *errorFloor, float *errorTotal, psVector *mask, psVector *x, psVector *y, psVector *mag, psVector *e0obs, psVector *e1obs, psVector *e2obs, psVector *dz);
+bool pmPSFShapeParamsErrors (float *errorFloor, psVector *mag, psVector *e0res, psVector *e1res, psVector *e2res, psVector *mask, int nGroup, psStatsOptions stdevOpt);
+
+/// @}
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPeaks.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPeaks.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPeaks.c	(revision 22158)
@@ -0,0 +1,569 @@
+/** @file  pmPeaks.c
+ *
+ *  This file defines functions to detect and manipulate peaks in images
+ *
+ *  @author GLG, MHPCC
+ *  @author EAM, IfA: significant modifications.
+ *
+ *  @version $Revision: 1.20.16.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-20 23:08:22 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+#include "pmPeaks.h"
+
+/******************************************************************************
+AddPeak(): A private function which allocates a psArray, if the peaks
+argument is NULL, otherwise it adds the peak to that array.
+XXX EAM : row,col now refer to image coords, NOT parent (since this is private) 
+XXX EAM : now also calculates fractional peak positions from 3x3 bicube region
+*****************************************************************************/
+static psArray *AddPeak(psArray *peaks,
+                        const psImage *image,
+                        psS32 row,
+                        psS32 col,
+                        pmPeakType type)
+{
+    psTrace("psModules.objects", 5, "---- begin ----\n");
+
+    if (peaks == NULL) {
+        peaks = psArrayAllocEmpty(100);
+    }
+
+    // the peak position is in parent coordinates
+    pmPeak *peak = pmPeakAlloc(col + image->col0, row + image->row0, image->data.F32[row][col], type);
+
+    // measure fractional peak position using the 3x3 bicube fit
+
+    // ix,iy must land on image with 1 pixel border
+    int ix = PS_MAX (PS_MIN (col, image->numCols - 2), 1);
+    int iy = PS_MAX (PS_MIN (row, image->numRows - 2), 1);
+
+    // calculate peak position relative to ix,iy
+    // XXX these functions need to take a mask, weight, and calculate the errors
+    psPolynomial2D *bicube = psImageBicubeFit (image, ix + image->col0, iy + image->row0);
+    psPlane min = psImageBicubeMin (bicube);
+    psFree (bicube);
+
+    // if min point is too deviant, use the peak value
+    if ((fabs(min.x) < 1.5) && (fabs(min.y) < 1.5)) {
+        peak->xf = min.x + ix + image->col0;
+        peak->yf = min.y + iy + image->row0;
+	peak->dx = 0.0;
+	peak->dy = 0.0;
+    } else {
+        peak->xf = ix;
+        peak->yf = iy;
+	peak->dx = 1.0;
+	peak->dy = 1.0;
+    }
+
+    psArrayAdd(peaks, 100, peak);
+    psFree (peak);
+
+    psTrace("psModules.objects", 5, "---- end ----\n");
+    return(peaks);
+}
+
+/******************************************************************************
+getRowVectorFromImage(): a private function which simply returns a
+psVector containing the specified row of data from the psImage.
+ 
+XXX: Is there a better way to do this?
+XXX EAM: does this really need to alloc a new vector???
+*****************************************************************************/
+static psVector *getRowVectorFromImage(psImage *image,
+                                       psU32 row)
+{
+    psTrace("psModules.objects", 4, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_IMAGE_NON_NULL(image, NULL);
+    PS_ASSERT_IMAGE_TYPE(image, PS_TYPE_F32, NULL);
+
+    psVector *tmpVector = psVectorAlloc(image->numCols, PS_TYPE_F32);
+    for (psU32 col = 0; col < image->numCols ; col++) {
+        tmpVector->data.F32[col] = image->data.F32[row][col];
+    }
+    psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+    return(tmpVector);
+}
+
+/******************************************************************************
+isItInThisRegion(): a private function which simply returns a
+boolean denoting if specified coordinate is in the region.
+XXX: Macro this.
+*****************************************************************************/
+static bool isItInThisRegion(const psRegion valid,
+                             psS32 x,
+                             psS32 y)
+{
+    psTrace("psModules.objects", 4, "---- %s() begin ----\n", __func__);
+    if ((x >= valid.x0) &&
+            (x <= valid.x1) &&
+            (y >= valid.y0) &&
+            (y <= valid.y1)) {
+        psTrace("psModules.objects", 4, "---- %s(true) end ----\n", __func__);
+        return(true);
+    }
+    psTrace("psModules.objects", 4, "---- %s(false) end ----\n", __func__);
+    return(false);
+}
+
+/******************************************************************************
+pmPeakAlloc(): Allocate the pmPeak data structure and set appropriate members.
+*****************************************************************************/
+static void peakFree(pmPeak *tmp)
+{} //
+
+pmPeak *pmPeakAlloc(psS32 x,
+                    psS32 y,
+                    psF32 value,
+                    pmPeakType type)
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    static int id = 1;
+    pmPeak *tmp = (pmPeak *) psAlloc(sizeof(pmPeak));
+    *(int *)&tmp->id = id++;
+    tmp->x = x;
+    tmp->y = y;
+    tmp->value = value;
+    tmp->flux = 0;
+    tmp->SN = 0;
+    tmp->xf = x;
+    tmp->yf = y;
+    tmp->assigned = false;
+    tmp->type = type;
+    tmp->footprint = NULL;
+
+    psMemSetDeallocator(tmp, (psFreeFunc) peakFree);
+
+    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    return(tmp);
+}
+
+bool psMemCheckPeak(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) peakFree);
+}
+
+
+// psSort comparison function for peaks
+// XXX: Add error-checking for NULL args
+int pmPeaksCompareAscend (const void **a, const void **b)
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    pmPeak *A = *(pmPeak **)a;
+    pmPeak *B = *(pmPeak **)b;
+
+    psF32 diff;
+
+    diff = A->value - B->value;
+    if (diff < FLT_EPSILON) {
+        psTrace("psModules.objects", 3, "---- %s(-1) end ----\n", __func__);
+        return (-1);
+    } else if (diff > FLT_EPSILON) {
+        psTrace("psModules.objects", 3, "---- %s(+1) end ----\n", __func__);
+        return (+1);
+    }
+    psTrace("psModules.objects", 3, "---- %s(0) end ----\n", __func__);
+    return (0);
+}
+
+// psSort comparison function for peaks
+// XXX: Add error-checking for NULL args
+int pmPeaksCompareDescend (const void **a, const void **b)
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    pmPeak *A = *(pmPeak **)a;
+    pmPeak *B = *(pmPeak **)b;
+
+    psF32 diff;
+
+    diff = A->value - B->value;
+    if (diff < FLT_EPSILON) {
+        psTrace("psModules.objects", 3, "---- %s(+1) end ----\n", __func__);
+        return (+1);
+    } else if (diff > FLT_EPSILON) {
+        psTrace("psModules.objects", 3, "---- %s(-1) end ----\n", __func__);
+        return (-1);
+    }
+    psTrace("psModules.objects", 3, "---- %s(0) end ----\n", __func__);
+    return (0);
+}
+
+// sort by SN (descending)
+int pmPeakSortBySN (const void **a, const void **b)
+{
+    pmPeak *A = *(pmPeak **)a;
+    pmPeak *B = *(pmPeak **)b;
+
+    psF32 fA = A->SN;
+    psF32 fB = B->SN;
+    if (isnan (fA)) fA = 0;
+    if (isnan (fB)) fB = 0;
+
+    psF32 diff = fA - fB;
+    if (diff > FLT_EPSILON) return (-1);
+    if (diff < FLT_EPSILON) return (+1);
+    return (0);
+}
+
+// sort by Y (ascending)
+int pmPeakSortByY (const void **a, const void **b)
+{
+    pmPeak *A = *(pmPeak **)a;
+    pmPeak *B = *(pmPeak **)b;
+
+    psF32 fA = A->y;
+    psF32 fB = B->y;
+
+    psF32 diff = fA - fB;
+    if (diff > FLT_EPSILON) return (+1);
+    if (diff < FLT_EPSILON) return (-1);
+    return (0);
+}
+
+/******************************************************************************
+pmPeaksInVector(vector, threshold): Find all local peaks in the given vector
+above the given threshold.  Returns a vector of type PS_TYPE_U32 containing
+the location (x value) of all peaks.
+ 
+XXX: What types should be supported?  Only F32 is implemented.
+ 
+XXX: We currently step through the input vector twice; once to determine the
+size of the output vector, then to set the values of the output vector.
+Depending upon actual use, this may need to be optimized.
+*****************************************************************************/
+psVector *pmPeaksInVector(const psVector *vector,
+			 psF32 threshold)
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_VECTOR_NON_NULL(vector, NULL);
+    PS_ASSERT_VECTOR_NON_EMPTY(vector, NULL);
+    PS_ASSERT_VECTOR_TYPE(vector, PS_TYPE_F32, NULL);
+    int count = 0;
+    int n = vector->n;
+
+    //
+    // Special case: the input vector has a single element.
+    //
+    if (n == 1) {
+        psVector *tmpVector = NULL;
+        if (vector->data.F32[0] > threshold) {
+            tmpVector = psVectorAlloc(1, PS_TYPE_U32);
+            tmpVector->data.U32[0] = 0;
+        } else {
+            tmpVector = psVectorAlloc(0, PS_TYPE_U32);
+        }
+        psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+        return(tmpVector);
+    }
+
+    //
+    // Determine if first pixel is a peak
+    //
+    if ((vector->data.F32[0] > vector->data.F32[1]) &&
+            (vector->data.F32[0] > threshold)) {
+        count++;
+    }
+
+    //
+    // Determine if interior pixels are peaks
+    //
+    for (psU32 i = 1; i < n-1 ; i++) {
+        if ((vector->data.F32[i] > vector->data.F32[i-1]) &&
+                (vector->data.F32[i] >= vector->data.F32[i+1]) &&
+                (vector->data.F32[i] > threshold)) {
+            count++;
+        }
+    }
+
+    //
+    // Determine if last pixel is a peak
+    //
+    if ((vector->data.F32[n-1] > vector->data.F32[n-2]) &&
+            (vector->data.F32[n-1] > threshold)) {
+        count++;
+    }
+
+    //
+    // We know how many peaks exist, so we now allocate a psVector to store
+    // those peaks.
+    //
+    psVector *tmpVector = psVectorAlloc(count, PS_TYPE_U32);
+    count = 0;
+
+    //
+    // Determine if first pixel is a peak
+    //
+    if ((vector->data.F32[0] > vector->data.F32[1]) &&
+            (vector->data.F32[0] > threshold)) {
+        tmpVector->data.U32[count++] = 0;
+    }
+
+    //
+    // Determine if interior pixels are peaks
+    //
+    for (psU32 i = 1; i < (n-1) ; i++) {
+        if ((vector->data.F32[i] > vector->data.F32[i-1]) &&
+                (vector->data.F32[i] >= vector->data.F32[i+1]) &&
+                (vector->data.F32[i] > threshold)) {
+            tmpVector->data.U32[count++] = i;
+        }
+    }
+
+    //
+    // Determine if last pixel is a peak
+    //
+    if ((vector->data.F32[n-1] > vector->data.F32[n-2]) &&
+            (vector->data.F32[n-1] > threshold)) {
+        tmpVector->data.U32[count++] = n-1;
+    }
+
+    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    return(tmpVector);
+}
+
+
+/******************************************************************************
+pmPeaksInImage(image, threshold): Find all local peaks in the given psImage
+above the given threshold.  Returns a psArray containing location (x/y value)
+of all peaks.
+ 
+XXX: I'm not convinced the peak type definition in the SDRS is mutually
+exclusive.  Some peaks can have multiple types.  Edges for sure.  Also, a
+digonal line with the same value at each point will have a peak for every
+point on that line.
+ 
+XXX: This does not work if image has either a single row, or a single column.
+ 
+The peak is returned in the image parent coordinates
+
+*****************************************************************************/
+psArray *pmPeaksInImage(const psImage *image, psF32 threshold)
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_IMAGE_NON_NULL(image, NULL);
+    PS_ASSERT_IMAGE_TYPE(image, PS_TYPE_F32, NULL);
+    if ((image->numRows == 1) || (image->numCols == 1)) {
+        psError(PS_ERR_UNKNOWN, true, "Currently, input image must have at least 2 rows and 2 columns.");
+        psTrace("psModules.objects", 3, "---- %s(NULL) end ----\n", __func__);
+        return(NULL);
+    }
+    psVector *tmpRow = NULL;
+    psU32 col = 0;
+    psU32 row = 0;
+    psArray *list = NULL;
+
+    // Find peaks in row 0 only.
+    row = 0;
+    tmpRow = getRowVectorFromImage((psImage *) image, row);
+    psVector *row1 = pmPeaksInVector(tmpRow, threshold);
+    // pmPeaksInVector returns coords in the vector, not corrected for col0
+
+    for (psU32 i = 0 ; i < row1->n ; i++ ) {
+        col = row1->data.U32[i];
+        // is pixel (0,0) is a peak?
+        if (col == 0) {
+            if ( (image->data.F32[row][col] >  image->data.F32[row][col+1]) &&
+                    (image->data.F32[row][col] >  image->data.F32[row+1][col]) &&
+                    (image->data.F32[row][col] >= image->data.F32[row+1][col+1])) {
+
+                if (image->data.F32[row][col] > threshold) {
+                    list = AddPeak(list, image, row, col, PM_PEAK_EDGE);
+                }
+            }
+        } else if (col < (image->numCols - 1)) {
+            if ( (image->data.F32[row][col] >= image->data.F32[row][col-1]) &&
+                    (image->data.F32[row][col] >  image->data.F32[row][col+1]) &&
+                    (image->data.F32[row][col] >= image->data.F32[row+1][col-1]) &&
+                    (image->data.F32[row][col] >  image->data.F32[row+1][col]) &&
+                    (image->data.F32[row][col] >= image->data.F32[row+1][col+1])) {
+                if (image->data.F32[row][col] > threshold) {
+                    list = AddPeak(list, image, row, col, PM_PEAK_EDGE);
+                }
+            }
+
+        } else if (col == (image->numCols - 1)) {
+            if ( (image->data.F32[row][col] >= image->data.F32[row][col-1]) &&
+                    (image->data.F32[row][col] > image->data.F32[row+1][col]) &&
+                    (image->data.F32[row][col] >= image->data.F32[row+1][col-1])) {
+                if (image->data.F32[row][col] > threshold) {
+                    list = AddPeak(list, image, row, col, PM_PEAK_EDGE);
+                }
+            }
+
+        } else {
+            psError(PS_ERR_UNKNOWN, true, "peak specified valid column range.");
+        }
+    }
+    psFree (tmpRow);
+    psFree (row1);
+
+    //
+    // Exit if this image has a single row.
+    //
+    if (image->numRows == 1) {
+        psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+        return(list);
+    }
+
+    //
+    // Find peaks in interior rows only.
+    //
+    for (row = 1 ; row < (image->numRows - 1) ; row++) {
+        tmpRow = getRowVectorFromImage((psImage *) image, row);
+        row1 = pmPeaksInVector(tmpRow, threshold);
+
+        // Step through all local peaks in this row.
+        for (psU32 i = 0 ; i < row1->n ; i++ ) {
+            pmPeakType myType = PM_PEAK_UNDEF;
+            col = row1->data.U32[i];
+
+            if (col == 0) {
+                // If col==0, then we can not read col-1 pixels
+                if ((image->data.F32[row][col] >  image->data.F32[row-1][col]) &&
+                        (image->data.F32[row][col] >= image->data.F32[row-1][col+1]) &&
+                        (image->data.F32[row][col] >= image->data.F32[row][col+1]) &&
+                        (image->data.F32[row][col] >= image->data.F32[row+1][col]) &&
+                        (image->data.F32[row][col] >= image->data.F32[row+1][col+1])) {
+                    myType = PM_PEAK_EDGE;
+                    list = AddPeak(list, image, row, col, myType);
+                }
+            } else if (col < (image->numCols - 1)) {
+                // This is an interior pixel
+                if ((image->data.F32[row][col] >= image->data.F32[row-1][col-1]) &&
+                        (image->data.F32[row][col] >  image->data.F32[row-1][col]) &&
+                        (image->data.F32[row][col] >= image->data.F32[row-1][col+1]) &&
+                        (image->data.F32[row][col] > image->data.F32[row][col-1]) &&
+                        (image->data.F32[row][col] >= image->data.F32[row][col+1]) &&
+                        (image->data.F32[row][col] >= image->data.F32[row+1][col-1]) &&
+                        (image->data.F32[row][col] >= image->data.F32[row+1][col]) &&
+                        (image->data.F32[row][col] >= image->data.F32[row+1][col+1])) {
+                    if (image->data.F32[row][col] > threshold) {
+                        if ((image->data.F32[row][col] > image->data.F32[row-1][col-1]) &&
+                                (image->data.F32[row][col] > image->data.F32[row-1][col]) &&
+                                (image->data.F32[row][col] > image->data.F32[row-1][col+1]) &&
+                                (image->data.F32[row][col] > image->data.F32[row][col-1]) &&
+                                (image->data.F32[row][col] > image->data.F32[row][col+1]) &&
+                                (image->data.F32[row][col] > image->data.F32[row+1][col-1]) &&
+                                (image->data.F32[row][col] > image->data.F32[row+1][col]) &&
+                                (image->data.F32[row][col] > image->data.F32[row+1][col+1])) {
+                            myType = PM_PEAK_LONE;
+                        }
+
+                        if ((image->data.F32[row][col] == image->data.F32[row-1][col-1]) ||
+                                (image->data.F32[row][col] == image->data.F32[row-1][col]) ||
+                                (image->data.F32[row][col] == image->data.F32[row-1][col+1]) ||
+                                (image->data.F32[row][col] == image->data.F32[row][col-1]) ||
+                                (image->data.F32[row][col] == image->data.F32[row][col+1]) ||
+                                (image->data.F32[row][col] == image->data.F32[row+1][col-1]) ||
+                                (image->data.F32[row][col] == image->data.F32[row+1][col]) ||
+                                (image->data.F32[row][col] == image->data.F32[row+1][col+1])) {
+                            myType = PM_PEAK_FLAT;
+                        }
+
+                        list = AddPeak(list, image, row, col, myType);
+
+                    }
+                }
+            } else if (col == (image->numCols - 1)) {
+                // If col==numCols - 1, then we can not read col+1 pixels
+                if ((image->data.F32[row][col] >= image->data.F32[row-1][col-1]) &&
+                        (image->data.F32[row][col] >  image->data.F32[row-1][col]) &&
+                        (image->data.F32[row][col] > image->data.F32[row][col-1]) &&
+                        (image->data.F32[row][col] >= image->data.F32[row][col+1]) &&
+                        (image->data.F32[row][col] >= image->data.F32[row+1][col-1]) &&
+                        (image->data.F32[row][col] >= image->data.F32[row+1][col])) {
+                    myType = PM_PEAK_EDGE;
+                    list = AddPeak(list, image, row, col, myType);
+                }
+            } else {
+                psError(PS_ERR_UNKNOWN, true, "peak specified outside valid column range.");
+            }
+
+        }
+        psFree (tmpRow);
+        psFree (row1);
+    }
+
+    //
+    // Find peaks in the last row only.
+    //
+    row = image->numRows - 1;
+    tmpRow = getRowVectorFromImage((psImage *) image, row);
+    row1 = pmPeaksInVector(tmpRow, threshold);
+    for (psU32 i = 0 ; i < row1->n ; i++ ) {
+        col = row1->data.U32[i];
+        if (col == 0) {
+            if ( (image->data.F32[row][col] >  image->data.F32[row-1][col]) &&
+                    (image->data.F32[row][col] >= image->data.F32[row-1][col+1]) &&
+                    (image->data.F32[row][col] >  image->data.F32[row][col+1])) {
+                if (image->data.F32[row][col] > threshold) {
+                    list = AddPeak(list, image, row, col, PM_PEAK_EDGE);
+                }
+            }
+        } else if (col < (image->numCols - 1)) {
+            if ( (image->data.F32[row][col] >= image->data.F32[row-1][col-1]) &&
+                    (image->data.F32[row][col] >  image->data.F32[row-1][col]) &&
+                    (image->data.F32[row][col] >= image->data.F32[row-1][col+1]) &&
+                    (image->data.F32[row][col] >  image->data.F32[row][col-1]) &&
+                    (image->data.F32[row][col] >= image->data.F32[row][col+1])) {
+                if (image->data.F32[row][col] > threshold) {
+                    list = AddPeak(list, image, row, col, PM_PEAK_EDGE);
+                }
+            }
+
+        } else if (col == (image->numCols - 1)) {
+            if ( (image->data.F32[row][col] >= image->data.F32[row-1][col-1]) &&
+                    (image->data.F32[row][col] >  image->data.F32[row-1][col]) &&
+                    (image->data.F32[row][col] >  image->data.F32[row][col-1])) {
+                if (image->data.F32[row][col] > threshold) {
+                    list = AddPeak(list, image, row, col, PM_PEAK_EDGE);
+                }
+            }
+        } else {
+            psError(PS_ERR_UNKNOWN, true, "peak specified outside valid column range.");
+        }
+    }
+    psFree (tmpRow);
+    psFree (row1);
+    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    return(list);
+}
+
+// return a new array of peaks which are in the valid region and below threshold
+// XXX this function is unused and probably could be dropped
+psArray *pmPeaksSubset(
+    psArray *peaks,
+    psF32 maxValue,
+    const psRegion valid)
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_PTR_NON_NULL(peaks, NULL);
+
+    psArray *output = psArrayAllocEmpty (200);
+
+    psTrace ("psModules.objects", 3, "list size is %ld\n", peaks->n);
+
+    for (int i = 0; i < peaks->n; i++) {
+        pmPeak *tmpPeak = (pmPeak *) peaks->data[i];
+        if (tmpPeak->value > maxValue)
+            continue;
+        if (isItInThisRegion(valid, tmpPeak->x, tmpPeak->y))
+            continue;
+        psArrayAdd (output, 200, tmpPeak);
+    }
+    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    return(output);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPeaks.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPeaks.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmPeaks.h	(revision 22158)
@@ -0,0 +1,145 @@
+/* @file  pmPeaks.h
+ *
+ * The process of finding, measuring, and classifying astronomical sources on
+ * images is one of the critical tasks of the IPP or any astronomical software
+ * system. This file will define structures and functions related to the task
+ * of source detection and measurement. The elements defined in this section
+ * are generally low-level components which can be connected together to
+ * construct a complete object measurement suite.
+ *
+ * @author GLG, MHPCC
+ *
+ * @version $Revision: 1.11.16.1 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-20 23:08:22 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+# ifndef PM_PEAKS_H
+# define PM_PEAKS_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+/** pmPeakType
+ *
+ *  A peak pixel may have several features which may be determined when the
+ *  peak is found or measured. These are specified by the pmPeakType enum.
+ *  PM_PEAK_LONE represents a single pixel which is higher than its 8 immediate
+ *  neighbors.  The PM_PEAK_EDGE represents a peak pixel which touching the image
+ *  edge. The PM_PEAK_FLAT represents a peak pixel which has more than a specific
+ *  number of neighbors at the same value, within some tolarence:
+ *
+ */
+typedef enum {
+    PM_PEAK_LONE,                       ///< Isolated peak.
+    PM_PEAK_EDGE,                       ///< Peak on edge.
+    PM_PEAK_FLAT,                       ///< Peak has equal-value neighbors.
+    PM_PEAK_UNDEF                       ///< Undefined.
+} pmPeakType;
+
+
+/** pmPeak data structure
+ *
+ *  A source has the capacity for several types of measurements. The
+ *  simplest measurement of a source is the location and flux of the peak pixel
+ *  associated with the source:
+ *
+ */
+typedef struct
+{
+    const int id;   ///< Unique ID for object
+    int x;                              ///< X-coordinate of peak pixel.
+    int y;                              ///< Y-coordinate of peak pixel.
+    float xf;                           ///< bicube fit to peak coord (x)
+    float yf;                           ///< bicube fit to peak coord (y)
+    float dx;                           ///< bicube fit error on peak coord (x)
+    float dy;                           ///< bicube fit error on peak coord (y)
+    float value;                        ///< level in detection image
+    float flux;                         ///< level in unsmoothed sci image
+    float SN;                           ///< S/N implied by detection level
+    bool assigned;                      ///< is peak assigned to a source?
+    pmPeakType type;			///< Description of peak.
+    struct pmFootprint *footprint;	///< reference to containing footprint
+}
+pmPeak;
+
+
+/** pmPeakAlloc()
+ *
+ *  @return pmPeak*    newly allocated pmPeak with all internal pointers set to NULL
+ */
+pmPeak *pmPeakAlloc(
+    int x,    ///< Row-coordinate in image space
+    int y,    ///< Col-coordinate in image space
+    float counts,   ///< The value of the peak pixel
+    pmPeakType type   ///< The type of peak pixel
+);
+
+bool psMemCheckPeak(psPtr ptr);
+
+/** pmPeaksInVector()
+ *
+ * Find all local peaks in the given vector above the given threshold. A peak
+ * is defined as any element with a value greater than its two neighbors and with
+ * a value above the threshold. Two types of special cases must be addressed.
+ * Equal value elements: If an element has the same value as the following
+ * element, it is not considered a peak. If an element has the same value as the
+ * preceding element (but not the following), then it is considered a peak. Note
+ * that this rule (arbitrarily) identifies flat regions by their trailing edge.
+ * Edge cases: At start of the vector, the element must be higher than its
+ * neighbor. At the end of the vector, the element must be higher or equal to its
+ * neighbor. These two rules again places the peak associated with a flat region
+ * which touches the image edge at the image edge. The result of this function is
+ * a vector containing the coordinates (element number) of the detected peaks
+ * (type psU32).
+ *
+ */
+psVector *pmPeaksInVector(
+    const psVector *vector,  ///< The input vector (float)
+    float threshold   ///< Threshold above which to find a peak
+);
+
+
+/** pmPeaksInImage()
+ *
+ * Find all local peaks in the given image above the given threshold. This
+ * function should find all row peaks using pmFindVectorPeaks, then test each row
+ * peak and exclude peaks which are not local peaks. A peak is a local peak if it
+ * has a higher value than all 8 neighbors. If the peak has the same value as its
+ * +y neighbor or +x neighbor, it is NOT a local peak. If any other neighbors
+ * have an equal value, the peak is considered a valid peak. Note two points:
+ * first, the +x neighbor condition is already enforced by pmFindVectorPeaks.
+ * Second, these rules have the effect of making flat-topped regions have single
+ * peaks at the (+x,+y) corner. When selecting the peaks, their type must also be
+ * set. The result of this function is an array of pmPeak entries.
+ *
+ */
+psArray *pmPeaksInImage(
+    const psImage *image,  ///< The input image where peaks will be found (float)
+    float threshold   ///< Threshold above which to find a peak
+);
+
+
+/** pmPeaksSubset()
+ *
+ * Create a new peaks array, removing certain types of peaks from the input
+ * array of peaks based on the given criteria. Peaks should be eliminated if they
+ * have a peak value above the given maximum value limit or if the fall outside
+ * the valid region.  The result of the function is a new array with a reduced
+ * number of peaks.
+ *
+ */
+psArray *pmPeaksSubset(
+    psArray *peaks,                     ///< Add comment.
+    float maxvalue,                     ///< Add comment.
+    const psRegion valid                ///< Add comment.
+);
+
+int pmPeaksCompareAscend (const void **a, const void **b);
+int pmPeaksCompareDescend (const void **a, const void **b);
+
+int pmPeakSortBySN (const void **a, const void **b);
+int pmPeakSortByY (const void **a, const void **b);
+
+/// @}
+# endif /* PM_PEAKS_H */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmResiduals.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmResiduals.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmResiduals.c	(revision 22158)
@@ -0,0 +1,59 @@
+/** @file pmResiduals.c
+ *
+ * Functions to manipulate the residual tables (data - model).
+ *
+ * @author EAM, IfA
+ * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
+ * Copyright 2004 IfA, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pslib.h>
+#include "pmResiduals.h"
+
+static void pmResidualsFree (pmResiduals *resid) {
+
+    if (resid == NULL) return;
+
+    psFree (resid->Ro);
+    psFree (resid->Rx);
+    psFree (resid->Ry);
+    psFree (resid->weight);
+    psFree (resid->mask);
+    return;
+}
+
+pmResiduals *pmResidualsAlloc (int xSize, int ySize, int xBin, int yBin) {
+
+    pmResiduals *resid = (pmResiduals *) psAlloc(sizeof(pmResiduals));
+    psMemSetDeallocator(resid, (psFreeFunc) pmResidualsFree);
+
+    int nX = xSize * xBin;
+    int nY = ySize * yBin;
+
+    nX = (nX % 2) ? nX : nX + 1;
+    nY = (nY % 2) ? nY : nY + 1;
+
+    resid->Ro  = psImageAlloc (nX, nY, PS_TYPE_F32);
+    resid->Rx  = psImageAlloc (nX, nY, PS_TYPE_F32);
+    resid->Ry  = psImageAlloc (nX, nY, PS_TYPE_F32);
+    resid->weight = psImageAlloc (nX, nY, PS_TYPE_F32);
+    resid->mask   = psImageAlloc (nX, nY, PS_TYPE_U8);
+
+    resid->xBin = xBin;
+    resid->yBin = yBin;
+    resid->xCenter = 0.5*(nX - 1); 
+    resid->yCenter = 0.5*(nY - 1);
+    return resid;
+}
+
+bool psMemCheckResiduals(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmResidualsFree);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmResiduals.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmResiduals.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmResiduals.h	(revision 22158)
@@ -0,0 +1,34 @@
+/** @file pmResiduals.h
+ *
+ * Functions to manipulate the residual tables (data - model).
+ *
+ * @author EAM, IfA
+ * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
+ * Copyright 2004 IfA, University of Hawaii
+ */
+
+# ifndef PM_RESIDUALS_H
+# define PM_RESIDUALS_H
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+/** residual tables for sources 
+ */
+typedef struct {
+    psImage *Ro;
+    psImage *Rx;
+    psImage *Ry;
+    psImage *weight;
+    psImage *mask;
+    int xBin;
+    int yBin;
+    int xCenter;
+    int yCenter;
+} pmResiduals;
+
+pmResiduals *pmResidualsAlloc (int xSize, int ySize, int xBin, int yBin);
+bool psMemCheckResiduals(psPtr ptr);
+
+/// @}
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSource.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSource.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSource.c	(revision 22158)
@@ -0,0 +1,1047 @@
+/** @file  pmSource.c
+ *
+ *  Functions to define and manipulate sources on images
+ *
+ *  @author GLG, MHPCC
+ *  @author EAM, IfA: significant modifications.
+ *
+ *  @version $Revision: 1.55 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-15 20:25:00 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <strings.h>
+#include <pslib.h>
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPAMaskWeight.h"
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmResiduals.h"
+#include "pmGrowthCurve.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+
+static void sourceFree(pmSource *tmp)
+{
+    if (!tmp)
+        return;
+
+    psTrace("psModules.objects", 5, "---- begin ----\n");
+    psFree(tmp->peak);
+    psFree(tmp->pixels);
+    psFree(tmp->weight);
+    psFree(tmp->maskObj);
+    psFree(tmp->maskView);
+    psFree(tmp->modelFlux);
+    psFree(tmp->psfFlux);
+    psFree(tmp->moments);
+    psFree(tmp->modelPSF);
+    psFree(tmp->modelEXT);
+    psFree(tmp->modelFits);
+    psFree(tmp->extpars);
+    psFree(tmp->blends);
+    psTrace("psModules.objects", 5, "---- end ----\n");
+}
+
+// free only the pixel data associated with this source
+void pmSourceFreePixels(pmSource *source)
+{
+
+    if (!source)
+        return;
+
+    psFree (source->pixels);
+    psFree (source->weight);
+    psFree (source->maskObj);
+    psFree (source->maskView);
+    psFree (source->modelFlux);
+    psFree (source->psfFlux);
+
+    source->pixels = NULL;
+    source->weight = NULL;
+    source->maskObj = NULL;
+    source->maskView = NULL;
+    source->modelFlux = NULL;
+    source->psfFlux = NULL;
+    return;
+}
+
+bool psMemCheckSource(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) sourceFree);
+}
+
+/******************************************************************************
+pmSourceAlloc(): Allocate the pmSource structure and initialize its members
+to NULL.
+*****************************************************************************/
+
+pmSource *pmSourceAlloc()
+{
+    psTrace("psModules.objects", 5, "---- begin ----\n");
+    static int id = 1;
+    pmSource *source = (pmSource *) psAlloc(sizeof(pmSource));
+    *(int *)&source->id = id++;
+    source->seq = -1;
+    source->peak = NULL;
+    source->pixels = NULL;
+    source->weight = NULL;
+    source->maskObj = NULL;
+    source->maskView = NULL;
+    source->modelFlux = NULL;
+    source->psfFlux = NULL;
+    source->moments = NULL;
+    source->blends = NULL;
+    source->modelPSF = NULL;
+    source->modelEXT = NULL;
+    source->modelFits = NULL;
+    source->type = PM_SOURCE_TYPE_UNKNOWN;
+    source->mode = PM_SOURCE_MODE_DEFAULT;
+    source->extpars = NULL;
+    source->region = psRegionSet(NAN, NAN, NAN, NAN);
+    psMemSetDeallocator(source, (psFreeFunc) sourceFree);
+
+    // default values are NAN
+    source->psfMag = NAN;
+    source->extMag = NAN;
+    source->errMag = NAN;
+    source->apMag  = NAN;
+    source->sky    = NAN;
+    source->skyErr = NAN;
+    source->pixWeight = NAN;
+
+    source->psfChisq = NAN;
+    source->crNsigma = NAN;
+    source->extNsigma = NAN;
+
+    psTrace("psModules.objects", 5, "---- end ----\n");
+    return(source);
+}
+
+/******************************************************************************
+pmSourceCopy(): copy the pmSource structure and contents
+XXX : are we OK with incrementing the ID?
+*****************************************************************************/
+pmSource *pmSourceCopy(pmSource *in)
+{
+    if (in == NULL) {
+        return(NULL);
+    }
+    // this copy is used to allow multiple fit attempts on the
+    // same object.  the pixels, weight, and mask arrays all point to
+    // the same original subarrays.  the peak and moments point at
+    // the original values.
+    pmSource *source = pmSourceAlloc ();
+
+    // this is actually the same peak as the original, is this the correct way to handle this?
+    if (in->peak != NULL) {
+        source->peak = pmPeakAlloc (in->peak->x, in->peak->y, in->peak->value, in->peak->type);
+        source->peak->xf = in->peak->xf;
+        source->peak->yf = in->peak->yf;
+        source->peak->flux = in->peak->flux;
+        source->peak->SN = in->peak->SN;
+    }
+
+    // copy the values in the moments structure
+    if (in->moments != NULL) {
+        source->moments  =  pmMomentsAlloc();
+        *source->moments = *in->moments;
+    }
+
+    // These images are all views to the parent.
+    // We want a new view, but pointing at the same pixels.
+    source->pixels   = psImageCopyView(NULL, in->pixels);
+    source->weight   = psImageCopyView(NULL, in->weight);
+    source->maskView = in->maskView ? psImageCopyView(NULL, in->maskView) : NULL;
+
+    // the maskObj is a unique mask array; create a new mask image
+    source->maskObj = in->maskObj ? psImageCopy (NULL, in->maskObj, PS_TYPE_MASK) : NULL;
+
+    source->type = in->type;
+    source->mode = in->mode;
+
+    return(source);
+}
+
+// x,y are defined in the parent image coords of readout->image
+bool pmSourceDefinePixels(pmSource *mySource,
+                          const pmReadout *readout,
+                          psF32 x,
+                          psF32 y,
+                          psF32 Radius)
+{
+    PS_ASSERT_PTR_NON_NULL(mySource, false);
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_PTR_NON_NULL(readout->image, false);
+    PS_ASSERT_INT_POSITIVE(Radius, false);
+
+    psRegion srcRegion;
+
+    // Grab a subimage of the original image of size (2 * outerRadius).
+    srcRegion = psRegionForSquare (x, y, Radius);
+    srcRegion = psRegionForImage (readout->image, srcRegion);
+
+    // these images are subset images of the equivalent parents
+    mySource->pixels = psImageSubset(readout->image, srcRegion);
+    if (readout->weight) {
+        mySource->weight = psImageSubset(readout->weight, srcRegion);
+    }
+    if (readout->mask) {
+        mySource->maskView = psImageSubset(readout->mask,  srcRegion);
+        // the object mask is a copy, and used to define the source pixels
+        mySource->maskObj = psImageCopy(NULL, mySource->maskView, PS_TYPE_MASK);
+    }
+    mySource->region   = srcRegion;
+
+    return true;
+}
+
+bool pmSourceRedefinePixels(pmSource *mySource,
+                            const pmReadout *readout,
+                            psF32 x,
+                            psF32 y,
+                            psF32 Radius)
+{
+    PS_ASSERT_PTR_NON_NULL(mySource, false);
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_PTR_NON_NULL(readout->image, false);
+    PS_ASSERT_INT_POSITIVE(Radius, false);
+
+    bool extend;
+    psRegion newRegion;
+
+    // check to see if new region is completely contained within old region
+    newRegion = psRegionForSquare (x, y, Radius);
+    newRegion = psRegionForImage (readout->image, newRegion);
+
+    extend = false;
+    extend |= (int)(newRegion.x0) < (int)(mySource->region.x0);
+    extend |= (int)(newRegion.x1) > (int)(mySource->region.x1);
+    extend |= (int)(newRegion.y0) < (int)(mySource->region.y0);
+    extend |= (int)(newRegion.y1) > (int)(mySource->region.y1);
+
+    extend |= (mySource->pixels == NULL);
+    extend |= (mySource->weight == NULL);
+    extend |= (mySource->maskObj == NULL);
+    extend |= (mySource->maskView == NULL);
+
+    // extend = true;
+    if (extend) {
+        // re-create the subimage
+        psFree (mySource->pixels);
+        psFree (mySource->weight);
+        psFree (mySource->maskView);
+
+        mySource->pixels   = psImageSubset(readout->image,  newRegion);
+        mySource->weight   = psImageSubset(readout->weight, newRegion);
+        mySource->maskView = psImageSubset(readout->mask,   newRegion);
+        mySource->region   = newRegion;
+
+        // re-copy the main mask pixels.  NOTE: the user will need to reset the object mask
+        // pixels (eg, with psImageKeepCircle)
+        mySource->maskObj = psImageCopy (mySource->maskObj, mySource->maskView, PS_TYPE_MASK);
+
+        // drop the old modelFlux pixels and force the user to re-create
+        psFree (mySource->modelFlux);
+        mySource->modelFlux = NULL;
+
+        // drop the old psfFlux pixels and force the user to re-create
+        psFree (mySource->psfFlux);
+        mySource->psfFlux = NULL;
+    }
+    return extend;
+}
+
+/******************************************************************************
+    pmSourcePSFClump(source, recipe): Find the likely PSF clump in the
+    sigma-x, sigma-y plane. return 0,0 clump in case of error.
+*****************************************************************************/
+
+// XXX EAM include a S/N cutoff in selecting the sources?
+// XXX this function should probably accept the values, not a recipe. wrap with a
+// psphot-specific function which applies the recipe values
+pmPSFClump pmSourcePSFClump(psArray *sources, psMetadata *recipe)
+{
+    psTrace("psModules.objects", 5, "---- begin ----\n");
+
+    # define NPIX 10
+    # define SCALE 0.1
+
+    psArray *peaks  = NULL;
+    pmPSFClump errorClump = {-1.0, -1.0, 0.0, 0.0};
+    pmPSFClump emptyClump = {+0.0, +0.0, 0.0, 0.0};
+    pmPSFClump psfClump;
+
+    PS_ASSERT_PTR_NON_NULL(sources, errorClump);
+    PS_ASSERT_PTR_NON_NULL(recipe, errorClump);
+
+    bool status = true;
+    float PSF_CLUMP_SN_LIM = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_SN_LIM");
+    if (!status) {
+        PSF_CLUMP_SN_LIM = 0;
+    }
+
+    // find the sigmaX, sigmaY clump
+    {
+        psStats *stats  = NULL;
+        psImage *splane = NULL;
+        int binX, binY;
+        bool status;
+
+        psF32 SX_MAX = psMetadataLookupF32 (&status, recipe, "MOMENTS_SX_MAX");
+        if (!status)
+            SX_MAX = 10.0;
+        psF32 SY_MAX = psMetadataLookupF32 (&status, recipe, "MOMENTS_SY_MAX");
+        if (!status)
+            SY_MAX = 10.0;
+        psF32 AR_MAX = psMetadataLookupF32 (&status, recipe, "MOMENTS_AR_MAX");
+        if (!status)
+            AR_MAX =  3.0;
+        psF32 AR_MIN = 1.0 / AR_MAX;
+
+        // construct a sigma-plane image
+        splane = psImageAlloc (SX_MAX/SCALE, SY_MAX/SCALE, PS_TYPE_F32);
+        psImageInit(splane, 0);  // psImageAlloc doesn't zero the data
+
+        // place the sources in the sigma-plane image (ignore 0,0 values?)
+        int nValid = 0;
+        for (psS32 i = 0 ; i < sources->n ; i++)
+        {
+            pmSource *tmpSrc = (pmSource *) sources->data[i];
+            if (tmpSrc == NULL)
+                continue;
+            if (tmpSrc->moments == NULL)
+                continue;
+            if (tmpSrc->moments->SN < PSF_CLUMP_SN_LIM)
+                continue;
+
+            // Sx,Sy are limited at 0.  a peak at 0,0 is artificial
+            if (fabs(tmpSrc->moments->Sx) < 0.05)
+                continue;
+            if (fabs(tmpSrc->moments->Sy) < 0.05)
+                continue;
+            if ((tmpSrc->moments->Sx / tmpSrc->moments->Sy) > AR_MAX)
+                continue;
+            if ((tmpSrc->moments->Sx / tmpSrc->moments->Sy) < AR_MIN)
+                continue;
+            if (tmpSrc->mode & PM_SOURCE_MODE_BLEND)
+                continue;
+
+            // for the moment, force splane dimensions to be 10x10 image pix
+            binX = tmpSrc->moments->Sx/SCALE;
+            if (binX < 0)
+                continue;
+            if (binX >= splane->numCols)
+                continue;
+
+            binY = tmpSrc->moments->Sy/SCALE;
+            if (binY < 0)
+                continue;
+            if (binY >= splane->numRows)
+                continue;
+
+            splane->data.F32[binY][binX] += 1.0;
+            nValid ++;
+        }
+
+        // find the peak in this image
+        stats = psStatsAlloc (PS_STAT_MAX);
+        if (!psImageStats (stats, splane, NULL, 0)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to get image statistics.\n");
+            psFree(stats);
+            psFree(splane);
+            return emptyClump;
+        }
+        peaks = pmPeaksInImage (splane, stats[0].max / 2);
+        psTrace ("psModules.objects", 2, "clump threshold is %f\n", stats[0].max/2);
+
+        const bool keep_psf_clump = psMetadataLookupBool(NULL, recipe, "KEEP_PSF_CLUMP");
+        if (keep_psf_clump)
+        {
+            psMetadataAdd(recipe, PS_LIST_TAIL,
+                          "PSF_CLUMP", PS_DATA_IMAGE, "Image of PSF coefficients", splane);
+        }
+        psFree (splane);
+        psFree (stats);
+
+        // if we failed to find a valid peak, return the empty clump (failure signal)
+        if (peaks == NULL)
+        {
+            psLogMsg ("psphot", 3, "failed to find a peak in the PSF clump image\n");
+            if (nValid == 0) {
+                psLogMsg ("psphot", 3, "no valid sources kept for PSF search\n");
+            } else {
+                psLogMsg ("psphot", 3, "no significant peak\n");
+            }
+            return (emptyClump);
+        }
+    }
+
+    // measure statistics on Sx, Sy if Sx, Sy within range of clump
+    {
+        pmPeak *clump;
+        psF32 minSx, maxSx;
+        psF32 minSy, maxSy;
+        psVector *tmpSx = NULL;
+        psVector *tmpSy = NULL;
+        psStats *stats  = NULL;
+
+        // select the single highest peak
+        psArraySort (peaks, pmPeaksCompareDescend);
+        clump = peaks->data[0];
+        psTrace ("psModules.objects", 2, "clump is at %d, %d (%f)\n", clump->x, clump->y, clump->value);
+
+        // define section window for clump
+        minSx = clump->x * SCALE - 0.2;
+        maxSx = clump->x * SCALE + 0.2;
+        minSy = clump->y * SCALE - 0.2;
+        maxSy = clump->y * SCALE + 0.2;
+
+        tmpSx = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
+        tmpSy = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
+
+        // create vectors with Sx, Sy values in window
+        // clip sources based on S/N
+        for (psS32 i = 0 ; i < sources->n ; i++)
+        {
+            pmSource *tmpSrc = (pmSource *) sources->data[i];
+
+            if (tmpSrc == NULL)
+                continue;
+            if (tmpSrc->moments == NULL)
+                continue;
+            if (tmpSrc->moments->SN < PSF_CLUMP_SN_LIM)
+                continue;
+
+            if (tmpSrc->moments->Sx < minSx)
+                continue;
+            if (tmpSrc->moments->Sx > maxSx)
+                continue;
+            if (tmpSrc->moments->Sy < minSy)
+                continue;
+            if (tmpSrc->moments->Sy > maxSy)
+                continue;
+            tmpSx->data.F32[tmpSx->n] = tmpSrc->moments->Sx;
+            tmpSy->data.F32[tmpSy->n] = tmpSrc->moments->Sy;
+            tmpSx->n++;
+            tmpSy->n++;
+            if (tmpSx->n == tmpSx->nalloc) {
+                psVectorRealloc (tmpSx, tmpSx->nalloc + 100);
+                psVectorRealloc (tmpSy, tmpSy->nalloc + 100);
+            }
+        }
+
+        // measures stats of Sx, Sy
+        stats = psStatsAlloc (PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV);
+
+        psVectorStats (stats, tmpSx, NULL, NULL, 0);
+        psfClump.X  = stats->clippedMean;
+        psfClump.dX = stats->clippedStdev;
+
+        psVectorStats (stats, tmpSy, NULL, NULL, 0);
+        psfClump.Y  = stats->clippedMean;
+        psfClump.dY = stats->clippedStdev;
+
+        psTrace ("psModules.objects", 2, "clump  X,  Y: %f, %f\n", psfClump.X, psfClump.Y);
+        psTrace ("psModules.objects", 2, "clump DX, DY: %f, %f\n", psfClump.dX, psfClump.dY);
+
+        psFree (stats);
+        psFree (peaks);
+        psFree (tmpSx);
+        psFree (tmpSy);
+    }
+
+    psTrace("psModules.objects", 5, "---- end ----\n");
+    return (psfClump);
+}
+
+/******************************************************************************
+    pmSourceRoughClass(source, recipe): make a guess at the source
+    classification.
+    XXX: How can this function ever return FALSE?
+*****************************************************************************/
+
+bool pmSourceRoughClass(psArray *sources, psMetadata *recipe, pmPSFClump clump, psMaskType maskSat)
+{
+    psTrace("psModules.objects", 5, "---- begin ----");
+
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(recipe, false);
+
+    int Nsat     = 0;
+    int Next     = 0;
+    int Nstar    = 0;
+    int Npsf     = 0;
+    int Ncr      = 0;
+    int Nsatstar = 0;
+    psRegion inner;
+
+    // report stats on S/N values for star-like objects
+    psVector *starsn_peaks = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
+    psVector *starsn_moments = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
+
+    // get basic parameters, or set defaults
+    bool status;
+    float PSF_SN_LIM = psMetadataLookupF32 (&status, recipe, "PSF_SN_LIM");
+    if (!status)
+        PSF_SN_LIM = 20.0;
+    float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_NSIGMA");
+    if (!status)
+        PSF_CLUMP_NSIGMA = 1.5;
+    float INNER_RADIUS = psMetadataLookupF32 (&status, recipe, "SKY_INNER_RADIUS");
+
+    // XXX allow clump size to be scaled relative to sigmas?
+    // make rough IDs based on clumpX,Y,DX,DY
+    for (psS32 i = 0 ; i < sources->n ; i++) {
+
+        pmSource *source = (pmSource *) sources->data[i];
+
+        source->peak->type = 0;
+
+        // we are basically classifying by moments; use the default if not found
+        if (!source->moments) {
+            source->type = PM_SOURCE_TYPE_STAR;
+            Nstar++;
+            continue;
+        }
+
+        psF32 sigX = source->moments->Sx;
+        psF32 sigY = source->moments->Sy;
+
+        // XXX EAM : can we use the value of SATURATE if mask is NULL?
+        inner = psRegionForSquare (source->peak->x, source->peak->y, 2);
+        inner = psRegionForImage (source->maskView, inner);
+        int Nsatpix = psImageCountPixelMask (source->maskView, inner, maskSat);
+
+        // saturated star (size consistent with PSF or larger)
+        // Nsigma should be user-configured parameter
+        bool big = (sigX > (clump.X - clump.dX)) && (sigY > (clump.Y - clump.dY));
+        big = true;
+        if ((Nsatpix > 1) && big) {
+            source->type = PM_SOURCE_TYPE_STAR;
+            source->mode |= PM_SOURCE_MODE_SATSTAR;
+            // recalculate moments here with larger box?
+            pmSourceMoments (source, INNER_RADIUS);
+            Nsatstar ++;
+            continue;
+        }
+
+        // saturated object (not a star, eg bleed trails, hot pixels)
+        if (Nsatpix > 1) {
+            source->type = PM_SOURCE_TYPE_SATURATED;
+            source->mode |= PM_SOURCE_MODE_SATURATED;
+            Nsat ++;
+            continue;
+        }
+
+        // likely defect (too small to be stellar) (push out to 3 sigma)
+        // low S/N objects which are small are probably stellar
+        // only set candidate defects if
+        // XXX these limits are quite arbitrary
+        if ((sigX < 0.05) || (sigY < 0.05)) {
+            source->type = PM_SOURCE_TYPE_DEFECT;
+            source->mode |= PM_SOURCE_MODE_DEFECT;
+            Ncr ++;
+            continue;
+        }
+
+        // likely unsaturated extended source (too large to be stellar)
+        if ((sigX > (clump.X + 3*clump.dX)) || (sigY > (clump.Y + 3*clump.dY))) {
+            source->type = PM_SOURCE_TYPE_EXTENDED;
+            Next ++;
+            continue;
+        }
+
+        // the rest are probable stellar objects
+        starsn_moments->data.F32[starsn_moments->n] = source->moments->SN;
+        starsn_moments->n ++;
+        starsn_peaks->data.F32[starsn_peaks->n] = source->peak->SN;
+        starsn_peaks->n ++;
+        Nstar ++;
+
+        // PSF star (within 1.5 sigma of clump center, S/N > limit)
+        psF32 radius = hypot ((sigX-clump.X)/clump.dX, (sigY-clump.Y)/clump.dY);
+        if ((source->moments->SN > PSF_SN_LIM) && (radius < PSF_CLUMP_NSIGMA)) {
+            source->type = PM_SOURCE_TYPE_STAR;
+            source->mode |= PM_SOURCE_MODE_PSFSTAR;
+            Npsf ++;
+            continue;
+        }
+
+        // random type of star
+        source->type = PM_SOURCE_TYPE_STAR;
+    }
+
+    psStats *stats = NULL;
+    stats = psStatsAlloc (PS_STAT_MIN | PS_STAT_MAX);
+    if (!psVectorStats (stats, starsn_moments, NULL, NULL, 0)) {
+        // Don't care about this error
+        psErrorClear();
+    }
+    psLogMsg ("pmObjects", 3, "SN range (moments): %f - %f\n", stats[0].min, stats[0].max);
+    psFree (starsn_moments);
+    psFree (stats);
+
+    stats = psStatsAlloc (PS_STAT_MIN | PS_STAT_MAX);
+    if (!psVectorStats (stats, starsn_peaks, NULL, NULL, 0)) {
+        // Don't care about this error
+        psErrorClear();
+    }
+    psLogMsg ("pmObjects", 3, "SN range (peaks)  : %f - %f\n", stats[0].min, stats[0].max);
+    psFree (starsn_peaks);
+    psFree (stats);
+
+    psTrace ("psModules.objects", 2, "Nstar:    %3d\n", Nstar);
+    psTrace ("psModules.objects", 2, "Npsf:     %3d\n", Npsf);
+    psTrace ("psModules.objects", 2, "Next:     %3d\n", Next);
+    psTrace ("psModules.objects", 2, "Nsatstar: %3d\n", Nsatstar);
+    psTrace ("psModules.objects", 2, "Nsat:     %3d\n", Nsat);
+    psTrace ("psModules.objects", 2, "Ncr:      %3d\n", Ncr);
+
+    psTrace("psModules.objects", 5, "---- end ----\n");
+    return true;
+}
+
+/******************************************************************************
+pmSourceMoments(source, radius): this function takes a subImage defined in the
+pmSource data structure, along with the peak location, and determines the
+various moments associated with that peak.
+
+Requires the following to have been created:
+    pmSource
+    pmSource->peak
+    pmSource->pixels
+    pmSource->weight
+    pmSource->mask
+
+XXX: The peak calculations are done in image coords, not subImage coords.
+
+XXX EAM : this version clips input pixels on S/N
+XXX EAM : this version returns false for several reasons
+*****************************************************************************/
+# define VALID_RADIUS(X,Y,RAD2) (((RAD2) >= (PS_SQR(X) + PS_SQR(Y))) ? 1 : 0)
+
+bool pmSourceMoments(pmSource *source,
+                     psF32 radius)
+{
+    psTrace("psModules.objects", 5, "---- begin ----\n");
+    PS_ASSERT_PTR_NON_NULL(source, false);
+    PS_ASSERT_PTR_NON_NULL(source->peak, false);
+    PS_ASSERT_PTR_NON_NULL(source->pixels, false);
+    PS_ASSERT_FLOAT_LARGER_THAN(radius, 0.0, false);
+
+    //
+    // XXX: Verify the setting for sky if source->moments == NULL.
+    //
+    psF32 sky = 0.0;
+    if (source->moments == NULL) {
+        source->moments = pmMomentsAlloc();
+    } else {
+        sky = source->moments->Sky;
+    }
+
+    //
+    // Sum = SUM (z - sky)
+    // X1  = SUM (x - xc)*(z - sky)
+    // X2  = SUM (x - xc)^2 * (z - sky)
+    // XY  = SUM (x - xc)*(y - yc)*(z - sky)
+    //
+    psF32 peakPixel = -PS_MAX_F32;
+    psS32 numPixels = 0;
+    psF32 Sum = 0.0;
+    psF32 Var = 0.0;
+    psF32 X1 = 0.0;
+    psF32 Y1 = 0.0;
+    psF32 X2 = 0.0;
+    psF32 Y2 = 0.0;
+    psF32 XY = 0.0;
+    psF32 x  = 0;
+    psF32 y  = 0;
+    psF32 R2 = PS_SQR(radius);
+
+    psF32 xPeak = source->peak->x;
+    psF32 yPeak = source->peak->y;
+    psF32 xOff = source->pixels->col0 - source->peak->x;
+    psF32 yOff = source->pixels->row0 - source->peak->y;
+
+    // XXX why do I get different results for these two methods of finding Sx?
+    // XXX Sx, Sy would be better measured if we clip pixels close to sky
+    // XXX Sx, Sy can still be imaginary, so we probably need to keep Sx^2?
+    // We loop through all pixels in this subimage (source->pixels), and for each
+    // pixel that is not masked, AND within the radius of the peak pixel, we
+    // proceed with the moments calculation.  need to do two loops for a
+    // numerically stable result.  first loop: get the sums.
+    // XXX EAM : mask == 0 is valid
+
+    for (psS32 row = 0; row < source->pixels->numRows ; row++) {
+
+        psF32 *vPix = source->pixels->data.F32[row];
+        psF32 *vWgt = source->weight->data.F32[row];
+        psU8  *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.U8[row];
+
+        for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) {
+            if (vMsk) {
+                if (*vMsk) {
+                    vMsk++;
+                    psTrace("psModules.objects", 10, "Ignoring pixel %d,%d due to mask: %d\n",
+                            col, row, (int)*vMsk);
+                    continue;
+                }
+                vMsk++;
+            }
+	    if (isnan(*vPix)) continue;
+
+            psF32 xDiff = col + xOff;
+            psF32 yDiff = row + yOff;
+
+            // radius is just a function of (xDiff, yDiff)
+            if (!VALID_RADIUS(xDiff, yDiff, R2)) {
+#if 1
+                psTrace("psModules.objects", 10, "Ignoring pixel %d,%d due to position: %f %f\n",
+                        col, row, xDiff, yDiff);
+#endif
+                continue;
+            }
+
+            psF32 pDiff = *vPix - sky;
+            psF32 wDiff = *vWgt;
+
+            // XXX EAM : check for valid S/N in pixel
+            // XXX EAM : should this limit be user-defined?
+            if (PS_SQR(pDiff) < wDiff) {
+#if 1
+                psTrace("psModules.objects", 10, "Ignoring pixel %d,%d due to insignificance: %f, %f\n",
+                        col, row, pDiff, wDiff);
+#endif
+                continue;
+            }
+
+            Var += wDiff;
+            Sum += pDiff;
+
+            psF32 xWght = xDiff * pDiff;
+            psF32 yWght = yDiff * pDiff;
+
+            X1  += xWght;
+            Y1  += yWght;
+
+            XY  += xDiff * yWght;
+            X2  += xDiff * xWght;
+            Y2  += yDiff * yWght;
+
+            peakPixel = PS_MAX (*vPix, peakPixel);
+            numPixels++;
+        }
+    }
+
+    // if we have less than (1/4) of the possible pixels, force a retry
+    // XXX EAM - the limit is a bit arbitrary.  make it user defined?
+    if ((numPixels < 0.75*R2) || (Sum <= 0)) {
+        psTrace ("psModules.objects", 3, "insufficient valid pixels (%d vs %d; %f) for source\n",
+                 numPixels, (int)(0.75*R2), Sum);
+        psTrace("psModules.objects", 5, "---- end (false) ----\n");
+        return (false);
+    }
+
+    psTrace ("psModules.objects", 4, "sky: %f  Sum: %f  X1: %f  Y1: %f  X2: %f  Y2: %f  XY: %f  Npix: %d\n",
+             sky, Sum, X1, Y1, X2, Y2, XY, numPixels);
+
+    //
+    // first moment X  = X1/Sum + xc
+    // second moment X = sqrt (X2/Sum - (X1/Sum)^2)
+    // Sxy             = XY / Sum
+    //
+    x = X1/Sum;
+    y = Y1/Sum;
+    if ((fabs(x) > radius) || (fabs(y) > radius)) {
+        psTrace ("psModules.objects", 3, "large centroid swing; invalid peak %d, %d\n",
+                 source->peak->x, source->peak->y);
+        psTrace("psModules.objects", 5, "---- end(false)  ----\n");
+        return (false);
+    }
+
+    source->moments->x = x + xPeak;
+    source->moments->y = y + yPeak;
+
+    // XXX EAM : Sxy needs to have x*y subtracted
+    source->moments->Sxy = XY/Sum - x*y;
+    source->moments->Sum = Sum;
+    source->moments->SN  = Sum / sqrt(Var);
+    source->moments->Peak = peakPixel;
+    source->moments->nPixels = numPixels;
+
+    // XXX EAM : these values can be negative, so we need to limit the range
+    // XXX EAM : make the use of this consistent: should this be the second moment or sqrt?
+    // source->moments->Sx = sqrt(PS_MAX(X2/Sum - PS_SQR(x), 0));
+    // source->moments->Sy = sqrt(PS_MAX(Y2/Sum - PS_SQR(y), 0));
+    source->moments->Sx = PS_MAX(X2/Sum - PS_SQR(x), 0);
+    source->moments->Sy = PS_MAX(Y2/Sum - PS_SQR(y), 0);
+
+    psTrace ("psModules.objects", 4,
+             "sky: %f  Sum: %f  x: %f  y: %f  Sx: %f  Sy: %f  Sxy: %f\n",
+             sky, Sum, source->moments->x, source->moments->y,
+             source->moments->Sx, source->moments->Sy, source->moments->Sxy);
+
+    psTrace("psModules.objects", 5, "---- end ----\n");
+    return(true);
+}
+
+// construct a realization of the source model
+bool pmSourceCacheModel (pmSource *source, psMaskType maskVal) {
+    PS_ASSERT_PTR_NON_NULL(source, false);
+    // select appropriate model
+    pmModel *model = pmSourceGetModel (NULL, source);
+    if (model == NULL) return false;  // model must be defined
+
+    // if we already have a cached image, re-use that memory
+    source->modelFlux = psImageCopy (source->modelFlux, source->pixels, PS_TYPE_F32);
+    psImageInit (source->modelFlux, 0.0);
+
+    // in some places (psphotEnsemble), we need a normalized version
+    // in others, we just want the model.  which is more commonly used?
+    // modelFlux always has unity normalization (I0 = 1.0)
+    pmModelAdd (source->modelFlux, source->maskObj, model, PM_MODEL_OP_FULL | PM_MODEL_OP_NORM, maskVal);
+    return true;
+}
+
+// construct a realization of the source model
+// XXX this function should optionally save an existing psf image from modelFlux
+bool pmSourceCachePSF (pmSource *source, psMaskType maskVal) {
+    PS_ASSERT_PTR_NON_NULL(source, false);
+
+    // select appropriate model
+    if (source->modelPSF == NULL) return false;  // model must be defined
+
+    // if we already have a cached image, re-use that memory
+    source->psfFlux = psImageCopy (source->psfFlux, source->pixels, PS_TYPE_F32);
+    psImageInit (source->psfFlux, 0.0);
+
+    // in some places (psphotEnsemble), we need a normalized version
+    // in others, we just want the model.  which is more commonly used?
+    // psfFlux always has unity normalization (I0 = 1.0)
+    pmModelAdd (source->psfFlux, source->maskObj, source->modelPSF, PM_MODEL_OP_FULL | PM_MODEL_OP_NORM, maskVal);
+    return true;
+}
+
+// should we call pmSourceCacheModel if it does not exist?
+bool pmSourceOp (pmSource *source, pmModelOpMode mode, bool add, psMaskType maskVal, int dx, int dy)
+{
+    PS_ASSERT_PTR_NON_NULL(source, false);
+    PS_ASSERT_PTR_NON_NULL(source->peak, false);
+    bool status;
+
+    if (add) {
+        psTrace ("psphot", 3, "replacing object at %f,%f\n", source->peak->xf, source->peak->yf);
+    } else {
+        psTrace ("psphot", 3, "removing object at %f,%f\n", source->peak->xf, source->peak->yf);
+    }
+
+    pmModel *model = pmSourceGetModel (NULL, source);
+    if (model == NULL) return false;  // model must be defined
+
+    if (source->modelFlux) {
+        // add in the pixels from the modelFlux image
+        int dX = source->modelFlux->col0 - source->pixels->col0;
+        int dY = source->modelFlux->row0 - source->pixels->row0;
+        assert (dX >= 0);
+        assert (dY >= 0);
+        assert (dX + source->modelFlux->numCols <= source->pixels->numCols);
+        assert (dY + source->modelFlux->numRows <= source->pixels->numRows);
+
+        // modelFlux has unity normalization
+        float Io = model->params->data.F32[PM_PAR_I0];
+        if (mode & PM_MODEL_OP_NORM) {
+            Io = 1.0;
+        }
+
+        psU8 **mask = NULL;
+        if (source->maskObj) {
+            mask = source->maskObj->data.U8;
+        }
+
+        psF32 **target = source->pixels->data.F32;
+        if (mode & PM_MODEL_OP_NOISE) {
+	    // XXX need to scale by the gain...
+            target = source->weight->data.F32;
+        }
+
+        // XXX need to respect the source and model masks?
+        for (int iy = 0; iy < source->modelFlux->numRows; iy++) {
+            int oy = iy + dY;
+            for (int ix = 0; ix < source->modelFlux->numCols; ix++) {
+                int ox = ix + dX;
+                if (mask && (mask[iy][ix] & maskVal)) continue;
+                float value = Io*source->modelFlux->data.F32[iy][ix];
+                if (add) {
+                    target[oy][ox] += value;
+                } else {
+                    target[oy][ox] -= value;
+                }
+            }
+        }
+        return true;
+    }
+
+    psImage *target = source->pixels;
+    if (mode & PM_MODEL_OP_NOISE) {
+        target = source->weight;
+    }
+
+    if (add) {
+        status = pmModelAddWithOffset (target, source->maskObj, model, PM_MODEL_OP_FULL, maskVal, dx, dy);
+    } else {
+        status = pmModelSubWithOffset (target, source->maskObj, model, PM_MODEL_OP_FULL, maskVal, dx, dy);
+    }
+
+    return true;
+}
+
+bool pmSourceAdd (pmSource *source, pmModelOpMode mode, psMaskType maskVal) {
+    return pmSourceOp (source, mode, true, maskVal, 0, 0);
+}
+
+bool pmSourceSub (pmSource *source, pmModelOpMode mode, psMaskType maskVal) {
+    return pmSourceOp (source, mode, false, maskVal, 0, 0);
+}
+
+bool pmSourceAddWithOffset (pmSource *source, pmModelOpMode mode, psMaskType maskVal, int dx, int dy) {
+    return pmSourceOp (source, mode, true, maskVal, dx, dy);
+}
+
+bool pmSourceSubWithOffset (pmSource *source, pmModelOpMode mode, psMaskType maskVal, int dx, int dy) {
+    return pmSourceOp (source, mode, false, maskVal, dx, dy);
+}
+
+// given a source, which model is currently appropriate?
+// choose PSF or EXT based on source->type, but fall back on PSF
+// if the EXT model is NULL
+pmModel *pmSourceGetModel (bool *isPSF, const pmSource *source)
+{
+    PS_ASSERT_PTR_NON_NULL(source, NULL);
+
+    pmModel *model;
+
+    if (isPSF) {
+        *isPSF = false;
+    }
+
+    switch (source->type) {
+      case PM_SOURCE_TYPE_STAR:
+        model = source->modelPSF;
+        if (model == NULL)
+            return NULL;
+        if (isPSF) {
+            *isPSF = true;
+        }
+        return model;
+
+	// the 'best' extended model is saved in source->modelEXT (may be a pointer to one of
+	// the elements of source->modelFits)
+      case PM_SOURCE_TYPE_EXTENDED:
+	model = source->modelEXT;
+        if (!model && source->modelPSF) {
+	    // XXX raise an error or warning here?
+            if (isPSF) {
+                *isPSF = true;
+            }
+            return source->modelPSF;
+        }
+        return (model);
+        break;
+
+      default:
+        return NULL;
+    }
+    return NULL;
+}
+
+// sort by SN (descending)
+int pmSourceSortBySN (const void **a, const void **b)
+{
+    pmSource *A = *(pmSource **)a;
+    pmSource *B = *(pmSource **)b;
+
+    psF32 fA = (A->peak == NULL) ? 0 : A->peak->SN;
+    psF32 fB = (B->peak == NULL) ? 0 : B->peak->SN;
+    if (isnan (fA)) fA = 0;
+    if (isnan (fB)) fB = 0;
+
+    psF32 diff = fA - fB;
+    if (diff > FLT_EPSILON) return (-1);
+    if (diff < FLT_EPSILON) return (+1);
+    return (0);
+}
+
+// sort by Y (ascending)
+int pmSourceSortByY (const void **a, const void **b)
+{
+    pmSource *A = *(pmSource **)a;
+    pmSource *B = *(pmSource **)b;
+
+    psF32 fA = (A->peak == NULL) ? 0 : A->peak->y;
+    psF32 fB = (B->peak == NULL) ? 0 : B->peak->y;
+
+    psF32 diff = fA - fB;
+    if (diff > FLT_EPSILON) return (+1);
+    if (diff < FLT_EPSILON) return (-1);
+    return (0);
+}
+
+pmSourceMode pmSourceModeFromString (const char *name) {
+  if (!strcasecmp (name, "DEFAULT"   )) return PM_SOURCE_MODE_DEFAULT;
+  if (!strcasecmp (name, "PSFMODEL"  )) return PM_SOURCE_MODE_PSFMODEL;
+  if (!strcasecmp (name, "EXTMODEL"  )) return PM_SOURCE_MODE_EXTMODEL;
+  if (!strcasecmp (name, "FITTED"    )) return PM_SOURCE_MODE_FITTED;
+  if (!strcasecmp (name, "FAIL"      )) return PM_SOURCE_MODE_FAIL;
+  if (!strcasecmp (name, "POOR"      )) return PM_SOURCE_MODE_POOR;
+  if (!strcasecmp (name, "PAIR"      )) return PM_SOURCE_MODE_PAIR;
+  if (!strcasecmp (name, "PSFSTAR"   )) return PM_SOURCE_MODE_PSFSTAR;
+  if (!strcasecmp (name, "SATSTAR"   )) return PM_SOURCE_MODE_SATSTAR;
+  if (!strcasecmp (name, "BLEND"     )) return PM_SOURCE_MODE_BLEND;
+  if (!strcasecmp (name, "EXTERNAL"  )) return PM_SOURCE_MODE_EXTERNAL;
+  if (!strcasecmp (name, "BADPSF"    )) return PM_SOURCE_MODE_BADPSF;
+  if (!strcasecmp (name, "DEFECT"    )) return PM_SOURCE_MODE_DEFECT;
+  if (!strcasecmp (name, "SATURATED" )) return PM_SOURCE_MODE_SATURATED;
+  if (!strcasecmp (name, "CRLIMIT"   )) return PM_SOURCE_MODE_CR_LIMIT;
+  if (!strcasecmp (name, "EXTLIMIT"  )) return PM_SOURCE_MODE_EXT_LIMIT;
+  if (!strcasecmp (name, "SUBTRACTED")) return PM_SOURCE_MODE_SUBTRACTED;
+  return PM_SOURCE_MODE_DEFAULT;
+}
+
+char *pmSourceModeToString (const pmSourceMode mode) {
+  switch (mode) {
+    case PM_SOURCE_MODE_DEFAULT    : return psStringCopy ("DEFAULT"   );
+    case PM_SOURCE_MODE_PSFMODEL   : return psStringCopy ("PSFMODEL"  );
+    case PM_SOURCE_MODE_EXTMODEL   : return psStringCopy ("EXTMODEL"  );
+    case PM_SOURCE_MODE_FITTED     : return psStringCopy ("FITTED"    );
+    case PM_SOURCE_MODE_FAIL       : return psStringCopy ("FAIL"      );
+    case PM_SOURCE_MODE_POOR       : return psStringCopy ("POOR"      );
+    case PM_SOURCE_MODE_PAIR       : return psStringCopy ("PAIR"      );
+    case PM_SOURCE_MODE_PSFSTAR    : return psStringCopy ("PSFSTAR"   );
+    case PM_SOURCE_MODE_SATSTAR    : return psStringCopy ("SATSTAR"   );
+    case PM_SOURCE_MODE_BLEND      : return psStringCopy ("BLEND"     );
+    case PM_SOURCE_MODE_EXTERNAL   : return psStringCopy ("EXTERNAL"  );
+    case PM_SOURCE_MODE_BADPSF     : return psStringCopy ("BADPSF"    );
+    case PM_SOURCE_MODE_DEFECT     : return psStringCopy ("DEFECT"    );
+    case PM_SOURCE_MODE_SATURATED  : return psStringCopy ("SATURATED" );
+    case PM_SOURCE_MODE_CR_LIMIT   : return psStringCopy ("CRLIMIT"   );
+    case PM_SOURCE_MODE_EXT_LIMIT  : return psStringCopy ("EXTLIMIT"  );
+    case PM_SOURCE_MODE_SUBTRACTED : return psStringCopy ("SUBTRACTED");
+    default:
+      return NULL;
+  }
+  return NULL;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSource.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSource.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSource.h	(revision 22158)
@@ -0,0 +1,243 @@
+/* @file  pmSource.h
+ *
+ * @author EAM, IfA; GLG, MHPCC
+ *
+ * @version $Revision: 1.24 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-04-08 18:35:38 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+# ifndef PM_SOURCE_H
+# define PM_SOURCE_H
+
+# include "pmSourceExtendedPars.h"
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+/** pmSourceType enumeration
+ *
+ * A given source may be identified as most-likely to be one of several source
+ * types. The pmSource entry pmSourceType defines the current best-guess for this
+ * source.
+ *
+ */
+typedef enum {
+    PM_SOURCE_TYPE_UNKNOWN,		///< not yet classified
+    PM_SOURCE_TYPE_DEFECT,		///< a cosmic-ray
+    PM_SOURCE_TYPE_SATURATED,		///< random saturated pixels (eg, bleed trails)
+    PM_SOURCE_TYPE_STAR,		///< a good-quality star (subtracted model is PSF)
+    PM_SOURCE_TYPE_EXTENDED,		///< an extended object (eg, galaxy) (subtracted model is EXT)
+} pmSourceType;
+
+typedef enum {
+    PM_SOURCE_MODE_DEFAULT    = 0x0000, ///<
+    PM_SOURCE_MODE_PSFMODEL   = 0x0001, ///< Source fitted with a psf model (linear or non-linear)
+    PM_SOURCE_MODE_EXTMODEL   = 0x0002, ///< Source fitted with an extended-source model
+    PM_SOURCE_MODE_FITTED     = 0x0004, ///< Source fitted with non-linear model (PSF or EXT; good or bad)
+    PM_SOURCE_MODE_FAIL       = 0x0008, ///< Fit (non-linear) failed (non-converge, off-edge, run to zero)
+    PM_SOURCE_MODE_POOR       = 0x0010, ///< Fit succeeds, but low-SN, high-Chisq, or large (for PSF -- drop?)
+    PM_SOURCE_MODE_PAIR       = 0x0020, ///< Source fitted with a double psf
+    PM_SOURCE_MODE_PSFSTAR    = 0x0040, ///< Source used to define PSF model
+    PM_SOURCE_MODE_SATSTAR    = 0x0080, ///< Source model peak is above saturation
+    PM_SOURCE_MODE_BLEND      = 0x0100, ///< Source is a blend with other sourcers
+    PM_SOURCE_MODE_EXTERNAL   = 0x0200, ///< Source based on supplied input position
+    PM_SOURCE_MODE_BADPSF     = 0x0400, ///< Failed to get good estimate of object's PSF
+    PM_SOURCE_MODE_DEFECT     = 0x0800, ///< Source is thought to be a defect
+    PM_SOURCE_MODE_SATURATED  = 0x1000, ///< Source is thought to be saturated pixels (bleed trail)
+    PM_SOURCE_MODE_CR_LIMIT   = 0x2000, ///< Source has crNsigma above limit
+    PM_SOURCE_MODE_EXT_LIMIT  = 0x4000, ///< Source has extNsigma above limit
+    PM_SOURCE_MODE_SUBTRACTED = 0x8000, ///< XXX this flag is actually only used internally (move)
+} pmSourceMode;
+
+/** pmSource data structure
+ *
+ *  This source has the capacity for several types of measurements. The
+ *  simplest measurement of a source is the location and flux of the peak pixel
+ *  associated with the source:
+ *
+ *  XXX do I have to re-organize this (again!) to allow an arbitrary set of extended model fits??
+ *  XXX put the Mag and Err inside the pmModel?
+ *  XXX keep the modelEXT or add to the psArray 
+ *  
+ *
+ */
+struct pmSource {
+    const int id;                       ///< Unique ID for object
+    int seq;				///< ID for output (generated on write)
+    pmPeak  *peak;                      ///< Description of peak pixel.
+    psImage *pixels;                    ///< Rectangular region including object pixels.
+    psImage *weight;                    ///< Image variance.
+    psImage *maskObj;                   ///< unique mask for this object which marks included pixels associated with objects.
+    psImage *maskView;                  ///< view into global image mask for this object region
+    psImage *modelFlux;                 ///< cached copy of the best model for this source
+    psImage *psfFlux;                   ///< cached copy of the psf model for this source
+    pmMoments *moments;                 ///< Basic moments measured for the object.
+    pmModel *modelPSF;                  ///< PSF Model fit (parameters and type)
+    pmModel *modelEXT;                  ///< EXT Model fit used for subtraction (parameters and type)
+    psArray *modelFits;			///< collection of extended source models (best == modelEXT)
+    pmSourceType type;                  ///< Best identification of object.
+    pmSourceMode mode;                  ///< analysis flags set for object.
+    psArray *blends;			///< collection of sources thought to be confused with object
+    float psfMag;                       ///< calculated from flux in modelPSF
+    float extMag;                       ///< calculated from flux in modelEXT
+    float errMag;                       ///< error in psfMag OR extMag (depending on type)
+    float apMag;                        ///< apMag corresponding to psfMag or extMag (depending on type)
+    float pixWeight;                    ///< model-weighted coverage of valid pixels
+    float psfChisq;			///< probability of PSF
+    float crNsigma;                     ///< Nsigma deviation from PSF to CR
+    float extNsigma;                    ///< Nsigma deviation from PSF to EXT
+    float sky, skyErr;                  ///< The sky and its error at the center of the object
+    psRegion region;                    ///< area on image covered by selected pixels
+    pmSourceExtendedPars *extpars;      ///< extended source parameters
+};
+
+/** pmPSFClump data structure
+ *
+ * A collection of object moment measurements can be used to determine
+ * approximate object classes. The key to this analysis is the location and
+ * statistics (in the second-moment plane,
+ *
+ */
+typedef struct
+{
+    float X;
+    float dX;
+    float Y;
+    float dY;
+}
+pmPSFClump;
+
+
+/** pmSourceAlloc()
+ *
+ */
+pmSource  *pmSourceAlloc();
+
+/** pmSourceCopy()
+ *
+ */
+
+bool psMemCheckSource(psPtr ptr);
+
+pmSource  *pmSourceCopy(pmSource *source);
+
+// free just the pixels for a source, keeping derived data
+void pmSourceFreePixels(pmSource *source);
+
+/** pmSourceDefinePixels()
+ *
+ * Define psImage subarrays for the source located at coordinates x,y on the
+ * image set defined by readout. The pixels defined by this operation consist of
+ * a square window (of full width 2Radius+1) centered on the pixel which contains
+ * the given coordinate, in the frame of the readout. The window is defined to
+ * have limits which are valid within the boundary of the readout image, thus if
+ * the radius would fall outside the image pixels, the subimage is truncated to
+ * only consist of valid pixels. If readout->mask or readout->weight are not
+ * NULL, matching subimages are defined for those images as well. This function
+ * fails if no valid pixels can be defined (x or y less than Radius, for
+ * example). This function should be used to define a region of interest around a
+ * source, including both source and sky pixels.
+ *
+ */
+bool pmSourceDefinePixels(
+    pmSource *mySource,                 ///< source to be re-defined
+    const pmReadout *readout,  ///< base the source on this readout
+    psF32 x,                            ///< center coords of source
+    psF32 y,                            ///< center coords of source
+    psF32 Radius                        ///< size of box on source
+);
+
+bool pmSourceRedefinePixels (
+    pmSource *mySource,   ///< source to be re-defined
+    const pmReadout *readout,   ///< base the source on this readout
+    psF32 x,     ///< center coords of source
+    psF32 y,      ///< center coords of source
+    psF32 Radius   ///< size of box on source
+);
+
+/** pmSourcePSFClump()
+ *
+ * We use the source moments to make an initial, approximate source
+ * classification, and as part of the information needed to build a PSF model for
+ * the image. As long as the PSF shape does not vary excessively across the
+ * image, the sources which are represented by a PSF (the start) will have very
+ * similar second moments. The function pmSourcePSFClump searches a collection of
+ * sources with measured moments for a group with moments which are all very
+ * similar. The function returns a pmPSFClump structure, representing the
+ * centroid and size of the clump in the sigma_x, sigma_y second-moment plane.
+ *
+ * The goal is to identify and characterize the stellar clump within the
+ * sigma_x, sigma_y second-moment plane.  To do this, an image is constructed to
+ * represent this plane.  The units of sigma_x and sigma_y are in image pixels. A
+ * pixel in this analysis image represents 0.1 pixels in the input image. The
+ * dimensions of the image need only be 10 pixels. The peak pixel in this image
+ * (above a threshold of half of the image maximum) is found. The coordinates of
+ * this peak pixel represent the 2D mode of the sigma_x, sigma_y distribution.
+ * The sources with sigma_x, sigma_y within 0.2 pixels of this value are then
+ *  * used to calculate the median and standard deviation of the sigma_x, sigma_y
+ * values. These resulting values are returned via the pmPSFClump structure.
+ *
+ * The return value indicates the success (TRUE) of the operation.
+ *
+ * XXX: Limit the S/N of the candidate sources (part of Metadata)? (TBD).
+ * XXX: Save the clump parameters on the Metadata (TBD)
+ *
+ */
+pmPSFClump pmSourcePSFClump(
+    psArray *source,                    ///< The input pmSource
+    psMetadata *metadata                ///< Contains classification parameters
+);
+
+/** pmSourceRoughClass()
+ *
+ * Based on the specified data values, make a guess at the source
+ * classification. The sources are provides as a psArray of pmSource entries.
+ * Definable parameters needed to make the classification are provided to the
+ * routine with the psMetadata structure. The rules (in SDRS) refer to values which
+ * can be extracted from the metadata using the given keywords. Except as noted,
+ * the data type for these parameters are psF32.
+ *
+ */
+bool pmSourceRoughClass(
+    psArray *source,                    ///< The input pmSource
+    psMetadata *metadata,               ///< Contains classification parameters
+    pmPSFClump clump,                   ///< Statistics about the PSF clump
+    psMaskType maskSat                  ///< Mask value for saturated pixels
+);
+
+
+/** pmSourceMoments()
+ *
+ * Measure source moments for the given source, using the value of
+ * source.moments.sky provided as the local background value and the peak
+ * coordinates as the initial source location. The resulting moment values are
+ * applied to the source.moments entry, and the source is returned. The moments
+ * are measured within the given circular radius of the source.peak coordinates.
+ * The return value indicates the success (TRUE) of the operation.
+ *
+ */
+bool pmSourceMoments(
+    pmSource *source,   ///< The input pmSource for which moments will be computed
+    float radius   ///< Use a circle of pixels around the peak
+);
+
+pmModel *pmSourceGetModel (bool *isPSF, const pmSource *source);
+
+bool pmSourceAdd (pmSource *source, pmModelOpMode mode, psMaskType maskVal);
+bool pmSourceSub (pmSource *source, pmModelOpMode mode, psMaskType maskVal);
+bool pmSourceAddWithOffset (pmSource *source, pmModelOpMode mode, psMaskType maskVal, int dx, int dy);
+bool pmSourceSubWithOffset (pmSource *source, pmModelOpMode mode, psMaskType maskVal, int dx, int dy);
+
+bool pmSourceOp (pmSource *source, pmModelOpMode mode, bool add, psMaskType maskVal, int dx, int dy);
+bool pmSourceCacheModel (pmSource *source, psMaskType maskVal);
+bool pmSourceCachePSF (pmSource *source, psMaskType maskVal);
+
+int             pmSourceSortBySN (const void **a, const void **b);
+int             pmSourceSortByY (const void **a, const void **b);
+
+pmSourceMode pmSourceModeFromString (const char *name);
+char *pmSourceModeToString (const pmSourceMode mode);
+
+/// @}
+# endif /* PM_SOURCE_H */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceContour.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceContour.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceContour.c	(revision 22158)
@@ -0,0 +1,459 @@
+/** @file  pmSourceContour.c
+ *
+ *  Functions to measure the local sky and sky variance for sources on images
+ *
+ *  @author GLG, MHPCC
+ *  @author EAM, IfA: significant modifications.
+ *
+ *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-01-02 20:39:04 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include "pslib.h"
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmResiduals.h"
+#include "pmGrowthCurve.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmSourceContour.h"
+
+/******************************************************************************
+findValue(source, level, row, col, dir): a private function which determines
+the column coordinate of the model function which has the value "level".  If
+dir equals 0, then you loop leftwards from the peak pixel, otherwise,
+rightwards.
+ 
+XXX: reverse order of row,col args?
+ 
+XXX: Input row/col are in image coords.
+ 
+XXX: The result is returned in image coords.
+*****************************************************************************/
+# define LEFT false
+# define RIGHT true
+
+// return the first coordinate at or below the threshold in the requested direction
+static int findContourNeg(
+    psImage *image,
+    float threshold,
+    int x,
+    int y,
+    bool right)
+{
+
+    psTrace("psModules.objects", 4, "---- %s() begin ----\n", __func__);
+
+    // We define variables incr and lastColumn so that we can use the same loop
+    // whether we are stepping leftwards, or rightwards.
+
+    int incr;
+    int subCol;
+    int lastColumn;
+    if (right) {
+        incr = 1;
+        lastColumn = image->numCols - 1;
+    } else {
+        incr = -1;
+        lastColumn = 0;
+    }
+
+    subCol = x;
+
+    while (subCol != lastColumn) {
+        float value = image->data.F32[y][subCol];
+        if (value <= threshold) {
+            psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+            return (subCol);
+        }
+        subCol += incr;
+    }
+    psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+    return (lastColumn);
+}
+
+// return the last coordinate at or below the threshold in the requested direction
+static int findContourPos(
+    psImage *image,
+    float threshold,
+    int x,
+    int y,
+    bool right,
+    int xEnd)
+{
+
+    psTrace("psModules.objects", 4, "---- %s() begin ----\n", __func__);
+
+    // We define variables incr and lastColumn so that we can use the same loop
+    // whether we are stepping leftwards, or rightwards.
+
+    int incr;
+    int subCol;
+    int lastColumn;
+    if (right) {
+        incr = 1;
+        lastColumn = PS_MIN (image->numCols - 1, xEnd);
+    } else {
+        incr = -1;
+        lastColumn = PS_MAX (0, xEnd);
+    }
+
+    subCol = x;
+    while (subCol != lastColumn) {
+        float value = image->data.F32[y][subCol];
+        if (value >= threshold) {
+            psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+            if (subCol == x) {
+                return (subCol);
+            }
+            return (subCol);
+        }
+        subCol += incr;
+    }
+    psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+    return (lastColumn);
+}
+
+/******************************************************************************
+findValue(source, level, row, col, dir): a private function which determines
+the column coordinate of the model function which has the value "level".  If
+dir equals 0, then you loop leftwards from the peak pixel, otherwise,
+rightwards.
+ 
+XXX: reverse order of row,col args?
+ 
+XXX: Input row/col are in image coords.
+ 
+XXX: The result is returned in image coords.
+*****************************************************************************/
+static psF32 findValue(pmSource *source,
+                       psF32 level,
+                       psU32 row,
+                       psU32 col,
+                       psU32 dir)
+{
+    psTrace("psModules.objects", 4, "---- %s() begin ----\n", __func__);
+    //
+    // Convert coords to subImage space.
+    //
+    psU32 subRow = row - source->pixels->row0;
+    psU32 subCol = col - source->pixels->col0;
+
+    // Ensure that the starting column is allowable.
+    if (!((0 <= subCol) && (subCol < source->pixels->numCols))) {
+        psError(PS_ERR_UNKNOWN, true, "Starting column outside subImage range");
+        psTrace("psModules.objects", 4, "---- %s(NAN) end ----\n", __func__);
+        return(NAN);
+    }
+    if (!((0 <= subRow) && (subRow < source->pixels->numRows))) {
+        psTrace("psModules.objects", 4, "---- %s(NAN) end ----\n", __func__);
+        psError(PS_ERR_UNKNOWN, true, "Starting row outside subImage range");
+        return(NAN);
+    }
+
+    // XXX EAM : i changed this to match pmModelEval above, but see
+    // XXX EAM   the note below in pmSourceContour
+    psF32 oldValue = pmModelEval(source->modelEXT, source->pixels, subCol, subRow);
+    if (oldValue == level) {
+        psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+        return(((psF32) (subCol + source->pixels->col0)));
+    }
+
+    //
+    // We define variables incr and lastColumn so that we can use the same loop
+    // whether we are stepping leftwards, or rightwards.
+    //
+    psS32 incr;
+    psS32 lastColumn;
+    if (dir == 0) {
+        incr = -1;
+        lastColumn = -1;
+    } else {
+        incr = 1;
+        lastColumn = source->pixels->numCols;
+    }
+    subCol+=incr;
+
+    while (subCol != lastColumn) {
+        psF32 newValue = pmModelEval(source->modelEXT, source->pixels, subCol, subRow);
+        if (oldValue == level) {
+            psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+            return((psF32) (subCol + source->pixels->col0));
+        }
+
+        if ((newValue <= level) && (level <= oldValue)) {
+            // This is simple linear interpolation.
+            psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+            return( ((psF32) (subCol + source->pixels->col0)) + ((psF32) incr) * ((level - newValue) / (oldValue - newValue)) );
+        }
+
+        if ((oldValue <= level) && (level <= newValue)) {
+            // This is simple linear interpolation.
+            psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+            return( ((psF32) (subCol + source->pixels->col0)) + ((psF32) incr) * ((level - oldValue) / (newValue - oldValue)) );
+        }
+
+        subCol+=incr;
+    }
+
+    psTrace("psModules.objects", 4, "---- %s(NAN) end ----\n", __func__);
+    return(NAN);
+}
+
+/******************************************************************************
+new implementation of source contour function
+*****************************************************************************/
+psArray *pmSourceContour (psImage *image, int xc, int yc, float threshold)
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_PTR_NON_NULL(image, NULL);
+
+    int xR, yR, x0, x1, x0s, x1s;
+    int x = xc - image->col0;
+    int y = yc - image->row0;
+
+    // Ensure that the starting column is allowable.
+    if (x < 0) {
+        return NULL;
+    }
+    if (y < 0) {
+        return NULL;
+    }
+    if (x >= image->numCols) {
+        return NULL;
+    }
+    if (y >= image->numRows) {
+        return NULL;
+    }
+
+    // the requested point must be within the contour
+    if (image->data.F32[y][x] < threshold) {
+        return NULL;
+    }
+
+    // Allocate data for x/y pairs.
+    psVector *xVec = psVectorAllocEmpty(100, PS_TYPE_F32);
+    psVector *yVec = psVectorAllocEmpty(100, PS_TYPE_F32);
+
+    // First row: find the left and right end-points
+    int Npt = 0;
+
+    x0 = findContourNeg (image, threshold, x, y, LEFT);
+    x1 = findContourNeg (image, threshold, x, y, RIGHT);
+    xVec->data.F32[Npt + 0] = image->col0 + x0;
+    xVec->data.F32[Npt + 1] = image->col0 + x1;
+    yVec->data.F32[Npt + 0] = image->row0 + y;
+    yVec->data.F32[Npt + 1] = image->row0 + y;
+    Npt += 2;
+
+    x0s = x0;
+    x1s = x1;
+
+    // look for contour outline above row
+    xR = x0s;
+    yR = y + 1;
+    while (yR < image->numRows) {
+        if (image->data.F32[yR][xR] < threshold) {
+            x0 = findContourPos (image, threshold, xR, yR, RIGHT, x1);
+            if (x0 == x1) {
+                // fprintf (stderr, "top: %d (%d - %d)\n", yR, xR, x1);
+                goto pt1;
+            }
+            x1 = findContourNeg (image, threshold, x0, yR, RIGHT);
+            x0--;
+        } else {
+            x0 = findContourNeg (image, threshold, xR, yR, LEFT);
+            x1 = findContourNeg (image, threshold, xR, yR, RIGHT);
+        }
+        // fprintf (stderr, "pos: %d (%d - %d)\n", yR, x0, x1);
+
+        xVec->data.F32[Npt + 0] = image->col0 + x0;
+        xVec->data.F32[Npt + 1] = image->col0 + x1;
+        yVec->data.F32[Npt + 0] = image->row0 + yR;
+        yVec->data.F32[Npt + 1] = image->row0 + yR;
+        Npt += 2;
+
+        if (Npt >= xVec->nalloc - 1) {
+            psVectorRealloc (xVec, xVec->nalloc + 100);
+            psVectorRealloc (yVec, yVec->nalloc + 100);
+        }
+        yR ++;
+        xR = x0;
+    }
+
+pt1:
+    // look for contour outline below row
+    xR = x0s;
+    x1 = x1s;
+    yR = y - 1;
+    while (yR >= 0) {
+        if (image->data.F32[yR][xR] < threshold) {
+            x0 = findContourPos (image, threshold, xR, yR, RIGHT, x1);
+            if (x0 == x1) {
+                // fprintf (stderr, "top: %d (%d - %d)\n", yR, xR, x1);
+                goto pt2;
+            }
+            x1 = findContourNeg (image, threshold, x0, yR, RIGHT);
+            x0--;
+        } else {
+            x0 = findContourNeg (image, threshold, xR, yR, LEFT);
+            x1 = findContourNeg (image, threshold, xR, yR, RIGHT);
+        }
+        // fprintf (stderr, "neg: %d (%d - %d)\n", yR, x0, x1);
+
+        xVec->data.F32[Npt + 0] = image->col0 + x0;
+        xVec->data.F32[Npt + 1] = image->col0 + x1;
+        yVec->data.F32[Npt + 0] = image->row0 + yR;
+        yVec->data.F32[Npt + 1] = image->row0 + yR;
+        Npt += 2;
+
+        if (Npt >= xVec->nalloc - 1) {
+            psVectorRealloc (xVec, xVec->nalloc + 100);
+            psVectorRealloc (yVec, yVec->nalloc + 100);
+        }
+        yR --;
+    }
+pt2:
+    xVec->n = Npt;
+    yVec->n = Npt;
+
+    // fprintf (stderr, "done\n");
+    psArray *tmpArray = psArrayAlloc(2);
+
+    tmpArray->data[0] = (psPtr *) xVec;
+    tmpArray->data[1] = (psPtr *) yVec;
+    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    return(tmpArray);
+}
+
+/******************************************************************************
+    pmSourceContour(src, img, level, mode): For an input subImage, and model, this
+    routine returns a psArray of coordinates that evaluate to the specified level.
+ 
+    XXX: Probably should remove the "image" argument.
+    XXX: What type should the output coordinate vectors consist of?  col,row?
+    XXX: Why a pmArray output?
+    XXX: doex x,y correspond with col,row or row/col?
+    XXX: What is mode?
+    XXX: The top, bottom of the contour is not correctly determined.
+    XXX EAM : this function is using the model for the contour, but it should
+              be using only the image counts
+*****************************************************************************/
+psArray *pmSourceContour_Crude(pmSource *source,
+                               const psImage *image,
+                               psF32 level)
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_PTR_NON_NULL(source, false);
+    PS_ASSERT_PTR_NON_NULL(image, false);
+    PS_ASSERT_PTR_NON_NULL(source->moments, false);
+    PS_ASSERT_PTR_NON_NULL(source->peak, false);
+    PS_ASSERT_PTR_NON_NULL(source->pixels, false);
+    PS_ASSERT_PTR_NON_NULL(source->modelEXT, false);
+    // XXX EAM : what is the purpose of modelPSF/modelEXT?
+
+    //
+    // Allocate data for x/y pairs.
+    //
+    psVector *xVec = psVectorAlloc(2 * source->pixels->numRows, PS_TYPE_F32);
+    psVector *yVec = psVectorAlloc(2 * source->pixels->numRows, PS_TYPE_F32);
+
+    //
+    // Start at the row with peak pixel, then decrement.
+    //
+    psS32 col = source->peak->x;
+    for (psS32 row = source->peak->y; row>= 0 ; row--) {
+        // XXX: yVec contain no real information.  Do we really need it?
+        yVec->data.F32[row] = (psF32) (source->pixels->row0 + row);
+        yVec->data.F32[row+yVec->n] = (psF32) (source->pixels->row0 + row);
+
+        // Starting at peak pixel, search leftwards for the column intercept.
+        psF32 leftIntercept = findValue(source, level, row, col, 0);
+        if (isnan(leftIntercept)) {
+            psError(PS_ERR_UNKNOWN, true, "Could not find contour edge (NAN)");
+            psFree(xVec);
+            psFree(yVec);
+            psTrace("psModules.objects", 3, "---- %s(NULL) end ----\n", __func__);
+            return(NULL);
+            //psLogMsg(__func__, PS_LOG_WARN, "WARNING: Could not find contour edge (NAN)\n");
+        }
+        xVec->data.F32[row] = ((psF32) source->pixels->col0) + leftIntercept;
+
+        // Starting at peak pixel, search rightwards for the column intercept.
+
+        psF32 rightIntercept = findValue(source, level, row, col, 1);
+        if (isnan(rightIntercept)) {
+            psError(PS_ERR_UNKNOWN, true, "Could not find contour edge (NAN)");
+            psFree(xVec);
+            psFree(yVec);
+            psTrace("psModules.objects", 3, "---- %s(NULL) end ----\n", __func__);
+            return(NULL);
+            //psLogMsg(__func__, PS_LOG_WARN, "WARNING: Could not find contour edge (NAN)\n");
+        }
+        psTrace("psModules.objects", 4, "The intercepts are (%.2f, %.2f)\n", leftIntercept, rightIntercept);
+        xVec->data.F32[row+xVec->n] = ((psF32) source->pixels->col0) + rightIntercept;
+
+        // Set starting column for next row
+        col = (psS32) ((leftIntercept + rightIntercept) / 2.0);
+    }
+    //
+    // Start at the row (+1) with peak pixel, then increment.
+    //
+    col = source->peak->x;
+    for (psS32 row = 1 + source->peak->y; row < source->pixels->numRows ; row++) {
+        // XXX: yVec contain no real information.  Do we really need it?
+        yVec->data.F32[row] = (psF32) (source->pixels->row0 + row);
+        yVec->data.F32[row+yVec->n] = (psF32) (source->pixels->row0 + row);
+
+        // Starting at peak pixel, search leftwards for the column intercept.
+        psF32 leftIntercept = findValue(source, level, row, col, 0);
+        if (isnan(leftIntercept)) {
+            psError(PS_ERR_UNKNOWN, true, "Could not find contour edge (NAN)");
+            psFree(xVec);
+            psFree(yVec);
+            psTrace("psModules.objects", 3, "---- %s(NULL) end ----\n", __func__);
+            return(NULL);
+            //psLogMsg(__func__, PS_LOG_WARN, "WARNING: Could not find contour edge (NAN)\n");
+        }
+        xVec->data.F32[row] = ((psF32) source->pixels->col0) + leftIntercept;
+
+        // Starting at peak pixel, search rightwards for the column intercept.
+        psF32 rightIntercept = findValue(source, level, row, col, 1);
+        if (isnan(rightIntercept)) {
+            psError(PS_ERR_UNKNOWN, true, "Could not find contour edge (NAN)");
+            psFree(xVec);
+            psFree(yVec);
+            psTrace("psModules.objects", 3, "---- %s(NULL) end ----\n", __func__);
+            return(NULL);
+            //psLogMsg(__func__, PS_LOG_WARN, "WARNING: Could not find contour edge (NAN)\n");
+        }
+        xVec->data.F32[row+xVec->n] = ((psF32) source->pixels->col0) + rightIntercept;
+
+        // Set starting column for next row
+        col = (psS32) ((leftIntercept + rightIntercept) / 2.0);
+    }
+
+    //
+    // Allocate an array for result, store coord vectors there.
+    //
+    psArray *tmpArray = psArrayAlloc(2);
+
+    tmpArray->data[0] = (psPtr *) yVec;
+    tmpArray->data[1] = (psPtr *) xVec;
+    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    return(tmpArray);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceContour.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceContour.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceContour.h	(revision 22158)
@@ -0,0 +1,39 @@
+/* @file  pmSourceContour.h
+ *
+ * @author EAM, IfA; GLG, MHPCC
+ *
+ * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-01-24 02:54:15 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+# ifndef PM_SOURCE_CONTOUR_H
+# define PM_SOURCE_CONTOUR_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+psArray *pmSourceContour (psImage *image, int xc, int yc, float threshold);
+
+
+/** pmSourceContour()
+ *
+ * Find points in a contour for the given source at the given level. If type
+ * is PM_CONTOUR_CRUDE, the contour is found by starting at the source peak,
+ * running along each pixel row until the level is crossed, then interpolating to
+ * the level coordinate for that row. This is done for each row, with the
+ * starting point determined by the midpoint of the previous row, until the
+ * starting point has a value below the contour level. The returned contour
+ * consists of two vectors giving the x and y coordinates of the contour levels.
+ * This function may be used as part of the model guess inputs.  Other contour
+ * types may be specified in the future for more refined contours (TBD)
+ *
+ */
+psArray *pmSourceContour_Crude(
+    pmSource *source,   ///< The input pmSource
+    const psImage *image,  ///< The input image (float) (this arg should be removed)
+    float level   ///< The level of the contour
+);
+
+/// @}
+# endif /* PM_SOURCE_PHOTOMETRY_H */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceExtendedPars.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceExtendedPars.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceExtendedPars.c	(revision 22158)
@@ -0,0 +1,198 @@
+/** @file  pmSourceExtendedPars.c
+ *
+ *  Functions to define and manipulate sources on images
+ *
+ *  @author GLG, MHPCC
+ *  @author EAM, IfA: significant modifications.
+ *
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-12-22 00:31:41 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPAMaskWeight.h"
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmResiduals.h"
+#include "pmGrowthCurve.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+
+static void pmSourceExtendedParsFree (pmSourceExtendedPars *pars) {
+    if (!pars) return;
+
+    psFree(pars->profile);
+    psFree(pars->annuli);
+    psFree(pars->isophot);
+    psFree(pars->petrosian);
+    psFree(pars->kron);
+    return;
+}
+
+pmSourceExtendedPars *pmSourceExtendedParsAlloc () {
+    pmSourceExtendedPars *pars = (pmSourceExtendedPars *) psAlloc(sizeof(pmSourceExtendedPars));
+    psMemSetDeallocator(pars, (psFreeFunc) pmSourceExtendedParsFree);
+
+    pars->profile = NULL;
+    pars->annuli = NULL;
+    pars->isophot = NULL;
+    pars->petrosian = NULL;
+    pars->kron = NULL;
+
+    return pars;
+}
+
+bool psMemCheckSourceExtendedPars(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmSourceExtendedParsFree);
+}
+
+
+static void pmSourceRadialProfileFree (pmSourceRadialProfile *profile) {
+    if (!profile) return;
+
+    psFree(profile->radius);
+    psFree(profile->flux);
+    psFree(profile->weight);
+    return;
+}
+
+pmSourceRadialProfile *pmSourceRadialProfileAlloc () {
+
+    pmSourceRadialProfile *profile = (pmSourceRadialProfile *) psAlloc(sizeof(pmSourceRadialProfile));
+    psMemSetDeallocator(profile, (psFreeFunc) pmSourceRadialProfileFree);
+
+    profile->radius = NULL;
+    profile->flux = NULL;
+    profile->weight = NULL;
+
+    return profile;
+}
+
+bool psMemCheckSourceRadialProfile(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmSourceRadialProfileFree);
+}
+
+
+static void pmSourceIsophotalValuesFree (pmSourceIsophotalValues *isophot) {
+    if (!isophot) return;
+    return;
+}
+
+pmSourceIsophotalValues *pmSourceIsophotalValuesAlloc () {
+
+    pmSourceIsophotalValues *isophot = (pmSourceIsophotalValues *) psAlloc(sizeof(pmSourceIsophotalValues));
+    psMemSetDeallocator(isophot, (psFreeFunc) pmSourceIsophotalValuesFree);
+
+    isophot->mag = 0.0;
+    isophot->magErr = 0.0;
+    isophot->rad = 0.0;
+    isophot->radErr = 0.0;
+
+    return isophot;
+}
+
+
+bool psMemCheckSourceIsophotalValues(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmSourceIsophotalValuesFree);
+}
+
+
+static void pmSourcePetrosianValuesFree (pmSourcePetrosianValues *petrosian) {
+    if (!petrosian) return;
+    return;
+}
+
+pmSourcePetrosianValues *pmSourcePetrosianValuesAlloc () {
+
+    pmSourcePetrosianValues *petrosian = (pmSourcePetrosianValues *) psAlloc(sizeof(pmSourcePetrosianValues));
+    psMemSetDeallocator(petrosian, (psFreeFunc) pmSourcePetrosianValuesFree);
+
+    petrosian->mag = 0.0;
+    petrosian->magErr = 0.0;
+    petrosian->rad = 0.0;
+    petrosian->radErr = 0.0;
+
+    return petrosian;
+}
+
+
+bool psMemCheckSourcePetrosianValues(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmSourcePetrosianValuesFree);
+}
+
+static void pmSourceKronValuesFree (pmSourceKronValues *kron) {
+    if (!kron) return;
+    return;
+}
+
+pmSourceKronValues *pmSourceKronValuesAlloc () {
+
+    pmSourceKronValues *kron = (pmSourceKronValues *) psAlloc(sizeof(pmSourceKronValues));
+    psMemSetDeallocator(kron, (psFreeFunc) pmSourceKronValuesFree);
+
+    kron->mag = 0.0;
+    kron->magErr = 0.0;
+    kron->rad = 0.0;
+    kron->radErr = 0.0;
+
+    return kron;
+}
+
+
+bool psMemCheckSourceKronValues(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmSourceKronValuesFree);
+}
+
+
+static void pmSourceAnnuliFree (pmSourceAnnuli *annuli) {
+    if (!annuli) return;
+
+    psFree (annuli->flux);
+    psFree (annuli->fluxErr);
+    psFree (annuli->fluxVar);
+
+    return;
+}
+
+pmSourceAnnuli *pmSourceAnnuliAlloc () {
+
+    pmSourceAnnuli *annuli = (pmSourceAnnuli *) psAlloc(sizeof(pmSourceAnnuli));
+    psMemSetDeallocator(annuli, (psFreeFunc) pmSourceAnnuliFree);
+
+    annuli->flux = NULL;
+    annuli->fluxErr = NULL;
+    annuli->fluxVar = NULL;
+
+    return annuli;
+}
+
+
+bool psMemCheckSourceAnnuli(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmSourceAnnuliFree);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceExtendedPars.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceExtendedPars.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceExtendedPars.h	(revision 22158)
@@ -0,0 +1,71 @@
+/* @file  pmSourceExtendedPars.h
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-01-02 20:39:04 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+# ifndef PM_SOURCE_EXTENDED_PARS_H
+# define PM_SOURCE_EXTENDED_PARS_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+typedef struct {
+  psVector *radius;
+  psVector *flux;
+  psVector *weight;
+} pmSourceRadialProfile;
+
+typedef struct {
+  psVector *flux;
+  psVector *fluxErr;
+  psVector *fluxVar;
+} pmSourceAnnuli;
+
+typedef struct {
+  float mag;
+  float magErr;
+  float rad;
+  float radErr;
+} pmSourceIsophotalValues;
+
+typedef struct {
+  float mag;
+  float magErr;
+  float rad;
+  float radErr;
+} pmSourcePetrosianValues;
+
+typedef struct {
+  float mag;
+  float magErr;
+  float rad;
+  float radErr;
+} pmSourceKronValues;
+
+typedef struct {
+  pmSourceRadialProfile   *profile;
+  pmSourceAnnuli          *annuli;
+  pmSourceIsophotalValues *isophot;
+  pmSourcePetrosianValues *petrosian;
+  pmSourceKronValues      *kron;
+} pmSourceExtendedPars;
+
+pmSourceExtendedPars *pmSourceExtendedParsAlloc ();
+bool psMemCheckSourceExtendedPars(psPtr ptr);
+pmSourceRadialProfile *pmSourceRadialProfileAlloc ();
+bool psMemCheckSourceRadialProfile(psPtr ptr);
+pmSourceIsophotalValues *pmSourceIsophotalValuesAlloc ();
+bool psMemCheckSourceIsophotalValues(psPtr ptr);
+pmSourcePetrosianValues *pmSourcePetrosianValuesAlloc ();
+bool psMemCheckSourcePetrosianValues(psPtr ptr);
+pmSourceKronValues *pmSourceKronValuesAlloc ();
+bool psMemCheckSourceKronValues(psPtr ptr);
+pmSourceAnnuli *pmSourceAnnuliAlloc ();
+bool psMemCheckSourceAnnuli(psPtr ptr);
+
+/// @}
+# endif /* PM_SOURCE_H */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceFitModel.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceFitModel.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceFitModel.c	(revision 22158)
@@ -0,0 +1,233 @@
+/** @file  pmSourceFitModel.c
+ *
+ *  fit single source models to image pixels
+ *
+ *  @author EAM, IfA
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.27 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-09-28 00:38:56 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmGrowthCurve.h"
+#include "pmResiduals.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmModelClass.h"
+#include "pmSourceFitModel.h"
+
+// save as static values so they may be set externally
+static psF32 PM_SOURCE_FIT_MODEL_NUM_ITERATIONS = 15;
+static psF32 PM_SOURCE_FIT_MODEL_TOLERANCE = 0.1;
+static psF32 PM_SOURCE_FIT_MODEL_WEIGHT = 1.0;
+static bool  PM_SOURCE_FIT_MODEL_PIX_WEIGHTS = true;
+
+bool pmSourceFitModelInit (float nIter, float tol, float weight, bool poissonErrors)
+{
+
+    PM_SOURCE_FIT_MODEL_NUM_ITERATIONS = nIter;
+    PM_SOURCE_FIT_MODEL_TOLERANCE = tol;
+    PM_SOURCE_FIT_MODEL_WEIGHT = weight;
+    PM_SOURCE_FIT_MODEL_PIX_WEIGHTS = poissonErrors;
+
+    return true;
+}
+
+bool pmSourceFitModel (pmSource *source,
+                       pmModel *model,
+                       pmSourceFitMode mode,
+                       psMaskType maskVal)
+{
+    psTrace("psModules.objects", 5, "---- %s begin ----\n", __func__);
+    PS_ASSERT_PTR_NON_NULL(source, false);
+    PS_ASSERT_PTR_NON_NULL(source->pixels, false);
+    PS_ASSERT_PTR_NON_NULL(source->maskObj, false);
+    PS_ASSERT_PTR_NON_NULL(source->weight, false);
+
+    psBool fitStatus = true;
+    psBool onPic     = true;
+    psBool rc        = true;
+
+    // maximum number of valid pixels
+    psS32 nPix = source->pixels->numRows * source->pixels->numCols;
+
+    // arrays to hold the data to be fitted
+    psArray *x = psArrayAllocEmpty(nPix);
+    psVector *y = psVectorAllocEmpty(nPix, PS_TYPE_F32);
+    psVector *yErr = psVectorAllocEmpty(nPix, PS_TYPE_F32);
+
+    // fill in the coordinate and value entries
+    nPix = 0;
+    for (psS32 i = 0; i < source->pixels->numRows; i++) {
+        for (psS32 j = 0; j < source->pixels->numCols; j++) {
+            // skip masked points
+            if (source->maskObj->data.U8[i][j] & maskVal) {
+                continue;
+            }
+            // skip zero-weight points
+            if (source->weight->data.F32[i][j] == 0) {
+                continue;
+            }
+            // skip nan values in image
+            if (!isfinite(source->pixels->data.F32[i][j])) {
+                continue;
+            }
+
+            psVector *coord = psVectorAlloc(2, PS_TYPE_F32);
+
+            // Convert i/j to image space:
+            coord->data.F32[0] = (psF32) (j + source->pixels->col0);
+            coord->data.F32[1] = (psF32) (i + source->pixels->row0);
+            x->data[nPix] = (psPtr *) coord;
+            y->data.F32[nPix] = source->pixels->data.F32[i][j];
+
+            // psMinimizeLMChi2 takes wt = 1/dY^2.  suggestion from RHL is to use the local sky
+            // as weight to avoid the bias from systematic errors here we would just use the
+            // source sky variance
+            if (PM_SOURCE_FIT_MODEL_PIX_WEIGHTS) {
+                yErr->data.F32[nPix] = 1.0 / source->weight->data.F32[i][j];
+            } else {
+                yErr->data.F32[nPix] = 1.0 / PM_SOURCE_FIT_MODEL_WEIGHT;
+            }
+            nPix++;
+        }
+    }
+    x->n = nPix;
+    y->n = nPix;
+    yErr->n = nPix;
+
+    psVector *params = model->params;
+    psVector *dparams = model->dparams;
+
+    // create the minimization constraints
+    psMinConstraint *constraint = psMinConstraintAlloc();
+    constraint->paramMask = psVectorAlloc (params->n, PS_TYPE_U8);
+    constraint->checkLimits = model->modelLimits;
+
+    // set parameter mask based on fitting mode
+    int nParams = 0;
+    switch (mode) {
+    case PM_SOURCE_FIT_NORM:
+        // NORM-only model fits only source normalization (Io)
+        nParams = 1;
+        psVectorInit (constraint->paramMask, 1);
+        constraint->paramMask->data.U8[PM_PAR_I0] = 0;
+        break;
+    case PM_SOURCE_FIT_PSF:
+        // PSF model only fits x,y,Io
+        nParams = 3;
+        psVectorInit (constraint->paramMask, 1);
+        constraint->paramMask->data.U8[PM_PAR_I0] = 0;
+        constraint->paramMask->data.U8[PM_PAR_XPOS] = 0;
+        constraint->paramMask->data.U8[PM_PAR_YPOS] = 0;
+        break;
+    case PM_SOURCE_FIT_EXT:
+        // EXT model fits all params (except sky)
+        nParams = params->n - 1;
+        psVectorInit (constraint->paramMask, 0);
+        constraint->paramMask->data.U8[PM_PAR_SKY] = 1;
+        break;
+    default:
+        psAbort("invalid fitting mode");
+    }
+    // force the floating parameters to fall within the contraint ranges
+    for (int i = 0; i < params->n; i++) {
+        model->modelLimits (PS_MINIMIZE_PARAM_MIN, i, params->data.F32, NULL);
+        model->modelLimits (PS_MINIMIZE_PARAM_MAX, i, params->data.F32, NULL);
+    }
+
+    if (nPix <  nParams + 1) {
+        psTrace ("psModules.objects", 4, "insufficient valid pixels\n");
+        model->flags |= PM_MODEL_STATUS_BADARGS;
+        psFree (x);
+        psFree (y);
+        psFree (yErr);
+        psFree (constraint);
+        return(false);
+    }
+
+    psMinimization *myMin = psMinimizationAlloc (PM_SOURCE_FIT_MODEL_NUM_ITERATIONS, PM_SOURCE_FIT_MODEL_TOLERANCE);
+
+    psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F32);
+
+    fitStatus = psMinimizeLMChi2(myMin, covar, params, constraint, x, y, yErr, model->modelFunc);
+    for (int i = 0; i < dparams->n; i++) {
+        if (psTraceGetLevel("psModules.objects") >= 4) {
+            fprintf (stderr, "%f ", params->data.F32[i]);
+        }
+        if ((constraint->paramMask != NULL) && constraint->paramMask->data.U8[i])
+            continue;
+        dparams->data.F32[i] = sqrt(covar->data.F32[i][i]);
+    }
+    psTrace ("psModules.objects", 4, "niter: %d, chisq: %f", myMin->iter, myMin->value);
+
+    // save the resulting chisq, nDOF, nIter
+    model->chisq = myMin->value;
+    model->nIter = myMin->iter;
+    model->nDOF  = y->n - nParams;
+    model->flags |= PM_MODEL_STATUS_FITTED;
+    if (!fitStatus) model->flags |= PM_MODEL_STATUS_NONCONVERGE;
+
+    // get the Gauss-Newton distance for fixed model parameters
+    // hold the fitted parameters fixed; mask sky which is not fitted at all
+    if (constraint->paramMask != NULL) {
+        psVector *delta = psVectorAlloc (params->n, PS_TYPE_F32);
+        psVector *altmask = psVectorAlloc (params->n, PS_TYPE_U8);
+        altmask->data.U8[0] = 1;
+        for (int i = 1; i < dparams->n; i++) {
+            altmask->data.U8[i] = (constraint->paramMask->data.U8[i]) ? 0 : 1;
+        }
+        psMinimizeGaussNewtonDelta(delta, params, altmask, x, y, yErr, model->modelFunc);
+
+        for (int i = 0; i < dparams->n; i++) {
+            if (!constraint->paramMask->data.U8[i])
+                continue;
+            // note that delta is the value *subtracted* from the parameter
+            // to get the new guess.  for dparams to represent the direction
+            // of motion, we need to take -delta
+            dparams->data.F32[i] = -delta->data.F32[i];
+        }
+        psFree (delta);
+        psFree (altmask);
+    }
+
+    // models can go insane: reject these
+    onPic &= (params->data.F32[PM_PAR_XPOS] >= source->pixels->col0);
+    onPic &= (params->data.F32[PM_PAR_XPOS] <  source->pixels->col0 + source->pixels->numCols);
+    onPic &= (params->data.F32[PM_PAR_YPOS] >= source->pixels->row0);
+    onPic &= (params->data.F32[PM_PAR_YPOS] <  source->pixels->row0 + source->pixels->numRows);
+    if (!onPic) {
+        model->flags |= PM_MODEL_STATUS_OFFIMAGE;
+    }
+
+    source->mode |= PM_SOURCE_MODE_FITTED;
+
+    psFree(x);
+    psFree(y);
+    psFree(yErr);
+    psFree(myMin);
+    psFree(covar);
+    psFree(constraint);
+
+    rc = (onPic && fitStatus);
+    psTrace("psModules.objects", 5, "---- %s(%d) end ----\n", __func__, rc);
+    return(rc);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceFitModel.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceFitModel.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceFitModel.h	(revision 22158)
@@ -0,0 +1,78 @@
+/* @file  pmSourceFitModel.h
+ *
+ * @author EAM, IfA; GLG, MHPCC
+ *
+ * @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-06-20 02:22:26 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+# ifndef PM_SOURCE_FIT_MODEL_H
+# define PM_SOURCE_FIT_MODEL_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+typedef enum {
+    PM_SOURCE_FIT_NORM,
+    PM_SOURCE_FIT_PSF,
+    PM_SOURCE_FIT_EXT,
+    PM_SOURCE_FIT_PSF_AND_SKY,
+    PM_SOURCE_FIT_EXT_AND_SKY
+} pmSourceFitMode;
+
+bool pmSourceFitModelInit(
+    float nIter,   ///< max number of allowed iterations
+    float tol,      ///< convergence criterion
+    float weight,      ///< use this weight for constant-weight fits
+    bool poissonErrors   // use poisson errors for fits?
+);
+
+/** pmSourceFitModel()
+ *
+ * Fit the requested model to the specified source. The starting guess for the model is given
+ * by the input source.model parameter values. The pixels of interest are specified by the
+ * source.pixels and source.mask entries. This function calls psMinimizeLMChi2() on the image
+ * data. The function returns TRUE on success or FALSE on failure.
+ *
+ */
+bool pmSourceFitModel(
+    pmSource *source,   ///< The input pmSource
+    pmModel *model,   ///< model to be fitted
+    pmSourceFitMode mode,  ///< define parameters to be fitted
+    psMaskType maskVal                  ///< Value to mask
+);
+
+
+// initialize data for a group of object models
+bool pmSourceFitSetInit (pmModelType type);
+
+// clear data for a group of object models
+void pmSourceFitSetClear (void);
+
+// function used to set limits for a group of models
+bool pmSourceFitSet_CheckLimits (psMinConstraintMode mode, int nParam, float *params, float *betas);
+
+// function used to fit a group of object models
+psF32 pmSourceFitSet_Function(psVector *deriv,
+                              const psVector *params,
+                              const psVector *x);
+
+/** pmSourceFitSet()
+ *
+ * Fit the requested model to the specified source. The starting guess for the model is given
+ * by the input source.model parameter values. The pixels of interest are specified by the
+ * source.pixels and source.mask entries. This function calls psMinimizeLMChi2() on the image
+ * data. The function returns TRUE on success or FALSE on failure.
+ *
+ */
+bool pmSourceFitSet(
+    pmSource *source,   ///< The input pmSource
+    psArray *modelSet,   ///< model to be fitted
+    pmSourceFitMode mode,  ///< define parameters to be fitted
+    psMaskType maskVal                  ///< Vale to mask
+
+);
+
+/// @}
+# endif /* PM_SOURCE_FIT_MODEL_H */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceFitSet.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceFitSet.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceFitSet.c	(revision 22158)
@@ -0,0 +1,495 @@
+/** @file  pmSourceFitModel.c
+ *
+ *  fit single source models to image pixels
+ *
+ *  @author EAM, IfA
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-01-02 20:39:04 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmGrowthCurve.h"
+#include "pmResiduals.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmModelClass.h"
+#include "pmSourceFitModel.h"
+#include "pmSourceFitSet.h"
+
+// save as static values so they may be set externally
+static psF32 PM_SOURCE_FIT_MODEL_NUM_ITERATIONS = 15;
+static psF32 PM_SOURCE_FIT_MODEL_TOLERANCE = 0.1;
+static psF32 PM_SOURCE_FIT_MODEL_WEIGHT = 1.0;
+static bool  PM_SOURCE_FIT_MODEL_PIX_WEIGHTS = true;
+
+/********************* Source Model Set Functions ***************************/
+
+static pmSourceFitSetData *thisSet = NULL;
+
+static void pmSourceFitSetDataFree (pmSourceFitSetData *set) {
+    if (!set) return;
+
+    psFree (set->modelSet);
+    psFree (set->paramSet);
+    psFree (set->derivSet);
+    return;
+}
+
+pmSourceFitSetData *pmSourceFitSetDataAlloc (psArray *modelSet) {
+    PS_ASSERT_PTR_NON_NULL(modelSet, NULL);
+
+    pmSourceFitSetData *set = (pmSourceFitSetData *) psAlloc(sizeof(pmSourceFitSetData));
+    psMemSetDeallocator(set, (psFreeFunc) pmSourceFitSetDataFree);
+
+    set->modelSet = psMemIncrRefCounter (modelSet);
+    set->paramSet = psArrayAlloc (modelSet->n);
+    set->derivSet = psArrayAlloc (modelSet->n);
+    set->nParamSet = 0;
+
+    for (int i = 0; i < modelSet->n; i++) {
+        pmModel *model = modelSet->data[i];
+
+        int nParams = pmModelClassParameterCount (model->type);
+
+        set->paramSet->data[i] = psVectorCopy (NULL, model->params, PS_DATA_F32);
+        set->derivSet->data[i] = psVectorAlloc (nParams, PS_DATA_F32);
+        psVectorInit (set->derivSet->data[i], 0.0);
+
+        set->nParamSet += nParams;
+    }
+
+    return set;
+}
+
+bool psMemCheckSourceFitSetData(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmSourceFitSetDataFree);
+}
+
+
+// this function is called with the full set of parameters and the beta values in a single vector
+bool pmSourceFitSetCheckLimits (psMinConstraintMode mode, int nParam, float *params,
+                                float *betas)
+{
+    PS_ASSERT_PTR_NON_NULL(thisSet, false);
+
+    // nParam is the parameter in the full sequence.  determine which single model this comes from
+    int nModel = -1;
+    int nParamOne = -1;
+    int nParamBase = 0;
+    for (int i = 0; i < thisSet->modelSet->n; i++) {
+        psVector *param = thisSet->paramSet->data[i];
+        if ((nParamBase <= nParam) && (nParam < nParamBase + param->n)) {
+            nModel = i;
+            nParamOne = nParam - nParamBase;
+            break;
+        }
+        nParamBase += param->n;
+    }
+    assert (nModel > -1);
+
+    pmModel *model = thisSet->modelSet->data[nModel];
+
+    // pass the single model function a pointer to the start of that model's sequence
+    float *paramOne = params + nParamBase;
+    float *betaOne = betas + nParamBase;
+    bool status = model->modelLimits (mode, nParamOne, paramOne, betaOne);
+    return status;
+}
+
+// merge parameters from FitSet models into single param and deriv vectors
+bool pmSourceFitSetJoin (psVector *deriv, psVector *param, pmSourceFitSetData *set)
+{
+    PS_ASSERT_PTR_NON_NULL(set, false);
+    PS_ASSERT_PTR_NON_NULL(set->paramSet, false);
+    PS_ASSERT_PTR_NON_NULL(set->derivSet, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(set->paramSet, set->derivSet, false);
+    int n = 0;
+    int sum = 0;
+    for (int i = 0; i < set->paramSet->n; i++) {
+        sum+= set->paramSet->n;
+    }
+
+    // Must assert that the deriv and param psVectors are large enough, or else
+    // a seg fault occurs.
+    // XXX: Put the correct error call in here:
+    if (0) {
+        if (deriv->n < sum || param->n < sum) {
+            PS_ASSERT_PTR_NON_NULL(0, false);
+        }
+    }
+
+    for (int i = 0; i < set->paramSet->n; i++) {
+
+        psVector *paramOne = set->paramSet->data[i];
+        psVector *derivOne = set->derivSet->data[i];
+
+	// one or the other (param or deriv) must be set
+	assert ((deriv != NULL) || (param != NULL));
+
+	// if we are setting derive, derivOne and paramOne must be same length
+        assert ((deriv == NULL) || (paramOne->n == derivOne->n));
+	
+        for (int j = 0; j < paramOne->n; j++, n++) {
+	    if (param) {
+		param->data.F32[n] = paramOne->data.F32[j];
+	    }
+            if (deriv) {
+                deriv->data.F32[n] = derivOne->data.F32[j];
+            }
+        }
+    }
+    return true;
+}
+
+// distribute parameters from single param and deriv vectors into FitSet models
+bool pmSourceFitSetSplit (pmSourceFitSetData *set, const psVector *deriv, const psVector *param) 
+{
+    PS_ASSERT_VECTOR_NON_NULL(param, false);
+    PS_ASSERT_PTR_NON_NULL(set, false);
+    PS_ASSERT_PTR_NON_NULL(set->paramSet, false);
+    PS_ASSERT_PTR_NON_NULL(set->derivSet, false);
+    PS_ASSERT_VECTORS_SIZE_EQUAL(set->paramSet, set->derivSet, false);
+
+    int n = 0;
+    for (int i = 0; i < set->paramSet->n; i++) {
+
+        psVector *paramOne = set->paramSet->data[i];
+        psVector *derivOne = set->derivSet->data[i];
+        assert ((deriv == NULL) || (paramOne->n == derivOne->n));
+
+        for (int j = 0; j < paramOne->n; j++, n++) {
+            paramOne->data.F32[j] = param->data.F32[n];
+            if (deriv) {
+                derivOne->data.F32[j] = deriv->data.F32[n];
+            }
+        }
+    }
+    return true;
+}
+
+bool pmSourceFitSetValues (pmSourceFitSetData *set, const psVector *dparam, 
+                           const psVector *param, pmSource *source,
+                           psMinimization *myMin, int nPix, bool fitStatus)
+{
+    PS_ASSERT_PTR_NON_NULL(set, false);
+    PS_ASSERT_PTR_NON_NULL(set->paramSet, false);
+    PS_ASSERT_VECTOR_NON_NULL(dparam, false);
+    PS_ASSERT_VECTOR_NON_NULL(param, false);
+    PS_ASSERT_PTR_NON_NULL(source, false);
+    PS_ASSERT_PTR_NON_NULL(source->pixels, false);
+    PS_ASSERT_PTR_NON_NULL(myMin, false);
+
+    bool onPic = true;
+
+    int n = 0;
+    for (int i = 0; i < set->paramSet->n; i++) {
+
+        pmModel *model = set->modelSet->data[i];
+
+        for (int j = 0; j < model->params->n; j++, n++) {
+            if (psTraceGetLevel("psModules.objects") >= 4) {
+                fprintf (stderr, "%f ", param->data.F32[n]);
+            }
+            model->params->data.F32[j] = param->data.F32[n];
+            model->dparams->data.F32[j] = dparam->data.F32[n];
+        }
+        psTrace ("psModules.objects", 4, " src %d", i);
+
+        // save the resulting chisq, nDOF, nIter
+        // these are not unique for any one source
+        model->chisq = myMin->value;
+        model->nIter = myMin->iter;
+        model->nDOF  = nPix - model->params->n;
+
+        // set the model success or failure status
+        model->flags |= PM_MODEL_STATUS_FITTED;
+        if (!fitStatus) model->flags |= PM_MODEL_STATUS_NONCONVERGE;
+
+        // models can go insane: reject these
+        onPic &= (model->params->data.F32[PM_PAR_XPOS] >= source->pixels->col0);
+        onPic &= (model->params->data.F32[PM_PAR_XPOS] <  source->pixels->col0 + source->pixels->numCols);
+        onPic &= (model->params->data.F32[PM_PAR_XPOS] >= source->pixels->row0);
+        onPic &= (model->params->data.F32[PM_PAR_XPOS] <  source->pixels->row0 + source->pixels->numRows);
+        if (!onPic) model->flags |= PM_MODEL_STATUS_OFFIMAGE;
+    }
+    return true;
+}
+
+// generic psMinLMM-style function for fitting: split the parameters across the models, call
+// each model function one-at-a-time, the join the derivatives for on-going evaluation
+psF32 pmSourceFitSetFunction(psVector *deriv, const psVector *param, const psVector *x)
+{
+    PS_ASSERT_PTR_NON_NULL(thisSet, NAN);
+    float chisqSum = 0.0;
+    float chisqOne = 0.0;
+    pmSourceFitSetSplit (thisSet, deriv, param);
+
+    for (int i = 0; i < thisSet->modelSet->n; i++) {
+
+        pmModel *model = thisSet->modelSet->data[i];
+
+        psVector *paramOne = thisSet->paramSet->data[i];
+        psVector *derivOne = thisSet->derivSet->data[i];
+
+        chisqOne = model->modelFunc (derivOne, paramOne, x);
+        chisqSum += chisqOne;
+    }
+    pmSourceFitSetJoin (deriv, NULL, thisSet);
+
+    return (chisqSum);
+}
+
+// XXX allow the mode to be a function of the object (eg, S/N)
+bool pmSourceFitSetMasks (psMinConstraint *constraint, pmSourceFitSetData *set,
+                          pmSourceFitMode mode)
+{
+    PS_ASSERT_PTR_NON_NULL(set, false);
+    PS_ASSERT_PTR_NON_NULL(constraint, false);
+
+    // unmask everyone
+    psVectorInit (constraint->paramMask, 0);
+
+    int n = 0;
+    for (int i = 0; i < set->paramSet->n; i++) {
+        psVector *paramOne = set->paramSet->data[i];
+
+        switch (mode) {
+          case PM_SOURCE_FIT_NORM:
+            // mask all but Xo,Yo,Io
+            for (int j = 0; j < paramOne->n; j++) {
+                if (j == PM_PAR_I0) continue;
+                constraint->paramMask->data.U8[n + j] = 1;
+            }
+            break;
+          case PM_SOURCE_FIT_PSF:
+            // mask all but Xo,Yo,Io
+            for (int j = 0; j < paramOne->n; j++) {
+                if (j == PM_PAR_XPOS) continue;
+                if (j == PM_PAR_YPOS) continue;
+                if (j == PM_PAR_I0) continue;
+                constraint->paramMask->data.U8[n + j] = 1;
+            }
+            break;
+          case PM_SOURCE_FIT_EXT:
+            // EXT model fits all params (except sky)
+            constraint->paramMask->data.U8[n + PM_PAR_SKY] = 1;
+            break;
+          default:
+            psAbort("invalid fitting mode");
+        }
+        n += paramOne->n;
+    }
+    return true;
+}
+
+bool pmSourcePrintModelSet (FILE *file, psArray *modelSet) {
+
+    for (int i = 0; i < modelSet->n; i++) {
+	pmModel *model = modelSet->data[i];
+	int nParams = pmModelClassParameterCount (model->type);
+	for (int j = 0; j < nParams; j++) {
+	    fprintf (file, "%d %d  : %f %f\n", i, j, model->params->data.F32[j], model->dparams->data.F32[j]);
+	}
+    }
+    return true;
+}
+
+bool pmSourceFitSetPrint (FILE *file, pmSourceFitSetData *set) {
+
+    for (int i = 0; i < set->paramSet->n; i++) {
+        psVector *paramOne = set->paramSet->data[i];
+        psVector *derivOne = set->derivSet->data[i];
+        for (int j = 0; j < paramOne->n; j++) {
+	    fprintf (file, "%d %d  : %f %f\n", i, j, paramOne->data.F32[j], derivOne->data.F32[j]);
+        }
+    }
+    return true;
+}
+
+bool pmSourceFitSet (pmSource *source,
+                     psArray *modelSet,
+                     pmSourceFitMode mode,
+                     psMaskType maskVal)
+{
+    psTrace("psModules.objects", 3, "---- %s begin ----\n", __func__);
+    PS_ASSERT_PTR_NON_NULL(source, false);
+    PS_ASSERT_PTR_NON_NULL(source->pixels, false);
+    PS_ASSERT_PTR_NON_NULL(source->maskObj, false);
+    PS_ASSERT_PTR_NON_NULL(source->weight, false);
+
+    bool fitStatus = true;
+    bool onPic     = true;
+
+    // maximum number of valid pixels
+    int nPix = source->pixels->numRows * source->pixels->numCols;
+
+    // construct the coordinate and value entries
+    psArray *x = psArrayAllocEmpty(nPix);
+    psVector *y = psVectorAllocEmpty(nPix, PS_TYPE_F32);
+    psVector *yErr = psVectorAllocEmpty(nPix, PS_TYPE_F32);
+
+    // fill in the coordinate and value entries
+    nPix = 0;
+    for (psS32 i = 0; i < source->pixels->numRows; i++) {
+        for (psS32 j = 0; j < source->pixels->numCols; j++) {
+            // skip masked points
+            if (source->maskObj->data.U8[i][j] & maskVal) {
+                continue;
+            }
+            // skip zero-weight points
+            if (source->weight->data.F32[i][j] == 0) {
+                continue;
+            }
+            // skip nan values in image
+            if (!isfinite(source->pixels->data.F32[i][j])) {
+                continue;
+            }
+
+            psVector *coord = psVectorAlloc(2, PS_TYPE_F32);
+
+            // Convert i/j to image space:
+            coord->data.F32[0] = (psF32) (j + source->pixels->col0);
+            coord->data.F32[1] = (psF32) (i + source->pixels->row0);
+            x->data[nPix] = (psPtr *) coord;
+            y->data.F32[nPix] = source->pixels->data.F32[i][j];
+
+            // psMinimizeLMChi2 takes wt = 1/dY^2.  suggestion from RHL is to use the local sky
+            // as weight to avoid the bias from systematic errors here we would just use the
+            // source sky variance
+            if (PM_SOURCE_FIT_MODEL_PIX_WEIGHTS) {
+                yErr->data.F32[nPix] = 1.0 / source->weight->data.F32[i][j];
+            } else {
+                yErr->data.F32[nPix] = 1.0 / PM_SOURCE_FIT_MODEL_WEIGHT;
+            }
+            nPix++;
+        }
+    }
+    x->n = nPix;
+    y->n = nPix;
+    yErr->n = nPix;
+
+    // create the FitSet and set the initial parameter guesses
+    thisSet = pmSourceFitSetDataAlloc (modelSet);
+
+    // define param and deriv vectors for complete set of parameters
+    psVector *params = psVectorAlloc (thisSet->nParamSet, PS_TYPE_F32);
+
+    // set the param and deriv vectors based on the curent values
+    pmSourceFitSetJoin (NULL, params, thisSet);
+
+    // create the minimization constraints
+    psMinConstraint *constraint = psMinConstraintAlloc();
+    constraint->paramMask = psVectorAlloc (thisSet->nParamSet, PS_TYPE_U8);
+    constraint->checkLimits = pmSourceFitSetCheckLimits;
+
+    pmSourceFitSetMasks (constraint, thisSet, mode);
+
+    // force the floating parameters to fall within the contraint ranges
+    for (int i = 0; i < params->n; i++) {
+        pmSourceFitSetCheckLimits (PS_MINIMIZE_PARAM_MIN, i, params->data.F32, NULL);
+        pmSourceFitSetCheckLimits (PS_MINIMIZE_PARAM_MAX, i, params->data.F32, NULL);
+    }
+
+    if (psTraceGetLevel("psModules.objects") >= 5) {
+        for (int i = 0; i < params->n; i++) {
+            fprintf (stderr, "%d %f %d\n", i, params->data.F32[i], constraint->paramMask->data.U8[i]);
+        }
+    }
+
+    if (nPix <  thisSet->nParamSet + 1) {
+        psTrace (__func__, 4, "insufficient valid pixels\n");
+        psTrace("psModules.objects", 3, "---- %s() end : fail pixels ----\n", __func__);
+        for (int i = 0; i < modelSet->n; i++) {
+            pmModel *model = modelSet->data[i];
+            model->flags |= PM_MODEL_STATUS_BADARGS;
+        }
+        psFree (x);
+        psFree (y);
+        psFree (yErr);
+        psFree (params);
+        psFree(constraint);
+        psFree (thisSet);
+        thisSet = NULL;
+        return(false);
+    }
+
+    psMinimization *myMin = psMinimizationAlloc (PM_SOURCE_FIT_MODEL_NUM_ITERATIONS, PM_SOURCE_FIT_MODEL_TOLERANCE);
+
+    psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F32);
+
+    fitStatus = psMinimizeLMChi2(myMin, covar, params, constraint, x, y, yErr, pmSourceFitSetFunction);
+    if (!fitStatus) {
+        psTrace("psModules.objects", 4, "Failed to fit model (%ld components)\n", modelSet->n);
+    }
+
+    // parameter errors from the covariance matrix
+    psVector *dparams = psVectorAlloc (thisSet->nParamSet, PS_TYPE_F32);
+    for (int i = 0; i < dparams->n; i++) {
+        if ((constraint->paramMask != NULL) && constraint->paramMask->data.U8[i])
+            continue;
+        dparams->data.F32[i] = sqrt(covar->data.F32[i][i]);
+    }
+
+    // get the Gauss-Newton distance for fixed model parameters
+    if (constraint->paramMask != NULL) {
+        psVector *delta = psVectorAlloc (params->n, PS_TYPE_F32);
+        psVector *altmask = psVectorAlloc (params->n, PS_TYPE_U8);
+        altmask->data.U8[0] = 1;
+        for (int i = 1; i < dparams->n; i++) {
+            altmask->data.U8[i] = (constraint->paramMask->data.U8[i]) ? 0 : 1;
+        }
+        psMinimizeGaussNewtonDelta(delta, params, altmask, x, y, yErr, pmSourceFitSetFunction);
+
+        for (int i = 0; i < dparams->n; i++) {
+            if (!constraint->paramMask->data.U8[i])
+                continue;
+            // note that delta is the value *subtracted* from the parameter
+            // to get the new guess.  for dparams to represent the direction
+            // of motion, we need to take -delta
+            dparams->data.F32[i] = -delta->data.F32[i];
+        }
+        psFree (delta);
+        psFree (altmask);
+    }
+
+    pmSourceFitSetValues (thisSet, dparams, params, source, myMin, y->n, fitStatus);
+    psTrace ("psModules.objects", 5, "onPic: %d, fitStatus: %d, nIter: %d, chisq: %f, nPix: %ld\n", onPic, fitStatus, myMin->iter, myMin->value, y->n);
+
+    source->mode |= PM_SOURCE_MODE_FITTED;
+
+    psFree(x);
+    psFree(y);
+    psFree(yErr);
+    psFree(myMin);
+    psFree(covar);
+    psFree(constraint);
+    psFree(params);
+    psFree(dparams);
+    psFree(thisSet);
+
+    thisSet = NULL;
+
+    bool rc = (onPic && fitStatus);
+    psTrace("psModules.objects", 5, "---- %s end (%d) ----\n", __func__, rc);
+    return(rc);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceFitSet.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceFitSet.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceFitSet.h	(revision 22158)
@@ -0,0 +1,57 @@
+/* @file  pmSourceFitSet.h
+ *
+ * @author EAM, IfA; GLG, MHPCC
+ *
+ * @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+# ifndef PM_SOURCE_FIT_SET_H
+# define PM_SOURCE_FIT_SET_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+typedef struct {
+    psArray *modelSet;
+    psArray *paramSet;
+    psArray *derivSet;
+    int nParamSet;
+} pmSourceFitSetData;
+
+// initialize data for a group of object models
+pmSourceFitSetData *pmSourceFitSetDataAlloc (psArray *modelSet);
+bool psMemCheckSourceFitSetData(psPtr ptr);
+
+// function used to set limits for a group of models
+bool pmSourceFitSetCheckLimits (psMinConstraintMode mode, int nParam, float *params, float *betas);
+
+bool pmSourceFitSetJoin (psVector *deriv, psVector *param, pmSourceFitSetData *set);
+bool pmSourceFitSetSplit (pmSourceFitSetData *set, const psVector *deriv, const psVector *param);
+bool pmSourceFitSetValues (pmSourceFitSetData *set, const psVector *dparam, const psVector *param, pmSource *source, psMinimization *myMin, int nPix, bool fitStatus);
+
+psF32 pmSourceFitSetFunction(psVector *deriv, const psVector *param, const psVector *x);
+bool pmSourceFitSetMasks (psMinConstraint *constraint, pmSourceFitSetData *set, pmSourceFitMode mode);
+
+/** pmSourceFitSet()
+ *
+ * Fit the requested model to the specified source. The starting guess for the model is given
+ * by the input source.model parameter values. The pixels of interest are specified by the
+ * source.pixels and source.mask entries. This function calls psMinimizeLMChi2() on the image
+ * data. The function returns TRUE on success or FALSE on failure.
+ *
+ */
+bool pmSourceFitSet(
+    pmSource *source,   ///< The input pmSource
+    psArray *modelSet,   ///< model to be fitted
+    pmSourceFitMode mode,  ///< define parameters to be fitted
+    psMaskType maskVal                  ///< Vale to mask
+
+);
+
+bool pmSourcePrintModelSet (FILE *file, psArray *modelSet);
+bool pmSourceFitSetPrint (FILE *file, pmSourceFitSetData *set);
+
+/// @}
+# endif /* PM_SOURCE_FIT_MODEL_H */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO.c	(revision 22158)
@@ -0,0 +1,1004 @@
+/** @file  pmSourceIO.c
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.63 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-17 22:38:15 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <strings.h>            /* for strn?casecmp */
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+#include "pmFPAfileFitsIO.h"
+#include "pmConcepts.h"
+
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmGrowthCurve.h"
+#include "pmResiduals.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmModelClass.h"
+#include "pmSourceIO.h"
+
+#define BLANK_HEADERS "BLANK.HEADERS"   // Name of metadata in camera configuration containing header names
+                                        // for putting values into a blank PHU
+
+// translations between psphot object types and dophot object types
+int pmSourceGetDophotType (pmSource *source)
+{
+    PS_ASSERT_PTR_NON_NULL(source, -1);
+
+    switch (source->type) {
+
+      case PM_SOURCE_TYPE_DEFECT:
+      case PM_SOURCE_TYPE_SATURATED:
+        return (8);
+
+      case PM_SOURCE_TYPE_STAR:
+        if (source->mode & PM_SOURCE_MODE_SATSTAR)
+            return (10);
+        if (source->mode & PM_SOURCE_MODE_POOR)
+            return (7);
+        if (source->mode & PM_SOURCE_MODE_FAIL)
+            return (4);
+        return (1);
+
+      case PM_SOURCE_TYPE_EXTENDED:
+        return (2);
+
+      default:
+        return (0);
+    }
+    return (0);
+}
+
+// translations between psphot object types and dophot object types
+bool pmSourceSetDophotType (pmSource *source, int type)
+{
+    PS_ASSERT_PTR_NON_NULL(source, false);
+
+    if (type == 4) {
+        source->mode |= PM_SOURCE_MODE_FAIL;
+    }
+    if (type == 7) {
+        source->mode |= PM_SOURCE_MODE_POOR;
+    }
+    if (type == 10) {
+        source->mode |= PM_SOURCE_MODE_SATSTAR;
+    }
+
+    switch (type) {
+      case 1:
+      case 4:
+      case 7:
+      case 10:
+        source->type = PM_SOURCE_TYPE_STAR;
+        return true;
+      case 2:
+        source->type = PM_SOURCE_TYPE_EXTENDED;
+        return true;
+      case 8:
+        source->type = PM_SOURCE_TYPE_DEFECT;
+        return true;
+      default:
+        return false;
+    }
+    return false;
+}
+
+// Given a FITS file pointer, write the table of object data
+bool pmFPAviewWriteObjects (const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, false); // Suitable FPA for writing
+
+    if (view->chip == -1) {
+        if (!pmFPAWriteObjects (fpa, view, file, config)) {
+            psError(PS_ERR_IO, false, "Failed to write objects from fpa");
+            psFree(fpa);
+            return false;
+        }
+        psFree(fpa);
+        return true;
+    }
+
+    if (view->chip >= fpa->chips->n) {
+        psError(PS_ERR_UNKNOWN, false, "Writing chip == %d (>= chips->n == %ld)", view->chip, fpa->chips->n);
+        psFree(fpa);
+        return false;
+    }
+    pmChip *chip = fpa->chips->data[view->chip];
+
+    if (view->cell == -1) {
+        if (!pmChipWriteObjects (chip, view, file, config)) {
+            psError(PS_ERR_IO, false, "Failed to write objects from chip");
+            psFree(fpa);
+            return false;
+        }
+        psFree(fpa);
+        return true;
+    }
+
+    if (view->cell >= chip->cells->n) {
+        psError(PS_ERR_UNKNOWN, false, "Writing cell == %d (>= cells->n == %ld)",
+                view->cell, chip->cells->n);
+        psFree(fpa);
+        return false;
+    }
+    pmCell *cell = chip->cells->data[view->cell];
+
+    if (view->readout == -1) {
+        if (!pmCellWriteObjects (cell, view, file, config)) {
+            psError(PS_ERR_IO, false, "Failed to write objects from cell");
+            psFree(fpa);
+            return false;
+        }
+        psFree(fpa);
+        return true;
+    }
+
+    if (view->readout >= cell->readouts->n) {
+        psError(PS_ERR_UNKNOWN, false, "Writing readout == %d (>= readouts->n == %ld)",
+                view->readout, cell->readouts->n);
+        psFree(fpa);
+        return false;
+    }
+    pmReadout *readout = cell->readouts->data[view->readout];
+
+    if (!pmReadoutWriteObjects (readout, view, file, config)) {
+        psError(PS_ERR_IO, false, "Failed to write objects from readout %d", view->readout);
+        psFree(fpa);
+        return false;
+    }
+
+    psFree(fpa);
+    return true;
+}
+
+// read in all chip-level Objects files for this FPA
+bool pmFPAWriteObjects (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(fpa->chips, false);
+
+    pmFPAview *thisView = pmFPAviewAlloc (view->nRows);
+    *thisView = *view;
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        thisView->chip = i;
+        if (!pmChipWriteObjects (chip, thisView, file, config)) {
+            psError(PS_ERR_IO, false, "Failed to write %dth chip", i);
+            psFree (thisView);
+            return false;
+        }
+    }
+    psFree (thisView);
+    return true;
+}
+
+// read in all cell-level Objects files for this chip
+bool pmChipWriteObjects (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_PTR_NON_NULL(chip->cells, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    pmFPAview *thisView = pmFPAviewAlloc (view->nRows);
+    *thisView = *view;
+
+    for (int i = 0; i < chip->cells->n; i++) {
+        pmCell *cell = chip->cells->data[i];
+        thisView->cell = i;
+        if (!pmCellWriteObjects (cell, thisView, file, config)) {
+            psError(PS_ERR_IO, false, "Failed to write %dth cell", i);
+            psFree (thisView);
+            return false;
+        }
+    }
+    psFree (thisView);
+    return true;
+}
+
+// read in all readout-level Objects files for this cell
+bool pmCellWriteObjects (pmCell *cell, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_PTR_NON_NULL(cell->readouts, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    pmFPAview *thisView = pmFPAviewAlloc (view->nRows);
+    *thisView = *view;
+
+    for (int i = 0; i < cell->readouts->n; i++) {
+        pmReadout *readout = cell->readouts->data[i];
+        thisView->readout = i;
+        if (!pmReadoutWriteObjects (readout, thisView, file, config)) {
+            psError(PS_ERR_IO, false, "Failed to write %dth readout", i);
+            psFree (thisView);
+            return false;
+        }
+    }
+    psFree (thisView);
+    return true;
+}
+
+// write out all readout-level Objects files for this cell
+bool pmReadoutWriteObjects (pmReadout *readout, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    pmCell *cell = readout->parent;
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    pmChip *chip = cell->parent;
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    pmFPA *fpa = chip->parent;
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+
+    bool status;
+    pmHDU *hdu;
+    psMetadata *updates;
+    psMetadata *outhead;
+
+    char *exttype  = NULL;
+    char *dataname = NULL;
+    char *xsrcname = NULL;
+    char *xfitname = NULL;
+    char *headname = NULL;
+
+    // if sources is NULL, write out an empty table
+    // input / output sources are stored on the readout->analysis as "PSPHOT.SOURCES" -- a better name might be something like PM_SOURCE_DATA
+    psArray *sources = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.SOURCES");
+    if (!sources) {
+        sources = psArrayAlloc(0);
+        psMetadataAddArray(readout->analysis, PS_LIST_TAIL, "PSPHOT.SOURCES", PS_META_REPLACE, "Blank array of sources", sources);
+        psFree(sources); // Held onto by the metadata, so we can continue to use
+    }
+
+    switch (file->type) {
+      case PM_FPA_FILE_RAW:
+        pmSourcesWriteRAW (sources, file->filename);
+        break;
+
+      case PM_FPA_FILE_OBJ:
+        pmSourcesWriteOBJ (sources, file->filename);
+        break;
+
+      case PM_FPA_FILE_SX:
+        pmSourcesWriteSX (sources, file->filename);
+        break;
+
+      case PM_FPA_FILE_CMP:
+        // a SPLIT format : only one header and object table per file
+        hdu = pmFPAviewThisHDU (view, fpa);
+        if (!hdu) {
+            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find HDU to write sources.");
+            return false;
+        }
+
+        // copy the header to an output header, add the output header data
+        outhead = psMetadataCopy (NULL, hdu->header);
+
+        // copy over the entries saved by PSPHOT
+        updates = psMetadataLookupPtr (NULL, readout->analysis, "PSPHOT.HEADER");
+        if (updates) {
+            psMetadataCopy (outhead, updates);
+        }
+
+        // copy over the entries saved by PSASTRO
+        updates = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.HEADER");
+        if (updates) {
+            psMetadataCopy (outhead, updates);
+        }
+
+        bool status = pmSourcesWriteCMP (sources, file->filename, outhead);
+        psFree (outhead);
+
+        if (!status) {
+            psError(PS_ERR_IO, false, "Failed to write CMP file\n");
+            return false;
+        }
+        break;
+
+      case PM_FPA_FILE_CMF:
+        // write a header? (only if this is the first readout for cell)
+        //   note that the file->header is set to track the last hdu->header written
+        // write the data? (always?)
+
+        // get the current header
+        hdu = pmFPAviewThisHDU (view, fpa);
+        if (!hdu) {
+            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find HDU to write sources.");
+            return false;
+        }
+
+        // determine the output table format
+        psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, "PSPHOT");
+        if (!status) {
+          psError(PS_ERR_UNKNOWN, true, "missing recipe PSPHOT in config data");
+          return false;
+        }
+
+        // if this is not TRUE, the output files only contain the psf measurements.
+        bool XSRC_OUTPUT = psMetadataLookupBool(&status, recipe, "EXTENDED_SOURCE_ANALYSIS");
+        bool XFIT_OUTPUT = psMetadataLookupBool(&status, recipe, "EXTENDED_SOURCE_FITS");
+
+        // define the EXTNAME values for the different data segments:
+        {
+            // lookup the EXTNAME values used for table data and image header segments
+            char *rule = NULL;
+
+            // Menu of EXTNAME rules
+            psMetadata *menu = psMetadataLookupMetadata(&status, file->camera, "EXTNAME.RULES");
+            if (!menu) {
+                psError(PS_ERR_UNKNOWN, true, "missing EXTNAME.RULES in camera.config");
+                return false;
+            }
+
+            // EXTNAME for image header
+            rule = psMetadataLookupStr(&status, menu, "CMF.HEAD");
+            if (!rule) {
+                psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.HEAD in EXTNAME.RULES in camera.config");
+                return false;
+            }
+            headname = pmFPAfileNameFromRule (rule, file, view);
+
+            // EXTNAME for table data
+            rule = psMetadataLookupStr(&status, menu, "CMF.DATA");
+            if (!rule) {
+                psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.DATA in EXTNAME.RULES in camera.config");
+                return false;
+            }
+            dataname = pmFPAfileNameFromRule (rule, file, view);
+
+            if (XSRC_OUTPUT) {
+              // EXTNAME for extended source data table
+              rule = psMetadataLookupStr(&status, menu, "CMF.XSRC");
+              if (!rule) {
+                psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.XSRC in EXTNAME.RULES in camera.config");
+                return false;
+              }
+              xsrcname = pmFPAfileNameFromRule (rule, file, view);
+            }
+            if (XFIT_OUTPUT) {
+              // EXTNAME for extended source data table
+              rule = psMetadataLookupStr(&status, menu, "CMF.XFIT");
+              if (!rule) {
+                psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.XFIT in EXTNAME.RULES in camera.config");
+                return false;
+              }
+              xfitname = pmFPAfileNameFromRule (rule, file, view);
+            }
+        }
+
+        // write out the IMAGE header segment (only for the first readout of the cell)
+        {
+            // this header block is new, write it to disk
+            if (hdu->header != file->header) {
+                // add EXTNAME, EXTHEAD, EXTTYPE to header
+                psMetadataAddStr (hdu->header, PS_LIST_TAIL, "EXTDATA", PS_META_REPLACE, "name of table extension", dataname);
+                psMetadataAddStr (hdu->header, PS_LIST_TAIL, "EXTTYPE", PS_META_REPLACE, "extension type", "IMAGE");
+                if (!file->wrote_phu) {
+                    // this hdu->header acts as the PHU: set EXTEND to be true
+                    psMetadataAddBool (hdu->header, PS_LIST_TAIL, "EXTEND", PS_META_REPLACE, "this file has extensions", true);
+                    file->wrote_phu = true;
+                }
+
+                // save psphot and psastro metadata in the image and table headers
+                updates = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.HEADER");
+                if (updates) {
+                    psMetadataCopy (hdu->header, updates);
+                }
+                updates = psMetadataLookupPtr (&status, readout->analysis, "PSASTRO.HEADER");
+                if (updates) {
+                    psMetadataCopy (hdu->header, updates);
+                }
+
+                pmConfigConformHeader(hdu->header, file->format);
+
+                psFitsWriteBlank (file->fits, hdu->header, headname);
+                psTrace ("pmFPAfile", 5, "wrote ext head %s (type: %d)\n", file->filename, file->type);
+                file->header = hdu->header;
+            }
+        }
+
+        // write out the TABLE data segment
+        {
+            // create a header to hold the output data
+            outhead = psMetadataAlloc ();
+
+            exttype = psMemIncrRefCounter (psMetadataLookupStr(&status, recipe, "OUTPUT.FORMAT"));
+            if (!exttype) {
+                exttype = psStringCopy ("SMPDATA");
+            }
+
+            // write the links to the image header
+            psMetadataAddStr (outhead, PS_LIST_TAIL, "EXTHEAD", PS_META_REPLACE, "name of image extension w/", headname);
+            psMetadataAddStr (outhead, PS_LIST_TAIL, "EXTTYPE", PS_META_REPLACE, "extension type", exttype);
+            psFree (exttype);
+
+            // if we request XSRC output, add the XSRC name to this header
+            if (xsrcname) {
+              psMetadataAddStr (outhead, PS_LIST_TAIL, "XSRCNAME", PS_META_REPLACE, "name of XSRC table extension", xsrcname);
+            }
+            if (xfitname) {
+              psMetadataAddStr (outhead, PS_LIST_TAIL, "XFITNAME", PS_META_REPLACE, "name of XFIT table extension", xfitname);
+            }
+
+            // XXX these are case-sensitive since the EXTYPE is case-sensitive
+            status = false;
+            if (!strcmp (exttype, "SMPDATA")) {
+                status = pmSourcesWrite_SMPDATA (file->fits, sources, file->header, outhead, dataname);
+            }
+            if (!strcmp (exttype, "PS1_DEV_0")) {
+                status = pmSourcesWrite_PS1_DEV_0 (file->fits, sources, file->header, outhead, dataname);
+            }
+            if (!strcmp (exttype, "PS1_DEV_1")) {
+                status = pmSourcesWrite_PS1_DEV_1 (file->fits, sources, file->header, outhead, dataname, xsrcname);
+            }
+            if (xsrcname) {
+              if (!strcmp (exttype, "PS1_DEV_1")) {
+                status = pmSourcesWrite_PS1_DEV_1_XSRC (file->fits, sources, xsrcname, recipe);
+              }
+            }
+            if (xfitname) {
+              if (!strcmp (exttype, "PS1_DEV_1")) {
+                status = pmSourcesWrite_PS1_DEV_1_XFIT (file->fits, sources, xfitname);
+              }
+            }
+            if (!status) {
+                psError(PS_ERR_IO, false, "writing CMF data to %s with format %s\n", file->filename, exttype);
+                psFree (headname);
+                psFree (dataname);
+                psFree (xsrcname);
+                psFree (xfitname);
+                psFree (outhead);
+                return false;
+            }
+        }
+
+        psTrace ("pmFPAfile", 5, "wrote ext data %s (type: %d)\n", file->filename, file->type);
+
+        psFree (headname);
+        psFree (dataname);
+        psFree (xsrcname);
+        psFree (xfitname);
+        psFree (outhead);
+        break;
+
+      default:
+        fprintf (stderr, "warning: type mismatch\n");
+        break;
+    }
+    return true;
+}
+// a MEF CMF file has: PHU, CELL-HEAD, TABLE, CELL-HEAD, TABLE, TABLE, TABLE...
+
+// if this file needs to have a PHU written out, write one
+bool pmSource_CMF_WritePHU (const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    bool status;
+
+    // not needed if already written
+    if (file->wrote_phu) return true;
+
+    // not needed if not FPA
+    // XXX this prevents us from defining a SPLIT/MEF CMF file...
+    if (file->fileLevel != PM_FPA_LEVEL_FPA) return true;
+
+    // not needed if only one chip
+    if (file->fpa->chips->n == 1) return true;
+
+
+    // find the FPA phu
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, false); // Suitable FPA for writing
+    pmHDU *phu = psMemIncrRefCounter(pmFPAviewThisPHU(view, fpa));
+
+    // if there is no PHU, this is a single header+image (extension-less) file. This could be
+    // the case for an input SPLIT set of files being written out as a MEF.  if there is a PHU,
+    // write it out as a 'blank'
+    psMetadata *outhead = psMetadataAlloc();
+    if (phu) {
+        psMetadataCopy (outhead, phu->header);
+    }
+    psFree(phu);
+
+    pmConfigConformHeader (outhead, file->format);
+
+    // We need to get some FPA-level concepts in there
+    // This is a hack, not very pretty.  But then, so is writing the FPA in this manner without
+    // using the pmFPAMosaic functions....
+    // XXX why are these not correctly inserted by pmConfigConformHeader??
+
+    // Because these concepts are not part of the "RULE" in the camera format, pmConfigConformHeader only adds
+    // what is required by the "RULE".
+    // Though we can configure Ohana to look at particular header keywords, it doesn't like having the
+    // important values in "HIERARCH FPA.TIME", etc, as is done for skycells, so we stoop to its level,
+    // putting in additional header keywords that it can understand.
+
+    psMetadata *headers = psMetadataLookupMetadata(NULL, fpa->camera, BLANK_HEADERS); // Header names
+    if (!headers) {
+        psError(PS_ERR_UNEXPECTED_NULL, false,
+                "Unable to find %s metadata within camera configuration", BLANK_HEADERS);
+        psFree(outhead);
+        psFree(fpa);
+        return false;
+    }
+
+    {
+        const char *mjdName = psMetadataLookupStr(NULL, headers, "FPA.TIME"); // Header name
+        if (!mjdName || strlen(mjdName) == 0) {
+            psError(PS_ERR_UNEXPECTED_NULL, false,
+                    "Unable to find FPA.TIME in %s within camera configuration.", BLANK_HEADERS);
+            psFree(outhead);
+            psFree(fpa);
+            return false;
+        }
+        psTime *time = psMetadataLookupTime(NULL, fpa->concepts, "FPA.TIME"); // Time of observation
+        double mjd = psTimeToMJD(time); // The MJD of observation
+        psMetadataAddF64(outhead, PS_LIST_TAIL, mjdName, PS_META_REPLACE,
+                         "Time of observation", mjd);
+    }
+
+    {
+        const char *expName = psMetadataLookupStr(NULL, headers, "FPA.EXPOSURE"); // Header name
+        if (!expName || strlen(expName) == 0) {
+            psError(PS_ERR_UNEXPECTED_NULL, false,
+                    "Unable to find FPA.EXPOSURE in %s within camera configuration.",
+                    BLANK_HEADERS);
+            psFree(outhead);
+            psFree(fpa);
+            return false;
+        }
+        float exptime = psMetadataLookupF32(NULL, fpa->concepts, "FPA.EXPOSURE"); // Exposure time
+        psMetadataAddF32(outhead, PS_LIST_TAIL, expName, PS_META_REPLACE,
+                         "Exposure time (sec)", exptime);
+    }
+
+    {
+        const char *amName = psMetadataLookupStr(NULL, headers, "FPA.AIRMASS"); // Header name
+        if (!amName || strlen(amName) == 0) {
+            psError(PS_ERR_UNEXPECTED_NULL, false,
+                    "Unable to find FPA.AIRMASS in %s within camera configuration.",
+                    BLANK_HEADERS);
+            psFree(outhead);
+            psFree(fpa);
+            return false;
+        }
+        float airmass = psMetadataLookupF32(NULL, fpa->concepts, "FPA.AIRMASS"); // Airmass
+        psMetadataAddF32(outhead, PS_LIST_TAIL, amName, PS_META_REPLACE,
+                         "Observation airmass", airmass);
+    }
+
+    psMetadata *fileData = psMetadataLookupMetadata(NULL, file->format, "FILE"); // File information
+    const char *fpaNameHdr = psMetadataLookupStr(NULL, fileData, "FPA.OBS");
+    if (fpaNameHdr && strlen(fpaNameHdr) > 0) {
+        const char *fpaName = psMetadataLookupStr(NULL, fpa->concepts, "FPA.OBS");
+        psMetadataAddStr(outhead, PS_LIST_TAIL, fpaNameHdr, PS_META_REPLACE,
+                         "FPA observation identifier", fpaName);
+    }
+
+    // if we have mosaic-level astrometry information, add it here:
+    psMetadata *updates = psMetadataLookupPtr (&status, fpa->analysis, "PSASTRO.HEADER");
+    if (updates) {
+        psMetadataCopy (outhead, updates);
+    }
+    psFree(fpa);
+
+    psMetadataAddBool (outhead, PS_LIST_TAIL, "EXTEND", PS_META_REPLACE, "this file has extensions", true);
+    psFitsWriteBlank (file->fits, outhead, "");
+    file->wrote_phu = true;
+
+    psTrace ("pmFPAfile", 5, "wrote phu %s (type: %d)\n", file->filename, file->type);
+    psFree (outhead);
+
+    return true;
+}
+
+// Given a FITS file pointer, read the table of object data
+// XXX add in error handling
+bool pmFPAviewReadObjects (const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+
+    pmFPA *fpa = file->fpa;
+
+    if (view->chip == -1) {
+        pmFPAReadObjects (fpa, view, file, config);
+        return true;
+    }
+
+    if (view->chip >= fpa->chips->n) {
+        return false;
+    }
+    pmChip *chip = fpa->chips->data[view->chip];
+
+    if (view->cell == -1) {
+        pmChipReadObjects (chip, view, file, config);
+        return true;
+    }
+
+    if (view->cell >= chip->cells->n) {
+        return false;
+    }
+    pmCell *cell = chip->cells->data[view->cell];
+
+    if (view->readout == -1) {
+        pmCellReadObjects (cell, view, file, config);
+        return true;
+    }
+
+    if (view->readout >= cell->readouts->n) {
+        return false;
+    }
+    pmReadout *readout = cell->readouts->data[view->readout];
+
+    pmReadoutReadObjects (readout, view, file, config);
+    return true;
+}
+
+// read in all chip-level Objects files for this FPA
+bool pmFPAReadObjects (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa->chips, false);
+
+    pmFPAview *thisView = pmFPAviewAlloc (view->nRows);
+    *thisView = *view;
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        thisView->chip = i;
+        pmChipReadObjects (chip, thisView, file, config);
+    }
+    psFree (thisView);
+
+    if (!pmConceptsReadFPA(fpa, PM_CONCEPT_SOURCE_HEADER, true, NULL)) {
+        psError(PS_ERR_IO, false, "Failed to read concepts for fpa.\n");
+        return false;
+    }
+
+    return true;
+}
+
+// read in all cell-level Objects files for this chip
+bool pmChipReadObjects (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_PTR_NON_NULL(chip->cells, false);
+
+    pmFPAview *thisView = pmFPAviewAlloc (view->nRows);
+    *thisView = *view;
+
+    chip->data_exists = false;
+    for (int i = 0; i < chip->cells->n; i++) {
+        pmCell *cell = chip->cells->data[i];
+        thisView->cell = i;
+        pmCellReadObjects (cell, thisView, file, config);
+        if (!cell->data_exists) continue;
+        chip->data_exists = true;
+    }
+    psFree (thisView);
+
+    if (!pmConceptsReadChip(chip, PM_CONCEPT_SOURCE_HEADER, true, true, NULL)) {
+        psError(PS_ERR_IO, false, "Failed to read concepts for chip.\n");
+        return false;
+    }
+
+    return true;
+}
+
+// read in all readout-level Objects files for this cell
+bool pmCellReadObjects (pmCell *cell, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_PTR_NON_NULL(cell->readouts, false);
+
+    pmFPAview *thisView = pmFPAviewAlloc (view->nRows);
+    *thisView = *view;
+
+    // multiple readout mode is not yet defined for CMP or CMF files
+    // if they have not been allocated, allocate a single readout
+    if (!cell->readouts || !cell->readouts->n) {
+        pmReadout *readout = pmReadoutAlloc (cell);
+        psFree (readout);
+    }
+
+    cell->data_exists = false;
+    for (int i = 0; i < cell->readouts->n; i++) {
+        pmReadout *readout = cell->readouts->data[i];
+        thisView->readout = i;
+        pmReadoutReadObjects (readout, thisView, file, config);
+        if (!readout->data_exists) {
+            continue;
+        }
+
+        // load in the concept information for this cell
+        if (!pmConceptsReadCell(cell, PM_CONCEPT_SOURCE_HEADER, true, NULL)) {
+            //psError(PS_ERR_UNKNOWN, false, "Failed to read concepts for cell");
+            //return false;
+            psWarning("Difficulty reading concepts for cell; attempting to proceed.");
+        }
+        cell->data_exists = true;
+    }
+    psFree (thisView);
+
+    if (!pmConceptsReadCell(cell, PM_CONCEPT_SOURCE_HEADER, true, NULL)) {
+        //psError(PS_ERR_UNKNOWN, false, "Failed to read concepts for cell");
+        //return false;
+        psWarning("Difficulty reading concepts for cell; attempting to proceed.");
+    }
+
+    return true;
+}
+
+// read in all readout-level Objects files for this cell
+bool pmReadoutReadObjects (pmReadout *readout, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    bool status;
+    psArray *sources = NULL;
+    pmHDU *hdu;
+
+    switch (file->type) {
+      case PM_FPA_FILE_OBJ:
+        psError(PS_ERR_UNKNOWN, true, "OBJ is not supported as an input object format");
+        return false;
+
+      case PM_FPA_FILE_SX:
+        psError(PS_ERR_UNKNOWN, true, "SX is not supported as an input object format");
+        return false;
+
+      case PM_FPA_FILE_CMP:
+        // a SPLIT format : only one header and object table per file
+
+        // read in header, if not yet loaded
+        hdu = pmFPAviewThisHDU (view, file->fpa);
+#if 0
+        if (file->filename)
+            psFree (file->filename);
+        file->filename = pmFPAfileNameFromRule (file->filerule, file, view);
+#endif
+
+        // indirect filenames
+        if (!strcasecmp (file->filename, "@FILES")) {
+            psFree (file->filename);
+            char *filesrc = pmFPAfileNameFromRule (file->filesrc, file, view);
+            file->filename = psMetadataLookupStr (&status, file->names, filesrc);
+            psFree (filesrc);
+            if (file->filename == NULL) return false;
+            // psMetadataLookupStr just returns a view, file->filename must be protected
+            psMemIncrRefCounter (file->filename);
+        }
+
+        // read the PHU from this file
+        file->fits = psFitsOpen (file->filename, "r");
+        if (hdu->header != NULL) {
+            psFree (hdu->header);
+        }
+        hdu->header = psFitsReadHeader (NULL, file->fits);
+        psFitsClose (file->fits);
+        file->fits = NULL;
+
+        sources = pmSourcesReadCMP (file->filename, hdu->header);
+        break;
+
+      case PM_FPA_FILE_CMF:
+        // read in header, if not yet loaded
+        hdu = pmFPAviewThisHDU (view, file->fpa);
+
+        // lookup the EXTNAME values used for table data and image header segments
+        char *rule = NULL;
+        // Menu of EXTNAME rules
+        psMetadata *menu = psMetadataLookupMetadata(&status, file->camera, "EXTNAME.RULES");
+        if (!menu) {
+            psError(PS_ERR_UNKNOWN, true, "missing EXTNAME.RULES in camera.config");
+            return false;
+        }
+        // EXTNAME for image header
+        rule = psMetadataLookupStr(&status, menu, "CMF.HEAD");
+        if (!rule) {
+            psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.HEAD in EXTNAME.RULES in camera.config");
+            return false;
+        }
+        char *headname = pmFPAfileNameFromRule (rule, file, view);
+        // EXTNAME for table data
+        rule = psMetadataLookupStr(&status, menu, "CMF.DATA");
+        if (!rule) {
+            psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.DATA in EXTNAME.RULES in camera.config");
+            return false;
+        }
+        char *dataname = pmFPAfileNameFromRule (rule, file, view);
+
+        // advance to the IMAGE HEADER extension
+        if (hdu->header == NULL) {
+            // if the IMAGE header does not exist, we have no data for this view
+            if (!psFitsMoveExtName (file->fits, headname)) {
+                readout->data_exists = false;
+                psFree (headname);
+                psFree (dataname);
+                return true;
+            }
+            hdu->header = psFitsReadHeader (NULL, file->fits);
+        }
+
+        // we need to find the corresponding table EXTNAME.
+        // first check the header
+        char *extdata = psMetadataLookupStr (NULL, hdu->header, "EXTDATA");
+        if (extdata) {
+            // if EXTDATA is defined in the header, use that value for 'dataname'
+            psFree (dataname);
+            dataname = psMemIncrRefCounter (extdata);
+        }
+
+        // advance to the table data extension
+        // since we have read the IMAGE header, the TABLE header should exist
+        if (!psFitsMoveExtName (file->fits, dataname)) {
+            psAbort("cannot find data extension %s in %s", dataname, file->filename);
+        }
+
+        psMetadata *tableHeader = psFitsReadHeader(NULL, file->fits); // The FITS header
+        if (!tableHeader) psAbort("cannot read table header");
+
+        char *exttype = psMetadataLookupStr (NULL, tableHeader, "EXTTYPE");
+        if (!exttype) psAbort("cannot read table type");
+
+        // XXX these are case-sensitive since the EXTYPE is case-sensitive
+        if (!strcmp (exttype, "SMPDATA")) {
+            sources = pmSourcesRead_SMPDATA (file->fits, hdu->header);
+        }
+        if (!strcmp (exttype, "PS1_DEV_0")) {
+            sources = pmSourcesRead_PS1_DEV_0 (file->fits, hdu->header);
+        }
+        if (!strcmp (exttype, "PS1_DEV_1")) {
+            sources = pmSourcesRead_PS1_DEV_1 (file->fits, hdu->header);
+        }
+
+        psTrace("psModules.objects", 6, "read CMF table from %s : %s : %s", file->filename, headname, dataname);
+        psFree (headname);
+        psFree (dataname);
+        psFree (tableHeader);
+        break;
+
+      default:
+        fprintf (stderr, "warning: type mismatch\n");
+        break;
+    }
+    readout->data_exists = true;
+    status = psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSPHOT.SOURCES", PS_DATA_ARRAY, "input sources", sources);
+    psFree (sources);
+    return true;
+}
+
+bool pmFPAviewCheckDataStatusForSources (const pmFPAview *view, const pmFPAfile *file)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+
+    pmFPA *fpa = file->fpa;
+
+    if (view->chip == -1) {
+        bool exists = pmFPACheckDataStatusForSources (fpa);
+        return exists;
+    }
+    if (view->chip >= fpa->chips->n) {
+        psError(PS_ERR_IO, true, "Requested chip == %d >= fpa->chips->n == %ld", view->chip, fpa->chips->n);
+        return false;
+    }
+    pmChip *chip = fpa->chips->data[view->chip];
+
+    if (view->cell == -1) {
+        bool exists = pmChipCheckDataStatusForSources (chip);
+        return exists;
+    }
+    if (view->cell >= chip->cells->n) {
+        psError(PS_ERR_IO, true, "Requested cell == %d >= chip->cells->n == %ld", view->cell, chip->cells->n);
+        return false;
+    }
+    pmCell *cell = chip->cells->data[view->cell];
+
+    if (view->readout == -1) {
+        bool exists = pmCellCheckDataStatusForSources (cell);
+        return exists;
+    }
+
+    if (view->readout >= cell->readouts->n) {
+        psError(PS_ERR_IO, true, "Requested readout == %d >= cell->readouds->n == %ld", view->readout, cell->readouts->n);
+        return false;
+    }
+    pmReadout *readout = cell->readouts->data[view->readout];
+
+    bool exists = pmReadoutCheckDataStatusForSources (readout);
+    return exists;
+}
+
+bool pmFPACheckDataStatusForSources (const pmFPA *fpa)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(fpa->chips, false);
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        if (!chip) continue;
+        if (pmChipCheckDataStatusForSources (chip)) return true;
+    }
+    return false;
+}
+
+bool pmChipCheckDataStatusForSources (const pmChip *chip)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_PTR_NON_NULL(chip->cells, false);
+
+    for (int i = 0; i < chip->cells->n; i++) {
+        pmCell *cell = chip->cells->data[i];
+        if (!cell) continue;
+        if (pmCellCheckDataStatusForSources (cell)) return true;
+    }
+    return false;
+}
+
+bool pmCellCheckDataStatusForSources (const pmCell *cell)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_PTR_NON_NULL(cell->readouts, false);
+
+    for (int i = 0; i < cell->readouts->n; i++) {
+        pmReadout *readout = cell->readouts->data[i];
+        if (!readout) continue;
+        if (pmReadoutCheckDataStatusForSources (readout)) return true;
+    }
+    return false;
+}
+
+bool pmReadoutCheckDataStatusForSources (const pmReadout *readout)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+
+    bool status;
+
+    // select the psf of interest
+    pmPSF *psf = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.SOURCES");
+    if (!psf) return false;
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO.h	(revision 22158)
@@ -0,0 +1,65 @@
+/* @file  pmSourceIO.h
+ * @brief functions to read and write object files
+ *
+ * @author EAM, IfA; GLG, MHPCC
+ *
+ * @version $Revision: 1.18 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-17 22:38:15 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+# ifndef PM_SOURCE_IO_H
+# define PM_SOURCE_IO_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+int pmSourceGetDophotType (pmSource *source);
+bool pmSourceSetDophotType (pmSource *source, int type);
+
+bool pmSourcesWriteRAW (psArray *sources, char *filename);
+bool pmSourcesWriteOBJ (psArray *sources, char *filename);
+bool pmSourcesWriteSX (psArray *sources, char *filename);
+bool pmSourcesWriteCMP (psArray *sources, char *filename, psMetadata *header);
+
+bool pmSourcesWrite_SMPDATA (psFits *fits, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname);
+bool pmSourcesWrite_PS1_DEV_0 (psFits *fits, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname);
+bool pmSourcesWrite_PS1_DEV_1 (psFits *fits, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, char *xsrcname);
+bool pmSourcesWrite_PS1_DEV_1_XSRC (psFits *fits, psArray *sources, char *extname, psMetadata *recipe);
+bool pmSourcesWrite_PS1_DEV_1_XFIT (psFits *fits, psArray *sources, char *extname);
+
+bool pmSource_CMF_WritePHU (const pmFPAview *view, pmFPAfile *file, pmConfig *config);
+
+psArray *pmSourcesReadCMP (char *filename, psMetadata *header);
+
+psArray *pmSourcesRead_SMPDATA (psFits *fits, psMetadata *header);
+psArray *pmSourcesRead_PS1_DEV_0 (psFits *fits, psMetadata *header);
+psArray *pmSourcesRead_PS1_DEV_1 (psFits *fits, psMetadata *header);
+
+bool pmSourcesWritePSFs (psArray *sources, char *filename);
+bool pmSourcesWriteEXTs (psArray *sources, char *filename, bool require);
+bool pmSourcesWriteNULLs (psArray *sources, char *filename);
+bool pmMomentsWriteText (psArray *sources, char *filename);
+bool pmPeaksWriteText (psArray *peaks, char *filename);
+
+bool pmFPAviewReadObjects (const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmFPAReadObjects (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmChipReadObjects (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmCellReadObjects (pmCell *cell, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmReadoutReadObjects (pmReadout *readout, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+
+bool pmFPAviewWriteObjects (const pmFPAview *view, pmFPAfile *file, pmConfig *config);
+bool pmFPAWriteObjects (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmChipWriteObjects (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmCellWriteObjects (pmCell *cell, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmReadoutWriteObjects (pmReadout *readout, const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+
+bool pmFPAviewCheckDataStatusForSources (const pmFPAview *view, const pmFPAfile *file);
+bool pmFPACheckDataStatusForSources (const pmFPA *fpa);
+bool pmChipCheckDataStatusForSources (const pmChip *chip);
+bool pmCellCheckDataStatusForSources (const pmCell *cell);
+bool pmReadoutCheckDataStatusForSources (const pmReadout *readout);
+
+/// @}
+# endif /* PM_SOURCE_IO_H */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_CMP.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_CMP.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_CMP.c	(revision 22158)
@@ -0,0 +1,297 @@
+/** @file  pmSourceIO.c
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.32 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmGrowthCurve.h"
+#include "pmResiduals.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmModelClass.h"
+#include "pmSourceIO.h"
+
+// XXX make sure in and out have consistent zero-point adjustments
+// XXX make sure the angle in correctly translated to/from degrees
+// XXX we lose all information from the 'type' field
+
+// XXX update this file is we convert to PAR[4] : SigmaX*sqrt(2) (not 1/SigmaX)
+
+// elixir-style pseudo FITS table (header + ascii list)
+bool pmSourcesWriteCMP (psArray *sources, char *filename, psMetadata *header)
+{
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(filename, false);
+    PS_ASSERT_PTR_NON_NULL(header, false);
+
+    int i, type;
+    // psMetadataItem *mdi;
+    psF32 *PAR, *dPAR;
+    float lsky = 0;
+    bool status;
+    psEllipseAxes axes;
+
+    // find config information for output header
+    float ZERO_POINT = psMetadataLookupF32 (&status, header, "ZERO_PT");
+    if (!status) {
+        ZERO_POINT = 25.0;
+    }
+
+    // MEF elements have XTENSION, not SIMPLE: remove this (replace with SIMPLE)
+    psMetadataLookupStr (&status, header, "XTENSION");
+    if (status) {
+        psMetadataRemoveKey (header, "XTENSION");
+    }
+
+    // create file, write-out header
+    psMetadataAddS32 (header, PS_LIST_HEAD, "NAXIS", PS_META_REPLACE, "head data only", 0);
+    psMetadataAddBool (header, PS_LIST_HEAD, "SIMPLE", PS_META_REPLACE, "CMP file, not simple", false);
+
+    psFits *fits = psFitsOpen (filename, "w");
+    if (fits == NULL) {
+        psError(PS_ERR_IO, false, "can't open output file for write %s\n", filename);
+        return false;
+    }
+    // XXX what is the EXTNAME??
+    if (!psFitsWriteBlank(fits, header, "")) {
+        psError(PS_ERR_IO, false, "Writing header to %s\n", filename);
+        (void)psFitsClose(fits);
+        return false;
+    }
+    if (!psFitsClose(fits)) {
+        const psErrorCode code = psErrorCodeLast();
+
+        if (code == PS_ERR_BAD_FITS) {
+            psErrorClear();
+        } else {
+            psError(PS_ERR_IO, false, "Closing %s\n", filename);
+            return false;
+        }
+    }
+
+    // re-open, add data to end of file
+    FILE *f = fopen (filename, "a+");
+    if (f == NULL) {
+        psLogMsg ("WriteSourceOBJ", 3, "can't reopen output file for append %s\n", filename);
+        psError(PS_ERR_IO, false, "can't open output file for output %s\n", filename);
+        return false;
+    }
+
+    fseeko(f, 0, SEEK_END);
+
+    psLine *line = psLineAlloc (67);  // 66 is imclean-defined line length
+
+    // write sources with models first
+    for (i = 0; i < sources->n; i++) {
+        pmSource *source = (pmSource *) sources->data[i];
+
+	// no difference between PSF and non-PSF model
+        pmModel *model = pmSourceGetModel (NULL, source);
+        if (model == NULL)
+            continue;
+
+        PAR = model->params->data.F32;
+        dPAR = model->dparams->data.F32;
+
+        type = pmSourceGetDophotType (source);
+        lsky = (source->sky < 1.0) ? 0.0 : log10(source->sky);
+
+        axes = pmPSF_ModelToAxes (PAR, 20.0);
+
+        float errMag = isfinite(source->errMag) ? source->errMag : 999;
+
+        psLineInit (line);
+        psLineAdd (line, "%6.1f ",  PAR[PM_PAR_XPOS]);
+        psLineAdd (line, "%6.1f ",  PAR[PM_PAR_YPOS]);
+        psLineAdd (line, "%6.3f ",  PS_MIN (99.0, source->psfMag + ZERO_POINT));
+        psLineAdd (line, "%03d ",   PS_MIN (999, (int)errMag));
+        psLineAdd (line, "%2d ",    type);
+        psLineAdd (line, "%3.1f ",  lsky);
+        psLineAdd (line, "%6.3f ",  PS_MIN (99.0, source->extMag + ZERO_POINT));
+        psLineAdd (line, "%6.3f ",  PS_MIN (99.0, source->apMag  + ZERO_POINT));
+        psLineAdd (line, "%6.2f ",  axes.major);
+        psLineAdd (line, "%6.2f ",  axes.minor);
+        psLineAdd (line, "%5.1f\n", axes.theta);
+        fwrite (line->line, 1, line->Nline, f);
+    }
+    fclose (f);
+    psFree (line);
+    return true;
+}
+
+# define BYTES_STAR 66
+# define BLOCK 1000
+
+// elixir-style pseudo FITS table (header + ascii list)
+psArray *pmSourcesReadCMP (char *filename, psMetadata *header)
+{
+    PS_ASSERT_PTR_NON_NULL(filename, false);
+    PS_ASSERT_PTR_NON_NULL(header, false);
+
+    bool status;
+    int Ninstar;
+    psF32 *PAR, *dPAR;
+    psEllipseAxes axes;
+
+    // define PSF model type
+    int modelType = pmModelClassGetType ("PS_MODEL_GAUSS");
+
+    char *PSF_NAME = psMetadataLookupStr (&status, header, "PSF_NAME");
+    if (PSF_NAME != NULL) {
+        modelType = pmModelClassGetType (PSF_NAME);
+    }
+
+    // find config information for output header
+    float ZERO_POINT = psMetadataLookupF32 (&status, header, "ZERO_PT");
+    if (!status)
+        ZERO_POINT = 25.0;
+
+    // how many lines in the header?
+    long nLines = header->list->n;
+    off_t nBytes = nLines * 80;
+    if (nBytes % 2880) {
+        off_t nBlock = 1 + (off_t)(nBytes / 2880);
+        nBytes = nBlock * 2880;
+    }
+
+    // re-open, seek to end of header
+    FILE *f = fopen (filename, "r");
+    if (f == NULL) {
+        psLogMsg ("pmSourcesReadCMP", 3, "can't open output file for input %s\n", filename);
+        return NULL;
+    }
+
+    fseeko(f, nBytes, SEEK_SET);
+
+    // prepare array to store data
+    int nStars = psMetadataLookupS32 (&status, header, "NSTARS");
+    psArray *sources = psArrayAlloc (nStars);
+    sources->n = 0;
+
+    // we have fixed bytes / line : use that info
+    // XXX use the min of nStars and BLOCK?
+    char *buffer = psAlloc (BYTES_STAR*PS_MIN(nStars, BLOCK));
+
+    int Nextra = 0;
+    while (true) {
+        /* load next data block */
+        // XXX fix the use of two vars with different case -JH
+        off_t Nbytes = BYTES_STAR * BLOCK - Nextra;
+        off_t nbytes = fread (&buffer[Nextra], 1, Nbytes, f);
+        if (nbytes == 0) {
+            goto done_load;
+        }
+        nbytes += Nextra;
+
+        /* check line-by-line integrity */
+        char *c  = buffer;
+        char *c2 = NULL;
+        while (c < buffer + nbytes) {
+            for (c2 = c; *c2 == '\n'; c2++)
+                ;
+            if (c2 > c) { /* extra return chars */
+                memmove (c, c2, (int)(buffer + nbytes - c2));
+                int Nskip = c2 - c;
+                nbytes -= Nskip;
+                memset(buffer + nbytes, '\0', Nskip);
+                psLogMsg (__func__, 4, "deleted %d extra return chars\n", Nskip);
+            }
+            c2 = strchr (c, '\n');
+            if (c2 == (char *) NULL) {
+                goto done_check;
+            }
+            c2++;
+            if ((c2 - c) != BYTES_STAR) { /* bad line, delete it */
+                memmove (c, c2, (int)(buffer + nbytes - c2));
+                int Nskip = c2 - c;
+                nbytes -= Nskip;
+		memset(buffer + nbytes, '\0', Nskip);
+                psLogMsg (__func__, 4, "deleted line, %d extra chars\n", Nskip);
+            } else {
+                c = c2;
+            }
+        }
+done_check:
+
+        /* extract data for stars */
+        Ninstar = nbytes / BYTES_STAR;
+        Nextra = nbytes % BYTES_STAR;
+        for (int j = 0; j < Ninstar; j++) {
+            psString line = psStringNCopy (&buffer[j*BYTES_STAR], BYTES_STAR);
+
+            psArray *array = psStringSplitArray (line, " ", false);
+
+            // XXX this is a bit cheap: I don't even attempt to interpret the
+            // sextractor / dophot analysis to distinguish stars and galaxies
+            // your milage may vary...
+            pmSource *source = pmSourceAlloc ();
+            source->modelPSF = pmModelAlloc (modelType);
+            source->type = PM_SOURCE_TYPE_STAR;
+
+            PAR = source->modelPSF->params->data.F32;
+            dPAR = source->modelPSF->dparams->data.F32;
+
+            PAR[PM_PAR_SKY] = pow (atof (array->data[5]), 10.0);
+            PAR[PM_PAR_XPOS] = atof (array->data[0]);
+            PAR[PM_PAR_YPOS] = atof (array->data[1]);
+            source->psfMag = atof (array->data[2]);
+            source->extMag = atof (array->data[6]);
+            source->errMag = atof (array->data[3]) / 1000.0;
+            source->apMag  = atof (array->data[7]);
+            axes.major     = atof (array->data[8]);
+            axes.minor     = atof (array->data[9]);
+            axes.theta  = atof (array->data[10]);
+
+            if (!isfinite(axes.major))
+                goto skip_source;
+            if (!isfinite(axes.minor))
+                goto skip_source;
+            if (!isfinite(axes.theta))
+                goto skip_source;
+
+	    pmPSF_AxesToModel (PAR, axes);
+
+            psArrayAdd (sources, 100, source);
+
+skip_source:
+            psFree (line);
+            psFree (array);
+            psFree (source);
+
+        }
+    }
+done_load:
+
+    // XXX if sources->n != nStars, give an error?
+    psFree (buffer);
+
+    fclose (f);
+    return (sources);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_OBJ.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_OBJ.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_OBJ.c	(revision 22158)
@@ -0,0 +1,103 @@
+/** @file  pmSourceIO.c
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmGrowthCurve.h"
+#include "pmResiduals.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmModelClass.h"
+#include "pmSourceIO.h"
+
+// dophot-style output list with fixed line width
+bool pmSourcesWriteOBJ (psArray *sources, char *filename)
+{
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(filename, false);
+
+    int type;
+    psF32 *PAR, *dPAR;
+    float dmag, apResid;
+    psEllipseAxes axes;
+
+    psTimerStart ("string");
+
+    psLine *line = psLineAlloc (104);  // 104 is dophot-defined line length
+
+    FILE *f = fopen (filename, "w");
+    if (f == NULL) {
+        psLogMsg (__func__, 3, "can't open output file for output %s\n", filename);
+        return false;
+    }
+
+    // write sources with models
+    for (int i = 0; i < sources->n; i++) {
+        pmSource *source = (pmSource *) sources->data[i];
+
+	// no difference between PSF and non-PSF model
+        pmModel *model = pmSourceGetModel (NULL, source);
+        if (model == NULL)
+            continue;
+
+        PAR = model->params->data.F32;
+        dPAR = model->dparams->data.F32;
+
+        dmag = dPAR[PM_PAR_I0] / PAR[PM_PAR_I0];
+        type = pmSourceGetDophotType (source);
+        if ((source->apMag < 99.0) && (source->psfMag < 99.0)) {
+            apResid = source->apMag - source->psfMag;
+        } else {
+            apResid = 0.0;
+        }
+
+        axes = pmPSF_ModelToAxes (PAR, 20.0);
+
+        psLineInit (line);
+        psLineAdd (line, "%3d",   type);
+        psLineAdd (line, "%8.2f", PAR[PM_PAR_XPOS]);
+        psLineAdd (line, "%8.2f", PAR[PM_PAR_YPOS]);
+        psLineAdd (line, "%8.3f", source->psfMag);
+        psLineAdd (line, "%6.3f", dmag);
+        psLineAdd (line, "%9.2f", source->sky);
+        psLineAdd (line, "%9.3f", axes.major);
+        psLineAdd (line, "%9.3f", axes.minor);
+        psLineAdd (line, "%7.2f", axes.theta);
+        psLineAdd (line, "%8.3f", source->extMag);
+        psLineAdd (line, "%8.3f", source->apMag);
+        psLineAdd (line, "%8.2f\n", apResid);
+        fwrite (line->line, 1, line->Nline, f);
+    }
+    fclose (f);
+    psFree (line);
+    fprintf (stderr, "%f seconds for %d objects\n", psTimerMark ("string"), (int)sources->n);
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_PS1_DEV_0.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_PS1_DEV_0.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_PS1_DEV_0.c	(revision 22158)
@@ -0,0 +1,224 @@
+/** @file  pmSourceIO.c
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-01-02 20:39:04 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmGrowthCurve.h"
+#include "pmResiduals.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmModelClass.h"
+#include "pmSourceIO.h"
+
+// panstars-style FITS table output (header + table in 1st extension)
+// this format consists of a header derived from the image header
+// followed by a zero-size matrix, followed by the table data
+
+// this output format is valid for psphot analysis of an image, and does not include calibrated
+// values derived in the DVO database.
+// XXX how do I generate the source tables which I need to send to PSPS?
+// XXX: input parameter imageHeader is never used.
+bool pmSourcesWrite_PS1_DEV_0 (psFits *fits, psArray *sources, psMetadata *imageHeader,
+                               psMetadata *tableHeader, char *extname)
+{
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(extname, false);
+
+    psArray *table;
+    psMetadata *row;
+    int i;
+    psF32 *PAR, *dPAR;
+    psEllipseAxes axes;
+    psF32 xPos, yPos;
+    psF32 xErr, yErr;
+
+    table = psArrayAllocEmpty (sources->n);
+
+    // we write out all sources, regardless of quality.  the source flags tell us the state
+    for (i = 0; i < sources->n; i++) {
+        pmSource *source = (pmSource *) sources->data[i];
+
+        // no difference between PSF and non-PSF model
+        pmModel *model = pmSourceGetModel(NULL, source);
+
+        if (model != NULL) {
+            PAR = model->params->data.F32;
+            dPAR = model->dparams->data.F32;
+            xPos = PAR[PM_PAR_XPOS];
+            yPos = PAR[PM_PAR_YPOS];
+            xErr = dPAR[PM_PAR_XPOS];
+            yErr = dPAR[PM_PAR_YPOS];
+
+            axes = pmPSF_ModelToAxes (PAR, 20.0);
+        } else {
+            // XXX: This code seg faults if source->peak is NULL.
+            xPos = source->peak->xf;
+            yPos = source->peak->yf;
+            xErr = 0.0; // XXX a better choice, please
+            yErr = 0.0; // XXX a better choice, please
+            axes.major = 0.0;
+            axes.minor = 0.0;
+            axes.theta = 0.0;
+        }
+
+        float peakMag = (source->peak->flux > 0) ? -2.5*log10(source->peak->flux) : NAN;
+        psS16 nImageOverlap = 1;
+        psS32 ID = 0; // XXX need to figure out how to generate this
+
+        row = psMetadataAlloc ();
+        // XXX we are not writing out the mode (flags) or the type (psf, ext, etc)
+        psMetadataAdd (row, PS_LIST_TAIL, "IPP_IDET",         PS_DATA_U32, "IPP detection identifier index",             ID);
+        psMetadataAdd (row, PS_LIST_TAIL, "X_PSF",            PS_DATA_F32, "PSF x coordinate",                           xPos);
+        psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF",            PS_DATA_F32, "PSF y coordinate",                           yPos);
+        psMetadataAdd (row, PS_LIST_TAIL, "X_PSF_SIG",        PS_DATA_F32, "Sigma in PSF x coordinate",                  xErr);
+        psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF_SIG",        PS_DATA_F32, "Sigma in PSF y coordinate",                  yErr);
+        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG",     PS_DATA_F32, "PSF fit instrumental magnitude",             PS_MIN (99.0, source->psfMag));
+        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG_SIG", PS_DATA_F32, "Sigma of PSF instrumental magnitude",        PS_MIN (99.0, source->errMag));
+        psMetadataAdd (row, PS_LIST_TAIL, "PEAK_FLUX_AS_MAG", PS_DATA_F32, "Peak flux expressed as magnitude",           PS_MIN (99.0, peakMag));
+        psMetadataAdd (row, PS_LIST_TAIL, "SKY",              PS_DATA_F32, "Sky level",                                  source->sky);
+        psMetadataAdd (row, PS_LIST_TAIL, "SKY_SIGMA",        PS_DATA_F32, "Sigma of sky level",                         source->skyErr);
+        // XXX this is called STAR_GALAXY_SEP in the ICD; PSF_PROB is better
+        // XXX need to set this value in psphotEvalPSF
+        // XXX can I use the 2d polynomial peak fit to constrain this for the low-sn sources?
+        psMetadataAdd (row, PS_LIST_TAIL, "PSF_PROBABILITY",  PS_DATA_F32,  "Probability of PSF-ness",                   NAN);
+        // XXX these should be major and minor, not 'x' and 'y'
+        psMetadataAdd (row, PS_LIST_TAIL, "PSF_WIDTH_X",      PS_DATA_F32, "PSF width in x coordinate",                  axes.major);
+        psMetadataAdd (row, PS_LIST_TAIL, "PSF_WIDTH_Y",      PS_DATA_F32, "PSF width in y coordinate",                  axes.minor);
+        psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      axes.theta);
+        psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor",                source->pixWeight);
+        // XXX not sure how to get this : need to load Nimages with weight
+        psMetadataAdd (row, PS_LIST_TAIL, "N_FRAMES",         PS_DATA_U16, "Number of frames overlapping source center", nImageOverlap);
+        psMetadataAdd (row, PS_LIST_TAIL, "DUMMY",            PS_DATA_U16, "padding", 0);
+
+        // XXX these calibrated values are not supplied by psphot analysis
+        // psMetadataAdd (row, PS_LIST_TAIL, "RA_PSF",           PS_DATA_F64, "RA from PSF fit",                         RA);
+        // psMetadataAdd (row, PS_LIST_TAIL, "DEC_PSF",          PS_DATA_F64, "DEC from PSF fit",                        DEC);
+        // psMetadataAdd (row, PS_LIST_TAIL, "RA_PSF_SIG",       PS_DATA_F32, "Sigma of PSF fit RA",                     dRA);
+        // psMetadataAdd (row, PS_LIST_TAIL, "DEC_PSF_SIG",      PS_DATA_F32, "Sigma of PSF fit DEC",                    dDEC);
+        // psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG",      PS_DATA_F32, "Calibrated magnitude",                    calMag);
+        // psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG_sIG",  PS_DATA_F32, "Sigma of calibrated magnitude",           calMagErr);
+
+        psArrayAdd (table, 100, row);
+        psFree (row);
+    }
+
+    if (table->n == 0) {
+        psFitsWriteBlank (fits, tableHeader, extname);
+        psFree (table);
+        return true;
+    }
+
+    psTrace ("pmFPAfile", 5, "writing ext data %s\n", extname);
+    if (!psFitsWriteTable (fits, tableHeader, table, extname)) {
+        psError(PS_ERR_IO, false, "writing ext data %s\n", extname);
+        psFree(table);
+        return false;
+    }
+
+    psFree (table);
+    return true;
+}
+
+// read in a readout from the fits file
+psArray *pmSourcesRead_PS1_DEV_0 (psFits *fits, psMetadata *header)
+{
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    PS_ASSERT_PTR_NON_NULL(header, false);
+
+    bool status;
+    psF32 *PAR, *dPAR;
+    psEllipseAxes axes;
+
+    // define PSF model type
+    int modelType = pmModelClassGetType ("PS_MODEL_GAUSS");
+
+    char *PSF_NAME = psMetadataLookupStr (&status, header, "PSF_NAME");
+    if (PSF_NAME != NULL) {
+        modelType = pmModelClassGetType (PSF_NAME);
+    }
+
+    psArray *table = psFitsReadTable (fits);
+    // validate a single row of the table (must match SMP)
+    // XXX: The following seg-faults if table returns NULL, so I added the ASSERT
+    PS_ASSERT_PTR_NON_NULL(table, NULL);
+    psArray *sources = psArrayAlloc (table->n);
+
+    // convert the table to the pmSource entries
+    // XXX need to chooose PSF vs EXT, based on type?
+    for (int i = 0; i < table->n; i++) {
+        pmSource *source = pmSourceAlloc ();
+        pmModel *model = pmModelAlloc (modelType);
+        source->modelPSF  = model;
+        source->type = PM_SOURCE_TYPE_STAR;
+
+        // NOTE: A SEGV here because "model" is NULL is probably caused by not initialising the models.
+        PAR = model->params->data.F32;
+        dPAR = model->dparams->data.F32;
+
+        psMetadata *row = table->data[i];
+
+        PAR[PM_PAR_XPOS]  = psMetadataLookupF32 (&status, row, "X_PSF");
+        PAR[PM_PAR_YPOS]  = psMetadataLookupF32 (&status, row, "Y_PSF");
+        dPAR[PM_PAR_XPOS] = psMetadataLookupF32 (&status, row, "X_PSF_SIG");
+        dPAR[PM_PAR_YPOS] = psMetadataLookupF32 (&status, row, "Y_PSF_SIG");
+        axes.major        = psMetadataLookupF32 (&status, row, "PSF_WIDTH_X");
+        axes.minor        = psMetadataLookupF32 (&status, row, "PSF_WIDTH_Y");
+        axes.theta        = psMetadataLookupF32 (&status, row, "PSF_THETA");
+
+        PAR[PM_PAR_SKY]   = psMetadataLookupF32 (&status, row, "SKY");
+        dPAR[PM_PAR_SKY]  = psMetadataLookupF32 (&status, row, "SKY_SIGMA");
+        source->sky = PAR[PM_PAR_SKY];
+        source->skyErr = dPAR[PM_PAR_SKY];
+
+        // XXX use these to determine PAR[PM_PAR_I0]?
+        source->psfMag    = psMetadataLookupF32 (&status, row, "PSF_INST_MAG");
+        source->errMag    = psMetadataLookupF32 (&status, row, "PSF_INST_MAG_SIG");
+
+        pmPSF_AxesToModel (PAR, axes);
+
+        float lflux = psMetadataLookupF32 (&status, row, "PEAK_FLUX_AS_MAG");
+        float flux = (isfinite(lflux)) ? pow(10.0, -0.4*lflux) : NAN;
+        source->peak = pmPeakAlloc(PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], flux, PM_PEAK_LONE);
+        source->peak->flux = flux;
+
+        source->pixWeight = psMetadataLookupF32 (&status, row, "PSF_QF");
+
+        // XXX other values saved but not loaded?
+        // psMetadataLookupS64 (&status, row, "IPP_IDET");
+        // psMetadataLookupF32 (&status, row, "PSF_PROBABILITY");
+        // psMetadataLookupF32 (&status, row, "N_FRAMES");
+
+        sources->data[i] = source;
+    }
+    psFree (table);
+    return (sources);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_PS1_DEV_1.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_PS1_DEV_1.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_PS1_DEV_1.c	(revision 22158)
@@ -0,0 +1,544 @@
+/** @file  pmSourceIO.c
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-04-08 18:35:38 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmGrowthCurve.h"
+#include "pmResiduals.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmModelClass.h"
+#include "pmSourceIO.h"
+
+// panstarrs-style FITS table output (header + table in 1st extension)
+// this format consists of a header derived from the image header
+// followed by a zero-size matrix, followed by the table data
+
+// this output format is valid for psphot analysis of an image, and does not include calibrated
+// values derived in the DVO database.
+// XXX how do I generate the source tables which I need to send to PSPS?
+
+bool pmSourcesWrite_PS1_DEV_1 (psFits *fits, psArray *sources, psMetadata *imageHeader,
+                               psMetadata *tableHeader, char *extname, char *xsrcname)
+{
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(extname, false);
+
+    psArray *table;
+    psMetadata *row;
+    int i;
+    psF32 *PAR, *dPAR;
+    psEllipseAxes axes;
+    psF32 xPos, yPos;
+    psF32 xErr, yErr;
+
+    // let's write these out in S/N order
+    sources = psArraySort (sources, pmSourceSortBySN);
+
+    table = psArrayAllocEmpty (sources->n);
+
+    // we write out all sources, regardless of quality.  the source flags tell us the state
+    for (i = 0; i < sources->n; i++) {
+        pmSource *source = (pmSource *) sources->data[i];
+        source->seq = i;
+
+        // no difference between PSF and non-PSF model
+        pmModel *model = pmSourceGetModel (NULL, source);
+
+        if (model != NULL) {
+            PAR = model->params->data.F32;
+            dPAR = model->dparams->data.F32;
+            xPos = PAR[PM_PAR_XPOS];
+            yPos = PAR[PM_PAR_YPOS];
+            xErr = dPAR[PM_PAR_XPOS];
+            yErr = dPAR[PM_PAR_YPOS];
+
+            axes = pmPSF_ModelToAxes (PAR, 20.0);
+        } else {
+            xPos = source->peak->xf;
+            yPos = source->peak->yf;
+            xErr = source->peak->dx;
+            yErr = source->peak->dy;
+            axes.major = 0.0;
+            axes.minor = 0.0;
+            axes.theta = 0.0;
+        }
+
+        float peakMag = (source->peak->flux > 0) ? -2.5*log10(source->peak->flux) : NAN;
+        psS16 nImageOverlap = 1;
+
+        row = psMetadataAlloc ();
+        // XXX we are not writing out the mode (flags) or the type (psf, ext, etc)
+        psMetadataAdd (row, PS_LIST_TAIL, "IPP_IDET",         PS_DATA_U32, "IPP detection identifier index",             source->seq);
+        psMetadataAdd (row, PS_LIST_TAIL, "X_PSF",            PS_DATA_F32, "PSF x coordinate",                           xPos);
+        psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF",            PS_DATA_F32, "PSF y coordinate",                           yPos);
+        psMetadataAdd (row, PS_LIST_TAIL, "X_PSF_SIG",        PS_DATA_F32, "Sigma in PSF x coordinate",                  xErr);
+        psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF_SIG",        PS_DATA_F32, "Sigma in PSF y coordinate",                  yErr);
+        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG",     PS_DATA_F32, "PSF fit instrumental magnitude",             PS_MIN (99.0, source->psfMag));
+        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG_SIG", PS_DATA_F32, "Sigma of PSF instrumental magnitude",        PS_MIN (99.0, source->errMag));
+        psMetadataAdd (row, PS_LIST_TAIL, "PEAK_FLUX_AS_MAG", PS_DATA_F32, "Peak flux expressed as magnitude",           PS_MIN (99.0, peakMag));
+        psMetadataAdd (row, PS_LIST_TAIL, "SKY",              PS_DATA_F32, "Sky level",                                  source->sky);
+        psMetadataAdd (row, PS_LIST_TAIL, "SKY_SIGMA",        PS_DATA_F32, "Sigma of sky level",                         source->skyErr);
+
+        psMetadataAdd (row, PS_LIST_TAIL, "PSF_CHISQ",        PS_DATA_F32,  "Chisq of PSF-fit to top 9 pixels",          source->psfChisq);
+        psMetadataAdd (row, PS_LIST_TAIL, "CR_NSIGMA",        PS_DATA_F32,  "Nsigma deviations from PSF to CF",          source->crNsigma);
+        psMetadataAdd (row, PS_LIST_TAIL, "EXT_NSIGMA",       PS_DATA_F32,  "Nsigma deviations from PSF to EXT",         source->extNsigma);
+
+        // XXX these should be major and minor, not 'x' and 'y'
+        psMetadataAdd (row, PS_LIST_TAIL, "PSF_WIDTH_X",      PS_DATA_F32, "PSF width in x coordinate",                  axes.major);
+        psMetadataAdd (row, PS_LIST_TAIL, "PSF_WIDTH_Y",      PS_DATA_F32, "PSF width in y coordinate",                  axes.minor);
+        psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      axes.theta);
+        psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor",                source->pixWeight);
+
+        // XXX not sure how to get this : need to load Nimages with weight?
+        psMetadataAdd (row, PS_LIST_TAIL, "N_FRAMES",         PS_DATA_U16, "Number of frames overlapping source center", nImageOverlap);
+        psMetadataAdd (row, PS_LIST_TAIL, "FLAGS",            PS_DATA_U16, "psphot analysis flags",                      source->mode);
+
+        // XXX these calibrated values are not supplied by psphot analysis
+        // psMetadataAdd (row, PS_LIST_TAIL, "RA_PSF",           PS_DATA_F64, "RA from PSF fit",                         RA);
+        // psMetadataAdd (row, PS_LIST_TAIL, "DEC_PSF",          PS_DATA_F64, "DEC from PSF fit",                        DEC);
+        // psMetadataAdd (row, PS_LIST_TAIL, "RA_PSF_SIG",       PS_DATA_F32, "Sigma of PSF fit RA",                     dRA);
+        // psMetadataAdd (row, PS_LIST_TAIL, "DEC_PSF_SIG",      PS_DATA_F32, "Sigma of PSF fit DEC",                    dDEC);
+        // psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG",      PS_DATA_F32, "Calibrated magnitude",                    calMag);
+        // psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG_sIG",  PS_DATA_F32, "Sigma of calibrated magnitude",           calMagErr);
+
+        psArrayAdd (table, 100, row);
+        psFree (row);
+    }
+
+    if (table->n == 0) {
+        psFitsWriteBlank (fits, tableHeader, extname);
+        psFree (table);
+        return true;
+    }
+
+    psTrace ("pmFPAfile", 5, "writing ext data %s\n", extname);
+    if (!psFitsWriteTable (fits, tableHeader, table, extname)) {
+        psError(PS_ERR_IO, false, "writing ext data %s\n", extname);
+        psFree(table);
+        return false;
+    }
+    psFree (table);
+
+    return true;
+}
+
+// read in a readout from the fits file
+psArray *pmSourcesRead_PS1_DEV_1 (psFits *fits, psMetadata *header)
+{
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    PS_ASSERT_PTR_NON_NULL(header, false);
+
+    bool status;
+    psF32 *PAR, *dPAR;
+    psEllipseAxes axes;
+
+    // define PSF model type
+    int modelType = pmModelClassGetType ("PS_MODEL_GAUSS");
+
+    char *PSF_NAME = psMetadataLookupStr (&status, header, "PSF_NAME");
+    if (PSF_NAME != NULL) {
+        modelType = pmModelClassGetType (PSF_NAME);
+    }
+    assert (modelType > -1);
+
+    // XXX need to look up the XSRCNAME entries
+
+    // validate a single row of the table (must match SMP)
+
+    // XXX test return values
+
+    // XXX we have a memory problem, which is illustrated here: if I allocate the sources array
+    // (line 1) before freeing the table, the data is not really freed (but not a leak?)  if I
+    // allocate the sources array *after* freeing the table, the data is actually freed
+    // psArray *fooSources = psArrayAllocEmpty (10000);
+    // psFree (table);
+    // return (fooSources);
+
+
+    // We get the size of the table, and allocate the array of sources first because the table is large and
+    // ephemeral --- when the table gets blown away, whatever is allocated after the table is read.  In fact,
+    // it's better to read the table row by row.
+    long numSources = psFitsTableSize(fits); // Number of sources in table
+    psArray *sources = psArrayAlloc(numSources); // Array of sources, to return
+
+    // convert the table to the pmSource entries
+    // XXX need to chooose PSF vs EXT, based on type?
+    for (int i = 0; i < numSources; i++) {
+        psMetadata *row = psFitsReadTableRow(fits, i); // Table row
+
+        pmSource *source = pmSourceAlloc ();
+        pmModel *model = pmModelAlloc (modelType);
+        source->modelPSF  = model;
+        source->type = PM_SOURCE_TYPE_STAR;
+
+        // NOTE: A SEGV here because "model" is NULL is probably caused by not initialising the models.
+        PAR = model->params->data.F32;
+        dPAR = model->dparams->data.F32;
+
+        PAR[PM_PAR_XPOS]  = psMetadataLookupF32 (&status, row, "X_PSF");
+        PAR[PM_PAR_YPOS]  = psMetadataLookupF32 (&status, row, "Y_PSF");
+        dPAR[PM_PAR_XPOS] = psMetadataLookupF32 (&status, row, "X_PSF_SIG");
+        dPAR[PM_PAR_YPOS] = psMetadataLookupF32 (&status, row, "Y_PSF_SIG");
+        axes.major        = psMetadataLookupF32 (&status, row, "PSF_WIDTH_X");
+        axes.minor        = psMetadataLookupF32 (&status, row, "PSF_WIDTH_Y");
+        axes.theta        = psMetadataLookupF32 (&status, row, "PSF_THETA");
+
+        PAR[PM_PAR_SKY]   = psMetadataLookupF32 (&status, row, "SKY");
+        dPAR[PM_PAR_SKY]  = psMetadataLookupF32 (&status, row, "SKY_SIGMA");
+        source->sky = PAR[PM_PAR_SKY];
+        source->skyErr = dPAR[PM_PAR_SKY];
+
+        // XXX use these to determine PAR[PM_PAR_I0]?
+        source->psfMag    = psMetadataLookupF32 (&status, row, "PSF_INST_MAG");
+        source->errMag    = psMetadataLookupF32 (&status, row, "PSF_INST_MAG_SIG");
+
+        pmPSF_AxesToModel (PAR, axes);
+
+        float lflux = psMetadataLookupF32 (&status, row, "PEAK_FLUX_AS_MAG");
+        float flux = (isfinite(lflux)) ? pow(10.0, -0.4*lflux) : NAN;
+        source->peak = pmPeakAlloc(PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], flux, PM_PEAK_LONE);
+        source->peak->flux = flux;
+
+        source->pixWeight = psMetadataLookupF32 (&status, row, "PSF_QF");
+
+	// note that some older versions used PSF_PROBABILITY: this was not well defined.
+        source->psfChisq  = psMetadataLookupF32 (&status, row, "PSF_CHISQ");
+        source->crNsigma  = psMetadataLookupF32 (&status, row, "CR_NSIGMA");
+        source->extNsigma = psMetadataLookupF32 (&status, row, "EXT_NSIGMA");
+
+        source->mode      = psMetadataLookupU16 (&status, row, "FLAGS");
+        assert (status);
+
+        // XXX other values saved but not loaded?
+        // psMetadataLookupS64 (&status, row, "IPP_IDET");
+        // psMetadataLookupF32 (&status, row, "N_FRAMES");
+
+        sources->data[i] = source;
+        psFree(row);
+    }
+
+    return sources;
+}
+
+bool pmSourcesWrite_PS1_DEV_1_XSRC (psFits *fits, psArray *sources, char *extname, psMetadata *recipe)
+{
+
+    bool status;
+    psArray *table;
+    psMetadata *row;
+    psF32 *PAR, *dPAR;
+    psF32 xPos, yPos;
+    psF32 xErr, yErr;
+
+    // create a header to hold the output data
+    psMetadata *outhead = psMetadataAlloc ();
+
+    // write the links to the image header
+    psMetadataAddStr (outhead, PS_LIST_TAIL, "EXTNAME", PS_META_REPLACE, "xsrc table extension", extname);
+
+    // let's write these out in S/N order
+    sources = psArraySort (sources, pmSourceSortBySN);
+
+    table = psArrayAllocEmpty (sources->n);
+
+    // which extended source analyses should we perform?
+    bool doPetrosian    = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_PETROSIAN");
+    bool doIsophotal    = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ISOPHOTAL");
+    bool doAnnuli       = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANNULI");
+    bool doKron         = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_KRON");
+
+    psVector *radialBinsLower = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.LOWER");
+    psVector *radialBinsUpper = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.UPPER");
+    assert (radialBinsLower->n == radialBinsUpper->n);
+
+    // we write out all sources, regardless of quality.  the source flags tell us the state
+    for (int i = 0; i < sources->n; i++) {
+	// skip source if it is not a ext sourc
+	// XXX we have two places that extended source parameters are measured:
+	// psphotExtendedSources, which measures the aperture-like parameters and (potentially) the psf-convolved extended source models,
+	// psphotFitEXT, which does the simple extended source model fit (not psf-convolved)
+	// should we require both?
+
+	pmSource *source = sources->data[i];
+
+	// skip sources without measurements
+	if (source->extpars == NULL) continue;
+
+	// we require a PSF model fit (ignore the real crud)
+	pmModel *model = source->modelPSF;
+	if (model == NULL) continue;
+
+	// XXX I need to split the extended models from the extended aperture measurements
+	PAR = model->params->data.F32;
+	dPAR = model->dparams->data.F32;
+	xPos = PAR[PM_PAR_XPOS];
+	yPos = PAR[PM_PAR_YPOS];
+	xErr = dPAR[PM_PAR_XPOS];
+	yErr = dPAR[PM_PAR_YPOS];
+
+        row = psMetadataAlloc ();
+
+        // XXX we are not writing out the mode (flags) or the type (psf, ext, etc)
+        psMetadataAdd (row, PS_LIST_TAIL, "IPP_IDET",         PS_DATA_U32, "IPP detection identifier index",             source->seq);
+        psMetadataAdd (row, PS_LIST_TAIL, "X_EXT",            PS_DATA_F32, "EXT model x coordinate",                     xPos);
+        psMetadataAdd (row, PS_LIST_TAIL, "Y_EXT",            PS_DATA_F32, "EXT model y coordinate",                     yPos);
+        psMetadataAdd (row, PS_LIST_TAIL, "X_EXT_SIG",        PS_DATA_F32, "Sigma in EXT x coordinate",                  xErr);
+        psMetadataAdd (row, PS_LIST_TAIL, "Y_EXT_SIG",        PS_DATA_F32, "Sigma in EXT y coordinate",                  yErr);
+
+	// Petrosian measurements
+	// XXX insert header data: petrosian ref radius, flux ratio
+	if (doPetrosian) {
+	    pmSourcePetrosianValues *petrosian = source->extpars->petrosian;
+	    if (petrosian) {
+		psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG",        PS_DATA_F32, "Petrosian Magnitude",       petrosian->mag);
+		psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_ERR",    PS_DATA_F32, "Petrosian Magnitude Error", petrosian->magErr);
+		psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS",     PS_DATA_F32, "Petrosian Radius",          petrosian->rad);
+		psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_ERR", PS_DATA_F32, "Petrosian Radius Error",    petrosian->radErr);
+	    } else {
+		psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG",        PS_DATA_F32, "Petrosian Magnitude",       NAN);
+		psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_ERR",    PS_DATA_F32, "Petrosian Magnitude Error", NAN);
+		psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS",     PS_DATA_F32, "Petrosian Radius",          NAN);
+		psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_ERR", PS_DATA_F32, "Petrosian Radius Error",    NAN);
+	    }
+	} 
+
+	// Kron measurements
+	if (doKron) {
+	    pmSourceKronValues *kron = source->extpars->kron;
+	    if (kron) {
+		psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG",        PS_DATA_F32, "Kron Magnitude",       kron->mag);
+		psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_ERR",    PS_DATA_F32, "Kron Magnitude Error", kron->magErr);
+		psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS",     PS_DATA_F32, "Kron Radius",          kron->rad);
+		psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS_ERR", PS_DATA_F32, "Kron Radius Error",    kron->radErr);
+	    } else {
+		psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG",        PS_DATA_F32, "Kron Magnitude",       NAN);
+		psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_ERR",    PS_DATA_F32, "Kron Magnitude Error", NAN);
+		psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS",     PS_DATA_F32, "Kron Radius",          NAN);
+		psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS_ERR", PS_DATA_F32, "Kron Radius Error",    NAN);
+	    }
+	}
+
+	// Isophot measurements
+	// XXX insert header data: isophotal level
+	if (doIsophotal) {
+	    pmSourceIsophotalValues *isophot = source->extpars->isophot;
+	    if (isophot) {
+		psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG",        PS_DATA_F32, "Isophot Magnitude",       isophot->mag);
+		psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_ERR",    PS_DATA_F32, "Isophot Magnitude Error", isophot->magErr);
+		psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS",     PS_DATA_F32, "Isophot Radius",          isophot->rad);
+		psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS_ERR", PS_DATA_F32, "Isophot Radius Error",    isophot->radErr);
+	    } else {
+		psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG",        PS_DATA_F32, "Isophot Magnitude",       NAN);
+		psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_ERR",    PS_DATA_F32, "Isophot Magnitude Error", NAN);
+		psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS",     PS_DATA_F32, "Isophot Radius",          NAN);
+		psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS_ERR", PS_DATA_F32, "Isophot Radius Error",    NAN);
+	    }
+	}
+
+	// Flux Annuli
+	if (doAnnuli) {
+	    pmSourceAnnuli *annuli = source->extpars->annuli;
+	    if (annuli) {
+		psVector *fluxVal = annuli->flux;
+		psVector *fluxErr = annuli->fluxErr;
+		psVector *fluxVar = annuli->fluxVar;
+
+		for (int j = 0; j < fluxVal->n; j++) {
+		    char name[32];
+		    sprintf (name, "FLUX_VAL_R_%02d", j);
+		    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux value in annulus", fluxVal->data.F32[j]);
+		    sprintf (name, "FLUX_ERR_R_%02d", j);
+		    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux error in annulus", fluxErr->data.F32[j]);
+		    sprintf (name, "FLUX_VAR_R_%02d", j);
+		    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux stdev in annulus", fluxVar->data.F32[j]);
+		} 
+	    } else {
+		for (int j = 0; j < radialBinsLower->n; j++) {
+		    char name[32];
+		    sprintf (name, "FLUX_VAL_R_%02d", j);
+		    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux value in annulus", NAN);
+		    sprintf (name, "FLUX_ERR_R_%02d", j);
+		    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux error in annulus", NAN);
+		    sprintf (name, "FLUX_VAR_R_%02d", j);
+		    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux stdev in annulus", NAN);
+		} 
+	    }
+	}
+
+	psArrayAdd (table, 100, row);
+	psFree (row);
+    }
+
+    if (table->n == 0) {
+	psFitsWriteBlank (fits, outhead, extname);
+	psFree (outhead);
+	psFree (table);
+	return true;
+    }
+
+    psTrace ("pmFPAfile", 5, "writing ext data %s\n", extname);
+    if (!psFitsWriteTable (fits, outhead, table, extname)) {
+	psError(PS_ERR_IO, false, "writing ext data %s\n", extname);
+	psFree (outhead);
+	psFree(table);
+	return false;
+    }
+    psFree (outhead);
+    psFree (table);
+
+    return true;
+}
+
+bool pmSourcesWrite_PS1_DEV_1_XFIT (psFits *fits, psArray *sources, char *extname)
+{
+
+    psArray *table;
+    psMetadata *row;
+    psF32 *PAR, *dPAR;
+    psEllipseAxes axes;
+    psF32 xPos, yPos;
+    psF32 xErr, yErr;
+    char name[64];
+
+    // create a header to hold the output data
+    psMetadata *outhead = psMetadataAlloc ();
+
+    // write the links to the image header
+    psMetadataAddStr (outhead, PS_LIST_TAIL, "EXTNAME", PS_META_REPLACE, "xsrc table extension", extname);
+
+    // let's write these out in S/N order
+    sources = psArraySort (sources, pmSourceSortBySN);
+
+    // we are writing one row per model; we need to write out same number of columns for each row: find the max Nparams
+    int nParamMax = 0;
+    for (int i = 0; i < sources->n; i++) {
+	pmSource *source = sources->data[i];
+	if (source->modelFits == NULL) continue;
+	for (int j = 0; j < source->modelFits->n; j++) {
+	    pmModel *model = source->modelFits->data[j];
+	    assert (model);
+	    nParamMax = PS_MAX (nParamMax, model->params->n);
+	}
+    }
+
+    table = psArrayAllocEmpty (sources->n);
+
+    // we write out all sources, regardless of quality.  the source flags tell us the state
+    for (int i = 0; i < sources->n; i++) {
+
+	pmSource *source = sources->data[i];
+
+	// XXX if no model fits are saved, write out modelEXT?
+	if (source->modelFits == NULL) continue;
+
+	// We have multiple sources : need to flag the one used to subtract the light (the 'best' model)
+	for (int j = 0; j < source->modelFits->n; j++) {
+
+	    // choose the convolved EXT model, if available, otherwise the simple one
+	    pmModel *model = source->modelFits->data[j];
+	    assert (model);
+
+	    PAR = model->params->data.F32;
+	    dPAR = model->dparams->data.F32;
+	    xPos = PAR[PM_PAR_XPOS];
+	    yPos = PAR[PM_PAR_YPOS];
+	    xErr = dPAR[PM_PAR_XPOS];
+	    yErr = dPAR[PM_PAR_YPOS];
+
+	    axes = pmPSF_ModelToAxes (PAR, 20.0);
+
+	    row = psMetadataAlloc ();
+
+	    // XXX we are not writing out the mode (flags) or the type (psf, ext, etc)
+	    psMetadataAddU32 (row, PS_LIST_TAIL, "IPP_IDET",         0, "IPP detection identifier index",             source->seq);
+	    psMetadataAddF32 (row, PS_LIST_TAIL, "X_EXT",            0, "EXT model x coordinate",                     xPos);
+	    psMetadataAddF32 (row, PS_LIST_TAIL, "Y_EXT",            0, "EXT model y coordinate",                     yPos);
+	    psMetadataAddF32 (row, PS_LIST_TAIL, "X_EXT_SIG",        0, "Sigma in EXT x coordinate",                  xErr);
+	    psMetadataAddF32 (row, PS_LIST_TAIL, "Y_EXT_SIG",        0, "Sigma in EXT y coordinate",                  yErr);
+	    psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_INST_MAG",     0, "EXT fit instrumental magnitude",             model->mag);
+	    psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_INST_MAG_SIG", 0, "Sigma of PSF instrumental magnitude",        model->magErr);
+
+	    psMetadataAddF32 (row, PS_LIST_TAIL, "NPARAMS",          0, "number of model parameters",                 model->params->n);
+	    psMetadataAddStr (row, PS_LIST_TAIL, "MODEL_TYPE",       0, "name of model",                              pmModelClassGetName (model->type));
+
+	    // XXX these should be major and minor, not 'x' and 'y'
+	    psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_WIDTH_MAJ",    0, "EXT width in x coordinate",                  axes.major);
+	    psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_WIDTH_MIN",    0, "EXT width in y coordinate",                  axes.minor);
+	    psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_THETA",        0, "EXT orientation angle",                      axes.theta);
+
+	    // write out the other generic parameters
+	    for (int k = 0; k < nParamMax; k++) {
+		if (k == PM_PAR_I0) continue;
+		if (k == PM_PAR_SKY) continue;
+		if (k == PM_PAR_XPOS) continue;
+		if (k == PM_PAR_YPOS) continue;
+		if (k == PM_PAR_SXX) continue;
+		if (k == PM_PAR_SXY) continue;
+		if (k == PM_PAR_SYY) continue;
+
+		snprintf (name, 64, "EXT_PAR_%02d", k);
+
+		if (k < model->params->n) {
+		    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "", model->params->data.F32[k]);
+		} else {
+		    psMetadataAddF32 (row, PS_LIST_TAIL, name, PS_DATA_F32, "", NAN);
+		}
+	    }
+
+	    // XXX other parameters which may be set.
+	    // XXX flag / value to define the model
+	    // XXX write out the model type, fit status flags
+
+	    psArrayAdd (table, 100, row);
+	    psFree (row);
+	}
+    }
+
+    if (table->n == 0) {
+	psFitsWriteBlank (fits, outhead, extname);
+	psFree (outhead);
+	psFree (table);
+	return true;
+    }
+
+    psTrace ("pmFPAfile", 5, "writing ext data %s\n", extname);
+    if (!psFitsWriteTable (fits, outhead, table, extname)) {
+	psError(PS_ERR_IO, false, "writing ext data %s\n", extname);
+	psFree (outhead);
+	psFree(table);
+	return false;
+    }
+    psFree (outhead);
+    psFree (table);
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_RAW.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_RAW.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_RAW.c	(revision 22158)
@@ -0,0 +1,293 @@
+/** @file  pmSourceIO.c
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.18 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmGrowthCurve.h"
+#include "pmResiduals.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmModelClass.h"
+#include "pmSourcePhotometry.h"
+#include "pmSourceIO.h"
+
+/***** Text Output Methods *****/
+bool pmSourcesWriteRAW (psArray *sources, char *filename)
+{
+
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(filename, false);
+
+    char *name = (char *) psAlloc (strlen(filename) + 10);
+
+    sprintf (name, "%s.psf.dat", filename);
+    pmSourcesWritePSFs (sources, name);
+
+    sprintf (name, "%s.ext.dat", filename);
+    pmSourcesWriteEXTs (sources, name, true);
+
+    sprintf (name, "%s.nul.dat", filename);
+    pmSourcesWriteNULLs (sources, name);
+
+    sprintf (name, "%s.mnt.dat", filename);
+    pmMomentsWriteText (sources, name);
+
+    psFree (name);
+    return true;
+}
+
+// write the PSF sources to an output file
+bool pmSourcesWritePSFs (psArray *sources, char *filename)
+{
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(filename, false);
+
+    double dPos;
+    int i, j;
+    FILE *f;
+    psF32 *PAR, *dPAR;
+    pmModel  *model;
+
+    f = fopen (filename, "w");
+    if (f == NULL) {
+        psLogMsg (__func__, 3, "can't open output file for PSF sources: %s\n", filename);
+        return false;
+    }
+
+    // write sources with models first
+    for (i = 0; i < sources->n; i++) {
+        pmSource *source = (pmSource *) sources->data[i];
+        if (source->type != PM_SOURCE_TYPE_STAR)
+            continue;
+        model = source->modelPSF;
+        if (model == NULL)
+            continue;
+
+        PAR  = model->params->data.F32;
+        dPAR = model->dparams->data.F32;
+
+        // dPos is positional error, dMag is mag error
+        dPos = hypot (dPAR[PM_PAR_XPOS], dPAR[PM_PAR_YPOS]);
+
+        fprintf (f, "%7.1f %7.1f  %7.1f %8.4f  %7.4f %7.4f  ",
+                 PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], source->sky,
+                 source->psfMag, source->errMag, dPos);
+
+        for (j = 4; j < model->params->n; j++) {
+            fprintf (f, "%9.6f ", PAR[j]);
+        }
+        fprintf (f, " : ");
+        for (j = 4; j < model->params->n; j++) {
+            fprintf (f, "%9.6f ", dPAR[j]);
+        }
+
+        float logChi = ((model[0].chisq == 0.0) || (model[0].nDOF == 0)) ? NAN : log10(model[0].chisq/model[0].nDOF);
+        float logChiNorm = ((model[0].chisqNorm == 0.0) || (model[0].nDOF == 0)) ? NAN : log10(model[0].chisqNorm/model[0].nDOF);
+
+        fprintf (f, ": %8.4f %2d %#5x %7.3f %7.3f  %7.1f %7.2f %4.2f %4d %2d\n",
+                 source[0].apMag, source[0].type, source[0].mode,
+                 logChi, logChiNorm,
+                 source[0].peak->SN,
+                 model[0].radiusFit,
+                 source[0].pixWeight,
+                 model[0].nDOF,
+                 model[0].nIter);
+    }
+    fclose (f);
+    return true;
+}
+
+// dump the sources to an output file
+bool pmSourcesWriteEXTs (psArray *sources, char *filename, bool requireEXT)
+{
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(filename, false);
+
+    double dPos;
+    int i, j;
+    FILE *f;
+    psF32 *PAR, *dPAR;
+    pmModel  *model;
+
+    f = fopen (filename, "w");
+    if (f == NULL) {
+        psLogMsg ("pmModelWriteEXTs", 3, "can't open output file for EXT sources: %s\n", filename);
+        return false;
+    }
+
+    // write sources with models first
+    for (i = 0; i < sources->n; i++) {
+        pmSource *source = (pmSource *) sources->data[i];
+
+        if (requireEXT && (source->type != PM_SOURCE_TYPE_EXTENDED))
+            continue;
+
+        model = source->modelEXT;
+        if (model == NULL)
+            continue;
+
+        PAR  = model->params->data.F32;
+        dPAR = model->dparams->data.F32;
+
+        // dPos is shape error
+        // XXX these are hardwired for SGAUSS
+        dPos = hypot ((dPAR[PM_PAR_SXX] / PAR[PM_PAR_SXX]), (dPAR[PM_PAR_SYY] / PAR[PM_PAR_SYY]));
+
+        fprintf (f, "%7.1f %7.1f  %7.1f %8.4f  %7.4f %7.4f  ",
+                 PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], source->sky,
+                 source->extMag, source->errMag, dPos);
+
+        for (j = 4; j < model->params->n; j++) {
+            fprintf (f, "%9.6f ", PAR[j]);
+        }
+        fprintf (f, " : ");
+        for (j = 4; j < model->params->n; j++) {
+            fprintf (f, "%9.6f ", dPAR[j]);
+        }
+        fprintf (f, ": %7.4f  %2d %#5x %7.3f %7.3f  %7.1f %7.2f %4.2f %4d %2d\n",
+                 source->apMag,
+                 source[0].type, source[0].mode,
+                 log10(model[0].chisq/model[0].nDOF),
+                 log10(model[0].chisqNorm/model[0].nDOF),
+                 source[0].peak->SN,
+                 model[0].radiusFit,
+                 source[0].pixWeight,
+                 model[0].nDOF,
+                 model[0].nIter);
+    }
+    fclose (f);
+    return true;
+}
+
+// dump the sources to an output file
+bool pmSourcesWriteNULLs (psArray *sources, char *filename)
+{
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(filename, false);
+
+    int i;
+    FILE *f;
+    pmMoments *moment = NULL;
+    pmSource *source = NULL;
+
+    f = fopen (filename, "w");
+    if (f == NULL) {
+        psLogMsg ("DumpObjects", 3, "can't open output file for NULL sources: %s\n", filename);
+        return false;
+    }
+
+    pmMoments *empty = pmMomentsAlloc ();
+
+    // write sources with models first
+    for (i = 0; i < sources->n; i++) {
+        source = sources->data[i];
+
+        // skip these sources (in PSF or EXT)
+        if (source->type == PM_SOURCE_TYPE_STAR)
+            continue;
+        if (source->type == PM_SOURCE_TYPE_EXTENDED)
+            continue;
+
+        if (source->moments == NULL) {
+            moment = empty;
+        } else {
+            moment = source->moments;
+        }
+
+        fprintf (f, "%5d %5d  %7.1f  %7.1f %7.1f  %6.3f %6.3f  %8.1f %7.1f %7.1f %7.1f  %4d %2d\n",
+                 source->peak->x, source->peak->y, source->peak->value,
+                 moment->x, moment->y,
+                 moment->Sx, moment->Sy,
+                 moment->Sum, moment->Peak,
+                 moment->Sky, moment->SN,
+                 moment->nPixels, source->type);
+    }
+    fclose (f);
+    psFree (empty);
+    return true;
+}
+
+// write the moments to an output file
+bool pmMomentsWriteText (psArray *sources, char *filename)
+{
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(filename, false);
+
+    int i;
+    FILE *f;
+    pmSource *source = NULL;
+
+    f = fopen (filename, "w");
+    if (f == NULL) {
+        psLogMsg ("pmMomentsWriteText", 3, "can't open output file for moments: %s\n", filename);
+        return false;
+    }
+
+    for (i = 0; i < sources->n; i++) {
+        source = sources->data[i];
+        if (source->moments == NULL)
+            continue;
+        fprintf (f, "%5d %5d  %7.1f  %7.1f %7.1f  %6.3f %6.3f  %10.1f %7.1f %7.1f %7.1f  %4d %2d %#5x\n",
+                 source->peak->x, source->peak->y, source->peak->value,
+                 source->moments->x, source->moments->y,
+                 source->moments->Sx, source->moments->Sy,
+                 source->moments->Sum, source->moments->Peak,
+                 source->moments->Sky, source->moments->SN,
+                 source->moments->nPixels, source->type, source->mode);
+    }
+    fclose (f);
+    return true;
+}
+
+// write the peaks to an output file
+bool pmPeaksWriteText (psArray *peaks, char *filename)
+{
+
+    int i;
+    FILE *f;
+
+    f = fopen (filename, "w");
+    if (f == NULL) {
+        psLogMsg ("pmPeaksWriteText", 3, "can't open output file for peaks%s\n", filename);
+        return false;
+    }
+
+    for (i = 0; i < peaks->n; i++) {
+        pmPeak *peak = peaks->data[i];
+        if (peak == NULL)
+            continue;
+        fprintf (f, "%5d %5d  %7.1f %7.2f %7.2f %7.2f\n",
+                 peak->x, peak->y, peak->value, peak->SN, peak->xf, peak->yf);
+    }
+    fclose (f);
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_SMPDATA.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_SMPDATA.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_SMPDATA.c	(revision 22158)
@@ -0,0 +1,202 @@
+/** @file  pmSourceIO.c
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmResiduals.h"
+#include "pmGrowthCurve.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmModelClass.h"
+#include "pmSourceIO.h"
+
+// elixir-style FITS table output (header + table in 1st extension)
+// this format consists of a header derived from the image header
+// followed by a zero-size matrix, followed by the table data
+// XXX: input parameter imageHeader is never used
+bool pmSourcesWrite_SMPDATA (psFits *fits, psArray *sources, psMetadata *imageHeader,
+                             psMetadata *tableHeader, char *extname)
+{
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(extname, false);
+
+    psArray *table;
+    psMetadata *row;
+    int i;
+    psF32 *PAR, *dPAR;
+    bool status;
+    psEllipseAxes axes;
+    psF32 xPos, yPos;
+
+    // find config information for output header
+    float ZERO_POINT = psMetadataLookupF32 (&status, imageHeader, "ZERO_PT");
+    if (!status)
+        ZERO_POINT = 25.0;
+
+    float lsky = 0;
+    int type = 0;
+
+    table = psArrayAllocEmpty (sources->n);
+
+    for (i = 0; i < sources->n; i++) {
+        pmSource *source = (pmSource *) sources->data[i];
+
+	// no difference between PSF and non-PSF model
+        pmModel *model = pmSourceGetModel (NULL, source);
+        if (model != NULL) {
+	    PAR = model->params->data.F32;
+	    dPAR = model->dparams->data.F32;
+	    xPos = PAR[PM_PAR_XPOS];
+	    yPos = PAR[PM_PAR_YPOS];
+
+	    type = pmSourceGetDophotType (source);
+	    lsky = (source->sky < 1.0) ? 0.0 : log10(source->sky);
+
+	    axes = pmPSF_ModelToAxes (PAR, 20.0);
+
+	} else {
+	    xPos = source->peak->xf;
+	    yPos = source->peak->yf;
+	    axes.major = 0.0;
+	    axes.minor = 0.0;
+	    axes.theta = 0.0;
+	}
+
+        row = psMetadataAlloc ();
+        psMetadataAdd (row, PS_LIST_TAIL, "X_PIX",   PS_DATA_F32, "", xPos);
+        psMetadataAdd (row, PS_LIST_TAIL, "Y_PIX",   PS_DATA_F32, "", yPos);
+        psMetadataAdd (row, PS_LIST_TAIL, "MAG_RAW", PS_DATA_F32, "", PS_MIN (99.0, source->psfMag + ZERO_POINT));
+        psMetadataAdd (row, PS_LIST_TAIL, "MAG_ERR", PS_DATA_F32, "", PS_MIN (999, 1000*source->errMag));
+        psMetadataAdd (row, PS_LIST_TAIL, "MAG_GAL", PS_DATA_F32, "", PS_MIN (99.0, source->extMag + ZERO_POINT));
+        psMetadataAdd (row, PS_LIST_TAIL, "MAG_AP",  PS_DATA_F32, "", PS_MIN (99.0, source->apMag + ZERO_POINT));
+        psMetadataAdd (row, PS_LIST_TAIL, "LOG_SKY", PS_DATA_F32, "", lsky);
+        psMetadataAdd (row, PS_LIST_TAIL, "FWHM_X",  PS_DATA_F32, "", axes.major);
+        psMetadataAdd (row, PS_LIST_TAIL, "FWHM_Y",  PS_DATA_F32, "", axes.minor);
+        psMetadataAdd (row, PS_LIST_TAIL, "THETA",   PS_DATA_F32, "", axes.theta);
+        psMetadataAdd (row, PS_LIST_TAIL, "DOPHOT",  PS_DATA_U8,  "", type);
+        psMetadataAdd (row, PS_LIST_TAIL, "WEIGHT",  PS_DATA_U8,  "", PS_MIN (255, PS_MAX(0, 255*source->pixWeight)));
+        psMetadataAdd (row, PS_LIST_TAIL, "DUMMY",   PS_DATA_U16, "", 0);
+
+        psArrayAdd (table, 100, row);
+        psFree (row);
+    }
+
+    if (table->n == 0) {
+        psFitsWriteBlank (fits, tableHeader, extname);
+        psFree (table);
+        return true;
+    }
+
+    psTrace ("pmFPAfile", 5, "writing ext data %s\n", extname);
+    if (!psFitsWriteTable (fits, tableHeader, table, extname)) {
+        psError(PS_ERR_IO, false, "writing ext data %s\n", extname);
+        psFree(table);
+        return false;
+    }
+
+    psFree (table);
+    return true;
+}
+
+// read in a readout from the fits file
+psArray *pmSourcesRead_SMPDATA (psFits *fits, psMetadata *header)
+{
+    PS_ASSERT_PTR_NON_NULL(fits, false);
+    PS_ASSERT_PTR_NON_NULL(header, false);
+
+    bool status;
+    psF32 *PAR, *dPAR;
+    psEllipseAxes axes;
+    float lsky;
+
+    // define PSF model type
+    int modelType = pmModelClassGetType ("PS_MODEL_GAUSS");
+
+    char *PSF_NAME = psMetadataLookupStr (&status, header, "PSF_NAME");
+    if (PSF_NAME != NULL) {
+        modelType = pmModelClassGetType (PSF_NAME);
+    }
+
+    // find config information for output header
+    float ZERO_POINT = psMetadataLookupF32 (&status, header, "ZERO_PT");
+    if (!status)
+        ZERO_POINT = 25.0;
+
+    psArray *table = psFitsReadTable (fits);
+    // validate a single row of the table (must match SMP)
+
+    psArray *sources = psArrayAlloc (table->n);
+
+    // convert the table to the pmSource entries
+    // XXX need to chooose PSF vs EXT, based on type?
+    for (int i = 0; i < table->n; i++) {
+        pmSource *source = pmSourceAlloc ();
+        pmModel *model = pmModelAlloc (modelType);
+        source->modelPSF  = model;
+        source->type = PM_SOURCE_TYPE_STAR;
+
+        PAR = model->params->data.F32;
+        dPAR = model->dparams->data.F32;
+
+        psMetadata *row = table->data[i];
+
+        lsky             = psMetadataLookupF32 (&status, row, "LOG_SKY");
+        PAR[PM_PAR_SKY]  = pow(10.0, lsky);
+        source->sky    = PAR[PM_PAR_SKY];
+
+        PAR[PM_PAR_XPOS] = psMetadataLookupF32 (&status, row, "X_PIX");
+        PAR[PM_PAR_YPOS] = psMetadataLookupF32 (&status, row, "Y_PIX");
+        axes.major       = psMetadataLookupF32 (&status, row, "FWHM_X");
+        axes.minor       = psMetadataLookupF32 (&status, row, "FWHM_Y");
+        axes.theta       = psMetadataLookupF32 (&status, row, "THETA");
+
+	pmPSF_AxesToModel (PAR, axes);
+
+
+        source->psfMag = psMetadataLookupF32 (&status, row, "MAG_RAW") - ZERO_POINT;
+        source->extMag = psMetadataLookupF32 (&status, row, "MAG_GAL") - ZERO_POINT;
+        source->errMag = psMetadataLookupF32 (&status, row, "MAG_ERR") * 0.001;
+        source->apMag  = psMetadataLookupF32 (&status, row, "MAG_AP")  - ZERO_POINT;
+
+        source->pixWeight = psMetadataLookupU8 (&status, row, "WEIGHT")/255.0;
+        int dophot = psMetadataLookupU8 (&status, row, "DOPHOT");
+	pmSourceSetDophotType (source, dophot);
+
+	double Area = 2.0 * M_PI * axes.major * axes.minor;
+	double peakFlux = source->psfMag / Area;
+
+	source->peak = pmPeakAlloc(PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], peakFlux, PM_PEAK_LONE);
+        sources->data[i] = source;
+    }
+    psFree (table);
+    return (sources);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_SX.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_SX.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceIO_SX.c	(revision 22158)
@@ -0,0 +1,95 @@
+/** @file  pmSourceIO.c
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmGrowthCurve.h"
+#include "pmResiduals.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmModelClass.h"
+#include "pmSourceIO.h"
+
+// elixir-mode / sextractor-style output list with fixed line width
+bool pmSourcesWriteSX (psArray *sources, char *filename)
+{
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(filename, false);
+
+    psF32 *PAR, *dPAR;
+    psEllipseAxes axes;
+
+    psLine *line = psLineAlloc (110);  // 110 is sextractor line length
+
+    FILE *f = fopen (filename, "w");
+    if (f == NULL) {
+        psLogMsg (__func__, 3, "can't open output file for output %s\n", filename);
+        return false;
+    }
+
+    // write sources with models
+    for (int i = 0; i < sources->n; i++) {
+        pmSource *source = (pmSource *) sources->data[i];
+
+	// no difference between PSF and non-PSF model
+        pmModel *model = pmSourceGetModel (NULL, source);
+        if (model == NULL)
+            continue;
+
+        PAR = model->params->data.F32;
+        dPAR = model->dparams->data.F32;
+
+        // pmSourceSextractType (source, &type, &flags);
+
+	axes = pmPSF_ModelToAxes (PAR, 20.0);
+
+        psLineInit (line);
+        psLineAdd (line, "%5.2f",  0.0); // should be type
+        psLineAdd (line, "%11.3f", PAR[PM_PAR_XPOS]);
+        psLineAdd (line, "%11.3f", PAR[PM_PAR_YPOS]);
+        psLineAdd (line, "%9.4f",  source->psfMag);
+        psLineAdd (line, "%9.4f",  source->errMag);
+        psLineAdd (line, "%13.4f", source->sky);
+        psLineAdd (line, "%9.2f",  axes.major);
+        psLineAdd (line, "%9.2f",  axes.minor);
+        psLineAdd (line, "%6.1f",  axes.theta);
+        psLineAdd (line, "%9.4f",  source->extMag);
+        psLineAdd (line, "%9.4f",  source->apMag);
+        psLineAdd (line, "%4d\n",  0); // should be flags
+        fwrite (line->line, 1, line->Nline, f);
+    }
+    fclose (f);
+    psFree (line);
+    return true;
+}
+
+// XXX need to fix the FWHM / shape stuff,
+// XXX make sure we are using the correct mags, etc
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePhotometry.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePhotometry.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePhotometry.c	(revision 22158)
@@ -0,0 +1,809 @@
+/** @file  pmSourcePhotometry.c
+ *
+ *  @author EAM, IfA; GLG, MHPCC
+ *
+ *  @version $Revision: 1.43 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-15 20:25:00 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+#include "pmErrorCodes.h"
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPAMaskWeight.h"
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmGrowthCurve.h"
+#include "pmResiduals.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmModelClass.h"
+#include "pmSourcePhotometry.h"
+
+# define DO_SKY 0
+
+static float AP_MIN_SN = 0.0;
+
+bool pmSourceMagnitudesInit (psMetadata *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    bool status;
+
+    float limit = psMetadataLookupF32 (&status, config, "AP_MIN_SN");
+    if (status) {
+        AP_MIN_SN = limit;
+    }
+    return true;
+}
+
+/**
+    this function is used to calculate the three defined source magnitudes:
+    - apMag  : only if S/N > AP_MIN_SN
+             : is optionally corrected for curve-of-growth if:
+        - the source is a STAR (PSF)
+        - the option is selected (mode & PM_SOURCE_PHOT_GROWTH)
+    - psfMag : all sources with non-NULL modelPSF
+             : is optionally corrected for aperture residual if:
+        - the source is a STAR (PSF)
+        - the option is selected (mode & PM_SOURCE_PHOT_APCORR)
+
+    - extMag : all sources with non-NULL modelEXT
+**/
+
+// XXX masked region should be (optionally) elliptical
+bool pmSourceMagnitudes (pmSource *source, pmPSF *psf, pmSourcePhotometryMode mode, psMaskType maskVal)
+{
+    PS_ASSERT_PTR_NON_NULL(source, false);
+    PS_ASSERT_PTR_NON_NULL(psf, false);
+
+    int status = false;
+    bool isPSF;
+    float x, y;
+    float rflux;
+    float SN;
+    pmModel *model;
+
+    source->psfMag = NAN;
+    source->extMag = NAN;
+    source->errMag = NAN;
+    source->apMag  = NAN;
+
+    // we must have a valid model
+    model = pmSourceGetModel (&isPSF, source);
+    if (model == NULL) {
+        psTrace ("psModules.objects", 3, "fail mag : no valid model");
+        return false;
+    }
+
+    if (model->dparams->data.F32[PM_PAR_I0] > 0) {
+        SN = model->params->data.F32[PM_PAR_I0] / model->dparams->data.F32[PM_PAR_I0];
+        source->errMag = 1.0 / SN;
+    } else {
+        SN = NAN;
+        source->errMag = NAN;
+    }
+    x = model->params->data.F32[PM_PAR_XPOS];
+    y = model->params->data.F32[PM_PAR_YPOS];
+
+    // measure PSF model photometry
+    if (psf->FluxScale) {
+        // the source peak pixel is guaranteed to be on the image, and only minimally different from the source center
+        double fluxScale = pmTrend2DEval (psf->FluxScale, (float)source->peak->x, (float)source->peak->y);
+        if (!isfinite(fluxScale)) {
+            // XXX objects on the edge can be slightly outside -- if we get an
+            // error, use the full fit.
+            psErrorClear();
+            status = pmSourcePhotometryModel (&source->psfMag, source->modelPSF);
+        } else {
+            if (isfinite(fluxScale) && (fluxScale > 0.0)) {
+                source->psfMag = -2.5*log10(fluxScale * source->modelPSF->params->data.F32[PM_PAR_I0]);
+            } else {
+                source->psfMag = NAN;
+            }
+        }
+    } else {
+        status = pmSourcePhotometryModel (&source->psfMag, source->modelPSF);
+    }
+
+    // if we have a collection of model fits, one of them is a pointer to modelEXT?
+    // XXX not guaranteed
+    if (source->modelFits) {
+      for (int i = 0; i < source->modelFits->n; i++) {
+	pmModel *model = source->modelFits->data[i];
+	status = pmSourcePhotometryModel (&model->mag, model);
+      }
+      if (source->modelEXT) {
+	source->extMag = source->modelEXT->mag;
+      }
+    } else {
+      if (source->modelEXT) {
+	status = pmSourcePhotometryModel (&source->extMag, source->modelEXT);
+      }
+    }
+
+    // for PSFs, correct both apMag and psfMag to same system, consistent with infinite flux star in aperture RADIUS
+    if ((mode & PM_SOURCE_PHOT_APCORR) && isPSF && psf && psf->ApTrend) {
+        // the source peak pixel is guaranteed to be on the image, and only minimally different from the source center
+        double apTrend = pmTrend2DEval (psf->ApTrend, (float)source->peak->x, (float)source->peak->y);
+        source->psfMag += apTrend;
+    }
+
+    if (!isfinite(SN) || (SN < AP_MIN_SN)) {
+        psTrace ("psModules.objects", 3, "fail mag : bad SN: %f (limit: %f)", SN, AP_MIN_SN);
+        return false;
+    }
+
+    // replace source flux
+    // XXX need to be certain which model and size of mask for prior subtraction
+    // XXX full model or just analytical?
+    // XXX use pmSourceAdd instead?
+    if (source->mode & PM_SOURCE_MODE_SUBTRACTED) {
+        pmModelAdd (source->pixels, source->maskObj, model, PM_MODEL_OP_FULL, maskVal);
+    }
+
+    // if we are measuring aperture photometry and applying the growth correction,
+    // we need to shift the flux in the selected pixels (but not the mask)
+    // psImageShift ();
+    psImage *flux = NULL, *mask = NULL; // Star flux and mask images, to photometer
+    if (mode & PM_SOURCE_PHOT_INTERP) {
+        float dx = 0.5 - x + (int)x;
+        float dy = 0.5 - y + (int)y;
+        x += dx;
+        y += dy;
+
+        if (!psImageShiftMask(&flux, &mask, source->pixels, source->maskObj, maskVal, dx, dy,
+                              NAN, 0xff, PS_INTERPOLATE_BICUBE)) {
+            // Not much we can do about it
+            psErrorClear();
+            psTrace ("psModules.objects", 3, "fail shift");
+            return false;
+        }
+
+        // XXX this is test code to verify the shift is doing the right thing (seems to be)
+        # if (0)
+            // measure centroid of unshifted gaussian (should be 16.0,16.0)
+        {
+            psImage *image = source->pixels;
+            float xo = 0.0;
+            float yo = 0.0;
+            float xo2 = 0.0;
+            float yo2 = 0.0;
+            float no = 0.0;
+            for (int j = 0; j < image->numRows; j++)
+            {
+                for (int i = 0; i < image->numCols; i++) {
+                    xo += i*image->data.F32[j][i];
+                    yo += j*image->data.F32[j][i];
+                    xo2 += i*i*image->data.F32[j][i];
+                    yo2 += j*j*image->data.F32[j][i];
+                    no += image->data.F32[j][i];
+                }
+            }
+            xo /= no;
+            yo /= no;
+            xo2 = sqrt (xo2/no - xo*xo);
+            yo2 = sqrt (yo2/no - yo*yo);
+            fprintf (stderr, "pre-shift centroid: %f,%f, sigma: %f,%f: flux: %f\n", xo, yo, xo2, yo2, no);
+        }
+
+        // measure centroid of unshifted gaussian (should be 16.0,16.0)
+        {
+            psImage *image = flux;
+            float xo = 0.0;
+            float yo = 0.0;
+            float xo2 = 0.0;
+            float yo2 = 0.0;
+            float no = 0.0;
+            for (int j = 0; j < image->numRows; j++)
+            {
+                for (int i = 0; i < image->numCols; i++) {
+                    xo += i*image->data.F32[j][i];
+                    yo += j*image->data.F32[j][i];
+                    xo2 += i*i*image->data.F32[j][i];
+                    yo2 += j*j*image->data.F32[j][i];
+                    no += image->data.F32[j][i];
+                }
+            }
+            xo /= no;
+            yo /= no;
+            xo2 = sqrt (xo2/no - xo*xo);
+            yo2 = sqrt (yo2/no - yo*yo);
+            fprintf (stderr, "pre-shift centroid: %f,%f, sigma: %f,%f: flux: %f\n", xo, yo, xo2, yo2, no);
+        }
+        # endif
+
+    } else {
+        flux = source->pixels;
+        mask = source->maskObj;
+    }
+
+    // measure the weight of included pixels
+    // XXX is this supposed to use the weight or the flux?
+    if (mode & PM_SOURCE_PHOT_WEIGHT) {
+        pmSourcePixelWeight (&source->pixWeight, model, source->pixels, source->maskObj, maskVal);
+    }
+
+    // measure object aperture photometry
+    status = pmSourcePhotometryAper  (&source->apMag, model, flux, mask, maskVal);
+    if (!status) {
+        psTrace ("psModules.objects", 3, "fail mag : bad Ap Mag");
+    }
+
+    // for PSFs, correct both apMag and psfMag to same system, consistent with infinite flux star in aperture RADIUS
+    // if the aper mag is NAN, the flux < 0.  this can happen for sources near the
+    // detection limits (esp near bright neighbors)
+    if (isfinite (source->apMag) && isPSF && psf) {
+        if (psf->growth && (mode & PM_SOURCE_PHOT_GROWTH)) {
+            source->apMag += pmGrowthCurveCorrect (psf->growth, model->radiusFit);
+        }
+        if (mode & PM_SOURCE_PHOT_APCORR) {
+	    rflux   = pow (10.0, 0.4*source->psfMag);
+	    source->apMag -= PS_SQR(model->radiusFit)*rflux * psf->skyBias + psf->skySat / rflux;
+        }
+    }
+    if (mode & PM_SOURCE_PHOT_INTERP) {
+        psFree(flux);
+        psFree(mask);
+    }
+
+    // if source was originally subtracted, re-subtract object, leave local sky
+    // XXX replace with pmSourceSub...
+    if (source->mode & PM_SOURCE_MODE_SUBTRACTED) {
+        pmModelSub (source->pixels, source->maskObj, model, PM_MODEL_OP_FULL, maskVal);
+    }
+
+    return status;
+}
+
+/*
+aprMag' - fitMag = flux*skySat + r^2*rflux*skyBias + ApTrend(x,y)
+(aprMag - flux*skySat - r^2*rflux*skyBias) - fitMAg = ApTrend(x,y)
+(aprMag - flux*skySat - r^2*rflux*skyBias) = fitMAg + ApTrend(x,y)
+
+*/
+
+// return source model magnitude
+bool pmSourcePhotometryModel (float *fitMag, pmModel *model)
+{
+    PS_ASSERT_PTR_NON_NULL(fitMag, false);
+    if (model == NULL) {
+        return false;
+    }
+
+    float fitSum = 0;
+    *fitMag = NAN;
+
+    // measure fitMag
+    fitSum = model->modelFlux (model->params);
+    if (fitSum <= 0)
+        return false;
+    if (!isfinite(fitSum))
+        return false;
+    *fitMag = -2.5*log10(fitSum);
+
+    return (true);
+}
+
+// return source aperture magnitude
+bool pmSourcePhotometryAper (float *apMag, pmModel *model, psImage *image, psImage *mask, psMaskType maskVal)
+{
+    PS_ASSERT_PTR_NON_NULL(apMag, false);
+    PS_ASSERT_PTR_NON_NULL(image, false);
+    PS_ASSERT_PTR_NON_NULL(mask, false);
+    PS_ASSERT_PTR_NON_NULL(model, false);
+
+    float apSum = 0;
+    float sky = 0;
+    *apMag = NAN;
+
+    if (DO_SKY) {
+        sky = model->params->data.F32[PM_PAR_SKY];
+    } else {
+        sky = 0;
+    }
+
+    psF32 **imData = image->data.F32;
+    psU8 **mkData = mask->data.U8;
+
+    // measure apMag
+    for (int ix = 0; ix < image->numCols; ix++) {
+        for (int iy = 0; iy < image->numRows; iy++) {
+            if (mkData[iy][ix] & maskVal)
+                continue;
+            apSum += imData[iy][ix] - sky;
+        }
+    }
+    if (apSum <= 0) {
+	*apMag = NAN;
+        return true;
+    }
+
+    *apMag = -2.5*log10(apSum);
+    return true;
+}
+
+// return source aperture magnitude
+bool pmSourcePixelWeight (float *pixWeight, pmModel *model, psImage *image, psImage *mask, psMaskType maskVal)
+{
+    PS_ASSERT_PTR_NON_NULL(pixWeight, false);
+    PS_ASSERT_PTR_NON_NULL(image, false);
+    PS_ASSERT_PTR_NON_NULL(mask, false);
+    PS_ASSERT_PTR_NON_NULL(model, false);
+
+    float modelSum = 0;
+    float validSum = 0;
+    float sky = 0;
+    float value;
+
+    int Xo, Yo, dP;
+    int dX, DX, NX;
+    int dY, DY, NY;
+
+    *pixWeight = 0.0;
+
+    // we only care about the value of the object model, not the local sky
+    if (DO_SKY) {
+        sky = model->params->data.F32[PM_PAR_SKY];
+    } else {
+        sky = 0;
+    }
+
+    // the model function returns the source flux at a position
+    psVector *coord = psVectorAlloc(2, PS_TYPE_F32);
+
+    psVector *params = model->params;
+
+    Xo = params->data.F32[PM_PAR_XPOS];
+    Yo = params->data.F32[PM_PAR_YPOS];
+
+    dX = Xo - image->col0;
+    dP = image->numCols - dX;
+    DX = PS_MAX(dX, dP);
+    NX = image->numCols;
+
+    dY = Yo - image->row0;
+    dP = image->numRows - dY;
+    DY = PS_MAX(dY, dP);
+    NY = image->numRows;
+
+    // measure modelSum and validSum
+    // XXX this does not work for sources near the edge: we need to measure for
+    // a full square region
+    for (int ix = -DX; ix < DX + 1; ix++) {
+        int mx = ix + dX;
+        for (int iy = -DY; iy < DY + 1; iy++) {
+            int my = iy + dY;
+
+            coord->data.F32[0] = (psF32) (ix + Xo);
+            coord->data.F32[1] = (psF32) (iy + Yo);
+
+            // for the full model, add all points
+            value = model->modelFunc (NULL, params, coord) - sky;
+            modelSum += value;
+
+            // include count only the unmasked pixels within the image area
+            if (mx < 0)
+                continue;
+            if (my < 0)
+                continue;
+            if (mx >= NX)
+                continue;
+            if (my >= NY)
+                continue;
+            if (mask->data.U8[my][mx] & maskVal)
+                continue;
+
+            validSum += value;
+        }
+    }
+    psFree (coord);
+
+    if (validSum <= 0)
+        return false;
+
+    *pixWeight = validSum / modelSum;
+    return (true);
+}
+
+# if (0)
+double pmSourceCrossProduct (const pmSource *Mi,
+                             const pmSource *Mj,
+                             const bool unweighted_sum) // should the cross product be weighted?
+{
+    PS_ASSERT_PTR_NON_NULL(Mi, NAN);
+    PS_ASSERT_PTR_NON_NULL(Mj, NAN);
+
+    int Xs, Xe, Ys, Ye;
+    int xi, xj, yi, yj;
+    int xIs, xJs, yIs, yJs;
+    int xIe, yIe;
+    double flux, wt;
+
+    const psImage *Pi = Mi->pixels;
+    assert (Pi != NULL);
+    const psImage *Pj = Mj->pixels;
+    assert (Pj != NULL);
+
+    const psImage *Wi = Mi->weight;
+    if (!unweighted_sum) {
+        assert (Wi != NULL);
+    }
+
+    const psImage *Ti = Mi->maskObj;
+    assert (Ti != NULL);
+    const psImage *Tj = Mj->maskObj;
+    assert (Tj != NULL);
+
+    Xs = PS_MAX (Pi->col0, Pj->col0);
+    Xe = PS_MIN (Pi->col0 + Pi->numCols, Pj->col0 + Pj->numCols);
+
+    Ys = PS_MAX (Pi->row0, Pj->row0);
+    Ye = PS_MIN (Pi->row0 + Pi->numRows, Pj->row0 + Pj->numRows);
+
+    xIs = Xs - Pi->col0;
+    xJs = Xs - Pj->col0;
+    yIs = Ys - Pi->row0;
+    yJs = Ys - Pj->row0;
+
+    xIe = Xe - Pi->col0;
+    yIe = Ye - Pi->row0;
+
+    // note that this is addressing the same image pixels,
+    // though only if both are source not model images
+    flux = 0;
+    for (yi = yIs, yj = yJs; yi < yIe; yi++, yj++) {
+        for (xi = xIs, xj = xJs; xi < xIe; xi++, xj++) {
+            if (Ti->data.U8[yi][xi])
+                continue;
+            if (Tj->data.U8[yj][xj])
+                continue;
+
+            if (unweighted_sum) {
+                flux += (Pi->data.F32[yi][xi] * Pj->data.F32[yj][xj]);
+            } else {
+                wt = Wi->data.F32[yi][xi];
+                if (wt > 0) {
+                    flux += (Pi->data.F32[yi][xi] * Pj->data.F32[yj][xj]) / wt;
+                }
+            }
+        }
+    }
+    return flux;
+}
+
+double pmSourceCrossWeight(const pmSource *Mi,
+                           const pmSource *Mj,
+                           const bool unweighted_sum) // should the cross product be weighted?
+{
+    PS_ASSERT_PTR_NON_NULL(Mi, NAN);
+    PS_ASSERT_PTR_NON_NULL(Mj, NAN);
+
+    int Xs, Xe, Ys, Ye;
+    int xi, xj, yi, yj;
+    int xIs, xJs, yIs, yJs;
+    int xIe, yIe;
+    double flux, wt;
+
+    const psImage *Pi = Mi->pixels;
+    assert (Pi != NULL);
+    const psImage *Pj = Mj->pixels;
+    assert (Pj != NULL);
+
+    const psImage *Wi = Mi->weight;
+    if (!unweighted_sum) {
+        assert (Wi != NULL);
+    }
+
+    const psImage *Ti = Mi->maskObj;
+    assert (Ti != NULL);
+    const psImage *Tj = Mj->maskObj;
+    assert (Tj != NULL);
+
+    Xs = PS_MAX (Pi->col0, Pj->col0);
+    Xe = PS_MIN (Pi->col0 + Pi->numCols, Pj->col0 + Pj->numCols);
+
+    Ys = PS_MAX (Pi->row0, Pj->row0);
+    Ye = PS_MIN (Pi->row0 + Pi->numRows, Pj->row0 + Pj->numRows);
+
+    xIs = Xs - Pi->col0;
+    xJs = Xs - Pj->col0;
+    yIs = Ys - Pi->row0;
+    yJs = Ys - Pj->row0;
+
+    xIe = Xe - Pi->col0;
+    yIe = Ye - Pi->row0;
+
+    // note that this is addressing the same image pixels,
+    // though only if both are source not model images
+    flux = 0;
+    for (yi = yIs, yj = yJs; yi < yIe; yi++, yj++) {
+        for (xi = xIs, xj = xJs; xi < xIe; xi++, xj++) {
+            if (Ti->data.U8[yi][xi])
+                continue;
+            if (Tj->data.U8[yj][xj])
+                continue;
+
+            if (unweighted_sum) {
+                flux++;
+            } else {
+                wt = Wi->data.F32[yi][xi];
+                if (wt > 0) {
+                    flux += 1.0 / wt;
+                }
+            }
+        }
+    }
+    return flux;
+}
+
+double pmSourceWeight(const pmSource *Mi,
+                      int term,
+                      const bool unweighted_sum) // should the cross product be weighted?
+{
+    PS_ASSERT_PTR_NON_NULL(Mi, NAN);
+    double flux = 0, wt = 0, factor = 0;
+
+    const psImage *Pi = Mi->pixels;
+    assert (Pi != NULL);
+    const psImage *Wi = Mi->weight;
+    if (!unweighted_sum) {
+        assert (Wi != NULL);
+    }
+    const psImage *Ti = Mi->maskObj;
+    assert (Ti != NULL);
+
+    // note that this is addressing the same image pixels,
+    // though only if both are source not model images
+    for (int yi = 0; yi < Pi->numRows; yi++) {
+        for (int xi = 0; xi < Pi->numCols; xi++) {
+            if (Ti->data.U8[yi][xi])
+                continue;
+            if (!unweighted_sum) {
+                wt = Wi->data.F32[yi][xi];
+                if (wt == 0)
+                    continue;
+            }
+
+            switch (term) {
+            case 0:
+                factor = 1;
+                break;
+            case 1:
+                factor = xi + Pi->col0;
+                break;
+            case 2:
+                factor = yi + Pi->row0;
+                break;
+            default:
+                psAbort("invalid term for pmSourceWeight");
+            }
+
+            if (unweighted_sum) {
+                flux += (factor * Pi->data.F32[yi][xi]);
+            } else {
+                flux += (factor * Pi->data.F32[yi][xi]) / wt;
+            }
+            // fprintf (stderr, "Pi: %f, flux: %f\n", Pi->data.F32[yi][xi], flux);
+        }
+    }
+    return flux;
+}
+# endif
+
+bool pmSourceChisq (pmModel *model, psImage *image, psImage *mask, psImage *weight,
+                    psMaskType maskVal)
+{
+    PS_ASSERT_PTR_NON_NULL(model, false);
+    PS_ASSERT_PTR_NON_NULL(image, false);
+    PS_ASSERT_PTR_NON_NULL(mask, false);
+    PS_ASSERT_PTR_NON_NULL(weight, false);
+
+    double dC = 0.0;
+    int Npix = 0;
+    for (int j = 0; j < image->numRows; j++) {
+        for (int i = 0; i < image->numCols; i++) {
+            if (mask->data.U8[j][i] & maskVal)
+                continue;
+            if (weight->data.F32[j][i] <= 0)
+                continue;
+            dC += PS_SQR (image->data.F32[j][i]) / weight->data.F32[j][i];
+            Npix ++;
+        }
+    }
+    model->nDOF = Npix - 1;
+    model->chisq = dC;
+
+    return (true);
+}
+
+
+double pmSourceModelWeight(const pmSource *Mi,
+                      int term,
+                      const bool unweighted_sum) // should the cross product be weighted?
+{
+    PS_ASSERT_PTR_NON_NULL(Mi, NAN);
+    double flux = 0, wt = 0, factor = 0;
+
+    const psImage *Pi = Mi->modelFlux;
+    assert (Pi != NULL);
+    const psImage *Wi = Mi->weight;
+    if (!unweighted_sum) {
+        assert (Wi != NULL);
+    }
+    const psImage *Ti = Mi->maskObj;
+    assert (Ti != NULL);
+
+    for (int yi = 0; yi < Pi->numRows; yi++) {
+        for (int xi = 0; xi < Pi->numCols; xi++) {
+            if (Ti->data.U8[yi][xi])
+                continue;
+            if (!unweighted_sum) {
+                wt = Wi->data.F32[yi][xi];
+                if (wt == 0)
+                    continue;
+            }
+
+            switch (term) {
+            case 0:
+                factor = 1;
+                break;
+            case 1:
+                factor = xi + Pi->col0;
+                break;
+            case 2:
+                factor = yi + Pi->row0;
+                break;
+            default:
+                psAbort("invalid term for pmSourceWeight");
+            }
+
+            if (unweighted_sum) {
+                flux += (factor * Pi->data.F32[yi][xi]);
+            } else {
+                flux += (factor * Pi->data.F32[yi][xi]) / wt;
+            }
+        }
+    }
+    return flux;
+}
+
+double pmSourceModelDotModel (const pmSource *Mi,
+                              const pmSource *Mj,
+                              const bool unweighted_sum) // should the cross product be weighted?
+{
+    PS_ASSERT_PTR_NON_NULL(Mi, NAN);
+    PS_ASSERT_PTR_NON_NULL(Mj, NAN);
+    int Xs, Xe, Ys, Ye;
+    int xi, xj, yi, yj;
+    int xIs, xJs, yIs, yJs;
+    int xIe, yIe;
+    double flux, wt;
+
+    const psImage *Pi = Mi->modelFlux;
+    assert (Pi != NULL);
+    const psImage *Pj = Mj->modelFlux;
+    assert (Pj != NULL);
+
+    const psImage *Wi = Mi->weight;
+    if (!unweighted_sum) {
+        assert (Wi != NULL);
+    }
+
+    const psImage *Ti = Mi->maskObj;
+    assert (Ti != NULL);
+    const psImage *Tj = Mj->maskObj;
+    assert (Tj != NULL);
+
+    Xs = PS_MAX (Pi->col0, Pj->col0);
+    Xe = PS_MIN (Pi->col0 + Pi->numCols, Pj->col0 + Pj->numCols);
+
+    Ys = PS_MAX (Pi->row0, Pj->row0);
+    Ye = PS_MIN (Pi->row0 + Pi->numRows, Pj->row0 + Pj->numRows);
+
+    xIs = Xs - Pi->col0;
+    xJs = Xs - Pj->col0;
+    yIs = Ys - Pi->row0;
+    yJs = Ys - Pj->row0;
+
+    xIe = Xe - Pi->col0;
+    yIe = Ye - Pi->row0;
+
+    // note that weight is addressing the same image pixels
+    flux = 0;
+    for (yi = yIs, yj = yJs; yi < yIe; yi++, yj++) {
+        for (xi = xIs, xj = xJs; xi < xIe; xi++, xj++) {
+            if (Ti->data.U8[yi][xi])
+                continue;
+            if (Tj->data.U8[yj][xj])
+                continue;
+
+            // XXX skip the nonsense weight pixels?
+            if (unweighted_sum) {
+                flux += (Pi->data.F32[yi][xi] * Pj->data.F32[yj][xj]);
+            } else {
+                wt = Wi->data.F32[yi][xi];
+                if (wt > 0) {
+                    flux += (Pi->data.F32[yi][xi] * Pj->data.F32[yj][xj]) / wt;
+                }
+            }
+        }
+    }
+    return flux;
+}
+
+double pmSourceDataDotModel (const pmSource *Mi,
+                             const pmSource *Mj,
+                             const bool unweighted_sum) // should the cross product be weighted?
+{
+    PS_ASSERT_PTR_NON_NULL(Mi, NAN);
+    PS_ASSERT_PTR_NON_NULL(Mj, NAN);
+    int Xs, Xe, Ys, Ye;
+    int xi, xj, yi, yj;
+    int xIs, xJs, yIs, yJs;
+    int xIe, yIe;
+    double flux, wt;
+
+    const psImage *Pi = Mi->pixels;
+    assert (Pi != NULL);
+    const psImage *Pj = Mj->modelFlux;
+    assert (Pj != NULL);
+
+    const psImage *Wi = Mi->weight;
+    if (!unweighted_sum) {
+        assert (Wi != NULL);
+    }
+
+    const psImage *Ti = Mi->maskObj;
+    assert (Ti != NULL);
+    const psImage *Tj = Mj->maskObj;
+    assert (Tj != NULL);
+
+    Xs = PS_MAX (Pi->col0, Pj->col0);
+    Xe = PS_MIN (Pi->col0 + Pi->numCols, Pj->col0 + Pj->numCols);
+
+    Ys = PS_MAX (Pi->row0, Pj->row0);
+    Ye = PS_MIN (Pi->row0 + Pi->numRows, Pj->row0 + Pj->numRows);
+
+    xIs = Xs - Pi->col0;
+    xJs = Xs - Pj->col0;
+    yIs = Ys - Pi->row0;
+    yJs = Ys - Pj->row0;
+
+    xIe = Xe - Pi->col0;
+    yIe = Ye - Pi->row0;
+
+    // note that weight is addressing the same image pixels,
+    flux = 0;
+    for (yi = yIs, yj = yJs; yi < yIe; yi++, yj++) {
+        for (xi = xIs, xj = xJs; xi < xIe; xi++, xj++) {
+            if (Ti->data.U8[yi][xi])
+                continue;
+            if (Tj->data.U8[yj][xj])
+                continue;
+
+            // XXX skip the nonsense weight pixels?
+            if (unweighted_sum) {
+                flux += (Pi->data.F32[yi][xi] * Pj->data.F32[yj][xj]);
+            } else {
+                wt = Wi->data.F32[yi][xi];
+                if (wt > 0) {
+                    flux += (Pi->data.F32[yi][xi] * Pj->data.F32[yj][xj]) / wt;
+                }
+            }
+        }
+    }
+    return flux;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePhotometry.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePhotometry.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePhotometry.h	(revision 22158)
@@ -0,0 +1,67 @@
+/* @file  pmSourcePhotometry.h
+ * @brief functions to measure source photometry
+ *
+ * @author EAM, IfA; GLG, MHPCC
+ *
+ * @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-15 20:25:00 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+# ifndef PM_SOURCE_PHOTOMETRY_H
+# define PM_SOURCE_PHOTOMETRY_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+/**
+ *
+ * The function returns both the magnitude of the fit, defined as -2.5log(flux),
+ * where the flux is integrated under the model, theoretically from a radius of 0
+ * to infinity. In practice, we integrate the model beyond 50sigma.  The aperture magnitude is
+ * defined as -2.5log(flux) , where the flux is summed for all pixels which are
+ * not excluded by the aperture mask. The model flux is calculated by calling the
+ * model-specific function provided by pmModelFlux_GetFunction.
+ *
+ * XXX: must code this.
+ *
+ */
+
+typedef enum {
+    PM_SOURCE_PHOT_NONE   = 0x0000,
+    PM_SOURCE_PHOT_GROWTH = 0x0001,
+    PM_SOURCE_PHOT_APCORR = 0x0002,
+    PM_SOURCE_PHOT_WEIGHT = 0x0004,
+    PM_SOURCE_PHOT_INTERP = 0x0008,
+} pmSourcePhotometryMode;
+
+bool pmSourcePhotometryModel(
+    float *fitMag,                      ///< integrated fit magnitude
+    pmModel *model                      ///< model used for photometry
+);
+
+bool pmSourcePhotometryAper(
+    float   *apMag,                     ///< aperture flux magnitude
+    pmModel *model,                     ///< model used for photometry
+    psImage *image,                     ///< image pixels to be used
+    psImage *mask,                      ///< mask of pixels to ignore
+    psMaskType maskVal                  ///< Value to mask
+);
+
+bool pmSourceMagnitudesInit (psMetadata *config);
+bool pmSourceMagnitudes (pmSource *source, pmPSF *psf, pmSourcePhotometryMode mode, psMaskType maskVal);
+bool pmSourcePixelWeight (float *pixWeight, pmModel *model, psImage *image, psImage *mask, psMaskType maskVal);
+bool pmSourceChisq (pmModel *model, psImage *image, psImage *mask, psImage *weight, psMaskType maskVal);
+
+
+double pmSourceDataDotModel (const pmSource *Mi, const pmSource *Mj, const bool unweighted_sum);
+double pmSourceModelDotModel (const pmSource *Mi, const pmSource *Mj, const bool unweighted_sum);
+double pmSourceModelWeight(const pmSource *Mi, int term, const bool unweighted_sum);
+
+// retire these:
+// double pmSourceCrossProduct(const pmSource *Mi, const pmSource *Mj, const bool unweighted_sum);
+// double pmSourceCrossWeight(const pmSource *Mi, const pmSource *Mj, const bool unweighted_sum);
+// double pmSourceWeight(const pmSource *Mi, int term, const bool unweighted_sum);
+
+/// @}
+# endif /* PM_SOURCE_PHOTOMETRY_H */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePlotApResid.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePlotApResid.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePlotApResid.c	(revision 22158)
@@ -0,0 +1,163 @@
+/** @file  pmSourcePlot.c
+ *
+ *  Plot the Aperture Mag - Fitted Mag residuals
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
+ *  Copyright 2006 IfA, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmResiduals.h"
+#include "pmGrowthCurve.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmSourcePlots.h"
+#include "pmKapaPlots.h"
+
+// this variable is defined in psmodules.h if ohana-config is found
+# if (HAVE_KAPA)
+    # include <kapa.h>
+
+// plot the sx, sy, sxy as vector field,
+// plot the PSF measured sx, sy, sxy as vector field
+// pull the sources from the config / file?
+bool pmSourcePlotApResid (const pmFPAview *view, pmFPAfile *file, const pmConfig *config,
+                          pmSourcePlotLayout *layout)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(layout, false);
+
+    Graphdata graphdata;
+    KapaSection section;
+
+    psLogMsg ("psphot", 3, "creating ap mag - psf mag plot");
+
+    // find the currently selected readout
+    pmReadout  *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT");
+
+    psArray *sources = psMetadataLookupPtr (NULL, readout->analysis, "PSPHOT.SOURCES");
+    if (sources == NULL)
+        return false;
+
+    int kapa = pmKapaOpen (true);
+    if (kapa == -1) {
+        psError(PS_ERR_UNKNOWN, true, "failure to open kapa");
+        return false;
+    }
+
+    int DX = 1000;
+    float dx = DX / layout->nX;
+    float dy = dx * layout->aspectRatio;
+    int DY = dy * layout->nY;
+
+    // XXX make the aspect-ratio match the image
+    if (layout->i == 0) {
+        KapaResize (kapa, DX, DY);
+    }
+
+    KapaClearPlots (kapa);
+    KapaInitGraph (&graphdata);
+    section.dx = dx / DX;
+    section.dy = dy / DY;
+    section.x = layout->iX * section.dx;
+    section.y = layout->iY * section.dy;
+    section.name = NULL;
+    psStringAppend (&section.name, "a%d", layout->i);
+    KapaSetSection (kapa, &section);
+    psFree (section.name);
+
+    psVector *x = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
+    psVector *y = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
+
+    graphdata.xmin = +32.0;
+    graphdata.xmax = -32.0;
+    graphdata.ymin = +32.0;
+    graphdata.ymax = -32.0;
+
+    // construct the plot vectors
+    int n = 0;
+    for (int i = 0; i < sources->n; i++) {
+        pmSource *source = sources->data[i];
+	if (!source) continue;
+        if (source->type != PM_SOURCE_TYPE_STAR) continue;
+	if (!isfinite (source->apMag)) continue;
+	if (!isfinite (source->psfMag)) continue;
+
+        x->data.F32[n] = source->psfMag;
+        y->data.F32[n] = source->apMag - source->psfMag;
+        graphdata.xmin = PS_MIN(graphdata.xmin, x->data.F32[n]);
+        graphdata.xmax = PS_MAX(graphdata.xmax, x->data.F32[n]);
+        graphdata.ymin = PS_MIN(graphdata.ymin, y->data.F32[n]);
+        graphdata.ymax = PS_MAX(graphdata.ymax, y->data.F32[n]);
+
+        n++;
+    }
+    x->n = y->n = n;
+
+    float range;
+    range = graphdata.xmax - graphdata.xmin;
+    graphdata.xmax += 0.05*range;
+    graphdata.xmin -= 0.05*range;
+    range = graphdata.ymax - graphdata.ymin;
+    graphdata.ymax += 0.05*range;
+    graphdata.ymin -= 0.05*range;
+
+    // XXX set the plot range to match the image
+    KapaSetLimits (kapa, &graphdata);
+
+    KapaSetFont (kapa, "helvetica", 14);
+    KapaBox (kapa, &graphdata);
+    KapaSendLabel (kapa, "PSF Mag", KAPA_LABEL_XM);
+    KapaSendLabel (kapa, "Ap Mag - PSF Mag", KAPA_LABEL_YM);
+
+    graphdata.color = KapaColorByName ("black");
+    graphdata.ptype = 2;
+    graphdata.size = 0.5;
+    graphdata.style = 2;
+    KapaPrepPlot (kapa, n, &graphdata);
+    KapaPlotVector (kapa, n, x->data.F32, "x");
+    KapaPlotVector (kapa, n, y->data.F32, "y");
+
+    if (layout->i == layout->nTotal - 1) {
+        psLogMsg ("psphot", 3, "saving plot to %s", file->filename);
+        KapaPNG (kapa, file->filename);
+	KapaClearPlots (kapa);
+    }
+
+    psFree (x);
+    psFree (y);
+    return true;
+}
+
+# else
+
+bool pmSourcePlotApResid (const pmFPAview *view, pmFPAfile *file, const pmConfig *config, pmSourcePlotLayout *layout)
+{
+    psLogMsg ("psphot", 3, "skipping ap-mag resid plot");
+    return true;
+}
+
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePlotMoments.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePlotMoments.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePlotMoments.c	(revision 22158)
@@ -0,0 +1,176 @@
+/** @file  pmSourcePlot.c
+ *
+ * This file contains functions to write source plots
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-15 20:25:00 $
+ *
+ *  Copyright 2006 IfA, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmGrowthCurve.h"
+#include "pmResiduals.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmSourcePlots.h"
+#include "pmKapaPlots.h"
+
+// this variable is defined in psmodules.h if ohana-config is found
+# if (HAVE_KAPA)
+# include <kapa.h>
+
+// plot the sx, sy moments plane (faint and bright sources)
+bool pmSourcePlotMoments (const pmFPAview *view, pmFPAfile *file, const pmConfig *config,
+                          pmSourcePlotLayout *layout)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(layout, false);
+
+    Graphdata graphdata;
+    KapaSection section;
+
+    psLogMsg ("psphot", 3, "creating moments plot");
+
+    // find the currently selected readout
+    pmReadout  *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT");
+
+    psArray *sources = psMetadataLookupPtr (NULL, readout->analysis, "PSPHOT.SOURCES");
+    if (sources == NULL)
+        return false;
+
+    int kapa = pmKapaOpen (false);
+    if (kapa == -1) {
+        psError(PS_ERR_UNKNOWN, true, "failure to open kapa");
+        return false;
+    }
+
+    // moments plot subplots are square
+    int DX = 1000;
+    int dx = DX / layout->nX;
+    int dy = dx;
+    int DY = dy * layout->nY;
+
+    // XXX make the aspect-ratio match the image
+    if (layout->i == 0) {
+        KapaResize (kapa, DX, DY);
+    }
+
+    KapaClearPlots (kapa);
+    KapaInitGraph (&graphdata);
+    section.dx = dx / (float) DX;
+    section.dy = dy / (float) DY;
+    section.x = layout->iX * section.dx;
+    section.y = layout->iY * section.dy;
+    section.name = NULL;
+    psStringAppend (&section.name, "a%d", layout->i);
+    KapaSetSection (kapa, &section);
+    psFree (section.name);
+
+    // examine sources to set data range
+    graphdata.xmin = -0.05;
+    graphdata.ymin = -0.05;
+    graphdata.xmax = +4.05;
+    graphdata.ymax = +4.05;
+    KapaSetLimits (kapa, &graphdata);
+
+    KapaSetFont (kapa, "helvetica", 14);
+    KapaBox (kapa, &graphdata);
+    KapaSendLabel (kapa, "&ss&h_x| (pixels)", KAPA_LABEL_XM);
+    KapaSendLabel (kapa, "&ss&h_y| (pixels)", KAPA_LABEL_YM);
+
+    psVector *xBright = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
+    psVector *yBright = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
+    psVector *xFaint  = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
+    psVector *yFaint  = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
+
+    // construct the vectors
+    int nB = 0;
+    int nF = 0;
+    for (int i = 0; i < sources->n; i++) {
+        pmSource *source = sources->data[i];
+        if (source->moments == NULL)
+            continue;
+
+        xFaint->data.F32[nF] = source->moments->Sx;
+        yFaint->data.F32[nF] = source->moments->Sy;
+        nF++;
+
+        // XXX make this a user-defined cutoff
+        if (source->moments->SN < 50)
+            continue;
+
+        xBright->data.F32[nB] = source->moments->Sx;
+        yBright->data.F32[nB] = source->moments->Sy;
+        nB++;
+    }
+    xFaint->n = nF;
+    yFaint->n = nF;
+
+    xBright->n = nB;
+    yBright->n = nB;
+
+    graphdata.color = KapaColorByName ("black");
+    graphdata.ptype = 0;
+    graphdata.size = 0.3;
+    graphdata.style = 2;
+    KapaPrepPlot (kapa, nF, &graphdata);
+    KapaPlotVector (kapa, nF, xFaint->data.F32, "x");
+    KapaPlotVector (kapa, nF, yFaint->data.F32, "y");
+
+    graphdata.color = KapaColorByName ("red");
+    graphdata.ptype = 2;
+    graphdata.size = 0.5;
+    graphdata.style = 2;
+    KapaPrepPlot (kapa, nB, &graphdata);
+    KapaPlotVector (kapa, nB, xBright->data.F32, "x");
+    KapaPlotVector (kapa, nB, yBright->data.F32, "y");
+
+    if (layout->i == layout->nTotal - 1) {
+        psLogMsg ("psphot", 3, "saving plot to %s", file->filename);
+        KapaPNG (kapa, file->filename);
+	KapaClearPlots (kapa);
+    }
+
+    psFree (xBright);
+    psFree (yBright);
+    psFree (xFaint);
+    psFree (yFaint);
+
+    return true;
+}
+
+
+# else
+
+    bool pmSourcePlotMoments (const pmFPAview *view, pmFPAfile *file, const pmConfig *config, pmSourcePlotLayout *layout)
+{
+    psLogMsg ("psphot", 3, "skipping moments plot");
+    return true;
+}
+
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePlotPSFModel.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePlotPSFModel.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePlotPSFModel.c	(revision 22158)
@@ -0,0 +1,237 @@
+/** @file  pmSourcePlot.c
+ *
+ * This file contains functions to write source plots
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
+ *
+ *  Copyright 2006 IfA, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmGrowthCurve.h"
+#include "pmResiduals.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmSourcePlots.h"
+#include "pmKapaPlots.h"
+
+// this variable is defined in psmodules.h if ohana-config is found
+# if (HAVE_KAPA)
+# include <kapa.h>
+
+// plot the sx, sy, sxy as vector field,
+// plot the PSF measured sx, sy, sxy as vector field
+// pull the sources from the config / file?
+bool pmSourcePlotPSFModel (const pmFPAview *view, pmFPAfile *file, const pmConfig *config,
+                           pmSourcePlotLayout *layout)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(layout, false);
+
+    Graphdata graphdata;
+    KapaSection section;
+
+    psLogMsg ("psphot", 3, "creating psf model plot");
+
+    // find the currently selected readout
+    pmReadout  *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT");
+
+    psArray *sources = psMetadataLookupPtr (NULL, readout->analysis, "PSPHOT.SOURCES");
+    if (sources == NULL)
+        return false;
+
+    int kapa = pmKapaOpen (false);
+    if (kapa == -1) {
+        psError(PS_ERR_UNKNOWN, true, "failure to open kapa");
+        return false;
+    }
+
+    int DX = 1000;
+    float dx = DX / layout->nX;
+    float dy = dx * layout->aspectRatio;
+    int DY = dy * layout->nY;
+
+    // XXX make the aspect-ratio match the image
+    if (layout->i == 0) {
+        KapaResize (kapa, DX, DY);
+    }
+    
+    KapaClearPlots (kapa);
+    KapaInitGraph (&graphdata);
+    section.dx = dx / DX;
+    section.dy = dy / DY;
+    section.x = layout->iX * section.dx;
+    section.y = layout->iY * section.dy;
+    section.name = NULL;
+    psStringAppend (&section.name, "a%d", layout->i);
+    KapaSetSection (kapa, &section);
+    psFree (section.name);
+
+    psVector *xMNT = psVectorAllocEmpty (2*sources->n, PS_TYPE_F32);
+    psVector *yMNT = psVectorAllocEmpty (2*sources->n, PS_TYPE_F32);
+    psVector *xPSF = psVectorAllocEmpty (2*sources->n, PS_TYPE_F32);
+    psVector *yPSF = psVectorAllocEmpty (2*sources->n, PS_TYPE_F32);
+    psVector *xMIN = psVectorAllocEmpty (2*sources->n, PS_TYPE_F32);
+    psVector *yMIN = psVectorAllocEmpty (2*sources->n, PS_TYPE_F32);
+
+    // construct the plot vectors
+    int nMNT = 0;
+    int nPSF = 0;
+    int nMIN = 0;
+    dx = 0;
+    dy = 0;
+    float scale = 10;
+    for (int i = 0; i < sources->n; i++) {
+        pmSource *source = sources->data[i];
+        if (source->moments == NULL)
+            continue;
+        if (source->moments->SN < 25)
+            continue;
+        if (source->type != PM_SOURCE_TYPE_STAR)
+            continue;
+
+        pmModel *model = source->modelPSF;
+        if (model == NULL)
+            continue;
+
+        psF32 *PAR = model->params->data.F32;
+
+        psEllipseMoments moments;
+        moments.x2 = source->moments->Sx;
+        moments.y2 = source->moments->Sy;
+        moments.xy = source->moments->Sxy;
+
+        // force the axis ratio to be < 20.0
+        psEllipseAxes axes_mnt = psEllipseMomentsToAxes (moments, 20.0);
+        psEllipseAxes axes_psf = pmPSF_ModelToAxes (PAR, 20.0);
+
+        // moments major axis
+        dx = scale*axes_mnt.major*cos(axes_mnt.theta);
+        dy = scale*axes_mnt.major*sin(axes_mnt.theta);
+        xMNT->data.F32[nMNT] = PAR[PM_PAR_XPOS] - dx;
+        yMNT->data.F32[nMNT] = PAR[PM_PAR_YPOS] - dy;
+        nMNT++;
+        xMNT->data.F32[nMNT] = PAR[PM_PAR_XPOS] + dx;
+        yMNT->data.F32[nMNT] = PAR[PM_PAR_YPOS] + dy;
+        nMNT++;
+
+        // psf major axis
+        dx = scale*axes_psf.major*cos(axes_psf.theta);
+        dy = scale*axes_psf.major*sin(axes_psf.theta);
+        xPSF->data.F32[nPSF] = PAR[PM_PAR_XPOS] - dx;
+        yPSF->data.F32[nPSF] = PAR[PM_PAR_YPOS] - dy;
+        nPSF++;
+        xPSF->data.F32[nPSF] = PAR[PM_PAR_XPOS] + dx;
+        yPSF->data.F32[nPSF] = PAR[PM_PAR_YPOS] + dy;
+        nPSF++;
+
+        // minor axis (to show size)
+        dy = +scale*axes_psf.minor*cos(axes_psf.theta);
+        dx = -scale*axes_psf.minor*sin(axes_psf.theta);
+        xMIN->data.F32[nMIN] = PAR[PM_PAR_XPOS] - dx;
+        yMIN->data.F32[nMIN] = PAR[PM_PAR_YPOS] - dy;
+        nMIN++;
+        xMIN->data.F32[nMIN] = PAR[PM_PAR_XPOS] + dx;
+        yMIN->data.F32[nMIN] = PAR[PM_PAR_YPOS] + dy;
+        nMIN++;
+
+        graphdata.xmin = PS_MIN(graphdata.xmin, PAR[PM_PAR_XPOS]);
+        graphdata.xmax = PS_MAX(graphdata.xmax, PAR[PM_PAR_XPOS]);
+        graphdata.ymin = PS_MIN(graphdata.ymin, PAR[PM_PAR_YPOS]);
+        graphdata.ymax = PS_MAX(graphdata.ymax, PAR[PM_PAR_YPOS]);
+    }
+    xMNT->n = yMNT->n = nMNT;
+    xPSF->n = yPSF->n = nPSF;
+    xMIN->n = yMIN->n = nMIN;
+
+    float range;
+    range = graphdata.xmax - graphdata.xmin;
+    graphdata.xmax += 0.05*range;
+    graphdata.xmin -= 0.05*range;
+    range = graphdata.ymax - graphdata.ymin;
+    graphdata.ymax += 0.05*range;
+    graphdata.ymin -= 0.05*range;
+
+    // XXX set the plot range to match the image
+    KapaSetLimits (kapa, &graphdata);
+
+    KapaSetFont (kapa, "helvetica", 14);
+    KapaBox (kapa, &graphdata);
+    KapaSendLabel (kapa, "x (pixels)", KAPA_LABEL_XM);
+    KapaSendLabel (kapa, "y (pixels)", KAPA_LABEL_YM);
+    KapaSendLabel (kapa, "vector is major axis (scaled by 20) : black are moments, blue are psf model, red is psf minor axis", KAPA_LABEL_XP);
+
+    graphdata.color = KapaColorByName ("black");
+    graphdata.ptype = 100;
+    graphdata.size = 0.3;
+    graphdata.style = 2;
+    KapaPrepPlot (kapa, nMNT, &graphdata);
+    KapaPlotVector (kapa, nMNT, xMNT->data.F32, "x");
+    KapaPlotVector (kapa, nMNT, yMNT->data.F32, "y");
+
+    graphdata.color = KapaColorByName ("blue");
+    graphdata.ptype = 100;
+    graphdata.size = 0.5;
+    graphdata.style = 2;
+    KapaPrepPlot (kapa, nPSF, &graphdata);
+    KapaPlotVector (kapa, nPSF, xPSF->data.F32, "x");
+    KapaPlotVector (kapa, nPSF, yPSF->data.F32, "y");
+
+    graphdata.color = KapaColorByName ("red");
+    graphdata.ptype = 100;
+    graphdata.size = 0.5;
+    graphdata.style = 2;
+    KapaPrepPlot (kapa, nMIN, &graphdata);
+    KapaPlotVector (kapa, nMIN, xMIN->data.F32, "x");
+    KapaPlotVector (kapa, nMIN, yMIN->data.F32, "y");
+
+    if (layout->i == layout->nTotal - 1) {
+        psLogMsg ("psphot", 3, "saving plot to %s", file->filename);
+        KapaPNG (kapa, file->filename);
+	KapaClearPlots (kapa);
+    }
+
+    psFree (xMNT);
+    psFree (yMNT);
+    psFree (xPSF);
+    psFree (yPSF);
+    psFree (xMIN);
+    psFree (yMIN);
+
+    return true;
+}
+
+# else
+
+    bool pmSourcePlotPSFModel (const pmFPAview *view, pmFPAfile *file, const pmConfig *config, pmSourcePlotLayout *layout)
+{
+    psLogMsg ("psphot", 3, "skipping psf model plot");
+    return true;
+}
+
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePlots.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePlots.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePlots.c	(revision 22158)
@@ -0,0 +1,178 @@
+/** @file  pmSourcePlot.c
+ *
+ * This file contains functions to write source plots
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
+ *
+ *  Copyright 2006 IfA, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+
+#include "pmConfig.h"
+#include "pmDetrendDB.h"
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+#include "pmSourcePlots.h"
+
+// this function is called for the specific plotting program at the fileLevel
+// fileLevel must be >= chip
+bool pmFPAviewWriteSourcePlot(const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    if ((view->readout != -1) || (view->cell != -1)) {
+        psError(PS_ERR_UNKNOWN, true, "source plots must have fileLevel >= chip");
+        return false;
+    }
+
+    pmFPA *fpa = file->fpa;
+
+    if (view->chip == -1) {
+        pmFPAWriteSourcePlot (fpa, view, file, config, NULL);
+        return true;
+    }
+
+    pmChipWriteSourcePlot (fpa, view, file, config, NULL);
+    return true;
+}
+
+// read in all chip-level SourcePlot files for this FPA
+bool pmFPAWriteSourcePlot (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config, pmSourcePlotLayout *layout)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    // if the layout is not defined, this level is the top level being plotted
+    // determine the plot layout
+    if (!layout) {
+        layout = pmSourcePlotLayoutAlloc ();
+        // XXX temporary hardwired values for essence?
+        layout->nX = 4;
+        layout->nY = 2;
+        layout->aspectRatio = 1.0;
+        // count the number of chips and their layout (xrange, yrange, axis ratio)
+        for (int i = 0; i < fpa->chips->n; i++) {
+            pmChip *chip = fpa->chips->data[i];
+            if (chip->data_exists) {
+                layout->nTotal ++;
+            }
+        }
+    }
+
+    pmFPAview *chipView = pmFPAviewAlloc(0);
+
+    while (pmFPAviewNextChip (chipView, fpa, 1) != NULL) {
+        pmChipWriteSourcePlot (fpa, chipView, file, config, layout);
+        layout->i ++;
+        layout->iX ++;
+        if (layout->iX == layout->nX) {
+            layout->iY++;
+            layout->iX = 0;
+        }
+    }
+    psFree (chipView);
+    psFree (layout);
+    return true;
+}
+
+// read in all cell-level SourcePlot files for this chip
+bool pmChipWriteSourcePlot (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config, pmSourcePlotLayout *layout)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    // if the layout is not defined, this level is the top level being plotted
+    // determine the plot layout (always single chip)
+    if (!layout) {
+        layout = pmSourcePlotLayoutAlloc ();
+        layout->nTotal = 1;
+        layout->nX = 1;
+        layout->nY = 1;
+        layout->aspectRatio = 1.0;
+    } else {
+        psMemIncrRefCounter (layout);
+    }
+
+    pmFPAview *newView = pmFPAviewAlloc(0);
+    newView->chip = view->chip;
+
+    while (pmFPAviewNextCell (newView, fpa, 1) != NULL) {
+        while (pmFPAviewNextReadout (newView, fpa, 1) != NULL) {
+
+            if (!strcmp (file->name, "SOURCE.PLOT.PSFMODEL")) {
+                pmSourcePlotPSFModel (newView, file, config, layout);
+            }
+            if (!strcmp (file->name, "SOURCE.PLOT.MOMENTS")) {
+                pmSourcePlotMoments (newView, file, config, layout);
+            }
+            if (!strcmp (file->name, "SOURCE.PLOT.APRESID")) {
+                pmSourcePlotApResid (newView, file, config, layout);
+            }
+        }
+    }
+    psFree (newView);
+    psFree (layout);
+    return true;
+}
+
+static void pmSourcePlotLayoutFree(pmSourcePlotLayout *layout)
+{
+    return;
+}
+
+pmSourcePlotLayout *pmSourcePlotLayoutAlloc()
+{
+    pmSourcePlotLayout *layout = (pmSourcePlotLayout *)psAlloc(sizeof(pmSourcePlotLayout));
+    psMemSetDeallocator(layout, (psFreeFunc)pmSourcePlotLayoutFree );
+
+    layout->nX = layout->nY = layout->nTotal = 0;
+    layout->iX = layout->iY = layout->i  =  0;
+    layout->aspectRatio = 1.0;
+    return (layout);
+}
+
+bool psMemCheckSourcePlotLayout(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmSourcePlotLayoutFree);
+}
+
+
+/* we have three types of plots to produce (maybe more?)
+ * for each plot, we need to supply the following information:
+ *     - what are overall dimensions?
+ *     - what is the relative position of this element?
+ *     - what are the dimensions of this element?
+ *     - create a new page for this element?
+
+ * the answers to these questions come from slightly different locations
+ * for the different types of plots:
+
+ *  1) focal-plane layout based plots:
+ *     - dimensions depend on fileLevel
+
+ *  2) multi-row plots:
+ *     - dimensions depend on total number of rows
+
+ *  2) multi-page plots:
+ *     - dimensions depend on total number of rows
+ */
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePlots.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePlots.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourcePlots.h	(revision 22158)
@@ -0,0 +1,42 @@
+/* @file  pmSourcePlots.h
+ * @brief functions to create plots illustrating source properties
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-11-10 01:09:20 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_SOURCE_PLOTS_H
+#define PM_SOURCE_PLOTS_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+typedef struct
+{
+    int nX;
+    int nY;
+    int nTotal;
+    int iX;
+    int iY;
+    int i;
+    float aspectRatio;
+}
+pmSourcePlotLayout;
+
+// typedef bool (*pmSourcePlotFunction)(pmConfig *config, pmFPAview *view, pmSourcePlotLayout *layout);
+
+pmSourcePlotLayout *pmSourcePlotLayoutAlloc();
+bool psMemCheckSourcePlotLayout(psPtr ptr);
+
+bool pmFPAviewWriteSourcePlot(const pmFPAview *view, pmFPAfile *file, const pmConfig *config);
+bool pmFPAWriteSourcePlot (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config, pmSourcePlotLayout *layout);
+bool pmChipWriteSourcePlot (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config, pmSourcePlotLayout *layout);
+bool pmSourcePlotPSFModel (const pmFPAview *view, pmFPAfile *file, const pmConfig *config, pmSourcePlotLayout *layout);
+bool pmSourcePlotMoments (const pmFPAview *view, pmFPAfile *file, const pmConfig *config, pmSourcePlotLayout *layout);
+bool pmSourcePlotApResid (const pmFPAview *view, pmFPAfile *file, const pmConfig *config, pmSourcePlotLayout *layout);
+
+/// @}
+#endif // PM_SOURCE_PLOTS_H
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceSky.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceSky.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceSky.c	(revision 22158)
@@ -0,0 +1,156 @@
+/** @file  pmSourceSky.c
+ *
+ *  Functions to measure the local sky and sky variance for sources on images
+ *
+ *  @author GLG, MHPCC
+ *  @author EAM, IfA: significant modifications.
+ *
+ *  @version $Revision: 1.17 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-15 20:25:00 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPAMaskWeight.h"
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmResiduals.h"
+#include "pmGrowthCurve.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmSourceSky.h"
+
+/******************************************************************************
+pmSource *pmSourceLocalSky(source, statsOptions, Radius): this
+routine creates a new pmSource.moments element if needed and sets pmSource.pmMoments.sky
+
+The sky value is set from the pixels in the square annulus surrounding the
+peak pixel.
+
+The source.pixels and source.mask must already exist
+
+This function modifies the source mask; it should only be called before the object aperture is defined
+*****************************************************************************/
+
+bool pmSourceLocalSky(
+    pmSource *source,
+    psStatsOptions statsOptions,
+    psF32 Radius,
+    psMaskType maskVal,
+    psMaskType markVal)
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_PTR_NON_NULL(source, false);
+    PS_ASSERT_IMAGE_NON_NULL(source->pixels, false);
+    PS_ASSERT_IMAGE_NON_NULL(source->maskObj, false);
+    PS_ASSERT_PTR_NON_NULL(source->peak, false);
+    PS_ASSERT_INT_POSITIVE(Radius, false);
+
+    psStatsOptions statistic = psStatsSingleOption(statsOptions);
+    if (statistic == 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Multiple or no statistics specified: %x\n", statsOptions);
+        return NULL;
+    }
+
+    psImage *image = source->pixels;
+    psImage *mask  = source->maskObj;
+    pmPeak *peak  = source->peak;
+    psRegion srcRegion;
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
+    srcRegion = psRegionForSquare(peak->x, peak->y, Radius);
+    srcRegion = psRegionForImage(mask, srcRegion);
+
+    psImageMaskRegion(mask, srcRegion, "OR", markVal);
+    psStats *myStats = psStatsAlloc(statsOptions);
+    if (!psImageStats(myStats, image, mask, maskVal)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to get image statistics.\n");
+        psFree(myStats);
+        return false;
+    }
+    psImageMaskRegion(mask, srcRegion, "AND", PS_NOT_U8(markVal));
+    double value = psStatsGetValue(myStats, statistic);
+    psFree(myStats);
+
+    if (isnan(value)) {
+        psTrace("psModules.objects", 3, "---- %s(false) end ----\n", __func__);
+        return(false);
+    }
+    if (source->moments == NULL) {
+        source->moments = pmMomentsAlloc();
+    }
+    source->moments->Sky = value;
+    psTrace("psModules.objects", 3, "---- %s(true) end ----\n", __func__);
+    return (true);
+}
+
+// A complementary function to pmSourceLocalSky: calculate the local median variance
+bool pmSourceLocalSkyVariance(
+    pmSource *source,
+    psStatsOptions statsOptions,
+    psF32 Radius,
+    psMaskType maskVal,
+    psMaskType markVal
+)
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_PTR_NON_NULL(source, false);
+    PS_ASSERT_IMAGE_NON_NULL(source->weight, false);
+    PS_ASSERT_IMAGE_NON_NULL(source->maskObj, false);
+    PS_ASSERT_PTR_NON_NULL(source->peak, false);
+    PS_ASSERT_INT_POSITIVE(Radius, false);
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
+    psStatsOptions statistic = psStatsSingleOption(statsOptions);
+    if (statistic == 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Multiple or no statistics specified: %x\n", statsOptions);
+        return NULL;
+    }
+
+    psImage *image = source->weight;
+    psImage *mask  = source->maskObj;
+    pmPeak *peak  = source->peak;
+    psRegion srcRegion;
+
+    srcRegion = psRegionForSquare(peak->x, peak->y, Radius);
+    srcRegion = psRegionForImage(mask, srcRegion);
+
+    psImageMaskRegion(mask, srcRegion, "OR", markVal);
+    psStats *myStats = psStatsAlloc(statsOptions);
+    if (!psImageStats(myStats, image, mask, maskVal)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to get image statistics.\n");
+        psFree(myStats);
+        return false;
+    }
+    psImageMaskRegion(mask, srcRegion, "AND", PS_NOT_U8(markVal));
+    double value = psStatsGetValue(myStats, statistic);
+    psFree(myStats);
+
+    if (isnan(value)) {
+        psTrace("psModules.objects", 3, "---- %s(false) end ----\n", __func__);
+        return(false);
+    }
+    if (source->moments == NULL) {
+        source->moments = pmMomentsAlloc();
+    }
+    source->moments->dSky = value;
+    psTrace("psModules.objects", 3, "---- %s(true) end ----\n", __func__);
+    return (true);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceSky.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceSky.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceSky.h	(revision 22158)
@@ -0,0 +1,47 @@
+/* @file  pmSourceSky.h
+ * @author EAM, IfA; GLG, MHPCC
+ *
+ * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-06-20 02:22:26 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+# ifndef PM_SOURCE_SKY_H
+# define PM_SOURCE_SKY_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+/** pmSourceLocalSky()
+ *
+ * Measure the local sky in the vicinity of the given source. The Radius
+ * defines the square aperture in which the moments will be measured. This
+ * function assumes the source pixels have been defined, and that the value of
+ * Radius here is smaller than the value of Radius used to define the pixels. The
+ * annular region not contained within the radius defined here is used to measure
+ * the local background in the vicinity of the source. The local background
+ * measurement uses the specified statistic passed in via the statsOptions entry.
+ * This function allocates the pmMoments structure. The resulting sky is used to
+ * set the value of the pmMoments.sky element of the provided pmSource structure.
+ *
+ */
+bool pmSourceLocalSky(
+    pmSource *source,   ///< The input image (float)
+    psStatsOptions statsOptions, ///< The statistic used in calculating the background sky
+    float Radius,   ///< The inner radius of the square annulus to exclude
+    psMaskType maskVal,                 ///< Value to mask
+    psMaskType mark                     ///< Mask value for marking
+);
+
+
+// A complementary function to pmSourceLocalSky: calculate the local sky variance
+bool pmSourceLocalSkyVariance(
+    pmSource *source,   ///< The input image (float)
+    psStatsOptions statsOptions, ///< The statistic used in calculating the background sky
+    float Radius,   ///< The inner radius of the square annulus to exclude
+    psMaskType maskVal,                 ///< Value to mask
+    psMaskType mark                     ///< Mask value for marking
+);
+
+/// @}
+# endif /* PM_SOURCE_PHOTOMETRY_H */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceUtils.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceUtils.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceUtils.c	(revision 22158)
@@ -0,0 +1,117 @@
+/** @file  pmSource.c
+ *
+ *  Functions to define and manipulate sources on images
+ *
+ *  @author GLG, MHPCC
+ *  @author EAM, IfA: significant modifications.
+ *
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-11-10 01:09:20 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <pslib.h>
+#include "pmHDU.h"
+#include "pmFPA.h"
+#include "pmFPAMaskWeight.h"
+#include "pmPeaks.h"
+#include "pmMoments.h"
+#include "pmResiduals.h"
+#include "pmGrowthCurve.h"
+#include "pmTrend2D.h"
+#include "pmPSF.h"
+#include "pmModel.h"
+#include "pmSource.h"
+#include "pmSourceUtils.h"
+
+/******************************************************************************
+    pmSourceModelGuess(source, model): This function allocates a new
+    pmModel structure based on the given modelType specified in the argument list.
+    The corresponding pmModelGuess function is returned, and used to
+    supply the values of the params array in the pmModel structure.
+ 
+    XXX: Many parameters are based on the src->moments structure, which is in
+    image, not subImage coords.  Therefore, the calls to the model evaluation
+    functions will be in image, not subImage coords.  Remember this.
+*****************************************************************************/
+pmModel *pmSourceModelGuess(pmSource *source,
+                            pmModelType modelType)
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    PS_ASSERT_PTR_NON_NULL(source, NULL);
+    PS_ASSERT_PTR_NON_NULL(source->moments, NULL);
+    PS_ASSERT_PTR_NON_NULL(source->peak, NULL);
+
+    pmModel *model = pmModelAlloc(modelType);
+
+    if (!model->modelGuess(model, source)) {
+	psFree (model);
+	return NULL;
+    }
+
+    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    return(model);
+}
+
+pmSource *pmSourceFromModel (pmModel *model, pmReadout *readout, float radius, 
+                             pmSourceType type)
+{
+    PS_ASSERT_PTR_NON_NULL(model, NULL);
+    PS_ASSERT_PTR_NON_NULL(readout, NULL);
+
+    pmSource *source = pmSourceAlloc ();
+
+    // use the model centroid for the peak
+    switch (type) {
+      case PM_SOURCE_TYPE_STAR:
+	source->modelPSF = model;
+	break;
+      case PM_SOURCE_TYPE_EXTENDED:
+	source->modelEXT = model;
+	break;
+      default:
+	psAbort ("invalid source type");
+    }
+    source->type = type;
+
+    pmCell *cell = readout->parent;
+
+    float Io    = model->params->data.F32[PM_PAR_I0];
+    float xChip = model->params->data.F32[PM_PAR_XPOS];
+    float yChip = model->params->data.F32[PM_PAR_YPOS];
+
+    source->peak = pmPeakAlloc (xChip, yChip, Io, PM_PEAK_LONE);
+
+    int x0Cell = psMetadataLookupS32(NULL, cell->concepts, "CELL.X0");
+    int y0Cell = psMetadataLookupS32(NULL, cell->concepts, "CELL.Y0");
+    int xParityCell = psMetadataLookupS32(NULL, cell->concepts, "CELL.XPARITY");
+    int yParityCell = psMetadataLookupS32(NULL, cell->concepts, "CELL.YPARITY");
+
+    // XXX fix the binning : currently not selected from concepts
+    // int xBin = psMetadataLookupS32(NULL, cell->concepts, "CELL.XBIN"); // Binning in x and y
+    // int yBin = psMetadataLookupS32(NULL, cell->concepts, "CELL.YBIN"); // Binning in x and y
+    int xBin = 1;
+    int yBin = 1;
+
+    // Position on the cell 
+    float xCell = PM_CHIP_TO_CELL(xChip, x0Cell, xParityCell, xBin);
+    float yCell = PM_CHIP_TO_CELL(yChip, y0Cell, yParityCell, yBin);
+
+    // Position on the readout
+    // float xReadout = CELL_TO_READOUT(xCell, x0Readout);
+    // float yReadout = CELL_TO_READOUT(yCell, y0Readout);
+    
+    pmSourceDefinePixels (source, readout, xCell, yCell, radius);
+
+    return (source);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceUtils.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceUtils.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSourceUtils.h	(revision 22158)
@@ -0,0 +1,40 @@
+/* @file  pmSourceUtils.h
+ *
+ * Utility functions for working with pmSources
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-08-24 00:11:02 $
+ * Copyright 2007 IfA, University of Hawaii
+ */
+
+# ifndef PM_SOURCE_UTILS_H
+# define PM_SOURCE_UTILS_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+/** pmSourceModelGuess()
+ *
+ * Convert available data to an initial guess for the given model. This
+ * function allocates a pmModel entry for the pmSource structure based on the
+ * provided model selection. The method of defining the model parameter guesses
+ * are specified for each model below. The guess values are placed in the model
+ * parameters. The function returns TRUE on success or FALSE on failure.
+ *
+ */
+pmModel *pmSourceModelGuess(
+    pmSource *source,   ///< The input pmSource
+    pmModelType model   ///< The type of model to be created.
+);
+
+pmSource *pmSourceFromModel (
+  pmModel *model, 
+  pmReadout *readout, 
+  float radius,
+  pmSourceType type
+  );
+
+/// @}
+# endif /* PM_MODEL_CLASS_H */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSpan.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSpan.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSpan.c	(revision 22158)
@@ -0,0 +1,73 @@
+/* @file  pmSpan.c
+ *
+ * @author RHL, Princeton & IfA; EAM, IfA
+ *
+ * @version $Revision: 1.1.2.1 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-20 23:08:03 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <strings.h>
+#include <pslib.h>
+#include "pmSpan.h"
+
+/*** functions to manipulate image spans ***/
+
+static void spanFree(pmSpan *tmp) {
+    return;
+}
+
+/*
+ * pmSpanAlloc()
+ */
+pmSpan *pmSpanAlloc(int y, int x0, int x1)
+{
+    pmSpan *span = (pmSpan *)psAlloc(sizeof(pmSpan));
+    psMemSetDeallocator(span, (psFreeFunc) spanFree);
+
+    span->y = y;
+    span->x0 = x0;
+    span->x1 = x1;
+
+    return(span);
+}
+
+bool pmSpanTest(const psPtr ptr)
+{
+    return (psMemGetDeallocator(ptr) == (psFreeFunc)spanFree);
+}
+
+//
+// Sort pmSpans by y, then x0, then x1
+//
+int pmSpanSortByYX(const void **a, const void **b) {
+    const pmSpan *sa = *(const pmSpan **)a;
+    const pmSpan *sb = *(const pmSpan **)b;
+
+    if (sa->y < sb->y) {
+	return -1;
+    } else if (sa->y == sb->y) {
+	if (sa->x0 < sb->x0) {
+	    return -1;
+	} else if (sa->x0 == sb->x0) {
+	    if (sa->x1 < sb->x1) {
+		return -1;
+	    } else if (sa->x1 == sb->x1) {
+		return 0;
+	    } else {
+		return 1;
+	    }
+	} else {
+	    return 1;
+	}
+    } else {
+	return 1;
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSpan.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSpan.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmSpan.h	(revision 22158)
@@ -0,0 +1,28 @@
+/* @file  pmSpan.h
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.1.2.1 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-20 23:08:03 $
+ * Copyright 2006 Institute for Astronomy, University of Hawaii
+ */
+
+# ifndef PM_SPAN_H
+# define PM_SPAN_H
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+// Describe a segment of an image
+typedef struct {
+    int y;                              //!< Row that span's in
+    int x0;                             //!< Starting column (inclusive)
+    int x1;                             //!< Ending column (inclusive)
+} pmSpan;
+
+pmSpan *pmSpanAlloc(int y, int x1, int x2);
+bool pmSpanTest(const psPtr ptr);
+int pmSpanSortByYX (const void **a, const void **b);
+
+/// @}
+# endif /* PM_SPAN_H */
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmTrend2D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmTrend2D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmTrend2D.c	(revision 22158)
@@ -0,0 +1,300 @@
+/** @file  pmTrend2D.c
+ *
+ *  @author EAM, IfA
+ *
+ *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-01-15 02:47:51 $
+ *  Copyright 2004 Institute for Astronomy, University of Hawaii
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+# include <strings.h>
+# include <pslib.h>
+# include "pmTrend2D.h"
+
+static void pmTrend2DFree (pmTrend2D *trend) {
+
+    if (trend == NULL) 
+        return;
+
+    psFree (trend->stats);
+    psFree (trend->poly);
+    psFree (trend->map);
+    return;
+}
+
+pmTrend2D *pmTrend2DAlloc (pmTrend2DMode mode, psImage *image, int nXtrend, int nYtrend, psStats *stats)
+{
+    PS_ASSERT_PTR_NON_NULL(stats, NULL);
+    if (mode == PM_TREND_MAP) {
+        PS_ASSERT_PTR_NON_NULL(image, NULL);
+    }
+
+    pmTrend2D *trend = (pmTrend2D *) psAlloc(sizeof(pmTrend2D));
+    psMemSetDeallocator(trend, (psFreeFunc) pmTrend2DFree);
+
+    trend->map = NULL;
+    trend->poly = NULL;
+    trend->stats = psMemIncrRefCounter (stats);
+    trend->mode = mode;
+	
+    switch (mode) {
+      case PM_TREND_POLY_ORD:
+	trend->poly = psPolynomial2DAlloc (PS_POLYNOMIAL_ORD, nXtrend, nYtrend);
+	// set masking somehow
+ 	for (int nx = 0; nx < trend->poly->nX + 1; nx++) {
+	    for (int ny = 0; ny < trend->poly->nY + 1; ny++) {
+		if (nx + ny >= PS_MAX (trend->poly->nX, trend->poly->nY) + 1) {
+		    trend->poly->coeffMask[nx][ny] = PS_POLY_MASK_SET;
+		} else {
+		    trend->poly->coeffMask[nx][ny] = PS_POLY_MASK_NONE;
+		}
+	    }
+	}
+	break;
+
+      case PM_TREND_POLY_CHEB:
+	trend->poly = psPolynomial2DAlloc (PS_POLYNOMIAL_CHEB, nXtrend, nYtrend);
+	break;
+
+      case PM_TREND_MAP: {
+	  // binning defines the map scale relationship
+	  psImageBinning *binning = psImageBinningAlloc();
+	  binning->nXruff = nXtrend;
+	  binning->nYruff = nYtrend;
+	  binning->nXfine = image->numCols;
+	  binning->nYfine = image->numRows;
+
+	  trend->map = psImageMapAlloc (image, binning, stats);
+	  psFree (binning);
+	  break;
+      }
+      // XXX: Put a more graceful error here.
+      default:
+	psAbort ("error");
+    }
+    return (trend);
+}
+
+bool psMemCheckTrend2D(psPtr ptr)
+{
+    PS_ASSERT_PTR(ptr, false);
+    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmTrend2DFree);
+}
+
+pmTrend2D *pmTrend2DNoImageAlloc (pmTrend2DMode mode, psImageBinning *binning, psStats *stats)
+{
+    if (mode == PM_TREND_MAP) {
+        PS_ASSERT_PTR_NON_NULL(binning, NULL);
+        PS_ASSERT_PTR_NON_NULL(stats, NULL);
+    }
+    pmTrend2D *trend = (pmTrend2D *) psAlloc(sizeof(pmTrend2D));
+    psMemSetDeallocator(trend, (psFreeFunc) pmTrend2DFree);
+
+    trend->map = NULL;
+    trend->poly = NULL;
+    trend->stats = psMemIncrRefCounter (stats);
+    trend->mode = mode;
+	
+    switch (mode) {
+      case PM_TREND_POLY_ORD:
+	trend->poly = psPolynomial2DAlloc (PS_POLYNOMIAL_ORD, binning->nXruff, binning->nYruff);
+	// set masking somehow
+ 	for (int nx = 0; nx < trend->poly->nX + 1; nx++) {
+	    for (int ny = 0; ny < trend->poly->nY + 1; ny++) {
+		if (nx + ny >= PS_MAX (trend->poly->nX, trend->poly->nY) + 1) {
+		    trend->poly->coeffMask[nx][ny] = PS_POLY_MASK_SET;
+		} else {
+		    trend->poly->coeffMask[nx][ny] = PS_POLY_MASK_NONE;
+		}
+	    }
+	}
+	break;
+
+      case PM_TREND_POLY_CHEB:
+	trend->poly = psPolynomial2DAlloc (PS_POLYNOMIAL_CHEB, binning->nXruff, binning->nYruff);
+	break;
+
+      case PM_TREND_MAP: {
+	  // binning defines the map scale relationship
+	  trend->map = psImageMapNoImageAlloc (binning, stats);
+	  break;
+      }
+
+      default:
+	psAbort ("error");
+    }
+    return (trend);
+}
+
+pmTrend2D *pmTrend2DFieldAlloc (pmTrend2DMode mode, int nXfield, int nYfield, int nXtrend, int nYtrend, psStats *stats)
+{
+    PS_ASSERT_PTR_NON_NULL(stats, NULL);
+    pmTrend2D *trend = (pmTrend2D *) psAlloc(sizeof(pmTrend2D));
+    psMemSetDeallocator(trend, (psFreeFunc) pmTrend2DFree);
+
+    trend->map = NULL;
+    trend->poly = NULL;
+    trend->stats = psMemIncrRefCounter (stats);
+    trend->mode = mode;
+	
+    switch (mode) {
+      case PM_TREND_POLY_ORD:
+	trend->poly = psPolynomial2DAlloc (PS_POLYNOMIAL_ORD, nXtrend, nYtrend);
+	// set masking somehow
+ 	for (int nx = 0; nx < trend->poly->nX + 1; nx++) {
+	    for (int ny = 0; ny < trend->poly->nY + 1; ny++) {
+		if (nx + ny >= PS_MAX (trend->poly->nX, trend->poly->nY) + 1) {
+		    trend->poly->coeffMask[nx][ny] = PS_POLY_MASK_SET;
+		} else {
+		    trend->poly->coeffMask[nx][ny] = PS_POLY_MASK_NONE;
+		}
+	    }
+	}
+	break;
+
+      case PM_TREND_POLY_CHEB:
+	trend->poly = psPolynomial2DAlloc (PS_POLYNOMIAL_CHEB, nXtrend, nYtrend);
+	break;
+
+      case PM_TREND_MAP: {
+	  // binning defines the map scale relationship
+	  psImageBinning *binning = psImageBinningAlloc();
+	  binning->nXfine = nXfield;
+	  binning->nYfine = nYfield;
+	  binning->nXruff = nXtrend;
+	  binning->nYruff = nYtrend;
+
+	  trend->map = psImageMapAlloc (NULL, binning, stats);
+	  psFree (binning);
+	  break;
+      }
+
+      default:
+        // XXX: Put a more graceful error here.
+	psAbort ("error");
+    }
+    return (trend);
+}
+
+bool pmTrend2DFit (pmTrend2D *trend, psVector *mask, psMaskType maskVal, psVector *x,
+                   psVector *y, psVector *f, psVector *df)
+{
+    PS_ASSERT_PTR_NON_NULL(trend, false);
+    PS_ASSERT_VECTOR_NON_NULL(x, false);
+    PS_ASSERT_VECTOR_NON_NULL(y, false);
+    PS_ASSERT_VECTOR_NON_NULL(f, false);
+
+    bool status;
+    switch (trend->mode) {
+      case PM_TREND_POLY_ORD:
+      case PM_TREND_POLY_CHEB:
+        status = psVectorClipFitPolynomial2D (trend->poly, trend->stats, mask, maskVal, f, df, x, y);
+	// we can use the API here which adjusts the polynomial order based on the number
+	// of points in the image, and potentially based on the fractional range of the
+	// data?
+	break;
+
+      case PM_TREND_MAP:
+	// XXX supply fraction from trend elements
+	// XXX need to add the API which adjusts the scale
+	status = psImageMapClipFit (trend->map, trend->stats, mask, maskVal, x, y, f, df);
+	break;
+
+      default:
+	psAbort ("error");
+    }
+    return status;
+}
+
+double pmTrend2DEval (pmTrend2D *trend, float x, float y)
+{
+    if (!trend) return 0.0;
+
+    double result;
+    switch (trend->mode) {
+      case PM_TREND_POLY_ORD:
+      case PM_TREND_POLY_CHEB:
+	result = psPolynomial2DEval (trend->poly, x, y);
+	break;
+
+      case PM_TREND_MAP:
+	result = psImageMapEval (trend->map, x, y);
+	break;
+
+      default:
+	psAbort ("error");
+    }
+    return result;
+}
+
+psVector *pmTrend2DEvalVector (pmTrend2D *trend, psVector *x, psVector *y)
+{
+    PS_ASSERT_PTR_NON_NULL(trend, NULL);
+    PS_ASSERT_VECTOR_NON_NULL(x, false);
+    PS_ASSERT_VECTOR_NON_NULL(y, false);
+    psVector *result;
+
+    switch (trend->mode) {
+      case PM_TREND_POLY_ORD:
+      case PM_TREND_POLY_CHEB:
+	result = psPolynomial2DEvalVector (trend->poly, x, y);
+	break;
+
+      case PM_TREND_MAP:
+	result = psImageMapEvalVector (trend->map, x, y);
+	break;
+
+      default:
+	psAbort ("error");
+    }
+    return result;
+}
+
+psString pmTrend2DModeToString (pmTrend2DMode mode) {
+    
+    psString name;
+
+    switch (mode) {
+      case PM_TREND_NONE:
+	name = psStringCopy ("NONE");
+	break;
+      case PM_TREND_POLY_ORD:
+	name = psStringCopy ("POLY_ORD");
+	break;
+      case PM_TREND_POLY_CHEB:
+	name = psStringCopy ("POLY_CHEB");
+	break;
+      case PM_TREND_MAP:
+	name = psStringCopy ("MAP");
+	break;
+      default:
+        psError (PS_ERR_UNKNOWN, true, "Unknown pmTrend2D mode\n");
+	psAbort ("invalid mode %d", mode);
+    }
+    return name;
+}
+
+pmTrend2DMode pmTrend2DModeFromString (psString name) {
+
+    if (!name) return PM_TREND_NONE;
+
+    if (!strcasecmp (name, "NONE")) {
+	return PM_TREND_NONE;
+    }
+    if (!strcasecmp (name, "POLY_ORD")) {
+	return PM_TREND_POLY_ORD;
+    }
+    if (!strcasecmp (name, "POLY_CHEB")) {
+	return PM_TREND_POLY_CHEB;
+    }
+    if (!strcasecmp (name, "MAP")) {
+	return PM_TREND_MAP;
+    }
+    psError (PS_ERR_UNKNOWN, true, "Unknown pmTrend2D mode %s\n", name);
+    return PM_TREND_NONE;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmTrend2D.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmTrend2D.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/objects/pmTrend2D.h	(revision 22158)
@@ -0,0 +1,55 @@
+/* @file  pmTrend2D.h
+ *
+ * functions to represent ways of modeling a 2D trend
+ *
+ * @author EAM, IfA
+ *
+ * @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-12-15 01:23:18 $
+ * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+# ifndef PM_TREND_2D_H
+# define PM_TREND_2D_H
+
+#include <pslib.h>
+
+/// @addtogroup Objects Object Detection / Analysis Functions
+/// @{
+
+typedef enum {
+    PM_TREND_NONE,
+    PM_TREND_POLY_ORD,
+    PM_TREND_POLY_CHEB,
+    PM_TREND_MAP,
+} pmTrend2DMode;
+
+typedef struct {
+    psPolynomial2D *poly;
+    psImageMap *map;
+    psStats *stats;                     // Statistics for clipped fitting
+    psStatsOptions singleMean, singleStdev; // Staistics for mean and stdev when there's a single pixel
+    pmTrend2DMode mode; // POLY_ORD, POLY_CHEB, MAP
+} pmTrend2D;
+
+// allocate a pmTrend2D structure tied to an image dimensions.  nXtrend,nYtrend is the order for the polynomials, max number of grid cells for
+// psImageMap
+pmTrend2D *pmTrend2DAlloc (pmTrend2DMode mode, psImage *image, int nXtrend, int nYtrend, psStats *stats);
+
+bool psMemCheckTrend2D(psPtr ptr);
+
+pmTrend2D *pmTrend2DNoImageAlloc (pmTrend2DMode mode, psImageBinning *binning, psStats *stats);
+
+// allocate a pmTrend2D tied to an abstract field with size nXfield,nYfield
+pmTrend2D *pmTrend2DFieldAlloc (pmTrend2DMode mode, int nXfield, int nYfield, int nXtrend, int nYtrend, psStats *stats);
+
+bool pmTrend2DFit (pmTrend2D *trend, psVector *mask, psMaskType maskVal, psVector *x, psVector *y, psVector *f, psVector *df);
+
+double pmTrend2DEval (pmTrend2D *trend, float x, float y);
+psVector *pmTrend2DEvalVector (pmTrend2D *trend, psVector *x, psVector *y);
+
+psString pmTrend2DModeToString (pmTrend2DMode mode);
+pmTrend2DMode pmTrend2DModeFromString (psString name);
+
+/// @}
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/psmodules.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/psmodules.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/psmodules.h	(revision 22158)
@@ -0,0 +1,123 @@
+#ifndef PS_MODULES_H
+#define PS_MODULES_H
+
+#include <pslib.h>
+
+// the following headers are from psModule:extras
+#include <psPipe.h>
+#include <psIOBuffer.h>
+#include <psVectorBracket.h>
+#include <pmKapaPlots.h>
+
+// XXX the following headers define constructs needed by the elements below
+#include <pmConfig.h>
+#include <pmDetrendDB.h>
+#include <pmHDU.h>
+#include <pmFPA.h>
+#include <pmFPALevel.h>
+#include <pmFPAview.h>
+#include <pmFPAfile.h>
+
+// the following headers are from psModule:config
+#include <pmErrorCodes.h>
+#include <pmConfigRecipes.h>
+#include <pmConfigCamera.h>
+#include <pmConfigCommand.h>
+#include <pmConfigMask.h>
+#include <pmVersion.h>
+
+// the following headers are from psModule:concepts
+#include <pmConcepts.h>
+#include <pmConceptsRead.h>
+#include <pmConceptsStandard.h>
+#include <pmConceptsWrite.h>
+#include <pmConceptsPhotcode.h>
+#include <pmConceptsAverage.h>
+#include <pmConceptsUpdate.h>
+
+// the following headers are from psModule:camera
+#include <pmHDUUtils.h>
+#include <pmHDUGenerate.h>
+#include <pmFPAFlags.h>
+#include <pmFPAfileDefine.h>
+#include <pmFPAfileFitsIO.h>
+#include <pmFPAfileIO.h>
+#include <pmFPARead.h>
+#include <pmFPAConstruct.h>
+#include <pmFPACopy.h>
+#include <pmFPAHeader.h>
+#include <pmFPAMaskWeight.h>
+#include <pmFPAMosaic.h>
+#include <pmFPARead.h>
+#include <pmFPAWrite.h>
+#include <pmFPA_JPEG.h>
+#include <pmFPAExtent.h>
+#include <pmFPACalibration.h>
+#include <pmReadoutStack.h>
+#include <pmFPAUtils.h>
+#include <pmCellSquish.h>
+
+// the following headers are from psModule:detrend
+#include <pmFlatField.h>
+#include <pmFlatNormalize.h>
+#include <pmFringeStats.h>
+#include <pmMaskBadPixels.h>
+#include <pmNonLinear.h>
+#include <pmOverscan.h>
+#include <pmBias.h>
+#include <pmShutterCorrection.h>
+// #include <pmSkySubtract.h>
+#include <pmDark.h>
+
+// the following headers are from psModule:astrom
+#include <pmAstrometryWCS.h>
+#include <pmAstrometryUtils.h>
+#include <pmAstrometryRegions.h>
+#include <pmAstrometryObjects.h>
+#include <pmAstrometryModel.h>
+#include <pmAstrometryRefstars.h>
+#include <pmAstrometryDistortion.h>
+
+// the following headers are from psModule:imcombine
+#include <pmStack.h>
+#include <pmStackReject.h>
+#include <pmSubtraction.h>
+#include <pmSubtractionStamps.h>
+#include <pmSubtractionKernels.h>
+#include <pmSubtractionMatch.h>
+#include <pmSubtractionIO.h>
+#include <pmSubtractionParams.h>
+#include <pmSubtractionMask.h>
+#include <pmSubtractionEquation.h>
+#include <pmReadoutCombine.h>
+
+// the following headers are from psModule:objects
+#include <pmPeaks.h>
+#include <pmSpan.h>
+#include <pmFootprint.h>
+#include <pmDetections.h>
+#include <pmMoments.h>
+#include <pmResiduals.h>
+#include <pmGrowthCurve.h>
+#include <pmTrend2D.h>
+#include <pmPSF.h>
+#include <pmModel.h>
+#include <pmSource.h>
+#include <pmSourceUtils.h>
+#include <pmSourceIO.h>
+#include <pmSourceSky.h>
+#include <pmSourceFitModel.h>
+#include <pmSourceFitSet.h>
+#include <pmSourceContour.h>
+#include <pmSourcePlots.h>
+#include <pmPSF_IO.h>
+#include <pmPSFtry.h>
+#include <pmModelClass.h>
+#include <pmModelUtils.h>
+#include <pmSourcePhotometry.h>
+
+// The following headers are from random locations, here because they cross bounds
+#include <pmReadoutFake.h>
+#include <pmPSFEnvelope.h>
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/sky/pmSkyCell.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/sky/pmSkyCell.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/sky/pmSkyCell.h	(revision 22158)
@@ -0,0 +1,18 @@
+#ifndef PM_SKY_CELL_H
+#define PM_SKY_CELL_H
+
+/// Structure representing a sky cell
+typedef struct
+{
+    psImage *image;                     // Image; type F32
+    psImage *mask;                      // Mask image; type MASK_TYPE
+    psImage *weight;                    // Weight map; type F32
+    psPlaneTransform *toTPA;            // Transformation from pixels to tangent plane
+    psPlaneTransform *fromTPA;          // Transformation from tangent plane to pixels
+    psProjection *toSky;                // Projection to the sky
+}
+pmSkyCell;
+
+
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/sky/pmWarp.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/sky/pmWarp.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/sky/pmWarp.h	(revision 22158)
@@ -0,0 +1,24 @@
+#ifndef PM_WARP_MAP_H
+#define PM_WARP_MAP_H
+
+// a single pswarpMap converts coordinates from one image to a second image
+// the linear model is only valid over a limited range of pixels
+typedef struct
+{
+    double Xo, Xx, Xy;
+    double Yo, Yx, Yy;
+    int xo;
+    int yo;
+}
+pswarpMap;
+
+// the pswarpMapGrid carries a collection of pswarpMag structures representing the
+// local value of the pswarpMap at different locations in the image.
+typedef struct
+{
+    pswarpMap ***maps;
+    int nXpts, nYpts;                   // number of x,y samples in the grid
+    int nXpix, nYpix;                   // x,y spacing in src image pixels of grid samples
+    int xMin,  yMin;                    // coordinate of first grid sample
+}
+pswarpMapGrid;
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/sky/pmWarpMap.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/sky/pmWarpMap.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/sky/pmWarpMap.c	(revision 22158)
@@ -0,0 +1,241 @@
+#include <stdio.h>
+#include <math.h>
+#include <pslib.h>
+
+#include "pmWarpMap.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Allocators and deallocators
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static void warpMapFree(pswarpMap *map)
+{
+    // No operations required; this function exists merely to identify a pmWarpMap
+    return;
+}
+
+pswarpMap *pswarpMapAlloc(void)
+{
+    pswarpMap *map = (pswarpMap *) psAlloc (sizeof(pswarpMap));
+    psMemSetDeallocator(map, (psFreeFunc)warpMapFree);
+
+    map->Xo = map->Xx = map->Xy = NAN;
+    map->Yo = map->Yx = map->Yy = NAN;
+    map->xo = map->yo = NAN;
+
+    return map;
+}
+
+
+static void warpMapGridFree(pswarpMapGrid *grid)
+{
+    if (!grid->maps) {
+        // Nothing to free
+        return;
+    }
+
+    for (int i = 0; i < grid->nXpts; i++) {
+        for (int j = 0; j < grid->nYpts; j++) {
+            psFree(grid->maps[i][j]);
+        }
+        psFree(grid->maps[i]);
+    }
+    psFree (grid->maps);
+    return;
+}
+
+pswarpMapGrid *pswarpMapGridAlloc(int nXpts, int nYpts)
+{
+    PS_ASSERT_INT_POSITIVE(nXpts, NULL);
+    PS_ASSERT_INT_POSITIVE(nYpts, NULL);
+
+    pswarpMapGrid *grid = (pswarpMapGrid *) psAlloc(sizeof(pswarpMapGrid));
+    psMemSetDeallocator(grid, (psFreeFunc)warpMapGridFree);
+
+    grid->maps = psAlloc(nXpts*sizeof(void **));
+    for (int i = 0; i < nXpts; i++) {
+        grid->maps[i] = psAlloc(nYpts*sizeof(void *));
+        for (int j = 0; j < nYpts; j++) {
+            grid->maps[i][j] = pswarpMapAlloc();
+        }
+    }
+    grid->nXpts = nXpts;
+    grid->nYpts = nYpts;
+
+    grid->nXpix = 0;
+    grid->nYpix = 0;
+
+    return grid;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Operations
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// XXX for the moment, ignore readout->cell->chip offsets
+pswarpMapGrid *pswarpMapGridFromImage(pmSkyCell *dest, const pmReadout *src, int nXpix, int nYpix)
+{
+    PS_ASSERT_PTR_NON_NULL(dest, NULL);
+    PS_ASSERT_PTR_NON_NULL(src, NULL);
+    PS_ASSERT_IMAGE_NON_NULL(src->image, NULL);
+    PS_ASSERT_INT_NON_NEGATIVE(nXpix, NULL);
+    PS_ASSERT_INT_NON_NEGATIVE(nYpix, NULL);
+
+    // split the difference of the remainder
+    int xMin = 0.5 * (src->image->numCols % nXpix); // Minimum in x
+    int yMin = 0.5 * (src->image->numRows % nYpix); // Minimum in y
+
+    int nXpts = src->image->numCols / nXpix; // Number of points in x
+    if (src->image->numCols % nXpix == 0) {
+        nXpts++;
+    }
+    int nYpts = src->image->numRows / nYpix; // Number of points in y
+    if (src->image->numRows % nYpix == 0) {
+        nYpts++;
+    }
+
+    pmWarpMapGrid *grid = pmWarpMapGridAlloc(nXpts, nYpts);
+    grid->nXpix = nXpix;
+    grid->nYpix = nYpix;
+    grid->xMin = xMin;
+    grid->yMin = yMin;
+
+    for (int ni = 0, i = xMin; ni < nXpts; i += nXpix, ni++) {
+        for (int nj = 0, j = yMin; nj < nYpts; j += nYpix, nj++) {
+            pmWarpMapSetLocalModel(grid->maps[ni][nj], dest, src, i, j);
+        }
+    }
+
+    return grid;
+}
+
+bool pmWarpMapGridSetGrid(const pmWarpMapGrid *grid, int ix, int iy, int *gridX, int *gridY)
+{
+    *gridX = (ix - grid->xMin + 0.5*grid->nXpix) / grid->nXpix;
+    *gridY = (iy - grid->yMin + 0.5*grid->nYpix) / grid->nYpix;
+
+    return true;
+}
+
+bool pmWarpMapGridNextGrid(const pmWarpMapGrid *grid, int gridX, int gridY, int *nextX, int *nextY)
+{
+    *nextX = gridX*grid->nXpix + grid->xMin + 0.5*grid->nXpix;
+    *nextY = gridY*grid->nYpix + grid->yMin + 0.5*grid->nYpix;
+
+    return true;
+}
+
+// measure the max error accumulated in appling one grid point to its neighbors
+double pmWarpMapGridMaxError(const pmWarpMapGrid *grid)
+{
+    double maxError = 0;                // Maximum error
+
+    for (int i = 0; i < grid->nXpts - 1; i++) {
+        for (int j = 0; j < grid->nYpts - 1; j++) {
+            // measure the output coordinates for the next grid position using the current grid map
+            // compare with the coordinates measured using the next grid map
+            double xRaw, yRaw;          // Raw position
+            double xRef, yRef;          // Reference position
+
+            pmWarpMapApply(&xRaw, &yRaw, grid->maps[i][j], grid->maps[i][j]->xo + grid->nXpix,
+                           grid->maps[i][j]->yo);
+            pmWarpMapApply(&xRef, &yRef, grid->maps[i+1][j], grid->maps[i][j]->xo + grid->nXpix,
+                           grid->maps[i][j]->yo);
+
+            double posError = hypot(xRaw-xRef, yRaw-yRef);
+            maxError = PS_MAX(maxError, posError);
+        }
+    }
+
+    return maxError;
+}
+
+bool pmWarpMapApply(double *outX, double *outY, const pmWarpMap *map, double inX, double inY)
+{
+    *outX = map->Xo + map->Xx*inX + map->Xy*inY;
+    *outY = map->Yo + map->Yx*inX + map->Yy*inY;
+
+    return true;
+}
+
+bool pmWarpMapSetLocalModel(pmWarpMap *map, const pmSkyCell *dest, const pmReadout *src, int ix, int iy)
+{
+    PS_ASSERT_PTR_NON_NULL(map, false);
+    PS_ASSERT_PTR_NON_NULL(dest, false);
+    PS_ASSERT_PTR_NON_NULL(dest->toSky, false);
+    PS_ASSERT_PTR_NON_NULL(dest->fromTPA, false);
+    PS_ASSERT_PTR_NON_NULL(src, false);
+    pmCell *cell = src->parent;         // Parent cell of source
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    pmChip *chip = cell->parent;        // Parent chip of source
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_PTR_NON_NULL(chip->toFPA, false);
+    pmFPA *fpa = chip->parent;          // Parent FPA of source
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(fpa->toTPA, false);
+    PS_ASSERT_PTR_NON_NULL(fpa->toSky, false);
+    PS_ASSERT_INT_NON_NEGATIVE(ix, false);
+    PS_ASSERT_INT_NON_NEGATIVE(iy, false);
+
+    // These will get allocated in the course of the calculations; may as well allocate them here
+    // XXX save these as static for speed?
+    // Alternatively, pass in a buffer containing these pre-allocated.
+    psPlane *offset = psPlaneAlloc();   // Position offset from the main position of interest (ix,iy)
+    psPlane *FP = psPlaneAlloc();       // Position in the focal plane
+    psPlane *TP = psPlaneAlloc();       // Position in the tangent plane
+    psSphere *sky = psSphereAlloc();    // Position on the sky
+
+    // XXX need to include readout->cell->chip offsets
+    // --> Look up CELL.X0, CELL.Y0 in concepts
+    // --> Use readout->col0, readout->row0
+
+    // V(0,0) position
+    offset->x = ix;
+    offset->y = iy;
+    psPlaneTransformApply(FP, chip->toFPA, offset);
+    psPlaneTransformApply (TP, fpa->toTPA, FP);
+    psDeproject(sky, TP, fpa->toSky);
+    psProject(TP, sky, dest->toSky);
+    psPlane *V00 = psPlaneTransformApply(NULL, dest->fromTPA, TP); // Coordinates at the position of interest
+
+    // V(1,0) position
+    offset->x = ix + 1;
+    offset->y = iy;
+    psPlaneTransformApply(FP, chipSrc->toFPA, offset);
+    psPlaneTransformApply(TP, fpaSrc->toTPA, FP);
+    psDeproject(sky, TP, fpaSrc->toSky);
+    psProject(TP, sky, dest->toSky);
+    psPlane *V10 = psPlaneTransformApply(NULL, dest->fromTPA, TP); // Coordinates at position + (1,0)
+
+    // V(0,1) position
+    offset->x = ix;
+    offset->y = iy + 1;
+    psPlaneTransformApply(FP, chipSrc->toFPA, offset);
+    psPlaneTransformApply(TP, fpaSrc->toTPA, FP);
+    psDeproject(sky, TP, fpaSrc->toSky);
+    psProject(TP, sky, fpaDest->toSky);
+    psPlane *V01 = psPlaneTransformApply(NULL, dest->fromTPA, TP); // Coordinates at position + (0,1)
+
+    psFree(offset);
+    psFree(FP);
+    psFree(TP);
+    psFree(sky);
+
+    // Generate local linear transformation
+    map->Xx = V10->x - V00->x;
+    map->Xy = V01->x - V00->x;
+    map->Xo = V00->x - map->Xx * ix - map->Xy * iy;
+
+    map->Yx = V10->y - V00->y;
+    map->Yy = V01->y - V00->y;
+    map->Yo = V00->y - map->Yx * ix - map->Yy * iy;
+
+    map->xo = ix;
+    map->yo = iy;
+
+    psFree(V00);
+    psFree(V10);
+    psFree(V01);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/src/sky/pmWarpMap.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/src/sky/pmWarpMap.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/src/sky/pmWarpMap.h	(revision 22158)
@@ -0,0 +1,88 @@
+/*  @file pmWarpMap.h
+ *  @brief Warp Map Manipulation functions
+ * 
+ *  @author Paul Price, IfA
+ *  @author Eugene Magnier, IfA
+ * 
+ *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-01-24 01:05:41 $
+ *  Copyright 2005-2006 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef PM_WARP_MAP_H
+#define PM_WARP_MAP_H
+
+/// @addtogroup Sky
+/// @{
+
+// a single pmWarpMap converts coordinates from one image to a second image
+// the linear model is only valid over a limited range of pixels
+typedef struct
+{
+    double Xo, Xx, Xy;                  // Transformation coefficients for x
+    double Yo, Yx, Yy;                  // Transformation coefficients for y
+    int xo, yo;                         // Origin
+}
+pmWarpMap;
+
+// the pmWarpMapGrid carries a collection of pmWarpMag structures representing the
+// local value of the pmWarpMap at different locations in the image.
+typedef struct
+{
+    pmWarpMap ***maps;                  // 2D image of pointers to maps
+    int nXpts, nYpts;                   // number of x,y samples in the grid
+    int nXpix, nYpix;                   // x,y spacing in src image pixels of grid samples
+    int xMin,  yMin;                    // coordinate of first grid sample
+}
+pmWarpMapGrid;
+
+/// Allocator
+pmWarpMap *pmWarpMapAlloc(void);
+
+/// Allocator
+pmWarpMapGrid *pmWarpMapGridAlloc(int Nx, // Number of grid points in x
+                                  int Ny // Number of grid points in y
+                                 );
+
+
+// Operations follow
+
+
+// construct a grid with superpixel spacing of nXpix, nYpix
+pmWarpMapGrid *pmWarpMapGridFromImage(pmSkyCell *dest, // Destination sky cell
+                                      const pmReadout *src, // Source readout
+                                      int nXpix, // Number of pixels in x
+                                      int nYpix // Number of pixels in y
+                                     );
+
+bool pmWarpMapGridSetGrid(pmWarpMapGrid *grid,
+                          int ix, int iy,
+                          int *gridX,
+                          int *gridY
+                         );
+
+bool pmWarpMapGridNextGrid(pmWarpMapGrid *grid,
+                           int gridX,
+                           int gridY,
+                           int *nextX,
+                           int *nextY
+                          );
+
+// measure the max error accumulated in appling one grid point to its neighbors
+double pmWarpMapGridMaxError(const pmWarpMapGrid *grid
+                            );
+
+bool pmWarpMapApply(double *outX,
+                    double *outY,
+                    const pmWarpMap *map,
+                    double inX,
+                    double inY);
+
+// determine the map for the given pixel from src to dest. pixel is in src coords
+bool pmWarpMapSetLocalModel(pmWarpMap *map,
+                            const pmSkyCell *dest,
+                            const pmReadout *src,
+                            int ix, int iy
+                           );
+/// @}
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/templates/c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/templates/c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/templates/c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/templates/h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/templates/h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/templates/h	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/.cvsignore	(revision 22158)
@@ -0,0 +1,15 @@
+.deps
+.libs
+Makefile
+tst_pmFlatField
+tst_pmMaskBadPixels
+tst_pmNonLinear
+tst_pmSubtractBias
+temp
+Makefile.in
+tst_pmObjects01
+tst_pmReadoutCombine
+tst_pmSubtractSky
+tst_pmImageSubtract
+tst_pmImageCombine
+tst_pmAstrometry
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/Makefile.am	(revision 22158)
@@ -0,0 +1,9 @@
+SUBDIRS = tap pstap $(SRCDIRS)
+
+TESTS = test.pl
+
+EXTRA_DIST = test.pl
+
+CLEANFILES = core core.* *~
+
+test: check
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/.cvsignore	(revision 22158)
@@ -0,0 +1,12 @@
+.deps
+.libs
+Makefile
+Makefile.in
+temp
+tst_pmAstrometry
+tst_pmAstrometry01
+tap_pmAstrometryWCS
+tap_pmAstrometryWCS_DVO
+tap_pmAstrometryWCS_DVO2
+tap_pmAstrometryWCS_DVO3
+tap_pmAstrometryWCS_DVO4
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/Makefile.am	(revision 22158)
@@ -0,0 +1,30 @@
+AM_CPPFLAGS = \
+	$(SRCINC) \
+	-I$(top_srcdir)/test/tap/src \
+	-I$(top_srcdir)/test/pstap/src \
+	$(PSMODULES_CFLAGS)
+
+AM_LDFLAGS = \
+	$(top_builddir)/src/libpsmodules.la  \
+	$(top_builddir)/test/tap/src/libtap.la \
+	$(top_builddir)/test/pstap/src/libpstap.la \
+	$(PSMODULES_LIBS)
+
+TEST_PROGS = \
+	tap_pmAstrometryWCS \
+	tap_pmAstrometryWCS_DVO \
+	tap_pmAstrometryWCS_DVO2 \
+	tap_pmAstrometryWCS_DVO3 \
+	tap_pmAstrometryWCS_DVO4
+
+if BUILD_TESTS
+bin_PROGRAMS = $(TEST_PROGS)
+TESTS = $(TEST_PROGS)
+else
+check_PROGRAMS = $(TEST_PROGS)
+endif
+
+CLEANFILES = $(check_DATA) temp/* core core.* *~ *.bb *.bbg *.da gmon.out
+
+test: check
+	$(top_srcdir)/test/test.pl
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmAstrometry.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmAstrometry.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmAstrometry.c	(revision 22158)
@@ -0,0 +1,318 @@
+    /** @file  tst_pmAstrometry.c
+     *
+ *  @brief Contains the tests: pmAstrometry.[ch].  The pmxxxAlloc()
+ *  and psFree() functionality are used here.
+ *
+ *  @author GLG, MHPCC
+ *
+ *  XXX: Untested: pmFPACheckParents()
+ *  XXX: Create the pmHDU alloc/free function, test them here
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-06-19 18:28:38 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define CHIP_ALLOC_NAME "ChipName"
+#define CELL_ALLOC_NAME "CellName"
+#define MISC_NUM 32
+#define MISC_NAME "META00"
+#define MISC_NAME2 "META01"
+#define NUM_BIAS_DATA 10
+#define TEST_NUM_ROWS 32
+#define TEST_NUM_COLS 32
+
+psPlaneTransform *PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM()
+{
+    psPlaneTransform *pt = psPlaneTransformAlloc(1, 1);
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+    return(pt);
+}
+
+psPlaneDistort *PS_CREATE_4D_IDENTITY_PLANE_DISTORT()
+{
+    psPlaneDistort *pd = psPlaneDistortAlloc(1, 1, 1, 1);
+    pd->x->coeff[1][0][0][0] = 1.0;
+    pd->y->coeff[0][1][0][0] = 1.0;
+    return(pd);
+}
+
+/******************************************************************************
+generateSimpleFPA(): This function generates a pmFPA data structure and then
+populates its members with real data.  We do this to ensure that the data is
+later being psFree()'ed correctly.
+ *****************************************************************************/
+pmFPA* generateSimpleFPA(psMetadata *camera)
+{
+    pmFPA* fpa = pmFPAAlloc(camera);
+    fpa->fromTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toSky = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+    psMetadataAddS32(fpa->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32((psMetadata *) fpa->camera, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(fpa->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    fpa->hdu = pmHDUAlloc(NULL);
+    return(fpa);
+}
+
+
+/******************************************************************************
+testFPAAlloc()
+    1: We ensure that pmFPAAlloc() properly allocates a pmFPA struct.
+    2: We populate the members with real data to ensure they are being
+       free'ed correctly.
+ *****************************************************************************/
+void testFPAAlloc(void)
+{
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = pmFPAAlloc(camera);
+        ok(fpa != NULL, "pmFPAAlloc() returned a non-NULL");
+        ok(fpa->fromTPA == NULL, "pmFPAAlloc() set ->fromTPA to NULL");
+        ok(fpa->toTPA == NULL, "pmFPAAlloc() set ->toTPA to NULL");
+        ok(fpa->toSky == NULL, "pmFPAAlloc() set ->toSky to NULL");
+        ok(fpa->concepts != NULL &&
+           psMemCheckMetadata(fpa->concepts), "pmFPAAlloc() set ->concepts correctly");
+        ok(fpa->conceptsRead == PM_CONCEPT_SOURCE_NONE, "pmFPAAlloc() set ->conceptsRead correctly");
+        ok(fpa->analysis != NULL &&
+           psMemCheckMetadata(fpa->analysis), "pmFPAAlloc() set ->analysis correctly");
+        ok(fpa->camera == camera, "pmFPAAlloc() set ->camera correctly");
+        ok(fpa->chips != NULL &&
+           psMemCheckArray(fpa->chips), "pmFPAAlloc() set ->chips correctly");
+        ok(fpa->hdu == NULL, "pmFPAAlloc() set ->hdu to NULL");
+        ok(fpa->wrote_phu == false, "pmFPAAlloc() set ->wrote_phu to FALSE");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Populate the pmFPA struct with real data to ensure they were
+    // psFree()'ed correctly.
+    {
+        psMemId id = psMemGetId();
+        pmFPA* fpa = generateSimpleFPA(NULL);
+        psFree(fpa);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
+/******************************************************************************
+generateSimpleChip(): This function generates a pmChip data structure and then
+populates its members with real data.  We do this to ensure that the data is
+later being psFree()'ed correctly.
+ *****************************************************************************/
+pmChip *generateSimpleChip(pmFPA *fpa)
+{
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    chip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    chip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    psMetadataAddS32(chip->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(chip->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    chip->hdu = pmHDUAlloc(NULL);
+    return(chip);
+}
+
+void testChipAlloc(void)
+{
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+        ok(chip != NULL, "pmChipAlloc() returned non-NULL");
+        ok(chip->toFPA == NULL, "pmChipAlloc() set chip->toChip to NULL");
+        ok(chip->fromFPA == NULL, "pmChipAlloc() set chip->fromChip to NULL");
+        ok(chip->concepts != NULL &&
+           psMemCheckMetadata(chip->concepts), "pmChipAlloc() set ->concepts correctly");
+        ok(chip->conceptsRead == PM_CONCEPT_SOURCE_NONE, "pmCellAlloc() set ->conceptsRead correctly");
+        ok(chip->analysis != NULL &&
+           psMemCheckMetadata(chip->analysis), "pmChipAlloc() set ->analysis correctly");
+        ok(chip->cells != NULL &&
+           psMemCheckArray(chip->cells), "pmChipAlloc() set ->cells correctly");
+        ok(chip->parent == fpa, "pmChipAlloc() set ->parent correctly");
+        ok(chip->process == true, "pmChipAlloc() set ->process correctly");
+        ok(chip->file_exists == false, "pmChipAlloc() set ->file_exists correctly");
+        ok(chip->data_exists == false, "pmChipAlloc() set ->data_exists correctly");
+        ok(chip->hdu == NULL, "pmChipAlloc() set ->hdu to NULL");
+        ok(chip->wrote_phu == false, "pmChipAlloc() set ->wrote_phu correctly");
+        psFree(camera);
+        psFree(fpa);
+        psFree(chip);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Populate the pmChip struct with real data to ensure they were
+    // psFree()'ed correctly.
+    {
+        psMemId id = psMemGetId();
+        pmChip *chip = generateSimpleChip(NULL);
+        psFree(chip);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.  We do this to ensure that the data is
+later being psFree()'ed correctly.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmFPA *fpa, pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    cell->hdu = pmHDUAlloc(NULL);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(cell);
+}
+
+void testCellAlloc(void)
+{
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+        pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+        ok(cell != NULL, "pmCellAlloc returned non-NULL");
+        ok(cell->concepts != NULL &&
+           psMemCheckMetadata(cell->concepts), "pmCellpAlloc() set ->concepts correctly");
+        ok(cell->conceptsRead == PM_CONCEPT_SOURCE_NONE, "pmCellAlloc() set ->conceptsRead correctly");
+        ok(cell->config == NULL, "pmCellpAlloc() set ->config to NULL");
+        ok(cell->analysis != NULL &&
+           psMemCheckMetadata(cell->analysis), "pmCellAlloc() set ->analysis correctly");
+        ok(cell->readouts != NULL &&
+           psMemCheckArray(cell->readouts), "pmCellAlloc() set ->readouts correctly");
+        ok(cell->parent == chip, "pmCellAlloc() set ->parent correctly");
+        ok(cell->process == true, "pmCellAlloc() set ->process correctly");
+        ok(cell->file_exists == false, "pmCellAlloc() set ->file_exists correctly");
+        ok(cell->data_exists == false, "pmCellAlloc() set ->data_exists correctly");
+        ok(cell->hdu == NULL, "pmCellAlloc() set ->hdu to NULL");
+        ok(cell->wrote_phu == false, "pmCellAlloc() set ->wrote_phu correctly");
+        psFree(camera);
+        psFree(fpa);
+        psFree(chip);
+        psFree(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Populate the pmCell struct with real data to ensure they were
+    // psFree()'ed correctly.
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL, NULL);
+        psFree(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // test pmCellFreeReadouts()
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL, NULL);
+        pmCellFreeReadouts(cell);
+        ok(cell->readouts->n == 0, "pmCellFreeReadouts() correctly set cell->readouts->n to 0");
+        psFree(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks (pmCellFreeReadouts)");
+    }
+
+}
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.  We do this to ensure that the data is
+later being psFree()'ed correctly.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+
+void testReadoutAlloc(void)
+{
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+        pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+        pmReadout *readout = pmReadoutAlloc(cell);
+        ok(readout != NULL, "pmReadoutAlloc() returned non-NULL");
+        ok(readout->col0 == 0, "pmReadoutAlloc() set ->col0 correctly");
+        ok(readout->row0 == 0, "pmReadoutAlloc() set ->row0 correctly");
+        ok(readout->image == NULL, "pmReadoutAlloc() set ->image correctly");
+        ok(readout->mask == NULL, "pmReadoutAlloc() set ->mask correctly");
+        ok(readout->weight == NULL, "pmReadoutAlloc() set ->weight correctly");
+        ok(readout->bias != NULL &&
+           psMemCheckList(readout->bias), "pmReadoutAlloc() set ->bias correctly");
+        ok(readout->analysis != NULL &&
+           psMemCheckMetadata(readout->analysis), "pmReadoutAlloc() set ->analysis correctly");
+        ok(readout->parent == cell, "pmReadoutAlloc() set ->parent correctly");
+        ok(readout->process == true, "pmReadoutAlloc() set ->process correctly");
+        ok(readout->file_exists == false, "pmReadoutAlloc() set ->file_exists correctly");
+        ok(readout->data_exists == false, "pmReadoutAlloc() set ->data_exists correctly");
+        psFree(camera);
+        psFree(fpa);
+        psFree(chip);
+        psFree(cell);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Populate the pmReadout struct with real data to ensure they were
+    // psFree()'ed correctly.
+    {
+        psMemId id = psMemGetId();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        psFree(readout);
+        // XXX: The pmReadout->bias list is not being free'ed correctly.
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+/*
+    {
+        psMemId id = psMemGetId();
+        pmReadout *readout = pmReadoutAlloc(NULL);
+        readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+        readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+            psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+            psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        }
+        psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+        return(readout);
+    }
+*/
+}
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(56);
+
+    testFPAAlloc();
+    testChipAlloc();
+    testCellAlloc();
+    testReadoutAlloc();
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmAstrometryWCS.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmAstrometryWCS.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmAstrometryWCS.c	(revision 22158)
@@ -0,0 +1,151 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+int main (void)
+{
+    plan_tests(33);
+
+    note("pmAstrometryWCS tests");
+
+    {
+        note("test pmAstromReadWCS");
+        psMemId id = psMemGetId();
+
+        // construct a header with a simple set of WCS values
+        // convert to pmFPA components and check
+
+        psMetadata *header = psMetadataAlloc();
+
+        psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE1", PS_META_REPLACE, "", "RA---TAN");
+        psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE2", PS_META_REPLACE, "", "DEC--TAN");
+
+        // center coords (R,D)
+        psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL1", PS_META_REPLACE, "", 0.0);
+        psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL2", PS_META_REPLACE, "", 0.0);
+
+        // center coords (X,Y)
+        psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX1", PS_META_REPLACE, "", 0.0);
+        psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX2", PS_META_REPLACE, "", 0.0);
+
+        // degrees per pixel
+        psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT1",  PS_META_REPLACE, "", 1.0/3600.0);
+        psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT2",  PS_META_REPLACE, "", 1.0/3600.0);
+
+        // rotation matrix
+        psMetadataAddF32 (header, PS_LIST_TAIL, "PC001001", PS_META_REPLACE, "", 1.0);
+        psMetadataAddF32 (header, PS_LIST_TAIL, "PC001002", PS_META_REPLACE, "", 0.0);
+        psMetadataAddF32 (header, PS_LIST_TAIL, "PC002001", PS_META_REPLACE, "", 0.0);
+        psMetadataAddF32 (header, PS_LIST_TAIL, "PC002002", PS_META_REPLACE, "", 1.0);
+
+        pmFPA *fpa = pmFPAAlloc (NULL);
+        pmChip *chip = pmChipAlloc (NULL, "test");
+
+        // toFPA carries pixel scale (microns per pixel)
+        // toSky carries plate scale (radians per micron)
+        bool status = pmAstromReadWCS (fpa, chip, header, 10.0);
+        ok (status, "converted WCS keywords to FPA astrometry");
+        skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+        ok(fpa->toSky->type == PS_PROJ_TAN, "correct projection (TAN)");
+
+        // make these tests double
+        ok_float(fpa->toSky->R*PS_DEG_RAD, 0.0, "projection center RA %f", fpa->toSky->R*PS_DEG_RAD);
+        ok_float(fpa->toSky->R*PS_DEG_RAD, 0.0, "projection center DEC %f", fpa->toSky->R*PS_DEG_RAD);
+
+        ok_float(fpa->toSky->Xs, PM_RAD_DEG/3600.0/10.0, "projection X scale %f", fpa->toSky->Xs);
+        ok_float(fpa->toSky->Ys, PM_RAD_DEG/3600.0/10.0, "projection X scale %f", fpa->toSky->Ys);
+
+        ok_float(fpa->toTPA->x->coeff[1][0], 1.0, "TP scale (unity): %f", fpa->toTPA->x->coeff[1][0]);
+        ok_float(fpa->toTPA->y->coeff[0][1], 1.0, "TP scale (unity): %f", fpa->toTPA->x->coeff[1][0]);
+
+        ok_float(chip->toFPA->x->coeff[0][0], 0.0, "ref pixel X: %f", chip->toFPA->x->coeff[0][0]);
+        ok_float(chip->toFPA->y->coeff[0][0], 0.0, "ref pixel Y: %f", chip->toFPA->y->coeff[0][0]);
+
+        ok_float(chip->toFPA->x->coeff[1][0], 10.0, "CD1_1: %f", chip->toFPA->x->coeff[1][0]);
+        ok_float(chip->toFPA->x->coeff[0][1], 0.0, "CD1_2: %f", chip->toFPA->x->coeff[0][1]);
+        ok_float(chip->toFPA->y->coeff[1][0], 0.0, "CD2_1: %f", chip->toFPA->y->coeff[1][0]);
+        ok_float(chip->toFPA->y->coeff[0][1], 10.0, "CD2_2: %f", chip->toFPA->y->coeff[0][1]);
+
+        psFree (fpa);
+        psFree (chip);
+        psFree (header);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+    }
+
+    {
+        note("test pmAstromReadWCS");
+        psMemId id = psMemGetId();
+
+        // construct a header with a simple set of WCS values
+        // convert to pmFPA components and check
+
+        psMetadata *header = psMetadataAlloc();
+
+        psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE1", PS_META_REPLACE, "", "RA---TAN");
+        psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE2", PS_META_REPLACE, "", "DEC--TAN");
+
+        // center coords (R,D)
+        psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL1", PS_META_REPLACE, "", 0.0);
+        psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL2", PS_META_REPLACE, "", 0.0);
+
+        // center coords (X,Y)
+        psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX1", PS_META_REPLACE, "", 10.0);
+        psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX2", PS_META_REPLACE, "", 10.0);
+
+        // degrees per pixel
+        psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT1",  PS_META_REPLACE, "", 1.0/3600.0);
+        psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT2",  PS_META_REPLACE, "", 1.0/3600.0);
+
+        // rotation matrix
+        psMetadataAddF32 (header, PS_LIST_TAIL, "PC001001", PS_META_REPLACE, "", 1.0);
+        psMetadataAddF32 (header, PS_LIST_TAIL, "PC001002", PS_META_REPLACE, "", 0.0);
+        psMetadataAddF32 (header, PS_LIST_TAIL, "PC002001", PS_META_REPLACE, "", 0.0);
+        psMetadataAddF32 (header, PS_LIST_TAIL, "PC002002", PS_META_REPLACE, "", 1.0);
+
+        pmFPA *fpa = pmFPAAlloc (NULL);
+        pmChip *chip = pmChipAlloc (NULL, "test");
+
+        // toFPA carries pixel scale (pixels per micron)
+        // toTPA carries plate scale (microns per arcsecond)
+        bool status = pmAstromReadWCS (fpa, chip, header, 10.0);
+        ok (status, "converted WCS keywords to FPA astrometry");
+        skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+        ok(fpa->toSky->type == PS_PROJ_TAN, "correct projection (TAN)");
+
+        // make these tests double
+        ok_float(fpa->toSky->R*PS_DEG_RAD, 0.0, "projection center RA %f", fpa->toSky->R*PS_DEG_RAD);
+        ok_float(fpa->toSky->R*PS_DEG_RAD, 0.0, "projection center DEC %f", fpa->toSky->R*PS_DEG_RAD);
+
+        ok_float(fpa->toSky->Xs, PM_RAD_DEG/3600.0/10.0, "projection X scale %f", fpa->toSky->Xs);
+        ok_float(fpa->toSky->Ys, PM_RAD_DEG/3600.0/10.0, "projection X scale %f", fpa->toSky->Ys);
+
+        ok_float(fpa->toTPA->x->coeff[1][0], 1.0, "TP scale (unity): %f", fpa->toTPA->x->coeff[1][0]);
+        ok_float(fpa->toTPA->y->coeff[0][1], 1.0, "TP scale (unity): %f", fpa->toTPA->x->coeff[1][0]);
+
+        ok_float(chip->toFPA->x->coeff[0][0], -100.0, "ref pixel X: %f", chip->toFPA->x->coeff[0][0]);
+        ok_float(chip->toFPA->y->coeff[0][0], -100.0, "ref pixel Y: %f", chip->toFPA->y->coeff[0][0]);
+
+        ok_float(chip->toFPA->x->coeff[1][0], 10.0, "CD1_1: %f", chip->toFPA->x->coeff[1][0]);
+        ok_float(chip->toFPA->x->coeff[0][1], 0.0, "CD1_2: %f", chip->toFPA->x->coeff[0][1]);
+        ok_float(chip->toFPA->y->coeff[1][0], 0.0, "CD2_1: %f", chip->toFPA->y->coeff[1][0]);
+        ok_float(chip->toFPA->y->coeff[0][1], 10.0, "CD2_2: %f", chip->toFPA->y->coeff[0][1]);
+
+        psFree (fpa);
+        psFree (chip);
+        psFree (header);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+    }
+
+    return exit_status();
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmAstrometryWCS_DVO.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmAstrometryWCS_DVO.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmAstrometryWCS_DVO.c	(revision 22158)
@@ -0,0 +1,528 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+# if (HAVE_KAPA)
+    # include "dvo.h"
+
+    psMetadata *WriteCoordsToHeader (Coords *coords);
+void test1(); // basic TAN projection,
+void test2(); // small rotation
+void test3(); // 2nd order term
+
+void test1in(); // basic TAN projection,
+void test2in(); // small rotation
+void test3in(); // 2nd order term
+
+void testA(); // alloc test
+void testB(); // alloc test
+
+int main (void)
+{
+    plan_tests(992);
+
+    note("pmAstrometryWCS tests compared with DVO coords routines");
+    note("this file tests pmAstromWCS <-> Header representations");
+
+    test1in();
+    test2in();
+    test3in();
+
+    test1();
+    test2();
+    test3();
+    return exit_status();
+}
+
+void test3in()
+{
+    note("test pmAstromWCStoHeader");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style coordinate system
+    Coords coords;
+    strcpy (coords.ctype, "RA---TAN");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 0.0;
+    coords.crpix2 = 0.0;
+    coords.cdelt1 = 1.0/3600;
+    coords.cdelt2 = 1.0/3600;
+    coords.pc1_1  = 1.0;
+    coords.pc1_2  = 0.0;
+    coords.pc2_1  = 0.0;
+    coords.pc2_2  = 1.0;
+    coords.Npolyterms = 2;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+    coords.polyterms[0][0] = 0.01; // L vs X^2
+    coords.polyterms[2][1] = 0.01; // M vs Y^2
+
+    psMetadata *header1 = WriteCoordsToHeader(&coords);
+    pmAstromWCS *wcs1 = pmAstromWCSfromHeader(header1);
+    skip_start (wcs1 == NULL, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psMetadata *header2 = psMetadataAlloc();
+    pmAstromWCStoHeader(header2, wcs1);
+    pmAstromWCS *wcs2 = pmAstromWCSfromHeader(header2);
+
+    ok (wcs2 != NULL, "converted WCS keywords to WCS astrometry");
+    skip_start (wcs2 == NULL, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psSphere *sky1 = psSphereAlloc();
+    psSphere *sky2 = psSphereAlloc();
+    psPlane *chip = psPlaneAlloc();
+
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            chip->x = x;
+            chip->y = y;
+            pmAstromWCStoSky (sky1, wcs1, chip);
+            pmAstromWCStoSky (sky2, wcs2, chip);
+            while (sky1->r > 2*M_PI)
+                sky1->r -= 2*M_PI;
+            while (sky1->r <      0)
+                sky1->r += 2*M_PI;
+            while (sky2->r > 2*M_PI)
+                sky2->r -= 2*M_PI;
+            while (sky2->r <      0)
+                sky2->r += 2*M_PI;
+
+            ok_float(sky1->r*PS_DEG_RAD, sky2->r*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", sky1->r*PS_DEG_RAD, sky2->r*PS_DEG_RAD, sky1->r*PS_DEG_RAD - sky2->r*PS_DEG_RAD);
+            ok_float(sky1->d*PS_DEG_RAD, sky2->d*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", sky1->d*PS_DEG_RAD, sky2->d*PS_DEG_RAD, sky1->d*PS_DEG_RAD - sky2->d*PS_DEG_RAD);
+        }
+    }
+    psFree (sky1);
+    psFree (sky2);
+    psFree (chip);
+
+    skip_end();
+    psFree (wcs2);
+    psFree (header2);
+
+    skip_end();
+    psFree (wcs1);
+    psFree (header1);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+void test2in()
+{
+    note("test pmAstromWCStoHeader");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style coordinate system
+    Coords coords;
+    strcpy (coords.ctype, "RA---TAN");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 0.0;
+    coords.crpix2 = 0.0;
+    coords.cdelt1 = 1.0/3600;
+    coords.cdelt2 = 1.0/3600;
+    coords.pc1_1  = 0.9;
+    coords.pc1_2  = -0.1;
+    coords.pc2_1  = 0.1;
+    coords.pc2_2  = 0.9;
+    coords.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+
+    psMetadata *header1 = WriteCoordsToHeader(&coords);
+    pmAstromWCS *wcs1 = pmAstromWCSfromHeader(header1);
+    skip_start (wcs1 == NULL, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psMetadata *header2 = psMetadataAlloc();
+    pmAstromWCStoHeader(header2, wcs1);
+    pmAstromWCS *wcs2 = pmAstromWCSfromHeader(header2);
+
+    ok (wcs2 != NULL, "converted WCS keywords to WCS astrometry");
+    skip_start (wcs2 == NULL, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psSphere *sky1 = psSphereAlloc();
+    psSphere *sky2 = psSphereAlloc();
+    psPlane *chip = psPlaneAlloc();
+
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            chip->x = x;
+            chip->y = y;
+            pmAstromWCStoSky (sky1, wcs1, chip);
+            pmAstromWCStoSky (sky2, wcs2, chip);
+            while (sky1->r > 2*M_PI)
+                sky1->r -= 2*M_PI;
+            while (sky1->r <      0)
+                sky1->r += 2*M_PI;
+            while (sky2->r > 2*M_PI)
+                sky2->r -= 2*M_PI;
+            while (sky2->r <      0)
+                sky2->r += 2*M_PI;
+
+            ok_float(sky1->r*PS_DEG_RAD, sky2->r*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", sky1->r*PS_DEG_RAD, sky2->r*PS_DEG_RAD, sky1->r*PS_DEG_RAD - sky2->r*PS_DEG_RAD);
+            ok_float(sky1->d*PS_DEG_RAD, sky2->d*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", sky1->d*PS_DEG_RAD, sky2->d*PS_DEG_RAD, sky1->d*PS_DEG_RAD - sky2->d*PS_DEG_RAD);
+        }
+    }
+    psFree (sky1);
+    psFree (sky2);
+    psFree (chip);
+
+    skip_end();
+    psFree (wcs2);
+    psFree (header2);
+
+    skip_end();
+    psFree (wcs1);
+    psFree (header1);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+void test1in()
+{
+    note("test pmAstromWCStoHeader");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style coordinate system
+    Coords coords;
+    strcpy (coords.ctype, "RA---TAN");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 0.0;
+    coords.crpix2 = 0.0;
+    coords.cdelt1 = 1.0/3600;
+    coords.cdelt2 = 1.0/3600;
+    coords.pc1_1  = 1.0;
+    coords.pc1_2  = 0.0;
+    coords.pc2_1  = 0.0;
+    coords.pc2_2  = 1.0;
+    coords.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+
+    psMetadata *header1 = WriteCoordsToHeader(&coords);
+    pmAstromWCS *wcs1 = pmAstromWCSfromHeader(header1);
+    skip_start (wcs1 == NULL, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psMetadata *header2 = psMetadataAlloc();
+    pmAstromWCStoHeader(header2, wcs1);
+    pmAstromWCS *wcs2 = pmAstromWCSfromHeader(header2);
+
+    ok (wcs2 != NULL, "converted WCS keywords to WCS astrometry");
+    skip_start (wcs2 == NULL, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psSphere *sky1 = psSphereAlloc();
+    psSphere *sky2 = psSphereAlloc();
+    psPlane *chip = psPlaneAlloc();
+
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            chip->x = x;
+            chip->y = y;
+            pmAstromWCStoSky (sky1, wcs1, chip);
+            pmAstromWCStoSky (sky2, wcs2, chip);
+            while (sky1->r > 2*M_PI)
+                sky1->r -= 2*M_PI;
+            while (sky1->r <      0)
+                sky1->r += 2*M_PI;
+            while (sky2->r > 2*M_PI)
+                sky2->r -= 2*M_PI;
+            while (sky2->r <      0)
+                sky2->r += 2*M_PI;
+
+            ok_float(sky1->r*PS_DEG_RAD, sky2->r*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", sky1->r*PS_DEG_RAD, sky2->r*PS_DEG_RAD, sky1->r*PS_DEG_RAD - sky2->r*PS_DEG_RAD);
+            ok_float(sky1->d*PS_DEG_RAD, sky2->d*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", sky1->d*PS_DEG_RAD, sky2->d*PS_DEG_RAD, sky2->d*PS_DEG_RAD - sky2->d*PS_DEG_RAD);
+        }
+    }
+    psFree (sky1);
+    psFree (sky2);
+    psFree (chip);
+
+    skip_end();
+    psFree (wcs2);
+    psFree (header2);
+
+    skip_end();
+    psFree (wcs1);
+    psFree (header1);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+void test3 ()
+{
+    note("test pmAstromWCSfromHeader ");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style coordinate system
+    Coords coords;
+    strcpy (coords.ctype, "RA---TAN");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 0.0;
+    coords.crpix2 = 0.0;
+    coords.cdelt1 = 1.0/3600;
+    coords.cdelt2 = 1.0/3600;
+    coords.pc1_1  = 1.0;
+    coords.pc1_2  = 0.0;
+    coords.pc2_1  = 0.0;
+    coords.pc2_2  = 1.0;
+    coords.Npolyterms = 2;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+    coords.polyterms[0][0] = 0.01; // L vs X^2
+    coords.polyterms[2][1] = 0.01; // M vs Y^2
+
+    psMetadata *header = WriteCoordsToHeader (&coords);
+    pmAstromWCS *wcs = pmAstromWCSfromHeader (header);
+
+    ok (wcs != NULL, "converted WCS keywords to WCS astrometry");
+    skip_start (wcs == NULL, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psSphere *sky = psSphereAlloc();
+    psPlane *chip = psPlaneAlloc();
+
+    double rDVO, dDVO;
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            XY_to_RD (&rDVO, &dDVO, x, y, &coords);
+            chip->x = x;
+            chip->y = y;
+            pmAstromWCStoSky (sky, wcs, chip);
+            while (sky->r > 2*M_PI)
+                sky->r -= 2*M_PI;
+            while (sky->r <      0)
+                sky->r += 2*M_PI;
+
+            ok_float(rDVO, sky->r*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", rDVO, sky->r*PS_DEG_RAD, rDVO - sky->r*PS_DEG_RAD);
+            ok_float(dDVO, sky->d*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", dDVO, sky->d*PS_DEG_RAD, dDVO - sky->d*PS_DEG_RAD);
+        }
+    }
+    psFree (sky);
+    psFree (chip);
+
+    skip_end();
+    psFree (wcs);
+    psFree (header);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+void test2 ()
+{
+    note("test pmAstromWCSfromHeader");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style coordinate system
+    Coords coords;
+    strcpy (coords.ctype, "RA---TAN");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 0.0;
+    coords.crpix2 = 0.0;
+    coords.cdelt1 = 1.0/3600;
+    coords.cdelt2 = 1.0/3600;
+    coords.pc1_1  = 0.9;
+    coords.pc1_2  = -0.1;
+    coords.pc2_1  = 0.1;
+    coords.pc2_2  = 0.9;
+    coords.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+
+    psMetadata *header = WriteCoordsToHeader (&coords);
+    pmAstromWCS *wcs = pmAstromWCSfromHeader (header);
+
+    ok (wcs != NULL, "converted WCS keywords to WCS astrometry");
+    skip_start (wcs == NULL, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psSphere *sky = psSphereAlloc();
+    psPlane *chip = psPlaneAlloc();
+
+    double rDVO, dDVO;
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            XY_to_RD (&rDVO, &dDVO, x, y, &coords);
+            chip->x = x;
+            chip->y = y;
+            pmAstromWCStoSky (sky, wcs, chip);
+            while (sky->r > 2*M_PI)
+                sky->r -= 2*M_PI;
+            while (sky->r <      0)
+                sky->r += 2*M_PI;
+
+            ok_float(rDVO, sky->r*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", rDVO, sky->r*PS_DEG_RAD, rDVO - sky->r*PS_DEG_RAD);
+            ok_float(dDVO, sky->d*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", dDVO, sky->d*PS_DEG_RAD, dDVO - sky->d*PS_DEG_RAD);
+        }
+    }
+    psFree (sky);
+    psFree (chip);
+
+    skip_end();
+    psFree (wcs);
+    psFree (header);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+void test1()
+{
+    note("test pmAstromWCSfromHeader");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style coordinate system
+    Coords coords;
+    strcpy (coords.ctype, "RA---TAN");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 0.0;
+    coords.crpix2 = 0.0;
+    coords.cdelt1 = 1.0/3600;
+    coords.cdelt2 = 1.0/3600;
+    coords.pc1_1  = 1.0;
+    coords.pc1_2  = 0.0;
+    coords.pc2_1  = 0.0;
+    coords.pc2_2  = 1.0;
+    coords.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+
+    psMetadata *header = WriteCoordsToHeader (&coords);
+    pmAstromWCS *wcs = pmAstromWCSfromHeader (header);
+
+    ok (wcs != NULL, "converted WCS keywords to WCS astrometry");
+    skip_start (wcs == NULL, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psSphere *sky = psSphereAlloc();
+    psPlane *chip = psPlaneAlloc();
+
+    double rDVO, dDVO;
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            XY_to_RD (&rDVO, &dDVO, x, y, &coords);
+            chip->x = x;
+            chip->y = y;
+            pmAstromWCStoSky (sky, wcs, chip);
+            while (sky->r > 2*M_PI)
+                sky->r -= 2*M_PI;
+            while (sky->r <      0)
+                sky->r += 2*M_PI;
+
+            ok_float(rDVO, sky->r*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", rDVO, sky->r*PS_DEG_RAD, rDVO - sky->r*PS_DEG_RAD);
+            ok_float(dDVO, sky->d*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", dDVO, sky->d*PS_DEG_RAD, dDVO - sky->d*PS_DEG_RAD);
+        }
+    }
+    psFree (sky);
+    psFree (chip);
+
+    skip_end();
+    psFree (wcs);
+    psFree (header);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+void testA()
+{
+    note("test coord allocs");
+    psMemId id = psMemGetId();
+
+    psPlane *chip = psPlaneAlloc();
+    psFree (chip);
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+void testB()
+{
+    note("test coord allocs");
+    psMemId id = psMemGetId();
+
+    psSphere *sky = psSphereAlloc();
+    psFree (sky);
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+psMetadata *WriteCoordsToHeader (Coords *coords)
+{
+
+    char name[16];
+
+    // construct a header using coords as the input
+    psMetadata *header = psMetadataAlloc();
+
+    sprintf (name, "RA--%s", &coords[0].ctype[4]);
+    psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE1", PS_META_REPLACE, "", name);
+    sprintf (name, "DEC-%s", &coords[0].ctype[4]);
+    psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE2", PS_META_REPLACE, "", name);
+
+    // center coords (R,D)
+    psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL1", PS_META_REPLACE, "", coords[0].crval1);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL2", PS_META_REPLACE, "", coords[0].crval2);
+
+    // center coords (X,Y)
+    psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX1", PS_META_REPLACE, "", coords[0].crpix1);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX2", PS_META_REPLACE, "", coords[0].crpix2);
+
+    // degrees per pixel
+    psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT1",  PS_META_REPLACE, "", coords[0].cdelt1);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT2",  PS_META_REPLACE, "", coords[0].cdelt2);
+
+    // rotation matrix
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PC001001", PS_META_REPLACE, "", coords[0].pc1_1);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PC001002", PS_META_REPLACE, "", coords[0].pc1_2);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PC002001", PS_META_REPLACE, "", coords[0].pc2_1);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PC002002", PS_META_REPLACE, "", coords[0].pc2_2);
+
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X2Y0", PS_META_REPLACE, "", coords[0].polyterms[0][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X1Y1", PS_META_REPLACE, "", coords[0].polyterms[1][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X0Y2", PS_META_REPLACE, "", coords[0].polyterms[2][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X2Y0", PS_META_REPLACE, "", coords[0].polyterms[0][1]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X1Y1", PS_META_REPLACE, "", coords[0].polyterms[1][1]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X0Y2", PS_META_REPLACE, "", coords[0].polyterms[2][1]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X3Y0", PS_META_REPLACE, "", coords[0].polyterms[3][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X2Y1", PS_META_REPLACE, "", coords[0].polyterms[4][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X1Y2", PS_META_REPLACE, "", coords[0].polyterms[5][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X0Y3", PS_META_REPLACE, "", coords[0].polyterms[6][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X3Y0", PS_META_REPLACE, "", coords[0].polyterms[3][1]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X2Y1", PS_META_REPLACE, "", coords[0].polyterms[4][1]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X1Y2", PS_META_REPLACE, "", coords[0].polyterms[5][1]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X0Y3", PS_META_REPLACE, "", coords[0].polyterms[6][1]);
+
+    psMetadataAddS32 (header, PS_LIST_TAIL, "NPLYTERM", PS_META_REPLACE, "", coords[0].Npolyterms);
+
+    return header;
+}
+
+# else
+
+    int main (void)
+{
+    plan_tests(2);
+
+    ok(true, "Skipping tests: (libdvo not available)");
+    note("pmAstrometryWCS tests compared with DVO coords routines : SKIPPED (libdvo not available)");
+
+    return exit_status();
+}
+
+# endif
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmAstrometryWCS_DVO2.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmAstrometryWCS_DVO2.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmAstrometryWCS_DVO2.c	(revision 22158)
@@ -0,0 +1,630 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+# if (HAVE_KAPA)
+    # include "dvo.h"
+
+    psMetadata *WriteCoordsToHeader (Coords *coords);
+void test1(); // basic TAN projection,
+void test2(); // small rotation
+void test3(); // 2nd order term
+void test1x(); // basic TAN projection with central offset
+void test2x(); // small rotation with central offset
+void test3x(); // 2nd order term with central offset
+void test3inv(); // 2nd order term with central offset
+
+int main (void)
+{
+    plan_tests(1483);
+
+    note("pmAstromReadWCS tests compared with DVO coords routines");
+
+    test1();
+    test2();
+    test3();
+    test1x();
+    test2x();
+    test3x();
+    test3inv();
+
+    return exit_status();
+}
+
+void test1()
+{
+    note("test pmAstromReadWCS");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style coordinate system
+    Coords coords;
+    strcpy (coords.ctype, "RA---TAN");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 0.0;
+    coords.crpix2 = 0.0;
+    coords.cdelt1 = 1.0/3600;
+    coords.cdelt2 = 1.0/3600;
+    coords.pc1_1  = 1.0;
+    coords.pc1_2  = 0.0;
+    coords.pc2_1  = 0.0;
+    coords.pc2_2  = 1.0;
+    coords.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+
+    psMetadata *header = WriteCoordsToHeader (&coords);
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadWCS (fpa, chip, header, PM_RAD_DEG*10.0/3600.0);
+    ok (status, "converted WCS keywords to WCS astrometry");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psPlane *onChip = psPlaneAlloc();
+    psPlane *onFPA = psPlaneAlloc();
+    psPlane *onTPA = psPlaneAlloc();
+    psSphere *onSky = psSphereAlloc();
+
+    double rDVO, dDVO;
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            XY_to_RD (&rDVO, &dDVO, x, y, &coords);
+
+            onChip->x = x;
+            onChip->y = y;
+
+            psPlaneTransformApply (onFPA, chip->toFPA, onChip);
+            psPlaneTransformApply (onTPA, fpa->toTPA, onFPA);
+            psDeproject (onSky, onTPA, fpa->toSky);
+
+            while (onSky->r > 2*M_PI)
+                onSky->r -= 2*M_PI;
+            while (onSky->r <      0)
+                onSky->r += 2*M_PI;
+
+            ok_float(rDVO, onSky->r*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", rDVO, onSky->r*PS_DEG_RAD, rDVO - onSky->r*PS_DEG_RAD);
+            ok_float(dDVO, onSky->d*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", dDVO, onSky->d*PS_DEG_RAD, dDVO - onSky->d*PS_DEG_RAD);
+        }
+    }
+    psFree (onSky);
+    psFree (onTPA);
+    psFree (onFPA);
+    psFree (onChip);
+
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+    psFree (header);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+void test2()
+{
+    note("test pmAstromReadWCS");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style coordinate system
+    Coords coords;
+    strcpy (coords.ctype, "RA---TAN");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 0.0;
+    coords.crpix2 = 0.0;
+    coords.cdelt1 = 1.0/3600;
+    coords.cdelt2 = 1.0/3600;
+    coords.pc1_1  = 0.9;
+    coords.pc1_2  = 0.1;
+    coords.pc2_1  =-0.1;
+    coords.pc2_2  = 0.9;
+    coords.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+
+    psMetadata *header = WriteCoordsToHeader (&coords);
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadWCS (fpa, chip, header, PM_RAD_DEG*10.0/3600.0);
+    ok (status, "converted WCS keywords to WCS astrometry");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psPlane *onChip = psPlaneAlloc();
+    psPlane *onFPA = psPlaneAlloc();
+    psPlane *onTPA = psPlaneAlloc();
+    psSphere *onSky = psSphereAlloc();
+
+    double rDVO, dDVO;
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            XY_to_RD (&rDVO, &dDVO, x, y, &coords);
+
+            onChip->x = x;
+            onChip->y = y;
+
+            psPlaneTransformApply (onFPA, chip->toFPA, onChip);
+            psPlaneTransformApply (onTPA, fpa->toTPA, onFPA);
+            psDeproject (onSky, onTPA, fpa->toSky);
+
+            while (onSky->r > 2*M_PI)
+                onSky->r -= 2*M_PI;
+            while (onSky->r <      0)
+                onSky->r += 2*M_PI;
+
+            ok_float(rDVO, onSky->r*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", rDVO, onSky->r*PS_DEG_RAD, rDVO - onSky->r*PS_DEG_RAD);
+            ok_float(dDVO, onSky->d*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", dDVO, onSky->d*PS_DEG_RAD, dDVO - onSky->d*PS_DEG_RAD);
+        }
+    }
+    psFree (onSky);
+    psFree (onTPA);
+    psFree (onFPA);
+    psFree (onChip);
+
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+    psFree (header);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+void test3()
+{
+    note("test pmAstromReadWCS");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style coordinate system
+    Coords coords;
+    strcpy (coords.ctype, "RA---TAN");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 0.0;
+    coords.crpix2 = 0.0;
+    coords.cdelt1 = 1.0/3600;
+    coords.cdelt2 = 1.0/3600;
+    coords.pc1_1  = 1.0;
+    coords.pc1_2  = 0.0;
+    coords.pc2_1  = 0.0;
+    coords.pc2_2  = 1.0;
+    coords.Npolyterms = 2;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+    coords.polyterms[0][0] = 0.01; // L vs X^2
+    coords.polyterms[2][1] = 0.01; // M vs Y^2
+
+
+    psMetadata *header = WriteCoordsToHeader (&coords);
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadWCS (fpa, chip, header, PM_RAD_DEG*10.0/3600.0);
+    ok (status, "converted WCS keywords to WCS astrometry");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psPlane *onChip = psPlaneAlloc();
+    psPlane *onFPA = psPlaneAlloc();
+    psPlane *onTPA = psPlaneAlloc();
+    psSphere *onSky = psSphereAlloc();
+
+    double rDVO, dDVO;
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            XY_to_RD (&rDVO, &dDVO, x, y, &coords);
+
+            onChip->x = x;
+            onChip->y = y;
+
+            psPlaneTransformApply (onFPA, chip->toFPA, onChip);
+            psPlaneTransformApply (onTPA, fpa->toTPA, onFPA);
+            psDeproject (onSky, onTPA, fpa->toSky);
+
+            while (onSky->r > 2*M_PI)
+                onSky->r -= 2*M_PI;
+            while (onSky->r <      0)
+                onSky->r += 2*M_PI;
+
+            ok_float(rDVO, onSky->r*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", rDVO, onSky->r*PS_DEG_RAD, rDVO - onSky->r*PS_DEG_RAD);
+            ok_float(dDVO, onSky->d*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", dDVO, onSky->d*PS_DEG_RAD, dDVO - onSky->d*PS_DEG_RAD);
+        }
+    }
+    psFree (onSky);
+    psFree (onTPA);
+    psFree (onFPA);
+    psFree (onChip);
+
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+    psFree (header);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+void test1x()
+{
+    note("test pmAstromReadWCS");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style coordinate system
+    Coords coords;
+    strcpy (coords.ctype, "RA---TAN");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = +50.0;
+    coords.crpix2 = -20.0;
+    coords.cdelt1 = 1.0/3600;
+    coords.cdelt2 = 1.0/3600;
+    coords.pc1_1  = 1.0;
+    coords.pc1_2  = 0.0;
+    coords.pc2_1  = 0.0;
+    coords.pc2_2  = 1.0;
+    coords.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+
+    psMetadata *header = WriteCoordsToHeader (&coords);
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadWCS (fpa, chip, header, PM_RAD_DEG*10.0/3600.0);
+    ok (status, "converted WCS keywords to WCS astrometry");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psPlane *onChip = psPlaneAlloc();
+    psPlane *onFPA = psPlaneAlloc();
+    psPlane *onTPA = psPlaneAlloc();
+    psSphere *onSky = psSphereAlloc();
+
+    double rDVO, dDVO;
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            XY_to_RD (&rDVO, &dDVO, x, y, &coords);
+
+            onChip->x = x;
+            onChip->y = y;
+
+            psPlaneTransformApply (onFPA, chip->toFPA, onChip);
+            psPlaneTransformApply (onTPA, fpa->toTPA, onFPA);
+            psDeproject (onSky, onTPA, fpa->toSky);
+
+            while (onSky->r > 2*M_PI)
+                onSky->r -= 2*M_PI;
+            while (onSky->r <      0)
+                onSky->r += 2*M_PI;
+
+            ok_float(rDVO, onSky->r*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", rDVO, onSky->r*PS_DEG_RAD, rDVO - onSky->r*PS_DEG_RAD);
+            ok_float(dDVO, onSky->d*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", dDVO, onSky->d*PS_DEG_RAD, dDVO - onSky->d*PS_DEG_RAD);
+        }
+    }
+    psFree (onSky);
+    psFree (onTPA);
+    psFree (onFPA);
+    psFree (onChip);
+
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+    psFree (header);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+void test2x()
+{
+    note("test pmAstromReadWCS");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style coordinate system
+    Coords coords;
+    strcpy (coords.ctype, "RA---TAN");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = +50.0;
+    coords.crpix2 = -20.0;
+    coords.cdelt1 = 1.0/3600;
+    coords.cdelt2 = 1.0/3600;
+    coords.pc1_1  = 0.9;
+    coords.pc1_2  = 0.1;
+    coords.pc2_1  =-0.1;
+    coords.pc2_2  = 0.9;
+    coords.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+
+    psMetadata *header = WriteCoordsToHeader (&coords);
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadWCS (fpa, chip, header, PM_RAD_DEG*10.0/3600.0);
+    ok (status, "converted WCS keywords to WCS astrometry");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psPlane *onChip = psPlaneAlloc();
+    psPlane *onFPA = psPlaneAlloc();
+    psPlane *onTPA = psPlaneAlloc();
+    psSphere *onSky = psSphereAlloc();
+
+    double rDVO, dDVO;
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            XY_to_RD (&rDVO, &dDVO, x, y, &coords);
+
+            onChip->x = x;
+            onChip->y = y;
+
+            psPlaneTransformApply (onFPA, chip->toFPA, onChip);
+            psPlaneTransformApply (onTPA, fpa->toTPA, onFPA);
+            psDeproject (onSky, onTPA, fpa->toSky);
+
+            while (onSky->r > 2*M_PI)
+                onSky->r -= 2*M_PI;
+            while (onSky->r <      0)
+                onSky->r += 2*M_PI;
+
+            ok_float(rDVO, onSky->r*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", rDVO, onSky->r*PS_DEG_RAD, rDVO - onSky->r*PS_DEG_RAD);
+            ok_float(dDVO, onSky->d*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", dDVO, onSky->d*PS_DEG_RAD, dDVO - onSky->d*PS_DEG_RAD);
+        }
+    }
+    psFree (onSky);
+    psFree (onTPA);
+    psFree (onFPA);
+    psFree (onChip);
+
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+    psFree (header);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+void test3x()
+{
+    note("test pmAstromReadWCS");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style coordinate system
+    Coords coords;
+    strcpy (coords.ctype, "RA---TAN");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = +50.0;
+    coords.crpix2 = -20.0;
+    coords.cdelt1 = 1.0/3600;
+    coords.cdelt2 = 1.0/3600;
+    coords.pc1_1  = 1.0;
+    coords.pc1_2  = 0.0;
+    coords.pc2_1  = 0.0;
+    coords.pc2_2  = 1.0;
+    coords.Npolyterms = 2;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+    coords.polyterms[0][0] = 0.01; // L vs X^2
+    coords.polyterms[2][1] = 0.01; // M vs Y^2
+
+
+    psMetadata *header = WriteCoordsToHeader (&coords);
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadWCS (fpa, chip, header, PM_RAD_DEG*10.0/3600.0);
+    ok (status, "converted WCS keywords to WCS astrometry");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psPlane *onChip = psPlaneAlloc();
+    psPlane *onFPA = psPlaneAlloc();
+    psPlane *onTPA = psPlaneAlloc();
+    psSphere *onSky = psSphereAlloc();
+
+    double rDVO, dDVO;
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            XY_to_RD (&rDVO, &dDVO, x, y, &coords);
+
+            onChip->x = x;
+            onChip->y = y;
+
+            psPlaneTransformApply (onFPA, chip->toFPA, onChip);
+            psPlaneTransformApply (onTPA, fpa->toTPA, onFPA);
+            psDeproject (onSky, onTPA, fpa->toSky);
+
+            while (onSky->r > 2*M_PI)
+                onSky->r -= 2*M_PI;
+            while (onSky->r <      0)
+                onSky->r += 2*M_PI;
+
+            ok_float(rDVO, onSky->r*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", rDVO, onSky->r*PS_DEG_RAD, rDVO - onSky->r*PS_DEG_RAD);
+            ok_float(dDVO, onSky->d*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", dDVO, onSky->d*PS_DEG_RAD, dDVO - onSky->d*PS_DEG_RAD);
+        }
+    }
+    psFree (onSky);
+    psFree (onTPA);
+    psFree (onFPA);
+    psFree (onChip);
+
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+    psFree (header);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+void test3inv()
+{
+    note("test the inversion of the non-linear polynomial for toFPA -> fromFPA in pmAstromReadWCS");
+    note("note that the tolerance for these tests are rather loose");
+    note("a 2nd order polynomial is not a great approximate to 1 over a 2nd order polynomial");
+    note("unless the non-linear terms are quite small");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style coordinate system
+    Coords coords;
+    strcpy (coords.ctype, "RA---TAN");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = +50.0;
+    coords.crpix2 = -20.0;
+    coords.cdelt1 = 1.0/3600;
+    coords.cdelt2 = 1.0/3600;
+    coords.pc1_1  = 1.0;
+    coords.pc1_2  = 0.0;
+    coords.pc2_1  = 0.0;
+    coords.pc2_2  = 1.0;
+    coords.Npolyterms = 2;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+    coords.polyterms[0][0] = 0.01; // L vs X^2
+    coords.polyterms[2][1] = 0.01; // M vs Y^2
+
+
+    psMetadata *header = WriteCoordsToHeader (&coords);
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadWCS (fpa, chip, header, PM_RAD_DEG*10.0/3600.0);
+    ok (status, "converted WCS keywords to WCS astrometry");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psPlane *aChip  = psPlaneAlloc();
+    psPlane *aFPA   = psPlaneAlloc();
+    psPlane *aTPA   = psPlaneAlloc();
+    psPlane *bChip  = psPlaneAlloc();
+    psPlane *bFPA   = psPlaneAlloc();
+    psPlane *bTPA   = psPlaneAlloc();
+    psSphere *onSky = psSphereAlloc();
+
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            // convert up to sky
+            aChip->x = x;
+            aChip->y = y;
+
+            psPlaneTransformApply (aFPA, chip->toFPA, aChip);
+            psPlaneTransformApply (aTPA, fpa->toTPA, aFPA);
+            psDeproject (onSky, aTPA, fpa->toSky);
+
+            while (onSky->r > 2*M_PI)
+                onSky->r -= 2*M_PI;
+            while (onSky->r <      0)
+                onSky->r += 2*M_PI;
+
+            psProject (bTPA, onSky, fpa->toSky);
+            psPlaneTransformApply (bFPA, fpa->fromTPA, bTPA);
+            psPlaneTransformApply (bChip, chip->fromFPA, bFPA);
+
+            // calculate appropriate tol values as f(x,y)
+            ok_float_tol(aChip->x, bChip->x, 1.0, "coordinate match: %f vs %f (delta = %f)", aChip->x, bChip->x, aChip->x - bChip->x);
+            ok_float_tol(aChip->y, bChip->y, 1.0, "coordinate match: %f vs %f (delta = %f)", aChip->y, bChip->y, aChip->y - bChip->y);
+
+            ok_float(aFPA->x, bFPA->x, "coordinate match: %f vs %f (delta = %f)", aFPA->x, bFPA->x, aFPA->x - bFPA->x);
+            ok_float(aFPA->y, bFPA->y, "coordinate match: %f vs %f (delta = %f)", aFPA->y, bFPA->y, aFPA->y - bFPA->y);
+
+            // in this example, TPA coordinates are 10 arcsec/mm; the tol. below represent 1nano-arcsec
+            ok_float_tol(aTPA->x, bTPA->x, 1e-10, "coordinate match: %f vs %f (delta = %g)", aTPA->x, bTPA->x, aTPA->x - bTPA->x);
+            ok_float_tol(aTPA->y, bTPA->y, 1e-10, "coordinate match: %f vs %f (delta = %g)", aTPA->y, bTPA->y, aTPA->y - bTPA->y);
+        }
+    }
+    psFree (onSky);
+    psFree (aTPA);
+    psFree (aFPA);
+    psFree (aChip);
+    psFree (bTPA);
+    psFree (bFPA);
+    psFree (bChip);
+
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+    psFree (header);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+psMetadata *WriteCoordsToHeader (Coords *coords)
+{
+
+    char name[16];
+
+    // construct a header using coords as the input
+    psMetadata *header = psMetadataAlloc();
+
+    sprintf (name, "RA--%s", &coords[0].ctype[4]);
+    psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE1", PS_META_REPLACE, "", name);
+    sprintf (name, "DEC-%s", &coords[0].ctype[4]);
+    psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE2", PS_META_REPLACE, "", name);
+
+    // center coords (R,D)
+    psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL1", PS_META_REPLACE, "", coords[0].crval1);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL2", PS_META_REPLACE, "", coords[0].crval2);
+
+    // center coords (X,Y)
+    psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX1", PS_META_REPLACE, "", coords[0].crpix1);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX2", PS_META_REPLACE, "", coords[0].crpix2);
+
+    // degrees per pixel
+    psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT1",  PS_META_REPLACE, "", coords[0].cdelt1);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT2",  PS_META_REPLACE, "", coords[0].cdelt2);
+
+    // rotation matrix
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PC001001", PS_META_REPLACE, "", coords[0].pc1_1);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PC001002", PS_META_REPLACE, "", coords[0].pc1_2);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PC002001", PS_META_REPLACE, "", coords[0].pc2_1);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PC002002", PS_META_REPLACE, "", coords[0].pc2_2);
+
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X2Y0", PS_META_REPLACE, "", coords[0].polyterms[0][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X1Y1", PS_META_REPLACE, "", coords[0].polyterms[1][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X0Y2", PS_META_REPLACE, "", coords[0].polyterms[2][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X2Y0", PS_META_REPLACE, "", coords[0].polyterms[0][1]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X1Y1", PS_META_REPLACE, "", coords[0].polyterms[1][1]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X0Y2", PS_META_REPLACE, "", coords[0].polyterms[2][1]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X3Y0", PS_META_REPLACE, "", coords[0].polyterms[3][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X2Y1", PS_META_REPLACE, "", coords[0].polyterms[4][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X1Y2", PS_META_REPLACE, "", coords[0].polyterms[5][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X0Y3", PS_META_REPLACE, "", coords[0].polyterms[6][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X3Y0", PS_META_REPLACE, "", coords[0].polyterms[3][1]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X2Y1", PS_META_REPLACE, "", coords[0].polyterms[4][1]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X1Y2", PS_META_REPLACE, "", coords[0].polyterms[5][1]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X0Y3", PS_META_REPLACE, "", coords[0].polyterms[6][1]);
+
+    psMetadataAddS32 (header, PS_LIST_TAIL, "NPLYTERM", PS_META_REPLACE, "", coords[0].Npolyterms);
+
+    return header;
+}
+
+# else
+
+    int main (void)
+{
+    plan_tests(2);
+
+    ok(true, "Skipping tests: (libdvo not available)");
+    note("pmAstrometryWCS tests compared with DVO coords routines : SKIPPED (libdvo not available)");
+
+    return exit_status();
+}
+
+# endif
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmAstrometryWCS_DVO3.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmAstrometryWCS_DVO3.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmAstrometryWCS_DVO3.c	(revision 22158)
@@ -0,0 +1,655 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+# if (HAVE_KAPA)
+    # include "dvo.h"
+
+    psMetadata *WriteCoordsToHeader (Coords *coords);
+void test1(); // basic TAN projection,
+void test2(); // small rotation
+void test3(); // 2nd order term
+void test1x(); // basic TAN projection with central offset
+void test2x(); // small rotation with central offset
+void test3x(); // 2nd order term with central offset
+
+int main (void)
+{
+    plan_tests(991);
+
+    note("pmAstromWriteWCS tests compared with DVO coords routines");
+
+    test1();
+    test2();
+    test3();
+    test1x();
+    test2x();
+    test3x();
+
+    return exit_status();
+}
+
+void test1()
+{
+    note("test pmAstromReadWCS");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style coordinate system
+    Coords coords;
+    strcpy (coords.ctype, "RA---TAN");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 0.0;
+    coords.crpix2 = 0.0;
+    coords.cdelt1 = 1.0/3600.0;
+    coords.cdelt2 = 1.0/3600.0;
+    coords.pc1_1  = 1.0;
+    coords.pc1_2  = 0.0;
+    coords.pc2_1  = 0.0;
+    coords.pc2_2  = 1.0;
+    coords.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+
+    psMetadata *header1 = WriteCoordsToHeader (&coords);
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadWCS (fpa, chip, header1, 10.0);
+
+    ok (status, "converted WCS keywords to WCS astrometry");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psMetadata *header2 = psMetadataAlloc();
+    status = pmAstromWriteWCS (header2, fpa, chip, 0.001);
+    pmAstromWCS *wcs = pmAstromWCSfromHeader(header2);
+
+    psPlane  *aChip = psPlaneAlloc();
+    psPlane  *aFPA = psPlaneAlloc();
+    psPlane  *aTPA = psPlaneAlloc();
+    psSphere *aSky = psSphereAlloc();
+
+    psPlane  *bChip = psPlaneAlloc();
+    psSphere *bSky = psSphereAlloc();
+
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            aChip->x = x;
+            aChip->y = y;
+            bChip->x = x;
+            bChip->y = y;
+
+            psPlaneTransformApply (aFPA, chip->toFPA, aChip);
+            psPlaneTransformApply (aTPA, fpa->toTPA, aFPA);
+            psDeproject (aSky, aTPA, fpa->toSky);
+
+            pmAstromWCStoSky (bSky, wcs, bChip);
+
+            while (aSky->r > 2*M_PI)
+                aSky->r -= 2*M_PI;
+            while (aSky->r <      0)
+                aSky->r += 2*M_PI;
+            while (bSky->r > 2*M_PI)
+                bSky->r -= 2*M_PI;
+            while (bSky->r <      0)
+                bSky->r += 2*M_PI;
+
+            ok_float(aSky->r*PS_DEG_RAD, bSky->r*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", aSky->r*PS_DEG_RAD, bSky->r*PS_DEG_RAD, aSky->r*PS_DEG_RAD - bSky->r*PS_DEG_RAD);
+            ok_float(aSky->d*PS_DEG_RAD, bSky->d*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", aSky->d*PS_DEG_RAD, bSky->d*PS_DEG_RAD, aSky->d*PS_DEG_RAD - bSky->d*PS_DEG_RAD);
+        }
+    }
+    psFree (aSky);
+    psFree (aTPA);
+    psFree (aFPA);
+    psFree (aChip);
+
+    psFree (bSky);
+    psFree (bChip);
+
+    psFree (wcs);
+    psFree (header2);
+
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+    psFree (header1);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+void test2()
+{
+    note("test pmAstromReadWCS");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style coordinate system
+    Coords coords;
+    strcpy (coords.ctype, "RA---TAN");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 0.0;
+    coords.crpix2 = 0.0;
+    coords.cdelt1 = 1.0/3600.0;
+    coords.cdelt2 = 1.0/3600.0;
+    coords.pc1_1  = 0.9;
+    coords.pc1_2  = 0.1;
+    coords.pc2_1  = -0.1;
+    coords.pc2_2  = 0.9;
+    coords.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+
+    psMetadata *header1 = WriteCoordsToHeader (&coords);
+
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadWCS (fpa, chip, header1, 10.0);
+
+    ok (status, "converted WCS keywords to WCS astrometry");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psMetadata *header2 = psMetadataAlloc();
+    status = pmAstromWriteWCS (header2, fpa, chip, 0.001);
+
+    pmAstromWCS *wcs = pmAstromWCSfromHeader(header2);
+
+    psPlane  *aChip = psPlaneAlloc();
+    psPlane  *aFPA = psPlaneAlloc();
+    psPlane  *aTPA = psPlaneAlloc();
+    psSphere *aSky = psSphereAlloc();
+
+    psPlane  *bChip = psPlaneAlloc();
+    psSphere *bSky = psSphereAlloc();
+
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            aChip->x = x;
+            aChip->y = y;
+            bChip->x = x;
+            bChip->y = y;
+
+            psPlaneTransformApply (aFPA, chip->toFPA, aChip);
+            psPlaneTransformApply (aTPA, fpa->toTPA, aFPA);
+            psDeproject (aSky, aTPA, fpa->toSky);
+
+            pmAstromWCStoSky (bSky, wcs, bChip);
+
+            while (aSky->r > 2*M_PI)
+                aSky->r -= 2*M_PI;
+            while (aSky->r <      0)
+                aSky->r += 2*M_PI;
+            while (bSky->r > 2*M_PI)
+                bSky->r -= 2*M_PI;
+            while (bSky->r <      0)
+                bSky->r += 2*M_PI;
+
+            ok_float(aSky->r*PS_DEG_RAD, bSky->r*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", aSky->r*PS_DEG_RAD, bSky->r*PS_DEG_RAD, aSky->r*PS_DEG_RAD - bSky->r*PS_DEG_RAD);
+            ok_float(aSky->d*PS_DEG_RAD, bSky->d*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", aSky->d*PS_DEG_RAD, bSky->d*PS_DEG_RAD, aSky->d*PS_DEG_RAD - bSky->d*PS_DEG_RAD);
+        }
+    }
+    psFree (aSky);
+    psFree (aTPA);
+    psFree (aFPA);
+    psFree (aChip);
+
+    psFree (bSky);
+    psFree (bChip);
+
+    psFree (wcs);
+    psFree (header2);
+
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+    psFree (header1);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+void test3()
+{
+    note("test pmAstromReadWCS");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style coordinate system
+    Coords coords;
+    strcpy (coords.ctype, "RA---TAN");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 0.0;
+    coords.crpix2 = 0.0;
+    coords.cdelt1 = 1.0/3600.0;
+    coords.cdelt2 = 1.0/3600.0;
+    coords.pc1_1  = 1.0;
+    coords.pc1_2  = 0.0;
+    coords.pc2_1  = 0.0;
+    coords.pc2_2  = 1.0;
+    coords.Npolyterms = 2;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+    coords.polyterms[0][0] = 0.01; // L vs X^2
+    coords.polyterms[2][1] = 0.01; // M vs Y^2
+
+    psMetadata *header1 = WriteCoordsToHeader (&coords);
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadWCS (fpa, chip, header1, 10.0);
+
+    ok (status, "converted WCS keywords to WCS astrometry");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psMetadata *header2 = psMetadataAlloc();
+    status = pmAstromWriteWCS (header2, fpa, chip, 0.001);
+
+    pmAstromWCS *wcs = pmAstromWCSfromHeader(header2);
+
+    psPlane  *aChip = psPlaneAlloc();
+    psPlane  *aFPA = psPlaneAlloc();
+    psPlane  *aTPA = psPlaneAlloc();
+    psSphere *aSky = psSphereAlloc();
+
+    psPlane  *bChip = psPlaneAlloc();
+    psSphere *bSky = psSphereAlloc();
+
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            aChip->x = x;
+            aChip->y = y;
+            bChip->x = x;
+            bChip->y = y;
+
+            psPlaneTransformApply (aFPA, chip->toFPA, aChip);
+            psPlaneTransformApply (aTPA, fpa->toTPA, aFPA);
+            psDeproject (aSky, aTPA, fpa->toSky);
+
+            pmAstromWCStoSky (bSky, wcs, bChip);
+
+            while (aSky->r > 2*M_PI)
+                aSky->r -= 2*M_PI;
+            while (aSky->r <      0)
+                aSky->r += 2*M_PI;
+            while (bSky->r > 2*M_PI)
+                bSky->r -= 2*M_PI;
+            while (bSky->r <      0)
+                bSky->r += 2*M_PI;
+
+            ok_float(aSky->r*PS_DEG_RAD, bSky->r*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", aSky->r*PS_DEG_RAD, bSky->r*PS_DEG_RAD, aSky->r*PS_DEG_RAD - bSky->r*PS_DEG_RAD);
+            ok_float(aSky->d*PS_DEG_RAD, bSky->d*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", aSky->d*PS_DEG_RAD, bSky->d*PS_DEG_RAD, aSky->d*PS_DEG_RAD - bSky->d*PS_DEG_RAD);
+        }
+    }
+    psFree (aSky);
+    psFree (aTPA);
+    psFree (aFPA);
+    psFree (aChip);
+
+    psFree (bSky);
+    psFree (bChip);
+
+    psFree (wcs);
+    psFree (header2);
+
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+    psFree (header1);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+void test1x()
+{
+    note("test pmAstromReadWCS");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style coordinate system
+    Coords coords;
+    strcpy (coords.ctype, "RA---TAN");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 20.0;
+    coords.crpix2 = 50.0;
+    coords.cdelt1 = 1.0/3600.0;
+    coords.cdelt2 = 1.0/3600.0;
+    coords.pc1_1  = 1.0;
+    coords.pc1_2  = 0.0;
+    coords.pc2_1  = 0.0;
+    coords.pc2_2  = 1.0;
+    coords.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+
+    psMetadata *header1 = WriteCoordsToHeader (&coords);
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadWCS (fpa, chip, header1, 10.0);
+
+    ok (status, "converted WCS keywords to WCS astrometry");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psMetadata *header2 = psMetadataAlloc();
+    status = pmAstromWriteWCS (header2, fpa, chip, 0.001);
+    pmAstromWCS *wcs = pmAstromWCSfromHeader(header2);
+
+    psPlane  *aChip = psPlaneAlloc();
+    psPlane  *aFPA = psPlaneAlloc();
+    psPlane  *aTPA = psPlaneAlloc();
+    psSphere *aSky = psSphereAlloc();
+
+    psPlane  *bChip = psPlaneAlloc();
+    psSphere *bSky = psSphereAlloc();
+
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            aChip->x = x;
+            aChip->y = y;
+            bChip->x = x;
+            bChip->y = y;
+
+            psPlaneTransformApply (aFPA, chip->toFPA, aChip);
+            psPlaneTransformApply (aTPA, fpa->toTPA, aFPA);
+            psDeproject (aSky, aTPA, fpa->toSky);
+
+            pmAstromWCStoSky (bSky, wcs, bChip);
+
+            while (aSky->r > 2*M_PI)
+                aSky->r -= 2*M_PI;
+            while (aSky->r <      0)
+                aSky->r += 2*M_PI;
+            while (bSky->r > 2*M_PI)
+                bSky->r -= 2*M_PI;
+            while (bSky->r <      0)
+                bSky->r += 2*M_PI;
+
+            ok_float(aSky->r*PS_DEG_RAD, bSky->r*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", aSky->r*PS_DEG_RAD, bSky->r*PS_DEG_RAD, aSky->r*PS_DEG_RAD - bSky->r*PS_DEG_RAD);
+            ok_float(aSky->d*PS_DEG_RAD, bSky->d*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", aSky->d*PS_DEG_RAD, bSky->d*PS_DEG_RAD, aSky->d*PS_DEG_RAD - bSky->d*PS_DEG_RAD);
+        }
+    }
+    psFree (aSky);
+    psFree (aTPA);
+    psFree (aFPA);
+    psFree (aChip);
+
+    psFree (bSky);
+    psFree (bChip);
+
+    psFree (wcs);
+    psFree (header2);
+
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+    psFree (header1);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+void test2x()
+{
+    note("test pmAstromReadWCS");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style coordinate system
+    Coords coords;
+    strcpy (coords.ctype, "RA---TAN");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 50.0;
+    coords.crpix2 = -20.0;
+    coords.cdelt1 = 1.0/3600.0;
+    coords.cdelt2 = 1.0/3600.0;
+    coords.pc1_1  = 0.9;
+    coords.pc1_2  = 0.1;
+    coords.pc2_1  = -0.1;
+    coords.pc2_2  = 0.9;
+    coords.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+
+    psMetadata *header1 = WriteCoordsToHeader (&coords);
+
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadWCS (fpa, chip, header1, 10.0);
+
+    ok (status, "converted WCS keywords to WCS astrometry");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psMetadata *header2 = psMetadataAlloc();
+    status = pmAstromWriteWCS (header2, fpa, chip, 0.001);
+
+    pmAstromWCS *wcs = pmAstromWCSfromHeader(header2);
+
+    psPlane  *aChip = psPlaneAlloc();
+    psPlane  *aFPA = psPlaneAlloc();
+    psPlane  *aTPA = psPlaneAlloc();
+    psSphere *aSky = psSphereAlloc();
+
+    psPlane  *bChip = psPlaneAlloc();
+    psSphere *bSky = psSphereAlloc();
+
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            aChip->x = x;
+            aChip->y = y;
+            bChip->x = x;
+            bChip->y = y;
+
+            psPlaneTransformApply (aFPA, chip->toFPA, aChip);
+            psPlaneTransformApply (aTPA, fpa->toTPA, aFPA);
+            psDeproject (aSky, aTPA, fpa->toSky);
+
+            pmAstromWCStoSky (bSky, wcs, bChip);
+
+            while (aSky->r > 2*M_PI)
+                aSky->r -= 2*M_PI;
+            while (aSky->r <      0)
+                aSky->r += 2*M_PI;
+            while (bSky->r > 2*M_PI)
+                bSky->r -= 2*M_PI;
+            while (bSky->r <      0)
+                bSky->r += 2*M_PI;
+
+            ok_float(aSky->r*PS_DEG_RAD, bSky->r*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", aSky->r*PS_DEG_RAD, bSky->r*PS_DEG_RAD, aSky->r*PS_DEG_RAD - bSky->r*PS_DEG_RAD);
+            ok_float(aSky->d*PS_DEG_RAD, bSky->d*PS_DEG_RAD, "coordinate match: %f vs %f (delta = %f)", aSky->d*PS_DEG_RAD, bSky->d*PS_DEG_RAD, aSky->d*PS_DEG_RAD - bSky->d*PS_DEG_RAD);
+        }
+    }
+    psFree (aSky);
+    psFree (aTPA);
+    psFree (aFPA);
+    psFree (aChip);
+
+    psFree (bSky);
+    psFree (bChip);
+
+    psFree (wcs);
+    psFree (header2);
+
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+    psFree (header1);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+void test3x()
+{
+    note("test pmAstromReadWCS");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style coordinate system
+    Coords coords;
+    strcpy (coords.ctype, "RA---TAN");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 20.0;
+    coords.crpix2 = 50.0;
+    coords.cdelt1 = 1.0/3600.0;
+    coords.cdelt2 = 1.0/3600.0;
+    coords.pc1_1  = 1.0;
+    coords.pc1_2  = 0.0;
+    coords.pc2_1  = 0.0;
+    coords.pc2_2  = 1.0;
+    coords.Npolyterms = 2;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+    coords.polyterms[0][0] = 0.01; // L vs X^2
+    coords.polyterms[2][1] = 0.01; // M vs Y^2
+
+    psMetadata *header1 = WriteCoordsToHeader (&coords);
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadWCS (fpa, chip, header1, 10.0);
+
+    ok (status, "converted WCS keywords to WCS astrometry");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psMetadata *header2 = psMetadataAlloc();
+    status = pmAstromWriteWCS (header2, fpa, chip, 0.00001);
+
+    pmAstromWCS *wcs = pmAstromWCSfromHeader(header2);
+
+    psPlane  *aChip = psPlaneAlloc();
+    psPlane  *aFPA = psPlaneAlloc();
+    psPlane  *aTPA = psPlaneAlloc();
+    psSphere *aSky = psSphereAlloc();
+
+    psPlane  *bChip = psPlaneAlloc();
+    psSphere *bSky = psSphereAlloc();
+
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            aChip->x = x;
+            aChip->y = y;
+            bChip->x = x;
+            bChip->y = y;
+
+            psPlaneTransformApply (aFPA, chip->toFPA, aChip);
+            psPlaneTransformApply (aTPA, fpa->toTPA, aFPA);
+            psDeproject (aSky, aTPA, fpa->toSky);
+
+            pmAstromWCStoSky (bSky, wcs, bChip);
+
+            while (aSky->r > 2*M_PI)
+                aSky->r -= 2*M_PI;
+            while (aSky->r <      0)
+                aSky->r += 2*M_PI;
+            while (bSky->r > 2*M_PI)
+                bSky->r -= 2*M_PI;
+            while (bSky->r <      0)
+                bSky->r += 2*M_PI;
+
+            // XXX we are getting round-off errors as a result of the wcs transformation
+            // having terms in units of pix/degree. for now require 10mas on this
+            ok_float_tol(aSky->r*PS_DEG_RAD, bSky->r*PS_DEG_RAD, 0.01/3600.0, "coordinate match: %f vs %f (delta = %f)", aSky->r*PS_DEG_RAD, bSky->r*PS_DEG_RAD, aSky->r*PS_DEG_RAD - bSky->r*PS_DEG_RAD);
+            ok_float_tol(aSky->d*PS_DEG_RAD, bSky->d*PS_DEG_RAD, 0.01/3600.0, "coordinate match: %f vs %f (delta = %f)", aSky->d*PS_DEG_RAD, bSky->d*PS_DEG_RAD, aSky->d*PS_DEG_RAD - bSky->d*PS_DEG_RAD);
+        }
+    }
+    psFree (aSky);
+    psFree (aTPA);
+    psFree (aFPA);
+    psFree (aChip);
+
+    psFree (bSky);
+    psFree (bChip);
+
+    psFree (wcs);
+    psFree (header2);
+
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+    psFree (header1);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+psMetadata *WriteCoordsToHeader (Coords *coords)
+{
+
+    char name[16];
+
+    // construct a header using coords as the input
+    psMetadata *header = psMetadataAlloc();
+
+    sprintf (name, "RA--%s", &coords[0].ctype[4]);
+    psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE1", PS_META_REPLACE, "", name);
+    sprintf (name, "DEC-%s", &coords[0].ctype[4]);
+    psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE2", PS_META_REPLACE, "", name);
+
+    // center coords (R,D)
+    psMetadataAddF64 (header, PS_LIST_TAIL, "CRVAL1", PS_META_REPLACE, "", coords[0].crval1);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "CRVAL2", PS_META_REPLACE, "", coords[0].crval2);
+
+    // center coords (X,Y)
+    psMetadataAddF64 (header, PS_LIST_TAIL, "CRPIX1", PS_META_REPLACE, "", coords[0].crpix1);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "CRPIX2", PS_META_REPLACE, "", coords[0].crpix2);
+
+    // degrees per pixel
+    psMetadataAddF64 (header, PS_LIST_TAIL, "CDELT1",  PS_META_REPLACE, "", coords[0].cdelt1);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "CDELT2",  PS_META_REPLACE, "", coords[0].cdelt2);
+
+    // rotation matrix
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PC001001", PS_META_REPLACE, "", coords[0].pc1_1);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PC001002", PS_META_REPLACE, "", coords[0].pc1_2);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PC002001", PS_META_REPLACE, "", coords[0].pc2_1);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PC002002", PS_META_REPLACE, "", coords[0].pc2_2);
+
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PCA1X2Y0", PS_META_REPLACE, "", coords[0].polyterms[0][0]);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PCA1X1Y1", PS_META_REPLACE, "", coords[0].polyterms[1][0]);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PCA1X0Y2", PS_META_REPLACE, "", coords[0].polyterms[2][0]);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PCA2X2Y0", PS_META_REPLACE, "", coords[0].polyterms[0][1]);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PCA2X1Y1", PS_META_REPLACE, "", coords[0].polyterms[1][1]);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PCA2X0Y2", PS_META_REPLACE, "", coords[0].polyterms[2][1]);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PCA1X3Y0", PS_META_REPLACE, "", coords[0].polyterms[3][0]);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PCA1X2Y1", PS_META_REPLACE, "", coords[0].polyterms[4][0]);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PCA1X1Y2", PS_META_REPLACE, "", coords[0].polyterms[5][0]);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PCA1X0Y3", PS_META_REPLACE, "", coords[0].polyterms[6][0]);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PCA2X3Y0", PS_META_REPLACE, "", coords[0].polyterms[3][1]);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PCA2X2Y1", PS_META_REPLACE, "", coords[0].polyterms[4][1]);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PCA2X1Y2", PS_META_REPLACE, "", coords[0].polyterms[5][1]);
+    psMetadataAddF64 (header, PS_LIST_TAIL, "PCA2X0Y3", PS_META_REPLACE, "", coords[0].polyterms[6][1]);
+
+    psMetadataAddS32 (header, PS_LIST_TAIL, "NPLYTERM", PS_META_REPLACE, "", coords[0].Npolyterms);
+
+    return header;
+}
+
+# else
+
+    int main (void)
+{
+    plan_tests(2);
+
+    ok(true, "Skipping tests: (libdvo not available)");
+    note("pmAstrometryWCS tests compared with DVO coords routines : SKIPPED (libdvo not available)");
+
+    return exit_status();
+}
+
+# endif
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmAstrometryWCS_DVO4.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmAstrometryWCS_DVO4.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmAstrometryWCS_DVO4.c	(revision 22158)
@@ -0,0 +1,956 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+// HAVA_KAPA checks for Ohana libraries, needed for the Coords structure
+# if (HAVE_KAPA)
+# include "dvo.h"
+
+psMetadata *WriteCoordsToHeader (Coords *coords);
+void test1(); // basic WRP+DIS projections,
+void test2(); // small rotation
+void test3(); // 2nd order terms in WRP
+void test4(); // small rotation in WRP and DIS
+void test5(); // 2nd order terms in WRP and DIS
+void test1x(); // basic WRP+DIS projections with central offset
+void test2x(); // small rotation with central offset
+void test3x(); // 2nd order term in WRP with central offset
+
+int main (void)
+{
+    plan_tests(1329);
+
+    note("pmAstromWriteWCS tests compared with DVO coords routines");
+
+    test1();
+    test2();
+    test3();
+    test4();
+    test5();
+    test1x();
+    test2x();
+    test3x();
+
+    return exit_status();
+}
+
+// create a fake chip-level mosaic header
+void test1()
+{
+    note("test pmAstrom Read,Write BilevelChip");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style mosaic coordinate system
+    // chip-level data (chip -> fpa)
+    Coords coords;
+    strcpy (coords.ctype, "RA---WRP");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 0.0;
+    coords.crpix2 = 0.0;
+    coords.cdelt1 = 10.0; // microns per pixel
+    coords.cdelt2 = 10.0; // microns per pixel
+    coords.pc1_1  = 1.0;
+    coords.pc1_2  = 0.0;
+    coords.pc2_1  = 0.0;
+    coords.pc2_2  = 1.0;
+    coords.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+
+    // mosaic-level data (fpa->sky)
+    Coords mosaic;
+    strcpy (mosaic.ctype, "RA---DIS");
+    mosaic.crval1 = 0.0;
+    mosaic.crval2 = 0.0;
+    mosaic.crpix1 = 0.0;
+    mosaic.crpix2 = 0.0;
+    mosaic.cdelt1 = 1.0 / 10.0 / 3600.0; // degrees per micron
+    mosaic.cdelt2 = 1.0 / 10.0 / 3600.0; // degrees per micron
+    mosaic.pc1_1  = 1.0;
+    mosaic.pc1_2  = 0.0;
+    mosaic.pc2_1  = 0.0;
+    mosaic.pc2_2  = 1.0;
+    mosaic.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        mosaic.polyterms[i][0] = 0.0;
+        mosaic.polyterms[i][1] = 0.0;
+    }
+    RegisterMosaic (&mosaic);
+
+    psMetadata *headerChp = WriteCoordsToHeader (&coords);
+    psMetadata *headerMos = WriteCoordsToHeader (&mosaic);
+
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadBilevelChip (chip, headerChp);
+    ok (status, "read bilevel chip header");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    bool status = pmAstromReadBilevelMosaic (fpa, headerMos);
+    ok (status, "read bilevel fpa header");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psPlane  *onChip = psPlaneAlloc();
+    psPlane  *onFPA  = psPlaneAlloc();
+    psPlane  *onTPA  = psPlaneAlloc();
+    psSphere *onSky  = psSphereAlloc();
+
+    double rDVO, dDVO;
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            XY_to_RD (&rDVO, &dDVO, x, y, &coords);
+
+            onChip->x = x;
+            onChip->y = y;
+
+            psPlaneTransformApply (onFPA, chip->toFPA, onChip);
+            psPlaneTransformApply (onTPA, fpa->toTPA, onFPA);
+            psDeproject (onSky, onTPA, fpa->toSky);
+
+            while (onSky->r > 2*M_PI)
+                onSky->r -= 2*M_PI;
+            while (onSky->r <      0)
+                onSky->r += 2*M_PI;
+
+            // fprintf (stderr, "fpa x: %f vs %f : %f\n", rDVO, onFPA->x, rDVO - onFPA->x);
+            // fprintf (stderr, "fpa y: %f vs %f : %f\n", dDVO, onFPA->y, dDVO - onFPA->y);
+
+            ok_float(onSky->r*PM_DEG_RAD, rDVO, "coordinate match: %f vs %f (delta = %f)", onSky->r*PM_DEG_RAD, rDVO, 3600.0*(onSky->r*PM_DEG_RAD - rDVO));
+            ok_float(onSky->d*PM_DEG_RAD, dDVO, "coordinate match: %f vs %f (delta = %f)", onSky->d*PM_DEG_RAD, dDVO, 3600.0*(onSky->d*PM_DEG_RAD - dDVO));
+        }
+    }
+    psFree (onSky);
+    psFree (onTPA);
+    psFree (onFPA);
+    psFree (onChip);
+
+    skip_end();
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+
+    psFree (headerMos);
+    psFree (headerChp);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+// create a fake chip-level mosaic header
+void test2()
+{
+    note("test pmAstrom Read,Write BilevelChip");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style mosaic coordinate system
+    // chip-level data (chip -> fpa)
+    Coords coords;
+    strcpy (coords.ctype, "RA---WRP");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 0.0;
+    coords.crpix2 = 0.0;
+    coords.cdelt1 = 10.0; // microns per pixel
+    coords.cdelt2 = 10.0; // microns per pixel
+    coords.pc1_1  = 0.9;
+    coords.pc1_2  = 0.1;
+    coords.pc2_1  =-0.1;
+    coords.pc2_2  = 0.9;
+    coords.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+
+    // mosaic-level data (fpa->sky)
+    Coords mosaic;
+    strcpy (mosaic.ctype, "RA---DIS");
+    mosaic.crval1 = 0.0;
+    mosaic.crval2 = 0.0;
+    mosaic.crpix1 = 0.0;
+    mosaic.crpix2 = 0.0;
+    mosaic.cdelt1 = 1.0 / 10.0 / 3600.0; // degrees per micron
+    mosaic.cdelt2 = 1.0 / 10.0 / 3600.0; // degrees per micron
+    mosaic.pc1_1  = 1.0;
+    mosaic.pc1_2  = 0.0;
+    mosaic.pc2_1  = 0.0;
+    mosaic.pc2_2  = 1.0;
+    mosaic.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        mosaic.polyterms[i][0] = 0.0;
+        mosaic.polyterms[i][1] = 0.0;
+    }
+    RegisterMosaic (&mosaic);
+
+    psMetadata *headerChp = WriteCoordsToHeader (&coords);
+    psMetadata *headerMos = WriteCoordsToHeader (&mosaic);
+
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadBilevelChip (chip, headerChp);
+    ok (status, "read bilevel chip header");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    bool status = pmAstromReadBilevelMosaic (fpa, headerMos);
+    ok (status, "read bilevel fpa header");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psPlane  *onChip = psPlaneAlloc();
+    psPlane  *onFPA  = psPlaneAlloc();
+    psPlane  *onTPA  = psPlaneAlloc();
+    psSphere *onSky  = psSphereAlloc();
+
+    double rDVO, dDVO;
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            XY_to_RD (&rDVO, &dDVO, x, y, &coords);
+
+            onChip->x = x;
+            onChip->y = y;
+
+            psPlaneTransformApply (onFPA, chip->toFPA, onChip);
+            psPlaneTransformApply (onTPA, fpa->toTPA, onFPA);
+            psDeproject (onSky, onTPA, fpa->toSky);
+
+            while (onSky->r > 2*M_PI)
+                onSky->r -= 2*M_PI;
+            while (onSky->r <      0)
+                onSky->r += 2*M_PI;
+
+            // fprintf (stderr, "fpa x: %f vs %f : %f\n", rDVO, onFPA->x, rDVO - onFPA->x);
+            // fprintf (stderr, "fpa y: %f vs %f : %f\n", dDVO, onFPA->y, dDVO - onFPA->y);
+
+            ok_float(onSky->r*PS_DEG_RAD, rDVO, "coordinate match: %f vs %f (delta = %f)", onSky->r*PS_DEG_RAD, rDVO, 3600.0*(onSky->r*PS_DEG_RAD - rDVO));
+            ok_float(onSky->d*PS_DEG_RAD, dDVO, "coordinate match: %f vs %f (delta = %f)", onSky->d*PS_DEG_RAD, dDVO, 3600.0*(onSky->d*PS_DEG_RAD - dDVO));
+        }
+    }
+    psFree (onSky);
+    psFree (onTPA);
+    psFree (onFPA);
+    psFree (onChip);
+
+    skip_end();
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+
+    psFree (headerMos);
+    psFree (headerChp);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+// create a fake chip-level mosaic header
+void test3()
+{
+    note("test pmAstrom Read,Write BilevelChip");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style mosaic coordinate system
+    // chip-level data (chip -> fpa)
+    Coords coords;
+    strcpy (coords.ctype, "RA---WRP");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 0.0;
+    coords.crpix2 = 0.0;
+    coords.cdelt1 = 10.0; // microns per pixel
+    coords.cdelt2 = 10.0; // microns per pixel
+    coords.pc1_1  = 1.0;
+    coords.pc1_2  = 0.0;
+    coords.pc2_1  = 0.0;
+    coords.pc2_2  = 1.0;
+    coords.Npolyterms = 2;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+    coords.polyterms[0][0] = 0.01; // L vs X^2
+    coords.polyterms[2][1] = 0.01; // M vs Y^2
+
+    // mosaic-level data (fpa->sky)
+    Coords mosaic;
+    strcpy (mosaic.ctype, "RA---DIS");
+    mosaic.crval1 = 0.0;
+    mosaic.crval2 = 0.0;
+    mosaic.crpix1 = 0.0;
+    mosaic.crpix2 = 0.0;
+    mosaic.cdelt1 = 1.0 / 10.0 / 3600.0; // degrees per micron
+    mosaic.cdelt2 = 1.0 / 10.0 / 3600.0; // degrees per micron
+    mosaic.pc1_1  = 1.0;
+    mosaic.pc1_2  = 0.0;
+    mosaic.pc2_1  = 0.0;
+    mosaic.pc2_2  = 1.0;
+    mosaic.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        mosaic.polyterms[i][0] = 0.0;
+        mosaic.polyterms[i][1] = 0.0;
+    }
+    RegisterMosaic (&mosaic);
+
+    psMetadata *headerChp = WriteCoordsToHeader (&coords);
+    psMetadata *headerMos = WriteCoordsToHeader (&mosaic);
+
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadBilevelChip (chip, headerChp);
+    ok (status, "read bilevel chip header");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    bool status = pmAstromReadBilevelMosaic (fpa, headerMos);
+    ok (status, "read bilevel fpa header");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psPlane  *onChip = psPlaneAlloc();
+    psPlane  *onFPA  = psPlaneAlloc();
+    psPlane  *onTPA  = psPlaneAlloc();
+    psSphere *onSky  = psSphereAlloc();
+
+    double rDVO, dDVO;
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            XY_to_RD (&rDVO, &dDVO, x, y, &coords);
+
+            onChip->x = x;
+            onChip->y = y;
+
+            psPlaneTransformApply (onFPA, chip->toFPA, onChip);
+            psPlaneTransformApply (onTPA, fpa->toTPA, onFPA);
+            psDeproject (onSky, onTPA, fpa->toSky);
+
+            while (onSky->r > 2*M_PI)
+                onSky->r -= 2*M_PI;
+            while (onSky->r <      0)
+                onSky->r += 2*M_PI;
+
+            // fprintf (stderr, "fpa x: %f vs %f : %f\n", rDVO, onFPA->x, rDVO - onFPA->x);
+            // fprintf (stderr, "fpa y: %f vs %f : %f\n", dDVO, onFPA->y, dDVO - onFPA->y);
+
+            ok_float(onSky->r*PM_DEG_RAD, rDVO, "coordinate match: %f vs %f (delta = %f)", onSky->r*PM_DEG_RAD, rDVO, 3600.0*(onSky->r*PM_DEG_RAD - rDVO));
+            ok_float(onSky->d*PM_DEG_RAD, dDVO, "coordinate match: %f vs %f (delta = %f)", onSky->d*PM_DEG_RAD, dDVO, 3600.0*(onSky->d*PM_DEG_RAD - dDVO));
+        }
+    }
+    psFree (onSky);
+    psFree (onTPA);
+    psFree (onFPA);
+    psFree (onChip);
+
+    skip_end();
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+
+    psFree (headerMos);
+    psFree (headerChp);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+// create a fake chip-level mosaic header
+void test4()
+{
+    note("test pmAstrom Read,Write BilevelChip");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style mosaic coordinate system
+    // chip-level data (chip -> fpa)
+    Coords coords;
+    strcpy (coords.ctype, "RA---WRP");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 0.0;
+    coords.crpix2 = 0.0;
+    coords.cdelt1 = 10.0; // microns per pixel
+    coords.cdelt2 = 10.0; // microns per pixel
+    coords.pc1_1  = 0.9;
+    coords.pc1_2  = 0.1;
+    coords.pc2_1  =-0.1;
+    coords.pc2_2  = 0.9;
+    coords.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+
+    // mosaic-level data (fpa->sky)
+    Coords mosaic;
+    strcpy (mosaic.ctype, "RA---DIS");
+    mosaic.crval1 = 0.0;
+    mosaic.crval2 = 0.0;
+    mosaic.crpix1 = 0.0;
+    mosaic.crpix2 = 0.0;
+    mosaic.cdelt1 = 1.0 / 10.0 / 3600.0; // degrees per micron
+    mosaic.cdelt2 = 1.0 / 10.0 / 3600.0; // degrees per micron
+    mosaic.pc1_1  = 0.9;
+    mosaic.pc1_2  =-0.1;
+    mosaic.pc2_1  = 0.1;
+    mosaic.pc2_2  = 0.9;
+    mosaic.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        mosaic.polyterms[i][0] = 0.0;
+        mosaic.polyterms[i][1] = 0.0;
+    }
+    RegisterMosaic (&mosaic);
+
+    psMetadata *headerChp = WriteCoordsToHeader (&coords);
+    psMetadata *headerMos = WriteCoordsToHeader (&mosaic);
+
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadBilevelChip (chip, headerChp);
+    ok (status, "read bilevel chip header");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    bool status = pmAstromReadBilevelMosaic (fpa, headerMos);
+    ok (status, "read bilevel fpa header");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psPlane  *onChip = psPlaneAlloc();
+    psPlane  *onFPA  = psPlaneAlloc();
+    psPlane  *onTPA  = psPlaneAlloc();
+    psSphere *onSky  = psSphereAlloc();
+
+    double rDVO, dDVO;
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            XY_to_RD (&rDVO, &dDVO, x, y, &coords);
+
+            onChip->x = x;
+            onChip->y = y;
+
+            psPlaneTransformApply (onFPA, chip->toFPA, onChip);
+            psPlaneTransformApply (onTPA, fpa->toTPA, onFPA);
+            psDeproject (onSky, onTPA, fpa->toSky);
+
+            while (onSky->r > 2*M_PI)
+                onSky->r -= 2*M_PI;
+            while (onSky->r <      0)
+                onSky->r += 2*M_PI;
+
+            // fprintf (stderr, "fpa x: %f vs %f : %f\n", rDVO, onFPA->x, rDVO - onFPA->x);
+            // fprintf (stderr, "fpa y: %f vs %f : %f\n", dDVO, onFPA->y, dDVO - onFPA->y);
+
+            ok_float(onSky->r*PM_DEG_RAD, rDVO, "coordinate match: %f vs %f (delta = %f)", onSky->r*PM_DEG_RAD, rDVO, 3600.0*(onSky->r*PM_DEG_RAD - rDVO));
+            ok_float(onSky->d*PM_DEG_RAD, dDVO, "coordinate match: %f vs %f (delta = %f)", onSky->d*PM_DEG_RAD, dDVO, 3600.0*(onSky->d*PM_DEG_RAD - dDVO));
+        }
+    }
+    psFree (onSky);
+    psFree (onTPA);
+    psFree (onFPA);
+    psFree (onChip);
+
+    skip_end();
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+
+    psFree (headerMos);
+    psFree (headerChp);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+// create a fake chip-level mosaic header
+void test5()
+{
+    note("test pmAstrom Read,Write BilevelChip");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style mosaic coordinate system
+    // chip-level data (chip -> fpa)
+    Coords coords;
+    strcpy (coords.ctype, "RA---WRP");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = 0.0;
+    coords.crpix2 = 0.0;
+    coords.cdelt1 = 10.0; // microns per pixel
+    coords.cdelt2 = 10.0; // microns per pixel
+    coords.pc1_1  = 1.0;
+    coords.pc1_2  = 0.0;
+    coords.pc2_1  = 0.0;
+    coords.pc2_2  = 1.0;
+    coords.Npolyterms = 2;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+    coords.polyterms[0][0] = 0.01; // L vs X^2
+    coords.polyterms[2][1] = 0.01; // M vs Y^2
+
+    // mosaic-level data (fpa->sky)
+    Coords mosaic;
+    strcpy (mosaic.ctype, "RA---DIS");
+    mosaic.crval1 = 0.0;
+    mosaic.crval2 = 0.0;
+    mosaic.crpix1 = 0.0;
+    mosaic.crpix2 = 0.0;
+    mosaic.cdelt1 = 1.0 / 10.0 / 3600.0; // degrees per micron
+    mosaic.cdelt2 = 1.0 / 10.0 / 3600.0; // degrees per micron
+    mosaic.pc1_1  = 1.0;
+    mosaic.pc1_2  = 0.0;
+    mosaic.pc2_1  = 0.0;
+    mosaic.pc2_2  = 1.0;
+    mosaic.Npolyterms = 2;
+    for (int i = 0; i < 7; i++) {
+        mosaic.polyterms[i][0] = 0.0;
+        mosaic.polyterms[i][1] = 0.0;
+    }
+    RegisterMosaic (&mosaic);
+    mosaic.polyterms[0][0] = 0.01; // L vs X^2
+    mosaic.polyterms[2][1] = 0.01; // M vs Y^2
+
+    psMetadata *headerChp = WriteCoordsToHeader (&coords);
+    psMetadata *headerMos = WriteCoordsToHeader (&mosaic);
+
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadBilevelChip (chip, headerChp);
+    ok (status, "read bilevel chip header");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    bool status = pmAstromReadBilevelMosaic (fpa, headerMos);
+    ok (status, "read bilevel fpa header");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psPlane  *onChip = psPlaneAlloc();
+    psPlane  *onFPA  = psPlaneAlloc();
+    psPlane  *onTPA  = psPlaneAlloc();
+    psSphere *onSky  = psSphereAlloc();
+
+    double rDVO, dDVO;
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            XY_to_RD (&rDVO, &dDVO, x, y, &coords);
+
+            onChip->x = x;
+            onChip->y = y;
+
+            psPlaneTransformApply (onFPA, chip->toFPA, onChip);
+            psPlaneTransformApply (onTPA, fpa->toTPA, onFPA);
+            psDeproject (onSky, onTPA, fpa->toSky);
+
+            while (onSky->r > 2*M_PI)
+                onSky->r -= 2*M_PI;
+            while (onSky->r <      0)
+                onSky->r += 2*M_PI;
+
+            // fprintf (stderr, "fpa x: %f vs %f : %f\n", rDVO, onFPA->x, rDVO - onFPA->x);
+            // fprintf (stderr, "fpa y: %f vs %f : %f\n", dDVO, onFPA->y, dDVO - onFPA->y);
+
+            ok_float(onSky->r*PM_DEG_RAD, rDVO, "coordinate match: %f vs %f (delta = %f)", onSky->r*PM_DEG_RAD, rDVO, 3600.0*(onSky->r*PM_DEG_RAD - rDVO));
+            ok_float(onSky->d*PM_DEG_RAD, dDVO, "coordinate match: %f vs %f (delta = %f)", onSky->d*PM_DEG_RAD, dDVO, 3600.0*(onSky->d*PM_DEG_RAD - dDVO));
+        }
+    }
+    psFree (onSky);
+    psFree (onTPA);
+    psFree (onFPA);
+    psFree (onChip);
+
+    skip_end();
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+
+    psFree (headerMos);
+    psFree (headerChp);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+// create a fake chip-level mosaic header
+void test1x()
+{
+    note("test pmAstrom Read,Write BilevelChip");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style mosaic coordinate system
+    // chip-level data (chip -> fpa)
+    Coords coords;
+    strcpy (coords.ctype, "RA---WRP");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = +50.0;
+    coords.crpix2 = -20.0;
+    coords.cdelt1 = 10.0; // microns per pixel
+    coords.cdelt2 = 10.0; // microns per pixel
+    coords.pc1_1  = 1.0;
+    coords.pc1_2  = 0.0;
+    coords.pc2_1  = 0.0;
+    coords.pc2_2  = 1.0;
+    coords.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+
+    // mosaic-level data (fpa->sky)
+    Coords mosaic;
+    strcpy (mosaic.ctype, "RA---DIS");
+    mosaic.crval1 = 0.0;
+    mosaic.crval2 = 0.0;
+    mosaic.crpix1 = 0.0;
+    mosaic.crpix2 = 0.0;
+    mosaic.cdelt1 = 1.0 / 10.0 / 3600.0; // degrees per micron
+    mosaic.cdelt2 = 1.0 / 10.0 / 3600.0; // degrees per micron
+    mosaic.pc1_1  = 1.0;
+    mosaic.pc1_2  = 0.0;
+    mosaic.pc2_1  = 0.0;
+    mosaic.pc2_2  = 1.0;
+    mosaic.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        mosaic.polyterms[i][0] = 0.0;
+        mosaic.polyterms[i][1] = 0.0;
+    }
+    RegisterMosaic (&mosaic);
+
+    psMetadata *headerChp = WriteCoordsToHeader (&coords);
+    psMetadata *headerMos = WriteCoordsToHeader (&mosaic);
+
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadBilevelChip (chip, headerChp);
+    ok (status, "read bilevel chip header");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    bool status = pmAstromReadBilevelMosaic (fpa, headerMos);
+    ok (status, "read bilevel fpa header");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psPlane  *onChip = psPlaneAlloc();
+    psPlane  *onFPA  = psPlaneAlloc();
+    psPlane  *onTPA  = psPlaneAlloc();
+    psSphere *onSky  = psSphereAlloc();
+
+    double rDVO, dDVO;
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            XY_to_RD (&rDVO, &dDVO, x, y, &coords);
+
+            onChip->x = x;
+            onChip->y = y;
+
+            psPlaneTransformApply (onFPA, chip->toFPA, onChip);
+            psPlaneTransformApply (onTPA, fpa->toTPA, onFPA);
+            psDeproject (onSky, onTPA, fpa->toSky);
+
+            while (onSky->r > 2*M_PI)
+                onSky->r -= 2*M_PI;
+            while (onSky->r <      0)
+                onSky->r += 2*M_PI;
+
+            // fprintf (stderr, "fpa x: %f vs %f : %f\n", rDVO, onFPA->x, rDVO - onFPA->x);
+            // fprintf (stderr, "fpa y: %f vs %f : %f\n", dDVO, onFPA->y, dDVO - onFPA->y);
+
+            ok_float(onSky->r*PM_DEG_RAD, rDVO, "coordinate match: %f vs %f (delta = %f)", onSky->r*PM_DEG_RAD, rDVO, 3600.0*(onSky->r*PM_DEG_RAD - rDVO));
+            ok_float(onSky->d*PM_DEG_RAD, dDVO, "coordinate match: %f vs %f (delta = %f)", onSky->d*PM_DEG_RAD, dDVO, 3600.0*(onSky->d*PM_DEG_RAD - dDVO));
+        }
+    }
+    psFree (onSky);
+    psFree (onTPA);
+    psFree (onFPA);
+    psFree (onChip);
+
+    skip_end();
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+
+    psFree (headerMos);
+    psFree (headerChp);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+// create a fake chip-level mosaic header
+void test2x()
+{
+    note("test pmAstrom Read,Write BilevelChip");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style mosaic coordinate system
+    // chip-level data (chip -> fpa)
+    Coords coords;
+    strcpy (coords.ctype, "RA---WRP");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = +50.0;
+    coords.crpix2 = -20.0;
+    coords.cdelt1 = 10.0; // microns per pixel
+    coords.cdelt2 = 10.0; // microns per pixel
+    coords.pc1_1  = 0.9;
+    coords.pc1_2  = 0.1;
+    coords.pc2_1  =-0.1;
+    coords.pc2_2  = 0.9;
+    coords.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+
+    // mosaic-level data (fpa->sky)
+    Coords mosaic;
+    strcpy (mosaic.ctype, "RA---DIS");
+    mosaic.crval1 = 0.0;
+    mosaic.crval2 = 0.0;
+    mosaic.crpix1 = 0.0;
+    mosaic.crpix2 = 0.0;
+    mosaic.cdelt1 = 1.0 / 10.0 / 3600.0; // degrees per micron
+    mosaic.cdelt2 = 1.0 / 10.0 / 3600.0; // degrees per micron
+    mosaic.pc1_1  = 1.0;
+    mosaic.pc1_2  = 0.0;
+    mosaic.pc2_1  = 0.0;
+    mosaic.pc2_2  = 1.0;
+    mosaic.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        mosaic.polyterms[i][0] = 0.0;
+        mosaic.polyterms[i][1] = 0.0;
+    }
+    RegisterMosaic (&mosaic);
+
+    psMetadata *headerChp = WriteCoordsToHeader (&coords);
+    psMetadata *headerMos = WriteCoordsToHeader (&mosaic);
+
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadBilevelChip (chip, headerChp);
+    ok (status, "read bilevel chip header");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    bool status = pmAstromReadBilevelMosaic (fpa, headerMos);
+    ok (status, "read bilevel fpa header");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psPlane  *onChip = psPlaneAlloc();
+    psPlane  *onFPA  = psPlaneAlloc();
+    psPlane  *onTPA  = psPlaneAlloc();
+    psSphere *onSky  = psSphereAlloc();
+
+    double rDVO, dDVO;
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            XY_to_RD (&rDVO, &dDVO, x, y, &coords);
+
+            onChip->x = x;
+            onChip->y = y;
+
+            psPlaneTransformApply (onFPA, chip->toFPA, onChip);
+            psPlaneTransformApply (onTPA, fpa->toTPA, onFPA);
+            psDeproject (onSky, onTPA, fpa->toSky);
+
+            while (onSky->r > 2*M_PI)
+                onSky->r -= 2*M_PI;
+            while (onSky->r <      0)
+                onSky->r += 2*M_PI;
+
+            // fprintf (stderr, "fpa x: %f vs %f : %f\n", rDVO, onFPA->x, rDVO - onFPA->x);
+            // fprintf (stderr, "fpa y: %f vs %f : %f\n", dDVO, onFPA->y, dDVO - onFPA->y);
+
+            ok_float(onSky->r*PM_DEG_RAD, rDVO, "coordinate match: %f vs %f (delta = %f)", onSky->r*PM_DEG_RAD, rDVO, 3600.0*(onSky->r*PM_DEG_RAD - rDVO));
+            ok_float(onSky->d*PM_DEG_RAD, dDVO, "coordinate match: %f vs %f (delta = %f)", onSky->d*PM_DEG_RAD, dDVO, 3600.0*(onSky->d*PM_DEG_RAD - dDVO));
+        }
+    }
+    psFree (onSky);
+    psFree (onTPA);
+    psFree (onFPA);
+    psFree (onChip);
+
+    skip_end();
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+
+    psFree (headerMos);
+    psFree (headerChp);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+// create a fake chip-level mosaic header
+void test3x()
+{
+    note("test pmAstrom Read,Write BilevelChip");
+    psMemId id = psMemGetId();
+
+    // build a DVO-style mosaic coordinate system
+    // chip-level data (chip -> fpa)
+    Coords coords;
+    strcpy (coords.ctype, "RA---WRP");
+    coords.crval1 = 0.0;
+    coords.crval2 = 0.0;
+    coords.crpix1 = +50.0;
+    coords.crpix2 = -20.0;
+    coords.cdelt1 = 10.0; // microns per pixel
+    coords.cdelt2 = 10.0; // microns per pixel
+    coords.pc1_1  = 1.0;
+    coords.pc1_2  = 0.0;
+    coords.pc2_1  = 0.0;
+    coords.pc2_2  = 1.0;
+    coords.Npolyterms = 2;
+    for (int i = 0; i < 7; i++) {
+        coords.polyterms[i][0] = 0.0;
+        coords.polyterms[i][1] = 0.0;
+    }
+    coords.polyterms[0][0] = 0.01; // L vs X^2
+    coords.polyterms[2][1] = 0.01; // M vs Y^2
+
+    // mosaic-level data (fpa->sky)
+    Coords mosaic;
+    strcpy (mosaic.ctype, "RA---DIS");
+    mosaic.crval1 = 0.0;
+    mosaic.crval2 = 0.0;
+    mosaic.crpix1 = 0.0;
+    mosaic.crpix2 = 0.0;
+    mosaic.cdelt1 = 1.0 / 10.0 / 3600.0; // degrees per micron
+    mosaic.cdelt2 = 1.0 / 10.0 / 3600.0; // degrees per micron
+    mosaic.pc1_1  = 1.0;
+    mosaic.pc1_2  = 0.0;
+    mosaic.pc2_1  = 0.0;
+    mosaic.pc2_2  = 1.0;
+    mosaic.Npolyterms = 0;
+    for (int i = 0; i < 7; i++) {
+        mosaic.polyterms[i][0] = 0.0;
+        mosaic.polyterms[i][1] = 0.0;
+    }
+    RegisterMosaic (&mosaic);
+
+    psMetadata *headerChp = WriteCoordsToHeader (&coords);
+    psMetadata *headerMos = WriteCoordsToHeader (&mosaic);
+
+    pmFPA *fpa = pmFPAAlloc (NULL);
+    pmChip *chip = pmChipAlloc (fpa, NULL);
+
+    bool status = pmAstromReadBilevelChip (chip, headerChp);
+    ok (status, "read bilevel chip header");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    bool status = pmAstromReadBilevelMosaic (fpa, headerMos);
+    ok (status, "read bilevel fpa header");
+    skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests");
+
+    psPlane  *onChip = psPlaneAlloc();
+    psPlane  *onFPA  = psPlaneAlloc();
+    psPlane  *onTPA  = psPlaneAlloc();
+    psSphere *onSky  = psSphereAlloc();
+
+    double rDVO, dDVO;
+    for (double x = -2000; x <= +2000; x+= 500.0) {
+        for (double y = -2000; y <= +2000; y+= 500.0) {
+            XY_to_RD (&rDVO, &dDVO, x, y, &coords);
+
+            onChip->x = x;
+            onChip->y = y;
+
+            psPlaneTransformApply (onFPA, chip->toFPA, onChip);
+            psPlaneTransformApply (onTPA, fpa->toTPA, onFPA);
+            psDeproject (onSky, onTPA, fpa->toSky);
+
+            while (onSky->r > 2*M_PI)
+                onSky->r -= 2*M_PI;
+            while (onSky->r <      0)
+                onSky->r += 2*M_PI;
+
+            // fprintf (stderr, "fpa x: %f vs %f : %f\n", rDVO, onFPA->x, rDVO - onFPA->x);
+            // fprintf (stderr, "fpa y: %f vs %f : %f\n", dDVO, onFPA->y, dDVO - onFPA->y);
+
+            ok_float(onSky->r*PM_DEG_RAD, rDVO, "coordinate match: %f vs %f (delta = %f)", onSky->r*PM_DEG_RAD, rDVO, 3600.0*(onSky->r*PM_DEG_RAD - rDVO));
+            ok_float(onSky->d*PM_DEG_RAD, dDVO, "coordinate match: %f vs %f (delta = %f)", onSky->d*PM_DEG_RAD, dDVO, 3600.0*(onSky->d*PM_DEG_RAD - dDVO));
+        }
+    }
+    psFree (onSky);
+    psFree (onTPA);
+    psFree (onFPA);
+    psFree (onChip);
+
+    skip_end();
+    skip_end();
+    psFree (fpa);
+    psFree (chip);
+
+    psFree (headerMos);
+    psFree (headerChp);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+}
+
+psMetadata *WriteCoordsToHeader (Coords *coords)
+{
+
+    char name[16];
+
+    // construct a header using coords as the input
+    psMetadata *header = psMetadataAlloc();
+
+    sprintf (name, "RA--%s", &coords[0].ctype[4]);
+    psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE1", PS_META_REPLACE, "", name);
+    sprintf (name, "DEC-%s", &coords[0].ctype[4]);
+    psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE2", PS_META_REPLACE, "", name);
+
+    // center coords (R,D)
+    psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL1", PS_META_REPLACE, "", coords[0].crval1);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL2", PS_META_REPLACE, "", coords[0].crval2);
+
+    // center coords (X,Y)
+    psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX1", PS_META_REPLACE, "", coords[0].crpix1);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX2", PS_META_REPLACE, "", coords[0].crpix2);
+
+    // degrees per pixel
+    psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT1",  PS_META_REPLACE, "", coords[0].cdelt1);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT2",  PS_META_REPLACE, "", coords[0].cdelt2);
+
+    // rotation matrix
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PC001001", PS_META_REPLACE, "", coords[0].pc1_1);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PC001002", PS_META_REPLACE, "", coords[0].pc1_2);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PC002001", PS_META_REPLACE, "", coords[0].pc2_1);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PC002002", PS_META_REPLACE, "", coords[0].pc2_2);
+
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X2Y0", PS_META_REPLACE, "", coords[0].polyterms[0][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X1Y1", PS_META_REPLACE, "", coords[0].polyterms[1][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X0Y2", PS_META_REPLACE, "", coords[0].polyterms[2][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X2Y0", PS_META_REPLACE, "", coords[0].polyterms[0][1]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X1Y1", PS_META_REPLACE, "", coords[0].polyterms[1][1]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X0Y2", PS_META_REPLACE, "", coords[0].polyterms[2][1]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X3Y0", PS_META_REPLACE, "", coords[0].polyterms[3][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X2Y1", PS_META_REPLACE, "", coords[0].polyterms[4][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X1Y2", PS_META_REPLACE, "", coords[0].polyterms[5][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X0Y3", PS_META_REPLACE, "", coords[0].polyterms[6][0]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X3Y0", PS_META_REPLACE, "", coords[0].polyterms[3][1]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X2Y1", PS_META_REPLACE, "", coords[0].polyterms[4][1]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X1Y2", PS_META_REPLACE, "", coords[0].polyterms[5][1]);
+    psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X0Y3", PS_META_REPLACE, "", coords[0].polyterms[6][1]);
+
+    psMetadataAddS32 (header, PS_LIST_TAIL, "NPLYTERM", PS_META_REPLACE, "", coords[0].Npolyterms);
+
+    return header;
+}
+
+# else
+
+    int main (void)
+{
+    plan_tests(2);
+
+    ok(true, "Skipping tests: (libdvo not available)");
+    note("pmAstrometryWCS tests compared with DVO coords routines : SKIPPED (libdvo not available)");
+
+    return exit_status();
+}
+
+# endif
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmHDU.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmHDU.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tap_pmHDU.c	(revision 22158)
@@ -0,0 +1,272 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+//#include <unistd.h>
+
+#define GENIMAGE(img,c,r,TYP, valueFcn) \
+img = psImageAlloc(c,r,PS_TYPE_##TYP); \
+for (psU32 row=0;row<r;row++) { \
+    ps##TYP* imgRow = img->data.TYP[row]; \
+    for (psU32 col=0;col<c;col++) { \
+        imgRow[col] = (ps##TYP)(valueFcn); \
+    } \
+}
+const char* fitsFilename = "tmp.fits";
+const char* fitsFilename2 = "tmp2.fits";
+
+bool createFitsFile(void)
+{
+    psFits* fitsFile = psFitsOpen(fitsFilename, "w");
+
+    if (fitsFile == NULL) {
+        diag("Could not create 'multi' FITS file");
+        return false;
+    }
+
+    psImage* image = psImageAlloc(16, 16, PS_TYPE_F32);
+
+    char extname[80];
+    for (int lcv = 0; lcv < 8; lcv++) {
+        snprintf(extname, 80, "ext-%d", lcv);
+
+        psMetadata* header = psMetadataAlloc();
+
+        psMetadataAdd(header, PS_LIST_TAIL, "MYINT",
+                      PS_DATA_S32,
+                      "psS32 Item", (psS32)lcv);
+
+        psMetadataAdd(header, PS_LIST_TAIL, "MYFLT",
+                      PS_DATA_F32,
+                      "psF32 Item", (float)(1.0f/(float)(1+lcv)));
+
+        psMetadataAdd(header, PS_LIST_TAIL, "MYDBL",
+                      PS_DATA_F64,
+                      "psF64 Item", (double)(1.0/(double)(1+lcv)));
+
+        psMetadataAdd(header, PS_LIST_TAIL, "MYBOOL",
+                      PS_DATA_BOOL,
+                      "psBool Item",
+                      (lcv%2 == 0));
+
+        psMetadataAdd(header, PS_LIST_TAIL, "MYSTR",
+                      PS_DATA_STRING,
+                      "String Item",
+                      extname);
+
+        // set the pixels in the image
+        psImageInit(image, (float)lcv);
+        if (!psFitsWriteImage(fitsFile, header, image, 0, extname)) {
+            diag("Could not write image");
+        }
+        psFree(header);
+    }
+    psFree(image);
+    psFree(fitsFile);
+
+    return true;
+}
+
+
+bool createFitsFile2(void)
+{
+    psFits* fitsFile = psFitsOpen(fitsFilename2, "w");
+
+    if (fitsFile == NULL) {
+        diag("Could not create 'multi' FITS file");
+        return false;
+    }
+
+    psImage* image = psImageAlloc(16, 16, PS_TYPE_F32);
+
+    char extname[80];
+    for (int lcv = 0; lcv < 8; lcv++) {
+        snprintf(extname, 80, "ext-%d", lcv);
+        pmHDU *hdu = pmHDUAlloc(extname);
+        hdu->header = psMetadataAlloc();
+
+        psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYINT",
+                      PS_DATA_S32,
+                      "psS32 Item", (psS32)lcv);
+
+        psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYFLT",
+                      PS_DATA_F32,
+                      "psF32 Item", (float)(1.0f/(float)(1+lcv)));
+
+        psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYDBL",
+                      PS_DATA_F64,
+                      "psF64 Item", (double)(1.0/(double)(1+lcv)));
+
+        psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYBOOL",
+                      PS_DATA_BOOL,
+                      "psBool Item",
+                      (lcv%2 == 0));
+
+        psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYSTR",
+                      PS_DATA_STRING,
+                      "String Item",
+                      extname);
+
+        // set the pixels in the image
+        psImageInit(image, (float)lcv);
+        if(!pmHDUWrite(hdu, fitsFile)) {
+            diag("Could not write header");
+            psErrorStackPrint(stdout, "THIS");
+
+exit(0);
+        }
+        if (!psFitsWriteImage(fitsFile, NULL, image, 0, extname)) {
+            diag("Could not write image");
+        }
+
+        psFree(hdu);
+    }
+    psFree(image);
+    psFree(fitsFile);
+
+    return true;
+}
+
+
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(18);
+      psError(PS_ERR_IO, true, "HEY: ERROR");
+
+    psHistogram *myHist = psHistogramAlloc(10, 5, 1);
+    psFree(myHist);
+
+    // Test pmHDUAlloc()
+    // Use a NULL extname
+    {
+        psMemId id = psMemGetId();
+        pmHDU *hdu = pmHDUAlloc(NULL);
+        ok(hdu, "pmHDUAlloc(NULL) returned non-NULL");
+        skip_start(!hdu, 7, "Skipping tests because pmHDUAlloc(NULL) returned NULL");
+        ok(hdu->blankPHU == true, "pmHDUAlloc(NULL) set hdu->blankPHU correctly");
+        ok(hdu->extname == NULL, "pmHDUAlloc(NULL) set hdu->extname correctly");
+        ok(hdu->format == NULL, "pmHDUAlloc(NULL) set hdu->format correctly");
+        ok(hdu->header == NULL, "pmHDUAlloc(NULL) set hdu->header correctly");
+        ok(hdu->images == NULL, "pmHDUAlloc(NULL) set hdu->images correctly");
+        ok(hdu->weights == NULL, "pmHDUAlloc(NULL) set hdu->weights correctly");
+        ok(hdu->masks == NULL, "pmHDUAlloc(NULL) set hdu->masks correctly");
+        psFree(hdu);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Use a non-NULL extname
+    {
+        psMemId id = psMemGetId();
+        pmHDU *hdu = pmHDUAlloc("ext-0");
+        ok(hdu, "pmHDUAlloc(extname) returned non-NULL");
+        skip_start(!hdu, 7, "Skipping tests because pmHDUAlloc(extname) returned NULL");
+        ok(hdu->blankPHU == false, "pmHDUAlloc(extname) set hdu->blankPHU correctly");
+        ok(0 == strcmp(hdu->extname, "ext-0"), "pmHDUAlloc(extname) set hdu->extname correctly");
+        ok(hdu->format == NULL, "pmHDUAlloc(extname) set hdu->format correctly");
+        ok(hdu->header == NULL, "pmHDUAlloc(extname) set hdu->header correctly");
+        ok(hdu->images == NULL, "pmHDUAlloc(extname) set hdu->images correctly");
+        ok(hdu->weights == NULL, "pmHDUAlloc(extname) set hdu->weights correctly");
+        ok(hdu->masks == NULL, "pmHDUAlloc(extname) set hdu->masks correctly");
+        psFree(hdu);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // tst_psFitsReadHeader()
+    {
+        ok(createFitsFile2(), "Created test FITS file");
+        psFits* fits = psFitsOpen(fitsFilename2,"r");
+        ok(fits != NULL, "psFitsOpen returned non-NULL on existing file");
+        int numHDUs = psFitsGetSize(fits);
+        ok(numHDUs == 8, "The test FITS file has %d HDUs", numHDUs);
+
+        for (int hdunum = 0; hdunum < numHDUs; hdunum++)
+        {
+            psMemId id = psMemGetId();
+            char extname[80];
+            snprintf(extname,80,"ext-%d",hdunum);
+            psFitsMoveExtNum(fits, hdunum, false);
+            pmHDU *hdu = pmHDUAlloc(extname);
+            bool rc = pmHDUReadHeader(hdu, fits);
+            ok(rc == true, "pmHDUReadHeader() returned TRUE");
+            ok(hdu->header != NULL &&
+               psMemCheckMetadata(hdu->header), "pmHDUReadHeader() correctly returned the hdu->header member");
+
+            // check for the extra metadata items
+            psS32 intItem = psMetadataLookupS32(NULL, hdu->header, "MYINT");
+            psF32 fltItem = psMetadataLookupF32(NULL, hdu->header, "MYFLT");
+            psF64 dblItem = psMetadataLookupF64(NULL, hdu->header, "MYDBL");
+            psMetadataItem* boolItem = psMetadataLookup(hdu->header, "MYBOOL");
+            psString strItem = psMetadataLookupStr(NULL, hdu->header, "MYSTR");
+
+            ok(intItem == hdunum, "Retrieved psS32 metadata item from file");
+            ok(fabsf(fltItem - 1.0f/(float)(1+hdunum)) <= FLT_EPSILON,
+               "Retrieved psF32 metadata item from file.  Got %f vs %f",
+               fltItem,1.0f/(float)(1+hdunum));
+            ok(abs(dblItem - 1.0/(double)(1+hdunum)) <= DBL_EPSILON,
+               "Retrieved psF64 metadata item from file.  Got %g vs %g",
+               dblItem, 1.0/(double)(1+hdunum));
+            ok(boolItem != NULL && boolItem->type == PS_DATA_BOOL,
+               "Retrieved psBool metadata item from file");
+            ok(strItem != NULL && strncmp(strItem,extname,strlen(extname)) == 0,
+               "Retrieved string metadata item from file.  Got '%s' vs '%s' (%d)",
+               strItem,extname,strlen(extname));
+            psFree(hdu);
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks (header %d)", hdunum);
+        }
+
+
+        // Call pmHDUReadHeader() with NULL pmHDU input.  Should returne false.
+        {
+            psMemId id = psMemGetId();
+//            pmHDU *hdu = pmHDUAlloc(NULL);
+            bool rc = pmHDUReadHeader(NULL, fits);
+            ok(rc == false, "pmHDUReadHeader() returned FALSE with NULL hdu input");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+        // Call pmHDUReadHeader() with NULL pmFits input.  Should returne false.
+        {
+            psMemId id = psMemGetId();
+            pmHDU *hdu = pmHDUAlloc(NULL);
+            bool rc = pmHDUReadHeader(hdu, NULL);
+            ok(rc == false, "pmHDUReadHeader() returned FALSE with NULL pmFits input");
+            psFree(hdu);
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+
+        psFree(fits);
+    }
+
+
+/* HERE
+    // tst_psFitsWriteHeader()
+    {
+        psMemId id = psMemGetId();
+        ok(createFitsFile2(), "Created 'multi' FITS file");
+
+        psMetadata* header   = psMetadataAlloc();
+        psFits*     fitsFile = psFitsOpen(fitsFilename,"a+");
+
+        // Test psFitsReadWrite generates files from psFitsWriteImage which 
+        // calls psFitsWriteHeader so these additional tests check for error conditions
+        // Attempt call function with NULL metadata
+        ok(!psFitsWriteHeader(fitsFile, NULL), "Expected return of true for NULL metadata pointer");
+        psFree(fitsFile);
+
+        // Attempt to call function with NULL fits
+        ok(!psFitsWriteHeader(NULL, header), "Expected return of true for NULL fits file pointer");
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+HERE*/
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tst_pmAstrometry.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tst_pmAstrometry.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tst_pmAstrometry.c	(revision 22158)
@@ -0,0 +1,615 @@
+/** @file  tst_pmAstrometry.c
+ *
+ *  @brief Contains the tests: pmAstrometry.[ch].  The pmxxxAlloc()
+ *  and psFree() functionality are used here.
+ *
+ *  @author GLG, MHPCC
+ *
+ *  XXX: Untested: pmFPACheckParents()
+ *  XXX: Create the pmHDU alloc/free function, test them here
+ *
+ *  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-01-26 21:10:51 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include "config.h"
+#include <math.h>
+#include <string.h>
+#include "psTest.h"
+#include "pslib_strict.h"
+#include "pmAstrometry.h"
+
+static psS32 testFPAAlloc(void);
+static psS32 testChipAlloc(void);
+static psS32 testCellAlloc(void);
+static psS32 testReadoutAlloc(void);
+
+testDescription tests[] = {
+                              {testFPAAlloc,739,"pmFPAAlloc",0,false},
+                              {testChipAlloc,740,"pmChipAlloc",0,false},
+                              {testCellAlloc,741,"pmCellAlloc",0,false},
+                              {testReadoutAlloc,742,"pmReadoutAlloc",0,false},
+                              {NULL}
+                          };
+
+#define CHIP_ALLOC_NAME "ChipName"
+#define CELL_ALLOC_NAME "CellName"
+#define MISC_NUM 32
+#define MISC_NAME "META00"
+#define MISC_NAME2 "META01"
+#define NUM_BIAS_DATA 10
+#define TEST_NUM_ROWS 32
+#define TEST_NUM_COLS 32
+
+psPlaneTransform *PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM()
+{
+    psPlaneTransform *pt = psPlaneTransformAlloc(1, 1);
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+    return(pt);
+}
+
+psPlaneDistort *PS_CREATE_4D_IDENTITY_PLANE_DISTORT()
+{
+    psPlaneDistort *pd = psPlaneDistortAlloc(1, 1, 1, 1);
+    pd->x->coeff[1][0][0][0] = 1.0;
+    pd->y->coeff[0][1][0][0] = 1.0;
+    return(pd);
+}
+
+/******************************************************************************
+generateSimpleFPA(): This function generates a pmFPA data structure and then
+populates its members with real data.  We do this to ensure that the data is
+later being psFree()'ed correctly.
+ *****************************************************************************/
+pmFPA *generateSimpleFPA()
+{
+    psBool rc;
+    pmFPA* fpa = pmFPAAlloc(psMetadataAlloc());
+
+    if (fpa == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc() returned a NULL.");
+        return(NULL);
+    }
+
+    //
+    // Test and create camera metadata.
+    //
+    if (fpa->camera == NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: fpa->camera is NULL.");
+        psFree(fpa);
+        return(NULL);
+    } else {
+        rc = psMetadataAddS32((psMetadata *) fpa->camera, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+        if (rc == false) {
+            psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: could not add metadata to fpa->camera.");
+            psFree(fpa);
+            return(NULL);
+        }
+        psS32 tmpS32 = psMetadataLookupS32(&rc, fpa->camera, MISC_NAME);
+        if ((rc == false) || (tmpS32 != MISC_NUM)) {
+            psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: could not read metadata from fpa->camera.");
+            psFree(fpa);
+            return(NULL);
+        }
+    }
+
+    //
+    // Create various transforms and projections.
+    //
+    fpa->fromTangentPlane = PS_CREATE_4D_IDENTITY_PLANE_DISTORT();
+    fpa->toTangentPlane = PS_CREATE_4D_IDENTITY_PLANE_DISTORT();
+    fpa->projection = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+
+    //
+    // Ensure fpa concepts metadata was allocated properly.
+    //
+    if (fpa->concepts == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc did not set fpa->concepts.");
+        psFree(fpa);
+        return(NULL);
+    } else {
+        rc = psMetadataAddS32(fpa->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+        if (rc == false) {
+            psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: could not add data to fpa->concepts.");
+            psFree(fpa);
+            return(NULL);
+        }
+        psS32 tmpS32 = psMetadataLookupS32(&rc, fpa->concepts, MISC_NAME);
+        if ((rc == false) || (tmpS32 != MISC_NUM)) {
+            psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: could not read metadata from fpa->concepts.");
+            psFree(fpa);
+            return(NULL);
+        }
+    }
+
+    //
+    // Create ->analysis metadata.
+    //
+    fpa->analysis = psMetadataAlloc();
+    rc = psMetadataAddS32(fpa->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    //
+    // We test the fpa->chips array later.
+    //
+
+    //
+    // How to test the p_pmHDU *hdu member?
+    //
+
+    //
+    // Create ->phu metadata.
+    //
+    fpa->phu = psMetadataAlloc();
+    rc = psMetadataAddS32(fpa->phu, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    return(fpa);
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+    psLogSetFormat("HLNM");
+
+    return ! runTestSuite(stderr,"pmAstrometry",tests,argc,argv);
+}
+
+/******************************************************************************
+testFPAAlloc()
+    1: We ensure that pmFPAAlloc() properly allocates a pmFPA struct.
+    2: We populate the members with real data to ensure they are being
+       free'ed correctly.
+ *****************************************************************************/
+static psS32 testFPAAlloc(void)
+{
+    psMetadata *camera = psMetadataAlloc();
+    pmFPA* fpa = pmFPAAlloc(camera);
+
+    if (fpa == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc() returned a NULL.");
+        return 1;
+    }
+
+    if (fpa->fromTangentPlane != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc did not set ->fromTangentPlane to NULL.");
+        return 2;
+    }
+
+    if (fpa->toTangentPlane != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc did not set ->toTangentPlane to NULL.");
+        return 3;
+    }
+    if (fpa->projection != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc did not set ->projection to NULL.");
+        return 4;
+    }
+
+    if (fpa->concepts == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc did not set ->concepts.");
+        return 5;
+    }
+
+    if (fpa->analysis != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc did not set ->analysis to NULL.");
+        return 6;
+    }
+
+    if (fpa->camera != camera) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc did not set ->camera.");
+        return 7;
+    }
+
+    if (fpa->chips == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc did not set ->chips.");
+        return 8;
+    }
+
+    if (fpa->hdu != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc did not set ->hdu to NULL.");
+        return 9;
+    }
+    psFree(fpa);
+
+    //
+    // Populate the pmFPA struct with real data to ensure they were
+    // psFree()'ed correctly.
+    //
+    fpa = generateSimpleFPA();
+    if (fpa == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: generateSimpleFPA() returned NULL.");
+        return(15);
+    }
+    psFree(fpa);
+
+    return(0);
+}
+
+/******************************************************************************
+generateSimpleChip(): This function generates a pmChip data structure and then
+populates its members with real data.  We do this to ensure that the data is
+later being psFree()'ed correctly.
+ *****************************************************************************/
+pmChip *generateSimpleChip(pmFPA *fpa)
+{
+    psBool rc;
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    if (chip == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmChipAlloc returned a NULL.");
+        return(NULL);
+    }
+    chip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    chip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    //
+    // We already ensured that chip->concepts was working properly.
+    //
+
+    //
+    // Create ->analysis metadata.
+    //
+    chip->analysis = psMetadataAlloc();
+    rc = psMetadataAddS32(chip->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    //
+    // We test the chip->cells array later.
+    //
+
+    //
+    // How to test the p_pmHDU *hdu member?
+    //
+
+    return(chip);
+}
+
+static psS32 testChipAlloc(void)
+{
+    pmFPA* fpa = generateSimpleFPA();
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    if (chip == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmChipAlloc returned a NULL.");
+        return 1;
+    }
+
+    if (chip->col0 != -1) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: chip->col0 set improperly.\n");
+        return 5;
+    }
+
+    if (chip->row0 != -1) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: chip->row0 set improperly.\n");
+        return 6;
+    }
+
+    if (chip->toFPA != NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: chip->toChip set improperly.\n");
+        return 7;
+    }
+
+    if (chip->fromFPA != NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: chip->toFPA set improperly.\n");
+        return 8;
+    }
+
+    if (chip->concepts == NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: chip->concepts set improperly.\n");
+        return 21;
+    } else {
+        psMetadataItem *tmpMeta = psMetadataLookup(chip->concepts, "CHIP.NAME");
+        if (0 != strcmp((char *) tmpMeta->data.V, CHIP_ALLOC_NAME)) {
+            psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: The metadata was set improperly.\n");
+            return (32);
+        }
+        // XXX: Code a test to ensure the metadata has the correct type
+    }
+
+    if (chip->analysis != NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: chip->analysis set improperly.\n");
+        return 10;
+    }
+
+    if (chip->cells == NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: chip->cells set improperly.\n");
+        return 22;
+    }
+
+    if (chip->parent != fpa) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: chip->parent set improperly.\n");
+        return 23;
+    }
+
+    if (chip->valid != false) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: chip->valid set improperly.\n");
+        return 24;
+    }
+
+    if (chip->hdu != NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: chip->hdu set improperly.\n");
+        return 25;
+    }
+    psFree(fpa);
+
+    //
+    // Populate the pmChip struct with real data to ensure they were
+    // psFree()'ed correctly.
+    //
+    fpa = generateSimpleFPA();
+    chip = generateSimpleChip(fpa);
+    psFree(fpa);
+
+    return(0);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.  We do this to ensure that the data is
+later being psFree()'ed correctly.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmFPA *fpa, pmChip *chip)
+{
+    psBool rc;
+    pmCell *cell = pmCellAlloc(chip, (psMetadata *) fpa->camera, CELL_ALLOC_NAME);
+    if (cell == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmCellAlloc returned a NULL.");
+        return(NULL);
+    }
+    cell->toChip = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    cell->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    cell->toSky = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    //
+    // We already ensured that cell->concepts was working properly.
+    //
+
+    //
+    // Test camera metadata.
+    //
+    if (cell->camera == NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: cell->camera is NULL.");
+        psFree(fpa);
+        return(NULL);
+    } else {
+        rc = psMetadataAddS32((psMetadata *) cell->camera, PS_LIST_HEAD, MISC_NAME2, 0, NULL, MISC_NUM);
+        if (rc == false) {
+            psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: could not add metadata to cell->camera.");
+            psFree(fpa);
+            return(NULL);
+        }
+        psS32 tmpS32 = psMetadataLookupS32(&rc, cell->camera, MISC_NAME2);
+        if ((rc == false) || (tmpS32 != MISC_NUM)) {
+            psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: could not read metadata from cell->camera.");
+            psFree(fpa);
+            return(NULL);
+        }
+    }
+
+    //
+    // Create ->analysis metadata.
+    //
+    cell->analysis = psMetadataAlloc();
+    rc = psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    //
+    // We test the cell->readouts array later.
+    //
+
+    //
+    // How to test the p_pmHDU *hdu member?
+    //
+
+    return(cell);
+}
+
+static psS32 testCellAlloc(void)
+{
+    pmFPA* fpa = generateSimpleFPA();
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    pmCell *cell = pmCellAlloc(chip, (psMetadata *) fpa->camera, CELL_ALLOC_NAME);
+    if (cell == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmCellAlloc returned a NULL.n");
+        return 3;
+    }
+
+    if (cell->col0 != -1) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: cell->col0 set improperly.\n");
+        return 5;
+    }
+
+    if (cell->row0 != -1) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: cell->row0 set improperly.\n");
+        return 6;
+    }
+
+    if (cell->toChip != NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: cell->toChip set improperly.\n");
+        return 7;
+    }
+
+    if (cell->toFPA != NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: cell->toFPA set improperly.\n");
+        return 8;
+    }
+
+    if (cell->toSky != NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: cell->toSky set improperly.\n");
+        return 9;
+    }
+
+    if (cell->concepts == NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: cell->concepts set improperly.\n");
+        return 21;
+    } else {
+        psMetadataItem *tmpMeta = psMetadataLookup(cell->concepts, "CELL.NAME");
+        if (0 != strcmp((char *) tmpMeta->data.V, CELL_ALLOC_NAME)) {
+            psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: The metadata was set improperly.\n");
+            return (32);
+        }
+        // XXX: Code a test to ensure the metadata has the correct type
+    }
+
+    if (cell->camera != fpa->camera) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: cell->camera set improperly.\n");
+        return 20;
+    }
+
+    if (cell->analysis != NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: cell->analysis set improperly.\n");
+        return 10;
+    }
+
+    if (cell->readouts == NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: cell->readouts set improperly.\n");
+        return 22;
+    }
+
+    if (cell->parent != chip) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: cell->parent set improperly.\n");
+        return 23;
+    }
+
+    if (cell->valid != false) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: cell->valid set improperly.\n");
+        return 24;
+    }
+
+    if (cell->hdu != NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: cell->hdu set improperly.\n");
+        return 27;
+    }
+    psFree(fpa);
+
+    //
+    // Populate the pmCell struct with real data to ensure they were
+    // psFree()'ed correctly.
+    //
+    fpa = generateSimpleFPA();
+    chip = generateSimpleChip(fpa);
+    cell = generateSimpleCell(fpa, chip);
+    psFree(fpa);
+
+    return(0);
+}
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.  We do this to ensure that the data is
+later being psFree()'ed correctly.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmFPA *fpa, pmChip *chip, pmCell *cell)
+{
+    psBool rc;
+    pmReadout *readout = pmReadoutAlloc(cell);
+    if (readout == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmReadoutAlloc returned a NULL.");
+        return(NULL);
+    }
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+
+    //
+    // Create a psList of bias data.
+    //
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        if (readout->bias == NULL) {
+            readout->bias = psListAlloc(tmpImage);
+        } else {
+            psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        }
+    }
+
+    //
+    // Test readout->analysis metadata.
+    //
+    if (readout->analysis == NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: readout->analysis is NULL.");
+        psFree(fpa);
+        return(NULL);
+    } else {
+        rc = psMetadataAddS32((psMetadata *) readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+        if (rc == false) {
+            psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: could not add metadata to readout->analysis.");
+            psFree(fpa);
+            return(NULL);
+        }
+    }
+
+    return(readout);
+}
+
+
+static psS32 testReadoutAlloc(void)
+{
+    pmFPA* fpa = generateSimpleFPA();
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    pmCell *cell = pmCellAlloc(chip, (psMetadata *) fpa->camera, CELL_ALLOC_NAME);
+    pmReadout *readout = pmReadoutAlloc(cell);
+    if (readout == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmReadoutAlloc returned a NULL.\n");
+        return 4;
+    }
+
+    if (readout->col0 != -1) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: pmReadout->col0 set improperly.\n");
+        return 5;
+    }
+
+    if (readout->row0 != -1) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: pmReadout->row0 set improperly.\n");
+        return 6;
+    }
+
+    if (readout->colBins != -1) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: pmReadout->colBins set improperly.\n");
+        return 7;
+    }
+
+    if (readout->rowBins != -1) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: pmReadout->colBins set improperly.\n");
+        return 8;
+    }
+
+    if (readout->image != NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: pmReadout->image set improperly.\n");
+        return 10;
+    }
+
+    if (readout->mask != NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: pmReadout->mask set improperly.\n");
+        return 12;
+    }
+
+    if (readout->weight != NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: pmReadout->weight set improperly.\n");
+        return 14;
+    }
+
+    if (readout->bias != NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: pmReadout->bias set improperly.\n");
+        return 16;
+    }
+
+    if (readout->analysis == NULL) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: pmReadout->analysis set improperly.\n");
+        return 18;
+    }
+
+    if (readout->parent != cell) {
+        psLogMsg(__func__, PS_LOG_ERROR, "TEST ERROR: pmReadout->parent set improperly.\n");
+        return 20;
+    }
+    psFree(fpa);
+
+    //
+    // Populate the pmReadout struct with real data to ensure they were
+    // psFree()'ed correctly.
+    //
+    fpa = generateSimpleFPA();
+    chip = generateSimpleChip(fpa);
+    cell = generateSimpleCell(fpa, chip);
+    readout = generateSimpleReadout(fpa, chip, cell);
+    psFree(fpa);
+
+    return(0);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tst_pmAstrometry01.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tst_pmAstrometry01.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/astrom/tst_pmAstrometry01.c	(revision 22158)
@@ -0,0 +1,675 @@
+/** @file  tst_psAstrometry01.c
+*
+*  @brief This code will test the pmFPA hierarchy transform code in psAstrometry.[ch]
+*
+*  @author GLG, MHPCC
+*
+*  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2006-03-06 22:53:47 $
+*
+* XXX: Add tests were the coordinate does not transform to any legitimate cell
+* or chip, or FPA, or whatever.
+*
+* XXX: For each function, add tests for bad input parameters, as well as failed transforms.
+*
+* XXX: Must test pmFPASelectChip() and pmFPAExcludeChip().
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+#include "config.h"
+#include <math.h>
+#include <string.h>
+#include "psTest.h"
+#include "pslib_strict.h"
+#include "pmAstrometry.h"
+static psS32 test3( void );
+static psS32 test4( void );
+static psS32 test5( void );
+
+testDescription tests[] = {
+                              {test3, 666, "pmAstrometry focal plane transformations", 0, false},
+                              {test4, 667, "pmCheckParents()", 0, false},
+                              {test5, 668, "pmFPASelectChip() and pmFPAExcludeChip()", 0, false},
+                              {NULL}
+                          };
+
+psS32 currentId = 0;
+psS32 memLeaks = 0;
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetLevel( PS_LOG_INFO );
+    psLogSetFormat("HLNM");
+
+    return ( ! runTestSuite( stderr, "psAstrometry", tests, argc, argv ) );
+}
+
+#define PS_PERCENT_COMPARE(X, Y, PERCENT_FRACTION) (fabs((Y)-(X))/fabs(X) < (PERCENT_FRACTION))
+#define VERBOSE 0
+#define NUM_READOUTS 1
+#define READOUT_NUM_ROWS 10
+#define READOUT_NUM_COLS 10
+
+#define NUM_CELLS 4
+#define CELL_GAP 2
+#define CELL_WIDTH READOUT_NUM_COLS
+#define CELL_HEIGHT READOUT_NUM_ROWS
+#define CELL_MIN_X 0
+#define CELL_MAX_X CELL_HEIGHT
+#define CELL_MIN_Y 0
+#define CELL_MAX_Y CELL_WIDTH
+
+#define NUM_CHIPS 2
+#define CHIP_GAP 2
+#define CHIP_MIN_X 0
+#define CHIP_MAX_X CELL_HEIGHT
+#define CHIP_MIN_Y 0
+#define CHIP_MAX_Y ((NUM_CELLS * CELL_WIDTH) + ((NUM_CELLS) * CELL_GAP))
+#define CHIP_WIDTH CHIP_MAX_Y
+#define CHIP_HEIGHT CHIP_MAX_X
+
+#define NUM_FPAS 1
+#define FPA_MIN_X 0
+#define FPA_MAX_X CHIP_HEIGHT
+#define FPA_MIN_Y 0
+#define FPA_MAX_Y (((NUM_CHIPS) * CHIP_WIDTH) + (((NUM_CHIPS)-1) * CHIP_GAP))
+
+#define PROJECTION_SCALE_X 1.0
+#define PROJECTION_SCALE_Y 1.0
+
+psPlaneTransform *PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM()
+{
+    psPlaneTransform *pt = psPlaneTransformAlloc(1, 1);
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+    return(pt);
+}
+
+psPlaneDistort *PS_CREATE_4D_IDENTITY_PLANE_DISTORT()
+{
+    psPlaneDistort *pd = psPlaneDistortAlloc(1, 1, 1, 1);
+    pd->x->coeff[1][0][0][0] = 1.0;
+    pd->y->coeff[0][1][0][0] = 1.0;
+    return(pd);
+}
+
+/******************************************************************************
+genSystem(): This routine will create a system of FPAs/Chips/Cells/Readouts.  For
+simplicity, an FPA is defined as a linear array of chips, and a chip is
+defined as a linear array of cells, both in the y (cols) direction.  The
+transforms between the various layers take into account the cell/chip and
+the boundaries between each.
+ *****************************************************************************/
+pmFPA *genSystem()
+{
+    //
+    // Create top pmFPA structure.
+    //
+    const psMetadata *camera = psMetadataAlloc();
+    pmFPA* myFPA = pmFPAAlloc(camera);
+    if (myFPA == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc() returned a NULL.\n");
+        return NULL;
+    }
+    myFPA->fromTangentPlane = PS_CREATE_4D_IDENTITY_PLANE_DISTORT();
+    myFPA->toTangentPlane = PS_CREATE_4D_IDENTITY_PLANE_DISTORT();
+    myFPA->projection = psProjectionAlloc(0.0,0.0,PROJECTION_SCALE_X,PROJECTION_SCALE_X,PS_PROJ_TAN);
+
+    myFPA->chips = psArrayRealloc(myFPA->chips, NUM_CHIPS);
+    for (psS32 chipID=0 ; chipID<NUM_CHIPS ; chipID++) {
+        pmChip *myChip = pmChipAlloc(myFPA, "ChipName");
+        if (myChip == NULL) {
+            psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmChipAlloc() returned a NULL.\n");
+            return NULL;
+        }
+        myFPA->chips->data[chipID] = (psPtr *) myChip;
+        myChip->row0 = 0;
+        myChip->col0 = chipID * (CHIP_WIDTH + CHIP_GAP);
+
+        // We create the transforms between the chip and FPA.  The
+        // transform is a simple identity transform.
+        myChip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+        myChip->toFPA->y->coeff[0][0] = (psF64) myChip->col0;
+        myChip->toFPA->y->coeff[1][1] = 0.0;
+        myChip->toFPA->x->coeff[0][0] = (psF64) myChip->row0;
+        myChip->toFPA->x->coeff[1][1] = 0.0;
+
+        myChip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+        myChip->fromFPA->y->coeff[0][0] = (psF64) (- myChip->col0);
+        myChip->fromFPA->y->coeff[1][1] = 0.0;
+        myChip->fromFPA->x->coeff[0][0] = (psF64) (- myChip->row0);
+        myChip->fromFPA->x->coeff[1][1] = 0.0;
+
+        myChip->cells = psArrayRealloc(myChip->cells, NUM_CELLS);
+        for (psS32 cellID=0 ; cellID<NUM_CELLS ; cellID++) {
+            pmCell *myCell = pmCellAlloc(myChip, NULL, "CellName");
+            if (myCell == NULL) {
+                psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmCellAlloc() returned a NULL.\n");
+                return NULL;
+            }
+            myChip->cells->data[cellID] = (psPtr *) myCell;
+            myCell->row0 = 0;
+            myCell->col0 = cellID * (CELL_WIDTH + CELL_GAP);
+            myCell->toChip = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+            myCell->toChip->y->coeff[0][0] = (psF64) myCell->col0;
+            myCell->toChip->y->coeff[1][1] = 0.0;
+            myCell->toChip->x->coeff[0][0] = (psF64) myCell->row0;
+            myCell->toChip->x->coeff[1][1] = 0.0;
+
+            myCell->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+            myCell->toFPA->y->coeff[0][0] = (psF64) (myCell->col0 + myChip->col0);
+            myCell->toFPA->y->coeff[1][1] = 0.0;
+            myCell->toFPA->x->coeff[0][0] = (psF64) (myCell->row0 + myChip->row0);
+            myCell->toFPA->x->coeff[1][1] = 0.0;
+
+            myCell->toSky = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+            myCell->toSky->y->coeff[0][0] = myCell->toFPA->y->coeff[0][0];
+            myCell->toSky->y->coeff[1][1] = 0.0;
+            myCell->toSky->x->coeff[0][0] = myCell->toFPA->x->coeff[0][0];
+            myCell->toSky->x->coeff[1][1] = 0.0;
+
+            myCell->readouts = psArrayRealloc(myCell->readouts, NUM_READOUTS);
+            for (psS32 readoutID=0 ; readoutID<NUM_READOUTS ; readoutID++) {
+                pmReadout *myReadout = pmReadoutAlloc(myCell);
+                if (myReadout == NULL) {
+                    psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmReadoutAlloc() returned a NULL.\n");
+                    return NULL;
+                }
+                myCell->readouts->data[readoutID] = (psPtr *) myReadout;
+                myReadout->image = psImageAlloc(READOUT_NUM_COLS, READOUT_NUM_ROWS, PS_TYPE_F32);
+                for (psS32 row=0;row<READOUT_NUM_ROWS;row++) {
+                    for(psS32 col=0;col<READOUT_NUM_COLS;col++) {
+                        myReadout->image->data.F32[row][col] = (psF32) ((chipID * (CHIP_WIDTH + CHIP_GAP)) +
+                                                               (cellID * (CELL_WIDTH + CELL_GAP)));
+                    }
+                }
+                myReadout->row0 = myCell->row0;
+                myReadout->col0 = myCell->col0;
+                myReadout->rowBins = 0;
+                myReadout->colBins = 0;
+            }
+            if (VERBOSE) {
+                printf("\n\n\n\nFor chip %d cell %d the cell->toFPA transform is:\n", chipID, cellID);
+                PS_PRINT_PLANE_TRANSFORM(myCell->toFPA);
+                printf("\n\n\n\nFor chip %d cell %d the cell->toChip transform is:\n", chipID, cellID);
+                PS_PRINT_PLANE_TRANSFORM(myCell->toChip);
+                printf("\n\n\n\nFor chip %d cell %d the cell->toSky transform is:\n", chipID, cellID);
+                PS_PRINT_PLANE_TRANSFORM(myCell->toSky);
+            }
+        }
+        if (VERBOSE) {
+            printf("\n\n\n\nFor chip %d the chip->toFPA transform is:\n", chipID);
+            PS_PRINT_PLANE_TRANSFORM(myChip->toFPA);
+            printf("\n\n\n\nFor chip %d the chip->fromFPA transform is:\n", chipID);
+            PS_PRINT_PLANE_TRANSFORM(myChip->fromFPA);
+        }
+    }
+
+    return(myFPA);
+}
+
+
+/******************************************************************************
+This routine tests many Astrometry functions.  It loops through all valid
+pixels of all cells of all chips and computes the corresponding (x,y)
+coordinates in the FPA plane.  It then calls the pmChipInFPA() then
+pmCellInFPA() with the FPA coordinate and determines the chip/cell that that
+coordinate corresponds to.  Following that it does a variety of tests on the
+various functions that tharnsform coordinates within the pmFPA hierarchy.
+ 
+List of tested functions:
+    pmCellInFPA()  yes
+    pmChipInFPA()  yes
+    pmCellInChip()  yes
+ 
+    pmCoordCellToFPA()  yes
+    pmCoordChipToFPA()  yes
+    pmCoordFPAToChip()  yes
+    pmCoordCellToChip()  yes
+    pmCoordChipToCell()  yes
+ 
+    pmCoordFPAToTP()  yes
+    pmCoordTPToFPA()  yes
+ 
+    pmCoordTPToSky()  yes
+    pmCoordSkyToTP()  yes
+    pmCoordSkyToCell()  yes
+    pmCoordCellToSky()  yes
+    pmCoordCellToSkyQuick() yes
+    pmCoordSkyToCellQuick() yes
+ *****************************************************************************/
+psS32 test3( void )
+{
+    psS32 x;
+    psS32 y;
+    psPlane fpaCoord;
+    pmFPA *myFPA = genSystem();
+    pmCell *myCell = NULL;
+    psPlane chipCoord;
+    psPlane cellCoord;
+    psPlane testCoord;
+    psSphere *skyCoord = psSphereAlloc();
+    // XXX: This code causes a seg fault.
+    //    psSphere skyTmp;
+    //    psMemCheckType(PS_DATA_SPHERE, &skyTmp);
+    psPlane tpCoord;
+    psS32 testStatus = 0;
+
+    //
+    // I'm not convinced that the p_psProject() and p_psDeproject() functions work
+    // correctly.  If we project a set of coordinates over a wide range of (R, D)
+    // values, then deproject them, the original (R, D) values are only produced
+    // when D is larger than 0.  This code demonstrates that.  I also created tests
+    // that currently fail in tst_psCoord01.c.  I have a workaround in the function
+    // XXXDeproject() in pmAstrometry.c.
+    //
+    if (0) {
+        // This loop goes from (R, D) -> (X, Y) -> (R, D)
+        psPlane planeCoord01;
+        psSphere skyCoord01;
+        psSphere skyCoord02;
+        #define DEG_INC 15.0
+
+        for (psF32 R = -90.0 ; R <= 90.0 ; R+= DEG_INC) {
+            for (psF32 D = -90.0 ; D <= 90.0 ; D+= DEG_INC) {
+                if ((fabs(R) != 90.0) && (fabs(D) != 90.0)) {
+                    skyCoord01.r = DEG_TO_RAD(R);
+                    skyCoord01.d = DEG_TO_RAD(D);
+                    p_psProject(&planeCoord01, &skyCoord01, myFPA->projection);
+                    p_psDeproject(&skyCoord02, &planeCoord01, myFPA->projection);
+                    printf("(%.2fr %.2fd) (%.2fr %.2fd) -> (%.2f %.2f) -> (%.2fr %.2fd)", R, D,
+                           skyCoord01.r, skyCoord01.d,
+                           planeCoord01.x, planeCoord01.y,
+                           skyCoord02.r, skyCoord02.d);
+                    if ((fabs(skyCoord01.r - skyCoord02.r) < FLT_EPSILON) &&
+                            (fabs(skyCoord01.d - skyCoord02.d) < FLT_EPSILON)) {
+                        printf(": CORRECT\n");
+                    } else {
+                        printf(": WRONG\n");
+                    }
+                }
+            }
+        }
+        psFree(myFPA);
+        return(0);
+    }
+    if (0) {
+        // This loop goes from (X, Y) -> (R, D) -> (X, Y)
+        #define SPACE_INC 4.0
+        for(testCoord.x=-CELL_HEIGHT;testCoord.x<=CELL_HEIGHT;testCoord.x+=SPACE_INC)
+        {
+            for (testCoord.y=-CELL_WIDTH;testCoord.y<=CELL_WIDTH;testCoord.y+=SPACE_INC) {
+                psPlane planeCoord01;
+                psPlane planeCoord02;
+                psSphere skyCoord01;
+                psSphere skyCoord02;
+                p_psDeproject(&skyCoord01, &testCoord, myFPA->projection);
+                p_psProject(&planeCoord01, &skyCoord01, myFPA->projection);
+                p_psDeproject(&skyCoord02, &planeCoord01, myFPA->projection);
+                p_psProject(&planeCoord02, &skyCoord02, myFPA->projection);
+                printf("Plane: (%.2f %.2f) -> (%.2fr %.2fd) -> (%.2f %.2f)\n",
+                       testCoord.x, testCoord.y,
+                       skyCoord01.r, skyCoord01.d,
+                       planeCoord01.x, planeCoord01.y);
+                /*
+                                printf("Plane: (%.2f %.2f) -> (%.2f %.2f) -> (%.2f %.2f)\n",
+                                        testCoord.x, testCoord.y, planeCoord01.x, planeCoord01.y,
+                                        planeCoord02.x, planeCoord02.y);
+                                printf("Sphere: (%.2f %.2f) -> (%.2f %.2f)\n",
+                                        skyCoord01.r, skyCoord01.d, skyCoord02.r, skyCoord02.d);
+                                printf("Plane: (%.2f %.2f) -> (%.2fd %.2fr) -> (%.2f %.2f) -> (%.2fd %.2fr) -> (%.2f %.2f)\n",
+                                        testCoord.x, testCoord.y,
+                                        skyCoord01.r, skyCoord01.d,
+                                        planeCoord01.x, planeCoord01.y,
+                                        skyCoord02.r, skyCoord02.d,
+                                        planeCoord02.x, planeCoord02.y);
+                */
+            }
+        }
+        psFree(myFPA);
+        return(0);
+    }
+    //
+    // We iterate through all cells on all chips on the fpa.  We determine
+    // the expected fpaCcoord.
+    //
+
+    for (psS32 chip=0;chip<NUM_CHIPS;chip++) {
+        for (psS32 cell=0;cell<NUM_CELLS;cell++) {
+            for(x=0;x<CELL_HEIGHT;x++) {
+                for (y=0;y<CELL_WIDTH;y++) {
+                    fpaCoord.x = (psF64) x;
+                    fpaCoord.y = (psF64) (y + (chip * (CHIP_WIDTH + CHIP_GAP)) +
+                                          (cell * (CELL_WIDTH + CELL_GAP)));
+                    if (VERBOSE) {
+                        printf("------------------ (%.2f, %.2f) ------------------\n", fpaCoord.x, fpaCoord.y);
+                        printf("(chip, cell, x, y) is (%d, %d, %d, %d)\n", chip, cell, x, y);
+                    }
+                    pmChip* tmpChip = pmChipInFPA(&fpaCoord, myFPA);
+                    myCell = pmCellInFPA(&fpaCoord, myFPA);
+
+                    if ((myCell == NULL) || (tmpChip == NULL)) {
+                        if (tmpChip == NULL) {
+                            printf("TEST ERROR: pmChipInFPA() returned NULL\n");
+                            testStatus = 1;
+                        } else if (myCell == NULL) {
+                            printf("TEST ERROR: pmCellInFPA(): returned NULL\n");
+                            testStatus = 1;
+                        }
+                    } else {
+                        pmCoordFPAToChip(&chipCoord, &fpaCoord, tmpChip);
+                        pmCoordChipToCell(&cellCoord, &chipCoord, myCell);
+
+                        if (x != (psS32) cellCoord.x) {
+                            printf("TEST ERROR: pmCoordFPAToChip()->pmCoordChipToCell(): x coord was %d (%f), should be %d\n", (psS32) cellCoord.x, cellCoord.x, x);
+                            testStatus = 1;
+                        }
+                        if (y != (psS32) cellCoord.y) {
+                            printf("TEST ERROR: pmCoordFPAToChip()->pmCoordChipToCell(): y coord was %d (%f), should be %d\n", (psS32) cellCoord.y, cellCoord.y, y);
+                            testStatus = 1;
+                        }
+
+                        pmCoordCellToChip(&testCoord, &cellCoord, myCell);
+                        if (fabs(testCoord.x - chipCoord.x) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordCellToChip() x coord was %.2f, should be %d\n", cellCoord.x, x);
+                            testStatus = 1;
+                        }
+                        if (fabs(testCoord.y - chipCoord.y) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordCellToChip() y coord was %.2f, should be %d\n", cellCoord.y, y);
+                            testStatus = 1;
+                        }
+
+                        pmCell *myCell2 = pmCellInChip(&chipCoord, tmpChip);
+                        if (myCell2 != myCell) {
+                            printf("TEST ERROR: pmCellInChip() != pmCellInChip(pmChipInFPA()) (%p %p)\n", myCell2, myCell);
+                            testStatus = 1;
+                        }
+
+                        pmCoordChipToFPA(&testCoord, &chipCoord, tmpChip);
+                        if (fabs(testCoord.x - x) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordChipToFPA() x coord was %.2f, should be %d\n", cellCoord.x, x);
+                            testStatus = 1;
+                        }
+                        if (fabs(testCoord.y - fpaCoord.y) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordChipToFPA() y coord was %.2f, should be %.2f\n", cellCoord.y, fpaCoord.y);
+                            testStatus = 1;
+                        }
+
+                        pmCoordFPAToTP(&testCoord, &fpaCoord, 0.0, 0.0, myFPA);
+                        if (fabs(testCoord.x - fpaCoord.x) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordFPAToTP() x coord was %.2f, should be %d\n", cellCoord.x, x);
+                            testStatus = 1;
+                        }
+                        if (fabs(testCoord.y - fpaCoord.y) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordFPAToTP() y coord was %.2f, should be %d\n", cellCoord.y, y);
+                            testStatus = 1;
+                        }
+
+                        //
+                        // Test pmCoordTPToSky() -> pmCoordSkyToTP()
+                        //
+                        if (1) {
+                            psSphere *rc = pmCoordTPToSky(skyCoord, &testCoord, myFPA->projection);
+                            if (rc == NULL) {
+                                printf("pmCoordTPToSky() failed.\n");
+                            } else {
+                                psPlane *rc = pmCoordSkyToTP(&tpCoord, skyCoord, myFPA->projection);
+                                if (rc == NULL) {
+                                    printf("pmCoordSkyToTP() failed.\n");
+                                } else {
+                                    if (fabs(testCoord.x - tpCoord.x) > FLT_EPSILON) {
+                                        printf("TEST ERROR: pmCoordTPToSky()/pmCoordSkyToTP() x coord was %.2f, should be %.2f\n", tpCoord.x, testCoord.x);
+                                        testStatus = 1;
+                                    }
+                                    if (fabs(testCoord.y - tpCoord.y) > FLT_EPSILON) {
+                                        printf("TEST ERROR: pmCoordTPToSky()/pmCoordSkyToTP() y coord was %.2f, should be %.2f\n", tpCoord.y, testCoord.y);
+                                        testStatus = 1;
+                                    }
+                                    if (VERBOSE) {
+                                        printf("(%.2f %.2f) -> (%.2f %.2f) -> (%.2f %.2f)\n", testCoord.x, testCoord.y, skyCoord->r, skyCoord->d, tpCoord.x, tpCoord.y);
+                                    }
+                                }
+                            }
+                        }
+
+                        //
+                        // Test pmCoordCellToSky() -> pmCoordSkyToCell()
+                        //
+                        if (1) {
+                            psPlane tmpCellCoord;
+                            psSphere *rc = pmCoordCellToSky(skyCoord, &cellCoord, 0.0, 0.0, myCell);
+                            if (rc == NULL) {
+                                printf("pmCoordCellToSky() failed.\n");
+                            } else {
+                                psPlane *rc = pmCoordSkyToCell(&tmpCellCoord, skyCoord, 0.0, 0.0, myCell);
+                                if (rc == NULL) {
+                                    printf("pmCoordSkyToCell() failed.\n");
+                                } else {
+                                    if (fabs(cellCoord.x - tmpCellCoord.x) > FLT_EPSILON) {
+                                        printf("TEST ERROR: pmCoordCellToSky()/pmCoordSkyToCell() x coord was %.2f, should be %.2f\n", tmpCellCoord.x, cellCoord.x);
+                                        testStatus = 1;
+                                    }
+                                    if (fabs(cellCoord.y - tmpCellCoord.y) > FLT_EPSILON) {
+                                        printf("TEST ERROR: pmCoordCellToSky()/pmCoordSkyToCell() y coord was %.2f, should be %.2f\n", tmpCellCoord.y, cellCoord.y);
+                                        testStatus = 1;
+                                    }
+                                    if (VERBOSE) {
+                                        printf("(%.2f %.2f) -> (%.2f %.2f) -> (%.2f %.2f)\n", testCoord.x, testCoord.y, skyCoord->r, skyCoord->d, tmpCellCoord.x, tmpCellCoord.y);
+                                    }
+                                }
+                            }
+                        }
+
+                        //
+                        // Test pmCoordCellToSkyQuick() -> pmCoordSkyToCellQuick()
+                        // I'm not sure how to test this in a system with chip and cell gaps.
+                        // There's no way to create an accurate polynomial transform from
+                        // a cell to the sky where there are cell, or chip gaps.
+                        //
+                        if ((NUM_CHIPS == 1) && (NUM_CELLS == 1)) {
+                            psPlane tmpCellCoord;
+                            psSphere *rc = pmCoordCellToSkyQuick(skyCoord, &cellCoord, myCell);
+                            if (rc == NULL) {
+                                printf("pmCoordCellToSkyQuick() failed.\n");
+                            } else {
+                                psPlane *rc = pmCoordSkyToCellQuick(&tmpCellCoord, skyCoord, myCell);
+                                if (rc == NULL) {
+                                    printf("pmCoordSkyToCellQuick() failed.\n");
+                                } else {
+                                    if (fabs(cellCoord.x - tmpCellCoord.x) > FLT_EPSILON) {
+                                        printf("TEST ERROR: pmCoordCellToSky()/pmCoordSkyToCell() x coord was %.2f, should be %.2f\n", tmpCellCoord.x, cellCoord.x);
+                                        testStatus = 1;
+                                    }
+                                    if (fabs(cellCoord.y - tmpCellCoord.y) > FLT_EPSILON) {
+                                        printf("TEST ERROR: pmCoordCellToSky()/pmCoordSkyToCell() y coord was %.2f, should be %.2f\n", tmpCellCoord.y, cellCoord.y);
+                                        testStatus = 1;
+                                    }
+                                    if (VERBOSE) {
+                                        printf("(%.2f %.2f) -> (%.2f %.2f) -> (%.2f %.2f)\n", testCoord.x, testCoord.y, skyCoord->r, skyCoord->d, tmpCellCoord.x, tmpCellCoord.y);
+                                    }
+                                }
+                            }
+                        }
+
+                        pmCoordCellToFPA(&testCoord, &cellCoord, myCell);
+                        if (fabs(testCoord.x - fpaCoord.x) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordCellToFPA() x coord was %.2f, should be %d\n", cellCoord.x, x);
+                            testStatus = 1;
+                        }
+                        if (fabs(testCoord.y - fpaCoord.y) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordCellToFPA() y coord was %.2f, should be %d\n", cellCoord.y, y);
+                            testStatus = 1;
+                        }
+
+                        pmCoordTPToFPA(&testCoord, &fpaCoord, 0.0, 0.0, myFPA);
+                        if (fabs(testCoord.x - fpaCoord.x) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordTPToFPA() x coord was %.2f, should be %d\n", cellCoord.x, x);
+                            testStatus = 1;
+                        }
+                        if (fabs(testCoord.y - fpaCoord.y) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordTPToFPA() y coord was %.2f, should be %d\n", cellCoord.y, y);
+                            testStatus = 1;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    psFree(myFPA);
+    psFree(skyCoord);
+
+    return(testStatus);
+}
+
+/******************************************************************************
+test4(): This routine wil test the pmFPACheckParents() function.  We generate
+an pmFPA hierarchy, then set the parents of each readout/cell/chip to NULL,
+then call pmFPACheckParents() to restore them, then we ensure they were
+restored.
+ *****************************************************************************/
+psS32 test4( void )
+{
+    psS32 testStatus = 0;
+
+    //
+    // Generate a pmFPA hierarchy.
+    //
+    pmFPA *tmpFPA = genSystem();
+
+    //
+    // We set the parents of each readout/cell/chip to NULL.
+    //
+    for (psS32 chipID = 0; chipID < tmpFPA->chips->n ; chipID++) {
+        pmChip *tmpChip = (pmChip *) tmpFPA->chips->data[chipID];
+        tmpChip->parent = NULL;
+
+        for (psS32 cellID = 0; cellID < tmpChip->cells->n ; cellID++) {
+            pmCell *tmpCell = (pmCell *) tmpChip->cells->data[cellID];
+            tmpCell->parent = NULL;
+
+            for (psS32 readoutID = 0; readoutID < tmpCell->readouts->n ; readoutID++) {
+                pmReadout *tmpReadout = (pmReadout *) tmpCell->readouts->data[readoutID];
+                tmpReadout->parent = NULL;
+            }
+        }
+    }
+
+    //
+    // Ensure that pmFPACheckParents() returned FALSE.
+    //
+    psBool rc = pmFPACheckParents(tmpFPA);
+    if (rc != false) {
+        printf("TEST ERROR: pmCheckParents() returned TRUE.\n");
+        testStatus = 1;
+    }
+
+    //
+    // Ensure that the parent members are right.
+    //
+    for (psS32 chipID = 0; chipID < tmpFPA->chips->n ; chipID++) {
+        pmChip *tmpChip = (pmChip *) tmpFPA->chips->data[chipID];
+        if (tmpChip->parent != tmpFPA) {
+            printf("TEST ERROR: pmCheckParents() did not restore Chip->parent.\n");
+            testStatus = 2;
+        }
+
+        for (psS32 cellID = 0; cellID < tmpChip->cells->n ; cellID++) {
+            pmCell *tmpCell = (pmCell *) tmpChip->cells->data[cellID];
+            if (tmpCell->parent != tmpChip) {
+                printf("TEST ERROR: pmCheckParents() did not restore Cell->parent.\n");
+                testStatus = 3;
+            }
+
+            for (psS32 readoutID = 0; readoutID < tmpCell->readouts->n ; readoutID++) {
+                pmReadout *tmpReadout = (pmReadout *) tmpCell->readouts->data[readoutID];
+                if (tmpReadout->parent != tmpCell) {
+                    printf("TEST ERROR: pmCheckParents() did not restore Readout->parent.\n");
+                    testStatus = 4;
+                }
+            }
+        }
+    }
+
+    psFree(tmpFPA);
+    return(testStatus);
+}
+
+/******************************************************************************
+test5(): This routine wil test the pmFPASelectChip() and pmFPAExcludeChip()
+functions.  We generate an pmFPA hierarchy, then set the ->valid members with
+those routines, then verify.
+ *****************************************************************************/
+psS32 test5( void )
+{
+    psS32 testStatus = 0;
+    pmChip *tmpChip = NULL;
+
+    //
+    // Generate a pmFPA hierarchy.
+    //
+    pmFPA *tmpFPA = genSystem();
+
+    //
+    // We test the ->valid member for each chip.
+    //
+    for (psS32 i = 0 ; i < tmpFPA->chips->n ; i++) {
+        tmpChip = (pmChip *) tmpFPA->chips->data[i];
+        if ((tmpChip == NULL) || (tmpChip->valid != false)) {
+            printf("TEST ERROR: Could not properly generate an FPA hierarchy.\n");
+            testStatus = 1;
+        }
+    }
+
+    //
+    // Exclude chip number 0, include all others, then test return value
+    //
+    psS32 numChips = pmFPAExcludeChip(tmpFPA, 0);
+    if (numChips != (NUM_CHIPS-1)) {
+        printf("TEST ERROR: pmFPAExcludeChip() did not return the correct number of chips.\n");
+        testStatus = 2;
+    }
+
+    //
+    // We test the ->valid member for each chip.
+    //
+    tmpChip = (pmChip *) tmpFPA->chips->data[0];
+    if (tmpChip->valid != false) {
+        printf("TEST ERROR: pmFPAExcludeChip() did not set the proper chip->valid to FALSE.\n");
+        testStatus = 3;
+    }
+    for (psS32 i = 1 ; i < tmpFPA->chips->n ; i++) {
+        pmChip *tmpChip = (pmChip *) tmpFPA->chips->data[i];
+        if (tmpChip->valid != true) {
+            printf("TEST ERROR: pmFPAExcludeChip() did not set the proper chip->valids to FALSE.\n");
+            testStatus = 4;
+        }
+    }
+
+
+    //
+    // Include chip number 0, exclude all others, then test return value
+    //
+    psBool tmpBool = pmFPASelectChip(tmpFPA, 0);
+    if (tmpBool != true) {
+        printf("TEST ERROR: pmFPASelectChip() returned FALSE.\n");
+        testStatus = 5;
+    }
+
+    //
+    // We test the ->valid member for each chip.
+    //
+    tmpChip = (pmChip *) tmpFPA->chips->data[0];
+    if (tmpChip->valid != true) {
+        printf("TEST ERROR: pmFPASelectChip() did not set the proper chip->valid to FALSE.\n");
+        testStatus = 6;
+    }
+    for (psS32 i = 1 ; i < tmpFPA->chips->n ; i++) {
+        pmChip *tmpChip = (pmChip *) tmpFPA->chips->data[i];
+        if (tmpChip->valid != false) {
+            printf("TEST ERROR: pmFPASelectChip() did not set the proper chip->valids to FALSE.\n");
+            testStatus = 7;
+        }
+    }
+
+    psFree(tmpFPA);
+    return(testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/.cvsignore	(revision 22158)
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+temp
+tst_pmAstrometry
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/Makefile.am	(revision 22158)
@@ -0,0 +1,41 @@
+AM_CPPFLAGS = \
+	$(SRCINC) \
+	-I$(top_srcdir)/test/tap/src \
+	-I$(top_srcdir)/test/pstap/src \
+	$(PSMODULES_CFLAGS)
+
+AM_LDFLAGS = \
+	$(top_builddir)/src/libpsmodules.la  \
+	$(top_builddir)/test/tap/src/libtap.la \
+	$(top_builddir)/test/pstap/src/libpstap.la \
+	$(PSMODULES_LIBS)
+
+TEST_PROGS = \
+	tap_pmFPA \
+	tap_pmFPAReadWrite \
+	tap_pmHDU \
+	tap_pmHDUUtils \
+	tap_pmFPALevel \
+	tap_pmFPAFlags \
+	tap_pmFPAExtent \
+	tap_pmFPAUtils \
+	tap_pmFPAConstruct \
+	tap_pmFPAView \
+	tap_pmFPAHeader \
+	tap_pmFPAMaskW \
+	tap_pmFPACellSquish \
+	tap_pmReadoutStack \
+	tap_pmReadoutFake \
+	tap_pmFPACopy
+
+if BUILD_TESTS
+bin_PROGRAMS = $(TEST_PROGS)
+TESTS = $(TEST_PROGS)
+else
+check_PROGRAMS = $(TEST_PROGS)
+endif
+
+CLEANFILES = $(check_DATA) temp/* core core.* *~ *.bb *.bbg *.da gmon.out
+
+test: check
+	$(top_srcdir)/test/test.pl
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/SampleIPPConfig
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/SampleIPPConfig	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/SampleIPPConfig	(revision 22158)
@@ -0,0 +1,45 @@
+### Example .ipprc file
+    PATH            STR     .
+    DATAPATH	str	datapath
+
+### Database configuration
+    DBSERVER	STR	localhost
+    DBUSER		STR	test
+    DBPASSWORD	STR	""
+    DBNAME          STR     test
+    DBPORT		S32	0
+
+### Setups for each camera system
+    CAMERAS		METADATA
+	CAMERA0		STR	camera0/camera.config
+	CAMERA1		STR	camera1/camera.config
+    END
+
+### Setups for psLib
+    TIME		STR	time.config
+    LOGLEVEL	S32	3
+    LOGFORMAT	STR	HLNM
+    LOGDEST	STR	STDOUT
+
+### Default trace logging initializations
+    TRACE		METADATA
+	dummyTraceFacility01	S32	1
+	dummyTraceFacility02	S32	2
+    END
+
+### Predefined recipe files
+    RECIPES         METADATA                # Site-level recipes
+        R00		STR	recipes/R00.config
+        R01		STR	recipes/R01.config
+        R02		STR	recipes/R02.config
+        R03		STR	recipes/R03.config
+    END
+
+### Misc arbitraty metadata
+    ARBITRARY_STRING_S32	S32	20
+    ARBITRARY_STRING_F32	F32	21.0
+    ARBITRARY_STRING_F64	F64	22.0
+    ARBITRARY_STRING_STR	STR	19.0
+    ARBITRARY_STRING_BOOL_T	BOOL	true
+    ARBITRARY_STRING_BOOL_F	BOOL	false
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera0/#camera.config~
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera0/#camera.config~	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera0/#camera.config~	(revision 22158)
@@ -0,0 +1,22 @@
+FORMATS         METADATA
+        C0_FM0     STR     camera0/format0.config
+        C0_FM1     STR     camera0/format1.config
+END
+
+RECIPES         METADATA
+        C0_RECIPE0          STR     camera0/recipe0.config
+        C0_RECIPE1          STR     camera0/recipe1.config
+END
+
+# How to translate PS concepts into FITS headers
+TRANSLATION     METADATA
+        CELL.TRIMSEC            STR     TRIMSEC
+        CELL.BIASSEC            STR     BIASSEC
+END
+
+
+FPA     METADATA
+        ccd00   STR     LeftAmp RightAmp
+        ccd01   STR     LeftAmp RightAmp
+END
+ID      STR     CAMERA0
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera0/camera.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera0/camera.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera0/camera.config	(revision 22158)
@@ -0,0 +1,24 @@
+FORMATS         METADATA
+        C0_FM0     STR     camera0/format0.config
+        C0_FM1     STR     camera0/format1.config
+END
+
+RECIPES         METADATA
+        C0_RECIPE0          STR     camera0/recipe0.config
+        C0_RECIPE1          STR     camera0/recipe1.config
+END
+
+# How to translate PS concepts into FITS headers
+TRANSLATION     METADATA
+        CELL.TRIMSEC            STR     TRIMSEC
+        CELL.BIASSEC            STR     BIASSEC
+        CELL.TRIMSEC0            STR     TRIMSEC
+        CELL.BIASSEC1            STR     BIASSEC
+END
+
+
+FPA     METADATA
+        ccd00   STR     LeftAmp RightAmp
+        ccd01   STR     LeftAmp RightAmp
+END
+ID      STR     CAMERA0
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera0/format0.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera0/format0.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera0/format0.config	(revision 22158)
@@ -0,0 +1,31 @@
+RULE    METADATA
+        F0_KEY0        STR     string20
+        F0_KEY1        STR     string21
+        F0_KEY2        S32     20
+END
+
+FILE    METADATA
+        PHU             STR     FPA
+        EXTENSIONS      STR     CELL
+        FPA.NAME        STR     EXPNUM
+END
+
+DEFAULTS        METADATA
+        F0_DEF0           STR     DefString20
+        F0_DEF1           STR     DefString21
+        F0_DEF2           F32     21.0
+        F0_DEF3           S32     22
+END
+
+CELLS   METADATA
+        left    METADATA        # Left amplifier
+                CELL.BIASSEC.SOURCE     STR     HEADER
+                CELL.TRIMSEC.SOURCE     STR     HEADER
+        END
+        right   METADATA        # Right amplifier
+                CELL.BIASSEC.SOURCE     STR     HEADER
+                CELL.TRIMSEC.SOURCE     STR     HEADER
+        END
+END
+
+ID	STR	camera0/format0.config
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera0/format1.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera0/format1.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera0/format1.config	(revision 22158)
@@ -0,0 +1,29 @@
+RULE    METADATA
+        F1_KEY0        STR     string30
+        F1_KEY1        STR     string31
+        F1_KEY2        S32     30
+END
+
+FILE    METADATA
+        PHU             STR     FPA
+        EXTENSIONS      STR     CELL
+        FPA.NAME        STR     EXPNUM
+END
+
+DEFAULTS        METADATA
+        F1_DEF0           STR     DefString30
+        F1_DEF1           STR     DefString31
+        F1_DEF2           F32     31.0
+        F1_DEF3           S32     32
+END
+
+CELLS   METADATA
+        left    METADATA        # Left amplifier
+                CELL.BIASSEC.SOURCE     STR     HEADER
+                CELL.TRIMSEC.SOURCE     STR     HEADER
+        END
+        right   METADATA        # Right amplifier
+                CELL.BIASSEC.SOURCE     STR     HEADER
+                CELL.TRIMSEC.SOURCE     STR     HEADER
+        END
+END
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera0/recipe0.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera0/recipe0.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera0/recipe0.config	(revision 22158)
@@ -0,0 +1,4 @@
+R0_KEY0		STR	RecipeString0
+R0_KEY1		STR	RecipeString1
+R0_KEY2		S32	2
+R0_KEY3		F32	3
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera0/recipe1.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera0/recipe1.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera0/recipe1.config	(revision 22158)
@@ -0,0 +1,4 @@
+R1_KEY0		STR	RecipeString10
+R1_KEY1		STR	RecipeString11
+R1_KEY2		S32	12
+R1_KEY3		F32	13
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera1/#camera.config~
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera1/#camera.config~	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera1/#camera.config~	(revision 22158)
@@ -0,0 +1,14 @@
+FORMATS         METADATA
+        C1_FM0     STR     camera1/format0.config
+        C1_FM1     STR     camera1/format1.config
+END
+
+RECIPES         METADATA
+        C1_RECIPE0          STR     camera1/recipe0.config
+        C1_RECIPE1          STR     camera1/recipe1.config
+END
+
+FPA     METADATA
+        ccd00   STR     LeftAmp RightAmp
+        ccd01   STR     LeftAmp RightAmp
+END
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera1/camera.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera1/camera.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera1/camera.config	(revision 22158)
@@ -0,0 +1,20 @@
+FORMATS         METADATA
+        C1_FM0     STR     camera1/format0.config
+        C1_FM1     STR     camera1/format1.config
+END
+
+RECIPES         METADATA
+        C1_RECIPE0          STR     camera1/recipe0.config
+        C1_RECIPE1          STR     camera1/recipe1.config
+END
+
+# How to translate PS concepts into FITS headers
+TRANSLATION     METADATA
+        CELL.TRIMSEC            STR     TRIMSEC
+        CELL.BIASSEC            STR     BIASSEC
+END
+
+FPA     METADATA
+        ccd00   STR     LeftAmp RightAmp
+        ccd01   STR     LeftAmp RightAmp
+END
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera1/format0.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera1/format0.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera1/format0.config	(revision 22158)
@@ -0,0 +1,29 @@
+RULE    METADATA
+        F0_KEY0        STR     string40
+        F0_KEY1        STR     string41
+        F0_KEY2        S32     420
+END
+
+FILE    METADATA
+        PHU             STR     FPA
+        EXTENSIONS      STR     CELL
+        FPA.NAME        STR     EXPNUM
+END
+
+DEFAULTS        METADATA
+        F0_DEF0           STR     DefString40
+        F0_DEF1           STR     DefString41
+        F0_DEF2           F32     41.0
+        F0_DEF3           S32     44
+END
+
+CELLS   METADATA
+        left    METADATA        # Left amplifier
+                CELL.BIASSEC.SOURCE     STR     HEADER
+                CELL.TRIMSEC.SOURCE     STR     HEADER
+        END
+        right   METADATA        # Right amplifier
+                CELL.BIASSEC.SOURCE     STR     HEADER
+                CELL.TRIMSEC.SOURCE     STR     HEADER
+        END
+END
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera1/format1.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera1/format1.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera1/format1.config	(revision 22158)
@@ -0,0 +1,29 @@
+RULE    METADATA
+        F1_KEY0        STR     string80
+        F1_KEY1        STR     string81
+        F1_KEY2        S32     80
+END
+
+FILE    METADATA
+        PHU             STR     FPA
+        EXTENSIONS      STR     CELL
+        FPA.NAME        STR     EXPNUM
+END
+
+DEFAULTS        METADATA
+        F1_DEF0           STR     DefString80
+        F1_DEF1           STR     DefString81
+        F1_DEF2           F32     81.0
+        F1_DEF3           S32     82
+END
+
+CELLS   METADATA
+        left    METADATA        # Left amplifier
+                CELL.BIASSEC.SOURCE     STR     HEADER
+                CELL.TRIMSEC.SOURCE     STR     HEADER
+        END
+        right   METADATA        # Right amplifier
+                CELL.BIASSEC.SOURCE     STR     HEADER
+                CELL.TRIMSEC.SOURCE     STR     HEADER
+        END
+END
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera1/recipe0.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera1/recipe0.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera1/recipe0.config	(revision 22158)
@@ -0,0 +1,4 @@
+R0_KEY0		STR	RecipeString120
+R0_KEY1		STR	RecipeString121
+R0_KEY2		S32	122
+R0_KEY3		F32	123
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera1/recipe1.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera1/recipe1.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/camera1/recipe1.config	(revision 22158)
@@ -0,0 +1,4 @@
+R1_KEY0		STR	RecipeString230
+R1_KEY1		STR	RecipeString2311
+R1_KEY2		S32	232
+R1_KEY3		F32	233
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/path2/SampleIPPConfig2
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/path2/SampleIPPConfig2	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/path2/SampleIPPConfig2	(revision 22158)
@@ -0,0 +1,32 @@
+### Example .ipprc file
+
+### Database configuration
+DBSERVER	STR	ippdb.ifa.hawaii.edu	# Database host name (for psDBInit)
+DBUSER		STR	ipp			# Database user name (for psDBInit)
+DBPASSWORD	STR	password		# Database password (for psDBInit)
+
+### Setups for each camera system
+CAMERAS		METADATA
+	MEGACAM_RAW	STR	megacam_raw.config
+	MEGACAM_SPLICE	STR	megacam_splice.config
+	GPC1_RAW	STR	gpc1_raw.config
+	LRIS_BLUE	STR	lris_blue.config
+	LRIS_RED	STR	lris_red.config
+END
+
+### psLib setup
+#TIME		STR	/home/mithrandir/price/pan-starrs/jhroot/i686-pc-linux-gnu/etc/pslib/psTime.config	# Time configuration file
+LOGLEVEL	S32	3			# Logging level; 3=INFO
+LOGFORMAT	STR	HLNM			# Log format
+LOGDEST	STR	STDOUT				# Log destination
+TRACE		METADATA			# Trace levels
+	dummyTraceFunc01	S32	1
+	dummyTraceFunc02	S32	2
+END
+ARBITRARY_STRING_S32	S32	20
+ARBITRARY_STRING_F32	F32	21.0
+ARBITRARY_STRING_F64	F64	22.0
+ARBITRARY_STRING_STR	STR	19.0
+ARBITRARY_STRING_BOOL_T	BOOL	true
+ARBITRARY_STRING_BOOL_F	BOOL	false
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/sampleFitsFile.fits
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/sampleFitsFile.fits	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/data/sampleFitsFile.fits	(revision 22158)
@@ -0,0 +1,1 @@
+SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   16 / length of data axis 1                          NAXIS2  =                   16 / length of data axis 2                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H MYINT   =                    0 / psS32 Item                                     MYFLT   =                   1. / psF32 Item                                     MYDBL   =                   1. / psF64 Item                                     MYBOOL  =                    T / psBool Item                                    MYSTR   = 'ext-0   '           / String Item                                    EXTNAME = 'ext-0   '                                                            END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   16 / length of data axis 1                          NAXIS2  =                   16 / length of data axis 2                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     MYINT   =                    1 / psS32 Item                                     MYFLT   =                  0.5 / psF32 Item                                     MYDBL   =                  0.5 / psF64 Item                                     MYBOOL  =                    F / psBool Item                                    MYSTR   = 'ext-1   '           / String Item                                    EXTNAME = 'ext-1   '                                                            END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   16 / length of data axis 1                          NAXIS2  =                   16 / length of data axis 2                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     MYINT   =                    2 / psS32 Item                                     MYFLT   =            0.3333333 / psF32 Item                                     MYDBL   =    0.333333333333333 / psF64 Item                                     MYBOOL  =                    T / psBool Item                                    MYSTR   = 'ext-2   '           / String Item                                    EXTNAME = 'ext-2   '                                                            END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   16 / length of data axis 1                          NAXIS2  =                   16 / length of data axis 2                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     MYINT   =                    3 / psS32 Item                                     MYFLT   =                 0.25 / psF32 Item                                     MYDBL   =                 0.25 / psF64 Item                                     MYBOOL  =                    F / psBool Item                                    MYSTR   = 'ext-3   '           / String Item                                    EXTNAME = 'ext-3   '                                                            END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   16 / length of data axis 1                          NAXIS2  =                   16 / length of data axis 2                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     MYINT   =                    4 / psS32 Item                                     MYFLT   =                  0.2 / psF32 Item                                     MYDBL   =                  0.2 / psF64 Item                                     MYBOOL  =                    T / psBool Item                                    MYSTR   = 'ext-4   '           / String Item                                    EXTNAME = 'ext-4   '                                                            END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   16 / length of data axis 1                          NAXIS2  =                   16 / length of data axis 2                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     MYINT   =                    5 / psS32 Item                                     MYFLT   =            0.1666667 / psF32 Item                                     MYDBL   =    0.166666666666667 / psF64 Item                                     MYBOOL  =                    F / psBool Item                                    MYSTR   = 'ext-5   '           / String Item                                    EXTNAME = 'ext-5   '                                                            END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @   @                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   16 / length of data axis 1                          NAXIS2  =                   16 / length of data axis 2                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     MYINT   =                    6 / psS32 Item                                     MYFLT   =            0.1428571 / psF32 Item                                     MYDBL   =    0.142857142857143 / psF64 Item                                     MYBOOL  =                    T / psBool Item                                    MYSTR   = 'ext-6   '           / String Item                                    EXTNAME = 'ext-6   '                                                            END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À  @À                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   16 / length of data axis 1                          NAXIS2  =                   16 / length of data axis 2                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     MYINT   =                    7 / psS32 Item                                     MYFLT   =                0.125 / psF32 Item                                     MYDBL   =                0.125 / psF64 Item                                     MYBOOL  =                    F / psBool Item                                    MYSTR   = 'ext-7   '           / String Item                                    EXTNAME = 'ext-7   '                                                            END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à  @à                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmAstrometry.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmAstrometry.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmAstrometry.c	(revision 22158)
@@ -0,0 +1,667 @@
+/** @file  tst_psAstrometry01.c
+*
+* XXX: The source code that is tested here is in the pmAstrometry.c and
+* pmAstrometry.h files.  However, those files are not included in the
+* current automake configuration.  These tests are therefore, not
+* runnable.  We include them in this distribution for the future.
+*
+* XXX: These tests need to be converted to tap format.
+*
+* XXX: Add tests were the coordinate does not transform to any legitimate cell
+* or chip, or FPA, or whatever.
+*
+* XXX: For each function, add tests for bad input parameters, as well as failed transforms.
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define PS_PERCENT_COMPARE(X, Y, PERCENT_FRACTION) (fabs((Y)-(X))/fabs(X) < (PERCENT_FRACTION))
+#define VERBOSE 0
+#define NUM_READOUTS 1
+#define READOUT_NUM_ROWS 10
+#define READOUT_NUM_COLS 10
+
+#define NUM_CELLS 4
+#define CELL_GAP 2
+#define CELL_WIDTH READOUT_NUM_COLS
+#define CELL_HEIGHT READOUT_NUM_ROWS
+#define CELL_MIN_X 0
+#define CELL_MAX_X CELL_HEIGHT
+#define CELL_MIN_Y 0
+#define CELL_MAX_Y CELL_WIDTH
+
+#define NUM_CHIPS 2
+#define CHIP_GAP 2
+#define CHIP_MIN_X 0
+#define CHIP_MAX_X CELL_HEIGHT
+#define CHIP_MIN_Y 0
+#define CHIP_MAX_Y ((NUM_CELLS * CELL_WIDTH) + ((NUM_CELLS) * CELL_GAP))
+#define CHIP_WIDTH CHIP_MAX_Y
+#define CHIP_HEIGHT CHIP_MAX_X
+
+#define NUM_FPAS 1
+#define FPA_MIN_X 0
+#define FPA_MAX_X CHIP_HEIGHT
+#define FPA_MIN_Y 0
+#define FPA_MAX_Y (((NUM_CHIPS) * CHIP_WIDTH) + (((NUM_CHIPS)-1) * CHIP_GAP))
+
+#define PROJECTION_SCALE_X 1.0
+#define PROJECTION_SCALE_Y 1.0
+
+psS32 currentId = 0;
+psS32 memLeaks = 0;
+
+psPlaneTransform *PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM()
+{
+    psPlaneTransform *pt = psPlaneTransformAlloc(1, 1);
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+    return(pt);
+}
+
+psPlaneDistort *PS_CREATE_4D_IDENTITY_PLANE_DISTORT()
+{
+    psPlaneDistort *pd = psPlaneDistortAlloc(1, 1, 1, 1);
+    pd->x->coeff[1][0][0][0] = 1.0;
+    pd->y->coeff[0][1][0][0] = 1.0;
+    return(pd);
+}
+
+/******************************************************************************
+genSystem(): This routine will create a system of FPAs/Chips/Cells/Readouts.  For
+simplicity, an FPA is defined as a linear array of chips, and a chip is
+defined as a linear array of cells, both in the y (cols) direction.  The
+transforms between the various layers take into account the cell/chip and
+the boundaries between each.
+ *****************************************************************************/
+pmFPA *genSystem()
+{
+    //
+    // Create top pmFPA structure.
+    //
+    const psMetadata *camera = psMetadataAlloc();
+    pmFPA* myFPA = pmFPAAlloc(camera);
+    if (myFPA == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc() returned a NULL.\n");
+        return NULL;
+    }
+    myFPA->fromTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    myFPA->toTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    myFPA->projection = psProjectionAlloc(0.0,0.0,PROJECTION_SCALE_X,PROJECTION_SCALE_X,PS_PROJ_TAN);
+
+    myFPA->chips = psArrayRealloc(myFPA->chips, NUM_CHIPS);
+    for (psS32 chipID=0 ; chipID<NUM_CHIPS ; chipID++) {
+        pmChip *myChip = pmChipAlloc(myFPA, "ChipName");
+        if (myChip == NULL) {
+            psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmChipAlloc() returned a NULL.\n");
+            return NULL;
+        }
+        myFPA->chips->data[chipID] = (psPtr *) myChip;
+        int myChipRow0 = 0;
+        int myChipCol0 = chipID * (CHIP_WIDTH + CHIP_GAP);
+
+        // We create the transforms between the chip and FPA.  The
+        // transform is a simple identity transform.
+        myChip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+        myChip->toFPA->y->coeff[0][0] = (psF64) myChipCol0;
+        myChip->toFPA->y->coeff[1][1] = 0.0;
+        myChip->toFPA->x->coeff[0][0] = (psF64) myChipRow0;
+        myChip->toFPA->x->coeff[1][1] = 0.0;
+
+        myChip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+        myChip->fromFPA->y->coeff[0][0] = (psF64) (- myChipCol0);
+        myChip->fromFPA->y->coeff[1][1] = 0.0;
+        myChip->fromFPA->x->coeff[0][0] = (psF64) (- myChipRow0);
+        myChip->fromFPA->x->coeff[1][1] = 0.0;
+
+        myChip->cells = psArrayRealloc(myChip->cells, NUM_CELLS);
+        for (psS32 cellID=0 ; cellID<NUM_CELLS ; cellID++) {
+            pmCell *myCell = pmCellAlloc(myChip, NULL, "CellName");
+            if (myCell == NULL) {
+                psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmCellAlloc() returned a NULL.\n");
+                return NULL;
+            }
+            myChip->cells->data[cellID] = (psPtr *) myCell;
+            int myCellRow0 = 0;
+            int myCellCol0 = cellID * (CELL_WIDTH + CELL_GAP);
+            myCell->toChip = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+            myCell->toChip->y->coeff[0][0] = (psF64) myCellCol0;
+            myCell->toChip->y->coeff[1][1] = 0.0;
+            myCell->toChip->x->coeff[0][0] = (psF64) myCellRow0;
+            myCell->toChip->x->coeff[1][1] = 0.0;
+
+            myCell->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+            myCell->toFPA->y->coeff[0][0] = (psF64) (myCellCol0 + myChipCol0);
+            myCell->toFPA->y->coeff[1][1] = 0.0;
+            myCell->toFPA->x->coeff[0][0] = (psF64) (myCellRow0 + myChipRow0);
+            myCell->toFPA->x->coeff[1][1] = 0.0;
+
+            myCell->toSky = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+            myCell->toSky->y->coeff[0][0] = myCell->toFPA->y->coeff[0][0];
+            myCell->toSky->y->coeff[1][1] = 0.0;
+            myCell->toSky->x->coeff[0][0] = myCell->toFPA->x->coeff[0][0];
+            myCell->toSky->x->coeff[1][1] = 0.0;
+
+            myCell->readouts = psArrayRealloc(myCell->readouts, NUM_READOUTS);
+            for (psS32 readoutID=0 ; readoutID<NUM_READOUTS ; readoutID++) {
+                pmReadout *myReadout = pmReadoutAlloc(myCell);
+                if (myReadout == NULL) {
+                    psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmReadoutAlloc() returned a NULL.\n");
+                    return NULL;
+                }
+                myCell->readouts->data[readoutID] = (psPtr *) myReadout;
+                myReadout->image = psImageAlloc(READOUT_NUM_COLS, READOUT_NUM_ROWS, PS_TYPE_F32);
+                for (psS32 row=0;row<READOUT_NUM_ROWS;row++) {
+                    for(psS32 col=0;col<READOUT_NUM_COLS;col++) {
+                        myReadout->image->data.F32[row][col] = (psF32) ((chipID * (CHIP_WIDTH + CHIP_GAP)) +
+                                                               (cellID * (CELL_WIDTH + CELL_GAP)));
+                    }
+                }
+                int myReadoutRow0 = myCellRow0;
+                int myReadoutCol0 = myCellCol0;
+                myReadout->rowBins = 0;
+                myReadout->colBins = 0;
+            }
+            if (VERBOSE) {
+                printf("\n\n\n\nFor chip %d cell %d the cell->toFPA transform is:\n", chipID, cellID);
+                PS_PRINT_PLANE_TRANSFORM(myCell->toFPA);
+                printf("\n\n\n\nFor chip %d cell %d the cell->toChip transform is:\n", chipID, cellID);
+                PS_PRINT_PLANE_TRANSFORM(myCell->toChip);
+                printf("\n\n\n\nFor chip %d cell %d the cell->toSky transform is:\n", chipID, cellID);
+                PS_PRINT_PLANE_TRANSFORM(myCell->toSky);
+            }
+        }
+        if (VERBOSE) {
+            printf("\n\n\n\nFor chip %d the chip->toFPA transform is:\n", chipID);
+            PS_PRINT_PLANE_TRANSFORM(myChip->toFPA);
+            printf("\n\n\n\nFor chip %d the chip->fromFPA transform is:\n", chipID);
+            PS_PRINT_PLANE_TRANSFORM(myChip->fromFPA);
+        }
+    }
+
+    return(myFPA);
+}
+
+
+/******************************************************************************
+This routine tests many Astrometry functions.  It loops through all valid
+pixels of all cells of all chips and computes the corresponding (x,y)
+coordinates in the FPA plane.  It then calls the pmChipInFPA() then
+pmCellInFPA() with the FPA coordinate and determines the chip/cell that that
+coordinate corresponds to.  Following that it does a variety of tests on the
+various functions that tharnsform coordinates within the pmFPA hierarchy.
+ 
+List of tested functions:
+    pmCellInFPA()  yes
+    pmChipInFPA()  yes
+    pmCellInChip()  yes
+ 
+    pmCoordCellToFPA()  yes
+    pmCoordChipToFPA()  yes
+    pmCoordFPAToChip()  yes
+    pmCoordCellToChip()  yes
+    pmCoordChipToCell()  yes
+ 
+    pmCoordFPAToTP()  yes
+    pmCoordTPToFPA()  yes
+ 
+    pmCoordTPToSky()  yes
+    pmCoordSkyToTP()  yes
+    pmCoordSkyToCell()  yes
+    pmCoordCellToSky()  yes
+    pmCoordCellToSkyQuick() yes
+    pmCoordSkyToCellQuick() yes
+ *****************************************************************************/
+psS32 test3( void )
+{
+    psS32 x;
+    psS32 y;
+    psPlane fpaCoord;
+    pmFPA *myFPA = genSystem();
+    pmCell *myCell = NULL;
+    psPlane chipCoord;
+    psPlane cellCoord;
+    psPlane testCoord;
+    psSphere *skyCoord = psSphereAlloc();
+    // XXX: This code causes a seg fault.
+    //    psSphere skyTmp;
+    //    psMemCheckType(PS_DATA_SPHERE, &skyTmp);
+    psPlane tpCoord;
+    psS32 testStatus = 0;
+
+    //
+    // I'm not convinced that the p_psProject() and p_psDeproject() functions work
+    // correctly.  If we project a set of coordinates over a wide range of (R, D)
+    // values, then deproject them, the original (R, D) values are only produced
+    // when D is larger than 0.  This code demonstrates that.  I also created tests
+    // that currently fail in tst_psCoord01.c.  I have a workaround in the function
+    // XXXDeproject() in pmAstrometry.c.
+    //
+    if (0) {
+        // This loop goes from (R, D) -> (X, Y) -> (R, D)
+        psPlane planeCoord01;
+        psSphere skyCoord01;
+        psSphere skyCoord02;
+        #define DEG_INC 15.0
+
+        for (psF32 R = -90.0 ; R <= 90.0 ; R+= DEG_INC) {
+            for (psF32 D = -90.0 ; D <= 90.0 ; D+= DEG_INC) {
+                if ((fabs(R) != 90.0) && (fabs(D) != 90.0)) {
+                    skyCoord01.r = DEG_TO_RAD(R);
+                    skyCoord01.d = DEG_TO_RAD(D);
+                    p_psProject(&planeCoord01, &skyCoord01, myFPA->projection);
+                    p_psDeproject(&skyCoord02, &planeCoord01, myFPA->projection);
+                    printf("(%.2fr %.2fd) (%.2fr %.2fd) -> (%.2f %.2f) -> (%.2fr %.2fd)", R, D,
+                           skyCoord01.r, skyCoord01.d,
+                           planeCoord01.x, planeCoord01.y,
+                           skyCoord02.r, skyCoord02.d);
+                    if ((fabs(skyCoord01.r - skyCoord02.r) < FLT_EPSILON) &&
+                            (fabs(skyCoord01.d - skyCoord02.d) < FLT_EPSILON)) {
+                        printf(": CORRECT\n");
+                    } else {
+                        printf(": WRONG\n");
+                    }
+                }
+            }
+        }
+        psFree(myFPA);
+        return(0);
+    }
+    if (0) {
+        // This loop goes from (X, Y) -> (R, D) -> (X, Y)
+        #define SPACE_INC 4.0
+        for(testCoord.x=-CELL_HEIGHT;testCoord.x<=CELL_HEIGHT;testCoord.x+=SPACE_INC)
+        {
+            for (testCoord.y=-CELL_WIDTH;testCoord.y<=CELL_WIDTH;testCoord.y+=SPACE_INC) {
+                psPlane planeCoord01;
+                psPlane planeCoord02;
+                psSphere skyCoord01;
+                psSphere skyCoord02;
+                p_psDeproject(&skyCoord01, &testCoord, myFPA->projection);
+                p_psProject(&planeCoord01, &skyCoord01, myFPA->projection);
+                p_psDeproject(&skyCoord02, &planeCoord01, myFPA->projection);
+                p_psProject(&planeCoord02, &skyCoord02, myFPA->projection);
+                printf("Plane: (%.2f %.2f) -> (%.2fr %.2fd) -> (%.2f %.2f)\n",
+                       testCoord.x, testCoord.y,
+                       skyCoord01.r, skyCoord01.d,
+                       planeCoord01.x, planeCoord01.y);
+                /*
+                                printf("Plane: (%.2f %.2f) -> (%.2f %.2f) -> (%.2f %.2f)\n",
+                                        testCoord.x, testCoord.y, planeCoord01.x, planeCoord01.y,
+                                        planeCoord02.x, planeCoord02.y);
+                                printf("Sphere: (%.2f %.2f) -> (%.2f %.2f)\n",
+                                        skyCoord01.r, skyCoord01.d, skyCoord02.r, skyCoord02.d);
+                                printf("Plane: (%.2f %.2f) -> (%.2fd %.2fr) -> (%.2f %.2f) -> (%.2fd %.2fr) -> (%.2f %.2f)\n",
+                                        testCoord.x, testCoord.y,
+                                        skyCoord01.r, skyCoord01.d,
+                                        planeCoord01.x, planeCoord01.y,
+                                        skyCoord02.r, skyCoord02.d,
+                                        planeCoord02.x, planeCoord02.y);
+                */
+            }
+        }
+        psFree(myFPA);
+        return(0);
+    }
+    //
+    // We iterate through all cells on all chips on the fpa.  We determine
+    // the expected fpaCcoord.
+    //
+
+    for (psS32 chip=0;chip<NUM_CHIPS;chip++) {
+        for (psS32 cell=0;cell<NUM_CELLS;cell++) {
+            for(x=0;x<CELL_HEIGHT;x++) {
+                for (y=0;y<CELL_WIDTH;y++) {
+                    fpaCoord.x = (psF64) x;
+                    fpaCoord.y = (psF64) (y + (chip * (CHIP_WIDTH + CHIP_GAP)) +
+                                          (cell * (CELL_WIDTH + CELL_GAP)));
+                    if (VERBOSE) {
+                        printf("------------------ (%.2f, %.2f) ------------------\n", fpaCoord.x, fpaCoord.y);
+                        printf("(chip, cell, x, y) is (%d, %d, %d, %d)\n", chip, cell, x, y);
+                    }
+                    pmChip* tmpChip = pmChipInFPA(&fpaCoord, myFPA);
+                    myCell = pmCellInFPA(&fpaCoord, myFPA);
+
+                    if ((myCell == NULL) || (tmpChip == NULL)) {
+                        if (tmpChip == NULL) {
+                            printf("TEST ERROR: pmChipInFPA() returned NULL\n");
+                            testStatus = 1;
+                        } else if (myCell == NULL) {
+                            printf("TEST ERROR: pmCellInFPA(): returned NULL\n");
+                            testStatus = 1;
+                        }
+                    } else {
+                        pmCoordFPAToChip(&chipCoord, &fpaCoord, tmpChip);
+                        pmCoordChipToCell(&cellCoord, &chipCoord, myCell);
+
+                        if (x != (psS32) cellCoord.x) {
+                            printf("TEST ERROR: pmCoordFPAToChip()->pmCoordChipToCell(): x coord was %d (%f), should be %d\n", (psS32) cellCoord.x, cellCoord.x, x);
+                            testStatus = 1;
+                        }
+                        if (y != (psS32) cellCoord.y) {
+                            printf("TEST ERROR: pmCoordFPAToChip()->pmCoordChipToCell(): y coord was %d (%f), should be %d\n", (psS32) cellCoord.y, cellCoord.y, y);
+                            testStatus = 1;
+                        }
+
+                        pmCoordCellToChip(&testCoord, &cellCoord, myCell);
+                        if (fabs(testCoord.x - chipCoord.x) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordCellToChip() x coord was %.2f, should be %d\n", cellCoord.x, x);
+                            testStatus = 1;
+                        }
+                        if (fabs(testCoord.y - chipCoord.y) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordCellToChip() y coord was %.2f, should be %d\n", cellCoord.y, y);
+                            testStatus = 1;
+                        }
+
+                        pmCell *myCell2 = pmCellInChip(&chipCoord, tmpChip);
+                        if (myCell2 != myCell) {
+                            printf("TEST ERROR: pmCellInChip() != pmCellInChip(pmChipInFPA()) (%p %p)\n", myCell2, myCell);
+                            testStatus = 1;
+                        }
+
+                        pmCoordChipToFPA(&testCoord, &chipCoord, tmpChip);
+                        if (fabs(testCoord.x - x) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordChipToFPA() x coord was %.2f, should be %d\n", cellCoord.x, x);
+                            testStatus = 1;
+                        }
+                        if (fabs(testCoord.y - fpaCoord.y) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordChipToFPA() y coord was %.2f, should be %.2f\n", cellCoord.y, fpaCoord.y);
+                            testStatus = 1;
+                        }
+
+                        pmCoordFPAToTP(&testCoord, &fpaCoord, 0.0, 0.0, myFPA);
+                        if (fabs(testCoord.x - fpaCoord.x) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordFPAToTP() x coord was %.2f, should be %d\n", cellCoord.x, x);
+                            testStatus = 1;
+                        }
+                        if (fabs(testCoord.y - fpaCoord.y) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordFPAToTP() y coord was %.2f, should be %d\n", cellCoord.y, y);
+                            testStatus = 1;
+                        }
+
+                        //
+                        // Test pmCoordTPToSky() -> pmCoordSkyToTP()
+                        //
+                        if (1) {
+                            psSphere *rc = pmCoordTPToSky(skyCoord, &testCoord, myFPA->projection);
+                            if (rc == NULL) {
+                                printf("pmCoordTPToSky() failed.\n");
+                            } else {
+                                psPlane *rc = pmCoordSkyToTP(&tpCoord, skyCoord, myFPA->projection);
+                                if (rc == NULL) {
+                                    printf("pmCoordSkyToTP() failed.\n");
+                                } else {
+                                    if (fabs(testCoord.x - tpCoord.x) > FLT_EPSILON) {
+                                        printf("TEST ERROR: pmCoordTPToSky()/pmCoordSkyToTP() x coord was %.2f, should be %.2f\n", tpCoord.x, testCoord.x);
+                                        testStatus = 1;
+                                    }
+                                    if (fabs(testCoord.y - tpCoord.y) > FLT_EPSILON) {
+                                        printf("TEST ERROR: pmCoordTPToSky()/pmCoordSkyToTP() y coord was %.2f, should be %.2f\n", tpCoord.y, testCoord.y);
+                                        testStatus = 1;
+                                    }
+                                    if (VERBOSE) {
+                                        printf("(%.2f %.2f) -> (%.2f %.2f) -> (%.2f %.2f)\n", testCoord.x, testCoord.y, skyCoord->r, skyCoord->d, tpCoord.x, tpCoord.y);
+                                    }
+                                }
+                            }
+                        }
+
+                        //
+                        // Test pmCoordCellToSky() -> pmCoordSkyToCell()
+                        //
+                        if (1) {
+                            psPlane tmpCellCoord;
+                            psSphere *rc = pmCoordCellToSky(skyCoord, &cellCoord, 0.0, 0.0, myCell);
+                            if (rc == NULL) {
+                                printf("pmCoordCellToSky() failed.\n");
+                            } else {
+                                psPlane *rc = pmCoordSkyToCell(&tmpCellCoord, skyCoord, 0.0, 0.0, myCell);
+                                if (rc == NULL) {
+                                    printf("pmCoordSkyToCell() failed.\n");
+                                } else {
+                                    if (fabs(cellCoord.x - tmpCellCoord.x) > FLT_EPSILON) {
+                                        printf("TEST ERROR: pmCoordCellToSky()/pmCoordSkyToCell() x coord was %.2f, should be %.2f\n", tmpCellCoord.x, cellCoord.x);
+                                        testStatus = 1;
+                                    }
+                                    if (fabs(cellCoord.y - tmpCellCoord.y) > FLT_EPSILON) {
+                                        printf("TEST ERROR: pmCoordCellToSky()/pmCoordSkyToCell() y coord was %.2f, should be %.2f\n", tmpCellCoord.y, cellCoord.y);
+                                        testStatus = 1;
+                                    }
+                                    if (VERBOSE) {
+                                        printf("(%.2f %.2f) -> (%.2f %.2f) -> (%.2f %.2f)\n", testCoord.x, testCoord.y, skyCoord->r, skyCoord->d, tmpCellCoord.x, tmpCellCoord.y);
+                                    }
+                                }
+                            }
+                        }
+
+                        //
+                        // Test pmCoordCellToSkyQuick() -> pmCoordSkyToCellQuick()
+                        // I'm not sure how to test this in a system with chip and cell gaps.
+                        // There's no way to create an accurate polynomial transform from
+                        // a cell to the sky where there are cell, or chip gaps.
+                        //
+                        if ((NUM_CHIPS == 1) && (NUM_CELLS == 1)) {
+                            psPlane tmpCellCoord;
+                            psSphere *rc = pmCoordCellToSkyQuick(skyCoord, &cellCoord, myCell);
+                            if (rc == NULL) {
+                                printf("pmCoordCellToSkyQuick() failed.\n");
+                            } else {
+                                psPlane *rc = pmCoordSkyToCellQuick(&tmpCellCoord, skyCoord, myCell);
+                                if (rc == NULL) {
+                                    printf("pmCoordSkyToCellQuick() failed.\n");
+                                } else {
+                                    if (fabs(cellCoord.x - tmpCellCoord.x) > FLT_EPSILON) {
+                                        printf("TEST ERROR: pmCoordCellToSky()/pmCoordSkyToCell() x coord was %.2f, should be %.2f\n", tmpCellCoord.x, cellCoord.x);
+                                        testStatus = 1;
+                                    }
+                                    if (fabs(cellCoord.y - tmpCellCoord.y) > FLT_EPSILON) {
+                                        printf("TEST ERROR: pmCoordCellToSky()/pmCoordSkyToCell() y coord was %.2f, should be %.2f\n", tmpCellCoord.y, cellCoord.y);
+                                        testStatus = 1;
+                                    }
+                                    if (VERBOSE) {
+                                        printf("(%.2f %.2f) -> (%.2f %.2f) -> (%.2f %.2f)\n", testCoord.x, testCoord.y, skyCoord->r, skyCoord->d, tmpCellCoord.x, tmpCellCoord.y);
+                                    }
+                                }
+                            }
+                        }
+
+                        pmCoordCellToFPA(&testCoord, &cellCoord, myCell);
+                        if (fabs(testCoord.x - fpaCoord.x) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordCellToFPA() x coord was %.2f, should be %d\n", cellCoord.x, x);
+                            testStatus = 1;
+                        }
+                        if (fabs(testCoord.y - fpaCoord.y) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordCellToFPA() y coord was %.2f, should be %d\n", cellCoord.y, y);
+                            testStatus = 1;
+                        }
+
+                        pmCoordTPToFPA(&testCoord, &fpaCoord, 0.0, 0.0, myFPA);
+                        if (fabs(testCoord.x - fpaCoord.x) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordTPToFPA() x coord was %.2f, should be %d\n", cellCoord.x, x);
+                            testStatus = 1;
+                        }
+                        if (fabs(testCoord.y - fpaCoord.y) > FLT_EPSILON) {
+                            printf("TEST ERROR: pmCoordTPToFPA() y coord was %.2f, should be %d\n", cellCoord.y, y);
+                            testStatus = 1;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    psFree(myFPA);
+    psFree(skyCoord);
+
+    return(testStatus);
+}
+
+/******************************************************************************
+test4(): This routine wil test the pmFPACheckParents() function.  We generate
+an pmFPA hierarchy, then set the parents of each readout/cell/chip to NULL,
+then call pmFPACheckParents() to restore them, then we ensure they were
+restored.
+ *****************************************************************************/
+psS32 test4( void )
+{
+    psS32 testStatus = 0;
+
+    //
+    // Generate a pmFPA hierarchy.
+    //
+    pmFPA *tmpFPA = genSystem();
+
+    //
+    // We set the parents of each readout/cell/chip to NULL.
+    //
+    for (psS32 chipID = 0; chipID < tmpFPA->chips->n ; chipID++) {
+        pmChip *tmpChip = (pmChip *) tmpFPA->chips->data[chipID];
+        tmpChip->parent = NULL;
+
+        for (psS32 cellID = 0; cellID < tmpChip->cells->n ; cellID++) {
+            pmCell *tmpCell = (pmCell *) tmpChip->cells->data[cellID];
+            tmpCell->parent = NULL;
+
+            for (psS32 readoutID = 0; readoutID < tmpCell->readouts->n ; readoutID++) {
+                pmReadout *tmpReadout = (pmReadout *) tmpCell->readouts->data[readoutID];
+                tmpReadout->parent = NULL;
+            }
+        }
+    }
+
+    //
+    // Ensure that pmFPACheckParents() returned FALSE.
+    //
+    psBool rc = pmFPACheckParents(tmpFPA);
+    if (rc != false) {
+        printf("TEST ERROR: pmCheckParents() returned TRUE.\n");
+        testStatus = 1;
+    }
+
+    //
+    // Ensure that the parent members are right.
+    //
+    for (psS32 chipID = 0; chipID < tmpFPA->chips->n ; chipID++) {
+        pmChip *tmpChip = (pmChip *) tmpFPA->chips->data[chipID];
+        if (tmpChip->parent != tmpFPA) {
+            printf("TEST ERROR: pmCheckParents() did not restore Chip->parent.\n");
+            testStatus = 2;
+        }
+
+        for (psS32 cellID = 0; cellID < tmpChip->cells->n ; cellID++) {
+            pmCell *tmpCell = (pmCell *) tmpChip->cells->data[cellID];
+            if (tmpCell->parent != tmpChip) {
+                printf("TEST ERROR: pmCheckParents() did not restore Cell->parent.\n");
+                testStatus = 3;
+            }
+
+            for (psS32 readoutID = 0; readoutID < tmpCell->readouts->n ; readoutID++) {
+                pmReadout *tmpReadout = (pmReadout *) tmpCell->readouts->data[readoutID];
+                if (tmpReadout->parent != tmpCell) {
+                    printf("TEST ERROR: pmCheckParents() did not restore Readout->parent.\n");
+                    testStatus = 4;
+                }
+            }
+        }
+    }
+
+    psFree(tmpFPA);
+    return(testStatus);
+}
+
+/******************************************************************************
+test5(): This routine wil test the pmFPASelectChip() and pmFPAExcludeChip()
+functions.  We generate an pmFPA hierarchy, then set the ->valid members with
+those routines, then verify.
+ *****************************************************************************/
+psS32 test5( void )
+{
+    psS32 testStatus = 0;
+    pmChip *tmpChip = NULL;
+
+    //
+    // Generate a pmFPA hierarchy.
+    //
+    pmFPA *tmpFPA = genSystem();
+
+    //
+    // We test the ->valid member for each chip.
+    //
+    for (psS32 i = 0 ; i < tmpFPA->chips->n ; i++) {
+        tmpChip = (pmChip *) tmpFPA->chips->data[i];
+        if ((tmpChip == NULL) || (tmpChip->valid != false)) {
+            printf("TEST ERROR: Could not properly generate an FPA hierarchy.\n");
+            testStatus = 1;
+        }
+    }
+
+    //
+    // Exclude chip number 0, include all others, then test return value
+    //
+    psS32 numChips = pmFPAExcludeChip(tmpFPA, 0);
+    if (numChips != (NUM_CHIPS-1)) {
+        printf("TEST ERROR: pmFPAExcludeChip() did not return the correct number of chips.\n");
+        testStatus = 2;
+    }
+
+    //
+    // We test the ->valid member for each chip.
+    //
+    tmpChip = (pmChip *) tmpFPA->chips->data[0];
+    if (tmpChip->valid != false) {
+        printf("TEST ERROR: pmFPAExcludeChip() did not set the proper chip->valid to FALSE.\n");
+        testStatus = 3;
+    }
+    for (psS32 i = 1 ; i < tmpFPA->chips->n ; i++) {
+        pmChip *tmpChip = (pmChip *) tmpFPA->chips->data[i];
+        if (tmpChip->valid != true) {
+            printf("TEST ERROR: pmFPAExcludeChip() did not set the proper chip->valids to FALSE.\n");
+            testStatus = 4;
+        }
+    }
+
+
+    //
+    // Include chip number 0, exclude all others, then test return value
+    //
+    psBool tmpBool = pmFPASelectChip(tmpFPA, 0);
+    if (tmpBool != true) {
+        printf("TEST ERROR: pmFPASelectChip() returned FALSE.\n");
+        testStatus = 5;
+    }
+
+    //
+    // We test the ->valid member for each chip.
+    //
+    tmpChip = (pmChip *) tmpFPA->chips->data[0];
+    if (tmpChip->valid != true) {
+        printf("TEST ERROR: pmFPASelectChip() did not set the proper chip->valid to FALSE.\n");
+        testStatus = 6;
+    }
+    for (psS32 i = 1 ; i < tmpFPA->chips->n ; i++) {
+        pmChip *tmpChip = (pmChip *) tmpFPA->chips->data[i];
+        if (tmpChip->valid != false) {
+            printf("TEST ERROR: pmFPASelectChip() did not set the proper chip->valids to FALSE.\n");
+            testStatus = 7;
+        }
+    }
+
+    psFree(tmpFPA);
+    return(testStatus);
+}
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(92);
+
+    test3();
+    test4();
+    test5();
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPA.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPA.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPA.c	(revision 22158)
@@ -0,0 +1,492 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    All functions are tested.
+*/
+
+#define CHIP_ALLOC_NAME "ChipName"
+#define CELL_ALLOC_NAME "CellName"
+#define MISC_NUM 32
+#define MISC_NAME "META00"
+#define MISC_NAME2 "META01"
+#define NUM_BIAS_DATA 10
+#define TEST_NUM_ROWS 32
+#define TEST_NUM_COLS 32
+#define NUM_READOUTS	4
+#define NUM_CELLS	6
+#define NUM_CHIPS	8
+
+psPlaneTransform *PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM()
+{
+    psPlaneTransform *pt = psPlaneTransformAlloc(1, 1);
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+    return(pt);
+}
+
+psPlaneDistort *PS_CREATE_4D_IDENTITY_PLANE_DISTORT()
+{
+    psPlaneDistort *pd = psPlaneDistortAlloc(1, 1, 1, 1);
+    pd->x->coeff[1][0][0][0] = 1.0;
+    pd->y->coeff[0][1][0][0] = 1.0;
+    return(pd);
+}
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    cell->hdu = pmHDUAlloc(NULL);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = psMemDecrRefCounter((psPtr) generateSimpleReadout(cell));
+    }
+    return(cell);
+}
+
+/******************************************************************************
+generateSimpleChip(): This function generates a pmChip data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmChip *generateSimpleChip(pmFPA *fpa)
+{
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    chip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    chip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    psMetadataAddS32(chip->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(chip->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    chip->hdu = pmHDUAlloc(NULL);
+    psArrayRealloc(chip->cells, NUM_CELLS);
+    for (int i = 0 ; i < NUM_CELLS ; i++) {
+        chip->cells->data[i] = psMemDecrRefCounter((psPtr) generateSimpleCell(chip));
+    }
+    return(chip);
+}
+
+/******************************************************************************
+generateSimpleFPA(): This function generates a pmFPA data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmFPA* generateSimpleFPA(psMetadata *camera)
+{
+    pmFPA* fpa = pmFPAAlloc(camera);
+    fpa->fromTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toSky = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+    psMetadataAddS32(fpa->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    if (camera != NULL) {
+        psMetadataAddS32((psMetadata *) fpa->camera, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    }
+    psMetadataAddS32(fpa->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    fpa->hdu = pmHDUAlloc(NULL);
+    psArrayRealloc(fpa->chips, NUM_CHIPS);
+    for (int i = 0 ; i < NUM_CHIPS ; i++) {
+        fpa->chips->data[i] = psMemDecrRefCounter((psPtr) generateSimpleChip(fpa));
+    }
+
+    return(fpa);
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(92);
+
+    // ------------------------------------------------------------------------
+    // pmFPAAlloc() tests
+    // Call pmFPAAlloc() with NULL pmCamera input.
+    {
+        psMemId id = psMemGetId();
+        pmFPA* fpa = pmFPAAlloc(NULL);
+        ok(fpa != NULL && psMemCheckFPA(fpa), "pmFPAAlloc() returned a non-NULL pmFPA with a NULL pmCamera input");
+        psFree(fpa);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Call pmFPAAlloc() with acceptable input parameters.
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = pmFPAAlloc(camera);
+        ok(fpa != NULL, "pmFPAAlloc() returned a non-NULL");
+        ok(fpa->fromTPA == NULL, "pmFPAAlloc() set ->fromTPA to NULL");
+        ok(fpa->toTPA == NULL, "pmFPAAlloc() set ->toTPA to NULL");
+        ok(fpa->toSky == NULL, "pmFPAAlloc() set ->toSky to NULL");
+        ok(fpa->concepts != NULL &&
+           psMemCheckMetadata(fpa->concepts), "pmFPAAlloc() set ->concepts correctly");
+        ok(fpa->conceptsRead == PM_CONCEPT_SOURCE_NONE, "pmFPAAlloc() set ->conceptsRead correctly");
+        ok(fpa->analysis != NULL &&
+           psMemCheckMetadata(fpa->analysis), "pmFPAAlloc() set ->analysis correctly");
+        ok(fpa->camera == camera, "pmFPAAlloc() set ->camera correctly");
+        ok(fpa->chips != NULL &&
+           psMemCheckArray(fpa->chips), "pmFPAAlloc() set ->chips correctly");
+        ok(fpa->hdu == NULL, "pmFPAAlloc() set ->hdu to NULL");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Populate the pmFPA struct with real data to ensure they were psFree()'ed correctly.
+    {
+        psMemId id = psMemGetId();
+        pmFPA* fpa = generateSimpleFPA(NULL);
+        psFree(fpa);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks (Populate the pmFPA struct with real data)");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // pmFPAFreeData() tests
+    // Call pmFPAFreeData() with NULL pmFPA input parameter
+    {
+        psMemId id = psMemGetId();
+        pmFPAFreeData(NULL);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks (Call pmFPAFreeData() with NULL pmFPA input parameter)");
+    }
+
+
+    // Call pmFPAFreeData() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmFPA* fpa = generateSimpleFPA(NULL);
+        fpa->hdu->images = psArrayAlloc(10);
+        fpa->hdu->weights = psArrayAlloc(10);
+        fpa->hdu->masks = psArrayAlloc(10);
+        pmFPAFreeData(fpa);
+        ok(fpa->hdu->images == NULL, "pmFPAFreeData() correctly set fpa->hdu->images to NULL");
+        ok(fpa->hdu->weights == NULL, "pmFPAFreeData() correctly set fpa->hdu->weights to NULL");
+        ok(fpa->hdu->masks == NULL, "pmFPAFreeData() correctly set fpa->hdu->masks to NULL");
+        psFree(fpa);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // pmChipAlloc() tests
+    // Call pmChipAlloc() with NULL input parameters
+    {
+        psMemId id = psMemGetId();
+        pmChip *chip = pmChipAlloc(NULL, CHIP_ALLOC_NAME);
+        ok(chip != NULL, "pmChipAlloc() returned non-NULL with NULL pmFPA input parameter");
+        psFree(chip);
+        pmFPA* fpa = generateSimpleFPA(NULL);
+        chip = pmChipAlloc(fpa, NULL);
+        ok(chip != NULL, "pmChipAlloc() returned non-NULL with NULL chip name input parameter");
+        psFree(fpa);
+        psFree(chip);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmChipAlloc() tests
+    // XXX: Add tests for NULL inputs.
+    {
+        psMemId id = psMemGetId();
+        pmFPA* fpa = generateSimpleFPA(NULL);
+        pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+        ok(chip != NULL, "pmChipAlloc() returned non-NULL");
+        ok(chip->toFPA == NULL, "pmChipAlloc() set chip->toChip to NULL");
+        ok(chip->fromFPA == NULL, "pmChipAlloc() set chip->fromChip to NULL");
+        ok(chip->concepts != NULL &&
+           psMemCheckMetadata(chip->concepts), "pmChipAlloc() set ->concepts correctly");
+        ok(chip->conceptsRead == PM_CONCEPT_SOURCE_NONE, "pmCellAlloc() set ->conceptsRead correctly");
+        ok(chip->analysis != NULL &&
+           psMemCheckMetadata(chip->analysis), "pmChipAlloc() set ->analysis correctly");
+        ok(chip->cells != NULL &&
+           psMemCheckArray(chip->cells), "pmChipAlloc() set ->cells correctly");
+        ok(chip->parent == fpa, "pmChipAlloc() set ->parent correctly");
+        ok(chip->process == true, "pmChipAlloc() set ->process correctly");
+        ok(chip->file_exists == false, "pmChipAlloc() set ->file_exists correctly");
+        ok(chip->data_exists == false, "pmChipAlloc() set ->data_exists correctly");
+        ok(chip->hdu == NULL, "pmChipAlloc() set ->hdu to NULL");
+        psFree(fpa);
+        psFree(chip);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Populate the pmChip struct with real data to ensure they were free'ed correctly.
+    {
+        psMemId id = psMemGetId();
+        pmChip *chip = generateSimpleChip(NULL);
+        psFree(chip);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks (Populate the pmChip struct with real data)");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // pmChipFreeData() tests
+    // Call pmChipFreeData() with NULL pmFPA input parameter
+    {
+        psMemId id = psMemGetId();
+        pmChipFreeData(NULL);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks (Call pmChipFreeData() with NULL pmFPA input parameter)");
+    }
+
+
+    // Call pmChipFreeData() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmChip* chip = generateSimpleChip(NULL);
+        chip->hdu->images = psArrayAlloc(10);
+        chip->hdu->weights = psArrayAlloc(10);
+        chip->hdu->masks = psArrayAlloc(10);
+        pmChipFreeData(chip);
+        ok(chip->hdu->images == NULL, "pmChipFreeData() correctly set chip->hdu->images to NULL");
+        ok(chip->hdu->weights == NULL, "pmChipFreeData() correctly set chip->hdu->weights to NULL");
+        ok(chip->hdu->masks == NULL, "pmChipFreeData() correctly set chip->hdu->masks to NULL");
+        psFree(chip);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // pmChipFreeCells() tests
+    // Call pmChipFreeCells() with NULL pmFPA input parameter
+    {
+        psMemId id = psMemGetId();
+        pmChipFreeCells(NULL);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks (Call pmChipFreeCells() with NULL pmFPA input parameter)");
+    }
+
+
+    // Call pmChipFreeCells() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmChip* chip = generateSimpleChip(NULL);
+        pmChipFreeCells(chip);
+        ok(chip->cells->n == 0, "pmChipFreeCells() free'ed chip->cells correctly");
+        psFree(chip);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // pmCellAlloc() tests
+    // Call pmCellAlloc() with NULL input parameters
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = pmCellAlloc(NULL, CELL_ALLOC_NAME);
+        ok(cell != NULL, "pmCellAlloc returned non-NULL with NULL pmChip input parameter");
+        psFree(cell);
+
+        pmChip *chip = pmChipAlloc(NULL, NULL);
+        cell = pmCellAlloc(chip, NULL);
+        ok(cell != NULL, "pmCellAlloc returned non-NULL with NULL cell name input parameter");
+        psFree(chip);
+        psFree(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmCellAlloc() tests
+    // Call pmCellAlloc() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+        pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+        ok(cell != NULL, "pmCellAlloc returned non-NULL");
+        ok(cell->concepts != NULL &&
+           psMemCheckMetadata(cell->concepts), "pmCellpAlloc() set ->concepts correctly");
+        ok(cell->conceptsRead == PM_CONCEPT_SOURCE_NONE, "pmCellAlloc() set ->conceptsRead correctly");
+        ok(cell->config == NULL, "pmCellpAlloc() set ->config to NULL");
+        ok(cell->analysis != NULL &&
+           psMemCheckMetadata(cell->analysis), "pmCellAlloc() set ->analysis correctly");
+        ok(cell->readouts != NULL &&
+           psMemCheckArray(cell->readouts), "pmCellAlloc() set ->readouts correctly");
+        ok(cell->parent == chip, "pmCellAlloc() set ->parent correctly");
+        ok(cell->process == true, "pmCellAlloc() set ->process correctly");
+        ok(cell->file_exists == false, "pmCellAlloc() set ->file_exists correctly");
+        ok(cell->data_exists == false, "pmCellAlloc() set ->data_exists correctly");
+        ok(cell->hdu == NULL, "pmCellAlloc() set ->hdu to NULL");
+        psFree(camera);
+        psFree(fpa);
+        psFree(chip);
+        psFree(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Populate the pmCell struct with real data to ensure they were
+    // psFree()'ed correctly.
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        psFree(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks (Populate the pmCell struct with real data)");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // pmCellFreeData() tests
+    // Call pmCellFreeData() with NULL pmFPA input parameter
+    {
+        psMemId id = psMemGetId();
+        pmCellFreeData(NULL);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks (Call pmCellFreeData() with NULL pmFPA input parameter)");
+    }
+
+
+    // Call pmCellFreeData() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        cell->hdu->images = psArrayAlloc(10);
+        cell->hdu->weights = psArrayAlloc(10);
+        cell->hdu->masks = psArrayAlloc(10);
+        pmCellFreeData(cell);
+        ok(cell->hdu->images == NULL, "pmCellFreeData() correctly set cell->hdu->images to NULL");
+        ok(cell->hdu->weights == NULL, "pmCellFreeData() correctly set cell->hdu->weights to NULL");
+        ok(cell->hdu->masks == NULL, "pmCellFreeData() correctly set cell->hdu->masks to NULL");
+        psFree(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // test pmCellFreeReadouts()
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmCellFreeReadouts(cell);
+        ok(cell->readouts->n == 0, "pmCellFreeReadouts() correctly set cell->readouts->n to 0");
+        psFree(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks (pmCellFreeReadouts)");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // pmReadoutAlloc() tests
+    // Call pmReadoutAlloc() with NULL input parameters
+    {
+        psMemId id = psMemGetId();
+        pmReadout *readout = pmReadoutAlloc(NULL);
+        ok(readout != NULL, "pmReadoutAlloc() returned non-NULL with NULL pmCell input parameter");
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmReadoutAlloc() with acceptable parameters
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+        pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+        pmReadout *readout = pmReadoutAlloc(cell);
+        ok(readout != NULL, "pmReadoutAlloc() returned non-NULL");
+        ok(readout->col0 == 0, "pmReadoutAlloc() set ->col0 correctly");
+        ok(readout->row0 == 0, "pmReadoutAlloc() set ->row0 correctly");
+        ok(readout->image == NULL, "pmReadoutAlloc() set ->image correctly");
+        ok(readout->mask == NULL, "pmReadoutAlloc() set ->mask correctly");
+        ok(readout->weight == NULL, "pmReadoutAlloc() set ->weight correctly");
+        ok(readout->bias != NULL &&
+           psMemCheckList(readout->bias), "pmReadoutAlloc() set ->bias correctly");
+        ok(readout->analysis != NULL &&
+           psMemCheckMetadata(readout->analysis), "pmReadoutAlloc() set ->analysis correctly");
+        ok(readout->parent == cell, "pmReadoutAlloc() set ->parent correctly");
+        ok(readout->process == true, "pmReadoutAlloc() set ->process correctly");
+        ok(readout->file_exists == false, "pmReadoutAlloc() set ->file_exists correctly");
+        ok(readout->data_exists == false, "pmReadoutAlloc() set ->data_exists correctly");
+        psFree(camera);
+        psFree(fpa);
+        psFree(chip);
+        psFree(cell);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Populate the pmReadout struct with real data to ensure they were
+    // psFree()'ed correctly.
+    {
+        psMemId id = psMemGetId();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        psFree(readout);
+        // XXX: The pmReadout->bias list is not being free'ed correctly.
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // pmReadoutFreeData() tests
+    // Call pmReadoutFreeData() with NULL pmFPA input parameter
+    {
+        psMemId id = psMemGetId();
+        pmReadoutFreeData(NULL);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks (Call pmReadoutFreeData() with NULL pmFPA input parameter)");
+    }
+
+
+    // Call pmReadoutFreeData() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        pmReadoutFreeData(readout);
+        ok(readout->image == NULL, "pmReadoutFreeData() correctly set readout->image to NULL");
+        ok(readout->weight == NULL, "pmReadoutFreeData() correctly set readout->weight to NULL");
+        ok(readout->mask == NULL, "pmReadoutFreeData() correctly set readout->mask to NULL");
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // pmFPACheckParents() tests
+    // psBool pmFPACheckParents(pmFPA *fpa)
+    // Call pmFPACheckParents() with NULL pmFPA input parameter
+    {
+        psMemId id = psMemGetId();
+        bool rc = pmFPACheckParents(NULL);
+        ok(rc == false, "pmFPACheckParents() returned FALSE with NULL pmFPA input parameter");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPACheckParents() tests
+    // Call pmFPACheckParents() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmFPA* fpa = generateSimpleFPA(NULL);
+        bool rc = pmFPACheckParents(fpa);
+        ok(rc == true, "pmFPACheckParents() returned FALSE with acceptable input parameters");
+        psFree(fpa);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPACellSquish.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPACellSquish.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPACellSquish.c	(revision 22158)
@@ -0,0 +1,193 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+// XXX: Use better name for the temporary FITS file
+// XXX: The code to generate and free the FPA hierarchy was copied from
+// tap-pmFPA.c.  EIther include it directly, or library, or something.
+// Also, get rid of the manual free functions and use psFree() once
+// it correctly frees child members
+// XXX: For the genSimpleFPA() code, add IDs to each function so that
+// the values set in each chip-?cell-?hdu-?image are unique
+// XXX: For the genSimpleFPA() code, write masks and weights as well
+
+#define CHIP_ALLOC_NAME        "ChipName"
+#define CELL_ALLOC_NAME        "CellName"
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define MISC_NAME2             "META01"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           4
+#define TEST_NUM_COLS           4
+#define NUM_READOUTS            3
+#define NUM_CELLS               10
+#define NUM_CHIPS               8
+#define NUM_HDUS                5
+#define BASE_IMAGE              10
+#define BASE_MASK               40
+#define BASE_WEIGHT             70
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+psPlaneTransform *PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM()
+{
+    psPlaneTransform *pt = psPlaneTransformAlloc(1, 1);
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+    return(pt);
+}
+
+psPlaneDistort *PS_CREATE_4D_IDENTITY_PLANE_DISTORT()
+{
+    psPlaneDistort *pd = psPlaneDistortAlloc(1, 1, 1, 1);
+    pd->x->coeff[1][0][0][0] = 1.0;
+    pd->y->coeff[0][1][0][0] = 1.0;
+    return(pd);
+}
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    cell->hdu = pmHDUAlloc("cellExtName");
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = psMemDecrRefCounter((psPtr) generateSimpleReadout(cell));
+    }
+
+    // First try to read data from ../dataFiles, then try dataFiles.
+    bool rc = pmConfigFileRead(&cell->hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        rc = pmConfigFileRead(&cell->hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            diag("pmConfigFileRead() was unsuccessful (from generateSimpleCell())");
+	}
+    }
+
+    cell->hdu->images = psArrayAlloc(NUM_HDUS);
+    cell->hdu->masks = psArrayAlloc(NUM_HDUS);
+    cell->hdu->weights = psArrayAlloc(NUM_HDUS);
+    for (int k = 0 ; k < NUM_HDUS ; k++) {
+        cell->hdu->images->data[k]  = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        cell->hdu->masks->data[k]   = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        cell->hdu->weights->data[k] = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(cell->hdu->images->data[k], (float) (BASE_IMAGE+k));
+        psImageInit(cell->hdu->masks->data[k], (psU8) (BASE_MASK+k));
+        psImageInit(cell->hdu->weights->data[k], (float) (BASE_WEIGHT+k));
+    }
+
+    //XXX: Should the region be set some other way?  Like through the various config files?
+//    psRegion *region = psRegionAlloc(0.0, TEST_NUM_COLS-1, 0.0, TEST_NUM_ROWS-1);
+    psRegion *region = psRegionAlloc(0.0, 0.0, 0.0, 0.0);
+    // You shouldn't have to remove the key from the metadata.  Find out how to simply change the key value.
+    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC");
+    psMetadataAddPtr(cell->concepts, PS_LIST_TAIL|PS_META_REPLACE, "CELL.TRIMSEC", PS_DATA_REGION, "I am a region", region);
+    psFree(region);
+    return(cell);
+}
+
+/******************************************************************************
+generateSimpleChip(): This function generates a pmChip data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmChip *generateSimpleChip(pmFPA *fpa)
+{
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    chip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    chip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    psMetadataAddS32(chip->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(chip->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    psArrayRealloc(chip->cells, NUM_CELLS);
+    for (int i = 0 ; i < NUM_CELLS ; i++) {
+        chip->cells->data[i] = psMemDecrRefCounter((psPtr) generateSimpleCell(chip));
+    }
+    return(chip);
+}
+
+/******************************************************************************
+generateSimpleFPA(): This function generates a pmFPA data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmFPA* generateSimpleFPA(psMetadata *camera)
+{
+    pmFPA* fpa = pmFPAAlloc(camera);
+    fpa->fromTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toSky = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+    psMetadataAddS32(fpa->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    if (camera != NULL) {
+        psMetadataAddS32((psMetadata *) fpa->camera, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    }
+    psMetadataAddS32(fpa->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(fpa->chips, NUM_CHIPS);
+    for (int i = 0 ; i < NUM_CHIPS ; i++) {
+        fpa->chips->data[i] = psMemDecrRefCounter((psPtr) generateSimpleChip(fpa));
+    }
+
+    pmConceptsBlankFPA(fpa);
+    return(fpa);
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(4);
+
+
+    // ----------------------------------------------------------------------
+    // pmCellSquish() tests
+    // bool pmCellSquish(pmCell *cell, psMaskType maskVal, bool useShifts)
+    {
+        psMemId id = psMemGetId();
+        ok(!pmCellSquish(NULL, 0, false), "pmCellSquish(NULL) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // ----------------------------------------------------------------------
+    // pmCellSquish() tests
+    // bool pmCellSquish(pmCell *cell, psMaskType maskVal, bool useShifts)
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(pmCellSquish(cell, 0, false), "pmCellSquish(NULL) returned NULL");
+        psFree(camera);
+        psFree(fpa);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAConstruct.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAConstruct.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAConstruct.c	(revision 22158)
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(9);
+
+    // ----------------------------------------------------------------------
+    // pmFPAConstruct() tests
+    // pmFPA *pmFPAConstruct(const psMetadata *camera)
+    // test will NULL camera input param
+    {
+        psMemId id = psMemGetId();
+        pmFPA* fpa = pmFPAConstruct(NULL);
+        ok(fpa == NULL, "pmFPAConstruct() NULL will NULL camera input param");
+        psFree(fpa);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // pmFPA *pmFPAConstruct(const psMetadata *camera)
+    // test will acceptable data
+    // XXX: The memory leak code is put outside the call to pmConfigFileRead() because of
+    // a memory leak in pmConfigFileRead().
+    {
+        psMetadata *camera = psMetadataAlloc();
+        bool rc = pmConfigFileRead(&camera, "dataFiles/camera0/camera.config", "CAMERA 0 config file");
+        if (!rc) {
+             rc = pmConfigFileRead(&camera, "../dataFiles/camera0/camera.config", "CAMERA 0 config file");
+	}
+
+        // Generate the pmFPA heirarchy
+        psMemId id = psMemGetId();
+        ok(rc, "Succesfully read camera format file");
+        pmFPA* fpa = pmFPAConstruct(camera);
+        ok(fpa != NULL, "pmFPAConstruct() returned non-NULL");
+        if (VERBOSE) {
+            pmFPAPrint(stdout, fpa, true, true);
+	}
+        bool errorFlag = false;
+        ok(fpa->chips->n == 2, "pmFPAConstruct() set fpa->chips->n (%d)", fpa->chips->n);
+        for (int chipID = 0 ; chipID < fpa->chips->n ; chipID++) {
+            pmChip *chip = fpa->chips->data[chipID];
+            ok(chip->cells->n == 2, "pmFPAConstruct() set chip->cells->n (%d)", chip->cells->n);
+            for (int cellID = 0 ; cellID < chip->cells->n ; cellID++) {
+                pmCell *cell = chip->cells->data[cellID];
+                for (int readoutID = 0 ; readoutID < cell->readouts->n ; readoutID++) {
+                    pmReadout *readout = cell->readouts->data[readoutID];
+                    readout = readout;
+		}
+	    }
+	}
+        ok(!errorFlag, "pmFPAConstruct() read the pmFPA structure correctly");
+
+
+
+
+        psFree(fpa);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+
+        psFree(camera);
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPACopy.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPACopy.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPACopy.c	(revision 22158)
@@ -0,0 +1,601 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define CHIP_ALLOC_NAME		"ChipName"
+#define CELL_ALLOC_NAME		"CellName"
+#define MISC_NUM_SOURCE		32
+#define MISC_NUM_TARGET		16
+#define MISC_NAME_SOURCE	"META00_SOURCE"
+#define MISC_NAME_TARGET	"META00_TARGET"
+#define NUM_BIAS_DATA		10
+#define SOURCE_NUM_ROWS		16
+#define SOURCE_NUM_COLS		8
+#define TARGET_NUM_ROWS		15
+#define TARGET_NUM_COLS		5
+#define NUM_READOUTS		4
+#define NUM_CELLS		6
+#define NUM_CHIPS		8
+#define SOURCE_BASE		10
+#define BASE_INC		20
+#define TARGET_BASE		(SOURCE_BASE + BASE_INC)
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+psPlaneTransform *PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM()
+{
+    psPlaneTransform *pt = psPlaneTransformAlloc(1, 1);
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+    return(pt);
+}
+
+psPlaneDistort *PS_CREATE_4D_IDENTITY_PLANE_DISTORT()
+{
+    psPlaneDistort *pd = psPlaneDistortAlloc(1, 1, 1, 1);
+    pd->x->coeff[1][0][0][0] = 1.0;
+    pd->y->coeff[0][1][0][0] = 1.0;
+    return(pd);
+}
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadoutSource(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(SOURCE_NUM_COLS, SOURCE_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(SOURCE_NUM_COLS, SOURCE_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(SOURCE_NUM_COLS, SOURCE_NUM_ROWS, PS_TYPE_F32);
+    for (int i = 0 ; i < SOURCE_NUM_ROWS ; i++) {
+        for (int j = 0 ; j < SOURCE_NUM_COLS ; j++) {
+            readout->image->data.F32[i][j] = (float) (i + j + SOURCE_BASE);
+            readout->mask->data.U8[i][j] = (psU8) (i + j + SOURCE_BASE);
+            readout->weight->data.F32[i][j] = (float) (i + j + SOURCE_BASE);
+	}
+    }
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(SOURCE_NUM_COLS, SOURCE_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME_SOURCE, 0, NULL, MISC_NUM_SOURCE);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCellSource(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME_SOURCE, 0, NULL, MISC_NUM_SOURCE);
+    cell->hdu = pmHDUAlloc(NULL);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME_SOURCE, 0, NULL, MISC_NUM_SOURCE);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, "CELL.XPARITY", PS_META_REPLACE, NULL, 1);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, "CELL.YPARITY", PS_META_REPLACE, NULL, 1);
+
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = psMemDecrRefCounter((psPtr) generateSimpleReadoutSource(cell));
+    }
+    cell->data_exists = true;
+    return(cell);
+}
+
+/******************************************************************************
+generateSimpleChip(): This function generates a pmChip data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmChip *generateSimpleChipSource(pmFPA *fpa)
+{
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    chip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    chip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    psMetadataAddS32(chip->analysis, PS_LIST_HEAD, MISC_NAME_SOURCE, 0, NULL, MISC_NUM_SOURCE);
+    psMetadataAddS32(chip->concepts, PS_LIST_HEAD, MISC_NAME_SOURCE, 0, NULL, MISC_NUM_SOURCE);
+    chip->hdu = pmHDUAlloc(NULL);
+    psArrayRealloc(chip->cells, NUM_CELLS);
+    for (int i = 0 ; i < NUM_CELLS ; i++) {
+        chip->cells->data[i] = psMemDecrRefCounter((psPtr) generateSimpleCellSource(chip));
+    }
+    chip->data_exists = true;
+    return(chip);
+}
+
+/******************************************************************************
+generateSimpleFPA(): This function generates a pmFPA data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmFPA* generateSimpleFPASource(psMetadata *camera)
+{
+    pmFPA* fpa = pmFPAAlloc(camera);
+    fpa->fromTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toSky = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+    psMetadataAddS32(fpa->analysis, PS_LIST_HEAD, MISC_NAME_SOURCE, 0, NULL, MISC_NUM_SOURCE);
+    if (camera != NULL) {
+        psMetadataAddS32((psMetadata *) fpa->camera, PS_LIST_HEAD, MISC_NAME_SOURCE, 0, NULL, MISC_NUM_SOURCE);
+    }
+    psMetadataAddS32(fpa->concepts, PS_LIST_HEAD, MISC_NAME_SOURCE, 0, NULL, MISC_NUM_SOURCE);
+    fpa->hdu = pmHDUAlloc(NULL);
+    psArrayRealloc(fpa->chips, NUM_CHIPS);
+    for (int i = 0 ; i < NUM_CHIPS ; i++) {
+        fpa->chips->data[i] = psMemDecrRefCounter((psPtr) generateSimpleChipSource(fpa));
+    }
+
+    return(fpa);
+}
+
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadoutTarget(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TARGET_NUM_COLS, TARGET_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TARGET_NUM_COLS, TARGET_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TARGET_NUM_COLS, TARGET_NUM_ROWS, PS_TYPE_F32);
+    for (int i = 0 ; i < TARGET_NUM_ROWS ; i++) {
+        for (int j = 0 ; j < TARGET_NUM_COLS ; j++) {
+            readout->image->data.F32[i][j] = (float) (i + j + TARGET_BASE);
+            readout->mask->data.U8[i][j] = (psU8) (i + j + TARGET_BASE);
+            readout->weight->data.F32[i][j] = (float) (i + j + TARGET_BASE);
+	}
+    }
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TARGET_NUM_COLS, TARGET_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME_TARGET, 0, NULL, MISC_NUM_TARGET);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCellTarget(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME_TARGET, 0, NULL, MISC_NUM_TARGET);
+    cell->hdu = pmHDUAlloc(NULL);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME_TARGET, 0, NULL, MISC_NUM_TARGET);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, "CELL.XPARITY", PS_META_REPLACE, NULL, 1);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, "CELL.YPARITY", PS_META_REPLACE, NULL, 1);
+    psArrayRealloc(cell->readouts, 0);
+    for (int i = 0 ; i < 0 ; i++) {
+        cell->readouts->data[i] = psMemDecrRefCounter((psPtr) generateSimpleReadoutTarget(cell));
+    }
+    return(cell);
+}
+
+/******************************************************************************
+generateSimpleChip(): This function generates a pmChip data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmChip *generateSimpleChipTarget(pmFPA *fpa)
+{
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    chip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    chip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    psMetadataAddS32(chip->analysis, PS_LIST_HEAD, MISC_NAME_TARGET, 0, NULL, MISC_NUM_TARGET);
+    psMetadataAddS32(chip->concepts, PS_LIST_HEAD, MISC_NAME_TARGET, 0, NULL, MISC_NUM_TARGET);
+    chip->hdu = pmHDUAlloc(NULL);
+    psArrayRealloc(chip->cells, NUM_CELLS);
+    for (int i = 0 ; i < NUM_CELLS ; i++) {
+        chip->cells->data[i] = psMemDecrRefCounter((psPtr) generateSimpleCellTarget(chip));
+    }
+    return(chip);
+}
+
+/******************************************************************************
+generateSimpleFPA(): This function generates a pmFPA data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmFPA* generateSimpleFPATarget(psMetadata *camera)
+{
+    pmFPA* fpa = pmFPAAlloc(camera);
+    fpa->fromTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toSky = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+    psMetadataAddS32(fpa->analysis, PS_LIST_HEAD, MISC_NAME_TARGET, 0, NULL, MISC_NUM_TARGET);
+    if (camera != NULL) {
+        psMetadataAddS32((psMetadata *) fpa->camera, PS_LIST_HEAD, MISC_NAME_TARGET, 0, NULL, MISC_NUM_TARGET);
+    }
+    psMetadataAddS32(fpa->concepts, PS_LIST_HEAD, MISC_NAME_TARGET, 0, NULL, MISC_NUM_TARGET);
+    fpa->hdu = pmHDUAlloc(NULL);
+    psArrayRealloc(fpa->chips, NUM_CHIPS);
+    for (int i = 0 ; i < NUM_CHIPS ; i++) {
+        fpa->chips->data[i] = psMemDecrRefCounter((psPtr) generateSimpleChipTarget(fpa));
+    }
+
+    return(fpa);
+}
+
+bool testCellCopy(pmCell* cellTarget, pmCell *cellSource) {
+    bool errorFlag = false;
+    for (int readoutID = 0 ; readoutID < cellTarget->readouts->n ; readoutID++) {
+        pmReadout *readoutTarget = cellTarget->readouts->data[readoutID];
+        pmReadout *readoutSource = cellSource->readouts->data[readoutID];
+
+        psImage *imageTarget = readoutTarget->image;
+        psImage *imageSource = readoutSource->image;
+        for (int i = 0 ; i < SOURCE_NUM_ROWS ; i++) {
+            for (int j = 0 ; j < SOURCE_NUM_COLS ; j++) {
+                if (imageSource->data.F32[i][j] != imageTarget->data.F32[i][j]) {
+                    diag("ERROR: target readout[%d] image[%d][%d] is %.2f, should be %.2f",
+                          readoutID, i, j, imageTarget->data.F32[i][j], imageSource->data.F32[i][j]);
+                    errorFlag = true;
+		}
+	    }
+	}
+        if (errorFlag) {
+            diag("ERROR: pmCellCopy() did not set the data for readout %d, image correctly", readoutID);
+	}
+
+        psImage *maskTarget = readoutTarget->mask;
+        psImage *maskSource = readoutSource->mask;
+        for (int i = 0 ; i < SOURCE_NUM_ROWS ; i++) {
+            for (int j = 0 ; j < SOURCE_NUM_COLS ; j++) {
+                if (maskTarget->data.U8[i][j] != maskSource->data.U8[i][j]) {
+                    diag("ERROR: target readout[%d] mask[%d][%d] is %d, should be %d",
+                          readoutID, i, j, maskTarget->data.U8[i][j], maskSource->data.U8[i][j]);
+                    errorFlag = true;
+		}
+	    }
+	}
+        if (errorFlag) {
+            diag("ERROR: pmCellCopy() did not set the data for readout %d, mask correctly", readoutID);
+	}
+
+        psImage *weightTarget = readoutTarget->weight;
+        psImage *weightSource = readoutSource->weight;
+        for (int i = 0 ; i < SOURCE_NUM_ROWS ; i++) {
+            for (int j = 0 ; j < SOURCE_NUM_COLS ; j++) {
+                if (weightTarget->data.F32[i][j] != weightSource->data.F32[i][j]) {
+                    diag("ERROR: target readout[%d] weight[%d][%d] is %.2f, should be %.2f",
+                          readoutID, i, j, weightTarget->data.F32[i][j], weightSource->data.F32[i][j]);
+                    errorFlag = true;
+		}
+	    }
+	}
+        if (errorFlag) {
+            diag("ERROR: pmCellCopy() did not set the data for readout %d, weight correctly", readoutID);
+	}
+    }
+    return(errorFlag);
+}
+
+
+bool testChipCopy(pmChip* chipTarget, pmChip *chipSource) {
+    bool errorFlag = false;
+    for (int cellID = 0 ; cellID < chipSource->cells->n ; cellID++) {
+        pmCell *cellTarget = chipTarget->cells->data[cellID];
+        pmCell *cellSource = chipSource->cells->data[cellID];
+        errorFlag|= testCellCopy(cellTarget, cellSource);
+    }
+    return(errorFlag);
+}
+
+bool testFPACopy(pmFPA* fpaTarget, pmFPA *fpaSource) {
+    bool errorFlag = false;
+    for (int chipID = 0 ; chipID < fpaSource->chips->n ; chipID++) {
+        pmChip *chipTarget = fpaTarget->chips->data[chipID];
+        pmChip *chipSource = fpaSource->chips->data[chipID];
+        errorFlag|= testChipCopy(chipTarget, chipSource);
+    }
+    return(errorFlag);
+}
+
+
+bool testCellCopyStructure(pmCell* cellTarget, pmCell *cellSource) {
+    bool errorFlag = false;
+    for (int readoutID = 0 ; readoutID < cellTarget->readouts->n ; readoutID++) {
+        pmReadout *readoutTarget = cellTarget->readouts->data[readoutID];
+        if (readoutTarget->image->numRows != SOURCE_NUM_ROWS ||
+            readoutTarget->image->numCols != SOURCE_NUM_COLS) {
+            diag("ERROR: readoutTarget->image size is (%d by %d)\n", readoutTarget->image->numRows, 
+                  readoutTarget->image->numCols);
+            errorFlag = true;
+	}
+
+        if (readoutTarget->mask->numRows != SOURCE_NUM_ROWS ||
+            readoutTarget->mask->numCols != SOURCE_NUM_COLS) {
+            diag("ERROR: readoutTarget->mask size is (%d by %d)\n", readoutTarget->mask->numRows, 
+                  readoutTarget->mask->numCols);
+            errorFlag = true;
+	}
+        if (readoutTarget->weight->numRows != SOURCE_NUM_ROWS ||
+            readoutTarget->weight->numCols != SOURCE_NUM_COLS) {
+            diag("ERROR: readoutTarget->weight size is (%d by %d)\n", readoutTarget->weight->numRows, 
+                  readoutTarget->weight    ->numCols);
+            errorFlag = true;
+	}
+    }
+    return(errorFlag);
+}
+
+
+bool testChipCopyStructure(pmChip* chipTarget, pmChip *chipSource) {
+    bool errorFlag = false;
+    for (int cellID = 0 ; cellID < chipSource->cells->n ; cellID++) {
+        pmCell *cellTarget = chipTarget->cells->data[cellID];
+        pmCell *cellSource = chipSource->cells->data[cellID];
+        errorFlag|= testCellCopyStructure(cellTarget, cellSource);
+    }
+    return(errorFlag);
+}
+
+bool testFPACopyStructure(pmFPA* fpaTarget, pmFPA *fpaSource) {
+    bool errorFlag = false;
+    for (int chipID = 0 ; chipID < fpaSource->chips->n ; chipID++) {
+        pmChip *chipTarget = fpaTarget->chips->data[chipID];
+        pmChip *chipSource = fpaSource->chips->data[chipID];
+        errorFlag|= testChipCopyStructure(chipTarget, chipSource);
+    }
+    return(errorFlag);
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(92);
+
+
+    // ------------------------------------------------------------------------
+    // pmFPACopy() tests
+    // Call pmFPACopy() with bad input parameters.
+    if (1) {
+        psMemId id = psMemGetId();
+        pmFPA* fpaSource = generateSimpleFPASource(NULL);
+        pmFPA* fpaTarget = generateSimpleFPATarget(NULL);
+        bool rc = pmFPACopy(NULL, fpaSource);
+        ok(rc == FALSE, "pmFPACopy() returned FALSE with NULL target pmFPA input parameter");
+        rc = pmFPACopy(fpaTarget, NULL);
+        ok(rc == FALSE, "pmFPACopy() returned FALSE with NULL source pmFPA input parameter");
+        psFree(fpaSource);
+        psFree(fpaTarget);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmFPACopy() with acceptable input parameters.
+    if (1) {
+        psMemId id = psMemGetId();
+        pmFPA* fpaSource = generateSimpleFPASource(NULL);
+        pmFPA* fpaTarget = generateSimpleFPATarget(NULL);
+        bool rc = pmFPACopy(fpaTarget, fpaSource);
+        ok(rc == true, "pmFPACopy() returned TRUE with acceptable input parameters");
+        int tmpS32 = psMetadataLookupS32(&rc, fpaTarget->concepts, MISC_NAME_TARGET);
+        ok(rc, "psMetadataLookupStr(NULL, fpaTarget->concepts, MISC_NAME_TARGET) was successful");
+        ok(tmpS32 == MISC_NUM_TARGET, "pmFPACopy() copied the source FPA concepts correctly");
+
+        tmpS32 = psMetadataLookupS32(&rc, fpaTarget->concepts, MISC_NAME_SOURCE);
+        ok(rc, "psMetadataLookupStr(NULL, fpaTarget->concepts, MISC_NAME_SOURCE) was successful");
+        ok(tmpS32 == MISC_NUM_SOURCE, "pmFPACopy() copied the source FPA concepts correctly");
+        ok(!testFPACopy(fpaTarget, fpaSource), "pmFPACopy() set the pmReadout data correctly");
+
+        psFree(fpaSource);
+        psFree(fpaTarget);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // pmChipCopy() tests
+    // Call pmChipCopy() with bad input parameters.
+    if (1) {
+        psMemId id = psMemGetId();
+        pmChip* chipSource = generateSimpleChipSource(NULL);
+        pmChip* chipTarget = generateSimpleChipTarget(NULL);
+        bool rc = pmChipCopy(NULL, chipSource);
+        ok(rc == FALSE, "pmChipCopy() returned FALSE with NULL target pmChip input parameter");
+        rc = pmChipCopy(chipTarget, NULL);
+        ok(rc == FALSE, "pmChipCopy() returned FALSE with NULL source pmChip input parameter");
+        psFree(chipSource);
+        psFree(chipTarget);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmChipCopy() with acceptable input parameters.
+    if (1) {
+        psMemId id = psMemGetId();
+        pmFPA *fpaSource = generateSimpleFPASource(NULL);
+        pmFPA *fpaTarget = generateSimpleFPATarget(NULL);
+        pmChip* chipSource = generateSimpleChipSource(fpaSource);
+        pmChip* chipTarget = generateSimpleChipTarget(fpaTarget);
+        bool rc = pmChipCopy(chipTarget, chipSource);
+        ok(rc == true, "pmChipCopy() returned TRUE with acceptable input parameters");
+        ok(!testChipCopy(chipTarget, chipSource), "pmChipCopy() set the pmReadout data correctly");
+        psFree(chipSource);
+        psFree(chipTarget);
+        psFree(fpaSource);
+        psFree(fpaTarget);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // pmCellCopy() tests
+    // Call pmCellCopy() with bad input parameters.
+    if (1) {
+        psMemId id = psMemGetId();
+        pmCell* cellSource = generateSimpleCellSource(NULL);
+        pmCell* cellTarget = generateSimpleCellTarget(NULL);
+        bool rc = pmCellCopy(NULL, cellSource);
+        ok(rc == FALSE, "pmCellCopy() returned FALSE with NULL target pmCell input parameter");
+        rc = pmCellCopy(cellTarget, NULL);
+        ok(rc == FALSE, "pmCellCopy() returned FALSE with NULL source pmCell input parameter");
+        psFree(cellSource);
+        psFree(cellTarget);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // Call pmCellCopy() with acceptable input parameters.
+    if (1) {
+        psMemId id = psMemGetId();
+        pmChip *parentSource = generateSimpleChipSource(NULL);
+        pmChip *parentTarget = generateSimpleChipSource(NULL);
+        pmCell* cellSource = generateSimpleCellSource(parentSource);
+        pmCell* cellTarget = generateSimpleCellTarget(parentTarget);
+        bool rc = pmCellCopy(cellTarget, cellSource);
+        ok(rc == true, "pmCellCopy() returned TRUE with NULL target pmCell input parameter");
+        ok(!testCellCopy(cellTarget, cellSource), "pmChipCopy() set the pmReadout data correctly");
+        psFree(cellSource);
+        psFree(cellTarget);
+        psFree(parentSource);
+        psFree(parentTarget);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // pmFPACopyStructure() tests
+    // bool pmFPACopyStructure(pmFPA *target, const pmFPA *source, int xBin, int yBin)
+    // Call pmFPACopyStructure() with bad input parameters.
+    if (1) {
+        psMemId id = psMemGetId();
+        pmFPA* fpaSource = generateSimpleFPASource(NULL);
+        pmFPA* fpaTarget = generateSimpleFPATarget(NULL);
+        bool rc = pmFPACopyStructure(NULL, fpaSource, 1.0, 1.0);
+        ok(rc == FALSE, "pmFPACopyStructure() returned FALSE with NULL target pmFPA input parameter");
+        rc = pmFPACopyStructure(fpaTarget, NULL, 1.0, 1.0);
+        ok(rc == FALSE, "pmFPACopyStructure() returned FALSE with NULL source pmFPA input parameter");
+        rc = pmFPACopyStructure(fpaTarget, fpaSource, 0.0, 1.0);
+        ok(rc == FALSE, "pmFPACopyStructure() returned FALSE with non-positive xBin input parameter");
+        rc = pmFPACopyStructure(fpaTarget, fpaSource, 1.0, 0.0);
+        ok(rc == FALSE, "pmFPACopyStructure() returned FALSE with non-positive yBin input parameter");
+        psFree(fpaSource);
+        psFree(fpaTarget);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmFPACopyStructure() with acceptable input parameters.
+    if (1) {
+        psMemId id = psMemGetId();
+        pmFPA* fpaSource = generateSimpleFPASource(NULL);
+        pmFPA* fpaTarget = generateSimpleFPATarget(NULL);
+        bool rc = pmFPACopyStructure(fpaTarget, fpaSource, 1.0, 1.0);
+        ok(rc == true, "pmFPACopyStructure() returned TRUE with acceptable input parameters");
+        ok(!testFPACopyStructure(fpaTarget, fpaSource), "pmFPACopyStructure() set the pmReadout data correctly");
+        int tmpS32 = psMetadataLookupS32(&rc, fpaTarget->concepts, MISC_NAME_TARGET);
+        ok(tmpS32 == MISC_NUM_TARGET, "pmFPACopy() copied the source FPA concepts correctly");
+        psFree(fpaSource);
+        psFree(fpaTarget);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // pmChipCopyStructure() tests
+    // bool pmChipCopyStructure(pmChip *target, const pmChip *source, int xBin, int yBin)
+    // Call pmChipCopyStructure() with bad input parameters.
+    if (1) {
+        psMemId id = psMemGetId();
+        pmChip* chipSource = generateSimpleChipSource(NULL);
+        pmChip* chipTarget = generateSimpleChipTarget(NULL);
+        bool rc = pmChipCopyStructure(NULL, chipSource, 1.0, 1.0);
+        ok(rc == FALSE, "pmChipCopyStructure() returned FALSE with NULL target pmChip input parameter");
+        rc = pmChipCopyStructure(chipTarget, NULL, 1.0, 1.0);
+        ok(rc == FALSE, "pmChipCopyStructure() returned FALSE with NULL source pmChip input parameter");
+        rc = pmChipCopyStructure(chipTarget, chipSource, 0.0, 1.0);
+        ok(rc == FALSE, "pmChipCopyStructure() returned FALSE with non-positive xBin input parameter");
+        rc = pmChipCopyStructure(chipTarget, chipSource, 1.0, 0.0);
+        ok(rc == FALSE, "pmChipCopyStructure() returned FALSE with non-positive yBin input parameter");
+        psFree(chipSource);
+        psFree(chipTarget);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmChipCopyStructure() with acceptable parameters.
+    if (1) {
+        psMemId id = psMemGetId();
+        pmFPA *fpaSource = generateSimpleFPASource(NULL);
+        pmFPA *fpaTarget = generateSimpleFPATarget(NULL);
+        pmChip* chipSource = generateSimpleChipSource(fpaSource);
+        pmChip* chipTarget = generateSimpleChipTarget(fpaTarget);
+        bool rc = pmChipCopyStructure(chipTarget, chipSource, 1.0, 1.0);
+        ok(rc == true, "pmChipCopyStructure() returned TRUE with acceptable input parameters");
+        ok(!testChipCopyStructure(chipTarget, chipSource), "pmChipCopyStructure() set the pmReadout data correctly");
+        psFree(chipSource);
+        psFree(chipTarget);
+        psFree(fpaSource);
+        psFree(fpaTarget);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // pmCellCopyStructure() tests
+    // bool pmCellCopyStructure(pmCell *target, const pmCell *source, int xBin, int yBin)
+    // Call pmCellCopyStructure() with bad input parameters.
+    if (1) {
+        psMemId id = psMemGetId();
+        pmCell* cellSource = generateSimpleCellSource(NULL);
+        pmCell* cellTarget = generateSimpleCellTarget(NULL);
+        bool rc = pmCellCopyStructure(NULL, cellSource, 1.0, 1.0);
+        ok(rc == FALSE, "pmCellCopyStructure() returned FALSE with NULL target pmCell input parameter");
+        rc = pmCellCopyStructure(cellTarget, NULL, 1.0, 1.0);
+        ok(rc == FALSE, "pmCellCopyStructure() returned FALSE with NULL source pmCell input parameter");
+        rc = pmCellCopyStructure(cellTarget, cellSource, 0.0, 1.0);
+        ok(rc == FALSE, "pmCellCopyStructure() returned FALSE with non-positive xBin input parameter");
+        rc = pmCellCopyStructure(cellTarget, cellSource, 1.0, 0.0);
+        ok(rc == FALSE, "pmCellCopyStructure() returned FALSE with non-positive yBin input parameter");
+        psFree(cellSource);
+        psFree(cellTarget);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmCellCopyStructure() with acceptable input parameters.
+    if (1) {
+        psMemId id = psMemGetId();
+        pmChip *parentSource = generateSimpleChipSource(NULL);
+        pmChip *parentTarget = generateSimpleChipSource(NULL);
+        pmCell* cellSource = generateSimpleCellSource(parentSource);
+        pmCell* cellTarget = generateSimpleCellTarget(parentTarget);
+        bool rc = pmCellCopyStructure(cellTarget, cellSource, 1.0, 1.0);
+        ok(rc == true, "pmCellCopyStructure() returned TRUE with NULL target pmCell input parameter");
+        ok(!testCellCopyStructure(cellTarget, cellSource), "pmCellCopyStructure() set the pmReadout data correctly");
+        psFree(cellSource);
+        psFree(cellTarget);
+        psFree(parentSource);
+        psFree(parentTarget);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // pmChipDuplicate() tests
+    // pmChip *pmChipDuplicate(pmFPA *fpa, const pmChip *source);
+    // Call pmChipDuplicate() with bad input parameters.
+    if (0) {
+        psMemId id = psMemGetId();
+        pmChip *chipSource = generateSimpleChipSource(NULL);
+        pmChip *chipTarget = pmChipDuplicate(NULL, NULL);
+        ok(chipTarget == NULL, "pmChipDuplicate() returned NULL with NULL pmChip input parameter");
+        psFree(chipSource);
+        psFree(chipTarget);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAExtent.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAExtent.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAExtent.c	(revision 22158)
@@ -0,0 +1,425 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    All functions are tested.
+*/
+
+// XXX: For the genSimpleFPA() code, add IDs to each function so that
+// the values set in each chip-?cell-?hdu-?image are unique
+// XXX: For the genSimpleFPA() code, write masks and weights as well
+
+#define CHIP_ALLOC_NAME        "ChipName"
+#define CELL_ALLOC_NAME        "CellName"
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define MISC_NAME2             "META01"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           4
+#define TEST_NUM_COLS           4
+#define NUM_READOUTS            3
+#define NUM_CELLS               10
+#define NUM_CHIPS               8
+#define NUM_HDUS                5
+#define BASE_IMAGE              10
+#define BASE_MASK               40
+#define BASE_WEIGHT             70
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+psPlaneTransform *PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM()
+{
+    psPlaneTransform *pt = psPlaneTransformAlloc(1, 1);
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+    return(pt);
+}
+
+psPlaneDistort *PS_CREATE_4D_IDENTITY_PLANE_DISTORT()
+{
+    psPlaneDistort *pd = psPlaneDistortAlloc(1, 1, 1, 1);
+    pd->x->coeff[1][0][0][0] = 1.0;
+    pd->y->coeff[0][1][0][0] = 1.0;
+    return(pd);
+}
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    cell->hdu = pmHDUAlloc("cellExtName");
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = psMemDecrRefCounter((psPtr) generateSimpleReadout(cell));
+    }
+
+    bool rc = pmConfigFileRead(&cell->hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        rc = pmConfigFileRead(&cell->hdu->format, "../camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            diag("pmConfigFileRead() was unsuccessful (from generateSimpleCell())");
+        }
+    }
+
+    cell->hdu->images = psArrayAlloc(NUM_HDUS);
+    cell->hdu->masks = psArrayAlloc(NUM_HDUS);
+    cell->hdu->weights = psArrayAlloc(NUM_HDUS);
+    for (int k = 0 ; k < NUM_HDUS ; k++) {
+        cell->hdu->images->data[k]  = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        cell->hdu->masks->data[k]   = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        cell->hdu->weights->data[k] = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(cell->hdu->images->data[k], (float) (BASE_IMAGE+k));
+        psImageInit(cell->hdu->masks->data[k], (psU8) (BASE_MASK+k));
+        psImageInit(cell->hdu->weights->data[k], (float) (BASE_WEIGHT+k));
+    }
+
+    //XXX: Should the region be set some other way?  Like through the various config files?
+    psRegion *region = psRegionAlloc(0.0, 0.0, 0.0, 0.0);
+    // You shouldn't have to remove the key from the metadata.  Find out how to simply change the key value.
+    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC");
+    psMetadataAddPtr(cell->concepts, PS_LIST_TAIL|PS_META_REPLACE, "CELL.TRIMSEC", PS_DATA_REGION, "I am a region", region);
+    psFree(region);
+    return(cell);
+}
+
+/******************************************************************************
+generateSimpleChip(): This function generates a pmChip data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmChip *generateSimpleChip(pmFPA *fpa)
+{
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    chip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    chip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    psMetadataAddS32(chip->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(chip->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(chip->cells, NUM_CELLS);
+    for (int i = 0 ; i < NUM_CELLS ; i++) {
+        chip->cells->data[i] = psMemDecrRefCounter((psPtr) generateSimpleCell(chip));
+    }
+
+    // XXX: Add code to initialize chip pmConcepts
+
+
+    return(chip);
+}
+
+/******************************************************************************
+generateSimpleFPA(): This function generates a pmFPA data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmFPA* generateSimpleFPA(psMetadata *camera)
+{
+    pmFPA* fpa = pmFPAAlloc(camera);
+    fpa->fromTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toSky = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+    psMetadataAddS32(fpa->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    if (camera != NULL) {
+        psMetadataAddS32((psMetadata *) fpa->camera, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    }
+    psMetadataAddS32(fpa->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    psArrayRealloc(fpa->chips, NUM_CHIPS);
+    for (int i = 0 ; i < NUM_CHIPS ; i++) {
+        fpa->chips->data[i] = psMemDecrRefCounter((psPtr) generateSimpleChip(fpa));
+    }
+
+    pmConceptsBlankFPA(fpa);
+    return(fpa);
+}
+
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(25);
+
+
+    // ----------------------------------------------------------------------
+    // pmReadoutExtent() tests: NULL input
+    {
+        psMemId id = psMemGetId();
+        ok(NULL == pmReadoutExtent(NULL), "pmReadoutExtent(NULL) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // pmReadoutExtent() tests: acceptable inputs
+    // XXX: We should probably test when the images are NULL, and use different size
+    // images in each readout.
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        bool errorFlag = false;
+        for (int chipID = 0 ; chipID < fpa->chips->n ; chipID++) {
+            pmChip *chip = fpa->chips->data[chipID];
+            for (int cellID = 0 ; cellID < chip->cells->n ; cellID++) {
+                pmCell *cell = chip->cells->data[cellID];
+                for (int readoutID = 0 ; readoutID < cell->readouts->n ; readoutID++) {
+                    pmReadout *readout = cell->readouts->data[readoutID];
+                    psRegion *region = pmReadoutExtent(readout);
+                    int xWindow = psMetadataLookupS32(NULL, readout->parent->concepts, "CELL.XWINDOW");
+                    int yWindow = psMetadataLookupS32(NULL, readout->parent->concepts, "CELL.YWINDOW");
+                    if (!region || 
+                         region->x0 != xWindow ||
+                         region->x1 != xWindow + readout->image->numCols ||
+                         region->y0 != yWindow ||
+                         region->y1 != yWindow + readout->image->numRows) {
+                        diag("ERROR: pmReadoutExtent() did not set the psRegion correctly for chip/cell/readout (%d/%d/%d)\n", chipID, cellID, readoutID);
+                        errorFlag = true;
+		    }
+                    psFree(region);
+		}
+	    }
+	}
+        ok(!errorFlag, "pmReadoutExtent() passed all tests");
+
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmCellExtent() tests: NULL input
+    {
+        psMemId id = psMemGetId();
+        ok(NULL == pmCellExtent(NULL), "pmCellExtent(NULL) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmCellExtent() tests: acceptable inputs
+    // XX: We should probably set different region sizes to better test the min/max code
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        bool errorFlag = false;
+        for (int chipID = 0 ; chipID < fpa->chips->n ; chipID++) {
+            pmChip *chip = fpa->chips->data[chipID];
+            for (int cellID = 0 ; cellID < chip->cells->n ; cellID++) {
+                pmCell *cell = chip->cells->data[cellID];
+                // Determine the actual extent
+                psRegion *cellExtent = psRegionAlloc(INFINITY, 0, INFINITY, 0); // Extent of cell
+                for (int readoutID = 0 ; readoutID < cell->readouts->n ; readoutID++) {
+                    pmReadout *readout = cell->readouts->data[readoutID];
+                    psRegion *roExtent = pmReadoutExtent(readout); // Extent of readout
+                    cellExtent->x0 = PS_MIN(cellExtent->x0, roExtent->x0);
+                    cellExtent->x1 = PS_MAX(cellExtent->x1, roExtent->x1);
+                    cellExtent->y0 = PS_MIN(cellExtent->y0, roExtent->y0);
+                    cellExtent->y1 = PS_MAX(cellExtent->y1, roExtent->y1);
+                    psFree(roExtent);
+		}
+                bool mdok;
+                int x0 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.X0"); // Cell x offset
+                int y0 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.Y0"); // Cell y offset
+                cellExtent->x0 += x0;
+                cellExtent->x1 += x0;
+                cellExtent->y0 += y0;
+                cellExtent->y1 += y0;
+    
+                psRegion *tstExtent = pmCellExtent(cell);
+                if (!cell ||
+                     tstExtent->x0 != cellExtent->x0 ||
+                     tstExtent->x1 != cellExtent->x1 ||
+                     tstExtent->y0 != cellExtent->y0 ||
+                     tstExtent->y1 != cellExtent->y1) {
+                     diag("ERROR: psRegion set incorrectly for chip/cell (%d/%d)", chipID, cellID);
+                     errorFlag = true;
+		}
+                psFree(tstExtent);
+                psFree(cellExtent);
+	    }
+	}
+        ok(!errorFlag, "pmCellExtent() passed all tests");
+
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // ----------------------------------------------------------------------
+    // pmChipExtent() tests: NULL input
+    {
+        psMemId id = psMemGetId();
+        ok(NULL == pmChipExtent(NULL), "pmChipExtent(NULL) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmChipExtent() tests: acceptable inputs
+    // XX: We should probably set different region sizes to better test the min/max code
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        bool errorFlag = false;
+        for (int chipID = 0 ; chipID < fpa->chips->n ; chipID++) {
+            pmChip *chip = fpa->chips->data[chipID];
+            psRegion *chipExtent = pmChipPixels(chip);
+            bool rc;
+            int x0 = psMetadataLookupS32(&rc, chip->concepts, "CHIP.X0"); // Chip x offset
+            int y0 = psMetadataLookupS32(&rc, chip->concepts, "CHIP.Y0"); // Chip y offset
+            chipExtent->x0 += x0;
+            chipExtent->x1 += x0;
+            chipExtent->y0 += y0;
+            chipExtent->y1 += y0;
+            psRegion *tstExtent = pmChipExtent(chip);
+            if (!chip ||
+                tstExtent->x0 != chipExtent->x0 ||
+                tstExtent->x1 != chipExtent->x1 ||
+                tstExtent->y0 != chipExtent->y0 ||
+                tstExtent->y1 != chipExtent->y1) {
+                diag("ERROR: psRegion set incorrectly for chip (%d)", chipID);
+                errorFlag = true;
+	    }
+            psFree(tstExtent);
+            psFree(chipExtent);
+	}
+        ok(!errorFlag, "pmChipExtent() passed all tests");
+
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmChipPixels() tests: NULL input
+    {
+        psMemId id = psMemGetId();
+        ok(NULL == pmChipPixels(NULL), "pmChipPixels(NULL) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmChipPixels() tests: acceptable inputs
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+
+        bool errorFlag = false;
+        for (int chipID = 0 ; chipID < fpa->chips->n ; chipID++) {
+            pmChip *chip = fpa->chips->data[chipID];
+            // Determine the actual pixels
+            psRegion *actualExtent = psRegionAlloc(INFINITY, 0, INFINITY, 0);
+            for (int cellID = 0 ; cellID < chip->cells->n ; cellID++) {
+                pmCell *cell = chip->cells->data[cellID];
+                psRegion *cellExtent = pmCellExtent(cell);
+                actualExtent->x0 = PS_MIN(actualExtent->x0, cellExtent->x0);
+                actualExtent->x1 = PS_MAX(actualExtent->x1, cellExtent->x1);
+                actualExtent->y0 = PS_MIN(actualExtent->y0, cellExtent->y0);
+                actualExtent->y1 = PS_MAX(actualExtent->y1, cellExtent->y1);
+                psFree(cellExtent);
+	    }
+
+            // Now test if pmChipPixels() determines the same pixels
+            psRegion *tstExtent = pmChipPixels(chip);
+            if (!tstExtent ||
+                 tstExtent->x0 != actualExtent->x0 ||
+                 tstExtent->x1 != actualExtent->x1 ||
+                 tstExtent->y0 != actualExtent->y0 ||
+                 tstExtent->y1 != actualExtent->y1) {
+                diag("ERROR: pixels set incorrectly for chip %d", chipID);
+                errorFlag = true;
+	    }
+
+            // Free temp memory
+            psFree(tstExtent);
+            psFree(actualExtent);
+	}
+        ok(!errorFlag, "pmChipPixels() passed all tests");
+
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmFPAPixels() tests: NULL input
+    {
+        psMemId id = psMemGetId();
+        ok(NULL == pmFPAPixels(NULL), "pmFPAPixels(NULL) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAPixels() tests: acceptable inputs
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+
+        psRegion *actualExtent = psRegionAlloc(INFINITY, 0, INFINITY, 0); // Extent of fpa
+        for (int chipID = 0 ; chipID < fpa->chips->n ; chipID++) {
+            pmChip *chip = fpa->chips->data[chipID];
+            psRegion *chipExtent = pmChipExtent(chip); // Extent of chip
+            actualExtent->x0 = PS_MIN(actualExtent->x0, chipExtent->x0);
+            actualExtent->x1 = PS_MAX(actualExtent->x1, chipExtent->x1);
+            actualExtent->y0 = PS_MIN(actualExtent->y0, chipExtent->y0);
+            actualExtent->y1 = PS_MAX(actualExtent->y1, chipExtent->y1);
+            psFree(chipExtent);
+        }
+
+        bool errorFlag = false;
+        psRegion *tstExtent = pmFPAPixels(fpa);
+        if (!tstExtent ||
+             tstExtent->x0 != actualExtent->x0 ||
+             tstExtent->x1 != actualExtent->x1 ||
+             tstExtent->y0 != actualExtent->y0 ||
+             tstExtent->y1 != actualExtent->y1) {
+            diag("ERROR: pmFPAPixels() set the pixels incorrectly");
+            errorFlag = true;
+	}
+        ok(!errorFlag, "pmFPAPixels() set the pixels psRegion correctly");
+
+        psFree(tstExtent);
+        psFree(actualExtent);
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAFlags.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAFlags.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAFlags.c	(revision 22158)
@@ -0,0 +1,1021 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS
+    TESTED:
+        pmFPASetFileStatus()
+        pmChipSetFileStatus()
+        pmCellSetFileStatus()
+
+        pmFPACheckFileStatus()
+        pmChipCheckFileStatus()
+        pmCellCheckFileStatus()
+
+        pmFPASetDataStatus()
+        pmChipSetDataStatus()
+        pmCellSetDataStatus()
+
+        pmFPACheckDataStatus()
+        pmChipCheckDataStatus()
+        pmCellCheckDataStatus()
+        pmReadoutCheckDataStatus()
+    MUST TEST:
+        pmFPAviewCheckDataStatus()
+        pmFPASelectChip()
+        pmChipSelectCell()
+        pmFPAExcludeChip()
+        pmChipExcludeCell()
+*/
+
+// XXX: For the genSimpleFPA() code, add IDs to each function so that
+// the values set in each chip-?cell-?hdu-?image are unique
+// XXX: For the genSimpleFPA() code, write masks and weights as well
+// XXX: Add in the associated CheckStatus tests
+
+#define CHIP_ALLOC_NAME        "ChipName"
+#define CELL_ALLOC_NAME        "CellName"
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define MISC_NAME2             "META01"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           4
+#define TEST_NUM_COLS           4
+#define NUM_READOUTS            3
+#define NUM_CELLS               10
+#define NUM_CHIPS               8
+#define NUM_HDUS                5
+#define BASE_IMAGE              10
+#define BASE_MASK               40
+#define BASE_WEIGHT             70
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+psPlaneTransform *PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM()
+{
+    psPlaneTransform *pt = psPlaneTransformAlloc(1, 1);
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+    return(pt);
+}
+
+psPlaneDistort *PS_CREATE_4D_IDENTITY_PLANE_DISTORT()
+{
+    psPlaneDistort *pd = psPlaneDistortAlloc(1, 1, 1, 1);
+    pd->x->coeff[1][0][0][0] = 1.0;
+    pd->y->coeff[0][1][0][0] = 1.0;
+    return(pd);
+}
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    cell->hdu = pmHDUAlloc("cellExtName");
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = psMemDecrRefCounter((psPtr) generateSimpleReadout(cell));
+    }
+
+    bool rc = pmConfigFileRead(&cell->hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        rc = pmConfigFileRead(&cell->hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            diag("pmConfigFileRead() was unsuccessful (from generateSimpleCell())");
+        }
+    }
+
+    cell->hdu->images = psArrayAlloc(NUM_HDUS);
+    cell->hdu->masks = psArrayAlloc(NUM_HDUS);
+    cell->hdu->weights = psArrayAlloc(NUM_HDUS);
+    for (int k = 0 ; k < NUM_HDUS ; k++) {
+        cell->hdu->images->data[k]  = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        cell->hdu->masks->data[k]   = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        cell->hdu->weights->data[k] = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(cell->hdu->images->data[k], (float) (BASE_IMAGE+k));
+        psImageInit(cell->hdu->masks->data[k], (psU8) (BASE_MASK+k));
+        psImageInit(cell->hdu->weights->data[k], (float) (BASE_WEIGHT+k));
+    }
+
+    //XXX: Should the region be set some other way?  Like through the various config files?
+    psRegion *region = psRegionAlloc(0.0, 0.0, 0.0, 0.0);
+    // You shouldn't have to remove the key from the metadata.  Find out how to simply change the key value.
+    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC");
+    psMetadataAddPtr(cell->concepts, PS_LIST_TAIL|PS_META_REPLACE, "CELL.TRIMSEC", PS_DATA_REGION, "I am a region", region);
+    psFree(region);
+    return(cell);
+}
+
+/******************************************************************************
+generateSimpleChip(): This function generates a pmChip data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmChip *generateSimpleChip(pmFPA *fpa)
+{
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    chip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    chip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    psMetadataAddS32(chip->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(chip->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(chip->cells, NUM_CELLS);
+    for (int i = 0 ; i < NUM_CELLS ; i++) {
+        chip->cells->data[i] = psMemDecrRefCounter((psPtr) generateSimpleCell(chip));
+    }
+
+    // XXX: Add code to initialize chip pmConcepts
+
+
+    return(chip);
+}
+
+/******************************************************************************
+generateSimpleFPA(): This function generates a pmFPA data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmFPA* generateSimpleFPA(psMetadata *camera)
+{
+    pmFPA* fpa = pmFPAAlloc(camera);
+    fpa->fromTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toSky = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+    psMetadataAddS32(fpa->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    if (camera != NULL) {
+        psMetadataAddS32((psMetadata *) fpa->camera, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    }
+    psMetadataAddS32(fpa->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(fpa->chips, NUM_CHIPS);
+    for (int i = 0 ; i < NUM_CHIPS ; i++) {
+        fpa->chips->data[i] = psMemDecrRefCounter((psPtr) generateSimpleChip(fpa));
+    }
+
+    // XXX: Eventually, when you finish the pmConcepts tests, add full concept
+    // reading code from wherever.
+    pmConceptsBlankFPA(fpa);
+    return(fpa);
+}
+
+void SetCellFileExists(pmCell *cell) {
+    cell->file_exists = true;
+    for (int i = 0 ; i < cell->readouts->n ; i++) {
+        pmReadout *readout = cell->readouts->data[i];
+        readout->file_exists = true;
+    }
+}
+
+void SetChipFileExists(pmChip *chip) {
+    chip->file_exists = true;
+    for (int i = 0 ; i < chip->cells->n ; i++) {
+        pmCell *cell = chip->cells->data[i];
+        cell->file_exists = true;
+        SetCellFileExists(cell);
+    }
+}
+
+void SetFPAFileExists(pmFPA *fpa) {
+    for (int i = 0 ; i < fpa->chips->n ; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        chip->file_exists = true;
+        SetChipFileExists(chip);
+    }
+}
+
+void SetReadoutDataExists(pmReadout *readout) {
+    readout->data_exists = true;
+}
+
+void SetCellDataExists(pmCell *cell) {
+    cell->data_exists = true;
+    for (int i = 0 ; i < cell->readouts->n ; i++) {
+        pmReadout *readout = cell->readouts->data[i];
+        readout->data_exists = true;
+    }
+}
+
+void SetChipDataExists(pmChip *chip) {
+    chip->data_exists = true;
+    for (int i = 0 ; i < chip->cells->n ; i++) {
+        pmCell *cell = chip->cells->data[i];
+        cell->data_exists = true;
+        SetCellDataExists(cell);
+    }
+}
+
+void SetFPADataExists(pmFPA *fpa) {
+    for (int i = 0 ; i < fpa->chips->n ; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        chip->data_exists = true;
+        SetChipDataExists(chip);
+    }
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(107);
+
+
+    // ----------------------------------------------------------------------
+    // pmFPASetFileStatus() tests: verify with NULL pmFPA param
+    // bool pmFPASetFileStatus(pmFPA *fpa, bool status)
+    {
+        psMemId id = psMemGetId();
+        bool rc = pmFPASetFileStatus(NULL, false);
+        ok(!rc, "pmFPASetFileStatus() returned FALSE with NULL pmFPA param");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPASetFileStatus() tests: verify with acceptable data
+    // bool pmFPASetFileStatus(pmFPA *fpa, bool status)
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+
+        // First, set all flags to FALSE
+        bool correctStatus = false;
+        bool rc = pmFPASetFileStatus(fpa, correctStatus);
+        ok(rc, "pmFPASetFileStatus() returned successfully with acceptable input params");
+        bool errorFlag = false;
+        for (int k = 0 ; k < fpa->chips->n ; k++) {
+            pmChip *chip = fpa->chips->data[k];
+            for (int j = 0 ; j < chip->cells->n ; j++) {
+                pmCell *cell = chip->cells->data[j];
+                if (cell->file_exists != correctStatus) {
+                    diag("TEST ERROR: pmFPASetFileStatus() failed to set file status for chip %d cell %d\n", k, j);
+                    errorFlag = true;
+                }
+    
+                for (int i = 0; i < cell->readouts->n; i++) {
+                    pmReadout *readout = cell->readouts->data[i];
+                    if (readout->file_exists != correctStatus) {
+                        diag("TEST ERROR: pmFPASetFileStatus() failed to set file status for chip %d cell %d readout %d\n", k, j, i);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+        ok(!errorFlag, "pmFPASetFileStatus() set file status in all cells to FALSE");
+
+        // Second, set all flags to TRUE
+        correctStatus = true;
+        rc = pmFPASetFileStatus(fpa, correctStatus);
+        ok(rc, "pmFPASetFileStatus() returned successfully with acceptable input params");
+        errorFlag = false;
+        for (int k = 0 ; k < fpa->chips->n ; k++) {
+            pmChip *chip = fpa->chips->data[k];
+            for (int j = 0 ; j < chip->cells->n ; j++) {
+                pmCell *cell = chip->cells->data[j];
+                if (cell->file_exists != correctStatus) {
+                    diag("TEST ERROR: pmFPASetFileStatus() failed to set file status for chip %d cell %d\n", k, j);
+                    errorFlag = true;
+                }
+    
+                for (int i = 0; i < cell->readouts->n; i++) {
+                    pmReadout *readout = cell->readouts->data[i];
+                    if (readout->file_exists != correctStatus) {
+                        diag("TEST ERROR: pmFPASetFileStatus() failed to set file status for chip %d cell %d readout %d\n", k, j, i);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+        ok(!errorFlag, "pmFPASetFileStatus() set file status in all cells to TRUE");
+
+        // Third, set all flags to FALSE
+        correctStatus = false;
+        rc = pmFPASetFileStatus(fpa, correctStatus);
+        ok(rc, "pmFPASetFileStatus() returned successfully with acceptable input params");
+        errorFlag = false;
+        for (int k = 0 ; k < fpa->chips->n ; k++) {
+            pmChip *chip = fpa->chips->data[k];
+            for (int j = 0 ; j < chip->cells->n ; j++) {
+                pmCell *cell = chip->cells->data[j];
+                if (cell->file_exists != correctStatus) {
+                    diag("TEST ERROR: pmFPASetFileStatus() failed to set file status for chip %d cell %d\n", k, j);
+                    errorFlag = true;
+                }
+    
+                for (int i = 0; i < cell->readouts->n; i++) {
+                    pmReadout *readout = cell->readouts->data[i];
+                    if (readout->file_exists != correctStatus) {
+                        diag("TEST ERROR: pmFPASetFileStatus() failed to set file status for chip %d cell %d readout %d\n", k, j, i);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+        ok(!errorFlag, "pmFPASetFileStatus() set file status in all cells to FALSE");
+
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmChipSetFileStatus() tests: verify with NULL pmChip param
+    // bool pmChipSetFileStatus(pmChip *chip, bool status)
+    {
+        psMemId id = psMemGetId();
+        bool rc = pmChipSetFileStatus(NULL, false);
+        ok(!rc, "pmChipSetFileStatus() returned FALSE with NULL pmChip param");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmChipSetFileStatus() tests: verify with acceptable data
+    // bool pmChipSetFileStatus(pmChip *chip, bool status)
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+
+        // First, set all flags to FALSE
+        bool correctStatus = false;
+        bool rc = pmChipSetFileStatus(chip, correctStatus);
+        ok(rc, "pmChipSetFileStatus() returned successfully with acceptable input params");
+        bool errorFlag = false;
+        if (chip->file_exists != correctStatus) {
+            diag("TEST ERROR: pmChipSetFileStatus() failed to set file status for chip param");
+            errorFlag = true;
+        }
+        for (int j = 0 ; j < chip->cells->n ; j++) {
+            pmCell *cell = chip->cells->data[j];
+            if (cell->file_exists != correctStatus) {
+                diag("TEST ERROR: pmChipSetFileStatus() failed to set file status for cell %d\n", j);
+                errorFlag = true;
+            }
+
+            for (int i = 0; i < cell->readouts->n; i++) {
+                pmReadout *readout = cell->readouts->data[i];
+                if (readout->file_exists != correctStatus) {
+                    diag("TEST ERROR: pmChipSetFileStatus() failed to set file status for cell %d readout %d\n", j, i);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "pmChipSetFileStatus() set file status in all cells to FALSE");
+
+        // Second, set all flags to TRUE
+        correctStatus = true;
+        rc = pmChipSetFileStatus(chip, correctStatus);
+        ok(rc, "pmChipSetFileStatus() returned successfully with acceptable input params");
+        errorFlag = false;
+        if (chip->file_exists != correctStatus) {
+            diag("TEST ERROR: pmChipSetFileStatus() failed to set file status for chip param");
+            errorFlag = true;
+        }
+        for (int j = 0 ; j < chip->cells->n ; j++) {
+            pmCell *cell = chip->cells->data[j];
+            if (cell->file_exists != correctStatus) {
+                diag("TEST ERROR: pmChipSetFileStatus() failed to set file status for cell %d\n", j);
+                errorFlag = true;
+            }
+
+            for (int i = 0; i < cell->readouts->n; i++) {
+                pmReadout *readout = cell->readouts->data[i];
+                if (readout->file_exists != correctStatus) {
+                    diag("TEST ERROR: pmChipSetFileStatus() failed to set file status for cell %d readout %d\n", j, i);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "pmChipSetFileStatus() set file status in all cells to TRUE");
+
+        // Third, set all flags to FALSE
+        correctStatus = false;
+        rc = pmChipSetFileStatus(chip, correctStatus);
+        ok(rc, "pmChipSetFileStatus() returned successfully with acceptable input params");
+        errorFlag = false;
+        if (chip->file_exists != correctStatus) {
+            diag("TEST ERROR: pmChipSetFileStatus() failed to set file status for chip param");
+            errorFlag = true;
+        }
+        for (int j = 0 ; j < chip->cells->n ; j++) {
+            pmCell *cell = chip->cells->data[j];
+            if (cell->file_exists != correctStatus) {
+                diag("TEST ERROR: pmChipSetFileStatus() failed to set file status for cell %d\n", j);
+                errorFlag = true;
+            }
+
+            for (int i = 0; i < cell->readouts->n; i++) {
+                pmReadout *readout = cell->readouts->data[i];
+                if (readout->file_exists != correctStatus) {
+                    diag("TEST ERROR: pmChipSetFileStatus() failed to set file status for cell %d readout %d\n", j, i);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "pmChipSetFileStatus() set file status in all cells to FALSE");
+
+
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmCellSetFileStatus() tests: verify with NULL pmCell param
+    {
+        psMemId id = psMemGetId();
+        bool rc = pmCellSetFileStatus(NULL, false);
+        ok(!rc, "pmCellSetFileStatus() returned FALSE with NULL pmCell param");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmCellSetFileStatus() tests: verify with acceptable data
+    // bool pmCellSetFileStatus(pmCell *cell, bool status)
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+
+        // First, set all flags to FALSE
+        bool correctStatus = false;
+        bool rc = pmCellSetFileStatus(cell, correctStatus);
+        ok(rc, "pmCellSetFileStatus() returned successfully with acceptable input params");
+        bool errorFlag = false;
+        if (cell->file_exists != correctStatus) {
+            diag("TEST ERROR: pmCellSetFileStatus() failed to set file status for cell param\n");
+            errorFlag = true;
+        }
+        for (int i = 0; i < cell->readouts->n; i++) {
+
+            pmReadout *readout = cell->readouts->data[i];
+            if (readout->file_exists != correctStatus) {
+                diag("TEST ERROR: pmCellSetFileStatus() failed to set file status for cell %d\n", i);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "pmCellSetFileStatus() set file status in all cells to FALSE");
+
+        // Second, set all flags to TRUE
+        correctStatus = true;
+        rc = pmCellSetFileStatus(cell, correctStatus);
+        ok(rc, "pmCellSetFileStatus() returned successfully with acceptable input params");
+        errorFlag = false;
+        if (cell->file_exists != correctStatus) {
+            diag("TEST ERROR: pmCellSetFileStatus() failed to set file status for cell param\n");
+            errorFlag = true;
+        }
+        for (int i = 0; i < cell->readouts->n; i++) {
+            pmReadout *readout = cell->readouts->data[i];
+            if (readout->file_exists != correctStatus) {
+                diag("TEST ERROR: pmCellSetFileStatus() failed to set file status for cell %d\n", i);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "pmCellSetFileStatus() set file status in all cells to TRUE");
+
+        // Third, set all flags to FALSE
+        correctStatus = false;
+        rc = pmCellSetFileStatus(cell, correctStatus);
+        ok(rc, "pmCellSetFileStatus() returned successfully with acceptable input params");
+        errorFlag = false;
+        if (cell->file_exists != correctStatus) {
+            diag("TEST ERROR: pmCellSetFileStatus() failed to set file status for cell param\n");
+            errorFlag = true;
+        }
+        for (int i = 0; i < cell->readouts->n; i++) {
+            pmReadout *readout = cell->readouts->data[i];
+            if (readout->file_exists != correctStatus) {
+                diag("TEST ERROR: pmCellSetFileStatus() failed to set file status for readout %d\n", i);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "pmCellSetFileStatus() set file status in all cells to FALSE");
+
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmFPACheckFileStatus() tests
+    // bool pmFPACheckFileStatus(const pmFPA *fpa)
+    // Call with NULL pmFPA input parameter
+    {
+        psMemId id = psMemGetId();
+        bool rc = pmFPACheckFileStatus(NULL);
+        ok(rc == false, "pmFPACheckFileStatus() returned FALSE with NULL pmFPA input parameter");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmFPA *fpa = generateSimpleFPA(NULL);
+        bool rc = pmFPACheckFileStatus(fpa);
+        ok(rc == false, "pmFPACheckFileStatus() returned FALSE with NULL pmFPA input parameter");
+        SetFPAFileExists(fpa);
+        rc = pmFPACheckFileStatus(fpa);
+        ok(rc == true, "pmFPACheckFileStatus() returned TRUE with NULL pmFPA input parameter");
+        psFree(fpa);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmChipCheckFileStatus() tests
+    // Call with NULL pmChip input parameter
+    {
+        psMemId id = psMemGetId();
+        bool rc = pmChipCheckFileStatus(NULL);
+        ok(rc == false, "pmChipCheckFileStatus() returned FALSE with NULL pmChip input parameter");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call with acceptable input parameter
+    {
+        psMemId id = psMemGetId();
+        pmChip *chip = generateSimpleChip(NULL);
+        bool rc = pmChipCheckFileStatus(chip);
+        ok(rc == false, "pmChipCheckFileStatus() returned FALSE with NULL pmChip input parameter");
+        SetChipFileExists(chip);
+        rc = pmChipCheckFileStatus(chip);
+        ok(rc == true, "pmChipCheckFileStatus() returned TRUE with NULL pmChip input parameter");
+        psFree(chip);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmCellCheckFileStatus() tests
+    // bool pmCellCheckFileStatus(const pmCell *cell)
+    // Call with NULL pmCell input parameter
+    {
+        psMemId id = psMemGetId();
+        bool rc = pmCellCheckFileStatus(NULL);
+        ok(rc == false, "pmCellCheckFileStatus() returned FALSE with NULL pmCell input parameter");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        bool rc = pmCellCheckFileStatus(cell);
+        ok(rc == false, "pmCellCheckFileStatus() returned FALSE with acceptable input parameters");
+        SetCellFileExists(cell);
+        rc = pmCellCheckFileStatus(cell);
+        ok(rc == true, "pmCellCheckFileStatus() returned TRUE with acceptable input parameters");
+        psFree(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmFPASetDataStatus() tests: verify with NULL pmFPA param
+    {
+        psMemId id = psMemGetId();
+        bool rc = pmFPASetDataStatus(NULL, false);
+        ok(!rc, "pmFPASetDataStatus() returned FALSE with NULL pmFPA param");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPASetDataStatus() tests: verify with acceptable data
+    // bool pmFPASetDataStatus(pmFPA *fpa, bool status)
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+
+        // First, set all flags to FALSE
+        bool correctStatus = false;
+        bool rc = pmFPASetDataStatus(fpa, correctStatus);
+        ok(rc, "pmFPASetDataStatus() returned successfully with acceptable input params");
+        bool errorFlag = false;
+        for (int k = 0 ; k < fpa->chips->n ; k++) {
+            pmChip *chip = fpa->chips->data[k];
+            for (int j = 0 ; j < chip->cells->n ; j++) {
+                pmCell *cell = chip->cells->data[j];
+                if (cell->data_exists != correctStatus) {
+                    diag("TEST ERROR: pmFPASetDataStatus() failed to set file status for chip %d cell %d\n", k, j);
+                    errorFlag = true;
+                }
+    
+                for (int i = 0; i < cell->readouts->n; i++) {
+                    pmReadout *readout = cell->readouts->data[i];
+                    if (readout->data_exists != correctStatus) {
+                        diag("TEST ERROR: pmFPASetDataStatus() failed to set file status for chip %d cell %d readout %d\n", k, j, i);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+        ok(!errorFlag, "pmFPASetDataStatus() set file status in all cells to FALSE");
+
+        // Second, set all flags to TRUE
+        correctStatus = true;
+        rc = pmFPASetDataStatus(fpa, correctStatus);
+        ok(rc, "pmFPASetDataStatus() returned successfully with acceptable input params");
+        errorFlag = false;
+        for (int k = 0 ; k < fpa->chips->n ; k++) {
+            pmChip *chip = fpa->chips->data[k];
+            for (int j = 0 ; j < chip->cells->n ; j++) {
+                pmCell *cell = chip->cells->data[j];
+                if (cell->data_exists != correctStatus) {
+                    diag("TEST ERROR: pmFPASetDataStatus() failed to set file status for chip %d cell %d\n", k, j);
+                    errorFlag = true;
+                }
+    
+                for (int i = 0; i < cell->readouts->n; i++) {
+                    pmReadout *readout = cell->readouts->data[i];
+                    if (readout->data_exists != correctStatus) {
+                        diag("TEST ERROR: pmFPASetDataStatus() failed to set file status for chip %d cell %d readout %d\n", k, j, i);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+        ok(!errorFlag, "pmFPASetDataStatus() set file status in all cells to TRUE");
+
+        // Third, set all flags to FALSE
+        correctStatus = false;
+        rc = pmFPASetDataStatus(fpa, correctStatus);
+        ok(rc, "pmFPASetDataStatus() returned successfully with acceptable input params");
+        errorFlag = false;
+        for (int k = 0 ; k < fpa->chips->n ; k++) {
+            pmChip *chip = fpa->chips->data[k];
+            for (int j = 0 ; j < chip->cells->n ; j++) {
+                pmCell *cell = chip->cells->data[j];
+                if (cell->data_exists != correctStatus) {
+                    diag("TEST ERROR: pmFPASetDataStatus() failed to set file status for chip %d cell %d\n", k, j);
+                    errorFlag = true;
+                }
+    
+                for (int i = 0; i < cell->readouts->n; i++) {
+                    pmReadout *readout = cell->readouts->data[i];
+                    if (readout->data_exists != correctStatus) {
+                        diag("TEST ERROR: pmFPASetDataStatus() failed to set file status for chip %d cell %d readout %d\n", k, j, i);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+        ok(!errorFlag, "pmFPASetDataStatus() set file status in all cells to FALSE");
+
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmChipSetDataStatus() tests: verify with NULL pmChip param
+    // bool pmChipSetDataStatus(pmChip *chip, bool status)
+    {
+        psMemId id = psMemGetId();
+        bool rc = pmChipSetDataStatus(NULL, false);
+        ok(!rc, "pmChipSetDataStatus() returned FALSE with NULL pmChip param");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmChipSetDataStatus() tests: verify with acceptable data
+    // bool pmChipSetDataStatus(pmChip *chip, bool status)
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+
+        // First, set all flags to FALSE
+        bool correctStatus = false;
+        bool rc = pmChipSetDataStatus(chip, correctStatus);
+        ok(rc, "pmChipSetDataStatus() returned successfully with acceptable input params");
+        bool errorFlag = false;
+        if (chip->data_exists != correctStatus) {
+            diag("TEST ERROR (a): pmChipSetDataStatus() failed to set file status for chip param\n");
+            errorFlag = true;
+        }
+        for (int j = 0 ; j < chip->cells->n ; j++) {
+            pmCell *cell = chip->cells->data[j];
+            if (cell->data_exists != correctStatus) {
+                diag("TEST ERROR (b): pmChipSetDataStatus() failed to set file status for cell %d\n", j);
+                errorFlag = true;
+            }
+
+            for (int i = 0; i < cell->readouts->n; i++) {
+                pmReadout *readout = cell->readouts->data[i];
+                if (readout->data_exists != correctStatus) {
+                    diag("TEST ERROR (c): pmChipSetDataStatus() failed to set file status for cell %d readout %d\n", j, i);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "pmChipSetDataStatus() set data status in all cells to FALSE");
+
+        // Second, set all flags to TRUE
+        correctStatus = true;
+        rc = pmChipSetDataStatus(chip, correctStatus);
+        ok(rc, "pmChipSetDataStatus() returned successfully with acceptable input params");
+        errorFlag = false;
+        if (chip->data_exists != correctStatus) {
+            diag("TEST ERROR (a): pmChipSetDataStatus() failed to set file status for chip param\n");
+            errorFlag = true;
+        }
+        for (int j = 0 ; j < chip->cells->n ; j++) {
+            pmCell *cell = chip->cells->data[j];
+            if (cell->data_exists != correctStatus) {
+                diag("TEST ERROR (b): pmChipSetDataStatus() failed to set file status for cell %d\n", j);
+                errorFlag = true;
+            }
+
+            for (int i = 0; i < cell->readouts->n; i++) {
+                pmReadout *readout = cell->readouts->data[i];
+                if (readout->data_exists != correctStatus) {
+                    diag("TEST ERROR (c): pmChipSetDataStatus() failed to set file status for cell %d readout %d\n", j, i);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "pmChipSetDataStatus() set data status in all cells to TRUE");
+
+        // ThirdSecond, set all flags to FALSE
+        correctStatus = false;
+        rc = pmChipSetDataStatus(chip, correctStatus);
+        ok(rc, "pmChipSetDataStatus() returned successfully with acceptable input params");
+        errorFlag = false;
+        if (chip->data_exists != correctStatus) {
+            diag("TEST ERROR (a): pmChipSetDataStatus() failed to set file status for chip param\n");
+            errorFlag = true;
+        }
+        for (int j = 0 ; j < chip->cells->n ; j++) {
+            pmCell *cell = chip->cells->data[j];
+            if (cell->data_exists != correctStatus) {
+                diag("TEST ERROR (b): pmChipSetDataStatus() failed to set file status for cell %d\n", j);
+                errorFlag = true;
+            }
+
+            for (int i = 0; i < cell->readouts->n; i++) {
+                pmReadout *readout = cell->readouts->data[i];
+                if (readout->data_exists != correctStatus) {
+                    diag("TEST ERROR (c): pmChipSetDataStatus() failed to set file status for cell %d readout %d\n", j, i);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "pmChipSetDataStatus() set data status in all cells to FALSE");
+
+
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmCellSetDataStatus() tests: verify with NULL pmCell param
+    // bool pmCellSetDataStatus(pmCell *cell, bool status)
+    {
+        psMemId id = psMemGetId();
+        bool rc = pmCellSetDataStatus(NULL, false);
+        ok(!rc, "pmCellSetDataStatus() returned FALSE with NULL pmCell param");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmCellSetDataStatus() tests: verify with acceptable data
+    // bool pmCellSetDataStatus(pmCell *cell, bool status)
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+
+        // First, set all flags to FALSE
+        bool correctStatus = false;
+        bool rc = pmCellSetDataStatus(cell, correctStatus);
+        ok(rc, "pmCellSetDataStatus() returned successfully with acceptable input params");
+        bool errorFlag = false;
+        if (cell->data_exists != correctStatus) {
+            diag("TEST ERROR: pmCellSetDataStatus() failed to set file status for cell param\n");
+            errorFlag = true;
+        }
+        for (int i = 0; i < cell->readouts->n; i++) {
+            pmReadout *readout = cell->readouts->data[i];
+            if (readout->data_exists != correctStatus) {
+                diag("TEST ERROR: pmCellSetDataStatus() failed to set file status for cell %d\n", i);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "pmCellSetDataStatus() set data status in all cells to FALSE");
+
+        // Second, set all flags to TRUE
+        correctStatus = true;
+        rc = pmCellSetDataStatus(cell, correctStatus);
+        ok(rc, "pmCellSetDataStatus() returned successfully with acceptable input params");
+        errorFlag = false;
+        if (cell->data_exists != correctStatus) {
+            diag("TEST ERROR: pmCellSetDataStatus() failed to set file status for cell param\n");
+            errorFlag = true;
+        }
+        for (int i = 0; i < cell->readouts->n; i++) {
+            pmReadout *readout = cell->readouts->data[i];
+            if (readout->data_exists != correctStatus) {
+                diag("TEST ERROR: pmCellSetDataStatus() failed to set file status for cell %d\n", i);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "pmCellSetDataStatus() set data status in all cells to TRUE");
+
+        // Third, set all flags to FALSE
+        correctStatus = false;
+        rc = pmCellSetDataStatus(cell, correctStatus);
+        ok(rc, "pmCellSetDataStatus() returned successfully with acceptable input params");
+        errorFlag = false;
+        if (cell->data_exists != correctStatus) {
+            diag("TEST ERROR: pmCellSetDataStatus() failed to set file status for cell param\n");
+            errorFlag = true;
+        }
+        for (int i = 0; i < cell->readouts->n; i++) {
+            pmReadout *readout = cell->readouts->data[i];
+            if (readout->data_exists != correctStatus) {
+                diag("TEST ERROR: pmCellSetDataStatus() failed to set file status for readout %d\n", i);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "pmCellSetDataStatus() set data status in all cells to FALSE");
+
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmFPACheckDataStatus() tests
+    // bool pmFPACheckDataStatus(const pmFPA *fpa)
+    // Call with NULL pmFPA input parameter
+    {
+        psMemId id = psMemGetId();
+        bool rc = pmFPACheckDataStatus(NULL);
+        ok(rc == false, "pmFPACheckDataStatus() returned FALSE with NULL pmFPA input parameter");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmFPA *fpa = generateSimpleFPA(NULL);
+        bool rc = pmFPACheckDataStatus(fpa);
+        ok(rc == false, "pmFPACheckDataStatus() returned FALSE with NULL pmFPA input parameter");
+        SetFPADataExists(fpa);
+        rc = pmFPACheckDataStatus(fpa);
+        ok(rc == true, "pmFPACheckDataStatus() returned TRUE with NULL pmFPA input parameter");
+        psFree(fpa);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmChipCheckDataStatus() tests
+    // Call with NULL pmChip input parameter
+    {
+        psMemId id = psMemGetId();
+        bool rc = pmChipCheckDataStatus(NULL);
+        ok(rc == false, "pmChipCheckDataStatus() returned FALSE with NULL pmChip input parameter");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call with acceptable input parameter
+    {
+        psMemId id = psMemGetId();
+        pmChip *chip = generateSimpleChip(NULL);
+        bool rc = pmChipCheckDataStatus(chip);
+        ok(rc == false, "pmChipCheckDataStatus() returned FALSE with NULL pmChip input parameter");
+        SetChipDataExists(chip);
+        rc = pmChipCheckDataStatus(chip);
+        ok(rc == true, "pmChipCheckDataStatus() returned TRUE with NULL pmChip input parameter");
+        psFree(chip);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmCellCheckDataStatus() tests
+    // bool pmCellCheckDataStatus(const pmCell *cell)
+    // Call with NULL pmCell input parameter
+    {
+        psMemId id = psMemGetId();
+        bool rc = pmCellCheckDataStatus(NULL);
+        ok(rc == false, "pmCellCheckDataStatus() returned FALSE with NULL pmCell input parameter");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        bool rc = pmCellCheckDataStatus(cell);
+        ok(rc == false, "pmCellCheckDataStatus() returned FALSE with acceptable input parameters");
+        SetCellDataExists(cell);
+        rc = pmCellCheckDataStatus(cell);
+        ok(rc == true, "pmCellCheckDataStatus() returned TRUE with acceptable input parameters");
+        psFree(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmReadoutCheckDataStatus() tests
+    // bool pmReadoutCheckDataStatus(const pmReadout *readout)
+    // Call with NULL pmReadout input parameter
+    {
+        psMemId id = psMemGetId();
+        bool rc = pmReadoutCheckDataStatus(NULL);
+        ok(rc == false, "pmReadoutCheckDataStatus() returned FALSE with NULL pmReadout input parameter");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        bool rc = pmReadoutCheckDataStatus(readout);
+        ok(rc == false, "pmReadoutCheckDataStatus() returned FALSE with acceptable input parameters");
+        SetReadoutDataExists(readout);
+        rc = pmReadoutCheckDataStatus(readout);
+        ok(rc == true, "pmReadoutCheckDataStatus() returned TRUE with acceptable input parameters");
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAHeader.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAHeader.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAHeader.c	(revision 22158)
@@ -0,0 +1,449 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    All functions are tested.
+*/
+
+#define CHIP_ALLOC_NAME        "ChipName"
+#define CELL_ALLOC_NAME        "CellName"
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define MISC_NAME2             "META01"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           4
+#define TEST_NUM_COLS           4
+#define NUM_READOUTS            3
+#define NUM_CELLS               10
+#define NUM_CHIPS               8
+#define NUM_HDUS                5
+#define BASE_IMAGE              10
+#define BASE_MASK               40
+#define BASE_WEIGHT             70
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+char *fitsFilename = "tmp.fits";
+
+psPlaneTransform *PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM()
+{
+    psPlaneTransform *pt = psPlaneTransformAlloc(1, 1);
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+    return(pt);
+}
+
+psPlaneDistort *PS_CREATE_4D_IDENTITY_PLANE_DISTORT()
+{
+    psPlaneDistort *pd = psPlaneDistortAlloc(1, 1, 1, 1);
+    pd->x->coeff[1][0][0][0] = 1.0;
+    pd->y->coeff[0][1][0][0] = 1.0;
+    return(pd);
+}
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmChip *chip, int cellID)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    char extname[80];
+    snprintf(extname,80, "ext-%d", cellID);
+    cell->hdu = pmHDUAlloc(extname);
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = psMemDecrRefCounter((psPtr) generateSimpleReadout(cell));
+    }
+
+    // First try to read data from ../dataFiles, then try dataFiles.
+    bool rc = pmConfigFileRead(&cell->hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        rc = pmConfigFileRead(&cell->hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            diag("pmConfigFileRead() was unsuccessful (from generateSimpleCell())");
+	}
+    }
+
+    cell->hdu->images = psArrayAlloc(NUM_HDUS);
+    cell->hdu->masks = psArrayAlloc(NUM_HDUS);
+    cell->hdu->weights = psArrayAlloc(NUM_HDUS);
+    for (int k = 0 ; k < NUM_HDUS ; k++) {
+        cell->hdu->images->data[k]  = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        cell->hdu->masks->data[k]   = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        cell->hdu->weights->data[k] = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(cell->hdu->images->data[k], (float) (BASE_IMAGE+k));
+        psImageInit(cell->hdu->masks->data[k], (psU8) (BASE_MASK+k));
+        psImageInit(cell->hdu->weights->data[k], (float) (BASE_WEIGHT+k));
+    }
+
+    psRegion *region = psRegionAlloc(0.0, 0.0, 0.0, 0.0);
+    // You shouldn't have to remove the key from the metadata.
+    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC");
+    psMetadataAddPtr(cell->concepts, PS_LIST_TAIL|PS_META_REPLACE, "CELL.TRIMSEC", PS_DATA_REGION, "I am a region", region);
+    psFree(region);
+    return(cell);
+}
+
+/******************************************************************************
+generateSimpleChip(): This function generates a pmChip data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmChip *generateSimpleChip(pmFPA *fpa, int chipID)
+{
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    chip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    chip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    psMetadataAddS32(chip->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(chip->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    if (0) {
+        char extname[80];
+        snprintf(extname,80, "ext-%d", chipID);
+        chip->hdu = pmHDUAlloc(extname);
+    }
+
+    psArrayRealloc(chip->cells, NUM_CELLS);
+    for (int i = 0 ; i < NUM_CELLS ; i++) {
+        chip->cells->data[i] = psMemDecrRefCounter((psPtr) generateSimpleCell(chip, i));
+    }
+    return(chip);
+}
+
+/******************************************************************************
+generateSimpleFPA(): This function generates a pmFPA data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmFPA* generateSimpleFPA(psMetadata *camera)
+{
+    pmFPA* fpa = pmFPAAlloc(camera);
+    fpa->fromTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toSky = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+    psMetadataAddS32(fpa->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    if (camera != NULL) {
+        psMetadataAddS32((psMetadata *) fpa->camera, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    }
+    psMetadataAddS32(fpa->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    psArrayRealloc(fpa->chips, NUM_CHIPS);
+    for (int i = 0 ; i < NUM_CHIPS ; i++) {
+        fpa->chips->data[i] = psMemDecrRefCounter((psPtr) generateSimpleChip(fpa, i));
+    }
+    pmConceptsBlankFPA(fpa);
+    return(fpa);
+}
+
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(75);
+
+
+    // ----------------------------------------------------------------------
+    // pmCellReadHeader() tests: NULL input fits file
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA *fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        ok(!pmCellReadHeader(cell, NULL), "pmCellReadHeader(cell, NULL) returned FALSE");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmCellReadHeader() tests: NULL input pmCell
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(fitsFilename, "w");
+        ok(fitsFileW != NULL, "psFitsOpen() opened the FITS file");
+        ok(!pmCellReadHeader(NULL, fitsFileW), "pmCellReadHeader(NULL, fitsFile) returned FALSE");
+        psFree(fitsFileW);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmCellReadHeader() tests: acceptable data
+    {
+        psMemId id = psMemGetId();
+        // Create a FITS file for this test
+        psFits* fitsFileW = psFitsOpen(fitsFilename, "w");
+        ok(fitsFileW != NULL, "psFitsOpen() opened the FITS file");
+        char extname[80];
+        for (int lcv = 0; lcv < NUM_HDUS; lcv++) {
+            snprintf(extname, 80, "ext-%d", lcv);
+            pmHDU *hdu = pmHDUAlloc(extname);
+            hdu->header = psMetadataAlloc();
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYINT", PS_DATA_S32,
+                         "psS32 Item", (psS32)lcv);
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYFLT", PS_DATA_F32,
+                         "psF32 Item", (float)(1.0f/(float)(1+lcv)));
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYDBL", PS_DATA_F64,
+                         "psF64 Item", (double)(1.0/(double)(1+lcv)));
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYBOOL", PS_DATA_BOOL,
+                         "psBool Item", (lcv%2 == 0));
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYSTR", PS_DATA_STRING,
+                         "String Item", extname);
+            bool rc = pmConfigFileRead(&hdu->format, "../dataFiles/camera0/format0.config", "Camera 0 Config Format");
+            if (!rc) {
+                rc = pmConfigFileRead(&hdu->format, "dataFiles/camera0/format0.config", "Camera 0 Config Format");
+	    }
+            ok(rc == true, "pmConfigFileRead() was successful");
+            rc = pmHDUWrite(hdu, fitsFileW);
+            ok(rc == true, "pmHDUWrite() successfully wrote the header");
+            psFree(hdu);
+        }
+        psFitsClose(fitsFileW);
+
+        // Now, open that FITS file, and create an pmFPA hierarchy
+        psFits* fitsFileR = psFitsOpen(fitsFilename, "r");
+        ok(fitsFileR != NULL, "psFitsOpen returned non-NULL on existing file");
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA *fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+
+        ok(pmCellReadHeader(cell, fitsFileR), "pmCellReadHeader() returned TRUE with acceptable data");
+
+        // XXX: It's not clear if we should test if the HDU and pmConcepts actually
+        // get rid, since pmCellReadHeader() simply calls functions that are tested
+        // elsewhere.  However, if we should test it, test it here.
+
+        psFree(fpa);
+        psFree(camera);
+        psFree(fitsFileR);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmChipReadHeader() tests: NULL input fits file
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA *fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        ok(!pmChipReadHeader(chip, NULL), "pmChipReadHeader(chip, NULL) returned FALSE");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmChipReadHeader() tests: NULL input pmCell
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(fitsFilename, "w");
+        ok(fitsFileW != NULL, "psFitsOpen() opened the FITS file");
+        ok(!pmChipReadHeader(NULL, fitsFileW), "pmChipReadHeader(NULL, fitsFile) returned FALSE");
+        psFree(fitsFileW);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmChipReadHeader() tests: acceptable data
+    {
+        psMemId id = psMemGetId();
+
+        // Create a FITS file for this test
+        psFits* fitsFileW = psFitsOpen(fitsFilename, "w");
+        ok(fitsFileW != NULL, "psFitsOpen() opened the FITS file");
+        char extname[80];
+        for (int lcv = 0; lcv < NUM_HDUS; lcv++) {
+            snprintf(extname, 80, "ext-%d", lcv);
+            pmHDU *hdu = pmHDUAlloc(extname);
+            hdu->header = psMetadataAlloc();
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYINT", PS_DATA_S32,
+                         "psS32 Item", (psS32)lcv);
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYFLT", PS_DATA_F32,
+                         "psF32 Item", (float)(1.0f/(float)(1+lcv)));
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYDBL", PS_DATA_F64,
+                         "psF64 Item", (double)(1.0/(double)(1+lcv)));
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYBOOL", PS_DATA_BOOL,
+                         "psBool Item", (lcv%2 == 0));
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYSTR", PS_DATA_STRING,
+                         "String Item", extname);
+            bool rc = pmConfigFileRead(&hdu->format, "../dataFiles/camera0/format0.config", "Camera 0 Config Format");
+            if (!rc) {
+               rc = pmConfigFileRead(&hdu->format, "dataFiles/camera0/format0.config", "Camera 0 Config Format");
+	    }
+            ok(rc == true, "pmConfigFileRead() was successful");
+            rc = pmHDUWrite(hdu, fitsFileW);
+            ok(rc == true, "pmHDUWrite() successfully wrote the header");
+            psFree(hdu);
+        }
+        psFitsClose(fitsFileW);
+
+        // Now, open that FITS file, and create an pmFPA hierarchy
+        psFits* fitsFileR = psFitsOpen(fitsFilename, "r");
+        ok(fitsFileR != NULL, "psFitsOpen returned non-NULL on existing file");
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA *fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+
+        // Set the correct extension names for the chips (if we put this in the
+        // generateChip() code, then psMOdules aborts.
+        for (int chipID = 0 ; chipID < fpa->chips->n ; chipID++) {
+            pmChip *chip = fpa->chips->data[chipID];
+            char extname[80];
+            snprintf(extname,80, "ext-%d", chipID);
+            chip->hdu = pmHDUAlloc(extname);
+	}
+
+        ok(pmChipReadHeader(chip, fitsFileR), "pmChipReadHeader() returned TRUE with acceptable data");
+
+
+        // XXX: It's not clear if we should test if the HDU and pmConcepts actually
+        // get rid, since pmCellReadHeader() simply calls functions that are tested
+        // elsewhere.  However, if we should test it, test it here.
+
+        psFree(fpa);
+        psFree(camera);
+        psFree(fitsFileR);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmFPAReadHeader() tests: NULL input fits file
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA *fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        ok(!pmFPAReadHeader(fpa, NULL), "pmFPAReadHeader(fpa, NULL) returned FALSE");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAReadHeader() tests: NULL input pmCell
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(fitsFilename, "w");
+        ok(fitsFileW != NULL, "psFitsOpen() opened the FITS file");
+        ok(!pmFPAReadHeader(NULL, fitsFileW), "pmFPAReadHeader(NULL, fitsFile) returned FALSE");
+        psFree(fitsFileW);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAReadHeader() tests: acceptable data
+    {
+        psMemId id = psMemGetId();
+
+        // Create a FITS file for this test
+        psFits* fitsFileW = psFitsOpen(fitsFilename, "w");
+        ok(fitsFileW != NULL, "psFitsOpen() opened the FITS file");
+        char extname[80];
+        for (int lcv = 0; lcv < NUM_HDUS; lcv++) {
+            snprintf(extname, 80, "ext-%d", lcv);
+            pmHDU *hdu = pmHDUAlloc(extname);
+            hdu->header = psMetadataAlloc();
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYINT", PS_DATA_S32,
+                         "psS32 Item", (psS32)lcv);
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYFLT", PS_DATA_F32,
+                         "psF32 Item", (float)(1.0f/(float)(1+lcv)));
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYDBL", PS_DATA_F64,
+                         "psF64 Item", (double)(1.0/(double)(1+lcv)));
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYBOOL", PS_DATA_BOOL,
+                         "psBool Item", (lcv%2 == 0));
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYSTR", PS_DATA_STRING,
+                         "String Item", extname);
+            bool rc = pmConfigFileRead(&hdu->format, "../dataFiles/camera0/format0.config", "Camera 0 Config Format");
+            if (!rc) {
+                rc = pmConfigFileRead(&hdu->format, "dataFiles/camera0/format0.config", "Camera 0 Config Format");
+	    }
+            ok(rc == true, "pmConfigFileRead() was successful");
+            rc = pmHDUWrite(hdu, fitsFileW);
+            ok(rc == true, "pmHDUWrite() successfully wrote the header");
+            psFree(hdu);
+        }
+        psFitsClose(fitsFileW);
+
+        // Now, open that FITS file, and create an pmFPA hierarchy
+        psFits* fitsFileR = psFitsOpen(fitsFilename, "r");
+        ok(fitsFileR != NULL, "psFitsOpen returned non-NULL on existing file");
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA *fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+
+        // Set the correct extension names for the chips (if we put this in the
+        // generateChip() code, then psMOdules aborts.
+        for (int chipID = 0 ; chipID < fpa->chips->n ; chipID++) {
+            pmChip *chip = fpa->chips->data[chipID];
+            char extname[80];
+            snprintf(extname,80, "ext-%d", chipID);
+            chip->hdu = pmHDUAlloc(extname);
+	}
+        snprintf(extname,80, "ext-%d", 0);
+        fpa->hdu = pmHDUAlloc(extname);
+
+        ok(pmFPAReadHeader(fpa, fitsFileR), "pmFPAReadHeader() returned TRUE with acceptable data");
+
+        // XXX: It's not clear if we should test if the HDU and pmConcepts actually
+        // get rid, since pmCellReadHeader() simply calls functions that are tested
+        // elsewhere.  However, if we should test it, test it here.
+
+        psFree(fpa);
+        psFree(camera);
+        psFree(fitsFileR);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPALevel.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPALevel.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPALevel.c	(revision 22158)
@@ -0,0 +1,76 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    All functions are tested.
+    XXX: Add tests for bad input parameters.
+*/
+
+#define	ERR_TRACE_LEVEL		0
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(14);
+
+    // ----------------------------------------------------------------------
+    // pmFPALevelToName(): tests
+    // const char *pmFPALevelToName(pmFPALevel level)
+    {
+        psMemId id = psMemGetId();
+        char *str = (char *) pmFPALevelToName(PM_FPA_LEVEL_NONE);
+        ok(!strcmp(str, "NONE"), "pmFPALevelToName(PM_FPA_LEVEL_NONE)");
+
+        str = (char *) pmFPALevelToName(PM_FPA_LEVEL_FPA);
+        ok(!strcmp(str, "FPA"), "pmFPALevelToName(PM_FPA_LEVEL_FPA)");
+
+        str = (char *) pmFPALevelToName(PM_FPA_LEVEL_CHIP);
+        ok(!strcmp(str, "CHIP"), "pmFPALevelToName(PM_FPA_LEVEL_CHIP)");
+
+        str = (char *) pmFPALevelToName(PM_FPA_LEVEL_CELL);
+        ok(!strcmp(str, "CELL"), "pmFPALevelToName(PM_FPA_LEVEL_CELL)");
+
+        str = (char *) pmFPALevelToName(PM_FPA_LEVEL_READOUT);
+        ok(!strcmp(str, "READOUT"), "pmFPALevelToName(PM_FPA_LEVEL_READOUT)");
+
+        // XXX: We avoid this because pmFPALevelToName() aborts
+        if (0) {
+            str = (char *) pmFPALevelToName(-1);
+            ok(str == NULL, "pmFPALevelToName(-1)");
+	}
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmFPALevelFromName(): tests
+    {
+        psMemId id = psMemGetId();
+        pmFPALevel lev = pmFPALevelFromName("NONE");
+        ok(lev == PM_FPA_LEVEL_NONE, "pmFPALevelToName(NONE)");
+
+        lev = pmFPALevelFromName("FPA");
+        ok(lev == PM_FPA_LEVEL_FPA, "pmFPALevelToName(FPA)");
+
+        lev = pmFPALevelFromName("CHIP");
+        ok(lev == PM_FPA_LEVEL_CHIP, "pmFPALevelToName(CHIP)");
+
+        lev = pmFPALevelFromName("CELL");
+        ok(lev == PM_FPA_LEVEL_CELL, "pmFPALevelToName(CELL)");
+
+        lev = pmFPALevelFromName("READOUT");
+        ok(lev == PM_FPA_LEVEL_READOUT, "pmFPALevelToName(READOUT)");
+
+        lev = pmFPALevelFromName("BOGUS");
+        ok(lev == PM_FPA_LEVEL_NONE, "pmFPALevelToName(BOGUS)");
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAMaskW.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAMaskW.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAMaskW.c	(revision 22158)
@@ -0,0 +1,426 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+// XXX: Use better name for the temporary FITS file
+// XXX: For the genSimpleFPA() code, add IDs to each function so that
+// the values set in each chip-?cell-?hdu-?image are unique
+// XXX: For the genSimpleFPA() code, write masks and weights as well
+// XXX: Must add tests for pmReadoutGenerateWeight()
+// XXX: We don't test pmReadoutGenerateMaskWeight() and pmCellGenerateMaskWeight()
+// because they are simply calls to the above tested functions
+
+#define CHIP_ALLOC_NAME        "ChipName"
+#define CELL_ALLOC_NAME        "CellName"
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define MISC_NAME2             "META01"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           4
+#define TEST_NUM_COLS           4
+#define NUM_READOUTS            3
+#define NUM_CELLS               10
+#define NUM_CHIPS               8
+#define NUM_HDUS                5
+#define BASE_IMAGE              10
+#define BASE_MASK               40
+#define BASE_WEIGHT             70
+#define SATURATION_LEVEL	10000.0
+#define BAD_LEVEL		100.0
+#define SATURATION_MASK		1
+#define BAD_MASK		2
+#define CELL_GAIN		1.0
+#define CELL_READNOISE		2.0
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+psPlaneTransform *PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM()
+{
+    psPlaneTransform *pt = psPlaneTransformAlloc(1, 1);
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+    return(pt);
+}
+
+psPlaneDistort *PS_CREATE_4D_IDENTITY_PLANE_DISTORT()
+{
+    psPlaneDistort *pd = psPlaneDistortAlloc(1, 1, 1, 1);
+    pd->x->coeff[1][0][0][0] = 1.0;
+    pd->y->coeff[0][1][0][0] = 1.0;
+    return(pd);
+}
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (int i = 0 ; i < TEST_NUM_ROWS ; i++) {
+        for (int j = 0 ; j < TEST_NUM_COLS ; j++) {
+            readout->image->data.F32[i][j] = 32.0;
+            readout->mask->data.U8[i][j] = 0;
+            readout->weight->data.F32[i][j] = 1.0;
+	}
+    }
+
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    cell->hdu = pmHDUAlloc("cellExtName");
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = psMemDecrRefCounter((psPtr) generateSimpleReadout(cell));
+    }
+
+    // First try to read data from ../dataFiles, then try dataFiles.
+    bool rc = pmConfigFileRead(&cell->hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        rc = pmConfigFileRead(&cell->hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            diag("pmConfigFileRead() was unsuccessful (from generateSimpleCell())");
+	}
+    }
+
+    cell->hdu->images = psArrayAlloc(NUM_HDUS);
+    cell->hdu->masks = psArrayAlloc(NUM_HDUS);
+    cell->hdu->weights = psArrayAlloc(NUM_HDUS);
+    for (int k = 0 ; k < NUM_HDUS ; k++) {
+        cell->hdu->images->data[k]  = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        cell->hdu->masks->data[k]   = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        cell->hdu->weights->data[k] = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(cell->hdu->images->data[k], (float) (BASE_IMAGE+k));
+        psImageInit(cell->hdu->masks->data[k], (psU8) (BASE_MASK+k));
+        psImageInit(cell->hdu->weights->data[k], (float) (BASE_WEIGHT+k));
+    }
+
+    //XXX: Should the region be set some other way?  Like through the various config files?
+    psRegion *region = psRegionAlloc(0.0, 0.0, 0.0, 0.0);
+    // You shouldn't have to remove the key from the metadata.
+    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC");
+    psMetadataAddPtr(cell->concepts, PS_LIST_TAIL|PS_META_REPLACE, "CELL.TRIMSEC", PS_DATA_REGION, "I am a region", region);
+    psFree(region);
+    return(cell);
+}
+
+/******************************************************************************
+generateSimpleChip(): This function generates a pmChip data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmChip *generateSimpleChip(pmFPA *fpa)
+{
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    chip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    chip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    psMetadataAddS32(chip->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(chip->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    psArrayRealloc(chip->cells, NUM_CELLS);
+    for (int i = 0 ; i < NUM_CELLS ; i++) {
+        chip->cells->data[i] = psMemDecrRefCounter((psPtr) generateSimpleCell(chip));
+    }
+    return(chip);
+}
+
+/******************************************************************************
+generateSimpleFPA(): This function generates a pmFPA data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmFPA* generateSimpleFPA(psMetadata *camera)
+{
+    pmFPA* fpa = pmFPAAlloc(camera);
+    fpa->fromTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toSky = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+    psMetadataAddS32(fpa->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    if (camera != NULL) {
+        psMetadataAddS32((psMetadata *) fpa->camera, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    }
+    psMetadataAddS32(fpa->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    psArrayRealloc(fpa->chips, NUM_CHIPS);
+    for (int i = 0 ; i < NUM_CHIPS ; i++) {
+        fpa->chips->data[i] = psMemDecrRefCounter((psPtr) generateSimpleChip(fpa));
+    }
+    pmConceptsBlankFPA(fpa);
+    return(fpa);
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(18);
+
+    // ----------------------------------------------------------------------
+    // pmReadoutSetMask() tests: NULL inputs
+    // bool pmReadoutSetMask(pmReadout *readout, psMaskType satMask, psMaskType badMask)
+    if (1) {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        pmReadout *readout = cell->readouts->data[0];
+        bool rc;
+
+        // Set readout == NULL, ensure pmReadoutSetMask() returnes FALSE, with no seg faults, memory leaks
+        rc = pmReadoutSetMask(NULL, SATURATION_MASK, BAD_MASK);
+        ok(!rc, "pmReadoutSetMask(NULL, SATURATION_MASK, BAD_MASK) returned FALSE with null pmReadout input");
+
+        // Set readout->image, ensure pmReadoutSetMask() returnes FALSE, with no seg faults, memory leaks
+        psImage *saveImg = readout->image;
+        readout->image = NULL;
+        rc = pmReadoutSetMask(readout, SATURATION_MASK, BAD_MASK);
+        ok(!rc, "pmReadoutSetMask(readout, SATURATION_MASK, BAD_MASK) returned FALSE with null pmReadout->image input");
+        readout->image = saveImg;
+
+        // Set pixels in the upper-left quadrant to values [10000:11000] range
+        // Set pixels in the upper-right quadrant to values [0:1000] range
+        // Set pixels in the lower-left quadrant to values [100000:1000000] range
+        // Set pixels in the lower-right quadrant to values [100000:1000000] range
+
+        for (int i = 0 ; i < readout->image->numRows ; i++) {
+            for (int j = 0 ; j < readout->image->numCols ; j++) {
+                if (i < readout->image->numRows/2) {
+                    if (j < readout->image->numCols/2) {
+                        readout->image->data.F32[i][j] = 10000.0 + (float) (i + j);
+		    } else {
+                        readout->image->data.F32[i][j] = (float) (i + j);
+		    }
+		} else {
+                    readout->image->data.F32[i][j] = 100000.0 + (float) (i + j);
+		}
+	    }
+	}
+
+        // Set the acceptable pixel range to [100.0 : 20000.0]
+        rc = psMetadataAddF32(readout->parent->concepts, PS_LIST_HEAD, "CELL.SATURATION", PS_META_REPLACE, NULL, 20000.0);
+        rc|= psMetadataAddF32(readout->parent->concepts, PS_LIST_HEAD, "CELL.BAD", PS_META_REPLACE, NULL, 100.0);
+        ok(rc, "Set pixel range in cell->concepts successfully");
+
+        // Call pmReadoutSetMask() and then verify that the mask data was set correctly
+        rc = pmReadoutSetMask(readout, SATURATION_MASK, BAD_MASK);
+        ok(rc, "pmReadoutSetMask(readout, SATURATION_MASK, BAD_MASK) returned TRUE with acceptable input data");
+        bool errorFlag = false;
+        for (int i = 0 ; i < readout->image->numRows ; i++) {
+            for (int j = 0 ; j < readout->image->numCols ; j++) {
+                if (i < readout->image->numRows/2) {
+                    if (j < readout->image->numCols/2) {
+                        if(readout->mask->data.U8[i][j] != 0) {
+                            if (VERBOSE) {
+                                diag("TEST ERROR: mask[%d][%d] is %d, should be 0\n",
+                                      i, j, readout->mask->data.U8[i][j]);
+			    }
+                            errorFlag = true;
+			}
+		    } else {
+                        if(readout->mask->data.U8[i][j] != BAD_MASK) {
+                            if (VERBOSE) {
+                                diag("TEST ERROR: mask[%d][%d] is %d, should be %d\n",
+                                      i, j, readout->mask->data.U8[i][j], BAD_MASK);
+			    }
+                            errorFlag = true;
+			}
+		    }
+		} else {
+                    if(readout->mask->data.U8[i][j] != SATURATION_MASK) {
+                        if (VERBOSE) {
+                            diag("TEST ERROR: mask[%d][%d] is %d, should be %d\n",
+                                  i, j, readout->mask->data.U8[i][j], SATURATION_MASK);
+                        }
+                        errorFlag = true;
+		    }
+		}
+	    }
+	}
+        ok(!errorFlag, "pmReadoutSetMask() set the mask values correctly");
+        psFree(fpa);    
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // ----------------------------------------------------------------------
+    // pmReadoutGenerateMask() tests: NULL inputs
+    // bool pmReadoutGenerateMask(pmReadout *readout, psMaskType satMask, psMaskType badMask)
+    // XXX: This test is a duplicate of the above pmReadoutSetMask() test since the actual
+    // code is almost the same.  Must test with the readout->mask == NULL.
+    if (1) {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        pmReadout *readout = cell->readouts->data[0];
+        bool rc;
+
+        // Set readout == NULL, ensure pmReadoutGenerateMask() returnes FALSE, with no seg faults, memory leaks
+        rc = pmReadoutGenerateMask(NULL, SATURATION_MASK, BAD_MASK);
+        ok(!rc, "pmReadoutGenerateMask(NULL, SATURATION_MASK, BAD_MASK) returned FALSE with null pmReadout input");
+
+        // Set pixels in the upper-left quadrant to values [10000:11000] range
+        // Set pixels in the upper-right quadrant to values [0:1000] range
+        // Set pixels in the lower-left quadrant to values [100000:1000000] range
+        // Set pixels in the lower-right quadrant to values [100000:1000000] range
+
+        for (int i = 0 ; i < readout->image->numRows ; i++) {
+            for (int j = 0 ; j < readout->image->numCols ; j++) {
+                if (i < readout->image->numRows/2) {
+                    if (j < readout->image->numCols/2) {
+                        readout->image->data.F32[i][j] = 10000.0 + (float) (i + j);
+		    } else {
+                        readout->image->data.F32[i][j] = (float) (i + j);
+		    }
+		} else {
+                    readout->image->data.F32[i][j] = 100000.0 + (float) (i + j);
+		}
+	    }
+	}
+
+        // Set the acceptable pixel range to [100.0 : 20000.0]
+        rc = psMetadataAddF32(readout->parent->concepts, PS_LIST_HEAD, "CELL.SATURATION", PS_META_REPLACE, NULL, 20000.0);
+        rc|= psMetadataAddF32(readout->parent->concepts, PS_LIST_HEAD, "CELL.BAD", PS_META_REPLACE, NULL, 100.0);
+        ok(rc, "Set pixel range in cell->concepts successfully");
+
+        // Call pmReadoutGenerateMask() and then verify that the mask data was set correctly
+        rc = pmReadoutGenerateMask(readout, SATURATION_MASK, BAD_MASK);
+        ok(rc, "pmReadoutGenerateMask(readout, SATURATION_MASK, BAD_MASK) returned TRUE with acceptable input data");
+        bool errorFlag = false;
+        for (int i = 0 ; i < readout->image->numRows ; i++) {
+            for (int j = 0 ; j < readout->image->numCols ; j++) {
+                if (i < readout->image->numRows/2) {
+                    if (j < readout->image->numCols/2) {
+                        if(readout->mask->data.U8[i][j] != 0) {
+                            if (VERBOSE) {
+                                diag("TEST ERROR: mask[%d][%d] is %d, should be 0\n",
+                                      i, j, readout->mask->data.U8[i][j]);
+			    }
+                            errorFlag = true;
+			}
+		    } else {
+                        if(readout->mask->data.U8[i][j] != BAD_MASK) {
+                            if (VERBOSE) {
+                                diag("TEST ERROR: mask[%d][%d] is %d, should be %d\n",
+                                      i, j, readout->mask->data.U8[i][j], BAD_MASK);
+                                errorFlag = true;
+			    }
+			}
+		    }
+		} else {
+                    if(readout->mask->data.U8[i][j] != SATURATION_MASK) {
+                        if (VERBOSE) {
+                            diag("TEST ERROR: mask[%d][%d] is %d, should be %d\n",
+                                  i, j, readout->mask->data.U8[i][j], SATURATION_MASK);
+                        }
+                        errorFlag = true;
+		    }
+		}
+	    }
+	}
+        ok(!errorFlag, "pmReadoutGenerateMask() set the mask values correctly");
+
+        psFree(fpa);    
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // ----------------------------------------------------------------------
+    // pmReadoutSetWeight() tests: NULL inputs
+    // bool pmReadoutSetWeight(pmReadout *readout, bool poisson)
+    if (1) {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        pmReadout *readout = cell->readouts->data[0];
+        bool rc;
+
+        // Set readout == NULL, ensure pmReadoutSetWeight() returnes FALSE, with no seg faults, memory leaks
+        rc = pmReadoutSetWeight(NULL, false);
+        ok(!rc, "pmReadoutSetWeight(NULL, false) returned FALSE with null pmReadout input");
+
+
+        // Set the acceptable pixel range to [100.0 : 20000.0]
+        rc = psMetadataAddF32(readout->parent->concepts, PS_LIST_HEAD, "CELL.GAIN", PS_META_REPLACE, NULL, CELL_GAIN);
+        rc|= psMetadataAddF32(readout->parent->concepts, PS_LIST_HEAD, "CELL.READNOISE", PS_META_REPLACE, NULL, CELL_READNOISE);
+        ok(rc, "Set GAIN and READNOISE in cell->concepts successfully");
+
+        // Call pmReadoutSetWeight() and then verify that the mask data was set correctly
+        rc = pmReadoutSetWeight(readout, false);
+        ok(rc, "pmReadoutSetWeight(readout, false) returned TRUE with acceptable input data");
+        bool errorFlag = false;
+        for (int i = 0 ; i < readout->weight->numRows ; i++) {
+            for (int j = 0 ; j < readout->weight->numCols ; j++) {
+                psF32 exp = CELL_READNOISE * CELL_READNOISE / CELL_GAIN / CELL_GAIN;
+                if(abs(readout->weight->data.F32[i][j] - exp) > 1e-4) {
+                    if (VERBOSE) {
+                        diag("TEST ERROR: weight[%d][%d] is %.2f, should be %.2f\n",
+                              i, j, readout->weight->data.F32[i][j], exp);
+		    }
+                    errorFlag = true;
+		}
+	    }
+	}
+        ok(!errorFlag, "pmReadoutSetWeight() set the weight values correctly (non-Poisson)");
+
+        for (int i = 0 ; i < readout->image->numRows ; i++) {
+            for (int j = 0 ; j < readout->image->numCols ; j++) {
+               readout->image->data.F32[i][j] = 100.0 + (float) (i + j);
+	    }
+	}
+        // Call pmReadoutSetWeight() and then verify that the mask data was set correctly
+        rc = pmReadoutSetWeight(readout, true);
+        ok(rc, "pmReadoutSetWeight(readout, true) returned TRUE with acceptable input data");
+        errorFlag = false;
+        for (int i = 0 ; i < readout->weight->numRows ; i++) {
+            for (int j = 0 ; j < readout->weight->numCols ; j++) {
+                psF32 exp = abs(readout->image->data.F32[i][j] / CELL_GAIN); 
+                if (exp < 1.0) exp = 1.0;
+                exp+= CELL_READNOISE * CELL_READNOISE / CELL_GAIN / CELL_GAIN;
+                if(abs(readout->weight->data.F32[i][j] - exp) > 1e-4) {
+                    if (VERBOSE) {
+                        diag("TEST ERROR: weight[%d][%d] is %.2f, should be %.2f\n",
+                              i, j, readout->weight->data.F32[i][j], exp);
+		    }
+                    errorFlag = true;
+		}
+	    }
+	}
+
+        ok(!errorFlag, "pmReadoutSetWeight() set the weight values correctly (Poisson)");
+        psFree(fpa);    
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAReadWrite.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAReadWrite.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAReadWrite.c	(revision 22158)
@@ -0,0 +1,1218 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+// XXX: Use better name for the temporary FITS file
+// XXX: The code to generate and free the FPA hierarchy was copied from
+// tap-pmFPA.c.  EIther include it directly, or library, or something.
+// Also, get rid of the manual free functions and use psFree() once
+// it correctly frees child members
+// XXX: For the genSimpleFPA() code, add IDs to each function so that
+// the values set in each chip-?cell-?hdu-?image are unique
+
+#define CHIP_ALLOC_NAME		"ChipName"
+#define CELL_ALLOC_NAME		"CellName"
+#define MISC_NUM		32
+#define MISC_NAME		"META00"
+#define MISC_NAME2		"META01"
+#define NUM_BIAS_DATA		10
+#define TEST_NUM_ROWS		4
+#define TEST_NUM_COLS		4
+#define NUM_READOUTS		3
+#define NUM_CELLS		10
+#define NUM_CHIPS		8
+#define NUM_HDUS		5
+#define BASE_IMAGE		10
+#define BASE_MASK		40
+#define BASE_WEIGHT		70
+#define VERBOSE			0
+#define ERR_TRACE_LEVEL		10
+
+psPlaneTransform *PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM()
+{
+    psPlaneTransform *pt = psPlaneTransformAlloc(1, 1);
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+    return(pt);
+}
+
+psPlaneDistort *PS_CREATE_4D_IDENTITY_PLANE_DISTORT()
+{
+    psPlaneDistort *pd = psPlaneDistortAlloc(1, 1, 1, 1);
+    pd->x->coeff[1][0][0][0] = 1.0;
+    pd->y->coeff[0][1][0][0] = 1.0;
+    return(pd);
+}
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    cell->hdu = pmHDUAlloc("cellExtName");
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = psMemDecrRefCounter((psPtr) generateSimpleReadout(cell));
+    }
+
+    // First try to read data from ../dataFiles, then try dataFiles.
+    bool rc = pmConfigFileRead(&cell->hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        rc = pmConfigFileRead(&cell->hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            diag("pmConfigFileRead() was unsuccessful (from generateSimpleCell())");
+	}
+    }
+
+    cell->hdu->images = psArrayAlloc(NUM_HDUS);
+    cell->hdu->masks = psArrayAlloc(NUM_HDUS);
+    cell->hdu->weights = psArrayAlloc(NUM_HDUS);
+    for (int k = 0 ; k < NUM_HDUS ; k++) {
+        cell->hdu->images->data[k]  = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        cell->hdu->masks->data[k]   = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        cell->hdu->weights->data[k] = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(cell->hdu->images->data[k], (float) (BASE_IMAGE+k));
+        psImageInit(cell->hdu->masks->data[k], (psU8) (BASE_MASK+k));
+        psImageInit(cell->hdu->weights->data[k], (float) (BASE_WEIGHT+k));
+    }
+
+    //XXX: Should the region be set some other way?  Like through the various config files?
+    psRegion *region = psRegionAlloc(0.0, 0.0, 0.0, 0.0);
+    // You shouldn't have to remove the key from the metadata.  Find out how to simply change the key value.
+    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC");
+    psMetadataAddPtr(cell->concepts, PS_LIST_TAIL|PS_META_REPLACE, "CELL.TRIMSEC", PS_DATA_REGION, "I am a region", region);
+    psFree(region);
+    return(cell);
+}
+
+/******************************************************************************
+generateSimpleChip(): This function generates a pmChip data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmChip *generateSimpleChip(pmFPA *fpa)
+{
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    chip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    chip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    psMetadataAddS32(chip->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(chip->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    psArrayRealloc(chip->cells, NUM_CELLS);
+    for (int i = 0 ; i < NUM_CELLS ; i++) {
+        chip->cells->data[i] = psMemDecrRefCounter((psPtr) generateSimpleCell(chip));
+    }
+
+    // XXX: Add code to initialize chip pmConcepts
+
+
+    return(chip);
+}
+
+/******************************************************************************
+generateSimpleFPA(): This function generates a pmFPA data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmFPA* generateSimpleFPA(psMetadata *camera)
+{
+    pmFPA* fpa = pmFPAAlloc(camera);
+    fpa->fromTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toSky = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+    psMetadataAddS32(fpa->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    if (camera != NULL) {
+        psMetadataAddS32((psMetadata *) fpa->camera, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    }
+    psMetadataAddS32(fpa->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    psArrayRealloc(fpa->chips, NUM_CHIPS);
+    for (int i = 0 ; i < NUM_CHIPS ; i++) {
+        fpa->chips->data[i] = psMemDecrRefCounter((psPtr) generateSimpleChip(fpa));
+    }
+    pmConceptsBlankFPA(fpa);
+    return(fpa);
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(22);
+
+    // ----------------------------------------------------------------------
+    // ----------------------------------------------------------------------
+    // pmCellWrite(): tests
+    // Verify pmCellWrite() with NULL pmCell arg
+    if (0) {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(".tmp00", "w");
+        ok(!pmCellWrite(NULL, fitsFileW, NULL, false), "pmCellWrite() returned FALSE with NULL pmCell input");
+        psFitsClose(fitsFileW);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmCellWrite() with NULL pmCell arg
+    // XXXX: Big problem: Without the next code, everything else fails.  Why?
+    if (0) {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(".tmp00", "w");
+        ok(!pmCellWrite(NULL, fitsFileW, NULL, false), "pmCellWrite() returned FALSE with NULL pmCell input");
+        psFitsClose(fitsFileW);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmCellWrite() with NULL pmFits arg
+    if (0) {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        ok(!pmCellWrite(cell, NULL, NULL, false), "pmCellWrite() returned FALSE with NULL psFits param");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmCellWrite() with acceptable input params
+    // We first write a FITS file with the pmCellWrite(), then we read it and verify.
+    // First call pmCellWrite()
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(".tmp00", "w");
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(cell != NULL, "Allocated a pmCell successfully");
+
+        //  Use pmCellWrite() to write image data to the FITS file
+        bool rc = pmCellWrite(cell, fitsFileW, NULL, false);
+        ok(rc, "pmCellWrite() returned TRUE");
+
+        //  Close the FITS file, free memory
+        psFitsClose(fitsFileW);
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // ----------------------------------------------------------------------
+    // pmCellRead() tests 
+    // Verify pmCellRead() with NULL pmCell param
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+        ok(!pmCellRead(NULL, fitsFileR, NULL), "pmCellRead() returned FALSE with NULL pmCell param");
+        psFitsClose(fitsFileR);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmCellRead() with NULL pmFits param
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(!pmCellRead(cell, NULL, NULL), "pmCellRead() returned FALSE with NULL pmFits param");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmCellRead() with acceptable data (using the FITS file created above)
+    {
+        psMemId id = psMemGetId();
+        bool rc;
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        // Free the existing cell hdu image data (so we can verify that pmCellRead() actually reads the data
+        psFree(cell->hdu->images);
+        cell->hdu->images = NULL;
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+
+        rc = pmCellRead(cell, fitsFileR, NULL);
+        ok(rc, "pmCellRead() returned TRUE");
+        skip_start(!rc, 1, "Skipping tests because pmCellRead returned NULL");
+        for (int k = 0 ; k < cell->hdu->images->n ; k++) {
+            bool errorFlag = false;
+            psImage *img = cell->hdu->images->data[k];
+            for (int i = 0 ; i < img->numRows ; i++) {
+                for (int j = 0 ; j < img->numCols ; j++) {
+                    if (((float) (BASE_IMAGE+k)) != img->data.F32[i][j]) {
+                        diag("TEST ERROR: img[%d][%d] is %.2f, should be %.2f\n", i, j,
+                              img->data.F32[i][j], ((float) (BASE_IMAGE+k)));
+                        errorFlag = true;
+		    }
+		}
+	    }
+            ok(!errorFlag, "pmCellWrite()/pmCellRead() properly set the image data (image %d)", k);
+        }
+        skip_end();
+        psFitsClose(fitsFileR);
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // ----------------------------------------------------------------------
+    // pmCellWriteWeight(): tests
+    // Verify pmCellWriteWeight() with NULL pmCell arg
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(".tmp00", "w");
+        ok(!pmCellWriteWeight(NULL, fitsFileW, NULL, false), "pmCellWriteWeight() returned FALSE with NULL pmCell input");
+        psFitsClose(fitsFileW);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmCellWriteWeight() with NULL pmFits arg
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        ok(!pmCellWriteWeight(cell, NULL, NULL, false), "pmCellWriteWeight() returned FALSE with NULL psFits param");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmCellWriteWeight() with acceptable input params
+    // We first write a FITS file with the pmCellWriteWeight(), then we read it and verify.
+    // First call pmCellWriteWeight()
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(".tmp00", "w");
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(cell != NULL, "Allocated a pmCell successfully");
+
+        //  Use pmCellWriteWeight() to write weight data to the FITS file
+        bool rc = pmCellWriteWeight(cell, fitsFileW, NULL, false);
+        ok(rc, "pmCellWriteWeight() returned TRUE");
+
+        //  Close the FITS file, free memory
+        psFitsClose(fitsFileW);
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmCellReadWeight() tests 
+    // Verify pmCellReadWeight() with NULL pmCell param
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+        ok(!pmCellReadWeight(NULL, fitsFileR, NULL), "pmCellReadWeight() returned FALSE with NULL pmCell param");
+        psFitsClose(fitsFileR);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmCellReadWeight() with NULL pmFits param
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(!pmCellReadWeight(cell, NULL, NULL), "pmCellReadWeight() returned FALSE with NULL pmFits param");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmCellReadWeight() with acceptable data (using the FITS file created above)
+    {
+        psMemId id = psMemGetId();
+        bool rc;
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        // Free the existing cell hdu weight data (so we can verify that pmCellReadWeight() actually reads the data
+        psFree(cell->hdu->weights);
+        cell->hdu->weights = NULL;
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+
+        rc = pmCellReadWeight(cell, fitsFileR, NULL);
+        ok(rc, "pmCellReadWeight() returned TRUE");
+        for (int k = 0 ; k < cell->hdu->weights->n ; k++) {
+            bool errorFlag = false;
+            psImage *msk = cell->hdu->weights->data[k];
+            for (int i = 0 ; i < msk->numRows ; i++) {
+                for (int j = 0 ; j < msk->numCols ; j++) {
+                    if (((float) (BASE_WEIGHT+k)) != msk->data.F32[i][j]) {
+                        diag("TEST ERROR: msk[%d][%d] is %.2f, should be %.2f\n", i, j,
+                              msk->data.F32[i][j], ((float) (BASE_WEIGHT+k)));
+                        errorFlag = true;
+		    }
+		}
+	    }
+            ok(!errorFlag, "pmCellWriteWeight()/pmCellReadWeight() properly set the weight data (image %d)", k);
+        }
+        psFitsClose(fitsFileR);
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // ----------------------------------------------------------------------
+    // ----------------------------------------------------------------------
+    // pmCellWriteMask(): tests
+    // Verify pmCellWriteMask() with NULL pmCell arg
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(".tmp00", "w");
+        ok(!pmCellWriteMask(NULL, fitsFileW, NULL, false), "pmCellWriteMask() returned FALSE with NULL pmCell input");
+        psFitsClose(fitsFileW);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmCellWriteMask() with NULL pmFits arg
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        ok(!pmCellWriteMask(cell, NULL, NULL, false), "pmCellWriteMask() returned FALSE with NULL psFits param");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmCellWriteMask() with acceptable input params
+    // We first write a FITS file with the pmCellWriteMask(), then we read it and verify.
+    // First call pmCellWriteMask()
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(".tmp00", "w");
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(cell != NULL, "Allocated a pmCell successfully");
+
+        //  Use pmCellWriteMask() to write mask data to the FITS file
+        bool rc = pmCellWriteMask(cell, fitsFileW, NULL, false);
+        ok(rc, "pmCellWriteMask() returned TRUE");
+
+        //  Close the FITS file, free memory
+        psFitsClose(fitsFileW);
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmCellReadMask() tests 
+    // Verify pmCellReadMask() with NULL pmCell param
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+        ok(!pmCellReadMask(NULL, fitsFileR, NULL), "pmCellReadMask() returned FALSE with NULL pmCell param");
+        psFitsClose(fitsFileR);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmCellReadMask() with NULL pmFits param
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(!pmCellReadMask(cell, NULL, NULL), "pmCellReadMask() returned FALSE with NULL pmFits param");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmCellReadMask() with acceptable data (using the FITS file created above)
+    {
+        psMemId id = psMemGetId();
+        bool rc;
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        // Free the existing cell hdu mask data (so we can verify that pmCellReadMask() actually reads the data
+        psFree(cell->hdu->masks);
+        cell->hdu->masks = NULL;
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+
+        rc = pmCellReadMask(cell, fitsFileR, NULL);
+        ok(rc, "pmCellReadMask() returned TRUE");
+        for (int k = 0 ; k < cell->hdu->masks->n ; k++) {
+            bool errorFlag = false;
+            psImage *msk = cell->hdu->masks->data[k];
+            for (int i = 0 ; i < msk->numRows ; i++) {
+                for (int j = 0 ; j < msk->numCols ; j++) {
+                    if (0) {
+                        if (((float) (BASE_WEIGHT+k)) != msk->data.F32[i][j]) {
+                            diag("TEST ERROR: msk[%d][%d] is %.2f, should be %.2f\n", i, j,
+                                  msk->data.F32[i][j], ((float) (BASE_WEIGHT+k)));
+                            errorFlag = true;
+                        }
+		    }
+                    if (1) {
+                        if (((BASE_MASK+k)) != msk->data.U8[i][j]) {
+                            diag("TEST ERROR: msk[%d][%d] is %.2f, should be %.2f\n", i, j,
+                                  msk->data.F32[i][j], ((float) (BASE_MASK+k)));
+                            errorFlag = true;
+                        }
+		    }
+    		}
+	    }
+            ok(!errorFlag, "pmCellWriteMask()/pmCellReadMask() properly set the mask data (image %d)", k);
+        }
+        psFitsClose(fitsFileR);
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // ----------------------------------------------------------------------
+    // ----------------------------------------------------------------------
+    // pmChipWrite() tests
+    // Verify pmChipWrite() with NULL pmChip param
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(".tmp01", "w");
+        ok(!pmChipWrite(NULL, fitsFileW, NULL, false, true), "pmChipWrite() returned NULL with NULL pmChip param");
+        psFitsClose(fitsFileW);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmChipWrite() with NULL pmFits param
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(!pmChipWrite(chip, NULL, NULL, false, true), "pmChipWrite() returned NULL with NULL pmFits param");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmChipWrite() with acceptable data
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(".tmp01", "w");
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        ok(chip != NULL, "Allocated a pmChip successfully");
+
+        //  Use pmChipWrite() to write image data to the FITS file
+        bool rc = pmChipWrite(chip, fitsFileW, NULL, false, true);
+        ok(rc, "pmChipWrite() returned TRUE");
+
+        //  Close the FITS file, free memory
+        psFitsClose(fitsFileW);
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmChipRead() tests
+    // Verify pmChipRead() with NULL pmChip param
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+        ok(!pmChipRead(NULL, fitsFileR, NULL), "pmChipRead() returned NULL with NULL pmChip param");
+        psFitsClose(fitsFileR);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmChipRead() with NULL pmFits param
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        ok(!pmChipRead(chip, NULL, NULL), "pmChipRead() returned NULL with NULL pmFits param");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmChipRead() with acceptable input data
+    {
+        psMemId id = psMemGetId();
+        bool rc;
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        // Free the cells for chip 0 so we can verify that pmChipRead() actually reads the data from file
+        for (int chipID = 0 ; chipID < chip->cells->n ; chipID++) {
+            pmCell *cell = (pmCell *) chip->cells->data[chipID];
+            psFree(cell);
+            cell = NULL;
+	}
+
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+        rc = pmChipRead(chip, fitsFileR, NULL);
+        ok(rc, "pmChipRead() returned TRUE");
+        bool errorFlag = false;
+        // XXX: chipID should be cellID
+        for (int chipID = 0 ; chipID < chip->cells->n ; chipID++) {
+            if (VERBOSE) diag("Reading cell %d\n", chipID);
+            pmCell *cell = (pmCell *) chip->cells->data[chipID];
+            for (int k = 0 ; k < cell->hdu->images->n ; k++) {
+                if (VERBOSE) diag("NOTE: image %d\n", k);
+                psImage *img = cell->hdu->images->data[k];
+                for (int i = 0 ; i < img->numRows ; i++) {
+                    for (int j = 0 ; j < img->numCols ; j++) {
+                        if (((float) (BASE_IMAGE+k)) != img->data.F32[i][j]) {
+                            diag("TEST ERROR: img[%d][%d] is %.2f, should be %.2f\n", i, j,
+                                  img->data.F32[i][j], ((float) (BASE_IMAGE+k)));
+                            errorFlag = true;
+			}
+		    }
+		}
+	    }
+            ok(!errorFlag, "pmChipWrite()/pmChipRead() properly set the image data (cell %d)", chipID);
+	}
+
+        psFitsClose(fitsFileR);
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmChipWriteWeight() tests
+    // Verify pmChipWriteWeight() with NULL pmChip param
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(".tmp01", "w");
+        ok(!pmChipWriteWeight(NULL, fitsFileW, NULL, false, true), "pmChipWriteWeight() returned NULL with NULL pmChip param");
+        psFitsClose(fitsFileW);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmChipWriteWeight() with NULL pmFits param
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(!pmChipWriteWeight(chip, NULL, NULL, false, true), "pmChipWriteWeight() returned NULL with NULL pmFits param");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmChipWriteWeight() with acceptable data
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(".tmp01", "w");
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        ok(chip != NULL, "Allocated a pmChip successfully");
+
+        //  Use pmChipWriteWeight() to write image data to the FITS file
+        bool rc = pmChipWriteWeight(chip, fitsFileW, NULL, false, true);
+        ok(rc, "pmChipWriteWeight() returned TRUE");
+
+        //  Close the FITS file, free memory
+        psFitsClose(fitsFileW);
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmChipReadMask() tests
+    // Verify pmChipReadMask() with NULL pmChip param
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+        ok(!pmChipReadMask(NULL, fitsFileR, NULL), "pmChipReadMask() returned NULL with NULL pmChip param");
+        psFitsClose(fitsFileR);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmChipReadMask() with NULL pmFits param
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        ok(!pmChipReadMask(chip, NULL, NULL), "pmChipReadMask() returned NULL with NULL pmFits param");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmChipReadMask() with acceptable input data
+    {
+        psMemId id = psMemGetId();
+        bool rc;
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        // Free the cells for chip 0 so we can verify that pmChipReadMask() actually reads the data from file
+        for (int chipID = 0 ; chipID < chip->cells->n ; chipID++) {
+            pmCell *cell = (pmCell *) chip->cells->data[chipID];
+            psFree(cell);
+            cell = NULL;
+	}
+
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+        rc = pmChipReadMask(chip, fitsFileR, NULL);
+        ok(rc, "pmChipReadMask() returned TRUE");
+        bool errorFlag = false;
+        // XXX: chipID should be cellID
+        for (int chipID = 0 ; chipID < chip->cells->n ; chipID++) {
+            if (VERBOSE) diag("Reading cell %d\n", chipID);
+            pmCell *cell = (pmCell *) chip->cells->data[chipID];
+            for (int k = 0 ; k < cell->hdu->weights->n ; k++) {
+                if (VERBOSE) diag("NOTE: image %d\n", k);
+                psImage *wgt = cell->hdu->weights->data[k];
+                for (int i = 0 ; i < wgt->numRows ; i++) {
+                    for (int j = 0 ; j < wgt->numCols ; j++) {
+                        if (((float) (BASE_WEIGHT+k)) != wgt->data.F32[i][j]) {
+                            diag("TEST ERROR: wgt[%d][%d] is %.2f, should be %.2f\n", i, j,
+                                  wgt->data.F32[i][j], ((float) (BASE_WEIGHT+k)));
+                            errorFlag = true;
+			}
+		    }
+		}
+	    }
+            ok(!errorFlag, "pmChipWriteWeight()/pmChipReadWeight() properly set the weight data (cell %d)", chipID);
+	}
+
+        psFitsClose(fitsFileR);
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmChipReadMask() tests
+    // Verify pmChipReadMask() with NULL pmChip param
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+        ok(!pmChipReadMask(NULL, fitsFileR, NULL), "pmChipReadMask() returned NULL with NULL pmChip param");
+        psFitsClose(fitsFileR);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmChipReadMask() with NULL pmFits param
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        ok(!pmChipReadMask(chip, NULL, NULL), "pmChipReadMask() returned NULL with NULL pmFits param");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmChipReadMask() with acceptable input data
+    {
+        psMemId id = psMemGetId();
+        bool rc;
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        // Free the cells for chip 0 so we can verify that pmChipReadMask() actually reads the data from file
+        for (int chipID = 0 ; chipID < chip->cells->n ; chipID++) {
+            pmCell *cell = (pmCell *) chip->cells->data[chipID];
+            psFree(cell);
+            cell = NULL;
+	}
+
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+        rc = pmChipReadMask(chip, fitsFileR, NULL);
+        ok(rc, "pmChipReadMask() returned TRUE");
+        bool errorFlag = false;
+        // XXX: chipID should be cellID
+        for (int chipID = 0 ; chipID < chip->cells->n ; chipID++) {
+            if (VERBOSE) diag("Reading cell %d\n", chipID);
+            pmCell *cell = (pmCell *) chip->cells->data[chipID];
+            for (int k = 0 ; k < cell->hdu->masks->n ; k++) {
+                if (VERBOSE) diag("NOTE: image %d\n", k);
+                psImage *msk = cell->hdu->masks->data[k];
+                for (int i = 0 ; i < msk->numRows ; i++) {
+                    for (int j = 0 ; j < msk->numCols ; j++) {
+                        if (((BASE_MASK+k)) != msk->data.U8[i][j]) {
+                            diag("TEST ERROR: msk[%d][%d] is %.2f, should be %.2f\n", i, j,
+                                  msk->data.F32[i][j], ((float) (BASE_MASK+k)));
+                            errorFlag = true;
+			}
+		    }
+		}
+	    }
+            ok(!errorFlag, "pmChipWriteMask()/pmChipReadMask() properly set the mask data (cell %d)", chipID);
+	}
+
+        psFitsClose(fitsFileR);
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // ----------------------------------------------------------------------
+    // pmFPAWrite() tests
+    // pmFPAWrite(pmFPA *fpa, psFits *fits, psDB *db, bool blank, bool recurse)
+    // Verify pmFPAWrite() with NULL pmFPA param
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(".tmp01", "w");
+        ok(!pmFPAWrite(NULL, fitsFileW, NULL, false, true), "pmFPAWrite() returned NULL with NULL pmFPA param");
+        psFitsClose(fitsFileW);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmFPAWrite() with NULL pmFits param
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(!pmFPAWrite(fpa, NULL, NULL, false, true), "pmFPAWrite() returned NULL with NULL pmFits param");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmFPAWrite() with acceptable data
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(".tmp01", "w");
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        bool rc = pmFPAWrite(fpa, fitsFileW, NULL, false, true);
+        ok(rc, "pmFPAWrite() returned TRUE");
+        //  Close the FITS file, free memory
+        psFitsClose(fitsFileW);
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmFPARead() tests
+    // Verify pmFPARead() with NULL pmFPA param
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+        ok(!pmFPARead(NULL, fitsFileR, NULL), "pmFPARead() returned NULL with NULL pmFPA param");
+        psFitsClose(fitsFileR);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmFPARead() with NULL pmFits param
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        ok(!pmFPARead(fpa, NULL, NULL), "pmFPARead() returned NULL with NULL pmFits param");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmFPARead() with acceptable input data
+    {
+        psMemId id = psMemGetId();
+        bool rc;
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        // Free the cells for chip 0 so we can verify that pmFPARead() actually reads the data from file
+        if (0) {
+            for (int chipID = 0 ; chipID < chip->cells->n ; chipID++) {
+                pmCell *cell = (pmCell *) chip->cells->data[chipID];
+                psFree(cell);
+                cell = NULL;
+            }
+	}
+
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+        rc = pmFPARead(fpa, fitsFileR, NULL);
+        ok(rc, "pmFPARead() returned TRUE");
+        bool errorFlag = false;
+        // XXX: fpaID should be chipID
+        // XXX: chipID should be cellID
+        for (int fpaID = 0 ; fpaID < fpa->chips->n ; fpaID++) {
+            pmChip *chip = fpa->chips->data[fpaID];
+            for (int chipID = 0 ; chipID < chip->cells->n ; chipID++) {
+                if (VERBOSE) diag("Reading cell %d\n", chipID);
+                pmCell *cell = (pmCell *) chip->cells->data[chipID];
+                for (int k = 0 ; k < cell->hdu->images->n ; k++) {
+                    if (VERBOSE) diag("NOTE: image %d\n", k);
+                    psImage *img = cell->hdu->images->data[k];
+                    for (int i = 0 ; i < img->numRows ; i++) {
+                        for (int j = 0 ; j < img->numCols ; j++) {
+                            if (((float) (BASE_IMAGE+k)) != img->data.F32[i][j]) {
+                                diag("TEST ERROR: img[%d][%d] is %.2f, should be %.2f\n", i, j,
+                                      img->data.F32[i][j], ((float) (BASE_IMAGE+k)));
+                                errorFlag = true;
+        			}
+        		    }
+        		}
+        	    }
+                ok(!errorFlag, "pmFPAWrite()/pmFPARead() properly set the image data (chip %d, cell %d)", fpaID, chipID);
+    	    }
+	}
+
+        psFitsClose(fitsFileR);
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // ----------------------------------------------------------------------
+    // pmFPAWriteWeight() tests
+    // pmFPAWriteWeight(pmFPA *fpa, psFits *fits, psDB *db, bool blank, bool recurse)
+    // Verify pmFPAWriteWeight() with NULL pmFPA param
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(".tmp01", "w");
+        ok(!pmFPAWriteWeight(NULL, fitsFileW, NULL, false, true), "pmFPAWriteWeight() returned NULL with NULL pmFPA param");
+        psFitsClose(fitsFileW);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmFPAWriteWeight() with NULL pmFits param
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(!pmFPAWriteWeight(fpa, NULL, NULL, false, true), "pmFPAWriteWeight() returned NULL with NULL pmFits param");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmFPAWriteWeight() with acceptable data
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(".tmp01", "w");
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        bool rc = pmFPAWriteWeight(fpa, fitsFileW, NULL, false, true);
+        ok(rc, "pmFPAWriteWeight() returned TRUE");
+        //  Close the FITS file, free memory
+        psFitsClose(fitsFileW);
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmFPAReadWeight() tests
+    // Verify pmFPAReadWeight() with NULL pmFPA param
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+        ok(!pmFPARead(NULL, fitsFileR, NULL), "pmFPAReadWeight() returned NULL with NULL pmFPA param");
+        psFitsClose(fitsFileR);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmFPAReadWeight() with NULL pmFits param
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        ok(!pmFPARead(fpa, NULL, NULL), "pmFPAReadWeight() returned NULL with NULL pmFits param");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmFPAReadWeight() with acceptable input data
+    {
+        psMemId id = psMemGetId();
+        bool rc;
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        // Free the cells for chip 0 so we can verify that pmFPAReadWeight() actually reads the data from file
+        if (0) {
+            for (int chipID = 0 ; chipID < chip->cells->n ; chipID++) {
+                pmCell *cell = (pmCell *) chip->cells->data[chipID];
+                psFree(cell);
+                cell = NULL;
+            }
+	}
+
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+        rc = pmFPARead(fpa, fitsFileR, NULL);
+        ok(rc, "pmFPAReadWeight() returned TRUE");
+        bool errorFlag = false;
+        // XXX: fpaID should be chipID
+        // XXX: chipID should be cellID
+        for (int fpaID = 0 ; fpaID < fpa->chips->n ; fpaID++) {
+            pmChip *chip = fpa->chips->data[fpaID];
+            for (int chipID = 0 ; chipID < chip->cells->n ; chipID++) {
+                if (VERBOSE) diag("Reading cell %d\n", chipID);
+                pmCell *cell = (pmCell *) chip->cells->data[chipID];
+                for (int k = 0 ; k < cell->hdu->weights->n ; k++) {
+                    if (VERBOSE) diag("NOTE: image %d\n", k);
+                    psImage *wgt = cell->hdu->weights->data[k];
+                    for (int i = 0 ; i < wgt->numRows ; i++) {
+                        for (int j = 0 ; j < wgt->numCols ; j++) {
+                            if (((float) (BASE_WEIGHT+k)) != wgt->data.F32[i][j]) {
+                                diag("TEST ERROR: wgt[%d][%d] is %.2f, should be %.2f\n", i, j,
+                                      wgt->data.F32[i][j], ((float) (BASE_WEIGHT+k)));
+                                errorFlag = true;
+        			}
+        		    }
+        		}
+        	    }
+                ok(!errorFlag, "pmFPAWriteWeight()/pmFPAReadWeight() properly set the image data (chip %d, cell %d)", fpaID, chipID);
+    	    }
+	}
+
+        psFitsClose(fitsFileR);
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // ----------------------------------------------------------------------
+    // pmFPAWriteMask() tests
+    // pmFPAWriteMask(pmFPA *fpa, psFits *fits, psDB *db, bool blank, bool recurse)
+    // Verify pmFPAWriteMask() with NULL pmFPA param
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(".tmp01", "w");
+        ok(!pmFPAWriteMask(NULL, fitsFileW, NULL, false, true), "pmFPAWriteMask() returned NULL with NULL pmFPA param");
+        psFitsClose(fitsFileW);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmFPAWriteMask() with NULL pmFits param
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(!pmFPAWriteMask(fpa, NULL, NULL, false, true), "pmFPAWriteMask() returned NULL with NULL pmFits param");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmFPAWriteMask() with acceptable data
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(".tmp01", "w");
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        bool rc = pmFPAWriteMask(fpa, fitsFileW, NULL, false, true);
+        ok(rc, "pmFPAWriteMask() returned TRUE");
+        //  Close the FITS file, free memory
+        psFitsClose(fitsFileW);
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmFPAReadMask() tests
+    // Verify pmFPAReadMask() with NULL pmFPA param
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+        ok(!pmFPARead(NULL, fitsFileR, NULL), "pmFPAReadMask() returned NULL with NULL pmFPA param");
+        psFitsClose(fitsFileR);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmFPAReadMask() with NULL pmFits param
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        ok(!pmFPARead(fpa, NULL, NULL), "pmFPAReadMask() returned NULL with NULL pmFits param");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Verify pmFPAReadMask() with acceptable input data
+    {
+        psMemId id = psMemGetId();
+        bool rc;
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        // Free the cells for chip 0 so we can verify that pmFPAReadMask() actually reads the data from file
+        if (0) {
+            for (int chipID = 0 ; chipID < chip->cells->n ; chipID++) {
+                pmCell *cell = (pmCell *) chip->cells->data[chipID];
+                psFree(cell);
+                cell = NULL;
+            }
+	}
+
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+        rc = pmFPARead(fpa, fitsFileR, NULL);
+        ok(rc, "pmFPAReadMask() returned TRUE");
+        bool errorFlag = false;
+        // XXX: fpaID should be chipID
+        // XXX: chipID should be cellID
+        for (int fpaID = 0 ; fpaID < fpa->chips->n ; fpaID++) {
+            pmChip *chip = fpa->chips->data[fpaID];
+            for (int chipID = 0 ; chipID < chip->cells->n ; chipID++) {
+                if (VERBOSE) diag("Reading cell %d\n", chipID);
+                pmCell *cell = (pmCell *) chip->cells->data[chipID];
+                for (int k = 0 ; k < cell->hdu->masks->n ; k++) {
+                    if (VERBOSE) diag("NOTE: image %d\n", k);
+                    psImage *msk = cell->hdu->masks->data[k];
+                    for (int i = 0 ; i < msk->numRows ; i++) {
+                        for (int j = 0 ; j < msk->numCols ; j++) {
+                            if (((BASE_MASK+k)) != msk->data.U8[i][j]) {
+                                diag("TEST ERROR: msk[%d][%d] is %.2f, should be %.2f\n", i, j,
+                                      msk->data.F32[i][j], ((float) (BASE_MASK+k)));
+                                errorFlag = true;
+        			}
+        		    }
+        		}
+        	    }
+                ok(!errorFlag, "pmFPAWriteMask()/pmFPAReadMask() properly set the image data (chip %d, cell %d)", fpaID, chipID);
+    	    }
+	}
+
+        psFitsClose(fitsFileR);
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAUtils.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAUtils.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAUtils.c	(revision 22158)
@@ -0,0 +1,295 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    All functions are tested.
+*/
+
+#define CHIP_ALLOC_NAME        "ChipName"
+#define CELL_ALLOC_NAME        "CellName"
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define MISC_NAME2             "META01"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           4
+#define TEST_NUM_COLS           4
+#define NUM_READOUTS            3
+#define NUM_CELLS               10
+#define NUM_CHIPS               8
+#define NUM_HDUS                5
+#define BASE_IMAGE              10
+#define BASE_MASK               40
+#define BASE_WEIGHT             70
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+psPlaneTransform *PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM()
+{
+    psPlaneTransform *pt = psPlaneTransformAlloc(1, 1);
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+    return(pt);
+}
+
+psPlaneDistort *PS_CREATE_4D_IDENTITY_PLANE_DISTORT()
+{
+    psPlaneDistort *pd = psPlaneDistortAlloc(1, 1, 1, 1);
+    pd->x->coeff[1][0][0][0] = 1.0;
+    pd->y->coeff[0][1][0][0] = 1.0;
+    return(pd);
+}
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    cell->hdu = pmHDUAlloc("cellExtName");
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = psMemDecrRefCounter((psPtr) generateSimpleReadout(cell));
+    }
+
+    // First try to read data from ../dataFiles, then try dataFiles.
+    bool rc = pmConfigFileRead(&cell->hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        rc = pmConfigFileRead(&cell->hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            diag("pmConfigFileRead() was unsuccessful (from generateSimpleCell())");
+	}
+    }
+
+    cell->hdu->images = psArrayAlloc(NUM_HDUS);
+    cell->hdu->masks = psArrayAlloc(NUM_HDUS);
+    cell->hdu->weights = psArrayAlloc(NUM_HDUS);
+    for (int k = 0 ; k < NUM_HDUS ; k++) {
+        cell->hdu->images->data[k]  = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        cell->hdu->masks->data[k]   = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        cell->hdu->weights->data[k] = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(cell->hdu->images->data[k], (float) (BASE_IMAGE+k));
+        psImageInit(cell->hdu->masks->data[k], (psU8) (BASE_MASK+k));
+        psImageInit(cell->hdu->weights->data[k], (float) (BASE_WEIGHT+k));
+    }
+
+    //XXX: Should the region be set some other way?  Like through the various config files?
+    psRegion *region = psRegionAlloc(0.0, 0.0, 0.0, 0.0);
+    // You shouldn't have to remove the key from the metadata.
+    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC");
+    psMetadataAddPtr(cell->concepts, PS_LIST_TAIL|PS_META_REPLACE, "CELL.TRIMSEC", PS_DATA_REGION, "I am a region", region);
+    psFree(region);
+    return(cell);
+}
+
+/******************************************************************************
+generateSimpleChip(): This function generates a pmChip data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmChip *generateSimpleChip(pmFPA *fpa)
+{
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    chip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    chip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    psMetadataAddS32(chip->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(chip->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    psArrayRealloc(chip->cells, NUM_CELLS);
+    for (int i = 0 ; i < NUM_CELLS ; i++) {
+        chip->cells->data[i] = psMemDecrRefCounter((psPtr) generateSimpleCell(chip));
+    }
+    return(chip);
+}
+
+/******************************************************************************
+generateSimpleFPA(): This function generates a pmFPA data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmFPA* generateSimpleFPA(psMetadata *camera)
+{
+    pmFPA* fpa = pmFPAAlloc(camera);
+    fpa->fromTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toSky = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+    psMetadataAddS32(fpa->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    if (camera != NULL) {
+        psMetadataAddS32((psMetadata *) fpa->camera, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    }
+    psMetadataAddS32(fpa->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    psArrayRealloc(fpa->chips, NUM_CHIPS);
+    for (int i = 0 ; i < NUM_CHIPS ; i++) {
+        fpa->chips->data[i] = psMemDecrRefCounter((psPtr) generateSimpleChip(fpa));
+    }
+    pmConceptsBlankFPA(fpa);
+    return(fpa);
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(40);
+
+
+    // ----------------------------------------------------------------------
+    // pmFPAFindChip() tests
+    // Call pmFPAFindChip() with NULL pmFPA input parameter
+    {
+        psMemId id = psMemGetId();
+        int rc = pmFPAFindChip(NULL, "chip-0");
+        ok(-1 == rc, "pmFPAFindChip() returns -1 with NULL pmFPA input parameter");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmFPAFindChip() with bogus chip name
+    {
+        psMemId id = psMemGetId();
+        pmFPA* fpa = generateSimpleFPA(NULL);
+        int rc = pmFPAFindChip(fpa, "bogus");
+        ok(-1 == rc, "pmFPAFindChip() returns -1 with bogus chip name");
+        psFree(fpa);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmFPAFindChip() with NULL chip name
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        pmFPA* fpa = generateSimpleFPA(NULL);
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        int rc = pmFPAFindChip(fpa, NULL);
+        ok(-1 == rc, "pmFPAFindChip() returns -1 with NULL name input param");
+        psFree(fpa);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmFPAFindChip() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        pmFPA* fpa = generateSimpleFPA(NULL);
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        // Set unique chip names
+        for (int chipID = 0 ; chipID < fpa->chips->n ; chipID++) {
+            pmChip *chip = fpa->chips->data[chipID];
+            char tmpName[100];
+            sprintf(tmpName, "chip-%d", chipID);
+            psMetadataAddStr(chip->concepts, PS_LIST_TAIL, "CHIP.NAME", PS_META_REPLACE, NULL, tmpName);
+	}
+
+        // Verify that pmFPAFindChip() finds those chips correctly
+        for (int chipID = 0 ; chipID < fpa->chips->n ; chipID++) {
+            char tmpName[100];
+            sprintf(tmpName, "chip-%d", chipID);
+            int rc = pmFPAFindChip(fpa, tmpName);
+            ok(rc == chipID, "pmFPAFindChip() correctly found chip %s (%d)", tmpName, rc);
+	}
+
+        psFree(fpa);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // ----------------------------------------------------------------------
+    // pmChipFindCell() tests
+    // Call pmChipFindCell() with bogus cell name
+    {
+        psMemId id = psMemGetId();
+        int rc = pmChipFindCell(NULL, "cell-0");
+        ok(-1 == rc, "pmChipFindCell() returns -1 with NULL pmChip input param");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Call pmChipFindCell() with bogus cell name
+    {
+        psMemId id = psMemGetId();
+        pmFPA* fpa = generateSimpleFPA(NULL);
+        pmChip *chip = fpa->chips->data[0];
+        int rc = pmChipFindCell(chip, "bogus");
+        ok(-1 == rc, "pmChipFindCell() returns -1 with bogus cell name");
+        psFree(fpa);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmChipFindCell() with NULL cell name
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmChip heirarchy
+        pmFPA* fpa = generateSimpleFPA(NULL);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        int rc = pmChipFindCell(chip, NULL);
+        ok(-1 == rc, "pmChipFindCell() returns -1 with NULL name input param");
+        psFree(fpa);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmChipFindCell() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmChip heirarchy
+        pmFPA* fpa = generateSimpleFPA(NULL);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        // Set unique cell names
+        for (int cellID = 0 ; cellID < chip->cells->n ; cellID++) {
+            pmCell *cell = chip->cells->data[cellID];
+            char tmpName[100];
+            sprintf(tmpName, "cell-%d", cellID);
+            psMetadataAddStr(cell->concepts, PS_LIST_TAIL, "CELL.NAME", PS_META_REPLACE, NULL, tmpName);
+	}
+
+        // Verify that pmChipFindCell() finds those cells correctly
+        for (int cellID = 0 ; cellID < chip->cells->n ; cellID++) {
+            char tmpName[100];
+            sprintf(tmpName, "cell-%d", cellID);
+            int rc = pmChipFindCell(chip, tmpName);
+            ok(rc == cellID, "pmChipFindCell() correctly found cell %s (%d)", tmpName, rc);
+	}
+
+        psFree(fpa);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAView.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAView.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmFPAView.c	(revision 22158)
@@ -0,0 +1,1023 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    All functions are tested.
+*/
+
+#define CHIP_ALLOC_NAME        "ChipName"
+#define CELL_ALLOC_NAME        "CellName"
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define MISC_NAME2             "META01"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           4
+#define TEST_NUM_COLS           4
+#define NUM_READOUTS            3
+#define NUM_CELLS               10
+#define NUM_CHIPS               8
+#define NUM_HDUS                5
+#define BASE_IMAGE              10
+#define BASE_MASK               40
+#define BASE_WEIGHT             70
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+psPlaneTransform *PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM()
+{
+    psPlaneTransform *pt = psPlaneTransformAlloc(1, 1);
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+    return(pt);
+}
+
+psPlaneDistort *PS_CREATE_4D_IDENTITY_PLANE_DISTORT()
+{
+    psPlaneDistort *pd = psPlaneDistortAlloc(1, 1, 1, 1);
+    pd->x->coeff[1][0][0][0] = 1.0;
+    pd->y->coeff[0][1][0][0] = 1.0;
+    return(pd);
+}
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    cell->hdu = pmHDUAlloc("cellExtName");
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = psMemDecrRefCounter((psPtr) generateSimpleReadout(cell));
+    }
+
+    // First try to read data from ../dataFiles, then try dataFiles.
+    bool rc = pmConfigFileRead(&cell->hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        rc = pmConfigFileRead(&cell->hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            diag("pmConfigFileRead() was unsuccessful (from generateSimpleCell())");
+	}
+    }
+
+    cell->hdu->images = psArrayAlloc(NUM_HDUS);
+    cell->hdu->masks = psArrayAlloc(NUM_HDUS);
+    cell->hdu->weights = psArrayAlloc(NUM_HDUS);
+    for (int k = 0 ; k < NUM_HDUS ; k++) {
+        cell->hdu->images->data[k]  = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        cell->hdu->masks->data[k]   = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        cell->hdu->weights->data[k] = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(cell->hdu->images->data[k], (float) (BASE_IMAGE+k));
+        psImageInit(cell->hdu->masks->data[k], (psU8) (BASE_MASK+k));
+        psImageInit(cell->hdu->weights->data[k], (float) (BASE_WEIGHT+k));
+    }
+    cell->hdu->blankPHU = true;
+
+    //XXX: Should the region be set some other way?  Like through the various config files?
+    psRegion *region = psRegionAlloc(0.0, 0.0, 0.0, 0.0);
+    // You shouldn't have to remove the key from the metadata.  Find out how to simply change the key value.
+    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC");
+    psMetadataAddPtr(cell->concepts, PS_LIST_TAIL|PS_META_REPLACE, "CELL.TRIMSEC", PS_DATA_REGION, "I am a region", region);
+    psFree(region);
+    return(cell);
+}
+
+/******************************************************************************
+generateSimpleChip(): This function generates a pmChip data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmChip *generateSimpleChip(pmFPA *fpa)
+{
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    chip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    chip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    psMetadataAddS32(chip->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(chip->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    chip->hdu = pmHDUAlloc("chipExtName");
+    bool rc = pmConfigFileRead(&chip->hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        rc = pmConfigFileRead(&chip->hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            diag("pmConfigFileRead() was unsuccessful (from generateSimpleChip())");
+        }
+    }
+    chip->hdu->blankPHU = true;
+
+    psArrayRealloc(chip->cells, NUM_CELLS);
+    for (int i = 0 ; i < NUM_CELLS ; i++) {
+        chip->cells->data[i] = psMemDecrRefCounter((psPtr) generateSimpleCell(chip));
+    }
+
+    return(chip);
+}
+
+/******************************************************************************
+generateSimpleFPA(): This function generates a pmFPA data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmFPA* generateSimpleFPA(psMetadata *camera)
+{
+    pmFPA* fpa = pmFPAAlloc(camera);
+    fpa->fromTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toSky = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+    psMetadataAddS32(fpa->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    if (camera != NULL) {
+        psMetadataAddS32((psMetadata *) fpa->camera, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    }
+    psMetadataAddS32(fpa->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    fpa->hdu = pmHDUAlloc("fpaExtName");
+    bool rc = pmConfigFileRead(&fpa->hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        rc = pmConfigFileRead(&fpa->hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            diag("pmConfigFileRead() was unsuccessful (from generateSimpleFPA())");
+        }
+    }
+    fpa->hdu->blankPHU = true;
+
+    psArrayRealloc(fpa->chips, NUM_CHIPS);
+    for (int i = 0 ; i < NUM_CHIPS ; i++) {
+        fpa->chips->data[i] = psMemDecrRefCounter((psPtr) generateSimpleChip(fpa));
+    }
+    pmConceptsBlankFPA(fpa);
+    return(fpa);
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(174);
+
+
+    // ----------------------------------------------------------------------
+    // pmFPAViewAlloc() tests
+    {
+        psMemId id = psMemGetId();
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+        ok(tmpView != NULL && psMemCheckFPAview(tmpView), "pmFPAviewAlloc() returned non-NULL");
+        ok(tmpView->nRows == 32, "pmFPAviewAlloc() set ->nRows properly");
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmFPAViewReset() tests: NULL input
+    {
+        psMemId id = psMemGetId();
+        ok(!pmFPAviewReset(NULL), "pmFPAviewReset() returned FALSE with NULL input");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAViewReset() tests: acceptable input
+    {
+        psMemId id = psMemGetId();
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+        ok(tmpView != NULL, "pmFPAviewAlloc() returned non-NULL");
+        tmpView->chip = 16;
+        tmpView->cell = 16;
+        tmpView->readout = 16;
+        tmpView->iRows = 16;
+        ok(pmFPAviewReset(tmpView), "pmFPAviewReset() returned TRUE");
+        ok(tmpView->chip == -1, "pmFPAviewReset() set tmpView->chip to -1");
+        ok(tmpView->cell == -1, "pmFPAviewReset() set tmpView->cell to -1");
+        ok(tmpView->readout == -1, "pmFPAviewReset() set tmpView->readout to 0");
+        ok(tmpView->iRows == 0, "pmFPAviewReset() set tmpView->iRows to 0");
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmFPAViewForLevel() tests: NULL input
+    // pmFPAview *pmFPAviewForLevel(pmFPALevel level, const pmFPAview *input)
+
+    {
+        psMemId id = psMemGetId();
+        ok(!pmFPAviewForLevel(PM_FPA_LEVEL_FPA, NULL), "pmFPAviewForLevel() returned FALSE with NULL input");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAViewForLevel() tests: acceptable input
+    {
+        psMemId id = psMemGetId();
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+        ok(tmpView != NULL, "pmFPAviewAlloc() returned non-NULL");
+        tmpView->chip = 16;
+        tmpView->cell = 16;
+        tmpView->readout = 16;
+        tmpView->iRows = 16;
+
+        pmFPAview *newView = pmFPAviewForLevel(PM_FPA_LEVEL_FPA, tmpView);
+        ok(newView, "pmFPAviewReset(PM_FPA_LEVEL_FPA) returned non-NULL");
+        ok(newView->chip == -1, "pmFPAviewReset() set tmpView->chip to -1");
+        psFree(newView);
+
+        newView = pmFPAviewForLevel(PM_FPA_LEVEL_CHIP, tmpView);
+        ok(newView, "pmFPAviewReset(PM_FPA_LEVEL_CHIP) returned non-NULL");
+        ok(newView->cell == -1, "pmFPAviewReset() set tmpView->cell to -1");
+        psFree(newView);
+
+        newView = pmFPAviewForLevel(PM_FPA_LEVEL_CELL, tmpView);
+        ok(newView, "pmFPAviewReset(PM_FPA_LEVEL_CELL) returned non-NULL");
+        ok(newView->readout == -1, "pmFPAviewReset() set tmpView->readout to 0");
+        psFree(newView);
+
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmFPAViewLevel() tests: NULL input
+    // pmFPALevel pmFPAviewLevel(const pmFPAview *view)
+    {
+        psMemId id = psMemGetId();
+        ok(!pmFPAviewLevel(NULL), "pmFPAviewLevel() returned NULL with NULL input");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAViewLevel() tests: acceptable input
+    {
+        psMemId id = psMemGetId();
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+        ok(tmpView != NULL, "pmFPAviewAlloc() returned non-NULL");
+        tmpView->chip = 16;
+        tmpView->cell = 16;
+        tmpView->readout = 16;
+        tmpView->iRows = 16;
+
+        tmpView->chip = -1;
+        ok(PM_FPA_LEVEL_FPA == pmFPAviewLevel(tmpView), "pmFPAviewReset() returned PM_FPA_LEVEL_FPA");
+        tmpView->chip = 16;
+
+        tmpView->cell = -1;
+        ok(PM_FPA_LEVEL_CHIP == pmFPAviewLevel(tmpView), "pmFPAviewReset() returned PM_FPA_LEVEL_CHIP");
+        tmpView->cell = 16;
+
+        tmpView->readout = -1;
+        ok(PM_FPA_LEVEL_CELL == pmFPAviewLevel(tmpView), "pmFPAviewReset() returned PM_FPA_LEVEL_CELL");
+        tmpView->readout = 16;
+
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // ----------------------------------------------------------------------
+    // pmFPAviewThisChip() tests: NULL view input
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        ok(NULL == pmFPAviewThisChip(NULL, fpa), "pmFPAviewThisChip(NULL, fpa) returned NULL");
+
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAviewThisChip() tests: NULL pmFPA input
+    {
+        psMemId id = psMemGetId();
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+        ok(NULL == pmFPAviewThisChip(tmpView, NULL), "pmFPAviewThisChip(pmFPAView, NULL) returned NULL");
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAviewThisChip() tests: NULL fpa->chips input
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        psArray *chips = fpa->chips;
+        fpa->chips = NULL;
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+        ok(NULL == pmFPAviewThisChip(tmpView, fpa), "pmFPAviewThisChip(pmFPAView, fpa) returned NULL view input");
+        fpa->chips = chips;
+        psFree(fpa);
+        psFree(camera);
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // pmFPAviewThisChip() tests: acceptable input
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+
+        // Test with tmpView->chip too low
+        tmpView->chip = -1;
+        ok(NULL == pmFPAviewThisChip(tmpView, fpa), "pmFPAviewThisChip(pmFPAView, fpa) returned NULL with pmFPAView->chip == -1");
+
+        // Test with tmpView->chip too high
+        tmpView->chip = fpa->chips->n;
+        ok(NULL == pmFPAviewThisChip(tmpView, fpa), "pmFPAviewThisChip(pmFPAView, fpa) returned NULL with pmFPAView->chip larger than the number of chips");
+    
+        // Test with various tmpView->chip 
+        bool errorFlag = false;
+        for (int i = 0 ; i < NUM_CHIPS ; i++) {
+            tmpView->chip = i;
+            pmChip *tmpChip = pmFPAviewThisChip(tmpView, fpa);
+            if (!tmpChip || tmpChip != fpa->chips->data[i]) {
+                diag("ERROR: pmFPAviewThisChip() returned the incorrect chip (%d)", i);
+                errorFlag = true;
+	    }
+	}
+        ok(!errorFlag, "pmFPAviewThisChip() returned the correct pmChip for all tests");
+        psFree(fpa);
+        psFree(camera);
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // ----------------------------------------------------------------------
+    // pmFPAviewNextChip() tests: NULL view input
+    // pmChip *pmFPAviewNextChip(pmFPAview *view, const pmFPA *fpa, int nStep)
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        ok(NULL == pmFPAviewNextChip(NULL, fpa, 0), "pmFPAviewNextChip(NULL, fpa, 0) returned NULL");
+
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAviewNextChip() tests: NULL pmFPA input
+    {
+        psMemId id = psMemGetId();
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+        ok(NULL == pmFPAviewNextChip(tmpView, NULL, 0), "pmFPAviewNextChip(pmFPAView, NULL, 0) returned NULL");
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAviewNextChip() tests: acceptable input
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+
+        // Test with tmpView->chip too low
+        // XXX: Source code is wrong: must guard against input tmpView->chip = -1
+        tmpView->chip = -1;
+        ok(fpa->chips->data[0] == pmFPAviewNextChip(tmpView, fpa, 1), "pmFPAviewNextChip(pmFPAView, fpa, 1) returned NULL with pmFPAView->chip == -1");
+
+        // Test with tmpView->chip too high
+        tmpView->chip = fpa->chips->n;
+        ok(NULL == pmFPAviewNextChip(tmpView, fpa, 0), "pmFPAviewNextChip(pmFPAView, fpa, 0) returned NULL with pmFPAView->chip larger than the number of chips");
+    
+        // Test with various tmpView->chip, step = 0
+        bool errorFlag = false;
+        for (int i = 0 ; i < NUM_CHIPS ; i++) {
+            tmpView->chip = i;
+            pmChip *tmpChip = pmFPAviewNextChip(tmpView, fpa, 0);
+            if (!tmpChip || tmpChip != fpa->chips->data[i]) {
+                diag("ERROR: pmFPAviewNextChip() returned the incorrect chip (%d)", i);
+                errorFlag = true;
+	    }
+	}
+        ok(!errorFlag, "pmFPAviewNextChip() returned the correct pmChip for all tests (step = 0)");
+
+        // Test with various tmpView->chip, step = 1
+        errorFlag = false;
+        for (int i = 0 ; i < NUM_CHIPS-1 ; i++) {
+            tmpView->chip = i;
+            pmChip *tmpChip = pmFPAviewNextChip(tmpView, fpa, 1);
+            if (!tmpChip || tmpChip != fpa->chips->data[i+1]) {
+                diag("ERROR: pmFPAviewNextChip() returned the incorrect chip (%d)", i);
+                errorFlag = true;
+	    }
+	}
+        ok(!errorFlag, "pmFPAviewNextChip() returned the correct pmChip for all tests (step = 1)");
+
+        psFree(fpa);
+        psFree(camera);
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmFPAviewThisCell() tests: NULL view input
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        ok(NULL == pmFPAviewThisCell(NULL, fpa), "pmFPAviewThisCell(NULL, fpa) returned NULL");
+
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAviewThisCell() tests: NULL pmFPA input
+    {
+        psMemId id = psMemGetId();
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+        ok(NULL == pmFPAviewThisCell(tmpView, NULL), "pmFPAviewThisCell(pmFPAView, NULL) returned NULL");
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAviewThisCell() tests: NULL fpa->chips input
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        psArray *chips = fpa->chips;
+        fpa->chips = NULL;
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+        ok(NULL == pmFPAviewThisCell(tmpView, fpa), "pmFPAviewThisCell(pmFPAView, fpa) returned NULL view input");
+        fpa->chips = chips;
+        psFree(fpa);
+        psFree(camera);
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // pmFPAviewThisCell() tests: acceptable input
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+
+        // Test with tmpView->chip too low
+        tmpView->chip = -1;
+        ok(NULL == pmFPAviewThisCell(tmpView, fpa), "pmFPAviewThisCell(pmFPAView, fpa) returned NULL with pmFPAView->chip == -1");
+
+        // Test with tmpView->chip too high
+        tmpView->chip = fpa->chips->n;
+        ok(NULL == pmFPAviewThisCell(tmpView, fpa), "pmFPAviewThisCell(pmFPAView, fpa) returned NULL with pmFPAView->chip larger than the number of chips");
+    
+        // Test with various tmpView->chip 
+        bool errorFlag = false;
+        for (int i = 0 ; i < NUM_CHIPS ; i++) {
+            pmChip *chip = fpa->chips->data[i];
+            for (int j = 0 ; j < NUM_CELLS ; j++) {
+                tmpView->chip = i;
+                tmpView->cell = j;
+                pmCell *tmpCell = pmFPAviewThisCell(tmpView, fpa);
+                if (!tmpCell || tmpCell != chip->cells->data[j]) {
+                    diag("ERROR: pmFPAviewThisCell() returned the incorrect chip/cell (%d, %d)", i, j);
+                    errorFlag = true;
+		}
+
+    	    }
+	}
+        ok(!errorFlag, "pmFPAviewThisCell() returned the correct pmCell for all tests");
+        psFree(fpa);
+        psFree(camera);
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmFPAviewNextCell() tests: NULL view input
+    // pmChip *pmFPAviewNextCell(pmFPAview *view, const pmFPA *fpa, int nStep)
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        ok(NULL == pmFPAviewNextCell(NULL, fpa, 0), "pmFPAviewNextCell(NULL, fpa, 0) returned NULL");
+
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAviewNextCell() tests: NULL pmFPA input
+    {
+        psMemId id = psMemGetId();
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+        ok(NULL == pmFPAviewNextCell(tmpView, NULL, 0), "pmFPAviewNextCell(pmFPAView, NULL, 0) returned NULL");
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAviewNextCell() tests: acceptable input
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+
+        // Test with tmpView->chip too low
+        tmpView->chip = -1;
+        ok(NULL == pmFPAviewNextCell(tmpView, fpa, 0), "pmFPAviewNextCell(pmFPAView, fpa) returned NULL with pmFPAView->chip == -1");
+
+        // Test with tmpView->chip too high
+        tmpView->chip = fpa->chips->n;
+        ok(NULL == pmFPAviewNextCell(tmpView, fpa, 0), "pmFPAviewNextCell(pmFPAView, fpa) returned NULL with pmFPAView->chip larger than the number of chips");
+    
+        // Test with various tmpView->chip (step = 0)
+        bool errorFlag = false;
+        for (int i = 0 ; i < NUM_CHIPS ; i++) {
+            pmChip *chip = fpa->chips->data[i];
+            for (int j = 0 ; j < NUM_CELLS ; j++) {
+                tmpView->chip = i;
+                tmpView->cell = j;
+                pmCell *tmpCell = pmFPAviewNextCell(tmpView, fpa, 0);
+                if (!tmpCell || tmpCell != chip->cells->data[j]) {
+                    diag("ERROR: pmFPAviewNextCell() returned the incorrect chip/cell (%d, %d)", i, j);
+                    errorFlag = true;
+		}
+
+    	    }
+	}
+        ok(!errorFlag, "pmFPAviewNextCell() returned the correct pmCell for all tests (step = 0)");
+
+        // Test with various tmpView->chip (step = 1)
+        errorFlag = false;
+        for (int i = 0 ; i < NUM_CHIPS ; i++) {
+            pmChip *chip = fpa->chips->data[i];
+            for (int j = 0 ; j < NUM_CELLS-1 ; j++) {
+                tmpView->chip = i;
+                tmpView->cell = j;
+                pmCell *tmpCell = pmFPAviewNextCell(tmpView, fpa, 1);
+                if (!tmpCell || tmpCell != chip->cells->data[j+1]) {
+                    diag("ERROR: pmFPAviewNextCell() returned the incorrect chip/cell (%d, %d)", i, j);
+                    errorFlag = true;
+		}
+
+    	    }
+	}
+        ok(!errorFlag, "pmFPAviewNextCell() returned the correct pmCell for all tests (step = 1)");
+
+        psFree(fpa);
+        psFree(camera);
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // ----------------------------------------------------------------------
+    // pmFPAviewThisReadout() tests: NULL view input
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        ok(NULL == pmFPAviewThisReadout(NULL, fpa), "pmFPAviewThisReadout(NULL, fpa) returned NULL");
+
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAviewThisReadout() tests: NULL pmFPA input
+    {
+        psMemId id = psMemGetId();
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+        ok(NULL == pmFPAviewThisReadout(tmpView, NULL), "pmFPAviewThisReadout(pmFPAView, NULL) returned NULL");
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAviewThisReadout() tests: NULL fpa->chips input
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        psArray *chips = fpa->chips;
+        fpa->chips = NULL;
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+        ok(NULL == pmFPAviewThisReadout(tmpView, fpa), "pmFPAviewThisReadout(pmFPAView, fpa) returned NULL view input");
+        fpa->chips = chips;
+        psFree(fpa);
+        psFree(camera);
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // pmFPAviewThisReadout() tests: acceptable input
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+
+        // Test with tmpView->chip too low
+        tmpView->chip = -1;
+        ok(NULL == pmFPAviewThisReadout(tmpView, fpa), "pmFPAviewThisReadout(pmFPAView, fpa) returned NULL with pmFPAView->chip == -1");
+
+        // Test with tmpView->chip too high
+        tmpView->chip = fpa->chips->n;
+        ok(NULL == pmFPAviewThisReadout(tmpView, fpa), "pmFPAviewThisReadout(pmFPAView, fpa) returned NULL with pmFPAView->chip larger than the number of chips");
+    
+        // Test with various tmpView->chip 
+        bool errorFlag = false;
+        for (int i = 0 ; i < NUM_CHIPS ; i++) {
+            pmChip *chip = fpa->chips->data[i];
+            for (int j = 0 ; j < NUM_CELLS ; j++) {
+                pmCell *cell = chip->cells->data[j];
+                for (int k = 0 ; k < NUM_READOUTS ; k++) {
+                    tmpView->chip = i;
+                    tmpView->cell = j;
+                    tmpView->readout = k;
+                    pmReadout *tmpReadout = pmFPAviewThisReadout(tmpView, fpa);
+                    if (!tmpReadout || tmpReadout != cell->readouts->data[k]) {
+                        diag("ERROR: pmFPAviewThisReadout() returned the incorrect chip/cell/readout (%d, %d, %d)", i, j, k);
+                        errorFlag = true;
+		    }
+		}
+    	    }
+	}
+        ok(!errorFlag, "pmFPAviewThisReadout() returned the correct pmCell for all tests");
+
+        psFree(fpa);
+        psFree(camera);
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmFPAviewNextReadout() tests: NULL view input
+    // pmChip *pmFPAviewNextReadout(pmFPAview *view, const pmFPA *fpa, int nStep)
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        ok(NULL == pmFPAviewNextReadout(NULL, fpa, 0), "pmFPAviewNextReadout(NULL, fpa, 0) returned NULL");
+
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAviewNextReadout() tests: NULL pmFPA input
+    {
+        psMemId id = psMemGetId();
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+        ok(NULL == pmFPAviewNextReadout(tmpView, NULL, 0), "pmFPAviewNextReadout(pmFPAView, NULL, 0) returned NULL");
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // pmFPAviewNextReadout() tests: acceptable input
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+
+        // Test with tmpView->chip too low
+        tmpView->chip = -1;
+        ok(NULL == pmFPAviewNextReadout(tmpView, fpa, 0), "pmFPAviewNextReadout(pmFPAView, fpa) returned NULL with pmFPAView->chip == -1");
+
+        // Test with tmpView->chip too high
+        tmpView->chip = fpa->chips->n;
+        ok(NULL == pmFPAviewNextReadout(tmpView, fpa, 0), "pmFPAviewNextReadout(pmFPAView, fpa) returned NULL with pmFPAView->chip larger than the number of chips");
+    
+        // Test with various tmpView->chip (step = 0)
+        bool errorFlag = false;
+        for (int i = 0 ; i < NUM_CHIPS ; i++) {
+            pmChip *chip = fpa->chips->data[i];
+            for (int j = 0 ; j < NUM_CELLS ; j++) {
+                pmCell *cell = chip->cells->data[j];
+                for (int k = 0 ; k < NUM_READOUTS ; k++) {
+                    tmpView->chip = i;
+                    tmpView->cell = j;
+                    tmpView->readout = k;
+                    pmReadout *tmpReadout = pmFPAviewNextReadout(tmpView, fpa, 0);
+                    if (!tmpReadout || tmpReadout != cell->readouts->data[k]) {
+                        diag("ERROR: pmFPAviewNextReadout() returned the incorrect chip/cell/readout (%d, %d, %d)", i, j, k);
+                        errorFlag = true;
+		    }
+		}
+    	    }
+	}
+        ok(!errorFlag, "pmFPAviewNextReadout() returned the correct pmCell for all tests (step = 0)");
+
+        // Test with various tmpView->chip (step = 1)
+        errorFlag = false;
+        for (int i = 0 ; i < NUM_CHIPS ; i++) {
+            pmChip *chip = fpa->chips->data[i];
+            for (int j = 0 ; j < NUM_CELLS ; j++) {
+                pmCell *cell = chip->cells->data[j];
+                for (int k = 0 ; k < NUM_READOUTS-1 ; k++) {
+                    tmpView->chip = i;
+                    tmpView->cell = j;
+                    tmpView->readout = k;
+                    pmReadout *tmpReadout = pmFPAviewNextReadout(tmpView, fpa, 1);
+                    if (!tmpReadout || tmpReadout != cell->readouts->data[k+1]) {
+                        diag("ERROR: pmFPAviewNextReadout() returned the incorrect chip/cell/readout (%d, %d, %d)", i, j, k);
+                        errorFlag = true;
+		    }
+		}
+    	    }
+	}
+        ok(!errorFlag, "pmFPAviewNextReadout() returned the correct pmCell for all tests (step = 1)");
+
+        psFree(fpa);
+        psFree(camera);
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmFPAviewThisHDU() tests: NULL view input
+    // pmHDU *pmFPAviewThisHDU(const pmFPAview *view, const pmFPA *fpa)
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        ok(NULL == pmFPAviewThisHDU(NULL, fpa), "pmFPAviewThisHDU(NULL, fpa) returned NULL");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // pmFPAviewThisHDU() tests: NULL pmFPA input
+    // pmHDU *pmFPAviewThisHDU(const pmFPAview *view, const pmFPA *fpa)
+    {
+        psMemId id = psMemGetId();
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+        ok(NULL == pmFPAviewThisHDU(tmpView, NULL), "pmFPAviewThisHDU(pmFPAView, NULL) returned NULL");
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAviewThisHDU() tests: acceptable input
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+
+        tmpView->chip = -1;
+        pmHDU *hdu = pmFPAviewThisHDU(tmpView, fpa);
+        ok(hdu, "pmFPAviewThisHDU() returned non-NULL with tmpView->chip = -1");
+        ok(hdu == pmHDUFromFPA(fpa), "pmFPAviewThisHDU() returned the correct HDU");
+        tmpView->chip = NUM_CHIPS/2;
+
+        tmpView->cell = -1;
+        hdu = pmFPAviewThisHDU(tmpView, fpa);
+        ok(hdu, "pmFPAviewThisHDU() returned non-NULL with tmpView->cell = -1");
+        ok(hdu == pmHDUFromChip(pmFPAviewThisChip(tmpView, fpa)), "pmFPAviewThisHDU() returned the correct HDU");
+        tmpView->cell = NUM_CELLS/2;
+
+        tmpView->readout = -1;
+        hdu = pmFPAviewThisHDU(tmpView, fpa);
+        ok(hdu, "pmFPAviewThisHDU() returned non-NULL with tmpView->readout = -1");
+        ok(hdu == pmHDUFromCell(pmFPAviewThisCell(tmpView, fpa)), "pmFPAviewThisHDU() returned the correct HDU");
+        tmpView->readout = NUM_READOUTS/2;
+
+        hdu = pmFPAviewThisHDU(tmpView, fpa);
+        ok(hdu, "pmFPAviewThisHDU() returned non-NULL");
+        ok(hdu == pmHDUFromReadout(pmFPAviewThisReadout(tmpView, fpa)), "pmFPAviewThisHDU() returned the correct HDU");
+
+        psFree(fpa);
+        psFree(camera);
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmFPAviewThisPHU() tests: NULL view input
+    // pmHDU *pmFPAviewThisPHU(const pmFPAview *view, const pmFPA *fpa)
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        ok(NULL == pmFPAviewThisPHU(NULL, fpa), "pmFPAviewThisPHU(NULL, fpa) returned NULL");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // pmFPAviewThisPHU() tests: NULL pmFPA input
+    // pmHDU *pmFPAviewThisPHU(const pmFPAview *view, const pmFPA *fpa)
+    {
+        psMemId id = psMemGetId();
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+        ok(NULL == pmFPAviewThisPHU(tmpView, NULL), "pmFPAviewThisPHU(pmFPAView, NULL) returned NULL");
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAviewThisPHU() tests: acceptable input
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        pmFPAview *tmpView = pmFPAviewAlloc(32);
+
+        tmpView->chip = -1;
+        pmHDU *hdu = pmFPAviewThisPHU(tmpView, fpa);
+        ok(hdu, "pmFPAviewThisPHU() returned non-NULL with tmpView->chip = -1");
+        ok(hdu == pmHDUFromFPA(fpa), "pmFPAviewThisPHU() returned the correct HDU");
+        tmpView->chip = NUM_CHIPS/2;
+
+        tmpView->cell = -1;
+        hdu = pmFPAviewThisPHU(tmpView, fpa);
+        ok(hdu, "pmFPAviewThisPHU() returned non-NULL with tmpView->cell = -1");
+        ok(hdu == pmHDUFromChip(pmFPAviewThisChip(tmpView, fpa)), "pmFPAviewThisPHU() returned the correct HDU");
+        tmpView->cell = NUM_CELLS/2;
+
+        tmpView->readout = -1;
+        hdu = pmFPAviewThisPHU(tmpView, fpa);
+        ok(hdu, "pmFPAviewThisPHU() returned non-NULL with tmpView->readout = -1");
+        ok(hdu == pmHDUFromCell(pmFPAviewThisCell(tmpView, fpa)), "pmFPAviewThisPHU() returned the correct HDU");
+        tmpView->readout = NUM_READOUTS/2;
+
+        hdu = pmFPAviewThisPHU(tmpView, fpa);
+        ok(hdu == NULL, "pmFPAviewThisPHU() returned NULL");
+
+        psFree(fpa);
+        psFree(camera);
+        psFree(tmpView);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmFPAviewGenerate() tests: NULL pmFPA input
+    {
+        psMemId id = psMemGetId();
+        int chipID = NUM_CHIPS/2;
+        int cellID = NUM_CELLS/2;
+        int readoutID = NUM_READOUTS/2;
+        pmFPA* fpa = generateSimpleFPA(NULL);
+        pmChip *chip = fpa->chips->data[chipID];
+        pmCell *cell = chip->cells->data[cellID];
+        pmReadout *readout = cell->readouts->data[readoutID];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        ok(readout != NULL, "Allocated a pmReadout successfully");
+        pmFPAview *view = pmFPAviewGenerate(NULL, chip, cell, readout);
+        ok(view == NULL, "pmFPAviewGenerate(NULL, chip, cell, readout) returned NULL");
+        psFree(fpa);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmFPAviewGenerate() tests: acceptable input parameters
+    // XX: Add more input combinations.
+    {
+        psMemId id = psMemGetId();
+        int chipID = NUM_CHIPS/2;
+        int cellID = NUM_CELLS/2;
+        int readoutID = NUM_READOUTS/2;
+        pmFPA* fpa = generateSimpleFPA(NULL);
+        pmChip *chip = fpa->chips->data[chipID];
+        pmCell *cell = chip->cells->data[cellID];
+        pmReadout *readout = cell->readouts->data[readoutID];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        ok(readout != NULL, "Allocated a pmReadout successfully");
+        pmFPAview *view = pmFPAviewGenerate(fpa, chip, cell, readout);
+        ok(view != NULL && psMemCheckFPAview(view), "pmFPAviewGenerate() returned an pmFPAviw with acceptable input parameters");
+        ok(view->chip == chipID, "pmFPAviewGenerate() set pmFPAview->chip correctly");
+        ok(view->cell == cellID, "pmFPAviewGenerate() set pmFPAview->cell correctly");
+        ok(view->readout == readoutID, "pmFPAviewGenerate() set pmFPAview->readout correctly");
+        psFree(view);
+        psFree(fpa);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmHDU.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmHDU.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmHDU.c	(revision 22158)
@@ -0,0 +1,571 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    All functions are tested.
+*/
+
+#define NUM_HDUS 8
+char *fitsFilename = "tmp.fits";
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", 0);
+    plan_tests(159);
+
+
+    // ----------------------------------------------------------------------
+    // pmHDUAlloc() tests
+    // Test pmHDUAlloc() with a NULL extname
+    {
+        psMemId id = psMemGetId();
+        pmHDU *hdu = pmHDUAlloc(NULL);
+        ok(hdu, "pmHDUAlloc(NULL) returned non-NULL");
+        skip_start(!hdu, 7, "Skipping tests because pmHDUAlloc(NULL) returned NULL");
+        ok(hdu->blankPHU == true, "pmHDUAlloc(NULL) set hdu->blankPHU correctly");
+        ok(hdu->extname == NULL, "pmHDUAlloc(NULL) set hdu->extname correctly");
+        ok(hdu->format == NULL, "pmHDUAlloc(NULL) set hdu->format correctly");
+        ok(hdu->header == NULL, "pmHDUAlloc(NULL) set hdu->header correctly");
+        ok(hdu->images == NULL, "pmHDUAlloc(NULL) set hdu->images correctly");
+        ok(hdu->weights == NULL, "pmHDUAlloc(NULL) set hdu->weights correctly");
+        ok(hdu->masks == NULL, "pmHDUAlloc(NULL) set hdu->masks correctly");
+        psFree(hdu);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmHDUAlloc() with a non-NULL extname
+    {
+        psMemId id = psMemGetId();
+        pmHDU *hdu = pmHDUAlloc("ext-0");
+        ok(hdu, "pmHDUAlloc(extname) returned non-NULL");
+        skip_start(!hdu, 7, "Skipping tests because pmHDUAlloc(extname) returned NULL");
+        ok(hdu->blankPHU == false, "pmHDUAlloc(extname) set hdu->blankPHU correctly");
+        ok(0 == strcmp(hdu->extname, "ext-0"), "pmHDUAlloc(extname) set hdu->extname correctly");
+        ok(hdu->format == NULL, "pmHDUAlloc(extname) set hdu->format correctly");
+        ok(hdu->header == NULL, "pmHDUAlloc(extname) set hdu->header correctly");
+        ok(hdu->images == NULL, "pmHDUAlloc(extname) set hdu->images correctly");
+        ok(hdu->weights == NULL, "pmHDUAlloc(extname) set hdu->weights correctly");
+        ok(hdu->masks == NULL, "pmHDUAlloc(extname) set hdu->masks correctly");
+        psFree(hdu);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmHDUWrite(), pmHDURead tests
+    // Test pmHDUWrite() with NULL pmHDU input argument
+    {
+        psMemId id = psMemGetId();
+        // Create simple FITS file
+        psFits* fitsFile = psFitsOpen(".tmp00", "w");
+        ok(fitsFile != NULL, "psFitsOpen() was successful");
+        psMetadata* header = psMetadataAlloc();
+        psImage* image = psImageAlloc(16, 16, PS_TYPE_F32);
+        ok(psFitsWriteImage(fitsFile, header, image, 0, "extname"), "psFitsWriteImage() successful");
+        psFree(header);
+        psFree(image);
+        bool rc = pmHDUWrite(NULL, fitsFile);
+        ok(rc == false, "pmHDUWrite() returned FALSE with NULL psHDU as input");
+        psFitsClose(fitsFile);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmHDUWrite() with NULL psFits input argument
+    {
+        psMemId id = psMemGetId();
+        pmHDU *hdu = pmHDUAlloc("extname");
+        hdu->header = psMetadataAlloc();
+        psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYINT", PS_DATA_S32, "psS32 Item", 0);
+        bool rc = pmConfigFileRead(&hdu->format, "../dataFiles/camera0/format0.config", "Camera 0 Config Format");
+        if (!rc) {
+            rc = pmConfigFileRead(&hdu->format, "dataFiles/camera0/format0.config", "Camera 0 Config Format");
+	}
+        ok(rc == true, "pmConfigFileRead() was successful");
+        rc = pmHDUWrite(hdu, NULL);
+        ok(rc == false, "pmHDUWrite() returned FALSE with NULL psFits file as input");
+        psFree(hdu);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmHDURead() with NULL pmHDU input argument
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen("../dataFiles/sampleFitsFile.fits", "r");
+        if (!fitsFile) {
+            fitsFile = psFitsOpen("dataFiles/sampleFitsFile.fits", "r");
+	}
+        ok(fitsFile != NULL, "psFitsOpen() was successful");
+        bool rc = pmHDURead(NULL, fitsFile);
+        ok(rc == false, "pmHDURead() returned FALSE with NULL psHDU as input");
+        psFitsClose(fitsFile);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmHDURead() with NULL pmHDU input argument
+    {
+        psMemId id = psMemGetId();
+        pmHDU *hdu = pmHDUAlloc("extname");
+        hdu->header = psMetadataAlloc();
+        bool rc = pmHDURead(hdu, NULL);
+        ok(rc == false, "pmHDURead() returned FALSE with NULL psFits file as input");
+        psFree(hdu);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // 1. Create a simple FITS file
+    // 2. Create a simple pmHDU header
+    // 3. Use pmHDUWrite() to write that header to the FITS file
+    // 4. Close the FITS file
+    // 5. Read that fits file from disk
+    // 6. Create another pmHDU
+    // 7. Call pmHDURead()which will read the FITS data into hdu->images
+    // 8. Verify that hdu->images was set correctly.
+    // 
+    // XXX: Add code to delete .tmp00
+    // XXX: Should we try with multiple images in the psArray hdu->images?
+    #define BASE 20
+    {
+        psMemId id = psMemGetId();
+        // 1. Create a simple FITS file
+        psFits* fitsFileW = psFitsOpen(".tmp00", "w");
+        ok(fitsFileW != NULL, "psFitsOpen() was successful");
+        // 2. Create a simple pmHDU header
+        //    Allocate and format hdu->header
+        //    Set hdu->images
+        pmHDU *hdu = pmHDUAlloc("extname");
+        bool rc = pmConfigFileRead(&hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            rc = pmConfigFileRead(&hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+	}
+        ok(rc, "pmConfigFileRead() was successful");
+        hdu->images = psArrayAlloc(NUM_HDUS);
+        for (int k = 0 ; k < NUM_HDUS ; k++) {
+            hdu->images->data[k] = psImageAlloc(4, 4, PS_TYPE_F32);
+            psImageInit(hdu->images->data[k], (float) (BASE+k));
+	}
+        // 3. Use pmHDUWrite() to write that header to the FITS file
+        rc = pmHDUWrite(hdu, fitsFileW);
+        ok(rc == true, "pmHDUWrite() returned TRUE");
+        // 4. Close the FITS file, free memory
+        psFree(hdu);
+        psFitsClose(fitsFileW);
+
+        // Now, try to read that FITS file from disk.
+        // 5. Read that fits file from disk
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+        ok(fitsFileR != NULL, "psFitsOpen() was successful");
+        // 6. Create another pmHDU
+        hdu = pmHDUAlloc("extname");
+        hdu->images = NULL;
+        // 7. Call pmHDURead()which will read the FITS data into hdu->images
+        rc = pmHDURead(hdu, fitsFileR);
+        ok(rc == true, "pmHDURead() returned TRUE");
+        ok(hdu->images != NULL, "pmHDURead() created hdu->images");
+        // 8. Verify that hdu->images was set correctly.
+        bool errorFlag = false;
+        for (int k = 0 ; k < NUM_HDUS ; k++) {
+            psImage *img = (psImage *) hdu->images->data[k];
+            for (psS32 i = 0 ; i < img->numRows ; i++) {
+                for (psS32 j = 0 ; j < img->numCols ; j++) {
+                    if (((float) k+BASE) != img->data.F32[i][j]) {
+                        errorFlag = true;
+                        diag("TEST ERROR (image %d): img[%d][%d] is %f, should be %f\n",
+                              k, i, j, img->data.F32[i][j], ((float)k+BASE));
+        	    }
+            	}
+	    }
+	}
+        ok(!errorFlag, "pmHDURead() correctly returned the image data");
+        psFitsClose(fitsFileR);
+        psFree(hdu);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmHDUWriteWeight(), pmHDUReadWeight() tests
+    // Test pmHDUWriteWeight() with NULL pmHDU input argument
+    {
+        psMemId id = psMemGetId();
+        // Create simple FITS file
+        psFits* fitsFile = psFitsOpen(".tmp00", "w");
+        ok(fitsFile != NULL, "psFitsOpen() was successful");
+        psMetadata* header = psMetadataAlloc();
+        psImage* image = psImageAlloc(16, 16, PS_TYPE_F32);
+        ok(psFitsWriteImage(fitsFile, header, image, 0, "extname"), "psFitsWriteImage() successful");
+        psFree(header);
+        psFree(image);
+        bool rc = pmHDUWriteWeight(NULL, fitsFile);
+        ok(rc == false, "pmHDUWriteWeight() returned FALSE with NULL psHDU as input");
+        psFitsClose(fitsFile);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmHDUWriteWeight() with NULL psFits input argument
+    {
+        psMemId id = psMemGetId();
+        pmHDU *hdu = pmHDUAlloc("extname");
+        hdu->header = psMetadataAlloc();
+        psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYINT", PS_DATA_S32, "psS32 Item", 0);
+        bool rc = pmConfigFileRead(&hdu->format, "../dataFiles/camera0/format0.config", "Camera 0 Config Format");
+        if (!rc) {
+            rc = pmConfigFileRead(&hdu->format, "dataFiles/camera0/format0.config", "Camera 0 Config Format");
+	}
+        ok(rc == true, "pmConfigFileRead() was successful");
+        rc = pmHDUWriteWeight(hdu, NULL);
+        ok(rc == false, "pmHDUWriteWeight    () returned FALSE with NULL psFits file as input");
+        psFree(hdu);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmHDUReadWeight() with NULL pmHDU input argument
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen("../dataFiles/sampleFitsFile.fits", "r");
+        if (!fitsFile) {
+            fitsFile = psFitsOpen("dataFiles/sampleFitsFile.fits", "r");
+	}
+        ok(fitsFile != NULL, "psFitsOpen() was successful");
+        bool rc = pmHDUReadWeight(NULL, fitsFile);
+        ok(rc == false, "pmHDUReadWeight() returned FALSE with NULL psHDU as input");
+        psFitsClose(fitsFile);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmHDUReadWeight() with NULL pmHDU input argument
+    {
+        psMemId id = psMemGetId();
+        pmHDU *hdu = pmHDUAlloc("extname");
+        hdu->header = psMetadataAlloc();
+        bool rc = pmHDUReadWeight(hdu, NULL);
+        ok(rc == false, "pmHDUReadWeight    () returned FALSE with NULL psFits file as input");
+        psFree(hdu);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // 1. Create a simple FITS file
+    // 2. Create a simple pmHDU header
+    // 3. Use pmHDUWriteWeight() to write that header to the FITS file
+    // 4. Close the FITS file
+    // 5. Read that fits file from disk
+    // 6. Create another pmHDU
+    // 7. Call pmHDUReadWeight()which will read the FITS data into hdu->images
+    // 8. Verify that hdu->images was set correctly.
+    // 
+    // XXX: Add code to delete .tmp00
+    // XXX: Should we try with multiple images in the psArray hdu->images?
+    #define BASE 20
+    {
+        psMemId id = psMemGetId();
+        // 1. Create a simple FITS file
+        psFits* fitsFileW = psFitsOpen(".tmp00", "w");
+        ok(fitsFileW != NULL, "psFitsOpen() was successful");
+        // 2. Create a simple pmHDU header
+        //    Allocate and format hdu->header
+        //    Set hdu->images
+        pmHDU *hdu = pmHDUAlloc("extname");
+        bool rc = pmConfigFileRead(&hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            rc = pmConfigFileRead(&hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+	}
+        ok(rc, "pmConfigFileRead() was successful");
+        hdu->weights = psArrayAlloc(NUM_HDUS);
+        for (int k = 0 ; k < NUM_HDUS ; k++) {
+            hdu->weights->data[k] = psImageAlloc(4, 4, PS_TYPE_F32);
+            psImageInit(hdu->weights->data[k], (float) (BASE+k));
+	}
+        // 3. Use pmHDUWriteWeight() to write that header to the FITS file
+        rc = pmHDUWriteWeight(hdu, fitsFileW);
+        ok(rc == true, "pmHDUWriteWeight() returned TRUE");
+        // 4. Close the FITS file, free memory
+        psFree(hdu);
+        psFitsClose(fitsFileW);
+
+        // Now, try to read that FITS file from disk.
+        // 5. Read that fits file from disk
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+        ok(fitsFileR != NULL, "psFitsOpen() was successful");
+        // 6. Create another pmHDU
+        hdu = pmHDUAlloc("extname");
+        hdu->weights = NULL;
+        // 7. Call pmHDUReadWeight()which will read the FITS data into hdu->weights
+        rc = pmHDUReadWeight(hdu, fitsFileR);
+        ok(rc == true, "pmHDUReadWeight() returned TRUE");
+        ok(hdu->weights != NULL, "pmHDUReadWeight() created hdu->weights");
+        // 8. Verify that hdu->weights was set correctly.
+        bool errorFlag = false;
+        for (int k = 0 ; k < NUM_HDUS ; k++) {
+            psImage *img = (psImage *) hdu->weights->data[k];
+            for (psS32 i = 0 ; i < img->numRows ; i++) {
+                for (psS32 j = 0 ; j < img->numCols ; j++) {
+                    if (((float) k+BASE) != img->data.F32[i][j]) {
+                        errorFlag = true;
+                        diag("TEST ERROR (image %d): img[%d][%d] is %f, should be %f\n",
+                              k, i, j, img->data.F32[i][j], ((float)k+BASE));
+        	    }
+            	}
+	    }
+	}
+        ok(!errorFlag, "pmHDUReadWeight() correctly returned the image data");
+        psFitsClose(fitsFileR);
+        psFree(hdu);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmHDUWriteMask(), pmHDUReadMask() tests
+    // Test pmHDUWriteMask() with NULL pmHDU input argument
+    {
+        psMemId id = psMemGetId();
+        // Create simple FITS file
+        psFits* fitsFile = psFitsOpen(".tmp00", "w");
+        ok(fitsFile != NULL, "psFitsOpen() was successful");
+        psMetadata* header = psMetadataAlloc();
+        psImage* image = psImageAlloc(16, 16, PS_TYPE_F32);
+        ok(psFitsWriteImage(fitsFile, header, image, 0, "extname"), "psFitsWriteImage() successful");
+        psFree(header);
+        psFree(image);
+        bool rc = pmHDUWriteMask(NULL, fitsFile);
+        ok(rc == false, "pmHDUWriteMask() returned FALSE with NULL psHDU as input");
+        psFitsClose(fitsFile);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmHDUWriteMask() with NULL psFits input argument
+    {
+        psMemId id = psMemGetId();
+        pmHDU *hdu = pmHDUAlloc("extname");
+        hdu->header = psMetadataAlloc();
+        psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYINT", PS_DATA_S32, "psS32 Item", 0);
+        bool rc = pmConfigFileRead(&hdu->format, "dataFiles/camera0/format0.config", "Camera 0 Config Format");
+        if (!rc) {
+             pmConfigFileRead(&hdu->format, "../dataFiles/camera0/format0.config", "Camera 0 Config Format");
+	}
+        ok(rc == true, "pmConfigFileRead() was successful");
+        rc = pmHDUWriteMask(hdu, NULL);
+        ok(rc == false, "pmHDUWriteMask() returned FALSE with NULL psFits file as input");
+        psFree(hdu);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmHDUReadMask() with NULL pmHDU input argument
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen("../dataFiles/sampleFitsFile.fits", "r");
+        if (!fitsFile) {
+            fitsFile = psFitsOpen("dataFiles/sampleFitsFile.fits", "r");
+	}
+        ok(fitsFile != NULL, "psFitsOpen() was successful");
+        bool rc = pmHDUReadMask(NULL, fitsFile);
+        ok(rc == false, "pmHDUReadMask() returned FALSE with NULL psHDU as input");
+        psFitsClose(fitsFile);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmHDUReadMask() with NULL pmHDU input argument
+    {
+        psMemId id = psMemGetId();
+        pmHDU *hdu = pmHDUAlloc("extname");
+        hdu->header = psMetadataAlloc();
+        bool rc = pmHDUReadMask(hdu, NULL);
+        ok(rc == false, "pmHDUReadMask() returned FALSE with NULL psFits file as input");
+        psFree(hdu);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // 1. Create a simple FITS file
+    // 2. Create a simple pmHDU header
+    // 3. Use pmHDUWriteMask() to write that header to the FITS file
+    // 4. Close the FITS file
+    // 5. Read that fits file from disk
+    // 6. Create another pmHDU
+    // 7. Call pmHDUReadMask()which will read the FITS data into hdu->images
+    // 8. Verify that hdu->images was set correctly.
+    // 
+    // XXX: Add code to delete .tmp00
+    // XXX: Should we try with multiple images in the psArray hdu->images?
+    #define BASE 20
+    {
+        psMemId id = psMemGetId();
+        // 1. Create a simple FITS file
+        psFits* fitsFileW = psFitsOpen(".tmp00", "w");
+        ok(fitsFileW != NULL, "psFitsOpen() was successful");
+        // 2. Create a simple pmHDU header
+        //    Allocate and format hdu->header
+        //    Set hdu->images
+        pmHDU *hdu = pmHDUAlloc("extname");
+        bool rc = pmConfigFileRead(&hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            rc = pmConfigFileRead(&hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+	}
+        ok(rc, "pmConfigFileRead() was successful");
+        hdu->masks = psArrayAlloc(NUM_HDUS);
+        for (int k = 0 ; k < NUM_HDUS ; k++) {
+            hdu->masks->data[k] = psImageAlloc(4, 4, PS_TYPE_F32);
+            psImageInit(hdu->masks->data[k], (float) (BASE+k));
+	}
+        // 3. Use pmHDUWriteMask() to write that header to the FITS file
+        rc = pmHDUWriteMask(hdu, fitsFileW);
+        ok(rc == true, "pmHDUWriteMask() returned TRUE");
+        // 4. Close the FITS file, free memory
+        psFree(hdu);
+        psFitsClose(fitsFileW);
+
+        // Now, try to read that FITS file from disk.
+        // 5. Read that fits file from disk
+        psFits* fitsFileR = psFitsOpen(".tmp00", "r");
+        ok(fitsFileR != NULL, "psFitsOpen() was successful");
+        // 6. Create another pmHDU
+        hdu = pmHDUAlloc("extname");
+        hdu->masks = NULL;
+        // 7. Call pmHDUReadMask()which will read the FITS data into hdu->masks
+        rc = pmHDUReadMask(hdu, fitsFileR);
+        ok(rc == true, "pmHDUReadMask() returned TRUE");
+        ok(hdu->masks != NULL, "pmHDUReadMask() created hdu->masks");
+        // 8. Verify that hdu->masks was set correctly.
+        bool errorFlag = false;
+        for (int k = 0 ; k < NUM_HDUS ; k++) {
+            psImage *img = (psImage *) hdu->masks->data[k];
+            for (psS32 i = 0 ; i < img->numRows ; i++) {
+                for (psS32 j = 0 ; j < img->numCols ; j++) {
+                    if (((float) k+BASE) != img->data.F32[i][j]) {
+                        errorFlag = true;
+                        diag("TEST ERROR (image %d): img[%d][%d] is %f, should be %f\n",
+                              k, i, j, img->data.F32[i][j], ((float)k+BASE));
+        	    }
+            	}
+	    }
+	}
+        ok(!errorFlag, "pmHDUReadMask() correctly returned the image data");
+        psFitsClose(fitsFileR);
+        psFree(hdu);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmHDUReadHeader(), pmHDUWriteHeader() tests
+    // Test pmHDUReadHeader() with NULL pmHDU input argument
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen("../dataFiles/sampleFitsFile.fits", "r");
+        if (!fitsFile) {
+            fitsFile = psFitsOpen("dataFiles/sampleFitsFile.fits", "r");
+	}
+        ok(fitsFile != NULL, "psFitsOpen() was successful");
+        bool rc = pmHDUReadHeader(NULL, fitsFile);
+        ok(rc == false, "pmHDUReadHeader() returned FALSE with NULL psHDU as input");
+        psFitsClose(fitsFile);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmHDUReadHeader() with NULL psFits input argument
+    {
+        psMemId id = psMemGetId();
+        pmHDU *hdu = pmHDUAlloc("extname");
+        hdu->header = psMetadataAlloc();
+        bool rc = pmHDUReadHeader(hdu, NULL);
+        ok(rc == false, "pmHDUReadHeader() returned FALSE with NULL psFits file as input");
+        psFree(hdu);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmHDUReadHeader() and pmHDUWriteHeader()
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFileW = psFitsOpen(fitsFilename, "w");
+        ok(fitsFileW != NULL, "psFitsOpen() opened the FITS file");
+        char extname[80];
+        for (int lcv = 0; lcv < NUM_HDUS; lcv++) {
+            snprintf(extname, 80, "ext-%d", lcv);
+            pmHDU *hdu = pmHDUAlloc(extname);
+            hdu->header = psMetadataAlloc();
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYINT", PS_DATA_S32,
+                         "psS32 Item", (psS32)lcv);
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYFLT", PS_DATA_F32,
+                         "psF32 Item", (float)(1.0f/(float)(1+lcv)));
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYDBL", PS_DATA_F64,
+                         "psF64 Item", (double)(1.0/(double)(1+lcv)));
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYBOOL", PS_DATA_BOOL,
+                         "psBool Item", (lcv%2 == 0));
+            psMetadataAdd(hdu->header, PS_LIST_TAIL, "MYSTR", PS_DATA_STRING,
+                         "psStr Item", extname);
+
+            bool rc = pmConfigFileRead(&hdu->format, "../dataFiles/camera0/format0.config", "Camera 0 Config Format");
+            if (!rc) {
+                rc = pmConfigFileRead(&hdu->format, "dataFiles/camera0/format0.config", "Camera 0 Config Format");
+	    }
+            ok(rc == true, "pmConfigFileRead() was successful");
+            rc = pmHDUWrite(hdu, fitsFileW);
+            ok(rc == true, "pmHDUWrite() successfully wrote the header");
+            psFree(hdu);
+        }
+        psFitsClose(fitsFileW);
+
+        psFits* fitsFileR = psFitsOpen(fitsFilename, "r");
+        ok(fitsFileR != NULL, "psFitsOpen returned non-NULL on existing file");
+        int numHDUs = psFitsGetSize(fitsFileR);
+        ok(numHDUs == NUM_HDUS, "The test FITS file has %d HDUs", numHDUs);
+
+        for (int hdunum = 0; hdunum < NUM_HDUS; hdunum++)
+        {
+            char extname[80];
+            snprintf(extname,80, "ext-%d", hdunum);
+            psFitsMoveExtNum(fitsFileR, hdunum, false);
+            pmHDU *hdu = pmHDUAlloc(extname);
+            bool rc = pmHDUReadHeader(hdu, fitsFileR);
+            ok(rc == true, "pmHDUReadHeader() returned TRUE");
+            ok(hdu->header != NULL && psMemCheckMetadata(hdu->header),
+              "pmHDUReadHeader() correctly returned the hdu->header member");
+
+            psS32 intItem = psMetadataLookupS32(NULL, hdu->header, "MYINT");
+            ok(intItem == hdunum, "Retrieved psS32 metadata item from file");
+
+            psF32 fltItem = psMetadataLookupF32(NULL, hdu->header, "MYFLT");
+            ok(fabsf(fltItem - 1.0f/(float)(1+hdunum)) <= FLT_EPSILON,
+               "Retrieved psF32 metadata item from file.  Got %f vs %f",
+               fltItem,1.0f/(float)(1+hdunum));
+
+            psF64 dblItem = psMetadataLookupF64(NULL, hdu->header, "MYDBL");
+            ok(abs(dblItem - 1.0/(double)(1+hdunum)) <= DBL_EPSILON,
+               "Retrieved psF64 metadata item from file.  Got %g vs %g",
+               dblItem, 1.0/(double)(1+hdunum));
+
+            psMetadataItem* boolItem = psMetadataLookup(hdu->header, "MYBOOL");
+            ok(boolItem != NULL && boolItem->type == PS_DATA_BOOL,
+               "Retrieved psBool metadata item from file");
+
+            psString strItem = psMetadataLookupStr(NULL, hdu->header, "MYSTR");
+            ok(strItem != NULL && strncmp(strItem,extname,strlen(extname)) == 0,
+               "Retrieved string metadata item from file.  Got '%s' vs '%s' (%d)",
+               strItem,extname,strlen(extname));
+
+            psFree(hdu);
+        }
+        psFitsClose(fitsFileR);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmHDUUtils.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmHDUUtils.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmHDUUtils.c	(revision 22158)
@@ -0,0 +1,480 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    All functions are tested.
+*/
+
+#define CHIP_ALLOC_NAME        "ChipName"
+#define CELL_ALLOC_NAME        "CellName"
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define MISC_NAME2             "META01"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           4
+#define TEST_NUM_COLS           4
+#define NUM_READOUTS            3
+#define NUM_CELLS               10
+#define NUM_CHIPS               8
+#define NUM_HDUS                5
+#define BASE_IMAGE              10
+#define BASE_MASK               40
+#define BASE_WEIGHT             70
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+psPlaneTransform *PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM()
+{
+    psPlaneTransform *pt = psPlaneTransformAlloc(1, 1);
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+    return(pt);
+}
+
+psPlaneDistort *PS_CREATE_4D_IDENTITY_PLANE_DISTORT()
+{
+    psPlaneDistort *pd = psPlaneDistortAlloc(1, 1, 1, 1);
+    pd->x->coeff[1][0][0][0] = 1.0;
+    pd->y->coeff[0][1][0][0] = 1.0;
+    return(pd);
+}
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    cell->hdu = pmHDUAlloc("cellExtName");
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = psMemDecrRefCounter((psPtr) generateSimpleReadout(cell));
+    }
+
+    // First try to read data from ../dataFiles, then try dataFiles.
+    bool rc = pmConfigFileRead(&cell->hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        rc = pmConfigFileRead(&cell->hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            diag("pmConfigFileRead() was unsuccessful (from generateSimpleCell())");
+	}
+    }
+
+    cell->hdu->images = psArrayAlloc(NUM_HDUS);
+    cell->hdu->masks = psArrayAlloc(NUM_HDUS);
+    cell->hdu->weights = psArrayAlloc(NUM_HDUS);
+    for (int k = 0 ; k < NUM_HDUS ; k++) {
+        cell->hdu->images->data[k]  = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        cell->hdu->masks->data[k]   = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        cell->hdu->weights->data[k] = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(cell->hdu->images->data[k], (float) (BASE_IMAGE+k));
+        psImageInit(cell->hdu->masks->data[k], (psU8) (BASE_MASK+k));
+        psImageInit(cell->hdu->weights->data[k], (float) (BASE_WEIGHT+k));
+    }
+
+    //XXX: Should the region be set some other way?  Like through the various config files?
+    psRegion *region = psRegionAlloc(0.0, 0.0, 0.0, 0.0);
+    // You shouldn't have to remove the key from the metadata.  Find out how to simply change the key value.
+    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC");
+    psMetadataAddPtr(cell->concepts, PS_LIST_TAIL|PS_META_REPLACE, "CELL.TRIMSEC", PS_DATA_REGION, "I am a region", region);
+    psFree(region);
+    return(cell);
+}
+
+/******************************************************************************
+generateSimpleChip(): This function generates a pmChip data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmChip *generateSimpleChip(pmFPA *fpa)
+{
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    chip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    chip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    psMetadataAddS32(chip->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(chip->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    chip->hdu = pmHDUAlloc("chipExtName");
+
+    bool rc = pmConfigFileRead(&chip->hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        rc = pmConfigFileRead(&chip->hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            diag("pmConfigFileRead() was unsuccessful (from generateSimpleChip())");
+	}
+    }
+
+    psArrayRealloc(chip->cells, NUM_CELLS);
+    for (int i = 0 ; i < NUM_CELLS ; i++) {
+        chip->cells->data[i] = psMemDecrRefCounter((psPtr) generateSimpleCell(chip));
+    }
+    return(chip);
+}
+
+/******************************************************************************
+generateSimpleFPA(): This function generates a pmFPA data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmFPA* generateSimpleFPA(psMetadata *camera)
+{
+    pmFPA* fpa = pmFPAAlloc(camera);
+    fpa->fromTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toSky = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+    psMetadataAddS32(fpa->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    if (camera != NULL) {
+        psMetadataAddS32((psMetadata *) fpa->camera, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    }
+    psMetadataAddS32(fpa->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    fpa->hdu = pmHDUAlloc("fpaExtName");
+    bool rc = pmConfigFileRead(&fpa->hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        rc = pmConfigFileRead(&fpa->hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            diag("pmConfigFileRead() was unsuccessful (from generateSimpleFPA())");
+	}
+    }
+
+    psArrayRealloc(fpa->chips, NUM_CHIPS);
+    for (int i = 0 ; i < NUM_CHIPS ; i++) {
+        fpa->chips->data[i] = psMemDecrRefCounter((psPtr) generateSimpleChip(fpa));
+    }
+    pmConceptsBlankFPA(fpa);
+    return(fpa);
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(73);
+
+
+    // ----------------------------------------------------------------------
+    // pmHDUFromFPA() tests
+    // Call pmHDUFromFPA() with NULL input params
+    {
+        psMemId id = psMemGetId();
+        pmHDU *hdu = pmHDUFromFPA(NULL);
+        ok(hdu == NULL, "pmHDUFromFPA(NULL) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmHDUFromFPA() with acceptable input params
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        pmHDU *hdu = pmHDUFromFPA(fpa);
+        ok(hdu == fpa->hdu, "pmHDUFromFPA(NULL) returned the correct pmHDU of an pmFPA struct");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmHDUFromChip() tests
+    // Call pmHDUFromChip() with NULL input params
+    {
+        psMemId id = psMemGetId();
+        pmHDU *hdu = pmHDUFromChip(NULL);
+        ok(hdu == NULL, "pmHDUFromChip(NULL) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmHDUFromChip() with acceptable input params
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        pmHDU *hdu = pmHDUFromChip(chip);
+        ok(hdu == chip->hdu, "pmHDUFromChip() returned the correct pmHDU of an pmChip struct");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmHDUFromChip() with acceptable input params
+    // Set chip->hdu to NULL, verify chip->parent->hdu is returned
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        psFree(chip->hdu);
+        chip->hdu = NULL;
+        pmHDU *hdu = pmHDUFromChip(chip);
+        ok(hdu == chip->parent->hdu, "pmHDUFromChip() returned the correct pmHDU of an pmChip struct");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmHDUFromCell() tests
+    // Call pmHDUFromCell() with NULL input params
+    {
+        psMemId id = psMemGetId();
+        pmHDU *hdu = pmHDUFromCell(NULL);
+        ok(hdu == NULL, "pmHDUFromCell(NULL) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmHDUFromCell() with acceptable input params
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        pmHDU *hdu = pmHDUFromCell(cell);
+        ok(hdu == cell->hdu, "pmHDUFromCell() returned the correct pmHDU of an pmCell struct");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmHDUFromCell() with acceptable input params
+    // Set cell->hdu to NULL, verify cell->parent->hdu is returned
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        psFree(cell->hdu);
+        cell->hdu = NULL;
+        pmHDU *hdu = pmHDUFromCell(cell);
+        ok(hdu == cell->parent->hdu, "pmHDUFromCell() returned the correct pmHDU of an pmCell struct");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmHDUFromReadout() tests
+    // Call pmHDUFromReadout() with NULL input params
+    {
+        psMemId id = psMemGetId();
+        pmHDU *hdu = pmHDUFromReadout(NULL);
+        ok(hdu == NULL, "pmHDUFromReadout(NULL) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmHDUFromReadout() with acceptable input params
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        pmReadout *readout = cell->readouts->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        ok(readout != NULL, "Allocated a pmReadout successfully");
+        pmHDU *hdu = pmHDUFromReadout(readout);
+        ok(hdu == readout->parent->hdu, "pmHDUFromReadout() returned the correct pmHDU of an pmReadout struct");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmHDUGetLowest() tests
+    // Call pmHDUGetLowest() with all NULL inputs
+    {
+        psMemId id = psMemGetId();
+        pmHDU *hdu = pmHDUGetLowest(NULL, NULL, NULL);
+        ok(hdu == NULL, "pmHDUFromReadout(NULL, NULL, NULL)");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmHDUGetLowest() with all acceptable inputs
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        pmHDU *hdu = pmHDUGetLowest(fpa, chip, cell);
+        ok(hdu == cell->hdu, "pmHDUGetLowest(fpa, chip, cell)");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmHDUGetLowest() with all (fpa, chip, NULL) inputs
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        pmHDU *hdu = pmHDUGetLowest(fpa, chip, NULL);
+        ok(hdu == chip->hdu, "pmHDUGetLowest(fpa, chip, NULL)");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmHDUGetLowest() with all (fpa, NULL, NULL) inputs
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        pmHDU *hdu = pmHDUGetLowest(fpa, NULL, NULL);
+        ok(hdu == fpa->hdu, "pmHDUGetLowest(fpa, NULL, NULL)");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    //pmHDUGetHighest() tests
+    // Call pmHDUGetHighest() with all NULL inputs
+    {
+        psMemId id = psMemGetId();
+        pmHDU *hdu = pmHDUGetHighest(NULL, NULL, NULL);
+        ok(hdu == NULL, "pmHDUFromReadout(NULL, NULL, NULL)");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmHDUGetHighest() with all acceptable inputs
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        pmHDU *hdu = pmHDUGetHighest(fpa, chip, cell);
+        ok(hdu == fpa->hdu, "pmHDUGetHighest(fpa, chip, cell)");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmHDUGetHighest() with (NULL, chip, cell) inputs
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        pmHDU *hdu = pmHDUGetHighest(NULL, chip, cell);
+        ok(hdu == chip->hdu, "pmHDUGetHighest(NULL, chip, cell)");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmHDUGetHighest() with (NULL, NULL, cell) inputs
+    {
+        psMemId id = psMemGetId();
+        // Generate the pmFPA heirarchy
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA* fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        ok(fpa != NULL, "Allocated a pmFPA successfully");
+        ok(chip != NULL, "Allocated a pmChip successfully");
+        ok(cell != NULL, "Allocated a pmCell successfully");
+        pmHDU *hdu = pmHDUGetHighest(NULL, NULL, cell);
+        ok(hdu == cell->hdu, "pmHDUGetHighest(NULL, NULL, cell)");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmReadoutFake.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmReadoutFake.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmReadoutFake.c	(revision 22158)
@@ -0,0 +1,177 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    Only one function in the source code: pmReadoutFakeFromSources()
+
+    pmReadoutFakeFromSources() is only tested with bad input parameters.
+    Tests must be written to exercise it with legitimate input sources, and
+    verify the output.
+*/
+
+#define MISC_NUM                32
+#define MISC_NAME               "META00"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           5
+#define TEST_NUM_COLS           8
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#define NUM_SOURCES		5
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    psImageInit(readout->image, 1.0);
+    psImageInit(readout->mask, 2);
+    psImageInit(readout->weight, 3.0);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(11);
+
+    // ------------------------------------------------------------------------
+    // pmReadoutFakeFromSources() tests
+    // bool pmReadoutFakeFromSources(pmReadout *readout, int numCols, int numRows, const psArray *sources,
+    //                               const psVector *xOffset, const psVector *yOffset, const pmPSF *psf,
+    //                               float minFlux, int radius, bool circularise)
+    //
+    // Call pmReadoutFakeFromSources() with bad input parameters.
+    {
+        psMemId id = psMemGetId();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        psVector *xOffset = psVectorAlloc(NUM_SOURCES, PS_TYPE_S32);
+        psVector *yOffset = psVectorAlloc(NUM_SOURCES, PS_TYPE_S32);
+        psVector *xOffsetBig = psVectorAlloc(NUM_SOURCES*2, PS_TYPE_S32);
+        psVector *xOffsetF32 = psVectorAlloc(NUM_SOURCES, PS_TYPE_F32);
+        psVector *yOffsetF32 = psVectorAlloc(NUM_SOURCES, PS_TYPE_F32);
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0; i < sources->n ; i++) {
+            sources->data[i] = pmSourceAlloc();
+        }
+        pmPSFOptions *psfOptions = pmPSFOptionsAlloc();
+        psfOptions->psfTrendNx = 1;
+        psfOptions->psfTrendNy = 2;
+        psfOptions->psfFieldNx = 3;
+        psfOptions->psfFieldNy = 4;
+        psfOptions->psfFieldXo = 5;
+        psfOptions->psfFieldYo = 6;
+        pmModelClassInit();
+        psfOptions->type = pmModelClassGetType("PS_MODEL_GAUSS");
+        pmPSF *psf = pmPSFAlloc(psfOptions);
+
+        // NULL pmReadout input parameter
+        bool rc = pmReadoutFakeFromSources(NULL, TEST_NUM_COLS, TEST_NUM_ROWS, sources,
+                                           xOffset, yOffset, psf, 0.0, 1.0, false);
+        ok(rc == false, "pmReadoutFakeFromSources() returned FALSE with pmReadout input parameter");
+
+        // Non-positive numCols input parameter
+        rc = pmReadoutFakeFromSources(readout, 0, TEST_NUM_ROWS, sources,
+                                           xOffset, yOffset, psf, 0.0, 1.0, false);
+        ok(rc == false, "pmReadoutFakeFromSources() returned FALSE with Non-positive numCols input parameter");
+
+        // Non-positive numRows input parameter
+        rc = pmReadoutFakeFromSources(readout, TEST_NUM_COLS, 0, sources,
+                                           xOffset, yOffset, psf, 0.0, 1.0, false);
+        ok(rc == false, "pmReadoutFakeFromSources() returned FALSE with Non-positive numRow input parameter");
+
+        // NULL pmSource input parameter
+        rc = pmReadoutFakeFromSources(readout, TEST_NUM_COLS, TEST_NUM_ROWS, NULL,
+                                           xOffset, yOffset, psf, 0.0, 1.0, false);
+        ok(rc == false, "pmReadoutFakeFromSources() returned FALSE with pmSource input parameter");
+
+        // NULL pmPSF input parameter
+        rc = pmReadoutFakeFromSources(readout, TEST_NUM_COLS, TEST_NUM_ROWS, sources,
+                                           xOffset, yOffset, NULL, 0.0, 1.0, false);
+        ok(rc == false, "pmReadoutFakeFromSources() returned FALSE with input parameter");
+
+        // NULL incorrect type xOffset input parameter
+        rc = pmReadoutFakeFromSources(readout, TEST_NUM_COLS, TEST_NUM_ROWS, sources,
+                                           xOffsetF32, yOffset, psf, 0.0, 1.0, false);
+        ok(rc == false, "pmReadoutFakeFromSources() returned FALSE with incorrect type xOffset input parameter");
+
+        // NULL incorrect type yOffset input parameter
+        rc = pmReadoutFakeFromSources(readout, TEST_NUM_COLS, TEST_NUM_ROWS, sources,
+                                           xOffset, yOffsetF32, psf, 0.0, 1.0, false);
+        ok(rc == false, "pmReadoutFakeFromSources() returned FALSE with incorrect type yOffset input parameter");
+
+        // NULL incorrect size xOffset input parameter
+        rc = pmReadoutFakeFromSources(readout, TEST_NUM_COLS, TEST_NUM_ROWS, sources,
+                                           xOffsetBig, yOffset, psf, 0.0, 1.0, false);
+        ok(rc == false, "pmReadoutFakeFromSources() returned FALSE with incorrect size xOffset input parameter");
+
+        psFree(readout);
+        psFree(xOffset);
+        psFree(yOffset);
+        psFree(xOffsetBig);
+        psFree(xOffsetF32);
+        psFree(yOffsetF32);
+        psFree(sources);
+        psFree(psfOptions);
+        psFree(psf);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmReadoutFakeFromSources() with acceptable input parameters.
+    {
+        psMemId id = psMemGetId();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        psVector *xOffset = psVectorAlloc(NUM_SOURCES, PS_TYPE_S32);
+        psVector *yOffset = psVectorAlloc(NUM_SOURCES, PS_TYPE_S32);
+        psVector *xOffsetF32 = psVectorAlloc(NUM_SOURCES, PS_TYPE_F32);
+        psVector *yOffsetF32 = psVectorAlloc(NUM_SOURCES, PS_TYPE_F32);
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0; i < sources->n ; i++) {
+            sources->data[i] = pmSourceAlloc();
+        }
+        pmPSFOptions *psfOptions = pmPSFOptionsAlloc();
+        psfOptions->psfTrendNx = 1;
+        psfOptions->psfTrendNy = 2;
+        psfOptions->psfFieldNx = 3;
+        psfOptions->psfFieldNy = 4;
+        psfOptions->psfFieldXo = 5;
+        psfOptions->psfFieldYo = 6;
+        pmModelClassInit();
+        psfOptions->type = pmModelClassGetType("PS_MODEL_GAUSS");
+        pmPSF *psf = pmPSFAlloc(psfOptions);
+
+        bool rc = pmReadoutFakeFromSources(readout, TEST_NUM_COLS, TEST_NUM_ROWS, sources,
+                                           xOffset, yOffset, psf, 0.0, 1.0, false);
+        ok(rc == true, "pmReadoutFakeFromSources() returned TRUE with acceptable input parameters");
+
+        psFree(readout);
+        psFree(xOffset);
+        psFree(yOffset);
+        psFree(xOffsetF32);
+        psFree(yOffsetF32);
+        psFree(sources);
+        psFree(psfOptions);
+        psFree(psf);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmReadoutStack.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmReadoutStack.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/camera/tap_pmReadoutStack.c	(revision 22158)
@@ -0,0 +1,250 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    All functions are tested.
+*/
+
+#define CELL_ALLOC_NAME		"CellName"
+#define MISC_NUM		32
+#define MISC_NAME		"META00"
+#define NUM_BIAS_DATA		10
+#define TEST_NUM_ROWS		5
+#define TEST_NUM_COLS		8
+#define NUM_INPUTS		10
+#define NUM_READOUTS		4
+#define VERBOSE			0
+#define ERR_TRACE_LEVEL		10
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    psImageInit(readout->image, 1.0);
+    psImageInit(readout->mask, 2);
+    psImageInit(readout->weight, 3.0);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(int ID)
+{
+    pmCell *cell = pmCellAlloc(NULL, CELL_ALLOC_NAME);
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    cell->hdu = pmHDUAlloc(NULL);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psRegion *region = psRegionAlloc(0.0, (float) (10 + ID), 0.0, (float) (20 + ID));
+    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC");
+    psMetadataAddPtr(cell->concepts, PS_LIST_TAIL|PS_META_REPLACE, "CELL.TRIMSEC", PS_DATA_REGION, "I am a region", region);
+    psFree(region);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = psMemDecrRefCounter((psPtr) generateSimpleReadout(cell));
+    }
+
+    return(cell);
+}
+
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(29);
+
+    // ------------------------------------------------------------------------
+    // pmReadoutUpdateSize() tests
+    // Call pmReadoutUpdateSize() with NULL pmReadout input parameter.
+    {
+        psMemId id = psMemGetId();
+        bool rc = pmReadoutUpdateSize(NULL, 0, 0, TEST_NUM_COLS, TEST_NUM_ROWS, false);
+        ok(rc == false, "pmReadoutUpdateSize() returned FALSE with NULL pmReadout input parameter");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmReadoutUpdateSize() with acceptable input parameters (mask == false).
+    {
+        psMemId id = psMemGetId();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        bool rc = pmReadoutUpdateSize(readout, 0, 0, 2*TEST_NUM_COLS, 2*TEST_NUM_ROWS, false);
+        ok(rc == true, "pmReadoutUpdateSize() returned TRUE with acceptable input parameters");
+        ok(readout->image->numCols == (2*TEST_NUM_COLS) &&
+           readout->image->numRows == (2*TEST_NUM_ROWS), "pmReadoutUpdateSize() generated the correct size pmReadout->image");
+        bool errorFlag = false;
+        for (int i = 0 ; i < readout->image->numRows ; i++) {
+            for (int j = 0 ; j < readout->image->numCols ; j++) {
+                psF32 correctF32;
+                if (i < TEST_NUM_ROWS && j < TEST_NUM_COLS) {
+                   correctF32 = 1.0;
+                } else {
+                   correctF32 = 0.0;
+                }
+                if (readout->image->data.F32[i][j] != correctF32) {
+                    diag("ERROR: readout->image[%d][%d] is %.2f, should be %.2f", i, j, readout->image->data.F32[i][j], correctF32);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "pmReadoutUpdateSize() initialized pmReadout->image to zero");
+        ok(readout->mask->numCols == (TEST_NUM_COLS) &&
+           readout->mask->numRows == (TEST_NUM_ROWS), "pmReadoutUpdateSize() generated the correct size pmReadout->mask");
+
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmReadoutUpdateSize() with acceptable input parameters (mask == true).
+    {
+        psMemId id = psMemGetId();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        bool rc = pmReadoutUpdateSize(readout, 0, 0, 2*TEST_NUM_COLS, 2*TEST_NUM_ROWS, true);
+        ok(rc == true, "pmReadoutUpdateSize() returned TRUE with acceptable input parameters");
+        ok(readout->image->numCols == (2*TEST_NUM_COLS) &&
+           readout->image->numRows == (2*TEST_NUM_ROWS), "pmReadoutUpdateSize() generated the correct size pmReadout->image");
+        bool errorFlag = false;
+        for (int i = 0 ; i < readout->image->numRows ; i++) {
+            for (int j = 0 ; j < readout->image->numCols ; j++) {
+                psF32 correctF32;
+                if (i < TEST_NUM_ROWS && j < TEST_NUM_COLS) {
+                   correctF32 = 1.0;
+                } else {
+                   correctF32 = 0.0;
+                }
+                if (readout->image->data.F32[i][j] != correctF32) {
+                    diag("ERROR: readout->image[%d][%d] is %.2f, should be %.2f", i, j, readout->image->data.F32[i][j], correctF32);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "pmReadoutUpdateSize() initialized pmReadout->image to zero");
+        ok(readout->mask->numCols == (2*TEST_NUM_COLS) &&
+           readout->mask->numRows == (2*TEST_NUM_ROWS), "pmReadoutUpdateSize() generated the correct size pmReadout->mask");
+        errorFlag = false;
+        for (int i = 0 ; i < readout->mask->numRows ; i++) {
+            for (int j = 0 ; j < readout->mask->numCols ; j++) {
+                psF32 correctU8;
+                if (i < TEST_NUM_ROWS && j < TEST_NUM_COLS) {
+                   correctU8 = 2;
+                } else {
+                   correctU8 = 0;
+                }
+                if (readout->mask->data.U8[i][j] != correctU8) {
+                    diag("ERROR: readout->mask[%d][%d] is %d, should be %d", i, j, readout->mask->data.U8[i][j], correctU8);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "pmReadoutUpdateSize() initialized pmReadout->mask to zero");
+
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // ------------------------------------------------------------------------
+    // pmReadoutStackValidate() tests
+    // Call pmReadoutStackValidate() with bad input parameters.
+    {
+        psMemId id = psMemGetId();
+        int minInputCols, maxInputCols, minInputRows, maxInputRows, numCols, numRows;
+        minInputCols = maxInputCols = minInputRows = maxInputRows = numCols = numRows = 0;
+        bool rc = pmReadoutStackValidate(&minInputCols, &maxInputCols, &minInputRows, &maxInputRows,
+                                         &numCols, &numRows, NULL);
+        psArray *inputs = psArrayAlloc(NUM_INPUTS);
+        for (int i = 0 ; i < NUM_INPUTS ; i++) {
+            inputs->data[i] = (psPtr *) generateSimpleReadout(NULL);
+        }
+
+        // NULL psArray input parameter
+        rc = pmReadoutStackValidate(&minInputCols, &maxInputCols, &minInputRows, &maxInputRows,
+                                   &numCols, &numRows, NULL);
+        ok(rc == false, "pmReadoutStackValidate() returned FALSE with NULL pmArray input parameter");
+
+        // NULL minInputColsPtr
+        rc = pmReadoutStackValidate(NULL, &maxInputCols, &minInputRows, &maxInputRows,
+                                    &numCols, &numRows, inputs);
+        ok(rc == false, "pmReadoutStackValidate() returned FALSE with NULL minInputColsPtr input parameter");
+
+        // NULL maxInputColsPtr
+        rc = pmReadoutStackValidate(&minInputCols, NULL, &minInputRows, &maxInputRows,
+                                    &numCols, &numRows, inputs);
+        ok(rc == false, "pmReadoutStackValidate() returned FALSE with NULL maxInputColsPtr input parameter");
+
+        // NULL minInputRowsPtr
+        rc = pmReadoutStackValidate(&minInputCols, &maxInputCols, NULL, &maxInputRows,
+                                    &numCols, &numRows, inputs);
+        ok(rc == false, "pmReadoutStackValidate() returned FALSE with NULL minInputRowsPtr input parameter");
+
+        // NULL maxInputRowsPtr
+        rc = pmReadoutStackValidate(&minInputCols, &maxInputCols, &minInputRows, NULL,
+                                    &numCols, &numRows, inputs);
+        ok(rc == false, "pmReadoutStackValidate() returned FALSE with NULL maxInputRowsPtr input parameter");
+
+        // NULL numColsPtr
+        rc = pmReadoutStackValidate(&minInputCols, &maxInputCols, &minInputRows, &maxInputRows,
+                                    NULL, &numRows, inputs);
+        ok(rc == false, "pmReadoutStackValidate() returned FALSE with NULL numColsPtr input parameter");
+
+        // NULL numRowsPtr
+        rc = pmReadoutStackValidate(&minInputCols, &maxInputCols, &minInputRows, &maxInputRows,
+                                    &numCols, NULL, inputs);
+        ok(rc == false, "pmReadoutStackValidate() returned FALSE with NULL numRowsPtr input parameter");
+
+        psFree(inputs);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmReadoutStackValidate() with acceptable input parameters.
+    {
+        psMemId id = psMemGetId();
+        int minInputCols, maxInputCols, minInputRows, maxInputRows, numCols, numRows;
+        minInputCols = maxInputCols = minInputRows = maxInputRows = numCols = numRows = 0;
+        pmCell *cells[NUM_INPUTS];
+        psArray *inputs = psArrayAlloc(NUM_INPUTS);
+        for (int i = 0 ; i < NUM_INPUTS ; i++) {
+            cells[i] = generateSimpleCell(i);
+            inputs->data[i] = (psPtr *) generateSimpleReadout(cells[i]);
+        }
+        bool rc = pmReadoutStackValidate(&minInputCols, &maxInputCols, &minInputRows, &maxInputRows,
+                                   &numCols, &numRows, inputs);
+        ok(rc == true, "pmReadoutStackValidate() returned TRUE with acceptable input parameters");
+        ok(minInputCols == 0, "pmReadoutStackValidate() set minInputCols correctly");
+        ok(maxInputCols == TEST_NUM_COLS, "pmReadoutStackValidate() set maxInputCols correctly");
+        ok(minInputRows == 0, "pmReadoutStackValidate() set minInputRows correctly");
+        ok(maxInputRows == TEST_NUM_ROWS, "pmReadoutStackValidate() set maxInputRows correctly");
+        ok(numCols == (10 + NUM_INPUTS - 1), "pmReadoutStackValidate() set numCols correctly");
+        ok(numRows == (20 + NUM_INPUTS - 1), "pmReadoutStackValidate() set numRows correctly");
+
+        for (int i = 0 ; i < NUM_INPUTS ; i++) {
+            psFree(cells[i]);
+        }
+        psFree(inputs);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/concepts/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/concepts/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/concepts/.cvsignore	(revision 22158)
@@ -0,0 +1,4 @@
+.deps
+.libs
+Makefile
+Makefile.in
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/concepts/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/concepts/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/concepts/Makefile.am	(revision 22158)
@@ -0,0 +1,29 @@
+AM_CPPFLAGS = \
+	$(SRCINC) \
+	-I$(top_srcdir)/test/tap/src \
+	-I$(top_srcdir)/test/pstap/src \
+	$(PSMODULES_CFLAGS)
+
+AM_LDFLAGS = \
+	$(top_builddir)/src/libpsmodules.la  \
+	$(top_builddir)/test/tap/src/libtap.la \
+	$(top_builddir)/test/pstap/src/libpstap.la \
+	$(PSMODULES_LIBS)
+
+TEST_PROGS = \
+	tap_pmConcepts \
+	tap_pmConceptsUpdate \
+	tap_pmConceptsPhotcode \
+	tap_pmConceptsAverage
+
+if BUILD_TESTS
+bin_PROGRAMS = $(TEST_PROGS)
+TESTS = $(TEST_PROGS)
+else
+check_PROGRAMS = $(TEST_PROGS)
+endif
+
+CLEANFILES = $(check_DATA) temp/* core core.* *~ *.bb *.bbg *.da gmon.out
+
+test: check
+	$(top_srcdir)/test/test.pl
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/concepts/tap_pmConcepts.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/concepts/tap_pmConcepts.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/concepts/tap_pmConcepts.c	(revision 22158)
@@ -0,0 +1,499 @@
+    /** @file tst_pmConcepts.c
+ *
+ *  @brief Contains the tests for pmConcepts.c:
+ *
+ *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-01-02 20:49:56 $
+*   pmConceptSpecAlloc()
+    pmConceptsList()
+*   pmConceptGetRequired()
+*   pmConceptSetRequired()
+    pmConceptRegister()
+    pmConceptsRead()
+*   pmConceptsBlankFPA()
+    pmConceptsReadFPA()
+    pmConceptsWriteFPA()
+*   pmConceptsBlankChip()
+    pmConceptsReadChip()
+    pmConceptsWriteChip()
+*   pmConceptsBlankCell()
+    pmConceptsReadCell()
+    pmConceptsWriteCell()
+*   pmConceptsInit()
+*   pmConceptsDone()
+    pmFPACopyConcepts()
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+psMetadataItem *dummyConceptParser(
+    const psMetadataItem *concept,
+    const psMetadataItem *pattern,
+    pmConceptSource source,
+    const psMetadata *cameraFormat,
+    const pmFPA *fpa,
+    const pmChip *chip,
+    const pmCell *cell)
+{
+    if (concept == NULL ||
+        pattern == NULL ||
+        source == PM_CONCEPT_SOURCE_NONE ||
+        cameraFormat == NULL ||
+        fpa == NULL ||
+        chip == NULL ||
+        cell == NULL) {
+        printf("dummyConceptParser() args are NULL\n");
+    }
+    return(NULL);
+}
+
+// FPA.RA and FPA.DEC
+psMetadataItem *dummyConceptFormatter(
+    const psMetadataItem *concept,
+    pmConceptSource source,
+    const psMetadata *cameraFormat,
+    const pmFPA *fpa,
+    const pmChip *chip,
+    const pmCell *cell)
+{
+    if (concept == NULL ||
+        source == PM_CONCEPT_SOURCE_NONE ||
+        cameraFormat == NULL ||
+        fpa == NULL ||
+        chip == NULL ||
+        cell == NULL) {
+        printf("dummyConceptFormatter() args are NULL\n");
+    }
+    return(NULL);
+}
+
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel(".", ERR_TRACE_LEVEL);
+    plan_tests(126);
+    
+    // --------------------------------------------------------------------
+    // Tests for pmConceptSpecAlloc()
+    // Acceptable input parameters.
+    {
+        psMemId id = psMemGetId();
+        psMetadataItem *blank = psMetadataItemAlloc("myItem1", PS_DATA_BOOL, "I am a boolean", true);
+        pmConceptSpec *tmp = pmConceptSpecAlloc(blank, dummyConceptParser,
+            dummyConceptFormatter, true);
+        ok(tmp != NULL, "pmConceptSpecAlloc() returned non-NULL");
+        skip_start(tmp == NULL, 4, "Skipping tests because pmConceptSpecAlloc() returned NULL");
+        ok(tmp->blank == blank, "pmConceptSpecAlloc() set the ->blank member correctly");
+        ok(tmp->parse == dummyConceptParser, "pmConceptSpecAlloc() set the ->parse member correctly");
+        ok(tmp->format == dummyConceptFormatter, "pmConceptSpecAlloc() set the ->format member correctly");
+        ok(tmp->required == true, "pmConceptSpecAlloc() set the ->required member correctly");
+        skip_end();
+        psFree(tmp);
+        psFree(blank);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // NULL input parameters.
+    {
+        psMemId id = psMemGetId();
+        pmConceptSpec *tmp = pmConceptSpecAlloc(NULL, NULL, NULL, false);
+        ok(tmp != NULL, "pmConceptSpecAlloc() returned non-NULL with NULL inputs");
+        psFree(tmp);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // --------------------------------------------------------------------
+    // Tests for pmConceptGetRequired() and pmConceptSetRequired()
+    // Acceptable input parameters.
+    // We get the "required" for FPA.TELESCOPE, ensure that it is false
+    // then set it to true, then ensure that it is true.
+    {
+        psMemId id = psMemGetId();
+        bool tmpBool = pmConceptGetRequired("FPA.TELESCOPE", PM_FPA_LEVEL_FPA);
+        ok (tmpBool == false, "pmConceptGetRequired() returned true for FPA.TELESCOPE");
+        tmpBool = pmConceptSetRequired("FPA.TELESCOPE", PM_FPA_LEVEL_FPA, true);
+        ok (tmpBool == true, "pmConceptSetRequired() returned true for FPA.TELESCOPE");
+        tmpBool = pmConceptGetRequired("FPA.TELESCOPE", PM_FPA_LEVEL_FPA);
+        ok (tmpBool == true, "pmConceptGetRequired() returned true for FPA.TELESCOPE");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test pmConceptGetRequired() with a few incorrect concept names
+    // and/or levels.
+    {
+        psMemId id = psMemGetId();
+        bool tmpBool = pmConceptGetRequired("FPA.TELESCOPE", PM_FPA_LEVEL_CHIP);
+        ok (tmpBool == false, "pmConceptGetRequired() returned false for FPA.TELESCOPE with wrong level (CHIP)");
+        tmpBool = pmConceptGetRequired("FPA.TELESCOPE", PM_FPA_LEVEL_CELL);
+        ok (tmpBool == false, "pmConceptGetRequired() returned false for FPA.TELESCOPE with wrong level (CELL)");
+        tmpBool = pmConceptGetRequired("FPA.BADCONCEPTNAME", PM_FPA_LEVEL_FPA);
+        ok (tmpBool == false, "pmConceptGetRequired() returned false for FPA.BADCONCEPTNAME");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // --------------------------------------------------------------------
+    // Tests for pmConceptsInit(), pmConceptsDone()
+    // We determine if pmConceptsInit() was successful by looking at the
+    // "required" for the CHIP.XPARITY concept at level PM_FPA_LEVEL_CHIP
+    {
+        psMemId id = psMemGetId();
+        pmConceptsDone();
+        // pmConceptsInit() should return TRUE after pmConceptsDone() is called
+        ok(true == pmConceptsInit(), "pmConceptsInit() returned TRUE");
+
+        // FPA concepts
+        ok(false == pmConceptGetRequired("FPA.TELESCOPE", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.TELESCOPE at level: FPA");
+        ok(false == pmConceptGetRequired("FPA.INSTRUMENT", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.INSTRUMENT at level: FPA");
+        ok(false == pmConceptGetRequired("FPA.DETECTOR", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.DETECTOR at level: FPA");
+        ok(false == pmConceptGetRequired("FPA.CAMERA", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.CAMERA at level: FPA");
+        ok(false == pmConceptGetRequired("FPA.FOCUS", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.FOCUS at level: FPA");
+        ok(false == pmConceptGetRequired("FPA.AIRMASS", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.AIRMASS at level: FPA");
+        ok(false == pmConceptGetRequired("FPA.FILTERID", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.FILTERID at level: FPA");
+        ok(false == pmConceptGetRequired("FPA.FILTER", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.FILTER at level: FPA");
+        ok(false == pmConceptGetRequired("FPA.POSANGLE", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.POSANGLE at level: FPA");
+        ok(false == pmConceptGetRequired("FPA.RADECSYS", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.RADECSYS at level: FPA");
+        ok(false == pmConceptGetRequired("FPA.RA", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.RA at level: FPA");
+        ok(false == pmConceptGetRequired("FPA.DEC", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.DEC at level: FPA");
+        ok(false == pmConceptGetRequired("FPA.OBSTYPE", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.OBSTYPE at level: FPA");
+        ok(false == pmConceptGetRequired("FPA.OBJECT", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.OBJECT at level: FPA");
+        ok(false == pmConceptGetRequired("FPA.ALT", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.ALT at level: FPA");
+        ok(false == pmConceptGetRequired("FPA.AZ", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.AZ at level: FPA");
+        ok(false == pmConceptGetRequired("FPA.TIMESYS", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.TIMESYS at level: FPA");
+        ok(false == pmConceptGetRequired("FPA.TIME", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.TIME at level: FPA");
+        ok(false == pmConceptGetRequired("FPA.TEMP", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.TEMP at level: FPA");
+        ok(false == pmConceptGetRequired("FPA.EXPOSURE", PM_FPA_LEVEL_FPA),
+          "pmConceptGetRequired() returned false for FPA.EXPOSURE at level: FPA");
+
+        // Chip concepts
+        ok(true == pmConceptGetRequired("CHIP.XPARITY", PM_FPA_LEVEL_CHIP),
+          "pmConceptGetRequired() returned true for CHIP.XPARITY at level: CHIP");
+        ok(true == pmConceptGetRequired("CHIP.YPARITY", PM_FPA_LEVEL_CHIP),
+          "pmConceptGetRequired() returned true for CHIP.YPARITY at level: CHIP");
+        ok(true == pmConceptGetRequired("CHIP.X0", PM_FPA_LEVEL_CHIP),
+          "pmConceptGetRequired() returned true for CHIP.X0 at level: CHIP");
+        ok(true == pmConceptGetRequired("CHIP.Y0", PM_FPA_LEVEL_CHIP),
+          "pmConceptGetRequired() returned true for CHIP.Y0 at level: CHIP");
+        ok(true == pmConceptGetRequired("CHIP.XSIZE", PM_FPA_LEVEL_CHIP),
+          "pmConceptGetRequired() returned true for CHIP.XSIZE at level: CHIP");
+        ok(true == pmConceptGetRequired("CHIP.YSIZE", PM_FPA_LEVEL_CHIP),
+          "pmConceptGetRequired() returned true for CHIP.YSIZE at level: CHIP");
+        ok(false == pmConceptGetRequired("CHIP.TEMP", PM_FPA_LEVEL_CHIP),
+          "pmConceptGetRequired() returned true for CHIP.TEMP at level: CHIP");
+
+        // Cell concepts
+        ok(true == pmConceptGetRequired("CELL.GAIN", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned true for CELL.GAIN at level: CELL");
+        ok(true == pmConceptGetRequired("CELL.READNOISE", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned true for CELL.READNOISE at level: CELL");
+        ok(true == pmConceptGetRequired("CELL.SATURATION", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned true for CELL.SATURATION at level: CELL");
+        ok(true == pmConceptGetRequired("CELL.BAD", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned true for CELL.BAD at level: CELL");
+        ok(true == pmConceptGetRequired("CELL.XPARITY", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned true for CELL.XPARITY at level: CELL");
+        ok(true == pmConceptGetRequired("CELL.YPARITY", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned true for CELL.YPARITY at level: CELL");
+        ok(true == pmConceptGetRequired("CELL.READDIR", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned true for CELL.READDIR at level: CELL");
+        ok(false == pmConceptGetRequired("CELL.EXPOSURE", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned false for CELL.EXPOSURE at level: CELL");
+        ok(false == pmConceptGetRequired("CELL.DARKTIME", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned false for CELL.DARKTIME at level: CELL");
+        ok(true == pmConceptGetRequired("CELL.TRIMSEC", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned true for CELL.TRIMSEC at level: CELL");
+        ok(true == pmConceptGetRequired("CELL.BIASSEC", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned true for CELL.BIASSEC at level: CELL");
+        ok(true == pmConceptGetRequired("CELL.XBIN", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned true for CELL.XBIN at level: CELL");
+        ok(true == pmConceptGetRequired("CELL.YBIN", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned true for CELL.YBIN at level: CELL");
+        ok(false == pmConceptGetRequired("CELL.TIMESYS", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned false for CELL.TIMESYS at level: CELL");
+        ok(false == pmConceptGetRequired("CELL.TIME", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned false for CELL.TIME at level: CELL");
+        ok(true == pmConceptGetRequired("CELL.X0", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned true for CELL.X0 at level: CELL");
+        ok(true == pmConceptGetRequired("CELL.Y0", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned true for CELL.Y0 at level: CELL");
+        ok(true == pmConceptGetRequired("CELL.XSIZE", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned true for CELL.XSIZE at level: CELL");
+        ok(true == pmConceptGetRequired("CELL.YSIZE", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned true for CELL.YSIZE at level: CELL");
+        ok(true == pmConceptGetRequired("CELL.XWINDOW", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned true for CELL.XWINDOW at level: CELL");
+        ok(true == pmConceptGetRequired("CELL.YWINDOW", PM_FPA_LEVEL_CELL),
+          "pmConceptGetRequired() returned true for CELL.YWINDOW at level: CELL");
+
+        // The 2nd pmConceptsInit() should return FALSE after pmConceptsInit() is called
+        ok(false == pmConceptsInit(), "pmConceptsInit() returned FALSE");
+
+        pmConceptsDone();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // --------------------------------------------------------------------
+    // Tests for pmConceptsBlankFPA()
+    // Verify error with NULL input.
+    {
+        psMemId id = psMemGetId();
+        bool rc = pmConceptsBlankFPA(NULL);
+        ok(rc == false, "pmConceptsBlankFPA() returned FALSE with NULL input");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // -----------------------------------------------------------------------------
+    // Tests for pmConceptsBlankFPA()
+    // Call with valid data.  We test by ensuring the first 5 metadata items were
+    // added to fpa->concepts.
+    {
+        psMemId id = psMemGetId();
+        bool mdok;
+        char *tmpStr;
+        psF32 tmpF32;
+        psF64 tmpF64;
+        psS32 tmpS32;
+        pmFPA *fpa = pmFPAAlloc(NULL);
+        bool rc = false;
+
+        // First junk items to fpa->concepts so that we know they are later blanked.
+        rc|= psMetadataAddStr(fpa->concepts, PS_LIST_TAIL, "FPA.TELESCOPE", PS_META_REPLACE, "", "JUNK");
+        rc|= psMetadataAddStr(fpa->concepts, PS_LIST_TAIL, "FPA.INSTRUMENT", PS_META_REPLACE, "", "JUNK");
+        rc|= psMetadataAddStr(fpa->concepts, PS_LIST_TAIL, "FPA.DETECTOR", PS_META_REPLACE, "", "JUNK");
+        rc|= psMetadataAddStr(fpa->concepts, PS_LIST_TAIL, "FPA.CAMERA", PS_META_REPLACE, "", "JUNK");
+        rc|= psMetadataAddF32(fpa->concepts, PS_LIST_TAIL, "FPA.FOCUS", PS_META_REPLACE, "", 22.0);
+        rc|= psMetadataAddF32(fpa->concepts, PS_LIST_TAIL, "FPA.AIRMASS", PS_META_REPLACE, "", 22.0);
+        rc|= psMetadataAddStr(fpa->concepts, PS_LIST_TAIL, "FPA.FILTERID", PS_META_REPLACE, "", "JUNK");
+        rc|= psMetadataAddStr(fpa->concepts, PS_LIST_TAIL, "FPA.FILTER", PS_META_REPLACE, "", "JUNK");
+        rc|= psMetadataAddF32(fpa->concepts, PS_LIST_TAIL, "FPA.POSANGLE", PS_META_REPLACE, "", 22.0);
+        rc|= psMetadataAddStr(fpa->concepts, PS_LIST_TAIL, "FPA.RADECSYS", PS_META_REPLACE, "", "JUNK");
+        rc|= psMetadataAddF64(fpa->concepts, PS_LIST_TAIL, "FPA.RA", PS_META_REPLACE, "", 22.0);
+        rc|= psMetadataAddF64(fpa->concepts, PS_LIST_TAIL, "FPA.DEC", PS_META_REPLACE, "", 22.0);
+        rc|= psMetadataAddStr(fpa->concepts, PS_LIST_TAIL, "FPA.OBSTYPE", PS_META_REPLACE, "", "JUNK");
+        rc|= psMetadataAddStr(fpa->concepts, PS_LIST_TAIL, "FPA.OBJECT", PS_META_REPLACE, "", "JUNK");
+        rc|= psMetadataAddF64(fpa->concepts, PS_LIST_TAIL, "FPA.ALT", PS_META_REPLACE, "", 22.0);
+        rc|= psMetadataAddF64(fpa->concepts, PS_LIST_TAIL, "FPA.AZ", PS_META_REPLACE, "", 22.0);
+        rc|= psMetadataAddS32(fpa->concepts, PS_LIST_TAIL, "FPA.TIMESYS", PS_META_REPLACE, "", 22);
+        rc|= psMetadataAddF32(fpa->concepts, PS_LIST_TAIL, "FPA.TEMP", PS_META_REPLACE, "", 22.0);
+        rc|= psMetadataAddF32(fpa->concepts, PS_LIST_TAIL, "FPA.EXPOSURE", PS_META_REPLACE, "", 22.0);
+        ok(rc, "Set dummy data in fpa->concepts");
+
+        rc = pmConceptsBlankFPA(fpa);
+        ok(rc == true, "pmConceptsBlankFPA() returned TRUE with valid input data");
+        tmpStr = psMetadataLookupStr(&mdok, fpa->concepts, "FPA.TELESCOPE");
+        ok(mdok && !strcmp(tmpStr, ""), "FPA.TELESCOPE was cleared (%s)", tmpStr);
+        tmpStr = psMetadataLookupStr(&mdok, fpa->concepts, "FPA.INSTRUMENT");
+        ok(mdok && !strcmp(tmpStr, ""), "FPA.INSTRUMENT was cleared (%s)", tmpStr);
+        tmpStr = psMetadataLookupStr(&mdok, fpa->concepts, "FPA.DETECTOR");
+        ok(mdok && !strcmp(tmpStr, ""), "FPA.DETECTOR was cleared (%s)", tmpStr);
+        tmpStr = psMetadataLookupStr(&mdok, fpa->concepts, "FPA.CAMERA");
+        ok(mdok && !strcmp(tmpStr, ""), "FPA.CAMERA was cleared (%s)", tmpStr);
+        tmpF32 = psMetadataLookupF32(&mdok, fpa->concepts, "FPA.FOCUS");
+        ok(mdok && isnan(tmpF32), "FPA.FOCUS was cleared (%f)", tmpF32);
+        tmpF32 = psMetadataLookupF32(&mdok, fpa->concepts, "FPA.AIRMASS");
+        ok(mdok && isnan(tmpF32), "FPA.AIRMASS was cleared (%f)", tmpF32);
+        tmpStr = psMetadataLookupStr(&mdok, fpa->concepts, "FPA.FILTERID");
+        ok(mdok && !strcmp(tmpStr, ""), "FPA.FILTERID was cleared (%s)", tmpStr);
+        tmpStr = psMetadataLookupStr(&mdok, fpa->concepts, "FPA.FILTER");
+        ok(mdok && !strcmp(tmpStr, ""), "FPA.FILTER was cleared (%s)", tmpStr);
+        tmpF32 = psMetadataLookupF32(&mdok, fpa->concepts, "FPA.POSANGLE");
+        ok(mdok && isnan(tmpF32), "FPA.POSANGLE was cleared (%f)", tmpF32);
+        tmpStr = psMetadataLookupStr(&mdok, fpa->concepts, "FPA.RADECSYS");
+        ok(mdok && !strcmp(tmpStr, ""), "FPA.RADECSYS was cleared (%s)", tmpStr);
+        tmpF64 = psMetadataLookupF64(&mdok, fpa->concepts, "FPA.RA");
+        ok(mdok && isnan(tmpF64), "FPA.RA was cleared (%f)", tmpF64);
+        tmpF64 = psMetadataLookupF64(&mdok, fpa->concepts, "FPA.DEC");
+        ok(mdok && isnan(tmpF64), "FPA.DEC was cleared (%f)", tmpF64);
+        tmpStr = psMetadataLookupStr(&mdok, fpa->concepts, "FPA.OBSTYPE");
+        ok(mdok && !strcmp(tmpStr, ""), "FPA.OBSTYPE was cleared (%s)", tmpStr);
+        tmpStr = psMetadataLookupStr(&mdok, fpa->concepts, "FPA.OBJECT");
+        ok(mdok && !strcmp(tmpStr, ""), "FPA.OBJECT was cleared (%s)", tmpStr);
+        tmpF64 = psMetadataLookupF64(&mdok, fpa->concepts, "FPA.ALT");
+        ok(mdok && isnan(tmpF64), "FPA.ALT was cleared (%f)", tmpF64);
+        tmpF64 = psMetadataLookupF64(&mdok, fpa->concepts, "FPA.AZ");
+        ok(mdok && isnan(tmpF64), "FPA.AZ was cleared (%f)", tmpF64);
+        tmpS32 = psMetadataLookupS32(&mdok, fpa->concepts, "FPA.TIMESYS");
+        ok(mdok && -1 == tmpS32, "FPA.TIMESYS was cleared (%d)", tmpS32);
+        // XXX: Add code to make sure it was cleared.
+        psMetadataItem *tmpMI = psMetadataLookup(fpa->concepts, "FPA.TIME");
+        ok(tmpMI != NULL, "FPA.TIME was cleared");
+        tmpF32 = psMetadataLookupF32(&mdok, fpa->concepts, "FPA.TEMP");
+        ok(mdok && isnan(tmpF32), "FPA.TEMP was cleared (%f)", tmpF32);
+        tmpF32 = psMetadataLookupF32(&mdok, fpa->concepts, "FPA.TEMP");
+        ok(mdok && isnan(tmpF32), "FPA.TEMP was cleared (%f)", tmpF32);
+
+        psFree(fpa);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // -----------------------------------------------------------------------------
+    // Tests for pmConceptsBlankChip()
+    // Call with valid data.  We test by ensuring the first 5 metadata items were
+    // added to chip->concepts.
+    {
+        psMemId id = psMemGetId();
+        bool mdok;
+        psF32 tmpF32;
+        psS32 tmpS32;
+        pmChip *chip = pmChipAlloc(NULL, NULL);
+        bool rc = false;
+
+        // First junk items to chip->concepts so that we know they are later blanked.
+        rc|= psMetadataAddS32(chip->concepts, PS_LIST_TAIL, "CHIP.XPARITY", PS_META_REPLACE, "", 22);
+        rc|= psMetadataAddS32(chip->concepts, PS_LIST_TAIL, "CHIP.YPARITY", PS_META_REPLACE, "", 22);
+        rc|= psMetadataAddS32(chip->concepts, PS_LIST_TAIL, "CHIP.X0", PS_META_REPLACE, "", 22);
+        rc|= psMetadataAddS32(chip->concepts, PS_LIST_TAIL, "CHIP.Y0", PS_META_REPLACE, "", 22);
+        rc|= psMetadataAddS32(chip->concepts, PS_LIST_TAIL, "CHIP.XSIZE", PS_META_REPLACE, "", 22);
+        rc|= psMetadataAddS32(chip->concepts, PS_LIST_TAIL, "CHIP.YSIZE", PS_META_REPLACE, "", 22);
+        rc|= psMetadataAddF32(chip->concepts, PS_LIST_TAIL, "CHIP.TEMP", PS_META_REPLACE, "", 22.0);
+        ok(rc, "Set dummy data in chip->concepts");
+
+        rc = pmConceptsBlankChip(chip);
+        tmpS32 = psMetadataLookupS32(&mdok, chip->concepts, "CHIP.XPARITY");
+        ok(mdok && 0 == tmpS32, "CHIP.XPARITY was cleared (%d)", tmpS32);
+        tmpS32 = psMetadataLookupS32(&mdok, chip->concepts, "CHIP.YPARITY");
+        ok(mdok && 0 == tmpS32, "CHIP.YPARITY was cleared (%d)", tmpS32);
+        tmpS32 = psMetadataLookupS32(&mdok, chip->concepts, "CHIP.X0");
+        ok(mdok && 0 == tmpS32, "CHIP.X0 was cleared (%d)", tmpS32);
+        tmpS32 = psMetadataLookupS32(&mdok, chip->concepts, "CHIP.Y0");
+        ok(mdok && 0 == tmpS32, "CHIP.Y0 was cleared (%d)", tmpS32);
+        tmpS32 = psMetadataLookupS32(&mdok, chip->concepts, "CHIP.XSIZE");
+        ok(mdok && 0 == tmpS32, "CHIP.XSIZE was cleared (%d)", tmpS32);
+        tmpS32 = psMetadataLookupS32(&mdok, chip->concepts, "CHIP.YSIZE");
+        ok(mdok && 0 == tmpS32, "CHIP.YSIZE was cleared (%d)", tmpS32);
+        tmpF32 = psMetadataLookupF32(&mdok, chip->concepts, "CHIP.TEMP");
+        ok(mdok && isnan(tmpF32), "CHIP.TEMP was cleared (%d)", tmpF32);
+
+        psFree(chip);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // -----------------------------------------------------------------------------
+    // Tests for pmConceptsBlankCell()
+    // Call with valid data.  We test by ensuring the first 5 metadata items were
+    // added to cell->concepts.
+    {
+        psMemId id = psMemGetId();
+        bool mdok;
+        psF32 tmpF32;
+        psS32 tmpS32;
+        pmCell *cell = pmCellAlloc(NULL, NULL);
+        bool rc = false;
+
+        // First junk items to cell->concepts so that we know they are later blanked.
+        rc|= psMetadataAddF32(cell->concepts, PS_LIST_TAIL, "CELL.GAIN", PS_META_REPLACE, "", 22.0);
+        rc|= psMetadataAddF32(cell->concepts, PS_LIST_TAIL, "CELL.READNOISE", PS_META_REPLACE, "", 22.0);
+        rc|= psMetadataAddS32(cell->concepts, PS_LIST_TAIL, "CELL.XPARITY", PS_META_REPLACE, "", 22);
+        rc|= psMetadataAddS32(cell->concepts, PS_LIST_TAIL, "CELL.YPARITY", PS_META_REPLACE, "", 22);
+        rc|= psMetadataAddS32(cell->concepts, PS_LIST_TAIL, "CELL.READDIR", PS_META_REPLACE, "", 22);
+        rc|= psMetadataAddF32(cell->concepts, PS_LIST_TAIL, "CELL.SATURATION", PS_META_REPLACE, "", 22.0);
+        rc|= psMetadataAddF32(cell->concepts, PS_LIST_TAIL, "CELL.BAD", PS_META_REPLACE, "", 22.0);
+        rc|= psMetadataAddF32(cell->concepts, PS_LIST_TAIL, "CELL.EXPOSURE", PS_META_REPLACE, "", 22.0);
+        rc|= psMetadataAddF32(cell->concepts, PS_LIST_TAIL, "CELL.DARKTIME", PS_META_REPLACE, "", 22.0);
+        rc|= psMetadataAddS32(cell->concepts, PS_LIST_TAIL, "CELL.XBIN", PS_META_REPLACE, "", 22);
+        rc|= psMetadataAddS32(cell->concepts, PS_LIST_TAIL, "CELL.YBIN", PS_META_REPLACE, "", 22);
+        rc|= psMetadataAddS32(cell->concepts, PS_LIST_TAIL, "CELL.TIMESYS", PS_META_REPLACE, "", 22);
+        rc|= psMetadataAddS32(cell->concepts, PS_LIST_TAIL, "CELL.X0", PS_META_REPLACE, "", 22);
+        rc|= psMetadataAddS32(cell->concepts, PS_LIST_TAIL, "CELL.Y0", PS_META_REPLACE, "", 22);
+        rc|= psMetadataAddS32(cell->concepts, PS_LIST_TAIL, "CELL.XSIZE", PS_META_REPLACE, "", 22);
+        rc|= psMetadataAddS32(cell->concepts, PS_LIST_TAIL, "CELL.YSIZE", PS_META_REPLACE, "", 22);
+        rc|= psMetadataAddS32(cell->concepts, PS_LIST_TAIL, "CELL.XWINDOW", PS_META_REPLACE, "", 22);
+        rc|= psMetadataAddS32(cell->concepts, PS_LIST_TAIL, "CELL.YWINDOW", PS_META_REPLACE, "", 22);
+        rc|= psMetadataAddS32(cell->concepts, PS_LIST_TAIL, "CELL.", PS_META_REPLACE, "", 22);
+
+
+        ok(rc, "Set dummy data in cell->concepts");
+
+        rc = pmConceptsBlankCell(cell);
+        ok(rc == true, "pmConceptsBlankCELL() returned TRUE with valid input data");
+
+        tmpF32 = psMetadataLookupF32(&mdok, cell->concepts, "CELL.GAIN");
+        ok(mdok && isnan(tmpF32), "CELL.GAIN was cleared (%f)", tmpF32);
+        tmpF32 = psMetadataLookupF32(&mdok, cell->concepts, "CELL.READNOISE");
+        ok(mdok && isnan(tmpF32), "CELL.READNOISE was cleared (%f)", tmpF32);
+        tmpF32 = psMetadataLookupF32(&mdok, cell->concepts, "CELL.SATURATION");
+        ok(mdok && isnan(tmpF32), "CELL.SATURATION was cleared (%f)", tmpF32);
+        tmpF32 = psMetadataLookupF32(&mdok, cell->concepts, "CELL.BAD");
+        ok(mdok && isnan(tmpF32), "CELL.BAD was cleared (%f)", tmpF32);
+
+        tmpS32 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.XPARITY");
+        ok(mdok && 0 == tmpS32, "CELL.XPARITY was cleared (%d)", tmpS32);
+        tmpS32 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.YPARITY");
+        ok(mdok && 0 == tmpS32, "CELL.YPARITY was cleared (%d)", tmpS32);
+        tmpS32 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.READDIR");
+        ok(mdok && 0 == tmpS32, "CELL.READDIR was cleared (%d)", tmpS32);
+        tmpF32 = psMetadataLookupF32(&mdok, cell->concepts, "CELL.EXPOSURE");
+        ok(mdok && isnan(tmpF32), "CELL.EXPOSURE was cleared (%f)", tmpF32);
+        tmpF32 = psMetadataLookupF32(&mdok, cell->concepts, "CELL.DARKTIME");
+        ok(mdok && isnan(tmpF32), "CELL.DARKTIME was cleared (%f)", tmpF32);
+        // XXX: Add code to make sure it was cleared.
+        psMetadataItem *tmpMI = psMetadataLookup(cell->concepts, "CELL.TRIMSEC");
+        ok(tmpMI != NULL, "CELL.TRIMSEC was cleared");
+        tmpMI = psMetadataLookup(cell->concepts, "CELL.BIASSEC");
+        ok(tmpMI != NULL, "CELL.BIASSEC was cleared");
+        tmpS32 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.XBIN");
+        ok(mdok && 0 == tmpS32, "CELL.XBIN was cleared (%d)", tmpS32);
+        tmpS32 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.YBIN");
+        ok(mdok && 0 == tmpS32, "CELL.YBIN was cleared (%d)", tmpS32);
+        tmpS32 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.TIMESYS");
+        ok(mdok && -1 == tmpS32, "CELL.TIMESYS was cleared (%d)", tmpS32);
+        // XXX: Add code to make sure it was cleared.
+        tmpMI = psMetadataLookup(cell->concepts, "CELL.TIME");
+        ok(tmpMI != NULL, "CELL.TIME was cleared");
+        tmpS32 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.X0");
+        ok(mdok && 0 == tmpS32, "CELL.X0 was cleared (%d)", tmpS32);
+        tmpS32 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.Y0");
+        ok(mdok && 0 == tmpS32, "CELL.Y0 was cleared (%d)", tmpS32);
+        tmpS32 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.XSIZE");
+        ok(mdok && 0 == tmpS32, "CELL.XSIZE was cleared (%d)", tmpS32);
+        tmpS32 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.YSIZE");
+        ok(mdok && 0 == tmpS32, "CELL.YSIZE was cleared (%d)", tmpS32);
+        tmpS32 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.XWINDOW");
+        ok(mdok && 0 == tmpS32, "CELL.XWINDOW was cleared (%d)", tmpS32);
+        tmpS32 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.YWINDOW");
+        ok(mdok && 0 == tmpS32, "CELL.YWINDOW was cleared (%d)", tmpS32);
+
+        psFree(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/concepts/tap_pmConceptsAverage.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/concepts/tap_pmConceptsAverage.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/concepts/tap_pmConceptsAverage.c	(revision 22158)
@@ -0,0 +1,443 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+// XXX: Use better name for the temporary FITS file
+// XXX: The code to generate and free the FPA hierarchy was copied from
+// tap-pmFPA.c.  EIther include it directly, or library, or something.
+// Also, get rid of the manual free functions and use psFree() once
+// it correctly frees child members
+// XXX: For the genSimpleFPA() code, add IDs to each function so that
+// the values set in each chip-?cell-?hdu-?image are unique
+// XXX: For the genSimpleFPA() code, write masks and weights as well
+
+#define CHIP_ALLOC_NAME        "ChipName"
+#define CELL_ALLOC_NAME        "CellName"
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define MISC_NAME2             "META01"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           4
+#define TEST_NUM_COLS           4
+#define NUM_READOUTS            3
+#define NUM_CELLS               10
+#define NUM_CHIPS               8
+#define NUM_FPAS		4
+#define NUM_HDUS                5
+#define BASE_IMAGE              10
+#define BASE_MASK               40
+#define BASE_WEIGHT             70
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+psPlaneTransform *PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM()
+{
+    psPlaneTransform *pt = psPlaneTransformAlloc(1, 1);
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+    return(pt);
+}
+
+psPlaneDistort *PS_CREATE_4D_IDENTITY_PLANE_DISTORT()
+{
+    psPlaneDistort *pd = psPlaneDistortAlloc(1, 1, 1, 1);
+    pd->x->coeff[1][0][0][0] = 1.0;
+    pd->y->coeff[0][1][0][0] = 1.0;
+    return(pd);
+}
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    cell->hdu = pmHDUAlloc("cellExtName");
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = psMemDecrRefCounter((psPtr) generateSimpleReadout(cell));
+    }
+
+    // First try to read data from ../dataFiles, then try dataFiles.
+    bool rc = pmConfigFileRead(&cell->hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        rc = pmConfigFileRead(&cell->hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            diag("pmConfigFileRead() was unsuccessful (from generateSimpleCell())");
+	}
+    }
+
+    cell->hdu->images = psArrayAlloc(NUM_HDUS);
+    cell->hdu->masks = psArrayAlloc(NUM_HDUS);
+    cell->hdu->weights = psArrayAlloc(NUM_HDUS);
+    for (int k = 0 ; k < NUM_HDUS ; k++) {
+        cell->hdu->images->data[k]  = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        cell->hdu->masks->data[k]   = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        cell->hdu->weights->data[k] = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(cell->hdu->images->data[k], (float) (BASE_IMAGE+k));
+        psImageInit(cell->hdu->masks->data[k], (psU8) (BASE_MASK+k));
+        psImageInit(cell->hdu->weights->data[k], (float) (BASE_WEIGHT+k));
+    }
+
+    //XXX: Should the region be set some other way?  Like through the various config files?
+//    psRegion *region = psRegionAlloc(0.0, TEST_NUM_COLS-1, 0.0, TEST_NUM_ROWS-1);
+    psRegion *region = psRegionAlloc(0.0, 0.0, 0.0, 0.0);
+    // You shouldn't have to remove the key from the metadata.  Find out how to simply change the key value.
+    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC");
+    psMetadataAddPtr(cell->concepts, PS_LIST_TAIL|PS_META_REPLACE, "CELL.TRIMSEC", PS_DATA_REGION, "I am a region", region);
+    psFree(region);
+    return(cell);
+}
+
+/******************************************************************************
+generateSimpleChip(): This function generates a pmChip data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmChip *generateSimpleChip(pmFPA *fpa)
+{
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    chip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    chip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    psMetadataAddS32(chip->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(chip->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(chip->cells, NUM_CELLS);
+    for (int i = 0 ; i < NUM_CELLS ; i++) {
+        chip->cells->data[i] = psMemDecrRefCounter((psPtr) generateSimpleCell(chip));
+    }
+    return(chip);
+}
+
+/******************************************************************************
+generateSimpleFPA(): This function generates a pmFPA data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmFPA* generateSimpleFPA(psMetadata *camera)
+{
+    pmFPA* fpa = pmFPAAlloc(camera);
+    fpa->fromTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toSky = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+    psMetadataAddS32(fpa->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    if (camera != NULL) {
+        psMetadataAddS32((psMetadata *) fpa->camera, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    }
+    psMetadataAddS32(fpa->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(fpa->chips, NUM_CHIPS);
+    for (int i = 0 ; i < NUM_CHIPS ; i++) {
+        fpa->chips->data[i] = psMemDecrRefCounter((psPtr) generateSimpleChip(fpa));
+    }
+    pmConceptsBlankFPA(fpa);
+    return(fpa);
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(50);
+
+    // ----------------------------------------------------------------------
+    // pmConceptsAverageFPAs() tests: NULL input pmFPA *target
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA *targetFPA = generateSimpleFPA(camera);
+        pmFPA *sourceFPA[NUM_FPAS];
+
+        sourceFPA[0] = generateSimpleFPA(camera);
+        psList *sources = psListAlloc(sourceFPA[0]);
+        for (int fpaID = 1 ; fpaID < NUM_FPAS ; fpaID++) {
+            sourceFPA[fpaID] = generateSimpleFPA(camera);
+            bool rc = psListAdd(sources, PS_LIST_HEAD, sourceFPA[fpaID]);
+            ok(rc, "Successfully added FPA %d to list", fpaID);
+	}
+        ok(!pmConceptsAverageFPAs(NULL, sources), "pmConceptsAverage(NULL, sources) returned FALSE");
+
+        for (int fpaID = 0 ; fpaID < NUM_FPAS ; fpaID++) {
+            psFree(sourceFPA[fpaID]);
+	}
+        psFree(sources);
+        psFree(targetFPA);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmConceptsAverageFPAs() tests: NULL input psList *sources
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA *targetFPA = generateSimpleFPA(camera);
+        pmFPA *sourceFPA[NUM_FPAS];
+
+        sourceFPA[0] = generateSimpleFPA(camera);
+        psList *sources = psListAlloc(sourceFPA[0]);
+        for (int fpaID = 1 ; fpaID < NUM_FPAS ; fpaID++) {
+            sourceFPA[fpaID] = generateSimpleFPA(camera);
+            bool rc = psListAdd(sources, PS_LIST_HEAD, sourceFPA[fpaID]);
+            ok(rc, "Successfully added FPA %d to list", fpaID);
+	}
+        ok(!pmConceptsAverageFPAs(targetFPA, NULL), "pmConceptsAverage(NULL, sources) returned FALSE");
+
+        for (int fpaID = 0 ; fpaID < NUM_FPAS ; fpaID++) {
+            psFree(sourceFPA[fpaID]);
+	}
+        psFree(sources);
+        psFree(targetFPA);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmConceptsAverageFPAs() tests: acceptable inputs
+    // XXX: There's a memory leak somewhere in this test, not sure where.
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA *targetFPA = generateSimpleFPA(camera);
+        pmFPA *sourceFPA[NUM_FPAS];
+        psMetadata *cameras[NUM_FPAS];
+
+        // Ensure that the FPA.TIME average is computed correctly
+        psList *sources = NULL;
+        psF64 actualTime = 0.0;
+        for (int fpaID = 0 ; fpaID < NUM_FPAS ; fpaID++) {
+            cameras[fpaID] = psMetadataAlloc();
+            sourceFPA[fpaID] = generateSimpleFPA(cameras[fpaID]);
+            psTime *fpaTime = psMetadataLookupPtr(NULL, (sourceFPA[fpaID])->concepts, "FPA.TIME");
+            // Add a small value to the psTime so that we can test/ensure that pmConceptsAverageFPAs()
+            // is actually calculating an average.
+            fpaTime->sec += (double) (fpaID * 1000);
+            actualTime+= psTimeToMJD(fpaTime);
+            if (0 == fpaID) {
+                sources = psListAlloc(sourceFPA[fpaID]);
+	    } else {
+                bool rc = psListAdd(sources, PS_LIST_HEAD, sourceFPA[fpaID]);
+                ok(rc, "Successfully added FPA %d to list", fpaID);
+	    }
+	}
+        // XXX: The memory leak occurs during the following single call
+        ok(pmConceptsAverageFPAs(targetFPA, sources), "pmConceptsAverage(targetFPA, sources) returned TRUE");
+        actualTime/= (float) NUM_FPAS;
+        psTime *fpaTime = psMetadataLookupPtr(NULL, targetFPA->concepts, "FPA.TIME");
+        ok(abs(actualTime - psTimeToMJD(fpaTime)) < 1e-4, "pmConceptsAverageFPAs() calculated the average time correctly");
+
+        // Replace the FPA.TIMESYS with a non-conforming value, verify that pmConceptsAverageFPAs() returns an error
+
+        psTimeType timeSys = psMetadataLookupS32(NULL, sourceFPA[0]->concepts, "FPA.TIMESYS");
+        psMetadataAddS32(sourceFPA[NUM_FPAS-1]->concepts, PS_LIST_HEAD, "FPA.TIMESYS", PS_META_REPLACE, NULL, timeSys+10);
+        ok(!pmConceptsAverageFPAs(targetFPA, sources), "pmConceptsAverage(NULL, sources) returned FALSE with nonequal FPA.TIMESYS metadata");
+        psMetadataAddS32(sourceFPA[NUM_FPAS-1]->concepts, PS_LIST_HEAD, "FPA.TIMESYS", PS_META_REPLACE, NULL, timeSys);
+        ok(pmConceptsAverageFPAs(targetFPA, sources), "pmConceptsAverage(NULL, sources) returned TRUE with equal FPA.TIMESYS metadata");
+
+
+        // Replace the FPA.TIMESYS with a non-conforming value, verify that pmConceptsAverageFPAs() returnes an error        
+        psString filter = psMetadataLookupStr(NULL, sourceFPA[0]->concepts, "FPA.FILTER");
+        psMetadataAddStr(sourceFPA[NUM_FPAS-1]->concepts, PS_LIST_HEAD, "FPA.FILTER", PS_META_REPLACE, NULL, "BOGUS STRING");
+        ok(!pmConceptsAverageFPAs(targetFPA, sources), "pmConceptsAverage(NULL, sources) returned FALSE with nonequal FPA.FILTER metadata");
+        psMetadataAddStr(sourceFPA[NUM_FPAS-1]->concepts, PS_LIST_HEAD, "FPA.FILTER", PS_META_REPLACE, NULL, filter);
+        ok(pmConceptsAverageFPAs(targetFPA, sources), "pmConceptsAverage(NULL, sources) returned TRUE with equal FPA.FILTER metadata");
+
+        // Free data, check for memory leaks
+        for (int fpaID = 0 ; fpaID < NUM_FPAS ; fpaID++) {
+            psFree(sourceFPA[fpaID]);
+            psFree(cameras[fpaID]);
+	}
+        psFree(sources);
+//        psFree(filter);
+        psFree(targetFPA);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // ----------------------------------------------------------------------
+    // pmConceptsAverageCells() tests: NULL input pmFPA *target
+    // bool pmConceptsAverageCells(pmCell *target, psList *sources, psRegion *trimsec, psRegion *biassec, bool same)
+    {
+        psMemId id = psMemGetId();
+        psMetadata *tgtCamera = psMetadataAlloc();
+        pmFPA *tgtFPA = generateSimpleFPA(tgtCamera);
+        pmChip *tgtChip = tgtFPA->chips->data[0];
+        pmCell *tgtCell = tgtChip->cells->data[0];
+        psMetadata *srcCamera = psMetadataAlloc();
+        pmFPA *srcFPA = generateSimpleFPA(srcCamera);
+        pmChip *srcChip = srcFPA->chips->data[0];
+
+        psList *sources = NULL;
+        psF32 tstGain = 0.0;
+        psF32 tstReadnoise = 0.0;
+        psF32 tstExposure = 0.0;
+        psF32 tstDarktime = 0.0;
+        psF32 tstSaturation = 0.0;
+        psF32 tstBad = 0.0;
+        
+        for (int cellID = 0 ; cellID < srcChip->cells->n ; cellID++) {
+            pmCell *cell = srcChip->cells->data[cellID];
+            // Set the various concepts which we will test later
+            psMetadataAddF32(cell->concepts, PS_LIST_HEAD, "CELL.GAIN", PS_META_REPLACE, NULL, 0.0 + (float) cellID);
+            tstGain+= 0.0 + (float) cellID;
+            psMetadataAddF32(cell->concepts, PS_LIST_HEAD, "CELL.READNOISE", PS_META_REPLACE, NULL, 10.0 + (float) cellID);
+            tstReadnoise+= 10.0 + (float) cellID;
+            psMetadataAddF32(cell->concepts, PS_LIST_HEAD, "CELL.EXPOSURE", PS_META_REPLACE, NULL, 20.0 + (float) cellID);
+            tstExposure+= 20.0 + (float) cellID;
+            psMetadataAddF32(cell->concepts, PS_LIST_HEAD, "CELL.DARKTIME", PS_META_REPLACE, NULL, 30.0 + (float) cellID);
+            tstDarktime+= 30.0 + (float) cellID;
+            psMetadataAddF32(cell->concepts, PS_LIST_HEAD, "CELL.SATURATION", PS_META_REPLACE, NULL, 40.0 + (float) cellID);
+            if (cellID == 0)
+                tstSaturation = 40.0 + (float) cellID;
+            psMetadataAddF32(cell->concepts, PS_LIST_HEAD, "CELL.BAD", PS_META_REPLACE, NULL, 50.0 + (float) cellID);
+            if (cellID == (srcChip->cells->n - 1))
+                tstBad = 50.0 + (float) cellID;
+            if (cellID == 0) {
+                sources = psListAlloc(srcChip->cells->data[cellID]);
+	    } else {
+                bool rc = psListAdd(sources, PS_LIST_HEAD, srcChip->cells->data[cellID]);
+                ok(rc, "Successfully added cell %d to list", cellID);
+	    }
+	}
+        tstGain /= (psF64) srcChip->cells->n;
+        tstReadnoise /= (psF64) srcChip->cells->n;
+        tstExposure /= (psF64) srcChip->cells->n;
+        tstDarktime /= (psF64) srcChip->cells->n;
+
+        psRegion *trimsec = psRegionAlloc(0, 1, 2, 3);
+        psRegion *biassec = psRegionAlloc(4, 5, 6, 7);
+
+        // Ensure pmConceptsAverageCells() returns NULL with NULL tgtCell input
+        bool rc = pmConceptsAverageCells(NULL, sources, trimsec, biassec, false);
+        ok(!rc, "pmConceptsAverageCells() returned FALSE with NULL sources input");
+
+        // Ensure pmConceptsAverageCells() returns NULL with NULL sources input
+        rc = pmConceptsAverageCells(tgtCell, NULL, trimsec, biassec, false);
+        ok(!rc, "pmConceptsAverageCells() returned FALSE with NULL targetCell input");
+
+        // Ensure pmConceptsAverageCells() returns NULL with sources->n = 0
+        sources->n = 0;
+        rc = pmConceptsAverageCells(tgtCell, sources, trimsec, biassec, false);
+        ok(!rc, "pmConceptsAverageCells() returned FALSE with NULL sources->n = 0");
+        sources->n = NUM_CELLS;
+
+        // Call pmConceptsAverageCells() with acceptable input data
+        rc = pmConceptsAverageCells(tgtCell, sources, trimsec, biassec, false);
+        ok(rc, "pmConceptsAverageCells() returned TRUE with acceptable input data");
+        psF32 tmpF32;
+        tmpF32 = psMetadataLookupF32(NULL, tgtCell->concepts, "CELL.GAIN");
+        ok(abs(tmpF32 - tstGain) < 1e-4, "pmConceptsAverageCells() calculated the average CELL.GAIN correctly");
+        tmpF32 = psMetadataLookupF32(NULL, tgtCell->concepts, "CELL.READNOISE");
+        ok(abs(tmpF32 - tstReadnoise) < 1e-4, "pmConceptsAverageCells() calculated the average CELL.READNOISE correctly");
+        tmpF32 = psMetadataLookupF32(NULL, tgtCell->concepts, "CELL.EXPOSURE");
+        ok(abs(tmpF32 - tstExposure) < 1e-4, "pmConceptsAverageCells() calculated the average CELL.EXPOSURE correctly");
+        tmpF32 = psMetadataLookupF32(NULL, tgtCell->concepts, "CELL.DARKTIME");
+        ok(abs(tmpF32 - tstDarktime) < 1e-4, "pmConceptsAverageCells() calculated the average CELL.DARKTIME correctly");
+        tmpF32 = psMetadataLookupF32(NULL, tgtCell->concepts, "CELL.SATURATION");
+        ok(abs(tmpF32 - tstSaturation) < 1e-4, "pmConceptsAverageCells() calculated the average CELL.SATURATION correctly (%f %f)", tmpF32, tstSaturation);
+        tmpF32 = psMetadataLookupF32(NULL, tgtCell->concepts, "CELL.BAD");
+        ok(abs(tmpF32 - tstBad) < 1e-4, "pmConceptsAverageCells() calculated the average CELL.BAD correctly");
+        psRegion *tstTrimsec = psMetadataLookupPtr(NULL, tgtCell->concepts, "CELL.TRIMSEC");
+        ok(tstTrimsec->x0 == 0.0 && tstTrimsec->x1 == 1.0 && tstTrimsec->y0 == 2.0 && tstTrimsec->y1 == 3.0,
+           "pmConceptsAverageCells() set the CELL>TRIMSEC region correctly");
+        psRegion *tstBiassec = psMetadataLookupPtr(NULL, tgtCell->concepts, "CELL.BIASSEC");
+        ok(tstBiassec->x0 == 4.0 && tstBiassec->x1 == 5.0 && tstBiassec->y0 == 6.0 && tstBiassec->y1 == 7.0,
+           "pmConceptsAverageCells() set the CELL>TRIMSEC region correctly");
+
+        psS32 tmpS32;
+        pmCell *srcCell = srcChip->cells->data[NUM_CELLS - 1];
+
+        // Set the CELL.TIMESYS metadata unequal, verify that error occurs
+        rc = psMetadataAddS32(srcCell->concepts, PS_LIST_HEAD, "CELL.TIMESYS", PS_META_REPLACE, NULL, 232);
+        tmpS32 = psMetadataLookupS32(&rc, srcCell->concepts, "CELL.TIMESYS");
+        rc = pmConceptsAverageCells(tgtCell, sources, trimsec, biassec, false);
+        ok(!rc, "pmConceptsAverageCells() returned FALSE with non equal CELL.TIMESYS metadata");
+        psMetadataAddS32(srcCell->concepts, PS_LIST_HEAD, "CELL.TIMESYS", PS_META_REPLACE, NULL, tmpS32);
+
+        // Set the CELL.READDIR metadata unequal, verify that error occurs
+        rc = psMetadataAddS32(srcCell->concepts, PS_LIST_HEAD, "CELL.READDIR", PS_META_REPLACE, NULL, 232);
+        tmpS32 = psMetadataLookupS32(&rc, srcCell->concepts, "CELL.READDIR");
+        rc = pmConceptsAverageCells(tgtCell, sources, trimsec, biassec, false);
+        ok(!rc, "pmConceptsAverageCells() returned FALSE with non equal CELL.READDIR metadata");
+        psMetadataAddS32(srcCell->concepts, PS_LIST_HEAD, "CELL.READDIR", PS_META_REPLACE, NULL, tmpS32);
+
+        // Set the CELL.XBIN metadata unequal, verify that error occurs
+        rc = psMetadataAddS32(srcCell->concepts, PS_LIST_HEAD, "CELL.XBIN", PS_META_REPLACE, NULL, 232);
+        tmpS32 = psMetadataLookupS32(&rc, srcCell->concepts, "CELL.XBIN");
+        rc = pmConceptsAverageCells(tgtCell, sources, trimsec, biassec, false);
+        ok(!rc, "pmConceptsAverageCells() returned FALSE with non equal CELL.XBIN metadata");
+        psMetadataAddS32(srcCell->concepts, PS_LIST_HEAD, "CELL.XBIN", PS_META_REPLACE, NULL, tmpS32);
+
+        // Set the CELL.YBIN metadata unequal, verify that error occurs
+        rc = psMetadataAddS32(srcCell->concepts, PS_LIST_HEAD, "CELL.YBIN", PS_META_REPLACE, NULL, 232);
+        tmpS32 = psMetadataLookupS32(&rc, srcCell->concepts, "CELL.YBIN");
+        rc = pmConceptsAverageCells(tgtCell, sources, trimsec, biassec, false);
+        ok(!rc, "pmConceptsAverageCells() returned FALSE with non equal CELL.YBIN metadata");
+        psMetadataAddS32(srcCell->concepts, PS_LIST_HEAD, "CELL.YBIN", PS_META_REPLACE, NULL, tmpS32);
+
+        // Set the CELL.X0 metadata unequal, verify that error occurs
+        rc = psMetadataAddS32(srcCell->concepts, PS_LIST_HEAD, "CELL.X0", PS_META_REPLACE, NULL, 232);
+        tmpS32 = psMetadataLookupS32(&rc, srcCell->concepts, "CELL.X0");
+        rc = pmConceptsAverageCells(tgtCell, sources, trimsec, biassec, true);
+        ok(!rc, "pmConceptsAverageCells() returned FALSE with non equal CELL.X0 metadata (same = true)");
+        psMetadataAddS32(srcCell->concepts, PS_LIST_HEAD, "CELL.X0", PS_META_REPLACE, NULL, tmpS32);
+
+        // Set the CELL.Y0 metadata unequal, verify that error occurs
+        rc = psMetadataAddS32(srcCell->concepts, PS_LIST_HEAD, "CELL.Y0", PS_META_REPLACE, NULL, 232);
+        tmpS32 = psMetadataLookupS32(&rc, srcCell->concepts, "CELL.Y0");
+        rc = pmConceptsAverageCells(tgtCell, sources, trimsec, biassec, true);
+        ok(!rc, "pmConceptsAverageCells() returned FALSE with non equal CELL.Y0 metadata (same = true)");
+        psMetadataAddS32(srcCell->concepts, PS_LIST_HEAD, "CELL.Y0", PS_META_REPLACE, NULL, tmpS32);
+
+        // Set the CELL.X0 metadata unequal, verify that no error occurs with same==false
+        rc = psMetadataAddS32(srcCell->concepts, PS_LIST_HEAD, "CELL.X0", PS_META_REPLACE, NULL, 232);
+        tmpS32 = psMetadataLookupS32(&rc, srcCell->concepts, "CELL.X0");
+        rc = pmConceptsAverageCells(tgtCell, sources, trimsec, biassec, false);
+        ok(!rc, "pmConceptsAverageCells() returned FALSE with non equal CELL.X0 metadata (same = false)");
+        psMetadataAddS32(srcCell->concepts, PS_LIST_HEAD, "CELL.X0", PS_META_REPLACE, NULL, tmpS32);
+
+        // Set the CELL.Y0 metadata unequal, verify that no error occurs with same==false
+        rc = psMetadataAddS32(srcCell->concepts, PS_LIST_HEAD, "CELL.Y0", PS_META_REPLACE, NULL, 232);
+        tmpS32 = psMetadataLookupS32(&rc, srcCell->concepts, "CELL.Y0");
+        rc = pmConceptsAverageCells(tgtCell, sources, trimsec, biassec, false);
+        ok(!rc, "pmConceptsAverageCells() returned FALSE with non equal CELL.Y0 metadata (same = false)");
+        psMetadataAddS32(srcCell->concepts, PS_LIST_HEAD, "CELL.Y0", PS_META_REPLACE, NULL, tmpS32);
+
+        psFree(tgtFPA);
+        psFree(srcFPA);
+        psFree(tgtCamera);
+        psFree(srcCamera);
+        psFree(biassec);
+        psFree(trimsec);
+        psFree(sources);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+}
+
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/concepts/tap_pmConceptsPhotcode.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/concepts/tap_pmConceptsPhotcode.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/concepts/tap_pmConceptsPhotcode.c	(revision 22158)
@@ -0,0 +1,116 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(25);
+
+
+    // ----------------------------------------------------------------------
+    // pmConceptsPhotcodeForView() tests: NULL pmConfig input
+    // psString pmConceptsPhotcodeForView(pmConfig *config, pmFPAfile *file, const pmFPAview *view)
+    {
+        psMemId id = psMemGetId();
+        pmConfig *config =pmConfigAlloc();
+        pmFPAfile *file = pmFPAfileAlloc();
+        pmFPAview *view = pmFPAviewAlloc(32);
+        ok(NULL == pmConceptsPhotcodeForView(NULL, file, view),
+          "pmConceptsPhotcodeForView(NULL, file, view) returned NULL");
+        psFree(config);
+        psFree(file);
+        psFree(view);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmConceptsPhotcodeForView() tests: NULL pmConfig input
+    // psString pmConceptsPhotcodeForView(pmConfig *config, pmFPAfile *file, const pmFPAview *view)
+    {
+        psMemId id = psMemGetId();
+        pmConfig *config =pmConfigAlloc();
+        pmFPAfile *file = pmFPAfileAlloc();
+        pmFPAview *view = pmFPAviewAlloc(32);
+        ok(NULL == pmConceptsPhotcodeForView(NULL, file, view),
+          "pmConceptsPhotcodeForView(NULL, file, view) returned NULL");
+        psFree(config);
+        psFree(file);
+        psFree(view);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmConceptsPhotcodeForView() tests: NULL pmFPAfile input
+    // psString pmConceptsPhotcodeForView(pmConfig *config, pmFPAfile *file, const pmFPAview *view)
+    {
+        psMemId id = psMemGetId();
+        pmConfig *config =pmConfigAlloc();
+        pmFPAfile *file = pmFPAfileAlloc();
+        pmFPAview *view = pmFPAviewAlloc(32);
+        ok(NULL == pmConceptsPhotcodeForView(config, NULL, view),
+          "pmConceptsPhotcodeForView(config, NULL, view) returned NULL");
+        psFree(config);
+        psFree(file);
+        psFree(view);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmConceptsPhotcodeForView() tests: NULL pmFPAview input
+    // psString pmConceptsPhotcodeForView(pmConfig *config, pmFPAfile *file, const pmFPAview *view)
+    {
+        psMemId id = psMemGetId();
+        pmConfig *config =pmConfigAlloc();
+        pmFPAfile *file = pmFPAfileAlloc();
+        pmFPAview *view = pmFPAviewAlloc(32);
+        ok(NULL == pmConceptsPhotcodeForView(config, file, NULL),
+          "pmConceptsPhotcodeForView(config, file, NULL) returned NULL");
+        psFree(config);
+        psFree(file);
+        psFree(view);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmConceptsPhotcodeForView() tests: acceptable inputs
+    // psString pmConceptsPhotcodeForView(pmConfig *config, pmFPAfile *file, const pmFPAview *view)
+    {
+        psMemId id = psMemGetId();
+        psString str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+//        str[2] = "../dataFiles/SampleIPPConfig";
+        str[2] = "../config/data/SampleIPPConfig";
+        psS32 argc = 3;
+        pmConfig *config = pmConfigRead(&argc, str, "RecipeName");
+        ok(config, "pmConfigRead() returned non-NULL");
+        pmFPAfile *file = pmFPAfileAlloc();
+        // XXX: Insert code to read a pmFPAfile correctly
+        pmFPAview *view = pmFPAviewAlloc(0);
+
+        skip_start(!config, 2, "Skipping tests because pmConfigRead() failed");        
+        bool rc;
+        psMetadata *recipe  = psMetadataLookupPtr(&rc, config->recipes, "PPIMAGE");
+        char *rule = psMetadataLookupStr(&rc, recipe, "PHOTCODE.RULE");
+        psString goodPhotcode = pmFPAfileNameFromRule(rule, file, view);
+
+        psString testPhotcode = pmConceptsPhotcodeForView(config, file, view);
+        ok(testPhotcode, "pmConceptsPhotcodeForView(config, file, view) returned non-NULL");
+        ok(!strcmp(goodPhotcode, testPhotcode), "pmConceptsPhotcodeForView() produced the correct string");
+        skip_end();
+        psFree(config);
+        psFree(file);
+        psFree(view);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/concepts/tap_pmConceptsUpdate.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/concepts/tap_pmConceptsUpdate.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/concepts/tap_pmConceptsUpdate.c	(revision 22158)
@@ -0,0 +1,248 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+// XXX: Use better name for the temporary FITS file
+// XXX: The code to generate and free the FPA hierarchy was copied from
+// tap-pmFPA.c.  EIther include it directly, or library, or something.
+// Also, get rid of the manual free functions and use psFree() once
+// it correctly frees child members
+// XXX: For the genSimpleFPA() code, add IDs to each function so that
+// the values set in each chip-?cell-?hdu-?image are unique
+// XXX: For the genSimpleFPA() code, write masks and weights as well
+
+#define CHIP_ALLOC_NAME        "ChipName"
+#define CELL_ALLOC_NAME        "CellName"
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define MISC_NAME2             "META01"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           4
+#define TEST_NUM_COLS           4
+#define NUM_READOUTS            3
+#define NUM_CELLS               10
+#define NUM_CHIPS               8
+#define NUM_HDUS                5
+#define BASE_IMAGE              10
+#define BASE_MASK               40
+#define BASE_WEIGHT             70
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+psPlaneTransform *PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM()
+{
+    psPlaneTransform *pt = psPlaneTransformAlloc(1, 1);
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+    return(pt);
+}
+
+psPlaneDistort *PS_CREATE_4D_IDENTITY_PLANE_DISTORT()
+{
+    psPlaneDistort *pd = psPlaneDistortAlloc(1, 1, 1, 1);
+    pd->x->coeff[1][0][0][0] = 1.0;
+    pd->y->coeff[0][1][0][0] = 1.0;
+    return(pd);
+}
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    cell->hdu = pmHDUAlloc("cellExtName");
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = psMemDecrRefCounter((psPtr) generateSimpleReadout(cell));
+    }
+
+    // First try to read data from ../dataFiles, then try dataFiles.
+    bool rc = pmConfigFileRead(&cell->hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        rc = pmConfigFileRead(&cell->hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            diag("pmConfigFileRead() was unsuccessful (from generateSimpleCell())");
+	}
+    }
+
+    cell->hdu->images = psArrayAlloc(NUM_HDUS);
+    cell->hdu->masks = psArrayAlloc(NUM_HDUS);
+    cell->hdu->weights = psArrayAlloc(NUM_HDUS);
+    for (int k = 0 ; k < NUM_HDUS ; k++) {
+        cell->hdu->images->data[k]  = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        cell->hdu->masks->data[k]   = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        cell->hdu->weights->data[k] = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(cell->hdu->images->data[k], (float) (BASE_IMAGE+k));
+        psImageInit(cell->hdu->masks->data[k], (psU8) (BASE_MASK+k));
+        psImageInit(cell->hdu->weights->data[k], (float) (BASE_WEIGHT+k));
+    }
+
+    psRegion *region = psRegionAlloc(0.0, 0.0, 0.0, 0.0);
+    // You shouldn't have to remove the key from the metadata.
+    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC");
+    psMetadataAddPtr(cell->concepts, PS_LIST_TAIL|PS_META_REPLACE, "CELL.TRIMSEC", PS_DATA_REGION, "I am a region", region);
+    psFree(region);
+    return(cell);
+}
+
+/******************************************************************************
+generateSimpleChip(): This function generates a pmChip data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmChip *generateSimpleChip(pmFPA *fpa)
+{
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    chip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    chip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    psMetadataAddS32(chip->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(chip->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(chip->cells, NUM_CELLS);
+    for (int i = 0 ; i < NUM_CELLS ; i++) {
+        chip->cells->data[i] = psMemDecrRefCounter((psPtr) generateSimpleCell(chip));
+    }
+
+    // XXX: Add code to initialize chip pmConcepts
+
+
+    return(chip);
+}
+
+/******************************************************************************
+generateSimpleFPA(): This function generates a pmFPA data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmFPA* generateSimpleFPA(psMetadata *camera)
+{
+    pmFPA* fpa = pmFPAAlloc(camera);
+    fpa->fromTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toSky = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+    psMetadataAddS32(fpa->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    if (camera != NULL) {
+        psMetadataAddS32((psMetadata *) fpa->camera, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    }
+    psMetadataAddS32(fpa->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+
+    psArrayRealloc(fpa->chips, NUM_CHIPS);
+    for (int i = 0 ; i < NUM_CHIPS ; i++) {
+        fpa->chips->data[i] = psMemDecrRefCounter((psPtr) generateSimpleChip(fpa));
+    }
+    pmConceptsBlankFPA(fpa);
+    return(fpa);
+}
+
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(7);
+
+
+    // ----------------------------------------------------------------------
+    // pmConceptsUpdate() tests: NULL inputs
+    // bool pmConceptsUpdate(const pmFPA *fpa, const pmChip *chip, const pmCell *cell)
+    {
+        psMemId id = psMemGetId();
+        ok(pmConceptsUpdate(NULL, NULL, NULL), "pmConceptsUpdate(NULL, NULL, NULL) returned TRUE");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    
+    // pmConceptsUpdate() tests: acceptable inputs
+    // XXX: Must add tests for the BIASSEC concepts
+    {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA *fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        pmCell *cell = chip->cells->data[0];
+        bool rc = pmConceptsUpdate(NULL, NULL, cell);
+
+        // Calculate expected myTrimsec
+        bool xStatus, yStatus; // Status of MD lookups
+        psImageBinning *binning = psImageBinningAlloc();
+        binning->nXbin = psMetadataLookupS32(&xStatus, cell->concepts, "CELL.XBIN");
+        binning->nYbin = psMetadataLookupS32(&yStatus, cell->concepts, "CELL.YBIN");
+        psRegion *goodTrimsec = psMetadataLookupPtr(NULL, cell->concepts, "CELL.TRIMSEC");
+        double goodTrimsecX0 = goodTrimsec->x0;
+        double goodTrimsecX1 = goodTrimsec->x1;
+        double goodTrimsecY0 = goodTrimsec->y0;
+        double goodTrimsecY1 = goodTrimsec->y1;
+        goodTrimsecX0/= binning->nXbin;
+        goodTrimsecX1/= binning->nXbin;
+        goodTrimsecY0/= binning->nYbin;
+        goodTrimsecY1/= binning->nYbin;
+        goodTrimsecX0 = (int) goodTrimsec->x0;
+        if (goodTrimsec->x1 > (int)goodTrimsec->x1) {
+            goodTrimsecX1 = (int)goodTrimsec->x1 + 1;
+         } else {
+            goodTrimsecX1 = (int)goodTrimsec->x1;
+	 }
+        goodTrimsecY0 = (int)goodTrimsec->y0;
+        if (goodTrimsec->y1 > (int)goodTrimsec->y1) {
+            goodTrimsecY1 = (int)goodTrimsec->y1 + 1;
+	} else {
+            goodTrimsecY1 = (int)goodTrimsec->y1;
+	}
+        psFree(binning);
+
+        // Add CELL.TRIMSEC.UPDATE concept to cell->concepts
+        psMetadataAddS32(cell->concepts, PS_LIST_HEAD, "CELL.TRIMSEC.UPDATE", 0, NULL, 32);
+        psS32 num = psMetadataLookupS32(&rc, cell->concepts, "CELL.TRIMSEC.UPDATE");
+        ok(rc, "Successfully added CELL.TRIMSEC.UPDATE to cell->concepts (%d)", num);
+
+        // Add CELL.BIASSEC.UPDATE concept to cell->concepts
+        psMetadataAddS32(cell->concepts, PS_LIST_HEAD, "CELL.BIASSEC.UPDATE", 0, NULL, 32);
+        num = psMetadataLookupS32(&rc, cell->concepts, "CELL.BIASSEC.UPDATE");
+        ok(rc, "Successfully added CELL.BIASSEC.UPDATE to cell->concepts (%d)", num);
+
+        // Call pmConceptsUpdate to update the CELL.TRIMSEC concept
+        ok(rc, "pmConceptsUpdate(NULL, NULL, pmCell) returned TRUE");
+
+        psRegion *testTrimsec = psMetadataLookupPtr(NULL, cell->concepts, "CELL.TRIMSEC"); // Trim section
+        ok(testTrimsec->x1 == goodTrimsecX1 && testTrimsec->y1 == goodTrimsecY1 &&
+           testTrimsec->x0 == goodTrimsecX0 && testTrimsec->y0 == goodTrimsecY0,
+           "pmConceptsUpdate() updated CELL.TRIMSEC correctly (%f %f)",
+            testTrimsec->x1, testTrimsec->y1);
+
+        // XXX: This fails but the problem might be with the test code
+        if (0) {
+            num = psMetadataLookupS32(&rc, cell->concepts, "CELL.TRIMSEC.UPDATE");
+            ok(!rc, "pmConceptsUpdate() removed CELL.TRIMSEC.UPDATE to cell->concepts (%d)", num);
+        }
+
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/.cvsignore	(revision 22158)
@@ -0,0 +1,7 @@
+.deps
+.libs
+Makefile
+Makefile.in
+temp
+tst_pmConfig
+SampleIPPConfig
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/Makefile.am	(revision 22158)
@@ -0,0 +1,35 @@
+AM_CPPFLAGS = \
+	$(SRCINC) \
+	-I$(top_srcdir)/test/tap/src \
+	-I$(top_srcdir)/test/pstap/src \
+	$(PSMODULES_CFLAGS)
+
+AM_LDFLAGS = \
+	$(top_builddir)/src/libpsmodules.la  \
+	$(top_builddir)/test/tap/src/libtap.la \
+	$(top_builddir)/test/pstap/src/libpstap.la \
+	$(PSMODULES_LIBS)
+
+TEST_PROGS = \
+	tap_pmConfig \
+	tap_pmConfigCommand \
+	tap_pmConfigMask \
+	tap_pmErrorCodes \
+	tap_pmVersion
+
+check_DATA =
+
+
+EXTRA_DIST = data
+
+if BUILD_TESTS
+bin_PROGRAMS = $(TEST_PROGS)
+TESTS = $(TEST_PROGS)
+else
+check_PROGRAMS = $(TEST_PROGS)
+endif
+
+CLEANFILES = $(check_DATA) temp/* core core.* *~ *.bb *.bbg *.da gmon.out
+
+test: check
+	$(top_srcdir)/test/test.pl
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/SampleIPPConfig
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/SampleIPPConfig	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/SampleIPPConfig	(revision 22158)
@@ -0,0 +1,74 @@
+### Example .ipprc file
+    PATH            STR     .
+    DATAPATH	str	datapath
+
+PATH            STR     .
+
+### Database configuration
+DBSERVER	STR	localhost		# Database host name (for psDBInit)
+DBUSER		STR	test			# Database user name (for psDBInit)
+DBPASSWORD	STR	DB-PW			# Database password (for psDBInit)
+DBNAME          STR     test                    # ????
+DBPORT		S32	0
+
+
+### Setups for each camera system
+CAMERAS		METADATA
+	CAMERA0		STR	camera0/camera.config
+	CAMERA1		STR	camera1/camera.config
+END
+
+### psLib setup
+#TIME		STR	/home/mithrandir/price/pan-starrs/jhroot/i686-pc-linux-gnu/etc/pslib/psTime.config	# Time configuration file
+LOGLEVEL	S32	3			# Logging level; 3=INFO
+LOGFORMAT	STR	HLNM			# Log format
+LOGDEST	STR	STDOUT				# Log destination
+TRACE		METADATA			# Trace levels
+	dummyTraceFunc01	S32	1
+	dummyTraceFunc02	S32	2
+END
+ARBITRARY_STRING_S32	S32	20
+ARBITRARY_STRING_F32	F32	21.0
+ARBITRARY_STRING_F64	F64	22.0
+ARBITRARY_STRING_STR	STR	19.0
+ARBITRARY_STRING_BOOL_T	BOOL	true
+ARBITRARY_STRING_BOOL_F	BOOL	false
+=======
+    CAMERAS		METADATA
+	CAMERA0		STR	camera0/camera.config
+	CAMERA1		STR	camera1/camera.config
+    END
+
+### Setups for psLib
+    TIME		STR	time.config
+    LOGLEVEL	S32	3
+    LOGFORMAT	STR	HLNM
+    LOGDEST	STR	STDOUT
+
+### Default trace logging initializations
+    TRACE		METADATA
+	dummyTraceFacility01	S32	1
+	dummyTraceFacility02	S32	2
+    END
+
+### Predefined recipe files
+    RECIPES         METADATA                # Site-level recipes
+        R00		STR	recipes/R00.config
+        R01		STR	recipes/R01.config
+        R02		STR	recipes/R02.config
+        R03		STR	recipes/R03.config
+    END
+
+### Misc arbitraty metadata
+    ARBITRARY_STRING_S32	S32	20
+    ARBITRARY_STRING_F32	F32	21.0
+    ARBITRARY_STRING_F64	F64	22.0
+    ARBITRARY_STRING_STR	STR	19.0
+    ARBITRARY_STRING_BOOL_T	BOOL	true
+    ARBITRARY_STRING_BOOL_F	BOOL	false
+
+RECIPES         METADATA
+	MASKS			STR	recipes_masks.config
+        JUNK_RECIPE_00		STR	recipe_file00
+        JUNK_RECIPE_01		STR	recipe_file01
+END
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/basicConfig
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/basicConfig	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/basicConfig	(revision 22158)
@@ -0,0 +1,25 @@
+
+TEST MULTI
+TEST STR FOO
+TEST STR BAR
+
+PATH              STR     .
+
+# load the site-specific information from here
+SITE              STR     site.config
+
+# load the system configuration information from here
+SYSTEM            STR     system.config
+
+### psLib setup
+LOGLEVEL	S32	5			# Logging level; 3=INFO
+LOGFORMAT	STR	M			# Log format
+LOGDEST		STR	STDERR			# Log destination
+TRACEDEST	STR	STDERR			# Trace destination
+
+# place default trace lines here
+TRACE		METADATA			# Trace levels
+  err		S32	10
+# psLib.db      S32	10
+END
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera0/camera.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera0/camera.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera0/camera.config	(revision 22158)
@@ -0,0 +1,15 @@
+FORMATS         METADATA
+        C0_FM0     STR     camera0/format0.config
+        C0_FM1     STR     camera0/format1.config
+END
+
+RECIPES         METADATA
+        C0_RECIPE0          STR     camera0/recipe0.config
+        C0_RECIPE1          STR     camera0/recipe1.config
+END
+
+FPA     METADATA
+        ccd00   STR     LeftAmp RightAmp
+        ccd01   STR     LeftAmp RightAmp
+END
+ID      STR     CAMERA0
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera0/format0.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera0/format0.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera0/format0.config	(revision 22158)
@@ -0,0 +1,36 @@
+RULE    METADATA
+        F0_KEY0        STR     string20
+        F0_KEY1        STR     string21
+        F0_KEY2        S32     20
+END
+
+FILE    METADATA
+        PHU             STR     FPA
+        EXTENSIONS      STR     CELL
+        FPA.NAME        STR     EXPNUM
+END
+
+DEFAULTS        METADATA
+        F0_DEF0           STR     DefString20
+        F0_DEF1           STR     DefString21
+        F0_DEF2           F32     21.0
+        F0_DEF3           S32     22
+END
+
+CELLS   METADATA
+        left    METADATA        # Left amplifier
+                CELL.BIASSEC.SOURCE     STR     HEADER
+                CELL.TRIMSEC.SOURCE     STR     HEADER
+        END
+        right   METADATA        # Right amplifier
+                CELL.BIASSEC.SOURCE     STR     HEADER
+                CELL.TRIMSEC.SOURCE     STR     HEADER
+        END
+END
+
+ID	STR	camera0/format0.config
+
+TRANSLATION     METADATA
+        FPA.TELESCOPE   STR     TELESCOP
+        FPA.INSTRUMENT  STR     INSTRUME
+END
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera0/format1.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera0/format1.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera0/format1.config	(revision 22158)
@@ -0,0 +1,34 @@
+RULE    METADATA
+        F1_KEY0        STR     string30
+        F1_KEY1        STR     string31
+        F1_KEY2        S32     30
+END
+
+FILE    METADATA
+        PHU             STR     FPA
+        EXTENSIONS      STR     CELL
+        FPA.NAME        STR     EXPNUM
+END
+
+DEFAULTS        METADATA
+        F1_DEF0           STR     DefString30
+        F1_DEF1           STR     DefString31
+        F1_DEF2           F32     31.0
+        F1_DEF3           S32     32
+END
+
+CELLS   METADATA
+        left    METADATA        # Left amplifier
+                CELL.BIASSEC.SOURCE     STR     HEADER
+                CELL.TRIMSEC.SOURCE     STR     HEADER
+        END
+        right   METADATA        # Right amplifier
+                CELL.BIASSEC.SOURCE     STR     HEADER
+                CELL.TRIMSEC.SOURCE     STR     HEADER
+        END
+END
+
+TRANSLATION     METADATA
+        FPA.TELESCOPE   STR     TELESCOP
+        FPA.INSTRUMENT  STR     INSTRUME
+END
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera0/recipe0.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera0/recipe0.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera0/recipe0.config	(revision 22158)
@@ -0,0 +1,4 @@
+R0_KEY0		STR	RecipeString0
+R0_KEY1		STR	RecipeString1
+R0_KEY2		S32	2
+R0_KEY3		F32	3
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera0/recipe1.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera0/recipe1.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera0/recipe1.config	(revision 22158)
@@ -0,0 +1,4 @@
+R1_KEY0		STR	RecipeString10
+R1_KEY1		STR	RecipeString11
+R1_KEY2		S32	12
+R1_KEY3		F32	13
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera1/camera.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera1/camera.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera1/camera.config	(revision 22158)
@@ -0,0 +1,14 @@
+FORMATS         METADATA
+        C1_FM0     STR     camera1/format0.config
+        C1_FM1     STR     camera1/format1.config
+END
+
+RECIPES         METADATA
+        C1_RECIPE0          STR     camera1/recipe0.config
+        C1_RECIPE1          STR     camera1/recipe1.config
+END
+
+FPA     METADATA
+        ccd00   STR     LeftAmp RightAmp
+        ccd01   STR     LeftAmp RightAmp
+END
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera1/format0.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera1/format0.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera1/format0.config	(revision 22158)
@@ -0,0 +1,34 @@
+RULE    METADATA
+        F0_KEY0        STR     string40
+        F0_KEY1        STR     string41
+        F0_KEY2        S32     420
+END
+
+FILE    METADATA
+        PHU             STR     FPA
+        EXTENSIONS      STR     CELL
+        FPA.NAME        STR     EXPNUM
+END
+
+DEFAULTS        METADATA
+        F0_DEF0           STR     DefString40
+        F0_DEF1           STR     DefString41
+        F0_DEF2           F32     41.0
+        F0_DEF3           S32     44
+END
+
+CELLS   METADATA
+        left    METADATA        # Left amplifier
+                CELL.BIASSEC.SOURCE     STR     HEADER
+                CELL.TRIMSEC.SOURCE     STR     HEADER
+        END
+        right   METADATA        # Right amplifier
+                CELL.BIASSEC.SOURCE     STR     HEADER
+                CELL.TRIMSEC.SOURCE     STR     HEADER
+        END
+END
+
+TRANSLATION     METADATA
+        FPA.TELESCOPE   STR     TELESCOP
+        FPA.INSTRUMENT  STR     INSTRUME
+END
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera1/format1.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera1/format1.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera1/format1.config	(revision 22158)
@@ -0,0 +1,34 @@
+RULE    METADATA
+        F1_KEY0        STR     string80
+        F1_KEY1        STR     string81
+        F1_KEY2        S32     80
+END
+
+FILE    METADATA
+        PHU             STR     FPA
+        EXTENSIONS      STR     CELL
+        FPA.NAME        STR     EXPNUM
+END
+
+DEFAULTS        METADATA
+        F1_DEF0           STR     DefString80
+        F1_DEF1           STR     DefString81
+        F1_DEF2           F32     81.0
+        F1_DEF3           S32     82
+END
+
+CELLS   METADATA
+        left    METADATA        # Left amplifier
+                CELL.BIASSEC.SOURCE     STR     HEADER
+                CELL.TRIMSEC.SOURCE     STR     HEADER
+        END
+        right   METADATA        # Right amplifier
+                CELL.BIASSEC.SOURCE     STR     HEADER
+                CELL.TRIMSEC.SOURCE     STR     HEADER
+        END
+END
+
+TRANSLATION     METADATA
+        FPA.TELESCOPE   STR     TELESCOP
+        FPA.INSTRUMENT  STR     INSTRUME
+END
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera1/recipe0.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera1/recipe0.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera1/recipe0.config	(revision 22158)
@@ -0,0 +1,4 @@
+R0_KEY0		STR	RecipeString120
+R0_KEY1		STR	RecipeString121
+R0_KEY2		S32	122
+R0_KEY3		F32	123
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera1/recipe1.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera1/recipe1.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/camera1/recipe1.config	(revision 22158)
@@ -0,0 +1,4 @@
+R1_KEY0		STR	RecipeString230
+R1_KEY1		STR	RecipeString2311
+R1_KEY2		S32	232
+R1_KEY3		F32	233
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/path2/SampleIPPConfig2
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/path2/SampleIPPConfig2	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/path2/SampleIPPConfig2	(revision 22158)
@@ -0,0 +1,32 @@
+### Example .ipprc file
+
+### Database configuration
+DBSERVER	STR	ippdb.ifa.hawaii.edu	# Database host name (for psDBInit)
+DBUSER		STR	ipp			# Database user name (for psDBInit)
+DBPASSWORD	STR	password		# Database password (for psDBInit)
+
+### Setups for each camera system
+CAMERAS		METADATA
+	MEGACAM_RAW	STR	megacam_raw.config
+	MEGACAM_SPLICE	STR	megacam_splice.config
+	GPC1_RAW	STR	gpc1_raw.config
+	LRIS_BLUE	STR	lris_blue.config
+	LRIS_RED	STR	lris_red.config
+END
+
+### psLib setup
+#TIME		STR	/home/mithrandir/price/pan-starrs/jhroot/i686-pc-linux-gnu/etc/pslib/psTime.config	# Time configuration file
+LOGLEVEL	S32	3			# Logging level; 3=INFO
+LOGFORMAT	STR	HLNM			# Log format
+LOGDEST	STR	STDOUT				# Log destination
+TRACE		METADATA			# Trace levels
+	dummyTraceFunc01	S32	1
+	dummyTraceFunc02	S32	2
+END
+ARBITRARY_STRING_S32	S32	20
+ARBITRARY_STRING_F32	F32	21.0
+ARBITRARY_STRING_F64	F64	22.0
+ARBITRARY_STRING_STR	STR	19.0
+ARBITRARY_STRING_BOOL_T	BOOL	true
+ARBITRARY_STRING_BOOL_F	BOOL	false
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/recipe_file00
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/recipe_file00	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/recipe_file00	(revision 22158)
@@ -0,0 +1,2 @@
+recipe00		BOOL    TRUE
+recipe01		BOOL    FALSE
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/recipe_file01
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/recipe_file01	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/recipe_file01	(revision 22158)
@@ -0,0 +1,2 @@
+recipe00		BOOL    FALSE
+recipe01		BOOL    TRUE
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/recipes/recipe1.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/recipes/recipe1.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/recipes/recipe1.config	(revision 22158)
@@ -0,0 +1,12 @@
+
+KEY1	STR	VALUE1
+KEY2	STR	VALUE2
+
+RECIPE1_ALT METADATA
+  KEY2  STR     VALUE2_ALT
+END
+
+KEY3 MULTI 
+KEY3 STR V1
+KEY3 STR V2
+KEY3 STR V3
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/recipes_masks.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/recipes_masks.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/recipes_masks.config	(revision 22158)
@@ -0,0 +1,10 @@
+### Recipe specifying values for various mask concepts
+BLANK           U8      0x01            # The pixel is blank or has no (valid) data
+FLAT            U8      0x02            # The pixel is non-positive in the flat-field
+DETECTOR        U8      0x02            # The detector pixel is bad (e.g., bad column, charge trap)
+SAT             U8      0x04            # The pixel is saturated in the image of interest
+BAD             U8      0x04            # The pixel is low in the image of interest
+RANGE           U8      0x04            # The pixel is out of range in the image of interest
+CR              U8      0x08            # The pixel is probably a CR
+SUSPECT         U8      0x40            # The pixel is suspected of being bad, but may not be
+MARK            U8      0x80            # The pixel is marked as temporarily ignored
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/site.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/site.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/site.config	(revision 22158)
@@ -0,0 +1,32 @@
+
+# place your data directories here and refer to as path://PATH/remainder
+DATAPATH	METADATA
+	TEST1	STR	dataTest1
+	TEST2	STR	dataTest2
+END
+
+# List of tessellations, and their DVO CATDIR
+TESSELLATIONS	METADATA
+	TESS1		STR	path://TEST1/skycells/
+	TESS2		STR	path://TEST2/skycells/
+END
+
+# dvo databases used for output
+DVO.CATDIRS	METADATA
+	CATDIR1		STR	path://TEST1/catdir/
+END
+
+# dvo databases used for psastro reference
+PSASTRO.CATDIRS	METADATA
+	CATDIR1		STR	path://TEST1/catdir/
+END
+
+# nebulous server
+NEB_SERVER	STR	http://alala:80/nebulous	# Nebulous server
+
+# Database configuration
+DBSERVER	STR	ipp000			# Database host name (for psDBInit)
+DBNAME		STR	XXX			# Database name (for psDBInit)
+DBUSER		STR	XXX			# Database user name (for psDBInit)
+DBPASSWORD	STR	XXX			# Database password (for psDBInit)
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/system.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/system.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/system.config	(revision 22158)
@@ -0,0 +1,24 @@
+## system-wide options : these are concepts not specific to any camera or recipe
+
+### Setups for each camera system
+CAMERAS		METADATA
+	TEST1			STR	testCamera1/camera.config
+END
+
+### camera names as expected by DVO
+DVO.CAMERAS		METADATA
+	TEST1			STR	testCamera1
+END
+
+# Header keywords for skycell concepts; required because DVO doesn't read HIERARCH
+SKYCELLS	METADATA
+	FPA.TIME	STR	MJD-OBS
+	CELL.TIME	STR	MJD-OBS
+	FPA.EXPOSURE	STR	EXPTIME
+	CELL.EXPOSURE	STR	EXPTIME
+	FPA.AIRMASS	STR	AIRMASS
+END
+
+RECIPES		METADATA		# Site-level recipes
+	RECIPE1		STR		recipes/recipe1.config  # Simple recipe
+END
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/testCamera1/camera.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/testCamera1/camera.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/testCamera1/camera.config	(revision 22158)
@@ -0,0 +1,12 @@
+
+RECIPES	METADATA	# Site-level recipes
+	RECIPE1	STR	testCamera1/recipe1.config  # Simple recipe
+END
+
+FORMATS METADATA
+  	RAW  	STR	testCamera1/format.config
+END
+
+FPA	METADATA
+	chip	STR	cell
+END
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/testCamera1/format.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/testCamera1/format.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/testCamera1/format.config	(revision 22158)
@@ -0,0 +1,53 @@
+# sample MEF format with HDU = cell
+
+# How to identify this type
+RULE	METADATA
+	TELESCOP	STR	TestTelescope
+	DETECTOR	STR	TestDetector
+	NAXIS           S32     0
+	EXTEND		BOOL	T
+END
+
+# How to read this data
+FILE	METADATA
+	PHU		STR	FPA	# The FITS file represents an entire FPA
+	EXTENSIONS	STR	CELL	# The extensions represent cells
+	FPA.NAME	STR	EXPNUM	# A PHU keyword for unique identifier within the hierarchy level
+END
+
+# What's in the FITS file?
+CONTENTS	METADATA
+	# Extension name, chip name:type
+	amp		STR	chip:LeftAmp:left
+END
+
+# Specify the cell data
+CELLS	METADATA
+	left	METADATA	# Left amplifier
+		CELL.BIASSEC.SOURCE	STR	HEADER
+		CELL.TRIMSEC.SOURCE	STR	HEADER
+		CELL.BIASSEC		STR	BIASSEC
+		CELL.TRIMSEC		STR	DATASEC
+		CELL.XPARITY		S32	1 # We could have specified this as a DEFAULT, but this works
+		CELL.X0			S32	1
+		CELL.Y0			S32	1
+	END
+END
+
+# How to translate PS concepts into FITS headers
+TRANSLATION	METADATA
+	FPA.AIRMASS		STR	AIRMASS
+	FPA.FILTERID		STR	FILTER
+END
+
+# Default PS concepts that may be specified by value
+DEFAULTS	METADATA
+	FPA.TELESCOPE		STR	CFHT
+	FPA.INSTRUMENT		STR	MEGACAM
+END
+
+# Where there might be some ambiguity, specify the format
+FORMATS		METADATA
+	FPA.RA		STR	HOURS
+	FPA.DEC		STR	DEGREES
+END
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/testCamera1/recipe1.config
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/testCamera1/recipe1.config	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/data/testCamera1/recipe1.config	(revision 22158)
@@ -0,0 +1,10 @@
+
+KEY1	STR	VALUE1_CAMERA
+# KEY2	STR	VALUE2_CAMERA
+
+RECIPE1_ALT METADATA
+  KEY1  STR     VALUE1_CAMERA_ALT
+END
+
+KEY3 MULTI RESET
+KEY3 STR V4
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/tap_pmConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/tap_pmConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/tap_pmConfig.c	(revision 22158)
@@ -0,0 +1,1284 @@
+/** @file tst_pmConfig.c
+ *
+ *  @brief Contains the tests for pmConfig.c:
+ *
+ * This code will test the pmConfig() routine.
+*       pmConfigReadParamsSet
+*       pmConfigAlloc		
+*       pmConfigSet
+*       pmConfigDone
+*       pmConfigFileRead
+*        pmConfigValidateCameraFormat
+*        pmConfigCameraFormatFromHeader
+*        pmConfigCameraByName
+?        pmConfigDB
+*        pmConfigConformHeader
+-        pmConfigFileSets
+-        pmConfigFileSetsMD
+*        pmConfigConvertFilename
+*        pmConfigRead
+ * XXXX: Must determine what to do with NULL arguments, then test it.
+ *
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-06-10 20:58:28 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+#define ERR_TRACE_LEVEL         10
+#define	VERBOSE			0
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(181);
+    
+    // --------------------------------------------------------------------
+    // --------------------------------------------------------------------
+    // Tests for pmConfigReadParamsSet()
+    {
+        psMemId id = psMemGetId();
+        bool oldReadCameraConfig = pmConfigReadParamsSet(false);
+        ok(oldReadCameraConfig == true, "pmConfigReadParamsSet() returned old value correctly");
+        oldReadCameraConfig = pmConfigReadParamsSet(true);
+        ok(oldReadCameraConfig == false, "pmConfigReadParamsSet() returned old value correctly");
+        oldReadCameraConfig = pmConfigReadParamsSet(true);
+        ok(oldReadCameraConfig == true, "pmConfigReadParamsSet() returned new value correctly");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    
+    
+    // --------------------------------------------------------------------
+    // --------------------------------------------------------------------
+    // Tests for pmConfigAlloc()
+    // XXX: Add a MemCheckConfig() function to verify the return type
+    {
+        psMemId id = psMemGetId();
+
+        pmConfig *myConfig = pmConfigAlloc();
+        ok(myConfig != NULL, "pmConfigAlloc() returned non-NULL");
+        skip_start(myConfig == NULL, 10, "skipping tests because pmConfigAlloc() returned NULL");
+        ok(myConfig->site == NULL, "pmConfigAlloc() initialized pmConfig->site properly");
+        ok(myConfig->camera == NULL, "pmConfigAlloc() initialized pmConfig->camera properly");
+        ok(myConfig->cameraName == NULL, "pmConfigAlloc() initialized pmConfig->cameraName properly");
+        ok(myConfig->format == NULL, "pmConfigAlloc() initialized pmConfig->format properly");
+        ok(myConfig->formatName == NULL, "pmConfigAlloc() initialized pmConfig->formatName properly");
+        ok(myConfig->recipes != NULL && psMemCheckMetadata(myConfig->recipes),
+            "pmConfigAlloc() initialized pmConfig->recipes properly");
+        ok(myConfig->recipesRead == PM_RECIPE_SOURCE_NONE, "pmConfigAlloc() initialized pmConfig->recipesRead properly");
+        ok(myConfig->recipeSymbols != NULL && psMemCheckMetadata(myConfig->recipeSymbols),
+            "pmConfigAlloc() initialized pmConfig->recipesSymbols properly");
+        ok(myConfig->arguments != NULL && psMemCheckMetadata(myConfig->arguments),
+            "pmConfigAlloc() initialized pmConfig->arguments properly");
+        ok(myConfig->database == NULL, "pmConfigAlloc() initialized pmConfig->database properly");
+        ok(myConfig->defaultRecipe == NULL, "pmConfigAlloc() initialized pmConfig->defaultRecipe properly");
+
+        skip_end();
+        psFree(myConfig);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    
+    
+    // --------------------------------------------------------------------
+    // --------------------------------------------------------------------
+    // Test pmConfigSet()
+    // Test with NULL input
+    // XX: Test with empty string?
+    {
+        psMemId id = psMemGetId();
+        pmConfigSet(NULL);
+        ok(true, "called pmConfigSet() with NULL input pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_VALUE == tmpErr->code,
+          "pmConfigSet(NULL) created the PS_ERR_BAD_PARAMETER_VALUE error");
+        psFree(tmpErr);
+        psErrorClear();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    
+    
+    // Test with acceptable config file name, with a simple path
+    {
+        pmConfigDone();
+        psMemId id = psMemGetId();
+        psMetadata *config = NULL;
+        bool rc = pmConfigFileRead(&config, "SampleIPPConfig2", "DESCRIPTION");
+        ok(rc == false, "pmConfigFileRead() returned FALSE before calling pmConfigSet()");
+        pmConfigSet("../dataFiles/path2:dataFiles/path2");
+        rc = pmConfigFileRead(&config, "SampleIPPConfig2", "DESCRIPTION");
+        ok(rc == true, "pmConfigFileRead() returned TRUE after calling pmConfigSet() (test 1)");
+        psFree(config);
+        pmConfigDone();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test with acceptable config file name, with a compound path
+    {
+        pmConfigDone();
+        psMemId id = psMemGetId();
+        psMetadata *config = NULL;
+        bool rc = pmConfigFileRead(&config, "SampleIPPConfig2", "DESCRIPTION");
+        ok(rc == false, "pmConfigFileRead() returned FALSE before calling pmConfigSet()");
+        pmConfigSet("junk:../dataFiles/path2:dataFiles/path2:data/path5");
+        rc = pmConfigFileRead(&config, "SampleIPPConfig2", "DESCRIPTION");
+        ok(rc == true, "pmConfigFileRead() returned TRUE after calling pmConfigSet() (test 2)");
+        psFree(config);
+        pmConfigDone();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // --------------------------------------------------------------------
+    // --------------------------------------------------------------------
+    // Test pmConfigDone(): ensure it frees memory allocated by pmConfigSet();
+    // This also ensures that pmConfigSet() psFrees memory between calls
+    {
+        psMemId id = psMemGetId();
+        pmConfigSet("junk01");
+        pmConfigSet("junk:../dataFiles/path2:dataFiles/path2:data/path5");
+        pmConfigSet("junk02");
+        pmConfigDone();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks: pmConfigDone()");
+    }
+
+
+
+    // --------------------------------------------------------------------
+    // --------------------------------------------------------------------
+    // Test pmConfigFileRead()
+    // Test with NULL config pointer
+    // XXX: There's a memory leak if the first argument points to data that's
+    // already allocated (pmConfigFileRead() frees the first argument)
+    {
+        psMemId id = psMemGetId();
+        psString name = "foo1";
+        psString desc = "foo2";
+        bool rc = pmConfigFileRead(NULL, name, desc);
+        ok(rc == false, "pmConfigFileRead() returned FALSE with NULL config pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_NULL == tmpErr->code,
+          "pmConfigFileRead() created the PS_ERR_BAD_PARAMETER_NULL error");
+        psFree(tmpErr);
+        psErrorClear();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test with NULL name pointer
+    // XXX: Test with empty name string?
+    {
+        psMemId id = psMemGetId();
+        psMetadata *config = psMetadataAlloc();
+        psString desc = "foo2";
+        bool rc = pmConfigFileRead(&config, NULL, desc);
+        ok(rc == false, "pmConfigFileRead() returned FALSE with NULL name pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_VALUE == tmpErr->code,
+          "pmConfigFileRead() created the PS_ERR_BAD_PARAMETER_VALUE error");
+        psFree(tmpErr);
+        psErrorClear();
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test with NULL desc pointer
+    // XXX: Test with empty desc string and otherwise acceptable inputs.
+    // That generated errors elsewhere.
+    {
+        psMemId id = psMemGetId();
+        psMetadata *config = psMetadataAlloc();
+        psString name = "foo1";
+        bool rc = pmConfigFileRead(&config, name, NULL);
+        ok(rc == false, "pmConfigFileRead() returned FALSE with NULL desc pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_VALUE == tmpErr->code,
+          "pmConfigFileRead() created the PS_ERR_BAD_PARAMETER_VALUE error");
+        psFree(tmpErr);
+        psErrorClear();
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test with acceptable config file name, no paths
+    {
+        psMemId id = psMemGetId();
+        psMetadata *config = NULL;
+        psString name = "../dataFiles/SampleIPPConfig";
+        psString name2 = "dataFiles/SampleIPPConfig";
+        psString desc = "DESCRIPTION";
+        // First try to read data from ../dataFiles, then try dataFiles.
+        bool rc = pmConfigFileRead(&config, name, desc);
+        if (!rc) {
+            rc = pmConfigFileRead(&config, name2, desc);
+	}
+        ok(rc == true, "pmConfigFileRead() returned TRUE with acceptable inputs");
+
+        // Test the several arbitrary config file strings.
+        psS32 tmpInt = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_S32");
+        ok(rc == true && tmpInt == 20, "pmConfigFileRead() properly set metadata (S32)");
+        psF32 tmpFloat = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_F32");
+        ok(rc == true && tmpFloat == 21.0, "pmConfigFileRead() properly set metadata (F32)");
+        psF64 tmpDub = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_F64");
+        ok(rc == true && tmpDub == 22.0, "pmConfigFileRead() properly set metadata (F64)");
+        psBool tmpBool = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_BOOL_T");
+        ok(rc == true && tmpBool == true, "pmConfigFileRead() properly set metadata (bool)");
+        tmpBool = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_BOOL_F");
+        ok(rc == true && tmpBool == false, "pmConfigFileRead() properly set metadata (bool)");
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test with acceptable config file name, no paths
+    {
+        psMemId id = psMemGetId();
+        psMetadata *config = NULL;
+        psString name = "../dataFiles/SampleIPPConfig";
+        psString name2 = "dataFiles/SampleIPPConfig";
+        psString desc = "DESCRIPTION";
+        bool rc = pmConfigFileRead(&config, name, desc);
+        if (!rc) {
+            rc = pmConfigFileRead(&config, name2, desc);
+	}
+        ok(rc == true, "pmConfigFileRead() returned TRUE with acceptable inputs");
+
+        // Test the several arbitrary config file strings.
+        psS32 tmpInt = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_S32");
+        ok(rc == true && tmpInt == 20, "pmConfigFileRead() properly set metadata (S32)");
+        psF32 tmpFloat = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_F32");
+        ok(rc == true && tmpFloat == 21.0, "pmConfigFileRead() properly set metadata (F32)");
+        psF64 tmpDub = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_F64");
+        ok(rc == true && tmpDub == 22.0, "pmConfigFileRead() properly set metadata (F64)");
+        psBool tmpBool = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_BOOL_T");
+        ok(rc == true && tmpBool == true, "pmConfigFileRead() properly set metadata (bool)");
+        tmpBool = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_BOOL_F");
+        ok(rc == true && tmpBool == false, "pmConfigFileRead() properly set metadata (bool)");
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test with acceptable config file name, no paths
+    {
+        psMemId id = psMemGetId();
+        psMetadata *config = NULL;
+        psString name = "../dataFiles/SampleIPPConfig";
+        psString name2 = "dataFiles/SampleIPPConfig";
+        psString desc = "DESCRIPTION";
+        bool rc = pmConfigFileRead(&config, name, desc);
+        if (!rc) {
+            rc = pmConfigFileRead(&config, name2, desc);
+	}
+        ok(rc == true, "pmConfigFileRead() returned TRUE with acceptable inputs");
+
+        // Test the several arbitrary config file strings.
+        psS32 tmpInt = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_S32");
+        ok(rc == true && tmpInt == 20, "pmConfigFileRead() properly set metadata (S32)");
+        psF32 tmpFloat = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_F32");
+        ok(rc == true && tmpFloat == 21.0, "pmConfigFileRead() properly set metadata (F32)");
+        psF64 tmpDub = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_F64");
+        ok(rc == true && tmpDub == 22.0, "pmConfigFileRead() properly set metadata (F64)");
+        psBool tmpBool = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_BOOL_T");
+        ok(rc == true && tmpBool == true, "pmConfigFileRead() properly set metadata (bool)");
+        tmpBool = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_BOOL_F");
+        ok(rc == true && tmpBool == false, "pmConfigFileRead() properly set metadata (bool)");
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test with acceptable config file name, with path
+    // Note: This also tests the pmConfigSet() function.
+    {
+        psMemId id = psMemGetId();
+        psMetadata *config = NULL;
+        psString name = "SampleIPPConfig2";
+        psString desc = "DESCRIPTION";
+        pmConfigSet("../dataFiles/path2:dataFiles/path2");
+        bool rc = pmConfigFileRead(&config, name, desc);
+        ok(rc == true, "pmConfigFileRead() returned TRUE using paths");
+        // Test the several arbitrary config file strings.
+        psS32 tmpInt = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_S32");
+        ok(rc == true && tmpInt == 20, "pmConfigFileRead() properly set metadata (S32)");
+        psF32 tmpFloat = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_F32");
+        ok(rc == true && tmpFloat == 21.0, "pmConfigFileRead() properly set metadata (F32)");
+        psF64 tmpDub = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_F64");
+        ok(rc == true && tmpDub == 22.0, "pmConfigFileRead() properly set metadata (F64)");
+        psBool tmpBool = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_BOOL_T");
+        ok(rc == true && tmpBool == true, "pmConfigFileRead() properly set metadata (bool)");
+        tmpBool = psMetadataLookupS32(&rc, config, "ARBITRARY_STRING_BOOL_F");
+        ok(rc == true && tmpBool == false, "pmConfigFileRead() properly set metadata (bool)");
+        psFree(config);
+        pmConfigDone();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // --------------------------------------------------------------------
+    // --------------------------------------------------------------------
+    // Test pmConfigValidateCameraFormat()
+    // Test with NULL valid pointer
+    // XXX: This is commented out because of a seg-fault
+    if (0) {
+        psMemId id = psMemGetId();
+        psMetadata *cameraFormat = psMetadataAlloc();
+        psMetadata *header = psMetadataAlloc();
+        bool rc = pmConfigValidateCameraFormat(NULL, cameraFormat, header);
+        ok(rc == false, "pmConfigValidateCameraFormat() returned FALSE with NULL valid pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_NULL == tmpErr->code,
+          "pmConfigValidateCameraFormat() created the PS_ERR_BAD_PARAMETER_NULL error");
+        psFree(tmpErr);
+        psErrorClear();
+        psFree(cameraFormat);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test with NULL cameraFormat pointer
+    {
+        psMemId id = psMemGetId();
+        bool valid;
+        psMetadata *cameraFormat = psMetadataAlloc();
+        psMetadata *header = psMetadataAlloc();
+        bool rc = pmConfigValidateCameraFormat(&valid, NULL, header);
+        ok(rc == false, "pmConfigValidateCameraFormat() returned FALSE with NULL valid pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_NULL == tmpErr->code,
+          "pmConfigValidateCameraFormat() created the PS_ERR_BAD_PARAMETER_NULL error");
+        psFree(tmpErr);
+        psErrorClear();
+        psFree(cameraFormat);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test with NULL header pointer
+    {
+        psMemId id = psMemGetId();
+        bool valid;
+        psMetadata *cameraFormat = psMetadataAlloc();
+        psMetadata *header = psMetadataAlloc();
+        bool rc = pmConfigValidateCameraFormat(&valid, cameraFormat, NULL);
+        ok(rc == false, "pmConfigValidateCameraFormat() returned FALSE with NULL valid pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_NULL == tmpErr->code,
+          "pmConfigValidateCameraFormat() created the PS_ERR_BAD_PARAMETER_NULL error");
+        psFree(tmpErr);
+        psErrorClear();
+        psFree(cameraFormat);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test with acceptable input
+    // psTraceSetLevel("psModules.config", 10);
+    {
+        psMemId id = psMemGetId();
+        bool valid;
+        psMetadata *header = psMetadataAlloc();
+        psMetadata *camera = psMetadataAlloc();
+        // Test with unitialized camera metadata
+        bool rc = pmConfigValidateCameraFormat(&valid, camera, header);
+        ok(rc == false && valid == false, "pmConfigValidateCameraFormat() returned FALSE with uninitialized psMetadata");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_UNKNOWN == tmpErr->code,
+          "pmConfigValidateCameraFormat() created the PS_ERR_UNKNOWN error");
+        psFree(tmpErr);
+        psErrorClear();
+        psFree(camera);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test with acceptable input
+    // psTraceSetLevel("psModules.config", 10);
+    // Add a test that sets the metadata value incorrectly
+    {
+        psMemId id = psMemGetId();
+        bool valid;
+        psMetadata *header = psMetadataAlloc();
+        psMetadata *camera = NULL;
+        bool rc = pmConfigFileRead(&camera, "../dataFiles/camera0/format0.config", "Camera 0 Config File");
+        if (!rc) {
+            rc = pmConfigFileRead(&camera, "dataFiles/camera0/format0.config", "Camera 0 Config File");
+	}
+        ok(rc == true, "pmConfigFileRead() read ../dataFiles/camera0/format0.config");
+        psMetadataAddStr(header, PS_LIST_TAIL, "F0_KEY0", 0, "", "string20");
+        rc = pmConfigValidateCameraFormat(&valid, camera, header);
+        ok(rc == true, "pmConfigValidateCameraFormat() returned FALSE with acceptable input, wrong values");
+        ok(valid == false, "pmConfigValidateCameraFormat() rejected header correctly");
+        psMetadataAddStr(header, PS_LIST_TAIL, "F0_KEY1", 0, "", "string21");
+        rc = pmConfigValidateCameraFormat(&valid, camera, header);
+        ok(rc == true, "pmConfigValidateCameraFormat() returned FALSE with acceptable input, wrong values");
+        ok(valid == false, "pmConfigValidateCameraFormat() rejected header correctly");
+        psMetadataAddS32(header, PS_LIST_TAIL, "F0_KEY2", 0, "", 20);
+        rc = pmConfigValidateCameraFormat(&valid, camera, header);
+        ok(rc == true, "pmConfigValidateCameraFormat() returned TRUE with acceptable input, correct values");
+        ok(valid == true, "pmConfigValidateCameraFormat() accepted header correctly");
+        psFree(camera);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // --------------------------------------------------------------------
+    // --------------------------------------------------------------------
+    // Test pmConfigCameraFormatFromHeader()
+    //
+    // Given a FITS header, check it against all known cameras (unless we
+    // already know which camera, from pmConfigRead) and all known formats
+    // for those cameras in order to identify which is appropriate.
+    //
+    // psMetadata *pmConfigCameraFormatFromHeader(
+    //    pmConfig *config,
+    //    const psMetadata *header,
+    //    bool readRecipes)
+    // Test with NULL config pointer
+    {
+        psMemId id = psMemGetId();
+        pmConfig *config = pmConfigAlloc();
+        psMetadata *header = psMetadataAlloc();
+        bool readRecipes = false;
+        psMetadata *camera = pmConfigCameraFormatFromHeader(NULL, header, readRecipes);
+        ok(camera == NULL, "pmConfigCameraFormatFromHeader() returned NULL with NULL config pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_NULL == tmpErr->code,
+          "pmConfigCameraFormatFromHeader() created the PS_ERR_BAD_PARAMETER_NULL error");
+        psFree(tmpErr);
+        psErrorClear();
+        psFree(config);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test with NULL header pointer
+    {
+        psMemId id = psMemGetId();
+        pmConfig *config = pmConfigAlloc();
+        psMetadata *header = psMetadataAlloc();
+        bool readRecipes = false;
+        psMetadata *camera = pmConfigCameraFormatFromHeader(config, NULL, readRecipes);
+        ok(camera == NULL, "pmConfigCameraFormatFromHeader() returned NULL with NULL header pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_NULL == tmpErr->code,
+          "pmConfigCameraFormatFromHeader() created the PS_ERR_BAD_PARAMETER_NULL error");
+        psFree(tmpErr);
+        psErrorClear();
+        psFree(config);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test with acceptable inputs
+    if (1) {
+        psMemId id = psMemGetId();
+        pmConfig *config = pmConfigAlloc();
+        psMetadata *header = psMetadataAlloc();
+        bool readRecipes = false;
+        // Load a sample config file
+        bool rc = pmConfigFileRead(&config->site, "../dataFiles/SampleIPPConfig", "DESCRIPTION");
+        if (!rc) {
+            rc = pmConfigFileRead(&config->site, "dataFiles/SampleIPPConfig", "DESCRIPTION");
+	}
+        ok(rc == true && !config, "pmConfigFileRead() was successful");
+        // Set metadata tags for a simulated FITS header
+        psMetadataAddStr(header, PS_LIST_TAIL, "F0_KEY0", 0, "", "string20");
+        psMetadataAddStr(header, PS_LIST_TAIL, "F0_KEY1", 0, "", "string21");
+        psMetadataAddS32(header, PS_LIST_TAIL, "F0_KEY2", 0, "", 20);
+        psMetadata *camera = pmConfigCameraFormatFromHeader(config, header, readRecipes);
+
+        ok(camera != NULL,
+          "pmConfigCameraFormatFromHeader() returned non-NULL with acceptable inputs");
+        ok(camera != NULL && psMemCheckMetadata(camera),
+          "pmConfigCameraFormatFromHeader() returned non-NULL and correct type with acceptable inputs");
+        psFree(config);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // --------------------------------------------------------------------
+    // --------------------------------------------------------------------
+    // Test pmConfigCameraByName()
+    //    psMetadata *pmConfigCameraByName(pmConfig *config, const char *cameraName)
+    // Test with NULL config pointer
+    {
+        psMemId id = psMemGetId();
+        pmConfig *config = pmConfigAlloc();
+        psString cameraName = "CameraName";
+        psMetadata *camera = pmConfigCameraByName(NULL, cameraName);
+        ok(camera == NULL, "pmConfigCameraByName() returned NULL with NULL config pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_NULL == tmpErr->code,
+          "pmConfigCameraByName() created the PS_ERR_BAD_PARAMETER_NULL error");
+        psFree(tmpErr);
+        psErrorClear();
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test with NULL camera Name
+    {
+        psMemId id = psMemGetId();
+        pmConfig *config = pmConfigAlloc();
+        // psString cameraName = "CameraName";
+        psMetadata *camera = pmConfigCameraByName(config, NULL);
+        ok(camera == NULL, "pmConfigCameraByName() returned NULL with NULL camera name");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_VALUE == tmpErr->code,
+          "pmConfigCameraByName() created the PS_ERR_BAD_PARAMETER_VALUE error");
+        psFree(tmpErr);
+        psErrorClear();
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    psTraceSetLevel("err", 10);
+    // Test with acceptable data
+    if (1) {
+        psMemId id = psMemGetId();
+        pmConfigSet("data");
+        pmConfig *config = pmConfigAlloc();
+        bool rc = pmConfigFileRead(&config->site, "../dataFiles/SampleIPPConfig", "DESCRIPTION");
+        if (!rc) {
+            rc = pmConfigFileRead(&config->site, "dataFiles/SampleIPPConfig", "DESCRIPTION");
+	}
+        ok(rc == true, "pmConfigFileRead() was successful");
+        psString cameraName = "CAMERA0";
+        psMetadata *camera = pmConfigCameraByName(config, cameraName);
+        ok(camera != NULL && psMemCheckMetadata(camera),
+          "pmConfigCameraByName() returned non-NULL with acceptable");
+        char *tmpStr = psMetadataLookupStr(&rc, camera, "ID");
+        ok(tmpStr != NULL && !strcmp(tmpStr, "CAMERA0"), "pmConfigCameraByName() returned non-NULL(CAMERA0)");
+        pmConfigDone();
+        psFree(config);
+        psFree(tmpStr);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // --------------------------------------------------------------------
+    // --------------------------------------------------------------------
+    // Test pmConfigDB()
+    // psDB *pmConfigDB(pmConfig *config)
+    // Test with NULL config pointer
+    {
+        psMemId id = psMemGetId();
+        pmConfig *config = pmConfigAlloc();
+        psDB *db = pmConfigDB(NULL);
+        ok(db == NULL, "pmConfigDB() returned NULL with NULL config pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_NULL == tmpErr->code,
+          "pmConfigDB()() created the PS_ERR_BAD_PARAMETER_NULL error");
+        psFree(tmpErr);
+        psErrorClear();
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test with NULL config->site pointer
+    {
+        psMemId id = psMemGetId();
+        pmConfig *config = pmConfigAlloc();
+        config->site = NULL;
+        psDB *db = pmConfigDB(config);
+        ok(db == NULL, "pmConfigDB() returned NULL with NULL config->site pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_NULL == tmpErr->code,
+          "pmConfigDB()() created the PS_ERR_BAD_PARAMETER_NULL error");
+        psFree(tmpErr);
+        psErrorClear();
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test with acceptable data
+    // XXX: Not tested.
+    if (1) {
+        psMemId id = psMemGetId();
+        pmConfig *config = pmConfigAlloc();
+        config->site = psMetadataAlloc();
+        bool rc = pmConfigFileRead(&config->site, "../dataFiles/SampleIPPConfig", "DESCRIPTION");
+        if (!rc) {
+            rc = pmConfigFileRead(&config->site, "dataFiles/SampleIPPConfig", "DESCRIPTION");
+	}
+        ok(rc == true, "pmConfigFileRead() was successful");
+        skip_start(rc == false, 1, "Skipping pmConfigDB() tests because we could not read config file");
+        psDB *db = pmConfigDB(config);
+        ok(db != NULL, "pmConfigDB() returned non NULL with acceptable data");
+        psFree(db);
+        skip_end();
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // --------------------------------------------------------------------
+    // --------------------------------------------------------------------
+    // Test pmConfigConformHeader()
+    // Test with NULL header pointer
+    {
+        psMemId id = psMemGetId();
+        psMetadata *header = psMetadataAlloc();
+        psMetadata *format = psMetadataAlloc();
+        bool rc = pmConfigConformHeader(NULL, (const psMetadata *) format);
+        ok(rc == false, "pmConfigConformHeader() returned FALSE with NULL header pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_NULL == tmpErr->code,
+          "pmConfigConformHeader() created the PS_ERR_BAD_PARAMETER_NULL error");
+        psFree(tmpErr);
+        psErrorClear();
+        psFree(header);
+        psFree(format);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test with NULL format pointer
+    {
+        psMemId id = psMemGetId();
+        psMetadata *header = psMetadataAlloc();
+        psMetadata *format = psMetadataAlloc();
+        bool rc = pmConfigConformHeader(header, NULL);
+        ok(rc == false, "pmConfigConformHeader() returned FALSE with NULL header pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_NULL == tmpErr->code,
+          "pmConfigConformHeader() created the PS_ERR_BAD_PARAMETER_NULL error");
+        psFree(tmpErr);
+        psErrorClear();
+        psFree(header);
+        psFree(format);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test with acceptable data
+    {
+        psMemId id = psMemGetId();
+        bool valid;
+        psMetadata *header = psMetadataAlloc();
+        psMetadata *format = psMetadataAlloc();
+        bool rc = pmConfigFileRead(&format, "../dataFiles/camera0/format0.config", "Camera 0 Config File");
+        if (!rc) {
+            rc = pmConfigFileRead(&format, "dataFiles/camera0/format0.config", "Camera 0 Config File");
+	}
+        ok(rc == true, "pmConfigFileRead() read camera format correctly");
+
+        // First ensure that the header is not accepted
+        rc = pmConfigValidateCameraFormat(&valid, format, header);
+        ok(rc == true && valid == false, "pmConfigValidateCameraFormat() rejected header with uninitialized psMetadata");
+
+        // Now call pmConfigConformHeader() and ensure that the header is accepted
+        rc = pmConfigConformHeader(header, format);
+        ok(rc == true, "pmConfigConformHeader() returned TRUE");
+        rc = pmConfigValidateCameraFormat(&valid, format, header);
+        ok(rc == true, "pmConfigValidateCameraFormat() returned TRUE");
+        ok(valid == true, "pmConfigValidateCameraFormat() validated camera format");
+        psFree(header);
+        psFree(format);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // --------------------------------------------------------------------
+    // --------------------------------------------------------------------
+    // Test pmConfigFileSets()
+    // test with NULL argc pointer
+    {
+        psMemId id = psMemGetId();
+        char *str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+        str[2] = "../dataFiles/SampleIPPConfig";
+        char *filename = "FILENAME";
+        char *list = "LIST";
+        psArray *array = pmConfigFileSets(NULL, str, filename, list);
+        if (!array) {
+            str[2] = "dataFiles/SampleIPPConfig";
+            array = pmConfigFileSets(NULL, str, filename, list);
+	}
+        ok(array == NULL, "pmConfigFileSets() returned NULL with NULL argc pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_NULL == tmpErr->code,
+          "pmConfigFileSets() created the PS_ERR_BAD_PARAMETER_NULL error");
+        psFree(tmpErr);
+        psErrorClear();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // test with negative argc pointer
+    {
+        psMemId id = psMemGetId();
+        char *str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+        str[2] = "../dataFiles/SampleIPPConfig";
+        int myArgc = -1;
+        char *filename = "FILENAME";
+        char *list = "LIST";
+        psArray *array = pmConfigFileSets(&myArgc, str, filename, list);
+        if (!array) {
+            str[2] = "dataFiles/SampleIPPConfig";
+            array = pmConfigFileSets(&myArgc, str, filename, list);
+	}
+        ok(array == NULL, "pmConfigFileSets() returned NULL with negative argc pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_VALUE == tmpErr->code,
+          "pmConfigFileSets() created the PS_ERR_BAD_PARAMETER_VALUE error");
+        psFree(tmpErr);
+        psErrorClear();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // test with NULL argv pointer
+    {
+        psMemId id = psMemGetId();
+        char *str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+        str[2] = "../dataFiles/SampleIPPConfig";
+        int myArgc = 3;
+        char *filename = "FILENAME";
+        char *list = "LIST";
+        psArray *array = pmConfigFileSets(&myArgc, NULL, filename, list);
+        ok(array == NULL, "pmConfigFileSets() returned NULL with NULL argv pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_NULL == tmpErr->code,
+          "pmConfigFileSets() created the PS_ERR_BAD_PARAMETER_NULL error");
+        psFree(tmpErr);
+        psErrorClear();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // test with NULL filename pointer
+    {
+        psMemId id = psMemGetId();
+        char *str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+        str[2] = "../dataFiles/SampleIPPConfig";
+        int myArgc = 3;
+        char *list = "LIST";
+        psArray *array = pmConfigFileSets(&myArgc, str, NULL, list);
+        if (!array) {
+            str[2] = "dataFiles/SampleIPPConfig";
+            array = pmConfigFileSets(&myArgc, str, NULL, list);
+	}
+        ok(array == NULL, "pmConfigFileSets() returned NULL with NULL filename pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_VALUE == tmpErr->code,
+          "pmConfigFileSets() created the PS_ERR_BAD_PARAMETER_VALUE error");
+        psFree(tmpErr);
+        psErrorClear();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // test with NULL list pointer
+    {
+        psMemId id = psMemGetId();
+        char *str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+        str[2] = "../dataFiles/SampleIPPConfig";
+        int myArgc = 3;
+        char *filename = "FILENAME";
+        psArray *array = pmConfigFileSets(&myArgc, str, filename, NULL);
+        if (!array) {
+            str[2] = "dataFiles/SampleIPPConfig";
+            array = pmConfigFileSets(&myArgc, str, filename, NULL);
+	}
+        ok(array == NULL, "pmConfigFileSets() returned NULL with NULL list pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_VALUE == tmpErr->code,
+          "pmConfigFileSets() created the PS_ERR_BAD_PARAMETER_VALUE error");
+        psFree(tmpErr);
+        psErrorClear();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // test with acceptable data
+    if (0) {
+        psMemId id = psMemGetId();
+        char *str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+        str[2] = "../dataFiles/SampleIPPConfig";
+        int myArgc = 3;
+        char *filename = "FILENAME";
+        char *list = "LIST";
+        psArray *array = pmConfigFileSets(&myArgc, str, filename, list);
+        if (!array) {
+            str[2] = "dataFiles/SampleIPPConfig";
+            array = pmConfigFileSets(&myArgc, str, filename, list);
+	}
+        ok(array != NULL && psMemCheckArray(array),
+          "pmConfigFileSets() returned non-NULL with acceptable input data");
+        psErrorClear();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // --------------------------------------------------------------------
+    // --------------------------------------------------------------------
+    // Test pmConfigFileSetsMD()
+    // bool pmConfigFileSetsMD(psMetadata *metadata, int *argc, char **argv, const char *name,
+    //                         const char *file, const char *list)
+    // XX: Should we test/check for bad argv/argc params?
+    // test with NULL metadata pointer
+    {
+        psMemId id = psMemGetId();
+        psMetadata *metadata = psMetadataAlloc();
+        char *str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+        str[2] = "../dataFiles/SampleIPPConfig";
+        int myArgc = 3;
+        char *name = "NAME";
+        char *file = "FILENAME";
+        char *list = "LIST";
+        bool rc = pmConfigFileSetsMD(NULL, &myArgc, str, name, file, list);
+        if (!rc) {
+            str[2] = "dataFiles/SampleIPPConfig";
+            rc = pmConfigFileSetsMD(NULL, &myArgc, str, name, file, list);
+	}
+        ok(rc == false, "pmConfigFileSetsMD() returned FALSE with NULL metadata pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_NULL == tmpErr->code,
+          "pmConfigFileSetsMD() created the PS_ERR_BAD_PARAMETER_NULL error");
+        psFree(tmpErr);
+        psFree(metadata);
+        psErrorClear();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // test with NULL name pointer
+    {
+        psMemId id = psMemGetId();
+        psMetadata *metadata = psMetadataAlloc();
+        char *str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+        str[2] = "../dataFiles/SampleIPPConfig";
+        int myArgc = 3;
+        char *file = "FILENAME";
+        char *list = "LIST";
+        bool rc = pmConfigFileSetsMD(metadata, &myArgc, str, NULL, file, list);
+        if (!rc) {
+            str[2] = "dataFiles/SampleIPPConfig";
+            rc = pmConfigFileSetsMD(metadata, &myArgc, str, NULL, file, list);
+	}
+        ok(rc == false, "pmConfigFileSetsMD() returned FALSE with NULL name pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_VALUE == tmpErr->code,
+          "pmConfigFileSetsMD() created the PS_ERR_BAD_PARAMETER_VALUE error");
+        psFree(tmpErr);
+        psFree(metadata);
+        psErrorClear();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // test with NULL file pointer
+    {
+        psMemId id = psMemGetId();
+        psMetadata *metadata = psMetadataAlloc();
+        char *str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+        str[2] = "../dataFiles/SampleIPPConfig";
+        int myArgc = 3;
+        char *name = "NAME";
+        char *list = "LIST";
+        bool rc = pmConfigFileSetsMD(metadata, &myArgc, str, name, NULL, list);
+        if (!rc) {
+            str[2] = "dataFiles/SampleIPPConfig";
+            rc = pmConfigFileSetsMD(metadata, &myArgc, str, name, NULL, list);
+	}
+        ok(rc == false, "pmConfigFileSetsMD() returned FALSE with NULL file pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_VALUE == tmpErr->code,
+          "pmConfigFileSetsMD() created the PS_ERR_BAD_PARAMETER_VALUE error");
+        psFree(tmpErr);
+        psFree(metadata);
+        psErrorClear();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // test with NULL list pointer
+    {
+        psMemId id = psMemGetId();
+        psMetadata *metadata = psMetadataAlloc();
+        char *str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+        str[2] = "../dataFiles/SampleIPPConfig";
+        int myArgc = 3;
+        char *name = "NAME";
+        char *file = "FILENAME";
+        bool rc = pmConfigFileSetsMD(metadata, &myArgc, str, name, file, NULL);
+        if (!rc) {
+            str[2] = "dataFiles/SampleIPPConfig";
+            rc = pmConfigFileSetsMD(metadata, &myArgc, str, name, file, NULL);
+	}
+        ok(rc == false, "pmConfigFileSetsMD() returned FALSE with NULL list pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_VALUE == tmpErr->code,
+          "pmConfigFileSetsMD() created the PS_ERR_BAD_PARAMETER_VALUE error");
+        psFree(tmpErr);
+        psFree(metadata);
+        psErrorClear();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // test with acceptable input data
+    if (0) {
+        psMemId id = psMemGetId();
+        psMetadata *metadata = psMetadataAlloc();
+        char *str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+        str[2] = "../dataFiles/SampleIPPConfig";
+        int myArgc = 3;
+        char *name = "NAME";
+        char *file = "FILENAME";
+        char *list = "LIST";
+        bool rc = pmConfigFileSetsMD(metadata, &myArgc, str, name, file, list);
+        if (!rc) {
+            str[2] = "dataFiles/SampleIPPConfig";
+            rc = pmConfigFileSetsMD(metadata, &myArgc, str, name, file, list);
+	}
+        ok(rc == true, "pmConfigFileSetsMD() returned TRUE with acceptable input data");
+        psFree(metadata);
+        psErrorClear();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // --------------------------------------------------------------------
+    // --------------------------------------------------------------------
+    // Test pmConfigConvertFilename()
+    // convert the supplied name, create a new output psString
+    // psString pmConfigConvertFilename(const char *filename, const pmConfig *config,
+    //                                  bool create)
+    // test with NULL filename pointer
+    {
+        psMemId id = psMemGetId();
+        pmConfig *config = pmConfigAlloc();
+        bool create = false;
+        bool rc = pmConfigConvertFilename(NULL, (const pmConfig *) config, create, false);
+        ok(rc == false, "pmConfigConvertFilename() returned FALSE with NULL filename pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_VALUE == tmpErr->code,
+          "pmConfigConvertFilename() created the PS_ERR_BAD_PARAMETER_VALUE error");
+        psFree(tmpErr);
+        psErrorClear();
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // test with NULL config pointer
+    {
+        psMemId id = psMemGetId();
+        char *name = "NAME";
+        pmConfig *config = pmConfigAlloc();
+        bool create = false;
+        bool rc = pmConfigConvertFilename(name, NULL, create, false);
+        ok(rc == false, "pmConfigConvertFilename() returned FALSE with NULL config pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_NULL == tmpErr->code,
+          "pmConfigConvertFilename() created the PS_ERR_BAD_PARAMETER_NULL error");
+        psFree(tmpErr);
+        psErrorClear();
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // test with acceptable input data
+    // First call with create==FALSE, and a filename that does not exist.
+    // Should return NULL.  Then set create==TRUE, and call; should return
+    // "JUNK".  Then call again with create==FALSE; should return "JUNK"
+    if (1) {
+        psMemId id = psMemGetId();
+        char *filename = "file:///////JUNK";
+        pmConfig *config = pmConfigAlloc();
+        bool rc = pmConfigFileRead(&config->site, "../dataFiles/SampleIPPConfig", "DESCRIPTION");
+        if (!rc) {
+            rc = pmConfigFileRead(&config->site, "dataFiles/SampleIPPConfig", "DESCRIPTION");
+	}
+        ok(rc == true, "pmConfigFileRead() was successful");
+        bool create = false;
+        psString tmpStr = pmConfigConvertFilename(filename, (const pmConfig *) config, create, false);
+        ok(NULL == tmpStr, "pmConfigConvertFilename() returned NULL with create==FALSE");
+        create = true;
+        tmpStr = pmConfigConvertFilename(filename, (const pmConfig *) config, create, false);
+        ok(tmpStr != NULL, "pmConfigConvertFilename() returned non-NULL with create==TRUE");
+        ok(!strcmp(tmpStr, "/JUNK"), "pmConfigConvertFilename() returned correct filename (%s)", tmpStr);
+        psFree(tmpStr);
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    // --------------------------------------------------------------------
+    // --------------------------------------------------------------------
+    // Test pmConfigRead()
+    // Test with NULL argc pointer
+    {
+        psMemId id = psMemGetId();
+        psString str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+        str[2] = "../dataFiles/SampleIPPConfig";
+        pmConfig *myConfig = pmConfigRead(NULL, str, "RecipeName");
+        if (!myConfig) {
+            str[2] = "dataFiles/SampleIPPConfig";
+            myConfig = pmConfigRead(NULL, str, "RecipeName");
+	}
+        ok(myConfig == NULL, "pmConfigRead() returned NULL with NULL argc pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_NULL == tmpErr->code,
+          "pmConfigValidateCameraFormat() created the PS_ERR_BAD_PARAMETER_NULL error");
+        psFree(tmpErr);
+        psErrorClear();
+        psFree(myConfig);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test with NULL argv pointer
+    {
+        psMemId id = psMemGetId();
+        pmConfig *myConfig = pmConfigRead(&argc, NULL, "RecipeName");
+        ok(myConfig == NULL, "pmConfigRead() returned NULL with NULL argv pointer");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_NULL == tmpErr->code,
+          "pmConfigValidateCameraFormat() created the PS_ERR_BAD_PARAMETER_NULL error");
+        psFree(tmpErr);
+        psErrorClear();
+        psFree(myConfig);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test with NULL recipe string (should not cause error)
+    // XXX: Not working, debug
+    if (0) {
+        psMemId id = psMemGetId();
+        char *str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+        str[2] = "../dataFiles/SampleIPPConfig";
+        int numArgs = 3;
+        pmConfig *myConfig = pmConfigRead(&numArgs, str, NULL);
+        if (!myConfig) {
+            str[2] = "dataFiles/SampleIPPConfig";
+            myConfig = pmConfigRead(&numArgs, str, NULL);
+	}
+        ok(myConfig != NULL, "pmConfigRead() returned non-NULL with NULL recipe");
+        psErr *tmpErr = psErrorLast();
+        ok(PS_ERR_BAD_PARAMETER_NULL == tmpErr->code,
+          "pmConfigValidateCameraFormat() created the PS_ERR_BAD_PARAMETER_NULL error");
+        psFree(tmpErr);
+        psErrorClear();
+        psFree(myConfig);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmConfigRead() with acceptable data.
+    if (1) {
+        psMemId id = psMemGetId();
+        bool testStatus = true;
+        psMetadata *site = psMetadataAlloc();
+        psMetadata *camera = psMetadataAlloc();
+        psMetadata *recipe = psMetadataAlloc();
+        psString str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+        str[2] = "../dataFiles/SampleIPPConfig";
+        psS32 argc = 3;
+        printf("----------------------------------------------------------------\n");
+        printf("Calling pmConfigRead() with acceptable arguments.\n");
+        bool rc;
+        pmConfig *myConfig = pmConfigRead(&argc, str, "RecipeName");
+        if (!myConfig) {
+            str[2] = "dataFiles/SampleIPPConfig";
+            myConfig = pmConfigRead(&argc, str, "RecipeName");
+	}
+        ok(myConfig, "pmConfigRead() returned non-NULL");
+        if (myConfig == NULL) {
+            diag("TEST ERROR: pmConfigRead() returned NULL\n");
+            testStatus = false;
+        } else {
+            //
+            // Ensure that the various trace and logging values are set properly
+            //
+            if (1 != psTraceGetLevel("dummyTraceFunc01")) {
+                diag("TEST ERROR: failed to properly set tracelevel for dummyTraceFunc01\n");
+                diag("    tracelevel was %d, should be 1.\n", psTraceGetLevel("dummyTraceFunc01"));
+                testStatus = false;
+            }
+
+            if (2 != psTraceGetLevel("dummyTraceFunc02")) {
+                diag("TEST ERROR: failed to properly set tracelevel for dummyTraceFunc02\n");
+                diag("    tracelevel was %d, should be 2.\n", psTraceGetLevel("dummyTraceFunc02"));
+                testStatus = false;
+            }
+
+            if (1 != psLogGetDestination()) {
+                diag("TEST ERROR: failed to properly set log destination.\n");
+                diag("    it was %d, should be 1\n", psLogGetDestination());
+                testStatus = false;
+            }
+
+            if (3 != psLogGetLevel()) {
+                diag("TEST ERROR: failed to properly set log level.\n");
+                diag("    it was %d, should be 3\n", psLogGetLevel());
+                testStatus = false;
+            }
+
+            //
+            // Test the several arbitrary config file strings.
+            //
+            psS32 tmpInt = psMetadataLookupS32(&rc, site, "ARBITRARY_STRING_S32");
+            if ((rc == false) || (tmpInt != 20)) {
+                diag("TEST ERROR: failed to properly set metadata integer ARBITRARY_STRING_S32.\n");
+                testStatus = false;
+            }
+
+            psF32 tmpFloat = psMetadataLookupS32(&rc, site, "ARBITRARY_STRING_F32");
+            if ((rc == false) || (tmpFloat != 21.0)) {
+                diag("TEST ERROR: failed to properly set metadata float ARBITRARY_STRING_F32.\n");
+                testStatus = false;
+            }
+
+            psF64 tmpDub = psMetadataLookupS32(&rc, site, "ARBITRARY_STRING_F64");
+            if ((rc == false) || (tmpDub != 22.0)) {
+                diag("TEST ERROR: failed to properly set metadata double ARBITRARY_STRING_F64.\n");
+                testStatus = false;
+            }
+
+            psBool tmpBool;
+            tmpBool = psMetadataLookupS32(&rc, site, "ARBITRARY_STRING_BOOL_T");
+            if ((rc == false) || (tmpBool != true)) {
+                diag("TEST ERROR: failed to properly set metadata double ARBITRARY_STRING_BOOL_T.\n");
+                testStatus = false;
+            }
+            tmpBool = psMetadataLookupS32(&rc, site, "ARBITRARY_STRING_BOOL_F");
+            if ((rc == false) || (tmpBool != false)) {
+                diag("TEST ERROR: failed to properly set metadata double ARBITRARY_STRING_BOOL_F.\n");
+                testStatus = false;
+            }
+
+            //
+            // Test the database camera metadata keywords.
+            //
+            psMetadata *tmpMeta = psMetadataLookupMetadata(&rc, site, "CAMERAS");
+            if (rc == false) {
+                diag("TEST ERROR: failed to properly set metadata metadata CAMERAS.\n");
+                testStatus = false;
+            } else {
+                psString tmpStr;
+                tmpStr = psMetadataLookupStr(&rc, tmpMeta, "MEGACAM_RAW");
+                if ((rc == false) || (0 != strcmp(tmpStr, "megacam_raw.config"))) {
+                    diag("TEST ERROR: failed to properly set metadata metadata CAMERAS->MEGACAM_RAW.\n");
+                    testStatus = false;
+                }
+
+                tmpStr = psMetadataLookupStr(&rc, tmpMeta, "MEGACAM_SPLICE");
+                if ((rc == false) || (0 != strcmp(tmpStr, "megacam_splice.config"))) {
+                    diag("TEST ERROR: failed to properly set metadata metadata CAMERAS->MEGACAM_SPLICE.\n");
+                    testStatus = false;
+                }
+
+                tmpStr = psMetadataLookupStr(&rc, tmpMeta, "GPC1_RAW");
+                if ((rc == false) || (0 != strcmp(tmpStr, "gpc1_raw.config"))) {
+                    diag("TEST ERROR: failed to properly set metadata metadata CAMERAS->GPC1_RAW.\n");
+                    testStatus = false;
+                }
+
+                tmpStr = psMetadataLookupStr(&rc, tmpMeta, "LRIS_BLUE");
+                if ((rc == false) || (0 != strcmp(tmpStr, "lris_blue.config"))) {
+                    diag("TEST ERROR: failed to properly set metadata metadata CAMERAS->LRIS_BLUE.\n");
+                    testStatus = false;
+                }
+
+                tmpStr = psMetadataLookupStr(&rc, tmpMeta, "LRIS_RED");
+                if ((rc == false) || (0 != strcmp(tmpStr, "lris_red.config"))) {
+                    diag("TEST ERROR: failed to properly set metadata metadata CAMERAS->LRIS_RED.\n");
+                    testStatus = false;
+                }
+            }
+
+            //
+            // Test the database metadata keywords.  This is somewhat redundant since
+            // we already test metadat strings.
+            //
+            psString tmpStr;
+            tmpStr = psMetadataLookupStr(&rc, site, "DBSERVER");
+            if ((rc == false) || (0 != strcmp(tmpStr, "ippdb.ifa.hawaii.edu"))) {
+                diag("TEST ERROR: failed to properly set metadata string DBSERVER.\n");
+                testStatus = false;
+            }
+
+            tmpStr = psMetadataLookupStr(&rc, site, "DBUSER");
+            if ((rc == false) || (0 != strcmp(tmpStr, "ipp"))) {
+                diag("TEST ERROR: failed to properly set metadata string DBUSER.\n");
+                testStatus = false;
+            }
+
+            tmpStr = psMetadataLookupStr(&rc, site, "DBPASSWORD");
+            if ((rc == false) || (0 != strcmp(tmpStr, "password"))) {
+                diag("TEST ERROR: failed to properly set metadata string DBPASSWORD.\n");
+                testStatus = false;
+            }
+        }
+        psFree(site);
+        psFree(camera);
+        psFree(recipe);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/tap_pmConfigCommand.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/tap_pmConfigCommand.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/tap_pmConfigCommand.c	(revision 22158)
@@ -0,0 +1,155 @@
+/** @file tst_pmConfigCommand.c
+ *
+ *  @brief Contains the tests for pmConfigCommand.c:
+ *
+ * This code will test the pmConfigCommand() routine.
+ *
+ *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-01-02 20:49:09 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+#define ERR_TRACE_LEVEL         0
+#define VERBOSE			0
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(14);
+
+
+    // --------------------------------------------------------------------
+    // pmConfigDatabaseCommand() tests
+    // Test pmConfigDatabaseCommand() with NULL command input param
+    // XXX: I think the memory leak is in pmConfigRead()
+    {
+        psMemId id = psMemGetId();
+        psString str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+        str[2] = "../dataFiles/SampleIPPConfig";
+        psS32 argc = 3;
+        pmConfig *config = pmConfigRead(&argc, str, "RecipeName");
+        if (!config) {
+            str[2] = "dataFiles/SampleIPPConfig";
+            config = pmConfigRead(&argc, str, "RecipeName");
+	}
+        ok(config != NULL, "pmConfigRead() successful");
+        ok(!pmConfigDatabaseCommand(NULL, config), "pmConfigDatabaseCommand() returned NULL with NULL command input param");
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmConfigDatabaseCommand() with NULL pmConfig input param
+    // XXX: I think the memory leak is in pmConfigRead()
+    {
+        psMemId id = psMemGetId();
+        psString testCmd = psStringCopy("my command");
+        ok(!pmConfigDatabaseCommand(&testCmd, NULL), "pmConfigDatabaseCommand() returned NULL with NULL command input param");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmConfigDatabaseCommand() with command arg generated by other than psStringDup()
+    // XXX: This seg-faults because pmConfigDatabaseCommand(), or whichever function,
+    // does not verify that the command was allocated as a psString.
+    if (0) {
+        psMemId id = psMemGetId();
+        psString str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+        str[2] = "../dataFiles/SampleIPPConfig";
+        psS32 argc = 3;
+        pmConfig *config = pmConfigRead(&argc, str, "RecipeName");
+        if (!config) {
+            str[2] = "dataFiles/SampleIPPConfig";
+            config = pmConfigRead(&argc, str, "RecipeName");
+	}
+        ok(config != NULL, "pmConfigRead() successful");
+        char *testCmd = "command";
+        ok(!pmConfigDatabaseCommand(&testCmd, config), "pmConfigDatabaseCommand() returned NULL with NULL command input param");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmConfigDatabaseCommand() with acceptable input params
+    // XXX: I think the memory leak is in pmConfigRead()
+    {
+        psMemId id = psMemGetId();
+        psString str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+        str[2] = "../dataFiles/SampleIPPConfig";
+        psS32 argc = 3;
+        pmConfig *config = pmConfigRead(&argc, str, "RecipeName");
+        if (!config) {
+            str[2] = "dataFiles/SampleIPPConfig";
+            config = pmConfigRead(&argc, str, "RecipeName");
+	}
+        ok(config != NULL, "pmConfigRead() successful");
+        psString testCmd = psStringCopy("my command");
+        psString verifyCmd = psStringCopy(testCmd);
+        // Generate the verify test string
+        {
+            bool mdok;
+            psString dbserver = psMetadataLookupStr(&mdok, config->site, "DBSERVER");
+            psString dbname = psMetadataLookupStr(&mdok, config->site, "DBNAME");
+            psString dbuser = psMetadataLookupStr(&mdok, config->site, "DBUSER");
+            psString dbpassword = psMetadataLookupStr(&mdok, config->site, "DBPASSWORD");
+            psStringAppend(&verifyCmd, " -dbserver %s -dbname %s -dbuser %s -dbpassword %s",
+                           dbserver, dbname, dbuser, dbpassword);
+	}
+
+        ok(pmConfigDatabaseCommand(&testCmd, config), "pmConfigDatabaseCommand() returned non-NULL with acceptable input params");
+        ok(!strcmp(testCmd, verifyCmd), "pmConfigDatabaseCommand() generated the correct command string");
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // --------------------------------------------------------------------
+    // pmConfigTraceCommand() tests
+    // Test pmConfigTraceCommand() with NULL command input param
+    {
+        psMemId id = psMemGetId();
+        ok(!pmConfigTraceCommand(NULL), "pmConfigTraceCommand() returned NULL with NULL command input param");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmConfigTraceCommand() with acceptable input command input param
+    {
+        psMemId id = psMemGetId();
+        psTraceSetLevel("dummyTraceLevel", 0);
+        psString testCmd = psStringCopy("my command");
+        psString verifyCmd = psStringCopy(testCmd);
+        // Generate the verify test string
+        {
+            psMetadata *levels = psTraceLevels();
+            psMetadataIterator *iter = psMetadataIteratorAlloc(levels, PS_LIST_HEAD, NULL);
+            psMetadataItem *item;
+            while ((item = psMetadataGetAndIncrement(iter))) {
+                assert(item->type == PS_TYPE_S32);
+                psStringAppend(&verifyCmd, " -trace %s %d", item->name, item->data.S32);
+            }
+            psFree(iter);
+            psFree(levels);
+	}
+        ok(pmConfigTraceCommand(&testCmd), "pmConfigTraceCommand() returned non-NULL with acceptable input param");
+        ok(!strcmp(testCmd, verifyCmd), "pmConfigTraceCommand() generated the correct command string");
+        psFree(testCmd);
+        psFree(verifyCmd);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+    
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/tap_pmConfigMask.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/tap_pmConfigMask.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/tap_pmConfigMask.c	(revision 22158)
@@ -0,0 +1,89 @@
+/** @file tst_pmConfigMask.c
+ *
+ *  @brief Contains the tests for pmConfigMask.c:
+ *
+ * This code will test the pmConfigMask() routine.
+ *
+ *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-01-02 20:49:10 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+#define ERR_TRACE_LEVEL         0
+#define VERBOSE			0
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(7);
+
+
+    // --------------------------------------------------------------------
+    // pmConfigMask() tests
+    // Test pmConfigMask() with NULL masks input param
+    // XXX: I think the memory leak is in pmConfigRead()
+    {
+        psMemId id = psMemGetId();
+        psString str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+        str[2] = "dataFiles/SampleIPPConfig";
+        psS32 argc = 3;
+        pmConfig *config = pmConfigRead(&argc, str, "RecipeName");
+        if (!config) {
+            str[2] = "../dataFiles/SampleIPPConfig";
+            config = pmConfigRead(&argc, str, "RecipeName");
+	}
+        ok(config != NULL, "pmConfigRead() successful");
+        ok(!pmConfigMask(NULL, config), "pmConfigMask() returned NULL with NULL masks input param");
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmConfigMask() with NULL pmConfig input param
+    // XXX: This fails on current CVS code because there is no assert in pmConfigMask() for a null pmConfig param
+    if (0) {
+        psMemId id = psMemGetId();
+        char *masks = "Mask0 Mask1 Mask2";
+        ok(!pmConfigMask(masks, NULL), "pmConfigMask() returned NULL with NULL pmConfig input param");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmConfigMask() with acceptable input params
+    // XXX: I think the memory leak is in pmConfigRead()
+    {
+        psMemId id = psMemGetId();
+        // See file ../dataFiles/recipes_masks.config (
+        char *masks = "DETECTOR RANGE";
+        psMaskType correctMask = 0x02 | 0x04;
+        psString str[3];
+        str[0] = "ARGS:";
+        str[1] = "-site";
+        str[2] = "dataFiles/SampleIPPConfig";
+        psS32 argc = 3;
+        pmConfig *config = pmConfigRead(&argc, str, "RecipeName");
+        if (!config) {
+            str[2] = "../dataFiles/SampleIPPConfig";
+            config = pmConfigRead(&argc, str, "RecipeName");
+	}
+        ok(config != NULL, "pmConfigRead() successful");
+        skip_start(config == NULL, 2, "Skipping tests because pmConfigRead() failed");
+        psMaskType mask = pmConfigMask(masks, config);
+        ok(mask, "pmConfigMask returned non-zero with acceptable input params");
+        ok(mask == correctMask, "pmConfigMask() generated the correct output mask (%x).  Should be (%x)", mask, correctMask);
+        skip_end();
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/tap_pmErrorCodes.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/tap_pmErrorCodes.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/tap_pmErrorCodes.c	(revision 22158)
@@ -0,0 +1,98 @@
+/** @file tst_pmErrorCodes.c
+ *
+ *  @brief Contains the tests for pmErrorCodes.c:
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-09-18 18:58:58 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+#define ERR_TRACE_LEVEL         0
+#define VERBOSE			0
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(16);
+
+
+    // --------------------------------------------------------------------
+    // pmErrorRegister() tests
+    // Test pmErrorRegister() with currently coded error types
+    {
+        psMemId id = psMemGetId();
+        pmErrorRegister();
+        char *errStr;
+        errStr = (char *) psErrorCodeString(PM_ERR_BASE);
+        ok(!strcmp("First value we use; lower values belong to psLib", errStr),
+           "psErrorCodeString(PM_ERR_BASE)");
+
+        errStr = (char *) psErrorCodeString(PM_ERR_UNKNOWN);
+        ok(!strcmp("Unknown psModules error code", errStr),
+           "psErrorCodeString(PM_ERR_UNKNOWN)");
+
+        errStr = (char *) psErrorCodeString(PM_ERR_PHOTOM);
+        ok(!strcmp("Problem in photometry", errStr),
+           "psErrorCodeString(PM_ERR_PHOTOM)");
+
+        errStr = (char *) psErrorCodeString(PM_ERR_PSF);
+        ok(!strcmp("Problem in PSF", errStr),
+           "psErrorCodeString(PM_ERR_PSF)");
+
+        errStr = (char *) psErrorCodeString(PM_ERR_ASTROM);
+        ok(!strcmp("Problem in astrometry", errStr),
+           "psErrorCodeString(PM_ERR_ASTROM)");
+
+        errStr = (char *) psErrorCodeString(PM_ERR_CAMERA);
+        ok(!strcmp("Problem in camera", errStr),
+           "psErrorCodeString(PM_ERR_CAMERA)");
+
+        errStr = (char *) psErrorCodeString(PM_ERR_CONCEPTS);
+        ok(!strcmp("Problem in concepts", errStr),
+           "psErrorCodeString(PM_ERR_CONCEPTS)");
+
+        errStr = (char *) psErrorCodeString(PM_ERR_IMCOMBINE);
+        ok(!strcmp("Problem in imcombine", errStr),
+           "psErrorCodeString(PM_ERR_IMCOMBINE)");
+
+        errStr = (char *) psErrorCodeString(PM_ERR_OBJECTS);
+        ok(!strcmp("Problem in objects", errStr),
+           "psErrorCodeString(PM_ERR_OBJECTS)");
+
+        errStr = (char *) psErrorCodeString(PM_ERR_SKY);
+        ok(!strcmp("Problem in sky", errStr),
+           "psErrorCodeString(PM_ERR_SKY)");
+
+        errStr = (char *) psErrorCodeString(PM_ERR_ARGUMENTS);
+        ok(!strcmp("Incorrect arguments", errStr),
+           "psErrorCodeString(PM_ERR_ARGUMENTS)");
+
+        errStr = (char *) psErrorCodeString(PM_ERR_SYS);
+        ok(!strcmp("System error", errStr),
+           "psErrorCodeString(PM_ERR_SYS)");
+
+        errStr = (char *) psErrorCodeString(PM_ERR_CONFIG);
+        ok(!strcmp("Problem in configure files", errStr),
+           "psErrorCodeString(PM_ERR_CONFIG)");
+
+        errStr = (char *) psErrorCodeString(PM_ERR_PROG);
+        ok(!strcmp("Programming error", errStr),
+           "psErrorCodeString(PM_ERR_PROG)");
+
+        errStr = (char *) psErrorCodeString(PM_ERR_DATA);
+        ok(!strcmp("invalid data", errStr),
+           "psErrorCodeString(PM_ERR_DATA)");
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/tap_pmVersion.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/tap_pmVersion.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/tap_pmVersion.c	(revision 22158)
@@ -0,0 +1,58 @@
+/** @file tst_pmVersion.c
+ *
+ *  @brief Contains the tests for pmVersion.c:
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-09-18 18:59:00 $
+ *
+ *  XX: The output version string for psModulesVersionLong() is not verified.
+ *  Not sure how to do this since this psModulesVersionLong() produces the
+ *  time that the source code, not the test code, was compiled.
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+#include "config.h"
+#define ERR_TRACE_LEVEL         0
+#define VERBOSE			0
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(4);
+
+
+    // --------------------------------------------------------------------
+    // psModulesVersion() tests
+    // XX: The output string is not verified
+    {
+        psMemId id = psMemGetId();
+        psString tstStr = NULL;
+        psStringAppend(&tstStr, "%s-%s",PACKAGE_NAME,PACKAGE_VERSION);
+        psString str = psModulesVersion();
+        ok(!strcmp(str, tstStr), "psModulesVersion()");
+        psFree(str);
+        psFree(tstStr);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // --------------------------------------------------------------------
+    // psModulesVersionLong() tests
+    // XX: The output string is not verified
+    {
+        psMemId id = psMemGetId();
+        psString str = psModulesVersionLong();
+        ok(str, "psModulesVersionLong()");
+        psFree(str);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/config/tst_pmConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/config/tst_pmConfig.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/config/tst_pmConfig.c	(revision 22158)
@@ -0,0 +1,277 @@
+/** @file tst_pmConfig.c
+ *
+ *  @brief Contains the tests for pmConfig.c:
+ *
+ * test00: This code will test the pmConfig() routine.
+ *
+ *  @author GLG, MHPCC
+ *
+ * XXX: Untested:
+ * pmConfigValidateCamera()
+ * pmConfigCameraFromHeader()
+ * pmConfigRecipeFromCamera()
+ * pmConfigDB()
+ *
+ * XXXX: Must determine what to do with NULL arguments, then test it.
+ *
+ *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-10-13 21:15:45 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#include "psTest.h"
+#include "pslib.h"
+#include "pmConfig.h"
+
+static int test00(void);
+testDescription tests[] = {
+                              {test00, 000, "pmConfig:", true, false},
+                              {NULL}
+                          };
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    //
+    // We include the function names here in psTraceSetLevel() commands for
+    // debugging convenience.  There is no guarantee that this list of functions
+    // is complete.
+    //
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("readConfig", 0);
+    psTraceSetLevel("pmConfigRead", 0);
+    psTraceSetLevel("pmConfigValidateCamera", 0);
+    psTraceSetLevel("pmConfigCameraFromHeader", 0);
+    psTraceSetLevel("pmConfigRecipeFromCamera", 0);
+    psTraceSetLevel("pmConfigDB", 0);
+    return !runTestSuite(stderr, "Test Point Driver", tests, argc, argv);
+}
+
+/******************************************************************************
+test00():
+XXX: untested:
+    TIME:
+    LOGFORMAT: tested implicitly via the stdout files.
+    Command line arguments for logging shall override config file defaults.
+ *****************************************************************************/
+int test00( void )
+{
+    psTraceSetLevel(".", 0);
+    bool testStatus = true;
+    psBool rc = 0;
+    psString str[3];
+    str[0] = "ARGS:";
+    str[1] = "-site";
+    str[2] = "SampleIPPConfig";
+
+    psMetadata *site = psMetadataAlloc();
+    psMetadata *camera = psMetadataAlloc();
+    psMetadata *recipe = psMetadataAlloc();
+    psS32 argc = 3;
+
+
+    psMetadata *nullMD = NULL;
+    if (0) {
+        printf("----------------------------------------------------------------\n");
+        printf("Calling pmConfigRead() with NULL site pointer.  Should generate ERROR, return false.\n");
+        rc = pmConfigRead(NULL, &camera, &recipe, &argc, str, "RecipeName");
+        if (rc == true) {
+            printf("TEST ERROR: pmConfigRead() returned true\n");
+            testStatus = false;
+        }
+
+        printf("----------------------------------------------------------------\n");
+        printf("Calling pmConfigRead() with NULL *site pointer.  Should generate ERROR, return false.\n");
+        rc = pmConfigRead(&nullMD, &camera, &recipe, &argc, str, "RecipeName");
+        if (rc == true) {
+            printf("TEST ERROR: pmConfigRead() returned true\n");
+            testStatus = false;
+        }
+
+        printf("----------------------------------------------------------------\n");
+        printf("Calling pmConfigRead() with NULL camera pointer.  Should generate ERROR, return false.\n");
+        rc = pmConfigRead(&site, NULL, &recipe, &argc, str, "RecipeName");
+        if (rc == true) {
+            printf("TEST ERROR: pmConfigRead() returned true\n");
+            testStatus = false;
+        }
+
+        printf("----------------------------------------------------------------\n");
+        printf("Calling pmConfigRead() with NULL *camera pointer.  Should generate ERROR, return false.\n");
+        rc = pmConfigRead(&site, &nullMD, &recipe, &argc, str, "RecipeName");
+        if (rc == true) {
+            printf("TEST ERROR: pmConfigRead() returned true\n");
+            testStatus = false;
+        }
+
+        printf("----------------------------------------------------------------\n");
+        printf("Calling pmConfigRead() with NULL recipe pointer.  Should generate ERROR, return false.\n");
+        rc = pmConfigRead(&site, &camera, NULL, &argc, str, "RecipeName");
+        if (rc == true) {
+            printf("TEST ERROR: pmConfigRead() returned true\n");
+            testStatus = false;
+        }
+
+        printf("----------------------------------------------------------------\n");
+        printf("Calling pmConfigRead() with NULL *recipe pointer.  Should generate ERROR, return false.\n");
+        rc = pmConfigRead(&site, &camera, &nullMD, &argc, str, "RecipeName");
+        if (rc == true) {
+            printf("TEST ERROR: pmConfigRead() returned true\n");
+            testStatus = false;
+        }
+
+        printf("----------------------------------------------------------------\n");
+        printf("Calling pmConfigRead() with NULL argv pointer.  Should generate ERROR, return false.\n");
+        rc = pmConfigRead(&site, &camera, &recipe, &argc, NULL, "RecipeName");
+        if (rc == true) {
+            printf("TEST ERROR: pmConfigRead() returned true\n");
+            testStatus = false;
+        }
+
+        printf("----------------------------------------------------------------\n");
+        printf("Calling pmConfigRead() with negative argc.  Should generate ERROR, return false.\n");
+        psS32 tmpArgc = -1;
+        rc = pmConfigRead(&site, &camera, &recipe, &tmpArgc, str, "RecipeName");
+        if (rc == true) {
+            printf("TEST ERROR: pmConfigRead() returned true\n");
+            testStatus = false;
+        }
+    }
+
+    printf("----------------------------------------------------------------\n");
+    printf("Calling pmConfigRead() with acceptable arguments.\n");
+
+    rc = pmConfigRead(&site, &camera, &recipe, &argc, str, "RecipeName");
+    if (rc == false) {
+        printf("TEST ERROR: pmConfigRead() returned False\n");
+        testStatus = false;
+    } else {
+        //
+        // Ensure that the various trace and logging values are set properly
+        //
+        if (1 != psTraceGetLevel("dummyTraceFunc01")) {
+            printf("TEST ERROR: failed to properly set tracelevel for dummyTraceFunc01\n");
+            printf("    tracelevel was %d, should be 1.\n", psTraceGetLevel("dummyTraceFunc01"));
+            testStatus = false;
+        }
+
+        if (2 != psTraceGetLevel("dummyTraceFunc02")) {
+            printf("TEST ERROR: failed to properly set tracelevel for dummyTraceFunc02\n");
+            printf("    tracelevel was %d, should be 2.\n", psTraceGetLevel("dummyTraceFunc02"));
+            testStatus = false;
+        }
+
+        if (1 != psLogGetDestination()) {
+            printf("TEST ERROR: failed to properly set log destination.\n");
+            printf("    it was %d, should be 1\n", psLogGetDestination());
+            testStatus = false;
+        }
+
+        if (3 != psLogGetLevel()) {
+            printf("TEST ERROR: failed to properly set log level.\n");
+            printf("    it was %d, should be 3\n", psLogGetLevel());
+            testStatus = false;
+        }
+
+        //
+        // Test the several arbitrary config file strings.
+        //
+        psS32 tmpInt = psMetadataLookupS32(&rc, site, "ARBITRARY_STRING_S32");
+        if ((rc == false) || (tmpInt != 20)) {
+            printf("TEST ERROR: failed to properly set metadata integer ARBITRARY_STRING_S32.\n");
+            testStatus = false;
+        }
+
+        psF32 tmpFloat = psMetadataLookupS32(&rc, site, "ARBITRARY_STRING_F32");
+        if ((rc == false) || (tmpFloat != 21.0)) {
+            printf("TEST ERROR: failed to properly set metadata float ARBITRARY_STRING_F32.\n");
+            testStatus = false;
+        }
+
+        psF64 tmpDub = psMetadataLookupS32(&rc, site, "ARBITRARY_STRING_F64");
+        if ((rc == false) || (tmpDub != 22.0)) {
+            printf("TEST ERROR: failed to properly set metadata double ARBITRARY_STRING_F64.\n");
+            testStatus = false;
+        }
+
+        psBool tmpBool;
+        tmpBool = psMetadataLookupS32(&rc, site, "ARBITRARY_STRING_BOOL_T");
+        if ((rc == false) || (tmpBool != true)) {
+            printf("TEST ERROR: failed to properly set metadata double ARBITRARY_STRING_BOOL_T.\n");
+            testStatus = false;
+        }
+        tmpBool = psMetadataLookupS32(&rc, site, "ARBITRARY_STRING_BOOL_F");
+        if ((rc == false) || (tmpBool != false)) {
+            printf("TEST ERROR: failed to properly set metadata double ARBITRARY_STRING_BOOL_F.\n");
+            testStatus = false;
+        }
+
+        //
+        // Test the database camera metadata keywords.
+        //
+        psMetadata *tmpMeta = psMetadataLookupMetadata(&rc, site, "CAMERAS");
+        if (rc == false) {
+            printf("TEST ERROR: failed to properly set metadata metadata CAMERAS.\n");
+            testStatus = false;
+        } else {
+            psString tmpStr;
+            tmpStr = psMetadataLookupStr(&rc, tmpMeta, "MEGACAM_RAW");
+            if ((rc == false) || (0 != strcmp(tmpStr, "megacam_raw.config"))) {
+                printf("TEST ERROR: failed to properly set metadata metadata CAMERAS->MEGACAM_RAW.\n");
+                testStatus = false;
+            }
+
+            tmpStr = psMetadataLookupStr(&rc, tmpMeta, "MEGACAM_SPLICE");
+            if ((rc == false) || (0 != strcmp(tmpStr, "megacam_splice.config"))) {
+                printf("TEST ERROR: failed to properly set metadata metadata CAMERAS->MEGACAM_SPLICE.\n");
+                testStatus = false;
+            }
+
+            tmpStr = psMetadataLookupStr(&rc, tmpMeta, "GPC1_RAW");
+            if ((rc == false) || (0 != strcmp(tmpStr, "gpc1_raw.config"))) {
+                printf("TEST ERROR: failed to properly set metadata metadata CAMERAS->GPC1_RAW.\n");
+                testStatus = false;
+            }
+
+            tmpStr = psMetadataLookupStr(&rc, tmpMeta, "LRIS_BLUE");
+            if ((rc == false) || (0 != strcmp(tmpStr, "lris_blue.config"))) {
+                printf("TEST ERROR: failed to properly set metadata metadata CAMERAS->LRIS_BLUE.\n");
+                testStatus = false;
+            }
+
+            tmpStr = psMetadataLookupStr(&rc, tmpMeta, "LRIS_RED");
+            if ((rc == false) || (0 != strcmp(tmpStr, "lris_red.config"))) {
+                printf("TEST ERROR: failed to properly set metadata metadata CAMERAS->LRIS_RED.\n");
+                testStatus = false;
+            }
+        }
+
+        //
+        // Test the database metadata keywords.  This is somewhat redundant since
+        // we already test metadat strings.
+        //
+        psString tmpStr;
+        tmpStr = psMetadataLookupStr(&rc, site, "DBSERVER");
+        if ((rc == false) || (0 != strcmp(tmpStr, "ippdb.ifa.hawaii.edu"))) {
+            printf("TEST ERROR: failed to properly set metadata string DBSERVER.\n");
+            testStatus = false;
+        }
+
+        tmpStr = psMetadataLookupStr(&rc, site, "DBUSER");
+        if ((rc == false) || (0 != strcmp(tmpStr, "ipp"))) {
+            printf("TEST ERROR: failed to properly set metadata string DBUSER.\n");
+            testStatus = false;
+        }
+
+        tmpStr = psMetadataLookupStr(&rc, site, "DBPASSWORD");
+        if ((rc == false) || (0 != strcmp(tmpStr, "password"))) {
+            printf("TEST ERROR: failed to properly set metadata string DBPASSWORD.\n");
+            testStatus = false;
+        }
+    }
+
+    psFree(site);
+    psFree(camera);
+    psFree(recipe);
+    return(testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/.cvsignore	(revision 22158)
@@ -0,0 +1,9 @@
+.deps
+.libs
+Makefile
+Makefile.in
+temp
+tst_pmFlatField
+tst_pmMaskBadPixels
+tst_pmNonLinear
+.tmp_tst_pmNonLinearLookupFile
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/Makefile.am	(revision 22158)
@@ -0,0 +1,26 @@
+AM_CPPFLAGS = \
+	$(SRCINC) \
+	-I$(top_srcdir)/test/tap/src \
+	-I$(top_srcdir)/test/pstap/src \
+	$(PSMODULES_CFLAGS)
+
+AM_LDFLAGS = \
+	$(top_builddir)/src/libpsmodules.la  \
+	$(top_builddir)/test/tap/src/libtap.la \
+	$(top_builddir)/test/pstap/src/libpstap.la \
+	$(PSMODULES_LIBS)
+
+TEST_PROGS = \
+	tap_pmShutterCorrection
+
+if BUILD_TESTS
+bin_PROGRAMS = $(TEST_PROGS)
+TESTS = $(TEST_PROGS)
+else
+check_PROGRAMS = $(TEST_PROGS)
+endif
+
+CLEANFILES = $(check_DATA) temp/* core core.* *~ *.bb *.bbg *.da gmon.out
+
+test: check
+	$(top_srcdir)/test/test.pl
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tap_pmBias.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tap_pmBias.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tap_pmBias.c	(revision 22158)
@@ -0,0 +1,529 @@
+/** @file tap_pmBias.c
+ *
+ * XXX: pmBiasSubtractFrame(): Must add tests for CELL.X0, CELL.Y0 stuff:
+ * XXX: pmBiasSubtractFrame(): Must add tests with scale != 1.0
+ * XXX: pmBiasSubtract(): must test with acceptable data
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define BADFLAT			0
+#define VERBOSE                 1
+#define ERR_TRACE_LEVEL         0
+#define TEST_NUM_ROWS		8
+#define TEST_NUM_COLS		8
+#define NUM_BIAS_DATA		2
+#define NUM_HDUS		8
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define CELL_ALLOC_NAME        "CellName"
+#define NUM_READOUTS            3
+#define BASE_IMAGE              10
+#define BASE_MASK               40
+#define BASE_WEIGHT             70
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (int i=0;i<TEST_NUM_ROWS;i++) {
+        for (int j=0;j<TEST_NUM_COLS;j++) {
+            readout->image->data.F32[i][j] = (float) (i + j);
+        }
+    }
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    cell->hdu = pmHDUAlloc("cellExtName");
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = generateSimpleReadout(cell);
+    }
+
+    bool rc = pmConfigFileRead(&cell->hdu->format, "../camera/data/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        diag("pmConfigFileRead() was unsuccessful (from generateSimpleCell())");
+    }
+
+    cell->hdu->images = psArrayAlloc(NUM_HDUS);
+    cell->hdu->masks = psArrayAlloc(NUM_HDUS);
+    cell->hdu->weights = psArrayAlloc(NUM_HDUS);
+    for (int k = 0 ; k < NUM_HDUS ; k++) {
+        cell->hdu->images->data[k]  = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        cell->hdu->masks->data[k]   = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        cell->hdu->weights->data[k] = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(cell->hdu->images->data[k], (float) (BASE_IMAGE+k));
+        psImageInit(cell->hdu->masks->data[k], (psU8) (BASE_MASK+k));
+        psImageInit(cell->hdu->weights->data[k], (float) (BASE_WEIGHT+k));
+    }
+
+    //XXX: Should the region be set some other way?  Like through the various config files?
+//    psRegion *region = psRegionAlloc(0.0, TEST_NUM_COLS-1, 0.0, TEST_NUM_ROWS-1);
+    psRegion *region = psRegionAlloc(0.0, 0.0, 0.0, 0.0);
+    // You shouldn't have to remove the key from the metadata.  Find out how to simply change the key value.
+    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC");
+    psMetadataAddPtr(cell->concepts, PS_LIST_TAIL|PS_META_REPLACE, "CELL.TRIMSEC", PS_DATA_REGION, "I am a region", region);
+    psFree(region);
+    return(cell);
+}
+
+void myFreeCell(pmCell *cell)
+{
+    for (int k = 0 ; k < cell->readouts->n ; k++) {
+        psFree(cell->readouts->data[k]);
+    }
+    psFree(cell);
+}
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(1);
+
+
+    // ----------------------------------------------------------------------
+    // pmBiasSubtractFrame() tests
+    // bool pmBiasSubtractFrame(pmReadout *in, pmReadout *sub, float scale)
+    // Call pmBiasSubtractFrame() with NULL pmReadout input
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *sub = generateSimpleReadout(cell);
+
+        ok(!pmBiasSubtractFrame(NULL, sub, 1.0), "pmBiasSubtractFrame(NULL, sub, 1.0) returned FALSE");
+        psFree(in);
+        psFree(sub);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // bool pmBiasSubtractFrame(pmReadout *in, pmReadout *sub, float scale)
+    // Call pmBiasSubtractFrame() with NULL pmReadout input->image
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        psFree(in->image);
+        in->image = NULL;
+        pmReadout *sub = generateSimpleReadout(cell);
+
+        ok(!pmBiasSubtractFrame(in, sub, 1.0), "pmBiasSubtractFrame() returned FALSE with NULL pmReadout input->image");
+        psFree(in);
+        psFree(sub);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmBiasSubtractFrame() with empty pmReadout input->image
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        psFree(in->image);
+        in->image = psImageAlloc(0, 0, PS_TYPE_F32);
+        pmReadout *sub = generateSimpleReadout(cell);
+
+        ok(!pmBiasSubtractFrame(in, sub, 1.0), "pmBiasSubtractFrame() returned FALSE with empty input->image");
+        psFree(in);
+        psFree(sub);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmBiasSubtractFrame() with bad type for pmReadout input->image
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        psFree(in->image);
+        in->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_S32);
+        pmReadout *sub = generateSimpleReadout(cell);
+
+        ok(!pmBiasSubtractFrame(in, sub, 1.0), "pmBiasSubtractFrame() returned FALSE with bad type for pmReadout input->image");
+        psFree(in);
+        psFree(sub);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmBiasSubtractFrame() with NULL pmReadout sub
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *sub = generateSimpleReadout(cell);
+
+        ok(!pmBiasSubtractFrame(in, NULL, 1.0), "pmBiasSubtractFrame(in, NULL, 1.0) returned FALSE");
+        psFree(in);
+        psFree(sub);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmBiasSubtractFrame() with NULL pmReadout sub->image
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *sub = generateSimpleReadout(cell);
+        psFree(sub->image);
+        sub->image = NULL;
+
+        ok(!pmBiasSubtractFrame(in, sub, 1.0), "pmBiasSubtractFrame() returned FALSE with NULL pmReadout sub->image");
+        psFree(in);
+        psFree(sub);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmBiasSubtractFrame() with empty pmReadout sub->image
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *sub = generateSimpleReadout(cell);
+        psFree(sub->image);
+        sub->image = psImageAlloc(0, 0, PS_TYPE_F32);
+
+        ok(!pmBiasSubtractFrame(in, sub, 1.0), "pmBiasSubtractFrame() returned FALSE with NULL pmReadout sub->image");
+        psFree(in);
+        psFree(sub);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmBiasSubtractFrame() with bad type for pmReadout sub->image
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *sub = generateSimpleReadout(cell);
+        psFree(sub->image);
+        sub->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_S32);
+
+        ok(!pmBiasSubtractFrame(in, sub, 1.0), "pmBiasSubtractFrame() returned FALSE with bad type for pmReadout sub->image");
+        psFree(in);
+        psFree(sub);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmBiasSubtractFrame() with differing input image sizes
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *sub = generateSimpleReadout(cell);
+        psFree(sub->image);
+        sub->image = psImageAlloc(TEST_NUM_COLS/2, TEST_NUM_ROWS/2, PS_TYPE_S32);
+
+        ok(!pmBiasSubtractFrame(in, sub, 1.0), "pmBiasSubtractFrame() returned FALSE with with differing input image sizes");
+        psFree(in);
+        psFree(sub);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmBiasSubtractFrame() with differing image X parity
+    {
+        psMemId id = psMemGetId();
+        pmCell *cellIn = generateSimpleCell(NULL);
+        pmCell *cellSub = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cellIn);
+        pmReadout *sub = generateSimpleReadout(cellSub);
+
+        // Set the X parity differently for each pmReadout's parent cell
+        psMetadataAddS32(in->parent->concepts, PS_LIST_TAIL, "CELL.XPARITY", PS_META_REPLACE, "", -1);
+        psMetadataAddS32(sub->parent->concepts, PS_LIST_TAIL, "CELL.XPARITY", PS_META_REPLACE, "", 1);
+        ok(!pmBiasSubtractFrame(in, sub, 1.0), "pmBiasSubtractFrame() returned FALSE with differing image X parity");
+        psFree(in);
+        psFree(sub);
+        myFreeCell(cellIn);
+        myFreeCell(cellSub);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmBiasSubtractFrame() with differing image Y parity
+    {
+        psMemId id = psMemGetId();
+        pmCell *cellIn = generateSimpleCell(NULL);
+        pmCell *cellSub = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cellIn);
+        pmReadout *sub = generateSimpleReadout(cellSub);
+
+        // Set the Y parity differently for each pmReadout's parent cell
+        psMetadataAddS32(in->parent->concepts, PS_LIST_TAIL, "CELL.YPARITY", PS_META_REPLACE, "", -1);
+        psMetadataAddS32(sub->parent->concepts, PS_LIST_TAIL, "CELL.YPARITY", PS_META_REPLACE, "", 1);
+        ok(!pmBiasSubtractFrame(in, sub, 1.0), "pmBiasSubtractFrame() returned FALSE with differing image Y parity");
+        psFree(in);
+        psFree(sub);
+        myFreeCell(cellIn);
+        myFreeCell(cellSub);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmBiasSubtractFrame() with differing image Y parity
+    {
+        psMemId id = psMemGetId();
+        pmCell *cellIn = generateSimpleCell(NULL);
+        pmCell *cellSub = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cellIn);
+        pmReadout *sub = generateSimpleReadout(cellSub);
+        for (int i = 0 ; i < in->image->numRows ; i++) {
+            for (int j = 0 ; j < in->image->numCols ; j++) {
+                in->image->data.F32[i][j] = (float) (i + j + 10);
+	    }
+	}
+
+        for (int i = 0 ; i < sub->image->numRows ; i++) {
+            for (int j = 0 ; j < sub->image->numCols ; j++) {
+                sub->image->data.F32[i][j] = 10.0;
+	    }
+	}
+
+        ok(pmBiasSubtractFrame(in, sub, 1.0), "pmBiasSubtractFrame() returned TRUE");
+        bool errorFlag = false;
+        for (int i = 0 ; i < in->image->numRows ; i++) {
+            for (int j = 0 ; j < in->image->numCols ; j++) {
+                if (in->image->data.F32[i][j] != (float) (i + j)) {
+                    if (VERBOSE) diag("ERROR: image[%d][%d] is %.2f, should be %.2f\n",
+                        i, j, in->image->data.F32[i][j], (float) (i + j));
+                    errorFlag = true;
+		}
+	    }
+	}
+
+        ok(!errorFlag, "pmBiasSubtractFrame() set the pixels correctly");
+        psFree(in);
+        psFree(sub);
+        myFreeCell(cellIn);
+        myFreeCell(cellSub);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmBiasSubtract() tests
+    // bool pmBiasSubtract(pmReadout *in, pmOverscanOptions *overscanOpts,
+    //               const pmReadout *bias, const pmReadout *dark, const pmFPAview *view)
+    // Call pmBiasSubtract() with NULL pmReadout input
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *bias = generateSimpleReadout(cell);
+        pmReadout *dark = generateSimpleReadout(cell);
+        pmFPAview *view = pmFPAviewAlloc(TEST_NUM_ROWS);
+        // XXX: Must set the following:
+        pmOverscanOptions *overscanOpts = NULL;
+
+        ok(!pmBiasSubtract(NULL, overscanOpts, bias, dark, view), "pmBiasSubtract() returned FALSE with NULL input pmReadout: in");
+        psFree(in);
+        psFree(bias);
+        psFree(dark);
+        myFreeCell(cell);
+        psFree(view);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmBiasSubtract() with NULL pmReadout input->image
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        psFree(in->image);
+        in->image = NULL;
+        pmReadout *bias = generateSimpleReadout(cell);
+        pmReadout *dark = generateSimpleReadout(cell);
+        pmFPAview *view = pmFPAviewAlloc(TEST_NUM_ROWS);
+        // XXX: Must set the following:
+        pmOverscanOptions *overscanOpts = NULL;
+
+        ok(!pmBiasSubtract(in, overscanOpts, bias, dark, view), "pmBiasSubtract() returned FALSE with NULL input image");
+        psFree(in);
+        psFree(bias);
+        psFree(dark);
+        myFreeCell(cell);
+        psFree(view);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmBiasSubtract() with wrong type for pmReadout input->image
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        psFree(in->image);
+        in->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_S32);
+        pmReadout *bias = generateSimpleReadout(cell);
+        pmReadout *dark = generateSimpleReadout(cell);
+        pmFPAview *view = pmFPAviewAlloc(TEST_NUM_ROWS);
+        // XXX: Must set the following:
+        pmOverscanOptions *overscanOpts = NULL;
+
+        ok(!pmBiasSubtract(in, overscanOpts, bias, dark, view), "pmBiasSubtract() returned FALSE with wrong type for pmReadout input->image");
+        psFree(in);
+        psFree(bias);
+        psFree(dark);
+        myFreeCell(cell);
+        psFree(view);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmBiasSubtract() with NULL image for input pmReadout bias
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *bias = generateSimpleReadout(cell);
+        psFree(bias->image);
+        bias->image = NULL;
+        pmReadout *dark = generateSimpleReadout(cell);
+        pmFPAview *view = pmFPAviewAlloc(TEST_NUM_ROWS);
+        // XXX: Must set the following:
+        pmOverscanOptions *overscanOpts = NULL;
+
+        ok(!pmBiasSubtract(in, overscanOpts, bias, dark, view), "pmBiasSubtract() returned FALSE with NULL image for input pmReadout bias");
+        psFree(in);
+        psFree(bias);
+        psFree(dark);
+        myFreeCell(cell);
+        psFree(view);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmBiasSubtract() with wrong type image for input pmReadout bias
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *bias = generateSimpleReadout(cell);
+        psFree(bias->image);
+        bias->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_S32);
+        pmReadout *dark = generateSimpleReadout(cell);
+        pmFPAview *view = pmFPAviewAlloc(TEST_NUM_ROWS);
+        // XXX: Must set the following:
+        pmOverscanOptions *overscanOpts = NULL;
+
+        ok(!pmBiasSubtract(in, overscanOpts, bias, dark, view), "pmBiasSubtract() returned FALSE with wrong type image for input pmReadout bias");
+        psFree(in);
+        psFree(bias);
+        psFree(dark);
+        myFreeCell(cell);
+        psFree(view);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmBiasSubtract() with NULL image for input pmReadout dark
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *bias = generateSimpleReadout(cell);
+        pmReadout *dark = generateSimpleReadout(cell);
+        psFree(dark->image);
+        dark->image = NULL;
+        pmFPAview *view = pmFPAviewAlloc(TEST_NUM_ROWS);
+        // XXX: Must set the following:
+        pmOverscanOptions *overscanOpts = NULL;
+
+        ok(!pmBiasSubtract(in, overscanOpts, bias, dark, view), "pmBiasSubtract() returned FALSE with wrong type image for input pmReadout bias");
+        psFree(in);
+        psFree(bias);
+        psFree(dark);
+        myFreeCell(cell);
+        psFree(view);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmBiasSubtract() with wrong type image for input pmReadout dark
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *bias = generateSimpleReadout(cell);
+        pmReadout *dark = generateSimpleReadout(cell);
+        psFree(dark->image);
+        dark->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_S32);
+        pmFPAview *view = pmFPAviewAlloc(TEST_NUM_ROWS);
+        // XXX: Must set the following:
+        pmOverscanOptions *overscanOpts = NULL;
+
+        ok(!pmBiasSubtract(in, overscanOpts, bias, dark, view), "pmBiasSubtract() returned FALSE with wrong type image for input pmReadout dark");
+        psFree(in);
+        psFree(bias);
+        psFree(dark);
+        myFreeCell(cell);
+        psFree(view);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmBiasSubtract() with NULL pmView (while pmReadout dark non-NULL)
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *bias = generateSimpleReadout(cell);
+        pmReadout *dark = generateSimpleReadout(cell);
+        pmFPAview *view = pmFPAviewAlloc(TEST_NUM_ROWS);
+        // XXX: Must set the following:
+        pmOverscanOptions *overscanOpts = NULL;
+
+        ok(!pmBiasSubtract(in, overscanOpts, bias, dark, NULL), "pmBiasSubtract() returned FALSE with NULL pmView (while pmReadout dark non-NULL)");
+        psFree(in);
+        psFree(bias);
+        psFree(dark);
+        myFreeCell(cell);
+        psFree(view);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tap_pmFlatField.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tap_pmFlatField.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tap_pmFlatField.c	(revision 22158)
@@ -0,0 +1,348 @@
+/** @file tap_pmFlatField.c
+ *
+ * XXX: Added a mask argument to pmFlatField().  Must add tests.  For now, all
+ * masks are NULL.
+ *
+ *  XXX: I added the CELL.TRIMSEC region code but there are not tests for it.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+#define BADFLAT			0
+#define VERBOSE                 1
+#define ERR_TRACE_LEVEL         10
+#define TEST_NUM_ROWS		8
+#define TEST_NUM_COLS		8
+#define NUM_BIAS_DATA		2
+#define NUM_HDUS		8
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define CELL_ALLOC_NAME        "CellName"
+#define NUM_READOUTS            3
+#define BASE_IMAGE              10
+#define BASE_MASK               40
+#define BASE_WEIGHT             70
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (int i=0;i<TEST_NUM_ROWS;i++) {
+        for (int j=0;j<TEST_NUM_COLS;j++) {
+            readout->image->data.F32[i][j] = (float) (i + j);
+        }
+    }
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    cell->hdu = pmHDUAlloc("cellExtName");
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = generateSimpleReadout(cell);
+    }
+
+    bool rc = pmConfigFileRead(&cell->hdu->format, "../camera/data/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        diag("pmConfigFileRead() was unsuccessful (from generateSimpleCell())");
+    }
+
+    cell->hdu->images = psArrayAlloc(NUM_HDUS);
+    cell->hdu->masks = psArrayAlloc(NUM_HDUS);
+    cell->hdu->weights = psArrayAlloc(NUM_HDUS);
+    for (int k = 0 ; k < NUM_HDUS ; k++) {
+        cell->hdu->images->data[k]  = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        cell->hdu->masks->data[k]   = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        cell->hdu->weights->data[k] = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(cell->hdu->images->data[k], (float) (BASE_IMAGE+k));
+        psImageInit(cell->hdu->masks->data[k], (psU8) (BASE_MASK+k));
+        psImageInit(cell->hdu->weights->data[k], (float) (BASE_WEIGHT+k));
+    }
+
+    //XXX: Should the region be set some other way?  Like through the various config files?
+//    psRegion *region = psRegionAlloc(0.0, TEST_NUM_COLS-1, 0.0, TEST_NUM_ROWS-1);
+    psRegion *region = psRegionAlloc(0.0, 0.0, 0.0, 0.0);
+    // You shouldn't have to remove the key from the metadata.  Find out how to simply change the key value.
+    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC");
+    psMetadataAddPtr(cell->concepts, PS_LIST_TAIL|PS_META_REPLACE, "CELL.TRIMSEC", PS_DATA_REGION, "I am a region", region);
+    psFree(region);
+    return(cell);
+}
+
+void myFreeCell(pmCell *cell)
+{
+    for (int k = 0 ; k < cell->readouts->n ; k++) {
+        psFree(cell->readouts->data[k]);
+    }
+    psFree(cell);
+}
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(28);
+
+
+    // bool pmFlatField(pmReadout *in, pmReadout *flat, psMaskType badFlat)
+    // Test pmFlatField() with NULL input psReadout
+    {
+        psMemId id = psMemGetId();
+        pmReadout *in = generateSimpleReadout(NULL);
+        pmReadout *flat = generateSimpleReadout(NULL);
+        ok(!pmFlatField(NULL, flat, 0), "pmFlatField(NULL, flat, 0) returned FALSE");
+        psFree(in);
+        psFree(flat);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // bool pmFlatField(pmReadout *in, pmReadout *flat, psMaskType badFlat)
+    // Test pmFlatField() with NULL input psReadout->image
+    {
+        psMemId id = psMemGetId();
+        pmReadout *in = generateSimpleReadout(NULL);
+        psFree(in->image);
+        in->image = NULL;
+        pmReadout *flat = generateSimpleReadout(NULL);
+        ok(!pmFlatField(in, flat, 0), "pmFlatField(in, flat, 0) returned FALSE with NULL input psReadout->image");
+        psFree(in);
+        psFree(flat);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // bool pmFlatField(pmReadout *in, pmReadout *flat, psMaskType badFlat)
+    // Test pmFlatField() with NULL input psReadout->image
+    {
+        psMemId id = psMemGetId();
+        pmReadout *in = generateSimpleReadout(NULL);
+        psFree(in->image);
+        in->image = psImageAlloc(0, 0, PS_TYPE_F32);
+        pmReadout *flat = generateSimpleReadout(NULL);
+        ok(!pmFlatField(in, flat, 0), "pmFlatField(in, flat, 0) returned FALSE with empty input psReadout->image");
+        psFree(in);
+        psFree(flat);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // bool pmFlatField(pmReadout *in, pmReadout *flat, psMaskType badFlat)
+    // Test pmFlatField() with NULL input flat
+    {
+        psMemId id = psMemGetId();
+        pmReadout *in = generateSimpleReadout(NULL);
+        pmReadout *flat = generateSimpleReadout(NULL);
+        ok(!pmFlatField(in, NULL, 0), "pmFlatField(in, NULL, 0) returned FALSE");
+        psFree(in);
+        psFree(flat);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // bool pmFlatField(pmReadout *in, pmReadout *flat, psMaskType badFlat)
+    // Test pmFlatField() with NULL input flat->image
+    {
+        psMemId id = psMemGetId();
+        pmReadout *in = generateSimpleReadout(NULL);
+        pmReadout *flat = generateSimpleReadout(NULL);
+        psFree(flat->image);
+        flat->image = NULL;
+        ok(!pmFlatField(in, NULL, 0), "pmFlatField(in, flat, 0) returned FALSE with NULL input flat->image");
+        psFree(in);
+        psFree(flat);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // bool pmFlatField(pmReadout *in, pmReadout *flat, psMaskType badFlat)
+    // Test pmFlatField() with NULL input flat->image
+    {
+        psMemId id = psMemGetId();
+        pmReadout *in = generateSimpleReadout(NULL);
+        pmReadout *flat = generateSimpleReadout(NULL);
+        psFree(flat->image);
+        flat->image = psImageAlloc(0, 0, PS_TYPE_F32);
+        ok(!pmFlatField(in, NULL, 0), "pmFlatField(in, flat, 0) returned FALSE with empty input flat->image");
+        psFree(in);
+        psFree(flat);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // bool pmFlatField(pmReadout *in, pmReadout *flat, psMaskType badFlat)
+    // Test pmFlatField() with differing types of flat/in image
+    {
+        psMemId id = psMemGetId();
+        pmReadout *in = generateSimpleReadout(NULL);
+        pmReadout *flat = generateSimpleReadout(NULL);
+        psFree(flat->image);
+        flat->image = psImageAlloc(0, 0, PS_TYPE_F64);
+        ok(!pmFlatField(in, NULL, 0), "pmFlatField(in, flat, 0) returned FALSE with differing types of flat/in image");
+        psFree(in);
+        psFree(flat);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmFlatField() with input image larger than flat image
+    {
+        psMemId id = psMemGetId();
+        pmReadout *in = generateSimpleReadout(NULL);
+        pmReadout *flat = generateSimpleReadout(NULL);
+        psFree(flat->image);
+        flat->image = psImageAlloc(TEST_NUM_ROWS/2, TEST_NUM_COLS/2, PS_TYPE_F32);
+        ok(!pmFlatField(in, flat, 1), "pmFlatField(in, flat, 0) returned FALSE with input image larger than flat image");
+        psFree(in);
+        psFree(flat);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmFlatField() with input image and flat image of differing types
+    {
+        psMemId id = psMemGetId();
+        pmReadout *in = generateSimpleReadout(NULL);
+        pmReadout *flat = generateSimpleReadout(NULL);
+        psFree(flat->image);
+        flat->image = psImageAlloc(TEST_NUM_ROWS, TEST_NUM_COLS, PS_TYPE_F64);
+        ok(!pmFlatField(in, flat, 1), "pmFlatField(in, flat, 0) returned FALSE with input image and flat image of differing types");
+        psFree(in);
+        psFree(flat);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmFlatField() with input image mask smaller than input image
+    {
+        psMemId id = psMemGetId();
+        pmReadout *in = generateSimpleReadout(NULL);
+        pmReadout *flat = generateSimpleReadout(NULL);
+        psFree(in->mask);
+        in->mask = psImageAlloc(TEST_NUM_ROWS/2, TEST_NUM_COLS/2, PS_TYPE_MASK);
+        ok(!pmFlatField(in, flat, 1), "pmFlatField(in, flat, 0) returned FALSE with input image mask smaller than input image");
+        psFree(in);
+        psFree(flat);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmFlatField() with input image mask of incorrect type
+    {
+        psMemId id = psMemGetId();
+        pmReadout *in = generateSimpleReadout(NULL);
+        pmReadout *flat = generateSimpleReadout(NULL);
+        psFree(in->mask);
+        in->mask = psImageAlloc(TEST_NUM_ROWS, TEST_NUM_COLS, PS_TYPE_F32);
+        ok(!pmFlatField(in, flat, 1), "pmFlatField(in, flat, 0) returned FALSE with input image mask of incorrect type");
+        psFree(in);
+        psFree(flat);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmFlatField() with offset greater than input image
+    // XXX: Must rewrite with offsets coming from metadata
+    if (0) {
+        psMemId id = psMemGetId();
+        pmReadout *in = generateSimpleReadout(NULL);
+        pmReadout *flat = generateSimpleReadout(NULL);
+        *(int*)&in->col0 = 50;
+        *(int*)&in->row0 = 50;
+        ok(!pmFlatField(in, flat, 1), "pmFlatField(in, flat, 0) returned FALSE with offset greater than input image");
+        psFree(in);
+        psFree(flat);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmFlatField() with acceptable input data
+    // Set the flat field to 1
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *flat = generateSimpleReadout(cell);
+        psImageInit(in->image, 6.0);
+        psImageInit(in->mask, 0);
+        psImageInit(flat->image, 2.0);
+        ok(pmFlatField(in, flat, 1), "pmFlatField(in, flat, 0) returned TRUE with acceptable input data");
+        bool errorFlag = false;
+        for (int i = 0 ; i < in->image->numRows ; i++) {
+            for (int j = 0 ; j < in->image->numCols ; j++) {
+                if (in->image->data.F32[i][j] != 3.0) {
+                    if (VERBOSE) diag("ERROR: image[%d][%d] is %.2f, should be 3.0", i, j,
+                        in->image->data.F32[i][j]);
+		}
+                if (in->mask->data.PS_TYPE_MASK_DATA[i][j] != 0) {
+                    if (VERBOSE) diag("ERROR: mask[%d][%d] is %d, should be 0", i, j,
+                        in->image->data.PS_TYPE_MASK_DATA[i][j]);
+		}
+	    }
+	}
+        ok(!errorFlag, "pmFlatField() set the image data correctly");
+
+        psFree(in);
+        psFree(flat);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmFlatField() with acceptable input data
+    // Set the flat field to -1
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *flat = generateSimpleReadout(cell);
+        psImageInit(in->image, 6.0);
+        psImageInit(in->mask, 0);
+        psImageInit(flat->image, -1.0);
+        ok(pmFlatField(in, flat, 1), "pmFlatField(in, flat, 0) returned TRUE with acceptable input data");
+        bool errorFlag = false;
+        for (int i = 0 ; i < in->image->numRows ; i++) {
+            for (int j = 0 ; j < in->image->numCols ; j++) {
+                if (!isnan(in->image->data.F32[i][j])) {
+                    if (VERBOSE) diag("ERROR: image[%d][%d] is %.2f, should be NAN", i, j,
+                        in->image->data.F32[i][j]);
+		}
+                if (in->mask->data.PS_TYPE_MASK_DATA[i][j] != 1) {
+                    if (VERBOSE) diag("ERROR: mask[%d][%d] is %d, should be 0", i, j,
+                        in->image->data.PS_TYPE_MASK_DATA[i][j]);
+		}
+	    }
+	}
+        ok(!errorFlag, "pmFlatField() set the image data correctly");
+
+        psFree(in);
+        psFree(flat);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tap_pmMaskBadPixels.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tap_pmMaskBadPixels.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tap_pmMaskBadPixels.c	(revision 22158)
@@ -0,0 +1,520 @@
+/** @file tap_pmMaskBadPixels.c
+ *
+ * XXX: must test pmMaskFlagSuspectPixels() with acceptable input data
+ * XXX: must test pmMaskIdentifyBadPixels() with acceptable input data
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define BADFLAT			0
+#define VERBOSE                 1
+#define ERR_TRACE_LEVEL         0
+#define TEST_NUM_ROWS		8
+#define TEST_NUM_COLS		8
+#define NUM_BIAS_DATA		2
+#define NUM_HDUS		8
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define CELL_ALLOC_NAME        "CellName"
+#define NUM_READOUTS            3
+#define BASE_IMAGE              10
+#define BASE_MASK               40
+#define BASE_WEIGHT             70
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (int i=0;i<TEST_NUM_ROWS;i++) {
+        for (int j=0;j<TEST_NUM_COLS;j++) {
+            readout->image->data.F32[i][j] = (float) (i + j);
+        }
+    }
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    cell->hdu = pmHDUAlloc("cellExtName");
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = generateSimpleReadout(cell);
+    }
+
+    bool rc = pmConfigFileRead(&cell->hdu->format, "../camera/data/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        diag("pmConfigFileRead() was unsuccessful (from generateSimpleCell())");
+    }
+
+    cell->hdu->images = psArrayAlloc(NUM_HDUS);
+    cell->hdu->masks = psArrayAlloc(NUM_HDUS);
+    cell->hdu->weights = psArrayAlloc(NUM_HDUS);
+    for (int k = 0 ; k < NUM_HDUS ; k++) {
+        cell->hdu->images->data[k]  = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        cell->hdu->masks->data[k]   = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        cell->hdu->weights->data[k] = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(cell->hdu->images->data[k], (float) (BASE_IMAGE+k));
+        psImageInit(cell->hdu->masks->data[k], (psU8) (BASE_MASK+k));
+        psImageInit(cell->hdu->weights->data[k], (float) (BASE_WEIGHT+k));
+    }
+
+    //XXX: Should the region be set some other way?  Like through the various config files?
+//    psRegion *region = psRegionAlloc(0.0, TEST_NUM_COLS-1, 0.0, TEST_NUM_ROWS-1);
+    psRegion *region = psRegionAlloc(0.0, 0.0, 0.0, 0.0);
+    // You shouldn't have to remove the key from the metadata.  Find out how to simply change the key value.
+    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC");
+    psMetadataAddPtr(cell->concepts, PS_LIST_TAIL|PS_META_REPLACE, "CELL.TRIMSEC", PS_DATA_REGION, "I am a region", region);
+    psFree(region);
+    return(cell);
+}
+
+void myFreeCell(pmCell *cell)
+{
+    for (int k = 0 ; k < cell->readouts->n ; k++) {
+        psFree(cell->readouts->data[k]);
+    }
+    psFree(cell);
+}
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(1);
+
+
+    // ----------------------------------------------------------------------
+    // pmMaskBadPixels() tests
+    // Call pmMaskBadPixels() with NULL pmReadout input
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *mask = generateSimpleReadout(cell);
+
+        ok(!pmMaskBadPixels(NULL, mask, 0), "pmMaskBadPixels(NULL, mask, 0) returned FALSE");
+        psFree(in);
+        psFree(mask);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskBadPixels() with NULL pmReadout input->mask
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        psFree(in->mask);
+        in->mask = NULL;
+        pmReadout *mask = generateSimpleReadout(cell);
+
+        ok(!pmMaskBadPixels(in, mask, 0), "pmMaskBadPixels() returned FALSE with NULL pmReadout input->mask");
+        psFree(in);
+        psFree(mask);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskBadPixels() with incorrect type for input->mask
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        psFree(in->mask);
+        in->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        pmReadout *mask = generateSimpleReadout(cell);
+
+        ok(!pmMaskBadPixels(in, mask, 0), "pmMaskBadPixels() returned FALSE with NULL pmReadout input->mask");
+        psFree(in);
+        psFree(mask);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskBadPixels() with NULL pmReadout mask
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *mask = generateSimpleReadout(cell);
+
+        ok(!pmMaskBadPixels(in, NULL, 0), "pmMaskBadPixels(in, NULL, 0) returned FALSE");
+        psFree(in);
+        psFree(mask);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskBadPixels() with NULL pmReadout mask->mask
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *mask = generateSimpleReadout(cell);
+        psFree(mask->mask);
+        mask->mask = NULL;
+
+        ok(!pmMaskBadPixels(in, mask, 0), "pmMaskBadPixels() returned FALSE with NULL pmReadout mask->mask");
+        psFree(in);
+        psFree(mask);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskBadPixels() with incorrect type for mask->mask
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *mask = generateSimpleReadout(cell);
+        psFree(mask->mask);
+        mask->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+
+        ok(!pmMaskBadPixels(in, mask, 0), "pmMaskBadPixels() returned FALSE with incorrect type for mask->mask");
+        psFree(in);
+        psFree(mask);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskBadPixels() with input mask larger than mask->mask
+    {
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *mask = generateSimpleReadout(cell);
+        psFree(mask->mask);
+        mask->mask = psImageAlloc(TEST_NUM_COLS/2, TEST_NUM_ROWS/2, PS_TYPE_MASK);
+
+        ok(!pmMaskBadPixels(in, mask, 0), "pmMaskBadPixels() returned FALSE with input mask larger than mask->mask");
+        psFree(in);
+        psFree(mask);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskBadPixels() with acceptable input data
+    {
+        #define MASK_VAL 1
+        psMemId id = psMemGetId();
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        pmReadout *mask = generateSimpleReadout(cell);
+        for (int i = 0 ; i < in->mask->numRows ; i++) {
+            for (int j = 0 ; j < in->mask->numCols ; j++) {
+                in->mask->data.PS_TYPE_MASK_DATA[i][j] = 0;
+                mask->mask->data.PS_TYPE_MASK_DATA[i][j] = 0;
+                if (i >= in->mask->numRows/2 && j >= in->mask->numCols/2) {
+                    mask->mask->data.PS_TYPE_MASK_DATA[i][j] = MASK_VAL;
+		}
+	    }
+	}
+
+        ok(pmMaskBadPixels(in, mask, MASK_VAL), "pmMaskBadPixels() returned TRUE with acceptable input data");
+        bool errorFlag = false;     
+        for (int i = 0 ; i < in->mask->numRows ; i++) {
+            for (int j = 0 ; j < in->mask->numCols ; j++) {
+                psU8 expect;
+                if (i >= in->mask->numRows/2 && j >= in->mask->numCols/2) {
+                    expect = MASK_VAL;
+		} else {
+                    expect = 0;
+		}
+                if (in->mask->data.PS_TYPE_MASK_DATA[i][j] != expect) {
+                    if (VERBOSE) diag("ERROR: in->mask[%d][%d] is %d, should be %d",
+                                       i, j, in->mask->data.PS_TYPE_MASK_DATA[i][j], expect);
+                    errorFlag = true;
+		}
+	    }
+	}
+        ok(!errorFlag, "pmMaskBadPixels() set the input mask correctly");
+
+        psFree(in);
+        psFree(mask);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+
+    // ----------------------------------------------------------------------
+    // pmMaskFlagSuspectPixels() tests
+    // Call pmMaskFlagSuspectPixels() with NULL pmReadout input
+    {
+        psMemId id = psMemGetId();
+        psImage *out = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_S32);
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+
+        ok(!pmMaskFlagSuspectPixels(out, NULL, 1.0, 1, 1.0, rng), "pmMaskFlagSuspectPixels() returned NULL with NULL input pmReadout");
+        psFree(rng);
+        psFree(out);
+        psFree(in);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskFlagSuspectPixels() with NULL pmReadout->image
+    {
+        psMemId id = psMemGetId();
+        psImage *out = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_S32);
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        psFree(in->image);
+        in->image = NULL;
+        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+        ok(!pmMaskFlagSuspectPixels(out, NULL, 1.0, 1, 1.0, rng), "pmMaskFlagSuspectPixels() returned NULL with NULL input pmReadout->image");
+        psFree(rng);
+        psFree(out);
+        psFree(in);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskFlagSuspectPixels() with empty pmReadout->image
+    {
+        psMemId id = psMemGetId();
+        psImage *out = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_S32);
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        psFree(in->image);
+        in->image = psImageAlloc(0, 0, PS_TYPE_F32);
+        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+        ok(!pmMaskFlagSuspectPixels(out, NULL, 1.0, 1, 1.0, rng), "pmMaskFlagSuspectPixels() returned NULL with empty input pmReadout->image");
+        psFree(rng);
+        psFree(out);
+        psFree(in);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskFlagSuspectPixels() with incorrect type for pmReadout->image
+    {
+        psMemId id = psMemGetId();
+        psImage *out = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_S32);
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        psFree(in->image);
+        in->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_S32);
+        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+        ok(!pmMaskFlagSuspectPixels(out, NULL, 1.0, 1, 1.0, rng), "pmMaskFlagSuspectPixels() returned NULL with incorrect type for pmReadout->image");
+        psFree(rng);
+        psFree(out);
+        psFree(in);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskFlagSuspectPixels() with empty in->mask
+    {
+        psMemId id = psMemGetId();
+        psImage *out = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_S32);
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        psFree(in->mask);
+        in->mask = psImageAlloc(0, 0, PS_TYPE_MASK);
+        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+        ok(!pmMaskFlagSuspectPixels(out, NULL, 1.0, 1, 1.0, rng), "pmMaskFlagSuspectPixels() returned NULL with incorrect type for pmReadout->image");
+        psFree(rng);
+        psFree(out);
+        psFree(in);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskFlagSuspectPixels() with bad size for in->mask
+    {
+        psMemId id = psMemGetId();
+        psImage *out = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_S32);
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        psFree(in->mask);
+        in->mask = psImageAlloc(TEST_NUM_COLS/2, TEST_NUM_ROWS/2, PS_TYPE_MASK);
+        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+        ok(!pmMaskFlagSuspectPixels(out, NULL, 1.0, 1, 1.0, rng), "pmMaskFlagSuspectPixels() returned NULL with bad size for in->mask");
+        psFree(rng);
+        psFree(out);
+        psFree(in);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskFlagSuspectPixels() with bad type for in->mask
+    {
+        psMemId id = psMemGetId();
+        psImage *out = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_S32);
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        psFree(in->mask);
+        in->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_S32);
+        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+        ok(!pmMaskFlagSuspectPixels(out, NULL, 1.0, 1, 1.0, rng), "pmMaskFlagSuspectPixels() returned NULL with bad type for in->mask");
+        psFree(rng);
+        psFree(out);
+        psFree(in);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskFlagSuspectPixels() with empty out image
+    {
+        psMemId id = psMemGetId();
+        psImage *out = psImageAlloc(0, 0, PS_TYPE_S32);
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+        ok(!pmMaskFlagSuspectPixels(out, NULL, 1.0, 1, 1.0, rng), "pmMaskFlagSuspectPixels() returned NULL with empty out image");
+        psFree(rng);
+        psFree(out);
+        psFree(in);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskFlagSuspectPixels() with incorrect type for out image
+    {
+        psMemId id = psMemGetId();
+        psImage *out = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+        ok(!pmMaskFlagSuspectPixels(out, NULL, 1.0, 1, 1.0, rng), "pmMaskFlagSuspectPixels() returned NULL with incorrect type for out image");
+        psFree(rng);
+        psFree(out);
+        psFree(in);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskFlagSuspectPixels() with incorrect size for out image
+    {
+        psMemId id = psMemGetId();
+        psImage *out = psImageAlloc(TEST_NUM_COLS/2, TEST_NUM_ROWS/2, PS_TYPE_S32);
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+        ok(!pmMaskFlagSuspectPixels(out, NULL, 1.0, 1, 1.0, rng), "pmMaskFlagSuspectPixels() returned NULL with incorrect size for out image");
+        psFree(rng);
+        psFree(out);
+        psFree(in);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskFlagSuspectPixels() with rej input <= 0.0
+    {
+        psMemId id = psMemGetId();
+        psImage *out = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_S32);
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+
+        ok(!pmMaskFlagSuspectPixels(out, in, 0.0, 1, 1.0, rng), "pmMaskFlagSuspectPixels() returned NULL with rej input <= 0.0");
+        psFree(rng);
+        psFree(out);
+        psFree(in);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskFlagSuspectPixels() with frac input outside range [0.0:1.0]
+    {
+        psMemId id = psMemGetId();
+        psImage *out = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_S32);
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *in = generateSimpleReadout(cell);
+        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+
+        ok(!pmMaskFlagSuspectPixels(out, in, 1.0, 1, -1.0, rng), "pmMaskFlagSuspectPixels() returned NULL with frac input < 0.0");
+        ok(!pmMaskFlagSuspectPixels(out, in, 1.0, 1, 2.0, rng), "pmMaskFlagSuspectPixels() returned NULL with frac input > 1.0");
+        psFree(rng);
+        psFree(out);
+        psFree(in);
+        myFreeCell(cell);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+
+    // ----------------------------------------------------------------------
+    // pmMaskIdentifyBadPixels() tests
+    // Call pmMaskIdentifyBadPixels() with NULL input image
+    {
+        psMemId id = psMemGetId();
+        psImage *suspects = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_S32);
+        ok(!pmMaskIdentifyBadPixels(NULL, 1.0, 0), "pmMaskIdentifyBadPixels() returned NULL with NULL input image");
+        psFree(suspects);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskIdentifyBadPixels() with empty input image
+    {
+        psMemId id = psMemGetId();
+        psImage *suspects = psImageAlloc(0, 0, PS_TYPE_S32);
+        ok(!pmMaskIdentifyBadPixels(NULL, 1.0, 0), "pmMaskIdentifyBadPixels() returned NULL with empty input image");
+        psFree(suspects);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmMaskIdentifyBadPixels() with incorrect type for input image
+    {
+        psMemId id = psMemGetId();
+        psImage *suspects = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        ok(!pmMaskIdentifyBadPixels(NULL, 1.0, 0), "pmMaskIdentifyBadPixels() returned NULL with incorrect type for input image");
+        psFree(suspects);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tap_pmNonLinear.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tap_pmNonLinear.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tap_pmNonLinear.c	(revision 22158)
@@ -0,0 +1,237 @@
+/* @file tap_pmNonLinear.c
+ *
+ *  XXX: Add tests 
+ *      Input psVectors and psImages have incorrect type
+ *      Input psVectors are wrong size
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define TEST_NUM_ROWS 8
+#define TEST_NUM_COLS 8
+#define NUM_BIAS_DATA 2
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (int i=0;i<TEST_NUM_ROWS;i++) {
+        for (int j=0;j<TEST_NUM_COLS;j++) {
+            readout->image->data.F32[i][j] = (float) (i + j);
+        }
+    }
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(72);
+
+
+    // ----------------------------------------------------------------------
+    // pmNonLinearityPolynomial() tests
+    // Call pmNonLinearityPolynomial() with NULL input readout.
+    {
+        psMemId id = psMemGetId();
+        psPolynomial1D *myPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 2);
+        myPoly->coeff[1] = 1.0;
+        pmReadout *rc = pmNonLinearityPolynomial(NULL, myPoly);
+        ok(!rc, "pmNonLinearityPolynomial() returned NULL with a NULL input pmReadout");
+        psFree(myPoly);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    
+     
+    // Call pmNonLinearityPolynomial() with NULL input readout->image.
+    {
+        psMemId id = psMemGetId();
+        pmReadout *myReadout = generateSimpleReadout(NULL);
+        psPolynomial1D *myPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 2);
+        myPoly->coeff[1] = 1.0;
+        psImage *tmpImage = myReadout->image;
+        myReadout->image = NULL;
+        pmReadout *rc = pmNonLinearityPolynomial(myReadout, myPoly);
+        ok(!rc, "pmNonLinearityPolynomial() returned NULL with a NULL input pmReadout");
+        myReadout->image = tmpImage;
+        psFree(myReadout);
+        psFree(myPoly);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    
+     
+    // Call pmNonLinearityPolynomial() with NULL polynomial.
+    {
+        psMemId id = psMemGetId();
+        pmReadout *myReadout = generateSimpleReadout(NULL);
+        pmReadout *rc = pmNonLinearityPolynomial(myReadout, NULL);
+        ok(!rc, "pmNonLinearityPolynomial() returned NULL with a NULL input psPolynomial");
+        psFree(myReadout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    
+     
+    // Call pmNonLinearityPolynomial() with acceptable input data
+    { 
+        psMemId id = psMemGetId();
+        pmReadout *myReadout = generateSimpleReadout(NULL);
+        psPolynomial1D *myPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 2);
+        myPoly->coeff[1] = 1.0;
+        myReadout = pmNonLinearityPolynomial(myReadout, myPoly);
+        bool errorFlag = false;
+        for (int i=0;i<TEST_NUM_ROWS;i++) {
+            for (int j=0;j<TEST_NUM_COLS;j++) {
+                float expect = psPolynomial1DEval(myPoly, (float) (i + j));
+                float actual = myReadout->image->data.F32[i][j];
+                if (FLT_EPSILON < fabs(expect - actual)) {
+                    if (VERBOSE) diag("TEST ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "pmNonLinearityPolynomial() set the image data correctly");
+    
+        psFree(myReadout);
+        psFree(myPoly);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmNonLinearityLookup() tests
+    // Call pmNonLinearityLookup() with NULL input pmReadout.
+    {
+        psMemId id = psMemGetId();
+        psVector *inVec = psVectorAlloc(PS_MAX(TEST_NUM_COLS, TEST_NUM_ROWS)*3, PS_TYPE_F32);
+        psVector *outVec = psVectorAlloc(PS_MAX(TEST_NUM_COLS, TEST_NUM_ROWS)*3, PS_TYPE_F32);
+        for (psS32 i=0;i<PS_MAX(TEST_NUM_COLS, TEST_NUM_ROWS)*3;i++) {
+            inVec->data.F32[i] = (float) i;
+            outVec->data.F32[i] = (float) (2 * i);
+        }
+        pmReadout *rc = pmNonLinearityLookup(NULL, inVec, outVec);
+        ok(!rc, "pmNonLinearityLookup() returned NULL with NULL input pmReadout");
+        psFree(inVec);
+        psFree(outVec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmNonLinearityLookup() with NULL input pmReadout->image
+    {
+        psMemId id = psMemGetId();
+        pmReadout *myReadout = generateSimpleReadout(NULL);
+        psImage *tmpImage = myReadout->image;
+        myReadout->image = NULL;
+        psVector *inVec = psVectorAlloc(PS_MAX(TEST_NUM_COLS, TEST_NUM_ROWS)*3, PS_TYPE_F32);
+        psVector *outVec = psVectorAlloc(PS_MAX(TEST_NUM_COLS, TEST_NUM_ROWS)*3, PS_TYPE_F32);
+        for (psS32 i=0;i<PS_MAX(TEST_NUM_COLS, TEST_NUM_ROWS)*3;i++) {
+            inVec->data.F32[i] = (float) i;
+            outVec->data.F32[i] = (float) (2 * i);
+        }
+        pmReadout *rc = pmNonLinearityLookup(myReadout, inVec, outVec);
+        ok(!rc, "pmNonLinearityLookup() returned NULL with NULL input pmReadout->image");
+        myReadout->image = tmpImage;
+        psFree(myReadout);
+        psFree(inVec);
+        psFree(outVec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmNonLinearityLookup() with NULL input inFlux
+    {
+        psMemId id = psMemGetId();
+        pmReadout *myReadout = generateSimpleReadout(NULL);
+        psVector *inVec = psVectorAlloc(PS_MAX(TEST_NUM_COLS, TEST_NUM_ROWS)*3, PS_TYPE_F32);
+        psVector *outVec = psVectorAlloc(PS_MAX(TEST_NUM_COLS, TEST_NUM_ROWS)*3, PS_TYPE_F32);
+        for (psS32 i=0;i<PS_MAX(TEST_NUM_COLS, TEST_NUM_ROWS)*3;i++) {
+            inVec->data.F32[i] = (float) i;
+            outVec->data.F32[i] = (float) (2 * i);
+        }
+        pmReadout *rc = pmNonLinearityLookup(myReadout, NULL, outVec);
+        ok(!rc, "pmNonLinearityLookup() returned NULL with input inFlux");
+        psFree(myReadout);
+        psFree(inVec);
+        psFree(outVec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Call pmNonLinearityLookup() with NULL input outFlux
+    {
+        psMemId id = psMemGetId();
+        pmReadout *myReadout = generateSimpleReadout(NULL);
+        psVector *inVec = psVectorAlloc(PS_MAX(TEST_NUM_COLS, TEST_NUM_ROWS)*3, PS_TYPE_F32);
+        psVector *outVec = psVectorAlloc(PS_MAX(TEST_NUM_COLS, TEST_NUM_ROWS)*3, PS_TYPE_F32);
+        for (psS32 i=0;i<PS_MAX(TEST_NUM_COLS, TEST_NUM_ROWS)*3;i++) {
+            inVec->data.F32[i] = (float) i;
+            outVec->data.F32[i] = (float) (2 * i);
+        }
+        pmReadout *rc = pmNonLinearityLookup(myReadout, inVec, NULL);
+        ok(!rc, "pmNonLinearityLookup() returned NULL with input outFlux");
+        psFree(myReadout);
+        psFree(inVec);
+        psFree(outVec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmNonLinearityLookup() with acceptable input data
+    {
+        psMemId id = psMemGetId();
+        pmReadout *myReadout = generateSimpleReadout(NULL);
+        psVector *inVec = psVectorAlloc(PS_MAX(TEST_NUM_COLS, TEST_NUM_ROWS)*3, PS_TYPE_F32);
+        psVector *outVec = psVectorAlloc(PS_MAX(TEST_NUM_COLS, TEST_NUM_ROWS)*3, PS_TYPE_F32);
+        for (psS32 i=0;i<PS_MAX(TEST_NUM_COLS, TEST_NUM_ROWS)*3;i++) {
+            inVec->data.F32[i] = (float) i;
+            outVec->data.F32[i] = (float) (2 * i);
+        }
+        {
+            myReadout = pmNonLinearityLookup(myReadout, inVec, outVec);
+            ok(myReadout, "pmNonLinearityLookup() returned non-NULL with acceptable input data");
+            bool errorFlag = false;
+            if (myReadout) {
+                for (int i=0;i<TEST_NUM_ROWS;i++) {
+                    for (int j=0;j<TEST_NUM_COLS;j++) {
+                        float expect = (float) (2 * (i + j));
+                        float actual = myReadout->image->data.F32[i][j];
+                        if (FLT_EPSILON < fabs(expect - actual)) {
+                            if (VERBOSE) diag("TEST ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
+                            errorFlag = true;
+                        }
+                    }
+                }
+                ok(!errorFlag, "pmNonLinearityLookup() set the image data correctly");
+	    }
+	}
+        psFree(myReadout);
+        psFree(inVec);
+        psFree(outVec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tap_pmShutterCorrection.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tap_pmShutterCorrection.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tap_pmShutterCorrection.c	(revision 22158)
@@ -0,0 +1,430 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "tap.h"
+
+int main (void)
+{
+    plan_tests(46);
+
+    diag("pmShutterCorrection tests");
+
+    // test allocation, free of pmShutterCorrPars
+    diag("pmShutterCorrParsAlloc tests");
+    {
+        psMemId id = psMemGetId();
+        pmShutterCorrection *pars = pmShutterCorrectionAlloc ();
+
+        ok(pars != NULL, "pmShutterCorrPars successfully allocated");
+        skip_start(pars == NULL, 0, "Skipping tests because pmShutterCorrParsAlloc() failed");
+        skip_end();
+
+        psFree(pars);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test parameter guess (linearly spaced exptimes, TK/TO < 1)
+    diag("pmShutterCorrectionGuess tests : coarse linear-spaced exptimes");
+    {
+        psMemId id = psMemGetId();
+
+        int NPTS = 10;
+        float AK = 5.0;
+        float TK = 0.1;
+        float TO = 0.2;
+        psVector *exptime = psVectorAlloc (NPTS, PS_TYPE_F32);
+        psVector *counts  = psVectorAlloc (NPTS, PS_TYPE_F32);
+        exptime->n = counts->n = NPTS;
+
+        for (int i = 0; i < exptime->n; i++) {
+            exptime->data.F32[i] = i*0.25;
+            counts->data.F32[i] = AK*(exptime->data.F32[i] + TK) / (exptime->data.F32[i] + TO);
+        }
+
+        pmShutterCorrection *pars = pmShutterCorrectionGuess (exptime, counts);
+
+        ok(pars != NULL, "pmShutterCorrPars successfully allocated");
+        skip_start(pars == NULL, 0, "Skipping tests because pmShutterCorrParsAlloc() failed");
+
+        // with coarse linearly-spaced times large compared to TO and TK,
+        // we can't expect very accurate guesses.  the exptime guess is fairly good because
+        // the largest exptime is much longer than TK or TO
+        ok(fabs(pars->scale  - AK) < 0.5, "scale guess is close enough (got %f vs %f)",  pars->scale, AK);
+        ok(fabs(pars->offset - TK) < 0.5, "offset guess is close enough (got %f vs %f)", pars->offset, TK);
+        ok(fabs(pars->offref - TO) < 0.5, "offref guess is close enough (got %f vs %f)", pars->offref, TO);
+        skip_end();
+
+        psFree(pars);
+        psFree(exptime);
+        psFree(counts);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test parameter guess (linearly spaced exptimes, TK/TO < 1)
+    diag("pmShutterCorrectionGuess tests : fine linear-spaced exptimes");
+    {
+        psMemId id = psMemGetId();
+
+        int NPTS = 20;
+        float AK = 5.0;
+        float TK = 0.1;
+        float TO = 0.2;
+        psVector *exptime = psVectorAlloc (NPTS, PS_TYPE_F32);
+        psVector *counts  = psVectorAlloc (NPTS, PS_TYPE_F32);
+        exptime->n = counts->n = NPTS;
+
+        for (int i = 0; i < exptime->n; i++) {
+            exptime->data.F32[i] = i*0.1;
+            counts->data.F32[i] = AK*(exptime->data.F32[i] + TK) / (exptime->data.F32[i] + TO);
+        }
+
+        pmShutterCorrection *pars = pmShutterCorrectionGuess (exptime, counts);
+
+        ok(pars != NULL, "pmShutterCorrection successfully allocated");
+        skip_start(pars == NULL, 0, "Skipping tests because pmShutterCorrectionAlloc() failed");
+
+        // with fine linearly-spaced times large compared to TO and TK,
+        // we get a good guess to TK and TO, but since the largest exptime is not
+        // many times larger than TO, we don't do very well with the AK
+        ok(fabs(pars->scale  - AK) < 0.5, "scale guess is close enough (got %f vs %f)",  pars->scale, AK);
+        ok(fabs(pars->offset - TK) < 0.05, "offset guess is close enough (got %f vs %f)", pars->offset, TK);
+        ok(fabs(pars->offref - TO) < 0.05, "offref guess is close enough (got %f vs %f)", pars->offref, TO);
+        skip_end();
+
+        psFree(pars);
+        psFree(exptime);
+        psFree(counts);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test parameter guess (log spaced exptimes, TK/TO < 1)
+    diag("pmShutterCorrectionGuess tests : log-spaced exptimes");
+    {
+        psMemId id = psMemGetId();
+
+        int NPTS = 40;
+        float AK = 5.0;
+        float TK = 0.1;
+        float TO = 0.2;
+        psVector *exptime = psVectorAlloc (NPTS, PS_TYPE_F32);
+        psVector *counts  = psVectorAlloc (NPTS, PS_TYPE_F32);
+        exptime->n = counts->n = NPTS;
+
+        for (int i = 0; i < exptime->n; i++) {
+            exptime->data.F32[i] = pow(10.0, -2 + i*0.1);
+            counts->data.F32[i] = AK*(exptime->data.F32[i] + TK) / (exptime->data.F32[i] + TO);
+        }
+
+        pmShutterCorrection *pars = pmShutterCorrectionGuess (exptime, counts);
+
+        // with fine log-spaced times well-sampling TO and TK,
+        // we can expect accurate guesses
+        ok(pars != NULL, "pmShutterCorrectionsuccessfully allocated");
+        skip_start(pars == NULL, 0, "Skipping tests because pmShutterCorrectionAlloc() failed");
+        ok(fabs(pars->scale  - AK) < 0.01, "scale guess is close enough (got %f vs %f)",  pars->scale, AK);
+        ok(fabs(pars->offset - TK) < 0.01, "offset guess is close enough (got %f vs %f)", pars->offset, TK);
+        ok(fabs(pars->offref - TO) < 0.01, "offref guess is close enough (got %f vs %f)", pars->offref, TO);
+        skip_end();
+
+        psFree(pars);
+        psFree(exptime);
+        psFree(counts);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // test parameter guess (linearly spaced exptimes, TK/TO > 1)
+    diag("pmShutterCorrectionGuess tests : coarse linear-spaced exptimes, TK/TO > 1");
+    {
+        psMemId id = psMemGetId();
+
+        int NPTS = 10;
+        float AK = 5.0;
+        float TK = 0.2;
+        float TO = 0.1;
+        psVector *exptime = psVectorAlloc (NPTS, PS_TYPE_F32);
+        psVector *counts  = psVectorAlloc (NPTS, PS_TYPE_F32);
+        exptime->n = counts->n = NPTS;
+
+        for (int i = 0; i < exptime->n; i++) {
+            exptime->data.F32[i] = i*0.25;
+            counts->data.F32[i] = AK*(exptime->data.F32[i] + TK) / (exptime->data.F32[i] + TO);
+        }
+
+        pmShutterCorrection *pars = pmShutterCorrectionGuess (exptime, counts);
+
+        ok(pars != NULL, "pmShutterCorrection successfully allocated");
+        skip_start(pars == NULL, 0, "Skipping tests because pmShutterCorrectionAlloc() failed");
+
+        // with coarse linearly-spaced times large compared to TO and TK,
+        // we can't expect very accurate guesses.  the exptime guess is fairly good because
+        // the largest exptime is much longer than TK or TO
+        ok(fabs(pars->scale  - AK) < 0.5, "scale guess is close enough (got %f vs %f)",  pars->scale, AK);
+        ok(fabs(pars->offset - TK) < 0.5, "offset guess is close enough (got %f vs %f)", pars->offset, TK);
+        ok(fabs(pars->offref - TO) < 0.5, "offref guess is close enough (got %f vs %f)", pars->offref, TO);
+        skip_end();
+
+        psFree(pars);
+        psFree(exptime);
+        psFree(counts);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test parameter guess (linearly spaced exptimes, TK/TO > 1)
+    diag("pmShutterCorrectionGuess tests : fine linear-spaced exptimes, TK/TO > 1");
+    {
+        psMemId id = psMemGetId();
+
+        int NPTS = 20;
+        float AK = 5.0;
+        float TK = 0.2;
+        float TO = 0.1;
+        psVector *exptime = psVectorAlloc (NPTS, PS_TYPE_F32);
+        psVector *counts  = psVectorAlloc (NPTS, PS_TYPE_F32);
+        exptime->n = counts->n = NPTS;
+
+        for (int i = 0; i < exptime->n; i++) {
+            exptime->data.F32[i] = i*0.1;
+            counts->data.F32[i] = AK*(exptime->data.F32[i] + TK) / (exptime->data.F32[i] + TO);
+        }
+
+        pmShutterCorrection *pars = pmShutterCorrectionGuess (exptime, counts);
+
+        ok(pars != NULL, "pmShutterCorrection successfully allocated");
+        skip_start(pars == NULL, 0, "Skipping tests because pmShutterCorrectionsAlloc() failed");
+
+        // with fine linearly-spaced times large compared to TO and TK,
+        // we get a good guess to TK and TO, but since the largest exptime is not
+        // many times larger than TO, we don't do very well with the AK
+        ok(fabs(pars->scale  - AK) < 0.5, "scale guess is close enough (got %f vs %f)",  pars->scale, AK);
+        ok(fabs(pars->offset - TK) < 0.05, "offset guess is close enough (got %f vs %f)", pars->offset, TK);
+        ok(fabs(pars->offref - TO) < 0.05, "offref guess is close enough (got %f vs %f)", pars->offref, TO);
+        skip_end();
+
+        psFree(pars);
+        psFree(exptime);
+        psFree(counts);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test parameter guess (log spaced exptimes, TK/TO > 1)
+    diag("pmShutterCorrectionGuess tests : log-spaced exptimes, TK/TO > 1");
+    {
+        psMemId id = psMemGetId();
+
+        int NPTS = 40;
+        float AK = 5.0;
+        float TK = 0.2;
+        float TO = 0.1;
+        psVector *exptime = psVectorAlloc (NPTS, PS_TYPE_F32);
+        psVector *counts  = psVectorAlloc (NPTS, PS_TYPE_F32);
+        exptime->n = counts->n = NPTS;
+
+        for (int i = 0; i < exptime->n; i++) {
+            exptime->data.F32[i] = pow(10.0, -2 + i*0.1);
+            counts->data.F32[i] = AK*(exptime->data.F32[i] + TK) / (exptime->data.F32[i] + TO);
+        }
+
+        pmShutterCorrection *pars = pmShutterCorrectionGuess (exptime, counts);
+
+        // with fine log-spaced times well-sampling TO and TK,
+        // we can expect accurate guesses
+        ok(pars != NULL, "pmShutterCorrection successfully allocated");
+        skip_start(pars == NULL, 0, "Skipping tests because pmShutterCorrectionAlloc() failed");
+        ok(fabs(pars->scale  - AK) < 0.01, "scale guess is close enough (got %f vs %f)",  pars->scale, AK);
+        ok(fabs(pars->offset - TK) < 0.01, "offset guess is close enough (got %f vs %f)", pars->offset, TK);
+        ok(fabs(pars->offref - TO) < 0.01, "offref guess is close enough (got %f vs %f)", pars->offref, TO);
+        skip_end();
+
+        psFree(pars);
+        psFree(exptime);
+        psFree(counts);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test non-linear fitting
+    diag("pmShutterCorrectionFullFit tests : linear-spaced exptimes");
+    {
+        psMemId id = psMemGetId();
+
+        int NPTS = 20;
+        float FL = 10000.0;
+        float AK = 5.0;
+        float TK = 0.2;
+        float TO = 0.1;
+        psVector *exptime = psVectorAlloc (NPTS, PS_TYPE_F32);
+        psVector *counts  = psVectorAlloc (NPTS, PS_TYPE_F32);
+        psVector *cntErr  = psVectorAlloc (NPTS, PS_TYPE_F32);
+        exptime->n = counts->n = cntErr->n = NPTS;
+
+        for (int i = 0; i < exptime->n; i++) {
+            exptime->data.F32[i] = i*0.1;
+            counts->data.F32[i] = AK*(exptime->data.F32[i] + TK) / (exptime->data.F32[i] + TO);
+            cntErr->data.F32[i] = AK*sqrt(FL*(exptime->data.F32[i] + TK)) / (exptime->data.F32[i] + TO);
+        }
+
+        pmShutterCorrection *guess = pmShutterCorrectionGuess (exptime, counts);
+        skip_start(guess == NULL, 0, "Skipping tests because pmShutterCorrectionGuess() failed");
+        pmShutterCorrection *pars = pmShutterCorrectionFullFit (exptime, counts, cntErr, guess);
+
+        // with fine log-spaced times well-sampling TO and TK,
+        // we can expect accurate guesses
+        ok(pars != NULL, "pmShutterCorrection successfully allocated by FullFit");
+        skip_start(pars == NULL, 0, "Skipping tests because pmShutterCorrectionsAlloc() failed");
+        ok(fabs(pars->scale  - AK) < 0.01, "scale fit is close enough (got %f vs %f)",  pars->scale, AK);
+        ok(fabs(pars->offset - TK) < 0.01, "offset fit is close enough (got %f vs %f)", pars->offset, TK);
+        ok(fabs(pars->offref - TO) < 0.01, "offref fit is close enough (got %f vs %f)", pars->offref, TO);
+        skip_end();
+
+        psFree(pars);
+        skip_end();
+
+        psFree(guess);
+        psFree(exptime);
+        psFree(counts);
+        psFree(cntErr);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test non-linear fitting
+    diag("pmShutterCorrectionFullFit tests : log-spaced exptimes");
+    {
+        psMemId id = psMemGetId();
+
+        int NPTS = 40;
+        float FL = 10000.0;
+        float AK = 1.0;
+        float TK = 0.2;
+        float TO = 0.1;
+        psVector *exptime = psVectorAlloc (NPTS, PS_TYPE_F32);
+        psVector *counts  = psVectorAlloc (NPTS, PS_TYPE_F32);
+        psVector *cntErr  = psVectorAlloc (NPTS, PS_TYPE_F32);
+        exptime->n = counts->n = cntErr->n = NPTS;
+
+        for (int i = 0; i < exptime->n; i++) {
+            exptime->data.F32[i] = pow(10.0, -2 + i*0.1);
+            counts->data.F32[i] = AK*(exptime->data.F32[i] + TK) / (exptime->data.F32[i] + TO);
+            cntErr->data.F32[i] = AK*sqrt(FL*(exptime->data.F32[i] + TK)) / (exptime->data.F32[i] + TO);
+        }
+
+        pmShutterCorrection*guess = pmShutterCorrectionGuess (exptime, counts);
+        skip_start(guess == NULL, 0, "Skipping tests because pmShutterCorrectionGuess() failed");
+        pmShutterCorrection *pars = pmShutterCorrectionFullFit (exptime, counts, cntErr, guess);
+
+        // with fine log-spaced times well-sampling TO and TK,
+        // we can expect accurate guesses
+        ok(pars != NULL, "pmShutterCorrection successfully allocated by FullFit");
+        skip_start(pars == NULL, 0, "Skipping tests because pmShutterCorrectionAlloc() failed");
+        ok(fabs(pars->scale  - AK) < 0.01, "scale fit is close enough (got %f vs %f)",  pars->scale, AK);
+        ok(fabs(pars->offset - TK) < 0.01, "offset fit is close enough (got %f vs %f)", pars->offset, TK);
+        ok(fabs(pars->offref - TO) < 0.01, "offref fit is close enough (got %f vs %f)", pars->offref, TO);
+        skip_end();
+
+        psFree(pars);
+        skip_end();
+
+        psFree(guess);
+        psFree(exptime);
+        psFree(counts);
+        psFree(cntErr);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // XXX should add tests with the input counts scattered with GaussDev...
+
+    // test linear fitting
+    diag("pmShutterCorrectionLinFit tests : linear-spaced exptimes");
+    {
+        psMemId id = psMemGetId();
+
+        int NPTS = 20;
+        float FL = 10000.0;
+        float AK = 5.0;
+        float TK = 0.2;
+        float TO = 0.1;
+        psVector *exptime = psVectorAlloc (NPTS, PS_TYPE_F32);
+        psVector *counts  = psVectorAlloc (NPTS, PS_TYPE_F32);
+        psVector *cntErr  = psVectorAlloc (NPTS, PS_TYPE_F32);
+        exptime->n = counts->n = cntErr->n = NPTS;
+
+        for (int i = 0; i < exptime->n; i++) {
+            exptime->data.F32[i] = i*0.1;
+            counts->data.F32[i] = AK*(exptime->data.F32[i] + TK) / (exptime->data.F32[i] + TO);
+            cntErr->data.F32[i] = AK*sqrt(FL*(exptime->data.F32[i] + TK)) / (exptime->data.F32[i] + TO);
+        }
+
+        pmShutterCorrection*guess = pmShutterCorrectionGuess (exptime, counts);
+        skip_start(guess == NULL, 0, "Skipping tests because pmShutterCorrectionGuess() failed");
+        pmShutterCorrection *full = pmShutterCorrectionFullFit (exptime, counts, cntErr, guess);
+        pmShutterCorrection *pars = pmShutterCorrectionLinFit (exptime, counts, cntErr, NULL, full->offref, 1, 5, 0);
+
+        // with fine log-spaced times well-sampling TO and TK,
+        // we can expect accurate guesses
+        ok(pars != NULL, "pmShutterCorrection successfully allocated by FullFit");
+        skip_start(pars == NULL, 0, "Skipping tests because pmShutterCorrectionAlloc() failed");
+        ok(fabs(pars->scale  - AK) < 0.01, "scale fit is close enough (got %f vs %f)",  pars->scale, AK);
+        ok(fabs(pars->offset - TK) < 0.01, "offset fit is close enough (got %f vs %f)", pars->offset, TK);
+        ok(fabs(pars->offref - TO) < 0.01, "offref fit is close enough (got %f vs %f)", pars->offref, TO);
+        skip_end();
+
+        psFree(pars);
+        psFree(full);
+        skip_end();
+
+        psFree(guess);
+        psFree(exptime);
+        psFree(counts);
+        psFree(cntErr);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test linear fitting
+    diag("pmShutterCorrectionLinFit tests : log-spaced exptimes");
+    {
+        psMemId id = psMemGetId();
+
+        int NPTS = 40;
+        float FL = 10000.0;
+        float AK = 1.0;
+        float TK = 0.2;
+        float TO = 0.1;
+        psVector *exptime = psVectorAlloc (NPTS, PS_TYPE_F32);
+        psVector *counts  = psVectorAlloc (NPTS, PS_TYPE_F32);
+        psVector *cntErr  = psVectorAlloc (NPTS, PS_TYPE_F32);
+        exptime->n = counts->n = cntErr->n = NPTS;
+
+        for (int i = 0; i < exptime->n; i++) {
+            exptime->data.F32[i] = pow(10.0, -2 + i*0.1);
+            counts->data.F32[i] = AK*(exptime->data.F32[i] + TK) / (exptime->data.F32[i] + TO);
+            cntErr->data.F32[i] = AK*sqrt(FL*(exptime->data.F32[i] + TK)) / (exptime->data.F32[i] + TO);
+        }
+
+        pmShutterCorrection *guess = pmShutterCorrectionGuess (exptime, counts);
+        skip_start(guess == NULL, 0, "Skipping tests because pmShutterCorrectionGuess() failed");
+        pmShutterCorrection *full = pmShutterCorrectionFullFit (exptime, counts, cntErr, guess);
+        pmShutterCorrection *pars = pmShutterCorrectionLinFit (exptime, counts, cntErr, NULL, full->offref, 1, 5, 0);
+
+        // with fine log-spaced times well-sampling TO and TK,
+        // we can expect accurate guesses
+        ok(pars != NULL, "pmShutterCorrection successfully allocated by FullFit");
+        skip_start(pars == NULL, 0, "Skipping tests because pmShutterCorrectionAlloc() failed");
+        ok(fabs(pars->scale  - AK) < 0.01, "scale fit is close enough (got %f vs %f)",  pars->scale, AK);
+        ok(fabs(pars->offset - TK) < 0.01, "offset fit is close enough (got %f vs %f)", pars->offset, TK);
+        ok(fabs(pars->offref - TO) < 0.01, "offref fit is close enough (got %f vs %f)", pars->offref, TO);
+        skip_end();
+
+        psFree(pars);
+        psFree(full);
+        skip_end();
+
+        psFree(guess);
+        psFree(exptime);
+        psFree(counts);
+        psFree(cntErr);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    return exit_status();
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tst_pmFlatField.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tst_pmFlatField.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tst_pmFlatField.c	(revision 22158)
@@ -0,0 +1,290 @@
+/** @file tst_pmFlatField.c
+ *
+ *  @brief Contains the tests for pmFlatField.c:
+ *
+ *    Test A - Divide input image by flat image
+ *    Test B - Mask flat image data
+ *    Test C - Mask flat image data starting with non-null mask
+ *    Test E - Attempt to use null input image
+ *    Test F - Attempt tp use null flat image
+ *    Test G - Attempt to use input image bigger than flat image
+ *    Test H - Attempt to use input image mask bigger than flat image
+ *    Test I - Attempt to use offset greater than input image
+ *    Test J - Attempt to use complex input image
+ *    Test K - Attempt to use complex flat image
+ *    Test L - Attempt to use non-equal input and flat image types
+ *    Test M - Attempt to use non-mask type mask image
+ *
+ * XXX: Added a mask argument to pmFlatField().  Must add tests.  For now, all
+ * masks are NULL.
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  XXX: I added the CELL.TRIMSEC region code but there are not tests for it.
+ *
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-11-15 20:09:03 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+
+#include "psTest.h"
+#include "pslib.h"
+#include "pmFlatField.h"
+
+
+#define PRINT_MATRIX(IMAGE,TYPE,STRING)                                                                      \
+printf(STRING);                                                                                              \
+printf("\n");                                                                                                \
+for(int i=IMAGE->numRows-1; i>-1; i--) {                                                                     \
+    for(int j=0; j<IMAGE->numCols; j++) {                                                                    \
+        if(PS_IS_PSELEMTYPE_COMPLEX(IMAGE->type.type)) {                                                     \
+            printf("%f+%fi ", creal(IMAGE->data.TYPE[i][j]), cimag(IMAGE->data.TYPE[i][j]));                 \
+        } else if(PS_IS_PSELEMTYPE_INT(IMAGE->type.type)) {                                                  \
+            printf("%d ", (int)IMAGE->data.TYPE[i][j]);                                                      \
+        } else {                                                                                             \
+            printf("%f ", (double)IMAGE->data.TYPE[i][j]);                                                   \
+        }                                                                                                    \
+    }                                                                                                        \
+    printf("\n");                                                                                            \
+}                                                                                                            \
+printf("\n");
+
+
+#define CREATE_AND_SET_IMAGE(NAME,TYPE,VALUE,NROWS,NCOLS)                                                    \
+psImage *NAME = (psImage*)psImageAlloc(NCOLS,NROWS,PS_TYPE_##TYPE);                                          \
+for(int i=0; i<NAME->numRows; i++) {                                                                         \
+    for(int j=0; j<NAME->numCols; j++) {                                                                     \
+        NAME->data.TYPE[i][j] = VALUE;                                                                       \
+    }                                                                                                        \
+}
+
+
+static int testFlatField(void);
+
+
+testDescription tests[] = {
+                              {testFlatField, 753, "pmFlatField", 0, false},
+                              {NULL}
+                          };
+
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    return !runTestSuite(stderr, "Test Point Driver", tests, argc, argv);
+}
+
+
+int testFlatField( void )
+{
+    // Test A - Divide input image by flat image
+    printPositiveTestHeader(stdout, "pmFlatField", "Test A - Divide input image by flat image");
+    CREATE_AND_SET_IMAGE(inImage,F64,6.0,3,3)
+    pmReadout *inReadout = pmReadoutAlloc(NULL);
+    inReadout->image = inImage;
+    inReadout->row0 = 0;
+    inReadout->col0 = 0;
+    CREATE_AND_SET_IMAGE(inMask, U8, 0, 3,3);
+    inReadout->mask = inMask;
+    PRINT_MATRIX((inReadout->mask),U8,"Input mask:");
+    PRINT_MATRIX(inImage,F64,"Input image:");
+
+    CREATE_AND_SET_IMAGE(flatImage1,F64,2.0,3,3)
+    pmReadout *flatReadout = pmReadoutAlloc(NULL);
+    flatReadout->row0 = 0;
+    flatReadout->col0 = 0;
+    flatReadout->image = flatImage1;
+    PRINT_MATRIX(flatImage1,F64,"Flat image:");
+
+    if ( !pmFlatField(inReadout, flatReadout) ) {
+        psError(PS_ERR_UNKNOWN,true,"Test A - Returned false should be true");
+        return 1;
+    }
+    PRINT_MATRIX(inImage,F64, "Resulting image:");
+    printFooter(stdout, "pmFlatField", "Test A - Divide input image by flat image", true);
+    printf("\n\n\n");
+
+
+    // Test B - Mask flat image data
+    printPositiveTestHeader(stdout, "pmFlatField", "Test B - Mask flat image data");
+    PRINT_MATRIX(inImage, F64, "Input image:");
+    CREATE_AND_SET_IMAGE(flatImage2,F64,0.0,3,3)
+    PRINT_MATRIX(flatImage2, F64, "Flat image:");
+    flatReadout->image = flatImage2;
+    if ( !pmFlatField(inReadout, flatReadout) ) {
+        psError(PS_ERR_UNKNOWN,true,"Test B - Returned false should be true");
+        return 2;
+    }
+    PRINT_MATRIX(inReadout->mask, PS_TYPE_MASK_DATA, "Resulting mask:");
+    PRINT_MATRIX(inImage,F64,"Resulting image:");
+    printFooter(stdout, "pmFlatField", "Test B - Mask flat image data", true);
+    printf("\n\n\n");
+
+
+    // Test C - Mask flat image data starting with non-null mask
+    printPositiveTestHeader(stdout, "pmFlatField", "Test C - Mask flat image data starting with non-null mask");
+    PRINT_MATRIX(inImage, F64, "Input image:");
+    flatImage2->data.F64[0][0] = 3.0;
+    flatImage2->data.F64[0][1] = -3.0;
+    PRINT_MATRIX(flatImage2, F64, "Flat image:");
+    CREATE_AND_SET_IMAGE(mask1,U8,0,3,3);
+    psFree(inReadout->mask);
+    inReadout->mask = mask1;
+    if ( !pmFlatField(inReadout, flatReadout) ) {
+        psError(PS_ERR_UNKNOWN,true,"Test C - Returned false should be true");
+        return 3;
+    }
+    PRINT_MATRIX(flatImage2, F64, "Flat image out:");
+    PRINT_MATRIX(inReadout->mask, PS_TYPE_MASK_DATA,"Resulting mask:");
+    PRINT_MATRIX(inImage,F64,"Resulting image:");
+    printFooter(stdout, "pmFlatField", "Test C - Mask flat image data starting with non-null mask", true);
+    printf("\n\n\n");
+
+
+    // Test D - Attempt to use null flat readout
+    printNegativeTestHeader(stdout,"pmFlatField", "Test D - Attempt to use null flat readout",
+                            "Null not allowed for flat readout", 0);
+    if( pmFlatField(inReadout, NULL) ) {
+        psError(PS_ERR_UNKNOWN,true,"Test D - Returned true should be false");
+        return 4;
+    }
+    printFooter(stdout, "pmFlatField", "Test D - Attempt to use null flat readout", true);
+    printf("\n\n\n");
+
+
+    // Test E - Attempt to use null input image
+    printNegativeTestHeader(stdout,"pmFlatField", "Test E - Attempt to use null input image",
+                            "Null not allowed for input image", 0);
+    psImage *temp = inReadout->image;
+    inReadout->image = NULL;
+    if ( pmFlatField(inReadout, flatReadout) ) {
+        psError(PS_ERR_UNKNOWN,true,"Test E - Returned true should be false" );
+        return 5;
+    }
+    inReadout->image = temp    ;
+    printFooter(stdout, "pmFlatField", "Test E - Attempt to use null input image", true);
+    printf("\n\n\n");
+
+
+    // Test F - Attempt tp use null flat image
+    printNegativeTestHeader(stdout,"pmFlatField", "Test F - Attempt tp use null flat image",
+                            "Null not allowed for flat image", 0);
+    temp = flatReadout->image;
+    flatReadout->image = NULL;
+    if ( pmFlatField(inReadout, flatReadout) ) {
+        psError(PS_ERR_UNKNOWN,true,"Test F - Returned true should be false" );
+        return 6;
+    }
+    flatReadout->image = temp;
+    printFooter(stdout, "pmFlatField", "Test F - Attempt tp use null flat image", true);
+    printf("\n\n\n");
+
+
+    // Test G - Attempt to use input image bigger than flat image
+    printNegativeTestHeader(stdout,"pmFlatField", "Test G - Attempt to use input image bigger than flat image",
+                            "Input image size exceeds that of flat image", 0);
+    CREATE_AND_SET_IMAGE(smallFlat,F64,0.0,2,2);
+    temp = flatReadout->image;
+    flatReadout->image = smallFlat;
+    if ( pmFlatField(inReadout, flatReadout) ) {
+        psError(PS_ERR_UNKNOWN,true,"Test G - Returned true should be false");
+        return 7;
+    }
+    flatReadout->image = temp;
+    printFooter(stdout, "pmFlatField", "Test G - Attempt to use input image bigger than flat image", true);
+    printf("\n\n\n");
+
+    // Test H - Attempt to use input image mask bigger than flat image
+    printNegativeTestHeader(stdout,"pmFlatField", "Test H - Attempt to use input image mask bigger than flat image",
+                            "Input image mask size exceeds that of flat image", 0);
+    CREATE_AND_SET_IMAGE(largeMask,F64,0.0,5,5);
+    inReadout->mask = largeMask;
+    if ( pmFlatField(inReadout, flatReadout) ) {
+        psError(PS_ERR_UNKNOWN,true,"Test H - Returned true should be false");
+        return 8;
+    }
+    printFooter(stdout, "pmFlatField", "Test H - Attempt to use input image mask bigger than flat image", true);
+    printf("\n\n\n");
+    inReadout->mask = mask1;
+
+    // Test I - Attempt to use offset greater than input image
+    printNegativeTestHeader(stdout,"pmFlatField", "Test I - Attempt to use offset greater than input image",
+                            "Total offset >= input image size", 0);
+    *(int*)&inReadout->col0 = 50;
+    *(int*)&inReadout->row0 = 50;
+    if ( pmFlatField(inReadout, flatReadout) ) {
+        psError(PS_ERR_UNKNOWN,true,"Test I - Returned true should be false");
+        return 9;
+    }
+    *(int*)&inReadout->col0 = 0;
+    *(int*)&inReadout->row0 = 0;
+    printFooter(stdout, "pmFlatField", "Test I - Attempt to use offset greater than input image", true);
+    printf("\n\n\n");
+
+
+    // Test J - Attempt to use complex input image
+    printNegativeTestHeader(stdout,"pmFlatField", "Test J - Attempt to use complex input image",
+                            "Complex types not allowed for input image", 0);
+    *(psElemType* ) & inReadout->image->type.type = PS_TYPE_C64;
+    if ( pmFlatField(inReadout, flatReadout) ) {
+        psError(PS_ERR_UNKNOWN,true,"Test J - Returned true should be false");
+        return 10;
+    }
+    *(psElemType* ) & inReadout->image->type.type = PS_TYPE_F64;
+    printFooter(stdout, "pmFlatField", "Test J - Attempt to use complex input image", true);
+    printf("\n\n\n");
+
+
+    // Test K - Attempt to use complex flat image
+    printNegativeTestHeader(stdout,"pmFlatField", "Test K - Attempt to use complex flat image",
+                            "Complex types not allowed for flat image", 0);
+    *(psElemType* ) & flatReadout->image->type.type = PS_TYPE_C64;
+    if ( pmFlatField(inReadout, flatReadout) ) {
+        psError(PS_ERR_UNKNOWN,true,"Test K - Returned ture should be false");
+        return 11;
+    }
+    *(psElemType* ) & flatReadout->image->type.type = PS_TYPE_F64;
+    printFooter(stdout, "pmFlatField", "Test K - Attempt to use complex flat image", true);
+    printf("\n\n\n");
+
+
+    // Test L - Attempt to use non-equal input and flat image types
+    printNegativeTestHeader(stdout,"pmFlatField", "Test L - Attempt to use non-equal input and flat image types",
+                            "Input and flat image types differ", 0);
+    *(psElemType* ) & flatReadout->image->type.type = PS_TYPE_F32;
+    if ( pmFlatField(inReadout, flatReadout) ) {
+        psError(PS_ERR_UNKNOWN,true,"Test L - Returned true should be false");
+        return 12;
+    }
+    *(psElemType* ) & flatReadout->image->type.type = PS_TYPE_F64;
+    printFooter(stdout, "pmFlatField", "Test L - Attempt to use non-equal input and flat image types", true);
+    printf("\n\n\n");
+
+
+    // Test M - Attempt to use non-mask type mask image
+    printNegativeTestHeader(stdout,"pmFlatField", "Test M - Attempt to use non-mask type mask image",
+                            "Mask must be PS_TYPE_MASK type", 0);
+    *(psElemType* ) & inReadout->mask->type.type = PS_TYPE_F32;
+    if ( pmFlatField(inReadout, flatReadout) ) {
+        psError(PS_ERR_UNKNOWN,true,"Test M - Returned true should be false");
+        return 13;
+    }
+    *(psElemType* ) & inReadout->mask->type.type = PS_TYPE_MASK;
+    printFooter(stdout, "pmFlatField", "Test M - Attempt to use non-mask type mask image", true);
+    printf("\n\n\n");
+
+
+    // Free memory
+    psFree(inReadout);
+    psFree(flatReadout);
+    //psFree(inImage);
+    psFree(flatImage1);
+    //psFree(flatImage1);
+    psFree(smallFlat);
+    psFree(largeMask);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tst_pmMaskBadPixels.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tst_pmMaskBadPixels.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tst_pmMaskBadPixels.c	(revision 22158)
@@ -0,0 +1,381 @@
+/** @file tst_pmMaskBadPixels.c
+ *
+ *  @brief Contains the tests for pmMaskBadPixels:
+ *
+ *    Test A - Create mask based on maskVal argument
+ *    Test B - Create mask based on saturation argument
+ *    Test C - Create mask based on growVal and grow arguments
+ *    Test D - Auto Create mask based on maskVal argument
+ *    Test E - Attempt to use null mask
+ *    Test F - Attempt tp use null input image
+ *    Test G - Attempt to use input image bigger than mask
+ *    Test H - Attempt to use input image mask bigger than mask
+ *    Test I - Attempt to use offset greater than input image
+ *    Test J - Attempt to use complex input image
+ *    Test K - Attempt to use non-mask type mask image
+ *
+ *  @author Ross Harman, MHPCC
+ *
+ *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-11-15 20:09:03 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+
+#include "psTest.h"
+#include "pslib.h"
+#include "pmMaskBadPixels.h"
+
+
+#define PRINT_MATRIX(IMAGE,TYPE,STRING)                                                                      \
+printf(STRING);                                                                                              \
+printf("\n");                                                                                                \
+for(int i=(IMAGE)->numRows-1; i>-1; i--) {                                                                     \
+    for(int j=0; j<(IMAGE)->numCols; j++) {                                                                    \
+        if(PS_IS_PSELEMTYPE_COMPLEX((IMAGE)->type.type)) {                                                     \
+            printf("%f+%fi ", creal((IMAGE)->data.TYPE[i][j]), cimag((IMAGE)->data.TYPE[i][j]));                 \
+        } else if(PS_IS_PSELEMTYPE_INT((IMAGE)->type.type)) {                                                  \
+            printf("%d", (int)(IMAGE)->data.TYPE[i][j]);                                                       \
+        } else {                                                                                             \
+            printf("%f", (double)(IMAGE)->data.TYPE[i][j]);                                                    \
+        }                                                                                                    \
+    }                                                                                                        \
+    printf("\n");                                                                                            \
+}                                                                                                            \
+printf("\n");
+
+
+#define CREATE_AND_SET_IMAGE(NAME,TYPE,VALUE,NROWS,NCOLS)                                                    \
+(NAME) = (psImage*)psImageAlloc(NCOLS,NROWS,PS_TYPE_##TYPE);                                             \
+for(int i=0; i<(NAME)->numRows; i++) {                                                                         \
+    for(int j=0; j<(NAME)->numCols; j++) {                                                                     \
+        (NAME)->data.TYPE[i][j] = VALUE;                                                                       \
+    }                                                                                                        \
+}
+
+static int testMaskBadPixels1(void);
+static int testMaskBadPixels2(void);
+static int testMaskBadPixels3(void);
+static int testMaskBadPixels4(void);
+static int testMaskBadPixels5(void);
+static int testMaskBadPixels6(void);
+static int testMaskBadPixels7(void);
+static int testMaskBadPixels8(void);
+static int testMaskBadPixels9(void);
+static int testMaskBadPixels10(void);
+static int testMaskBadPixels11(void);
+
+
+testDescription tests[] = {
+                              {testMaskBadPixels1, 885, "pmMaskBadPixels - Create mask based on maskVal argument", 0, false},
+                              {testMaskBadPixels2, 885, "pmMaskBadPixels - Create mask based on saturation argument", 0, false},
+                              {testMaskBadPixels3, 885, "pmMaskBadPixels - Create mask based on growVal and grow arguments", 0, false},
+                              {testMaskBadPixels4, 885, "pmMaskBadPixels - Auto create mask based on maskVal argument", 0, false},
+                              {testMaskBadPixels5, 885, "pmMaskBadPixels - Attempt to use null mask", 0, false},
+                              {testMaskBadPixels6, 885, "pmMaskBadPixels - Attempt tp use null input image", 0, false},
+                              {testMaskBadPixels7, 885, "pmMaskBadPixels - Attempt to use input image bigger than mask", 0, false},
+                              {testMaskBadPixels8, 885, "pmMaskBadPixels - Attempt to use input image mask bigger than mask", 0, false},
+                              {testMaskBadPixels9, 885, "pmMaskBadPixels - Attempt to use offset greater than input image", 0, false},
+                              {testMaskBadPixels10, 885, "pmMaskBadPixels - Attempt to use complex input image", 0, false},
+                              {testMaskBadPixels11, 885, "pmMaskBadPixels - Attempt to use non-mask type mask image", 0, false        },
+                              {NULL}
+                          };
+
+/*
+    #define PS_TYPE_MASK PS_TYPE_U8
+    #define PS_TYPE_MASK_DATA U8
+    #define PS_TYPE_MASK_NAME "psU8"
+*/
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    return !runTestSuite(stderr, "Test Point Driver", tests, argc, argv);
+}
+
+
+#define NUM_ROWS 50
+#define NUM_COLS 50
+#define DEFAULT_IMAGE_VAL 0.0
+#define DEFAULT_MASK_VAL 0
+#define MASK_VAL 1
+#define SAT_VAL  100.0
+#define GROW_VAL 1
+#define GROW_RAD 10
+int testMaskBadPixels1( void )
+{
+    //
+    // Test A - Create mask based on maskVal argument
+    //
+
+    pmReadout *inReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(inReadout->image, F32, DEFAULT_IMAGE_VAL, NUM_ROWS, NUM_COLS);
+    inReadout->image->row0 = 0;
+    inReadout->image->col0 = 0;
+    inReadout->row0 = 0;
+    inReadout->col0 = 0;
+
+    pmReadout *maskReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(maskReadout->image, U8, DEFAULT_MASK_VAL, NUM_ROWS, NUM_COLS)
+    maskReadout->image->data.PS_TYPE_MASK_DATA[NUM_ROWS/2][NUM_COLS/2]=1;
+    maskReadout->image->row0 = 0;
+    maskReadout->image->col0 = 0;
+
+    PRINT_MATRIX(maskReadout->image, U8, "Data mask:");
+
+    pmMaskBadPixels(inReadout, maskReadout, MASK_VAL, SAT_VAL, GROW_VAL, GROW_RAD);
+    PRINT_MATRIX(inReadout->mask, PS_TYPE_MASK_DATA, "Resulting mask:");
+
+    psFree(inReadout);
+    psFree(maskReadout);
+
+    return 0;
+}
+
+int testMaskBadPixels2( void )
+{
+    //
+    // Test B - Create mask based on saturation argument
+    //
+
+    pmReadout *inReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(inReadout->image, F32, DEFAULT_IMAGE_VAL, NUM_ROWS, NUM_COLS);
+    inReadout->image->row0 = 0;
+    inReadout->image->col0 = 0;
+    inReadout->row0 = 0;
+    inReadout->col0 = 0;
+    inReadout->image->data.F32[NUM_ROWS/2][NUM_COLS/2] = 150.0;
+
+    pmReadout *maskReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(maskReadout->image, U8, DEFAULT_MASK_VAL, NUM_ROWS, NUM_COLS)
+
+    //PS_IMAGE_PRINT_F32(inReadout->image);
+    PRINT_MATRIX(maskReadout->image, U8, "Data mask:");
+    pmMaskBadPixels(inReadout, maskReadout, MASK_VAL, SAT_VAL, GROW_VAL, GROW_RAD);
+    PRINT_MATRIX(inReadout->mask, U8, "Resulting mask:");
+
+    psFree(inReadout);
+    psFree(maskReadout);
+
+    return 0;
+}
+
+int testMaskBadPixels3( void )
+{
+    //
+    // Test C - Create mask based on growVal and grow arguments
+    //
+
+    pmReadout *inReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(inReadout->image, F32, DEFAULT_IMAGE_VAL, NUM_ROWS, NUM_COLS);
+    inReadout->image->row0 = 0;
+    inReadout->image->col0 = 0;
+    inReadout->row0 = 0;
+    inReadout->col0 = 0;
+    inReadout->image->data.F32[NUM_ROWS/2][NUM_COLS/2]=GROW_VAL;
+    inReadout->image->data.F32[NUM_ROWS/4][NUM_COLS/4]=GROW_VAL;
+    inReadout->image->data.F32[NUM_ROWS/4][NUM_COLS-(NUM_COLS/4)]=GROW_VAL;
+
+    pmReadout *maskReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(maskReadout->image, U8, DEFAULT_MASK_VAL, NUM_ROWS, NUM_COLS);
+
+    PRINT_MATRIX(maskReadout->image, U8, "Data mask:");
+    //PS_IMAGE_PRINT_F32(inReadout->image);
+    pmMaskBadPixels(inReadout, maskReadout, MASK_VAL, SAT_VAL, GROW_VAL, GROW_RAD);
+    PRINT_MATRIX(inReadout->mask, U8, "Resulting mask:");
+
+    psFree(inReadout);
+    psFree(maskReadout);
+
+    return 0;
+}
+
+int testMaskBadPixels4( void )
+{
+    //
+    // Test D - Auto Create mask based on maskVal argument
+    //
+
+    pmReadout *inReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(inReadout->image, F32, DEFAULT_IMAGE_VAL, NUM_ROWS, NUM_COLS);
+    inReadout->image->row0 = 0;
+    inReadout->image->col0 = 0;
+    inReadout->row0 = 0;
+    inReadout->col0 = 0;
+
+    pmReadout *maskReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(maskReadout->image, U8, DEFAULT_MASK_VAL, NUM_ROWS, NUM_COLS)
+    maskReadout->image->data.PS_TYPE_MASK_DATA[NUM_ROWS/2][NUM_COLS/2]=1;
+
+    PRINT_MATRIX(maskReadout->image, U8, "Data mask:");
+    pmMaskBadPixels(inReadout, maskReadout, MASK_VAL, SAT_VAL, GROW_VAL, GROW_RAD);
+    PRINT_MATRIX(inReadout->mask, U8, "Resulting mask:");
+
+    psFree(inReadout);
+    psFree(maskReadout);
+
+    return 0;
+}
+
+int testMaskBadPixels5( void )
+{
+    //
+    // Test E - Attempt to use null mask
+    //
+
+    pmReadout *inReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(inReadout->image, F32, DEFAULT_IMAGE_VAL, NUM_ROWS, NUM_COLS);
+    inReadout->image->row0 = 0;
+    inReadout->image->col0 = 0;
+    inReadout->row0 = 0;
+    inReadout->col0 = 0;
+
+    pmMaskBadPixels(inReadout, NULL, MASK_VAL, SAT_VAL, GROW_VAL, GROW_RAD);
+    psFree(inReadout);
+
+    return 0;
+}
+
+int testMaskBadPixels6( void )
+{
+    //
+    // Test F - Attempt tp use null input image
+    //
+
+    pmReadout *inReadout = pmReadoutAlloc(NULL);
+    inReadout->row0 = 0;
+    inReadout->col0 = 0;
+
+    pmReadout *maskReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(maskReadout->image, U8, DEFAULT_MASK_VAL, NUM_ROWS, NUM_COLS)
+
+    pmMaskBadPixels(inReadout, maskReadout, MASK_VAL, SAT_VAL, GROW_VAL, GROW_RAD);
+
+    psFree(inReadout);
+    psFree(maskReadout);
+
+    return 0;
+}
+
+int testMaskBadPixels7( void )
+{
+    //
+    // Test G - Attempt to use input image bigger than mask
+    //
+
+    pmReadout *inReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(inReadout->image, F32, DEFAULT_IMAGE_VAL, NUM_ROWS+10, NUM_COLS+10);
+    inReadout->image->row0 = 0;
+    inReadout->image->col0 = 0;
+    inReadout->row0 = 0;
+    inReadout->col0 = 0;
+
+    pmReadout *maskReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(maskReadout->image, U8, DEFAULT_MASK_VAL, NUM_ROWS, NUM_COLS)
+
+    pmMaskBadPixels(inReadout, maskReadout, MASK_VAL, SAT_VAL, GROW_VAL, GROW_RAD);
+
+    psFree(inReadout);
+    psFree(maskReadout);
+
+    return 0;
+}
+
+int testMaskBadPixels8( void )
+{
+    //
+    // Test H - Attempt to use mask bigger than image
+    //
+
+    pmReadout *inReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(inReadout->image, F32, DEFAULT_IMAGE_VAL, NUM_ROWS, NUM_COLS);
+    inReadout->image->row0 = 0;
+    inReadout->image->col0 = 0;
+    inReadout->row0 = 0;
+    inReadout->col0 = 0;
+
+    pmReadout *maskReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(maskReadout->image, U8, DEFAULT_MASK_VAL, NUM_ROWS+10, NUM_COLS+10)
+
+    pmMaskBadPixels(inReadout, maskReadout, MASK_VAL, SAT_VAL, GROW_VAL, GROW_RAD);
+
+    psFree(inReadout);
+    psFree(maskReadout);
+
+    return 0;
+}
+
+int testMaskBadPixels9( void )
+{
+    //
+    // Test I - Attempt to use offset greater than input image
+    //
+
+    pmReadout *inReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(inReadout->image, F32, DEFAULT_IMAGE_VAL, NUM_ROWS, NUM_COLS);
+    inReadout->image->row0 = 0;
+    inReadout->image->col0 = 0;
+    inReadout->row0 = 0;
+    inReadout->col0 = 0;
+    *(int*)&inReadout->image->col0 = 150;
+    *(int*)&inReadout->image->row0 = 150;
+
+    pmReadout *maskReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(maskReadout->image, U8, DEFAULT_MASK_VAL, NUM_ROWS, NUM_COLS)
+    pmMaskBadPixels(inReadout, maskReadout, MASK_VAL, SAT_VAL, GROW_VAL, GROW_RAD);
+
+    psFree(inReadout);
+    psFree(maskReadout);
+
+    return 0;
+}
+
+int testMaskBadPixels10( void )
+{
+    //
+    // Test J - Attempt to use complex input image
+    //
+
+    pmReadout *inReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(inReadout->image, C64, DEFAULT_IMAGE_VAL, NUM_ROWS, NUM_COLS);
+    inReadout->image->row0 = 0;
+    inReadout->image->col0 = 0;
+    inReadout->row0 = 0;
+    inReadout->col0 = 0;
+
+    pmReadout *maskReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(maskReadout->image, U8, DEFAULT_MASK_VAL, NUM_ROWS, NUM_COLS)
+
+    pmMaskBadPixels(inReadout, maskReadout, MASK_VAL, SAT_VAL, GROW_VAL, GROW_RAD);
+
+    psFree(inReadout);
+    psFree(maskReadout);
+
+    return 0;
+}
+
+int testMaskBadPixels11( void )
+{
+    //
+    // Test K - Attempt to use mask image with wrong data type.
+    //
+
+    pmReadout *inReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(inReadout->image, F32, DEFAULT_IMAGE_VAL, NUM_ROWS, NUM_COLS);
+    inReadout->image->row0 = 0;
+    inReadout->image->col0 = 0;
+    inReadout->row0 = 0;
+    inReadout->col0 = 0;
+
+    pmReadout *maskReadout = pmReadoutAlloc(NULL);
+    CREATE_AND_SET_IMAGE(maskReadout->image, F64, DEFAULT_MASK_VAL, NUM_ROWS, NUM_COLS)
+
+    pmMaskBadPixels(inReadout, maskReadout, MASK_VAL, SAT_VAL, GROW_VAL, GROW_RAD);
+
+    psFree(inReadout);
+    psFree(maskReadout);
+
+    return 0;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tst_pmNonLinear.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tst_pmNonLinear.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tst_pmNonLinear.c	(revision 22158)
@@ -0,0 +1,268 @@
+/* @file tst_pmNonLinear.c
+ *
+ *  @brief Contains the tests for pmNonLinear.c:
+ *
+ * test00: This code will create a simple polynomial, and call
+ * pmNonLinearityPolynomial() for a variety of image sizes [(1, 1), (1,
+ * N), (N, 1), (N, N)].  
+ *
+ * test01: This code will create simple table lookup vectors, and call
+ * pmNonLinearityPolynomial() for a variety of image sizes [(1, 1), (1,
+ * N), (N, 1), (N, N)].  
+ *
+ * test02, test03: This code tests the functions with various unallowable
+ * input parameters (NULLS) and incorrect vector sizes.
+ *
+ *  @author GLG, MHPCC
+ *
+ *  XXX: Add tests in which the lookup file has incorrect number of entries,
+ *  and where the data is outside the pmReadout range.
+ *
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-01-26 21:10:51 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include "psTest.h"
+#include "pslib.h"
+#include "pmNonLinear.h"
+static int test00(void);
+static int test01(void);
+static int test02(void);
+static int test03(void);
+testDescription tests[] = {
+                              {test00, 000, "pmNonLinearityPolynomial", true, false},
+                              {test01, 000, "pmNonLinearityLookup", true, false},
+                              {test02, 000, "pmNonLinearityPolynomial(): error/warning conditions", true, false},
+                              {test03, 000, "pmNonLinearityLookup(): error/warning conditions", true, false},
+                              {NULL}
+                          };
+
+#define NUM_ROWS 8
+#define NUM_COLS 8
+#define LOOKUP_FILENAME ".tmp_tst_pmNonLinearLookupFile"
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    //
+    // We generate a lookup file for future tests.  We should probably remove
+    // it when we're done.
+    //
+    FILE *fp = fopen(LOOKUP_FILENAME, "w");
+    ;
+    for (psS32 i=0;i<PS_MAX(NUM_COLS, NUM_ROWS)*3;i++) {
+        fprintf(fp, "%f %f\n", (float) i, (float) (2 * i));
+    }
+    fclose(fp);
+
+    //    system("rm LOOKUP_FILENAME");
+    return !runTestSuite(stderr, "Test Point Driver", tests, argc, argv);
+}
+
+int doNonLinearityPolynomialTest(int numCols, int numRows)
+{
+    int i;
+    int j;
+    float actual;
+    float expect;
+    int testStatus = true;
+    psImage *myImage = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    pmReadout *myReadout = pmReadoutAlloc(NULL);
+    myReadout->image = myImage;
+    psPolynomial1D *myPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 2);
+    myPoly->coeff[1] = 1.0;
+
+    printPositiveTestHeader(stdout, "pmNonLinear", "doNonLinearityPolynomialTest");
+
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols;j++) {
+            myReadout->image->data.F32[i][j] = (float) (i + j);
+        }
+    }
+
+    myReadout = pmNonLinearityPolynomial(myReadout, myPoly);
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols;j++) {
+            expect = psPolynomial1DEval(myPoly, (float) (i + j));
+            actual = myReadout->image->data.F32[i][j];
+            if (FLT_EPSILON < fabs(expect - actual)) {
+                printf("TEST ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
+                testStatus = false;
+            }
+        }
+    }
+
+
+    psFree(myReadout);
+    psFree(myPoly);
+    printFooter(stdout, "pmNonLinear", "doNonLinearityPolynomialTest", true);
+    return(testStatus);
+}
+
+int test00( void )
+{
+    int testStatus = 0;
+
+    testStatus |= doNonLinearityPolynomialTest(1, 1);
+    testStatus |= doNonLinearityPolynomialTest(NUM_COLS, 1);
+    testStatus |= doNonLinearityPolynomialTest(1, NUM_ROWS);
+    testStatus |= doNonLinearityPolynomialTest(NUM_COLS, NUM_ROWS);
+
+    return(testStatus);
+}
+
+int doNonLinearityLookupTest(int numCols, int numRows)
+{
+    int i;
+    int j;
+    float actual;
+    float expect;
+    int testStatus = true;
+    psImage *myImage = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    pmReadout *myReadout = pmReadoutAlloc(NULL);
+    myReadout->image = myImage;
+
+    printPositiveTestHeader(stdout, "pmNonLinear", "doNonLinearityLookupTest");
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols;j++) {
+            myReadout->image->data.F32[i][j] = (float) (i + j);
+        }
+    }
+
+    myReadout = pmNonLinearityLookup(myReadout, LOOKUP_FILENAME);
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols;j++) {
+            expect = (float) (2 * (i + j));
+            actual = myReadout->image->data.F32[i][j];
+            if (FLT_EPSILON < fabs(expect - actual)) {
+                printf("TEST ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
+                testStatus = false;
+            }
+        }
+    }
+
+    psFree(myReadout);
+    printFooter(stdout, "pmNonLinear", "doNonLinearityLookupTest", true);
+    return(testStatus);
+}
+
+int test01( void )
+{
+    int testStatus = 0;
+
+    testStatus |= doNonLinearityLookupTest(1, 1);
+    testStatus |= doNonLinearityLookupTest(NUM_COLS, 1);
+    testStatus |= doNonLinearityLookupTest(1, NUM_ROWS);
+    testStatus |= doNonLinearityLookupTest (NUM_COLS, NUM_ROWS);
+
+    return(testStatus);
+}
+
+int test02( void )
+{
+    int i;
+    int j;
+    int testStatus = true;
+    psImage *myImage = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+    pmReadout *myReadout = pmReadoutAlloc(NULL);
+    pmReadout *rc = NULL;
+    myReadout->image = myImage;
+    psPolynomial1D *myPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 2);
+    myPoly->coeff[1] = 1.0;
+
+    printPositiveTestHeader(stdout, "pmNonLinear", "Testing bad input parameter conditions.");
+    for (i=0;i<NUM_ROWS;i++) {
+        for (j=0;j<NUM_COLS;j++) {
+            myReadout->image->data.F32[i][j] = (float) (i + j);
+        }
+    }
+
+    printf("------------------------------------------------------------\n");
+    printf("Calling pmNonLinearityPolynomial() with NULL input readout.  Should generate error, return NULL.\n");
+    rc = pmNonLinearityPolynomial(NULL, myPoly);
+    if (rc != NULL) {
+        printf("TEST ERROR: pmNonLinearityPolynomial() returned a non-NULL pmReadout\n");
+        testStatus = false;
+    }
+
+    printf("------------------------------------------------------------\n");
+    printf("Calling pmNonLinearityPolynomial() with NULL input readout->image.  Should generate error, return NULL.\n");
+    psImage *tmpImage = myReadout->image;
+    myReadout->image = NULL;
+    rc = pmNonLinearityPolynomial(myReadout, myPoly);
+    if (rc != NULL) {
+        printf("TEST ERROR: pmNonLinearityPolynomial() returned a non-NULL pmReadout\n");
+        testStatus = false;
+    }
+    myReadout->image = tmpImage;
+
+    printf("------------------------------------------------------------\n");
+    printf("Calling pmNonLinearityPolynomial() with NULL polynomial.  Should generate error, return NULL.\n");
+    rc = pmNonLinearityPolynomial(myReadout, NULL);
+    if (rc != NULL) {
+        printf("TEST ERROR: pmNonLinearityPolynomial() returned a non-NULL pmReadout\n");
+        testStatus = false;
+    }
+
+    psFree(myReadout);
+    psFree(myPoly);
+    return(testStatus);
+}
+
+
+int test03Init(pmReadout *myReadout)
+{
+    for (psS32 i=0;i<NUM_ROWS;i++) {
+        for (psS32 j=0;j<NUM_COLS;j++) {
+            myReadout->image->data.F32[i][j] = (float) (i + j);
+        }
+    }
+    return(0);
+}
+
+int test03()
+{
+    int testStatus = true;
+    psImage *myImage = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+    pmReadout *myReadout = pmReadoutAlloc(NULL);
+    pmReadout *rc = NULL;
+    myReadout->image = myImage;
+
+    test03Init(myReadout);
+    printf("------------------------------------------------------------\n");
+    printf("Calling pmNonLinearityLookup() with NULL input pmReadout.  Should generate error, return NULL.\n");
+    rc = pmNonLinearityLookup(NULL, LOOKUP_FILENAME);
+    if (rc != NULL) {
+        printf("TEST ERROR: pmNonLinearityPolynomial() returned a non-NULL pmReadout\n");
+        testStatus = false;
+    }
+
+    printf("------------------------------------------------------------\n");
+    printf("Calling pmNonLinearityLookup() with NULL input pmReadout->image.  Should generate error, return NULL.\n");
+    psImage *tmpImage = myReadout->image;
+    myReadout->image = NULL;
+    rc = pmNonLinearityLookup(myReadout, LOOKUP_FILENAME);
+    if (rc != NULL) {
+        printf("TEST ERROR: pmNonLinearityPolynomial() returned a non-NULL pmReadout\n");
+        testStatus = false;
+    }
+    myReadout->image = tmpImage;
+
+    printf("------------------------------------------------------------\n");
+    printf("Calling pmNonLinearityLookup() with non-existent lookup file.\n");
+    rc = pmNonLinearityLookup(myReadout, "I_DONT_EXIST");
+    if (rc == NULL) {
+        printf("TEST ERROR: pmNonLinearityPolynomial() returned a NULL pmReadout\n");
+        testStatus = false;
+    }
+
+
+    printf("------------------------------------------------------------\n");
+    printf("Calling pmNonLinearityLookup() with one pixels outside inFlux range.  Should generate warnings.\n");
+
+    psFree(myReadout);
+
+    printFooter(stdout, "pmNonLinear", "Testing bad input parameter conditions.", true);
+    return(testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tst_pmSubtractBias.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tst_pmSubtractBias.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tst_pmSubtractBias.c	(revision 22158)
@@ -0,0 +1,1129 @@
+/** @file tst_pmSubtractBias.c
+ *
+ *  @brief Contains the tests for pmSubtractBias.c:
+ *
+ * test00a: This code will subtract full bias frames from the input image.
+ * XXX: Must test:
+ *  Various image offsets.
+ *  Various image size combinations.
+ *  Various data types for the bias and input images.
+ *  Ensure code works when CELL.TRIMSEC is not set.
+ * test00b: This code will subtract full dark frames from the input image.
+ * XXX: Must test:
+ *  Various image offsets.
+ *  Various image size combinations.
+ *  Various data types for the bias and input images.
+ *  Code properly determines CELL.DARKTIME from cell metadata.
+ *  Ensure code works when CELL.DARKTIME is not set.
+ *  Ensure code works when CELL.TRIMSEC is not set.
+ *  test03: Calculate a row overscan vector and subtract it from each
+ *  row in the input image.
+ * test05:
+ *
+ *  @author GLG, MHPCC
+ *
+ *  XXX: Memory leaks are not being detected.
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-05-25 22:02:23 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include "psTest.h"
+#include "pslib.h"
+#include "pmSubtractBias.h"
+static int test00a(void);
+static int test00b(void);
+//static int test01(void);
+//static int test02(void);
+//static int test03(void);
+//static int test04(void);
+static int test05(void);
+testDescription tests[] = {
+                              {test00a, 000, "doSubtractBiasFullFrame", 0, true},
+                              {test00b, 000, "doSubtractDarkFullFrame", 0, true},
+                              //                              {test01, 000, "pmSubtractBias", 0, true},
+                              //                              {test02, 000, "pmSubtractBias", 0, true},
+                              //                              {test03, 000, "pmSubtractBias", 0, true},
+                              //                              {test04, 000, "pmSubtractBias", 0, true},
+                              {test05, 000, "pmSubtractBias", 0, false},
+                              {NULL}
+                          };
+
+psS32 currentId = 0;
+psS32 memLeaks = 0;             // XXX: remove
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("spline1DFree", 0);
+    psTraceSetLevel("calculateSecondDerivs", 0);
+    psTraceSetLevel("vectorBinDisectF32", 0);
+    psTraceSetLevel("vectorBinDisectF64", 0);
+    psTraceSetLevel("p_psVectorBinDisect", 0);
+    psTraceSetLevel("psSpline1DAlloc", 0);
+    psTraceSetLevel("psVectorFitSpline1D", 0);
+    psTraceSetLevel("psSpline1DEval", 0);
+    psTraceSetLevel("psSpline1DEvalVector", 0);
+
+    psS32 currentId = psMemGetId(); // XXX: remove
+    psS32 memLeaks = 0;             // XXX: remove
+    if (0) {
+        PRINT_MEMLEAKS(0);
+    }
+
+    return !runTestSuite(stderr, "Test Point Driver", tests, argc, argv);
+}
+
+#define NUM_ROWS 8
+#define NUM_COLS 8
+#define MAX_HEADER_MSG_LENGTH 1000
+#define POLYNOMIAL_FIT_ORDER 2
+#define NUM_OVERSCANS 2
+/******************************************************************************
+doSubtractBiasFullFrame(): a sample pmReadout as well as a bias image are
+created and the bias image is subtracted from the pmReadout.
+ *****************************************************************************/
+int doSubtractBiasFullFrame(int numCols, int numRows)
+{
+    int i;
+    int j;
+    float actual;
+    float expect;
+    int testStatus = 0;
+    psImage *tmpImage1 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    psImage *tmpImage2 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    pmReadout *myReadout = pmReadoutAlloc(NULL);
+    pmReadout *myBias = pmReadoutAlloc(NULL);
+    myReadout->image = tmpImage1;
+    myBias->image = tmpImage2;
+
+    char *HeaderMessageStr = (char *) psAlloc(MAX_HEADER_MSG_LENGTH);
+    sprintf(HeaderMessageStr, "doSubtractBiasFullFrame(%d, %d)", numRows, numCols);
+    printPositiveTestHeader(stdout, "pmSubtractBias", HeaderMessageStr);
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols;j++) {
+            myReadout->image->data.F32[i][j] = (float) (i + j);
+            myBias->image->data.F32[i][j] = 1.0;
+        }
+    }
+
+    myReadout = pmSubtractBias(myReadout, NULL, PM_FIT_NONE, false,
+                               NULL, 0, myBias, NULL);
+
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols;j++) {
+            expect = ((float) (i + j)) - 1.0;
+            actual = myReadout->image->data.F32[i][j];
+            if (FLT_EPSILON < fabs(expect - actual)) {
+                printf("TEST ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
+                testStatus = 1;
+            }
+        }
+    }
+
+
+    psFree(myReadout);
+    psFree(myBias);
+    printFooter(stdout, "pmSubtractBias", HeaderMessageStr, true);
+    psFree(HeaderMessageStr);
+    return(testStatus);
+}
+
+
+int test00a( void )
+{
+    int testStatus = 0;
+
+    testStatus |= doSubtractBiasFullFrame(1, 1);
+    testStatus |= doSubtractBiasFullFrame(NUM_COLS, 1);
+    testStatus |= doSubtractBiasFullFrame(1, NUM_ROWS);
+    testStatus |= doSubtractBiasFullFrame(NUM_COLS, NUM_ROWS);
+    return(testStatus);
+}
+
+
+/******************************************************************************
+doSubtractDarkFullFrame(): a sample pmReadout as well as a dark image are
+created and the dark image is subtracted from the pmReadout.
+ *****************************************************************************/
+int doSubtractDarkFullFrame(int numCols, int numRows)
+{
+    int i;
+    int j;
+    float actual;
+    float expect;
+    int testStatus = 0;
+    psImage *tmpImage1 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    psImage *tmpImage2 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    pmReadout *myReadout = pmReadoutAlloc(NULL);
+    pmReadout *myDark = pmReadoutAlloc(NULL);
+    myReadout->image = tmpImage1;
+    myDark->image = tmpImage2;
+
+    char *HeaderMessageStr = (char *) psAlloc(MAX_HEADER_MSG_LENGTH);
+    sprintf(HeaderMessageStr, "doSubtractDarkFullFrame(%d, %d)", numRows, numCols);
+    printPositiveTestHeader(stdout, "pmSubtractBias", HeaderMessageStr);
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols;j++) {
+            myReadout->image->data.F32[i][j] = (float) (i + j);
+            myDark->image->data.F32[i][j] = 1.0;
+        }
+    }
+
+    myReadout = pmSubtractBias(myReadout, NULL, PM_FIT_NONE, false,
+                               NULL, 0, NULL, myDark);
+
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols;j++) {
+            expect = ((float) (i + j)) - 1.0;
+            actual = myReadout->image->data.F32[i][j];
+            if (FLT_EPSILON < fabs(expect - actual)) {
+                printf("TEST ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
+                testStatus = 1;
+            }
+        }
+    }
+
+
+    psFree(myReadout);
+    psFree(myDark);
+    printFooter(stdout, "pmSubtractBias", HeaderMessageStr, true);
+    psFree(HeaderMessageStr);
+    return(testStatus);
+}
+
+
+int test00b( void )
+{
+    int testStatus = 0;
+
+    testStatus |= doSubtractDarkFullFrame(1, 1);
+    testStatus |= doSubtractDarkFullFrame(NUM_COLS, 1);
+    testStatus |= doSubtractDarkFullFrame(1, NUM_ROWS);
+    testStatus |= doSubtractDarkFullFrame(NUM_COLS, NUM_ROWS);
+    return(testStatus);
+}
+
+
+/*
+int doSubtractOverscansTestInputCases(int numCols, int numRows)
+{
+    int i;
+    int j;
+    int testStatus = 0;
+    psImage *tmpImage1 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    psImage *tmpImage2 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    psImage *tmpImage3 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    psImage *tmpImage4 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    psImage *tmpImage2Short = psImageAlloc(numCols-1, numRows-1, PS_TYPE_F32);
+    psImage *tmpImage3Short = psImageAlloc(numCols-1, numRows-1, PS_TYPE_F32);
+    psImage *tmpImage4Short = psImageAlloc(numCols-1, numRows-1, PS_TYPE_F32);
+    pmReadout *myReadout = pmReadoutAlloc(NULL);
+    myReadout->image = tmpImage1;
+    pmReadout *rc = NULL;
+    psList *list;
+    psList *listShort;
+    psStats *stat = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    psImage *tmpImage5 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    pmReadout *myBias = pmReadoutAlloc(NULL);
+    myBias->image = tmpImage5;
+    printPositiveTestHeader(stdout, "pmSubtractBias", "Testing input parameter error conditions");
+ 
+    psImage *tmpImage5ShortRows = psImageAlloc(numCols, numRows-1, PS_TYPE_F32);
+    pmReadout *myBiasShortRows = pmReadoutAlloc(NULL);
+    myBiasShortRows->image = tmpImage5ShortRows;
+    psImage *tmpImage5ShortCols = psImageAlloc(numCols-1, numRows, PS_TYPE_F32);
+    pmReadout *myBiasShortCols = pmReadoutAlloc(NULL);
+    myBiasShortCols->image = tmpImage5ShortCols;
+ 
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols;j++) {
+            myReadout->image->data.F32[i][j] = (float) (i + j);
+            tmpImage2->data.F32[i][j] = 3.0;
+            tmpImage3->data.F32[i][j] = 4.0;
+            tmpImage4->data.F32[i][j] = 5.0;
+            myBias->image->data.F32[i][j] = 1.0;
+        }
+    }
+    list = psListAlloc(tmpImage2);
+    psListAdd(list, PS_LIST_HEAD, tmpImage3);
+    psListAdd(list, PS_LIST_HEAD, tmpImage4);
+ 
+    for (i=0;i<numRows-1;i++) {
+        for (j=0;j<numCols-1;j++) {
+            tmpImage2Short->data.F32[i][j] = 3.0;
+            tmpImage3Short->data.F32[i][j] = 4.0;
+            tmpImage4Short->data.F32[i][j] = 5.0;
+        }
+    }
+    listShort = psListAlloc(tmpImage2Short);
+    psListAdd(listShort, PS_LIST_HEAD, tmpImage3Short);
+    psListAdd(listShort, PS_LIST_HEAD, tmpImage4Short);
+    for (i=0;i<numRows-1;i++) {
+        for (j=0;j<numCols;j++) {
+            myBiasShortRows->image->data.F32[i][j] = 1.0;
+        }
+    }
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols-1;j++) {
+            myBiasShortCols->image->data.F32[i][j] = 1.0;
+        }
+    }
+ 
+ 
+    printf("------------------------------------------------------------------\n");
+    printf("Calling pmSubtractBias() with NULL overscan list and PM_OVERSCAN_ALL.  Should generate error.\n");
+    rc = pmSubtractBias(myReadout, NULL, NULL, PM_OVERSCAN_ALL, stat, 0, PM_FIT_NONE, NULL);
+    if (rc != myReadout) {
+        printf("TEST ERROR: pmSubtractBias() did not return input pmReadout.\n");
+        testStatus = false;
+    }
+ 
+    printf("------------------------------------------------------------------\n");
+    printf("Calling pmSubtractBias() with NULL overscan list and PM_OVERSCAN_ROWS.  Should generate error.\n");
+    rc = pmSubtractBias(myReadout, NULL, NULL, PM_OVERSCAN_ROWS, stat, 0, PM_FIT_NONE, NULL);
+    if (rc != myReadout) {
+        printf("TEST ERROR: pmSubtractBias() did not return input pmReadout.\n");
+        testStatus = false;
+        psFree(rc);
+    }
+ 
+    printf("------------------------------------------------------------------\n");
+    printf("Calling pmSubtractBias() with NULL overscan list and PM_OVERSCAN_COLUMNS.  Should generate error.\n");
+    rc = pmSubtractBias(myReadout, NULL, NULL, PM_OVERSCAN_COLUMNS, stat, 0, PM_FIT_NONE, NULL);
+    if (rc != myReadout) {
+        printf("TEST ERROR: pmSubtractBias() did not return input pmReadout.\n");
+        testStatus = false;
+        psFree(rc);
+    }
+ 
+    printf("------------------------------------------------------------------\n");
+    printf("Calling pmSubtractBias() with non-NULL overscan list and PM_OVERSCAN_NONE.  Should generate warning.\n");
+    rc = pmSubtractBias(myReadout, NULL, list, PM_OVERSCAN_NONE, stat, 0, PM_FIT_NONE, myBias);
+ 
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols;j++) {
+            psF32 expect = ((float) (i + j)) - 1.0;
+            psF32 actual = rc->image->data.F32[i][j];
+            if (FLT_EPSILON < fabs(expect - actual)) {
+                printf("TEST ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
+                testStatus = 1;
+            }
+ 
+            // Restore myReadout for next test.
+            myReadout->image->data.F32[i][j] = (float) (i + j);
+        }
+    }
+ 
+    // XXX: This does not seem to be a requirement.
+    if (0) {
+        printf("------------------------------------------------------------------\n");
+        printf("Calling pmSubtractBias() with NULL overscan list and PM_OVERSCAN_NONE.  Should generate warning.\n");
+        rc = pmSubtractBias(myReadout, NULL, NULL, PM_OVERSCAN_NONE, stat,
+                            0, PM_FIT_NONE, myBias);
+ 
+        for (i=0;i<numRows;i++) {
+            for (j=0;j<numCols;j++) {
+                psF32 expect = ((float) (i + j)) - 1.0;
+                psF32 actual = rc->image->data.F32[i][j];
+                if (FLT_EPSILON < fabs(expect - actual)) {
+                    printf("TEST ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
+                    testStatus = 1;
+                }
+ 
+                // Restore myReadout for next test.
+                myReadout->image->data.F32[i][j] = (float) (i + j);
+            }
+        }
+    }
+ 
+    printf("------------------------------------------------------------------\n");
+    printf("Calling pmSubtractBias() with PM_OVERSCAN_NONE and PM_FIT_POLYNOMIAL.  Should generate Warning.\n");
+    rc = pmSubtractBias(myReadout, NULL, NULL, PM_OVERSCAN_NONE, stat, 0, PM_FIT_POLYNOMIAL, myBias);
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols;j++) {
+            psF32 expect = ((float) (i + j)) - 1.0;
+            psF32 actual = rc->image->data.F32[i][j];
+            if (FLT_EPSILON < fabs(expect - actual)) {
+                printf("TEST ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
+                testStatus = 1;
+            }
+ 
+            // Restore myReadout for next test.
+            myReadout->image->data.F32[i][j] = (float) (i + j);
+        }
+    }
+ 
+ 
+    printf("------------------------------------------------------------------\n");
+    printf("Calling pmSubtractBias() with PM_OVERSCAN_ALL and PM_FIT_SPLINE.  Should generate Warning.\n");
+    rc = pmSubtractBias(myReadout, NULL, NULL, PM_OVERSCAN_NONE, stat, 0, PM_FIT_SPLINE, myBias);
+    if (rc != myReadout) {
+        printf("TEST ERROR: pmSubtractBias() did not return input pmReadout.\n");
+        testStatus = false;
+        psFree(rc);
+    }
+ 
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols;j++) {
+            psF32 expect = ((float) (i + j)) - 1.0;
+            psF32 actual = rc->image->data.F32[i][j];
+            if (FLT_EPSILON < fabs(expect - actual)) {
+                printf("TEST ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
+                testStatus = 1;
+            }
+ 
+            // Restore myReadout for next test.
+            myReadout->image->data.F32[i][j] = (float) (i + j);
+        }
+    }
+ 
+ 
+    printf("------------------------------------------------------------------\n");
+    printf("Calling pmSubtractBias() with multiple stats->options.  Should generate Warning.\n");
+    stat->options|= PS_STAT_SAMPLE_MEDIAN;
+    myReadout = pmSubtractBias(myReadout, NULL, list, PM_OVERSCAN_ALL, stat,
+                               0, PM_FIT_NONE, NULL);
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols;j++) {
+            psF32 expect = ((float) (i + j)) - 12.0;
+            psF32 actual = rc->image->data.F32[i][j];
+            if (FLT_EPSILON < fabs(expect - actual)) {
+                printf("TEST ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
+                testStatus = 1;
+            }
+        }
+    }
+    stat->options = PS_STAT_SAMPLE_MEAN;
+ 
+    printf("------------------------------------------------------------------\n");
+    printf("Calling pmSubtractBias() undersize overscans (PM_OVERSCAN_ROWS).  Should generate Warning.\n");
+    rc = pmSubtractBias(myReadout, NULL, listShort, PM_OVERSCAN_ROWS, stat,
+                        0, PM_FIT_NONE, NULL);
+    if (0) {
+        for (i=0;i<numRows;i++) {
+            for (j=0;j<numCols;j++) {
+                psF32 expect = ((float) (i + j)) - 12.0;
+                psF32 actual = rc->image->data.F32[i][j];
+                if (FLT_EPSILON < fabs(expect - actual)) {
+                    printf("TEST ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
+                    testStatus = 1;
+                }
+            }
+        }
+    }
+ 
+    printf("------------------------------------------------------------------\n");
+    printf("Calling pmSubtractBias() undersize overscans (PM_OVERSCAN_COLUMNS).  Should generate Warning.\n");
+    rc = pmSubtractBias(myReadout, NULL, listShort, PM_OVERSCAN_COLUMNS, stat,
+                        0, PM_FIT_NONE, NULL);
+    if (0) {
+        for (i=0;i<numRows;i++) {
+            for (j=0;j<numCols;j++) {
+                psF32 expect = ((float) (i + j)) - 12.0;
+                psF32 actual = rc->image->data.F32[i][j];
+                if (FLT_EPSILON < fabs(expect - actual)) {
+                    printf("TEST ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
+                    testStatus = 1;
+                }
+            }
+        }
+    }
+ 
+    printf("------------------------------------------------------------------\n");
+    printf("Calling pmSubtractBias() undersize bias image (short rows).  Should generate Error.\n");
+    myReadout = pmSubtractBias(myReadout, NULL, NULL, PM_OVERSCAN_NONE, NULL,
+                               0, PM_FIT_NONE, myBiasShortRows);
+    if (rc != myReadout) {
+        printf("TEST ERROR: pmSubtractBias() did not return input pmReadout.\n");
+        testStatus = false;
+        psFree(rc);
+    }
+ 
+ 
+    printf("------------------------------------------------------------------\n");
+    printf("Calling pmSubtractBias() undersize bias image (short columns).  Should generate Error.\n");
+    myReadout = pmSubtractBias(myReadout, NULL, NULL, PM_OVERSCAN_NONE, NULL,
+                               0, PM_FIT_NONE, myBiasShortCols);
+    if (rc != myReadout) {
+        printf("TEST ERROR: pmSubtractBias() did not return input pmReadout.\n");
+        testStatus = false;
+        psFree(rc);
+    }
+ 
+    printf("------------------------------------------------------------------\n");
+    printf("Calling pmSubtractBias() with bogus PM_FIT.  Should generate Error.\n");
+    myReadout = pmSubtractBias(myReadout, NULL, list, PM_OVERSCAN_ROWS, stat,
+                               0, 54321, NULL);
+    if (rc != myReadout) {
+        printf("TEST ERROR: pmSubtractBias() did not return input pmReadout.\n");
+        testStatus = false;
+        psFree(rc);
+    }
+ 
+    printf("------------------------------------------------------------------\n");
+    printf("Calling pmSubtractBias() with bogus overScanAxis.  Should generate Error.\n");
+    myReadout = pmSubtractBias(myReadout, NULL, list, 54321, stat,
+                               0, PM_FIT_NONE, NULL);
+    if (rc != myReadout) {
+        printf("TEST ERROR: pmSubtractBias() did not return input pmReadout.\n");
+        testStatus = false;
+        psFree(rc);
+    }
+ 
+    if (0) {
+        for (i=0;i<numRows;i++) {
+            for (j=0;j<numCols;j++) {
+                psF32 expect = ((float) (i + j)) - 12.0;
+                psF32 actual = rc->image->data.F32[i][j];
+                if (FLT_EPSILON < fabs(expect - actual)) {
+                    printf("TEST ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
+                    testStatus = 1;
+                }
+            }
+        }
+    }
+ 
+    printf("------------------------------------------------------------------\n");
+    psFree(myReadout);
+    psFree(tmpImage2);
+    psFree(tmpImage3);
+    psFree(tmpImage4);
+    psFree(tmpImage2Short);
+    psFree(tmpImage3Short);
+    psFree(tmpImage4Short);
+    psFree(myBias);
+    psFree(myBiasShortRows);
+    psFree(myBiasShortCols);
+    psFree(stat);
+    psFree(list);
+    psFree(listShort);
+ 
+    printFooter(stdout, "pmSubtractBias", "Testing input parameter error conditions", true);
+    return(testStatus);
+}
+ 
+int test04( void )
+{
+    int testStatus = 0;
+ 
+    testStatus |= doSubtractOverscansTestInputCases(NUM_COLS, NUM_ROWS);
+    return(testStatus);
+}
+*/
+
+void PS_POLY1D_PRINT(
+    psPolynomial1D *poly)
+{
+    printf("-------------- PS_POLY1D_PRINT() --------------\n");
+    printf("poly->nX is %d\n", poly->nX);
+    for (psS32 i = 0 ; i < (1 + poly->nX) ; i++) {
+        printf("poly->coeff[%d] is %f\n", i, poly->coeff[i]);
+    }
+}
+
+void PS_PRINT_SPLINE2(psSpline1D *mySpline)
+{
+    printf("-------------- PS_PRINT_SPLINE2() --------------\n");
+    if (mySpline != NULL) {
+        printf("mySpline->n is %d\n", mySpline->n);
+        for (psS32 i = 0 ; i < mySpline->n ; i++) {
+            if (mySpline->spline[i] != NULL) {
+                PS_POLY1D_PRINT(mySpline->spline[i]);
+            }
+        }
+        if (mySpline->knots != NULL) {
+            PS_VECTOR_PRINT_F32(mySpline->knots);
+        }
+    } else {
+        printf("NULL\n");
+    }
+    printf("-------------- PS_PRINT_SPLINE2() DONE --------------\n");
+}
+
+
+
+
+
+
+/******************************************************************************
+doSubtractOverscansGeneric(): This is a general version of the
+bias subtraction tests which allows the various parameters to be specified
+as arguments.
+ *****************************************************************************/
+int doSubtractOverscansGeneric(
+    int imageNumCols,
+    int imageNumRows,
+    int overscanNumCols,
+    int overscanNumRows,
+    int numOverscans,
+    pmOverscanAxis overscanaxis,
+    pmFit fit,
+    psS32 nBin)
+{
+    int i;
+    int j;
+    float actual;
+    float expect;
+    int testStatus = 0;
+
+    printPositiveTestHeader(stdout, "pmSubtractBias", "PUT COMMENT HERE");
+    printf("---- doSubtractOverscansGeneric() ----\n");
+    printf("    Image size: %d by %d\n", imageNumRows, imageNumCols);
+    printf("    Overscan size: %d by %d\n", overscanNumRows, overscanNumCols);
+    printf("    Total Overscans: %d\n", numOverscans);
+    printf("    Binning factor: %d\n", nBin);
+    if (overscanaxis == PM_OVERSCAN_ROWS)
+        printf("    Overscan axis: PM_OVERSCAN_ROWS\n");
+    if (overscanaxis == PM_OVERSCAN_COLUMNS)
+        printf("    Overscan axis: PM_OVERSCAN_COLUMNS\n");
+    if (overscanaxis == PM_OVERSCAN_ALL)
+        printf("    Overscan axis: PM_OVERSCAN_ALL\n");
+    if (overscanaxis == PM_OVERSCAN_NONE)
+        printf("    Overscan axis: PM_OVERSCAN_NONE\n");
+    if (fit == PM_FIT_NONE)
+        printf("    Fit type: PM_FIT_NONE\n");
+    if (fit == PM_FIT_POLYNOMIAL)
+        printf("    Fit type: PM_FIT_POLYNOMIAL\n");
+    if (fit == PM_FIT_SPLINE)
+        printf("    Fit type: PM_FIT_SPLINE\n");
+
+    //
+    // Create and initialize input image, FPA hierarchy.
+    //
+    const psMetadata *camera = psMetadataAlloc();
+    pmFPA* fpa = pmFPAAlloc(camera);
+
+    if (fpa == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmFPAAlloc returned a NULL.\n");
+        return 1;
+    }
+
+    pmChip *chip = pmChipAlloc(fpa, "ChipName");
+    if (chip == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmChipAlloc returned a NULL.\n");
+        return 2;
+    }
+
+    pmCell *cell = pmCellAlloc(chip, (psMetadata *) camera, "CellName");
+    if (cell == NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR, "TEST ERROR: pmCellAlloc returned a NULL.\n");
+        return 3;
+    }
+
+    pmReadout *myReadout = pmReadoutAlloc(cell);
+    myReadout->image = psImageAlloc(imageNumCols, imageNumRows, PS_TYPE_F32);
+    for (i=0;i<myReadout->image->numRows;i++) {
+        for (j=0;j<myReadout->image->numCols;j++) {
+            myReadout->image->data.F32[i][j] = (float) (i + j);
+        }
+    }
+
+    //
+    // Set overscan axis in the metadata.
+    //
+    psBool rc = false;
+    if (overscanaxis == PM_OVERSCAN_ROWS) {
+        rc = psMetadataAddS32(myReadout->parent->concepts, PS_LIST_HEAD, "CELL.READDIR", 0, NULL, 1);
+    } else if (overscanaxis == PM_OVERSCAN_COLUMNS) {
+        rc = psMetadataAddS32(myReadout->parent->concepts, PS_LIST_HEAD, "CELL.READDIR", 0, NULL, 2);
+    } else if (overscanaxis == PM_OVERSCAN_ALL) {
+        rc = psMetadataAddS32(myReadout->parent->concepts, PS_LIST_HEAD, "CELL.READDIR", 0, NULL, 3);
+    } else if (overscanaxis == PM_OVERSCAN_NONE) {
+        rc = psMetadataAddS32(myReadout->parent->concepts, PS_LIST_HEAD, "CELL.READDIR", 0, NULL, 0);
+    }
+    if (rc == false) {
+        printf("TEST ERROR: Could not set CELL.READDIR metadata.\n");
+        testStatus = 1;
+    }
+
+    psStats *stat = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    psPolynomial1D *myPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, POLYNOMIAL_FIT_ORDER);
+    psSpline1D *mySpline = NULL;
+
+
+    if (0) {
+        if (overscanNumRows <= 0) {
+            overscanNumRows = 1;
+        }
+        if (overscanNumCols <= 0) {
+            overscanNumCols = 1;
+        }
+    }
+    psF32 oAverage = 0.0;
+    myReadout->bias = NULL;
+    for (psS32 i = 0 ; i < numOverscans ; i++) {
+        psImage *tmpImage = psImageAlloc(overscanNumCols, overscanNumRows, PS_TYPE_F32);
+        psF32 oValue = (float) (i + 3);
+        PS_IMAGE_SET_F32(tmpImage, oValue);
+        oAverage += oValue;
+        if (myReadout->bias == NULL) {
+            myReadout->bias = psListAlloc(tmpImage);
+        } else {
+            psListAdd(myReadout->bias, PS_LIST_HEAD, tmpImage);
+        }
+    }
+    oAverage/= (psF32) numOverscans;
+    if (0) {
+        if (fit == PM_FIT_NONE) {
+            myReadout = pmSubtractBias(myReadout, NULL, PM_FIT_NONE, overscanaxis,
+                                       stat, nBin, NULL, NULL);
+        } else if (fit == PM_FIT_POLYNOMIAL) {
+            myReadout = pmSubtractBias(myReadout, myPoly, PM_FIT_POLYNOMIAL, overscanaxis,
+                                       stat, nBin, NULL, NULL);
+        } else if (fit == PM_FIT_SPLINE) {
+            //        mySpline = psSpline1DAlloc();
+            myReadout = pmSubtractBias(myReadout, mySpline, PM_FIT_SPLINE, overscanaxis,
+                                       stat, nBin, NULL, NULL);
+        }
+        if (myReadout == NULL ) {
+            printf("TEST ERROR: pmSubtractBias() returned NULL.\n");
+            testStatus = 1;
+        } else {
+            for (i=0;i<imageNumRows;i++) {
+                for (j=0;j<imageNumCols;j++) {
+                    expect = ((float) (i + j)) - oAverage;
+                    actual = myReadout->image->data.F32[i][j];
+                    if (FLT_EPSILON < fabs(expect - actual)) {
+                        printf("TEST ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
+                        testStatus = 1;
+                    } else {
+                        //printf("GOOD: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
+                    }
+                }
+            }
+        }
+    }
+
+    // HEY
+    psFree(fpa);
+    psFree(stat);
+    psFree(myPoly);
+    psFree(mySpline);
+
+    printFooter(stdout, "pmSubtractBias", "Column Overscans", true);
+    return(testStatus);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+test05a() The following combinations are tested here:
+ Overscan images are same size, no fit, bin factor is 1.
+ Overscan images are same size, no fit, bin factor is 2.
+ *****************************************************************************/
+int test05a(
+    psS32 imageNumCols,
+    psS32 imageNumRows,
+    psS32 overscanNumCols,
+    psS32 overscanNumRows)
+{
+    int testStatus = 0;
+
+    // imageNumCols, imageNumRows, overscanNumCols, overscanNumRows,
+    // overscanaxis, fit, nBin
+
+    //
+    // Overscan images are same size, no fit, bin factor is 1.
+    //
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, NUM_OVERSCANS,
+                  PM_OVERSCAN_ALL,
+                  PM_FIT_NONE, 1);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, NUM_OVERSCANS,
+                  PM_OVERSCAN_COLUMNS,
+                  PM_FIT_NONE, 1);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, NUM_OVERSCANS,
+                  PM_OVERSCAN_ROWS,
+                  PM_FIT_NONE, 1);
+
+    //
+    // Overscan images are same size, no fit, bin factor is 2.
+    //
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, NUM_OVERSCANS,
+                  PM_OVERSCAN_ALL,
+                  PM_FIT_NONE, 2);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, NUM_OVERSCANS,
+                  PM_OVERSCAN_COLUMNS,
+                  PM_FIT_NONE, 2);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, NUM_OVERSCANS,
+                  PM_OVERSCAN_ROWS,
+                  PM_FIT_NONE, 2);
+
+    return(testStatus);
+}
+
+
+/******************************************************************************
+test05b() The following combinations are tested here:
+ Overscan images are too small, spline fit, bin factor is 1.
+ Overscan images are too small, spline fit, bin factor is 2.
+ Overscan images are same size, spline fit, bin factor is 1.
+ Overscan images are same size, spline fit, bin factor is 2.
+ Overscan images are too big,   spline fit, bin factor is 1.
+ Overscan images are too big,   spline fit, bin factor is 2.
+ A single overscan image of the same size, spline fit, bin factor is 1.
+ 
+ Overscan images are too small, polynomial fit, bin factor is 1.
+ Overscan images are too small, polynomial fit, bin factor is 2.
+ Overscan images are same size, polynomial fit, bin factor is 1.
+ Overscan images are same size, polynomial fit, bin factor is 2.
+ Overscan images are too big,   polynomial fit, bin factor is 1.
+ Overscan images are too big,   polynomial fit, bin factor is 2.
+ A single overscan image of the same size, polynomial fit, bin factor is 1.
+ 
+XXX: Must add M-by-N image size tests.
+ *****************************************************************************/
+int test05b(
+    psS32 imageNumCols,
+    psS32 imageNumRows,
+    psS32 overscanNumCols,
+    psS32 overscanNumRows)
+{
+    int testStatus = 0;
+
+    //
+    // Overscan images are too small, spline fit, bin factor is 1.
+    //
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols-2, overscanNumRows-2, NUM_OVERSCANS,
+                  PM_OVERSCAN_ALL,
+                  PM_FIT_SPLINE, 1);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols-2, overscanNumRows-2, NUM_OVERSCANS,
+                  PM_OVERSCAN_COLUMNS,
+                  PM_FIT_SPLINE, 1);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols-2, overscanNumRows-2, NUM_OVERSCANS,
+                  PM_OVERSCAN_ROWS,
+                  PM_FIT_SPLINE, 1);
+
+    //
+    // Overscan images are too small, spline fit, bin factor is 2.
+    //
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols-2, overscanNumRows-2, NUM_OVERSCANS,
+                  PM_OVERSCAN_ALL,
+                  PM_FIT_SPLINE, 2);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols-2, overscanNumRows-2, NUM_OVERSCANS,
+                  PM_OVERSCAN_COLUMNS,
+                  PM_FIT_SPLINE, 2);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols-2, overscanNumRows-2, NUM_OVERSCANS,
+                  PM_OVERSCAN_ROWS,
+                  PM_FIT_SPLINE, 2);
+
+
+    //
+    // Overscan images are same size, spline fit, bin factor is 1.
+    //
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, NUM_OVERSCANS,
+                  PM_OVERSCAN_ALL,
+                  PM_FIT_SPLINE, 1);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, NUM_OVERSCANS,
+                  PM_OVERSCAN_COLUMNS,
+                  PM_FIT_SPLINE, 1);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, NUM_OVERSCANS,
+                  PM_OVERSCAN_ROWS,
+                  PM_FIT_SPLINE, 1);
+
+    //
+    // Overscan images are same size, spline fit, bin factor is 2.
+    //
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, NUM_OVERSCANS,
+                  PM_OVERSCAN_ALL,
+                  PM_FIT_SPLINE, 2);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, NUM_OVERSCANS,
+                  PM_OVERSCAN_COLUMNS,
+                  PM_FIT_SPLINE, 2);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, NUM_OVERSCANS,
+                  PM_OVERSCAN_ROWS,
+                  PM_FIT_SPLINE, 2);
+
+    //
+    // Overscan images are too big, spline fit, bin factor is 1.
+    //
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols+2, overscanNumRows+2, NUM_OVERSCANS,
+                  PM_OVERSCAN_ALL,
+                  PM_FIT_SPLINE, 1);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols+2, overscanNumRows+2, NUM_OVERSCANS,
+                  PM_OVERSCAN_COLUMNS,
+                  PM_FIT_SPLINE, 1);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols+2, overscanNumRows+2, NUM_OVERSCANS,
+                  PM_OVERSCAN_ROWS,
+                  PM_FIT_SPLINE, 1);
+
+    //
+    // Overscan images are too big, spline fit, bin factor is 2.
+    //
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols+2, overscanNumRows+2, NUM_OVERSCANS,
+                  PM_OVERSCAN_ALL,
+                  PM_FIT_SPLINE, 2);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols+2, overscanNumRows+2, NUM_OVERSCANS,
+                  PM_OVERSCAN_COLUMNS,
+                  PM_FIT_SPLINE, 2);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols+2, overscanNumRows+2 , NUM_OVERSCANS,
+                  PM_OVERSCAN_ROWS,
+                  PM_FIT_SPLINE, 2);
+
+
+    //
+    // A single overscan image of the same size, spline fit, bin factor is 1.
+    //
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, 1,
+                  PM_OVERSCAN_ALL,
+                  PM_FIT_SPLINE, 1);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, 1,
+                  PM_OVERSCAN_COLUMNS,
+                  PM_FIT_SPLINE, 1);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, 1,
+                  PM_OVERSCAN_ROWS,
+                  PM_FIT_SPLINE, 1);
+
+
+    //
+    // Overscan images are too small, polynomial fit, bin factor is 1.
+    //
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols-2, overscanNumRows-2, NUM_OVERSCANS,
+                  PM_OVERSCAN_ALL,
+                  PM_FIT_POLYNOMIAL, 1);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols-2, overscanNumRows-2, NUM_OVERSCANS,
+                  PM_OVERSCAN_COLUMNS,
+                  PM_FIT_POLYNOMIAL, 1);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols-2, overscanNumRows-2, NUM_OVERSCANS,
+                  PM_OVERSCAN_ROWS,
+                  PM_FIT_POLYNOMIAL, 1);
+
+    //
+    // Overscan images are too small, polynomial fit, bin factor is 2.
+    //
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols-2, overscanNumRows-2, NUM_OVERSCANS,
+                  PM_OVERSCAN_ALL,
+                  PM_FIT_POLYNOMIAL, 2);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols-2, overscanNumRows-2, NUM_OVERSCANS,
+                  PM_OVERSCAN_COLUMNS,
+                  PM_FIT_POLYNOMIAL, 2);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols-2, overscanNumRows-2, NUM_OVERSCANS,
+                  PM_OVERSCAN_ROWS,
+                  PM_FIT_POLYNOMIAL, 2);
+
+
+    //
+    // Overscan images are same size, polynomial fit, bin factor is 1.
+    //
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, NUM_OVERSCANS,
+                  PM_OVERSCAN_ALL,
+                  PM_FIT_POLYNOMIAL, 1);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, NUM_OVERSCANS,
+                  PM_OVERSCAN_COLUMNS,
+                  PM_FIT_POLYNOMIAL, 1);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, NUM_OVERSCANS,
+                  PM_OVERSCAN_ROWS,
+                  PM_FIT_POLYNOMIAL, 1);
+
+    //
+    // Overscan images are same size, polynomial fit, bin factor is 2.
+    //
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, NUM_OVERSCANS,
+                  PM_OVERSCAN_ALL,
+                  PM_FIT_POLYNOMIAL, 2);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, NUM_OVERSCANS,
+                  PM_OVERSCAN_COLUMNS,
+                  PM_FIT_POLYNOMIAL, 2);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, NUM_OVERSCANS,
+                  PM_OVERSCAN_ROWS,
+                  PM_FIT_POLYNOMIAL, 2);
+
+    //
+    // Overscan images are too big, polynomial fit, bin factor is 1.
+    //
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols+2, overscanNumRows+2, NUM_OVERSCANS,
+                  PM_OVERSCAN_ALL,
+                  PM_FIT_POLYNOMIAL, 1);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols+2, overscanNumRows+2, NUM_OVERSCANS,
+                  PM_OVERSCAN_COLUMNS,
+                  PM_FIT_POLYNOMIAL, 1);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols+2, overscanNumRows+2, NUM_OVERSCANS,
+                  PM_OVERSCAN_ROWS,
+                  PM_FIT_POLYNOMIAL, 1);
+
+    //
+    // Overscan images are too big, polynomial fit, bin factor is 2.
+    //
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols+2, overscanNumRows+2, NUM_OVERSCANS,
+                  PM_OVERSCAN_ALL,
+                  PM_FIT_POLYNOMIAL, 2);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols+2, overscanNumRows+2, NUM_OVERSCANS,
+                  PM_OVERSCAN_COLUMNS,
+                  PM_FIT_POLYNOMIAL, 2);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols+2, overscanNumRows+2, NUM_OVERSCANS,
+                  PM_OVERSCAN_ROWS,
+                  PM_FIT_POLYNOMIAL, 2);
+
+    //
+    // A single overscan image of the same size, polynomial fit, bin factor is 1.
+    //
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, 1,
+                  PM_OVERSCAN_ALL,
+                  PM_FIT_POLYNOMIAL, 1);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, 1,
+                  PM_OVERSCAN_COLUMNS,
+                  PM_FIT_POLYNOMIAL, 1);
+
+    testStatus |= doSubtractOverscansGeneric(imageNumCols, imageNumRows,
+                  overscanNumCols, overscanNumRows, 1,
+                  PM_OVERSCAN_ROWS,
+                  PM_FIT_POLYNOMIAL, 1);
+
+    return(testStatus);
+}
+
+
+
+#define LOW_COLS 3
+#define LOW_ROWS 3
+
+/******************************************************************************
+test05(): See test05a() and test05b().
+ 
+We run the tests in test05b() starting with all possible combinations of
+sizes.
+ 
+XXX: Must add M-by-N image size tests.
+ *****************************************************************************/
+int test05()
+{
+    int testStatus = 0;
+    //    testStatus = test05a(NUM_COLS, NUM_ROWS, NUM_COLS, NUM_ROWS);
+
+    //    testStatus|= test05b(LOW_COLS, LOW_ROWS, LOW_COLS, LOW_ROWS);
+    //    testStatus|= test05b(LOW_COLS, LOW_ROWS, LOW_COLS, NUM_ROWS);
+    //    testStatus|= test05b(LOW_COLS, LOW_ROWS, NUM_COLS, LOW_ROWS);
+    //    testStatus|= test05b(LOW_COLS, LOW_ROWS, NUM_COLS, NUM_ROWS);
+
+    //    testStatus|= test05b(LOW_COLS, NUM_ROWS, LOW_COLS, LOW_ROWS);
+    //    testStatus|= test05b(LOW_COLS, NUM_ROWS, LOW_COLS, NUM_ROWS);
+    //    testStatus|= test05b(LOW_COLS, NUM_ROWS, NUM_COLS, LOW_ROWS);
+    //    testStatus|= test05b(LOW_COLS, NUM_ROWS, NUM_COLS, NUM_ROWS);
+
+    //    testStatus|= test05b(NUM_COLS, LOW_ROWS, LOW_COLS, LOW_ROWS);
+    //    testStatus|= test05b(NUM_COLS, LOW_ROWS, LOW_COLS, NUM_ROWS);
+    //    testStatus|= test05b(NUM_COLS, LOW_ROWS, NUM_COLS, LOW_ROWS);
+    //    testStatus|= test05b(NUM_COLS, LOW_ROWS, NUM_COLS, NUM_ROWS);
+
+    //    testStatus|= test05b(NUM_COLS, NUM_ROWS, LOW_COLS, LOW_ROWS);
+    //    testStatus|= test05b(NUM_COLS, NUM_ROWS, LOW_COLS, NUM_ROWS);
+    //    testStatus|= test05b(NUM_COLS, NUM_ROWS, NUM_COLS, LOW_ROWS);
+    testStatus|= test05b(NUM_COLS, NUM_ROWS, NUM_COLS, NUM_ROWS);
+
+
+    return(testStatus);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tst_pmSubtractSky.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tst_pmSubtractSky.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/detrend/tst_pmSubtractSky.c	(revision 22158)
@@ -0,0 +1,375 @@
+/** @file tst_pmSubtractSky.c
+ *
+ *  @brief Contains the tests for pmSubtractSky.c:
+ *
+ * test00: This code will test the pmSubtractSky routine.
+ *
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-05-25 22:02:23 $
+ *
+ *  XXX: I added the CELL.TRIMSEC region code but there are not tests for it.
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#include "psTest.h"
+#include "pslib.h"
+#include "pmSubtractSky.h"
+#define NUM_ROWS 512
+#define NUM_COLS 512
+#define POLY_X_ORDER 3
+#define POLY_Y_ORDER 3
+#define ERROR_TOLERANCE 1.0
+#define OBJECT_INTENSITY 2000.0
+static int test00(void);
+static int test01(void);
+testDescription tests[] = {
+                              {test00, 000, "pmSubtractSky", 0, false},
+                              {test01, 000, "pmSubtractSky: warning, error messages", 0, false},
+                              {NULL}
+                          };
+
+float func(int i, int j)
+{
+    return((float) (i + j));
+}
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    return !runTestSuite(stderr, "Test Point Driver", tests, argc, argv);
+    //    test00();
+}
+
+/******************************************************************************
+ *****************************************************************************/
+int doSubtractSkySimple(int numCols, int numRows, int binFactor)
+{
+    int i;
+    int j;
+    int testStatus = 0;
+    psImage *tmpImageF32 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    //    pmReadout *myReadout = pmReadoutAlloc(numCols, numRows, tmpImageF32);
+    pmReadout *myReadout = pmReadoutAlloc(NULL);
+    myReadout->image = tmpImageF32;
+    psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    psPolynomial2D *myPoly = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, POLY_X_ORDER, POLY_Y_ORDER);
+
+    printPositiveTestHeader(stdout, "pmSubtractSky", "doSubtractSkySimple");
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols;j++) {
+            myReadout->image->data.F32[i][j] = func(i, j);
+        }
+    }
+
+    myReadout = pmSubtractSky(myReadout, (void *) myPoly, PM_FIT_POLYNOMIAL,
+                              binFactor, myStats, 10.0);
+    if (myReadout == NULL) {
+        printf("TEST ERROR: pmSubtractSky() returned NULL.\n");
+        testStatus = 1;
+    } else {
+        for (i=0;i<numRows;i++) {
+            for (j=0;j<numCols;j++) {
+                if (ERROR_TOLERANCE < fabs(myReadout->image->data.F32[i][j])) {
+                    printf("TEST ERROR: image[%d][%d] is %f, should be 0.0\n", i, j, myReadout->image->data.F32[i][j]);
+                    testStatus = 1;
+                }
+            }
+        }
+    }
+    psFree(myReadout);
+    psFree(myStats);
+    psFree(myPoly);
+    printFooter(stdout, "pmSubtractSky", "doSubtractSkySimple", true);
+    return(testStatus);
+}
+
+/******************************************************************************
+ *****************************************************************************/
+int doSubtractSkyWithObjects(int numCols, int numRows, int binFactor)
+{
+    int i;
+    int j;
+    int testStatus = 0;
+    psImage *tmpImageF32 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    //    pmReadout *myReadout = pmReadoutAlloc(numCols, numRows, tmpImageF32);
+    pmReadout *myReadout = pmReadoutAlloc(NULL);
+    myReadout->image = tmpImageF32;
+    psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    psPolynomial2D *myPoly = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, POLY_X_ORDER, POLY_Y_ORDER);
+    psImage *trueImage = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    psF32 errorTolerance = ERROR_TOLERANCE * ((psF32) binFactor);
+
+    printPositiveTestHeader(stdout, "pmSubtractSky", "doSubtractSkyWithObjects");
+    for (i=0;i<numRows;i++) {
+        for (j=0;j<numCols;j++) {
+            myReadout->image->data.F32[i][j] = func(i, j);
+        }
+    }
+    // We insert a few bright spots in the image.
+    myReadout->image->data.F32[NUM_ROWS/4][NUM_COLS/4]+= OBJECT_INTENSITY;
+    myReadout->image->data.F32[NUM_ROWS/4][3*NUM_COLS/4]+= OBJECT_INTENSITY;
+    myReadout->image->data.F32[3*NUM_ROWS/4][NUM_COLS/4]+= OBJECT_INTENSITY;
+    myReadout->image->data.F32[3*NUM_ROWS/4][3*NUM_COLS/4]+= OBJECT_INTENSITY;
+    PS_IMAGE_SET_F32(trueImage, 0.0);
+    trueImage->data.F32[NUM_ROWS/4][NUM_COLS/4]+= OBJECT_INTENSITY;
+    trueImage->data.F32[NUM_ROWS/4][3*NUM_COLS/4]+= OBJECT_INTENSITY;
+    trueImage->data.F32[3*NUM_ROWS/4][NUM_COLS/4]+= OBJECT_INTENSITY;
+    trueImage->data.F32[3*NUM_ROWS/4][3*NUM_COLS/4]+= OBJECT_INTENSITY;
+
+    myReadout = pmSubtractSky(myReadout, (void *) myPoly, PM_FIT_POLYNOMIAL,
+                              binFactor, myStats, 2.0);
+    if (myReadout == NULL) {
+        printf("TEST ERROR: pmSubtractSky() returned NULL.\n");
+        testStatus = 1;
+    } else {
+        for (i=0;i<numRows;i++) {
+            for (j=0;j<numCols;j++) {
+                if (errorTolerance < fabs(myReadout->image->data.F32[i][j] - trueImage->data.F32[i][j])) {
+                    printf("TEST ERROR: image[%d][%d] is %f, should be %f\n", i, j,
+                           myReadout->image->data.F32[i][j], trueImage->data.F32[i][j]);
+                    testStatus = 1;
+                }
+            }
+        }
+    }
+    psFree(myReadout);
+    psFree(myStats);
+    psFree(myPoly);
+    psFree(trueImage);
+    printFooter(stdout, "pmSubtractSky", "doSubtractSkyWithObjects", true);
+    return(testStatus);
+}
+
+
+int test00( void )
+{
+    int testStatus = 0;
+
+    psTraceSetLevel(".", 0);
+
+    // Bin Factor == 1
+    printf("doSubtractSkySimple(1, 1, 1)\n");
+    testStatus |= doSubtractSkySimple(1, 1, 1);
+    printf("doSubtractSkySimple(NUM_COLS, 1, 1)\n");
+    testStatus |= doSubtractSkySimple(NUM_COLS, 1, 1);
+
+    printf("doSubtractSkySimple(1, NUM_ROWS, 1)\n");
+    testStatus |= doSubtractSkySimple(1, NUM_ROWS, 1);
+    printf("doSubtractSkySimple(NUM_COLS, NUM_ROWS, 1)\n");
+    testStatus |= doSubtractSkySimple(NUM_COLS, NUM_ROWS, 1);
+
+    // Bin Factor == 2
+    printf("doSubtractSkySimple(1, 1, 2)\n");
+    testStatus |= doSubtractSkySimple(1, 1, 2);
+    printf("doSubtractSkySimple(NUM_COLS, 1, 2)\n");
+    testStatus |= doSubtractSkySimple(NUM_COLS, 1, 2);
+    printf("doSubtractSkySimple(1, NUM_ROWS, 2)\n");
+    testStatus |= doSubtractSkySimple(1, NUM_ROWS, 2);
+    printf("doSubtractSkySimple(NUM_COLS, NUM_ROWS, 2)\n");
+    testStatus |= doSubtractSkySimple(NUM_COLS, NUM_ROWS, 2);
+
+    printf("doSubtractSkyWithObjects(NUM_COLS, NUM_ROWS, 1)\n");
+    testStatus |= doSubtractSkyWithObjects(NUM_COLS, NUM_ROWS, 1);
+    printf("doSubtractSkyWithObjects(NUM_COLS, NUM_ROWS, 2)\n");
+    testStatus |= doSubtractSkyWithObjects(NUM_COLS, NUM_ROWS, 2);
+    printf("doSubtractSkyWithObjects(NUM_COLS, NUM_ROWS, 4)\n");
+    testStatus |= doSubtractSkyWithObjects(NUM_COLS, NUM_ROWS, 8);
+
+    printf("doSubtractSkyWithObjects(NUM_COLS, NUM_ROWS, 8)\n");
+    testStatus |= doSubtractSkyWithObjects(NUM_COLS, NUM_ROWS, 8);
+    printf("doSubtractSkyWithObjects(NUM_COLS, NUM_ROWS, 16)\n");
+    testStatus |= doSubtractSkyWithObjects(NUM_COLS, NUM_ROWS, 16);
+    printf("doSubtractSkyWithObjects(NUM_COLS, NUM_ROWS, 32)\n");
+    testStatus |= doSubtractSkyWithObjects(NUM_COLS, NUM_ROWS, 32);
+    printf("doSubtractSkyWithObjects(NUM_COLS, NUM_ROWS, 64)\n");
+    testStatus |= doSubtractSkyWithObjects(NUM_COLS, NUM_ROWS, 64);
+    printf("doSubtractSkyWithObjects(NUM_COLS, NUM_ROWS, 128)\n");
+    testStatus |= doSubtractSkyWithObjects(NUM_COLS, NUM_ROWS, 128);
+    printf("doSubtractSkyWithObjects(NUM_COLS, NUM_ROWS, 256)\n");
+    testStatus |= doSubtractSkyWithObjects(NUM_COLS, NUM_ROWS, 256);
+
+    return(testStatus);
+}
+
+#define NUM_ROWS_SMALL 16
+#define NUM_COLS_SMALL 16
+int test01( void )
+{
+    int testStatus = 0;
+    psS32 i;
+    psS32 j;
+    psImage *tmpImageF32 = psImageAlloc(NUM_COLS_SMALL, NUM_ROWS_SMALL, PS_TYPE_F32);
+    psImage *tmpImageF64 = psImageAlloc(NUM_COLS_SMALL, NUM_ROWS_SMALL, PS_TYPE_F64);
+    //    pmReadout *myReadout = pmReadoutAlloc(NUM_COLS_SMALL, NUM_ROWS_SMALL, tmpImageF32);
+    pmReadout *myReadout = pmReadoutAlloc(NULL);
+    myReadout->image = tmpImageF32;
+    pmReadout *rc = NULL;
+    psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    psPolynomial2D *myPoly = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, POLY_X_ORDER, POLY_Y_ORDER);
+
+    printPositiveTestHeader(stdout, "pmSubtractSky", "Testing bad input parameter conditions.");
+    for (i=0;i<NUM_ROWS_SMALL;i++) {
+        for (j=0;j<NUM_COLS_SMALL;j++) {
+            myReadout->image->data.F32[i][j] = func(i, j);
+        }
+    }
+
+    printf("----------------------------------------------------------------\n");
+    printf("Calling pmSubtractSky() with NULL pmReadout.  Should error.\n\n");
+    rc = pmSubtractSky(NULL, (void *) myPoly, PM_FIT_POLYNOMIAL, 1, myStats, 2.0);
+    if (rc != NULL) {
+        printf("TEST ERROR: pmSubtractSky() returned a non-NULL pmReadout\n");
+        testStatus = false;
+    }
+
+    printf("----------------------------------------------------------------\n");
+    printf("Calling pmSubtractSky() with NULL pmReadout->image.  Should error.\n\n");
+    myReadout->image = NULL;
+    rc = pmSubtractSky(myReadout, (void *) myPoly, PM_FIT_POLYNOMIAL, 1, myStats, 2.0);
+    if (rc != NULL) {
+        printf("TEST ERROR: pmSubtractSky() returned a non-NULL pmReadout\n");
+        testStatus = false;
+    }
+    myReadout->image = tmpImageF32;
+
+    printf("----------------------------------------------------------------\n");
+    printf("Calling pmSubtractSky() with PS_TYPE_F64 pmReadout->image.  Should error.\n\n");
+    myReadout->image = tmpImageF64;
+    rc = pmSubtractSky(myReadout, (void *) myPoly, PM_FIT_POLYNOMIAL, 1, myStats, 2.0);
+    if (rc != NULL) {
+        printf("TEST ERROR: pmSubtractSky() returned a non-NULL pmReadout\n");
+        testStatus = false;
+    }
+    myReadout->image = tmpImageF32;
+
+    printf("----------------------------------------------------------------\n");
+    printf("Calling pmSubtractSky() with NULL fitSpec.  Should return image, no ERROR, no WARNING.\n\n");
+    rc = pmSubtractSky(myReadout, NULL, PM_FIT_POLYNOMIAL, 1, myStats, 2.0);
+    if (rc != myReadout) {
+        printf("TEST ERROR: pmSubtractSky() returned something other than pmReadout\n");
+        testStatus = false;
+    }
+
+    printf("----------------------------------------------------------------\n");
+    printf("Calling pmSubtractSky() with PM_FIT_NONE fit.  Should return image, no ERROR, no WARNING.\n\n");
+    rc = pmSubtractSky(myReadout, (void *) myPoly, PM_FIT_NONE, 1, myStats, 2.0);
+    if (rc != myReadout) {
+        printf("TEST ERROR: pmSubtractSky() returned something other than pmReadout\n");
+        testStatus = false;
+    }
+
+    printf("----------------------------------------------------------------\n");
+    printf("Calling pmSubtractSky() with PM_FIT_SPLINE fit.  Should return image, no ERROR, no WARNING.\n\n");
+    rc = pmSubtractSky(myReadout, (void *) myPoly, PM_FIT_SPLINE, 1, myStats, 2.0);
+    if (rc != myReadout) {
+        printf("TEST ERROR: pmSubtractSky() returned something other than pmReadout\n");
+        testStatus = false;
+    }
+
+    printf("----------------------------------------------------------------\n");
+    printf("Calling pmSubtractSky() with NULL myStats.  Should fit entire image, generate WARNING.\n\n");
+    rc = pmSubtractSky(myReadout, (void *) myPoly, PM_FIT_POLYNOMIAL, 1, NULL, 2.0);
+    for (i=0;i<NUM_ROWS_SMALL;i++) {
+        for (j=0;j<NUM_COLS_SMALL;j++) {
+            if (ERROR_TOLERANCE < fabs(rc->image->data.F32[i][j])) {
+                printf("TEST ERROR: image[%d][%d] is %f, should be 0.0\n", i, j,
+                       rc->image->data.F32[i][j]);
+                testStatus = false;
+            }
+        }
+    }
+
+    printf("----------------------------------------------------------------\n");
+    psU64 oldOptions = myStats->options;
+    myStats->options = 0;
+    printf("Calling pmSubtractSky() with no myStats->options specified.  Should fit entire image, generate WARNING.\n\n");
+    rc = pmSubtractSky(myReadout, (void *) myPoly, PM_FIT_POLYNOMIAL, 1, myStats, 2.0);
+    for (i=0;i<NUM_ROWS_SMALL;i++) {
+        for (j=0;j<NUM_COLS_SMALL;j++) {
+            if (ERROR_TOLERANCE < fabs(rc->image->data.F32[i][j])) {
+                printf("TEST ERROR: image[%d][%d] is %f, should be 0.0\n", i, j,
+                       rc->image->data.F32[i][j]);
+                testStatus = false;
+            }
+        }
+    }
+    myStats->options = oldOptions;
+
+    printf("----------------------------------------------------------------\n");
+    oldOptions = myStats->options;
+    myStats->options = PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN;
+    printf("Calling pmSubtractSky() with multiple myStats->options specified.  Should fit entire image, generate WARNING.\n\n");
+    rc = pmSubtractSky(myReadout, (void *) myPoly, PM_FIT_POLYNOMIAL, 1, myStats, 2.0);
+    for (i=0;i<NUM_ROWS_SMALL;i++) {
+        for (j=0;j<NUM_COLS_SMALL;j++) {
+            if (ERROR_TOLERANCE < fabs(rc->image->data.F32[i][j])) {
+                printf("TEST ERROR: image[%d][%d] is %f, should be 0.0\n", i, j,
+                       rc->image->data.F32[i][j]);
+                testStatus = false;
+            }
+        }
+    }
+    myStats->options = oldOptions;
+
+    printf("----------------------------------------------------------------\n");
+    printf("Calling pmSubtractSky() with 0 binFactor.  Should fit entire image, generate WARNING.\n\n");
+    rc = pmSubtractSky(myReadout, (void *) myPoly, PM_FIT_POLYNOMIAL, 0, myStats, 2.0);
+    for (i=0;i<NUM_ROWS_SMALL;i++) {
+        for (j=0;j<NUM_COLS_SMALL;j++) {
+            if (ERROR_TOLERANCE < fabs(rc->image->data.F32[i][j])) {
+                printf("TEST ERROR: image[%d][%d] is %f, should be 0.0\n", i, j,
+                       rc->image->data.F32[i][j]);
+                testStatus = false;
+            }
+        }
+    }
+
+    printf("----------------------------------------------------------------\n");
+    printf("Calling pmSubtractSky() with -1 binFactor.  Should fit entire image, generate WARNING.\n\n");
+    rc = pmSubtractSky(myReadout, (void *) myPoly, PM_FIT_POLYNOMIAL, -1, myStats, 2.0);
+    for (i=0;i<NUM_ROWS_SMALL;i++) {
+        for (j=0;j<NUM_COLS_SMALL;j++) {
+            if (ERROR_TOLERANCE < fabs(rc->image->data.F32[i][j])) {
+                printf("TEST ERROR: image[%d][%d] is %f, should be 0.0\n", i, j,
+                       rc->image->data.F32[i][j]);
+                testStatus = false;
+            }
+        }
+    }
+
+    printf("----------------------------------------------------------------\n");
+    printf("Calling pmSubtractSky() with -1.0 clipSD.  Should fit entire image, generate WARNING.\n\n");
+    rc = pmSubtractSky(myReadout, (void *) myPoly, PM_FIT_POLYNOMIAL, 1, myStats, -1.0);
+    for (i=0;i<NUM_ROWS_SMALL;i++) {
+        for (j=0;j<NUM_COLS_SMALL;j++) {
+            if (ERROR_TOLERANCE < fabs(rc->image->data.F32[i][j])) {
+                printf("TEST ERROR: image[%d][%d] is %f, should be 0.0\n", i, j,
+                       rc->image->data.F32[i][j]);
+                testStatus = false;
+            }
+        }
+    }
+
+    printf("----------------------------------------------------------------\n");
+    printf("Calling pmSubtractSky() with bogus psFit.  Should generate Error.\n\n");
+    rc = pmSubtractSky(myReadout, (void *) myPoly, 54321, 1, myStats, -1.0);
+    if (rc != myReadout) {
+        printf("TEST ERROR: pmSubtractSky() returned something other than pmReadout\n");
+        testStatus = false;
+    }
+
+
+    //    myReadout = pmSubtractSky(myReadout, (void *) myPoly, PM_FIT_POLYNOMIAL,
+    //                              1, myStats, 2.0);
+
+
+    printf("----------------------------------------------------------------\n");
+    psFree(myReadout);
+    psFree(myStats);
+    psFree(myPoly);
+    psFree(tmpImageF64);
+    printFooter(stdout, "pmSubtractSky", "Testing bad input parameter conditions.", true);
+    return(testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/extras/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/extras/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/extras/.cvsignore	(revision 22158)
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/extras/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/extras/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/extras/Makefile.am	(revision 22158)
@@ -0,0 +1,25 @@
+AM_CPPFLAGS = \
+	$(SRCINC) \
+	-I$(top_srcdir)/test/tap/src \
+	-I$(top_srcdir)/test/pstap/src \
+	$(PSMODULES_CFLAGS)
+
+AM_LDFLAGS = \
+	$(top_builddir)/src/libpsmodules.la  \
+	$(top_builddir)/test/tap/src/libtap.la \
+	$(top_builddir)/test/pstap/src/libpstap.la \
+	$(PSMODULES_LIBS)
+
+TEST_PROGS =
+
+if BUILD_TESTS
+bin_PROGRAMS = $(TEST_PROGS)
+TESTS = $(TEST_PROGS)
+else
+check_PROGRAMS = $(TEST_PROGS)
+endif
+
+CLEANFILES = $(check_DATA) temp/* core core.* *~ *.bb *.bbg *.da gmon.out
+
+test: check
+	$(top_srcdir)/test/test.pl
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/imcombine/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/imcombine/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/imcombine/.cvsignore	(revision 22158)
@@ -0,0 +1,8 @@
+.deps
+.libs
+Makefile
+Makefile.in
+temp
+tst_pmImageCombine
+tst_pmReadoutCombine
+tap_pmImageCombine
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/imcombine/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/imcombine/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/imcombine/Makefile.am	(revision 22158)
@@ -0,0 +1,28 @@
+AM_CPPFLAGS = \
+	$(SRCINC) \
+	-I$(top_srcdir)/test/tap/src \
+	-I$(top_srcdir)/test/pstap/src \
+	$(PSMODULES_CFLAGS)
+
+AM_LDFLAGS = \
+	$(top_builddir)/src/libpsmodules.la  \
+	$(top_builddir)/test/tap/src/libtap.la \
+	$(top_builddir)/test/pstap/src/libpstap.la \
+	$(PSMODULES_LIBS)
+
+TEST_PROGS =
+
+if BUILD_TESTS
+bin_PROGRAMS = $(TEST_PROGS)
+TESTS = $(TEST_PROGS)
+else
+check_PROGRAMS = $(TEST_PROGS)
+endif
+
+CLEANFILES = $(check_DATA) temp/* core core.* *~ *.bb *.bbg *.da gmon.out
+
+test: check
+	$(top_srcdir)/test/test.pl
+
+# Removed
+#	tap_pmImageCombine
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/imcombine/tap_pmImageCombine.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/imcombine/tap_pmImageCombine.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/imcombine/tap_pmImageCombine.c	(revision 22158)
@@ -0,0 +1,67 @@
+#include <stdio.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+
+#define NUM 10
+#define SIZE 100
+
+psArray *generate_images(void)
+{
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 12345);   // Random Number Generator
+
+    // Generate images
+    psArray *images = psArrayAlloc(NUM);// Array of images
+    for (int i = 0; i < NUM; i++) {
+        psImage *image = psImageAlloc(SIZE, SIZE, PS_TYPE_F32); // Image i
+        for (int y = 0; y < SIZE; y++) {
+            for (int x = 0; x < SIZE; x++) {
+                image->data.F32[y][x] = psRandomGaussian(rng);
+            }
+        }
+        images->data[i] = image;
+    }
+    psFree(rng);
+
+    return images;
+}
+
+int main(int argc, char *argv[])
+{
+    plan_tests(6);
+
+    diag("Image combination tests");
+
+    // Basic combination
+    {
+        psArray *images = generate_images();
+        psImage *combined = pmCombineImages(NULL, NULL, images, NULL, NULL, 0, NULL, 1, 3.0);
+        ok(combined, "Combined image generated");
+        skip_start(!combined, 5, "Combination failed.");
+
+        ok(combined->type.type == PS_TYPE_F32, "Correct type");
+        ok(combined->numCols == SIZE && combined->numRows == SIZE, "Correct size");
+        int discrepant = 0;             // Number of discrepant pixels
+        for (int y = 0; y < SIZE; y++)
+        {
+            for (int x = 0; x < SIZE; x++) {
+                if (fabsf(combined->data.F32[y][x]) > 3.0 / sqrt(NUM)) {
+                    discrepant++;
+                }
+            }
+        }
+        ok(discrepant <= 30, "%d discrepant pixels", discrepant); // Should have 99.7% of 100x100 pixels OK
+
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
+        psImageStats(stats, combined, NULL, 0);
+        ok(stats->sampleMean < 3.0 / sqrt(NUM * SIZE * SIZE), "Sample mean: %e", stats->sampleMean);
+        ok(fabs(stats->sampleStdev - 1.0 / sqrt(NUM)) < 1.0e-3, "Sample stdev: %e",
+           stats->sampleStdev);
+        psFree(stats);
+
+        skip_end();
+        psFree(combined);
+        psFree(images);
+    }
+
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/imcombine/tst_pmImageCombine.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/imcombine/tst_pmImageCombine.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/imcombine/tst_pmImageCombine.c	(revision 22158)
@@ -0,0 +1,365 @@
+/** @file tst_pmImageCombine.c
+ *
+ *  @brief Contains the tests for pmImageCombine.c:
+ *
+ *  test00: This code will test the various functions in the pmImageCombine.c file.
+ *
+ *  @author GLG, MHPCC
+ *
+ *  XXX: Must verify the results internally.  Don't use stdout file.
+ *  XXX: Must test masks with pmRejectPixels()
+ *
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-03-04 01:01:34 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#include "psTest.h"
+#include "pslib.h"
+#include "pmImageCombine.h"
+static int test00(void);
+testDescription tests[] = {
+                              {test00, 000, "pmCombineImages()", true, false},
+                              {NULL}
+                          };
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    return !runTestSuite(stderr, "Test Point Driver", tests, argc, argv);
+}
+
+psF32 genRanFloat(psF32 low,
+                  psF32 high)
+{
+    psF32 ran1 = (((psF32) (random() % 10000)) / 10000.0);
+    return(low + (ran1 * (high - low)));
+}
+
+psF32 genRanInt(psS32 low,
+                psS32 high)
+{
+    psF32 ran1 = (((psF32) (random() % 10000)) / 10000.0);
+    return((psS32) (low + (ran1 * (high - low))));
+}
+
+#define TST00_EXPANSION_FACTOR_X 1.0
+#define TST00_EXPANSION_FACTOR_Y 1.0
+#define TST00_OFFSET_X 0.0
+#define TST00_OFFSET_Y 0.0
+#define TST00_NUM_PIXELS 10
+#define TST00_MASK_VALUE 1
+#define TST00_NUM_ITERATIONS 4
+#define TST00_SIGMA_CLIP 1.0
+#define TST00_REJECTION_THRESHOLD 0.01
+#define TST00_GRADIENT_LIMIT 10.0
+/*******************************************************************************
+NOTE: This function returns FALSE if there were no errors.
+ ******************************************************************************/
+psBool testCombineImages(psS32 numRows,
+                         psS32 numCols,
+                         psS32 numImages)
+{
+    printf("Testing pmCombineImages(%d, %d, %d)\n", numRows, numCols, numImages);
+    bool testStatus = false;
+
+    psArray *images = psArrayAlloc(numImages);
+    psArray *errors = psArrayAlloc(numImages);
+    psArray *masks = psArrayAlloc(numImages);
+    images->n = images->nalloc;
+    errors->n = errors->nalloc;
+    masks->n = masks->nalloc;
+    for (psS32 i = 0 ; i < numImages ; i++) {
+        images->data[i] = (psPtr *) psImageAlloc(numCols, numRows, PS_TYPE_F32);
+        errors->data[i] = (psPtr *) psImageAlloc(numCols, numRows, PS_TYPE_F32);
+        masks->data[i] = (psPtr *) psImageAlloc(numCols, numRows, PS_TYPE_U8);
+        psImage *image = (psImage *) images->data[i];
+        psImage *error = (psImage *) errors->data[i];
+        psImage *mask = (psImage *) masks->data[i];
+        PS_IMAGE_SET_F32(image, 0.0);
+        PS_IMAGE_SET_F32(error, 1.0);
+        PS_IMAGE_SET_U8(mask, 0);
+
+        for (psS32 row = 0 ; row < numRows ; row++) {
+            for (psS32 col = 0 ; col < numCols ; col++) {
+                // Scale row/col to [-1.0:1.0]
+                psF32 rowScaled = ((psF32) (row - (numRows/2))) / ((psF32) (numRows/2));
+                psF32 colScaled = ((psF32) (col - (numCols/2))) / ((psF32) (numCols/2));
+                image->data.F32[row][col] = PS_SQR((2.0 - rowScaled) + (2.0 - colScaled)) + genRanFloat(0.0, 0.5);
+            }
+        }
+    }
+
+    //
+    // Same as above except the numImages is wrong
+    //
+    psArray *imagesLong = psArrayAlloc(numImages+1);
+    psArray *errorsLong = psArrayAlloc(numImages+1);
+    psArray *masksLong = psArrayAlloc(numImages+1);
+    imagesLong->n = imagesLong->nalloc;
+    errorsLong->n = errorsLong->nalloc;
+    masksLong->n = masksLong->nalloc;
+    for (psS32 i = 0 ; i < numImages+1 ; i++) {
+        imagesLong->data[i] = (psPtr *) psImageAlloc(numCols, numRows, PS_TYPE_F32);
+        errorsLong->data[i] = (psPtr *) psImageAlloc(numCols, numRows, PS_TYPE_F32);
+        masksLong->data[i] = (psPtr *) psImageAlloc(numCols, numRows, PS_TYPE_U8);
+        psImage *image = (psImage *) imagesLong->data[i];
+        psImage *error = (psImage *) errorsLong->data[i];
+        psImage *mask = (psImage *) masksLong->data[i];
+        PS_IMAGE_SET_F32(image, 0.0);
+        PS_IMAGE_SET_F32(error, 1.0);
+        PS_IMAGE_SET_U8(mask, 0);
+
+        for (psS32 row = 0 ; row < numRows ; row++) {
+            for (psS32 col = 0 ; col < numCols ; col++) {
+                // Scale row/col to [-1.0:1.0]
+                psF32 rowScaled = ((psF32) (row - (numRows/2))) / ((psF32) (numRows/2));
+                psF32 colScaled = ((psF32) (col - (numCols/2))) / ((psF32) (numCols/2));
+                image->data.F32[row][col] = PS_SQR((2.0 - rowScaled) + (2.0 - colScaled)) + genRanFloat(0.0, 0.5);
+            }
+        }
+    }
+
+    //
+    // Same as above except the type is wrong
+    //
+    psArray *imagesBadType = psArrayAlloc(numImages);
+    psArray *errorsBadType = psArrayAlloc(numImages);
+    psArray *masksBadType = psArrayAlloc(numImages);
+    imagesBadType->n = imagesBadType->nalloc;
+    errorsBadType->n = errorsBadType->nalloc;
+    masksBadType->n = masksBadType->nalloc;
+    for (psS32 i = 0 ; i < numImages ; i++) {
+        imagesBadType->data[i] = (psPtr *) psImageAlloc(numCols, numRows, PS_TYPE_F64);
+        errorsBadType->data[i] = (psPtr *) psImageAlloc(numCols, numRows, PS_TYPE_F64);
+        masksBadType->data[i] = (psPtr *) psImageAlloc(numCols, numRows, PS_TYPE_S8);
+        psImage *image = (psImage *) imagesBadType->data[i];
+        psImage *error = (psImage *) errorsBadType->data[i];
+        psImage *mask = (psImage *) masksBadType    ->data[i];
+        PS_IMAGE_SET_F32(image, 0.0);
+        PS_IMAGE_SET_F32(error, 1.0);
+        PS_IMAGE_SET_U8(mask, 0);
+
+        for (psS32 row = 0 ; row < numRows ; row++) {
+            for (psS32 col = 0 ; col < numCols ; col++) {
+                // Scale row/col to [-1.0:1.0]
+                psF32 rowScaled = ((psF32) (row - (numRows/2))) / ((psF32) (numRows/2));
+                psF32 colScaled = ((psF32) (col - (numCols/2))) / ((psF32) (numCols/2));
+                image->data.F32[row][col] = PS_SQR((2.0 - rowScaled) + (2.0 - colScaled)) + genRanFloat(0.0, 0.5);
+            }
+        }
+    }
+
+    psPixels *pixels = psPixelsAlloc(TST00_NUM_PIXELS);
+    pixels->n = pixels->nalloc;
+    for (psS32 p = 0 ; p < TST00_NUM_PIXELS ; p++) {
+        psS32 col =  genRanInt(0, numCols);
+        psS32 row =  genRanInt(0, numRows);
+        pixels->data[p].x = (psF32) col;
+        pixels->data[p].y = (psF32) row;
+        psS32 im = genRanInt(0, numImages-1);
+        psImage *image = (psImage *) images->data[im];
+        image->data.F32[row][col] += 100.0;
+        printf("Generating a bad pixel in image (%d) at (%d, %d)\n", im, row, col);
+    }
+
+    psArray *questionablePixels = NULL;
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+
+    //-------------------------------------------------------------------------
+    printf("Calling with a NULL images.  Should generate error, return NULL.\n");
+    psImage *outImg = pmCombineImages(NULL, &questionablePixels, NULL, errors,
+                                      masks, TST00_MASK_VALUE, pixels, TST00_NUM_ITERATIONS,
+                                      TST00_SIGMA_CLIP, stats);
+    if (outImg != NULL) {
+        printf("TEST ERROR: pmCombineImages() returned a non-NULL psImage.\n");
+        psFree(outImg);
+        testStatus = true;
+    }
+
+    //-------------------------------------------------------------------------
+    printf("Calling with a long images.  Should generate error, return NULL.\n");
+    outImg = pmCombineImages(NULL, &questionablePixels, imagesLong, errors,
+                             masks, TST00_MASK_VALUE, pixels, TST00_NUM_ITERATIONS,
+                             TST00_SIGMA_CLIP, stats);
+    if (outImg != NULL) {
+        printf("TEST ERROR: pmCombineImages() returned a non-NULL psImage.\n");
+        psFree(outImg);
+        testStatus = true;
+    }
+
+    //-------------------------------------------------------------------------
+    printf("Calling with a bad type images.  Should generate error, return NULL.\n");
+    outImg = pmCombineImages(NULL, &questionablePixels, imagesBadType, errors,
+                             masks, TST00_MASK_VALUE, pixels, TST00_NUM_ITERATIONS,
+                             TST00_SIGMA_CLIP, stats);
+    if (outImg != NULL) {
+        printf("TEST ERROR: pmCombineImages() returned a non-NULL psImage.\n");
+        psFree(outImg);
+        testStatus = true;
+    }
+
+    //-------------------------------------------------------------------------
+    printf("Calling with a long errors.  Should generate error, return NULL.\n");
+    outImg = pmCombineImages(NULL, &questionablePixels, images, errorsLong,
+                             masks, TST00_MASK_VALUE, pixels, TST00_NUM_ITERATIONS,
+                             TST00_SIGMA_CLIP, stats);
+    if (outImg != NULL) {
+        printf("TEST ERROR: pmCombineImages() returned a non-NULL psImage.\n");
+        psFree(outImg);
+        testStatus = true;
+    }
+
+    //-------------------------------------------------------------------------
+    printf("Calling with a bad type errors.  Should generate error, return NULL.\n");
+    outImg = pmCombineImages(NULL, &questionablePixels, images, errorsBadType,
+                             masks, TST00_MASK_VALUE, pixels, TST00_NUM_ITERATIONS,
+                             TST00_SIGMA_CLIP, stats);
+    if (outImg != NULL) {
+        printf("TEST ERROR: pmCombineImages() returned a non-NULL psImage.\n");
+        psFree(outImg);
+        testStatus = true;
+    }
+
+    //-------------------------------------------------------------------------
+    printf("Calling with a long masks.  Should generate error, return NULL.\n");
+    outImg = pmCombineImages(NULL, &questionablePixels, images, errors,
+                             masksLong, TST00_MASK_VALUE, pixels, TST00_NUM_ITERATIONS,
+                             TST00_SIGMA_CLIP, stats);
+    if (outImg != NULL) {
+        printf("TEST ERROR: pmCombineImages() returned a non-NULL psImage.\n");
+        psFree(outImg);
+        testStatus = true;
+    }
+
+    //-------------------------------------------------------------------------
+    printf("Calling with a bad type masks.  Should generate error, return NULL.\n");
+    outImg = pmCombineImages(NULL, &questionablePixels, images, errors,
+                             masksBadType, TST00_MASK_VALUE, pixels, TST00_NUM_ITERATIONS,
+                             TST00_SIGMA_CLIP, stats);
+    if (outImg != NULL) {
+        printf("TEST ERROR: pmCombineImages() returned a non-NULL psImage.\n");
+        psFree(outImg);
+        testStatus = true;
+    }
+
+    //-------------------------------------------------------------------------
+    printf("Calling with a NULL stats.  Should generate error, return NULL.\n");
+    outImg = pmCombineImages(NULL, &questionablePixels, images, errors,
+                             masks, TST00_MASK_VALUE, pixels, TST00_NUM_ITERATIONS,
+                             TST00_SIGMA_CLIP, NULL);
+    if (outImg != NULL) {
+        printf("TEST ERROR: pmCombineImages() returned a non-NULL psImage.\n");
+        psFree(outImg);
+        testStatus = true;
+    }
+
+    //-------------------------------------------------------------------------
+    printf("Calling with acceptable data.  Should generate a psImage.\n");
+    outImg = pmCombineImages(NULL, &questionablePixels, images, errors,
+                             masks, TST00_MASK_VALUE, pixels, TST00_NUM_ITERATIONS,
+                             TST00_SIGMA_CLIP, stats);
+    if (outImg == NULL) {
+        printf("TEST ERROR: pmCombineImages() returned a NULL psImage.\n");
+        testStatus = true;
+    }
+    if (0) {
+        for (psS32 p = 0 ; p < TST00_NUM_PIXELS ; p++) {
+            psS32 col = (psS32) (pixels->data[p]).x;
+            psS32 row = (psS32) (pixels->data[p]).y;
+            printf("------------------------------------------\n");
+            printf("Pixel (%d, %d) in combined image is %f\n", row, col, outImg->data.F32[row][col]);
+            for (psS32 i = 0 ; i < numImages ; i++) {
+                psImage *image = (psImage *) images->data[i];
+                printf("Pixel (after combine) (%d, %d) in image (%d) is %f\n", row, col, i, image->data.F32[row][col]);
+            }
+        }
+    }
+
+    if (questionablePixels->n != numImages) {
+        printf("TEST ERROR: pmCombineImages(): questionablePixels->n was %ld, should have been %d\n",
+               questionablePixels->n, numImages);
+        testStatus = true;
+    } else {
+        // XXX: We should internally verify this with the pixels list, not merely use the stdout.
+        for (psS32 i = 0 ; i < questionablePixels->n ; i++) {
+            psPixels *myPixels = (psPixels *) questionablePixels->data[i];
+            for (psS32 p = 0 ; p < myPixels->n ; p++) {
+                printf("Image %d, questionable pixel %d is (%f %f)\n",
+                       i, p, myPixels->data[p].y, myPixels->data[p].x);
+            }
+        }
+    }
+
+    psArray *expandTransforms = psArrayAlloc(numImages);
+    psArray *contractTransforms = psArrayAlloc(numImages);
+    expandTransforms->n = expandTransforms->nalloc;
+    contractTransforms->n = contractTransforms->nalloc;
+    for (psS32 im = 0 ; im < numImages ; im++) {
+        psPlaneTransform *ptExpand = psPlaneTransformAlloc(2, 2);
+        ptExpand->x->coeff[0][0] = TST00_OFFSET_X;
+        ptExpand->x->coeff[1][0] = TST00_EXPANSION_FACTOR_X;
+        ptExpand->y->coeff[0][0] = TST00_OFFSET_Y;
+        ptExpand->y->coeff[0][1] = TST00_EXPANSION_FACTOR_Y;
+        expandTransforms->data[im] = (psPtr *) ptExpand;
+
+        psPlaneTransform *ptContract = psPlaneTransformAlloc(2, 2);
+        ptContract->x->coeff[0][0] = -TST00_OFFSET_X;
+        ptContract->x->coeff[1][0] = 1.0 / TST00_EXPANSION_FACTOR_X;
+        ptContract->y->coeff[0][0] = -TST00_OFFSET_Y;
+        ptContract->y->coeff[0][1] = 1.0 / TST00_EXPANSION_FACTOR_Y;
+        contractTransforms->data[im] = (psPtr *) ptContract;
+    }
+
+    //-------------------------------------------------------------------------
+    //
+    // XXX: psRejectPixels() has known bugs.  Specifically, in the psImageTransform() call.
+    // We exclude this from our tests.
+    //
+    printf("\n\n\nCalling pmRejectPixels() with acceptable data.  Should generate a psArray.\n");
+    psArray *pixelRejects = pmRejectPixels(images, NULL, questionablePixels, expandTransforms,
+                                           contractTransforms, TST00_REJECTION_THRESHOLD,
+                                           TST00_GRADIENT_LIMIT);
+    if (pixelRejects == NULL) {
+        printf("TEST ERROR: pmRejectPixels() returned a NULL psArray.\n");
+        testStatus = true;
+    } else {
+        // XXX: We should internally verify this with the pixels list, not merely use the stdout.
+        for (psS32 i = 0 ; i < pixelRejects->n ; i++) {
+            psPixels *myPixels = (psPixels *) pixelRejects->data[i];
+            printf("tst_pmImageCombine.c: Image %d had %ld rejects.\n", i, myPixels->n);
+
+            for (psS32 p = 0 ; p < myPixels->n ; p++) {
+                printf("Image %d, rejected pixel %d is (%f %f)\n", i, p,
+                       myPixels->data[p].y, myPixels->data[p].x);
+            }
+        }
+        psFree(pixelRejects);
+    }
+
+    psFree(images);
+    psFree(errors);
+    psFree(masks);
+    psFree(imagesLong);
+    psFree(errorsLong);
+    psFree(masksLong);
+    psFree(imagesBadType);
+    psFree(errorsBadType);
+    psFree(masksBadType);
+    psFree(pixels);
+    psFree(stats);
+
+    return(testStatus);
+}
+
+/*******************************************************************************
+NOTE: This function returns TRUE if there were no errors.
+ ******************************************************************************/
+int test00( void )
+{
+    bool testStatus = false;
+
+    testStatus|= testCombineImages(10, 10, 5);
+
+    return(!testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/imcombine/tst_pmImageSubtract.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/imcombine/tst_pmImageSubtract.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/imcombine/tst_pmImageSubtract.c	(revision 22158)
@@ -0,0 +1,847 @@
+/** @file tst_pmImageSubtract.c
+ *
+ *  @brief Contains the tests for pmImageSubtract.c:
+ *
+ *  test00: This code will test the various functions in pmObjects.c
+ *
+ *  @author GLG, MHPCC
+ *
+ *  XXX: Most test simply ensure that the functions can be called with allowable
+ *  data.  More work need to be done to verify the results.
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-05-25 22:02:46 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#include "psTest.h"
+#include "pslib.h"
+#include "pmImageSubtract.h"
+#define ERROR_TOLERANCE 1.0
+static int test00(void);
+static int test01(void);
+static int test02(void);
+static int test03(void);
+testDescription tests[] = {
+                              {test00, 000, "pmSubtractionKernelsAllocPOIS()", true, false},
+                              {test01, 000, "pmSubtractionKernelsAllocISIS()", true, false},
+                              {test02, 000, "pmSubtractionFindStamps()", true, false},
+                              {test03, 000, "pmSubtractionCalculateEquation()", true, false},
+                              {NULL}
+                          };
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    return !runTestSuite(stderr, "Test Point Driver", tests, argc, argv);
+}
+
+
+/*******************************************************************************
+NOTE: This function returns FALSE if there were no errors.
+ 
+XXX: Call with various unallowable input parameters.
+ 
+XXX: Untested: we don't loop through the (u, v, xOrder, yOrder) psVectors and
+ensure that each value is set correctly.
+ ******************************************************************************/
+psBool testPOISAlloc(psS32 size,
+                     psS32 SpatialOrder)
+{
+    printf("Testing pmSubtractionKernelsAllocPOIS(%d, %d)\n", size, SpatialOrder);
+
+    bool testStatus = false;
+    psS32 nBasisFunctions = (2 * size + 1) * (2 * size + 1) * (SpatialOrder + 1) * (SpatialOrder + 2) / 2;
+
+    psSubtractionKernels *kernels = pmSubtractionKernelsAllocPOIS(size, SpatialOrder);
+    if (kernels == NULL) {
+        printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() returned a NULL psSubtractionKernels.\n");
+        testStatus = true;
+    } else {
+        if (kernels->type != PM_SUBTRACTION_KERNEL_POIS) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated the wrong kernels->type.\n");
+            testStatus = true;
+        }
+
+        if ((kernels->u == NULL) ||
+                (kernels->u->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a NULL ->u member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a incorrect length ->u member.\n");
+            testStatus = true;
+        }
+
+        if ((kernels->v == NULL) ||
+                (kernels->v->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a NULL ->v member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a incorrect length ->v member.\n");
+            testStatus = true;
+        }
+
+        if (kernels->sigma != NULL) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a non-NULL ->sigma member.\n");
+            testStatus = true;
+        }
+
+        if ((kernels->xOrder == NULL) ||
+                (kernels->xOrder->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a NULL ->xOrder member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a incorrect length ->xOrder member.\n");
+            testStatus = true;
+        }
+
+        if ((kernels->yOrder == NULL) ||
+                (kernels->yOrder->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a NULL ->yOrder member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a incorrect length ->yOrder member.\n");
+            testStatus = true;
+        }
+
+        if (kernels->subIndex != 0) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a non-zero ->subIndex member (%d).\n", kernels->subIndex);
+            testStatus = true;
+        }
+
+        psS32 i = kernels->subIndex;
+        if ((kernels->u->data.F32[i] != 0) ||
+                (kernels->v->data.F32[i] != 0)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS(): the ->subIndex member points to a kernel with (%f, %f) (u, v) basis function.\n",
+                   kernels->u->data.F32[i], kernels->v->data.F32[i]);
+            testStatus = true;
+        }
+
+        if (kernels->preCalc != NULL) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a non-NULL ->preCalc member.\n");
+            testStatus = true;
+        }
+
+        if (kernels->size != size) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated an incorrect ->size member (%d).\n", kernels->size);
+            testStatus = true;
+        }
+
+        if (kernels->spatialOrder != SpatialOrder) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated an incorrect ->spatialOrder member (%d).\n", kernels->spatialOrder);
+            testStatus = true;
+        }
+    }
+    psFree(kernels);
+    return(testStatus);
+}
+
+/*******************************************************************************
+NOTE: This function returns TRUE if there were no errors.
+ ******************************************************************************/
+int test00( void )
+{
+    bool testStatus = false;
+
+    testStatus|= testPOISAlloc(1, 1);
+    testStatus|= testPOISAlloc(2, 3);
+    testStatus|= testPOISAlloc(3, 4);
+
+    return(!testStatus);
+}
+
+/*******************************************************************************
+NOTE: This function returns FALSE if there were no errors.
+ 
+XXX: Call with various unallowable input parameters.
+ 
+XXX: Untested: we don't loop through the (u, v, xOrder, yOrder) psVectors and
+ensure that each value is set correctly.  We don't ensure that he preCalc
+psImages are set correctly.
+ ******************************************************************************/
+psBool testISISAlloc(psS32 sigmaLength,
+                     psS32 orderLength,
+                     psS32 size,
+                     psS32 SpatialOrder)
+{
+    printf("Testing pmSubtractionKernelsAllocISIS(%d, %d, %d, %d)\n",
+           sigmaLength, orderLength, size, SpatialOrder);
+
+    psVector *sigmas = psVectorAlloc(sigmaLength, PS_TYPE_F32);
+    sigmas->n = sigmas->nalloc;
+    for (psS32 i = 0 ; i < sigmas->n ; i++) {
+        sigmas->data.F32[i] = 1.0 + (psF32) i;
+    }
+    psVector *orders = psVectorAlloc(orderLength, PS_TYPE_S32);
+    orders->n = orders->nalloc;
+    for (psS32 i = 0 ; i < orders->n ; i++) {
+        orders->data.S32[i] = i + 2;
+    }
+
+    bool testStatus = false;
+    psS32 numSigmas = sigmas->n;
+    psS32 nBasisFunctions = 0;
+    for (psS32 s = 0 ; s < numSigmas ; s++) {
+        for (psS32 o = 0 ; o < orders->n ; o++) {
+            nBasisFunctions+= ((orders->data.S32[o] + 1) * (orders->data.S32[o] + 2) / 2);
+        }
+    }
+    nBasisFunctions*= ((SpatialOrder + 1) * (SpatialOrder + 2) / 2);
+
+    psSubtractionKernels *kernels = pmSubtractionKernelsAllocISIS(sigmas, orders, size, SpatialOrder);
+    if (kernels == NULL) {
+        printf("TEST ERROR: pmSubtractionKernelsAllocISIS() returned a NULL psSubtractionKernels.\n");
+        testStatus = true;
+    } else {
+        if (kernels->type != PM_SUBTRACTION_KERNEL_ISIS) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated the wrong kernels->type.\n");
+            testStatus = true;
+        }
+
+        if ((kernels->u == NULL) ||
+                (kernels->u->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a NULL ->u member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a incorrect length ->u member.\n");
+            testStatus = true;
+        }
+
+        if ((kernels->v == NULL) ||
+                (kernels->v->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a NULL ->v member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a incorrect length ->v member.\n");
+            testStatus = true;
+        }
+
+        if ((kernels->sigma == NULL) ||
+                (kernels->sigma->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a NULL ->sigma member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a incorrect length ->sigma member.\n");
+            testStatus = true;
+        }
+
+        if ((kernels->xOrder == NULL) ||
+                (kernels->xOrder->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a NULL ->xOrder member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a incorrect length ->xOrder member.\n");
+            testStatus = true;
+        }
+
+        if ((kernels->yOrder == NULL) ||
+                (kernels->yOrder->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a NULL ->yOrder member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a incorrect length ->yOrder member.\n");
+            testStatus = true;
+        }
+
+        if (kernels->subIndex != 0) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a non-zero ->subIndex member (%d).\n", kernels->subIndex);
+            testStatus = true;
+        }
+
+        //
+        // Ensure that kernels->subIndex points to the correct kernel.
+        //
+        psS32 i = kernels->subIndex;
+        if ((kernels->u->data.F32[i] != 0.0) ||
+                (kernels->v->data.F32[i] != 0.0) ||
+                (kernels->xOrder->data.F32[i] != 0.0) ||
+                (kernels->yOrder->data.F32[i] != 0.0) ||
+                (kernels->sigma->data.F32[i] != sigmas->data.F32[0])) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS(): the ->subIndex member points to the wrong kernel.\n");
+            printf("TEST ERROR: (u, v, xOrder, yOrder, sigma) is (%f, %f, %f, %f, %f).\n",
+                   kernels->u->data.F32[i], kernels->v->data.F32[i],
+                   kernels->xOrder->data.F32[i], kernels->yOrder->data.F32[i],
+                   kernels->sigma->data.F32[i]);
+            testStatus = true;
+        }
+
+        //
+        // Ensure that the preCalc images are allocated correctly.
+        //
+        if ((kernels->preCalc == NULL) ||
+                (kernels->preCalc->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a NULL ->preCalc member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a incorrect length ->preCalc member.\n");
+            testStatus = true;
+        } else {
+            for (psS32 k = 0 ; k < kernels->u->n ; k++) {
+                psImage *kerImg = (psImage *) kernels->preCalc->data[k];
+                if (kerImg == NULL) {
+                    printf("TEST ERROR: the %d-th kernel preCalc image is NULL.\n", k);
+                    testStatus = true;
+                } else {
+                    if (kerImg->type.type != PS_TYPE_F32) {
+                        printf("TEST ERROR: preCalc image %d had ioncorrect type.\n", k);
+                        testStatus = true;
+                    }
+                    if ((kerImg->numRows != (1 + (2 * size))) ||
+                            (kerImg->numCols != (1 + (2 * size)))) {
+                        printf("TEST ERROR: preCalc image %d had incorrect size (%d, %d).\n", k,
+                               kerImg->numRows, kerImg->numCols);
+                        testStatus = true;
+                    }
+                }
+            }
+        }
+
+        if (kernels->size != size) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated an incorrect ->size member (%d).\n", kernels->size);
+            testStatus = true;
+        }
+
+        if (kernels->spatialOrder != SpatialOrder) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated an incorrect ->spatialOrder member (%d).\n", kernels->spatialOrder);
+            testStatus = true;
+        }
+    }
+    psFree(sigmas);
+
+    psFree(kernels->u);
+    psFree(kernels->v);
+    psFree(kernels->sigma);
+    psFree(kernels->xOrder);
+    psFree(kernels->yOrder);
+    psFree(kernels->preCalc);
+    psFree(kernels);
+    psFree(orders);
+    return(testStatus);
+}
+
+/*******************************************************************************
+NOTE: This function returns TRUE if there were no errors.
+ ******************************************************************************/
+int test01( void )
+{
+    bool testStatus = false;
+
+    /*
+        testStatus|= testISISAlloc(1, 1, 1, 1);
+        testStatus|= testISISAlloc(2, 2, 2, 2);
+        testStatus|= testISISAlloc(2, 3, 4, 5);
+        testStatus|= testISISAlloc(3, 4, 5, 6);
+    */
+
+    return(!testStatus);
+}
+
+
+/*******************************************************************************
+NOTE: This function returns FALSE if there were no errors.
+ 
+XXX: Can we test to ensure that no stamps overlap?
+ 
+XXX: Test stamp alloc/dealloc functions.
+ ******************************************************************************/
+#define TST02_THRESHOLD 3.0
+#define TST02_MASK_VAL 1
+psBool testFindStamps(psS32 numCols,
+                      psS32 numRows,
+                      psS32 xNum,
+                      psS32 yNum,
+                      psS32 border)
+{
+    printf("Testing pmSubtractionFindStamps(%d, %d, %d, %d, %d)\n",
+           numCols, numRows, xNum, yNum, border);
+    bool testStatus = false;
+
+    // Create a test image and set a single pixel in the center of each stamp.
+    psImage *tstImg = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    int numStamps = 0;
+    PS_IMAGE_SET_F32(tstImg, 0.0);
+    for (psS32 j = 0; j < yNum; j++) {
+        for (psS32 i = 0; i < xNum; i++) {
+            psS32 yMin = border + j * (numRows - 2.0 * border) / yNum;
+            psS32 yMax = PS_MIN(numRows-1, (border + (j + 1) * (numRows - 2.0 * border) / yNum) - 1);
+            psS32 xMin = border + i * (numCols - 2.0 * border) / xNum;
+            psS32 xMax = PS_MIN(numCols-1, (border + (i + 1) * (numCols - 2.0 * border) / xNum) - 1);
+
+            tstImg->data.F32[(yMax+yMin)/2][(xMax+xMin)/2] = TST02_THRESHOLD + (psF32) (i + j);
+            numStamps++;
+        }
+    }
+    psImage *tmpMask= psImageAlloc(numCols, numRows, PS_TYPE_U8);
+    PS_IMAGE_SET_U8(tstImg, 0);
+
+    //-------------------------------------------------------------------------
+    printf("Calling with a NULL psImage.  Should generate error, return NULL.\n");
+    psArray *stamps = pmSubtractionFindStamps(NULL, NULL, tmpMask, TST02_MASK_VAL,
+                      TST02_THRESHOLD, xNum, yNum,
+                      border);
+    if (stamps != NULL) {
+        printf("TEST ERROR: pmSubtractionFindStamps returned a non-NULL psArray.\n");
+        psFree(stamps);
+        testStatus = true;
+    }
+
+    //-------------------------------------------------------------------------
+    printf("Calling with a non-positive xNum.  Should generate error, return NULL.\n");
+    stamps = pmSubtractionFindStamps(NULL, tstImg, tmpMask, TST02_MASK_VAL,
+                                     TST02_THRESHOLD, 0, yNum,
+                                     border);
+    if (stamps != NULL) {
+        printf("TEST ERROR: pmSubtractionFindStamps returned a non-NULL psArray.\n");
+        psFree(stamps);
+        testStatus = true;
+    }
+
+    //-------------------------------------------------------------------------
+    printf("Calling with a non-positive yNum.  Should generate error, return NULL.\n");
+    stamps = pmSubtractionFindStamps(NULL, tstImg, tmpMask, TST02_MASK_VAL,
+                                     TST02_THRESHOLD, xNum, 0,
+                                     border);
+    if (stamps != NULL) {
+        printf("TEST ERROR: pmSubtractionFindStamps returned a non-NULL psArray.\n");
+        psFree(stamps);
+        testStatus = true;
+    }
+
+    //-------------------------------------------------------------------------
+    printf("Calling with a non-positive border.  Should generate error, return NULL.\n");
+    stamps = pmSubtractionFindStamps(NULL, tstImg, tmpMask, TST02_MASK_VAL,
+                                     TST02_THRESHOLD, xNum, yNum,
+                                     0);
+    if (stamps != NULL) {
+        printf("TEST ERROR: pmSubtractionFindStamps returned a non-NULL psArray.\n");
+        psFree(stamps);
+        testStatus = true;
+    }
+
+    //-------------------------------------------------------------------------
+    printf("Calling with acceptable input parameters, non-NULL mask.\n");
+    stamps = pmSubtractionFindStamps(NULL, tstImg, tmpMask, TST02_MASK_VAL,
+                                     TST02_THRESHOLD, xNum, yNum,
+                                     border);
+    if (stamps == NULL) {
+        printf("TEST ERROR: pmSubtractionFindStamps returned a non-NULL psArray.\n");
+        testStatus = true;
+    } else {
+        if (stamps->n != numStamps) {
+            printf("TEST ERROR: %ld stamps were found, %d were expected.\n",
+                   stamps->n, numStamps);
+            testStatus = true;
+        }
+        for (psS32 s = 0 ; s < stamps->n ; s++) {
+            pmStamp *stamp = (pmStamp *) stamps->data[s];
+            psS32 row = stamp->y;
+            psS32 col = stamp->x;
+            // printf("Stamp %d at (%d, %d) has a value of %f\n", s, row, col, tstImg->data.F32[row][col]);
+            if (tstImg->data.F32[row][col] < TST02_THRESHOLD) {
+                if (stamp->status != PM_STAMP_NONE) {
+                    printf("TEST ERROR: stamp %d had peak value %f (below theshold) and the status was not set to PM_STAMP_NONE.\n",
+                           s, tstImg->data.F32[row][col]);
+                    testStatus = true;
+                }
+            } else {
+                if (stamp->status != PM_STAMP_RECALC) {
+                    printf("TEST ERROR: stamp %d had peak value %f (above theshold) and the status was not set to PM_STAMP_RECALC.\n",
+                           s, tstImg->data.F32[row][col]);
+                    testStatus = true;
+                }
+            }
+        }
+    }
+    psFree(stamps);
+
+    //-------------------------------------------------------------------------
+    printf("Calling with acceptable input parameters, NULL mask.\n");
+    stamps = pmSubtractionFindStamps(NULL, tstImg, NULL, TST02_MASK_VAL,
+                                     TST02_THRESHOLD, xNum, yNum,
+                                     border);
+    if (stamps == NULL) {
+        printf("TEST ERROR: pmSubtractionFindStamps returned a non-NULL psArray.\n");
+        testStatus = true;
+    } else {
+        if (stamps->n != numStamps) {
+            printf("TEST ERROR: %ld stamps were found, %d were expected.\n",
+                   stamps->n, numStamps);
+            testStatus = true;
+        }
+        for (psS32 s = 0 ; s < stamps->n ; s++) {
+            pmStamp *stamp = (pmStamp *) stamps->data[s];
+            psS32 row = stamp->y;
+            psS32 col = stamp->x;
+            //printf("Stamp %d at (%d, %d) has a value of %f\n", s, row, col, tstImg->data.F32[row][col]);
+            if (tstImg->data.F32[row][col] < TST02_THRESHOLD) {
+                if (stamp->status != PM_STAMP_NONE) {
+                    printf("TEST ERROR: stamp %d had peak value %f (below theshold) and the status was not set to PM_STAMP_NONE.\n",
+                           s, tstImg->data.F32[row][col]);
+                    testStatus = true;
+                }
+            } else {
+                if (stamp->status != PM_STAMP_RECALC) {
+                    printf("TEST ERROR: stamp %d had peak value %f (above theshold) and the status was not set to PM_STAMP_RECALC.\n",
+                           s, tstImg->data.F32[row][col]);
+                    testStatus = true;
+                }
+            }
+        }
+    }
+
+    psFree(tstImg);
+    psFree(tmpMask);
+    psFree(stamps);
+
+    return(testStatus);
+}
+
+
+
+/*******************************************************************************
+NOTE: This function returns TRUE if there were no errors.
+ ******************************************************************************/
+int test02( void )
+{
+    bool testStatus = false;
+
+    testStatus|= testFindStamps(100, 100, 2, 2, 2);
+    testStatus|= testFindStamps(100, 100, 10, 10, 2);
+
+    return(!testStatus);
+}
+
+
+psF32 genRanFloat(psF32 low,
+                  psF32 high)
+{
+    psF32 ran1 = (((psF32) (random() % 10000)) / 10000.0);
+    return(low + (ran1 * (high - low)));
+}
+
+//
+// XXX: POIS kernels are producing NANs if the image size is 20 or less.
+//
+// XXX: ISIS kernels are producing NANS if the TST03_ORDER_LENGTH is 2 or larger.
+//
+#define TST03_THRESHOLD  3.0
+#define TST03_MASK_VAL  1
+#define TST03_KERNEL_SIZE 2
+#define TST03_SPATIAL_ORDER 2
+#define TST03_ORDER_LENGTH 1
+#define TST03_SIGMA_LENGTH 1
+#define TST03_PSF_MAX  10.0
+#define TST03_BG 0.0
+#define TST03_IMAGE_SIZE 25
+#define TST03_NUM_COLS  TST03_IMAGE_SIZE
+#define TST03_NUM_ROWS  TST03_IMAGE_SIZE
+#define TST03_NUM_STAMPS 2
+#define TST03_NUM_STAMPS_COLS TST03_NUM_STAMPS
+#define TST03_NUM_STAMPS_ROWS TST03_NUM_STAMPS
+#define TST03_BORDER  TST03_KERNEL_SIZE
+//#define TST03_FOOTPRINT (((TST03_IMAGE_SIZE - (2 * TST03_BORDER)) / TST03_NUM_STAMPS) - TST03_KERNEL_SIZE)
+#define TST03_FOOTPRINT  4
+#define TST03_PSF_WIDTH  (TST03_FOOTPRINT/2 - 1)
+
+/*******************************************************************************
+This routine generates an object in the center of the stamp defined by the
+(xMin, xMax) and (yMin, yMax) boundary.
+ ******************************************************************************/
+psBool genObject(psImage *tstImg,
+                 psImage *refImg,
+                 psS32 xMin,
+                 psS32 xMax,
+                 psS32 yMin,
+                 psS32 yMax)
+{
+    if (((1 + 2 * TST03_PSF_WIDTH) > (xMax - xMin)) ||
+            ((1 + 2 * TST03_PSF_WIDTH) > (yMax - yMin))) {
+        printf("INCORRECT TEST CONFIGURATION: TST03_PSF_WIDTH is too big.\n");
+        printf("TST03_PSF_WIDTH is %d: (xMin - xMax) is %d\n", TST03_PSF_WIDTH, (xMax - xMin));
+        return(FALSE);
+    }
+    //
+    // This code basically creates a peak at the center of the stamp with
+    // a height of TST03_PSF_MAX
+    //
+    psS32 xCenter = (xMax + xMin) / 2;
+    psS32 yCenter = (yMax + yMin) / 2;
+    psF32 subImageWidth = 1.0 + sqrtf(PS_SQR(((psF32) ((yMax-yMin)/2))) + PS_SQR(((psF32) ((xMax-xMin)/2))));
+    for (psS32 y = yMin ; y <= yMax ; y++) {
+        for (psS32 x = xMin ; x <= xMax ; x++) {
+            psF32 dist = sqrtf(PS_SQR((psF32) (y - yCenter)) + PS_SQR((psF32) (x - xCenter)));
+            psF32 pixel = TST03_PSF_MAX * PS_SQR(((psF32) (subImageWidth - dist)) / ((psF32) subImageWidth));
+            if (pixel < 0.0) {
+                pixel = 0.0;
+            }
+            refImg->data.F32[y][x] = pixel + TST03_BG;
+            tstImg->data.F32[y][x] = pixel + TST03_BG;
+            // Add some noise for the test image.
+            tstImg->data.F32[y][x]+= genRanFloat(0.0, 1.0);
+        }
+    }
+
+    return(TRUE);
+}
+
+/*******************************************************************************
+NOTE: This function returns FALSE if there were no errors.
+ 
+XXX: We should use a larger variety of input parameter configurations.
+ 
+I test the following functions here (since they linearly rely on a set of data
+structures that the previoues ones generate):
+    pmSubtractionCalculateEquation()
+    pmSubtractionSolveEquation()
+    pmSubtractionRejectStamps()
+    pmSubtractionKernelImage()
+ ******************************************************************************/
+psBool testSubCalcEqu(psS32 numCols,
+                      psS32 numRows,
+                      psS32 xNum,
+                      psS32 yNum,
+                      psS32 border,
+                      pmSubtractionKernelsType KernelType)
+{
+    printf("Testing pmSubtractionCalculateEquation(): \n");
+    printf("    image size is (%d, %d)\n", numRows, numCols);
+    printf("    num stamps is (%d, %d).  Border is %d\n", yNum, xNum, border);
+    if (KernelType == PM_SUBTRACTION_KERNEL_POIS) {
+        printf("   kernel type is PM_SUBTRACTION_KERNEL_POIS.\n");
+    } else if (KernelType == PM_SUBTRACTION_KERNEL_ISIS) {
+        printf("   kernel type is PM_SUBTRACTION_KERNEL_ISIS.\n");
+    }
+    bool testStatus = false;
+
+    // Create a test image and set a single pixel in the center of each stamp.
+    psImage *tstImg = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    psImage *refImg = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    psImage *maskImg = psImageAlloc(numCols, numRows, PS_TYPE_U8);
+    PS_IMAGE_SET_F32(tstImg, 0.0);
+    PS_IMAGE_SET_F32(maskImg, 0);
+    for (psS32 j = 0; j < yNum; j++) {
+        for (psS32 i = 0; i < xNum; i++) {
+            psS32 yMin = border + j * (numRows - 2.0 * border) / yNum;
+            psS32 yMax = PS_MIN(numRows-1, (border + (j + 1) * (numRows - 2.0 * border) / yNum) - 1);
+            psS32 xMin = border + i * (numCols - 2.0 * border) / xNum;
+            psS32 xMax = PS_MIN(numCols-1, (border + (i + 1) * (numCols - 2.0 * border) / xNum) - 1);
+
+            genObject(tstImg, refImg, xMin, xMax, yMin, yMax);
+        }
+    }
+    printf("Generating stamps...\n");
+    psArray *stamps = pmSubtractionFindStamps(NULL, tstImg, NULL, TST03_MASK_VAL,
+                      TST03_THRESHOLD, xNum, yNum,
+                      border);
+
+    //
+    // PsVectors sigmas and orders are for ISIS kernels only.
+    //
+    psVector *sigmas = psVectorAlloc(TST03_SIGMA_LENGTH, PS_TYPE_F32);
+    sigmas->n = sigmas->nalloc;
+    for (psS32 i = 0 ; i < sigmas->n ; i++) {
+        sigmas->data.F32[i] = 1.0 + (psF32) i;
+    }
+    psVector *orders = psVectorAlloc(TST03_ORDER_LENGTH, PS_TYPE_S32);
+    orders->n = orders->nalloc;
+    for (psS32 i = 0 ; i < orders->n ; i++) {
+        orders->data.S32[i] = i + 2;
+    }
+
+    //
+    // Create the subtraction kernels
+    //
+    printf("Generating kernel basis functions...\n");
+    psSubtractionKernels *myKernels = NULL;
+    if (KernelType == PM_SUBTRACTION_KERNEL_POIS) {
+        myKernels = pmSubtractionKernelsAllocPOIS(TST03_KERNEL_SIZE, TST03_SPATIAL_ORDER);
+    } else if (KernelType == PM_SUBTRACTION_KERNEL_ISIS) {
+        myKernels = pmSubtractionKernelsAllocISIS(sigmas, orders, TST03_KERNEL_SIZE, TST03_SPATIAL_ORDER);
+    }
+
+    if ((stamps == NULL) ||
+            (myKernels == NULL)) {
+        printf("TEST ERROR: stamps or myKernels is NULL.\n");
+        testStatus = true;
+    } else {
+        //-------------------------------------------------------------------------
+        printf("Calling with a NULL psArray stamps.  Should generate error, return FALSE.\n");
+        psBool rc = pmSubtractionCalculateEquation(NULL, refImg, tstImg, myKernels, TST03_FOOTPRINT);
+        if (rc == TRUE) {
+            printf("TEST ERROR: pmSubtractionCalculateEquation() returned TRUE.\n");
+            testStatus = true;
+        }
+
+        //-------------------------------------------------------------------------
+        printf("Calling with a NULL reference images.  Should generate error, return FALSE.\n");
+        rc = pmSubtractionCalculateEquation(stamps, NULL, tstImg, myKernels, TST03_FOOTPRINT);
+        if (rc == TRUE) {
+            printf("TEST ERROR: pmSubtractionCalculateEquation() returned TRUE.\n");
+            testStatus = true;
+        }
+
+        //-------------------------------------------------------------------------
+        printf("Calling with a NULL input images.  Should generate error, return FALSE.\n");
+        rc = pmSubtractionCalculateEquation(stamps, refImg, NULL, myKernels, TST03_FOOTPRINT);
+        if (rc == TRUE) {
+            printf("TEST ERROR: pmSubtractionCalculateEquation() returned TRUE.\n");
+            testStatus = true;
+        }
+
+        //-------------------------------------------------------------------------
+        printf("Calling with a NULL kernel basis functions.  Should generate error, return FALSE.\n");
+        rc = pmSubtractionCalculateEquation(stamps, refImg, tstImg, NULL, TST03_FOOTPRINT);
+        if (rc == TRUE) {
+            printf("TEST ERROR: pmSubtractionCalculateEquation() returned TRUE.\n");
+            testStatus = true;
+        }
+
+        //-------------------------------------------------------------------------
+        printf("Calling with acceptable input parameters.  Should return TRUE.\n");
+
+        rc = pmSubtractionCalculateEquation(stamps, refImg, tstImg, myKernels, TST03_FOOTPRINT);
+        if (rc != TRUE) {
+            printf("TEST ERROR: pmSubtractionCalculateEquation() returned FALSE.\n");
+            testStatus = true;
+        } else {
+
+            if (0) {
+                for (psS32 s = 0 ; s < stamps->n ; s++) {
+                    printf("********************************* Stamp %d *********************************\n", s);
+                    pmStamp *stamp = (pmStamp *) stamps->data[s];
+                    if (stamp->vector != NULL) {
+                        PS_VECTOR_PRINT_F64(stamp->vector);
+                    }
+                    if (stamp->matrix != NULL) {
+                        printf("Stamp matrix size is (%d, %d)\n", stamp->matrix->numRows, stamp->matrix->numCols);
+                        PS_IMAGE_PRINT_F64(stamp->matrix);
+                    }
+                }
+            }
+
+
+            //-------------------------------------------------------------------------
+            printf("Calling pmSubtractionSolveEquation() with a NULL stamp argument.  Should generate error, return FALSE.\n");
+            psVector *solution = pmSubtractionSolveEquation(NULL, NULL);
+            if (solution != NULL) {
+                printf("TEST ERROR: pmSubtractionSolveEquation() returned non-NULL.\n");
+                testStatus = true;
+            }
+
+            //-------------------------------------------------------------------------
+            printf("Calling pmSubtractionSolveEquation() with acceptable input parameters.  Should return non-NULL.\n");
+            solution = pmSubtractionSolveEquation(NULL, stamps);
+            if (solution == NULL) {
+                printf("TEST ERROR: pmSubtractionSolveEquation() returned NULL.\n");
+                testStatus = true;
+            } else {
+                printf("The solution vector is:\n");
+                for (psS32 i = 0 ; i < solution->n ; i++) {
+                    printf("(%.2f) ", solution->data.F64[i]);
+                }
+                printf("\n");
+
+                //-------------------------------------------------------------------------
+                printf("Calling pmSubtractionRejectStamps() with acceptable input parameters.  Should return TRUE.\n");
+                rc = pmSubtractionRejectStamps(stamps, maskImg, 0xff, TST03_FOOTPRINT, 1.0, refImg,
+                                               tstImg, solution, myKernels);
+                if (rc != TRUE) {
+                    printf("TEST ERROR: pmSubtractionRejectStamps() returned FALSE.\n");
+                    testStatus = true;
+                } else {}
+
+                //-------------------------------------------------------------------------
+                printf("Calling pmSubtractionKernelImage() with NULL solution.  Should generate error, return NULL.\n");
+                psImage *kernelImg = pmSubtractionKernelImage(NULL, NULL, myKernels, 0.0, 0.0);
+                if (kernelImg != NULL) {
+                    printf("TEST ERROR: pmSubtractionKernelImage() returned non-NULL.\n");
+                    testStatus = true;
+                }
+                free(kernelImg);
+
+                //-------------------------------------------------------------------------
+                printf("Calling pmSubtractionKernelImage() with NULL kernels.  Should generate error, return NULL.\n");
+                kernelImg = pmSubtractionKernelImage(NULL, solution, NULL, 0.0, 0.0);
+                if (kernelImg != NULL) {
+                    printf("TEST ERROR: pmSubtractionKernelImage() returned non-NULL.\n");
+                    testStatus = true;
+                }
+                free(kernelImg);
+
+                //-------------------------------------------------------------------------
+                printf("Calling pmSubtractionKernelImage() unallowable x value.  Should generate error, return NULL.\n");
+                kernelImg = pmSubtractionKernelImage(NULL, solution, myKernels, -2.0, 0.0);
+                if (kernelImg != NULL) {
+                    printf("TEST ERROR: pmSubtractionKernelImage() returned non-NULL.\n");
+                    testStatus = true;
+                }
+                free(kernelImg);
+
+                //-------------------------------------------------------------------------
+                printf("Calling pmSubtractionKernelImage() unallowable x value.  Should generate error, return NULL.\n");
+                kernelImg = pmSubtractionKernelImage(NULL, solution, myKernels, 2.0, 0.0);
+                if (kernelImg != NULL) {
+                    printf("TEST ERROR: pmSubtractionKernelImage() returned non-NULL.\n");
+                    testStatus = true;
+                }
+                free(kernelImg);
+
+                //-------------------------------------------------------------------------
+                printf("Calling pmSubtractionKernelImage() unallowable y value.  Should generate error, return NULL.\n");
+                kernelImg = pmSubtractionKernelImage(NULL, solution, myKernels, 0.0, -2.0);
+                if (kernelImg != NULL) {
+                    printf("TEST ERROR: pmSubtractionKernelImage() returned non-NULL.\n");
+                    testStatus = true;
+                }
+                free(kernelImg);
+
+                //-------------------------------------------------------------------------
+                printf("Calling pmSubtractionKernelImage() unallowable y value.  Should generate error, return NULL.\n");
+                kernelImg = pmSubtractionKernelImage(NULL, solution, myKernels, 0.0, 2.0);
+                if (kernelImg != NULL) {
+                    printf("TEST ERROR: pmSubtractionKernelImage() returned non-NULL.\n");
+                    testStatus = true;
+                }
+                free(kernelImg);
+
+                //-------------------------------------------------------------------------
+                printf("Calling pmSubtractionKernelImage() with acceptable input parameters.  Should return a psImage.\n");
+                kernelImg = pmSubtractionKernelImage(NULL, solution, myKernels, 0.5, 0.5);
+                if (kernelImg == NULL) {
+                    printf("TEST ERROR: pmSubtractionKernelImage() returned NULL.\n");
+                    testStatus = true;
+                } else {
+                    for (psS32 row = 0 ; row < kernelImg->numRows; row++) {
+                        for (psS32 col = 0 ; col < kernelImg->numCols; col++) {
+                            printf("%f ", kernelImg->data.F32[row][col]);
+                        }
+                        printf("\n");
+                    }
+                }
+                free(kernelImg);
+
+                psFree(solution);
+            }
+        }
+    }
+    psFree(tstImg);
+    psFree(refImg);
+    psFree(stamps);
+    psFree(myKernels);
+    psFree(orders);
+    psFree(sigmas);
+
+    return(testStatus);
+}
+
+/*******************************************************************************
+NOTE: This function returns TRUE if there were no errors.
+ ******************************************************************************/
+int test03( void )
+{
+    bool testStatus = false;
+
+
+    srand(1995);
+    if (1)
+        testStatus|= testSubCalcEqu(TST03_NUM_COLS,
+                                    TST03_NUM_ROWS,
+                                    TST03_NUM_STAMPS_COLS,
+                                    TST03_NUM_STAMPS_ROWS,
+                                    TST03_BORDER,
+                                    PM_SUBTRACTION_KERNEL_POIS);
+
+
+    srand(1995);
+    if (1)
+        testStatus|= testSubCalcEqu(TST03_NUM_COLS,
+                                    TST03_NUM_ROWS,
+                                    TST03_NUM_STAMPS_COLS,
+                                    TST03_NUM_STAMPS_ROWS,
+                                    TST03_BORDER,
+                                    PM_SUBTRACTION_KERNEL_ISIS);
+
+
+
+    return(!testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/imcombine/tst_pmReadoutCombine.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/imcombine/tst_pmReadoutCombine.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/imcombine/tst_pmReadoutCombine.c	(revision 22158)
@@ -0,0 +1,462 @@
+/** @file tst_pmReadoutCombine.c
+ *
+ *  test00() This routine will test the basic functionality.
+ *
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-03-04 01:01:34 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ *  XXX: Untested:
+ * S16, S32 types
+ * Multiple input readouts with varying sizes and offsets.
+ * params->fracLow and params->fracHigh
+ * params->nKeep
+ * (gain > 0.0) && (readnoise >= 0.0) (applyZeroScale == true)
+ * (gain > 0.0) && (readnoise >= 0.0) (applyZeroScale == false)
+ *
+ */
+
+#include "psTest.h"
+#include "pslib.h"
+#include "pmReadoutCombine.h"
+static int test00(void);
+static int test01(void);
+testDescription tests[] = {
+                              {test00, 000, "pmSubtractBias(): Basic readout combines with no image overlap", true, false},
+                              {test01, 000, "pmSubtractBias(): input parameter error conditions", true, false},
+                              {NULL}
+                          };
+
+#define NUM_READOUTS  10
+#define INPUT_NUM_ROWS 20
+#define INPUT_NUM_COLS 20
+#define VEC_ZERO 1.0
+#define VEC_SCALE 2.0
+
+psS32 VerifyTheOutput(psImage *output, psF32 expect)
+{
+    bool testStatus = true;
+
+    for (psS32 i = 0 ; i < output->numRows ; i++) {
+        for (psS32 j = 0 ; j < output->numCols ; j++) {
+            if (output->data.F32[i][j] != expect) {
+                printf("TEST ERROR: output[%d][%d] is %.2f, should be %f\n", i, j, output->data.F32[i][j], expect);
+                testStatus = false;
+            }
+        }
+    }
+    return(testStatus);
+}
+
+
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    return !runTestSuite(stderr, "Test Point Driver", tests, argc, argv);
+}
+
+/******************************************************************************
+simpleCombineNoOverlap(): this routine creates a list of NUM_READOUTS input
+readouts and calls pmReadoutCombine().
+ *****************************************************************************/
+int simpleCombineNoOverlap(psS32 numInputCols, psS32 numInputRows)
+{
+    int i;
+    int r;
+    psList *list = NULL;
+    int baseRowsReadout[NUM_READOUTS];
+    int baseColsReadout[NUM_READOUTS];
+    int baseRows[NUM_READOUTS];
+    int baseCols[NUM_READOUTS];
+    int numRows[NUM_READOUTS];
+    int numCols[NUM_READOUTS];
+    int minOutRow = 10000;
+    int minOutCol = 10000;
+    int maxOutRow = -1;
+    int maxOutCol = -1;
+    psImage *output = NULL;
+    psCombineParams *params = (psCombineParams *) psAlloc(sizeof(psCombineParams));
+    psVector *zero = psVectorAlloc(NUM_READOUTS, PS_TYPE_F32);
+    psVector *scale = psVectorAlloc(NUM_READOUTS, PS_TYPE_F32);
+    zero->n = zero->nalloc;
+    scale->n = scale->nalloc;
+    printPositiveTestHeader(stdout, "pmReadoutCombine", "simpleCombineNoOverlap");
+
+    for (i=0;i<NUM_READOUTS;i++) {
+        zero->data.F32[i] = VEC_ZERO;
+    }
+    for (i=0;i<NUM_READOUTS;i++) {
+        scale->data.F32[i] = VEC_SCALE;
+    }
+
+    params->stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    params->maskVal = 1;
+    params->fracLow = 0.0;
+    params->fracHigh = 10000.0;
+    params->nKeep = 0;
+
+    //
+    // Create a psList of psReadouts.  The pixels in readout r will all have the
+    // value r.
+    //
+    for (r=0;r<NUM_READOUTS;r++) {
+        baseRowsReadout[r] = r + 40;
+        baseColsReadout[r] = r + 42;
+        baseRows[r] = r;
+        baseCols[r] = r+2;
+        numRows[r] = 4 + (2 * r);
+        numCols[r] = 8 + (2 * r);
+
+        baseRowsReadout[r] = 0;
+        baseColsReadout[r] = 0;
+        baseRows[r] = 0;
+        baseCols[r] = 0;
+        numRows[r] = numInputRows;
+        numCols[r] = numInputCols;
+
+        psImage *tmpImage = psImageAlloc(numCols[r], numRows[r], PS_TYPE_F32);
+        PS_IMAGE_SET_F32(tmpImage, ((float) r));
+        *(int *) (& (tmpImage->row0)) = baseRows[r];
+        *(int *) (& (tmpImage->col0)) = baseCols[r];
+        pmReadout *tmpReadout = pmReadoutAlloc(NULL);
+        tmpReadout->row0 = 0;
+        tmpReadout->col0 = 0;
+        tmpReadout->image = tmpImage;
+
+        minOutRow = PS_MIN(minOutRow, (baseRowsReadout[r] + baseRows[r]));
+        minOutCol = PS_MIN(minOutCol, (baseColsReadout[r] + baseCols[r]));
+        maxOutRow = PS_MAX(maxOutRow, (baseRowsReadout[r] + baseRows[r] + numRows[r]));
+        maxOutCol = PS_MAX(maxOutCol, (baseColsReadout[r] + baseCols[r] + numCols[r]));
+
+        if (r == 0) {
+            list = psListAlloc(tmpReadout);
+        } else {
+            psListAdd(list, PS_LIST_HEAD, tmpReadout);
+        }
+    }
+    printf("tst_pmReadoutCombine(): (minOutRow, minOutCol) to (maxOutRow, maxOutCol) is (%d, %d) (%d, %d)\n",
+           minOutRow, minOutCol, maxOutRow, maxOutCol);
+
+    output = pmReadoutCombine(output, list, params, zero, scale, true, 0.0, 0.0);
+    psF32 NR = (psF32) NUM_READOUTS;
+    psF32 expectedPixel = ((NR/2.0) * (VEC_ZERO + (VEC_ZERO + VEC_SCALE * (NR - 1)))) / NR;
+
+    int testStatus = VerifyTheOutput(output, expectedPixel);
+
+    psFree(params->stats);
+    psFree(params);
+    psFree(output);
+    psFree(zero);
+    psFree(scale);
+
+    psListElem *tmpInput = (psListElem *) list->head;
+    while (NULL != tmpInput) {
+        pmReadout *tmpReadout = (pmReadout *) tmpInput->data;
+        psFree(tmpReadout);
+        tmpInput = tmpInput->next;
+    }
+    psFree(list);
+
+    printFooter(stdout, "pmReadoutCombine", "simpleCombineNoOverlap", true);
+    return(testStatus);
+}
+
+int test00( void )
+{
+    int testStatus = 0;
+
+    testStatus |= simpleCombineNoOverlap(1, 1);
+    testStatus |= simpleCombineNoOverlap(INPUT_NUM_COLS, 1);
+    testStatus |= simpleCombineNoOverlap(1, INPUT_NUM_ROWS);
+    testStatus |= simpleCombineNoOverlap(INPUT_NUM_COLS, INPUT_NUM_ROWS);
+
+    return(testStatus);
+}
+
+/******************************************************************************
+test01(): we simply call pmReadoutCombine() with a variety of erroneous input
+parameter combinations and verify that it behaves properly.
+ *****************************************************************************/
+int test01()
+{
+    int testStatus = true;
+    int i;
+    int r;
+    psList *list = NULL;
+    int baseRowsReadout[NUM_READOUTS];
+    int baseColsReadout[NUM_READOUTS];
+    int baseRows[NUM_READOUTS];
+    int baseCols[NUM_READOUTS];
+    int numRows[NUM_READOUTS];
+    int numCols[NUM_READOUTS];
+    int minOutRow = 10000;
+    int minOutCol = 10000;
+    int maxOutRow = -1;
+    int maxOutCol = -1;
+    psImage *output = NULL;
+    psImage *rc = NULL;
+    psCombineParams *params = (psCombineParams *) psAlloc(sizeof(psCombineParams));
+    psVector *zero = psVectorAlloc(NUM_READOUTS, PS_TYPE_F32);
+    psVector *zeroHalf = psVectorAlloc(NUM_READOUTS/2, PS_TYPE_F32);
+    psVector *zeroBig = psVectorAlloc(NUM_READOUTS+1, PS_TYPE_F32);
+    psVector *zeroF64 = psVectorAlloc(NUM_READOUTS, PS_TYPE_F64);
+    psVector *scale = psVectorAlloc(NUM_READOUTS, PS_TYPE_F32);
+    psVector *scaleHalf = psVectorAlloc(NUM_READOUTS/2, PS_TYPE_F32);
+    psVector *scaleBig = psVectorAlloc(NUM_READOUTS*2, PS_TYPE_F32);
+    psVector *scaleF64 = psVectorAlloc(NUM_READOUTS, PS_TYPE_F64);
+    zero->n = zero->nalloc;
+    zeroHalf->n = zeroHalf->nalloc;
+    zeroBig->n = zeroBig->nalloc;
+    zeroF64->n = zeroF64->nalloc;
+    scale->n = scale->nalloc;
+    scaleHalf->n = scaleHalf->nalloc;
+    scaleBig->n = scaleBig->nalloc;
+    scaleF64->n = scaleF64->nalloc;
+    for (i=0;i<NUM_READOUTS;i++) {
+        zero->data.F32[i] = 3.0;
+        zeroBig->data.F32[i] = 3.0;
+        zero->data.F32[i] = VEC_ZERO;
+        zeroBig->data.F32[i] = VEC_ZERO;
+    }
+    for (i=0;i<NUM_READOUTS;i++) {
+        scale->data.F32[i] = 6.0;
+        scaleBig->data.F32[i] = 6.0;
+        scale->data.F32[i] = VEC_SCALE;
+        scaleBig->data.F32[i] = VEC_SCALE;
+    }
+    printPositiveTestHeader(stdout, "pmReadoutCombine", "Testing bad input parameter conditions");
+
+    params->stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    params->maskVal = 1;
+    params->fracLow = 0.0;
+    params->fracHigh = 10000.0;
+    params->nKeep = 0;
+
+    for (r=0;r<NUM_READOUTS;r++) {
+        baseRowsReadout[r] = 0;
+        baseColsReadout[r] = 0;
+        baseRows[r] = 0;
+        baseCols[r] = 0;
+        numRows[r] = INPUT_NUM_ROWS;
+        numCols[r] = INPUT_NUM_COLS;
+
+        psImage *tmpImage = psImageAlloc(numCols[r], numRows[r], PS_TYPE_F32);
+        PS_IMAGE_SET_F32(tmpImage, ((float) r));
+        *(int *) (& (tmpImage->row0)) = baseRows[r];
+        *(int *) (& (tmpImage->col0)) = baseCols[r];
+        pmReadout *tmpReadout = pmReadoutAlloc(NULL);
+        tmpReadout->row0 = 0;
+        tmpReadout->col0 = 0;
+        tmpReadout->image = tmpImage;
+        minOutRow = PS_MIN(minOutRow, (baseRowsReadout[r] + baseRows[r]));
+        minOutCol = PS_MIN(minOutCol, (baseColsReadout[r] + baseCols[r]));
+        maxOutRow = PS_MAX(maxOutRow, (baseRowsReadout[r] + baseRows[r] + numRows[r]));
+        maxOutCol = PS_MAX(maxOutCol, (baseColsReadout[r] + baseCols[r] + numCols[r]));
+
+        if (r == 0) {
+            list = psListAlloc(tmpReadout);
+        } else {
+            psListAdd(list, PS_LIST_HEAD, tmpReadout);
+        }
+    }
+
+    printf("----------------------------------------------------------------------------\n");
+    printf("Calling pmReadoutCombine() with NULL zero vector.\n");
+    rc = pmReadoutCombine(NULL, list, params, NULL, scale, true, 0.0, 0.0);
+    if (rc != NULL) {
+        psF32 NR = (psF32) NUM_READOUTS;
+        psF32 expectedPixel = ((NR/2.0) * (0.0 + (0.0 + VEC_SCALE * (NR - 1)))) / NR;
+        if (false == VerifyTheOutput(rc, expectedPixel)) {
+            testStatus = false;
+        }
+
+        if (rc->type.type != scale->type.type) {
+            printf("TEST ERROR: output readout->image has incorrect type.\n");
+            testStatus = false;
+        }
+        psFree(rc);
+    } else {
+        printf("TEST ERROR: pmReadoutCombine() returned NULL\n");
+        testStatus = false;
+
+    }
+
+    printf("----------------------------------------------------------------------------\n");
+    printf("Calling pmReadoutCombine() with incorrect length zero vector (too small).  Should generate error.\n");
+    rc = pmReadoutCombine(NULL, list, params, zeroHalf, scale, true, 0.0, 0.0);
+    if (rc != NULL) {
+        printf("TEST ERROR: pmReadoutCombine() did not return NULL\n");
+        testStatus = false;
+    }
+
+    printf("----------------------------------------------------------------------------\n");
+    printf("Calling pmReadoutCombine() with incorrect type zero vector.  Should generate error.\n");
+    rc = pmReadoutCombine(NULL, list, params, zeroF64, scale, true, 0.0, 0.0);
+    if (rc != NULL) {
+        printf("TEST ERROR: pmReadoutCombine() did not return NULL\n");
+        testStatus = false;
+    }
+
+    printf("----------------------------------------------------------------------------\n");
+    printf("Calling pmReadoutCombine() with incorrect length zero vector (too big).  Should generate warning.\n");
+    rc = pmReadoutCombine(output, list, params, zeroBig, scale, true, 0.0, 0.0);
+    if (rc != NULL) {
+        psF32 NR = (psF32) NUM_READOUTS;
+        psF32 expectedPixel = ((NR/2.0) * (VEC_ZERO + (VEC_ZERO + VEC_SCALE * (NR - 1)))) / NR;
+
+        if (false == VerifyTheOutput(rc, expectedPixel)) {
+            testStatus = false;
+        }
+        psFree(rc);
+        rc = NULL;
+    } else {
+        printf("TEST ERROR: pmReadoutCombine() returned NULL\n");
+        testStatus = false;
+    }
+
+    printf("----------------------------------------------------------------------------\n");
+    printf("Calling pmReadoutCombine() with NULL scale vector.\n");
+    rc = pmReadoutCombine(output, list, params, zero, NULL, true, 0.0, 0.0);
+
+    if (rc != NULL) {
+        psF32 NR = (psF32) NUM_READOUTS;
+        psF32 expectedPixel = ((NR/2.0) * (VEC_ZERO + (VEC_ZERO + 1.0 * (NR - 1)))) / NR;
+        if (false == VerifyTheOutput(rc, expectedPixel)) {
+            testStatus = false;
+        }
+
+        if (rc->type.type != scale->type.type) {
+            printf("TEST ERROR: output readout->image has incorrect type.\n");
+            testStatus = false;
+        }
+        psFree(rc);
+    } else {
+        printf("TEST ERROR: pmReadoutCombine() returned NULL\n");
+        testStatus = false;
+
+    }
+
+    printf("----------------------------------------------------------------------------\n");
+    printf("Calling pmReadoutCombine() with incorrect length scale vector (too small).  Should generate error.\n");
+    rc = pmReadoutCombine(output, list, params, zero, scaleHalf, true, 0.0, 0.0);
+    if (rc != NULL) {
+        printf("TEST ERROR: pmReadoutCombine() did not return NULL\n");
+        testStatus = false;
+    }
+
+    printf("----------------------------------------------------------------------------\n");
+    printf("Calling pmReadoutCombine() with incorrect type scale vector.  Should generate error.\n");
+    rc = pmReadoutCombine(output, list, params, zero, scaleF64, true, 0.0, 0.0);
+    if (rc != NULL) {
+        printf("TEST ERROR: pmReadoutCombine() did not return NULL\n");
+        testStatus = false;
+    }
+
+    printf("----------------------------------------------------------------------------\n");
+    printf("Calling pmReadoutCombine() with incorrect length scale vector (too big).  Should generate warning.\n");
+    rc = pmReadoutCombine(output, list, params, zero, scaleBig, true, 0.0, 0.0);
+    if (rc != NULL) {
+        psF32 NR = (psF32) NUM_READOUTS;
+        psF32 expectedPixel = ((NR/2.0) * (VEC_ZERO + (VEC_ZERO + VEC_SCALE * (NR - 1)))) / NR;
+
+        if (false == VerifyTheOutput(rc, expectedPixel)) {
+            testStatus = false;
+        }
+        psFree(rc);
+        rc = NULL;
+    } else {
+        printf("TEST ERROR: pmReadoutCombine() returned NULL\n");
+        testStatus = false;
+    }
+
+    printf("----------------------------------------------------------------------------\n");
+    printf("Calling pmReadoutCombine() insufficient size output image.  Should generate error, return NULL.\n");
+    output = psImageAlloc(1, 1, PS_TYPE_F32);
+    rc = pmReadoutCombine(output, list, params, zero, scale, true, 0.0, 0.0);
+    if (rc != NULL) {
+        printf("TEST ERROR: pmReadoutCombine() did not return NULL\n");
+        testStatus = false;
+    }
+    psFree(output);
+    output = NULL;
+
+    printf("----------------------------------------------------------------------------\n");
+    printf("Calling pmReadoutCombine() row0/col0 too large.  Should generate error, return NULL.\n");
+    output = psImageAlloc(1, 1, PS_TYPE_F32);
+    *(psS32*)&output->row0 = 10000;
+    *(psS32*)&output->col0 = 10000;
+    rc = pmReadoutCombine(output, list, params, zero, scale, true, 0.0, 0.0);
+    if (rc != NULL) {
+        printf("TEST ERROR: pmReadoutCombine() did not return NULL\n");
+        testStatus = false;
+    }
+    psFree(output);
+    output = NULL;
+
+    printf("----------------------------------------------------------------------------\n");
+    printf("Calling pmReadoutCombine() with NULL input list.  Should generate error, return NULL.\n");
+    rc = pmReadoutCombine(output, NULL, params, zero, scale, true, 0.0, 0.0);
+    if (rc != NULL) {
+        printf("TEST ERROR: pmReadoutCombine() did not return NULL\n");
+        testStatus = false;
+    }
+
+    printf("----------------------------------------------------------------------------\n");
+    printf("Calling pmReadoutCombine() with NULL params.  Should generate error, return NULL.\n");
+    rc = pmReadoutCombine(output, list, NULL, zero, scale, true, 0.0, 0.0);
+    if (rc != NULL) {
+        printf("TEST ERROR: pmReadoutCombine() did not return NULL\n");
+        testStatus = false;
+    }
+
+    printf("----------------------------------------------------------------------------\n");
+    psStatsOptions oldStatsOpts = params->stats->options |= PS_STAT_MIN;
+    printf("Calling pmReadoutCombine() with multiple stats->options.  Should generate error, return NULL.\n");
+    rc = pmReadoutCombine(output, list, params, zero, scale, true, 0.0, 0.0);
+    if (rc != NULL) {
+        printf("TEST ERROR: pmReadoutCombine() did not return NULL\n");
+        testStatus = false;
+    }
+    params->stats->options = oldStatsOpts;
+
+    printf("----------------------------------------------------------------------------\n");
+    psStats *oldStats = params->stats;
+    printf("Calling pmReadoutCombine() with NULL param->stats.  Should generate error, return NULL.\n");
+    params->stats = NULL;
+    rc = pmReadoutCombine(output, list, params, zero, scale, true, 0.0, 0.0);
+    if (rc != NULL) {
+        printf("TEST ERROR: pmReadoutCombine() did not return NULL\n");
+        testStatus = false;
+    }
+    params->stats = oldStats;
+
+    printf("----------------------------------------------------------------------------\n");
+    printf("============================================================================\n");
+
+    psFree(params->stats);
+    psFree(params);
+    //    psFree(output);
+    //    psFree(rc);
+    psFree(zero);
+    psFree(zeroHalf);
+    psFree(zeroBig);
+    psFree(zeroF64);
+    psFree(scale);
+    psFree(scaleHalf);
+    psFree(scaleBig);
+    psFree(scaleF64);
+    psListElem *tmpInput = (psListElem *) list->head;
+    while (NULL != tmpInput) {
+        pmReadout *tmpReadout = (pmReadout *) tmpInput->data;
+        psFree(tmpReadout);
+        tmpInput = tmpInput->next;
+    }
+    psFree(list);
+
+    printFooter(stdout, "pmReadoutCombine", "Testing bad input parameter conditions", true);
+    return(testStatus);
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/.cvsignore	(revision 22158)
@@ -0,0 +1,9 @@
+.deps
+.libs
+Makefile
+Makefile.in
+temp
+tap_pmGrowthCurve
+tap_pmSourceFitModel
+tap_pmSourceFitModel_Delta
+tap_pmSourcePhotometry
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/Makefile.am	(revision 22158)
@@ -0,0 +1,51 @@
+AM_CPPFLAGS = \
+	$(SRCINC) \
+	-I$(top_srcdir)/test/tap/src \
+	-I$(top_srcdir)/test/pstap/src \
+	$(PSMODULES_CFLAGS)
+
+AM_LDFLAGS = \
+	$(top_builddir)/src/libpsmodules.la  \
+	$(top_builddir)/test/tap/src/libtap.la \
+	$(top_builddir)/test/pstap/src/libpstap.la \
+	$(PSMODULES_LIBS)
+
+TEST_PROGS = \
+	tap_pmPeaks \
+	tap_pmGrowthCurve \
+	tap_pmMoments \
+	tap_pmSource \
+	tap_pmModel \
+	tap_pmModelUtils \
+	tap_pmModelClass \
+	tap_pmPSF \
+	tap_pmTrend2D \
+	tap_pmResiduals \
+	tap_pmSourceExtendedPars \
+	tap_pmSourceSky \
+	tap_pmSourceIO_PS1_DEV_0 \
+	tap_pmSourceIO_PS1_DEV_1 \
+	tap_pmSourceIO_SMPDATA \
+	tap_pmSourceContour \
+	tap_pmSourceUtils \
+	tap_pmSourceFitSet \
+	tap_pmPSF_IO \
+	tap_pmSourceIO_SMPDATA
+
+if BUILD_TESTS
+bin_PROGRAMS = $(TEST_PROGS)
+TESTS = $(TEST_PROGS)
+else
+check_PROGRAMS = $(TEST_PROGS)
+endif
+
+CLEANFILES = $(check_DATA) temp/* core core.* *~ *.bb *.bbg *.da gmon.out
+
+test: check
+	$(top_srcdir)/test/test.pl
+
+# Removed
+#	tap_pmSourcePhotometry
+#	tap_pmGrowthCurve
+#	tap_pmSourceFitModel
+#	tap_pmSourceFitModel_Delta
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmFringe.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmFringe.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmFringe.c	(revision 22158)
@@ -0,0 +1,130 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define NUM_ROWS 8
+#define NUM_COLS 16
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(35);
+
+
+    // Test pmFringeRegionsAlloc()
+    {
+        psMemId id = psMemGetId();
+        pmFringeRegions *fringe = pmFringeRegionsAlloc(1, 2, 3, 4, 5);
+        ok(fringe != NULL, "pmFringeRegionsAlloc() returned non-NULL");
+        ok(fringe->x == NULL, "pmFringeRegionsAlloc() set fringe->x correctly");
+        ok(fringe->y == NULL, "pmFringeRegionsAlloc() set fringe->y correctly");
+        ok(fringe->mask == NULL, "pmFringeRegionsAlloc() set fringe->mask correctly");
+        ok(fringe->nRequested == 1, "pmFringeRegionsAlloc() set fringe->nRequested correctly");
+        ok(fringe->nAccepted == 0, "pmFringeRegionsAlloc() set fringe->nAccepted correctly");
+        ok(fringe->dX == 2, "pmFringeRegionsAlloc() set fringe->dX correctly");
+        ok(fringe->dY == 3, "pmFringeRegionsAlloc() set fringe->dY correctly");
+        ok(fringe->nX == 4, "pmFringeRegionsAlloc() set fringe->nX correctly");
+        ok(fringe->nY == 5, "pmFringeRegionsAlloc() set fringe->nY correctly");
+        psFree(fringe);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    #define NUM_FRINGE_PNTS 10
+    #define DX 2
+    #define DY 2
+    #define NX 1
+    #define NY 1
+    // test pmFringeRegionsCreatePoints(): NULL random number generator,
+    // NULL fringe X, y, and mask vectors.
+    {
+        psMemId id = psMemGetId();
+        pmFringeRegions *fringe = pmFringeRegionsAlloc(NUM_FRINGE_PNTS, DX, DY, NX, NY);
+        ok(fringe != NULL, "pmFringeRegionsAlloc() returned non-NULL");
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        bool rc = pmFringeRegionsCreatePoints(fringe, img, NULL);
+        ok(rc, "pmFringeRegionsCreatePoints() returned TRUE");
+        ok(fringe->x != NULL &&
+           fringe->x->type.type == PS_TYPE_F32 &&
+           fringe->x->n ==NUM_FRINGE_PNTS, "pmFringeRegionsCreatePoints() returned correct fringe->x psVector");
+        ok(fringe->y != NULL &&
+           fringe->y->type.type == PS_TYPE_F32 &&
+           fringe->y->n ==NUM_FRINGE_PNTS, "pmFringeRegionsCreatePoints() returned correct fringe->y psVector");
+        ok(fringe->mask != NULL &&
+           fringe->mask->type.type == PS_TYPE_MASK &&
+           fringe->mask->n ==NUM_FRINGE_PNTS, "pmFringeRegionsCreatePoints() returned correct fringe->mask psVector");
+        bool errorFlag = false;
+        for (int i = 0 ; i < NUM_FRINGE_PNTS ; i++) {
+            if (fringe->mask->data.U8[i] != 0) {
+                diag("ERROR: pmFringeRegionsCreatePoints() did not set mask[%d] to 0", i);
+                errorFlag = true;
+            }
+            if (!((fringe->x->data.F32[i] >= DX) &&
+                 (fringe->x->data.F32[i] <= NUM_COLS-DX))) {
+                diag("ERROR: pmFringeRegionsCreatePoints() did not set x[%d] correctly.  It was %.2f, should be within (%d %d)", i,
+                      fringe->x->data.F32[i], DX, NUM_COLS-DX);
+                errorFlag = true;
+            }
+            if (!((fringe->y->data.F32[i] >= DY) &&
+                 (fringe->y->data.F32[i] <= NUM_ROWS-DY))) {
+                diag("ERROR: pmFringeRegionsCreatePoints() did not set x[%d] correctly.  It was %.2f, should be within (%d %d)", i,
+                      fringe->y->data.F32[i], DY, NUM_ROWS-DY);
+                errorFlag = true;
+            }
+        }
+
+        psFree(img);
+        psFree(fringe);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // test pmFringeRegionsCreatePoints(): non-NULL random number generator,
+    // non-NULL fringe X, y, and mask vectors.
+    {
+        psMemId id = psMemGetId();
+        pmFringeRegions *fringe = pmFringeRegionsAlloc(NUM_FRINGE_PNTS, DX, DY, NX, NY);
+        ok(fringe != NULL, "pmFringeRegionsAlloc() returned non-NULL");
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 10);
+        fringe->x = psVectorAlloc(NUM_FRINGE_PNTS/2, PS_TYPE_F32);
+        fringe->y = psVectorAlloc(NUM_FRINGE_PNTS/2, PS_TYPE_F32);
+        fringe->mask = psVectorAlloc(NUM_FRINGE_PNTS/2, PS_TYPE_MASK);
+        bool rc = pmFringeRegionsCreatePoints(fringe, img, NULL);
+        ok(rc, "pmFringeRegionsCreatePoints() returned TRUE");
+        ok(fringe->x != NULL &&
+           fringe->x->type.type == PS_TYPE_F32 &&
+           fringe->x->n ==NUM_FRINGE_PNTS, "pmFringeRegionsCreatePoints() returned correct fringe->x psVector");
+        ok(fringe->y != NULL &&
+           fringe->y->type.type == PS_TYPE_F32 &&
+           fringe->y->n ==NUM_FRINGE_PNTS, "pmFringeRegionsCreatePoints() returned correct fringe->y psVector");
+        ok(fringe->mask != NULL &&
+           fringe->mask->type.type == PS_TYPE_MASK &&
+           fringe->mask->n ==NUM_FRINGE_PNTS, "pmFringeRegionsCreatePoints() returned correct fringe->mask psVector");
+        bool errorFlag = false;
+        for (int i = 0 ; i < NUM_FRINGE_PNTS ; i++) {
+            if (fringe->mask->data.U8[i] != 0) {
+                diag("ERROR: pmFringeRegionsCreatePoints() did not set mask[%d] to 0", i);
+                errorFlag = true;
+            }
+            if (!((fringe->x->data.F32[i] >= DX) &&
+                 (fringe->x->data.F32[i] <= NUM_COLS-DX))) {
+                diag("ERROR: pmFringeRegionsCreatePoints() did not set x[%d] correctly.  It was %.2f, should be within (%d %d)", i,
+                      fringe->x->data.F32[i], DX, NUM_COLS-DX);
+                errorFlag = true;
+            }
+            if (!((fringe->y->data.F32[i] >= DY) &&
+                 (fringe->y->data.F32[i] <= NUM_ROWS-DY))) {
+                diag("ERROR: pmFringeRegionsCreatePoints() did not set x[%d] correctly.  It was %.2f, should be within (%d %d)", i,
+                      fringe->y->data.F32[i], DY, NUM_ROWS-DY);
+                errorFlag = true;
+            }
+        }
+        psFree(rng);
+        psFree(img);
+        psFree(fringe);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmGrowthCurve.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmGrowthCurve.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmGrowthCurve.c	(revision 22158)
@@ -0,0 +1,378 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/*
+    STATUS:
+	All functions are tested.  However, some of the pmGrowthCurveCorrect()
+	tests that were supplied by IfA ae failing.
+*/
+
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(70);
+
+    // ----------------------------------------------------------------------
+    // pmGrowthCurveAlloc() tests
+    // call pmGrowthCurveAlloc() with acceptable input parameters.
+    {
+        psMemId id = psMemGetId();
+        pmGrowthCurve *growthCurve = pmGrowthCurveAlloc(1.0, 2.0, 3.0);
+        ok(growthCurve && psMemCheckGrowthCurve(growthCurve), "pmGrowthCurveAlloc() allocated a pmGrowthCurve correctly");
+        ok(growthCurve->radius && psMemCheckVector(growthCurve->radius), "pmGrowthCurveAlloc() allocated the radius psVector correctly");
+        ok(growthCurve->apMag  && psMemCheckVector(growthCurve->apMag) &&
+           growthCurve->apMag->n == growthCurve->radius->n, "pmGrowthCurveAlloc() allocated the apMag psVector correctly");
+        ok(growthCurve->refRadius == 3.0, "pmGrowthCurveAlloc() set growthCurve->refRadius correctly");
+        ok(growthCurve->maxRadius == 2.0, "pmGrowthCurveAlloc() set growthCurve->maxRadius correctly");
+        ok(growthCurve->apLoss == 0.0, "pmGrowthCurveAlloc() set growthCurve->apLoss correctly");
+        ok(growthCurve->fitMag == 0.0, "pmGrowthCurveAlloc() set growthCurve->fitMag correctly");
+        psFree(growthCurve);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmGrowthCurveCorrect() tests
+    // Call pmGrowthCurveCorrect() with NULL input pmGrowthCurve
+    {
+        psMemId id = psMemGetId();
+        pmGrowthCurve *growthCurve = pmGrowthCurveAlloc(1.0, 2.0, 3.0);
+        ok(isnan(pmGrowthCurveCorrect(NULL, 0.0)), "pmGrowthCurveCorrect() returned NAN with NULL input pmGrowthCurve");
+        psFree(growthCurve);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmGrowthCurveCorrect() with acceptable input parameters.
+    {
+        #define RADIUS 0.5
+        psMemId id = psMemGetId();
+        pmGrowthCurve *growthCurve = pmGrowthCurveAlloc(1.0, 2.0, 3.0);
+        float testCor = pmGrowthCurveCorrect(growthCurve, RADIUS);
+        float actRad = psVectorInterpolate (growthCurve->radius, growthCurve->apMag, RADIUS);
+        float actCor = growthCurve->apRef - actRad;
+
+        ok(!isnan(testCor), "pmGrowthCurveCorrect() call was successful");
+        ok(actCor == testCor, "pmGrowthCurveCorrect() calculated the correction correctly");
+
+        psFree(growthCurve);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // EM test 01: test allocation
+    // offset of 0.0,0.0 wrt growth ref source
+    {
+        psMemId id = psMemGetId();
+
+        pmGrowthCurve *growth = pmGrowthCurveAlloc (2.0, 100.0, 15.0);
+
+        ok(growth != NULL, "growth curve allocated");
+        skip_start(growth == NULL, 0, "Skipping tests because pmShutterCorrParsAlloc() failed");
+
+        ok(growth->radius->n == (100.0 - 2.0), "correct number of growth radii");
+        ok(growth->apMag->n == (100.0 - 2.0), "correct number of growth apMags");
+
+        ok_float(growth->refRadius, 15.0, "correct refRadius");
+        ok_float(growth->maxRadius, 100.0, "correct maxRadius");
+
+        // does the growth curve correctly fix aperture mags?
+
+        // generate a simple readout
+        pmReadout *readout = pmReadoutAlloc (NULL);
+        readout->image = psImageAlloc (64, 64, PS_TYPE_F32);
+        readout->mask  = psImageAlloc (64, 64, PS_TYPE_U8);
+
+        // create an empty reference image
+        psImageInit (readout->image, 0.0);
+        psImageInit (readout->mask, 0);
+
+        // generate a simple psf
+        pmModelClassInit();
+        pmPSF *psf = pmPSFBuildSimple("PS_MODEL_GAUSS", 1.5, 1.5, 0.0);
+        psf->growth = growth;
+
+        pmGrowthCurveGenerate(readout, psf, false, 0, 0);
+
+        // check ap mags for a few radii set by hand
+        ok_float_tol(growth->apMag->data.F32[0],   -9.7805, 0.0001, "apMag at radius 0: %f", growth->apMag->data.F32[0]);
+        ok_float_tol(growth->apMag->data.F32[3],  -10.3722, 0.0001, "apMag at radius 3: %f", growth->apMag->data.F32[3]);
+        ok_float_tol(growth->apMag->data.F32[10], -10.3759, 0.0001, "apMag at radius 10: %f", growth->apMag->data.F32[10]);
+        ok_float_tol(growth->apMag->data.F32[30], -10.3759, 0.0001, "apMag at radius 30: %f", growth->apMag->data.F32[30]);
+
+        ok_float_tol(growth->apRef,  -10.3759, 0.0001, "apMag at ref radius : %f", growth->apRef);
+        ok_float_tol(growth->fitMag, -10.3759, 0.0001, "fitMag : %f", growth->fitMag);
+        ok_float(growth->apLoss, 0.0, "apLoss : %f", growth->apLoss);
+
+        // create template model and measure apMag at fractional offsets
+        // XXX note model is at 0.5,0.5 subpix center
+        pmModel *modelRef = pmModelAlloc(psf->type);
+        modelRef->params->data.F32[PM_PAR_SKY] = 0;
+        modelRef->params->data.F32[PM_PAR_I0] = 1000;
+        modelRef->params->data.F32[PM_PAR_XPOS] = 32.5;
+        modelRef->params->data.F32[PM_PAR_YPOS] = 32.5;
+
+        // measure growth-corrected photometry:
+        pmSource *source = pmSourceAlloc ();
+        source->modelPSF = pmModelFromPSF (modelRef, psf);
+        source->type = PM_SOURCE_TYPE_STAR;
+        source->pixels = psMemIncrRefCounter (readout->image);
+        source->maskObj = psMemIncrRefCounter (readout->mask);
+
+        source->modelPSF->dparams->data.F32[PM_PAR_I0] = 1;
+        source->mode = PM_SOURCE_MODE_SUBTRACTED;
+
+        source->modelPSF->radiusFit = 15.0;
+
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        double refMag = source->apMag;
+
+        source->modelPSF->radiusFit = 10.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        ok_float_tol(refMag - source->apMag, +0.0000, 0.0001, "growth offset is is %f", refMag - source->apMag);
+
+        source->modelPSF->radiusFit = 8.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        ok_float_tol(refMag - source->apMag, +0.0000, 0.0001, "growth offset is is %f", refMag - source->apMag);
+
+        source->modelPSF->radiusFit = 6.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        ok_float_tol(refMag - source->apMag, +0.0003, 0.0001, "growth offset is is %f", refMag - source->apMag);
+
+        source->modelPSF->radiusFit = 4.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        ok_float_tol(refMag - source->apMag, +0.0020, 0.0001, "growth offset is is %f", refMag - source->apMag);
+
+        source->modelPSF->radiusFit = 3.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        ok_float_tol(refMag - source->apMag, -0.0001, 0.0001, "growth offset is is %f", refMag - source->apMag);
+
+        source->modelPSF->radiusFit = 2.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        ok_float_tol(refMag - source->apMag, -0.0075, 0.0001, "growth offset is is %f", refMag - source->apMag);
+
+        // XXX include some apertures outside of growth correction range
+
+        psFree(modelRef);
+        psFree(source);
+        psFree(readout);
+        psFree(psf);
+
+        skip_end();
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // EM test 02: test allocation
+    // offset of 0.2,0.2 wrt growth ref source
+    {
+        psMemId id = psMemGetId();
+
+        pmGrowthCurve *growth = pmGrowthCurveAlloc (2.0, 100.0, 15.0);
+
+        ok(growth != NULL, "growth curve allocated");
+        skip_start(growth == NULL, 0, "Skipping tests because pmShutterCorrParsAlloc() failed");
+
+        ok(growth->radius->n == (100.0 - 2.0), "correct number of growth radii");
+        ok(growth->apMag->n == (100.0 - 2.0), "correct number of growth apMags");
+
+        ok_float(growth->refRadius, 15.0, "correct refRadius");
+        ok_float(growth->maxRadius, 100.0, "correct maxRadius");
+
+        // does the growth curve correctly fix aperture mags?
+
+        // generate a simple readout
+        pmReadout *readout = pmReadoutAlloc (NULL);
+        readout->image = psImageAlloc (64, 64, PS_TYPE_F32);
+        readout->mask  = psImageAlloc (64, 64, PS_TYPE_U8);
+
+        // create an empty reference image
+        psImageInit (readout->image, 0.0);
+        psImageInit (readout->mask, 0);
+
+        // generate a simple psf
+        pmPSF *psf = pmPSFBuildSimple ("PS_MODEL_GAUSS", 1.5, 1.5, 0.0);
+        psf->growth = growth;
+
+        pmGrowthCurveGenerate (readout, psf, false, 0, 0);
+
+        // check ap mags for a few radii set by hand
+        ok_float_tol(growth->apMag->data.F32[0],   -9.7805, 0.0001, "apMag at radius 0: %f", growth->apMag->data.F32[0]);
+        ok_float_tol(growth->apMag->data.F32[3],  -10.3722, 0.0001, "apMag at radius 3: %f", growth->apMag->data.F32[3]);
+        ok_float_tol(growth->apMag->data.F32[10], -10.3759, 0.0001, "apMag at radius 10: %f", growth->apMag->data.F32[10]);
+        ok_float_tol(growth->apMag->data.F32[30], -10.3759, 0.0001, "apMag at radius 30: %f", growth->apMag->data.F32[30]);
+
+        ok_float_tol(growth->apRef,  -10.3759, 0.0001, "apMag at ref radius : %f", growth->apRef);
+        ok_float_tol(growth->fitMag, -10.3759, 0.0001, "fitMag : %f", growth->fitMag);
+        ok_float(growth->apLoss, 0.0, "apLoss : %f", growth->apLoss);
+
+        // create template model and measure apMag at fractional offsets
+        // XXX note model is at 0.5,0.5 subpix center
+        pmModel *modelRef = pmModelAlloc(psf->type);
+        modelRef->params->data.F32[PM_PAR_SKY] = 0;
+        modelRef->params->data.F32[PM_PAR_I0] = 1000;
+        modelRef->params->data.F32[PM_PAR_XPOS] = 32.3;
+        modelRef->params->data.F32[PM_PAR_YPOS] = 32.3;
+
+        // measure growth-corrected photometry:
+        pmSource *source = pmSourceAlloc ();
+        source->modelPSF = pmModelFromPSF (modelRef, psf);
+        source->type = PM_SOURCE_TYPE_STAR;
+        source->pixels = psMemIncrRefCounter (readout->image);
+        source->maskObj = psMemIncrRefCounter (readout->mask);
+
+        source->modelPSF->dparams->data.F32[PM_PAR_I0] = 1;
+        source->mode = PM_SOURCE_MODE_SUBTRACTED;
+
+        source->modelPSF->radiusFit = 15.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        double refMag = source->apMag;
+
+        source->modelPSF->radiusFit = 10.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        ok_float_tol(refMag - source->apMag, +0.0000, 0.0001, "growth offset is is %f", refMag - source->apMag);
+
+        source->modelPSF->radiusFit = 8.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        ok_float_tol(refMag - source->apMag, +0.0000, 0.0001, "growth offset is is %f", refMag - source->apMag);
+
+        source->modelPSF->radiusFit = 6.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        ok_float_tol(refMag - source->apMag, +0.0004, 0.0001, "growth offset is is %f", refMag - source->apMag);
+
+        source->modelPSF->radiusFit = 4.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        ok_float_tol(refMag - source->apMag, +0.0026, 0.0001, "growth offset is is %f", refMag - source->apMag);
+
+        source->modelPSF->radiusFit = 3.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        ok_float_tol(refMag - source->apMag, -0.0001, 0.0001, "growth offset is is %f", refMag - source->apMag);
+
+        source->modelPSF->radiusFit = 2.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        ok_float_tol(refMag - source->apMag, -0.0103, 0.0001, "growth offset is is %f", refMag - source->apMag);
+
+        // XXX include some apertures outside of growth correction range
+
+        psFree(modelRef);
+        psFree(source);
+        psFree(readout);
+        psFree(psf);
+
+        skip_end();
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // EM test 03: test allocation
+    // offset of 0.4,0.4 wrt growth ref source
+    {
+        psMemId id = psMemGetId();
+
+        pmGrowthCurve *growth = pmGrowthCurveAlloc (2.0, 100.0, 15.0);
+
+        ok(growth != NULL, "growth curve allocated");
+        skip_start(growth == NULL, 0, "Skipping tests because pmShutterCorrParsAlloc() failed");
+
+        ok(growth->radius->n == (100.0 - 2.0), "correct number of growth radii");
+        ok(growth->apMag->n == (100.0 - 2.0), "correct number of growth apMags");
+
+        ok_float(growth->refRadius, 15.0, "correct refRadius");
+        ok_float(growth->maxRadius, 100.0, "correct maxRadius");
+
+        // does the growth curve correctly fix aperture mags?
+
+        // generate a simple readout
+        pmReadout *readout = pmReadoutAlloc (NULL);
+        readout->image = psImageAlloc (64, 64, PS_TYPE_F32);
+        readout->mask  = psImageAlloc (64, 64, PS_TYPE_U8);
+
+        // create an empty reference image
+        psImageInit (readout->image, 0.0);
+        psImageInit (readout->mask, 0);
+
+        // generate a simple psf
+        pmPSF *psf = pmPSFBuildSimple ("PS_MODEL_GAUSS", 1.5, 1.5, 0.0);
+        psf->growth = growth;
+
+        pmGrowthCurveGenerate(readout, psf, false, 0, 0);
+
+        // check ap mags for a few radii set by hand
+        ok_float_tol(growth->apMag->data.F32[0],   -9.7805, 0.0001, "apMag at radius 0: %f", growth->apMag->data.F32[0]);
+        ok_float_tol(growth->apMag->data.F32[3],  -10.3722, 0.0001, "apMag at radius 3: %f", growth->apMag->data.F32[3]);
+        ok_float_tol(growth->apMag->data.F32[10], -10.3759, 0.0001, "apMag at radius 10: %f", growth->apMag->data.F32[10]);
+        ok_float_tol(growth->apMag->data.F32[30], -10.3759, 0.0001, "apMag at radius 30: %f", growth->apMag->data.F32[30]);
+
+        ok_float_tol(growth->apRef,  -10.3759, 0.0001, "apMag at ref radius : %f", growth->apRef);
+        ok_float_tol(growth->fitMag, -10.3759, 0.0001, "fitMag : %f", growth->fitMag);
+        ok_float(growth->apLoss, 0.0, "apLoss : %f", growth->apLoss);
+
+        // create template model and measure apMag at fractional offsets
+        // XXX note model is at 0.5,0.5 subpix center
+        pmModel *modelRef = pmModelAlloc(psf->type);
+        modelRef->params->data.F32[PM_PAR_SKY] = 0;
+        modelRef->params->data.F32[PM_PAR_I0] = 1000;
+        modelRef->params->data.F32[PM_PAR_XPOS] = 32.1;
+        modelRef->params->data.F32[PM_PAR_YPOS] = 32.1;
+
+        // measure growth-corrected photometry:
+        pmSource *source = pmSourceAlloc ();
+        source->modelPSF = pmModelFromPSF (modelRef, psf);
+        source->type = PM_SOURCE_TYPE_STAR;
+        source->pixels = psMemIncrRefCounter (readout->image);
+        source->maskObj = psMemIncrRefCounter (readout->mask);
+
+        source->modelPSF->dparams->data.F32[PM_PAR_I0] = 1;
+        source->mode = PM_SOURCE_MODE_SUBTRACTED;
+
+        source->modelPSF->radiusFit = 15.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        double refMag = source->apMag;
+
+        source->modelPSF->radiusFit = 10.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        ok_float_tol(refMag - source->apMag, +0.0000, 0.0001, "growth offset is is %f", refMag - source->apMag);
+
+        source->modelPSF->radiusFit = 8.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        ok_float_tol(refMag - source->apMag, +0.0000, 0.0001, "growth offset is is %f", refMag - source->apMag);
+
+        source->modelPSF->radiusFit = 6.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        ok_float_tol(refMag - source->apMag, +0.0006, 0.0001, "growth offset is is %f", refMag - source->apMag);
+
+        source->modelPSF->radiusFit = 4.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        ok_float_tol(refMag - source->apMag, +0.0038, 0.0001, "growth offset is is %f", refMag - source->apMag);
+
+        source->modelPSF->radiusFit = 3.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        ok_float_tol(refMag - source->apMag, +0.0000, 0.0001, "growth offset is is %f", refMag - source->apMag);
+
+        source->modelPSF->radiusFit = 2.0;
+        pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP, 0, 0);
+        ok_float_tol(refMag - source->apMag, -0.0164, 0.0001, "growth offset is is %f", refMag - source->apMag);
+
+        // XXX include some apertures outside of growth correction range
+
+        psFree(modelRef);
+        psFree(source);
+        psFree(readout);
+        psFree(psf);
+
+        skip_end();
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmModel.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmModel.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmModel.c	(revision 22158)
@@ -0,0 +1,460 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    All functions are tested.  However...
+
+    The source code for pmModelAddWithOffset() and pmModelSubWithOffset() is
+    almost exactly the same as the source code for pmModelAdd() and
+    pmModelSub().  We do not test them here.
+*/
+
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           (8+1)
+#define TEST_NUM_COLS           (8+1)
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#define NUM_ROWS		8
+#define NUM_COLS		16
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.01)
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(53);
+
+    // ----------------------------------------------------------------------
+    // pmModelAlloc() tests
+    // call pmModelAlloc() with unallowable model class type
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModel *model = pmModelAlloc(-1);
+        ok(model == NULL, "pmModelAlloc() returned a NULL with unallowable model class type");
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // call pmModelAlloc() with acceptable input params
+    {
+        #define TEST_MODEL_CLASS_TYPE 1
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        ok(model != NULL && psMemCheckModel(model), "pmModelAlloc() returned a non-NULL pmModel");
+        skip_start(!model, 1, "Skipping tests because pmModelAlloc() returned NULL");
+        ok(model->type == TEST_MODEL_CLASS_TYPE, "pmModelAlloc() set pmModel->type correctly");
+        ok(model->chisq == 0.0, "pmModelAlloc() set pmModel->chisq correctly");
+        ok(model->nDOF == 0, "pmModelAlloc() set pmModel->nDOF correctly");
+        ok(model->nIter == 0, "pmModelAlloc() set pmModel->nIter correctly");
+        ok(model->radiusFit == 0, "pmModelAlloc() set pmModel->radiusFit correctly");
+        ok(model->flags == PM_MODEL_STATUS_NONE, "pmModelAlloc() set pmModel->flags correctly");
+        ok(model->residuals == NULL, "pmModelAlloc() set pmModel->residuals correctly");
+        int nParams = pmModelClassParameterCount(TEST_MODEL_CLASS_TYPE);
+        ok(model->params != NULL && model->params->n == nParams, "pmModelAlloc() set the pmModel->params psVector correctly");
+        ok(model->dparams != NULL && model->dparams->n == nParams, "pmModelAlloc() set the pmModel->dparams psVector correctly");
+        bool errorFlag = false;
+        for (psS32 i = 0; i < nParams; i++) {
+            if (model->params->data.F32[i] != 0.0 || model->dparams->data.F32[i] != 0.0) {
+                if (VERBOSE) {
+                    diag("ERROR: params/dparams[%d] is (%.2f %.2f) should be (%.2f %.2f)\n", i, model->params->data.F32[i], model->dparams->data.F32[i], 0.0, 0.0);
+		}
+                errorFlag = true;
+	    }
+        }
+        ok(!errorFlag, "pmModelAlloc() set the members of the model->params and model->dparams psVectors correctly");
+        pmModelClass *class = pmModelClassSelect(TEST_MODEL_CLASS_TYPE);
+        ok(model->modelFunc == class->modelFunc, "pmModelAlloc() set pmModel->modelFunc correctly");
+        ok(model->modelFlux == class->modelFlux, "pmModelAlloc() set pmModel->modelFlux correctly");
+        ok(model->modelRadius == class->modelRadius, "pmModelAlloc() set pmModel->modelRadius correctly");
+        ok(model->modelLimits == class->modelLimits, "pmModelAlloc() set pmModel->modelLimits correctly");
+        ok(model->modelGuess == class->modelGuess, "pmModelAlloc() set pmModel->modelGuess correctly");
+        ok(model->modelFromPSF == class->modelFromPSF, "pmModelAlloc() set pmModel->modelFromPSF correctly");
+        ok(model->modelParamsFromPSF == class->modelParamsFromPSF, "pmModelAlloc() set pmModel->modelParamsFromPSF correctly");
+        ok(model->modelFitStatus == class->modelFitStatus, "pmModelAlloc() set pmModel->modelFitStatus correctly");
+
+        psFree(model);
+        skip_end();
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmModelCopy() tests
+    // call pmModelCopy() with NULL input pmModel parameter
+    {
+        psMemId id = psMemGetId();
+        pmModel *model = pmModelCopy(NULL);
+        ok(model == NULL, "pmModelCopy() returned NULL with NULL input pmModel parameter");
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // call pmModelCopy() with acceptable input params
+    {
+        #define TEST_MODEL_CLASS_TYPE 1
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModel *modelSrc = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        ok(modelSrc != NULL && psMemCheckModel(modelSrc), "pmModelAlloc() returned a non-NULL pmModel");
+        modelSrc->chisq = 1.0;
+        modelSrc->nDOF = 2;
+        modelSrc->nIter = 3;
+        modelSrc->flags = PM_MODEL_STATUS_NONE;
+        modelSrc->radiusFit = 4;
+        pmModel *modelDst = pmModelCopy(modelSrc);
+        ok(modelDst != NULL && psMemCheckModel(modelDst), "pmModelCopy() returned a non-NULL pmModel");
+        ok(modelDst->chisq == 1.0, "pmModelCopy() set the pmModel->chisq member correctly");
+        ok(modelDst->nDOF == 2, "pmModelCopy() set the pmModel->nDOF member correctly");
+        ok(modelDst->nIter == 3, "pmModelCopy() set the pmModel->nIter member correctly");
+        ok(modelDst->flags == PM_MODEL_STATUS_NONE, "pmModelCopy() set the pmModel->flags member correctly");
+        ok(modelDst->radiusFit == 4, "pmModelCopy() set the pmModel->radiusFit member correctly");
+
+        psFree(modelSrc);
+        psFree(modelDst);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmModelEval() tests
+    // call pmModelEval() with NULL input pmModel parameter
+    {
+        psMemId id = psMemGetId();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psF32 tmpF;
+        tmpF = pmModelEval(NULL, img, 0, 0);
+        ok(isnan(tmpF), "pmModelEval() returned NAN with NULL input pmModel parameter");
+        psFree(model);
+        psFree(img);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psF32 pmModelEval(pmModel *model, psImage *image, psS32 col, psS32 row)
+    // call pmModelEval() with NULL input psImage parameter
+    {
+        psMemId id = psMemGetId();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psF32 tmpF;
+        tmpF = pmModelEval(model, NULL, 0, 0);
+        ok(isnan(tmpF), "pmModelEval() returned NAN with NULL input psImage parameter");
+        psFree(model);
+        psFree(img);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psF32 pmModelEval(pmModel *model, psImage *image, psS32 col, psS32 row)
+    // call pmModelEval() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        for (int i = 0 ; i < NUM_ROWS ; i++) {
+            for (int j = 0 ; j < NUM_COLS ; j++) {
+                img->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        psVector *x = psVectorAlloc(2, PS_TYPE_F32);
+        x->data.F32[0] = (float) (NUM_COLS / 2);
+        x->data.F32[1] = (float) (NUM_ROWS / 2);
+        psF32 testF = model->modelFunc (NULL, model->params, x);
+        psF32 tmpF;
+        tmpF = pmModelEval(model, img, (int) x->data.F32[0], (int) x->data.F32[1]);
+        ok(!isnan(tmpF), "pmModelEval() returned successfully");
+        ok(testF == tmpF, "pmModelEval() evaluated the model correctly");
+        psFree(model);
+        psFree(img);
+        psFree(x);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+/* XXX: This seems to have disappeared from pmModel.h
+    // ----------------------------------------------------------------------
+    // pmModelEvalWithOffset() tests
+    // psF32 pmModelEvalWithOffset(pmModel *model, psImage *image, 
+    //                             psS32 col, psS32 row, int dx, int dy)
+    // call pmModelEvalWithOffset() with NULL input pmModel parameter
+    {
+        psMemId id = psMemGetId();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psF32 tmpF;
+        tmpF = pmModelEvalWithOffset(NULL, img, 0, 0, 0, 0);
+        ok(isnan(tmpF), "pmModelEvalWithOffset() returned NAN with NULL input pmModel parameter");
+        psFree(model);
+        psFree(img);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psF32 pmModelEvalWithOffset(pmModel *model, psImage *image, 
+    //                             psS32 col, psS32 row, int dx, int dy)
+    // call pmModelEvalWithOffset() with NULL input psImage parameter
+    {
+        psMemId id = psMemGetId();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psF32 tmpF;
+        tmpF = pmModelEvalWithOffset(model, NULL, 0, 0, 0, 0);
+        ok(isnan(tmpF), "pmModelEvalWithOffset() returned NAN with NULL input psImage parameter");
+        psFree(model);
+        psFree(img);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psF32 pmModelEvalWithOffset(pmModel *model, psImage *image, psS32 col, psS32 row)
+    // call pmModelEvalWithOffset() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        for (int i = 0 ; i < NUM_ROWS ; i++) {
+            for (int j = 0 ; j < NUM_COLS ; j++) {
+                img->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        psVector *x = psVectorAlloc(2, PS_TYPE_F32);
+        x->data.F32[0] = (float) ((NUM_COLS / 2) + (NUM_COLS / 4));
+        x->data.F32[1] = (float) ((NUM_ROWS / 2) + (NUM_ROWS / 4));
+        psF32 testF = model->modelFunc (NULL, model->params, x);
+        psF32 tmpF;
+        tmpF = pmModelEvalWithOffset(model, img, (int) x->data.F32[0], (int) x->data.F32[1], NUM_COLS/4, NUM_ROWS/4);
+        ok(!isnan(tmpF), "pmModelEvalWithOffset() returned successfully");
+        ok(testF == tmpF, "pmModelEvalWithOffset() evaluated the model correctly");
+        psFree(model);
+        psFree(img);
+        psFree(x);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+*/
+
+
+    // ----------------------------------------------------------------------
+    // pmModelAdd() tests
+    // call pmModelAdd() with bad input parameters
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psImage *imgS32 = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_S32);
+        psImage *mask = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_U8);
+        for (int i = 0 ; i < NUM_ROWS ; i++) {
+            for (int j = 0 ; j < NUM_COLS ; j++) {
+                img->data.F32[i][j] = 0.0;
+                mask->data.U8[i][j] = 0;
+            }
+        }
+        pmModel *model = pmModelAlloc(pmModelClassGetType("PS_MODEL_GAUSS"));
+        psF32 *PAR = model->params->data.F32;
+        PAR[PM_PAR_XPOS] = (float) (NUM_COLS/2);
+        PAR[PM_PAR_YPOS] = (float) (NUM_ROWS/2);
+        PAR[PM_PAR_SXX] = 1.0;
+        PAR[PM_PAR_SYY] = 1.0;
+
+        // NULL psImage input parameter
+        bool rc = pmModelAdd(NULL, mask, model, PM_MODEL_OP_FUNC, 1);
+        ok(rc == false, "pmModelAdd() returned FALSE with NULL psImage input parameter");
+
+        // NULL pmModel input parameter
+        rc = pmModelAdd(img, mask, NULL, PM_MODEL_OP_FUNC, 1);
+        ok(rc == false, "pmModelAdd() returned FALSE with NULL pmModel input parameter");
+
+        // Incorrect type psImage input parameter
+        rc = pmModelAdd(imgS32, mask, model, PM_MODEL_OP_FUNC, 1);
+        ok(rc == false, "pmModelAdd() returned FALSE with Incorrect type psImage input parameter");
+
+        psFree(img);
+        psFree(imgS32);
+        psFree(mask);
+        psFree(model);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // call pmModelAdd() with acceptable parameters
+    // We only test with a single Gaussian model, with no residuals or masks.
+    // For completeness, additional tests should be added.
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psImage *mask = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_U8);
+        for (int i = 0 ; i < NUM_ROWS ; i++) {
+            for (int j = 0 ; j < NUM_COLS ; j++) {
+                img->data.F32[i][j] = 0.0;
+                mask->data.U8[i][j] = 0;
+            }
+        }
+        pmModel *model = pmModelAlloc(pmModelClassGetType("PS_MODEL_GAUSS"));
+        psF32 *PAR = model->params->data.F32;
+        PAR[PM_PAR_I0] = 5.0;
+        PAR[PM_PAR_XPOS] = 0.0;
+        PAR[PM_PAR_YPOS] = 0.0;
+        PAR[PM_PAR_XPOS] = (float) (NUM_COLS/2);
+        PAR[PM_PAR_YPOS] = (float) (NUM_ROWS/2);
+        PAR[PM_PAR_SXX] = 10.0;
+        PAR[PM_PAR_SYY] = 10.0;
+
+        bool rc = pmModelAdd(img, mask, model, PM_MODEL_OP_FUNC, 1);
+        ok(rc == true, "pmModelAdd() returned TRUE with acceptable input parameters");
+        psVector *x = psVectorAlloc(2, PS_TYPE_F32);
+        bool errorFlag = false;
+        for (int i = 0 ; i < NUM_ROWS ; i++) {
+            for (int j = 0 ; j < NUM_COLS ; j++) {
+                x->data.F32[0] = (float) j;
+                x->data.F32[1] = (float) i;
+                psF32 modF = model->modelFunc (NULL, model->params, x);
+                psF32 imgF = img->data.F32[i][j];
+                if (!TEST_FLOATS_EQUAL(modF, imgF)) {
+                    diag("ERROR: img[%d][%d] is %.2f, should be %.2f\n", i, j, img->data.F32[i][j], modF);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "pmModelAdd() set the image pixels correctly");
+        psFree(x);
+        psFree(img);
+        psFree(mask);
+        psFree(model);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmModelSub() tests
+    // call pmModelSub() with bad input parameters
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psImage *imgS32 = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_S32);
+        psImage *mask = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_U8);
+        for (int i = 0 ; i < NUM_ROWS ; i++) {
+            for (int j = 0 ; j < NUM_COLS ; j++) {
+                img->data.F32[i][j] = 0.0;
+                mask->data.U8[i][j] = 0;
+            }
+        }
+        pmModel *model = pmModelAlloc(pmModelClassGetType("PS_MODEL_GAUSS"));
+        psF32 *PAR = model->params->data.F32;
+        PAR[PM_PAR_XPOS] = (float) (NUM_COLS/2);
+        PAR[PM_PAR_YPOS] = (float) (NUM_ROWS/2);
+        PAR[PM_PAR_SXX] = 1.0;
+        PAR[PM_PAR_SYY] = 1.0;
+
+        // NULL psImage input parameter
+        bool rc = pmModelSub(NULL, mask, model, PM_MODEL_OP_FUNC, 1);
+        ok(rc == false, "pmModelSub() returned FALSE with NULL psImage input parameter");
+
+        // NULL pmModel input parameter
+        rc = pmModelSub(img, mask, NULL, PM_MODEL_OP_FUNC, 1);
+        ok(rc == false, "pmModelSub() returned FALSE with NULL pmModel input parameter");
+
+        // Incorrect type psImage input parameter
+        rc = pmModelSub(imgS32, mask, model, PM_MODEL_OP_FUNC, 1);
+        ok(rc == false, "pmModelSub() returned FALSE with Incorrect type psImage input parameter");
+
+        psFree(img);
+        psFree(imgS32);
+        psFree(mask);
+        psFree(model);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // call pmModelSub() with acceptable parameters
+    // We only test with a single Gaussian model, with no residuals or masks.
+    // For completeness, additional tests should be added.
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psImage *mask = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_U8);
+        for (int i = 0 ; i < NUM_ROWS ; i++) {
+            for (int j = 0 ; j < NUM_COLS ; j++) {
+                img->data.F32[i][j] = 0.0;
+                mask->data.U8[i][j] = 0;
+            }
+        }
+        pmModel *model = pmModelAlloc(pmModelClassGetType("PS_MODEL_GAUSS"));
+        psF32 *PAR = model->params->data.F32;
+        PAR[PM_PAR_I0] = 5.0;
+        PAR[PM_PAR_XPOS] = 0.0;
+        PAR[PM_PAR_YPOS] = 0.0;
+        PAR[PM_PAR_XPOS] = (float) (NUM_COLS/2);
+        PAR[PM_PAR_YPOS] = (float) (NUM_ROWS/2);
+        PAR[PM_PAR_SXX] = 10.0;
+        PAR[PM_PAR_SYY] = 10.0;
+
+        bool rc = pmModelSub(img, mask, model, PM_MODEL_OP_FUNC, 1);
+        ok(rc == true, "pmModelSub() returned TRUE with acceptable input parameters");
+        psVector *x = psVectorAlloc(2, PS_TYPE_F32);
+        bool errorFlag = false;
+        for (int i = 0 ; i < NUM_ROWS ; i++) {
+            for (int j = 0 ; j < NUM_COLS ; j++) {
+                x->data.F32[0] = (float) j;
+                x->data.F32[1] = (float) i;
+                psF32 modF = model->modelFunc (NULL, model->params, x);
+                psF32 imgF = img->data.F32[i][j];
+                if (!TEST_FLOATS_EQUAL(modF, -imgF)) {
+                    diag("ERROR: img[%d][%d] is %.2f, should be %.2f\n", i, j, img->data.F32[i][j], modF);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "pmModelSub() set the image pixels correctly");
+        psFree(x);
+        psFree(img);
+        psFree(mask);
+        psFree(model);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // XXX: The source code for pmModelAddWithOffset() and pmModelSubWithOffset() is
+    // almost exactly the same as the source code for pmModelAdd() and pmModelSub().
+    // We do not test them here.
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmModelClass.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmModelClass.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmModelClass.c	(revision 22158)
@@ -0,0 +1,181 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    All functions are tested except pmModelClassCleanup() which is deferred
+    because there's no way to test that it frees a static variable, except
+    throug hthe memory leak tests
+*/
+
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           (8+1)
+#define TEST_NUM_COLS           (8+1)
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#include "models/pmModel_GAUSS.c"
+#include "models/pmModel_PGAUSS.c"
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(37);
+
+    // ----------------------------------------------------------------------
+    // Test pmModelClassAlloc()
+    // pmModelClass *pmModelClassAlloc (int nModels)
+    {
+        psMemId id = psMemGetId();
+        pmModelClass *modelClass = pmModelClassAlloc(4);
+        ok(modelClass != NULL && psMemCheckModelClass(modelClass), "pmModelClassAlloc() returned a non-NULL pmModelClass");
+        psFree(modelClass);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Test pmModelClassCleanup(), pmModelClassSelect()
+    // Basically, call pmModelClassInit(), then pmModelClassCleanup(), and ensure that
+    // various default models are not there.
+    // XXX: We don't run this test because the spec changed and pmModelClassSelect() now calls
+    // pmModelClassInit().
+    if (0) {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModelClassCleanup();
+        ok(NULL == pmModelClassSelect(0), "pmModelClassCleanup(): removed PS_MODEL_GAUSS");
+        ok(NULL == pmModelClassSelect(1), "pmModelClassCleanup(): removed PS_MODEL_PGAUSS");
+        ok(NULL == pmModelClassSelect(2), "pmModelClassCleanup(): removed PS_MODEL_QGAUSS");
+        ok(NULL == pmModelClassSelect(3), "pmModelClassCleanup(): removed PS_MODEL_RGAUSS");
+        ok(NULL == pmModelClassSelect(4), "pmModelClassCleanup(): removed PS_MODEL_SERSIC");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Test pmModelClassInit(), pmModelClassGetName()
+    // Basically, call pmModelClassCleanup(), then pmModelClassInit() and ensure that
+    // various default models are there.
+    {
+        psMemId id = psMemGetId();
+
+        pmModelClassCleanup();
+        ok(pmModelClassInit(), "pmModelClassInit() returned TRUE");
+        ok(!strcmp(pmModelClassGetName(0), "PS_MODEL_GAUSS"), "pmModelClassInit() added pmModel PS_MODEL_GAUSS");
+        ok(!strcmp(pmModelClassGetName(1), "PS_MODEL_PGAUSS"), "pmModelClassInit() added pmModel PS_MODEL_PGAUSS");
+        ok(!strcmp(pmModelClassGetName(2), "PS_MODEL_QGAUSS"), "pmModelClassInit() added pmModel PS_MODEL_QGAUSS");
+        ok(!strcmp(pmModelClassGetName(3), "PS_MODEL_RGAUSS"), "pmModelClassInit() added pmModel PS_MODEL_RGAUSS");
+        ok(!strcmp(pmModelClassGetName(4), "PS_MODEL_SERSIC"), "pmModelClassInit() added pmModel PS_MODEL_SERSIC");
+        ok(!pmModelClassInit(), "pmModelClassInit() returned FALSE (2nd time)");
+        ok(NULL == pmModelClassGetName(-1), "pmModelClassGetName(-1) returned NULL");
+        ok(NULL == pmModelClassGetName(1000), "pmModelClassGetName(1000) returned NULL");
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Test pmModelClassGetType()
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        ok(-1 == pmModelClassGetType("BOGUS"), "pmModelClassGetType(BOGUS) returned -1");
+        ok(0 == pmModelClassGetType("PS_MODEL_GAUSS"), "pmModelClassGetType(PS_MODEL_GAUSS) successful");
+        ok(1 == pmModelClassGetType("PS_MODEL_PGAUSS"), "pmModelClassGetType(PS_MODEL_PGAUSS) successful");
+        ok(2 == pmModelClassGetType("PS_MODEL_QGAUSS"), "pmModelClassGetType(PS_MODEL_QGAUSS) successful");
+        ok(3 == pmModelClassGetType("PS_MODEL_RGAUSS"), "pmModelClassGetType(PS_MODEL_RGAUSS) successful");
+        ok(4 == pmModelClassGetType("PS_MODEL_SERSIC"), "pmModelClassGetType(PS_MODEL_SERSIC) successful");
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Test pmModelClassParameterCount()
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        ok(0 == pmModelClassParameterCount(-1), "pmModelClassParameterCount(-1) returned 0");
+        ok(0 == pmModelClassParameterCount(1000), "pmModelClassParameterCount(1000) returned 0");
+        ok(7 == pmModelClassParameterCount(0), "pmModelClassParameterCount(0) returned 7");
+        ok(7 == pmModelClassParameterCount(1), "pmModelClassParameterCount(1) returned 7");
+        ok(8 == pmModelClassParameterCount(2), "pmModelClassParameterCount(2) returned 8");
+        ok(8 == pmModelClassParameterCount(3), "pmModelClassParameterCount(3) returned 8");
+        ok(8 == pmModelClassParameterCount(4), "pmModelClassParameterCount(4) returned 8");
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Test pmModelClassSelect()
+    // pmModelClass *pmModelClassSelect (pmModelType type)
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModelClass *model = NULL;
+        model = pmModelClassSelect(-1);
+        ok(model == NULL, "pmModelClassSelect(-1) successful");
+        model = pmModelClassSelect(1000);
+        ok(model == NULL, "pmModelClassSelect(1000) successful");
+        model = pmModelClassSelect(0);
+        ok(model != NULL && !strcmp(model->name, "PS_MODEL_GAUSS"), "pmModelClassSelect(0) successful");
+        model = pmModelClassSelect(1);
+        ok(model != NULL && !strcmp(model->name, "PS_MODEL_PGAUSS"), "pmModelClassSelect(1) successful");
+        model = pmModelClassSelect(2);
+        ok(model != NULL && !strcmp(model->name, "PS_MODEL_QGAUSS"), "pmModelClassSelect(2) successful");
+        model = pmModelClassSelect(3);
+        ok(model != NULL && !strcmp(model->name, "PS_MODEL_RGAUSS"), "pmModelClassSelect(3) successful");
+        model = pmModelClassSelect(4);
+        ok(model != NULL && !strcmp(model->name, "PS_MODEL_SERSIC"), "pmModelClassSelect(4) successful");
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Test pmModelClassAdd()
+    // We create a new modelClass, then add it, then ensure that it exists.
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModelClass *newModel = pmModelClassAlloc(1);
+        newModel->name = psStringCopy("PS_MODEL_NEW00");
+        newModel->nParams = 22;
+        pmModelClassAdd(newModel);
+        int ID = pmModelClassGetType("PS_MODEL_NEW00");
+        ok(ID != -1 && !strcmp("PS_MODEL_NEW00", pmModelClassGetName(ID)), "pmModelClassAdd() added the new model successfully");
+        psFree(newModel->name);
+        psFree(newModel);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmModelUtils.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmModelUtils.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmModelUtils.c	(revision 22158)
@@ -0,0 +1,203 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+	All functions are tested.
+*/
+
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#define NUM_ROWS		8
+#define NUM_COLS		16
+#define TEST_MODEL_CLASS_TYPE 1
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.0001)
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(46);
+
+    // ----------------------------------------------------------------------
+    // pmModelFromPSF() tests
+    // pmModel *pmModelFromPSF (pmModel *modelEXT, pmPSF *psf)
+    // call pmModelFromPSF() with NULL pmModel input parameter
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        pmPSFOptions *psfOptions = pmPSFOptionsAlloc();
+        psfOptions->type = pmModelClassGetType("PS_MODEL_GAUSS");
+        pmPSF *psf = pmPSFAlloc(psfOptions);
+        pmModel *tmpModel = pmModelFromPSF(NULL, psf);
+        ok(tmpModel == NULL, "pmModelFromPSF() returned NULL with NULL pmModel input parameter");
+        psFree(model);
+        psFree(psfOptions);
+        psFree(psf);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // call pmModelFromPSF() with NULL pmPSF input parameter
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        pmPSFOptions *psfOptions = pmPSFOptionsAlloc();
+        psfOptions->type = pmModelClassGetType("PS_MODEL_GAUSS");
+        pmPSF *psf = pmPSFAlloc(psfOptions);
+        pmModel *tmpModel = pmModelFromPSF(model, NULL);
+        ok(tmpModel == NULL, "pmModelFromPSF() returned NULL with NULL pmPSF input parameter");
+        psFree(model);
+        psFree(psfOptions);
+        psFree(psf);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // call pmModelFromPSF() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        pmPSFOptions *psfOptions = pmPSFOptionsAlloc();
+        psfOptions->type = pmModelClassGetType("PS_MODEL_GAUSS");
+        pmPSF *psf = pmPSFAlloc(psfOptions);
+        pmModel *tmpModel = pmModelFromPSF(model, psf);
+        ok(tmpModel != NULL, "pmModelFromPSF() returned non-NULL with acceptable input parameters");
+
+        pmModel *testModelPSF = pmModelAlloc(psf->type);
+        model->modelFromPSF(testModelPSF, model, psf);
+        ok(tmpModel->type == testModelPSF->type, "pmModelFromPSF() set the model->type correctly");
+        ok(tmpModel->chisq == testModelPSF->chisq, "pmModelFromPSF() set the model->chisq correctly");
+        ok(tmpModel->chisqNorm == testModelPSF->chisqNorm, "pmModelFromPSF() set the model->chisqNorm correctly");
+        ok(tmpModel->nDOF == testModelPSF->nDOF, "pmModelFromPSF() set the model->nDOF correctly");
+        ok(tmpModel->nIter == testModelPSF->nIter, "pmModelFromPSF() set the model->nIter correctly");
+        ok(tmpModel->flags == testModelPSF->flags, "pmModelFromPSF() set the model->flags correctly");
+        ok(tmpModel->radiusFit == testModelPSF->radiusFit, "pmModelFromPSF() set the model->radiusFit correctly");
+        ok(tmpModel->modelFunc == testModelPSF->modelFunc, "pmModelFromPSF() set the model->modelFunc correctly");
+        ok(tmpModel->modelFlux == testModelPSF->modelFlux, "pmModelFromPSF() set the model->modelFlux correctly");
+        ok(tmpModel->modelRadius == testModelPSF->modelRadius, "pmModelFromPSF() set the model->modelRadius correctly");
+        ok(tmpModel->modelLimits == testModelPSF->modelLimits, "pmModelFromPSF() set the model->modelLimits correctly");
+        ok(tmpModel->modelGuess == testModelPSF->modelGuess, "pmModelFromPSF() set the model->modelGuess correctly");
+        ok(tmpModel->modelFromPSF == testModelPSF->modelFromPSF, "pmModelFromPSF() set the model->modelFromPSF correctly");
+        ok(tmpModel->modelParamsFromPSF == testModelPSF->modelParamsFromPSF, "pmModelFromPSF() set the model->modelParamsFromPSF correctly");
+        ok(tmpModel->modelFitStatus == testModelPSF->modelFitStatus, "pmModelFromPSF() set the model->modelFitStatus correctly");
+
+        psFree(testModelPSF);
+        psFree(tmpModel);
+        psFree(model);
+        psFree(psfOptions);
+        psFree(psf);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmModelFromPSFforXY() tests
+    // pmModel *pmModelFromPSFforXY (pmPSF *psf, float Xo, float Yo, float Io)
+    // call pmModelFromPSFforXY() with NULL pmPSF input parameter
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmPSFOptions *psfOptions = pmPSFOptionsAlloc();
+        psfOptions->type = pmModelClassGetType("PS_MODEL_GAUSS");
+        pmPSF *psf = pmPSFAlloc(psfOptions);
+        pmModel *tmpModel = pmModelFromPSFforXY(NULL, 1.0, 2.0, 3.0);
+        ok(tmpModel == NULL, "pmModelFromPSFforXY() returned NULL with NULL pmPSF input parameter");
+        psFree(psfOptions);
+        psFree(psf);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // call pmModelFromPSFforXY() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmPSFOptions *psfOptions = pmPSFOptionsAlloc();
+        psfOptions->type = pmModelClassGetType("PS_MODEL_GAUSS");
+        pmPSF *psf = pmPSFAlloc(psfOptions);
+
+        pmModel *testModelPSF = pmModelAlloc (psf->type);
+        testModelPSF->modelParamsFromPSF(testModelPSF, psf, 1.0, 2.0, 3.0);
+
+        pmModel *tmpModel = pmModelFromPSFforXY(psf, 1.0, 2.0, 3.0);
+        ok(tmpModel != NULL, "pmModelFromPSFforXY() returned non-NULL with acceptable input parameters");
+
+        ok(tmpModel->type == testModelPSF->type, "pmModelFromPSF() set the model->type correctly");
+        ok(tmpModel->chisq == testModelPSF->chisq, "pmModelFromPSF() set the model->chisq correctly");
+        ok(TEST_FLOATS_EQUAL(tmpModel->chisqNorm, testModelPSF->chisqNorm), "pmModelFromPSF() set the model->chisqNorm correctly");
+        ok(tmpModel->nDOF == testModelPSF->nDOF, "pmModelFromPSF() set the model->nDOF correctly");
+        ok(tmpModel->nIter == testModelPSF->nIter, "pmModelFromPSF() set the model->nIter correctly");
+        ok(tmpModel->flags == testModelPSF->flags, "pmModelFromPSF() set the model->flags correctly");
+        ok(tmpModel->radiusFit == testModelPSF->radiusFit, "pmModelFromPSF() set the model->radiusFit correctly");
+        ok(tmpModel->modelFunc == testModelPSF->modelFunc, "pmModelFromPSF() set the model->modelFunc correctly");
+        ok(tmpModel->modelFlux == testModelPSF->modelFlux, "pmModelFromPSF() set the model->modelFlux correctly");
+        ok(tmpModel->modelRadius == testModelPSF->modelRadius, "pmModelFromPSF() set the model->modelRadius correctly");
+        ok(tmpModel->modelLimits == testModelPSF->modelLimits, "pmModelFromPSF() set the model->modelLimits correctly");
+        ok(tmpModel->modelGuess == testModelPSF->modelGuess, "pmModelFromPSF() set the model->modelGuess correctly");
+        ok(tmpModel->modelFromPSF == testModelPSF->modelFromPSF, "pmModelFromPSF() set the model->modelFromPSF correctly");
+        ok(tmpModel->modelParamsFromPSF == testModelPSF->modelParamsFromPSF, "pmModelFromPSF() set the model->modelParamsFromPSF correctly");
+        ok(tmpModel->modelFitStatus == testModelPSF->modelFitStatus, "pmModelFromPSF() set the model->modelFitStatus correctly");
+
+        psFree(tmpModel);
+        psFree(testModelPSF);
+        psFree(psfOptions);
+        psFree(psf);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmModelSetFlux() tests
+    // bool pmModelSetFlux(pmModel *model, float flux) {
+    // call pmModelSetFlux() with NULL pmPSF input parameter
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        bool rc = pmModelSetFlux(NULL, 1.0);
+        ok(!rc, "pmModelSetFlux(() returned FALSE with NULL pmModel input parameter");
+        psFree(model);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // call pmModelSetFlux() with acceptable input parameters
+    // XXX: We should probably test with more input values
+    {
+        psMemId id = psMemGetId();
+        pmModelClassInit();
+        pmModel *model = pmModelAlloc(TEST_MODEL_CLASS_TYPE);
+        model->params->data.F32[PM_PAR_SXX] = 1.0;
+        model->params->data.F32[PM_PAR_SYY] = 1.0;
+        model->params->data.F32[PM_PAR_SXY] = 1.0;
+
+        // Compute the test flux value
+        float tmpF = model->params->data.F32[PM_PAR_I0];
+        model->params->data.F32[PM_PAR_I0] = 1.0;
+        float testFlux = model->modelFlux (model->params);
+        testFlux = 1.0 / testFlux;    
+        model->params->data.F32[PM_PAR_I0] = tmpF;
+
+        bool rc = pmModelSetFlux(model, 1.0);
+        ok(rc, "pmModelSetFlux(() returned TRUE with acceptable input parameters");
+        ok(TEST_FLOATS_EQUAL(testFlux, model->params->data.F32[PM_PAR_I0]), "pmModelSetFlux() set the flux correctly");
+        psFree(model);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmMoments.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmMoments.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmMoments.c	(revision 22158)
@@ -0,0 +1,33 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(11);
+
+    // Test pmMomentsAlloc()
+    {
+        psMemId id = psMemGetId();
+        pmMoments *tmpMoments = pmMomentsAlloc();
+        ok(tmpMoments != NULL, "pmMomentsAlloc() returned a non-NULL pmMoments");
+        skip_start(tmpMoments == NULL, 9, "Skipping tests because pmMomentsAlloc() returned NULL");
+        ok(tmpMoments->x == 0.0, "pmMomentsAlloc set->x correctly");
+        ok(tmpMoments->y == 0.0, "pmMomentsAlloc set->y correctly");
+        ok(tmpMoments->Sx == 0.0, "pmMomentsAlloc set->Sx correctly");
+        ok(tmpMoments->Sy == 0.0, "pmMomentsAlloc set->Sy correctly");
+        ok(tmpMoments->Sxy == 0.0, "pmMomentsAlloc set->Sxy correctly");
+        ok(tmpMoments->Sum == 0.0, "pmMomentsAlloc set->Sum correctly");
+        ok(tmpMoments->Peak == 0.0, "pmMomentsAlloc set->Peak correctly");
+        ok(tmpMoments->Sky == 0.0, "pmMomentsAlloc set->Sky correctly");
+        ok(tmpMoments->nPixels == 0, "pmMomentsAlloc set->nPixels correctly");
+        psFree(tmpMoments);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmPSF.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmPSF.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmPSF.c	(revision 22158)
@@ -0,0 +1,326 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/*
+Tested:
+    pmPSFOptions *pmPSFOptionsAlloc()
+    pmPSF *pmPSFAlloc (pmPSFOptions *options)
+    bool psMemCheckPSF(psPtr ptr)
+Must test:
+    double pmPSF_SXYfromModel (psF32 *modelPar)
+    double pmPSF_SXYtoModel (psF32 *fittedPar)
+    bool pmGrowthCurveGenerate (pmReadout *readout, pmPSF *psf, bool ignore, psMas!
+    pmPSF *pmPSFBuildSimple (char *typeName, float sxx, float syy, float sxy, ...)
+    bool pmPSF_AxesToModel (psF32 *modelPar, psEllipseAxes axes)
+    bool pmPSF_FitToModel (psF32 *fittedPar, float minMinorAxis)
+    psEllipsePol pmPSF_ModelToFit (psF32 *modelPar)
+    psEllipseAxes pmPSF_ModelToAxes (psF32 *modelPar, double maxAR)
+*/
+
+
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         10
+#define TEST_FLOATS_EQUAL(X, Y) (abs((X) - (Y)) < 0.0001)
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(83);
+
+    // ----------------------------------------------------------------------
+    // pmPSFOptionsAlloc() tests
+    // pmPSFOptions *pmPSFOptionsAlloc()
+    {
+        psMemId id = psMemGetId();
+        pmPSFOptions *psfOptions = pmPSFOptionsAlloc();
+        ok(psfOptions != NULL && psMemCheckPSFOptions(psfOptions), "pmPSFOptionsAlloc() returned non-NULL");
+        ok(psfOptions->type == 0, "pmPSFOptionsAlloc set pmPSFOptions->type ");
+        ok(psfOptions->stats == NULL, "pmPSFOptionsAlloc set pmPSFOptions->stats ");
+        ok(psfOptions->psfTrendMode == PM_TREND_NONE, "pmPSFOptionsAlloc set pmPSFOptions->psfTrendMode ");
+        ok(psfOptions->psfTrendNx == 0, "pmPSFOptionsAlloc set pmPSFOptions->psfTrendNx ");
+        ok(psfOptions->psfTrendNy == 0, "pmPSFOptionsAlloc set pmPSFOptions->psfTrendNy ");
+        ok(psfOptions->psfFieldNx == 0, "pmPSFOptionsAlloc set pmPSFOptions->psfFieldNx ");
+        ok(psfOptions->psfFieldNy == 0, "pmPSFOptionsAlloc set pmPSFOptions->psfFieldNy ");
+        ok(psfOptions->psfFieldXo == 0, "pmPSFOptionsAlloc set pmPSFOptions->psfFieldXo ");
+        ok(psfOptions->psfFieldYo == 0, "pmPSFOptionsAlloc set pmPSFOptions->psfFieldYo ");
+        ok(psfOptions->poissonErrorsPhotLMM == true, "pmPSFOptionsAlloc set pmPSFOptions->poissonErrorsPhotLMM ");
+        ok(psfOptions->poissonErrorsPhotLin == false, "pmPSFOptionsAlloc set pmPSFOptions->poissonErrorsPhotLin ");
+        ok(psfOptions->poissonErrorsParams  == true, "pmPSFOptionsAlloc set pmPSFOptions->poissonErrorsParams ");
+        psFree(psfOptions);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmPSFAlloc() tests
+    // call pmPSFAlloc() with NULL input parameters
+    #define TEST_POISSON_ERRORS true
+    {
+        psMemId id = psMemGetId();
+        pmPSF *psf = pmPSFAlloc(NULL);
+        ok(psf == NULL, "pmPSFAlloc() returned NULL with NULL input parameters");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // call pmPSFAlloc() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmPSFOptions *psfOptions = pmPSFOptionsAlloc();
+        psfOptions->psfTrendNx = 1;
+        psfOptions->psfTrendNy = 2;
+        psfOptions->psfFieldNx = 3;
+        psfOptions->psfFieldNy = 4;
+        psfOptions->psfFieldXo = 5;
+        psfOptions->psfFieldYo = 6;
+        pmModelClassInit();
+        psfOptions->type = pmModelClassGetType("PS_MODEL_GAUSS");
+        pmPSF *psf = pmPSFAlloc(psfOptions);
+        ok(psf != NULL && psMemCheckPSF(psf), "pmPSFAlloc() returned non-NULL");
+        ok(psf->type == psfOptions->type, "pmPSFAlloc() set the pmPSF->type correctly");
+        ok(psf->chisq == 0.0, "pmPSFAlloc() set the pmPSF->chisq correctly");
+        ok(psf->ApResid == 0.0, "pmPSFAlloc() set the pmPSF->ApResid correctly");
+        ok(psf->dApResid == 0.0, "pmPSFAlloc() set the pmPSF->dApResid correctly");
+        ok(psf->skyBias == 0.0, "pmPSFAlloc() set the pmPSF->skyBias correctly");
+        ok(psf->skySat == 0.0, "pmPSFAlloc() set the pmPSF->skySat correctly");
+        ok(psf->nPSFstars == 0, "pmPSFAlloc() set the pmPSF->nPSFstars correctly");
+        ok(psf->nApResid == 0, "pmPSFAlloc() set the pmPSF->nApResid correctly");
+        int Nparams = pmModelClassParameterCount(psfOptions->type);
+        ok(psf->params != NULL &&
+           psMemCheckArray(psf->params) &&
+           psf->params->n == Nparams, "pmPSFAlloc() set the pmPSF->params correctly");
+        ok(psf->poissonErrorsPhotLMM == psfOptions->poissonErrorsPhotLMM, "pmPSFAlloc() set the pmPSF->poissonErrorsPhotLMM");
+        ok(psf->poissonErrorsPhotLin == psfOptions->poissonErrorsPhotLin, "pmPSFAlloc() set the pmPSF->poissonErrorsPhotLin");
+        ok(psf->poissonErrorsParams == psfOptions->poissonErrorsParams, "pmPSFAlloc() set the pmPSF->poissonErrorsParams");
+        ok(psf->ApTrend == NULL, "pmPSFAlloc() set the pmPSF->ApTrend");
+        ok(psf->FluxScale == NULL, "pmPSFAlloc() set the pmPSF->FluxScale");
+        ok(psf->growth == NULL, "pmPSFAlloc() set the pmPSF->growth");
+        ok(psf->residuals == NULL, "pmPSFAlloc() set the pmPSF->residuals");
+        ok(psf->psfTrendMode == psfOptions->psfTrendMode, "pmPSFAlloc() set the pmPSF->psfTrendMode");
+        ok(psf->trendNx == psfOptions->psfTrendNx, "pmPSFAlloc() set the pmPSF->trendNx (%d %d)", psf->trendNx, psfOptions->psfTrendNx);
+        ok(psf->trendNy == psfOptions->psfTrendNy, "pmPSFAlloc() set the pmPSF->trendNy (%d %d)", psf->trendNy, psfOptions->psfTrendNy);
+        ok(psf->fieldNx == psfOptions->psfFieldNx, "pmPSFAlloc() set the pmPSF->fieldNx");
+        ok(psf->fieldNy == psfOptions->psfFieldNy, "pmPSFAlloc() set the pmPSF->fieldNy");
+        ok(psf->fieldXo == psfOptions->psfFieldXo, "pmPSFAlloc() set the pmPSF->fieldXo");
+        ok(psf->fieldYo == psfOptions->psfFieldYo, "pmPSFAlloc() set the pmPSF->fieldYo");
+        ok(psf->ApTrend == NULL, "pmPSFAlloc() set the pmPSF->ApTrend correctly");
+        ok(psf->FluxScale == NULL, "pmPSFAlloc() set the pmPSF->FluxScale correctly");
+
+        if (psf->poissonErrorsPhotLMM) {
+            ok(psf->ChiTrend->nX == 1, "pmPSFAlloc() set the pmPSF->ChiTrend correctly");
+	} else {
+            ok(psf->ChiTrend->nX == 2, "pmPSFAlloc() set the pmPSF->ChiTrend correctly");
+	}
+        ok(psf->growth == NULL, "pmPSFAlloc() set the pmPSF->growth correctly");
+        ok(psf->residuals == NULL, "pmPSFAlloc() set the pmPSF->residuals correctly");
+        ok(psf->params != NULL && psMemCheckArray(psf->params) && psf->params->n == Nparams, 
+           "pmPSFAlloc() set the pmPSF->params psVector correctly");
+
+        pmModelClassCleanup();
+        psFree(psf);
+        psFree(psfOptions);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmPSF_SXYfromModel() tests
+    // Call pmPSF_SXYfromModel() with NULL input parameters
+    {
+        psMemId id = psMemGetId();
+        double tmpD = pmPSF_SXYfromModel(NULL);
+        ok(isnan(tmpD), "pmPSF_SXYfromModel() returned NULL with NULL input parameters");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSF_SXYfromModel() with NULL input parameters
+    {
+        psMemId id = psMemGetId();
+        psF32 modelPar[20];
+        modelPar[PM_PAR_SXX] = 2.0;
+        modelPar[PM_PAR_SYY] = 3.0;
+        modelPar[PM_PAR_SXY] = 5.0;
+        double SXX = modelPar[PM_PAR_SXX];
+        double SYY = modelPar[PM_PAR_SYY];
+        double SXY = modelPar[PM_PAR_SXY];
+        psF32 verF = SXY / PS_SQR(1.0 / PS_SQR(SXX) + 1.0 / PS_SQR(SYY));
+        psF32 testF = pmPSF_SXYfromModel(modelPar);
+        ok(verF == testF, "pmPSF_SXYfromModel() calculated correctly");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmPSF_SXYtoModel() tests
+    // Call pmPSF_SXYtoModel() with NULL input parameters
+    {
+        psMemId id = psMemGetId();
+        double tmpD = pmPSF_SXYtoModel(NULL);
+        ok(isnan(tmpD), "pmPSF_SXYtoModel() returned NULL with NULL input parameters");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSF_SXYtoModel() with NULL input parameters
+    {
+        psMemId id = psMemGetId();
+        psF32 fittedPar[20];
+        fittedPar[PM_PAR_SXX] = 2.0;
+        fittedPar[PM_PAR_SYY] = 3.0;
+        fittedPar[PM_PAR_SXY] = 5.0;
+        double SXX = fittedPar[PM_PAR_SXX];
+        double SYY = fittedPar[PM_PAR_SYY];
+        double fit = fittedPar[PM_PAR_SXY];
+        double verF = fit * PS_SQR(1.0 / PS_SQR(SXX) + 1.0 / PS_SQR(SYY));
+        psF32 testF = pmPSF_SXYtoModel(fittedPar);
+        ok(TEST_FLOATS_EQUAL(verF, testF), "pmPSF_SXYtoModel() calculated correctly (%f %f)", verF, testF);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmPSF_FitToModel() tests
+    // Call pmPSF_FitToModel() with NULL input parameters
+    {
+        psMemId id = psMemGetId();
+        bool rc = pmPSF_FitToModel(NULL, 0.0);
+        ok(rc == false, "pmPSF_FitToModel() returned NULL with NULL input parameters");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSF_FitToModel() with NULL input parameters
+    {
+        #define MIN_MINOR_AXIS 1.0
+        psMemId id = psMemGetId();
+        psF32 origFittedPar[3], testFittedPar[3];
+        psEllipsePol pol;
+        pol.e0 = origFittedPar[PM_PAR_E0] = testFittedPar[PM_PAR_E0] = 2.0;
+        pol.e1 = origFittedPar[PM_PAR_E1] = testFittedPar[PM_PAR_E1] = 3.0;
+        pol.e2 = origFittedPar[PM_PAR_E2] = testFittedPar[PM_PAR_E2] = 5.0;
+        ok(pmPSF_FitToModel(testFittedPar, MIN_MINOR_AXIS), "pmPSF_FitToModel() returned TRUE with acceptable input parameters");
+
+        psEllipseAxes axes;
+        psEllipsePolToAxes(pol, MIN_MINOR_AXIS, &axes);
+        psEllipseShape shape = psEllipseAxesToShape(axes);
+
+        ok(TEST_FLOATS_EQUAL(testFittedPar[PM_PAR_SXX], shape.sx * M_SQRT2),
+          "pmPSF_FitToModel() set fittedPar[PM_PAR_SXX] correctly");
+        ok(TEST_FLOATS_EQUAL(testFittedPar[PM_PAR_SYY], shape.sy * M_SQRT2),
+          "pmPSF_FitToModel() set fittedPar[PM_PAR_SYY] correctly");
+        ok(TEST_FLOATS_EQUAL(testFittedPar[PM_PAR_SXY], shape.sxy),
+          "pmPSF_FitToModel() set fittedPar[PM_PAR_SXY] correctly");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmPSF_ModelToFit() tests
+    // psEllipsePol pmPSF_ModelToFit (psF32 *modelPar)
+    // Call pmPSF_ModelToFit() with NULL input parameters
+    {
+        psMemId id = psMemGetId();
+        psEllipsePol pol = pmPSF_ModelToFit(NULL);
+        ok(isnan(pol.e0), "pmPSF_ModelToFit() returned NULL (psEllipsePol) with NULL input parameters");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSF_ModelToFit() with NULL input parameters
+    {
+        #define MIN_MINOR_AXIS 1.0
+        psMemId id = psMemGetId();
+        psF32 modelPar[3];
+        modelPar[PM_PAR_SXX] = 2.0;
+        modelPar[PM_PAR_SYY] = 3.0;
+        modelPar[PM_PAR_SXY] = 5.0;
+
+        psEllipsePol pol = pmPSF_ModelToFit(modelPar);
+        ok(!isnan(pol.e0), "pmPSF_ModelToFit() returned TRUE with acceptable input parameters");
+
+        psEllipseShape shape;
+        shape.sx  = modelPar[PM_PAR_SXX] / M_SQRT2;
+        shape.sy  = modelPar[PM_PAR_SYY] / M_SQRT2;
+        shape.sxy = modelPar[PM_PAR_SXY];
+        psEllipsePol actPol = psEllipseShapeToPol(shape);
+        ok(TEST_FLOATS_EQUAL(pol.e0, actPol.e0), "pmPSF_ModelToFit() set psEllipsePol.e0 correctly");
+        ok(TEST_FLOATS_EQUAL(pol.e1, actPol.e1), "pmPSF_ModelToFit() set psEllipsePol.e1 correctly");
+        ok(TEST_FLOATS_EQUAL(pol.e2, actPol.e2), "pmPSF_ModelToFit() set psEllipsePol.e2 correctly");
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmPSF_ModelToAxes() tests
+    // psEllipseAxes pmPSF_ModelToAxes (psF32 *modelPar, double maxAR)
+    // Call pmPSF_ModelToAxes() with NULL input parameters
+    {
+        psMemId id = psMemGetId();
+        psEllipseAxes axes = pmPSF_ModelToAxes(NULL, 1.0);
+        ok(isnan(axes.major), "pmPSF_ModelToAxes() returned NULL (psEllipseAxes) with NULL input parameters");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSF_ModelToAxes() with NULL input parameters
+    {
+        #define MAX_AX 1.0
+        psMemId id = psMemGetId();
+        psF32 modelPar[3];
+        modelPar[PM_PAR_SXX] = 2.0;
+        modelPar[PM_PAR_SYY] = 3.0;
+        modelPar[PM_PAR_SXY] = 5.0;
+
+        psEllipseShape shape;
+        shape.sx  = modelPar[PM_PAR_SXX] / M_SQRT2;
+        shape.sy  = modelPar[PM_PAR_SYY] / M_SQRT2;
+        shape.sxy = modelPar[PM_PAR_SXY];
+        psEllipseAxes axes = psEllipseShapeToAxes (shape, MAX_AX);
+
+        psEllipseAxes actAxes = pmPSF_ModelToAxes(modelPar, MAX_AX);
+        ok(!isnan(actAxes.major), "pmPSF_ModelToAxes() returned TRUE with acceptable input parameters");
+        ok(TEST_FLOATS_EQUAL(actAxes.major, axes.major), "pmPSF_ModelToAxes() set psEllipseAxes.major correctly");
+        ok(TEST_FLOATS_EQUAL(actAxes.minor, axes.minor), "pmPSF_ModelToAxes() set psEllipseAxes.minor correctly");
+        ok(TEST_FLOATS_EQUAL(actAxes.theta, axes.theta), "pmPSF_ModelToAxes() set psEllipseAxes.theta correctly");
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmPSF_AxesToModel() tests
+    // bool pmPSF_AxesToModel (psF32 *modelPar, psEllipseAxes axes)
+    // Call pmPSF_AxesToModel() with NULL input parameters
+    {
+        psMemId id = psMemGetId();
+        psEllipseAxes axes;
+        bool rc = pmPSF_AxesToModel(NULL, axes);
+        ok(rc == false, "pmPSF_AxesToModel() returned NULL with NULL input parameters");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSF_AxesToModel() with NULL input parameters
+    {
+        #define MIN_MINOR_AXIS 1.0
+        psMemId id = psMemGetId();
+        psF32 modelPar[3];
+        psEllipseAxes axes;
+        axes.major = 2.0;
+        axes.minor = 3.0;
+        axes.theta = 5.0;
+        ok(pmPSF_AxesToModel(modelPar, axes), "pmPSF_AxesToModel() returned TRUE with acceptable input parameters");
+        psEllipseShape shape = psEllipseAxesToShape(axes);
+        ok(TEST_FLOATS_EQUAL(modelPar[PM_PAR_SXX], shape.sx * M_SQRT2), "pmPSF_AxesToModel() set modelPar[PM_PAR_SXX] correctly");
+        ok(TEST_FLOATS_EQUAL(modelPar[PM_PAR_SYY], shape.sy * M_SQRT2), "pmPSF_AxesToModel() set modelPar[PM_PAR_SYY] correctly");
+        ok(TEST_FLOATS_EQUAL(modelPar[PM_PAR_SXY], shape.sxy), "pmPSF_AxesToModel() set modelPar[PM_PAR_SXY] correctly");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmPSF_IO.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmPSF_IO.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmPSF_IO.c	(revision 22158)
@@ -0,0 +1,467 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS
+    Uder construction.  Only lightly tested so far.
+*/
+
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.0001)
+#define NUM_MODELS		5
+
+#define CHIP_ALLOC_NAME        "ChipName"
+#define CELL_ALLOC_NAME        "CellName"
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define MISC_NAME2             "META01"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           4
+#define TEST_NUM_COLS           4
+#define NUM_READOUTS            3
+#define NUM_CELLS               10
+#define NUM_CHIPS               8
+#define NUM_HDUS                5
+#define BASE_IMAGE              10
+#define BASE_MASK               40
+#define BASE_WEIGHT             70
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+psPlaneTransform *PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM()
+{
+    psPlaneTransform *pt = psPlaneTransformAlloc(1, 1);
+    pt->x->coeff[1][0] = 1.0;
+    pt->y->coeff[0][1] = 1.0;
+    return(pt);
+}
+
+psPlaneDistort *PS_CREATE_4D_IDENTITY_PLANE_DISTORT()
+{
+    psPlaneDistort *pd = psPlaneDistortAlloc(1, 1, 1, 1);
+    pd->x->coeff[1][0][0][0] = 1.0;
+    pd->y->coeff[0][1][0][0] = 1.0;
+    return(pd);
+}
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    cell->hdu = pmHDUAlloc("cellExtName");
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = psMemDecrRefCounter((psPtr) generateSimpleReadout(cell));
+    }
+
+    // First try to read data from ../dataFiles, then try dataFiles.
+    bool rc = pmConfigFileRead(&cell->hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        rc = pmConfigFileRead(&cell->hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            diag("pmConfigFileRead() was unsuccessful (from generateSimpleCell())");
+	}
+    }
+
+    cell->hdu->images = psArrayAlloc(NUM_HDUS);
+    cell->hdu->masks = psArrayAlloc(NUM_HDUS);
+    cell->hdu->weights = psArrayAlloc(NUM_HDUS);
+    for (int k = 0 ; k < NUM_HDUS ; k++) {
+        cell->hdu->images->data[k]  = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        cell->hdu->masks->data[k]   = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        cell->hdu->weights->data[k] = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(cell->hdu->images->data[k], (float) (BASE_IMAGE+k));
+        psImageInit(cell->hdu->masks->data[k], (psU8) (BASE_MASK+k));
+        psImageInit(cell->hdu->weights->data[k], (float) (BASE_WEIGHT+k));
+    }
+
+    //XXX: Should the region be set some other way?  Like through the various config files?
+//    psRegion *region = psRegionAlloc(0.0, TEST_NUM_COLS-1, 0.0, TEST_NUM_ROWS-1);
+    psRegion *region = psRegionAlloc(0.0, 0.0, 0.0, 0.0);
+    // You shouldn't have to remove the key from the metadata.  Find out how to simply change the key value.
+    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC");
+    psMetadataAddPtr(cell->concepts, PS_LIST_TAIL|PS_META_REPLACE, "CELL.TRIMSEC", PS_DATA_REGION, "I am a region", region);
+    psFree(region);
+    return(cell);
+}
+
+/******************************************************************************
+generateSimpleChip(): This function generates a pmChip data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmChip *generateSimpleChip(pmFPA *fpa)
+{
+    pmChip *chip = pmChipAlloc(fpa, CHIP_ALLOC_NAME);
+    chip->toFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    chip->fromFPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    psMetadataAddS32(chip->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(chip->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(chip->cells, NUM_CELLS);
+    for (int i = 0 ; i < NUM_CELLS ; i++) {
+        chip->cells->data[i] = psMemDecrRefCounter((psPtr) generateSimpleCell(chip));
+    }
+
+    // XXX: Add code to initialize chip pmConcepts
+
+
+    return(chip);
+}
+
+/******************************************************************************
+generateSimpleFPA(): This function generates a pmFPA data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmFPA* generateSimpleFPA(psMetadata *camera)
+{
+    pmFPA* fpa = pmFPAAlloc(camera);
+    fpa->hdu = pmHDUAlloc("cellExtName");
+    fpa->fromTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toTPA = PS_CREATE_2D_IDENTITY_PLANE_TRANSFORM();
+    fpa->toSky = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+    psMetadataAddS32(fpa->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    if (camera != NULL) {
+        psMetadataAddS32((psMetadata *) fpa->camera, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    }
+    psMetadataAddS32(fpa->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(fpa->chips, NUM_CHIPS);
+    for (int i = 0 ; i < NUM_CHIPS ; i++) {
+        fpa->chips->data[i] = psMemDecrRefCounter((psPtr) generateSimpleChip(fpa));
+    }
+    pmConceptsBlankFPA(fpa);
+    return(fpa);
+}
+
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(28);
+
+
+    // ----------------------------------------------------------------------
+    // pmPSFmodelCheckDataStatusForView() tests
+    // bool pmPSFmodelCheckDataStatusForView (const pmFPAview *view, const pmFPAfile *file)
+    // Call pmPSFmodelCheckDataStatusForView() with NULL pmFPAview input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+
+        pmFPAview *view = pmFPAviewAlloc(32);
+        pmFPAfile *file = pmFPAfileAlloc();
+        bool rc = pmPSFmodelCheckDataStatusForView(NULL, file);
+        ok(rc == false, "pmPSFmodelCheckDataStatusForView() returned FALSE with NULL pmFPAview input parameter");
+        psFree(view);
+        psFree(file);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSFmodelCheckDataStatusForView() with NULL pmFPAfile input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+
+        pmFPAview *view = pmFPAviewAlloc(32);
+        pmFPAfile *file = pmFPAfileAlloc();
+        bool rc = pmPSFmodelCheckDataStatusForView(view, NULL);
+        ok(rc == false, "pmPSFmodelCheckDataStatusForView() returned FALSE with NULL pmFPAfile input parameter");
+        psFree(view);
+        psFree(file);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSFmodelCheckDataStatusForView() with acceptable input parameters
+    if (1) {
+        psMemId id = psMemGetId();
+
+        pmFPAview *view = pmFPAviewAlloc(32);
+        view->chip = -1;
+        view->cell = -1;
+        pmFPAfile *file = pmFPAfileAlloc();
+        psMetadata *camera = psMetadataAlloc();
+        file->fpa = generateSimpleFPA(camera);
+        bool rc = pmPSFmodelCheckDataStatusForView(view, file);
+        ok(rc == false, "pmPSFmodelCheckDataStatusForView() returned FALSE acceptable input parameters, but no PSPHOT.PSF");
+
+        // Add PSPHOT.PSF to chip->analysis and call pmPSFmodelCheckDataStatusForChip()
+        pmChip *chip = file->fpa->chips->data[0];
+        psVector *junk = psVectorAlloc(10, PS_TYPE_F32);
+        bool rc2 = psMetadataAddPtr(chip->analysis, PS_LIST_HEAD, "PSPHOT.PSF", PS_DATA_VECTOR, NULL, junk);
+        ok(rc2 == true, "added PSPHOT.PSF metadata to chip->analysis");
+        rc = pmPSFmodelCheckDataStatusForView(view, file);
+        ok(rc == true, "pmPSFmodelCheckDataStatusForView() returned TRUE acceptable input parameters");
+
+        psFree(view);
+        psFree(file->fpa);
+        file->fpa = NULL;
+        psFree(file);
+        psFree(camera);
+        psFree(junk);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmPSFmodelCheckDataStatusForFPA() tests
+    // bool pmPSFmodelCheckDataStatusForFPA (const pmFPA *fpa)
+    // Call pmPSFmodelCheckDataStatusForFPA() with NULL pmFPA input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA *fpa = generateSimpleFPA(camera);
+        bool rc = pmPSFmodelCheckDataStatusForFPA(NULL);
+        ok(rc == false, "pmPSFmodelCheckDataStatusForFPA() returned FALSE with NULL pmFPA input parameter");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSFmodelCheckDataStatusForFPA() with NULL pmFPA->chips input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA *fpa = generateSimpleFPA(camera);
+        for (int i = 0 ; i < fpa->chips->n ; i++) {
+            psFree(fpa->chips->data[i]);
+	}
+        bool rc = pmPSFmodelCheckDataStatusForFPA(NULL);
+        ok(rc == false, "pmPSFmodelCheckDataStatusForFPA() returned FALSE with NULL pmFPA->chips input parameter");
+        psFree(fpa);
+        psFree(camera);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSFmodelCheckDataStatusForFPA() with acceptable input parameters
+    if (1) {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA *fpa = generateSimpleFPA(camera);
+        bool rc = pmPSFmodelCheckDataStatusForFPA(fpa);
+        ok(rc == false, "pmPSFmodelCheckDataStatusForFPA() returned FALSE with acceptable input parameters, but no PSPHOT.PSF");
+
+        // Add PSPHOT.PSF to chip->analysis and call pmPSFmodelCheckDataStatusForChip()
+        psVector *junk = psVectorAlloc(10, PS_TYPE_F32);
+        pmChip *chip = fpa->chips->data[0];
+        bool rc2 = psMetadataAddPtr(chip->analysis, PS_LIST_HEAD, "PSPHOT.PSF", PS_DATA_VECTOR, NULL, junk);
+        ok(rc2 == true, "added PSPHOT.PSF metadata to chip->analysis");
+        rc = pmPSFmodelCheckDataStatusForFPA(fpa);
+        ok(rc == true, "pmPSFmodelCheckDataStatusForFPA() returned TRUE with acceptable input parameters");
+
+        psFree(fpa);
+        psFree(camera);
+        psFree(junk);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmPSFmodelCheckDataStatusForChip() tests
+    // bool pmPSFmodelCheckDataStatusForChip (const pmChip *chip)
+    // Call pmPSFmodelCheckDataStatusForChip() with NULL pmChip input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        bool rc = pmPSFmodelCheckDataStatusForChip(NULL);
+        ok(rc == false, "pmPSFmodelCheckDataStatusForChip() returned FALSE with NULL pmChip input parameter");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSFmodelCheckDataStatusForChip() with acceptable input parameters
+    if (1) {
+        psMemId id = psMemGetId();
+        psMetadata *camera = psMetadataAlloc();
+        pmFPA *fpa = generateSimpleFPA(camera);
+        pmChip *chip = fpa->chips->data[0];
+        bool rc = pmPSFmodelCheckDataStatusForChip(chip);
+        ok(rc == false, "pmPSFmodelCheckDataStatusForChip() returned false with acceptable pmChip, but no PSPHOT.PSF");
+
+        // Add PSPHOT.PSF to chip->analysis and call pmPSFmodelCheckDataStatusForChip()
+        psVector *junk = psVectorAlloc(10, PS_TYPE_F32);
+        bool rc2 = psMetadataAddPtr(chip->analysis, PS_LIST_HEAD, "PSPHOT.PSF", PS_DATA_VECTOR, NULL, junk);
+        ok(rc2 == true, "added PSPHOT.PSF metadata to chip->analysis");
+        rc = pmPSFmodelCheckDataStatusForChip(chip);
+        ok(rc == true, "pmPSFmodelCheckDataStatusForChip() returned TRUE with acceptable input parameters");
+    
+        psFree(fpa);
+        psFree(camera);
+        psFree(junk);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmPSFmodelWrite() tests
+    // bool pmPSFmodelWrite (psMetadata *analysis, const pmFPAview *view,
+    //                       pmFPAfile *file, const pmConfig *config)
+    // Call pmPSFmodelWrite() with NULL pmFPAview input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        pmFPAview *view = pmFPAviewAlloc(32);
+        pmFPAfile *file = pmFPAfileAlloc();
+        psMetadata *camera = psMetadataAlloc();
+        file->fpa = generateSimpleFPA(camera);
+        psMetadata *analysis = psMetadataAlloc();
+        pmConfig *config = pmConfigAlloc();
+
+        bool rc = pmPSFmodelWrite(analysis, NULL, file, config);
+        ok(rc == false, "pmPSFmodelWrite() returned FALSE with NULL pmFPAview input parameter");
+
+        psFree(view);
+        psFree(file->fpa);
+        file->fpa = NULL;
+        psFree(file);
+        psFree(camera);
+        psFree(analysis);
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSFmodelWrite() with NULL pmFPAfile input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        pmFPAview *view = pmFPAviewAlloc(32);
+        pmFPAfile *file = pmFPAfileAlloc();
+        psMetadata *camera = psMetadataAlloc();
+        file->fpa = generateSimpleFPA(camera);
+        psMetadata *analysis = psMetadataAlloc();
+        pmConfig *config = pmConfigAlloc();
+
+        bool rc = pmPSFmodelWrite(analysis, view, NULL, config);
+        ok(rc == false, "pmPSFmodelWrite() returned FALSE with NULL pmFPAfile input parameter");
+
+        psFree(view);
+        psFree(file->fpa);
+        file->fpa = NULL;
+        psFree(file);
+        psFree(camera);
+        psFree(analysis);
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSFmodelWrite() with NULL pmFPAfile->file input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        pmFPAview *view = pmFPAviewAlloc(32);
+        pmFPAfile *file = pmFPAfileAlloc();
+        psMetadata *analysis = psMetadataAlloc();
+        pmConfig *config = pmConfigAlloc();
+
+        bool rc = pmPSFmodelWrite(analysis, view, NULL, config);
+        ok(rc == false, "pmPSFmodelWrite() returned FALSE with NULL pmFPAfile->fpa input parameter");
+
+        psFree(view);
+        psFree(file);
+        psFree(analysis);
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPSFmodelWrite() with acceptable input parameters
+    // XXX: This is currently being coded.  It does not work.
+    if (0) {
+        psMemId id = psMemGetId();
+        pmFPAview *view = pmFPAviewAlloc(32);
+        pmFPAfile *file = pmFPAfileAlloc();
+        psMetadata *camera = psMetadataAlloc();
+        file->fpa = generateSimpleFPA(camera);
+        pmConfigFileRead(&file->camera, "../dataFiles/camera0/camera.config", "CAMERA");
+        psMetadataPrint(stdout, file->camera, 0);
+        psMetadata *menu = psMetadataLookupMetadata(NULL, file->camera, "EXTNAME.RULES");
+        if (!menu) {
+            printf("NOTE: missing EXTNAME.RULES in camera.config\n");
+            exit(1);
+        }
+
+
+        psMetadata *analysis = psMetadataAlloc();
+        pmConfig *config = pmConfigAlloc();
+
+        // XXX: I failed here and then moved on.
+        /*
+        The function reads the PSPHOT recipes and requires that it contains a
+	PSPHOT key in the metadata.  I'm not sure how to do that, but I could
+	have hacked around it.  Then, however, it required several keys in
+	that metadata like PSF.CLUMP.X, PSF.CLUMP.Y, PSF.CLUMP.DX,
+	PSF.CLUMP.DY.  I could also put them in there, but I just gave up.
+	What should I do here?  I could easily create a metadata file with all
+	those metadata keys, but I'd rather use an existing one.
+        */
+
+        if (1) {
+            psMetadata *junk = psMetadataAlloc();
+            bool rc0 = pmConfigFileRead(&junk, "../dataFiles/recipes/psphot.config", "SAVE.PSF");
+            if (!rc0) {
+                rc0 = pmConfigFileRead(&junk, "dataFiles/recipes/psphot.config", "SAVE.PSF");
+	    }
+            ok(rc0, "Successfully read the PSPHOT recipe file");
+//          psMetadata *recipe = psMetadataLookupPtr(&rc0, junk, "SAVE.OUTPUT");
+            bool rc2 = psMetadataLookupBool(&rc0, junk, "SAVE.OUTPUT");
+            printf("rc0 is %d\n", (int) rc0);
+            printf("rc2 is %d\n", (int) rc2);
+//          if (recipe == NULL) printf("ERROR: recipe is NULL\n");
+            psMetadataPrint(stdout, junk, 0);
+            psFree(junk);
+	}
+        if (config->recipes == NULL) printf("COOL: config->recipes is NULL");
+        bool rc0 = pmConfigFileRead(&config->recipes, "../dataFiles/camera0/recipes.config", "PSPHOT");
+        if (!rc0) {
+            rc0 = pmConfigFileRead(&config->recipes, "dataFiles/camera0/recipes.config", "PSPHOT");
+	}
+        ok(rc0, "Successfully read the PSPHOT recipe file");
+psMetadataPrint(stdout, config->recipes, 0);
+
+        if (config->recipes == NULL) printf("FUCK: config->recipes is NULL");
+        psMetadata *recipe = psMetadataLookupPtr(NULL, config->recipes, "PSPHOT");
+        if (!recipe) {
+            printf("FUCK: missing recipe %s\n", "PSPHOT");
+            exit(1);
+        }
+
+
+        bool rc = pmPSFmodelWrite(analysis, view, file, config);
+        ok(rc == true, "pmPSFmodelWrite() returned TRUE with acceptable input parameters");
+
+        psFree(view);
+        psFree(file->fpa);
+        file->fpa = NULL;
+        psFree(file);
+        psFree(camera);
+        psFree(analysis);
+        psFree(config);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmPSFtoMetadata.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmPSFtoMetadata.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmPSFtoMetadata.c	(revision 22158)
@@ -0,0 +1,52 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    Under construction: 10% complete.
+*/
+
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           (8)
+#define TEST_NUM_COLS           (16)
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.0001)
+#define NUM_SOURCES		100
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(1);
+
+
+    // ----------------------------------------------------------------------
+    // pmPSFtoMetadata() tests
+    // psMetadata *pmPSFtoMetadata (psMetadata *metadata, pmPSF *psf)
+    // Call pmPSFtoMetadata() with NULL psPSF input parameter
+    if (1) {
+        psMemId id = psMemGetId();
+        psMetadata *metadata = psMetadataAlloc();
+        pmPSFOptions *psfOptions = pmPSFOptionsAlloc();
+        psfOptions->psfTrendNx = 1;
+        psfOptions->psfTrendNy = 2;
+        psfOptions->psfFieldNx = 3;
+        psfOptions->psfFieldNy = 4;
+        psfOptions->psfFieldXo = 5;
+        psfOptions->psfFieldYo = 6;
+        pmModelClassInit();
+        psfOptions->type = pmModelClassGetType("PS_MODEL_GAUSS");
+        pmPSF *psf = pmPSFAlloc(psfOptions);
+        psMetadata *meta2 = pmPSFtoMetadata(metadata, NULL);
+        ok(meta2 == NULL, "pmPSFtoMetadata() returned NULL with NULL psPSF input parameter");
+        psFree(metadata);
+        psFree(psfOptions);
+        psFree(psf);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmPeaks.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmPeaks.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmPeaks.c	(revision 22158)
@@ -0,0 +1,744 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    All functions are tested.
+        pmPeaksInImage(): Must debug tests for small images (1-by-1, N-by-1, 1-by-N)
+*/
+
+#define TST01_VECTOR_LENGTH 10
+#define NUM_ROWS 10
+#define NUM_COLS 10
+#define TST02_NUM_ROWS 5
+#define TST02_NUM_COLS 5
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+/******************************************************************************
+test01(): we first test pmPeaksInVector() with a variety of bad input
+parameters.  Then we test it with a simple vector both 1- and multi-elements.
+ *****************************************************************************/
+bool test_pmPeaksInVector(int n)
+{
+    psMemId id = psMemGetId();
+    bool testStatus = true;
+    psVector *inData = psVectorAlloc(n, PS_TYPE_F32);
+    inData->n = inData->nalloc;
+    psVector *outData = NULL;
+
+    // Test first pixel peak.
+    for (psS32 i = 0 ; i < n ; i++) {
+        inData->data.F32[i] = (float) (n-i);
+    }
+    inData->data.F32[0] = (float) n;
+    outData= pmPeaksInVector(inData, 0.0);
+    if (outData == NULL) {
+        diag("TEST ERROR: pmPeaksInVector returned a NULL psVector.\n");
+        testStatus = false;
+    } else {
+        if (outData->n != 1) {
+            diag("TEST ERROR: outData->n is %ld\n", outData->n);
+            testStatus = false;
+        }
+        if (outData->data.U32[0] != 0) {
+            diag("TEST ERROR: Did not find peak at element 0.\n");
+            testStatus = false;
+        }
+        psFree(outData);
+    }
+
+
+    //
+    // Test first pixel peak, large threshold
+    //
+    for (psS32 i = 0 ; i < n ; i++) {
+        inData->data.F32[i] = (float) (n-i);
+    }
+    inData->data.F32[0] = (float) n;
+    outData= pmPeaksInVector(inData, (float) (n*n));
+    if (outData == NULL) {
+        diag("TEST ERROR: pmPeaksInVector returned a NULL psVector.\n");
+        testStatus = false;
+    } else {
+        if (outData->n != 0) {
+            diag("TEST ERROR: outData->n is %ld\n", outData->n);
+            testStatus = false;
+        }
+        psFree(outData);
+
+        // Skip remaining tests if the input vector has length 1.
+        if (n == 1) {
+            psFree(inData);
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+            return(testStatus);
+        }
+    }
+
+    // Test last pixel peak.
+    for (psS32 i = 0 ; i < n ; i++) {
+        inData->data.F32[i] = (float) (i);
+    }
+    inData->data.F32[n-1] = (float) n;
+
+    outData= pmPeaksInVector(inData, 0.0);
+    if (outData == NULL) {
+        diag("TEST ERROR: pmPeaksInVector returned a NULL psVector.\n");
+        testStatus = false;
+    } else {
+        if (outData->n != 1) {
+            diag("TEST ERROR: outData->n is %ld\n", outData->n);
+            testStatus = false;
+        }
+        if (outData->data.U32[0] != n-1) {
+            diag("TEST ERROR: Did not find peak at element %d.\n", n-1);
+            testStatus = false;
+        }
+        psFree(outData);
+    }
+
+
+    // Test last pixel peak, large threshold.
+    for (psS32 i = 0 ; i < n ; i++) {
+        inData->data.F32[i] = (float) (i);
+    }
+    inData->data.F32[n-1] = (float) n;
+    outData= pmPeaksInVector(inData, (float) (n*n));
+    if (outData == NULL) {
+        diag("TEST ERROR: pmPeaksInVector returned a NULL psVector.\n");
+        testStatus = false;
+    } else {
+        if (outData->n != 0) {
+            diag("TEST ERROR: outData->n is %ld\n", outData->n);
+            testStatus = false;
+        }
+        psFree(outData);
+    }
+
+
+    // Test interior peaks.
+    // Set all even number elements to be peaks.
+    for (psS32 i = 0 ; i < n ; i++) {
+        if (0 == i%2) {
+            inData->data.F32[i] = (float) (2 * i);
+        } else {
+            inData->data.F32[i] = (float) (i);
+        }
+    }
+    inData->data.F32[0] = (float) n;
+
+
+    outData= pmPeaksInVector(inData, 0.0);
+    if (outData == NULL) {
+        diag("TEST ERROR: pmPeaksInVector returned a NULL psVector.\n");
+        testStatus = false;
+    } else {
+        if (outData->n != n/2) {
+            diag("TEST ERROR: outData->n is %ld\n", outData->n);
+            testStatus = false;
+        }
+        for (psS32 i = 0 ; i < outData->n ; i++) {
+            if (outData->data.U32[i] != (2 * i)) {
+                diag("TEST ERROR: the %d-th peak is element number %d\n", i, outData->data.U32[i]);
+                testStatus = false;
+            }
+        }
+        psFree(outData);
+    }
+
+
+    // Test interior peaks, with threshold = n*n.
+    // Should generate an empty output psVector.
+    outData= pmPeaksInVector(inData, (float) (n*n));
+    if (outData == NULL) {
+        diag("TEST ERROR: pmPeaksInVector returned a NULL psVector.\n");
+        testStatus = false;
+    } else {
+        if (outData->n != 0) {
+            diag("TEST ERROR: outData->n is %ld\n", outData->n);
+            testStatus = false;
+        }
+        psFree(outData);
+    }
+    psFree(inData);
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    return(testStatus);
+}
+
+
+bool test_pmPeaksInImage(int numRows, int numCols)
+{
+    psMemId id = psMemGetId();
+    bool testStatus = true;
+    psImage *inData = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    psArray *outData = NULL;
+    // Initialize test image.
+    for (psS32 i = 0 ; i < numRows ; i++) {
+        for (psS32 j = 0 ; j < numCols ; j++) {
+            inData->data.F32[i][j] = PS_SQR(i - numRows/2) + PS_SQR(j-numCols/2);
+        }
+    }
+
+    // Set corner and center pixels as peaks.
+    inData->data.F32[0][0] = PS_SQR(numRows) + PS_SQR(numCols);
+    inData->data.F32[0][numCols-1] = PS_SQR(numRows) + PS_SQR(numCols);
+    inData->data.F32[numRows-1][0] = PS_SQR(numRows) + PS_SQR(numCols);
+    inData->data.F32[numRows-1][numCols-1] = PS_SQR(numRows) + PS_SQR(numCols);
+    inData->data.F32[numRows/2][numCols/2] = PS_SQR(numRows) + PS_SQR(numCols);
+
+    // Call pmPeaksInImage() with a threshold of 0.0.
+    outData = pmPeaksInImage(inData, 0.0);
+
+    if (outData == NULL) {
+        diag("TEST ERROR: pmPeaksInImage returned a NULL psList.\n");
+        testStatus = false;
+    } else {
+        psS32 expectedNumPeaks;
+        if ((numRows == 1) && (numCols == 1)) {
+            expectedNumPeaks = 1;
+        } else if ((numRows == 1) || (numCols == 1)) {
+            expectedNumPeaks = 3;
+        } else {
+            expectedNumPeaks = 5;
+        }
+        if (outData->n != expectedNumPeaks) {
+            diag("TEST ERROR: pmPeaksInImage found %ld peaks (should be %d)\n", outData->n, expectedNumPeaks);
+            testStatus = false;
+        }
+
+        // HEY: verify
+        for (psS32 i = 0 ; i < outData->n ; i++) {
+            pmPeak *tmpPeak = (pmPeak *) outData->data[i];
+            if (((tmpPeak->x == 0) && (tmpPeak->y == 0)) ||
+                    ((tmpPeak->x == 0) && (tmpPeak->y == numRows-1)) ||
+                    ((tmpPeak->x == numCols-1) && (tmpPeak->y == 0)) ||
+                    ((tmpPeak->x == numCols-1) && (tmpPeak->y == numRows-1))) {
+                if (!((tmpPeak->type & PM_PEAK_LONE) || (tmpPeak->type & PM_PEAK_EDGE))) {
+                    diag("TEST ERROR: (0) peak at (%d, %d) (%f) ->type set improperly (0x%x).",
+                          tmpPeak->y, tmpPeak->x, tmpPeak->value, tmpPeak->type);
+                    diag(" should be (0x%x or 0x%x).\n", PM_PEAK_LONE, PM_PEAK_EDGE);
+                    testStatus = false;
+                }
+            } else if ((tmpPeak->x == numCols/2) && (tmpPeak->y == numRows/2)) {
+                if (tmpPeak->type != PM_PEAK_LONE) {
+                    diag("TEST ERROR: (1) peak at (%d, %d) (%f) ->type set improperly (0x%x).\n",
+                           tmpPeak->y, tmpPeak->x, tmpPeak->value, tmpPeak->type);
+                    diag(" should be (0x%x).\n", PM_PEAK_LONE);
+                    testStatus = false;
+                }
+            } else {
+                diag("TEST ERROR: Peak at (%d, %d) (%f)\n", tmpPeak->y, tmpPeak->x, tmpPeak->value);
+                testStatus = false;
+            }
+        }
+    }
+    psFree(inData);
+    psFree(outData);
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    return(testStatus);
+}
+
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(69);
+
+
+    // ------------------------------------------------------------------------
+    // Test pmPeakAlloc()
+    {
+        psMemId id = psMemGetId();
+        pmPeak *tmpPeak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        ok(tmpPeak != NULL, "pmPeakAlloc() returned a non-NULL pmPeak");
+        skip_start(tmpPeak == NULL, 9, "Skipping tests because pmPeakAlloc() returned NULL");
+        ok(tmpPeak->id == 1, "pmPeakAlloc() set pmPeak->id");
+        ok(tmpPeak->x == 1, "pmPeakAlloc() set pmPeak->x");
+        ok(tmpPeak->y == 2, "pmPeakAlloc() set pmPeak->y");
+        ok(tmpPeak->value == 3.0, "pmPeakAlloc() set pmPeak->value");
+        ok(tmpPeak->flux == 0, "pmPeakAlloc() pmPeak->flux");
+        ok(tmpPeak->SN == 0, "pmPeakAlloc() pmPeak->SN");
+        ok(tmpPeak->xf == 1, "pmPeakAlloc() pmPeak->xf");
+        ok(tmpPeak->yf == 2, "pmPeakAlloc() pmPeak->yF");
+        ok(tmpPeak->type == PM_PEAK_LONE, "pmPeakAlloc() pmPeak->type");
+        psFree(tmpPeak);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmPeakAlloc(): ensure pmPeak->id is properly incremented.
+    {
+        psMemId id = psMemGetId();
+        pmPeak *tmpPeak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        skip_start(tmpPeak == NULL, 1, "Skipping tests because pmPeakAlloc() returned NULL");
+        ok(tmpPeak->id == 2, "pmPeakAlloc() incremented and set pmPeak->id");
+        psFree(tmpPeak);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Calling pmPeaksCompareAscend with NULL peak1
+    // XXX: This currently seg-faults because NULL args are not pretested in pmPeaksCompareAscend()
+    if (0) {
+        psMemId id = psMemGetId();
+        pmPeak **peak2 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak2 = pmPeakAlloc(3, 4, 3.0, PM_PEAK_LONE);
+        int rc = pmPeaksCompareAscend(NULL, (const void **) peak2);
+        ok(rc == -1, "pmPeaksCompareAscend() returned correct result (peak1 < peak2)");
+        psFree(*peak2);
+        psFree(peak2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Calling pmPeaksCompareAscend with NULL peak2
+    // XXX: This currently seg-faults because NULL args are not pretested in pmPeaksCompareAscend()
+    if (0) {
+        psMemId id = psMemGetId();
+        pmPeak **peak1 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak1 = pmPeakAlloc(3, 4, 2.0, PM_PEAK_LONE);
+        int rc = pmPeaksCompareAscend((const void **)peak1, NULL);
+        ok(rc == -1, "pmPeaksCompareAscend() returned correct result (peak1 < peak2)");
+        psFree(*peak1);
+        psFree(peak1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Calling pmPeaksCompareAscend with NULL *peak1
+    // XXX: This currently seg-faults because NULL args are not pretested in pmPeaksCompareAscend()
+    if (0) {
+        psMemId id = psMemGetId();
+        pmPeak **peak1 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        pmPeak **peak2 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak2 = pmPeakAlloc(3, 4, 3.0, PM_PEAK_LONE);
+        int rc = pmPeaksCompareAscend((const void **)peak1, (const void **) peak2);
+        ok(rc == -1, "pmPeaksCompareAscend() returned correct result (peak1 < peak2)");
+        psFree(peak1);
+        psFree(*peak2);
+        psFree(peak2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Calling pmPeaksCompareAscend with NULL *peak2
+    // XXX: This currently seg-faults because NULL args are not pretested in pmPeaksCompareAscend()
+    if (0) {
+        psMemId id = psMemGetId();
+        pmPeak **peak1 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak1 = pmPeakAlloc(3, 4, 2.0, PM_PEAK_LONE);
+        pmPeak **peak2 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        int rc = pmPeaksCompareAscend((const void **)peak1, (const void **) peak2);
+        ok(rc == -1, "pmPeaksCompareAscend() returned correct result (peak1 < peak2)");
+        psFree(*peak1);
+        psFree(peak1);
+        psFree(peak2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Calling pmPeaksCompareAscend with peak1 < peak2
+    {
+        psMemId id = psMemGetId();
+        pmPeak **peak1 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak1 = pmPeakAlloc(3, 4, 2.0, PM_PEAK_LONE);
+        pmPeak **peak2 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak2 = pmPeakAlloc(3, 4, 3.0, PM_PEAK_LONE);
+        int rc = pmPeaksCompareAscend((const void **)peak1, (const void **) peak2);
+        ok(rc == -1, "pmPeaksCompareAscend() returned correct result (peak1 < peak2)");
+        psFree(*peak1);
+        psFree(peak1);
+        psFree(*peak2);
+        psFree(peak2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Calling pmPeaksCompareAscend with peak1 > peak2
+    {
+        psMemId id = psMemGetId();
+        pmPeak **peak1 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak1 = pmPeakAlloc(3, 4, 3.0, PM_PEAK_LONE);
+        pmPeak **peak2 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak2 = pmPeakAlloc(3, 4, 2.0, PM_PEAK_LONE);
+        int rc = pmPeaksCompareAscend((const void **)peak1, (const void **) peak2);
+        ok(rc == 1, "pmPeaksCompareAscend() returned correct result (peak1 > peak2)");
+        psFree(*peak1);
+        psFree(peak1);
+        psFree(*peak2);
+        psFree(peak2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Calling pmPeaksCompareAscend with peak1 == peak2
+    {
+        psMemId id = psMemGetId();
+        pmPeak **peak1 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak1 = pmPeakAlloc(3, 4, 2.0, PM_PEAK_LONE);
+        pmPeak **peak2 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak2 = pmPeakAlloc(3, 4, 2.0, PM_PEAK_LONE);
+        int rc = pmPeaksCompareAscend((const void **)peak1, (const void **) peak2);
+        ok(rc == 0, "pmPeaksCompareAscend() returned correct result (peak1 == peak2)", rc);
+        psFree(*peak1);
+        psFree(peak1);
+        psFree(*peak2);
+        psFree(peak2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Calling pmPeaksCompareDescend with NULL peak1
+    // XXX: This currently seg-faults because NULL args are not pretested in pmPeaksCompareDescend()
+    if (0) {
+        psMemId id = psMemGetId();
+        pmPeak **peak2 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak2 = pmPeakAlloc(3, 4, 3.0, PM_PEAK_LONE);
+        int rc = pmPeaksCompareDescend(NULL, (const void **) peak2);
+        ok(rc == -1, "pmPeaksCompareDescend() returned correct result (peak1 < peak2)");
+        psFree(*peak2);
+        psFree(peak2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Calling pmPeaksCompareDescend with NULL peak2
+    // XXX: This currently seg-faults because NULL args are not pretested in pmPeaksCompareDescend()
+    if (0) {
+        psMemId id = psMemGetId();
+        pmPeak **peak1 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak1 = pmPeakAlloc(3, 4, 2.0, PM_PEAK_LONE);
+        int rc = pmPeaksCompareDescend((const void **)peak1, NULL);
+        ok(rc == -1, "pmPeaksCompareDescend() returned correct result (peak1 < peak2)");
+        psFree(*peak1);
+        psFree(peak1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Calling pmPeaksCompareDescend with NULL *peak1
+    // XXX: This currently seg-faults because NULL args are not pretested in pmPeaksCompareDescend()
+    if (0) {
+        psMemId id = psMemGetId();
+        pmPeak **peak1 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        pmPeak **peak2 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak2 = pmPeakAlloc(3, 4, 3.0, PM_PEAK_LONE);
+        int rc = pmPeaksCompareDescend((const void **)peak1, (const void **) peak2);
+        ok(rc == -1, "pmPeaksCompareDescend() returned correct result (peak1 < peak2)");
+        psFree(peak1);
+        psFree(*peak2);
+        psFree(peak2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Calling pmPeaksCompareDescend with NULL *peak2
+    // XXX: This currently seg-faults because NULL args are not pretested in pmPeaksCompareDescend()
+    if (0) {
+        psMemId id = psMemGetId();
+        pmPeak **peak1 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak1 = pmPeakAlloc(3, 4, 2.0, PM_PEAK_LONE);
+        pmPeak **peak2 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        int rc = pmPeaksCompareDescend((const void **)peak1, (const void **) peak2);
+        ok(rc == -1, "pmPeaksCompareDescend() returned correct result (peak1 < peak2)");
+        psFree(*peak1);
+        psFree(peak1);
+        psFree(peak2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Calling pmPeaksCompareDescend with peak1 < peak2
+    {
+        psMemId id = psMemGetId();
+        pmPeak **peak1 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak1 = pmPeakAlloc(3, 4, 2.0, PM_PEAK_LONE);
+        pmPeak **peak2 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak2 = pmPeakAlloc(3, 4, 3.0, PM_PEAK_LONE);
+        int rc = pmPeaksCompareDescend((const void **)peak1, (const void **) peak2);
+        ok(rc == 1, "pmPeaksCompareDescend() returned correct result (peak1 < peak2)");
+        psFree(*peak1);
+        psFree(peak1);
+        psFree(*peak2);
+        psFree(peak2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Calling pmPeaksCompareDescend with peak1 > peak2
+    {
+        psMemId id = psMemGetId();
+        pmPeak **peak1 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak1 = pmPeakAlloc(3, 4, 3.0, PM_PEAK_LONE);
+        pmPeak **peak2 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak2 = pmPeakAlloc(3, 4, 2.0, PM_PEAK_LONE);
+        int rc = pmPeaksCompareDescend((const void **)peak1, (const void **) peak2);
+        ok(rc == -1, "pmPeaksCompareDescend() returned correct result (peak1 > peak2)");
+        psFree(*peak1);
+        psFree(peak1);
+        psFree(*peak2);
+        psFree(peak2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Calling pmPeaksCompareDescend with peak1 == peak2
+    {
+        psMemId id = psMemGetId();
+        pmPeak **peak1 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak1 = pmPeakAlloc(3, 4, 2.0, PM_PEAK_LONE);
+        pmPeak **peak2 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak2 = pmPeakAlloc(3, 4, 2.0, PM_PEAK_LONE);
+        int rc = pmPeaksCompareDescend((const void **)peak1, (const void **) peak2);
+        ok(rc == 0, "pmPeaksCompareDescend() returned correct result (peak1 == peak2)", rc);
+        psFree(*peak1);
+        psFree(peak1);
+        psFree(*peak2);
+        psFree(peak2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // pmPeakSortBySN() tests
+    // int pmPeakSortBySN (const void **a, const void **b)
+    // Call pmPeakSortBySN() with acceptable input parameters.
+    // XXX: We don't test with NULL input parameters since this functions has no PS_ASSERTS to protect
+    // against that.
+    {
+        psMemId id = psMemGetId();
+        pmPeak **peak1 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak1 = pmPeakAlloc(3, 4, 2.0, PM_PEAK_LONE);
+        (*peak1)->SN = 10.0;
+        pmPeak **peak2 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak2 = pmPeakAlloc(3, 4, 3.0, PM_PEAK_LONE);
+        (*peak2)->SN = 20.0;
+        int rc = pmPeakSortBySN((const void **)peak1, (const void **) peak2);
+        ok(rc == 1, "pmPeakSortBySN() returned correct result (peak1 < peak2) (%d)", rc);
+        rc = pmPeakSortBySN((const void **)peak2, (const void **) peak1);
+        ok(rc == -1, "pmPeakSortBySN() returned correct result (peak2 < peak1) (%d)", rc);
+        rc = pmPeakSortBySN((const void **)peak1, (const void **) peak1);
+        ok(rc == 0, "pmPeakSortBySN() returned correct result (peak1 == peak2) (%d)", rc);
+        psFree(*peak1);
+        psFree(peak1);
+        psFree(*peak2);
+        psFree(peak2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // pmPeakSortByY() tests
+    // int pmPeakSortByY (const void **a, const void **b)
+    // Call pmPeakSortByY() with acceptable input parameters.
+    // XXX: We don't test with NULL input parameters since this functions has no PS_ASSERTS to protect
+    // against that.
+    {
+        psMemId id = psMemGetId();
+        pmPeak **peak1 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak1 = pmPeakAlloc(3, 4, 2.0, PM_PEAK_LONE);
+        (*peak1)->y = 10.0;
+        pmPeak **peak2 = (pmPeak **) psAlloc(sizeof(pmPeak *));
+        *peak2 = pmPeakAlloc(3, 4, 3.0, PM_PEAK_LONE);
+        (*peak2)->y = 20.0;
+        int rc = pmPeakSortByY((const void **)peak1, (const void **) peak2);
+        ok(rc == -1, "pmPeakSortByY() returned correct result (peak1 < peak2) (%d)", rc);
+        rc = pmPeakSortByY((const void **)peak2, (const void **) peak1);
+        ok(rc == 1, "pmPeakSortByY() returned correct result (peak2 < peak1) (%d)", rc);
+        rc = pmPeakSortByY((const void **)peak1, (const void **) peak1);
+        ok(rc == 0, "pmPeakSortByY() returned correct result (peak1 == peak2) (%d)", rc);
+        psFree(*peak1);
+        psFree(peak1);
+        psFree(*peak2);
+        psFree(peak2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // pmPeaksInVector() tests
+    // Test pmPeaksInVector() with bad input parameters.
+    // Calling pmPeaksInVector with NULL psVector.  Should generate error.
+    {
+        psMemId id = psMemGetId();
+        psVector *tmpVec = pmPeaksInVector(NULL, 0.0);
+        ok(tmpVec == NULL, "pmPeaksInVector() returned a NULL with NULL psVector input");
+        psFree(tmpVec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Calling pmPeaksInVector with empty psVector.  Should generate error.
+    {
+        psMemId id = psMemGetId();
+        psVector *tmpVecEmpty = psVectorAlloc(0, PS_TYPE_F32);
+        psVector *tmpVec = pmPeaksInVector(tmpVecEmpty, 0.0);
+        ok(tmpVec == NULL, "pmPeaksInVector() returned a NULL with NULL psVector input");
+        psFree(tmpVec);
+        psFree(tmpVecEmpty);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Calling pmPeaksInVector with PS_TYPE_F64 psVector.  Should generate error.
+    {
+        psMemId id = psMemGetId();
+        psVector *tmpVecF64 = psVectorAlloc(TST01_VECTOR_LENGTH, PS_TYPE_F64);
+        psVector *tmpVec = pmPeaksInVector(tmpVecF64, 0.0);
+        ok(tmpVec == NULL, "pmPeaksInVector() returned a NULL with F64 psVector input");
+        psFree(tmpVecF64);
+        psFree(tmpVec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    ok(test_pmPeaksInVector(1), "Tested pmPeaksInVector() on length 1 input vector");
+    ok(test_pmPeaksInVector(10), "Tested pmPeaksInVector() on length 10 input vector");
+
+
+    // ------------------------------------------------------------------------
+    // pmPeaksInImage() tests
+    // Calling pmPeaksInImage with NULL psImage.  Should generate error.
+    {
+        psMemId id = psMemGetId();
+        psArray *tmpArray = pmPeaksInImage(NULL, 0.0);
+        ok(tmpArray == NULL, "pmPeaksInImage() returned NULL with NULL input image");
+        psFree(tmpArray);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Calling pmPeaksInImage with empty psImage.  Should generate error.
+    {
+        psMemId id = psMemGetId();
+        psImage *tmpImageEmpty = psImageAlloc(0, 0, PS_TYPE_F32);
+        psArray *tmpArray = pmPeaksInImage(tmpImageEmpty, 0.0);
+        ok(tmpArray == NULL, "pmPeaksInImage() returned NULL with empty input image");
+        psFree(tmpArray);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    
+
+    // Calling pmPeaksInImage with PS_TYPE_F64 psImage.  Should generate error
+    {
+        psMemId id = psMemGetId();
+        psImage *tmpImageF64 = psImageAlloc(TST02_NUM_ROWS, TST02_NUM_COLS, PS_TYPE_F64);
+        psArray *tmpArray = pmPeaksInImage(tmpImageF64, 0.0);
+        ok(tmpArray == NULL, "pmPeaksInImage() returned NULL with F64 input image");
+        psFree(tmpImageF64);
+        psFree(tmpArray);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // XXX: Uncomment these and debug
+    //    testStatus&= test_pmPeaksInImage(1, 1);
+    //    testStatus&= test_pmPeaksInImage(2, 5);
+    //    testStatus&= test_pmPeaksInImage(5, 2);
+    // HEY: add code for small images
+    //    testStatus&= test_pmPeaksInImage(1, 1);
+    //    testStatus&= test_pmPeaksInImage(1, 8);
+    //    testStatus&= test_pmPeaksInImage(8, 1);
+    ok(test_pmPeaksInImage(TST02_NUM_ROWS, TST02_NUM_COLS),
+      "Tested pmPeaksInImage() on (%d, %d) image", TST02_NUM_ROWS, TST02_NUM_COLS);
+    ok(test_pmPeaksInImage(2*TST02_NUM_ROWS, TST02_NUM_COLS),
+      "Tested pmPeaksInImage() on (%d, %d) image", 2*TST02_NUM_ROWS, TST02_NUM_COLS);
+    ok(test_pmPeaksInImage(TST02_NUM_ROWS, 2*TST02_NUM_COLS),
+      "Tested pmPeaksInImage() on (%d, %d) image", TST02_NUM_ROWS, 2*TST02_NUM_COLS);
+
+
+    // ------------------------------------------------------------------------
+    // Test pmPeaksSubset()
+    // Calling pmPeaksSubset with NULL psList.  Should generate error.
+    {
+        psMemId id = psMemGetId();
+        psArray *outData = pmPeaksSubset(NULL, 0.0, psRegionSet(0, 0, 0, 0));
+        ok(outData == NULL, "pmPeaksSubset() returned a NULL with a NULL psArray input");
+        psFree(outData);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Set peaks in input image.  All even-column and even-row pixels are
+    // set non-zero, all other pixels are set to zero.
+    psImage *imgData = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+    psS32 numPeaksOrig = 0;
+    for (psS32 i = 0 ; i < NUM_ROWS ; i++) {
+        for (psS32 j = 0 ; j < NUM_COLS ; j++) {
+            if ((0 == i%2) && (0 == j%2)) {
+                imgData->data.F32[i][j] = (float) (i + 10);
+                numPeaksOrig++;
+            } else {
+                imgData->data.F32[i][j] = 0.0;
+            }
+        }
+    }
+    // Call pmPeaksSubset() with large maxValue and disjoint psRegion.
+    // Should not remove any peaks.
+    {
+        psMemId id = psMemGetId();
+        psArray *outData = pmPeaksInImage(imgData, 0.0);
+        psArray *outData2 = pmPeaksSubset(outData, PS_MAX_F32, psRegionSet(20, 20, 20, 20));
+        ok(outData2 != NULL && psMemCheckArray(outData),
+           "pmPeaksSubset() returned a non-NULL psArray (large maxValue)");
+        ok(outData2->n == numPeaksOrig,
+          "pmPeaksSubset() returned correct number of peaks (was %d, should be %d)", outData2->n+1, numPeaksOrig);
+        psFree(outData);
+        psFree(outData2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPeaksSubset() with small maxValue and disjoint psRegion.
+    // Should not remove any peaks.
+    {
+        psMemId id = psMemGetId();
+        psArray *outData = pmPeaksInImage(imgData, 0.0);
+        psArray *outData2 = pmPeaksSubset(outData, 0.0, psRegionSet(20, 20, 20, 20));
+        ok(outData2 != NULL && psMemCheckArray(outData),
+           "pmPeaksSubset() returned a non-NULL psArray (small maxValue)");
+        ok(outData2->n == 0,
+          "pmPeaksSubset() returned correct number of peaks (was %d, should be %d)", outData2->n, 0);
+        psFree(outData);
+        psFree(outData2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPeaksSubset() with large maxValue and enclosing psRegion.
+    // Should remove aall peaks.
+    {
+        psMemId id = psMemGetId();
+        psArray *outData = pmPeaksInImage(imgData, 0.0);
+        psRegion tmpRegion = psRegionSet(-PS_MAX_F32, PS_MAX_F32, -PS_MAX_F32, PS_MAX_F32);
+        psArray *outData2 = pmPeaksSubset(outData, PS_MAX_F32, tmpRegion);
+        ok(outData2 != NULL && psMemCheckArray(outData),
+           "pmPeaksSubset() returned a non-NULL psArray (small maxValue, enclosing psRegion)");
+        ok(outData2->n == 0,
+          "pmPeaksSubset() returned correct number of peaks (was %d, should be %d)", outData2->n, 0);
+        psFree(outData);
+        psFree(outData2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmPeaksSubset() with large maxValue and enclosing psRegion.
+    // Should remove aall peaks.
+    {
+        psMemId id = psMemGetId();
+        psArray *outData = pmPeaksInImage(imgData, 0.0);
+        psRegion tmpRegion = psRegionSet(-PS_MAX_F32, PS_MAX_F32, -PS_MAX_F32, PS_MAX_F32);
+        psArray *outData2 = pmPeaksSubset(outData, 0.0, tmpRegion);
+        ok(outData2 != NULL && psMemCheckArray(outData),
+           "pmPeaksSubset() returned a non-NULL psArray (small maxValue, inclusive psRegion)");
+        ok(outData2->n == 0,
+          "pmPeaksSubset() returned correct number of peaks (was %d, should be %d)", outData2->n, 0);
+        psFree(outData);
+        psFree(outData2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmResiduals.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmResiduals.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmResiduals.c	(revision 22158)
@@ -0,0 +1,46 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+	All functions are tested.
+*/
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(11);
+
+
+    // Test pmFringeRegionsAlloc()
+    // pmResiduals *pmResidualsAlloc (int xSize, int ySize, int xBin, int yBin);
+    {
+        psMemId id = psMemGetId();
+        int xSize = 1;
+        int ySize = 2;
+        int xBin = 3;
+        int yBin = 4;
+        pmResiduals *resid = pmResidualsAlloc(xSize, ySize, xBin, yBin);
+        ok(resid != NULL && psMemCheckResiduals(resid), "pmResidualsAlloc() allocated a pmResiduals struct correctly");
+        ok(resid->Ro && psMemCheckImage(resid->Ro), "pmResidualsAlloc() allocated the resid->Ro image");
+        ok(resid->Rx && psMemCheckImage(resid->Rx), "pmResidualsAlloc() allocated the resid->Rx image");
+        ok(resid->Ry && psMemCheckImage(resid->Ry), "pmResidualsAlloc() allocated the resid->Ry image");
+        ok(resid->weight && psMemCheckImage(resid->weight), "pmResidualsAlloc() allocated the resid->weight image");
+        ok(resid->mask && psMemCheckImage(resid->mask), "pmResidualsAlloc() allocated the resid->mask image");
+
+        int nX = xSize * xBin;
+        int nY = ySize * yBin;
+        nX = (nX % 2) ? nX : nX + 1;
+        nY = (nY % 2) ? nY : nY + 1;
+        ok(resid->xBin == xBin, "pmResidualsAlloc() set resid->xBin correctly");
+        ok(resid->yBin == yBin, "pmResidualsAlloc() set resid->yBin correctly");
+        ok(resid->xCenter == 0.5*(nX - 1), "pmResidualsAlloc() set resid->xCenter correctly");
+        ok(resid->yCenter == 0.5*(nY - 1), "pmResidualsAlloc() set resid->xCenter correctly");
+
+        psFree(resid);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSource.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSource.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSource.c	(revision 22158)
@@ -0,0 +1,838 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/*
+Tested:
+    Tested
+        pmSourceAlloc()
+        pmSourceCopy()
+        pmSourceDefinePixels()
+        pmSourceRedefinePixels()
+        pmSourcePSFClump()
+        pmSourceGetModel()
+        pmSourceAdd()
+        pmSourceSub()
+        pmSourceAddWithOffset()
+        pmSourceSubWithOffset()
+        pmSourceOp()
+        pmSourceCacheModel()
+        pmSourceCachePSF()
+        pmSourceSortBySN()	(COMPILER ERRORS)
+        pmSourceSortByY()	(COMPILER ERRORS)
+    Must test
+        pmSourceMoments()
+        pmSourceRoughClass()
+
+*/
+
+
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           (4+1)
+#define TEST_NUM_COLS           (4+1)
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.01)
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(128);
+
+    // ----------------------------------------------------------------------
+    // Test pmSourceAlloc()
+    // pmSource *pmSourceAlloc();
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        ok(src != NULL && psMemCheckSource(src), "pmSourceAlloc() returned a non-NULL pmSource");
+        skip_start(src == NULL, 24, "Skipping tests because pmSourceAlloc() returned NULL");
+        ok(src->peak == NULL, "pmSourceAlloc() pmSource->peak correctly");
+        ok(src->pixels == NULL, "pmSourceAlloc() pmSource->pixels correctly");
+        ok(src->weight == NULL, "pmSourceAlloc() pmSource->weight correctly");
+        ok(src->maskObj == NULL, "pmSourceAlloc() pmSource->maskObj correctly");
+        ok(src->maskView == NULL, "pmSourceAlloc() pmSource->maskView correctly");
+        ok(src->modelFlux == NULL, "pmSourceAlloc() pmSource->modelFlux correctly");
+        ok(src->psfFlux == NULL, "pmSourceAlloc() pmSource->psfFlux correctly");
+        ok(src->moments == NULL, "pmSourceAlloc() pmSource->moments correctly");
+        ok(src->blends == NULL, "pmSourceAlloc() pmSource->blends correctly");
+        ok(src->modelPSF == NULL, "pmSourceAlloc() pmSource->modelPSF correctly");
+        ok(src->modelEXT == NULL, "pmSourceAlloc() pmSource->modelEXT correctly");
+        ok(src->modelConv == NULL, "pmSourceAlloc() pmSource->modelConv correctly");
+        ok(src->type == PM_SOURCE_TYPE_UNKNOWN, "pmSourceAlloc() pmSource->type correctly");
+        ok(src->mode == PM_SOURCE_MODE_DEFAULT, "pmSourceAlloc() pmSource->mode correctly");
+
+        ok(isnan(src->psfMag), "pmSourceAlloc() pmSource->psfMag correctly");
+        ok(isnan(src->extMag), "pmSourceAlloc() pmSource->extMag correctly");
+        ok(isnan(src->errMag), "pmSourceAlloc() pmSource->errMag correctly");
+        ok(isnan(src->apMag), "pmSourceAlloc() pmSource->apMag correctly");
+        ok(isnan(src->sky), "pmSourceAlloc() pmSource->sky correctly");
+        ok(isnan(src->skyErr), "pmSourceAlloc() pmSource->skyErr correctly");
+        ok(isnan(src->pixWeight), "pmSourceAlloc() pmSource->pixWeight correctly");
+        int srcID = src->id;
+        psFree(src);
+
+        // Allocate another pmSource to ensure that pmSource->id is incremented
+        pmSource *src = pmSourceAlloc();
+        ok(src != NULL, "pmSourceAlloc() returned a non-NULL pmSource");
+        ok(src->id == srcID+1, "pmSourceAlloc() incremented the pmSource->id correctly");
+        psFree(src);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceCopy() tests
+    // Call pmSourceCopy() with NULL input
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceCopy(NULL);
+        ok(src == NULL, "pmSourceCopy(NULL) returned NULL");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceCopy() with non-NULL input, but NULL members
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        ok(src != NULL, "pmSourceAlloc() returned a non-NULL pmSource");
+        pmSource *dst = pmSourceCopy(src);
+        ok(dst != NULL, "pmSourceCopy() returned a non-NULL pmSource");
+        ok(dst != src, "pmSourceCopy() allocated a new pmSource");
+        ok(dst->type == src->type, "pmSourceCopy() set the pmSource->type");
+        ok(dst->mode == src->mode, "pmSourceCopy() set the pmSource->mode");
+        psFree(src);
+        psFree(dst);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceCopy() with non-NULL input, non-NULL members
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        ok(src != NULL, "pmSourceAlloc() returned a non-NULL pmSource");
+        // Set pmPeak values
+        src->peak = pmPeakAlloc (1, 2, 3.0, PM_PEAK_LONE);
+        src->peak->xf = 4.0;
+        src->peak->yf = 5.0;
+        src->peak->flux = 6.0;
+        src->peak->SN = 10.0;
+        src->moments = pmMomentsAlloc();
+        src->moments->x = 11.0;
+        src->moments->y = 12.0;
+        src->moments->Sx = 15.0;
+        src->moments->Sy = 16.0;
+        src->moments->Sxy = 19.0;
+
+        src->pixels = psImageAlloc(2, 4, PS_TYPE_F32);
+        src->weight = psImageAlloc(6, 8, PS_TYPE_F32);
+        src->maskView  = psImageAlloc(10, 12, PS_TYPE_U8);
+        pmSource *dst = pmSourceCopy(src);
+        ok(dst != NULL, "pmSourceCopy() returned a non-NULL pmSource");
+        ok(dst != src, "pmSourceCopy() allocated a new pmSource");
+        ok(dst->type == src->type, "pmSourceCopy() set the pmSource->type");
+        ok(dst->mode == src->mode, "pmSourceCopy() set the pmSource->mode");
+        ok(dst->peak != NULL, "pmSourceCopy() allocated a new pmSource->peak");
+        ok(dst->peak->xf == src->peak->xf, "pmSourceCopy() pmSource->peak->xf");
+        ok(dst->peak->yf == src->peak->yf, "pmSourceCopy() pmSource->peak->yf");
+        ok(dst->peak->flux == src->peak->flux, "pmSourceCopy() pmSource->peak->flux");
+        ok(dst->peak->SN == src->peak->SN, "pmSourceCopy() pmSource->peak->SN");
+        ok(dst->moments != NULL, "pmSourceCopy() allocated a new pmSource->moments");
+        ok(dst->moments->x == src->moments->x, "pmSourceCopy() pmSource->moments->x");
+        ok(dst->moments->y == src->moments->y, "pmSourceCopy() pmSource->moments->y");
+        ok(dst->moments->Sx == src->moments->Sx, "pmSourceCopy() pmSource->moments->Sx");
+        ok(dst->moments->Sy == src->moments->Sy, "pmSourceCopy() pmSource->moments->Sy");
+        ok(dst->moments->Sxy == src->moments->Sxy, "pmSourceCopy() pmSource->moments->Sxy");
+
+        // XXX: We should possibly do a better job testing that these images are copied correctly.
+        ok(dst->pixels != NULL, "pmSourceCopy() allocated a new pmSource->pixels");
+        ok(dst->pixels->numCols == src->pixels->numCols && dst->pixels->numRows == src->pixels->numRows, 
+           "pmSourceCopy() generated correct size pmSource->pixels");
+        ok(dst->weight != NULL, "pmSourceCopy() allocated a new pmSource->weight");
+        ok(dst->weight->numCols == src->weight->numCols && dst->weight->numRows == src->weight->numRows, 
+           "pmSourceCopy() generated correct size pmSource->weight");
+        ok(dst->maskView != NULL, "pmSourceCopy() allocated a new pmSource->maskView");
+        ok(dst->maskView->numCols == src->maskView->numCols && dst->maskView->numRows == src->maskView->numRows, 
+           "pmSourceCopy() generated correct size pmSource->maskView");
+
+        psFree(src);
+        psFree(dst);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceDefinePixels() tests
+    // Call pmSourceDefinePixels() with NULL pmSource input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        ok(!pmSourceDefinePixels(NULL, readout, 1.0, 2.0, 3.0),
+           "pmSourceDefinePixels() returned false with NULL pmSource input parameter");
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceDefinePixels() with NULL pmReadout input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        ok(!pmSourceDefinePixels(src, NULL, 1.0, 2.0, 3.0),
+           "pmSourceDefinePixels() returned false with NULL pmReadout input parameter");
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceDefinePixels() with NULL pmReadout->image input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        psFree(readout->image);
+        readout->image = NULL;
+        ok(!pmSourceDefinePixels(src, NULL, 1.0, 2.0, 3.0),
+           "pmSourceDefinePixels() returned false with NULL pmReadout input parameter");
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceDefinePixels() with negative radius input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        ok(!pmSourceDefinePixels(src, readout, 1.0, 2.0, -3.0),
+           "pmSourceDefinePixels() returned false with negative radius input parameter");
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceDefinePixels() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        for (int i = 0 ; i < readout->image->numRows ; i++) {
+            for (int j = 0 ; j < readout->image->numCols ; j++) {
+                readout->image->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        bool rc = pmSourceDefinePixels(src, readout, (float) TEST_NUM_COLS/2, (float) TEST_NUM_ROWS/2, 2.0);
+        ok(rc, "pmSourceDefinePixels() returned TRUE with acceptable input parameters");
+        int expectedNumCols = 1 + (TEST_NUM_COLS/2);
+        int expectedNumRows = 1 + (TEST_NUM_COLS/2);
+        // XX: We only verify the size of the pixels, weight, maskView, and maskObj
+        // images.  A better test would verify that the actual data is set correctly.
+        // We don't do that here since it basically duplicated psLib function tests.
+        ok(src->pixels->numCols == expectedNumCols && src->pixels->numRows == expectedNumRows, 
+               "pmSourceDefinePixels() set the size of pmSource->pixels correctly");
+        ok(src->weight->numCols == expectedNumCols && src->weight->numRows == expectedNumRows, 
+               "pmSourceDefinePixels() set the size of pmSource->weight correctly");
+        ok(src->maskView->numCols == expectedNumCols && src->maskView->numRows == expectedNumRows, 
+               "pmSourceDefinePixels() set the size of pmSource->maskView correctly");
+        ok(src->maskObj->numCols == expectedNumCols && src->maskObj->numRows == expectedNumRows, 
+               "pmSourceDefinePixels() set the size of pmSource->maskObj correctly");
+
+        psRegion region = psRegionForSquare((float) TEST_NUM_COLS/2, (float) TEST_NUM_ROWS/2, 2.0);
+        region = psRegionForImage(readout->image, region);
+        ok(src->region.x0 == region.x0 && src->region.x1 == region.x1 &&
+           src->region.y0 == region.y0 && src->region.y1 == region.y1,
+          "pmSourceDefinePixels() set pmSource->region correctly");
+
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceRedefinePixels() tests
+    // Call pmSourceRedefinePixels() with NULL pmSource input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        ok(!pmSourceRedefinePixels(NULL, readout, 1.0, 2.0, 3.0),
+           "pmSourceRedefinePixels() returned false with NULL pmSource input parameter");
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceRedefinePixels() with NULL pmReadout input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        ok(!pmSourceRedefinePixels(src, NULL, 1.0, 2.0, 3.0),
+           "pmSourceRedefinePixels() returned false with NULL pmReadout input parameter");
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceRedefinePixels() with NULL pmReadout->image input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        psFree(readout->image);
+        readout->image = NULL;
+        ok(!pmSourceRedefinePixels(src, NULL, 1.0, 2.0, 3.0),
+           "pmSourceRedefinePixels() returned false with NULL pmReadout input parameter");
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceRedefinePixels() with negative radius input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        ok(!pmSourceRedefinePixels(src, readout, 1.0, 2.0, -3.0),
+           "pmSourceRedefinePixels() returned false with negative radius input parameter");
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceRedefinePixels() with acceptable input parameters
+    if (1) {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        pmReadout *readout = generateSimpleReadout(NULL);
+        for (int i = 0 ; i < readout->image->numRows ; i++) {
+            for (int j = 0 ; j < readout->image->numCols ; j++) {
+                readout->image->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        // First set the pixels region to a square of radius 1.
+        bool rc = pmSourceDefinePixels(src, readout, (float) TEST_NUM_COLS/2, (float) TEST_NUM_ROWS/2, 1.0);
+        ok(rc, "pmSourceDefinePixels() returned TRUE with radius 1");
+
+        // Set these flux images so we can verify they are later psFree'ed and set to NULL
+        src->modelFlux = psImageAlloc(2, 2, PS_TYPE_F32);
+        src->psfFlux = psImageAlloc(2, 2, PS_TYPE_F32);
+
+        // Now set the radius to 2, and call pmSourceRedefinePixels()
+        rc = pmSourceRedefinePixels(src, readout, (float) TEST_NUM_COLS/2, (float) TEST_NUM_ROWS/2, 2.0);
+        ok(rc, "pmSourceRedefinePixels() returned TRUE with acceptable input parameters");
+        int expectedNumCols = 1 + (TEST_NUM_COLS/2);
+        int expectedNumRows = 1 + (TEST_NUM_COLS/2);
+        // XX: We only verify the size of the pixels, weight, maskView, and maskObj
+        // images.  A better test would verify that the actual data is set correctly.
+        // We don't do that here since it basically duplicated psLib function tests.
+        ok(src->pixels->numCols == expectedNumCols && src->pixels->numRows == expectedNumRows, 
+               "pmSourceRedefinePixels() set the size of pmSource->pixels correctly");
+        ok(src->weight->numCols == expectedNumCols && src->weight->numRows == expectedNumRows, 
+               "pmSourceRedefinePixels() set the size of pmSource->weight correctly");
+        ok(src->maskView->numCols == expectedNumCols && src->maskView->numRows == expectedNumRows, 
+               "pmSourceRedefinePixels() set the size of pmSource->maskView correctly");
+        ok(src->maskObj->numCols == expectedNumCols && src->maskObj->numRows == expectedNumRows, 
+               "pmSourceRedefinePixels() set the size of pmSource->maskObj correctly");
+
+        psRegion region = psRegionForSquare((float) TEST_NUM_COLS/2, (float) TEST_NUM_ROWS/2, 2.0);
+        region = psRegionForImage(readout->image, region);
+        ok(src->region.x0 == region.x0 && src->region.x1 == region.x1 &&
+           src->region.y0 == region.y0 && src->region.y1 == region.y1,
+          "pmSourceRedefinePixels() set pmSource->region correctly");
+
+        ok(src->modelFlux == NULL, "pmSourceRedefinePixels() set the pmSource->modelFlux to NULL");
+        ok(src->psfFlux == NULL, "pmSourceRedefinePixels() set the pmSource->psfFlux to NULL");
+
+        psFree(src);
+        psFree(readout);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourcePSFClump() tests
+    // pmPSFClump pmSourcePSFClump(psArray *sources, psMetadata *recipe)
+    // Call pmSourcePSFClump() with NULL pmSource input parameter
+    #define NUM_SOURCES 10
+    {
+        psMemId id = psMemGetId();
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        psMetadata *recipe = psMetadataAlloc();
+        bool rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "PSF_CLUMP_SN_LIM", 0, NULL, 0.0);
+        rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "MOMENTS_SX_MAX", 0, NULL, 10.0);
+        rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "MOMENTS_SY_MAX", 0, NULL, 10.0);
+        rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "MOMENTS_AR_MAX", 0, NULL, 3.0);
+
+        pmPSFClump clump = pmSourcePSFClump(NULL, recipe);
+        ok(clump.X == -1.0 && clump.dX == -1.0 && 
+           clump.Y == 0.0 && clump.dY == 0.0, "pmSourcePSFClump(NULL, recipe) returned the error clump");
+
+        psFree(sources);
+        psFree(recipe);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcePSFClump() with NULL recipe input parameter
+    {
+        psMemId id = psMemGetId();
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        psMetadata *recipe = psMetadataAlloc();
+        bool rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "PSF_CLUMP_SN_LIM", 0, NULL, 0.0);
+        rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "MOMENTS_SX_MAX", 0, NULL, 10.0);
+        rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "MOMENTS_SY_MAX", 0, NULL, 10.0);
+        rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "MOMENTS_AR_MAX", 0, NULL, 3.0);
+
+        pmPSFClump clump = pmSourcePSFClump(sources, NULL);
+        ok(clump.X == -1.0 && clump.dX == -1.0 && 
+           clump.Y == 0.0 && clump.dY == 0.0, "pmSourcePSFClump(sources, NULL) returned the error clump");
+
+        psFree(sources);
+        psFree(recipe);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcePSFClump() with acceptable input parameters
+    // XX: This is a fairly simplistic test.  We set the moments of all test pmSources
+    // to (5.0, 5.0), so the clump should be fairly easy to detect.  For further testing
+    // add:
+    //	  Add outliers to the Sx and Sy data, make sure they aren't used in the calculation
+    //    Force it to get the various metadata from the recipes arg.
+    //    Add a few non pmSource types to the sources input pmArray
+    //    Add a few NULL pmSources, or NULL pmSource->moments to the sources input pmArray
+    //    Ensure the data is saved with the KEEP_PSF_CLUMP metadata item
+    //    Add cases where you fail to find a peak.
+    //    Modify data so that the inputs have different moments
+    //
+    {
+        psMemId id = psMemGetId();
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->moments = pmMomentsAlloc();
+            src->moments->Sx = 5.0;
+            src->moments->Sy = 5.0;
+            sources->data[i] = src;
+	}
+        psMetadata *recipe = psMetadataAlloc();
+        bool rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "PSF_CLUMP_SN_LIM", 0, NULL, 0.0);
+        rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "MOMENTS_SX_MAX", 0, NULL, 10.0);
+        rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "MOMENTS_SY_MAX", 0, NULL, 10.0);
+        rc = psMetadataAddF32(recipe, PS_LIST_HEAD, "MOMENTS_AR_MAX", 0, NULL, 3.0);
+
+        pmPSFClump clump = pmSourcePSFClump(sources, recipe);
+        ok(clump.X == 5.0 && clump.dX == 0.0 && 
+           clump.Y == 5.0 && clump.dY == 0.0, "pmSourcePSFClump(sources, NULL) returned the correct clump");
+
+        if (VERBOSE) {
+            printf("clump: (%.2f %.2f %.2f %.2f)\n", clump.X, clump.dX, clump.Y, clump.dY);
+	}
+        psFree(sources);
+        psFree(recipe);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceGetModel() tests
+    // pmModel *pmSourceGetModel (bool *isPSF, const pmSource *source)
+    // Call pmSourceGetModel() with NULL pmSource input parameter
+    #define NUM_SOURCES 10
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        bool isPDF;
+        pmModel *model = pmSourceGetModel(&isPDF, NULL);
+        ok(model == NULL, "pmSourceGetModel() returned NULL with NULL pmSource input parameter");
+
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Call pmSourceGetModel() with acceptable input parameters
+    #define NUM_SOURCES 10
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        // For testing only:
+        src->modelPSF = (pmModel *) 1;
+        src->modelConv = (pmModel *) 2;
+        src->modelEXT = (pmModel *) 3;
+        bool isPDF;
+
+        src->modelConv = (pmModel *) 0;
+        src->type = PM_SOURCE_TYPE_UNKNOWN;
+        pmModel *model = pmSourceGetModel(&isPDF, src);
+        ok(model == NULL, "pmSourceGetModel() returned a NULL pmModel with acceptable input parameters and src->type = PM_SOURCE_TYPE_UNKNOWN");
+        ok(false == isPDF, "pmSourceGetModel() set isPDF to FALSE");
+
+        src->type = PM_SOURCE_TYPE_STAR;
+        model = pmSourceGetModel(&isPDF, src);
+        ok(model != NULL, "pmSourceGetModel() returned a non-NULL pmModel with acceptable input parameters");
+        ok(1 == (int) model, "pmSourceGetModel() returned the correct model with pmSource->type == PM_SOURCE_TYPE_STAR");
+        ok(true == isPDF, "pmSourceGetModel() set isPDF to TRUE");
+
+        src->type = PM_SOURCE_TYPE_EXTENDED;
+        src->modelConv = (pmModel *) 2;
+        model = pmSourceGetModel(&isPDF, src);
+        ok(model != NULL, "pmSourceGetModel() returned a non-NULL pmModel with acceptable input parameters");
+        ok(2 == (int) model, "pmSourceGetModel() returned the correct model with pmSource->type == PM_SOURCE_TYPE_EXTENDED (%d)", (int) model);
+        ok(false == isPDF, "pmSourceGetModel() set isPDF to FALSE");
+
+        src->modelConv = (pmModel *) 0;
+        src->type = PM_SOURCE_TYPE_EXTENDED;
+        model = pmSourceGetModel(&isPDF, src);
+        ok(model != NULL, "pmSourceGetModel() returned a non-NULL pmModel with acceptable input parameters");
+        ok(3 == (int) model, "pmSourceGetModel() returned the correct model with pmSource->type == PM_SOURCE_TYPE_EXTENDED");
+        ok(false == isPDF, "pmSourceGetModel() set isPDF to FALSE");
+
+        src->modelPSF = NULL;
+        src->modelConv = NULL;
+        src->modelEXT = NULL;
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceOp() tests
+    // bool pmSourceOp (pmSource *source, pmModelOpMode mode, bool add,
+    //                  psMaskType maskVal, int dx, int dy)
+    // Call pmSourceOp() with NULL pmSource input parameter
+    #define NUM_SOURCES 10
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        bool rc = pmSourceOp(NULL, PM_MODEL_OP_NONE, true, 1, 0, 0);
+        ok(!rc, "pmSourceOpl() returned FALSE with NULL pmSource input parameter");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // call pmSourceOp() with acceptable parameters
+    // We only test with a single Gaussian model, with no residuals or masks.
+    // For completeness, additional tests should be added.
+        // We should also set mode &= PM_MODEL_OP_NOISE to test that the src->weights are added.
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i = 0 ; i < TEST_NUM_ROWS ; i++) {
+            for (int j = 0 ; j < TEST_NUM_COLS ; j++) {
+                src->pixels->data.F32[i][j] = 0.0;
+            }
+        }
+        src->peak = pmPeakAlloc(TEST_NUM_COLS/2, TEST_NUM_ROWS/2, 5.0, PM_PEAK_LONE);
+        src->type = PM_SOURCE_TYPE_STAR;
+        src->modelPSF = pmModelAlloc(pmModelClassGetType("PS_MODEL_GAUSS"));
+        psF32 *PAR = src->modelPSF->params->data.F32;
+        PAR[PM_PAR_I0] = 5.0;
+        PAR[PM_PAR_XPOS] = 0.0;
+        PAR[PM_PAR_YPOS] = 0.0;
+        PAR[PM_PAR_XPOS] = (float) (TEST_NUM_COLS/2);
+        PAR[PM_PAR_YPOS] = (float) (TEST_NUM_ROWS/2);
+        PAR[PM_PAR_SXX] = 10.0;
+        PAR[PM_PAR_SYY] = 10.0;
+
+        bool rc = pmSourceOp(src, PM_SOURCE_MODE_PSFMODEL, true, 0, 0, 0);
+        ok(rc == true, "pmSourceOp() returned TRUE with acceptable input parameters");
+        psVector *x = psVectorAlloc(2, PS_TYPE_F32);
+        bool errorFlag = false;
+        for (int i = 0 ; i < TEST_NUM_ROWS ; i++) {
+            for (int j = 0 ; j < TEST_NUM_COLS ; j++) {
+                x->data.F32[0] = (float) j;
+                x->data.F32[1] = (float) i;
+                psF32 modF = src->modelPSF->modelFunc (NULL, src->modelPSF->params, x);
+                psF32 imgF = src->pixels->data.F32[i][j];
+                if (!TEST_FLOATS_EQUAL(modF, imgF)) {
+                    diag("ERROR: src->pixels[%d][%d] is %.2f, should be %.2f", i, j, src->pixels->data.F32[i][j], modF);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "pmSourceOp() set the image pixels correctly (PSF function)");
+        psFree(x);
+        psFree(src);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // call pmSourceOp() with acceptable parameters
+    // Test source->modelFlux
+        // We should also set mode &= PM_MODEL_OP_NOISE to test that the src->weights are added.
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        src->modelFlux = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i = 0 ; i < TEST_NUM_ROWS ; i++) {
+            for (int j = 0 ; j < TEST_NUM_COLS ; j++) {
+                src->pixels->data.F32[i][j] = 0.0;
+                src->modelFlux->data.F32[i][j] = (float) (i + j);
+            }
+        }
+        src->peak = pmPeakAlloc(TEST_NUM_COLS/2, TEST_NUM_ROWS/2, 5.0, PM_PEAK_LONE);
+        src->type = PM_SOURCE_TYPE_STAR;
+        src->modelPSF = pmModelAlloc(pmModelClassGetType("PS_MODEL_GAUSS"));
+        psF32 *PAR = src->modelPSF->params->data.F32;
+        PAR[PM_PAR_I0] = 1.0;
+        PAR[PM_PAR_XPOS] = 0.0;
+        PAR[PM_PAR_YPOS] = 0.0;
+        PAR[PM_PAR_XPOS] = (float) (TEST_NUM_COLS/2);
+        PAR[PM_PAR_YPOS] = (float) (TEST_NUM_ROWS/2);
+        PAR[PM_PAR_SXX] = 10.0;
+        PAR[PM_PAR_SYY] = 10.0;
+
+        bool rc = pmSourceOp(src, PM_SOURCE_MODE_PSFMODEL, true, 0, 0, 0);
+        ok(rc == true, "pmSourceOp() returned TRUE with acceptable input parameters");
+        psVector *x = psVectorAlloc(2, PS_TYPE_F32);
+        bool errorFlag = false;
+        for (int i = 0 ; i < TEST_NUM_ROWS ; i++) {
+            for (int j = 0 ; j < TEST_NUM_COLS ; j++) {
+                x->data.F32[0] = (float) j;
+                x->data.F32[1] = (float) i;
+                psF32 modF = src->modelFlux->data.F32[i][j];
+                psF32 imgF = src->pixels->data.F32[i][j];
+                if (!TEST_FLOATS_EQUAL(modF, imgF)) {
+                    diag("ERROR: src->pixels[%d][%d] is %.2f, should be %.2f", i, j, src->pixels->data.F32[i][j], modF);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "pmSourceOp() set the image pixels correctly (src->modelFlux cache image)");
+        psFree(x);
+        psFree(src);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceCacheModel() tests
+    // call pmSourceCacheModel() with NULL pmSource input parameter
+    {
+        psMemId id = psMemGetId();
+        bool rc = pmSourceCacheModel(NULL, 0);
+        ok(rc == false, "pmSourceCacheModel() returned FALSE with NULL pmSource input parameter");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceCacheModel() tests
+    // bool pmSourceCacheModel (pmSource *source, psMaskType maskVal) {
+    // call pmSourceCacheModel() with acceptable parameters
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i = 0 ; i < TEST_NUM_ROWS ; i++) {
+            for (int j = 0 ; j < TEST_NUM_COLS ; j++) {
+                src->pixels->data.F32[i][j] = 0.0;
+            }
+        }
+        src->peak = pmPeakAlloc(TEST_NUM_COLS/2, TEST_NUM_ROWS/2, 5.0, PM_PEAK_LONE);
+        src->type = PM_SOURCE_TYPE_STAR;
+        src->modelPSF = pmModelAlloc(pmModelClassGetType("PS_MODEL_GAUSS"));
+        psF32 *PAR = src->modelPSF->params->data.F32;
+        PAR[PM_PAR_I0] = 1.0;
+        PAR[PM_PAR_XPOS] = 0.0;
+        PAR[PM_PAR_YPOS] = 0.0;
+        PAR[PM_PAR_XPOS] = (float) (TEST_NUM_COLS/2);
+        PAR[PM_PAR_YPOS] = (float) (TEST_NUM_ROWS/2);
+        PAR[PM_PAR_SXX] = 10.0;
+        PAR[PM_PAR_SYY] = 10.0;
+
+        bool rc = pmSourceCacheModel(src, 0);
+        ok(rc == true, "pmSourceCacheModel() returned TRUE with acceptable input parameters");
+
+        psVector *x = psVectorAlloc(2, PS_TYPE_F32);
+        bool errorFlag = false;
+        for (int i = 0 ; i < TEST_NUM_ROWS ; i++) {
+            for (int j = 0 ; j < TEST_NUM_COLS ; j++) {
+                x->data.F32[0] = (float) j;
+                x->data.F32[1] = (float) i;
+                psF32 modF = src->modelPSF->modelFunc (NULL, src->modelPSF->params, x);
+                psF32 imgF = src->modelFlux->data.F32[i][j];
+                if (!TEST_FLOATS_EQUAL(modF, imgF)) {
+                    diag("ERROR: src->modelFlux[%d][%d] is %.2f, should be %.2f", i, j, src->modelFlux->data.F32[i][j], modF);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "pmSourceCacheModel() set the src->modelFlux correctly (PSF function)");
+        psFree(x);
+        psFree(src);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceCachePSF() tests
+    // bool pmSourceCachePSF (pmSource *source, psMaskType maskVal) {
+    // call pmSourceCachePSF() with NULL pmSource input parameter
+    {
+        psMemId id = psMemGetId();
+        bool rc = pmSourceCachePSF(NULL, 0);
+        ok(rc == false, "pmSourceCachePSF() returned FALSE with NULL pmSource input parameter");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // call pmSourceCachePSF() with acceptable parameters
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i = 0 ; i < TEST_NUM_ROWS ; i++) {
+            for (int j = 0 ; j < TEST_NUM_COLS ; j++) {
+                src->pixels->data.F32[i][j] = 0.0;
+            }
+        }
+        src->peak = pmPeakAlloc(TEST_NUM_COLS/2, TEST_NUM_ROWS/2, 5.0, PM_PEAK_LONE);
+        src->type = PM_SOURCE_TYPE_STAR;
+        src->modelPSF = pmModelAlloc(pmModelClassGetType("PS_MODEL_GAUSS"));
+        psF32 *PAR = src->modelPSF->params->data.F32;
+        PAR[PM_PAR_I0] = 1.0;
+        PAR[PM_PAR_XPOS] = 0.0;
+        PAR[PM_PAR_YPOS] = 0.0;
+        PAR[PM_PAR_XPOS] = (float) (TEST_NUM_COLS/2);
+        PAR[PM_PAR_YPOS] = (float) (TEST_NUM_ROWS/2);
+        PAR[PM_PAR_SXX] = 10.0;
+        PAR[PM_PAR_SYY] = 10.0;
+
+        bool rc = pmSourceCachePSF(src, 0);
+        ok(rc == true, "pmSourceCachePSF() returned TRUE with acceptable input parameters");
+
+        psVector *x = psVectorAlloc(2, PS_TYPE_F32);
+        bool errorFlag = false;
+        for (int i = 0 ; i < TEST_NUM_ROWS ; i++) {
+            for (int j = 0 ; j < TEST_NUM_COLS ; j++) {
+                x->data.F32[0] = (float) j;
+                x->data.F32[1] = (float) i;
+                psF32 modF = src->modelPSF->modelFunc (NULL, src->modelPSF->params, x);
+                psF32 imgF = src->psfFlux->data.F32[i][j];
+                if (!TEST_FLOATS_EQUAL(modF, imgF)) {
+                    diag("ERROR: src->psfFlux[%d][%d] is %.2f, should be %.2f", i, j, src->psfFlux->data.F32[i][j], modF);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "pmSourceCachePSF() set the src->psfFlux correctly (PSF function)");
+        psFree(x);
+        psFree(src);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------
+    // pmSourceSortBySN() tests
+    // int pmSourceSortBySN (const void **a, const void **b)
+    // Call pmSourceSortBySN() with acceptable input parameters.
+    // XXX: We don't test with NULL input parameters since this function has no PS_ASSERTS to protect
+    // against that.
+/* XXXX: Compiler errors: fix this
+    {
+        psMemId id = psMemGetId();
+        pmSource *src1 = pmSourceAlloc();
+        src1->peak = pmPeakAlloc(3, 4, 2.0, PM_PEAK_LONE);
+        src1->peak->SN = 10.0;
+        pmSource *src2 = pmSourceAlloc();
+        src2->peak = pmPeakAlloc(3, 4, 2.0, PM_PEAK_LONE);
+        src2->peak->SN = 20.0;
+
+        int rc = pmSourceSortBySN((const void **) &src1, (const void **) &src2);
+        ok(rc == 1, "pmSourceSortBySN() returned correct result (source1 < source2) (%d)", rc);
+        rc = pmSourceSortBySN((const void **) &src2, (const void **) &src1);
+        ok(rc == -1, "pmSourceSortBySN() returned correct result (source2 < source1) (%d)", rc);
+        rc = pmSourceSortBySN((const void **) &src1, (const void **) &src1);
+        ok(rc == 0, "pmSourceSortBySN() returned correct result (source1 == source2) (%d)", rc);
+
+        psFree(src1);
+        psFree(src2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------
+    // pmSourceSortByY() tests
+    // int pmSourceSortByY (const void **a, const void **b)
+    // Call pmSourceSortByY() with acceptable input parameters.
+    // XXX: We don't test with NULL input parameters since this function has no PS_ASSERTS to protect
+    // against that.
+    {
+        psMemId id = psMemGetId();
+        pmSource *src1 = pmSourceAlloc();
+        src1->peak = pmPeakAlloc(3, 4, 2.0, PM_PEAK_LONE);
+        src1->peak->y = 10.0;
+        pmSource *src2 = pmSourceAlloc();
+        src2->peak = pmPeakAlloc(3, 4, 2.0, PM_PEAK_LONE);
+        src2->peak->y = 20.0;
+
+        int rc = pmSourceSortByY((const void **) &src1, (const void **) &src2);
+        ok(rc == -1, "pmSourceSortByY() returned correct result (source1 < source2) (%d)", rc);
+        rc = pmSourceSortByY((const void **) &src2, (const void **) &src1);
+        ok(rc == 1, "pmSourceSortByY() returned correct result (source2 < source1) (%d)", rc);
+        rc = pmSourceSortByY((const void **) &src1, (const void **) &src1);
+        ok(rc == 0, "pmSourceSortByY() returned correct result (source1 == source2) (%d)", rc);
+
+        psFree(src1);
+        psFree(src2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+*/
+
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceContour.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceContour.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceContour.c	(revision 22158)
@@ -0,0 +1,179 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    XXX: All functions only tested with unallowable input parameters.
+    I tried to use acceptable data, but could not get the source code to work the
+    way I thought it should have.
+*/
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           (10)
+#define TEST_NUM_COLS           (16)
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         10
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.0001)
+#define NUM_SOURCES		100
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(11);
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceContour() tests
+    // psArray *pmSourceContour (psImage *image, int xc, int yc, float threshold)
+    // Call pmSourceContour() with NULL psImage input parameter
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psArray *array = pmSourceContour(NULL, 1, 2, 3.0);
+        ok(array == NULL, "pmSourceContour() returned NULL with NULL psImage input parameter");
+        psFree(img);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceContour() with unallowed row/column numbers
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psArray *array = pmSourceContour(img, -1, 2, 3.0);
+        ok(array == NULL, "pmSourceContour() returned NULL with column = -1");
+        array = pmSourceContour(img, TEST_NUM_COLS, 2, 3.0);
+        ok(array == NULL, "pmSourceContour() returned NULL with column >= numCols");
+        array = pmSourceContour(img, 1, -1, 3.0);
+        ok(array == NULL, "pmSourceContour() returned NULL with row = -1");
+        array = pmSourceContour(img, 1, TEST_NUM_ROWS, 3.0);
+        ok(array == NULL, "pmSourceContour() returned NULL with row >= numRows");
+
+        psFree(img);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceContour() with acceptable input parameters
+    // XXX: These tests currently fail
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i = 0 ; i < img->numRows ; i++) {
+            for (int j = 0 ; j < img->numCols ; j++) {
+                img->data.F32[i][j] = (float) ((TEST_NUM_ROWS + TEST_NUM_COLS) - (abs(i - (TEST_NUM_ROWS/2)) + abs(j - (TEST_NUM_COLS/2))));
+	    }
+	}
+        if (1) {
+            for (int i = 0 ; i < img->numRows ; i++) {
+                for (int j = 0 ; j < img->numCols ; j++) {
+                    printf("(%.0f)", img->data.F32[i][j]);
+    	    }
+                printf("\n");
+	    }
+	}
+
+        psArray *array = pmSourceContour(img, TEST_NUM_COLS/2, TEST_NUM_ROWS/2, 22.0);
+        ok(array != NULL, "pmSourceContour() returned non-NULL with acceptable input parameters");
+        for (int i = 0 ; i < array->n ; i++) {
+            psVector *vec = (psVector *) array->data[i];
+            printf("Point %d: (%.2f %.2f)\n", i, vec->data.F32[0], vec->data.F32[1]);
+	}
+
+        psFree(array);
+        psFree(img);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceContour_Crude() tests
+    // psArray *pmSourceContour_Crude_Crude(pmSource *source, psImage *image, psF32 level)
+    // Call pmSourceContour_Crude() with NULL psSource input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        src->moments = pmMomentsAlloc();
+        src->modelEXT = pmModelAlloc(1);
+        psImage *img = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i = 0 ; i < img->numRows ; i++) {
+            for (int j = 0 ; j < img->numCols ; j++) {
+                if ((i >= TEST_NUM_ROWS/4) && (i < 3*TEST_NUM_ROWS/4) &&
+                    (j >= TEST_NUM_COLS/4) && (j < 3*TEST_NUM_COLS/4)) {
+                    img->data.F32[i][j] = 5.0;
+		} else {
+                    img->data.F32[i][j] = 0.0;
+		}
+	    }
+	}
+        psArray *array = pmSourceContour_Crude(NULL, img, 3.0);
+        ok(array == NULL, "pmSourceContour_Crude() returned NULL with NULL pmSource input parameter");
+        psFree(img);
+        psFree(src);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceContour_Crude() with NULL psImage input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        src->moments = pmMomentsAlloc();
+        src->modelEXT = pmModelAlloc(1);
+        psImage *img = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i = 0 ; i < img->numRows ; i++) {
+            for (int j = 0 ; j < img->numCols ; j++) {
+                if ((i >= TEST_NUM_ROWS/4) && (i < 3*TEST_NUM_ROWS/4) &&
+                    (j >= TEST_NUM_COLS/4) && (j < 3*TEST_NUM_COLS/4)) {
+                    img->data.F32[i][j] = 5.0;
+		} else {
+                    img->data.F32[i][j] = 0.0;
+		}
+	    }
+	}
+        psArray *array = pmSourceContour_Crude(src, NULL, 3.0);
+        ok(array == NULL, "pmSourceContour_Crude() returned NULL with NULL pmImage input parameter");
+        psFree(img);
+        psFree(src);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceContour_Crude() with acceptable input parameters
+    // XXX: Must correct this
+    if (0) {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        src->moments = pmMomentsAlloc();
+        src->modelEXT = pmModelAlloc(1);
+        psImage *img = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+
+        if (0) {
+            for (int i = 0 ; i < img->numRows ; i++) {
+                for (int j = 0 ; j < img->numCols ; j++) {
+                    img->data.F32[i][j] = (float) ((TEST_NUM_ROWS + TEST_NUM_COLS) - (abs(i - (TEST_NUM_ROWS/2)) + abs(j - (TEST_NUM_COLS/2))));
+		}
+	    }
+	}
+        printf("Calling pmSourceContour_Crude()\n");
+        psArray *array = pmSourceContour_Crude(src, img, 22.0);
+        printf("Called pmSourceContour_Crude()\n");
+        ok(array != NULL, "pmSourceContour_Crude() returned non-NULL with NULL pmImage input parameter");
+        psFree(img);
+        psFree(src);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceExtendedPars.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceExtendedPars.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceExtendedPars.c	(revision 22158)
@@ -0,0 +1,121 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+        All functions are tested.
+*/
+
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(35);
+
+    // ----------------------------------------------------------------------
+    // pmSourceExtendedParsAlloc() tests
+    {
+        psMemId id = psMemGetId();
+        pmSourceExtendedPars *tmp = pmSourceExtendedParsAlloc();
+        ok(tmp && psMemCheckSourceExtendedPars(tmp), "pmSourceExtendedParsAlloc() allocated a pmSourceExtendedPars struct");
+
+        ok(tmp->profile == NULL, "pmSourceExtendedParsAlloc() set the ->profile member to NULL");
+        ok(tmp->annuli == NULL, "pmSourceExtendedParsAlloc() set the ->annuli member to NULL");
+        ok(tmp->isophot == NULL, "pmSourceExtendedParsAlloc() set the ->isophot member to NULL");
+        ok(tmp->petrosian == NULL, "pmSourceExtendedParsAlloc() set the ->petrosian member to NULL");
+        ok(tmp->kron == NULL, "pmSourceExtendedParsAlloc() set the ->kron member to NULL");
+
+        psFree(tmp);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceRadialProfileAlloc() tests
+    {
+        psMemId id = psMemGetId();
+        pmSourceRadialProfile *tmp = pmSourceRadialProfileAlloc();
+        ok(tmp && psMemCheckSourceRadialProfile(tmp), "pmSourceRadialProfile() allocated a pmSourceRadialProfilestruct");
+
+        ok(tmp->radius == NULL, "pmSourceRadialProfileAlloc() set the ->radius member to NULL");
+        ok(tmp->flux == NULL, "pmSourceRadialProfileAlloc() set the ->flux member to NULL");
+        ok(tmp->weight == NULL, "pmSourceRadialProfileAlloc() set the ->weight member to NULL");
+
+        psFree(tmp);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceIsophotalValuesAlloc() tests
+    {
+        psMemId id = psMemGetId();
+        pmSourceIsophotalValues *tmp = pmSourceIsophotalValuesAlloc();
+        ok(tmp && psMemCheckSourceIsophotalValues(tmp), "pmSourceIsophotalValues() allocated a pmSourceIsophotalValuesstruct");
+
+        ok(tmp->mag == 0.0, "pmSourceIsophotalValuesAlloc() set the ->mag member to 0.0");
+        ok(tmp->magErr == 0.0, "pmSourceIsophotalValuesAlloc() set the ->magErr member to 0.0");
+        ok(tmp->rad == 0.0, "pmSourceIsophotalValuesAlloc() set the ->rad member to 0.0");
+        ok(tmp->radErr == 0.0, "pmSourceIsophotalValuesAlloc() set the ->radErr member to 0.0");
+
+        psFree(tmp);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourcePetrosianValuesAlloc() tests
+    {
+        psMemId id = psMemGetId();
+        pmSourcePetrosianValues *tmp = pmSourcePetrosianValuesAlloc();
+        ok(tmp && psMemCheckSourcePetrosianValues(tmp), "pmSourcePetrosianValues() allocated a pmSourcePetrosianValuesstruct");
+
+        ok(tmp->mag == 0.0, "pmSourcePetrosianValuesAlloc() set the ->mag member to 0.0");
+        ok(tmp->magErr == 0.0, "pmSourcePetrosianValuesAlloc() set the ->magErr member to 0.0");
+        ok(tmp->rad == 0.0, "pmSourcePetrosianValuesAlloc() set the ->rad member to 0.0");
+        ok(tmp->radErr == 0.0, "pmSourcePetrosianValuesAlloc() set the ->radErr member to 0.0");
+
+        psFree(tmp);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceKronValuesAlloc() tests
+    {
+        psMemId id = psMemGetId();
+        pmSourceKronValues *tmp = pmSourceKronValuesAlloc();
+        ok(tmp && psMemCheckSourceKronValues(tmp), "pmSourceKronValues() allocated a pmSourceKronValuesstruct");
+
+        ok(tmp->mag == 0.0, "pmSourceKronValuesAlloc() set the ->mag member to 0.0");
+        ok(tmp->magErr == 0.0, "pmSourceKronValuesAlloc() set the ->magErr member to 0.0");
+        ok(tmp->rad == 0.0, "pmSourceKronValuesAlloc() set the ->rad member to 0.0");
+        ok(tmp->radErr == 0.0, "pmSourceKronValuesAlloc() set the ->radErr member to 0.0");
+
+        psFree(tmp);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceAnnuliAlloc() tests
+    {
+        psMemId id = psMemGetId();
+        pmSourceAnnuli *tmp = pmSourceAnnuliAlloc();
+        ok(tmp && psMemCheckSourceAnnuli(tmp), "pmSourceAnnuli() allocated a pmSourceAnnulistruct");
+
+        ok(tmp->flux == NULL, "pmSourceAnnuliAlloc() set the ->flux member to NULL");
+        ok(tmp->fluxErr == NULL, "pmSourceAnnuliAlloc() set the ->fluxErr member to NULL");
+        ok(tmp->fluxVar == NULL, "pmSourceAnnuliAlloc() set the ->fluxVar member to NULL");
+
+        psFree(tmp);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceFitModel.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceFitModel.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceFitModel.c	(revision 22158)
@@ -0,0 +1,191 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+bool fitModels (psRandom *seed, float flux, float radius, float sigma);
+bool fitModelFlux (psRandom *seed, float flux, float radius, float sigma);
+
+// tests to check accuracy of fitted models for a range of fit radii, sigma, and flux.
+// we generate a fake source, then fit the model to it.  the difference or fractional
+// difference between the true and fitted parameters is saved.
+// we run these tests 200 times each an examine the resulting distribution of deviations.
+// the tests fail if the stdevs are more than 2x the expected stdev based on poisson noise
+// ** is 2x too generous?
+int main (void)
+{
+    pmModelGroupInit ();
+    pmSourceFitModelInit (15, 0.01, 1.0, true);
+
+    // psTraceSetLevel ("psModules.objects.pmSourceFitModel", 10);
+    // psTraceSetLevel ("psLib.math.psMinimizeLMChi2", 10);
+
+    plan_tests(240);
+
+    // build a gauss-deviate vector (mean = 0.0, sigma = 1.0)
+    psRandom *seed = psRandomAlloc (PS_RANDOM_TAUS, 0);
+
+    static float radius[] = {3.0, 5.0, 7.0, 10.0, 15.0, 25.0};
+    static float sigma[] = {1.0, 1.5, 2.0};
+    static float flux[] = {10000.0, 3000.0, 1000.0, 300.0, 100.0, 30.0, 10.0};
+
+    // drop-dead simple: should always work
+    bool status = fitModels (seed, 10000.0, 10.0, 2.0);
+    skip_start (!status, 240, "*** BASIC MODEL FITTING FAILS! *** : skipping related tests");
+
+    for (int i = 0; i < sizeof(sigma)/sizeof(float); i++) {
+        for (int j = 0; j < sizeof(radius)/sizeof(float); j++) {
+            for (int k = 0; k < sizeof(flux)/sizeof(float); k++) {
+                fitModels (seed, flux[k], radius[j], sigma[i]);
+            }
+        }
+    }
+
+    skip_end();
+    return exit_status();
+}
+
+static psVector *par1 = NULL;
+static psVector *par2 = NULL;
+static psVector *par3 = NULL;
+static psVector *par4 = NULL;
+static psVector *par5 = NULL;
+
+# define NMODELS 200
+bool fitModels (psRandom *seed, float flux, float radius, float sigma)
+{
+
+    psMemId id = psMemGetId();
+
+    diag("test model fit - flux: %f, radius: %f, sigma: %f", flux, radius, sigma);
+
+    par1 = psVectorAllocEmpty (NMODELS, PS_TYPE_F32);
+    par2 = psVectorAllocEmpty (NMODELS, PS_TYPE_F32);
+    par3 = psVectorAllocEmpty (NMODELS, PS_TYPE_F32);
+    par4 = psVectorAllocEmpty (NMODELS, PS_TYPE_F32);
+    par5 = psVectorAllocEmpty (NMODELS, PS_TYPE_F32);
+
+    for (int i = 0; i < NMODELS; i++) {
+        fitModelFlux (seed, flux, radius, sigma);
+    }
+
+    float signal = 2*M_PI*sigma*sigma*flux;
+    float noise = sqrt(signal + 4*M_PI*sigma*sigma*(100 + PS_SQR(5)));
+    float dMag = noise / signal;
+    float dPos = sigma * dMag;
+    diag ("signal: %f, noise: %f, dMag: %f, dPos: %f", signal, noise, dMag, dPos);
+
+    bool status = (par1->n == NMODELS);
+    ok (status, "all %d tests passed", NMODELS);
+
+    psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
+    psVectorStats (stats, par1, NULL, NULL, 0);
+    ok ((stats->sampleStdev/dMag < 2.0), "Io ref/fit stdev: %e : %e sigma", stats->sampleStdev, stats->sampleStdev/dMag);
+    psVectorStats (stats, par2, NULL, NULL, 0);
+    ok ((stats->sampleStdev/dPos < 2.0), "Xo ref/fit stdev: %e : %e sigma", stats->sampleStdev, stats->sampleStdev/dPos);
+    psVectorStats (stats, par3, NULL, NULL, 0);
+    ok ((stats->sampleStdev/dPos < 2.0), "Yo ref/fit stdev: %e : %e sigma", stats->sampleStdev, stats->sampleStdev/dPos);
+    psVectorStats (stats, par4, NULL, NULL, 0);
+    ok ((stats->sampleStdev/dMag < 2.0), "Sx ref/fit stdev: %e : %e sigma", stats->sampleStdev, stats->sampleStdev/dMag);
+    psVectorStats (stats, par5, NULL, NULL, 0);
+    ok ((stats->sampleStdev/dMag < 2.0), "Sy ref/fit stdev: %e : %e sigma", stats->sampleStdev, stats->sampleStdev/dMag);
+
+    psFree (par1);
+    psFree (par2);
+    psFree (par3);
+    psFree (par4);
+    psFree (par5);
+    psFree (stats);
+
+    ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks");
+    return status;
+}
+
+bool fitModelFlux (psRandom *seed, float flux, float radius, float sigma)
+{
+
+    psVector *rnd = psVectorAlloc (1000, PS_TYPE_F32);
+    for (int i = 0; i < rnd->n; i++) {
+        rnd->data.F32[i] = psRandomGaussian (seed);
+    }
+
+    // construct a model
+    pmSource *source = pmSourceAlloc ();
+    source->moments = pmMomentsAlloc ();
+
+    pmModelType type = pmModelClassGetType ("PS_MODEL_GAUSS");
+    source->modelEXT = pmModelAlloc (type);
+
+    source->modelEXT->params->data.F32[0] = 0;
+    source->modelEXT->params->data.F32[1] = flux;
+    source->modelEXT->params->data.F32[2] = 50;
+    source->modelEXT->params->data.F32[3] = 50;
+    source->modelEXT->params->data.F32[4] = 2.0*sqrt(sigma);
+    source->modelEXT->params->data.F32[5] = 2.0*sqrt(sigma);
+    source->modelEXT->params->data.F32[6] = 0;
+
+    source->pixels = psImageAlloc (100, 100, PS_TYPE_F32);
+    source->weight = psImageAlloc (100, 100, PS_TYPE_F32);
+    source->mask   = psImageAlloc (100, 100, PS_TYPE_U8);
+    psImageInit (source->pixels, 0.0);
+    psImageInit (source->weight, 0.0);
+    psImageInit (source->mask, 0);
+
+    // create an image with the model, and add noise: gain is 1, subtracted sky is 100, readnoise is 5
+    pmModelAdd (source->pixels, source->mask, source->modelEXT, PM_MODEL_OP_FULL);
+    int npix = 0;
+    for (int j = 0; j < source->pixels->numRows; j++) {
+        for (int i = 0; i < source->pixels->numCols; i++) {
+            float flux = source->pixels->data.F32[j][i];
+            float var = flux + 100 + PS_SQR(5);
+            source->pixels->data.F32[j][i] += rnd->data.F32[npix]*sqrt(var);
+            source->weight->data.F32[j][i] = var;
+            npix ++;
+            if (npix == rnd->n)
+                npix = 0;
+        }
+    }
+
+    // psFits *fits = psFitsOpen ("test.fits", "w");
+    // psFitsWriteImage (fits, NULL, source->pixels, 0, NULL);
+    // psFitsClose (fits);
+
+    // save the original model, modify params
+    pmModel *guess = pmModelCopy (source->modelEXT);
+    guess->params->data.F32[1] *= 0.9;
+    guess->params->data.F32[2] += 1.0;
+    guess->params->data.F32[3] -= 1.0;
+    guess->params->data.F32[4] *= 0.9;
+    guess->params->data.F32[5] *= 0.9;
+
+    psImageKeepCircle (source->mask, 50, 50, radius, "OR", PM_MASK_MARK);
+    bool status = pmSourceFitModel (source, guess, PM_SOURCE_FIT_EXT);
+    if (!status) {
+        psFree (rnd);
+        psFree (source);
+        psFree (guess);
+        return false;
+    }
+    psImageKeepCircle (source->mask, 50, 50, radius, "AND", PS_NOT_U8(PM_MASK_MARK));
+
+    par1->data.F32[par1->n] = (source->modelEXT->params->data.F32[1] / guess->params->data.F32[1]);
+    par2->data.F32[par2->n] = (source->modelEXT->params->data.F32[2] - guess->params->data.F32[2]);
+    par3->data.F32[par3->n] = (source->modelEXT->params->data.F32[3] - guess->params->data.F32[3]);
+    par4->data.F32[par4->n] = (source->modelEXT->params->data.F32[4] / guess->params->data.F32[4]);
+    par5->data.F32[par5->n] = (source->modelEXT->params->data.F32[5] / guess->params->data.F32[5]);
+
+    psVectorExtend (par1, 100, 1);
+    psVectorExtend (par2, 100, 1);
+    psVectorExtend (par3, 100, 1);
+    psVectorExtend (par4, 100, 1);
+    psVectorExtend (par5, 100, 1);
+
+    psFree (rnd);
+    psFree (source);
+    psFree (guess);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceFitModel_Delta.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceFitModel_Delta.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceFitModel_Delta.c	(revision 22158)
@@ -0,0 +1,238 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+bool fitModels (psRandom *seed, float flux, float radius, float sigma);
+bool fitModelFlux (psRandom *seed, float flux, float radius, float sigma);
+bool printDev (float *src, float *par, int Npar, bool absolute);
+
+int main (void)
+{
+    pmModelGroupInit ();
+    pmSourceFitModelInit (15, 0.01, 1.0, true);
+
+    float flux = 10000;
+    float sigma = 2.0;
+    float radius = 10.0;
+
+    plan_tests(240);
+
+    // build a gauss-deviate vector (mean = 0.0, sigma = 1.0)
+    psRandom *seed = psRandomAlloc (PS_RANDOM_TAUS, 0);
+
+    // noise vector to noise up the image
+    psVector *rnd = psVectorAlloc (1000, PS_TYPE_F32);
+    for (int i = 0; i < rnd->n; i++) {
+        rnd->data.F32[i] = psRandomGaussian (seed);
+    }
+
+    // construct a GAUSS model
+    pmSource *source = pmSourceAlloc ();
+    source->moments = pmMomentsAlloc ();
+
+    pmModelType type = pmModelClassGetType ("PS_MODEL_GAUSS");
+    source->modelEXT = pmModelAlloc (type);
+
+    source->modelEXT->params->data.F32[0] = 0;
+    source->modelEXT->params->data.F32[1] = flux;
+    source->modelEXT->params->data.F32[2] = 50;
+    source->modelEXT->params->data.F32[3] = 50;
+    source->modelEXT->params->data.F32[4] = 2.0*sqrt(sigma);
+    source->modelEXT->params->data.F32[5] = 2.0*sqrt(sigma);
+    source->modelEXT->params->data.F32[6] = 0;
+
+    source->pixels = psImageAlloc (100, 100, PS_TYPE_F32);
+    source->weight = psImageAlloc (100, 100, PS_TYPE_F32);
+    source->mask   = psImageAlloc (100, 100, PS_TYPE_U8);
+    psImageInit (source->pixels, 0.0);
+    psImageInit (source->weight, 0.0);
+    psImageInit (source->mask, 0);
+
+    // create an image with the model, and add noise: gain is 1, subtracted sky is 100, readnoise is 5
+    pmModelAdd (source->pixels, source->mask, source->modelEXT, PM_MODEL_OP_FULL);
+    int npix = 0;
+    for (int j = 0; j < source->pixels->numRows; j++) {
+        for (int i = 0; i < source->pixels->numCols; i++) {
+            float flux = source->pixels->data.F32[j][i];
+            float var = flux + 100 + PS_SQR(5);
+            source->pixels->data.F32[j][i] += rnd->data.F32[npix]*sqrt(var);
+            source->weight->data.F32[j][i] = var;
+            npix ++;
+            if (npix == rnd->n)
+                npix = 0;
+        }
+    }
+
+    // fit with a PGAUSS model
+    pmModel *guess;
+
+    type = pmModelClassGetType ("PS_MODEL_PGAUSS");
+    guess = pmModelAlloc (type);
+
+    guess->params->data.F32[0] = 0;
+    guess->params->data.F32[1] = flux;
+    guess->params->data.F32[2] = 50;
+    guess->params->data.F32[3] = 50;
+    guess->params->data.F32[4] = 2.0*sqrt(sigma);
+    guess->params->data.F32[5] = 2.0*sqrt(sigma);
+    guess->params->data.F32[6] = 0;
+    // modify guess
+    guess->params->data.F32[1] *= 0.9;
+    guess->params->data.F32[2] += 1.0;
+    guess->params->data.F32[3] -= 1.0;
+    guess->params->data.F32[4] *= 0.9;
+    guess->params->data.F32[5] *= 0.9;
+
+    psImageKeepCircle (source->mask, 50, 50, radius, "OR", PM_MASK_MARK);
+    pmSourceFitModel (source, guess, PM_SOURCE_FIT_EXT);
+    psImageKeepCircle (source->mask, 50, 50, radius, "AND", PS_NOT_U8(PM_MASK_MARK));
+
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 1, false);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 2, true);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 3, true);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 4, false);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 5, false);
+
+    psImageKeepCircle (source->mask, 50, 50, radius, "OR", PM_MASK_MARK);
+    pmSourceFitModel (source, guess, PM_SOURCE_FIT_PSF);
+    psImageKeepCircle (source->mask, 50, 50, radius, "AND", PS_NOT_U8(PM_MASK_MARK));
+
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 1, false);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 2, true);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 3, true);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 4, false);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 5, false);
+
+    // muck up the Sx, Sy terms a little : how does this affect the dparams?
+    float Sx = guess->params->data.F32[4];
+    float Sy = guess->params->data.F32[5];
+    guess->params->data.F32[4] = 0.95*Sx;
+    guess->params->data.F32[5] = 0.95*Sy;
+
+    psImageKeepCircle (source->mask, 50, 50, radius, "OR", PM_MASK_MARK);
+    pmSourceFitModel (source, guess, PM_SOURCE_FIT_PSF);
+    psImageKeepCircle (source->mask, 50, 50, radius, "AND", PS_NOT_U8(PM_MASK_MARK));
+
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 1, false);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 2, true);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 3, true);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 4, false);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 5, false);
+
+    // muck up the Sx, Sy terms a little : how does this affect the dparams?
+    guess->params->data.F32[4] = 0.99*Sx;
+    guess->params->data.F32[5] = 0.99*Sy;
+
+    psImageKeepCircle (source->mask, 50, 50, radius, "OR", PM_MASK_MARK);
+    pmSourceFitModel (source, guess, PM_SOURCE_FIT_PSF);
+    psImageKeepCircle (source->mask, 50, 50, radius, "AND", PS_NOT_U8(PM_MASK_MARK));
+
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 1, false);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 2, true);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 3, true);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 4, false);
+    printDev (source->modelEXT->params->data.F32, guess->params->data.F32, 5, false);
+
+    psFree (rnd);
+    psFree (source);
+    psFree (guess);
+
+    return true;
+}
+
+bool printDev (float *src, float *fit, int Npar, bool absolute)
+{
+    float dev;
+    if (absolute) {
+        dev = (src[Npar]-fit[Npar]);
+        fprintf (stderr, "par %d : %f vs %f : abso dev %f\n", Npar, src[Npar], fit[Npar], dev);
+    } else {
+        dev = (src[Npar]/fit[Npar]);
+        fprintf (stderr, "par %d : %f vs %f : frac dev %f\n", Npar, src[Npar], fit[Npar], dev);
+    }
+    return true;
+}
+
+# if (0)
+    int main (void)
+{
+    pmModelGroupInit ();
+    pmSourceFitModelInit (15, 0.01, 1.0, true);
+
+    plan_tests(240);
+
+    // build a gauss-deviate vector (mean = 0.0, sigma = 1.0)
+    psRandom *seed = psRandomAlloc (PS_RANDOM_TAUS, 0);
+
+    static float radius[] = {3.0, 5.0, 7.0, 10.0, 15.0, 25.0};
+    static float sigma[] = {1.0, 1.5, 2.0};
+    static float flux[] = {10000.0, 3000.0, 1000.0, 300.0, 100.0, 30.0, 10.0};
+
+    for (int i = 0; i < sizeof(sigma)/sizeof(float); i++) {
+        for (int j = 0; j < sizeof(radius)/sizeof(float); j++) {
+            for (int k = 0; k < sizeof(flux)/sizeof(float); k++) {
+                fitModels (seed, flux[k], radius[j], sigma[i]);
+            }
+        }
+    }
+
+    return exit_status();
+}
+
+static psVector *par1 = NULL;
+static psVector *par2 = NULL;
+static psVector *par3 = NULL;
+static psVector *par4 = NULL;
+static psVector *par5 = NULL;
+
+bool fitModels (psRandom *seed, float flux, float radius, float sigma)
+{
+
+    psMemId id = psMemGetId();
+
+    diag("test model fit - flux: %f, radius: %f, sigma: %f", flux, radius, sigma);
+
+    par1 = psVectorAllocEmpty (200, PS_TYPE_F32);
+    par2 = psVectorAllocEmpty (200, PS_TYPE_F32);
+    par3 = psVectorAllocEmpty (200, PS_TYPE_F32);
+    par4 = psVectorAllocEmpty (200, PS_TYPE_F32);
+    par5 = psVectorAllocEmpty (200, PS_TYPE_F32);
+
+    for (int i = 0; i < 200; i++) {
+        fitModelFlux (seed, flux, radius, sigma);
+    }
+
+    float signal = 2*M_PI*sigma*sigma*flux;
+    float noise = sqrt(signal + 4*M_PI*sigma*sigma*(100 + PS_SQR(5)));
+    float dMag = noise / signal;
+    float dPos = sigma * dMag;
+    diag ("signal: %f, noise: %f, dMag: %f, dPos: %f", signal, noise, dMag, dPos);
+
+    psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
+    psVectorStats (stats, par1, NULL, NULL, 0);
+    ok ((stats->sampleStdev/dMag < 2.0), "Io ref/fit stdev: %f : %f sigma", stats->sampleStdev, stats->sampleStdev/dMag);
+    psVectorStats (stats, par2, NULL, NULL, 0);
+    ok ((stats->sampleStdev/dPos < 2.0), "Xo ref/fit stdev: %f : %f sigma", stats->sampleStdev, stats->sampleStdev/dPos);
+    psVectorStats (stats, par3, NULL, NULL, 0);
+    ok ((stats->sampleStdev/dPos < 2.0), "Yo ref/fit stdev: %f : %f sigma", stats->sampleStdev, stats->sampleStdev/dPos);
+    psVectorStats (stats, par4, NULL, NULL, 0);
+    ok ((stats->sampleStdev/dMag < 2.0), "Sx ref/fit stdev: %f : %f sigma", stats->sampleStdev, stats->sampleStdev/dMag);
+    psVectorStats (stats, par5, NULL, NULL, 0);
+    ok ((stats->sampleStdev/dMag < 2.0), "Sy ref/fit stdev: %f : %f sigma", stats->sampleStdev, stats->sampleStdev/dMag);
+
+    psFree (par1);
+    psFree (par2);
+    psFree (par3);
+    psFree (par4);
+    psFree (par5);
+    psFree (stats);
+
+    ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    return true;
+}
+
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceFitSet.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceFitSet.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceFitSet.c	(revision 22158)
@@ -0,0 +1,726 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    All functions are tested except:
+        pmSourceFitSetCheckLimits()
+        pmSourceFitSetFunction()
+    Those functions set static variables which aer invisible to test code.
+
+    These functions are very lightly tested and must be augmented:
+	pmSourceFitSet()
+	pmSourceFitSetMasks()
+*/
+
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           (16)
+#define TEST_NUM_COLS           (30)
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.0001)
+#define NUM_MODELS		5
+
+pmSource *create_pmSource() {
+    pmSource *src = pmSourceAlloc();
+    if (1) {
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        src->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+        if (1) {
+            for (int i = 0 ; i < TEST_NUM_ROWS ; i++) {
+                for (int j = 0 ; j < TEST_NUM_COLS ; j++) {
+                    src->pixels->data.F32[i][j] = 0.0;
+                    src->weight->data.F32[i][j] = 1.0;
+                    src->maskObj->data.U8[i][j] = 0;
+                }
+            }
+        }
+        if (1) {
+            int halfRows = TEST_NUM_ROWS/2;
+            int halfCols = TEST_NUM_COLS/2;
+            for (int i = halfRows-1 ; i < halfRows+1 ; i++) {
+                for (int j = halfCols-1 ; j < halfCols+1 ; j++) {
+                    src->pixels->data.F32[i][j] = 1.0;
+                }
+            }
+            src->pixels->data.F32[halfRows][halfCols] = 5.0;
+        }
+    }
+    return(src);
+}
+
+bool call_pmSourceFitSet() {
+    psArray *modelSet = psArrayAlloc(NUM_MODELS);
+    for (int i = 0 ; i < NUM_MODELS ; i++) {
+        modelSet->data[i] = (psPtr *) pmModelAlloc(i);
+    }
+    pmSource *src = create_pmSource();
+    bool rc = pmSourceFitSet(src, modelSet, PM_SOURCE_FIT_PSF, 1);
+    if (!rc) {
+        diag("ERROR: pmSourceFitSet() returned FALSE");
+        return(false);
+    }
+    psFree(src);
+    for (int i = 0 ; i < NUM_MODELS ; i++) {
+        psFree(modelSet->data[i]);
+        modelSet->data[i] = NULL;
+    }
+    psFree(modelSet);
+    pmModelClassCleanup();
+  
+    return(true);
+}
+
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(70);
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceFitSetDataAlloc() tests
+    // Call pmSourceFitSetDataAlloc() with NULL psArray input parameter
+    {
+        psMemId id = psMemGetId();
+        psArray *modelSet = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < modelSet->n ; i++) {
+            modelSet->data[i] = (psPtr *) pmModelAlloc(1);
+	}
+        pmSourceFitSetData *fitSetData = pmSourceFitSetDataAlloc(NULL);
+        ok(fitSetData == NULL, "pmSourceFitSetDataAlloc() returned NULL with NULL psArray input parameter");
+        psFree(fitSetData);
+        pmModelClassCleanup();
+        psFree(modelSet); 
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceFitSetDataAlloc() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        psArray *modelSet = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < modelSet->n ; i++) {
+            modelSet->data[i] = (psPtr *) pmModelAlloc(i);
+	}
+        pmSourceFitSetData *set = pmSourceFitSetDataAlloc(modelSet);
+        ok(set != NULL && psMemCheckSourceFitSetData(set),
+          "pmSourceFitSetDataAlloc() returned non-NULL with acceptable input parameters");
+        ok(set->paramSet != NULL && set->paramSet->n == modelSet->n, 
+          "pmSourceFitSetDataAlloc() set the set->paramSet psArray correctly");
+        ok(set->derivSet != NULL && set->derivSet->n == modelSet->n, 
+          "pmSourceFitSetDataAlloc() set the set->derivSet psArray correctly");
+        for (int i = 0 ; i < modelSet->n ; i++) {
+            int nParams = pmModelClassParameterCount(i);
+            psVector *tmpV = (psVector *) (set->paramSet->data[i]);
+            ok(tmpV != NULL && psMemCheckVector(tmpV) && tmpV->n == nParams,
+               "pmSourceFitSetDataAlloc() set the set->paramSet->data psVector correctly");
+
+            tmpV = (psVector *) (set->derivSet->data[i]);
+            ok(tmpV != NULL && psMemCheckVector(tmpV) && tmpV->n == nParams,
+               "pmSourceFitSetDataAlloc() set the set->derivSet->data psVector correctly");
+
+            bool errorFlag = false;
+            for (int i = 0 ; i < tmpV->n ; i++) {
+                if (tmpV->data.F32[i] != 0.0) {
+                    errorFlag = true;
+		}
+	    }
+            ok(!errorFlag, "pmSourceFitSetDataAlloc() set the set->derivSet->data correctly");
+	}
+        
+        psFree(set);
+        pmModelClassCleanup();
+        psFree(modelSet); 
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceFitSetCheckLimits() tests
+    // Call pmSourceFitSetCheckLimits() with thisSet == NULL
+    // XXX: Can not test full functionality of pmSourceFitSetCheckLimits() because it
+    // requires that the static variable thisSet be allocated.
+    {
+        psMemId id = psMemGetId();
+        #define NUM_PARAMS 10
+        psF32 *params = (psF32 *) psAlloc(NUM_PARAMS * sizeof(psF32));
+        psF32 *betas = (psF32 *) psAlloc(NUM_PARAMS * sizeof(psF32));
+        bool rc = pmSourceFitSetCheckLimits(PS_MINIMIZE_PARAM_MIN, 10, params, betas);
+        ok(rc == false, "pmSourceFitSetCheckLimits() returned NULL with thisSet == FALSE");
+        psFree(params);
+        psFree(betas);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceFitSetFunction() tests
+    // Call pmSourceFitSetFunction() with thisSet == NULL
+    // XXX: Can not test full functionality of pmSourceFitSetCheckLimits() because it
+    // requires that the static variable thisSet be allocated.
+    {
+        psMemId id = psMemGetId();
+        #define NUM_PARAMS 10
+        psVector *deriv = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+        psVector *param = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+        psVector *x = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+        psF32 tmpF = pmSourceFitSetFunction(deriv, param, x);
+        ok(isnan(tmpF), "pmSourceFitSetFunction() returned NULL with thisSet == FALSE");
+        psFree(deriv);
+        psFree(param);
+        psFree(x);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceFitSetJoin() tests
+    // Call pmSourceFitSetJoin() with NULL pmSourceFitSetData input parameter
+    {
+        psMemId id = psMemGetId();
+        #define NUM_PARAMS 10
+        psVector *deriv = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+        psVector *param = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+        psArray *modelSet = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < modelSet->n ; i++) {
+            modelSet->data[i] = (psPtr *) pmModelAlloc(i);
+	}
+        pmSourceFitSetData *set = pmSourceFitSetDataAlloc(modelSet);
+        bool rc = pmSourceFitSetJoin(deriv, param, NULL);
+        ok(rc == false, "pmSourceFitSetJoin() returned FALSE with NULL pmSourceFitSetData input parameter");
+        psFree(deriv);
+        psFree(param);
+        psFree(modelSet); 
+        psFree(set);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceFitSetJoin() with unequal size set->paramSet and set->derivSet input parameters
+    {
+        psMemId id = psMemGetId();
+        psVector *deriv = psVectorAlloc(1000, PS_TYPE_F32);
+        psVector *param = psVectorAlloc(1000, PS_TYPE_F32);
+        psArray *modelSet = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < modelSet->n ; i++) {
+            modelSet->data[i] = (psPtr *) pmModelAlloc(i);
+	}
+        pmSourceFitSetData *set = pmSourceFitSetDataAlloc(modelSet);
+        psFree(set->paramSet);
+        set->paramSet = psArrayAlloc(set->derivSet->n + 1);
+        bool rc = pmSourceFitSetJoin(deriv, param, set);
+        ok(rc == false, "pmSourceFitSetJoin() returned FALSE with unequal size set->paramSet and set->derivSet input parameters");
+        psFree(deriv);
+        psFree(param);
+        psFree(modelSet); 
+        psFree(set);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceFitSetJoin() with deriv and param input psVector too small
+    // XXX: Must add a PS_ASSERT to the source code to detect this
+    if (0) {
+        psMemId id = psMemGetId();
+        psVector *small = psVectorAlloc(1, PS_TYPE_F32);
+        psVector *big = psVectorAlloc(1000, PS_TYPE_F32);
+        psArray *modelSet = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < modelSet->n ; i++) {
+            modelSet->data[i] = (psPtr *) pmModelAlloc(i);
+	}
+        pmSourceFitSetData *set = pmSourceFitSetDataAlloc(modelSet);
+        bool rc = pmSourceFitSetJoin(small, big, set);
+        ok(rc == false, "pmSourceFitSetJoin() returned FALSE with deriv input psVector too small");
+        rc = pmSourceFitSetJoin(big, small, set);
+        ok(rc == false, "pmSourceFitSetJoin() returned FALSE with param input psVector too small");
+        psFree(small);
+        psFree(big);
+        psFree(modelSet); 
+        psFree(set);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceFitSetJoin() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        psVector *deriv = psVectorAlloc(1000, PS_TYPE_F32);
+        psVector *param = psVectorAlloc(1000, PS_TYPE_F32);
+        psArray *modelSet = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < modelSet->n ; i++) {
+            modelSet->data[i] = (psPtr *) pmModelAlloc(i);
+	}
+        pmSourceFitSetData *set = pmSourceFitSetDataAlloc(modelSet);
+
+        psF32 cnt = 0.0;
+        for (int i = 0; i < set->paramSet->n; i++) {
+            psVector *paramOne = set->paramSet->data[i];
+            psVector *derivOne = set->derivSet->data[i];
+            for (int j = 0; j < paramOne->n; j++) {
+                paramOne->data.F32[j] = cnt;
+                derivOne->data.F32[j] = cnt;
+                cnt = cnt + 1.0;
+            }
+        }
+
+        bool rc = pmSourceFitSetJoin(deriv, param, set);
+        ok(rc == true, "pmSourceFitSetJoin() returned TRUE acceptable input parameters");
+
+        bool errorFlag = false;
+        for (int i = 0; i < (int) cnt ; i++) {
+            if (deriv->data.F32[i] != (float) i) {
+                diag("ERROR: deriv->data.F32[%d] is %.2ff, should be %.2f\n", i, deriv->data.F32[i], (float) i);
+                errorFlag = true;
+            }
+            if (param->data.F32[i] != (float) i) {
+                diag("ERROR: param->data.F32[%d] is %.2ff, should be %.2f\n", i, param->data.F32[i], (float) i);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "pmSourceFitSetJoin() set the deriv and param psVectors correctly");
+
+        psFree(deriv);
+        psFree(param);
+        psFree(modelSet); 
+        psFree(set);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceFitSetSplit() tests
+    // Call pmSourceFitSetSplit() with NULL pmSourceFitSetData input parameter
+    {
+        psMemId id = psMemGetId();
+        #define NUM_PARAMS 10
+        psVector *deriv = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+        psVector *param = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+        psArray *modelSet = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < modelSet->n ; i++) {
+            modelSet->data[i] = (psPtr *) pmModelAlloc(i);
+	}
+        pmSourceFitSetData *set = pmSourceFitSetDataAlloc(modelSet);
+        bool rc = pmSourceFitSetSplit(NULL, deriv, param);
+        ok(rc == false, "pmSourceFitSetSplit() returned FALSE with NULL pmSourceFitSetData input parameter");
+        psFree(deriv);
+        psFree(param);
+        psFree(modelSet); 
+        psFree(set);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceFitSetSplit() with NULL src->paramSet and src->derivSet input parameters and
+    // src->paramSet and src->derivSet of unequal size
+    {
+        psMemId id = psMemGetId();
+        #define NUM_PARAMS 10
+        psVector *deriv = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+        psVector *param = psVectorAlloc(NUM_PARAMS, PS_TYPE_F32);
+        psArray *modelSet = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < modelSet->n ; i++) {
+            modelSet->data[i] = (psPtr *) pmModelAlloc(i);
+	}
+        pmSourceFitSetData *set = pmSourceFitSetDataAlloc(modelSet);
+        psArray *tmpArray = set->paramSet;
+        set->paramSet = NULL;
+        bool rc = pmSourceFitSetSplit(set, deriv, param);
+        ok(rc == false, "pmSourceFitSetSplit() returned FALSE with NULL src->paramSet input parameter");
+        set->paramSet = tmpArray;
+
+        tmpArray = set->derivSet;
+        set->derivSet = NULL;
+        rc = pmSourceFitSetSplit(set, deriv, param);
+        ok(rc == false, "pmSourceFitSetSplit() returned FALSE with NULL src->derivSet input parameter");
+        set->derivSet = tmpArray;
+
+        psFree(set->paramSet);
+        set->paramSet = psArrayAlloc(set->derivSet->n + 1);
+        ok(rc == false, "pmSourceFitSetSplit() returned FALSE with src->paramSet and src->derivSet of unequal size");
+
+        psFree(deriv);
+        psFree(param);
+        psFree(modelSet); 
+        psFree(set);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceFitSetSplit() with NULL param input parameter
+    {
+        psMemId id = psMemGetId();
+        psVector *deriv = psVectorAlloc(1000, PS_TYPE_F32);
+        psVector *param = psVectorAlloc(1000, PS_TYPE_F32);
+        for (int i = 0 ; i < 1000 ; i++) {
+            param->data.F32[i] = (float) i;
+            deriv->data.F32[i] = (float) i;
+        }
+        psArray *modelSet = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < modelSet->n ; i++) {
+            modelSet->data[i] = (psPtr *) pmModelAlloc(i);
+	}
+        pmSourceFitSetData *set = pmSourceFitSetDataAlloc(modelSet);
+        bool rc = pmSourceFitSetSplit(set, deriv, NULL);
+        ok(rc == false, "pmSourceFitSetSplit() returned FALSE with NULL param input parameter");
+        psFree(deriv);
+        psFree(param);
+        psFree(modelSet); 
+        psFree(set);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceFitSetSplit() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        psVector *deriv = psVectorAlloc(1000, PS_TYPE_F32);
+        psVector *param = psVectorAlloc(1000, PS_TYPE_F32);
+        for (int i = 0 ; i < 1000 ; i++) {
+            deriv->data.F32[i] = (float) i;
+            param->data.F32[i] = (float) i;
+        }
+        psArray *modelSet = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < modelSet->n ; i++) {
+            modelSet->data[i] = (psPtr *) pmModelAlloc(i);
+	}
+        pmSourceFitSetData *set = pmSourceFitSetDataAlloc(modelSet);
+        bool rc = pmSourceFitSetSplit(set, deriv, param);
+        ok(rc == true, "pmSourceFitSetSplit() returned FALSE with acceptable input parameters");
+
+        bool errorFlag = false;
+        psF32 cnt = 0.0;
+        for (int i = 0; i < set->paramSet->n; i++) {
+            psVector *paramOne = set->paramSet->data[i];
+            psVector *derivOne = set->derivSet->data[i];
+            for (int j = 0; j < paramOne->n; j++) {
+                if (paramOne->data.F32[j] != cnt) {
+                    diag("ERROR: paramOne->data.F32[%d] is %.2ff, should be %.2f\n", i, paramOne->data.F32[i], (float) i);
+                    errorFlag = true;
+                }
+                if (derivOne->data.F32[j] != cnt) {
+                    diag("ERROR: derivOne->data.F32[%d] is %.2ff, should be %.2f\n", i, derivOne->data.F32[i], (float) i);
+                    errorFlag = true;
+                }
+                cnt = cnt + 1.0;
+            }
+        }
+        ok(!errorFlag, "pmSourceFitSetSplit() set the deriv and param psVectors correctly");
+
+        psFree(deriv);
+        psFree(param);
+        psFree(modelSet); 
+        psFree(set);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceFitSetValues() tests
+    // Call pmSourceFitSetValues() with bad input parameters
+    {
+        psMemId id = psMemGetId();
+        #define VEC_SIZE 1000
+        #define NUM_ITER 32
+        #define TOL 0.1
+        psVector *param = psVectorAlloc(VEC_SIZE, PS_TYPE_F32);
+        psVector *dparam = psVectorAlloc(VEC_SIZE, PS_TYPE_F32);
+        psArray *modelSet = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < modelSet->n ; i++) {
+            modelSet->data[i] = (psPtr *) pmModelAlloc(i);
+	}
+        pmSourceFitSetData *set = pmSourceFitSetDataAlloc(modelSet);
+        pmSource *src = create_pmSource();
+        psMinimization *myMin = psMinimizationAlloc(NUM_ITER, TOL);
+        int nPix = 10;
+        bool fitStatus = true;
+        // NULL set input parameter
+        bool rc = pmSourceFitSetValues(NULL, dparam, param, src, myMin, nPix, fitStatus);
+        ok(rc == false, "pmSourceFitSetValues() returned FALSE with NULL set input parameter");
+
+        // NULL set->paramSet
+        psArray *tmpArray = set->paramSet;
+        set->paramSet = NULL;
+        rc = pmSourceFitSetValues(set, dparam, param, src, myMin, nPix, fitStatus);
+        ok(rc == false, "pmSourceFitSetValues() returned FALSE with NULL set->paramSet");
+        set->paramSet = tmpArray;
+
+        // NULL dparam input parameter
+        rc = pmSourceFitSetValues(set, NULL, param, src, myMin, nPix, fitStatus);
+        ok(rc == false, "pmSourceFitSetValues() returned FALSE with NULL dparam input parameter");
+
+        // NULL param input parameter
+        rc = pmSourceFitSetValues(set, dparam, NULL, src, myMin, nPix, fitStatus);
+        ok(rc == false, "pmSourceFitSetValues() returned FALSE with NULL param input parameter");
+
+        // NULL pmSource input parameter
+        rc = pmSourceFitSetValues(set, dparam, param, NULL, myMin, nPix, fitStatus);
+        ok(rc == false, "pmSourceFitSetValues() returned FALSE with NULL pmSource input parameter");
+
+        // NULL pmSource->pixels input parameter
+        psImage *tmpImg = src->pixels;
+        src->pixels = NULL;
+        rc = pmSourceFitSetValues(set, dparam, param, src, myMin, nPix, fitStatus);
+        ok(rc == false, "pmSourceFitSetValues() returned FALSE with NULL pmSource->pixels input parameter");
+        src->pixels = tmpImg;
+
+        // NULL psMinimization input parameter
+        rc = pmSourceFitSetValues(set, dparam, param, src, NULL, nPix, fitStatus);
+        ok(rc == false, "pmSourceFitSetValues() returned FALSE with NULL psMinimization input parameter");
+
+        psFree(param);
+        psFree(dparam);
+        psFree(modelSet); 
+        psFree(set);
+        psFree(src);
+        psFree(myMin);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmSourceFitSetValues() tests
+    // Call pmSourceFitSetValues() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        #define VEC_SIZE 1000
+        #define NUM_ITER 32
+        #define TOL 0.1
+        #define MIN_VALUE	22.0
+        #define NUM_PIX 100
+        psVector *param = psVectorAlloc(VEC_SIZE, PS_TYPE_F32);
+        psVector *dparam = psVectorAlloc(VEC_SIZE, PS_TYPE_F32);
+        for (int i = 0 ; i < VEC_SIZE ; i++) {
+            param->data.F32[i] = (float) i;
+            dparam->data.F32[i] = (float) i;
+        }
+        psArray *modelSet = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < modelSet->n ; i++) {
+            modelSet->data[i] = (psPtr *) pmModelAlloc(i);
+	}
+        pmSourceFitSetData *set = pmSourceFitSetDataAlloc(modelSet);
+        pmSource *src = create_pmSource();
+        psMinimization *myMin = psMinimizationAlloc(NUM_ITER, TOL);
+        int nPix = NUM_PIX;
+        bool fitStatus = true;
+
+        bool rc = pmSourceFitSetValues(set, dparam, param, src, myMin, nPix, fitStatus);
+        ok(rc == true, "pmSourceFitSetValues() returned TRUE with acceptable input paramaters");
+
+        bool errorFlag = false;
+        psF32 cnt = 0.0;
+        for (int i = 0; i < set->paramSet->n; i++) {
+            pmModel *model = set->modelSet->data[i];
+            for (int j = 0; j < model->params->n; j++) {
+                if (model->params->data.F32[j] != cnt) {
+                    diag("ERROR: model->params->data.F32[%d] is %.2ff, should be %.2f\n", i, model->params->data.F32[i], (float) i);
+                    errorFlag = true;
+                }
+                if (model->dparams->data.F32[j] != cnt) {
+                    diag("ERROR: model->dparams->data.F32[%d] is %.2ff, should be %.2f\n", i, model->dparams->data.F32[i], (float) i);
+                    errorFlag = true;
+                }
+                if (model->chisq != myMin->value) {
+                    diag("ERROR: model->chisq is %.2f, should be %.2f", model->chisq, MIN_VALUE);
+                    errorFlag = true;
+                }
+                if (model->nIter != myMin->iter) {
+                    diag("ERROR: model->nIter is %.2f, should be %.2f", model->nIter, NUM_ITER);
+                    errorFlag = true;
+                }
+                if (model->nDOF != NUM_PIX - model->params->n) {
+                    diag("ERROR: model->nDOF is %d, should be %d", model->nDOF, NUM_PIX-model->params->n);
+                    errorFlag = true;
+                }
+
+                cnt = cnt + 1.0;
+            }
+        }
+        ok(!errorFlag, "pmSourceFitSetValues() set the deriv and param psVectors correctly");
+
+        psFree(param);
+        psFree(dparam);
+        psFree(modelSet); 
+        psFree(set);
+        psFree(src);
+        psFree(myMin);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceFitSetMasks() tests
+    // Call pmSourceFitSetMasks() with bad input parameters
+    {
+        psMemId id = psMemGetId();
+        #define VEC_SIZE 1000
+        #define NUM_ITER 32
+        #define TOL 0.1
+        psArray *modelSet = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < modelSet->n ; i++) {
+            modelSet->data[i] = (psPtr *) pmModelAlloc(i);
+	}
+        pmSourceFitSetData *set = pmSourceFitSetDataAlloc(modelSet);
+        psMinConstraint *constraint = psMinConstraintAlloc();
+
+        // NULL psMinConstraint input parameter
+        bool rc = pmSourceFitSetMasks(NULL, set, PM_SOURCE_FIT_NORM);
+        ok(rc == false, "pmSourceFitSetMasks() returned TRUE with NULL psMinConstraint input parameter");
+
+        // NULL pmSourceFitSetData input parameter
+        rc = pmSourceFitSetMasks(constraint, NULL, PM_SOURCE_FIT_NORM);
+        ok(rc == false, "pmSourceFitSetMasks() returned TRUE with NULL pmSourceFitSetData input parameter");
+
+        psFree(modelSet); 
+        psFree(set);
+        psFree(constraint);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceFitSetMasks() with acceptable input parameters
+    // For thoroughness, we should test the PM_SOURCE_FIT_PSF and PM_SOURCE_FIT_EXT mode
+    {
+        psMemId id = psMemGetId();
+        #define VEC_SIZE 1000
+        #define NUM_ITER 32
+        #define TOL 0.1
+        psArray *modelSet = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < modelSet->n ; i++) {
+            modelSet->data[i] = (psPtr *) pmModelAlloc(i);
+	}
+        pmSourceFitSetData *set = pmSourceFitSetDataAlloc(modelSet);
+        psMinConstraint *constraint = psMinConstraintAlloc();
+        constraint->paramMask = psVectorAlloc(1000, PS_TYPE_F32);
+
+        // Acceptable input parameters
+        bool rc = pmSourceFitSetMasks(constraint, set, PM_SOURCE_FIT_NORM);
+        ok(rc == true, "pmSourceFitSetMasks() returned TRUE with acceptable input parameters");
+
+        bool errorFlag = false;
+        int n = 0;
+        for (int i = 0; i < set->paramSet->n; i++) {
+            psVector *paramOne = set->paramSet->data[i];
+            for (int j = 0; j < paramOne->n; j++) {
+                if (j == PM_PAR_I0) continue;
+                if (constraint->paramMask->data.U8[n + j] != 1) {
+                    diag("ERROR: constraint->paramMask->data.U8[%d] is %d, should be a",
+                          n + j, constraint->paramMask->data.U8[n + j]);
+                    errorFlag = true;
+                }
+            }
+            n += paramOne->n;
+        }
+        ok(!errorFlag, "pmSourceFitSetMasks() constraint->paramMask psVector correctly");
+
+        psFree(modelSet); 
+        psFree(set);
+        psFree(constraint);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceFitSet() tests
+    // Call pmSourceFitSet() with NULL psSource input parameter
+    {
+        psMemId id = psMemGetId();
+        psArray *modelSet = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < NUM_MODELS ; i++) {
+            modelSet->data[i] = (psPtr *) pmModelAlloc(i);
+	}
+        pmSource *src = create_pmSource();
+        bool rc = pmSourceFitSet(NULL, modelSet, PM_SOURCE_FIT_PSF, 1);
+        ok(rc == false, "pmSourceFitSet() returned FALSE with NULL psSource input parameter");
+        psFree(src);
+        for (int i = 0 ; i < NUM_MODELS ; i++) {
+            psFree(modelSet->data[i]);
+            modelSet->data[i] = NULL;
+        }
+        psFree(modelSet);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceFitSet() with NULL psSource pixels, weight, maskObj input parameters
+    {
+        psMemId id = psMemGetId();
+        psArray *modelSet = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < NUM_MODELS ; i++) {
+            modelSet->data[i] = (psPtr *) pmModelAlloc(i);
+	}
+        pmSource *src = create_pmSource();
+        psImage *tmpImg = src->pixels;
+        src->pixels = NULL;
+        bool rc = pmSourceFitSet(src, modelSet, PM_SOURCE_FIT_PSF, 1);
+        ok(rc == false, "pmSourceFitSet() returned FALSE with NULL src->pixels input parameter");
+        src->pixels = tmpImg;
+
+        tmpImg = src->weight;
+        src->weight = NULL;
+        rc = pmSourceFitSet(src, modelSet, PM_SOURCE_FIT_PSF, 1);
+        ok(rc == false, "pmSourceFitSet() returned FALSE with NULL src->weight input parameter");
+        src->weight = tmpImg;
+
+        tmpImg = src->maskObj;
+        src->maskObj = NULL;
+        rc = pmSourceFitSet(src, modelSet, PM_SOURCE_FIT_PSF, 1);
+        ok(rc == false, "pmSourceFitSet() returned FALSE with NULL src->maskObj input parameter");
+        src->maskObj = tmpImg;
+        psFree(src);
+        for (int i = 0 ; i < NUM_MODELS ; i++) {
+            psFree(modelSet->data[i]);
+            modelSet->data[i] = NULL;
+        }
+        psFree(modelSet);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceFitSet() with acceptable input parameters
+    // This is a verly limited test.  It only uses a simple object in the pmSource
+    // parameter and simply tests that pmSourceFitSet() returns teh correct type and mode.
+    // Must add more extensive input types.
+    if (1) {
+        psMemId id = psMemGetId();
+        psArray *modelSet = psArrayAlloc(NUM_MODELS);
+        for (int i = 0 ; i < NUM_MODELS ; i++) {
+            modelSet->data[i] = (psPtr *) pmModelAlloc(i);
+	}
+        pmSource *src = create_pmSource();
+        bool rc = pmSourceFitSet(src, modelSet, PM_SOURCE_FIT_PSF, 1);
+        ok(rc == true, "pmSourceFitSet() returned TRUE with acceptable parameters");
+        ok(src->mode & PM_SOURCE_MODE_FITTED, "pmSourceFitSet() set source->mode |= PM_SOURCE_MODE_FITTED (%d)", src->mode);
+        ok(src->type == PM_SOURCE_TYPE_UNKNOWN, "pmSourceFitSet() set source->type correctly (%d)", src->type);
+
+        psFree(src);
+        for (int i = 0 ; i < NUM_MODELS ; i++) {
+            psFree(modelSet->data[i]);
+            modelSet->data[i] = NULL;
+        }
+        psFree(modelSet);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceIO_PS1_DEV_0.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceIO_PS1_DEV_0.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceIO_PS1_DEV_0.c	(revision 22158)
@@ -0,0 +1,243 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    All functions are tested.
+    XX: These tests read/write a file.  Must choose a more unique name.
+*/
+
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.0001)
+#define NUM_SOURCES		5
+#define FITS_FILENAME  ".tmp00"
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(79);
+
+
+    // ----------------------------------------------------------------------
+    // pmSourcesWrite_PS1_DEV_0() tests
+    // Call pmSourcesWrite_PS1_DEV_0() with NULL psFits input parameter
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(FITS_FILENAME, "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            src->type = PM_SOURCE_TYPE_STAR;
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_PS1_DEV_0(NULL, sources, imageHeader, tableHeader, extname);
+        ok(rc == false, "pmSourcesWrite_PS1_DEV_0() returned FALSE with NULL psFits input parameter");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesWrite_PS1_DEV_0() with NULL pmSource input parameter
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(FITS_FILENAME, "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_PS1_DEV_0(fitsFile, NULL, imageHeader, tableHeader, extname);
+        ok(rc == false, "pmSourcesWrite_PS1_DEV_0() returned FALSE with NULL pmSource input parameter");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesWrite_PS1_DEV_0() with NULL extname input parameter
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(FITS_FILENAME, "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_PS1_DEV_0(fitsFile, sources, imageHeader, tableHeader, NULL);
+        ok(rc == false, "pmSourcesWrite_PS1_DEV_0() returned FALSE with NULL extname input parameter");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourcesRead_PS1_DEV_0() tests
+    // Call pmSourcesRead_PS1_DEV_0() with NULL psFits input parameter
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(FITS_FILENAME, "r");
+        psMetadata *header = psMetadataAlloc();
+        psArray *array = pmSourcesRead_PS1_DEV_0(NULL, header);
+        ok(array == NULL, "pmSourcesRead_PS1_DEV_0() returned NULL with NULL psFits input parameter");
+        psFree(fitsFile);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesRead_PS1_DEV_0() with NULL header input parameter
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(FITS_FILENAME, "r");
+        psMetadata *header = psMetadataAlloc();
+        psArray *array = pmSourcesRead_PS1_DEV_0(fitsFile, NULL);
+        ok(array == NULL, "pmSourcesRead_PS1_DEV_0() returned NULL with NULL header input parameter");
+        psFree(fitsFile);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Call pmSourcesWrite_PS1_DEV_0() with acceptable input parameters
+    #define TEST_BASE_X_POS		10.0
+    #define TEST_BASE_Y_POS		20.0
+    #define TEST_BASE_X_ERR		30.0
+    #define TEST_BASE_Y_ERR		40.0
+    #define TEST_BASE_PSF_MAG	50.0
+    #define TEST_BASE_ERR_MAG	60.0
+    #define TEST_BASE_SKY		70.0
+    #define TEST_BASE_SKY_ERR	80.0
+    #define TEST_BASE_PIX_WEIGHT	90.0
+    #define TEST_BASE_PEAK_FLUX	120.0
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(FITS_FILENAME, "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            // Set even numbered sources to PM_SOURCE_TYPE_STAR
+            pmModel *model = NULL;
+            if (i%2) {
+                src->type = PM_SOURCE_TYPE_STAR;
+                src->modelPSF = pmModelAlloc(1);
+                model = src->modelPSF;
+	    } else {
+                src->type = PM_SOURCE_TYPE_EXTENDED;
+                src->modelConv = pmModelAlloc(1);
+                model = src->modelConv;
+ 	    }
+            for (int p = 0 ; p < model->params->n ; p++) {
+                model->params->data.F32[p] = (float) (i + p);
+                model->dparams->data.F32[p] = (float) (i + p);
+	    }
+            model->params->data.F32[PM_PAR_XPOS] = TEST_BASE_X_POS + (float) i;
+            model->params->data.F32[PM_PAR_YPOS] = TEST_BASE_Y_POS + (float) i;
+            model->dparams->data.F32[PM_PAR_XPOS] = TEST_BASE_X_ERR + (float) i;
+            model->dparams->data.F32[PM_PAR_YPOS] = TEST_BASE_Y_ERR + (float) i;
+            src->psfMag = TEST_BASE_PSF_MAG + (float) i;
+            src->errMag = TEST_BASE_ERR_MAG + (float) i;
+            src->peak->flux = TEST_BASE_PEAK_FLUX + (float) i;
+            src->sky = TEST_BASE_SKY + (float) i;
+            src->skyErr = TEST_BASE_SKY_ERR + (float) i;
+            src->pixWeight = TEST_BASE_PIX_WEIGHT + (float) i;
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_PS1_DEV_0(fitsFile, sources, imageHeader, tableHeader, extname);
+        ok(rc == true, "pmSourcesWrite_PS1_DEV_0() returned TRUE with acceptable input parameters");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesRead_PS1_DEV_0() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(FITS_FILENAME, "r");
+        psMetadata *header = psMetadataAlloc();
+        psArray *array = pmSourcesRead_PS1_DEV_0(fitsFile, header);
+        ok(array != NULL, "pmSourcesRead_PS1_DEV_0() returned non-NULL with acceptable input parameters");
+        skip_start(array == NULL, 1, "Skipping tests because pmSourcesRead_PS1_DEV_0() returned NULL");
+        for (int i = 0 ; i < array->n ; i++) {
+             pmSource *src = (pmSource *) array->data[i];
+             ok(src != NULL && psMemCheckSource(src), "pmSourcesRead_PS1_DEV_0() read source %d correctly", i);
+
+             // XXX: Source code always sets the type to PM_SOURCE_TYPE_STAR.  Is that right?
+             ok(src->type == PM_SOURCE_TYPE_STAR, "pmSourcesRead_PS1_DEV_0() set the source type correctly (is %d, should be %d)",
+                src->type, PM_SOURCE_TYPE_STAR);
+
+             ok(src->sky == (TEST_BASE_SKY + (float) i), "pmSourcesRead_PS1_DEV_0() set src->sky correctly (is %.2f, should be %.2f)",
+                src->sky, (TEST_BASE_SKY + (float) i));
+             ok(src->skyErr == (TEST_BASE_SKY_ERR + (float) i), "pmSourcesRead_PS1_DEV_0() set src->skyErr correctly (is %.2f, should be %.2f)",
+                src->skyErr, (TEST_BASE_SKY_ERR + (float) i));
+             ok(src->pixWeight == (TEST_BASE_PIX_WEIGHT + (float) i), "pmSourcesRead_PS1_DEV_0() set src->pixWeight correctly (is %.2f, should be %.2f)",
+                src->pixWeight, (TEST_BASE_PIX_WEIGHT + (float) i));
+             ok(TEST_FLOATS_EQUAL(src->peak->flux, (TEST_BASE_PEAK_FLUX + (float) i)), "pmSourcesRead_PS1_DEV_0() set src->peak->flux correctly (is %.2f, should be %.2f)",
+                src->peak->flux, (TEST_BASE_PEAK_FLUX + (float) i));
+             ok(src->psfMag == (TEST_BASE_PSF_MAG + (float) i), "pmSourcesRead_PS1_DEV_0() set src->psfMag correctly (is %.2f, should be %.2f)",
+                src->psfMag, (TEST_BASE_PSF_MAG + (float) i));
+             ok(src->errMag == (TEST_BASE_ERR_MAG + (float) i), "pmSourcesRead_PS1_DEV_0() set src->errMag correctly (is %.2f, should be %.2f)",
+                src->errMag, (TEST_BASE_ERR_MAG + (float) i));
+
+             // XXX: Source code always sets src->modelPSF.  Is that right?
+             pmModel *model = src->modelPSF;
+             ok(model != NULL  && psMemCheckModel(model), "pmSourcesRead_PS1_DEV_0() set src->modelPSF correctly");
+             skip_start(model == NULL, 2, "Skipping tests because pmSourcesRead_PS1_DEV_0() did not set src->modelPSF");
+             ok(model->params->data.F32[PM_PAR_XPOS] == (TEST_BASE_X_POS + (float) i),
+               "pmSourcesRead_PS1_DEV_0() set src->model->params->data.F32[PM_PAR_XPOS] correctly (is %.2f, should be %.2f)",
+                model->params->data.F32[PM_PAR_XPOS], (TEST_BASE_X_POS + (float) i));
+             ok(model->params->data.F32[PM_PAR_YPOS] == (TEST_BASE_Y_POS + (float) i),
+               "pmSourcesRead_PS1_DEV_0() set src->model->params->data.F32[PM_PAR_YPOS] correctly (is %.2f, should be %.2f)",
+                model->params->data.F32[PM_PAR_YPOS], (TEST_BASE_Y_POS + (float) i));
+             ok(model->dparams->data.F32[PM_PAR_XPOS] == (TEST_BASE_X_ERR + (float) i),
+               "pmSourcesRead_PS1_DEV_0() set src->model->dparams->data.F32[PM_PAR_XPOS] correctly (is %.2f, should be %.2f)",
+                model->dparams->data.F32[PM_PAR_XPOS], (TEST_BASE_X_ERR + (float) i));
+             ok(model->dparams->data.F32[PM_PAR_YPOS] == (TEST_BASE_Y_ERR + (float) i),
+               "pmSourcesRead_PS1_DEV_0() set src->model->dparams->data.F32[PM_PAR_YPOS] correctly (is %.2f, should be %.2f)",
+                model->dparams->data.F32[PM_PAR_YPOS], (TEST_BASE_Y_ERR + (float) i));
+             skip_end();
+	}
+        skip_end();
+        psFree(fitsFile);
+        psFree(header);
+        psFree(array);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceIO_PS1_DEV_1.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceIO_PS1_DEV_1.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceIO_PS1_DEV_1.c	(revision 22158)
@@ -0,0 +1,309 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    No test for pmSourcesWrite_PS1_DEV_1_XSRC() since there is no associated
+        read function.
+    All other functions are tested.
+    XX: These tests read/write a file.  Must choose a more unique name.
+*/
+
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           (8)
+#define TEST_NUM_COLS           (16)
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.0001)
+#define NUM_SOURCES		5
+#define TABLE_FILENAME	"table.fits"
+const char* tableFilename = "table.fits";
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(79);
+
+
+    // ----------------------------------------------------------------------
+    // pmSourcesWrite_PS1_DEV_1() tests
+    // Call pmSourcesWrite_PS1_DEV_1() with NULL psFits input parameter
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(TABLE_FILENAME, "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            src->type = PM_SOURCE_TYPE_STAR;
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_PS1_DEV_1(NULL, sources, imageHeader, tableHeader, extname, NULL);
+        ok(rc == false, "pmSourcesWrite_PS1_DEV_1() returned FALSE with NULL psFits input parameter");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesWrite_PS1_DEV_1() with NULL pmSource input parameter
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(TABLE_FILENAME, "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_PS1_DEV_1(fitsFile, NULL, imageHeader, tableHeader, extname, NULL);
+        ok(rc == false, "pmSourcesWrite_PS1_DEV_1() returned FALSE with NULL pmSource input parameter");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesWrite_PS1_DEV_1() with NULL extname input parameter
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(TABLE_FILENAME, "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_PS1_DEV_1(fitsFile, sources, imageHeader, tableHeader, NULL, NULL);
+        ok(rc == false, "pmSourcesWrite_PS1_DEV_1() returned FALSE with NULL extname input parameter");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourcesRead_PS1_DEV_1() tests
+    // Call pmSourcesRead_PS1_DEV_1() with NULL psFits input parameter
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(TABLE_FILENAME, "r");
+        psMetadata *header = psMetadataAlloc();
+        psArray *array = pmSourcesRead_PS1_DEV_1(NULL, header);
+        ok(array == NULL, "pmSourcesRead_PS1_DEV_1() returned NULL with NULL psFits input parameter");
+        psFree(fitsFile);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesRead_PS1_DEV_1() with NULL header input parameter
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(TABLE_FILENAME, "r");
+        psMetadata *header = psMetadataAlloc();
+        psArray *array = pmSourcesRead_PS1_DEV_1(fitsFile, NULL);
+        ok(array == NULL, "pmSourcesRead_PS1_DEV_1() returned NULL with NULL header input parameter");
+        psFree(fitsFile);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Call pmSourcesWrite_PS1_DEV_1() with acceptable input parameters
+    #define TEST_BASE_X_POS             10.0
+    #define TEST_BASE_Y_POS             20.0
+    #define TEST_BASE_X_ERR             30.0
+    #define TEST_BASE_Y_ERR             40.0
+    #define TEST_BASE_PSF_MAG		50.0
+    #define TEST_BASE_ERR_MAG		60.0
+    #define TEST_BASE_SKY               500.0
+    #define TEST_BASE_SKY_ERR		80.0
+    #define TEST_BASE_PIX_WEIGHT        90.0
+    #define TEST_BASE_PEAK_FLUX		120.0
+    #define TEST_BASE_PSF_PROB		150.0
+    #define TEST_BASE_CR_N_SIGMA	160.0
+    #define TEST_BASE_EXT_N_SIGMA       170.0   
+    #define TEST_BASE_MODE		1
+
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(TABLE_FILENAME, "w");
+        if (fitsFile == NULL) {
+            diag("ERROR: Could not create 'table' FITS file");
+            return false;
+        }
+
+        if (1) {
+            // make the PHU an image (per FITS standard, it must be)
+            psImage* image = psImageAlloc(16, 16, PS_TYPE_F32);
+            if (!psFitsWriteImage(fitsFile, NULL, image, 1, NULL)) {
+                diag("ERROR: Could not write PHU image");
+                return false;
+            }
+            psFree(image);
+        }
+
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            // Set even numbered sources to PM_SOURCE_TYPE_STAR
+            pmModel *model = NULL;
+            if (i%2) {
+                src->type = PM_SOURCE_TYPE_STAR;
+                src->modelPSF = pmModelAlloc(1);
+                model = src->modelPSF;
+	    } else {
+                src->type = PM_SOURCE_TYPE_EXTENDED;
+                src->modelConv = pmModelAlloc(1);
+                model = src->modelConv;
+	    }
+            for (int p = 0 ; p < model->params->n ; p++) {
+                model->params->data.F32[p] = (float) (i + p);
+                model->dparams->data.F32[p] = (float) (i + p);
+	    }
+
+            model->params->data.F32[PM_PAR_XPOS] = TEST_BASE_X_POS + (float) i;
+            model->params->data.F32[PM_PAR_YPOS] = TEST_BASE_Y_POS + (float) i;
+            model->dparams->data.F32[PM_PAR_XPOS] = TEST_BASE_X_ERR + (float) i;
+            model->dparams->data.F32[PM_PAR_YPOS] = TEST_BASE_Y_ERR + (float) i;
+            src->psfMag = TEST_BASE_PSF_MAG + (float) i;
+            src->errMag = TEST_BASE_ERR_MAG + (float) i;
+            src->peak->flux = TEST_BASE_PEAK_FLUX + (float) i;
+            src->sky = TEST_BASE_SKY + (float) i;
+            src->skyErr = TEST_BASE_SKY_ERR + (float) i;
+            src->pixWeight = TEST_BASE_PIX_WEIGHT + (float) i;
+            sources->data[i] = (psPtr *) src;
+            src->psfMag = TEST_BASE_PSF_MAG + (float) i;
+            src->errMag = TEST_BASE_ERR_MAG + (float) i;
+            src->sky = TEST_BASE_SKY + (float) i;
+            src->skyErr = TEST_BASE_SKY_ERR + (float) i;
+//            src->psfProb = TEST_BASE_PSF_PROB + (float) i;
+            src->crNsigma = TEST_BASE_CR_N_SIGMA + (float) i;
+            src->extNsigma = TEST_BASE_EXT_N_SIGMA + (float) i;
+            src->mode = TEST_BASE_MODE + i;
+            src->peak->SN = (float) (10 - i);
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_PS1_DEV_1(fitsFile, sources, imageHeader, tableHeader, extname, NULL);
+        ok(rc == true, "pmSourcesWrite_PS1_DEV_1() returned TRUE with acceptable input parameters");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesRead_PS1_DEV_1() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(tableFilename, "rw");
+        if (fitsFile == NULL) {
+            diag("ERROR: Could not create 'table' FITS file");
+            return false;
+        }
+
+        // XXX: I'm not exactly sure why, but without this, the psFitsReadTableSize() call
+        // in pmSourcesRead_PS1_DEV_1() fails.  However, Robert also did this in psFits.
+        if (1) {
+            psFitsMoveExtNum(fitsFile, 1, false);
+	}
+
+        // XX: Debugging purposes only.  Trying to duplicate the call to
+        // psFitsTableRead() from DEV_0
+        if (0) {
+            psArray *table = psFitsReadTable(fitsFile);
+            if (table == NULL) {
+                printf("ERROR: table is NULL\n");
+                exit(0);
+	    }
+            for (int i = 0; i < table->n; i++) {
+                psMetadata *row = table->data[i];
+                float sky = psMetadataLookupF32(NULL, row, "SKY");
+                printf("For row %d, the psFitsReadTable() produces a sky of %.2f\n", i, sky);
+	    }
+	}
+
+        psMetadata *header = psMetadataAlloc();
+        psArray *array = pmSourcesRead_PS1_DEV_1(fitsFile, header);
+        ok(array != NULL, "pmSourcesRead_PS1_DEV_1() returned non-NULL with acceptable input parameters");
+        skip_start(array == NULL, 1, "Skipping tests because pmSourcesRead_PS1_DEV_1() returned NULL");
+        for (int i = 0 ; i < array->n ; i++) {
+             pmSource *src = (pmSource *) array->data[i];
+             ok(src != NULL && psMemCheckSource(src), "pmSourcesRead_PS1_DEV_1() read source %d correctly", i);
+
+             // XXX: Source code always sets the type to PM_SOURCE_TYPE_STAR.  Is that right?
+             ok(src->type == PM_SOURCE_TYPE_STAR, "pmSourcesRead_PS1_DEV_1() set the source type correctly (is %d, should be %d)",
+                src->type, PM_SOURCE_TYPE_STAR);
+
+             ok(src->sky == (TEST_BASE_SKY + (float) i), "pmSourcesRead_PS1_DEV_1() set src->sky correctly (is %.2f, should be %.2f)",
+                src->sky, (TEST_BASE_SKY + (float) i));
+             ok(src->skyErr == (TEST_BASE_SKY_ERR + (float) i), "pmSourcesRead_PS1_DEV_1() set src->skyErr correctly (is %.2f, should be %.2f)",
+                src->skyErr, (TEST_BASE_SKY_ERR + (float) i));
+             ok(src->pixWeight == (TEST_BASE_PIX_WEIGHT + (float) i), "pmSourcesRead_PS1_DEV_1() set src->pixWeight correctly (is %.2f, should be %.2f)",
+                src->pixWeight, (TEST_BASE_PIX_WEIGHT + (float) i));
+             ok(TEST_FLOATS_EQUAL(src->peak->flux, (TEST_BASE_PEAK_FLUX + (float) i)), "pmSourcesRead_PS1_DEV_1() set src->peak->flux correctly (is %.2f, should be %.2f)",
+                src->peak->flux, (TEST_BASE_PEAK_FLUX + (float) i));
+             ok(src->psfMag == (TEST_BASE_PSF_MAG + (float) i), "pmSourcesRead_PS1_DEV_1() set src->psfMag correctly (is %.2f, should be %.2f)",
+                src->psfMag, (TEST_BASE_PSF_MAG + (float) i));
+             ok(src->errMag == (TEST_BASE_ERR_MAG + (float) i), "pmSourcesRead_PS1_DEV_1() set src->errMag correctly (is %.2f, should be %.2f)",
+                src->errMag, (TEST_BASE_ERR_MAG + (float) i));
+
+             // XXX: Source code always sets src->modelPSF.  Is that right?
+             pmModel *model = src->modelPSF;
+             ok(model != NULL  && psMemCheckModel(model), "pmSourcesRead_PS1_DEV_1() set src->modelPSF correctly");
+             skip_start(model == NULL, 2, "Skipping tests because pmSourcesRead_PS1_DEV_1() did not set src->modelPSF");
+             ok(model->params->data.F32[PM_PAR_XPOS] == (TEST_BASE_X_POS + (float) i),
+               "pmSourcesRead_PS1_DEV_1() set src->model->params->data.F32[PM_PAR_XPOS] correctly (is %.2f, should be %.2f)",
+                model->params->data.F32[PM_PAR_XPOS], (TEST_BASE_X_POS + (float) i));
+             ok(model->params->data.F32[PM_PAR_YPOS] == (TEST_BASE_Y_POS + (float) i),
+               "pmSourcesRead_PS1_DEV_1() set src->model->params->data.F32[PM_PAR_YPOS] correctly (is %.2f, should be %.2f)",
+                model->params->data.F32[PM_PAR_YPOS], (TEST_BASE_Y_POS + (float) i));
+             ok(model->dparams->data.F32[PM_PAR_XPOS] == (TEST_BASE_X_ERR + (float) i),
+               "pmSourcesRead_PS1_DEV_1() set src->model->dparams->data.F32[PM_PAR_XPOS] correctly (is %.2f, should be %.2f)",
+                model->dparams->data.F32[PM_PAR_XPOS], (TEST_BASE_X_ERR + (float) i));
+             ok(model->dparams->data.F32[PM_PAR_YPOS] == (TEST_BASE_Y_ERR + (float) i),
+               "pmSourcesRead_PS1_DEV_1() set src->model->dparams->data.F32[PM_PAR_YPOS] correctly (is %.2f, should be %.2f)",
+                model->dparams->data.F32[PM_PAR_YPOS], (TEST_BASE_Y_ERR + (float) i));
+             skip_end();
+	}
+        skip_end();
+        psFree(fitsFile);
+        psFree(header);
+        psFree(array);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceIO_SMPDATA.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceIO_SMPDATA.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceIO_SMPDATA.c	(revision 22158)
@@ -0,0 +1,276 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    All functions are tested.
+*/
+
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.0001)
+#define NUM_SOURCES		5
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(69);
+
+
+    // ----------------------------------------------------------------------
+    // pmSourcesWrite_SMPDATA() tests
+    // Call pmSourcesWrite_SMPDATA() with NULL psFits input parameter
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            src->type = PM_SOURCE_TYPE_STAR;
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_SMPDATA(NULL, sources, imageHeader, tableHeader, extname);
+        ok(rc == false, "pmSourcesWrite_SMPDATA() returned FALSE with NULL psFits input parameter");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesWrite_SMPDATA() with NULL pmSource input parameter
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_SMPDATA(fitsFile, NULL, imageHeader, tableHeader, extname);
+        ok(rc == false, "pmSourcesWrite_SMPDATA() returned FALSE with NULL pmSource input parameter");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesWrite_SMPDATA() with NULL extname input parameter
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_SMPDATA(fitsFile, sources, imageHeader, tableHeader, NULL);
+        ok(rc == false, "pmSourcesWrite_SMPDATA() returned FALSE with NULL extname input parameter");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourcesRead_SMPDATA() tests
+    // Call pmSourcesRead_SMPDATA() with NULL psFits input parameter
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "r");
+        psMetadata *header = psMetadataAlloc();
+        psArray *array = pmSourcesRead_SMPDATA(NULL, header);
+        ok(array == NULL, "pmSourcesRead_SMPDATA() returned NULL with NULL psFits input parameter");
+        psFree(fitsFile);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourcesRead_SMPDATA() with NULL header input parameter
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "r");
+        psMetadata *header = psMetadataAlloc();
+        psArray *array = pmSourcesRead_SMPDATA(fitsFile, NULL);
+        ok(array == NULL, "pmSourcesRead_SMPDATA() returned NULL with NULL header input parameter");
+        psFree(fitsFile);
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Call pmSourcesWrite_SMPDATA() with acceptable input parameters
+    #define TEST_BASE_X_POS		10.0
+    #define TEST_BASE_Y_POS		20.0
+    #define TEST_BASE_X_ERR		30.0
+    #define TEST_BASE_Y_ERR		40.0
+    #define TEST_BASE_PSF_MAG		50.0
+    #define TEST_BASE_ERR_MAG		60.0
+    #define TEST_BASE_SKY		70.0
+    #define TEST_BASE_SKY_ERR		80.0
+    #define TEST_BASE_PIX_WEIGHT	90.0
+    #define TEST_BASE_PEAK_FLUX		120.0
+    #define TEST_BASE_EXT_MAG		150.0
+    #define TEST_BASE_AP_MAG		160.0
+    // XXX: The following metadata items are not tested: FWHM_X, FWHM_Y, THETA
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "w");
+        psArray *sources = psArrayAlloc(NUM_SOURCES);
+        for (int i = 0 ; i < sources->n ; i++) {
+            pmSource *src = pmSourceAlloc();
+            src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+            // Set even numbered sources to PM_SOURCE_TYPE_STAR
+            pmModel *model = NULL;
+            if (i%2) {
+                src->type = PM_SOURCE_TYPE_STAR;
+                src->modelPSF = pmModelAlloc(1);
+                model = src->modelPSF;
+	    } else {
+                src->type = PM_SOURCE_TYPE_EXTENDED;
+                src->modelConv = pmModelAlloc(1);
+                model = src->modelConv;
+ 	    }
+            for (int p = 0 ; p < model->params->n ; p++) {
+                model->params->data.F32[p] = (float) (i + p);
+                model->dparams->data.F32[p] = (float) (i + p);
+	    }
+            model->params->data.F32[PM_PAR_XPOS] = TEST_BASE_X_POS + (float) i;
+            model->params->data.F32[PM_PAR_YPOS] = TEST_BASE_Y_POS + (float) i;
+            model->dparams->data.F32[PM_PAR_XPOS] = TEST_BASE_X_ERR + (float) i;
+            model->dparams->data.F32[PM_PAR_YPOS] = TEST_BASE_Y_ERR + (float) i;
+            src->psfMag = TEST_BASE_PSF_MAG + (float) i;
+            src->errMag = TEST_BASE_ERR_MAG + (float) i;
+            src->peak->flux = TEST_BASE_PEAK_FLUX + (float) i;
+            src->sky = TEST_BASE_SKY + (float) i;
+            src->skyErr = TEST_BASE_SKY_ERR + (float) i;
+            src->pixWeight = TEST_BASE_PIX_WEIGHT + (float) i;
+            src->extMag = TEST_BASE_EXT_MAG + (float) i;
+            src->apMag = TEST_BASE_AP_MAG + (float) i;
+            sources->data[i] = (psPtr *) src;
+	}
+        psMetadata *imageHeader = psMetadataAlloc();
+        psMetadata *tableHeader = psMetadataAlloc();
+        psString extname = psStringCopy("ext");
+        bool rc = pmSourcesWrite_SMPDATA(fitsFile, sources, imageHeader, tableHeader, extname);
+        ok(rc == true, "pmSourcesWrite_SMPDATA() returned TRUE with acceptable input parameters");
+        psFree(fitsFile);
+        psFree(sources);
+        psFree(imageHeader);
+        psFree(tableHeader);
+        psFree(extname);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Call pmSourcesRead_SMPDATA() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        psFits* fitsFile = psFitsOpen(".tmp00", "r");
+        float ZERO_POINT = 25.0;
+        psMetadata *header = psMetadataAlloc();
+        psArray *array = pmSourcesRead_SMPDATA(fitsFile, header);
+        ok(array != NULL, "pmSourcesRead_SMPDATA() returned non-NULL with acceptable input parameters");
+        skip_start(array == NULL, 1, "Skipping tests because pmSourcesRead_SMPDATA() returned NULL");
+        for (int i = 0 ; i < array->n ; i++) {
+             pmSource *src = (pmSource *) array->data[i];
+             ok(src != NULL && psMemCheckSource(src), "pmSourcesRead_SMPDATA() read source %d correctly", i);
+
+             // src->model data
+             pmModel *model = src->modelPSF;
+             ok(model != NULL  && psMemCheckModel(model), "pmSourcesRead_SMPDATA() set src->modelPSF correctly");
+             skip_start(model == NULL, 2, "Skipping tests because pmSourcesRead_SMPDATA() did not set src->modelPSF");
+             {
+                 ok(model->params->data.F32[PM_PAR_XPOS] == (TEST_BASE_X_POS + (float) i),
+                   "pmSourcesRead_SMPDATA() set src->model->params->data.F32[PM_PAR_XPOS] correctly (is %.2f, should be %.2f)",
+                    model->params->data.F32[PM_PAR_XPOS], (TEST_BASE_X_POS + (float) i));
+
+                 ok(model->params->data.F32[PM_PAR_YPOS] == (TEST_BASE_Y_POS + (float) i),
+                   "pmSourcesRead_SMPDATA() set src->model->params->data.F32[PM_PAR_YPOS] correctly (is %.2f, should be %.2f)",
+                    model->params->data.F32[PM_PAR_YPOS], (TEST_BASE_Y_POS + (float) i));
+
+                 float tmpSrcSky = TEST_BASE_SKY + (float) i;
+                 float lsky = (tmpSrcSky < 1.0) ? 0.0 : log10(tmpSrcSky);
+                 float tmpF = pow(10.0, lsky);
+                 ok(model->params->data.F32[PM_PAR_SKY] == tmpF,
+                   "pmSourcesRead_SMPDATA() set src->model->params->data.F32[PM_PAR_SKY] correctly (is %.2f, should be %.2f)",
+                    model->params->data.F32[PM_PAR_SKY], tmpF);
+	     }
+             ok(src->psfMag == (TEST_BASE_PSF_MAG + (float) i), "pmSourcesRead_SMPDATA() set src->psfMag correctly (is %.2f, should be %.2f)",
+                src->psfMag, (TEST_BASE_PSF_MAG + (float) i));
+             float tmpF =  0.001 * PS_MIN(999, (1000 * (TEST_BASE_ERR_MAG + (float) i)));
+             ok(src->errMag == tmpF, "pmSourcesRead_SMPDATA() set src->errMag correctly (is %.2f, should be %.2f)",
+                src->errMag, tmpF);
+             tmpF = PS_MIN(99.0, (TEST_BASE_EXT_MAG + ZERO_POINT)) - ZERO_POINT;
+             ok(src->extMag == tmpF, "pmSourcesRead_SMPDATA() set src->extMag correctly (is %.2f, should be %.2f)",
+                src->extMag, tmpF);
+             tmpF = PS_MIN(99.0, (TEST_BASE_AP_MAG + ZERO_POINT)) - ZERO_POINT;
+             ok(src->apMag == tmpF, "pmSourcesRead_SMPDATA() set src->apMag correctly (is %.2f, should be %.2f)",
+                src->apMag, tmpF);
+             if (i%2) {
+                 ok(src->type == PM_SOURCE_TYPE_STAR, "pmSourcesRead_SMPDATA() set the source type correctly (is %d, should be %d)",
+                    src->type, PM_SOURCE_TYPE_STAR);
+	     } else {
+                 ok(src->type == PM_SOURCE_TYPE_EXTENDED, "pmSourcesRead_SMPDATA() set the source type correctly (is %d, should be %d)",
+                    src->type, PM_SOURCE_TYPE_EXTENDED);
+	     }
+             psU8 tmpU8 = (psU8) PS_MIN(255, PS_MAX(0, (255*(TEST_BASE_PIX_WEIGHT + (float) i))));
+             tmpF = (psF32) (tmpU8 / 255.0);
+             ok(src->pixWeight == tmpF, "pmSourcesRead_SMPDATA() set src->pixWeight correctly (is %.2f, should be %.2f)",
+                src->pixWeight, tmpF);
+
+             skip_end();
+
+             if (0) { // OLD
+                 // XXX: Source code always sets the type to PM_SOURCE_TYPE_STAR.  Is that right?
+                 ok(src->sky == (TEST_BASE_SKY + (float) i), "pmSourcesRead_SMPDATA() set src->sky correctly (is %.2f, should be %.2f)",
+                    src->sky, (TEST_BASE_SKY + (float) i));
+                 if (0) {
+                     ok(src->pixWeight == (TEST_BASE_PIX_WEIGHT + (float) i), "pmSourcesRead_SMPDATA() set src->pixWeight correctly (is %.2f, should be %.2f)",
+                        src->pixWeight, (TEST_BASE_PIX_WEIGHT + (float) i));
+		 }
+                 ok(TEST_FLOATS_EQUAL(src->peak->flux, 0.0), "pmSourcesRead_SMPDATA() set src->peak->flux correctly (is %.2f, should be %.2f)",
+                    src->peak->flux, 0.0);
+                 // XXX: Source code always sets src->modelPSF.  Is that right?
+                 ok(model->dparams->data.F32[PM_PAR_XPOS] == (TEST_BASE_X_ERR + (float) i),
+                   "pmSourcesRead_SMPDATA() set src->model->dparams->data.F32[PM_PAR_XPOS] correctly (is %.2f, should be %.2f)",
+                    model->dparams->data.F32[PM_PAR_XPOS], (TEST_BASE_X_ERR + (float) i));
+                 ok(model->dparams->data.F32[PM_PAR_YPOS] == (TEST_BASE_Y_ERR + (float) i),
+                   "pmSourcesRead_SMPDATA() set src->model->dparams->data.F32[PM_PAR_YPOS] correctly (is %.2f, should be %.2f)",
+                    model->dparams->data.F32[PM_PAR_YPOS], (TEST_BASE_Y_ERR + (float) i));
+	     }
+	}
+        skip_end();
+        psFree(fitsFile);
+        psFree(header);
+        psFree(array);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourcePhotometry.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourcePhotometry.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourcePhotometry.c	(revision 22158)
@@ -0,0 +1,167 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "tap.h"
+#include "pstap.h"
+
+bool pmSourcePhotometry_TestOffsets (double radius, double sigma, double fitMag, double apMag, double err1, double err2);
+
+int main (void)
+{
+
+    pmModelGroupInit ();
+
+    plan_tests(240);
+
+    diag("pmSourcePhotometry tests");
+
+    // test consistency of interpolated photometry for a range of apertures (for a fixed PSF sigma)
+    pmSourcePhotometry_TestOffsets (15.0, 2.0, -10.3759, -10.3759, +0.0000, +0.0000);
+    pmSourcePhotometry_TestOffsets (10.0, 2.0, -10.3759, -10.3759, +0.0000, +0.0000);
+    pmSourcePhotometry_TestOffsets ( 8.0, 2.0, -10.3759, -10.3759, +0.0000, +0.0000);
+    pmSourcePhotometry_TestOffsets ( 7.0, 2.0, -10.3759, -10.3759, +0.0000, +0.0001);
+    pmSourcePhotometry_TestOffsets ( 6.0, 2.0, -10.3759, -10.3758, +0.0001, +0.0004);
+    pmSourcePhotometry_TestOffsets ( 5.0, 2.0, -10.3759, -10.3733, +0.0003, +0.0011);
+    pmSourcePhotometry_TestOffsets ( 4.0, 2.0, -10.3759, -10.3520, +0.0006, +0.0018);
+    pmSourcePhotometry_TestOffsets ( 3.0, 2.0, -10.3759, -10.2626, +0.0001, +0.0002);
+    pmSourcePhotometry_TestOffsets ( 2.0, 2.0, -10.3759,  -9.7729, -0.0027, -0.0089);
+    pmSourcePhotometry_TestOffsets ( 1.0, 2.0, -10.3759,  -8.8689, -0.0051, -0.0161);
+
+    // test consistency of interpolated photometry for a range of apertures (for a fixed PSF sigma)
+    pmSourcePhotometry_TestOffsets (15.0, 1.5, -10.3759, -10.3759, +0.0000, +0.0000);
+    pmSourcePhotometry_TestOffsets (10.0, 1.5, -10.3759, -10.3759, +0.0000, +0.0000);
+    pmSourcePhotometry_TestOffsets ( 8.0, 1.5, -10.3759, -10.3759, +0.0000, +0.0000);
+    pmSourcePhotometry_TestOffsets ( 7.0, 1.5, -10.3759, -10.3759, +0.0000, +0.0001);
+    pmSourcePhotometry_TestOffsets ( 6.0, 1.5, -10.3759, -10.3758, +0.0001, +0.0004);
+    pmSourcePhotometry_TestOffsets ( 5.0, 1.5, -10.3759, -10.3733, +0.0003, +0.0011);
+    pmSourcePhotometry_TestOffsets ( 4.0, 1.5, -10.3759, -10.3520, +0.0006, +0.0018);
+    pmSourcePhotometry_TestOffsets ( 3.0, 1.5, -10.3759, -10.2626, +0.0001, +0.0002);
+    pmSourcePhotometry_TestOffsets ( 2.0, 1.5, -10.3759,  -9.7729, -0.0027, -0.0089);
+    pmSourcePhotometry_TestOffsets ( 1.0, 1.5, -10.3759,  -8.8689, -0.0051, -0.0161);
+
+    // test consistency of interpolated photometry for a range of apertures (for a fixed PSF sigma)
+    pmSourcePhotometry_TestOffsets (15.0, 1.0,  -9.4955,  -9.4955, +0.0000, +0.0000);
+    pmSourcePhotometry_TestOffsets (10.0, 1.0,  -9.4955,  -9.4955, +0.0000, +0.0000);
+    pmSourcePhotometry_TestOffsets ( 8.0, 1.0,  -9.4955,  -9.4955, +0.0000, +0.0000);
+    pmSourcePhotometry_TestOffsets ( 7.0, 1.0,  -9.4955,  -9.4955, +0.0000, +0.0000);
+    pmSourcePhotometry_TestOffsets ( 6.0, 1.0,  -9.4955,  -9.4955, +0.0000, +0.0001);
+    pmSourcePhotometry_TestOffsets ( 5.0, 1.0,  -9.4955,  -9.4955, +0.0001, +0.0002);
+    pmSourcePhotometry_TestOffsets ( 4.0, 1.0,  -9.4955,  -9.4968, +0.0006, +0.0022);
+    pmSourcePhotometry_TestOffsets ( 3.0, 1.0,  -9.4955,  -9.4945, +0.0021, +0.0068);
+    pmSourcePhotometry_TestOffsets ( 2.0, 1.0,  -9.4955,  -9.3323, -0.0034, -0.0118);
+    pmSourcePhotometry_TestOffsets ( 1.0, 1.0,  -9.4955,  -8.6844, -0.0141, -0.0440);
+
+    return exit_status();
+}
+
+bool pmSourcePhotometry_TestOffsets (double radius, double sigma, double fitMag, double apMag, double err1, double err2)
+{
+    psMemId id = psMemGetId();
+
+    diag("pmSourcePhotometry test offsets for radius %f", radius);
+
+    // generate a simple readout
+    pmReadout *readout = pmReadoutAlloc (NULL);
+    skip_start(readout == NULL, 0, "Skipping tests because pmReadoutAlloc failed");
+
+    readout->image = psImageAlloc (64, 64, PS_TYPE_F32);
+    readout->mask  = psImageAlloc (64, 64, PS_TYPE_U8);
+
+    // create an empty reference image
+    psImageInit (readout->image, 0.0);
+    psImageInit (readout->mask, 0);
+
+    // generate a simple psf
+    pmPSF *psf = pmPSFBuildSimple ("PS_MODEL_GAUSS", sigma, sigma, 0.0);
+    // psf->growth = pmGrowthCurveAlloc (2.0, 100.0, 15.0);
+    // pmGrowthCurveGenerate (readout, psf, false);
+
+    // create a source
+    pmSource *source = pmSourceAlloc ();
+    source->pixels = psMemIncrRefCounter (readout->image);
+    source->mask   = psMemIncrRefCounter (readout->mask);
+    source->type   = PM_SOURCE_TYPE_STAR;
+    source->mode   = PM_SOURCE_MODE_SUBTRACTED;
+
+    // create template model and measure apMag at fractional offsets
+    pmModel *modelRef = pmModelAlloc(psf->type);
+    modelRef->params->data.F32[PM_PAR_SKY] = 0;
+    modelRef->params->data.F32[PM_PAR_I0] = 1000;
+    modelRef->params->data.F32[PM_PAR_XPOS] = 32.5;
+    modelRef->params->data.F32[PM_PAR_YPOS] = 32.5;
+
+    // create modelPSF from this model
+    source->modelPSF = pmModelFromPSF (modelRef, psf);
+    source->modelPSF->dparams->data.F32[PM_PAR_I0] = 1;
+    source->modelPSF->radiusFit = radius;
+
+    // measure photometry for centered source (fractional pix : 0.5,0.5)
+    // pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_GROWTH | PM_SOURCE_PHOT_INTERP);
+    pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_INTERP);
+    ok_float_tol(source->psfMag, fitMag, 0.0002, "source fitMag is %f", source->psfMag);
+    ok_float_tol(source->apMag,  apMag, 0.0002, "source apMag is %f", source->apMag);
+    ok_float(source->errMag,   0.001, "source errMag is %f", source->errMag);
+    float refMag = source->apMag;
+
+    // these use an offset of 0.2,0.2
+    // measure photometry for a sub-pixel offset position
+    source->modelPSF->params->data.F32[PM_PAR_XPOS] = 32.3;
+    source->modelPSF->params->data.F32[PM_PAR_YPOS] = 32.3;
+    pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_INTERP);
+    ok_float_tol(refMag - source->apMag,  err1, 0.0002, "offset error is %f", refMag - source->apMag);
+
+    // measure photometry for a sub-pixel offset position
+    source->modelPSF->params->data.F32[PM_PAR_XPOS] = 32.7;
+    source->modelPSF->params->data.F32[PM_PAR_YPOS] = 32.3;
+    pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_INTERP);
+    ok_float_tol(refMag - source->apMag,  err1, 0.0002, "offset error is %f", refMag - source->apMag);
+
+    // measure photometry for a sub-pixel offset position
+    source->modelPSF->params->data.F32[PM_PAR_XPOS] = 32.3;
+    source->modelPSF->params->data.F32[PM_PAR_YPOS] = 32.7;
+    pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_INTERP);
+    ok_float_tol(refMag - source->apMag,  err1, 0.0002, "offset error is %f", refMag - source->apMag);
+
+    // measure photometry for a sub-pixel offset position
+    source->modelPSF->params->data.F32[PM_PAR_XPOS] = 32.7;
+    source->modelPSF->params->data.F32[PM_PAR_YPOS] = 32.7;
+    pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_INTERP);
+    ok_float_tol(refMag - source->apMag,  err1, 0.0002, "offset error is %f", refMag - source->apMag);
+
+    // these use an offset of 0.4,0.4
+    // measure photometry for a sub-pixel offset position
+    source->modelPSF->params->data.F32[PM_PAR_XPOS] = 32.1;
+    source->modelPSF->params->data.F32[PM_PAR_YPOS] = 32.1;
+    pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_INTERP);
+    ok_float_tol(refMag - source->apMag,  err2, 0.0002, "offset error is %f", refMag - source->apMag);
+
+    // measure photometry for a sub-pixel offset position
+    source->modelPSF->params->data.F32[PM_PAR_XPOS] = 32.9;
+    source->modelPSF->params->data.F32[PM_PAR_YPOS] = 32.1;
+    pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_INTERP);
+    ok_float_tol(refMag - source->apMag,  err2, 0.0002, "offset error is %f", refMag - source->apMag);
+
+    // measure photometry for a sub-pixel offset position
+    source->modelPSF->params->data.F32[PM_PAR_XPOS] = 32.1;
+    source->modelPSF->params->data.F32[PM_PAR_YPOS] = 32.9;
+    pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_INTERP);
+    ok_float_tol(refMag - source->apMag,  err2, 0.0002, "offset error is %f", refMag - source->apMag);
+
+    // measure photometry for a sub-pixel offset position
+    source->modelPSF->params->data.F32[PM_PAR_XPOS] = 32.9;
+    source->modelPSF->params->data.F32[PM_PAR_YPOS] = 32.9;
+    pmSourceMagnitudes (source, psf, PM_SOURCE_PHOT_INTERP);
+    ok_float_tol(refMag - source->apMag,  err2, 0.0002, "offset error is %f", refMag - source->apMag);
+
+    psFree (source);
+    psFree (modelRef);
+    psFree (psf);
+    psFree (readout);
+
+    skip_end();
+
+    ok(!psMemCheckLeaks (id, NULL, stdout, false), "no memory leaks");
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceSky.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceSky.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceSky.c	(revision 22158)
@@ -0,0 +1,267 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    All functions are tested.
+        pmSourceLocalSky(): needs more thorough testing with acceptable input params.
+        pmSourceLocalSkyVariance(): needs more thorough testing with acceptable input params.
+*/
+
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           (8)
+#define TEST_NUM_COLS           (16)
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.0001)
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(26);
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceLocalSky() tests
+    // Call pmSourceLocalSky() with NULL pmSource input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i =0 ; i < src->pixels->numRows ; i++) {
+            for (int j = 0 ; j < src->pixels->numCols ; j++) {
+                src->pixels->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSky(NULL, PS_STAT_SAMPLE_MEAN, 10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSky() returned FALSE with NULL pmSource input parameter");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceLocalSky() with NULL pmSource->pixels input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSky(src, PS_STAT_SAMPLE_MEAN, 10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSky() returned FALSE with NULL pmSource->pixels input parameter");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceLocalSky() with NULL pmSource->peak input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i =0 ; i < src->pixels->numRows ; i++) {
+            for (int j = 0 ; j < src->pixels->numCols ; j++) {
+                src->pixels->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        bool rc = pmSourceLocalSky(src, PS_STAT_SAMPLE_MEAN, 10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSky() returned FALSE with NULL pmSource->peak input parameter");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceLocalSky() with NULL pmSource->maskObj input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i =0 ; i < src->pixels->numRows ; i++) {
+            for (int j = 0 ; j < src->pixels->numCols ; j++) {
+                src->pixels->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSky(src, PS_STAT_SAMPLE_MEAN, -10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSky() returned FALSE with NULL pmSource->maskObj input parameter");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceLocalSky() with negative input radius
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i =0 ; i < src->pixels->numRows ; i++) {
+            for (int j = 0 ; j < src->pixels->numCols ; j++) {
+                src->pixels->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSky(src, PS_STAT_SAMPLE_MEAN, -10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSky() returned FALSE with negative input radius");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    
+    // Call pmSourceLocalSky() with acceptable input parameters
+    // XX: Future Improvements:
+    //     Test more PS_STATS types
+    //     Test more psRegion values (region bigger than image, 0 region, etc.)
+    //     Test mask values
+    //
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->pixels = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        psF32 mean = 0.0;
+        for (int i = 0 ; i < src->pixels->numRows ; i++) {
+            for (int j = 0 ; j < src->pixels->numCols ; j++) {
+                src->pixels->data.F32[i][j] = (float) (i + j);
+                mean+= (float) (i + j);
+                src->maskObj->data.U8[i][j] = 0;
+	    }
+	}
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSky(src, PS_STAT_SAMPLE_MEAN, 10.0, 0, 0);
+        ok(rc == true, "pmSourceLocalSky() returned TRUE with acceptable input parameters");
+        psF32 actualMean =  mean / (int) (TEST_NUM_ROWS * TEST_NUM_COLS);
+        psF32 testMean = src->moments->Sky;
+        ok(TEST_FLOATS_EQUAL(actualMean, testMean), "pmSourceLocalSky() calculated the mean correctly");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceLocalSkyVariance() tests
+    // Call pmSourceLocalSkyVariance() with NULL pmSource input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i =0 ; i < src->weight->numRows ; i++) {
+            for (int j = 0 ; j < src->weight->numCols ; j++) {
+                src->weight->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSkyVariance(NULL, PS_STAT_SAMPLE_MEAN, 10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSkyVariance() returned FALSE with NULL pmSource input parameter");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceLocalSkyVariance() with NULL pmSource->weight input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSkyVariance(src, PS_STAT_SAMPLE_MEAN, 10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSkyVariance() returned FALSE with NULL pmSource->weight input parameter");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceLocalSkyVariance() with NULL pmSource->maskObj input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i =0 ; i < src->weight->numRows ; i++) {
+            for (int j = 0 ; j < src->weight->numCols ; j++) {
+                src->weight->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSkyVariance(src, PS_STAT_SAMPLE_MEAN, -10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSkyVariance() returned FALSE with NULL pmSource->maskObj input parameter");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceLocalSkyVariance() with NULL pmSource->peak input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i =0 ; i < src->weight->numRows ; i++) {
+            for (int j = 0 ; j < src->weight->numCols ; j++) {
+                src->weight->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        bool rc = pmSourceLocalSkyVariance(src, PS_STAT_SAMPLE_MEAN, 10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSkyVariance() returned FALSE with NULL pmSource->peak input parameter");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceLocalSkyVariance() with negative input radius
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        for (int i =0 ; i < src->weight->numRows ; i++) {
+            for (int j = 0 ; j < src->weight->numCols ; j++) {
+                src->weight->data.F32[i][j] = (float) (i + j);
+	    }
+	}
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSkyVariance(src, PS_STAT_SAMPLE_MEAN, -10.0, 1, 2);
+        ok(rc == false, "pmSourceLocalSkyVariance() returned FALSE with negative input radius");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceLocalSkyVariance() with acceptable input parameters
+    // XX: Future Improvements:
+    //     Test more PS_STATS types
+    //     Test more psRegion values (region bigger than image, 0 region, etc.)
+    //     Test mask values
+    //
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        src->maskObj = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        psF32 mean = 0.0;
+        for (int i = 0 ; i < src->weight->numRows ; i++) {
+            for (int j = 0 ; j < src->weight->numCols ; j++) {
+                src->weight->data.F32[i][j] = (float) (i + j);
+                mean+= (float) (i + j);
+                src->maskObj->data.U8[i][j] = 0;
+	    }
+	}
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        bool rc = pmSourceLocalSkyVariance(src, PS_STAT_SAMPLE_MEAN, 10.0, 0, 0);
+        ok(rc == true, "pmSourceLocalSkyVariance() returned TRUE with acceptable input parameters");
+        psF32 actualMean =  mean / (int) (TEST_NUM_ROWS * TEST_NUM_COLS);
+        psF32 testMean = src->moments->dSky;
+        ok(TEST_FLOATS_EQUAL(actualMean, testMean), "pmSourceLocalSky() calculated the mean correctly");
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceUtils.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceUtils.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmSourceUtils.c	(revision 22158)
@@ -0,0 +1,272 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS
+    All functions are tested.
+       pmSourceFromModel(): Must verify the pmSourceDefinePixels() set the
+           values correctly.
+*/
+
+#define MISC_NUM                32
+#define MISC_NAME              "META00"
+#define NUM_BIAS_DATA           10
+#define TEST_NUM_ROWS           (8)
+#define TEST_NUM_COLS           (16)
+#define VERBOSE                 0
+#define ERR_TRACE_LEVEL         0
+#define TEST_FLOATS_EQUAL(X, Y) (abs((X) - (Y)) < 0.0001)
+#define NUM_SOURCES		100
+
+#define CELL_ALLOC_NAME        "CellName"
+#define NUM_READOUTS            3
+#define NUM_CELLS               10
+#define NUM_HDUS                5
+#define BASE_IMAGE              10
+#define BASE_MASK               40
+#define BASE_WEIGHT             70
+
+
+/******************************************************************************
+generateSimpleReadout(): This function generates a pmReadout data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmReadout *generateSimpleReadout(pmCell *cell)
+{
+    pmReadout *readout = pmReadoutAlloc(cell);
+    readout->image = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    readout->mask = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_U8);
+    readout->weight = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < NUM_BIAS_DATA ; i++) {
+        psImage *tmpImage = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(tmpImage, (double) i);
+        psListAdd(readout->bias, PS_LIST_HEAD, tmpImage);
+        psFree(tmpImage);
+    }
+    psMetadataAddS32(readout->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    return(readout);
+}
+
+/******************************************************************************
+generateSimpleCell(): This function generates a pmCell data structure and then
+populates its members with real data.
+ *****************************************************************************/
+pmCell *generateSimpleCell(pmChip *chip)
+{
+    pmCell *cell = pmCellAlloc(chip, CELL_ALLOC_NAME);
+
+    psMetadataAddS32(cell->analysis, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psMetadataAddS32(cell->concepts, PS_LIST_HEAD, MISC_NAME, 0, NULL, MISC_NUM);
+    psArrayRealloc(cell->readouts, NUM_READOUTS);
+    cell->hdu = pmHDUAlloc("cellExtName");
+    for (int i = 0 ; i < NUM_READOUTS ; i++) {
+        cell->readouts->data[i] = generateSimpleReadout(cell);
+    }
+
+    // First try to read data from ../dataFiles, then try dataFiles.
+    bool rc = pmConfigFileRead(&cell->hdu->format, "../dataFiles/camera0/format0.config", "Camera format 0");
+    if (!rc) {
+        rc = pmConfigFileRead(&cell->hdu->format, "dataFiles/camera0/format0.config", "Camera format 0");
+        if (!rc) {
+            diag("pmConfigFileRead() was unsuccessful (from generateSimpleCell())");
+	}
+    }
+
+    cell->hdu->images = psArrayAlloc(NUM_HDUS);
+    cell->hdu->masks = psArrayAlloc(NUM_HDUS);
+    cell->hdu->weights = psArrayAlloc(NUM_HDUS);
+    for (int k = 0 ; k < NUM_HDUS ; k++) {
+        cell->hdu->images->data[k]  = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        cell->hdu->masks->data[k]   = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_MASK);
+        cell->hdu->weights->data[k] = psImageAlloc(TEST_NUM_COLS, TEST_NUM_ROWS, PS_TYPE_F32);
+        psImageInit(cell->hdu->images->data[k], (float) (BASE_IMAGE+k));
+        psImageInit(cell->hdu->masks->data[k], (psU8) (BASE_MASK+k));
+        psImageInit(cell->hdu->weights->data[k], (float) (BASE_WEIGHT+k));
+    }
+
+    psRegion *region = psRegionAlloc(0.0, 0.0, 0.0, 0.0);
+    // You shouldn't have to remove the key from the metadata.  Find out how to simply change the key value.
+    psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC");
+    psMetadataAddPtr(cell->concepts, PS_LIST_TAIL|PS_META_REPLACE, "CELL.TRIMSEC", PS_DATA_REGION, "I am a region", region);
+    psFree(region);
+    return(cell);
+}
+
+void myFreeCell(pmCell *cell)
+{
+    for (int k = 0 ; k < cell->readouts->n ; k++) {
+        psFree(cell->readouts->data[k]);
+    }
+    psFree(cell);
+}
+
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    psTraceSetLevel("psModules.objects", 0);
+    plan_tests(23);
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceModelGuess() tests
+    // Call pmSourceModelGuess() with NULL pmSource input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        src->moments = pmMomentsAlloc();
+        pmModelType type = pmModelClassGetType ("PS_MODEL_GAUSS");
+        pmModel *model = pmSourceModelGuess(NULL, type);
+        ok(model == NULL, "pmSourceModelGuess() returned NULL with NULL pmSource input parameter");
+        psFree(src);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceModelGuess() with NULL pmSource->peak input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->moments = pmMomentsAlloc();
+        pmModelType type = pmModelClassGetType ("PS_MODEL_GAUSS");
+        pmModel *model = pmSourceModelGuess(NULL, type);
+        ok(model == NULL, "pmSourceModelGuess() returned NULL with NULL pmSource->peak input parameter");
+        psFree(src);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceModelGuess() with NULL pmSource->moments input parameter
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        pmModelType type = pmModelClassGetType ("PS_MODEL_GAUSS");
+        pmModel *model = pmSourceModelGuess(NULL, type);
+        ok(model == NULL, "pmSourceModelGuess() returned NULL with NULL pmSource->moments input parameter");
+        psFree(src);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // pmModel *pmSourceModelGuess(pmSource *source, pmModelType modelType)
+    // Call pmSourceModelGuess() with acceptable input parameters
+    // We only test a single model (PS_MODEL_GAUSS), but since this function is mostly
+    // a wrapper to the model functions, that will suffice.
+    {
+        psMemId id = psMemGetId();
+        pmSource *src = pmSourceAlloc();
+        src->peak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+        src->moments = pmMomentsAlloc();
+
+        src->moments->Sx = 1.0;
+        src->moments->y = 2.0;
+        src->moments->Sxy = 3.0;
+        src->moments->Sky = 4.0;
+        src->moments->Peak = 5.0;
+        src->moments->x = 6.0;
+        src->moments->y = 7.0;
+
+        pmModelType type = pmModelClassGetType("PS_MODEL_GAUSS");
+        pmModel *testModel = pmModelAlloc(type);
+        testModel->modelGuess(testModel, src);
+        pmModel *model = pmSourceModelGuess(src, type);
+        ok(model != NULL, "pmSourceModelGuess() returned non-NULL with acceptable input parameters");
+        psF32 *PAR  = model->params->data.F32;
+        psEllipseMoments emoments;
+        emoments.x2 = src->moments->Sx;
+        emoments.y2 = src->moments->Sy;
+        emoments.xy = src->moments->Sxy;
+        // force the axis ratio to be < 20.0
+        psEllipseAxes axes = psEllipseMomentsToAxes (emoments, 20.0);
+        psEllipseShape shape = psEllipseAxesToShape (axes);
+        ok(TEST_FLOATS_EQUAL(PAR[PM_PAR_SKY], src->moments->Sky), "pmSourceModelGuess() returned set model->params[PM_PAR_SKY] correctly");
+        ok(TEST_FLOATS_EQUAL(PAR[PM_PAR_I0], src->moments->Peak - src->moments->Sky), "pmSourceModelGuess() returned set model->params[PM_PAR_IO] correctly");
+        ok(TEST_FLOATS_EQUAL(PAR[PM_PAR_XPOS], src->moments->x), "pmSourceModelGuess() returned set model->params[PM_PAR_XPOS] correctly");
+        ok(TEST_FLOATS_EQUAL(PAR[PM_PAR_YPOS], src->moments->y), "pmSourceModelGuess() returned set model->params[PM_PAR_YPOS] correctly");
+        ok(TEST_FLOATS_EQUAL(PAR[PM_PAR_SXX], PS_MAX(0.5, M_SQRT2*shape.sx)), "pmSourceModelGuess() returned set model->params[PM_PAR_SXX] correctly");
+        ok(TEST_FLOATS_EQUAL(PAR[PM_PAR_SYY], PS_MAX(0.5, M_SQRT2*shape.sy)), "pmSourceModelGuess() returned set model->params[PM_PAR_SYY] correctly");
+        ok(TEST_FLOATS_EQUAL(PAR[PM_PAR_SXY], shape.sxy), "pmSourceModelGuess() returned set model->params[PM_PAR_SXY] correctly");
+        psFree(src);
+        psFree(testModel);
+        psFree(model);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ----------------------------------------------------------------------
+    // pmSourceModelGuess() tests
+    // Call pmSourceFromModel() with NULL pmModel input parameter
+    {
+        psMemId id = psMemGetId();
+        pmModelType type = pmModelClassGetType ("PS_MODEL_GAUSS");
+        pmModel *model = pmModelAlloc(type);
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *readout = cell->readouts->data[0];
+        pmSource *src = pmSourceFromModel(NULL, readout, 10.0, PM_SOURCE_TYPE_STAR);
+        ok(src == NULL, "pmSourceFromModel() returned NULL with NULL pmModel input parameter");
+        psFree(model);
+        psFree(src);
+        myFreeCell(cell);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceFromModel() with NULL pmReadout input parameter
+    {
+        psMemId id = psMemGetId();
+
+        pmModelType type = pmModelClassGetType ("PS_MODEL_GAUSS");
+        pmModel *model = pmModelAlloc(type);
+        pmCell *cell = generateSimpleCell(NULL);
+        pmSource *src = pmSourceFromModel(model, NULL, 10.0, PM_SOURCE_TYPE_STAR);
+        ok(src == NULL, "pmSourceFromModel() returned NULL with NULL pmReadout input parameter");
+        psFree(model);
+        psFree(src);
+        myFreeCell(cell);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmSourceFromModel() with acceptable input parameters
+    // XXX: Must verify the pmSourceDefinePixels() set the values correctly.
+    {
+        psMemId id = psMemGetId();
+
+        pmModel *model = pmModelAlloc(pmModelClassGetType("PS_MODEL_GAUSS"));
+        float Io    = model->params->data.F32[PM_PAR_I0] = 2.0;
+        float xChip = model->params->data.F32[PM_PAR_XPOS] = 3.0;
+        float yChip = model->params->data.F32[PM_PAR_YPOS] = 5.0;
+        pmCell *cell = generateSimpleCell(NULL);
+        pmReadout *readout = cell->readouts->data[0];
+        pmSource *src = pmSourceFromModel(model, readout, 10.0, PM_SOURCE_TYPE_STAR);
+        ok(src != NULL, "pmSourceFromModel() returned non-NULL with acceptable input parameters");
+        ok(src->modelPSF == model, "pmSourceFromModel() set pmSource->modelPSF correctly");
+
+        pmPeak *tmpPeak = pmPeakAlloc (xChip, yChip, Io, PM_PEAK_LONE);
+        ok(src->peak->x == xChip, "pmSourceFromModel() set pmSource->peak->x correctly (%.2f %.2f)", src->peak->x, xChip);
+
+        psFree(model);
+        // XXX: We get psMemory aborts if the following is not done.
+        // There is probably an issue with psMemIncrRefCounter() in pmSourceUtils.c
+
+        src->modelPSF = NULL;
+        src->modelEXT = NULL;
+        psFree(src);
+        psFree(tmpPeak);
+        myFreeCell(cell);
+        pmModelClassCleanup();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmTrend2D.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmTrend2D.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tap_pmTrend2D.c	(revision 22158)
@@ -0,0 +1,504 @@
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "tap.h"
+#include "pstap.h"
+/* STATUS:
+    All functions are tested.
+        pmTrend2DFit(): Must test the PM_TREND_MAP case.
+*/
+
+#define NUM_ROWS 8
+#define NUM_COLS 16
+#define ERR_TRACE_LEVEL 0
+#define TEST_FLOATS_EQUAL(X, Y) (abs(X - Y) < 0.01)
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    psTraceSetLevel("err", ERR_TRACE_LEVEL);
+    plan_tests(91);
+
+    // ------------------------------------------------------------------------
+    // Test pmTrend2DAlloc()
+    // Call pmTrend2DAlloc() with NULL psImage input parameter (PM_TREND_MAP)
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        pmTrend2D *trend = pmTrend2DAlloc(PM_TREND_MAP, NULL, 2, 2, stats);
+        ok(trend == NULL, "pmTrend2DAlloc() returned NULL with NULL psImage input parameter");
+        psFree(img);
+        psFree(stats);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DAlloc() with NULL psImage input parameter (PM_TREND_POLY_ORD)
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        pmTrend2D *trend = pmTrend2DAlloc(PM_TREND_POLY_ORD, NULL, 2, 2, stats);
+        ok(trend != NULL, "pmTrend2DAlloc() returned NULL with NULL psImage input parameter");
+        psFree(img);
+        psFree(stats);
+        psFree(trend);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DAlloc() with NULL psStats input parameter
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        pmTrend2D *trend = pmTrend2DAlloc(PM_TREND_POLY_ORD, img, 2, 2, NULL);
+        ok(trend == NULL, "pmTrend2DAlloc() returned NULL with NULL psStats input parameter");
+        psFree(img);
+        psFree(stats);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DAlloc() with unallowed pmTrend2DMode
+    // XXX: We skip this test because pmTrend2DAlloc() aborts.
+    if (0) {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        pmTrend2D *trend = pmTrend2DAlloc(999, img, 2, 2, stats);
+        ok(trend == NULL, "pmTrend2DAlloc() returned NULL with unallowed pmTrend2DMode");
+        psFree(img);
+        psFree(stats);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DAlloc() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+
+        // Call pmTrend2DAlloc() with PM_TREND_POLY_ORD
+        pmTrend2D *trend = pmTrend2DAlloc(PM_TREND_POLY_ORD, img, 2, 4, stats);
+        ok(trend != NULL && psMemCheckTrend2D(trend), 
+          "pmTrend2DAlloc() returned non-NULL with acceptable input parameters");
+        ok(trend->map == NULL, "pmTrend2DAlloc() set trend->map to NULL");
+        ok(trend->mode == PM_TREND_POLY_ORD, "pmTrend2DAlloc() set trend->mode correctly");
+        ok(trend->stats == stats, "pmTrend2DAlloc() set trend->stats correctly");
+        ok(trend->poly != NULL && trend->poly->type == PS_POLYNOMIAL_ORD, "pmTrend2DAlloc() set trend->poly->type correctly");
+        ok(trend->poly->type == PS_POLYNOMIAL_ORD, "pmTrend2DAlloc() set trend->poly->type correctly");
+        ok(trend->poly->nX == 2, "pmTrend2DAlloc() set trend->poly->nX correctly");
+        ok(trend->poly->nY == 4, "pmTrend2DAlloc() set trend->poly->nY correctly");
+        psFree(trend);
+
+        // Call pmTrend2DAlloc() with PM_TREND_POLY_CHEB
+        trend = pmTrend2DAlloc(PM_TREND_POLY_CHEB, img, 2, 4, stats);
+        ok(trend != NULL && psMemCheckTrend2D(trend), 
+          "pmTrend2DAlloc() returned non-NULL with acceptable input parameters");
+        ok(trend->map == NULL, "pmTrend2DAlloc() set trend->map to NULL");
+        ok(trend->mode == PM_TREND_POLY_CHEB, "pmTrend2DAlloc() set trend->mode correctly");
+        ok(trend->stats == stats, "pmTrend2DAlloc() set trend->stats correctly");
+        ok(trend->poly != NULL && trend->poly->type == PS_POLYNOMIAL_CHEB, "pmTrend2DAlloc() set trend->poly->type correctly");
+        ok(trend->poly->type == PS_POLYNOMIAL_CHEB, "pmTrend2DAlloc() set trend->poly->type correctly");
+        ok(trend->poly->nX == 2, "pmTrend2DAlloc() set trend->poly->nX correctly");
+        ok(trend->poly->nY == 4, "pmTrend2DAlloc() set trend->poly->nY correctly");
+        psFree(trend);
+
+        // Create a new pmTrend with PM_TREND_MAP
+        trend = pmTrend2DAlloc(PM_TREND_MAP, img, 2, 4, stats);
+        ok(trend->map != NULL && psMemCheckImageMap(trend->map), 
+           "pmTrend2DAlloc() set trend->map correctly");
+        psFree(trend);
+
+        psFree(img);
+        psFree(stats);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Test pmTrend2DNoImageAlloc()
+    // Call pmTrend2DNoImageAlloc() with NULL psImageBinning input parameter
+    {
+        psMemId id = psMemGetId();
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        psImageBinning *binning = psImageBinningAlloc();
+        pmTrend2D *trend = pmTrend2DNoImageAlloc(PM_TREND_MAP, NULL, stats);
+        ok(trend == NULL, "pmTrend2DNoImageAlloc() returned NULL with NULL psImageBinning input parameter");
+        psFree(stats);
+        psFree(binning);
+        psFree(trend);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DNoImageAlloc() with NULL psStats input parameter
+    {
+        psMemId id = psMemGetId();
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        psImageBinning *binning = psImageBinningAlloc();
+        pmTrend2D *trend = pmTrend2DNoImageAlloc(PM_TREND_MAP, binning, NULL);
+        ok(trend == NULL, "pmTrend2DNoImageAlloc() returned NULL with NULL psStats input parameter");
+        psFree(stats);
+        psFree(binning);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DNoImageAlloc() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        psImageBinning *binning = psImageBinningAlloc();
+        binning->nXruff = 2;
+        binning->nYruff = 4;
+
+        // Call pmTrend2DNoImageAlloc() with PM_TREND_POLY_ORD
+        pmTrend2D *trend = pmTrend2DNoImageAlloc(PM_TREND_POLY_ORD, binning, stats);
+        ok(trend != NULL && psMemCheckTrend2D(trend), "pmTrend2DNoImageAlloc() returned non-NULL with acceptable input parameters");
+        ok(trend->map == NULL, "pmTrend2DAlloc() set trend->map to NULL");
+        ok(trend->mode == PM_TREND_POLY_ORD, "pmTrend2DAlloc() set trend->mode correctly");
+        ok(trend->stats == stats, "pmTrend2DAlloc() set trend->stats correctly");
+        ok(trend->poly != NULL && trend->poly->type == PS_POLYNOMIAL_ORD, "pmTrend2DAlloc() set trend->poly->type correctly");
+        ok(trend->poly->type == PS_POLYNOMIAL_ORD, "pmTrend2DAlloc() set trend->poly->type correctly");
+        ok(trend->poly->nX == 2, "pmTrend2DAlloc() set trend->poly->nX correctly");
+        ok(trend->poly->nY == 4, "pmTrend2DAlloc() set trend->poly->nY correctly");
+        psFree(trend);
+
+        // Call pmTrend2DNoImageAlloc() with PM_TREND_POLY_CHEB
+        trend = pmTrend2DNoImageAlloc(PM_TREND_POLY_CHEB, binning, stats);
+        ok(trend != NULL && psMemCheckTrend2D(trend), "pmTrend2DNoImageAlloc() returned non-NULL with acceptable input parameters");
+        ok(trend->map == NULL, "pmTrend2DAlloc() set trend->map to NULL");
+        ok(trend->mode == PM_TREND_POLY_CHEB, "pmTrend2DAlloc() set trend->mode correctly");
+        ok(trend->stats == stats, "pmTrend2DAlloc() set trend->stats correctly");
+        ok(trend->poly != NULL && trend->poly->type == PS_POLYNOMIAL_CHEB, "pmTrend2DAlloc() set trend->poly->type correctly");
+        ok(trend->poly->type == PS_POLYNOMIAL_CHEB, "pmTrend2DAlloc() set trend->poly->type correctly");
+        ok(trend->poly->nX == 2, "pmTrend2DAlloc() set trend->poly->nX correctly");
+        ok(trend->poly->nY == 4, "pmTrend2DAlloc() set trend->poly->nY correctly");
+        psFree(trend);
+
+        // Call pmTrend2DNoImageAlloc() with PM_TREND_MAP
+        trend = pmTrend2DNoImageAlloc(PM_TREND_MAP, binning, stats);
+        ok(trend != NULL && psMemCheckTrend2D(trend), "pmTrend2DNoImageAlloc() returned non-NULL with acceptable input parameters");
+        ok(trend->map && psMemCheckImageMap(trend->map), "pmTrend2DNoImageAlloc() set the trend->map correctly");
+        psFree(trend);
+
+        psFree(stats);
+        psFree(binning);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Test pmTrend2DFieldAlloc()
+    // Call pmTrend2DFieldAlloc() with NULL psStats input parameter
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        pmTrend2D *trend = pmTrend2DFieldAlloc(PM_TREND_MAP, 1, 2, 3, 4, NULL);
+        ok(trend == NULL, "pmTrend2DFieldAlloc() returned NULL with NULL psStats input parameter");
+        psFree(img);
+        psFree(stats);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DFieldAlloc() with acceptable input parameters
+    {
+        psMemId id = psMemGetId();
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+        pmTrend2D *trend = pmTrend2DFieldAlloc(PM_TREND_POLY_ORD, 1, 2, 3, 4, stats);
+        ok(trend != NULL && psMemCheckTrend2D(trend), "pmTrend2DFieldAlloc() returned non-NULL with acceptable input parameters");
+        ok(trend->poly != NULL && trend->poly->type == PS_POLYNOMIAL_ORD, "pmTrend2DFieldAlloc() set trend->poly->type correctly");
+        ok(trend->poly->type == PS_POLYNOMIAL_ORD, "pmTrend2DFieldAlloc() set trend->poly->type correctly");
+        ok(trend->poly->nX == 3, "pmTrend2DFieldAlloc() set trend->poly->nX correctly");
+        ok(trend->poly->nY == 4, "pmTrend2DFieldAlloc() set trend->poly->nY correctly");
+        psFree(trend);
+        trend = NULL;
+
+        // Create a new pmTrend with PM_TREND_MAP
+        // XXX: This currently fails due to a big in pmTrend2DFieldAlloc():
+        if (0) {
+            trend = pmTrend2DFieldAlloc(PM_TREND_MAP, 1, 2, 3, 4, stats);
+            ok(trend->map != NULL && psMemCheckImageMap(trend->map), 
+               "pmTrend2DAlloc() set trend->map correctly");
+	}
+
+        psFree(stats);
+        psFree(trend);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Test pmTrend2DModeToString()
+    // psString pmTrend2DModeToString (pmTrend2DMode mode)
+    // Call pmTrend2DModeToString() with unallowed pmTrend2DMode.
+    // XX: We comment this out because pmTrend2DModeToString() aborts.
+    if (0) {
+        psMemId id = psMemGetId();
+        psString str = pmTrend2DModeToString(99);
+        ok(str == NULL, "pmTrend2DModeToString() returned NULL with unallowed pmTrend2DMode");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DModeToString() with unallowed pmTrend2DMode.
+    {
+        psMemId id = psMemGetId();
+        psString str = pmTrend2DModeToString(PM_TREND_NONE);
+        ok(!strcmp(str, "NONE"), "pmTrend2DModeToString(PM_TREND_NONE)");
+        psFree(str);
+
+        str = pmTrend2DModeToString(PM_TREND_POLY_ORD);
+        ok(!strcmp(str, "POLY_ORD"), "pmTrend2DModeToString(PM_TREND_POLY_ORD)");
+        psFree(str);
+
+        str = pmTrend2DModeToString(PM_TREND_POLY_CHEB);
+        ok(!strcmp(str, "POLY_CHEB"), "pmTrend2DModeToString(PM_TREND_POLY_CHEB)");
+        psFree(str);
+
+        str = pmTrend2DModeToString(PM_TREND_MAP);
+        ok(!strcmp(str, "MAP"), "pmTrend2DModeToString(PM_TREND_MAP)");
+        psFree(str);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Test pmTrend2DModeFromString()
+    // Call pmTrend2DModeFromString() with NULL input parameter
+    {
+        psMemId id = psMemGetId();
+        pmTrend2DMode mode = pmTrend2DModeFromString(NULL);
+        ok(PM_TREND_NONE == mode, "pmTrend2DModeFromString(NULL) returned PM_TREND_NONE");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DModeFromString() with unallowed input string
+    {
+        psMemId id = psMemGetId();
+        pmTrend2DMode mode = pmTrend2DModeFromString("BOGUS");
+        ok(PM_TREND_NONE == mode, "pmTrend2DModeFromString(BOGUS) returned PM_TREND_NONE");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DModeFromString() with acceptable input string
+    {
+        psMemId id = psMemGetId();
+        pmTrend2DMode mode = pmTrend2DModeFromString("NONE");
+        ok(PM_TREND_NONE == mode, "pmTrend2DModeFromString(NONE) returned PM_TREND_NONE");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DModeFromString() with acceptable input string
+    {
+        psMemId id = psMemGetId();
+        pmTrend2DMode mode = pmTrend2DModeFromString("POLY_ORD");
+        ok(PM_TREND_POLY_ORD == mode, "pmTrend2DModeFromString(POLY_ORD) returned PM_TREND_NONE");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DModeFromString() with acceptable input string
+    {
+        psMemId id = psMemGetId();
+        pmTrend2DMode mode = pmTrend2DModeFromString("POLY_CHEB");
+        ok(PM_TREND_POLY_CHEB == mode, "pmTrend2DModeFromString(POLY_CHEB) returned PM_TREND_NONE");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Call pmTrend2DModeFromString() with acceptable input string
+    {
+        psMemId id = psMemGetId();
+        pmTrend2DMode mode = pmTrend2DModeFromString("MAP");
+        ok(PM_TREND_MAP == mode, "pmTrend2DModeFromString(MAP) returned PM_TREND_NONE");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Test pmTrend2DFit()
+    // Call pmTrend2DFit() with bad input parameters
+    {
+        #define VEC_SIZE 9
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
+        pmTrend2D *trend = pmTrend2DAlloc(PM_TREND_POLY_ORD, img, 4, 4, stats);
+        ok(trend != NULL && psMemCheckTrend2D(trend), 
+          "pmTrend2DAlloc() returned non-NULL with acceptable input parameters");
+        psVector *x = psVectorAlloc(VEC_SIZE, PS_TYPE_F32);
+        psVector *y = psVectorAlloc(VEC_SIZE, PS_TYPE_F32);
+        psVector *f = psVectorAlloc(VEC_SIZE, PS_TYPE_F32);
+        psVector *mask = psVectorAlloc(VEC_SIZE, PS_TYPE_U8);
+        psVector *df = psVectorAlloc(VEC_SIZE, PS_TYPE_F32);
+        for (int i = 0 ; i < VEC_SIZE ; i++) {
+            x->data.F32[i] = (float) (i);
+            y->data.F32[i] = (float) (2 * i);
+            f->data.F32[i] = x->data.F32[i] * y->data.F32[i];
+            mask->data.U8[i] = 0;
+            df->data.F32[i] = 0.0;
+        }
+
+        // NULL pmTrend2D input parameter
+        bool rc = pmTrend2DFit(NULL, mask, 0, x, y, f, df);
+        ok(rc == false, "pmTrend2DFit() returned FALSE with NULL pmTrend2D input parameter");
+
+        // NULL mask input parameter
+        rc = pmTrend2DFit(trend, NULL, 0, x, y, f, df);
+        ok(rc == false, "pmTrend2DFit() returned FALSE with NULL mask input parameter");
+
+        // NULL x psVector input parameter
+        rc = pmTrend2DFit(trend, mask, 0, NULL, y, f, df);
+        ok(rc == false, "pmTrend2DFit() returned FALSE with NULL x psVector input parameter");
+
+        // NULL y psVector input parameter
+        rc = pmTrend2DFit(trend, mask, 0, x, NULL, f, df);
+        ok(rc == false, "pmTrend2DFit() returned FALSE with NULL y psVector input parameter");
+
+        // NULL f psVector input parameter
+        rc = pmTrend2DFit(trend, mask, 0, x, y, NULL, df);
+        ok(rc == false, "pmTrend2DFit() returned FALSE with NULL f psVector input parameter");
+
+        // NULL df psVector input parameter
+        rc = pmTrend2DFit(trend, mask, 0, x, y, f, NULL);
+        ok(rc == true, "pmTrend2DFit() returned TRUE with NULL df psVector input parameter");
+
+        psFree(img);
+        psFree(stats);
+        psFree(trend);
+        psFree(x);
+        psFree(y);
+        psFree(f);
+        psFree(mask);
+        psFree(df);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Test pmTrend2DEval()
+    // Call pmTrend2DEval() with bad input parameters
+    {
+        psMemId id = psMemGetId();
+        psF64 tmpD = pmTrend2DEval(NULL, 0.0, 0.0);
+        ok(TEST_FLOATS_EQUAL(tmpD, 0.0), "pmTrend2DEval() returned 0.0 with NULL pmTrend2D input parameter");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Test pmTrend2DEvalVector()
+    // psVector *pmTrend2DEvalVector (pmTrend2D *trend, psVector *x, psVector *y)
+    // Call pmTrend2DEvalVector() with bad input parameters
+    {
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
+        pmTrend2D *trend = pmTrend2DAlloc(PM_TREND_POLY_ORD, img, 4, 4, stats);
+        psVector *x = psVectorAlloc(VEC_SIZE, PS_TYPE_F32);
+        psVector *y = psVectorAlloc(VEC_SIZE, PS_TYPE_F32);
+
+        // NULL pmTrend2D input parameter
+        psVector *f = pmTrend2DEvalVector(NULL, x, y);
+        ok(f == NULL, "pmTrend2DEvalVector() returned NULL with NULL pmTrend2D input parameter");
+
+        // NULL x psVector input parameter
+        f = pmTrend2DEvalVector(trend, NULL, y);
+        ok(f == NULL, "pmTrend2DEvalVector() returned NULL with NULL x psVector input parameter");
+
+        // NULL y psVector input parameter
+        f = pmTrend2DEvalVector(trend, x, NULL);
+        ok(f == NULL, "pmTrend2DEvalVector() returned NULL with NULL y psVector input parameter");
+
+        psFree(img);
+        psFree(stats);
+        psFree(trend);
+        psFree(x);
+        psFree(y);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test pmTrend2DFit(), pmTrend2DEval(), pmTrend2DEvalVector() with acceptable input parameters
+    // NOTE: We only test with a very simple 2D polynomial fit.  This is appropriate since the
+    // polynomial testing routines are tested extensively elsewhere.
+    // XXX: Must test the PM_TREND_MAP case.
+    {
+        #define VEC_SIZE 9
+        psMemId id = psMemGetId();
+        psImage *img = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+        psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
+        pmTrend2D *trend = pmTrend2DAlloc(PM_TREND_POLY_ORD, img, 4, 4, stats);
+        ok(trend != NULL && psMemCheckTrend2D(trend), 
+          "pmTrend2DAlloc() returned non-NULL with acceptable input parameters");
+        psVector *x = psVectorAlloc(VEC_SIZE, PS_TYPE_F32);
+        psVector *y = psVectorAlloc(VEC_SIZE, PS_TYPE_F32);
+        psVector *f = psVectorAlloc(VEC_SIZE, PS_TYPE_F32);
+        psVector *mask = psVectorAlloc(VEC_SIZE, PS_TYPE_U8);
+        psVector *df = psVectorAlloc(VEC_SIZE, PS_TYPE_F32);
+
+        int cnt = 0;
+        for (int i = 0 ; i < 3 ; i++) {
+            for (int j = 0 ; j < 3 ; j++) {
+                x->data.F32[cnt] = (float) i;
+                y->data.F32[cnt] = (float) j;
+                f->data.F32[cnt] = x->data.F32[cnt] * y->data.F32[cnt];
+                mask->data.U8[cnt] = 0;
+                df->data.F32[cnt] = 0.0;
+                cnt++;
+            }
+        }
+
+        bool rc = pmTrend2DFit(trend, mask, 0, x, y, f, NULL);
+        ok(rc == true, "pmTrend2DFit() returned TRUE with acceptable input parameters");
+
+        // Test pmTrend2DFit, pmTrend2DEval()
+        bool errorFlag = false;
+        for (int i = 0 ; i < VEC_SIZE ; i++) {
+            if (!TEST_FLOATS_EQUAL(pmTrend2DEval(trend, x->data.F32[i], y->data.F32[i]), f->data.F32[i])) {
+                diag("ERROR: at (%.2f %.2f), eval is %.2f, should be %.2f\n", x->data.F32[i], y->data.F32[i],
+                      pmTrend2DEval(trend, x->data.F32[i], y->data.F32[i]), f->data.F32[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "pmTrend2DFit() and pmTrend2DEval() set and evaluated the 2DTrend polynomial correctly");
+
+        // Test pmTrend2DEvalVector()
+        psVector *fTest = pmTrend2DEvalVector(trend, x, y);
+        errorFlag = false;
+        for (int i = 0 ; i < VEC_SIZE ; i++) {
+            if (!TEST_FLOATS_EQUAL(fTest->data.F32[i], f->data.F32[i])) {
+                diag("ERROR: at (%.2f %.2f), eval is %.2f, should be %.2f\n", 
+                      x->data.F32[i], y->data.F32[i], fTest->data.F32[i], f->data.F32[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "pmTrend2DFit() and pmTrend2DEval() set and evaluated the 2DTrend polynomial correctly");
+
+
+        psFree(img);
+        psFree(stats);
+        psFree(trend);
+        psFree(x);
+        psFree(y);
+        psFree(f);
+        psFree(fTest);
+        psFree(mask);
+        psFree(df);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+}
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tst_pmObjects01.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tst_pmObjects01.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/objects/tst_pmObjects01.c	(revision 22158)
@@ -0,0 +1,1300 @@
+/** @file tst_pmObjects.c
+ *
+ *  @brief Contains the tests for pmObjects.c:
+ *
+ * test00: This code will test the pmObjects routines.
+ *
+ *  @author GLG, MHPCC
+ *
+ * XXX: Must test
+ *       pmSourceRoughClass
+ *  many others...
+ *
+ *
+ * XXX: Must test output results for many other functions.
+ *
+ * XXX: There are many cases where row/col can be switched in the code.
+ * We must test that here by using non-square images.  All tests
+ * in this file should be run with non-square images.
+ *
+ * XXX: Memory leaks are not being caught.  If I allocated a psVector in these functions
+ * and never deallocate, no error is generated.
+ *
+ * XXX: Much of this file is commented out due to the API changes in rel 7.
+ *
+ *
+Fully Tested:
+    pmPeakAlloc()
+    pmMomentsAlloc()
+Weakly Tested:
+    pmSourceMoments()
+    most of psObjects.c is not tested
+ *
+ *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-08-24 00:11:59 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#include "psTest.h"
+#include "pslib.h"
+#include "pmObjects.h"
+#include "pmModelGroup.h"
+
+#define NUM_ROWS 10
+#define NUM_COLS 10
+#define ERROR_TOLERANCE 1.0
+#define ERROR_TOL 0.001
+static int test00(void);
+static int test01(void);
+static int test02(void);
+static int test03(void);
+static int test04(void);
+static int test05(void);
+//static int test06(void);
+//static int test07(void);
+//static int test08(void);
+//static int test09(void);
+//static int test15(void);
+//static int test16(void);
+//static int test20(void);
+testDescription tests[] = {
+                              {test00, 000, "pmObjects: structure allocators and deallocators", true, false},
+                              {test01, 001, "pmObjects: psFindVectorPeaks()", true, false},
+                              {test02, 001, "pmObjects: psFindImagePeaks()", true, false},
+                              {test03, 001, "pmObjects: pmCullPeaks()", true, false},
+                              {test04, 001, "pmObjects: pmSourceLocalSky()", true, false},
+                              {test05, 001, "pmObjects: pmSourceMoments()", true, false},
+                              //                              {test06, 001, "pmObjects: pmSourceSetPixelsCircle()", true, false},
+                              //                              {test07, 001, "pmObjects: pmMin()", true, false},
+                              //                              {test08, 001, "pmObjects: pmSourceModelGuess()", true, false},
+                              //{test09, 001, "pmObjects: pmSourceContour()", true, false},
+                              //{test15, 001, "pmObjects: pmSourceAddModel()", true, false},
+                              //{test16, 001, "pmObjects: pmSourceSubModel()", true, false},
+                              //{test20, 001, "pmObjects: pmSourceSubModel()", true, false},
+                              {NULL}
+                          };
+
+int main(int argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    //
+    // We include the function names here in psTraceSetLevel() commands for
+    // debugging convenience.  There is no guarantee that this list of functions
+    // is complete.
+    //
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("pmPeakAlloc", 0);
+    psTraceSetLevel("pmMomentsAlloc", 0);
+    psTraceSetLevel("modelFree", 0);
+    psTraceSetLevel("pmModelAlloc", 0);
+    psTraceSetLevel("sourceFree", 0);
+    psTraceSetLevel("pmSourceAlloc", 0);
+    psTraceSetLevel("pmFindVectorPeaks", 0);
+    psTraceSetLevel("getRowVectorFromImage", 0);
+    psTraceSetLevel("myListAddPeak", 0);
+    psTraceSetLevel("pmFindImagePeaks", 0);
+    psTraceSetLevel("isItInThisRegion", 0);
+    psTraceSetLevel("pmCullPeaks", 0);
+    psTraceSetLevel("pmPeaksSubset", 0);
+    psTraceSetLevel("pmSourceLocalSky", 0);
+    psTraceSetLevel("checkRadius2", 0);
+    psTraceSetLevel("pmSourceMoments", 0);
+    psTraceSetLevel("pmComparePeakAscend", 0);
+    psTraceSetLevel("pmComparePeakDescend", 0);
+    psTraceSetLevel("pmSourcePSFClump", 0);
+    psTraceSetLevel("pmSourceRoughClass", 0);
+    psTraceSetLevel("pmSourceDefinePixels", 0);
+    psTraceSetLevel("pmSourceModelGuess", 0);
+    psTraceSetLevel("pmModelEval", 0);
+    psTraceSetLevel("findValue", 0);
+    psTraceSetLevel("pmSourceContour", 0);
+    psTraceSetLevel("pmSourceFitModel_v5", 0);
+    psTraceSetLevel("pmSourceFitModel", 0);
+    psTraceSetLevel("p_pmSourceAddOrSubModel", 0);
+    psTraceSetLevel("pmSourceAddModel", 0);
+    psTraceSetLevel("pmSourceSubModel", 0);
+
+    return !runTestSuite(stderr, "Test Point Driver", tests, argc, argv);
+}
+
+/******************************************************************************
+test00(): Test the various allocators and deallocators.
+ *****************************************************************************/
+int test00( void )
+{
+    bool testStatus = true;
+    psTraceSetLevel(".", 0);
+
+    printf("Testing pmPeakAlloc()...\n");
+    pmPeak *tmpPeak = pmPeakAlloc(1, 2, 3.0, PM_PEAK_LONE);
+    if (tmpPeak == NULL) {
+        printf("TEST ERROR: pmPeakAlloc() returned a NULL pmPeak\n");
+        testStatus = false;
+    } else {
+        if (tmpPeak->x != 1) {
+            printf("TEST ERROR: pmPeakAlloc() improperly set pmPeak->x\n");
+            testStatus = false;
+        }
+        if (tmpPeak->y != 2) {
+            printf("TEST ERROR: pmPeakAlloc() improperly set pmPeak->y\n");
+            testStatus = false;
+        }
+        if (tmpPeak->counts != 3.0) {
+            printf("TEST ERROR: pmPeakAlloc() improperly set pmPeak->counts\n");
+            testStatus = false;
+        }
+        if (tmpPeak->class != PM_PEAK_LONE) {
+            printf("TEST ERROR: pmPeakAlloc() improperly set pmPeak->class\n");
+            testStatus = false;
+        }
+    }
+    psFree(tmpPeak);
+
+    printf("Testing pmMomentsAlloc()...\n");
+    pmMoments *tmpMoments = pmMomentsAlloc();
+    if (tmpMoments == NULL) {
+        printf("TEST ERROR: pmMomentsAlloc() returned a NULL pmMoments\n");
+        testStatus = false;
+    } else {
+        if ((fabs(tmpMoments->x-0.0) > ERROR_TOL) ||
+                (fabs(tmpMoments->y-0.0) > ERROR_TOL) ||
+                (fabs(tmpMoments->Sx-0.0) > ERROR_TOL) ||
+                (fabs(tmpMoments->Sy-0.0) > ERROR_TOL) ||
+                (fabs(tmpMoments->Sxy-0.0) > ERROR_TOL) ||
+                (fabs(tmpMoments->Sum-0.0) > ERROR_TOL) ||
+                (fabs(tmpMoments->Peak-0.0) > ERROR_TOL) ||
+                (fabs(tmpMoments->Sky-0.0) > ERROR_TOL) ||
+                (tmpMoments->nPixels != 0)) {
+            printf("TEST ERROR: pmMomentsAlloc() did not properly initialize the pmMoments structure.\n");
+            printf("    tmpMoments->x is %f\n", tmpMoments->x);
+            printf("    tmpMoments->y is %f\n", tmpMoments->y);
+            printf("    tmpMoments->Sx is %f\n", tmpMoments->Sx);
+            printf("    tmpMoments->Sy is %f\n", tmpMoments->Sy);
+            printf("    tmpMoments->Sxy is %f\n", tmpMoments->Sxy);
+            printf("    tmpMoments->Sum is %f\n", tmpMoments->Sum);
+            printf("    tmpMoments->Peak is %f\n", tmpMoments->Peak);
+            printf("    tmpMoments->Sky is %f\n", tmpMoments->Sky);
+            printf("    tmp    Moments->nPixels is %d\n", tmpMoments->nPixels);
+            testStatus = false;
+        }
+    }
+    psFree(tmpMoments);
+
+
+    //
+    // Loop through each type of model
+    //
+    psS32 i = 0;
+    while (0 != pmModelClassParameterCount(i)) {
+        printf("Testing pmModelAlloc(%s)...\n", pmModelClassGetName(0));
+        pmModel *tmpModel = pmModelAlloc(i);
+        if (tmpModel == NULL) {
+            printf("TEST ERROR: pmModelAlloc(%s) returned a NULL pmModel\n", pmModelClassGetName(0));
+            testStatus = false;
+        } else {
+
+            /* XXX: Should we test that the members were set correctly?
+                        if ((tmpModel->params->n != 7) || (tmpModel->dparams->n != 7)) {
+                            printf("TEST ERROR: pmModelAlloc(PS_MODEL_GAUSS) allocated an incorrect number of params (%ld, %ld)\n",
+                                   tmpModel->params->n, tmpModel->dparams->n);
+                            testStatus = false;
+                        } else {
+                            for (psS32 i = 0 ; i < 7 ; i++) {
+                                if ((tmpModel->params->data.F32[i] != 0.0) ||
+                                        (tmpModel->dparams->data.F32[i] != 0.0)) {
+                                    printf("TEST ERROR: pmModelAlloc(PS_MODEL_GAUSS) did not ininitialize the params/dparams array to 0.0.\n");
+                                    testStatus = false;
+                                }
+                            }
+                        }
+            */
+        }
+        psFree(tmpModel);
+        i++;
+    }
+
+
+    pmSource *tmpSource = pmSourceAlloc();
+    if (tmpSource == NULL) {
+        printf("TEST ERROR: pmSourceAlloc() returned a NULL pmSource\n");
+        testStatus = false;
+    }
+    psFree(tmpSource);
+
+    return(testStatus);
+}
+
+/******************************************************************************
+test01(): we first test pmFindVectorPeaks() with a variety of bad input
+parameters.  Then we test it with a simple vector both 1- and multi-elements.
+ *****************************************************************************/
+#define TST01_VECTOR_LENGTH 10
+bool test_pmFindVectorPeaks(int n)
+{
+    bool testStatus = true;
+    psVector *inData = psVectorAlloc(n, PS_TYPE_F32);
+    inData->n = inData->nalloc;
+    psVector *outData = NULL;
+
+    printf("-------------- Calling test_pmFindVectorPeaks on an %d size vector. --------------\n", n);
+    //
+    // Test first pixel peak.
+    //
+    printf("Test pmFindVectorPeaks() with a first-element peak.\n");
+    for (psS32 i = 0 ; i < n ; i++) {
+        inData->data.F32[i] = (float) (n-i);
+    }
+    inData->data.F32[0] = (float) n;
+
+    outData= pmFindVectorPeaks(inData, 0.0);
+    if (outData == NULL) {
+        printf("TEST ERROR: pmFindVectorPeaks returned a NULL psVector.\n");
+        testStatus = false;
+    } else {
+        if (outData->n != 1) {
+            printf("TEST ERROR: outData->n is %ld\n", outData->n);
+            testStatus = false;
+        }
+        if (outData->data.U32[0] != 0) {
+            printf("TEST ERROR: Did not find peak at element 0.\n");
+            testStatus = false;
+        }
+        psFree(outData);
+    }
+
+    //
+    // Test first pixel peak, large threshold
+    //
+    printf("Test pmFindVectorPeaks() with a first-element peak, large threshold.\n");
+    for (psS32 i = 0 ; i < n ; i++) {
+        inData->data.F32[i] = (float) (n-i);
+    }
+    inData->data.F32[0] = (float) n;
+
+    outData= pmFindVectorPeaks(inData, (float) (n*n));
+    if (outData == NULL) {
+        printf("TEST ERROR: pmFindVectorPeaks returned a NULL psVector.\n");
+        testStatus = false;
+    } else {
+
+        if (outData->n != 0) {
+            printf("TEST ERROR: outData->n is %ld\n", outData->n);
+            testStatus = false;
+        }
+        psFree(outData);
+
+        // Skip remaining tests if the input vector has length 1.
+        if (n == 1) {
+            psFree(inData);
+            return(testStatus);
+        }
+    }
+
+    //
+    // Test last pixel peak.
+    //
+    printf("Test pmFindVectorPeaks() with a last-element peak.\n");
+    for (psS32 i = 0 ; i < n ; i++) {
+        inData->data.F32[i] = (float) (i);
+    }
+    inData->data.F32[n-1] = (float) n;
+
+    outData= pmFindVectorPeaks(inData, 0.0);
+    if (outData == NULL) {
+        printf("TEST ERROR: pmFindVectorPeaks returned a NULL psVector.\n");
+        testStatus = false;
+    } else {
+
+        if (outData->n != 1) {
+            printf("TEST ERROR: outData->n is %ld\n", outData->n);
+            testStatus = false;
+        }
+        if (outData->data.U32[0] != n-1) {
+            printf("TEST ERROR: Did not find peak at element %d.\n", n-1);
+            testStatus = false;
+        }
+        psFree(outData);
+    }
+
+    //
+    // Test last pixel peak, large threshold.
+    //
+    printf("Test pmFindVectorPeaks() with a last-element peak, large threshold.\n");
+    for (psS32 i = 0 ; i < n ; i++) {
+        inData->data.F32[i] = (float) (i);
+    }
+    inData->data.F32[n-1] = (float) n;
+
+    outData= pmFindVectorPeaks(inData, (float) (n*n));
+    if (outData == NULL) {
+        printf("TEST ERROR: pmFindVectorPeaks returned a NULL psVector.\n");
+        testStatus = false;
+    } else {
+
+        if (outData->n != 0) {
+            printf("TEST ERROR: outData->n is %ld\n", outData->n);
+            testStatus = false;
+        }
+        psFree(outData);
+    }
+
+    //
+    // Test interior peaks.
+    // Set all even number elements to be peaks.
+    //
+    printf("Test pmFindVectorPeaks() with all even-numbered elements peak.\n");
+    for (psS32 i = 0 ; i < n ; i++) {
+        if (0 == i%2) {
+            inData->data.F32[i] = (float) (2 * i);
+        } else {
+            inData->data.F32[i] = (float) (i);
+        }
+    }
+    inData->data.F32[0] = (float) n;
+
+
+    outData= pmFindVectorPeaks(inData, 0.0);
+    if (outData == NULL) {
+        printf("TEST ERROR: pmFindVectorPeaks returned a NULL psVector.\n");
+        testStatus = false;
+    } else {
+
+        if (outData->n != n/2) {
+            printf("TEST ERROR: outData->n is %ld\n", outData->n);
+            testStatus = false;
+        }
+
+        for (psS32 i = 0 ; i < outData->n ; i++) {
+            if (outData->data.U32[i] != (2 * i)) {
+                printf("TEST ERROR: the %d-th peak is element number %d\n", i, outData->data.U32[i]);
+                testStatus = false;
+            }
+        }
+        psFree(outData);
+    }
+
+    //
+    // Test interior peaks, with threshold = n*n.
+    // Should generate an empty output psVector.
+    //
+    printf("Test pmFindVectorPeaks() with all even-numbered elements peak, large threshold.\n");
+    outData= pmFindVectorPeaks(inData, (float) (n*n));
+    if (outData == NULL) {
+        printf("TEST ERROR: pmFindVectorPeaks returned a NULL psVector.\n");
+        testStatus = false;
+    } else {
+
+        if (outData->n != 0) {
+            printf("TEST ERROR: outData->n is %ld\n", outData->n);
+            testStatus = false;
+        }
+        psFree(outData);
+    }
+
+    psFree(inData);
+    return(testStatus);
+}
+
+int test01( void )
+{
+    bool testStatus = true;
+    psVector *tmpVec = NULL;
+    psVector *tmpVecF64 = psVectorAlloc(TST01_VECTOR_LENGTH, PS_TYPE_F64);
+    psVector *tmpVecEmpty = psVectorAlloc(0, PS_TYPE_F32);
+    tmpVecF64->n = tmpVecF64->nalloc;
+    tmpVecEmpty->n = tmpVecEmpty->nalloc;
+
+    psTraceSetLevel(".", 0);
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmFindVectorPeaks with NULL psVector.  Should generate error and return NULL.\n");
+    tmpVec = pmFindVectorPeaks(NULL, 0.0);
+    if (tmpVec != NULL) {
+        printf("TEST ERROR: pmFindVectorPeaks() returned a non-NULL psVector.\n");
+        testStatus = false;
+        psFree(tmpVec);
+    }
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmFindVectorPeaks with empty psVector.  Should generate error and return NULL.\n");
+    tmpVec = pmFindVectorPeaks(tmpVecEmpty, 0.0);
+    if (tmpVec != NULL) {
+        printf("TEST ERROR: pmFindVectorPeaks() returned a non-NULL psVector.\n");
+        testStatus = false;
+        psFree(tmpVec);
+    }
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmFindVectorPeaks with PS_TYPE_F64 psVector.  Should generate error and return NULL.\n");
+    tmpVec = pmFindVectorPeaks(tmpVecF64, 0.0);
+    if (tmpVec != NULL) {
+        printf("TEST ERROR: pmFindVectorPeaks() returned a non-NULL psVector.\n");
+        testStatus = false;
+        psFree(tmpVec);
+    }
+    testStatus&= test_pmFindVectorPeaks(1);
+    testStatus&= test_pmFindVectorPeaks(TST01_VECTOR_LENGTH);
+
+    psFree(tmpVecF64);
+    psFree(tmpVecEmpty);
+    return(testStatus);
+}
+
+/******************************************************************************
+test02():
+// XXX: Must test flat peaks.
+// XXX: test 1-by-n and n-by-1 images.
+ *****************************************************************************/
+#define TST02_NUM_ROWS 5
+#define TST02_NUM_COLS 5
+bool test_pmFindImagePeaks(int numRows, int numCols)
+{
+    printf("-------------- Calling test_pmFindImagePeaks on an %d-by-%d image. --------------\n", numRows, numCols);
+    //    if ((numRows < 4) || (numCols < 4)) {
+    //        printf("WARNING: Don't call this test with a smaller than 4-by-4 image.\n");
+    //        return(true);
+    //    }
+    bool testStatus = true;
+    psImage *inData = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    psArray *outData = NULL;
+
+    //
+    // Initialize test image.
+    //
+    for (psS32 i = 0 ; i < numRows ; i++) {
+        for (psS32 j = 0 ; j < numCols ; j++) {
+            inData->data.F32[i][j] = PS_SQR(i - numRows/2) + PS_SQR(j-numCols/2);
+        }
+    }
+    //
+    // Set corner and center pixels as peaks.
+    //
+    inData->data.F32[0][0] = PS_SQR(numRows) + PS_SQR(numCols);
+    inData->data.F32[0][numCols-1] = PS_SQR(numRows) + PS_SQR(numCols);
+    inData->data.F32[numRows-1][0] = PS_SQR(numRows) + PS_SQR(numCols);
+    inData->data.F32[numRows-1][numCols-1] = PS_SQR(numRows) + PS_SQR(numCols);
+    inData->data.F32[numRows/2][numCols/2] = PS_SQR(numRows) + PS_SQR(numCols);
+
+    //
+    // Print image.
+    //
+    for (psS32 i = 0 ; i < numRows ; i++) {
+        for (psS32 j = 0 ; j < numCols ; j++) {
+            printf("(%.1f) ", inData->data.F32[i][j]);
+        }
+        printf("\n");
+    }
+
+    //
+    // Call pmFindImagePeaks() with a threshold of 0.0.
+    //
+    outData = pmFindImagePeaks(inData, 0.0);
+
+    if (outData == NULL) {
+        printf("TEST ERROR: pmFindImagePeaks returned a NULL psList.\n");
+        testStatus = false;
+    } else {
+        psS32 expectedNumPeaks;
+        if ((numRows == 1) && (numCols == 1)) {
+            expectedNumPeaks = 1;
+        } else if ((numRows == 1) || (numCols == 1)) {
+            expectedNumPeaks = 3;
+        } else {
+            expectedNumPeaks = 5;
+        }
+        if (outData->n != expectedNumPeaks) {
+            printf("TEST ERROR: pmFindImagePeaks found %ld peaks (should be %d)\n", outData->n, expectedNumPeaks);
+            testStatus = false;
+        }
+
+        // HEY: verify
+        for (psS32 i = 0 ; i < outData->n ; i++) {
+            pmPeak *tmpPeak = (pmPeak *) outData->data[i];
+            if (((tmpPeak->x == 0) && (tmpPeak->y == 0)) ||
+                    ((tmpPeak->x == 0) && (tmpPeak->y == numRows-1)) ||
+                    ((tmpPeak->x == numCols-1) && (tmpPeak->y == 0)) ||
+                    ((tmpPeak->x == numCols-1) && (tmpPeak->y == numRows-1))) {
+                if (!((tmpPeak->class & PM_PEAK_LONE) || (tmpPeak->class & PM_PEAK_EDGE))) {
+                    printf("TEST ERROR: (0) peak at (%d, %d) (%f) ->class set improperly (0x%x).",
+                           tmpPeak->y, tmpPeak->x, tmpPeak->counts, tmpPeak->class);
+                    printf(" should be (0x%x or 0x%x).\n", PM_PEAK_LONE, PM_PEAK_EDGE);
+                    testStatus = false;
+                }
+            } else if ((tmpPeak->x == numCols/2) && (tmpPeak->y == numRows/2)) {
+                if (tmpPeak->class != PM_PEAK_LONE) {
+                    printf("TEST ERROR: (1) peak at (%d, %d) (%f) ->class set improperly (0x%x).\n",
+                           tmpPeak->y, tmpPeak->x, tmpPeak->counts, tmpPeak->class);
+                    printf(" should be (0x%x).\n", PM_PEAK_LONE);
+                    testStatus = false;
+                }
+            } else {
+                printf("TEST ERROR: Peak at (%d, %d) (%f)\n", tmpPeak->y, tmpPeak->x, tmpPeak->counts);
+                testStatus = false;
+            }
+        }
+    }
+
+    psFree(inData);
+    psFree(outData);
+    return(testStatus);
+}
+
+int test02( void )
+{
+    bool testStatus = true;
+    psArray *tmpArray = NULL;
+    psImage *tmpImageF64 = psImageAlloc(TST02_NUM_ROWS, TST02_NUM_COLS, PS_TYPE_F64);
+    psImage *tmpImageEmpty = psImageAlloc(0, 0, PS_TYPE_F32);
+
+    psTraceSetLevel(".", 0);
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmFindImagePeaks with NULL psImage.  Should generate error and return NULL.\n");
+    tmpArray = pmFindImagePeaks(NULL, 0.0);
+    if (tmpArray != NULL) {
+        printf("TEST ERROR: pmFindImagePeaks() returned a non-NULL psImage.\n");
+        testStatus = false;
+        psFree(tmpArray);
+    }
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmFindImagePeaks with empty psImage.  Should generate error and return NULL.\n");
+    tmpArray = pmFindImagePeaks(tmpImageEmpty, 0.0);
+    if (tmpArray != NULL) {
+        printf("TEST ERROR: pmFindImagePeaks() returned a non-NULL psImage.\n");
+        testStatus = false;
+        psFree(tmpArray);
+    }
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmFindImagePeaks with PS_TYPE_F64 psImage.  Should generate error and return NULL.\n");
+    tmpArray = pmFindImagePeaks(tmpImageF64, 0.0);
+    if (tmpArray != NULL) {
+        printf("TEST ERROR: pmFindImagePeaks() returned a non-NULL psImage.\n");
+        testStatus = false;
+        psFree(tmpArray);
+    }
+    printf("----------------------------------------------------------------------------------\n");
+    //    testStatus&= test_pmFindImagePeaks(1, 1);
+    //    testStatus&= test_pmFindImagePeaks(2, 5);
+    //    testStatus&= test_pmFindImagePeaks(5, 2);
+    // HEY: add code for small images
+    //    testStatus&= test_pmFindImagePeaks(1, 1);
+    //    testStatus&= test_pmFindImagePeaks(1, 8);
+    //    testStatus&= test_pmFindImagePeaks(8, 1);
+    testStatus&= test_pmFindImagePeaks(TST02_NUM_ROWS,   TST02_NUM_COLS);
+    testStatus&= test_pmFindImagePeaks(2*TST02_NUM_ROWS, TST02_NUM_COLS);
+    testStatus&= test_pmFindImagePeaks(TST02_NUM_ROWS,   2*TST02_NUM_COLS);
+
+
+    psFree(tmpImageF64);
+    psFree(tmpImageEmpty);
+    return(testStatus);
+}
+
+/******************************************************************************
+test03(): We first test pmCullPeaks() with various NULL and unallowable input
+parameters.  Then we generate a list of peaks and test that pmCullPeaks()
+removes them correctly.
+ *****************************************************************************/
+int test03( void )
+{
+    bool testStatus = true;
+    psImage *imgData = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
+    psArray *outData = NULL;
+
+    /* XXX: Modify for new pmCullPeaks()
+            printf("----------------------------------------------------------------------------------\n");
+            printf("Calling pmCullPeaks with NULL psList.  Should generate error and return NULL.\n");
+            outData = pmCullPeaks(NULL, 0.0, NULL);
+            if (outData != NULL) {
+                printf("TEST ERROR: pmCulPeaks() returned a non-NULL psList.\n");
+                testStatus = false;
+        }
+    */
+
+    //
+    // Set peaks in input image.  All even-column and even-row pixels are
+    // set non-zero, all other pixels are set to zero.
+    //
+    psS32 numPeaksOrig = 0;
+    for (psS32 i = 0 ; i < NUM_ROWS ; i++) {
+        for (psS32 j = 0 ; j < NUM_COLS ; j++) {
+            if ((0 == i%2) && (0 == j%2)) {
+                imgData->data.F32[i][j] = (float) (i + 10);
+                numPeaksOrig++;
+            } else {
+                imgData->data.F32[i][j] = 0.0;
+            }
+        }
+    }
+    for (psS32 i = 0 ; i < NUM_ROWS ; i++) {
+        for (psS32 j = 0 ; j < NUM_COLS ; j++) {
+            printf("(%.1f) ", imgData->data.F32[i][j]);
+        }
+        printf("\n");
+    }
+    printf("Set %d peaks\n", numPeaksOrig);
+
+    //
+    // Call pmCullPeaks() with HUGE maxValue and NULL psRegion.  Should not
+    // remove any peaks.
+    //
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmCullPeaks with large maxValue and NULL psRegion.\n");
+    outData = pmFindImagePeaks(imgData, 0.0);
+    /* XXX: Modify for new pmCullPeaks
+        outData = pmCullPeaks(outData, PS_MAX_F32, NULL);
+
+        if (outData == NULL) {
+            printf("TEST ERROR: pmCullPeaks() returned a non-NULL psList.\n");
+            testStatus = false;
+            return(testStatus);
+        }
+        if (outData->n != numPeaksOrig) {
+            printf("TEST ERROR (0): pmCullPeaks incorrectly removed peaks\n");
+            printf("The pmCullPeaks() output had %d peaks, should have had %d peaks.\n", outData->n, numPeaksOrig);
+            testStatus = false;
+        }
+    */
+    psFree(outData);
+
+    //
+    // Call pmCullPeaks() with TINY maxValue and NULL psRegion.  Should
+    // remove all peaks.
+    //
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmCullPeaks with tiny maxValue and NULL psRegion.\n");
+    outData = pmFindImagePeaks(imgData, 0.0);
+    printf("pmFindImagePeaks found %ld peaks\n", outData->n);
+    /* XXX: Modify for new pmCullPeaks
+        outData = pmCullPeaks(outData, 0.0, NULL);
+
+        if (outData == NULL) {
+            printf("TEST ERROR: pmCullPeaks() returned a non-NULL psList.\n");
+            testStatus = false;
+            return(testStatus);
+        }
+        if (outData->n != 0) {
+            printf("TEST ERROR (1): pmCullPeaks incorrectly removed peaks\n");
+            printf("The pmCullPeaks() output had %d peaks, should have had %d peaks.\n", outData->n, 0);
+            testStatus = false;
+        }
+        psFree(outData);
+    */
+
+    //
+    // Call pmCullPeaks() with HUGE maxValue and disjoint psRegion.  Should
+    // not remove any peaks.
+    //
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmCullPeaks with large maxValue and disjoint psRegion.\n");
+    outData = pmFindImagePeaks(imgData, 0.0);
+    printf("pmFindImagePeaks found %ld peaks\n", outData->n);
+    psRegion tmpRegion = psRegionSet(10000.0, 20000.0, 10000.0, 20000.0);
+
+    /* XXX: Modify for new pmCullPeaks
+        outData = pmCullPeaks(outData, PS_MAX_F32, tmpRegion);
+
+        if (outData == NULL) {
+            printf("TEST ERROR: pmCullPeaks() returned a non-NULL psList.\n");
+            testStatus = false;
+            return(testStatus);
+        }
+        if (outData->n != numPeaksOrig) {
+            printf("TEST ERROR (2): pmCullPeaks incorrectly removed peaks\n");
+            printf("The pmCullPeaks() output had %d peaks, should have had %d peaks.\n", outData->n, numPeaksOrig);
+            testStatus = false;
+        }
+    */
+    psFree(outData);
+
+    //
+    // Call pmCullPeaks() with HUGE maxValue and non-disjoint psRegion.  Should
+    // remove all peaks.
+    //
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmCullPeaks with large maxValue and non-disjoint psRegion.\n");
+    outData = pmFindImagePeaks(imgData, 0.0);
+    printf("pmFindImagePeaks found %ld peaks\n", outData->n);
+    tmpRegion = psRegionSet(-PS_MAX_F32, PS_MAX_F32, -PS_MAX_F32, PS_MAX_F32);
+    /* XXX: Modify for new pmCullPeaks
+        outData = pmCullPeaks(outData, PS_MAX_F32, tmpRegion);
+
+        if (outData == NULL) {
+            printf("TEST ERROR: pmCullPeaks() returned a non-NULL psList.\n");
+            testStatus = false;
+            return(testStatus);
+        }
+        if (outData->n != 0) {
+            printf("TEST ERROR (3): pmCullPeaks incorrectly removed peaks\n");
+            printf("The pmCullPeaks() output had %d peaks, should have had %d peaks.\n", outData->n, 0);
+            testStatus = false;
+        }
+    */
+    psFree(outData);
+
+    printf("----------------------------------------------------------------------------------\n");
+    psFree(imgData);
+    return(testStatus);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#define TST04_NUM_ROWS 100
+#define TST04_NUM_COLS 100
+#define TST04_SKY 20.0
+#define TST04_INNER_RADIUS 3
+#define TST04_OUTER_RADIUS 5
+/******************************************************************************
+test04(): We first test pmSourceLocalSky() with various NULL and unallowable
+input parameters.
+ 
+XXX: Should we produce tests with boundary numbers for the inner/outer radius?
+ 
+XXX: Call this with varying sizes for the image.
+ *****************************************************************************/
+int test04( void )
+{
+    bool testStatus = true;
+    psImage *imgData = psImageAlloc(TST04_NUM_COLS, TST04_NUM_ROWS, PS_TYPE_F32);
+    psImageInit(imgData, TST04_SKY);
+    psImage *imgMask = psImageAlloc(TST04_NUM_COLS, TST04_NUM_ROWS, PS_TYPE_U8);
+    psImageInit(imgMask, 0);
+    //    psImage *imgMaskS8 = psImageAlloc(TST04_NUM_COLS, TST04_NUM_ROWS, PS_TYPE_S8);
+    //    psImageInit(imgMaskS8, 0);
+    psImage *imgDataF64 = psImageAlloc(TST04_NUM_COLS, TST04_NUM_ROWS, PS_TYPE_F64);
+    psImageInit(imgDataF64, 0.0);
+    pmPeak *tmpPeak = pmPeakAlloc((psF32) (TST04_NUM_ROWS / 2),
+                                  (psF32) (TST04_NUM_COLS / 2),
+                                  200.0,
+                                  PM_PEAK_LONE);
+    pmSource *tmpSource = pmSourceAlloc();
+    tmpSource->pixels = imgData;
+    tmpSource->mask = imgMask;
+    tmpSource->peak = tmpPeak;
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmSourceLocalSky with NULL tmpSource.  Should generate error and return FALSE.\n");
+    bool rc = pmSourceLocalSky(NULL, PS_STAT_SAMPLE_MEAN, 10.0);
+    if (rc != false) {
+        printf("TEST ERROR: pmSourceLocalSky() returned a non-FALSE pmSource.\n");
+        testStatus = false;
+    }
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmSourceLocalSky with Radius<0.0.  Should generate error and return FALSE.\n");
+    rc = pmSourceLocalSky(tmpSource, PS_STAT_SAMPLE_MEAN, -10.0);
+    if (rc != false) {
+        printf("TEST ERROR: pmSourceLocalSky() returned a non-FALSE pmSource.\n");
+        testStatus = false;
+    }
+
+    //
+    // XXX: The following code should be a separate function, and we should call it
+    // with a variety of image sizes, peaks.
+    //
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmSourceLocalSky with valid data.\n");
+    tmpPeak->x = (psF32) (TST04_NUM_ROWS / 2);
+    tmpPeak->y = (psF32) (TST04_NUM_COLS / 2);
+    rc = pmSourceLocalSky(tmpSource, PS_STAT_SAMPLE_MEAN, 10.0);
+
+    if (rc == false) {
+        printf("TEST ERROR: pmSourceLocalSky() returned a FALSE pmSource.\n");
+        testStatus = false;
+    } else {
+        if (tmpSource->peak == NULL) {
+            printf("TEST ERROR: pmSourceLocalSky() returned a NULL pmSource->peak.\n");
+            testStatus = false;
+        } else {
+            if (tmpSource->peak->x != tmpPeak->x) {
+                printf("TEST ERROR: pmSourceLocalSky() pmSource->peak->x was %d, should have been %d.\n",
+                       tmpSource->peak->x, tmpPeak->x);
+                testStatus = false;
+            }
+
+            if (tmpSource->peak->y != tmpPeak->y) {
+                printf("TEST ERROR: pmSourceLocalSky() pmSource->peak->y was %d, should have been %d.\n",
+                       tmpSource->peak->y, tmpPeak->y);
+                testStatus = false;
+            }
+
+            if (tmpSource->peak->counts != tmpPeak->counts) {
+                printf("TEST ERROR: pmSourceLocalSky() pmSource->peak->counts was %f, should have been %f.\n",
+                       tmpSource->peak->counts, tmpPeak->counts);
+                testStatus = false;
+            }
+
+            if (tmpSource->peak->class != tmpPeak->class) {
+                printf("TEST ERROR: pmSourceLocalSky() pmSource->peak->class was %d, should have been %d.\n",
+                       tmpSource->peak->class, tmpPeak->class);
+                testStatus = false;
+            }
+        }
+
+        if (tmpSource->moments == NULL) {
+            printf("TEST ERROR: pmSourceLocalSky() returned a NULL pmSource->moments.\n");
+            testStatus = false;
+        } else {
+            if (tmpSource->moments->Sky != TST04_SKY) {
+                printf("TEST ERROR: pmSourceLocalSky() pmSource->moments->Sky was %f, should have been %f.\n", tmpSource->moments->Sky, TST04_SKY);
+                testStatus = false;
+            }
+        }
+    }
+
+    printf("----------------------------------------------------------------------------------\n");
+    psFree(tmpSource);
+    //    psFree(imgData);
+    //    psFree(imgDataF64);
+    //    psFree(imgMask);
+    //    psFree(imgMaskS8);
+    return(testStatus);
+}
+
+#define TST05_NUM_ROWS 100
+#define TST05_NUM_COLS 100
+#define TST05_SKY 20.0
+#define TST05_INNER_RADIUS 3
+#define TST05_OUTER_RADIUS 5
+/******************************************************************************
+test05(): We first test pmSourceMoments() with various NULL and unallowable
+input parameters.
+ 
+XXX: Should we produce tests with boundary numbers for the inner/outer radius?
+ 
+XXX: Call this with varying sizes for the image.
+ 
+XXX: The actual values of the moments are not tested.
+ *****************************************************************************/
+int test05( void )
+{
+    bool testStatus = true;
+    psImage *imgData = psImageAlloc(TST04_NUM_COLS, TST04_NUM_ROWS, PS_TYPE_F32);
+    psImageInit(imgData, TST04_SKY);
+    psImage *imgMask = psImageAlloc(TST04_NUM_COLS, TST04_NUM_ROWS, PS_TYPE_U8);
+    psImageInit(imgMask, 0);
+    pmPeak *tmpPeak = pmPeakAlloc((psF32) (TST04_NUM_ROWS / 2),
+                                  (psF32) (TST04_NUM_COLS / 2),
+                                  200.0,
+                                  PM_PEAK_LONE);
+    pmSource *tmpSource = pmSourceAlloc();
+    tmpSource->pixels = imgData;
+    tmpSource->mask = imgMask;
+    tmpSource->peak = tmpPeak;
+    psBool rc = pmSourceLocalSky(tmpSource, PS_STAT_SAMPLE_MEAN, 10.0);
+
+    if (rc == false) {
+        printf("TEST ERROR: pmSourceLocalSky() returned a FALSE pmSource.\n");
+        testStatus = false;
+    }
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmSourceMoments with NULL pmSource.  Should generate error and return FALSE.\n");
+    rc = pmSourceMoments(NULL, 10.0);
+    if (rc != false) {
+        printf("TEST ERROR: pmSourceMoments() returned TRUE.\n");
+        testStatus = false;
+    }
+    // XXX: test with pmSource->peaks NULL
+    // XXX: test with pmSource->pixels NULL
+    // XXX: test with pmSource->mask NULL
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmSourceMoments with radius < 0.0.  Should generate error and return FALSE.\n");
+    rc = pmSourceMoments(tmpSource, -10.0);
+    if (rc != false) {
+        printf("TEST ERROR: pmSourceMoments() returned TRUE.\n");
+        testStatus = false;
+    }
+
+    printf("----------------------------------------------------------------------------------\n");
+    psFree(tmpSource);
+    return(testStatus);
+
+}
+
+#define TST09_NUM_ROWS 70
+#define TST09_NUM_COLS 70
+#define TST09_SKY 5.0
+#define TST09_INNER_RADIUS 3
+#define TST09_OUTER_RADIUS 10
+#define LEVEL (TST09_SKY + 10.0)
+/******************************************************************************
+test09(): We first test pmSourceContour() with various NULL and unallowable
+input parameters.
+ 
+XXX: We don't verify the numbers.
+ *****************************************************************************/
+int test09( void )
+{
+    bool testStatus = true;
+    psImage *imgData = psImageAlloc(TST09_NUM_COLS, TST09_NUM_ROWS, PS_TYPE_F32);
+    psImageInit(imgData, TST09_SKY);
+    psImage *imgMask = psImageAlloc(TST09_NUM_COLS, TST09_NUM_ROWS, PS_TYPE_U8);
+    psImageInit(imgMask, 0);
+    pmPeak *tmpPeak = pmPeakAlloc((psF32) (TST09_NUM_ROWS / 2),
+                                  (psF32) (TST09_NUM_COLS / 2),
+                                  200.0,
+                                  PM_PEAK_LONE);
+    pmSource *tmpSource = pmSourceAlloc();
+    tmpSource->pixels = imgData;
+    tmpSource->mask = imgMask;
+    tmpSource->peak = tmpPeak;
+    psBool rc = pmSourceLocalSky(tmpSource, PS_STAT_SAMPLE_MEAN, 10.0);
+    if (rc == false) {
+        printf("TEST ERROR: pmSourceLocalSky() returned a FALSE pmSource.\n");
+        testStatus = false;
+    }
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmSourceContour with NULL pmSource .  Should generate error, return FALSE.\n");
+    rc = pmSourceContour(NULL, imgData, LEVEL, PS_CONTOUR_CRUDE);
+    if (rc != false) {
+        printf("TEST ERROR: pmSourceContour() returned TRUE.\n");
+        testStatus = false;
+        psFree(rc);
+    }
+
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmSourceContour with NULL psImage .  Should generate error, return FALSE.\n");
+    rc = pmSourceContour(tmpSource, NULL, LEVEL, PS_CONTOUR_CRUDE);
+    if (rc != FALSE) {
+        printf("TEST ERROR: pmSourceContour() returned TRUE.\n");
+        testStatus = false;
+        psFree(rc);
+    }
+
+    //
+    // XXX: pmSourceContour() has a problem with contour tops/bottoms.
+    // Must correct this.
+    //
+    if (1) {
+        printf("----------------------------------------------------------------------------------\n");
+        printf("Calling pmSourceContour with acceptable data.\n");
+        printf("NOTE: must figure out the parameters for this test to be meaningful.\n");
+        tmpSource->modelPSF->params->data.F32[0] = TST09_SKY;
+        tmpSource->modelPSF->params->data.F32[1] = 15.0;
+        tmpSource->modelPSF->params->data.F32[2] = (psF32) (TST09_NUM_ROWS / 2);
+        tmpSource->modelPSF->params->data.F32[3] = (psF32) (TST09_NUM_COLS / 2);
+        tmpSource->modelPSF->params->data.F32[4] = 2.0;
+        tmpSource->modelPSF->params->data.F32[5] = 2.0;
+        tmpSource->modelPSF->params->data.F32[6] = 2.0;
+        rc = pmSourceContour(tmpSource, imgData, LEVEL, PS_CONTOUR_CRUDE);
+        if (rc == false) {
+            printf("TEST ERROR: pmSourceContour() returned FALSE.\n");
+            testStatus = false;
+        } else {
+            psFree(rc);
+        }
+    }
+
+    psFree(tmpSource);
+    return(testStatus);
+}
+
+#define TST15_NUM_ROWS 100
+#define TST15_NUM_COLS 100
+#define TST15_SKY 10.0
+#define TST15_INNER_RADIUS 3
+#define TST15_OUTER_RADIUS 5
+/******************************************************************************
+test15(): We first test pmSourceAddModel() with various NULL and unallowable
+input parameters.
+ 
+XXX: We don't verify the numbers.
+ *****************************************************************************/
+/*
+int test15( void )
+{
+    bool testStatus = true;
+    psImage *imgData = psImageAlloc(TST15_NUM_COLS, TST15_NUM_ROWS, PS_TYPE_F32);
+    psImageInit(imgData, TST15_SKY);
+    psImage *imgMask = psImageAlloc(TST15_NUM_COLS, TST15_NUM_ROWS, PS_TYPE_U8);
+    psImageInit(imgMask, 0);
+    pmPeak *tmpPeak = pmPeakAlloc((psF32) (TST15_NUM_ROWS / 2),
+                                  (psF32) (TST15_NUM_COLS / 2),
+                                  200.0,
+                                  PM_PEAK_LONE);
+    pmSource *tmpSource = pmSourceAlloc();
+    tmpSource->pixels = imgData;
+    tmpSource->mask = imgMask;
+    tmpSource->peak = tmpPeak;
+    psBool rc = pmSourceLocalSky(tmpSource, PS_STAT_SAMPLE_MEAN, 10.0);
+    if (rc == false) {
+        printf("TEST ERROR: pmSourceLocalSky() returned a FALSE pmSource.\n");
+        testStatus = false;
+    }
+ 
+ 
+    tmpSource->modelPSF = pmModelAlloc(PS_MODEL_GAUSS);
+    tmpSource->modelPSF->params->data.F32[0] = 5.0;
+    tmpSource->modelPSF->params->data.F32[1] = 70.0;
+    tmpSource->modelPSF->params->data.F32[2] = (psF32) (TST15_NUM_ROWS / 2);
+    tmpSource->modelPSF->params->data.F32[3] = (psF32) (TST15_NUM_COLS / 2);
+    tmpSource->modelPSF->params->data.F32[4] = 1.0;
+    tmpSource->modelPSF->params->data.F32[5] = 1.0;
+    tmpSource->modelPSF->params->data.F32[6] = 2.0;
+ 
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmSourceAddModel with NULL psImage.  Should generate error, return FALSE.\n");
+    rc = pmSourceAddModel(NULL, tmpSource, true);
+    if (rc == true) {
+        printf("TEST ERROR: pmSourceAddModel() returned TRUE.\n");
+        testStatus = false;
+    }
+ 
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmSourceAddModel with NULL psSrc.  Should generate error, return FALSE.\n");
+    rc = pmSourceAddModel(imgData, NULL, true);
+    if (rc == true) {
+        printf("TEST ERROR: pmSourceAddModel() returned TRUE.\n");
+        testStatus = false;
+    }
+ 
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmSourceAddModel with acceptable data.\n");
+    rc = pmSourceAddModel(imgData, tmpSource, true);
+    if (rc != true) {
+        printf("TEST ERROR: pmSourceAddModel() returned FALSE.\n");
+        testStatus = false;
+    }
+ 
+    psFree(tmpSource);
+    psFree(imgData);
+    return(testStatus);
+}
+*/
+
+#define TST16_NUM_ROWS 100
+#define TST16_NUM_COLS 100
+#define TST16_SKY 10.0
+#define TST16_INNER_RADIUS 3
+#define TST16_OUTER_RADIUS 5
+/******************************************************************************
+test16(): We first test pmSourceSubModel() with various NULL and unallowable
+input parameters.
+ 
+XXX: We don't verify the numbers.
+ *****************************************************************************/
+/*
+int test16( void )
+{
+    bool testStatus = true;
+    psImage *imgData = psImageAlloc(TST16_NUM_COLS, TST16_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < imgData->numRows; i++) {
+        for (psS32 j = 0 ; j < imgData->numCols; j++) {
+            imgData->data.F32[i][j] = TST16_SKY;
+        }
+    }
+    pmSource *tmpSource = NULL;
+    psBool rc = false;
+ 
+    pmPeak *tmpPeak = pmPeakAlloc((psF32) (TST16_NUM_ROWS / 2),
+                                  (psF32) (TST16_NUM_COLS / 2),
+                                  200.0,
+                                  PM_PEAK_LONE);
+ 
+    printf("Calling pmSourceLocalSky with valid data.\n");
+    tmpPeak->x = (psF32) (TST16_NUM_ROWS / 2);
+    tmpPeak->y = (psF32) (TST16_NUM_COLS / 2);
+    tmpSource = pmSourceLocalSky(imgData,
+                                 tmpPeak,
+                                 PS_STAT_SAMPLE_MEAN,
+                                 (psF32) TST16_INNER_RADIUS,
+                                 (psF32) TST16_OUTER_RADIUS);
+ 
+    if (tmpSource == NULL) {
+        printf("TEST ERROR: pmSourceLocalSky() returned a NULL pmSource.\n");
+        testStatus = false;
+    }
+ 
+    tmpSource->modelPSF = pmModelAlloc(PS_MODEL_GAUSS);
+    tmpSource->modelPSF->params->data.F32[0] = 5.0;
+    tmpSource->modelPSF->params->data.F32[1] = 70.0;
+    tmpSource->modelPSF->params->data.F32[2] = (psF32) (TST16_NUM_ROWS / 2);
+    tmpSource->modelPSF->params->data.F32[3] = (psF32) (TST16_NUM_COLS / 2);
+    tmpSource->modelPSF->params->data.F32[4] = 1.0;
+    tmpSource->modelPSF->params->data.F32[5] = 1.0;
+    tmpSource->modelPSF->params->data.F32[6] = 2.0;
+ 
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmSourceSubModel with NULL psImage.  Should generate error, return FALSE.\n");
+    rc = pmSourceSubModel(NULL, tmpSource, true);
+    if (rc == true) {
+        printf("TEST ERROR: pmSourceSubModel() returned TRUE.\n");
+        testStatus = false;
+    }
+ 
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmSourceSubModel with NULL psSrc.  Should generate error, return FALSE.\n");
+    rc = pmSourceSubModel(imgData, NULL, true);
+    if (rc == true) {
+        printf("TEST ERROR: pmSourceSubModel() returned TRUE.\n");
+        testStatus = false;
+    }
+ 
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmSourceSubModel with acceptable data.\n");
+    rc = pmSourceSubModel(imgData, tmpSource, true);
+    if (rc != true) {
+        printf("TEST ERROR: pmSourceSubModel() returned FALSE.\n");
+        testStatus = false;
+    }
+ 
+    psFree(tmpSource);
+    psFree(imgData);
+    return(testStatus);
+}
+*/
+
+#define TST20_NUM_ROWS 100
+#define TST20_NUM_COLS 100
+#define TST20_SKY 10.0
+#define TST20_INNER_RADIUS 3
+#define TST20_OUTER_RADIUS 5
+/******************************************************************************
+test20(): We first test pmSourceSubModel() with various NULL and unallowable
+input parameters.
+ 
+XXX: We don't verify the numbers.
+ *****************************************************************************/
+/*
+int test20( void )
+{
+    bool testStatus = true;
+    psImage *imgData = psImageAlloc(TST20_NUM_COLS, TST20_NUM_ROWS, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < imgData->numRows; i++) {
+        for (psS32 j = 0 ; j < imgData->numCols; j++) {
+            imgData->data.F32[i][j] = TST20_SKY;
+        }
+    }
+    pmSource *tmpSource = NULL;
+    psBool rc = false;
+ 
+    pmPeak *tmpPeak = pmPeakAlloc((psF32) (TST20_NUM_ROWS / 2),
+                                  (psF32) (TST20_NUM_COLS / 2),
+                                  200.0,
+                                  PM_PEAK_LONE);
+ 
+    printf("Calling pmSourceLocalSky with valid data.\n");
+    tmpPeak->x = (psF32) (TST20_NUM_ROWS / 2);
+    tmpPeak->y = (psF32) (TST20_NUM_COLS / 2);
+    tmpSource = pmSourceLocalSky(imgData,
+                                 tmpPeak,
+                                 PS_STAT_SAMPLE_MEAN,
+                                 (psF32) TST20_INNER_RADIUS,
+                                 (psF32) TST20_OUTER_RADIUS);
+ 
+    if (tmpSource == NULL) {
+        printf("TEST ERROR: pmSourceLocalSky() returned a NULL pmSource.\n");
+        testStatus = false;
+    }
+ 
+    tmpSource->modelPSF = pmModelAlloc(PS_MODEL_GAUSS);
+ 
+ 
+    tmpSource->modelPSF->params->data.F32[0] = 5.0;
+    tmpSource->modelPSF->params->data.F32[1] = 70.0;
+    tmpSource->modelPSF->params->data.F32[2] = (psF32) (TST20_NUM_ROWS / 2);
+    tmpSource->modelPSF->params->data.F32[3] = (psF32) (TST20_NUM_COLS / 2);
+    tmpSource->modelPSF->params->data.F32[4] = 1.0;
+    tmpSource->modelPSF->params->data.F32[5] = 1.0;
+    tmpSource->modelPSF->params->data.F32[6] = 2.0;
+ 
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmSourceFitModel with NULL psImage.  Should generate error, return FALSE.\n");
+    rc = pmSourceFitModel(tmpSource, NULL);
+    if (rc == true) {
+        printf("TEST ERROR: pmSourceFitModel() returned TRUE.\n");
+        testStatus = false;
+    }
+ 
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmSourceFitModel with NULL pmSource.  Should generate error, return FALSE.\n");
+    rc = pmSourceFitModel(NULL, imgData);
+    if (rc == true) {
+        printf("TEST ERROR: pmSourceFitModel() returned TRUE.\n");
+        testStatus = false;
+    }
+ 
+    printf("----------------------------------------------------------------------------------\n");
+    printf("Calling pmSourceFitModel with acceptable data.\n");
+    rc = pmSourceFitModel(tmpSource, imgData);
+    printf("pmSourceFitModel returned %d\n", rc);
+ 
+    // XXX: Memory leaks are not being tested
+    psVector *junk = psVectorAlloc(10, PS_TYPE_F32);
+    junk->data.F32[0] = 0.0;
+ 
+    psFree(tmpSource);
+    psFree(imgData);
+    return(testStatus);
+}
+*/
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/pstap/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/pstap/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/pstap/.cvsignore	(revision 22158)
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/pstap/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/pstap/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/pstap/Makefile.am	(revision 22158)
@@ -0,0 +1,1 @@
+SUBDIRS = src
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/pstap/src/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/pstap/src/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/pstap/src/.cvsignore	(revision 22158)
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+libpstap.la
+pstap.lo
+.deps
+.libs
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/pstap/src/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/pstap/src/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/pstap/src/Makefile.am	(revision 22158)
@@ -0,0 +1,18 @@
+
+AM_CPPFLAGS = \
+	$(SRCINC) \
+	-I$(top_srcdir)/test/tap/src \
+	-I$(top_srcdir)/test/pstap/src \
+	$(PSMODULES_CFLAGS)
+
+AM_LDFLAGS = \
+	$(top_builddir)/src/libpsmodules.la  \
+	$(top_builddir)/test/tap/src/libtap.la \
+	$(PSMODULES_LIBS)
+
+TEST_LTLIBS = libpstap.la
+libpstap_la_SOURCES = pstap.c
+noinst_HEADERS = pstap.h
+
+noinst_LTLIBRARIES = $(TEST_LTLIBS)
+
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/pstap/src/pstap.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/pstap/src/pstap.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/pstap/src/pstap.c	(revision 22158)
@@ -0,0 +1,6 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <tap.h>
+#include <pslib.h>
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/pstap/src/pstap.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/pstap/src/pstap.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/pstap/src/pstap.h	(revision 22158)
@@ -0,0 +1,63 @@
+#include <pslib.h>
+
+#include "tap.h"
+
+#define done() ok(psMemCheckLeaks(0, NULL, stdout, false) == 0, "Memory Leaks"); return exit_status()
+
+        # define mem() ok(psMemCheckLeaks(psMemGetLastId(), NULL, stdout, false) == 0, "Memory Leaks")
+
+        # define checkLeaks false
+
+        # define checkMem() if(checkLeaks) mem()
+
+            # ifdef __GNUC__
+
+            // write a comment which is counted as a test (and swallowed by prove)
+            # define note(A, ...) _gen_result(1, __func__, __FILE__, __LINE__, A, ## __VA_ARGS__);
+
+// use to test the value of a float
+# define ok_float(VALUE,EXPECT,COMMENT, ...)\
+ok((fabsf((VALUE)-(EXPECT)) < FLT_EPSILON), COMMENT, ## __VA_ARGS__);
+
+// use to test the value of a double
+# define ok_double(VALUE,EXPECT,COMMENT, ...)\
+ok((fabs((VALUE)-(EXPECT)) < DBL_EPSILON), COMMENT, ## __VA_ARGS__);
+
+// use to test the value of a float within a defined tolerance
+# define ok_float_tol(VALUE,EXPECT,TOL,COMMENT, ...)\
+ok((fabsf((VALUE)-(EXPECT)) < (TOL)), COMMENT, ## __VA_ARGS__);
+
+// use to test the value of a double within a defined tolerance
+# define ok_double_tol(VALUE,EXPECT,TOL,COMMENT, ...)\
+ok((fabs((VALUE)-(EXPECT)) < (TOL)), COMMENT, ## __VA_ARGS__);
+
+# define ok_str(VALUE,EXPECT,COMMENT, ...)\
+ok(strcmp(VALUE, EXPECT) == 0, COMMENT, ## __VA_ARGS__);
+
+#elif __STDC_VERSION__ >= 199901L /* __GNUC__ */
+
+// write a comment which is counted as a test (and swallowed by prove)
+# define note(A, ...) _gen_result(1, __func__, __FILE__, __LINE__, A, ...);
+
+// use to test the value of a float
+# define ok_float(VALUE,EXPECT, ...)\
+ok((fabsf((VALUE)-(EXPECT)) < FLT_EPSILON), __VA_ARGS__);
+
+// use to test the value of a double
+# define ok_double(VALUE,EXPECT, ...)\
+ok((fabs((VALUE)-(EXPECT)) < DBL_EPSILON), __VA_ARGS__);
+
+// use to test the value of a float
+# define ok_float_tol(VALUE,EXPECT,TOL, ...)\
+ok((fabsf((VALUE)-(EXPECT)) < (TOL)), __VA_ARGS__);
+
+// use to test the value of a double
+# define ok_double_tol(VALUE,EXPECT,TOL, ...)\
+ok((fabs((VALUE)-(EXPECT)) < )(TOL)), __VA_ARGS__);
+
+# define ok_str(VALUE,EXPECT, ...)\
+ok(strcmp(VALUE, EXPECT) == 0, __VA_ARGS__);
+
+#else /* __STDC_VERSION__ */
+# error "Needs gcc or C99 compiler for variadic macros."
+#endif /* __STDC_VERSION__ */
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/.cvsignore	(revision 22158)
@@ -0,0 +1,13 @@
+.in
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+config.log
+config.status
+configure
+libtool
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/INSTALL
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/INSTALL	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/INSTALL	(revision 22158)
@@ -0,0 +1,8 @@
+Quick Installation
+
+    ./configure
+    make
+    make check
+    make install
+
+Run "configure --help" for additional options.
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/LICENSE
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/LICENSE	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/LICENSE	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/Makefile.am	(revision 22158)
@@ -0,0 +1,5 @@
+SUBDIRS  = src
+#SUBDIRS += tests
+
+prove:
+	prove -v -r
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/README
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/README	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/README	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/bootstrap.sh
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/bootstrap.sh	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/bootstrap.sh	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/compile
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/compile	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/compile	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/configure.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/configure.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/configure.in	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/src/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/src/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/src/.cvsignore	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/src/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/src/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/src/Makefile.am	(revision 22158)
@@ -0,0 +1,8 @@
+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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/src/tap.3
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/src/tap.3	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/src/tap.3	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/src/tap.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/src/tap.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/src/tap.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/src/tap.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/src/tap.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/src/tap.h	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/.cvsignore	(revision 22158)
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/Makefile.am	(revision 22158)
@@ -0,0 +1,7 @@
+SUBDIRS=	diag
+SUBDIRS+=	fail
+SUBDIRS+=	ok
+SUBDIRS+=	pass
+SUBDIRS+=	plan
+SUBDIRS+=	skip
+SUBDIRS+=	todo
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/README
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/README	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/README	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/diag/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/diag/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/diag/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/diag/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/diag/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/diag/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/diag/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/diag/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/diag/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/diag/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/diag/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/diag/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/diag/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/diag/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/diag/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/fail/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/fail/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/fail/.cvsignore	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/fail/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/fail/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/fail/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/fail/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/fail/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/fail/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/fail/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/fail/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/fail/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/fail/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/fail/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/fail/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/.cvsignore	(revision 22158)
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/Makefile.am	(revision 22158)
@@ -0,0 +1,3 @@
+SUBDIRS  =	ok
+SUBDIRS +=	ok-hash
+SUBDIRS +=	ok-numeric
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-hash/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-hash/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-hash/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-hash/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-hash/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-hash/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-hash/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-hash/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-hash/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-hash/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-hash/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-hash/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-hash/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-hash/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-hash/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-numeric/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-numeric/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-numeric/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-numeric/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-numeric/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-numeric/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-numeric/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-numeric/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-numeric/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-numeric/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-numeric/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-numeric/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-numeric/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-numeric/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok-numeric/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/ok/ok/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/pass/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/pass/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/pass/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/pass/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/pass/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/pass/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/pass/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/pass/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/pass/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/pass/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/pass/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/pass/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/pass/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/pass/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/pass/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/.cvsignore	(revision 22158)
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no-tests/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no-tests/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no-tests/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no-tests/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no-tests/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no-tests/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no-tests/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no-tests/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no-tests/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no-tests/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no-tests/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no-tests/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no-tests/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no-tests/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no-tests/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no_plan/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no_plan/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no_plan/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no_plan/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no_plan/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no_plan/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no_plan/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no_plan/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no_plan/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no_plan/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no_plan/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no_plan/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no_plan/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no_plan/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/no_plan/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/not-enough-tests/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/not-enough-tests/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/not-enough-tests/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/not-enough-tests/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/not-enough-tests/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/not-enough-tests/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/not-enough-tests/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/not-enough-tests/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/not-enough-tests/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/not-enough-tests/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/not-enough-tests/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/not-enough-tests/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/not-enough-tests/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/not-enough-tests/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/not-enough-tests/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/sane/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/sane/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/sane/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/sane/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/sane/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/sane/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/sane/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/sane/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/sane/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/sane/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/sane/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/sane/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/sane/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/sane/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/sane/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/skip_all/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/skip_all/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/skip_all/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/skip_all/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/skip_all/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/skip_all/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/skip_all/plan.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/skip_all/plan.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/skip_all/plan.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/skip_all/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/skip_all/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/skip_all/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/skip_all/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/skip_all/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/skip_all/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/skip_all/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/skip_all/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/skip_all/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-plans/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-plans/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-plans/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-plans/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-plans/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-plans/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-plans/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-plans/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-plans/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-plans/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-plans/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-plans/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-plans/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-plans/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-plans/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-tests/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-tests/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-tests/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-tests/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-tests/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-tests/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-tests/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-tests/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-tests/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-tests/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-tests/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-tests/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-tests/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-tests/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/plan/too-many-tests/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/skip/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/skip/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/skip/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/skip/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/skip/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/skip/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/skip/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/skip/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/skip/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/skip/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/skip/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/skip/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/skip/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/skip/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/skip/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/todo/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/todo/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/todo/.cvsignore	(revision 22158)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/todo/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/todo/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/todo/Makefile.am	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/todo/test.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/todo/test.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/todo/test.c	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/todo/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/todo/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/todo/test.pl	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/todo/test.t
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/todo/test.t	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/tap/tests/todo/test.t	(revision 22158)
@@ -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: /branches/eam_branches/eam_branch_20080719/psModules/test/test.pl
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psModules/test/test.pl	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psModules/test/test.pl	(revision 22158)
@@ -0,0 +1,31 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2006  Joshua Hoblitt
+#
+# $Id: test.pl,v 1.1 2006-09-23 02:47:58 magnier Exp $
+
+use strict;
+use warnings FATAL => qw( all);
+
+use vars qw($VERSION);
+$VERSION = '0.01';
+
+use File::Find::Rule;
+use Cwd;
+
+my $rule = File::Find::Rule->new;
+# ignore .lib directories
+$rule->or($rule->new
+        ->directory
+        ->name('.libs')
+        ->prune
+        ->discard,
+        $rule->new
+    );
+$rule->name(qr/^tap_[^.]*$/)
+        ->maxdepth(2)
+        ->relative;
+
+my @test_files = $rule->in(getcwd());
+
+system("prove @test_files");
Index: /branches/eam_branches/eam_branch_20080719/psphot/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/.cvsignore	(revision 22158)
@@ -0,0 +1,19 @@
+bin
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+compile
+config.log
+config.status
+configure
+depcomp
+install-sh
+missing
+config.guess
+libtool
+ltmain.sh
+stamp-h1
+config.sub
+psphot.pc
+psphot-config
Index: /branches/eam_branches/eam_branch_20080719/psphot/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/Makefile.am	(revision 22158)
@@ -0,0 +1,12 @@
+SUBDIRS = src
+
+CLEANFILES = *.pyc *~ core core.*
+
+bin_SCRIPTS = psphot-config 
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA= psphot.pc
+
+EXTRA_DIST = \
+	psphot-config.in \
+	psphot.pc.in \
+	autogen.sh
Index: /branches/eam_branches/eam_branch_20080719/psphot/autogen.sh
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/autogen.sh	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/autogen.sh	(revision 22158)
@@ -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=psphot
+TEST_TYPE=-f
+# change this to be a unique filename in the top level dir
+FILE=autogen.sh
+
+DIE=0
+
+LIBTOOLIZE=libtoolize
+ACLOCAL="aclocal $ACLOCAL_FLAGS"
+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: /branches/eam_branches/eam_branch_20080719/psphot/configure.ac
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/configure.ac	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/configure.ac	(revision 22158)
@@ -0,0 +1,216 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.61)
+
+AC_INIT([psphot], [0.9.0], [ipp-support@ifa.hawaii.edu])
+AC_CONFIG_SRCDIR([src])
+
+AM_INIT_AUTOMAKE([1.6 foreign dist-bzip2])
+AM_CONFIG_HEADER([src/config.h])
+AM_MAINTAINER_MODE
+
+IPP_STDCFLAGS
+
+AC_LANG(C)
+AC_GNU_SOURCE
+AC_PROG_CC_C99
+AC_PROG_INSTALL
+AC_PROG_LIBTOOL
+AC_SYS_LARGEFILE
+
+dnl ------------------------------------------------------------
+
+AC_PATH_PROG([ERRORCODES], [psParseErrorCodes], [missing])
+if test "$ERRORCODES" = "missing" ; then
+  AC_MSG_ERROR([psParseErrorCodes is required])
+fi
+
+dnl ------------------ kapa,libkapa options -------------------------
+dnl -- libkapa implies the requirement for libpng, libjpeg as well --
+
+dnl save LIBS/CFLAGS/LDFLAGS
+TMP_LIBS=${LIBS}
+TMP_CFLAGS=${CFLAGS}
+TMP_LDFLAGS=${LDFLAGS}
+TMP_CPPFLAGS=${CPPFLAGS}
+
+dnl test for command-line options: use ohana-config if not supplied
+KAPA_CFLAGS_CONFIG="true"
+KAPA_LIBS_CONFIG="true"
+AC_ARG_WITH(kapa,
+[AS_HELP_STRING(--with-kapa=DIR,Specify location of libkapa)],
+[KAPA_CFLAGS="-I$withval/include" KAPA_LIBS="-L$withval/lib" 
+ KAPA_CFLAGS_CONFIG="false"       KAPA_LIBS_CONFIG="false"])
+AC_ARG_WITH(kapa-include,
+[AS_HELP_STRING(--with-kapa-include=DIR,Specify libkapa include directory.)],
+[KAPA_CFLAGS="-I$withval" KAPA_CFLAGS_CONFIG="false"])
+AC_ARG_WITH(kapa-lib,
+[AS_HELP_STRING(--with-kapa-lib=DIR,Specify libkapa library directory.)],
+[KAPA_LIBS="-L$withval" KAPA_LIBS_CONFIG="false"])
+
+echo "KAPA_CFLAGS_CONFIG: $KAPA_CFLAGS_CONFIG"
+echo "KAPA_LIBS_CONFIG: $KAPA_LIBS_CONFIG"
+echo "KAPA_CFLAGS: $KAPA_CFLAGS"
+echo "KAPA_LIBS: $KAPA_LIBS"
+
+dnl HAVE_KAPA is set to false if any of the tests fail
+HAVE_KAPA="true"
+AC_MSG_NOTICE([checking for libkapa])
+if test "$KAPA_CFLAGS_CONFIG" = "true" -o "$KAPA_LIBS_CONFIG" = "true"; then
+  AC_MSG_NOTICE([kapa info supplied by ohana-config])
+  KAPA_CONFIG=`which ohana-config`
+  AC_CHECK_FILE($KAPA_CONFIG,[],
+    [HAVE_KAPA="false"; AC_MSG_WARN([libkapa is not found: output plots disabled.  Obtain libkapa at http://kiawe.ifa.hawaii.edu/Elixir/Ohana or use --with-kapa to specify location])])
+  
+  echo "HAVE_KAPA: $HAVE_KAPA"
+  echo "KAPA_CFLAGS_CONFIG: $KAPA_CFLAGS_CONFIG"
+
+  if test "$HAVE_KAPA" = "true" -a "$KAPA_CFLAGS_CONFIG" = "true" ; then
+   AC_MSG_NOTICE([libkapa cflags info supplied by ohana-config])
+   AC_MSG_CHECKING([libkapa cflags])
+   KAPA_CFLAGS="`${KAPA_CONFIG} --cflags`"
+   AC_MSG_RESULT([${KAPA_CFLAGS}])
+  fi
+
+  if test "$HAVE_KAPA" = "true" -a "$KAPA_LIBS_CONFIG" = "true" ; then
+   AC_MSG_NOTICE([libkapa ldflags info supplied by ohana-config])
+   AC_MSG_CHECKING([libkapa ldflags])
+   KAPA_LIBS="`${KAPA_CONFIG} --libs` -lX11"
+   AC_MSG_RESULT([${KAPA_LIBS}])
+  fi
+fi
+
+if test "$HAVE_KAPA" = "true" ; then
+ AC_MSG_NOTICE([libkapa supplied])
+ PSPHOT_CFLAGS="${PSPHOT_CFLAGS} ${KAPA_CFLAGS}"
+ PSPHOT_LIBS="${PSPHOT_LIBS} ${KAPA_LIBS}"
+else
+ AC_MSG_NOTICE([libkapa ignored])
+fi
+
+dnl HAVE_KAPA is set to false if any of the tests fail
+dnl HAVE_KAPA=true
+dnl AC_CHECK_HEADERS([kapa.h],
+dnl  [PSPHOT_CFLAGS="$PSPHOT_CFLAGS $KAPA_CFLAGS" AC_SUBST(KAPA_CFLAGS)],
+dnl  [HAVE_KAPA=false; AC_MSG_WARN([libkapa headers not found: output plots disabled.  Obtain libkapa at http://kiawe.ifa.hawaii.edu/Elixir/Ohana or use --with-kapa to specify location.])]
+dnl )
+dnl AC_CHECK_LIB(kapa,KapaInitGraph,
+dnl  [PSPHOT_LIBS="$PSPHOT_LIBS $JPEG_LDFLAGS -ljpeg"],  
+dnl  [HAVE_KAPA=false; AC_MSG_WARN([libkapa headers not found: output plots disabled.  Obtain libkapa at http://kiawe.ifa.hawaii.edu/Elixir/Ohana or use --with-kapa to specify location.])],[-lm]
+dnl )
+
+dnl restore the CFLAGS/LDFLAGS
+LIBS=${TMP_LIBS}
+CFLAGS=${TMP_CFLAGS}
+LDFLAGS=${TMP_LDFLAGS}
+CPPFLAGS=${TMP_CPPFLAGS}
+
+dnl ------------------ libjpeg options ---------------------
+
+dnl save LIBS/CFLAGS/LDFLAGS
+TMP_LIBS=${LIBS}
+TMP_CFLAGS=${CFLAGS}
+TMP_LDFLAGS=${LDFLAGS}
+TMP_CPPFLAGS=${CPPFLAGS}
+
+AC_ARG_WITH(jpeg,
+[AS_HELP_STRING(--with-jpeg=DIR,Specify location of libjpeg.)],
+[JPEG_CFLAGS="-I$withval/include"
+ JPEG_LDFLAGS="-L$withval/lib"])
+AC_ARG_WITH(jpeg-include,
+[AS_HELP_STRING(--with-jpeg-include=DIR,Specify libjpeg include directory.)],
+[JPEG_CFLAGS="-I$withval"])
+AC_ARG_WITH(jpeg-lib,
+[AS_HELP_STRING(--with-jpeg-lib=DIR,Specify libjpeg library directory.)],
+[JPEG_LDFLAGS="-L$withval"])
+
+CFLAGS="${CFLAGS} ${JPEG_CFLAGS}"
+CPPFLAGS=${CFLAGS}
+LDFLAGS="${LDFLAGS} ${JPEG_LDFLAGS}"
+
+AC_CHECK_HEADERS([jpeglib.h],
+  [PSPHOT_CFLAGS="$PSPHOT_CFLAGS $JPEG_CFLAGS" AC_SUBST(JPEG_CFLAGS)],
+  [HAVE_KAPA=false; AC_MSG_WARN([libjpeg headers not found: output plots disabled.  Obtain libjpeg from http://www.ijg.org/ or use --with-jpeg to specify location.])]
+)
+
+AC_CHECK_LIB(jpeg,jpeg_CreateCompress,
+  [PSPHOT_LIBS="$PSPHOT_LIBS $JPEG_LDFLAGS -ljpeg"],
+  [HAVE_KAPA=false; AC_MSG_WARN([libjpeg library not found: output plots disabled.  Obtain libjpeg from http://www.ijg.org/ or use --with-jpeg to specify location.])]
+)
+
+dnl restore the CFLAGS/LDFLAGS
+LIBS=${TMP_LIBS}
+CFLAGS=${TMP_CFLAGS}
+LDFLAGS=${TMP_LDFLAGS}
+CPPFLAGS=${TMP_CPPFLAGS}
+
+dnl ------------------ libpng options ---------------------
+
+dnl save LIBS/CFLAGS/LDFLAGS
+TMP_LIBS=${LIBS}
+TMP_CFLAGS=${CFLAGS}
+TMP_LDFLAGS=${LDFLAGS}
+TMP_CPPFLAGS=${CPPFLAGS}
+
+AC_ARG_WITH(png,
+[AS_HELP_STRING(--with-png=DIR,Specify location of libpng.)],
+[PNG_CFLAGS="-I$withval/include"
+ PNG_LDFLAGS="-L$withval/lib"])
+AC_ARG_WITH(png-include,
+[AS_HELP_STRING(--with-png-include=DIR,Specify libpng include directory.)],
+[PNG_CFLAGS="-I$withval"])
+AC_ARG_WITH(png-lib,
+[AS_HELP_STRING(--with-png-lib=DIR,Specify libpng library directory.)],
+[PNG_LDFLAGS="-L$withval"])
+
+CFLAGS="${CFLAGS} ${PNG_CFLAGS}"
+CPPFLAGS=${CFLAGS}
+LDFLAGS="${LDFLAGS} ${PNG_LDFLAGS}"
+
+AC_CHECK_HEADERS([png.h],
+  [PSPHOT_CFLAGS="$PSPHOT_CFLAGS $PNG_CFLAGS" AC_SUBST(PNG_CFLAGS)],
+  [HAVE_KAPA=false; AC_MSG_WARN([libpng headers not found: output plots disabled.  Obtain libpng from http://www.ijg.org/ or use --with-png to specify location.])]
+)
+
+AC_CHECK_LIB(png,png_init_io,
+  [PSPHOT_LIBS="$PSPHOT_LIBS $PNG_LDFLAGS -lpng"],
+  [HAVE_KAPA=false; AC_MSG_WARN([libpng library not found: output plots disabled.  Obtain libpng from http://www.ijg.org/ or use --with-png to specify location.])]
+)
+
+dnl restore the CFLAGS/LDFLAGS
+LIBS=${TMP_LIBS}
+CFLAGS=${TMP_CFLAGS}
+LDFLAGS=${TMP_LDFLAGS}
+CPPFLAGS=${TMP_CPPFLAGS}
+
+dnl ------------------ use kapa or not? ---------------------
+
+if test "$HAVE_KAPA" == "true" ; then
+  AC_MSG_RESULT([including plotting functions])
+  AC_DEFINE([HAVE_KAPA],[1],[enable use of libkapa])
+else
+  AC_MSG_RESULT([skipping plotting functions])
+  AC_DEFINE([HAVE_KAPA],[0],[disable use of libkapa])
+fi
+
+dnl ------------- psLib, psModules ---------------
+PKG_CHECK_MODULES([PSLIB], [pslib >= 1.0.0])
+PKG_CHECK_MODULES([PSMODULE], [psmodules >= 1.0.0])
+
+dnl Set CFLAGS for build
+IPP_STDOPTS
+
+CFLAGS="${CFLAGS=} -Wall -Werror"
+echo "PSPHOT_CFLAGS: $PSPHOT_CFLAGS"
+echo "PSPHOT_LIBS: $PSPHOT_LIBS"
+
+AC_SUBST([PSPHOT_CFLAGS])
+AC_SUBST([PSPHOT_LIBS])
+
+AC_CONFIG_FILES([
+  Makefile
+  src/Makefile
+  psphot-config
+  psphot.pc
+])
+
+AC_OUTPUT
Index: /branches/eam_branches/eam_branch_20080719/psphot/doc/2Dmodels.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/doc/2Dmodels.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/doc/2Dmodels.txt	(revision 22158)
@@ -0,0 +1,29 @@
+
+I am testing a new concept for the 2D representation of various values
+measured by psphot.  I have been using 2D polynomials to fit the
+variations of, eg, the psf parameters as a function of position in the
+images.  this has been somewhat successful, but it has also been
+fraught with a number of problems.  the worst issue has been the fact
+that the polynomial form is not physically motivated.  in some cases,
+eg the variation of the psf shape parameters, the true variations for
+real distributions are not well represented by a polynomial.  I have
+done some ad hoc tricks to get the functional form to look roughly
+like a polynomial, but this is really quite a hack.  the other problem
+is that it is difficult to decide if the polynomial does an acceptable
+job representing the variations.
+
+My new concept for modeling 2D variations in some parameter is to
+define a low-resolution 2D image to represent the variation.  The
+advantage is that the image may be define with whatever resolution may
+be sampled by the input data, and the functional form need not be
+constrained by the polynomial basis function.  
+
+** is this a poor substitute for using a chebychev polynomial as a
+   better basis function?
+
+psphot parameters which vary by position:
+
+pmPSF.params 
+pmPSF.ApTrend
+pmPSF.FluxScale (flux given normalization of 1.0)
+
Index: /branches/eam_branches/eam_branch_20080719/psphot/doc/config.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/doc/config.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/doc/config.txt	(revision 22158)
@@ -0,0 +1,56 @@
+
+# input data options
+# IMAGE             STR    file.fits
+# MASK_IMAGE	    STR    mask.fits
+# WEIGHT_IMAGE	    STR	   weight.fits
+
+# output data options
+OUTPUT_FILE	    STR	   output.smp    # output object file
+OUTPUT_MODE	    STR	   TEXT          # output mode: TEXT, OBJ, SX, CMP, CMF 
+# RESID_IMAGE	    STR	   resid.fits    # output residual image
+
+# image noise parameters
+RDNOISE             STR  HD:RDNOISE      # read-noise in electrons
+GAIN                STR  HD:GAIN         # electrons / DN
+
+# masking parameters
+XMIN                F32  32        	 # minimum valid x-coord
+XMAX                F32   0        	 # maximum valid x-coord
+YMIN                F32   1        	 # minimum valid y-coord
+YMAX                F32   0        	 # maximum valid y-coord
+SATURATION          F32  50000     	 # saturation level on this chip
+
+# image statistics parameters
+IMSTATS_NPIX        S32  100000    	 # number of pixels to use for sky estimate:
+
+# peak finding 
+PEAKS_SMOOTH_SIGMA  F32  1.0       	 # smoothing kernel sigma in pixels
+PEAKS_SMOOTH_NSIGMA F32  3.0   	   	 # smoothing kernel width in sigmas
+PEAKS_NSIGMA_LIMIT  F32  10.0  	   	 # peak significance threshold
+
+# basic object statistics
+SKY_INNER_RADIUS    F32  15		 # square annulus for local sky measurement
+SKY_OUTER_RADIUS    F32  25		 # square annulus for local sky measurement
+PSF_MOMENTS_RADIUS  F32  5
+PSF_SN_LIM          F32  100
+
+# PSF model parameters : choose the PSF model
+# list as many PSF_MODEL options as desired
+PSF_MODEL           STR  PS_MODEL_QGAUSS
+#PSF_MODEL           STR  PS_MODEL_PGAUSS
+#PSF_MODEL           STR  PS_MODEL_GAUSS
+PSF_FIT_RADIUS      F32  25		 # fitting radius for test PSF model
+
+# PSF model parameters : apply the PSF model
+PSF_FIT_NSIGMA       F32  1		 # significance for pixel included in fit
+PSF_FIT_PADDING      F32  5              # extra annulus to use for fit 
+PSF_SHAPE_NSIGMA     F32  3.0		 # max significance for shape variation
+PSF_MIN_SN           F32  2.0		 # reject objects below this significance
+PSF_MAX_CHI          F32  10.0		 # reject objects worse that this
+
+# Galaxy model parameters
+GAL_MODEL            STR  PS_MODEL_SGAUSS
+GAL_MIN_SN           F32  3
+GAL_FIT_NSIGMA       F32  1		 # significance for pixel included in fit
+GAL_FIT_PADDING      F32  5              # extra annulus to use for fit 
+GAL_MOMENTS_RADIUS   F32  9
Index: /branches/eam_branches/eam_branch_20080719/psphot/doc/footprints.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/doc/footprints.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/doc/footprints.txt	(revision 22158)
@@ -0,0 +1,43 @@
+
+pmFootprintCullPeaks is very expensive (15 - 30 msec per object) and
+must be performed on every peak.  We need to improve the speed (even
+at the cost of memory) and we need to thread it.
+
+*** pmFootprints makes use of the mask image, but it does not use the
+    master mask values.  this must be fixed!
+
+-- here is the algorithm
+
+** note: this is run once for each footprint...
+
+* the incoming footprint peak list is already sorted by brightness
+
+* loop over all peaks
+
+  * choose a threshold which is the peak flux - nsigma_delta*stdev
+    ? actually, the threshold is using the edge of the containing
+    subimage?  I'm a little confused by this.
+
+  * if the threshold is below a minimum threshold, we drop it
+    - the code is calling psArrayRemoveIndex for each of these, then decrementing i.
+      this is inefficient since psArray is not a psList.  two possible options here:
+      
+      * do not remove the dropped peaks from the array until the full
+        processing is done, then re-build the array in a single pass.
+        flag peaks to be dropped (either in the structure or with a
+        parallel vector)
+
+      * have the code build a separate 'bright peaks' array on the fly
+        then swap the new peaks out under the pmFootprint.
+
+  * psArrayRemoveIndex is used 3x in pmFootprints.c : review each case
+
+  * the subImage is divided into footprints above threshold about the
+    current peak.
+
+    - EAM : Need to disect pmFindFootprintsAtPoint.  Is it expensive
+        in this case?  Should we be calling the normal pmFootprints
+        function?
+
+
+  
Index: /branches/eam_branches/eam_branch_20080719/psphot/doc/notes.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/doc/notes.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/doc/notes.txt	(revision 22158)
@@ -0,0 +1,671 @@
+
+2008.06.25
+
+ timing : footprints
+
+ on GPC1, with FFT: 
+    pass 1 :     convolved with grow disc: 17.558344 sec
+    pass 2 :     convolved with grow disc: 8.915036 sec
+
+2008.01.31
+
+ Most of the fixes listed below have been finished except for:
+
+ * careful handling of the r ~ 0 fluxes / effective positions (for eg sersic)
+ * the EXT output parameters have not been tested
+
+ In addition, some further work to be done:
+
+ * multiple image detection
+ * multiple image fitting (including projection)
+ * optimization
+ * multi-threading
+
+ * possibly try the 'active deblending' concept that Ken from WISE is using.
+   * instead of fitting a double star with the positions floating at a
+     slightly random location, search for significant additions within
+     a grid about the central peak (say ~ 1sigma / 0.2 pix?).  
+     (note that this is a linear fit)
+
+ * for the blend groups, freeze the positions for the fainter sources
+   (consistent with the non-linear S/N threshold)
+
+ 
+
+2007.08.17
+
+ I am working on a number of cleanup / fixes.  I have made an overhaul
+ of the pmModel APIs, adding function pointers in the pmModel
+ structure to the class-specific utility functions (eg,
+ pmModel->modelFunc is the actual function which is evaluated). 
+
+ TO DO:
+
+ * update pmSourceFitSet to be able to include more than one model
+   type (currently it assumes the sources are all, eg, PSFs).  This is
+   now needed because the old implementation used the function lookups
+   which have been dropped.
+
+ * define a generic API set to handle 2D modelling of a scalar using
+   either polynomials (as the pmPSF code currently does) or an
+   image-based representation (as the psphot sky model currently
+   does).  
+
+   The image-based representation can automatically step down from NxM
+   super pixels to a smaller number based on the density of
+   measurements.  
+
+   Include ways to smooth and regularize the output result.
+
+   This mechanism can be applied to: psf parameters, aperture
+   residual, psf peak-to-flux variations, the psphot background
+   representation.
+
+ * generate and store the output radial profile for objects
+
+ * finish testing and incorportate the CR / EXT measurements
+
+ * adjustments to pixel center based on second derivatives : needed
+   for the sersic models.
+
+ * adjustments to pixel flux for extreme values (r ~ 0) : needed for
+   the sersic models.
+
+ * on psf stars : fall back on a Gaussian.
+
+ * OPTIMIZATIONS !!
+
+ * drop the model sky element : should only be in source->sky,dsky
+
+2006.11.16
+
+ensemble:
+
+  * first block: 
+    * select sources of interest / skip
+    * generate a guess model
+    * re-measure moments for saturated stars (MOVE)
+    * update peak position (MOVE to peaks)
+    * set the object radius 
+    * build temporary source copies (including pixels, mask, weight)
+
+  * second block:
+    * measure the cross-products and weights
+    * add to the sparse matrix
+
+  * build full-image mask
+  * measure coord weights
+  * build order elements
+
+  * solve for source amplitudes
+  * update models
+
+  * create psSparseBorder to solve matrix equations which have a large
+    sparse region, with a completely filled border of a smaller number
+    of rows.
+
+  * trying to modify psphotEnsemble to (1) be more general (not just
+    PSFs) and (2) fit for the sky offset.
+
+    - how is the radius for each source set?
+    
+
+2006.11.11
+
+  I am trying to define a complete set of tests to validate the
+  measurement of the photometry compared with the simulated images.
+  Part of my confusion is controlling exactly which corrections are
+  applied to the output magnitudes.  Here is the complete list:
+
+  psfMag_out = psfMag_meas + ApTrend(x,y,0.0,0.0)
+  apMag_out = apMag_meas + growth(radius,refRadius) + f(skyBias,skySat)
+
+  these corrections are modified by the following config settings:
+
+  IGNORE_GROWTH (sets all growth magnitudes to the fitMag value,
+  effectively turning off the growth correction)
+
+  APTREND : set the level of correction
+    NONE     : no correction is fitted
+    CONSTANT : just a single constant (applied to get psfMag_out)
+    SKYBIAS  : the skybias term is fitted (constant applied to psfMag,
+               slope applied apMag)
+  
+2006.11.08
+
+  I have been testing the pmSourceMagnitudes interpolation of the
+  source position when measuing the aperture magnitudes.  I built a
+  test suite for pmSourceMagnitudes and pmGrowthCurve.  even with
+  bicubic interpolation, there are noticable errors for small
+  apertures (ie, small compared to the PSF sigma).  I used a gaussian
+  PSF to make the tests.  it seems that, if the radius is less than 2
+  sigma or so, the interpolated aperture mag is in error by as much as
+  12mmag.  The size of this effect must depend on the smoothing
+  algorithm, the shape of the PSF, the size of the PSF relative to the
+  pixels, and the size of the subpixel interpolation.  I believe the
+  effect is a result of the smoothing introduced by the interpolation:
+  the smoothing pushes the flux in the inner portions of the PSF down
+  and enhances the flux in the outer portions.  thus, there is
+  actually a turn over in the error: at very large values, the error
+  is very small because the aperture contains all of the flux, and the
+  interpolation has little effect.  as the radius shrinks, the error
+  grows (in the sense of M_raw - M_interpolated; ie, the flux in the
+  interpolated source is too large).  around 2-3sigma, the error turns
+  over and becomes negative (too little flux in the interpolated
+  source). 
+
+  The sigmas I used for these tests (1.0, 1.5, 2.0 pix) are
+  appropriate for the range we expect to see from PS1, or any
+  well-sampled detector.  Thus, even though the effect is probably
+  less important for poorer seeing, we have to be careful to avoid it
+  in our Pan-STARRS analysis.
+
+  Currently, the minimum aperture is defined only by the config
+  variable PSF_FIT_PAD, which really implies a padding.  My proposal
+  is to require the minimum aperture to be a number of sigma (an
+  additional parameter).  Then, the formula for the radius would be
+  something like:
+
+  MAX (modelRadiusPSF (PSF_FIT_NSIGMA), PSF_FIT_RADIUS_NSIG) +
+  PSF_FIT_PAD
+
+  with PSF_FIT_RADIUS_NSIG (choose a better name!) set to something
+  like 2 or 3.
+
+2006.11.06
+
+  I have added the aperture interpolation as a component of the
+  pmSourceMagnitudes function.  
+
+  I am trying to make things a bit more organized, with more
+  consistent APIs. 
+
+  * changed pmPSFtry to use the pmSourceMagnitudes API
+  * changed pmPSFtry to use new pmSource entries for each try (saving
+  * the pmModels generated)
+
+  other notes:
+  * moved psphotGrowthCurve -> pmGrowthCurveGenerate 
+
+  things I know need to be added / fixed:
+  * measure bicube fit to peak from smoothed image
+  * use psphotEnsemble fit to re-measure normalization?
+  * extended object statistical measures 
+
+2006.11.02
+
+  Looking into the growth curve problem.  RHL sent his recipe for
+  correcting to true circular apertures.  I've done a test fix of
+  interpolating the stellar image to the desired center.  it looks
+  like bilinear interpolation is insufficient (about 8% error for 2
+  pixel radius aperture).  Unless I've got the formula wrong, the
+  effective smoothing of the gaussian is moving flux from the center
+  out and making small apertures in error that depends on the offset.
+  Bicubic could be enough to clean this up?  
+
+  I think the current code may need to be careful modified to include
+  the interpolation for every aperture measurement.  there are paired
+  'pmModelAdd' and pmModelSub steps to add and remove the model flux.
+  I need to be careful about how the mask affects these steps.
+
+  I also need to be careful in interpreting the test results: since
+  the simulated images create objects by filling in a pixel and then
+  smoothing, all objects have centroids which are exactly 0.5 pixel
+  offsets.  These all then have a fixed growth correction error, which
+  fortunately happens to be substantial (because of a 0.5 pixel offset
+  in the growth curve reference object!)
+
+  I need to double check the 0.5 pixel error issues.  There are
+  problems with the pslib version of psImageShift and
+  psImageInterpolate (or at least inconsistencies).  the pmModelAdd
+  and Sub functions and the centroid functions are probably also
+  inconsistent.
+
+2006.11.01
+
+  Trying to understand low-level errors in psphot using simulated
+  data.  the main issue I am concerned with is the bias RHL is seeing
+  in SDSS-psphot comparisons.  But there are other issues that are
+  creeping in and probably point at logical errors in the code.
+
+  * in pmPSFtry, I measure the first pass on the aperture residual (to
+    choose between PSF model options, if that is being tested).  This
+    analysis currently uses a polynomial fit (1st order) for the offset
+    and the sky bias (using r^2/flux as an independent variable).
+
+    Notes:
+
+    - is the psf-fit error distribution reasonable?  perhaps a little
+      on the high side: at 10000 DN, noise is 0.0138, should be
+      0.0107.
+
+    - scatter of ap-fit is surprisingly high.  M_input - M_fit has a
+      median chisq of 2 (mean of 5), while M_input - M_ap has a median
+      chisq of 125 (mean of 380).  This is using a radius of 15.  It
+      cleans up hugely when I go to a radius of 7 and even more so
+      with radius = 4. (In this case, the PSF sigma is 1.5, so 4 is
+      well matched and 7 is only slightly large).
+
+      * make the initial PSF fitting radius and aperture radius
+	  different?  
+      * make the initial PSF fitting radius a function of the measured
+	  PSF sigma?
+
+    - I have been fitting ap-fit mag without weights; the resulting
+      ap-fit errors are highly over-estimated since the ap-fit scatter
+      is too high.  I have added code to carry the weights (error from
+      the fit only at the moment, ie, not the ap error as well).  This
+      is good, but not as important if the radius is chosen well above.
+
+  * a bias in the psphotEnsemble results depending on the sky level
+    but not in the PSF model fits?  turning on/off CONST_PHOT_WT has
+    an equivalent effect, but is quite small.  why is one sensitive to
+    the sky and the other is not?  
+
+  * the error measured by psphotEnsemble was wrong (and inconsistent
+    for a given weighting situation): fixed the def of the error.
+
+  * still trying to understand the corrections being made.  running a
+    few tests:
+
+    keeping PSF_FIT_RADIUS at 4.0
+
+    t1 : no growth correction,    constant weights
+    t2 :    growth correction,    constant weights
+    t3 : no growth correction, no constant weights
+    t4 :    growth correction, no constant weights
+    t5 :    growth correction,    constant weights, constant ap (4)
+    t6 :    growth correction,    constant weights, integer radius
+    t7 :    growth correction,    constant weights, integer radius
+    (for t7, I've fixed the bug that the growth correction include the
+    min radius).
+
+  * psphotGrowthCurve is messed up : the measurement does not correct
+    for the actual object center, and at small radii this is an
+    important source of noise.
+
+2006.06.28
+
+  I am adding a few minor features.  First up is the ability to break
+  the processing at interesting stages.  These will be:
+
+  - PEAKS: after sources are generated, but before moments are
+    measured
+  - MOMENTS: after moments are measured, before the PSF is measured
+  - PSFMODEL: after the psf model is measured, before sources are
+    fitted in bulk
+  - ENSEMBLE: after the linear ensemble fitting
+  - DEFAULT: complete processing
+
+2006.04.22
+
+  I have updated psphot to work with the cycle 11 release of psLib and
+  psModules.  At this point, the IfA group is now working off of the
+  CVS head rather than from a separate IfA branch of psLib and
+  psModules.  The cycle 11 release of psLib needed a few updates to
+  fix minor problems.  The psModules code needed significant work to
+  fix discrepancies.  The new version of psphot has also been leak
+  checked, at least for basic configurations.  This new version of
+  psphot should be used with the new camera configuration system,
+  which can be found in the ipp/config directory.  Here are the
+  necessary tags:
+
+  psphot: psphot_dev_11_0
+  psModules: rel11_ifa_pre0
+  psLib: rel11_ifa_0
+
+2006.04.16
+
+  Examining some of the throughput issues.  the flux measurement speed
+  is strongly dependent on the interation of the function step size:
+
+  dz = 0.01 : 3.24s for 4400 objects
+  dz = 0.1  : 0.44s for 4400 objects
+
+  there is an increased error in the result with the larger step size,
+  but it is smaller than the phot error.  Still, we could do better
+  with a smarter integration function.
+
+  Including the aperture photometry on all sources, but not the
+  pixWeight, the source magnitudes takes 4.8 sec for 4400 objects.
+
+  Adding the pixWeight increases the time to 7.5 sec for 4400 objects
+
+2006.02.12
+
+  Last week, I made a new tag (psphot_dev_08) after finishing the work
+  to clean memory leaks and to modify psphot to work with Paul's
+  ppImage infrastructure.  
+
+  I have added a new background model function which generates a
+  median map based on Robert's suggestion of a) half-step windows and
+  b) linear interpolation.
+
+  Now, I am working to remove the constant sky level concepts and make
+  every relevant test use the signal/noise ratio as the trigger.  This
+  has impacts on the peak detections, the threshold for blends, and
+  the threshold for choosing pixels in the fitting routines.
+
+2005.12.23
+
+  Improvements in psphot as of psphot_dev_07
+
+  - updated to work with psModule release 9.0
+  - moved model test functions into psphot as optional mode
+  - added pmSourceFitSet : simultaneous model group fitting
+  - added bicubic interpolation to tweak up the peak coordinates
+  - added aperture residual analysis after complete object model & subtraction
+  - added 3D (x,y,rflux) aperture residual fitting
+  - added blend vs blob fitting (BlendFit)
+  - added ensemble PSF fitting, with sparse matrix inversion
+  - improved the flagging / marking of model results
+  - better abstraction for setting fit parameters
+  - various low-level fixes
+  - added PSF output option
+  - added break points
+  - added more optional output formats
+  - fixed FITS table output
+
+  Things still to be added to psphot:
+
+  - better initial background model (NxM median grid?)
+  - include local background model in EnsemblePSF Fit (use sparse matrix)
+  - 2nd pass (after object subtraction) to smooth and detect faint objects
+  - re-add background to object-subtracted image
+  - cleanup function names
+  - push more functions into psLib / psModule
+  - fix extended / galaxy models to improve stability
+  - add mode with input PSF
+  - add mode with input fixed sources (PS_SOURCE_FIXED)
+  - cleanup memory leaks
+
+2005.11.25
+
+  I've updated psphot to work with the current psLib v8, though a
+  number of psLib fixes were needed.  These are pushed under
+  psLib:eam_rel8_b2.  The psphot code which works with that version of
+  psLib is tagged psphot_dev_04.
+
+  I'm working on converting psphot to work with the current release of
+  psModules, which basically includes all of the object functions. 
+
+  - change comments are relative to psModules (vs psphot versions)
+
+  psEllipse.c : OK
+  psEllipse.h : OK
+  pmModelGroup.c : OK (missing TGAUSS entry)
+  pmModelGroup.h : OK (adds many comments)
+
+  pmPSFtry.c : a bunch of formatting weirdness (try-> got line breaks
+	       added pmPSFtryMetric_Alt
+	       fixed up usage of psVectorClipFitPolynomial1D  
+	       fixed up usage of psPolynomial..Alloc  
+
+  pmPSFtry.h : OK (Added extensive comments)
+
+  pmPSF.c : fixed up usage of psPolynomial..Alloc
+
+  pmPSF.h : OK (Added extensive comments)
+
+  pmObjects.c : cleaned up some formatting,
+		fixed usage of psImageCountPixelMask
+
+  pmObjects.h : added apMag and fitMag to pmSource
+		dropped PS_MODEL_name defines
+
+  psLibUtils.[ch] should be dropped from psModules
+  psModulesUtils.[ch] should be dropped from psModules
+
+  Makefile.am : dropped psModulesUtils.[ch], psLibUtils.[ch]
+
+  - I have successfully tested psphot with the psModules.v8 code
+    (eam_rel8_b1 tag).  I only needed to make a few modes in the
+    psModules code.  
+
+2005.11.16
+
+  I have made some fixes to make psphot work with pslib rel8_0.  I
+  need to merge psphot with the rel8_0 version of the psMinimize and
+  pmObjects code.  
+
+2005.09.06
+
+  I have built a working version of PSPhot using my own copy of the
+  pmObjects.[ch] files.  I need to minimize the difference between the
+  v0.7.0, v0.5.0, and my own version of pmObjects.c
+
+  additions to psLib based on the new version:
+  - extended the minimization to include parameter limits
+
+  changes v0.5.0 / v0.7.0 / EAM
+  - changed all ps* to pm*
+  - fixed naming for local static functions (eg modelFree not p_psModelFree)
+  - dropped all hard-coded model names (vs v0.7.0)
+  - using current psMemSetDellocator name
+  - added noise image to pmSource
+  - converted old asserts to new asserts (PS_.._CHECK..)
+  - add return from error in pmFindImagePeaks
+  - allow isItInThisRegion to have NULL region (true)
+  - fixed subImages to correspond to region definition (end is
+    exclusive) in LocalSky and SetPixelCircle
+  - dropped old, redundant code in pmSourceLocalSky
+  - fixed pmSourceMoments use of mask (0 is valid, not 1)
+  - added pmSourceMoments validity tests (numPixels, Sum, centroid shift)
+  - added correction for Sxy (XY/Sum - x*y)
+  - added pmSourcePSFClump function (and pmPSFClump structure)
+  - allow missing sources in pmSourcePSFClump (not all peaks yield
+    sources)
+  - moved pmSourceRoughClass metadata lookups out of inner loop
+  - added saturated pixel test using pmImageCountPixelMask
+  - various redefinitions of initial classes
+  - dropped old, redundant code in pmSourceSetPixelsCircle
+  - mask image set to type psU8 (was psF32)
+  - abstract object model functions for pmSourceModelGuess
+  - converted evalModel to a public function psModelEval, modified params
+  - pmSourceFitModel operates on a specified model
+  - pmSourceFitModel had option to apply/ignore PSF information
+  - pmSourceFitModel calculates yErr
+  - pmSourceFitModel calculates the covariance matrix
+  - added paramMask to pmSourceFitModel 
+  - pmSourceFitModel_EAM uses covar to carry in beta and param
+    limits...
+  - pmSourceFitModel requires solution to stay within image
+  - pmSourceFitModel calculates and saves chisq, nIter, nDOF
+  - pmSourceFitModel uses GaussNewtonDelta for frozen params
+  - added mask to pmSourceAdd, pmSourceSub
+  - model abstractions in pmSourceAdd, pmSourceSub
+  - fixed 'center' option in pmSourceAdd/Sub
+
+  - pmPSF params should be F64
+
+  lingering concerns:
+  - Polynomials and related functions are STILL messed up.  this is a
+    major priority!!!
+  - pmSourceFitModel calculates sqrt(var), psMinimize calculates sq(sqrt(var))
+  - does psImageAlloc zero the image?  if so, drop init routine
+    from pmSourcePSFClump
+  - pmSourceRoughClass uses RDNOISE, GAIN to calculate SN: should use
+    the source->noise image? part of pmSourceMoments?
+  - pmSourceMoments_EAM uses macro for checkRegion
+  - pmObjects_EAM.c uses some hardcoded mask values (LocalSky)
+  - why does LocalSky_EAM not need subImageMask->col0 = subImage->col0??
+  - psGetRowVectorFromImage should be in psLib (in psLibUtils)
+  - pmSourceSetPixelsCircle and pmSourceLocalSky probably could use
+    the psImageMaskRegion, etc functions.
+  - pmSourceSetPixelsCircle uses a hard-coded mask value
+  - define a mask registration process??
+  - pmSourceContour is using the model flux, not the image flux
+
+2005.09.05
+
+  I have a working version of PSPhot which handles PSF and galaxy
+  models.  I am tagging the module with an alpha version number. this
+  version compiles with psLib-0.5.0, at least my version of it.  My
+  current goal is to make it work with the current psLib head (nearly
+  0.7.0) with a mimimum of _EAM versions of functions.
+
+  the tag for the working version is dev_01
+
+2005.06.04
+
+  progress on psphot has moved along well.  At this point, the process
+  loads the image, finds the peaks, determines a best PSF model,
+  identifies objects which are consistent with that model, and
+  attempts to fit a galaxy model to the objects which are not
+  consistent with the model. 
+
+  a variety of minor issues remain, as well as some major issues. 
+
+  - use a proper noise image to keep the fits honest after other
+    objects have been subtracted.  
+
+  - define the masks in terms of a single mask image.  this image
+    could be provided initially by the user.   
+
+  - add noise enhancement (couple with mask marking subtraction)
+
+  - 
+
+2005.04.12
+
+- psPeak, psSource, etc: should be pmPeak, pmSource, etc
+- pmCullPeaks: should be pmCullImagePeaks
+
+- does pmSourceMoments need an image argument?
+
+- psLibInit / p_psTimeInit
+
+  we should not have to know about astronomy time concepts (ie, have a
+  timeConfig file) in order to use the time functions for basic work.
+  This means having a PS_TIME_UNIX which just works with the UNIX
+  clock and avoids all initialization issues.
+
+- psImageStats is much too slow for basic median
+  - this function does a complete sort on all pixel values.  we need
+  to use the histogram method (spec a different type of median)
+
+- psImageStats, ROBUST_MEDIAN fails
+- there are errors in psVectorStats for ROBUST MEAN, STDEV (& median?)
+  * this is ill-defined.  revise the ADD: too sensitive to the
+  binning, smoothing scales 
+
+- pmFindImagePeaks is not finding any peaks:
+  typo in interior row section: see bug 359
+  after this fix: PASS
+
+* p_psGetRowVectorFromImage : PASS
+* psGetRowVectorFromImage : PASS 
+- both have about the same time (~15 us +/- 5us) for 2048 pix on alala
+
+* pmFindVectorPeaks : PASS (returned row data in data.U32)
+
+- # include <string.h> : needed in psMetadata.c
+
+* MyListAddPeak / pmPeakAlloc are inconsistent wrt col,row vs x,y
+
+- why does psMetadataItemAllocV allocate a string of length
+  MAX_STRING_LENGTH for the comment, then use strncpy?
+
+  should be:
+
+    // set metadata item comment
+    if (comment == NULL) {
+        // Per SDRS, null isn't allowed, must use "" instead
+        metadataItem->comment = psStringCopy ("");
+    } else {
+        metadataItem->comment = psStringCopy (comment);
+    }
+
+psMetadataAdd -> psMetadataAddItem is all confused:
+ - we end up with two psMetadataItemAlloc calls, when only one should
+   be used
+ - psMetadataItemAlloc was doing the wrong thing if the incoming data
+   was NULL
+ - I think the logic in this block is wrong as well.  
+
+ * I fixed this in psMetadata.c
+
+2005.04.14 : 
+
+ - psImageStats is still much too slow
+
+ - pmObjects : changed to using psArray to carry peaks / sources,
+   rather than psList
+
+ - added function pmPeaksSubset to replace pmCullPeaks
+
+ - pmSourceLocalSky: added min/max fncs to force subimage to stay in
+   image
+
+ - Sx, Sy can go negative: have forced limit to 0,0
+
+ - pmSourceRoughClass: implemented sigmaX, sigmaY search for stellar
+   clump (uses pmComparePeakDescend)
+
+   - the search ignores the 0,0 pixel
+
+   - pmSourceRoughClass uses all detected peaks.  allow an exclusion
+     for peak > max, peak < min?
+
+   - need to push clump stats on the metadata
+
+   - the source classes are assigned so they are mutually exclusive 
+
+   - change PS_SOURCE_OTHER to STAR? 
+
+ - pmSourceSetPixelCircle:
+
+   - name should be pmSourceSetPixelsCircle (geometry could be an
+     option...)
+
+   - I cleaned the defined region to match the convensions of
+     pmSourceLocalSky
+
+   - truncate and force subimage to lie on image
+
+   - CheckRadius2 seems like an inefficient coding
+
+   - valid pixels have mask value of 1 (inverse of other funcs)
+
+ - pmSourceFitModel:
+
+   - num iterations is much too large
+
+   - 
+
+mrq:
+
+ - allocate alpha, beta arrays
+ - mrq2dcof (pars, alpha, beta)
+ - make guess pars', alpha', beta'
+ - mrq2dcof (pars', alpha', beta')
+ - if (chisq < old chisq), keep new guess
+
+
+2005.04.19:
+
+- psMinimizeLMChi2 has some serious problems.  I re-wrote it starting
+  from the mrqmin example in ohana.   after a variety little bugs, it
+  seems to work quite well.  the program 'modeltest.c' runs two
+  different gaussians through psMinimizeLMChi2, and gets the right
+  answer quite quickly.  The first pass at the implementation had a
+  variety of problems.  to avoid any worry about errors in the
+  psMatrix code, I implemented psGaussJordan, basing the code on the
+  elixir gaussj.c code.  this worked fine, and let me find the errors
+  elsewhere in the code. the LUD version now works just the same as
+  the GaussJ version.
+
+
+2005.04.21
+
+- psMinimizeLMChi2 does an excellent job now in most cases.  I am able
+  to run pmSourceFitModel on the PSF stars quite well.  I added in the
+  (nearly) correct errors (actually, just using sqrt(N), limiting to
+  N>=1).  I see one problem object, which is quite faint, and does not
+  converge well: I get very large values for x,y, Sx, Sy, etc.  I need
+  to think about constraining these fits from running way off scale.
+
+  fit:   0.123879 sec for 277 stars (gauss)
+  fit:   0.155940 sec for 277 stars (pgauss) (!)
+  fit:   0.153292 sec for 277 stars
+  (0.5 msec per star)
Index: /branches/eam_branches/eam_branch_20080719/psphot/doc/outline.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/doc/outline.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/doc/outline.txt	(revision 22158)
@@ -0,0 +1,21 @@
+
+Here is a summary outline of the steps taken by psphotReadout:
+
+* setup (choose recipe, choose readout, define break-point)
+* create mask and weight images if needed, set mask for analysis region
+* psphotImageMedian : construct a background model image and subtract it
+* psphotFindPeaks   : smooth and find the peak pixels from the smoothed image
+  - no pmSource defined yet, only pmPeak
+* psphotSourceStats : create sources for each peak and measure their moments
+  - pmSource defined here, with pixels covering SKY_OUTER_RADIUS
+  - no pmModel is defined yet.
+* psphotBasicDeblend : identify blended sources by proximity and valley depth
+* psphotRoughClass : source classification guess based on moments
+  - set the source.type,mode.
+  - re-calculate moments for saturated stars
+* psphotChoosePSF : define the psf model
+  - this generates model fits to the identified psf stars
+    (one for each tested model)
+  - these models are not kept (seems like a waste, but later fits must be consistent)
+* psphotGuessModels : set the initial PSF model for each object (even EXTENDED)
+  - creates modelPSF entries
Index: /branches/eam_branches/eam_branch_20080719/psphot/doc/output.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/doc/output.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/doc/output.txt	(revision 22158)
@@ -0,0 +1,15 @@
+
+we have several output formats:
+  - TEXT : separate ASCII tables for PSF, EXT, MNT, and NULL
+  - SX : sextractor-style ASCII file
+  - OBJ : dophot-style ASCII file
+  - CMP : old-style elixir format (header + text)
+  - CMF : fits-table
+
+we have several options for organization:
+  - single chip/readout : outroot.ext
+  - split chips : outroot.NN.ext
+  - mef chips : outroot.ext (extensions with names)
+
+  * only CMF will work with MEF model
+
Index: /branches/eam_branches/eam_branch_20080719/psphot/doc/psfmodel.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/doc/psfmodel.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/doc/psfmodel.txt	(revision 22158)
@@ -0,0 +1,62 @@
+
+2007.09.25
+
+  The PSF model has parameters which vary across the image.  This 2D
+  is can be represented as either a polynomial (ordinary or chebychev)
+  or as an image map.  The user requests the maximum X & Y scale
+  (PSF.TREND.NX & PSF.TREND.NY) for the variations, and
+  psphotChoosePSF / pmPSFtry attempt to find the best choice for the
+  scale.  For the polynomial representations, NX and NY are the order
+  of the variation.  For the image map, NX and NY are the size of the
+  image map.
+
+2007.09.21
+
+  there are three places where we can choose to use errors in the fits or not:
+
+  * non-linear fitting of the models to the pixel flux distribution (poissonErrorsPhotLMM)
+  * linear fitting of the models to the pixel flux distribution (poissonErrorsPhotLin)
+  * fitting of the 2D variations in the psf parameters (poissonErrorsParams)
+  * fitting of the 2D variations in the aperture residuals
+
+2007.09.20
+
+  I am upgrading the PSF model to allow the parameter variation to be
+  modeled with pmTrend2D instead of just polynomials.  I am making a
+  list of places to modify the code:
+
+pmPSFAlloc : need a method beyong psfTrendMask to carry in the psf
+options
+
+pmPSF_ModelToFit : no need to change these
+
+update pmPSFBuildSimple to set the parameters of the pmTrend, which
+ever is used.
+
+pmPSFtry.c: some significant re-work!
+
+
+
+pmPSF_IO : need new functions to save / load the trend (psImages)
+
+2006.10.27
+
+  I have been working to fix the PSF modeling in psphot.  The PSF
+  model consists of a flux model for an individual object using an
+  analytical model with a number of parameters.  For a collection of
+  PSF objects, the variation of the parameters as a function of
+  position are then themselves fitted with a model.  The PSF model for
+  a single object consists of a radial profile with a functional form
+  f(z) where a given value of z defines an elliptical coutour of the
+  form z = \frac{x^2}{2\sigma_x^2} + \frac{y^2}{2\sigma_y^2} +
+  \sigma_{xy}xy.
+
+
+
+  The term \sigma_{xy} is difficult to model as a simple function of x
+  and y (eg, a low-order polynomial).  
+
+  A better model can be constructed for
+  \frac{\sigma_{xy}}{(\sigma_x^{-2} + \sigma_y^{-2})^2}, which varies
+  like a^2 \sin 2\theta 
+
Index: /branches/eam_branches/eam_branch_20080719/psphot/doc/psphot.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/doc/psphot.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/doc/psphot.txt	(revision 22158)
@@ -0,0 +1,160 @@
+
+TBD priorities:
+
+- test psImageSmooth / remove psImageSmooth_EAM
+- unify pmSourceLocalSky / pmSourceLocalSky_EAM
+- unify pmSourceMoments_EAM / pmSourceMoments_EAM
+- merge with image data hierarchy stuff
+- better name for psPSF_Test
+
+Defined APIs:
+
+top-level psphot functions : these do not need to be in psModules
+  psMetadata  *psphotArguments ();
+  psImageData *psphotSetup ();
+  psStats     *psphotImageStats ();
+  psArray     *pmPeaksSigmaLimit ();
+  psArray     *psphotSourceStats ();
+  pmPSF       *psphotChoosePSF ();
+  bool         psphotApplyPSF ();
+  bool         psphotFitGalaxies ();
+  void         psphotOutput ();
+
+psphot-specific functions
+  bool         psphotMarkPSF ();
+  bool         psphotSubtractPSF ();
+  int          psphotSortBySN ();
+  int          psphotSaveImage ();
+
+** add the following entries to the psLibSDRS
+
+psLib extra utilities
+  bool         psTimerStart ();		- already in SDRS
+  void         psTimerFree (); 		- already in SDRS
+  bool         psTimerClear ();		- add to psLibSDRS
+  psF64        psTimerMark (); 		- already in SDRS
+  psS32        psLogArguments ();	- now: psArgumentVerbosity in SDRS
+  psS32        psTraceArguments ();	- now: psArgumentVerbosity in SDRS
+  int          psArgumentGet ();	- already in SDRS
+  int          psArgumentRemove ();	- already in SDRS
+  psVector    *psVectorCreate ();	- add to psLibSDRS
+  int          psImageCountPixelMask ();- add to psLibSDRS
+  psVector    *psGetRowVectorFromImage(); - add to psLibSDRS?
+  bool         p_psVectorPrintRow ();     - add to psLibSDRS?
+
+// basic image functions
+  bool         psImageInit ();		- already in SDRS
+  void         psImageSmooth_EAM ();    - test psLib version and drop
+
+// psLine functions
+  psLine      *psLineAlloc ();		- add to psLibSDRS
+  bool         psLineInit (); 		- add to psLibSDRS
+  bool         psLineAdd ();  		- add to psLibSDRS
+
+** compare with current implementation / update psLib
+   we need to define a mechanism to carry the beta values and the
+   parameter limits
+
+// minimize 
+  psBool       p_psMinLM_GuessABP_EAM ();
+  psBool       psMinimizeLMChi2_EAM();
+  psF64        p_psMinLM_dLinear ();  -- not included in pslib.h files
+
+** already in psLib : some need to be cleaned up by MHPCC
+
+// polynomial functions
+  psF64           Polynomial2DEval();
+  psImage        *psBuildSums2D();
+  psPolynomial2D *VectorFitPolynomial2DOrd_EAM();
+  psPolynomial2D *Polynomial2DAlloc();
+  void            psPolynomial2DDump ();
+  psPolynomial2D *RobustFit2D_nomask();
+  psPolynomial2D *RobustFit2D();
+  psVector       *Polynomial2DEvalVector();
+
+  psVector       *psBuildSums1D();
+  void            psPolynomial1DDump ();
+  psF64           Polynomial1DEval_EAM();
+  psVector       *Polynomial1DEvalVector_EAM();
+  psPolynomial1D *Polynomial1DAlloc();
+  psPolynomial1D *VectorFitPolynomial1DOrd_EAM();
+
+** make sure these are all in the psModules SDRS:
+
+pmObjects.h:
+  pmMoments           *pmMomentsAlloc();
+  pmModel             *pmModelAlloc();
+  pmSource            *pmSourceAlloc();
+  psVector            *pmFindVectorPeaks()
+  psArray             *pmFindImagePeaks()
+  psList              *pmCullPeaks()
+  pmSource            *pmSourceLocalSky()
+  bool                 pmSourceMoments()
+  pmPSFClump           pmSourcePSFClump()
+  bool                 pmSourceRoughClass()
+  bool                 pmSourceSetPixelsCircle()
+  pmModel             *pmSourceModelGuess()
+  psArray             *pmSourceContour()
+  bool                 pmSourceFitModel()
+  bool                 pmSourceAddModel()
+  bool                 pmSourceSubModel()
+  int                  pmModelParameterCount ();
+  char                *pmModelGetType ();
+  pmModelType          pmModelSetType ();
+  pmModelFunc          pmModelFunc_GetFunction ();
+  pmModelFlux          pmModelFlux_GetFunction ();
+  pmModelRadius        pmModelRadius_GetFunction ();
+  pmModelLimits        pmModelLimits_GetFunction ();
+  pmModelGuessFunc     pmModelGuessFunc_GetFunction ();
+  pmModelFromPSFFunc   pmModelFromPSFFunc_GetFunction ();
+  pmModelFitStatusFunc pmModelFitStatusFunc_GetFunction ();
+
+model function abstractions:
+  typedef psMinimizeLMChi2Func pmModelFunc;
+  typedef psF64 (*pmModelFlux)(const psVector *params);
+  typedef psF64 (*pmModelRadius)(const psVector *params, double flux);
+  typedef bool (*pmModelLimits)(psVector **beta_lim, psVector **params_min, psVector **params_max);
+  typedef bool (*pmModelGuessFunc)(pmModel *model, pmSource *source);
+  typedef bool (*pmModelFromPSFFunc)(pmModel *modelPSF, pmModel *modelFLT, pmPSF *psf);
+  typedef bool (*pmModelFitStatusFunc)(pmModel *model);
+
+conversions between elliptical shape representations
+  EllipseAxes  EllipseMomentsToAxes ();
+  EllipseShape EllipseAxesToShape ();
+  EllipseAxes  EllipseShapeToAxes ();
+
+output functions
+  bool         pmSourcesWriteText ();  	-- be careful about psImageData...
+  bool         pmSourcesWriteOBJ ();   	-- be careful about psImageData...
+  bool         pmSourcesWriteCMP ();   	-- be careful about psImageData...
+  bool         pmSourcesWriteCMF ();   	-- be careful about psImageData...
+  bool         pmSourcesWriteSX ();    	-- be careful about psImageData...
+  int          pmSourcesDophotType ();
+  bool         pmPeaksWriteText ();
+  bool         pmMomentsWriteText ();
+  bool         pmModelWritePSFs ();
+  bool         pmModelWriteFLTs ();
+  bool         pmModelWriteNULLs ();
+
+// psf utilities
+  pmPSF       *pmPSFAlloc ();
+  pmPSF_Test  *pmPSF_TestAlloc ();
+  pmPSF_Test  *pmPSF_TestModel ();
+  bool         pmPSFFromModels ();
+  pmModel     *pmModelFromPSF ();
+  bool         pmSourcePhotometry ();
+  bool         pmPSFMetricModel ();
+
+// psModule extra utilities
+  bool         pmSourceFitModel_EAM();  -- requires updated version of psMinimize...
+  bool         pmSourceLocalSky_EAM (); -- compare with pmSourceLocalSky & choose
+  bool         pmSourceMoments_EAM();   -- compare with pmSourceMoments & choose
+  bool         pmSourceDefinePixels();  -- be careful about psImageData...
+  bool         pmModelFitStatus ();
+  int          pmSourceDophotType ();
+  psF32        pmConfigLookupF32 ();	-- merge with Paul's image container hierarchy
+
+** this needs to be confronted with the phase2 / image container hierarchy
+
+// psImageData functions
+  psImageData *psImageDataAlloc ();
Index: /branches/eam_branches/eam_branch_20080719/psphot/doc/regions.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/doc/regions.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/doc/regions.txt	(revision 22158)
@@ -0,0 +1,159 @@
+
+I am having some trouble with functions that refer to both subimages
+and regions.  there are inconsistencies between the coordinate
+conventions.  I am going to go through the list of image functions are
+decide if we can choose either 1) external coordinates always refer to
+parent coordinates or 2) something else!
+
+bool psImageSet(const psImage *image, int x, int y, double complex value);
+double complex psImageGet(const psImage *image, int x, int y);
+ - sdrs does not specify
+ - code uses subimage
+
+psRegion psRegionForImage(psImage *image, psRegion in);
+ - sdrs says subimage
+ - code uses subimage
+
+psImage *psFitsReadImage(psImage *out, const psFits *fits, psRegion region, int z);
+ - region here specifies a subimage of the disk image
+ 
+bool psFitsUpdateImage(psFits *fits, const psImage *input, int x0, int y0, int z);
+ - x0,y0 here refer to the disk image coordinates
+
+bool psFitsWriteImage(psFits *fits, psMetadata *header, const psImage
+*input, int depth, const char *extname);
+ - note that the output disk image is truncated to the subimage
+
+bool psFitsInsertImage(psFits *fits, psMetadata *header, const psImage *input, int depth,
+                       const char *extname, bool after);
+ - same as above
+
+psImage *psImageSubset(psImage *image, psRegion region);
+ - code uses region as coordinates in parent image
+ - sdrs does not specify
+ - XXX I think the range tests for region fail if the input is a
+   subimage
+
+psImage *psImageCopy(psImage *output, const psImage *input, psElemType type);
+ - maintains the col0,row0 values
+
+psVector *psImageRow(psVector *out, const psImage *input, int row);
+psVector *psImageCol(psVector *out, const psImage *input, int column);
+ - code uses subimage coordinates for row and column
+
+psVector *psImageSlice()
+psVector* psImageCut()
+ - code uses subimage coordinates (no correction)
+ - sdrs does not specify
+
+psImage *psImageRebin()
+ - mask and input image must currently agree
+
+psImage *psImageTransform()
+ - sdrs is unclear: I think the region defines the output image such
+ that the pixel in the input image *parent* coordinates which
+ corresponds to region.x0,y0 in turn corresponds to the output image
+ 0,0 pixel; the output image always has col0,row0 = 0,0
+
+long psImageCountPixelMask (psImage *mask, psRegion region, psMaskType value);
+ - sdrs says the region corresponds to subimage coordinates
+
+psPolynomial2D *psImageFitPolynomial(psPolynomial2D *coeffs, const psImage *input);
+psImage *psImageEvalPolynomial(psImage *input, const psPolynomial2D *coeffs);
+ - sdrs does not specify
+ - polynomial coordinates should refer to the *parent* image
+
+double complex psImagePixelInterpolate(input, x, y, ...)
+ - sdrs does not specify
+
+int psImageOverlaySection(psImage *image, const psImage *overlay, )
+ - sdrs does not specify
+
+psImage *psPixelsToMask()
+psPixels *psPixelsFromMask()
+ - sdrs does not specify
+
+void psImageMaskRegion()
+void psImageKeepRegion()
+ - sdrs does not specify
+
+void psImageMaskCircle()
+void psImageKeepCircle()
+ - sdrs does not specify
+
+pmReadout *pmSubtractSky(pmReadout *in, psPolynomial2D *poly, psImage *mask, psU8 maskVal, 
+                         int binFactor, psStats *stats, float clipSD);
+ - choice of polynomial coordinates
+
+stats *pmFringeStats (psArray *fringePoints, psImage *image, psMetadata *config);
+ - unspecified
+
+psF32 pmModelEval(pmModel *model, psImage *image, psS32 col, psS32 row);
+ - sdrs says col,row are in *subimage* coords
+
+psArray *pmFindImagePeaks(const psImage *image, float threshold);
+ - does not specify coordinate system
+ - code uses subimage?
+
+bool pmSourceDefinePixels()
+bool pmSourceRedefinePixels()
+ - sdrs does not specify very clearly
+
+
+
+---------
+
+functions which are not affected
+psFitsReadImage()
+psFitsUpdateImage()
+psFitsWriteImage()
+psFitsInsertImage()
+psImageCopy()  -- maintains col0,row0
+psImageRebin() -- mask and image must match
+
+functions which currently use parent coordinates (CORRECT)
+psImageSubset()  -- check on range tests
+psImageMaskRegion()
+psImageKeepRegion()
+psImageMaskCircle()
+psImageKeepCircle()
+pmSourceMoments -- (OK if input peaks are in parent coords)
+
+functions which currently use subimage coordinates (FIX)
+psImageSet()
+psImageGet()
+psRegionForImage() *fixed*
+psImageRow()
+psImageCol()
+psImageSlice()
+psImageCut()
+psImageCountPixelMask ();
+pmModelEval()
+pmFindImagePeaks() *fixed*
+pmSourceDefinePixels() *fixed by psRegionForImage fix*
+pmSourceRedefinePixels() *fixed by psRegionForImage fix*
+
+functions which are unclear (CHECK)
+psImageTransform()
+psImageFitPolynomial()
+psImageEvalPolynomial()
+psImagePixelInterpolate()
+psPixelsToMask()
+pmSubtractSky()
+pmFringeStats()
+
+
+***** one ambiguity: if we have a subimage, but we do not have the
+      parent image data (subimage does not carry dimensions of parent
+      array), then a 0 or negative upper-edge of a region cannot be
+      defined relative to the parent. we can specify it relative to
+      the subimage.  so, for example, given a subimage [32,100:32,100]
+      of a much larger image, then psRegionForImage with 0,0,0,0 as
+      input would return a region with values 32,100:32,100...
+
+
+
+
+
+*** things I've modified
+    psRegionForImage expects parent (not subimage) coordinates
Index: /branches/eam_branches/eam_branch_20080719/psphot/doc/speed.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/doc/speed.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/doc/speed.txt	(revision 22158)
@@ -0,0 +1,129 @@
+
+psphot -g
+psModule -g
+psLib -O2
+on alala:
+
+alala: psphot -vv starfield.fits starfield starfield.cnf -resid starfield.resid.3.fits
+    load data: 0.983568 sec
+    System random seed value used  seed = 25904F7C7454AE25 hex
+    background: 1229.280029 +/- 27.700180
+    image stats: 0.063085 sec
+    System random seed value used  seed = 411E5A0600A49AF3 hex
+    fit background model: 0.580152 sec
+    smooth: 1.842415 sec
+    threshold: 83.100540 DN
+    4356 peaks: 0.571587 sec
+    4230 moments: 3.965099 sec
+    SN range: 3.355829 - 1043.401001
+    identified 107 blended objects (0.121737 sec)
+    selected candidate 300 PSF objects
+    fit flt:   3.682850 sec for 300 sources
+    fit psf:   1.704141 sec for 300 sources
+    fit stats: 0.000884 +/- 0.004499
+    try model PS_MODEL_QGAUSS, ap-fit: -0.007532 +/- 0.004499 : sky bias: -0.717999
+    select psf model: 5.402742 sec
+    selected psf model PS_MODEL_QGAUSS, ApResid: -0.007532 +/- 0.004499
+    fitting pixels with at least 27.700180 object counts
+    built models: 0.991345 (4230 objects)
+    built matrix: 1.472869 (27998 elements)
+    measure ensemble of PSFs: 4.334556
+    fit PSF models: 12.205738 sec for 4230 objects
+    replace unfitted models: 0.021473 sec (4230 objects)
+    measure aperture residuals : 0.451886 sec
+    measure full-frame aperture residual: 0.454032 sec
+    aperture residual: -0.002842 +/- 0.002729 : 0.166072 bias
+    wrote output: 4.648821 sec
+    complete psphot run: 35.334080 sec
+
+
+psphot -g
+psModule -O2
+psLib -O2
+on alala:
+
+alala: psphot -vv starfield.fits starfield starfield.cnf -resid starfield.resid.3.fits
+    load data: 1.001502 sec
+    System random seed value used  seed = 5F43A63F532D4B3F hex
+    background: 1229.280029 +/- 27.700180
+    image stats: 0.063169 sec
+    System random seed value used  seed = F5F5FF99A6578F61 hex
+    fit background model: 0.530384 sec
+    smooth: 1.856414 sec
+    threshold: 83.100540 DN
+    4365 peaks: 0.237292 sec
+    4239 moments: 4.087611 sec
+    SN range: 3.356469 - 1043.400879
+    identified 107 blended objects (0.123372 sec)
+    selected candidate 300 PSF objects
+    fit flt:   3.741444 sec for 300 sources
+    fit psf:   1.676478 sec for 300 sources
+    fit stats: 0.000883 +/- 0.004499
+    try model PS_MODEL_QGAUSS, ap-fit: -0.007532 +/- 0.004499 : sky bias: -0.717985
+    select psf model: 5.458156 sec
+    selected psf model PS_MODEL_QGAUSS, ApResid: -0.007532 +/- 0.004499
+    fitting pixels with at least 27.700180 object counts
+    built models: 0.791613 (4239 objects)
+    built matrix: 1.267909 (28101 elements)
+    measure ensemble of PSFs: 3.551364
+    fit PSF models: 11.240197 sec for 4239 objects
+    replace unfitted models: 0.018051 sec (4239 objects)
+    measure aperture residuals : 0.411856 sec
+    measure full-frame aperture residual: 0.413843 sec
+    aperture residual: -0.002831 +/- 0.002717 : 0.164772 bias
+    wrote output: 4.355429 sec
+    complete psphot run: 33.126283 sec
+
+after reducing indirection in pmSourceMoments:
+    4268 moments: 3.762452 sec
+
+psphot -O2
+psModule -O2
+psLib -O2
+
+alala: psphot -vv starfield.fits starfield starfield.cnf -resid starfield.resid.3.fits
+    load data: 0.484324 sec
+    System random seed value used  seed = 980050732A392EC7 hex
+    background: 1229.280029 +/- 27.700180
+    image stats: 0.058759 sec
+    System random seed value used  seed = 44E1A6EE77B0E9CE hex
+    fit background model: 0.395125 sec
+    smooth: 1.861776 sec
+    threshold: 83.100540 DN
+    4351 peaks: 0.234874 sec
+    4264 moments: 3.719435 sec
+    SN range: 2.023345 - 1043.401123
+    identified 124 blended objects (0.115230 sec)
+    selected candidate 300 PSF objects
+    fit flt:   3.525501 sec for 300 sources
+    fit psf:   1.595031 sec for 300 sources
+    fit stats: 0.000884 +/- 0.004499
+    try model PS_MODEL_QGAUSS, ap-fit: -0.007532 +/- 0.004499 : sky bias: -0.717976
+    select psf model: 5.160442 sec
+    selected psf model PS_MODEL_QGAUSS, ApResid: -0.007532 +/- 0.004499
+    fitting pixels with at least 27.700180 object counts
+    built models: 0.760805 (4264 objects)
+    built matrix: 0.908674 (23703 elements)
+    measure ensemble of PSFs: 3.115425
+    fit PSF models: 10.162397 sec for 4264 objects
+    replace unfitted models: 0.017491 sec (4264 objects)
+    measure aperture residuals : 0.408242 sec
+    measure full-frame aperture residual: 0.410207 sec
+    aperture residual: -0.002908 +/- 0.002734 : 0.170692 bias
+    wrote output: 4.225560 sec
+    complete psphot run: 30.149281 sec
+
+
+    fit PSF models: 10.162397 sec for 4264 objects
+    select psf model: 5.160442 sec
+    wrote output: 4.225560 sec
+    4264 moments: 3.719435 sec
+    measure ensemble of PSFs: 3.115425 sec
+
+    other : 3.5 sec
+
+    fixed per objects : 4 msec / object (17 of 30 sec)
+
+
+** still can re-compile with -DPS_NO_TRACE
+** ASSERTS cannot be compiled out at the moment!
Index: /branches/eam_branches/eam_branch_20080719/psphot/doc/timing.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/doc/timing.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/doc/timing.txt	(revision 22158)
@@ -0,0 +1,84 @@
+
+                                                         -- threadable?
+                                                         |
+  0.000673 sec NPEAK      0.00 msec / item (505)       - ? Find SatStars
+  0.231828 sec NPIX       0.00 msec / item (PIX)       - ? Replace Background
+  0.349591 sec NPIX       0.00 msec / item (2048*4096) - ? Background Model
+  0.609246 sec NPIX       0.00 msec / item (2048*4096) - ? Find Peaks
+  0.733840 sec NPIX       0.00 msec / item (2048*4096) - ? Find Peaks
+  6.076478 sec NPIX       0.00 msec / item (2048*4096) - ? Smooth Images
+  7.683749 sec NPIX       0.00 msec / item (2048*4096) - ? Smooth Image
+  0.003003 sec NPEAK      0.01 msec / item (505)       - ? Source Size
+  0.003934 sec NPEAK      0.01 msec / item (??)        - ? Source Sizes
+  0.019364 sec NPEAK      0.04 msec / item (505)       - ? Find Blends
+  0.045397 sec NPEAK      0.09 msec / item (??)        - ? Replaced Flux
+  0.046370 sec NPEAK      0.09 msec / item (505)       - ? Add Noise
+  0.046680 sec NPEAK      0.09 msec / item (505)       - ? Sub Noise
+  0.050980 sec NPEAK      0.10 msec / item (505)       - ? Replaced Flux
+  2.785612 sec NFOOT      0.27 msec / item (10455)     - ? Find Footprints
+  0.322163 sec NPEAK      0.64 msec / item (505)       - ? Rough Class
+  0.163793 sec NPEAK      0.66 msec / item (??)        - ? Rough Class
+  0.820221 sec NFOOT      1.40 msec / item (587)       - ? Find Footprints
+  2.311492 sec NPEAK      4.58 msec / item (??)        - ? Built Models
+  2.413531 sec NPEAK      4.78 msec / item (505)       - ? Build Models
+  1.635674 sec NPEAK      6.54 msec / item (??)        - ? Measure Moments
+  3.547435 sec NPEAK      7.02 msec / item (505)       - ? Measure Moments
+  8.118224 sec NSRCS      7.81 msec / item (1040)      - ? ApTrend
+  4.165990 sec NPEAK      8.25 msec / item (505)       - ? Fit PSF (linear)
+  4.294968 sec NPEAK      8.50 msec / item (505)       - ? Fit PSF (linear)
+  4.638916 sec NPEAK      9.19 msec / item (??)        - ? Fit PSF (linear)
+154.599482 sec NFOOT     14.79 msec / item (10455)     - ? Cull Footprints
+  1.259951 sec NPSF      17.75 msec / item (71)        - ? Fit PSF (non-linear)
+ 22.009468 sec NFOOT     37.49 msec / item (587)       - ? Cull Footprints: 
+ 15.069461 sec NPEAK     38.34 msec / item (393)       - ? Fit PSF (non-linear) + EXT (27) 
+  2.938324 sec NPSF      41.38 msec / item (71)        - ? Fit EXT (non-linear)
+  2.723019 sec NPSF      53.39 msec / item (51)        - ? PSF Residuals
+
+244.837692 sec    complete psphot run: 
+
+Note:
+
+* PSF Residuals is the most expensive per item, but will always be
+  performed on a limited number of items (typically < 300 PSF stars).
+  The maximum impact is thus limited.
+
+* The non-linear fitting is (not surprisingly) very expensive per
+  item, but again will only be performed on a limited subset (S/N >
+  20?).
+
+* The Cull Footprints is quite expensive per item, and has the serious
+  problem that it must be performed on all peaks.  This will dominate
+  all processing time unless we can address it.
+
+* The linear fitting in this example seems to surprisingly expensive
+  per item, but I think it is not quite accurate.  
+
+* ApTrend is only measured on a subset of the sources (S/N > XX, max
+  total number)
+
+* Measure Moments and Build Models are potentially a substantial drain
+  since these (probably) should be applied to all objects.  Moments is
+  currently being limited to brighter objects.  
+
+Thread strategies:
+
+
+* tests with wbb4.031117_0154.052.fits test -chip 7 : 
+
+* baseline: 
+    grow   : 18.313876 sec
+    merged : 18.772070 sec
+    total  : 26.958080 sec (dt = 8.18)
+
+* upgrade to remove psArrayRemove:
+    grow   : 18.327212 sec
+    merged : 18.778043 sec
+    total  : 25.553486 sec (dt = 6.78; ddt = 1.4)
+
+* recycle idImage:
+    grow   : 18.383393 sec
+    merged : 18.848875 sec 
+    total  : 24.721451 sec (dt = 5.88; ddt = 2.3)
+
+(no real difference??)
+
Index: /branches/eam_branches/eam_branch_20080719/psphot/doc/timing.v2.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/doc/timing.v2.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/doc/timing.v2.txt	(revision 22158)
@@ -0,0 +1,94 @@
+#             msec                   - multithread?
+#             item                   |
+15.558560 sec 37.31    NBRT   417  : y  non-linear fits
+ 0.000736 sec  0.00    NPEAK  550  : ?  satstar blends
+ 0.005947 sec  0.00    NPEAK 1315  : ?  source sizes
+ 0.076172 sec  0.01    NPEAK 7636  : ?  set footprint ids (NPIX?)
+ 0.003383 sec  0.01    NPEAK  550  : ?  source sizes
+ 0.019354 sec  0.04    NPEAK  550  : ?  other blends
+ 0.050572 sec  0.08    NPEAK  627  : ?  set footprint ids
+ 0.049778 sec  0.09    NPEAK  550  : ?  replaced models
+ 0.051736 sec  0.09    NPEAK  550  : ?  add noise
+ 0.051929 sec  0.09    NPEAK  550  : ?  sub noise
+ 0.055094 sec  0.10    NPEAK  550  : ?  replaced models
+ 0.152204 sec  0.20    NPEAK  765  : ?  rough class
+ 0.8      sec  0.26    NPEAK 3100  : ?  merge footprints
+ 0.268983 sec  0.49    NPEAK  550  : ?  rough class
+ 0.7      sec  1.25    NPEAK  560  : ?  cull peaks
+ 2.092846 sec  2.74    NPEAK  765  : ?  moments
+ 8.9      sec  3.05    NPEAK 2914  : ?  cull peaks
+ 3.339909 sec  4.37    NPEAK  765  : ?  built models
+ 2.572153 sec  4.68    NPEAK  550  : ?  build models
+ 3.816792 sec  6.94    NPEAK  550  : ?  moments
+ 9.337548 sec  7.10    NPEAK 1315  : ?  measure magnitudes :  for 1315 objects (643 with apertures)
+ 4.301656 sec  7.82    NPEAK  550  : ?  linear fit
+ 4.429642 sec  8.05    NPEAK  550  : ?  linear fit
+ 4.947403 sec  9.00    NPEAK  550  : ?  linear fit 
+ 0.2      sec  0.02    NPIX 8300 k : ?  found grown footprints: 
+ 0.205680 sec  0.02    NPIX 8300 k : ?  find footprints
+ 0.211664 sec  0.03    NPIX 8300 k : ?  replace background
+ 0.348357 sec  0.04    NPIX 8300 k : ?  subtracted background
+ 0.598805 sec  0.07    NPIX 8300 k : ?  find peaks
+ 0.599952 sec  0.07    NPIX 8300 k : ?  find peaks 
+ 0.723508 sec  0.09    NPIX 8300 k : ?  found footprints: 
+ 1.4      sec  0.17    NPIX 8300 k : ?  found grown footprints: 
+ 0.809106 sec 12.64    NPSF    64  : ?  psf fit
+ 2.155031 sec 34.21    NPSF    63  : ?  full fit
+ 2.592620 sec 74.07    NPSF    35  : ?  psf residuals
+ 5.931090 sec  0.71   sNPIX 8300 k : ?  smoothed signficance
+ 7.780419 sec  0.94   sNPIX 8300 k : ?  smoothed signficance
+12.947970 sec  1.56   sNPIX 8300 k : ?  convolved with grow disc: 
+14.525486 sec  1.75   sNPIX 8300 k : ?  convolved with grow disc: 
+
+Notes:
+
+Note:
+
+* PSF Residuals is the most expensive per item, but will always be
+  performed on a limited number of items (typically < 300 PSF stars).
+  The maximum impact is thus limited.
+
+* The non-linear fitting is (not surprisingly) very expensive per
+  item, but again will only be performed on a limited subset (S/N >
+  20?).
+
+* the linear fits are the next most costly, and will dominate the
+  timing since all sources must be so fit, and multiple times.
+
+* measure magnitudes is expensive, but only runs once
+
+* measure moments is expensive, but only runs once (and/or on a bright subset?)
+
+Adding it up:
+
+GPC1 : 10^11 det for 60*5000* 60 chips --> 5500 det / chip
+     : 23 megapix
+
+* cost per object:
+  
+  56.5 msec -> 310 sec for detection analysis (on kawelu, not optimized)
+
+* cost for bright detections
+
+  ~ 35 sec (for 1000 bright sources)
+
+* cost per megapixel:
+
+  5.5 sec
+
+  -> 126 sec for GPC1
+
+* other overhead (psf construction, background, smoothing)
+
+  -> 20 sec
+
+** total : 490 sec (kawelu, not optimized, 1.0GHz!)
+
+** ~ 220 sec optimized 
+** ~ 100 sec on 2.3GHz machines
+(probably there are other gains on the real hardware: memory bandwidth, ?)
+
+assuming 100sec is all we get, we need ~1.5 cores per chip to keep up at 60sec / exposure (average)
+
+120 cores for ppImage (chip)
+
Index: /branches/eam_branches/eam_branch_20080719/psphot/doc/timing.v3.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/doc/timing.v3.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/doc/timing.v3.txt	(revision 22158)
@@ -0,0 +1,39 @@
+0.000408 sec    found 0 satstar blend peaks, leaving 551 sources: 
+0.002058 sec    measure source sizes for 551 sources: 
+0.003553 sec    measure source sizes for 1302 sources: 
+0.009676 sec    identified 36 blended objects: 
+0.026266 sec    replaced models for 551 objects: 
+0.026892 sec    sub noise for 551 objects: 
+0.026924 sec    add noise for 551 objects: 
+0.029050 sec    replaced models for 551 objects: 
+0.032975 sec    set footprint array IDs: 
+0.047061 sec    set footprint array IDs: 
+0.080533 sec    rough classification: 
+0.107024 sec    replace background flux : 
+0.111200 sec    found 631 footprints: 
+0.132417 sec    rough classification: 
+0.182467 sec    subtracted background model: 
+0.2      sec    cull peaks
+0.297289 sec    2676 peaks: 
+0.3      sec    rest of foot
+0.300492 sec    849 peaks: 
+0.364908 sec    found 7613 footprints: 
+0.393265 sec    measure ensemble of PSFs: 
+0.405241 sec    build median image: 
+0.454711 sec    measure ensemble of PSFs: 
+0.680027 sec    measure ensemble of PSFs: 
+0.900696 sec    751 sources, 290 moments, 9 failed: 
+1.1 sec    rest of footpr
+1.147541 sec    built models for 551 objects: 
+1.289976 sec    generate residuals for 35 objects: 
+1.456877 sec    built models for 751 objects: 
+1.5      sec    select psf model (ex resid)
+1.661166 sec    551 sources, 551 moments, 8 failed: 
+2.988601 sec    built smoothed signficance image: 
+3.677652 sec    built smoothed signficance image: 
+4.354904 sec    measure magnitudes :  for 1302 objects (634 with apertures)
+5.8 sec    cull peaks
+6.594287 sec    convolved with grow disc: 
+7.413455 sec    convolved with grow disc: 
+7.616990 sec    fit models:  for 417 objects (354 psf, 31 ext, 32 failed, 134 skipped)
+55.393567 sec    complete psphot run: 
Index: /branches/eam_branches/eam_branch_20080719/psphot/doc/versions.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/doc/versions.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/doc/versions.txt	(revision 22158)
@@ -0,0 +1,49 @@
+
+2006.02.02
+  I'm tagging psphot after I updated it to work with the readouts
+  using the structures being used for ppImage.  In this release, I
+  have also moved to autoconf for psphot, and the psphotReadout
+  portion is being defined as a library against which the other
+  elements are linked.  It should be possible to use this library with
+  ppImage, but I have not yet tested that.  
+
+  link psphot_dev_08 against psLib:eam_rel9_b2 and
+  psModule:eam_rel9_b2.
+
+2006.01.18
+  the tag below (psphot_dev_07) was moved to a later release.  It
+  should be used with psLib:eam_rel9_b1 from 2006/1/18 and
+  psModule:eam_rel9_p0.  
+
+2005.12.23
+  psphot_dev_07 should be compiled against psLib:eam_rel9_b1 and
+  psModule:eam_rel9_b1.  This version now handles the ensemble PSF
+  fitting, detection of blended sources, fitting of 'blends' (groups
+  of PSFs with distinct be 'blended' peaks) and 'blobs' (unresolved
+  extended objects, with a test for double PSF vs extended source
+  model.
+
+2005.11.25
+
+  psphot_dev_05 should be compiled against psLib tag eam_rel8_b2 and
+  psModules tag eam_rel8_b1.  this version removes all _EAM versions
+  of psLib and psModules code.  It now uses the psModules version of
+  the object code.
+
+  psphot_dev_04 should be compiled against psLib tag eam_rel8_b2 this
+  version removes all _EAM versions of psLib code, so that it is now
+  consistent with psLib.v8 (fixes are pushed into the eam_rel8_b2
+  branch).
+
+2005.11.16
+
+  psphot_dev_03 should be compiled against psLib tag eam_rel8_b1, a
+  branch starting from psLib rel8_0.  I needed to make some minor
+  fixes in psLib to work successfully with psLib rel8_0.
+
+  psphot_dev_02 was getting segfaults from a bug added into psLib in
+  rel8_0 in p_psVectorClippedStats.  I also fixed some errors arising
+  from changing types (argument to psMetadataParseConfig).
+
+
+
Index: /branches/eam_branches/eam_branch_20080719/psphot/psphot-config.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/psphot-config.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/psphot-config.in	(revision 22158)
@@ -0,0 +1,87 @@
+#! /bin/sh
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+top_srcdir=@ABS_SRCDIR@
+
+usage()
+{
+    cat <<EOF
+Usage: psphot-config [OPTION]
+
+Known values for OPTION are:
+
+  --prefix		print psphot installation prefix
+  --libs		print library linking information
+  --cflags		print pre-processor and compiler flags
+  --build-libs		print library linking information to the build (non-installed) version
+  --build-cflags	print pre-processor and compiler flags to the build (non-installed) version
+  --help		display this help and exit
+  --version		output version information
+
+EOF
+
+    exit $1
+}
+
+if test $# -eq 0; then
+    usage 1
+fi
+
+cflags=false
+libs=false
+
+while test $# -gt 0; do
+    case "$1" in
+    -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+    *) optarg= ;;
+    esac
+
+    case "$1" in
+    --prefix=*)
+	prefix=$optarg
+	;;
+
+    --prefix)
+	echo $prefix
+	;;
+
+    --version)
+	echo @VERSION@
+	exit 0
+	;;
+
+    --help)
+	usage 0
+	;;
+
+    --cflags)
+       	echo -I${includedir} @PSPHOT_CFLAGS@
+       	;;
+
+    --libs)
+       	echo -L${libdir} -lpsphot @PSPHOT_LIBS@
+       	;;
+
+    --build-cflags)
+       	echo @SRCINC@ @PSPHOT_CFLAGS@
+       	;;
+
+    --build-libs)
+       	echo -L@ABS_SRCDIR@/src/.libs -lpsphot @PSPHOT_LIBS@
+       	;;
+
+    --deps)
+       	echo @PSPHOT_LIBS@
+       	;;
+    *)
+	usage
+	exit 1
+	;;
+    esac
+    shift
+done
+
+exit 0
Index: /branches/eam_branches/eam_branch_20080719/psphot/psphot.pc.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/psphot.pc.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/psphot.pc.in	(revision 22158)
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libpsphot
+Description: Pan-STARRS Photometry Library
+Version: @VERSION@
+Requires: pslib psmodules
+Libs: -L${libdir} -lpsphot
+Libs.private: @PSPHOT_LIBS@
+Cflags: -I${includedir}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/.cvsignore	(revision 22158)
@@ -0,0 +1,18 @@
+*.o
+*.lo
+.libs
+.deps
+Makefile
+Makefile.in
+libpsphot.la
+psphot
+psphotTest
+psphot.loT
+psphotErrorCodes.h
+psphotErrorCodes.c
+config.h
+config.h.in
+stamp-h1
+
+polyfitTest
+growthTest
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/Makefile.am	(revision 22158)
@@ -0,0 +1,107 @@
+
+lib_LTLIBRARIES = libpsphot.la
+libpsphot_la_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PSPHOT_CFLAGS)
+
+bin_PROGRAMS = psphot
+
+psphot_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PSPHOT_CFLAGS)
+psphot_LDFLAGS = $(PSLIB_LIBS) $(PSMODULE_LIBS) $(PSPHOT_LIBS)
+psphot_LDADD = libpsphot.la
+
+psphot_SOURCES = \
+        psphot.c                \
+	psphotArguments.c	\
+	psphotCleanup.c	   	\
+	psphotImageLoop.c	\
+	psphotMosaicChip.c	\
+	psphotSetMaskBits.c	\
+	psphotParseCamera.c
+
+libpsphot_la_SOURCES = \
+	psphotErrorCodes.c	       \
+	psphotCullPeaks.c	       \
+	psphotVersion.c		       \
+	psphotModelGroupInit.c	       \
+	psphotMaskReadout.c	       \
+	psphotDefineFiles.c	       \
+	psphotReadout.c		       \
+	psphotModelBackground.c	       \
+	psphotSubtractBackground.c     \
+	psphotFindDetections.c	       \
+	psphotFindPeaks.c	       \
+	psphotFindFootprints.c	       \
+	psphotSignificanceImage.c      \
+	psphotSourceStats.c	       \
+	psphotRoughClass.c	       \
+	psphotBasicDeblend.c	       \
+	psphotChoosePSF.c	       \
+	psphotGuessModels.c            \
+	psphotFitSourcesLinear.c       \
+	psphotBlendFit.c	       \
+	psphotReplaceUnfit.c	       \
+	psphotApResid.c		       \
+	psphotMagnitudes.c	       \
+	psphotSkyReplace.c	       \
+	psphotEvalPSF.c		       \
+	psphotEvalFLT.c		       \
+	psphotSourceFits.c	       \
+	psphotRadiusChecks.c	       \
+	psphotOutput.c		       \
+	psphotFakeSources.c	       \
+	psphotModelWithPSF.c           \
+	psphotExtendedSourceAnalysis.c \
+	psphotExtendedSourceFits.c     \
+	psphotRadialProfile.c	       \
+	psphotPetrosian.c	       \
+	psphotIsophotal.c	       \
+	psphotAnnuli.c		       \
+	psphotKron.c		       \
+	psphotKernelFromPSF.c	       \
+	psphotPSFConvModel.c	       \
+	psphotModelTest.c	       \
+	psphotFitSet.c		       \
+	psphotSourceFreePixels.c       \
+	psphotSummaryPlots.c           \
+	psphotMergeSources.c	       \
+	psphotLoadPSF.c	               \
+	psphotReadoutCleanup.c	       \
+	psphotSourcePlots.c	       \
+	psphotRadialPlot.c	       \
+	psphotDeblendSatstars.c	       \
+	psphotMosaicSubimage.c	       \
+	psphotMakeResiduals.c	       \
+	psphotSourceSize.c	       \
+	psphotDiagnosticPlots.c	       \
+	psphotMakeFluxScale.c	       \
+	psphotCheckStarDistribution.c  \
+	psphotAddNoise.c
+
+# dropped? psphotGrowthCurve.c
+
+include_HEADERS = \
+	psphot.h \
+	psphotErrorCodes.h
+
+noinst_HEADERS = \
+	psphotInternal.h \
+	psphotStandAlone.h
+
+clean-local:
+	-rm -f TAGS
+
+# Tags for emacs
+tags:
+	etags `find . -name \*.[ch] -print`
+
+# Error codes.
+BUILT_SOURCES = psphotErrorCodes.h psphotErrorCodes.c
+CLEANFILES = psphotErrorCodes.h psphotErrorCodes.c
+EXTRA_DIST = psphotErrorCodes.dat psphotErrorCodes.c.in psphotErrorCodes.h.in \
+	models/pmModel_STRAIL.c \
+	models/pmModel_TEST1.c
+
+psphotErrorCodes.h : psphotErrorCodes.dat psphotErrorCodes.h.in
+	$(ERRORCODES) --data=psphotErrorCodes.dat --outdir=. psphotErrorCodes.h
+
+psphotErrorCodes.c : psphotErrorCodes.dat psphotErrorCodes.c.in psphotErrorCodes.h
+	$(ERRORCODES) --data=psphotErrorCodes.dat --outdir=. psphotErrorCodes.c
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/models/pmModel_STRAIL.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/models/pmModel_STRAIL.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/models/pmModel_STRAIL.c	(revision 22158)
@@ -0,0 +1,618 @@
+
+/******************************************************************************
+    params->data.F32[0] = So;
+    params->data.F32[1] = Zo;
+    params->data.F32[2] = Xo;
+    params->data.F32[3] = Yo;
+    params->data.F32[4] = 1 / SigmaX;
+    params->data.F32[5] = 1 / SigmaY;
+    params->data.F32[6] = Sxy;
+    params->data.F32[7] = length;
+    params->data.F32[8] = theta;
+*****************************************************************************/
+
+# define PM_MODEL_FUNC            pmModelFunc_STRAIL
+# define PM_MODEL_FLUX            pmModelFlux_STRAIL
+# define PM_MODEL_GUESS           pmModelGuess_STRAIL
+# define PM_MODEL_LIMITS          pmModelLimits_STRAIL
+# define PM_MODEL_RADIUS          pmModelRadius_STRAIL
+# define PM_MODEL_FROM_PSF        pmModelFromPSF_STRAIL
+# define PM_MODEL_PARAMS_FROM_PSF pmModelParamsFromPSF_STRAIL
+# define PM_MODEL_FIT_STATUS      pmModelFitStatus_STRAIL
+
+psF32 PM_MODEL_FUNC(psVector *deriv,
+                         const psVector *params,
+                         const psVector *x)
+{
+    psF32 *PAR = params->data.F32;
+
+    psF32 trailLength = PAR[7];
+    psF32 theta = PAR[8];
+
+    psF32 x0 = PAR[2];  //streak center
+    psF32 y0 = PAR[3];  //streak center
+
+    //S values (1/sigma for x and y case, sigma for xy case)
+    psF32 sx = PAR[4];
+    psF32 sy = PAR[5];
+    psF32 sxy = PAR[6];
+
+    psF32 sinT=sin(theta);
+    psF32 cosT=cos(theta);
+    psF32 sin2T=sin(2.0*theta);
+    psF32 cos2T=cos(2.0*theta);
+
+    //    printf("Trying object at %4.1f,%4.1f with length %3.1f and angle %1.3f\r", x0, y0, length, theta);
+
+    //current location relative to trail center
+    psF32 X  = x->data.F32[0] - x0;
+    psF32 Y  = x->data.F32[1] - y0;
+
+    //x' and y' location (trail-orienter coords)
+    psF32 xs = X*cosT + Y*sinT;
+    psF32 ys = -1.0*X*sinT + Y*cosT;
+
+    //initialize variables to be changed below
+    psF32 x1 = 0;
+    psF32 y1 = 0;
+    psF32 px = 0;
+    psF32 py = 0;
+    psF32 z  = 0;
+    psF32 zx = 0;
+    psF32 t  = 0;
+    psF32 tx = 0;
+    psF32 r  = 0;
+    psF32 rx = 0;
+    psF32 f  = 0;
+
+    psF32 sxrot = 0;
+    psF32 syrot = 0;
+    psF32 sxyrot = 0;
+    psF32 dsxrot = 0;
+    psF32 dsyrot = 0;
+    psF32 dsxyrot = 0;
+
+    //    psF32 Rx = 0;
+    //    psF32 Ry = 0;
+    //    psF32 Rxy = 0;
+
+
+    //calculate new S values (1/sigma) for rotated frame
+    psF32 sxrotsq = PS_SQR(cosT*sx) + PS_SQR(sinT*sy) + cosT*sinT*sxy;
+    psF32 syrotsq = PS_SQR(cosT*sy) + PS_SQR(sinT*sx) - cosT*sinT*sxy;
+
+    //    psF32 testtwo=10.1;
+    //    psF32 testone=fabsf(testtwo);
+    //    fprintf (stderr, "Test: %f is the absolute value of %f?\n",testone,testtwo);
+    if (sxrotsq<0) {
+      sxrot = sqrt(-(sxrotsq));
+      syrot = sqrt(syrotsq);
+      fprintf (stderr, "error in sxrotsq: Neg,  sxrotsq=%f sx=%f sy=%f sxy=%f theta=%f\n",sxrotsq,sx,sy,sxy,theta);
+    } else if (syrotsq<0) {
+      sxrot = sqrt(sxrotsq);
+      syrot = sqrt(-(syrotsq));
+      fprintf (stderr, "error in syrotsq: Neg,  syrotsq=%f sx=%f sy=%f sxy=%f theta=%f\n",syrotsq,sx,sy,sxy,theta);
+    } else if (sxrotsq==0){
+      sxrot = 0.01;
+      syrot = sqrt(syrotsq);
+      fprintf (stderr, "error in sxrotsq: Zero,  sxrotsq=%f \n",sxrotsq);
+    } else if (syrotsq==0) {
+      syrot = 0.01;
+      sxrot = sqrt(sxrotsq);
+      fprintf (stderr, "error in syrotsq: Zero,  syrotsq=%f \n",syrotsq);
+      //      return(0);
+    }else {
+      sxrot = sqrt(sxrotsq);
+      syrot = sqrt(syrotsq);
+    }
+
+    sxyrot = sxy*cos2T + (PS_SQR(sy) - PS_SQR(sx))*sin2T;
+
+      if (isnan(sxrot)) {
+        fprintf (stderr, "error in sxrot  syrot=%f sx=%f sy=%f sxy=%f cosT=%f sinT=%f\n",syrot,sx,sy,sxy,cosT,sinT);
+      } else if (isnan(syrot)) {
+        fprintf (stderr, "error in syrot  sxrot=%f sx=%f sy=%f sxy=%f cosT=%f sinT=%f\n",sxrot,sx,sy,sxy,cosT,sinT);
+      }
+
+    //calculate length of pipe (not of trail motion)
+    psF32 length = trailLength - 2.0*2.0/sxrot;
+
+
+    if (xs < length/(-2.0)) {
+      x1 = (xs+length/2.0)*cosT - ys*sinT; //Endpoint1
+      y1 = (xs+length/2.0)*sinT + ys*cosT; //Endpoint1
+      //1.6 factor comes from by-eye testing of fits, sqrt from the later squaring of it
+      //1.6 ~= phi (golden mean)...coincidence?
+      px = sxrot*x1/sqrt(1.6);
+      py = syrot*y1;
+
+      //first find out what the falloff in the x direction is...
+      zx  = 0.5*PS_SQR(px);
+      tx = 1 + zx + zx*zx/2.0 + zx*zx*zx/6.0;
+      rx = 1.0 / (tx + zx*zx*zx*zx/24.0);
+
+      //...and now in the y direction
+      z  = 0.5*PS_SQR(py)+sxyrot*x1*y1;
+      t  = 1 + z + z*z/2.0;
+      r  = 1.0 / (t + z*z*z/6.0); /* exp (-Z) */
+      f  = PAR[1]*rx*r + PAR[0];
+
+    } else if (xs > length/2.0){
+      x1 = (xs-length/2.0)*cosT - ys*sinT; //Endpoint2
+      y1 = (xs-length/2.0)*sinT + ys*cosT; //Endpoint2
+      px = sxrot*x1/sqrt(1.6);
+      py = syrot*y1;
+      zx  = 0.5*PS_SQR(px);
+      tx = 1 + zx + zx*zx/2.0 + zx*zx*zx/6.0;
+      rx = 1.0 / (tx + zx*zx*zx*zx/24.0);
+
+      z  = 0.5*PS_SQR(py)+sxyrot*x1*y1;
+      t  = 1 + z + z*z/2.0;
+      r  = 1.0 / (t + z*z*z/6.0); /* exp (-Z) */
+      f  = PAR[1]*rx*r + PAR[0];
+
+      if (isnan(r)) {
+        fprintf (stderr, "error in +r  t=%f z=%f\n",t,z);
+      }
+
+    } else {
+      x1 = -ys*sinT;
+      y1 = ys*cosT;
+      px = sx*x1;
+      py = sy*y1;
+      z  = 0.5*PS_SQR(px) + 0.5*PS_SQR(py) + sxy*x1*y1;
+      t  = 1 + z + z*z/2.0;
+      r  = 1.0 / (t + z*z*z/6.0); /* exp (-Z) */
+      rx = 1.0;  //so that dF/dF0 can be generalized
+      f  = PAR[1]*r + PAR[0];
+
+      if (isnan(r)) {
+        fprintf (stderr, "error in midr  t=%f z=%f\n",t,z);
+      }
+    }
+
+
+    //ok...so this is df/dPAR[X]
+    if (deriv != NULL) {
+        psF32 q = 1;
+        //stable
+        deriv->data.F32[0] = +1.0;
+        deriv->data.F32[1] = +r * rx;
+
+          if (isnan(deriv->data.F32[0])) {
+            fprintf (stderr, "error in deriv0\n");
+          } else if (isnan(deriv->data.F32[1])) {
+            fprintf (stderr, "error in deriv1 r=%f rx=%f\n",r,rx);
+          }
+
+        dsxrot = 2.0*PS_SQR(sy)*sinT*cosT - 2.0*PS_SQR(sx)*sinT*cosT + sxy*(PS_SQR(cosT)-PS_SQR(sinT));
+        dsyrot = 2.0*PS_SQR(sx)*sinT*cosT - 2.0*PS_SQR(sy)*sinT*cosT - sxy*(PS_SQR(cosT)-PS_SQR(sinT));
+        dsxyrot = 2.0*cos2T*(PS_SQR(sy)-PS_SQR(sx)) - 2.0*sxy*sin2T;
+
+          if (isnan(dsxrot)) {
+            fprintf (stderr, "error in dsxrot\n");
+          } else if (isnan(dsyrot)) {
+            fprintf (stderr, "error in dsyrot\n");
+          } else if (isnan(dsxyrot)) {
+            fprintf (stderr, "error in dsxyrot\n");
+          }
+
+        //initialize variables definied in the if statements
+        //      psF32 XXX=0;
+        //      psF32 YYY=0;
+
+
+        // variable over piecewise func
+        // change the endcaps to be 4th order gaussians with sxrot_fit=1.6*sxrot
+        // y' direction can ge adequately modelled by a 3rd order gaussian with syrot
+        if (xs < length/(-2.0)) {
+
+          q=PAR[1]*r*rx;
+          deriv->data.F32[2] = -q*(rx*tx/1.6*x1*PS_SQR(sxrot) + r*t*y1*sxyrot);
+          deriv->data.F32[3] = -q*r*t*(y1*PS_SQR(syrot) + x1*sxyrot);
+          deriv->data.F32[4] = -q*(rx*tx*x1*sx*PS_SQR(cosT)/1.6*(x1+2.0*cosT/sxrot) + r*t*y1*sx*sinT*(y1*sinT+2.0*PS_SQR(syrot)*PS_SQR(cosT)/(sxrot*sxrot*sxrot)) + 2.0*r*t*sx*(-1.0*x1*y1*sin2T+y1*sxyrot*(cosT*cosT*cosT)/(sxrot*sxrot*sxrot)+x1*sxyrot*(sinT*cosT*cosT)/(sxrot*sxrot*sxrot)));
+          deriv->data.F32[5] = -q*(rx*tx*x1*sy*PS_SQR(sinT)/1.6*(x1+2.0*cosT/sxrot) + r*t*y1*sy*(y1*PS_SQR(cosT)+2.0*PS_SQR(syrot)*(sinT*sinT*sinT)/(sxrot*sxrot*sxrot)) + 2.0*r*t*sy*(x1*y1*sin2T+y1*sxyrot*(sinT*sinT*cosT)/(sxrot*sxrot*sxrot)+x1*sxyrot*(sinT*sinT*sinT)/(sxrot*sxrot*sxrot)));
+          deriv->data.F32[6] = -q*(rx*tx*x1*cosT*sinT/3.2*(x1+2.0*cosT/sxrot) + r*t*y1*cosT*sinT/2.0*(-y1+2.0*PS_SQR(syrot)*sinT/(sxrot*sxrot*sxrot)) + r*t*(x1*y1*cos2T+y1*sxyrot*sinT*cosT*cosT/(sxrot*sxrot*sxrot)+x1*sxyrot*sinT*sinT*cosT/(sxrot*sxrot*sxrot)));
+          deriv->data.F32[7] = -q*(rx*tx*PS_SQR(sxrot)*x1*cosT/3.2 + r*t*PS_SQR(syrot)*y1*sinT/2.0 + r*t*sxyrot/2.0*(y1*cosT+x1*sinT));
+          deriv->data.F32[8] = -q*(rx*tx*x1/3.2*(x1*(2.0*sinT*cosT*(PS_SQR(sy)-PS_SQR(sx))+sxy*(PS_SQR(cosT)-PS_SQR(sinT)))+PS_SQR(sxrot)*(2.0*cosT*(2.0*sinT*cosT*(PS_SQR(sy)-PS_SQR(sx))+sxy*(PS_SQR(cosT)-PS_SQR(sinT)))/(sxrot*sxrot*sxrot) - sinT*length)) + r*t*y1/2.0*(y1*(2.0*sinT*cosT*(PS_SQR(sx)-PS_SQR(sy))-sxy*(PS_SQR(cosT)-PS_SQR(sinT)))+PS_SQR(syrot)*(2.0*sinT*(2.0*sinT*cosT*(PS_SQR(sy)-PS_SQR(sx))+sxy*(PS_SQR(cosT)-PS_SQR(sinT)))/(sxrot*sxrot*sxrot)+cosT*length)) + r*t*(2.0*x1*y1*(cos2T*(PS_SQR(sy)-PS_SQR(sx))-sxy*sin2T)+y1*sxyrot/2.0*(2.0*cosT*(2.0*sinT*cosT*(PS_SQR(sy)-PS_SQR(sx))+sxy*(PS_SQR(cosT)-PS_SQR(sinT)))/(sxrot*sxrot*sxrot)-length*sinT)+x1*sxyrot/2.0*(2.0*sinT*(2.0*sinT*cosT*(PS_SQR(sy)-PS_SQR(sx))+sxy*(PS_SQR(cosT)-PS_SQR(sinT)))/(sxrot*sxrot*sxrot)+length*cosT)));
+
+          /*      if (isnan(deriv->data.F32[2])) {
+            fprintf (stderr, "error in deriv2\n");
+          } else if (isnan(deriv->data.F32[3])) {
+            fprintf (stderr, "error in deriv3\n");
+          } else if (isnan(deriv->data.F32[4])) {
+            fprintf (stderr, "error in deriv4\n");
+          } else if (isnan(deriv->data.F32[5])) {
+            fprintf (stderr, "error in deriv5\n");
+          } else if (isnan(deriv->data.F32[6])) {
+            fprintf (stderr, "error in deriv6\n");
+          } else if (isnan(deriv->data.F32[7])) {
+            fprintf (stderr, "error in deriv7\n");
+          } else if (isnan(deriv->data.F32[8])) {
+            fprintf (stderr, "error in deriv8\n");
+          }
+          */
+
+
+
+        } else if (xs > length/2.0){
+
+          q=PAR[1]*r*rx;
+          deriv->data.F32[2] = -q*(rx*tx/1.6*x1*PS_SQR(sxrot) + r*t*y1*sxyrot);
+          deriv->data.F32[3] = -q*r*t*(y1*PS_SQR(syrot) + x1*sxyrot);
+          deriv->data.F32[4] = -q*(rx*tx*x1*sx*PS_SQR(cosT)/1.6*(x1-2.0*cosT/sxrot) + r*t*y1*sx*sinT*(y1*sinT-2.0*PS_SQR(syrot)*PS_SQR(cosT)/(sxrot*sxrot*sxrot)) + 2.0*r*t*sx*(-1.0*x1*y1*sin2T-y1*sxyrot*(cosT*cosT*cosT)/(sxrot*sxrot*sxrot)-x1*sxyrot*(sinT*cosT*cosT)/(sxrot*sxrot*sxrot)));
+          deriv->data.F32[5] = -q*(rx*tx*x1*sy*PS_SQR(sinT)/1.6*(x1-2.0*cosT/sxrot) + r*t*y1*sy*(y1*PS_SQR(cosT)-2.0*PS_SQR(syrot)*(sinT*sinT*sinT)/(sxrot*sxrot*sxrot)) + 2.0*r*t*sy*(x1*y1*sin2T-y1*sxyrot*(sinT*sinT*cosT)/(sxrot*sxrot*sxrot)-x1*sxyrot*(sinT*sinT*sinT)/(sxrot*sxrot*sxrot)));
+          deriv->data.F32[6] = -q*(rx*tx*x1*cosT*sinT/3.2*(x1-2.0*cosT/sxrot) + r*t*y1*cosT*sinT/2.0*(-y1-2.0*PS_SQR(syrot)*sinT/(sxrot*sxrot*sxrot)) + r*t*(x1*y1*cos2T-y1*sxyrot*sinT*cosT*cosT/(sxrot*sxrot*sxrot)-x1*sxyrot*sinT*sinT*cosT/(sxrot*sxrot*sxrot)));
+          deriv->data.F32[7] = q*(rx*tx*PS_SQR(sxrot)*x1*cosT/3.2 + r*t*PS_SQR(syrot)*y1*sinT/2.0 + r*t*sxyrot/2.0*(y1*cosT+x1*sinT));
+          deriv->data.F32[8] = -q*(rx*tx*x1/3.2*(x1*(2.0*sinT*cosT*(PS_SQR(sy)-PS_SQR(sx))+sxy*(PS_SQR(cosT)-PS_SQR(sinT)))-PS_SQR(sxrot)*(2.0*cosT*(2.0*sinT*cosT*(PS_SQR(sy)-PS_SQR(sx))+sxy*(PS_SQR(cosT)-PS_SQR(sinT)))/(sxrot*sxrot*sxrot) - sinT*length)) + r*t*y1/2.0*(y1*(2.0*sinT*cosT*(PS_SQR(sx)-PS_SQR(sy))-sxy*(PS_SQR(cosT)-PS_SQR(sinT)))-PS_SQR(syrot)*(2.0*sinT*(2.0*sinT*cosT*(PS_SQR(sy)-PS_SQR(sx))+sxy*(PS_SQR(cosT)-PS_SQR(sinT)))/(sxrot*sxrot*sxrot)+cosT*length)) + r*t*(2.0*x1*y1*(cos2T*(PS_SQR(sy)-PS_SQR(sx))-sxy*sin2T)-y1*sxyrot/2.0*(2.0*cosT*(2.0*sinT*cosT*(PS_SQR(sy)-PS_SQR(sx))+sxy*(PS_SQR(cosT)-PS_SQR(sinT)))/(sxrot*sxrot*sxrot)-length*sinT)-x1*sxyrot/2.0*(2.0*sinT*(2.0*sinT*cosT*(PS_SQR(sy)-PS_SQR(sx))+sxy*(PS_SQR(cosT)-PS_SQR(sinT)))/(sxrot*sxrot*sxrot)+length*cosT)));
+
+
+          /*      if (isnan(deriv->data.F32[2])) {
+            fprintf (stderr, "error in deriv2\n");
+          } else if (isnan(deriv->data.F32[3])) {
+            fprintf (stderr, "error in deriv3\n");
+          } else if (isnan(deriv->data.F32[4])) {
+            fprintf (stderr, "error in deriv4\n");
+          } else if (isnan(deriv->data.F32[5])) {
+            fprintf (stderr, "error in deriv5\n");
+          } else if (isnan(deriv->data.F32[6])) {
+            fprintf (stderr, "error in deriv6\n");
+          } else if (isnan(deriv->data.F32[7])) {
+            fprintf (stderr, "error in deriv7\n");
+          } else if (isnan(deriv->data.F32[8])) {
+            fprintf (stderr, "error in deriv8\n");
+          }
+          */
+
+        } else {
+          // this does not change from before, as the y' falloff can be modelled by the standard 3rd order gaussian
+          // note difference from a pure gaussian: q = PAR[1]*r
+          q = PAR[1]*r*r*t;
+          deriv->data.F32[2] = q*(PS_SQR(sx*sinT)*x1 - PS_SQR(sy)*y1*cosT*sinT - sxy*x1*sinT*cosT + sxy*y1*PS_SQR(sinT));
+          deriv->data.F32[3] = q*(-1*PS_SQR(sx)*x1*sinT*cosT + PS_SQR(sy*cosT)*y1 + sxy*x1*PS_SQR(cosT) - sxy*y1*sinT*cosT);
+          deriv->data.F32[4] = -q*sx*PS_SQR(x1);
+          deriv->data.F32[5] = -q*sy*PS_SQR(y1);
+          deriv->data.F32[6] = -q*x1*y1;
+          deriv->data.F32[7] = 0;
+          deriv->data.F32[8] = -q*( PS_SQR(sx)*x1*(xs*sinT - ys*cosT) + PS_SQR(sy)*y1*(xs*cosT - ys*sinT) + sxy*x1*(xs*cosT - ys*sinT) + sxy*y1*(xs*sinT - ys*cosT) );
+
+          if (isnan(deriv->data.F32[2])) {
+            fprintf (stderr, "error in deriv2\n");
+          } else if (isnan(deriv->data.F32[3])) {
+            fprintf (stderr, "error in deriv3\n");
+          } else if (isnan(deriv->data.F32[4])) {
+            fprintf (stderr, "error in deriv4\n");
+          } else if (isnan(deriv->data.F32[5])) {
+            fprintf (stderr, "error in deriv5\n");
+          } else if (isnan(deriv->data.F32[6])) {
+            fprintf (stderr, "error in deriv6\n");
+          } else if (isnan(deriv->data.F32[7])) {
+            fprintf (stderr, "error in deriv7\n");
+          } else if (isnan(deriv->data.F32[8])) {
+            fprintf (stderr, "error in deriv8\n");
+          }
+
+
+        }
+    }
+    return(f);
+}
+
+//fixed
+// XXX this needs to apply the axis ratio limits to prevent avoid solutions
+# define AR_MAX 20.0
+# define AR_RATIO 0.99
+bool PM_MODEL_LIMITS (psMinConstraintMode mode, int nParam, float *params, float *beta) {
+
+    float beta_lim = 0;
+    float params_min = 0;
+    float params_max = 0;
+    float f1, f2, q1;
+    float q2 = 0;
+
+    // we need to calculate the limits for SXY specially
+    if (nParam == PM_PAR_SXY) {
+        f1 = 1.0 / PS_SQR(params[PM_PAR_SYY]) + 1.0 / PS_SQR(params[PM_PAR_SXX]);
+        f2 = 1.0 / PS_SQR(params[PM_PAR_SYY]) - 1.0 / PS_SQR(params[PM_PAR_SXX]);
+        q1 = PS_SQR(f1)*AR_RATIO - PS_SQR(f2);
+        assert (q1 > 0);
+        q2  = 0.5*sqrt (q1);
+    }
+
+    switch (mode) {
+      case PS_MINIMIZE_BETA_LIMIT:
+        switch (nParam) {
+          case PM_PAR_SKY:  beta_lim = 1000;   break;
+          case PM_PAR_I0:   beta_lim = 10000;    break; // too small?
+          case PM_PAR_XPOS: beta_lim = 50;     break;
+          case PM_PAR_YPOS: beta_lim = 50;     break;
+          case PM_PAR_SXX:  beta_lim = 0.5;    break;
+          case PM_PAR_SYY:  beta_lim = 0.5;    break;
+          case PM_PAR_SXY:  beta_lim = 1.0;    break;  // set this to q2?
+          case 7:           beta_lim = 10.0;     break;
+          case 8:           beta_lim = M_PI/6.0; break;
+
+          default:
+            psAbort("invalid parameter %d for beta test", nParam);
+        }
+        if (fabs(beta[nParam]) > fabs(beta_lim)) {
+            beta[nParam] = (beta[nParam] > 0) ? fabs(beta_lim) : -fabs(beta_lim);
+            return false;
+        }
+        return true;
+      case PS_MINIMIZE_PARAM_MIN:
+        switch (nParam) {
+          case PM_PAR_SKY:  params_min = -1000; break;
+          case PM_PAR_I0:   params_min =     0; break;
+          case PM_PAR_XPOS: params_min =  -100; break;
+          case PM_PAR_YPOS: params_min =  -100; break;
+          case PM_PAR_SXX:  params_min =   0.5; break;
+          case PM_PAR_SYY:  params_min =   0.5; break;
+          case PM_PAR_SXY:  params_min =  -5.0; break; // set this to -q2?
+          case 7:           params_min =     0;  break;
+          case 8:           params_min = -1*M_PI; break;
+
+          default:
+            psAbort("invalid parameter %d for param min test", nParam);
+        }
+        if (params[nParam] < params_min) {
+            params[nParam] = params_min;
+            return false;
+        }
+        return true;
+      case PS_MINIMIZE_PARAM_MAX:
+        switch (nParam) {
+          case PM_PAR_SKY:  params_max =   1e5; break;
+          case PM_PAR_I0:   params_max =   1e8; break;
+          case PM_PAR_XPOS: params_max =   1e4; break;
+          case PM_PAR_YPOS: params_max =   1e4; break;
+          case PM_PAR_SXX:  params_max =   100; break;
+          case PM_PAR_SYY:  params_max =   100; break;
+          case PM_PAR_SXY:  params_max =   +q2; break;
+          case 7:           params_max =   150; break;
+          case 8:           params_max =  M_PI; break;
+          default:
+            psAbort("invalid parameter %d for param max test", nParam);
+        }
+        if (params[nParam] > params_max) {
+            params[nParam] = params_max;
+            return false;
+        }
+        return true;
+      default:
+        psAbort("invalid choice for limits");
+    }
+    psAbort("should not reach here");
+    return false;
+}
+
+//fixed
+psF64 PM_MODEL_FLUX(const psVector *params)
+{
+    float f, norm, z;
+
+    psF32 *PAR = params->data.F32;
+
+    psF64 A1   = PS_SQR(PAR[4]);
+    psF64 A2   = PS_SQR(PAR[5]);
+    psF64 A3   = PS_SQR(PAR[6]);
+    psF32 Rx=2./PS_SQR(PAR[4]);
+    psF32 Ry=2./PS_SQR(PAR[5]);
+    psF32 Rxy=PAR[6];
+
+
+    psF32 theta = PAR[8];
+    psF32 sinT=sin(theta);
+    psF32 cosT=cos(theta);
+
+    psF32 Syrot = ( PS_SQR(sinT)/Rx + PS_SQR(cosT)/Ry - Rxy*sinT*cosT );  //rotated sigma y
+
+    psF64 A4   = Syrot*PAR[7];
+
+    psF64 Area = 2.0 * M_PI / sqrt(A1*A2 - A3) + A4;
+    // Area is equivalent to 2 pi sigma^2 + rectangle
+
+    // the area needs to be multiplied by the integral of f(z)
+    norm = 0.0;
+    for (z = 0.005; z < 50; z += 0.01) {
+        f = 1.0 / (1 + z + z*z/2 + z*z*z/6);
+        norm += f;
+    }
+    norm *= 0.01;
+
+    psF64 Flux = params->data.F32[1] * Area * norm;
+
+    return(Flux);
+}
+
+// define this function so it never returns Inf or NaN
+// also prevent 0 returns, and just send a v small number
+// return the radius which yields the requested flux
+
+//fixed, but need to change how it is called to accomodate 2 radii
+psF64 PM_MODEL_RADIUS  (const psVector *params, psF64 flux)
+{
+    if (flux <= 0) return (1.0);
+    if (params->data.F32[1] <= 0) return (1.0);
+    if (flux >= params->data.F32[1]) return (1.0);
+
+    psF32 *PAR = params->data.F32;
+    psF32 sigma  = sqrt(2.0) * hypot (1.0 / params->data.F32[4], 1.0 / params->data.F32[5]);
+
+    psF32 theta = PAR[8];
+    psF32 sinT=sin(theta);
+    psF32 cosT=cos(theta);
+    psF32 Rx=2./PS_SQR(PAR[4]);
+    psF32 Ry=2./PS_SQR(PAR[5]);
+    psF32 Rxy=PAR[6];
+    psF32 length=PAR[7];
+
+    psF32 Syrot = ( PS_SQR(sinT)/Rx + PS_SQR(cosT)/Ry - Rxy*sinT*cosT );  //rotated sigma y
+
+    psF64 radius = 0;
+    if (flux > 0){
+      psF64 radius0 = sigma * sqrt (2.0 * log(params->data.F32[1] / flux));
+      psF64 radius1 = Syrot * sqrt (2.0 * log(params->data.F32[1] / flux));
+
+      if (radius0 > radius1) {
+        radius=radius0+length/2.0;
+      } else {
+        radius=radius1+length/2.0;
+      }
+    } else {
+      radius = 1000;
+    }
+
+    if (radius < 0.01){
+      radius = 0.01;
+    }
+
+    if (isnan(radius)) {
+      fprintf (stderr, "error in code\n");
+    }
+    return (radius);
+}
+
+//fixed I think...no good way of guessing as far as I can tell
+bool PM_MODEL_GUESS (pmModel *model, pmSource *source)
+{
+    pmMoments *Smoments = source->moments;
+    psF32     *params  = model->params->data.F32;
+
+    psEllipseAxes axes;
+    psEllipseShape shape;
+    psEllipseMoments moments;
+
+    moments.x2 = PS_SQR(Smoments->Sx);
+    moments.y2 = PS_SQR(Smoments->Sy);
+    moments.xy = Smoments->Sxy;
+    //sometimes these moment inputs are zero...why?
+
+    // solve the math to go from Moments To Shape
+    // limit the axis ratio to 20 (a guess)
+    axes = psEllipseMomentsToAxes(moments, 20.0);
+    shape = psEllipseAxesToShape(axes);
+
+    params[0] = Smoments->Sky;
+    params[1] = Smoments->Peak - Smoments->Sky;
+    params[2] = Smoments->x;
+    params[3] = Smoments->y;
+    params[7] = 2 * axes.major;
+    params[8] = axes.theta;
+
+    if (moments.x2 == 0 || moments.y2 == 0){
+      params[4] = 2.0;
+      params[5] = 2.0;
+      params[6] = 0.0;
+    } else {
+      params[4] = 1.0 / shape.sx;
+      params[5] = 1.0 / shape.sy;
+      params[6] = shape.sxy;
+    }
+
+    //    printf("Who is NaN? momx: %4.3f  momy: %4.3f  momxy: %4.3f\n", moments.x2,moments.y2, moments.xy);
+
+    return(true);
+}
+
+//fixed
+bool PM_MODEL_FROM_PSF (pmModel *modelPSF, pmModel *modelFLT, const pmPSF *psf)
+{
+    psF32 *out = modelPSF->params->data.F32;
+    psF32 *in  = modelFLT->params->data.F32;
+
+    out[0] = in[0];
+    out[1] = in[1];
+    out[2] = in[2];
+    out[3] = in[3];
+    out[7] = in[7];
+    out[8] = in[8];
+
+    for (int i = 4; i < 7; i++) {
+      pmTrend2D *trend = psf->params->data[i-4];
+        out[i] = pmTrend2DEval (trend, out[2], out[3]);
+    }
+    return(true);
+}
+
+// construct the PSF model from the FLT model and the psf
+// XXX is this sufficiently general do be a global function, not a pmModelClass function?
+bool PM_MODEL_PARAMS_FROM_PSF (pmModel *model, const pmPSF *psf, float Xo, float Yo, float Io)
+{
+    psF32 *PAR = model->params->data.F32;
+
+    // we require these two parameters to exist
+    assert (psf->params->n > PM_PAR_YPOS);
+    assert (psf->params->n > PM_PAR_XPOS);
+
+    PAR[PM_PAR_SKY]  = 0.0;
+    PAR[PM_PAR_I0]   = Io;
+    PAR[PM_PAR_XPOS] = Xo;
+    PAR[PM_PAR_YPOS] = Yo;
+
+    // supply the model-fitted parameters, or copy from the input
+    for (int i = 0; i < psf->params->n; i++) {
+        if (i == PM_PAR_SKY) continue;
+        pmTrend2D *trend = psf->params->data[i];
+        PAR[i] = pmTrend2DEval(trend, Xo, Yo);
+    }
+
+    // the 2D PSF model fits polarization terms (E0,E1,E2)
+    // convert to shape terms (SXX,SYY,SXY)
+    // XXX user-defined value for limit?
+    if (!pmPSF_FitToModel (PAR, 0.1)) {
+        psError(PM_ERR_PSF, false, "Failed to fit object at (r,c) = (%.1f,%.1f)", Xo, Yo);
+        return false;
+    }
+
+    // apply the model limits here: this truncates excessive extrapolation
+    // XXX do we need to do this still?  should we put in asserts to test?
+    for (int i = 0; i < psf->params->n; i++) {
+        // apply the limits to all components or just the psf-model parameters?
+        if (psf->params->data[i] == NULL)
+            continue;
+
+        bool status = true;
+        status &= PM_MODEL_LIMITS (PS_MINIMIZE_PARAM_MIN, i, PAR, NULL);
+        status &= PM_MODEL_LIMITS (PS_MINIMIZE_PARAM_MAX, i, PAR, NULL);
+        if (!status) {
+            psTrace ("psModules.objects", 5, "Hitting parameter limits at (r,c) = (%.1f, %.1f)", Xo, Yo);
+            model->flags |= PM_MODEL_STATUS_LIMITS;
+        }
+    }
+    return(true);
+}
+
+//done I think
+bool PM_MODEL_FIT_STATUS (pmModel *model)
+{
+    psF32 dP;
+    bool  status;
+
+    psF32 *PAR  = model->params->data.F32;
+    psF32 *dPAR = model->dparams->data.F32;
+
+    dP = 0;
+    dP += PS_SQR(dPAR[4] / PAR[4]);
+    dP += PS_SQR(dPAR[5] / PAR[5]);
+    dP = sqrt (dP);
+
+    status = true;
+    status &= (dP < 0.5);
+    status &= (PAR[1] > 0);
+    status &= ((dPAR[1]/PAR[1]) < 0.5);
+    //    status &= ((dPAR[7]/PAR[7]) < 0.5);
+    //    status &= ((dPAR[8]/PAR[8]) < 0.5);
+
+    if (status) return true;
+    return false;
+}
+
+# undef PM_MODEL_FUNC
+# undef PM_MODEL_FLUX
+# undef PM_MODEL_GUESS
+# undef PM_MODEL_LIMITS
+# undef PM_MODEL_RADIUS
+# undef PM_MODEL_FROM_PSF
+# undef PM_MODEL_PARAMS_FROM_PSF
+# undef PM_MODEL_FIT_STATUS
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/models/pmModel_TEST1.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/models/pmModel_TEST1.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/models/pmModel_TEST1.c	(revision 22158)
@@ -0,0 +1,311 @@
+/******************************************************************************
+ * this file defines the TEST1 source shape model.  Note that these model functions are loaded
+ * by pmModelGroup.c using 'include', and thus need no 'include' statements of their own.  The
+ * models use a psVector to represent the set of parameters, with the sequence used to specify
+ * the meaning of the parameter.  The meaning of the parameters may thus vary depending on the
+ * specifics of the model.  All models which are used a PSF representations share a few
+ * parameters, for which # define names are listed in pmModel.h:
+
+ * PM_PAR_SKY 0   - local sky : note that this is unused and may be dropped in the future
+ * PM_PAR_I0 1    - central intensity
+ * PM_PAR_XPOS 2  - X center of object
+ * PM_PAR_YPOS 3  - Y center of object
+ * PM_PAR_SXX 4   - X^2 term of elliptical contour (sqrt(2) * SigmaX)
+ * PM_PAR_SYY 5   - Y^2 term of elliptical contour (sqrt(2) * SigmaY)
+ * PM_PAR_SXY 6   - X*Y term of elliptical contour
+ *****************************************************************************/
+
+# define PM_MODEL_FUNC            pmModelFunc_TEST1
+# define PM_MODEL_FLUX            pmModelFlux_TEST1
+# define PM_MODEL_GUESS           pmModelGuess_TEST1
+# define PM_MODEL_LIMITS          pmModelLimits_TEST1
+# define PM_MODEL_RADIUS          pmModelRadius_TEST1
+# define PM_MODEL_FROM_PSF        pmModelFromPSF_TEST1
+# define PM_MODEL_PARAMS_FROM_PSF pmModelParamsFromPSF_TEST1
+# define PM_MODEL_FIT_STATUS      pmModelFitStatus_TEST1
+
+// the model is a function of the pixel coordinate (pixcoord[0,1] = x,y)
+psF32 PM_MODEL_FUNC(psVector *deriv,
+                    const psVector *params,
+                    const psVector *pixcoord)
+{
+    psF32 *PAR = params->data.F32;
+
+    // XXX this is fitting sigma_x/sqrt(2), sigma_y/sqrt(2)
+    psF32 X  = pixcoord->data.F32[0] - PAR[PM_PAR_XPOS];
+    psF32 Y  = pixcoord->data.F32[1] - PAR[PM_PAR_YPOS];
+    psF32 px = X / PAR[PM_PAR_SXX];
+    psF32 py = Y / PAR[PM_PAR_SYY];
+    psF32 z  = PS_SQR(px) + PS_SQR(py) + PAR[PM_PAR_SXY]*X*Y;
+    psF32 t  = 1 + z + z*z/2.0;
+    psF32 r  = 1.0 / (t + z*z*z/6.0); /* exp (-Z) */
+    psF32 f  = PAR[PM_PAR_I0]*r + PAR[PM_PAR_SKY];
+
+    if (deriv != NULL) {
+        psF32 *dPAR = deriv->data.F32;
+        psF32 q = PAR[PM_PAR_I0]*r*r*t;
+        dPAR[PM_PAR_SKY]  = +1.0;
+        dPAR[PM_PAR_I0]   = +r;
+        dPAR[PM_PAR_XPOS] = q*(2.0*px/PAR[PM_PAR_SXX] + Y*PAR[PM_PAR_SXY]);
+        dPAR[PM_PAR_YPOS] = q*(2.0*py/PAR[PM_PAR_SYY] + X*PAR[PM_PAR_SXY]);
+        dPAR[PM_PAR_SXX]  = +2.0*q*px*px/PAR[PM_PAR_SXX];
+        dPAR[PM_PAR_SYY]  = +2.0*q*py*py/PAR[PM_PAR_SYY];
+        dPAR[PM_PAR_SXY]  = -q*X*Y;
+    }
+    return(f);
+}
+
+// define the parameter limits
+bool PM_MODEL_LIMITS (psMinConstraintMode mode, int nParam, float *params, float *beta)
+{
+    float beta_lim = 0;
+    float params_min = 0;
+    float params_max = 0;
+
+    switch (mode) {
+      case PS_MINIMIZE_BETA_LIMIT:
+        switch (nParam) {
+          case PM_PAR_SKY:  beta_lim = 1000;  break;
+          case PM_PAR_I0:   beta_lim = 3e6;   break;
+          case PM_PAR_XPOS: beta_lim = 5;     break;
+          case PM_PAR_YPOS: beta_lim = 5;     break;
+          case PM_PAR_SXX:  beta_lim = 0.5;   break;
+          case PM_PAR_SYY:  beta_lim = 0.5;   break;
+          case PM_PAR_SXY:  beta_lim = 0.5;   break;
+          default:
+            psAbort("invalid parameter %d for beta test", nParam);
+        }
+        if (fabs(beta[nParam]) > fabs(beta_lim)) {
+            beta[nParam] = (beta[nParam] > 0) ? fabs(beta_lim) : -fabs(beta_lim);
+            return false;
+        }
+        return true;
+      case PS_MINIMIZE_PARAM_MIN:
+        switch (nParam) {
+          case PM_PAR_SKY:  params_min = -1000; break;
+          case PM_PAR_I0:   params_min =     0; break;
+          case PM_PAR_XPOS: params_min =  -100; break;
+          case PM_PAR_YPOS: params_min =  -100; break;
+          case PM_PAR_SXX:  params_min =   0.5; break;
+          case PM_PAR_SYY:  params_min =   0.5; break;
+          case PM_PAR_SXY:  params_min =  -5.0; break;
+          default:
+            psAbort("invalid parameter %d for param min test", nParam);
+        }
+        if (params[nParam] < params_min) {
+            params[nParam] = params_min;
+            return false;
+        }
+        return true;
+      case PS_MINIMIZE_PARAM_MAX:
+        switch (nParam) {
+          case PM_PAR_SKY:  params_max =   1e5; break;
+          case PM_PAR_I0:   params_max =   1e8; break;
+          case PM_PAR_XPOS: params_max =   1e4; break;
+          case PM_PAR_YPOS: params_max =   1e4; break;
+          case PM_PAR_SXX:  params_max =   100; break;
+          case PM_PAR_SYY:  params_max =   100; break;
+          case PM_PAR_SXY:  params_max =  +5.0; break;
+          default:
+            psAbort("invalid parameter %d for param max test", nParam);
+        }
+        if (params[nParam] > params_max) {
+            params[nParam] = params_max;
+            return false;
+        }
+        return true;
+      default:
+        psAbort("invalid choice for limits");
+    }
+    psAbort("should not reach here");
+    return false;
+}
+
+// make an initial guess for parameters
+bool PM_MODEL_GUESS (pmModel *model, pmSource *source)
+{
+    pmMoments *moments = source->moments;
+    psF32     *PAR  = model->params->data.F32;
+
+    PAR[PM_PAR_SKY] = moments->Sky;
+    PAR[PM_PAR_I0] = moments->Peak - moments->Sky;
+    PAR[PM_PAR_XPOS] = moments->x;
+    PAR[PM_PAR_YPOS] = moments->y;
+    PAR[PM_PAR_SXX] = PS_MAX(0.5, moments->Sx);
+    PAR[PM_PAR_SYY] = PS_MAX(0.5, moments->Sy);
+    PAR[PM_PAR_SXY] = 0.0;  // XXX we can get this right if we do the integral
+
+    return(true);
+}
+
+psF64 PM_MODEL_FLUX(const psVector *params)
+{
+    float norm, z;
+    psEllipseShape shape;
+
+    psF32 *PAR = params->data.F32;
+
+    shape.sx  = PAR[PM_PAR_SXX] / sqrt(2.0);
+    shape.sy  = PAR[PM_PAR_SYY] / sqrt(2.0);
+    shape.sxy = PAR[PM_PAR_SXY];
+
+    // Area is equivalent to 2 pi sigma^2
+    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
+    psF64 Area = 2.0 * M_PI * axes.major * axes.minor;
+
+    // the area needs to be multiplied by the integral of f(z)
+    norm = 0.0;
+
+# define DZ 0.25
+
+    float f0 = 1.0;
+    float f1, f2;
+    for (z = DZ; z < 50; z += DZ) {
+        f1 = 1.0 / (1 + z + z*z/2.0 + z*z*z/6.0);
+        z += DZ;
+        f2 = 1.0 / (1 + z + z*z/2.0 + z*z*z/6.0);
+        norm += f0 + 4*f1 + f2;
+        f0 = f2;
+    }
+    norm *= DZ / 3.0;
+
+    psF64 Flux = PAR[PM_PAR_I0] * Area * norm;
+
+    return(Flux);
+}
+
+// define this function so it never returns Inf or NaN
+// return the radius which yields the requested flux
+psF64 PM_MODEL_RADIUS (const psVector *params, psF64 flux)
+{
+    psEllipseShape shape;
+
+    if (flux <= 0)
+        return (1.0);
+    if (params->data.F32[PM_PAR_I0] <= 0)
+        return (1.0);
+    if (flux >= params->data.F32[PM_PAR_I0])
+        return (1.0);
+
+    psF32 *PAR = params->data.F32;
+
+    shape.sx  = PAR[PM_PAR_SXX] / sqrt(2.0);
+    shape.sy  = PAR[PM_PAR_SYY] / sqrt(2.0);
+    shape.sxy = PAR[PM_PAR_SXY];
+
+    // this estimates the radius assuming f(z) is roughly exp(-z)
+    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
+    psF64 radius = axes.major * sqrt (2.0 * log(params->data.F32[PM_PAR_I0] / flux));
+
+    if (isnan(radius)) psAbort("error in code: never return invalid radius");
+    if (radius < 0) psAbort("error in code: never return invalid radius");
+
+    return (radius);
+}
+
+bool PM_MODEL_FROM_PSF (pmModel *modelPSF, pmModel *modelFLT, const pmPSF *psf)
+{
+    psF32 *out = modelPSF->params->data.F32;
+    psF32 *in  = modelFLT->params->data.F32;
+
+    // we require these two parameters to exist
+    assert (psf->params->n > PM_PAR_YPOS);
+    assert (psf->params->n > PM_PAR_XPOS);
+
+    for (int i = 0; i < psf->params->n; i++) {
+        if (psf->params->data[i] == NULL) {
+            out[i] = in[i];
+        } else {
+            pmTrend2D *trend = psf->params->data[i];
+            out[i] = pmTrend2DEval(trend, in[PM_PAR_XPOS], in[PM_PAR_YPOS]);
+        }
+    }
+
+    // the 2D model for SXY actually fits SXY / (SXX^-2 + SYY^-2); correct here
+    out[PM_PAR_SXY] = pmPSF_SXYtoModel (out);
+
+    return(true);
+}
+
+// construct the PSF model from the FLT model and the psf
+// XXX is this sufficiently general do be a global function, not a pmModelClass function?
+bool PM_MODEL_PARAMS_FROM_PSF (pmModel *model, const pmPSF *psf, float Xo, float Yo, float Io)
+{
+    psF32 *PAR = model->params->data.F32;
+
+    // we require these two parameters to exist
+    assert (psf->params->n > PM_PAR_YPOS);
+    assert (psf->params->n > PM_PAR_XPOS);
+
+    PAR[PM_PAR_SKY]  = 0.0;
+    PAR[PM_PAR_I0]   = Io;
+    PAR[PM_PAR_XPOS] = Xo;
+    PAR[PM_PAR_YPOS] = Yo;
+
+    // supply the model-fitted parameters, or copy from the input
+    for (int i = 0; i < psf->params->n; i++) {
+        if (i == PM_PAR_SKY) continue;
+        pmTrend2D *trend = psf->params->data[i];
+        PAR[i] = pmTrend2DEval(trend, Xo, Yo);
+    }
+
+    // the 2D PSF model fits polarization terms (E0,E1,E2)
+    // convert to shape terms (SXX,SYY,SXY)
+    // XXX user-defined value for limit?
+    if (!pmPSF_FitToModel (PAR, 0.1)) {
+        psError(PM_ERR_PSF, false, "Failed to fit object at (r,c) = (%.1f,%.1f)", Xo, Yo);
+        return false;
+    }
+
+    // apply the model limits here: this truncates excessive extrapolation
+    // XXX do we need to do this still?  should we put in asserts to test?
+    for (int i = 0; i < psf->params->n; i++) {
+        // apply the limits to all components or just the psf-model parameters?
+        if (psf->params->data[i] == NULL)
+            continue;
+
+        bool status = true;
+        status &= PM_MODEL_LIMITS (PS_MINIMIZE_PARAM_MIN, i, PAR, NULL);
+        status &= PM_MODEL_LIMITS (PS_MINIMIZE_PARAM_MAX, i, PAR, NULL);
+        if (!status) {
+            psTrace ("psModules.objects", 5, "Hitting parameter limits at (r,c) = (%.1f, %.1f)", Xo, Yo);
+            model->flags |= PM_MODEL_STATUS_LIMITS;
+        }
+    }
+    return(true);
+}
+
+// XXX double-check these definitions below
+// this test is invalid if the parameters are derived
+// from the PSF model
+bool PM_MODEL_FIT_STATUS (pmModel *model)
+{
+    psF32 dP;
+    bool  status;
+
+    psF32 *PAR  = model->params->data.F32;
+    psF32 *dPAR = model->dparams->data.F32;
+
+    dP = 0;
+    dP += PS_SQR(dPAR[PM_PAR_SXX] / PAR[PM_PAR_SXX]);
+    dP += PS_SQR(dPAR[PM_PAR_SYY] / PAR[PM_PAR_SYY]);
+    dP = sqrt (dP);
+
+    status = true;
+    status &= (dP < 0.5);
+    status &= (PAR[PM_PAR_I0] > 0);
+    status &= ((dPAR[PM_PAR_I0]/PAR[PM_PAR_I0]) < 0.5);
+
+    if (status)
+        return true;
+    return false;
+}
+
+# undef PM_MODEL_FUNC
+# undef PM_MODEL_FLUX
+# undef PM_MODEL_GUESS
+# undef PM_MODEL_LIMITS
+# undef PM_MODEL_RADIUS
+# undef PM_MODEL_FROM_PSF
+# undef PM_MODEL_PARAMS_FROM_PSF
+# undef PM_MODEL_FIT_STATUS
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphot.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphot.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphot.c	(revision 22158)
@@ -0,0 +1,42 @@
+# include "psphotStandAlone.h"
+
+static void usage (void) {
+    fprintf (stderr, "USAGE: psphot [-file image(s)] [-list imagelist] (output)\n");
+    exit (PS_EXIT_CONFIG_ERROR);
+}
+
+int main (int argc, char **argv) {
+
+    psTimerStart ("complete");
+    pmErrorRegister();			// register psModule's error codes/messages
+    psphotErrorRegister();              // register our error codes/messages
+    psphotModelClassInit ();            // load implementation-specific models
+
+    // load command-line arguments, options, and system config data
+    pmConfig *config = psphotArguments (argc, argv);
+    if (!config) {
+	psErrorStackPrint(stderr, "Error reading arguments\n");
+	usage ();
+    }
+
+    // load input data (config and images (signal, noise, mask)
+    if (!psphotParseCamera (config)) {
+        psErrorStackPrint(stderr, "Error setting up the camera\n");
+        exit (psphotGetExitStatus());
+    }
+
+    // call psphot for each readout
+    if (!psphotImageLoop (config)) {
+        psErrorStackPrint(stderr, "Error in the psphot image loop\n");
+        exit (psphotGetExitStatus());
+    }
+
+    psLogMsg ("psphot", 3, "complete psphot run: %f sec\n", psTimerMark ("complete"));
+
+    psErrorCode exit_status = psphotGetExitStatus();
+    psphotCleanup (config);
+    exit (exit_status);
+}
+
+// all functions which return to this level must raise one of the top-level error codes if they
+// exit with an error.  these error codes are used to specify the program exit status
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphot.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphot.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphot.h	(revision 22158)
@@ -0,0 +1,183 @@
+/* This file defines the library functions available to external programs.  It must be included
+ * by programs which are compiled against psphot functions.
+ */
+
+#ifndef PSPHOT_H
+#define PSPHOT_H
+
+#include <psmodules.h>
+#include "psphotErrorCodes.h"
+
+#define PSPHOT_RECIPE "PSPHOT" // Name of the recipe to use
+
+#define PSPHOT_RECIPE_PSF_FAKE_ALLOW "PSF.FAKE.ALLOW" // Name for recipe component permitting fake PSFs
+
+
+// top-level psphot functions
+const char     *psphotCVSName(void);
+psString        psphotVersion(void);
+psString        psphotVersionLong(void);
+
+bool            psphotModelTest (pmConfig *config, const pmFPAview *view, psMetadata *recipe);
+bool            psphotReadout (pmConfig *config, const pmFPAview *view);
+bool            psphotReadoutCleanup (pmConfig *config, pmReadout *readout, psMetadata *recipe, pmDetections *detections, pmPSF *psf, psArray *sources);
+bool            psphotDefineFiles (pmConfig *config, pmFPAfile *input);
+bool            psphotSetMaskBits (pmConfig *config);
+
+// XXX test functions
+psArray        *psphotFakeSources ();
+
+// psphotReadout functions
+bool            psphotModelBackground (pmConfig *config, const pmFPAview *view, const char *filename);
+bool            psphotSubtractBackground (pmConfig *config, const pmFPAview *view, const char *filename) ;
+pmDetections   *psphotFindDetections (pmDetections *detections, pmReadout *readout, psMetadata *recipe);
+
+psArray        *psphotSourceStats (pmReadout *readout, psMetadata *recipe, pmDetections *detections);
+bool            psphotRoughClass (psArray *sources, psMetadata *recipe, const bool findPsfClump);
+bool            psphotBasicDeblend (psArray *sources, psMetadata *recipe);
+pmPSF          *psphotChoosePSF (pmReadout *readout, psArray *sources, psMetadata *recipe);
+bool            psphotPSFstats (pmReadout *readout, psMetadata *recipe, pmPSF *psf);
+bool            psphotMomentsStats (pmReadout *readout, psMetadata *recipe, psArray *sources);
+bool            psphotFitSourcesLinear (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf, bool final);
+bool            psphotGuessModels (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf);
+bool            psphotBlendFit (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf);
+bool            psphotReplaceUnfitSources (psArray *sources, psMaskType maskVal);
+bool            psphotReplaceAllSources (psArray *sources, psMetadata *recipe);
+bool            psphotRemoveAllSources (psArray *sources, psMetadata *recipe);
+bool            psphotApResid (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf);
+bool            psphotMagnitudes (psArray *sources, psMetadata *recipe, pmPSF *psf, pmReadout *background);
+bool            psphotSkyReplace (pmConfig *config, const pmFPAview *view);
+bool            psphotExtendedSourceAnalysis (pmReadout *readout, psArray *sources, psMetadata *recipe);
+bool            psphotExtendedSourceFits (pmReadout *readout, psArray *sources, psMetadata *recipe);
+
+// used by psphotFindDetections
+psImage        *psphotSignificanceImage (pmReadout *readout, psMetadata *recipe, const int pass, psMaskType maskVal);
+psArray        *psphotFindPeaks (psImage *significance, pmReadout *readout, psMetadata *recipe, const float threshold, const int nMax);
+bool            psphotFindFootprints (pmDetections *detections, psImage *significance, pmReadout *readout, psMetadata *recipe, const int pass, psMaskType maskVal);
+psErrorCode     psphotCullPeaks(const psImage *img, const psImage *weight, const psMetadata *recipe, psArray *footprints);
+
+// used by ApResid
+bool            psphotMagErrorScale (float *errorScale, float *errorFloor, psVector *dMag, psVector *dap, psVector *mask, int nGroup);
+bool            psphotApResidTrend (pmReadout *readout, pmPSF *psf, int Npsf, int scale, float *errorScale, float *errorFloor, psVector *mask, psVector *xPos, psVector *yPos, psVector *apResid, psVector *dMag);
+
+// basic support functions
+void            psphotModelClassInit (void);
+bool            psphotGrowthCurve (pmReadout *readout, pmPSF *psf, bool ignore, psMaskType maskVal);
+bool            psphotSetMaskAndWeight (pmConfig *config, pmReadout *readout, psMetadata *recipe);
+void            psphotSourceFreePixels (psArray *sources);
+
+// functions to set the correct source pixels
+bool            psphotInitRadiusPSF (const psMetadata *recipe, const pmModelType type);
+bool            psphotCheckRadiusPSF (pmReadout *readout, pmSource *source, pmModel *model, psMaskType markVal);
+bool            psphotCheckRadiusPSFBlend (pmReadout *readout, pmSource *source, pmModel *model, psMaskType markVal, float dR);
+bool            psphotInitRadiusEXT (psMetadata *recipe, pmModelType type);
+bool            psphotCheckRadiusEXT (pmReadout *readout, pmSource *source, pmModel *model, psMaskType markVal);
+
+// output functions
+bool            psphotAddPhotcode (psMetadata *recipe, pmConfig *config, const pmFPAview *view, const char *filerule);
+bool            psphotDumpMoments (psMetadata *recipe, psArray *sources);
+psMetadata     *psphotDefineHeader (psMetadata *recipe);
+int             psphotSaveImage (psMetadata *header, psImage *image, char *filename);
+bool            psphotDumpConfig (pmConfig *config);
+pmReadout      *psphotSelectBackground (pmConfig *config, const pmFPAview *view, const bool stdev);
+
+// PSF / DBL / EXT evaluation functions
+bool            psphotEvalPSF (pmSource *source, pmModel *model);
+bool            psphotEvalDBL (pmSource *source, pmModel *model);
+bool            psphotEvalEXT (pmSource *source, pmModel *model);
+
+//  functions to support the source fitting process
+bool            psphotInitLimitsPSF (psMetadata *recipe, pmReadout *readout);
+bool            psphotInitLimitsEXT (psMetadata *recipe);
+bool            psphotFitBlend (pmReadout *readout, pmSource *source, pmPSF *psf, psMaskType maskVal, psMaskType markVal);
+bool            psphotFitBlob (pmReadout *readout, pmSource *source, psArray *sources, pmPSF *psf, psMaskType maskVal, psMaskType markVal);
+bool            psphotFitPSF (pmReadout *readout, pmSource *source, pmPSF *psf, psMaskType maskVal, psMaskType markVal);
+pmModel        *psphotFitEXT (pmReadout *readout, pmSource *source, pmModelType modelType, psMaskType maskVal, psMaskType markVal);
+psArray        *psphotFitDBL (pmReadout *readout, pmSource *source, psMaskType maskVal, psMaskType markVal);
+
+// functions to support simultaneous multi-source fitting
+bool            psphotFitSet (pmSource *oneSrc, pmModel *oneModel, char *fitset, pmSourceFitMode mode, psMaskType maskVal);
+
+// plotting functions (available if libkapa is installed)
+bool            psphotPlotMoments (pmConfig *config, pmFPAview *view, psArray *sources);
+bool            psphotPlotPSFModel (pmConfig *config, pmFPAview *view, psArray *sources);
+bool            psphotFitInit ();
+bool            psphotFitSummary ();
+bool            psphotMergeSources (psArray *oldSources, psArray *newSources);
+bool            psphotLoadExtSources (pmConfig *config, const pmFPAview *view, psArray *sources);
+pmPSF          *psphotLoadPSF (pmConfig *config, const pmFPAview *view, psMetadata *recipe);
+bool            psphotSetHeaderNstars (psMetadata *recipe, psArray *sources);
+bool            psphotAddNoise (pmReadout *readout, psArray *sources, psMetadata *recipe);
+bool            psphotSubNoise (pmReadout *readout, psArray *sources, psMetadata *recipe);
+bool            psphotAddOrSubNoise (pmReadout *readout, psArray *sources, psMetadata *recipe, bool add);
+bool            psphotRadialPlot (int *kapa, const char *filename, pmSource *source);
+bool            psphotSourcePlots (pmReadout *readout, psArray *sources, psMetadata *recipe);
+bool            psphotMosaicSubimage (psImage *outImage, pmSource *source, int Xo, int Yo, int DX, int DY);
+
+bool            psphotAddWithTest (pmSource *source, bool useState, psMaskType maskVal);
+bool            psphotSubWithTest (pmSource *source, bool useState, psMaskType maskVal);
+bool            psphotSetState (pmSource *source, bool curState, psMaskType maskVal);
+bool            psphotDeblendSatstars (psArray *sources, psMetadata *recipe);
+bool            psphotSourceSize (pmConfig *config, pmReadout *readout, psArray *sources, psMetadata *recipe, long first);
+
+bool            psphotMakeResiduals (psArray *sources, psMetadata *recipe, pmPSF *psf, psMaskType maskVal);
+
+pmModel        *psphotPSFConvModel (pmReadout *readout, pmSource *source, pmModelType modelType, psMaskType maskVal, psMaskType markVal, int psfSize);
+
+psKernel       *psphotKernelFromPSF (pmSource *source, int nPix);
+
+bool            psphotRadialProfile (pmSource *source, psMetadata *recipe, psMaskType maskVal);
+bool            psphotPetrosian (pmSource *source, psMetadata *recipe, psMaskType maskVal);
+bool            psphotIsophotal (pmSource *source, psMetadata *recipe, psMaskType maskVal);
+bool            psphotAnnuli (pmSource *source, psMetadata *recipe, psMaskType maskVal);
+bool            psphotKron (pmSource *source, psMetadata *recipe, psMaskType maskVal);
+
+// structures & functions to support psf-convolved model fitting
+
+// pmPCMData : PSF Convolved Model data storage structure
+typedef struct {
+    psImage *model;
+    psArray *dmodels;
+    psImage *modelConv;
+    psArray *dmodelsConv;
+} pmPCMData;
+
+
+// psf-convolved model fitting
+bool psphotModelWithPSF_LMM (
+    psMinimization *min,
+    psImage *covar,
+    psVector *params,
+    psMinConstraint *constraint,
+    pmSource *source,
+    const psKernel *psf,
+    psMinimizeLMChi2Func func);
+
+psF32 psphotModelWithPSF_SetABX(
+    psImage  *alpha,
+    psVector *beta,
+    const psVector *params,
+    const psVector *paramMask,
+    pmPCMData *pcm,
+    const pmSource *source,
+    const psKernel *psf,
+    psMinimizeLMChi2Func func);
+
+pmPCMData *pmPCMDataAlloc (
+    const psVector *params,
+    const psVector *paramMask,
+    pmSource *source);
+
+psImage *pmPCMDataSaveImage (pmPCMData *pcm);
+
+int psphotKapaOpen ();
+bool psphotKapaClose ();
+bool psphotImageBackgroundCellHistogram (psVector *values, float mean, float sigma, int ix, int iy);
+bool psphotDiagnosticPlots (pmConfig *config, char *name, ...);
+
+bool psphotMakeFluxScale (psImage *image, psMetadata *recipe, pmPSF *psf);
+
+bool psphotCheckStarDistribution (psArray *sources, psArray *stars, pmPSFOptions *options);
+int psphotSupplementStars (psArray *stars, psArray *sources, psImageBinning *binning, int ix, int iy);
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotAddNoise.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotAddNoise.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotAddNoise.c	(revision 22158)
@@ -0,0 +1,100 @@
+# include "psphotInternal.h"
+
+bool psphotAddNoise (pmReadout *readout, psArray *sources, psMetadata *recipe) {
+  return psphotAddOrSubNoise (readout, sources, recipe, true);
+}
+
+bool psphotSubNoise (pmReadout *readout, psArray *sources, psMetadata *recipe) {
+  return psphotAddOrSubNoise (readout, sources, recipe, false);
+}
+
+bool psphotAddOrSubNoise (pmReadout *readout, psArray *sources, psMetadata *recipe, bool add) {
+
+    bool status = false;
+    psEllipseShape oldshape;
+    psEllipseShape newshape;
+    psEllipseAxes axes;
+
+    PS_ASSERT (readout, false);
+    PS_ASSERT (readout->parent, false);
+    PS_ASSERT (readout->parent->concepts, false);
+
+    psTimerStart ("psphot");
+
+    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
+    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
+    assert (maskVal);
+
+    // increase variance by factor*(object noise):
+    // weight = flux/gain + rn^2/g^2
+    // we are adding factor*flux/gain
+
+    float FACTOR = psMetadataLookupF32 (&status, recipe, "NOISE.FACTOR");
+    PS_ASSERT (status, false);
+    float SIZE = psMetadataLookupF32 (&status, recipe, "NOISE.SIZE");
+    PS_ASSERT (status, false);
+
+    if (SIZE <= 0) {
+       return true;
+    }
+
+    float GAIN = psMetadataLookupF32(&status, readout->parent->concepts, "CELL.GAIN"); // Cell gain
+    PS_ASSERT (status, false);
+
+    FACTOR /= GAIN;
+
+    // loop over all source
+    for (int i = 0; i < sources->n; i++) {
+        pmSource *source = sources->data[i];
+
+        // skip sources which were not subtracted
+        if (!(source->mode & PM_SOURCE_MODE_SUBTRACTED)) continue;
+
+        // select appropriate model
+        pmModel *model = pmSourceGetModel (NULL, source);
+        if (model == NULL) continue;  // model must be defined
+
+        if (add) {
+            psTrace ("psphot", 4, "adding noise for object at %f,%f\n", model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS]);
+        } else {
+            psTrace ("psphot", 4, "remove noise for object at %f,%f\n", model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS]);
+        }
+
+        psF32 *PAR = model->params->data.F32;
+
+        // save original values
+        float oldI0  = PAR[PM_PAR_I0];
+        oldshape.sx  = PAR[PM_PAR_SXX];
+        oldshape.sy  = PAR[PM_PAR_SYY];
+        oldshape.sxy = PAR[PM_PAR_SXY];
+
+	// XXX can this be done more intelligently?
+	if (oldI0 == 0.0) continue;
+	if (!isfinite(oldI0)) continue;
+
+        // increase size and height of source
+        axes = psEllipseShapeToAxes (oldshape, 20.0);
+        axes.major *= SIZE;
+        axes.minor *= SIZE;
+        newshape = psEllipseAxesToShape (axes);
+        PAR[PM_PAR_I0]  = FACTOR*PS_SQR(oldI0);
+        PAR[PM_PAR_SXX] = newshape.sx;
+        PAR[PM_PAR_SYY] = newshape.sy;
+        PAR[PM_PAR_SXY] = newshape.sxy;
+
+        // XXX if we use pmSourceOp, the size (and possibly Io) will not be respected
+        pmSourceOp (source, PM_MODEL_OP_FULL | PM_MODEL_OP_NOISE, add, maskVal, 0, 0);
+
+        // restore original values
+        PAR[PM_PAR_I0]  = oldI0;
+        PAR[PM_PAR_SXX] = oldshape.sx;
+        PAR[PM_PAR_SYY] = oldshape.sy;
+        PAR[PM_PAR_SXY] = oldshape.sxy;
+    }
+    if (add) {
+        psLogMsg ("psphot.noise", PS_LOG_INFO, "add noise for %ld objects: %f sec\n", sources->n, psTimerMark ("psphot"));
+    } else {
+        psLogMsg ("psphot.noise", PS_LOG_INFO, "sub noise for %ld objects: %f sec\n", sources->n, psTimerMark ("psphot"));
+    }
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotAnnuli.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotAnnuli.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotAnnuli.c	(revision 22158)
@@ -0,0 +1,61 @@
+# include "psphotInternal.h"
+
+bool psphotAnnuli (pmSource *source, psMetadata *recipe, psMaskType maskVal) {
+
+  assert (source->extpars);
+  assert (source->extpars->profile);
+  assert (source->extpars->profile->radius);
+  assert (source->extpars->profile->flux);
+
+  bool status;
+
+  psVector *radius = source->extpars->profile->radius;
+  psVector *weight = source->extpars->profile->weight;
+  psVector *flux = source->extpars->profile->flux;
+
+  // XXX how do I define the radii?  we can put a vector in the recipe...
+  // radialBins defines the bounds or start and stop (we can skip some that way...
+  psVector *radialBinsLower = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.LOWER");
+  psVector *radialBinsUpper = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.UPPER");
+  assert (radialBinsLower->n == radialBinsUpper->n);
+
+  psVector *fluxValues = psVectorAlloc (radialBinsLower->n, PS_TYPE_F32);
+  psVector *fluxSquare = psVectorAlloc (radialBinsLower->n, PS_TYPE_F32);
+  psVector *fluxWeight = psVectorAlloc (radialBinsLower->n, PS_TYPE_F32);
+  psVector *pixelCount = psVectorAlloc (radialBinsLower->n, PS_TYPE_F32);
+  psVectorInit (fluxValues, 0.0);
+  psVectorInit (fluxSquare, 0.0);
+  psVectorInit (fluxWeight, 0.0);
+  psVectorInit (pixelCount, 0.0);
+
+  // XXX this code assumes the radii are in pixels.  convert from arcsec with plate scale
+  // XXX assume the annulii above are not overlapping?  much faster...
+  // XXX this might be must faster in the reverse order: loop over annulii and use disection to 
+  // skip to the start of the annulus.
+  for (int i = 0; i < flux->n; i++) {
+    for (int j = 0; j < radialBinsLower->n; j++) {
+      if (radius->data.F32[i] < radialBinsLower->data.F32[j]) continue;
+      if (radius->data.F32[i] > radialBinsUpper->data.F32[j]) continue;
+      fluxValues->data.F32[j] += flux->data.F32[i];
+      fluxSquare->data.F32[j] += PS_SQR(flux->data.F32[i]);
+      fluxWeight->data.F32[j] += weight->data.F32[i];
+      pixelCount->data.F32[j] += 1.0;
+    }
+  }
+
+  for (int j = 0; j < radialBinsLower->n; j++) {
+    fluxValues->data.F32[j] /= pixelCount->data.F32[j];
+    fluxSquare->data.F32[j] /= pixelCount->data.F32[j];
+    fluxSquare->data.F32[j] -= PS_SQR(fluxValues->data.F32[j]);
+  }
+  
+  source->extpars->annuli = pmSourceAnnuliAlloc ();
+  source->extpars->annuli->flux    = fluxValues;
+  source->extpars->annuli->fluxErr = fluxWeight;
+  source->extpars->annuli->fluxVar = fluxSquare;
+
+  psFree (pixelCount);
+
+  return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotApResid.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotApResid.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotApResid.c	(revision 22158)
@@ -0,0 +1,365 @@
+# include "psphotInternal.h"
+
+# define SKIPSTAR(MSG) { psTrace ("psphot", 3, "invalid : %s", MSG); continue; }
+// measure the aperture residual statistics and 2D variations
+
+bool psphotApResid (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf)
+{
+    int Nfail = 0;
+    int Nskip = 0;
+    int Npsf;
+    bool status;
+    pmModel *model;
+    pmSource *source;
+
+    PS_ASSERT_PTR_NON_NULL(psf, false);
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+    PS_ASSERT_PTR_NON_NULL(recipe, false);
+
+    psTimerStart ("psphot");
+
+    bool measureAptrend = psMetadataLookupBool (&status, recipe, "MEASURE.APTREND");
+    if (!measureAptrend) {
+      return true;
+    }
+
+    // bit-masks to test for good/bad pixels
+    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT");
+    assert (maskVal);
+
+    // bit-mask to mark pixels not used in analysis
+    psMaskType markVal = psMetadataLookupU8(&status, recipe, "MARK.PSPHOT");
+    assert (markVal);
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
+    // S/N limit to perform full non-linear fits
+    float MAX_AP_OFFSET = psMetadataLookupF32 (&status, recipe, "MAX_AP_OFFSET");
+
+    // this is the smallest radius allowed: need to at least extend growth curve down to this...
+    float PSF_FIT_PAD   = psMetadataLookupF32 (&status, recipe, "PSF_FIT_PADDING");
+    bool IGNORE_GROWTH = psMetadataLookupBool (&status, recipe, "IGNORE_GROWTH");
+    bool INTERPOLATE_AP = psMetadataLookupBool (&status, recipe, "INTERPOLATE_AP");
+
+    // XXX is this still needed?  the pmTrend2D stuff should be auto-adjusting...
+    int APTREND_NSTAR_MIN = psMetadataLookupS32(&status, recipe, "APTREND.NSTAR.MIN");
+    assert (status);
+
+    // maximum order for aperture correction
+    int APTREND_ORDER_MAX = psMetadataLookupS32(&status, recipe, "APTREND.ORDER.MAX");
+    assert (status);
+
+    if (APTREND_ORDER_MAX < 1) {
+        psError(PSPHOT_ERR_CONFIG, true, "APTREND.ORDER.MAX must be 1 or more");
+        return false;
+    }
+
+    pmSourcePhotometryMode photMode = 0;
+    if (!IGNORE_GROWTH) photMode |= PM_SOURCE_PHOT_GROWTH;
+    if (INTERPOLATE_AP) photMode |= PM_SOURCE_PHOT_INTERP;
+
+    // set limits on the aperture magnitudes
+    pmSourceMagnitudesInit (recipe);
+
+    // measure the aperture loss as a function of radius for PSF
+    float REF_RADIUS = psMetadataLookupF32 (&status, recipe, "PSF_REF_RADIUS");
+    psf->growth = pmGrowthCurveAlloc (PSF_FIT_PAD, 100.0, REF_RADIUS);
+
+    if (!pmGrowthCurveGenerate (readout, psf, IGNORE_GROWTH, maskVal, markVal)) {
+        psError(PSPHOT_ERR_APERTURE, false, "Fitting aperture corrections");
+        psFree(psf->growth); psf->growth = NULL;
+        return false;
+    }
+
+    psVector *mask    = psVectorAllocEmpty (300, PS_TYPE_U8);
+    psVector *mag     = psVectorAllocEmpty (300, PS_TYPE_F32);
+    psVector *xPos    = psVectorAllocEmpty (300, PS_TYPE_F32);
+    psVector *yPos    = psVectorAllocEmpty (300, PS_TYPE_F32);
+    psVector *apResid = psVectorAllocEmpty (300, PS_TYPE_F32);
+    psVector *dMag    = psVectorAllocEmpty (300, PS_TYPE_F32);
+    Npsf = 0;
+
+    // select all good PM_SOURCE_TYPE_STAR entries
+    for (int i = 0; i < sources->n; i++) {
+        source = sources->data[i];
+        model = source->modelPSF;
+
+        if (source->type != PM_SOURCE_TYPE_STAR) SKIPSTAR ("NOT STAR");
+        if (source->mode &  PM_SOURCE_MODE_SATSTAR) SKIPSTAR ("SATSTAR");
+        if (source->mode &  PM_SOURCE_MODE_BLEND) SKIPSTAR ("BLEND");
+        if (source->mode &  PM_SOURCE_MODE_FAIL) SKIPSTAR ("FAIL STAR");
+        if (source->mode &  PM_SOURCE_MODE_POOR) SKIPSTAR ("POOR STAR");
+
+        // get growth-corrected, apTrend-uncorrected magnitudes in scaled apertures
+        // will fail if below S/N threshold or model is missing
+        if (!pmSourceMagnitudes (source, psf, photMode, maskVal)) {
+            Nskip ++;
+	    psTrace ("psphot", 3, "skip : bad source mag");
+            continue;
+        }
+
+        if (!isfinite(source->apMag) || !isfinite(source->psfMag)) {
+            Nfail ++;
+	    psTrace ("psphot", 3, "fail : nan mags : %f %f", source->apMag, source->psfMag);
+            continue;
+        }
+
+	// aperture residual for this source
+	float dap = source->apMag - source->psfMag;
+
+        // sanity clipping : if the model is very discrepant, put your expectation in the recipe
+        if ((MAX_AP_OFFSET > 0) && (fabs(dap) > MAX_AP_OFFSET)) {
+            Nfail ++;
+	    psTrace ("psphot", 3, "fail : bad dap %f %f", dap, MAX_AP_OFFSET);
+            continue;
+        }
+
+	mag->data.F32[Npsf]     = source->psfMag;
+        apResid->data.F32[Npsf] = dap;
+        xPos->data.F32[Npsf]    = model->params->data.F32[PM_PAR_XPOS];
+        yPos->data.F32[Npsf]    = model->params->data.F32[PM_PAR_YPOS];
+
+        mask->data.U8[Npsf] = 0;
+
+        dMag->data.F32[Npsf] = model->dparams->data.F32[PM_PAR_I0] / model->params->data.F32[PM_PAR_I0];
+
+        psVectorExtend (mag,     100, 1);
+        psVectorExtend (mask,    100, 1);
+        psVectorExtend (xPos,    100, 1);
+        psVectorExtend (yPos,    100, 1);
+        psVectorExtend (dMag,    100, 1);
+        psVectorExtend (apResid, 100, 1);
+        Npsf ++;
+    }
+    
+    psLogMsg ("psphot.apresid", PS_LOG_DETAIL, "measure aperture residuals for %d objects (%d skipped, %d failed, %ld invalid)\n",
+              Npsf, Nskip, Nfail, sources->n - Npsf - Nskip - Nfail);
+
+    // XXX choose a better value here?
+    if (Npsf < APTREND_NSTAR_MIN) {
+        psError(PSPHOT_ERR_APERTURE, true, "Only %d valid aperture residual sources (need %d), giving up",
+                Npsf, APTREND_NSTAR_MIN);
+        return false;
+    }
+
+    // XXX deprecating the old code which allowed the ApResid to be fitted as a function of flux and r^2/flux
+    // XXX is this asymmetric clipping still needed?  this analysis should come after neighbors are subtracted...
+    // 3hi/1lo sigma clipping on the rflux vs metric fit
+    // systematic error information
+    float errorScale = 0.0;
+    float errorFloor = 0.0;
+
+    float errorFloorMin = FLT_MAX;
+    int entryMin = -1;
+
+    // Fit out the dap vs mag trend, iterate over spatial scale until error Floor increases.
+    // Stop if Npsf / (Nx * Ny) < 3
+    for (int i = 1; i <= APTREND_ORDER_MAX; i++) {
+
+	if (!psphotApResidTrend (readout, psf, Npsf, i, &errorScale, &errorFloor, mask, xPos, yPos, apResid, dMag)) {
+	    break;
+	}
+
+	// store the resulting errorFloor values and the scales, redo the best
+	if (errorFloor < errorFloorMin) {
+	    errorFloorMin = errorFloor;
+	    entryMin = i;
+	}
+    }
+    if (entryMin == -1) {
+	psAbort ("failed on ApResid Trend");
+    }
+
+    // XXX catch error condition 
+    psphotApResidTrend (readout, psf, Npsf, entryMin, &errorScale, &errorFloor, mask, xPos, yPos, apResid, dMag);
+
+    // construct the fitted values and the residuals
+    psVector *apResidFit = pmTrend2DEvalVector (psf->ApTrend, xPos, yPos);
+    psVector *apResidRes = (psVector *) psBinaryOp (NULL, (void *) apResid, "-", (void *) apResidFit);
+    psVector *dMagSys = (psVector *) psBinaryOp (NULL, (void *) dMag, "*", (void *) psScalarAlloc(errorScale, PS_TYPE_F32));
+
+    if (psTraceGetLevel("psphot") >= 5) {
+	FILE *dumpFile = fopen ("apresid.dat", "w");
+	for (int i = 0; i < xPos->n; i++) {
+	    fprintf (dumpFile, "%f %f  %f %f %f  %f %f  %x\n", 
+		     xPos->data.F32[i], yPos->data.F32[i], 
+		     mag->data.F32[i], dMag->data.F32[i], dMagSys->data.F32[i],
+		     apResid->data.F32[i], apResidRes->data.F32[i],
+		     mask->data.U8[i]);
+	}
+	fclose (dumpFile);
+    }
+
+    // apply ApTrend results
+    float xc = 0.5*readout->image->numCols + readout->image->col0 + 0.5;
+    float yc = 0.5*readout->image->numRows + readout->image->row0 + 0.5;
+
+    psf->ApResid  = pmTrend2DEval (psf->ApTrend, xc, yc); // ap-fit at chip center
+    psf->dApResid = errorFloor;
+    psf->nApResid = Npsf;
+
+    // save results for later output
+    psMetadataAdd (recipe, PS_LIST_TAIL, "SKYBIAS",  PS_DATA_F32 | PS_META_REPLACE, "aperture sky bias",   0.0);
+    psMetadataAdd (recipe, PS_LIST_TAIL, "SKYSAT",   PS_DATA_F32 | PS_META_REPLACE, "aperture sky bias",   0.0);
+    psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT",  PS_DATA_F32 | PS_META_REPLACE, "aperture residual",   psf->ApResid);
+    psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", psf->dApResid);
+    psMetadataAdd (recipe, PS_LIST_TAIL, "APLOSS",   PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", psf->growth->apLoss);
+    psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "ap residual scatter", psf->nApResid);
+
+    // psLogMsg ("psphot.apresid", PS_LOG_INFO, "measure full-frame aperture residuals for %d of %d objects: %f sec\n", Nkeep, Npsf, psTimerMark ("psphot"));
+    psLogMsg ("psphot.apresid", PS_LOG_DETAIL, "aperture residual: %f +/- %f\n", psf->ApResid, psf->dApResid);
+
+    psFree (mag);
+    psFree (mask);
+    psFree (xPos);
+    psFree (yPos);
+
+    psFree (apResid);
+    psFree (apResidFit);
+    psFree (apResidRes);
+
+    psFree (dMagSys);
+    psFree (dMag);
+
+    return true;
+}
+
+/*
+  (aprMag' - fitMag) = rflux*skyBias + ApTrend(x,y)
+  (aprMag - rflux*skyBias) - fitMag = ApTrend(x,y)
+  (aprMag - rflux*skyBias) = fitMag + ApTrend(x,y)
+*/
+
+bool psphotMagErrorScale (float *errorScale, float *errorFloor, psVector *dMag, psVector *dap, psVector *mask, int nGroup) {
+
+    psStats *statsS = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
+    psStats *statsM = psStatsAlloc (PS_STAT_SAMPLE_MEAN);
+
+    // measure the trend in bins with 10 values each; if < 10 total, use them all
+    int nBin = PS_MAX (dMag->n / nGroup, 1);
+
+    // output vectors for ApResid trend 
+    psVector *dSo = psVectorAlloc (nBin, PS_TYPE_F32);
+    psVector *dMo = psVectorAlloc (nBin, PS_TYPE_F32);
+    psVector *dRo = psVectorAlloc (nBin, PS_TYPE_F32);
+
+    // use dMag to group the dMag and dap vectors
+    psVector *index = psVectorSortIndex (NULL, dMag);
+
+    // subset vectors for dMag and dap values within the given range
+    psVector *dMSubset = psVectorAllocEmpty (nGroup, PS_TYPE_F32);
+    psVector *dASubset = psVectorAllocEmpty (nGroup, PS_TYPE_F32);
+    psVector *mkSubset = psVectorAllocEmpty (nGroup, PS_TYPE_U8);
+
+    int n = 0;
+    for (int i = 0; i < dMo->n; i++) {
+	int j;
+	for (j = 0; (j < nGroup) && (n < dMag->n); j++, n++) {
+	    int N = index->data.U32[n];
+	    dMSubset->data.F32[j] = dMag->data.F32[N];
+	    dASubset->data.F32[j] = dap->data.F32[N];
+	    mkSubset->data.U8[j]  = mask->data.U8[N];
+	}
+	dMSubset->n = j;
+	dASubset->n = j;
+	mkSubset->n = j;
+
+	psStatsInit (statsS);
+	psStatsInit (statsM);
+
+	if (j > 2) {
+	    bool status = true;
+	    status &= psVectorStats (statsS, dASubset, NULL, mkSubset, 0xff);
+	    status &= psVectorStats (statsM, dMSubset, NULL, mkSubset, 0xff);
+	    if (!status) { psErrorClear (); }
+	    dSo->data.F32[i] = statsS->robustStdev;
+	    dMo->data.F32[i] = statsM->sampleMean;
+	    dRo->data.F32[i] = statsS->robustStdev / statsM->sampleMean;
+	} else {
+	    dSo->data.F32[i] = NAN;
+	    dMo->data.F32[i] = NAN;
+	    dRo->data.F32[i] = NAN;
+	}
+    }
+    psFree (dMSubset);
+    psFree (dASubset);
+    psFree (mkSubset);
+    
+    psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
+    if (!psVectorStats (stats, dRo, NULL, NULL, 0)) {
+	// XXX better testing of raised error
+	psErrorClear();
+    }
+
+    *errorScale = stats->sampleMedian;
+    for (int i = 0; i < dSo->n; i++) {
+	*errorFloor = dSo->data.F32[i];
+	if (isfinite(*errorFloor)) break;
+    }
+
+    psFree (stats);
+    psFree (index);
+
+    psFree (dRo);
+    psFree (dMo);
+    psFree (dSo);
+    
+    psFree (statsS);
+    psFree (statsM);
+
+    return true;
+}
+
+bool psphotApResidTrend (pmReadout *readout, pmPSF *psf, int Npsf, int scale, float *errorScale, float *errorFloor, psVector *mask, psVector *xPos, psVector *yPos, psVector *apResid, psVector *dMag) {
+
+    int Nx, Ny;
+	
+    if (readout->image->numCols > readout->image->numRows) {
+	Nx = scale;
+	Ny = PS_MAX (1, Nx * (readout->image->numRows / (float) readout->image->numCols));
+    } else {
+	Ny = scale;
+	Nx = PS_MAX (1, Ny * (readout->image->numCols / (float) readout->image->numRows));
+    }
+
+    if (Npsf < 3*Nx*Ny) {
+	return false;
+    }
+
+    // the mask marks the values not used to calculate the ApTrend
+    psVectorInit (mask, 0);
+
+    // XXX stats structure for use by ApTrend : make parameters user setable
+    psStats *stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
+    stats->min = 2.0;
+    stats->max = 3.0;
+
+    // measure Trend2D for the current spatial scale
+    psFree (psf->ApTrend);
+    psf->ApTrend = pmTrend2DAlloc (PM_TREND_MAP, readout->image, Nx, Ny, stats);
+
+    // XXX test for errors here
+    pmTrend2DFit (psf->ApTrend, mask, 0xff, xPos, yPos, apResid, dMag);
+    
+    // construct the fitted values and the residuals
+    psVector *apResidFit = pmTrend2DEvalVector (psf->ApTrend, xPos, yPos);
+    psVector *apResidRes = (psVector *) psBinaryOp (NULL, (void *) apResid, "-", (void *) apResidFit);
+
+    // measure systematic errorFloor & systematic / photon scale factor
+    // XXX this is a bit arbitrary, but it forces ~3 stars from the bright bin per spatial bin
+    int nGroup = PS_MAX (3*Nx*Ny, 10);
+    psphotMagErrorScale (errorScale, errorFloor, dMag, apResidRes, mask, nGroup);
+
+    psLogMsg ("psphot.apresid", PS_LOG_INFO, "result of %d x %d grid (%d stars per bin)\n", Nx, Ny, nGroup);
+    psLogMsg ("psphot.apresid", PS_LOG_INFO, "systematic error / photon error: %f\n", *errorScale);
+    psLogMsg ("psphot.apresid", PS_LOG_INFO, "systematic scatter floor: %f\n", *errorFloor);
+
+    psFree (stats);
+    psFree (apResidFit);
+    psFree (apResidRes);
+
+    return true;
+}
+    
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotArguments.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotArguments.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotArguments.c	(revision 22158)
@@ -0,0 +1,122 @@
+# include "psphotStandAlone.h"
+
+pmConfig *psphotArguments(int argc, char **argv) {
+
+    int N;
+    bool status;
+
+    if (argc == 1) {
+        psError(PSPHOT_ERR_ARGUMENTS, true, "Too few arguments: %d", argc);
+        return NULL;
+    }
+
+    if ((N = psArgumentGet (argc, argv, "-version"))) {
+        psString version;
+        version = psphotVersionLong();    fprintf (stdout, "%s\n", version); psFree (version);
+        version = psModulesVersionLong(); fprintf (stdout, "%s\n", version); psFree (version);
+        version = psLibVersionLong();     fprintf (stdout, "%s\n", version); psFree (version);
+        exit (0);
+    }
+
+    // load config data from default locations
+    pmConfig *config = pmConfigRead(&argc, argv, PSPHOT_RECIPE);
+    if (config == NULL) {
+        psError(PSPHOT_ERR_CONFIG, false, "Can't read site configuration");
+        return NULL;
+    }
+
+    // save the following additional recipe values based on command-line options
+    // these options override the PSPHOT recipe values loaded from recipe files
+    psMetadata *options = pmConfigRecipeOptions (config, PSPHOT_RECIPE);
+
+    // run the test model (requires X,Y coordinate)
+    if ((N = psArgumentGet (argc, argv, "-modeltest"))) {
+        psMetadataAddBool (options, PS_LIST_TAIL, "TEST_FIT",   0, "", true);
+        psMetadataAddF32  (options, PS_LIST_TAIL, "TEST_FIT_X", 0, "", atof(argv[N+1]));
+        psMetadataAddF32  (options, PS_LIST_TAIL, "TEST_FIT_Y", 0, "", atof(argv[N+2]));
+
+        psArgumentRemove (N, &argc, argv);
+        psArgumentRemove (N, &argc, argv);
+        psArgumentRemove (N, &argc, argv);
+
+        // specify the modeltest model
+        if ((N = psArgumentGet (argc, argv, "-model"))) {
+            psArgumentRemove (N, &argc, argv);
+            psMetadataAddStr (options, PS_LIST_TAIL, "TEST_FIT_MODEL", 0, "", argv[N]);
+            psArgumentRemove (N, &argc, argv);
+        }
+
+        // specify the test fit mode
+        if ((N = psArgumentGet (argc, argv, "-fitmode"))) {
+            psArgumentRemove (N, &argc, argv);
+            psMetadataAddStr (options, PS_LIST_TAIL, "TEST_FIT_MODE", 0, "", argv[N]);
+            psArgumentRemove (N, &argc, argv);
+        }
+        if ((N = psArgumentGet (argc, argv, "-fitset"))) {
+            psArgumentRemove (N, &argc, argv);
+            psMetadataAddStr (options, PS_LIST_TAIL, "TEST_FIT_SET", 0, "", argv[N]);
+            psArgumentRemove (N, &argc, argv);
+        }
+    }
+
+    // photcode : used in output to supplement header data (argument or recipe?)
+    if ((N = psArgumentGet (argc, argv, "-photcode"))) {
+        psArgumentRemove (N, &argc, argv);
+        psMetadataAddStr (options, PS_LIST_TAIL, "PHOTCODE", PS_META_REPLACE, "", argv[N]);
+        psArgumentRemove (N, &argc, argv);
+    }
+
+    // break : used from recipe throughout psphotReadout
+    if ((N = psArgumentGet (argc, argv, "-break"))) {
+        psArgumentRemove (N, &argc, argv);
+        psMetadataAddStr (options, PS_LIST_TAIL, "BREAK_POINT", PS_META_REPLACE, "", argv[N]);
+        psArgumentRemove (N, &argc, argv);
+    }
+
+    // fitmode : used from recipe throughout psphotReadout
+    if ((N = psArgumentGet (argc, argv, "-fitmode"))) {
+        psArgumentRemove (N, &argc, argv);
+        psMetadataAddStr (options, PS_LIST_TAIL, "FITMODE", PS_META_REPLACE, "", argv[N]);
+        psArgumentRemove (N, &argc, argv);
+    }
+
+    // analysis region : overrides recipe value, used in psphotReadout/psphotEnsemblePSF
+    if ((N = psArgumentGet (argc, argv, "-region"))) {
+        psArgumentRemove (N, &argc, argv);
+        psMetadataAddStr (options, PS_LIST_TAIL, "ANALYSIS_REGION", 0, "", argv[N]);
+        psArgumentRemove (N, &argc, argv);
+    }
+
+    // chip selection is used to limit chips to be processed
+    if ((N = psArgumentGet (argc, argv, "-chip"))) {
+        psArgumentRemove (N, &argc, argv);
+        psMetadataAddStr (config->arguments, PS_LIST_TAIL, "CHIP_SELECTIONS", PS_DATA_STRING, "", argv[N]);
+        psArgumentRemove (N, &argc, argv);
+    }
+
+    // if these command-line options are supplied, load the file name lists into config->arguments
+    // override any configuration-specified source for these files
+    //
+    pmConfigFileSetsMD (config->arguments, &argc, argv, "MASK",   "-mask",   "-masklist");
+    pmConfigFileSetsMD (config->arguments, &argc, argv, "WEIGHT", "-weight", "-weightlist");
+    pmConfigFileSetsMD (config->arguments, &argc, argv, "PSPHOT.PSF", "-psf", "-psflist");
+    pmConfigFileSetsMD (config->arguments, &argc, argv, "SRC",    "-src",    "-srclist");
+
+    // the input file is a required argument; if not found, we will exit
+    status = pmConfigFileSetsMD (config->arguments, &argc, argv, "INPUT", "-file", "-list");
+    if (!status) {
+        psError(PSPHOT_ERR_ARGUMENTS, false, "pmConfigFileSetsMD failed to parse arguments");
+        return NULL;
+    }
+
+    if (argc != 2) {
+        psError(PSPHOT_ERR_ARGUMENTS, true, "Expected to see one more argument; saw %d", argc - 1);
+        return NULL;
+    }
+
+    // output position is fixed
+    psMetadataAddStr (config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "", argv[1]);
+
+    psTrace("psphot", 1, "Done with psphotArguments...\n");
+    return (config);
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotBasicDeblend.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotBasicDeblend.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotBasicDeblend.c	(revision 22158)
@@ -0,0 +1,129 @@
+# include "psphotInternal.h"
+
+bool psphotBasicDeblend (psArray *sources, psMetadata *recipe) {
+
+    int N;
+    bool status;
+    float threshold;
+    pmSource *source, *testSource;
+
+    int Nblend = 0;
+
+    psTimerStart ("psphot");
+
+    float FRACTION = psMetadataLookupF32 (&status, recipe, "DEBLEND_PEAK_FRACTION");
+    if (!status) FRACTION = 0.25;
+
+    float NSIGMA   = psMetadataLookupF32 (&status, recipe, "DEBLEND_SKY_NSIGMA");
+    if (!status) NSIGMA = 5.0;
+
+    // we need sources spatially-sorted to find overlaps
+    sources = psArraySort (sources, pmSourceSortByY);
+
+    // source analysis is done in peak order (brightest first)
+    // we use an index for this so the spatial sorting is kept
+    psVector *SN = psVectorAlloc (sources->n, PS_DATA_F32);
+    for (int i = 0; i < SN->n; i++) {
+        source = sources->data[i];
+        SN->data.F32[i] = source->peak->SN;
+    }
+    psVector *index = psVectorSortIndex (NULL, SN);
+    // this results in an index of increasing SN
+
+    // examine sources in decreasing SN order
+    for (int i = sources->n - 1; i >= 0; i--) {
+        N = index->data.U32[i];
+        source = sources->data[N];
+
+        if (source->mode & PM_SOURCE_MODE_BLEND) continue;
+
+        // temporary array for overlapping objects we find
+        psArray *overlap = psArrayAllocEmpty (100);
+
+        // search backwards for overlapping sources
+        for (int j = N - 1; j >= 0; j--) {
+            testSource = sources->data[j];
+            if (testSource->peak->x <  source->pixels->col0) continue;
+            if (testSource->peak->x >= source->pixels->col0 + source->pixels->numCols) continue;
+            if (testSource->peak->y <  source->pixels->row0) break;
+            if (testSource->peak->y >= source->pixels->row0 + source->pixels->numRows) {
+                fprintf (stderr, "warning: invalid condition\n");
+                continue;
+            }
+            psArrayAdd (overlap, 100, testSource);
+        }
+
+        // search forwards for overlapping sources
+        for (int j = N + 1; j < sources->n; j++) {
+            testSource = sources->data[j];
+            if (testSource->peak->x <  source->pixels->col0) continue;
+            if (testSource->peak->x >= source->pixels->col0 + source->pixels->numCols) continue;
+            if (testSource->peak->y <  source->pixels->row0) {
+                fprintf (stderr, "warning: invalid condition\n");
+                continue;
+            }
+            if (testSource->peak->y >= source->pixels->row0 + source->pixels->numRows) break;
+            psArrayAdd (overlap, 100, testSource);
+        }
+
+        if (overlap->n == 0) {
+            psFree (overlap);
+            continue;
+        }
+
+        // this source has overlapping neighbors, check for actual blends
+        // generate source contour (1/4 peak counts)
+        // set the threshold based on user inputs
+
+        // threshold is fraction of the source peak flux
+        // image is background subtracted; source->moments->Sky should always be 0.0
+        threshold = FRACTION * source->peak->SN;
+        // threshold is no less than NSIGMA
+        threshold = PS_MAX (threshold, NSIGMA);
+
+        // generate a basic contour (set of x,y coordinates at-or-below flux level)
+        psArray *contour = pmSourceContour (source->pixels, source->peak->x, source->peak->y, threshold);
+        if (contour == NULL) {
+            psFree (overlap);
+            continue;
+        }
+
+        // the source contour consists of two vectors, xv and yv.  the contour is
+        // a series of coordinate pairs, (xv[i],yv[i]) & (xv[i+1],yv[i+1]).  both
+        // coordinate pairs have the same yv[] value, with xv[i] corresponding to
+        // the left boundary and xv[i+1] corresponding to the right boundary
+
+	// a blend can only be associated with one primary source
+
+        psVector *xv = contour->data[0];
+        psVector *yv = contour->data[1];
+        for (int k = 0; k < overlap->n; k++) {
+            testSource = overlap->data[k];
+	    if (testSource->mode & PM_SOURCE_MODE_BLEND) continue;
+            if (testSource->peak->value > source->peak->value) continue;
+            for (int j = 0; j < xv->n; j+=2) {
+                if (fabs(yv->data.F32[j] - testSource->peak->y) > 0.5) continue;
+                if (xv->data.F32[j+0] > testSource->peak->x) break;
+                if (xv->data.F32[j+1] < testSource->peak->x) break;
+
+                testSource->mode |= PM_SOURCE_MODE_BLEND;
+
+                // add this to the list of source->blends
+                if (source->blends == NULL) {
+                    source->blends = psArrayAllocEmpty (16);
+                }
+                psArrayAdd (source->blends, 16, testSource);
+
+                Nblend ++;
+                j = xv->n;
+            }
+        }
+        psFree (overlap);
+        psFree (contour);
+    }
+    psLogMsg ("psphot.deblend", PS_LOG_INFO, "identified %d blended objects: %f sec\n", Nblend, psTimerMark ("psphot"));
+
+    psFree (SN);
+    psFree (index);
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotBlendFit.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotBlendFit.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotBlendFit.c	(revision 22158)
@@ -0,0 +1,120 @@
+# include "psphotInternal.h"
+
+// XXX I don't like this name
+bool psphotBlendFit (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf) {
+
+    int Nfit = 0;
+    int Npsf = 0;
+    int Next = 0;
+    int Nfail = 0;
+    bool status;
+
+    psTimerStart ("psphot");
+
+    // bit-masks to test for good/bad pixels
+    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT");
+    assert (maskVal);
+
+    // bit-mask to mark pixels not used in analysis
+    psMaskType markVal = psMetadataLookupU8(&status, recipe, "MARK.PSPHOT");
+    assert (markVal);
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
+    // source analysis is done in S/N order (brightest first)
+    sources = psArraySort (sources, pmSourceSortBySN);
+
+    // S/N limit to perform full non-linear fits
+    float FIT_SN_LIM = psMetadataLookupF32 (&status, recipe, "FULL_FIT_SN_LIM");
+
+    psphotInitLimitsPSF (recipe, readout);
+    psphotInitLimitsEXT (recipe);
+    psphotInitRadiusPSF (recipe, psf->type);
+
+    psphotFitInit ();
+
+    // option to limit analysis to a specific region
+    char *region = psMetadataLookupStr (&status, recipe, "ANALYSIS_REGION");
+    psRegion AnalysisRegion = psRegionForImage (readout->image, psRegionFromString (region));
+    if (psRegionIsNaN (AnalysisRegion)) psAbort("analysis region mis-defined");
+
+    for (int i = 0; i < sources->n; i++) {
+        // if (i%100 == 0) psphotFitSummary ();
+
+        pmSource *source = sources->data[i];
+
+        // skip non-astronomical objects (very likely defects)
+        if (source->mode &  PM_SOURCE_MODE_BLEND) continue;
+        if (source->mode &  PM_SOURCE_MODE_CR_LIMIT) continue;
+        if (source->type == PM_SOURCE_TYPE_DEFECT) continue;
+        if (source->type == PM_SOURCE_TYPE_SATURATED) continue;
+
+        // skip DBL second sources (ie, added by psphotFitBlob)
+        if (source->mode &  PM_SOURCE_MODE_PAIR) continue;
+
+        // limit selection to some SN limit
+        // XXX this should use peak?
+        if (source->moments == NULL) continue;
+        if (source->moments->SN < FIT_SN_LIM) continue;
+
+        // XXX this should use peak?
+        if (source->moments->x < AnalysisRegion.x0) continue;
+        if (source->moments->y < AnalysisRegion.y0) continue;
+        if (source->moments->x > AnalysisRegion.x1) continue;
+        if (source->moments->y > AnalysisRegion.y1) continue;
+
+        // if model is NULL, we don't have a starting guess
+        if (source->modelPSF == NULL) continue;
+
+        // skip sources which are insignificant flux?
+        if (source->modelPSF->params->data.F32[1] < 0.1) {
+            psTrace ("psphot", 5, "skipping near-zero source: %f, %f : %f\n",
+                     source->modelPSF->params->data.F32[1],
+                     source->modelPSF->params->data.F32[2],
+                     source->modelPSF->params->data.F32[3]);
+            continue;
+        }
+
+        // replace object in image
+        if (source->mode & PM_SOURCE_MODE_SUBTRACTED) {
+            pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
+        }
+        Nfit ++;
+
+        // try fitting PSFs, then try extended sources
+        // these functions subtract the resulting fitted source (XXX and update the modelFlux?)
+	// XXX re-consider conditions under which the source has EXT fit:
+	// I should try EXT if the source size measurement says it is large
+	if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) {
+	    if (psphotFitBlob (readout, source, sources, psf, maskVal, markVal)) {
+		source->type = PM_SOURCE_TYPE_EXTENDED;
+		psTrace ("psphot", 5, "source at %7.1f, %7.1f is ext", source->moments->x, source->moments->y);
+		Next ++;
+		continue;
+	    }
+	} else {
+	    if (psphotFitBlend (readout, source, psf, maskVal, markVal)) {
+		source->type = PM_SOURCE_TYPE_STAR;
+		psTrace ("psphot", 5, "source at %7.1f, %7.1f is psf", source->moments->x, source->moments->y);
+		Npsf ++;
+		continue;
+	    }
+	}
+
+        psTrace ("psphot", 5, "source at %7.1f, %7.1f failed", source->moments->x, source->moments->y);
+        Nfail ++;
+
+        // re-subtract the object, leave local sky
+        pmSourceCacheModel (source, maskVal);
+        pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
+        source->mode |= PM_SOURCE_MODE_SUBTRACTED;
+    }
+
+    if (psTraceGetLevel("psphot") >= 6) {
+      psphotSaveImage (NULL, readout->image,  "image.v2.fits");
+    }
+
+    psLogMsg ("psphot.psphotBlendFit", PS_LOG_INFO, "fit models: %f sec for %d objects (%d psf, %d ext, %d failed, %ld skipped)\n", psTimerMark ("psphot"), Nfit, Npsf, Next, Nfail, sources->n - Nfit);
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotCheckStarDistribution.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotCheckStarDistribution.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotCheckStarDistribution.c	(revision 22158)
@@ -0,0 +1,104 @@
+# include "psphotInternal.h"
+
+// examine the x,y distribution of the psfstars and extend the selection if needed
+// desired region and coverage are specified by pmPSFOptions
+// even if stars->n is at the limit, we will add more sources to fill out the area
+
+bool psphotCheckStarDistribution (psArray *stars, psArray *sources, pmPSFOptions *options) {
+
+    // count the number of PSFSTAR sources in each cell.  for polynomial representations, we
+    // use an image (Norder + 1) x (Norder + 1)
+    int Nx = options->psfTrendNx;
+    int Ny = options->psfTrendNy;
+    if (options->psfTrendMode != PM_TREND_MAP) {
+	Nx ++;
+	Ny ++;
+    }
+
+    // set up and image and an image binning structure to cover the field
+    psImage *nCell = psImageAlloc (Nx, Ny, PS_TYPE_S32);
+    psImageInit (nCell, 0);
+
+    psImageBinning *binning = psImageBinningAlloc();
+    binning->nXruff = Nx;
+    binning->nYruff = Ny;
+    binning->nXfine = options->psfFieldNx;
+    binning->nYfine = options->psfFieldNy;
+
+    psImageBinningSetScale (binning, PS_IMAGE_BINNING_CENTER);
+    psImageBinningSetSkipByOffset (binning, options->psfFieldXo, options->psfFieldYo);
+
+    // where are the PSF stars located?
+    for (int i = 0; i < stars->n; i++) {
+	
+	pmSource *source = stars->data[i];
+        if (source->peak == NULL) continue;
+        if (!(source->mode & PM_SOURCE_MODE_PSFSTAR)) continue;
+
+	int binX = psImageBinningGetRuffX (binning, source->peak->xf);
+	int binY = psImageBinningGetRuffY (binning, source->peak->yf);
+
+	assert (binX >= 0);
+	assert (binY >= 0);
+	assert (binX <  nCell->numCols);
+	assert (binY <  nCell->numRows);
+
+	nCell->data.S32[binY][binX] ++;
+    }
+	
+    // do any cells have too few PSFSTAR sources?
+    // we use 3 as a minimum (slightly arbitrary...)
+    for (int iy = 0; iy < nCell->numRows; iy++) { 
+	for (int ix = 0; ix < nCell->numCols; ix++) { 
+	    if (nCell->data.S32[iy][ix] < 3) {
+		int nNew = psphotSupplementStars (stars, sources, binning, ix, iy);
+		if (nNew) {
+		    psLogMsg ("pmObjects", 3, "added %d fainter PSF candidates to %d,%d\n", nNew, ix, iy);
+		} else {
+		    psLogMsg ("pmObjects", 3, "tried to add to %d,%d, but no more sources are available\n", ix, iy);		    
+		}
+	    }
+	}
+    }
+
+    psFree (nCell);
+    psFree (binning);
+    return true;
+}
+
+// select more possible PSF stars in the specified cell
+// sources should be sorted by SN before calling this function
+int psphotSupplementStars (psArray *stars, psArray *sources, psImageBinning *binning, int ix, int iy) {
+
+    int nNew = 0;
+
+    float Xs = psImageBinningGetFineX (binning, ix);
+    float Xe = psImageBinningGetFineX (binning, ix + 1);
+
+    float Ys = psImageBinningGetFineY (binning, iy);
+    float Ye = psImageBinningGetFineY (binning, iy + 1);
+
+    for (int i = 0; i < sources->n; i++) {
+
+	// add sources which are marked as stars, in S/N order until...
+	pmSource *source = sources->data[i];
+        if (source->peak == NULL) continue;
+        if (source->moments == NULL) continue;
+        if (source->mode & PM_SOURCE_MODE_PSFSTAR) continue;
+        if (source->type != PM_SOURCE_TYPE_STAR) continue;
+
+	float x = source->peak->xf;
+	float y = source->peak->yf;
+
+	if (x < Xs) continue;
+	if (y < Ys) continue;
+	if (x > Xe) continue;
+	if (y > Ye) continue;
+
+	source->mode |= PM_SOURCE_MODE_PSFSTAR;
+	psArrayAdd (stars, 200, source);
+
+	nNew ++;
+    }
+    return nNew;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotChoosePSF.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotChoosePSF.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotChoosePSF.c	(revision 22158)
@@ -0,0 +1,492 @@
+# include "psphotInternal.h"
+
+// try PSF models and select best option
+pmPSF *psphotChoosePSF (pmReadout *readout, psArray *sources, psMetadata *recipe) {
+
+    bool status;
+
+    psTimerStart ("psphot");
+
+    // bit-masks to test for good/bad pixels
+    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT");
+    assert (maskVal);
+
+    // bit-mask to mark pixels not used in analysis
+    psMaskType markVal = psMetadataLookupU8(&status, recipe, "MARK.PSPHOT");
+    assert (markVal);
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
+    // examine PSF sources in S/N order (brightest first)
+    sources = psArraySort (sources, pmSourceSortBySN);
+
+    // structure to store user options defining the psf
+    pmPSFOptions *options = pmPSFOptionsAlloc ();
+
+    // load user options from the recipe. no need to check existence -- they are
+    // array to store candidate PSF stars
+    int NSTARS = psMetadataLookupS32 (&status, recipe, "PSF_MAX_NSTARS");
+    assert (status);
+
+    float PSF_MIN_DS = psMetadataLookupF32 (&status, recipe, "PSF_MIN_DS");
+    assert (status);
+
+    // supply the measured sky variance for optional constant errors (non-poissonian)
+    float SKY_SIG = psMetadataLookupF32 (&status, recipe, "SKY_SIG");
+    assert (status);
+
+    // use poissonian errors or local-sky errors
+    options->poissonErrorsPhotLMM = psMetadataLookupBool (&status, recipe, "POISSON.ERRORS.PHOT.LMM");
+    assert (status);
+
+    // use poissonian errors or local-sky errors
+    options->poissonErrorsPhotLin = psMetadataLookupBool (&status, recipe, "POISSON.ERRORS.PHOT.LIN");
+    assert (status);
+
+    // use poissonian errors or local-sky errors
+    options->poissonErrorsParams = psMetadataLookupBool (&status, recipe, "POISSON.ERRORS.PARAMS");
+    assert (status);
+
+    // how to model the PSF variations across the field
+    options->psfTrendMode = pmTrend2DModeFromString (psMetadataLookupStr (&status, recipe, "PSF.TREND.MODE"));
+    assert (status);
+
+    options->psfTrendNx = psMetadataLookupS32 (&status, recipe, "PSF.TREND.NX");
+    assert (status);
+
+    options->psfTrendNy = psMetadataLookupS32 (&status, recipe, "PSF.TREND.NY");
+    assert (status);
+
+    // get the fixed PSF fit radius
+    // XXX check that PSF_FIT_RADIUS < SKY_OUTER_RADIUS
+    options->radius = psMetadataLookupF32 (&status, recipe, "PSF_FIT_RADIUS");
+    assert (status);
+
+    // XXX ROBUST seems to be too agressive given the small numbers.  
+    // options->stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
+    options->stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
+
+    // dimensions of the field for which the PSF is defined
+    options->psfFieldNx = readout->image->numCols;
+    options->psfFieldNy = readout->image->numRows;
+    options->psfFieldXo = readout->image->col0;
+    options->psfFieldYo = readout->image->row0;
+
+    pmSourceFitModelInit (15, 0.01, PS_SQR(SKY_SIG), options->poissonErrorsPhotLMM);
+
+    psArray *stars = psArrayAllocEmpty (sources->n);
+
+    // select the candidate PSF stars (pointers to original sources)
+    for (int i = 0; i < sources->n; i++) {
+        pmSource *source = sources->data[i];
+        if (source->mode & PM_SOURCE_MODE_PSFSTAR) {
+            // keep NSTARS PSF stars, unmark the rest
+            if (stars->n < NSTARS) {
+                psArrayAdd (stars, 200, source);
+            } else {
+                source->mode &= ~PM_SOURCE_MODE_PSFSTAR;
+            }
+        }
+    }
+    // check that the identified psf stars sufficiently cover the region; if not, extend the
+    // limits somewhat
+    psphotCheckStarDistribution (stars, sources, options);
+
+    psLogMsg ("psphot.pspsf", PS_LOG_DETAIL, "selected candidate %ld PSF objects\n", stars->n);
+
+    // get the list pointers for the PSF_MODEL entries
+    psArray *modelNames = NULL;
+    psMetadataItem *item = psMetadataLookup (recipe, "PSF_MODEL");
+    if (item == NULL) psAbort("missing PSF_MODEL selection");
+
+    if (item->type == PS_DATA_STRING) {
+        modelNames = psArrayAlloc(1);
+        modelNames->data[0] = psStringCopy (item->data.V);
+    } else {
+        if (item->type != PS_DATA_METADATA_MULTI) psAbort("missing PSF_MODEL selection");
+        modelNames = psListToArray (item->data.list);
+    }
+
+    // generate a psf model using the first selection
+    if (stars->n == 0) {
+        psError(PSPHOT_ERR_PSF, false, "Failed to fit any models when choosing PSF");
+        bool mdok;                      // Status of MD lookup
+        if (!psMetadataLookupBool(&mdok, recipe, PSPHOT_RECIPE_PSF_FAKE_ALLOW)) {
+            return false;
+        }
+        psErrorStackPrint(stderr, "Using guess PSF model");
+        psErrorClear();
+
+        psFree(options);
+
+        // unset the PSFSTAR flags (none are used):
+        for (int i = 0; i < sources->n; i++) {
+            pmSource *source = sources->data[i];
+            source->mode &= ~PM_SOURCE_MODE_PSFSTAR;
+        }
+
+        // XXX set sxx, etc from FWHM in recipe
+        pmPSF *psf = pmPSFBuildSimple (modelNames->data[0], 1.0, 1.0, 0.0, 1.0);
+        psf->fieldNx = readout->image->numCols;
+        psf->fieldNy = readout->image->numRows;
+        psFree (modelNames);
+
+        bool status = true;
+        status &= psphotMakeFluxScale (readout->image, recipe, psf);
+        status &= psphotPSFstats (readout, recipe, psf);
+        if (!status) {
+            psError(PSPHOT_ERR_PSF, false, "Failed to fit any models when choosing PSF");
+            psFree (psf);
+            return NULL;
+        }
+
+        // XXX set DSX_MEAN, etc?
+        return psf;
+    }
+
+    // set up an array to store the results
+    psArray *models = psArrayAlloc (modelNames->n);
+
+    // try each model option listed in config
+    for (int i = 0; i < modelNames->n; i++) {
+        char *modelName = modelNames->data[i];
+        pmPSFtry *try = pmPSFtryModel (stars, modelName, options, maskVal, markVal); // Attempt at fit
+        if (!try) {
+            // No big deal --- we'll try another model
+            psErrorClear();
+            continue;
+        }
+        models->data[i] = try;
+    }
+
+    // select the best of the models
+    // here we are using the clippedStdev on the metric as the indicator
+    int bestN = -1;
+    float bestM = 0.0;
+    for (int i = 0; i < models->n; i++) {
+        pmPSFtry *try = models->data[i];
+        if (try == NULL) {
+            psTrace ("psphot", 3, "PSF model %d is NULL", i);
+            continue;
+        }
+        float M = try->psf->dApResid;
+        if (bestN < 0 || M < bestM) {
+            bestM = M;
+            bestN = i;
+        }
+    }
+
+    // use the best model:
+    if (bestN < 0) {
+        psFree (models);
+        psFree (stars);
+
+        psErrorStackPrint (stderr, "Failed to fit any models when choosing PSF");
+        psErrorClear();
+
+        bool mdok;                      // Status of MD lookup
+        if (!psMetadataLookupBool(&mdok, recipe, PSPHOT_RECIPE_PSF_FAKE_ALLOW)) {
+	    psFree (modelNames);
+	    psFree(options);
+            return NULL;
+        }
+
+        // generate a psf model using the first selection
+	psLogMsg ("psphot.pspsf", PS_LOG_INFO, "Using guess PSF model");
+
+        // unset the PSFSTAR flags (none are used):
+        for (int i = 0; i < sources->n; i++) {
+            pmSource *source = sources->data[i];
+            source->mode &= ~PM_SOURCE_MODE_PSFSTAR;
+        }
+
+        // XXX set sxx, etc from FWHM in recipe
+        pmPSF *psf = pmPSFBuildSimple (modelNames->data[0], 1.0, 1.0, 0.0, 1.0);
+        psf->fieldNx = readout->image->numCols;
+        psf->fieldNy = readout->image->numRows;
+        psFree (modelNames);
+
+        bool status = true;
+        status &= psphotMakeFluxScale (readout->image, recipe, psf);
+        status &= psphotPSFstats (readout, recipe, psf);
+        if (!status) {
+            psError(PSPHOT_ERR_PSF, false, "Failed to fit any models when choosing PSF");
+            psFree (psf);
+            return NULL;
+        }
+
+        // XXX set DSX_MEAN, etc?
+        return psf;
+    }
+
+    psFree (modelNames);
+    psFree (stars);
+
+    pmPSFtry *try = models->data[bestN];
+
+    // measure and save the median value of dparams[PM_PAR_SXX],dparams[PM_PAR_SYY]
+    // these are used by psphotEvalPSF to identify extended sources
+    // XXX is this still needed?
+    psVector *Sx = psVectorAllocEmpty (try->sources->n, PS_TYPE_F32);
+    psVector *Sy = psVectorAllocEmpty (try->sources->n, PS_TYPE_F32);
+    psVector *dSx = psVectorAllocEmpty (try->sources->n, PS_TYPE_F32);
+    psVector *dSy = psVectorAllocEmpty (try->sources->n, PS_TYPE_F32);
+    psVector *dSN = psVectorAllocEmpty (try->sources->n, PS_TYPE_F32);
+    for (int i = 0; i < try->sources->n; i++) {
+        // masked for: bad model fit, outlier in parameters
+        if (try->mask->data.U8[i] & PSFTRY_MASK_ALL)
+            continue;
+
+        pmSource *source = try->sources->data[i];
+        Sx->data.F32[Sx->n] = source->modelPSF->params->data.F32[PM_PAR_SXX];
+        Sy->data.F32[Sy->n] = source->modelPSF->params->data.F32[PM_PAR_SYY];
+        dSN->data.F32[dSN->n] = source->modelPSF->dparams->data.F32[PM_PAR_I0] / source->modelPSF->params->data.F32[PM_PAR_I0];
+        dSx->data.F32[dSx->n] = source->modelPSF->dparams->data.F32[PM_PAR_SXX];
+        dSy->data.F32[dSy->n] = source->modelPSF->dparams->data.F32[PM_PAR_SYY];
+        Sx->n ++;
+        Sy->n ++;
+        dSN->n ++;
+        dSx->n ++;
+        dSy->n ++;
+    }
+    psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
+
+    psVectorStats (stats, dSx, NULL, NULL, 0);
+    float dSxo = stats->sampleMean;
+    psLogMsg ("psphot.choosePSF", PS_LOG_INFO, "dSxo: mean: %f, median: %f, stdev: %f, npts: %ld", stats->sampleMean, stats->sampleMedian, stats->sampleStdev, dSx->n);
+
+    psVectorStats (stats, dSy, NULL, NULL, 0);
+    float dSyo = stats->sampleMean;
+    psLogMsg ("psphot.choosePSF", PS_LOG_INFO, "dSyo: mean: %f, median: %f, stdev: %f, npts: %ld", stats->sampleMean, stats->sampleMedian, stats->sampleStdev, dSy->n);
+
+    for (int i = 0; i < dSN->n; i++) {
+        dSx->data.F32[i] = (dSx->data.F32[i] - dSxo) / PS_MAX (PSF_MIN_DS, Sx->data.F32[i]*dSN->data.F32[i]);
+        dSy->data.F32[i] = (dSy->data.F32[i] - dSyo) / PS_MAX (PSF_MIN_DS, Sy->data.F32[i]*dSN->data.F32[i]);
+    }
+
+    psVectorStats (stats, dSx, NULL, NULL, 0);
+    float nSx = stats->sampleStdev;
+    psLogMsg ("psphot.choosePSF", PS_LOG_INFO, "ndSx: mean: %f, median: %f, stdev: %f, npts: %ld", stats->sampleMean, stats->sampleMedian, stats->sampleStdev, dSx->n);
+    psVectorStats (stats, dSy, NULL, NULL, 0);
+    float nSy = stats->sampleStdev;
+    psLogMsg ("psphot.choosePSF", PS_LOG_INFO, "ndSy: mean: %f, median: %f, stdev: %f, npts: %ld", stats->sampleMean, stats->sampleMedian, stats->sampleStdev, dSy->n);
+
+    psFree (Sx);
+    psFree (Sy);
+    psFree (dSx);
+    psFree (dSy);
+    psFree (dSN);
+    psFree (stats);
+
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "DSX_MEAN", PS_META_REPLACE, "mean offset of dSXX", dSxo);
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "DSY_MEAN", PS_META_REPLACE, "mean offset of dSYY", dSyo);
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "DSX_STDV", PS_META_REPLACE, "stdev of mean-corrected dSXX", nSx);
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "DSY_STDV", PS_META_REPLACE, "stdev of mean-corrected dSYY", nSy);
+
+    // unset the PSFSTAR flag for stars not used for PSF model
+    for (int i = 0; i < try->sources->n; i++) {
+        pmSource *source = try->sources->data[i];
+        if (try->mask->data.U8[i]) {
+            source->mode &= ~PM_SOURCE_MODE_PSFSTAR;
+        }
+    }
+
+    // build a PSF residual image
+    if (!psphotMakeResiduals (try->sources, recipe, try->psf, maskVal)) {
+        psError(PSPHOT_ERR_PSF, false, "Unable to construct residual table for PSF");
+        psFree (models);
+        psFree(options);
+        return NULL;
+    }
+
+    // build a PSF residual image
+    if (!psphotMakeFluxScale (readout->image, recipe, try->psf)) {
+        psError(PSPHOT_ERR_PSF, false, "Unable to construct flux scale for PSF");
+        psFree (models);
+        psFree(options);
+        return NULL;
+    }
+
+    // XXX test dump of psf star data and psf-subtracted image
+    if (psTraceGetLevel("psphot.psfstars") > 5) {
+        psphotSaveImage (NULL, readout->image,  "rawstars.fits");
+
+        for (int i = 0; i < try->sources->n; i++) {
+            // masked for: bad model fit, outlier in parameters
+            if (try->mask->data.U8[i] & PSFTRY_MASK_ALL)
+                continue;
+
+            pmSource *source = try->sources->data[i];
+            float x = source->modelPSF->params->data.F32[PM_PAR_XPOS];
+            float y = source->modelPSF->params->data.F32[PM_PAR_YPOS];
+
+            // set the mask and subtract the PSF model
+            // XXX should we be using maskObj? should we be unsetting the mask?
+            // use pmModelSub because modelFlux has not been generated
+            assert (source->maskObj);
+            psImageKeepCircle (source->maskObj, x, y, options->radius, "OR", markVal);
+            pmModelSub (source->pixels, source->maskObj, source->modelPSF, PM_MODEL_OP_FULL, maskVal);
+            psImageKeepCircle (source->maskObj, x, y, options->radius, "AND", PS_NOT_U8(markVal));
+        }
+
+        FILE *f = fopen ("shapes.dat", "w");
+        for (int i = 0; i < try->sources->n; i++) {
+            psF32 inPar[10];  // must be psF32 to pmPSF_FitToModel
+
+            // masked for: bad model fit, outlier in parameters
+            if (try->mask->data.U8[i] & PSFTRY_MASK_ALL) continue;
+
+            pmSource *source = try->sources->data[i];
+            psF32 *outPar = source->modelEXT->params->data.F32;
+
+            psEllipseShape shape;
+
+            shape.sx  = outPar[PM_PAR_SXX] / M_SQRT2;
+            shape.sy  = outPar[PM_PAR_SYY] / M_SQRT2;
+            shape.sxy = outPar[PM_PAR_SXY];
+
+            psEllipsePol pol = pmPSF_ModelToFit (outPar);
+            inPar[PM_PAR_E0] = pol.e0;
+            inPar[PM_PAR_E1] = pol.e1;
+            inPar[PM_PAR_E2] = pol.e2;
+            pmPSF_FitToModel (inPar, 0.1);
+
+            psEllipseAxes axes1 = psEllipseShapeToAxes (shape, 20.0);
+            psEllipseAxes axes2;
+            (void)psEllipsePolToAxes(pol, 0.1, &axes2);
+            psEllipsePol pol2 = psEllipseAxesToPol (axes1);
+
+            fprintf (f, "%3d  %7.2f %7.2f  %7.4f %7.4f %7.4f  --  %7.4f %7.4f %7.4f  :  %7.4f %7.4f %7.4f  --  %7.4f %7.4f %7.4f : %7.4f %7.4f %6.1f : %7.4f %7.4f %6.1f\n",
+                     i, outPar[PM_PAR_XPOS], outPar[PM_PAR_YPOS],
+                     outPar[PM_PAR_SXX], outPar[PM_PAR_SXY], outPar[PM_PAR_SYY],
+                     pol.e0, pol.e1, pol.e2,
+                     pol2.e0, pol2.e1, pol2.e2,
+                     inPar[PM_PAR_SXX], inPar[PM_PAR_SXY], inPar[PM_PAR_SYY],
+                     axes1.major, axes1.minor, axes1.theta*PM_DEG_RAD,
+                     axes2.major, axes2.minor, axes2.theta*PM_DEG_RAD
+                     );
+        }
+        fclose (f);
+
+        psphotSaveImage (NULL, readout->image,  "psfstars.fits");
+        pmSourcesWritePSFs (try->sources, "psfstars.dat");
+        pmSourcesWriteEXTs (try->sources, "extstars.dat", false);
+        // XXX need alternative output function
+        // psMetadata *psfData = pmPSFtoMetadata (NULL, try->psf);
+        // psMetadataConfigWrite (psfData, "psfmodel.dat");
+        psLogMsg ("psphot.choosePSF", PS_LOG_INFO, "wrote out psf-subtracted image, psf data, exiting\n");
+        exit (0);
+    }
+
+    // save only the best model;
+    // XXX we are not saving the fitted sources
+    // XXX do we want to keep them so we may optionally write them out?
+    pmPSF *psf = psMemIncrRefCounter(try->psf);
+    psFree (models);
+
+    if (!psphotPSFstats (readout, recipe, psf)) {
+        psError(PSPHOT_ERR_PSF, false, "cannot measure PSF shape terms");
+        psFree(options);
+        psFree(psf);
+        return NULL;
+    }
+
+    char *modelName = pmModelClassGetName (psf->type);
+    psLogMsg ("psphot.pspsf", PS_LOG_INFO, "select psf model: %f sec\n", psTimerMark ("psphot"));
+    psLogMsg ("psphot.pspsf", PS_LOG_INFO, "psf model %s, ApResid: %f +/- %f\n", modelName, psf->ApResid, psf->dApResid);
+
+    psFree (options);
+    return (psf);
+}
+
+// measure average parameters of the PSF model
+bool psphotPSFstats (pmReadout *readout, psMetadata *recipe, pmPSF *psf) {
+
+    psEllipseShape shape;
+    psEllipseAxes axes;
+
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_PTR_NON_NULL(recipe, false);
+    PS_ASSERT_PTR_NON_NULL(psf, false);
+
+    psImage *image = readout->image;
+    PS_ASSERT_PTR_NON_NULL(image, false);
+
+    // construct a normalized PSF model at this coordinate (Io = 1.0)
+    pmModel *modelPSF = pmModelFromPSFforXY (psf, 0.5*image->numCols, 0.5*image->numRows, 1.0);
+    if (modelPSF == NULL) {
+        psError(PSPHOT_ERR_PSF, false, "Failed to estimate PSF model at image centre");
+        return false;
+    }
+
+    // get the model full-width at half-max
+    double FWHM_X = 2*modelPSF->modelRadius (modelPSF->params, 0.5);
+
+    // XXX make sure this is consistent with the re-definition of PM_PAR_SXX
+    shape.sx  = modelPSF->params->data.F32[PM_PAR_SXX];
+    shape.sy  = modelPSF->params->data.F32[PM_PAR_SYY];
+    shape.sxy = modelPSF->params->data.F32[PM_PAR_SXY];
+    axes = psEllipseShapeToAxes (shape, 20.0);
+
+    double FWHM_Y = FWHM_X * (axes.minor / axes.major);
+
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "FWHM_X",   PS_META_REPLACE, "PSF FWHM Major axis", FWHM_X);
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "FWHM_Y",   PS_META_REPLACE, "PSF FWHM Minor axis", FWHM_Y);
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "ANGLE",    PS_META_REPLACE, "PSF angle",           axes.theta);
+    psMetadataAddS32 (recipe, PS_LIST_TAIL, "NPSFSTAR", PS_META_REPLACE, "Number of stars used to make PSF", psf->nPSFstars);
+    psMetadataAddBool(recipe, PS_LIST_TAIL, "PSFMODEL", PS_META_REPLACE, "Valid PSF Model?", true);
+    psFree (modelPSF);
+
+    return true;
+}
+
+// determine approximate PSF shape parameters based on the moments
+bool psphotMomentsStats (pmReadout *readout, psMetadata *recipe, psArray *sources) {
+
+    // without the PSF model, we can only rely on the source->moments
+    // as a measure of the FWHM values
+
+    int FWHM_N = 0;
+    double FWHM_X = 0.0;
+    double FWHM_Y = 0.0;
+    double FWHM_T = 0.0;
+
+    psEllipseMoments moments;
+    psEllipseAxes axes;
+
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_PTR_NON_NULL(recipe, false);
+    PS_ASSERT_PTR_NON_NULL(sources, false);
+
+    for (int i = 0; i < sources->n; i++) {
+        pmSource *source = sources->data[i];
+        if (!source) continue;
+        if (!(source->mode & PM_SOURCE_MODE_PSFSTAR)) continue;
+
+        // moments->Sx,Sy are roughly sigma_x,y
+        moments.x2 = PS_SQR(source->moments->Sx);
+        moments.y2 = PS_SQR(source->moments->Sy);
+        moments.xy = source->moments->Sxy;
+
+        // limit axis ratio < 20.0
+        axes = psEllipseMomentsToAxes (moments, 20.0);
+
+        FWHM_X += axes.major * 2.35;
+        FWHM_Y += axes.minor * 2.35;
+        FWHM_T += axes.theta;
+        FWHM_N ++;
+    }
+
+    FWHM_X /= FWHM_N;
+    FWHM_Y /= FWHM_N;
+    FWHM_T /= FWHM_N;
+
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "FWHM_X",   PS_META_REPLACE, "PSF FWHM Major axis (from moments)", FWHM_X);
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "FWHM_Y",   PS_META_REPLACE, "PSF FWHM Minor axis (from moments)", FWHM_Y);
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "ANGLE",    PS_META_REPLACE, "PSF angle",           FWHM_T);
+    psMetadataAddS32 (recipe, PS_LIST_TAIL, "NPSFSTAR", PS_META_REPLACE, "Number of stars used to make PSF", 0);
+    psMetadataAddBool(recipe, PS_LIST_TAIL, "PSFMODEL", PS_META_REPLACE, "Valid PSF Model?", false);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotCleanup.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotCleanup.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotCleanup.c	(revision 22158)
@@ -0,0 +1,36 @@
+# include "psphotStandAlone.h"
+
+void psphotCleanup (pmConfig *config) {
+
+    psFree (config);
+
+    psTimerStop ();
+    psMemCheckCorruption (stderr, true);
+    pmModelClassCleanup ();
+    psTimeFinalize ();
+    pmConceptsDone ();
+    pmConfigDone ();
+    // fprintf (stderr, "found %d leaks at %s\n", psMemCheckLeaks (0, NULL, NULL, false), "psphot");
+    fprintf (stderr, "found %d leaks at %s\n", psMemCheckLeaks (0, NULL, stdout, false), "psphot");
+    return;
+}
+
+psExit psphotGetExitStatus () {
+
+    psErrorCode err = psErrorCodeLast ();
+    switch (err) {
+      case PS_ERR_NONE:
+	return PS_EXIT_SUCCESS;
+      case PSPHOT_ERR_SYS:
+        return PS_EXIT_SYS_ERROR;
+      case PSPHOT_ERR_CONFIG:
+        return PS_EXIT_CONFIG_ERROR;
+      case PSPHOT_ERR_PROG:
+        return PS_EXIT_PROG_ERROR;
+      case PSPHOT_ERR_DATA:
+        return PS_EXIT_DATA_ERROR;
+      default:
+        return PS_EXIT_UNKNOWN_ERROR;
+    }
+    return PS_EXIT_UNKNOWN_ERROR;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotCullPeaks.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotCullPeaks.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotCullPeaks.c	(revision 22158)
@@ -0,0 +1,264 @@
+# include "psphotInternal.h"
+
+/*
+ * Cull a set of peaks contained in a psArray of pmFootprints
+ */
+psErrorCode
+psphotCullPeaks(const psImage *image,   // the image wherein lives the footprint
+                const psImage *weight,  // corresponding variance image
+                const psMetadata *recipe,
+                psArray *footprints) {  // array of pmFootprints
+    bool status = false;
+    float nsigma_delta = psMetadataLookupF32(&status, recipe, "FOOTPRINT_CULL_NSIGMA_DELTA");
+    if (!status) {
+        nsigma_delta = 0; // min.
+    }
+    float nsigma_min = psMetadataLookupF32(&status, recipe, "FOOTPRINT_CULL_NSIGMA_MIN");
+    if (!status) {
+        nsigma_min = 0;
+    }
+    const float skyStdev = psMetadataLookupF32(NULL, recipe, "SKY_STDEV");
+
+    return pmFootprintArrayCullPeaks(image, weight, footprints,
+                                     nsigma_delta, nsigma_min*skyStdev);
+}
+
+
+/*
+ * Cull an entire psArray of pmFootprints
+ * XXX drop this intermediate level function?
+ */
+psErrorCode
+pmFootprintArrayCullPeaks(const psImage *img, // the image wherein lives the footprint
+			  const psImage *weight,	// corresponding variance image
+			  psArray *footprints, // array of pmFootprints
+			  const float nsigma_delta, // how many sigma above local background a peak
+    					// needs to be to survive
+			  const float min_threshold) { // minimum permitted coll height
+    for (int i = 0; i < footprints->n; i++) {
+	pmFootprint *fp = footprints->data[i];
+	if (pmFootprintCullPeaks(img, weight, fp, nsigma_delta, min_threshold) != PS_ERR_NONE) {
+	    return psError(PS_ERR_UNKNOWN, false, "Culling pmFootprint %d", fp->id);
+	}
+    }
+    
+    return PS_ERR_NONE;
+}
+
+ /*
+  * Examine the peaks in a pmFootprint, and throw away the ones that are not sufficiently
+  * isolated.  More precisely, for each peak find the highest coll that you'd have to traverse
+  * to reach a still higher peak --- and if that coll's more than nsigma DN below your
+  * starting point, discard the peak.
+  */
+psErrorCode pmFootprintCullPeaks_OLD(const psImage *img, // the image wherein lives the footprint
+				 const psImage *weight,	// corresponding variance image
+				 pmFootprint *fp, // Footprint containing mortal peaks
+				 const float nsigma_delta, // how many sigma above local background a peak
+				 	// needs to be to survive
+				 const float min_threshold) { // minimum permitted coll height
+    assert (img != NULL); assert (img->type.type == PS_TYPE_F32);
+    assert (weight != NULL); assert (weight->type.type == PS_TYPE_F32);
+    assert (img->row0 == weight->row0 && img->col0 == weight->col0);
+    assert (fp != NULL);
+
+    if (fp->peaks == NULL || fp->peaks->n == 0) { // nothing to do
+	return PS_ERR_NONE;
+    }
+
+    psRegion subRegion;			// desired subregion; 1 larger than bounding box (grr)
+    subRegion.x0 = fp->bbox.x0; subRegion.x1 = fp->bbox.x1 + 1;
+    subRegion.y0 = fp->bbox.y0; subRegion.y1 = fp->bbox.y1 + 1;
+    const psImage *subImg = psImageSubset((psImage *)img, subRegion);
+    const psImage *subWt = psImageSubset((psImage *)weight, subRegion);
+    assert (subImg != NULL && subWt != NULL);
+    //
+    // We need a psArray of peaks brighter than the current peak.  We'll fake this
+    // by reusing the fp->peaks but lying about n.
+    //
+    // We do this for efficiency (otherwise I'd need two peaks lists), and we are
+    // rather too chummy with psArray in consequence.  But it works.
+    //
+    psArray *brightPeaks = psArrayAlloc(0);
+    psFree(brightPeaks->data);
+    brightPeaks->data = psMemIncrRefCounter(fp->peaks->data);// use the data from fp->peaks
+    //
+    // The brightest peak is always safe; go through other peaks trying to cull them
+    //
+    for (int i = 1; i < fp->peaks->n; i++) { // n.b. fp->peaks->n can change within the loop
+	const pmPeak *peak = fp->peaks->data[i];
+	int x = peak->x - subImg->col0;
+	int y = peak->y - subImg->row0;
+	//
+	// Find the level nsigma below the peak that must separate the peak
+	// from any of its friends
+	//
+	assert (x >= 0 && x < subImg->numCols && y >= 0 && y < subImg->numRows);
+	const float stdev = sqrt(subWt->data.F32[y][x]);
+	float threshold = subImg->data.F32[y][x] - nsigma_delta*stdev;
+	if (isnan(threshold) || threshold < min_threshold) {
+#if 1	  // min_threshold is assumed to be below the detection threshold,
+	  // so all the peaks are pmFootprint, and this isn't the brightest
+	    // XXX mark peak to be dropped
+	    (void)psArrayRemoveIndex(fp->peaks, i);
+	    i--;			// we moved everything down one
+	    continue;
+#else
+#error n.b. We will be running LOTS of checks at this threshold, so only find the footprint once
+	    threshold = min_threshold;
+#endif
+	}
+
+	// XXX EAM : if stdev >= 0, i'm not sure how this can ever be true?
+	if (threshold > subImg->data.F32[y][x]) {
+	    threshold = subImg->data.F32[y][x] - 10*FLT_EPSILON;
+	}
+
+	// XXX this is a bit expensive: psImageAlloc for every peak contained in this footprint
+	// perhaps this should alloc a single ID image above and pass it in to be set.
+
+	const int peak_id = 1;		// the ID for the peak of interest
+	brightPeaks->n = i;		// only stop at a peak brighter than we are
+
+	// XXX optionally use the faster pmFootprintsFind if the subimage size is large (eg, M31)
+
+	pmFootprint *peakFootprint = pmFootprintsFindAtPoint(subImg, threshold, brightPeaks, peak->y, peak->x);
+	brightPeaks->n = 0;		// don't double free
+	psImage *idImg = pmSetFootprintID(NULL, peakFootprint, peak_id);
+	psFree(peakFootprint);
+
+	// Check if any of the previous (brighter) peaks are within the footprint of this peak
+	// If so, the current peak is bogus; drop it.
+	int j;
+	for (j = 0; j < i; j++) {
+	    const pmPeak *peak2 = fp->peaks->data[j];
+	    int x2 = peak2->x - subImg->col0;
+	    int y2 = peak2->y - subImg->row0;
+	    const int peak2_id = idImg->data.S32[y2][x2]; // the ID for some other peak
+
+	    if (peak2_id == peak_id) {	// There's a brighter peak within the footprint above
+		;			// threshold; so cull our initial peak
+		(void)psArrayRemoveIndex(fp->peaks, i);
+		i--;			// we moved everything down one
+		break;
+	    }
+	}
+	if (j == i) {
+	    j++;
+	}
+
+	psFree(idImg);
+    }
+
+    brightPeaks->n = 0; psFree(brightPeaks);
+    psFree((psImage *)subImg);
+    psFree((psImage *)subWt);
+
+    return PS_ERR_NONE;
+}
+
+ /*
+  * Examine the peaks in a pmFootprint, and throw away the ones that are not sufficiently
+  * isolated.  More precisely, for each peak find the highest coll that you'd have to traverse
+  * to reach a still higher peak --- and if that coll's more than nsigma DN below your
+  * starting point, discard the peak.
+  */
+
+# define IN_PEAK 1 
+psErrorCode pmFootprintCullPeaks(const psImage *img, // the image wherein lives the footprint
+				 const psImage *weight,	// corresponding variance image
+				 pmFootprint *fp, // Footprint containing mortal peaks
+				 const float nsigma_delta, // how many sigma above local background a peak
+				 // needs to be to survive
+				 const float min_threshold) { // minimum permitted coll height
+    assert (img != NULL); assert (img->type.type == PS_TYPE_F32);
+    assert (weight != NULL); assert (weight->type.type == PS_TYPE_F32);
+    assert (img->row0 == weight->row0 && img->col0 == weight->col0);
+    assert (fp != NULL);
+
+    if (fp->peaks == NULL || fp->peaks->n == 0) { // nothing to do
+	return PS_ERR_NONE;
+    }
+
+    psRegion subRegion;			// desired subregion; 1 larger than bounding box (grr)
+    subRegion.x0 = fp->bbox.x0; subRegion.x1 = fp->bbox.x1 + 1;
+    subRegion.y0 = fp->bbox.y0; subRegion.y1 = fp->bbox.y1 + 1;
+
+    psImage *subImg = psImageSubset((psImage *)img, subRegion);
+    psImage *subWt = psImageSubset((psImage *)weight, subRegion);
+    assert (subImg != NULL && subWt != NULL);
+
+    psImage *idImg = psImageAlloc(subImg->numCols, subImg->numRows, PS_TYPE_S32);
+
+    // We need a psArray of peaks brighter than the current peak.  
+    // We reject peaks which either:
+    // 1) are below the local threshold
+    // 2) have a brighter peak within their threshold
+
+    // allocate the full-sized array.  if the final array is much smaller, we can realloc
+    // at that point.
+    psArray *brightPeaks = psArrayAllocEmpty(fp->peaks->n);
+    psArrayAdd (brightPeaks, 128, fp->peaks->data[0]);
+
+    // The brightest peak is always safe; go through other peaks trying to cull them
+    for (int i = 1; i < fp->peaks->n; i++) { // n.b. fp->peaks->n can change within the loop
+	const pmPeak *peak = fp->peaks->data[i];
+	int x = peak->x - subImg->col0;
+	int y = peak->y - subImg->row0;
+	//
+	// Find the level nsigma below the peak that must separate the peak
+	// from any of its friends
+	//
+	assert (x >= 0 && x < subImg->numCols && y >= 0 && y < subImg->numRows);
+	const float stdev = sqrt(subWt->data.F32[y][x]);
+	float threshold = subImg->data.F32[y][x] - nsigma_delta*stdev;
+	if (isnan(threshold) || threshold < min_threshold) {
+	    // min_threshold is assumed to be below the detection threshold,
+	    // so all the peaks are pmFootprint, and this isn't the brightest
+	    continue;
+	}
+
+	// XXX EAM : if stdev >= 0, i'm not sure how this can ever be true?
+	if (threshold > subImg->data.F32[y][x]) {
+	    threshold = subImg->data.F32[y][x] - 10*FLT_EPSILON;
+	}
+
+	// XXX this is a bit expensive: psImageAlloc for every peak contained in this footprint
+	// perhaps this should alloc a single ID image above and pass it in to be set.
+
+	// XXX optionally use the faster pmFootprintsFind if the subimage size is large (eg, M31)
+
+	// at this point brightPeaks only has the peaks brighter than the current
+	pmFootprint *peakFootprint = pmFootprintsFindAtPoint(subImg, threshold, brightPeaks, peak->y, peak->x);
+
+	// XXX need to supply the image here
+	// we set the IDs to either 1 (in peak) or 0 (not in peak)
+	pmSetFootprintID (idImg, peakFootprint, IN_PEAK);
+	psFree(peakFootprint);
+
+	// Check if any of the previous (brighter) peaks are within the footprint of this peak
+	// If so, the current peak is bogus; drop it.
+	bool keep = true;
+	for (int j = 0; keep && (j < brightPeaks->n); j++) {
+	    const pmPeak *peak2 = fp->peaks->data[j];
+	    int x2 = peak2->x - subImg->col0;
+	    int y2 = peak2->y - subImg->row0;
+	    if (idImg->data.S32[y2][x2] == IN_PEAK) 
+		// There's a brighter peak within the footprint above threshold; so cull our initial peak
+		keep = false;
+	}
+	if (!keep) continue;
+
+	psArrayAdd (brightPeaks, 128, fp->peaks->data[i]);
+    }
+
+    psFree (fp->peaks);
+    fp->peaks = brightPeaks;
+
+    psFree(idImg);
+    psFree(subImg);
+    psFree(subWt);
+
+    return PS_ERR_NONE;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotDeblendSatstars.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotDeblendSatstars.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotDeblendSatstars.c	(revision 22158)
@@ -0,0 +1,159 @@
+# include "psphotInternal.h"
+
+bool psphotDeblendSatstars (psArray *sources, psMetadata *recipe) {
+
+    int N;
+    pmSource *source;
+
+    psTimerStart ("psphot");
+
+    int Nblend = 0;
+    float SAT_TEST_LEVEL = 50000;
+    float SAT_MIN_RADIUS = 5.0;
+
+    // we need sources spatially-sorted to find overlaps
+    sources = psArraySort (sources, pmSourceSortByY);
+
+    // source analysis is done in peak order (brightest first)
+    // we use an index for this so the spatial sorting is kept
+    psVector *SN = psVectorAlloc (sources->n, PS_DATA_F32);
+    for (int i = 0; i < SN->n; i++) {
+        source = sources->data[i];
+        SN->data.F32[i] = source->peak->SN;
+    }
+    psVector *index = psVectorSortIndex (NULL, SN);
+    // this results in an index of increasing SN
+
+    // examine sources in decreasing SN order
+    for (int i = sources->n - 1; i >= 0; i--) {
+        N = index->data.U32[i];
+        source = sources->data[N];
+
+        // XXX filter? if (source->mode & PM_SOURCE_MODE_SATSTAR) continue;
+        if (source->mode & PM_SOURCE_MODE_BLEND) continue;
+        if (source->peak->flux < SAT_TEST_LEVEL) continue;
+
+	// save these for reference below
+	int xPeak = source->peak->x;
+	int yPeak = source->peak->y;
+
+        // generate a basic contour (set of x,y coordinates at-or-below flux level)
+        psArray *contour = pmSourceContour (source->pixels, xPeak, yPeak, SAT_TEST_LEVEL);
+        if (contour == NULL) continue;
+
+	// contour consists of a set of X,Y coords giving the boundary
+	psVector *xVec = contour->data[0];
+	psVector *yVec = contour->data[1];
+
+	// XXX should we filter based on the number of pixels in the contour?
+
+	// find the center of the contour (let's just use mid[x,y])
+	int xMin = xVec->data.F32[0];
+	int xMax = xVec->data.F32[0];
+	int yMin = yVec->data.F32[0];
+	int yMax = yVec->data.F32[0];
+	for (int j = 0; j < xVec->n; j++) {
+	    xMin = PS_MIN (xMin, xVec->data.F32[j]);
+	    xMax = PS_MAX (xMax, xVec->data.F32[j]);
+	    yMin = PS_MIN (yMin, yVec->data.F32[j]);
+	    yMax = PS_MAX (yMax, yVec->data.F32[j]);
+	}	
+	int xCenter = 0.5*(xMin + xMax);
+	int yCenter = 0.5*(yMin + yMax);
+	psFree (contour);
+
+	// reset the peak for this source to the value of the center pixel
+	source->peak->x = xCenter;
+	source->peak->y = yCenter;
+	source->peak->xf = xCenter;
+	source->peak->yf = yCenter;
+	
+	// temporary array for overlapping objects we find
+        psArray *overlap = psArrayAllocEmpty (100);
+
+        // search backwards for overlapping sources
+        for (int j = N - 1; j >= 0; j--) {
+            pmSource *testSource = sources->data[j];
+            if (testSource->peak->x <  source->pixels->col0) continue;
+            if (testSource->peak->x >= source->pixels->col0 + source->pixels->numCols) continue;
+            if (testSource->peak->y <  source->pixels->row0) break;
+            if (testSource->peak->y >= source->pixels->row0 + source->pixels->numRows) {
+                fprintf (stderr, "warning: invalid condition\n");
+                continue;
+            }
+            psArrayAdd (overlap, 100, testSource);
+        }
+
+        // search forwards for overlapping sources
+        for (int j = N + 1; j < sources->n; j++) {
+            pmSource *testSource = sources->data[j];
+            if (testSource->peak->x <  source->pixels->col0) continue;
+            if (testSource->peak->x >= source->pixels->col0 + source->pixels->numCols) continue;
+            if (testSource->peak->y <  source->pixels->row0) {
+                fprintf (stderr, "warning: invalid condition\n");
+                continue;
+            }
+            if (testSource->peak->y >= source->pixels->row0 + source->pixels->numRows) break;
+            psArrayAdd (overlap, 100, testSource);
+        }
+
+        if (overlap->n == 0) {
+            psFree (overlap);
+            continue;
+        }
+
+	// now find the contour which is at 0.5*SAT_TEST_LEVEL (xPeak, yPeak is valid high pixel)
+        contour = pmSourceContour (source->pixels, xPeak, yPeak, 0.5*SAT_TEST_LEVEL);
+        if (contour == NULL) {
+	    psFree (overlap);
+	    continue; 
+	}
+	
+	// any peaks within this contour should be dropped (mark as blend, drop after loop is done)
+	// also drop any peaks which are too close to this peal
+        psVector *xv = contour->data[0];
+        psVector *yv = contour->data[1];
+        for (int k = 0; k < overlap->n; k++) {
+            pmSource *testSource = overlap->data[k];
+	    float radius = hypot((testSource->peak->x - xCenter), (testSource->peak->y - yCenter));
+	    if (radius < SAT_MIN_RADIUS) {
+                testSource->mode |= PM_SOURCE_MODE_BLEND;
+                Nblend ++;
+		continue;
+	    }
+            for (int j = 0; j < xv->n; j+=2) {
+                if (fabs(yv->data.F32[j] - testSource->peak->y) > 0.5) continue;
+                if (xv->data.F32[j+0] > testSource->peak->x) break;
+                if (xv->data.F32[j+1] < testSource->peak->x) break;
+                testSource->mode |= PM_SOURCE_MODE_BLEND;
+                Nblend ++;
+                j = xv->n; // skip rest of contour
+            }
+        }
+        psFree (overlap);
+        psFree (contour);
+    }
+
+    // drop the sources marked as BLEND
+    for (int i = 0; i < sources->n;) {
+	pmSource *source = sources->data[i];
+
+        if (!(source->mode & PM_SOURCE_MODE_BLEND)) {
+	    i++;
+	    continue;
+	}
+
+	// shuffle the remaining sources forward
+	for (int j = i; j < sources->n - 1; j++) {
+	    sources->data[j] = sources->data[j+1];
+	}
+	psFree (source);
+	sources->n --;
+    }
+
+    psFree (SN);
+    psFree (index);
+
+    psLogMsg ("psphot", PS_LOG_INFO, "found %d satstar blend peaks, leaving %ld sources: %f sec\n", Nblend, sources->n, psTimerMark ("psphot"));
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotDefineFiles.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotDefineFiles.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotDefineFiles.c	(revision 22158)
@@ -0,0 +1,134 @@
+# include "psphotInternal.h"
+
+// XXX we need to be able to distinguish several cases:
+// 1) the particular output data was not requested
+// 2) the particular output data was requested but was not generated (skipped)
+// 3) the particular output data was requested but was not generated (for valid failure)
+// 4) the particular output data was requested but was not generated (surprising failure)
+
+// define the needed / desired I/O files
+bool psphotDefineFiles (pmConfig *config, pmFPAfile *input) {
+
+    bool status = false;
+
+    // select recipe options supplied on command line
+    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
+
+    // the output sources are carried on the input->fpa structures
+    pmFPAfile *outsources = pmFPAfileDefineOutputFromFile (config, input, "PSPHOT.OUTPUT");
+    if (!outsources) {
+        psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for PSPHOT.OUTPUT");
+        return false;
+    }
+    outsources->save = true;
+
+    // if we are choosing not to save the output detections, mark this file inactive so it will
+    // not be written, but will keep the detections in memory for other functions (eg, astrometry)
+    if (!psMetadataLookupBool (NULL, recipe, "SAVE.OUTPUT")) {
+        pmFPAfileActivate (config->files, false, "PSPHOT.OUTPUT");
+        outsources->save = false;
+    }
+
+    // optionally save the residual image
+    if (psMetadataLookupBool(NULL, recipe, "SAVE.RESID")) {
+        pmFPAfile *output = pmFPAfileDefineOutputFromFile (config, input, "PSPHOT.RESID");
+        if (!output) {
+            psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for PSPHOT.RESID");
+            return false;
+        }
+        output->save = true;
+    }
+    // optionally save the background model (small FITS image)
+    if (psMetadataLookupBool(NULL, recipe, "SAVE.BACKMDL")) {
+        int DX = psMetadataLookupS32 (&status, recipe, "BACKGROUND.XBIN");
+        int DY = psMetadataLookupS32 (&status, recipe, "BACKGROUND.YBIN");
+        pmFPAfile *output = pmFPAfileDefineFromFile (config, input, DX, DY, "PSPHOT.BACKMDL");
+        if (!output) {
+            psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for PSPHOT.BACKMDL");
+            return false;
+        }
+        output->save = true;
+    }
+    // optionally save the background model's standard deviation (small FITS image)
+    if (psMetadataLookupBool(NULL, recipe, "SAVE.BACKMDL.STDEV")) {
+        int DX = psMetadataLookupS32 (&status, recipe, "BACKGROUND.XBIN");
+        int DY = psMetadataLookupS32 (&status, recipe, "BACKGROUND.YBIN");
+        pmFPAfile *output = pmFPAfileDefineFromFile (config, input, DX, DY, "PSPHOT.BACKMDL.STDEV");
+        if (!output) {
+            psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for PSPHOT.BACKMDL.STDEV");
+            return false;
+        }
+        output->save = true;
+    }
+    // optionally save the full background image
+    if (psMetadataLookupBool(NULL, recipe, "SAVE.BACKGND")) {
+        pmFPAfile *output = pmFPAfileDefineFromFile (config, input,  1,  1, "PSPHOT.BACKGND");
+        if (!output) {
+            psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for PSPHOT.BACKGND");
+            return false;
+        }
+        output->save = true;
+    }
+    // optionally save the background-subtracted image
+    if (psMetadataLookupBool(NULL, recipe, "SAVE.BACKSUB")) {
+        pmFPAfile *output = pmFPAfileDefineFromFile (config, input,  1,  1, "PSPHOT.BACKSUB");
+        if (!output) {
+            psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for PSPHOT.");
+            return false;
+        }
+        output->save = true;
+    }
+    // optionally save the PSF Model
+    if (psMetadataLookupBool(NULL, recipe, "SAVE.PSF")) {
+        pmFPAfile *output = pmFPAfileDefineOutputFromFile (config, input, "PSPHOT.PSF.SAVE");
+        if (!output) {
+            psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for PSPHOT.PSF.SAVE");
+            return false;
+        }
+        output->save = true;
+    }
+
+    // optionally save output plots
+    // allow specific plots only
+    if (psMetadataLookupBool(NULL, recipe, "SAVE.PLOTS")) {
+        pmFPAfile *output = NULL;
+        output = pmFPAfileDefineOutputFromFile (config, input, "SOURCE.PLOT.MOMENTS");
+        if (!output) {
+            psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for SOURCE.PLOT.MOMENTS");
+            return false;
+        }
+        output->save = true;
+        output = pmFPAfileDefineOutputFromFile (config, input, "SOURCE.PLOT.PSFMODEL");
+        if (!output) {
+            psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for SOURCE.PLOT.PSFMODEL");
+            return false;
+        }
+        output->save = true;
+        output = pmFPAfileDefineOutputFromFile (config, input, "SOURCE.PLOT.APRESID");
+        if (!output) {
+            psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for SOURCE.PLOT.APRESID");
+            return false;
+        }
+        output->save = true;
+    }
+
+    if (psMetadataLookupPtr(NULL, config->arguments, "SRC")) {
+        if (!pmFPAfileDefineFromArgs (&status, config, "PSPHOT.INPUT.CMF", "SRC")) {
+            psError(PSPHOT_ERR_CONFIG, false, "Failed to find/build PSPHOT.INPUT.CMF");
+            return status;
+        }
+    }
+
+    if (psMetadataLookupPtr(NULL, config->arguments, "PSPHOT.PSF")) {
+        pmFPAfileBindFromArgs(&status, input, config, "PSPHOT.PSF.LOAD", "PSPHOT.PSF");
+        if (!status) {
+            psError(PSPHOT_ERR_CONFIG, false, "Failed to find/build PSPHOT.PSF.LOAD");
+            return status;
+        }
+    }
+
+    // XXX add in example PSF image thumbnails
+    // pmFPAfileConstruct (config->files, format, config->camera, "PSPHOT.PSF_SAMPLE");
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotDiagnosticPlots.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotDiagnosticPlots.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotDiagnosticPlots.c	(revision 22158)
@@ -0,0 +1,189 @@
+# include "psphotInternal.h"
+
+# if (HAVE_KAPA)
+
+static int kapa_fd = -1;
+
+int psphotKapaOpen ()
+{
+    char kapa[64];
+
+    strcpy (kapa, "kapa");
+
+    if (kapa_fd == -1) {
+        kapa_fd = KapaOpenNamedSocket (kapa, "psphot");
+    }
+    return kapa_fd;
+}
+
+bool psphotKapaClose ()
+{
+
+    if (kapa_fd == -1)
+        return true;
+    KapaClose (kapa_fd);
+    kapa_fd = -1;
+    return true;
+}
+
+bool psphotImageBackgroundCellHistogram (psVector *values, float mean, float sigma, int ix, int iy)
+{
+
+    KapaSection section;
+    Graphdata graphdata;
+
+    int kapa = pmKapaOpen (true);
+    if (kapa == -1) {
+        psError(PS_ERR_UNKNOWN, true, "failure to open kapa");
+        return false;
+    }
+
+    psStats *stats = psStatsAlloc (PS_STAT_MAX | PS_STAT_MIN);
+    psVectorStats (stats, values, NULL, NULL, 0);
+
+    psHistogram *histogram = psHistogramAlloc (stats->min, stats->max, 1000);
+    psVectorHistogram (histogram, values, NULL, NULL, 0);
+
+    KapaInitGraph (&graphdata);
+    KapaClearPlots (kapa);
+
+    // plot 1 is the full range
+    section.x  = 0.0;
+    section.y  = 0.0;
+    section.dx = 1.0;
+    section.dy = 0.5;
+    section.name = strcreate ("bottom");
+    KapaSetSection (kapa, &section);
+    free (section.name);
+
+    // set limits based on data values
+    graphdata.xmin = stats->min;
+    graphdata.xmax = stats->max;
+
+    psStatsInit (stats);
+    stats->options = PS_STAT_MAX | PS_STAT_MIN;
+    psVectorStats (stats, histogram->nums, NULL, NULL, 0);
+
+    // scale the plot to hold the histogram
+    graphdata.ymin = stats->min - 0.05*(stats->max - stats->min);
+    graphdata.ymax = stats->max + 0.05*(stats->max - stats->min);
+
+    KapaSetLimits (kapa, &graphdata);
+    KapaSetFont (kapa, "helvetica", 14);
+    KapaBox (kapa, &graphdata);
+
+    graphdata.color = KapaColorByName ("black");
+    graphdata.ptype = 0;
+    graphdata.size = 0.5;
+    graphdata.style = 1;
+    KapaPrepPlot (kapa, histogram->nums->n, &graphdata);
+    KapaPlotVector (kapa, histogram->nums->n, histogram->bounds->data.F32, "x");
+    KapaPlotVector (kapa, histogram->nums->n, histogram->nums->data.F32, "y");
+    psFree (histogram);
+
+    // plot 2 is the +/- 10 sigma
+    section.x  = 0.0;
+    section.y  = 0.5;
+    section.dx = 1.0;
+    section.dy = 0.5;
+    section.name = strcreate ("top");
+    KapaSetSection (kapa, &section);
+    free (section.name);
+
+    // +/- 10 sigma
+    graphdata.xmin = mean - 10.0*sigma;
+    graphdata.xmax = mean + 10.0*sigma;
+
+    histogram = psHistogramAlloc (graphdata.xmin, graphdata.xmax, 100);
+    psVectorHistogram (histogram, values, NULL, NULL, 0);
+
+    psStatsInit (stats);
+    stats->options = PS_STAT_MAX | PS_STAT_MIN;
+    psVectorStats (stats, histogram->nums, NULL, NULL, 0);
+
+    // scale the plot to hold the histogram
+    graphdata.ymin = stats->min - 0.05*(stats->max - stats->min);
+    graphdata.ymax = stats->max + 0.05*(stats->max - stats->min);
+
+    KapaSetLimits (kapa, &graphdata);
+    KapaSetFont (kapa, "helvetica", 14);
+    KapaBox (kapa, &graphdata);
+
+    graphdata.color = KapaColorByName ("black");
+    graphdata.ptype = 0;
+    graphdata.size = 0.5;
+    graphdata.style = 1;
+    KapaPrepPlot (kapa, histogram->nums->n, &graphdata);
+    KapaPlotVector (kapa, histogram->nums->n, histogram->bounds->data.F32, "x");
+    KapaPlotVector (kapa, histogram->nums->n, histogram->nums->data.F32, "y");
+
+    char line[128];
+    sprintf (line, "sky: %f +/- %f, cell %d,%d", mean, sigma, ix, iy);
+    KapaSendLabel (kapa, line, KAPA_LABEL_XP);
+
+    // pause until user types 'return'
+    fprintf (stdout, "press return");
+    fgets (line, 64, stdin);
+
+    psFree (stats);
+    psFree (histogram);
+
+    return true;
+}
+
+bool psphotDiagnosticPlots (pmConfig *config, char *name, ...) {
+
+    va_list argPtr;
+    bool status;
+
+    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
+    assert (recipe);
+
+    psMetadata *plots = psMetadataLookupPtr (&status, recipe, "DIAGNOSTIC.PLOTS");
+    assert (plots);
+
+    // do we want the requested plot?
+    if (!psMetadataLookupBool (&status, plots, name)) return false;
+
+    // Get the variable list parameters to pass to allocation function
+    va_start(argPtr, name);
+
+    if (!strcmp(name, "IMAGE.BACKGROUND.CELL.HISTOGRAM")) {
+
+        int ix = va_arg(argPtr, psS32);
+        int iy = va_arg(argPtr, psS32);
+        float mean  = va_arg(argPtr, double);
+        float sigma = va_arg(argPtr, double);
+        psVector *values = va_arg(argPtr, psPtr);
+
+        int xPlot = psMetadataLookupS32 (&status, plots, "IMAGE.BACKGROUND.CELL.HISTOGRAM.X");
+        assert (status);
+        int yPlot = psMetadataLookupS32 (&status, plots, "IMAGE.BACKGROUND.CELL.HISTOGRAM.Y");
+        assert (status);
+
+        bool gotX = (xPlot < 0) || (xPlot == ix);
+        bool gotY = (yPlot < 0) || (yPlot == iy);
+
+        if (gotX && gotY) {
+            psphotImageBackgroundCellHistogram (values, mean, sigma, ix, iy);
+            goto done;
+        }
+    }
+
+    // Clean up stack after variable arguement has been used
+done:
+    va_end(argPtr);
+    return true;
+}
+
+# else
+
+int psphotKapaOpen () { return -1; }
+bool psphotKapaClose () { return true; }
+bool psphotImageBackgroundCellHistogram (psVector *values, float mean, float sigma, int ix, int iy)
+{
+    return true;
+}
+bool psphotDiagnosticPlots (pmConfig *config, char *name, ...) { return true; }
+
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotErrorCodes.c.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotErrorCodes.c.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotErrorCodes.c.in	(revision 22158)
@@ -0,0 +1,25 @@
+/*
+ * The line
+    { PSPHOT_ERR_$X{ErrorCode}, "$X{ErrorDescription}"},
+ * (without the Xs)
+ * will be replaced by values from errorCodes.dat
+ */
+#include "pslib.h"
+#include "psphotErrorCodes.h"
+
+void psphotErrorRegister(void)
+{
+    static psErrorDescription errors[] = {
+       { PSPHOT_ERR_BASE, "First value we use; lower values belong to psLib" },
+       { PSPHOT_ERR_${ErrorCode}, "${ErrorDescription}"},
+    };
+    static int nerror = PSPHOT_ERR_NERROR - PSPHOT_ERR_BASE; // number of values in enum
+
+    for (int i = 0; i < nerror; i++) {
+       psErrorDescription *tmp = psAlloc(sizeof(psErrorDescription));
+       *tmp = errors[i];
+       psErrorRegister(tmp, 1);
+       psFree(tmp);			/* it's on the internal list */
+    }
+    nerror = 0;			                // don't register more than once
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotErrorCodes.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotErrorCodes.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotErrorCodes.dat	(revision 22158)
@@ -0,0 +1,17 @@
+#
+# This file is used to generate psphotErrorClasses.h
+#
+UNKNOWN			Unknown PM error code
+NOT_IMPLEMENTED		Desired feature is not yet implemented
+FITS			Problem in FITS I/O
+FITS_WCS		Error interpreting FITS WCS information
+PHOTOM			Problem in photometry
+PSF			Problem in PSF
+APERTURE		Problem with aperture photometry
+SKY			Problem in sky determination
+# these errors correspond to standard exit conditions
+ARGUMENTS               Incorrect arguments
+SYS                     System error
+CONFIG                  Problem in configure files
+PROG                    Programming error
+DATA                    invalid data
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotErrorCodes.h.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotErrorCodes.h.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotErrorCodes.h.in	(revision 22158)
@@ -0,0 +1,18 @@
+#if !defined(PSPHOT_ERROR_CODES_H)
+#define PSPHOT_ERROR_CODES_H
+/*
+ * The line
+ *  PSPHOT_ERR_$X{ErrorCode},
+ * (without the X)
+ *
+ * will be replaced by values from errorCodes.dat
+ */
+typedef enum {
+    PSPHOT_ERR_BASE = 1300,
+    PSPHOT_ERR_${ErrorCode},
+    PSPHOT_ERR_NERROR
+} psphotErrorCode;
+
+void psphotErrorRegister(void);
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotEvalFLT.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotEvalFLT.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotEvalFLT.c	(revision 22158)
@@ -0,0 +1,64 @@
+# include "psphotInternal.h"
+
+bool psphotEvalEXT (pmSource *source, pmModel *model)
+{ 
+    int keep;
+
+    // do we actually have a valid EXT model?
+    if (model == NULL) {
+	source->mode &= ~PM_SOURCE_MODE_FITTED;
+	psTrace ("psphot", 5, "no model fitted?\n");
+	return false;
+    }
+
+    // was the model actually fitted?
+    if (!(model->flags & PM_MODEL_STATUS_FITTED)) {
+	source->mode &= ~PM_SOURCE_MODE_FITTED; 
+	psTrace ("psphot", 5, "no model fitted?\n");
+	return false;
+    }
+
+    // did the model fit fail for one or another reason?
+    if (model->flags & (PM_MODEL_STATUS_BADARGS | 
+			PM_MODEL_STATUS_NONCONVERGE | 
+			PM_MODEL_STATUS_OFFIMAGE)) {
+	source->mode |= PM_SOURCE_MODE_FAIL;
+	psLogMsg ("psphot", 5, "EXT fail fit\n");
+	psTrace ("psphot", 5, "EXT fail fit\n");
+
+	if (model->flags & PM_MODEL_STATUS_OFFIMAGE) {
+	  psTrace ("psphot", 5, "off image\n");
+	}
+	if (model->flags & PM_MODEL_STATUS_BADARGS) {
+	  psTrace ("psphot", 5, "bad args\n");
+	}
+	if (model->flags & PM_MODEL_STATUS_NONCONVERGE) {
+	  psTrace ("psphot", 5, "non converge\n");
+	}
+	return false;
+    }
+
+    // unless we prove otherwise, this object is extended
+    source->type = PM_SOURCE_TYPE_EXTENDED;
+
+    // the following source->mode information pertains to modelEXT:
+    source->mode |= PM_SOURCE_MODE_EXTMODEL;
+
+    // if the object has a fitted peak below 0, the fit did not converge cleanly
+    // XXX this limit is fairly arbitrary, and must be > the value is the model limits
+    if (model->params->data.F32[PM_PAR_I0] <= 0.02) {
+	source->mode |= PM_SOURCE_MODE_FAIL;
+	psTrace ("psphot", 5, "model central intensity ~ zero\n");
+	return false;
+    } 
+
+    keep = model->modelFitStatus(model);
+    if (keep) return true;
+
+    // poor-quality fit; only keep if nothing else works...
+    psLogMsg ("psphot", 5, "EXT poor fit\n");
+    psTrace ("psphot", 5, "EXT poor fit\n");
+
+    source->mode |= PM_SOURCE_MODE_POOR;
+    return false;
+}	
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotEvalPSF.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotEvalPSF.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotEvalPSF.c	(revision 22158)
@@ -0,0 +1,238 @@
+# include "psphotInternal.h"
+
+// given a pmSource which has been fitted using modelPSF, evaluate the
+// resulting fit: did the fit succeed? is this object PSF-like? is this object 
+// extended?  return status is TRUE for a valid PSF, FALSE otherwise.
+
+// identify objects consistent with PSF shape/magnitude distribution
+// we expect dparams[PM_PAR_SXX],dparams[PM_PAR_SXX] to have a scatter of:
+// sigma_x / (S/N)
+
+// any objects which is consistent with the PSF should have 
+// abs(dparams[PM_PAR_SXX]) < N * dsxLine(mag) & abs(dparams[PM_PAR_SYY]) < N * dsyLine(mag)
+// this includes a minimum buffer (DS) for the brighter objects
+
+// EAM : 2006.10.20 : I have re-defined params[PM_PAR_SXX] : it is now sqrt(2)*sigma_x, not 1/sigma_x
+
+// saturated stars should fall outside (larger), but have peaks above SATURATION
+// extended sources should be larger, cosmic rays smaller
+// we also reject objects with S/N too low or ChiSquare to high
+
+// floor for DS value 
+// XXX EAM : add to configuration?
+
+static float SATURATION;
+static float PSF_MIN_SN;
+static float PSF_MIN_DS;
+static float PSF_MAX_CHI;
+static float PSF_SHAPE_NSIGMA;
+static float PSF_DSX_MEAN;
+static float PSF_DSY_MEAN;
+static float PSF_DSX_STDEV;
+static float PSF_DSY_STDEV;
+
+bool psphotInitLimitsPSF (psMetadata *recipe, pmReadout *readout) {
+
+    bool status;
+
+    // XXX do we need to set this differently from the value used to mark saturated pixels?
+    pmCell *cell     = readout->parent;
+    SATURATION       = psMetadataLookupF32 (&status, cell->concepts, "CELL.SATURATION");
+    PSF_MIN_SN       = psMetadataLookupF32 (&status, recipe, "PSF_MIN_SN");
+    PSF_MAX_CHI      = psMetadataLookupF32 (&status, recipe, "PSF_MAX_CHI");
+    PSF_SHAPE_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_SHAPE_NSIGMA");
+    PSF_MIN_DS       = psMetadataLookupF32 (&status, recipe, "PSF_MIN_DS");
+    if (!status) PSF_MIN_DS = 0.01;
+
+    PSF_DSX_MEAN     = psMetadataLookupF32 (&status, recipe, "DSX_MEAN");
+    PSF_DSY_MEAN     = psMetadataLookupF32 (&status, recipe, "DSY_MEAN");
+    PSF_DSX_STDEV    = psMetadataLookupF32 (&status, recipe, "DSX_STDV");
+    PSF_DSY_STDEV    = psMetadataLookupF32 (&status, recipe, "DSY_STDV");
+
+    return true;
+}
+
+// examine the model->status, fit parameters, etc and decide if the model succeeded
+// set the source->type and source->mode appropriately
+bool psphotEvalPSF (pmSource *source, pmModel *model) { 
+
+    int keep;
+    float dSX, dSY, SX, SY, SN;
+    float nSx, nSy, Chi;
+
+    // do we actually have a valid PSF model?
+    if (model == NULL) {
+	source->mode &= ~PM_SOURCE_MODE_FITTED;
+	return false;
+    }
+
+    // was the model actually fitted?
+    if (!(model->flags & PM_MODEL_STATUS_FITTED)) {
+	source->mode &= ~PM_SOURCE_MODE_FITTED; 
+	if (source->mode & PM_SOURCE_MODE_SATSTAR) {
+	    psTrace ("psphot", 5, "satstar was not fitted");
+	}
+	return false;
+    }
+    // did the model fit fail for one or another reason?
+    if (model->flags & (PM_MODEL_STATUS_BADARGS | 
+			PM_MODEL_STATUS_NONCONVERGE | 
+			PM_MODEL_STATUS_OFFIMAGE)) {
+	source->mode |= PM_SOURCE_MODE_FAIL;
+	if (source->mode & PM_SOURCE_MODE_SATSTAR) {
+	    psTrace ("psphot", 5, "satstar failed fit");
+	}
+	return false;
+    }
+
+    // unless we prove otherwise, this object is a star.
+    source->type = PM_SOURCE_TYPE_STAR;
+
+    // the following source->mode information pertains to modelPSF:
+    source->mode |= PM_SOURCE_MODE_PSFMODEL;
+
+    // if the object has fitted peak above saturation, label as SATSTAR
+    // this is a valid PSF object, but ignore the other quality tests
+    // remember: fit does not use saturated pixels (masked)
+    // XXX no extended object can saturate and stay extended...
+    if (model->params->data.F32[PM_PAR_I0] >= SATURATION) {
+	if (source->mode & PM_SOURCE_MODE_PSFSTAR) {
+	    psLogMsg ("psphot", 5, "PSFSTAR marked SATSTAR\n");
+	}
+	source->mode |=  PM_SOURCE_MODE_SATSTAR;
+	return true;
+    } 
+
+    // if the object has a fitted peak below 0.02, the source is not viable
+    // perhaps the fit did not converge cleanly
+    if (model->params->data.F32[PM_PAR_I0] <= 0.02) {
+	source->mode |= PM_SOURCE_MODE_FAIL;
+	if (source->mode & PM_SOURCE_MODE_SATSTAR) {
+	    psTrace ("psphot", 5, "satstar failed fit (peak below 0)");
+	}
+	return false;
+    } 
+
+    // if the source was predicted to be a SATSTAR, but it fitted below saturation, 
+    // make a note to the user
+    if (source->mode & PM_SOURCE_MODE_SATSTAR) {
+	psLogMsg ("psphot", 5, "SATSTAR marked normal (fitted peak below saturation)\n");
+	source->mode &= ~PM_SOURCE_MODE_SATSTAR;
+    }
+
+    SN  = model->params->data.F32[PM_PAR_I0]/model->dparams->data.F32[PM_PAR_I0];
+    SX  = model->params->data.F32[PM_PAR_SXX];
+    SY  = model->params->data.F32[PM_PAR_SYY];
+    dSX = model->dparams->data.F32[PM_PAR_SXX];
+    dSY = model->dparams->data.F32[PM_PAR_SYY];
+    Chi = model->chisqNorm / model->nDOF;
+
+    // swing of sigma_x,y in sigmas
+    nSx = (dSX - PSF_DSX_MEAN) / (PSF_DSX_STDEV * PS_MAX (PSF_MIN_DS, (SX / SN)));
+    nSy = (dSY - PSF_DSY_MEAN) / (PSF_DSY_STDEV * PS_MAX (PSF_MIN_DS, (SY / SN)));
+
+    // assign PM_SOURCE_MODE_GOODSTAR to bright objects within PSF region of dparams[]
+    keep = TRUE;
+    // keep &= (fabs(nSx) < PSF_SHAPE_NSIGMA);
+    // keep &= (fabs(nSy) < PSF_SHAPE_NSIGMA);
+    keep &= (SN > PSF_MIN_SN);
+    keep &= (Chi < PSF_MAX_CHI);
+
+    if (source->mode & PM_SOURCE_MODE_SATSTAR) {
+	psTrace ("psphot", 5, "satstar fit results: %f, %f  %d :  %f %f : %f %f : %f %f\n", 
+		     model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS], keep,
+		 dSX, nSx, dSY, nSy, SN, Chi);
+    }
+
+    if (keep) {
+	if (source->mode & PM_SOURCE_MODE_PSFSTAR) {
+	    psTrace ("psphot", 7, "PSFSTAR kept (%f, %f  :  %f %f : %f %f : %f %f)\n", 
+		     model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS], dSX, nSx, dSY, nSy, SN, Chi);
+	}
+	return true;
+    }
+
+    // this source is not a star, warn if it was a PSFSTAR
+    if (source->mode & PM_SOURCE_MODE_PSFSTAR) {
+	psTrace ("psphot", 5, "PSFSTAR demoted based on fit quality   (%f, %f  :  %f %f : %f %f : %f %f)\n", 
+		  model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS], dSX, nSx, dSY, nSy, SN, Chi);
+    } else {
+	psTrace ("psphot", 5, "fails PSF fit (%f, %f  :  %f %f : %f %f : %f %f)\n", 
+		  model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS], dSX, nSx, dSY, nSy, SN, Chi);
+    }
+
+    // object appears to be small, suspected defect.  this is a weak indication for a defect: a
+    // large positive or negative swing can also come from the bright sources for which we are 
+    // more sensitive to the wings than for the faint sources.  
+    // XXX allow -NSIGMA and +NSIGMA to have different values?
+    if ((nSx <= -PSF_SHAPE_NSIGMA) || (nSy <= -PSF_SHAPE_NSIGMA)) {
+	source->type = PM_SOURCE_TYPE_DEFECT;
+	return false;
+    }
+
+    // object appears to be large, suspected extended source
+    if ((nSx >= PSF_SHAPE_NSIGMA) || (nSy >= PSF_SHAPE_NSIGMA)) {
+	source->type = PM_SOURCE_TYPE_EXTENDED;
+	return false;
+    }
+
+    // poor-quality fit; only keep if nothing else works...
+    source->mode |= PM_SOURCE_MODE_POOR;
+    return false;
+}	
+
+// examine the model->status, fit parameters, etc and decide if the model succeeded
+// set the source->type and source->mode appropriately
+bool psphotEvalDBL (pmSource *source, pmModel *model) { 
+
+    // do we actually have a valid PSF model?
+    if (model == NULL) {
+	source->mode &= ~PM_SOURCE_MODE_FITTED;
+	return false;
+    }
+
+    // was the model actually fitted?
+    if (!(model->flags & PM_MODEL_STATUS_FITTED)) {
+	source->mode &= ~PM_SOURCE_MODE_FITTED; 
+	return false;
+    }
+    // did the model fit fail for one or another reason?
+    if (model->flags & (PM_MODEL_STATUS_BADARGS | 
+			PM_MODEL_STATUS_NONCONVERGE | 
+			PM_MODEL_STATUS_OFFIMAGE)) {
+	source->mode |= PM_SOURCE_MODE_FAIL;
+	return false;
+    }
+
+    // unless we prove otherwise, this object is a star.
+    source->type = PM_SOURCE_TYPE_STAR;
+
+    // the following source->mode information pertains to modelPSF:
+    source->mode |= PM_SOURCE_MODE_PSFMODEL;
+
+    // if the object has fitted peak above saturation, label as SATSTAR
+    // this is a valid PSF object, but ignore the other quality tests
+    // remember: fit does not use saturated pixels (masked)
+    // XXX no extended object can saturate and stay extended...
+    if (model->params->data.F32[PM_PAR_I0] >= SATURATION) {
+	if (source->mode & PM_SOURCE_MODE_PSFSTAR) {
+	    psLogMsg ("psphot", 5, "PSFSTAR marked SATSTAR\n");
+	}
+	source->mode |=  PM_SOURCE_MODE_SATSTAR;
+	return true;
+    } 
+
+    // if the object has a fitted peak below 0, the fit did not converge cleanly
+    if (model->params->data.F32[PM_PAR_I0] <= 0) {
+	source->mode |= PM_SOURCE_MODE_FAIL;
+	return false;
+    } 
+
+    // if the source was predicted to be a SATSTAR, but it fitted below saturation, 
+    // make a note to the user
+    if (source->mode & PM_SOURCE_MODE_SATSTAR) {
+	psLogMsg ("psphot", 5, "SATSTAR marked normal (fitted peak below saturation)\n");
+	source->mode &= ~PM_SOURCE_MODE_SATSTAR;
+    }
+    return true;
+}	
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotExtendedSourceAnalysis.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotExtendedSourceAnalysis.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotExtendedSourceAnalysis.c	(revision 22158)
@@ -0,0 +1,131 @@
+# include "psphotInternal.h"
+
+// aperture-like measurements for extended sources
+bool psphotExtendedSourceAnalysis (pmReadout *readout, psArray *sources, psMetadata *recipe) {
+
+    bool status;
+    int Next = 0;
+    int Npetro = 0;
+    int Nisophot = 0;
+    int Nannuli = 0;
+    int Nkron = 0;
+
+    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
+    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
+    assert (maskVal);
+
+    // perform full non-linear fits / extended source analysis?
+    if (!psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANALYSIS")) {
+	psLogMsg ("psphot", PS_LOG_INFO, "skipping extended source measurements\n");
+	return true;
+    }
+
+    // option to limit analysis to a specific region
+    char *region = psMetadataLookupStr (&status, recipe, "ANALYSIS_REGION");
+    psRegion AnalysisRegion = psRegionForImage (readout->image, psRegionFromString (region));
+    if (psRegionIsNaN (AnalysisRegion)) psAbort("analysis region mis-defined");
+
+    // S/N limit to perform full non-linear fits
+    float SN_LIM = psMetadataLookupF32 (&status, recipe, "EXTENDED_SOURCE_SN_LIM");
+
+    // which extended source analyses should we perform?
+    bool doPetrosian    = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_PETROSIAN");
+    bool doIsophotal    = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ISOPHOTAL");
+    bool doAnnuli       = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANNULI");
+    bool doKron         = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_KRON");
+
+    // source analysis is done in S/N order (brightest first)
+    sources = psArraySort (sources, pmSourceSortBySN);
+
+    // XXX some init functions for the extended source recipe options?
+
+    // choose the sources of interest
+    for (int i = 0; i < sources->n; i++) {
+
+	pmSource *source = sources->data[i];
+
+	// skip PSF-like and non-astronomical objects
+	if (source->type == PM_SOURCE_TYPE_STAR) continue;
+	if (source->type == PM_SOURCE_TYPE_DEFECT) continue;
+	if (source->type == PM_SOURCE_TYPE_SATURATED) continue;
+
+	// limit selection to some SN limit
+	assert (source->peak); // how can a source not have a peak?
+	if (source->peak->SN < SN_LIM) continue;
+
+	// limit selection by analysis region
+	if (source->peak->x < AnalysisRegion.x0) continue;
+	if (source->peak->y < AnalysisRegion.y0) continue;
+	if (source->peak->x > AnalysisRegion.x1) continue;
+	if (source->peak->y > AnalysisRegion.y1) continue;
+
+	// replace object in image
+	if (source->mode & PM_SOURCE_MODE_SUBTRACTED) {
+	    pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
+	}
+	Next ++;
+
+	// if we request any of these measurements, we require the radial profile
+	if (doPetrosian || doIsophotal || doAnnuli || doKron) {
+	    if (!psphotRadialProfile (source, recipe, maskVal)) {
+		// all measurements below require the radial profile; skip them all
+		// re-subtract the object, leave local sky
+		psTrace ("psphot", 5, "failed to extract radial profile for source at %7.1f, %7.1f", source->moments->x, source->moments->y);
+		pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
+		source->mode |= PM_SOURCE_MODE_SUBTRACTED;
+		continue;
+	    }
+	}
+
+	// Isophotal Mags
+	if (doIsophotal) {
+	    if (!psphotIsophotal (source, recipe, maskVal)) {
+		psTrace ("psphot", 5, "failed to measure isophotal mags for source at %7.1f, %7.1f", source->moments->x, source->moments->y);
+	    } else {
+		psTrace ("psphot", 5, "measured isophotal mags for source at %7.1f, %7.1f", source->moments->x, source->moments->y);
+		Nisophot ++;
+	    }
+	}
+
+	// Petrosian Mags
+	if (doPetrosian) {
+	    if (!psphotPetrosian (source, recipe, maskVal)) {
+		psTrace ("psphot", 5, "measured petrosian flux & radius for source at %7.1f, %7.1f", source->moments->x, source->moments->y);
+	    } else {
+		psTrace ("psphot", 5, "measured petrosian flux & radius for source at %7.1f, %7.1f", source->moments->x, source->moments->y);
+		Npetro ++;
+	    }
+	}
+
+	// Kron Mags
+	if (doKron) {
+	    if (!psphotKron (source, recipe, maskVal)) {
+		psTrace ("psphot", 5, "failed to measure kron mags for source at %7.1f, %7.1f", source->moments->x, source->moments->y);
+	    } else {
+		psTrace ("psphot", 5, "measure kron mags for source at %7.1f, %7.1f", source->moments->x, source->moments->y);
+		Nkron ++;
+	    }
+	}
+
+	// Radial Annuli
+	if (doAnnuli) {
+	    if (!psphotAnnuli (source, recipe, maskVal)) {
+		psError(PSPHOT_ERR_UNKNOWN, false, "failure in Annuli analysis");
+		return false;
+	    } 
+	    psTrace ("psphot", 5, "measured annuli for source at %7.1f, %7.1f", source->moments->x, source->moments->y);
+	    Nannuli ++;
+	}
+
+	// re-subtract the object, leave local sky
+	pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
+	source->mode |= PM_SOURCE_MODE_SUBTRACTED;
+    }
+
+    psLogMsg ("psphot", PS_LOG_INFO, "extended source analysis: %f sec for %d objects\n", psTimerMark ("psphot"), Next);
+    psLogMsg ("psphot", PS_LOG_INFO, "  %d petrosian\n", Npetro);
+    psLogMsg ("psphot", PS_LOG_INFO, "  %d isophotal\n", Nisophot);
+    psLogMsg ("psphot", PS_LOG_INFO, "  %d annuli\n", Nannuli);
+    psLogMsg ("psphot", PS_LOG_INFO, "  %d kron\n", Nkron);
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotExtendedSourceFits.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotExtendedSourceFits.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotExtendedSourceFits.c	(revision 22158)
@@ -0,0 +1,276 @@
+# include "psphotInternal.h"
+
+// non-linear model fitting for extended sources
+bool psphotExtendedSourceFits (pmReadout *readout, psArray *sources, psMetadata *recipe) {
+
+    bool status;
+    int Next = 0;
+    int Nconvolve = 0;
+    int NconvolvePass = 0;
+    int Nplain = 0;
+    int NplainPass = 0;
+    bool savePics = false;
+
+    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
+    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
+    assert (maskVal);
+
+    psMaskType markVal = psMetadataLookupU8(&status, recipe, "MARK.PSPHOT"); // Mask value for bad pixels
+    assert (markVal);
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
+    // perform full extended source non-linear fits?
+    if (!psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_FITS")) {
+	psLogMsg ("psphot", PS_LOG_INFO, "skipping extended source measurements\n");
+	return true;
+    }
+
+    // select the collection of desired models
+    psMetadata *models = psMetadataLookupMetadata (&status, recipe, "EXTENDED_SOURCE_MODELS");
+    if (!status) {
+	psWarning ("extended source model fits requested but model model is missing (EXTENDED_SOURCE_MODELS)\n");
+	return true;
+    }
+    if (models->list->n == 0) {
+	psWarning ("extended source model fits requested but no models are specified\n");
+	return true;
+    }
+
+    // validate the model entries
+    psMetadataIterator *iter = psMetadataIteratorAlloc (models, PS_LIST_HEAD, NULL);
+    psMetadataItem *item = NULL;
+    while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
+
+      if (item->type != PS_DATA_METADATA) {
+	psAbort ("Invalid type for EXTENDED_SOURCE_MODEL entry %s, not a metadata folder", item->name);
+	// XXX we could cull the bad entries or build a validated model folder
+      }
+
+      psMetadata *model = (psMetadata *) item->data.md;
+
+      // check on the model type
+      char *modelName = psMetadataLookupStr (&status, model, "MODEL");
+      int modelType = pmModelClassGetType (modelName);
+      if (modelType < 0) {
+	psAbort ("Unknown model class for EXTENDED_SOURCE_MODEL entry %s: %s", item->name, modelName);
+      }	
+      psMetadataAddS32 (model, PS_LIST_TAIL, "MODEL_TYPE", PS_META_REPLACE, "", modelType);
+
+      // check on the SNLIM, set a float value
+      char *SNword = psMetadataLookupStr (&status, model, "SNLIM");
+      if (!status) {
+	psAbort("SNLIM not defined for extended source model %s\n", item->name);
+      }
+      float SNlim = atof (SNword);
+      psMetadataAddF32 (model, PS_LIST_TAIL, "SNLIM_VALUE", PS_META_REPLACE, "", SNlim);
+	
+      // check on the PSF-Convolution status
+      char *convolvedWord = psMetadataLookupStr (&status, model, "PSF_CONVOLVED");
+      if (!status || (strcasecmp (convolvedWord, "true") && strcasecmp (convolvedWord, "false"))) {
+	psAbort ("PSF_CONVOLVED entry invalid or missing for EXTENDED_SOURCE_MODEL entry %s", item->name);
+      }	
+      bool convolved = !strcasecmp (convolvedWord, "true");
+      psMetadataAddBool (model, PS_LIST_TAIL, "PSF_CONVOLVED_VALUE", PS_META_REPLACE, "", convolved);
+    }
+    psFree (iter);
+
+    // option to limit analysis to a specific region
+    char *region = psMetadataLookupStr (&status, recipe, "ANALYSIS_REGION");
+    psRegion AnalysisRegion = psRegionForImage (readout->image, psRegionFromString (region));
+    if (psRegionIsNaN (AnalysisRegion)) psAbort("analysis region mis-defined");
+
+    // what fraction of the PSF is used? (radius in pixels : 2 -> 5x5 box)
+    int psfSize = psMetadataLookupS32 (&status, recipe, "PCM_BOX_SIZE");
+    assert (status);
+
+    // source analysis is done in S/N order (brightest first)
+    sources = psArraySort (sources, pmSourceSortBySN);
+
+    // choose the sources of interest
+    for (int i = 0; i < sources->n; i++) {
+
+        pmSource *source = sources->data[i];
+
+        // skip PSF-like and non-astronomical objects
+        if (source->type == PM_SOURCE_TYPE_STAR) continue;
+        if (source->type == PM_SOURCE_TYPE_DEFECT) continue;
+        if (source->type == PM_SOURCE_TYPE_SATURATED) continue;
+
+        // XXX this should use peak?
+        if (source->peak->x < AnalysisRegion.x0) continue;
+        if (source->peak->y < AnalysisRegion.y0) continue;
+        if (source->peak->x > AnalysisRegion.x1) continue;
+        if (source->peak->y > AnalysisRegion.y1) continue;
+
+        // if model is NULL, we don't have a starting guess
+	// XXX use the parameters guessed from moments
+        // if (source->modelEXT == NULL) continue;
+
+        // replace object in image
+        if (source->mode & PM_SOURCE_MODE_SUBTRACTED) {
+            pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
+        }
+        Next ++;
+
+	// save the modelFlux here in case we need to subtract it (for failure)
+	psImage *modelFluxStart = psMemIncrRefCounter (source->modelFlux);
+
+	if (savePics) {
+	  psphotSaveImage (NULL, readout->image, "image.xp.fits");
+	}
+
+	// array to store the pointers to the model flux images while the models are being fitted
+	psArray *modelFluxes = psArrayAllocEmpty (4);
+    
+	// allocate the array to store the model fits
+	if (source->modelFits == NULL) {
+	    source->modelFits = psArrayAllocEmpty (4);
+	}
+
+	// loop here over the models chosen for each source (exclude by S/N)
+	psMetadataIterator *iter = psMetadataIteratorAlloc (models, PS_LIST_HEAD, NULL);
+	psMetadataItem *item = NULL;
+	while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
+
+	  // XXX this should have been forced above
+	  assert (item->type == PS_DATA_METADATA);
+	  psMetadata *model = (psMetadata *) item->data.md;
+
+	  // check the SNlim and skip model if source is too faint
+	  float SNlim = psMetadataLookupF32 (&status, model, "SNLIM_VALUE");
+	  assert (status);
+
+	  // limit selection to some SN limit
+	  assert (source->peak); // how can a source not have a peak?
+	  if (source->peak->SN < SNlim) continue;
+
+	  // check on the model type
+	  pmModelType modelType = psMetadataLookupS32 (&status, model, "MODEL_TYPE");
+	  assert (status);
+
+	  // check on the PSF-Convolution status
+	  bool convolved = psMetadataLookupBool (&status, model, "PSF_CONVOLVED_VALUE");
+	  assert (status);
+
+	  // XXX psTraceSetLevel ("psLib.math.psMinimizeLMChi2", 6);
+	  // XXX psTraceSetLevel ("psphot.psphotModelWithPSF_LMM", 6);
+
+	  // fit the model as convolved or not
+	  pmModel *modelFit = NULL;
+	  if (convolved) {
+	      modelFit = psphotPSFConvModel (readout, source, modelType, maskVal, markVal, psfSize);
+	      if (!modelFit) {
+		  psTrace ("psphot", 5, "failed to fit psf-conv model for object at %f, %f", source->moments->x, source->moments->y);
+		  continue;
+	      } 
+	      psTrace ("psphot", 4, "fit psf-conv model for %f, %f : %s chisq = %f\n", source->moments->x, source->moments->y, pmModelClassGetName (modelFit->type), modelFit->chisq);
+	      Nconvolve ++;
+	      if (!(modelFit->flags & (PM_MODEL_STATUS_BADARGS | PM_MODEL_STATUS_NONCONVERGE | PM_MODEL_STATUS_OFFIMAGE))) {
+		  NconvolvePass ++;
+	      }
+	  } else {
+	      psFree (source->modelFlux);
+	      source->modelFlux = NULL;
+	      modelFit = psphotFitEXT (readout, source, modelType, maskVal, markVal);
+	      if (!modelFit) {
+		  psTrace ("psphot", 5, "failed to fit plain model for object at %f, %f", source->moments->x, source->moments->y);
+		  continue;
+	      } 
+	      pmSourceCacheModel (source, maskVal);
+	      psTrace ("psphot", 4, "fit plain model for %f, %f : %s chisq = %f\n", source->moments->x, source->moments->y, pmModelClassGetName (modelFit->type), modelFit->chisq);
+	      Nplain ++;
+	      if (!(modelFit->flags & (PM_MODEL_STATUS_BADARGS | PM_MODEL_STATUS_NONCONVERGE | PM_MODEL_STATUS_OFFIMAGE))) {
+		  NplainPass ++;
+	      }
+	  }
+
+	  // save each of the model flux images and store the best
+	  psArrayAdd (modelFluxes, 4, source->modelFlux);
+
+	  // test for fit quality / result
+	  psArrayAdd (source->modelFits, 4, modelFit);
+
+	  psFree (modelFit);
+	}
+	psFree (iter);
+
+	// evaluate the relative quality of the models, choose one
+	float minChisq = NAN;
+	int minModel = -1;
+	for (int i = 0; i < source->modelFits->n; i++) {
+	    pmModel *model = source->modelFits->data[i];
+	    
+	    if (!(model->flags & PM_MODEL_STATUS_FITTED)) continue;
+	    
+	    if (model->flags & (PM_MODEL_STATUS_BADARGS)) continue;
+	    if (model->flags & (PM_MODEL_STATUS_NONCONVERGE)) continue;
+	    if (model->flags & (PM_MODEL_STATUS_OFFIMAGE)) continue;
+
+	    if ((minModel < 0) || (model->chisq < minChisq)) {
+		minChisq = model->chisq;
+		minModel = i;
+	    }
+	}	    
+
+	if (minModel == -1) {
+	  // re-subtract the object, leave local sky
+	  psTrace ("psphot", 5, "failed to fit extended source model to object at %f, %f", source->moments->x, source->moments->y);
+
+	  // replace original model, subtract it
+	  psFree (source->modelFlux);
+	  source->modelFlux = modelFluxStart;
+
+	  pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
+	  source->mode |= PM_SOURCE_MODE_SUBTRACTED;
+
+	  psFree (modelFluxes);
+
+	  if (savePics) {
+	    psphotSaveImage (NULL, readout->image, "image.xp.fits");
+	    char key[10];
+	    fprintf (stdout, "continue? ");
+	    fgets (key, 8, stdin);
+	    if (key[0] == 'n') {
+	      savePics = false;
+	    }
+	  }
+	  continue;
+	}	
+
+	// save the best extended model in modelEXT
+	psFree (source->modelEXT);
+	source->modelEXT = psMemIncrRefCounter (source->modelFits->data[minModel]);
+
+	// save the modelFlux for the best model
+	psFree (source->modelFlux);
+	source->modelFlux = psMemIncrRefCounter (modelFluxes->data[minModel]);
+
+        // subtract the best fit from the object, leave local sky
+        pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
+        source->mode |= PM_SOURCE_MODE_SUBTRACTED;
+
+	// the initial model flux is no longer needed
+	psFree (modelFluxStart);
+	psFree (modelFluxes);
+
+	psTrace ("psphot", 4, "best ext model for %f, %f : %s chisq = %f\n", source->moments->x, source->moments->y, pmModelClassGetName (source->modelEXT->type), source->modelEXT->chisq);
+	psTrace ("psphot", 5, "extended source model for source at %7.1f, %7.1f", source->moments->x, source->moments->y);
+
+	if (savePics) {
+	  psphotSaveImage (NULL, readout->image, "image.xm.fits");
+	  char key[10];
+	  fprintf (stdout, "continue? ");
+	  fgets (key, 8, stdin);
+	  if (key[0] == 'n') {
+	    savePics = false;
+	  }
+	}
+    }
+
+    psLogMsg ("psphot", PS_LOG_INFO, "extended source analysis: %f sec for %d objects\n", psTimerMark ("psphot"), Next);
+    psLogMsg ("psphot", PS_LOG_INFO, "  %d convolved models (%d passed)\n", Nconvolve, NconvolvePass);
+    psLogMsg ("psphot", PS_LOG_INFO, "  %d plain models (%d passed)\n", Nplain, NplainPass);
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotExtendedSources.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotExtendedSources.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotExtendedSources.c	(revision 22158)
@@ -0,0 +1,137 @@
+# include "psphot.h"
+
+bool psphotExtendedSources (pmReadout *readout, psArray *sources, psMetadata *recipe) {
+
+    bool status;
+    int Next = 0;
+    int Nconvolve = 0;
+    int Npetro = 0;
+    int Nisophot = 0;
+    int Nannuli = 0;
+    int Nkron = 0;
+
+    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
+    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
+    assert (maskVal);
+
+    // perform full non-linear fits / extended source analysis?
+    if (!psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_FITS")) {
+	psLogMsg ("psphot", PS_LOG_INFO, "skipping extended source measurements\n");
+	return true;
+    }
+
+    // option to limit analysis to a specific region
+    char *region = psMetadataLookupStr (&status, recipe, "ANALYSIS_REGION");
+    psRegion AnalysisRegion = psRegionForImage (readout->image, psRegionFromString (region));
+    if (psRegionIsNaN (AnalysisRegion)) psAbort("analysis region mis-defined");
+
+    // S/N limit to perform full non-linear fits
+    float SN_LIM = psMetadataLookupF32 (&status, recipe, "EXTENDED_SOURCE_SN_LIM");
+
+    // which extended source analyses should we perform?
+    bool doPSFConvModel = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_PSF_CONVOLVED_MODEL");
+    bool doPetrosian    = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_PETROSIAN");
+    bool doIsophotal    = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ISOPHOTAL");
+    bool doAnnuli       = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANNULI");
+    bool doKron         = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_KRON");
+
+    // source analysis is done in S/N order (brightest first)
+    sources = psArraySort (sources, pmSourceSortBySN);
+
+    // XXX some init functions for the extended source recipe options?
+
+    // choose the sources of interest
+    for (int i = 0; i < sources->n; i++) {
+
+        pmSource *source = sources->data[i];
+
+        // skip PSF-like and non-astronomical objects
+        if (source->type == PM_SOURCE_TYPE_STAR) continue;
+        if (source->type == PM_SOURCE_TYPE_DEFECT) continue;
+        if (source->type == PM_SOURCE_TYPE_SATURATED) continue;
+
+        // limit selection to some SN limit
+        assert (source->peak); // how can a source not have a peak?
+        if (source->peak->SN < SN_LIM) continue;
+
+        // XXX this should use peak?
+        if (source->peak->x < AnalysisRegion.x0) continue;
+        if (source->peak->y < AnalysisRegion.y0) continue;
+        if (source->peak->x > AnalysisRegion.x1) continue;
+        if (source->peak->y > AnalysisRegion.y1) continue;
+
+        // if model is NULL, we don't have a starting guess
+	// XXX this is probably not needed for objects where we only measure aperture-like terms
+        if (source->modelEXT == NULL) continue;
+
+        // replace object in image
+        if (source->mode & PM_SOURCE_MODE_SUBTRACTED) {
+            pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
+        }
+        Next ++;
+
+	if (doPSFConvModel && !psphotPSFConvModel (source, recipe, maskVal)) {
+	    psError(PSPHOT_ERR_UNKNOWN, false, "failure in PSF Convolved Model fit");
+	    return false;
+	} else {
+	  // XXX why am I caching the model?
+	    pmSourceCacheModel (source, maskVal); // XXX put this in the source model function?
+	    psTrace ("psphot", 5, "psf-convolved model for source at %7.1f, %7.1f", source->moments->x, source->moments->y);
+            Nconvolve ++;
+	}
+
+	// all of these below require the radial profile
+	// XXX push this as a test and call in each of the functions below?
+	// XXX this constructs a pmSourceExtendedParameters element
+	if (doPetrosian || doIsophotal || doAnnuli || doKron) {
+	  if (!psphotRadialProfile (source, recipe, maskVal)) {
+	    psError(PSPHOT_ERR_UNKNOWN, false, "failure to generate radial profile");
+	    return false;
+	  }
+	}
+
+	if (doPetrosian && !psphotPetrosian (source, recipe, maskVal)) {
+	    psError(PSPHOT_ERR_UNKNOWN, false, "failure in Petrosian analysis");
+	    return false;
+	} else {
+	    psTrace ("psphot", 5, "measured petrosian flux & radius for source at %7.1f, %7.1f", source->moments->x, source->moments->y);
+            Npetro ++;
+	}
+
+	if (doIsophotal && !psphotIsophotal (source, recipe, maskVal)) {
+	    psError(PSPHOT_ERR_UNKNOWN, false, "failure in Isophotal analysis");
+	    return false;
+	} else {
+	    psTrace ("psphot", 5, "psf-convolved model for source at %7.1f, %7.1f", source->moments->x, source->moments->y);
+            Nisophot ++;
+	}
+
+	if (doAnnuli && !psphotAnnuli (source, recipe, maskVal)) {
+	    psError(PSPHOT_ERR_UNKNOWN, false, "failure in Annuli analysis");
+	    return false;
+	} else {
+	    psTrace ("psphot", 5, "psf-convolved model for source at %7.1f, %7.1f", source->moments->x, source->moments->y);
+            Nannuli ++;
+	}
+
+	if (doKron && !psphotKron (source, recipe, maskVal)) {
+	    psError(PSPHOT_ERR_UNKNOWN, false, "failure in Kron analysis");
+	    return false;
+	} else {
+	    psTrace ("psphot", 5, "psf-convolved model for source at %7.1f, %7.1f", source->moments->x, source->moments->y);
+            Nkron ++;
+	}
+
+        // re-subtract the object, leave local sky
+        pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
+        source->mode |= PM_SOURCE_MODE_SUBTRACTED;
+    }
+
+    psLogMsg ("psphot", PS_LOG_INFO, "extended source analysis: %f sec for %d objects\n", psTimerMark ("psphot"), Next);
+    psLogMsg ("psphot", PS_LOG_INFO, "  %d convolved models\n", Nconvolve);
+    psLogMsg ("psphot", PS_LOG_INFO, "  %d petrosian\n", Npetro);
+    psLogMsg ("psphot", PS_LOG_INFO, "  %d isophotal\n", Nisophot);
+    psLogMsg ("psphot", PS_LOG_INFO, "  %d annuli\n", Nannuli);
+    psLogMsg ("psphot", PS_LOG_INFO, "  %d kron\n", Nkron);
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotFakeSources.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotFakeSources.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotFakeSources.c	(revision 22158)
@@ -0,0 +1,30 @@
+# include "psphotInternal.h"
+
+psArray *psphotFakeSources () {
+
+    // psphotUpdateHeader (header, config);
+
+    psArray *sources = psArrayAlloc (50);
+
+    for (int i = 0; i < sources->n; i++) {
+        pmSource *source = pmSourceAlloc ();
+        source->moments = pmMomentsAlloc ();
+        source->moments->x = 10;
+        source->moments->y = 10;
+        source->moments->Sx = 1;
+        source->moments->Sy = 1;
+        source->moments->Sxy = 0;
+        source->moments->Sum = 1000;
+        source->moments->Peak = 100;
+        source->moments->Sky = 10;
+        source->moments->nPixels = 10;
+
+        source->peak = pmPeakAlloc (10, 10, 0, 0);
+        source->type = PM_SOURCE_TYPE_STAR;
+
+        pmModelType modelType = pmModelClassGetType ("PS_MODEL_QGAUSS");
+        source->modelPSF = pmSourceModelGuess (source, modelType);
+        sources->data[i] = source;
+    }
+    return sources;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotFindDetections.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotFindDetections.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotFindDetections.c	(revision 22158)
@@ -0,0 +1,57 @@
+# include "psphotInternal.h"
+
+// smooth the image, search for peaks, optionally define footprints based on the peaks
+pmDetections *psphotFindDetections (pmDetections *detections, pmReadout *readout, psMetadata *recipe) {
+
+    bool status;
+    int pass;
+    float NSIGMA_PEAK = 25.0;
+    int NMAX = 0;
+
+    psTimerStart ("psphot");
+
+    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
+    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
+    assert (maskVal);
+
+    // Use the new pmFootprints approach?
+    const bool useFootprints = psMetadataLookupBool(NULL, recipe, "USE_FOOTPRINTS");
+
+    // on first pass, detections have not yet been allocated
+    if (!detections) {
+	detections = pmDetectionsAlloc();
+	pass = 1;
+        NSIGMA_PEAK = psMetadataLookupF32 (&status, recipe, "PEAKS_NSIGMA_LIMIT"); PS_ASSERT (status, NULL);
+        NMAX = psMetadataLookupS32 (&status, recipe, "PEAKS_NMAX"); PS_ASSERT (status, NULL);
+    } else {
+	pass = 2;
+        NSIGMA_PEAK = psMetadataLookupF32 (&status, recipe, "PEAKS_NSIGMA_LIMIT_2"); PS_ASSERT (status, NULL);
+	NMAX = 0; // unlimited number of peaks in final pass: allow a limit (PEAKS_NMAX_2) ?
+    }
+
+    float threshold = PS_SQR(NSIGMA_PEAK);
+
+    // move the old peaks array (if it exists) to oldPeaks 
+    // XXX generically, we should be able to call this function an arbitrary number of times
+    assert (detections->oldPeaks == NULL);
+    detections->oldPeaks = detections->peaks;
+    detections->peaks = NULL;
+
+    // generate the smoothed significance image
+    psImage *significance = psphotSignificanceImage (readout, recipe, pass, maskVal);
+
+    // detect the peaks in the significance image
+    detections->peaks = psphotFindPeaks (significance, readout, recipe, threshold, NMAX);
+    psMetadataAddF32  (recipe, PS_LIST_TAIL, "PEAK_THRESHOLD", PS_META_REPLACE, "Peak Detection Threshold", threshold);
+
+    // optionally merge peaks into footprints
+    if (useFootprints) {
+	psphotFindFootprints (detections, significance, readout, recipe, pass, maskVal);
+    }
+
+    psFree (significance);
+    return detections;
+}
+
+// if we use the footprints, the output peaks list contains both old and new peaks,
+// otherwise it only contains the new peaks.
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotFindFootprints.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotFindFootprints.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotFindFootprints.c	(revision 22158)
@@ -0,0 +1,72 @@
+# include "psphotInternal.h"
+
+bool psphotFindFootprints (pmDetections *detections, psImage *significance, pmReadout *readout, psMetadata *recipe, const int pass, psMaskType maskVal) {
+
+    bool status;
+
+    psTimerStart ("footprints");
+
+    int npixMin = psMetadataLookupS32(&status, recipe, "FOOTPRINT_NPIXMIN");
+    PS_ASSERT (status, false);
+
+    float FOOTPRINT_NSIGMA_LIMIT;
+    if (pass == 1) {
+	FOOTPRINT_NSIGMA_LIMIT = psMetadataLookupS32(&status, recipe, "FOOTPRINT_NSIGMA_LIMIT");
+    } else {
+	FOOTPRINT_NSIGMA_LIMIT = psMetadataLookupS32(&status, recipe, "FOOTPRINT_NSIGMA_LIMIT_2");
+    }
+    PS_ASSERT (status, false);
+
+    // XXX do we need to use the same threshold here as for peaks?  does it make sense for
+    // these to be different?
+
+    float threshold = PS_SQR(FOOTPRINT_NSIGMA_LIMIT);
+
+    int growRadius = 0;
+    if (pass == 1) {
+	growRadius = psMetadataLookupS32(&status, recipe, "FOOTPRINT_GROW_RADIUS");
+    } else {
+	growRadius = psMetadataLookupS32(&status, recipe, "FOOTPRINT_GROW_RADIUS_2");
+    }
+    PS_ASSERT (status, false);
+
+    // find the raw footprints & assign the peaks to those footprints 
+    psArray *footprints = pmFootprintsFind (significance, threshold, npixMin);
+    pmFootprintsAssignPeaks(footprints, detections->peaks);
+    // XXX handle the error conditions here
+
+    // footprints now owns the peaks; after culling (below), we will rebuild the peaks array
+    psFree (detections->peaks); 
+
+    psLogMsg ("psphot", PS_LOG_DETAIL, "found %ld footprints: %f sec\n", footprints->n, psTimerMark ("footprints"));
+
+    // optionally grow footprints isotropically by growRadius pixels
+    if (growRadius > 0) {
+	psArray *tmp = pmFootprintArrayGrow(footprints, growRadius);
+	psLogMsg ("psphot", PS_LOG_DETAIL, "grow footprint coverage by %d pixels, %ld footprints become %ld footprints: %f sec\n", growRadius, footprints->n, tmp->n, psTimerMark ("footprints"));
+	psFree(footprints);
+	footprints = tmp;
+    }
+
+    if (pass == 2) {
+	// merge in old peaks;
+	const int includePeaks = 0x0 | 0x2; // i.e. just from newFootprints
+	
+	// XXX EAM : still not sure I understand this: are we double-couning or undercounting peaks
+
+	psArray *mergedFootprints = pmFootprintArraysMerge(detections->footprints, footprints, includePeaks);
+	psLogMsg ("psphot", PS_LOG_DETAIL, "merged %ld new footprints with %ld existing ones: %f sec\n", footprints->n, detections->footprints->n, psTimerMark ("footprints"));
+
+	psFree(footprints);
+	psFree(detections->footprints);
+	detections->footprints = mergedFootprints;
+    } else {
+	detections->footprints = footprints;
+    }
+
+    psphotCullPeaks(readout->image, readout->weight, recipe, detections->footprints);
+    detections->peaks = pmFootprintArrayToPeaks(detections->footprints);
+    psLogMsg ("psphot", PS_LOG_INFO, "%ld peaks, %ld total footprints: %f sec\n", detections->peaks->n, detections->footprints->n, psTimerMark ("footprints"));
+
+    return detections;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotFindPeaks.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotFindPeaks.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotFindPeaks.c	(revision 22158)
@@ -0,0 +1,54 @@
+# include "psphotInternal.h"
+
+// Find peaks in the significance image above a threshold significance level.  The significance
+// image must be constructed to represent (S/N)^2.  If nMax is non-zero, only return a maximum
+// of nMax peaks
+psArray *psphotFindPeaks (psImage *significance, pmReadout *readout, psMetadata *recipe, const float threshold, const int nMax) {
+
+    bool status = false;
+
+    psTimerStart ("peaks");
+
+    // find the peaks in the smoothed image
+    psArray *peaks = pmPeaksInImage (significance, threshold);
+    if (peaks == NULL) {
+	// XXX should we be sending back an empty array instead of NULL?
+        // XXX this may also be due to a programming or config error
+        // XXX do we need to set something in the readout->analysis to indicate that
+        // we tried and failed to find peaks (something in the header data)
+        psError(PSPHOT_ERR_DATA, false, "no peaks found in this image");
+        return false;
+    }
+
+    // correct the peak values to S/N = sqrt(significance)
+    // get the peak flux from the unsmoothed image
+    // the peak pixel coords are guaranteed to be on the image
+    int row0 = readout->image->row0;
+    int col0 = readout->image->col0;
+    for (int i = 0; i < peaks->n; i++) {
+        pmPeak *peak = peaks->data[i];
+        peak->SN = sqrt(peak->value);
+        peak->flux = readout->image->data.F32[peak->y-row0][peak->x-col0];
+    }
+
+    // limit the total number of returned peaks as specified
+    psArraySort (peaks, pmPeakSortBySN);
+    if (nMax && (peaks->n > nMax)) {
+	psArray *tmpPeaks = psArrayAllocEmpty (nMax);
+	for (int i = 0; i < nMax; i++) {
+	    psArrayAdd (tmpPeaks, 100, peaks->data[i]);
+	}
+	psFree (peaks);
+	peaks = tmpPeaks;
+    }
+
+    // optional dump of all peak data 
+    char *output = psMetadataLookupStr (&status, recipe, "PEAKS_OUTPUT_FILE");
+    if (output && strcasecmp (output, "NONE")) {
+        pmPeaksWriteText (peaks, output);
+    }
+    psLogMsg ("psphot", PS_LOG_INFO, "%ld peaks: %f sec\n", peaks->n, psTimerMark ("peaks"));
+
+    return peaks;
+
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotFitSet.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotFitSet.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotFitSet.c	(revision 22158)
@@ -0,0 +1,48 @@
+# include "psphotInternal.h"
+
+// This is only used by psphotModelTest.c
+bool psphotFitSet (pmSource *source, pmModel *oneModel, char *fitset, pmSourceFitMode mode, psMaskType maskVal) {
+
+    double x, y, Io;
+
+    FILE *f = fopen (fitset, "r");
+    if (f == NULL) return false;
+
+    psArray *modelSet = psArrayAllocEmpty (16);
+
+    while (fscanf (f, "%lf %lf %lf", &x, &y, &Io) == 3) {
+        pmModel *model = pmModelAlloc (oneModel->type);
+
+        for (psS32 i = 0; i < model->params->n; i++) {
+            model->params->data.F32[i] = oneModel->params->data.F32[i];
+            model->dparams->data.F32[i] = oneModel->dparams->data.F32[i];
+        }
+        model->params->data.F32[1] = Io;
+        model->params->data.F32[2] = x;
+        model->params->data.F32[3] = y;
+        psArrayAdd (modelSet, 16, model);
+    }
+
+    // XXX pmSourceFitSet must cache the modelFlux?
+    pmSourceFitSet (source, modelSet, mode, maskVal);
+
+    // write out positive object
+    psphotSaveImage (NULL, source->pixels, "object.fits");
+
+    // subtract object, leave local sky
+    for (int i = 0; i < modelSet->n; i++) {
+        pmModel *model = modelSet->data[i];
+        pmModelSub (source->pixels, source->maskObj, model, PM_MODEL_OP_FULL, maskVal);
+
+        fprintf (stderr, "output parameters (obj %d):\n", i);
+        for (int n = 0; n < model->params->n; n++) {
+            fprintf (stderr, "%d : %f\n", n, model->params->data.F32[n]);
+        }
+    }
+
+    // write out
+    psphotSaveImage (NULL, source->pixels, "resid.fits");
+    psphotSaveImage (NULL, source->maskObj, "mask.fits");
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotFitSourcesLinear.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotFitSourcesLinear.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotFitSourcesLinear.c	(revision 22158)
@@ -0,0 +1,309 @@
+# include "psphotInternal.h"
+
+// fit flux (and optionally sky model) to all reasonable sources
+// with the linear fitting process.  sources must have an associated
+// model with selected pixels, and the fit radius must be defined
+
+// given the set of sources, each of which points to the pixels in the
+// science image, we construct a set of simulated sources with their own pixels.
+// these are used to determine the simultaneous linear fit of fluxes.
+// the analysis is performed wrt the simulated pixel values
+
+static bool SetBorderMatrixElements (psSparseBorder *border, pmReadout *readout, psArray *sources, bool constant_weights, int SKY_FIT_ORDER, psMaskType markVal);
+
+bool psphotFitSourcesLinear (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf, bool final) {
+
+    bool status;
+    float x;
+    float y;
+    float f;
+    // float r;
+
+    psTimerStart ("psphot");
+
+    // bit-masks to test for good/bad pixels
+    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT");
+    assert (maskVal);
+
+    // bit-mask to mark pixels not used in analysis
+    psMaskType markVal = psMetadataLookupU8(&status, recipe, "MARK.PSPHOT");
+    assert (markVal);
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
+    // source analysis is done in spatial order
+    sources = psArraySort (sources, pmSourceSortByY);
+
+    // storage array for fitSources
+    psArray *fitSources = psArrayAllocEmpty (sources->n);
+
+    // option to limit analysis to a specific region
+    char *region = psMetadataLookupStr (&status, recipe, "ANALYSIS_REGION");
+    psRegion AnalysisRegion = psRegionFromString (region);
+    AnalysisRegion = psRegionForImage (readout->image, AnalysisRegion);
+    if (psRegionIsNaN (AnalysisRegion)) psAbort("analysis region mis-defined");
+
+    bool CONSTANT_PHOTOMETRIC_WEIGHTS =
+        psMetadataLookupBool(&status, recipe, "CONSTANT_PHOTOMETRIC_WEIGHTS");
+    if (!status) {
+        psAbort("You must provide a value for the BOOL recipe CONSTANT_PHOTOMETRIC_WEIGHTS");
+    }
+    int SKY_FIT_ORDER = psMetadataLookupS32(&status, recipe, "SKY_FIT_ORDER");
+    if (!status) {
+        SKY_FIT_ORDER = 0;
+    }
+    bool SKY_FIT_LINEAR = psMetadataLookupBool(&status, recipe, "SKY_FIT_LINEAR");
+    if (!status) {
+        SKY_FIT_LINEAR = false;
+    }
+
+    // select the sources which will be used for the fitting analysis
+    for (int i = 0; i < sources->n; i++) {
+        pmSource *source = sources->data[i];
+
+        // skip non-astronomical objects (very likely defects)
+        if (source->type == PM_SOURCE_TYPE_DEFECT) continue;
+        if (source->type == PM_SOURCE_TYPE_SATURATED) continue;
+        if (source->type == PM_SOURCE_TYPE_STAR &&
+            source->mode & PM_SOURCE_MODE_SATSTAR) continue;
+        if (final) {
+            if (source->mode &  PM_SOURCE_MODE_SUBTRACTED) continue;
+        } else {
+            if (source->mode &  PM_SOURCE_MODE_BLEND) continue;
+        }
+
+	// generate model for sources without, or skip if we can't
+	if (!source->modelFlux) {
+	    if (!pmSourceCacheModel (source, maskVal)) continue;
+	}
+
+        // save the original coords
+        x = source->peak->xf;
+        y = source->peak->yf;
+
+        // is the source in the region of interest?
+        if (x < AnalysisRegion.x0) continue;
+        if (y < AnalysisRegion.y0) continue;
+        if (x > AnalysisRegion.x1) continue;
+        if (y > AnalysisRegion.y1) continue;
+
+        psArrayAdd (fitSources, 100, source);
+    }
+    psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "built fitSources: %f (%ld objects)\n", psTimerMark ("psphot"), sources->n);
+
+    // vectors to store stats for each object
+    // psVector *weight = psVectorAlloc (fitSources->n, PS_TYPE_F32);
+    psVector *errors = psVectorAlloc (fitSources->n, PS_TYPE_F32);
+
+    // create the border matrix (includes the sparse matrix)
+    // for just sky: 1 row; for x,y terms: 3 rows
+    psSparse *sparse = psSparseAlloc (fitSources->n, 100);
+    int nBorder = (SKY_FIT_ORDER == 0) ? 1 : 3;
+    psSparseBorder *border = psSparseBorderAlloc (sparse, nBorder);
+
+    // fill out the sparse matrix elements and border elements (B)
+    // SRCi is the current source of interest
+    // SRCj is a possibly overlapping source
+    for (int i = 0; i < fitSources->n; i++) {
+        pmSource *SRCi = fitSources->data[i];
+
+        // diagonal elements of the sparse matrix (auto-cross-product)
+        f = pmSourceModelDotModel (SRCi, SRCi, CONSTANT_PHOTOMETRIC_WEIGHTS);
+        psSparseMatrixElement (sparse, i, i, f);
+
+        // the formal error depends on the weighting scheme
+        if (CONSTANT_PHOTOMETRIC_WEIGHTS) {
+            float var = pmSourceModelDotModel (SRCi, SRCi, false);
+            errors->data.F32[i] = 1.0 / sqrt(var);
+        } else {
+            errors->data.F32[i] = 1.0 / sqrt(f);
+        }
+
+
+        // find the image x model value
+        f = pmSourceDataDotModel (SRCi, SRCi, CONSTANT_PHOTOMETRIC_WEIGHTS);
+        psSparseVectorElement (sparse, i, f);
+
+        // add the per-source weights (border region)
+        switch (SKY_FIT_ORDER) {
+          case 1:
+            f = pmSourceModelWeight (SRCi, 1, CONSTANT_PHOTOMETRIC_WEIGHTS);
+            psSparseBorderElementB (border, i, 1, f);
+            f = pmSourceModelWeight (SRCi, 2, CONSTANT_PHOTOMETRIC_WEIGHTS);
+            psSparseBorderElementB (border, i, 2, f);
+
+          case 0:
+            f = pmSourceModelWeight (SRCi, 0, CONSTANT_PHOTOMETRIC_WEIGHTS);
+            psSparseBorderElementB (border, i, 0, f);
+            break;
+
+          default:
+            psAbort("Invalid SKY_FIT_ORDER %d\n", SKY_FIT_ORDER);
+            break;
+        }
+
+        // loop over all other stars following this one
+        for (int j = i + 1; j < fitSources->n; j++) {
+            pmSource *SRCj = fitSources->data[j];
+
+            // skip over disjoint source images, break after last possible overlap
+            if (SRCi->pixels->row0 + SRCi->pixels->numRows < SRCj->pixels->row0) break;
+            if (SRCj->pixels->row0 + SRCj->pixels->numRows < SRCi->pixels->row0) continue;
+            if (SRCi->pixels->col0 + SRCi->pixels->numCols < SRCj->pixels->col0) continue;
+            if (SRCj->pixels->col0 + SRCj->pixels->numCols < SRCi->pixels->col0) continue;
+
+            // got an overlap; calculate cross-product and add to output array
+            f = pmSourceModelDotModel (SRCi, SRCj, CONSTANT_PHOTOMETRIC_WEIGHTS);
+            psSparseMatrixElement (sparse, j, i, f);
+        }
+    }
+
+    psSparseResort (sparse);
+    psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "built matrix: %f (%d elements)\n", psTimerMark ("psphot"), sparse->Nelem);
+
+    // set the sky, sky_x, sky_y components of border matrix
+    SetBorderMatrixElements (border, readout, fitSources, CONSTANT_PHOTOMETRIC_WEIGHTS, SKY_FIT_ORDER, markVal);
+    psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "set border: %f (%d elements)\n", psTimerMark ("psphot"), sparse->Nelem);
+
+    psSparseConstraint constraint;
+    constraint.paramMin   = 0.0;
+    constraint.paramMax   = 1e8;
+    constraint.paramDelta = 1e8;
+
+    // solve for normalization terms (need include local sky?)
+    psVector *norm = NULL;
+    psVector *skyfit = NULL;
+    if (SKY_FIT_LINEAR) {
+        psSparseBorderSolve (&norm, &skyfit, constraint, border, 5);
+        fprintf (stderr, "skyfit: %f\n", skyfit->data.F32[0]);
+    } else {
+        norm = psSparseSolve (NULL, constraint, sparse, 5);
+        skyfit = NULL;
+    }
+    psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "solve matrix: %f (%d elements)\n", psTimerMark ("psphot"), sparse->Nelem);
+
+    // adjust I0 for fitSources and subtract
+    for (int i = 0; i < fitSources->n; i++) {
+        pmSource *source = fitSources->data[i];
+        pmModel *model = pmSourceGetModel (NULL, source);
+
+        // assign linearly-fitted normalization
+        if (isnan(norm->data.F32[i])) {
+            psAbort("linear fitted source is nan");
+        }
+        model->params->data.F32[PM_PAR_I0] = norm->data.F32[i];
+        model->dparams->data.F32[PM_PAR_I0] = errors->data.F32[i];
+        // XXX is the value of 'errors' modified by the sky fit?
+
+        // subtract object
+        pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
+        source->mode |= PM_SOURCE_MODE_SUBTRACTED;
+    }
+    psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "sub models: %f (%d elements)\n", psTimerMark ("psphot"), sparse->Nelem);
+
+    // measure chisq for each source
+    for (int i = 0; final && (i < fitSources->n); i++) {
+        pmSource *source = fitSources->data[i];
+        pmModel *model = pmSourceGetModel (NULL, source);
+        pmSourceChisq (model, source->pixels, source->maskObj, source->weight, maskVal);
+    }
+    psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "get chisqs: %f (%d elements)\n", psTimerMark ("psphot"), sparse->Nelem);
+
+    // psFree (index);
+    psFree (sparse);
+    psFree (fitSources);
+    psFree (norm);
+    psFree (skyfit);
+    psFree (errors);
+    psFree (border);
+
+    psLogMsg ("psphot.ensemble", PS_LOG_INFO, "measure ensemble of PSFs: %f sec\n", psTimerMark ("psphot"));
+    return true;
+}
+
+// XXX do we need this?
+
+// Calculate the weight terms for the sky fit component of the matrix.  This function operates
+// on the pixels which correspond to all of the sources of interest.  These elements fill in
+// the border matrix components in the sparse matrix equation.
+static bool SetBorderMatrixElements (psSparseBorder *border, pmReadout *readout, psArray *sources, bool constant_weights, int SKY_FIT_ORDER, psMaskType markVal) {
+
+    // generate the image-wide weight terms
+    // turn on MARK for all image pixels
+    psRegion fullArray = psRegionSet (0, 0, 0, 0);
+    fullArray = psRegionForImage (readout->mask, fullArray);
+    psImageMaskRegion (readout->mask, fullArray, "OR", markVal);
+    psLogMsg ("psphot.ensemble", PS_LOG_INFO, "step 1: %f sec\n", psTimerMark ("psphot"));
+
+    // turn off MARK for all object pixels
+    for (int i = 0; i < sources->n; i++) {
+        pmSource *source = sources->data[i];
+        pmModel *model = pmSourceGetModel (NULL, source);
+        if (model == NULL) continue;
+        float x = model->params->data.F32[PM_PAR_XPOS];
+        float y = model->params->data.F32[PM_PAR_YPOS];
+        psImageMaskCircle (source->maskView, x, y, model->radiusFit, "AND", PS_NOT_U8(markVal));
+    }
+    psLogMsg ("psphot.ensemble", PS_LOG_INFO, "step 2: %f sec\n", psTimerMark ("psphot"));
+
+    // accumulate the image statistics from the masked regions
+    psF32 **image  = readout->image->data.F32;
+    psF32 **weight = readout->weight->data.F32;
+    psU8  **mask   = readout->mask->data.U8;
+
+    double w, x, y, x2, xy, y2, xc, yc, wt, f, fo, fx, fy;
+    w = x = y = x2 = xy = y2 = fo = fx = fy = 0;
+
+    int col0 = readout->image->col0;
+    int row0 = readout->image->row0;
+
+    for (int j = 0; j < readout->image->numRows; j++) {
+        for (int i = 0; i < readout->image->numCols; i++) {
+            if (mask[j][i]) continue;
+            if (constant_weights) {
+                wt = 1.0;
+            } else {
+                wt = weight[j][i];
+            }
+            f = image[j][i];
+            w   += 1/wt;
+            fo  += f/wt;
+            if (SKY_FIT_ORDER == 0) continue;
+
+            xc  = i + col0;
+            yc  = j + row0;
+            x  +=    xc/wt;
+            y  +=    yc/wt;
+            x2 += xc*xc/wt;
+            xy += xc*yc/wt;
+            y2 += yc*yc/wt;
+            fx +=  f*xc/wt;
+            fy +=  f*yc/wt;
+        }
+    }
+    psLogMsg ("psphot.ensemble", PS_LOG_INFO, "step 3: %f sec\n", psTimerMark ("psphot"));
+
+    // turn off MARK for all image pixels
+    psImageMaskRegion (readout->mask, fullArray, "AND", PS_NOT_U8(markVal));
+    psLogMsg ("psphot.ensemble", PS_LOG_INFO, "step 4: %f sec\n", psTimerMark ("psphot"));
+
+    // set the Border T elements
+    psSparseBorderElementG (border, 0, fo);
+    psSparseBorderElementT (border, 0, 0, w);
+    if (SKY_FIT_ORDER > 0) {
+        psSparseBorderElementG (border, 0, fx);
+        psSparseBorderElementG (border, 0, fy);
+        psSparseBorderElementT (border, 1, 0, x);
+        psSparseBorderElementT (border, 2, 0, y);
+        psSparseBorderElementT (border, 0, 1, x);
+        psSparseBorderElementT (border, 1, 1, x2);
+        psSparseBorderElementT (border, 2, 1, xy);
+        psSparseBorderElementT (border, 0, 2, y);
+        psSparseBorderElementT (border, 1, 2, xy);
+        psSparseBorderElementT (border, 2, 2, y2);
+    }
+    psLogMsg ("psphot.ensemble", PS_LOG_INFO, "step 5: %f sec\n", psTimerMark ("psphot"));
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotGuessModels.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotGuessModels.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotGuessModels.c	(revision 22158)
@@ -0,0 +1,106 @@
+# include "psphotInternal.h"
+
+// A guess for when the moments aren't available
+static pmModel *wildGuess(pmSource *source, // Source for which to guess
+                          pmPSF *psf    // The point-spread function
+    )
+{
+    pmModel *model = pmModelAlloc(psf->type);
+    psF32 *PAR = model->params->data.F32;
+    PAR[PM_PAR_SKY]  = 0;
+    // XXX get this from the image pixels
+    PAR[PM_PAR_I0]   = source->peak->flux;
+    PAR[PM_PAR_XPOS] = source->peak->xf;
+    PAR[PM_PAR_YPOS] = source->peak->yf;
+    return model;
+}
+
+// construct an initial PSF model for each object
+bool psphotGuessModels (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf) {
+
+    bool status;
+
+    psTimerStart ("psphot");
+
+    // bit-masks to test for good/bad pixels
+    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT");
+    assert (maskVal);
+
+    // bit-mask to mark pixels not used in analysis
+    psMaskType markVal = psMetadataLookupU8(&status, recipe, "MARK.PSPHOT");
+    assert (markVal);
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
+    // setup the PSF fit radius details
+    psphotInitRadiusPSF (recipe, psf->type);
+
+    for (int i = 0; i < sources->n; i++) {
+	pmSource *source = sources->data[i];
+
+	// skip non-astronomical objects (very likely defects)
+	if (source->type == PM_SOURCE_TYPE_DEFECT) continue;
+	if (source->type == PM_SOURCE_TYPE_SATURATED) continue;
+
+	// XXX if a source is faint, it will not have moments measured.
+	// it must be modelled as a PSF.  In this case, we need to use
+	// the peak centroid to get the coordinates and get the peak flux
+	// from the image?
+	pmModel *modelEXT;
+	if (!source->moments) {
+	    modelEXT = wildGuess(source, psf);
+	} else {
+	    // use the source moments, etc to guess basic model parameters
+	    modelEXT = pmSourceModelGuess (source, psf->type);
+	    if (!modelEXT) {
+		modelEXT = wildGuess(source, psf);
+	    }
+	    // these valuse are set in pmSourceModelGuess, should this rule be in there as well?
+	    if (source->mode &  PM_SOURCE_MODE_SATSTAR) {
+		modelEXT->params->data.F32[PM_PAR_XPOS] = source->moments->x;
+		modelEXT->params->data.F32[PM_PAR_YPOS] = source->moments->y;
+	    } else {
+		modelEXT->params->data.F32[PM_PAR_XPOS] = source->peak->xf;
+		modelEXT->params->data.F32[PM_PAR_YPOS] = source->peak->yf;
+	    }
+	}
+
+	// set PSF parameters for this model (apply 2D shape model)
+	pmModel *modelPSF = pmModelFromPSF (modelEXT, psf);
+	if (modelPSF == NULL) {
+	    psError(PSPHOT_ERR_PSF, false,
+		    "Failed to determine PSF model at r,c = (%d,%d); trying centre of image",
+		    source->peak->y, source->peak->x);
+	    //
+	    // Try the centre of the image
+	    //
+	    modelEXT->params->data.F32[PM_PAR_XPOS] = 0.5*readout->image->numCols;
+	    modelEXT->params->data.F32[PM_PAR_YPOS] = 0.5*readout->image->numRows;
+	    modelPSF = pmModelFromPSF (modelEXT, psf);
+	    if (modelPSF == NULL) {
+		psError(PSPHOT_ERR_PSF, false,
+			"Failed to determine PSF model at centre of image");
+		psFree(modelEXT);
+		return false;
+	    }
+
+	    source->mode |= PM_SOURCE_MODE_BADPSF;
+	}
+	psFree (modelEXT);
+
+	// XXX need to define the guess flux?
+	// set the fit radius based on the object flux limit and the model
+	psphotCheckRadiusPSF (readout, source, modelPSF, markVal);
+
+	// set the source PSF model
+	source->modelPSF = modelPSF;
+	source->modelPSF->residuals = psf->residuals;
+
+	pmSourceCacheModel (source, maskVal);
+    }
+    psLogMsg ("psphot.models", 4, "built models for %ld objects: %f sec\n", sources->n, psTimerMark ("psphot"));
+    return true;
+}
+
+// XXX do we always know which model is supposed to be used?
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotImageLoop.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotImageLoop.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotImageLoop.c	(revision 22158)
@@ -0,0 +1,101 @@
+# include "psphotStandAlone.h"
+
+# define ESCAPE(MESSAGE) { \
+  psError(PSPHOT_ERR_DATA, false, MESSAGE); \
+  psFree (view); \
+  return false; \
+}
+
+bool psphotImageLoop (pmConfig *config) {
+
+    bool status;
+    pmChip *chip;
+    pmCell *cell;
+    pmReadout *readout;
+
+    pmFPAfile *load = psMetadataLookupPtr (&status, config->files, "PSPHOT.LOAD");
+    if (!status) {
+	psError(PSPHOT_ERR_PROG, false, "Can't find input data!");
+	return false;
+    }
+    pmFPAfile *input = psMetadataLookupPtr (&status, config->files, "PSPHOT.INPUT");
+    if (!status) {
+	psError(PSPHOT_ERR_PROG, false, "Can't find input data!");
+	return false;
+    }
+
+    pmFPAview *view = pmFPAviewAlloc (0);
+    
+    // files associated with the science image
+    if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE ("failed input for fpa in psphot.");
+
+    // for psphot, we force data to be read at the chip level 
+    while ((chip = pmFPAviewNextChip (view, load->fpa, 1)) != NULL) {
+        psLogMsg ("psphot", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+        if (! chip->process || ! chip->file_exists) { continue; }
+
+	// load just the input image data (image, mask, weight)
+	pmFPAfileActivate (config->files, false, NULL);
+	pmFPAfileActivate (config->files, true, "PSPHOT.LOAD");
+	pmFPAfileActivate (config->files, true, "PSPHOT.MASK");
+	pmFPAfileActivate (config->files, true, "PSPHOT.WEIGHT");
+	if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE ("failed input for Chip in psphot.");
+
+	// mosaic the cells of a chip into a single contiguous (trimmed) chip
+        if (!psphotMosaicChip(config, view, "PSPHOT.INPUT", "PSPHOT.LOAD")) ESCAPE ("Unable to mosaic chip.");
+
+	// try to load other supporting data (PSF, SRC, etc).
+	// do not re-load the following three files
+	pmFPAfileActivate (config->files, true, NULL);
+	pmFPAfileActivate (config->files, false, "PSPHOT.LOAD");
+	pmFPAfileActivate (config->files, false, "PSPHOT.MASK");
+	pmFPAfileActivate (config->files, false, "PSPHOT.WEIGHT");
+	if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE ("failed input for Chip in psphot.");
+
+	// re-activate files so they will be closed and freed below
+	pmFPAfileActivate (config->files, true, NULL);
+
+	// there is now only a single chip (multiple readouts?). loop over it and process
+	while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
+            psLogMsg ("psphot", 5, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+
+	    // process each of the readouts
+	    while ((readout = pmFPAviewNextReadout (view, input->fpa, 1)) != NULL) {
+		psLogMsg ("psphot", 6, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+		if (! readout->data_exists) { continue; }
+
+		// run the actual photometry analysis on this chip/cell/readout
+		if (!psphotReadout (config, view)) {
+		    psError(psErrorCodeLast(), false, "failure in psphotReadout for chip %d, cell %d, readout %d\n", view->chip, view->cell, view->readout);
+		    psFree (view);
+		    return false;
+		}
+	    }
+	}
+
+	// save output which is saved at the chip level
+	if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE ("failed output for Chip in psphot.");
+    }
+    // save output which is saved at the fpa level
+    if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE ("failed ouput for FPA in psphot.");
+
+    // fail if we failed to handle an error
+    if (psErrorCodeLast() != PS_ERR_NONE) psAbort ("failed to handle an error!");
+
+    psFree (view);
+    return true;
+}
+
+// I/O files related to psphot:
+// PSPHOT.INPUT   : input image file(s)
+// PSPHOT.RESID   : residual image
+// PSPHOT.OUTPUT  : output object tables (object)
+
+// PSPHOT.BACKSUB : background subtracted image
+// PSPHOT.BACKGND : background model (full-scale image?)
+// PSPHOT.BACKMDL : background model (binned image?)
+// PSPHOT.PSF     : sample PSF images
+
+// PSPHOT.MASK
+// PSPHOT.WEIGHT
+// 
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotImageMedian.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotImageMedian.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotImageMedian.c	(revision 22158)
@@ -0,0 +1,392 @@
+# include "psphotInternal.h"
+static int npass = 0;
+
+// generate the median in NxN boxes, clipping heavily
+// linear interpolation to generate full-scale model
+bool psphotImageMedian (pmConfig *config, const pmFPAview *view, psMaskType maskVal)
+{
+    bool status = true;
+    static char *defaultStatsName = "FITTED_MEAN";
+
+    pmReadout *readout = NULL;
+    pmReadout *background = NULL;
+    pmReadout *backSub = NULL;
+
+    psTimerStart ("psphot");
+
+    // select the appropriate recipe information
+    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
+
+    // user supplied seed, if available
+    unsigned long seed = psMetadataLookupS32 (&status, recipe, "IMSTATS_SEED");
+    if (!status) {
+        seed = 0;
+    }
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, seed);
+
+    // subtract this amount extra from the sky
+    float SKY_BIAS = psMetadataLookupF32 (&status, recipe, "SKY_BIAS");
+    if (!status) {
+        SKY_BIAS = 0;
+    }
+
+    // supply the sky background statistics options
+    char *statsName = psMetadataLookupStr (&status, recipe, "SKY_STAT");
+    if (statsName == NULL) {
+        statsName = defaultStatsName;
+    }
+    psStatsOptions statsOptionLocation = psStatsOptionFromString(statsName);
+    if (!(statsOptionLocation & (PS_STAT_SAMPLE_MEAN |
+                                 PS_STAT_SAMPLE_MEDIAN |
+                                 PS_STAT_ROBUST_MEDIAN |
+                                 PS_STAT_ROBUST_QUARTILE |
+                                 PS_STAT_CLIPPED_MEAN |
+                                 PS_STAT_FITTED_MEAN |
+                                 PS_STAT_FITTED_MEAN_V2 |
+                                 PS_STAT_FITTED_MEAN_V3 |
+                                 PS_STAT_FITTED_MEAN_V4))) {
+        statsOptionLocation = PS_STAT_FITTED_MEAN;
+    }
+
+    psStatsOptions statsOptionWidth = PS_STAT_NONE;
+    if (statsOptionLocation & (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN)) {
+        statsOptionWidth = PS_STAT_SAMPLE_STDEV;
+    } else if (statsOptionLocation & (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_QUARTILE)) {
+#if 1
+        statsOptionWidth = PS_STAT_ROBUST_STDEV; // not set; => NaN
+#else
+        statsOptionWidth = PS_STAT_FITTED_STDEV;
+#endif
+    } else if (statsOptionLocation & PS_STAT_FITTED_MEAN) {
+        statsOptionWidth = PS_STAT_FITTED_STDEV;
+    } else if (statsOptionLocation & PS_STAT_CLIPPED_MEAN) {
+        statsOptionWidth = PS_STAT_CLIPPED_STDEV;
+    } else if (statsOptionLocation & PS_STAT_FITTED_MEAN_V2) {
+        statsOptionWidth = PS_STAT_FITTED_STDEV_V2;
+    } else if (statsOptionLocation & PS_STAT_FITTED_MEAN_V3) {
+        statsOptionWidth = PS_STAT_FITTED_STDEV_V3;
+    } else if (statsOptionLocation & PS_STAT_FITTED_MEAN_V4) {
+        statsOptionWidth = PS_STAT_FITTED_STDEV_V4;
+    } else {
+        psAbort("Unable to estimate variance of selected statsOptionLocations 0x%x", statsOptionLocation);
+    }
+
+    const psStatsOptions statsOption = statsOptionLocation | statsOptionWidth;
+    psStats *stats = psStatsAlloc (statsOption);
+
+    // set range for old-version of sky statistic
+    if (statsOptionLocation & PS_STAT_ROBUST_QUARTILE) {
+        stats->min = 0.25;
+        stats->max = 0.75;
+    }
+
+    // set user-option for number of pixels per region
+    stats->nSubsample = psMetadataLookupF32 (&status, recipe, "IMSTATS_NPIX");
+    if (!status) {
+        stats->nSubsample = 1000;
+    }
+
+    // optionally set the binsize
+    stats->binsize = psMetadataLookupF32 (&status, recipe, "SKY_HISTOGRAM_BINS");
+    if (status) {
+        stats->options |= PS_STAT_USE_BINSIZE;
+    }
+
+    // optionally set the sigma clipping
+    stats->clipSigma = psMetadataLookupF32 (&status, recipe, "SKY_CLIP_SIGMA");
+    if (!status) {
+        if ((stats->options & PS_STAT_FITTED_MEAN) || (stats->options & PS_STAT_FITTED_MEAN_V2)) {
+            stats->clipSigma = 1.0;
+        } else {
+            stats->clipSigma = 3.0;
+        }
+    }
+
+    // stats is not initialized by psStats???  use this to save the input options
+    // XXX re-work this to use the new psStatsInit function
+    psStats *statsDefaults = psStatsAlloc (statsOption);
+    *statsDefaults = *stats;
+
+    // find the currently selected readout
+    pmFPAfile *file = psMetadataLookupPtr (&status, config->files, "PSPHOT.INPUT");
+    pmFPA *inFPA = file->fpa;
+    readout = pmFPAviewThisReadout (view, inFPA);
+
+    psImage *image = readout->image;
+    psImage *mask  = readout->mask;
+
+    // I have the fine image size, I know the binning factor, determine the ruff image size
+    psImageBinning *binning = psImageBinningAlloc();
+    binning->nXfine = image->numCols;
+    binning->nYfine = image->numRows;
+    binning->nXbin  = psMetadataLookupS32 (&status, recipe, "BACKGROUND.XBIN");
+    binning->nYbin  = psMetadataLookupS32 (&status, recipe, "BACKGROUND.YBIN");
+
+    psImageBinningSetRuffSize(binning, PS_IMAGE_BINNING_CENTER);
+    psImageBinningSetSkip(binning, image);
+    status = psMetadataAddPtr(recipe, PS_LIST_TAIL, "PSPHOT.BACKGROUND.BINNING", PS_DATA_UNKNOWN | PS_META_REPLACE, "Background binning", binning);
+    PS_ASSERT (status, false);
+
+    // we save the binning structure for use in psphotMagnitudes
+    pmReadout *model      = pmFPAGenerateReadout (config, view, "PSPHOT.BACKMDL",       inFPA, binning);
+    pmReadout *modelStdev = pmFPAGenerateReadout (config, view, "PSPHOT.BACKMDL.STDEV", inFPA, binning);
+
+    psF32 **modelData = model->image->data.F32;
+    psF32 **modelStdevData = modelStdev->image->data.F32;
+
+    // measure clipped median for subimages
+    psRegion ruffRegion = {0,0,0,0};
+    psRegion fineRegion = {0,0,0,0};
+    for (int iy = 0; iy < model->image->numRows; iy++) {
+        for (int ix = 0; ix < model->image->numCols; ix++) {
+
+            // convert the ruff grid cell to the equivalent fine grid cell
+            // XXX we need to watch out for row0,col0
+            ruffRegion = psRegionSet (ix, ix + 2, iy, iy + 2);
+            fineRegion = psImageBinningSetFineRegion (binning, ruffRegion);
+            fineRegion = psRegionForImage (image, fineRegion);
+
+            psImage *subset  = psImageSubset (image, fineRegion);
+            if (!subset->numCols || !subset->numRows) {
+                psFree (subset);
+                continue;
+            }
+            psImage *submask = psImageSubset (mask, fineRegion);
+
+            // reset the default values
+            *stats = *statsDefaults;
+
+            // Use the selected background statistic for the first pass
+            // If it fails, fall back on the "ROBUST_MEDIAN" version
+            // If both fail, set the pixel to NAN and (below) interpolate
+            // XXX psImageBackground will probably be renamed psImageStats
+            // XXX don't bother trying if there are no valid pixels...
+
+	    psVector *sample = NULL;
+
+	    // turn on stats tracing in desired cells
+	    # if (0)
+	    psMetadata *plots = psMetadataLookupPtr (&status, recipe, "DIAGNOSTIC.PLOTS");
+	    assert (plots);
+	    
+	    int xPlot = psMetadataLookupS32 (&status, plots, "IMAGE.BACKGROUND.CELL.HISTOGRAM.X");
+	    assert (status);
+	    int yPlot = psMetadataLookupS32 (&status, plots, "IMAGE.BACKGROUND.CELL.HISTOGRAM.Y");
+	    assert (status);
+
+	    bool gotX = (xPlot < 0) || (xPlot == ix);
+	    bool gotY = (yPlot < 0) || (yPlot == iy);
+
+	    if (gotX && gotY) {
+		psTraceSetLevel ("psLib.math.vectorFittedStats_v4", 6);
+		psTraceSetLevel ("psLib.math.vectorRobustStats", 6);
+	    } else {
+		psTraceSetLevel ("psLib.math.vectorFittedStats_v4", 0);
+		psTraceSetLevel ("psLib.math.vectorRobustStats", 0);
+	    }	    
+	    # endif
+
+            if (psImageBackground(stats, &sample, subset, submask, maskVal, rng)) {
+                if (stats->options & PS_STAT_ROBUST_QUARTILE) {
+                    modelData[iy][ix] = stats->robustMedian;
+                } else {
+                    modelData[iy][ix] = psStatsGetValue(stats, statsOptionLocation);
+                }
+                modelStdevData[iy][ix] = psStatsGetValue(stats, statsOptionWidth);
+
+		// supply sample to plotting routing
+		psphotDiagnosticPlots (config, "IMAGE.BACKGROUND.CELL.HISTOGRAM", ix, iy, modelData[iy][ix], modelStdevData[iy][ix], sample);
+		psFree (sample);
+            } else {
+                psStatsOptions currentOptions = stats->options;
+                stats->options = PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV;
+                if (!psImageBackground(stats, &sample, subset, submask, maskVal, rng)) {
+                    psLogMsg ("psphot", PS_LOG_WARN, "Failed to estimate background using ROBUST_MEDIAN for "
+                               "(%dx%d, (row0,col0) = (%d,%d)",
+                               subset->numRows, subset->numCols, subset->row0, subset->col0);
+                    modelData[iy][ix] = modelStdevData[iy][ix] = NAN;
+                } else {
+                    modelData[iy][ix] = psStatsGetValue (stats, PS_STAT_ROBUST_MEDIAN);
+                    modelStdevData[iy][ix] = psStatsGetValue(stats, PS_STAT_ROBUST_STDEV);
+
+		    // supply sample to plotting routing
+		    psphotDiagnosticPlots (config, "IMAGE.BACKGROUND.CELL.HISTOGRAM", ix, iy, modelData[iy][ix], modelStdevData[iy][ix], sample);
+		    psFree (sample);
+                }
+                // drop errors caused by psImageBackground failures
+                // XXX we probably should trap and exit on serious failures
+                psErrorClear();
+                stats->options = currentOptions;
+            }
+            modelData[iy][ix] += SKY_BIAS;
+            psFree (subset);
+            psFree (submask);
+        }
+    }
+
+    if (psTraceGetLevel("psphot") > 5) {
+        char name[256];
+        sprintf (name, "backraw.%02d.fits", npass);
+        psphotSaveImage (NULL, model->image, name);
+    }
+
+    // patch over bad regions (use average of 8 possible neighbor pixels)
+    // XXX consider testing all pixels against the 8 neighbors and replacing outliers...
+    double Count = 0;                   // number of good pixels
+    double Value = 0;                   // sum of good pixel's value
+    double ValueStdev = 0;              // sum of good pixel's standard deviations
+    for (int iy = 0; iy < model->image->numRows; iy++) {
+        for (int ix = 0; ix < model->image->numCols; ix++) {
+            if (!isnan(modelData[iy][ix])) {
+                Value += modelData[iy][ix];
+                ValueStdev += modelStdevData[iy][ix];
+                Count++;
+                continue;
+            }
+
+            double value = 0;
+            double count = 0;
+            for (int jy = iy - 1; jy <= iy + 1; jy++) {
+                if (jy <   0) continue;
+                if (jy >= model->image->numRows) continue;
+                for (int jx = ix - 1; jx <= ix + 1; jx++) {
+                    if (!jx && !jy) continue;
+                    if (jx   <   0) continue;
+                    if (jx   >= model->image->numCols) continue;
+                    value += modelData[jy][jx];
+                    count += 1.0;
+                }
+            }
+            if (count > 0) modelData[iy][ix] = value / count;
+        }
+    }
+    if (Count == 0) {
+        psError (PSPHOT_ERR_DATA, true, "failed to build background image");
+	psFree(stats);
+	psFree(statsDefaults);
+	psFree(binning);
+	psFree(rng);
+        return false;
+    }
+
+    Value /= Count;
+    ValueStdev /= Count;
+
+    // patch over remaining bad regions (use global average)
+    for (int iy = 0; iy < model->image->numRows; iy++) {
+        for (int ix = 0; ix < model->image->numCols; ix++) {
+            if (!isnan(modelData[iy][ix])) continue;
+            modelData[iy][ix] = Value;
+            modelStdevData[iy][ix] = ValueStdev;
+        }
+    }
+
+    psLogMsg ("psphot", PS_LOG_MINUTIA, "build median image: %f sec\n", psTimerMark ("psphot"));
+
+    psMetadataAddF32(recipe, PS_LIST_TAIL, "SKY_MEAN", PS_META_REPLACE, "sky mean", Value);
+    psMetadataAddF32(recipe, PS_LIST_TAIL, "SKY_STDEV", PS_META_REPLACE, "sky stdev", ValueStdev);
+    psLogMsg ("psphot", PS_LOG_INFO, "image sky : mean %f stdev %f", Value, ValueStdev);
+
+    // measure image and background stats and save for later output
+    psStats *statsBck = psStatsAlloc (PS_STAT_SAMPLE_MEAN |
+                                      PS_STAT_SAMPLE_STDEV |
+                                      PS_STAT_MIN |
+                                      PS_STAT_MAX);
+    psImageStats (statsBck, model->image, NULL, 0);
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "MSKY_MN",
+                      PS_META_REPLACE, "sky model mean",          statsBck->sampleMean);
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "MSKY_SIG",
+                      PS_META_REPLACE, "sky model stdev",         statsBck->sampleStdev);
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "MSKY_MAX",
+                      PS_META_REPLACE, "sky model maximum value", statsBck->max);
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "MSKY_MIN",
+                      PS_META_REPLACE, "sky model minimum value", statsBck->min);
+    psMetadataAddS32 (recipe, PS_LIST_TAIL, "MSKY_NX",
+                      PS_META_REPLACE, "sky model size (x)",      model->image->numCols);
+    psMetadataAddS32 (recipe, PS_LIST_TAIL, "MSKY_NY",
+                      PS_META_REPLACE, "sky model size (y)",      model->image->numRows);
+    psLogMsg ("psphot", PS_LOG_INFO, "background sky : min %f mean %f max %f stdev %f",
+              statsBck->min, statsBck->sampleMean, statsBck->max, statsBck->sampleStdev);
+    psFree (statsBck);
+
+    // select background pixels, from output background file, or create
+    file = psMetadataLookupPtr (&status, config->files, "PSPHOT.BACKGND");
+    if (file) {
+        // we are using PSPHOT.BACKGND as an I/O file: select readout or create
+        if (file->mode == PM_FPA_MODE_INTERNAL) {
+            background = file->readout;
+        } else {
+            background = pmFPAviewThisReadout (view, file->fpa);
+        }
+        if (background == NULL) {
+            // readout does not yet exist: create from input
+            pmFPAfileCopyStructureView (file->fpa, inFPA, 1, 1, view);
+            background = pmFPAviewThisReadout (view, file->fpa);
+            if ((image->numCols != background->image->numCols) || (image->numRows != background->image->numRows)) {
+                psError (PSPHOT_ERR_PROG, true, "inconsistent sizes for background dimensions");
+                return false;
+            }
+        }
+    } else {
+        background = pmFPAfileDefineInternal (config->files, "PSPHOT.BACKGND", image->numCols, image->numRows, PS_TYPE_F32);
+    }
+    psF32 **backData = background->image->data.F32;
+
+    // linear interpolation to full-scale
+    if (!psImageUnbin (background->image, model->image, binning)) {
+        psError (PSPHOT_ERR_PROG, true, "inconsistent sizes for unbinning");
+        return false;
+    }
+
+    psLogMsg ("psphot", PS_LOG_MINUTIA, "build resampled image: %f sec\n", psTimerMark ("psphot"));
+
+    // back-sub image pixels, from output background file (don't create if not requested)
+    file = psMetadataLookupPtr (&status, config->files, "PSPHOT.BACKSUB");
+    if (file) {
+        // we are using PSPHOT.BACKSUB as an I/O file: select readout or create
+        backSub = pmFPAviewThisReadout (view, file->fpa);
+        if (backSub == NULL) {
+            // readout does not yet exist: create from input
+            pmFPAfileCopyStructureView (file->fpa, inFPA, 1, 1, view);
+            backSub = pmFPAviewThisReadout (view, file->fpa);
+        }
+    }
+
+    if (psTraceGetLevel("psphot") > 5) {
+        char name[256];
+        sprintf (name, "image.%02d.fits", npass);
+        psphotSaveImage (NULL, image, name);
+        sprintf (name, "back.%02d.fits", npass);
+        psphotSaveImage (NULL, background->image, name);
+        sprintf (name, "mask.%02d.fits", npass);
+        psphotSaveImage (NULL, mask, name);
+        sprintf (name, "backmdl.%02d.fits", npass);
+        psphotSaveImage (NULL, model->image, name);
+    }
+
+    // subtract the background model (save in backSub, if requested)
+    for (int j = 0; j < image->numRows; j++) {
+        for (int i = 0; i < image->numCols; i++) {
+            image->data.F32[j][i] -= backData[j][i];
+            if (backSub) {
+                backSub->image->data.F32[j][i] = image->data.F32[j][i];
+            }
+        }
+    }
+
+    if (psTraceGetLevel("psphot") > 5) {
+        char name[256];
+        sprintf (name, "backsub.%02d.fits", npass);
+        psphotSaveImage (NULL, image, name);
+    }
+    npass ++;
+
+    psLogMsg ("psphot", PS_LOG_INFO, "subtracted background model: %f sec\n", psTimerMark ("psphot"));
+    psFree(stats);
+    psFree(statsDefaults);
+    psFree(binning);
+    psFree(rng);
+
+    // the pmReadout selected in this function are all view on entries in config->files
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotInternal.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotInternal.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotInternal.h	(revision 22158)
@@ -0,0 +1,17 @@
+/* this file is included by the internal, library functions. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef PSPHOT_INTERNAL_H
+#define PSPHOT_INTERNAL_H
+
+#include <stdio.h>
+#include <strings.h>  // for strcasecmp
+#include <unistd.h>   // for unlink
+#include <pslib.h>
+#include <psmodules.h>
+#include "psphot.h"
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotIsophotal.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotIsophotal.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotIsophotal.c	(revision 22158)
@@ -0,0 +1,78 @@
+# include "psphotInternal.h"
+
+bool psphotIsophotal (pmSource *source, psMetadata *recipe, psMaskType maskVal) {
+
+  assert (source->extpars);
+  assert (source->extpars->profile);
+  assert (source->extpars->profile->radius);
+  assert (source->extpars->profile->flux);
+
+  bool status;
+
+  psVector *radius = source->extpars->profile->radius;
+  psVector *flux = source->extpars->profile->flux;
+
+  // flux at which to measure isophotal parameters
+  // XXX ISOPHOTAL_FLUX should be specified in mags, need the zero point to get counts/sec
+  float ISOPHOT_FLUX = psMetadataLookupF32 (&status, recipe, "ISOPHOTAL_FLUX");
+  assert (status);
+
+  // find the first bin below the flux level and the last above the level
+  // XXX can this be done faster with bisection?
+  // XXX do I need to worry about crazy outliers?
+  // XXX should i be smoothing or fitting the curve?
+  int firstBelow = -1;
+  int lastAbove = -1;
+  for (int i = 0; i < flux->n; i++) {
+    if (flux->data.F32[i] > ISOPHOT_FLUX) lastAbove = i;
+    if ((firstBelow < 0) && (flux->data.F32[i] < ISOPHOT_FLUX)) firstBelow = i;
+  }
+  // if we don't go out far enough, we have a problem...
+  if (lastAbove == flux->n - 1) {
+    psTrace ("psphot", 5, "did not go out far enough to reach isophotal magnitude");
+    // XXX raise a flag ?
+    return false;
+  }
+  if (firstBelow < 0) {
+    psTrace ("psphot", 5, "did not go out far enough to bound isophotal magnitude: error unmeasured");
+    // XXX raise a flag ?
+    lastAbove = firstBelow;
+    return false;
+  }
+
+  // need to examine pixels in this vicinity
+  float isophotalFluxFirst = 0;
+  float isophotalFluxLast = 0;
+  for (int i = 0; i <= PS_MAX(firstBelow, lastAbove); i++) {
+    if (i <= firstBelow) {
+      isophotalFluxFirst += flux->data.F32[i];
+    }
+    if (i <= lastAbove) {
+      isophotalFluxLast += flux->data.F32[i];
+    }
+  }
+  float isophotalFlux    = 0.5*(isophotalFluxLast + isophotalFluxFirst);
+  float isophotalFluxErr = 0.5*fabs(isophotalFluxLast - isophotalFluxFirst);
+
+  float isophotalRad     = 0.5*(radius->data.F32[firstBelow] + radius->data.F32[lastAbove]);
+  float isophotalRadErr  = 0.5*fabs(radius->data.F32[firstBelow] - radius->data.F32[lastAbove]);
+
+  if (!source->extpars->isophot) {
+    source->extpars->isophot = pmSourceIsophotalValuesAlloc ();
+  }
+
+  // these are uncalibrated: instrumental mags and pixel units
+  source->extpars->isophot->mag    = -2.5*log10(isophotalFlux);
+  source->extpars->isophot->magErr = isophotalFluxErr / isophotalFlux;
+
+  source->extpars->isophot->rad    = isophotalRad;
+  source->extpars->isophot->radErr = isophotalRadErr;
+
+  psTrace ("psphot", 5, "Isophot flux:%f +/- %f @ %f +/- %f for %f, %f\n",
+           source->extpars->isophot->mag, source->extpars->isophot->magErr,
+           source->extpars->isophot->rad, source->extpars->isophot->radErr,
+           source->peak->xf, source->peak->yf);
+
+  return true;
+
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotKernelFromPSF.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotKernelFromPSF.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotKernelFromPSF.c	(revision 22158)
@@ -0,0 +1,45 @@
+# include "psphotInternal.h"
+
+psKernel *psphotKernelFromPSF (pmSource *source, int nPix) {
+
+    assert (source);
+    assert (source->psfFlux); // XXX build if needed?
+
+    int x0 = source->peak->xf - source->psfFlux->col0;
+    int y0 = source->peak->yf - source->psfFlux->row0;
+
+    // need to decide on the size: dynamically? statically?
+    psKernel *psf = psKernelAlloc (-nPix, +nPix, -nPix, +nPix);
+
+    // XXX we should just re-construct a PSF at this location 
+    // psModelAdd (psf->image, NULL, source->modelPSF, PM_MODEL_OP_FULL | PM_MODEL_OP_NORM | PM_MODEL_OP_CENTER);
+  
+    // if the realized PSF for this object does not cover the full kernel, give up for now
+    if (x0 + psf->xMin < 0) goto escape;
+    if (x0 + psf->xMax >= source->psfFlux->numCols) goto escape;
+    if (y0 + psf->yMin < 0) goto escape;
+    if (y0 + psf->yMax >= source->psfFlux->numRows) goto escape;
+
+    double sum = 0.0;
+    for (int j = psf->yMin; j <= psf->yMax; j++) {
+	for (int i = psf->xMin; i <= psf->xMax; i++) {
+	    double value = source->psfFlux->data.F32[y0 + j][x0 + i];
+	    psf->kernel[j][i] = value;
+	    sum += value;
+	}
+    }
+    assert (sum > 0.0);
+
+    // psf must be normalized (integral = 1.0)
+    for (int i = 0; i < psf->image->numRows; i++) {
+	for (int j = 0; j < psf->image->numCols; j++) {
+	    psf->image->data.F32[i][j] /= sum;
+	}
+    }
+
+    return psf;
+
+escape:
+    psFree (psf);
+    return NULL;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotKron.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotKron.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotKron.c	(revision 22158)
@@ -0,0 +1,8 @@
+# include "psphotInternal.h"
+
+bool psphotKron (pmSource *source, psMetadata *recipe, psMaskType maskVal) {
+
+  psLogMsg ("psphot", PS_LOG_INFO, "not implemented\n");
+  return true;
+
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotLoadPSF.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotLoadPSF.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotLoadPSF.c	(revision 22158)
@@ -0,0 +1,28 @@
+# include "psphotInternal.h"
+
+// load an externally supplied psf model
+pmPSF *psphotLoadPSF (pmConfig *config, const pmFPAview *view, psMetadata *recipe) {
+
+    // find the currently selected chip
+    pmChip *chip = pmFPAfileThisChip (config->files, view, "PSPHOT.PSF.LOAD");
+    if (!chip) return NULL;
+
+    // find the currently selected readout
+    pmReadout *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.PSF.LOAD");
+    if (!readout) return NULL;
+
+    // check if a PSF model is supplied by the user
+    pmPSF *psf = psMetadataLookupPtr (NULL, chip->analysis, "PSPHOT.PSF");
+    if (psf == NULL) {
+        psLogMsg ("psphot", 3, "no psf supplied for this chip");
+        return NULL;
+    }
+
+    if (!psphotPSFstats (readout, recipe, psf)) psAbort("cannot measure PSF shape terms");
+
+    psLogMsg ("psphot", 3, "using externally supplied PSF model for this readout");
+
+    // we return a psf which can be free (and which may be removed from the metadata)
+    psMemIncrRefCounter (psf);
+    return psf;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMagnitudes.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMagnitudes.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMagnitudes.c	(revision 22158)
@@ -0,0 +1,56 @@
+# include "psphotInternal.h"
+
+bool psphotMagnitudes(psArray *sources, psMetadata *recipe, pmPSF *psf, pmReadout *background) {
+
+    bool status = false;
+    int Nap = 0;
+
+    psTimerStart ("psphot");
+
+    // bit-masks to test for good/bad pixels
+    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT");
+    assert (maskVal);
+
+    // bit-mask to mark pixels not used in analysis
+    psMaskType markVal = psMetadataLookupU8(&status, recipe, "MARK.PSPHOT");
+    assert (markVal);
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
+    pmSourceMagnitudesInit (recipe);
+
+    // XXX require that we have a background model, or
+    // allow it to be missing, setting local sky to 0.0?
+    PS_ASSERT (background, false);
+
+    // the binning details are saved on the analysis metadata
+    psImageBinning *binning = psMetadataLookupPtr(&status, recipe, "PSPHOT.BACKGROUND.BINNING");
+    PS_ASSERT (status, false);
+
+    bool IGNORE_GROWTH = psMetadataLookupBool (&status, recipe, "IGNORE_GROWTH");
+    bool INTERPOLATE_AP = psMetadataLookupBool (&status, recipe, "INTERPOLATE_AP");
+
+    pmSourcePhotometryMode photMode = PM_SOURCE_PHOT_APCORR | PM_SOURCE_PHOT_WEIGHT;
+    if (!IGNORE_GROWTH) photMode |= PM_SOURCE_PHOT_GROWTH;
+    if (INTERPOLATE_AP) photMode |= PM_SOURCE_PHOT_INTERP;
+
+    for (int i = 0; i < sources->n; i++) {
+        pmSource *source = (pmSource *) sources->data[i];
+        status = pmSourceMagnitudes (source, psf, photMode, maskVal);
+        if (status) Nap ++;
+
+        source->sky = psImageUnbinPixel(source->peak->x, source->peak->y, background->image, binning);
+        if (isnan(source->sky) && false) {
+          psError(PSPHOT_ERR_SKY, false, "Setting pmSource.sky");
+          psErrorStackPrint(NULL, " ");
+          psErrorClear();
+        }
+    }
+
+    psLogMsg ("psphot.magnitudes", PS_LOG_DETAIL, "measure magnitudes : %f sec for %ld objects (%d with apertures)\n", psTimerMark ("psphot"), sources->n, Nap);
+    return true;
+}
+
+// XXX add in a measurement of the bright and faint completeness values
+// XXX push these into the recipe
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMakeFluxScale.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMakeFluxScale.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMakeFluxScale.c	(revision 22158)
@@ -0,0 +1,63 @@
+# include "psphotInternal.h"
+
+bool psphotMakeFluxScale (psImage *image, psMetadata *recipe, pmPSF *psf) {
+
+    bool status = false;
+
+    psTimerStart ("residuals");
+
+    int Nx = psMetadataLookupS32(&status, recipe, "PSF.FLUXSCALE.NX");
+    int Ny = psMetadataLookupS32(&status, recipe, "PSF.FLUXSCALE.NY");
+
+    // stats structure for use by ApTrend : XXX make parameters user setable
+    psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
+
+    pmTrend2D *trend = pmTrend2DAlloc (PM_TREND_MAP, image, Nx, Ny, stats);
+    
+    psVector *xPts = psVectorAlloc (Nx*Ny, PS_TYPE_F32);
+    psVector *yPts = psVectorAlloc (Nx*Ny, PS_TYPE_F32);
+    psVector *fPts = psVectorAlloc (Nx*Ny, PS_TYPE_F32);
+
+    int Npts = 0;
+
+    // generate a set of test normalized PSF fluxes filling the grid 
+    for (int ix = 0; ix < Nx; ix++) {
+	for (int iy = 0; iy < Ny; iy++) {
+	    
+	    float x = psImageBinningGetFineX (trend->map->binning, ix + 0.5);
+	    float y = psImageBinningGetFineY (trend->map->binning, iy + 0.5);
+
+	    // create normalized model object at xc,yc 
+	    pmModel *model = pmModelFromPSFforXY (psf, x, y, 1.0);
+
+	    // measure the fitMag for this model
+	    float fitSum = model->modelFlux (model->params);
+	    assert (fitSum > 0);
+	    assert (isfinite(fitSum));
+
+	    xPts->data.F32[Npts] = x;
+	    yPts->data.F32[Npts] = y;
+	    fPts->data.F32[Npts] = fitSum;
+	    Npts ++;
+	    assert (Npts <= xPts->nalloc);
+	    psFree (model);
+	}
+    }
+    xPts->n = Npts;
+    yPts->n = Npts;
+    fPts->n = Npts;
+    
+    // XXX test for errors here
+    pmTrend2DFit (trend, NULL, 0xff, xPts, yPts, fPts, NULL);
+    
+    // XXX do something useful to measure residual statistics
+
+    psf->FluxScale = trend;
+
+    psFree (xPts);
+    psFree (yPts);
+    psFree (fPts);
+    psFree (stats);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMakeResiduals.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMakeResiduals.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMakeResiduals.c	(revision 22158)
@@ -0,0 +1,293 @@
+# include "psphotInternal.h"
+
+bool psphotMakeResiduals (psArray *sources, psMetadata *recipe, pmPSF *psf, psMaskType maskVal) {
+
+    bool status, isPSF;
+    double flux, dflux;
+    psU8 mflux;
+
+    psTimerStart ("residuals");
+
+    if (!psMetadataLookupBool(&status, recipe, "PSF.RESIDUALS")) return true;
+
+    int SPATIAL_ORDER = psMetadataLookupS32(&status, recipe, "PSF.RESIDUALS.SPATIAL_ORDER");
+    PS_ASSERT (status, false);
+    if (SPATIAL_ORDER != 0 && SPATIAL_ORDER != 1) {
+        psError(PSPHOT_ERR_CONFIG, true, "PSF.RESIDUALS.SPATIAL_ORDER must be 0 or 1 (not %d)",
+                SPATIAL_ORDER);
+        return false;
+    }
+
+    int xBin = psMetadataLookupS32(&status, recipe, "PSF.RESIDUALS.XBIN");
+    PS_ASSERT (status, false);
+    PS_ASSERT (xBin != 0, false);
+
+    int yBin = psMetadataLookupS32(&status, recipe, "PSF.RESIDUALS.YBIN");
+    PS_ASSERT (status, false);
+    PS_ASSERT (yBin != 0, false);
+
+    float nSigma = psMetadataLookupF32(&status, recipe, "PSF.RESIDUALS.NSIGMA");
+    PS_ASSERT (status, false);
+
+    float pixelSN = psMetadataLookupF32(&status, recipe, "PSF.RESIDUALS.PIX.SN");
+    PS_ASSERT (status, false);
+
+    char *modeString = psMetadataLookupStr(&status, recipe, "PSF.RESIDUALS.INTERPOLATION");
+    PS_ASSERT (status, false);
+
+    psImageInterpolateMode mode = psImageInterpolateModeFromString (modeString);
+    if (mode == PS_INTERPOLATE_NONE) {
+        psError(PSPHOT_ERR_CONFIG, false, "invalid interpolation in psphot.config");
+        return false;
+    }
+
+    char *statString = psMetadataLookupStr(&status, recipe, "PSF.RESIDUALS.STATISTIC");
+    PS_ASSERT (status, false);
+
+    psStatsOptions statOption = psStatsOptionFromString (statString);
+    if (!statOption) {
+        psError(PSPHOT_ERR_CONFIG, false, "invalid residual statistic in psphot.config");
+        return false;
+    }
+
+    // user parameters:
+    // size of aperture (determine from source images?)
+    // binning factor
+
+    // select the subset of sources which are the PSFSTARs
+    // for each input source:
+    // - construct a residual image, renormalized
+    // - construct a renormalized weight image
+    // - construct a new mask image
+
+    // construct the output residual table (Nx*DX,Ny*DY)
+    // for each output pixel:
+    // - construct a histogram of the values & weights (interpolate to the common pixel coordinate)
+    // - measure the robust median & sigma
+    // - reject (mask) input pixels which are outliers
+    // - re-measure the robust median & sigma
+    // - set output pixel, weight, and mask
+
+    // XXX need to set these correctly!!
+    const int badMask = 1;              // mask bits
+    const int poorMask = 2;             //       from psImageInterpolate
+    const int clippedMask = 4;          // mask bit set for clipped values
+
+    // determine the maximum image size from the input sources
+    int xSize = 0;
+    int ySize = 0;
+
+    psVector *xC = psVectorAllocEmpty (100, PS_TYPE_F32);
+    psVector *yC = psVectorAllocEmpty (100, PS_TYPE_F32);
+
+    // build (DATA - MODEL) [an image] for each psf star
+    psArray *input = psArrayAllocEmpty (100);
+    for (int i = 0; i < sources->n; i++) {
+
+        pmSource *source = sources->data[i];
+
+        if (!(source->mode & PM_SOURCE_MODE_PSFSTAR)) continue;
+
+        // which model to use?
+        pmModel *model = pmSourceGetModel (&isPSF, source);
+        if (model == NULL) continue;  // model must be defined
+
+        psImage *image  = psImageCopy (NULL, source->pixels,   PS_TYPE_F32);
+        psImage *weight = psImageCopy (NULL, source->weight,   PS_TYPE_F32);
+        psImage *mask   = psImageCopy (NULL, source->maskView, PS_TYPE_U8);
+        pmModelSub (image, mask, model, PM_MODEL_OP_FUNC, maskVal);
+
+        // re-normalize image and weight
+        float Io = model->params->data.F32[PM_PAR_I0];
+        psBinaryOp (image, image, "/", psScalarAlloc(Io, PS_TYPE_F32));
+        psBinaryOp (weight, weight, "/", psScalarAlloc(Io*Io, PS_TYPE_F32));
+
+        // we will interpolate the image and weight - include the mask or not?
+        // XXX consider better values for the mask bits
+        psImageInterpolateOptions *interp =
+            psImageInterpolateOptionsAlloc(mode, image, weight, NULL, 0xff, 0.0, 0.0, badMask, poorMask, 0.0);
+        psArrayAdd (input,  100, interp);
+
+        // save the X,Y position for future reference
+        xC->data.F32[xC->n] = model->params->data.F32[PM_PAR_XPOS];
+        yC->data.F32[yC->n] = model->params->data.F32[PM_PAR_YPOS];
+        psVectorExtend (xC, 100, 1);
+        psVectorExtend (yC, 100, 1);
+
+        xSize = PS_MAX (xSize, image->numCols);
+        ySize = PS_MAX (ySize, image->numRows);
+
+        // free up the excess references
+        psFree (mask);
+        psFree (image);
+        psFree (weight);
+        psFree (interp);
+    }
+    pmResiduals *resid = pmResidualsAlloc (xSize, ySize, xBin, yBin);
+
+    // x(resid) = (x(image) - Xo)*xBin + xCenter
+
+    psVector *fluxes  = psVectorAlloc (input->n, PS_TYPE_F32);
+    psVector *dfluxes = psVectorAlloc (input->n, PS_TYPE_F32);
+    psVector *fmasks  = psVectorAlloc (input->n, PS_TYPE_U8);
+
+    // statistic to use to determine baseline for clipping
+    psStats *fluxClip     = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
+    psStats *fluxClipDef  = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
+    // statistic to use to determine output flux
+    // XXX make API to convert statOption for MEAN/MEDIAN in to corresponding STDEV?
+    psStats *fluxStats    = psStatsAlloc (statOption | PS_STAT_SAMPLE_STDEV);
+    psStats *fluxStatsDef = psStatsAlloc (statOption | PS_STAT_SAMPLE_STDEV);
+
+    // Use psF64 to minimize overflow problems?
+    psImage *A = psImageAlloc(3, 3, PS_TYPE_F64); // Least-squares matrix
+    psVector *B = psVectorAlloc(3, PS_TYPE_F64); // Least-squares vector
+
+    // Solve MODEL = R + x R_x + y R_y in pixel-by-pixel a least-squares sense
+    // (If SPATIAL_ORDER == 0, just solve MODEL = R)
+    for (int oy = 0; resid != NULL && oy < resid->Ro->numRows; oy++) {
+        for (int ox = 0; ox < resid->Ro->numCols; ox++) {
+
+	    int nGoodPixel = 0;              // pixel is off the image
+    
+            // build the vector of data values for this output pixel
+            for (int i = 0; i < input->n; i++) {
+
+                psImageInterpolateOptions *interp = input->data[i];
+
+                // fractional image position
+                float ix = (ox + 0.5 - resid->xCenter) / (float) xBin + xC->data.F32[i] - interp->image->col0;
+                float iy = (oy + 0.5 - resid->yCenter) / (float) yBin + yC->data.F32[i] - interp->image->row0;
+
+                mflux = 0;
+                bool offImage = false;
+                if (psImageInterpolate (&flux, &dflux, &mflux, ix, iy, interp) == PS_INTERPOLATE_STATUS_OFF) {
+                    // This pixel is off the image
+                    offImage = true;
+		    fmasks->data.U8[i] = 1;
+		    // fprintf (stderr, "off image: %f %f : %f %f\n", ix, iy, flux, dflux);
+                } 
+                fluxes->data.F32[i] = flux;
+                dfluxes->data.F32[i] = dflux;
+                fmasks->data.U8[i] = mflux;
+		if (isnan(flux)) { 
+		    fmasks->data.U8[i] = 1;
+		}
+		if (fmasks->data.U8[i] == 0) {
+		    nGoodPixel ++;
+		}            
+	    }
+
+	    // skip pixels which are off the image...
+	    bool validPixel = (SPATIAL_ORDER == 0) ? (nGoodPixel > 1) : (nGoodPixel > 3);
+            if (!validPixel) {
+                resid->Ro->data.F32[oy][ox] = 0.0;
+                resid->Rx->data.F32[oy][ox] = 0.0;
+		resid->Ry->data.F32[oy][ox] = 0.0;
+		resid->mask->data.U8[oy][ox] = 1;
+		continue;
+            }
+
+            // measure the robust median to determine a baseline reference value
+            *fluxClip = *fluxClipDef;
+            psVectorStats (fluxClip, fluxes, NULL, fmasks, 0xff);
+            psErrorClear();             // clear (ignore) any outstanding errors
+
+            // mark input pixels which are more than N sigma from the median
+            for (int i = 0; i < fluxes->n; i++) {
+                float delta = fluxes->data.F32[i] - fluxClip->robustMedian;
+                float sigma = sqrt (dfluxes->data.F32[i]);
+                float swing = fabs(delta) / sigma;
+
+                // make this a user option
+                if (swing > nSigma) {
+                    fmasks->data.U8[i] = clippedMask;
+                }
+            }
+
+            if (SPATIAL_ORDER == 0) {
+                // measure the desired statistic on the unclipped pixels
+                *fluxStats = *fluxStatsDef;
+                psVectorStats (fluxStats, fluxes, NULL, fmasks, 0xff);
+                psErrorClear();         // clear (ignore) any outstanding errors
+
+                resid->Ro->data.F32[oy][ox] = psStatsGetValue(fluxStats, statOption);
+                resid->Rx->data.F32[oy][ox] = resid->Ry->data.F32[oy][ox] = 0.0;
+                //resid->weight->data.F32[oy][ox] = fluxStats->sampleStdev;
+
+		if (resid->Ro->data.F32[oy][ox] < pixelSN*fluxStats->sampleStdev) {
+		  resid->mask->data.U8[oy][ox] = 1;
+		}
+
+            } else {
+                assert (SPATIAL_ORDER == 1);
+                psImageInit(A, 0.0);
+                psVectorInit(B, 0.0);
+                for (int i = 0; i < fluxes->n; i++) {
+                    if (fmasks->data.U8[i]) continue;
+                    B->data.F64[0] += fluxes->data.F32[i]/dfluxes->data.F32[i];
+                    B->data.F64[1] += fluxes->data.F32[i]*xC->data.F32[i]/dfluxes->data.F32[i];
+                    B->data.F64[2] += fluxes->data.F32[i]*yC->data.F32[i]/dfluxes->data.F32[i];
+
+                    A->data.F64[0][0] += 1.0/dfluxes->data.F32[i];
+                    A->data.F64[1][0] += xC->data.F32[i]/dfluxes->data.F32[i];
+                    A->data.F64[2][0] += yC->data.F32[i]/dfluxes->data.F32[i];
+
+                    A->data.F64[1][1] += PS_SQR(xC->data.F32[i])/dfluxes->data.F32[i];
+                    A->data.F64[2][2] += PS_SQR(yC->data.F32[i])/dfluxes->data.F32[i];
+                    A->data.F64[1][2] += xC->data.F32[i]*yC->data.F32[i]/dfluxes->data.F32[i];
+                }
+
+                A->data.F64[0][1] = A->data.F64[1][0];
+                A->data.F64[0][2] = A->data.F64[2][0];
+                A->data.F64[2][1] = A->data.F64[1][2];
+
+                if (!psMatrixGJSolve(A, B)) {
+                    psError(PSPHOT_ERR_PSF, false, "Singular matrix solving for (y,x) = (%d,%d)'s residuals",
+                            oy, ox);
+                    psFree(resid); resid = NULL;
+                    break;
+                }
+
+                resid->Ro->data.F32[oy][ox] = B->data.F64[0];
+                resid->Rx->data.F32[oy][ox] = B->data.F64[1];
+                resid->Ry->data.F32[oy][ox] = B->data.F64[2];
+
+		float dRo = sqrt(A->data.F32[0][0]);
+		if (resid->Ro->data.F32[oy][ox] < pixelSN*dRo) {
+		  resid->mask->data.U8[oy][ox] = 1;
+		}
+                //resid->weight->data.F32[oy][ox] = XXX;
+            }
+        }
+    }
+
+    psFree (A);
+    psFree (B);
+
+    psLogMsg ("psphot.pspsf", PS_LOG_INFO, "generate residuals for %ld objects: %f sec\n", input->n, psTimerMark ("residuals"));
+
+    psFree (xC);
+    psFree (yC);
+    psFree (input);
+
+    psFree (fluxes);
+    psFree (dfluxes);
+    psFree (fmasks);
+
+    psFree (fluxStats);
+    psFree (fluxStatsDef);
+    psFree (fluxClip);
+    psFree (fluxClipDef);
+
+    if (resid != NULL && psTraceGetLevel("psphot") > 5) {
+      psphotSaveImage (NULL, resid->Ro,     "resid.ro.fits");
+      psphotSaveImage (NULL, resid->Rx,     "resid.rx.fits");
+      psphotSaveImage (NULL, resid->Ry,     "resid.ry.fits");
+      psphotSaveImage (NULL, resid->weight, "resid.wt.fits");
+      psphotSaveImage (NULL, resid->mask,   "resid.mk.fits");
+    }
+
+    psf->residuals = resid;
+    return (resid != NULL) ? true : false;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMaskReadout.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMaskReadout.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMaskReadout.c	(revision 22158)
@@ -0,0 +1,55 @@
+# include "psphotInternal.h"
+
+// generate mask and weight if not defined, additional mask for restricted subregion 
+bool psphotSetMaskAndWeight (pmConfig *config, pmReadout *readout, psMetadata *recipe) {
+
+    bool status;
+
+    // ** Interpret the mask values:
+    // XXX drop the write to recipe and move config into psphotRoughClass?
+    // XXX alternatively, define a function to set the psphot recipe masks
+    psMaskType maskSat  = pmConfigMaskGet("SAT", config); // Mask value for saturated pixels
+    psMetadataAddU8 (recipe, PS_LIST_TAIL, "MASK.SAT", PS_META_REPLACE, "user-defined mask", maskSat);
+
+    psMaskType maskBad  = pmConfigMaskGet("BAD", config); // Mask value for bad pixels
+    psMetadataAddU8 (recipe, PS_LIST_TAIL, "MASK.BAD", PS_META_REPLACE, "user-defined mask", maskBad);
+
+    // generate mask & weight images if they don't already exit
+    if (!readout->mask) {
+        if (!pmReadoutGenerateMask(readout, maskSat, maskBad)) {
+            psError (PSPHOT_ERR_CONFIG, false, "trouble creating mask");
+            return false;
+        }
+    }
+    if (!readout->weight) {
+        if (!pmReadoutGenerateWeight(readout, true)) {
+            psError (PSPHOT_ERR_CONFIG, false, "trouble creating weight");
+            return false;
+        }
+    }
+
+    // mask the excluded outer pixels
+    // these coordinates refer to the parent image
+    // these bounds will saturate on the subimage
+    // negative upper bounds will subtract from the *subimage*
+    float XMIN  = psMetadataLookupF32 (&status, recipe, "XMIN");
+    float XMAX  = psMetadataLookupF32 (&status, recipe, "XMAX");
+    float YMIN  = psMetadataLookupF32 (&status, recipe, "YMIN");
+    float YMAX  = psMetadataLookupF32 (&status, recipe, "YMAX");
+    psRegion valid = psRegionSet (XMIN, XMAX, YMIN, YMAX);
+
+    // restrict the supplied region above to the valid area on the image
+    psRegion keep = psRegionForImage (readout->image, valid);
+
+    // psImageKeepRegion assumes the region refers to the parent coordinates
+    psImageKeepRegion (readout->mask, keep, "OR", maskBad);
+
+    // test output of files at this stage
+    if (psTraceGetLevel("psphot") >= 5) {
+        psphotSaveImage (NULL, readout->image,  "image.fits");
+        psphotSaveImage (NULL, readout->mask,   "mask.fits");
+        psphotSaveImage (NULL, readout->weight, "weight.fits");
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMergeSources.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMergeSources.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMergeSources.c	(revision 22158)
@@ -0,0 +1,52 @@
+# include "psphotInternal.h"
+
+// add newly selected sources to the existing list of sources
+bool psphotMergeSources (psArray *oldSources, psArray *newSources) {
+
+    for (int i = 0; i < newSources->n; i++) {
+        pmSource *source = newSources->data[i];
+        psArrayAdd (oldSources, 100, source);
+    }
+    return true;
+}
+
+// merge the externally supplied sources with the existing sources.  mark them as having
+// mode PM_SOURCE_MODE_EXTERNAL
+bool psphotLoadExtSources (pmConfig *config, const pmFPAview *view, psArray *sources) {
+
+    // find the currently selected readout
+    pmReadout  *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT.CMF");
+    if (!readout) {
+        psLogMsg ("psphot", 3, "no external sources supplied");
+        return true;
+    }
+
+    psArray *extSources = psMetadataLookupPtr (NULL, readout->analysis, "PSPHOT.SOURCES");
+    if (!extSources) {
+        psLogMsg ("psphot", 3, "no external sources for this readout");
+        return true;
+    }
+
+    for (int i = 0; i < extSources->n; i++) {
+        pmSource *source = extSources->data[i];
+        source->mode |= PM_SOURCE_MODE_EXTERNAL;
+        pmModel *model = source->modelPSF;
+
+        float xpos = model->params->data.F32[PM_PAR_XPOS];
+        float ypos = model->params->data.F32[PM_PAR_YPOS];
+
+        source->peak = pmPeakAlloc(xpos, ypos, 1.0, PM_PEAK_LONE);
+        source->peak->xf = xpos;
+        source->peak->yf = ypos;
+        source->peak->flux = 1.0;
+
+        // drop the loaded source modelPSF
+        psFree (source->modelPSF);
+        source->modelPSF = NULL;
+    }
+
+    psphotMergeSources (sources, extSources);
+    psLogMsg ("psphot", 3, "%ld external sources merged to yield %ld total sources", extSources->n, sources->n);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotModelBackground.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotModelBackground.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotModelBackground.c	(revision 22158)
@@ -0,0 +1,320 @@
+# include "psphotInternal.h"
+static int npass = 0;
+
+// generate the median in NxN boxes, clipping heavily
+// linear interpolation to generate full-scale model
+bool psphotModelBackground (pmConfig *config, const pmFPAview *view, const char *filename)
+{
+    bool status = true;
+    static char *defaultStatsName = "FITTED_MEAN";
+
+    psTimerStart ("psphot");
+
+    // find the currently selected readout
+    pmFPAfile *file = psMetadataLookupPtr (&status, config->files, filename);
+    pmFPA *inFPA = file->fpa;
+    pmReadout *readout = pmFPAviewThisReadout (view, inFPA);
+    psImage *image = readout->image;
+    psImage *mask  = readout->mask;
+
+    // select the appropriate recipe information
+    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
+    assert (recipe);
+
+    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
+    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
+    assert (maskVal);
+
+    // user supplied seed, if available
+    unsigned long seed = psMetadataLookupS32 (&status, recipe, "IMSTATS_SEED");
+    if (!status) {
+        seed = 0;
+    }
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, seed);
+
+    // subtract this amount extra from the sky
+    float SKY_BIAS = psMetadataLookupF32 (&status, recipe, "SKY_BIAS");
+    if (!status) {
+        SKY_BIAS = 0;
+    }
+
+    // supply the sky background statistics options
+    char *statsName = psMetadataLookupStr (&status, recipe, "SKY_STAT");
+    if (statsName == NULL) {
+        statsName = defaultStatsName;
+    }
+    psStatsOptions statsOptionLocation = psStatsOptionFromString(statsName);
+    if (!(statsOptionLocation & (PS_STAT_SAMPLE_MEAN |
+                                 PS_STAT_SAMPLE_MEDIAN |
+                                 PS_STAT_ROBUST_MEDIAN |
+                                 PS_STAT_ROBUST_QUARTILE |
+                                 PS_STAT_CLIPPED_MEAN |
+                                 PS_STAT_FITTED_MEAN |
+                                 PS_STAT_FITTED_MEAN_V2 |
+                                 PS_STAT_FITTED_MEAN_V3 |
+                                 PS_STAT_FITTED_MEAN_V4))) {
+        statsOptionLocation = PS_STAT_FITTED_MEAN;
+    }
+
+    psStatsOptions statsOptionWidth = PS_STAT_NONE;
+    if (statsOptionLocation & (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN)) {
+        statsOptionWidth = PS_STAT_SAMPLE_STDEV;
+    } else if (statsOptionLocation & (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_QUARTILE)) {
+#if 1
+        statsOptionWidth = PS_STAT_ROBUST_STDEV; // not set; => NaN
+#else
+        statsOptionWidth = PS_STAT_FITTED_STDEV;
+#endif
+    } else if (statsOptionLocation & PS_STAT_FITTED_MEAN) {
+        statsOptionWidth = PS_STAT_FITTED_STDEV;
+    } else if (statsOptionLocation & PS_STAT_CLIPPED_MEAN) {
+        statsOptionWidth = PS_STAT_CLIPPED_STDEV;
+    } else if (statsOptionLocation & PS_STAT_FITTED_MEAN_V2) {
+        statsOptionWidth = PS_STAT_FITTED_STDEV_V2;
+    } else if (statsOptionLocation & PS_STAT_FITTED_MEAN_V3) {
+        statsOptionWidth = PS_STAT_FITTED_STDEV_V3;
+    } else if (statsOptionLocation & PS_STAT_FITTED_MEAN_V4) {
+        statsOptionWidth = PS_STAT_FITTED_STDEV_V4;
+    } else {
+        psAbort("Unable to estimate variance of selected statsOptionLocations 0x%x", statsOptionLocation);
+    }
+
+    const psStatsOptions statsOption = statsOptionLocation | statsOptionWidth;
+    psStats *stats = psStatsAlloc (statsOption);
+
+    // set range for old-version of sky statistic
+    if (statsOptionLocation & PS_STAT_ROBUST_QUARTILE) {
+        stats->min = 0.25;
+        stats->max = 0.75;
+    }
+
+    // set user-option for number of pixels per region
+    stats->nSubsample = psMetadataLookupF32 (&status, recipe, "IMSTATS_NPIX");
+    if (!status) {
+        stats->nSubsample = 1000;
+    }
+
+    // optionally set the binsize
+    stats->binsize = psMetadataLookupF32 (&status, recipe, "SKY_HISTOGRAM_BINS");
+    if (status) {
+        stats->options |= PS_STAT_USE_BINSIZE;
+    }
+
+    // optionally set the sigma clipping
+    stats->clipSigma = psMetadataLookupF32 (&status, recipe, "SKY_CLIP_SIGMA");
+    if (!status) {
+        if ((stats->options & PS_STAT_FITTED_MEAN) || (stats->options & PS_STAT_FITTED_MEAN_V2)) {
+            stats->clipSigma = 1.0;
+        } else {
+            stats->clipSigma = 3.0;
+        }
+    }
+
+    // stats is not initialized by psStats???  use this to save the input options
+    // XXX re-work this to use the new psStatsInit function
+    psStats *statsDefaults = psStatsAlloc (statsOption);
+    *statsDefaults = *stats;
+
+    // I have the fine image size, I know the binning factor, determine the ruff image size
+    psImageBinning *binning = psImageBinningAlloc();
+    binning->nXfine = image->numCols;
+    binning->nYfine = image->numRows;
+    binning->nXbin  = psMetadataLookupS32 (&status, recipe, "BACKGROUND.XBIN");
+    binning->nYbin  = psMetadataLookupS32 (&status, recipe, "BACKGROUND.YBIN");
+
+    psImageBinningSetRuffSize(binning, PS_IMAGE_BINNING_CENTER);
+    psImageBinningSetSkip(binning, image);
+    status = psMetadataAddPtr(recipe, PS_LIST_TAIL, "PSPHOT.BACKGROUND.BINNING", PS_DATA_UNKNOWN | PS_META_REPLACE, "Background binning", binning);
+    PS_ASSERT (status, false);
+
+    // we save the binning structure for use in psphotMagnitudes
+    pmReadout *model      = pmFPAGenerateReadout (config, view, "PSPHOT.BACKMDL",       inFPA, binning);
+    pmReadout *modelStdev = pmFPAGenerateReadout (config, view, "PSPHOT.BACKMDL.STDEV", inFPA, binning);
+
+    psF32 **modelData = model->image->data.F32;
+    psF32 **modelStdevData = modelStdev->image->data.F32;
+
+    // XXXX we can thread this here by running blocks in parallel
+
+    // measure clipped median for subimages
+    psRegion ruffRegion = {0,0,0,0};
+    psRegion fineRegion = {0,0,0,0};
+    for (int iy = 0; iy < model->image->numRows; iy++) {
+        for (int ix = 0; ix < model->image->numCols; ix++) {
+
+            // convert the ruff grid cell to the equivalent fine grid cell
+            // XXX we need to watch out for row0,col0
+            ruffRegion = psRegionSet (ix, ix + 2, iy, iy + 2);
+            fineRegion = psImageBinningSetFineRegion (binning, ruffRegion);
+            fineRegion = psRegionForImage (image, fineRegion);
+
+            psImage *subset  = psImageSubset (image, fineRegion);
+            if (!subset->numCols || !subset->numRows) {
+                psFree (subset);
+                continue;
+            }
+            psImage *submask = psImageSubset (mask, fineRegion);
+
+            // reset the default values
+            *stats = *statsDefaults;
+
+            // Use the selected background statistic for the first pass
+            // If it fails, fall back on the "ROBUST_MEDIAN" version
+            // If both fail, set the pixel to NAN and (below) interpolate
+            // XXX psImageBackground will probably be renamed psImageStats
+            // XXX don't bother trying if there are no valid pixels...
+
+            psVector *sample = NULL;
+
+            // turn on stats tracing in desired cells
+            # if (0)
+            psMetadata *plots = psMetadataLookupPtr (&status, recipe, "DIAGNOSTIC.PLOTS");
+            assert (plots);
+
+            int xPlot = psMetadataLookupS32 (&status, plots, "IMAGE.BACKGROUND.CELL.HISTOGRAM.X");
+            assert (status);
+            int yPlot = psMetadataLookupS32 (&status, plots, "IMAGE.BACKGROUND.CELL.HISTOGRAM.Y");
+            assert (status);
+
+            bool gotX = (xPlot < 0) || (xPlot == ix);
+            bool gotY = (yPlot < 0) || (yPlot == iy);
+
+            if (gotX && gotY) {
+                psTraceSetLevel ("psLib.math.vectorFittedStats_v4", 6);
+                psTraceSetLevel ("psLib.math.vectorRobustStats", 6);
+            } else {
+                psTraceSetLevel ("psLib.math.vectorFittedStats_v4", 0);
+                psTraceSetLevel ("psLib.math.vectorRobustStats", 0);
+            }
+            # endif
+
+            if (psImageBackground(stats, &sample, subset, submask, maskVal, rng)) {
+                if (stats->options & PS_STAT_ROBUST_QUARTILE) {
+                    modelData[iy][ix] = stats->robustMedian;
+                } else {
+                    modelData[iy][ix] = psStatsGetValue(stats, statsOptionLocation);
+                }
+                modelStdevData[iy][ix] = psStatsGetValue(stats, statsOptionWidth);
+
+                // supply sample to plotting routing
+                psphotDiagnosticPlots (config, "IMAGE.BACKGROUND.CELL.HISTOGRAM", ix, iy, modelData[iy][ix], modelStdevData[iy][ix], sample);
+            } else {
+                psStatsOptions currentOptions = stats->options;
+                stats->options = PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV;
+                if (!psImageBackground(stats, &sample, subset, submask, maskVal, rng)) {
+                    psLogMsg ("psphot", PS_LOG_WARN, "Failed to estimate background using ROBUST_MEDIAN for "
+                               "(%dx%d, (row0,col0) = (%d,%d)",
+                               subset->numRows, subset->numCols, subset->row0, subset->col0);
+                    modelData[iy][ix] = modelStdevData[iy][ix] = NAN;
+                } else {
+                    modelData[iy][ix] = psStatsGetValue (stats, PS_STAT_ROBUST_MEDIAN);
+                    modelStdevData[iy][ix] = psStatsGetValue(stats, PS_STAT_ROBUST_STDEV);
+
+                    // supply sample to plotting routing
+                    psphotDiagnosticPlots (config, "IMAGE.BACKGROUND.CELL.HISTOGRAM", ix, iy, modelData[iy][ix], modelStdevData[iy][ix], sample);
+                }
+                // drop errors caused by psImageBackground failures
+                // XXX we probably should trap and exit on serious failures
+                psErrorClear();
+                stats->options = currentOptions;
+            }
+            psFree(sample);
+            modelData[iy][ix] += SKY_BIAS;
+            psFree (subset);
+            psFree (submask);
+        }
+    }
+
+    if (psTraceGetLevel("psphot") > 5) {
+        char name[256];
+        sprintf (name, "backraw.%02d.fits", npass);
+        psphotSaveImage (NULL, model->image, name);
+    }
+
+    // patch over bad regions (use average of 8 possible neighbor pixels)
+    // XXX consider testing all pixels against the 8 neighbors and replacing outliers...
+    double Count = 0;                   // number of good pixels
+    double Value = 0;                   // sum of good pixel's value
+    double ValueStdev = 0;              // sum of good pixel's standard deviations
+    for (int iy = 0; iy < model->image->numRows; iy++) {
+        for (int ix = 0; ix < model->image->numCols; ix++) {
+            if (!isnan(modelData[iy][ix])) {
+                Value += modelData[iy][ix];
+                ValueStdev += modelStdevData[iy][ix];
+                Count++;
+                continue;
+            }
+
+            double value = 0;
+            double count = 0;
+            for (int jy = iy - 1; jy <= iy + 1; jy++) {
+                if (jy <   0) continue;
+                if (jy >= model->image->numRows) continue;
+                for (int jx = ix - 1; jx <= ix + 1; jx++) {
+                    if (!jx && !jy) continue;
+                    if (jx   <   0) continue;
+                    if (jx   >= model->image->numCols) continue;
+                    value += modelData[jy][jx];
+                    count += 1.0;
+                }
+            }
+            if (count > 0) modelData[iy][ix] = value / count;
+        }
+    }
+    if (Count == 0) {
+        psError (PSPHOT_ERR_DATA, true, "failed to build background image");
+        psFree(stats);
+        psFree(statsDefaults);
+        psFree(binning);
+        psFree(rng);
+        return false;
+    }
+
+    Value /= Count;
+    ValueStdev /= Count;
+
+    // patch over remaining bad regions (use global average)
+    for (int iy = 0; iy < model->image->numRows; iy++) {
+        for (int ix = 0; ix < model->image->numCols; ix++) {
+            if (!isnan(modelData[iy][ix])) continue;
+            modelData[iy][ix] = Value;
+            modelStdevData[iy][ix] = ValueStdev;
+        }
+    }
+
+    psLogMsg ("psphot", PS_LOG_MINUTIA, "build median image: %f sec\n", psTimerMark ("psphot"));
+
+    psMetadataAddF32(recipe, PS_LIST_TAIL, "SKY_MEAN", PS_META_REPLACE, "sky mean", Value);
+    psMetadataAddF32(recipe, PS_LIST_TAIL, "SKY_STDEV", PS_META_REPLACE, "sky stdev", ValueStdev);
+    psLogMsg ("psphot", PS_LOG_INFO, "image sky : mean %f stdev %f", Value, ValueStdev);
+
+    // measure image and background stats and save for later output
+    psStats *statsBck = psStatsAlloc (PS_STAT_SAMPLE_MEAN |
+                                      PS_STAT_SAMPLE_STDEV |
+                                      PS_STAT_MIN |
+                                      PS_STAT_MAX);
+    psImageStats (statsBck, model->image, NULL, 0);
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "MSKY_MN",
+                      PS_META_REPLACE, "sky model mean",          statsBck->sampleMean);
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "MSKY_SIG",
+                      PS_META_REPLACE, "sky model stdev",         statsBck->sampleStdev);
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "MSKY_MAX",
+                      PS_META_REPLACE, "sky model maximum value", statsBck->max);
+    psMetadataAddF32 (recipe, PS_LIST_TAIL, "MSKY_MIN",
+                      PS_META_REPLACE, "sky model minimum value", statsBck->min);
+    psMetadataAddS32 (recipe, PS_LIST_TAIL, "MSKY_NX",
+                      PS_META_REPLACE, "sky model size (x)",      model->image->numCols);
+    psMetadataAddS32 (recipe, PS_LIST_TAIL, "MSKY_NY",
+                      PS_META_REPLACE, "sky model size (y)",      model->image->numRows);
+    psLogMsg ("psphot", PS_LOG_INFO, "background sky : min %f mean %f max %f stdev %f",
+              statsBck->min, statsBck->sampleMean, statsBck->max, statsBck->sampleStdev);
+
+    psFree(stats);
+    psFree(statsBck);
+    psFree(statsDefaults);
+    psFree(binning);
+    psFree(rng);
+
+    npass ++;
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotModelGroupInit.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotModelGroupInit.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotModelGroupInit.c	(revision 22158)
@@ -0,0 +1,25 @@
+# include "psphotInternal.h"
+
+// Add locally-defined models here.  As these mature, they can be moved to 
+// psModule/src/objects/models
+
+# include "models/pmModel_TEST1.c"
+# include "models/pmModel_STRAIL.c"
+
+static pmModelClass userModels[] = {
+    {"PS_MODEL_TEST1", 7, pmModelFunc_TEST1,  pmModelFlux_TEST1,  pmModelRadius_TEST1,  pmModelLimits_TEST1,  pmModelGuess_TEST1, pmModelFromPSF_TEST1, pmModelParamsFromPSF_TEST1, pmModelFitStatus_TEST1},
+    {"PS_MODEL_STRAIL", 9, pmModelFunc_STRAIL,  pmModelFlux_STRAIL,  pmModelRadius_STRAIL,  pmModelLimits_STRAIL,  pmModelGuess_STRAIL, pmModelFromPSF_STRAIL, pmModelParamsFromPSF_STRAIL, pmModelFitStatus_STRAIL},
+};
+
+void psphotModelClassInit (void) 
+{ 
+
+    // if pmModelClassInit returns false, we have already init'ed
+    if (!pmModelClassInit ()) return;
+
+    int Nmodels = sizeof (userModels) / sizeof (pmModelClass);
+    for (int i = 0; i < Nmodels; i++) {
+	pmModelClassAdd (&userModels[i]);
+    }
+    return;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotModelTest.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotModelTest.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotModelTest.c	(revision 22158)
@@ -0,0 +1,250 @@
+# include "psphotInternal.h"
+# define PM_SOURCE_FIT_PSF_X_EXT PM_SOURCE_FIT_PSF_AND_SKY
+
+// XXX add more test information?
+bool psphotModelTest (pmConfig *config, const pmFPAview *view, psMetadata *recipe) {
+
+    bool status;
+    int modelType = -1;
+    float obsMag, fitMag, value;
+    char name[64];
+    pmPSF *psf = NULL;
+    pmSourceFitMode fitMode;
+
+    // bit-masks to test for good/bad pixels
+    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT");
+    assert (maskVal);
+
+    // bit-mask to mark pixels not used in analysis
+    psMaskType markVal = psMetadataLookupU8(&status, recipe, "MARK.PSPHOT");
+    assert (markVal);
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
+    // run model fitting tests on a single source?
+    if (!psMetadataLookupBool (&status, recipe, "TEST_FIT")) return false;
+
+    psTimerStart ("modelTest");
+
+    // find the currently selected readout
+    pmReadout  *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT");
+    PS_ASSERT_PTR_NON_NULL (readout, false);
+
+    // use poissonian errors or local-sky errors
+    bool POISSON_ERRORS = psMetadataLookupBool (&status, recipe, "POISSON_ERRORS");
+    if (!status) POISSON_ERRORS = true;
+    pmSourceFitModelInit (15, 0.1, 1.0, POISSON_ERRORS);
+
+    // find the various fitting parameters (try test values first)
+    float INNER = psMetadataLookupF32 (&status, recipe, "TEST_FIT_INNER_RADIUS");
+    if (!status || !isfinite(INNER)) {
+        INNER = psMetadataLookupF32 (&status, recipe, "SKY_INNER_RADIUS");
+    }
+    float OUTER = psMetadataLookupF32 (&status, recipe, "TEST_FIT_OUTER_RADIUS");
+    if (!status || !isfinite(OUTER)) {
+        OUTER = psMetadataLookupF32 (&status, recipe, "SKY_OUTER_RADIUS");
+    }
+    float RADIUS = psMetadataLookupF32 (&status, recipe, "TEST_FIT_RADIUS");
+    if (!status || !isfinite(RADIUS)) {
+        RADIUS = psMetadataLookupF32 (&status, recipe, "PSF_FIT_RADIUS");
+    }
+    float mRADIUS = psMetadataLookupF32 (&status, recipe, "TEST_MOMENTS_RADIUS");
+    if (!status || !isfinite(mRADIUS)) {
+        mRADIUS = psMetadataLookupF32 (&status, recipe, "PSF_MOMENTS_RADIUS");
+    }
+
+    // define the source of interest
+    float xObj     = psMetadataLookupF32 (&status, recipe, "TEST_FIT_X");
+    float yObj     = psMetadataLookupF32 (&status, recipe, "TEST_FIT_Y");
+    if (!isfinite(xObj) || !isfinite(yObj)) psAbort ("object position is not defined");
+
+    // what fitting mode to use?
+    fitMode = PM_SOURCE_FIT_EXT;
+    char *fitModeWord = psMetadataLookupStr (&status, recipe, "TEST_FIT_MODE");
+    if (fitModeWord && !strcasecmp (fitModeWord, "PSF")) fitMode = PM_SOURCE_FIT_PSF;
+    if (fitModeWord && !strcasecmp (fitModeWord, "CONV")) fitMode = PM_SOURCE_FIT_PSF_X_EXT;
+    if (fitModeWord && !strcasecmp (fitModeWord, "DEFAULT")) fitMode = PM_SOURCE_FIT_EXT;
+
+    // construct the source structures
+    pmSource *source = pmSourceAlloc();
+    source->peak = pmPeakAlloc (xObj, yObj, 0, 0);
+    pmSourceDefinePixels (source, readout, xObj, yObj, OUTER);
+
+    // in fitMode, psf sets the model type
+    if (fitMode == PM_SOURCE_FIT_PSF) {
+        psf = psphotLoadPSF (config, view, recipe);
+        if (!psf) psAbort("PSF_INPUT_FILE not supplied");
+        modelType = psf->type;
+        source->type = PM_SOURCE_TYPE_STAR;
+    }
+    if (fitMode == PM_SOURCE_FIT_EXT) {
+        // find the model: supplied by user or first in the PSF_MODEL list
+        char *modelName  = psMetadataLookupStr (&status, recipe, "TEST_FIT_MODEL");
+        if (!status || !strcasecmp (modelName, "DEFAULT")) {
+            // get the list pointers for the PSF_MODEL entries
+
+            psList *list = NULL;
+            psMetadataItem *mdi = psMetadataLookup (recipe, "PSF_MODEL");
+            if (mdi == NULL) psAbort("missing PSF_MODEL selection");
+            if (mdi->type == PS_DATA_STRING) {
+                list = psListAlloc(NULL);
+                psListAdd (list, PS_LIST_HEAD, mdi);
+            } else {
+                if (mdi->type != PS_DATA_METADATA_MULTI) psAbort("missing PSF_MODEL selection");
+                list = psMemIncrRefCounter(mdi->data.list);
+            }
+
+            // take the first list element
+            psMetadataItem *item = psListGet (list, PS_LIST_HEAD);
+            modelName = item->data.V;
+        }
+        modelType = pmModelClassGetType (modelName);
+        if (modelType < 0) psAbort("unknown model %s", modelName);
+        source->type = PM_SOURCE_TYPE_EXTENDED;
+    }
+    if (fitMode == PM_SOURCE_FIT_PSF_X_EXT) {
+        // we need to load BOTH a psf and an ext model
+        psf = psphotLoadPSF (config, view, recipe);
+        if (!psf) psAbort("PSF_INPUT_FILE not supplied");
+
+        // find the model: supplied by user or first in the PSF_MODEL list
+        char *modelName  = psMetadataLookupStr (&status, recipe, "TEST_FIT_MODEL");
+        if (!status || !strcasecmp (modelName, "DEFAULT")) {
+            // get the list pointers for the PSF_MODEL entries
+
+            psList *list = NULL;
+            psMetadataItem *mdi = psMetadataLookup (recipe, "PSF_MODEL");
+            if (mdi == NULL) psAbort("missing PSF_MODEL selection");
+            if (mdi->type == PS_DATA_STRING) {
+                list = psListAlloc(NULL);
+                psListAdd (list, PS_LIST_HEAD, mdi);
+            } else {
+                if (mdi->type != PS_DATA_METADATA_MULTI) psAbort("missing PSF_MODEL selection");
+                list = psMemIncrRefCounter(mdi->data.list);
+            }
+
+            // take the first list element
+            psMetadataItem *item = psListGet (list, PS_LIST_HEAD);
+            modelName = item->data.V;
+        }
+        modelType = pmModelClassGetType (modelName);
+        if (modelType < 0) psAbort("unknown model %s", modelName);
+        source->type = PM_SOURCE_TYPE_EXTENDED;
+    }
+
+    // find the local sky
+    status = pmSourceLocalSky (source, PS_STAT_SAMPLE_MEDIAN, INNER, maskVal, markVal);
+    if (!status) psAbort("pmSourceLocalSky error");
+
+    // get the source moments
+    status = pmSourceMoments (source, mRADIUS);
+    if (!status) psAbort("psSourceMoments error");
+    source->peak->value = source->moments->Peak;
+
+    fprintf (stderr, "sum: %f @ (%f, %f)\n", source->moments->Sum, source->moments->x, source->moments->y);
+    fprintf (stderr, "moments: %f, %f - %f\n", source->moments->Sx, source->moments->Sy, source->moments->Sxy);
+
+    psEllipseMoments moments;
+    moments.x2 = source->moments->Sx;
+    moments.y2 = source->moments->Sy;
+    moments.xy = source->moments->Sxy;
+    psEllipseAxes axes = psEllipseMomentsToAxes (moments, 20.0);
+
+    fprintf (stderr, "axes: %f @ (%f, %f)\n", axes.theta*180/M_PI, axes.major, axes.minor);
+
+    // get the initial model parameter guess
+    pmModel *model = pmSourceModelGuess (source, modelType);
+    source->modelEXT = model;
+
+    // if any parameters are defined by the user, take those values
+    int nParams = pmModelClassParameterCount (modelType);
+    psF32 *params = model->params->data.F32;
+    params[PM_PAR_XPOS] = xObj; // XXX use the user-supplied value,
+    params[PM_PAR_YPOS] = yObj; // XXX or use the centroid
+    for (int i = 0; i < nParams; i++) {
+        if (i == PM_PAR_XPOS) continue;
+        if (i == PM_PAR_YPOS) continue;
+
+        sprintf (name, "TEST_FIT_PAR%d", i);
+        value = psMetadataLookupF32 (&status, recipe, name);
+        if (status && isfinite (value)) {
+            params[i] = value;
+        }
+    }
+
+    float area = params[4]*params[5];
+    fprintf (stderr, "peak: %f @ (%f, %f)\n", source->moments->Sum*area, (double)source->peak->x, (double)source->peak->y);
+
+    // for PSF fitting, set the shape parameters based on the PSF & source position
+    if (fitMode == PM_SOURCE_FIT_PSF) {
+        source->modelPSF = pmModelFromPSF (model, psf);
+        psFree (model);
+        model = source->modelPSF;
+        params = model->params->data.F32;
+    }
+
+    // list model input shape
+    psEllipseShape shape;
+    shape.sx  = 1.4 / model->params->data.F32[4];
+    shape.sy  = 1.4 / model->params->data.F32[5];
+    shape.sxy = model->params->data.F32[6];
+    axes = psEllipseShapeToAxes (shape, 20.0);
+
+    fprintf (stderr, "guess: %f @ (%f, %f)\n", axes.theta*180/M_PI, axes.major, axes.minor);
+
+    fprintf (stderr, "input parameters: \n");
+    for (int i = 0; i < nParams; i++) {
+        fprintf (stderr, "%d : %f\n", i, params[i]);
+    }
+
+    // define the pixels used for the fit
+    psImageKeepCircle (source->maskObj, xObj, yObj, RADIUS, "OR", markVal);
+    psphotSaveImage (NULL, source->maskObj, "mask1.fits");
+
+    char *fitset = psMetadataLookupStr (&status, recipe, "TEST_FIT_SET");
+    if (status) {
+        status = psphotFitSet (source, model, fitset, fitMode, maskVal);
+        exit (0);
+    }
+
+    if (fitMode == PM_SOURCE_FIT_PSF_X_EXT) {
+        // build the psf for the object
+        source->modelPSF = pmModelFromPSF (model, psf);
+        source->modelEXT = model;
+
+	// what fraction of the PSF is used? (radius in pixels : 2 -> 5x5 box)
+	int psfSize = psMetadataLookupS32 (&status, recipe, "PCM_BOX_SIZE");
+	assert (status);
+
+        model = psphotPSFConvModel (readout, source, modelType, maskVal, markVal, psfSize);
+        params = model->params->data.F32;
+    } else {
+        status = pmSourceFitModel (source, model, fitMode, maskVal);
+    }
+
+    // measure the source mags
+    pmSourcePhotometryModel (&fitMag, model);
+    pmSourcePhotometryAper  (&obsMag, model, source->pixels, source->maskObj, maskVal);
+    fprintf (stderr, "ap: %f, fit: %f, apmifit: %f, nIter: %d\n", obsMag, fitMag, obsMag - fitMag, model->nIter);
+
+    // write out positive object
+    psphotSaveImage (NULL, source->pixels, "object.fits");
+
+    // subtract object, leave local sky
+    // pmModelSub (source->pixels, source->maskObj, model, PM_MODEL_OP_FULL, maskVal);
+    pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
+
+    fprintf (stderr, "output parameters: \n");
+    for (int i = 0; i < nParams; i++) {
+        fprintf (stderr, "%d : %f\n", i, params[i]);
+    }
+
+    // write out
+    psphotSaveImage (NULL, source->pixels, "resid.fits");
+    psphotSaveImage (NULL, source->maskObj, "mask.fits");
+
+    psLogMsg ("psphot", PS_LOG_INFO, "model test : %f sec\n", psTimerMark ("modelTest"));
+
+    exit (0);
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotModelWithPSF.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotModelWithPSF.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotModelWithPSF.c	(revision 22158)
@@ -0,0 +1,417 @@
+# include "psphotInternal.h"
+# define SAVE_IMAGES 0
+
+bool psphotModelWithPSF_LMM (
+    psMinimization *min,
+    psImage *covar,
+    psVector *params,
+    psMinConstraint *constraint,
+    pmSource *source,
+    const psKernel *psf,
+    psMinimizeLMChi2Func func)
+{
+    psTrace("psphot", 3, "---- begin ----\n");
+    PS_ASSERT_PTR_NON_NULL(min, false);
+    PS_ASSERT_VECTOR_NON_NULL(params, false);
+    PS_ASSERT_VECTOR_NON_EMPTY(params, false);
+    PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32, false);
+    psVector *paramMask = NULL;
+    if (constraint != NULL) {
+        paramMask = constraint->paramMask;
+        if (paramMask != NULL) {
+            PS_ASSERT_VECTOR_TYPE(paramMask, PS_TYPE_U8, false);
+            PS_ASSERT_VECTORS_SIZE_EQUAL(params, paramMask, false);
+        }
+    }
+    PS_ASSERT_PTR_NON_NULL(func, false);
+    PS_ASSERT_PTR_NON_NULL(source, false);
+
+    psMinimizeLMLimitFunc checkLimits = NULL;
+    if (constraint) {
+        checkLimits = constraint->checkLimits;
+    }
+
+    // this function has test values and current values for several things
+    // the current value is in lower case
+    // the test value is in upper case
+
+    // allocate internal arrays (current vs Guess)
+    psImage *Alpha = NULL;
+    psVector *Beta = NULL;
+
+    // Alpha & Beta only contain elements to represent the unmasked parameters
+    if (!psMinLM_AllocAB (&Alpha, &Beta, params, paramMask)) {
+	psAbort ("programming error: no unmasked parameters to be fit\n");
+    }
+    
+    // allocate internal arrays (current vs Guess)
+    psImage *alpha   = psImageAlloc(Alpha->numCols, Alpha->numRows, PS_TYPE_F32);
+    psVector *beta   = psVectorAlloc(Beta->n, PS_TYPE_F32);
+    psVector *Params = psVectorAlloc(params->n, PS_TYPE_F32);
+
+    psF32 Chisq = 0.0;
+    psF32 lambda = 0.001;
+    psF32 dLinear = 0.0;
+
+    // generate PCM data storage structure
+    pmPCMData *pcm = pmPCMDataAlloc (params, paramMask, source);
+
+    // calculate initial alpha and beta, set chisq (min->value)
+    min->value = psphotModelWithPSF_SetABX(alpha, beta, params, paramMask, pcm, source, psf, func);
+    if (isnan(min->value)) {
+        min->iter = min->maxIter;
+        return(false);
+    }
+    // dump some useful info if trace is defined
+    if (psTraceGetLevel("psphot") >= 6) {
+        p_psImagePrint(psTraceGetDestination(), alpha, "alpha guess (0)");
+        p_psVectorPrint(psTraceGetDestination(), beta, "beta guess (0)");
+    }
+    if (psTraceGetLevel("psphot") >= 5) {
+        p_psVectorPrint(psTraceGetDestination(), params, "params guess (0)");
+    }
+
+    // iterate until the tolerance is reached, or give up
+    while ((min->iter < min->maxIter) && ((min->lastDelta > min->tol) || !isfinite(min->lastDelta))) {
+        psTrace("psphot", 5, "Iteration number %d.  (max iterations is %d).\n", min->iter, min->maxIter);
+        psTrace("psphot", 5, "Last delta is %f.  Min->tol is %f.\n", min->lastDelta, min->tol);
+
+
+        // set a new guess for Alpha, Beta, Params
+        if (!psMinLM_GuessABP(Alpha, Beta, Params, alpha, beta, params, paramMask, checkLimits, lambda, &dLinear)) {
+            min->iter ++;
+            lambda *= 10.0;
+            continue;
+        }
+
+        // dump some useful info if trace is defined
+        if (psTraceGetLevel("psphot") >= 6) {
+            p_psImagePrint(psTraceGetDestination(), Alpha, "Alpha guess (1)");
+            p_psVectorPrint(psTraceGetDestination(), Beta, "Beta guess (1)");
+            p_psVectorPrint(psTraceGetDestination(), beta, "beta current (1)");
+        }
+        if (psTraceGetLevel("psphot") >= 5) {
+            p_psVectorPrint(psTraceGetDestination(), Params, "params guess (1)");
+        }
+
+        // calculate Chisq for new guess, update Alpha & Beta
+        Chisq = psphotModelWithPSF_SetABX(Alpha, Beta, Params, paramMask, pcm, source, psf, func);
+        if (isnan(Chisq)) {
+            min->iter ++;
+            lambda *= 10.0;
+            continue;
+        }
+
+        // convergence criterion:
+        // compare the delta (min->value - Chisq) with the
+        // expected delta from the linear model (dLinear)
+        // accept new guess if it is an improvement (rho > 0), or else increase lambda
+        psF32 rho = (min->value - Chisq) / dLinear;
+
+        psTrace("psphot", 5, "last chisq: %f, new chisq %f, delta: %f, rho: %f\n", min->value,
+                Chisq, min->lastDelta, rho);
+
+        // dump some useful info if trace is defined
+        if (psTraceGetLevel("psphot") >= 6) {
+            p_psImagePrint(psTraceGetDestination(), Alpha, "alpha guess (2)");
+            p_psVectorPrint(psTraceGetDestination(), Beta, "beta guess (2)");
+        }
+
+        /* if (Chisq < min->value) {  */
+        if (rho > 0.0) {
+            min->lastDelta = (min->value - Chisq) / (source->pixels->numCols*source->pixels->numRows - params->n);
+            min->value = Chisq;
+            alpha  = psImageCopy(alpha, Alpha, PS_TYPE_F32);
+            beta   = psVectorCopy(beta, Beta, PS_TYPE_F32);
+            params = psVectorCopy(params, Params, PS_TYPE_F32);
+            lambda *= 0.25;
+
+	    // save the new convolved model image
+	    psFree (source->modelFlux);
+	    source->modelFlux = pmPCMDataSaveImage(pcm);
+        } else {
+            lambda *= 10.0;
+        }
+        min->iter++;
+    }
+    psTrace("psphot", 5, "chisq: %f, last delta: %f, Niter: %d\n", min->value, min->lastDelta, min->iter);
+
+    // construct & return the covariance matrix (if requested)
+    if (covar != NULL) {
+        if (!psMinLM_GuessABP(Alpha, Beta, Params, alpha, beta, params, paramMask, NULL, 0.0, NULL)) {
+            psTrace ("psphot", 5, "failure to calculate covariance matrix\n");
+        }
+	// set covar values which are not masked
+	psImageInit (covar, 0.0);
+	for (int j = 0, J = 0; j < params->n; j++) {
+	    if (paramMask && (paramMask->data.U8[j])) {
+		covar->data.F32[j][j] = 1.0;
+		continue;
+	    }
+	    for (int k = 0, K = 0; k < params->n; k++) {
+		if (paramMask && (paramMask->data.U8[k])) continue;
+		covar->data.F32[j][k] = Alpha->data.F32[J][K];
+		K++;
+	    }
+	    J++;
+	}
+    }
+
+    // free the internal temporary data
+    psFree(alpha);
+    psFree(Alpha);
+    psFree(beta);
+    psFree(Beta);
+    psFree(Params);
+    psFree(pcm);
+
+    if (min->iter == min->maxIter) {
+        psTrace("psphot", 3, "---- end (false) ----\n");
+        return(false);
+    }
+
+    psTrace("psphot", 3, "---- end (true) ----\n");
+    return(true);
+}
+
+psF32 psphotModelWithPSF_SetABX(
+    psImage  *alpha,
+    psVector *beta,
+    const psVector *params,
+    const psVector *paramMask,
+    pmPCMData *pcm,
+    const pmSource *source,
+    const psKernel *psf,
+    psMinimizeLMChi2Func func)
+{
+    // XXX: Check vector sizes.
+    PS_ASSERT_IMAGE_NON_NULL(alpha, NAN);
+    PS_ASSERT_VECTOR_NON_NULL(beta, NAN);
+    PS_ASSERT_VECTOR_NON_NULL(params, NAN);
+
+    PS_ASSERT_PTR_NON_NULL(source, NAN);
+    PS_ASSERT_IMAGE_NON_NULL(source->pixels, NAN);
+    PS_ASSERT_IMAGE_NON_NULL(source->weight, NAN);
+    PS_ASSERT_IMAGE_NON_NULL(source->maskObj, NAN);
+
+    PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32, false);
+    if (paramMask) {
+        PS_ASSERT_VECTOR_TYPE(paramMask, PS_TYPE_MASK, false);
+    }
+
+    // 1 *** generate the model and derivative images for this parameter set
+
+    // storage for model derivatives
+    psVector *deriv = psVectorAlloc(params->n, PS_TYPE_F32);
+
+    // working vector to store local coordinate
+    psVector *coord = psVectorAlloc(2, PS_TYPE_F32);
+
+    psImageInit (pcm->model, 0.0);
+    for (int n = 0; n < params->n; n++) {
+	if (!pcm->dmodels->data[n]) continue;
+	psImageInit (pcm->dmodels->data[n], 0.0);
+    }
+
+    // fill in the coordinate and value entries
+    for (psS32 i = 0; i < source->pixels->numRows; i++) {
+        for (psS32 j = 0; j < source->pixels->numCols; j++) {
+
+	    // XXX can we skip some of the data points where the model
+	    // is not going to be fitted??
+
+            // skip masked points
+	    // XXX probably should not skipped masked points: 
+	    // XXX skip if convolution of unmasked pixels will not see this pixel
+            // if (source->maskObj->data.U8[i][j]) {
+	    // continue;
+	    // }
+
+            // skip zero-weight points
+	    // XXX why is this not masked?
+            // if (source->weight->data.F32[i][j] == 0) {
+	    // continue;
+	    // }
+            // skip nan value points
+	    // XXX why is this not masked?
+            // if (!isfinite(source->pixels->data.F32[i][j])) {
+	    // continue;
+	    // }
+
+            // Convert i/j to image space:
+            coord->data.F32[0] = (psF32) (j + source->pixels->col0);
+            coord->data.F32[1] = (psF32) (i + source->pixels->row0);
+
+	    pcm->model->data.F32[i][j] = func (deriv, params, coord);
+
+	    for (int n = 0; n < params->n; n++) {
+		if ((paramMask != NULL) && (paramMask->data.U8[n])) { continue; }
+		psImage *dmodel = pcm->dmodels->data[n];
+		dmodel->data.F32[i][j] = deriv->data.F32[n];
+	    }
+        }
+    }
+    psFree(coord);
+    psFree(deriv);
+
+    // convolve model and dmodel arrays with PSF
+    psImageConvolveDirect (pcm->modelConv, pcm->model, psf);
+    for (int n = 0; n < pcm->dmodels->n; n++) {
+	if (pcm->dmodels->data[n] == NULL) continue;
+	psImage *dmodel = pcm->dmodels->data[n];
+	psImage *dmodelConv = pcm->dmodelsConv->data[n];
+	psImageConvolveDirect (dmodelConv, dmodel, psf);
+    }
+
+    // XXX TEST : SAVE IMAGES
+# if (SAVE_IMAGES) 
+    psphotSaveImage (NULL, psf->image, "psf.fits");
+    psphotSaveImage (NULL, pcm->model, "model.fits");
+    psphotSaveImage (NULL, pcm->modelConv, "modelConv.fits");
+    psphotSaveImage (NULL, source->pixels, "obj.fits");
+    psphotSaveImage (NULL, source->maskObj, "mask.fits");
+    psphotSaveImage (NULL, source->weight, "weight.fits");
+# endif
+
+    // 2 *** accumulate alpha & beta 
+
+    // zero alpha and beta for summing below
+    psImageInit (alpha, 0.0);
+    psVectorInit (beta, 0.0);
+    float chisq = 0.0;
+
+    for (psS32 i = 0; i < source->pixels->numRows; i++) {
+        for (psS32 j = 0; j < source->pixels->numCols; j++) {
+	    // XXX are we doing the right thing with the mask?
+            // skip masked points
+            if (source->maskObj->data.U8[i][j]) {
+                continue;
+            }
+            // skip zero-weight points
+            if (source->weight->data.F32[i][j] == 0) {
+                continue;
+            }
+            // skip nan value points
+            if (!isfinite(source->pixels->data.F32[i][j])) {
+                continue;
+            }
+
+	    float ymodel  = pcm->modelConv->data.F32[i][j];
+	    float yweight = 1.0 / source->weight->data.F32[i][j];
+	    float delta = ymodel - source->pixels->data.F32[i][j];
+
+	    chisq += PS_SQR(delta) * yweight;
+
+	    if (isnan(delta)) psAbort("nan in delta");
+	    if (isnan(chisq)) psAbort("nan in chisq");
+
+	    // alpha & beta only contain unmasked elements 
+	    for (int n1 = 0, N1 = 0; n1 < params->n; n1++) {
+		if ((paramMask != NULL) && (paramMask->data.U8[n1])) continue;
+		psImage *dmodel = pcm->dmodelsConv->data[n1];
+		float weight = dmodel->data.F32[i][j] * yweight;
+		for (int n2 = 0, N2 = 0; n2 <= n1; n2++) {
+		    if ((paramMask != NULL) && (paramMask->data.U8[n2])) continue;
+		    dmodel = pcm->dmodelsConv->data[n2];
+		    alpha->data.F32[N1][N2] += weight * dmodel->data.F32[i][j];
+		    N2++;
+		}
+		beta->data.F32[N1] += weight * delta;
+		N1++;
+	    }
+	}
+    }
+
+    // calculate lower-left half of alpha
+    for (psS32 j = 1; j < alpha->numCols; j++) {
+        for (psS32 k = 0; k < j; k++) {
+            alpha->data.F32[k][j] = alpha->data.F32[j][k];
+        }
+    }
+
+    return(chisq);
+}
+
+static void pmPCMDataFree (pmPCMData *pcm) {
+
+    if (pcm == NULL) return;
+
+    psFree (pcm->model);
+    psFree (pcm->modelConv);
+    psFree (pcm->dmodels);
+    psFree (pcm->dmodelsConv);
+    return;
+}
+
+pmPCMData *pmPCMDataAlloc (
+    const psVector *params,
+    const psVector *paramMask,
+    pmSource *source) {
+
+    pmPCMData *pcm = (pmPCMData *) psAlloc(sizeof(pmPCMData));
+    psMemSetDeallocator(pcm, (psFreeFunc) pmPCMDataFree);
+
+    // Allocate storage images for raw model and derivative images
+    pcm->model = psImageCopy (NULL, source->pixels, PS_TYPE_F32);
+    pcm->dmodels = psArrayAlloc (params->n);
+    for (psS32 n = 0; n < params->n; n++) {
+	pcm->dmodels->data[n] = NULL;
+	if ((paramMask != NULL) && (paramMask->data.U8[n])) { continue; }
+	pcm->dmodels->data[n] = psImageCopy (NULL, source->pixels, PS_TYPE_F32);
+    }
+
+    // Allocate storage images for convolved model and derivative images
+    pcm->modelConv = psImageCopy (NULL, source->pixels, PS_TYPE_F32);
+    pcm->dmodelsConv = psArrayAlloc (params->n);
+    for (psS32 n = 0; n < params->n; n++) {
+	pcm->dmodelsConv->data[n] = NULL;
+	if ((paramMask != NULL) && (paramMask->data.U8[n])) { continue; }
+	pcm->dmodelsConv->data[n] = psImageCopy (NULL, source->pixels, PS_TYPE_F32);
+    }
+
+    return pcm;
+}
+
+psImage *pmPCMDataSaveImage (pmPCMData *pcm) {
+
+    psImage *model = psImageCopy (NULL, pcm->modelConv, PS_TYPE_F32);
+   
+    return model;
+}
+
+/*
+ *
+ * we have a function func(param; value)
+ 
+ * basic LMM:
+ 
+ - fill in the data (x, y)
+ 
+ chisq = SetABX (alpha, beta, params, paramMask, x, y, dy, func)
+ 
+ while () {
+ GuessABP (Alpha, Beta, Params, alpha, beta, params, paramMask, checkLimits, lambda)
+ dLinear = dLinear(Beta, beta, lambda);
+ chisq = SetABX (alpha, beta, params, paramMask, x, y, dy, func)
+ convergence tests...
+ }
+ 
+ 
+
+ ** GuessABP:
+
+ f_c = sum_i (kern_i * func (x_i; p_o))
+
+ df_c/dp_o = d/dp_o [sum_i (kern_i * func (x_i; p_o))]
+
+ df_c/dp_o = sum_i (d/dp_o [kern_i * func (x_i; p_o)])
+
+ df_c/dp_o = sum_i (kern_i * d/dp_o [func (x_i; p_o)])
+
+ - generate image arrays for func, dfunc/dp_j (not masked)
+ - convolve each with psf
+ - measure delta = f_conv - data
+ - etc
+*/
+
+
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMosaicChip.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMosaicChip.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMosaicChip.c	(revision 22158)
@@ -0,0 +1,39 @@
+# include "psphotInternal.h"
+
+bool psphotMosaicChip(pmConfig *config, const pmFPAview *view, char *outFile, char *inFile)
+{
+    bool status;                        // Status of MD lookup
+
+    pmFPAfile *in = psMetadataLookupPtr(&status, config->files, inFile); // Input file
+    if (!status) {
+        psErrorStackPrint(stderr, "Can't find required I/O file!\n");
+        exit(EXIT_FAILURE);
+    }
+
+    pmFPAfile *out = psMetadataLookupPtr(&status, config->files, outFile); // Output file
+    if (!status) {
+        psErrorStackPrint(stderr, "Can't find required I/O file!\n");
+        exit(EXIT_FAILURE);
+    }
+
+    // XXXX we are failing to get the output hdu right
+    pmChip *outChip = pmFPAviewThisChip(view, out->fpa);
+    pmChip *inChip = pmFPAviewThisChip(view, in->fpa);
+    if (!outChip->hdu && !outChip->parent->hdu) {
+        const char *name = psMetadataLookupStr(&status, in->fpa->concepts, "FPA.NAME"); // Name of FPA
+        pmFPAAddSourceFromView(out->fpa, name, view, out->format);
+    }
+
+    psMaskType blankMask = pmConfigMaskGet("BLANK", config);
+
+    // mosaic the chip, forcing a deep copy (resulting images are not subimages)
+    psTrace("pmChipMosaic", 5, "mosaic chip %s to %s (xbin,ybin: %d,%d to %d,%d)\n",
+            in->name, out->name, in->xBin, in->yBin, out->xBin, out->yBin);
+    status = pmChipMosaic(outChip, inChip, true, blankMask);
+    return status;
+}
+
+// XXX does this do everything needed?
+// * mask & weight
+// * loaded PSF model (in readout->analysis)
+// * loaded SRC sources (in readout->analysis)
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMosaicSubimage.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMosaicSubimage.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotMosaicSubimage.c	(revision 22158)
@@ -0,0 +1,46 @@
+# include "psphotInternal.h"
+
+// insert the source image into the outimage at Xo, Yo
+bool psphotMosaicSubimage (psImage *outImage, pmSource *source, int Xo, int Yo, int DX, int DY) {
+
+    psRegion inRegion, outRegion;
+    psImage *inImage = source->pixels;
+
+    // identify the region in the output image
+    outRegion = psRegionSet (Xo, Xo + DX, Yo, Yo + DX);
+    outRegion = psRegionForImage (outImage, outRegion);
+    int DXo = outRegion.x1 - outRegion.x0;
+    int DYo = outRegion.y1 - outRegion.y0;
+    if (DXo <= 0) return false;
+    if (DYo <= 0) return false;
+    
+    // center the input source in the output box
+    int dX = (DXo - 1) / 2;
+    int dY = (DYo - 1) / 2;
+
+    // int xo = inImage->col0 + inImage->numCols / 2;
+    // int yo = inImage->row0 + inImage->numRows / 2;
+
+    int xo = source->peak->xf;
+    int yo = source->peak->yf;
+
+    // adjust region to overlay input image pixels
+    inRegion = psRegionSet (xo - dX, xo + dX + 1, yo - dY, yo + dY + 1);
+    inRegion = psRegionForImage (inImage, inRegion);
+
+    float peak = source->peak->flux;
+
+    psImage *subImage = psImageSubset (inImage, inRegion);
+    psImage *newImage = psImageAlloc (subImage->numCols, subImage->numRows, PS_TYPE_F32);
+    for (int iy = 0; iy < newImage->numRows; iy++) {
+	for (int ix = 0; ix < newImage->numCols; ix++) {
+	    newImage->data.F32[iy][ix] = subImage->data.F32[iy][ix] / peak;
+	}
+    }
+
+    psImageOverlaySection (outImage, newImage, Xo, Yo, "=");
+
+    psFree (subImage);
+    psFree (newImage);
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotOutput.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotOutput.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotOutput.c	(revision 22158)
@@ -0,0 +1,158 @@
+# include "psphotInternal.h"
+
+pmReadout *psphotSelectBackground (pmConfig *config,
+                                   const pmFPAview *view,
+                                   const bool stdev // return background's standard deviation?
+                                   ) {
+
+    bool status;
+    pmReadout *background;
+
+    pmFPAfile *file = psMetadataLookupPtr (&status, config->files, "PSPHOT.BACKMDL");
+    if (!file) return NULL;
+    if (file->mode == PM_FPA_MODE_INTERNAL) {
+        background = file->readout;
+    } else {
+        background = pmFPAviewThisReadout (view, file->fpa);
+    }
+    return background;
+}
+
+// XXX replace this with a call to a pmConfig function (pmConfigDump...)
+bool psphotDumpConfig (pmConfig *config) {
+
+  psMetadataConfigWrite (config->complete, "complete.md");
+  psMetadataConfigWrite (config->camera, "camera.md");
+  psMetadataConfigWrite (config->recipes, "recipes.md");
+  psMetadataConfigWrite (config->arguments, "arguments.md");
+  psMetadataConfigWrite (config->files, "files.md");
+  return true;
+}
+
+int psphotSaveImage (psMetadata *header, psImage *image, char *filename) {
+
+    psFits *fits = psFitsOpen (filename, "w");
+    psFitsWriteImage (fits, NULL, image, 0, NULL);
+    psFitsClose (fits);
+    return (TRUE);
+}
+
+bool psphotDumpMoments (psMetadata *recipe, psArray *sources) {
+
+    bool status;
+
+    // optional dump of all rough source data
+    char *output = psMetadataLookupStr (&status, recipe, "MOMENTS_OUTPUT_FILE");
+    if (!output) return false;
+    if (output[0] == 0) return false;
+    if (!strcasecmp (output, "NONE")) return false;
+
+    pmMomentsWriteText (sources, output);
+    return true;
+}
+
+bool psphotDumpSource (pmSource *source, char *name) {
+
+    FILE *f = fopen (name, "w");
+    if (f == NULL) psAbort("can't open file");
+
+    for (int i = 0; i < source->pixels->numRows; i++) {
+        for (int j = 0; j < source->pixels->numCols; j++) {
+            // skip masked points
+            if (source->maskObj->data.U8[i][j]) {
+                continue;
+            }
+            // skip zero-weight points
+            if (source->weight->data.F32[i][j] == 0) {
+                continue;
+            }
+
+            fprintf (f, "%d %d %f %f %d\n",
+                     (j + source->pixels->col0),
+                     (i + source->pixels->row0),
+                     source->pixels->data.F32[i][j],
+                     1.0 / source->weight->data.F32[i][j],
+                     source->maskObj->data.U8[i][j]);
+        }
+    }
+    fclose (f);
+    return true;
+}
+
+bool psphotAddPhotcode (psMetadata *recipe, pmConfig *config, const pmFPAview *view, const char *filerule) {
+
+    bool status;
+
+    pmFPAfile *input = psMetadataLookupPtr (&status, config->files, filerule);
+    PS_ASSERT (status, false);
+
+    // determine PHOTCODE from fpa & view, overwrite in recipe
+    char *photcode = pmConceptsPhotcodeForView (config, input, view);
+    PS_ASSERT (photcode, false);
+
+    psMetadataAddStr (recipe, PS_LIST_TAIL, "PHOTCODE", PS_META_REPLACE, "photcode from FPA concepts", photcode);
+    psLogMsg ("psphot", 3, "PHOTCODE is %s", photcode);
+
+    psFree (photcode);
+    return true;
+}
+
+bool psphotSetHeaderNstars (psMetadata *recipe, psArray *sources) {
+
+    int nSrc = 0;
+
+    // count the number of sources which will be written
+    for (int i = 0; (sources != NULL) && (i < sources->n); i++) {
+        pmSource *source = (pmSource *) sources->data[i];
+        pmModel *model = pmSourceGetModel (NULL, source);
+        if (model == NULL)
+            continue;
+        nSrc ++;
+    }
+    psMetadataAdd (recipe, PS_LIST_TAIL, "NSTARS", PS_DATA_S32 | PS_META_REPLACE, "NUMBER OF STARS", nSrc);
+    return true;
+}
+
+// these values are saved in an output header stub - they are added to either the
+// PHU header (CMP) or the MEF table header (CMF)
+psMetadata *psphotDefineHeader (psMetadata *recipe) {
+
+    psMetadata *header = psMetadataAlloc ();
+
+    // write necessary information to output header
+    psMetadataItemSupplement (header, recipe, "ZERO_PT");
+    psMetadataItemSupplement (header, recipe, "PHOTCODE");
+
+    psMetadataItemSupplement (header, recipe, "APMIFIT");
+    psMetadataItemSupplement (header, recipe, "DAPMIFIT");
+    psMetadataItemSupplement (header, recipe, "NAPMIFIT");
+    psMetadataItemSupplement (header, recipe, "SKYBIAS");
+    psMetadataItemSupplement (header, recipe, "SKYSAT");
+
+    // PSF model parameters (shape values for image center)
+    psMetadataItemSupplement (header, recipe, "NPSFSTAR");
+    psMetadataItemSupplement (header, recipe, "APLOSS");
+    psMetadataItemSupplement (header, recipe, "FWHM_X");
+    psMetadataItemSupplement (header, recipe, "FWHM_Y");
+    psMetadataItemSupplement (header, recipe, "ANGLE");
+
+    // XXX these need to be defined from elsewhere
+    psMetadataAdd (header, PS_LIST_TAIL, "FSATUR",   PS_DATA_F32 | PS_META_REPLACE, "SATURATION MAG",      0.0);
+    psMetadataAdd (header, PS_LIST_TAIL, "FLIMIT",   PS_DATA_F32 | PS_META_REPLACE, "COMPLETENESS MAG",    0.0);
+    psMetadataItemSupplement (header, recipe, "NSTARS");
+
+    // sky background model statistics
+    psMetadataItemSupplement (header, recipe, "MSKY_MN");
+    psMetadataItemSupplement (header, recipe, "MSKY_SIG");
+    psMetadataItemSupplement (header, recipe, "MSKY_MIN");
+    psMetadataItemSupplement (header, recipe, "MSKY_MAX");
+    psMetadataItemSupplement (header, recipe, "MSKY_NX");
+    psMetadataItemSupplement (header, recipe, "MSKY_NY");
+
+    psMetadataAddF32 (header, PS_LIST_TAIL, "DT_PHOT", PS_META_REPLACE, "elapsed psphot time", psTimerMark ("psphotReadout"));
+
+    // XXX : don't require any of these about values to exist
+    psErrorClear ();
+
+    return header;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotPSFConvModel.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotPSFConvModel.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotPSFConvModel.c	(revision 22158)
@@ -0,0 +1,139 @@
+# include "psphotInternal.h"
+# define USE_DELTA_PSF 0
+
+// save as static values so they may be set externally
+static psF32 PM_SOURCE_FIT_MODEL_NUM_ITERATIONS = 15;
+static psF32 PM_SOURCE_FIT_MODEL_TOLERANCE = 0.1;
+
+// input source has both modelPSF and modelEXT.  on successful exit, we set the
+// modelConv to contain the fitted parameters, and the modelFlux to contain the 
+// convolved model image.
+pmModel *psphotPSFConvModel (pmReadout *readout, pmSource *source, pmModelType modelType, psMaskType maskVal, psMaskType markVal, int psfSize) {
+    
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
+    // make sure we save a cached copy of the psf flux
+    pmSourceCachePSF (source, maskVal);
+
+    // convert the cached cached psf model for this source to a psKernel
+    psKernel *psf = psphotKernelFromPSF (source, psfSize);
+    if (!psf) return NULL;
+
+# if (USE_DELTA_PSF)
+    psImageInit (psf->image, 0.0);
+    psf->image->data.F32[(int)(0.5*psf->image->numRows)][(int)(0.5*psf->image->numCols)] = 1.0;
+# endif
+
+    // generate copy of the model
+    // XXX we could modify the parameter values or even the model 
+    // here based on the observed seeing (some lookup table...)
+
+    // use the source moments, etc to guess basic model parameters
+    pmModel *modelConv = pmSourceModelGuess (source, modelType);
+    if (!modelConv) {
+	psFree (psf);
+	return NULL;
+    }
+
+    // XXX test : modify the Io, SXX, SYY terms based on the psf SXX, SYY terms:
+    psEllipseShape psfShape;
+    psfShape.sx  = source->modelPSF->params->data.F32[PM_PAR_SXX] / M_SQRT2;
+    psfShape.sxy = source->modelPSF->params->data.F32[PM_PAR_SXY];
+    psfShape.sy  = source->modelPSF->params->data.F32[PM_PAR_SYY] / M_SQRT2;
+    psEllipseAxes psfAxes = psEllipseShapeToAxes (psfShape, 20.0);
+
+    // XXX test : modify the Io, SXX, SYY terms based on the psf SXX, SYY terms:
+    psEllipseShape extShape;
+    extShape.sx  = modelConv->params->data.F32[PM_PAR_SXX] / M_SQRT2;
+    extShape.sxy = modelConv->params->data.F32[PM_PAR_SXY];
+    extShape.sy  = modelConv->params->data.F32[PM_PAR_SYY] / M_SQRT2;
+    psEllipseAxes extAxes = psEllipseShapeToAxes (extShape, 20.0);
+
+    // decrease the initial guess ellipse by psf_minor axis:
+    psEllipseAxes extAxesMod;
+    extAxesMod.major = sqrt (PS_MAX (1.0, PS_SQR(extAxes.major) - PS_SQR(psfAxes.minor)));
+    extAxesMod.minor = sqrt (PS_MAX (1.0, PS_SQR(extAxes.minor) - PS_SQR(psfAxes.minor)));
+    extAxesMod.theta = extAxes.theta;
+
+    psEllipseShape extShapeMod = psEllipseAxesToShape (extAxesMod);
+    modelConv->params->data.F32[PM_PAR_SXX] = extShapeMod.sx * M_SQRT2;
+    modelConv->params->data.F32[PM_PAR_SXY] = extShapeMod.sxy;
+    modelConv->params->data.F32[PM_PAR_SYY] = extShapeMod.sy * M_SQRT2;
+
+    // increase the initial guess central intensity by 2pi r^2:
+    modelConv->params->data.F32[PM_PAR_I0] *= (1.0 + PS_SQR(psfAxes.minor) / PS_SQR(extAxesMod.minor));
+
+    psVector *params  = modelConv->params;
+    psVector *dparams = modelConv->dparams;
+
+    psphotCheckRadiusEXT (readout, source, modelConv, markVal);
+
+    // create the minimization constraints
+    psMinConstraint *constraint = psMinConstraintAlloc();
+    constraint->paramMask = psVectorAlloc (params->n, PS_TYPE_U8);
+    constraint->checkLimits = modelConv->modelLimits;
+
+    // set parameter mask based on fitting mode
+    // we fit a model without a floating sky term
+    int nParams = params->n - 1;
+    psVectorInit (constraint->paramMask, 0);
+    constraint->paramMask->data.U8[PM_PAR_SKY] = 1;
+
+    // force the floating parameters to fall within the contraint ranges
+    for (int i = 0; i < params->n; i++) {
+	modelConv->modelLimits (PS_MINIMIZE_PARAM_MIN, i, params->data.F32, NULL);
+	modelConv->modelLimits (PS_MINIMIZE_PARAM_MAX, i, params->data.F32, NULL);
+    }
+
+    // set up the minimization process
+    psMinimization *myMin = psMinimizationAlloc (PM_SOURCE_FIT_MODEL_NUM_ITERATIONS, PM_SOURCE_FIT_MODEL_TOLERANCE);
+
+    psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F32);
+
+    bool fitStatus = psphotModelWithPSF_LMM (myMin, covar, params, constraint, source, psf, modelConv->modelFunc);
+    for (int i = 0; i < dparams->n; i++) {
+        if (psTraceGetLevel("psphot") >= 4) {
+            fprintf (stderr, "%f ", params->data.F32[i]);
+        }
+        if ((constraint->paramMask != NULL) && constraint->paramMask->data.U8[i])
+            continue;
+        dparams->data.F32[i] = sqrt(covar->data.F32[i][i]);
+    }
+    psTrace ("psphot", 4, "niter: %d, chisq: %f", myMin->iter, myMin->value);
+
+    // renormalize output model image (generated by fitting process)
+    float Io = params->data.F32[PM_PAR_I0];
+    for (int iy = 0; iy < source->modelFlux->numRows; iy++) {
+	for (int ix = 0; ix < source->modelFlux->numCols; ix++) {
+	    source->modelFlux->data.F32[iy][ix] /= Io;
+	}
+    }
+
+    // save the resulting chisq, nDOF, nIter
+    modelConv->chisq = myMin->value;
+    modelConv->nIter = myMin->iter;
+
+    // XXX I actually need to count the number of unmasked pixels here
+    modelConv->nDOF  = source->pixels->numCols*source->pixels->numRows  -  nParams;
+
+    modelConv->flags |= PM_MODEL_STATUS_FITTED;
+    if (!fitStatus) modelConv->flags |= PM_MODEL_STATUS_NONCONVERGE;
+
+    // models can go insane: reject these
+    bool onPic = true;
+    onPic &= (params->data.F32[PM_PAR_XPOS] >= source->pixels->col0);
+    onPic &= (params->data.F32[PM_PAR_XPOS] <  source->pixels->col0 + source->pixels->numCols);
+    onPic &= (params->data.F32[PM_PAR_YPOS] >= source->pixels->row0);
+    onPic &= (params->data.F32[PM_PAR_YPOS] <  source->pixels->row0 + source->pixels->numRows);
+    if (!onPic) modelConv->flags |= PM_MODEL_STATUS_OFFIMAGE;
+
+    source->mode |= PM_SOURCE_MODE_FITTED; // XXX is this needed?
+
+    psFree(psf);
+    psFree(myMin);
+    psFree(covar);
+    psFree(constraint);
+
+    return modelConv;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotParseCamera.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotParseCamera.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotParseCamera.c	(revision 22158)
@@ -0,0 +1,81 @@
+# include "psphotStandAlone.h"
+
+// define the needed / desired I/O files
+bool psphotParseCamera (pmConfig *config) {
+
+    bool status = false;
+
+    // the file to be loaded may have subdivisions at the cell and readout level
+    // we load into pmFPAfile *load, then reformat into pmFPAfile *input
+    pmFPAfile *load = pmFPAfileDefineFromArgs (&status, config, "PSPHOT.LOAD", "INPUT");
+    if (!status) {
+	psError(PSPHOT_ERR_CONFIG, false, "Failed to build FPA from PSPHOT.LOAD");
+	return status;
+    }
+    load->dataLevel = PM_FPA_LEVEL_CHIP; // force load at the CHIP level
+
+    // if MASK or WEIGHT was supplied on command line, bind files to 'load'
+    // the mask and weight will be mosaicked with the image
+    pmFPAfile *mask = pmFPAfileBindFromArgs (&status, load, config, "PSPHOT.MASK", "MASK");
+    if (!status) {
+	psError (PS_ERR_UNKNOWN, false, "failed to load find definition");
+	return NULL;
+    }
+    if (mask) {
+	// XXX need to load the mask bit names from one of the headers
+	// this grabs the first available hdu : no guarantee that it will be valid, though
+	pmHDU *hdu = pmHDUGetFirst (mask->fpa);
+	if (!hdu) {
+	    psError(PS_ERR_IO, true, "no valid HDU for PSPHOT.MASK");
+	    return NULL;
+	}
+	// XXX should this be done in pmFPAfileIO.c read functions?
+	if (!pmConfigMaskReadHeader (config, hdu->header)) {
+	    psError(PS_ERR_IO, false, "error in mask bits");
+	    return NULL;
+	}
+    }
+    if (!psphotSetMaskBits (config)) {
+	psError (PS_ERR_UNKNOWN, false, "failed to set mask bit values");
+	return NULL;
+    }
+    
+    pmFPAfileBindFromArgs (&status, load, config, "PSPHOT.WEIGHT", "WEIGHT");
+    if (!status) {
+	psError (PS_ERR_UNKNOWN, false, "failed to load find definition");
+	return NULL;
+    }
+
+    // the psphot analysis is performed on chips
+    pmFPAfile *input = pmFPAfileDefineChipMosaic(config, load->fpa, "PSPHOT.INPUT");
+    if (!input) {
+        psError(PSPHOT_ERR_CONFIG, false, _("Unable to generate new file from PSPHOT.INPUT"));
+        return NULL;
+    }
+
+    // define the additional input/output files associated with psphot 
+    if (!psphotDefineFiles (config, input)) {
+	psError(PSPHOT_ERR_CONFIG, false, "Trouble defining the additional input/output files");
+	return false;
+    }
+
+    // Chip selection: turn on only the chips specified (pass status to suppress missing-key log msg)
+    char *chipLine = psMetadataLookupStr(&status, config->arguments, "CHIP_SELECTIONS");
+    psArray *chips = psStringSplitArray (chipLine, ",", false);
+    if (chips->n > 0) {
+	// select on the basis of extname?
+	pmFPASelectChip (load->fpa, -1, true); // deselect all chips
+	for (int i = 0; i < chips->n; i++) {
+	    int chipNum = atoi(chips->data[i]);
+	    if (! pmFPASelectChip(load->fpa, chipNum, false)) {
+		psError(PSPHOT_ERR_CONFIG, false, "Chip number %d doesn't exist in camera.\n", chipNum);
+		return false;
+	    }
+        }
+    }
+    psFree (chips);
+    psTrace("psphot", 1, "Done with psphotParseCamera...\n");
+
+    psErrorClear();			// some metadata lookup may have failed
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotPetrosian.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotPetrosian.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotPetrosian.c	(revision 22158)
@@ -0,0 +1,109 @@
+# include "psphotInternal.h"
+
+bool psphotPetrosian (pmSource *source, psMetadata *recipe, psMaskType maskVal) {
+
+  bool status;
+
+  assert (source->extpars);
+  assert (source->extpars->profile);
+  assert (source->extpars->profile->radius);
+  assert (source->extpars->profile->flux);
+
+  psVector *radius = source->extpars->profile->radius;
+  psVector *flux = source->extpars->profile->flux;
+
+  // flux at which to measure isophotal parameters
+  float PETROSIAN_R0 = psMetadataLookupF32 (&status, recipe, "PETROSIAN_R0");
+  float PETROSIAN_RF = psMetadataLookupF32 (&status, recipe, "PETROSIAN_FLUX_RATIO");
+  assert (status);
+
+  // first find flux at R0
+  int firstAbove = -1;
+  int lastBelow = -1;
+  for (int i = 0; i < radius->n; i++) {
+    if (radius->data.F32[i] < PETROSIAN_R0) lastBelow = i;
+    if ((firstAbove < 0) && (radius->data.F32[i] > PETROSIAN_R0)) firstAbove = i;
+  }
+  // if we don't go out far enough, we have a problem...
+  if (lastBelow == radius->n - 1) {
+    psTrace ("psphot", 5, "did not go out far enough to reach petrosian reference radius...");
+    // XXX skip object? raise a flag ?
+    return false;
+  }
+  if (firstAbove < 0) {
+    psTrace ("psphot", 5, "did not go out far enough to bound petrosian reference radius");
+    // XXX raise a flag ?
+    return false;
+  }
+
+  // average flux in this range
+  float fluxR0 = 0.0;
+  int fluxRn = 0;
+  for (int i = PS_MIN(firstAbove, lastBelow); i <= PS_MAX(firstAbove, lastBelow); i++) {
+    fluxR0 += flux->data.F32[i];
+    fluxRn ++;
+  }
+  fluxR0 /= (float)(fluxRn);
+
+  // target flux for petrosian radius
+  float fluxRP = fluxR0 * PETROSIAN_RF;
+
+  // find the first bin below the flux level and the last above the level
+  // XXX can this be done faster with bisection?
+  // XXX do I need to worry about crazy outliers?
+  // XXX should i be smoothing or fitting the curve?
+  int firstBelow = -1;
+  int lastAbove = -1;
+  for (int i = 0; i < flux->n; i++) {
+    if (flux->data.F32[i] > fluxRP) lastAbove = i;
+    if ((firstBelow < 0) && (flux->data.F32[i] < fluxRP)) firstBelow = i;
+  }
+  // if we don't go out far enough, we have a problem...
+  if (lastAbove == radius->n - 1) {
+    psTrace ("psphot", 5, "did not go out far enough to reach petrosian radius...");
+    // XXX skip object? raise a flag ?
+    return false;
+  }
+  if (firstBelow < 0) {
+    psTrace ("psphot", 5, "did not go out far enough to bound petrosian radius");
+    // XXX raise a flag ?
+    return false;
+  }
+
+  // need to examine pixels in this vicinity
+  float fluxFirst = 0;
+  float fluxLast = 0;
+  for (int i = 0; i <= PS_MAX(firstBelow, lastAbove); i++) {
+    if (i <= firstBelow) {
+      fluxFirst += flux->data.F32[i];
+    }
+    if (i <= lastAbove) {
+      fluxLast += flux->data.F32[i];
+    }
+  }
+  float fluxRPSum    = 0.5*(fluxLast + fluxFirst);
+  float fluxRPSumErr = 0.5*fabs(fluxLast - fluxFirst);
+  // XXX need to use the weight appropriately here...
+
+  float rad     = 0.5*(radius->data.F32[firstBelow] + radius->data.F32[lastAbove]);
+  float radErr  = 0.5*fabs(radius->data.F32[firstBelow] - radius->data.F32[lastAbove]);
+
+  if (!source->extpars->petrosian) {
+    source->extpars->petrosian = pmSourcePetrosianValuesAlloc ();
+  }
+
+  // these are uncalibrated: instrumental mags and pixel units
+  source->extpars->petrosian->mag    = -2.5*log10(fluxRPSum);
+  source->extpars->petrosian->magErr = fluxRPSumErr / fluxRPSum;
+
+  source->extpars->petrosian->rad    = rad;
+  source->extpars->petrosian->radErr = radErr;
+
+  psTrace ("psphot", 5, "Petrosian flux:%f +/- %f @ %f +/- %f for %f, %f\n",
+           source->extpars->petrosian->mag, source->extpars->petrosian->magErr,
+           source->extpars->petrosian->rad, source->extpars->petrosian->radErr,
+           source->peak->xf, source->peak->yf);
+
+  return true;
+
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotRadialPlot.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotRadialPlot.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotRadialPlot.c	(revision 22158)
@@ -0,0 +1,118 @@
+# include "psphotInternal.h"
+
+// this variable is defined in psmodules.h if ohana-config is found
+# if (HAVE_KAPA)
+
+# include <kapa.h>
+
+static int nCount = 0;
+
+bool psphotRadialPlot (int *kapa, const char *filename, pmSource *source) {
+
+    Graphdata graphdata;
+
+    // only plot 50 stars for now...
+    if (nCount > 00) {
+	if (*kapa != 0) {
+	    KiiClose (*kapa);
+	    *kapa = 0;
+	}
+	return true;
+    }
+
+    // XXX get the 'showWindow' option from the recipes somewhere
+    // XXX 'showWindow = false' is broken
+    if (*kapa == 0) {
+	*kapa = pmKapaOpen (false);
+	KapaResize (*kapa, 500, 500);
+	unlink (filename);
+    }
+    if (*kapa == -1) {
+	psError(PSPHOT_ERR_UNKNOWN, true, "failure to open kapa");
+	return false;
+    }
+
+    KapaInitGraph (&graphdata);
+    KapaClearPlots (*kapa);
+
+    // examine sources to set data range
+    graphdata.xmin =  -0.05;
+    graphdata.xmax = +30.05;
+    graphdata.ymin = -0.05;
+    graphdata.ymax = +5.05;
+    KapaSetLimits (*kapa, &graphdata);
+  
+    KapaSetFont (*kapa, "helvetica", 14);
+    KapaBox (*kapa, &graphdata);
+    KapaSendLabel (*kapa, "radius (pixels)", KAPA_LABEL_XM);
+    KapaSendLabel (*kapa, "log flux (counts)", KAPA_LABEL_YM);
+	       
+    int nPts = source->pixels->numRows * source->pixels->numCols;
+    psVector *rg = psVectorAllocEmpty (nPts, PS_TYPE_F32);
+    psVector *fg = psVectorAllocEmpty (nPts, PS_TYPE_F32);
+    psVector *rb = psVectorAllocEmpty (nPts, PS_TYPE_F32);
+    psVector *fb = psVectorAllocEmpty (nPts, PS_TYPE_F32);
+
+    int ng = 0;
+    int nb = 0;
+    float Xo = source->modelPSF->params->data.F32[PM_PAR_XPOS] - source->pixels->col0;
+    float Yo = source->modelPSF->params->data.F32[PM_PAR_YPOS] - source->pixels->row0;
+    for (int iy = 0; iy < source->pixels->numRows; iy++) {
+	for (int ix = 0; ix < source->pixels->numCols; ix++) {
+	    if (source->maskObj->data.U8[iy][ix]) {
+		rb->data.F32[nb] = hypot (ix - Xo, iy - Yo) ;
+		fb->data.F32[nb] = log10(source->pixels->data.F32[iy][ix]);
+		nb++;
+	    } else {
+		rg->data.F32[ng] = hypot (ix - Xo, iy - Yo) ;
+		fg->data.F32[ng] = log10(source->pixels->data.F32[iy][ix]);
+		ng++;
+	    }
+	}
+    }
+  
+    // set the plot range here based on lflux, radius
+
+    graphdata.color = KapaColorByName ("black");
+    graphdata.ptype = 2;
+    graphdata.size = 0.5;
+    graphdata.style = 2;
+    KapaPrepPlot (*kapa, ng, &graphdata);
+    KapaPlotVector (*kapa, ng, rg->data.F32, "x");
+    KapaPlotVector (*kapa, ng, fg->data.F32, "y");
+
+    graphdata.color = KapaColorByName ("red");
+    graphdata.ptype = 0;
+    graphdata.size = 0.3;
+    graphdata.style = 2;
+    KapaPrepPlot (*kapa, nb, &graphdata);
+    KapaPlotVector (*kapa, nb, rb->data.F32, "x");
+    KapaPlotVector (*kapa, nb, fb->data.F32, "y");
+  
+    psLogMsg ("psphot", 3, "saving plot to %s", filename);
+
+    char pagename[16];
+    sprintf (pagename, "%02d", nCount);
+    if (nCount == 0) {
+	KiiPS (*kapa, filename, false, KAPA_PS_NEWPLOT, pagename);
+    } else {
+	KiiPS (*kapa, filename, false, KAPA_PS_NEWPAGE, pagename);
+    }
+
+    psFree (rg);
+    psFree (fg);
+    psFree (rb);
+    psFree (fb);
+
+    nCount ++;
+    return true;
+}
+
+# else
+
+bool psphotRadialPlot (int *kapa, const char *filename, pmSource *source) {
+    psLogMsg ("psphot", 3, "skipping source radial plots");
+    return true;
+}
+
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotRadialProfile.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotRadialProfile.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotRadialProfile.c	(revision 22158)
@@ -0,0 +1,71 @@
+# include "psphotInternal.h"
+
+# define COMPARE_RADIUS(A,B) (radius->data.F32[A] < radius->data.F32[B])
+# define SWAP_RADIUS(TYPE,A,B) { \
+  float tmp; \
+  if (A != B) { \
+    tmp = radius->data.F32[A]; \
+    radius->data.F32[A] = radius->data.F32[B]; \
+    radius->data.F32[B] = tmp; \
+    tmp = flux->data.F32[A]; \
+    flux->data.F32[A] = flux->data.F32[B]; \
+    flux->data.F32[B] = tmp; \
+    tmp = weight->data.F32[A]; \
+    weight->data.F32[A] = weight->data.F32[B]; \
+    weight->data.F32[B] = tmp; \
+  } \
+}
+
+bool psphotRadialProfile (pmSource *source, psMetadata *recipe, psMaskType maskVal) {
+
+    // allocate pmSourceExtendedParameters, if not already defined
+    if (!source->extpars) {
+        source->extpars = pmSourceExtendedParsAlloc ();
+    }
+
+    if (!source->extpars->profile) {
+        source->extpars->profile = pmSourceRadialProfileAlloc ();
+    }
+
+    int nPts = source->pixels->numRows * source->pixels->numCols;
+    source->extpars->profile->radius = psVectorAllocEmpty (nPts, PS_TYPE_F32);
+    source->extpars->profile->flux   = psVectorAllocEmpty (nPts, PS_TYPE_F32);
+    source->extpars->profile->weight = psVectorAllocEmpty (nPts, PS_TYPE_F32);
+
+    psVector *radius = source->extpars->profile->radius;
+    psVector *flux   = source->extpars->profile->flux;
+    psVector *weight = source->extpars->profile->weight;
+
+    // XXX use the extended source model here for Xo, Yo?
+    // XXX define a radius scaled to the elliptical contour?
+
+    int n = 0;
+    
+    float Xo = 0.0;
+    float Yo = 0.0;
+
+    if (source->modelEXT) {
+      Xo = source->modelEXT->params->data.F32[PM_PAR_XPOS] - source->pixels->col0;
+      Yo = source->modelEXT->params->data.F32[PM_PAR_YPOS] - source->pixels->row0;
+    } else {
+      Xo = source->peak->xf - source->pixels->col0;
+      Yo = source->peak->yf - source->pixels->row0;
+    }
+    for (int iy = 0; iy < source->pixels->numRows; iy++) {
+        for (int ix = 0; ix < source->pixels->numCols; ix++) {
+            if (source->maskObj->data.U8[iy][ix]) continue;
+            radius->data.F32[n] = hypot (ix - Xo, iy - Yo) ;
+            flux->data.F32[n]   = source->pixels->data.F32[iy][ix];
+            weight->data.F32[n] = source->weight->data.F32[iy][ix];
+            n++;
+        }
+    }
+    radius->n = n;
+    weight->n = n;
+    flux->n = n;
+
+    // sort the vector set by the radius
+    PSSORT (radius->n, COMPARE_RADIUS, SWAP_RADIUS, NONE);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotRadiusChecks.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotRadiusChecks.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotRadiusChecks.c	(revision 22158)
@@ -0,0 +1,105 @@
+# include "psphotInternal.h"
+# define RADIUS_TYPE int
+
+static float PSF_FIT_NSIGMA;
+static float PSF_FIT_PADDING;
+static float PSF_FIT_RADIUS = 0;	// radius to use in fitting (ignored if <= 0,
+					// and a per-object radius is calculated)
+
+bool psphotInitRadiusPSF(const psMetadata *recipe, const pmModelType type) {
+
+    bool status = true;
+
+    PSF_FIT_NSIGMA  = psMetadataLookupF32(&status, recipe, "PSF_FIT_NSIGMA");
+    PSF_FIT_PADDING = psMetadataLookupF32(&status, recipe, "PSF_FIT_PADDING");
+    PSF_FIT_RADIUS =  psMetadataLookupF32(&status, recipe, "PSF_FIT_RADIUS");
+
+    return true;
+}
+
+// call this function whenever you (re)-define the PSF model
+bool psphotCheckRadiusPSF (pmReadout *readout, pmSource *source, pmModel *model, psMaskType markVal)
+{
+    psF32 *PAR = model->params->data.F32;
+
+    // XXX do we have a better value for the sky noise level?  not really...
+    pmMoments *moments = source->moments;
+
+    // set the fit radius based on the object flux limit and the model
+    float radiusFit = PSF_FIT_RADIUS;
+    if (radiusFit <= 0) {		// use fixed radius
+	if (moments == NULL) {
+	    radiusFit = model->modelRadius(model->params, PSF_FIT_NSIGMA*moments->dSky);
+	} else {
+	    radiusFit = model->modelRadius(model->params, 1.0);
+	}
+    }
+    model->radiusFit = (RADIUS_TYPE)(radiusFit + PSF_FIT_PADDING);
+
+    if (isnan(model->radiusFit)) psAbort("error in radius");
+	
+    if (source->mode & PM_SOURCE_MODE_SATSTAR) {
+	model->radiusFit *= 2;
+    }
+
+    bool status = pmSourceRedefinePixels (source, readout, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->radiusFit);
+
+    // set the mask to flag the excluded pixels
+    psImageKeepCircle (source->maskObj, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->radiusFit, "OR", markVal);
+    return status;
+}
+
+bool psphotCheckRadiusPSFBlend (pmReadout *readout, pmSource *source, pmModel *model, psMaskType markVal, float dR) {
+
+    psF32 *PAR = model->params->data.F32;
+
+    pmMoments *moments = source->moments;
+    if (moments == NULL) return false;
+
+    // set the fit radius based on the object flux limit and the model
+    model->radiusFit = (RADIUS_TYPE) (model->modelRadius (model->params, PSF_FIT_NSIGMA*moments->dSky) + dR + PSF_FIT_PADDING);
+    if (isnan(model->radiusFit)) psAbort("error in radius");
+	
+    if (source->mode &  PM_SOURCE_MODE_SATSTAR) {
+	model->radiusFit *= 2;
+    }
+
+    bool status = pmSourceRedefinePixels (source, readout, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->radiusFit);
+
+    // set the mask to flag the excluded pixels
+    psImageKeepCircle (source->maskObj, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->radiusFit, "OR", markVal);
+    return status;
+}
+
+static float EXT_FIT_NSIGMA;
+static float EXT_FIT_PADDING;
+
+bool psphotInitRadiusEXT (psMetadata *recipe, pmModelType type) {
+
+    bool status;
+
+    EXT_FIT_NSIGMA   = psMetadataLookupF32 (&status, recipe, "EXT_FIT_NSIGMA");
+    EXT_FIT_PADDING  = psMetadataLookupF32 (&status, recipe, "EXT_FIT_PADDING");
+
+    return true;
+}
+
+// call this function whenever you (re)-define the EXT model
+bool psphotCheckRadiusEXT (pmReadout *readout, pmSource *source, pmModel *model, psMaskType markVal) {
+
+    psF32 *PAR = model->params->data.F32;
+
+    pmMoments *moments = source->moments;
+    if (moments == NULL) return false;
+
+    // set the fit radius based on the object flux limit and the model
+    model->radiusFit = (RADIUS_TYPE) (model->modelRadius (model->params, EXT_FIT_NSIGMA*moments->dSky) + EXT_FIT_PADDING);
+    if (isnan(model->radiusFit)) psAbort("error in radius");
+
+    // redefine the pixels if needed
+    bool status = pmSourceRedefinePixels (source, readout, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->radiusFit);
+
+    // set the mask to flag the excluded pixels
+    psImageKeepCircle (source->maskObj, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->radiusFit, "OR", markVal);
+    return status;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotReadout.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotReadout.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotReadout.c	(revision 22158)
@@ -0,0 +1,269 @@
+# include "psphotInternal.h"
+
+bool psphotReadout(pmConfig *config, const pmFPAview *view) {
+
+    // measure the total elapsed time in psphotReadout.  XXX the current threading plan
+    // for psphot envisions threading within psphotReadout, not multiple threads calling
+    // the same psphotReadout.  In the current plan, this dtime is the elapsed time used
+    // jointly by the multiple threads, not the total time used by all threads.
+    psTimerStart ("psphotReadout");
+
+    // select the current recipe
+    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSPHOT_RECIPE);
+    if (!recipe) {
+        psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSPHOT_RECIPE);
+        return false;
+    }
+
+    // set the photcode for this image
+    if (!psphotAddPhotcode (recipe, config, view, "PSPHOT.INPUT")) {
+        psError (PSPHOT_ERR_CONFIG, false, "trouble defining the photcode");
+        return false;
+    }
+
+    // find the currently selected readout
+    pmReadout  *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT");
+    PS_ASSERT_PTR_NON_NULL (readout, false);
+
+    // optional break-point for processing
+    char *breakPt = psMetadataLookupStr (NULL, recipe, "BREAK_POINT");
+    PS_ASSERT_PTR_NON_NULL (breakPt, false);
+
+    // Generate the mask and weight images, including the user-defined analysis region of interest
+    psphotSetMaskAndWeight (config, readout, recipe);
+    if (!strcasecmp (breakPt, "NOTHING")) {
+        return psphotReadoutCleanup(config, readout, recipe, NULL, NULL, NULL);
+    }
+
+    // generate a background model (median, smoothed image)
+    if (!psphotModelBackground (config, view, "PSPHOT.INPUT")) {
+        return psphotReadoutCleanup (config, readout, recipe, NULL, NULL, NULL);
+    }
+    if (!psphotSubtractBackground (config, view, "PSPHOT.INPUT")) {
+        return psphotReadoutCleanup (config, readout, recipe, NULL, NULL, NULL);
+    }
+    if (!strcasecmp (breakPt, "BACKMDL")) {
+        return psphotReadoutCleanup (config, readout, recipe, NULL, NULL, NULL);
+    }
+
+    // run a single-model test if desired (exits from here if test is run)
+    psphotModelTest (config, view, recipe);
+
+    // load the psf model, if suppled.  FWHM_X,FWHM_Y,etc are saved in the recipe
+    pmPSF *psf = psphotLoadPSF (config, view, recipe);
+
+    // several functions below behave differently if we have a PSF model already
+    bool havePSF = (psf != NULL);
+
+    // find the detections (by peak and/or footprint) in the image.
+    pmDetections *detections = psphotFindDetections (NULL, readout, recipe);
+    if (!detections) {
+        psLogMsg ("psphot", 3, "unable to find detections in this image");
+        return psphotReadoutCleanup (config, readout, recipe, detections, psf, NULL);
+    }
+ 
+    // XXX test write out the footprint image
+    if (0) {
+	psImage *footprintImage = pmSetFootprintArrayIDs (detections->footprints, true);
+	psphotSaveImage (NULL, footprintImage, "footprints.1.fits");
+	psFree (footprintImage);
+    }
+
+    // construct sources and measure basic stats
+    psArray *sources = psphotSourceStats (readout, recipe, detections);
+    if (!sources) return false;
+    if (!strcasecmp (breakPt, "PEAKS")) {
+        return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources);
+    }
+
+    // find blended neighbors of very saturated stars
+    // XXX merge this with Basic Deblend?
+    psphotDeblendSatstars (sources, recipe);
+
+    // mark blended peaks PS_SOURCE_BLEND
+    if (!psphotBasicDeblend (sources, recipe)) {
+        psLogMsg ("psphot", 3, "failed on deblend analysis");
+        return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
+    }
+
+    // classify sources based on moments, brightness
+    if (!psphotRoughClass (sources, recipe, havePSF)) {
+        psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image");
+        return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
+    }
+    if (!strcasecmp (breakPt, "MOMENTS")) {
+        return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources);
+    }
+
+    // if we were not supplied a PSF, choose one here
+    if (psf == NULL) {
+        // use bright stellar objects to measure PSF
+        // XXX if we do not have enough stars to generate the PSF, build one
+        // from the SEEING guess and model class
+        psf = psphotChoosePSF (readout, sources, recipe);
+        if (psf == NULL) {
+            psLogMsg ("psphot", 3, "failure to construct a psf model");
+            return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
+        }
+        havePSF = true;
+    }
+    if (!strcasecmp (breakPt, "PSFMODEL")) {
+        return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
+    }
+
+    // include externally-supplied sources
+    psphotLoadExtSources (config, view, sources);
+
+    // construct an initial model for each object
+    psphotGuessModels (readout, sources, recipe, psf);
+
+    // XXX test output of models
+    // psphotTestSourceOutput (readout, sources, recipe, psf);
+
+    // linear PSF fit to source peaks
+    psphotFitSourcesLinear (readout, sources, recipe, psf, FALSE);
+
+    if (0) { 
+	FILE *out = fopen ("out.pass1.dat", "w");
+	
+	for (int i = 0; i < sources->n; i++) {
+	    pmSource *source = sources->data[i];
+	    if (!source) continue;
+	    pmPeak *peak = source->peak;
+	    if (!peak) continue;
+	    pmModel *model = source->modelPSF;
+	    if (!model) continue;
+	    if (!model->params) continue;
+	    
+	    fprintf (out, "%d %f %f  %f %f  %f %f\n", 
+		     i, peak->xf, peak->yf, peak->flux, peak->SN,
+		     model->params->data.F32[PM_PAR_I0],
+		     model->dparams->data.F32[PM_PAR_I0]);
+	}
+	fclose (out);
+    }
+
+    // identify CRs and extended sources
+    psphotSourceSize (config, readout, sources, recipe, 0);
+    if (!strcasecmp (breakPt, "ENSEMBLE")) {
+        goto finish;
+    }
+
+    // non-linear PSF and EXT fit to brighter sources
+    psphotBlendFit (readout, sources, recipe, psf);
+
+    // replace all sources
+    psphotReplaceAllSources (sources, recipe);
+
+    // linear fit to include all sources
+    psphotFitSourcesLinear (readout, sources, recipe, psf, TRUE);
+
+    // if we only do one pass, skip to extended source analysis
+    if (!strcasecmp (breakPt, "PASS1")) {
+        goto pass1finish;
+    }
+
+    // XXX for the moment, drop the re-calc of the background (prove this works)
+    // replace background in residual image
+    // psphotSkyReplace (config, view);
+    // re-measure background model (median, smoothed image)
+    // psphotImageMedian (config, view);
+
+    // add noise for subtracted objects
+    psphotAddNoise (readout, sources, recipe);
+
+    // find fainter sources (pass 2)
+    detections = psphotFindDetections (detections, readout, recipe);
+
+    // XXX test write out the footprint image
+    if (0) {
+	psImage *footprintImage = pmSetFootprintArrayIDs (detections->footprints, true);
+	psphotSaveImage (NULL, footprintImage, "footprints.2.fits");
+	psFree (footprintImage);
+    }
+
+    // remove noise for subtracted objects (ie, return to normal noise level)
+    psphotSubNoise (readout, sources, recipe);
+
+    // define new sources based on only the new peaks
+    psArray *newSources = psphotSourceStats (readout, recipe, detections);
+
+    // set source type
+    if (!psphotRoughClass (newSources, recipe, havePSF)) {
+        psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image");
+        return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
+    }
+
+    // create full input models
+    psphotGuessModels (readout, newSources, recipe, psf);
+
+    // replace all sources so fit below applies to all at once
+    psphotReplaceAllSources (sources, recipe);
+
+    // merge the newly selected sources into the existing list
+    psphotMergeSources (sources, newSources);
+    psFree (newSources);
+
+    // linear fit to all sources
+    psphotFitSourcesLinear (readout, sources, recipe, psf, TRUE);
+
+    if (0) { 
+	FILE *out = fopen ("out.pass2.dat", "w");
+	
+	for (int i = 0; i < sources->n; i++) {
+	    pmSource *source = sources->data[i];
+	    if (!source) continue;
+	    pmPeak *peak = source->peak;
+	    if (!peak) continue;
+	    pmModel *model = source->modelPSF;
+	    if (!model) continue;
+	    if (!model->params) continue;
+	    
+	    fprintf (out, "%d %f %f  %f %f  %f %f\n", 
+		     i, peak->xf, peak->yf, peak->flux, peak->SN,
+		     model->params->data.F32[PM_PAR_I0],
+		     model->dparams->data.F32[PM_PAR_I0]);
+	}
+	fclose (out);
+    }
+
+pass1finish:
+
+    // measure source size for the remaining sources
+    psphotSourceSize (config, readout, sources, recipe, 0);
+
+    if (0) {
+	psphotSaveImage (NULL, readout->mask, "mask.fits");
+    }
+	
+    psphotExtendedSourceAnalysis (readout, sources, recipe);
+
+    psphotExtendedSourceFits (readout, sources, recipe);
+
+finish:
+
+    // plot positive sources 
+    // psphotSourcePlots (readout, sources, recipe); 
+
+    // measure aperture photometry corrections
+    if (!psphotApResid (readout, sources, recipe, psf)) {
+        psLogMsg ("psphot", 3, "failed on psphotApResid");
+        return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
+    }
+
+    // calculate source magnitudes
+    pmReadout *background = psphotSelectBackground (config, view, false);
+    psphotMagnitudes(sources, recipe, psf, background);
+
+    // replace failed sources?
+    // psphotReplaceUnfitSources (sources);
+
+    // replace background in residual image
+    psphotSkyReplace (config, view);
+
+    // drop the references to the image pixels held by each source
+    psphotSourceFreePixels (sources);
+
+    // create the exported-metadata and free local data
+    return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources);
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotReadoutCleanup.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotReadoutCleanup.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotReadoutCleanup.c	(revision 22158)
@@ -0,0 +1,88 @@
+# include "psphotInternal.h"
+
+// psphotReadoutCleanup is called on exit from psphotReadout.  If the last raised error is
+// not a DATA error, then there was a serious problem.  Only in this case, or if the fail
+// on the stats measurement, do we return false
+bool psphotReadoutCleanup (pmConfig *config, pmReadout *readout, psMetadata *recipe, pmDetections *detections, pmPSF *psf, psArray *sources) {
+
+    // remove internal pmFPAfiles, if created
+    bool status = true;
+    status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKMDL");
+    status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKMDL.STDEV");
+    status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKGND");
+    if (!status) {
+	psError(PSPHOT_ERR_PROG, false, "trouble dropping internal files");
+	psFree (psf);
+	psFree (sources);
+	psFree (detections);
+	return false;
+    }
+
+    if (psErrorCodeLast() == PSPHOT_ERR_DATA) {
+        psErrorStackPrint(stderr, "Error in the psphot readout analysis");
+	psErrorClear();
+    } 
+    if (psErrorCodeLast() != PS_ERR_NONE) { 
+	psFree (psf);
+	psFree (sources);
+	psFree (detections);
+	return false;
+    }
+
+    // use the psf-model to measure FWHM stats
+    if (psf) {
+        if (!psphotPSFstats (readout, recipe, psf)) {
+            psError(PSPHOT_ERR_PROG, false, "Failed to measure PSF shape parameters");
+	    psFree (psf);
+	    psFree (sources);
+	    psFree (detections);
+            return false;
+        }
+    }
+    // otherwise, use the source moments to measure FWHM stats
+    if (!psf && sources) {
+        if (!psphotMomentsStats (readout, recipe, sources)) {
+            psError(PSPHOT_ERR_PROG, false, "Failed to measure Moment shape parameters");
+	    psFree (psf);
+	    psFree (sources);
+	    psFree (detections);
+            return false;
+        }
+    }
+
+    // write NSTARS to the image header
+    psphotSetHeaderNstars (recipe, sources);
+
+    // create an output header with stats results
+    psMetadata *header = psphotDefineHeader (recipe);
+
+    // save the results of the analysis
+    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSPHOT.HEADER",  PS_DATA_METADATA, "header stats", header);
+    if (sources) {
+	psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSPHOT.SOURCES", PS_DATA_ARRAY, "psphot sources", sources);
+    }
+    if (psf) {
+	// save the psf for possible output.  if there was already an entry, it was loaded from external sources
+	// the new one may have been updated or modified, so replace the existing entry.  We
+	// are required to save it on the chip, but this will cause problems if we ever want to
+	// run psphot on an unmosaiced image
+	pmCell *cell = readout->parent;
+	pmChip *chip = cell->parent;
+	psMetadataAdd (chip->analysis, PS_LIST_TAIL, "PSPHOT.PSF", PS_DATA_UNKNOWN | PS_META_REPLACE,  "psphot psf", psf);
+    }
+
+    if (psErrorCodeLast() != PS_ERR_NONE) {
+        psErrorStackPrint(stderr, "unexpected remaining errors");
+	abort();
+    }
+
+    // XXX move this to top of loop?
+    pmKapaClose ();
+
+    psFree (detections);
+    psFree (psf);
+    psFree (header);
+    psFree (sources);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotReplaceUnfit.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotReplaceUnfit.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotReplaceUnfit.c	(revision 22158)
@@ -0,0 +1,115 @@
+# include "psphotInternal.h"
+
+// replace the flux for sources which failed
+bool psphotReplaceUnfitSources (psArray *sources, psMaskType maskVal) {
+
+    pmSource *source;
+
+    psTimerStart ("psphot");
+
+    for (int i = 0; i < sources->n; i++) {
+      source = sources->data[i];
+
+      // replace other sources?
+      if (source->mode & PM_SOURCE_MODE_FAIL) goto replace;
+      continue;
+
+    replace:
+        pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
+        source->mode &= ~PM_SOURCE_MODE_SUBTRACTED;
+    }
+    psLogMsg ("psphot.replace", 3, "replace unfitted models: %f sec (%ld objects)\n", psTimerMark ("psphot"), sources->n);
+    return true;
+}
+
+bool psphotReplaceAllSources (psArray *sources, psMetadata *recipe) {
+
+    bool status;
+    pmSource *source;
+
+    psTimerStart ("psphot");
+
+    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
+    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
+    assert (maskVal);
+
+    for (int i = 0; i < sources->n; i++) {
+      source = sources->data[i];
+
+      // replace other sources?
+      if (!(source->mode & PM_SOURCE_MODE_SUBTRACTED)) continue;
+
+      pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
+      source->mode &= ~PM_SOURCE_MODE_SUBTRACTED;
+    }
+    psLogMsg ("psphot.replace", PS_LOG_INFO, "replaced models for %ld objects: %f sec\n", sources->n, psTimerMark ("psphot"));
+    return true;
+}
+
+bool psphotRemoveAllSources (psArray *sources, psMetadata *recipe) {
+
+    bool status;
+    pmSource *source;
+
+    psTimerStart ("psphot");
+
+    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
+    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
+    assert (maskVal);
+
+    for (int i = 0; i < sources->n; i++) {
+      source = sources->data[i];
+
+      // replace other sources?
+      if (source->mode & PM_SOURCE_MODE_SUBTRACTED) continue;
+
+      pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
+      source->mode |= PM_SOURCE_MODE_SUBTRACTED;
+    }
+    psLogMsg ("psphot.replace", PS_LOG_INFO, "replaced models for %ld objects: %f sec\n", sources->n, psTimerMark ("psphot"));
+    return true;
+}
+
+// add source, if the source has been subtracted (or if we ignore the state)
+bool psphotAddWithTest (pmSource *source, bool useState, psMaskType maskVal) {
+
+    // what is current state? (true : add; false : sub)
+    bool state = !(source->mode & PM_SOURCE_MODE_SUBTRACTED);
+    if (state && useState) return true;
+
+    // replace the model if 1) state says it is missing or 2) useState is false (just do it)
+    if (!state || !useState) {
+        pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
+    }
+    return true;
+}
+
+// sub source, if the source has been added (or if we ignore the state)
+bool psphotSubWithTest (pmSource *source, bool useState, psMaskType maskVal) {
+
+    // what is current state? (true : sub; false : add)
+    bool state = (source->mode & PM_SOURCE_MODE_SUBTRACTED);
+    if (state && useState) return true;
+
+    // replace the model if 1) state says it is missing or 2) useState is false (just do it)
+    if (!state || !useState) {
+        pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
+    }
+    return true;
+}
+
+// add or sub source replace or if the source has
+bool psphotSetState (pmSource *source, bool curState, psMaskType maskVal) {
+
+    // what is desired state? (true : add; false : sub)
+    bool newState = !(source->mode & PM_SOURCE_MODE_SUBTRACTED);
+    if (curState == newState) return true;
+
+    if (curState && !newState) {
+        pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
+    }
+    if (newState && !curState) {
+        pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
+    }
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotRoughClass.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotRoughClass.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotRoughClass.c	(revision 22158)
@@ -0,0 +1,60 @@
+# include "psphotInternal.h"
+
+# define CHECK_STATUS(S,MSG) { \
+  if (!status) { \
+    psError(PSPHOT_ERR_CONFIG, false, "missing PSF Clump entry: %s\n", MSG); \
+    return false; \
+  } }
+
+// 2006.02.02 : no leaks
+bool psphotRoughClass (psArray *sources, psMetadata *recipe, const bool havePSF) {
+
+    bool status;
+    static pmPSFClump psfClump;
+
+    psTimerStart ("psphot");
+
+    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
+    psMaskType maskSat = psMetadataLookupU8(&status, recipe, "MASK.SAT"); // Mask value for bad pixels
+    assert (maskSat);
+
+    if (!havePSF) {
+        // determine the PSF parameters from the source moment values
+        psfClump = pmSourcePSFClump (sources, recipe);
+	psMetadataAddF32 (recipe, PS_LIST_TAIL, "PSF.CLUMP.X",  PS_META_REPLACE, "psf clump center", psfClump.X);
+	psMetadataAddF32 (recipe, PS_LIST_TAIL, "PSF.CLUMP.Y",  PS_META_REPLACE, "psf clump center", psfClump.Y);
+	psMetadataAddF32 (recipe, PS_LIST_TAIL, "PSF.CLUMP.DX", PS_META_REPLACE, "psf clump center", psfClump.dX);
+	psMetadataAddF32 (recipe, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY);
+    } else {
+        // pull FWHM_X,Y from the recipe, use to define psfClump.X,Y
+        psfClump.X  = psMetadataLookupF32 (&status, recipe, "PSF.CLUMP.X");  CHECK_STATUS (status, "PSF.CLUMP.X");
+        psfClump.Y  = psMetadataLookupF32 (&status, recipe, "PSF.CLUMP.Y");  CHECK_STATUS (status, "PSF.CLUMP.Y");
+        psfClump.dX = psMetadataLookupF32 (&status, recipe, "PSF.CLUMP.DX");  CHECK_STATUS (status, "PSF.CLUMP.DX");
+        psfClump.dY = psMetadataLookupF32 (&status, recipe, "PSF.CLUMP.DY");  CHECK_STATUS (status, "PSF.CLUMP.DY");
+    }
+
+    if (psfClump.X < 0) {
+        psError(PSPHOT_ERR_PROG, false, "programming error calling pmSourcePSFClump");
+        return false;
+    }
+    if (!psfClump.X || !psfClump.Y) {
+        psError(PSPHOT_ERR_DATA, true, "Failed to find a valid PSF clump");
+        return false;
+    }
+    psLogMsg ("psphot", 3, "psf clump  X,  Y: %f, %f\n", psfClump.X, psfClump.Y);
+    psLogMsg ("psphot", 3, "psf clump DX, DY: %f, %f\n", psfClump.dX, psfClump.dY);
+
+    // group into STAR, COSMIC, EXTENDED, SATURATED, etc.
+    if (!pmSourceRoughClass (sources, recipe, psfClump, maskSat)) {
+        psError(PSPHOT_ERR_PROG, false, "programming error calling pmSourceRoughClass");
+        return false;
+    }
+
+    // optional printout of source moments only
+    psphotDumpMoments (recipe, sources);
+
+    psLogMsg ("psphot.roughclass", PS_LOG_INFO, "rough classification: %f sec\n", psTimerMark ("psphot"));
+
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSavePSFStars.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSavePSFStars.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSavePSFStars.c	(revision 22158)
@@ -0,0 +1,148 @@
+# include "psphotInternal.h"
+
+bool psphotSourcePlots (pmReadout *readout, psArray *sources, psMetadata *recipe) {
+
+    // bool status = false;
+    psTimerStart ("psphot");
+
+    // if this file is defined, create the necessary output data
+    pmFPAfile *file = psMetadataLookupPtr(&status, config->files, "PSPHOT.PSF.STARS");
+
+    // the source images are written to an image 10x the size of a PSF object
+    // float OUTER = psMetadataLookupF32 (&status, recipe, "SKY_OUTER_RADIUS");
+    // PS_ASSERT (status, false);
+
+    int DX = 21;
+    int DY = 21;
+
+    // examine PSF sources in S/N order (brightest first)
+    sources = psArraySort (sources, pmSourceSortBySN);
+
+    // counters to track the size of the image and area used in a row
+    int dX = 0;				// starting corner of next box
+    int dY = 0;				// height of row so far
+    int NX = 20*DX;			// full width of output image
+    int NY = 0;				// total height of output image
+
+    // first, examine the PSF and SAT stars:
+    // - determine bounding boxes for summary image
+    for (int i = 0; i < sources->n; i++) {
+
+        pmSource *source = sources->data[i];
+
+	bool keep = false;
+        keep |= (source->mode & PM_SOURCE_MODE_PSFSTAR);
+        keep |= (source->mode & PM_SOURCE_MODE_SATSTAR);
+	if (!keep) continue;
+
+	// how does this subimage get placed into the output image?
+	// DX = source->pixels->numCols
+	// DY = source->pixels->numRows
+
+	if (dX + DX > NX) {
+	    // too wide for the rest of this row
+	    if (dX == 0) {
+		// alone on this row
+		NY += DY;
+		dX = 0;
+		dY = 0;
+	    } else {
+		// start the next row
+		NY += dY;
+		dX = DX;
+		dY = DY;
+	    }
+	} else {
+	    // extend this row
+	    dX += DX;
+	    dY = PS_MAX (dY, DY);
+	}
+    }
+
+    // allocate output image
+    psImage *outpos = psImageAlloc (NX, NY, PS_TYPE_F32);
+    psImage *outsub = psImageAlloc (NX, NY, PS_TYPE_F32);
+
+    int Xo = 0;				// starting corner of next box
+    int Yo = 0;				// starting corner of next box
+    dY = 0;				// height of row so far
+
+    int nPSF = 0;
+    int nSAT = 0;
+    int kapa = 0;			// file descriptor for plotting routine
+
+    // first, examine the PSF and SAT stars:
+    // - generate radial plots (PS plots)
+    // - create output image array
+    for (int i = 0; i < sources->n; i++) {
+
+        pmSource *source = sources->data[i];
+
+	bool keep = false;
+        if (source->mode & PM_SOURCE_MODE_PSFSTAR) {
+	    nPSF ++;
+	    keep = true;
+	}
+        if (source->mode & PM_SOURCE_MODE_SATSTAR) {
+	    nSAT ++;
+	    keep = true;
+	}	    
+	if (!keep) continue;
+
+	// how does this subimage get placed into the output image?
+	// DX = source->pixels->numCols
+	// DY = source->pixels->numRows
+
+	if (Xo + DX > NX) {
+	    // too wide for the rest of this row
+	    if (Xo == 0) {
+		// place source alone on this row
+		psphotAddWithTest (source, true); // replace source if subtracted
+		psphotRadialPlot (&kapa, "radial.plots.ps", source);
+		psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY);
+
+		psphotSubWithTest (source, false); // remove source (force)
+		psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY);
+
+		psphotSetState (source, false); // replace source (has been subtracted)
+		Yo += DY;
+		Xo = 0;
+		dY = 0;
+	    } else {
+		// start the next row
+		Yo += dY;
+		Xo = 0;
+		psphotAddWithTest (source, true); // replace source if subtracted
+		psphotRadialPlot (&kapa, "radial.plots.ps", source);
+		psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY);
+
+		psphotSubWithTest (source, false); // remove source (force)
+		psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY);
+		psphotSetState (source, false); // replace source (has been subtracted)
+
+		Xo = DX;
+		dY = DY;
+	    }
+	} else {
+	    // extend this row
+	    psphotAddWithTest (source, true); // replace source if subtracted
+	    psphotRadialPlot (&kapa, "radial.plots.ps", source);
+	    psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY);
+
+	    psphotSubWithTest (source, false); // remove source (force)
+	    psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY);
+	    psphotSetState (source, false); // replace source (has been subtracted)
+
+	    Xo += DX;
+	    dY = PS_MAX (dY, DY);
+	}
+    }
+
+    psphotSaveImage (NULL, outpos, "outpos.fits");
+    psphotSaveImage (NULL, outsub, "outsub.fits");
+    psLogMsg ("psphot", PS_LOG_INFO, "plotted %d sources (%d psf, %d sat): %f sec\n", nPSF + nSAT, nPSF, nSAT, psTimerMark ("psphot"));
+
+    psFree (outpos);
+    psFree (outsub);
+    return (sources);
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSetMaskBits.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSetMaskBits.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSetMaskBits.c	(revision 22158)
@@ -0,0 +1,32 @@
+# include "psphotInternal.h"
+
+// XXX Should it be an error for any of these to not exist?
+
+// This function is called by the stand-alone psphot program to set the mask values in the
+// config file.  It sets the named mask values MASK.PSPHOT and MARK.PSPHOT in the PSPHOT
+// recipe.  Functions or programs which call psphotReadout as a library function must set these
+// named mask values in the PSPHOT recipe on their own.
+
+bool psphotSetMaskBits (pmConfig *config) {
+
+    psMaskType maskValue;
+    psMaskType markValue;
+
+    if (!pmConfigMaskSetBits (&maskValue, &markValue, config)) {
+	psError (PS_ERR_UNKNOWN, true, "Unable to define the mask bit values");
+	return false;
+    }
+
+    // select the current recipe
+    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSPHOT_RECIPE);
+    if (!recipe) {
+        psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSPHOT_RECIPE);
+        return false;
+    }
+
+    // set maskValue and markValue in the psphot recipe
+    psMetadataAddU8 (recipe, PS_LIST_TAIL, "MARK.PSPHOT", PS_META_REPLACE, "user-defined mask", markValue);
+    psMetadataAddU8 (recipe, PS_LIST_TAIL, "MASK.PSPHOT", PS_META_REPLACE, "user-defined mask", maskValue);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSignificanceImage.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSignificanceImage.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSignificanceImage.c	(revision 22158)
@@ -0,0 +1,122 @@
+# include "psphotInternal.h"
+
+// In this function, we smooth the image and weight, then generate the significance image :
+// (S/N)^2.  If FWMH_X,Y have been recorded, use them, otherwise use PEAKS_SMOOTH_SIGMA for the
+// smoothing kernel.
+psImage *psphotSignificanceImage (pmReadout *readout, psMetadata *recipe, const int pass, psMaskType maskVal) {
+
+    float SIGMA_SMTH, NSIGMA_SMTH;
+    bool status = false;
+    bool guess = false;
+
+    // smooth the image and weight map
+    psTimerStart ("smooth");
+
+    // XXX we can a) choose fft to convolve if needed and b) multithread fftw
+
+    bool status_x, status_y;
+    float FWHM_X = psMetadataLookupF32 (&status_x, recipe, "FWHM_X");
+    float FWHM_Y = psMetadataLookupF32 (&status_y, recipe, "FWHM_Y");
+    if (status_x && status_y) {
+      // if we know the FHWM, use that to set the smoothing kernel (XXX allow an optional override?)
+      SIGMA_SMTH  = 0.5*(FWHM_X + FWHM_Y) / (2.0*sqrt(2.0*log(2.0)));
+      NSIGMA_SMTH = psMetadataLookupF32 (&status, recipe, "PEAKS_SMOOTH_NSIGMA");
+      guess = false;
+    } else {
+      // if we do not know the FWHM, use the guess smoothing kernel supplied.
+      // it is a configuration error if these are not supplied
+      SIGMA_SMTH  = psMetadataLookupF32 (&status, recipe, "PEAKS_SMOOTH_SIGMA"); 
+      PS_ASSERT (status, NULL);
+      NSIGMA_SMTH = psMetadataLookupF32 (&status, recipe, "PEAKS_SMOOTH_NSIGMA"); 
+      PS_ASSERT (status, NULL);
+      guess = true;
+    }
+    // record the actual smoothing sigma
+    psMetadataAddF32  (recipe, PS_LIST_TAIL, "SIGMA_SMOOTH", PS_META_REPLACE, "Smoothing sigma for detections", SIGMA_SMTH);
+
+    // smooth the image, applying the mask as we go
+    psImage *smooth_im = psImageCopy (NULL, readout->image, PS_TYPE_F32);
+    psImageSmoothMaskF32 (smooth_im, readout->mask, maskVal, SIGMA_SMTH, NSIGMA_SMTH);
+    psLogMsg ("psphot", PS_LOG_MINUTIA, "smooth image: %f sec\n", psTimerMark ("smooth"));
+
+    // Smooth the weight, applying the mask as we go.  The variance is smoothed by the PSF^2,
+    // renomalized to maintain the input level of the variance.  We achieve this by smoothing
+    // with a Gaussian with sigma = SIGMA_SMTH/sqrt(2) with unity normalization.  Note that
+    // this process yields a smoothed image with correlated errors.  The pixel-to-pixel
+    // variations in smooth_im will be decreased by a factor of 4*pi*SIGMA_SMTH^2, but for
+    // measurements based on apertures comparable to or larger than the smoothing kernel, the
+    // effective per-pixel variance is maintained.
+    psImage *smooth_wt = psImageCopy (NULL, readout->weight, PS_TYPE_F32);
+    psImageSmoothMaskF32 (smooth_wt, readout->mask, maskVal, SIGMA_SMTH/sqrt(2), NSIGMA_SMTH);
+    psLogMsg ("psphot", PS_LOG_MINUTIA, "smooth weight: %f sec\n", psTimerMark ("smooth"));
+
+    psImage *mask = readout->mask;
+
+    // optionally save example images under trace
+    // XXX change these to recipe value checks
+    if (psTraceGetLevel("psphot") > 5) {
+        char name[64];
+        sprintf (name, "imsmooth.v%d.fits", pass);
+        psphotSaveImage (NULL, smooth_im, name);
+        sprintf (name, "wtsmooth.v%d.fits", pass);
+        psphotSaveImage (NULL, smooth_wt, name);
+    }
+
+    // We have an input image with PSF size sigma_r.  We have smoothed it with a kernel of size
+    // sigma_s.  The result is an image with PSF size sigma_o: sigma_o^2 = sigma_r^2 +
+    // sigma_s^2.  Ideally, we are choosing sigma_s = sigma_r, in which case sigma_o^2 = 2
+    // sigma_s^2.  If we do not know the input image PSF size (initial detection stage), then
+    // we are assuming that sigma_r = sigma_s.  
+
+    // Build the significance image on top of smooth_im.  We need to correct the ratio im/wt by
+    // 2 factors: 1) the relationship the peak value and the integrated flux, and 2) the
+    // relationship between the per-pixel variance (var_i) and the total variance included in
+    // the flux measurement (effective area).  These latter correction comes from: flux = Io *
+    // 2\pi\sigma_o^2 and total variance = var_i * 4\pi\sigma_o^2, thus (S/N)^2 = flux^2 / var
+    // = (Io/var_i) \pi sigma_o^2
+
+    // in fact, because of the smoothing and the resulting correlated errors, the per-pixel
+    // varience is a bit smaller than the value predicted here.  The total variance should be
+    // \alpha 4\pi(\sigma_r_^2 + \sigma_s^2) where \alpha approaches 1 for \sigma_s / \sigma_r
+    // << 1, and \alpha approaches 0.5 for \sigma_s / \sigma_r >> 1, with a value of 0.7
+    // (actually 1/1.5) for \sigma_s = \sigma_r
+
+    // if the smoothing kernel size is known to be the psf size (\sigma_s = \sigma_r), then we
+    // can use the scaling factor of 1/1.5; otherwise, we want to be conservative and use \alpha
+    // = 0.5.  Thus, for the guess smoothing kernel, (S/N)^2 = 3.0 (Io/var_i) \pi sigma_s^2 for
+    // the guess case and (S/N)^2 = 2.0 (Io/var_i) \pi sigma_s^2 for the known case
+
+    // XXX hmm, somehow the simulations are coming up with 4pi, not 3pi (as if \alpha is 1/2.0,
+    // not 1/1.5 for sigma_s = sigma_r...
+
+    float factor = guess ? 4.0 * M_PI * PS_SQR(SIGMA_SMTH) : 4.0 * M_PI * PS_SQR(SIGMA_SMTH);
+    // record the effective area and significance scaling factor
+    float effArea = 8.0 * M_PI * PS_SQR(SIGMA_SMTH);
+    psMetadataAddF32  (recipe, PS_LIST_TAIL, "EFFECTIVE_AREA", PS_META_REPLACE, "Effective Area", effArea);
+    psMetadataAddF32  (recipe, PS_LIST_TAIL, "SIGNIFICANCE_SCALE_FACTOR", PS_META_REPLACE, "Signicance scale factor", factor);
+
+    // XXX multithread this if needed
+    for (int j = 0; j < smooth_im->numRows; j++) {
+        for (int i = 0; i < smooth_im->numCols; i++) {
+            float value = smooth_im->data.F32[j][i];
+            if (value < 0 || smooth_wt->data.F32[j][i] <= 0 || (mask->data.U8[j][i] & maskVal)) {
+                smooth_im->data.F32[j][i] = 0.0;
+            } else {
+                smooth_im->data.F32[j][i] = factor * PS_SQR(value) / smooth_wt->data.F32[j][i];
+            }
+        }
+    }
+    psLogMsg ("psphot", PS_LOG_INFO, "built smoothed signficance image: %f sec\n", psTimerMark ("smooth"));
+
+    // optionally save example images under trace
+    // XXX change these to recipe value checks
+    if (psTraceGetLevel("psphot") > 5) {
+        char name[64];
+        sprintf (name, "snsmooth.v%d.fits", pass);
+        psphotSaveImage (NULL, smooth_im, name);
+    }
+
+    psFree (smooth_wt);
+    return smooth_im;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSkyReplace.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSkyReplace.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSkyReplace.c	(revision 22158)
@@ -0,0 +1,33 @@
+# include "psphotInternal.h"
+
+// XXX make this an option?
+// in order to  successfully replace the sky, we must define a corresponding file...
+bool psphotSkyReplace (pmConfig *config, const pmFPAview *view) {
+
+    psTimerStart ("psphot");
+
+    // find the currently selected readout
+    pmReadout *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT");
+    if (readout == NULL) psAbort("input not defined");
+
+    // select background pixels, from output background file, or create
+    pmReadout *background = pmFPAfileThisReadout (config->files, view, "PSPHOT.BACKGND");
+    if (background == NULL) psAbort("background not defined");
+
+    // select the corresponding images
+    psF32 **image = readout->image->data.F32;
+    psU8  **mask  = readout->mask->data.U8;
+    psF32 **back  = background->image->data.F32;
+
+    // replace the background model
+    for (int j = 0; j < readout->image->numRows; j++) {
+        for (int i = 0; i < readout->image->numCols; i++) {
+            if (!mask[j][i]) {
+                image[j][i] += back[j][i];
+            }
+        }
+    }
+    psLogMsg ("psphot.sky", PS_LOG_DETAIL, "replace background flux : %f sec\n", psTimerMark ("psphot"));
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSortBySN.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSortBySN.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSortBySN.c	(revision 22158)
@@ -0,0 +1,1 @@
+
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSourceFits.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSourceFits.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSourceFits.c	(revision 22158)
@@ -0,0 +1,386 @@
+# include "psphotInternal.h"
+
+// given a source with an existing modelPSF, attempt a full PSF fit, subtract if successful
+// XXX this function does not call pmSourceFitModelInit : fix this?
+
+static int NfitPSF = 0;
+static int NfitBlend = 0;
+static int NfitDBL = 0;
+static int NfitEXT = 0;
+
+bool psphotFitInit () {
+    psTimerStart ("psphot.fits");
+    return true;
+}
+
+bool psphotFitSummary () {
+
+    fprintf (stderr, "fitted %5d psf, %5d blend, %5d ext, %5d dbl : %6.2f sec\n",
+             NfitPSF, NfitBlend, NfitEXT, NfitDBL, psTimerMark ("psphot.fits"));
+    return true;
+}
+
+bool psphotFitBlend (pmReadout *readout, pmSource *source, pmPSF *psf, psMaskType maskVal, psMaskType markVal) {
+
+    float x, y, dR;
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
+    // if this source is not a possible blend, just fit as PSF
+    if ((source->blends == NULL) || (source->mode & PM_SOURCE_MODE_SATSTAR)) {
+        bool status = psphotFitPSF (readout, source, psf, maskVal, markVal);
+        return status;
+    }
+
+    // save the PSF model from the Ensemble fit
+    pmModel *PSF = pmModelCopy (source->modelPSF);
+
+    if (isnan(PSF->params->data.F32[PM_PAR_I0])) psAbort("nan in blend fit primary");
+
+    x = PSF->params->data.F32[PM_PAR_XPOS];
+    y = PSF->params->data.F32[PM_PAR_YPOS];
+
+    psArray *modelSet = psArrayAllocEmpty (source->blends->n + 1);
+    psArrayAdd (modelSet, 16, PSF);
+
+    psArray *sourceSet = psArrayAllocEmpty (source->blends->n + 1);
+    psArrayAdd (sourceSet, 16, source);
+
+    // we need to include all blends in the fit (unless primary is saturated?)
+    dR = 0;
+    for (int i = 0; i < source->blends->n; i++) {
+        pmSource *blend = source->blends->data[i];
+
+        // find the blend which is furthest from source
+        dR = PS_MAX (dR, hypot (blend->peak->xf - x, blend->peak->yf - y));
+
+        // create the model and guess parameters for this blend
+        pmModel *model = pmModelAlloc (PSF->type);
+        for (int j = 0; j < model->params->n; j++) {
+            model->params->data.F32[j] = PSF->params->data.F32[j];
+            model->dparams->data.F32[j] = PSF->dparams->data.F32[j];
+        }
+
+        // XXX assume local sky is 0.0?
+        model->params->data.F32[PM_PAR_I0] = blend->peak->flux;
+        model->params->data.F32[PM_PAR_XPOS] = blend->peak->xf;
+        model->params->data.F32[PM_PAR_YPOS] = blend->peak->yf;
+
+        // these should never be invalid values
+        // XXX drop these tests eventually
+        if (isnan(model->params->data.F32[PM_PAR_I0]))   psAbort("nan in blend fit");
+        if (isnan(model->params->data.F32[PM_PAR_XPOS])) psAbort("nan in blend fit");
+        if (isnan(model->params->data.F32[PM_PAR_YPOS])) psAbort("nan in blend fit");
+
+        // add this blend to the list
+        psArrayAdd (modelSet, 16, model);
+        psArrayAdd (sourceSet, 16, blend);
+
+        // free to avoid double counting model
+        psFree (model);
+    }
+
+    // extend source radius as needed
+    psphotCheckRadiusPSFBlend (readout, source, PSF, markVal, dR);
+
+    // fit PSF model (set/unset the pixel mask)
+    pmSourceFitSet (source, modelSet, PM_SOURCE_FIT_PSF, maskVal);
+
+    // correct model chisq for flux trend
+    double chiTrend = psPolynomial1DEval (psf->ChiTrend, PSF->params->data.F32[PM_PAR_I0]);
+    PSF->chisqNorm = PSF->chisq / chiTrend;
+
+    // evaluate the blend objects, subtract if good, free otherwise
+    for (int i = 1; i < modelSet->n; i++) {
+        pmSource *blend = sourceSet->data[i];
+        pmModel *model  = modelSet->data[i];
+
+        // correct model chisq for flux trend
+        chiTrend = psPolynomial1DEval (psf->ChiTrend, model->params->data.F32[PM_PAR_I0]);
+        model->chisqNorm = model->chisq / chiTrend;
+
+        // if this one failed, skip it
+        if (!psphotEvalPSF (blend, model)) {
+            psTrace ("psphot", 4, "failed on blend %d of %ld\n", i, modelSet->n);
+            continue;
+        }
+
+        // otherwise, supply the resulting model to the corresponding blend
+        psFree(blend->modelPSF);
+        blend->modelPSF = psMemIncrRefCounter (model);
+        psTrace ("psphot", 5, "fitted blend as PSF\n");
+
+        // build cached model and subtract
+        pmSourceCacheModel (blend, maskVal);
+        pmSourceSub (blend, PM_MODEL_OP_FULL, maskVal);
+        blend->mode |=  PM_SOURCE_MODE_SUBTRACTED;
+    }
+    NfitBlend += modelSet->n;
+
+    // evaluate the primary object
+    if (!psphotEvalPSF (source, PSF)) {
+        psTrace ("psphot", 4, "failed on blend 0 of %ld\n", modelSet->n);
+        psFree (PSF);
+        psFree (modelSet);
+        psFree (sourceSet);
+        return false;
+    }
+    psFree (modelSet);
+    psFree (sourceSet);
+
+    // save the new, successful model
+    psFree (source->modelPSF);
+    source->modelPSF = PSF;
+    psTrace ("psphot", 5, "fitted primary as PSF\n");
+
+    // build cached model and subtract
+    pmSourceCacheModel (source, maskVal);
+    pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
+    source->mode |=  PM_SOURCE_MODE_SUBTRACTED;
+    return true;
+}
+
+bool psphotFitPSF (pmReadout *readout, pmSource *source, pmPSF *psf, psMaskType maskVal, psMaskType markVal) {
+
+    double chiTrend;
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
+    NfitPSF ++;
+
+    // save the PSF model from the Ensemble fit
+    pmModel *PSF = pmModelCopy (source->modelPSF);
+    if (isnan(PSF->params->data.F32[1])) psAbort("nan in psf fit");
+
+    // extend source radius as needed
+    psphotCheckRadiusPSF (readout, source, PSF, markVal);
+
+    // fit PSF model (set/unset the pixel mask)
+    pmSourceFitModel (source, PSF, PM_SOURCE_FIT_PSF, maskVal);
+
+    // correct model chisq for flux trend
+    chiTrend = psPolynomial1DEval (psf->ChiTrend, PSF->params->data.F32[PM_PAR_I0]);
+    PSF->chisqNorm = PSF->chisq / chiTrend;
+
+    // does the PSF model succeed?
+    if (!psphotEvalPSF (source, PSF)) {
+        psFree (PSF);
+        return false;
+    }
+
+    // free old model, save new model
+    psFree (source->modelPSF);
+    source->modelPSF = PSF;
+    psTrace ("psphot", 5, "fitted as PSF\n");
+
+    // build cached model and subtract
+    pmSourceCacheModel (source, maskVal);
+    pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
+    source->mode |=  PM_SOURCE_MODE_SUBTRACTED;
+    return true;
+}
+
+static float EXT_MIN_SN;
+static float EXT_MOMENTS_RAD;
+static pmModelType modelTypeEXT;
+
+bool psphotInitLimitsEXT (psMetadata *recipe) {
+
+    bool status;
+
+    // extended source model parameters
+    EXT_MIN_SN       = psMetadataLookupF32 (&status, recipe, "EXT_MIN_SN");
+    EXT_MOMENTS_RAD  = psMetadataLookupF32 (&status, recipe, "EXT_MOMENTS_RADIUS");
+
+    // extended source model descriptions
+    char *modelNameEXT = psMetadataLookupStr (&status, recipe, "EXT_MODEL");
+    modelTypeEXT = pmModelClassGetType (modelNameEXT);
+    psphotInitRadiusEXT (recipe, modelTypeEXT);
+
+    return true;
+}
+
+bool psphotFitBlob (pmReadout *readout, pmSource *source, psArray *sources, pmPSF *psf, psMaskType maskVal, psMaskType markVal) {
+
+    bool okEXT, okDBL;
+    float chiEXT, chiDBL;
+    double chiTrend;
+    pmModel *ONE = NULL;
+
+    // skip the source if we don't think it is extended
+    if (source->type == PM_SOURCE_TYPE_UNKNOWN) return false;
+    if (source->type == PM_SOURCE_TYPE_DEFECT) return false;
+    if (source->type == PM_SOURCE_TYPE_SATURATED) return false;
+    if (source->moments->SN < EXT_MIN_SN) return false;
+
+    // recalculate the source moments using the larger extended-source moments radius
+    if (!pmSourceMoments (source, EXT_MOMENTS_RAD)) return false;
+
+    psTrace ("psphot", 5, "trying blob...\n");
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
+    // this temporary source is used as a place-holder by the psphotEval functions below
+    pmSource *tmpSrc = pmSourceAlloc ();
+
+    pmModel *EXT = psphotFitEXT (readout, source, modelTypeEXT, maskVal, markVal);
+    okEXT = psphotEvalEXT (tmpSrc, EXT);
+    chiEXT = EXT->chisq / EXT->nDOF;
+
+    psArray *DBL = psphotFitDBL (readout, source, maskVal, markVal);
+    okDBL  = psphotEvalDBL (tmpSrc, DBL->data[0]);
+    okDBL &= psphotEvalDBL (tmpSrc, DBL->data[1]);
+    // XXX should I keep / save the flags set in the eval functions?
+
+    // correct first model chisqs for flux trend
+    ONE = DBL->data[0];
+    chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]);
+    ONE->chisqNorm = ONE->chisq / chiTrend;
+
+    // save chisq for double-star/galaxy comparison
+    chiDBL = ONE->chisq / ONE->nDOF;
+
+    // correct second model chisqs for flux trend
+    ONE = DBL->data[1];
+    chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]);
+    ONE->chisqNorm = ONE->chisq / chiTrend;
+
+    psFree (tmpSrc);
+
+    // psTraceSetLevel("psModules.objects.pmSourceFitSet", 0);
+
+    if (okEXT && okDBL) {
+        psTrace ("psphot", 5, "blob chisq: %f vs %f\n", chiEXT, chiDBL);
+        // XXX EAM : a bogus bias: need to examine this better
+        if (3*chiEXT > chiDBL) goto keepDBL;
+        goto keepEXT;
+    }
+
+    if (okEXT && !okDBL) goto keepEXT;
+    if (!okEXT && okDBL) goto keepDBL;
+
+    // both models failed; reject them both
+    psFree (EXT);
+    psFree (DBL);
+    return false;
+
+keepEXT:
+    // sub EXT
+    psFree (DBL);
+
+    // save new model
+    source->modelEXT = EXT;
+    source->type = PM_SOURCE_TYPE_EXTENDED;
+    source->mode |= PM_SOURCE_MODE_EXTMODEL;
+
+    // build cached model and subtract
+    pmSourceCacheModel (source, maskVal);
+    pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
+    source->mode |=  PM_SOURCE_MODE_SUBTRACTED;
+    psTrace ("psphot", 5, "blob as EXT: %f %f\n", EXT->params->data.F32[PM_PAR_XPOS], EXT->params->data.F32[PM_PAR_YPOS]);
+    return true;
+
+keepDBL:
+    // sub DLB
+    psFree (EXT);
+
+    // drop old model, save new second model...
+    psFree (source->modelPSF);
+    source->modelPSF = psMemIncrRefCounter (DBL->data[0]);
+    source->mode    |= PM_SOURCE_MODE_SUBTRACTED;
+    source->mode    |= PM_SOURCE_MODE_PAIR;
+
+    // copy most data from the primary source (modelEXT, blends stay NULL)
+    // XXX use pmSourceCopy?
+    pmSource *newSrc = pmSourceCopy (source);
+    newSrc->modelPSF = psMemIncrRefCounter (DBL->data[1]);
+
+    // build cached models and subtract
+    pmSourceCacheModel (source, maskVal);
+    pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
+    pmSourceCacheModel (newSrc, maskVal);
+    pmSourceSub (newSrc, PM_MODEL_OP_FULL, maskVal);
+    psTrace ("psphot", 5, "blob as DBL: %f %f\n", ONE->params->data.F32[PM_PAR_XPOS], ONE->params->data.F32[PM_PAR_YPOS]);
+
+    psArrayAdd (sources, 100, newSrc);
+    psFree (newSrc);
+    psFree (DBL);
+    return true;
+}
+
+// fit a double PSF source to an extended blob
+psArray *psphotFitDBL (pmReadout *readout, pmSource *source, psMaskType maskVal, psMaskType markVal) {
+
+    float dx, dy;
+    pmModel *DBL;
+    pmModel *PSF;
+    psEllipseAxes axes;
+    psEllipseMoments moments;
+    psArray *modelSet;
+
+    NfitDBL ++;
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
+    // make a guess at the position of the two sources
+    moments.x2 = source->moments->Sx;
+    moments.y2 = source->moments->Sy;
+    moments.xy = source->moments->Sxy;
+    axes = psEllipseMomentsToAxes (moments, 20.0);
+
+    // XXX this is really arbitrary: 4 pixel separation?
+    dx = 2 * cos (axes.theta);
+    dy = 2 * sin (axes.theta);
+
+    // save the PSF model from the Ensemble fit
+    PSF = source->modelPSF;
+    psphotCheckRadiusPSFBlend (readout, source, PSF, markVal, 8.0);
+    if (isnan(PSF->params->data.F32[1])) psAbort("nan in dbl fit");
+
+    modelSet = psArrayAlloc (2);
+
+    DBL = pmModelCopy (PSF);
+    DBL->params->data.F32[PM_PAR_I0]  *= 0.5;
+    DBL->params->data.F32[PM_PAR_XPOS] = source->peak->xf + dx;
+    DBL->params->data.F32[PM_PAR_YPOS] = source->peak->yf + dy;
+    modelSet->data[0] = DBL;
+
+    DBL = pmModelCopy (PSF);
+    DBL->params->data.F32[PM_PAR_I0]  *= 0.5;
+    DBL->params->data.F32[PM_PAR_XPOS] = source->peak->xf - dx;
+    DBL->params->data.F32[PM_PAR_YPOS] = source->peak->yf - dy;
+    modelSet->data[1] = DBL;
+
+    // fit PSF model (set/unset the pixel mask)
+    pmSourceFitSet (source, modelSet, PM_SOURCE_FIT_PSF, maskVal);
+    return (modelSet);
+}
+
+pmModel *psphotFitEXT (pmReadout *readout, pmSource *source, pmModelType modelType, psMaskType maskVal, psMaskType markVal) {
+
+    NfitEXT ++;
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
+    // use the source moments, etc to guess basic model parameters
+    pmModel *EXT = pmSourceModelGuess (source, modelType);
+    PS_ASSERT (EXT, NULL);
+
+    // if (isnan(EXT->params->data.F32[1])) psAbort("nan in ext fit");
+
+    psphotCheckRadiusEXT (readout, source, EXT, markVal);
+
+    if ((source->moments->Sx < 1e-3) || (source->moments->Sx < 1e-3)) {
+        psTrace ("psphot", 5, "problem source: moments: %f %f\n", source->moments->Sx, source->moments->Sy);
+    }
+
+    // fit EXT (not PSF) model (set/unset the pixel mask)
+    pmSourceFitModel (source, EXT, PM_SOURCE_FIT_EXT, maskVal);
+    return (EXT);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSourceFreePixels.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSourceFreePixels.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSourceFreePixels.c	(revision 22158)
@@ -0,0 +1,12 @@
+# include "psphotInternal.h"
+
+void psphotSourceFreePixels (psArray *sources) {
+
+    if (!sources) return;
+
+    for (int i = 0; i < sources->n; i++) {
+	pmSource *source = sources->data[i];
+	pmSourceFreePixels (source);
+    }
+    return;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSourcePlots.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSourcePlots.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSourcePlots.c	(revision 22158)
@@ -0,0 +1,162 @@
+# include "psphotInternal.h"
+
+bool psphotSourcePlots (pmReadout *readout, psArray *sources, psMetadata *recipe) {
+
+    bool status = false;
+    psTimerStart ("psphot");
+
+    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
+    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
+    assert (maskVal);
+
+    // the source images are written to an image 10x the size of a PSF object
+    // float OUTER = psMetadataLookupF32 (&status, recipe, "SKY_OUTER_RADIUS");
+    // PS_ASSERT (status, false);
+
+    int DX = 21;
+    int DY = 21;
+
+    // examine PSF sources in S/N order (brightest first)
+    sources = psArraySort (sources, pmSourceSortBySN);
+
+    // counters to track the size of the image and area used in a row
+    int dX = 0;                         // starting corner of next box
+    int dY = 0;                         // height of row so far
+    int NX = 20*DX;                     // full width of output image
+    int NY = DY;                        // total height of output image so far
+
+    // first, examine the PSF and SAT stars to set output image size:
+    // - add stamp widths until we exceed output image width,
+    // - then start a new row offset by max height
+    for (int i = 0; i < sources->n; i++) {
+
+        pmSource *source = sources->data[i];
+
+        bool keep = false;
+        keep |= (source->mode & PM_SOURCE_MODE_PSFSTAR);
+        keep |= (source->mode & PM_SOURCE_MODE_SATSTAR);
+        if (!keep) {
+	    psTrace ("psphot", 4, "not plotting star %d: %x", i, source->mode);
+	    continue;
+	}
+
+        // how does this subimage get placed into the output image?
+        // DX = source->pixels->numCols
+        // DY = source->pixels->numRows
+
+        if (dX + DX > NX) {
+            // too wide for the rest of this row
+            if (dX == 0) {
+                // alone on this row
+                NY += DY;
+                dX = 0;
+                dY = 0;
+            } else {
+                // start the next row
+                NY += dY;
+                dX = DX;
+                dY = DY;
+            }
+        } else {
+            // extend this row
+            dX += DX;
+            dY = PS_MAX (dY, DY);
+        }
+    }
+
+    if (NY == 0) {
+	psWarning ("no PSF or SAT stars to plot? skipping.\n");
+	return false;
+    }
+
+    // allocate output image
+    psImage *outpos = psImageAlloc (NX, NY, PS_TYPE_F32);
+    psImage *outsub = psImageAlloc (NX, NY, PS_TYPE_F32);
+
+    psImageInit (outpos, 0.0);
+    psImageInit (outsub, 0.0);
+
+    int Xo = 0;                         // starting corner of next box
+    int Yo = 0;                         // starting corner of next box
+    dY = 0;                             // height of row so far
+
+    int nPSF = 0;
+    int nSAT = 0;
+    int kapa = 0;                       // file descriptor for plotting routine
+
+    // first, examine the PSF and SAT stars:
+    // - generate radial plots (PS plots)
+    // - create output image array
+    for (int i = 0; i < sources->n; i++) {
+
+        pmSource *source = sources->data[i];
+
+        bool keep = false;
+        if (source->mode & PM_SOURCE_MODE_PSFSTAR) {
+            nPSF ++;
+            keep = true;
+        }
+        if (source->mode & PM_SOURCE_MODE_SATSTAR) {
+            nSAT ++;
+            keep = true;
+        }
+        if (!keep) continue;
+
+        // how does this subimage get placed into the output image?
+        // DX = source->pixels->numCols
+        // DY = source->pixels->numRows
+
+        if (Xo + DX > NX) {
+            // too wide for the rest of this row
+            if (Xo == 0) {
+                // place source alone on this row
+                psphotAddWithTest (source, true, maskVal); // replace source if subtracted
+                psphotRadialPlot (&kapa, "radial.plots.ps", source);
+                psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY);
+
+                psphotSubWithTest (source, false, maskVal); // remove source (force)
+                psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY);
+
+                psphotSetState (source, false, maskVal); // replace source (has been subtracted)
+                Yo += DY;
+                Xo = 0;
+                dY = 0;
+            } else {
+                // start the next row
+                Yo += dY;
+                Xo = 0;
+                psphotAddWithTest (source, true, maskVal); // replace source if subtracted
+                psphotRadialPlot (&kapa, "radial.plots.ps", source);
+                psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY);
+
+                psphotSubWithTest (source, false, maskVal); // remove source (force)
+                psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY);
+                psphotSetState (source, false, maskVal); // replace source (has been subtracted)
+
+                Xo = DX;
+                dY = DY;
+            }
+        } else {
+            // extend this row
+            psphotAddWithTest (source, true, maskVal); // replace source if subtracted
+            psphotRadialPlot (&kapa, "radial.plots.ps", source);
+            psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY);
+
+            psphotSubWithTest (source, false, maskVal); // remove source (force)
+            psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY);
+            psphotSetState (source, false, maskVal); // replace source (has been subtracted)
+
+            Xo += DX;
+            dY = PS_MAX (dY, DY);
+        }
+    }
+
+    psphotSaveImage (NULL, outpos, "outpos.fits");
+    psphotSaveImage (NULL, outsub, "outsub.fits");
+    psLogMsg ("psphot", PS_LOG_INFO, "plotted %d sources (%d psf, %d sat): %f sec\n", nPSF + nSAT, nPSF, nSAT, psTimerMark ("psphot"));
+
+    psFree (outpos);
+    psFree (outsub);
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSourceSize.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSourceSize.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSourceSize.c	(revision 22158)
@@ -0,0 +1,312 @@
+# include "psphotInternal.h"
+# include <gsl/gsl_sf_gamma.h>
+
+float psphotModelContour (psImage *image, psImage *weight, psImage *mask, pmModel *model, float Ro);
+
+// we need to call this function after sources have been fitted to the PSF model and
+// subtracted.  To determine the CR-nature, this function examines the 9 pixels in the 3x3
+// square containing the peak and compares the observed flux to the model.  To determine
+// the EXT-nature, this function measures the amount of positive or negative total
+// deviation from the psf model at the r = FWHM/2 position
+
+bool psphotSourceSize (pmConfig *config, pmReadout *readout, psArray *sources, psMetadata *recipe, long first) {
+
+    bool status;
+
+    psTimerStart ("psphot");
+
+    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
+    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
+    assert (maskVal);
+
+    // bit to mask the cosmic-ray pixels
+    psMaskType crMask  = pmConfigMaskGet("CR", config); // Mask value for cosmic rays
+
+    float CR_NSIGMA_LIMIT = psMetadataLookupF32 (&status, recipe, "PSPHOT.CR.NSIGMA.LIMIT");
+    assert (status);
+
+    float EXT_NSIGMA_LIMIT = psMetadataLookupF32 (&status, recipe, "PSPHOT.EXT.NSIGMA.LIMIT");
+    assert (status);
+
+    // loop over all source
+    for (int i = first; i < sources->n; i++) {
+	pmSource *source = sources->data[i];
+
+	// skip source if it was already measured
+	if (isfinite(source->crNsigma)) continue;
+
+	// source must have been subtracted
+	if (!(source->mode & PM_SOURCE_MODE_SUBTRACTED)) continue;
+
+	psF32 **resid  = source->pixels->data.F32;
+	psF32 **weight = source->weight->data.F32;
+	psU8 **mask    = source->maskObj->data.U8;
+
+	// check for extendedness: measure the delta flux significance at the 1 sigma contour
+	source->extNsigma = psphotModelContour (source->pixels, source->weight, source->maskObj, source->modelPSF, 1.0);
+
+	// XXX prevent a source from being both CR and EXT?
+	if (source->extNsigma > EXT_NSIGMA_LIMIT) {
+	  source->mode |= PM_SOURCE_MODE_EXT_LIMIT;
+	}
+
+	int xPeak = source->peak->xf - source->pixels->col0 + 0.5;
+	int yPeak = source->peak->yf - source->pixels->row0 + 0.5;
+
+	// XXX for now, skip sources which are too close to a boundary
+	// XXX raise a flag?
+	if (xPeak < 1) continue;
+	if (xPeak > source->pixels->numCols - 2) continue;
+	if (yPeak < 1) continue;
+	if (yPeak > source->pixels->numRows - 2) continue;
+
+	// XXX for now, just skip any sources with masked pixels
+	// XXX raise a flag?
+	bool keep = true;
+	for (int iy = -1; (iy <= +1) && keep; iy++) {
+	    for (int ix = -1; (ix <= +1) && keep; ix++) {
+		if (mask[yPeak+iy][xPeak+ix]) { keep &= false; }
+	    }
+	}
+	if (!keep) continue;
+
+	// XXX need to deal with edge peaks... and mask
+	float cX = 2*resid[yPeak][xPeak] - resid[yPeak+0][xPeak-1] - resid[yPeak+0][xPeak+1];
+	float cY = 2*resid[yPeak][xPeak] - resid[yPeak+1][xPeak+0] - resid[yPeak+1][xPeak+0];
+	float cL = 2*resid[yPeak][xPeak] - resid[yPeak-1][xPeak-1] - resid[yPeak+1][xPeak+1];
+	float cR = 2*resid[yPeak][xPeak] - resid[yPeak+1][xPeak-1] - resid[yPeak-1][xPeak+1];
+
+	float dcX = 4*weight[yPeak][xPeak] + weight[yPeak+0][xPeak-1] + weight[yPeak+0][xPeak+1];
+	float dcY = 4*weight[yPeak][xPeak] + weight[yPeak+1][xPeak+0] + weight[yPeak+1][xPeak+0];
+	float dcL = 4*weight[yPeak][xPeak] + weight[yPeak-1][xPeak-1] + weight[yPeak+1][xPeak+1];
+	float dcR = 4*weight[yPeak][xPeak] + weight[yPeak+1][xPeak-1] + weight[yPeak-1][xPeak+1];
+
+	float nX = cX / sqrt(dcX);
+	float nY = cY / sqrt(dcY);
+	float nL = cL / sqrt(dcL);
+	float nR = cR / sqrt(dcR);
+
+	// P(chisq > chisq_obs; Ndof) = gamma_Q (Ndof/2, chisq/2)
+	// Ndof = 4 ? (four measurements, no free parameters)
+	// XXX this value is going to be biased low because of systematic errors.
+	// we need to calibrate it somehow
+	// source->psfProb = gsl_sf_gamma_inc_Q (2, 0.5*chisq);
+
+	// not strictly accurate: overcounts the chisq contribution from the center pixel (by factor of 4)
+	source->psfChisq = PS_SQR (nX) + PS_SQR (nY) + PS_SQR (nX) + PS_SQR (nR);
+
+	float fCR = 0.0;
+	float fEXT = 0.0;
+	int nCR = 0;
+	int nEXT = 0;
+	if (nX > 0.0) {
+	    fCR += nX;
+	    nCR ++;
+	} else {
+	    fEXT += nX;
+	    nEXT ++;
+	}
+	if (nY > 0.0) {
+	    fCR += nY;
+	    nCR ++;
+	} else {
+	    fEXT += nY;
+	    nEXT ++;
+	}
+	if (nL > 0.0) {
+	    fCR += nL;
+	    nCR ++;
+	} else {
+	    fEXT += nL;
+	    nEXT ++;
+	}
+	if (nR > 0.0) {
+	    fCR += nR;
+	    nCR ++;
+	} else {
+	    fEXT += nR;
+	    nEXT ++;
+	}
+	source->crNsigma  = (nCR > 0)  ? fCR / nCR : 0.0;
+	// NOTE: abs needed to make the Nsigma value positive 
+
+	if (!isfinite(source->crNsigma)) {
+	  fprintf (stderr, ".");
+	  source->crNsigma = -6.0;
+	}
+
+	// this source is thought to be a cosmic ray.  flag the detection and mask the pixels
+	if (source->crNsigma > CR_NSIGMA_LIMIT) {
+	    source->mode |= PM_SOURCE_MODE_CR_LIMIT;
+	    pmPeak *peak = source->peak;
+	    psAssert (peak, "NULL peak");
+
+	    // replace the source flux
+	    pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
+	    source->mode &= ~PM_SOURCE_MODE_SUBTRACTED;
+
+	    psImage *mask   = source->maskView;
+	    psImage *pixels = source->pixels;
+	    psImage *weight = source->weight;
+
+	    # define SN_LIMIT 5.0
+
+	    int xo = peak->x - pixels->col0;
+	    int yo = peak->y - pixels->row0;
+
+	    // mark the pixels in this row to the left, then the right
+	    for (int ix = xo; ix >= 0; ix--) {
+		float SN = pixels->data.F32[yo][ix] / sqrt(weight->data.F32[yo][ix]);
+		if (SN > SN_LIMIT) {
+		    mask->data.U8[yo][ix] |= crMask;
+		}
+	    }
+	    for (int ix = xo + 1; ix < pixels->numCols; ix++) {
+		float SN = pixels->data.F32[yo][ix] / sqrt(weight->data.F32[yo][ix]);
+		if (SN > SN_LIMIT) {
+		    mask->data.U8[yo][ix] |= crMask;
+		}
+	    }
+
+	    // for each of the neighboring rows, mark the high pixels if they have a marked neighbor 
+	    // first go up:
+	    for (int iy = yo; iy >= 0; iy--) {
+		// mark the pixels in this row to the left, then the right
+		for (int ix = 0; ix < pixels->numCols; ix++) {
+		    float SN = pixels->data.F32[iy][ix] / sqrt(weight->data.F32[iy][ix]);
+		    if (SN < SN_LIMIT) continue;
+		    
+		    bool valid = false;
+		    valid |= (mask->data.U8[iy+1][ix] & crMask);
+		    valid |= (ix > 0) ? (mask->data.U8[iy+1][ix-1] & crMask) : 0;
+		    valid |= (ix <= mask->numCols) ? (mask->data.U8[iy+1][ix+1] & crMask) : 0;
+
+		    if (!valid) continue;
+		    mask->data.U8[iy][ix] |= crMask;
+		}
+	    }
+	    // next go down:
+	    for (int iy = yo+1; iy < pixels->numRows; iy++) {
+		// mark the pixels in this row to the left, then the right
+		for (int ix = 0; ix < pixels->numCols; ix++) {
+		    float SN = pixels->data.F32[iy][ix] / sqrt(weight->data.F32[iy][ix]);
+		    if (SN < SN_LIMIT) continue;
+		    
+		    bool valid = false;
+		    valid |= (mask->data.U8[iy-1][ix] & crMask);
+		    valid |= (ix > 0) ? (mask->data.U8[iy-1][ix-1] & crMask) : 0;
+		    valid |= (ix <= mask->numCols) ? (mask->data.U8[iy-1][ix+1] & crMask) : 0;
+
+		    if (!valid) continue;
+		    mask->data.U8[iy][ix] |= crMask;
+		}
+	    }
+	}
+    }
+
+    psLogMsg ("psphot.size", PS_LOG_INFO, "measure source sizes for %ld sources: %f sec\n", sources->n - first, psTimerMark ("psphot"));
+
+    return true;
+}
+
+
+// some possible classes:
+// all 4 curvatures are highly negative : CR
+// all 4 curvatures are highly positive : EXT
+
+// at least 2 are significantly negative, none are significantly positive : CR
+// at least 2 are significantly positive, none are significantly negative : EXT
+
+// any are significantly negative, some may be significantly positive : CR
+// any are significantly positive, none may be significantly positive : EXT
+	
+/* Nn  Np  No
+   4   0   0   CR_1
+   3   1   0   CR_1
+   3   0   1   CR_1
+   2   2   0   CR_2
+   2   1   1   CR_2
+   2   0   2   CR_2
+   1   3   0   CR_3
+   1   2   1   CR_3
+   1   1   2   CR_3
+   1   0   3   CR_3
+   0   4   0   EXT
+   0   3   1   EXT
+   0   2   2   EXT
+   0   1   3   PSF
+   0   0   4   PSF
+*/
+
+/* Alternatively, write a f(CR) = Sum(nX,etc if >0) */
+	  
+
+/* I can write the formal probability that the 4 measurements are consistent with a PSF
+ * based on how large the error values are (Nsigma -> erf -> P(Nsigma)).
+ * I should examine this value as a function of flux and also examine the distribution of
+ * the probabilities for the PSF sources.
+ */
+
+
+// given the PSF ellipse parameters, navigate around the 1sigma contour, return the total
+// deviation in sigmas.  This is measure on the residual image - should we ignore negative
+// deviations?
+float psphotModelContour (psImage *image, psImage *weight, psImage *mask, pmModel *model, float Ro) {
+
+    psF32 *PAR = model->params->data.F32;
+
+    // Ro = (x / SXX)^2 + (y / SYY)^2 + x y SXY;
+    // y^2 (1/SYY^2) + y (x SXY) + (x / SXX)^2 - Ro = 0;
+    // y = [-(x SXY) +/- sqrt ((x SXY)^2 - 4 (1/SYY^2) ((x/SXX)^2 - Ro))] * [SYY^2 / 2];
+    // y = [-B +/- sqrt (B^2 - 4 A C)] / [2 A];
+
+    // min/max value of x is where T -> 0
+    // solve this for x2:
+    float Q = Ro * PS_SQR(PAR[PM_PAR_SXX]) / (1.0 - PS_SQR(PAR[PM_PAR_SXX]*PAR[PM_PAR_SYY]*PAR[PM_PAR_SXY]) / 4.0);
+    if (Q < 0.0) return NAN; // ellipse is imaginary
+
+    int xMax = sqrt(Q);
+    int xMin = -1.0*xMax;
+
+    int nPts = 0;
+    float nSigma = 0.0;
+
+    for (int x = xMin; x <= xMax; x++) {
+	float A = PS_SQR (1.0 / PAR[PM_PAR_SYY]);
+	float B = x * PAR[PM_PAR_SXY];
+	float C = PS_SQR (x / PAR[PM_PAR_SXX]) - Ro;
+
+	float T = PS_SQR(B) - 4*A*C;
+	if (T < 0.0) continue;
+    
+	float yP = (-B + sqrt (T)) / (2.0 * A);
+	float yM = (-B - sqrt (T)) / (2.0 * A);
+
+	int xPix  = x  + PAR[PM_PAR_XPOS] - image->col0 + 0.5;
+	int yPixM = yM + PAR[PM_PAR_YPOS] - image->row0 + 0.5;
+	int yPixP = yP + PAR[PM_PAR_YPOS] - image->row0 + 0.5;
+
+	if (xPix < 0) continue;
+	if (xPix >= image->numCols) continue;
+
+	if ((yPixM >= 0) && (yPixM < image->numRows)) {
+	    if (!mask || !mask->data.U8[yPixM][xPix]) {
+		float dSigma = image->data.F32[yPixM][xPix] / sqrt (weight->data.F32[yPixM][xPix]);
+		nSigma += dSigma;
+		nPts ++;
+	    }
+	}
+	
+	if (yPixM == yPixP) continue;
+
+	if ((yPixP >= 0) && (yPixP < image->numRows)) {
+	    if (!mask || !mask->data.U8[yPixP][xPix]) {
+		float dSigma = image->data.F32[yPixP][xPix] / sqrt (weight->data.F32[yPixP][xPix]);
+		nSigma += dSigma;
+		nPts ++;
+	    }
+	}
+    }	
+    nSigma /= nPts;
+    return nSigma;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSourceStats.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSourceStats.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSourceStats.c	(revision 22158)
@@ -0,0 +1,126 @@
+# include "psphotInternal.h"
+
+psArray *psphotSourceStats (pmReadout *readout, psMetadata *recipe, pmDetections *detections)
+{
+    bool     status  = false;
+    psArray *sources = NULL;
+    float BIG_RADIUS;
+
+    psTimerStart ("psphot");
+
+    // bit-masks to test for good/bad pixels
+    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT");
+    assert (maskVal);
+
+    // bit-mask to mark pixels not used in analysis
+    psMaskType markVal = psMetadataLookupU8(&status, recipe, "MARK.PSPHOT");
+    assert (markVal);
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
+    // determine properties (sky, moments) of initial sources
+    float INNER    = psMetadataLookupF32 (&status, recipe, "SKY_INNER_RADIUS");
+    if (!status) return NULL;
+    float OUTER    = psMetadataLookupF32 (&status, recipe, "SKY_OUTER_RADIUS");
+    if (!status) return NULL;
+    float RADIUS   = psMetadataLookupF32 (&status, recipe, "PSF_MOMENTS_RADIUS");
+    if (!status) return NULL;
+    float MIN_SN   = psMetadataLookupF32 (&status, recipe, "MOMENTS_SN_MIN");
+    if (!status) return NULL;
+    char *breakPt  = psMetadataLookupStr (&status, recipe, "BREAK_POINT");
+    if (!status) return NULL;
+
+    psArray *peaks = detections->peaks;
+    if (!peaks) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "No peaks found!");
+        return NULL;
+    }
+
+    sources = psArrayAllocEmpty (peaks->n);
+
+    int Nfail = 0;
+    int Nmoments = 0;
+    for (int i = 0; i < peaks->n; i++) {
+
+        pmPeak *peak = peaks->data[i];
+        if (peak->assigned) continue;
+
+        // create a new source, add peak
+        pmSource *source = pmSourceAlloc();
+        source->peak = psMemIncrRefCounter(peak);
+
+        // allocate image, weight, mask arrays for each peak (square of radius OUTER)
+        pmSourceDefinePixels (source, readout, source->peak->x, source->peak->y, OUTER);
+        if (!strcasecmp (breakPt, "PEAKS")) {
+            peak->assigned = true;
+            psArrayAdd (sources, 100, source);
+            psFree (source);
+            continue;
+        }
+
+        // skip faint sources for moments measurement
+        if (source->peak->SN < MIN_SN) {
+            peak->assigned = true;
+            psArrayAdd (sources, 100, source);
+            psFree (source);
+            continue;
+        }
+
+        // measure a local sky value
+        // the local sky is now ignored; kept here for reference only
+        status = pmSourceLocalSky (source, PS_STAT_SAMPLE_MEDIAN, INNER, maskVal, markVal);
+        if (!status) {
+          psFree (source);
+          Nfail ++;
+          psErrorClear();
+          continue;
+        }
+
+        // measure the local sky variance (needed if noise is not sqrt(signal))
+        // XXX EAM : this should use ROBUST not SAMPLE median, but it is broken
+        status = pmSourceLocalSkyVariance (source, PS_STAT_SAMPLE_MEDIAN, INNER, maskVal, markVal);
+        if (!status) {
+          psFree (source);
+          Nfail ++;
+          psErrorClear();
+          continue;
+        }
+
+        // measure basic source moments
+        status = pmSourceMoments (source, RADIUS);
+        if (status) {
+            // add to the source array
+            peak->assigned = true;
+            psArrayAdd (sources, 100, source);
+            psFree (source);
+            Nmoments ++;
+            continue;
+        }
+
+        // if no valid pixels, or massive swing, likely saturated source,
+        // try a much larger box
+        BIG_RADIUS = PS_MIN (INNER, 3*RADIUS);
+        psTrace ("psphot", 4, "retrying moments for %d, %d\n", source->peak->x, source->peak->y);
+        status = pmSourceMoments (source, BIG_RADIUS);
+        if (status) {
+            // add to the source array
+            peak->assigned = true;
+            psArrayAdd (sources, 100, source);
+            psFree (source);
+            Nmoments ++;
+            continue;
+        }
+
+        psFree (source);
+        Nfail ++;
+        psErrorClear();
+        continue;
+    }
+
+    psLogMsg ("psphot", PS_LOG_INFO, "%ld sources, %d moments, %d failed: %f sec\n", sources->n, Nmoments, Nfail, psTimerMark ("psphot"));
+
+    return (sources);
+}
+
+// XXX EAM : filter out bad peaks (eg, no valid pixels available for sky)
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotStandAlone.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotStandAlone.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotStandAlone.h	(revision 22158)
@@ -0,0 +1,21 @@
+# ifdef HAVE_CONFIG_H
+# include <config.h>
+# endif
+
+#ifndef PSPHOT_STAND_ALONE_H
+#define PSPHOT_STAND_ALONE_H
+
+#include <stdio.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "psphot.h"
+
+// Top level functions
+pmConfig       *psphotArguments (int argc, char **argv);
+bool            psphotParseCamera (pmConfig *config);
+bool            psphotImageLoop (pmConfig *config);
+bool            psphotMosaicChip(pmConfig *config, const pmFPAview *view, char *outFile, char *inFile);
+void            psphotCleanup (pmConfig *config);
+psExit          psphotGetExitStatus ();
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSubtractBackground.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSubtractBackground.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSubtractBackground.c	(revision 22158)
@@ -0,0 +1,113 @@
+# include "psphotInternal.h"
+static int npass = 0;
+
+// generate the median in NxN boxes, clipping heavily
+// linear interpolation to generate full-scale model
+bool psphotSubtractBackground (pmConfig *config, const pmFPAview *view, const char *filename) 
+{
+    bool status = true;
+    pmReadout *background = NULL;
+    pmReadout *backSub = NULL;
+
+    psTimerStart ("psphot");
+
+    // find the currently selected readout
+    pmFPAfile *file = psMetadataLookupPtr (&status, config->files, filename);
+    pmFPA *inFPA = file->fpa;
+    pmReadout *readout = pmFPAviewThisReadout (view, inFPA);
+    psImage *image = readout->image;
+    psImage *mask  = readout->mask;
+
+    // find the currently selected readout
+    pmReadout *model = pmFPAfileThisReadout (config->files, view, "PSPHOT.BACKMDL");
+    assert (model);
+
+    // select the appropriate recipe information
+    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
+    assert (recipe);
+
+    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
+    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
+    assert (maskVal);
+
+    psImageBinning *binning = psMetadataLookupPtr(&status, recipe, "PSPHOT.BACKGROUND.BINNING");
+    assert (binning);
+
+    // select background pixels, from output background file, or create
+    file = psMetadataLookupPtr (&status, config->files, "PSPHOT.BACKGND");
+    if (file) {
+        // we are using PSPHOT.BACKGND as an I/O file: select readout or create
+        if (file->mode == PM_FPA_MODE_INTERNAL) {
+            background = file->readout;
+        } else {
+            background = pmFPAviewThisReadout (view, file->fpa);
+        }
+        if (background == NULL) {
+            // readout does not yet exist: create from input
+            pmFPAfileCopyStructureView (file->fpa, inFPA, 1, 1, view);
+            background = pmFPAviewThisReadout (view, file->fpa);
+            if ((image->numCols != background->image->numCols) || (image->numRows != background->image->numRows)) {
+                psError (PSPHOT_ERR_PROG, true, "inconsistent sizes for background dimensions");
+                return false;
+            }
+        }
+    } else {
+        background = pmFPAfileDefineInternal (config->files, "PSPHOT.BACKGND", image->numCols, image->numRows, PS_TYPE_F32);
+    }
+    psF32 **backData = background->image->data.F32;
+
+    // linear interpolation to full-scale
+    if (!psImageUnbin (background->image, model->image, binning)) {
+        psError (PSPHOT_ERR_PROG, true, "inconsistent sizes for unbinning");
+        return false;
+    }
+
+    psLogMsg ("psphot", PS_LOG_MINUTIA, "build resampled image: %f sec\n", psTimerMark ("psphot"));
+
+    // back-sub image pixels, from output background file (don't create if not requested)
+    file = psMetadataLookupPtr (&status, config->files, "PSPHOT.BACKSUB");
+    if (file) {
+        // we are using PSPHOT.BACKSUB as an I/O file: select readout or create
+        backSub = pmFPAviewThisReadout (view, file->fpa);
+        if (backSub == NULL) {
+            // readout does not yet exist: create from input
+            pmFPAfileCopyStructureView (file->fpa, inFPA, 1, 1, view);
+            backSub = pmFPAviewThisReadout (view, file->fpa);
+        }
+    }
+
+    if (psTraceGetLevel("psphot") > 5) {
+        char name[256];
+        sprintf (name, "image.%02d.fits", npass);
+        psphotSaveImage (NULL, image, name);
+        sprintf (name, "back.%02d.fits", npass);
+        psphotSaveImage (NULL, background->image, name);
+        sprintf (name, "mask.%02d.fits", npass);
+        psphotSaveImage (NULL, mask, name);
+        sprintf (name, "backmdl.%02d.fits", npass);
+        psphotSaveImage (NULL, model->image, name);
+    }
+
+    // subtract the background model (save in backSub, if requested)
+    // XXX if needed, multithread this (fairly trivial)
+    for (int j = 0; j < image->numRows; j++) {
+        for (int i = 0; i < image->numCols; i++) {
+            image->data.F32[j][i] -= backData[j][i];
+            if (backSub) {
+                backSub->image->data.F32[j][i] = image->data.F32[j][i];
+            }
+        }
+    }
+
+    if (psTraceGetLevel("psphot") > 5) {
+        char name[256];
+        sprintf (name, "backsub.%02d.fits", npass);
+        psphotSaveImage (NULL, image, name);
+    }
+    psLogMsg ("psphot", PS_LOG_INFO, "subtracted background model: %f sec\n", psTimerMark ("psphot"));
+
+    // the pmReadout selected in this function are all view on entries in config->files
+
+    npass ++;
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSummaryPlots.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSummaryPlots.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotSummaryPlots.c	(revision 22158)
@@ -0,0 +1,280 @@
+# include "psphotInternal.h"
+
+// the top portion of this file defines plotting functions which use kapa for plotting.
+// if kapa is not available, these functions are defined in the bottom portion as stubs
+// which perform NOP and return false (XXX should this be true??)
+
+// this variable is defined in psmodules.h if ohana-config is found
+# if (HAVE_KAPA)
+
+# include <kapa.h>
+
+// plot the sx, sy moments plane (faint and bright sources)
+bool psphotPlotMoments (pmConfig *config, pmFPAview *view, psArray *sources) {
+
+    // select model pixels (from output background model file, or create internal file)
+    pmFPAfile *file = psMetadataLookupPtr (NULL, config->files, "PSPHOT.MOMENT.PLT");
+    if (file == NULL) {
+	psLogMsg ("psphot", 3, "skipping moments plot");
+	return false;
+    }
+
+    // pmFPAfileOpen defers disk I/O for KAPA files: just get the correct name
+    pmFPAfileOpen (file, view, config);
+
+    Graphdata graphdata;
+
+    psLogMsg ("psphot", 3, "creating moments plot");
+
+    // XXX get the 'showWindow' option from the recipes somewhere
+    int kapa = pmKapaOpen (false);
+    if (kapa == -1) {
+	psError(PSPHOT_ERR_UNKNOWN, true, "failure to open kapa");
+	return false;
+    }
+
+    KapaResize (kapa, 500, 500);
+    KapaInitGraph (&graphdata);
+
+    // examine sources to set data range
+    graphdata.xmin = -0.05;
+    graphdata.ymin = -0.05;
+    graphdata.xmax = +2.05;
+    graphdata.ymax = +2.05;
+    KapaSetLimits (kapa, &graphdata);
+  
+    KapaSetFont (kapa, "helvetica", 14);
+    KapaBox (kapa, &graphdata);
+    KapaSendLabel (kapa, "&ss&h_x| (pixels)", KAPA_LABEL_XM);
+    KapaSendLabel (kapa, "&ss&h_y| (pixels)", KAPA_LABEL_YM);
+	       
+    psVector *xBright = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
+    psVector *yBright = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
+    psVector *xFaint  = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
+    psVector *yFaint  = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
+
+    // construct the vectors
+    int nB = 0;
+    int nF = 0;
+    for (int i = 0; i < sources->n; i++) {
+	pmSource *source = sources->data[i];
+	if (source->moments == NULL) continue;
+    
+	xFaint->data.F32[nF] = source->moments->Sx;
+	yFaint->data.F32[nF] = source->moments->Sy;
+	nF++;
+    
+	// XXX make this a user-defined cutoff
+	if (source->moments->SN < 25) continue;
+
+	xBright->data.F32[nB] = source->moments->Sx;
+	yBright->data.F32[nB] = source->moments->Sy;
+	nB++;
+    }
+    xFaint->n = nF;
+    yFaint->n = nF;
+
+    xBright->n = nB;
+    yBright->n = nB;
+  
+    graphdata.color = KapaColorByName ("black");
+    graphdata.ptype = 0;
+    graphdata.size = 0.3;
+    graphdata.style = 2;
+    KapaPrepPlot (kapa, nF, &graphdata);
+    KapaPlotVector (kapa, nF, xFaint->data.F32, "x");
+    KapaPlotVector (kapa, nF, yFaint->data.F32, "y");
+  
+    graphdata.color = KapaColorByName ("red");
+    graphdata.ptype = 2;
+    graphdata.size = 0.5;
+    graphdata.style = 2;
+    KapaPrepPlot (kapa, nB, &graphdata);
+    KapaPlotVector (kapa, nB, xBright->data.F32, "x");
+    KapaPlotVector (kapa, nB, yBright->data.F32, "y");
+
+    psLogMsg ("psphot", 3, "saving plot to %s", file->filename);
+    KapaPNG (kapa, file->filename);
+
+    psFree (xBright);
+    psFree (yBright);
+    psFree (xFaint);
+    psFree (yFaint);
+
+    return true;
+}
+
+// plot the sx, sy, sxy as vector field, 
+// plot the PSF measured sx, sy, sxy as vector field
+// pull the sources from the config / file?
+bool psphotPlotPSFModel (pmConfig *config, pmFPAview *view, psArray *sources) {
+
+    // select model pixels (from output background model file, or create internal file)
+    pmFPAfile *file = psMetadataLookupPtr (NULL, config->files, "PSPHOT.PSFMODEL.PLT");
+    if (file == NULL) {
+	psLogMsg ("psphot", 3, "skipping psf model plot");
+	return false;
+    }
+
+    // pmFPAfileOpen defers disk I/O for KAPA files: just get the correct name
+    pmFPAfileOpen (file, view, config);
+
+    Graphdata graphdata;
+
+    psLogMsg ("psphot", 3, "creating psf model plot");
+
+    int kapa = pmKapaOpen (false);
+    if (kapa == -1) {
+	psError(PSPHOT_ERR_UNKNOWN, true, "failure to open kapa");
+	return false;
+    }
+
+    // XXX make the aspect-ratio match the image
+    KapaResize (kapa, 800, 800);
+    KapaInitGraph (&graphdata);
+
+    psVector *xMNT = psVectorAllocEmpty (2*sources->n, PS_TYPE_F32);
+    psVector *yMNT = psVectorAllocEmpty (2*sources->n, PS_TYPE_F32);
+    psVector *xPSF = psVectorAllocEmpty (2*sources->n, PS_TYPE_F32);
+    psVector *yPSF = psVectorAllocEmpty (2*sources->n, PS_TYPE_F32);
+    psVector *xMIN = psVectorAllocEmpty (2*sources->n, PS_TYPE_F32);
+    psVector *yMIN = psVectorAllocEmpty (2*sources->n, PS_TYPE_F32);
+
+    // construct the plot vectors
+    int nMNT = 0;
+    int nPSF = 0;
+    int nMIN = 0;
+    float dx = 0;
+    float dy = 0;
+    float scale = 10;
+    for (int i = 0; i < sources->n; i++) {
+	pmSource *source = sources->data[i];
+	if (source->moments == NULL) continue;
+	if (source->moments->SN < 25) continue;
+        if (source->type != PM_SOURCE_TYPE_STAR) continue;
+    
+	pmModel *model = source->modelPSF;
+        if (model == NULL) continue;
+
+	psF32 *PAR = model->params->data.F32;
+
+	psEllipseMoments moments;
+	moments.x2 = source->moments->Sx;
+	moments.y2 = source->moments->Sy;
+	moments.xy = source->moments->Sxy;
+
+	psEllipseShape shape;
+	shape.sx  = PAR[PM_PAR_SXX] / sqrt(2.0);
+	shape.sy  = PAR[PM_PAR_SYY] / sqrt(2.0);
+	shape.sxy = PAR[PM_PAR_SXY];
+
+	// force the axis ratio to be < 20.0
+	psEllipseAxes axes_mnt = psEllipseMomentsToAxes (moments, 20.0);
+	psEllipseAxes axes_psf = psEllipseShapeToAxes (shape, 20.0);
+
+	// moments major axis
+	dx = scale*axes_mnt.major*cos(axes_mnt.theta);
+	dy = scale*axes_mnt.major*sin(axes_mnt.theta);
+	xMNT->data.F32[nMNT] = PAR[PM_PAR_XPOS] - dx;
+	yMNT->data.F32[nMNT] = PAR[PM_PAR_YPOS] - dy;
+	nMNT++;
+	xMNT->data.F32[nMNT] = PAR[PM_PAR_XPOS] + dx;
+	yMNT->data.F32[nMNT] = PAR[PM_PAR_YPOS] + dy;
+	nMNT++;
+    
+	// psf major axis
+	dx = scale*axes_psf.major*cos(axes_psf.theta);
+	dy = scale*axes_psf.major*sin(axes_psf.theta);
+	xPSF->data.F32[nPSF] = PAR[PM_PAR_XPOS] - dx;
+	yPSF->data.F32[nPSF] = PAR[PM_PAR_YPOS] - dy;
+	nPSF++;
+	xPSF->data.F32[nPSF] = PAR[PM_PAR_XPOS] + dx;
+	yPSF->data.F32[nPSF] = PAR[PM_PAR_YPOS] + dy;
+	nPSF++;
+
+	// minor axis (to show size)
+	dy = +scale*axes_psf.minor*cos(axes_psf.theta);
+	dx = -scale*axes_psf.minor*sin(axes_psf.theta);
+	xMIN->data.F32[nMIN] = PAR[PM_PAR_XPOS] - dx;
+	yMIN->data.F32[nMIN] = PAR[PM_PAR_YPOS] - dy;
+	nMIN++;
+	xMIN->data.F32[nMIN] = PAR[PM_PAR_XPOS] + dx;
+	yMIN->data.F32[nMIN] = PAR[PM_PAR_YPOS] + dy;
+	nMIN++;
+
+	graphdata.xmin = PS_MIN(graphdata.xmin, PAR[PM_PAR_XPOS]);
+	graphdata.xmax = PS_MAX(graphdata.xmax, PAR[PM_PAR_XPOS]);
+	graphdata.ymin = PS_MIN(graphdata.ymin, PAR[PM_PAR_YPOS]);
+	graphdata.ymax = PS_MAX(graphdata.ymax, PAR[PM_PAR_YPOS]);
+    }
+    xMNT->n = yMNT->n = nMNT;
+    xPSF->n = yPSF->n = nPSF;
+    xMIN->n = yMIN->n = nMIN;
+
+    float range;
+    range = graphdata.xmax - graphdata.xmin;
+    graphdata.xmax += 0.05*range;
+    graphdata.xmin -= 0.05*range;
+    range = graphdata.ymax - graphdata.ymin;
+    graphdata.ymax += 0.05*range;
+    graphdata.ymin -= 0.05*range;
+
+    // XXX set the plot range to match the image
+    KapaSetLimits (kapa, &graphdata);
+  
+    KapaSetFont (kapa, "helvetica", 14);
+    KapaBox (kapa, &graphdata);
+    KapaSendLabel (kapa, "x (pixels)", KAPA_LABEL_XM);
+    KapaSendLabel (kapa, "y (pixels)", KAPA_LABEL_YM);
+    KapaSendLabel (kapa, "vector is major axis (scale by 20) : black are moments, blue are psf model, red is psf minor axis", KAPA_LABEL_XP);
+	       
+    graphdata.color = KapaColorByName ("black");
+    graphdata.ptype = 100;
+    graphdata.size = 0.3;
+    graphdata.style = 2;
+    KapaPrepPlot (kapa, nMNT, &graphdata);
+    KapaPlotVector (kapa, nMNT, xMNT->data.F32, "x");
+    KapaPlotVector (kapa, nMNT, yMNT->data.F32, "y");
+  
+    graphdata.color = KapaColorByName ("blue");
+    graphdata.ptype = 100;
+    graphdata.size = 0.5;
+    graphdata.style = 2;
+    KapaPrepPlot (kapa, nPSF, &graphdata);
+    KapaPlotVector (kapa, nPSF, xPSF->data.F32, "x");
+    KapaPlotVector (kapa, nPSF, yPSF->data.F32, "y");
+
+    graphdata.color = KapaColorByName ("red");
+    graphdata.ptype = 100;
+    graphdata.size = 0.5;
+    graphdata.style = 2;
+    KapaPrepPlot (kapa, nMIN, &graphdata);
+    KapaPlotVector (kapa, nMIN, xMIN->data.F32, "x");
+    KapaPlotVector (kapa, nMIN, yMIN->data.F32, "y");
+
+    psLogMsg ("psphot", 3, "saving plot to %s", file->filename);
+    KapaPNG (kapa, file->filename);
+
+    psFree (xMNT);
+    psFree (yMNT);
+    psFree (xPSF);
+    psFree (yPSF);
+    psFree (xMIN);
+    psFree (yMIN);
+
+    return true;
+}
+
+# else
+
+bool psphotPlotMoments (pmConfig *config, pmFPAview *view, psArray *sources) {
+    psLogMsg ("psphot", 3, "skipping moments plot");
+    return true;
+}
+
+bool psphotPlotPSFModel (pmConfig *config, pmFPAview *view, psArray *sources) {
+    psLogMsg ("psphot", 3, "skipping psf model plot");
+    return true;
+}
+
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotTest.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotTest.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotTest.c	(revision 22158)
@@ -0,0 +1,83 @@
+# include "psphotInternal.h"
+
+void psExit (int status, char *process, char *format, ...) {
+
+    va_list ap;
+
+    va_start (ap, format);
+    fprintf (stderr, "exiting %s\n", process);
+    vfprintf (stderr, format, ap);
+    va_end (ap);
+
+    exit (status);
+}
+
+int main (int argc, char **argv) {
+
+    psRegion region = {0,0,0,0};        // a region representing the entire array
+    psphotTestArguments (&argc, argv);
+
+    psFits *file = psFitsOpen (argv[1], "r");
+    psMetadata *header = psFitsReadHeader (NULL, file);
+    psImage *image = psFitsReadImage (NULL, file, region, 0);
+    psFitsClose (file);
+
+    psImageJpegColormap (argv[5]);
+
+    // psImage *fimage = psImageCopy (NULL, image, PS_TYPE_F32);
+
+    int binning = atof(argv[6]);
+
+    psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEAN);
+    psImage *fimage = psImageRebin (NULL, image, NULL, 0, binning, stats);
+
+    float min = atof(argv[3]);
+    float max = atof(argv[4]);
+
+    psImageJpeg (fimage, argv[2], min, max);
+
+    psFree (header);
+    psFree (image);
+    exit (0);
+}
+
+
+# if (0)
+
+    psMetadata *row;
+    psArray *table;
+
+    psMetadataItem *mdi;
+
+    psMetadataConfigWrite (header, argv[2]);
+
+    // attempt to write image with NAXIS = 0
+    mdi = psMetadataLookup (header, "NAXIS");
+    mdi->data.S32 = 0;
+    mdi->type = PS_DATA_S32;
+
+    // create a test image
+    // psImage *tmpimage = psImageAlloc (10, 10, PS_DATA_F32);
+
+    // create a test table
+    table = psArrayAllocEmpty (10);
+
+    for (int i = 0; i < 10; i++) {
+        row = psMetadataAlloc ();
+        psMetadataAdd (row, PS_LIST_TAIL, "ROW",   PS_DATA_S32,    "", i);
+        psMetadataAdd (row, PS_LIST_TAIL, "FROW",  PS_TYPE_F32,    "", 0.1*i);
+        psMetadataAdd (row, PS_LIST_TAIL, "DUMMY", PS_DATA_STRING, "", "test line");
+
+        table->data[i] = row;
+    }
+    table->n = 10;
+
+    psMetadata *theader = psMetadataAlloc ();
+    psMetadataAdd (theader, PS_LIST_HEAD, "EXTNAME", PS_DATA_STRING, "extension name", "SMPFILE");
+
+    psFits *fits = psFitsOpen (argv[3], "w");
+    // psFitsWriteImage (fits, header, tmpimage, 0);
+    psFitsWriteHeader (header, fits);
+    psFitsWriteTable (fits, theader, table);
+
+# endif
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotTestArguments.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotTestArguments.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotTestArguments.c	(revision 22158)
@@ -0,0 +1,19 @@
+# include "psphotInternal.h"
+static int usage ();
+
+void psphotTestArguments (int *argc, char **argv) {
+
+  // basic pslib options
+  psLogSetFormat ("M");
+  psArgumentVerbosity (argc, argv);
+
+  if (*argc != 7) usage ();
+
+  return;
+}
+
+static int usage () {
+
+    fprintf (stderr, "USAGE: psphotTest (input.fits) (output.jpg) (zero) (scale) (colormap) (rebin)\n");
+    exit (2);
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotTestPSF.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotTestPSF.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotTestPSF.c	(revision 22158)
@@ -0,0 +1,131 @@
+# include "psphotInternal.h"
+
+bool psphotTestPSF (pmReadout *readout, psArray *sources, psMetadata *recipe) {
+
+    bool            status;
+    char           *modelName;
+    pmPSF          *psf = NULL;
+    psArray        *stars = NULL;
+
+    psTimerStart ("psphot");
+
+    psphotSaveImage (NULL, readout->image,  "image.fits");
+
+    // check if a PSF model is supplied by the user
+    psf = psMetadataLookupPtr (NULL, readout->analysis, "PSPHOT.PSF");
+    if (psf != NULL) return psf;
+
+    // examine PSF sources in S/N order (brightest first)
+    sources = psArraySort (sources, pmSourceSortBySN);
+
+    // array to store candidate PSF stars
+    int NSTARS = psMetadataLookupS32 (&status, recipe, "PSF_MAX_NSTARS");
+    if (!status) {
+        NSTARS = PS_MIN (sources->n, 200);
+        psWarning("PSF_MAX_NSTARS is not set in the recipe --- defaulting to %d\n", NSTARS);
+    }
+
+    // use poissonian errors or local-sky errors
+    bool POISSON_ERRORS = psMetadataLookupBool (&status, recipe, "POISSON_ERRORS");
+    if (!status) {
+        POISSON_ERRORS = true;
+        psWarning("POISSON_ERRORS is not set in the recipe --- defaulting to true.\n");
+    }
+    pmSourceFitModelInit (15, 0.1, 1.0, POISSON_ERRORS);
+
+    // how to model the PSF variations across the field
+    // XXX make a default value?  or not?
+    psMetadata *md = psMetadataLookupMetadata (&status, recipe, "PSF.TREND.MASK");
+    psPolynomial2D *psfTrendMask;
+    if (!status || !md) {
+        psWarning("PSF.TREND.MASK is not set in the recipe --- defaulting to use zeroth order.\n");
+        psfTrendMask = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 0, 0);
+    } else {
+        psfTrendMask = psPolynomial2DfromMetadata (md);
+        if (!psfTrendMask) {
+            psError(PSPHOT_ERR_PSF, true, "Unable to construct polynomial from PSF.TREND.MASK in the recipe");
+            return false;
+        }
+    }
+
+    stars = psArrayAllocEmpty (sources->n);
+
+    // select the candidate PSF stars (pointers to original sources)
+    for (int i = 0; (i < sources->n) && (stars->n < NSTARS); i++) {
+        pmSource *source = sources->data[i];
+        // if (source->mode & PM_SOURCE_MODE_PSFSTAR) psArrayAdd (stars, 200, source);
+        psArrayAdd (stars, 200, source);
+    }
+    psLogMsg ("psphot.pspsf", 4, "selected candidate %ld PSF objects\n", stars->n);
+
+    if (stars->n == 0) {
+        psError(PSPHOT_ERR_PSF, true, "Failed to find any PSF candidates");
+        return NULL;
+    }
+
+    // get the fixed PSF fit radius
+    // XXX EAM : check that PSF_FIT_RADIUS < SKY_OUTER_RADIUS
+    float RADIUS = psMetadataLookupF32 (&status, recipe, "PSF_FIT_RADIUS");
+    if (!status) {
+        psWarning("PSF_FIT_RADIUS is not set in the recipe --- defaulting to 20.0\n");
+        RADIUS = 20.0;
+    }
+
+    // for this test, require a single model
+    psMetadataItem *mdi = psMetadataLookup (recipe, "PSF_MODEL");
+    if (mdi == NULL) psAbort("missing PSF_MODEL selection");
+    if (mdi->type != PS_DATA_STRING) psAbort("choose a single PSF_MODEL");
+    modelName = mdi->data.V;
+
+    pmPSFtestModel (stars, modelName, RADIUS, POISSON_ERRORS, psfTrendMask);
+
+    psphotSaveImage (NULL, readout->image,  "resid.fits");
+    psphotSaveImage (NULL, readout->mask,   "mask.fits");
+    psphotSaveImage (NULL, readout->weight, "weight.fits");
+    
+    return true;
+}
+
+bool pmPSFtestModel (psArray *sources, char *modelName, float RADIUS, bool poissonErrors, psPolynomial2D *psfTrendMask)
+{
+    bool status;
+    float x;
+    float y;
+
+    pmModelType type = pmModelSetType (modelName);
+    pmPSF *psf = pmPSFAlloc (type, poissonErrors, psfTrendMask);
+    if (psf == NULL) psAbort("unknown model");
+
+    FILE *f = fopen ("params.dat", "w");
+
+    // stage 1:  fit an independent model (freeModel) to all sources
+    psTimerStart ("fit");
+    for (int i = 0; i < sources->n; i++) {
+        pmSource *source = sources->data[i];
+        pmModel  *model  = pmSourceModelGuess (source, psf->type);
+        x = source->peak->x;
+        y = source->peak->y;
+
+        // set temporary object mask and fit object
+        // fit model as EXT, not PSF
+        psImageKeepCircle (source->mask, x, y, RADIUS, "OR", markVal);
+        status = pmSourceFitModel (source, model, PM_SOURCE_FIT_EXT);
+        psImageKeepCircle (source->mask, x, y, RADIUS, "AND", PS_NOT_U8(markVal));
+
+	// write fitted parameters to file
+	fprintf (f, "%f ", model->params->data.F32[PM_PAR_XPOS]);
+	fprintf (f, "%f ", model->params->data.F32[PM_PAR_YPOS]);
+
+	fprintf (f, "%f ", model->params->data.F32[PM_PAR_SXX]);
+	fprintf (f, "%f ", model->params->data.F32[PM_PAR_SYY]);
+	fprintf (f, "%f ", model->params->data.F32[PM_PAR_SXY]);
+
+	fprintf (f, "%f %d\n", model->chisq, model->nIter);
+
+	// subtract model flux
+	pmModelSub (source->pixels, source->mask, model, PM_MODEL_OP_FULL);
+    }
+    fclose (f);
+    psLogMsg ("psphot.psftest", 4, "fit ext: %f sec for %ld sources\n", psTimerMark ("fit"), sources->n);
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotTestSourceOutput.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotTestSourceOutput.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotTestSourceOutput.c	(revision 22158)
@@ -0,0 +1,157 @@
+# include "psphotInternal.h"
+
+enum {
+    PSPHOT_ADD_NONE = 0,
+    PSPHOT_ADD_MODEL = 1,
+    PSPHOT_ADD_R0 = 2,
+    PSPHOT_ADD_R1 = 4,
+};
+
+bool psphotAddModel(psImage *image,
+		    pmModel *model,
+		    int mode
+    )
+{
+    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+
+    PS_ASSERT_PTR_NON_NULL(model, false);
+    PS_ASSERT_IMAGE_NON_NULL(image, false);
+    PS_ASSERT_IMAGE_TYPE(image, PS_TYPE_F32, false);
+
+    psVector *x = psVectorAlloc(2, PS_TYPE_F32);
+    psVector *params = model->params;
+    psS32 imageCol;
+    psS32 imageRow;
+    psF32 skyValue = params->data.F32[0];
+    psF32 pixelValue;
+    
+    float xCenter = model->params->data.F32[PM_PAR_XPOS];
+    float yCenter = model->params->data.F32[PM_PAR_YPOS];
+    float Io = model->params->data.F32[PM_PAR_I0];
+
+    int xBin = 1;
+    int yBin = 1;
+    float xResidCenter = 0.0;
+    float yResidCenter = 0.0;
+
+    psImageInterpolateOptions *Ro = NULL;
+    psImageInterpolateOptions *Rx = NULL;
+    psImageInterpolateOptions *Ry = NULL;
+    if (model->residuals && (mode & (PSPHOT_ADD_R0 | PSPHOT_ADD_R1))) {
+	Ro = psImageInterpolateOptionsAlloc(
+	    PS_INTERPOLATE_BILINEAR,
+	    model->residuals->Ro, NULL, NULL, 0, 0.0, 0.0, 1, 0, 0.0);
+	Rx = psImageInterpolateOptionsAlloc(
+	    PS_INTERPOLATE_BILINEAR,
+	    model->residuals->Rx, NULL, NULL, 0, 0.0, 0.0, 1, 0, 0.0);
+	Ry = psImageInterpolateOptionsAlloc(
+	    PS_INTERPOLATE_BILINEAR,
+	    model->residuals->Ry, NULL, NULL, 0, 0.0, 0.0, 1, 0, 0.0);
+
+	xBin = model->residuals->xBin;
+	yBin = model->residuals->yBin;
+	xResidCenter = model->residuals->xCenter;
+	yResidCenter = model->residuals->yCenter;
+    }
+
+    for (psS32 iy = 0; iy < image->numRows; iy++) {
+        for (psS32 ix = 0; ix < image->numCols; ix++) {
+
+            // Convert i/j to image coord space:
+	    imageCol = ix + image->col0;
+	    imageRow = iy + image->row0;
+
+            x->data.F32[0] = (float) imageCol;
+            x->data.F32[1] = (float) imageRow;
+
+            // set the appropriate pixel value for this coordinate
+	    if (mode & PSPHOT_ADD_MODEL) {
+		pixelValue = model->modelFunc (NULL, params, x) - skyValue;
+	    } else {
+		pixelValue = 0.0;
+	    }
+
+	    // get the contribution from the residual model
+	    // XXX for a test, do this for all sources and all pixels
+	    if (Ro) {
+		// fractional image position
+		// this is wrong for the 'center' case
+		float ox = xBin*(ix + 0.5 + image->col0 - xCenter) + xResidCenter;
+		float oy = yBin*(iy + 0.5 + image->row0 - yCenter) + yResidCenter;
+
+		psU8 mflux = 0;
+		double Fo = 0.0;
+		double Fx = 0.0;
+		double Fy = 0.0;
+		psImageInterpolate (&Fo, NULL, &mflux, ox, oy, Ro);
+		psImageInterpolate (&Fx, NULL, &mflux, ox, oy, Rx);
+		psImageInterpolate (&Fy, NULL, &mflux, ox, oy, Ry);
+
+		if (!mflux && isfinite(Fo) && isfinite(Fx) && isfinite(Fy)) {
+		    if (mode & PSPHOT_ADD_R0) {
+			pixelValue += Io*Fo;
+		    }
+		    if (mode & PSPHOT_ADD_R1) {
+			pixelValue += Io*(xCenter*Fx + yCenter*Fy);
+		    }
+		}
+	    }
+	    image->data.F32[iy][ix] += pixelValue;
+        }
+    }
+    psFree(x);
+    psFree(Ro);
+    psFree(Rx);
+    psFree(Ry);
+    psTrace("psModules.objects", 3, "---- %s(true) end ----\n", __func__);
+    return(true);
+}
+
+// construct an initial PSF model for each object 
+bool psphotTestSourceOutput (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf) {
+
+    psImage *imMo = psImageAlloc (readout->image->numCols, readout->image->numRows, PS_TYPE_F32);
+    psImage *imR0 = psImageAlloc (readout->image->numCols, readout->image->numRows, PS_TYPE_F32);
+    psImage *imR1 = psImageAlloc (readout->image->numCols, readout->image->numRows, PS_TYPE_F32);
+    
+    // create template model
+    pmModel *modelRef = pmModelAlloc(psf->type);
+    modelRef->params->data.F32[PM_PAR_SKY] = 0;
+    modelRef->params->data.F32[PM_PAR_I0] = 1000;
+
+    int dx = 25;
+    int dy = 25;
+
+    // generate a grid of fake sources with amplitude 1000
+    for (int iy = 50; iy < imMo->numRows; iy += 100) {
+	for (int ix = 50; ix < imMo->numCols; ix += 100) {
+	    
+	    // assign the x and y coords to the image center
+	    modelRef->params->data.F32[PM_PAR_XPOS] = ix;
+	    modelRef->params->data.F32[PM_PAR_YPOS] = iy;
+	    
+	    // create modelPSF from this model
+	    pmModel *model = pmModelFromPSF (modelRef, psf);
+	    model->residuals = psf->residuals;
+
+	    // generate working image for this source
+	    psRegion region = {ix - dx, ix + dx, iy - dy, iy + dy};
+
+	    psImage *vM = psImageSubset (imMo, region);
+	    psImage *v0 = psImageSubset (imR0, region);
+	    psImage *v1 = psImageSubset (imR1, region);
+
+	    // we want to make one image o
+	    psphotAddModel (vM, model, PSPHOT_ADD_MODEL);
+	    psphotAddModel (v0, model, PSPHOT_ADD_R0);
+	    psphotAddModel (v1, model, PSPHOT_ADD_R1);
+	}
+    }
+
+    psphotSaveImage (NULL, imMo, "grid.Mo.fits");
+    psphotSaveImage (NULL, imR0, "grid.R0.fits");
+    psphotSaveImage (NULL, imR1, "grid.R1.fits");
+
+    exit (0);
+}
+
Index: /branches/eam_branches/eam_branch_20080719/psphot/src/psphotVersion.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/psphot/src/psphotVersion.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/psphot/src/psphotVersion.c	(revision 22158)
@@ -0,0 +1,40 @@
+# include "psphotInternal.h"
+
+# if (HAVE_KAPA)
+# include <kapa.h>
+# endif
+
+static const char *cvsTag = "$Name: not supported by cvs2svn $";// CVS tag name
+
+psString psphotVersion(void)
+{
+    psString version = NULL;            // Version, to return
+    psStringAppend(&version, "%s-%s",PACKAGE_NAME,PACKAGE_VERSION);
+    return version;
+}
+
+psString psphotVersionLong(void)
+{
+    psString version = psphotVersion(); // Version, to return
+    psString tag = psStringStripCVS(cvsTag, "Name"); // CVS tag
+    psStringAppend(&version, " (cvs tag %s) %s, %s", tag, __DATE__, __TIME__);
+
+# if (HAVE_KAPA)
+    psString ohanaVersion = psStringStripCVS (ohana_version(), "Name");
+    psString libdvoVersion = psStringStripCVS (libdvo_version(), "Name");
+
+    psStringAppend (&version, " with libkapa (ohana %s, libdvo: %s)", ohanaVersion, libdvoVersion);
+    psFree (ohanaVersion);
+    psFree (libdvoVersion);
+# else
+    psStringAppend (&version, " WITHOUT libkapa");
+# endif
+
+    psFree(tag);
+    return version;
+}
+
+// Defined by RHL; leaving for backwards compatibility.
+const char *psphotCVSName(void) {
+   return cvsTag;
+}
Index: /branches/eam_branches/eam_branch_20080719/pswarp/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/.cvsignore	(revision 22158)
@@ -0,0 +1,18 @@
+bin
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+compile
+config.log
+config.status
+configure
+depcomp
+install-sh
+missing
+config.guess
+libtool
+ltmain.sh
+stamp-h1
+config.sub
+pswarp.pc
Index: /branches/eam_branches/eam_branch_20080719/pswarp/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/Makefile.am	(revision 22158)
@@ -0,0 +1,3 @@
+SUBDIRS = src
+
+CLEANFILES = *.pyc *~ core core.*
Index: /branches/eam_branches/eam_branch_20080719/pswarp/autogen.sh
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/autogen.sh	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/autogen.sh	(revision 22158)
@@ -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=pswarp
+TEST_TYPE=-f
+# change this to be a unique filename in the top level dir
+FILE=autogen.sh
+
+DIE=0
+
+LIBTOOLIZE=libtoolize
+ACLOCAL="aclocal $ACLOCAL_FLAGS"
+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: /branches/eam_branches/eam_branch_20080719/pswarp/configure.ac
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/configure.ac	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/configure.ac	(revision 22158)
@@ -0,0 +1,47 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.61)
+
+AC_INIT([pswarp], [0.1.1], [ipp-support@ifa.hawaii.edu])
+AC_CONFIG_SRCDIR([src])
+
+AM_INIT_AUTOMAKE([1.6 foreign dist-bzip2])
+AM_CONFIG_HEADER([src/config.h])
+AM_MAINTAINER_MODE
+
+IPP_STDCFLAGS
+
+AC_LANG(C)
+AC_GNU_SOURCE
+AC_PROG_CC_C99
+AC_PROG_INSTALL
+AC_PROG_LIBTOOL
+AC_SYS_LARGEFILE
+
+dnl ------------------------------------------------------------
+
+AC_PATH_PROG([ERRORCODES], [psParseErrorCodes], [missing])
+if test "$ERRORCODES" = "missing" ; then
+  AC_MSG_ERROR([psParseErrorCodes is required])
+fi
+
+
+PKG_CHECK_MODULES([PSLIB], [pslib >= 1.0.0])
+PKG_CHECK_MODULES([PSMODULE], [psmodules >= 1.0.0])
+PKG_CHECK_MODULES([PPSTATS], [ppStats >= 1.0.0]) 
+PKG_CHECK_MODULES([PSPHOT], [psphot >= 0.8.0]) 
+
+dnl Set CFLAGS for build
+IPP_STDOPTS
+CFLAGS="${CFLAGS} -Wall -Werror"
+echo "PSWARP_CFLAGS: $PSWARP_CFLAGS"
+echo "PSWARP_LIBS: $PSWARP_LIBS"
+
+AC_SUBST([PSWARP_CFLAGS])
+AC_SUBST([PSWARP_LIBS])
+
+AC_CONFIG_FILES([
+  Makefile
+  src/Makefile
+])
+
+AC_OUTPUT
Index: /branches/eam_branches/eam_branch_20080719/pswarp/doc/notes.txt
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/doc/notes.txt	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/doc/notes.txt	(revision 22158)
@@ -0,0 +1,29 @@
+
+- pswarp takes an image (and corresponding mask and weight images) and
+  warps the pixels to match the specified skycell projection and pixel
+  grid.  the astrometry of the input image is supplied by the header
+  of the image or by a specified SMP file. 
+
+- the input image, weight, mask are loaded into pmFPA structures with
+  the layout determined by the camera/format/layout
+
+- the skycell is loaded into a pmFPA structure.  at a minimum, a
+  single skycell may contain a single chip, cell, and readout, which
+  in turn correspond to the single set of pixels representing the
+  image region.  
+
+  * is there a need or use for a skycell to have a multilayered
+    structure equivalent in any way to the fpa->chip->cell->readout
+    layer?
+
+    - perhaps we will want to use a single fpa for a larger region
+      with small sky cells representing contiguous pixel regions.  
+
+    - perhaps we will want to warp an entire fpa exposure at once and
+      use a skyfpa to represent all of the possible output skycells
+      for a single input fpa exposure.
+
+- the output is a file or set of files corresponding to the skycell
+  files.  the details should be specified by the PSWARP.OUTPUT file
+  rule.
+
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/.cvsignore	(revision 22158)
@@ -0,0 +1,14 @@
+*.o
+*.lo
+.libs
+.deps
+Makefile
+Makefile.in
+pswarp
+pswarp.loT
+pswarpErrorCodes.h
+pswarpErrorCodes.c
+libpswarp.la
+config.h
+config.h.in
+stamp-h1
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/Makefile.am	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/Makefile.am	(revision 22158)
@@ -0,0 +1,43 @@
+bin_PROGRAMS = pswarp
+pswarp_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PPSTATS_CFLAGS) $(PSPHOT_CFLAGS) $(PSWARP_CFLAGS)
+pswarp_LDFLAGS = $(PSLIB_LIBS) $(PSMODULE_LIBS) $(PPSTATS_LIBS) $(PSPHOT_LIBS) $(PSWARP_LIBS)
+
+pswarp_SOURCES = \
+	pswarp.c			\
+	pswarpArguments.c		\
+	pswarpCleanup.c			\
+	pswarpLoop.c			\
+	pswarpDefine.c			\
+	pswarpDefineSkycell.c		\
+	pswarpErrorCodes.c		\
+	pswarpMapGrid.c			\
+	pswarpMatchRange.c		\
+	pswarpParseCamera.c		\
+	pswarpPixelFraction.c		\
+	pswarpSetMaskBits.c		\
+	pswarpSetThreads.c	        \
+	pswarpTransformReadout.c	\
+	pswarpTransformSources.c \
+	pswarpTransformTile.c		\
+	pswarpVersion.c            
+
+noinst_HEADERS = \
+	pswarp.h \
+	pswarpErrorCodes.h
+
+clean-local:
+	-rm -f TAGS
+
+# Tags for emacs
+tags:
+	etags `find . -name \*.[ch] -print`
+
+### Error codes.
+BUILT_SOURCES = pswarpErrorCodes.h pswarpErrorCodes.c
+CLEANFILES = pswarpErrorCodes.h pswarpErrorCodes.c
+
+pswarpErrorCodes.h : pswarpErrorCodes.dat pswarpErrorCodes.h.in
+	$(ERRORCODES) --data=pswarpErrorCodes.dat --outdir=. pswarpErrorCodes.h
+
+pswarpErrorCodes.c : pswarpErrorCodes.dat pswarpErrorCodes.c.in pswarpErrorCodes.h
+	$(ERRORCODES) --data=pswarpErrorCodes.dat --outdir=. pswarpErrorCodes.c
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarp.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarp.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarp.c	(revision 22158)
@@ -0,0 +1,53 @@
+# include "pswarp.h"
+
+static void usage (void) {
+    fprintf (stderr, "USAGE: pswarp [-file image(s)] [-list imagelist] [options] (output) (skycell)\n");
+    fprintf (stderr, "  options:\n");
+    fprintf (stderr, "    [-astrom astrom.cmp] : provide an alternative astrometry calibration\n");
+    fprintf (stderr, "    [-mask mask.fits] : provide a corresponding mask image\n");
+    fprintf (stderr, "    [-weight weight.fits] : provide a corresponding weight image (pixel varience)\n");
+    psErrorStackPrint(stderr, "\n");
+    exit (2);
+}
+
+int main (int argc, char **argv)
+{
+    psTimerStart("pswarp");
+
+    psLibInit(NULL);
+
+    // model inits are needed in pmSourceIO
+    // models defined in psphot/src/models are not available in psastro
+    pmModelClassInit();
+
+    pmConfig *config = pswarpArguments(argc, argv);
+    if (!config) usage();
+
+    if (!pswarpOptions(config)) {
+        psErrorStackPrint(stderr, "error parsing options\n");
+        exit(1);
+    }
+
+    // load identify the data sources
+    if (!pswarpParseCamera(config)) {
+        psErrorStackPrint(stderr, "error setting up the camera\n");
+        exit (1);
+    }
+
+    // load the skycell layout information
+    if (!pswarpDefine(config)) {
+        psErrorStackPrint(stderr, "error loading output definition\n");
+        exit (1);
+    }
+
+    // load and warp
+    if (!pswarpLoop(config)) {
+        psErrorStackPrint(stderr, "error warping data\n");
+        exit (1);
+    }
+
+    psLogMsg("pswarp", 3, "complete pswarp run: %f sec\n", psTimerMark("pswarp"));
+    pswarpCleanup(config);
+    psLibFinalize();
+    exit(EXIT_SUCCESS);
+}
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarp.h
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarp.h	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarp.h	(revision 22158)
@@ -0,0 +1,93 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>  // for strcasecmp
+#include <unistd.h>   // for unlink
+#include <pslib.h>
+#include <psmodules.h>
+#include <psphot.h>
+
+#define THREADED 1
+
+#include "pswarpErrorCodes.h"
+#define PSWARP_RECIPE  "PSWARP" // Name of the recipe to use
+#define PSASTRO_RECIPE "PSASTRO" // Name of the recipe to use
+
+#define PSWARP_ANALYSIS_VARFACTOR "PSWARP.VARFACTOR" // Name for variance factor in analysis metadata
+#define PSWARP_ANALYSIS_GOODPIX   "PSWARP.GOODPIX" // Name for number of good pixels in analysis metadata
+
+// a single pswarpMap converts coordinates from one image to a second image
+// the linear model is only valid over a limited range of pixels
+typedef struct {
+    double Xo, Xx, Xy;
+    double Yo, Yx, Yy;
+    int xo;
+    int yo;
+} pswarpMap;
+
+// the pswarpMapGrid carries a collection of pswarpMag structures representing the
+// local value of the pswarpMap at different locations in the image.
+typedef struct {
+    pswarpMap ***maps;
+    int nXpts, nYpts;                   // number of x,y samples in the grid
+    int nXpix, nYpix;                   // x,y spacing in src image pixels of grid samples
+    double xMin,  yMin;			// coordinate of first grid sample
+} pswarpMapGrid;
+
+typedef struct {
+    // values which are common to all tiles
+    pmReadout *input;
+    pmReadout *output;
+    pswarpMapGrid *grid;
+    psImageInterpolateOptions *interp;
+    psImage *region;
+
+    // input values for this tile
+    int gridX;
+    int gridY;
+
+    // output values for this tile
+    long goodPixels;
+} pswarpTransformTileArgs;
+
+pswarpTransformTileArgs *pswarpTransformTileArgsAlloc();
+bool pswarpTransformTile (pswarpTransformTileArgs *args);
+
+pmConfig *pswarpArguments (int argc, char **argv);
+bool pswarpOptions(pmConfig *config);
+bool pswarpSetMaskBits (pmConfig *config);
+bool pswarpParseCamera (pmConfig *config);
+bool pswarpDefine (pmConfig *config);
+bool pswarpLoop (pmConfig *config);
+void pswarpCleanup (pmConfig *config);
+bool pswarpTransformReadout (pmReadout *output, pmReadout *input, pmConfig *config);
+bool pswarpTransformSources(pmReadout *output, pmReadout *input, pmConfig *config);
+
+bool pswarpMatchRange (int *minX, int *minY, int *maxX, int *maxY, pmReadout *dest, pmReadout *src);
+
+pswarpMap *pswarpMapAlloc ();
+pswarpMapGrid *pswarpMapGridAlloc (int Nx, int Ny);
+
+pswarpMapGrid *pswarpMapGridFromImage (pmReadout *dest, pmReadout *src, int nXpix, int nYpix);
+bool pswarpMapGridSetGrid (pswarpMapGrid *grid, int ix, int iy, int *gridX, int *gridY);
+bool pswarpMapGridCoordRange (pswarpMapGrid *grid, int gridX, int gridY, psPlane *min, psPlane *max);
+int pswarpMapGridNextGrid_X (pswarpMapGrid *grid, int gridX);
+int pswarpMapGridNextGrid_Y (pswarpMapGrid *grid, int gridY);
+double pswarpMapGridMaxError (pswarpMapGrid *grid);
+bool pswarpMapApply (double *outX, double *outY, pswarpMap *map, double inX, double inY);
+bool pswarpMapSetLocalModel (pswarpMap *map, pmReadout *dest, pmReadout *src, int ix, int iy);
+
+bool pswarpDefineSkycell (pmFPAfile **outFile, pmConfig **outConfig, pmConfig *config,
+                          const char *filename, const char *argname);
+
+/// Check to see if the readout has a minimum fraction of "lit" pixels
+bool pswarpPixelFraction(const pmReadout *readout, ///< Readout to inspect
+                         psMetadata *stats, ///< Statistics to update with the result
+                         const pmConfig *config ///< Configuration
+    );
+
+// define threads for this program
+bool pswarpSetThreads ();
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpArguments.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpArguments.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpArguments.c	(revision 22158)
@@ -0,0 +1,150 @@
+# include "pswarp.h"
+# include <glob.h>
+
+pmConfig *pswarpArguments (int argc, char **argv) {
+
+    bool status;
+    int N;
+
+    if (argc == 1) {
+        psError(PSWARP_ERR_ARGUMENTS, true, "No arguments supplied");
+        return NULL;
+    }
+
+    // load config data from default locations
+    pmConfig *config = pmConfigRead(&argc, argv, PSWARP_RECIPE);
+    if (config == NULL) {
+        psError(PSWARP_ERR_CONFIG, false, "Can't read site configuration");
+        return NULL;
+    }
+
+    // save the following additional recipe values based on command-line options
+    // these options override the PSWARP recipe values loaded from recipe files
+    pmConfigRecipeOptions (config, PSWARP_RECIPE);
+
+    pmConfigFileSetsMD(config->arguments, &argc, argv, "ASTROM",   "-astrom", "-astromlist");
+
+    // chip selection is used to limit chips to be processed
+    if ((N = psArgumentGet(argc, argv, "-chip"))) {
+        psArgumentRemove(N, &argc, argv);
+        psMetadataAddStr(config->arguments, PS_LIST_TAIL, "CHIP_SELECTIONS", PS_DATA_STRING,
+                         "Only process these chips", argv[N]);
+        psArgumentRemove(N, &argc, argv);
+    }
+
+    // Statistics file
+    if ((N = psArgumentGet(argc, argv, "-stats"))) {
+        psArgumentRemove(N, &argc, argv);
+        psMetadataAddStr(config->arguments, PS_LIST_TAIL, "STATS", PS_DATA_STRING,
+                         "Filename for statistics of output image", argv[N]);
+        psArgumentRemove(N, &argc, argv);
+    }
+
+    // Number of threads
+    if ((N = psArgumentGet(argc, argv, "-threads"))) {
+        psArgumentRemove(N, &argc, argv);
+	int nThreads = atoi(argv[N]);
+        psMetadataAddS32(config->arguments, PS_LIST_TAIL, "NTHREADS", 0, "number of warp threads", nThreads);
+        psArgumentRemove(N, &argc, argv);
+
+	// create the thread pool with number of desired threads, supplying our thread launcher function
+	// XXX need to determine the number of threads from the config data
+	psThreadPoolInit (nThreads);
+    }
+    pswarpSetThreads ();
+
+    // PSF determination?
+    if ((N = psArgumentGet(argc, argv, "-psf"))) {
+        psArgumentRemove(N, &argc, argv);
+        psMetadataAddBool(config->arguments, PS_LIST_TAIL, "PSF", 0, "Do PSF determination?", true);
+    }
+
+    if (!pmConfigFileSetsMD (config->arguments, &argc, argv, "INPUT", "-file", "-list")) {
+        psError(PSWARP_ERR_ARGUMENTS, true, "Missing -file (input) or -list (input)");
+        return NULL;
+    }
+
+    // the mask and weight entries are optional (build from gain?)
+    pmConfigFileSetsMD (config->arguments, &argc, argv, "MASK",   "-mask",   "-masklist");
+    pmConfigFileSetsMD (config->arguments, &argc, argv, "WEIGHT", "-weight", "-weightlist");
+
+    if (argc != 3) {
+        psError(PSWARP_ERR_ARGUMENTS, true, "Incorrect arguments supplied");
+        return NULL;
+    }
+
+
+    psArray *array;
+
+    // output position is fixed
+    psMetadataAddStr (config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "", argv[1]);
+
+    // skycell position is fixed
+    array = psArrayAlloc(1);
+    array->data[0] = psStringCopy (argv[2]);
+    status = psMetadataAddPtr (config->arguments, PS_LIST_TAIL, "SKYCELL", PS_DATA_ARRAY, "", array);
+    psFree (array);
+
+    psTrace("pswarp", 1, "Done with pswarpArguments...\n");
+    return (config);
+}
+
+// Parse the recipe and format into the arguments
+bool pswarpOptions(pmConfig *config)
+{
+    // Select the appropriate recipe
+    psMetadata *recipe  = psMetadataLookupPtr (NULL, config->recipes, PSWARP_RECIPE);
+    if (!recipe) {
+        psError(PSWARP_ERR_CONFIG, true, "Can't find %s recipe!\n", PSWARP_RECIPE);
+        return false;
+    }
+
+    // Get grid size
+    bool status;                        // Status of MD lookup
+    int nGridX = psMetadataLookupS32 (&status, recipe, "GRID.NX");
+    if (!status) nGridX = 128;
+    int nGridY = psMetadataLookupS32 (&status, recipe, "GRID.NY");
+    if (!status) nGridY = 128;
+
+    // Get interpolation mode
+    psImageInterpolateMode interpolationMode; // Mode for interpolation
+    const char *name = psMetadataLookupStr (&status, recipe, "INTERPOLATION.MODE"); // Name of interp mode
+    if (!name) {
+        interpolationMode = PS_INTERPOLATE_BILINEAR;
+        psLogMsg ("pswarp", 3, "defaulting to bilinear interpolation\n");
+    } else {
+        interpolationMode = psImageInterpolateModeFromString (name);
+        if (interpolationMode == PS_INTERPOLATE_NONE) {
+            interpolationMode = PS_INTERPOLATE_BILINEAR;
+            psLogMsg ("pswarp", 3,
+                      "Unknown interpolation mode %s, defaulting to bilinear interpolation\n", name);
+        }
+    }
+
+    float poorFrac = psMetadataLookupF32(&status, recipe, "POOR.FRAC"); // Frac of bad flux for a "poor"
+    if (!status) {
+        poorFrac = 0.0;
+        psWarning("POOR.FRAC is not set in the %s recipe --- defaulting to %f.", PSWARP_RECIPE, poorFrac);
+    }
+
+    float acceptFrac = psMetadataLookupF32(&status, recipe, "ACCEPT.FRAC"); // Min fraction of good pixels
+    if (!status) {
+        acceptFrac = 0.0;
+        psWarning("ACCEPT.FRAC is not set in the %s recipe --- defaulting to %f.", PSWARP_RECIPE, poorFrac);
+    }
+
+    // Set recipe values in the arguments
+    psMetadataAddS32(config->arguments, PS_LIST_TAIL, "GRID.NX", 0,
+                     "Iso-astrom grid spacing in x", nGridX);
+    psMetadataAddS32(config->arguments, PS_LIST_TAIL, "GRID.NY", 0,
+                     "Iso-astrom grid spacing in y", nGridY);
+    psMetadataAddS32(config->arguments, PS_LIST_TAIL, "INTERPOLATION.MODE", 0,
+                     "Interpolation mode", interpolationMode);
+    psMetadataAddF32(config->arguments, PS_LIST_TAIL, "POOR.FRAC", 0,
+                     "Fraction of bad flux for a pixel to be marked as poor", poorFrac);
+    psMetadataAddF32(config->arguments, PS_LIST_TAIL, "ACCEPT.FRAC", 0,
+                     "Minimum fraction of good pixels for result to be accepted", acceptFrac);
+
+    psTrace("pswarp", 1, "Done with pswarpArguments...\n");
+    return (config);
+}
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpCleanup.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpCleanup.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpCleanup.c	(revision 22158)
@@ -0,0 +1,18 @@
+# include "pswarp.h"
+
+void pswarpCleanup (pmConfig *config) {
+
+    psFree (config);
+
+    psTimerStop ();
+    psMemCheckCorruption(stderr, true);
+    pmModelClassCleanup ();
+    psTimeFinalize ();
+    psThreadPoolFinalize ();
+    pmConceptsDone ();
+    pmConfigDone ();
+    // fprintf (stderr, "found %d leaks at %s\n", psMemCheckLeaks (0, NULL, stdout, false), "pswarp");
+    fprintf (stderr, "found %d leaks at %s\n", psMemCheckLeaks (0, NULL, NULL, false), "pswarp");
+
+    return;
+}
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpDefine.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpDefine.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpDefine.c	(revision 22158)
@@ -0,0 +1,112 @@
+# include "pswarp.h"
+// this function loads the skycell metadata
+
+bool pswarpDefine (pmConfig *config) {
+
+    // load the PSWARP recipe
+    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSWARP_RECIPE);
+    if (!recipe) {
+        psError(PSWARP_ERR_CONFIG, true, "Can't find PSWARP recipe!\n");
+        return false;
+    }
+
+    // select the input data sources
+    pmFPAfile *skycell = psMetadataLookupPtr (NULL, config->files, "PSWARP.SKYCELL");
+    if (!skycell) {
+        psError(PSWARP_ERR_CONFIG, false, "Can't find skycell data!\n");
+        return false;
+    }
+    pmFPAfile *output = psMetadataLookupPtr(NULL, config->files, "PSWARP.OUTPUT");
+    if (!output) {
+        psError(PSWARP_ERR_CONFIG, false, "Can't find output data!\n");
+        return false;
+    }
+    pmFPAfile *input = psMetadataLookupPtr(NULL, config->files, "PSWARP.INPUT");
+    if (!input) {
+        psError(PSWARP_ERR_CONFIG, false, "Can't find input data!\n");
+        return false;
+    }
+
+    // open the full skycell file; no need to defer different depths. only load the header data
+    pmFPAview *view = pmFPAviewAlloc (0);
+    pmFPAfileOpen (skycell, view, config);
+
+    // Read header and create target
+    {
+        if (!pmFPAReadHeaderSet(skycell->fpa, skycell->fits, config)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to read headers for skycell.");
+            psFree(view);
+            return false;
+        }
+        view->chip = 0;
+        view->cell = 0;
+        view->readout = 0;
+        pmCell *source = pmFPAfileThisCell(config->files, view, "PSWARP.SKYCELL"); // Source cell
+        pmHDU *hdu = pmHDUFromCell(source); // HDU for source
+        if (!hdu || !hdu->header) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find header for sky cell.");
+            psFree(view);
+            return false;
+        }
+        int numCols = psMetadataLookupS32(NULL, hdu->header, "NAXIS1"); // Number of columns
+        int numRows = psMetadataLookupS32(NULL, hdu->header, "NAXIS2"); // Number of rows
+
+        pmCell *target = pmFPAviewThisCell(view, output->fpa); // Target cell
+        pmReadout *readout = pmReadoutAlloc(target); // Target readout
+        readout->image = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+        psImageInit(readout->image, NAN);
+        psFree(readout);                // Drop reference
+
+        psMetadataItemSupplement(target->concepts, source->concepts, "CELL.XBIN");
+        psMetadataItemSupplement(target->concepts, source->concepts, "CELL.YBIN");
+        psMetadataItemSupplement(target->concepts, source->concepts, "CELL.XSIZE");
+        psMetadataItemSupplement(target->concepts, source->concepts, "CELL.YSIZE");
+        psMetadataItemSupplement(target->concepts, source->concepts, "CELL.XPARITY");
+        psMetadataItemSupplement(target->concepts, source->concepts, "CELL.YPARITY");
+        psMetadataItemSupplement(target->concepts, source->concepts, "CELL.X0");
+        psMetadataItemSupplement(target->concepts, source->concepts, "CELL.Y0");
+    }
+
+    // XXX this is not a sufficient test
+    view->chip = 0;
+    view->cell = 0;
+    view->readout = -1;
+    pmHDU *phu = pmFPAviewThisPHU(view, skycell->fpa); // Skycell PHU
+    pmHDU *hdu = pmFPAviewThisHDU(view, skycell->fpa); // Skycell header
+    bool bilevelAstrometry = false;
+    if (phu) {
+        char *ctype = psMetadataLookupStr(NULL, phu->header, "CTYPE1");
+        if (ctype) {
+            bilevelAstrometry = !strcmp(&ctype[4], "-DIS");
+        }
+    }
+
+    // We read from the skycell into the output.  i.e., the output receives the desired astrometry.
+    pmChip *outputChip = pmFPAviewThisChip(view, output->fpa); // Chip in the output
+    if (bilevelAstrometry) {
+        if (!pmAstromReadBilevelMosaic(output->fpa, phu->header)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to read bilevel mosaic astrometry for skycell.");
+            psFree(view);
+            return false;
+        }
+        if (!pmAstromReadBilevelChip(outputChip, hdu->header)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to read bilevel chip astrometry for skycell.");
+            psFree(view);
+            return false;
+        }
+    } else {
+        // we use a default FPA pixel scale of 1.0
+        if (!pmAstromReadWCS(output->fpa, outputChip, hdu->header, 1.0)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to read WCS astrometry for skycell.");
+            psFree(view);
+            return false;
+        }
+    }
+
+    const char *name = psMetadataLookupStr(NULL, input->fpa->concepts, "FPA.NAME"); // Name of FPA
+    view->chip = view->cell = view->readout = -1;
+    pmFPAAddSourceFromView(output->fpa, name, view, output->format);
+
+    psFree (view);
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpDefineSkycell.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpDefineSkycell.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpDefineSkycell.c	(revision 22158)
@@ -0,0 +1,144 @@
+# include "pswarp.h"
+
+// XXX this function is based on pmFPAfileDefineFromArgs
+// a skycell consists of only one file
+
+// search for argname on the config->argument list
+// construct an FPA based on the files in this list (must represent a single FPA)
+// built the association between the FPA elements (CHIP/CELL) and the files
+// define the pmFPAfile filename and bind it to this FPA
+// save the pmFPAfile on config->files
+// return the pmFPAfile (a view to the one saved on config->files)
+bool pswarpDefineSkycell (pmFPAfile **outFile, pmConfig **outConfig, pmConfig *config, const char *filename, const char *argname)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(filename, NULL);
+    PS_ASSERT_STRING_NON_EMPTY(argname, NULL);
+
+    bool status;
+    pmFPA *fpa = NULL;
+    psFits *fits = NULL;
+    pmFPAfile *file = NULL;
+    psMetadata *phu = NULL;
+    psMetadata *format = NULL;
+    pmConfig *skyConfig = NULL;
+
+    *outFile = NULL;
+    *outConfig = NULL;
+
+    // we search the argument data for the named fileset (argname)
+    psArray *infiles = psMetadataLookupPtr(&status, config->arguments, argname);
+    if (!status) {
+        return false;
+    }
+    if (infiles->n != 1) {
+        psError(PS_ERR_IO, false, "Found n == %ld files in %s in arguments\n", infiles->n, argname);
+        return false;
+    }
+
+    // this function is implicitly an INPUT operation: do not create the file
+    psString realName = pmConfigConvertFilename (infiles->data[0], config, false, false);
+    if (!realName) {
+        psError(PS_ERR_IO, false, "Failed to convert file name %s\n", (char *) infiles->data[0]);
+        return false;
+    }
+
+    // load the header of the image
+    fits = psFitsOpen (realName, "r");
+    if (!fits) {
+        psError(PS_ERR_IO, false, "Failed to open file %s\n", realName);
+        psFree (realName);
+        return false;
+    }
+    phu = psFitsReadHeader (NULL, fits);
+    if (!phu) {
+        psError(PS_ERR_IO, false, "Failed to read file header %s\n", realName);
+        psFree (realName);
+        return false;
+    }
+    psFitsClose(fits);
+
+    // XXX format needs to be equivalent to SIMPLE
+    // determine the current format from the header
+    // determine camera if not specified already
+    // XXX EAM : this operation should be defined as a pmConfig function (pmConfigCopy?)
+    skyConfig = pmConfigAlloc(0, NULL);
+    skyConfig->complete = psMemIncrRefCounter (config->complete);
+
+    psFree (skyConfig->files);
+    skyConfig->files = psMemIncrRefCounter (config->files);
+    psFree (skyConfig->arguments);
+    skyConfig->arguments = psMemIncrRefCounter (config->arguments);
+
+    format = pmConfigCameraFormatFromHeader (NULL, NULL, skyConfig, phu, false);
+    if (!format) {
+        psError(PS_ERR_IO, false, "Failed to read CCD format from %s\n", realName);
+        psFree(phu);
+        psFree (realName);
+        return false;
+    }
+
+    // build the template fpa, set up the basic view
+    fpa = pmFPAConstruct (skyConfig->camera, skyConfig->cameraName);
+    if (!fpa) {
+        psError(PS_ERR_IO, false, "Failed to construct FPA from %s", realName);
+        psFree (realName);
+        return false;
+    }
+    psFree (realName);
+
+    // load the given filerule (from config->camera) and bind it to the fpa
+    // the returned file is just a view to the entry on config->files
+    file = pmFPAfileDefineInput (skyConfig, fpa, filename);
+    if (!file) {
+        psError(PS_ERR_IO, false, "file %s not defined\n", filename);
+        psFree(phu);
+        psFree(fpa);
+        psFree(format);
+        return false;
+    }
+    psFree (format);
+    file->format = psMemIncrRefCounter(format);
+
+    // adjust the rules to identify these files in the file->names data
+    psFree (file->filerule);
+    file->filerule = psStringCopy ("@FILES");
+    file->filesrc = psStringCopy ("{CHIP.NAME}.{CELL.NAME}");
+
+    file->fileLevel = pmFPAPHULevel(format);
+    if (file->fileLevel == PM_FPA_LEVEL_NONE) {
+        psError(PS_ERR_IO, true, "Unable to determine file level for %s\n", file->name);
+        psFree(phu);
+        psFree(fpa);
+        psFree(format);
+        psFree(file);
+        return false;
+    }
+
+    // set the view to the corresponding entry for this phu
+    pmFPAview *view = pmFPAAddSourceFromHeader (fpa, phu, format);
+    if (!view) {
+        psError(PS_ERR_IO, false, "Unable to determine source for %s", file->name);
+        psFree(phu);
+        psFree (fpa);
+        psFree (format);
+        return false;
+    }
+
+    // associate the filename with the FPA element
+    char *name = pmFPAfileNameFromRule (file->filesrc, file, view);
+
+    // save the name association in the pmFPAfile structure
+    psMetadataAddStr (file->names, PS_LIST_TAIL, name, 0, "", infiles->data[0]);
+
+    psFree (view);
+    psFree (name);
+    psFree (phu);
+    psFree (fpa);
+
+    *outFile = file;
+    *outConfig = skyConfig;
+
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpErrorCodes.c.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpErrorCodes.c.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpErrorCodes.c.in	(revision 22158)
@@ -0,0 +1,25 @@
+/*
+ * The line
+    { PSWARP_ERR_$X{ErrorCode}, "$X{ErrorDescription}"},
+ * (without the Xs)
+ * will be replaced by values from errorCodes.dat
+ */
+#include "pslib.h"
+#include "pswarpErrorCodes.h"
+
+void pswarpErrorRegister(void)
+{
+    static psErrorDescription errors[] = {
+       { PSWARP_ERR_BASE, "First value we use; lower values belong to psLib" },
+       { PSWARP_ERR_${ErrorCode}, "${ErrorDescription}"},
+    };
+    static int nerror = PSWARP_ERR_NERROR - PSWARP_ERR_BASE; // number of values in enum
+
+    for (int i = 0; i < nerror; i++) {
+       psErrorDescription *tmp = psAlloc(sizeof(psErrorDescription));
+       *tmp = errors[i];
+       psErrorRegister(tmp, 1);
+       psFree(tmp);			/* it's on the internal list */
+    }
+    nerror = 0;			                // don't register more than once
+}
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpErrorCodes.dat
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpErrorCodes.dat	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpErrorCodes.dat	(revision 22158)
@@ -0,0 +1,10 @@
+#
+# This file is used to generate pswarpErrorClasses.h
+#
+BASE = 800		First value we use; lower values belong to psLib
+UNKNOWN			Unknown PM error code
+NOT_IMPLEMENTED		Desired feature is not yet implemented
+ARGUMENTS		Incorrect arguments
+CONFIG			Problem in configure files
+IO			Problem in FITS I/O
+DATA                    Problem in data values
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpErrorCodes.h.in
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpErrorCodes.h.in	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpErrorCodes.h.in	(revision 22158)
@@ -0,0 +1,18 @@
+#if !defined(PSWARP_ERROR_CODES_H)
+#define PSWARP_ERROR_CODES_H
+/*
+ * The line
+ *  PSWARP_ERR_$X{ErrorCode},
+ * (without the X)
+ *
+ * will be replaced by values from errorCodes.dat
+ */
+typedef enum {
+    PSWARP_ERR_BASE = 600,
+    PSWARP_ERR_${ErrorCode},
+    PSWARP_ERR_NERROR
+} pswarpErrorCode;
+
+void pswarpErrorRegister(void);
+
+#endif
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpHeadersLoad.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpHeadersLoad.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpHeadersLoad.c	(revision 22158)
@@ -0,0 +1,117 @@
+# include "pswarp.h"
+
+// XXX this function should load all of the PSWARP.INPUT headers
+// it should examine the overlap between each chip in PSWARP.INPUT
+// and the output (pswarpMatchRange) and select/de-select the chips
+// and/or cell which contribute pixels.
+
+// pswarpDataLoad should then load the pixel of the needed chips
+
+// all of the different astrometry analysis modes use the same data load loop
+bool pswarpHeadersLoad (pmConfig *config) {
+
+    pmChip *chip;
+    pmCell *cell;
+    pmReadout *readout;
+    pmFPAview *view;
+
+    // select the input data sources
+    pmFPAfile *input = psMetadataLookupPtr (NULL, config->files, "PSWARP.INPUT");
+    if (!input) {
+        psError(PSWARP_ERR_CONFIG, true, "Can't find input data!\n");
+        return false;
+    }
+
+    // use the external astrometry source if supplied
+    pmFPAfile *astrom = psMetadataLookupPtr (NULL, config->files, "PSWARP.ASTROM");
+    if (!astrom) {
+        astrom = input;
+    }
+
+    // select the output readout
+    view = pmFPAviewAlloc (0);
+    view->chip = 0;
+    view->cell = 0;
+    view->readout = 0;
+    pmReadout  *output = pmFPAfileThisReadout (config->files, view, "PSWARP.OUTPUT");
+    if (!output) {
+        psError(PSWARP_ERR_CONFIG, true, "Can't find output data!\n");
+        return false;
+    }
+    psFree (view);
+
+    // de-activate PSWARP.SKYCELL and PSWARP.OUTPUT
+    pmFPAfileActivate(config->files, false, "PSWARP.SKYCELL");
+    pmFPAfileActivate(config->files, false, "PSWARP.OUTPUT");
+
+    view = pmFPAviewAlloc (0);
+
+    // XXX need to read only the headers for the skycell
+    // XXX these pmAstromReadBilevel functions seem to be broken
+
+    // find the FPA phu
+    bool bilevelAstrometry = false;
+    pmHDU *phu = pmFPAviewThisPHU(view, astrom->fpa);
+    if (phu) {
+        char *ctype = psMetadataLookupStr (NULL, phu->header, "CTYPE1");
+        if (ctype) {
+            bilevelAstrometry = !strcmp(&ctype[4], "-DIS");
+        }
+    }
+    if (bilevelAstrometry) {
+        if (!pmAstromReadBilevelMosaic(input->fpa, phu->header)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to read bilevel mosaic astrometry for input.");
+            psFree(view);
+            return false;
+        }
+    }
+
+    // files associated with the science image
+    pmFPAfileIOChecks (config, view, PM_FPA_BEFORE);
+
+    while ((chip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
+        psTrace ("pswarp", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+        if (!chip->process || !chip->file_exists) { continue; }
+        pmFPAfileIOChecks (config, view, PM_FPA_BEFORE);
+
+        // read WCS data from the corresponding header
+        pmHDU *hdu = pmFPAviewThisHDU (view, astrom->fpa);
+        if (bilevelAstrometry) {
+            if (!pmAstromReadBilevelChip (chip, hdu->header)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to read bilevel chip astrometry for input.");
+                psFree(view);
+                return false;
+            }
+        } else {
+            // we use a default FPA pixel scale of 1.0
+            if (!pmAstromReadWCS(input->fpa, chip, hdu->header, 1.0)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to read WCS astrometry for input.");
+                psFree(view);
+                return false;
+            }
+        }
+
+        while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
+            psTrace ("pswarp", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+            if (!cell->process || !cell->file_exists) { continue; }
+            pmFPAfileIOChecks (config, view, PM_FPA_BEFORE);
+
+            // process each of the readouts
+            while ((readout = pmFPAviewNextReadout (view, input->fpa, 1)) != NULL) {
+                pmFPAfileIOChecks (config, view, PM_FPA_BEFORE);
+                if (! readout->data_exists) { continue; }
+
+                // XXX Replace with a function to examine the overlap and turn on/off chips
+                // based on that result
+                // pswarpTransformReadout_Opt (output, readout, config);
+
+                pmFPAfileIOChecks (config, view, PM_FPA_AFTER);
+            }
+            pmFPAfileIOChecks (config, view, PM_FPA_AFTER);
+        }
+        pmFPAfileIOChecks (config, view, PM_FPA_AFTER);
+    }
+    pmFPAfileIOChecks (config, view, PM_FPA_AFTER);
+    psFree (view);
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpLoop.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpLoop.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpLoop.c	(revision 22158)
@@ -0,0 +1,400 @@
+#include "pswarp.h"
+#include <ppStats.h>
+
+#define WCS_NONLIN_TOL 0.001            // Non-linear tolerance for header WCS
+
+// Lists of file rules for the detectors and skycells, and an independent list of everything else
+// Lists must end with a NULL
+static char *detectorFiles[] = { "PSWARP.INPUT", "PSWARP.MASK", "PSWARP.WEIGHT", NULL };
+static char *skycellFiles[] = { "PSWARP.OUTPUT", "PSWARP.OUTPUT.MASK", "PSWARP.OUTPUT.WEIGHT",
+                                "PSPHOT.OUTPUT", "PSPHOT.RESID", "PSPHOT.BACKMDL", "PSPHOT.BACKMDL.STDEV",
+                                "PSPHOT.BACKGND", "PSPHOT.BACKSUB", "PSPHOT.PSF.SAVE", "SOURCE.PLOT.MOMENTS",
+                                "SOURCE.PLOT.PSFMODEL", "SOURCE.PLOT.APRESID", NULL };
+static char *independentFiles[] = { "PSWARP.ASTROM", // Read independently from the input pixels
+                                    "PSWARP.SKYCELL", // Don't care about the skycell once we have its WCS
+                                    "PSPHOT.INPUT", // This is just a pointer to PSWARP.OUTPUT
+                                    "PSWARP.OUTPUT.SOURCES", // Save these independently so we can do the PSF
+                                    NULL };
+
+// Activate a list of files
+static void fileActivation(pmConfig *config, // Configuration
+                           char **files, // Files to turn on/off
+                           bool state   // Activation state
+    )
+{
+    for (int i = 0; files[i] != NULL; i++) {
+        pmFPAfileActivate(config->files, state, files[i]);
+    }
+    return;
+}
+
+// Run down the FPA hierarchy, checking files
+static bool ioChecksBefore(pmConfig *config // Configuration
+                           )
+{
+    pmFPAview *view = pmFPAviewAlloc(0); // View for checking
+    bool status = true;                 // Status of checks
+    status &= pmFPAfileIOChecks(config, view, PM_FPA_BEFORE);
+    view->chip = 0;
+    status &= pmFPAfileIOChecks(config, view, PM_FPA_BEFORE);
+    view->cell = 0;
+    status &= pmFPAfileIOChecks(config, view, PM_FPA_BEFORE);
+    psFree(view);
+    return status;
+}
+
+// Run up the FPA hierarchy, checking files
+static bool ioChecksAfter(pmConfig *config // Configuration
+                          )
+{
+    pmFPAview *view = pmFPAviewAlloc(0); // View for checking
+    view->chip = view->cell = 0;
+    bool status = true;                 // Status of checks
+    status &= pmFPAfileIOChecks(config, view, PM_FPA_AFTER);
+    view->cell = -1;
+    status &= pmFPAfileIOChecks(config, view, PM_FPA_AFTER);
+    view->chip = -1;
+    status &= pmFPAfileIOChecks(config, view, PM_FPA_AFTER);
+    psFree(view);
+    return status;
+}
+
+
+// Loop over the inputs, warp them to the output skycell and then write out the output.
+bool pswarpLoop(pmConfig *config)
+{
+    bool status; 
+
+    // load the recipe
+    psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, PSWARP_RECIPE);
+    if (!recipe) {
+        psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSWARP_RECIPE);
+        return false;
+    }
+
+    // output mask bits
+    psMaskType maskValue = psMetadataLookupU8(&status, recipe, "MASK.OUTPUT"); 
+    psAssert (status, "MASK.OUTPUT was not defined");
+
+    // select the input data sources
+    pmFPAfile *input = psMetadataLookupPtr(NULL, config->files, "PSWARP.INPUT");
+    if (!input) {
+        psError(PSWARP_ERR_CONFIG, true, "Can't find input data!\n");
+        return false;
+    }
+
+    // use the external astrometry source if supplied
+    pmFPAfile *astrom = psMetadataLookupPtr(NULL, config->files, "PSWARP.ASTROM");
+    if (!astrom) {
+        astrom = input;
+    }
+
+    if (astrom->camera != input->camera) {
+        psError(PS_ERR_UNKNOWN, true, "Input camera and astrometry camera do not match.");
+        return false;
+    }
+
+    // select the output readout
+    pmFPAview *view = pmFPAviewAlloc(0);
+    view->chip = 0;
+    view->cell = 0;
+    view->readout = 0;
+    pmReadout *output = pmFPAfileThisReadout(config->files, view, "PSWARP.OUTPUT");
+    if (!output) {
+        psError(PSWARP_ERR_CONFIG, true, "Can't find output data!\n");
+        return false;
+    }
+    psFree (view);
+
+    bool mdok;                          // Status of MD lookup
+    const char *statsName = psMetadataLookupStr(&mdok, config->arguments, "STATS"); // Filename for statistics
+    psMetadata *stats = NULL;           // Container for statistics
+    FILE *statsFile = NULL;             // File stream for statistics
+    if (mdok && statsName && strlen(statsName) > 0) {
+        psString resolved = pmConfigConvertFilename(statsName, config, true, true);
+        statsFile = fopen(resolved, "w");
+        if (!statsFile) {
+            psError(PS_ERR_IO, true, "Unable to open statistics file %s for writing.\n", resolved);
+            psFree(resolved);
+            return false;
+        }
+        psFree(resolved);
+        stats = psMetadataAlloc();
+    }
+
+    // Turn all skycell files on to generate them, and then turn them off for the loop over the input images
+    // the input, which is in a different format.
+    {
+        fileActivation(config, detectorFiles, false);
+        fileActivation(config, independentFiles, false);
+        fileActivation(config, skycellFiles, true);
+        ioChecksBefore(config);
+        fileActivation(config, skycellFiles, false);
+    }
+
+    // Read the input astrometry
+    {
+        pmFPAfileActivate(config->files, true, "PSWARP.ASTROM");
+
+        pmChip *chip;
+        pmFPAview *view = pmFPAviewAlloc(0);
+        pmFPAfileIOChecks (config, view, PM_FPA_BEFORE);
+        while ((chip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
+            psTrace ("pswarp", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+            if (!chip->process || !chip->file_exists) { continue; }
+            pmFPAfileIOChecks(config, view, PM_FPA_BEFORE);
+            pmCell *cell;
+            while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
+                psTrace ("pswarp", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+                if (!cell->process || !cell->file_exists) { continue; }
+                pmFPAfileIOChecks (config, view, PM_FPA_BEFORE);
+                pmFPAfileIOChecks (config, view, PM_FPA_AFTER);
+            }
+            pmFPAfileIOChecks (config, view, PM_FPA_AFTER);
+        }
+        pmFPAfileIOChecks (config, view, PM_FPA_AFTER);
+        psFree(view);
+
+        fileActivation(config, detectorFiles, true);
+        pmFPAfileActivate(config->files, false, "PSWARP.ASTROM");
+    }
+
+    // Turn on the source output --- we need to get rid of these so that we can measure the PSF
+    pmFPAfileActivate(config->files, true, "PSWARP.OUTPUT.SOURCES");
+
+    // Don't care about the skycell anymore --- we've read it, and that's all we need to do.
+    pmFPAfileActivate(config->files, false, "PSWARP.SKYCELL");
+    view = pmFPAviewAlloc(0);
+
+    // find the FPA phu
+    bool bilevelAstrometry = false;
+    pmHDU *phu = pmFPAviewThisPHU(view, astrom->fpa);
+    if (phu) {
+        char *ctype = psMetadataLookupStr(NULL, phu->header, "CTYPE1");
+        if (ctype) {
+            bilevelAstrometry = !strcmp (&ctype[4], "-DIS");
+        }
+    }
+    if (bilevelAstrometry) {
+        if (!pmAstromReadBilevelMosaic(input->fpa, phu->header)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to read bilevel mosaic astrometry for input FPA.");
+            psFree(view);
+            psFree(stats);
+            return false;
+        }
+    }
+
+    psList *cells = psListAlloc(NULL);  // List of cells, for concepts averaging
+
+    // files associated with the science image
+    pmFPAfileIOChecks (config, view, PM_FPA_BEFORE);
+
+    pmChip *chip;
+    while ((chip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
+        psTrace ("pswarp", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+        if (!chip->process || !chip->file_exists) { continue; }
+        pmFPAfileIOChecks (config, view, PM_FPA_BEFORE);
+
+        // read WCS data from the corresponding header
+        pmHDU *hdu = pmFPAviewThisHDU (view, astrom->fpa);
+        if (bilevelAstrometry) {
+            if (!pmAstromReadBilevelChip (chip, hdu->header)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to read bilevel chip astrometry for input FPA.");
+                psFree(view);
+                psFree(stats);
+                return false;
+            }
+        } else {
+            // we use a default FPA pixel scale of 1.0
+            if (!pmAstromReadWCS (input->fpa, chip, hdu->header, 1.0)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to read WCS astrometry for input FPA.");
+                psFree(view);
+                psFree(stats);
+                return false;
+            }
+        }
+
+        pmCell *cell;
+        while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
+            psTrace ("pswarp", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+            if (!cell->process || !cell->file_exists) { continue; }
+            pmFPAfileIOChecks (config, view, PM_FPA_BEFORE);
+
+            psListAdd(cells, PS_LIST_TAIL, cell);
+
+            // process each of the readouts
+            pmReadout *readout;
+            while ((readout = pmFPAviewNextReadout(view, input->fpa, 1)) != NULL) {
+                pmFPAfileIOChecks(config, view, PM_FPA_BEFORE);
+                if (!readout->data_exists) {
+                    continue;
+                }
+
+                // Copy the sources from the astrometry carrier to the input, so they can be accessed by
+                // pswarpTransformReadout
+                pmReadout *astromRO = pmFPAviewThisReadout(view, astrom->fpa); // Readout for astrometry
+                psArray *sources = psMetadataLookupPtr(&mdok, astromRO->analysis,
+                                                       "PSPHOT.SOURCES"); // Sources from astrometry
+                if (sources) {
+                    psMetadataAddPtr(readout->analysis, PS_LIST_TAIL, "PSPHOT.SOURCES", PS_DATA_ARRAY,
+                                     "Sources from input astrometry", sources);
+                }
+
+                pswarpTransformReadout(output, readout, config);
+
+                pmFPAfileIOChecks(config, view, PM_FPA_AFTER);
+            }
+            pmFPAfileIOChecks(config, view, PM_FPA_AFTER);
+        }
+        pmFPAfileIOChecks(config, view, PM_FPA_AFTER);
+    }
+
+    pmCell *outCell = output->parent;   // Output cell
+    pmChip *outChip = outCell->parent;  // Output chip
+    pmFPA *outFPA = outChip->parent;    // Output FP
+
+    if (!pswarpPixelFraction(output, stats, config)) {
+        // Don't write output images, and don't bother about anything else
+        output->data_exists = outCell->data_exists = outChip->data_exists = false;
+        psFree(cells);
+        psFree(view);
+        goto COMPLETED;
+    }
+
+    // Set variance factor
+    {
+        float varFactor = psMetadataLookupF32(NULL, output->analysis, PSWARP_ANALYSIS_VARFACTOR);
+        psAssert(isfinite(varFactor), "Should be something here.");
+        long goodPix = psMetadataLookupS64(NULL, output->analysis, PSWARP_ANALYSIS_GOODPIX);
+        psAssert(goodPix > 0, "Should be something here.");
+        varFactor /= goodPix;
+
+        psMetadataItem *vfItem = psMetadataLookup(outCell->concepts, "CELL.VARFACTOR"); // Item to update
+        psAssert(vfItem && vfItem->type == PS_TYPE_F32, "Concept should be as specified.");
+        if (!isfinite(vfItem->data.F32)) {
+            vfItem->data.F32 = varFactor;
+        } else {
+            vfItem->data.F32 *= varFactor;
+        }
+    }
+
+    if (!pmConceptsAverageCells(outCell, cells, NULL, NULL, false)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to average cell concepts.");
+        psFree(stats);
+        psFree(cells);
+        psFree(view);
+        return false;
+    }
+    psFree(cells);
+
+    if (!psMetadataCopy(outFPA->concepts, input->fpa->concepts)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to copy FPA concepts from input to output.");
+        psFree(stats);
+        psFree(view);
+        return false;
+    }
+
+    pmFPAfileIOChecks(config, view, PM_FPA_AFTER);
+
+    // Done with the detector side of things
+    fileActivation(config, detectorFiles, false);
+    fileActivation(config, independentFiles, false);
+    fileActivation(config, skycellFiles, true);
+
+    // We need a new PSF model for the warped frame
+    // It would be good to generate this analytically, but that's going to be tricky.
+    // We have a list of sources, so we could use those to redetermine the PSF model.
+    // Until Gene makes the necessary adaptations to psphot, we will simply redetermine the PSF model from
+    // scratch.
+    if (psMetadataLookupBool(&mdok, config->arguments, "PSF")) {
+        psMetadata *psphotRecipe = psMetadataLookupPtr(NULL, config->recipes,
+                                                       PSPHOT_RECIPE); // Recipe for psphot
+        if (!psphotRecipe) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find %s recipe.", PSPHOT_RECIPE);
+            return false;
+        }
+
+        psMetadataAddStr(psphotRecipe, PS_LIST_TAIL, "BREAK_POINT", PS_META_REPLACE,
+                         "Break point for psphot operations", "PSFMODEL");
+        psMetadataAddBool(psphotRecipe, PS_LIST_TAIL, PSPHOT_RECIPE_PSF_FAKE_ALLOW, PS_META_REPLACE,
+                          "Don't allow psphot to fit a fake PSF!", false);
+
+        // Get rid of the transformed sources so that we can measure the PSF
+        psMetadataRemoveKey(output->analysis, "PSPHOT.SOURCES");
+
+#if 0
+        pmFPAfile *photFile = psMetadataLookupPtr(NULL, config->files, "PSPHOT.INPUT");
+        pmFPACopy(photFile->fpa, outFPA);
+#endif
+
+        pmFPAview *view = pmFPAviewAlloc(0); // View into skycell
+        view->chip = view->cell = view->readout = 0;
+        if (!psphotReadout(config, view)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to determine PSF for warped image.");
+            return false;
+        }
+        psFree(view);
+
+        pmFPAfileActivate(config->files, true, "PSPHOT.INPUT");
+        pmFPAfileActivate(config->files, true, "PSPHOT.PSF.SAVE");
+    }
+
+    // Perform statistics on the output image
+    if (stats) {
+        if (!ppStatsFPA(stats, output->parent->parent->parent, view, maskValue, config)) {
+            psWarning("Unable to perform statistics on warped image.");
+        }
+    }
+
+    pmHDU *hdu = outFPA->hdu;           // HDU for the output warped image
+    if (!hdu->header) {
+        hdu->header = psMetadataAlloc();
+    }
+
+    if (!pmAstromWriteWCS(hdu->header, outFPA, outChip, WCS_NONLIN_TOL)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to generate WCS header.");
+        psFree(stats);
+        return false;
+    }
+
+    // Add MD5 information for readout
+    const char *chipName = psMetadataLookupStr(NULL, output->parent->parent->concepts, "CHIP.NAME");
+    const char *cellName = psMetadataLookupStr(NULL, output->parent->concepts, "CELL.NAME");
+    psString headerName = NULL; // Header name for MD5
+    psStringAppend(&headerName, "MD5_%s_%s_%d", chipName, cellName, view->readout);
+    psVector *md5 = psImageMD5(output->image); // md5 hash
+    psString md5string = psMD5toString(md5); // String
+    psFree(md5);
+    psMetadataAddStr(hdu->header, PS_LIST_TAIL, headerName, PS_META_REPLACE,
+                     "Image MD5", md5string);
+    psFree(md5string);
+    psFree(headerName);
+    psFree(view);
+
+    // Ensure everything is written out, at every level
+    ioChecksAfter(config);
+
+    // Now done with the skycell side of things
+
+    COMPLETED:
+    // Write out summary statistics
+    if (stats) {
+        psMetadataAddF32(stats, PS_LIST_TAIL, "DT_WARP", 0, "Time for warp completion",
+                         psTimerMark("pswarp"));
+
+        const char *statsMDC = psMetadataConfigFormat(stats);
+        if (!statsMDC) {
+            psError(PS_ERR_IO, false, "Unable to get statistics MDC file.\n");
+            psFree(stats);
+            fclose(statsFile);
+            return false;
+        }
+        fprintf(statsFile, "%s", statsMDC);
+        psFree((void*)statsMDC);
+        fclose(statsFile);
+
+        psFree(stats);
+    }
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpMapGrid.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpMapGrid.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpMapGrid.c	(revision 22158)
@@ -0,0 +1,241 @@
+# include "pswarp.h"
+
+// pswarpMapGridFromImage builds a set (a grid) of locally-linear maps which convert the source
+// coordinates (src) to destination coordinates (dest).  we construct a grid with superpixel
+// spacing of nXpix, nYpix.  The transformation for each grid cell is valid for the superpixel.
+// The grid over-fills the source image so every source image pixel is guaranteed to have a map.
+pswarpMapGrid *pswarpMapGridFromImage (pmReadout *dest, pmReadout *src, int nXpix, int nYpix) {
+
+    int i, ni;
+    int j, nj;
+
+    // start counting from the center of the superpixels
+    double xMin = 0.5*nXpix;
+    double yMin = 0.5*nYpix;
+
+    // the map is defined for coordinates in the image parent frame.
+    int Nx = src->image->numCols + src->image->col0;
+    int Ny = src->image->numRows + src->image->row0;
+
+    // allocate an extra superpixel to carry the remainder
+    int nXpts = Nx / nXpix;
+    int nYpts = Ny / nYpix;
+    if (Nx % nXpix) nXpts ++;
+    if (Ny % nYpix) nYpts ++;
+
+    // create the grid of maps
+    pswarpMapGrid *grid = pswarpMapGridAlloc (nXpts, nYpts);
+
+    // measure the map for the center of each superpixel
+    for (ni = 0, i = xMin; ni < nXpts; i += nXpix, ni++) {
+	for (nj = 0, j = yMin; nj < nYpts; j += nYpix, nj++) {
+	    pswarpMapSetLocalModel (grid->maps[ni][nj], dest, src, i, j);
+	}
+    }
+	    
+    grid->nXpix = nXpix;
+    grid->nYpix = nYpix;
+    grid->xMin = xMin;
+    grid->yMin = yMin;
+    return grid;
+}
+
+// set the grid coordinate (gridX,gridY) for the given source image coordinate (ix,iy)
+// XXX return true if the result is on the src image, false otherwise (???)
+bool pswarpMapGridSetGrid (pswarpMapGrid *grid, int ix, int iy, int *gridX, int *gridY) {
+
+    *gridX = 0.5 + (ix - grid->xMin) / (double) grid->nXpix;
+    *gridY = 0.5 + (iy - grid->yMin) / (double) grid->nYpix;
+
+    return true;
+}
+
+// given the specified grid coordinate (gridX, gridY), return the min and max coordinates for the tile
+bool pswarpMapGridCoordRange (pswarpMapGrid *grid, int gridX, int gridY, psPlane *min, psPlane *max) {
+
+    min->x = (gridX - 0.5)*grid->nXpix + grid->xMin;
+    min->y = (gridY - 0.5)*grid->nYpix + grid->yMin;
+
+    max->x = min->x + grid->nXpix;
+    max->y = min->y + grid->nYpix;
+
+    return true;
+}
+
+// given the specified grid coordinate (gridX), return the x-coordinate for the source image
+// corresponding to the next grid cell
+int pswarpMapGridNextGrid_X (pswarpMapGrid *grid, int gridX) {
+
+    int nextX = (gridX + 0.5)*grid->nXpix + grid->xMin;
+    return nextX;
+}
+
+// given the specified grid coordinate (gridY), return the y-coordinate for the source image
+// corresponding to the next grid cell
+int pswarpMapGridNextGrid_Y (pswarpMapGrid *grid, int gridY) {
+
+    int nextY = (gridY + 0.5)*grid->nYpix + grid->yMin;
+    return nextY;
+}
+
+// measure the max error accumulated in applying one grid point to its neighbors
+// XXX double-check this
+double pswarpMapGridMaxError (pswarpMapGrid *grid) {
+
+    double xRaw, yRaw;
+    double xRef, yRef;
+    double maxError = 0;
+
+    for (int i = 0; i < grid->nXpts - 1; i++) {
+	for (int j = 0; j < grid->nYpts - 1; j++) {
+
+	    // measure the output coordinates for the next grid position using the current grid map
+	    // compare with the coordinates measured using the next grid map
+	    pswarpMapApply (&xRaw, &yRaw, grid->maps[i][j], grid->maps[i][j]->xo + grid->nXpix, grid->maps[i][j]->yo);
+	    pswarpMapApply (&xRef, &yRef, grid->maps[i+1][j], grid->maps[i][j]->xo + grid->nXpix, grid->maps[i][j]->yo);
+
+	    double posError = hypot (xRaw-xRef, yRaw-yRef);
+	    maxError = PS_MAX (maxError, posError);
+	}
+    }	
+    return maxError;
+}
+
+// given the source coordinate (inX,inY), return the destination coordinate (outX,outY)
+bool pswarpMapApply (double *outX, double *outY, pswarpMap *map, double inX, double inY) {
+
+    *outX = map->Xo + map->Xx*inX + map->Xy*inY;
+    *outY = map->Yo + map->Yx*inX + map->Yy*inY;
+
+    return true;
+}
+
+// determine the (linear) map for the given pixel (ix,iy) from source image (src) to the destination image (dest)
+// pixel is in src coords. input and output pixel coordinates are in the parent frame of the image (Note that the
+// astrometric transformations are supplied for the parent image coordinate frame.
+bool pswarpMapSetLocalModel (pswarpMap *map, pmReadout *dest, pmReadout *src, int ix, int iy) {
+
+    pmCell *cell = NULL;
+
+    cell = src->parent;
+    pmChip *chipSrc = cell->parent;
+    pmFPA *fpaSrc = chipSrc->parent;
+
+    cell = dest->parent;
+    pmChip *chipDest = cell->parent;
+    pmFPA *fpaDest = chipDest->parent;
+
+    // XXX save these as static for speed?
+    psPlane *offset = psPlaneAlloc();
+
+    psPlane *FP = psPlaneAlloc();
+    psPlane *TP = psPlaneAlloc();
+    psSphere *sky = psSphereAlloc();
+
+    psPlane *V00 = psPlaneAlloc();
+    psPlane *V10 = psPlaneAlloc();
+    psPlane *V01 = psPlaneAlloc();
+
+    // XXX need to include readout->cell->chip offsets
+
+    // V(0,0) position
+    offset->x = ix;
+    offset->y = iy;
+    psPlaneTransformApply(FP, chipSrc->toFPA, offset);
+    psPlaneTransformApply (TP, fpaSrc->toTPA, FP);
+    psDeproject (sky, TP, fpaSrc->toSky);
+    psProject (TP, sky, fpaDest->toSky);
+    psPlaneTransformApply (FP, fpaDest->fromTPA, TP);
+    psPlaneTransformApply (V00, chipDest->fromFPA, FP);
+    
+    // V(1,0) position
+    offset->x = ix + 1;
+    offset->y = iy;
+    psPlaneTransformApply(FP, chipSrc->toFPA, offset);
+    psPlaneTransformApply (TP, fpaSrc->toTPA, FP);
+    psDeproject (sky, TP, fpaSrc->toSky);
+    psProject (TP, sky, fpaDest->toSky);
+    psPlaneTransformApply (FP, fpaDest->fromTPA, TP);
+    psPlaneTransformApply (V10, chipDest->fromFPA, FP);
+    
+    // V(0,1) position
+    offset->x = ix;
+    offset->y = iy + 1;
+    psPlaneTransformApply(FP, chipSrc->toFPA, offset);
+    psPlaneTransformApply (TP, fpaSrc->toTPA, FP);
+    psDeproject (sky, TP, fpaSrc->toSky);
+    psProject (TP, sky, fpaDest->toSky);
+    psPlaneTransformApply (FP, fpaDest->fromTPA, TP);
+    psPlaneTransformApply (V01, chipDest->fromFPA, FP);
+
+    map->Xx = V10->x - V00->x;
+    map->Xy = V01->x - V00->x;
+    map->Xo = V00->x - map->Xx*ix - map->Xy*iy;
+
+    map->Yx = V10->y - V00->y;
+    map->Yy = V01->y - V00->y;
+    map->Yo = V00->y - map->Yx*ix - map->Yy*iy;
+ 
+    map->xo = ix;
+    map->yo = iy;
+
+    psFree (offset);
+    psFree (FP);
+    psFree (TP);
+    psFree (sky);
+
+    psFree (V00);
+    psFree (V10);
+    psFree (V01);
+
+    return true;
+}
+
+static void pswarpMapFree (pswarpMap *map) {
+  return;
+}
+
+pswarpMap *pswarpMapAlloc () {
+
+  pswarpMap *map = (pswarpMap *) psAlloc (sizeof(pswarpMap));
+  psMemSetDeallocator(map, (psFreeFunc) pswarpMapFree);
+
+  return map;
+}
+
+static void pswarpMapGridFree (pswarpMapGrid *grid) {
+
+    if (grid == NULL) return;
+    if (grid->maps == NULL) return;
+
+    for (int i = 0; i < grid->nXpts; i++) {
+	for (int j = 0; j < grid->nYpts; j++) {
+	    psFree (grid->maps[i][j]);
+	}
+	psFree (grid->maps[i]);
+    }
+    psFree (grid->maps);
+    return;
+}
+
+pswarpMapGrid *pswarpMapGridAlloc (int nXpts, int nYpts) {
+
+  pswarpMapGrid *grid = (pswarpMapGrid *) psAlloc (sizeof(pswarpMapGrid));
+  psMemSetDeallocator(grid, (psFreeFunc) pswarpMapGridFree);
+
+  grid->maps = psAlloc (nXpts*sizeof(void **));
+  for (int i = 0; i < nXpts; i++) {
+      grid->maps[i] = psAlloc (nYpts*sizeof(void *));
+      for (int j = 0; j < nYpts; j++) {
+	  grid->maps[i][j] = pswarpMapAlloc();
+      }
+  }
+  grid->nXpts = nXpts;
+  grid->nYpts = nYpts;
+
+  grid->nXpix = 0;
+  grid->nYpix = 0;
+  
+  return grid;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpMatchRange.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpMatchRange.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpMatchRange.c	(revision 22158)
@@ -0,0 +1,119 @@
+# include "pswarp.h"
+
+# define TEST_MINMAX \
+    psPlaneTransformApply(destFP, chipDest->toFPA, destPix); \
+    psPlaneTransformApply (destTP, fpaDest->toTPA, destFP); \
+    psDeproject (sky, destTP, fpaDest->toSky); \
+    psProject (srcTP, sky, fpaSrc->toSky); \
+    psPlaneTransformApply (srcFP, fpaSrc->fromTPA, srcTP); \
+    psPlaneTransformApply (srcPix, chipSrc->fromFPA, srcFP); \
+    *minX = PS_MIN (*minX, srcPix->x); \
+    *minY = PS_MIN (*minY, srcPix->y); \
+    *maxX = PS_MAX (*maxX, srcPix->x); \
+    *maxY = PS_MAX (*maxY, srcPix->y);
+
+// we are warping from src to dest.  find the max overlapping pixels in the INPUT (src)
+// coordinate frame.  NOTE: these are in the parent pixel frame since the astrometric
+// transformation refers to the parent frame
+bool pswarpMatchRange (int *minX, int *minY, int *maxX, int *maxY, pmReadout *dest, pmReadout *src) {
+
+    // transform input corners and edge centers to output coords
+    // find max overlapping region of output image
+    
+    pmCell *cell = NULL;
+
+    cell = src->parent;
+    pmChip *chipSrc = cell->parent;
+    pmFPA *fpaSrc = chipSrc->parent;
+
+    cell = dest->parent;
+    pmChip *chipDest = cell->parent;
+    pmFPA *fpaDest = chipDest->parent;
+
+    *minX = src->image->numCols + src->image->col0 - 1;
+    *minY = src->image->numRows + src->image->row0 - 1;
+    *maxX = src->image->col0;
+    *maxY = src->image->row0;
+
+    // XXX save these as static for speed?
+    psPlane *srcPix = psPlaneAlloc();
+    psPlane *srcFP  = psPlaneAlloc();
+    psPlane *srcTP  = psPlaneAlloc();
+
+    psPlane *destPix = psPlaneAlloc();
+    psPlane *destFP  = psPlaneAlloc();
+    psPlane *destTP  = psPlaneAlloc();
+
+    psSphere *sky = psSphereAlloc();
+
+    destPix->x = dest->image->col0;
+    destPix->y = dest->image->row0;
+    TEST_MINMAX;
+    
+    destPix->x = dest->image->col0 + dest->image->numCols;
+    destPix->y = dest->image->row0;
+    TEST_MINMAX;
+    
+    destPix->x = dest->image->col0 + dest->image->numCols;
+    destPix->y = dest->image->row0 + dest->image->numRows;
+    TEST_MINMAX;
+    
+    destPix->x = dest->image->col0;
+    destPix->y = dest->image->row0 + dest->image->numRows;
+    TEST_MINMAX;
+    
+    destPix->x = dest->image->col0 + 0.5*dest->image->numCols;
+    destPix->y = dest->image->row0;
+    TEST_MINMAX;
+    
+    destPix->x = dest->image->col0;
+    destPix->y = dest->image->row0 + 0.5*dest->image->numRows;
+    TEST_MINMAX;
+    
+    destPix->x = dest->image->col0 + 0.5*dest->image->numCols;
+    destPix->y = dest->image->row0;
+    TEST_MINMAX;
+
+    destPix->x = dest->image->col0;
+    destPix->y = dest->image->row0 + 0.5*dest->image->numRows;
+    TEST_MINMAX;
+
+    *minX = PS_MAX (*minX, src->image->col0);
+    *minY = PS_MAX (*minY, src->image->row0);
+    *maxX = PS_MIN (*maxX, src->image->numCols + src->image->col0);
+    *maxY = PS_MIN (*maxY, src->image->numRows + src->image->row0);
+
+    // demo forward and backward transformation
+# if (0)
+    srcPix->x = *minX;
+    srcPix->y = *minY;
+    psPlaneTransformApply(srcFP, chipSrc->toFPA, srcPix); 
+    psPlaneTransformApply (srcTP, fpaSrc->toTPA, srcFP); 
+    psDeproject (sky, srcTP, fpaSrc->toSky); 
+    psProject (destTP, sky, fpaDest->toSky); 
+    psPlaneTransformApply (destFP, fpaDest->fromTPA, destTP); 
+    psPlaneTransformApply (destPix, chipDest->fromFPA, destFP); 
+    fprintf (stderr, "%f,%f -> %f,%f ", srcPix->x, srcPix->y, destPix->x, destPix->y);
+
+    psPlaneTransformApply(destFP, chipDest->toFPA, destPix); 
+    psPlaneTransformApply (destTP, fpaDest->toTPA, destFP); 
+    psDeproject (sky, destTP, fpaDest->toSky); 
+    psProject (srcTP, sky, fpaSrc->toSky); 
+    psPlaneTransformApply (srcFP, fpaSrc->fromTPA, srcTP); 
+    psPlaneTransformApply (srcPix, chipSrc->fromFPA, srcFP); 
+    fprintf (stderr, "-> %f,%f ", srcPix->x, srcPix->y);
+# endif
+
+    psFree (srcPix);
+    psFree (srcFP);
+    psFree (srcTP);
+
+    psFree (destPix);
+    psFree (destFP);
+    psFree (destTP);
+
+    psFree (sky);
+
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpParseCamera.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpParseCamera.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpParseCamera.c	(revision 22158)
@@ -0,0 +1,148 @@
+# include "pswarp.h"
+
+bool pswarpParseCamera (pmConfig *config) {
+
+    bool status;
+    bool mdok;                          // Status of MD lookup
+    pmFPAfile *skycell = NULL;
+    pmConfig *skyConfig = NULL;
+
+    // the input image(s) are required arguments; they define the camera
+    status = false;
+    pmFPAfile *input = pmFPAfileDefineFromArgs(&status, config, "PSWARP.INPUT", "INPUT");
+    if (!input || !status) {
+        psError(PSWARP_ERR_CONFIG, false, "Failed to build FPA from PSWARP.INPUT");
+        return false;
+    }
+
+    // the input image(s) are required arguments; they define the camera
+    status = false;
+    pmFPAfile *astrom = pmFPAfileDefineFromArgs(&status, config, "PSWARP.ASTROM", "ASTROM");
+    if (!status) {
+        psError (PS_ERR_UNKNOWN, false, "failed to load find definition");
+        return NULL;
+    }
+    if (astrom) {
+        psLogMsg ("pswarp", 3, "using supplied astrometry\n");
+    } else {
+        psLogMsg ("pswarp", 3, "using header astrometry\n");
+    }
+
+    // the mask is not required - but must conform to input camera
+    pmFPAfile *inMask = pmFPAfileBindFromArgs(&status, input, config, "PSWARP.MASK", "MASK");
+    if (!status) {
+        psError (PS_ERR_UNKNOWN, false, "failed to load find definition");
+        return NULL;
+    }
+    if (!inMask) {
+        psLogMsg ("pswarp", 3, "no mask supplied\n");
+    }
+    
+    // loading the mask here should have invoked pmConfigMaskReadHeader()
+    if (!pswarpSetMaskBits (config)) {
+        psError(PS_ERR_IO, false, "failed to set mask bits");
+        return NULL;
+    }
+
+    pmFPAfile *inWeight = pmFPAfileBindFromArgs(&status, input, config, "PSWARP.WEIGHT", "WEIGHT");
+    if (!status) {
+        psError (PS_ERR_UNKNOWN, false, "failed to load find definition");
+        return NULL;
+    }
+    if (!inWeight) {
+        psLogMsg ("pswarp", 3, "no weight supplied\n");
+    }
+
+    // the input skycell is a required argument: it defines the output image
+    // XXX we may need a different skycell structure here
+    status = pswarpDefineSkycell(&skycell, &skyConfig, config, "PSWARP.SKYCELL", "SKYCELL");
+    if (!status) {
+        psError(PSWARP_ERR_CONFIG, false, "Failed to build FPA from PSWARP.SKYCELL");
+        return false;
+    }
+    psFree(skyConfig);
+
+    // The output skycell
+    pmFPAfile *output = pmFPAfileDefineSkycell(config, NULL, "PSWARP.OUTPUT");
+    if (!output) {
+        psError(PSWARP_ERR_CONFIG, false, "Failed to build FPA from PSWARP.OUTPUT");
+        return false;
+    }
+    pmFPAfile *outMask = pmFPAfileDefineSkycell(config, output->fpa, "PSWARP.OUTPUT.MASK");
+    if (!outMask) {
+        psError(PSWARP_ERR_CONFIG, false, "Failed to build FPA from PSWARP.OUTPUT.MASK");
+        return false;
+    }
+
+    output->save = true;
+    outMask->save = true;
+
+    if (inWeight) {
+        pmFPAfile *outWeight = pmFPAfileDefineSkycell(config, output->fpa, "PSWARP.OUTPUT.WEIGHT");
+        if (!outWeight) {
+            psError(PSWARP_ERR_CONFIG, false, "Failed to build FPA from PSWARP.OUTPUT.WEIGHT");
+            return false;
+        }
+        outWeight->save = true;
+    }
+
+    if (astrom) {
+        pmFPAfile *outSources = pmFPAfileDefineSkycell(config, output->fpa, "PSWARP.OUTPUT.SOURCES");
+        if (!outSources) {
+            psError(PSWARP_ERR_CONFIG, false, "Failed to build FPA from PSWARP.OUTPUT.SOURCES");
+            return false;
+        }
+        outSources->save = true;
+    }
+
+    if (psMetadataLookupBool(&mdok, config->arguments, "PSF")) {
+        // This file, PSPHOT.INPUT, is just used as a carrier; output files (eg, PSPHOT.RESID) are defined by
+        // psphotDefineFiles
+        pmFPAfile *psphotInput = pmFPAfileDefineSkycell(config, output->fpa, "PSPHOT.INPUT");
+        if (!psphotInput) {
+            psError(PS_ERR_IO, false, _("Unable to generate output file from PSPHOT.INPUT"));
+            return false;
+        }
+
+        // Ensure psphot defines an output file for the PSF.
+        psMetadata *psphotRecipe = psMetadataLookupPtr(NULL, config->recipes, PSPHOT_RECIPE); // Recipe
+        if (!psphotRecipe) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find %s recipe.", PSPHOT_RECIPE);
+            return false;
+        }
+        psMetadataAddBool(psphotRecipe, PS_LIST_TAIL, "SAVE.PSF", PS_META_REPLACE, "Save PSF?", true);
+
+        // Define associated psphot input/output files
+        if (!psphotDefineFiles(config, psphotInput)) {
+            psError(PSPHOT_ERR_CONFIG, false,
+                    "Unable to define the additional input/output files for psphot");
+            return false;
+        }
+
+        // Turn off writing the sources we find as part of deriving the PSF --- they might clobber the ones we
+        // get from transforming the input coordinates.
+        pmFPAfile *psphotSources = psMetadataLookupPtr(NULL, config->files, "PSPHOT.OUTPUT");
+        assert(psphotSources);
+        psphotSources->save = false;
+    }
+
+    // Chip selection: turn on only the chips specified
+    char *chipLine = psMetadataLookupStr(&mdok, config->arguments, "CHIP_SELECTIONS");
+    if (mdok) {
+        psArray *chips = psStringSplitArray (chipLine, ",", false);
+        if (chips->n > 0) {
+            pmFPASelectChip (input->fpa, -1, true); // deselect all chips
+            for (int i = 0; i < chips->n; i++) {
+                int chipNum = atoi(chips->data[i]);
+                if (! pmFPASelectChip(input->fpa, chipNum, false)) {
+                    psError(PSWARP_ERR_CONFIG, true, "Chip number %d doesn't exist in camera.\n", chipNum);
+                    return false;
+                }
+            }
+        }
+        psFree (chips);
+    }
+
+    psTrace("pswarp", 1, "Done with pswarpParseCamera...\n");
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpPixelFraction.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpPixelFraction.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpPixelFraction.c	(revision 22158)
@@ -0,0 +1,90 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "pswarp.h"
+
+bool pswarpPixelFraction(const pmReadout *readout, psMetadata *stats, const pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_IMAGE_NON_NULL(readout->image, false);
+    PS_ASSERT_IMAGE_TYPE(readout->image, PS_TYPE_F32, false);
+    if (!readout->mask) {
+        // Can't do anything
+        return true;
+    }
+    PS_ASSERT_IMAGE_NON_NULL(readout->mask, false);
+    PS_ASSERT_IMAGES_SIZE_EQUAL(readout->mask, readout->image, false);
+    PS_ASSERT_IMAGE_TYPE(readout->mask, PS_TYPE_MASK, false);
+
+    if (stats) {
+        PS_ASSERT_METADATA_NON_NULL(stats, false);
+    }
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_METADATA_NON_NULL(config->arguments, false);
+
+    bool status; 
+
+    float minFrac = psMetadataLookupF32(NULL, config->arguments, "ACCEPT.FRAC"); // Minimum fraction
+
+    // load the recipe
+    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSWARP_RECIPE);
+    if (!recipe) {
+        psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSWARP_RECIPE);
+        return false;
+    }
+
+    // output mask bits
+    psMaskType maskValue = psMetadataLookupU8(&status, recipe, "MASK.OUTPUT"); 
+    psAssert (status, "MASK.OUTPUT was not defined");
+
+    psImage *image = readout->image;    // Image of interest
+    psImage *mask = readout->mask;      // Mask image
+
+    int numCols = image->numCols, numRows = image->numRows; // Size of image
+    long numPix = numCols * numRows;
+
+    // Range of valid pixels
+    int xMin = INT_MAX, xMax = -INT_MAX, yMin = INT_MAX, yMax = -INT_MAX;
+
+    long numBad = 0;                     // Number of bad pixels
+    for (int y = 0; y < numRows; y++) {
+        for (int x = 0; x < numCols; x++) {
+            if (mask->data.PS_TYPE_MASK_DATA[y][x] & maskValue) {
+                numBad++;
+            } else {
+                if (y > yMax) {
+                    yMax = y;
+                }
+                if (y < yMin) {
+                    yMin = y;
+                }
+                if (x > xMax) {
+                    xMax = x;
+                }
+                if (x < xMin) {
+                    xMin = x;
+                }
+            }
+        }
+    }
+
+    float goodFrac = (numPix - numBad) / (float)numPix; // Fraction of good pixels
+    bool accept = (goodFrac >= minFrac ? true : false); // Accept this readout?
+
+    if (stats) {
+        psMetadataAddBool(stats, PS_LIST_HEAD, "ACCEPT", 0, "Accept this readout?", accept);
+
+        psMetadataAddS32(stats, PS_LIST_TAIL, "RANGE.XMIN", 0, "Minimum valid x value", xMin);
+        psMetadataAddS32(stats, PS_LIST_TAIL, "RANGE.XMAX", 0, "Maximum valid x value", xMax);
+        psMetadataAddS32(stats, PS_LIST_TAIL, "RANGE.YMIN", 0, "Minimum valid y value", yMin);
+        psMetadataAddS32(stats, PS_LIST_TAIL, "RANGE.YMAX", 0, "Maximum valid y value", yMax);
+    }
+
+    return accept;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpSetMaskBits.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpSetMaskBits.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpSetMaskBits.c	(revision 22158)
@@ -0,0 +1,83 @@
+# include "pswarp.h"
+
+// This function is called by the stand-alone pswarp program to set the mask values in the
+// config file.  It sets the named mask values MASK.PSPHOT and MARK.PSPHOT in the PSPHOT
+// recipe.  Functions or programs which call psphotReadout as a library function must set these
+// named mask values in the PSPHOT recipe on their own.  This function should only be called
+// after the first header of the input mask image has been loaded and the named mask bits
+// updated in the config metadata.
+
+bool pswarpSetMaskBits (pmConfig *config) {
+
+    psMaskType maskIn = 0x00;			// mask for the input image
+    psMaskType markIn = 0x00;			// mark for the input image
+    psMaskType maskOut = 0x00;			// mask for the output image
+    psMaskType markOut = 0x00;			// mark for the output image
+
+    // this function sets the required single-image mask bits
+    if (!pmConfigMaskSetBits (&maskIn, &markIn, config)) {
+	psError (PS_ERR_UNKNOWN, true, "Unable to define the mask bit values");
+	return false;
+    }
+
+    // mask for non-linear flat regions (default to DETECTOR if not defined)
+    psMaskType badMask = pmConfigMaskGet("BAD.WARP", config); 
+    if (!badMask) {
+	badMask = 0x01;
+	pmConfigMaskSet (config, "BAD.WARP", badMask);
+    }
+    maskOut |= badMask;
+
+    // mask for non-linear flat regions (default to DETECTOR if not defined)
+    psMaskType poorMask = pmConfigMaskGet("POOR.WARP", config); 
+    if (!poorMask) {
+	poorMask = 0x02;
+	pmConfigMaskSet (config, "POOR.WARP", poorMask);
+    }
+    maskOut |= poorMask;
+
+    // search for an unset bit to use for MARK:
+    markOut = 0x80;
+
+    int nBits = sizeof(psMaskType) * 8;
+    for (int i = 0; !markOut && (i < nBits); i++) {
+	if (maskOut & markOut) {
+	    markOut >>= 1;
+	} else {
+	    markOut = markOut;
+	}
+    }
+
+    if (!markOut) {
+	psError (PS_ERR_UNKNOWN, true, "Unable to define the MARK bit mask: all bits taken!");
+	return false;
+    }
+
+    // update the pswarp recipe
+    psMetadata *warpRecipe = psMetadataLookupPtr (NULL, config->recipes, PSWARP_RECIPE);
+    if (!warpRecipe) {
+        psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSWARP_RECIPE);
+        return false;
+    }
+
+    // set maskOut and markOut in the psphot recipe
+    // NOTE: psphot works on the output images, not input images, so set the MARK and MASK correctly here
+    psMetadataAddU8 (warpRecipe, PS_LIST_TAIL, "MASK.INPUT",  PS_META_REPLACE, "user-defined mask", maskIn);
+    psMetadataAddU8 (warpRecipe, PS_LIST_TAIL, "MARK.INPUT",  PS_META_REPLACE, "user-defined mask", markIn);
+    psMetadataAddU8 (warpRecipe, PS_LIST_TAIL, "MASK.OUTPUT", PS_META_REPLACE, "user-defined mask", maskOut);
+    psMetadataAddU8 (warpRecipe, PS_LIST_TAIL, "MARK.OUTPUT", PS_META_REPLACE, "user-defined mask", markOut);
+
+    // update the psphot recipe
+    psMetadata *psphotRecipe = psMetadataLookupPtr (NULL, config->recipes, PSPHOT_RECIPE);
+    if (!psphotRecipe) {
+        psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSPHOT_RECIPE);
+        return false;
+    }
+
+    // set maskOut and markOut in the psphot recipe
+    // NOTE: psphot works on the output images, not input images, so set the MARK and MASK correctly here
+    psMetadataAddU8 (psphotRecipe, PS_LIST_TAIL, "MARK.PSPHOT", PS_META_REPLACE, "user-defined mask", markOut);
+    psMetadataAddU8 (psphotRecipe, PS_LIST_TAIL, "MASK.PSPHOT", PS_META_REPLACE, "user-defined mask", maskOut);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpSetThreads.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpSetThreads.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpSetThreads.c	(revision 22158)
@@ -0,0 +1,21 @@
+# include "pswarp.h"
+
+// each thread runs this function, starting a new job when it finished with an old one
+// it is called with a (void *) pointer to its own thread pointer
+bool pswarpThread_pswarpTransformTile (psThreadJob *job) {
+
+    pswarpTransformTileArgs *args = job->args->data[0];
+    bool status = pswarpTransformTile (args);
+    return status;
+}
+
+bool pswarpSetThreads () {
+
+    psThreadTask *task = NULL;
+
+    task = psThreadTaskAlloc ("PSWARP_TRANSFORM_TILE", 1);
+    task->function = &pswarpThread_pswarpTransformTile;
+    psThreadTaskAdd (task);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpThreadLauncher.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpThreadLauncher.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpThreadLauncher.c	(revision 22158)
@@ -0,0 +1,39 @@
+# include "pswarp.h"
+
+// each thread runs this function, starting a new job when it finished with an old one
+// it is called with a (void *) pointer to its own thread pointer
+void *pswarpThreadLauncher (void *data) {
+
+    psThread *self = data;
+    psThreadJob *job = NULL;
+
+    while (1) {
+
+	// if we get an error, just wait until we are cleared or killed
+	while (self->fault) {
+	    usleep (10000);
+	}
+
+	// request a new job, if there are none available, sleep a bit
+	// we have to lock here so the job queue cannot be empty yet no threads busy
+	psThreadLock();
+	while ((job = psThreadJobGetPending ()) == NULL) {
+	    psThreadUnlock();
+	    usleep (10000);
+	}
+	self->busy = true;
+	psThreadUnlock();
+
+	// list all allowed job types here
+	if (!strcmp (job->type, "PSWARP_TRANSFORM_TILE")) {
+	    pswarpTransformTileArgs *args = job->args->data[0];
+	    bool status = pswarpTransformTile (args);
+	    if (!status) {
+		self->fault = true;
+	    }
+	    // we do not have to lock here because this transition is not tied to the job queue
+	    self->busy = false;  
+	    continue;
+	}
+    }  
+}
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpThreads.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpThreads.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpThreads.c	(revision 22158)
@@ -0,0 +1,52 @@
+# include "pswarp.h"
+
+typedef enum {
+  PSWARP_TRANSFORM_TILE
+} pswarpJobType;
+
+typedef struct {
+  pswarpJobType type;
+  void *opts;
+} pswarpJob;
+
+static psArray *jobs = NULL;
+static pthread_t *threads = NULL;
+
+bool pswarpThreadsAddJob (pwarpJob *job) {
+
+  if (jobs == NULL) {
+    jobs = psArrayAlloc (16);
+  }
+
+  psArrayAdd (jobs, job);
+  return true;
+}
+
+bool pswarpThreadsLaunchJobs () {
+
+  while () {
+    while ((job = psListGetAndRemove (jobs, PS_LIST_HEAD)) == NULL) {
+      usleep (50000);
+    }
+
+    switch (job->type) {
+      case PSWARP_TRANSFORM_TILE:
+	status = pswarpTransformTile ((pswarpTransformTileOpts *)job->opts);
+	// send a message somewhere if the job fails
+	break;
+    }
+  }  
+}
+
+// create a pool of Nthreads
+bool pswarpThreadsCreate (int nThreads) {
+
+  threads = (pthread_t *) psAlloc (sizeof(pthread_t));
+
+  for (int i = 0; i < nThreads; i++) {
+    pthread_create (&threads[i], NULL, &function, NULL);
+  }
+
+  return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpTransformReadout.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpTransformReadout.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpTransformReadout.c	(revision 22158)
@@ -0,0 +1,151 @@
+# include "pswarp.h"
+
+// NOTE: in this function, the coordinates are transformed from the OUTPUT to the INPUT
+bool pswarpTransformReadout(pmReadout *output, pmReadout *input, pmConfig *config)
+{
+    // XXX this implementation currently ignores the use of the region
+    psImage *region = NULL;
+
+    psTimerStart ("warp");
+
+    // Get warp parameters
+    bool mdok;
+    int nGridX = psMetadataLookupS32(NULL, config->arguments, "GRID.NX");
+    int nGridY = psMetadataLookupS32(NULL, config->arguments, "GRID.NY");
+    psImageInterpolateMode interpolationMode = psMetadataLookupS32(NULL, config->arguments, "INTERPOLATION.MODE");
+
+    // load the recipe
+    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSWARP_RECIPE);
+    psAssert (recipe, "missing recipe %s", PSWARP_RECIPE);
+
+    // output mask bits
+    psMaskType maskIn   = psMetadataLookupU8(&mdok, recipe, "MASK.INPUT"); 
+    psMaskType maskPoor = pmConfigMaskGet("POOR.WARP", config); 
+    psMaskType maskBad  = pmConfigMaskGet("BAD.WARP", config); 
+    psAssert (mdok, "MASK.INPUT was not defined");
+
+    int nThreads = psMetadataLookupS32 (&mdok, config->arguments, "NTHREADS");
+    if (!mdok) nThreads = 0;
+
+    // Flux fraction for "poor"
+    float poorFrac = psMetadataLookupF32(NULL, config->arguments, "POOR.FRAC"); 
+
+    // pswarpMapGridFromImage builds a set of locally-linear maps which convert the
+    // output coordinates to input coordinates
+    pswarpMapGrid *grid = pswarpMapGridFromImage (input, output, nGridX, nGridY);
+
+    // XXX optionally modify the grid based on this result and force the maxError < XXX
+    double maxError = pswarpMapGridMaxError (grid);
+    psLogMsg ("pswarp", 3, "maximum error using this grid sampling: %f\n", maxError);
+
+    // Interpolation options : move these from the arguments to explicit assignments
+    psImageInterpolateOptions *interp = psImageInterpolateOptionsAlloc(interpolationMode, input->image, input->weight, input->mask, maskIn, NAN, NAN, maskBad, maskPoor, poorFrac);
+
+    if (input->weight && !output->weight) {
+	output->weight = psImageAlloc(output->image->numCols, output->image->numRows, PS_TYPE_F32);
+	psImageInit(output->weight, NAN);
+    }
+    if ((input->mask || maskPoor || maskBad) && !output->mask) {
+	output->mask = psImageAlloc(output->image->numCols, output->image->numRows, PS_TYPE_MASK);
+	psImageInit(output->mask, maskBad);
+    }
+
+    // total number of good pixels across all tiles (summed below)
+    int goodPixels = 0;
+
+    // create jobs and supply them to the threads
+    for (int gridY = 0; gridY < grid->nYpts; gridY++) {
+	for (int gridX = 0; gridX < grid->nXpts; gridX++) {
+
+	    pswarpTransformTileArgs *args = pswarpTransformTileArgsAlloc();
+
+	    // these items are just views to the data; they are not freed with args
+	    args->input = input;
+	    args->output = output;
+	    args->grid = grid;
+	    args->interp = interp;
+	    args->region = region;
+
+	    args->gridX = gridX;
+	    args->gridY = gridY;
+	    args->goodPixels = 0;
+
+	    // allocate a job
+	    psThreadJob *job = psThreadJobAlloc ("PSWARP_TRANSFORM_TILE");
+
+	    // construct the arguments for this job
+	    // job is pswarpTransformTile (gridX, gridY);
+	    psArrayAdd (job->args, 1, args);
+	    // fprintf (stderr, "adding job %d,%d, Nargs: %ld\n", gridX, gridY, job->args->n);
+
+	    // call: pswarpTransformTile (args);
+	    if (!psThreadJobAddPending (job)) {
+		psError(PS_ERR_UNKNOWN, false, "Unable to warp image.");
+		return false;
+	    }
+	    psFree (args);
+	}
+    }
+
+    // wait for the threads to finish and manage results
+    // wait here for the threaded jobs to finish
+    if (!psThreadPoolWait ()) {
+	psError(PS_ERR_UNKNOWN, false, "Unable to interpolate image.");
+	return false;
+    }
+    fprintf (stderr, "success for threaded jobs\n");
+
+    // each job records its own goodPixel values; sum them here
+    // we have only supplied one type of job, so we can assume the types here
+    psThreadJob *job = NULL;
+    while ((job = psThreadJobGetDone()) != NULL) {
+	if (job->args->n < 1) {
+	    fprintf (stderr, "error with job\n");
+	} else {
+	    pswarpTransformTileArgs *args = job->args->data[0];
+	    // fprintf (stderr, "finished job %d,%d, Nargs: %ld\n", args->gridX, args->gridY, job->args->n);
+	    goodPixels += args->goodPixels;
+	}
+	psFree (job);
+    }
+    psFree(interp);
+    psFree(grid);
+
+
+    // Store the variance factor and number of good pixels
+    if (goodPixels > 0) {
+	// Variance factor: large factor --> small scale
+        float varFactor = psImageInterpolateVarianceFactor(input->image->numCols / 2.0 + input->image->col0, input->image->numRows / 2.0 + input->image->row0, interp); 
+        psMetadataItem *vfItem = psMetadataLookup(output->analysis, PSWARP_ANALYSIS_VARFACTOR);
+        if (vfItem) {
+            psMetadataItem *goodpixItem = psMetadataLookup(output->analysis, PSWARP_ANALYSIS_GOODPIX);
+            psAssert(goodpixItem, "It should be where we left it!");
+            psAssert(vfItem->type == PS_TYPE_F32 && goodpixItem->type == PS_TYPE_S64,
+                     "Should be the type we said.");
+
+            vfItem->data.F32 += varFactor * goodPixels;
+            goodpixItem->data.S64 += goodPixels;
+        } else {
+            psMetadataAddF32(output->analysis, PS_LIST_TAIL, PSWARP_ANALYSIS_VARFACTOR, 0,
+                             "Variance factor weighted by the good pixels", varFactor * goodPixels);
+            psMetadataAddS64(output->analysis, PS_LIST_TAIL, PSWARP_ANALYSIS_GOODPIX, 0,
+                             "Number of good pixels", goodPixels);
+        }
+    }
+
+    if (goodPixels > 0) {
+	if (!pswarpTransformSources (output, input, config)) {
+	    psError(PS_ERR_UNKNOWN, false, "Unable to interpolate image.");
+	    return false;
+	}
+    }
+
+    // XXX should we not write anything out if there are no good pixels?
+    output->data_exists = true;
+    output->parent->data_exists = true;
+    output->parent->parent->data_exists = true;
+
+    psLogMsg ("pswarp", 3, "warping analysis: %f sec\n", psTimerMark ("warp"));
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpTransformReadout_Opt.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpTransformReadout_Opt.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpTransformReadout_Opt.c	(revision 22158)
@@ -0,0 +1,274 @@
+# include "pswarp.h"
+
+#define SOURCE_ARRAY_BUFFER 100         // Size to grow the array of sources at a time
+
+// NOTE: in this function, the coordinates are transformed from the OUTPUT to the INPUT
+bool pswarpTransformReadout_Opt(pmReadout *output, pmReadout *input, pmConfig *config)
+{
+    // XXX this implementation currently ignores the use of the region
+    psImage *region = NULL;
+
+    psTimerStart ("warp");
+
+    // Get warp parameters
+    bool mdok;
+    int nGridX = psMetadataLookupS32(NULL, config->arguments, "GRID.NX");
+    int nGridY = psMetadataLookupS32(NULL, config->arguments, "GRID.NY");
+    psImageInterpolateMode interpolationMode = psMetadataLookupS32(NULL, config->arguments,
+                                                                   "INTERPOLATION.MODE");
+    // load the recipe
+    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSWARP_RECIPE);
+    if (!recipe) {
+        psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSWARP_RECIPE);
+        return false;
+    }
+
+    // output mask bits
+    psMaskType maskIn   = psMetadataLookupU8(&mdok, recipe, "MASK.INPUT"); 
+    psMaskType maskPoor = pmConfigMaskGet("POOR.WARP", config); 
+    psMaskType maskBad  = pmConfigMaskGet("BAD.WARP", config); 
+    psAssert (mdok, "MASK.INPUT was not defined");
+
+    float poorFrac = psMetadataLookupF32(NULL, config->arguments, "POOR.FRAC"); // Flux fraction for "poor"
+
+    // we need to apply the offset to convert parent coordinates to child coordinates for
+    // psImagePixelInterpolate below
+    int inCol0 = input->image->col0;
+    int inRow0 = input->image->row0;
+    int outCol0 = output->image->col0;
+    int outRow0 = output->image->row0;
+
+    // we might want to do the rectangular regions outside of the selection independently
+    // psImageInit (output->image, NAN);
+
+    // find the output pixel range
+    int minX, minY, maxX, maxY;
+    pswarpMatchRange (&minX, &minY, &maxX, &maxY, input, output);
+
+    // pswarpMapGridFromImage builds a set of locally-linear maps which convert the
+    // output coordinates to input coordinates
+    pswarpMapGrid *grid = pswarpMapGridFromImage (input, output, nGridX, nGridY);
+
+    // XXX need to modify the grid based on this result and force the maxError < XXX
+    double maxError = pswarpMapGridMaxError (grid);
+    psLogMsg ("pswarp", 3, "maximum error using this grid sampling: %f\n", maxError);
+
+    int gridX, gridY, nextGridX, nextGridY;
+    pswarpMapGridSetGrid (grid, minX, minY, &gridX, &gridY);
+    nextGridY = pswarpMapGridNextGrid_Y (grid, gridY);
+    pswarpMap *map = grid->maps[gridX][gridY];
+
+    assert ((int)(minX - outCol0) >= 0);
+    assert ((int)(maxX - outCol0) <= output->image->numCols);
+    assert ((int)(minY - outRow0) >= 0);
+    assert ((int)(maxY - outRow0) <= output->image->numRows);
+
+    int gridXo = gridX;
+    int nextGridXo = pswarpMapGridNextGrid_X (grid, gridX);
+
+    psImage *inImage = input->image;    // Input image
+    psImage *inVar   = input->weight;   // Input weight map
+    psImage *inMask  = input->mask;     // Input mask
+
+    // Interpolation options
+    psImageInterpolateOptions *interp = psImageInterpolateOptionsAlloc(interpolationMode, inImage, 
+                                                                       inVar, inMask, maskIn, NAN, NAN,
+                                                                       maskBad, maskPoor, poorFrac);
+
+    psPlane *inPix = psPlaneAlloc();    // Coordinates on the input detector
+    psF32 **outImageData = output->image->data.F32; // Output image pixels
+    psF32 **outVarData = NULL;          // Output variance pixels
+    psMaskType **outMaskData = NULL;    // Output mask pixels
+    if (inVar) {
+        if (!output->weight) {
+            output->weight = psImageAlloc(output->image->numCols, output->image->numRows, PS_TYPE_F32);
+            psImageInit(output->weight, NAN);
+        }
+        outVarData = output->weight->data.F32;
+    }
+    if (inMask || maskPoor || maskBad) {
+        if (!output->mask) {
+            output->mask = psImageAlloc(output->image->numCols, output->image->numRows, PS_TYPE_MASK);
+            psImageInit(output->mask, maskBad);
+        }
+        outMaskData = output->mask->data.PS_TYPE_MASK_DATA;
+    }
+
+    // Iterate over the output image pixels (parent frame)
+    long goodPixels = 0;                // Number of input pixels landing on the output image
+    for (int y = minY; y < maxY; y++) {
+        if (y >= nextGridY) {
+            gridY ++;
+            nextGridY = pswarpMapGridNextGrid_Y (grid, gridY);
+            map = grid->maps[gridX][gridY];
+        }
+
+        gridX = gridXo;
+        nextGridX = nextGridXo;
+        map = grid->maps[gridX][gridY];
+        int yOut = y - outRow0;         // Position on image
+        for (int x = minX; x < maxX; x++) {
+            if (x >= nextGridX) {
+                gridX ++;
+                nextGridX = pswarpMapGridNextGrid_X (grid, gridX);
+                map = grid->maps[gridX][gridY];
+            }
+
+            // Only transform those pixels requested
+            if (region && region->data.U8[y][x]) continue;
+
+            // pswarpMapApply converts the output coordinate (x,y) to the input coordinate.
+            // both are in the parent frames of the input and output images.
+            pswarpMapApply (&inPix->x, &inPix->y, map, x + 0.5, y + 0.5);
+
+            if (inPix->x - inCol0 < 0) continue;
+            if (inPix->x - inCol0 >= inImage->numCols) continue;
+            if (inPix->y - inRow0 < 0) continue;
+            if (inPix->y - inRow0 >= inImage->numRows) continue;
+
+            goodPixels++;
+
+            // XXX include mask
+            // XXX apply scale and offset?
+            // psImagePixelInterpolate determines the value at pixel coordinate (x,y) in child coordinates
+            double imageValue, varValue;
+            psMaskType maskValue;
+            if (!psImageInterpolate(&imageValue, &varValue, &maskValue,
+                                    inPix->x - inCol0, inPix->y - inRow0, interp)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to interpolate image.");
+                psFree(interp);
+                psFree(inPix);
+                psFree(grid);
+                return false;
+            }
+            int xOut = x - outCol0;     // Position on image
+            outImageData[yOut][xOut] = imageValue;
+            if (inVar) {
+                outVarData[yOut][xOut] = varValue;
+            }
+            if (outMaskData) {
+                outMaskData[yOut][xOut] = maskValue;
+            }
+        }
+    }
+    psFree(interp);
+    psFree(inPix);
+    psFree(grid);
+
+    // Store the variance factor and number of good pixels
+    if (goodPixels > 0) {
+        float varFactor = psImageInterpolateVarianceFactor(inImage->numCols / 2.0 + inCol0,
+                                                           inImage->numRows / 2.0 + inRow0,
+                                                           interp); // Variance factor: large --> small scale
+        psMetadataItem *vfItem = psMetadataLookup(output->analysis, PSWARP_ANALYSIS_VARFACTOR);
+        if (vfItem) {
+            psMetadataItem *goodpixItem = psMetadataLookup(output->analysis, PSWARP_ANALYSIS_GOODPIX);
+            psAssert(goodpixItem, "It should be where we left it!");
+            psAssert(vfItem->type == PS_TYPE_F32 && goodpixItem->type == PS_TYPE_S64,
+                     "Should be the type we said.");
+
+            vfItem->data.F32 += varFactor * goodPixels;
+            goodpixItem->data.S64 += goodPixels;
+        } else {
+            psMetadataAddF32(output->analysis, PS_LIST_TAIL, PSWARP_ANALYSIS_VARFACTOR, 0,
+                             "Variance factor weighted by the good pixels", varFactor * goodPixels);
+            psMetadataAddS64(output->analysis, PS_LIST_TAIL, PSWARP_ANALYSIS_GOODPIX, 0,
+                             "Number of good pixels", goodPixels);
+        }
+    }
+
+    // Transform sources
+    psArray *inSources = psMetadataLookupPtr(&mdok, input->analysis, "PSPHOT.SOURCES"); // Sources in source
+    if (goodPixels > 0 && mdok && inSources) {
+        pswarpMapGrid *sourceGrid = pswarpMapGridFromImage(output, input, nGridX, nGridY); // Grid for sources
+
+        psArray *outSources = psMemIncrRefCounter(psMetadataLookupPtr(&mdok, output->analysis,
+                                                                      "PSPHOT.SOURCES")); // Target sources
+        if (!outSources) {
+            outSources = psArrayAllocEmpty(SOURCE_ARRAY_BUFFER);
+            psMetadataAddPtr(output->analysis, PS_LIST_TAIL, "PSPHOT.SOURCES", PS_DATA_ARRAY,
+                             "Warped sources", outSources);
+        }
+
+        for (int i = 0; i < inSources->n; i++) {
+            pmSource *source = inSources->data[i]; // Source of interest
+            pmModel *model = source->modelPSF; // Model for this source
+            float xIn, yIn;             // Coordinates of source
+            xIn = model->params->data.F32[PM_PAR_XPOS] - inCol0;
+            yIn = model->params->data.F32[PM_PAR_YPOS] - inRow0;
+            int xGrid, yGrid;           // Grid coordinates for local map
+            if (!pswarpMapGridSetGrid(sourceGrid, xIn + 0.5, yIn + 0.5, &xGrid, &yGrid)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to get grid coordinates for source at %f,%f\n",
+                        xIn, yIn);
+                psFree(outSources);
+                psFree(sourceGrid);
+                return false;
+            }
+            if (xGrid < 0 || xGrid >= sourceGrid->nXpts || yGrid < 0 || yGrid >= sourceGrid->nYpts) {
+                // It's not even on the grid
+                continue;
+            }
+
+            pswarpMap *map = sourceGrid->maps[xGrid][yGrid]; // Locally linear transformation
+            double xOut, yOut;          // Output coordinates
+            if (!pswarpMapApply(&xOut, &yOut, map, xIn + 0.5, yIn + 0.5)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to transform coordinates for source at %f,%f\n",
+                        xIn, yIn);
+                psFree(outSources);
+                psFree(sourceGrid);
+                return false;
+            }
+            xOut += outCol0 - 0.5;
+            yOut += outRow0 - 0.5;
+            if (xOut < minX || xOut > maxX || yOut < minY || yOut > maxY) {
+                // It's not in the output image
+                continue;
+            }
+
+            // Generate the new source in the output frame
+            pmSource *new = pmSourceAlloc(); // New source
+            new->peak = pmPeakAlloc(xOut, yOut, source->peak->flux, PM_PEAK_LONE);
+            new->peak->flux = source->peak->flux;
+            new->type = PM_SOURCE_TYPE_STAR;
+            new->psfMag = source->psfMag;
+            new->errMag = source->errMag;
+            new->sky = source->sky;
+            new->skyErr = source->skyErr;
+            new->pixWeight = source->pixWeight;
+            new->modelPSF = pmModelAlloc(source->modelPSF->type);
+
+#if 0
+            // XXX Note that this will not set the correct axes
+            pmPSF_AxesToModel(new->modelPSF->params->data.F32,
+                              pmPSF_ModelToAxes(source->modelPSF->params->data.F32, 20.0));
+#endif
+
+            // Propagate the position erorrs
+            float dxIn, dyIn;           // Errors in input coordinates
+            dxIn = model->dparams->data.F32[PM_PAR_XPOS];
+            dyIn = model->dparams->data.F32[PM_PAR_YPOS];
+
+            float dxOut, dyOut;         // Errors in output coordinates
+            dxOut = sqrt(PS_SQR(map->Xx * dxIn) + PS_SQR(map->Xy * dyIn));
+            dyOut = sqrt(PS_SQR(map->Yx * dxIn) + PS_SQR(map->Yy * dyIn));
+
+            new->modelPSF->params->data.F32[PM_PAR_XPOS] = xOut;
+            new->modelPSF->params->data.F32[PM_PAR_YPOS] = yOut;
+            new->modelPSF->dparams->data.F32[PM_PAR_XPOS] = dxOut;
+            new->modelPSF->dparams->data.F32[PM_PAR_YPOS] = dyOut;
+
+            psArrayAdd(outSources, SOURCE_ARRAY_BUFFER, new);
+            psFree(new);                // Drop reference
+        }
+        psFree(sourceGrid);
+        psFree(outSources);             // Drop reference
+    }
+
+    output->data_exists = true;
+    output->parent->data_exists = true;
+    output->parent->parent->data_exists = true;
+
+    psLogMsg ("pswarp", 3, "warping analysis: %f sec\n", psTimerMark ("warp"));
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpTransformReadout_Threaded.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpTransformReadout_Threaded.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpTransformReadout_Threaded.c	(revision 22158)
@@ -0,0 +1,246 @@
+# include "pswarp.h"
+
+# define THREADED 1
+# define SOURCE_ARRAY_BUFFER 100         // Size to grow the array of sources at a time
+
+// NOTE: in this function, the coordinates are transformed from the OUTPUT to the INPUT
+bool pswarpTransformReadout_Threaded(pmReadout *output, pmReadout *input, pmConfig *config)
+{
+    // XXX this implementation currently ignores the use of the region
+    psImage *region = NULL;
+
+    psTimerStart ("warp");
+
+    // Get warp parameters
+    bool mdok;
+    int nGridX = psMetadataLookupS32(NULL, config->arguments, "GRID.NX");
+    int nGridY = psMetadataLookupS32(NULL, config->arguments, "GRID.NY");
+    psImageInterpolateMode interpolationMode = psMetadataLookupS32(NULL, config->arguments, "INTERPOLATION.MODE");
+
+    // load the recipe
+    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSWARP_RECIPE);
+    psAssert (recipe, "missing recipe %s", PSWARP_RECIPE);
+
+    // output mask bits
+    psMaskType maskIn   = psMetadataLookupU8(&mdok, recipe, "MASK.INPUT"); 
+    psMaskType maskPoor = pmConfigMaskGet("POOR.WARP", config); 
+    psMaskType maskBad  = pmConfigMaskGet("BAD.WARP", config); 
+    psAssert (mdok, "MASK.INPUT was not defined");
+
+    // Flux fraction for "poor"
+    float poorFrac = psMetadataLookupF32(NULL, config->arguments, "POOR.FRAC"); 
+
+    // find the output pixel range
+    int minX, minY, maxX, maxY;
+    pswarpMatchRange (&minX, &minY, &maxX, &maxY, input, output);
+
+    // pswarpMapGridFromImage builds a set of locally-linear maps which convert the
+    // output coordinates to input coordinates
+    pswarpMapGrid *grid = pswarpMapGridFromImage (input, output, nGridX, nGridY);
+
+    // XXX need to modify the grid based on this result and force the maxError < XXX
+    double maxError = pswarpMapGridMaxError (grid);
+    psLogMsg ("pswarp", 3, "maximum error using this grid sampling: %f\n", maxError);
+
+    int gridX, gridY;
+    pswarpMapGridSetGrid (grid, minX, minY, &gridX, &gridY);
+# if (0)
+    // XXX these asserts probably belong in the function (don't have outCol0,Row0 anyway)
+    assert ((int)(minX - outCol0) >= 0);
+    assert ((int)(maxX - outCol0) <= output->image->numCols);
+    assert ((int)(minY - outRow0) >= 0);
+    assert ((int)(maxY - outRow0) <= output->image->numRows);
+# endif
+
+    psImage *inImage = input->image;    // Input image
+    psImage *inVar   = input->weight;   // Input weight map
+    psImage *inMask  = input->mask;     // Input mask
+
+    // Interpolation options
+    psImageInterpolateOptions *interp = psImageInterpolateOptionsAlloc(interpolationMode, inImage, 
+                                                                       inVar, inMask, maskIn, NAN, NAN,
+                                                                       maskBad, maskPoor, poorFrac);
+
+    if (inVar && !output->weight) {
+	output->weight = psImageAlloc(output->image->numCols, output->image->numRows, PS_TYPE_F32);
+	psImageInit(output->weight, NAN);
+    }
+    if ((inMask || maskPoor || maskBad) && !output->mask) {
+	output->mask = psImageAlloc(output->image->numCols, output->image->numRows, PS_TYPE_MASK);
+	psImageInit(output->mask, maskBad);
+    }
+
+    // total number of good pixels across all tiles (summed below)
+    int goodPixels = 0;
+
+    // create jobs and supply them to the threads
+    for (gridY = 0; gridY < nGridX; gridY++) {
+	for (gridX = 0; gridX < nGridY; gridX++) {
+
+	    pswarpTransformTileArgs *args = pswarpTransformTileArgsAlloc();
+
+	    // these items are just views to the data; they are not freed with args
+	    args->input = input;
+	    args->output = output;
+	    args->grid = grid;
+	    args->interp = interp;
+	    args->region = region;
+
+	    args->gridX = gridX;
+	    args->gridY = gridY;
+	    args->goodPixels = 0;
+
+# if (THREADED)	    
+	    // allocate a job
+	    psThreadJob *job = psThreadJobAlloc ("PSWARP_TRANSFORM_TILE", 0);
+
+	    // construct the arguments for this job
+	    // job is pswarpTransformTile (gridX, gridY);
+	    psArrayAdd (job->args, 1, args);
+	    psThreadJobAddPending (job);
+# else
+	    pswarpTransformTile (args);
+	    goodPixels += args->goodPixels;
+# endif
+	    psFree (args);
+	}
+    }
+
+# if (THREADED)	    
+    // wait here for the threaded jobs to finish
+    if (!psThreadPoolWait ()) {
+	psError(PS_ERR_UNKNOWN, false, "Unable to interpolate image.");
+	return false;
+    }
+    fprintf (stderr, "success for threaded jobs\n");
+
+    // each job records its own goodPixel values; sum them here
+    // we have only supplied one type of job, so we can assume the types here
+    psThreadJob *job = NULL;
+    while ((job = psThreadJobGetDone()) != NULL) {
+	pswarpTransformTileArgs *args = job->args->data[0];
+	goodPixels += args->goodPixels;
+	psFree (job);
+    }
+# endif
+    psFree(interp);
+    psFree(grid);
+
+
+    // Store the variance factor and number of good pixels
+    if (goodPixels > 0) {
+        float varFactor = psImageInterpolateVarianceFactor(inImage->numCols / 2.0 + inImage->col0,
+                                                           inImage->numRows / 2.0 + inImage->row0,
+                                                           interp); // Variance factor: large --> small scale
+        psMetadataItem *vfItem = psMetadataLookup(output->analysis, PSWARP_ANALYSIS_VARFACTOR);
+        if (vfItem) {
+            psMetadataItem *goodpixItem = psMetadataLookup(output->analysis, PSWARP_ANALYSIS_GOODPIX);
+            psAssert(goodpixItem, "It should be where we left it!");
+            psAssert(vfItem->type == PS_TYPE_F32 && goodpixItem->type == PS_TYPE_S64,
+                     "Should be the type we said.");
+
+            vfItem->data.F32 += varFactor * goodPixels;
+            goodpixItem->data.S64 += goodPixels;
+        } else {
+            psMetadataAddF32(output->analysis, PS_LIST_TAIL, PSWARP_ANALYSIS_VARFACTOR, 0,
+                             "Variance factor weighted by the good pixels", varFactor * goodPixels);
+            psMetadataAddS64(output->analysis, PS_LIST_TAIL, PSWARP_ANALYSIS_GOODPIX, 0,
+                             "Number of good pixels", goodPixels);
+        }
+    }
+
+    // Transform sources
+    psArray *inSources = psMetadataLookupPtr(&mdok, input->analysis, "PSPHOT.SOURCES"); // Sources in source
+    if (goodPixels > 0 && mdok && inSources) {
+        pswarpMapGrid *sourceGrid = pswarpMapGridFromImage(output, input, nGridX, nGridY); // Grid for sources
+
+        psArray *outSources = psMemIncrRefCounter(psMetadataLookupPtr(&mdok, output->analysis,
+                                                                      "PSPHOT.SOURCES")); // Target sources
+        if (!outSources) {
+            outSources = psArrayAllocEmpty(SOURCE_ARRAY_BUFFER);
+            psMetadataAddPtr(output->analysis, PS_LIST_TAIL, "PSPHOT.SOURCES", PS_DATA_ARRAY,
+                             "Warped sources", outSources);
+        }
+
+        for (int i = 0; i < inSources->n; i++) {
+            pmSource *source = inSources->data[i]; // Source of interest
+            pmModel *model = source->modelPSF; // Model for this source
+            float xIn, yIn;             // Coordinates of source
+            xIn = model->params->data.F32[PM_PAR_XPOS] - inImage->col0;
+            yIn = model->params->data.F32[PM_PAR_YPOS] - inImage->row0;
+            int xGrid, yGrid;           // Grid coordinates for local map
+            if (!pswarpMapGridSetGrid(sourceGrid, xIn + 0.5, yIn + 0.5, &xGrid, &yGrid)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to get grid coordinates for source at %f,%f\n",
+                        xIn, yIn);
+                psFree(outSources);
+                psFree(sourceGrid);
+                return false;
+            }
+            if (xGrid < 0 || xGrid >= sourceGrid->nXpts || yGrid < 0 || yGrid >= sourceGrid->nYpts) {
+                // It's not even on the grid
+                continue;
+            }
+
+            pswarpMap *map = sourceGrid->maps[xGrid][yGrid]; // Locally linear transformation
+            double xOut, yOut;          // Output coordinates
+            if (!pswarpMapApply(&xOut, &yOut, map, xIn + 0.5, yIn + 0.5)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to transform coordinates for source at %f,%f\n",
+                        xIn, yIn);
+                psFree(outSources);
+                psFree(sourceGrid);
+                return false;
+            }
+            xOut += output->image->col0 - 0.5;
+            yOut += output->image->row0 - 0.5;
+            if (xOut < minX || xOut > maxX || yOut < minY || yOut > maxY) {
+                // It's not in the output image
+                continue;
+            }
+
+            // Generate the new source in the output frame
+            pmSource *new = pmSourceAlloc(); // New source
+            new->peak = pmPeakAlloc(xOut, yOut, source->peak->flux, PM_PEAK_LONE);
+            new->peak->flux = source->peak->flux;
+            new->type = PM_SOURCE_TYPE_STAR;
+            new->psfMag = source->psfMag;
+            new->errMag = source->errMag;
+            new->sky = source->sky;
+            new->skyErr = source->skyErr;
+            new->pixWeight = source->pixWeight;
+            new->modelPSF = pmModelAlloc(source->modelPSF->type);
+
+#if 0
+            // XXX Note that this will not set the correct axes
+            pmPSF_AxesToModel(new->modelPSF->params->data.F32,
+                              pmPSF_ModelToAxes(source->modelPSF->params->data.F32, 20.0));
+#endif
+
+            // Propagate the position erorrs
+            float dxIn, dyIn;           // Errors in input coordinates
+            dxIn = model->dparams->data.F32[PM_PAR_XPOS];
+            dyIn = model->dparams->data.F32[PM_PAR_YPOS];
+
+            float dxOut, dyOut;         // Errors in output coordinates
+            dxOut = sqrt(PS_SQR(map->Xx * dxIn) + PS_SQR(map->Xy * dyIn));
+            dyOut = sqrt(PS_SQR(map->Yx * dxIn) + PS_SQR(map->Yy * dyIn));
+
+            new->modelPSF->params->data.F32[PM_PAR_XPOS] = xOut;
+            new->modelPSF->params->data.F32[PM_PAR_YPOS] = yOut;
+            new->modelPSF->dparams->data.F32[PM_PAR_XPOS] = dxOut;
+            new->modelPSF->dparams->data.F32[PM_PAR_YPOS] = dyOut;
+
+            psArrayAdd(outSources, SOURCE_ARRAY_BUFFER, new);
+            psFree(new);                // Drop reference
+        }
+        psFree(sourceGrid);
+        psFree(outSources);             // Drop reference
+    }
+
+    output->data_exists = true;
+    output->parent->data_exists = true;
+    output->parent->parent->data_exists = true;
+
+    psLogMsg ("pswarp", 3, "warping analysis: %f sec\n", psTimerMark ("warp"));
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpTransformReadout_Unthreaded.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpTransformReadout_Unthreaded.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpTransformReadout_Unthreaded.c	(revision 22158)
@@ -0,0 +1,216 @@
+# include "pswarp.h"
+
+#define SOURCE_ARRAY_BUFFER 100         // Size to grow the array of sources at a time
+
+// NOTE: in this function, the coordinates are transformed from the OUTPUT to the INPUT
+bool pswarpTransformReadout_Unthreaded(pmReadout *output, pmReadout *input, pmConfig *config)
+{
+    // XXX this implementation currently ignores the use of the region
+    psImage *region = NULL;
+
+    psTimerStart ("warp");
+
+    // Get warp parameters
+    bool mdok;
+    int nGridX = psMetadataLookupS32(NULL, config->arguments, "GRID.NX");
+    int nGridY = psMetadataLookupS32(NULL, config->arguments, "GRID.NY");
+    psImageInterpolateMode interpolationMode = psMetadataLookupS32(NULL, config->arguments, "INTERPOLATION.MODE");
+
+    // load the recipe
+    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSWARP_RECIPE);
+    psAssert (recipe, "missing recipe %s", PSWARP_RECIPE);
+
+    // output mask bits
+    psMaskType maskIn   = psMetadataLookupU8(&mdok, recipe, "MASK.INPUT"); 
+    psMaskType maskPoor = pmConfigMaskGet("POOR.WARP", config); 
+    psMaskType maskBad  = pmConfigMaskGet("BAD.WARP", config); 
+    psAssert (mdok, "MASK.INPUT was not defined");
+
+    // Flux fraction for "poor"
+    float poorFrac = psMetadataLookupF32(NULL, config->arguments, "POOR.FRAC"); 
+
+    // find the output pixel range
+    int minX, minY, maxX, maxY;
+    pswarpMatchRange (&minX, &minY, &maxX, &maxY, input, output);
+
+    // pswarpMapGridFromImage builds a set of locally-linear maps which convert the
+    // output coordinates to input coordinates
+    pswarpMapGrid *grid = pswarpMapGridFromImage (input, output, nGridX, nGridY);
+
+    // XXX need to modify the grid based on this result and force the maxError < XXX
+    double maxError = pswarpMapGridMaxError (grid);
+    psLogMsg ("pswarp", 3, "maximum error using this grid sampling: %f\n", maxError);
+
+    int gridX, gridY;
+    pswarpMapGridSetGrid (grid, minX, minY, &gridX, &gridY);
+# if (0)
+    // XXX these asserts probably belong in the function (don't have outCol0,Row0 anyway)
+    assert ((int)(minX - outCol0) >= 0);
+    assert ((int)(maxX - outCol0) <= output->image->numCols);
+    assert ((int)(minY - outRow0) >= 0);
+    assert ((int)(maxY - outRow0) <= output->image->numRows);
+# endif
+
+    psImage *inImage = input->image;    // Input image
+    psImage *inVar   = input->weight;   // Input weight map
+    psImage *inMask  = input->mask;     // Input mask
+
+    // Interpolation options
+    psImageInterpolateOptions *interp = psImageInterpolateOptionsAlloc(interpolationMode, inImage, 
+                                                                       inVar, inMask, maskIn, NAN, NAN,
+                                                                       maskBad, maskPoor, poorFrac);
+
+    if (inVar && !output->weight) {
+	output->weight = psImageAlloc(output->image->numCols, output->image->numRows, PS_TYPE_F32);
+	psImageInit(output->weight, NAN);
+    }
+    if ((inMask || maskPoor || maskBad) && !output->mask) {
+	output->mask = psImageAlloc(output->image->numCols, output->image->numRows, PS_TYPE_MASK);
+	psImageInit(output->mask, maskBad);
+    }
+
+    // total number of good pixels across all tiles (summed below)
+    int goodPixels = 0;
+
+    // (almost) the same structure as the threaded version
+    for (gridY = 0; gridY < nGridX; gridY++) {
+	for (gridX = 0; gridX < nGridY; gridX++) {
+
+	    pswarpTransformTileArgs *args = pswarpTransformTileArgsAlloc();
+
+	    // these items are just views to the data; they are not freed with args
+	    args->input = input;
+	    args->output = output;
+	    args->grid = grid;
+	    args->interp = interp;
+	    args->region = region;
+
+	    args->gridX = gridX;
+	    args->gridY = gridY;
+	    args->goodPixels = 0;
+
+	    pswarpTransformTile (args);
+	    goodPixels += args->goodPixels;
+	    psFree (args);
+	}
+    }
+    psFree(interp);
+    psFree(grid);
+
+    // Store the variance factor and number of good pixels
+    if (goodPixels > 0) {
+        float varFactor = psImageInterpolateVarianceFactor(inImage->numCols / 2.0 + inImage->col0,
+                                                           inImage->numRows / 2.0 + inImage->row0,
+                                                           interp); // Variance factor: large --> small scale
+        psMetadataItem *vfItem = psMetadataLookup(output->analysis, PSWARP_ANALYSIS_VARFACTOR);
+        if (vfItem) {
+            psMetadataItem *goodpixItem = psMetadataLookup(output->analysis, PSWARP_ANALYSIS_GOODPIX);
+            psAssert(goodpixItem, "It should be where we left it!");
+            psAssert(vfItem->type == PS_TYPE_F32 && goodpixItem->type == PS_TYPE_S64,
+                     "Should be the type we said.");
+
+            vfItem->data.F32 += varFactor * goodPixels;
+            goodpixItem->data.S64 += goodPixels;
+        } else {
+            psMetadataAddF32(output->analysis, PS_LIST_TAIL, PSWARP_ANALYSIS_VARFACTOR, 0,
+                             "Variance factor weighted by the good pixels", varFactor * goodPixels);
+            psMetadataAddS64(output->analysis, PS_LIST_TAIL, PSWARP_ANALYSIS_GOODPIX, 0,
+                             "Number of good pixels", goodPixels);
+        }
+    }
+
+    // Transform sources
+    psArray *inSources = psMetadataLookupPtr(&mdok, input->analysis, "PSPHOT.SOURCES"); // Sources in source
+    if (goodPixels > 0 && mdok && inSources) {
+        pswarpMapGrid *sourceGrid = pswarpMapGridFromImage(output, input, nGridX, nGridY); // Grid for sources
+
+        psArray *outSources = psMemIncrRefCounter(psMetadataLookupPtr(&mdok, output->analysis,
+                                                                      "PSPHOT.SOURCES")); // Target sources
+        if (!outSources) {
+            outSources = psArrayAllocEmpty(SOURCE_ARRAY_BUFFER);
+            psMetadataAddPtr(output->analysis, PS_LIST_TAIL, "PSPHOT.SOURCES", PS_DATA_ARRAY,
+                             "Warped sources", outSources);
+        }
+
+        for (int i = 0; i < inSources->n; i++) {
+            pmSource *source = inSources->data[i]; // Source of interest
+            pmModel *model = source->modelPSF; // Model for this source
+            float xIn, yIn;             // Coordinates of source
+            xIn = model->params->data.F32[PM_PAR_XPOS] - inImage->col0;
+            yIn = model->params->data.F32[PM_PAR_YPOS] - inImage->row0;
+            int xGrid, yGrid;           // Grid coordinates for local map
+            if (!pswarpMapGridSetGrid(sourceGrid, xIn + 0.5, yIn + 0.5, &xGrid, &yGrid)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to get grid coordinates for source at %f,%f\n",
+                        xIn, yIn);
+                psFree(outSources);
+                psFree(sourceGrid);
+                return false;
+            }
+            if (xGrid < 0 || xGrid >= sourceGrid->nXpts || yGrid < 0 || yGrid >= sourceGrid->nYpts) {
+                // It's not even on the grid
+                continue;
+            }
+
+            pswarpMap *map = sourceGrid->maps[xGrid][yGrid]; // Locally linear transformation
+            double xOut, yOut;          // Output coordinates
+            if (!pswarpMapApply(&xOut, &yOut, map, xIn + 0.5, yIn + 0.5)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to transform coordinates for source at %f,%f\n",
+                        xIn, yIn);
+                psFree(outSources);
+                psFree(sourceGrid);
+                return false;
+            }
+            xOut += output->image->col0 - 0.5;
+            yOut += output->image->row0 - 0.5;
+            if (xOut < minX || xOut > maxX || yOut < minY || yOut > maxY) {
+                // It's not in the output image
+                continue;
+            }
+
+            // Generate the new source in the output frame
+            pmSource *new = pmSourceAlloc(); // New source
+            new->peak = pmPeakAlloc(xOut, yOut, source->peak->flux, PM_PEAK_LONE);
+            new->peak->flux = source->peak->flux;
+            new->type = PM_SOURCE_TYPE_STAR;
+            new->psfMag = source->psfMag;
+            new->errMag = source->errMag;
+            new->sky = source->sky;
+            new->skyErr = source->skyErr;
+            new->pixWeight = source->pixWeight;
+            new->modelPSF = pmModelAlloc(source->modelPSF->type);
+
+#if 0
+            // XXX Note that this will not set the correct axes
+            pmPSF_AxesToModel(new->modelPSF->params->data.F32,
+                              pmPSF_ModelToAxes(source->modelPSF->params->data.F32, 20.0));
+#endif
+
+            // Propagate the position erorrs
+            float dxIn, dyIn;           // Errors in input coordinates
+            dxIn = model->dparams->data.F32[PM_PAR_XPOS];
+            dyIn = model->dparams->data.F32[PM_PAR_YPOS];
+
+            float dxOut, dyOut;         // Errors in output coordinates
+            dxOut = sqrt(PS_SQR(map->Xx * dxIn) + PS_SQR(map->Xy * dyIn));
+            dyOut = sqrt(PS_SQR(map->Yx * dxIn) + PS_SQR(map->Yy * dyIn));
+
+            new->modelPSF->params->data.F32[PM_PAR_XPOS] = xOut;
+            new->modelPSF->params->data.F32[PM_PAR_YPOS] = yOut;
+            new->modelPSF->dparams->data.F32[PM_PAR_XPOS] = dxOut;
+            new->modelPSF->dparams->data.F32[PM_PAR_YPOS] = dyOut;
+
+            psArrayAdd(outSources, SOURCE_ARRAY_BUFFER, new);
+            psFree(new);                // Drop reference
+        }
+        psFree(sourceGrid);
+        psFree(outSources);             // Drop reference
+    }
+
+    output->data_exists = true;
+    output->parent->data_exists = true;
+    output->parent->parent->data_exists = true;
+
+    psLogMsg ("pswarp", 3, "warping analysis: %f sec\n", psTimerMark ("warp"));
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpTransformSources.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpTransformSources.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpTransformSources.c	(revision 22158)
@@ -0,0 +1,110 @@
+# include "pswarp.h"
+
+# define SOURCE_ARRAY_BUFFER 100         // Size to grow the array of sources at a time
+
+// NOTE: in this function, the coordinates are transformed from the OUTPUT to the INPUT
+bool pswarpTransformSources(pmReadout *output, pmReadout *input, pmConfig *config)
+{
+
+    // find the output pixel range
+    int minX, minY, maxX, maxY;
+    pswarpMatchRange (&minX, &minY, &maxX, &maxY, input, output);
+
+    // Get warp parameters
+    bool mdok;
+    int nGridX = psMetadataLookupS32(NULL, config->arguments, "GRID.NX");
+    int nGridY = psMetadataLookupS32(NULL, config->arguments, "GRID.NY");
+
+    // Transform sources
+    psArray *inSources = psMetadataLookupPtr(&mdok, input->analysis, "PSPHOT.SOURCES"); // Sources in source
+    if (!inSources) return true;
+
+    pswarpMapGrid *sourceGrid = pswarpMapGridFromImage(output, input, nGridX, nGridY); // Grid for sources
+
+    psArray *outSources = psMemIncrRefCounter(psMetadataLookupPtr(&mdok, output->analysis, "PSPHOT.SOURCES")); // Target sources
+    if (!outSources) {
+	outSources = psArrayAllocEmpty(SOURCE_ARRAY_BUFFER);
+	psMetadataAddPtr(output->analysis, PS_LIST_TAIL, "PSPHOT.SOURCES", PS_DATA_ARRAY,
+			 "Warped sources", outSources);
+    }
+
+    // XXX it is probably not necessary to use the locally linear transformations we should
+    // be using the full astrometry: since there are 100 - 1000 fewer sources than pixels,
+    // this does not cost us so much time.
+    for (int i = 0; i < inSources->n; i++) {
+	pmSource *source = inSources->data[i]; // Source of interest
+	pmModel *model = source->modelPSF; // Model for this source
+	float xIn, yIn;             // Coordinates of source
+	xIn = model->params->data.F32[PM_PAR_XPOS] - input->image->col0;
+	yIn = model->params->data.F32[PM_PAR_YPOS] - input->image->row0;
+
+	int xGrid, yGrid;           // Grid coordinates for local map
+	if (!pswarpMapGridSetGrid(sourceGrid, xIn + 0.5, yIn + 0.5, &xGrid, &yGrid)) {
+	    psError(PS_ERR_UNKNOWN, false, "Unable to get grid coordinates for source at %f,%f\n",
+		    xIn, yIn);
+	    psFree(outSources);
+	    psFree(sourceGrid);
+	    return false;
+	}
+	if (xGrid < 0 || xGrid >= sourceGrid->nXpts || yGrid < 0 || yGrid >= sourceGrid->nYpts) {
+	    // It's not even on the grid
+	    // XXX how can this happen?
+	    continue;
+	}
+
+	pswarpMap *map = sourceGrid->maps[xGrid][yGrid]; // Locally linear transformation
+	double xOut, yOut;          // Output coordinates
+	if (!pswarpMapApply(&xOut, &yOut, map, xIn + 0.5, yIn + 0.5)) {
+	    psError(PS_ERR_UNKNOWN, false, "Unable to transform coordinates for source at %f,%f\n",
+		    xIn, yIn);
+	    psFree(outSources);
+	    psFree(sourceGrid);
+	    return false;
+	}
+	xOut += output->image->col0 - 0.5;
+	yOut += output->image->row0 - 0.5;
+	if (xOut < minX || xOut > maxX || yOut < minY || yOut > maxY) {
+	    // It's not in the output image
+	    continue;
+	}
+
+	// Generate the new source in the output frame
+	pmSource *new = pmSourceAlloc(); // New source
+	new->peak = pmPeakAlloc(xOut, yOut, source->peak->flux, PM_PEAK_LONE);
+	new->peak->flux = source->peak->flux;
+	new->type = PM_SOURCE_TYPE_STAR;
+	new->psfMag = source->psfMag;
+	new->errMag = source->errMag;
+	new->sky = source->sky;
+	new->skyErr = source->skyErr;
+	new->pixWeight = source->pixWeight;
+	new->modelPSF = pmModelAlloc(source->modelPSF->type);
+
+#if 0
+	// XXX Note that this will not set the correct axes
+	pmPSF_AxesToModel(new->modelPSF->params->data.F32,
+			  pmPSF_ModelToAxes(source->modelPSF->params->data.F32, 20.0));
+#endif
+
+	// Propagate the position erorrs
+	float dxIn, dyIn;           // Errors in input coordinates
+	dxIn = model->dparams->data.F32[PM_PAR_XPOS];
+	dyIn = model->dparams->data.F32[PM_PAR_YPOS];
+
+	float dxOut, dyOut;         // Errors in output coordinates
+	dxOut = sqrt(PS_SQR(map->Xx * dxIn) + PS_SQR(map->Xy * dyIn));
+	dyOut = sqrt(PS_SQR(map->Yx * dxIn) + PS_SQR(map->Yy * dyIn));
+
+	new->modelPSF->params->data.F32[PM_PAR_XPOS] = xOut;
+	new->modelPSF->params->data.F32[PM_PAR_YPOS] = yOut;
+	new->modelPSF->dparams->data.F32[PM_PAR_XPOS] = dxOut;
+	new->modelPSF->dparams->data.F32[PM_PAR_YPOS] = dyOut;
+
+	psArrayAdd(outSources, SOURCE_ARRAY_BUFFER, new);
+	psFree(new);                // Drop reference
+    }
+    psFree(sourceGrid);
+    psFree(outSources);             // Drop reference
+    return true;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpTransformTile.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpTransformTile.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpTransformTile.c	(revision 22158)
@@ -0,0 +1,103 @@
+# include "pswarp.h"
+
+void pswarpTransformTileArgsFree (pswarpTransformTileArgs *args) {
+    if (!args) return;
+    return;
+}
+
+pswarpTransformTileArgs *pswarpTransformTileArgsAlloc() {
+
+    pswarpTransformTileArgs *args = (pswarpTransformTileArgs *)psAlloc(sizeof(pswarpTransformTileArgs));
+    psMemSetDeallocator(args, (psFreeFunc)pswarpTransformTileArgsFree);
+
+    args->input = NULL;
+    args->output = NULL;
+    args->grid = NULL;
+    args->interp = NULL;
+    args->region = NULL;
+
+    args->gridX = 0;
+    args->gridY = 0;
+
+    args->goodPixels = 0;
+
+    return args;
+}
+
+bool pswarpTransformTile (pswarpTransformTileArgs *args) {
+
+    // int inCol0 = args->input->image->col0;
+    // int inRow0 = args->input->image->row0;
+    int inNcol = args->input->image->numCols;
+    int inNrow = args->input->image->numRows;
+
+    int outCol0 = args->output->image->col0;
+    int outRow0 = args->output->image->row0;
+    // int outNcol = args->output->image->numCols;
+    // int outNrow = args->output->image->numRows;
+
+    // get the coordinate range for this grid tile
+    psPlane minPt, maxPt;
+    pswarpMapGridCoordRange (args->grid, args->gridX, args->gridY, &minPt, &maxPt);
+
+    psF32 **outImageData     = (args->output->image)  ? args->output->image->data.F32  : NULL;
+    psF32 **outVarData       = (args->output->weight) ? args->output->weight->data.F32 : NULL;
+    psMaskType **outMaskData = (args->output->mask)   ? args->output->mask->data.U8    : NULL;
+
+    pswarpMap *map = args->grid->maps[args->gridX][args->gridY];
+
+    psImage *region = args->region;
+
+    double xInRaw, yInRaw;
+
+    // output values for this pixel
+    double imageValue;
+    double varValue;
+    psMaskType maskValue;
+
+    // Iterate over the output image pixels (parent frame)
+    long goodPixels = 0;                // Number of input pixels landing on the output image
+    for (int y = minPt.y; y < maxPt.y; y++) {
+        for (int x = minPt.x; x < maxPt.x; x++) {
+
+            // Only transform those pixels requested
+            if (region && region->data.U8[y][x]) continue;
+
+            // pswarpMapApply converts the output coordinate (x,y) to the input coordinate.
+            // both are in the parent frames of the input and output images.
+            pswarpMapApply (&xInRaw, &yInRaw, map, x + 0.5, y + 0.5);
+
+            double xIn = xInRaw - outCol0;	// Position on input image
+	    double yIn = yInRaw - outRow0;	// Position on input image
+
+            if (xIn < 0) continue;
+            if (yIn >= inNcol) continue;
+            if (yIn < 0) continue;
+            if (yIn >= inNrow) continue;
+
+            goodPixels++;
+
+            // psImagePixelInterpolate determines the value at pixel coordinate (x,y) in child coordinates
+            if (!psImageInterpolate(&imageValue, &varValue, &maskValue, xIn, yIn, args->interp)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to interpolate image.");
+                return false;
+            }
+
+            int xOut = x - outCol0;     // Position on output image
+	    int yOut = y - outRow0;	// Position on output image
+
+	    // not all images need be transformed
+	    if (outImageData) {
+		outImageData[yOut][xOut] = imageValue;
+	    }
+            if (outVarData) {
+                outVarData[yOut][xOut] = varValue;
+            }
+            if (outMaskData) {
+                outMaskData[yOut][xOut] = maskValue;
+            }
+        }
+    }
+    args->goodPixels = goodPixels;
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpVersion.c
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpVersion.c	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/src/pswarpVersion.c	(revision 22158)
@@ -0,0 +1,27 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include "pswarp.h"
+
+static const char *cvsTag = "$Name: not supported by cvs2svn $";// CVS tag name
+
+psString pswarpVersion(void)
+{
+    psString version = NULL;            // Version, to return
+    psStringAppend(&version, "%s-%s",PACKAGE_NAME,PACKAGE_VERSION);
+    return version;
+}
+
+psString pswarpVersionLong(void)
+{
+    psString version = pswarpVersion(); // Version, to return
+    psString tag = psStringStripCVS(cvsTag, "Name"); // CVS tag
+    psStringAppend(&version, " (cvs tag %s) %s, %s", tag, __DATE__, __TIME__);
+    psFree(tag);
+    return version;
+}
+
Index: /branches/eam_branches/eam_branch_20080719/pswarp/test/.cvsignore
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/test/.cvsignore	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/test/.cvsignore	(revision 22158)
@@ -0,0 +1,1 @@
+*
Index: /branches/eam_branches/eam_branch_20080719/pswarp/test/simple.image.op
===================================================================
--- /branches/eam_branches/eam_branch_20080719/pswarp/test/simple.image.op	(revision 22158)
+++ /branches/eam_branches/eam_branch_20080719/pswarp/test/simple.image.op	(revision 22158)
@@ -0,0 +1,56 @@
+
+$NX = 2048
+$NY = 2048
+
+macro go
+  mkref
+  mksrc
+  exec pswarp -file src.fits out ref.fits
+  exec rm -f src.fits out.fits ref.fits
+end
+
+macro mkref
+  mcreate ref $NX $NY
+  keyword ref CTYPE1 -w "RA---TAN"
+  keyword ref CTYPE2 -w "DEC--TAN"
+  keyword ref CRVAL1 -wf 0.0
+  keyword ref CRVAL2 -wf 0.0
+  keyword ref CRPIX1 -wf {$NX/2}
+  keyword ref CRPIX2 -wf {$NY/2}
+
+  keyword ref CDELT1 -wf {1/3600}
+  keyword ref CDELT2 -wf {1/3600}
+
+  keyword ref PC001001 -wf 1.0
+  keyword ref PC001002 -wf 0.0
+  keyword ref PC002001 -wf 0.0
+  keyword ref PC002002 -wf 1.0
+
+  wd ref ref.fits -bitpix -32 -bzero 0 -bscale 1
+end
+
+macro mksrc
+  mcreate src $NX $NY
+  for i 0 $NX 64
+    for j 0 $NY 64
+      zap src $i $j 1 1 -v 1
+    end
+  end
+
+  keyword src CTYPE1 -w "RA---TAN"
+  keyword src CTYPE2 -w "DEC--TAN"
+  keyword src CRVAL1 -wf 0.0
+  keyword src CRVAL2 -wf 0.0
+  keyword src CRPIX1 -wf {$NX/2}
+  keyword src CRPIX2 -wf {$NY/2}
+
+  keyword src CDELT1 -wf {1/3600}
+  keyword src CDELT2 -wf {1/3600}
+
+  keyword src PC001001 -wf {dcos(20)}
+  keyword src PC001002 -wf {-1*dsin(20)}
+  keyword src PC002001 -wf {dsin(20)}
+  keyword src PC002002 -wf {dcos(20)}
+
+  wd src src.fits -bitpix -32 -bzero 0 -bscale 1
+end
